From e4cc7bbf303177aa165c181a17efcdf422829959 Mon Sep 17 00:00:00 2001 From: Barry Harris <44396066+barry65536@users.noreply.github.com> Date: Sat, 3 Dec 2011 20:27:59 +0000 Subject: [PATCH] Initial commit --- fba.chm | Bin 0 -> 39874 bytes makefile | 71 + makefile.mingw | 695 + makefile.rules | 148 + makefile.vc | 544 + preset-example.zip | Bin 0 -> 593 bytes src/burn/bitswap.h | 100 + src/burn/burn.cpp | 1091 + src/burn/burn.h | 507 + src/burn/burn_gun.cpp | 159 + src/burn/burn_gun.h | 15 + src/burn/burn_led.cpp | 235 + src/burn/burn_led.h | 30 + src/burn/burn_memory.cpp | 74 + src/burn/burn_sound.cpp | 23 + src/burn/burn_sound.h | 48 + src/burn/burn_sound_a.asm | 751 + src/burn/burn_sound_c.cpp | 46 + src/burn/burnint.h | 121 + src/burn/cheat.cpp | 664 + src/burn/cheat.h | 49 + src/burn/devices/8255ppi.cpp | 450 + src/burn/devices/8255ppi.h | 27 + src/burn/devices/eeprom.cpp | 328 + src/burn/devices/eeprom.h | 56 + src/burn/devices/pandora.cpp | 122 + src/burn/devices/pandora.h | 7 + src/burn/devices/seibusnd.cpp | 525 + src/burn/devices/seibusnd.h | 32 + src/burn/devices/timekpr.cpp | 331 + src/burn/devices/timekpr.h | 10 + src/burn/driver.h | 79 + src/burn/drivers/capcom/cps.cpp | 1094 + src/burn/drivers/capcom/cps.h | 385 + src/burn/drivers/capcom/cps2_crpt.cpp | 1088 + src/burn/drivers/capcom/cps_config.cpp | 1605 + src/burn/drivers/capcom/cps_draw.cpp | 490 + src/burn/drivers/capcom/cps_mem.cpp | 427 + src/burn/drivers/capcom/cps_obj.cpp | 401 + src/burn/drivers/capcom/cps_pal.cpp | 297 + src/burn/drivers/capcom/cps_run.cpp | 497 + src/burn/drivers/capcom/cps_rw.cpp | 589 + src/burn/drivers/capcom/cps_scr.cpp | 265 + src/burn/drivers/capcom/cpsr.cpp | 199 + src/burn/drivers/capcom/cpsrd.cpp | 235 + src/burn/drivers/capcom/cpst.cpp | 192 + src/burn/drivers/capcom/ctv.cpp | 41 + src/burn/drivers/capcom/ctv_do.h | 192 + src/burn/drivers/capcom/ctv_make.cpp | 125 + src/burn/drivers/capcom/d_cps1.cpp | 14083 ++++++ src/burn/drivers/capcom/d_cps2.cpp | 10924 +++++ src/burn/drivers/capcom/kabuki.cpp | 167 + src/burn/drivers/capcom/ps.cpp | 86 + src/burn/drivers/capcom/ps_m.cpp | 94 + src/burn/drivers/capcom/ps_z.cpp | 208 + src/burn/drivers/capcom/qs.cpp | 128 + src/burn/drivers/capcom/qs_c.cpp | 454 + src/burn/drivers/capcom/qs_z.cpp | 138 + src/burn/drivers/cave/cave.cpp | 47 + src/burn/drivers/cave/cave.h | 63 + src/burn/drivers/cave/cave_palette.cpp | 154 + src/burn/drivers/cave/cave_sprite.cpp | 742 + src/burn/drivers/cave/cave_sprite_render.h | 281 + .../drivers/cave/cave_sprite_render_zoom.h | 182 + src/burn/drivers/cave/cave_tile.cpp | 981 + src/burn/drivers/cave/cave_tile_render.h | 370 + src/burn/drivers/cave/d_dodonpachi.cpp | 676 + src/burn/drivers/cave/d_donpachi.cpp | 783 + src/burn/drivers/cave/d_esprade.cpp | 723 + src/burn/drivers/cave/d_feversos.cpp | 645 + src/burn/drivers/cave/d_gaia.cpp | 887 + src/burn/drivers/cave/d_guwange.cpp | 714 + src/burn/drivers/cave/d_hotdogst.cpp | 757 + src/burn/drivers/cave/d_korokoro.cpp | 734 + src/burn/drivers/cave/d_mazinger.cpp | 846 + src/burn/drivers/cave/d_metmqstr.cpp | 852 + src/burn/drivers/cave/d_pwrinst2.cpp | 1212 + src/burn/drivers/cave/d_sailormn.cpp | 1696 + src/burn/drivers/cave/d_tjumpman.cpp | 583 + src/burn/drivers/cave/d_uopoko.cpp | 610 + src/burn/drivers/cps3/cps3.h | 46 + src/burn/drivers/cps3/cps3run.cpp | 2196 + src/burn/drivers/cps3/cps3snd.cpp | 215 + src/burn/drivers/cps3/d_cps3.cpp | 1204 + src/burn/drivers/d_parent.cpp | 343 + src/burn/drivers/galaxian/d_galaxian.cpp | 20973 ++++++++ src/burn/drivers/galaxian/gal.h | 316 + src/burn/drivers/galaxian/gal_gfx.cpp | 1255 + src/burn/drivers/galaxian/gal_run.cpp | 1960 + src/burn/drivers/galaxian/gal_sound.cpp | 943 + src/burn/drivers/galaxian/gal_stars.cpp | 241 + src/burn/drivers/irem/d_m62.cpp | 5022 ++ src/burn/drivers/irem/d_m63.cpp | 1152 + src/burn/drivers/irem/d_m72.cpp | 3928 ++ src/burn/drivers/irem/d_m90.cpp | 1828 + src/burn/drivers/irem/d_m92.cpp | 3763 ++ src/burn/drivers/irem/irem_cpu.cpp | 657 + src/burn/drivers/irem/irem_cpu.h | 18 + src/burn/drivers/konami/d_88games.cpp | 846 + src/burn/drivers/konami/d_ajax.cpp | 940 + src/burn/drivers/konami/d_aliens.cpp | 854 + src/burn/drivers/konami/d_blockhl.cpp | 589 + src/burn/drivers/konami/d_bottom9.cpp | 929 + src/burn/drivers/konami/d_contra.cpp | 1232 + src/burn/drivers/konami/d_crimfght.cpp | 798 + src/burn/drivers/konami/d_gbusters.cpp | 698 + src/burn/drivers/konami/d_gradius3.cpp | 973 + src/burn/drivers/konami/d_hcastle.cpp | 975 + src/burn/drivers/konami/d_hexion.cpp | 620 + src/burn/drivers/konami/d_mainevt.cpp | 1251 + src/burn/drivers/konami/d_parodius.cpp | 768 + src/burn/drivers/konami/d_rollerg.cpp | 642 + src/burn/drivers/konami/d_simpsons.cpp | 1000 + src/burn/drivers/konami/d_spy.cpp | 811 + src/burn/drivers/konami/d_surpratk.cpp | 641 + src/burn/drivers/konami/d_thunderx.cpp | 1174 + src/burn/drivers/konami/d_tmnt.cpp | 6557 +++ src/burn/drivers/konami/d_twin16.cpp | 2272 + src/burn/drivers/konami/d_ultraman.cpp | 695 + src/burn/drivers/konami/d_vendetta.cpp | 1236 + src/burn/drivers/konami/d_xmen.cpp | 1008 + src/burn/drivers/konami/k051316.cpp | 284 + src/burn/drivers/konami/k051733.cpp | 111 + src/burn/drivers/konami/k051960.cpp | 291 + src/burn/drivers/konami/k052109.cpp | 554 + src/burn/drivers/konami/k053245.cpp | 453 + src/burn/drivers/konami/k053247.cpp | 566 + src/burn/drivers/konami/k053251.cpp | 60 + src/burn/drivers/konami/k053936.cpp | 275 + src/burn/drivers/konami/k054000.cpp | 55 + src/burn/drivers/konami/konamiic.cpp | 179 + src/burn/drivers/konami/konamiic.h | 238 + src/burn/drivers/megadrive/d_megadrive.cpp | 40515 ++++++++++++++++ src/burn/drivers/megadrive/megadrive.cpp | 4225 ++ src/burn/drivers/megadrive/megadrive.h | 25 + src/burn/drivers/misc_post90s/d_1945kiii.cpp | 483 + src/burn/drivers/misc_post90s/d_aerofgt.cpp | 4416 ++ src/burn/drivers/misc_post90s/d_airbustr.cpp | 920 + src/burn/drivers/misc_post90s/d_aquarium.cpp | 764 + src/burn/drivers/misc_post90s/d_ashnojoe.cpp | 714 + src/burn/drivers/misc_post90s/d_backfire.cpp | 757 + src/burn/drivers/misc_post90s/d_bloodbro.cpp | 1108 + src/burn/drivers/misc_post90s/d_boogwing.cpp | 986 + src/burn/drivers/misc_post90s/d_cbuster.cpp | 880 + src/burn/drivers/misc_post90s/d_cninja.cpp | 3255 ++ src/burn/drivers/misc_post90s/d_crospang.cpp | 787 + src/burn/drivers/misc_post90s/d_crshrace.cpp | 887 + src/burn/drivers/misc_post90s/d_darkseal.cpp | 872 + src/burn/drivers/misc_post90s/d_dassault.cpp | 1170 + src/burn/drivers/misc_post90s/d_dcon.cpp | 798 + src/burn/drivers/misc_post90s/d_ddragon3.cpp | 2104 + src/burn/drivers/misc_post90s/d_deniam.cpp | 995 + src/burn/drivers/misc_post90s/d_dietgogo.cpp | 618 + src/burn/drivers/misc_post90s/d_diverboy.cpp | 496 + src/burn/drivers/misc_post90s/d_drtomy.cpp | 508 + src/burn/drivers/misc_post90s/d_egghunt.cpp | 558 + src/burn/drivers/misc_post90s/d_esd16.cpp | 1716 + src/burn/drivers/misc_post90s/d_f1gp.cpp | 1387 + src/burn/drivers/misc_post90s/d_fstarfrc.cpp | 1286 + src/burn/drivers/misc_post90s/d_funkyjet.cpp | 727 + src/burn/drivers/misc_post90s/d_funybubl.cpp | 623 + src/burn/drivers/misc_post90s/d_fuukifg3.cpp | 1302 + src/burn/drivers/misc_post90s/d_gaelco.cpp | 1480 + src/burn/drivers/misc_post90s/d_gaiden.cpp | 2008 + src/burn/drivers/misc_post90s/d_galpanic.cpp | 2022 + src/burn/drivers/misc_post90s/d_gotcha.cpp | 663 + src/burn/drivers/misc_post90s/d_gumbo.cpp | 773 + src/burn/drivers/misc_post90s/d_hyperpac.cpp | 4103 ++ src/burn/drivers/misc_post90s/d_kaneko16.cpp | 5029 ++ src/burn/drivers/misc_post90s/d_lordgun.cpp | 1513 + src/burn/drivers/misc_post90s/d_mcatadv.cpp | 1181 + src/burn/drivers/misc_post90s/d_midas.cpp | 668 + src/burn/drivers/misc_post90s/d_mogura.cpp | 410 + src/burn/drivers/misc_post90s/d_mugsmash.cpp | 686 + src/burn/drivers/misc_post90s/d_news.cpp | 450 + src/burn/drivers/misc_post90s/d_nmg5.cpp | 1761 + src/burn/drivers/misc_post90s/d_nmk16.cpp | 8834 ++++ src/burn/drivers/misc_post90s/d_ohmygod.cpp | 691 + src/burn/drivers/misc_post90s/d_pass.cpp | 512 + src/burn/drivers/misc_post90s/d_pirates.cpp | 691 + src/burn/drivers/misc_post90s/d_pktgaldx.cpp | 630 + src/burn/drivers/misc_post90s/d_powerins.cpp | 1196 + src/burn/drivers/misc_post90s/d_pushman.cpp | 975 + src/burn/drivers/misc_post90s/d_raiden.cpp | 1679 + src/burn/drivers/misc_post90s/d_rohga.cpp | 2286 + src/burn/drivers/misc_post90s/d_seta.cpp | 10165 ++++ src/burn/drivers/misc_post90s/d_seta2.cpp | 3412 ++ src/burn/drivers/misc_post90s/d_shadfrce.cpp | 1601 + src/burn/drivers/misc_post90s/d_silkroad.cpp | 643 + src/burn/drivers/misc_post90s/d_simpl156.cpp | 1090 + src/burn/drivers/misc_post90s/d_speedspn.cpp | 637 + src/burn/drivers/misc_post90s/d_suna16.cpp | 2359 + src/burn/drivers/misc_post90s/d_supbtime.cpp | 693 + src/burn/drivers/misc_post90s/d_suprnova.cpp | 774 + src/burn/drivers/misc_post90s/d_taotaido.cpp | 1026 + src/burn/drivers/misc_post90s/d_tecmosys.cpp | 1481 + src/burn/drivers/misc_post90s/d_tumbleb.cpp | 4641 ++ src/burn/drivers/misc_post90s/d_tumblep.cpp | 563 + src/burn/drivers/misc_post90s/d_unico.cpp | 1906 + src/burn/drivers/misc_post90s/d_vmetal.cpp | 706 + src/burn/drivers/misc_post90s/d_welltris.cpp | 962 + src/burn/drivers/misc_post90s/d_wwfwfest.cpp | 1203 + src/burn/drivers/misc_post90s/d_xorworld.cpp | 434 + src/burn/drivers/misc_post90s/d_yunsun16.cpp | 1112 + src/burn/drivers/misc_post90s/d_zerozone.cpp | 552 + src/burn/drivers/misc_post90s/deco16ic.cpp | 3201 ++ src/burn/drivers/misc_post90s/deco16ic.h | 116 + src/burn/drivers/misc_post90s/kanekotb.h | 3673 ++ src/burn/drivers/misc_post90s/nmk004.cpp | 1008 + src/burn/drivers/misc_post90s/nmk004.h | 10 + src/burn/drivers/misc_pre90s/d_1942.cpp | 1091 + src/burn/drivers/misc_pre90s/d_1943.cpp | 1477 + src/burn/drivers/misc_pre90s/d_4enraya.cpp | 530 + src/burn/drivers/misc_pre90s/d_ambush.cpp | 632 + src/burn/drivers/misc_pre90s/d_angelkds.cpp | 1029 + src/burn/drivers/misc_pre90s/d_arabian.cpp | 706 + src/burn/drivers/misc_pre90s/d_arkanoid.cpp | 1890 + src/burn/drivers/misc_pre90s/d_armedf.cpp | 1904 + src/burn/drivers/misc_pre90s/d_aztarac.cpp | 656 + src/burn/drivers/misc_pre90s/d_bankp.cpp | 609 + src/burn/drivers/misc_pre90s/d_baraduke.cpp | 967 + src/burn/drivers/misc_pre90s/d_bionicc.cpp | 945 + src/burn/drivers/misc_pre90s/d_blktiger.cpp | 1062 + src/burn/drivers/misc_pre90s/d_blockout.cpp | 745 + src/burn/drivers/misc_pre90s/d_blueprnt.cpp | 750 + src/burn/drivers/misc_pre90s/d_bombjack.cpp | 960 + src/burn/drivers/misc_pre90s/d_chaknpop.cpp | 779 + src/burn/drivers/misc_pre90s/d_commando.cpp | 1098 + src/burn/drivers/misc_pre90s/d_ddragon.cpp | 2597 + src/burn/drivers/misc_pre90s/d_dec0.cpp | 2462 + src/burn/drivers/misc_pre90s/d_dec8.cpp | 5385 ++ src/burn/drivers/misc_pre90s/d_dotrikun.cpp | 249 + src/burn/drivers/misc_pre90s/d_dynduke.cpp | 974 + src/burn/drivers/misc_pre90s/d_epos.cpp | 919 + src/burn/drivers/misc_pre90s/d_exedexes.cpp | 835 + src/burn/drivers/misc_pre90s/d_flstory.cpp | 1437 + src/burn/drivers/misc_pre90s/d_funkybee.cpp | 752 + src/burn/drivers/misc_pre90s/d_galaga.cpp | 1649 + src/burn/drivers/misc_pre90s/d_gauntlet.cpp | 2795 ++ src/burn/drivers/misc_pre90s/d_gberet.cpp | 1109 + src/burn/drivers/misc_pre90s/d_ginganin.cpp | 766 + src/burn/drivers/misc_pre90s/d_gng.cpp | 1481 + src/burn/drivers/misc_pre90s/d_gunsmoke.cpp | 1011 + src/burn/drivers/misc_pre90s/d_gyruss.cpp | 1081 + src/burn/drivers/misc_pre90s/d_higemaru.cpp | 537 + src/burn/drivers/misc_pre90s/d_ikki.cpp | 666 + src/burn/drivers/misc_pre90s/d_jack.cpp | 1926 + src/burn/drivers/misc_pre90s/d_kangaroo.cpp | 752 + src/burn/drivers/misc_pre90s/d_karnov.cpp | 1547 + src/burn/drivers/misc_pre90s/d_kyugo.cpp | 2610 + src/burn/drivers/misc_pre90s/d_ladybug.cpp | 1528 + src/burn/drivers/misc_pre90s/d_lkage.cpp | 1072 + src/burn/drivers/misc_pre90s/d_lwings.cpp | 2165 + src/burn/drivers/misc_pre90s/d_madgear.cpp | 1934 + src/burn/drivers/misc_pre90s/d_marineb.cpp | 850 + src/burn/drivers/misc_pre90s/d_markham.cpp | 531 + src/burn/drivers/misc_pre90s/d_meijinsn.cpp | 559 + src/burn/drivers/misc_pre90s/d_minivdr.cpp | 197 + src/burn/drivers/misc_pre90s/d_mitchell.cpp | 3250 ++ src/burn/drivers/misc_pre90s/d_mole.cpp | 499 + src/burn/drivers/misc_pre90s/d_mrdo.cpp | 761 + src/burn/drivers/misc_pre90s/d_mrflea.cpp | 643 + src/burn/drivers/misc_pre90s/d_mystston.cpp | 670 + src/burn/drivers/misc_pre90s/d_pac2650.cpp | 612 + src/burn/drivers/misc_pre90s/d_pacman.cpp | 6349 +++ src/burn/drivers/misc_pre90s/d_pkunwar.cpp | 624 + src/burn/drivers/misc_pre90s/d_pooyan.cpp | 772 + src/burn/drivers/misc_pre90s/d_prehisle.cpp | 886 + src/burn/drivers/misc_pre90s/d_quizo.cpp | 381 + src/burn/drivers/misc_pre90s/d_rallyx.cpp | 1534 + src/burn/drivers/misc_pre90s/d_renegade.cpp | 1417 + src/burn/drivers/misc_pre90s/d_retofinv.cpp | 987 + src/burn/drivers/misc_pre90s/d_route16.cpp | 1087 + src/burn/drivers/misc_pre90s/d_scotrsht.cpp | 650 + src/burn/drivers/misc_pre90s/d_scregg.cpp | 724 + src/burn/drivers/misc_pre90s/d_sf.cpp | 1720 + src/burn/drivers/misc_pre90s/d_skyfox.cpp | 624 + src/burn/drivers/misc_pre90s/d_skykid.cpp | 1087 + src/burn/drivers/misc_pre90s/d_snk68.cpp | 1878 + src/burn/drivers/misc_pre90s/d_solomon.cpp | 817 + src/burn/drivers/misc_pre90s/d_sonson.cpp | 768 + src/burn/drivers/misc_pre90s/d_srumbler.cpp | 829 + src/burn/drivers/misc_pre90s/d_tecmo.cpp | 1558 + src/burn/drivers/misc_pre90s/d_tigerheli.cpp | 2942 ++ src/burn/drivers/misc_pre90s/d_tigeroad.cpp | 1424 + src/burn/drivers/misc_pre90s/d_tnzs.cpp | 2728 ++ src/burn/drivers/misc_pre90s/d_toki.cpp | 1974 + src/burn/drivers/misc_pre90s/d_vaportra.cpp | 820 + src/burn/drivers/misc_pre90s/d_vigilant.cpp | 2190 + src/burn/drivers/misc_pre90s/d_vulgus.cpp | 826 + src/burn/drivers/misc_pre90s/d_wallc.cpp | 484 + src/burn/drivers/misc_pre90s/d_wc90.cpp | 1306 + src/burn/drivers/misc_pre90s/d_wc90b.cpp | 977 + src/burn/drivers/misc_pre90s/d_wwfsstar.cpp | 1009 + src/burn/drivers/misc_pre90s/tnzs_prot.cpp | 465 + src/burn/drivers/misc_pre90s/tnzs_prot.h | 100 + src/burn/drivers/neogeo/d_neogeo.cpp | 13918 ++++++ src/burn/drivers/neogeo/neo_decrypt.cpp | 675 + src/burn/drivers/neogeo/neo_palette.cpp | 117 + src/burn/drivers/neogeo/neo_run.cpp | 4876 ++ src/burn/drivers/neogeo/neo_sprite.cpp | 181 + src/burn/drivers/neogeo/neo_sprite_render.h | 656 + src/burn/drivers/neogeo/neo_text.cpp | 334 + src/burn/drivers/neogeo/neo_text_render.h | 79 + src/burn/drivers/neogeo/neo_upd4990a.cpp | 285 + src/burn/drivers/neogeo/neogeo.cpp | 433 + src/burn/drivers/neogeo/neogeo.h | 160 + src/burn/drivers/pgm/changes.txt | 221 + src/burn/drivers/pgm/d_pgm.cpp | 3506 ++ src/burn/drivers/pgm/pgm.h | 113 + src/burn/drivers/pgm/pgm_crypt.cpp | 975 + src/burn/drivers/pgm/pgm_draw.cpp | 854 + src/burn/drivers/pgm/pgm_prot.cpp | 2546 + src/burn/drivers/pgm/pgm_run.cpp | 1050 + src/burn/drivers/psikyo/d_psikyo.cpp | 2588 + src/burn/drivers/psikyo/d_psikyosh.cpp | 1570 + src/burn/drivers/psikyo/psikyo.h | 44 + src/burn/drivers/psikyo/psikyo_palette.cpp | 89 + src/burn/drivers/psikyo/psikyo_render.h | 284 + src/burn/drivers/psikyo/psikyo_sprite.cpp | 533 + src/burn/drivers/psikyo/psikyo_sprite_func.h | 761 + src/burn/drivers/psikyo/psikyo_tile.cpp | 287 + src/burn/drivers/psikyo/psikyosh_render.cpp | 743 + src/burn/drivers/psikyo/psikyosh_render.h | 270 + src/burn/drivers/sega/d_hangon.cpp | 1432 + src/burn/drivers/sega/d_outrun.cpp | 1686 + src/burn/drivers/sega/d_sys1.cpp | 5417 +++ src/burn/drivers/sega/d_sys16a.cpp | 3156 ++ src/burn/drivers/sega/d_sys16b.cpp | 9156 ++++ src/burn/drivers/sega/d_sys18.cpp | 2758 ++ src/burn/drivers/sega/d_xbrd.cpp | 2530 + src/burn/drivers/sega/d_ybrd.cpp | 2023 + src/burn/drivers/sega/fd1089.cpp | 280 + src/burn/drivers/sega/fd1094.cpp | 531 + src/burn/drivers/sega/fd1094.h | 6 + src/burn/drivers/sega/genesis_vid.cpp | 907 + src/burn/drivers/sega/genesis_vid.h | 12 + src/burn/drivers/sega/mc8123.cpp | 333 + src/burn/drivers/sega/mc8123.h | 1 + src/burn/drivers/sega/sys16.h | 284 + src/burn/drivers/sega/sys16_fd1094.cpp | 191 + src/burn/drivers/sega/sys16_gfx.cpp | 3338 ++ src/burn/drivers/sega/sys16_run.cpp | 3304 ++ src/burn/drivers/taito/cchip.cpp | 2612 + src/burn/drivers/taito/d_asuka.cpp | 2135 + src/burn/drivers/taito/d_bublbobl.cpp | 2648 + src/burn/drivers/taito/d_darius2.cpp | 2048 + src/burn/drivers/taito/d_othunder.cpp | 1160 + src/burn/drivers/taito/d_slapshot.cpp | 930 + src/burn/drivers/taito/d_superchs.cpp | 1151 + src/burn/drivers/taito/d_taitob.cpp | 4141 ++ src/burn/drivers/taito/d_taitof2.cpp | 11259 +++++ src/burn/drivers/taito/d_taitomisc.cpp | 5873 +++ src/burn/drivers/taito/d_taitox.cpp | 1656 + src/burn/drivers/taito/d_taitoz.cpp | 6045 +++ src/burn/drivers/taito/pc080sn.cpp | 851 + src/burn/drivers/taito/pc090oj.cpp | 143 + src/burn/drivers/taito/taito.cpp | 996 + src/burn/drivers/taito/taito.h | 241 + src/burn/drivers/taito/taito_ic.cpp | 126 + src/burn/drivers/taito/taito_ic.h | 559 + src/burn/drivers/taito/taito_m68705.cpp | 224 + src/burn/drivers/taito/taito_m68705.h | 40 + src/burn/drivers/taito/tc0100scn.cpp | 627 + src/burn/drivers/taito/tc0110pcr.cpp | 194 + src/burn/drivers/taito/tc0140syt.cpp | 238 + src/burn/drivers/taito/tc0150rod.cpp | 461 + src/burn/drivers/taito/tc0180vcu.cpp | 713 + src/burn/drivers/taito/tc0220ioc.cpp | 133 + src/burn/drivers/taito/tc0280grd.cpp | 222 + src/burn/drivers/taito/tc0360pri.cpp | 43 + src/burn/drivers/taito/tc0480scp.cpp | 885 + src/burn/drivers/taito/tc0510nio.cpp | 91 + src/burn/drivers/taito/tc0640fio.cpp | 117 + src/burn/drivers/toaplan/d_batrider.cpp | 1167 + src/burn/drivers/toaplan/d_batsugun.cpp | 718 + src/burn/drivers/toaplan/d_battleg.cpp | 975 + src/burn/drivers/toaplan/d_bbakraid.cpp | 1111 + src/burn/drivers/toaplan/d_demonwld.cpp | 870 + src/burn/drivers/toaplan/d_dogyuun.cpp | 785 + src/burn/drivers/toaplan/d_fixeight.cpp | 1031 + src/burn/drivers/toaplan/d_ghox.cpp | 607 + src/burn/drivers/toaplan/d_hellfire.cpp | 828 + src/burn/drivers/toaplan/d_kbash.cpp | 614 + src/burn/drivers/toaplan/d_kbash2.cpp | 549 + src/burn/drivers/toaplan/d_mahoudai.cpp | 696 + src/burn/drivers/toaplan/d_outzone.cpp | 1017 + src/burn/drivers/toaplan/d_pipibibs.cpp | 580 + src/burn/drivers/toaplan/d_rallybik.cpp | 620 + src/burn/drivers/toaplan/d_samesame.cpp | 820 + src/burn/drivers/toaplan/d_shippumd.cpp | 704 + src/burn/drivers/toaplan/d_snowbro2.cpp | 622 + src/burn/drivers/toaplan/d_tekipaki.cpp | 623 + src/burn/drivers/toaplan/d_truxton.cpp | 683 + src/burn/drivers/toaplan/d_truxton2.cpp | 627 + src/burn/drivers/toaplan/d_vfive.cpp | 679 + src/burn/drivers/toaplan/d_vimana.cpp | 693 + src/burn/drivers/toaplan/d_zerowing.cpp | 756 + src/burn/drivers/toaplan/toa_bcu2.cpp | 460 + src/burn/drivers/toaplan/toa_extratext.cpp | 340 + src/burn/drivers/toaplan/toa_extratext.h | 115 + src/burn/drivers/toaplan/toa_gp9001.cpp | 627 + src/burn/drivers/toaplan/toa_gp9001_render.h | 185 + src/burn/drivers/toaplan/toa_palette.cpp | 60 + src/burn/drivers/toaplan/toaplan.cpp | 148 + src/burn/drivers/toaplan/toaplan.h | 292 + src/burn/drivers/toaplan/toaplan1.cpp | 105 + src/burn/hiscore.cpp | 572 + src/burn/hiscore.h | 6 + src/burn/load.cpp | 105 + src/burn/sound/ay8910.c | 744 + src/burn/sound/ay8910.h | 45 + src/burn/sound/burn_y8950.cpp | 543 + src/burn/sound/burn_y8950.h | 28 + src/burn/sound/burn_ym2151.cpp | 173 + src/burn/sound/burn_ym2151.h | 31 + src/burn/sound/burn_ym2203.cpp | 411 + src/burn/sound/burn_ym2203.h | 22 + src/burn/sound/burn_ym2413.cpp | 179 + src/burn/sound/burn_ym2413.h | 18 + src/burn/sound/burn_ym2608.cpp | 368 + src/burn/sound/burn_ym2608.h | 19 + src/burn/sound/burn_ym2610.cpp | 400 + src/burn/sound/burn_ym2610.h | 21 + src/burn/sound/burn_ym2612.cpp | 228 + src/burn/sound/burn_ym2612.h | 26 + src/burn/sound/burn_ym3526.cpp | 542 + src/burn/sound/burn_ym3526.h | 27 + src/burn/sound/burn_ym3812.cpp | 542 + src/burn/sound/burn_ym3812.h | 28 + src/burn/sound/burn_ymf278b.cpp | 182 + src/burn/sound/burn_ymf278b.h | 19 + src/burn/sound/dac.cpp | 350 + src/burn/sound/dac.h | 8 + src/burn/sound/es5506.cpp | 2267 + src/burn/sound/es5506.h | 66 + src/burn/sound/es8712.cpp | 416 + src/burn/sound/es8712.h | 11 + src/burn/sound/fm.c | 5121 ++ src/burn/sound/fm.h | 241 + src/burn/sound/fmopl.c | 2522 + src/burn/sound/fmopl.h | 109 + src/burn/sound/ics2115.cpp | 449 + src/burn/sound/ics2115.h | 16 + src/burn/sound/iremga20.cpp | 260 + src/burn/sound/iremga20.h | 9 + src/burn/sound/k007232.cpp | 280 + src/burn/sound/k007232.h | 9 + src/burn/sound/k051649.cpp | 269 + src/burn/sound/k051649.h | 15 + src/burn/sound/k053260.cpp | 434 + src/burn/sound/k053260.h | 8 + src/burn/sound/k054539.cpp | 592 + src/burn/sound/k054539.h | 18 + src/burn/sound/msm5205.cpp | 363 + src/burn/sound/msm5205.h | 40 + src/burn/sound/msm6295.cpp | 470 + src/burn/sound/msm6295.h | 23 + src/burn/sound/namco_snd.cpp | 536 + src/burn/sound/namco_snd.h | 10 + src/burn/sound/rf5c68.cpp | 189 + src/burn/sound/rf5c68.h | 6 + src/burn/sound/saa1099.cpp | 447 + src/burn/sound/saa1099.h | 7 + src/burn/sound/samples.cpp | 374 + src/burn/sound/samples.h | 24 + src/burn/sound/segapcm.cpp | 151 + src/burn/sound/segapcm.h | 13 + src/burn/sound/sn76496.cpp | 469 + src/burn/sound/sn76496.h | 8 + src/burn/sound/upd7759.cpp | 497 + src/burn/sound/upd7759.h | 14 + src/burn/sound/x1010.cpp | 162 + src/burn/sound/x1010.h | 42 + src/burn/sound/ym2151.c | 2474 + src/burn/sound/ym2151.h | 81 + src/burn/sound/ym2413.c | 2160 + src/burn/sound/ym2413.h | 29 + src/burn/sound/ymdeltat.c | 653 + src/burn/sound/ymdeltat.h | 82 + src/burn/sound/ymf278b.c | 838 + src/burn/sound/ymf278b.h | 49 + src/burn/sound/ymz280b.cpp | 715 + src/burn/sound/ymz280b.h | 44 + src/burn/state.h | 70 + src/burn/stdfunc.h | 148 + src/burn/tiles_generic.cpp | 1990 + src/burn/tiles_generic.h | 86 + src/burn/timer.cpp | 430 + src/burn/timer.h | 36 + src/burn/vector.cpp | 167 + src/burn/vector.h | 7 + src/burn/version.h | 13 + src/burner/burner.h | 158 + src/burner/conc.cpp | 582 + src/burner/cong.cpp | 118 + src/burner/dat.cpp | 502 + src/burner/gamc.cpp | 776 + src/burner/gameinp.h | 99 + src/burner/gami.cpp | 1720 + src/burner/image.cpp | 524 + src/burner/misc.cpp | 431 + src/burner/sshot.cpp | 237 + src/burner/state.cpp | 317 + src/burner/statec.cpp | 171 + src/burner/title.h | 9 + src/burner/unzip.c | 1274 + src/burner/unzip.h | 275 + src/burner/win32/about.cpp | 294 + src/burner/win32/app.rc | 1299 + src/burner/win32/burner_win32.h | 442 + src/burner/win32/bzip.cpp | 595 + src/burner/win32/cona.cpp | 572 + src/burner/win32/debugger.cpp | 1571 + src/burner/win32/drv.cpp | 271 + src/burner/win32/dwmapi_core.cpp | 144 + src/burner/win32/dwmapi_core.h | 94 + src/burner/win32/dynhuff.cpp | 1008 + src/burner/win32/dynhuff.h | 137 + src/burner/win32/fba_kaillera.cpp | 213 + src/burner/win32/image_win32.cpp | 56 + src/burner/win32/inpc.cpp | 126 + src/burner/win32/inpcheat.cpp | 277 + src/burner/win32/inpd.cpp | 905 + src/burner/win32/inpdipsw.cpp | 360 + src/burner/win32/inps.cpp | 336 + src/burner/win32/ips_manager.cpp | 817 + src/burner/win32/localise.cpp | 1698 + src/burner/win32/main.cpp | 829 + src/burner/win32/mdi.cpp | 408 + src/burner/win32/media.cpp | 77 + src/burner/win32/memcard.cpp | 309 + src/burner/win32/menu.cpp | 1341 + src/burner/win32/misc_win32.cpp | 254 + src/burner/win32/neocdlist.cpp | 518 + src/burner/win32/neocdlist.h | 143 + src/burner/win32/neocdsel.cpp | 1323 + src/burner/win32/numdial.cpp | 1013 + src/burner/win32/numpluscommas.cpp | 251 + src/burner/win32/paletteviewer.cpp | 161 + src/burner/win32/popup_win32.cpp | 364 + src/burner/win32/progress.cpp | 202 + src/burner/win32/replay.cpp | 375 + src/burner/win32/res.cpp | 98 + src/burner/win32/resource.h | 628 + src/burner/win32/resource.rc | 44 + src/burner/win32/resource/TV Minus.ico | Bin 0 -> 1150 bytes .../resource/TV Not Found Non Essential.ico | Bin 0 -> 4286 bytes src/burner/win32/resource/TV Not Found.ico | Bin 0 -> 4286 bytes src/burner/win32/resource/TV Not Working.ico | Bin 0 -> 4286 bytes src/burner/win32/resource/TV Plus.ico | Bin 0 -> 1150 bytes src/burner/win32/resource/about.bmp | Bin 0 -> 196664 bytes src/burner/win32/resource/fba.ico | Bin 0 -> 132942 bytes src/burner/win32/resource/manifest.xml | 15 + src/burner/win32/resource/misc.bmp | Bin 0 -> 14456 bytes src/burner/win32/resource/splash.bmp | Bin 0 -> 204344 bytes src/burner/win32/resource_string.h | 232 + src/burner/win32/roms.cpp | 444 + src/burner/win32/run.cpp | 547 + src/burner/win32/scrn.cpp | 2964 ++ src/burner/win32/sel.cpp | 2256 + src/burner/win32/sfactd.cpp | 201 + src/burner/win32/splash.cpp | 99 + src/burner/win32/stated.cpp | 146 + src/burner/win32/string.rc | 233 + src/burner/win32/support_paths.cpp | 184 + src/burner/win32/systeminfo.cpp | 1386 + src/burner/win32/version.rc | 95 + src/burner/win32/wave.cpp | 116 + src/burner/zipfn.cpp | 207 + src/cpu/a68k/fba_make68k.c | 8244 ++++ src/cpu/arm/arm.cpp | 1354 + src/cpu/arm7/arm7.cpp | 177 + src/cpu/arm7/arm7core.c | 1726 + src/cpu/arm7/arm7core.h | 400 + src/cpu/arm7/arm7exec.c | 1366 + src/cpu/arm7_intf.cpp | 275 + src/cpu/arm7_intf.h | 60 + src/cpu/arm_intf.cpp | 248 + src/cpu/arm_intf.h | 90 + src/cpu/h6280/h6280.cpp | 602 + src/cpu/h6280/h6280.h | 53 + src/cpu/h6280/h6280ops.h | 1379 + src/cpu/h6280/tblh6280.c | 344 + src/cpu/h6280_intf.cpp | 197 + src/cpu/h6280_intf.h | 58 + src/cpu/hd6309/6309ops.c | 5599 +++ src/cpu/hd6309/6309tbl.c | 814 + src/cpu/hd6309/hd6309.cpp | 1333 + src/cpu/hd6309/hd6309.h | 89 + src/cpu/hd6309_intf.cpp | 320 + src/cpu/hd6309_intf.h | 63 + src/cpu/i8039/i8039.cpp | 1256 + src/cpu/i8039/i8039.h | 295 + src/cpu/konami/konami.cpp | 560 + src/cpu/konami/konami.h | 48 + src/cpu/konami/konamops.c | 4361 ++ src/cpu/konami/konamtbl.c | 491 + src/cpu/konami_intf.cpp | 162 + src/cpu/konami_intf.h | 50 + src/cpu/m6502/ill02.h | 335 + src/cpu/m6502/m6502.cpp | 998 + src/cpu/m6502/m6502.h | 340 + src/cpu/m6502/ops02.h | 813 + src/cpu/m6502/opsc02.h | 363 + src/cpu/m6502/opsn2a03.h | 38 + src/cpu/m6502/t6502.c | 360 + src/cpu/m6502/t65c02.c | 413 + src/cpu/m6502/t65sc02.c | 80 + src/cpu/m6502/tdeco16.c | 427 + src/cpu/m6502/tn2a03.c | 114 + src/cpu/m6502_intf.cpp | 448 + src/cpu/m6502_intf.h | 93 + src/cpu/m6800/6800ops.c | 2142 + src/cpu/m6800/6800tbl.c | 398 + src/cpu/m6800/m6800.cpp | 2445 + src/cpu/m6800/m6800.h | 296 + src/cpu/m6800_intf.cpp | 420 + src/cpu/m6800_intf.h | 179 + src/cpu/m6805/6805ops.c | 1822 + src/cpu/m6805/m6805.cpp | 863 + src/cpu/m6805/m6805.h | 69 + src/cpu/m6805_intf.cpp | 141 + src/cpu/m6805_intf.h | 41 + src/cpu/m6809/6809ops.c | 2997 ++ src/cpu/m6809/6809tbl.c | 316 + src/cpu/m6809/m6809.cpp | 1217 + src/cpu/m6809/m6809.h | 83 + src/cpu/m6809_intf.cpp | 308 + src/cpu/m6809_intf.h | 61 + src/cpu/m68k/m68k.h | 365 + src/cpu/m68k/m68k_in.c | 10459 ++++ src/cpu/m68k/m68kconf.h | 268 + src/cpu/m68k/m68kcpu.c | 923 + src/cpu/m68k/m68kcpu.h | 1993 + src/cpu/m68k/m68kdasm.c | 3533 ++ src/cpu/m68k/m68kmake.c | 1482 + src/cpu/nec/nec.cpp | 762 + src/cpu/nec/nec.h | 37 + src/cpu/nec/necea.h | 60 + src/cpu/nec/necinstr.c | 673 + src/cpu/nec/necinstr.h | 507 + src/cpu/nec/necmacro.h | 266 + src/cpu/nec/necmodrm.h | 104 + src/cpu/nec/necpriv.h | 178 + src/cpu/nec/v25.cpp | 861 + src/cpu/nec/v25instr.c | 81 + src/cpu/nec/v25instr.h | 510 + src/cpu/nec/v25priv.h | 265 + src/cpu/nec/v25sfr.c | 412 + src/cpu/s2650/s2650.cpp | 1500 + src/cpu/s2650/s2650.h | 33 + src/cpu/s2650_intf.cpp | 188 + src/cpu/s2650_intf.h | 60 + src/cpu/sek.cpp | 1889 + src/cpu/sek.h | 205 + src/cpu/sekdebug.h | 27 + src/cpu/sh2/sh2.cpp | 3367 ++ src/cpu/sh2/sh2.h | 55 + src/cpu/vez.cpp | 392 + src/cpu/vez.h | 60 + src/cpu/z80/z80.cpp | 4095 ++ src/cpu/z80/z80.h | 88 + src/cpu/z80/z80daisy.cpp | 77 + src/cpu/z80/z80daisy.h | 36 + src/cpu/zet.cpp | 478 + src/cpu/zet.h | 51 + src/depend/kaillera/client/kailleraclient.h | 135 + src/depend/kaillera/client/net.cpp | 106 + src/depend/kaillera/client/net.h | 15 + src/depend/libs/libpng/fba_libpng_v154.txt | 0 src/depend/libs/libpng/png.c | 2422 + src/depend/libs/libpng/png.h | 2588 + src/depend/libs/libpng/pngconf.h | 619 + src/depend/libs/libpng/pngdebug.h | 157 + src/depend/libs/libpng/pngerror.c | 672 + src/depend/libs/libpng/pngget.c | 1032 + src/depend/libs/libpng/pnginfo.h | 269 + src/depend/libs/libpng/pnglibconf.h | 187 + src/depend/libs/libpng/pngmem.c | 667 + src/depend/libs/libpng/pngpread.c | 1856 + src/depend/libs/libpng/pngpriv.h | 1358 + src/depend/libs/libpng/pngread.c | 1454 + src/depend/libs/libpng/pngrio.c | 176 + src/depend/libs/libpng/pngrtran.c | 4953 ++ src/depend/libs/libpng/pngrutil.c | 3666 ++ src/depend/libs/libpng/pngset.c | 1226 + src/depend/libs/libpng/pngstruct.h | 337 + src/depend/libs/libpng/pngtest.c | 1797 + src/depend/libs/libpng/pngtrans.c | 678 + src/depend/libs/libpng/pngwio.c | 254 + src/depend/libs/libpng/pngwrite.c | 1655 + src/depend/libs/libpng/pngwtran.c | 633 + src/depend/libs/libpng/pngwutil.c | 3179 ++ src/depend/libs/zlib/adler32.c | 169 + src/depend/libs/zlib/compress.c | 80 + src/depend/libs/zlib/crc32.c | 442 + src/depend/libs/zlib/crc32.h | 441 + src/depend/libs/zlib/deflate.c | 1834 + src/depend/libs/zlib/deflate.h | 342 + src/depend/libs/zlib/fba_zlib_v125.txt | 0 src/depend/libs/zlib/gzclose.c | 25 + src/depend/libs/zlib/gzguts.h | 132 + src/depend/libs/zlib/gzlib.c | 537 + src/depend/libs/zlib/gzread.c | 653 + src/depend/libs/zlib/gzwrite.c | 531 + src/depend/libs/zlib/infback.c | 632 + src/depend/libs/zlib/inffast.c | 340 + src/depend/libs/zlib/inffast.h | 11 + src/depend/libs/zlib/inffixed.h | 94 + src/depend/libs/zlib/inflate.c | 1480 + src/depend/libs/zlib/inflate.h | 122 + src/depend/libs/zlib/inftrees.c | 330 + src/depend/libs/zlib/inftrees.h | 62 + src/depend/libs/zlib/trees.c | 1244 + src/depend/libs/zlib/trees.h | 128 + src/depend/libs/zlib/uncompr.c | 59 + src/depend/libs/zlib/zconf.h | 428 + src/depend/libs/zlib/zconf.h.in | 428 + src/depend/libs/zlib/zlib.h | 1613 + src/depend/libs/zlib/zutil.c | 318 + src/depend/libs/zlib/zutil.h | 274 + src/depend/mingw/include/directx9/d3dx9.h | 78 + src/depend/mingw/include/directx9/d3dx9anim.h | 1114 + src/depend/mingw/include/directx9/d3dx9core.h | 754 + .../mingw/include/directx9/d3dx9effect.h | 873 + src/depend/mingw/include/directx9/d3dx9math.h | 1798 + .../mingw/include/directx9/d3dx9math.inl | 2251 + src/depend/mingw/include/directx9/d3dx9mesh.h | 3007 ++ .../mingw/include/directx9/d3dx9shader.h | 1010 + .../mingw/include/directx9/d3dx9shape.h | 221 + src/depend/mingw/include/directx9/d3dx9tex.h | 1735 + src/depend/mingw/include/directx9/d3dx9xof.h | 299 + src/depend/mingw/include/mingw_win32.h | 89 + src/depend/mingw/include/xaudio2/audiodefs.h | 263 + src/depend/mingw/include/xaudio2/sal.h | 252 + src/depend/mingw/include/xaudio2/xaudio2.h | 1290 + src/depend/mingw/include/xaudio2/xaudio2fx.h | 439 + src/depend/mingw/include/xaudio2/xma2defs.h | 728 + src/depend/scripts/build_details.cpp | 42 + src/depend/scripts/cave_sprite_func.pl | 127 + src/depend/scripts/cave_tile_func.pl | 103 + src/depend/scripts/fixrc.pl | 92 + src/depend/scripts/gamelist.pl | 441 + src/depend/scripts/license2rtf.pl | 115 + src/depend/scripts/neo_sprite_func.pl | 81 + src/depend/scripts/psikyo_tile_func.pl | 95 + src/depend/scripts/toa_gp9001_func.pl | 113 + src/depend/vc/include/afxres.h | 6 + src/interface/aud_dsp.cpp | 64 + src/interface/aud_dsp.h | 4 + src/interface/aud_interface.cpp | 184 + src/interface/cd_interface.cpp | 141 + src/interface/cd_interface.h | 41 + src/interface/inp_interface.cpp | 468 + src/interface/inp_keys.h | 148 + src/interface/interface.cpp | 96 + src/interface/interface.h | 242 + src/interface/lowpass2.cpp | 118 + src/interface/lowpass2.h | 25 + src/interface/prf_interface.cpp | 108 + src/interface/scalers/2xpm.cpp | 548 + src/interface/scalers/2xsai.cpp | 1208 + src/interface/scalers/2xsaimmx.asm | 2067 + src/interface/scalers/eagle_fm.asm | 462 + src/interface/scalers/epx.cpp | 223 + src/interface/scalers/hq2x32.asm | 1934 + src/interface/scalers/hq2xs.cpp | 352 + src/interface/scalers/hq2xs.h | 1824 + src/interface/scalers/hq2xs_16.cpp | 764 + src/interface/scalers/hq3x32.asm | 2475 + src/interface/scalers/hq3xs.cpp | 266 + src/interface/scalers/hq3xs.h | 3692 ++ src/interface/scalers/hq4x32.asm | 4015 ++ src/interface/scalers/hq_shared32.cpp | 413 + src/interface/scalers/hq_shared32.h | 41 + src/interface/scalers/interp.h | 355 + src/interface/scalers/scale2x.h | 924 + src/interface/scalers/scale2x_vc.h | 443 + src/interface/scalers/scale3x.h | 292 + src/interface/scalers/superscale.asm | 207 + src/interface/vid_interface.cpp | 449 + src/interface/vid_softfx.cpp | 944 + src/interface/vid_softfx.h | 60 + src/interface/vid_support.cpp | 39 + src/interface/vid_support.h | 2 + src/interface/win32/aud_dsound3.cpp | 304 + src/interface/win32/aud_xaudio2.cpp | 379 + src/interface/win32/cd_isowav.cpp | 595 + src/interface/win32/cdsound.cpp | 411 + src/interface/win32/cdsound.h | 58 + src/interface/win32/ddraw_core.cpp | 72 + src/interface/win32/ddraw_core.h | 21 + src/interface/win32/dinput_core.cpp | 602 + src/interface/win32/dinput_core.h | 16 + src/interface/win32/directx9_core.cpp | 158 + src/interface/win32/directx9_core.h | 63 + src/interface/win32/dsound_core.cpp | 54 + src/interface/win32/dsound_core.h | 11 + src/interface/win32/inp_dinput.cpp | 876 + .../win32/prf_performance_counter.cpp | 88 + src/interface/win32/resource/bicubic.fx | 801 + src/interface/win32/rgb_pattern.h | 210 + src/interface/win32/vid_d3d.cpp | 2428 + src/interface/win32/vid_ddraw.cpp | 1147 + src/interface/win32/vid_ddrawfx.cpp | 573 + src/interface/win32/vid_directx9.cpp | 2230 + src/interface/win32/vid_directx_support.cpp | 1689 + src/interface/win32/vid_directx_support.h | 46 + src/license.txt | 47 + whatsnew.html | 2142 + 811 files changed, 804772 insertions(+) create mode 100644 fba.chm create mode 100644 makefile create mode 100644 makefile.mingw create mode 100644 makefile.rules create mode 100644 makefile.vc create mode 100644 preset-example.zip create mode 100644 src/burn/bitswap.h create mode 100644 src/burn/burn.cpp create mode 100644 src/burn/burn.h create mode 100644 src/burn/burn_gun.cpp create mode 100644 src/burn/burn_gun.h create mode 100644 src/burn/burn_led.cpp create mode 100644 src/burn/burn_led.h create mode 100644 src/burn/burn_memory.cpp create mode 100644 src/burn/burn_sound.cpp create mode 100644 src/burn/burn_sound.h create mode 100644 src/burn/burn_sound_a.asm create mode 100644 src/burn/burn_sound_c.cpp create mode 100644 src/burn/burnint.h create mode 100644 src/burn/cheat.cpp create mode 100644 src/burn/cheat.h create mode 100644 src/burn/devices/8255ppi.cpp create mode 100644 src/burn/devices/8255ppi.h create mode 100644 src/burn/devices/eeprom.cpp create mode 100644 src/burn/devices/eeprom.h create mode 100644 src/burn/devices/pandora.cpp create mode 100644 src/burn/devices/pandora.h create mode 100644 src/burn/devices/seibusnd.cpp create mode 100644 src/burn/devices/seibusnd.h create mode 100644 src/burn/devices/timekpr.cpp create mode 100644 src/burn/devices/timekpr.h create mode 100644 src/burn/driver.h create mode 100644 src/burn/drivers/capcom/cps.cpp create mode 100644 src/burn/drivers/capcom/cps.h create mode 100644 src/burn/drivers/capcom/cps2_crpt.cpp create mode 100644 src/burn/drivers/capcom/cps_config.cpp create mode 100644 src/burn/drivers/capcom/cps_draw.cpp create mode 100644 src/burn/drivers/capcom/cps_mem.cpp create mode 100644 src/burn/drivers/capcom/cps_obj.cpp create mode 100644 src/burn/drivers/capcom/cps_pal.cpp create mode 100644 src/burn/drivers/capcom/cps_run.cpp create mode 100644 src/burn/drivers/capcom/cps_rw.cpp create mode 100644 src/burn/drivers/capcom/cps_scr.cpp create mode 100644 src/burn/drivers/capcom/cpsr.cpp create mode 100644 src/burn/drivers/capcom/cpsrd.cpp create mode 100644 src/burn/drivers/capcom/cpst.cpp create mode 100644 src/burn/drivers/capcom/ctv.cpp create mode 100644 src/burn/drivers/capcom/ctv_do.h create mode 100644 src/burn/drivers/capcom/ctv_make.cpp create mode 100644 src/burn/drivers/capcom/d_cps1.cpp create mode 100644 src/burn/drivers/capcom/d_cps2.cpp create mode 100644 src/burn/drivers/capcom/kabuki.cpp create mode 100644 src/burn/drivers/capcom/ps.cpp create mode 100644 src/burn/drivers/capcom/ps_m.cpp create mode 100644 src/burn/drivers/capcom/ps_z.cpp create mode 100644 src/burn/drivers/capcom/qs.cpp create mode 100644 src/burn/drivers/capcom/qs_c.cpp create mode 100644 src/burn/drivers/capcom/qs_z.cpp create mode 100644 src/burn/drivers/cave/cave.cpp create mode 100644 src/burn/drivers/cave/cave.h create mode 100644 src/burn/drivers/cave/cave_palette.cpp create mode 100644 src/burn/drivers/cave/cave_sprite.cpp create mode 100644 src/burn/drivers/cave/cave_sprite_render.h create mode 100644 src/burn/drivers/cave/cave_sprite_render_zoom.h create mode 100644 src/burn/drivers/cave/cave_tile.cpp create mode 100644 src/burn/drivers/cave/cave_tile_render.h create mode 100644 src/burn/drivers/cave/d_dodonpachi.cpp create mode 100644 src/burn/drivers/cave/d_donpachi.cpp create mode 100644 src/burn/drivers/cave/d_esprade.cpp create mode 100644 src/burn/drivers/cave/d_feversos.cpp create mode 100644 src/burn/drivers/cave/d_gaia.cpp create mode 100644 src/burn/drivers/cave/d_guwange.cpp create mode 100644 src/burn/drivers/cave/d_hotdogst.cpp create mode 100644 src/burn/drivers/cave/d_korokoro.cpp create mode 100644 src/burn/drivers/cave/d_mazinger.cpp create mode 100644 src/burn/drivers/cave/d_metmqstr.cpp create mode 100644 src/burn/drivers/cave/d_pwrinst2.cpp create mode 100644 src/burn/drivers/cave/d_sailormn.cpp create mode 100644 src/burn/drivers/cave/d_tjumpman.cpp create mode 100644 src/burn/drivers/cave/d_uopoko.cpp create mode 100644 src/burn/drivers/cps3/cps3.h create mode 100644 src/burn/drivers/cps3/cps3run.cpp create mode 100644 src/burn/drivers/cps3/cps3snd.cpp create mode 100644 src/burn/drivers/cps3/d_cps3.cpp create mode 100644 src/burn/drivers/d_parent.cpp create mode 100644 src/burn/drivers/galaxian/d_galaxian.cpp create mode 100644 src/burn/drivers/galaxian/gal.h create mode 100644 src/burn/drivers/galaxian/gal_gfx.cpp create mode 100644 src/burn/drivers/galaxian/gal_run.cpp create mode 100644 src/burn/drivers/galaxian/gal_sound.cpp create mode 100644 src/burn/drivers/galaxian/gal_stars.cpp create mode 100644 src/burn/drivers/irem/d_m62.cpp create mode 100644 src/burn/drivers/irem/d_m63.cpp create mode 100644 src/burn/drivers/irem/d_m72.cpp create mode 100644 src/burn/drivers/irem/d_m90.cpp create mode 100644 src/burn/drivers/irem/d_m92.cpp create mode 100644 src/burn/drivers/irem/irem_cpu.cpp create mode 100644 src/burn/drivers/irem/irem_cpu.h create mode 100644 src/burn/drivers/konami/d_88games.cpp create mode 100644 src/burn/drivers/konami/d_ajax.cpp create mode 100644 src/burn/drivers/konami/d_aliens.cpp create mode 100644 src/burn/drivers/konami/d_blockhl.cpp create mode 100644 src/burn/drivers/konami/d_bottom9.cpp create mode 100644 src/burn/drivers/konami/d_contra.cpp create mode 100644 src/burn/drivers/konami/d_crimfght.cpp create mode 100644 src/burn/drivers/konami/d_gbusters.cpp create mode 100644 src/burn/drivers/konami/d_gradius3.cpp create mode 100644 src/burn/drivers/konami/d_hcastle.cpp create mode 100644 src/burn/drivers/konami/d_hexion.cpp create mode 100644 src/burn/drivers/konami/d_mainevt.cpp create mode 100644 src/burn/drivers/konami/d_parodius.cpp create mode 100644 src/burn/drivers/konami/d_rollerg.cpp create mode 100644 src/burn/drivers/konami/d_simpsons.cpp create mode 100644 src/burn/drivers/konami/d_spy.cpp create mode 100644 src/burn/drivers/konami/d_surpratk.cpp create mode 100644 src/burn/drivers/konami/d_thunderx.cpp create mode 100644 src/burn/drivers/konami/d_tmnt.cpp create mode 100644 src/burn/drivers/konami/d_twin16.cpp create mode 100644 src/burn/drivers/konami/d_ultraman.cpp create mode 100644 src/burn/drivers/konami/d_vendetta.cpp create mode 100644 src/burn/drivers/konami/d_xmen.cpp create mode 100644 src/burn/drivers/konami/k051316.cpp create mode 100644 src/burn/drivers/konami/k051733.cpp create mode 100644 src/burn/drivers/konami/k051960.cpp create mode 100644 src/burn/drivers/konami/k052109.cpp create mode 100644 src/burn/drivers/konami/k053245.cpp create mode 100644 src/burn/drivers/konami/k053247.cpp create mode 100644 src/burn/drivers/konami/k053251.cpp create mode 100644 src/burn/drivers/konami/k053936.cpp create mode 100644 src/burn/drivers/konami/k054000.cpp create mode 100644 src/burn/drivers/konami/konamiic.cpp create mode 100644 src/burn/drivers/konami/konamiic.h create mode 100644 src/burn/drivers/megadrive/d_megadrive.cpp create mode 100644 src/burn/drivers/megadrive/megadrive.cpp create mode 100644 src/burn/drivers/megadrive/megadrive.h create mode 100644 src/burn/drivers/misc_post90s/d_1945kiii.cpp create mode 100644 src/burn/drivers/misc_post90s/d_aerofgt.cpp create mode 100644 src/burn/drivers/misc_post90s/d_airbustr.cpp create mode 100644 src/burn/drivers/misc_post90s/d_aquarium.cpp create mode 100644 src/burn/drivers/misc_post90s/d_ashnojoe.cpp create mode 100644 src/burn/drivers/misc_post90s/d_backfire.cpp create mode 100644 src/burn/drivers/misc_post90s/d_bloodbro.cpp create mode 100644 src/burn/drivers/misc_post90s/d_boogwing.cpp create mode 100644 src/burn/drivers/misc_post90s/d_cbuster.cpp create mode 100644 src/burn/drivers/misc_post90s/d_cninja.cpp create mode 100644 src/burn/drivers/misc_post90s/d_crospang.cpp create mode 100644 src/burn/drivers/misc_post90s/d_crshrace.cpp create mode 100644 src/burn/drivers/misc_post90s/d_darkseal.cpp create mode 100644 src/burn/drivers/misc_post90s/d_dassault.cpp create mode 100644 src/burn/drivers/misc_post90s/d_dcon.cpp create mode 100644 src/burn/drivers/misc_post90s/d_ddragon3.cpp create mode 100644 src/burn/drivers/misc_post90s/d_deniam.cpp create mode 100644 src/burn/drivers/misc_post90s/d_dietgogo.cpp create mode 100644 src/burn/drivers/misc_post90s/d_diverboy.cpp create mode 100644 src/burn/drivers/misc_post90s/d_drtomy.cpp create mode 100644 src/burn/drivers/misc_post90s/d_egghunt.cpp create mode 100644 src/burn/drivers/misc_post90s/d_esd16.cpp create mode 100644 src/burn/drivers/misc_post90s/d_f1gp.cpp create mode 100644 src/burn/drivers/misc_post90s/d_fstarfrc.cpp create mode 100644 src/burn/drivers/misc_post90s/d_funkyjet.cpp create mode 100644 src/burn/drivers/misc_post90s/d_funybubl.cpp create mode 100644 src/burn/drivers/misc_post90s/d_fuukifg3.cpp create mode 100644 src/burn/drivers/misc_post90s/d_gaelco.cpp create mode 100644 src/burn/drivers/misc_post90s/d_gaiden.cpp create mode 100644 src/burn/drivers/misc_post90s/d_galpanic.cpp create mode 100644 src/burn/drivers/misc_post90s/d_gotcha.cpp create mode 100644 src/burn/drivers/misc_post90s/d_gumbo.cpp create mode 100644 src/burn/drivers/misc_post90s/d_hyperpac.cpp create mode 100644 src/burn/drivers/misc_post90s/d_kaneko16.cpp create mode 100644 src/burn/drivers/misc_post90s/d_lordgun.cpp create mode 100644 src/burn/drivers/misc_post90s/d_mcatadv.cpp create mode 100644 src/burn/drivers/misc_post90s/d_midas.cpp create mode 100644 src/burn/drivers/misc_post90s/d_mogura.cpp create mode 100644 src/burn/drivers/misc_post90s/d_mugsmash.cpp create mode 100644 src/burn/drivers/misc_post90s/d_news.cpp create mode 100644 src/burn/drivers/misc_post90s/d_nmg5.cpp create mode 100644 src/burn/drivers/misc_post90s/d_nmk16.cpp create mode 100644 src/burn/drivers/misc_post90s/d_ohmygod.cpp create mode 100644 src/burn/drivers/misc_post90s/d_pass.cpp create mode 100644 src/burn/drivers/misc_post90s/d_pirates.cpp create mode 100644 src/burn/drivers/misc_post90s/d_pktgaldx.cpp create mode 100644 src/burn/drivers/misc_post90s/d_powerins.cpp create mode 100644 src/burn/drivers/misc_post90s/d_pushman.cpp create mode 100644 src/burn/drivers/misc_post90s/d_raiden.cpp create mode 100644 src/burn/drivers/misc_post90s/d_rohga.cpp create mode 100644 src/burn/drivers/misc_post90s/d_seta.cpp create mode 100644 src/burn/drivers/misc_post90s/d_seta2.cpp create mode 100644 src/burn/drivers/misc_post90s/d_shadfrce.cpp create mode 100644 src/burn/drivers/misc_post90s/d_silkroad.cpp create mode 100644 src/burn/drivers/misc_post90s/d_simpl156.cpp create mode 100644 src/burn/drivers/misc_post90s/d_speedspn.cpp create mode 100644 src/burn/drivers/misc_post90s/d_suna16.cpp create mode 100644 src/burn/drivers/misc_post90s/d_supbtime.cpp create mode 100644 src/burn/drivers/misc_post90s/d_suprnova.cpp create mode 100644 src/burn/drivers/misc_post90s/d_taotaido.cpp create mode 100644 src/burn/drivers/misc_post90s/d_tecmosys.cpp create mode 100644 src/burn/drivers/misc_post90s/d_tumbleb.cpp create mode 100644 src/burn/drivers/misc_post90s/d_tumblep.cpp create mode 100644 src/burn/drivers/misc_post90s/d_unico.cpp create mode 100644 src/burn/drivers/misc_post90s/d_vmetal.cpp create mode 100644 src/burn/drivers/misc_post90s/d_welltris.cpp create mode 100644 src/burn/drivers/misc_post90s/d_wwfwfest.cpp create mode 100644 src/burn/drivers/misc_post90s/d_xorworld.cpp create mode 100644 src/burn/drivers/misc_post90s/d_yunsun16.cpp create mode 100644 src/burn/drivers/misc_post90s/d_zerozone.cpp create mode 100644 src/burn/drivers/misc_post90s/deco16ic.cpp create mode 100644 src/burn/drivers/misc_post90s/deco16ic.h create mode 100644 src/burn/drivers/misc_post90s/kanekotb.h create mode 100644 src/burn/drivers/misc_post90s/nmk004.cpp create mode 100644 src/burn/drivers/misc_post90s/nmk004.h create mode 100644 src/burn/drivers/misc_pre90s/d_1942.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_1943.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_4enraya.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_ambush.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_angelkds.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_arabian.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_arkanoid.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_armedf.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_aztarac.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_bankp.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_baraduke.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_bionicc.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_blktiger.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_blockout.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_blueprnt.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_bombjack.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_chaknpop.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_commando.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_ddragon.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_dec0.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_dec8.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_dotrikun.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_dynduke.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_epos.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_exedexes.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_flstory.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_funkybee.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_galaga.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_gauntlet.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_gberet.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_ginganin.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_gng.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_gunsmoke.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_gyruss.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_higemaru.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_ikki.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_jack.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_kangaroo.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_karnov.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_kyugo.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_ladybug.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_lkage.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_lwings.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_madgear.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_marineb.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_markham.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_meijinsn.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_minivdr.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_mitchell.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_mole.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_mrdo.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_mrflea.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_mystston.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_pac2650.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_pacman.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_pkunwar.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_pooyan.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_prehisle.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_quizo.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_rallyx.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_renegade.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_retofinv.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_route16.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_scotrsht.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_scregg.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_sf.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_skyfox.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_skykid.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_snk68.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_solomon.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_sonson.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_srumbler.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_tecmo.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_tigerheli.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_tigeroad.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_tnzs.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_toki.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_vaportra.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_vigilant.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_vulgus.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_wallc.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_wc90.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_wc90b.cpp create mode 100644 src/burn/drivers/misc_pre90s/d_wwfsstar.cpp create mode 100644 src/burn/drivers/misc_pre90s/tnzs_prot.cpp create mode 100644 src/burn/drivers/misc_pre90s/tnzs_prot.h create mode 100644 src/burn/drivers/neogeo/d_neogeo.cpp create mode 100644 src/burn/drivers/neogeo/neo_decrypt.cpp create mode 100644 src/burn/drivers/neogeo/neo_palette.cpp create mode 100644 src/burn/drivers/neogeo/neo_run.cpp create mode 100644 src/burn/drivers/neogeo/neo_sprite.cpp create mode 100644 src/burn/drivers/neogeo/neo_sprite_render.h create mode 100644 src/burn/drivers/neogeo/neo_text.cpp create mode 100644 src/burn/drivers/neogeo/neo_text_render.h create mode 100644 src/burn/drivers/neogeo/neo_upd4990a.cpp create mode 100644 src/burn/drivers/neogeo/neogeo.cpp create mode 100644 src/burn/drivers/neogeo/neogeo.h create mode 100644 src/burn/drivers/pgm/changes.txt create mode 100644 src/burn/drivers/pgm/d_pgm.cpp create mode 100644 src/burn/drivers/pgm/pgm.h create mode 100644 src/burn/drivers/pgm/pgm_crypt.cpp create mode 100644 src/burn/drivers/pgm/pgm_draw.cpp create mode 100644 src/burn/drivers/pgm/pgm_prot.cpp create mode 100644 src/burn/drivers/pgm/pgm_run.cpp create mode 100644 src/burn/drivers/psikyo/d_psikyo.cpp create mode 100644 src/burn/drivers/psikyo/d_psikyosh.cpp create mode 100644 src/burn/drivers/psikyo/psikyo.h create mode 100644 src/burn/drivers/psikyo/psikyo_palette.cpp create mode 100644 src/burn/drivers/psikyo/psikyo_render.h create mode 100644 src/burn/drivers/psikyo/psikyo_sprite.cpp create mode 100644 src/burn/drivers/psikyo/psikyo_sprite_func.h create mode 100644 src/burn/drivers/psikyo/psikyo_tile.cpp create mode 100644 src/burn/drivers/psikyo/psikyosh_render.cpp create mode 100644 src/burn/drivers/psikyo/psikyosh_render.h create mode 100644 src/burn/drivers/sega/d_hangon.cpp create mode 100644 src/burn/drivers/sega/d_outrun.cpp create mode 100644 src/burn/drivers/sega/d_sys1.cpp create mode 100644 src/burn/drivers/sega/d_sys16a.cpp create mode 100644 src/burn/drivers/sega/d_sys16b.cpp create mode 100644 src/burn/drivers/sega/d_sys18.cpp create mode 100644 src/burn/drivers/sega/d_xbrd.cpp create mode 100644 src/burn/drivers/sega/d_ybrd.cpp create mode 100644 src/burn/drivers/sega/fd1089.cpp create mode 100644 src/burn/drivers/sega/fd1094.cpp create mode 100644 src/burn/drivers/sega/fd1094.h create mode 100644 src/burn/drivers/sega/genesis_vid.cpp create mode 100644 src/burn/drivers/sega/genesis_vid.h create mode 100644 src/burn/drivers/sega/mc8123.cpp create mode 100644 src/burn/drivers/sega/mc8123.h create mode 100644 src/burn/drivers/sega/sys16.h create mode 100644 src/burn/drivers/sega/sys16_fd1094.cpp create mode 100644 src/burn/drivers/sega/sys16_gfx.cpp create mode 100644 src/burn/drivers/sega/sys16_run.cpp create mode 100644 src/burn/drivers/taito/cchip.cpp create mode 100644 src/burn/drivers/taito/d_asuka.cpp create mode 100644 src/burn/drivers/taito/d_bublbobl.cpp create mode 100644 src/burn/drivers/taito/d_darius2.cpp create mode 100644 src/burn/drivers/taito/d_othunder.cpp create mode 100644 src/burn/drivers/taito/d_slapshot.cpp create mode 100644 src/burn/drivers/taito/d_superchs.cpp create mode 100644 src/burn/drivers/taito/d_taitob.cpp create mode 100644 src/burn/drivers/taito/d_taitof2.cpp create mode 100644 src/burn/drivers/taito/d_taitomisc.cpp create mode 100644 src/burn/drivers/taito/d_taitox.cpp create mode 100644 src/burn/drivers/taito/d_taitoz.cpp create mode 100644 src/burn/drivers/taito/pc080sn.cpp create mode 100644 src/burn/drivers/taito/pc090oj.cpp create mode 100644 src/burn/drivers/taito/taito.cpp create mode 100644 src/burn/drivers/taito/taito.h create mode 100644 src/burn/drivers/taito/taito_ic.cpp create mode 100644 src/burn/drivers/taito/taito_ic.h create mode 100644 src/burn/drivers/taito/taito_m68705.cpp create mode 100644 src/burn/drivers/taito/taito_m68705.h create mode 100644 src/burn/drivers/taito/tc0100scn.cpp create mode 100644 src/burn/drivers/taito/tc0110pcr.cpp create mode 100644 src/burn/drivers/taito/tc0140syt.cpp create mode 100644 src/burn/drivers/taito/tc0150rod.cpp create mode 100644 src/burn/drivers/taito/tc0180vcu.cpp create mode 100644 src/burn/drivers/taito/tc0220ioc.cpp create mode 100644 src/burn/drivers/taito/tc0280grd.cpp create mode 100644 src/burn/drivers/taito/tc0360pri.cpp create mode 100644 src/burn/drivers/taito/tc0480scp.cpp create mode 100644 src/burn/drivers/taito/tc0510nio.cpp create mode 100644 src/burn/drivers/taito/tc0640fio.cpp create mode 100644 src/burn/drivers/toaplan/d_batrider.cpp create mode 100644 src/burn/drivers/toaplan/d_batsugun.cpp create mode 100644 src/burn/drivers/toaplan/d_battleg.cpp create mode 100644 src/burn/drivers/toaplan/d_bbakraid.cpp create mode 100644 src/burn/drivers/toaplan/d_demonwld.cpp create mode 100644 src/burn/drivers/toaplan/d_dogyuun.cpp create mode 100644 src/burn/drivers/toaplan/d_fixeight.cpp create mode 100644 src/burn/drivers/toaplan/d_ghox.cpp create mode 100644 src/burn/drivers/toaplan/d_hellfire.cpp create mode 100644 src/burn/drivers/toaplan/d_kbash.cpp create mode 100644 src/burn/drivers/toaplan/d_kbash2.cpp create mode 100644 src/burn/drivers/toaplan/d_mahoudai.cpp create mode 100644 src/burn/drivers/toaplan/d_outzone.cpp create mode 100644 src/burn/drivers/toaplan/d_pipibibs.cpp create mode 100644 src/burn/drivers/toaplan/d_rallybik.cpp create mode 100644 src/burn/drivers/toaplan/d_samesame.cpp create mode 100644 src/burn/drivers/toaplan/d_shippumd.cpp create mode 100644 src/burn/drivers/toaplan/d_snowbro2.cpp create mode 100644 src/burn/drivers/toaplan/d_tekipaki.cpp create mode 100644 src/burn/drivers/toaplan/d_truxton.cpp create mode 100644 src/burn/drivers/toaplan/d_truxton2.cpp create mode 100644 src/burn/drivers/toaplan/d_vfive.cpp create mode 100644 src/burn/drivers/toaplan/d_vimana.cpp create mode 100644 src/burn/drivers/toaplan/d_zerowing.cpp create mode 100644 src/burn/drivers/toaplan/toa_bcu2.cpp create mode 100644 src/burn/drivers/toaplan/toa_extratext.cpp create mode 100644 src/burn/drivers/toaplan/toa_extratext.h create mode 100644 src/burn/drivers/toaplan/toa_gp9001.cpp create mode 100644 src/burn/drivers/toaplan/toa_gp9001_render.h create mode 100644 src/burn/drivers/toaplan/toa_palette.cpp create mode 100644 src/burn/drivers/toaplan/toaplan.cpp create mode 100644 src/burn/drivers/toaplan/toaplan.h create mode 100644 src/burn/drivers/toaplan/toaplan1.cpp create mode 100644 src/burn/hiscore.cpp create mode 100644 src/burn/hiscore.h create mode 100644 src/burn/load.cpp create mode 100644 src/burn/sound/ay8910.c create mode 100644 src/burn/sound/ay8910.h create mode 100644 src/burn/sound/burn_y8950.cpp create mode 100644 src/burn/sound/burn_y8950.h create mode 100644 src/burn/sound/burn_ym2151.cpp create mode 100644 src/burn/sound/burn_ym2151.h create mode 100644 src/burn/sound/burn_ym2203.cpp create mode 100644 src/burn/sound/burn_ym2203.h create mode 100644 src/burn/sound/burn_ym2413.cpp create mode 100644 src/burn/sound/burn_ym2413.h create mode 100644 src/burn/sound/burn_ym2608.cpp create mode 100644 src/burn/sound/burn_ym2608.h create mode 100644 src/burn/sound/burn_ym2610.cpp create mode 100644 src/burn/sound/burn_ym2610.h create mode 100644 src/burn/sound/burn_ym2612.cpp create mode 100644 src/burn/sound/burn_ym2612.h create mode 100644 src/burn/sound/burn_ym3526.cpp create mode 100644 src/burn/sound/burn_ym3526.h create mode 100644 src/burn/sound/burn_ym3812.cpp create mode 100644 src/burn/sound/burn_ym3812.h create mode 100644 src/burn/sound/burn_ymf278b.cpp create mode 100644 src/burn/sound/burn_ymf278b.h create mode 100644 src/burn/sound/dac.cpp create mode 100644 src/burn/sound/dac.h create mode 100644 src/burn/sound/es5506.cpp create mode 100644 src/burn/sound/es5506.h create mode 100644 src/burn/sound/es8712.cpp create mode 100644 src/burn/sound/es8712.h create mode 100644 src/burn/sound/fm.c create mode 100644 src/burn/sound/fm.h create mode 100644 src/burn/sound/fmopl.c create mode 100644 src/burn/sound/fmopl.h create mode 100644 src/burn/sound/ics2115.cpp create mode 100644 src/burn/sound/ics2115.h create mode 100644 src/burn/sound/iremga20.cpp create mode 100644 src/burn/sound/iremga20.h create mode 100644 src/burn/sound/k007232.cpp create mode 100644 src/burn/sound/k007232.h create mode 100644 src/burn/sound/k051649.cpp create mode 100644 src/burn/sound/k051649.h create mode 100644 src/burn/sound/k053260.cpp create mode 100644 src/burn/sound/k053260.h create mode 100644 src/burn/sound/k054539.cpp create mode 100644 src/burn/sound/k054539.h create mode 100644 src/burn/sound/msm5205.cpp create mode 100644 src/burn/sound/msm5205.h create mode 100644 src/burn/sound/msm6295.cpp create mode 100644 src/burn/sound/msm6295.h create mode 100644 src/burn/sound/namco_snd.cpp create mode 100644 src/burn/sound/namco_snd.h create mode 100644 src/burn/sound/rf5c68.cpp create mode 100644 src/burn/sound/rf5c68.h create mode 100644 src/burn/sound/saa1099.cpp create mode 100644 src/burn/sound/saa1099.h create mode 100644 src/burn/sound/samples.cpp create mode 100644 src/burn/sound/samples.h create mode 100644 src/burn/sound/segapcm.cpp create mode 100644 src/burn/sound/segapcm.h create mode 100644 src/burn/sound/sn76496.cpp create mode 100644 src/burn/sound/sn76496.h create mode 100644 src/burn/sound/upd7759.cpp create mode 100644 src/burn/sound/upd7759.h create mode 100644 src/burn/sound/x1010.cpp create mode 100644 src/burn/sound/x1010.h create mode 100644 src/burn/sound/ym2151.c create mode 100644 src/burn/sound/ym2151.h create mode 100644 src/burn/sound/ym2413.c create mode 100644 src/burn/sound/ym2413.h create mode 100644 src/burn/sound/ymdeltat.c create mode 100644 src/burn/sound/ymdeltat.h create mode 100644 src/burn/sound/ymf278b.c create mode 100644 src/burn/sound/ymf278b.h create mode 100644 src/burn/sound/ymz280b.cpp create mode 100644 src/burn/sound/ymz280b.h create mode 100644 src/burn/state.h create mode 100644 src/burn/stdfunc.h create mode 100644 src/burn/tiles_generic.cpp create mode 100644 src/burn/tiles_generic.h create mode 100644 src/burn/timer.cpp create mode 100644 src/burn/timer.h create mode 100644 src/burn/vector.cpp create mode 100644 src/burn/vector.h create mode 100644 src/burn/version.h create mode 100644 src/burner/burner.h create mode 100644 src/burner/conc.cpp create mode 100644 src/burner/cong.cpp create mode 100644 src/burner/dat.cpp create mode 100644 src/burner/gamc.cpp create mode 100644 src/burner/gameinp.h create mode 100644 src/burner/gami.cpp create mode 100644 src/burner/image.cpp create mode 100644 src/burner/misc.cpp create mode 100644 src/burner/sshot.cpp create mode 100644 src/burner/state.cpp create mode 100644 src/burner/statec.cpp create mode 100644 src/burner/title.h create mode 100644 src/burner/unzip.c create mode 100644 src/burner/unzip.h create mode 100644 src/burner/win32/about.cpp create mode 100644 src/burner/win32/app.rc create mode 100644 src/burner/win32/burner_win32.h create mode 100644 src/burner/win32/bzip.cpp create mode 100644 src/burner/win32/cona.cpp create mode 100644 src/burner/win32/debugger.cpp create mode 100644 src/burner/win32/drv.cpp create mode 100644 src/burner/win32/dwmapi_core.cpp create mode 100644 src/burner/win32/dwmapi_core.h create mode 100644 src/burner/win32/dynhuff.cpp create mode 100644 src/burner/win32/dynhuff.h create mode 100644 src/burner/win32/fba_kaillera.cpp create mode 100644 src/burner/win32/image_win32.cpp create mode 100644 src/burner/win32/inpc.cpp create mode 100644 src/burner/win32/inpcheat.cpp create mode 100644 src/burner/win32/inpd.cpp create mode 100644 src/burner/win32/inpdipsw.cpp create mode 100644 src/burner/win32/inps.cpp create mode 100644 src/burner/win32/ips_manager.cpp create mode 100644 src/burner/win32/localise.cpp create mode 100644 src/burner/win32/main.cpp create mode 100644 src/burner/win32/mdi.cpp create mode 100644 src/burner/win32/media.cpp create mode 100644 src/burner/win32/memcard.cpp create mode 100644 src/burner/win32/menu.cpp create mode 100644 src/burner/win32/misc_win32.cpp create mode 100644 src/burner/win32/neocdlist.cpp create mode 100644 src/burner/win32/neocdlist.h create mode 100644 src/burner/win32/neocdsel.cpp create mode 100644 src/burner/win32/numdial.cpp create mode 100644 src/burner/win32/numpluscommas.cpp create mode 100644 src/burner/win32/paletteviewer.cpp create mode 100644 src/burner/win32/popup_win32.cpp create mode 100644 src/burner/win32/progress.cpp create mode 100644 src/burner/win32/replay.cpp create mode 100644 src/burner/win32/res.cpp create mode 100644 src/burner/win32/resource.h create mode 100644 src/burner/win32/resource.rc create mode 100644 src/burner/win32/resource/TV Minus.ico create mode 100644 src/burner/win32/resource/TV Not Found Non Essential.ico create mode 100644 src/burner/win32/resource/TV Not Found.ico create mode 100644 src/burner/win32/resource/TV Not Working.ico create mode 100644 src/burner/win32/resource/TV Plus.ico create mode 100644 src/burner/win32/resource/about.bmp create mode 100644 src/burner/win32/resource/fba.ico create mode 100644 src/burner/win32/resource/manifest.xml create mode 100644 src/burner/win32/resource/misc.bmp create mode 100644 src/burner/win32/resource/splash.bmp create mode 100644 src/burner/win32/resource_string.h create mode 100644 src/burner/win32/roms.cpp create mode 100644 src/burner/win32/run.cpp create mode 100644 src/burner/win32/scrn.cpp create mode 100644 src/burner/win32/sel.cpp create mode 100644 src/burner/win32/sfactd.cpp create mode 100644 src/burner/win32/splash.cpp create mode 100644 src/burner/win32/stated.cpp create mode 100644 src/burner/win32/string.rc create mode 100644 src/burner/win32/support_paths.cpp create mode 100644 src/burner/win32/systeminfo.cpp create mode 100644 src/burner/win32/version.rc create mode 100644 src/burner/win32/wave.cpp create mode 100644 src/burner/zipfn.cpp create mode 100644 src/cpu/a68k/fba_make68k.c create mode 100644 src/cpu/arm/arm.cpp create mode 100644 src/cpu/arm7/arm7.cpp create mode 100644 src/cpu/arm7/arm7core.c create mode 100644 src/cpu/arm7/arm7core.h create mode 100644 src/cpu/arm7/arm7exec.c create mode 100644 src/cpu/arm7_intf.cpp create mode 100644 src/cpu/arm7_intf.h create mode 100644 src/cpu/arm_intf.cpp create mode 100644 src/cpu/arm_intf.h create mode 100644 src/cpu/h6280/h6280.cpp create mode 100644 src/cpu/h6280/h6280.h create mode 100644 src/cpu/h6280/h6280ops.h create mode 100644 src/cpu/h6280/tblh6280.c create mode 100644 src/cpu/h6280_intf.cpp create mode 100644 src/cpu/h6280_intf.h create mode 100644 src/cpu/hd6309/6309ops.c create mode 100644 src/cpu/hd6309/6309tbl.c create mode 100644 src/cpu/hd6309/hd6309.cpp create mode 100644 src/cpu/hd6309/hd6309.h create mode 100644 src/cpu/hd6309_intf.cpp create mode 100644 src/cpu/hd6309_intf.h create mode 100644 src/cpu/i8039/i8039.cpp create mode 100644 src/cpu/i8039/i8039.h create mode 100644 src/cpu/konami/konami.cpp create mode 100644 src/cpu/konami/konami.h create mode 100644 src/cpu/konami/konamops.c create mode 100644 src/cpu/konami/konamtbl.c create mode 100644 src/cpu/konami_intf.cpp create mode 100644 src/cpu/konami_intf.h create mode 100644 src/cpu/m6502/ill02.h create mode 100644 src/cpu/m6502/m6502.cpp create mode 100644 src/cpu/m6502/m6502.h create mode 100644 src/cpu/m6502/ops02.h create mode 100644 src/cpu/m6502/opsc02.h create mode 100644 src/cpu/m6502/opsn2a03.h create mode 100644 src/cpu/m6502/t6502.c create mode 100644 src/cpu/m6502/t65c02.c create mode 100644 src/cpu/m6502/t65sc02.c create mode 100644 src/cpu/m6502/tdeco16.c create mode 100644 src/cpu/m6502/tn2a03.c create mode 100644 src/cpu/m6502_intf.cpp create mode 100644 src/cpu/m6502_intf.h create mode 100644 src/cpu/m6800/6800ops.c create mode 100644 src/cpu/m6800/6800tbl.c create mode 100644 src/cpu/m6800/m6800.cpp create mode 100644 src/cpu/m6800/m6800.h create mode 100644 src/cpu/m6800_intf.cpp create mode 100644 src/cpu/m6800_intf.h create mode 100644 src/cpu/m6805/6805ops.c create mode 100644 src/cpu/m6805/m6805.cpp create mode 100644 src/cpu/m6805/m6805.h create mode 100644 src/cpu/m6805_intf.cpp create mode 100644 src/cpu/m6805_intf.h create mode 100644 src/cpu/m6809/6809ops.c create mode 100644 src/cpu/m6809/6809tbl.c create mode 100644 src/cpu/m6809/m6809.cpp create mode 100644 src/cpu/m6809/m6809.h create mode 100644 src/cpu/m6809_intf.cpp create mode 100644 src/cpu/m6809_intf.h create mode 100644 src/cpu/m68k/m68k.h create mode 100644 src/cpu/m68k/m68k_in.c create mode 100644 src/cpu/m68k/m68kconf.h create mode 100644 src/cpu/m68k/m68kcpu.c create mode 100644 src/cpu/m68k/m68kcpu.h create mode 100644 src/cpu/m68k/m68kdasm.c create mode 100644 src/cpu/m68k/m68kmake.c create mode 100644 src/cpu/nec/nec.cpp create mode 100644 src/cpu/nec/nec.h create mode 100644 src/cpu/nec/necea.h create mode 100644 src/cpu/nec/necinstr.c create mode 100644 src/cpu/nec/necinstr.h create mode 100644 src/cpu/nec/necmacro.h create mode 100644 src/cpu/nec/necmodrm.h create mode 100644 src/cpu/nec/necpriv.h create mode 100644 src/cpu/nec/v25.cpp create mode 100644 src/cpu/nec/v25instr.c create mode 100644 src/cpu/nec/v25instr.h create mode 100644 src/cpu/nec/v25priv.h create mode 100644 src/cpu/nec/v25sfr.c create mode 100644 src/cpu/s2650/s2650.cpp create mode 100644 src/cpu/s2650/s2650.h create mode 100644 src/cpu/s2650_intf.cpp create mode 100644 src/cpu/s2650_intf.h create mode 100644 src/cpu/sek.cpp create mode 100644 src/cpu/sek.h create mode 100644 src/cpu/sekdebug.h create mode 100644 src/cpu/sh2/sh2.cpp create mode 100644 src/cpu/sh2/sh2.h create mode 100644 src/cpu/vez.cpp create mode 100644 src/cpu/vez.h create mode 100644 src/cpu/z80/z80.cpp create mode 100644 src/cpu/z80/z80.h create mode 100644 src/cpu/z80/z80daisy.cpp create mode 100644 src/cpu/z80/z80daisy.h create mode 100644 src/cpu/zet.cpp create mode 100644 src/cpu/zet.h create mode 100644 src/depend/kaillera/client/kailleraclient.h create mode 100644 src/depend/kaillera/client/net.cpp create mode 100644 src/depend/kaillera/client/net.h create mode 100644 src/depend/libs/libpng/fba_libpng_v154.txt create mode 100644 src/depend/libs/libpng/png.c create mode 100644 src/depend/libs/libpng/png.h create mode 100644 src/depend/libs/libpng/pngconf.h create mode 100644 src/depend/libs/libpng/pngdebug.h create mode 100644 src/depend/libs/libpng/pngerror.c create mode 100644 src/depend/libs/libpng/pngget.c create mode 100644 src/depend/libs/libpng/pnginfo.h create mode 100644 src/depend/libs/libpng/pnglibconf.h create mode 100644 src/depend/libs/libpng/pngmem.c create mode 100644 src/depend/libs/libpng/pngpread.c create mode 100644 src/depend/libs/libpng/pngpriv.h create mode 100644 src/depend/libs/libpng/pngread.c create mode 100644 src/depend/libs/libpng/pngrio.c create mode 100644 src/depend/libs/libpng/pngrtran.c create mode 100644 src/depend/libs/libpng/pngrutil.c create mode 100644 src/depend/libs/libpng/pngset.c create mode 100644 src/depend/libs/libpng/pngstruct.h create mode 100644 src/depend/libs/libpng/pngtest.c create mode 100644 src/depend/libs/libpng/pngtrans.c create mode 100644 src/depend/libs/libpng/pngwio.c create mode 100644 src/depend/libs/libpng/pngwrite.c create mode 100644 src/depend/libs/libpng/pngwtran.c create mode 100644 src/depend/libs/libpng/pngwutil.c create mode 100644 src/depend/libs/zlib/adler32.c create mode 100644 src/depend/libs/zlib/compress.c create mode 100644 src/depend/libs/zlib/crc32.c create mode 100644 src/depend/libs/zlib/crc32.h create mode 100644 src/depend/libs/zlib/deflate.c create mode 100644 src/depend/libs/zlib/deflate.h create mode 100644 src/depend/libs/zlib/fba_zlib_v125.txt create mode 100644 src/depend/libs/zlib/gzclose.c create mode 100644 src/depend/libs/zlib/gzguts.h create mode 100644 src/depend/libs/zlib/gzlib.c create mode 100644 src/depend/libs/zlib/gzread.c create mode 100644 src/depend/libs/zlib/gzwrite.c create mode 100644 src/depend/libs/zlib/infback.c create mode 100644 src/depend/libs/zlib/inffast.c create mode 100644 src/depend/libs/zlib/inffast.h create mode 100644 src/depend/libs/zlib/inffixed.h create mode 100644 src/depend/libs/zlib/inflate.c create mode 100644 src/depend/libs/zlib/inflate.h create mode 100644 src/depend/libs/zlib/inftrees.c create mode 100644 src/depend/libs/zlib/inftrees.h create mode 100644 src/depend/libs/zlib/trees.c create mode 100644 src/depend/libs/zlib/trees.h create mode 100644 src/depend/libs/zlib/uncompr.c create mode 100644 src/depend/libs/zlib/zconf.h create mode 100644 src/depend/libs/zlib/zconf.h.in create mode 100644 src/depend/libs/zlib/zlib.h create mode 100644 src/depend/libs/zlib/zutil.c create mode 100644 src/depend/libs/zlib/zutil.h create mode 100644 src/depend/mingw/include/directx9/d3dx9.h create mode 100644 src/depend/mingw/include/directx9/d3dx9anim.h create mode 100644 src/depend/mingw/include/directx9/d3dx9core.h create mode 100644 src/depend/mingw/include/directx9/d3dx9effect.h create mode 100644 src/depend/mingw/include/directx9/d3dx9math.h create mode 100644 src/depend/mingw/include/directx9/d3dx9math.inl create mode 100644 src/depend/mingw/include/directx9/d3dx9mesh.h create mode 100644 src/depend/mingw/include/directx9/d3dx9shader.h create mode 100644 src/depend/mingw/include/directx9/d3dx9shape.h create mode 100644 src/depend/mingw/include/directx9/d3dx9tex.h create mode 100644 src/depend/mingw/include/directx9/d3dx9xof.h create mode 100644 src/depend/mingw/include/mingw_win32.h create mode 100644 src/depend/mingw/include/xaudio2/audiodefs.h create mode 100644 src/depend/mingw/include/xaudio2/sal.h create mode 100644 src/depend/mingw/include/xaudio2/xaudio2.h create mode 100644 src/depend/mingw/include/xaudio2/xaudio2fx.h create mode 100644 src/depend/mingw/include/xaudio2/xma2defs.h create mode 100644 src/depend/scripts/build_details.cpp create mode 100644 src/depend/scripts/cave_sprite_func.pl create mode 100644 src/depend/scripts/cave_tile_func.pl create mode 100644 src/depend/scripts/fixrc.pl create mode 100644 src/depend/scripts/gamelist.pl create mode 100644 src/depend/scripts/license2rtf.pl create mode 100644 src/depend/scripts/neo_sprite_func.pl create mode 100644 src/depend/scripts/psikyo_tile_func.pl create mode 100644 src/depend/scripts/toa_gp9001_func.pl create mode 100644 src/depend/vc/include/afxres.h create mode 100644 src/interface/aud_dsp.cpp create mode 100644 src/interface/aud_dsp.h create mode 100644 src/interface/aud_interface.cpp create mode 100644 src/interface/cd_interface.cpp create mode 100644 src/interface/cd_interface.h create mode 100644 src/interface/inp_interface.cpp create mode 100644 src/interface/inp_keys.h create mode 100644 src/interface/interface.cpp create mode 100644 src/interface/interface.h create mode 100644 src/interface/lowpass2.cpp create mode 100644 src/interface/lowpass2.h create mode 100644 src/interface/prf_interface.cpp create mode 100644 src/interface/scalers/2xpm.cpp create mode 100644 src/interface/scalers/2xsai.cpp create mode 100644 src/interface/scalers/2xsaimmx.asm create mode 100644 src/interface/scalers/eagle_fm.asm create mode 100644 src/interface/scalers/epx.cpp create mode 100644 src/interface/scalers/hq2x32.asm create mode 100644 src/interface/scalers/hq2xs.cpp create mode 100644 src/interface/scalers/hq2xs.h create mode 100644 src/interface/scalers/hq2xs_16.cpp create mode 100644 src/interface/scalers/hq3x32.asm create mode 100644 src/interface/scalers/hq3xs.cpp create mode 100644 src/interface/scalers/hq3xs.h create mode 100644 src/interface/scalers/hq4x32.asm create mode 100644 src/interface/scalers/hq_shared32.cpp create mode 100644 src/interface/scalers/hq_shared32.h create mode 100644 src/interface/scalers/interp.h create mode 100644 src/interface/scalers/scale2x.h create mode 100644 src/interface/scalers/scale2x_vc.h create mode 100644 src/interface/scalers/scale3x.h create mode 100644 src/interface/scalers/superscale.asm create mode 100644 src/interface/vid_interface.cpp create mode 100644 src/interface/vid_softfx.cpp create mode 100644 src/interface/vid_softfx.h create mode 100644 src/interface/vid_support.cpp create mode 100644 src/interface/vid_support.h create mode 100644 src/interface/win32/aud_dsound3.cpp create mode 100644 src/interface/win32/aud_xaudio2.cpp create mode 100644 src/interface/win32/cd_isowav.cpp create mode 100644 src/interface/win32/cdsound.cpp create mode 100644 src/interface/win32/cdsound.h create mode 100644 src/interface/win32/ddraw_core.cpp create mode 100644 src/interface/win32/ddraw_core.h create mode 100644 src/interface/win32/dinput_core.cpp create mode 100644 src/interface/win32/dinput_core.h create mode 100644 src/interface/win32/directx9_core.cpp create mode 100644 src/interface/win32/directx9_core.h create mode 100644 src/interface/win32/dsound_core.cpp create mode 100644 src/interface/win32/dsound_core.h create mode 100644 src/interface/win32/inp_dinput.cpp create mode 100644 src/interface/win32/prf_performance_counter.cpp create mode 100644 src/interface/win32/resource/bicubic.fx create mode 100644 src/interface/win32/rgb_pattern.h create mode 100644 src/interface/win32/vid_d3d.cpp create mode 100644 src/interface/win32/vid_ddraw.cpp create mode 100644 src/interface/win32/vid_ddrawfx.cpp create mode 100644 src/interface/win32/vid_directx9.cpp create mode 100644 src/interface/win32/vid_directx_support.cpp create mode 100644 src/interface/win32/vid_directx_support.h create mode 100644 src/license.txt create mode 100644 whatsnew.html diff --git a/fba.chm b/fba.chm new file mode 100644 index 0000000000000000000000000000000000000000..9cd857bc61f7d164001c742e53e91d8b8792859a GIT binary patch literal 39874 zcmeFZb8uzfw=cS5JL%ZAZQHiZj&0kvJLotat7ALq*mgQe$2a}O@7y}?RNeQg-m7|l z^jtO9m~&{3^%-kpjtxl_Wib!{0ATRZfj&Cgu+<!zZ=Hi1mOM;RYClFF#ZpH`|b3j^=17{|2<2pC@cIHseE+k-^>qv;1BYf_x{m- zvwpYVYdSXct4G9q? zpwJbB{J*9uLLU+Q_DfH!tfC|-C$0<>79<^n{GqC>sjMO@3kZ-aAp4l9$SX(+D+7f- zAp|;nOjVU+KJM^J4^;6EWNS4t*xP*$zPl`o;Y-5dJ{`S8+&v8zx4lhaH<^1fcP)p#M0q!?mbAj z3i`iXb3=%;jtBpb)rTwnkJSy$O&$LVAb3eM znhNb-pSCVG&X!I#_J4Z}-nEaC{*TPj-d5ki(AnbePy*`RVqr1?V`qCu zkH6do^n!%*{Fm6p!NK0q`7iUo#UuRLj*#?bMuv127S=%d@`0p~^p>_CQT>%G#DB-O zmQKcWMz#(>!IxZD?qvV6om~m+?41eB>|N|kK1Ox~rcO>D*ngl%XK8E?6k0@Az=!ca zDgP}Fa46uz`fuWooLgJkng68_vc*)u2TgBj=j>?zcen?Pkz7#p)}|i+T>O=F6BiP_ zjlHp4G05bsZqk;enPzBfli~;rlTYv+=5nu{%`Z!DhCLgQA0%QTo0O9{p<^^B}h<(VI z02}~L01JQtK>I;OKD;u1j2J%-kq@5k_usV$008`>%V=o`|E^g4+y9pQJ^v_H06vN+ z0E&!S_>`CH@nCKv$mp)E9M3Jm)}e>b>~YK;o9vMl{$%3t*w^uM_ORk!)Q=)X0Y(2oh} z$0h$e|CjzY`A=~F*#9Aa5cq?@9|Zm&@CSiE2>e0d4+4J>_=CV71pXlK2Z28b{QnC9 zgnw!Qh=?G+s{^VE!~g(-nOou%iC42+XoiL20*k=KM#4`~wD5!SmJ4tpxn_@x%FX63 zU6rP(@%MM0cL0O18avTPodnW_{_NSuZE9}L?QX-fo<{QOp;H*?C66{s{=t_;9;EXE zjNn_ZVyPUi3Uz#bz3SUDH3EguK2=B#Y znc6t3IiXvwOOBf{f;=mJ&F`xk{&Y?XOwD8Yw{1 z41Eg(=IG%9ureE99=s!79xbNxOIUj)x(D0n@@rJ`9J}0#uXOYh{*zV-t>$0fHz5_%(*j!;rHOS>iYvK=vq3O9 zOT&~kT%~t5QG$(R3|OEO0zp{lDa8l$Mrk{tivVfX!52Fb(WB6X4VOhP>;1ftY?8`q`#zys^-vr>SQxu`M3 z)?iUK(U3#ZF%I;Lz^m>?iHOEIrcJhh*cOOk+*%TyRxcYkl2dTF0E7;9iK zmv2tA46}R9NAW1n7xv94og$L$@_Yi&3f(@noL1?TIwNeo=ty~nzb7x!qwYueo%LEt8 zulntgM$|nQ8ryIT=);o|q* z-eAUQ^<;IW3A;nST)@@;_H*GY(n3u7a1(L$Jd~{qn5caQ7YC*}&Zj|w$?RwITZ6)H z+%tGwu_(fE?{z|77C+r=UQN2-4BidSHBTRLZfCzwkt4iw-t~^MpQmyhShRjts9$g$ z$6mn-kf8}&B1#sj&tubR-hUT! zCO5_Drb_d^R+Q~jVDk-Y^01MXJ50K49n<+|Hgk@{n}8XlFGEHmvwI64unH0doW)`+T7EVeV&qp*?Wrk zLPDMFoFd@M>$csX195KYusD}j@F}95h~mbv1U6xKL~5)ctUItM`>b*2JjPIfJxndfe8IIr9!LqXAbV6yd#+Gn%0+7|>QU5WSy}8eFmN4lTj5H`j2c z9Lw`_`Pm4-5@-1E3k0AD{N3+KAcDb6o6*O@g%Jqn+Oc51U zVeOois*GfM0sCUH}#g>_+t8cC0g#y@ru*Q zJEh@a<7wTTKn`sS8c9GrUC|71OOl&mC{%K^ST27NqyhsKW#=OYznrW3W)W%eMLa}YIXsL4keY?cDuF9Dq(Ddrw;m?&49a|X8V}AOq^L|+ zeNrOGb-M|l`&kg+kg(FA010=c{5j&lM2*wJl7UZRNs1|nlB-wkXc-kgu#R~upwX1u zTn}S*PtP}$WYN9Ch>0d~l}yAKQn5`KMU?HB$%U~Zv1Gdr2`&8`apvb$GfCV|mnO5D zQm%kjL&6BQUFldpmA0m*`y~kok~p>{+lsz@2c9?AkIZj6`xED}w7_L-K7(f%L|-K3 zgK1}OUw%zFZv|UlJ`;iPrQ${m7}Cz{G!zcM%Eq#(n{4m2BxomD%yIW|Ot$b!FJz08 z1>A}%$wzv4S!U))amYdPu}S8zrzQ3bFAbLqjge8xy>$yJi}^ylx0-R5vHTLdC{qc8 z4wtEyuX83~%QdM<#Pf;)3DuV4f%8kDfyO*$xU^9iLG9RM>xxWt%7vn;J55ueN__6; z-V-WmCPo=^c1Fqbj`Vr7EdfBqO$)f~xCkiHJVGws4{5%!s=48My68XLuWN@nARNRD6rAj*Z1Lq4B%V;X% zlM>la&<9l5NPkwT3#rZ=-?v`rJ)RST*~s2f1QvyHLC1mg;*DNcYt6KS4C!B63f$3r z({A&Z87ADAg(*}csloYMB}K?vE1po#Um(THK{>ji(WH8;QrmJ=W&_e~%h}^aG@ral zM`1T)W-X6B3qrBxvQHI(n|m}U32`MFGx)DXoHDmQS&55c8!HRK&eM%BRV|GkR4Kls z5ljx?Y2d}&B&GW!Nmk+Cu(Vkwi!i45?eh)|CwyVsj%ET8<&Fvje{>ij+jC&P9`wc% zH)68#f%k~XfYoHFC`}I@USJWKFP+a|2~s#+lb91bKxpH6El4$3U0kwxlK;!dZv79XhOate%u|B{Sw`??R3^?%wGC&e^D>m96%O?IWS6Ms&OAmt$b;wQyr zb9mV0;_5$H)wtnVjY}R2?}p&)bj&eD_b|=Un5_IupM=~P*<{PWK-ncr0r-=%MR5x> z<2FIQc`D_2abHP^sr=hM=Vr*zgs?}F9fxWtzimF#WBUdL#ZP>1Y)qdEauWo$Ph^e4 z-~niU`&W%>`cl7ahraSoYFHWEP9)+N_+R;q!JmPlLdcSkW|$h%NP~NH zd~cLF82?0-4{y$ra1WBPe0gI%Ik@@5MS)5BxGd^R0<}Jj#83ky6i15Yb*1oip*(4R ztJzsnS;Je1ERd(qH}TLhD{KmuBv%Z<3CouxCv~DE=N!Mtd7Sg*L{oGVsDy5B@a~d# z^L<_lNaV4E9&%aLZ&FQ(bYC-rHV~OiJ7WH!%vtf4%#_7grYG+@0|vE1tT82tBVor6`#{5T zXu@^c=vjizWF{ySH#h+avAnGp1q+K==}3ylCiKEWnI9qH`TpH!neJt#`3zhlp(I$Y z#GxCAo^hFa?|Jlr8@i=?SFRA0f1QB(%U$J+Ux(R=NCSA0jz%morYMpKl4F%H{x@%4 zoJu48qQ!5>ZY)5y+Qi}-x8r7_`72Br4Ok3I(NyJK!4x(PQcGK@g>L4}r8dXw1`=#2 zuHEp&ZAa>tia6}jTWvH7{^fUHq zvzWOJ=H7)f78af>f*R?OI144rl%L{)w&))8zFk>%54`Eqy?wKc0G6Tf%{%8G`@B-P zI!>urED@hWv^sJEUKd@pFJdq(P=`5|+Dg7&R(WP$IYr8QYyDIxM{8E9v8YQY%kADg z>D~!RF&)b%8_%k{XH-;XQCYCjG!7i;HWz*c!goZ^yOalzKwRyKq0>^7l_r|05mA+D zHNzU}n73ZvY@*~rgZ|ZjQ^bOF%x_NZHfDovRlxmfeF=W&mTx&q!v{`ObkGuUDYE%E zF)hccOA6eC^}0{m@gi|@!i!3tBPnrk?v}EU>9de(MoPKd-rQ;#CYTyHQH4urM7GkpJxGDdst3kUDUNKHH3 z8XB}6i)XG1hDVX&w@O#=!$Ja`aKFXwJkMx+UkWS``K!{B{yCNDX(|J?TMs_RST8qQMG_XM8w$3O2hXhm3JR3 z9=6w7ME=UMq}>sAD3vvKGl*z2og?KRvg&9&q48=EVy6V;$R*Qv=)KzU0yYa^$8US{ zgvaf5sFxQJGEsz8#-wd*pW7Ref%R_9lUSAnB4FP#dX?Evlu$XC3%xr@TJlJ(&!nZy zQ`46j!nJ}rmxz3NRqa4BR7UZgFLICNN)&R;fK|6+awuzcu8l+qARZ;dQ8M>yiyPcE z$_Xf1M6Qa+Hml0(sglLFQT=MTZs=2uU1UO|-fbsz@&)R1a&K)u*L_jbV7HQ&i0(}W z#4fj8RK@AUkXOyjv9^wG(!Ki83Z$uC^E%Xqh(ex&)mTWQcZiJA|%gq6A&MEFHNr%Pq+@VEpSNM+N?NNqcy;g| zDMsc8iGj_!mKj*2b_=`O}U3B3$ON5&mw6TDJ2{<*Y~fOJ*2=h zAFuFx_X#L@Qti-k17W5cP4>@)z=xpyg1fjQje8Aad0Wb#hXyFZysB&SU4nV_kXPl= z4~f*YyY??K+Va`)qOk($1t)YHg$VgPl#DCXTsqc}4Di*rdDT>c=oS@F!e_Br=JP>@ z^4xYiQiOx4z}9pO^8D(O$Bct}5gHd0yyM{W2&7@5DX;+ zsSW^fZLrkRyOY(cNyi9r7<}WZV<&Bq|D&`b7(=__MQw+6RY`urC8n!1J~?XxfH3X5|}gQ(OU5jhLw zrj}H(Iy?5NLi*@!?KA{U%g2ParAT&RbO;_e+x}P;ZkRGon!>AGC|)g1M+%DBh9nD)o77y>6W_FA>2q4(HaPa!$&kbTrxj<@z=sz zS2eGTc0mAXleQ7dZje!Z`*%5LxM|963sySTAAIpzk9>m{SX?cyO~+E2ZB6r(9rh5^ z>Lk={SQJOaMJ-s}UMNySxD^XutX7WI(uFIBwX|8$QPfwNB+CgbZMY3amALsAg6X$Y zACj6*!M^@&~HfiOf-a<3|J$9m{(=>g54+W&^u-5~**2h3^zNYrbYg80N#Q)7rG+~4O1 z|4WR)&Ey=?{C@LN)B4|2ESIFz|LN*N0?4f)ad z>3FboRExw+7E9vcFNw zC4sguzJSLUIaE^U@%WPP6M|1VISDN#BIDqcQbW*{$w(4Nv+C$@IWkVF7O)O(y2=RZ zS}9O{ZPQVp~@ntyvA_`znX|tm7ZQ@>w}MD*@<|-9|iK*^>h&+l}_QVP-b+@&C<#L@ijgAH#J!N}Fh?rS}Y*MV|Qt2^83#HRyyhJnz~@x8Q#$ z8}ve`afuO%76uV(nogtVsmNYbF*_72>dN-kqyZ}oCppw0ibUebeAlv7DIXfF25xY{ z5z$;yzMah{osb8SbHk|QPv4o56=_7Nb+rws|dbXbNLUUf3ip=e0uQH8PJ?PcxAvJvie zD|j zmSyW4(Yyi%UIXmk_#_au={j~LL3QQFAH(2EqC3kvuOb;@+RFMaZPkiHMl~CcC?ox%+-~i+l%L zpVQh!3EMMZ6>B$vEqE^qu9E~SIK_|NA!PA8o>uzVH4?ianZRw>L;SN3?Vd%W#=b05 z@lI79HIaKs@a%t$Zd!*6h3K{e>3i4iHdg@_`Fxmnc0yTS+TYFWdQtIK>CI}GP z_fqs+m2VXaYj?qaGWbVNi=9DoB?0s(Be;PKYdC-|KWJkP>r?N_=sCZZd;uz z>=Rg1RREG?;mOBFrK5Wj_7(XWH{#mp}`9ul7YpH5VJ zOYVOB>T)6FunUXHGKvJ8_+b(892-E;VT2aJ&C8|@J+vh&Jm~UCdrBv=-+yLNC)ocf z*oI#n^|L6DIleS;=bLbT4^kkn(H4JlbUjX~lu0gC5iow1z1>7_Wo99FoCUaHc^NAP zjUZO1E1fr3`}a;41D)-?OMW0`esUusnC~G_6{ub&@}TUPv_`+qMaz6A)PRzW>=kxPMKWr^Al#mkbLL8O2}!dC_o-$bIJ3k> z{j5BIA9mRj*!%2LEMl%J&o;WhooYD08?RgPOyEK7M#?>v-MY1Eq@8%%FuhWO~nx6JVYF(6})_pl1Cfc$Q|I`B> z9yeuuKU+oU(1Aa{GifzrAy|Y`3tB*$JEIUR>4vo9nuNhV!8ZZ|?k1;Uu*%uI^#ttZ z&uD-=jQ}>W@j8gOOpXXTJPDC?$eg7~yO85LywY&JPUM@Wc=Ddltjt6^bicM?oC{H7 zdgZ(t;cNEpwp--RPAmFletA4o5;2C9ko`iqX<_X8u?>Of3PiZv37lP1ZabyQyyP> zPphVO*IXXMqSj)$N7?Yx=zolVD+}STS#N0*zgpwP)=R0h0Gb|o$5Qu4UIm1Hp%ejVJNv4nlX#oe}}sd4iL-tQWAS<0lhL1^POzVZthrvuX61wt+|f+X*D(z#bo z%B}mEo};QyTp#81&KQ01^Cqr^l6J)Xa3{TqauLLCaS$=6B{sDgNWS|!_9Y6h_lY%6 zyT+Yf8E!>S+ZdV~=bKr|=H9?s_1j{fb<7)~o&mOA!poHY{nc&TkGx0YUV2=oxaR}P zHa^-C&9!Auu5pKw^w0`vdIL0h=I5xO7O(CWO&bW=hufGNQGT-sDsZ8SvhvWtt~~0l z*1LFcHomKu>KgPK-EHo`ULQ^&68NV;SC<7O4`;!Jc&YklK~7K4tNaBE-b9J5tSE%h zQF!MNa(yw|yW0M|R2{`KO^mvG`ZhnK$4*7n3KH9NM)lp%!3fkUcc7Z{7H<4~?t7Ev zDrDm?`bZytLcsP_J4H)vQw$y6PS&owPgQ#jp@?C`!& zl5l>gD*F=U&^IUDLW;=rl1ojH|Jo5u4LlYN#i^i?m6m0>n0PX!U`X4Qz7NyavB;=# zGYC$_rX}};Cts=MsgtitowrW48nab-Dy9`zm+9p37&zc#c=8-&5;td!B_H$Zgh5|# zPiNk;&f(c6|J0)nQGJ@W>RpoloI?A#SiB$9C>1lT_x{U`x5XVxvu`hR`?}U}xzh&t zDfj31CR_CDOqdM3n(v#rtO>(l-081}xqNW?9J z{Sf;E_vtRSbbgd<6f}gtPWC}wEUiUa2FwUkat$FFvJc1XJJ0}C=MKcuL_6PjXp%0; z!BPN|2w%gUaSS8Q-B(9 z5_c0>pJ32HEcGt~Fj-jmSso|ar(2<_1)tWkUbfNqY<}KU-OYA{;MdJ5|YwmiEejz%B1VV7Hz zP*9wPx7|d-$eDFV=8~ zKyZ0)yrIP?f$zQ2d#<=(-CI~lA>4_emH9eGd4iPP8J+iP`*`>E$mda6xg`4|^>9A@ z66qF2G|h{Bk}(gTFE6Er_cVg(TK-n7nA?47pgR35!qT$v$)W6Z-id!x(QMM*CyTv1 zm^bYuLyUYfdHj@w0r7In8?J9++U5ssmfJwuo>7CE{po8XIKJAc;rd?%<_0Ic(!+jeKrSDMtcr7nLU_8pN!=3uJ zg=;~>_qs411e>ait+1=zPztq+g^oReebgdQJvX*S=-6(CPsv z7^M5Vox0g25POUGss$<%MgIvfRj3ZBn;$@Uw@6a^l^7Z18)kYe|&zi%SB0m!$ieq zH(yX;>?)nRs)+xNs9q)=;cudz9YpC(T-ADU9@^Td)g>--h~SPcKCv-krhzYpfjjx# z4HBP$wP^XFcJh0r*htfElEq43l1*SFB<{5T`ov^u5U#-FY?A%8#`rW=)OT{{@C^b3h@L#Bt9F0L6R`0))_{Fvpi*Ilx{fwsA~ zKuw4LW&ZUH#Vgn29#ae7n?_dO?}(j&EJ6uik*&55*|DeE2=A^~6k7f?8wtYN#n^yi8w|tC~2Eqo>pfOgyeY3q!LP*ES3 z2nnguF>(J0q3MYoA*wO5Ua&{Roh;Oh_QUYx6_EAF2OH@q*rlpxZxxBQm3kVNYa>1{ z&lrrO;(`OTDB?#W!@Bduk!?GFdBU!+9>yZGSM*(>#nttA^8JxpRC%1ASyr06CfBEj z;fpspz9NdpPoNCDfq3P*ElpPU-OX}=X%@Kk*=e_d^S_qx^g9_TDV<%~cA#8Y9px!9 z{71KlJ~x_Fwr@UB_Ix!oRJCE!$hBg{6VQd6ON^cA&jwZ+8JkAJy9&x-vpq+nIv%sT z%5JXe_K$FBrO`f!mf-v4m1EotNyRd*UPNR;v-=gP-P71HV`;uor8SmOu4nN}Yg5N38$>s8Q_$z6${X2Rc z2SSggL-(ITeOA=2xkU9r7m(Y7TDLYhLtq$tbv2_QJ&+rhN;wBc{^F-YPKrj)5x z4-ixEuk$+yYWdYNRsyFK@;CL*C(wxSaB*nsKpXMz7ejIWHmy z{V;s%l1RHNao{*3bK~cJ*&pux{q7aEr!F*}zY&|3Yc)fD%BAN@#d0B;9&+Ya@T0Fq zkA3axOLb%w4rUk$Th_T*=6%OSS0}C31Mh{mH)+z!^W!197ZQLgldPF22<2%!jkXnZ z!(DGTb?r>_6Y<`(oTI-!Rv z4R7uQwAeS9Jr5E*YPQY(nCXTk*AY~)d3nGGsKUt#Da!|soJjh+lVuhq1Z-7F-Z&@6 zgE-HpUGL^gP|vzfI@qUY!w>TGYQfR8%V$5ksKM;>KPR~%lwj7m^(%CdckfB_A_y)R z>}Ji_J=>8z1WyT0yO}&?8(s zqv0l-q7>@}E#7m^@+foT3VGg-v(k$}H>;`2v91MF;@c%k&quZ!oob=5s9r2~N(+jQ zMOR|5n_NBcd&_)R4>Ys-9PMc{NY2l^fW5K&>_ehFhmAW{iPDJ)TzCypXdF{1Rf_fr zT-v`T98IYCOYP5H$=O_QuaLtv*KIBGA@W0E9RAh?50M$Za#tELgS^+Z(Nz!SkhAL* zwHZ%;&T$%_W%M%p0|^gv^<;GI%@{8tF?ThDO`ny`jkQXgZnHR}0#}CXI&NP)B{(+s z0sgz&(zXZrI99m?JBrD$r8=C3UQgep_9xh!l)9%=Z%XQB(TRC4-(YOiK(Z?3-lbC( z8^FD#(2HM^CP8wBxT_7rKG_ADn~>REN!QiXe8mw#H1EL)=%}@SmBFK>-af~PxUZ0= z&)j-Jq5ff8@nS4(t8v>7D}2cUar*#q7eZN8_Fdr6e*SxM8S$DTb>K-PXCZZf+xThx zVOkG9)XU`t4_6Q)k0p{nBNNr}U0-kc7UI0w4B{25jtH&dF1vCu1jLazdTXAIeL7QB&qQ{@Mk{Q8 zWk^Ej%rOfjbz>`gkP)_q0OKk6N|wr$BHiLA?#-1U41mSxBFt~TH| zL$3;H3B6ahQqL=f%-x#JvsEdSx`Y}fiOEFZ7Cn2|{~=Ey4zk`Ao@`j0LqI#UBvYiu zwB~{<|J*o;^2)7`ouvQ1`mK}^xGT4He7T=Plc{ltzJ48IO7wgTIQ`vrI6y#HXcYg)ypyL7uBOmr!AYg)-eT zxwg3G_sii89+2-9$L#U-5w&r93GG!k>zPd_KudDr*RbvGN_G9{s}F7|9G?5+HeL-MB#2%SDeA+5m=EdSq|)u)FvLiMsZ@w7 zx)xlWR%WVj?N-D+8`y7kwPl%i_3^lF<%`ibHA>?B3VzDZW=B9EVyc?Y@m1khxb15- zgZtiS?pysjqBZ9PyEtKu#}&g73Mm^-Il#}$ylm%sKPi;8wXs})O?JYe)h4YaY?x7k z-_%SEN}Qnb598l&STO7!!hth=gRMrdMXTd*gtkqWy?3#Ll%eKX_>^|Yk*D9R&-NY- z_cWL6631CKCYV|GYYiOnAr&0JsN%r#@w;Py@6_dk@21&(o)542)7hDq%v4exISG`m zB(SO|WwwaDopAH|`pJ6p%Eq^%>gGl*w9WzvQF|DA0gjMjNT~SWL=hTA5mN0Rer|wt zOrkFZJ!u#LfSvDmGnERJ}ifT^g?hVkJ8@rsz_lo5=RtEy6XZ-+K!tlZ#u)6N}*WMvfxE zP=*)9RWo7{Y4RfL$nN{Mxm>XL;-p2ED`t@&E63@)J!60+OiQYgmCcjhQap*+L~6{% zx0guF78fWP=!nfnQP=>%mTjkH->7iHS_l+1@!88St3~|)2SRo0X zW|Gk0AX_#otH+bTmoVa$q8cz$az-z`8!E2~a>dMIZkQ}6jWYZE(7E}^;?Z^ufyK(& z86xiX-8y~2mv5?%3Bm_cf_LTl1j@f9W1Q1T1}6bqUSRy~?#K`bsu7%!xSNmVnHysy>ME(zM*_OhUXr zr%JF%@-wbflc;9>{;S*I=((N7brRa7TE1xH|PJ;bl@mo_HaS8!=#unU0JhEf*c zlpH&VP2UhTd96LhDPPn<7ts28F;PQ=9MWGDS0N|Vm0JnA^=-SR^fdH@3|RGpN4D5K zUWZ7a;`yDwDLlw2t#$ zqPTa|_6$kJak$Pyxo<`p-QRDx9!X2lhH`WXM~ok~PnB);C7sAR8h zVonU?N5XDOd~p2Wm-!`VB{1gQt0O!p)-d9gmb}C8ZrCK4Ps>^h<2KVo?YqLgqFg9N z%c#b2lyv96%Lfq$T}WU* z6j{NQwTC!6$aiUjX<4~7b6gtX&oP#*ebkS58|IF0XzM3p?}c3yWwZ zwVtNGKE&qx%8sNxv&mkfyhN-hVq>m>9CtO1L)*8RO@y&wcp+uMm7F-d`xH0sm;9I>@ zThFJGN!5 z`w69gmiRttADL074y}Jw??yDiuiWIf0jD?Rr%OvTpJ-oZZ>f)aC#|$+&%5R%m9L`i zz0_itnCln0CZ%v*s?;dh-nZ5D{-dp!FTdR>dh?Lj>sOzqPmS&@@5@b(TNKaKD^DgD zv2MQQ^F0uBTg_#baDV$a_gSKHjbeJ*<*KIg&!?&DM^O^GOkeY~fEu;qf?uzLVbJ|Q z1_I^ZuC4B8au{ouP#s^yi?t~$XNGC`1A|Y~^mD4MCvUxjd|D~?p1ZnU25+%AcdA~ez%#tjB7GKZsH;JB95=5Qs4ahzF2=5>M?HZ9k5|1{ zQ;Z3($-Q?OZ@$u=^R8~BMEF6r!hyNCUe*2D>P)S%j$ZS&1*a*g`J%OGc-{fj)4B1K zgD>-|)7H!2iyw#a*djIJ50ie zsofz#F`O1^~5m4xv83)={Ca&mEm+ksClAEiaAXvy)a!h}MKb>_2l`bko9%APYp zkaOl5uIqPF)e17%brDOsr1R{UmK1s2OZ?ABCiI`d{lf~C$$$Bl`X+i+=9?BKe(mK7 zc*vD+r%Rafmn2RIOUol`RKGlR&wOLOuDk+&unh)cl+D{C&CTMGZJqNw(xr+xrgPJy zV5Mf}CtRPWSIFW$>Mq)Y3n!lwI;OnvJXR@Uh`3R91gVD`p~%rh^vLuwlYV}o%kT&* zPDbuVcn+`z!?dM;@7^2Y*D^s<-g&(-9s5@QeK-qgu~6kH$CCCX)?OnlO<==8-`c|& z0z~S*nYEa|!li0}tuWt+r?1{2$KOw>{@wH1NQ&R-X=Z|bQ`j%->)?HeJoQN(-uhGv zlg8!q+n|;6TVlYj8CU%k0&d%<)Ei2^$_Qbg+~fsWH;mTrzFkZ}jF#ugzF1JLRTU@9 z%%jS81NuK2@SHYkI*+{{rcRt6u&y)u6U(QV-kwPZ5DZKS6Y`&*hVY?~Pag-n4z<>> zb*{cnP93B+L`2SaxQ!S_R<>O|S}u@{G9o-T`AQdst&%IrHMAl_RHC$hf5Q}Q`IZ<% zvVMZPW??j;s?qgq_TrXJQRqv`>S}!ZJV#@YX$OTYmnd3~mn%_-ZUy@>}K>raN z$AS=W)(E{l#xw_%6vw)9StWkJ-_N7r$ARA389(CtUMt=u>mMLKcX`AzO!b7QT`8}K zwnK;GeaL9b&B|#IvL$~Pxk*|-^6mr?=k0z_ZPU6dU2k+zU4w~a*hN0q($+4XJAmAI zXa1`UUCt8zXONdJHbeh;bg@o z8ja!WVj1y^7-$6f8u5yY!>h!`xB2->mzJY}uqwm>!T0tqgrMHo+cM5jKd7{|w9_6! zck~w=hM>)XW|d!8+&4k54B&TTu-fG??M$3T+chcZTgdx9x z?k%itlrtjti^fEojVChd^^#T{-FPno#8u{-unmsoGUGuV9T%QX(vEZFc3-JzhnTX5TT$whElof zU3f9e7Vm}du?xO8E@2fmW0t(fxL9B)XLqry+_C5Y)*cr~10UQn5I&-pb_CxDs z%EL%yD}qBsRzlvY(Efy7s4H@0~kc z54_KY5Sy-tgmB;uW!>PlxP!dG9Xi3f(`;Dh5?+FKVExK|u80Rj74P6OKL`ZJaR)_h z7UGqKCEyTQ3r;P|EeG)?!feuasA&Ey6Tj0sBzcT*5>>b&&pAfGuL5M8;cCj83Wu23BJ72!a*^4_z1poAtk1A>+u`4PIOZd9-`sRG0fT6X->)R2 zf&H^A{aeQ|yIKG-5$f|I+DLW4(geOty5jbwy}>^q+fsf3^I+B?V&{_g$;Y6UP#I3ABIhN?tpLf~cf z=I|cQ8^i-gE&}Mk;0o~cxCd=$ggyveZfz8Ff&_#i!0W4vfU4jI(;<+)T3(eo1lX7~ zfuk{k3F{x7#|iLlX<*I+i-bCuTs6=I<_eIw;NMYbkdC4nSF;~ze0P0)Cah@)%@8mD z_{g^W4Pi!E>1EcX!u9*pvC$+WFxE7UD-=G6~MmIgVr&Jy)0@ubpIN7$5OdqTXDn0MN8?*aX5JdW_DwfneI`MF?T8bUmvM z*V@T=J=hdvSv(xnsHj0^!efCK_bLh(aWa7c3}(DTQli1MDjmL0p9hrp&h4jt^gtzl z(ePquZvno9M;;>8>vB~#jl;$tQJm3wl0mCdTAXAZTYJ?i6-x~s%DvDltR>ZGXw9}3 z!PIk3)(9Nb@TQaKQ__)5#$nvl)Rvkf(^3RkyJ{ZY9WinNX*7wAt@|6Vk0Dpg3KvoP0mr=xZ{|JnpbT+LtIOs*FmT<;jC zNTG1HH?oDsn1sSh;0so9d{jIY*$=aeB#-<8vDVVi6(XJzL4vdNP$J8cHh>j|hksLv zhS!=Om6%@P$}5CD#l)&)ide8!i~$en&G+JSrUpzO;UW?CuQ+)yLybqL9dW2dVI45s zGmuz_`EQBGj?9dBuRdaZgS_CbHZ%Jv!p6$hnhCmJRM8rpOwudWY*6g zwI;g*Bm*1UN+OLEv%<+e(VA&`yorg5+P7 zPGXzFEci$3#^FKe904U`2aW-y@|wIe>*BH#pR(Y_o%y1?)QdZKh0nOLs>ol75@p|F!ZvY}+Ty8aSGBku; zgfLQKRz#?^wH#=qv^I=*4#?k-bOq2No`DDyixvOyA7Kjv=Xo(0gl{SJSl$ci)~^c2 z(SQJet9w0xB{%1xWyb*#nsAP-5!vx?5nLspn2f>(wGaS=UyktI?|5R|FAcMThy&!b z3N-C|V_j>rVdw2p%)DB27RrFU=P0Vsx#h>2g9xy9R=17Kq1?*ge*yYAP=y$wO}i&d z7*Ozzv7?RDYO6EV%C=mA5v>1vNL0q4h@DVZY3B0~>Bb5jsg&~xf z&7vX|QxNGS^X+6}r*NH)N{F)KfkUXSN~*SCvWY4?0s)`v&x4RoaQZ} zZq#uri>te>HFNWEn&aQ4IU8=RsHh7MsI` zp&&0!RJz)l2XGFL|G7q*c2p0Mt-(wW>6aoc?{>`o_4nT!T-;(JOn+UCJcS z6|GojZb zf@fk#iVmZJDkwK$9WSJY1rd>>l0QhBE0P`h^fh83r5iAR+w$APH-RzYw4c{qa!E9Y|9E+mln$AJ!M}iG^Hrp}tpqZu< z8~{0`ZiCK&%aWR}&yETM`!|pfJ1H>_T-^=#^|3Puyt&}3@u}sV*Xl;2{|6YE-q!_1 z_Ucn49 z79z9!fq=B$*k)BTHZ*~c5g1YLD5S}hjd&T=P_Fzavwr$Jm7)gi&Lj~#ul^XB6lVyR zG}F->6PmW4LtEX_H*w$Y2zxwc+`#H#!4spy_)o7G&iQug(U{!Dl--%cuzpyPw7@C8tVxEQIXTii3Pr|tk~OgY;P+!z2NiSt5ce40RQ&8wKzIPA0o7q0Vy2n# z6dfoVRMx-aeBr|8z3!Dzc#x8s3{;n9*ke`wCy|kQ!28`h(PPNT-&u!n16~47eChXO za)HAC{sFci26J)O(=)O_)!n}Z=a`?5q~L)g=}gvd`1g%zzN(`$iT<%-{F?hzU8+-BfZ&xoC zD7?|%1wcK<|4uQleGN^=Z*H%|+6NrLgNtg!2APuzf*FAbOHDIqYtts9kLK zxIT6DB>hFVRW;ANO3p9UMIJPBPV*G6Pgu4J!HS7}6d`?)w$p-zoh z*Q34+YQ1+<&`nZLFrmQJpM&^^kuE~y674K}Awn>tNaH`gH-8of zEI0bWOv_4?)@IftU|@)h`V=$K_gMY}=?8Yj`?gdqlZjGK59fqY*L7`GQ~~hP?eH+- zp%#@P*eYpNg*b87_?N^mPR#A{&%1MNnp}n3X0+)NhmG{nX}tsc_Sv{#rjA^giO8u; zvfa&%62I_eBsuJc04JQs?foqb@Q`lUPvpq_ZWYA$bMT-QL*u?A$W>IDX)KSV)km3? zm?2um9GKhn@wCHc^ebUa&C{9R&Oab?cEX}`8SvcR{eJ(6eJiHcz<4_}ia>)sYLA() zIj`HhCj+$_bDuuySR_MU@R?Z_9NGt@@d=YK{%xwQB1EZ@~uQ;dG1Kcb0FsE=OU~>C+STil7Y8 zgELReV_1LORl6q_;qjSW=wPnRI`@J9#vRWjMqwe+|8>>qgKU{tQ{;nHW-4J7Vrczt zc@kwvL)fp0@zldAEVTN5Yz6WM$6KY2@x*bLs!Rx?S5PmtMtZ2Hs83g$2mca_odyY9 zHyf|8TX3%rJ?Ykuka1;HSf`m`4nvSjaHg9&Wznx20p84Bv)LE!JJixDETGFq~o?&hL_P5S@E8>~3hLq^rwCl~!i5!)ltO#bp$~1w(u~glhUJ%E$8p^uTPstf+0gs0 zgFY@^-4{1z8SGX@%#w*m-zb)P` z{fD18kK237!CbHLXm#mbgSQI|t});7l0u^b5r|$vMa^vR*i%s*3ggX%PMd1M)e6CM zWMoQQY^Jhl@;|BEPI+`SCBYv4T1jX5=@uBs6F7Ju5D?ykBVj*K&77aUV8Y`UJjD|b z)1-@TKVM_3iiCu(ow5HxOOj9pPP9}Ur3?3IQfGw=_@4qS3Dc>4`6^~B58ftHQnnZ@ z@hd4VU_io;t!qWUBu1h58wGOv&`4+8S{liE_KAUG^(fm^A>-;yrLqxfEMqu&Wz{?r zqzBwVSkG|UnbTGV^Q0Q`l1o!mPtZ3CpfS=n7YBRHOl@P~V^} zbJ%t7H}l{dxZgr&Ac2W9cKrC6W*cMFDSL(Z8fBV3w2F+48K1f2-teafz_pE(E(jNR z-7qe3vWFzbse+B8GynrGjqYcJP|p%&Jgi1Y&tbMxb7^kx)z8iT8)VF!FO{|qSb9)i zeQBb$Bwu3BT%E&PD}K^uc&09z(^EM076Fwnp)9gdBZ0+6Lmp>rs?oHQy<{grIml0y zPagphTNJDjI&#y~+`z=v)BA^o=;-R|5N`7~O`p_#|J5 zWXybcci&XxHS=5KJ*+ zWJA>o&>8co1x7o|t^IrMmVOC<)!!0Va__?&mjb6YNYAd~JzIv33Sw2gbRThsKAyA^ z$`EI2wx*KqQq+cLy_AveGOmPMvf?W)-E3~oRX;Y-rYSFsnTvsejNYj!OcJ?=vioH+F?a24A0LW92#@jFmrRREgjSrST)61 zKZMq{=2uy^YKoubF;u@S#qy8QD`c8A%F#5m$5$V-L2x_|{sd;jXW?P+|C-gu8@;{# zpau}~#|Q{wYx-LH8oGom28jKm&OpcDY!^vL_Z#TB;(B_>)&)G=3TB|Y(#ab6kcla< zcRB2voF8`obtBs&=!JB^%a6S;FI$A`yhcd6yx424W zVHj&VfyN1q&jCy-|5S6q^J0Bl@PpK|MkRN`F4-5@Z9GOQGmG$822vdyi9@5wrXpu- zchG)k4W{Yco?`W1?%RRuchkw&i=RGNS3};Te)^UEBMR|cIH1{Eq;>8QV07)$v4)VI z?W|xiT7#9K32l9%IITS#{h;#+oOI_{8V||=CN<5-n|ZxUvM_HBt7JZz;_?a0DBgEP z<DXhn{0I0P-oAmsm+}36Cs1~-=uRZ5Z@v})rC@{Oc|3URrtkI^sAw9s% zxZbS24sU;jF&F9^y4U9UxV1Ufyo_V8T%?wJzX9n2? z`u#Ihj6bW0rDofA2OEEEnCDB{>2&ZwP%^1Ao{3CbwhLF{;cBXT2S)4%$pfNkx;JXc#P~s49+fx#cMyX#_HpgtJ5IVqmo- z7!MA1IQBLB%V4aejZV!q^N(8{G>~OXdiE?Z>I{z|O6rK%1uMF=iN_B7eUf_jjl&Y? zf~@CLC^X*EUl5p=rK7AiDq%BUyESOA*#u$>S|oMpYm1&XR`%>_4FO~$(jhRh#-KXD zvPK9tZ1Od%5nB9}cD6JI!LS8=`Bi5KCULz`7)C{|lI?TWm5lyCSLTcno#v zVtjk@mlt&k5A>v9+uABKC*i{bp|C$$PtZ{eaF}7I^&=HV=xIYP^_oON4JOR?z@cMl zmyL1rw5_2K1q4fD(HeDwO@-QWVnRqa2z@@ici;aNcVrH-z4W!o* zFa}qIK+3-()CmKot>)+WXqsI@k@$Ie!1;i)foB zwK~`di(2Oqt-m}gArM26yT&ck&B_^{ETb#7>Z6rNC}KLiJZ}Us=RkONqMPh0NY88;GN8Ffj$y!f z22kMHWQ(>5$<3=;D6b+l$kGy&92-aE4gel^X_`bfbF=Of_~7t1F2>1WgAWMt#2fmn z@z(kw$Z1Qs;u4SN6?G;deLSia-f!1TwDK{u5$__s79|->ukA$*yY*+DK@82n!A|{5 zZm{m@SEr2$qkLDV`99`ztZ5~8l@2R}p`|13P=OZHbQy@|(@Si9>3AEfjJgodNriI` zSgZ5c_BLYd3;e#unTl^=4|VD($H4l0x`}L{_YSxdpesp6axV4V;0@p!!gITE428V% zu#KmD_FN#!e>1NBIer&pwH;my+Cxy(%-?kTtSvzpjGYJh!OgPcoZyLIq=5)b2jHDC zMQS zV?{IK>;=z5W-NkI2fc}F{fdg7cnj2N)5BH_xwsfPQAB5HcgistVBz24@w{DKdf!Im zc~B@C*NToor}+FZ+}i4Sc$d80qjUaRsHuD{d=9W7<4g3D=GUM?85VUIz87OqIw^~% z16`deC%5cJd9Nom9TFIEv*BIewln1)4BwRkV9qU2t41xmb8BBlv?t7o{?)Q0 zIJv=&eQC-kJmYHeoa^j53%Lxu*w=PRsX97+3p0ikL&?_S%RroEA_Mu791S!f85`=( zX5-MfJ2DOEYjKXJ9l7A8+rarjgwz*WE`94ejy|4)z zx}g_HvC|(SW85t2O*pfC(1PV*-ychM*1_;~#2Dh^GTm=*op+qn(`DP6YIoLQzd!wK zGw^Yt@`8$tF5 zXj4*qd}|Iy12`C3HQGoYNN%pd({;$*#E#rMQYynw+HTaqHgis&iF4k70_saka)p7~ ztA`uOoE%fr!i4Vt>D28X&kx8nK8Wt2|%K+ORt8L?c6{ zoy{-28Xn6y2=so)#zGFyg@g;xk=u6huOj|^(_^NL??qh1SYETG!g0YHyu2LB0Ws$_ zXSeq1?yu-b1Askgcjh<9p&*33Y8O=#@%UST14{Z=DOoJ)qi$N*rew9YIe*r=F#?+Y^x3`y#j0^8G*vshI$Y#zDS=nUY z1^){gn1Z2>9yYFZ`r;;o6`=K7qCLsJk};7*Z!L;BO&NJaBEjyBF@`n3&Vxxkcs<8t zJWYR{$+yQ3bsYAJR;o=DmxZ0M*CanP{D)F%kh|R!ddcOSfkqF>vj$BV8aKB>O&q#x zUXdEV&)HS|lf`XJ>#kH!PVUjKL+2r)b!3ZPF{r7L+8ic5>W!5Di5at_pzu4fxBDR- zI+rI;KM7_ndy%~nJ>RA;bn&>labfJfXtMw{;YyhWVgB2u6z0#lEiRxIWE54am$3i_FDatYOAk`&hZjr`JJbuBF}QZO{`f3*$@uD{D*(;%nqU7%U`+ zAgM_X)8~pjIO62Bm_$wdI#q+Qm~y8vYBMP;o`}L)w$yv_vDsExwwbTCcYBRjtWIEn zccWe%|LT#xy4sdbfw8I|@o{xodbO#+0k-wLapGU`@r=MZmMLfVL|z(yEm=v)7`xeo z{)Xs1W9!%3lhr~;WV8Ti)HR5&w`+wJuUc!&<)Dkq{)>|;h(ES3O%gR=YnK4u<*2P% zgSJXt1<@9)gGx=vzTV?1R0A|!{|3fXkX7)E2&;L{%sc?Vt5Pv;zb82mw{e2QP=dz{UM@AP~s<{b^y)QlF`P%J*`>-ylN)@?yvocQJ;yQxF zW>qW7ytT>K*^ecDnydqFmR_@|T zdO0oMy(w;!OV0x1f+#tETk8BG42isxzy0K$^Vs9KX7TW*_#>9hR8ZVrGRlmh!TJ2mVvS$>+rEDGE&a0Xg>wzseecr#!`6M@ChUg!c>B5 zxQxX;@BaI{`AN{wx$<+{XrP4YmLME(D(8T{_izP&%E3|6{J;@A7w|o1zWt)PA)jgp?%dXddgwji%3(jfp-y#R1i)@Ae9{G%HZ!-$^_KxEw5EBT=c-sy} z4r2}lw}1O`LO6aK>MDMov3~||XO(i#yZvut9-V9B{ zfd>uVer?=)+-}A9A!Qo~OCIVMzoW)zB6|h#Ge)d@3qhEm^JpAu@jjtTj@LLl)wDR3b^<1nS>v z7VbcRiWm}3;~d`3R!L zJjLzF!N?Mn=5ZJb`ETlwymx5QS>cHkU4f8@0_r{DK0-W5;!o+hJ3d0@I^~TK6v=@ z6p0>q;L-eiST#bl&V^}0jM(XATZnUdp)^jl!#50I6h_W5FkgzWA`q_-cF!{ds%~F9FQ>adp95I@M8Q=`;|1;U6T98BK~tuMSTHh%Sc< zIkXrEcev$m;1onAA;-Rib|6wW6vDB>YyKzfKi~(v_MEqL=jVp^lEjaOMSo8u z4_jb^57h{FQD~_ab?fiDCpjKr2|wO?x*t5t5%*Q%wxDBes_xM;;t3CRJ0j%a^$rXo zynh9gp)&V8@(OYBJ9f#8Eqsu8W2=bahrQByfv}DgOUB~`xKL@U?BlDg3~>`kIpG+b zfLLI7X4Kml-)d>B`nvs%e%I0exC~p^v7Qhr7QpfjhfQPu2Ik9q%#u_SIoA?ej%^%& zmznTw{q1)w8hO@I@QMu0OX!B4(dEcA0qZN#h%q4!o?X1 zxmO(85cb@@Zq$`ZV1O`j^qIAkQVWW=w5z4^wLT&oi&psAlRun_vGMq!4?Hc7f)P_v z?TwN%0$giVAV!Q3b-iWj z)vS`>N-uftZ!$wHc#^8dc{w6TWY7ZvhO-f)->eA)*8BsgG?poUKQus?6?6Q;Ps1a) z5lCH}wgl`WHRE%OVvk~e-D6aFQS(mb5@;&|@#Lc4BH29F|0pBFpFsX3Vtd+Xp*}Zr z`RRkXys)5r~kLdZcedNF;>%^_Ho1q_EUbujKhc=rgWPU_>**z*n+t$Oz8NT z0|pWxCdv%_Z#IwsW+80+(n|oI)wfNrYRu6 zr0NyccvUiLWbc)4o~-E%IV*B!QL4T4JBGD*BHmtVua1jZo}vQ*tYiOi+_b)t#bz-u zj}R&!lkrK}fY-K|{g}F33R<79TGKw)_wp2%JJk1?({Y~ISW`|0F?7`k9Y`=Ah>YPl zfO63Mlg1zm&M6=je)43L8~W8IXApxR6ED*YM8KM^hZPC6WsPhE5Yd4A2!aCs%H$Bl zXNviA1_--{6*8<(qGaIAiwch(sC=DsGaN^3#DrP*mt8@+77USx%r8p>qaeKc8qs2z zXoLu#gM5n`1i%#e2heE~pw{CJ?ptft3WLD21{#0n&h?eINy7Ar;!*Ds1g=xr5mZ+&LWgg}R$oTAWwAujgds)Z%BE`yxtJ*+>4UWFor`U2g%I@w<> zf$mh#_2<`|c^0G7}%Ji^#%hHip3-DonLgsj@#-O&+ zewYE=czmV6@ur0|Kx+z@!0ctfE4ozhcp|FdDJMe~F9~ms$^e4X#n5Lf6DU057z}a| z^9b0+m_E8Y9{b^?!4l%KpeauWH#AU_KsMnN183pnnG6Wf@a_doz)Ooh1~$tpAL#p! zI6|O?T2t#8+7+sR-IGnce#LI+t#b;4&DakGk(jIH`8{?a#nVtzo8}B;PajIMKscz2 zKTLKuwN9x9*mzr#SPA7Ic~DXVQqVI-Nz~Ehg{w z3_`3is43dx+(2|`cp*CRMglpJUIt_dIU7|eCW+Q$Bgs!F? z&D-w_I;Q*b@yx(%$TA^QXH|p`Pyh03#50OP*5n*DW8O{(>{~4sNpe#qz2TT=&W-aR z*GQazZ5EE#ZGy}S!@l-Sgsp~?CtN*xCZ!XT=!NGX3ZqKysc-rIG^D?`M8bQ;Yvtk;Al0R_i@F1F-t?C z+f*771A}QR6FRB*UY4y_Dfm87K#{8{WXripusGCn!n-U5Y4JiVC@#Zs3*(VGU@iNE z0*m9i*K;eUb6Ql4rf);@Yfykz$-ID7hw>+M-5e>Cm3#bGy%3=bauG}bn&$Efwa_gS zPvOmOR1sGLDZBD>mxe|6uGFFm172iK99*H60ke;hj_IO)1|^xROp>kwJ3BBU%i}~5 zIj@d+nnf8e{zM#y&BTgtUh(9zsC=p8wFLLjA7OpWTjGq0;9lh zpm1thESXCVI<8#~EM3bGs2O&XSEY05=+ogg172ZH26IT#@94~**hmqtl5$=GaS)7H z+I^I+f^uo~M9#v#YsP*mOT%2k;&xfU)#=Mq3bdyCtOl$pw>!$m+#vP3l?@Oh^+Rdb zH}1&f#Wwr$Wz1-!%ig46BkIW{cU3MN)KY1C{iZ;x9{ZwoyH`Tc97RBVgvr#bGvshc!_|e=Xp+Fo(AwN)s*jVHy z5d-CtA(`!**ol|KS&B&eS+Z|qa+|+fnRgmqrIT9}yYZaKQnlpo-!I{6CJCO*-ajp$ z*96JV;#txXsq&{wu#Ek~#H-;>A;eKenOikpZ?+Bx6jv5@P_9&h&AX&tD#KFELVGZf zZbov0>N;$=I2CUU^^}O@DI%u@Ej2Tguhz<0T@&tDQ_V63_#~ybLNRZk&7i^afrej^ ziqF>$zlP^_xz0?crpgyN!*i~Lj0z$%J}D6~O~EF(>E}OJ8M0fc1BG`;X;)7_q5Q*q zdCpK%jIi^x=WaeH(x+@skn@fEa7x#jWU&H}Ltt$;r=O8zlN#lYDeqdNui!n2{>5^IKk4-<^}{C(-ke6O5j5MI&O2NCLI+|Z69>usjHc|2Z|pEs4cF)f0OWk z0wPT+bJ^06`Qlu%Mp^i^Na7%!IJkti!><6o#!^e>^*L?hxN^yAcNd{`DFnIFZyW+8 z4|5qWERx7F4M^8_vY3`|(3OsbB$oXP&YPOfL(Ht!V)!cbB%tf$KxTP`I<<_GG3U{5 za1w#w429VfP9QQaYv#9g{w&l&uz!Ml&6-n#5JoaSdv3SJj~#XjIxBOQDHK>43CJC;`;26thvOPjL$xqmGVk z749MO@HgmPm?Oz97=er?rWwa_?z)f>>p`SGm71x~noU&?BcvIyZzj|M+1qDxYs3SYB1Z1Mh^elZ5r>~@ z<>-p|Zf%yxIi{($$bn1a`zVut$cU)c_oregVP)t81zr)Jw0s7sYIa_Q?l8FA+ikU& z%WY-Yaiez$6zrS+7_O@8ToqUmx-iXxItr^!a2tR^IdL7`R}}fojFl{%%M=7o2NCZ< z1wxtm7C0Z&s>3Vkn+{ZpL4jl{iGf6MlmR7e@;8$YefV8Cx1NfuO$_oM@8P)!{s1)< z+`0VASP>AN)LTSI07Op;d zm|cQq*)4U1J+6N~008SP>d%?D zrrbM{blF&90BHd1v+%q$y=-hCtl7!+dCZZ~^l}d&cd7+7-@s`(NPOr6Q zkQZ|*W&k(;0t^QZ13hfEE50t`!XKiv6-^rIJz2kMwc0z{#g=#GXKEz`&PDBlbnMu_ zLEv~kyFmDc9We~a#?l~Q0Q^%{w!h0;4gct;yt0|=w6Z9FmN^8PL5^<@>v~wiy-=>0 zhlXNGopP&FV=r?mm^$RLnQ?&_#!u1TM`Fc*{f`Rn zA+-qC6c{XsH0b^#F!dJZF9mUNx3;>nvTBz&CEBC}&t|7dmnt_b%9H>7OB5umO+13v zcr#HB)aTlsx?(S}fAn(I?goy%ou$mZ2tlXZboUPS1V~thZ zXkB2VJOFT0(;78V6+GdBhTu|`=g6kd>VK+0VWOkQtu{2wR0H&H0`3{m3`fBasz4Qz z_mubC-_e*4tIn|HQkBC-6SKft4R=X8?cGN6NjdKo)w#F`IE<&44QtpgHIkcvddEd8 z8~_E?b-^}zN@HB{oJ$~Ug2U&FKK1GtCr(a&8MuNix=-QJnA}mmFYeIVeZ}<*rVNe# zPJ<@RXK>ng&9hOVoIb|+Ao#Yai!B@PrH-C|f;*?|ckJqp*|N*1^tbdHsW~nGfLY&p zUcECK^Hb5)aYA5AH_o43yl7KJm&SZx632=)D_8{83m6YWOb#W}bOk#V)j!k&*@MKJ z6h0iuAq^0n)B<~EvZd50NHlj;H*i)K_NG^~1T4LRf6J5bCWwvhY(kHo&B)2q*&W{} zK`(eI?;Yd!NY?i z@M$cweuT)}ZoX)x!yOBD4YdnCLKLqGXy|K?2Oau`Gg_E)n{j9V>OrrBXYj-CD)F`SbL=Aak|{e98W2ymtM9iu|cHk!tcqBW1A$i zng}NsjJ)P`(yXBJg~98>JMbyGD7pQFro^bfY#Cb#w;6g|Rcu9Y$%Qrk95eA|SFL60jl^+j2Y@j zA(I7dtaZYC3+7O=JC)ad+Z8A=J^};bZXCe7_cO=@pN`WBALtvsYgAh;=Na4i;Zm1g z3Yu^hZ)+#beD2+n^F52RJa8EU`fba7cfJu6V8?TR@Lf-+%@`Xv7U-#TURD+{&cI`t z-Q`LsVDu#2B#-Wkc>hRKIt4^za-YdY2Tu(PB|-enGYH|Q*!>09Ujw^&7~QvjY(r10 z$0RDhPyY*P06@87a6~%j$181bPn@Fko zgB6be_82{cjb=A?qB`_Dnz;Nt(QMntV`@h|_;3BlnE<_}B%VnL<@p$FbeTyz>cfAt z&ALfzkuYYB8Ax$88%}D`Au|^DQMMid^|be`TQWK_85|%ddb? zTEb=X@x_BqU{|fV$3bt6@GOTc39Ekq`WQRQ$m%ztKn0^q;Eoc0Qe03%1y)HZf54YSTQ;f~*g8oO-5Wkh8M-7jcmchTk*WGYxiQeepX&|m)VADqfg)ZLv6GWCF$tkc{pqYg!24T+oUh;g z&XWC|B&2)w+OxxA}}D7Ry?Y!^B0G zWvNKo6VZK49Bq#T^1}7+=f7zLkgOR9_DM8$YkeB)nbatA^;fH{7TxVmB)7YV9v-ns zzt8nP^CWM!+Ma#$4@Y;4)zuKSO0|ynm(r?l8<-h~%b75?SeMwnbdEe5 zXJ_*doe=68z_143>~~WS;|rCZDVCj_PT(~QQli13n961?v)84B#>KUi+BIgpCH8xX z*JfD|#`-I3$6Kr7NsAf!W?MEu!kk*dbq=jl(vn)zZ7H==%KAylhLAqAb(4&21+7-k zZN$n-$L!U<(|LHfW-xk9ePH>ibMa`o_TU`q`g=IcS$wyw z(}{X1ht+)}+CDRLX{&cUGGE(`o}%ZHT2$>`;9G-5{lq!nwU5@muaGTC+1)lYJOAgR zbrZt>6Q2}6g=$qP6Q~iltw2*+(&PGnN?w>sVxUn<+#6iH^G0yc3R1>UQ*Xr-IXUfo z#tYR1ax5X6Cks;0VmWRtQ!sgw)<*EWHP@5jtm%!@h01p@SiHaHvt z9B|JxFBBIWZ!r-tB}9u2d#j6{y`ylGF|HkxiO==N^V=>tT9S#x6D%gxqjnBjQI*I` zKsWU`w5S9bRJfKcWjjLCm9=EATr2*QBv=_)-`vlel;;?-u_2r0M%=tKtYM<>%)`w| zf8)o_j|s>2kaevm)Z z(YyF@R559I_3K5S_cKti5nY`uhIQlsZvGI~A*JdGO*2f!T9aJyCHe5Ez#y0yf3wD1-!q_n$l~X!T<*Y|Gz^x;C}$S^dkEJ literal 0 HcmV?d00001 diff --git a/makefile b/makefile new file mode 100644 index 00000000..d267b6e6 --- /dev/null +++ b/makefile @@ -0,0 +1,71 @@ +# Main Makefile for FB Alpha, execute an appropriate system-specific makefile + +export + +# +# Declare variables +# + +# Make a special build, pass the quoted text as comment (use FORCE_UPDATE declaration below to force recompilation of resources) +# SPECIALBUILD = "This text will appear in the property sheet of the .exe file" + + + +# +# Flags. Uncomment any of these declarations to enable their function. +# + +# Inluclude Unicode support +UNICODE = 1 + +# Build A68K ASM 68000 core +BUILD_A68K = 1 + +# Include x86 Assembly routines +BUILD_X86_ASM = 1 + +# Build for x64 targets (MinGW64 and MSVC only, this will undefine BUILD_A68K and BUILD_X86_ASM) +#BUILD_X64_EXE = 1 + +# Include symbols and other debug information in the executable +#SYMBOL = 1 + +# Include features for debugging drivers +#DEBUG = 1 + +# Include rom set verifying features (comment this for release builds) +#ROM_VERIFY = 1 + +# Force recompilation of files that need it (i.e. use __TIME__, __DATE__, SPECIALBUILD). +FORCE_UPDATE = 1 + +# Use the __fastcall calling convention when interfacing with A68K/Musashi/Doze +FASTCALL = 1 + +# Compress executable with upx (the DEBUG option ignores this) +# COMPRESS = 1 + +# Perl is available +PERL = 1 + + +# +# execute an appropriate system-specific makefile +# + +mingw345: FORCE + @$(MAKE) -s -f makefile.mingw GCC345=1 + +mingw452: FORCE + @$(MAKE) -s -f makefile.mingw GCC452=1 + +mingw461: FORCE + @$(MAKE) -s -f makefile.mingw GCC461=1 + +sdl: FORCE + @$(MAKE) -s -f makefile.sdl + +vc: FORCE + @$(MAKE) -s -f makefile.vc + +FORCE: \ No newline at end of file diff --git a/makefile.mingw b/makefile.mingw new file mode 100644 index 00000000..89a80f02 --- /dev/null +++ b/makefile.mingw @@ -0,0 +1,695 @@ +# Makefile for FBA, for use with GNU make & GCC (MinGW) +# +# The first pass makes sure all intermediary targets are present. The second pass updates +# any targets, if necessary. (Intermediary) targets which have their own unique rules +# are generated as required. + +unexport + +# +# Flags. Uncomment any of these declarations to enable their function. +# + +# Check for changes in header files +DEPEND = 1 + + + +# +# Declare variables +# + +# Specify the name of the executable file, without ".exe" +NAME = fba + +ifdef BUILD_X64_EXE +ifdef BUILD_A68K +undefine BUILD_A68K +endif +ifdef BUILD_X86_ASM +undefine BUILD_X86_ASM +endif +endif + +ifndef CPUTYPE + CPUTYPE = i686 +endif + +ifdef BUILD_X86_ASM + MMX = 1 +else + MMX = 0 +endif + +ifndef BUILD_X86_ASM + NAME := $(NAME)n +endif +ifdef BUILD_X64_EXE + NAME = fba64 +endif +ifdef DEBUG + NAME := $(NAME)d +endif +ifdef SYMBOL + NAME := $(NAME)s +endif +ifndef UNICODE + NAME := $(NAME)a +endif + +ifeq ($(CPUTYPE),i686) + ppro = ppro +else + NAME := $(NAME)$(CPUTYPE) +endif + + + +# +# Specify paths/files +# + +ifdef GCC345 +objdir = obj/GNU345_WIN32/$(NAME)/ +endif +ifdef GCC452 +objdir = obj/GNU452_WIN32/$(NAME)/ +endif +ifdef GCC461 +objdir = obj/GNU461_WIN32/$(NAME)/ +endif + +srcdir = src/ + +include makefile.rules + +ifdef GCC345 +incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I- -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2 +endif +ifdef GCC452 +incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2 +endif +ifdef GCC461 +incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2 +endif + +ifdef UNICODE +# lib = -lunicows +endif + +# lib += `sdl-config --libs` +lib += -luser32 -lgdi32 -lcomdlg32 -lcomctl32 -lshell32 -lwinmm -lshlwapi \ + -ladvapi32 -lsetupapi -lole32 -luuid + + +depobj += resource.o \ + +autdep = $(depobj:.o=.d) + +ifdef BUILD_A68K +a68k.o = $(objdir)cpu/a68k/a68k.o +endif + +app_gnuc.rc = $(srcdir)depend/generated/app_gnuc.rc +license.rtf = $(srcdir)depend/generated/license.rtf +driverlist.h = $(srcdir)depend/generated/driverlist.h +ctv.h = $(srcdir)depend/generated/ctv.h +toa_gp9001_func.h = $(srcdir)depend/generated/toa_gp9001_func.h +neo_sprite_func.h = $(srcdir)depend/generated/neo_sprite_func.h +cave_tile_func.h = $(srcdir)depend/generated/cave_tile_func.h +cave_sprite_func.h = $(srcdir)depend/generated/cave_sprite_func.h +psikyo_tile_func.h = $(srcdir)depend/generated/psikyo_tile_func.h +build_details.h = $(srcdir)depend/generated/build_details.h + +allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o \ + $(foreach file,$(autobj:.o=.c), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \ + $(foreach file,$(autobj:.o=.cpp), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .cpp,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \ + $(foreach file,$(autobj:.o=.asm), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .asm,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \ + $(foreach file,$(autobj:.o=.rc), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .rc,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) + +ifdef BUILD_A68K +allobj += $(a68k.o) +endif + +alldep = $(foreach file,$(autobj:.o=.c), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .c,.d,$(wildcard $(srcdir)$(dir)/$(file))))))) \ + $(foreach file,$(autobj:.o=.cpp), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .cpp,.d,$(wildcard $(srcdir)$(dir)/$(file))))))) \ + $(foreach file,$(autobj:.o=.rc), \ + $(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \ + $(firstword $(subst .rc,.d,$(wildcard $(srcdir)$(dir)/$(file))))))) + +# +# +# Specify compiler/linker/assembler +# +# + +CC = gcc +CXX = g++ +LD = $(CXX) +AS = nasm + +LDFLAGS = -static + +ifdef GCC345 +CFLAGS = -pipe \ + -std=gnu99 -march=$(CPUTYPE) -O1 \ + -mno-cygwin -mwindows \ + -fforce-mem -fforce-addr -finline-limit=1200 -fthread-jumps \ + -freduce-all-givs -fmove-all-movables -fexpensive-optimizations \ + -Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \ + $(DEF) $(incdir) # `sdl-config --cflags` + +CXXFLAGS = -pipe \ + -march=$(CPUTYPE) -O3 \ + -mno-cygwin -mwindows \ + -fforce-mem -fforce-addr -finline-limit=1200 -fthread-jumps \ + -freduce-all-givs -fmove-all-movables -fexpensive-optimizations \ + -fcheck-new \ + -Wall -W -pedantic -Wno-long-long \ + -Wunknown-pragmas -Wundef -Wconversion -Wno-missing-braces \ + -Wuninitialized -Wpointer-arith -Winline -Wno-multichar \ + $(DEF) $(incdir) # `sdl-config --cflags` +endif +ifdef GCC452 +CFLAGS = -pipe \ + -std=gnu99 -march=$(CPUTYPE) -O1 \ + -mno-cygwin -mwindows \ + -fforce-addr -finline-limit=1200 -fthread-jumps \ + -fexpensive-optimizations \ + -Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \ + -Wno-sequence-point \ + $(DEF) $(incdir) # `sdl-config --cflags` + +CXXFLAGS = -pipe \ + -march=$(CPUTYPE) -O1 \ + -mno-cygwin -mwindows \ + -fforce-addr -finline-limit=1200 -fthread-jumps \ + -fexpensive-optimizations -fcheck-new \ + -Wall -W -pedantic -Wshadow -Wno-long-long -Wno-write-strings \ + -Wunknown-pragmas -Wundef -Wno-conversion -Wno-missing-braces -Wno-multichar \ + -Wuninitialized -Wpointer-arith -Wno-inline -Wno-address -Wno-unused-value \ + -Wno-sequence-point \ + $(DEF) $(incdir) # `sdl-config --cflags` +endif +ifdef GCC461 +CFLAGS = -pipe \ + -std=gnu99 -O1 \ + -mwindows \ + -fforce-addr -finline-limit=1200 -fthread-jumps \ + -fexpensive-optimizations \ + -Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \ + -Wno-sequence-point \ + $(DEF) $(incdir) # `sdl-config --cflags` + +CXXFLAGS = -pipe \ + -O1 \ + -mwindows \ + -fforce-addr -finline-limit=1200 -fthread-jumps \ + -fexpensive-optimizations -fcheck-new \ + -Wall -W -pedantic -Wshadow -Wno-long-long -Wno-write-strings \ + -Wunknown-pragmas -Wundef -Wno-conversion -Wno-missing-braces -Wno-multichar \ + -Wuninitialized -Wpointer-arith -Wno-inline -Wno-address -Wno-unused-value \ + -Wno-unused-but-set-variable -Wno-sequence-point \ + $(DEF) $(incdir) # `sdl-config --cflags` + +ifdef BUILD_X64_EXE + CFLAGS += -m64 + CXXFLAGS += -m64 + LDFLAGS += -m64 +else + CFLAGS += -m32 + CXXFLAGS += -m32 + LDFLAGS += -m32 +endif +endif + +ASFLAGS = -O1 -f coff -w-orphan-labels + +# D3DUtils & D3DMath need these +# DEF = -Dsinf=\(float\)sin -Dcosf=\(float\)cos -Dasinf=\(float\)asin -Dacosf=\(float\)acos -Dsqrtf=\(float\)sqrt + + DEF := -DBUILD_WIN32 -DUSE_SPEEDHACKS -DFILENAME=$(NAME) -DMMX=$(MMX) + +ifdef UNICODE + DEF := $(DEF) -D_UNICODE +endif + +ifdef SPECIALBUILD + DEF := $(DEF) -DSPECIALBUILD=$(SPECIALBUILD) +endif + +ifdef FASTCALL + DEF := $(DEF) -DFASTCALL +endif + +ifdef DEBUG +ifdef GCC345 + CFLAGS += -mconsole +endif +ifdef GCC452 + CFLAGS += -mconsole +endif + DEF := $(DEF) -DFBA_DEBUG +endif + +ifdef ROM_VERIFY + DEF := $(DEF) -DROM_VERIFY +endif + +ifdef BUILD_A68K + DEF := $(DEF) -DBUILD_A68K +endif + +ifdef BUILD_X86_ASM + DEF := $(DEF) -DBUILD_X86_ASM +endif + +ifdef BUILD_X64_EXE + DEF := $(DEF) -DBUILD_X64_EXE +endif + +ifdef SYMBOL + + CFLAGS += -ggdb3 + ASFLAGS += -g + DEF := $(DEF) -D_DEBUG + +ifdef PROFILE + CFLAGS += -pg + CXXFLAGS += -pg +else + CFLAGS += -fomit-frame-pointer + CXXFLAGS += -fomit-frame-pointer +endif + +else + LDFLAGS += -s +endif + +ifdef BUILD_X86_ASM + CFLAGS += -mmmx + CXXFLAGS += -mmmx +endif + +# For zlib +DEF := $(DEF) -DNO_VIZ -D_LARGEFILE64_SOURCE=0 -D_FILE_OFFSET_BITS=32 + +# +# +# Specify paths +# +# + +vpath %.asm $(foreach dir,$(alldir),$(srcdir)$(dir)/ ) +vpath %.cpp $(foreach dir,$(alldir),$(srcdir)$(dir)/ ) +vpath %.c $(foreach dir,$(alldir),$(srcdir)$(dir)/ ) +vpath %.h $(foreach dir,$(alldir),$(srcdir)$(dir)/ ) +vpath %.rc $(foreach dir,$(alldir),$(srcdir)$(dir)/ ) + +vpath %.o $(foreach dir,$(alldir),$(objdir)$(dir)/ ) +vpath %.d $(foreach dir,$(alldir),$(objdir)$(dir)/ ) + +# +# +# Rules +# +# + +.PHONY: all init cleandep touch clean + +ifeq ($(MAKELEVEL),1) +ifdef DEPEND + +all: init $(autdep) $(autobj) +ifdef GCC345 + @$(MAKE) -f makefile.mingw -s GCC345=1 +endif +ifdef GCC452 + @$(MAKE) -f makefile.mingw -s GCC452=1 +endif +ifdef GCC461 + @$(MAKE) -f makefile.mingw -s GCC461=1 +endif + +else + +all: init $(autobj) +ifdef GCC345 + @$(MAKE) -f makefile.mingw -s GCC345=1 +endif +ifdef GCC452 + @$(MAKE) -f makefile.mingw -s GCC452=1 +endif +ifdef GCC461 + @$(MAKE) -f makefile.mingw -s GCC461=1 +endif + +endif +else + +all: $(NAME).exe + +endif + +# +# +# Rule for linking the executable +# +# + +ifeq ($(MAKELEVEL),2) + +$(NAME).exe: $(allobj) + @echo + @echo Linking executable... $(NAME).exe + @$(LD) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(lib) + +ifdef DEBUG + +# Don't compress when making a debug build + +else +ifdef COMPRESS + @upx --best $@ +endif +endif +endif + +ifeq ($(MAKELEVEL),1) +ifdef FORCE_UPDATE +$(build_details.h): FORCE +endif +endif + +# +# Generate the gamelist +# + +burn.o burn.d: driverlist.h + +$(driverlist.h): $(drvobj) $(srcdir)depend/scripts/gamelist.pl +ifdef PERL + @$(srcdir)depend/scripts/gamelist.pl -o $@ -l gamelist.txt \ + $(filter %.cpp,$(foreach file,$(drvobj:.o=.cpp),$(foreach dir,$(alldir), \ + $(firstword $(wildcard $(srcdir)$(dir)/$(file)))))) +else +ifeq ($(MAKELEVEL),2) + @echo + @echo Warning: Perl is not available on this system. + @echo $@ cannot be updated or created! + @echo +endif +endif + +# +# Verify if driverlist.h needs to be updated +# + +#ifeq ($(MAKELEVEL),1) +#ifdef FORCE_UPDATE +#$(driverlist.h): FORCE +#endif +#endif + + +# +# Fix the .rc file +# + +resource.o resource.d: $(app_gnuc.rc) string.rc version.rc version.h $(build_details.h) + +$(license.rtf): $(srcdir)license.txt $(srcdir)depend/scripts/license2rtf.pl + +ifdef PERL + @$(srcdir)depend/scripts/license2rtf.pl $< -o $(srcdir)depend/generated/$(@F:.rc=.rtf) +else +ifeq ($(MAKELEVEL),2) + @echo + @echo Warning: Perl is not available on this system. + @echo $@ cannot be updated or created! + @echo +endif +endif + +$(app_gnuc.rc): app.rc $(license.rc) $(license.rtf) $(srcdir)depend/scripts/fixrc.pl $(srcdir)burner/win32/resource/fba.ico $(srcdir)burner/win32/resource/about.bmp $(srcdir)burner/win32/resource/splash.bmp $(srcdir)burner/win32/resource/misc.bmp + +ifdef PERL + @$(srcdir)depend/scripts/fixrc.pl $< -o $@ +else +ifeq ($(MAKELEVEL),2) + @echo + @echo Warning: Perl is not available on this system. + @echo $@ cannot be updated or created! + @echo +endif +endif + +# +# Generate some info on the build details +# + +about.o about.d: $(build_details.h) + +$(build_details.h): $(srcdir)depend/scripts/build_details.cpp + @$(CXX) -mconsole $(CXXFLAGS) $(LDFLAGS) $< -o $(objdir)depend/generated/build_details.exe + @$(objdir)depend/generated/build_details.exe >$@ + +# +# Compile 68000 cores +# + +# A68K + +ifdef BUILD_A68K +$(a68k.o): fba_make68k.c + @echo Compiling A68K MC68000 core... + @$(CC) -mconsole $(CFLAGS) $(LDFLAGS) -DWIN32 -Wno-unused -Wno-conversion -Wno-missing-prototypes \ + -s $< -o $(subst $(srcdir),$(objdir),$($@ + +# +# Extra rules for generated header file toa_gp9001_func.h, needed by toa_gp9001.cpp +# + +toa_bcu2.d toa_bcu2.o toa_gp9001.d toa_gp9001.o: $(toa_gp9001_func.h) + +$(toa_gp9001_func.h): $(srcdir)depend/scripts/toa_gp9001_func.pl + @$(srcdir)depend/scripts/toa_gp9001_func.pl -o $(toa_gp9001_func.h) + +# +# Extra rules for generated header file neo_sprite_func.h, needed by neo_sprite.cpp +# + +neo_sprite.d neo_sprite.o: $(neo_sprite_func.h) + +$(neo_sprite_func.h): $(srcdir)depend/scripts/neo_sprite_func.pl + @$(srcdir)depend/scripts/neo_sprite_func.pl -o $(neo_sprite_func.h) + +# +# Extra rules for generated header file cave_tile_func.h, needed by cave_tile.cpp +# + +cave_tile.d cave_tile.o: $(cave_tile_func.h) + +$(cave_tile_func.h): $(srcdir)depend/scripts/cave_tile_func.pl + @$(srcdir)depend/scripts/cave_tile_func.pl -o $(cave_tile_func.h) + +# +# Extra rules for generated header file cave_sprite_func.h, needed by cave_sprite.cpp +# + +cave_sprite.d cave_sprite.o: $(cave_sprite_func.h) + +$(cave_sprite_func.h): $(srcdir)depend/scripts/cave_sprite_func.pl + @$(srcdir)depend/scripts/cave_sprite_func.pl -o $(cave_sprite_func.h) + +# +# Extra rules for generated header file psikyo_tile_func.h / psikyo_sprite_func.h, needed by psikyo_tile.cpp / psikyo_sprite.cpp +# + +psikyo_tile.d psikyo_tile.o psikyosprite.d psikyo_sprite.o: $(psikyo_tile_func.h) + +$(psikyo_tile_func.h): $(srcdir)depend/scripts/psikyo_tile_func.pl + $(srcdir)depend/scripts/psikyo_tile_func.pl -o $(psikyo_tile_func.h) + +ifeq ($(MAKELEVEL),2) +ifdef DEPEND + +include $(alldep) + +endif +endif + +# +# Generic rule for resource files +# + +%.o: %.rc + @echo Compiling resource file $($(subst $(srcdir),$(objdir),$($(subst $(srcdir),$(objdir),$($(subst $(srcdir),$(objdir),$($@ + +# +# Compile 68000 cores +# + +# A68K + +ifdef BUILD_A68K +$(a68k.o): fba_make68k.c + echo "Compiling A68K MC68000 core... " + $(CC) $(CFLAGS) -DWIN32 $< /Fo$(subst $(srcdir),$(objdir),$($@ + +# +# Extra rules for generated header file toa_gp9001_func.h, needed by toa_gp9001.cpp +# + +toa_bcu2.o toa_gp9001.o: $(toa_gp9001_func.h) + +$(toa_gp9001_func.h): $(srcdir)depend/scripts/toa_gp9001_func.pl + $(srcdir)depend/scripts/toa_gp9001_func.pl -o $(toa_gp9001_func.h) + +# +# Extra rules for generated header file neo_sprite_func.h, needed by neo_sprite.cpp +# + +neo_sprite.o: $(neo_sprite_func.h) + +$(neo_sprite_func.h): $(srcdir)depend/scripts/neo_sprite_func.pl + $(srcdir)depend/scripts/neo_sprite_func.pl -o $(neo_sprite_func.h) + +# +# Extra rules for generated header file cave_tile_func.h, needed by cave_tile.cpp +# + +cave_tile.o: $(cave_tile_func.h) + +$(cave_tile_func.h): $(srcdir)depend/scripts/cave_tile_func.pl + $(srcdir)depend/scripts/cave_tile_func.pl -o $(cave_tile_func.h) + +# +# Extra rules for generated header file cave_sprite_func.h, needed by cave_sprite.cpp +# + +cave_sprite.o: $(cave_sprite_func.h) + +$(cave_sprite_func.h): $(srcdir)depend/scripts/cave_sprite_func.pl + $(srcdir)depend/scripts/cave_sprite_func.pl -o $(cave_sprite_func.h) + +# +# Extra rules for generated header file psikyo_tile_func.h / psikyo_sprite_func.h, needed by psikyo_tile.cpp / psikyo_sprite.cpp +# + +psikyo_tile.o psikyo_sprite.o: $(psikyo_tile_func.h) + +$(psikyo_tile_func.h): $(srcdir)depend/scripts/psikyo_tile_func.pl + $(srcdir)depend/scripts/psikyo_tile_func.pl -o $(psikyo_tile_func.h) + +# +# Generic rule for resource files +# + +%.res: %.rc + @echo Compiling resource file... $(aFlwb$a$@zI{nd$lga7F9T6!9Yz6%?fwrzhakbwZ(gX)Fv1%9ziUK0Dd&^*?^ zS|C;4!RrcRrnhvde7vK<<}*I$x4d5Z|^XtC7B!zI4UZbb>Z$!LA9 zJ1rYrUw2FDmTBqlk{Q9OyS~luo_-_U<8Ifk`!7>>FuTW^-<$gLK=60re$PUOyL|rX zOe;6%n@1KOv78lk=dkhhj&*78oJ)9%!%7a!5thAwxV!Jp&6TzdqJdf52ZWcFF-R@C z!qzfP!}LF2N6=;dc$bwo+x6nltUP%;f0>kHZbwjX`GF~-Aql5AyZqm?PF;TgsH)n} zZ+8E$K744><9%pflGgdH{hxV%YnVOXtRolT&B!FefIA9+VFm;O5DF0?2u;|c1fm+G qNfn5pv51HukY?Ob1ktPjq=GOtBSlz%H!B-REi(}A0@96)ARYk1Wwgft literal 0 HcmV?d00001 diff --git a/src/burn/bitswap.h b/src/burn/bitswap.h new file mode 100644 index 00000000..30bd77f9 --- /dev/null +++ b/src/burn/bitswap.h @@ -0,0 +1,100 @@ +#define BITSWAP32(n, \ + bit31, bit30, bit29, bit28, bit27, bit26, bit25, bit24, \ + bit23, bit22, bit21, bit20, bit19, bit18, bit17, bit16, \ + bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \ + bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \ + (((((n) >> (bit31)) & 1) << 31) | \ + ((((n) >> (bit30)) & 1) << 30) | \ + ((((n) >> (bit29)) & 1) << 29) | \ + ((((n) >> (bit28)) & 1) << 28) | \ + ((((n) >> (bit27)) & 1) << 27) | \ + ((((n) >> (bit26)) & 1) << 26) | \ + ((((n) >> (bit25)) & 1) << 25) | \ + ((((n) >> (bit24)) & 1) << 24) | \ + ((((n) >> (bit23)) & 1) << 23) | \ + ((((n) >> (bit22)) & 1) << 22) | \ + ((((n) >> (bit21)) & 1) << 21) | \ + ((((n) >> (bit20)) & 1) << 20) | \ + ((((n) >> (bit19)) & 1) << 19) | \ + ((((n) >> (bit18)) & 1) << 18) | \ + ((((n) >> (bit17)) & 1) << 17) | \ + ((((n) >> (bit16)) & 1) << 16) | \ + ((((n) >> (bit15)) & 1) << 15) | \ + ((((n) >> (bit14)) & 1) << 14) | \ + ((((n) >> (bit13)) & 1) << 13) | \ + ((((n) >> (bit12)) & 1) << 12) | \ + ((((n) >> (bit11)) & 1) << 11) | \ + ((((n) >> (bit10)) & 1) << 10) | \ + ((((n) >> (bit09)) & 1) << 9) | \ + ((((n) >> (bit08)) & 1) << 8) | \ + ((((n) >> (bit07)) & 1) << 7) | \ + ((((n) >> (bit06)) & 1) << 6) | \ + ((((n) >> (bit05)) & 1) << 5) | \ + ((((n) >> (bit04)) & 1) << 4) | \ + ((((n) >> (bit03)) & 1) << 3) | \ + ((((n) >> (bit02)) & 1) << 2) | \ + ((((n) >> (bit01)) & 1) << 1) | \ + ((((n) >> (bit00)) & 1) << 0)) + +#define BITSWAP24(n, \ + bit23, bit22, bit21, bit20, bit19, bit18, bit17, bit16, \ + bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \ + bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \ + (((((n) >> (bit23)) & 1) << 23) | \ + ((((n) >> (bit22)) & 1) << 22) | \ + ((((n) >> (bit21)) & 1) << 21) | \ + ((((n) >> (bit20)) & 1) << 20) | \ + ((((n) >> (bit19)) & 1) << 19) | \ + ((((n) >> (bit18)) & 1) << 18) | \ + ((((n) >> (bit17)) & 1) << 17) | \ + ((((n) >> (bit16)) & 1) << 16) | \ + ((((n) >> (bit15)) & 1) << 15) | \ + ((((n) >> (bit14)) & 1) << 14) | \ + ((((n) >> (bit13)) & 1) << 13) | \ + ((((n) >> (bit12)) & 1) << 12) | \ + ((((n) >> (bit11)) & 1) << 11) | \ + ((((n) >> (bit10)) & 1) << 10) | \ + ((((n) >> (bit09)) & 1) << 9) | \ + ((((n) >> (bit08)) & 1) << 8) | \ + ((((n) >> (bit07)) & 1) << 7) | \ + ((((n) >> (bit06)) & 1) << 6) | \ + ((((n) >> (bit05)) & 1) << 5) | \ + ((((n) >> (bit04)) & 1) << 4) | \ + ((((n) >> (bit03)) & 1) << 3) | \ + ((((n) >> (bit02)) & 1) << 2) | \ + ((((n) >> (bit01)) & 1) << 1) | \ + ((((n) >> (bit00)) & 1) << 0)) + +#define BITSWAP16(n, \ + bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \ + bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \ + (((((n) >> (bit15)) & 1) << 15) | \ + ((((n) >> (bit14)) & 1) << 14) | \ + ((((n) >> (bit13)) & 1) << 13) | \ + ((((n) >> (bit12)) & 1) << 12) | \ + ((((n) >> (bit11)) & 1) << 11) | \ + ((((n) >> (bit10)) & 1) << 10) | \ + ((((n) >> (bit09)) & 1) << 9) | \ + ((((n) >> (bit08)) & 1) << 8) | \ + ((((n) >> (bit07)) & 1) << 7) | \ + ((((n) >> (bit06)) & 1) << 6) | \ + ((((n) >> (bit05)) & 1) << 5) | \ + ((((n) >> (bit04)) & 1) << 4) | \ + ((((n) >> (bit03)) & 1) << 3) | \ + ((((n) >> (bit02)) & 1) << 2) | \ + ((((n) >> (bit01)) & 1) << 1) | \ + ((((n) >> (bit00)) & 1) << 0)) + +#define BITSWAP08(n, \ + bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \ + (((((n) >> (bit07)) & 1) << 7) | \ + ((((n) >> (bit06)) & 1) << 6) | \ + ((((n) >> (bit05)) & 1) << 5) | \ + ((((n) >> (bit04)) & 1) << 4) | \ + ((((n) >> (bit03)) & 1) << 3) | \ + ((((n) >> (bit02)) & 1) << 2) | \ + ((((n) >> (bit01)) & 1) << 1) | \ + ((((n) >> (bit00)) & 1) << 0)) + +#define BYTE_XOR_LE(a) ((a)) +#define BIT(x,n) (((x)>>(n))&1) diff --git a/src/burn/burn.cpp b/src/burn/burn.cpp new file mode 100644 index 00000000..3a873c05 --- /dev/null +++ b/src/burn/burn.cpp @@ -0,0 +1,1091 @@ +// Burn - Drivers module +// Burn - Drivers module + +#include "version.h" +#include "burnint.h" +#include "burn_sound.h" +#include "driverlist.h" + +// filler function, used if the application is not printing debug messages +static INT32 __cdecl BurnbprintfFiller(INT32, TCHAR* , ...) { return 0; } +// pointer to burner printing function +INT32 (__cdecl *bprintf)(INT32 nStatus, TCHAR* szFormat, ...) = BurnbprintfFiller; + +INT32 nBurnVer = BURN_VERSION; // Version number of the library + +UINT32 nBurnDrvCount = 0; // Count of game drivers +UINT32 nBurnDrvActive = ~0U; // Which game driver is selected +UINT32 nBurnDrvSelect[8] = { ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U }; // Which games are selected (i.e. loaded but not necessarily active) + +bool bBurnUseMMX; +#if defined BUILD_A68K +bool bBurnUseASMCPUEmulation = true; +#else +bool bBurnUseASMCPUEmulation = false; +#endif + +#if defined (FBA_DEBUG) + clock_t starttime = 0; +#endif + +UINT32 nCurrentFrame; // Framecount for emulated game + +UINT32 nFramesEmulated; // Counters for FPS display +UINT32 nFramesRendered; // +bool bForce60Hz = false; +INT32 nBurnFPS = 6000; +INT32 nBurnCPUSpeedAdjust = 0x0100; // CPU speed adjustment (clock * nBurnCPUSpeedAdjust / 0x0100) + +// Burn Draw: +UINT8* pBurnDraw = NULL; // Pointer to correctly sized bitmap +INT32 nBurnPitch = 0; // Pitch between each line +INT32 nBurnBpp; // Bytes per pixel (2, 3, or 4) + +INT32 nBurnSoundRate = 0; // sample rate of sound or zero for no sound +INT32 nBurnSoundLen = 0; // length in samples per frame +INT16* pBurnSoundOut = NULL; // pointer to output buffer + +INT32 nInterpolation = 1; // Desired interpolation level for ADPCM/PCM sound +INT32 nFMInterpolation = 0; // Desired interpolation level for FM sound + +UINT8 nBurnLayer = 0xFF; // Can be used externally to select which layers to show +UINT8 nSpriteEnable = 0xFF; // Can be used externally to select which layers to show + +INT32 nMaxPlayers; + +bool bSaveCRoms = 0; + +UINT32 *pBurnDrvPalette; + +bool BurnCheckMMXSupport() +{ +#if defined BUILD_X86_ASM + UINT32 nSignatureEAX = 0, nSignatureEBX = 0, nSignatureECX = 0, nSignatureEDX = 0; + + CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); + + return (nSignatureEDX >> 23) & 1; // bit 23 of edx indicates MMX support +#else + return 0; +#endif +} + +extern "C" INT32 BurnLibInit() +{ + BurnLibExit(); + nBurnDrvCount = sizeof(pDriver) / sizeof(pDriver[0]); // count available drivers + + cmc_4p_Precalc(); + bBurnUseMMX = BurnCheckMMXSupport(); + + return 0; +} + +extern "C" INT32 BurnLibExit() +{ + nBurnDrvCount = 0; + + return 0; +} + +INT32 BurnGetZipName(char** pszName, UINT32 i) +{ + static char szFilename[MAX_PATH]; + char* pszGameName = NULL; + + if (pszName == NULL) { + return 1; + } + + if (i == 0) { + pszGameName = pDriver[nBurnDrvActive]->szShortName; + } else { + INT32 nOldBurnDrvSelect = nBurnDrvActive; + UINT32 j = pDriver[nBurnDrvActive]->szBoardROM ? 1 : 0; + + // Try BIOS/board ROMs first + if (i == 1 && j == 1) { // There is a BIOS/board ROM + pszGameName = pDriver[nBurnDrvActive]->szBoardROM; + } + + if (pszGameName == NULL) { + // Go through the list to seek out the parent + while (j < i) { + char* pszParent = pDriver[nBurnDrvActive]->szParent; + pszGameName = NULL; + + if (pszParent == NULL) { // No parent + break; + } + + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + if (strcmp(pszParent, pDriver[nBurnDrvActive]->szShortName) == 0) { // Found parent + pszGameName = pDriver[nBurnDrvActive]->szShortName; + break; + } + } + + j++; + } + } + + nBurnDrvActive = nOldBurnDrvSelect; + } + + if (pszGameName == NULL) { + *pszName = NULL; + return 1; + } + + strcpy(szFilename, pszGameName); + strcat(szFilename, ".zip"); + + *pszName = szFilename; + + return 0; +} + +// ---------------------------------------------------------------------------- +// Static functions which forward to each driver's data and functions + +INT32 BurnStateMAMEScan(INT32 nAction, INT32* pnMin); +void BurnStateExit(); +INT32 BurnStateInit(); + +// Get the text fields for the driver in TCHARs +extern "C" TCHAR* BurnDrvGetText(UINT32 i) +{ + char* pszStringA = NULL; + wchar_t* pszStringW = NULL; + static char* pszCurrentNameA; + static wchar_t* pszCurrentNameW; + +#if defined (_UNICODE) + + static wchar_t szShortNameW[32]; + static wchar_t szDateW[32]; + static wchar_t szFullNameW[256]; + static wchar_t szCommentW[256]; + static wchar_t szManufacturerW[256]; + static wchar_t szSystemW[256]; + static wchar_t szParentW[32]; + static wchar_t szBoardROMW[32]; + static wchar_t szSampleNameW[32]; + +#else + + static INT8 szShortNameA[32]; + static INT8 szDateA[32]; + static INT8 szFullNameA[256]; + static INT8 szCommentA[256]; + static INT8 szManufacturerA[256]; + static INT8 szSystemA[256]; + static INT8 szParentA[32]; + static INT8 szBoardROMA[32]; + static INT8 szSampleNameA[32]; + +#endif + + if (!(i & DRV_ASCIIONLY)) { + switch (i & 0xFF) { + case DRV_FULLNAME: + pszStringW = pDriver[nBurnDrvActive]->szFullNameW; + + if (i & DRV_NEXTNAME) { + if (pszCurrentNameW && pDriver[nBurnDrvActive]->szFullNameW) { + pszCurrentNameW += wcslen(pszCurrentNameW) + 1; + if (!pszCurrentNameW[0]) { + return NULL; + } + pszStringW = pszCurrentNameW; + } + } else { + +#if !defined (_UNICODE) + + // Ensure all of the Unicode titles are printable in the current locale + pszCurrentNameW = pDriver[nBurnDrvActive]->szFullNameW; + if (pszCurrentNameW && pszCurrentNameW[0]) { + INT32 nRet; + + do { + nRet = wcstombs(szFullNameA, pszCurrentNameW, 256); + pszCurrentNameW += wcslen(pszCurrentNameW) + 1; + } while (nRet >= 0 && pszCurrentNameW[0]); + + // If all titles can be printed, we can use the Unicode versions + if (nRet >= 0) { + pszStringW = pszCurrentNameW = pDriver[nBurnDrvActive]->szFullNameW; + } + } + +#else + + pszStringW = pszCurrentNameW = pDriver[nBurnDrvActive]->szFullNameW; + +#endif + + } + break; + case DRV_COMMENT: + pszStringW = pDriver[nBurnDrvActive]->szCommentW; + break; + case DRV_MANUFACTURER: + pszStringW = pDriver[nBurnDrvActive]->szManufacturerW; + break; + case DRV_SYSTEM: + pszStringW = pDriver[nBurnDrvActive]->szSystemW; + } + +#if defined (_UNICODE) + + if (pszStringW && pszStringW[0]) { + return pszStringW; + } + +#else + + switch (i & 0xFF) { + case DRV_NAME: + pszStringA = szShortNameA; + break; + case DRV_DATE: + pszStringA = szDateA; + break; + case DRV_FULLNAME: + pszStringA = szFullNameA; + break; + case DRV_COMMENT: + pszStringA = szCommentA; + break; + case DRV_MANUFACTURER: + pszStringA = szManufacturerA; + break; + case DRV_SYSTEM: + pszStringA = szSystemA; + break; + case DRV_PARENT: + pszStringA = szParentA; + break; + case DRV_BOARDROM: + pszStringA = szBoardROMA; + break; + case DRV_SAMPLENAME: + pszStringA = szSampleNameA; + break; + } + + if (pszStringW && pszStringA && pszStringW[0]) { + if (wcstombs(pszStringA, pszStringW, 256) != -1U) { + return pszStringA; + } + + } + + pszStringA = NULL; + +#endif + + } + + if (i & DRV_UNICODEONLY) { + return NULL; + } + + switch (i & 0xFF) { + case DRV_NAME: + pszStringA = pDriver[nBurnDrvActive]->szShortName; + break; + case DRV_DATE: + pszStringA = pDriver[nBurnDrvActive]->szDate; + break; + case DRV_FULLNAME: + pszStringA = pDriver[nBurnDrvActive]->szFullNameA; + + if (i & DRV_NEXTNAME) { + if (!pszCurrentNameW && pDriver[nBurnDrvActive]->szFullNameA) { + pszCurrentNameA += strlen(pszCurrentNameA) + 1; + if (!pszCurrentNameA[0]) { + return NULL; + } + pszStringA = pszCurrentNameA; + } + } else { + pszStringA = pszCurrentNameA = pDriver[nBurnDrvActive]->szFullNameA; + pszCurrentNameW = NULL; + } + break; + case DRV_COMMENT: + pszStringA = pDriver[nBurnDrvActive]->szCommentA; + break; + case DRV_MANUFACTURER: + pszStringA = pDriver[nBurnDrvActive]->szManufacturerA; + break; + case DRV_SYSTEM: + pszStringA = pDriver[nBurnDrvActive]->szSystemA; + break; + case DRV_PARENT: + pszStringA = pDriver[nBurnDrvActive]->szParent; + break; + case DRV_BOARDROM: + pszStringA = pDriver[nBurnDrvActive]->szBoardROM; + break; + case DRV_SAMPLENAME: + pszStringA = pDriver[nBurnDrvActive]->szSampleName; + } + +#if defined (_UNICODE) + + switch (i & 0xFF) { + case DRV_NAME: + pszStringW = szShortNameW; + break; + case DRV_DATE: + pszStringW = szDateW; + break; + case DRV_FULLNAME: + pszStringW = szFullNameW; + break; + case DRV_COMMENT: + pszStringW = szCommentW; + break; + case DRV_MANUFACTURER: + pszStringW = szManufacturerW; + break; + case DRV_SYSTEM: + pszStringW = szSystemW; + break; + case DRV_PARENT: + pszStringW = szParentW; + break; + case DRV_BOARDROM: + pszStringW = szBoardROMW; + break; + case DRV_SAMPLENAME: + pszStringW = szSampleNameW; + break; + } + + if (pszStringW && pszStringA && pszStringA[0]) { + if (mbstowcs(pszStringW, pszStringA, 256) != -1U) { + return pszStringW; + } + } + +#else + + if (pszStringA && pszStringA[0]) { + return pszStringA; + } + +#endif + + return NULL; +} + + +// Get the ASCII text fields for the driver in ASCII format; +extern "C" char* BurnDrvGetTextA(UINT32 i) +{ + switch (i) { + case DRV_NAME: + return pDriver[nBurnDrvActive]->szShortName; + case DRV_DATE: + return pDriver[nBurnDrvActive]->szDate; + case DRV_FULLNAME: + return pDriver[nBurnDrvActive]->szFullNameA; + case DRV_COMMENT: + return pDriver[nBurnDrvActive]->szCommentA; + case DRV_MANUFACTURER: + return pDriver[nBurnDrvActive]->szManufacturerA; + case DRV_SYSTEM: + return pDriver[nBurnDrvActive]->szSystemA; + case DRV_PARENT: + return pDriver[nBurnDrvActive]->szParent; + case DRV_BOARDROM: + return pDriver[nBurnDrvActive]->szBoardROM; + case DRV_SAMPLENAME: + return pDriver[nBurnDrvActive]->szSampleName; + default: + return NULL; + } +} + +// Get the zip names for the driver +extern "C" INT32 BurnDrvGetZipName(char** pszName, UINT32 i) +{ + if (pDriver[nBurnDrvActive]->GetZipName) { // Forward to drivers function + return pDriver[nBurnDrvActive]->GetZipName(pszName, i); + } + + return BurnGetZipName(pszName, i); // Forward to general function +} + +extern "C" INT32 BurnDrvGetRomInfo(struct BurnRomInfo* pri, UINT32 i) // Forward to drivers function +{ + return pDriver[nBurnDrvActive]->GetRomInfo(pri, i); +} + +extern "C" INT32 BurnDrvGetRomName(char** pszName, UINT32 i, INT32 nAka) // Forward to drivers function +{ + return pDriver[nBurnDrvActive]->GetRomName(pszName, i, nAka); +} + +extern "C" INT32 BurnDrvGetInputInfo(struct BurnInputInfo* pii, UINT32 i) // Forward to drivers function +{ + return pDriver[nBurnDrvActive]->GetInputInfo(pii, i); +} + +extern "C" INT32 BurnDrvGetDIPInfo(struct BurnDIPInfo* pdi, UINT32 i) +{ + if (pDriver[nBurnDrvActive]->GetDIPInfo) { // Forward to drivers function + return pDriver[nBurnDrvActive]->GetDIPInfo(pdi, i); + } + + return 1; // Fail automatically +} + +extern "C" INT32 BurnDrvGetSampleInfo(struct BurnSampleInfo* pri, UINT32 i) // Forward to drivers function +{ + return pDriver[nBurnDrvActive]->GetSampleInfo(pri, i); +} + +extern "C" INT32 BurnDrvGetSampleName(char** pszName, UINT32 i, INT32 nAka) // Forward to drivers function +{ + return pDriver[nBurnDrvActive]->GetSampleName(pszName, i, nAka); +} + +// Get the screen size +extern "C" INT32 BurnDrvGetVisibleSize(INT32* pnWidth, INT32* pnHeight) +{ + *pnWidth =pDriver[nBurnDrvActive]->nWidth; + *pnHeight=pDriver[nBurnDrvActive]->nHeight; + + return 0; +} + +extern "C" INT32 BurnDrvGetVisibleOffs(INT32* pnLeft, INT32* pnTop) +{ + *pnLeft = 0; + *pnTop = 0; + + return 0; +} + +extern "C" INT32 BurnDrvGetFullSize(INT32* pnWidth, INT32* pnHeight) +{ + if (pDriver[nBurnDrvActive]->Flags & BDF_ORIENTATION_VERTICAL) { + *pnWidth =pDriver[nBurnDrvActive]->nHeight; + *pnHeight=pDriver[nBurnDrvActive]->nWidth; + } else { + *pnWidth =pDriver[nBurnDrvActive]->nWidth; + *pnHeight=pDriver[nBurnDrvActive]->nHeight; + } + + return 0; +} + +// Get screen aspect ratio +extern "C" INT32 BurnDrvGetAspect(INT32* pnXAspect, INT32* pnYAspect) +{ + *pnXAspect = pDriver[nBurnDrvActive]->nXAspect; + *pnYAspect = pDriver[nBurnDrvActive]->nYAspect; + + return 0; +} + +extern "C" INT32 BurnDrvSetVisibleSize(INT32 pnWidth, INT32 pnHeight) +{ + if (pDriver[nBurnDrvActive]->Flags & BDF_ORIENTATION_VERTICAL) { + pDriver[nBurnDrvActive]->nHeight = pnWidth; + pDriver[nBurnDrvActive]->nWidth = pnHeight; + } else { + pDriver[nBurnDrvActive]->nWidth = pnWidth; + pDriver[nBurnDrvActive]->nHeight = pnHeight; + } + + return 0; +} + +extern "C" INT32 BurnDrvSetAspect(INT32 pnXAspect,INT32 pnYAspect) +{ + pDriver[nBurnDrvActive]->nXAspect = pnXAspect; + pDriver[nBurnDrvActive]->nYAspect = pnYAspect; + + return 0; +} + +// Get the hardware code +extern "C" INT32 BurnDrvGetHardwareCode() +{ + return pDriver[nBurnDrvActive]->Hardware; +} + +// Get flags, including BDF_GAME_WORKING flag +extern "C" INT32 BurnDrvGetFlags() +{ + return pDriver[nBurnDrvActive]->Flags; +} + +// Return BDF_WORKING flag +extern "C" bool BurnDrvIsWorking() +{ + return pDriver[nBurnDrvActive]->Flags & BDF_GAME_WORKING; +} + +// Return max. number of players +extern "C" INT32 BurnDrvGetMaxPlayers() +{ + return pDriver[nBurnDrvActive]->Players; +} + +// Return genre flags +extern "C" INT32 BurnDrvGetGenreFlags() +{ + return pDriver[nBurnDrvActive]->Genre; +} + +// Return family flags +extern "C" INT32 BurnDrvGetFamilyFlags() +{ + return pDriver[nBurnDrvActive]->Family; +} + +// Init game emulation (loading any needed roms) +extern "C" INT32 BurnDrvInit() +{ + INT32 nReturnValue; + + if (nBurnDrvActive >= nBurnDrvCount) { + return 1; + } + +#if defined (FBA_DEBUG) + { + TCHAR szText[1024] = _T(""); + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(DRV_FULLNAME); + INT32 nName = 1; + + while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + nName++; + } + + // Print the title + + bprintf(PRINT_IMPORTANT, _T("*** Starting emulation of %s - %s.\n"), BurnDrvGetText(DRV_NAME), BurnDrvGetText(DRV_FULLNAME)); + + // Then print the alternative titles + + if (nName > 1) { + bprintf(PRINT_IMPORTANT, _T(" Alternative %s "), (nName > 2) ? _T("titles are") : _T("title is")); + pszName = BurnDrvGetText(DRV_FULLNAME); + nName = 1; + while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1022 > szText) { + break; + } + if (nName > 1) { + bprintf(PRINT_IMPORTANT, _T(SEPERATOR_1)); + } + bprintf(PRINT_IMPORTANT, _T("%s"), pszName); + nName++; + } + bprintf(PRINT_IMPORTANT, _T(".\n")); + } + } +#endif + + BurnSetRefreshRate(60.0); + + CheatInit(); + HiscoreInit(); + BurnStateInit(); + BurnInitMemoryManager(); + + nReturnValue = pDriver[nBurnDrvActive]->Init(); // Forward to drivers function + + nMaxPlayers = pDriver[nBurnDrvActive]->Players; + +#if defined (FBA_DEBUG) + if (!nReturnValue) { + starttime = clock(); + nFramesEmulated = 0; + nFramesRendered = 0; + nCurrentFrame = 0; + } else { + starttime = 0; + } +#endif + + return nReturnValue; +} + +// Exit game emulation +extern "C" INT32 BurnDrvExit() +{ +#if defined (FBA_DEBUG) + if (starttime) { + clock_t endtime; + clock_t nElapsedSecs; + + endtime = clock(); + nElapsedSecs = (endtime - starttime); + bprintf(PRINT_IMPORTANT, _T(" ** Emulation ended (running for %.2f seconds).\n"), (float)nElapsedSecs / CLOCKS_PER_SEC); + bprintf(PRINT_IMPORTANT, _T(" %.2f%% of frames rendered (%d out of a total %d).\n"), (float)nFramesRendered / nFramesEmulated * 100, nFramesRendered, nFramesEmulated); + bprintf(PRINT_IMPORTANT, _T(" %.2f frames per second (average).\n"), (float)nFramesRendered / nFramesEmulated * nBurnFPS / 100); + bprintf(PRINT_NORMAL, _T("\n")); + } +#endif + + CheatExit(); + CheatSearchExit(); + HiscoreExit(); + BurnStateExit(); + + nBurnCPUSpeedAdjust = 0x0100; + + pBurnDrvPalette = NULL; + + INT32 nRet = pDriver[nBurnDrvActive]->Exit(); // Forward to drivers function + + BurnExitMemoryManager(); + + return nRet; +} + +INT32 (__cdecl* BurnExtCartridgeSetupCallback)(BurnCartrigeCommand nCommand) = NULL; + +INT32 BurnDrvCartridgeSetup(BurnCartrigeCommand nCommand) +{ + if (nBurnDrvActive >= nBurnDrvCount || BurnExtCartridgeSetupCallback == NULL) { + return 1; + } + + if (nCommand == CART_EXIT) { + return pDriver[nBurnDrvActive]->Exit(); + } + + if (nCommand != CART_INIT_END && nCommand != CART_INIT_START) { + return 1; + } + + BurnExtCartridgeSetupCallback(CART_INIT_END); + +#if defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T(" * Loading")); +#endif + + if (BurnExtCartridgeSetupCallback(CART_INIT_START)) { + return 1; + } + + if (nCommand == CART_INIT_START) { + return pDriver[nBurnDrvActive]->Init(); + } + + return 0; +} + +// Do one frame of game emulation +extern "C" INT32 BurnDrvFrame() +{ + CheatApply(); // Apply cheats (if any) + HiscoreApply(); + return pDriver[nBurnDrvActive]->Frame(); // Forward to drivers function +} + +// Force redraw of the screen +extern "C" INT32 BurnDrvRedraw() +{ + if (pDriver[nBurnDrvActive]->Redraw) { + return pDriver[nBurnDrvActive]->Redraw(); // Forward to drivers function + } + + return 1; // No funtion provide, so simply return +} + +// Refresh Palette +extern "C" INT32 BurnRecalcPal() +{ + if (nBurnDrvActive < nBurnDrvCount) { + UINT8* pr = pDriver[nBurnDrvActive]->pRecalcPal; + if (pr == NULL) return 1; + *pr = 1; // Signal for the driver to refresh it's palette + } + + return 0; +} + +extern "C" INT32 BurnDrvGetPaletteEntries() +{ + return pDriver[nBurnDrvActive]->nPaletteEntries; +} + +// ---------------------------------------------------------------------------- + +INT32 (__cdecl *BurnExtProgressRangeCallback)(double fProgressRange) = NULL; +INT32 (__cdecl *BurnExtProgressUpdateCallback)(double fProgress, const TCHAR* pszText, bool bAbs) = NULL; + +INT32 BurnSetProgressRange(double fProgressRange) +{ + if (BurnExtProgressRangeCallback) { + return BurnExtProgressRangeCallback(fProgressRange); + } + + return 1; +} + +INT32 BurnUpdateProgress(double fProgress, const TCHAR* pszText, bool bAbs) +{ + if (BurnExtProgressUpdateCallback) { + return BurnExtProgressUpdateCallback(fProgress, pszText, bAbs); + } + + return 1; +} + +// ---------------------------------------------------------------------------- + +INT32 BurnSetRefreshRate(double dFrameRate) +{ + if (!bForce60Hz) { + nBurnFPS = (INT32)(100.0 * dFrameRate); + } + + return 0; +} + +inline static INT32 BurnClearSize(INT32 w, INT32 h) +{ + UINT8 *pl; + INT32 y; + + w *= nBurnBpp; + + // clear the screen to zero + for (pl = pBurnDraw, y = 0; y < h; pl += nBurnPitch, y++) { + memset(pl, 0x00, w); + } + + return 0; +} + +INT32 BurnClearScreen() +{ + struct BurnDriver* pbd = pDriver[nBurnDrvActive]; + + if (pbd->Flags & BDF_ORIENTATION_VERTICAL) { + BurnClearSize(pbd->nHeight, pbd->nWidth); + } else { + BurnClearSize(pbd->nWidth, pbd->nHeight); + } + + return 0; +} + +// Byteswaps an area of memory +INT32 BurnByteswap(UINT8* pMem, INT32 nLen) +{ + nLen >>= 1; + for (INT32 i = 0; i < nLen; i++, pMem += 2) { + UINT8 t = pMem[0]; + pMem[0] = pMem[1]; + pMem[1] = t; + } + + return 0; +} + +// Application-defined rom loading function: +INT32 (__cdecl *BurnExtLoadRom)(UINT8 *Dest, INT32 *pnWrote, INT32 i) = NULL; + +// Application-defined colour conversion function +static UINT32 __cdecl BurnHighColFiller(INT32, INT32, INT32, INT32) { return (UINT32)(~0); } +UINT32 (__cdecl *BurnHighCol) (INT32 r, INT32 g, INT32 b, INT32 i) = BurnHighColFiller; + +// ---------------------------------------------------------------------------- +// Colour-depth independant image transfer + +UINT16* pTransDraw = NULL; + +static INT32 nTransWidth, nTransHeight; + +void BurnTransferClear() +{ + memset((void*)pTransDraw, 0, nTransWidth * nTransHeight * sizeof(UINT16)); +} + +INT32 BurnTransferCopy(UINT32* pPalette) +{ + UINT16* pSrc = pTransDraw; + UINT8* pDest = pBurnDraw; + + if (!nTransWidth || !nTransHeight || !pTransDraw) { + bprintf(PRINT_NORMAL, _T("BurnTransferCopy called without BurnTransferInit!\n")); + return 1; + } + + pBurnDrvPalette = pPalette; + + switch (nBurnBpp) { + case 2: { + for (INT32 y = 0; y < nTransHeight; y++, pSrc += nTransWidth, pDest += nBurnPitch) { + for (INT32 x = 0; x < nTransWidth; x ++) { + ((UINT16*)pDest)[x] = pPalette[pSrc[x]]; + } + } + break; + } + case 3: { + for (INT32 y = 0; y < nTransHeight; y++, pSrc += nTransWidth, pDest += nBurnPitch) { + for (INT32 x = 0; x < nTransWidth; x++) { + UINT32 c = pPalette[pSrc[x]]; + *(pDest + (x * 3) + 0) = c & 0xFF; + *(pDest + (x * 3) + 1) = (c >> 8) & 0xFF; + *(pDest + (x * 3) + 2) = c >> 16; + + } + } + break; + } + case 4: { + for (INT32 y = 0; y < nTransHeight; y++, pSrc += nTransWidth, pDest += nBurnPitch) { + for (INT32 x = 0; x < nTransWidth; x++) { + ((UINT32*)pDest)[x] = pPalette[pSrc[x]]; + } + } + break; + } + } + + return 0; +} + +void BurnTransferExit() +{ + if (pTransDraw) { + free(pTransDraw); + pTransDraw = NULL; + } +} + +INT32 BurnTransferInit() +{ + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nTransHeight, &nTransWidth); + } else { + BurnDrvGetVisibleSize(&nTransWidth, &nTransHeight); + } + + pTransDraw = (UINT16*)malloc(nTransWidth * nTransHeight * sizeof(UINT16)); + if (pTransDraw == NULL) { + return 1; + } + + BurnTransferClear(); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Savestate support + +// Application-defined callback for processing the area +static INT32 __cdecl DefAcb (struct BurnArea* /* pba */) { return 1; } +INT32 (__cdecl *BurnAcb) (struct BurnArea* pba) = DefAcb; + +// Scan driver data +INT32 BurnAreaScan(INT32 nAction, INT32* pnMin) +{ + INT32 nRet = 0; + + // Handle any MAME-style variables + if (nAction & ACB_DRIVER_DATA) { + nRet = BurnStateMAMEScan(nAction, pnMin); + } + + // Forward to the driver + if (pDriver[nBurnDrvActive]->AreaScan) { + nRet |= pDriver[nBurnDrvActive]->AreaScan(nAction, pnMin); + } + + return nRet; +} + +// ---------------------------------------------------------------------------- +// Wrappers for MAME-specific function calls + +#include "driver.h" + +// ---------------------------------------------------------------------------- +// Wrapper for MAME logerror calls + +#if defined (FBA_DEBUG) && defined (MAME_USE_LOGERROR) +void logerror(char* szFormat, ...) +{ + static char szLogMessage[1024]; + + va_list vaFormat; + va_start(vaFormat, szFormat); + + _vsnprintf(szLogMessage, 1024, szFormat, vaFormat); + + va_end(vaFormat); + + bprintf(PRINT_ERROR, _T("%hs"), szLogMessage); + + return; +} +#endif + +// ---------------------------------------------------------------------------- +// Wrapper for MAME state_save_register_* calls + +struct BurnStateEntry { BurnStateEntry* pNext; BurnStateEntry* pPrev; char szName[256]; void* pValue; UINT32 nSize; }; + +static BurnStateEntry* pStateEntryAnchor = NULL; +typedef void (*BurnPostloadFunction)(); +static BurnPostloadFunction BurnPostload[8]; + +static void BurnStateRegister(const char* module, INT32 instance, const char* name, void* val, UINT32 size) +{ + // Allocate new node + BurnStateEntry* pNewEntry = (BurnStateEntry*)malloc(sizeof(BurnStateEntry)); + if (pNewEntry == NULL) { + return; + } + + memset(pNewEntry, 0, sizeof(BurnStateEntry)); + + // Link the new node + pNewEntry->pNext = pStateEntryAnchor; + if (pStateEntryAnchor) { + pStateEntryAnchor->pPrev = pNewEntry; + } + pStateEntryAnchor = pNewEntry; + + sprintf(pNewEntry->szName, "%s:%s %i", module, name, instance); + + pNewEntry->pValue = val; + pNewEntry->nSize = size; +} + +void BurnStateExit() +{ + if (pStateEntryAnchor) { + BurnStateEntry* pCurrentEntry = pStateEntryAnchor; + BurnStateEntry* pNextEntry; + + do { + pNextEntry = pCurrentEntry->pNext; + if (pCurrentEntry) { + free(pCurrentEntry); + } + } while ((pCurrentEntry = pNextEntry) != 0); + } + + pStateEntryAnchor = NULL; + + for (INT32 i = 0; i < 8; i++) { + BurnPostload[i] = NULL; + } +} + +INT32 BurnStateInit() +{ + BurnStateExit(); + + return 0; +} + +INT32 BurnStateMAMEScan(INT32 nAction, INT32* pnMin) +{ + if (nAction & ACB_VOLATILE) { + + if (pnMin && *pnMin < 0x029418) { // Return minimum compatible version + *pnMin = 0x029418; + } + + if (pStateEntryAnchor) { + struct BurnArea ba; + BurnStateEntry* pCurrentEntry = pStateEntryAnchor; + + do { + ba.Data = pCurrentEntry->pValue; + ba.nLen = pCurrentEntry->nSize; + ba.nAddress = 0; + ba.szName = pCurrentEntry->szName; + BurnAcb(&ba); + + } while ((pCurrentEntry = pCurrentEntry->pNext) != 0); + } + + if (nAction & ACB_WRITE) { + for (INT32 i = 0; i < 8; i++) { + if (BurnPostload[i]) { + BurnPostload[i](); + } + } + } + } + + return 0; +} + +// wrapper functions + +extern "C" void state_save_register_func_postload(void (*pFunction)()) +{ + for (INT32 i = 0; i < 8; i++) { + if (BurnPostload[i] == NULL) { + BurnPostload[i] = pFunction; + break; + } + } +} + +extern "C" void state_save_register_INT8(const char* module, INT32 instance, const char* name, INT8* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(INT8)); +} + +extern "C" void state_save_register_UINT8(const char* module, INT32 instance, const char* name, UINT8* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(UINT8)); +} + +extern "C" void state_save_register_INT16(const char* module, INT32 instance, const char* name, INT16* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(INT16)); +} + +extern "C" void state_save_register_UINT16(const char* module, INT32 instance, const char* name, UINT16* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(UINT16)); +} + +extern "C" void state_save_register_INT32(const char* module, INT32 instance, const char* name, INT32* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(INT32)); +} + +extern "C" void state_save_register_UINT32(const char* module, INT32 instance, const char* name, UINT32* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(UINT32)); +} + +extern "C" void state_save_register_int(const char* module, INT32 instance, const char* name, INT32* val) +{ + BurnStateRegister(module, instance, name, (void*)val, sizeof(INT32)); +} + +extern "C" void state_save_register_float(const char* module, INT32 instance, const char* name, float* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(float)); +} + +extern "C" void state_save_register_double(const char* module, INT32 instance, const char* name, double* val, UINT32 size) +{ + BurnStateRegister(module, instance, name, (void*)val, size * sizeof(double)); +} diff --git a/src/burn/burn.h b/src/burn/burn.h new file mode 100644 index 00000000..8cdebf0d --- /dev/null +++ b/src/burn/burn.h @@ -0,0 +1,507 @@ +// FB Alpha - Emulator for MC68000/Z80 based arcade games +// Refer to the "license.txt" file for more info + +// Burner emulation library + +#ifdef __cplusplus + extern "C" { +#endif + +#if !defined (_WIN32) + #define __cdecl +#endif + +#include + +#ifndef MAX_PATH +#define MAX_PATH (260) +#endif + +extern TCHAR szAppHiscorePath[MAX_PATH]; +extern TCHAR szAppSamplesPath[MAX_PATH]; + +// Enable the MAME logerror() function in debug builds +// #define MAME_USE_LOGERROR + +// Give access to the CPUID function for various compilers +#if defined (__GNUC__) + #define CPUID(f,ra,rb,rc,rd) __asm__ __volatile__ ("cpuid" \ + : "=a" (ra), "=b" (rb), "=c" (rc), "=d" (rd) \ + : "a" (f) \ + ); +#elif defined (_MSC_VER) + #define CPUID(f,ra,rb,rc,rd) __asm { __asm mov eax, f \ + __asm cpuid \ + __asm mov ra, eax \ + __asm mov rb, ebx \ + __asm mov rc, ecx \ + __asm mov rd, edx } +#else + #define CPUID(f,ra,rb,rc,rd) +#endif + +#ifndef BUILD_X86_ASM + #undef CPUID + #define CPUID(f,ra,rb,rc,rd) +#endif + +#ifdef _UNICODE + #define SEPERATOR_1 " \u2022 " + #define SEPERATOR_2 " \u25E6 " +#else + #define SEPERATOR_1 " ~ " + #define SEPERATOR_2 " ~ " +#endif + +#ifdef _UNICODE + #define WRITE_UNICODE_BOM(file) { UINT16 BOM[] = { 0xFEFF }; fwrite(BOM, 2, 1, file); } +#else + #define WRITE_UNICODE_BOM(file) +#endif + +typedef unsigned char UINT8; +typedef signed char INT8; +typedef unsigned short UINT16; +typedef signed short INT16; +typedef unsigned int UINT32; +typedef signed int INT32; +#ifdef _MSC_VER +typedef signed __int64 INT64; +typedef unsigned __int64 UINT64; +#else +__extension__ typedef unsigned long long UINT64; +__extension__ typedef long long INT64; +#endif + +#include "state.h" +#include "cheat.h" +#include "hiscore.h" + +extern INT32 nBurnVer; // Version number of the library + +enum BurnCartrigeCommand { CART_INIT_START, CART_INIT_END, CART_EXIT }; + +// --------------------------------------------------------------------------- +// Callbacks + +// Application-defined rom loading function +extern INT32 (__cdecl *BurnExtLoadRom)(UINT8* Dest, INT32* pnWrote, INT32 i); + +// Application-defined progress indicator functions +extern INT32 (__cdecl *BurnExtProgressRangeCallback)(double dProgressRange); +extern INT32 (__cdecl *BurnExtProgressUpdateCallback)(double dProgress, const TCHAR* pszText, bool bAbs); + +// Application-defined catridge initialisation function +extern INT32 (__cdecl *BurnExtCartridgeSetupCallback)(BurnCartrigeCommand nCommand); + +// Application-defined colour conversion function +extern UINT32 (__cdecl *BurnHighCol) (INT32 r, INT32 g, INT32 b, INT32 i); + +// --------------------------------------------------------------------------- + +extern UINT32 nCurrentFrame; + +inline static INT32 GetCurrentFrame() { + return nCurrentFrame; +} + +inline static void SetCurrentFrame(const UINT32 n) { + nCurrentFrame = n; +} + +// --------------------------------------------------------------------------- +// Driver info structures + +// ROMs + +#define BRF_PRG (1 << 20) +#define BRF_GRA (1 << 21) +#define BRF_SND (1 << 22) + +#define BRF_ESS (1 << 24) +#define BRF_BIOS (1 << 25) +#define BRF_SELECT (1 << 26) +#define BRF_OPT (1 << 27) +#define BRF_NODUMP (1 << 28) + +struct BurnRomInfo { + char szName[100]; + UINT32 nLen; + UINT32 nCrc; + UINT32 nType; +}; + +struct BurnSampleInfo { + char szName[100]; + UINT32 nFlags; +}; + +// Inputs + +#define BIT_DIGITAL (1) + +#define BIT_GROUP_ANALOG (4) +#define BIT_ANALOG_REL (4) +#define BIT_ANALOG_ABS (5) + +#define BIT_GROUP_CONSTANT (8) +#define BIT_CONSTANT (8) +#define BIT_DIPSWITCH (9) + +struct BurnInputInfo { + char* szName; + UINT8 nType; + union { + UINT8* pVal; // Most inputs use a char* + UINT16* pShortVal; // All analog inputs use a short* + }; + char* szInfo; +}; + +// DIPs + +struct BurnDIPInfo { + INT32 nInput; + UINT8 nFlags; + UINT8 nMask; + UINT8 nSetting; + char* szText; +}; + +// --------------------------------------------------------------------------- + +extern bool bBurnUseMMX; +extern bool bBurnUseASMCPUEmulation; + +extern UINT32 nFramesEmulated; +extern UINT32 nFramesRendered; +extern clock_t starttime; // system time when emulation started and after roms loaded + +extern bool bForce60Hz; + +extern INT32 nBurnFPS; +extern INT32 nBurnCPUSpeedAdjust; + +extern UINT32 nBurnDrvCount; // Count of game drivers +extern UINT32 nBurnDrvActive; // Which game driver is selected +extern UINT32 nBurnDrvSelect[8]; // Which games are selected (i.e. loaded but not necessarily active) + +extern INT32 nMaxPlayers; + +extern UINT8 *pBurnDraw; // Pointer to correctly sized bitmap +extern INT32 nBurnPitch; // Pitch between each line +extern INT32 nBurnBpp; // Bytes per pixel (2, 3, or 4) + +extern UINT8 nBurnLayer; // Can be used externally to select which layers to show +extern UINT8 nSpriteEnable; // Can be used externally to select which Sprites to show + +extern INT32 nBurnSoundRate; // Samplerate of sound +extern INT32 nBurnSoundLen; // Length in samples per frame +extern INT16* pBurnSoundOut; // Pointer to output buffer + +extern INT32 nInterpolation; // Desired interpolation level for ADPCM/PCM sound +extern INT32 nFMInterpolation; // Desired interpolation level for FM sound + +extern UINT32 *pBurnDrvPalette; + +#define PRINT_NORMAL (0) +#define PRINT_UI (1) +#define PRINT_IMPORTANT (2) +#define PRINT_ERROR (3) + +extern INT32 (__cdecl *bprintf) (INT32 nStatus, TCHAR* szFormat, ...); + +INT32 BurnLibInit(); +INT32 BurnLibExit(); + +INT32 BurnDrvInit(); +INT32 BurnDrvExit(); + +INT32 BurnDrvCartridgeSetup(BurnCartrigeCommand nCommand); + +INT32 BurnDrvFrame(); +INT32 BurnDrvRedraw(); +INT32 BurnRecalcPal(); +INT32 BurnDrvGetPaletteEntries(); + +INT32 BurnSetProgressRange(double dProgressRange); +INT32 BurnUpdateProgress(double dProgressStep, const TCHAR* pszText, bool bAbs); + +// --------------------------------------------------------------------------- +// Retrieve driver information + +#define DRV_NAME (0) +#define DRV_DATE (1) +#define DRV_FULLNAME (2) +//#define DRV_MEDIUMNAME (3) +#define DRV_COMMENT (4) +#define DRV_MANUFACTURER (5) +#define DRV_SYSTEM (6) +#define DRV_PARENT (7) +#define DRV_BOARDROM (8) +#define DRV_SAMPLENAME (9) + +#define DRV_NEXTNAME (1 << 8) +#define DRV_ASCIIONLY (1 << 12) +#define DRV_UNICODEONLY (1 << 13) + +TCHAR* BurnDrvGetText(UINT32 i); +char* BurnDrvGetTextA(UINT32 i); + +INT32 BurnDrvGetZipName(char** pszName, UINT32 i); +INT32 BurnDrvGetRomInfo(struct BurnRomInfo *pri, UINT32 i); +INT32 BurnDrvGetRomName(char** pszName, UINT32 i, INT32 nAka); +INT32 BurnDrvGetInputInfo(struct BurnInputInfo* pii, UINT32 i); +INT32 BurnDrvGetDIPInfo(struct BurnDIPInfo* pdi, UINT32 i); +INT32 BurnDrvGetVisibleSize(INT32* pnWidth, INT32* pnHeight); +INT32 BurnDrvGetVisibleOffs(INT32* pnLeft, INT32* pnTop); +INT32 BurnDrvGetFullSize(INT32* pnWidth, INT32* pnHeight); +INT32 BurnDrvGetAspect(INT32* pnXAspect, INT32* pnYAspect); +INT32 BurnDrvGetHardwareCode(); +INT32 BurnDrvGetFlags(); +bool BurnDrvIsWorking(); +INT32 BurnDrvGetMaxPlayers(); +INT32 BurnDrvSetVisibleSize(INT32 pnWidth, INT32 pnHeight); +INT32 BurnDrvSetAspect(INT32 pnXAspect, INT32 pnYAspect); +INT32 BurnDrvGetGenreFlags(); +INT32 BurnDrvGetFamilyFlags(); +INT32 BurnDrvGetSampleInfo(struct BurnSampleInfo *pri, UINT32 i); +INT32 BurnDrvGetSampleName(char** pszName, UINT32 i, INT32 nAka); + +void Reinitialise(); + +extern bool bDoIpsPatch; +void IpsApplyPatches(UINT8* base, char* rom_name); + +// --------------------------------------------------------------------------- +// Flags used with the Burndriver structure + +// Flags for the flags member +#define BDF_GAME_WORKING (1 << 0) +#define BDF_ORIENTATION_FLIPPED (1 << 1) +#define BDF_ORIENTATION_VERTICAL (1 << 2) +#define BDF_BOARDROM (1 << 3) +#define BDF_CLONE (1 << 4) +#define BDF_BOOTLEG (1 << 5) +#define BDF_PROTOTYPE (1 << 6) +#define BDF_16BIT_ONLY (1 << 7) +#define BDF_HACK (1 << 8) +#define BDF_HOMEBREW (1 << 9) +#define BDF_DEMO (1 << 10) +#define BDF_HISCORE_SUPPORTED (1 << 11) + +// Flags for the hardware member +// Format: 0xDDEEFFFF, where EE: Manufacturer, DD: Hardware platform, FFFF: Flags (used by driver) + +#define HARDWARE_PUBLIC_MASK (0xFFFF0000) + +#define HARDWARE_PREFIX_CARTRIDGE (0x80000000) + +#define HARDWARE_PREFIX_MISC_PRE90S (0x00000000) +#define HARDWARE_PREFIX_CAPCOM (0x01000000) +#define HARDWARE_PREFIX_SEGA (0x02000000) +#define HARDWARE_PREFIX_KONAMI (0x03000000) +#define HARDWARE_PREFIX_TOAPLAN (0x04000000) +#define HARDWARE_PREFIX_SNK (0x05000000) +#define HARDWARE_PREFIX_CAVE (0x06000000) +#define HARDWARE_PREFIX_CPS2 (0x07000000) +#define HARDWARE_PREFIX_IGS_PGM (0x08000000) +#define HARDWARE_PREFIX_CPS3 (0x09000000) +#define HARDWARE_PREFIX_MISC_POST90S (0x0a000000) +#define HARDWARE_PREFIX_TAITO (0x0b000000) +#define HARDWARE_PREFIX_SEGA_MEGADRIVE (0x0c000000) +#define HARDWARE_PREFIX_PSIKYO (0x0d000000) +//#define HARDWARE_PREFIX_KANEKO16 (0x0e000000) // spare +#define HARDWARE_PREFIX_PACMAN (0x0f000000) +#define HARDWARE_PREFIX_GALAXIAN (0x10000000) +#define HARDWARE_PREFIX_IREM (0x20000000) + +#define HARDWARE_MISC_PRE90S (HARDWARE_PREFIX_MISC_PRE90S) +#define HARDWARE_MISC_POST90S (HARDWARE_PREFIX_MISC_POST90S) + +#define HARDWARE_CAPCOM_CPS1 (HARDWARE_PREFIX_CAPCOM | 0x00010000) +#define HARDWARE_CAPCOM_CPS1_QSOUND (HARDWARE_PREFIX_CAPCOM | 0x00020000) +#define HARDWARE_CAPCOM_CPS1_GENERIC (HARDWARE_PREFIX_CAPCOM | 0x00030000) +#define HARDWARE_CAPCOM_CPSCHANGER (HARDWARE_PREFIX_CAPCOM | 0x00040000) +#define HARDWARE_CAPCOM_CPS2 (HARDWARE_PREFIX_CPS2 | 0x00010000) +#define HARDWARE_CAPCOM_CPS2_SIMM (0x0002) + +#define HARDWARE_SEGA_SYSTEMX (HARDWARE_PREFIX_SEGA | 0x00010000) +#define HARDWARE_SEGA_SYSTEMY (HARDWARE_PREFIX_SEGA | 0x00020000) +#define HARDWARE_SEGA_SYSTEM16A (HARDWARE_PREFIX_SEGA | 0x00030000) +#define HARDWARE_SEGA_SYSTEM16B (HARDWARE_PREFIX_SEGA | 0x00040000) +#define HARDWARE_SEGA_SYSTEM16M (HARDWARE_PREFIX_SEGA | 0x00050000) +#define HARDWARE_SEGA_SYSTEM18 (HARDWARE_PREFIX_SEGA | 0x00060000) +#define HARDWARE_SEGA_HANGON (HARDWARE_PREFIX_SEGA | 0x00070000) +#define HARDWARE_SEGA_OUTRUN (HARDWARE_PREFIX_SEGA | 0x00080000) +#define HARDWARE_SEGA_SYSTEM1 (HARDWARE_PREFIX_SEGA | 0x00090000) + +#define HARDWARE_SEGA_FD1089A_ENC (0x0001) +#define HARDWARE_SEGA_FD1089B_ENC (0x0002) +#define HARDWARE_SEGA_5358 (0x0004) +#define HARDWARE_SEGA_MC8123_ENC (0x0008) +#define HARDWARE_SEGA_BAYROUTE_MEMMAP (0x0010) +#define HARDWARE_SEGA_ALT_MEMMAP (0x0020) +#define HARDWARE_SEGA_FD1094_ENC (0x0040) +#define HARDWARE_SEGA_SPRITE_LOAD32 (0x0080) +#define HARDWARE_SEGA_YM2203 (0x0100) +#define HARDWARE_SEGA_INVERT_TILES (0x0200) +#define HARDWARE_SEGA_5521 (0x0400) +#define HARDWARE_SEGA_5797 (0x0800) +#define HARDWARE_SEGA_YM2413 (0x1000) +#define HARDWARE_SEGA_FD1094_ENC_CPU2 (0x2000) +#define HARDWARE_SEGA_ISGSM (0x4000) +#define HARDWARE_SEGA_5704_PS2 (0x8000) + +#define HARDWARE_KONAMI_68K_Z80 (HARDWARE_PREFIX_KONAMI | 0x00010000) +#define HARDWARE_KONAMI_68K_ONLY (HARDWARE_PREFIX_KONAMI | 0x00020000) + +#define HARDWARE_TOAPLAN_RAIZING (HARDWARE_PREFIX_TOAPLAN | 0x00010000) +#define HARDWARE_TOAPLAN_68K_Zx80 (HARDWARE_PREFIX_TOAPLAN | 0x00020000) +#define HARDWARE_TOAPLAN_68K_ONLY (HARDWARE_PREFIX_TOAPLAN | 0x00030000) + +#define HARDWARE_SNK_NEOGEO (HARDWARE_PREFIX_SNK | 0x00010000) +#define HARDWARE_SNK_SWAPP (0x0001) // Swap code roms +#define HARDWARE_SNK_SWAPV (0x0002) // Swap sound roms +#define HARDWARE_SNK_SWAPC (0x0004) // Swap sprite roms +#define HARDWARE_SNK_CMC42 (0x0008) // CMC42 encryption chip +#define HARDWARE_SNK_CMC50 (0x0010) // CMC50 encryption chip +#define HARDWARE_SNK_ALTERNATE_TEXT (0x0020) // KOF2000 text layer banks +#define HARDWARE_SNK_SMA_PROTECTION (0x0040) // SMA protection +#define HARDWARE_SNK_KOF2K3 (0x0080) // KOF2K3 hardware +#define HARDWARE_SNK_ENCRYPTED_M1 (0x0100) // M1 encryption +#define HARDWARE_SNK_P32 (0x0200) // SWAP32 P ROMs +#define HARDWARE_SNK_SPRITE32 (0x0400) + +#define HARDWARE_SNK_CONTROLMASK (0xF000) +#define HARDWARE_SNK_JOYSTICK (0x0000) // Uses joysticks +#define HARDWARE_SNK_PADDLE (0x1000) // Uses joysticks or paddles +#define HARDWARE_SNK_TRACKBALL (0x2000) // Uses a trackball +#define HARDWARE_SNK_4_JOYSTICKS (0x3000) // Uses 4 joysticks +#define HARDWARE_SNK_MAHJONG (0x4000) // Uses a special mahjong controller +#define HARDWARE_SNK_GAMBLING (0x5000) // Uses gambling controls + +#define HARDWARE_SNK_MVS (HARDWARE_PREFIX_SNK | 0x00020000) +#define HARDWARE_SNK_NEOCD (HARDWARE_PREFIX_SNK | 0x00030000) +#define HARDWARE_SNK_DEDICATED_PCB (HARDWARE_PREFIX_SNK | 0x00040000) + +#define HARDWARE_CAVE_68K_ONLY (HARDWARE_PREFIX_CAVE) +#define HARDWARE_CAVE_68K_Z80 (HARDWARE_PREFIX_CAVE | 0x0001) +#define HARDWARE_CAVE_M6295 (0x0002) +#define HARDWARE_CAVE_YM2151 (0x0004) + +#define HARDWARE_IGS_PGM (HARDWARE_PREFIX_IGS_PGM) +#define HARDWARE_IGS_USE_ARM_CPU (0x0001) + +#define HARDWARE_CAPCOM_CPS3 (HARDWARE_PREFIX_CPS3) +#define HARDWARE_CAPCOM_CPS3_NO_CD (0x0001) + +#define HARDWARE_TAITO_TAITOZ (HARDWARE_PREFIX_TAITO | 0x00010000) +#define HARDWARE_TAITO_TAITOF2 (HARDWARE_PREFIX_TAITO | 0x00020000) +#define HARDWARE_TAITO_MISC (HARDWARE_PREFIX_TAITO | 0x00030000) +#define HARDWARE_TAITO_TAITOX (HARDWARE_PREFIX_TAITO | 0x00040000) +#define HARDWARE_TAITO_TAITOB (HARDWARE_PREFIX_TAITO | 0x00050000) + +#define HARDWARE_IREM_M62 (HARDWARE_PREFIX_IREM | 0x00010000) +#define HARDWARE_IREM_M63 (HARDWARE_PREFIX_IREM | 0x00020000) +#define HARDWARE_IREM_M72 (HARDWARE_PREFIX_IREM | 0x00030000) +#define HARDWARE_IREM_M90 (HARDWARE_PREFIX_IREM | 0x00040000) +#define HARDWARE_IREM_M92 (HARDWARE_PREFIX_IREM | 0x00050000) + +#define HARDWARE_SEGA_MEGADRIVE (HARDWARE_PREFIX_SEGA_MEGADRIVE) + +#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM (1) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM (2) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM (3) +#define HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART (4) +#define HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM (5) +#define HARDWARE_SEGA_MEGADRIVE_PCB_CODE_MASTERS (6) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SSF2 (7) +#define HARDWARE_SEGA_MEGADRIVE_PCB_GAME_KANDUME (8) +#define HARDWARE_SEGA_MEGADRIVE_PCB_BEGGAR (9) +#define HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM (10) +#define HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE (11) +#define HARDWARE_SEGA_MEGADRIVE_PCB_NFL_QB_96 (12) +#define HARDWARE_SEGA_MEGADRIVE_PCB_C_SLAM (13) +#define HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA (14) +#define HARDWARE_SEGA_MEGADRIVE_PCB_LIONK3 (15) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SDK99 (16) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SKINGKONG (17) +#define HARDWARE_SEGA_MEGADRIVE_PCB_REDCL_EN (18) +#define HARDWARE_SEGA_MEGADRIVE_PCB_RADICA (19) +#define HARDWARE_SEGA_MEGADRIVE_PCB_KOF98 (20) +#define HARDWARE_SEGA_MEGADRIVE_PCB_KOF99 (21) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SOULBLAD (22) +#define HARDWARE_SEGA_MEGADRIVE_PCB_MJLOVER (23) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SQUIRRELK (24) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SMOUSE (25) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SMB (26) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SMB2 (27) +#define HARDWARE_SEGA_MEGADRIVE_PCB_KAIJU (28) +#define HARDWARE_SEGA_MEGADRIVE_PCB_CHINFIGHT3 (29) +#define HARDWARE_SEGA_MEGADRIVE_PCB_LIONK2 (30) +#define HARDWARE_SEGA_MEGADRIVE_PCB_BUGSLIFE (31) +#define HARDWARE_SEGA_MEGADRIVE_PCB_ELFWOR (32) +#define HARDWARE_SEGA_MEGADRIVE_PCB_ROCKMANX3 (33) +#define HARDWARE_SEGA_MEGADRIVE_PCB_SBUBBOB (34) +#define HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC (35) +#define HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP19IN1 (36) +#define HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP15IN1 (37) +#define HARDWARE_SEGA_MEGADRIVE_PCB_12IN1 (38) +#define HARDWARE_SEGA_MEGADRIVE_PCB_TOPFIGHTER (39) +#define HARDWARE_SEGA_MEGADRIVE_PCB_POKEMON (40) +#define HARDWARE_SEGA_MEGADRIVE_PCB_MULAN (41) + +#define HARDWARE_SEGA_MEGADRIVE_SRAM_00400 (0x0100) +#define HARDWARE_SEGA_MEGADRIVE_SRAM_00800 (0x0200) +#define HARDWARE_SEGA_MEGADRIVE_SRAM_01000 (0x0400) +#define HARDWARE_SEGA_MEGADRIVE_SRAM_04000 (0x0800) +#define HARDWARE_SEGA_MEGADRIVE_SRAM_10000 (0x1000) +#define HARDWARE_SEGA_MEGADRIVE_FRAM_00400 (0x2000) + + +#define HARDWARE_PSIKYO (HARDWARE_PREFIX_PSIKYO) + +#define HARDWARE_KANEKO16 (HARDWARE_PREFIX_KANEKO16) + +#define HARDWARE_PACMAN (HARDWARE_PREFIX_PACMAN) + +#define HARDWARE_GALAXIAN (HARDWARE_PREFIX_GALAXIAN) + +// flags for the genre member +#define GBF_HORSHOOT (1 << 0) +#define GBF_VERSHOOT (1 << 1) +#define GBF_SCRFIGHT (1 << 2) +#define GBF_VSFIGHT (1 << 3) +#define GBF_BIOS (1 << 4) +#define GBF_BREAKOUT (1 << 5) +#define GBF_CASINO (1 << 6) +#define GBF_BALLPADDLE (1 << 7) +#define GBF_MAZE (1 << 8) +#define GBF_MINIGAMES (1 << 9) +#define GBF_PINBALL (1 << 10) +#define GBF_PLATFORM (1 << 11) +#define GBF_PUZZLE (1 << 12) +#define GBF_QUIZ (1 << 13) +#define GBF_SPORTSMISC (1 << 14) +#define GBF_SPORTSFOOTBALL (1 << 15) +#define GBF_MISC (1 << 16) +#define GBF_MAHJONG (1 << 17) +#define GBF_RACING (1 << 18) +#define GBF_SHOOT (1 << 19) + +// flags for the family member +#define FBF_MSLUG (1 << 0) +#define FBF_SF (1 << 1) +#define FBF_KOF (1 << 2) +#define FBF_DSTLK (1 << 3) +#define FBF_FATFURY (1 << 4) +#define FBF_SAMSHO (1 << 5) +#define FBF_19XX (1 << 6) +#define FBF_SONICWI (1 << 7) +#define FBF_PWRINST (1 << 8) + +#ifdef __cplusplus + } // End of extern "C" +#endif + diff --git a/src/burn/burn_gun.cpp b/src/burn/burn_gun.cpp new file mode 100644 index 00000000..75b23e03 --- /dev/null +++ b/src/burn/burn_gun.cpp @@ -0,0 +1,159 @@ +#include "burnint.h" +#include "burn_gun.h" + +// Generic Light Gun support for FBA +// written by Barry Harris (Treble Winner) based on the code in Kev's opwolf driver + +INT32 nBurnGunNumPlayers = 0; +static bool bBurnGunDrawTargets = true; + +static INT32 nBurnGunMaxX = 0; +static INT32 nBurnGunMaxY = 0; + +INT32 BurnGunX[MAX_GUNS]; +INT32 BurnGunY[MAX_GUNS]; + +#define P1Colour 0xfc, 0x12, 0xee +#define P2Colour 0x1c, 0xfc, 0x1c +#define P3Colour 0x15, 0x93, 0xfd +#define P4Colour 0xf7, 0xfa, 0x0e + +#define a 0, +#define b 1, + +UINT8 BurnGunTargetData[18][18] = { + { a a a a a a a a b a a a a a a a a a }, + { a a a a a a b b b b b a a a a a a a }, + { a a a a b b a a b a a b b a a a a a }, + { a a a b a a a a b a a a a b a a a a }, + { a a b a a a a a b a a a a a b a a a }, + { a a b a a a a b b b a a a a b a a a }, + { a b a a a a b b b b b a a a a b a a }, + { a b a a a b b a a a a b a a a b a a }, + { b b b b b b b a a a b b b b b b b a }, + { a b a a a b b a a a a b b a a b a a }, + { a b a a a a b a b a b b a a a b a a }, + { a a b a a a a b b b b a a a b a a a }, + { a a b a a a a a b b a a a a b a a a }, + { a a a b a a a a b a a a a b a a a a }, + { a a a a b b a a b a a b b a a a a a }, + { a a a a a a b b b b b a a a a a a a }, + { a a a a a a a a b a a a a a a a a a }, + { a a a a a a a a a a a a a a a a a a }, +}; +#undef b +#undef a + +UINT8 BurnGunReturnX(INT32 num) +{ + if (num > MAX_GUNS - 1) return 0xff; + + float temp = (float)((BurnGunX[num] >> 8) + 8) / nBurnGunMaxX * 0xff; + return (UINT8)temp; +} + +UINT8 BurnGunReturnY(INT32 num) +{ + if (num > MAX_GUNS - 1) return 0xff; + + float temp = (float)((BurnGunY[num] >> 8) + 8) / nBurnGunMaxY * 0xff; + return (UINT8)temp; +} + +void BurnGunMakeInputs(INT32 num, INT16 x, INT16 y) +{ + if (num > MAX_GUNS - 1) return; + + const INT32 MinX = -8 * 0x100; + const INT32 MinY = -8 * 0x100; + + BurnGunX[num] += x; + BurnGunY[num] += y; + + if (BurnGunX[num] < MinX) BurnGunX[num] = MinX; + if (BurnGunX[num] > MinX + nBurnGunMaxX * 0x100) BurnGunX[num] = MinX + nBurnGunMaxX * 0x100; + if (BurnGunY[num] < MinY) BurnGunY[num] = MinY; + if (BurnGunY[num] > MinY + nBurnGunMaxY * 0x100) BurnGunY[num] = MinY + nBurnGunMaxY * 0x100; +} + +void BurnGunInit(INT32 nNumPlayers, bool bDrawTargets) +{ + if (nNumPlayers > MAX_GUNS) nNumPlayers = MAX_GUNS; + nBurnGunNumPlayers = nNumPlayers; + bBurnGunDrawTargets = bDrawTargets; + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nBurnGunMaxY, &nBurnGunMaxX); + } else { + BurnDrvGetVisibleSize(&nBurnGunMaxX, &nBurnGunMaxY); + } + + for (INT32 i = 0; i < MAX_GUNS; i++) { + BurnGunX[i] = ((nBurnGunMaxX / 2) - 7) << 8; + BurnGunY[i] = ((nBurnGunMaxY / 2) - 8) << 8; + } +} + +void BurnGunExit() +{ + nBurnGunNumPlayers = 0; + bBurnGunDrawTargets = true; + + nBurnGunMaxX = 0; + nBurnGunMaxY = 0; + + for (INT32 i = 0; i < MAX_GUNS; i++) { + BurnGunX[i] = 0; + BurnGunY[i] = 0; + } +} + +void BurnGunScan() +{ + SCAN_VAR(BurnGunX); + SCAN_VAR(BurnGunY); +} + +void BurnGunDrawTarget(INT32 num, INT32 x, INT32 y) +{ + if (bBurnGunDrawTargets == false) return; + + if (num > MAX_GUNS - 1) return; + + UINT8* pTile = pBurnDraw + nBurnGunMaxX * nBurnBpp * (y - 1) + nBurnBpp * x; + + UINT32 nTargetCol = 0; + if (num == 0) nTargetCol = BurnHighCol(P1Colour, 0); + if (num == 1) nTargetCol = BurnHighCol(P2Colour, 0); + if (num == 2) nTargetCol = BurnHighCol(P3Colour, 0); + if (num == 3) nTargetCol = BurnHighCol(P4Colour, 0); + + for (INT32 y2 = 0; y2 < 17; y2++) { + + pTile += nBurnGunMaxX * nBurnBpp; + + if ((y + y2) < 0 || (y + y2) > nBurnGunMaxY - 1) { + continue; + } + + for (INT32 x2 = 0; x2 < 17; x2++) { + + if ((x + x2) < 0 || (x + x2) > nBurnGunMaxX - 1) { + continue; + } + + if (BurnGunTargetData[y2][x2]) { + if (nBurnBpp == 2) { + ((UINT16*)pTile)[x2] = (UINT16)nTargetCol; + } else { + ((UINT32*)pTile)[x2] = nTargetCol; + } + } + } + } +} + +#undef P1Colour +#undef P2Colour +#undef P3Colour +#undef P4Colour diff --git a/src/burn/burn_gun.h b/src/burn/burn_gun.h new file mode 100644 index 00000000..e2210112 --- /dev/null +++ b/src/burn/burn_gun.h @@ -0,0 +1,15 @@ +#define MAX_GUNS 4 + +extern INT32 nBurnGunNumPlayers; + +extern INT32 BurnGunX[MAX_GUNS]; +extern INT32 BurnGunY[MAX_GUNS]; + +UINT8 BurnGunReturnX(INT32 num); +UINT8 BurnGunReturnY(INT32 num); + +extern void BurnGunInit(INT32 nNumPlayers, bool bDrawTargets); +void BurnGunExit(); +void BurnGunScan(); +extern void BurnGunDrawTarget(INT32 num, INT32 x, INT32 y); +extern void BurnGunMakeInputs(INT32 num, INT16 x, INT16 y); diff --git a/src/burn/burn_led.cpp b/src/burn/burn_led.cpp new file mode 100644 index 00000000..ccbdd102 --- /dev/null +++ b/src/burn/burn_led.cpp @@ -0,0 +1,235 @@ +#include "burnint.h" +#include "burn_led.h" + +#define MAX_LED 8 + +static INT32 led_status[MAX_LED]; + +static INT32 led_count; +static INT32 led_alpha_level; +static INT32 led_alpha_level2; +static INT32 led_color; +static INT32 led_size; +static INT32 led_position0; +static INT32 led_position; +static INT32 led_xpos; +static INT32 led_ypos; +static INT32 led_xadv; +static INT32 led_yadv; + +static INT32 nScreenWidth, nScreenHeight; +static INT32 screen_flipped; +static INT32 flipscreen = -1; + +static inline UINT32 alpha_blend32(UINT32 d) +{ + return (((((led_color & 0xff00ff) * led_alpha_level) + ((d & 0xff00ff) * led_alpha_level2)) & 0xff00ff00) | + ((((led_color & 0x00ff00) * led_alpha_level) + ((d & 0x00ff00) * led_alpha_level2)) & 0x00ff0000)) >> 8; +} + +static void set_led_draw_position() +{ + led_position = led_position0; + + if (screen_flipped ^ flipscreen) { + switch (led_position & 3) { + case LED_POSITION_TOP_LEFT: led_position = LED_POSITION_BOTTOM_RIGHT; break; + case LED_POSITION_TOP_RIGHT: led_position = LED_POSITION_BOTTOM_LEFT; break; + case LED_POSITION_BOTTOM_LEFT: led_position = LED_POSITION_TOP_RIGHT; break; + case LED_POSITION_BOTTOM_RIGHT: led_position = LED_POSITION_TOP_LEFT; break; + } + } + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth); + + led_xadv = 0; + led_yadv = led_size + 1; + + switch (led_position & 3) + { + case LED_POSITION_TOP_LEFT: + led_xpos = (nScreenWidth - 1) - led_size; + led_ypos = 1; + break; + + case LED_POSITION_BOTTOM_RIGHT: + led_xpos = 1; + led_ypos = (nScreenHeight - 1) - (led_yadv * led_count); + break; + + case LED_POSITION_BOTTOM_LEFT: + led_xpos = 1; + led_ypos = 1; + break; + + case LED_POSITION_TOP_RIGHT: + default: + led_xpos = (nScreenWidth - 1) - led_size; + led_ypos = (nScreenHeight - 1) - (led_yadv * led_count); + break; + } + } else { + BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight); + + led_xadv = led_size + 1; + led_yadv = 0; + + switch (led_position & 3) + { + case LED_POSITION_BOTTOM_LEFT: + led_xpos = 1; + led_ypos = (nScreenHeight - 1) - led_size; +// led_ypos; + break; + + case LED_POSITION_TOP_RIGHT: + led_xpos = (nScreenWidth - 1) - (led_xadv * led_count); + led_ypos = 1; + break; + + case LED_POSITION_TOP_LEFT: + led_xpos = 1; + led_ypos = 1; + break; + + case LED_POSITION_BOTTOM_RIGHT: + default: + led_xpos = (nScreenWidth - 1) - (led_xadv * led_count); + led_ypos = (nScreenHeight - 1) - led_size; + break; + } + } +} + +void BurnLEDSetFlipscreen(INT32 flip) +{ + flip = flip ? 1 : 0; + + if (flipscreen != flip) { + flipscreen = flip; + set_led_draw_position(); + } +} + +void BurnLEDReset() +{ + memset (led_status, 0, MAX_LED * sizeof(INT32)); + + BurnLEDSetFlipscreen(0); +} + +void BurnLEDInit(INT32 num, INT32 position, INT32 size, INT32 color, INT32 transparency) +{ + if (num >= MAX_LED) num = MAX_LED - 1; + + led_count = num; + led_color = color; + led_size = size; + led_position0 = position; + + led_alpha_level = (255 * transparency) / 100; + led_alpha_level2 = 256 - led_alpha_level; + + screen_flipped = (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) ? 1 : 0; + + BurnLEDReset(); +} + +void BurnLEDSetStatus(INT32 led, UINT32 status) +{ + if (led >= led_count) return; + + if (screen_flipped ^ flipscreen) { + led = (led_count - 1) - led; + } + + led_status[led] = status ? 1 : 0; +} + +void BurnLEDExit() +{ + BurnLEDReset(); + + led_count = 0; + + led_alpha_level = 0; + led_alpha_level2 = 0; + led_color = 0; + led_size = 0; + led_position = 0; + led_position0 = 0; + + led_xpos = 0; + led_ypos = 0; + + screen_flipped = 0; + nScreenWidth = 0; + nScreenHeight = 0; + + flipscreen = -1; +} + +void BurnLEDRender() +{ + INT32 xpos = led_xpos; + INT32 ypos = led_ypos; + int color = BurnHighCol((led_color >> 16) & 0xff, (led_color >> 8) & 0xff, (led_color >> 0) & 0xff, 0); + + for (INT32 i = 0; i < led_count; i++) + { + if (xpos < 0 || xpos > (nScreenWidth - led_size)) break; + + if (led_status[i]) + { + for (INT32 y = 0; y < led_size; y++) + { + UINT8 *ptr = pBurnDraw + (((ypos + y) * nScreenWidth) + xpos) * nBurnBpp; + + for (INT32 x = 0; x < led_size; x++) + { + if (nBurnBpp >= 4) + { + *((UINT32*)ptr) = alpha_blend32(*((UINT32*)ptr)); + } + else if (nBurnBpp == 3) + { + UINT32 t = alpha_blend32((ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); + + ptr[2] = t >> 16; + ptr[1] = t >> 8; + ptr[0] = t >> 0; + } + else if (nBurnBpp == 2) // alpha blend not supported for 16-bit + { + *((UINT16*)ptr) = color; + } + + ptr += nBurnBpp; + } + } + } + + xpos += led_xadv; + ypos += led_yadv; + } +} + +INT32 BurnLEDScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_DRIVER_DATA) { + ba.Data = &led_status; + ba.nLen = led_count * sizeof(INT32); + ba.nAddress = 0; + ba.szName = "Led status"; + BurnAcb(&ba); + } + + return 0; +} diff --git a/src/burn/burn_led.h b/src/burn/burn_led.h new file mode 100644 index 00000000..166be06c --- /dev/null +++ b/src/burn/burn_led.h @@ -0,0 +1,30 @@ + +#define LED_COLOR_RED 0xff0000 +#define LED_COLOR_GREEN 0x00ff00 +#define LED_COLOR_BLUE 0x0000ff +#define LED_COLOR_WHITE 0xffffff +#define LED_COLOR_YELLOW 0xffff00 + +#define LED_SIZE_2x2 2 +#define LED_SIZE_3x3 3 +#define LED_SIZE_4x4 4 +#define LED_SIZE_5x5 5 +#define LED_SIZE_6x6 6 +#define LED_SIZE_7x7 7 +#define LED_SIZE_8x8 8 + +#define LED_POSITION_TOP_LEFT 0 +#define LED_POSITION_TOP_RIGHT 1 +#define LED_POSITION_BOTTOM_LEFT 2 +#define LED_POSITION_BOTTOM_RIGHT 3 + +// transparency is a percentage 0 - 100 +void BurnLEDInit(INT32 num, INT32 position, INT32 size, INT32 color, INT32 transparency); + +void BurnLEDReset(); +void BurnLEDSetStatus(INT32 led, UINT32 status); +void BurnLEDSetFlipscreen(INT32 flip); +void BurnLEDRender(); +void BurnLEDExit(); + +INT32 BurnLEDScan(INT32 nAction, INT32 *pnMin); diff --git a/src/burn/burn_memory.cpp b/src/burn/burn_memory.cpp new file mode 100644 index 00000000..391b751f --- /dev/null +++ b/src/burn/burn_memory.cpp @@ -0,0 +1,74 @@ +// FB Alpha memory management module + +// The purpose of this module is to offer replacement functions for standard C/C++ ones +// that allocate and free memory. This should help deal with the problem of memory +// leaks and non-null pointers on game exit. + +#include "burnint.h" + +#define MAX_MEM_PTR 0x400 // more than 1024 malloc calls should be insane... + +static UINT8 *memptr[MAX_MEM_PTR]; // pointer to allocated memory + +// this should be called early on... BurnDrvInit? + +void BurnInitMemoryManager() +{ + memset (memptr, 0, MAX_MEM_PTR * sizeof(UINT8 **)); +} + +// should we pass the pointer as a variable here so that we can save a pointer to it +// and then ensure it is NULL'd in BurnFree or BurnExitMemoryManager? + +// call instead of 'malloc' +UINT8 *BurnMalloc(INT32 size) +{ + for (INT32 i = 0; i < MAX_MEM_PTR; i++) + { + if (memptr[i] == NULL) { + memptr[i] = (UINT8*)malloc(size); + + if (memptr[i] == NULL) { + bprintf (0, _T("BurnMalloc failed to allocate %d bytes of memory!\n"), size); + return NULL; + } + + memset (memptr[i], 0, size); // set contents to 0 + + return memptr[i]; + } + } + + bprintf (0, _T("BurnMalloc called too many times!\n")); + + return NULL; // Freak out! +} + +// call instead of "free" +void _BurnFree(void *ptr) +{ + UINT8 *mptr = (UINT8*)ptr; + + for (INT32 i = 0; i < MAX_MEM_PTR; i++) + { + if (memptr[i] == mptr) { + free (memptr[i]); + memptr[i] = NULL; + + break; + } + } +} + +// call in BurnDrvExit? + +void BurnExitMemoryManager() +{ + for (INT32 i = 0; i < MAX_MEM_PTR; i++) + { + if (memptr[i] != NULL) { + free (memptr[i]); + memptr[i] = NULL; + } + } +} diff --git a/src/burn/burn_sound.cpp b/src/burn/burn_sound.cpp new file mode 100644 index 00000000..46850ce9 --- /dev/null +++ b/src/burn/burn_sound.cpp @@ -0,0 +1,23 @@ +#include "burnint.h" +#include "burn_sound.h" + +INT16 Precalc[4096 *4]; + +// Routine used to precalculate the table used for interpolation +INT32 cmc_4p_Precalc() +{ + INT32 a, x, x2, x3; + + for (a = 0; a < 4096; a++) { + x = a * 4; // x = 0..16384 + x2 = x * x / 16384; // pow(x, 2); + x3 = x2 * x / 16384; // pow(x, 3); + + Precalc[a * 4 + 0] = (INT16)(-x / 3 + x2 / 2 - x3 / 6); + Precalc[a * 4 + 1] = (INT16)(-x / 2 - x2 + x3 / 2 + 16384); + Precalc[a * 4 + 2] = (INT16)( x + x2 / 2 - x3 / 2); + Precalc[a * 4 + 3] = (INT16)(-x / 6 + x3 / 6); + } + + return 0; +} diff --git a/src/burn/burn_sound.h b/src/burn/burn_sound.h new file mode 100644 index 00000000..f923e56f --- /dev/null +++ b/src/burn/burn_sound.h @@ -0,0 +1,48 @@ +// burn_sound.h - General sound support functions +// based on code by Daniel Moreno (ComaC) < comac2k@teleline.es > + +#if defined BUILD_X86_ASM +extern "C" { + int __cdecl ChannelMix_QS_A(int* Dest, int nLen, + char* Sample, int LoopEnd, + int* Pos, + int VolL, int VolR, + int LoopLen, + int IncPos, + char* EndBuff); + + void __cdecl BurnSoundCopyClamp_A(int* Src, short* Dest, int Len); + void __cdecl BurnSoundCopyClamp_Add_A(int* Src, short* Dest, int Len); + + void __cdecl BurnSoundCopyClamp_Mono_A(int* Src, short* Dest, int Len); + void __cdecl BurnSoundCopyClamp_Mono_Add_A(int* Src, short* Dest, int Len); + + void __cdecl BurnSoundCopy_FM_A(short* SrcL, short* SrcR, short* Dest, int Len, int VolL, int VolR); + void __cdecl BurnSoundCopy_FM_Add_A(short* SrcL, short* SrcR, short* Dest, int Len, int VolL, int VolR); + + /* SrcOPN should have left channel data at SrcOPN, right channel at SrcOPN + 4096, SrcPSG should have all summed channels */ + void __cdecl BurnSoundCopy_FM_OPN_A(short* SrcOPN, int* SrcPSG, short* Dest, int Len, int VolPSGL, int VolPSGR); + void __cdecl BurnSoundCopy_FM_OPN_Add_A(short* SrcOPN, int* SrcPSG, short* Dest, int Len, int VolPSGL, int VolPSGR); +} +#endif + +void BurnSoundCopyClamp_C(INT32* Src, INT16* Dest, INT32 Len); +void BurnSoundCopyClamp_Add_C(INT32* Src, INT16* Dest, INT32 Len); +void BurnSoundCopyClamp_Mono_C(INT32* Src, INT16* Dest, INT32 Len); +void BurnSoundCopyClamp_Mono_Add_C(INT32* Src, INT16* Dest, INT32 Len); + +extern INT32 cmc_4p_Precalc(); + +#ifdef __ELF__ + #define Precalc _Precalc +#endif + +extern "C" INT16 Precalc[]; + +#define INTERPOLATE4PS_8BIT(fp, sN, s0, s1, s2) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 64) +#define INTERPOLATE4PS_16BIT(fp, sN, s0, s1, s2) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 16384) +#define INTERPOLATE4PS_CUSTOM(fp, sN, s0, s1, s2, v) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / (INT32)(v)) + +#define INTERPOLATE4PU_8BIT(fp, sN, s0, s1, s2) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 64) +#define INTERPOLATE4PU_16BIT(fp, sN, s0, s1, s2) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 16384) +#define INTERPOLATE4PU_CUSTOM(fp, sN, s0, s1, s2, v) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / (UINT32)(v)) diff --git a/src/burn/burn_sound_a.asm b/src/burn/burn_sound_a.asm new file mode 100644 index 00000000..57735885 --- /dev/null +++ b/src/burn/burn_sound_a.asm @@ -0,0 +1,751 @@ +; MMX general sound support + PCM channel mixing +; based on code by Daniel Moreno (ComaC) - 2001 < comac2k@teleline.es > + +; ChannelMix_QS mixes one channel using 4 point, 3rd order interpolation. +; The volume of the resulting audio is 64 times louder, to have extra precision +; when mixing the channels. +; +; The BurnSoundCopy* functions convert a 32-bit (interleaved stereo or mono) buffer +; to interleaved 16-bit stereo, clamping and dividing volume by 256 on the fly. +; +; BurnSoundCopy_FM interleaves 2 16-bit buffers into a single interleaved stereo buffer, +; correcting volume (variable) on the fly +; +; BurnSoundCopy_FM interleaves 2 16-bit buffers into a single interleaved stereo buffer, +; adding a 3rd 32-bit buffer correcting volume on the 3rd buffer (variable) on the fly + +[BITS 32] + +global ChannelMix_QS_A +global _ChannelMix_QS_A + +global ChannelMix_8U_A +global _ChannelMix_8U_A + +global BurnSoundCopyClamp_A +global _BurnSoundCopyClamp_A +global BurnSoundCopyClamp_Add_A +global _BurnSoundCopyClamp_Add_A + +global _BurnSoundCopyClamp_Mono_A +global BurnSoundCopyClamp_Mono_A +global _BurnSoundCopyClamp_Mono_Add_A +global BurnSoundCopyClamp_Mono_Add_A + +global BurnSoundCopy_FM_A +global _BurnSoundCopy_FM_A +global BurnSoundCopy_FM_Add_A +global _BurnSoundCopy_FM_Add_A + +global _BurnSoundCopy_FM_OPN_A +global BurnSoundCopy_FM_OPN_A +global _BurnSoundCopy_FM_OPN_Add_A +global BurnSoundCopy_FM_OPN_Add_A + +extern _Precalc + + + +section .text + +; This macro is used from other functions. It contains the main mixing +; loop for 8 bit samples. At its input it expects: +; +; EAX -> pointer to sample buffer +; EBX -> index inside sample (current position) +; ECX -> index of the first sample that does NOT have to play (LoopEnd) +; ESI -> pointer to destination buffer +; mm3 -> Volumes Low = Left, High = Right +; +; Param 1 -> dword containing position increment +; Param 2 -> dword containing loop length +; Param 3 -> dword containing size of out buffer in samples +; Param 4 -> pointer to enf buffer +; Param 5 -> instructions to do to unpacked samples, or text NONE if none +; +; At exit: +; +; EBX -> next position to play +; EDX -> destroyed +; [Param 2] -> updated acordingly +; [Param 4] -> zero +; mm0 -> destroyed +; mm1 -> destroyed + +%macro Mix_Loop 5 + +%define INCR %1 +%define LOOP %2 +%define BUFLEN %3 +%define ENDBUF %4 + + cmp EBX, ECX ; Past the end? + jl %%Sigue ; No? -> Continue + +%%PassedEnd: + mov EDX, ECX ; We are at or near the end of the sample + add EDX, 0x3000 ; We need to either stop, set the pointer + and EDX, (0xFFFF << 12) ; to the loop point, or render a few samples + cmp EBX, EDX ; from the end buffer + jge %%LoopCheck ; + + ; We need to render samples from the end buffer + + push EBX ; We need to copy EBX to EDX (!!!) + pxor mm0, mm0 ; Zero mm0 (to do zero extension of sample) + + add EBX, 0x4000 ; load end buffer in EDX, index in EBX + sub EBX, EDX ; + mov EDX, ENDBUF ; + shr EBX, 12 ; + + punpcklbw mm0, [EDX + EBX] ; Load & unpack samples (from the end buffer) to 16 bit + + pop EDX ; !!! + jmp %%Interpolate + +%%LoopCheck: + cmp LOOP, 0x1000 ; > 0x1000 + jg %%SetLoopPoint ; Yes -> Loop Sample + cmp LOOP, 0 + je %%EndSample + + mov EBX, ECX ; Kludge to work around some situations + add EBX, 0x2000 ; where the QSound hardware is left in + jmp %%End_StayOn ; a non-standard state (e.g. DDTOD, DDSOM) + +%%EndSample: + xor EBX, EBX + xor EAX, EAX ; set bKey to zero + jmp %%End ; exit function + +%%SetLoopPoint: + sub EBX, LOOP ; Set EBX to the loop point + +%%NextSample: + cmp EBX, ECX ; Passed the end? + jge %%PassedEnd + +%%Sigue: + mov EDX, EBX + and EBX, (0xFFFF << 12) ; QSound banks are 0x10000 bytes + shr EBX, 12 ; EBX = Integer(nPos) + + pxor mm0, mm0 ; Zero mm0 (to do zero extension of sample) + punpcklbw mm0, [EAX + EBX] ; Load & unpack samples to 16 bit + +%%Interpolate: + mov EBX, EDX + and EDX, 0x0FFF ; EDX = Decimal(nPos) + + ; Execute sign adaptation instructions if necessary: + +%ifnidni %5, NONE + pxor mm0, %5 +%endif + + ; Interpolate sample + + pmaddwd mm0, [_Precalc + EDX*8] ; Get multipliers + movq mm1, mm0 ; We need High(mm0) + Low(mm0) + psrlq mm0, 32 ; mm0 = High(mm0) + paddd mm0, mm1 ; mm0 = Sample interpolated * 16384 + psrad mm0, 16 ; Shift samples right + packssdw mm0, mm0 ; Hi(mm0) = sample, Low(mm0) = sample + + add EBX, INCR ; Advance counters + pmaddwd mm0, mm3 ; Multiply samples with volume + dec BUFLEN ; 1 sample less left + + paddd mm0, [ESI] ; Add to buffer + movq [ESI], mm0 ; Store result on buffer + + lea ESI, [ESI + 8] + jnz %%NextSample ; Continue if there are more samples + +%%End_StayOn: + mov EAX, 1 ; leave bKey at 1 +%%End: + +%endmacro + +; Parameters to ChannelMix_QS/8U: + +%define BuffDest dword [EBP + 8] +%define BuffLen dword [EBP + 12] +%define SampleBuff dword [EBP + 16] +%define LoopEnd dword [EBP + 20] +%define PosPtr dword [EBP + 24] +%define Volumes qword [EBP + 28] +%define LoopLen dword [EBP + 36] +%define IncrPos dword [EBP + 40] +%define EndBuff dword [EBP + 44] + +_ChannelMix_QS_A: +ChannelMix_QS_A: + + push EBP + mov EBP, ESP + + push EBX + push ESI + push EDI + + mov EAX, SampleBuff ; EAX = Sample Buffer + mov EBX, PosPtr + + movq mm3, Volumes ; mm3 = Volumes + + mov EBX, [EBX] ; EBX = Sample Position + mov ECX, LoopEnd ; ECX = LoopEnd + sub ECX, 0x3000 + mov ESI, BuffDest ; ESI = destionation buffer + mov EDI, IncrPos ; EDI = IncrPos + + Mix_Loop EDI, LoopLen, BuffLen, EndBuff, NONE + + mov ECX, PosPtr + pop EDI + pop ESI + mov [ECX], EBX ; Save position + +; emms + pop EBX + pop EBP + ret + + +_ChannelMix_8U_A: +ChannelMix_8U_A: + + push EBP + mov EBP, ESP + + push EBX + push ESI + push EDI + + mov EAX, SampleBuff ; EAX = Sample Buffer + mov EBX, PosPtr + + movq mm3, Volumes ; mm3 = Volumes + movq mm4, [XorSign] ; mm4 = Value to xor to adapt sign + + dec EAX + mov EBX, [EBX] ; EBX = Sample Position + mov ECX, LoopEnd ; ECX = LoopEnd + mov ESI, BuffDest ; ESI = destionation buffer + mov EDI, IncrPos ; EDI = IncrPos + + Mix_Loop EDI, LoopLen, BuffLen, EndBuff, mm4 + + mov ECX, PosPtr + pop EDI + pop ESI + mov [ECX], EBX ; Save position + +; emms + pop EBX + pop EBP + ret + + +; Parameters to BurnSoundCopyClamp* functions + +%define BufSrc [EBP + 8] +%define BufDest [EBP + 12] +%define Len [EBP + 16] + +_BurnSoundCopyClamp_A: +BurnSoundCopyClamp_A: + + push EBP + mov EBP, ESP + + mov ECX, BufSrc ; ECX = Buff Src + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = SampleR*256, Low(mm0) = SampleL*256 + movq mm1, [ECX + 8] ; Load next sample too + psrad mm0, 8 ; Hi(mm0) = Sample1R, Low(mm0) = Sample1L + psrad mm1, 8 ; Hi(mm1) = Sample2R, Low(mm1) = Sample2L + add ECX, byte 16 ; ECX -> next samples + + packssdw mm0, mm1 ; We have both samples packed here + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of sample pairs. + ; Handle the last sample pair here + + movq mm0, [ECX] + psrad mm0, 8 + packssdw mm0, mm0 + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBP + ret + +_BurnSoundCopyClamp_Add_A: +BurnSoundCopyClamp_Add_A: + + push EBP + mov EBP, ESP + + mov ECX, BufSrc ; ECX = Buff Src + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = SampleR*256, Low(mm0) = SampleL*256 + movq mm1, [ECX + 8] ; Load next sample too + psrad mm0, 8 ; Hi(mm0) = Sample1R, Low(mm0) = Sample1L + psrad mm1, 8 ; Hi(mm1) = Sample2R, Low(mm1) = Sample2L + add ECX, byte 16 ; ECX -> next samples + + packssdw mm0, mm1 ; Here we have the 2 samples packed + + paddsw mm0, [EDX] ; Add to the contents of the buffer + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next 2 samples + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of sample pairs. + ; Handle the last sample pair here + + movq mm0, [ECX] + psrad mm0, 8 + packssdw mm0, mm0 + movd mm1, [EDX] + paddsw mm0, mm1 + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBP + ret + +_BurnSoundCopyClamp_Mono_A: +BurnSoundCopyClamp_Mono_A: + + push EBP + mov EBP, ESP + + mov ECX, BufSrc ; ECX = Buff Src + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = Sample2*256, Low(mm0) = Sample1*256 + psrad mm0, 8 ; Hi(mm0) = Sample2, Low(mm0) = Sample1 + add ECX, byte 8 ; ECX -> next samples + packssdw mm0, mm0 ; We have both samples packed here + punpcklwd mm0, mm0 + + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of samples. + ; Handle the last sample here + + movd mm0, [ECX] + psrad mm0, 8 + packssdw mm0, mm0 + punpcklwd mm0, mm0 + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBP + ret + +_BurnSoundCopyClamp_Mono_Add_A: +BurnSoundCopyClamp_Mono_Add_A: + + push EBP + mov EBP, ESP + + mov ECX, BufSrc ; ECX = Buff Src + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = Sample2*256, Low(mm0) = Sample1*256 + psrad mm0, 8 ; Hi(mm0) = Sample2, Low(mm0) = Sample1 + add ECX, byte 8 ; ECX -> next samples + packssdw mm0, mm0 ; We have both samples packed here + punpcklwd mm0, mm0 + + paddsw mm0, [EDX] ; Add to the contents of the buffer + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next 2 samples + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of samples. + ; Handle the last sample here + + movd mm0, [ECX] + psrad mm0, 8 + packssdw mm0, mm0 + punpcklwd mm0, mm0 + movd mm1, [EDX] + paddsw mm0, mm1 + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBP + ret + +; Parameters to BurnSoundCopy_FM + +%define BufSrcL dword [EBP + 8] +%define BufSrcR dword [EBP + 12] +%define BufDest dword [EBP + 16] +%define Len dword [EBP + 20] +%define Volumes qword [EBP + 24] + +_BurnSoundCopy_FM_A: +BurnSoundCopy_FM_A: + + push EBP + mov EBP, ESP + push EBX + + movq mm1, Volumes + packssdw mm1, Volumes + + ; mm1 now holds the volumes as packed words + + mov EAX, Len ; EAX = Length + + mov EDX, BufDest ; EDX = BufDest + mov ECX, BufSrcR ; ECX = BufSrcR + mov EBX, BufSrcL ; EBX = BufSrcL + + shr EAX, 1 + je .LastSample + +.Loop: + movd mm0, [EBX] + punpcklwd mm0, [ECX] + + ; mm0 now has SrcR2 - SrcL2 - SrcR1 - SrcL1 + + pmulhw mm0, mm1 ; Multiply mm0 with volumes + + add EBX, byte 4 ; EBX -> next samples + add ECX, byte 4 ; ECX -> next samples + + dec EAX ; 2 sample less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of sample pairs. + ; Handle the last sample pair here + + movd mm0, [EBX] + punpcklwd mm0, [ECX] + + ; mm0 now has ? - ? - SrcR1 - SrcL1 + + pmulhw mm0, mm1 ; Multiply mm0 with volumes + + movd [EDX], mm0 ; Save the result + +.End: + emms ; Done with MMX + pop EBX + pop EBP + ret + +_BurnSoundCopy_FM_Add_A: +BurnSoundCopy_FM_Add_A: + + push EBP + mov EBP, ESP + push EBX + + movq mm1, Volumes + packssdw mm1, Volumes + + ; mm1 now holds the volumes as packed words + + mov EAX, Len ; EAX = Length + + mov EDX, BufDest ; EDX = BufDest + mov ECX, BufSrcR ; ECX = BufSrcR + mov EBX, BufSrcL ; EBX = BufSrcL + + shr EAX, 1 + je .LastSample + +.Loop: + movd mm0, [EBX] + punpcklwd mm0, [ECX] + + ; mm0 now has SrcR2 - SrcL2 - SrcR1 - SrcL1 + + pmulhw mm0, mm1 ; Multiply mm0 with volumes + + add EBX, byte 4 ; EBX -> next samples + add ECX, byte 4 ; ECX -> next samples + + paddsw mm0, [EDX] ; Add to the contents of the buffer + dec EAX ; 2 sample less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of sample pairs. + ; Handle the last sample pair here + + movd mm0, [EBX] + punpcklwd mm0, [ECX] + + ; mm0 now has ? - ? - SrcR1 - SrcL1 + + pmulhw mm0, mm1 ; Multiply mm0 with volumes + + movd mm1, [EDX] + paddsw mm0, mm1 ; Add to the contents of the buffer + movd [EDX], mm0 ; Save the result + +.End: + emms ; Done with MMX + pop EBX + pop EBP + ret + +; Parameters to BurnSoundCopyFM_OPN_A + +%define BufSrcOPN dword [EBP + 8] +%define BufSrcPSG dword [EBP + 12] +%define BufDest dword [EBP + 16] +%define Len dword [EBP + 20] +%define Volumes qword [EBP + 24] + +_BurnSoundCopy_FM_OPN_A: +BurnSoundCopy_FM_OPN_A: + + push EBP + mov EBP, ESP + push EBX + + movq mm4, Volumes + packssdw mm4, Volumes + + mov EBX, BufSrcOPN ; EBX = Buff Src (OPN) + mov ECX, BufSrcPSG ; ECX = Buff Src (PSG) + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = Sample2, Low(mm0) = Sample1 + add ECX, byte 8 ; ECX -> next samples + + packssdw mm0, mm0 + + movd mm1, [EBX] ; OPN sample left + + punpcklwd mm0, mm0 + + ; mm0 now has SrcPSGR2 - SrcPSGL2 - SrcPSGR1 - SrcPSGL1 + + punpcklwd mm1, [EBX + 8192] ; OPN sample right + + ; mm1 now has SrcOPNR2 - SrcOPNL2 - SrcOPNR1 - SrcOPNL1 + + pmulhw mm0, mm4 ; Multiply mm0 with volumes + + add EBX, byte 4 ; EBX -> next samples + + paddsw mm0, mm1 + + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of samples. + ; Handle the last sample here + + movd mm0, [ECX] + packssdw mm0, mm0 + movd mm1, [EBX] + punpcklwd mm0, mm0 + punpcklwd mm1, [EBX + 8192] + pmulhw mm0, mm4 + paddsw mm0, mm1 + + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBX + pop EBP + ret + +_BurnSoundCopy_FM_OPN_Add_A: +BurnSoundCopy_FM_OPN_Add_A: + + push EBP + mov EBP, ESP + push EBX + + movq mm4, Volumes + packssdw mm4, Volumes + + mov EBX, BufSrcOPN ; EBX = Buff Src (OPN) + mov ECX, BufSrcPSG ; ECX = Buff Src (PSG) + mov EDX, BufDest ; EDX = Buff Dest + + mov EAX, Len ; EAX = Length + shr EAX, 1 + je .LastSample + +.Loop: + movq mm0, [ECX] ; Hi(mm0) = Sample2, Low(mm0) = Sample1 + add ECX, byte 8 ; ECX -> next samples + + packssdw mm0, mm0 + + movd mm1, [EBX] ; OPN sample left + + punpcklwd mm0, mm0 + + ; mm0 now has SrcPSGR2 - SrcPSGL2 - SrcPSGR1 - SrcPSGL1 + + punpcklwd mm1, [EBX + 8192] ; OPN sample right + + ; mm1 now has SrcOPNR2 - SrcOPNL2 - SrcOPNR1 - SrcOPNL1 + + pmulhw mm0, mm4 ; Multiply mm0 with volumes + + add EBX, byte 4 ; EBX -> next samples + + paddsw mm0, mm1 + + paddsw mm0, [EDX] ; Add to the contents of the buffer + + dec EAX ; 2 samples less left + + movq [EDX], mm0 ; Save the result + + lea EDX, [EDX + 8] ; EDX -> next sample + jnz .Loop ; Continue if there are more samples + +.LastSample: + mov EAX, Len ; EAX = Length + test EAX, 1 + je .End + + ; We need to handle an odd amount of samples. + ; Handle the last sample here + + movd mm0, [ECX] + packssdw mm0, mm0 + movd mm1, [EBX] + punpcklwd mm0, mm0 + punpcklwd mm1, [EBX + 8192] + pmulhw mm0, mm4 + paddsw mm0, mm1 + + movd mm1, [EDX] + paddsw mm0, mm1 ; Add to the contents of the buffer + + movd [EDX], mm0 + +.End: + emms ; Done with MMX + pop EBX + pop EBP + ret + + +section .data + +; Used to xor with the unpacked samples to change sign: +XorSign: dw 0x8000, 0x8000, 0x8000, 0x8000 + + + +section .bss + +VolMMX: resd 2 +ActiveFlag: resb 1 diff --git a/src/burn/burn_sound_c.cpp b/src/burn/burn_sound_c.cpp new file mode 100644 index 00000000..961efdb3 --- /dev/null +++ b/src/burn/burn_sound_c.cpp @@ -0,0 +1,46 @@ +#include "burnint.h" +#include "burn_sound.h" + +#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) + +void BurnSoundCopyClamp_C(INT32 *Src, INT16 *Dest, INT32 Len) +{ + Len *= 2; + while (Len--) { + *Dest = CLIP((*Src >> 8)); + Src++; + Dest++; + } +} + +void BurnSoundCopyClamp_Add_C(INT32 *Src, INT16 *Dest, INT32 Len) +{ + Len *= 2; + while (Len--) { + *Dest = CLIP((*Src >> 8) + *Dest); + Src++; + Dest++; + } +} + +void BurnSoundCopyClamp_Mono_C(INT32 *Src, INT16 *Dest, INT32 Len) +{ + while (Len--) { + Dest[0] = CLIP((*Src >> 8)); + Dest[1] = CLIP((*Src >> 8)); + Src++; + Dest += 2; + } +} + +void BurnSoundCopyClamp_Mono_Add_C(INT32 *Src, INT16 *Dest, INT32 Len) +{ + while (Len--) { + Dest[0] = CLIP((*Src >> 8) + Dest[0]); + Dest[1] = CLIP((*Src >> 8) + Dest[1]); + Src++; + Dest += 2; + } +} + +#undef CLIP diff --git a/src/burn/burnint.h b/src/burn/burnint.h new file mode 100644 index 00000000..5831d529 --- /dev/null +++ b/src/burn/burnint.h @@ -0,0 +1,121 @@ +// Burn - Arcade emulator library - internal code + +// Standard headers +#include +#include +#include +#include +#include + +#include "tchar.h" +#include "burn.h" + +// --------------------------------------------------------------------------- +// CPU emulation interfaces + +// sek.cpp +#include "sek.h" + +// zet.cpp +#include "zet.h" + +typedef union +{ + struct { UINT8 l,h,h2,h3; } b; + struct { UINT16 l,h; } w; + UINT32 d; +} PAIR; + +// --------------------------------------------------------------------------- +// Driver information + +struct BurnDriver { + char* szShortName; // The filename of the zip file (without extension) + char* szParent; // The filename of the parent (without extension, NULL if not applicable) + char* szBoardROM; // The filename of the board ROMs (without extension, NULL if not applicable) + char* szSampleName; // The filename of the samples zip file (without extension, NULL if not applicable) + char* szDate; + + // szFullNameA, szCommentA, szManufacturerA and szSystemA should always contain valid info + // szFullNameW, szCommentW, szManufacturerW and szSystemW should be used only if characters or scripts are needed that ASCII can't handle + char* szFullNameA; char* szCommentA; char* szManufacturerA; char* szSystemA; + wchar_t* szFullNameW; wchar_t* szCommentW; wchar_t* szManufacturerW; wchar_t* szSystemW; + + INT32 Flags; // See burn.h + INT32 Players; // Max number of players a game supports (so we can remove single player games from netplay) + INT32 Hardware; // Which type of hardware the game runs on + INT32 Genre; + INT32 Family; + INT32 (*GetZipName)(char** pszName, UINT32 i); // Function to get possible zip names + INT32 (*GetRomInfo)(struct BurnRomInfo* pri, UINT32 i); // Function to get the length and crc of each rom + INT32 (*GetRomName)(char** pszName, UINT32 i, INT32 nAka); // Function to get the possible names for each rom + INT32 (*GetSampleInfo)(struct BurnSampleInfo* pri, UINT32 i); // Function to get the sample flags + INT32 (*GetSampleName)(char** pszName, UINT32 i, INT32 nAka); // Function to get the possible names for each sample + INT32 (*GetInputInfo)(struct BurnInputInfo* pii, UINT32 i); // Function to get the input info for the game + INT32 (*GetDIPInfo)(struct BurnDIPInfo* pdi, UINT32 i); // Function to get the input info for the game + INT32 (*Init)(); INT32 (*Exit)(); INT32 (*Frame)(); INT32 (*Redraw)(); INT32 (*AreaScan)(INT32 nAction, INT32* pnMin); + UINT8* pRecalcPal; UINT32 nPaletteEntries; // Set to 1 if the palette needs to be fully re-calculated + INT32 nWidth, nHeight; INT32 nXAspect, nYAspect; // Screen width, height, x/y aspect +}; + +#define BurnDriverD BurnDriver // Debug status +#define BurnDriverX BurnDriver // Exclude from build + +// Standard functions for dealing with ROM and input info structures +#include "stdfunc.h" + +// --------------------------------------------------------------------------- + +// burn.cpp +INT32 BurnSetRefreshRate(double dRefreshRate); +INT32 BurnByteswap(UINT8* pm,INT32 nLen); +INT32 BurnClearScreen(); + +// load.cpp +INT32 BurnLoadRom(UINT8* Dest, INT32 i, INT32 nGap); +INT32 BurnXorRom(UINT8* Dest, INT32 i, INT32 nGap); +INT32 BurnLoadBitField(UINT8* pDest, UINT8* pSrc, INT32 nField, INT32 nSrcLen); + +// --------------------------------------------------------------------------- +// Colour-depth independant image transfer + +extern UINT16* pTransDraw; + +void BurnTransferClear(); +INT32 BurnTransferCopy(UINT32* pPalette); +void BurnTransferExit(); +INT32 BurnTransferInit(); + +// --------------------------------------------------------------------------- +// Plotting pixels + +inline static void PutPix(UINT8* pPix, UINT32 c) +{ + if (nBurnBpp >= 4) { + *((UINT32*)pPix) = c; + } else { + if (nBurnBpp == 2) { + *((UINT16*)pPix) = (UINT16)c; + } else { + pPix[0] = (UINT8)(c >> 0); + pPix[1] = (UINT8)(c >> 8); + pPix[2] = (UINT8)(c >> 16); + } + } +} + +// --------------------------------------------------------------------------- +// Setting up cpus for cheats + +void CpuCheatRegister(INT32 type, INT32 num); + +// burn_memory.cpp +void BurnInitMemoryManager(); +UINT8 *BurnMalloc(INT32 size); +void _BurnFree(void *ptr); +#define BurnFree(x) _BurnFree(x); x = NULL; +void BurnExitMemoryManager(); + +// --------------------------------------------------------------------------- +// Sound clipping macro +#define BURN_SND_CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) diff --git a/src/burn/cheat.cpp b/src/burn/cheat.cpp new file mode 100644 index 00000000..27792c61 --- /dev/null +++ b/src/burn/cheat.cpp @@ -0,0 +1,664 @@ +// Cheat module + +#include "burnint.h" +#include "vez.h" +#include "sh2.h" +#include "m6502_intf.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "s2650_intf.h" +#include "konami_intf.h" +#include "arm7_intf.h" + +bool bCheatsAllowed; +CheatInfo* pCheatInfo = NULL; + +static bool bCheatsEnabled = false; + +//---------------------------------------------------- +// Cpu interface for cheat application + +#define MAX_CHEAT_CPU 8 // enough? + +static INT32 nActiveCheatCpus; + +struct cheat_subs { + INT32 nCpu; // Which cpu is this? (SekOpen(#), ZetOpen(#)) + void (*cpu_open)(INT32); + void (*write)(UINT32, UINT8); + UINT8 (*read)(UINT32); + void (*cpu_close)(); + INT32 (*active_cpu)(); + UINT32 nMemorySize; +}; + +struct cheat_subs cheat_sub_block[MAX_CHEAT_CPU]; +struct cheat_subs *cheat_subptr; + +//--------------------------------------------------- +// Dummy handlers + +static INT32 CheatDummyGetActive() { return -1; } +static void CheatDummyOpen(INT32) {} +static void CheatDummyClose() {} +static void CheatDummyWriteByte(UINT32, UINT8) {} +static UINT8 CheatDummyReadByte(UINT32) { return 0; } + +// ----------------------------------------------- +// Set up handlers for cpu cores that aren't totally compatible + +#define CHEAT_READ(name,funct) \ +static UINT8 name##ReadByteCheat(UINT32 a) { \ + return funct; \ +} + +#define CHEAT_WRITE(name,funct) \ +static void name##WriteByteCheat(UINT32 a, UINT8 d) { \ + funct; \ +} + +CHEAT_READ(Sek, SekReadByte(a)) +CHEAT_READ(Sh2, Sh2ReadByte(a)) +CHEAT_WRITE(Sh2, Sh2WriteByte(a,d)) +CHEAT_READ(Zet, ZetReadByte(a)) +CHEAT_WRITE(Zet, ZetWriteRom(a,d)) +CHEAT_READ(M6800, M6800ReadByte(a)) +CHEAT_WRITE(M6800, M6800WriteRom(a,d)) +CHEAT_READ(M6809, M6809ReadByte(a)) +CHEAT_WRITE(M6809, M6809WriteRom(a,d)) +CHEAT_READ(HD6309, HD6309ReadByte(a)) +CHEAT_WRITE(HD6309, HD6309WriteRom(a,d)) +CHEAT_READ(m6502, M6502ReadByte(a)) +CHEAT_WRITE(m6502, M6502WriteRom(a,d)) +CHEAT_READ(s2650, s2650_read(a)) +CHEAT_WRITE(s2650, s2650_write_rom(a,d)) +CHEAT_READ(konami, konami_read(a)) +CHEAT_WRITE(konami, konami_write_rom(a,d)) + +//------------------------------------------------ +// Central cpu registry for functions necessary for cheats + +void CpuCheatRegister(INT32 type, INT32 nNum) +{ + cheat_subptr = &cheat_sub_block[nActiveCheatCpus]; + nActiveCheatCpus++; + + switch (type) + { + case 0x0000: // m68k + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = SekOpen; + cheat_subptr->cpu_close = SekClose; + cheat_subptr->active_cpu = SekGetActive; + cheat_subptr->write = SekWriteByteROM; + cheat_subptr->read = SekReadByteCheat; + cheat_subptr->nMemorySize = 0x01000000; + } + break; + + case 0x0001: // NEC V30 / V33 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = VezOpen; + cheat_subptr->cpu_close = VezClose; + cheat_subptr->active_cpu = VezGetActive; + cheat_subptr->write = cpu_writemem20; + cheat_subptr->read = cpu_readmem20; + cheat_subptr->nMemorySize = 0x00100000; + } + break; + + case 0x0002: // SH2 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = Sh2Open; + cheat_subptr->cpu_close = Sh2Close; + cheat_subptr->active_cpu = Sh2GetActive; + cheat_subptr->write = Sh2WriteByteCheat; + cheat_subptr->read = Sh2ReadByteCheat; + cheat_subptr->nMemorySize = 0x02080000; // Good enough for CPS3 + } + break; + + case 0x0003: // M6502 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = M6502Open; + cheat_subptr->cpu_close = M6502Close; + cheat_subptr->active_cpu = M6502GetActive; + cheat_subptr->write = m6502WriteByteCheat; + cheat_subptr->read = m6502ReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0004: // Z80 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = ZetOpen; + cheat_subptr->cpu_close = ZetClose; + cheat_subptr->active_cpu = ZetGetActive; + cheat_subptr->write = ZetWriteByteCheat; + cheat_subptr->read = ZetReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0005: // M6809 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = M6809Open; + cheat_subptr->cpu_close = M6809Close; + cheat_subptr->active_cpu = M6809GetActive; + cheat_subptr->write = M6809WriteByteCheat; + cheat_subptr->read = M6809ReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0006: // HD6309 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = HD6309Open; + cheat_subptr->cpu_close = HD6309Close; + cheat_subptr->active_cpu = HD6309GetActive; + cheat_subptr->write = HD6309WriteByteCheat; + cheat_subptr->read = HD6309ReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0007: // M6800 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = CheatDummyOpen; + cheat_subptr->cpu_close = CheatDummyClose; + cheat_subptr->active_cpu = CheatDummyGetActive; + cheat_subptr->write = M6800WriteByteCheat; + cheat_subptr->read = M6800ReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0008: // S2650 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = s2650Open; + cheat_subptr->cpu_close = s2650Close; + cheat_subptr->active_cpu = s2650GetActive; + cheat_subptr->write = s2650WriteByteCheat; + cheat_subptr->read = s2650ReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x0009: // Konami Custom + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = konamiOpen; + cheat_subptr->cpu_close = konamiClose; + cheat_subptr->active_cpu = konamiGetActive; + cheat_subptr->write = konamiWriteByteCheat; + cheat_subptr->read = konamiReadByteCheat; + cheat_subptr->nMemorySize = 0x00010000; + } + break; + + case 0x000a: // ARM7 + { + cheat_subptr->nCpu = nNum; + cheat_subptr->cpu_open = Arm7Open; + cheat_subptr->cpu_close = Arm7Close; + cheat_subptr->active_cpu = CheatDummyGetActive; + cheat_subptr->write = Arm7_write_rom_byte; + cheat_subptr->read = Arm7_program_read_byte_32le; + cheat_subptr->nMemorySize = 0x80000000; // enough for PGM... + } + break; + + // Just in case the called cpu isn't supported and so MinGW + // doesn't complain about unused functions... + default: + { + cheat_subptr->nCpu = 0; + cheat_subptr->cpu_open = CheatDummyOpen; + cheat_subptr->cpu_close = CheatDummyClose; + cheat_subptr->active_cpu = CheatDummyGetActive; + cheat_subptr->write = CheatDummyWriteByte; + cheat_subptr->read = CheatDummyReadByte; + cheat_subptr->nMemorySize = 0; + } + break; + } +} + +INT32 CheatUpdate() +{ + bCheatsEnabled = false; + + if (bCheatsAllowed) { + CheatInfo* pCurrentCheat = pCheatInfo; + CheatAddressInfo* pAddressInfo; + + while (pCurrentCheat) { + if (pCurrentCheat->nStatus > 1) { + pAddressInfo = pCurrentCheat->pOption[pCurrentCheat->nCurrent]->AddressInfo; + if (pAddressInfo->nAddress) { + bCheatsEnabled = true; + } + } + pCurrentCheat = pCurrentCheat->pNext; + } + } + + return 0; +} + +INT32 CheatEnable(INT32 nCheat, INT32 nOption) +{ + INT32 nCurrentCheat = 0; + CheatInfo* pCurrentCheat = pCheatInfo; + CheatAddressInfo* pAddressInfo; + INT32 nOpenCPU = -1; + + if (!bCheatsAllowed) { + return 1; + } + + if (nOption >= CHEAT_MAX_OPTIONS) { + return 1; + } + + cheat_subptr = &cheat_sub_block[0]; // first cpu... + + while (pCurrentCheat && nCurrentCheat <= nCheat) { + if (nCurrentCheat == nCheat) { + + if (nOption == -1) { + nOption = pCurrentCheat->nDefault; + } + + if (pCurrentCheat->nType != 1) { + + // Return OK if the cheat is already active with the same option + if (pCurrentCheat->nCurrent == nOption) { + return 0; + } + + // Deactivate old option (if any) + pAddressInfo = pCurrentCheat->pOption[nOption]->AddressInfo; + while (pAddressInfo->nAddress) { + + if (pAddressInfo->nCPU != nOpenCPU) { + + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + nOpenCPU = pAddressInfo->nCPU; + cheat_subptr = &cheat_sub_block[nOpenCPU]; + cheat_subptr->cpu_open(cheat_subptr->nCpu); + } + + // Write back original values to memory + cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nOriginalValue); + pAddressInfo++; + } + } + + // Activate new option + pAddressInfo = pCurrentCheat->pOption[nOption]->AddressInfo; + while (pAddressInfo->nAddress) { + + if (pAddressInfo->nCPU != nOpenCPU) { + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + nOpenCPU = pAddressInfo->nCPU; + cheat_subptr = &cheat_sub_block[nOpenCPU]; + cheat_subptr->cpu_open(cheat_subptr->nCpu); + } + + // Copy the original values + pAddressInfo->nOriginalValue = cheat_subptr->read(pAddressInfo->nAddress); + + if (pCurrentCheat->nType != 0) { + if (pAddressInfo->nCPU != nOpenCPU) { + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + nOpenCPU = pAddressInfo->nCPU; + cheat_subptr = &cheat_sub_block[nOpenCPU]; + cheat_subptr->cpu_open(cheat_subptr->nCpu); + } + + // Activate the cheat + cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nValue); + } + + pAddressInfo++; + } + + // Set cheat status and active option + if (pCurrentCheat->nType != 1) { + pCurrentCheat->nCurrent = nOption; + } + if (pCurrentCheat->nType == 0) { + pCurrentCheat->nStatus = 2; + } + if (pCurrentCheat->nType == 2) { + pCurrentCheat->nStatus = 1; + } + + break; + } + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + CheatUpdate(); + + if (nCurrentCheat == nCheat && pCurrentCheat) { + return 0; + } + + return 1; +} + +INT32 CheatApply() +{ + if (!bCheatsEnabled) { + return 0; + } + + INT32 nOpenCPU = -1; + + CheatInfo* pCurrentCheat = pCheatInfo; + CheatAddressInfo* pAddressInfo; + while (pCurrentCheat) { + if (pCurrentCheat->nStatus > 1) { + pAddressInfo = pCurrentCheat->pOption[pCurrentCheat->nCurrent]->AddressInfo; + while (pAddressInfo->nAddress) { + + if (pAddressInfo->nCPU != nOpenCPU) { + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + nOpenCPU = pAddressInfo->nCPU; + cheat_subptr = &cheat_sub_block[nOpenCPU]; + cheat_subptr->cpu_open(cheat_subptr->nCpu); + } + + cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nValue); + pAddressInfo++; + } + } + pCurrentCheat = pCurrentCheat->pNext; + } + + if (nOpenCPU != -1) { + cheat_subptr->cpu_close(); + } + + return 0; +} + +INT32 CheatInit() +{ + CheatExit(); + + bCheatsEnabled = false; + + return 0; +} + +void CheatExit() +{ + if (pCheatInfo) { + CheatInfo* pCurrentCheat = pCheatInfo; + CheatInfo* pNextCheat; + + do { + pNextCheat = pCurrentCheat->pNext; + for (INT32 i = 0; i < CHEAT_MAX_OPTIONS; i++) { + if (pCurrentCheat->pOption[i]) { + free(pCurrentCheat->pOption[i]); + } + } + if (pCurrentCheat) { + free(pCurrentCheat); + } + } while ((pCurrentCheat = pNextCheat) != 0); + } + + nActiveCheatCpus = 0; + for (INT32 i = 0; i < MAX_CHEAT_CPU; i++) { + CpuCheatRegister(-1, i); // set them all to dummy... + } + nActiveCheatCpus = 0; + + pCheatInfo = NULL; +} + +// Cheat search + +static UINT8 *MemoryValues = NULL; +static UINT8 *MemoryStatus = NULL; +static UINT32 nMemorySize = 0; + +#define NOT_IN_RESULTS 0 +#define IN_RESULTS 1 + +UINT32 CheatSearchShowResultAddresses[CHEATSEARCH_SHOWRESULTS]; +UINT32 CheatSearchShowResultValues[CHEATSEARCH_SHOWRESULTS]; + +INT32 CheatSearchInit() +{ + return 1; +} + +void CheatSearchExit() +{ + if (MemoryValues) { + free(MemoryValues); + MemoryValues = NULL; + } + if (MemoryStatus) { + free(MemoryStatus); + MemoryStatus = NULL; + } + + nMemorySize = 0; + + memset(CheatSearchShowResultAddresses, 0, CHEATSEARCH_SHOWRESULTS); + memset(CheatSearchShowResultValues, 0, CHEATSEARCH_SHOWRESULTS); +} + +void CheatSearchStart() +{ + UINT32 nAddress; + + INT32 nActiveCPU = 0; + cheat_subptr = &cheat_sub_block[nActiveCPU]; // first cpu only (ok?) + + nActiveCPU = cheat_subptr->active_cpu(); + if (nActiveCPU >= 0) cheat_subptr->cpu_close(); + cheat_subptr->cpu_open(cheat_subptr->nCpu); + nMemorySize = cheat_subptr->nMemorySize; + + MemoryValues = (UINT8*)malloc(nMemorySize); + MemoryStatus = (UINT8*)malloc(nMemorySize); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + MemoryValues[nAddress] = cheat_subptr->read(nAddress); + } + + cheat_subptr->cpu_close(); + if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU); + + memset(MemoryStatus, IN_RESULTS, nMemorySize); +} + +static void CheatSearchGetResults() +{ + UINT32 nAddress; + UINT32 nResultsPos = 0; + + memset(CheatSearchShowResultAddresses, 0, CHEATSEARCH_SHOWRESULTS); + memset(CheatSearchShowResultValues, 0, CHEATSEARCH_SHOWRESULTS); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == IN_RESULTS) { + CheatSearchShowResultAddresses[nResultsPos] = nAddress; + CheatSearchShowResultValues[nResultsPos] = MemoryValues[nAddress]; + nResultsPos++; + } + } +} + +UINT32 CheatSearchValueNoChange() +{ + UINT32 nMatchedAddresses = 0; + UINT32 nAddress; + + INT32 nActiveCPU = 0; + + nActiveCPU = cheat_subptr->active_cpu(); + if (nActiveCPU >= 0) cheat_subptr->cpu_close(); + cheat_subptr->cpu_open(0); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue; + if (cheat_subptr->read(nAddress) == MemoryValues[nAddress]) { + MemoryValues[nAddress] = cheat_subptr->read(nAddress); + nMatchedAddresses++; + } else { + MemoryStatus[nAddress] = NOT_IN_RESULTS; + } + } + + cheat_subptr->cpu_close(); + if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU); + + if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults(); + + return nMatchedAddresses; +} + +UINT32 CheatSearchValueChange() +{ + UINT32 nMatchedAddresses = 0; + UINT32 nAddress; + + INT32 nActiveCPU = 0; + + nActiveCPU = cheat_subptr->active_cpu(); + if (nActiveCPU >= 0) cheat_subptr->cpu_close(); + cheat_subptr->cpu_open(0); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue; + if (cheat_subptr->read(nAddress) != MemoryValues[nAddress]) { + MemoryValues[nAddress] = cheat_subptr->read(nAddress); + nMatchedAddresses++; + } else { + MemoryStatus[nAddress] = NOT_IN_RESULTS; + } + } + + cheat_subptr->cpu_close(); + if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU); + + if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults(); + + return nMatchedAddresses; +} + +UINT32 CheatSearchValueDecreased() +{ + UINT32 nMatchedAddresses = 0; + UINT32 nAddress; + + INT32 nActiveCPU = 0; + + nActiveCPU = cheat_subptr->active_cpu(); + if (nActiveCPU >= 0) cheat_subptr->cpu_close(); + cheat_subptr->cpu_open(0); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue; + if (cheat_subptr->read(nAddress) < MemoryValues[nAddress]) { + MemoryValues[nAddress] = cheat_subptr->read(nAddress); + nMatchedAddresses++; + } else { + MemoryStatus[nAddress] = NOT_IN_RESULTS; + } + } + + cheat_subptr->cpu_close(); + if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU); + + if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults(); + + return nMatchedAddresses; +} + +UINT32 CheatSearchValueIncreased() +{ + UINT32 nMatchedAddresses = 0; + UINT32 nAddress; + + INT32 nActiveCPU = 0; + + nActiveCPU = cheat_subptr->active_cpu(); + if (nActiveCPU >= 0) cheat_subptr->cpu_close(); + cheat_subptr->cpu_open(0); + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue; + if (cheat_subptr->read(nAddress) > MemoryValues[nAddress]) { + MemoryValues[nAddress] = cheat_subptr->read(nAddress); + nMatchedAddresses++; + } else { + MemoryStatus[nAddress] = NOT_IN_RESULTS; + } + } + + cheat_subptr->cpu_close(); + if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU); + + if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults(); + + return nMatchedAddresses; +} + +void CheatSearchDumptoFile() +{ + FILE *fp = fopen("cheatsearchdump.txt", "wt"); + UINT32 nAddress; + + if (fp) { + char Temp[256]; + + for (nAddress = 0; nAddress < nMemorySize; nAddress++) { + if (MemoryStatus[nAddress] == IN_RESULTS) { + sprintf(Temp, "Address %08X Value %02X\n", nAddress, MemoryValues[nAddress]); + fwrite(Temp, 1, strlen(Temp), fp); + } + } + + fclose(fp); + } +} + +#undef NOT_IN_RESULTS +#undef IN_RESULTS diff --git a/src/burn/cheat.h b/src/burn/cheat.h new file mode 100644 index 00000000..cc4ed307 --- /dev/null +++ b/src/burn/cheat.h @@ -0,0 +1,49 @@ +#define CHEAT_MAX_ADDRESS ( 64) +#define CHEAT_MAX_OPTIONS (192) +#define CHEAT_MAX_NAME (128) + +extern bool bCheatsAllowed; + +struct CheatAddressInfo { + INT32 nCPU; + INT32 nAddress; + UINT32 nValue; + UINT32 nOriginalValue; +}; + +struct CheatOption { + TCHAR szOptionName[CHEAT_MAX_NAME]; + struct CheatAddressInfo AddressInfo[CHEAT_MAX_ADDRESS + 1]; +}; + +struct CheatInfo { + struct CheatInfo* pNext; + struct CheatInfo* pPrevious; + INT32 nType; // Cheat type + INT32 nStatus; // 0 = Inactive + INT32 nCurrent; // Currently selected option + INT32 nDefault; // Default option + TCHAR szCheatName[CHEAT_MAX_NAME]; + struct CheatOption* pOption[CHEAT_MAX_OPTIONS]; +}; + +extern CheatInfo* pCheatInfo; + +INT32 CheatUpdate(); +INT32 CheatEnable(INT32 nCheat, INT32 nOption); +INT32 CheatApply(); +INT32 CheatInit(); +void CheatExit(); + +#define CHEATSEARCH_SHOWRESULTS 3 +extern UINT32 CheatSearchShowResultAddresses[CHEATSEARCH_SHOWRESULTS]; +extern UINT32 CheatSearchShowResultValues[CHEATSEARCH_SHOWRESULTS]; + +INT32 CheatSearchInit(); +void CheatSearchExit(); +void CheatSearchStart(); +UINT32 CheatSearchValueNoChange(); +UINT32 CheatSearchValueChange(); +UINT32 CheatSearchValueDecreased(); +UINT32 CheatSearchValueIncreased(); +void CheatSearchDumptoFile(); diff --git a/src/burn/devices/8255ppi.cpp b/src/burn/devices/8255ppi.cpp new file mode 100644 index 00000000..dcaf557c --- /dev/null +++ b/src/burn/devices/8255ppi.cpp @@ -0,0 +1,450 @@ +#include "burnint.h" +#include "8255ppi.h" + +#define MAX_PPIS 3 + +PPIPortRead PPI0PortReadA; +PPIPortRead PPI0PortReadB; +PPIPortRead PPI0PortReadC; +PPIPortWrite PPI0PortWriteA; +PPIPortWrite PPI0PortWriteB; +PPIPortWrite PPI0PortWriteC; +PPIPortRead PPI1PortReadA; +PPIPortRead PPI1PortReadB; +PPIPortRead PPI1PortReadC; +PPIPortWrite PPI1PortWriteA; +PPIPortWrite PPI1PortWriteB; +PPIPortWrite PPI1PortWriteC; +PPIPortRead PPI2PortReadA; +PPIPortRead PPI2PortReadB; +PPIPortRead PPI2PortReadC; +PPIPortWrite PPI2PortWriteA; +PPIPortWrite PPI2PortWriteB; +PPIPortWrite PPI2PortWriteC; + +typedef struct +{ + /* mode flags */ + UINT8 groupA_mode; + UINT8 groupB_mode; + UINT8 portA_dir; + UINT8 portB_dir; + UINT8 portCH_dir; + UINT8 portCL_dir; + + /* handshake signals (1=asserted; 0=non-asserted) */ + UINT8 obf_a; + UINT8 obf_b; + UINT8 ibf_a; + UINT8 ibf_b; + UINT8 inte_a; + UINT8 inte_b; + + UINT8 in_mask[3]; /* input mask */ + UINT8 out_mask[3]; /* output mask */ + UINT8 read[3]; /* data read from ports */ + UINT8 latch[3]; /* data written to ports */ + UINT8 output[3]; /* actual output data */ +} ppi8255; + +static ppi8255 chips[MAX_PPIS]; + +static void ppi8255_get_handshake_signals(ppi8255 *chip, UINT8 *result) +{ + UINT8 handshake = 0x00; + UINT8 mask = 0x00; + + /* group A */ + if (chip->groupA_mode == 1) + { + if (chip->portA_dir) + { + handshake |= chip->ibf_a ? 0x20 : 0x00; + handshake |= (chip->ibf_a && chip->inte_a) ? 0x08 : 0x00; + mask |= 0x28; + } + else + { + handshake |= chip->obf_a ? 0x00 : 0x80; + handshake |= (chip->obf_a && chip->inte_a) ? 0x08 : 0x00; + mask |= 0x88; + } + } + else if (chip->groupA_mode == 2) + { + handshake |= chip->inte_a ? 0x08 : 0x00; + handshake |= chip->obf_a ? 0x00 : 0x80; + handshake |= chip->ibf_a ? 0x20 : 0x00; + mask |= 0xA8; + } + + /* group B */ + if (chip->groupB_mode == 1) + { + if (chip->portA_dir) + { + handshake |= chip->ibf_b ? 0x02 : 0x00; + handshake |= (chip->ibf_b && chip->inte_b) ? 0x01 : 0x00; + mask |= 0x03; + } + else + { + handshake |= chip->obf_b ? 0x00 : 0x02; + handshake |= (chip->obf_b && chip->inte_b) ? 0x01 : 0x00; + mask |= 0x03; + } + } + + *result &= ~mask; + *result |= handshake & mask; +} + +static void ppi8255_write_port(ppi8255 *chip, INT32 port, INT32 chipnum) +{ + UINT8 write_data; + + write_data = chip->latch[port] & chip->out_mask[port]; + write_data |= 0xFF & ~chip->out_mask[port]; + + /* write out special port 2 signals */ + if (port == 2) + ppi8255_get_handshake_signals(chip, &write_data); + + chip->output[port] = write_data; + + if (chipnum == 0 && port == 0) { + if (PPI0PortWriteA) PPI0PortWriteA(write_data); + } + + if (chipnum == 0 && port == 1) { + if (PPI0PortWriteB) PPI0PortWriteB(write_data); + } + + if (chipnum == 0 && port == 2) { + if (PPI0PortWriteC) PPI0PortWriteC(write_data); + } + + if (chipnum == 1 && port == 0) { + if (PPI1PortWriteA) PPI1PortWriteA(write_data); + } + + if (chipnum == 1 && port == 1) { + if (PPI1PortWriteB) PPI1PortWriteB(write_data); + } + + if (chipnum == 1 && port == 2) { + if (PPI1PortWriteC) PPI1PortWriteC(write_data); + } + + if (chipnum == 2 && port == 0) { + if (PPI2PortWriteA) PPI2PortWriteA(write_data); + } + + if (chipnum == 2 && port == 1) { + if (PPI2PortWriteB) PPI2PortWriteB(write_data); + } + + if (chipnum == 2 && port == 2) { + if (PPI2PortWriteC) PPI2PortWriteC(write_data); + } +} + +static void ppi8255_input(ppi8255 *chip, INT32 port, UINT8 data, INT32 which) +{ + INT32 changed = 0; + + chip->read[port] = data; + + /* port C is special */ + if (port == 2) + { + if (((chip->groupA_mode == 1) && (chip->portA_dir == 0)) || (chip->groupA_mode == 2)) + { + /* is !ACKA asserted? */ + if (chip->obf_a && !(data & 0x40)) + { + chip->obf_a = 0; + changed = 1; + } + } + + if ((chip->groupB_mode == 1) && (chip->portB_dir == 0)) + { + /* is !ACKB asserted? */ + if (chip->obf_b && !(data & 0x04)) + { + chip->obf_b = 0; + changed = 1; + } + } + + if (changed) + ppi8255_write_port(chip, 2, which); + } +} + +static UINT8 ppi8255_read_port(ppi8255 *chip, INT32 port, INT32 chipnum) +{ + UINT8 result = 0x00; + + if (chip->in_mask[port]) + { + if (chipnum == 0 && port == 0) { + ppi8255_input(chip, port, (PPI0PortReadA) ? PPI0PortReadA() : 0, chipnum); + } + + if (chipnum == 0 && port == 1) { + ppi8255_input(chip, port, (PPI0PortReadB) ? PPI0PortReadB() : 0, chipnum); + } + + if (chipnum == 0 && port == 2) { + ppi8255_input(chip, port, (PPI0PortReadC) ? PPI0PortReadC() : 0, chipnum); + } + + if (chipnum == 1 && port == 0) { + ppi8255_input(chip, port, (PPI1PortReadA) ? PPI1PortReadA() : 0, chipnum); + } + + if (chipnum == 1 && port == 1) { + ppi8255_input(chip, port, (PPI1PortReadB) ? PPI1PortReadB() : 0, chipnum); + } + + if (chipnum == 1 && port == 2) { + ppi8255_input(chip, port, (PPI1PortReadC) ? PPI1PortReadC() : 0, chipnum); + } + + if (chipnum == 2 && port == 0) { + ppi8255_input(chip, port, (PPI2PortReadA) ? PPI2PortReadA() : 0, chipnum); + } + + if (chipnum == 2 && port == 1) { + ppi8255_input(chip, port, (PPI2PortReadB) ? PPI2PortReadB() : 0, chipnum); + } + + if (chipnum == 2 && port == 2) { + ppi8255_input(chip, port, (PPI2PortReadC) ? PPI2PortReadC() : 0, chipnum); + } + + result |= chip->read[port] & chip->in_mask[port]; + } + result |= chip->latch[port] & chip->out_mask[port]; + + /* read special port 2 signals */ + if (port == 2) + ppi8255_get_handshake_signals(chip, &result); + + return result; +} + +UINT8 ppi8255_r(INT32 which, INT32 offset) +{ + ppi8255 *chip = &chips[which]; + UINT8 result = 0; + + offset %= 4; + + switch(offset) + { + case 0: /* Port A read */ + case 1: /* Port B read */ + case 2: /* Port C read */ + result = ppi8255_read_port(chip, offset, which); + break; + + case 3: /* Control word */ + result = 0xFF; + break; + } + + return result; +} + +static void set_mode(INT32 which, INT32 data, INT32 call_handlers) +{ + ppi8255 *chip = &chips[which]; + INT32 i; + + /* parse out mode */ + chip->groupA_mode = (data >> 5) & 3; + chip->groupB_mode = (data >> 2) & 1; + chip->portA_dir = (data >> 4) & 1; + chip->portB_dir = (data >> 1) & 1; + chip->portCH_dir = (data >> 3) & 1; + chip->portCL_dir = (data >> 0) & 1; + + /* normalize groupA_mode */ + if (chip->groupA_mode == 3) + chip->groupA_mode = 2; + + /* Port A direction */ + if (chip->portA_dir) + chip->in_mask[0] = 0xFF, chip->out_mask[0] = 0x00; /* input */ + else + chip->in_mask[0] = 0x00, chip->out_mask[0] = 0xFF; /* output */ + + /* Port B direction */ + if (chip->portB_dir) + chip->in_mask[1] = 0xFF, chip->out_mask[1] = 0x00; /* input */ + else + chip->in_mask[1] = 0x00, chip->out_mask[1] = 0xFF; /* output */ + + /* Port C upper direction */ + if (chip->portCH_dir) + chip->in_mask[2] = 0xF0, chip->out_mask[2] = 0x00; /* input */ + else + chip->in_mask[2] = 0x00, chip->out_mask[2] = 0xF0; /* output */ + + /* Port C lower direction */ + if (chip->portCL_dir) + chip->in_mask[2] |= 0x0F; /* input */ + else + chip->out_mask[2] |= 0x0F; /* output */ + + /* now depending on the group modes, certain Port C lines may be replaced + * with varying control signals */ + switch(chip->groupA_mode) + { + case 0: /* Group A mode 0 */ + /* no changes */ + break; + + case 1: /* Group A mode 1 */ + /* bits 5-3 are reserved by Group A mode 1 */ + chip->in_mask[2] &= ~0x38; + chip->out_mask[2] &= ~0x38; + break; + + case 2: /* Group A mode 2 */ + /* bits 7-3 are reserved by Group A mode 2 */ + chip->in_mask[2] &= ~0xF8; + chip->out_mask[2] &= ~0xF8; + break; + } + + switch(chip->groupB_mode) + { + case 0: /* Group B mode 0 */ + /* no changes */ + break; + + case 1: /* Group B mode 1 */ + /* bits 2-0 are reserved by Group B mode 1 */ + chip->in_mask[2] &= ~0x07; + chip->out_mask[2] &= ~0x07; + break; + } + + /* KT: 25-Dec-99 - 8255 resets latches when mode set */ + chip->latch[0] = chip->latch[1] = chip->latch[2] = 0; + + if (call_handlers) + { + for (i = 0; i < 3; i++) + ppi8255_write_port(chip, i, which); + } +} + +void ppi8255_w(INT32 which, INT32 offset, UINT8 data) +{ + ppi8255 *chip = &chips[which]; + + offset %= 4; + + switch( offset ) + { + case 0: /* Port A write */ + case 1: /* Port B write */ + case 2: /* Port C write */ + chip->latch[offset] = data; + ppi8255_write_port(chip, offset, which); + + switch(offset) + { + case 0: + if (!chip->portA_dir && (chip->groupA_mode != 0)) + { + chip->obf_a = 1; + ppi8255_write_port(chip, 2, which); + } + break; + + case 1: + if (!chip->portB_dir && (chip->groupB_mode != 0)) + { + chip->obf_b = 1; + ppi8255_write_port(chip, 2, which); + } + break; + } + break; + + case 3: /* Control word */ + if (data & 0x80) + { + set_mode(which, data & 0x7f, 1); + } + else + { + /* bit set/reset */ + INT32 bit; + + bit = (data >> 1) & 0x07; + + if (data & 1) + chip->latch[2] |= (1<latch[2] &= ~(1<0;) + { + char b = *buf; + char c = *cmd; + + if ((b==0) || (c==0)) + return (b==c); + + switch ( c ) + { + case '0': + case '1': + if (b != c) return 0; + case 'X': + case 'x': + buf++; + len--; + cmd++; + break; + + case '*': + c = cmd[1]; + switch( c ) + { + case '0': + case '1': + if (b == c) { cmd++; } + else { buf++; len--; } + break; + default: return 0; + } + } + } + return (*cmd==0); +} + +INT32 EEPROMAvailable() +{ + return neeprom_available; +} + +void EEPROMInit(const eeprom_interface *interface) +{ + intf = interface; + + if ((1 << intf->address_bits) * intf->data_bits / 8 > MEMORY_SIZE) + { + bprintf(0, _T("EEPROM larger than eeprom allows")); + } + + memset(eeprom_data,0xff,(1 << intf->address_bits) * intf->data_bits / 8); + serial_count = 0; + latch = 0; + reset_line = EEPROM_ASSERT_LINE; + clock_line = EEPROM_ASSERT_LINE; + eeprom_read_address = 0; + sending = 0; + if (intf->cmd_unlock) locked = 1; + else locked = 0; + + char output[128]; + sprintf (output, "config\\games\\%s.nv", BurnDrvGetTextA(DRV_NAME)); + + neeprom_available = 0; + + INT32 len = ((1 << intf->address_bits) * (intf->data_bits >> 3)) & (MEMORY_SIZE-1); + + FILE *fz = fopen(output, "rb"); + if (fz != NULL) { + neeprom_available = 1; + fread (eeprom_data, len, 1, fz); + fclose (fz); + } +} + +void EEPROMExit() +{ + char output[128]; + sprintf (output, "config\\games\\%s.nv", BurnDrvGetTextA(DRV_NAME)); + + neeprom_available = 0; + + INT32 len = ((1 << intf->address_bits) * (intf->data_bits >> 3)) & (MEMORY_SIZE-1); + + FILE *fz = fopen(output, "wb"); + fwrite (eeprom_data, len, 1, fz); + fclose (fz); +} + +static void eeprom_write(INT32 bit) +{ + if (serial_count >= SERIAL_BUFFER_LENGTH-1) + { + bprintf(0, _T("error: EEPROM serial buffer overflow\n")); + return; + } + + serial_buffer[serial_count++] = (bit ? '1' : '0'); + serial_buffer[serial_count] = 0; + + if ( (serial_count > intf->address_bits) && + eeprom_command_match((char*)serial_buffer,intf->cmd_read,strlen((char*)serial_buffer)-intf->address_bits) ) + { + INT32 i,address; + + address = 0; + for (i = serial_count-intf->address_bits;i < serial_count;i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + if (intf->data_bits == 16) + eeprom_data_bits = (eeprom_data[2*address+0] << 8) + eeprom_data[2*address+1]; + else + eeprom_data_bits = eeprom_data[address]; + eeprom_read_address = address; + eeprom_clock_count = 0; + sending = 1; + serial_count = 0; + } + else if ( (serial_count > intf->address_bits) && + eeprom_command_match((char*)serial_buffer,intf->cmd_erase,strlen((char*)serial_buffer)-intf->address_bits) ) + { + INT32 i,address; + + address = 0; + for (i = serial_count-intf->address_bits;i < serial_count;i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + + if (locked == 0) + { + if (intf->data_bits == 16) + { + eeprom_data[2*address+0] = 0xff; + eeprom_data[2*address+1] = 0xff; + } + else + eeprom_data[address] = 0xff; + } + else + serial_count = 0; + } + else if ( (serial_count > (intf->address_bits + intf->data_bits)) && + eeprom_command_match((char*)serial_buffer,intf->cmd_write,strlen((char*)serial_buffer)-(intf->address_bits + intf->data_bits)) ) + { + INT32 i,address,data; + + address = 0; + for (i = serial_count-intf->data_bits-intf->address_bits;i < (serial_count-intf->data_bits);i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + data = 0; + for (i = serial_count-intf->data_bits;i < serial_count;i++) + { + data <<= 1; + if (serial_buffer[i] == '1') data |= 1; + } + + if (locked == 0) + { + if (intf->data_bits == 16) + { + eeprom_data[2*address+0] = data >> 8; + eeprom_data[2*address+1] = data & 0xff; + } + else + eeprom_data[address] = data; + } + else + serial_count = 0; + } + else if ( eeprom_command_match((char*)serial_buffer,intf->cmd_lock,strlen((char*)serial_buffer)) ) + { + locked = 1; + serial_count = 0; + } + else if ( eeprom_command_match((char*)serial_buffer,intf->cmd_unlock,strlen((char*)serial_buffer)) ) + { + locked = 0; + serial_count = 0; + } +} + +void EEPROMReset() +{ + serial_count = 0; + sending = 0; + reset_delay = intf->reset_delay; +} + +void EEPROMWriteBit(INT32 bit) +{ + latch = bit; +} + +INT32 EEPROMRead() +{ + INT32 res; + + if (sending) + res = (eeprom_data_bits >> intf->data_bits) & 1; + else + { + if (reset_delay > 0) + { + /* this is needed by wbeachvl */ + reset_delay--; + res = 0; + } + else + res = 1; + } + + return res; +} + +void EEPROMSetCSLine(INT32 state) +{ + reset_line = state; + + if (reset_line != EEPROM_CLEAR_LINE) + EEPROMReset(); +} + +void EEPROMSetClockLine(INT32 state) +{ + if (state == EEPROM_PULSE_LINE || (clock_line == EEPROM_CLEAR_LINE && state != EEPROM_CLEAR_LINE)) + { + if (reset_line == EEPROM_CLEAR_LINE) + { + if (sending) + { + if (eeprom_clock_count == intf->data_bits && intf->enable_multi_read) + { + eeprom_read_address = (eeprom_read_address + 1) & ((1 << intf->address_bits) - 1); + if (intf->data_bits == 16) + eeprom_data_bits = (eeprom_data[2*eeprom_read_address+0] << 8) + eeprom_data[2*eeprom_read_address+1]; + else + eeprom_data_bits = eeprom_data[eeprom_read_address]; + eeprom_clock_count = 0; + } + eeprom_data_bits = (eeprom_data_bits << 1) | 1; + eeprom_clock_count++; + } + else + eeprom_write(latch); + } + } + + clock_line = state; +} + +void EEPROMFill(const UINT8 *data, INT32 offset, INT32 length) +{ + memcpy(eeprom_data + offset, data, length); +} + +void EEPROMScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (nAction & ACB_DRIVER_DATA) { + + if (pnMin && *pnMin < 0x020902) { + *pnMin = 0x029705; + } + + memset(&ba, 0, sizeof(ba)); + ba.Data = serial_buffer; + ba.nLen = SERIAL_BUFFER_LENGTH; + ba.szName = "Serial Buffer"; + BurnAcb(&ba); + + SCAN_VAR(serial_count); + SCAN_VAR(eeprom_data_bits); + SCAN_VAR(eeprom_read_address); + SCAN_VAR(eeprom_clock_count); + SCAN_VAR(latch); + SCAN_VAR(reset_line); + SCAN_VAR(clock_line); + SCAN_VAR(sending); + SCAN_VAR(locked); + SCAN_VAR(reset_delay); + } + +// if (nAction & ACB_NVRAM) { +// +// if (pnMin && (nAction & ACB_TYPEMASK) == ACB_NVRAM) { +// *pnMin = 0x02705; +// } +// +// memset(&ba, 0, sizeof(ba)); +// ba.Data = eeprom_data; +// ba.nLen = MEMORY_SIZE; +// ba.szName = "EEPROM memory"; +// BurnAcb(&ba); +// } +} diff --git a/src/burn/devices/eeprom.h b/src/burn/devices/eeprom.h new file mode 100644 index 00000000..17a6fe13 --- /dev/null +++ b/src/burn/devices/eeprom.h @@ -0,0 +1,56 @@ + +typedef struct _eeprom_interface eeprom_interface; +struct _eeprom_interface +{ + INT32 address_bits; /* EEPROM has 2^address_bits cells */ + INT32 data_bits; /* every cell has this many bits (8 or 16) */ + const char *cmd_read; /* read command string, e.g. "0110" */ + const char *cmd_write; /* write command string, e.g. "0111" */ + const char *cmd_erase; /* erase command string, or 0 if n/a */ + const char *cmd_lock; /* lock command string, or 0 if n/a */ + const char *cmd_unlock; /* unlock command string, or 0 if n/a */ + INT32 enable_multi_read; /* set to 1 to enable multiple values to be read from one read command */ + INT32 reset_delay; /* number of times eeprom_read_bit() should return 0 after a reset, */ + /* before starting to return 1. */ +}; + +// default for most in fba +const eeprom_interface eeprom_interface_93C46 = +{ + 6, // address bits 6 + 16, // data bits 16 + "*110", // read 1 10 aaaaaa + "*101", // write 1 01 aaaaaa dddddddddddddddd + "*111", // erase 1 11 aaaaaa + "*10000xxxx", // lock 1 00 00xxxx + "*10011xxxx", // unlock 1 00 11xxxx + 1, + 0 +}; + +#define EEPROM_CLEAR_LINE 0 +#define EEPROM_ASSERT_LINE 1 +#define EEPROM_PULSE_LINE 2 + +void EEPROMInit(const eeprom_interface *interface); +void EEPROMReset(); +void EEPROMExit(); + +INT32 EEPROMAvailable(); // are we loading an eeprom file? + +INT32 EEPROMRead(); + +// Write each individually +void EEPROMWriteBit(INT32 bit); +void EEPROMSetCSLine(INT32 state); +void EEPROMSetClockLine(INT32 state); + +// Or all at once +#define EEPROMWrite(clock, cs, bit) \ + EEPROMWriteBit(bit); \ + EEPROMSetCSLine(cs ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE); \ + EEPROMSetClockLine(clock ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE) + +void EEPROMFill(const UINT8 *data, INT32 offset, INT32 length); + +void EEPROMScan(INT32 nAction, INT32* pnMin); diff --git a/src/burn/devices/pandora.cpp b/src/burn/devices/pandora.cpp new file mode 100644 index 00000000..ff807393 --- /dev/null +++ b/src/burn/devices/pandora.cpp @@ -0,0 +1,122 @@ +// Kaneko Pandora module + +#include "tiles_generic.h" + +static UINT16 *pandora_temp = NULL; +static UINT8 *pandora_ram = NULL; +static UINT8 *pandora_gfx = NULL; +static INT32 pandora_clear; +static INT32 pandora_xoffset; +static INT32 pandora_yoffset; +static INT32 pandora_color_offset; +INT32 pandora_flipscreen; + +void pandora_set_clear(INT32 clear) +{ + pandora_clear = clear; +} + +void pandora_update(UINT16 *dest) +{ + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + if (pandora_temp[i]) { + dest[i] = pandora_temp[i] & 0x3ff; + } + } +} + +void pandora_buffer_sprites() +{ + INT32 sx=0, sy=0, x=0, y=0; + + if (pandora_clear) memset (pandora_temp, 0, nScreenWidth * nScreenHeight * sizeof(UINT16)); + + for (INT32 offs = 0; offs < 0x1000; offs += 8) + { + INT32 attr = pandora_ram[offs+7]; + INT32 code = pandora_ram[offs+6] + ((attr & 0x3f) << 8); + INT32 dy = pandora_ram[offs+5]; + INT32 dx = pandora_ram[offs+4]; + INT32 color = pandora_ram[offs+3]; + INT32 flipy = attr & 0x40; + INT32 flipx = attr & 0x80; + + if (color & 1) dx |= 0x100; + if (color & 2) dy |= 0x100; + + if (color & 4) + { + x += dx; + y += dy; + } + else + { + x = dx; + y = dy; + } + + if (pandora_flipscreen) + { + sx = 240 - x; + sy = 240 - y; + flipx = !flipx; + flipy = !flipy; + } + else + { + sx = x; + sy = y; + } + + sx = (sx + pandora_xoffset) & 0x1ff; + sy = (sy + pandora_yoffset) & 0x1ff; + if (sx & 0x100) sx -= 0x200; + if (sy & 0x100) sy -= 0x200; + + if (sx >= nScreenWidth || sx < -15) continue; + if (sy >= nScreenHeight || sy < -15) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx); + } else { + Render16x16Tile_Mask_FlipY_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx); + } else { + Render16x16Tile_Mask_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx); + } + } + } +} + +// must be called after GenericTilesInit() +void pandora_init(UINT8 *ram, UINT8 *gfx, INT32 color_offset, INT32 x, INT32 y) +{ + pandora_ram = ram; + pandora_xoffset = x; + pandora_yoffset = y; + pandora_gfx = gfx; + pandora_color_offset = color_offset; + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth); + } else { + BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight); + } + + pandora_temp = (UINT16*)malloc(nScreenWidth * nScreenHeight * sizeof(UINT16)); + pandora_clear = 1; +} + +void pandora_exit() +{ + if (pandora_temp) { + free (pandora_temp); + pandora_temp = NULL; + } + + pandora_ram = pandora_gfx = NULL; +} diff --git a/src/burn/devices/pandora.h b/src/burn/devices/pandora.h new file mode 100644 index 00000000..5853c467 --- /dev/null +++ b/src/burn/devices/pandora.h @@ -0,0 +1,7 @@ +extern INT32 pandora_flipscreen; + +void pandora_set_clear(INT32 clear); +void pandora_update(UINT16 *dest); +void pandora_buffer_sprites(); +void pandora_init(UINT8 *ram, UINT8 *gfx, INT32 color_offset, INT32 x, INT32 y); +void pandora_exit(); diff --git a/src/burn/devices/seibusnd.cpp b/src/burn/devices/seibusnd.cpp new file mode 100644 index 00000000..0cd38bfa --- /dev/null +++ b/src/burn/devices/seibusnd.cpp @@ -0,0 +1,525 @@ +// +// FB Alpha Seibu sound hardware module +// +// Games using this hardware: +// +// Dead Angle 2x YM2203 + adpcm -- not implemented +// +// Dynamite Duke 1x YM3812 + 1x M6295 +// Toki 1x YM3812 + 1x M6295 +// Raiden 1x YM3812 + 1x M6295 +// Blood Brothers 1x YM3812 + 1x M6295 +// D-Con 1x YM3812 + 1x M6295 +// Legionnaire 1x YM3812 + 1x M6295 +// +// SD Gundam PSK 1x YM2151 + 1x M6295 +// Raiden II 1x YM2151 + 2x M6295 +// Raiden DX 1x YM2151 + 2x M6295 +// Zero Team 1x YM2151 + 2x M6295 +// +// Cross Shooter 1x YM2151 + ? +// Cabal 1x YM2151 + adpcm -- not implemented +// + +#include "burnint.h" +#include "burn_ym3812.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "msm6295.h" +#include "bitswap.h" + +static UINT8 main2sub[2]; +static UINT8 sub2main[2]; +static INT32 main2sub_pending; +static INT32 sub2main_pending; +static INT32 SeibuSoundBank; + +UINT8 *SeibuZ80DecROM; +UINT8 *SeibuZ80ROM; +UINT8 *SeibuZ80RAM; +INT32 seibu_coin_input; + +static INT32 seibu_sndcpu_frequency; +static INT32 seibu_snd_type; +static INT32 is_sdgndmps = 0; + +enum +{ + VECTOR_INIT, + RST10_ASSERT, + RST10_CLEAR, + RST18_ASSERT, + RST18_CLEAR +}; + +static void update_irq_lines(INT32 param) +{ + static INT32 irq1,irq2; + + switch(param) + { + case VECTOR_INIT: + irq1 = irq2 = 0xff; + break; + + case RST10_ASSERT: + irq1 = 0xd7; + break; + + case RST10_CLEAR: + irq1 = 0xff; + break; + + case RST18_ASSERT: + irq2 = 0xdf; + break; + + case RST18_CLEAR: + irq2 = 0xff; + break; + } + + if ((irq1 & irq2) == 0xff) { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } else { + if (irq2 == 0xdf) { + ZetSetVector(irq1 & irq2); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + } +} + +UINT8 seibu_main_word_read(INT32 offset) +{ + offset = (offset >> 1) & 7; + + switch (offset) + { + case 2: + case 3: + return sub2main[offset-2]; + case 5: + return main2sub_pending ? 1 : 0; + default: + return 0xff; + } +} + +void seibu_main_word_write(INT32 offset, UINT8 data) +{ + offset = (offset >> 1) & 7; + + switch (offset) + { + case 0: + case 1: + main2sub[offset] = data; + break; + + case 4: + if (is_sdgndmps) update_irq_lines(RST10_ASSERT); + update_irq_lines(RST18_ASSERT); + break; + + case 6: + sub2main_pending = 0; + main2sub_pending = 1; + break; + + default: + break; + } +} + +void seibu_sound_mustb_write_word(INT32 /*offset*/, UINT8 data) +{ + main2sub[0] = data & 0xff; + main2sub[1] = data >> 8; + + update_irq_lines(RST18_ASSERT); +} + +static void seibu_z80_bank(INT32 data) +{ + SeibuSoundBank = data & 1; + + ZetMapArea(0x8000, 0xffff, 0, SeibuZ80ROM + 0x10000 + (data & 1) * 0x8000); + ZetMapArea(0x8000, 0xffff, 2, SeibuZ80ROM + 0x10000 + (data & 1) * 0x8000); +} + +void __fastcall seibu_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x4000: + main2sub_pending = 0; + sub2main_pending = 1; + return; + + case 0x4001: + update_irq_lines(VECTOR_INIT); + return; + + case 0x4002: + // rst10 ack (unused) + return; + + case 0x4003: + update_irq_lines(RST18_CLEAR); + return; + + case 0x4007: + seibu_z80_bank(data); + return; + + case 0x4008: + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Write(0, data); + return; + + case 1: + BurnYM2151SelectRegister(data); + return; + + case 2: + BurnYM2203Write(0, 0, data); + return; + } + return; + + case 0x4009: + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Write(1, data); + return; + + case 1: + BurnYM2151WriteRegister(data); + return; + + case 2: + BurnYM2203Write(0, 1, data); + return; + } + return; + + case 0x4018: + case 0x4019: + sub2main[address & 1] = data; + return; + + case 0x401b: + // coin counters + return; + + case 0x6000: + MSM6295Command(0, data); + return; + + case 0x6002: + if (seibu_snd_type & 4) MSM6295Command(1, data); + return; + + // type 2 + case 0x6008: + case 0x6009: + if (seibu_snd_type == 2) BurnYM2203Write(1, address & 1, data); + return; + } +} + +UINT8 __fastcall seibu_sound_read(UINT16 address) +{ + switch (address) + { + case 0x4008: + switch (seibu_snd_type & 3) + { + case 0: + return BurnYM3812Read(0); + + case 1: + return BurnYM2151ReadStatus(); + + case 2: + return BurnYM2203Read(0, 0); + } + return 0; + + case 0x4009: { + if (seibu_snd_type < 2) return 0; + return BurnYM2203Read(0, 1); + } + + case 0x4010: + case 0x4011: + return main2sub[address & 1]; + + case 0x4012: + return sub2main_pending ? 1 : 0; + + case 0x4013: + return seibu_coin_input; + + case 0x6000: + return MSM6295ReadStatus(0); + + case 0x6002: + if (seibu_snd_type & 4) return MSM6295ReadStatus(0); + } + + return 0; +} + +static UINT8 decrypt_data(INT32 a,INT32 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0); + + return src; +} + +static UINT8 decrypt_opcode(INT32 a,INT32 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if (~BIT(a,13) & BIT(a,12)) src ^= 0x20; + if (~BIT(a,6) & BIT(a,1)) src ^= 0x10; + if (~BIT(a,12) & BIT(a,2)) src ^= 0x08; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0); + if (BIT(a,12) & BIT(a,9)) src = BITSWAP08(src,7,6,4,5,3,2,1,0); + if (BIT(a,11) & ~BIT(a,6)) src = BITSWAP08(src,6,7,5,4,3,2,1,0); + + return src; +} + +static void seibu_sound_decrypt(INT32 length) +{ + for (INT32 i = 0; i < length; i++) + { + UINT8 src = SeibuZ80ROM[i]; + + SeibuZ80ROM[i] = decrypt_data(i,src); + SeibuZ80DecROM[i] = decrypt_opcode(i,src); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / seibu_sndcpu_frequency; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + update_irq_lines(RST10_ASSERT); + } else { + update_irq_lines(RST10_CLEAR); + } +} + +static void Drv2151FMIRQHandler(INT32 nStatus) +{ + DrvFMIRQHandler(0, nStatus); +} + +static double Drv2203GetTime() +{ + return (double)ZetTotalCycles() / seibu_sndcpu_frequency; +} + +void seibu_sound_reset() +{ + ZetOpen(0); + ZetReset(); + update_irq_lines(VECTOR_INIT); + ZetClose(); + + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Reset(); + break; + + case 1: + BurnYM2151Reset(); + break; + + case 2: + BurnYM2203Reset(); + break; + } + + MSM6295Reset(0); + if (seibu_snd_type & 4) MSM6295Reset(1); + + memset (main2sub, 0, 2); + memset (sub2main, 0, 2); + main2sub_pending = 0; + sub2main_pending = 0; + + seibu_coin_input = 0; + SeibuSoundBank = 0; +} + +void seibu_sound_init(INT32 type, INT32 len, INT32 freq0 /*cpu*/, INT32 freq1 /*ym*/, INT32 freq2 /*oki*/) +{ + seibu_snd_type = type; + + if (len && SeibuZ80DecROM != NULL) { + seibu_sound_decrypt(len); + } else { + SeibuZ80DecROM = SeibuZ80ROM; + } + + seibu_sndcpu_frequency = freq0; + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x1fff, 0, SeibuZ80ROM); + ZetMapArea(0x0000, 0x1fff, 2, SeibuZ80DecROM, SeibuZ80ROM); + ZetMapArea(0x2000, 0x27ff, 0, SeibuZ80RAM); + ZetMapArea(0x2000, 0x27ff, 1, SeibuZ80RAM); + ZetMapArea(0x2000, 0x27ff, 2, SeibuZ80RAM); + ZetSetWriteHandler(seibu_sound_write); + ZetSetReadHandler(seibu_sound_read); + ZetMemEnd(); + ZetClose(); + + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Init(freq1, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(freq0); + break; + + case 1: + BurnYM2151Init(freq1, 100.0); + BurnYM2151SetIrqHandler(&Drv2151FMIRQHandler); + break; + + case 2: + BurnYM2203Init(2, freq1, DrvFMIRQHandler, DrvSynchroniseStream, Drv2203GetTime, 0); + BurnTimerAttachZet(freq0); + break; + } + + MSM6295Init(0, freq2, 100.0, 1); + if (seibu_snd_type & 4) MSM6295Init(1, freq2, 100.0, 1); + + // init kludge for sdgndmps + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "sdgndmps")) { + is_sdgndmps = 1; + } +} + +void seibu_sound_exit() +{ + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Exit(); + break; + + case 1: + BurnYM2151Exit(); + break; + + case 2: + BurnYM2203Exit(); + break; + } + + MSM6295Exit(0); + if (seibu_snd_type & 4) MSM6295Exit(1); + + ZetExit(); + + MSM6295ROM = NULL; + + SeibuZ80DecROM = NULL; + SeibuZ80ROM = NULL; + SeibuZ80RAM = NULL; + seibu_sndcpu_frequency = 0; + is_sdgndmps = 0; +} + +void seibu_sound_update(INT16 *pbuf, INT32 nLen) +{ + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Update(pbuf, nLen); + break; + + case 1: + BurnYM2151Render(pbuf, nLen); + break; + + case 2: + BurnYM2203Update(pbuf, nLen); + break; + } + + if (seibu_snd_type & 4) + MSM6295Render(1, pbuf, nLen); + MSM6295Render(0, pbuf, nLen); +} + +void seibu_sound_scan(INT32 *pnMin, INT32 nAction) +{ + if (nAction & ACB_VOLATILE) + { + ZetScan(nAction); + + switch (seibu_snd_type & 3) + { + case 0: + BurnYM3812Scan(nAction, pnMin); + break; + + case 1: + BurnYM2203Scan(nAction, pnMin); + break; + + case 2: + BurnYM2151Scan(nAction); + break; + } + + MSM6295Scan(0, nAction); + if (seibu_snd_type & 4) { + MSM6295Scan(1, nAction); + } + + SCAN_VAR(main2sub[0]); + SCAN_VAR(main2sub[1]); + SCAN_VAR(sub2main[0]); + SCAN_VAR(sub2main[1]); + SCAN_VAR(main2sub_pending); + SCAN_VAR(sub2main_pending); + SCAN_VAR(SeibuSoundBank); + } + + if (nAction & ACB_WRITE) + { + ZetOpen(0); + seibu_z80_bank(SeibuSoundBank); + ZetClose(); + } +} + diff --git a/src/burn/devices/seibusnd.h b/src/burn/devices/seibusnd.h new file mode 100644 index 00000000..2db8c401 --- /dev/null +++ b/src/burn/devices/seibusnd.h @@ -0,0 +1,32 @@ +#include "burn_ym3812.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +extern UINT8 *SeibuZ80DecROM; +extern UINT8 *SeibuZ80ROM; +extern UINT8 *SeibuZ80RAM; + +extern INT32 seibu_coin_input; + +unsigned char seibu_main_word_read(INT32 offset); +void seibu_main_word_write(INT32 offset, UINT8 data); +void seibu_sound_mustb_write_word(INT32 offset, UINT8 data); + +void seibu_sound_reset(); + +void seibu_sound_update(INT16 *pbuf, INT32 nLen); + +/* + Type 0 - YM3812 + Type 1 - YM2151 + Type 2 - YM2203 + + all init a single oki6295 + add 4 to init a second oki6295 +*/ + +void seibu_sound_init(INT32 type, INT32 encrypted_len, INT32 freq0 /*cpu*/, INT32 freq1 /*ym*/, INT32 freq2 /*oki*/); +void seibu_sound_exit(); + +void seibu_sound_scan(INT32 *pnMin, INT32 nAction); diff --git a/src/burn/devices/timekpr.cpp b/src/burn/devices/timekpr.cpp new file mode 100644 index 00000000..7a9ed682 --- /dev/null +++ b/src/burn/devices/timekpr.cpp @@ -0,0 +1,331 @@ +#include "burnint.h" +#include "time.h" +#include "timekpr.h" + +typedef struct +{ + UINT8 control; + UINT8 seconds; + UINT8 minutes; + UINT8 hours; + UINT8 day; + UINT8 date; + UINT8 month; + UINT8 year; + UINT8 century; + UINT8 *data; + INT32 type; + INT32 size; + INT32 offset_control; + INT32 offset_seconds; + INT32 offset_minutes; + INT32 offset_hours; + INT32 offset_day; + INT32 offset_date; + INT32 offset_month; + INT32 offset_year; + INT32 offset_century; + INT32 offset_flags; +} timekeeper_chip; + +static timekeeper_chip Chip; + +static INT32 AllocatedOwnDataArea = 0; + +#define MASK_SECONDS ( 0x7f ) +#define MASK_MINUTES ( 0x7f ) +#define MASK_HOURS ( 0x3f ) +#define MASK_DAY ( 0x07 ) +#define MASK_DATE ( 0x3f ) +#define MASK_MONTH ( 0x1f ) +#define MASK_YEAR ( 0xff ) +#define MASK_CENTURY ( 0xff ) + +#define CONTROL_W ( 0x80 ) +#define CONTROL_R ( 0x40 ) +#define CONTROL_S ( 0x20 ) /* not emulated */ +#define CONTROL_CALIBRATION ( 0x1f ) /* not emulated */ + +#define SECONDS_ST ( 0x80 ) + +#define DAY_FT ( 0x40 ) /* not emulated */ +#define DAY_CEB ( 0x20 ) /* M48T58 */ +#define DAY_CB ( 0x10 ) /* M48T58 */ + +#define DATE_BLE ( 0x80 ) /* M48T58: not emulated */ +#define DATE_BL ( 0x40 ) /* M48T58: not emulated */ + +#define FLAGS_BL ( 0x10 ) /* MK48T08: not emulated */ + +static inline UINT8 make_bcd(UINT8 data) +{ + return ( ( ( data / 10 ) % 10 ) << 4 ) + ( data % 10 ); +} + +static inline UINT8 from_bcd(UINT8 data) +{ + return ( ( ( data >> 4 ) & 15 ) * 10 ) + ( data & 15 ); +} + +static INT32 inc_bcd( UINT8 *data, INT32 mask, INT32 min, INT32 max ) +{ + INT32 bcd; + INT32 carry; + + bcd = ( *( data ) + 1 ) & mask; + carry = 0; + + if( ( bcd & 0x0f ) > 9 ) + { + bcd &= 0xf0; + bcd += 0x10; + if( bcd > max ) + { + bcd = min; + carry = 1; + } + } + + *( data ) = ( *( data ) & ~mask ) | ( bcd & mask ); + return carry; +} + +static void counter_to_ram(UINT8 *data, INT32 offset, INT32 counter) +{ + if( offset >= 0 ) + { + data[ offset ] = counter; + } +} + +static void counters_to_ram() +{ + counter_to_ram( Chip.data, Chip.offset_control, Chip.control ); + counter_to_ram( Chip.data, Chip.offset_seconds, Chip.seconds ); + counter_to_ram( Chip.data, Chip.offset_minutes, Chip.minutes ); + counter_to_ram( Chip.data, Chip.offset_hours, Chip.hours ); + counter_to_ram( Chip.data, Chip.offset_day, Chip.day ); + counter_to_ram( Chip.data, Chip.offset_date, Chip.date ); + counter_to_ram( Chip.data, Chip.offset_month, Chip.month ); + counter_to_ram( Chip.data, Chip.offset_year, Chip.year ); + counter_to_ram( Chip.data, Chip.offset_century, Chip.century ); +} + +static INT32 counter_from_ram(UINT8 *data, INT32 offset) +{ + if( offset >= 0 ) + { + return data[ offset ]; + } + return 0; +} + +static void counters_from_ram() +{ + Chip.control = counter_from_ram( Chip.data, Chip.offset_control ); + Chip.seconds = counter_from_ram( Chip.data, Chip.offset_seconds ); + Chip.minutes = counter_from_ram( Chip.data, Chip.offset_minutes ); + Chip.hours = counter_from_ram( Chip.data, Chip.offset_hours ); + Chip.day = counter_from_ram( Chip.data, Chip.offset_day ); + Chip.date = counter_from_ram( Chip.data, Chip.offset_date ); + Chip.month = counter_from_ram( Chip.data, Chip.offset_month ); + Chip.year = counter_from_ram( Chip.data, Chip.offset_year ); + Chip.century = counter_from_ram( Chip.data, Chip.offset_century ); +} + +UINT8 TimeKeeperRead(UINT32 offset) +{ + return Chip.data[offset]; +} + +void TimeKeeperWrite(INT32 offset, UINT8 data) +{ + if( offset == Chip.offset_control ) + { + if( ( Chip.control & CONTROL_W ) != 0 && + ( data & CONTROL_W ) == 0 ) + { + counters_from_ram(); + } + Chip.control = data; + } + else if( Chip.type == TIMEKEEPER_M48T58 && offset == Chip.offset_day ) + { + Chip.day = ( Chip.day & ~DAY_CEB ) | ( data & DAY_CEB ); + } + else if( Chip.type == TIMEKEEPER_M48T58 && offset == Chip.offset_date ) + { + data &= ~DATE_BL; + } + else if( Chip.type == TIMEKEEPER_MK48T08 && offset == Chip.offset_flags ) + { + data &= ~FLAGS_BL; + } + + Chip.data[ offset ] = data; +} + +void TimeKeeperTick() +{ + INT32 carry; + + if( ( Chip.seconds & SECONDS_ST ) != 0 || + ( Chip.control & CONTROL_W ) != 0 ) + { + return; + } + + carry = inc_bcd( &Chip.seconds, MASK_SECONDS, 0x00, 0x59 ); + if( carry ) + { + carry = inc_bcd( &Chip.minutes, MASK_MINUTES, 0x00, 0x59 ); + } + if( carry ) + { + carry = inc_bcd( &Chip.hours, MASK_HOURS, 0x00, 0x23 ); + } + + if( carry ) + { + UINT8 month; + UINT8 year; + UINT8 maxdays; + static const UINT8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 }; + + inc_bcd( &Chip.day, MASK_DAY, 0x01, 0x07 ); + + month = from_bcd( Chip.month ); + year = from_bcd( Chip.year ); + + if( month == 2 && ( year % 4 ) == 0 ) + { + maxdays = 0x29; + } + else if( month >= 1 && month <= 12 ) + { + maxdays = daysinmonth[ month - 1 ]; + } + else + { + maxdays = 0x31; + } + + carry = inc_bcd( &Chip.date, MASK_DATE, 0x01, maxdays ); + } + if( carry ) + { + carry = inc_bcd( &Chip.month, MASK_MONTH, 0x01, 0x12 ); + } + if( carry ) + { + carry = inc_bcd( &Chip.year, MASK_YEAR, 0x00, 0x99 ); + } + if( carry ) + { + carry = inc_bcd( &Chip.century, MASK_CENTURY, 0x00, 0x99 ); + if( Chip.type == TIMEKEEPER_M48T58 && ( Chip.day & DAY_CEB ) != 0 ) + { + Chip.day ^= DAY_CB; + } + } + + if( ( Chip.control & CONTROL_R ) == 0 ) + { + counters_to_ram(); + } +} + +void TimeKeeperInit(INT32 type, UINT8 *data) +{ + time_t rawtime; + struct tm *timeinfo; + + Chip.type = type; + + switch( Chip.type ) + { + case TIMEKEEPER_M48T02: + Chip.offset_control = 0x7f8; + Chip.offset_seconds = 0x7f9; + Chip.offset_minutes = 0x7fa; + Chip.offset_hours = 0x7fb; + Chip.offset_day = 0x7fc; + Chip.offset_date = 0x7fd; + Chip.offset_month = 0x7fe; + Chip.offset_year = 0x7ff; + Chip.offset_century = -1; + Chip.offset_flags = -1; + Chip.size = 0x800; + break; + case TIMEKEEPER_M48T58: + Chip.offset_control = 0x1ff8; + Chip.offset_seconds = 0x1ff9; + Chip.offset_minutes = 0x1ffa; + Chip.offset_hours = 0x1ffb; + Chip.offset_day = 0x1ffc; + Chip.offset_date = 0x1ffd; + Chip.offset_month = 0x1ffe; + Chip.offset_year = 0x1fff; + Chip.offset_century = -1; + Chip.offset_flags = -1; + Chip.size = 0x2000; + break; + case TIMEKEEPER_MK48T08: + Chip.offset_control = 0x1ff8; + Chip.offset_seconds = 0x1ff9; + Chip.offset_minutes = 0x1ffa; + Chip.offset_hours = 0x1ffb; + Chip.offset_day = 0x1ffc; + Chip.offset_date = 0x1ffd; + Chip.offset_month = 0x1ffe; + Chip.offset_year = 0x1fff; + Chip.offset_century = 0x1ff1; + Chip.offset_flags = 0x1ff0; + Chip.size = 0x2000; + break; + } + + if( data == NULL ) + { + data = (UINT8*)malloc(Chip.size); + memset(data, 0xff, Chip.size ); + AllocatedOwnDataArea = 1; + } + Chip.data = data; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + Chip.control = 0; + Chip.seconds = make_bcd(timeinfo->tm_sec); + Chip.minutes = make_bcd(timeinfo->tm_min); + Chip.hours = make_bcd(timeinfo->tm_hour); + Chip.day = make_bcd(timeinfo->tm_wday + 1 ); + Chip.date = make_bcd(timeinfo->tm_mday ); + Chip.month = make_bcd(timeinfo->tm_mon + 1 ); + Chip.year = make_bcd(timeinfo->tm_year % 100 ); + Chip.century = make_bcd(timeinfo->tm_year / 100 ); +} + +void TimeKeeperExit() +{ + if (AllocatedOwnDataArea) { + free (Chip.data); + Chip.data = NULL; + } + AllocatedOwnDataArea = 0; + memset(&Chip, 0, sizeof(Chip)); +} + +void TimeKeeperScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_NVRAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = Chip.data; + ba.nLen = Chip.size; + ba.szName = "Time Keeper RAM"; + BurnAcb(&ba); + } +} diff --git a/src/burn/devices/timekpr.h b/src/burn/devices/timekpr.h new file mode 100644 index 00000000..56915f3b --- /dev/null +++ b/src/burn/devices/timekpr.h @@ -0,0 +1,10 @@ +#define TIMEKEEPER_M48T58 ( 1 ) +#define TIMEKEEPER_M48T02 ( 2 ) +#define TIMEKEEPER_MK48T08 ( 3 ) + +UINT8 TimeKeeperRead(UINT32 offset); +void TimeKeeperWrite(INT32 offset, UINT8 data); +void TimeKeeperTick(); +void TimeKeeperInit(INT32 type, UINT8 *data); +void TimeKeeperExit(); +void TimeKeeperScan(INT32 nAction); diff --git a/src/burn/driver.h b/src/burn/driver.h new file mode 100644 index 00000000..e3185d59 --- /dev/null +++ b/src/burn/driver.h @@ -0,0 +1,79 @@ +/* + * For the MAME sound cores + */ + +#ifndef DRIVER_H +#define DRIVER_H + +#include +#include +#include +#include + +#if !defined (_WIN32) + #define __cdecl +#endif + +#ifndef INLINE + #define INLINE __inline static +#endif + +#define FBA + +typedef unsigned char UINT8; +typedef signed char INT8; +typedef unsigned short UINT16; +typedef signed short INT16; +typedef unsigned int UINT32; +typedef signed int INT32; +#ifdef _MSC_VER +typedef signed __int64 INT64; +typedef unsigned __int64 UINT64; +#else +__extension__ typedef unsigned long long UINT64; +__extension__ typedef long long INT64; +#endif +#define OSD_CPU_H + +/* OPN */ +#define HAS_YM2203 1 +#define HAS_YM2608 1 +#define HAS_YM2610 1 +#define HAS_YM2610B 1 +#define HAS_YM2612 1 +#define HAS_YM3438 1 +/* OPL */ +#define HAS_YM3812 1 +#define HAS_YM3526 1 +#define HAS_Y8950 1 + +enum { + CLEAR_LINE = 0, + ASSERT_LINE, + HOLD_LINE, + PULSE_LINE +}; + +#define timer_get_time() BurnTimerGetTime() + +#define READ8_HANDLER(name) UINT8 name(void) +#define WRITE8_HANDLER(name) void name(UINT8 data) + +#ifdef __cplusplus + extern "C" { +#endif + double BurnTimerGetTime(void); + + typedef UINT8 (*read8_handler)(UINT32 offset); + typedef void (*write8_handler)(UINT32 offset, UINT32 data); + + #ifdef MAME_USE_LOGERROR + void __cdecl logerror(char* szFormat, ...); + #else + #define logerror + #endif +#ifdef __cplusplus + } +#endif + +#endif /* DRIVER_H */ diff --git a/src/burn/drivers/capcom/cps.cpp b/src/burn/drivers/capcom/cps.cpp new file mode 100644 index 00000000..cc586546 --- /dev/null +++ b/src/burn/drivers/capcom/cps.cpp @@ -0,0 +1,1094 @@ +#include "cps.h" +// CPS (general) + +INT32 Cps = 0; // 1 = CPS1, 2 = CPS2, 3 = CPS Changer +INT32 Cps1Qs = 0; +INT32 Cps1Pic = 0; + +INT32 nCPS68KClockspeed = 0; +INT32 nCpsCycles = 0; // 68K Cycles per frame +INT32 nCpsZ80Cycles; + +UINT8 *CpsGfx =NULL; UINT32 nCpsGfxLen =0; // All the graphics +UINT8 *CpsRom =NULL; UINT32 nCpsRomLen =0; // Program Rom (as in rom) +UINT8 *CpsCode=NULL; UINT32 nCpsCodeLen=0; // Program Rom (decrypted) +UINT8 *CpsZRom=NULL; UINT32 nCpsZRomLen=0; // Z80 Roms +INT8 *CpsQSam=NULL; UINT32 nCpsQSamLen=0; // QSound Sample Roms +UINT8 *CpsAd =NULL; UINT32 nCpsAdLen =0; // ADPCM Data +UINT8 *CpsStar=NULL; +UINT32 nCpsGfxScroll[4]={0,0,0,0}; // Offset to Scroll tiles +UINT32 nCpsGfxMask=0; // Address mask + +// Separate out the bits of a byte +inline static UINT32 Separate(UINT32 b) +{ + UINT32 a = b; // 00000000 00000000 00000000 11111111 + a =((a & 0x000000F0) << 12) | (a & 0x0000000F); // 00000000 00001111 00000000 00001111 + a = ((a & 0x000C000C) << 6) | (a & 0x00030003); // 00000011 00000011 00000011 00000011 + a = ((a & 0x02020202) << 3) | (a & 0x01010101); // 00010001 00010001 00010001 00010001 + + return a; +} + +// Precalculated table of the Separate function +static UINT32 SepTable[256]; + +static INT32 SepTableCalc() +{ + static INT32 bDone = 0; + if (bDone) { + return 0; // Already done it + } + + for (INT32 i = 0; i < 256; i++) { + SepTable[i] = Separate(255 - i); + } + + bDone = 1; // done it + return 0; +} + +// Allocate space and load up a rom +static INT32 LoadUp(UINT8** pRom, INT32* pnRomLen, INT32 nNum) +{ + UINT8 *Rom; + struct BurnRomInfo ri; + + ri.nLen = 0; + BurnDrvGetRomInfo(&ri, nNum); // Find out how big the rom is + if (ri.nLen <= 0) { + return 1; + } + + // Load the rom + Rom = (UINT8*)malloc(ri.nLen); + if (Rom == NULL) { + return 1; + } + + if (BurnLoadRom(Rom,nNum,1)) { + if (Rom) { + free(Rom); + Rom = NULL; + } + return 1; + } + + // Success + *pRom = Rom; *pnRomLen = ri.nLen; + return 0; +} + +static INT32 LoadUpSplit(UINT8** pRom, INT32* pnRomLen, INT32 nNum) +{ + UINT8 *Rom; + struct BurnRomInfo ri; + UINT32 nRomSize[4], nTotalRomSize; + INT32 i; + + ri.nLen = 0; + for (i = 0; i < 4; i++) { + BurnDrvGetRomInfo(&ri, nNum + i); + nRomSize[i] = ri.nLen; + } + + nTotalRomSize = nRomSize[0] + nRomSize[1] + nRomSize[2] + nRomSize[3]; + if (!nTotalRomSize) return 1; + + Rom = (UINT8*)malloc(nTotalRomSize); + if (Rom == NULL) return 1; + + INT32 Offset = 0; + for (i = 0; i < 4; i++) { + if (i > 0) Offset += nRomSize[i - 1]; + if (BurnLoadRom(Rom + Offset, nNum + i, 1)) { + if (Rom) { + free(Rom); + Rom = NULL; + } + return 1; + } + } + + *pRom = Rom; + *pnRomLen = nTotalRomSize; + + return 0; +} + +// ----------------------------CPS1-------------------------------- +// Load 1 rom and interleave in the CPS style: +// rom : aa bb +// --ba --ba --ba --ba --ba --ba --ba --ba 8 pixels (four bytes) +// (skip four bytes) + +static INT32 CpsLoadOne(UINT8* Tile, INT32 nNum, INT32 nWord, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen=0; + UINT8 *pt = NULL, *pr = NULL; + INT32 i; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + + nRomLen &= ~1; // make sure even + + for (i = 0, pt = Tile, pr = Rom; i < nRomLen; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + return 0; +} + +static INT32 CpsLoadOnePang(UINT8 *Tile,INT32 nNum,INT32 nWord,INT32 nShift) +{ + INT32 i=0; + UINT8 *Rom = NULL; INT32 nRomLen = 0; + UINT8 *pt = NULL, *pr = NULL; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + + nRomLen &= ~1; // make sure even + + for (i = 0x100000, pt = Tile, pr = Rom + 0x100000; i < nRomLen; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + return 0; +} + +static INT32 CpsLoadOneHack160(UINT8 *Tile, INT32 nNum, INT32 nWord, INT32 nOffset) +{ + INT32 i = 0; + UINT8 *Rom1 = NULL, *Rom2 = NULL; + INT32 nRomLen1 = 0, nRomLen2 = 0; + UINT8 *pt = NULL, *pr = NULL; + + LoadUp(&Rom1, &nRomLen1, nNum); + if (Rom1 == NULL) { + return 1; + } + LoadUp(&Rom2, &nRomLen2, nNum + 1); + if (Rom2 == NULL) { + return 1; + } + + for (i = 0, pt = Tile, pr = Rom1 + (0x80000 * nOffset); i < 0x80000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= 0; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile, pr = Rom2 + (0x80000 * nOffset); i < 0x80000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= 2; + *((UINT32 *)pt) |= Pix; + } + + if (Rom2) { + free(Rom2); + Rom2 = NULL; + } + if (Rom1) { + free(Rom1); + Rom1 = NULL; + } + return 0; +} + +static INT32 CpsLoadOneBootleg(UINT8* Tile, INT32 nNum, INT32 nWord, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen=0; + UINT8 *pt = NULL, *pr = NULL; + INT32 i; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + nRomLen &= ~1; // make sure even + + for (i = 0, pt = Tile, pr = Rom; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile + 4, pr = Rom + 0x40000; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + return 0; +} + +static INT32 CpsLoadOneBootlegType2(UINT8* Tile, INT32 nNum, INT32 nWord, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen=0; + UINT8 *pt = NULL, *pr = NULL; + INT32 i; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + nRomLen &= ~1; // make sure even + + for (i = 0, pt = Tile, pr = Rom; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile + 4, pr = Rom + 0x40000; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile + 0x200000, pr = Rom + 0x80000; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile + 0x200004, pr = Rom + 0xc0000; i < 0x40000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + return 0; +} + +static INT32 CpsLoadOneSf2ebbl(UINT8* Tile, INT32 nNum, INT32 nWord, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen=0; + UINT8 *pt = NULL, *pr = NULL; + INT32 i; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + nRomLen &= ~1; // make sure even + + for (i = 0, pt = Tile, pr = Rom; i < 0x10000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + for (i = 0, pt = Tile + 4, pr = Rom + 0x10000; i < 0x10000; pt += 8) { + UINT32 Pix; // Eight pixels + UINT8 b; + b = *pr++; i++; Pix = SepTable[b]; + if (nWord) { + b = *pr++; i++; Pix |= SepTable[b] << 1; + } + + Pix <<= nShift; + *((UINT32 *)pt) |= Pix; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + return 0; +} + +INT32 CpsLoadTiles(UINT8* Tile, INT32 nStart) +{ + // left side of 16x16 tiles + CpsLoadOne(Tile, nStart , 1, 0); + CpsLoadOne(Tile, nStart + 1, 1, 2); + // right side of 16x16 tiles + CpsLoadOne(Tile + 4, nStart + 2, 1, 0); + CpsLoadOne(Tile + 4, nStart + 3, 1, 2); + return 0; +} + +INT32 CpsLoadTilesByte(UINT8* Tile, INT32 nStart) +{ + CpsLoadOne(Tile, nStart + 0, 0, 0); + CpsLoadOne(Tile, nStart + 1, 0, 1); + CpsLoadOne(Tile, nStart + 2, 0, 2); + CpsLoadOne(Tile, nStart + 3, 0, 3); + CpsLoadOne(Tile + 4, nStart + 4, 0, 0); + CpsLoadOne(Tile + 4, nStart + 5, 0, 1); + CpsLoadOne(Tile + 4, nStart + 6, 0, 2); + CpsLoadOne(Tile + 4, nStart + 7, 0, 3); + return 0; +} + +INT32 CpsLoadTilesForgottn(INT32 nStart) +{ + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 0, 0, 0); + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 1, 0, 1); + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 2, 1, 2); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 3, 1, 0); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 4, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 5, 0, 3); + CpsLoadOne(CpsGfx + 0 + 0x100000, nStart + 6, 0, 0); + CpsLoadOne(CpsGfx + 0 + 0x100000, nStart + 7, 0, 1); + CpsLoadOne(CpsGfx + 4 + 0x100000, nStart + 8, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x100000, nStart + 9, 0, 3); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 10, 1, 0); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 11, 0, 2); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 12, 0, 3); + CpsLoadOne(CpsGfx + 4 + 0x200000, nStart + 13, 1, 0); + CpsLoadOne(CpsGfx + 4 + 0x200000, nStart + 14, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x200000, nStart + 15, 0, 3); + CpsLoadOne(CpsGfx + 0 + 0x300000, nStart + 16, 0, 2); + CpsLoadOne(CpsGfx + 0 + 0x300000, nStart + 17, 0, 3); + CpsLoadOne(CpsGfx + 4 + 0x300000, nStart + 18, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x300000, nStart + 19, 0, 3); + + return 0; +} + +INT32 CpsLoadTilesForgottnu(INT32 nStart) +{ + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 0, 0, 0); + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 1, 0, 1); + CpsLoadOne(CpsGfx + 0 + 0x000000, nStart + 2, 1, 2); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 3, 1, 0); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 4, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x000000, nStart + 5, 0, 3); + CpsLoadOne(CpsGfx + 0 + 0x100000, nStart + 6, 0, 0); + CpsLoadOne(CpsGfx + 0 + 0x100000, nStart + 7, 0, 1); + CpsLoadOne(CpsGfx + 4 + 0x100000, nStart + 8, 0, 2); + CpsLoadOne(CpsGfx + 4 + 0x100000, nStart + 9, 0, 3); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 10, 1, 0); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 11, 0, 2); + CpsLoadOne(CpsGfx + 0 + 0x200000, nStart + 12, 0, 3); + CpsLoadOne(CpsGfx + 4 + 0x200000, nStart + 13, 1, 0); + CpsLoadOne(CpsGfx + 4 + 0x200000, nStart + 14, 1, 2); + CpsLoadOne(CpsGfx + 0 + 0x300000, nStart + 15, 0, 2); + CpsLoadOne(CpsGfx + 0 + 0x300000, nStart + 16, 0, 3); + + return 0; +} + +INT32 CpsLoadTilesPang(UINT8* Tile, INT32 nStart) +{ + CpsLoadOne( Tile, nStart, 1, 0); + CpsLoadOne( Tile, nStart + 1, 1, 2); + CpsLoadOnePang(Tile + 4, nStart, 1, 0); + CpsLoadOnePang(Tile + 4, nStart + 1, 1, 2); + + return 0; +} + +INT32 CpsLoadTilesHack160(UINT8* Tile, INT32 nStart) +{ + CpsLoadOneHack160(Tile + 0 + 0x000000, nStart, 1, 0); + CpsLoadOneHack160(Tile + 4 + 0x000000, nStart, 1, 1); + CpsLoadOneHack160(Tile + 0 + 0x200000, nStart, 1, 2); + CpsLoadOneHack160(Tile + 4 + 0x200000, nStart, 1, 3); + + return 0; +} + +INT32 CpsLoadTilesBootleg(UINT8 *Tile, INT32 nStart) +{ + CpsLoadOneBootleg(Tile, nStart, 0, 0); + CpsLoadOneBootleg(Tile, nStart + 1, 0, 1); + CpsLoadOneBootleg(Tile, nStart + 2, 0, 2); + CpsLoadOneBootleg(Tile, nStart + 3, 0, 3); + + return 0; +} + +INT32 CpsLoadTilesCaptcomb(UINT8 *Tile, INT32 nStart) +{ + CpsLoadOneBootlegType2(Tile, nStart, 0, 0); + CpsLoadOneBootlegType2(Tile, nStart + 1, 0, 1); + CpsLoadOneBootlegType2(Tile, nStart + 2, 0, 2); + CpsLoadOneBootlegType2(Tile, nStart + 3, 0, 3); + + return 0; +} + +INT32 CpsLoadTilesPunipic2(UINT8 *Tile, INT32 nStart) +{ + CpsLoadOneHack160(Tile + 0 + 0x000000, nStart, 1, 0); + CpsLoadOneHack160(Tile + 0 + 0x200000, nStart, 1, 1); + CpsLoadOneHack160(Tile + 4 + 0x000000, nStart, 1, 2); + CpsLoadOneHack160(Tile + 4 + 0x200000, nStart, 1, 3); + + return 0; +} + +INT32 CpsLoadTilesSf2ebbl(UINT8 *Tile, INT32 nStart) +{ + CpsLoadOneSf2ebbl(Tile, nStart + 0, 0, 0); + CpsLoadOneSf2ebbl(Tile, nStart + 1, 0, 2); + CpsLoadOneSf2ebbl(Tile, nStart + 2, 0, 1); + CpsLoadOneSf2ebbl(Tile, nStart + 3, 0, 3); + + return 0; +} + +INT32 CpsLoadStars(UINT8* pStar, INT32 nStart) +{ + UINT8* pTemp[2] = { NULL, NULL}; + INT32 nLen; + + for (INT32 i = 0; i < 2; i++) { + if (LoadUp(&pTemp[i], &nLen, nStart + (i << 1))) { + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + } + } + + for (INT32 i = 0; i < 0x1000; i++) { + pStar[i] = pTemp[0][i << 1]; + pStar[0x01000 + i] = pTemp[1][i << 1]; + } + + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + + return 0; +} + +INT32 CpsLoadStarsByte(UINT8* pStar, INT32 nStart) +{ + UINT8* pTemp[2] = { NULL, NULL}; + INT32 nLen; + + for (INT32 i = 0; i < 2; i++) { + if (LoadUp(&pTemp[i], &nLen, nStart + (i * 4))) { + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + } + } + + for (INT32 i = 0; i < 0x1000; i++) { + pStar[i] = pTemp[0][i]; + pStar[0x01000 + i] = pTemp[1][i]; + } + + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + + return 0; +} + +INT32 CpsLoadStarsForgottnAlt(UINT8* pStar, INT32 nStart) +{ + UINT8* pTemp[2] = { NULL, NULL}; + INT32 nLen; + + for (INT32 i = 0; i < 2; i++) { + if (LoadUp(&pTemp[i], &nLen, nStart + (i * 3))) { + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + } + } + + for (INT32 i = 0; i < 0x1000; i++) { + pStar[i] = pTemp[0][i << 1]; + pStar[0x01000 + i] = pTemp[1][i << 1]; + } + + if (pTemp[0]) { + free(pTemp[0]); + pTemp[0] = NULL; + } + if (pTemp[1]) { + free(pTemp[1]); + pTemp[1] = NULL; + } + + return 0; +} + +// ----------------------------CPS2-------------------------------- +// Load 1 rom and interleve in the CPS2 style: +// rom : aa bb -- -- (4 bytes) +// --ba --ba --ba --ba --ba --ba --ba --ba 8 pixels (four bytes) +// (skip four bytes) + +// memory 000000-100000 are in even word fields of first 080000 section +// memory 100000-200000 are in odd word fields of first 080000 section +// i = ABCD nnnn nnnn nnnn nnnn n000 +// s = 00AB Cnnn nnnn nnnn nnnn nnD0 + +inline static void Cps2Load100000(UINT8* Tile, UINT8* Sect, INT32 nShift) +{ + UINT8 *pt, *pEnd, *ps; + pt = Tile; pEnd = Tile + 0x100000; ps = Sect; + + do { + UINT32 Pix; // Eight pixels + Pix = SepTable[ps[0]]; + Pix |= SepTable[ps[1]] << 1; + Pix <<= nShift; + *((UINT32*)pt) |= Pix; + + pt += 8; ps += 4; + } + while (pt < pEnd); +} + +static INT32 Cps2LoadOne(UINT8* Tile, INT32 nNum, INT32 nWord, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen = 0; + UINT8 *pt, *pr; + + LoadUp(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + + if (nWord == 0) { + UINT8*Rom2 = NULL; INT32 nRomLen2 = 0; + UINT8*Rom3 = Rom; + + LoadUp(&Rom2, &nRomLen2, nNum + 1); + if (Rom2 == NULL) { + return 1; + } + + nRomLen <<= 1; + Rom = (UINT8*)malloc(nRomLen); + if (Rom == NULL) { + if (Rom2) { + free(Rom2); + Rom2 = NULL; + } + if (Rom3) { + free(Rom3); + Rom3 = NULL; + } + return 1; + } + + for (INT32 i = 0; i < nRomLen2; i++) { + Rom[(i << 1) + 0] = Rom3[i]; + Rom[(i << 1) + 1] = Rom2[i]; + } + + if (Rom2) { + free(Rom2); + Rom2 = NULL; + } + if (Rom3) { + free(Rom3); + Rom3 = NULL; + } + } + + // Go through each section + pt = Tile; pr = Rom; + for (INT32 b = 0; b < nRomLen >> 19; b++) { + Cps2Load100000(pt, pr, nShift); pt += 0x100000; + Cps2Load100000(pt, pr + 2, nShift); pt += 0x100000; + pr += 0x80000; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + + return 0; +} + +static INT32 Cps2LoadSplit(UINT8* Tile, INT32 nNum, INT32 nShift) +{ + UINT8 *Rom = NULL; INT32 nRomLen = 0; + UINT8 *pt, *pr; + + LoadUpSplit(&Rom, &nRomLen, nNum); + if (Rom == NULL) { + return 1; + } + + // Go through each section + pt = Tile; pr = Rom; + for (INT32 b = 0; b < nRomLen >> 19; b++) { + Cps2Load100000(pt, pr, nShift); pt += 0x100000; + Cps2Load100000(pt, pr + 2, nShift); pt += 0x100000; + pr += 0x80000; + } + + if (Rom) { + free(Rom); + Rom = NULL; + } + + return 0; +} + +INT32 Cps2LoadTiles(UINT8* Tile, INT32 nStart) +{ + // left side of 16x16 tiles + Cps2LoadOne(Tile, nStart, 1, 0); + Cps2LoadOne(Tile, nStart + 1, 1, 2); + // right side of 16x16 tiles + Cps2LoadOne(Tile + 4, nStart + 2, 1, 0); + Cps2LoadOne(Tile + 4, nStart + 3, 1, 2); + + return 0; +} + +INT32 Cps2LoadTilesSplit(UINT8* Tile, INT32 nStart) +{ + // left side of 16x16 tiles + Cps2LoadSplit(Tile, nStart + 0, 0); + Cps2LoadSplit(Tile, nStart + 4, 2); + // right side of 16x16 tiles + Cps2LoadSplit(Tile + 4, nStart + 8, 0); + Cps2LoadSplit(Tile + 4, nStart + 12, 2); + + return 0; +} + +INT32 Cps2LoadTilesSIM(UINT8* Tile, INT32 nStart) +{ + Cps2LoadOne(Tile, nStart, 0, 0); + Cps2LoadOne(Tile, nStart + 2, 0, 2); + Cps2LoadOne(Tile + 4, nStart + 4, 0, 0); + Cps2LoadOne(Tile + 4, nStart + 6, 0, 2); + + return 0; +} + +// ---------------------------------------------------------------- + +// The file extension indicates the data contained in a file. +// it consists of 2 numbers optionally followed by a single letter. +// The letter indicates the version. The meaning for the nubmers +// is as follows: +// 01 - 02 : Z80 program +// 03 - 10 : 68K program (filenames ending with x contain the XOR table) +// 11 - 12 : QSound sample data +// 13 - nn : Graphics data + +static UINT32 nGfxMaxSize; + +static INT32 CpsGetROMs(bool bLoad) +{ + char* pRomName; + struct BurnRomInfo ri; + + UINT8* CpsCodeLoad = CpsCode; + UINT8* CpsRomLoad = CpsRom; + UINT8* CpsGfxLoad = CpsGfx; + UINT8* CpsZRomLoad = CpsZRom; + UINT8* CpsQSamLoad = (UINT8*)CpsQSam; + + INT32 nGfxNum = 0; + + if (bLoad) { + if (!CpsCodeLoad || !CpsRomLoad || !CpsGfxLoad || !CpsZRomLoad || !CpsQSamLoad) { + return 1; + } + } else { + nCpsCodeLen = nCpsRomLen = nCpsGfxLen = nCpsZRomLen = nCpsQSamLen = 0; + + nGfxMaxSize = 0; + if (BurnDrvGetHardwareCode() & HARDWARE_CAPCOM_CPS2_SIMM) { + nGfxMaxSize = ~0U; + } + } + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + // SIMM Graphics ROMs + if (BurnDrvGetHardwareCode() & HARDWARE_CAPCOM_CPS2_SIMM) { + if ((ri.nType & BRF_GRA) && (ri.nType & 8)) { + if (bLoad) { + Cps2LoadTilesSIM(CpsGfxLoad, i); + CpsGfxLoad += ri.nLen * 8; + i += 7; + } else { + nCpsGfxLen += ri.nLen; + } + continue; + } + // SIMM QSound sample ROMs + if ((ri.nType & BRF_SND) && ((ri.nType & 15) == 13)) { + if (bLoad) { + BurnLoadRom(CpsQSamLoad, i, 1); + BurnByteswap(CpsQSamLoad, ri.nLen); + CpsQSamLoad += ri.nLen; + } else { + nCpsQSamLen += ri.nLen; + } + continue; + } + + // Different interleave SIMM QSound sample ROMs + if ((ri.nType & BRF_SND) && ((ri.nType & 15) == 15)) { + if (bLoad) { + BurnLoadRom(CpsQSamLoad + 1, i + 0, 2); + BurnLoadRom(CpsQSamLoad + 0, i + 1, 2); + i += 2; + } else { + nCpsQSamLen += ri.nLen; + } + continue; + } + } + + // 68K program ROMs + if ((ri.nType & 7) == 1) { + if (bLoad) { + BurnLoadRom(CpsRomLoad, i, 1); + CpsRomLoad += ri.nLen; + } else { + nCpsRomLen += ri.nLen; + } + continue; + } + // XOR tables + if ((ri.nType & 7) == 2) { + if (bLoad) { + BurnLoadRom(CpsCodeLoad, i, 1); + CpsCodeLoad += ri.nLen; + } else { + nCpsCodeLen += ri.nLen; + } + continue; + } + + // Z80 program ROMs + if ((ri.nType & 7) == 4) { + if (bLoad) { + BurnLoadRom(CpsZRomLoad, i, 1); + CpsZRomLoad += ri.nLen; + } else { + nCpsZRomLen += ri.nLen; + } + continue; + } + + // Normal Graphics ROMs + if (ri.nType & BRF_GRA) { + if (bLoad) { + if ((ri.nType & 15) == 6) { + Cps2LoadTilesSplit(CpsGfxLoad, i); + CpsGfxLoad += (nGfxMaxSize == ~0U ? ri.nLen : nGfxMaxSize) * 4; + i += 15; + } else { + Cps2LoadTiles(CpsGfxLoad, i); + CpsGfxLoad += (nGfxMaxSize == ~0U ? ri.nLen : nGfxMaxSize) * 4; + i += 3; + } + } else { + if (ri.nLen > nGfxMaxSize) { + nGfxMaxSize = ri.nLen; + } + if (ri.nLen < nGfxMaxSize) { + nGfxMaxSize = ~0U; + } + nCpsGfxLen += ri.nLen; + nGfxNum++; + } + continue; + } + + // QSound sample ROMs + if (ri.nType & BRF_SND) { + if (bLoad) { + BurnLoadRom(CpsQSamLoad, i, 1); + BurnByteswap(CpsQSamLoad, ri.nLen); + CpsQSamLoad += ri.nLen; + } else { + nCpsQSamLen += ri.nLen; + } + continue; + } + } + + if (bLoad) { +#if 0 + for (UINT32 i = 0; i < nCpsCodeLen / 4; i++) { + ((UINT32*)CpsCode)[i] ^= ((UINT32*)CpsRom)[i]; + } +#endif + cps2_decrypt_game_data(); + +// if (!nCpsCodeLen) return 1; + } else { + + if (nGfxMaxSize != ~0U) { + nCpsGfxLen = nGfxNum * nGfxMaxSize; + } + +#if 1 && defined FBA_DEBUG + if (!nCpsCodeLen) { + bprintf(PRINT_IMPORTANT, _T(" - 68K ROM size:\t0x%08X (Decrypted with key)\n"), nCpsRomLen); + } else { + bprintf(PRINT_IMPORTANT, _T(" - 68K ROM size:\t0x%08X (XOR table size: 0x%08X)\n"), nCpsRomLen, nCpsCodeLen); + } + bprintf(PRINT_IMPORTANT, _T(" - Z80 ROM size:\t0x%08X\n"), nCpsZRomLen); + bprintf(PRINT_IMPORTANT, _T(" - Graphics data:\t0x%08X\n"), nCpsGfxLen); + bprintf(PRINT_IMPORTANT, _T(" - QSound data:\t0x%08X\n"), nCpsQSamLen); +#endif + + if (/*!nCpsCodeLen ||*/ !nCpsRomLen || !nCpsGfxLen || !nCpsZRomLen || ! nCpsQSamLen) { + return 1; + } + } + + return 0; +} + +// ---------------------------------------------------------------- + +INT32 CpsInit() +{ + INT32 nMemLen, i; + + if (Cps == 1) { + BurnSetRefreshRate(59.61); + } else { + if (Cps == 2) { + BurnSetRefreshRate(59.633333); + } + } + + if (!nCPS68KClockspeed) { + if (!(Cps & 1)) { + nCPS68KClockspeed = 11800000; + } else { + nCPS68KClockspeed = 10000000; + } + } + nCPS68KClockspeed = nCPS68KClockspeed * 100 / nBurnFPS; + + nMemLen = nCpsGfxLen + nCpsRomLen + nCpsCodeLen + nCpsZRomLen + nCpsQSamLen + nCpsAdLen; + + if (Cps1Qs == 1) { + nMemLen += nCpsZRomLen * 2; + } + + // Allocate Gfx, Rom and Z80 Roms + CpsGfx = (UINT8*)malloc(nMemLen); + if (CpsGfx == NULL) { + return 1; + } + memset(CpsGfx, 0, nMemLen); + + CpsRom = CpsGfx + nCpsGfxLen; + CpsCode = CpsRom + nCpsRomLen; + if (Cps1Qs == 1) { + CpsEncZRom = CpsCode + nCpsCodeLen; + CpsZRom = CpsEncZRom + nCpsZRomLen * 2; + } else { + CpsZRom = CpsCode + nCpsCodeLen; + } + CpsQSam =(INT8*)(CpsZRom + nCpsZRomLen); + CpsAd =(UINT8*)(CpsQSam + nCpsQSamLen); + + // Create Gfx addr mask + for (i = 0; i < 31; i++) { + if ((1 << i) >= (INT32)nCpsGfxLen) { + break; + } + } + nCpsGfxMask = (1 << i) - 1; + + // Offset to Scroll tiles + if (!(Cps & 1)) { + nCpsGfxScroll[1] = nCpsGfxScroll[2] = nCpsGfxScroll[3] = 0x800000; + } else { + nCpsGfxScroll[1] = nCpsGfxScroll[2] = nCpsGfxScroll[3] = 0; + } + +#if 0 + if (nCpsZRomLen>=5) { + // 77->cfff and rst 00 in case driver doesn't load + CpsZRom[0] = 0x3E; CpsZRom[1] = 0x77; + CpsZRom[2] = 0x32; CpsZRom[3] = 0xFF; CpsZRom[4] = 0xCF; + CpsZRom[5] = 0xc7; + } +#endif + + SepTableCalc(); // Precalc the separate table + + CpsReset = 0; Cpi01A = Cpi01C = Cpi01E = 0; // blank other inputs + + // Use this as default - all CPS-2 games use it + SetCpsBId(CPS_B_21_DEF, 0); + + return 0; +} + +INT32 Cps2Init() +{ + Cps = 2; + + if (CpsGetROMs(false)) { + return 1; + } + + CpsInit(); + + if (CpsGetROMs(true)) { + return 1; + } + + return CpsRunInit(); +} + +INT32 CpsExit() +{ + if (!(Cps & 1)) { + CpsRunExit(); + } + + CpsLayEn[1] = CpsLayEn[2] = CpsLayEn[3] = CpsLayEn[4] = CpsLayEn[5] = 0; + nCpsLcReg = 0; + nCpsGfxScroll[1] = nCpsGfxScroll[2] = nCpsGfxScroll[3] = 0; + nCpsGfxMask = 0; + + Scroll1TileMask = 0; + Scroll2TileMask = 0; + Scroll3TileMask = 0; + + nCpsCodeLen = nCpsRomLen = nCpsGfxLen = nCpsZRomLen = nCpsQSamLen = nCpsAdLen = 0; + CpsCode = CpsRom = CpsZRom = CpsAd = CpsStar = NULL; + CpsQSam = NULL; + + // All Memory is allocated to this (this is the only one we can free) + if (CpsGfx) { + free(CpsGfx); + CpsGfx = NULL; + } + + nCPS68KClockspeed = 0; + Cps = 0; + + return 0; +} diff --git a/src/burn/drivers/capcom/cps.h b/src/burn/drivers/capcom/cps.h new file mode 100644 index 00000000..0094b23c --- /dev/null +++ b/src/burn/drivers/capcom/cps.h @@ -0,0 +1,385 @@ +// CPS ---------------------------------- +#include "burnint.h" + +#include "msm6295.h" +#include "eeprom.h" +#include "timer.h" + +// Maximum number of beam-synchronized interrupts to check +#define MAX_RASTER 10 + +extern UINT32 CpsMProt[4]; // Mprot changes +extern UINT32 CpsBID[3]; // Board ID changes + +// cps.cpp +extern INT32 Cps; // 1 = CPS1, 2 = CPS2, 3 = CPS CHanger +extern INT32 Cps1Qs; +extern INT32 Cps1Pic; +extern INT32 nCPS68KClockspeed; +extern INT32 nCpsCycles; // Cycles per frame +extern INT32 nCpsZ80Cycles; +extern UINT8 *CpsGfx; extern UINT32 nCpsGfxLen; // All the graphics +extern UINT8 *CpsRom; extern UINT32 nCpsRomLen; // Program Rom (as in rom) +extern UINT8 *CpsCode; extern UINT32 nCpsCodeLen; // Program Rom (decrypted) +extern UINT8 *CpsZRom; extern UINT32 nCpsZRomLen; // Z80 Roms +extern INT8 *CpsQSam; extern UINT32 nCpsQSamLen; // QSound Sample Roms +extern UINT8 *CpsAd; extern UINT32 nCpsAdLen; // ADPCM Data +extern UINT32 nCpsGfxScroll[4]; // Offset to Scroll tiles +extern UINT32 nCpsGfxMask; // Address mask +extern UINT8* CpsStar; +INT32 CpsInit(); +INT32 Cps2Init(); +INT32 CpsExit(); +INT32 CpsLoadTiles(UINT8 *Tile,INT32 nStart); +INT32 CpsLoadTilesByte(UINT8 *Tile,INT32 nStart); +INT32 CpsLoadTilesForgottn(INT32 nStart); +INT32 CpsLoadTilesForgottnu(INT32 nStart); +INT32 CpsLoadTilesPang(UINT8 *Tile,INT32 nStart); +INT32 CpsLoadTilesHack160(UINT8 *Tile,INT32 nStart); +INT32 CpsLoadTilesBootleg(UINT8 *Tile, INT32 nStart); +INT32 CpsLoadTilesCaptcomb(UINT8 *Tile, INT32 nStart); +INT32 CpsLoadTilesPunipic2(UINT8 *Tile, INT32 nStart); +INT32 CpsLoadTilesSf2ebbl(UINT8 *Tile, INT32 nStart); +INT32 CpsLoadStars(UINT8 *pStar, INT32 nStart); +INT32 CpsLoadStarsByte(UINT8 *pStar, INT32 nStart); +INT32 CpsLoadStarsForgottnAlt(UINT8 *pStar, INT32 nStart); +INT32 Cps2LoadTiles(UINT8 *Tile,INT32 nStart); +INT32 Cps2LoadTilesSIM(UINT8 *Tile,INT32 nStart); + +// cps_config.h +#define CPS_B_01 0 +#define CPS_B_02 1 +#define CPS_B_03 2 +#define CPS_B_04 3 +#define CPS_B_05 4 +#define CPS_B_11 5 +#define CPS_B_12 6 +#define CPS_B_13 7 +#define CPS_B_14 8 +#define CPS_B_15 9 +#define CPS_B_16 10 +#define CPS_B_17 11 +#define CPS_B_18 12 +#define CPS_B_21_DEF 13 +#define CPS_B_21_BT1 14 +#define CPS_B_21_BT2 15 +#define CPS_B_21_BT3 16 +#define CPS_B_21_BT4 17 +#define CPS_B_21_BT5 18 +#define CPS_B_21_BT6 19 +#define CPS_B_21_BT7 20 +#define CPS_B_21_QS1 21 +#define CPS_B_21_QS2 22 +#define CPS_B_21_QS3 23 +#define CPS_B_21_QS4 24 +#define CPS_B_21_QS5 25 +#define HACK_B_1 26 +#define HACK_B_2 27 +#define HACK_B_3 28 +#define HACK_B_4 29 + +#define GFXTYPE_SPRITES (1<<0) +#define GFXTYPE_SCROLL1 (1<<1) +#define GFXTYPE_SCROLL2 (1<<2) +#define GFXTYPE_SCROLL3 (1<<3) +#define GFXTYPE_STARS (1<<4) + +#define mapper_LWCHR 0 +#define mapper_LW621 1 +#define mapper_DM620 2 +#define mapper_ST24M1 3 +#define mapper_DM22A 4 +#define mapper_DAM63B 5 +#define mapper_ST22B 6 +#define mapper_TK22B 7 +#define mapper_WL24B 8 +#define mapper_S224B 9 +#define mapper_YI24B 10 +#define mapper_AR24B 11 +#define mapper_AR22B 12 +#define mapper_O224B 13 +#define mapper_MS24B 14 +#define mapper_CK24B 15 +#define mapper_NM24B 16 +#define mapper_CA24B 17 +#define mapper_CA22B 18 +#define mapper_STF29 19 +#define mapper_RT24B 20 +#define mapper_RT22B 21 +#define mapper_KD29B 22 +#define mapper_CC63B 23 +#define mapper_KR63B 24 +#define mapper_S9263B 25 +#define mapper_VA63B 26 +#define mapper_VA22B 27 +#define mapper_Q522B 28 +#define mapper_TK263B 29 +#define mapper_CD63B 30 +#define mapper_PS63B 31 +#define mapper_MB63B 32 +#define mapper_QD22B 33 +#define mapper_QD63B 34 +#define mapper_qtono2 35 +#define mapper_RCM63B 36 +#define mapper_PKB10B 37 +#define mapper_pang3 38 +#define mapper_sfzch 39 +#define mapper_cps2 40 +#define mapper_frog 41 +extern void SetGfxMapper(INT32 MapperId); +extern INT32 GfxRomBankMapper(INT32 Type, INT32 Code); +extern void SetCpsBId(INT32 CpsBId, INT32 bStars); + +// cps_pal.cpp +extern UINT32* CpsPal; // Hicolor version of palette +extern UINT32* CpsObjPal; // Pointer to lagged obj palette +extern INT32 nLagObjectPalettes; // Lag object palettes by one frame if non-zero +INT32 CpsPalInit(); +INT32 CpsPalExit(); +INT32 CpsPalUpdate(UINT8 *pNewPal,INT32 bRecalcAll); +INT32 CpsStarPalUpdate(UINT8* pNewPal, INT32 nLayer, INT32 bRecalcAll); + +// cps_mem.cpp +extern UINT8 *CpsRam90; +extern UINT8 *CpsZRamC0,*CpsZRamF0; +extern UINT8 *CpsSavePal; +extern UINT8 *CpsRam708,*CpsReg,*CpsFrg; +extern UINT8 *CpsSaveReg[MAX_RASTER + 1]; +extern UINT8 *CpsSaveFrg[MAX_RASTER + 1]; +extern UINT8 *CpsRamFF; +void CpsMapObjectBanks(INT32 nBank); +INT32 CpsMemInit(); +INT32 CpsMemExit(); +INT32 CpsAreaScan(INT32 nAction,INT32 *pnMin); + +// cps_run.cpp +extern UINT8 CpsReset; +extern UINT8 Cpi01A, Cpi01C, Cpi01E; +extern INT32 nIrqLine50, nIrqLine52; // The scanlines at which the interrupts are triggered +extern INT32 CpsDrawSpritesInReverse; +INT32 CpsRunInit(); +INT32 CpsRunExit(); +INT32 Cps1Frame(); +INT32 Cps2Frame(); + +inline static UINT8* CpsFindGfxRam(INT32 nAddr,INT32 nLen) +{ + nAddr&=0xffffff; // 24-bit bus + if (nAddr>=0x900000 && nAddr+nLen<=0x930000) return CpsRam90+nAddr-0x900000; + return NULL; +} + +// cps_rw.cpp +// Treble Winner - Added INP(1FD) for sf2ue +#define CPSINPSET INP(000) INP(001) INP(006) INP(007) INP(008) INP(010) INP(011) INP(012) INP(018) INP(019) INP(020) INP(021) INP(029) INP(176) INP(177) INP(179) INP(186) INP(1fd) + +// prototype for input bits +#define INP(nnn) extern UINT8 CpsInp##nnn[8]; +CPSINPSET +#undef INP + +#define INP(nnn) extern UINT8 Inp##nnn; +CPSINPSET +#undef INP + +#define CPSINPEX INP(c000) INP(c001) INP(c002) INP(c003) + +#define INP(nnnn) extern UINT8 CpsInp##nnnn[8]; +CPSINPEX +#undef INP + +// For the Forgotten Worlds analog controls +extern UINT16 CpsInp055, CpsInp05d; +extern UINT16 CpsInpPaddle1, CpsInpPaddle2; + +extern INT32 PangEEP; +extern INT32 Forgottn; +extern INT32 Cps1QsHack; +extern INT32 Kodh; +extern INT32 Cawingb; +extern INT32 Wofh; +extern INT32 Sf2thndr; +extern INT32 Pzloop2; +extern INT32 Ssf2tb; +extern INT32 Dinopic; +extern INT32 Dinohunt; +extern INT32 Port6SoundWrite; + +extern UINT8* CpsEncZRom; + +INT32 CpsRwInit(); +INT32 CpsRwExit(); +INT32 CpsRwGetInp(); +UINT8 __fastcall CpsReadByte(UINT32 a); +void __fastcall CpsWriteByte(UINT32 a, UINT8 d); +UINT16 __fastcall CpsReadWord(UINT32 a); +void __fastcall CpsWriteWord(UINT32 a, UINT16 d); + +// cps_draw.cpp +extern UINT8 CpsRecalcPal; // Flag - If it is 1, recalc the whole palette +extern INT32 nCpsLcReg; // Address of layer controller register +extern INT32 CpsLayEn[6]; // bits for layer enable +extern INT32 nStartline, nEndline; // specify the vertical slice of the screen to render +extern INT32 nRasterline[MAX_RASTER + 2]; // The lines at which an interrupt occurs +extern INT32 MaskAddr[4]; +extern INT32 CpsLayer1XOffs; +extern INT32 CpsLayer2XOffs; +extern INT32 CpsLayer3XOffs; +extern INT32 CpsLayer1YOffs; +extern INT32 CpsLayer2YOffs; +extern INT32 CpsLayer3YOffs; +void DrawFnInit(); +INT32 CpsDraw(); +INT32 CpsRedraw(); + +INT32 QsndInit(); +void QsndExit(); +void QsndReset(); +void QsndNewFrame(); +void QsndEndFrame(); +void QsndSyncZ80(); +INT32 QsndScan(INT32 nAction); + +// qs_z.cpp +INT32 QsndZInit(); +INT32 QsndZExit(); +INT32 QsndZScan(INT32 nAction); + +// qs_c.cpp +INT32 QscInit(INT32 nRate, INT32 nVolumeShift); +void QscReset(); +void QscExit(); +INT32 QscScan(INT32 nAction); +void QscNewFrame(); +void QscWrite(INT32 a, INT32 d); +INT32 QscUpdate(INT32 nEnd); + +// cps_tile.cpp +extern UINT32* CpstPal; +extern UINT32 nCpstType; extern INT32 nCpstX,nCpstY; +extern UINT32 nCpstTile; extern INT32 nCpstFlip; +extern short* CpstRowShift; +extern UINT32 CpstPmsk; // Pixel mask + +inline static void CpstSetPal(INT32 nPal) +{ + nPal <<= 4; + nPal &= 0x7F0; + CpstPal= CpsPal + nPal; +} + +// ctv.cpp +extern INT32 nBgHi; +extern UINT16 ZValue; +extern UINT16 *ZBuf; +extern UINT16 *pZVal; +extern UINT32 nCtvRollX,nCtvRollY; +extern UINT8 *pCtvTile; // Pointer to tile data +extern INT32 nCtvTileAdd; // Amount to add after each tile line +extern UINT8 *pCtvLine; // Pointer to output bitmap +typedef INT32 (*CtvDoFn)(); +typedef INT32 (*CpstOneDoFn)(); +extern CtvDoFn CtvDoX[0x20]; +extern CtvDoFn CtvDoXM[0x20]; +extern CtvDoFn CtvDoXB[0x20]; +extern CpstOneDoFn CpstOneDoX[3]; +extern CpstOneDoFn CpstOneObjDoX[2]; +INT32 CtvReady(); + +// nCpstType constants +// To get size do (nCpstType & 24) + 8 +#define CTT_FLIPX ( 1) +#define CTT_CARE ( 2) +#define CTT_ROWS ( 4) +#define CTT_8X8 ( 0) +#define CTT_16X16 ( 8) +#define CTT_32X32 (24) + +// cps_obj.cpp +extern INT32 nCpsObjectBank; + +extern UINT8 *BootlegSpriteRam; + +extern INT32 Sf2Hack; + +INT32 CpsObjInit(); +INT32 CpsObjExit(); +INT32 CpsObjGet(); +void CpsObjDrawInit(); +INT32 Cps1ObjDraw(INT32 nLevelFrom,INT32 nLevelTo); +INT32 Cps2ObjDraw(INT32 nLevelFrom,INT32 nLevelTo); + +// cps_scr.cpp +#define SCROLL_2 0 +#define SCROLL_3 1 +extern INT32 Ghouls; +extern INT32 Mercs; +extern INT32 Sf2jc; +extern INT32 Ssf2t; +extern INT32 Qad; +extern INT32 Xmcota; + +extern INT32 Scroll1TileMask; +extern INT32 Scroll2TileMask; +extern INT32 Scroll3TileMask; +INT32 Cps1Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy); +INT32 Cps1Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy); +INT32 Cps2Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy); +INT32 Cps2Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy); + +// cpsr.cpp +extern UINT8 *CpsrBase; // Tile data base +extern INT32 nCpsrScrX,nCpsrScrY; // Basic scroll info +extern UINT16 *CpsrRows; // Row scroll table, 0x400 words long +extern INT32 nCpsrRowStart; // Start of row scroll (can wrap?) + +// Information needed to draw a line +struct CpsrLineInfo { + INT32 nStart; // 0-0x3ff - where to start drawing tiles from + INT32 nWidth; // 0-0x400 - width of scroll shifts + // e.g. for no rowscroll at all, nWidth=0 + INT32 nTileStart; // Range of tiles which are visible onscreen + INT32 nTileEnd; // (e.g. 0x20 -> 0x50 , wraps around to 0x10) + INT16 Rows[16]; // 16 row scroll values for this line + INT32 nMaxLeft, nMaxRight; // Maximum row shifts left and right +}; +extern struct CpsrLineInfo CpsrLineInfo[15]; +INT32 Cps1rPrepare(); +INT32 Cps2rPrepare(); + +// cpsrd.cpp +INT32 Cps1rRender(); +INT32 Cps2rRender(); + +// dc_input.cpp +extern struct BurnInputInfo CpsFsi[0x1B]; + +// ps.cpp +extern UINT8 PsndCode, PsndFade; // Sound code/fade sent to the z80 program +INT32 PsndInit(); +INT32 PsndExit(); +void PsndNewFrame(); +INT32 PsndSyncZ80(INT32 nCycles); +INT32 PsndScan(INT32 nAction); + +// ps_z.cpp +INT32 PsndZInit(); +INT32 PsndZExit(); +INT32 PsndZScan(INT32 nAction); +extern INT32 Kodb; + +// ps_m.cpp +extern INT32 bPsmOkay; // 1 if the module is okay +INT32 PsmInit(); +INT32 PsmExit(); +void PsmNewFrame(); +INT32 PsmUpdate(INT32 nEnd); + +// kabuki.cpp +void wof_decode(); +void dino_decode(); +void punisher_decode(); +void slammast_decode(); + +// cps2_crypt.cpp +void cps2_decrypt_game_data(); diff --git a/src/burn/drivers/capcom/cps2_crpt.cpp b/src/burn/drivers/capcom/cps2_crpt.cpp new file mode 100644 index 00000000..8741ef19 --- /dev/null +++ b/src/burn/drivers/capcom/cps2_crpt.cpp @@ -0,0 +1,1088 @@ +/****************************************************************************** + +CPS-2 Encryption + +All credit goes to Andreas Naive for breaking the encryption algorithm. +Code by Nicola Salmoria. +Thanks to Charles MacDonald and Razoola for extracting the data from the hardware. + + +The encryption only affects opcodes, not data. + +It consists of two 4-round Feistel networks (FN) and involves both +the 16-bit opcode and the low 16 bits of the address. + +Let be: + +E = 16-bit ciphertext +A = 16-bit address +K = 64-bit key +D = 16-bit plaintext +y = FN1(x,k) = function describing the first Feistel network (x,y = 16 bit, k = 64 bit) +y = FN2(x,k) = function describing the second Feistel network (x,y = 16 bit, k = 64 bit) +y = EX(x) = fixed function that expands the 16-bit x to the 64-bit y + +Then the cipher can be described as: + +D = FN2( E, K XOR EX( FN1(A, K ) ) ) + + +Each round of the Feistel networks consists of four substitution boxes. The boxes +have 6 inputs and 2 outputs. Usually the input is the XOR of a data bit and a key +bit, however in some cases only the key is used. + +(TODO-notes about accuracy of s-boxes) + +The s-boxes were chosen in order to use an empty key (all FF) for the dead board. + + +Also, the hardware has different watchdog opcodes and address range (see below) +which are stored in the battery backed RAM. There doesn't appear to be any relation +between those and the 64-bit encryption key, so they probably use an additional +64 bits of battery-backed RAM. + + + +First FN: + + B(0 1 3 5 8 9 11 12) A(10 4 6 7 2 13 15 14) + L0 R0 + | | + XOR<-----------[F1]<------------| + | | + R1 L1 + | | + |------------>[F2]----------->XOR + | | + L2 R2 + | | + XOR<-----------[F3]<------------| + | | + R3 L3 + | | + |------------>[F4]----------->XOR + | | + L4 R4 + (10 4 6 7 2 13 15 14) (0 1 3 5 8 9 11 12) + + +Second FN: + + B(3 5 9 10 8 15 12 11) A(6 0 2 13 1 4 14 7) + L0 R0 + | | + XOR<-----------[F1]<------------| + | | + R1 L1 + | | + |------------>[F2]----------->XOR + | | + L2 R2 + | | + XOR<-----------[F3]<------------| + | | + R3 L3 + | | + |------------>[F4]----------->XOR + | | + L4 R4 + (6 0 2 13 1 4 14 7) (3 5 9 10 8 15 12 11) + +****************************************************************************** + +Some Encryption notes. +---------------------- + +Address range. + +The encryption does _not_ cover the entire address space. The range covered +differs per game. + + +Encryption Watchdog. + +The CPS2 system has a watchdog system that will disable the decryption +of data if the watchdog isn't triggered at least once every few seconds. +The trigger varies from game to game (some games do use the same) and is +basically a 68000 opcode/s instruction. The instruction is the same for +all regions of the game. The watchdog instructions are listed alongside +the decryption keys. + +*******************************************************************************/ + +#if 0 +#include "driver.h" +#include "cpu/m68000/m68kmame.h" +#include "ui.h" +#include "includes/cps1.h" +#endif + +#if 1 +#include "cps.h" +#include "bitswap.h" + +#define BIT(x,n) (((x)>>(n))&1) +#define BITSWAP8(a, b, c, d, e, f, g, h, i) BITSWAP08(a, b, c, d, e, f, g, h, i) +#endif + + +/******************************************************************************/ + +static const INT32 fn1_groupA[8] = { 10, 4, 6, 7, 2, 13, 15, 14 }; +static const INT32 fn1_groupB[8] = { 0, 1, 3, 5, 8, 9, 11, 12 }; + +static const INT32 fn2_groupA[8] = { 6, 0, 2, 13, 1, 4, 14, 7 }; +static const INT32 fn2_groupB[8] = { 3, 5, 9, 10, 8, 15, 12, 11 }; + +/******************************************************************************/ + +// The order of the input and output bits in the s-boxes is arbitrary. +// Each s-box can be XORed with an arbitrary vale in range 0-3 (but the same value +// must be used for the corresponding output bits in f1 and f3 or in f2 and f4) + +struct sbox +{ + const UINT8 table[64]; + const INT32 inputs[6]; // positions of the inputs bits, -1 means no input except from key + const INT32 outputs[2]; // positions of the output bits +}; + +// the above struct better defines how the hardware works, however +// to speed up the decryption at run time we convert it to the +// following one +struct optimised_sbox +{ + UINT8 input_lookup[256]; + UINT8 output[64]; +}; + + +static const struct sbox fn1_r1_boxes[4] = +{ + { // subkey bits 0- 5 + { + 0,2,2,0,1,0,1,1,3,2,0,3,0,3,1,2,1,1,1,2,1,3,2,2,2,3,3,2,1,1,1,2, + 2,2,0,0,3,1,3,1,1,1,3,0,0,1,0,0,1,2,2,1,2,3,2,2,2,3,1,3,2,0,1,3, + }, + { 3, 4, 5, 6, -1, -1 }, + { 3, 6 } + }, + { // subkey bits 6-11 + { + 3,0,2,2,2,1,1,1,1,2,1,0,0,0,2,3,2,3,1,3,0,0,0,2,1,2,2,3,0,3,3,3, + 0,1,3,2,3,3,3,1,1,1,1,2,0,1,2,1,3,2,3,1,1,3,2,2,2,3,1,3,2,3,0,0, + }, + { 0, 1, 2, 4, 7, -1 }, + { 2, 7 } + }, + { // subkey bits 12-17 + { + 3,0,3,1,1,0,2,2,3,1,2,0,3,3,2,3,0,1,0,1,2,3,0,2,0,2,0,1,0,0,1,0, + 2,3,1,2,1,0,2,0,2,1,0,1,0,2,1,0,3,1,2,3,1,3,1,1,1,2,0,2,2,0,0,0, + }, + { 0, 1, 2, 3, 6, 7 }, + { 0, 1 } + }, + { // subkey bits 18-23 + { + 3,2,0,3,0,2,2,1,1,2,3,2,1,3,2,1,2,2,1,3,3,2,1,0,1,0,1,3,0,0,0,2, + 2,1,0,1,0,1,0,1,3,1,1,2,2,3,2,0,3,3,2,0,2,1,3,3,0,0,3,0,1,1,3,3, + }, + { 0, 1, 3, 5, 6, 7 }, + { 4, 5 } + }, +}; + +static const struct sbox fn1_r2_boxes[4] = +{ + { // subkey bits 24-29 + { + 3,3,2,0,3,0,3,1,0,3,0,1,0,2,1,3,1,3,0,3,3,1,3,3,3,2,3,2,2,3,1,2, + 0,2,2,1,0,1,2,0,3,3,0,1,3,2,1,2,3,0,1,3,0,1,2,2,1,2,1,2,0,1,3,0, + }, + { 0, 1, 2, 3, 6, -1 }, + { 1, 6 } + }, + { // subkey bits 30-35 + { + 1,2,3,2,1,3,0,1,1,0,2,0,0,2,3,2,3,3,0,1,2,2,1,0,1,0,1,2,3,2,1,3, + 2,2,2,0,1,0,2,3,2,1,2,1,2,1,0,3,0,1,2,3,1,2,1,3,2,0,3,2,3,0,2,0, + }, + { 2, 4, 5, 6, 7, -1 }, + { 5, 7 } + }, + { // subkey bits 36-41 + { + 0,1,0,2,1,1,0,1,0,2,2,2,1,3,0,0,1,1,3,1,2,2,2,3,1,0,3,3,3,2,2,2, + 1,1,3,0,3,1,3,0,1,3,3,2,1,1,0,0,1,2,2,2,1,1,1,2,2,0,0,3,2,3,1,3, + }, + { 1, 2, 3, 4, 5, 7 }, + { 0, 3 } + }, + { // subkey bits 42-47 + { + 2,1,0,3,3,3,2,0,1,2,1,1,1,0,3,1,1,3,3,0,1,2,1,0,0,0,3,0,3,0,3,0, + 1,3,3,3,0,3,2,0,2,1,2,2,2,1,1,3,0,1,0,1,0,1,1,1,1,3,1,0,1,2,3,3, + }, + { 0, 1, 3, 4, 6, 7 }, + { 2, 4 } + }, +}; + +static const struct sbox fn1_r3_boxes[4] = +{ + { // subkey bits 48-53 + { + 0,0,0,3,3,1,1,0,2,0,2,0,0,0,3,2,0,1,2,3,2,2,1,0,3,0,0,0,0,0,2,3, + 3,0,0,1,1,2,3,3,0,1,3,2,0,1,3,3,2,0,0,1,0,2,0,0,0,3,1,3,3,3,3,3, + }, + { 0, 1, 5, 6, 7, -1 }, + { 0, 5 } + }, + { // subkey bits 54-59 + { + 2,3,2,3,0,2,3,0,2,2,3,0,3,2,0,2,1,0,2,3,1,1,1,0,0,1,0,2,1,2,2,1, + 3,0,2,1,2,3,3,0,3,2,3,1,0,2,1,0,1,2,2,3,0,2,1,3,1,3,0,2,1,1,1,3, + }, + { 2, 3, 4, 6, 7, -1 }, + { 6, 7 } + }, + { // subkey bits 60-65 + { + 3,0,2,1,1,3,1,2,2,1,2,2,2,0,0,1,2,3,1,0,2,0,0,2,3,1,2,0,0,0,3,0, + 2,1,1,2,0,0,1,2,3,1,1,2,0,1,3,0,3,1,1,0,0,2,3,0,0,0,0,3,2,0,0,0, + }, + { 0, 2, 3, 4, 5, 6 }, + { 1, 4 } + }, + { // subkey bits 66-71 + { + 0,1,0,0,2,1,3,2,3,3,2,1,0,1,1,1,1,1,0,3,3,1,1,0,0,2,2,1,0,3,3,2, + 1,3,3,0,3,0,2,1,1,2,3,2,2,2,1,0,0,3,3,3,2,2,3,1,0,2,3,0,3,1,1,0, + }, + { 0, 1, 2, 3, 5, 7 }, + { 2, 3 } + }, +}; + +static const struct sbox fn1_r4_boxes[4] = +{ + { // subkey bits 72-77 + { + 1,1,1,1,1,0,1,3,3,2,3,0,1,2,0,2,3,3,0,1,2,1,2,3,0,3,2,3,2,0,1,2, + 0,1,0,3,2,1,3,2,3,1,2,3,2,0,1,2,2,0,0,0,2,1,3,0,3,1,3,0,1,3,3,0, + }, + { 1, 2, 3, 4, 5, 7 }, + { 0, 4 } + }, + { // subkey bits 78-83 + { + 3,0,0,0,0,1,0,2,3,3,1,3,0,3,1,2,2,2,3,1,0,0,2,0,1,0,2,2,3,3,0,0, + 1,1,3,0,2,3,0,3,0,3,0,2,0,2,0,1,0,3,0,1,3,1,1,0,0,1,3,3,2,2,1,0, + }, + { 0, 1, 2, 3, 5, 6 }, + { 1, 3 } + }, + { // subkey bits 84-89 + { + 0,1,1,2,0,1,3,1,2,0,3,2,0,0,3,0,3,0,1,2,2,3,3,2,3,2,0,1,0,0,1,0, + 3,0,2,3,0,2,2,2,1,1,0,2,2,0,0,1,2,1,1,1,2,3,0,3,1,2,3,3,1,1,3,0, + }, + { 0, 2, 4, 5, 6, 7 }, + { 2, 6 } + }, + { // subkey bits 90-95 + { + 0,1,2,2,0,1,0,3,2,2,1,1,3,2,0,2,0,1,3,3,0,2,2,3,3,2,0,0,2,1,3,3, + 1,1,1,3,1,2,1,1,0,3,3,2,3,2,3,0,3,1,0,0,3,0,0,0,2,2,2,1,2,3,0,0, + }, + { 0, 1, 3, 4, 6, 7 }, + { 5, 7 } + }, +}; + +/******************************************************************************/ + +static const struct sbox fn2_r1_boxes[4] = +{ + { // subkey bits 0- 5 + { + 2,0,2,0,3,0,0,3,1,1,0,1,3,2,0,1,2,0,1,2,0,2,0,2,2,2,3,0,2,1,3,0, + 0,1,0,1,2,2,3,3,0,3,0,2,3,0,1,2,1,1,0,2,0,3,1,1,2,2,1,3,1,1,3,1, + }, + { 0, 3, 4, 5, 7, -1 }, + { 6, 7 } + }, + { // subkey bits 6-11 + { + 1,1,0,3,0,2,0,1,3,0,2,0,1,1,0,0,1,3,2,2,0,2,2,2,2,0,1,3,3,3,1,1, + 1,3,1,3,2,2,2,2,2,2,0,1,0,1,1,2,3,1,1,2,0,3,3,3,2,2,3,1,1,1,3,0, + }, + { 1, 2, 3, 4, 6, -1 }, + { 3, 5 } + }, + { // subkey bits 12-17 + { + 1,0,2,2,3,3,3,3,1,2,2,1,0,1,2,1,1,2,3,1,2,0,0,1,2,3,1,2,0,0,0,2, + 2,0,1,1,0,0,2,0,0,0,2,3,2,3,0,1,3,0,0,0,2,3,2,0,1,3,2,1,3,1,1,3, + }, + { 1, 2, 4, 5, 6, 7 }, + { 1, 4 } + }, + { // subkey bits 18-23 + { + 1,3,3,0,3,2,3,1,3,2,1,1,3,3,2,1,2,3,0,3,1,0,0,2,3,0,0,0,3,3,0,1, + 2,3,0,0,0,1,2,1,3,0,0,1,0,2,2,2,3,3,1,2,1,3,0,0,0,3,0,1,3,2,2,0, + }, + { 0, 2, 3, 5, 6, 7 }, + { 0, 2 } + }, +}; + +static const struct sbox fn2_r2_boxes[4] = +{ + { // subkey bits 24-29 + { + 3,1,3,0,3,0,3,1,3,0,0,1,1,3,0,3,1,1,0,1,2,3,2,3,3,1,2,2,2,0,2,3, + 2,2,2,1,1,3,3,0,3,1,2,1,1,1,0,2,0,3,3,0,0,2,0,0,1,1,2,1,2,1,1,0, + }, + { 0, 2, 4, 6, -1, -1 }, + { 4, 6 } + }, + { // subkey bits 30-35 + { + 0,3,0,3,3,2,1,2,3,1,1,1,2,0,2,3,0,3,1,2,2,1,3,3,3,2,1,2,2,0,1,0, + 2,3,0,1,2,0,1,1,2,0,2,1,2,0,2,3,3,1,0,2,3,3,0,3,1,1,3,0,0,1,2,0, + }, + { 1, 3, 4, 5, 6, 7 }, + { 0, 3 } + }, + { // subkey bits 36-41 + { + 0,0,2,1,3,2,1,0,1,2,2,2,1,1,0,3,1,2,2,3,2,1,1,0,3,0,0,1,1,2,3,1, + 3,3,2,2,1,0,1,1,1,2,0,1,2,3,0,3,3,0,3,2,2,0,2,2,1,2,3,2,1,0,2,1, + }, + { 0, 1, 3, 4, 5, 7 }, + { 1, 7 } + }, + { // subkey bits 42-47 + { + 0,2,1,2,0,2,2,0,1,3,2,0,3,2,3,0,3,3,2,3,1,2,3,1,2,2,0,0,2,2,1,2, + 2,3,3,3,1,1,0,0,0,3,2,0,3,2,3,1,1,1,1,0,1,0,1,3,0,0,1,2,2,3,2,0, + }, + { 1, 2, 3, 5, 6, 7 }, + { 2, 5 } + }, +}; + +static const struct sbox fn2_r3_boxes[4] = +{ + { // subkey bits 48-53 + { + 2,1,2,1,2,3,1,3,2,2,1,3,3,0,0,1,0,2,0,3,3,1,0,0,1,1,0,2,3,2,1,2, + 1,1,2,1,1,3,2,2,0,2,2,3,3,3,2,0,0,0,0,0,3,3,3,0,1,2,1,0,2,3,3,1, + }, + { 2, 3, 4, 6, -1, -1 }, + { 3, 5 } + }, + { // subkey bits 54-59 + { + 3,2,3,3,1,0,3,0,2,0,1,1,1,0,3,0,3,1,3,1,0,1,2,3,2,2,3,2,0,1,1,2, + 3,0,0,2,1,0,0,2,2,0,1,0,0,2,0,0,1,3,1,3,2,0,3,3,1,0,2,2,2,3,0,0, + }, + { 0, 1, 3, 5, 7, -1 }, + { 0, 2 } + }, + { // subkey bits 60-65 + { + 2,2,1,0,2,3,3,0,0,0,1,3,1,2,3,2,2,3,1,3,0,3,0,3,3,2,2,1,0,0,0,2, + 1,2,2,2,0,0,1,2,0,1,3,0,2,3,2,1,3,2,2,2,3,1,3,0,2,0,2,1,0,3,3,1, + }, + { 0, 1, 2, 3, 5, 7 }, + { 1, 6 } + }, + { // subkey bits 66-71 + { + 1,2,3,2,0,2,1,3,3,1,0,1,1,2,2,0,0,1,1,1,2,1,1,2,0,1,3,3,1,1,1,2, + 3,3,1,0,2,1,1,1,2,1,0,0,2,2,3,2,3,2,2,0,2,2,3,3,0,2,3,0,2,2,1,1, + }, + { 0, 2, 4, 5, 6, 7 }, + { 4, 7 } + }, +}; + +static const struct sbox fn2_r4_boxes[4] = +{ + { // subkey bits 72-77 + { + 2,0,1,1,2,1,3,3,1,1,1,2,0,1,0,2,0,1,2,0,2,3,0,2,3,3,2,2,3,2,0,1, + 3,0,2,0,2,3,1,3,2,0,0,1,1,2,3,1,1,1,0,1,2,0,3,3,1,1,1,3,3,1,1,0, + }, + { 0, 1, 3, 6, 7, -1 }, + { 0, 3 } + }, + { // subkey bits 78-83 + { + 1,2,2,1,0,3,3,1,0,2,2,2,1,0,1,0,1,1,0,1,0,2,1,0,2,1,0,2,3,2,3,3, + 2,2,1,2,2,3,1,3,3,3,0,1,0,1,3,0,0,0,1,2,0,3,3,2,3,2,1,3,2,1,0,2, + }, + { 0, 1, 2, 4, 5, 6 }, + { 4, 7 } + }, + { // subkey bits 84-89 + { + 2,3,2,1,3,2,3,0,0,2,1,1,0,0,3,2,3,1,0,1,2,2,2,1,3,2,2,1,0,2,1,2, + 0,3,1,0,0,3,1,1,3,3,2,0,1,0,1,3,0,0,1,2,1,2,3,2,1,0,0,3,2,1,1,3, + }, + { 0, 2, 3, 4, 5, 7 }, + { 1, 2 } + }, + { // subkey bits 90-95 + { + 2,0,0,3,2,2,2,1,3,3,1,1,2,0,0,3,1,0,3,2,1,0,2,0,3,2,2,3,2,0,3,0, + 1,3,0,2,2,1,3,3,0,1,0,3,1,1,3,2,0,3,0,2,3,2,1,3,2,3,0,0,1,3,2,1, + }, + { 2, 3, 4, 5, 6, 7 }, + { 5, 6 } + }, +}; + +/******************************************************************************/ + + +static UINT8 fn(UINT8 in, const struct optimised_sbox *sboxes, UINT32 key) +{ + const struct optimised_sbox *sbox1 = &sboxes[0]; + const struct optimised_sbox *sbox2 = &sboxes[1]; + const struct optimised_sbox *sbox3 = &sboxes[2]; + const struct optimised_sbox *sbox4 = &sboxes[3]; + + return + sbox1->output[sbox1->input_lookup[in] ^ ((key >> 0) & 0x3f)] | + sbox2->output[sbox2->input_lookup[in] ^ ((key >> 6) & 0x3f)] | + sbox3->output[sbox3->input_lookup[in] ^ ((key >> 12) & 0x3f)] | + sbox4->output[sbox4->input_lookup[in] ^ ((key >> 18) & 0x3f)]; +} + + + +// srckey is the 64-bit master key (2x32 bits) +// dstkey will contain the 96-bit key for the 1st FN (4x24 bits) +static void expand_1st_key(UINT32 *dstkey, const UINT32 *srckey) +{ + static const INT32 bits[96] = + { + 33, 58, 49, 36, 0, 31, + 22, 30, 3, 16, 5, 53, + 10, 41, 23, 19, 27, 39, + 43, 6, 34, 12, 61, 21, + 48, 13, 32, 35, 6, 42, + 43, 14, 21, 41, 52, 25, + 18, 47, 46, 37, 57, 53, + 20, 8, 55, 54, 59, 60, + 27, 33, 35, 18, 8, 15, + 63, 1, 50, 44, 16, 46, + 5, 4, 45, 51, 38, 25, + 13, 11, 62, 29, 48, 2, + 59, 61, 62, 56, 51, 57, + 54, 9, 24, 63, 22, 7, + 26, 42, 45, 40, 23, 14, + 2, 31, 52, 28, 44, 17, + }; + INT32 i; + + dstkey[0] = 0; + dstkey[1] = 0; + dstkey[2] = 0; + dstkey[3] = 0; + + for (i = 0; i < 96; ++i) + dstkey[i / 24] |= BIT(srckey[bits[i] / 32], bits[i] % 32) << (i % 24); +} + + +// srckey is the 64-bit master key (2x32 bits) XORed with the subkey +// dstkey will contain the 96-bit key for the 2nd FN (4x24 bits) +static void expand_2nd_key(UINT32 *dstkey, const UINT32 *srckey) +{ + static const INT32 bits[96] = + { + 34, 9, 32, 24, 44, 54, + 38, 61, 47, 13, 28, 7, + 29, 58, 18, 1, 20, 60, + 15, 6, 11, 43, 39, 19, + 63, 23, 16, 62, 54, 40, + 31, 3, 56, 61, 17, 25, + 47, 38, 55, 57, 5, 4, + 15, 42, 22, 7, 2, 19, + 46, 37, 29, 39, 12, 30, + 49, 57, 31, 41, 26, 27, + 24, 36, 11, 63, 33, 16, + 56, 62, 48, 60, 59, 32, + 12, 30, 53, 48, 10, 0, + 50, 35, 3, 59, 14, 49, + 51, 45, 44, 2, 21, 33, + 55, 52, 23, 28, 8, 26, + }; + INT32 i; + + dstkey[0] = 0; + dstkey[1] = 0; + dstkey[2] = 0; + dstkey[3] = 0; + + for (i = 0; i < 96; ++i) + dstkey[i / 24] |= BIT(srckey[bits[i] / 32], bits[i] % 32) << (i % 24); +} + + + +// seed is the 16-bit seed generated by the first FN +// subkey will contain the 64-bit key to be XORed with the master key +// for the 2nd FN (2x32 bits) +static void expand_subkey(UINT32* subkey, UINT16 seed) +{ + // Note that each row of the table is a permutation of the seed bits. + static const INT32 bits[64] = + { + 5, 10, 14, 9, 4, 0, 15, 6, 1, 8, 3, 2, 12, 7, 13, 11, + 5, 12, 7, 2, 13, 11, 9, 14, 4, 1, 6, 10, 8, 0, 15, 3, + 4, 10, 2, 0, 6, 9, 12, 1, 11, 7, 15, 8, 13, 5, 14, 3, + 14, 11, 12, 7, 4, 5, 2, 10, 1, 15, 0, 9, 8, 6, 13, 3, + }; + INT32 i; + + subkey[0] = 0; + subkey[1] = 0; + + for (i = 0; i < 64; ++i) + subkey[i / 32] |= BIT(seed, bits[i]) << (i % 32); +} + + + +static UINT16 feistel(UINT16 val, const INT32 *bitsA, const INT32 *bitsB, + const struct optimised_sbox* boxes1, const struct optimised_sbox* boxes2, const struct optimised_sbox* boxes3, const struct optimised_sbox* boxes4, + UINT32 key1, UINT32 key2, UINT32 key3, UINT32 key4) +{ + UINT8 l = BITSWAP8(val, bitsB[7],bitsB[6],bitsB[5],bitsB[4],bitsB[3],bitsB[2],bitsB[1],bitsB[0]); + UINT8 r = BITSWAP8(val, bitsA[7],bitsA[6],bitsA[5],bitsA[4],bitsA[3],bitsA[2],bitsA[1],bitsA[0]); + + l ^= fn(r, boxes1, key1); + r ^= fn(l, boxes2, key2); + l ^= fn(r, boxes3, key3); + r ^= fn(l, boxes4, key4); + + return + (BIT(l, 0) << bitsA[0]) | + (BIT(l, 1) << bitsA[1]) | + (BIT(l, 2) << bitsA[2]) | + (BIT(l, 3) << bitsA[3]) | + (BIT(l, 4) << bitsA[4]) | + (BIT(l, 5) << bitsA[5]) | + (BIT(l, 6) << bitsA[6]) | + (BIT(l, 7) << bitsA[7]) | + (BIT(r, 0) << bitsB[0]) | + (BIT(r, 1) << bitsB[1]) | + (BIT(r, 2) << bitsB[2]) | + (BIT(r, 3) << bitsB[3]) | + (BIT(r, 4) << bitsB[4]) | + (BIT(r, 5) << bitsB[5]) | + (BIT(r, 6) << bitsB[6]) | + (BIT(r, 7) << bitsB[7]); +} + + + +static INT32 extract_inputs(UINT32 val, const INT32 *inputs) +{ + INT32 i; + INT32 res = 0; + + for (i = 0; i < 6; ++i) + { + if (inputs[i] != -1) + res |= BIT(val, inputs[i]) << i; + } + + return res; +} + + + +static void optimise_sboxes(struct optimised_sbox* out, const struct sbox* in) +{ + INT32 box; + + for (box = 0; box < 4; ++box) + { + INT32 i; + + // precalculate the input lookup + for (i = 0; i < 256; ++i) + { + out[box].input_lookup[i] = extract_inputs(i, in[box].inputs); + } + + // precalculate the output masks + for (i = 0; i < 64; ++i) + { + INT32 o = in[box].table[i]; + + out[box].output[i] = 0; + if (o & 1) + out[box].output[i] |= 1 << in[box].outputs[0]; + if (o & 2) + out[box].output[i] |= 1 << in[box].outputs[1]; + } + } +} + +static void cps2_decrypt(const UINT32 *master_key, UINT32 upper_limit) +{ +#if 0 + UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1); + INT32 length = memory_region_length(REGION_CPU1); + UINT16 *dec = auto_malloc(length); + INT32 i; +#endif + +#if 1 + UINT16 *rom = (UINT16 *)CpsRom; + UINT32 length = upper_limit; + CpsCode = (UINT8*)malloc(length); + UINT16 *dec = (UINT16*)CpsCode; + UINT32 i; +#endif + + UINT32 key1[4]; + struct optimised_sbox sboxes1[4*4]; + struct optimised_sbox sboxes2[4*4]; + + optimise_sboxes(&sboxes1[0*4], fn1_r1_boxes); + optimise_sboxes(&sboxes1[1*4], fn1_r2_boxes); + optimise_sboxes(&sboxes1[2*4], fn1_r3_boxes); + optimise_sboxes(&sboxes1[3*4], fn1_r4_boxes); + optimise_sboxes(&sboxes2[0*4], fn2_r1_boxes); + optimise_sboxes(&sboxes2[1*4], fn2_r2_boxes); + optimise_sboxes(&sboxes2[2*4], fn2_r3_boxes); + optimise_sboxes(&sboxes2[3*4], fn2_r4_boxes); + + + // expand master key to 1st FN 96-bit key + expand_1st_key(key1, master_key); + + // add extra bits for s-boxes with less than 6 inputs + key1[0] ^= BIT(key1[0], 1) << 4; + key1[0] ^= BIT(key1[0], 2) << 5; + key1[0] ^= BIT(key1[0], 8) << 11; + key1[1] ^= BIT(key1[1], 0) << 5; + key1[1] ^= BIT(key1[1], 8) << 11; + key1[2] ^= BIT(key1[2], 1) << 5; + key1[2] ^= BIT(key1[2], 8) << 11; + + for (i = 0; i < 0x10000; ++i) + { +#if 0 + INT32 a; +#endif + +#if 1 + UINT32 a; +#endif + + UINT16 seed; + UINT32 subkey[2]; + UINT32 key2[4]; + + if ((i & 0xff) == 0) + { +#if 0 + char loadingMessage[256]; // for displaying with UI + sprintf(loadingMessage, "Decrypting %d%%", i*100/0x10000); + ui_set_startup_text(loadingMessage,FALSE); +#endif + +#if 1 + TCHAR loadingMessage[256]; // for displaying with UI + _stprintf(loadingMessage, _T("Decrypting 68000 ROMs with key %d %s"), (i*100/0x10000), _T("%")); + BurnUpdateProgress(0.0, loadingMessage, 0); +#endif + } + + + // pass the address through FN1 + seed = feistel(i, fn1_groupA, fn1_groupB, + &sboxes1[0*4], &sboxes1[1*4], &sboxes1[2*4], &sboxes1[3*4], + key1[0], key1[1], key1[2], key1[3]); + + + // expand the result to 64-bit + expand_subkey(subkey, seed); + + // XOR with the master key + subkey[0] ^= master_key[0]; + subkey[1] ^= master_key[1]; + + // expand key to 2nd FN 96-bit key + expand_2nd_key(key2, subkey); + + // add extra bits for s-boxes with less than 6 inputs + key2[0] ^= BIT(key2[0], 0) << 5; + key2[0] ^= BIT(key2[0], 6) << 11; + key2[1] ^= BIT(key2[1], 0) << 5; + key2[1] ^= BIT(key2[1], 1) << 4; + key2[2] ^= BIT(key2[2], 2) << 5; + key2[2] ^= BIT(key2[2], 3) << 4; + key2[2] ^= BIT(key2[2], 7) << 11; + key2[3] ^= BIT(key2[3], 1) << 5; + + + // decrypt the opcodes + for (a = i; a < length/2 && a < upper_limit/2; a += 0x10000) + { + dec[a] = feistel(rom[a], fn2_groupA, fn2_groupB, + &sboxes2[0*4], &sboxes2[1*4], &sboxes2[2*4], &sboxes2[3*4], + key2[0], key2[1], key2[2], key2[3]); + } + // copy the unencrypted part (not really needed) + while (a < length/2) + { + dec[a] = rom[a]; + a += 0x10000; + } + } +#if 0 + memory_set_decrypted_region(0, 0x000000, length - 1, dec); + m68k_set_encrypted_opcode_range(0,0,length); +#endif +} + + + + + + + +struct game_keys +{ + const char *name; /* game driver name */ + const UINT32 keys[2]; + UINT32 upper_limit; +}; + + +/* +(1) On a dead board, the only encrypted range is actually FF0000-FFFFFF. +It doesn't start from 0, and it's the upper half of a 128kB bank. +*/ + +static const struct game_keys keys_table[] = +{ + // name key upper watchdog + { "dead", { 0xffffffff,0xffffffff }, 0 }, // ffff ffff ffff + { "ssf2", { 0x23456789,0xabcdef01 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2u", { 0x12345678,0x9abcdef0 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2a", { 0x3456789a,0xbcdef012 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2ar1", { 0x3456789a,0xbcdef012 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2j", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2jr1", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2jr2", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2h", { 0x56789abc,0xdef01234 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2tb", { 0x89abcdef,0x01234567 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2tbr1", { 0x89abcdef,0x01234567 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2tbj", { 0x6789abcd,0xef012345 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ddtod", { 0x4767fe08,0x14ca35d9 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodr1", { 0x4767fe08,0x14ca35d9 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodu", { 0xeca19c3d,0x24736bf0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodur1", { 0xeca19c3d,0x24736bf0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodj", { 0x4510e79c,0xf36b8a2d }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodjr1", { 0x4510e79c,0xf36b8a2d }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodjr2", { 0x4510e79c,0xf36b8a2d }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtoda", { 0xdecac105,0x19710411 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodh", { 0x19691019,0xe825dde0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodhr1", { 0x19691019,0xe825dde0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ddtodhr2", { 0x19691019,0xe825dde0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000 + { "ecofghtr", { 0x931031dc,0xba987654 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "ecofghtru", { 0x931031ed,0xcba98765 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "ecofghtru1", { 0x931031ed,0xcba98765 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "uecology", { 0x931031fe,0xdcba9876 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "ecofghtra", { 0x931031ba,0x98765432 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "ecofghtrh", { 0x931031cb,0xa9876543 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345 + { "ssf2t", { 0x944e8302,0x56d3143c }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2ta", { 0x94c4d002,0x664a1471 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2tu", { 0x94fa8902,0x4c77143f }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2tur1", { 0x94fa8902,0x4c77143f }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "ssf2xj", { 0x942a5702,0x05ac140e }, 0x400000 }, // 0838 0007 2000 btst #7,$2000 + { "xmcota", { 0x3bc6eda4,0x97f80251 }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotau", { 0x32a57ecd,0x98016f4b }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotah", { 0xf5e8dc34,0xa096b217 }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotahr1", { 0xf5e8dc34,0xa096b217 }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaj", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaj1", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaj2", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaj3", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotajr", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaa", { 0x0795a4e2,0xdb3f861c }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "xmcotaar1", { 0x0795a4e2,0xdb3f861c }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0 + { "armwar", { 0x9e9d4c0b,0x8a39081f }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "armwarr1", { 0x9e9d4c0b,0x8a39081f }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "armwaru", { 0xd4c0b8a3,0x9081f9e9 }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "armwaru1", { 0xd4c0b8a3,0x9081f9e9 }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "pgear", { 0x9d4c0b8a,0x39081f9e }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "pgearr1", { 0x9d4c0b8a,0x39081f9e }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "armwara", { 0x1f9e9d4c,0x0b8a3908 }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0 + { "avsp", { 0x15208f79,0x4ade6cb3 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0 + { "avspu", { 0xb4f61089,0xccf75a23 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0 + { "avspj", { 0xe9dcb8fa,0x51372064 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0 + { "avspa", { 0xc168f3bd,0x2e4a5970 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0 + { "avsph", { 0x712b690a,0x43cd8e5f }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0 + { "dstlk", { 0x13d8a7a8,0x0008b090 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "dstlku", { 0x1e80ebf0,0x10227119 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "dstlkur1", { 0x1e80ebf0,0x10227119 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "dstlka", { 0x205d8398,0x06221971 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "dstlkh", { 0x22463efe,0x011169aa }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "vampj", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "vampja", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "vampjr1", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160 + { "ringdest", { 0x19940727,0x17444903 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0 + { "smbomb", { 0x19940209,0x17031403 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0 + { "smbombr1", { 0x19940209,0x17031403 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0 + { "ringdesta", { 0x19940727,0x17452103 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0 + { "cybots", { 0x45425943,0x05090901 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38 + { "cybotsu", { 0x43050909,0x01554259 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38 + { "cybotsj", { 0x05090901,0x4a425943 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38 + { "msh", { 0x1a11ee26,0xe7955d17 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "mshu", { 0x8705a24e,0x4a17319b }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "mshj", { 0x05e88219,0x31ad2142 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "mshjr1", { 0x05e88219,0x31ad2142 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "msha", { 0x457aeb01,0x3897c53d }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "mshh", { 0xfc4c5a50,0xb59cc190 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "mshb", { 0x7a152416,0xad27f8e6 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "nwarr", { 0x1019d145,0x03f05a05 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "nwarru", { 0x104a7d0c,0x3f1b7a1e }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "nwarrh", { 0xc4961b01,0x2a946020 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "nwarrb", { 0x17c67109,0xb7362a20 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "nwarra", { 0x4e940d0c,0x39b861a4 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "vhuntj", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "vhuntjr1", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "vhuntjr2", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160 + { "sfa", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfar1", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfar2", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfar3", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfau", { 0x25bead36,0x97cf4018 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfza", { 0xe43dc508,0x621b9a7f }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzj", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzjr1", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzjr2", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzh", { 0x876b0e39,0x5ca24fd1 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzhr1", { 0x876b0e39,0x5ca24fd1 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzb", { 0xef415bd3,0x7a92c680 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "sfzbr1", { 0xef415bd3,0x7a92c680 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "mmancp2u", { 0x054893fa,0x94642525 }, 0x100000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "rmancp2j", { 0x07215501,0x37fa32d0 }, 0x100000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0 + { "19xx", { 0x0e07181f,0x5fd0f080 }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "19xxa", { 0xcce74cf5,0xb7da3711 }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "19xxj", { 0x00115df8,0x000ff87e }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "19xxjr1", { 0x00115df8,0x000ff87e }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "19xxh", { 0x5d49bafa,0xf7216c9f }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "19xxb", { 0xe5f9476a,0x2dfb623f }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1 + { "ddsom", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomr1", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomr2", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomr3", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomu", { 0x489f0526,0x1bcd3e7a }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomur1", { 0x489f0526,0x1bcd3e7a }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomj", { 0xae92fa94,0x315a9045 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomjr1", { 0xae92fa94,0x315a9045 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsoma", { 0x8719abcd,0xef028345 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomh", { 0x42134245,0x120de607 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "ddsomb", { 0x7149a782,0xf3a5bfce }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1 + { "megaman2", { 0x50501cac,0xed346550 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0 + { "megaman2a", { 0x3f148a2b,0xd6790a15 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0 + { "rockman2j", { 0x319eca73,0x10551270 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0 + { "megaman2h" ,{ 0x765573ca,0x250210d0 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0 + { "qndream", { 0x5804ea73,0xf66b0798 }, 0x080000 }, // 0C81 1973 0827 cmpi.l #$19730827,D1 + { "sfa2", { 0xfc4acf9c,0x3bfbe1f9 }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfa2u", { 0x1bbf3d96,0x8af4614a }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfa2ur1", { 0x1bbf3d96,0x8af4614a }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2j", { 0x83f47e99,0xda772111 }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2a", { 0xafc2e8f4,0x43789487 }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2b", { 0xac134599,0x61f8bb2e }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2br1", { 0xac134599,0x61f8bb2e }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2h", { 0xf98a2d42,0x597b089f }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2n", { 0xe32bf89c,0xa57b46dc }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0 + { "sfz2al", { 0xf172c0d0,0x040621a6 }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0 + { "sfz2alj", { 0x99450c88,0xa00a2c4d }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0 + { "sfz2alh", { 0x95f15b7c,0x200c08c6 }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0 + { "sfz2alb", { 0x73cd4a28,0xff83af1c }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0 + { "spf2t", { 0x706a8750,0x7d0fc185 }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0 + { "spf2xj", { 0xb12c835a,0xe90976ff }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0 + { "spf2ta", { 0x9c48e1ab,0xd60f34fb }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0 + { "spf2th", { 0x51ed8cab,0x228f85b6 }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0 + { "xmvsf", { 0xbdcf8519,0x3fb2acea }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfr1", { 0xbdcf8519,0x3fb2acea }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfu", { 0x4fcb03d2,0xf8653bc1 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfur1", { 0x4fcb03d2,0xf8653bc1 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfj", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfjr1", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfjr2", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfa", { 0x7438fc3e,0x19abed90 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfar1", { 0x7438fc3e,0x19abed90 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfar2", { 0x7438fc3e,0x19abed90 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfh", { 0x835fb2d0,0x42fa9137 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "xmvsfb", { 0x8ead9e4a,0xb02184f0 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1 + { "batcir", { 0xd195e597,0x3cbce2b5 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1 + { "batcira", { 0x1e5d80cb,0x98882ec7 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1 + { "batcirj", { 0x00ff4dd8,0x000008e8 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1 + { "csclub", { 0x662e9fa0,0x4210e7c1 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "csclub1", { 0x662e9fa0,0x4210e7c1 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "cscluba", { 0x1366de2a,0x9ab42937 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "csclubj", { 0x4a2d0be5,0x56c013c0 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "csclubjr", { 0x4a2d0be5,0x56c013c0 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "csclubh", { 0xf014a8a7,0x2e7794d0 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1 + { "mshvsf", { 0x1384ae60,0x9cd725bf }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfu", { 0xa36d4971,0xcef51b28 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfu1", { 0xa36d4971,0xcef51b28 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfj", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfj1", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfj2", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfh", { 0x7e916fc4,0x03ab852d }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfa", { 0x52e3fa61,0x0c497bd8 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfa1", { 0x52e3fa61,0x0c497bd8 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfb", { 0xda68c749,0x5bf3e201 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mshvsfb1", { 0xda68c749,0x5bf3e201 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "sgemf", { 0x84234976,0x5e0fbb7e }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0 + { "pfghtj", { 0x97d2ebc0,0x308f94d7 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0 + { "sgemfa", { 0x090b412a,0xc47ee993 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0 + { "sgemfh", { 0x8163a71b,0x7c8fd224 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0 + { "vhunt2", { 0x36c1eba3,0x26b10f18 }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0 + { "vhunt2r1", { 0x36c1eba3,0x26b10f18 }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0 + { "vsav", { 0xe0cd5881,0x71babb70 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0 + { "vsavu", { 0xa62ea0ee,0x573e03e6 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0 + { "vsavj", { 0xfa8f4e33,0xa4b881b9 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0 + { "vsava", { 0x47ee9930,0x90b412ac }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0 + { "vsavh", { 0xb2d37c8d,0xd3b7aadd }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0 + { "vsav2", { 0xd681e4f4,0x60371edf }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0 + { "mvsc", { 0x48025ade,0x1c697b27 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscr1", { 0x48025ade,0x1c697b27 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscu", { 0x692dc41b,0x7ef1c805 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscur1", { 0x692dc41b,0x7ef1c805 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscj", { 0xafc16138,0x97123eb0 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscjr1", { 0xafc16138,0x97123eb0 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvsca", { 0xf248aec6,0x7905cd17 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscar1", { 0xf248aec6,0x7905cd17 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvsch", { 0x9d5c7a23,0xe56b18ef }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "mvscb", { 0x0874d6eb,0x51c2b798 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1 + { "sfa3", { 0x6abfc8e0,0x2780ddc1 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfa3u", { 0xe7bbf0e5,0x67943248 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfa3ur1", { 0xe7bbf0e5,0x67943248 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfa3h", { 0x8422df8c,0x7b17a361 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfa3hr1", { 0x8422df8c,0x7b17a361 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfa3b", { 0xd421c0b2,0x8116d296 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfz3j", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfz3jr1", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfz3jr2", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfz3a", { 0x990b9301,0xa4e42c7e }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "sfz3ar1", { 0x990b9301,0xa4e42c7e }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0 + { "jyangoku", { 0x6ca42ae6,0x92f63f59 }, 0 }, // 0C80 3652 1573 cmpi.l #$36521573,D0 + { "hsf2", { 0x5a369ddd,0xfea3189c }, 0x100000 }, // 0838 0007 2000 btst #7,$2000 + { "hsf2a", { 0xb8ed3630,0xaae30a3d }, 0x100000 }, // 0838 0007 2000 btst #7,$2000 + { "hsf2j", { 0x65d82fe0,0xdbb83e47 }, 0x100000 }, // 0838 0007 2000 btst #7,$2000 + { "gigawing", { 0xe52de290,0x1b60d780 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "gigawingj", { 0x1126196a,0xbef50895 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "gigawinga", { 0x3506a85a,0x66b1b768 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "gigawingh", { 0xcea74211,0x400da385 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "gigawingb", { 0x0fe745b0,0x96ef7f9d }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1 + { "mmatrix", { 0xac9ebd79,0x410467df }, 0x180000 }, // B6C0 B447 BACF cmpa.w D0,A3 cmp.w D7,D2 cmpa.w A7,A5 + { "mmatrixj", { 0x4df81e95,0x72ed9823 }, 0x180000 }, // B6C0 B447 BACF cmpa.w D0,A3 cmp.w D7,D2 cmpa.w A7,A5 + { "mpang", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4 + { "mpangr1", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4 + { "mpangu", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4 + { "mpangj", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4 + { "pzloop2", { 0xa054f812,0xc40d36b4 }, 0x400000 }, // 0C82 9A73 15F1 cmpi.l #$9A7315F1,D2 + { "pzloop2j", { 0xa054f812,0xc40d36b4 }, 0x400000 }, // 0C82 9A73 15F1 cmpi.l #$9A7315F1,D2 + { "choko", { 0xd3fb12c6,0x7f8e17b5 }, 0x400000 }, // 0C86 4D17 5B3C cmpi.l #$4D175B3C,D6 + { "dimahoo", { 0x0ddb8e40,0x2817fd2b }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3 + { "dimahoou", { 0x6575af59,0xb0fea691 }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3 + { "gmahou", { 0x97f7be58,0x6121eb62 }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3 + { "1944", { 0x1d3e724c,0x8b59fc7a }, 0x080000 }, // 0C86 7B5D 94F1 cmpi.l #$7B5D94F1,D6 + { "1944j", { 0x23d79c3a,0xe18b2746 }, 0x080000 }, // 0C86 7B5D 94F1 cmpi.l #$7B5D94F1,D6 + { "progear", { 0x639ad8c6,0xef130df3 }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1 + { "progearj", { 0x9f7edc56,0x39fb47be }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1 + { "progeara", { 0x658ab128,0xfddc9b5e }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1 + +#if 0 + { 0 } // end of table +#endif + +#if 1 + { 0, { 0, 0 }, 0 } // end of table +#endif +}; + + + +#if 1 +void cps2_decrypt_game_data() +{ + const char *gamename = BurnDrvGetTextA(DRV_NAME); + const struct game_keys *k = &keys_table[0]; + + while (k->name) + { + if (strcmp(k->name, gamename) == 0) + { + break; + } + ++k; + } + + if (k->name) + { + nCpsCodeLen = k->upper_limit ? k->upper_limit : nCpsRomLen; + + // we have a proper key so use it to decrypt + cps2_decrypt(k->keys, nCpsCodeLen); + } + else + { + // we don't have a proper key so use the XOR tables if available + if (CpsCode) { + UINT16 *rom = (UINT16*)CpsRom; + UINT16 *xor1 = (UINT16*)CpsCode; + INT32 length = nCpsCodeLen; + INT32 i; + + if (xor1) + { + for (i = 0; i < length/2; i++) + xor1[i] ^= rom[i]; + } + } + } +} +#endif + +#if 0 +DRIVER_INIT( cps2 ) +{ + const char *gamename = machine->gamedrv->name; + const struct game_keys *k = &keys_table[0]; + + while (k->name) + { + if (strcmp(k->name, gamename) == 0) + { + // we have a proper key so use it to decrypt + cps2_decrypt(k->keys, k->upper_limit ? k->upper_limit : 0x400000); + + break; + } + ++k; + } + + init_cps2_video(machine); +} +#endif diff --git a/src/burn/drivers/capcom/cps_config.cpp b/src/burn/drivers/capcom/cps_config.cpp new file mode 100644 index 00000000..85391b02 --- /dev/null +++ b/src/burn/drivers/capcom/cps_config.cpp @@ -0,0 +1,1605 @@ +#include "cps.h" + +struct GfxRange { + INT32 Type; + INT32 Start; + INT32 End; + INT32 Bank; +}; + +static const struct GfxRange *GfxBankMapper = NULL; +static INT32 GfxBankSizes[4] = { 0, 0, 0, 0 }; + +static const struct GfxRange mapper_LWCHR_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x07fff, 0 }, + { GFXTYPE_SCROLL1, 0x00000, 0x1ffff, 0 }, + + { GFXTYPE_STARS, 0x00000, 0x1ffff, 1 }, + { GFXTYPE_SCROLL2, 0x00000, 0x1ffff, 1 }, + { GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_LW621_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x07fff, 0 }, + { GFXTYPE_SCROLL1, 0x00000, 0x1ffff, 0 }, + + { GFXTYPE_STARS, 0x00000, 0x1ffff, 1 }, + { GFXTYPE_SCROLL2, 0x00000, 0x1ffff, 1 }, + { GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_DM620_table[] = { + { GFXTYPE_SCROLL3, 0x8000, 0xbfff, 1 }, + + { GFXTYPE_SPRITES, 0x2000, 0x3fff, 2 }, + + { GFXTYPE_STARS | GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_DM22A_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x01fff, 0 }, + { GFXTYPE_SCROLL1, 0x02000, 0x03fff, 0 }, + + { GFXTYPE_SCROLL2, 0x04000, 0x07fff, 1 }, + + { GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 2 }, + + { GFXTYPE_SPRITES, 0x02000, 0x03fff, 3 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_DAM63B_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x01fff, 0 }, + { GFXTYPE_SCROLL1, 0x02000, 0x02fff, 0 }, + { GFXTYPE_SCROLL2, 0x04000, 0x07fff, 0 }, + + { GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 1 }, + { GFXTYPE_SPRITES, 0x02000, 0x03fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_ST24M1_table[] = +{ + { GFXTYPE_STARS, 0x00000, 0x003ff, 0 }, + { GFXTYPE_SPRITES, 0x00000, 0x04fff, 0 }, + { GFXTYPE_SCROLL2, 0x04000, 0x07fff, 0 }, + + { GFXTYPE_SCROLL3, 0x00000, 0x07fff, 1 }, + { GFXTYPE_SCROLL1, 0x07000, 0x07fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_ST22B_table[] = { + { GFXTYPE_STARS, 0x00000, 0x1ffff, 0 }, + { GFXTYPE_SPRITES, 0x00000, 0x03fff, 0 }, + + { GFXTYPE_SPRITES, 0x04000, 0x04fff, 1 }, + { GFXTYPE_SCROLL2, 0x04000, 0x07fff, 1 }, + + { GFXTYPE_SCROLL3, 0x00000, 0x03fff, 2 }, + + { GFXTYPE_SCROLL3, 0x04000, 0x07fff, 3 }, + { GFXTYPE_SCROLL1, 0x07000, 0x07fff, 3 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_TK22B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x3fff, 0 }, + + { GFXTYPE_SPRITES, 0x4000, 0x5fff, 1 }, + { GFXTYPE_SCROLL1, 0x6000, 0x7fff, 1 }, + + { GFXTYPE_SCROLL3, 0x0000, 0x3fff, 2 }, + + { GFXTYPE_SCROLL2, 0x4000, 0x7fff, 3 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_WL24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x4fff, 0 }, + { GFXTYPE_SCROLL3, 0x5000, 0x6fff, 0 }, + { GFXTYPE_SCROLL1, 0x7000, 0x7fff, 0 }, + + { GFXTYPE_SCROLL2, 0x0000, 0x3fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_S224B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x43ff, 0 }, + { GFXTYPE_SCROLL1, 0x4400, 0x4bff, 0 }, + { GFXTYPE_SCROLL3, 0x4c00, 0x5fff, 0 }, + { GFXTYPE_SCROLL2, 0x6000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_YI24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x1fff, 0 }, + { GFXTYPE_SCROLL3, 0x2000, 0x3fff, 0 }, + { GFXTYPE_SCROLL1, 0x4000, 0x47ff, 0 }, + { GFXTYPE_SCROLL2, 0x4800, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_AR24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL1, 0x3000, 0x3fff, 0 }, + { GFXTYPE_SCROLL2, 0x4000, 0x5fff, 0 }, + { GFXTYPE_SCROLL3, 0x6000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_AR22B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL1, 0x3000, 0x3fff, 0 }, + + { GFXTYPE_SCROLL2, 0x4000, 0x5fff, 1 }, + { GFXTYPE_SCROLL3, 0x6000, 0x7fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_O224B_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x0bff, 0 }, + { GFXTYPE_SCROLL2, 0x0c00, 0x3bff, 0 }, + { GFXTYPE_SCROLL3, 0x3c00, 0x4bff, 0 }, + { GFXTYPE_SPRITES, 0x4c00, 0x7fff, 0 }, + + { GFXTYPE_SPRITES, 0x8000, 0xa7ff, 1 }, + { GFXTYPE_SCROLL2, 0xa800, 0xb7ff, 1 }, + { GFXTYPE_SCROLL3, 0xb800, 0xbfff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_MS24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL1, 0x4000, 0x4fff, 0 }, + { GFXTYPE_SCROLL2, 0x5000, 0x6fff, 0 }, + { GFXTYPE_SCROLL3, 0x7000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_CK24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL1, 0x3000, 0x3fff, 0 }, + { GFXTYPE_SCROLL2, 0x4000, 0x6fff, 0 }, + { GFXTYPE_SCROLL3, 0x7000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_NM24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL1, 0x4000, 0x47ff, 0 }, + { GFXTYPE_SPRITES, 0x4800, 0x67ff, 0 }, + { GFXTYPE_SCROLL2, 0x4800, 0x67ff, 0 }, + { GFXTYPE_SCROLL3, 0x6800, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_CA24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL3, 0x3000, 0x4fff, 0 }, + { GFXTYPE_SCROLL1, 0x5000, 0x57ff, 0 }, + { GFXTYPE_SPRITES, 0x5800, 0x7fff, 0 }, + { GFXTYPE_SCROLL2, 0x5800, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_CA22B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x2fff, 0 }, + { GFXTYPE_SCROLL3, 0x3000, 0x3fff, 0 }, + + { GFXTYPE_SCROLL3, 0x4000, 0x4fff, 1 }, + { GFXTYPE_SCROLL1, 0x5000, 0x57ff, 1 }, + { GFXTYPE_SPRITES, 0x5800, 0x7fff, 1 }, + { GFXTYPE_SCROLL2, 0x5800, 0x7fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_STF29_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x07fff, 0 }, + + { GFXTYPE_SPRITES, 0x08000, 0x0ffff, 1 }, + + { GFXTYPE_SPRITES, 0x10000, 0x11fff, 2 }, + { GFXTYPE_SCROLL3, 0x02000, 0x03fff, 2 }, + { GFXTYPE_SCROLL1, 0x04000, 0x04fff, 2 }, + { GFXTYPE_SCROLL2, 0x05000, 0x07fff, 2 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_RT24B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x53ff, 0 }, + { GFXTYPE_SCROLL1, 0x5400, 0x6fff, 0 }, + { GFXTYPE_SCROLL3, 0x7000, 0x7fff, 0 }, + + { GFXTYPE_SCROLL3, 0x0000, 0x3fff, 1 }, + { GFXTYPE_SCROLL2, 0x2800, 0x7fff, 1 }, + { GFXTYPE_SPRITES, 0x5400, 0x7fff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_RT22B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x3fff, 0 }, + + { GFXTYPE_SPRITES, 0x4000, 0x53ff, 1 }, + { GFXTYPE_SCROLL1, 0x5400, 0x6fff, 1 }, + { GFXTYPE_SCROLL3, 0x7000, 0x7fff, 1 }, + + { GFXTYPE_SCROLL3, 0x0000, 0x3fff, 2 }, + { GFXTYPE_SCROLL2, 0x2800, 0x3fff, 2 }, + + { GFXTYPE_SCROLL2, 0x4000, 0x7fff, 3 }, + { GFXTYPE_SPRITES, 0x5400, 0x7fff, 3 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_KD29B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES, 0x8000, 0x8fff, 1 }, + { GFXTYPE_SCROLL2, 0x9000, 0xbfff, 1 }, + { GFXTYPE_SCROLL1, 0xc000, 0xd7ff, 1 }, + { GFXTYPE_SCROLL3, 0xd800, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_CC63B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x7fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES, 0x8000, 0xffff, 1 }, + { GFXTYPE_SCROLL1, 0x8000, 0xffff, 1 }, + { GFXTYPE_SCROLL2, 0x8000, 0xffff, 1 }, + { GFXTYPE_SCROLL3, 0x8000, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_KR63B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x7fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x7fff, 0 }, + + { GFXTYPE_SCROLL1, 0x8000, 0x9fff, 1 }, + { GFXTYPE_SPRITES, 0x8000, 0xcfff, 1 }, + { GFXTYPE_SCROLL2, 0x8000, 0xcfff, 1 }, + { GFXTYPE_SCROLL3, 0xd000, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_S9263B_table[] = { + { GFXTYPE_SPRITES, 0x00000, 0x07fff, 0 }, + + { GFXTYPE_SPRITES, 0x08000, 0x0ffff, 1 }, + + { GFXTYPE_SPRITES, 0x10000, 0x11fff, 2 }, + { GFXTYPE_SCROLL3, 0x02000, 0x03fff, 2 }, + { GFXTYPE_SCROLL1, 0x04000, 0x04fff, 2 }, + { GFXTYPE_SCROLL2, 0x05000, 0x07fff, 2 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_VA63B_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x07fff, 0 }, + { 0 , 0, 0 , 0 } +}; + +static const struct GfxRange mapper_VA22B_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x03fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x04000, 0x07fff, 1 }, + { 0 , 0, 0 , 0 } +}; + +static const struct GfxRange mapper_Q522B_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x0000, 0x6fff, 0 }, + { GFXTYPE_SCROLL3, 0x7000, 0x77ff, 0 }, + { GFXTYPE_SCROLL1, 0x7800, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_TK263B_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x07fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x08000, 0x0ffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_CD63B_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x0fff, 0 }, + { GFXTYPE_SPRITES, 0x1000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x8000, 0xdfff, 1 }, + { GFXTYPE_SCROLL3, 0xe000, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_PS63B_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x0fff, 0 }, + { GFXTYPE_SPRITES, 0x1000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x8000, 0xdbff, 1 }, + { GFXTYPE_SCROLL3, 0xdc00, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_MB63B_table[] = { + { GFXTYPE_SCROLL1, 0x00000, 0x00fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x01000, 0x07fff, 0 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x08000, 0x0ffff, 1 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x10000, 0x167ff, 2 }, + { GFXTYPE_SCROLL3, 0x16800, 0x17fff, 2 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_QD22B_table[] = { + { GFXTYPE_SPRITES, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL1, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL2, 0x0000, 0x3fff, 0 }, + { GFXTYPE_SCROLL3, 0x0000, 0x3fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_QD63B_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x07ff, 0 }, + { GFXTYPE_SCROLL3, 0x0800, 0x1fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x2000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_qtono2_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x0fff, 0 }, + { GFXTYPE_SCROLL3, 0x1000, 0x3fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x4000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x8000, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_RCM63B_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x07fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x08000, 0x0ffff, 1 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x10000, 0x17fff, 2 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x18000, 0x1ffff, 3 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_PKB10B_table[] = { + { GFXTYPE_SCROLL1, 0x0000, 0x0fff, 0 }, + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x1000, 0x5fff, 0 }, + { GFXTYPE_SCROLL3, 0x6000, 0x7fff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_pang3_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x0000, 0x7fff, 0 }, + + { GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x8000, 0x9fff, 1 }, + { GFXTYPE_SCROLL1, 0xa000, 0xbfff, 1 }, + { GFXTYPE_SCROLL3, 0xc000, 0xffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_sfzch_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00000, 0x1ffff, 0 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_cps2_table[] = +{ + { GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3 | GFXTYPE_SPRITES, 0x00000, 0x1ffff, 1 }, + { 0 , 0, 0, 0 } +}; + +static const struct GfxRange mapper_frog_table[] = { + { GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x00001, 0x1ffff, 0 }, + { 0 , 0, 0, 0 } +}; + +void SetGfxMapper(INT32 MapperId) +{ + switch (MapperId) { + case mapper_LWCHR: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_LWCHR_table; + return; + } + + case mapper_LW621: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_LW621_table; + return; + } + + case mapper_DM620: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x2000; + GfxBankSizes[2] = 0x2000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_DM620_table; + return; + } + + case mapper_DM22A: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x2000; + GfxBankSizes[3] = 0x2000; + GfxBankMapper = mapper_DM22A_table; + return; + } + + case mapper_DAM63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_DAM63B_table; + return; + } + + case mapper_ST24M1: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_ST24M1_table; + return; + } + + case mapper_ST22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x4000; + GfxBankSizes[3] = 0x4000; + GfxBankMapper = mapper_ST22B_table; + return; + } + + case mapper_TK22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x4000; + GfxBankSizes[3] = 0x4000; + GfxBankMapper = mapper_TK22B_table; + return; + } + + case mapper_WL24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_WL24B_table; + return; + } + + case mapper_S224B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_S224B_table; + return; + } + + case mapper_YI24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_YI24B_table; + return; + } + + case mapper_AR24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_AR24B_table; + return; + } + + case mapper_AR22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_AR22B_table; + return; + } + + case mapper_O224B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_O224B_table; + return; + } + + case mapper_MS24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_MS24B_table; + return; + } + + case mapper_CK24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_CK24B_table; + return; + } + + case mapper_NM24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_NM24B_table; + return; + } + + case mapper_CA24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_CA24B_table; + return; + } + + case mapper_CA22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_CA22B_table; + return; + } + + case mapper_STF29: { + GfxBankSizes[0] = 0x08000; + GfxBankSizes[1] = 0x08000; + GfxBankSizes[2] = 0x08000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_STF29_table; + return; + } + + case mapper_RT24B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_RT24B_table; + return; + } + + case mapper_RT22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x4000; + GfxBankSizes[3] = 0x4000; + GfxBankMapper = mapper_RT22B_table; + return; + } + + case mapper_KD29B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_KD29B_table; + return; + } + + case mapper_CC63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_CC63B_table; + return; + } + + case mapper_KR63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_KR63B_table; + return; + } + + case mapper_S9263B: { + GfxBankSizes[0] = 0x08000; + GfxBankSizes[1] = 0x08000; + GfxBankSizes[2] = 0x08000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_S9263B_table; + return; + } + + case mapper_VA63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_VA63B_table; + return; + } + + case mapper_VA22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x4000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_VA22B_table; + return; + } + + case mapper_Q522B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_Q522B_table; + return; + } + + case mapper_TK263B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_TK263B_table; + return; + } + + case mapper_CD63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_CD63B_table; + return; + } + + case mapper_PS63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_PS63B_table; + return; + } + + case mapper_MB63B: { + GfxBankSizes[0] = 0x08000; + GfxBankSizes[1] = 0x08000; + GfxBankSizes[2] = 0x08000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_MB63B_table; + return; + } + + case mapper_QD22B: { + GfxBankSizes[0] = 0x4000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_QD22B_table; + return; + } + + case mapper_QD63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_QD63B_table; + return; + } + + case mapper_qtono2: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_qtono2_table; + return; + } + + case mapper_RCM63B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x8000; + GfxBankSizes[3] = 0x8000; + GfxBankMapper = mapper_RCM63B_table; + return; + } + + case mapper_PKB10B: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x0000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_PKB10B_table; + return; + } + + case mapper_pang3: { + GfxBankSizes[0] = 0x8000; + GfxBankSizes[1] = 0x8000; + GfxBankSizes[2] = 0x0000; + GfxBankSizes[3] = 0x0000; + GfxBankMapper = mapper_pang3_table; + return; + } + + case mapper_sfzch: { + GfxBankSizes[0] = 0x20000; + GfxBankSizes[1] = 0x00000; + GfxBankSizes[2] = 0x00000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_sfzch_table; + return; + } + + case mapper_cps2: { + GfxBankSizes[0] = 0x20000; + GfxBankSizes[1] = 0x20000; + GfxBankSizes[2] = 0x00000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_cps2_table; + return; + } + + case mapper_frog: { + GfxBankSizes[0] = 0x20000; + GfxBankSizes[1] = 0x00000; + GfxBankSizes[2] = 0x00000; + GfxBankSizes[3] = 0x00000; + GfxBankMapper = mapper_frog_table; + return; + } + } +} + +INT32 GfxRomBankMapper(INT32 Type, INT32 Code) +{ + const struct GfxRange *Range = GfxBankMapper; + INT32 Shift = 0; + + switch (Type) { + case GFXTYPE_SPRITES: Shift = 1; break; + case GFXTYPE_SCROLL1: Shift = 0; break; + case GFXTYPE_SCROLL2: Shift = 1; break; + case GFXTYPE_SCROLL3: Shift = 3; break; + } + + Code <<= Shift; + + while (Range->Type) { + if (Code >= Range->Start && Code <= Range->End) { + if (Range->Type & Type) { + INT32 Base = 0; + INT32 i; + + for (i = 0; i < Range->Bank; ++i) + Base += GfxBankSizes[i]; + + return (Base + (Code & (GfxBankSizes[Range->Bank] - 1))) >> Shift; + } + } + + ++Range; + } + +// bprintf(PRINT_NORMAL, _T("tile %02x/%04x out of range\n"), Type,Code>>Shift); + + return -1; +} + +void SetCpsBId(INT32 CpsBId, INT32 bStars) +{ + switch (CpsBId) { + case CPS_B_01: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x66; + MaskAddr[0] = 0x68; + MaskAddr[1] = 0x6a; + MaskAddr[2] = 0x6c; + MaskAddr[3] = 0x6e; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x30; + CpsLayEn[5] = 0x30; + } + return; + } + + case CPS_B_02: { + CpsBID[0] = 0x60; + CpsBID[1] = 0x00; + CpsBID[2] = 0x02; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x6c; + MaskAddr[0] = 0x6a; + MaskAddr[1] = 0x68; + MaskAddr[2] = 0x66; + MaskAddr[3] = 0x64; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_03: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x70; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x10; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_04: { + CpsBID[0] = 0x60; + CpsBID[1] = 0x00; + CpsBID[2] = 0x04; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x6e; + MaskAddr[0] = 0x66; + MaskAddr[1] = 0x70; + MaskAddr[2] = 0x68; + MaskAddr[3] = 0x72; + + CpsLayEn[1] = 0x02; + //CpsLayEn[2] = 0x0c; + CpsLayEn[2] = 0x04; + //CpsLayEn[3] = 0x0c; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_05: { + CpsBID[0] = 0x60; + CpsBID[1] = 0x00; + CpsBID[2] = 0x05; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x68; + MaskAddr[0] = 0x6a; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6e; + MaskAddr[3] = 0x70; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x20; + if (bStars) { + CpsLayEn[4] = 0x14; + CpsLayEn[5] = 0x14; + } + return; + } + + case CPS_B_11: { + CpsBID[0] = 0x72; + CpsBID[1] = 0x04; + CpsBID[2] = 0x01; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x66; + MaskAddr[0] = 0x68; + MaskAddr[1] = 0x6a; + MaskAddr[2] = 0x6c; + MaskAddr[3] = 0x6e; + + CpsLayEn[1] = 0x08; + CpsLayEn[2] = 0x10; + CpsLayEn[3] = 0x20; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_12: { + CpsBID[0] = 0x60; + CpsBID[1] = 0x04; + CpsBID[2] = 0x02; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x6c; + MaskAddr[0] = 0x6a; + MaskAddr[1] = 0x68; + MaskAddr[2] = 0x66; + MaskAddr[3] = 0x64; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_13: { + CpsBID[0] = 0x6e; + CpsBID[1] = 0x04; + CpsBID[2] = 0x03; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x62; + MaskAddr[0] = 0x64; + MaskAddr[1] = 0x66; + MaskAddr[2] = 0x68; + MaskAddr[3] = 0x6a; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x02; + CpsLayEn[3] = 0x04; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_14: { + CpsBID[0] = 0x5e; + CpsBID[1] = 0x04; + CpsBID[2] = 0x04; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x52; + MaskAddr[0] = 0x54; + MaskAddr[1] = 0x56; + MaskAddr[2] = 0x58; + MaskAddr[3] = 0x5a; + + CpsLayEn[1] = 0x08; + CpsLayEn[2] = 0x20; + CpsLayEn[3] = 0x10; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_15: { + CpsBID[0] = 0x4e; + CpsBID[1] = 0x04; + CpsBID[2] = 0x05; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x42; + MaskAddr[0] = 0x44; + MaskAddr[1] = 0x46; + MaskAddr[2] = 0x48; + MaskAddr[3] = 0x4a; + + CpsLayEn[1] = 0x04; + CpsLayEn[2] = 0x02; + CpsLayEn[3] = 0x20; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_16: { + CpsBID[0] = 0x40; + CpsBID[1] = 0x04; + CpsBID[2] = 0x06; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x4c; + MaskAddr[0] = 0x4a; + MaskAddr[1] = 0x48; + MaskAddr[2] = 0x46; + MaskAddr[3] = 0x44; + + CpsLayEn[1] = 0x10; + CpsLayEn[2] = 0x0a; + CpsLayEn[3] = 0x0a; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_17: { + CpsBID[0] = 0x48; + CpsBID[1] = 0x04; + CpsBID[2] = 0x07; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x54; + MaskAddr[0] = 0x52; + MaskAddr[1] = 0x50; + MaskAddr[2] = 0x4e; + MaskAddr[3] = 0x4c; + + CpsLayEn[1] = 0x08; + CpsLayEn[2] = 0x10; + CpsLayEn[3] = 0x02; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_18: { + CpsBID[0] = 0xd0; + CpsBID[1] = 0x04; + CpsBID[2] = 0x08; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0xdc; + MaskAddr[0] = 0xda; + MaskAddr[1] = 0xd8; + MaskAddr[2] = 0xd6; + MaskAddr[3] = 0xd4; + + CpsLayEn[1] = 0x10; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x02; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT1: { + CpsBID[0] = 0x72; + CpsBID[1] = 0x08; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x4e; + CpsMProt[1] = 0x4c; + CpsMProt[2] = 0x4a; + CpsMProt[3] = 0x48; + + nCpsLcReg = 0x68; + MaskAddr[0] = 0x66; + MaskAddr[1] = 0x64; + MaskAddr[2] = 0x62; + MaskAddr[3] = 0x60; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x12; + CpsLayEn[5] = 0x12; + } + return; + } + + case CPS_B_21_BT2: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x5e; + CpsMProt[1] = 0x5c; + CpsMProt[2] = 0x5a; + CpsMProt[3] = 0x58; + + nCpsLcReg = 0x60; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x30; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x30; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT3: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x46; + CpsMProt[1] = 0x44; + CpsMProt[2] = 0x42; + CpsMProt[3] = 0x40; + + nCpsLcReg = 0x60; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x12; + CpsLayEn[3] = 0x12; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT4: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x46; + CpsMProt[1] = 0x44; + CpsMProt[2] = 0x42; + CpsMProt[3] = 0x40; + + nCpsLcReg = 0x68; + MaskAddr[0] = 0x66; + MaskAddr[1] = 0x64; + MaskAddr[2] = 0x62; + MaskAddr[3] = 0x60; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x10; + CpsLayEn[3] = 0x02; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT5: { + CpsBID[0] = 0x32; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x4e; + CpsMProt[1] = 0x4c; + CpsMProt[2] = 0x4a; + CpsMProt[3] = 0x48; + + nCpsLcReg = 0x60; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x02; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT6: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x60; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x20; + CpsLayEn[2] = 0x14; + CpsLayEn[3] = 0x14; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_BT7: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x6c; + MaskAddr[0] = 0x00; + MaskAddr[1] = 0x00; + MaskAddr[2] = 0x00; + MaskAddr[3] = 0x00; + + CpsLayEn[1] = 0x14; + CpsLayEn[2] = 0x02; + CpsLayEn[3] = 0x14; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_DEF: { + CpsBID[0] = 0x32; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x40; + CpsMProt[1] = 0x42; + CpsMProt[2] = 0x44; + CpsMProt[3] = 0x46; + + nCpsLcReg = 0x66; + MaskAddr[0] = 0x68; + MaskAddr[1] = 0x6a; + MaskAddr[2] = 0x6c; + MaskAddr[3] = 0x6e; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x30; + CpsLayEn[5] = 0x30; + } + return; + } + + case CPS_B_21_QS1: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x62; + MaskAddr[0] = 0x64; + MaskAddr[1] = 0x66; + MaskAddr[2] = 0x68; + MaskAddr[3] = 0x6a; + + CpsLayEn[1] = 0x10; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x04; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_QS2: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x4a; + MaskAddr[0] = 0x4c; + MaskAddr[1] = 0x4e; + MaskAddr[2] = 0x40; + MaskAddr[3] = 0x42; + + CpsLayEn[1] = 0x16; + CpsLayEn[2] = 0x16; + CpsLayEn[3] = 0x16; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_QS3: { + CpsBID[0] = 0x4e; + CpsBID[1] = 0x0c; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x52; + MaskAddr[0] = 0x54; + MaskAddr[1] = 0x56; + MaskAddr[2] = 0x48; + MaskAddr[3] = 0x4a; + + CpsLayEn[1] = 0x04; + CpsLayEn[2] = 0x02; + CpsLayEn[3] = 0x20; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_QS4: { + CpsBID[0] = 0x6e; + CpsBID[1] = 0x0c; + CpsBID[2] = 0x01; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x56; + MaskAddr[0] = 0x40; + MaskAddr[1] = 0x42; + MaskAddr[2] = 0x68; + MaskAddr[3] = 0x6a; + + CpsLayEn[1] = 0x04; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x10; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case CPS_B_21_QS5: { + CpsBID[0] = 0x5e; + CpsBID[1] = 0x0c; + CpsBID[2] = 0x02; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x6a; + MaskAddr[0] = 0x6c; + MaskAddr[1] = 0x6e; + MaskAddr[2] = 0x70; + MaskAddr[3] = 0x72; + + CpsLayEn[1] = 0x04; + CpsLayEn[2] = 0x08; + CpsLayEn[3] = 0x10; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case HACK_B_1: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x54; + MaskAddr[0] = 0x52; + MaskAddr[1] = 0x50; + MaskAddr[2] = 0x4e; + MaskAddr[3] = 0x4c; + + CpsLayEn[1] = 0xff; + CpsLayEn[2] = 0xff; + CpsLayEn[3] = 0xff; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case HACK_B_2: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0xc4; + MaskAddr[0] = 0x52; + MaskAddr[1] = 0x50; + MaskAddr[2] = 0x4e; + MaskAddr[3] = 0x4c; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x02; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + + case HACK_B_3: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x60; + MaskAddr[0] = 0x68; + MaskAddr[1] = 0x6a; + MaskAddr[2] = 0x6c; + MaskAddr[3] = 0x6e; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x30; + CpsLayEn[5] = 0x30; + } + return; + } + + case HACK_B_4: { + CpsBID[0] = 0x00; + CpsBID[1] = 0x00; + CpsBID[2] = 0x00; + + CpsMProt[0] = 0x00; + CpsMProt[1] = 0x00; + CpsMProt[2] = 0x00; + CpsMProt[3] = 0x00; + + nCpsLcReg = 0x70; + MaskAddr[0] = 0x6e; + MaskAddr[1] = 0x6c; + MaskAddr[2] = 0x6a; + MaskAddr[3] = 0x68; + + CpsLayEn[1] = 0x02; + CpsLayEn[2] = 0x04; + CpsLayEn[3] = 0x08; + if (bStars) { + CpsLayEn[4] = 0x00; + CpsLayEn[5] = 0x00; + } + return; + } + } +} diff --git a/src/burn/drivers/capcom/cps_draw.cpp b/src/burn/drivers/capcom/cps_draw.cpp new file mode 100644 index 00000000..fd6edbdb --- /dev/null +++ b/src/burn/drivers/capcom/cps_draw.cpp @@ -0,0 +1,490 @@ +#include "cps.h" +// CPS - Draw + +UINT8 CpsRecalcPal = 0; // Flag - If it is 1, recalc the whole palette + +static INT32 LayerCont; +INT32 nStartline, nEndline; +INT32 nRasterline[MAX_RASTER + 2]; + +INT32 nCpsLcReg = 0; // Address of layer controller register +INT32 CpsLayEn[6] = {0, 0, 0, 0, 0, 0}; // bits for layer enable +INT32 MaskAddr[4] = {0, 0, 0, 0}; + +INT32 CpsLayer1XOffs = 0; +INT32 CpsLayer2XOffs = 0; +INT32 CpsLayer3XOffs = 0; +INT32 CpsLayer1YOffs = 0; +INT32 CpsLayer2YOffs = 0; +INT32 CpsLayer3YOffs = 0; + +static void Cps1Layers(); +static void Cps2Layers(); + +typedef INT32 (*CpsObjDrawDoFn)(INT32,INT32); +typedef INT32 (*CpsScrXDrawDoFn)(UINT8 *,INT32,INT32); +typedef void (*CpsLayersDoFn)(); +typedef INT32 (*CpsrPrepareDoFn)(); +typedef INT32 (*CpsrRenderDoFn)(); + +CpsObjDrawDoFn CpsObjDrawDoX; +CpsScrXDrawDoFn CpsScr1DrawDoX; +CpsScrXDrawDoFn CpsScr3DrawDoX; +CpsLayersDoFn CpsLayersDoX; +CpsrPrepareDoFn CpsrPrepareDoX; +CpsrRenderDoFn CpsrRenderDoX; + +void DrawFnInit() +{ + if(Cps == 2) { + CpsLayersDoX = Cps2Layers; + CpsScr1DrawDoX = Cps2Scr1Draw; + CpsScr3DrawDoX = Cps2Scr3Draw; + CpsObjDrawDoX = Cps2ObjDraw; + CpsrPrepareDoX = Cps2rPrepare; + CpsrRenderDoX = Cps2rRender; + } else { + CpsLayersDoX = Cps1Layers; + CpsScr1DrawDoX = Cps1Scr1Draw; + CpsScr3DrawDoX = Cps1Scr3Draw; + CpsObjDrawDoX = Cps1ObjDraw; + CpsrPrepareDoX = Cps1rPrepare; + CpsrRenderDoX = Cps1rRender; + } +} + +static INT32 DrawScroll1(INT32 i) +{ + // Draw Scroll 1 + INT32 nOff, nScrX, nScrY; + UINT8 *Find; + + nOff = *((UINT16 *)(CpsSaveReg[i] + 0x02)); + + // Get scroll coordinates + nScrX = *((UINT16 *)(CpsSaveReg[i] + 0x0c)); // Scroll 1 X + nScrY = *((UINT16 *)(CpsSaveReg[i] + 0x0e)); // Scroll 1 Y + + nScrX += 0x40; + +// bprintf(PRINT_NORMAL, _T("1 %x, %x, %x\n"), nOff, nScrX, nScrY); + + nScrX += CpsLayer1XOffs; + nScrY += 0x10; + nScrY += CpsLayer1YOffs; + nOff <<= 8; + nOff &= 0xffc000; + Find = CpsFindGfxRam(nOff, 0x4000); + if (Find == NULL) { + return 1; + } + CpsScr1DrawDoX(Find, nScrX, nScrY); + return 0; +} + +static INT32 DrawScroll2Init(INT32 i) +{ + // Draw Scroll 2 + INT32 nScr2Off; INT32 n; + + nScr2Off = *((UINT16 *)(CpsSaveReg[i] + 0x04)); + + // Get scroll coordinates + nCpsrScrX= *((UINT16 *)(CpsSaveReg[i] + 0x10)); // Scroll 2 X + nCpsrScrY= *((UINT16 *)(CpsSaveReg[i] + 0x12)); // Scroll 2 Ytess + + // Get row scroll information + n = *((UINT16 *)(CpsSaveReg[i] + 0x22)); + + nScr2Off <<= 8; + + nCpsrScrX += 0x40; + +// bprintf(PRINT_NORMAL, _T("2 %x, %x, %x\n"), nScr2Off, nCpsrScrX, nCpsrScrY); + + nCpsrScrX += CpsLayer2XOffs; + nCpsrScrX &= 0x03FF; + + nCpsrScrY += 0x10; + nCpsrScrY += CpsLayer2YOffs; + nCpsrScrY &= 0x03FF; + + nScr2Off &= 0xFFC000; + CpsrBase = CpsFindGfxRam(nScr2Off, 0x4000); + if (CpsrBase == NULL) { + return 1; + } + + CpsrRows = NULL; + + if (n & 1) { + INT32 nTab, nStart; + // Find row scroll table: + + nTab = *((UINT16 *)(CpsSaveReg[i] + 0x08)); + nStart = *((UINT16 *)(CpsSaveReg[i] + 0x20)); + + nTab <<= 8; + nTab &= 0xFFF800; // Vampire - Row scroll effect in VS screen background + + CpsrRows = (UINT16 *)CpsFindGfxRam(nTab, 0x0800); + + // Find start offset + nCpsrRowStart = nStart + 16; + } + + CpsrPrepareDoX(); + return 0; +} + +inline static INT32 DrawScroll2Exit() +{ + CpsrBase = NULL; + nCpsrScrX = 0; + nCpsrScrY = 0; + CpsrRows = NULL; + return 0; +} + +inline static INT32 DrawScroll2Do() +{ + if (CpsrBase == NULL) { + return 1; + } + CpsrRenderDoX(); + return 0; +} + +static INT32 DrawScroll3(INT32 i) +{ + // Draw Scroll 3 + INT32 nOff, nScrX, nScrY; + UINT8 *Find; + + nOff = *((UINT16 *)(CpsSaveReg[i] + 0x06)); + + // Get scroll coordinates + nScrX = *((UINT16 *)(CpsSaveReg[i] + 0x14)); // Scroll 3 X + nScrY = *((UINT16 *)(CpsSaveReg[i] + 0x16)); // Scroll 3 Y + + nScrX += 0x40; + +// bprintf(PRINT_NORMAL, _T("3 %x, %x, %x\n"), nOff, nScrX, nScrY); + + nScrX += CpsLayer3XOffs; + nScrY += 0x10; + nScrY += CpsLayer3YOffs; + + nOff <<= 8; + nOff &= 0xffc000; + Find=CpsFindGfxRam(nOff, 0x4000); + if (Find == NULL) { + return 1; + } + CpsScr3DrawDoX(Find, nScrX, nScrY); + return 0; +} + +static INT32 DrawStar(INT32 nLayer) +{ + INT32 nStar, nStarXPos, nStarYPos, nStarColour; + UINT8* pStar = CpsStar + (nLayer << 12); + + for (nStar = 0; nStar < 0x1000; nStar++) { + nStarColour = pStar[nStar]; + + if (nStarColour != 0x0F) { + nStarXPos = (((nStar >> 8) << 5) - *((INT16*)(CpsSaveReg[0] + 0x18 + (nLayer << 2))) + (nStarColour & 0x1F) - 64) & 0x01FF; + nStarYPos = ((nStar & 0xFF) - *((INT16*)(CpsSaveReg[0] + 0x1A + (nLayer << 2))) - 16) & 0xFF; + + if (nStarXPos < 384 && nStarYPos < 224) { + nStarColour = ((nStarColour & 0xE0) >> 1) + ((GetCurrentFrame() >> 4) & 0x0F); + PutPix(pBurnDraw + (nBurnPitch * nStarYPos) + (nBurnBpp * nStarXPos), CpsPal[0x0800 + (nLayer << 9) + nStarColour]); + } + } + } + + return 0; +} + +static void Cps1Layers() +{ + INT32 Draw[4]={-1,-1,-1,-1}; + INT32 nDrawMask=0; + INT32 i=0; + + nDrawMask=1; // Sprites always on + LayerCont = *((UINT16 *)(CpsSaveReg[0] + nCpsLcReg)); + // Get correct bits from Layer Controller + if (LayerCont & CpsLayEn[1]) nDrawMask|=2; + if (LayerCont & CpsLayEn[2]) nDrawMask|=4; + if (LayerCont & CpsLayEn[3]) nDrawMask|=8; + nDrawMask&=nBurnLayer; // User choice of layers to display + + // Layer control: + Draw[0]=(LayerCont>>12)&3; // top layer + Draw[1]=(LayerCont>>10)&3; + Draw[2]=(LayerCont>> 8)&3; + Draw[3]=(LayerCont>> 6)&3; // bottom layer (most covered up) + + // Check for repeated layers and if there are any, the lower layer is omitted +#define CRP(a,b) if (Draw[a]==Draw[b]) Draw[b]=-1; + CRP(0,1) CRP(0,2) CRP(0,3) CRP(1,2) CRP(1,3) CRP(2,3) +#undef CRP + + for (i = 0; i < 2; i++) { + if (LayerCont & CpsLayEn[4 + i]) { + CpsStarPalUpdate(CpsSavePal, i, CpsRecalcPal); + DrawStar(i); + } + } + + // prepare layer 2 + DrawScroll2Init(0); + + // draw layers, bottom -> top + for (i=3;i>=0;i--) + { + INT32 n=Draw[i]; // Find out which layer to draw + + if (n==0) { + if (nDrawMask & 1) CpsObjDrawDoX(0,7); + + if (!Mercs && !Sf2jc && !Qad) { + nBgHi=1; + switch (Draw[i+1]) { + case 1: + if (nDrawMask & 2) DrawScroll1(0); + break; + case 2: + if (nDrawMask & 4) DrawScroll2Do(); + break; + case 3: + if (nDrawMask & 8) DrawScroll3(0); + break; + } + nBgHi=0; + } + } + + // Then Draw the scroll layer on top + switch (n) { + case 1: + if (nDrawMask & 2) DrawScroll1(0); + break; + case 2: + if (nDrawMask & 4) DrawScroll2Do(); + break; + case 3: + if (nDrawMask & 8) DrawScroll3(0); + break; + } + } + + DrawScroll2Exit(); +} + +static void Cps2Layers() +{ + INT32 Draw[MAX_RASTER][4]; + INT32 Prio[MAX_RASTER][4]; + INT32 nDrawMask[MAX_RASTER]; + + CpsObjDrawInit(); + + INT32 nSlice = 0; + do { + LayerCont = *((UINT16 *)(CpsSaveReg[nSlice] + nCpsLcReg)); + + // Determine which layers are enabled + nDrawMask[nSlice] = 1; // Sprites always on + if (LayerCont & CpsLayEn[1]) nDrawMask[nSlice] |= 2; + if (LayerCont & CpsLayEn[2]) nDrawMask[nSlice] |= 4; + if (LayerCont & CpsLayEn[3]) nDrawMask[nSlice] |= 8; + nDrawMask[nSlice] &= nBurnLayer; // User choice of layers to display + + // Determine layerö priority: + Draw[nSlice][3] = (LayerCont >> 12) & 3; // top layer + Draw[nSlice][2] = (LayerCont >> 10) & 3; + Draw[nSlice][1] = (LayerCont >> 8) & 3; + Draw[nSlice][0] = (LayerCont >> 6) & 3; // bottom layer (most covered up) + + // Determine layer-sprite priority (layer >= sprites -> layer on top) + INT32 nLayPri = (CpsSaveFrg[nSlice][4] << 8) | CpsSaveFrg[nSlice][5]; // Layer priority register at word (400004) + Prio[nSlice][3] = (nLayPri >> 12) & 7; + Prio[nSlice][2] = (nLayPri >> 8) & 7; + Prio[nSlice][1] = (nLayPri >> 4) & 7; + Prio[nSlice][0] = 0; + + // Check for repeated layers (if found, discard the lower layer) +#define CRP(a, b) if (Draw[nSlice][a] == Draw[nSlice][b]) Draw[nSlice][b] = -1; + CRP(3, 2) CRP(3, 1) CRP(2, 1) CRP(3, 0) CRP(2, 0) CRP(1, 0) +#undef CRP + + // Pre-process priorities + // Higher priority layers must have higher layer-sprite priorities + // N.B. If this is not the case, masking effects may occur (not emulated) +#if 0 + // Raise sprite priorities of top layers if needed + INT32 nHighPrio = 0; + for (INT32 i = 0; i < 4; i++) { + if (Draw[nSlice][i] > 0) { + if (Prio[nSlice][Draw[nSlice][i]] < nHighPrio) { + Prio[nSlice][Draw[nSlice][i]] = nHighPrio; + } else { + nHighPrio = Prio[nSlice][Draw[nSlice][i]]; + } + } + } +#else + // Lower sprite priorities of bottom layers if needed + INT32 nHighPrio = 9999; + for (INT32 i = 3; i >= 0; i--) { + if (Draw[nSlice][i] > 0) { + if (Prio[nSlice][Draw[nSlice][i]] > nHighPrio) { + Prio[nSlice][Draw[nSlice][i]] = nHighPrio; + } else { + nHighPrio = Prio[nSlice][Draw[nSlice][i]]; + } + } + } +#endif + nSlice++; + } while (nSlice < MAX_RASTER && nRasterline[nSlice]); + + INT32 nPrevPrio = -1; + for (INT32 nCurrPrio = 0; nCurrPrio < 8; nCurrPrio++) { + + nSlice = 0; + do { + for (INT32 i = 0; i < 4; i++) { + + if (Prio[nSlice][Draw[nSlice][i]] == nCurrPrio) { + + // Render sprites between the previous layer and this one + if ((nDrawMask[0] & 1) && (nPrevPrio < nCurrPrio)) { + CpsObjDrawDoX(nPrevPrio + 1, nCurrPrio); + nPrevPrio = nCurrPrio; + } + + nStartline = nRasterline[nSlice]; + nEndline = nRasterline[nSlice + 1]; + if (!nEndline) { + nEndline = 224; + } + + // Render layer + switch (Draw[nSlice][i]) { + case 1: + if (nDrawMask[nSlice] & 2) { + DrawScroll1(nSlice); + } + break; + case 2: + if (nDrawMask[nSlice] & 4) { + DrawScroll2Init(nSlice); + DrawScroll2Do(); + DrawScroll2Exit(); + } + break; + case 3: + if (nDrawMask[nSlice] & 8) { + DrawScroll3(nSlice); + } + break; + } + } + } + nSlice++; + } while (nSlice < MAX_RASTER && nRasterline[nSlice]); + } + + // Render highest priority sprites + if ((nDrawMask[0] & 1) && (nPrevPrio < 7)) { + CpsObjDrawDoX(nPrevPrio + 1, 7); + } +} + +void CpsClearScreen() +{ + if (Cps == 1) { + switch (nBurnBpp) { + case 4: { + UINT32* pClear = (UINT32*)pBurnDraw; + UINT32 nColour = CpsPal[0xbff ^ 15]; + for (INT32 i = 0; i < 384 * 224 / 8; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + + case 3: { + UINT8* pClear = pBurnDraw; + UINT8 r = CpsPal[0xbff ^ 15]; + UINT8 g = (r >> 8) & 0xFF; + UINT8 b = (r >> 16) & 0xFF; + r &= 0xFF; + for (INT32 i = 0; i < 384 * 224; i++) { + *pClear++ = r; + *pClear++ = g; + *pClear++ = b; + } + break; + } + + case 2: { + UINT32* pClear = (UINT32*)pBurnDraw; + UINT32 nColour = CpsPal[0xbff ^ 15] | CpsPal[0xbff ^ 15] << 16; + for (INT32 i = 0; i < 384 * 224 / 16; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + } + } else { + memset(pBurnDraw, 0, 384 * 224 * nBurnBpp); + } +} + +static void DoDraw(INT32 Recalc) +{ + CtvReady(); // Point to correct tile drawing functions + + // Update Palette + CpsPalUpdate(CpsSavePal, Recalc); // recalc whole palette if needed + + CpsClearScreen(); + + CpsLayersDoX(); +} + +INT32 CpsDraw() +{ + DoDraw(CpsRecalcPal); + + CpsRecalcPal = 0; + return 0; +} + +INT32 CpsRedraw() +{ + DoDraw(1); + + CpsRecalcPal = 0; + return 0; +} + diff --git a/src/burn/drivers/capcom/cps_mem.cpp b/src/burn/drivers/capcom/cps_mem.cpp new file mode 100644 index 00000000..07916380 --- /dev/null +++ b/src/burn/drivers/capcom/cps_mem.cpp @@ -0,0 +1,427 @@ +#include "cps.h" +// CPS - Memory + +UINT32 CpsMProt[4]; +UINT32 CpsBID[3]; + +static UINT8 *CpsMem=NULL,*CpsMemEnd=NULL; +UINT8 *CpsRam90=NULL; +UINT8 *CpsZRamC0=NULL,*CpsZRamF0=NULL,*CpsEncZRom=NULL; +UINT8 *CpsSavePal=NULL; +UINT8 *CpsSaveReg[MAX_RASTER + 1]; +UINT8 *CpsSaveFrg[MAX_RASTER + 1]; +static UINT8 *CpsSaveRegData = NULL; +static UINT8 *CpsSaveFrgData = NULL; +UINT8 *CpsRam660=NULL,*CpsRam708=NULL,*CpsReg=NULL,*CpsFrg=NULL; +UINT8 *CpsRamFF=NULL; + +// This routine is called first to determine how much memory is needed +// and then to set up all the pointers. +static INT32 CpsMemIndex() +{ + UINT8* Next; Next = CpsMem; + + CpsRam90 = Next; Next += 0x030000; // Video Ram + CpsRamFF = Next; Next += 0x010000; // Work Ram + CpsReg = Next; Next += 0x000100; // Registers + + CpsSavePal = Next; Next += 0x002000; // Draw Copy of Correct Palette + + if (Cps == 2 || Cps1Qs == 1) { + CpsZRamC0 = Next; Next += 0x001000; // Z80 c000-cfff + CpsZRamF0 = Next; Next += 0x001000; // Z80 f000-ffff + } + + if (Cps == 2) { + CpsRam660 = Next; Next += 0x004000; // Extra Memory + CpsRam708 = Next; Next += 0x010000; // Obj Ram + CpsFrg = Next; Next += 0x000010; // 'Four' Registers (Registers at 0x400000) + + ZBuf = (UINT16*)Next; Next += 384 * 224 * 2; // Sprite Masking Z buffer + + CpsSaveRegData = Next; Next += 0x0100 * (MAX_RASTER + 1); // Draw Copy of registers + CpsSaveFrgData = Next; Next += 0x0010 * (MAX_RASTER + 1); // Draw Copy of 'Four' Registers + + for (INT32 i = 0; i < MAX_RASTER + 1; i++) { + CpsSaveReg[i] = CpsSaveRegData + i * 0x0100; + CpsSaveFrg[i] = CpsSaveFrgData + i * 0x0010; + } + + } else { + CpsSaveRegData = Next; Next += 0x0100; // Draw Copy of registers + CpsSaveFrgData = Next; Next += 0x0010; // Draw Copy of 'Four' Registers + + CpsSaveReg[0] = CpsSaveRegData; + CpsSaveFrg[0] = CpsSaveFrgData; + } + + CpsMemEnd = Next; + + return 0; +} + +static INT32 AllocateMemory() +{ + INT32 nLen; + + CpsMem = NULL; // Find out how much memory is needed + CpsMemIndex(); + nLen = CpsMemEnd - (UINT8*)0; + + if ((CpsMem = (UINT8*)malloc(nLen)) == NULL) { + return 1; + } + + memset(CpsMem, 0, nLen); // blank all memory + CpsMemIndex(); // Index the allocated memory + + return 0; +} + +// Map the correct bank of obj memory to the 68000 address space (including mirrors). +void CpsMapObjectBanks(INT32 nBank) +{ + if (nBank != nCpsObjectBank) { + nCpsObjectBank = nBank; + + if (nCpsObjectBank) { + SekMapMemory(CpsRam708 + 0x8000, 0x708000, 0x709FFF, SM_RAM); + SekMapMemory(CpsRam708 + 0x8000, 0x70A000, 0x70BFFF, SM_RAM); + SekMapMemory(CpsRam708 + 0x8000, 0x70C000, 0x70DFFF, SM_RAM); + SekMapMemory(CpsRam708 + 0x8000, 0x70E000, 0x70FFFF, SM_RAM); + } else { + SekMapMemory(CpsRam708, 0x708000, 0x709FFF, SM_RAM); + SekMapMemory(CpsRam708, 0x70A000, 0x70BFFF, SM_RAM); + SekMapMemory(CpsRam708, 0x70C000, 0x70DFFF, SM_RAM); + SekMapMemory(CpsRam708, 0x70E000, 0x70FFFF, SM_RAM); + } + } +} + +INT32 __fastcall CPSResetCallback() +{ + // Reset instruction on 68000 + if (!Cps1Pic) ZetReset(); // Reset Z80 (CPU #1) + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall CPSQSoundC0ReadByte(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" QS %06X read\n"), sekAddress); + + if (!(sekAddress & 1)) { + return 0xFF; + } + + QsndSyncZ80(); + + sekAddress &= 0x1FFF; + return CpsZRamC0[sekAddress >> 1]; +} + +void __fastcall CPSQSoundC0WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" QS %06X -> %02X\n"), sekAddress, byteValue); + + if (!(sekAddress & 1)) { + return; + } + + sekAddress &= 0x1FFF; + +#if 1 && defined USE_SPEEDHACKS + // Sync only when the last byte of the sound command is written + if (sekAddress == 0x001F) { + QsndSyncZ80(); + } +#else + QsndSyncZ80(); +#endif + + CpsZRamC0[sekAddress >> 1] = byteValue; +} + +UINT8 __fastcall CPSQSoundF0ReadByte(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" QS %06X read\n"), sekAddress); + + if (!(sekAddress & 1)) { + return 0xFF; + } + + QsndSyncZ80(); + + sekAddress &= 0x1FFF; + return CpsZRamF0[sekAddress >> 1]; +} + +void __fastcall CPSQSoundF0WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" QS %06X -> %02X\n"), sekAddress, byteValue); + + if (!(sekAddress & 1)) { + return; + } + + sekAddress &= 0x1FFF; + +#if 1 && defined USE_SPEEDHACKS + // Sync only when the last byte of the sound command is written + if (sekAddress == 0x001F) { + QsndSyncZ80(); + } +#else + QsndSyncZ80(); +#endif + + CpsZRamF0[sekAddress >> 1] = byteValue; +} + +// ---------------------------------------------------------------------------- + +#if 0 +UINT8 __fastcall CPSExtraNVRAMReadByte(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" - 0x%06X read.\n"), sekAddress); + + sekAddress &= 0x3FFF; + return CpsRam660[sekAddress]; +} + +void __fastcall CPSExtraNVRAMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" - 0x%06X -> %02X\n"), sekAddress, byteValue); + + sekAddress &= 0x3FFF; + CpsRam660[sekAddress] = byteValue; +} +#endif + +// ---------------------------------------------------------------------------- + +/* +INT32 prevline; + +void __fastcall CpsWriteSpriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (prevline != SekCurrentScanline()) { + prevline = SekCurrentScanline(); +// bprintf(PRINT_NORMAL, _T(" - sb (%3i)\n"), prevline); + } + + sekAddress &= 0x1FFF; + CpsRam708[sekAddress + nCpsObjectBank * 0x8000] = byteValue; +} + +void __fastcall CpsWriteSpriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (prevline != SekCurrentScanline()) { + prevline = SekCurrentScanline(); +// bprintf(PRINT_NORMAL, _T(" - sw (%3i)\n"), prevline); + } + + sekAddress &= 0x1FFE; + CpsRam708[sekAddress + nCpsObjectBank * 0x8000 + 1] = wordValue >> 8; + CpsRam708[sekAddress + nCpsObjectBank * 0x8000 + 0] = wordValue & 255; +} +*/ + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall haxx0rReadByte(UINT32 sekAddress) +{ + sekAddress &= 0xFFFF; + bprintf(PRINT_NORMAL, _T(" QS %06X read (%02X)\n"), sekAddress, CpsEncZRom[sekAddress]); + return CpsEncZRom[sekAddress]; +} + +INT32 CpsMemInit() +{ + if (AllocateMemory()) { + return 1; + } + + SekOpen(0); + + SekSetResetCallback(CPSResetCallback); + + // Map in memory: + // 68000 Rom (as seen as is, through read) + SekMapMemory(CpsRom, 0, nCpsRomLen - 1, SM_READ); + + // 68000 Rom (as seen decrypted, through fetch) + if (nCpsCodeLen > 0) { + // Decoded part (up to nCpsCodeLen) + SekMapMemory(CpsCode, 0, nCpsCodeLen - 1, SM_FETCH); + } + if (nCpsRomLen > nCpsCodeLen) { + // The rest (up to nCpsRomLen) + SekMapMemory(CpsRom + nCpsCodeLen, nCpsCodeLen, nCpsRomLen - 1, SM_FETCH); + } + + if (Cps == 2) { + nCpsObjectBank = -1; + CpsMapObjectBanks(0); + +#if 0 + SekMapHandler(3, 0x660000, 0x663FFF, SM_RAM); + SekSetReadByteHandler(3, CPSExtraNVRAMReadByte); + SekSetWriteByteHandler(3, CPSExtraNVRAMWriteByte); +#else + SekMapMemory(CpsRam660, 0x660000, 0x663FFF, SM_RAM); +#endif + +// SekMapHandler(4, 0x708000, 0x709FFF, SM_WRITE); +// SekMapHandler(4, 0x70A000, 0x70BFFF, SM_WRITE); +// SekMapHandler(4, 0x70C000, 0x70DFFF, SM_WRITE); +// SekMapHandler(4, 0x70E000, 0x70FFFF, SM_WRITE); + +// SekSetWriteByteHandler(4, CpsWriteSpriteByte); +// SekSetWriteWordHandler(4, CpsWriteSpriteWord); + } + + SekMapMemory(CpsRam90, 0x900000, 0x92FFFF, SM_RAM); // Gfx Ram + SekMapMemory(CpsRamFF, 0xFF0000, 0xFFFFFF, SM_RAM); // Work Ram + + SekSetReadByteHandler(0, CpsReadByte); + SekSetWriteByteHandler(0, CpsWriteByte); + SekSetReadWordHandler(0, CpsReadWord); + SekSetWriteWordHandler(0, CpsWriteWord); + + // QSound + if (Cps == 2) { + SekMapHandler(1, 0x618000, 0x619FFF, SM_RAM); + + SekSetReadByteHandler(1, CPSQSoundC0ReadByte); + SekSetWriteByteHandler(1, CPSQSoundC0WriteByte); + } + + if (Cps1Qs == 1) { + // Map the 1st 32KB of the QSound ROM into the 68K address space + for (INT32 i = 0x7FFF; i >= 0; i--) { + CpsEncZRom[(i << 1) + 0] = CpsEncZRom[i]; + CpsEncZRom[(i << 1) + 1] = 0xFF; + } + SekMapMemory(CpsEncZRom, 0xF00000, 0xF0FFFF, SM_ROM); + + // QSound shared RAM + SekMapHandler(1, 0xF18000, 0xF19FFF, SM_RAM); + SekMapHandler(2, 0xF1E000, 0xF1FFFF, SM_RAM); + + SekSetReadByteHandler(1, CPSQSoundC0ReadByte); + SekSetWriteByteHandler(1, CPSQSoundC0WriteByte); + SekSetReadByteHandler(2, CPSQSoundF0ReadByte); + SekSetWriteByteHandler(2, CPSQSoundF0WriteByte); + } + + SekClose(); + + return 0; +} + +INT32 CpsMemExit() +{ +#if 0 + FILE* fp = fopen("mem.raw", "wb"); + if (fp) { + fwrite(CpsRam660, 1, 0x4000, fp); + fclose(fp); + } +#endif + + // Deallocate all used memory + if (CpsMem) { + free(CpsMem); + CpsMem = NULL; + } + + return 0; +} + +static INT32 ScanRam() +{ + // scan ram: + struct BurnArea ba; + memset(&ba, 0, sizeof(ba)); + + ba.Data = CpsRam90; ba.nLen = 0x030000; ba.szName = "CpsRam90"; BurnAcb(&ba); + ba.Data = CpsRamFF; ba.nLen = 0x010000; ba.szName = "CpsRamFF"; BurnAcb(&ba); + ba.Data = CpsReg; ba.nLen = 0x000100; ba.szName = "CpsReg"; BurnAcb(&ba); + + if (Cps == 2 || Cps1Qs == 1) { + ba.Data = CpsZRamC0; ba.nLen = 0x001000; ba.szName = "CpsZRamC0"; BurnAcb(&ba); + ba.Data = CpsZRamF0; ba.nLen = 0x001000; ba.szName = "CpsZRamF0"; BurnAcb(&ba); + } + + if (Cps == 2) { + ba.Data = CpsRam708; ba.nLen = 0x010000; ba.szName = "CpsRam708"; BurnAcb(&ba); + ba.Data = CpsFrg; ba.nLen = 0x000010; ba.szName = "CpsFrg"; BurnAcb(&ba); + } + + return 0; +} + +// Scan the current state of the CPS1/2 machine +INT32 CpsAreaScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (CpsMem == NULL) { + return 1; + } + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_MEMORY_ROM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = CpsRom; + ba.nLen = nCpsRomLen; + ba.szName = "CpsRom"; + BurnAcb(&ba); + + ba.Data = CpsZRom; + ba.nLen = nCpsZRomLen; + ba.szName = "CpsZRom"; + BurnAcb(&ba); + } + + if (Cps == 2 || Cps1Qs == 1 || PangEEP == 1) { // Scan EEPROM + EEPROMScan(nAction, pnMin); + } + + if (nAction & ACB_MEMORY_RAM) { + + ScanRam(); + + if (Cps == 2) { + memset(&ba, 0, sizeof(ba)); + ba.Data = CpsRam660; + ba.nLen = 0x004000; + ba.szName = "CpsRam660"; + BurnAcb(&ba); + } + } + + + if (nAction & ACB_DRIVER_DATA) { // Scan volatile variables/registers/RAM + + SekScan(nAction); // Scan 68000 state + + if (nAction & ACB_WRITE) { // Palette could have changed + CpsRecalcPal = 1; + } + } + + if (Cps == 2 || Cps1Qs == 1) { // Scan QSound chips + QsndScan(nAction); + } else { // Scan PSound chips + PsndScan(nAction); + } + + return 0; +} diff --git a/src/burn/drivers/capcom/cps_obj.cpp b/src/burn/drivers/capcom/cps_obj.cpp new file mode 100644 index 00000000..bc2d7b90 --- /dev/null +++ b/src/burn/drivers/capcom/cps_obj.cpp @@ -0,0 +1,401 @@ +#include "cps.h" +// CPS Objs (sprites) + +INT32 nCpsObjectBank; + +UINT8 *BootlegSpriteRam = NULL; + +INT32 Sf2Hack = 0; + +// Our copy of the sprite table +static UINT8 *ObjMem = NULL; + +static INT32 nMax = 0; +static INT32 nGetNext = 0; + +static INT32 nMaxZValue; +static INT32 nMaxZMask; + +static INT32 nZOffset; + +// Object frames, so you can lag the Objs by nFrameCount-1 frames +struct ObjFrame { + INT32 nShiftX, nShiftY; + UINT8* Obj; + INT32 nCount; +}; + +static INT32 nFrameCount = 0; +static struct ObjFrame of[3]; + +INT32 CpsObjInit() +{ + nMax = 0x100; // CPS1 has 256 sprites + + if (Cps == 2) { // CPS2 has 1024 sprites + nMax = 0x400; + } + + nFrameCount = 2; // CPS2 sprites lagged by 1 frame and double buffered + // CPS1 sprites lagged by 1 frame + + ObjMem = (UINT8*)malloc((nMax << 3) * nFrameCount); + if (ObjMem == NULL) { + return 1; + } + + // Set up the frame buffers + for (INT32 i = 0; i < nFrameCount; i++) { + of[i].Obj = ObjMem + (nMax << 3) * i; + of[i].nCount = 0; + } + + nGetNext=0; + + if (Cps == 2) { + memset(ZBuf, 0, 384 * 224 * 2); + nMaxZMask = nZOffset = 0; + nMaxZValue = 1; + } + + return 0; +} + +INT32 CpsObjExit() +{ + for (INT32 i = 0; i < nFrameCount; i++) { + of[i].Obj = NULL; + of[i].nCount = 0; + } + + if (ObjMem) { + free(ObjMem); + ObjMem = NULL; + } + + nFrameCount = 0; + nMax = 0; + + return 0; +} + +// Get CPS sprites into Obj +INT32 CpsObjGet() +{ + INT32 i; + UINT8 *pg, *po; + struct ObjFrame* pof; + UINT8* Get = NULL; + + pof = of + nGetNext; + + pof->nCount = 0; + + po = pof->Obj; + pof->nShiftX = -0x40; + pof->nShiftY = -0x10; + + if (Cps == 2) { + Get = CpsRam708 + ((nCpsObjectBank ^ 1) << 15); // Select CPS2 sprite buffer +// Get = CpsRam708 + ((GetCurrentFrame() & 1) << 15); // Select CPS2 sprite buffer + + pof->nShiftX = -CpsSaveFrg[0][0x9]; + pof->nShiftY = -CpsSaveFrg[0][0xB]; + } else { + INT32 nOff = *((UINT16*)(CpsReg + 0x00)) << 8; + nOff &= 0xfff800; + Get = CpsFindGfxRam(nOff, 0x800); + + if (Sf2Hack) { + Get = CpsFindGfxRam(0x910000, 0x800); + } else { + if (Dinopic) { + Get = BootlegSpriteRam + 0x1000; + } + } + } + + if (Get==NULL) return 1; + + // Make a copy of all active sprites in the list + for (pg = Get, i = 0; i < nMax; pg += 8, i++) { + UINT16* ps = (UINT16*)pg; + + if (Cps == 2) { + if (ps[1] & 0x8000) { // end of sprite list? + break; + } + if (ps[0] == 0 && ps[1] == 0x0100 && ps[2] == 0 && ps[3] == 0xff00) { // Slammasters end of sprite list? + break; + } + } else { + if (Dinopic) { + if (ps[1] == 0x8000) { // end of sprite list + break; + } + } else { + if (ps[3] == 0xff00) { // end of sprite list + break; + } + } + } + + if (Dinopic) { + if (((ps[2] - 461) | ps[1]) == 0) { // sprite blank + continue; + } + } else { + if ((ps[0] | ps[3]) == 0) { // sprite blank + continue; + } + } + + // Okay - this sprite is active: + memcpy(po, pg, 8); // copy it over + + pof->nCount++; + po += 8; + } + + nGetNext++; + if (nGetNext >= nFrameCount) { + nGetNext = 0; + } + + return 0; +} + +void CpsObjDrawInit() +{ + nZOffset = nMaxZMask; + + if (nZOffset >= 0xFC00) { + // The Z buffer might moverflow the next fram, so initialise it + memset(ZBuf, 0, 384 * 224 * 2); + nZOffset = 0; + } + + nMaxZValue = nZOffset + 1; + nMaxZMask = nZOffset; + + return; +} + +INT32 Cps1ObjDraw(INT32 nLevelFrom,INT32 nLevelTo) +{ + INT32 i; UINT16 *ps; INT32 nPsAdd; + struct ObjFrame *pof; + (void)nLevelFrom; (void)nLevelTo; + + // Draw the earliest frame we have in history + pof=of+nGetNext; + + // Point to Obj list + ps=(UINT16 *)pof->Obj; + + if (!CpsDrawSpritesInReverse) { + ps+=(pof->nCount-1)<<2; nPsAdd=-4; // CPS1 is reversed + } else { + nPsAdd=4; + } + + // Go through all the Objs + for (i=0; inCount; i++,ps+=nPsAdd) { + INT32 x,y,n,a,bx,by,dx,dy; INT32 nFlip; + + if (Dinopic) { + n = ps[0]; a = ps[1]; x = ps[2] - 461; y = 0x2f0 - ps[3]; + bx = 1; + by = 1; + } else { + x = ps[0]; y = ps[1]; n = ps[2]; a = ps[3]; + + // Find out sprite size + bx=((a>> 8)&15)+1; + by=((a>>12)&15)+1; + } + + n = GfxRomBankMapper(GFXTYPE_SPRITES, n); + if (n == -1) continue; + + n |= (y & 0x6000) << 3; // high bits of address + + // CPS1 coords are 9 bit signed? + x&=0x01ff; if (x>=0x1c0) x-=0x200; + y&=0x01ff; y^=0x100; y-=0x100; + + x+=pof->nShiftX; + y+=pof->nShiftY; + + // Find the palette for the tiles on this sprite + CpstPal = CpsObjPal + ((a & 0x1F) << 4); + + nFlip=(a>>5)&3; + + // Take care with tiles if the sprite goes off the screen + if (x<0 || y<0 || x+(bx<<4)>384 || y+(by<<4)>224) { + nCpstType=CTT_16X16 | CTT_CARE; + } else { + nCpstType=CTT_16X16; + } + + nCpstFlip=nFlip; + for (dy=0;dyObj + nPsAdd * (nMaxZValue - nZOffset - 1); + nCount = nZOffset + pof->nCount; + + // Go through all the Objs + for (ZValue = (UINT16)nMaxZValue; ZValue <= nCount; ZValue++, ps += nPsAdd) { + INT32 x, y, n, a, bx, by, dx, dy; + INT32 nFlip; + INT32 v = ps[0] >> 13; + + if ((nSpriteEnable & (1 << v)) == 0) { + continue; + } + + // Check if sprite is between these levels + if (v > nLevelTo) { + bMask = 1; + continue; + } + if (v < nLevelFrom) { + continue; + } + + if (bMask) { + nMaxZMask = ZValue; + } else { + nMaxZValue = ZValue; + } + + // Select CpstOne function; + if (bMask || nMaxZMask > nMaxZValue) { + pCpstOne = CpstOneObjDoX[1]; + } else { + pCpstOne = CpstOneObjDoX[0]; + } + + x = ps[0]; + y = ps[1]; + n = ps[2]; + a = ps[3]; + + if (a & 0x80) { // marvel vs capcom ending sprite off-set + x += CpsSaveFrg[0][0x9]; + } + + // CPS2 coords are 10 bit signed (-512 to 511) + x &= 0x03FF; x ^= 0x200; x -= 0x200; + y &= 0x03FF; y ^= 0x200; y -= 0x200; + +#if 0 + // This *MAY* be needed to get correct sprite positions when raster interrups are used. + if (nRasterline[1]) { + for (INT32 i = 1; i < MAX_RASTER; i++) { + if ((y < nRasterline[i]) || (nRasterline[i] == 0)) { + x -= CpsSaveFrg[i - 1][0x09]; + y -= CpsSaveFrg[i - 1][0x0B]; + break; + } + } + } else { + x -= CpsSaveFrg[0][0x9]; + y -= CpsSaveFrg[0][0xB]; + } +#else + // Ignore sprite offsets when raster interrupts are used (seems to work for all games). + x += pof->nShiftX; + y += pof->nShiftY; + +// x -= CpsSaveFrg[0][0x9]; +// y -= CpsSaveFrg[0][0xB]; + +#endif + n |= (ps[1] & 0x6000) << 3; // high bits of address + + // Find the palette for the tiles on this sprite + CpstPal = CpsObjPal + ((a & 0x1F) << 4); + + nFlip = (a >> 5) & 3; + // Find out sprite size + bx = ((a >> 8) & 15) + 1; + by = ((a >> 12) & 15) + 1; + + // Take care with tiles if the sprite goes off the screen + if (x < 0 || y < 0 || x + (bx << 4) > 383 || y + (by << 4) > 223) { + nCpstType = CTT_16X16 | CTT_CARE; + } else { + nCpstType = CTT_16X16; + } + +// if (v == 0) { +// bprintf(PRINT_IMPORTANT, _T(" - %4i: 0x%04X 0x%04X 0x%04X 0x%04X\n"), ZValue - (UINT16)nMaxZValue, ps[0], ps[1], ps[2], ps[3]); +// } + + nCpstFlip = nFlip; + for (dy = 0; dy < by; dy++) { + for (dx = 0; dx < bx; dx++) { + INT32 ex, ey; + + if (nFlip & 1) { + ex = (bx - dx - 1); + } else { + ex = dx; + } + + if (nFlip & 2) { + ey = (by - dy - 1); + } else { + ey = dy; + } + + nCpstX = x + (ex << 4); + nCpstY = y + (ey << 4); + +// nCpstTile = n + (dy << 4) + dx; // normal version + nCpstTile = (n & ~0x0F) + (dy << 4) + ((n + dx) & 0x0F); // pgear fix + nCpstTile <<= 7; // Find real tile address + + pCpstOne(); + } + } + } + + return 0; +} diff --git a/src/burn/drivers/capcom/cps_pal.cpp b/src/burn/drivers/capcom/cps_pal.cpp new file mode 100644 index 00000000..3ec60d38 --- /dev/null +++ b/src/burn/drivers/capcom/cps_pal.cpp @@ -0,0 +1,297 @@ +#include "cps.h" +// CPS (palette) + +static UINT8* CpsPalSrc = NULL; // Copy of current input palette + +UINT32* CpsPal = NULL; // Hicolor version of palette +UINT32* CpsObjPal = NULL; + +INT32 nLagObjectPalettes; + +inline static UINT32 CalcColCPS1(UINT16 a) +{ + INT32 r, g, b, f; + const INT32 F_OFFSET = 0x0F; + + // Format is FFFF RRRR GGGG BBBB + f = (a & 0xF000) >> 12; + + r = (a & 0x0F00) >> 4; // Red + r |= r >> 4; + g = (a & 0x00F0); // Green + g |= g >> 4; + b = (a & 0x000F); // Blue + b |= b << 4; + + f += F_OFFSET; + r *= f; r /= F_OFFSET + 0x0F; + g *= f; g /= F_OFFSET + 0x0F; + b *= f; b /= F_OFFSET + 0x0F; + + return BurnHighCol(r, g, b, 0); +} + +static UINT32 CalcColCPS2(UINT16 a) +{ + INT32 r, g, b, f; + const INT32 F_OFFSET = 0x0F; + + // Format is FFFF RRRR GGGG BBBB + f = (a & 0xF000) >> 12; + + r = (a & 0x0F00) >> 4; // Red + r |= r >> 4; + g = (a & 0x00F0); // Green + g |= g >> 4; + b = (a & 0x000F); // Blue + b |= b << 4; + + f += F_OFFSET; + r *= f; r /= F_OFFSET + 0x0F; + g *= f; g /= F_OFFSET + 0x0F; + b *= f; b /= F_OFFSET + 0x0F; + + return BurnHighCol(r, g, b, 0); +} + +static INT32 CalcAll() +{ + UINT16* ps; + + if (Cps == 2) { + if (nLagObjectPalettes) { + ps = (UINT16*)CpsPalSrc + 0x0C00; + for (INT32 i = 0x0C00; i < 0x0E00; i++, ps++) { + CpsPal[i ^ 15] = CalcColCPS2(*ps); + } + ps = (UINT16*)CpsPalSrc + 0x0200; + for (INT32 i = 0x0200; i < 0x0800; i++, ps++) { + CpsPal[i ^ 15] = CalcColCPS2(*ps); + } + + memcpy(CpsPal + 0x0E00, CpsPal + 0x0C00, 0x0200 << 2); + } else { + ps = (UINT16*)CpsPalSrc; + for (INT32 i = 0x0000; i < 0x0800; i++, ps++) { + CpsPal[i ^ 15] = CalcColCPS2(*ps); + } + } + + } else { + ps = (UINT16*)CpsPalSrc; + for (INT32 i = 0x0000; i < 0x0c00; i++, ps++) { + CpsPal[i ^ 15] = CalcColCPS1(*ps); + } + } + + return 0; +} + +static void CalcAllStar(INT32 nLayer) +{ + UINT16* ps = (UINT16*)CpsPalSrc; + INT32 nOffset = 0x0800 + (nLayer << 9); + + for (INT32 i = 0; i < 128; i++, ps++) { + CpsPal[(i + nOffset) ^ 15] = CalcColCPS1(*(ps + nOffset)); + } +} + +INT32 CpsPalInit() +{ + INT32 nLen = 0; + + nLen = 0x1000 * sizeof(UINT16); + CpsPalSrc = (UINT8*)malloc(nLen); + if (CpsPalSrc == NULL) { + return 1; + } + memset(CpsPalSrc, 0, nLen); + + // The star layer palettes are at the end of the normal palette, so double the size + nLen = 0x1000 * sizeof(UINT32); + CpsPal = (UINT32*)malloc(nLen); + if (CpsPal == NULL) { + return 1; + } + + // Set CpsPal to initial values + CalcAll(); + if (CpsStar) { + CalcAllStar(0); + CalcAllStar(1); + } + + if (nLagObjectPalettes) { + CpsObjPal = CpsPal + 0x0C00; + } else { + CpsObjPal = CpsPal; + } + + return 0; +} + +INT32 CpsPalExit() +{ + if (CpsPal) { + free(CpsPal); + CpsPal = NULL; + } + if (CpsPalSrc) { + free(CpsPalSrc); + CpsPalSrc = NULL; + } + return 0; +} + +// Update CpsPal with the new palette at pNewPal (length 0x1000 bytes) +INT32 CpsPalUpdate(UINT8* pNewPal, INT32 bRecalcAll) +{ + INT32 i; + UINT16 *ps, *pn; + + // If we are recalculating the whole palette, just copy to CpsPalSrc + // and recalculate it all + if (bRecalcAll) { + ps = (UINT16*)CpsPalSrc; + pn = (UINT16*)pNewPal; + + if (nLagObjectPalettes) { + INT32 nBuffer = 0x0C00 + ((GetCurrentFrame() & 1) << 9); + + memcpy(ps + 0x0200, pn + 0x0200, 0x0600 << 1); + memcpy(ps + nBuffer, pn, 0x0200 << 1); + memcpy(ps + 0x0E00, pn, 0x0200 << 1); + + CpsObjPal = CpsPal + nBuffer; + } else { + memcpy(ps, pn, 0x0c00 << 1); + } + + CalcAll(); + + return 0; + } + + if (Cps == 2) { + if (nLagObjectPalettes) { + INT32 nBuffer = 0x0C00 + ((GetCurrentFrame() & 1) << 9); + + ps = (UINT16*)CpsPalSrc + (nBuffer ^ 0x0200); + pn = (UINT16*)pNewPal; + CpsObjPal = CpsPal + (nBuffer ^ 0x0200); + + for (i = 0; i < 0x0200; i++, ps++, pn++) { + UINT16 n; + n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsObjPal[i ^ 15] = CalcColCPS2(n); + } + + ps = (UINT16*)CpsPalSrc + 0x0200; + pn = (UINT16*)pNewPal + 0x0200; + + for (i = 0x0200; i < 0x0800; i++, ps++, pn++) { + UINT16 n; + n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsPal[i ^ 15] = CalcColCPS2(n); + } + + CpsObjPal = CpsPal + nBuffer; + } else { + ps = (UINT16*)CpsPalSrc; + pn = (UINT16*)pNewPal; + + for (i = 0x0000; i < 0x0800; i++, ps++, pn++) { + UINT16 n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsPal[i ^ 15] = CalcColCPS2(n); + } + } + } else { + ps = (UINT16*)CpsPalSrc; + pn = (UINT16*)pNewPal; + + for (i = 0x0000; i < 0x0c00; i++, ps++, pn++) { + UINT16 n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsPal[i ^ 15] = CalcColCPS1(n); + } + } + + return 0; +} + +INT32 CpsStarPalUpdate(UINT8* pNewPal, INT32 nLayer, INT32 bRecalcAll) +{ + INT32 i; + UINT16 *ps, *pn; + + if (nLayer == 0) { + ps = (UINT16*)CpsPalSrc + 0x0800; + pn = (UINT16*)pNewPal + 0x0800; + + if (bRecalcAll) { + memcpy(ps, pn, 256); + CalcAllStar(nLayer); + return 0; + } + + // Star layer 0 + for (i = 0x0800; i < 0x0880; i++, ps++, pn++) { + UINT16 n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsPal[i ^ 15] = CalcColCPS1(n); + } + } else { + ps = (UINT16*)CpsPalSrc + 0x0A00; + pn = (UINT16*)pNewPal + 0x0A00; + + if (bRecalcAll) { + memcpy(ps, pn, 256); + CalcAllStar(nLayer); + return 0; + } + + // Star layer 1 + for (i = 0x0A00; i < 0x0A80; i++, ps++, pn++) { + UINT16 n = *pn; + if (*ps == n) { + continue; // Colour hasn't changed - great! + } + + *ps = n; // Update our copy of the palette + + CpsPal[i ^ 15] = CalcColCPS1(n); + } + } + + return 0; +} + diff --git a/src/burn/drivers/capcom/cps_run.cpp b/src/burn/drivers/capcom/cps_run.cpp new file mode 100644 index 00000000..6eb0933b --- /dev/null +++ b/src/burn/drivers/capcom/cps_run.cpp @@ -0,0 +1,497 @@ +// CPS - Run +#include "cps.h" + +// Inputs: +UINT8 CpsReset = 0; +UINT8 Cpi01A = 0, Cpi01C = 0, Cpi01E = 0; + +static INT32 nInterrupt; +static INT32 nIrqLine, nIrqCycles; +static bool bEnableAutoIrq50, bEnableAutoIrq52; // Trigger an interrupt every 32 scanlines + +static const INT32 nFirstLine = 0x0C; // The first scanline of the display +static const INT32 nVBlank = 0x0106 - 0x0C; // The scanline at which the vblank interrupt is triggered + +static INT32 nCpsCyclesExtra; + +INT32 CpsDrawSpritesInReverse = 0; + +INT32 nIrqLine50, nIrqLine52; + +static INT32 DrvReset() +{ + // Reset machine + if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMReset(); + + SekOpen(0); + SekReset(); + SekClose(); + + if (!Cps1Pic) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + if (Cps == 2) { + // Disable beam-synchronized interrupts + *((UINT16*)(CpsReg + 0x4E)) = 0x0200; + *((UINT16*)(CpsReg + 0x50)) = 0x0106; + *((UINT16*)(CpsReg + 0x52)) = 0x0106; + } + + CpsMapObjectBanks(0); + + nCpsCyclesExtra = 0; + + if (Cps == 2 || Cps1Qs == 1) { // Sound init (QSound) + QsndReset(); + } + + HiscoreReset(); + + return 0; +} + +static const eeprom_interface qsound_eeprom_interface = +{ + 7, /* address bits */ + 8, /* data bits */ + "0110", /* read command */ + "0101", /* write command */ + "0111", /* erase command */ + 0, + 0, + 0, + 0 +}; + +static const eeprom_interface cps2_eeprom_interface = +{ + 6, /* address bits */ + 16, /* data bits */ + "0110", /* read command */ + "0101", /* write command */ + "0111", /* erase command */ + 0, + 0, + 0, + 0 +}; + +INT32 CpsRunInit() +{ + nLagObjectPalettes = 0; + + if (Cps == 2) nLagObjectPalettes = 1; + + SekInit(0, 0x68000); // Allocate 68000 + + if (CpsMemInit()) { // Memory init + return 1; + } + + if (Cps == 2 || PangEEP) { + EEPROMInit(&cps2_eeprom_interface); + } else { + if (Cps1Qs == 1) { + EEPROMInit(&qsound_eeprom_interface); + } + } + + CpsRwInit(); // Registers setup + + if (CpsPalInit()) { // Palette init + return 1; + } + if (CpsObjInit()) { // Sprite init + return 1; + } + + if ((Cps & 1) && Cps1Qs == 0 && Cps1Pic == 0) { // Sound init (MSM6295 + YM2151) + if (PsndInit()) { + return 1; + } + } + + if (Cps == 2 || Cps1Qs == 1) { // Sound init (QSound) + if (QsndInit()) { + return 1; + } + } + + if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMReset(); + DrvReset(); + + //Init Draw Function + DrawFnInit(); + + pBurnDrvPalette = CpsPal; + + return 0; +} + +INT32 CpsRunExit() +{ + if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMExit(); + + // Sound exit + if (Cps == 2 || Cps1Qs == 1) QsndExit(); + if (Cps != 2 && Cps1Qs == 0) PsndExit(); + + // Graphics exit + CpsObjExit(); + CpsPalExit(); + + // Sprite Masking exit + ZBuf = NULL; + + // Memory exit + CpsRwExit(); + CpsMemExit(); + + SekExit(); + + return 0; +} + +// nStart = 0-3, nCount=1-4 +inline static void GetPalette(INT32 nStart, INT32 nCount) +{ + // Update Palette (Ghouls points to the wrong place on boot up I think) + INT32 nPal = (*((UINT16*)(CpsReg + 0x0A)) << 8) & 0xFFF800; + + UINT8* Find = CpsFindGfxRam(nPal, 0x1000); + if (Find) { + memcpy(CpsSavePal + (nStart << 10), Find + (nStart << 10), nCount << 10); + } +} + +static void GetStarPalette() +{ + INT32 nPal = (*((UINT16*)(CpsReg + 0x0A)) << 8) & 0xFFF800; + + UINT8* Find = CpsFindGfxRam(nPal, 256); + if (Find) { + memcpy(CpsSavePal + 4096, Find + 4096, 256); + memcpy(CpsSavePal + 5120, Find + 5120, 256); + } +} + +inline static void CopyCpsReg(INT32 i) +{ + memcpy(CpsSaveReg[i], CpsReg, 0x0100); +} + +inline static void CopyCpsFrg(INT32 i) +{ + memcpy(CpsSaveFrg[i], CpsFrg, 0x0010); +} + +// Schedule a beam-synchronized interrupt +static void ScheduleIRQ() +{ + INT32 nLine = 0x0106; + + if (nIrqLine50 <= nLine) { + nLine = nIrqLine50; + } + if (nIrqLine52 < nLine) { + nLine = nIrqLine52; + } + + if (nLine < 0x0106) { + nIrqLine = nLine; + nIrqCycles = (nLine * nCpsCycles / 0x0106) + 1; + } else { + nIrqCycles = nCpsCycles + 1; + } + + return; +} + +// Execute a beam-synchronised interrupt and schedule the next one +static void DoIRQ() +{ + // 0x4E - bit 9 = 1: Beam Synchronized interrupts disabled + // 0x50 - Beam synchronized interrupt #1 occurs at raster line. + // 0x52 - Beam synchronized interrupt #2 occurs at raster line. + + // Trigger IRQ and copy registers. + if (nIrqLine >= nFirstLine) { + + nInterrupt++; + nRasterline[nInterrupt] = nIrqLine - nFirstLine; + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekRun(nCpsCycles * 0x01 / 0x0106); + if (nRasterline[nInterrupt] < 224) { + CopyCpsReg(nInterrupt); + CopyCpsFrg(nInterrupt); + } else { + nRasterline[nInterrupt] = 0; + } + + // Schedule next interrupt + if (!bEnableAutoIrq50) { + if (nIrqLine >= nIrqLine50) { + nIrqLine50 = 0x0106; + } + } else { + if (bEnableAutoIrq50 && nIrqLine == nIrqLine50) { + nIrqLine50 += 32; + } + } + if (!bEnableAutoIrq52 && nIrqLine >= nIrqLine52) { + nIrqLine52 = 0x0106; + } else { + if (bEnableAutoIrq52 && nIrqLine == nIrqLine52) { + nIrqLine52 += 32; + } + } + ScheduleIRQ(); + if (nIrqCycles < SekTotalCycles()) { + nIrqCycles = SekTotalCycles() + 1; + } + + return; +} + +INT32 Cps1Frame() +{ + INT32 nDisplayEnd, nNext, i; + + if (CpsReset) { + DrvReset(); + } + + SekNewFrame(); + if (Cps1Qs == 1) { + QsndNewFrame(); + } else { + if (!Cps1Pic) { + ZetOpen(0); + PsndNewFrame(); + } + } + + nCpsCycles = (INT32)((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust >> 8); + + CpsRwGetInp(); // Update the input port values + + nDisplayEnd = (nCpsCycles * (nFirstLine + 224)) / 0x0106; // Account for VBlank + + SekOpen(0); + SekIdle(nCpsCyclesExtra); + + SekRun(nCpsCycles * nFirstLine / 0x0106); // run 68K for the first few lines + + if (!CpsDrawSpritesInReverse) { + CpsObjGet(); // Get objects + } + + for (i = 0; i < 4; i++) { + nNext = ((i + 1) * nCpsCycles) >> 2; // find out next cycle count to run to + + if (SekTotalCycles() < nDisplayEnd && nNext > nDisplayEnd) { + + SekRun(nNext - nDisplayEnd); // run 68K + + memcpy(CpsSaveReg[0], CpsReg, 0x100); // Registers correct now + + GetPalette(0, 6); // Get palette + if (CpsStar) { + GetStarPalette(); + } + + if (CpsDrawSpritesInReverse) { + if (i == 3) CpsObjGet(); // Get objects + } + + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // Trigger VBlank interrupt + } + + SekRun(nNext - SekTotalCycles()); // run 68K + +// if (pBurnDraw) { +// CpsDraw(); // Draw frame +// } + } + + if (pBurnDraw) { + CpsDraw(); // Draw frame + } + + if (Cps1Qs == 1) { + QsndEndFrame(); + } else { + if (!Cps1Pic) { + PsndSyncZ80(nCpsZ80Cycles); + PsmUpdate(nBurnSoundLen); + ZetClose(); + } + } + + nCpsCyclesExtra = SekTotalCycles() - nCpsCycles; + + SekClose(); + + return 0; +} + +INT32 Cps2Frame() +{ + INT32 nDisplayEnd, nNext; // variables to keep track of executed 68K cyles + INT32 i; + + if (CpsReset) { + DrvReset(); + } + +// extern INT32 prevline; +// prevline = -1; + + SekNewFrame(); + QsndNewFrame(); + + nCpsCycles = (INT32)(((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust) / 0x0100); + SekSetCyclesScanline(nCpsCycles / 262); + + CpsRwGetInp(); // Update the input port values + + nDisplayEnd = nCpsCycles * (nFirstLine + 224) / 0x0106; // Account for VBlank + + nInterrupt = 0; + for (i = 0; i < MAX_RASTER + 2; i++) { + nRasterline[i] = 0; + } + + // Determine which (if any) of the line counters generates the first IRQ + bEnableAutoIrq50 = bEnableAutoIrq52 = false; + nIrqLine50 = nIrqLine52 = 0x0106; + if (*((UINT16*)(CpsReg + 0x50)) & 0x8000) { + bEnableAutoIrq50 = true; + } + if (bEnableAutoIrq50 || (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) { + nIrqLine50 = (*((UINT16*)(CpsReg + 0x50)) & 0x01FF); + } + if (*((UINT16*)(CpsReg + 0x52)) & 0x8000) { + bEnableAutoIrq52 = true; + } + if (bEnableAutoIrq52 || (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) { + nIrqLine52 = (*((UINT16*)(CpsReg + 0x52)) & 0x01FF); + } + ScheduleIRQ(); + + SekOpen(0); + SekIdle(nCpsCyclesExtra); + + if (nIrqCycles < nCpsCycles * nFirstLine / 0x0106) { + SekRun(nIrqCycles); + DoIRQ(); + } + nNext = nCpsCycles * nFirstLine / 0x0106; + if (SekTotalCycles() < nNext) { + SekRun(nNext - SekTotalCycles()); + } + + CopyCpsReg(0); // Get inititial copy of registers + CopyCpsFrg(0); // + + if (nIrqLine >= 0x0106 && (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) { + nIrqLine50 = *((UINT16*)(CpsReg + 0x50)) & 0x01FF; + nIrqLine52 = *((UINT16*)(CpsReg + 0x52)) & 0x01FF; + ScheduleIRQ(); + } + + GetPalette(0, 4); // Get palettes + CpsObjGet(); // Get objects + + for (i = 0; i < 3; i++) { + nNext = ((i + 1) * nDisplayEnd) / 3; // find out next cycle count to run to + + while (nNext > nIrqCycles && nInterrupt < MAX_RASTER) { + SekRun(nIrqCycles - SekTotalCycles()); + DoIRQ(); + } + SekRun(nNext - SekTotalCycles()); // run cpu + } + +// nCpsCyclesSegment[0] = (nCpsCycles * nVBlank) / 0x0106; +// nDone += SekRun(nCpsCyclesSegment[0] - nDone); + + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // VBlank + SekRun(nCpsCycles - SekTotalCycles()); + + if (pBurnDraw) { + CpsDraw(); + } + + nCpsCyclesExtra = SekTotalCycles() - nCpsCycles; + + QsndEndFrame(); + + SekClose(); + +// bprintf(PRINT_NORMAL, _T(" -\n")); + +#if 0 && defined FBA_DEBUG + if (nInterrupt) { + bprintf(PRINT_IMPORTANT, _T("Beam synchronized interrupt at line %2X.\r"), nRasterline[nInterrupt]); + } else { + bprintf(PRINT_NORMAL, _T("Beam synchronized interrupt disabled. \r")); + } + + extern INT32 counter; + if (counter) { + bprintf(PRINT_NORMAL, _T("\n\nSlices start at: ")); + for (i = 0; i < MAX_RASTER + 2; i++) { + bprintf(PRINT_NORMAL, _T("%2X "), nRasterline[i]); + } + bprintf(PRINT_NORMAL, _T("\n")); + for (i = 0; i < 0x80; i++) { + if (*((UINT16*)(CpsSaveReg[0] + i * 2)) != *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2))) { + bprintf(PRINT_NORMAL, _T("Register %2X: %4X -> %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[0] + i * 2)), *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2))); + } + } + bprintf(PRINT_NORMAL, _T("\n")); + for (i = 0; i < 0x010; i++) { + if (CpsSaveFrg[0][i] != CpsSaveFrg[nInterrupt][i]) { + bprintf(PRINT_NORMAL, _T("FRG %X: %02X -> %02X\n"), i, CpsSaveFrg[0][i], CpsSaveFrg[nInterrupt][i]); + } + } + bprintf(PRINT_NORMAL, _T("\n")); + if (((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]) != ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5])) { + bprintf(PRINT_NORMAL, _T("Layer-sprite priority: %04X -> %04X\n"), ((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]), ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5])); + } + + bprintf(PRINT_NORMAL, _T("\n")); + for (INT32 j = 0; j <= nInterrupt; j++) { + if (j) { + bprintf(PRINT_NORMAL, _T("IRQ : %i (triggered at line %3i)\n\n"), j, nRasterline[j]); + } else { + bprintf(PRINT_NORMAL, _T("Initial register status\n\n")); + } + + for (i = 0; i < 0x080; i+= 8) { + bprintf(PRINT_NORMAL, _T("%2X: %4X %4X %4X %4X %4X %4X %4X %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[j] + 0 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 2 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 4 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 6 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 8 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 10 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 12 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 14 + i * 2))); + } + + bprintf(PRINT_NORMAL, _T("\nFRG: ")); + for (i = 0; i < 0x010; i++) { + bprintf(PRINT_NORMAL, _T("%02X "), CpsSaveFrg[j][i]); + } + bprintf(PRINT_NORMAL, _T("\n\n")); + + } + + extern INT32 bRunPause; + bRunPause = 1; + counter = 0; + } +#endif + + return 0; +} + diff --git a/src/burn/drivers/capcom/cps_rw.cpp b/src/burn/drivers/capcom/cps_rw.cpp new file mode 100644 index 00000000..7d440e7b --- /dev/null +++ b/src/burn/drivers/capcom/cps_rw.cpp @@ -0,0 +1,589 @@ +#include "cps.h" +// CPS - Read/Write + +// Input bits +#define INP(nnn) UINT8 CpsInp##nnn[8]; +CPSINPSET +#undef INP + +// Bytes to return from ports +#define INP(nnn) UINT8 Inp##nnn; +CPSINPSET +#undef INP + +UINT16 CpsInp055 = 0; +UINT16 CpsInp05d = 0; +UINT16 CpsInpPaddle1 = 0; +UINT16 CpsInpPaddle2 = 0; +static INT32 ReadPaddle = 0; +INT32 CpsPaddle1Value = 0; +INT32 CpsPaddle2Value = 0; +INT32 CpsPaddle1 = 0; +INT32 CpsPaddle2 = 0; +static INT32 nDial055, nDial05d; + +INT32 PangEEP = 0; +INT32 Forgottn = 0; +INT32 Cps1QsHack = 0; +INT32 Kodh = 0; +INT32 Cawingb = 0; +INT32 Wofh = 0; +INT32 Sf2thndr = 0; +INT32 Pzloop2 = 0; +INT32 Ssf2tb = 0; +INT32 Dinopic = 0; +INT32 Dinohunt = 0; +INT32 Port6SoundWrite = 0; + +static INT32 nCalc[2] = {0, 0}; + +static const bool nCPSExtraNVRAM = false; +static INT32 n664001; + +#define INP(nnnn) UINT8 CpsInp##nnnn[8]; +CPSINPEX +#undef INP + +#define INP(nnnn) static UINT8 Inp##nnnn; +CPSINPEX +#undef INP + + +// Read input port 0x000-0x1ff +static UINT8 CpsReadPort(const UINT32 ia) +{ + UINT8 d = 0xFF; + +// bprintf(PRINT_NORMAL, _T("Read Port %x\n"), ia); + + if (ia == 0x000) { + d = (UINT8)~Inp000; + if (Pzloop2) { + if (ReadPaddle) { + d -= CpsPaddle2Value; + } else { + d = CpsPaddle2; + } + } + return d; + } + if (ia == 0x001) { + d = (UINT8)~Inp001; + if (Pzloop2) { + if (ReadPaddle) { + d -= CpsPaddle1Value; + } else { + d = CpsPaddle1; + } + } + return d; + } + if (ia == 0x010) { + d = (UINT8)~Inp010; + return d; + } + if (ia == 0x011) { + d = (UINT8)~Inp011; + return d; + } + if (ia == 0x012) { + d = (UINT8)~Inp012; + return d; + } + if (ia == 0x018) { + d = (UINT8)~Inp018; + return d; + } + if (ia == 0x019) { + d = (UINT8)~Inp019; + return d; + } + if (ia == 0x01A) { + d = (UINT8)~Cpi01A; + return d; + } + if (ia == 0x01C) { + d = (UINT8)~Cpi01C; + return d; + } + if (ia == 0x01E) { + d = (UINT8)~Cpi01E; + return d; + } + + if (Cps == 2) { + // Used on CPS2 only I think + if (ia == 0x020) { + d = (UINT8)~Inp020; + return d; + } + if (ia == 0x021) { + d = (UINT8)~Inp021; + d &= 0xFE; + d |= EEPROMRead(); + return d; + } + + // CPS2 Volume control + if (ia == 0x030) { + if (Ssf2tb) { + d = 0x20; + } else { + d = 0xe0; + } + return d; + } + if (ia == 0x031) { + d = 0x21; + return d; + } + + if (ia >= 0x0100 && ia < 0x0200) { + static INT32 nRasterLine; + +// bprintf(PRINT_NORMAL, _T(" - port 0x%02X (%3i)\n"), ia & 255, SekCurrentScanline()); + + // The linecounters seem to return the line at which the last IRQ triggered by this counter is scheduled minus the current line + if ((ia & 0x0FE) == 0x50) { + if ((ia & 1) == 0) { + nRasterLine = nIrqLine50 - SekCurrentScanline(); + return nRasterLine >> 8; + } else { + return nRasterLine & 0xFF; + } + } + if ((ia & 0x0FE) == 0x52) { + if ((ia & 1) == 0) { + nRasterLine = nIrqLine52 - SekCurrentScanline(); + return nRasterLine >> 8; + } else { + return nRasterLine & 0xFF; + } + } + + } + } else { + // Board ID + if (ia == 0x100 + CpsBID[0]) { + d = (UINT8)CpsBID[1]; + return d; + } + if (ia == 0x100 + (CpsBID[0] + 1)) { + d = (UINT8)CpsBID[2]; + return d; + } + + if (Sf2thndr) { + // this reads the B-ID from here on startup as well as the normal location in-game + if (ia == 0x1c8) { + d = (UINT8)CpsBID[1]; + return d; + } + + if (ia == 0x1c9) { + d = (UINT8)CpsBID[2]; + return d; + } + } + + // CPS1 EEPROM read + if (ia == 0xC007) { + return EEPROMRead(); + } + + // Pang3 EEPROM + if (PangEEP == 1) { + if (ia == 0x17B) { + return EEPROMRead(); + } + } + + // Extra Input ports (move from game-to-game) + if (ia == 0x006) { + d = (UINT8)~Inp006; + return d; + } + if (ia == 0x007) { + d = (UINT8)~Inp007; + return d; + } + if (ia == 0x008) { + d = (UINT8)~Inp008; + return d; + } + if (ia == 0x029) { + d = (UINT8)~Inp029; + return d; + } + if (ia == 0x176) { + d = (UINT8)~Inp176; + return d; + } + if (ia == 0x177) { + d = (UINT8)~Inp177; + return d; + } + if (ia == 0x179) { + d = (UINT8)~Inp179; + return d; + } + if (ia == 0x186) { + d = (UINT8)~Inp186; + return d; + } + if (ia == 0x1fd) { + d = (UINT8)~Inp1fd; + return d; + } + if (ia == 0xC000) { + d = (UINT8)~Inpc000; + return d; + } + if (ia == 0xC001) { + d = (UINT8)~Inpc001; + return d; + } + if (ia == 0xC002) { + d = (UINT8)~Inpc002; + return d; + } + if (ia == 0xC003) { + d = (UINT8)~Inpc003; + return d; + } + + // Forgotten Worlds Dial + if (Forgottn) { + if (ia == 0x053) { + return (nDial055 >> 8) & 0xFF; + } + if (ia == 0x055) { + return (nDial055 >> 16) & 0xFF; + } + if (ia == 0x05B) { + return (nDial05d >> 8) & 0xFF; + } + if (ia == 0x05D) { + return (nDial05d >> 16) & 0xFF; + } + } + } + + return d; +} + +// Write output port 0x000-0x1ff +static void CpsWritePort(const UINT32 ia, UINT8 d) +{ + if ((Cps & 1) && Cps1Qs == 0) { + // CPS1 sound code + if (ia == 0x181 || (Port6SoundWrite && (ia == 0x006 || ia == 0x007))) { + PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles); + + PsndCode = d; + return; + } + + // CPS1 sound fade + if (ia == 0x189) { + PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles); + + PsndFade = d; + return; + } + + if (ia == 0x041) { + nDial055 = 0; + } + if (ia == 0x049) { + nDial05d = 0; + } + } + + if (Cps == 1 && Cps1QsHack == 1) { + if (ia == 0x181) { + // Pass the Sound Code to the Q-Sound Shared Ram + CpsZRamC0[0x001] = d; + } + } + + // CPS registers + if (ia >= 0x100 && ia < 0x200) { + //Pang3 EEPROM + if (PangEEP == 1 && ia == 0x17B) { + EEPROMWrite(d & 0x40, d & 0x80, d & 0x01); + return; + } + CpsReg[(ia ^ 1) & 0xFF] = d; + return; + } + + if (Cps == 2) { + if (ia == 0x40) { + EEPROMWrite(d & 0x20, d& 0x40, d & 0x10); + return; + } + + // CPS2 object bank select + if ((ia & 0x1FF) == 0x0E1) { +// bprintf(PRINT_NORMAL, _T(" - %2i (%3i)\n"), d & 1, SekCurrentScanline()); +// CpsObjGet(); + CpsMapObjectBanks(d & 1); + return; + } + + if (ia == 0x41 && Pzloop2) { + ReadPaddle = d & 0x02; + } + } + + if (Cps1Qs == 1) { + //CPS1 EEPROM write + if (ia == 0xc007) { + EEPROMWrite(d & 0x40, d & 0x80, d & 0x01); + return; + } + } +} + +UINT8 __fastcall CpsReadByte(UINT32 a) +{ + // Input ports mirrored between 0x800000 and 0x807fff + if ((a & 0xFF8000) == 0x800000) { + return CpsReadPort(a & 0x1FF); + } + + if (Cps == 2) { + if ((a & 0xFF8000) == 0x660000) { + if (a == 0x664001) { + return n664001; + } + } + + return 0x00; + } + + if (a >= 0xF1C000 && a <= 0xF1C007) { + return CpsReadPort(a & 0xC00F); + } + + if (Dinohunt && a == 0xfc0001) return (UINT8)~Inpc001; + +// bprintf(PRINT_NORMAL, _T("Read Byte %x\n"), a); + + return 0x00; +} + +void __fastcall CpsWriteByte(UINT32 a,UINT8 d) +{ + // Output ports mirrored between 0x800000 and 0x807fff + if ((a & 0xFF8000) == 0x800000) { + CpsWritePort(a & 0x1FF, d); + return; + } + + if (Cps == 2) { + // 0x400000 registers + if ((a & 0xFFFFF0) == 0x400000) { + CpsFrg[a & 0x0F] = d; + return; + } + if ((a & 0xFF8000) == 0x660000) { + if (a == 0x664001) { + // bit 1 toggled on/off each frame + n664001 = d; + } + + return; + } + + return; + } + + if (Cps1Qs == 1) { + // CPS1 EEPROM + if (a == 0xf1c007) { + CpsWritePort(a & 0xC00F, d); + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Write Byte %x, %x\n"), a, d); +} + +UINT16 __fastcall CpsReadWord(UINT32 a) +{ + if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[3]) { + return (UINT16)((nCalc[0] * nCalc[1]) >> 16); + } + // ports mirrored between 0x800000 and 0x807fff + if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[2]) { + return (UINT16)((nCalc[0] * nCalc[1])); + } + +// bprintf(PRINT_NORMAL, _T("Read Word %x\n"), a); + + SEK_DEF_READ_WORD(0, a); +} + +void __fastcall CpsWriteWord(UINT32 a, UINT16 d) +{ + // ports mirrored between 0x800000 and 0x807fff + if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[0]) + nCalc[0] = d; + if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[1]) + nCalc[1] = d; + + if (a == 0x804040) { + if ((d & 0x0008) == 0) { + ZetReset(); + } + } + + if (Dinopic && a == 0x800222) { + CpsReg[6] = d & 0xff; + CpsReg[7] = d >> 8; + return; + } + +// bprintf(PRINT_NORMAL, _T("Write Word %x, %x\n"), a, d); + + SEK_DEF_WRITE_WORD(0, a, d); +} + +// Reset all inputs to zero +static INT32 InpBlank() +{ +#define INP(nnn) Inp##nnn = 0; memset(CpsInp##nnn, 0, sizeof(CpsInp##nnn)); + CPSINPSET +#undef INP + +#define INP(nnnn) Inp##nnnn = 0; memset(CpsInp##nnnn, 0, sizeof(CpsInp##nnnn)); + CPSINPEX +#undef INP + + CpsInp055 = CpsInp05d = 0; + + return 0; +} + +INT32 CpsRwInit() +{ + InpBlank(); + return 0; +} + +INT32 CpsRwExit() +{ + InpBlank(); + return 0; +} + +inline static void StopOpposite(UINT8* pInput) +{ + if ((*pInput & 0x03) == 0x03) { + *pInput &= ~0x03; + } + if ((*pInput & 0x0C) == 0x0C) { + *pInput &= ~0x0C; + } +} + +INT32 CpsRwGetInp() +{ + // Compile separate buttons into Inpxxx +#define INP(nnn) \ + { INT32 i = 0; Inp##nnn = 0; \ + for (i = 0; i < 8; i++) { Inp##nnn |= (CpsInp##nnn[i] & 1) << i; } } + CPSINPSET +#undef INP + + +#define INP(nnnn) \ + { INT32 i = 0; Inp##nnnn = 0; \ + for (i = 0; i < 8; i++) { Inp##nnnn |= (CpsInp##nnnn[i] & 1) << i; } } + CPSINPEX +#undef INP + + if (Forgottn) { + // Handle analog controls + nDial055 += (INT32)((INT16)CpsInp055); + nDial05d += (INT32)((INT16)CpsInp05d); + } + + if (Pzloop2) { + if (ReadPaddle) { + CpsPaddle1Value = 0; + CpsPaddle2Value = 0; + if (CpsInpPaddle1) { + if (CpsInpPaddle1 > 0x8000) { + CpsPaddle1Value = 2; + } + + if (CpsInpPaddle1 < 0x7fff) { + CpsPaddle1Value = 1; + } + } + + if (CpsInpPaddle2) { + if (CpsInpPaddle2 > 0x8000) { + CpsPaddle2Value = 2; + } + + if (CpsInpPaddle2 < 0x7fff) { + CpsPaddle2Value = 1; + } + } + } + + CpsPaddle1 += (CpsInpPaddle1 >> 8) & 0xff; + CpsPaddle2 += (CpsInpPaddle2 >> 8) & 0xff; + } + + StopOpposite(&Inp000); + StopOpposite(&Inp001); + + // Ghouls uses a 4-way stick + if (Ghouls) { + static UINT8 nPrevInp000, nPrevInp001; + + if ((Inp000 & 0x03) && (Inp000 & 0x0C)) { + Inp000 ^= (nPrevInp000 & 0x0F); + } else { + nPrevInp000 = Inp000; + } + + if ((Inp001 & 0x03) && (Inp001 & 0x0C)) { + Inp001 ^= (nPrevInp001 & 0x0F); + } else { + nPrevInp001 = Inp001; + } + } + + if (nMaxPlayers > 2) { + if (Cps == 2) { + StopOpposite(&Inp011); + if (nMaxPlayers == 4) { + StopOpposite(&Inp010); + } + } else { + StopOpposite(&Inp177); + if (nMaxPlayers == 4) { + StopOpposite(&Inp179); + } + if (Cps1Qs) { + StopOpposite(&Inpc001); + if (nMaxPlayers == 4) { + StopOpposite(&Inpc003); + } + } + } + } + + return 0; +} + +void CpsSoundCmd(UINT16 sound_code) { +// CpsWritePort(0x181, sound_code); + PsndCode = sound_code; +} diff --git a/src/burn/drivers/capcom/cps_scr.cpp b/src/burn/drivers/capcom/cps_scr.cpp new file mode 100644 index 00000000..02cfd003 --- /dev/null +++ b/src/burn/drivers/capcom/cps_scr.cpp @@ -0,0 +1,265 @@ +#include "cps.h" + +// CPS Scroll (Background Layers) + +// Base = 0x4000 long tile map +// sx=Scroll X value, sy=Scroll Y value, +INT32 Ghouls=0; +INT32 Mercs=0; +INT32 Sf2jc=0; +INT32 Ssf2t=0; +INT32 Qad=0; +INT32 Xmcota=0; + +INT32 Scroll1TileMask = 0; +INT32 Scroll2TileMask = 0; +INT32 Scroll3TileMask = 0; + +INT32 Cps1Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy) +{ + INT32 x,y; + INT32 ix,iy; + INT32 nKnowBlank=-1; // The tile we know is blank + + ix=(sx>>3)+1; iy=(sy>>3)+1; + sx&=7; sy&=7; sx=8-sx; sy=8-sy; + + for (y=-1; y<28; y++) + { + for (x=-1; x<48; x++) + { + INT32 t,a; + UINT16 *pst; + INT32 fx,fy,p; + fx=ix+x; fy=iy+y; // fx/fy= 0 to 63 + + // Find tile address + p=((fy&0x20)<<8) | ((fx&0x3f)<<7) | ((fy&0x1f)<<2); + p&=0x3fff; + pst=(UINT16 *)(Base + p); + + t=pst[0]; + + if (Scroll1TileMask) t &= Scroll1TileMask; + + t = GfxRomBankMapper(GFXTYPE_SCROLL1, t); + if (t == -1) continue; + + t<<=6; // Get real tile address + + t+=nCpsGfxScroll[1]; // add on offset to scroll tiles + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + + a=pst[1]; + + CpstSetPal(0x20 | (a&0x1f)); + + // Don't need to clip except around the border + if (x<0 || x>=48-1 || y<0 || y>=28-1) + nCpstType=CTT_8X8 | CTT_CARE; + else + nCpstType=CTT_8X8; + + nCpstX=sx+(x<<3); nCpstY=sy+(y<<3); + nCpstTile=t; nCpstFlip=(a>>5)&3; + + if (nBgHi) { + CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]); + } + + if(CpstOneDoX[nBgHi]()) nKnowBlank=t; + + } + } + + return 0; +} + +INT32 Cps2Scr1Draw(UINT8 *Base, INT32 sx, INT32 sy) +{ + INT32 x, y; + INT32 ix, iy; + INT32 nFirstY, nLastY; + INT32 nKnowBlank = -1; // The tile we know is blank + + ix = (sx >> 3) + 1; + sx &= 7; + sx = 8 - sx; + + iy = (sy >> 3) + 1; + sy &= 7; + + nLastY = (nEndline + sy) >> 3; + nFirstY = (nStartline + sy) >> 3; + + sy = 8 - sy; + + for (y = nFirstY - 1; y < nLastY; y++) { + INT32 nClipY = ((y << 3) < nStartline) | (((y << 3) + 8) >= nEndline); + for (x = -1; x < 48; x++) { + INT32 t, a; + UINT16 *pst; + INT32 fx, fy, p; + fx = ix + x; + fy = iy + y; // 0 <= fx/fy <= 63 + + // Find tile address + p = ((fy & 0x20) << 8) | ((fx & 0x3F) << 7) | ((fy & 0x1F) << 2); + p &= 0x3FFF; + pst = (UINT16 *)(Base + p); + + t = pst[0]; + t <<= 6; // Get real tile address + + t += nCpsGfxScroll[1]; // add on offset to scroll tiles + + if (t != nKnowBlank) { // Draw tile + a = pst[1]; + + CpstSetPal(0x20 | (a & 0x1F)); + + nCpstX = sx + (x << 3); + nCpstY = sy + (y << 3); + nCpstTile = t; + nCpstFlip = (a >> 5) & 3; + + // Don't need to clip except around the border + if (x < 0 || x >= 48 - 1 || nClipY) { + nCpstType = CTT_8X8 | CTT_CARE; + } else { + nCpstType = CTT_8X8; + } + + if (CpstOneDoX[2]()) { + nKnowBlank = t; + } + } + } + } + return 0; +} + +INT32 Cps1Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy) +{ + INT32 x,y; + INT32 ix,iy; + INT32 nKnowBlank=-1; // The tile we know is blank + ix=(sx>>5)+1; iy=(sy>>5)+1; + sx&=31; sy&=31; sx=32-sx; sy=32-sy; + + for (y=-1; y<7; y++) + { + for (x=-1; x<12; x++) + { + INT32 t,a; + UINT16 *pst; + INT32 fx,fy,p; + fx=ix+x; fy=iy+y; // fx/fy= 0 to 63 + + // Find tile address + p=((fy&0x38)<<8) | ((fx&0x3f)<<5) | ((fy&0x07)<<2); + p&=0x3fff; + pst=(UINT16 *)(Base + p); + + t=pst[0]; + + if (Scroll3TileMask) t &= Scroll3TileMask; + + t = GfxRomBankMapper(GFXTYPE_SCROLL3, t); + if (t == -1) continue; + + t<<=9; // Get real tile address + t+=nCpsGfxScroll[3]; // add on offset to scroll tiles + + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + + a=pst[1]; + + CpstSetPal(0x60 | (a&0x1f)); + + // Don't need to clip except around the border + if (x<0 || x>=12-1 || y<0 || y>=7-1) + nCpstType=CTT_32X32 | CTT_CARE; + else + nCpstType=CTT_32X32; + + nCpstX=sx+(x<<5); nCpstY=sy+(y<<5); + nCpstTile=t; nCpstFlip=(a>>5)&3; + + if (nBgHi) { + CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]); + } + + if(CpstOneDoX[nBgHi]()) nKnowBlank=t; + } + } + + return 0; +} + +INT32 Cps2Scr3Draw(UINT8 *Base, INT32 sx, INT32 sy) +{ + INT32 x, y; + INT32 ix, iy; + INT32 nFirstY, nLastY; + INT32 nKnowBlank = -1; // The tile we know is blank + + ix = (sx >> 5) + 1; + sx &= 31; + sx = 32 - sx; + + iy = (sy >> 5) + 1; + sy &= 31; + + nLastY = (nEndline + sy) >> 5; + nFirstY = (nStartline + sy) >> 5; + + sy = 32 - sy; + + for (y = nFirstY - 1; y < nLastY; y++) { + INT32 nClipY = ((y << 5) < nStartline) | (((y << 5) + 32) >= nEndline); + for (x = -1; x < 12; x++) { + INT32 t, a; + UINT16 *pst; + INT32 fx, fy, p; + fx = ix + x; + fy = iy + y; // 0 <= fx/fy <= 63 + + // Find tile address + p = ((fy & 0x38) << 8) | ((fx & 0x3F) << 5) | ((fy & 0x07) << 2); + p &= 0x3FFF; + pst = (UINT16 *)(Base + p); + + t = pst[0]; + + if(Xmcota && t>=0x5800) t-=0x4000; + else if(Ssf2t && t<0x5600) t+=0x4000; + t <<= 9; // Get real tile address + t += nCpsGfxScroll[3]; // add on offset to scroll tiles + + if (t != nKnowBlank) { // Draw tile + a = pst[1]; + + CpstSetPal(0x60 | (a & 0x1F)); + + nCpstX = sx + (x << 5); + nCpstY = sy + (y << 5); + nCpstTile = t; + nCpstFlip = (a >> 5) & 3; + + // Don't need to clip except around the border + if (x < 0 || x >= 12 - 1 || nClipY) { + nCpstType = CTT_32X32 | CTT_CARE; + } else { + nCpstType = CTT_32X32; + } + + if (CpstOneDoX[2]()) { + nKnowBlank = t; + } + } + } + } + return 0; +} + diff --git a/src/burn/drivers/capcom/cpsr.cpp b/src/burn/drivers/capcom/cpsr.cpp new file mode 100644 index 00000000..c653cbc1 --- /dev/null +++ b/src/burn/drivers/capcom/cpsr.cpp @@ -0,0 +1,199 @@ +#include "cps.h" + +// CPS Scroll2 with Row scroll support + +UINT8 *CpsrBase=NULL; // Tile data base +INT32 nCpsrScrX=0,nCpsrScrY=0; // Basic scroll info +UINT16 *CpsrRows=NULL; // Row scroll table, 0x400 words long +int nCpsrRowStart=0; // Start of row scroll (can wrap?) +static INT32 nShiftY=0; +static INT32 EndLineInfo=0; + +struct CpsrLineInfo CpsrLineInfo[15]; + +static void GetRowsRange(INT32 *pnStart,INT32 *pnWidth,INT32 nRowFrom,INT32 nRowTo) +{ + INT32 i,nStart,nWidth; + + // Get the range of scroll values within nRowCount rows + // Start with zero range + nStart=CpsrRows[nRowFrom&0x3ff]; nStart&=0x3ff; nWidth=0; + for (i=nRowFrom;i=0) + { + // On the right + if (nDiff>=nWidth) nWidth=nDiff; // expand width to cover it + } + else + { + // On the left + nStart+=nDiff; nStart&=0x3ff; + nWidth-=nDiff; // expand width to cover it + } + } + + if (nWidth>0x400) nWidth=0x400; + + *pnStart=nStart; + *pnWidth=nWidth; +} + + +static INT32 PrepareRows() +{ + INT32 y; INT32 r; + struct CpsrLineInfo *pli; + // Calculate the amount of pixels to shift each + // row of the tile lines, assuming we draw tile x at + // (x-pli->nTileStart)<<4 - i.e. 0, 16, ... + + r=nShiftY-16; + for (y = -1, pli = CpsrLineInfo; y < EndLineInfo; y++, pli++) + { + // Maximum row scroll left and right on this line + INT32 nMaxLeft=0,nMaxRight=0; + INT32 ty; INT16 *pr; + + if (CpsrRows==NULL) + { + // No row shift - all the same + INT32 v; + v =(pli->nTileStart<<4)-nCpsrScrX; + nMaxLeft=v; nMaxRight=v; + for (ty=0,pr=pli->Rows; ty<16; ty++,pr++) + { + *pr=(INT16)v; + } + } + else + { + for (ty=0,pr=pli->Rows; ty<16; ty++,pr++,r++) + { + // Get the row offset, if it's in range + if (r>=0 && rnTileStart<<4)-nCpsrScrX; + v-=CpsrRows[(nCpsrRowStart+r)&0x3ff]; + // clip to 10-bit signed + v+=0x200; v&=0x3ff; v-=0x200; + *pr=(INT16)v; + if (vnMaxRight) nMaxRight=v; + } + else + { + *pr=0; + } + } + } + + pli->nMaxLeft =nMaxLeft; + pli->nMaxRight=nMaxRight; + } + + return 0; +} + +// Prepare to draw Scroll 2 with rows, by seeing how much +// row scroll each tile line uses (pli->nStart/nWidth), +// and finding which tiles are visible onscreen (pli->nTileStart/End). + +INT32 Cps1rPrepare() +{ + INT32 y; struct CpsrLineInfo *pli; + if (CpsrBase==NULL) return 1; + + nEndline = 224; + EndLineInfo = 14; + nShiftY=16-(nCpsrScrY&15); + + for (y=-1,pli=CpsrLineInfo; y224) nRowTo=224; + + // Shift by row table start offset + nRowFrom+=nCpsrRowStart; + nRowTo +=nCpsrRowStart; + + // Find out what range of scroll values there are for this line + GetRowsRange(&nStart,&nWidth,nRowFrom,nRowTo); + } + + nStart+=nCpsrScrX; + nStart&=0x3ff; + + // Save info in CpsrLineInfo table + pli->nStart=nStart; + pli->nWidth=nWidth; + // Find range of tiles to draw to see whole width: + pli->nTileStart=nStart>>4; + pli->nTileEnd=(nStart+nWidth+0x18f)>>4; + } + + PrepareRows(); + return 0; +} + +INT32 Cps2rPrepare() +{ + INT32 y; + struct CpsrLineInfo *pli; + if (CpsrBase==NULL) return 1; + + EndLineInfo = ((nEndline + 15) >> 4); + + nShiftY=16-(nCpsrScrY&15); + for (y = -1, pli = CpsrLineInfo; y < EndLineInfo; y++, pli++) + { + INT32 nStart=0,nWidth=0; + + if (CpsrRows!=NULL) + { + INT32 nRowFrom,nRowTo; + // Find out which rows we need to check + nRowFrom=(y<<4)+nShiftY; + nRowTo=nRowFrom+16; + if (nRowFrom < 0) nRowFrom = 0; + if (nRowTo > nEndline) nRowTo = nEndline; + + // Shift by row table start offset + nRowFrom+=nCpsrRowStart; + nRowTo +=nCpsrRowStart; + + // Find out what range of scroll values there are for this line + GetRowsRange(&nStart,&nWidth,nRowFrom,nRowTo); + } + + nStart+=nCpsrScrX; + nStart&=0x3ff; + + // Save info in CpsrLineInfo table + pli->nStart=nStart; + pli->nWidth=nWidth; + // Find range of tiles to draw to see whole width: + pli->nTileStart=nStart>>4; + pli->nTileEnd=(nStart+nWidth+0x18f)>>4; + } + + PrepareRows(); + return 0; +} + diff --git a/src/burn/drivers/capcom/cpsrd.cpp b/src/burn/drivers/capcom/cpsrd.cpp new file mode 100644 index 00000000..63faeec2 --- /dev/null +++ b/src/burn/drivers/capcom/cpsrd.cpp @@ -0,0 +1,235 @@ +#include "cps.h" + +// CPS Scroll2 with Row scroll - Draw +static INT32 nKnowBlank=-1; // The tile we know is blank +static INT32 nFirstY, nLastY; +static INT32 bVCare; + +inline static UINT16 *FindTile(INT32 fx,INT32 fy) +{ + INT32 p; UINT16 *pst; + // Find tile address + p=((fy&0x30)<<8) | ((fx&0x3f)<<6) | ((fy&0x0f)<<2); + pst=(UINT16 *)(CpsrBase + p); + return pst; +} + +// Draw a tile line without Row Shift +static void Cps1TileLine(INT32 y,INT32 sx) +{ + INT32 x,ix,iy,sy; + + bVCare=0; + if (y<0 || y>=14-1) bVCare=1; // Take care on the edges + + ix=(sx>>4)+1; sx&=15; sx=16-sx; + sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1; + nCpstY=sy+(y<<4); + + for (x=-1; x<24; x++) + { + UINT16 *pst; INT32 t,a; + // Don't need to clip except around the border + if (bVCare || x<0 || x>=24-1) nCpstType=CTT_16X16 | CTT_CARE; + else nCpstType=CTT_16X16; + + pst=FindTile(ix+x,iy+y); + t=pst[0]; + + if (Scroll2TileMask) t &= Scroll2TileMask; + + t = GfxRomBankMapper(GFXTYPE_SCROLL2, t); + if (t == -1) continue; + + t<<=7; // Get real tile address + t+=nCpsGfxScroll[2]; // add on offset to scroll tile + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + + a=pst[1]; + + CpstSetPal(0x40 | (a&0x1f)); + nCpstX=sx+(x<<4); nCpstTile=t; nCpstFlip=(a>>5)&3; + + if(nBgHi) CpstPmsk=*(UINT16 *)(CpsSaveReg[0] + MaskAddr[(a&0x180)>>7]); + if(CpstOneDoX[nBgHi]()) nKnowBlank=t; + } +} + +static void Cps2TileLine(INT32 y,INT32 sx) +{ + INT32 x,ix,iy,sy; + + ix=(sx>>4)+1; sx&=15; sx=16-sx; + sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1; + nCpstY=sy+(y<<4); + + for (x=-1; x<24; x++) + { + UINT16 *pst; INT32 t,a; + // Don't need to clip except around the border + if (bVCare || x<0 || x>=24-1) nCpstType=CTT_16X16 | CTT_CARE; + else nCpstType=CTT_16X16; + + pst=FindTile(ix+x,iy+y); + t=pst[0]; + t<<=7; // Get real tile address + t+=nCpsGfxScroll[2]; // add on offset to scroll tiles + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + a=pst[1]; + + CpstSetPal(0x40 | (a&0x1f)); + nCpstX=sx+(x<<4); nCpstTile=t; nCpstFlip=(a>>5)&3; + if(CpstOneDoX[2]()) nKnowBlank=t; + } +} + +// Draw a tile line with Row Shift +static void Cps1TileLineRows(INT32 y,struct CpsrLineInfo *pli) +{ + INT32 sy,iy,x; + INT32 nTileCount; + INT32 nLimLeft,nLimRight; + + bVCare=0; + if (y<0 || y>=14-1) bVCare=1; // Take care on the edges + + nTileCount=pli->nTileEnd-pli->nTileStart; + + sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1; + nCpstY=sy+(y<<4); + CpstRowShift=pli->Rows; + + // If these rowshift limits go off the edges, we should take + // care drawing the tile. + nLimLeft =pli->nMaxLeft; + nLimRight=pli->nMaxRight; + for (x=0; xnTileStart+x; + + // See if we have to clip vertically anyway + bCare=bVCare; + if (bCare==0) // If we don't... + { + // Check screen limits of this tile + if (nLimLeft < 0) bCare=1; // Will cross left egde + if (nLimRight> 384-16) bCare=1; // Will cross right edge + } + if (bCare) nCpstType=CTT_16X16 | CTT_ROWS | CTT_CARE; + else nCpstType=CTT_16X16 | CTT_ROWS; + + pst=FindTile(tx,iy+y); + t=pst[0]; + + if (Scroll2TileMask) t &= Scroll2TileMask; + + t = GfxRomBankMapper(GFXTYPE_SCROLL2, t); + if (t == -1) continue; + + t<<=7; // Get real tile address + t+=nCpsGfxScroll[2]; // add on offset to scroll tiles + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + + a=pst[1]; + + CpstSetPal(0x40 | (a&0x1f)); + + nCpstX=x<<4; nCpstTile=t; nCpstFlip=(a>>5)&3; + + if (nBgHi) { + CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]); + } + + if(CpstOneDoX[nBgHi]()) nKnowBlank=t; + } +} + +static void Cps2TileLineRows(INT32 y,struct CpsrLineInfo *pli) +{ + INT32 sy,iy,x; + INT32 nTileCount; + INT32 nLimLeft,nLimRight; + + nTileCount=pli->nTileEnd-pli->nTileStart; + + sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1; + nCpstY=sy+(y<<4); + CpstRowShift=pli->Rows; + + // If these rowshift limits go off the edges, we should take + // care drawing the tile. + nLimLeft =pli->nMaxLeft; + nLimRight=pli->nMaxRight; + for (x=0; xnTileStart+x; + + // See if we have to clip vertically anyway + bCare=bVCare; + if (bCare==0) // If we don't... + { + // Check screen limits of this tile + if (nLimLeft < 0) bCare=1; // Will cross left egde + if (nLimRight> 384-16) bCare=1; // Will cross right edge + } + if (bCare) nCpstType=CTT_16X16 | CTT_ROWS | CTT_CARE; + else nCpstType=CTT_16X16 | CTT_ROWS; + + pst=FindTile(tx,iy+y); + t=pst[0]; + t<<=7; // Get real tile address + t+=nCpsGfxScroll[2]; // add on offset to scroll tiles + + if (t==nKnowBlank) continue; // Don't draw: we know it's blank + a=pst[1]; + + CpstSetPal(0x40 | (a&0x1f)); + + nCpstX=x<<4; nCpstTile=t; nCpstFlip=(a>>5)&3; + if(CpstOneDoX[2]()) nKnowBlank=t; + } +} + +INT32 Cps1rRender() +{ + INT32 y; struct CpsrLineInfo *pli; + if (CpsrBase==NULL) return 1; + + nKnowBlank=-1; // We don't know which tile is blank yet + + for (y=-1,pli=CpsrLineInfo; y<14; y++,pli++) + { + if (pli->nWidth==0) + Cps1TileLine(y,pli->nStart); // no rowscroll needed + else + Cps1TileLineRows(y,pli); // row scroll + } + return 0; +} + +INT32 Cps2rRender() +{ + INT32 y; + struct CpsrLineInfo *pli; + if (CpsrBase==NULL) return 1; + + nKnowBlank = -1; // We don't know which tile is blank yet + + nLastY = (nEndline + (nCpsrScrY & 15)) >> 4; + nFirstY = (nStartline + (nCpsrScrY & 15)) >> 4; + for (y = nFirstY - 1, pli = CpsrLineInfo + nFirstY; y < nLastY; y++, pli++) { + + bVCare = ((y << 4) < nStartline) | (((y << 4) + 16) >= nEndline); + + if (pli->nWidth==0) { + Cps2TileLine(y,pli->nStart); // no rowscroll needed + } else { + Cps2TileLineRows(y,pli); // row scroll + } + } + return 0; +} diff --git a/src/burn/drivers/capcom/cpst.cpp b/src/burn/drivers/capcom/cpst.cpp new file mode 100644 index 00000000..94b595fc --- /dev/null +++ b/src/burn/drivers/capcom/cpst.cpp @@ -0,0 +1,192 @@ +#include "cps.h" + +// CPS Tiles +UINT32 *CpstPal=NULL; + +// Arguments for the tile draw function +UINT32 nCpstType = 0; +INT32 nCpstX = 0, nCpstY = 0; +UINT32 nCpstTile = 0; +INT32 nCpstFlip = 0; +INT16 *CpstRowShift = NULL; +UINT32 CpstPmsk = 0; // Pixel mask + +INT32 nBgHi = 0; +UINT16 ZValue = 1; +UINT16* ZBuf = NULL; +UINT16* pZVal = NULL; + +static INT32 CpstOne(); +static INT32 Cps2tOne(); +static INT32 CpstOneBgHi(); +static INT32 CpstOneObjZ(); +CpstOneDoFn CpstOneDoX[3] = { CpstOne, CpstOneBgHi, Cps2tOne}; +CpstOneDoFn CpstOneObjDoX[2] = { CpstOne, CpstOneObjZ}; + +static INT32 CpstOne() +{ + INT32 nFun; INT32 nSize; + nSize=(nCpstType&24)+8; + + if (nCpstType&CTT_CARE) + { + if ((nCpstType&CTT_ROWS)==0) + { + // Return if not visible at all + if (nCpstX <= -nSize) return 0; + if (nCpstX >= 384) return 0; + if (nCpstY <= -nSize) return 0; + if (nCpstY >= 224) return 0; + } + nCtvRollX=0x4000017f + nCpstX * 0x7fff; + nCtvRollY=0x400000df + nCpstY * 0x7fff; + } + + // Clip to loaded graphics data (we have a gap of 0x200 at the end) + nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 1; + pCtvTile=CpsGfx+nCpstTile; + + // Find pLine (pointer to first pixel) + pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp; + + if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8; + + if (nCpstFlip&2) + { + // Flip vertically + if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; } + else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; } + else { nCtvTileAdd= -8; pCtvTile+= 7* 8; } + } + + nFun =nCpstType&0x1e; + nFun|=nCpstFlip&1; + return CtvDoX[nFun](); +} + +static INT32 CpstOneBgHi() +{ + INT32 nFun; INT32 nSize; + nSize=(nCpstType&24)+8; + + if (nCpstType&CTT_CARE) + { + if ((nCpstType&CTT_ROWS)==0) + { + // Return if not visible at all + if (nCpstX<=-nSize) return 0; + if (nCpstX>=384) return 0; + if (nCpstY<=-nSize) return 0; + if (nCpstY>=224) return 0; + } + nCtvRollX=0x4000017f + nCpstX * 0x7fff; + nCtvRollY=0x400000df + nCpstY * 0x7fff; + } + + // Clip to loaded graphics data (we have a gap of 0x200 at the end) + nCpstTile&=nCpsGfxMask; + if (nCpstTile>=nCpsGfxLen) return 1; + pCtvTile=CpsGfx+nCpstTile; + + // Find pLine (pointer to first pixel) + pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp; + + if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8; + + if (nCpstFlip&2) + { + // Flip vertically + if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; } + else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; } + else { nCtvTileAdd= -8; pCtvTile+= 7* 8; } + } + + nFun =nCpstType&0x1e; + nFun|=nCpstFlip&1; + return CtvDoXB[nFun](); +} + +static INT32 Cps2tOne() +{ + INT32 nFun; INT32 nSize; + nSize=(nCpstType&24)+8; + + if (nCpstType&CTT_CARE) + { + if ((nCpstType&CTT_ROWS)==0) + { + // Return if not visible at all + if (nCpstX <= -nSize) return 0; + if (nCpstX >= 384) return 0; + if (nCpstY <= -nStartline - nSize) return 0; + if (nCpstY >= nEndline) return 0; + } + nCtvRollX=0x4000017f + nCpstX * 0x7fff; + nCtvRollY=0x40000000 + nEndline - nStartline - 1 + (nCpstY - nStartline) * 0x7fff; + } + + // Clip to loaded graphics data (we have a gap of 0x200 at the end) + nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 0; + pCtvTile=CpsGfx+nCpstTile; + + // Find pLine (pointer to first pixel) + pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp; + + if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8; + + if (nCpstFlip&2) + { + // Flip vertically + if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; } + else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; } + else { nCtvTileAdd= -8; pCtvTile+= 7* 8; } + } + + nFun =nCpstType&0x1e; + nFun|=nCpstFlip&1; + return CtvDoX[nFun](); +} + +static INT32 CpstOneObjZ() +{ + INT32 nFun; INT32 nSize; + nSize=(nCpstType&24)+8; + + + if (nCpstType&CTT_CARE) + { + if ((nCpstType&CTT_ROWS)==0) + { + // Return if not visible at all + if (nCpstX <= -nSize) return 0; + if (nCpstX >= 384) return 0; + if (nCpstY <= -nSize) return 0; + if (nCpstY >= 224) return 0; + } + nCtvRollX=0x4000017f + nCpstX * 0x7fff; + nCtvRollY=0x400000df + nCpstY * 0x7fff; + } + + + // Clip to loaded graphics data (we have a gap of 0x200 at the end) + nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 1; + pCtvTile=CpsGfx+nCpstTile; + + // Find pLine (pointer to first pixel) + pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp; + pZVal=ZBuf + nCpstY*384 + nCpstX; + + if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8; + + if (nCpstFlip&2) + { + // Flip vertically + if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; } + else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; } + else { nCtvTileAdd= -8; pCtvTile+= 7* 8; } + } + + nFun =nCpstType&0x1e; + nFun|=nCpstFlip&1; + return CtvDoXM[nFun](); +} diff --git a/src/burn/drivers/capcom/ctv.cpp b/src/burn/drivers/capcom/ctv.cpp new file mode 100644 index 00000000..f9de0418 --- /dev/null +++ b/src/burn/drivers/capcom/ctv.cpp @@ -0,0 +1,41 @@ +#include "cps.h" + +// CPS Tile Variants +// horizontal/vertical clip rolls +UINT32 nCtvRollX=0,nCtvRollY=0; +// Add 0x7fff after each pixel/line +// If nRollX/Y&0x20004000 both == 0, you can draw the pixel + +UINT8 *pCtvTile=NULL; // Pointer to tile data +INT32 nCtvTileAdd=0; // Amount to add after each tile line +UINT8 *pCtvLine=NULL; // Pointer to output bitmap + +// Include all tile variants: +#include "ctv.h" + +static INT32 nLastBpp=0; +INT32 CtvReady() +{ + // Set up the CtvDoX functions to point to the correct bpp functions. + // Must be called before calling CpstOne + if (nBurnBpp!=nLastBpp) + { + if (nBurnBpp==2) { + memcpy(CtvDoX,CtvDo2,sizeof(CtvDoX)); + memcpy(CtvDoXM,CtvDo2m,sizeof(CtvDoXM)); + memcpy(CtvDoXB,CtvDo2b,sizeof(CtvDoXB)); + } + else if (nBurnBpp==3) { + memcpy(CtvDoX,CtvDo3,sizeof(CtvDoX)); + memcpy(CtvDoXM,CtvDo3m,sizeof(CtvDoXM)); + memcpy(CtvDoXB,CtvDo3b,sizeof(CtvDoXB)); + } + else if (nBurnBpp==4) { + memcpy(CtvDoX,CtvDo4,sizeof(CtvDoX)); + memcpy(CtvDoXM,CtvDo4m,sizeof(CtvDoXM)); + memcpy(CtvDoXB,CtvDo4b,sizeof(CtvDoXB)); + } + } + nLastBpp=nBurnBpp; + return 0; +} diff --git a/src/burn/drivers/capcom/ctv_do.h b/src/burn/drivers/capcom/ctv_do.h new file mode 100644 index 00000000..4c349587 --- /dev/null +++ b/src/burn/drivers/capcom/ctv_do.h @@ -0,0 +1,192 @@ +// CPS Tiles (header) + +// Draw a nxn tile +// pCtvLine, pTile, nTileAdd are defined +// CU_FLIPX is 1 to flip the tile horizontally +// CU_CARE is 1 to clip output based on nCtvRollX/Y +// CU_ROWS is 1 to shift output based on CpstRowShift +// CU_SIZE is 8, 16 or 32 +// CU_BPP is 1 2 3 4 bytes per pixel +// CU_MASK CPS1 BgHi CPS2 Sprite Masking + +#ifndef CU_FLIPX + #error "CU_FLIPX wasn\'t defined" +#endif + +#ifndef CU_CARE + #error "CU_CARE wasn\'t defined" +#endif + +#ifndef CU_ROWS + #error "CU_ROWS wasn\'t defined" +#endif + +#ifndef CU_SIZE + #error "CU_SIZE wasn\'t defined" +#endif + +#ifndef CU_BPP + #error "CU_BPP wasn\'t defined" +#endif + +#ifndef CU_MASK + #error "CU_MASK wasn\'t defined" +#endif + +{ + INT32 y; + UINT32 *ctp; + UINT32 nBlank = 0; + + UINT32 b; // Eight bit-packed pixels (msb) AAAABBBB CCCCDDDD EEEEFFFF GGGGHHHH (lsb) + UINT32 c; // 32-bit colour value + UINT8 *pPix; // Pointer to output bitmap + +#if CU_ROWS == 1 + INT16 *Rows = CpstRowShift; +#endif + + ctp = CpstPal; + +for (y = 0; y < CU_SIZE; y++, pCtvLine += nBurnPitch, pCtvTile += nCtvTileAdd + +#if CU_ROWS==1 + ,Rows++ +#endif + +#if CU_MASK==1 + ,pZVal += 384 +#endif + +) +{ +#if CU_CARE==1 + UINT32 rx = nCtvRollX; // Copy of nCtvRollX +#endif + +#if CU_MASK==1 + UINT16 *pPixZ; +#endif + +#if CU_CARE==1 + if (nCtvRollY & 0x20004000) { nCtvRollY += 0x7fff; continue; } else nCtvRollY += 0x7fff; // okay to plot line +#endif + + // Point to the line to draw + pPix = pCtvLine; +#if CU_MASK==1 + pPixZ = pZVal; +#endif + +#if CU_ROWS==1 + #if CU_MASK==1 + pPixZ += Rows[0]; + #endif + pPix += Rows[0] * nBurnBpp; + #if CU_CARE==1 + rx += Rows[0] * 0x7fff; + #endif +#endif + +// Make macros for plotting c and advancing pPix by one pixel +#if CU_BPP==2 + #if CU_MASK==1 + #define PLOT { if(*pPixZ < ZValue) { *((UINT16 *)pPix)=(UINT16)c; *pPixZ=ZValue; } } + #define ADV { pPix+=2; pPixZ++; } + #else + #define PLOT { *((UINT16 *)pPix)=(UINT16)c; } + #define ADV pPix+=2 + #endif +#elif CU_BPP==3 + #if CU_MASK==1 + #define PLOT { if(*pPixZ < ZValue) { pPix[0]=(UINT8)c; pPix[1]=(UINT8)(c>>8); pPix[2]=(UINT8)(c>>16); } } + #define ADV { pPix+=3; pPixZ++; } + #else + #define PLOT { pPix[0]=(UINT8)c; pPix[1]=(UINT8)(c>>8); pPix[2]=(UINT8)(c>>16); } + #define ADV pPix+=3 + #endif +#elif CU_BPP==4 + #if CU_MASK==1 + #define PLOT { if(*pPixZ < ZValue) { *((UINT32 *)pPix)=c; *pPixZ=ZValue; } } + #define ADV { pPix+=4; pPixZ++; } + #else + #define PLOT { *((UINT32 *)pPix)=c; } + #define ADV pPix+=4 + #endif +#else + #error Unsupported CU_BPP +#endif + +// Make macros for plotting the next pixel from 'b' (= 8 packed pixels) +// or skipping the pixel. +#if CU_FLIPX==0 + #define NEXTPIXEL ADV; b <<= 4; + #if CU_MASK==2 + #define DRAWPIXEL { c = (b >> 28); if (c && CpstPmsk & (1 << (c ^ 15))) { c = ctp[c]; PLOT } } + #else + #define DRAWPIXEL { if (b & 0xf0000000) { c = ctp[b >> 28]; PLOT } } + #endif +#else + #define NEXTPIXEL ADV; b >>= 4; + #if CU_MASK==2 + #define DRAWPIXEL { c = (b & 15); if (c && CpstPmsk & (1 << (c ^ 15))) { c = ctp[c]; PLOT } } + #else + #define DRAWPIXEL { if (b & 0x0000000f) { c = ctp[b & 15]; PLOT } } + #endif +#endif + +#define EIGHT(x) x x x x x x x x + +#if CU_CARE==1 + // If we need to clip left or right, check nCtvRollX before plotting + #define DO_PIX if ((rx & 0x20004000) == 0) DRAWPIXEL NEXTPIXEL rx += 0x7fff; +#else + // Always plot + #define DO_PIX DRAWPIXEL NEXTPIXEL +#endif + +#define DRAW_8 nBlank |= b; EIGHT(DO_PIX) + +#if CU_SIZE==8 + // 8x8 tiles + b=*((UINT32 *)(pCtvTile+0)); DRAW_8 +#elif CU_SIZE==16 + // 16x16 tiles + #if CU_FLIPX==0 + b=*((UINT32 *)(pCtvTile+0)); DRAW_8 + b=*((UINT32 *)(pCtvTile+4)); DRAW_8 + #else + b=*((UINT32 *)(pCtvTile+4)); DRAW_8 + b=*((UINT32 *)(pCtvTile+0)); DRAW_8 + #endif + +#elif CU_SIZE==32 + // 32x32 tiles + #if CU_FLIPX==0 + b=*((UINT32 *)(pCtvTile+ 0)); DRAW_8 + b=*((UINT32 *)(pCtvTile+ 4)); DRAW_8 + b=*((UINT32 *)(pCtvTile+ 8)); DRAW_8 + b=*((UINT32 *)(pCtvTile+12)); DRAW_8 + #else + b=*((UINT32 *)(pCtvTile+12)); DRAW_8 + b=*((UINT32 *)(pCtvTile+ 8)); DRAW_8 + b=*((UINT32 *)(pCtvTile+ 4)); DRAW_8 + b=*((UINT32 *)(pCtvTile+ 0)); DRAW_8 + #endif + +#else + #error Unsupported CU_SIZE +#endif + +#undef DRAW_8 +#undef DO_PIX +#undef EIGHT +#undef DRAWPIXEL +#undef NEXTPIXEL + +#undef ADV +#undef PLOT +} + + return nBlank == 0; +} diff --git a/src/burn/drivers/capcom/ctv_make.cpp b/src/burn/drivers/capcom/ctv_make.cpp new file mode 100644 index 00000000..91744a29 --- /dev/null +++ b/src/burn/drivers/capcom/ctv_make.cpp @@ -0,0 +1,125 @@ +#include + +// Create the ctv.h header file +// which includes all combinations of the cps tile drawing functions + +int main() +{ + int nCuMask=0; + int nCuBpp=0; + int nCuSize=0; + int nCuRows=0; + int nCuCare=0; + int nCuFlipX=0; + + for (nCuMask=0; nCuMask<=2; nCuMask++) + { + printf ("#define CU_MASK (%d)\n\n",nCuMask); + for (nCuBpp=2; nCuBpp<=4; nCuBpp++) + { + printf ("#define CU_BPP (%d)\n\n",nCuBpp); + for (nCuSize=8; nCuSize<=32; nCuSize<<=1) + { + printf ("#define CU_SIZE (%d)\n\n",nCuSize); + for (nCuRows=0; nCuRows<2; nCuRows++) + { + printf ("#define CU_ROWS (%d)\n\n",nCuRows); + for (nCuCare=0; nCuCare<2; nCuCare++) + { + printf ("#define CU_CARE (%d)\n",nCuCare); + for (nCuFlipX=0; nCuFlipX<2; nCuFlipX++) + { + printf ("#define CU_FLIPX (%d)\n",nCuFlipX); + + if ((nCuRows && (nCuSize != 16) || (nCuRows && nCuMask))) { + printf("// Invalid combination of capabilities.\n"); + } else { + printf ("static INT32 "); + printf ("CtvDo"); + printf ("%d",nCuBpp); + printf ("%.2d",nCuSize); + if (nCuRows) printf ("r"); else printf ("_"); + if (nCuCare) printf ("c"); else printf ("_"); + if (nCuFlipX) printf ("f"); else printf ("_"); + if (nCuMask==1) printf ("m()\n#include \"ctv_do.h\"\n"); + else if (nCuMask==2) printf ("b()\n#include \"ctv_do.h\"\n"); + else printf ("_()\n#include \"ctv_do.h\"\n"); + } + + + + printf ("#undef CU_FLIPX\n"); + } + printf ("#undef CU_CARE\n\n"); + } + printf ("#undef CU_ROWS\n\n"); + } + printf ("#undef CU_SIZE\n\n"); + } + printf ("#undef CU_BPP\n\n"); + } + printf ("#undef CU_MASK\n\n"); + } + + printf ("\n\n"); + + printf ("// Filler function\n"); + printf ("static INT32 CtvDo_______() { return 0; }\n\n\n\n"); + + for (nCuMask=0; nCuMask<=2; nCuMask++) + { + for (nCuBpp=2; nCuBpp<=4; nCuBpp++) + { + int i=0; + + if (nCuMask==1) + { + printf ("// Lookup table for %d bpp with Sprite Masking\n",nCuBpp); + printf ("static CtvDoFn CtvDo%dm[0x20]={\n",nCuBpp); + } + else if (nCuMask==2) + { + printf ("// Lookup table for %d bpp with BgHi\n",nCuBpp); + printf ("static CtvDoFn CtvDo%db[0x20]={\n",nCuBpp); + } + else + { + printf ("// Lookup table for %d bpp\n",nCuBpp); + printf ("static CtvDoFn CtvDo%d[0x20]={\n",nCuBpp); + } + + for (i=0;i<0x20;i++) + { + int s; + printf ("CtvDo"); + + s=(i&24)+8; + if (s!=8 && s!=16 && s!=32) { printf ("_______"); goto End; } + if ((i&4) && (s!=16)) { printf ("_______"); goto End; } + if ((i&4) && nCuMask) { printf ("_______"); goto End; } + printf ("%d",nCuBpp); + printf ("%.2d",s); + if (i&4) printf ("r"); else printf ("_"); + if (i&2) printf ("c"); else printf ("_"); + if (i&1) printf ("f"); else printf ("_"); + if (nCuMask==1) printf ("m"); + else if (nCuMask==2) printf ("b"); + else printf ("_"); + + End: + printf (","); + if (((i+1)&3)==0) printf("\n"); + } + printf ("};\n"); + } + } + + printf ("\n\n"); + printf ("// Current BPP:\n"); + printf ("CtvDoFn CtvDoX[0x20];\n"); + printf ("CtvDoFn CtvDoXM[0x20];\n"); + printf ("CtvDoFn CtvDoXB[0x20];\n"); + printf ("\n\n"); + + return 0; +} diff --git a/src/burn/drivers/capcom/d_cps1.cpp b/src/burn/drivers/capcom/d_cps1.cpp new file mode 100644 index 00000000..9de3267d --- /dev/null +++ b/src/burn/drivers/capcom/d_cps1.cpp @@ -0,0 +1,14083 @@ +#include "cps.h" + +#define CPS1_68K_PROGRAM_BYTESWAP 1 +#define CPS1_68K_PROGRAM_NO_BYTESWAP 2 +#define CPS1_Z80_PROGRAM 3 +#define CPS1_TILES 4 +#define CPS1_OKIM6295_SAMPLES 5 +#define CPS1_QSOUND_SAMPLES 6 +#define CPS1_PIC 7 + +//#define INCLUDE_DUPLICATES 1 +//#define INCLUDE_CPS1_PHOENIX 1 + +typedef INT32 (*Cps1Callback)(INT32); +static Cps1Callback Cps1CallbackFunction; + +// Input Definitions + +static struct BurnInputInfo NTFOInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(NTFO) + +static struct BurnInputInfo ThreeWondersInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Button 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(ThreeWonders) + +static struct BurnInputInfo CaptcommInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"P4 Coin" , BIT_DIGITAL , CpsInp179+6, "p4 coin" }, + {"P4 Start" , BIT_DIGITAL , CpsInp179+7, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , CpsInp179+3, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , CpsInp179+2, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , CpsInp179+1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , CpsInp179+0, "p4 right" }, + {"P4 Attack" , BIT_DIGITAL , CpsInp179+4, "p4 fire 1" }, + {"P4 Jump" , BIT_DIGITAL , CpsInp179+5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Captcomm) + +static struct BurnInputInfo CawingInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Cawing) + +static struct BurnInputInfo CawingbInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp008+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp008+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp008+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp008+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp008+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp008+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Cawingb) + +static struct BurnInputInfo Cworld2jInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Answer 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Answer 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Answer 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Answer 4" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Answer 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Answer 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Answer 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Answer 4" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Cworld2j) + +static struct BurnInputInfo DinoInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0 , "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4 , "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3 , "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2 , "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1 , "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0 , "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4 , "p1 fire 1"}, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5 , "p1 fire 2"}, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1 , "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5 , "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3 , "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2 , "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1 , "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0 , "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4 , "p2 fire 1"}, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5 , "p2 fire 2"}, + + {"P3 Coin" , BIT_DIGITAL , CpsInpc001+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInpc001+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInpc001+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInpc001+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInpc001+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInpc001+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInpc001+4, "p3 fire 1"}, + {"P3 Jump" , BIT_DIGITAL , CpsInpc001+5, "p3 fire 2"}, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6 , "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2 , "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Dino) + +static struct BurnInputInfo DinohInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0 , "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4 , "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3 , "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2 , "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1 , "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0 , "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4 , "p1 fire 1"}, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5 , "p1 fire 2"}, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+6 , "p1 fire 3"}, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1 , "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5 , "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3 , "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2 , "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1 , "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0 , "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4 , "p2 fire 1"}, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5 , "p2 fire 2"}, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+6 , "p2 fire 3"}, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6 , "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2 , "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Dinoh) + +static struct BurnInputInfo DynwarInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack Left" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Attack Right" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack Left" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Attack Right" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Dynwar) + +static struct BurnInputInfo FfightInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Ffight) + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo ForgottnInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL, CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL, CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL, CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL, CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL, CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL, CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL, CpsInp001+4, "p1 fire 1"}, + A("P1 Turn" , BIT_ANALOG_REL, &CpsInp055, "p1 z-axis"), + + {"P2 Coin" , BIT_DIGITAL, CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL, CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL, CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL, CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL, CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL, CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL, CpsInp000+4, "p2 fire 1"}, + A("P2 Turn" , BIT_ANALOG_REL, &CpsInp05d, "p2 z-axis"), + + {"Reset" , BIT_DIGITAL, &CpsReset, "reset" }, + {"Service" , BIT_DIGITAL, CpsInp018+2, "service" }, + + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +#undef A + +STDINPUTINFO(Forgottn) + +static struct BurnInputInfo GhoulsInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Fire" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Fire" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Ghouls) + +static struct BurnInputInfo KnightsInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Knights) + +static struct BurnInputInfo KodInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Kod) + +static struct BurnInputInfo KodhInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInpc000+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInpc000+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInpc000+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInpc000+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInpc000+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInpc000+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInpc000+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInpc000+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Kodh) + +static struct BurnInputInfo MegamanInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Fire" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Select" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Fire" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Select" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Megaman) + +static struct BurnInputInfo MercsInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Shot" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Special" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Mercs) + +static struct BurnInputInfo MswordInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Msword) + +static struct BurnInputInfo MtwinsInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Mtwins) + +static struct BurnInputInfo NemoInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Nemo) + +static struct BurnInputInfo Pang3InputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Shot 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Shot 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Pang3) + +static struct BurnInputInfo PnickjInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Turn 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Turn 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Turn 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Turn 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Pnickj) + +static struct BurnInputInfo PunisherInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Punisher) + +static struct BurnInputInfo PunisherbzInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Super" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Super" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, +}; + +STDINPUTINFO(Punisherbz) + +static struct BurnInputInfo QadInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Answer 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Answer 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Answer 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Answer 4" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Answer 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Answer 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Answer 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Answer 4" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Qad) + +static struct BurnInputInfo Qtono2jInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Answer 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Answer 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Answer 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Answer 4" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Answer 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Answer 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Answer 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Answer 4" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Qtono2j) + +static struct BurnInputInfo Sf2InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp177+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp177+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp177+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp177+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp177+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp177+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Sf2) + +static struct BurnInputInfo Sf2ueInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp1fd+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp1fd+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp1fd+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp1fd+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp1fd+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp1fd+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Sf2ue) + +static struct BurnInputInfo Sf2yycInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp019+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp019+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp176+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp176+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp176+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp019+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp019+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp176+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp176+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp176+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp019+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp019+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Sf2yyc) + +static struct BurnInputInfo Sf2m1InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp012+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp012+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp012+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp012+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp012+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp012+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Sf2m1) + +static struct BurnInputInfo Sf2m3InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp029+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp029+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp011+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp011+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp011+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp011+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp011+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp011+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp011+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp186+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp186+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp186+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp029+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp029+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp010+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp010+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp010+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp010+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp010+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp010+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp010+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp186+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp186+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp186+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp029+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp029+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Sf2m3) + +static struct BurnInputInfo SfzchInputList[] = +{ + {"P1 Pause" , BIT_DIGITAL , CpsInp018+2, "" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp018+0, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp018+6, "p1 fire 6" }, + + {"P2 Pause" , BIT_DIGITAL , CpsInp018+3, "" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp018+1, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp018+7, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, +}; + +STDINPUTINFO(Sfzch) + +static struct BurnInputInfo SlammastInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Pin" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Pin" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInpc001+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInpc001+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInpc001+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInpc001+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInpc001+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInpc001+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInpc001+4, "p3 fire 1"}, + {"P3 Jump" , BIT_DIGITAL , CpsInpc001+5, "p3 fire 2"}, + {"P3 Pin" , BIT_DIGITAL , CpsInp001+7 , "p3 fire 3"}, + + {"P4 Coin" , BIT_DIGITAL , CpsInpc003+6, "p4 coin" }, + {"P4 Start" , BIT_DIGITAL , CpsInpc003+7, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , CpsInpc003+3, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , CpsInpc003+2, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , CpsInpc003+1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , CpsInpc003+0, "p4 right" }, + {"P4 Attack" , BIT_DIGITAL , CpsInpc003+4, "p4 fire 1"}, + {"P4 Jump" , BIT_DIGITAL , CpsInpc003+5, "p4 fire 2"}, + {"P4 Pin" , BIT_DIGITAL , CpsInp000+7 , "p4 fire 3"}, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6 , "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2 , "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Slammast) + +static struct BurnInputInfo StriderInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Strider) + +static struct BurnInputInfo UnsquadInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, + +}; + +STDINPUTINFO(Unsquad) + +static struct BurnInputInfo VarthInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Varth) + +static struct BurnInputInfo WillowInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Willow) + +static struct BurnInputInfo WofInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInpc001+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInpc001+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInpc001+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInpc001+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInpc001+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInpc001+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInpc001+4, "p3 fire 1"}, + {"P3 Jump" , BIT_DIGITAL , CpsInpc001+5, "p3 fire 2"}, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Wof) + +static struct BurnInputInfo WofchInputList[] = +{ + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Start" , BIT_DIGITAL , CpsInpc001+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInpc001+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInpc001+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInpc001+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInpc001+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInpc001+4, "p3 fire 1"}, + {"P3 Jump" , BIT_DIGITAL , CpsInpc001+5, "p3 fire 2"}, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, +}; + +STDINPUTINFO(Wofch) + +static struct BurnInputInfo WofhfhInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp018+0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp018+4, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp018+1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp018+5, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp177+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp177+7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp177+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp177+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp177+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp177+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp177+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp177+5, "p3 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp018+6, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp018+2, "service" }, + {"Dip A" , BIT_DIPSWITCH, &Cpi01A , "dip" }, + {"Dip B" , BIT_DIPSWITCH, &Cpi01C , "dip" }, + {"Dip C" , BIT_DIPSWITCH, &Cpi01E , "dip" }, +}; + +STDINPUTINFO(Wofhfh) + +// Dip Switch Definitions + +#define CPS1_COINAGE_1(dipval) \ + {0 , 0xfe, 0 , 8 , "Coin A" }, \ + {dipval, 0x01, 0x07, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x06, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x05, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x07, 0x04, "1 Coin 6 Credits" }, \ + \ + {0 , 0xfe, 0 , 8 , "Coin B" }, \ + {dipval, 0x01, 0x38, 0x38, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x30, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x28, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x08, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x38, 0x18, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x38, 0x20, "1 Coin 6 Credits" }, + +#define CPS1_COINAGE_2(dipval) \ + {0 , 0xfe, 0 , 8 , "Coinage" }, \ + {dipval, 0x01, 0x07, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x06, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x05, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x07, 0x04, "1 Coin 6 Credits" }, + +#define CPS1_COINAGE_3(dipval) \ + {0 , 0xfe, 0 , 8 , "Coin A" }, \ + {dipval, 0x01, 0x07, 0x06, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x05, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x04, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x07, "2 Coins 1 Credit (1 to cont)"}, \ + {dipval, 0x01, 0x07, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, \ + \ + {0 , 0xfe, 0 , 8 , "Coin B" }, \ + {dipval, 0x01, 0x38, 0x30, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x28, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x20, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x38, "2 Coins 1 Credit (1 to cont)"}, \ + {dipval, 0x01, 0x38, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x38, 0x08, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x38, 0x18, "1 Coin 4 Credits" }, + +#define CPS1_DIFFICULTY_1(dipval) \ + {0 , 0xfe, 0 , 8 , "Difficulty" }, \ + {dipval, 0x01, 0x07, 0x00, "1 (Easiest)" }, \ + {dipval, 0x01, 0x07, 0x01, "2" }, \ + {dipval, 0x01, 0x07, 0x02, "3" }, \ + {dipval, 0x01, 0x07, 0x03, "4 (Normal)" }, \ + {dipval, 0x01, 0x07, 0x04, "5" }, \ + {dipval, 0x01, 0x07, 0x05, "6" }, \ + {dipval, 0x01, 0x07, 0x06, "7" }, \ + {dipval, 0x01, 0x07, 0x07, "8 (Hardest)" }, + +#define CPS1_DIFFICULTY_2(dipval) \ + {0 , 0xfe, 0 , 8 , "Difficulty" }, \ + {dipval, 0x01, 0x07, 0x03, "1 (Easiest)" }, \ + {dipval, 0x01, 0x07, 0x02, "2" }, \ + {dipval, 0x01, 0x07, 0x01, "3" }, \ + {dipval, 0x01, 0x07, 0x00, "4 (Normal)" }, \ + {dipval, 0x01, 0x07, 0x04, "5" }, \ + {dipval, 0x01, 0x07, 0x05, "6" }, \ + {dipval, 0x01, 0x07, 0x06, "7" }, \ + {dipval, 0x01, 0x07, 0x07, "8 (Hardest)" }, + +static struct BurnDIPInfo NTFODIPList[]= +{ + // Defaults + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x12) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x13) + + {0 , 0xfe, 0 , 4 , "Level Up Timer" }, + {0x13, 0x01, 0x18, 0x00, "More Slowly" }, + {0x13, 0x01, 0x18, 0x08, "Slowly" }, + {0x13, 0x01, 0x18, 0x10, "Quickly" }, + {0x13, 0x01, 0x18, 0x18, "More Quickly" }, + + {0 , 0xfe, 0 , 4 , "Bullet's Speed" }, + {0x13, 0x01, 0x60, 0x00, "Very Slow" }, + {0x13, 0x01, 0x60, 0x20, "Slow" }, + {0x13, 0x01, 0x60, 0x40, "Fast" }, + {0x13, 0x01, 0x60, 0x60, "Very Fast" }, + + {0 , 0xfe, 0 , 2 , "Initital Vitality" }, + {0x13, 0x01, 0x80, 0x00, "3 bars" }, + {0x13, 0x01, 0x80, 0x80, "4 bars" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Throttle Game Speed" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x04, 0x00, "Off" }, + {0x14, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x14, 0x01, 0x80, 0x00, "Game" }, + {0x14, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(NTFO) + +static struct BurnDIPInfo ThreeWondersDIPList[]= +{ + // Defaults + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x65, NULL }, + {0x15, 0xff, 0xff, 0x66, NULL }, + + // Dip A + CPS1_COINAGE_1(0x13) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + // Dip B + {0 , 0xfe, 0 , 4 , "Action Lives" }, + {0x14, 0x01, 0x03, 0x00, "1" }, + {0x14, 0x01, 0x03, 0x01, "2" }, + {0x14, 0x01, 0x03, 0x02, "3" }, + {0x14, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 4 , "Action Game Level" }, + {0x14, 0x01, 0x0c, 0x00, "Easy" }, + {0x14, 0x01, 0x0c, 0x04, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Hard" }, + {0x14, 0x01, 0x0c, 0x0c, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Shooting Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x20, "3" }, + {0x14, 0x01, 0x30, 0x30, "5" }, + + {0 , 0xfe, 0 , 4 , "Shooting Game Level" }, + {0x14, 0x01, 0xc0, 0x00, "Easy" }, + {0x14, 0x01, 0xc0, 0x40, "Normal" }, + {0x14, 0x01, 0xc0, 0x80, "Hard" }, + {0x14, 0x01, 0xc0, 0xc0, "Hardest" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Puzzle Lives" }, + {0x15, 0x01, 0x03, 0x00, "1" }, + {0x15, 0x01, 0x03, 0x01, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 4 , "Puzzle Game Level" }, + {0x15, 0x01, 0x0c, 0x00, "Easy" }, + {0x15, 0x01, 0x0c, 0x04, "Normal" }, + {0x15, 0x01, 0x0c, 0x08, "Hard" }, + {0x15, 0x01, 0x0c, 0x0c, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x10, 0x00, "Off" }, + {0x15, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x15, 0x01, 0x80, 0x00, "Game" }, + {0x15, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(ThreeWonders) + +static struct BurnDIPInfo CaptcommDIPList[]= +{ + // Defaults + {0x23, 0xff, 0xff, 0x00, NULL }, + {0x24, 0xff, 0xff, 0x0b, NULL }, + {0x25, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x23) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x23, 0x01, 0x40, 0x00, "Off" }, + {0x23, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x24) + + {0 , 0xfe, 0 , 4 , "Difficulty 2" }, + {0x24, 0x01, 0x18, 0x00, "Easy" }, + {0x24, 0x01, 0x18, 0x08, "Normal" }, + {0x24, 0x01, 0x18, 0x10, "Hard" }, + {0x24, 0x01, 0x18, 0x18, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Play Mode" }, + {0x24, 0x01, 0xc0, 0x80, "1 Player" }, + {0x24, 0x01, 0xc0, 0x00, "2 Player" }, + {0x24, 0x01, 0xc0, 0x40, "3 Player" }, + {0x24, 0x01, 0xc0, 0xc0, "4 Player" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x25, 0x01, 0x03, 0x03, "1" }, + {0x25, 0x01, 0x03, 0x00, "2" }, + {0x25, 0x01, 0x03, 0x01, "3" }, + {0x25, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x25, 0x01, 0x04, 0x00, "Off" }, + {0x25, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x25, 0x01, 0x08, 0x00, "Off" }, + {0x25, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x25, 0x01, 0x10, 0x00, "Off" }, + {0x25, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x25, 0x01, 0x20, 0x00, "Off" }, + {0x25, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x25, 0x01, 0x40, 0x00, "Off" }, + {0x25, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x25, 0x01, 0x80, 0x00, "Game" }, + {0x25, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Captcomm) + +static struct BurnDIPInfo CawingDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x03, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + // Dip B + {0 , 0xfe, 0 , 8 , "Difficulty (Enemys strength)"}, + {0x16, 0x01, 0x07, 0x00, "1 (Easiest)" }, + {0x16, 0x01, 0x07, 0x01, "2" }, + {0x16, 0x01, 0x07, 0x02, "3" }, + {0x16, 0x01, 0x07, 0x03, "4 (Normal)" }, + {0x16, 0x01, 0x07, 0x04, "5" }, + {0x16, 0x01, 0x07, 0x05, "6" }, + {0x16, 0x01, 0x07, 0x06, "7" }, + {0x16, 0x01, 0x07, 0x07, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty (Players strength)"}, + {0x16, 0x01, 0x18, 0x08, "Easy" }, + {0x16, 0x01, 0x18, 0x00, "Normal" }, + {0x16, 0x01, 0x18, 0x10, "Difficult" }, + {0x16, 0x01, 0x18, 0x18, "Very Difficult" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Cawing) + +static struct BurnDIPInfo Cworld2jDIPList[]= +{ + // Defaults + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x01, NULL }, + {0x11, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x0f) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Extended Test Mode" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, + + // Dip B + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x07, 0x01, "0" }, + {0x10, 0x01, 0x07, 0x02, "1" }, + {0x10, 0x01, 0x07, 0x03, "2" }, + {0x10, 0x01, 0x07, 0x04, "3" }, + {0x10, 0x01, 0x07, 0x05, "4" }, + + {0 , 0xfe, 0 , 3 , "Extend" }, + {0x10, 0x01, 0x18, 0x18, "D" }, + {0x10, 0x01, 0x18, 0x08, "E" }, + {0x10, 0x01, 0x18, 0x00, "N" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x10, 0x01, 0xe0, 0xe0, "1" }, + {0x10, 0x01, 0xe0, 0x60, "2" }, + {0x10, 0x01, 0xe0, 0x00, "3" }, + {0x10, 0x01, 0xe0, 0x40, "4" }, + {0x10, 0x01, 0xe0, 0x20, "5" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x04, 0x00, "Off" }, + {0x11, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x11, 0x01, 0x80, 0x00, "Game" }, + {0x11, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Cworld2j) + +static struct BurnDIPInfo DinoDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1b, 0x01, 0x08, 0x00, "Off" }, + {0x1b, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(Dino) + +static struct BurnDIPInfo DinohDIPList[]= +{ + // Defaults + {0x1d, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(Dinoh) + +static struct BurnDIPInfo DynwarDIPList[]= +{ + // Defaults + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_3(0x14) + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + // Dip B + CPS1_DIFFICULTY_2(0x15) + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x16, 0x01, 0x01, 0x00, "Off" }, + {0x16, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Turbo Mode" }, + {0x16, 0x01, 0x02, 0x00, "Off" }, + {0x16, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x16, 0x01, 0x80, 0x00, "Game" }, + {0x16, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Dynwar) + +static struct BurnDIPInfo FfightDIPList[]= +{ + // Defaults + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x0b, NULL }, + {0x16, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x14) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x15) + + {0 , 0xfe, 0 , 4 , "Difficulty 2" }, + {0x15, 0x01, 0x18, 0x00, "Easy" }, + {0x15, 0x01, 0x18, 0x08, "Normal" }, + {0x15, 0x01, 0x18, 0x10, "Hard" }, + {0x15, 0x01, 0x18, 0x18, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x60, 0x00, "100k" }, + {0x15, 0x01, 0x60, 0x20, "200k" }, + {0x15, 0x01, 0x60, 0x40, "100k and every 200k" }, + {0x15, 0x01, 0x60, 0x60, "None" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x03, 0x03, "1" }, + {0x16, 0x01, 0x03, 0x00, "2" }, + {0x16, 0x01, 0x03, 0x01, "3" }, + {0x16, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x16, 0x01, 0x08, 0x00, "Off" }, + {0x16, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x16, 0x01, 0x80, 0x00, "Game" }, + {0x16, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Ffight) + +static struct BurnDIPInfo ForgottnDIPList[]= +{ + // Defaults + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x12) + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x12, 0x01, 0x80, 0x00, "Off" }, + {0x12, 0x01, 0x80, 0x80, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x13) + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Forgottn) + +static struct BurnDIPInfo GhoulsDIPList[]= +{ + // Defaults + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x12) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x12, 0x01, 0xc0, 0x00, "Upright 1 Player" }, + {0x12, 0x01, 0xc0, 0x40, "Upright 2 Players" }, + {0x12, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x13) + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x30, 0x10, "10k, 30k and every 30k" }, + {0x13, 0x01, 0x30, 0x20, "20k, 50k and every 70k" }, + {0x13, 0x01, 0x30, 0x00, "30k, 60k and every 70k" }, + {0x13, 0x01, 0x30, 0x30, "40k, 70k and every 80k" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x00, "3" }, + {0x14, 0x01, 0x03, 0x01, "4" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + {0x14, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x14, 0x01, 0x80, 0x00, "Game" }, + {0x14, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Ghouls) + +static struct BurnDIPInfo GhoulsuDIPList[]= +{ + // Defaults + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x12) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x12, 0x01, 0xc0, 0x00, "Upright 1 Player" }, + {0x12, 0x01, 0xc0, 0x40, "Upright 2 Players" }, + {0x12, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x13) + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x30, 0x10, "10k, 30k and every 30k" }, + {0x13, 0x01, 0x30, 0x20, "20k, 50k and every 70k" }, + {0x13, 0x01, 0x30, 0x00, "30k, 60k and every 70k" }, + {0x13, 0x01, 0x30, 0x30, "40k, 70k and every 80k" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x03, "2" }, + {0x14, 0x01, 0x03, 0x00, "3" }, + {0x14, 0x01, 0x03, 0x01, "4" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x14, 0x01, 0x80, 0x00, "Game" }, + {0x14, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Ghoulsu) + +static struct BurnDIPInfo DaimakaiDIPList[]= +{ + // Defaults + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x12) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x12, 0x01, 0xc0, 0x00, "Upright 1 Player" }, + {0x12, 0x01, 0xc0, 0x40, "Upright 2 Players" }, + {0x12, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x13) + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x30, 0x10, "10k, 30k and every 30k" }, + {0x13, 0x01, 0x30, 0x20, "20k, 50k and every 70k" }, + {0x13, 0x01, 0x30, 0x00, "30k, 60k and every 70k" }, + {0x13, 0x01, 0x30, 0x30, "40k, 70k and every 80k" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x00, "3" }, + {0x14, 0x01, 0x03, 0x01, "4" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + {0x14, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x14, 0x01, 0x80, 0x00, "Game" }, + {0x14, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Daimakai) + +static struct BurnDIPInfo KnightsDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x1b) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + {0 , 0xfe, 0 , 8 , "Enemys Attack Frequency"}, + {0x1c, 0x01, 0x07, 0x00, "1 (Easiest)" }, + {0x1c, 0x01, 0x07, 0x01, "2" }, + {0x1c, 0x01, 0x07, 0x02, "3" }, + {0x1c, 0x01, 0x07, 0x03, "4 (Normal)" }, + {0x1c, 0x01, 0x07, 0x04, "5" }, + {0x1c, 0x01, 0x07, 0x05, "6" }, + {0x1c, 0x01, 0x07, 0x06, "7" }, + {0x1c, 0x01, 0x07, 0x07, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 8 , "Enemys Attack Power" }, + {0x1c, 0x01, 0x38, 0x38, "1 (Easiest)" }, + {0x1c, 0x01, 0x38, 0x30, "2" }, + {0x1c, 0x01, 0x38, 0x28, "3" }, + {0x1c, 0x01, 0x38, 0x00, "4 (Normal)" }, + {0x1c, 0x01, 0x38, 0x08, "5" }, + {0x1c, 0x01, 0x38, 0x10, "6" }, + {0x1c, 0x01, 0x38, 0x18, "7" }, + {0x1c, 0x01, 0x38, 0x20, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x1c, 0x01, 0x40, 0x40, "1" }, + {0x1c, 0x01, 0x40, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1c, 0x01, 0x80, 0x80, "2P" }, + {0x1c, 0x01, 0x80, 0x00, "3P" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x1d, 0x01, 0x03, 0x03, "1" }, + {0x1d, 0x01, 0x03, 0x00, "2" }, + {0x1d, 0x01, 0x03, 0x01, "3" }, + {0x1d, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x1d, 0x01, 0x04, 0x00, "Off" }, + {0x1d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Game" }, + {0x1d, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Knights) + +static struct BurnDIPInfo KodDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x1b) + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x1b, 0x01, 0x08, 0x08, "1" }, + {0x1b, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1b, 0x01, 0x10, 0x10, "2 Players" }, + {0x1b, 0x01, 0x10, 0x00, "3 Players" }, + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x1c) + + {0 , 0xfe, 0 , 8 , "Lives" }, + {0x1c, 0x01, 0x38, 0x08, "1" }, + {0x1c, 0x01, 0x38, 0x00, "2" }, + {0x1c, 0x01, 0x38, 0x10, "3" }, + {0x1c, 0x01, 0x38, 0x18, "4" }, + {0x1c, 0x01, 0x38, 0x20, "5" }, + {0x1c, 0x01, 0x38, 0x28, "6" }, + {0x1c, 0x01, 0x38, 0x30, "7" }, + {0x1c, 0x01, 0x38, 0x38, "8" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x1c, 0x01, 0xc0, 0x40, "80k and every 400k" }, + {0x1c, 0x01, 0xc0, 0x80, "160k and every 450k" }, + {0x1c, 0x01, 0xc0, 0x00, "200k and every 450k" }, + {0x1c, 0x01, 0xc0, 0xc0, "None" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x1d, 0x01, 0x04, 0x00, "Off" }, + {0x1d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Game" }, + {0x1d, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Kod) + +static struct BurnDIPInfo Kodr1DIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x1b) + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x1b, 0x01, 0x08, 0x08, "1" }, + {0x1b, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1b, 0x01, 0x10, 0x10, "2 Players" }, + {0x1b, 0x01, 0x10, 0x00, "3 Players" }, + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x1c) + + {0 , 0xfe, 0 , 8 , "Lives" }, + {0x1c, 0x01, 0x38, 0x08, "1" }, + {0x1c, 0x01, 0x38, 0x00, "2" }, + {0x1c, 0x01, 0x38, 0x10, "3" }, + {0x1c, 0x01, 0x38, 0x18, "4" }, + {0x1c, 0x01, 0x38, 0x20, "5" }, + {0x1c, 0x01, 0x38, 0x28, "6" }, + {0x1c, 0x01, 0x38, 0x30, "7" }, + {0x1c, 0x01, 0x38, 0x38, "8" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x1c, 0x01, 0xc0, 0x40, "80k and every 400k" }, + {0x1c, 0x01, 0xc0, 0x00, "160k and every 450k" }, + {0x1c, 0x01, 0xc0, 0x80, "200k and every 450k" }, + {0x1c, 0x01, 0xc0, 0xc0, "None" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x1d, 0x01, 0x04, 0x00, "Off" }, + {0x1d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Game" }, + {0x1d, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Kodr1) + +static struct BurnDIPInfo MegamanDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x01, NULL }, + {0x17, 0xff, 0xff, 0x00, NULL }, + + // Dip A + {0 , 0xfe, 0 , 19 , "Coinage" }, + {0x15, 0x01, 0x1f, 0x00, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x1f, 0x01, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x1f, 0x02, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x1f, 0x03, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x1f, 0x04, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x1f, 0x05, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x1f, 0x06, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x1f, 0x07, "1 Coin 8 Credits" }, + {0x15, 0x01, 0x1f, 0x08, "1 Coin 9 Credits" }, + {0x15, 0x01, 0x1f, 0x09, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0a, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0b, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0c, "5 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0d, "6 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0e, "7 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0f, "8 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x10, "9 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x11, "2 Coins Start 1 Coin Continue"}, + {0x15, 0x01, 0x1f, 0x12, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Coin Slots" }, + {0x15, 0x01, 0x60, 0x40, "1, Common" }, + {0x15, 0x01, 0x60, 0x00, "2, Common" }, + {0x15, 0x01, 0x60, 0x20, "2, Individual" }, + + // Dip B + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x00, "Easy" }, + {0x16, 0x01, 0x03, 0x01, "Normal" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x16, 0x01, 0x0c, 0x00, "100" }, + {0x16, 0x01, 0x0c, 0x04, "90" }, + {0x16, 0x01, 0x0c, 0x08, "70" }, + {0x16, 0x01, 0x0c, 0x0c, "60" }, + + {0 , 0xfe, 0 , 2 , "Voice" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x04, 0x04, "Off" }, + {0x17, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Megaman) + +static struct BurnDIPInfo RockmanjDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x01, NULL }, + {0x17, 0xff, 0xff, 0x00, NULL }, + + // Dip A + {0 , 0xfe, 0 , 19 , "Coinage" }, + {0x15, 0x01, 0x1f, 0x00, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x1f, 0x01, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x1f, 0x02, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x1f, 0x03, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x1f, 0x04, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x1f, 0x05, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x1f, 0x06, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x1f, 0x07, "1 Coin 8 Credits" }, + {0x15, 0x01, 0x1f, 0x08, "1 Coin 9 Credits" }, + {0x15, 0x01, 0x1f, 0x09, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0a, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0b, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0c, "5 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0d, "6 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0e, "7 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x0f, "8 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x10, "9 Coins 1 Credit" }, + {0x15, 0x01, 0x1f, 0x11, "2 Coins Start 1 Coin Continue"}, + {0x15, 0x01, 0x1f, 0x12, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Coin Slots" }, + {0x15, 0x01, 0x60, 0x40, "1, Common" }, + {0x15, 0x01, 0x60, 0x00, "2, Common" }, + {0x15, 0x01, 0x60, 0x20, "2, Individual" }, + + // Dip B + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x00, "Easy" }, + {0x16, 0x01, 0x03, 0x01, "Normal" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x16, 0x01, 0x0c, 0x00, "100" }, + {0x16, 0x01, 0x0c, 0x04, "90" }, + {0x16, 0x01, 0x0c, 0x08, "70" }, + {0x16, 0x01, 0x0c, 0x0c, "60" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x04, 0x04, "Off" }, + {0x17, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Rockmanj) + +static struct BurnDIPInfo MercsDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_2(0x1b) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x1c) + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x1c, 0x01, 0x08, 0x08, "1" }, + {0x1c, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1c, 0x01, 0x10, 0x10, "2 Player" }, + {0x1c, 0x01, 0x10, 0x00, "3 Player" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Off" }, + {0x1d, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Mercs) + +static struct BurnDIPInfo MswordDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x03, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + // Dip B + {0 , 0xfe, 0 , 8 , "Players vitality consumption"}, + {0x16, 0x01, 0x07, 0x00, "1 (Easiest)" }, + {0x16, 0x01, 0x07, 0x01, "2" }, + {0x16, 0x01, 0x07, 0x02, "3" }, + {0x16, 0x01, 0x07, 0x03, "4 (Normal)" }, + {0x16, 0x01, 0x07, 0x04, "5" }, + {0x16, 0x01, 0x07, 0x05, "6" }, + {0x16, 0x01, 0x07, 0x06, "7" }, + {0x16, 0x01, 0x07, 0x07, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 8 , "Level 2" }, + {0x16, 0x01, 0x38, 0x18, "1 (Easiest)" }, + {0x16, 0x01, 0x38, 0x10, "2" }, + {0x16, 0x01, 0x38, 0x08, "3" }, + {0x16, 0x01, 0x38, 0x00, "4 (Normal)" }, + {0x16, 0x01, 0x38, 0x20, "5" }, + {0x16, 0x01, 0x38, 0x28, "6" }, + {0x16, 0x01, 0x38, 0x30, "7" }, + {0x16, 0x01, 0x38, 0x38, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 2 , "Stage Select" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Vitality" }, + {0x17, 0x01, 0x03, 0x03, "1" }, + {0x17, 0x01, 0x03, 0x00, "2" }, + {0x17, 0x01, 0x03, 0x01, "3 (2 when continue)" }, + {0x17, 0x01, 0x03, 0x02, "4 (3 when continue)" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Msword) + +static struct BurnDIPInfo MtwinsDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x03, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x15) + + // Dip B + CPS1_DIFFICULTY_1(0x16) + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x38, 0x28, "1" }, + {0x16, 0x01, 0x38, 0x20, "2" }, + {0x16, 0x01, 0x38, 0x30, "3" }, + {0x16, 0x01, 0x38, 0x38, "4" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Mtwins) + +static struct BurnDIPInfo NemoDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x03, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x16) + + {0 , 0xfe, 0 , 3 , "Life Bar" }, + {0x16, 0x01, 0x18, 0x18, "Minimum" }, + {0x16, 0x01, 0x18, 0x00, "Medium" }, + {0x16, 0x01, 0x18, 0x10, "Maximum" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x17, 0x01, 0x03, 0x01, "1" }, + {0x17, 0x01, 0x03, 0x00, "2" }, + {0x17, 0x01, 0x03, 0x02, "3" }, + {0x17, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Nemo) + +static struct BurnDIPInfo Pang3DIPList[]= +{ + // Defaults + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(Pang3) + +static struct BurnDIPInfo PnickjDIPList[]= +{ + // Defaults + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x03, NULL }, + {0x15, 0xff, 0xff, 0x20, NULL }, + + // Dip A + CPS1_COINAGE_2(0x13) + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x13, 0x01, 0x08, 0x00, "1" }, + {0x13, 0x01, 0x08, 0x08, "2" }, + + // Dip B + CPS1_DIFFICULTY_1(0x14) + + {0 , 0xfe, 0 , 4 , "Vs. Play Mode" }, + {0x14, 0x01, 0xc0, 0x00, "1 Game Match" }, + {0x14, 0x01, 0xc0, 0x40, "3 Games Match" }, + {0x14, 0x01, 0xc0, 0x80, "5 Games Match" }, + {0x14, 0x01, 0xc0, 0xc0, "7 Games Match" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x15, 0x01, 0x10, 0x00, "Off" }, + {0x15, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x15, 0x01, 0x80, 0x00, "Game" }, + {0x15, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Pnickj) + +static struct BurnDIPInfo PunisherDIPList[]= +{ + // Defaults + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(Punisher) + +static struct BurnDIPInfo PunisherbzDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x10, NULL }, + {0x16, 0xff, 0xff, 0x6B, NULL }, + + // Dip A + CPS1_COINAGE_2(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x30, 0x00, "1" }, + {0x15, 0x01, 0x30, 0x10, "2" }, + {0x15, 0x01, 0x30, 0x20, "3" }, + {0x15, 0x01, 0x30, 0x30, "4" }, + + {0 , 0xfe, 0 , 2 , "Sound" }, + {0x15, 0x01, 0x40, 0x00, "Q Sound" }, + {0x15, 0x01, 0x40, 0x40, "Monaural" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, + + // Dip B + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x16, 0x01, 0x07, 0x00, "0 (Easiest)" }, + {0x16, 0x01, 0x07, 0x01, "1" }, + {0x16, 0x01, 0x07, 0x02, "2" }, + {0x16, 0x01, 0x07, 0x03, "3 (Normal)" }, + {0x16, 0x01, 0x07, 0x04, "4" }, + {0x16, 0x01, 0x07, 0x05, "5" }, + {0x16, 0x01, 0x07, 0x06, "6" }, + {0x16, 0x01, 0x07, 0x07, "7 (Hardest)" }, + + {0 , 0xfe, 0 , 4 , "Extend" }, + {0x16, 0x01, 0x18, 0x00, "800000" }, + {0x16, 0x01, 0x18, 0x08, "1800000" }, + {0x16, 0x01, 0x18, 0x10, "2800000" }, + {0x16, 0x01, 0x18, 0x18, "No Extend" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Punisherbz) + +static struct BurnDIPInfo QadDIPList[]= +{ + // Defaults + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x0b, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_2(0x0f) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + // Dip B + {0 , 0xfe, 0 , 5 , "Difficulty" }, + {0x10, 0x01, 0x07, 0x01, "Easiest" }, + {0x10, 0x01, 0x07, 0x02, "Easy" }, + {0x10, 0x01, 0x07, 0x03, "Normal" }, + {0x10, 0x01, 0x07, 0x04, "Hard" }, + {0x10, 0x01, 0x07, 0x05, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Wisdom of Enemy" }, + {0x10, 0x01, 0x18, 0x00, "Easy" }, + {0x10, 0x01, 0x18, 0x08, "Normal" }, + {0x10, 0x01, 0x18, 0x10, "Hard" }, + {0x10, 0x01, 0x18, 0x18, "Hardest" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x10, 0x01, 0xe0, 0x80, "1" }, + {0x10, 0x01, 0xe0, 0x60, "2" }, + {0x10, 0x01, 0xe0, 0x40, "3" }, + {0x10, 0x01, 0xe0, 0x20, "4" }, + {0x10, 0x01, 0xe0, 0x00, "5" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x04, 0x00, "Off" }, + {0x11, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x11, 0x01, 0x20, 0x20, "Off" }, + {0x11, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x11, 0x01, 0x80, 0x00, "Game" }, + {0x11, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Qad) + +static struct BurnDIPInfo QadjDIPList[]= +{ + // Defaults + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x20, NULL }, + + // Dip A + CPS1_COINAGE_2(0x0f) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + // Dip B + {0 , 0xfe, 0 , 5 , "Difficulty" }, + {0x10, 0x01, 0x07, 0x00, "0" }, + {0x10, 0x01, 0x07, 0x01, "1" }, + {0x10, 0x01, 0x07, 0x02, "2" }, + {0x10, 0x01, 0x07, 0x03, "3" }, + {0x10, 0x01, 0x07, 0x04, "4" }, + + {0 , 0xfe, 0 , 3 , "Lives" }, + {0x10, 0x01, 0xe0, 0x40, "1" }, + {0x10, 0x01, 0xe0, 0x20, "2" }, + {0x10, 0x01, 0xe0, 0x00, "3" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x04, 0x00, "Off" }, + {0x11, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x11, 0x01, 0x80, 0x00, "Game" }, + {0x11, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Qadj) + +static struct BurnDIPInfo Qtono2jDIPList[]= +{ + // Defaults + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x03, NULL }, + {0x11, 0xff, 0xff, 0x20, NULL }, + + // Dip A + CPS1_COINAGE_2(0x0f) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x10) + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x10, 0x01, 0xe0, 0x80, "1" }, + {0x10, 0x01, 0xe0, 0x60, "2" }, + {0x10, 0x01, 0xe0, 0x00, "3" }, + {0x10, 0x01, 0xe0, 0x40, "4" }, + {0x10, 0x01, 0xe0, 0x20, "5" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Infinite Lives" }, + {0x11, 0x01, 0x02, 0x00, "Off" }, + {0x11, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x04, 0x00, "Off" }, + {0x11, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x11, 0x01, 0x80, 0x00, "Game" }, + {0x11, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Qtono2j) + +static struct BurnDIPInfo Sf2DIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x1b) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x1c) + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x1d, 0x01, 0x04, 0x00, "Off" }, + {0x1d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Game" }, + {0x1d, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Sf2) + +static struct BurnDIPInfo Sf2jDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x03, NULL }, + {0x1d, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x1b) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x1b, 0x01, 0x40, 0x00, "Off" }, + {0x1b, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x1c) + + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x1c, 0x01, 0x08, 0x00, "1 Credit/No Continue" }, + {0x1c, 0x01, 0x08, 0x08, "2 Credits/Winner Continue"}, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x1d, 0x01, 0x04, 0x00, "Off" }, + {0x1d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1d, 0x01, 0x08, 0x00, "Off" }, + {0x1d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x1d, 0x01, 0x40, 0x00, "Off" }, + {0x1d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x1d, 0x01, 0x80, 0x00, "Game" }, + {0x1d, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Sf2j) + +static struct BurnDIPInfo SlammastDIPList[]= +{ + // Defaults + {0x23, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x23, 0x01, 0x08, 0x08, "Off" }, + {0x23, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Slammast) + +static struct BurnDIPInfo StriderDIPList[]= +{ + // Defaults + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x14) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x14, 0x01, 0xc0, 0x00, "Upright 1P" }, + {0x14, 0x01, 0xc0, 0x40, "Upright 2P" }, + {0x14, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x15) + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x30, 0x00, "20k, 40k and every 60k" }, + {0x15, 0x01, 0x30, 0x10, "30k, 50k and every 70k" }, + {0x15, 0x01, 0x30, 0x20, "20k & 60k only" }, + {0x15, 0x01, 0x30, 0x30, "30k & 60k only" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x03, 0x03, "2" }, + {0x16, 0x01, 0x03, 0x00, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x16, 0x01, 0x08, 0x00, "Off" }, + {0x16, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x16, 0x01, 0x80, 0x00, "Game" }, + {0x16, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Strider) + +static struct BurnDIPInfo StrideruaDIPList[]= +{ + // Defaults + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_1(0x14) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x14, 0x01, 0xc0, 0x00, "Upright 1P" }, + {0x14, 0x01, 0xc0, 0x40, "Upright 2P" }, + {0x14, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x30, 0x00, "20k, 40k and every 60k" }, + {0x15, 0x01, 0x30, 0x10, "30k, 50k and every 70k" }, + {0x15, 0x01, 0x30, 0x20, "20k & 60k only" }, + {0x15, 0x01, 0x30, 0x30, "30k & 60k only" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x03, 0x03, "2" }, + {0x16, 0x01, 0x03, 0x00, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x16, 0x01, 0x08, 0x00, "Off" }, + {0x16, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x16, 0x01, 0x80, 0x00, "Game" }, + {0x16, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Striderua) + +static struct BurnDIPInfo UnsquadDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x03, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_3(0x15) + + // Dip B + CPS1_DIFFICULTY_1(0x16) + + {0 , 0xfe, 0 , 4 , "Damage" }, + {0x16, 0x01, 0x18, 0x08, "Small" }, + {0x16, 0x01, 0x18, 0x00, "Normal" }, + {0x16, 0x01, 0x18, 0x10, "Big" }, + {0x16, 0x01, 0x18, 0x18, "Biggest" }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Unsquad) + +static struct BurnDIPInfo VarthDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x0b, NULL }, + {0x17, 0xff, 0xff, 0x60, NULL }, + + // Dip A + CPS1_COINAGE_1(0x15) + + {0 , 0xfe, 0 , 2 , "2C to Start, 1 to Cont" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + // Dip B + CPS1_DIFFICULTY_1(0x16) + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x18, 0x00, "600k and every 1400k" }, + {0x16, 0x01, 0x18, 0x08, "600k, 2000k and every 4500k"}, + {0x16, 0x01, 0x18, 0x10, "1200k, 3500k" }, + {0x16, 0x01, 0x18, 0x18, "2000k only" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x17, 0x01, 0x03, 0x01, "1" }, + {0x17, 0x01, 0x03, 0x02, "2" }, + {0x17, 0x01, 0x03, 0x00, "3" }, + {0x17, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x20, 0x00, "Off" }, + {0x17, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Varth) + +static struct BurnDIPInfo WillowDIPList[]= +{ + // Defaults + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x00, NULL }, + + // Dip A + CPS1_COINAGE_3(0x15) + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x15, 0x01, 0xc0, 0x00, "Upright 1P" }, + {0x15, 0x01, 0xc0, 0x40, "Upright 2P" }, + {0x15, 0x01, 0xc0, 0xc0, "Cocktail" }, + + // Dip B + CPS1_DIFFICULTY_2(0x16) + + {0 , 0xfe, 0 , 4 , "Nando Speed" }, + {0x16, 0x01, 0x18, 0x08, "Slow" }, + {0x16, 0x01, 0x18, 0x00, "Normal" }, + {0x16, 0x01, 0x18, 0x10, "Fast" }, + {0x16, 0x01, 0x18, 0x18, "Very Fast" }, + + {0 , 0xfe, 0 , 2 , "Stage Magic Continue" }, + {0x16, 0x01, 0x80, 0x00, "Off" }, + {0x16, 0x01, 0x80, 0x80, "On" }, + + // Dip C + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x17, 0x01, 0x03, 0x01, "1" }, + {0x17, 0x01, 0x03, 0x00, "2" }, + {0x17, 0x01, 0x03, 0x02, "3" }, + {0x17, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 4 , "Vitality" }, + {0x17, 0x01, 0x0c, 0x0c, "2" }, + {0x17, 0x01, 0x0c, 0x00, "3" }, + {0x17, 0x01, 0x0c, 0x04, "4" }, + {0x17, 0x01, 0x0c, 0x08, "5" }, + + {0 , 0xfe, 0 , 2 , "Screen" }, + {0x17, 0x01, 0x10, 0x00, "Off" }, + {0x17, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x20, 0x20, "Off" }, + {0x17, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x17, 0x01, 0x80, 0x00, "Game" }, + {0x17, 0x01, 0x80, 0x80, "Test" }, +}; + +STDDIPINFO(Willow) + +static struct BurnDIPInfo WofDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + + // Dip C + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1b, 0x01, 0x08, 0x08, "Off" }, + {0x1b, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Wof) + +static struct BurnDIPInfo WofhfhDIPList[]= +{ + // Defaults + {0x1b, 0xff, 0xff, 0x00, NULL }, + {0x1c, 0xff, 0xff, 0x13, NULL }, + {0x1d, 0xff, 0xff, 0x00, NULL }, + + // Dip A + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x1b, 0x01, 0x03, 0x00, "1 Coin 1 Credit" }, + {0x1b, 0x01, 0x03, 0x01, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0x03, 0x02, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0x03, 0x03, "1 Coin 4 Credits" }, + + // Dip B + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x1c, 0x01, 0x07, 0x00, "Extra Easy" }, + {0x1c, 0x01, 0x07, 0x01, "Very Easy" }, + {0x1c, 0x01, 0x07, 0x02, "Easy" }, + {0x1c, 0x01, 0x07, 0x03, "Normal" }, + {0x1c, 0x01, 0x07, 0x04, "Hard" }, + {0x1c, 0x01, 0x07, 0x05, "Very Hard" }, + {0x1c, 0x01, 0x07, 0x06, "Extra Hard" }, + {0x1c, 0x01, 0x07, 0x07, "Hardest" }, + + {0 , 0xfe, 0 , 8 , "Lives" }, + {0x1c, 0x01, 0x70, 0x70, "Start 4 Continue 5" }, + {0x1c, 0x01, 0x70, 0x60, "Start 3 Continue 4" }, + {0x1c, 0x01, 0x70, 0x50, "Start 2 Continue 3" }, + {0x1c, 0x01, 0x70, 0x40, "Start 1 Continue 2" }, + {0x1c, 0x01, 0x70, 0x30, "Start 4 Continue 4" }, + {0x1c, 0x01, 0x70, 0x20, "Start 3 Continue 3" }, + {0x1c, 0x01, 0x70, 0x10, "Start 2 Continue 2" }, + {0x1c, 0x01, 0x70, 0x00, "Start 1 Continue 1" }, + + // Dip C + {0 , 0xfe, 0 , 3 , "Coin Slots" }, + {0x1d, 0x01, 0x03, 0x02, "2 Players 1 Shooter" }, + {0x1d, 0x01, 0x03, 0x01, "3 Players 1 Shooter" }, + {0x1d, 0x01, 0x03, 0x00, "3 Players 3 Shooters" }, +}; + +STDDIPINFO(Wofhfh) + +// Rom Definitions + +#define A_BOARD_PLDS \ + { "buf1", 0x000117, 0xeb122de7, BRF_OPT }, \ + { "ioa1", 0x000117, 0x59c7ee3b, BRF_OPT }, \ + { "prg1", 0x000117, 0xf1129744, BRF_OPT }, \ + { "rom1", 0x000117, 0x41dc73b9, BRF_OPT }, \ + { "sou1", 0x000117, 0x84f4b2fe, BRF_OPT }, + +#define A_BOARD_QSOUND_PLDS \ + { "buf1", 0x000117, 0xeb122de7, BRF_OPT }, \ + { "ioa1", 0x000117, 0x59c7ee3b, BRF_OPT }, \ + { "prg2", 0x000117, 0x4386879a, BRF_OPT }, \ + { "rom1", 0x000117, 0x41dc73b9, BRF_OPT }, \ + +static struct BurnRomInfo NTFODrvRomDesc[] = { + { "41e_30.11f", 0x020000, 0x9deb1e75, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41e_35.11h", 0x020000, 0xd63942b3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41e_31.12f", 0x020000, 0xdf201112, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41e_36.12h", 0x020000, 0x816a818f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41-32m.8h", 0x080000, 0x4e9648ca, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "41-5m.7a", 0x080000, 0x01d1cb11, BRF_GRA | CPS1_TILES }, + { "41-7m.9a", 0x080000, 0xaeaa3509, BRF_GRA | CPS1_TILES }, + { "41-1m.3a", 0x080000, 0xff77985a, BRF_GRA | CPS1_TILES }, + { "41-3m.5a", 0x080000, 0x983be58f, BRF_GRA | CPS1_TILES }, + + { "41_09.12b", 0x010000, 0x0f9d8527, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "41_18.11c", 0x020000, 0xd1f15aeb, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "41_19.12c", 0x020000, 0x15aec3a6, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "yi24b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(NTFODrv) +STD_ROM_FN(NTFODrv) + +static struct BurnRomInfo NTFOUDrvRomDesc[] = { + { "41u_30.11f", 0x020000, 0xbe5439d0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41u_35.11h", 0x020000, 0x6ac96595, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41u_31.12f", 0x020000, 0x9811d6eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41u_36.12h", 0x020000, 0xa87e6137, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41-32m.8h", 0x080000, 0x4e9648ca, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "41-5m.7a", 0x080000, 0x01d1cb11, BRF_GRA | CPS1_TILES }, + { "41-7m.9a", 0x080000, 0xaeaa3509, BRF_GRA | CPS1_TILES }, + { "41-1m.3a", 0x080000, 0xff77985a, BRF_GRA | CPS1_TILES }, + { "41-3m.5a", 0x080000, 0x983be58f, BRF_GRA | CPS1_TILES }, + + { "41_9.12b", 0x010000, 0x0f9d8527, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "41e_18.11c", 0x020000, 0xd1f15aeb, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "41_19.12c", 0x020000, 0x15aec3a6, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "yi24b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(NTFOUDrv) +STD_ROM_FN(NTFOUDrv) + +static struct BurnRomInfo NTFOJDrvRomDesc[] = { + { "41_36.12f", 0x020000, 0x7fbd42ab, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_42.12h", 0x020000, 0xc7781f89, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_37.13f", 0x020000, 0xc6464b0b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_43.13h", 0x020000, 0x440fc0b5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_34.10f", 0x020000, 0xb5f341ec, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_40.10h", 0x020000, 0x3979837d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_35.11f", 0x020000, 0x95cc979a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41_41.11h", 0x020000, 0x57496819, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "41_09.4b", 0x020000, 0xbe1b6bc2, BRF_GRA | CPS1_TILES }, + { "41_01.4a", 0x020000, 0xd8946fc1, BRF_GRA | CPS1_TILES }, + { "41_13.9b", 0x020000, 0x2e06d0ec, BRF_GRA | CPS1_TILES }, + { "41_05.9a", 0x020000, 0xd8ba28e0, BRF_GRA | CPS1_TILES }, + { "41_24.5e", 0x020000, 0x5aa43cee, BRF_GRA | CPS1_TILES }, + { "41_17.5c", 0x020000, 0xbbeff902, BRF_GRA | CPS1_TILES }, + { "41_38.8h", 0x020000, 0x8889c0aa, BRF_GRA | CPS1_TILES }, + { "41_32.8f", 0x020000, 0xf0168249, BRF_GRA | CPS1_TILES }, + { "41_10.5b", 0x020000, 0xb7eb6a6d, BRF_GRA | CPS1_TILES }, + { "41_02.5a", 0x020000, 0x802e8153, BRF_GRA | CPS1_TILES }, + { "41_14.10b", 0x020000, 0x5a33f676, BRF_GRA | CPS1_TILES }, + { "41_06.10a", 0x020000, 0x4e53650b, BRF_GRA | CPS1_TILES }, + { "41_25.7e", 0x020000, 0x94add360, BRF_GRA | CPS1_TILES }, + { "41_18.7c", 0x020000, 0xa5e1c1f3, BRF_GRA | CPS1_TILES }, + { "41_39.9h", 0x020000, 0x5b5c3949, BRF_GRA | CPS1_TILES }, + { "41_33.9f", 0x020000, 0x7a31b0e2, BRF_GRA | CPS1_TILES }, + + { "41_23.13b", 0x010000, 0x0f9d8527, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "41_30.12c", 0x020000, 0xd1f15aeb, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "41_31.13c", 0x020000, 0x15aec3a6, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "yi22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(NTFOJDrv) +STD_ROM_FN(NTFOJDrv) + +static struct BurnRomInfo ThreeWondersRomDesc[] = { + { "rte_30a.11f", 0x020000, 0xef5b8b33, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_35a.11h", 0x020000, 0x7d705529, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_31a.12f", 0x020000, 0x32835e5e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_36a.12h", 0x020000, 0x7637975f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_28a.9f", 0x020000, 0x054137c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_33a.9h", 0x020000, 0x7264cb1b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_29a.10f", 0x020000, 0xcddaa919, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_34a.10h", 0x020000, 0xed52e7e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "rt-5m.7a", 0x080000, 0x86aef804, BRF_GRA | CPS1_TILES }, + { "rt-7m.9a", 0x080000, 0x4f057110, BRF_GRA | CPS1_TILES }, + { "rt-1m.3a", 0x080000, 0x902489d0, BRF_GRA | CPS1_TILES }, + { "rt-3m.5a", 0x080000, 0xe35ce720, BRF_GRA | CPS1_TILES }, + { "rt-6m.8a", 0x080000, 0x13cb0e7c, BRF_GRA | CPS1_TILES }, + { "rt-8m.10a", 0x080000, 0x1f055014, BRF_GRA | CPS1_TILES }, + { "rt-2m.4a", 0x080000, 0xe9a034f4, BRF_GRA | CPS1_TILES }, + { "rt-4m.6a", 0x080000, 0xdf0eea8b, BRF_GRA | CPS1_TILES }, + + { "rt_9.12b", 0x010000, 0xabfca165, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rt_18.11c", 0x020000, 0x26b211ab, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rt_19.12c", 0x020000, 0xdbe64ad0, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rt24b.1a", 0x000117, 0x54b85159, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(ThreeWonders) +STD_ROM_FN(ThreeWonders) + +static struct BurnRomInfo Wonder3uRomDesc[] = { + { "rtu_30a.11f", 0x020000, 0x0b156fd8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtu_35a.11h", 0x020000, 0x57350bf4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtu_31a.12f", 0x020000, 0x0e723fcc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtu_36a.12h", 0x020000, 0x523a45dc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_28a.9f", 0x020000, 0x054137c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_33a.9h", 0x020000, 0x7264cb1b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtu_29a.10f", 0x020000, 0x37ba3e20, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtu_34a.10h", 0x020000, 0xf99f46c0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "rt-5m.7a", 0x080000, 0x86aef804, BRF_GRA | CPS1_TILES }, + { "rt-7m.9a", 0x080000, 0x4f057110, BRF_GRA | CPS1_TILES }, + { "rt-1m.3a", 0x080000, 0x902489d0, BRF_GRA | CPS1_TILES }, + { "rt-3m.5a", 0x080000, 0xe35ce720, BRF_GRA | CPS1_TILES }, + { "rt-6m.8a", 0x080000, 0x13cb0e7c, BRF_GRA | CPS1_TILES }, + { "rt-8m.10a", 0x080000, 0x1f055014, BRF_GRA | CPS1_TILES }, + { "rt-2m.4a", 0x080000, 0xe9a034f4, BRF_GRA | CPS1_TILES }, + { "rt-4m.6a", 0x080000, 0xdf0eea8b, BRF_GRA | CPS1_TILES }, + + { "rt_9.12b", 0x010000, 0xabfca165, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rt_18.11c", 0x020000, 0x26b211ab, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rt_19.12c", 0x020000, 0xdbe64ad0, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rt24b.1a", 0x000117, 0x54b85159, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wonder3u) +STD_ROM_FN(Wonder3u) + +static struct BurnRomInfo Wonder3RomDesc[] = { + { "rtj_36.12f", 0x020000, 0xe3741247, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtj_42.12h", 0x020000, 0xb4baa117, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtj_37.13f", 0x020000, 0xa1f677b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtj_43.13h", 0x020000, 0x85337a47, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_34.10f", 0x020000, 0x054137c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_40.10h", 0x020000, 0x7264cb1b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtj_35.11f", 0x020000, 0xe72f9ea3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rtj_41.11h", 0x020000, 0xa11ee998, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "rt_09.4b", 0x020000, 0x2c40e480, BRF_GRA | CPS1_TILES }, + { "rt_01.4a", 0x020000, 0x3e11f8cd, BRF_GRA | CPS1_TILES }, + { "rt_13.9b", 0x020000, 0x51009117, BRF_GRA | CPS1_TILES }, + { "rt_05.9a", 0x020000, 0x283fd470, BRF_GRA | CPS1_TILES }, + { "rt_24.5e", 0x020000, 0xee4484ce, BRF_GRA | CPS1_TILES }, + { "rt_17.5c", 0x020000, 0xe5dcddeb, BRF_GRA | CPS1_TILES }, + { "rt_38.8h", 0x020000, 0xb2940c2d, BRF_GRA | CPS1_TILES }, + { "rt_32.8f", 0x020000, 0x08e2b758, BRF_GRA | CPS1_TILES }, + { "rt_10.5b", 0x020000, 0xe3f3ff94, BRF_GRA | CPS1_TILES }, + { "rt_02.5a", 0x020000, 0xfcffd73c, BRF_GRA | CPS1_TILES }, + { "rt_14.10b", 0x020000, 0x5c546d9a, BRF_GRA | CPS1_TILES }, + { "rt_06.10a", 0x020000, 0xd9650bc4, BRF_GRA | CPS1_TILES }, + { "rt_25.7e", 0x020000, 0x11b28831, BRF_GRA | CPS1_TILES }, + { "rt_18.7c", 0x020000, 0xce1afb7c, BRF_GRA | CPS1_TILES }, + { "rt_39.9h", 0x020000, 0xea7ac9ee, BRF_GRA | CPS1_TILES }, + { "rt_33.9f", 0x020000, 0xd6a99384, BRF_GRA | CPS1_TILES }, + { "rt_11.7b", 0x020000, 0x04f3c298, BRF_GRA | CPS1_TILES }, + { "rt_03.7a", 0x020000, 0x98087e08, BRF_GRA | CPS1_TILES }, + { "rt_15.11b", 0x020000, 0xb6aba565, BRF_GRA | CPS1_TILES }, + { "rt_07.11a", 0x020000, 0xc62defa1, BRF_GRA | CPS1_TILES }, + { "rt_26.8e", 0x020000, 0x532f542e, BRF_GRA | CPS1_TILES }, + { "rt_19.8c", 0x020000, 0x1f0f72bd, BRF_GRA | CPS1_TILES }, + { "rt_28.10e", 0x020000, 0x6064e499, BRF_GRA | CPS1_TILES }, + { "rt_21.10c", 0x020000, 0x20012ddc, BRF_GRA | CPS1_TILES }, + { "rt_12.8b", 0x020000, 0xe54664cc, BRF_GRA | CPS1_TILES }, + { "rt_04.8a", 0x020000, 0x4d7b9a1a, BRF_GRA | CPS1_TILES }, + { "rt_16.12b", 0x020000, 0x37c96cfc, BRF_GRA | CPS1_TILES }, + { "rt_08.12a", 0x020000, 0x75f4975b, BRF_GRA | CPS1_TILES }, + { "rt_27.9e", 0x020000, 0xec6edc0f, BRF_GRA | CPS1_TILES }, + { "rt_20.9c", 0x020000, 0x4fe52659, BRF_GRA | CPS1_TILES }, + { "rt_29.11e", 0x020000, 0x8fa77f9f, BRF_GRA | CPS1_TILES }, + { "rt_22.11c", 0x020000, 0x228a0d4a, BRF_GRA | CPS1_TILES }, + + { "rt_23.13b", 0x010000, 0xabfca165, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rt_30.12c", 0x020000, 0x26b211ab, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rt_31.13c", 0x020000, 0xdbe64ad0, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rt22b.1a", 0x000117, 0x89560d6a, BRF_OPT }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wonder3) +STD_ROM_FN(Wonder3) + +static struct BurnRomInfo Wonder3hRomDesc[] = { + { "22.bin", 0x020000, 0xe6071884, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "26.bin", 0x020000, 0xa28447b7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "23.bin", 0x020000, 0xfd3d6509, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27.bin", 0x020000, 0x999cba3d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_28a.9f", 0x020000, 0x054137c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rt_33a.9h", 0x020000, 0x7264cb1b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_29a.10f", 0x020000, 0xcddaa919, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "rte_34a.10h", 0x020000, 0xed52e7e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "16.bin", 0x040000, 0xc997bca2, BRF_GRA | CPS1_TILES }, + { "6.bin", 0x040000, 0x3eea321a, BRF_GRA | CPS1_TILES }, + { "18.bin", 0x040000, 0x98acdfd4, BRF_GRA | CPS1_TILES }, + { "8.bin", 0x040000, 0xdc9ca6f9, BRF_GRA | CPS1_TILES }, + { "12.bin", 0x040000, 0x0d8a6007, BRF_GRA | CPS1_TILES }, + { "2.bin", 0x040000, 0xd75563b9, BRF_GRA | CPS1_TILES }, + { "14.bin", 0x040000, 0x84369a28, BRF_GRA | CPS1_TILES }, + { "4.bin", 0x040000, 0xd4831578, BRF_GRA | CPS1_TILES }, + { "17.bin", 0x040000, 0x040edff5, BRF_GRA | CPS1_TILES }, + { "7.bin", 0x040000, 0xc7c0468c, BRF_GRA | CPS1_TILES }, + { "19.bin", 0x040000, 0x9fef114f, BRF_GRA | CPS1_TILES }, + { "9.bin", 0x040000, 0x48cbfba5, BRF_GRA | CPS1_TILES }, + { "13.bin", 0x040000, 0x8fc3d7d1, BRF_GRA | CPS1_TILES }, + { "3.bin", 0x040000, 0xc65e9a86, BRF_GRA | CPS1_TILES }, + { "15.bin", 0x040000, 0xf239341a, BRF_GRA | CPS1_TILES }, + { "5.bin", 0x040000, 0x947ac944, BRF_GRA | CPS1_TILES }, + + { "rt_9.12b", 0x010000, 0xabfca165, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rt_18.11c", 0x020000, 0x26b211ab, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rt_19.12c", 0x020000, 0xdbe64ad0, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rt24b.1a", 0x000117, 0x54b85159, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wonder3h) +STD_ROM_FN(Wonder3h) + +static struct BurnRomInfo CaptcommRomDesc[] = { + { "cce_23f.8f", 0x080000, 0x42c814c5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cc_22f.7f", 0x080000, 0x0fd34195, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cc_24f.9e", 0x020000, 0x3a794f25, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cc_28f.9f", 0x020000, 0xfc3c2906, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cc-5m.3a", 0x080000, 0x7261d8ba, BRF_GRA | CPS1_TILES }, + { "cc-7m.5a", 0x080000, 0x6a60f949, BRF_GRA | CPS1_TILES }, + { "cc-1m.4a", 0x080000, 0x00637302, BRF_GRA | CPS1_TILES }, + { "cc-3m.6a", 0x080000, 0xcc87cf61, BRF_GRA | CPS1_TILES }, + { "cc-6m.7a", 0x080000, 0x28718bed, BRF_GRA | CPS1_TILES }, + { "cc-8m.9a", 0x080000, 0xd4acc53a, BRF_GRA | CPS1_TILES }, + { "cc-2m.8a", 0x080000, 0x0c69f151, BRF_GRA | CPS1_TILES }, + { "cc-4m.10a", 0x080000, 0x1f9ebb97, BRF_GRA | CPS1_TILES }, + + { "cc_09.11a", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cc_18.11c", 0x020000, 0x6de2c2db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "cc_19.12c", 0x020000, 0xb99091ae, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cc63b.1a", 0x000117, 0xcae8f0f9, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ccprg1.11d", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632b.ic1", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(Captcomm) +STD_ROM_FN(Captcomm) + +static struct BurnRomInfo Captcommr1RomDesc[] = { + { "cce_23d.8f", 0x080000, 0x19c58ece, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cc_22d.7f", 0x080000, 0xa91949b7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cc_24d.9e", 0x020000, 0x680e543f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cc_28d.9f", 0x020000, 0x8820039f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cc-5m.3a", 0x080000, 0x7261d8ba, BRF_GRA | CPS1_TILES }, + { "cc-7m.5a", 0x080000, 0x6a60f949, BRF_GRA | CPS1_TILES }, + { "cc-1m.4a", 0x080000, 0x00637302, BRF_GRA | CPS1_TILES }, + { "cc-3m.6a", 0x080000, 0xcc87cf61, BRF_GRA | CPS1_TILES }, + { "cc-6m.7a", 0x080000, 0x28718bed, BRF_GRA | CPS1_TILES }, + { "cc-8m.9a", 0x080000, 0xd4acc53a, BRF_GRA | CPS1_TILES }, + { "cc-2m.8a", 0x080000, 0x0c69f151, BRF_GRA | CPS1_TILES }, + { "cc-4m.10a", 0x080000, 0x1f9ebb97, BRF_GRA | CPS1_TILES }, + + { "cc_09.11a", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cc_18.11c", 0x020000, 0x6de2c2db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "cc_19.12c", 0x020000, 0xb99091ae, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cc63b.1a", 0x000117, 0xcae8f0f9, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ccprg.11d", 0x000117, 0xe1c225c4, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Captcommr1) +STD_ROM_FN(Captcommr1) + +static struct BurnRomInfo CaptcommuRomDesc[] = { + { "ccu_23b.8f", 0x080000, 0x03da44fd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccu_22c.7f", 0x080000, 0x9b82a052, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccu_24b.9e", 0x020000, 0x84ff99b2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ccu_28b.9f", 0x020000, 0xfbcec223, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cc-5m.3a", 0x080000, 0x7261d8ba, BRF_GRA | CPS1_TILES }, + { "cc-7m.5a", 0x080000, 0x6a60f949, BRF_GRA | CPS1_TILES }, + { "cc-1m.4a", 0x080000, 0x00637302, BRF_GRA | CPS1_TILES }, + { "cc-3m.6a", 0x080000, 0xcc87cf61, BRF_GRA | CPS1_TILES }, + { "cc-6m.7a", 0x080000, 0x28718bed, BRF_GRA | CPS1_TILES }, + { "cc-8m.9a", 0x080000, 0xd4acc53a, BRF_GRA | CPS1_TILES }, + { "cc-2m.8a", 0x080000, 0x0c69f151, BRF_GRA | CPS1_TILES }, + { "cc-4m.10a", 0x080000, 0x1f9ebb97, BRF_GRA | CPS1_TILES }, + + { "ccu_09.11a", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ccu_18.11c", 0x020000, 0x6de2c2db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ccu_19.12c", 0x020000, 0xb99091ae, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cc63b.1a", 0x000117, 0xcae8f0f9, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ccprg.11d", 0x000117, 0xe1c225c4, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Captcommu) +STD_ROM_FN(Captcommu) + +static struct BurnRomInfo CaptcommjRomDesc[] = { + { "ccj_23f.8f", 0x080000, 0x5b482b62, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccj_22f.7f", 0x080000, 0x0fd34195, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccj_24f.9e", 0x020000, 0x3a794f25, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ccj_28f.9f", 0x020000, 0xfc3c2906, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cc_01.3a", 0x080000, 0x7261d8ba, BRF_GRA | CPS1_TILES }, + { "cc_02.4a", 0x080000, 0x6a60f949, BRF_GRA | CPS1_TILES }, + { "cc_03.5a", 0x080000, 0x00637302, BRF_GRA | CPS1_TILES }, + { "cc_04.6a", 0x080000, 0xcc87cf61, BRF_GRA | CPS1_TILES }, + { "cc_05.7a", 0x080000, 0x28718bed, BRF_GRA | CPS1_TILES }, + { "cc_06.8a", 0x080000, 0xd4acc53a, BRF_GRA | CPS1_TILES }, + { "cc_07.9a", 0x080000, 0x0c69f151, BRF_GRA | CPS1_TILES }, + { "cc_08.10a", 0x080000, 0x1f9ebb97, BRF_GRA | CPS1_TILES }, + + { "ccj_09.12a", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ccj_18.11c", 0x020000, 0x6de2c2db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ccj_19.12c", 0x020000, 0xb99091ae, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cc63b.1a", 0x000117, 0xcae8f0f9, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ccprg.11d", 0x000117, 0xe1c225c4, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Captcommj) +STD_ROM_FN(Captcommj) + +static struct BurnRomInfo Captcommjr1RomDesc[] = { + { "ccj_23b.8f", 0x080000, 0xe2a2d80e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccj_22c.7f", 0x080000, 0x9b82a052, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ccj_24b.9e", 0x020000, 0x84ff99b2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ccj_28b.9f", 0x020000, 0xfbcec223, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cc_01.3a", 0x080000, 0x7261d8ba, BRF_GRA | CPS1_TILES }, + { "cc_02.4a", 0x080000, 0x6a60f949, BRF_GRA | CPS1_TILES }, + { "cc_03.5a", 0x080000, 0x00637302, BRF_GRA | CPS1_TILES }, + { "cc_04.6a", 0x080000, 0xcc87cf61, BRF_GRA | CPS1_TILES }, + { "cc_05.7a", 0x080000, 0x28718bed, BRF_GRA | CPS1_TILES }, + { "cc_06.8a", 0x080000, 0xd4acc53a, BRF_GRA | CPS1_TILES }, + { "cc_07.9a", 0x080000, 0x0c69f151, BRF_GRA | CPS1_TILES }, + { "cc_08.10a", 0x080000, 0x1f9ebb97, BRF_GRA | CPS1_TILES }, + + { "ccj_09.12a", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ccj_18.11c", 0x020000, 0x6de2c2db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ccj_19.12c", 0x020000, 0xb99091ae, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cc63b.1a", 0x000117, 0xcae8f0f9, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ccprg.11d", 0x000117, 0xe1c225c4, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Captcommjr1) +STD_ROM_FN(Captcommjr1) + +static struct BurnRomInfo CaptcommbRomDesc[] = { + { "25.bin", 0x080000, 0xcb71ed7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27.bin", 0x080000, 0x47cb2e87, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "24.bin", 0x040000, 0x79794279, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "26.bin", 0x040000, 0xb01077ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "c91e-01.bin", 0x100000, 0xf863071c, BRF_GRA | CPS1_TILES }, + { "c91e-02.bin", 0x100000, 0x4b03c308, BRF_GRA | CPS1_TILES }, + { "c91e-03.bin", 0x100000, 0x3383ea96, BRF_GRA | CPS1_TILES }, + { "c91e-04.bin", 0x100000, 0xb8e1f4cf, BRF_GRA | CPS1_TILES }, + + { "l.bin", 0x010000, 0x698e8b58, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "c91e-05.bin", 0x040000, 0x096115fb, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Captcommb) +STD_ROM_FN(Captcommb) + +static struct BurnRomInfo CawingRomDesc[] = { + { "cae_30a.11f", 0x020000, 0x91fceacd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_35a.11h", 0x020000, 0x3ef03083, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_31a.12f", 0x020000, 0xe5b75caf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_36a.12h", 0x020000, 0xc73fd713, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ca-32m.8h", 0x080000, 0x0c4837d4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ca-5m.7a", 0x080000, 0x66d4cc37, BRF_GRA | CPS1_TILES }, + { "ca-7m.9a", 0x080000, 0xb6f896f2, BRF_GRA | CPS1_TILES }, + { "ca-1m.3a", 0x080000, 0x4d0620fd, BRF_GRA | CPS1_TILES }, + { "ca-3m.5a", 0x080000, 0x0b0341c3, BRF_GRA | CPS1_TILES }, + + { "ca_9.12b", 0x010000, 0x96fe7485, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ca_18.11c", 0x020000, 0x4a613a2c, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ca_19.12c", 0x020000, 0x74584493, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ca24b.1a", 0x000117, 0x76ec0b1c, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Cawing) +STD_ROM_FN(Cawing) + +static struct BurnRomInfo Cawingr1RomDesc[] = { + { "cae_30.11f", 0x020000, 0x23305cd5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_35.11h", 0x020000, 0x69419113, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_31.12f", 0x020000, 0x9008dfb3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cae_36.12h", 0x020000, 0x4dbf6f8e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ca-32m.8h", 0x080000, 0x0c4837d4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ca-5m.7a", 0x080000, 0x66d4cc37, BRF_GRA | CPS1_TILES }, + { "ca-7m.9a", 0x080000, 0xb6f896f2, BRF_GRA | CPS1_TILES }, + { "ca-1m.3a", 0x080000, 0x4d0620fd, BRF_GRA | CPS1_TILES }, + { "ca-3m.5a", 0x080000, 0x0b0341c3, BRF_GRA | CPS1_TILES }, + + { "cae_09.12b", 0x010000, 0x96fe7485, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cae_18.11c", 0x020000, 0x4a613a2c, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "cae_19.12c", 0x020000, 0x74584493, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ca24b.1a", 0x000117, 0x76ec0b1c, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Cawingr1) +STD_ROM_FN(Cawingr1) + +static struct BurnRomInfo CawinguRomDesc[] = { + { "cau_30a.11f", 0x020000, 0x91fceacd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cau_35a.11h", 0x020000, 0xf090d9b2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cau_31a.12f", 0x020000, 0xe5b75caf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cau_36a.12h", 0x020000, 0xc73fd713, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ca-32m.8h", 0x080000, 0x0c4837d4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ca-5m.7a", 0x080000, 0x66d4cc37, BRF_GRA | CPS1_TILES }, + { "ca-7m.9a", 0x080000, 0xb6f896f2, BRF_GRA | CPS1_TILES }, + { "ca-1m.3a", 0x080000, 0x4d0620fd, BRF_GRA | CPS1_TILES }, + { "ca-3m.5a", 0x080000, 0x0b0341c3, BRF_GRA | CPS1_TILES }, + + { "cau_09.12b", 0x010000, 0x96fe7485, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cau_18.11c", 0x020000, 0x4a613a2c, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "cau_19.12c", 0x020000, 0x74584493, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ca24b.1a", 0x000117, 0x76ec0b1c, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Cawingu) +STD_ROM_FN(Cawingu) + +static struct BurnRomInfo CawingjRomDesc[] = { + { "caj_36a.12f", 0x020000, 0x91fceacd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_42a.12h", 0x020000, 0x039f8362, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_37a.13f", 0x020000, 0xe5b75caf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_43a.13h", 0x020000, 0xc73fd713, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_34.10f", 0x020000, 0x51ea57f4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_40.10h", 0x020000, 0x2ab71ae1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_35.11f", 0x020000, 0x01d71973, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "caj_41.11h", 0x020000, 0x3a43b538, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "caj_09.4b", 0x020000, 0x41b0f9a6, BRF_GRA | CPS1_TILES }, + { "caj_01.4a", 0x020000, 0x1002d0b8, BRF_GRA | CPS1_TILES }, + { "caj_13.9b", 0x020000, 0x6f3948b2, BRF_GRA | CPS1_TILES }, + { "caj_05.9a", 0x020000, 0x207373d7, BRF_GRA | CPS1_TILES }, + { "caj_24.5e", 0x020000, 0xe356aad7, BRF_GRA | CPS1_TILES }, + { "caj_17.5c", 0x020000, 0x540f2fd8, BRF_GRA | CPS1_TILES }, + { "caj_38.8h", 0x020000, 0x2464d4ab, BRF_GRA | CPS1_TILES }, + { "caj_32.8f", 0x020000, 0x9b5836b3, BRF_GRA | CPS1_TILES }, + { "caj_10.5b", 0x020000, 0xbf8a5f52, BRF_GRA | CPS1_TILES }, + { "caj_02.5a", 0x020000, 0x125b018d, BRF_GRA | CPS1_TILES }, + { "caj_14.10b", 0x020000, 0x8458e7d7, BRF_GRA | CPS1_TILES }, + { "caj_06.10a", 0x020000, 0xcf80e164, BRF_GRA | CPS1_TILES }, + { "caj_25.7e", 0x020000, 0xcdd0204d, BRF_GRA | CPS1_TILES }, + { "caj_18.7c", 0x020000, 0x29c1d4b1, BRF_GRA | CPS1_TILES }, + { "caj_39.9h", 0x020000, 0xeea23b67, BRF_GRA | CPS1_TILES }, + { "caj_33.9f", 0x020000, 0xdde3891f, BRF_GRA | CPS1_TILES }, + + { "caj_23.13b", 0x010000, 0x96fe7485, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "caj_30.12c", 0x020000, 0x4a613a2c, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "caj_31.13c", 0x020000, 0x74584493, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ca22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Cawingj) +STD_ROM_FN(Cawingj) + +static struct BurnRomInfo CawingbRomDesc[] = { + { "2.16d", 0x080000, 0x8125d3f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // caw2 + { "1.19d", 0x080000, 0xb19b10ce, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // caw1 + +// { "ca-5m.7a", 0x080000, 0x66d4cc37, BRF_GRA | CPS1_TILES }, +// { "ca-7m.9a", 0x080000, 0xb6f896f2, BRF_GRA | CPS1_TILES }, +// { "ca-1m.3a", 0x080000, 0x4d0620fd, BRF_GRA | CPS1_TILES }, +// { "ca-3m.5a", 0x080000, 0x0b0341c3, BRF_GRA | CPS1_TILES }, + + { "caw5.bin", 0x080000, 0xa045c689, BRF_GRA | CPS1_TILES }, + { "caw7.bin", 0x080000, 0x30dd78db, BRF_GRA | CPS1_TILES }, + { "caw4.bin", 0x080000, 0x61192f7c, BRF_GRA | CPS1_TILES }, + { "caw6.bin", 0x080000, 0x4937fc41, BRF_GRA | CPS1_TILES }, + + { "cau_09.12b", 0x010000, 0x96fe7485, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ca_18.11c", 0x020000, 0x4a613a2c, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ca_19.12c", 0x020000, 0x74584493, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Cawingb) +STD_ROM_FN(Cawingb) + +static struct BurnRomInfo Cps1demoRomDesc[] = { + { "cd30-36.bin", 0x020000, 0x5eb617d6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cd35-42.bin", 0x020000, 0x1f1c0a62, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cd31-37.bin", 0x020000, 0x7ee8cdcd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // sound rom from cps1frog ? + { "cd36-43.bin", 0x020000, 0x7ee8cdcd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // sound rom from cps1frog ? + { "ff-32m.8h", 0x080000, 0xc747696e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd05-05m.bin", 0x080000, 0x35dc6153, BRF_GRA | CPS1_TILES }, + { "cd07-07m.bin", 0x080000, 0xbaf08a38, BRF_GRA | CPS1_TILES }, + { "cd01-01m.bin", 0x080000, 0x3ad8e790, BRF_GRA | CPS1_TILES }, + { "cd03-03m.bin", 0x080000, 0xfb5186f3, BRF_GRA | CPS1_TILES }, + + { "ff_09.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Cps1demo) +STD_ROM_FN(Cps1demo) + +static struct BurnRomInfo Cworld2jRomDesc[] = { + { "q5_36.12f", 0x020000, 0x38a08099, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_42.12h", 0x020000, 0x4d29b3a4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_37.13f", 0x020000, 0xeb547ebc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_43.13h", 0x020000, 0x3ef65ea8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_34.10f", 0x020000, 0x7fcc1317, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_40.10h", 0x020000, 0x7f14b7b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_35.11f", 0x020000, 0xabacee26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "q5_41.11h", 0x020000, 0xd3654067, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "q5_09.4b", 0x020000, 0x48496d80, BRF_GRA | CPS1_TILES }, + { "q5_01.4a", 0x020000, 0xc5453f56, BRF_GRA | CPS1_TILES }, + { "q5_13.9b", 0x020000, 0xc741ac52, BRF_GRA | CPS1_TILES }, + { "q5_05.9a", 0x020000, 0x143e068f, BRF_GRA | CPS1_TILES }, + { "q5_24.5e", 0x020000, 0xb419d139, BRF_GRA | CPS1_TILES }, + { "q5_17.5c", 0x020000, 0xbd3b4d11, BRF_GRA | CPS1_TILES }, + { "q5_38.8h", 0x020000, 0x9c24670c, BRF_GRA | CPS1_TILES }, + { "q5_32.8f", 0x020000, 0x3ef9c7c2, BRF_GRA | CPS1_TILES }, + { "q5_10.5b", 0x020000, 0x119e5e93, BRF_GRA | CPS1_TILES }, + { "q5_02.5a", 0x020000, 0xa2cadcbe, BRF_GRA | CPS1_TILES }, + { "q5_14.10b", 0x020000, 0xa8755f82, BRF_GRA | CPS1_TILES }, + { "q5_06.10a", 0x020000, 0xc92a91fc, BRF_GRA | CPS1_TILES }, + { "q5_25.7e", 0x020000, 0x979237cb, BRF_GRA | CPS1_TILES }, + { "q5_18.7c", 0x020000, 0xc57da03c, BRF_GRA | CPS1_TILES }, + { "q5_39.9h", 0x020000, 0xa5839b25, BRF_GRA | CPS1_TILES }, + { "q5_33.9f", 0x020000, 0x04d03930, BRF_GRA | CPS1_TILES }, + + { "q5_23.13b", 0x010000, 0xe14dc524, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "q5_30.12c", 0x020000, 0xd10c1b68, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "q5_31.13c", 0x020000, 0x7d17e496, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "q522b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "lwio.12e", 0x000117, 0xad52b90c, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Cworld2j) +STD_ROM_FN(Cworld2j) + +static struct BurnRomInfo DinoRomDesc[] = { + { "cde_23a.8f", 0x080000, 0x8f4e585e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cde_22a.7f", 0x080000, 0x9278aa12, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cde_21a.6f", 0x080000, 0x66d23de2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd-1m.3a", 0x080000, 0x8da4f917, BRF_GRA | CPS1_TILES }, + { "cd-3m.5a", 0x080000, 0x6c40f603, BRF_GRA | CPS1_TILES }, + { "cd-2m.4a", 0x080000, 0x09c8fc2d, BRF_GRA | CPS1_TILES }, + { "cd-4m.6a", 0x080000, 0x637ff38f, BRF_GRA | CPS1_TILES }, + { "cd-5m.7a", 0x080000, 0x470befee, BRF_GRA | CPS1_TILES }, + { "cd-7m.9a", 0x080000, 0x22bfb7a3, BRF_GRA | CPS1_TILES }, + { "cd-6m.8a", 0x080000, 0xe7599ac4, BRF_GRA | CPS1_TILES }, + { "cd-8m.10a", 0x080000, 0x211b4b15, BRF_GRA | CPS1_TILES }, + + { "cd_q.5k", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd-q1.1k", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q2.2k", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q3.3k", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q4.4k", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "cd63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(Dino) +STD_ROM_FN(Dino) + +static struct BurnRomInfo DinojRomDesc[] = { + { "cdj-23a.8f", 0x080000, 0x5f3ece96, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cdj-22a.7f", 0x080000, 0xa0d8de29, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cde_21a.rom", 0x080000, 0x66d23de2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd_gfx01.rom", 0x080000, 0x8da4f917, BRF_GRA | CPS1_TILES }, + { "cd_gfx03.rom", 0x080000, 0x6c40f603, BRF_GRA | CPS1_TILES }, + { "cd_gfx02.rom", 0x080000, 0x09c8fc2d, BRF_GRA | CPS1_TILES }, + { "cd_gfx04.rom", 0x080000, 0x637ff38f, BRF_GRA | CPS1_TILES }, + { "cd_gfx05.rom", 0x080000, 0x470befee, BRF_GRA | CPS1_TILES }, + { "cd_gfx07.rom", 0x080000, 0x22bfb7a3, BRF_GRA | CPS1_TILES }, + { "cd_gfx06.rom", 0x080000, 0xe7599ac4, BRF_GRA | CPS1_TILES }, + { "cd_gfx08.rom", 0x080000, 0x211b4b15, BRF_GRA | CPS1_TILES }, + + { "cd_q.rom", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd_q1.rom", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q2.rom", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q3.rom", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q4.rom", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "cd63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Dinoj) +STD_ROM_FN(Dinoj) + +static struct BurnRomInfo DinouRomDesc[] = { + { "cdu_23a.8f", 0x080000, 0x7c2543cd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cdu_22a.7f", 0x080000, 0xfab740a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cdu_21a.6f", 0x080000, 0x66d23de2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd-1m.3a", 0x080000, 0x8da4f917, BRF_GRA | CPS1_TILES }, + { "cd-3m.5a", 0x080000, 0x6c40f603, BRF_GRA | CPS1_TILES }, + { "cd-2m.4a", 0x080000, 0x09c8fc2d, BRF_GRA | CPS1_TILES }, + { "cd-4m.6a", 0x080000, 0x637ff38f, BRF_GRA | CPS1_TILES }, + { "cd-5m.7a", 0x080000, 0x470befee, BRF_GRA | CPS1_TILES }, + { "cd-7m.9a", 0x080000, 0x22bfb7a3, BRF_GRA | CPS1_TILES }, + { "cd-6m.8a", 0x080000, 0xe7599ac4, BRF_GRA | CPS1_TILES }, + { "cd-8m.10a", 0x080000, 0x211b4b15, BRF_GRA | CPS1_TILES }, + + { "cd_q.5k", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd-q1.1k", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q2.2k", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q3.3k", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd-q4.4k", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "cd63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(Dinou) +STD_ROM_FN(Dinou) + +static struct BurnRomInfo DinopicRomDesc[] = { + { "5.bin", 0x080000, 0x96dfcbf1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "3.bin", 0x080000, 0x13dfeb08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "7.bin", 0x080000, 0x6133f349, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "2.bin", 0x080000, 0x0e4058ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "4.bin", 0x080000, 0xf3c2c98d, BRF_GRA | CPS1_TILES }, + { "8.bin", 0x080000, 0xd574befc, BRF_GRA | CPS1_TILES }, + { "9.bin", 0x080000, 0x55ef0adc, BRF_GRA | CPS1_TILES }, + { "6.bin", 0x080000, 0xcc0805fc, BRF_GRA | CPS1_TILES }, + { "13.bin", 0x080000, 0x1371f714, BRF_GRA | CPS1_TILES }, + { "12.bin", 0x080000, 0xb284c4a7, BRF_GRA | CPS1_TILES }, + { "11.bin", 0x080000, 0xb7ad3394, BRF_GRA | CPS1_TILES }, + { "10.bin", 0x080000, 0x88847705, BRF_GRA | CPS1_TILES }, + + { "pic16c57-rp", 0x002d4c, 0x5a6d393c, BRF_PRG | CPS1_PIC }, + + { "1.bin", 0x080000, 0x7d921309, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Dinopic) +STD_ROM_FN(Dinopic) + +static struct BurnRomInfo Dinopic2RomDesc[] = { + { "27c4000-m12481.bin", 0x080000, 0x96dfcbf1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27c4000-m12374r-2.bin", 0x080000, 0x13dfeb08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27c4000-m12374r-3.bin", 0x080000, 0x6133f349, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27c4000-m12374r-1.bin", 0x080000, 0x0e4058ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "27c4000-m12481-4.bin", 0x080000, 0xf3c2c98d, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-3.bin", 0x080000, 0x417a4816, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-2.bin", 0x080000, 0x55ef0adc, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-1.bin", 0x080000, 0xcc0805fc, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-8.bin", 0x080000, 0x1371f714, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-7.bin", 0x080000, 0xb284c4a7, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-6.bin", 0x080000, 0xb7ad3394, BRF_GRA | CPS1_TILES }, + { "27c4000-m12481-5.bin", 0x080000, 0x88847705, BRF_GRA | CPS1_TILES }, + + { "pic16c57-xt.hex", 0x0026cc, 0xa6a5eac4, BRF_PRG | CPS1_PIC }, + + { "27c4000-m12623.bin", 0x080000, 0x7d921309, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + { "cat93c46p.bin", 0x000080, 0xd49fa351, BRF_OPT }, + { "gal20v8a-1.bin", 0x000157, 0xcd99ca47, BRF_OPT }, + { "gal20v8a-2.bin", 0x000157, 0x60d016b9, BRF_OPT }, + { "gal20v8a-3.bin", 0x000157, 0x049b7f4f, BRF_OPT }, + { "palce16v8h-1.bin", 0x000117, 0x48253c66, BRF_OPT }, + { "palce16v8h-2.bin", 0x000117, 0x9ae375ba, BRF_OPT }, +}; + +STD_ROM_PICK(Dinopic2) +STD_ROM_FN(Dinopic2) + +static struct BurnRomInfo DinoehRomDesc[] = { + { "dinoeh.23", 0x080000, 0xa6b88364, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cde_22a.rom", 0x080000, 0x9278aa12, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "dinoeh.21", 0x080000, 0xb89a0548, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd_gfx01.rom", 0x080000, 0x8da4f917, BRF_GRA | CPS1_TILES }, + { "cd_gfx03.rom", 0x080000, 0x6c40f603, BRF_GRA | CPS1_TILES }, + { "cd_gfx02.rom", 0x080000, 0x09c8fc2d, BRF_GRA | CPS1_TILES }, + { "cd_gfx04.rom", 0x080000, 0x637ff38f, BRF_GRA | CPS1_TILES }, + { "cd_gfx05.rom", 0x080000, 0x470befee, BRF_GRA | CPS1_TILES }, + { "cd_gfx07.rom", 0x080000, 0x22bfb7a3, BRF_GRA | CPS1_TILES }, + { "cd_gfx06.rom", 0x080000, 0xe7599ac4, BRF_GRA | CPS1_TILES }, + { "cd_gfx08.rom", 0x080000, 0x211b4b15, BRF_GRA | CPS1_TILES }, + + { "cd_q.rom", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd_q1.rom", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q2.rom", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q3.rom", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q4.rom", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Dinoeh) +STD_ROM_FN(Dinoeh) + +static struct BurnRomInfo DinohRomDesc[] = { + { "cda_23h.rom", 0x080000, 0x8e2a9cf0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cda_22h.rom", 0x080000, 0xf72cd219, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cda_21h.rom", 0x080000, 0xbc275b76, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cda_20h.rom", 0x080000, 0x8987c975, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd_gfx01.rom", 0x080000, 0x8da4f917, BRF_GRA | CPS1_TILES }, + { "cd_gfx03.rom", 0x080000, 0x6c40f603, BRF_GRA | CPS1_TILES }, + { "cd_gfx02.rom", 0x080000, 0x09c8fc2d, BRF_GRA | CPS1_TILES }, + { "cd_gfx04.rom", 0x080000, 0x637ff38f, BRF_GRA | CPS1_TILES }, + { "cd_gfx05.rom", 0x080000, 0x470befee, BRF_GRA | CPS1_TILES }, + { "cd_gfx07.rom", 0x080000, 0x22bfb7a3, BRF_GRA | CPS1_TILES }, + { "cd_gfx06.rom", 0x080000, 0xe7599ac4, BRF_GRA | CPS1_TILES }, + { "cd_gfx08.rom", 0x080000, 0x211b4b15, BRF_GRA | CPS1_TILES }, + + // This doesn't work at all without the Q-Sound data present - does it really use Q-Sound?? + + { "cd_q.rom", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd_q1.rom", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q2.rom", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q3.rom", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q4.rom", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Dinoh) +STD_ROM_FN(Dinoh) + +static struct BurnRomInfo DinohaRomDesc[] = { + { "kl2-r1.800", 0x100000, 0x4c70dca7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "kl2-l2.800", 0x100000, 0xc6ae7338, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd-a.160", 0x200000, 0x7e4f9fb3, BRF_GRA | CPS1_TILES }, + { "cd-b.160", 0x200000, 0x89532d85, BRF_GRA | CPS1_TILES }, + + { "cd_q.rom", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd_q1.rom", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q2.rom", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q3.rom", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q4.rom", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Dinoha) +STD_ROM_FN(Dinoha) + +static struct BurnRomInfo DinohbRomDesc[] = { + { "cd-d.800", 0x100000, 0x2a7b2915, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "cd-e.800", 0x100000, 0xe8370226, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd-a.160", 0x200000, 0x7e4f9fb3, BRF_GRA | CPS1_TILES }, + { "cd-b.160", 0x200000, 0x89532d85, BRF_GRA | CPS1_TILES }, +}; + +STD_ROM_PICK(Dinohb) +STD_ROM_FN(Dinohb) + +static struct BurnRomInfo DinohuntRomDesc[] = { + { "u23", 0x080000, 0x8d5ddc5d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "u22", 0x080000, 0xf72cd219, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "u21", 0x080000, 0xbc275b76, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "u20", 0x080000, 0x8987c975, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "u1", 0x080000, 0xa01a9fb5, BRF_GRA | CPS1_TILES }, + { "u2", 0x080000, 0xbdf02c17, BRF_GRA | CPS1_TILES }, + { "u3", 0x080000, 0x058beefa, BRF_GRA | CPS1_TILES }, + { "u4", 0x080000, 0x5028a9f1, BRF_GRA | CPS1_TILES }, + { "u5", 0x080000, 0xd77f89ea, BRF_GRA | CPS1_TILES }, + { "u6", 0x080000, 0xbfbcb034, BRF_GRA | CPS1_TILES }, + { "u7", 0x080000, 0xa2544d4e, BRF_GRA | CPS1_TILES }, + { "u8", 0x080000, 0x8869bbb1, BRF_GRA | CPS1_TILES }, + + { "u9", 0x010000, 0x2eb16a83, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "u18", 0x020000, 0x8d2899ba, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "u19", 0x020000, 0xb34a4b42, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Dinohunt) +STD_ROM_FN(Dinohunt) + +static struct BurnRomInfo DynwarRomDesc[] = { + { "30.11f", 0x020000, 0xf9ec6d68, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.11h", 0x020000, 0xe41fff2f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "31.12f", 0x020000, 0xe3de76ff, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "36.12h", 0x020000, 0x7a13cfbf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tkm-9.8h", 0x080000, 0x93654bcf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tkm-5.7a", 0x080000, 0xf64bb6a0, BRF_GRA | CPS1_TILES }, + { "tkm-8.9a", 0x080000, 0x21fe6274, BRF_GRA | CPS1_TILES }, + { "tkm-6.3a", 0x080000, 0x0bf228cb, BRF_GRA | CPS1_TILES }, + { "tkm-7.5a", 0x080000, 0x1255dfb1, BRF_GRA | CPS1_TILES }, + { "tkm-1.8a", 0x080000, 0x44f7661e, BRF_GRA | CPS1_TILES }, + { "tkm-4.10a", 0x080000, 0xa54c515d, BRF_GRA | CPS1_TILES }, + { "tkm-2.4a", 0x080000, 0xca5c687c, BRF_GRA | CPS1_TILES }, + { "tkm-3.6a", 0x080000, 0xf9fe6591, BRF_GRA | CPS1_TILES }, + + { "tke_17.12b", 0x010000, 0xb3b79d4f, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tke_18.11c", 0x020000, 0xac6e307d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "tke_19.12c", 0x020000, 0x068741db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "tk24b1.1a", 0x000117, 0xae4a7645, BRF_OPT}, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Dynwar) +STD_ROM_FN(Dynwar) + +static struct BurnRomInfo DynwaraRomDesc[] = { + { "tke_36.12f", 0x020000, 0x895991d1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tke_42.12h", 0x020000, 0xc898d2e8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tke_37.13f", 0x020000, 0xb228d58c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tke_43.13h", 0x020000, 0x1a14375a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "34.10f", 0x020000, 0x8f663d00, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "40.10h", 0x020000, 0x1586dbf3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.11f", 0x020000, 0x9db93d7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41.11h", 0x020000, 0x1aae69a4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "09.4b", 0x020000, 0xc3e83c69, BRF_GRA | CPS1_TILES }, + { "01.4a", 0x020000, 0x187b2886, BRF_GRA | CPS1_TILES }, + { "13.9b", 0x020000, 0x0273d87d, BRF_GRA | CPS1_TILES }, + { "05.9a", 0x020000, 0x339378b8, BRF_GRA | CPS1_TILES }, + { "24.5e", 0x020000, 0xc6909b6f, BRF_GRA | CPS1_TILES }, + { "17.5c", 0x020000, 0x2e2f8320, BRF_GRA | CPS1_TILES }, + { "38.8h", 0x020000, 0xcd7923ed, BRF_GRA | CPS1_TILES }, + { "32.8f", 0x020000, 0x21a0a453, BRF_GRA | CPS1_TILES }, + { "10.5b", 0x020000, 0xff28f8d0, BRF_GRA | CPS1_TILES }, + { "02.5a", 0x020000, 0xcc83c02f, BRF_GRA | CPS1_TILES }, + { "14.10b", 0x020000, 0x58d9b32f, BRF_GRA | CPS1_TILES }, + { "06.10a", 0x020000, 0x6f9edd75, BRF_GRA | CPS1_TILES }, + { "25.7e", 0x020000, 0x152ea74a, BRF_GRA | CPS1_TILES }, + { "18.7c", 0x020000, 0x1833f932, BRF_GRA | CPS1_TILES }, + { "39.9h", 0x020000, 0xbc09b360, BRF_GRA | CPS1_TILES }, + { "33.9f", 0x020000, 0x89de1533, BRF_GRA | CPS1_TILES }, + { "11.7b", 0x020000, 0x29eaf490, BRF_GRA | CPS1_TILES }, + { "03.7a", 0x020000, 0x7bf51337, BRF_GRA | CPS1_TILES }, + { "15.11b", 0x020000, 0xd36cdb91, BRF_GRA | CPS1_TILES }, + { "07.11a", 0x020000, 0xe04af054, BRF_GRA | CPS1_TILES }, + { "26.8e", 0x020000, 0x07fc714b, BRF_GRA | CPS1_TILES }, + { "19.8c", 0x020000, 0x7114e5c6, BRF_GRA | CPS1_TILES }, + { "28.10e", 0x020000, 0xaf62bf07, BRF_GRA | CPS1_TILES }, + { "21.10c", 0x020000, 0x523f462a, BRF_GRA | CPS1_TILES }, + { "12.8b", 0x020000, 0x38652339, BRF_GRA | CPS1_TILES }, + { "04.8a", 0x020000, 0x4951bc0f, BRF_GRA | CPS1_TILES }, + { "16.12b", 0x020000, 0x381608ae, BRF_GRA | CPS1_TILES }, + { "08.12a", 0x020000, 0xb475d4e9, BRF_GRA | CPS1_TILES }, + { "27.9e", 0x020000, 0xa27e81fa, BRF_GRA | CPS1_TILES }, + { "20.9c", 0x020000, 0x002796dc, BRF_GRA | CPS1_TILES }, + { "29.11e", 0x020000, 0x6b41f82d, BRF_GRA | CPS1_TILES }, + { "22.11c", 0x020000, 0x52145369, BRF_GRA | CPS1_TILES }, + + { "23.13c", 0x010000, 0xb3b79d4f, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tke_30.12e", 0x020000, 0xac6e307d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "tke_31.13e", 0x020000, 0x068741db, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "tk22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Dynwara) +STD_ROM_FN(Dynwara) + +static struct BurnRomInfo DynwarjRomDesc[] = { + { "36.12f", 0x020000, 0x1a516657, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "42.12h", 0x020000, 0x12a290a0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "37.13f", 0x020000, 0x932fc943, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "43.13h", 0x020000, 0x872ad76d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "34.10f", 0x020000, 0x8f663d00, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "40.10h", 0x020000, 0x1586dbf3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.11f", 0x020000, 0x9db93d7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "41.11h", 0x020000, 0x1aae69a4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "09.4b", 0x020000, 0xc3e83c69, BRF_GRA | CPS1_TILES }, + { "01.4a", 0x020000, 0x187b2886, BRF_GRA | CPS1_TILES }, + { "13.9b", 0x020000, 0x0273d87d, BRF_GRA | CPS1_TILES }, + { "05.9a", 0x020000, 0x339378b8, BRF_GRA | CPS1_TILES }, + { "24.5e", 0x020000, 0xc6909b6f, BRF_GRA | CPS1_TILES }, + { "17.5c", 0x020000, 0x2e2f8320, BRF_GRA | CPS1_TILES }, + { "38.8h", 0x020000, 0xcd7923ed, BRF_GRA | CPS1_TILES }, + { "32.8f", 0x020000, 0x21a0a453, BRF_GRA | CPS1_TILES }, + { "10.5b", 0x020000, 0xff28f8d0, BRF_GRA | CPS1_TILES }, + { "02.5a", 0x020000, 0xcc83c02f, BRF_GRA | CPS1_TILES }, + { "14.10b", 0x020000, 0x58d9b32f, BRF_GRA | CPS1_TILES }, + { "06.10a", 0x020000, 0x6f9edd75, BRF_GRA | CPS1_TILES }, + { "25.7e", 0x020000, 0x152ea74a, BRF_GRA | CPS1_TILES }, + { "18.7c", 0x020000, 0x1833f932, BRF_GRA | CPS1_TILES }, + { "39.9h", 0x020000, 0xbc09b360, BRF_GRA | CPS1_TILES }, + { "33.9f", 0x020000, 0x89de1533, BRF_GRA | CPS1_TILES }, + { "11.7b", 0x020000, 0x29eaf490, BRF_GRA | CPS1_TILES }, + { "03.7a", 0x020000, 0x7bf51337, BRF_GRA | CPS1_TILES }, + { "15.11b", 0x020000, 0xd36cdb91, BRF_GRA | CPS1_TILES }, + { "07.11a", 0x020000, 0xe04af054, BRF_GRA | CPS1_TILES }, + { "26.8e", 0x020000, 0x07fc714b, BRF_GRA | CPS1_TILES }, + { "19.8c", 0x020000, 0x7114e5c6, BRF_GRA | CPS1_TILES }, + { "28.10e", 0x020000, 0xaf62bf07, BRF_GRA | CPS1_TILES }, + { "21.10c", 0x020000, 0x523f462a, BRF_GRA | CPS1_TILES }, + { "12.8b", 0x020000, 0x38652339, BRF_GRA | CPS1_TILES }, + { "04.8a", 0x020000, 0x4951bc0f, BRF_GRA | CPS1_TILES }, + { "16.12b", 0x020000, 0x381608ae, BRF_GRA | CPS1_TILES }, + { "08.12a", 0x020000, 0xb475d4e9, BRF_GRA | CPS1_TILES }, + { "27.9e", 0x020000, 0xa27e81fa, BRF_GRA | CPS1_TILES }, + { "20.9c", 0x020000, 0x002796dc, BRF_GRA | CPS1_TILES }, + { "29.11e", 0x020000, 0x6b41f82d, BRF_GRA | CPS1_TILES }, + { "22.11c", 0x020000, 0x52145369, BRF_GRA | CPS1_TILES }, + + { "23.13c", 0x010000, 0xb3b79d4f, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "30.12e", 0x020000, 0x7e5f6cb4, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "31.13e", 0x020000, 0x4a30c737, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "tk22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Dynwarj) +STD_ROM_FN(Dynwarj) + +static struct BurnRomInfo DynwarjrRomDesc[] = { + { "tk1j_23.8f", 0x080000, 0x088a3009, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk1j_22.7f", 0x080000, 0x93654bcf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk1_01.3a", 0x080000, 0xf64bb6a0, BRF_GRA | CPS1_TILES }, + { "tk1_02.4a", 0x080000, 0x21fe6274, BRF_GRA | CPS1_TILES }, + { "tk1_03.5a", 0x080000, 0x0bf228cb, BRF_GRA | CPS1_TILES }, + { "tk1_04.6a", 0x080000, 0x1255dfb1, BRF_GRA | CPS1_TILES }, + { "tk1_05.7a", 0x080000, 0x44f7661e, BRF_GRA | CPS1_TILES }, + { "tk1_06.8a", 0x080000, 0xa54c515d, BRF_GRA | CPS1_TILES }, + { "tk1_07.9a", 0x080000, 0xca5c687c, BRF_GRA | CPS1_TILES }, + { "tk1_08.10a", 0x080000, 0xf9fe6591, BRF_GRA | CPS1_TILES }, + + { "tk1_09.12a", 0x020000, 0xdb77d899, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk1_18.11c", 0x020000, 0x7e5f6cb4, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "tk1_19.12c", 0x020000, 0x4a30c737, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "tk163b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Dynwarjr) +STD_ROM_FN(Dynwarjr) + +static struct BurnRomInfo FfightRomDesc[] = { + { "ff_36.11f", 0x020000, 0xf9a5ce83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_42.11h", 0x020000, 0x65f11215, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_37.12f", 0x020000, 0xe1033784, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffe_43.12h", 0x020000, 0x995e968a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff-32m.8h", 0x080000, 0xc747696e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ff-5m.7a", 0x080000, 0x9c284108, BRF_GRA | CPS1_TILES }, + { "ff-7m.9a", 0x080000, 0xa7584dfb, BRF_GRA | CPS1_TILES }, + { "ff-1m.3a", 0x080000, 0x0b605e44, BRF_GRA | CPS1_TILES }, + { "ff-3m.5a", 0x080000, 0x52291cd2, BRF_GRA | CPS1_TILES }, + + { "ff_09.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s224b.1a", 0x000117, 0x4e85b158, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Ffight) +STD_ROM_FN(Ffight) + +static struct BurnRomInfo FfightuRomDesc[] = { + { "ff_36.11f", 0x020000, 0xf9a5ce83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_42.11h", 0x020000, 0x65f11215, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_37.12f", 0x020000, 0xe1033784, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_43.12h", 0x020000, 0x4ca65947, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff-32m.8h", 0x080000, 0xc747696e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ff-5m.7a", 0x080000, 0x9c284108, BRF_GRA | CPS1_TILES }, + { "ff-7m.9a", 0x080000, 0xa7584dfb, BRF_GRA | CPS1_TILES }, + { "ff-1m.3a", 0x080000, 0x0b605e44, BRF_GRA | CPS1_TILES }, + { "ff-3m.5a", 0x080000, 0x52291cd2, BRF_GRA | CPS1_TILES }, + + { "ff_09.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s224b.1a", 0x000117, 0x4e85b158, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightu) +STD_ROM_FN(Ffightu) + +static struct BurnRomInfo Ffightu1RomDesc[] = { + { "ff_36.11f", 0x020000, 0xf9a5ce83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_42.11h", 0x020000, 0x65f11215, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_37.12f", 0x020000, 0xe1033784, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_43.12h", 0x020000, 0x4ca65947, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_34.9f", 0x020000, 0x0c8dc3fc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_40.9h", 0x020000, 0x8075bab9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_35.10f", 0x020000, 0x4a934121, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff_41.10h", 0x020000, 0x2af68154, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ff-5m.7a", 0x080000, 0x9c284108, BRF_GRA | CPS1_TILES }, + { "ff-7m.9a", 0x080000, 0xa7584dfb, BRF_GRA | CPS1_TILES }, + { "ff-1m.3a", 0x080000, 0x0b605e44, BRF_GRA | CPS1_TILES }, + { "ff-3m.5a", 0x080000, 0x52291cd2, BRF_GRA | CPS1_TILES }, + + { "ff_09.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s224b.1a", 0x000117, 0x4e85b158, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightu1) +STD_ROM_FN(Ffightu1) + +static struct BurnRomInfo FfightuaRomDesc[] = { + { "ffu_36.11f", 0x020000, 0xe2a48af9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_42.11h", 0x020000, 0xf4bb480e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_37.12f", 0x020000, 0xc371c667, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_43.36", 0x020000, 0x2f5771f9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff-32m.8h", 0x080000, 0xc747696e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ff-5m.7a", 0x080000, 0x9c284108, BRF_GRA | CPS1_TILES }, + { "ff-7m.9a", 0x080000, 0xa7584dfb, BRF_GRA | CPS1_TILES }, + { "ff-1m.3a", 0x080000, 0x0b605e44, BRF_GRA | CPS1_TILES }, + { "ff-3m.5a", 0x080000, 0x52291cd2, BRF_GRA | CPS1_TILES }, + + { "ff_09.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s224b.1a", 0x000117, 0x4e85b158, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightua) +STD_ROM_FN(Ffightua) + +static struct BurnRomInfo FfightubRomDesc[] = { + { "ffu_30.11f", 0x020000, 0xed988977, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_35.11h", 0x020000, 0x07bf1c21, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_31.12f", 0x020000, 0xdba5a476, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffu_36.12h", 0x020000, 0x4d89f542, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff-32m.8h", 0x080000, 0xc747696e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ff-5m.7a", 0x080000, 0x9c284108, BRF_GRA | CPS1_TILES }, + { "ff-7m.9a", 0x080000, 0xa7584dfb, BRF_GRA | CPS1_TILES }, + { "ff-1m.3a", 0x080000, 0x0b605e44, BRF_GRA | CPS1_TILES }, + { "ff-3m.5a", 0x080000, 0x52291cd2, BRF_GRA | CPS1_TILES }, + + { "ff_23.12b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s224b.1a", 0x000117, 0x4e85b158, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightub) +STD_ROM_FN(Ffightub) + +static struct BurnRomInfo FfightjRomDesc[] = { + { "ff36.bin", 0x020000, 0xf9a5ce83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff42.bin", 0x020000, 0x65f11215, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff37.bin", 0x020000, 0xe1033784, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff43.bin", 0x020000, 0xb6dee1c3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_34.10f", 0x020000, 0x0c8dc3fc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_40.10h", 0x020000, 0x8075bab9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_35.11f", 0x020000, 0x4a934121, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_41.11h", 0x020000, 0x2af68154, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ffj_09.4b", 0x020000, 0x5b116d0d, BRF_GRA | CPS1_TILES }, + { "ffj_01.4a", 0x020000, 0x815b1797, BRF_GRA | CPS1_TILES }, + { "ffj_13.9b", 0x020000, 0x8721a7da, BRF_GRA | CPS1_TILES }, + { "ffj_05.9a", 0x020000, 0xd0fcd4b5, BRF_GRA | CPS1_TILES }, + { "ffj_24.5e", 0x020000, 0xa1ab607a, BRF_GRA | CPS1_TILES }, + { "ffj_17.5c", 0x020000, 0x2dc18cf4, BRF_GRA | CPS1_TILES }, + { "ffj_38.8h", 0x020000, 0x6535a57f, BRF_GRA | CPS1_TILES }, + { "ffj_32.8f", 0x020000, 0xc8bc4a57, BRF_GRA | CPS1_TILES }, + { "ffj_10.5b", 0x020000, 0x624a924a, BRF_GRA | CPS1_TILES }, + { "ffj_02.5a", 0x020000, 0x5d91f694, BRF_GRA | CPS1_TILES }, + { "ffj_14.10b", 0x020000, 0x0a2e9101, BRF_GRA | CPS1_TILES }, + { "ffj_06.10a", 0x020000, 0x1c18f042, BRF_GRA | CPS1_TILES }, + { "ffj_25.7e", 0x020000, 0x6e8181ea, BRF_GRA | CPS1_TILES }, + { "ffj_18.7c", 0x020000, 0xb19ede59, BRF_GRA | CPS1_TILES }, + { "ffj_39.9h", 0x020000, 0x9416b477, BRF_GRA | CPS1_TILES }, + { "ffj_33.9f", 0x020000, 0x7369fa07, BRF_GRA | CPS1_TILES }, + + { "ff_23.bin", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ffj_30.bin", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ffj_31.bin", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s222b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightj) +STD_ROM_FN(Ffightj) + +static struct BurnRomInfo Ffightj1RomDesc[] = { + { "ffj_36.12f", 0x020000, 0xe2a48af9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_42.12h", 0x020000, 0xf4bb480e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_37.13f", 0x020000, 0xc371c667, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_43.13h", 0x020000, 0x6f81f194, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_34.10f", 0x020000, 0x0c8dc3fc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_40.10h", 0x020000, 0x8075bab9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_35.11f", 0x020000, 0x4a934121, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_41.11h", 0x020000, 0x2af68154, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ffj_09.4b", 0x020000, 0x5b116d0d, BRF_GRA | CPS1_TILES }, + { "ffj_01.4a", 0x020000, 0x815b1797, BRF_GRA | CPS1_TILES }, + { "ffj_13.9b", 0x020000, 0x8721a7da, BRF_GRA | CPS1_TILES }, + { "ffj_05.9a", 0x020000, 0xd0fcd4b5, BRF_GRA | CPS1_TILES }, + { "ffj_24.5e", 0x020000, 0xa1ab607a, BRF_GRA | CPS1_TILES }, + { "ffj_17.5c", 0x020000, 0x2dc18cf4, BRF_GRA | CPS1_TILES }, + { "ffj_38.8h", 0x020000, 0x6535a57f, BRF_GRA | CPS1_TILES }, + { "ffj_32.8f", 0x020000, 0xc8bc4a57, BRF_GRA | CPS1_TILES }, + { "ffj_10.5b", 0x020000, 0x624a924a, BRF_GRA | CPS1_TILES }, + { "ffj_02.5a", 0x020000, 0x5d91f694, BRF_GRA | CPS1_TILES }, + { "ffj_14.10b", 0x020000, 0x0a2e9101, BRF_GRA | CPS1_TILES }, + { "ffj_06.10a", 0x020000, 0x1c18f042, BRF_GRA | CPS1_TILES }, + { "ffj_25.7e", 0x020000, 0x6e8181ea, BRF_GRA | CPS1_TILES }, + { "ffj_18.7c", 0x020000, 0xb19ede59, BRF_GRA | CPS1_TILES }, + { "ffj_39.9h", 0x020000, 0x9416b477, BRF_GRA | CPS1_TILES }, + { "ffj_33.9f", 0x020000, 0x7369fa07, BRF_GRA | CPS1_TILES }, + + { "ff_23.13b", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ffj_30.12c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ffj_31.13c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s222b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightj1) +STD_ROM_FN(Ffightj1) + +static struct BurnRomInfo Ffightj2RomDesc[] = { + { "ff30-36.rom", 0x020000, 0x088ed1c9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff35-42.rom", 0x020000, 0xc4c491e6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff31-37.rom", 0x020000, 0x708557ff, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ff36-43.rom", 0x020000, 0xc004004a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_34.10f", 0x020000, 0x0c8dc3fc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_40.10h", 0x020000, 0x8075bab9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_35.11f", 0x020000, 0x4a934121, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ffj_41.11h", 0x020000, 0x2af68154, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ffj_09.4b", 0x020000, 0x5b116d0d, BRF_GRA | CPS1_TILES }, + { "ffj_01.4a", 0x020000, 0x815b1797, BRF_GRA | CPS1_TILES }, + { "ffj_13.9b", 0x020000, 0x8721a7da, BRF_GRA | CPS1_TILES }, + { "ffj_05.9a", 0x020000, 0xd0fcd4b5, BRF_GRA | CPS1_TILES }, + { "ffj_24.5e", 0x020000, 0xa1ab607a, BRF_GRA | CPS1_TILES }, + { "ffj_17.5c", 0x020000, 0x2dc18cf4, BRF_GRA | CPS1_TILES }, + { "ffj_38.8h", 0x020000, 0x6535a57f, BRF_GRA | CPS1_TILES }, + { "ffj_32.8f", 0x020000, 0xc8bc4a57, BRF_GRA | CPS1_TILES }, + { "ffj_10.5b", 0x020000, 0x624a924a, BRF_GRA | CPS1_TILES }, + { "ffj_02.5a", 0x020000, 0x5d91f694, BRF_GRA | CPS1_TILES }, + { "ffj_14.10b", 0x020000, 0x0a2e9101, BRF_GRA | CPS1_TILES }, + { "ffj_06.10a", 0x020000, 0x1c18f042, BRF_GRA | CPS1_TILES }, + { "ffj_25.7e", 0x020000, 0x6e8181ea, BRF_GRA | CPS1_TILES }, + { "ffj_18.7c", 0x020000, 0xb19ede59, BRF_GRA | CPS1_TILES }, + { "ffj_39.9h", 0x020000, 0x9416b477, BRF_GRA | CPS1_TILES }, + { "ffj_33.9f", 0x020000, 0x7369fa07, BRF_GRA | CPS1_TILES }, + + { "ff_23.bin", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ffj_30.bin", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ffj_31.bin", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s222b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Ffightj2) +STD_ROM_FN(Ffightj2) + +static struct BurnRomInfo FfightjhRomDesc[] = { + { "ff_23.8f", 0x080000, 0xae3dda7f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ff_22.7f", 0x080000, 0xb2d5a3aa, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ff_1.3a", 0x080000, 0x969d18e2, BRF_GRA | CPS1_TILES }, + { "ff_2.4a", 0x080000, 0x02b59f99, BRF_GRA | CPS1_TILES }, + { "ff_3.5a", 0x080000, 0x01d507ae, BRF_GRA | CPS1_TILES }, + { "ff_4.6a", 0x080000, 0xf7c4ceb0, BRF_GRA | CPS1_TILES }, + + { "ff_9.12a", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ff_18.11c", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ff_19.12c", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "gal16v8a-15lp.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Ffightjh) +STD_ROM_FN(Ffightjh) + +static struct BurnRomInfo ForgottnRomDesc[] = { + { "lw11.12f", 0x020000, 0x73e920b7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw15.12h", 0x020000, 0x50d7012d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw10.13f", 0x020000, 0xbea45994, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw14.13h", 0x020000, 0x539b2339, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw-07.10g", 0x080000, 0xfd252a26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "lw_2.2b", 0x020000, 0x4bd75fee, BRF_GRA | CPS1_TILES }, + { "lw_1.2a", 0x020000, 0x65f41485, BRF_GRA | CPS1_TILES }, + { "lw-08.9b", 0x080000, 0x25a8e43c, BRF_GRA | CPS1_TILES }, + { "lw-05.6d", 0x080000, 0xe4552fd7, BRF_GRA | CPS1_TILES }, + { "lw_30.8h", 0x020000, 0xb385954e, BRF_GRA | CPS1_TILES }, + { "lw_29.8f", 0x020000, 0x7bda1ac6, BRF_GRA | CPS1_TILES }, + { "lw_4.3b", 0x020000, 0x50cf757f, BRF_GRA | CPS1_TILES }, + { "lw_3.3a", 0x020000, 0xc03ef278, BRF_GRA | CPS1_TILES }, + { "lw_32.9h", 0x020000, 0x30967a15, BRF_GRA | CPS1_TILES }, + { "lw_31.9f", 0x020000, 0xc49d37fb, BRF_GRA | CPS1_TILES }, + { "lw-02.6b", 0x080000, 0x43e6c5c8, BRF_GRA | CPS1_TILES }, + { "lw_14.10b", 0x020000, 0x82862cce, BRF_GRA | CPS1_TILES }, + { "lw_13.10a", 0x020000, 0xb81c0e96, BRF_GRA | CPS1_TILES }, + { "lw-06.9d", 0x080000, 0x5b9edffc, BRF_GRA | CPS1_TILES }, + { "lw_26.10e", 0x020000, 0x57bcd032, BRF_GRA | CPS1_TILES }, + { "lw_25.10c", 0x020000, 0xbac91554, BRF_GRA | CPS1_TILES }, + { "lw_16.11b", 0x020000, 0x40b26554, BRF_GRA | CPS1_TILES }, + { "lw_15.11a", 0x020000, 0x1b7d2e07, BRF_GRA | CPS1_TILES }, + { "lw_28.11e", 0x020000, 0xa805ad30, BRF_GRA | CPS1_TILES }, + { "lw_27.11c", 0x020000, 0x103c1bd2, BRF_GRA | CPS1_TILES }, + + { "lw_00.13c", 0x010000, 0x59df2a63, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "lw-03u.12e", 0x020000, 0x807d051f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "lw-04u.13e", 0x020000, 0xe6cd098e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "lw621.1a", 0x000117, 0x5eec6ce9, BRF_OPT }, // b-board PLDs + { "lwio.12b", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Forgottn) +STD_ROM_FN(Forgottn) + +static struct BurnRomInfo ForgottnuRomDesc[] = { + { "lw11c.12f", 0x020000, 0xe62742b6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw15c.12h", 0x020000, 0x1b70f216, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw10c.13f", 0x020000, 0x8f5ea3f5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw14c.13h", 0x020000, 0x708e7472, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw-07.10g", 0x080000, 0xfd252a26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "lw_2.2b", 0x020000, 0x4bd75fee, BRF_GRA | CPS1_TILES }, + { "lw_1.2a", 0x020000, 0x65f41485, BRF_GRA | CPS1_TILES }, + { "lw-08.9b", 0x080000, 0x25a8e43c, BRF_GRA | CPS1_TILES }, + { "lw-05.6d", 0x080000, 0xe4552fd7, BRF_GRA | CPS1_TILES }, + { "lw_30.8h", 0x020000, 0xb385954e, BRF_GRA | CPS1_TILES }, + { "lw_29.8f", 0x020000, 0x7bda1ac6, BRF_GRA | CPS1_TILES }, + { "lw_4.3b", 0x020000, 0x50cf757f, BRF_GRA | CPS1_TILES }, + { "lw_3.3a", 0x020000, 0xc03ef278, BRF_GRA | CPS1_TILES }, + { "lw_32.9h", 0x020000, 0x30967a15, BRF_GRA | CPS1_TILES }, + { "lw_31.9f", 0x020000, 0xc49d37fb, BRF_GRA | CPS1_TILES }, + { "lw-02.6b", 0x080000, 0x43e6c5c8, BRF_GRA | CPS1_TILES }, + { "lw_14.10b", 0x020000, 0x82862cce, BRF_GRA | CPS1_TILES }, + { "lw_13.10a", 0x020000, 0xb81c0e96, BRF_GRA | CPS1_TILES }, + { "lw-06.9d", 0x080000, 0x5b9edffc, BRF_GRA | CPS1_TILES }, + { "lw-13.10d", 0x080000, 0x8e058ef5, BRF_GRA | CPS1_TILES }, + { "lw_16.11b", 0x020000, 0x40b26554, BRF_GRA | CPS1_TILES }, + { "lw_15.11a", 0x020000, 0x1b7d2e07, BRF_GRA | CPS1_TILES }, + + { "lw_00.13c", 0x010000, 0x59df2a63, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "lw-03u.12e", 0x020000, 0x807d051f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "lw-04u.13e", 0x020000, 0xe6cd098e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "lw621.1a", 0x000117, 0x5eec6ce9, BRF_OPT }, // b-board PLDs + { "lwio.12b", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Forgottnu) +STD_ROM_FN(Forgottnu) + +static struct BurnRomInfo ForgottnuaRomDesc[] = { + { "lwu_11a.14f", 0x020000, 0xddf78831, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lwu_15a.14g", 0x020000, 0xf7ce2097, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lwu_10a.13f", 0x020000, 0x8cb38c81, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lwu_14a.13g", 0x020000, 0xd70ef9fd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw-07.13e", 0x080000, 0xfd252a26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "lw-01.9d", 0x080000, 0x0318f298, BRF_GRA | CPS1_TILES }, + { "lw-08.9f", 0x080000, 0x25a8e43c, BRF_GRA | CPS1_TILES }, + { "lw-05.9e", 0x080000, 0xe4552fd7, BRF_GRA | CPS1_TILES }, + { "lw-12.9g", 0x080000, 0x8e6a832b, BRF_GRA | CPS1_TILES }, + { "lw-02.12d", 0x080000, 0x43e6c5c8, BRF_GRA | CPS1_TILES }, + { "lw-09.12f", 0x080000, 0x899cb4ad, BRF_GRA | CPS1_TILES }, + { "lw-06.12e", 0x080000, 0x5b9edffc, BRF_GRA | CPS1_TILES }, + { "lw-13.12g", 0x080000, 0x8e058ef5, BRF_GRA | CPS1_TILES }, + + { "lwu_00.14a", 0x010000, 0x59df2a63, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "lw-03u.14c", 0x020000, 0x807d051f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "lw-04u.13c", 0x020000, 0xe6cd098e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "lwchr.3a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.15e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Forgottnua) +STD_ROM_FN(Forgottnua) + +static struct BurnRomInfo LostwrldRomDesc[] = { + { "lw_11c.14f", 0x020000, 0x67e42546, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_15c.14g", 0x020000, 0x402e2a46, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_10c.13f", 0x020000, 0xc46479d7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_14c.13g", 0x020000, 0x97670f4a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw-07.13e", 0x080000, 0xfd252a26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "lw-01.9d", 0x080000, 0x0318f298, BRF_GRA | CPS1_TILES }, + { "lw-08.9f", 0x080000, 0x25a8e43c, BRF_GRA | CPS1_TILES }, + { "lw-05.9e", 0x080000, 0xe4552fd7, BRF_GRA | CPS1_TILES }, + { "lw-12.9g", 0x080000, 0x8e6a832b, BRF_GRA | CPS1_TILES }, + { "lw-02.12d", 0x080000, 0x43e6c5c8, BRF_GRA | CPS1_TILES }, + { "lw-09.12f", 0x080000, 0x899cb4ad, BRF_GRA | CPS1_TILES }, + { "lw-06.12e", 0x080000, 0x5b9edffc, BRF_GRA | CPS1_TILES }, + { "lw-13.12g", 0x080000, 0x8e058ef5, BRF_GRA | CPS1_TILES }, + + { "lw_00b.14a", 0x010000, 0x59df2a63, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "lw-03.14c", 0x020000, 0xce2159e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "lw-04.13c", 0x020000, 0x39305536, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "lwchr.3a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "lwio.15e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Lostwrld) +STD_ROM_FN(Lostwrld) + +static struct BurnRomInfo LostwrldoRomDesc[] = { + { "lw_11.14f", 0x020000, 0x61e2cc56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_15.14g", 0x020000, 0x8a0c18d3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_10.13f", 0x020000, 0x23bca4d5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw_14.13g", 0x020000, 0x3a023771, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "lw-07.13e", 0x080000, 0xfd252a26, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "lw-01.9d", 0x080000, 0x0318f298, BRF_GRA | CPS1_TILES }, + { "lw-08.9f", 0x080000, 0x25a8e43c, BRF_GRA | CPS1_TILES }, + { "lw-05.9e", 0x080000, 0xe4552fd7, BRF_GRA | CPS1_TILES }, + { "lw-12.9g", 0x080000, 0x8e6a832b, BRF_GRA | CPS1_TILES }, + { "lw-02.12d", 0x080000, 0x43e6c5c8, BRF_GRA | CPS1_TILES }, + { "lw-09.12f", 0x080000, 0x899cb4ad, BRF_GRA | CPS1_TILES }, + { "lw-06.12e", 0x080000, 0x5b9edffc, BRF_GRA | CPS1_TILES }, + { "lw-13.12g", 0x080000, 0x8e058ef5, BRF_GRA | CPS1_TILES }, + + { "lw_00b.14a", 0x010000, 0x59df2a63, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "lw-03.14c", 0x020000, 0xce2159e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "lw-04.13c", 0x020000, 0x39305536, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "lwchr.3a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "lwio.15e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Lostwrldo) +STD_ROM_FN(Lostwrldo) + +static struct BurnRomInfo GhoulsRomDesc[] = { + { "dme_29.10h", 0x020000, 0x166a58a2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dme_30.10j", 0x020000, 0x7ac8407a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dme_27.9h", 0x020000, 0xf734b2be, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dme_28.9j", 0x020000, 0x03d3e714, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm-17.7j", 0x080000, 0x3ea1b0f2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "dm-05.3a", 0x080000, 0x0ba9c0b0, BRF_GRA | CPS1_TILES }, + { "dm-07.3f", 0x080000, 0x5d760ab9, BRF_GRA | CPS1_TILES }, + { "dm-06.3c", 0x080000, 0x4ba90b59, BRF_GRA | CPS1_TILES }, + { "dm-08.3g", 0x080000, 0x4bdee9de, BRF_GRA | CPS1_TILES }, + { "09.4a", 0x010000, 0xae24bb19, BRF_GRA | CPS1_TILES }, + { "18.7a", 0x010000, 0xd34e271a, BRF_GRA | CPS1_TILES }, + { "13.4e", 0x010000, 0x3f70dd37, BRF_GRA | CPS1_TILES }, + { "22.7e", 0x010000, 0x7e69e2e6, BRF_GRA | CPS1_TILES }, + { "11.4c", 0x010000, 0x37c9b6c6, BRF_GRA | CPS1_TILES }, + { "20.7c", 0x010000, 0x2f1345b4, BRF_GRA | CPS1_TILES }, + { "15.4g", 0x010000, 0x3c2a212a, BRF_GRA | CPS1_TILES }, + { "24.7g", 0x010000, 0x889aac05, BRF_GRA | CPS1_TILES }, + { "10.4b", 0x010000, 0xbcc0f28c, BRF_GRA | CPS1_TILES }, + { "19.7b", 0x010000, 0x2a40166a, BRF_GRA | CPS1_TILES }, + { "14.4f", 0x010000, 0x20f85c03, BRF_GRA | CPS1_TILES }, + { "23.7f", 0x010000, 0x8426144b, BRF_GRA | CPS1_TILES }, + { "12.4d", 0x010000, 0xda088d61, BRF_GRA | CPS1_TILES }, + { "21.7d", 0x010000, 0x17e11df0, BRF_GRA | CPS1_TILES }, + { "16.4h", 0x010000, 0xf187ba1c, BRF_GRA | CPS1_TILES }, + { "25.7h", 0x010000, 0x29f79c78, BRF_GRA | CPS1_TILES }, + + { "26.10a", 0x010000, 0x3692f6e5, BRF_PRG | CPS1_Z80_PROGRAM }, + + A_BOARD_PLDS + + { "dm620.2a", 0x000117, 0xf6e5f727, BRF_OPT }, // b-board PLDs + { "lwio.8i", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Ghouls) +STD_ROM_FN(Ghouls) + +static struct BurnRomInfo GhoulsuRomDesc[] = { + { "dmu_29.10h", 0x020000, 0x334d85b2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmu_30.10j", 0x020000, 0xcee8ceb5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmu_27.9h", 0x020000, 0x4a524140, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmu_28.9j", 0x020000, 0x94aae205, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm-17.7j", 0x080000, 0x3ea1b0f2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "dm-05.3a", 0x080000, 0x0ba9c0b0, BRF_GRA | CPS1_TILES }, + { "dm-07.3f", 0x080000, 0x5d760ab9, BRF_GRA | CPS1_TILES }, + { "dm-06.3c", 0x080000, 0x4ba90b59, BRF_GRA | CPS1_TILES }, + { "dm-08.3g", 0x080000, 0x4bdee9de, BRF_GRA | CPS1_TILES }, + { "09.4a", 0x010000, 0xae24bb19, BRF_GRA | CPS1_TILES }, + { "18.7a", 0x010000, 0xd34e271a, BRF_GRA | CPS1_TILES }, + { "13.4e", 0x010000, 0x3f70dd37, BRF_GRA | CPS1_TILES }, + { "22.7e", 0x010000, 0x7e69e2e6, BRF_GRA | CPS1_TILES }, + { "11.4c", 0x010000, 0x37c9b6c6, BRF_GRA | CPS1_TILES }, + { "20.7c", 0x010000, 0x2f1345b4, BRF_GRA | CPS1_TILES }, + { "15.4g", 0x010000, 0x3c2a212a, BRF_GRA | CPS1_TILES }, + { "24.7g", 0x010000, 0x889aac05, BRF_GRA | CPS1_TILES }, + { "10.4b", 0x010000, 0xbcc0f28c, BRF_GRA | CPS1_TILES }, + { "19.7b", 0x010000, 0x2a40166a, BRF_GRA | CPS1_TILES }, + { "14.4f", 0x010000, 0x20f85c03, BRF_GRA | CPS1_TILES }, + { "23.7f", 0x010000, 0x8426144b, BRF_GRA | CPS1_TILES }, + { "12.4d", 0x010000, 0xda088d61, BRF_GRA | CPS1_TILES }, + { "21.7d", 0x010000, 0x17e11df0, BRF_GRA | CPS1_TILES }, + { "16.4h", 0x010000, 0xf187ba1c, BRF_GRA | CPS1_TILES }, + { "25.7h", 0x010000, 0x29f79c78, BRF_GRA | CPS1_TILES }, + + { "26.10a", 0x010000, 0x3692f6e5, BRF_PRG | CPS1_Z80_PROGRAM }, + + A_BOARD_PLDS + + { "dm620.2a", 0x000117, 0xf6e5f727, BRF_OPT }, // b-board PLDs + { "lwio.8i", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Ghoulsu) +STD_ROM_FN(Ghoulsu) + +static struct BurnRomInfo DaimakaiRomDesc[] = { + { "dmj_38.12f", 0x020000, 0x82fd1798, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmj_39.12h", 0x020000, 0x35366ccc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmj_40.13f", 0x020000, 0xa17c170a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmj_41.13h", 0x020000, 0x6af0b391, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm_33.10f", 0x020000, 0x384d60c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm_34.10h", 0x020000, 0x19abe30f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm_35.11f", 0x020000, 0xc04b85c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dm_36.11h", 0x020000, 0x89be83de, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "dm_02.4b", 0x020000, 0x8b98dc48, BRF_GRA | CPS1_TILES }, + { "dm_01.4a", 0x020000, 0x80896c33, BRF_GRA | CPS1_TILES }, + { "dm_10.9b", 0x020000, 0xc2e7d9ef, BRF_GRA | CPS1_TILES }, + { "dm_09.9a", 0x020000, 0xc9c4afa5, BRF_GRA | CPS1_TILES }, + { "dm_18.5e", 0x020000, 0x1aa0db99, BRF_GRA | CPS1_TILES }, + { "dm_17.5c", 0x020000, 0xdc6ed8ad, BRF_GRA | CPS1_TILES }, + { "dm_30.8h", 0x020000, 0xd9d3f8bd, BRF_GRA | CPS1_TILES }, + { "dm_29.8f", 0x020000, 0x49a48796, BRF_GRA | CPS1_TILES }, + { "dm_04.5b", 0x020000, 0xa4f4f8f0, BRF_GRA | CPS1_TILES }, + { "dm_03.5a", 0x020000, 0xb1033e62, BRF_GRA | CPS1_TILES }, + { "dm_12.10b", 0x020000, 0x10fdd76a, BRF_GRA | CPS1_TILES }, + { "dm_11.10a", 0x020000, 0x9040cb04, BRF_GRA | CPS1_TILES }, + { "dm_20.7e", 0x020000, 0x281d0b3e, BRF_GRA | CPS1_TILES }, + { "dm_19.7c", 0x020000, 0x2623b52f, BRF_GRA | CPS1_TILES }, + { "dm_32.9h", 0x020000, 0x99692344, BRF_GRA | CPS1_TILES }, + { "dm_31.9f", 0x020000, 0x54acb729, BRF_GRA | CPS1_TILES }, + { "dm_06.7b", 0x010000, 0xae24bb19, BRF_GRA | CPS1_TILES }, + { "dm_05.7a", 0x010000, 0xd34e271a, BRF_GRA | CPS1_TILES }, + { "dm_14.11b", 0x010000, 0x3f70dd37, BRF_GRA | CPS1_TILES }, + { "dm_13.11a", 0x010000, 0x7e69e2e6, BRF_GRA | CPS1_TILES }, + { "dm_22.8e", 0x010000, 0x37c9b6c6, BRF_GRA | CPS1_TILES }, + { "dm_21.8c", 0x010000, 0x2f1345b4, BRF_GRA | CPS1_TILES }, + { "dm_26.10e", 0x010000, 0x3c2a212a, BRF_GRA | CPS1_TILES }, + { "dm_25.10c", 0x010000, 0x889aac05, BRF_GRA | CPS1_TILES }, + { "dm_08.8b", 0x010000, 0xbcc0f28c, BRF_GRA | CPS1_TILES }, + { "dm_07.8a", 0x010000, 0x2a40166a, BRF_GRA | CPS1_TILES }, + { "dm_16.12b", 0x010000, 0x20f85c03, BRF_GRA | CPS1_TILES }, + { "dm_15.12a", 0x010000, 0x8426144b, BRF_GRA | CPS1_TILES }, + { "dm_24.9e", 0x010000, 0xda088d61, BRF_GRA | CPS1_TILES }, + { "dm_23.9c", 0x010000, 0x17e11df0, BRF_GRA | CPS1_TILES }, + { "dm_28.11e", 0x010000, 0xf187ba1c, BRF_GRA | CPS1_TILES }, + { "dm_27.11c", 0x010000, 0x29f79c78, BRF_GRA | CPS1_TILES }, + + { "37.13c", 0x010000, 0x3692f6e5, BRF_PRG | CPS1_Z80_PROGRAM }, + + A_BOARD_PLDS + + { "dm22a.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Daimakai) +STD_ROM_FN(Daimakai) + +static struct BurnRomInfo DaimakairRomDesc[] = { + { "damj_23.8f", 0x080000, 0xc3b248ec, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "damj_22.7f", 0x080000, 0x595ff2f3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "dam_01.3a", 0x080000, 0x0ba9c0b0, BRF_GRA | CPS1_TILES }, + { "dam_02.4a", 0x080000, 0x5d760ab9, BRF_GRA | CPS1_TILES }, + { "dam_03.5a", 0x080000, 0x4ba90b59, BRF_GRA | CPS1_TILES }, + { "dam_04.6a", 0x080000, 0x4bdee9de, BRF_GRA | CPS1_TILES }, + { "dam_05.7a", 0x080000, 0x7dc61b94, BRF_GRA | CPS1_TILES }, + { "dam_06.8a", 0x080000, 0xfde89758, BRF_GRA | CPS1_TILES }, + { "dam_07.9a", 0x080000, 0xec351d78, BRF_GRA | CPS1_TILES }, + { "dam_08.10a", 0x080000, 0xee2acc1e, BRF_GRA | CPS1_TILES }, + + { "dam_09.12a", 0x020000, 0x0656ff53, BRF_PRG | CPS1_Z80_PROGRAM }, + + A_BOARD_PLDS + + { "dam63b.1a", 0x000117, 0x474b3c8a, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Daimakair) +STD_ROM_FN(Daimakair) + +static struct BurnRomInfo DaimakbRomDesc[] = { + { "dmjb2.bin", 0x080000, 0x7d5f9f84, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "dmjb1.bin", 0x080000, 0x9b945cc4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "dm_02.4b", 0x020000, 0x8b98dc48, BRF_GRA | CPS1_TILES }, + { "dm_01.4a", 0x020000, 0x80896c33, BRF_GRA | CPS1_TILES }, + { "dm_10.9b", 0x020000, 0xc2e7d9ef, BRF_GRA | CPS1_TILES }, + { "dm_09.9a", 0x020000, 0xc9c4afa5, BRF_GRA | CPS1_TILES }, + { "dm_18.5e", 0x020000, 0x1aa0db99, BRF_GRA | CPS1_TILES }, + { "dm_17.5c", 0x020000, 0xdc6ed8ad, BRF_GRA | CPS1_TILES }, + { "dm_30.8h", 0x020000, 0xd9d3f8bd, BRF_GRA | CPS1_TILES }, + { "dm_29.8f", 0x020000, 0x49a48796, BRF_GRA | CPS1_TILES }, + { "dm_04.5b", 0x020000, 0xa4f4f8f0, BRF_GRA | CPS1_TILES }, + { "dm_03.5a", 0x020000, 0xb1033e62, BRF_GRA | CPS1_TILES }, + { "dm_12.10b", 0x020000, 0x10fdd76a, BRF_GRA | CPS1_TILES }, + { "dm_11.10a", 0x020000, 0x9040cb04, BRF_GRA | CPS1_TILES }, + { "dm_20.7e", 0x020000, 0x281d0b3e, BRF_GRA | CPS1_TILES }, + { "dm_19.7c", 0x020000, 0x2623b52f, BRF_GRA | CPS1_TILES }, + { "dm_32.9h", 0x020000, 0x99692344, BRF_GRA | CPS1_TILES }, + { "dm_31.9f", 0x020000, 0x54acb729, BRF_GRA | CPS1_TILES }, + { "dm_06.7b", 0x010000, 0xae24bb19, BRF_GRA | CPS1_TILES }, + { "dm_05.7a", 0x010000, 0xd34e271a, BRF_GRA | CPS1_TILES }, + { "dm_14.11b", 0x010000, 0x3f70dd37, BRF_GRA | CPS1_TILES }, + { "dm_13.11a", 0x010000, 0x7e69e2e6, BRF_GRA | CPS1_TILES }, + { "dm_22.8e", 0x010000, 0x37c9b6c6, BRF_GRA | CPS1_TILES }, + { "dm_21.8c", 0x010000, 0x2f1345b4, BRF_GRA | CPS1_TILES }, + { "dm_26.10e", 0x010000, 0x3c2a212a, BRF_GRA | CPS1_TILES }, + { "dm_25.10c", 0x010000, 0x889aac05, BRF_GRA | CPS1_TILES }, + { "dm_08.8b", 0x010000, 0xbcc0f28c, BRF_GRA | CPS1_TILES }, + { "dm_07.8a", 0x010000, 0x2a40166a, BRF_GRA | CPS1_TILES }, + { "dm_16.12b", 0x010000, 0x20f85c03, BRF_GRA | CPS1_TILES }, + { "dm_15.12a", 0x010000, 0x8426144b, BRF_GRA | CPS1_TILES }, + { "dm_24.9e", 0x010000, 0xda088d61, BRF_GRA | CPS1_TILES }, + { "dm_23.9c", 0x010000, 0x17e11df0, BRF_GRA | CPS1_TILES }, + { "dm_28.11e", 0x010000, 0xf187ba1c, BRF_GRA | CPS1_TILES }, + { "dm_27.11c", 0x010000, 0x29f79c78, BRF_GRA | CPS1_TILES }, + + { "dm_37.13c", 0x010000, 0x3692f6e5, BRF_PRG | CPS1_Z80_PROGRAM }, +}; + +STD_ROM_PICK(Daimakb) +STD_ROM_FN(Daimakb) + +static struct BurnRomInfo KnightsRomDesc[] = { + { "kr_23e.8f", 0x080000, 0x1b3997eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "kr_22.7f", 0x080000, 0xd0b671a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kr-5m.3a", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr-7m.5a", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr-1m.4a", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr-3m.6a", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr-6m.7a", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr-8m.9a", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr-2m.8a", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr-4m.10a", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.11a", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.11c", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.12c", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kr63b.1a", 0x000117, 0xfd5b6522, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Knights) +STD_ROM_FN(Knights) + +static struct BurnRomInfo KnightsuRomDesc[] = { + { "kr_23u.8f", 0x080000, 0x252bc2ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "kr_22.7f", 0x080000, 0xd0b671a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kr-5m.3a", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr-7m.5a", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr-1m.4a", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr-3m.6a", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr-6m.7a", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr-8m.9a", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr-2m.8a", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr-4m.10a", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.11a", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.11c", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.12c", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kr63b.1a", 0x000117, 0xfd5b6522, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Knightsu) +STD_ROM_FN(Knightsu) + +static struct BurnRomInfo KnightsjRomDesc[] = { + { "kr_23j.8f", 0x080000, 0xeae7417f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "kr_22.7f", 0x080000, 0xd0b671a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kr_01.3a", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr_02.4a", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr_03.5a", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr_04.6a", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr_05.7a", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr_06.8a", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr_07.9a", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr_08.10a", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.12a", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.11c", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.12c", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kr63b.1a", 0x000117, 0xfd5b6522, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Knightsj) +STD_ROM_FN(Knightsj) + +static struct BurnRomInfo KnightsjaRomDesc[] = { + { "krj_36.12f", 0x020000, 0xad3d1a8e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "krj_42.12h", 0x020000, 0xe694a491, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "krj_37.13f", 0x020000, 0x85596094, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "krj_43.13h", 0x020000, 0x9198bf8f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kr_34.10f", 0x020000, 0xfe6eb08d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kr_40.10h", 0x020000, 0x1172806d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kr_35.11f", 0x020000, 0xf854b020, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kr_41.11h", 0x020000, 0xeb52e78d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kr_09.4b", 0x020000, 0x08b76e10, BRF_GRA | CPS1_TILES }, + { "kr_01.4a", 0x020000, 0x40cecf5c, BRF_GRA | CPS1_TILES }, + { "kr_13.9b", 0x020000, 0x435aaa03, BRF_GRA | CPS1_TILES }, + { "kr_05.9a", 0x020000, 0x5b8a615b, BRF_GRA | CPS1_TILES }, + { "kr_24.5e", 0x020000, 0xde65153e, BRF_GRA | CPS1_TILES }, + { "kr_17.5c", 0x020000, 0xb171c968, BRF_GRA | CPS1_TILES }, + { "kr_38.8h", 0x020000, 0xf4466bf4, BRF_GRA | CPS1_TILES }, + { "kr_32.8f", 0x020000, 0x87380ddd, BRF_GRA | CPS1_TILES }, + { "kr_10.5b", 0x020000, 0x37006d66, BRF_GRA | CPS1_TILES }, + { "kr_02.5a", 0x020000, 0xb54612e3, BRF_GRA | CPS1_TILES }, + { "kr_14.10b", 0x020000, 0x0ae88766, BRF_GRA | CPS1_TILES }, + { "kr_06.10a", 0x020000, 0xecb1a09a, BRF_GRA | CPS1_TILES }, + { "kr_25.7e", 0x020000, 0x9aace189, BRF_GRA | CPS1_TILES }, + { "kr_18.7c", 0x020000, 0x09fa14a5, BRF_GRA | CPS1_TILES }, + { "kr_39.9h", 0x020000, 0xfd8a9aeb, BRF_GRA | CPS1_TILES }, + { "kr_33.9f", 0x020000, 0x11803e95, BRF_GRA | CPS1_TILES }, + { "kr_11.7b", 0x020000, 0xa967ceb3, BRF_GRA | CPS1_TILES }, + { "kr_03.7a", 0x020000, 0xea10db07, BRF_GRA | CPS1_TILES }, + { "kr_15.11b", 0x020000, 0x8140b83b, BRF_GRA | CPS1_TILES }, + { "kr_07.11a", 0x020000, 0x6af10648, BRF_GRA | CPS1_TILES }, + { "kr_26.8e", 0x020000, 0x8865d86b, BRF_GRA | CPS1_TILES }, + { "kr_19.8c", 0x020000, 0x029f4abe, BRF_GRA | CPS1_TILES }, + { "kr_28.10e", 0x020000, 0x5f84f92f, BRF_GRA | CPS1_TILES }, + { "kr_21.10c", 0x020000, 0x01b35065, BRF_GRA | CPS1_TILES }, + { "kr_12.8b", 0x020000, 0x03d945b1, BRF_GRA | CPS1_TILES }, + { "kr_04.8a", 0x020000, 0xe30c8388, BRF_GRA | CPS1_TILES }, + { "kr_16.12b", 0x020000, 0x40c39d1b, BRF_GRA | CPS1_TILES }, + { "kr_08.12a", 0x020000, 0xd310c9e8, BRF_GRA | CPS1_TILES }, + { "kr_27.9e", 0x020000, 0x3e041444, BRF_GRA | CPS1_TILES }, + { "kr_20.9c", 0x020000, 0xbd4bffb8, BRF_GRA | CPS1_TILES }, + { "kr_29.11e", 0x020000, 0x1387a076, BRF_GRA | CPS1_TILES }, + { "kr_22.11c", 0x020000, 0xfd351922, BRF_GRA | CPS1_TILES }, + + { "kr_23.13b", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_30.12c", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_31.13c", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kr22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12e", 0x000117, 0xad52b90c, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Knightsja) +STD_ROM_FN(Knightsja) + +static struct BurnRomInfo Knightsb2RomDesc[] = { + { "040-z.02", 0x080000, 0x95d00a7e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "040-r.02", 0x080000, 0x5a9d0b64, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kr_gfx1.rom", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr_gfx3.rom", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr_gfx2.rom", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr_gfx4.rom", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr_gfx5.rom", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr_gfx7.rom", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr_gfx6.rom", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr_gfx8.rom", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.rom", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.rom", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.rom", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Knightsb2) +STD_ROM_FN(Knightsb2) + +static struct BurnRomInfo Knightsb3RomDesc[] = { + { "23.096", 0x080000, 0x7733b8a6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "22.096", 0x080000, 0xd0b671a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "1.096", 0x080000, 0x91541596, BRF_GRA | CPS1_TILES }, + { "2.096", 0x080000, 0x5d332114, BRF_GRA | CPS1_TILES }, + { "3.096", 0x080000, 0x60488eba, BRF_GRA | CPS1_TILES }, + { "4.096", 0x080000, 0x394bdd11, BRF_GRA | CPS1_TILES }, + { "5.096", 0x080000, 0xb52af98b, BRF_GRA | CPS1_TILES }, + { "6.096", 0x080000, 0xe44e5eac, BRF_GRA | CPS1_TILES }, + { "7.096", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "8.096", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "9.512", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "18.010", 0x020000, 0x9b9be3ab, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "19.010", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Knightsb3) +STD_ROM_FN(Knightsb3) + +static struct BurnRomInfo KnightshRomDesc[] = { + { "krh_23.rom", 0x080000, 0xfa2ff63d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "krh_22.rom", 0x080000, 0x1438d070, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kr_gfx1.rom", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr_gfx3.rom", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr_gfx2.rom", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr_gfx4.rom", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr_gfx5.rom", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr_gfx7.rom", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr_gfx6.rom", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr_gfx8.rom", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.rom", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.rom", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.rom", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Knightsh) +STD_ROM_FN(Knightsh) + +static struct BurnRomInfo KnghtshaRomDesc[] = { + { "krha_23.rom", 0x080000, 0xa7fd309a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "krh_22.rom", 0x080000, 0x1438d070, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kr_gfx1.rom", 0x080000, 0x9e36c1a4, BRF_GRA | CPS1_TILES }, + { "kr_gfx3.rom", 0x080000, 0xc5832cae, BRF_GRA | CPS1_TILES }, + { "kr_gfx2.rom", 0x080000, 0xf095be2d, BRF_GRA | CPS1_TILES }, + { "kr_gfx4.rom", 0x080000, 0x179dfd96, BRF_GRA | CPS1_TILES }, + { "kr_gfx5.rom", 0x080000, 0x1f4298d2, BRF_GRA | CPS1_TILES }, + { "kr_gfx7.rom", 0x080000, 0x37fa8751, BRF_GRA | CPS1_TILES }, + { "kr_gfx6.rom", 0x080000, 0x0200bc3d, BRF_GRA | CPS1_TILES }, + { "kr_gfx8.rom", 0x080000, 0x0bb2b4e7, BRF_GRA | CPS1_TILES }, + + { "kr_09.rom", 0x010000, 0x5e44d9ee, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kr_18.rom", 0x020000, 0xda69d15f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kr_19.rom", 0x020000, 0xbfc654e9, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Knghtsha) +STD_ROM_FN(Knghtsha) + +static struct BurnRomInfo KodRomDesc[] = { + { "kde_30a.11e", 0x020000, 0xfcb5efe2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_37a.11f", 0x020000, 0xf22e5266, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_31a.12e", 0x020000, 0xc710d722, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_38a.12f", 0x020000, 0x57d6ed3a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_28.9e", 0x020000, 0x9367bcd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_35.9f", 0x020000, 0x4ca6a48a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_29.10e", 0x020000, 0x0360fa72, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_36a.10f", 0x020000, 0x95a3cef8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kd-5m.4a", 0x080000, 0xe45b8701, BRF_GRA | CPS1_TILES }, + { "kd-7m.6a", 0x080000, 0xa7750322, BRF_GRA | CPS1_TILES }, + { "kd-1m.3a", 0x080000, 0x5f74bf78, BRF_GRA | CPS1_TILES }, + { "kd-3m.5a", 0x080000, 0x5e5303bf, BRF_GRA | CPS1_TILES }, + { "kd-6m.4c", 0x080000, 0x113358f3, BRF_GRA | CPS1_TILES }, + { "kd-8m.6c", 0x080000, 0x38853c44, BRF_GRA | CPS1_TILES }, + { "kd-2m.3c", 0x080000, 0x9ef36604, BRF_GRA | CPS1_TILES }, + { "kd-4m.5c", 0x080000, 0x402b9b4f, BRF_GRA | CPS1_TILES }, + + { "kd_9.12a", 0x010000, 0xbac6ec26, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd_18.11c", 0x020000, 0x4c63181d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd_19.12c", 0x020000, 0x92941b80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kd29b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Kod) +STD_ROM_FN(Kod) + +static struct BurnRomInfo Kodr1RomDesc[] = { + { "kde_30.11e", 0x020000, 0xc7414fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_37.11f", 0x020000, 0xa5bf40d2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_31.12e", 0x020000, 0x1fffc7bd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_38.12f", 0x020000, 0x89e57a82, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_28.9e", 0x020000, 0x9367bcd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_35.9f", 0x020000, 0x4ca6a48a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_29.10e", 0x020000, 0x6a0ba878, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kde_36.10f", 0x020000, 0xb509b39d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kd-5m.4a", 0x080000, 0xe45b8701, BRF_GRA | CPS1_TILES }, + { "kd-7m.6a", 0x080000, 0xa7750322, BRF_GRA | CPS1_TILES }, + { "kd-1m.3a", 0x080000, 0x5f74bf78, BRF_GRA | CPS1_TILES }, + { "kd-3m.5a", 0x080000, 0x5e5303bf, BRF_GRA | CPS1_TILES }, + { "kd-6m.4c", 0x080000, 0x113358f3, BRF_GRA | CPS1_TILES }, + { "kd-8m.6c", 0x080000, 0x38853c44, BRF_GRA | CPS1_TILES }, + { "kd-2m.3c", 0x080000, 0x9ef36604, BRF_GRA | CPS1_TILES }, + { "kd-4m.5c", 0x080000, 0x402b9b4f, BRF_GRA | CPS1_TILES }, + + { "kd_9.9", 0x010000, 0xf5514510, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd_18.18", 0x020000, 0x69ecb2c8, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd_19.19", 0x020000, 0x02d851c1, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kd29b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Kodr1) +STD_ROM_FN(Kodr1) + +static struct BurnRomInfo KoduRomDesc[] = { + { "kdu_30b.11e", 0x020000, 0x825817f9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_37b.11f", 0x020000, 0xd2422dfb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_31b.12e", 0x020000, 0x9af36039, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_38b.12f", 0x020000, 0xbe8405a1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_28.9e", 0x020000, 0x9367bcd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_35.9f", 0x020000, 0x4ca6a48a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_29.10e", 0x020000, 0x0360fa72, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdu_36a.10f", 0x020000, 0x95a3cef8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kd-5m.4a", 0x080000, 0xe45b8701, BRF_GRA | CPS1_TILES }, + { "kd-7m.6a", 0x080000, 0xa7750322, BRF_GRA | CPS1_TILES }, + { "kd-1m.3a", 0x080000, 0x5f74bf78, BRF_GRA | CPS1_TILES }, + { "kd-3m.5a", 0x080000, 0x5e5303bf, BRF_GRA | CPS1_TILES }, + { "kd-6m.4c", 0x080000, 0x113358f3, BRF_GRA | CPS1_TILES }, + { "kd-8m.6c", 0x080000, 0x38853c44, BRF_GRA | CPS1_TILES }, + { "kd-2m.3c", 0x080000, 0x9ef36604, BRF_GRA | CPS1_TILES }, + { "kd-4m.5c", 0x080000, 0x402b9b4f, BRF_GRA | CPS1_TILES }, + + { "kd_09.12a", 0x010000, 0xbac6ec26, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd_18.11c", 0x020000, 0x4c63181d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd_19.12c", 0x020000, 0x92941b80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kd29b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Kodu) +STD_ROM_FN(Kodu) + +static struct BurnRomInfo KodjRomDesc[] = { + { "kdj_30a.11e", 0x020000, 0xebc788ad, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_37a.11f", 0x020000, 0xe55c3529, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_31a.12e", 0x020000, 0xc710d722, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_38a.12f", 0x020000, 0x57d6ed3a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_33.6f", 0x080000, 0x9bd7ad4b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "kd_06.8a", 0x080000, 0xe45b8701, BRF_GRA | CPS1_TILES }, + { "kd_08.10a", 0x080000, 0xa7750322, BRF_GRA | CPS1_TILES }, + { "kd_05.7a", 0x080000, 0x5f74bf78, BRF_GRA | CPS1_TILES }, + { "kd_07.9a", 0x080000, 0x5e5303bf, BRF_GRA | CPS1_TILES }, + { "kd_15.8c", 0x080000, 0x113358f3, BRF_GRA | CPS1_TILES }, + { "kd_17.10c", 0x080000, 0x38853c44, BRF_GRA | CPS1_TILES }, + { "kd_14.7c", 0x080000, 0x9ef36604, BRF_GRA | CPS1_TILES }, + { "kd_16.9c", 0x080000, 0x402b9b4f, BRF_GRA | CPS1_TILES }, + + { "kd_09.12a", 0x010000, 0xbac6ec26, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd_18.11c", 0x020000, 0x4c63181d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd_19.12c", 0x020000, 0x92941b80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kd29b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Kodj) +STD_ROM_FN(Kodj) + +static struct BurnRomInfo KodjaRomDesc[] = { + { "kdj_36a.12f", 0x020000, 0xebc788ad, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_42a.12h", 0x020000, 0xe55c3529, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_37a.13f", 0x020000, 0xc710d722, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kdj_43a.13h", 0x020000, 0x57d6ed3a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_34.10f", 0x020000, 0x9367bcd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_40.10h", 0x020000, 0x4ca6a48a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_35.11f", 0x020000, 0x0360fa72, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "kd_41a.11h", 0x020000, 0x95a3cef8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "kd_9.4b", 0x020000, 0x401a98e3, BRF_GRA | CPS1_TILES }, + { "kd_1.4a", 0x020000, 0x5894399a, BRF_GRA | CPS1_TILES }, + { "kd_13.9b", 0x020000, 0xb6685131, BRF_GRA | CPS1_TILES }, + { "kd_5.9a", 0x020000, 0xc29b9ab3, BRF_GRA | CPS1_TILES }, + { "kd_24.5e", 0x020000, 0x97008fdb, BRF_GRA | CPS1_TILES }, + { "kd_17.5c", 0x020000, 0xdc9a83d3, BRF_GRA | CPS1_TILES }, + { "kd_38.8h", 0x020000, 0x9c3dd2d1, BRF_GRA | CPS1_TILES }, + { "kd_32.8f", 0x020000, 0x1b2a802a, BRF_GRA | CPS1_TILES }, + { "kd_10.5b", 0x020000, 0xe788ae96, BRF_GRA | CPS1_TILES }, + { "kd_2.5a", 0x020000, 0xb022e3e3, BRF_GRA | CPS1_TILES }, + { "kd_14.10b", 0x020000, 0x4840c5ef, BRF_GRA | CPS1_TILES }, + { "kd_6.10a", 0x020000, 0x519faee4, BRF_GRA | CPS1_TILES }, + { "kd_25.7e", 0x020000, 0x5d0fa853, BRF_GRA | CPS1_TILES }, + { "kd_18.7c", 0x020000, 0x6ad3b2bb, BRF_GRA | CPS1_TILES }, + { "kd_39.9h", 0x020000, 0xd7920213, BRF_GRA | CPS1_TILES }, + { "kd_33.9f", 0x020000, 0x65c2bed6, BRF_GRA | CPS1_TILES }, + { "kd_11.7b", 0x020000, 0x147e3310, BRF_GRA | CPS1_TILES }, + { "kd_3.7a", 0x020000, 0x5d18bc83, BRF_GRA | CPS1_TILES }, + { "kd_15.11b", 0x020000, 0x57359746, BRF_GRA | CPS1_TILES }, + { "kd_7.11a", 0x020000, 0x7fe03079, BRF_GRA | CPS1_TILES }, + { "kd_26.8e", 0x020000, 0x57e5fab5, BRF_GRA | CPS1_TILES }, + { "kd_19.8c", 0x020000, 0xb1f30f7c, BRF_GRA | CPS1_TILES }, + { "kd_28.10e", 0x020000, 0x3a424135, BRF_GRA | CPS1_TILES }, + { "kd_21.10c", 0x020000, 0xce10d2c3, BRF_GRA | CPS1_TILES }, + { "kd_12.8b", 0x020000, 0xa6042aa2, BRF_GRA | CPS1_TILES }, + { "kd_4.8a", 0x020000, 0x0ce0ba30, BRF_GRA | CPS1_TILES }, + { "kd_16.12b", 0x020000, 0x63dcb7e0, BRF_GRA | CPS1_TILES }, + { "kd_8.12a", 0x020000, 0xc69b77ae, BRF_GRA | CPS1_TILES }, + { "kd_27.9e", 0x020000, 0x40d7bfed, BRF_GRA | CPS1_TILES }, + { "kd_20.9c", 0x020000, 0x01c1f399, BRF_GRA | CPS1_TILES }, + { "kd_29.11e", 0x020000, 0xa1eeac03, BRF_GRA | CPS1_TILES }, + { "kd_22.11c", 0x020000, 0x5ade98eb, BRF_GRA | CPS1_TILES }, + + { "kd_23.13b", 0x010000, 0xbac6ec26, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd_30.12c", 0x020000, 0x4c63181d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd_31.13c", 0x020000, 0x92941b80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "kd22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Kodja) +STD_ROM_FN(Kodja) + +static struct BurnRomInfo KodbRomDesc[] = { + { "3.ic172", 0x080000, 0x036dd74c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "4.ic171", 0x080000, 0x3e4b7295, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "cp.ic90", 0x080000, 0xe3b8589e, BRF_GRA | CPS1_TILES }, + { "dp.ic89", 0x080000, 0x3eec9580, BRF_GRA | CPS1_TILES }, + { "ap.ic88", 0x080000, 0xfdf5f163, BRF_GRA | CPS1_TILES }, + { "bp.ic87", 0x080000, 0x4e1c52b7, BRF_GRA | CPS1_TILES }, + { "ci.ic91", 0x080000, 0x22228bc5, BRF_GRA | CPS1_TILES }, + { "di.ic92", 0x080000, 0xab031763, BRF_GRA | CPS1_TILES }, + { "ai.ic93", 0x080000, 0xcffbf4be, BRF_GRA | CPS1_TILES }, + { "bi.ic94", 0x080000, 0x4a1b43fe, BRF_GRA | CPS1_TILES }, + + { "1.ic28", 0x010000, 0x01cae60c, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "2.ic19", 0x040000, 0xa2db1575, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Kodb) +STD_ROM_FN(Kodb) + +static struct BurnRomInfo KodhRomDesc[] = { + { "23.096", 0x080000, 0xdaf89cfb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "22.096", 0x080000, 0xc83e19d8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "1.096", 0x080000, 0x09261881, BRF_GRA | CPS1_TILES }, + { "2.096", 0x080000, 0xbc121ff2, BRF_GRA | CPS1_TILES }, + { "3.096", 0x080000, 0xf463ae22, BRF_GRA | CPS1_TILES }, + { "4.096", 0x080000, 0x01308733, BRF_GRA | CPS1_TILES }, + { "kod11.rom", 0x080000, 0x113358f3, BRF_GRA | CPS1_TILES }, + { "kod13.rom", 0x080000, 0x38853c44, BRF_GRA | CPS1_TILES }, + { "7.096", 0x080000, 0xc7ab4704, BRF_GRA | CPS1_TILES }, + { "kod12.rom", 0x080000, 0x402b9b4f, BRF_GRA | CPS1_TILES }, + + { "kd09.bin", 0x010000, 0xbac6ec26, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "kd18.bin", 0x020000, 0x4c63181d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "kd19.bin", 0x020000, 0x92941b80, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Kodh) +STD_ROM_FN(Kodh) + +static struct BurnRomInfo MegamanRomDesc[] = { + { "rcmu_23b.8f", 0x080000, 0x1cd33c7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcmu_22b.7f", 0x080000, 0x708268c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcmu_21a.6f", 0x080000, 0x4376ea95, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "rcm_01.3a", 0x080000, 0x6ecdf13f, BRF_GRA | CPS1_TILES }, + { "rcm_03.5a", 0x080000, 0x944d4f0f, BRF_GRA | CPS1_TILES }, + { "rcm_02.4a", 0x080000, 0x36f3073c, BRF_GRA | CPS1_TILES }, + { "rcm_04.6a", 0x080000, 0x54e622ff, BRF_GRA | CPS1_TILES }, + { "rcm_05.7a", 0x080000, 0x5dd131fd, BRF_GRA | CPS1_TILES }, + { "rcm_07.9a", 0x080000, 0xf0faf813, BRF_GRA | CPS1_TILES }, + { "rcm_06.8a", 0x080000, 0x826de013, BRF_GRA | CPS1_TILES }, + { "rcm_08.10a", 0x080000, 0xfbff64cf, BRF_GRA | CPS1_TILES }, + { "rcm_10.3c", 0x080000, 0x4dc8ada9, BRF_GRA | CPS1_TILES }, + { "rcm_12.5c", 0x080000, 0xf2b9ee06, BRF_GRA | CPS1_TILES }, + { "rcm_11.4c", 0x080000, 0xfed5f203, BRF_GRA | CPS1_TILES }, + { "rcm_13.6c", 0x080000, 0x5069d4a9, BRF_GRA | CPS1_TILES }, + { "rcm_14.7c", 0x080000, 0x303be3bd, BRF_GRA | CPS1_TILES }, + { "rcm_16.9c", 0x080000, 0x4f2d372f, BRF_GRA | CPS1_TILES }, + { "rcm_15.8c", 0x080000, 0x93d97fde, BRF_GRA | CPS1_TILES }, + { "rcm_17.10c", 0x080000, 0x92371042, BRF_GRA | CPS1_TILES }, + + { "rcm_09.11a", 0x010000, 0x22ac8f5f, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rcm_18.11c", 0x020000, 0x80f1f8aa, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rcm_19.12c", 0x020000, 0xf257dbe1, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rcm63b.1a", 0x000117, 0x84acd494, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Megaman) +STD_ROM_FN(Megaman) + +static struct BurnRomInfo MegamanaRomDesc[] = { + { "rcma_23b.8f", 0x080000, 0x61e4a397, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcma_22b.7f", 0x080000, 0x708268c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcma_21a.6f", 0x080000, 0x4376ea95, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "rcm_01.3a", 0x080000, 0x6ecdf13f, BRF_GRA | CPS1_TILES }, + { "rcm_02.4a", 0x080000, 0x944d4f0f, BRF_GRA | CPS1_TILES }, + { "rcm_03.5a", 0x080000, 0x36f3073c, BRF_GRA | CPS1_TILES }, + { "rcm_04.6a", 0x080000, 0x54e622ff, BRF_GRA | CPS1_TILES }, + { "rcm_05.7a", 0x080000, 0x5dd131fd, BRF_GRA | CPS1_TILES }, + { "rcm_06.8a", 0x080000, 0xf0faf813, BRF_GRA | CPS1_TILES }, + { "rcm_07.9a", 0x080000, 0x826de013, BRF_GRA | CPS1_TILES }, + { "rcm_08.10a", 0x080000, 0xfbff64cf, BRF_GRA | CPS1_TILES }, + { "rcm_10.3c", 0x080000, 0x4dc8ada9, BRF_GRA | CPS1_TILES }, + { "rcm_11.4c", 0x080000, 0xf2b9ee06, BRF_GRA | CPS1_TILES }, + { "rcm_12.5c", 0x080000, 0xfed5f203, BRF_GRA | CPS1_TILES }, + { "rcm_13.6c", 0x080000, 0x5069d4a9, BRF_GRA | CPS1_TILES }, + { "rcm_14.7c", 0x080000, 0x303be3bd, BRF_GRA | CPS1_TILES }, + { "rcm_15.8c", 0x080000, 0x4f2d372f, BRF_GRA | CPS1_TILES }, + { "rcm_16.9c", 0x080000, 0x93d97fde, BRF_GRA | CPS1_TILES }, + { "rcm_17.10c", 0x080000, 0x92371042, BRF_GRA | CPS1_TILES }, + + { "rcm_09.12a", 0x020000, 0x9632d6ef, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rcm_18.11c", 0x020000, 0x80f1f8aa, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rcm_19.12c", 0x020000, 0xf257dbe1, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rcm63b.1a", 0x000117, 0x84acd494, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Megamana) +STD_ROM_FN(Megamana) + +static struct BurnRomInfo RockmanjRomDesc[] = { + { "rcm_23a.8f", 0x080000, 0xefd96cb2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcm_22a.7f", 0x080000, 0x8729a689, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "rcm_21a.6f", 0x080000, 0x517ccde2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "rcm_01.3a", 0x080000, 0x6ecdf13f, BRF_GRA | CPS1_TILES }, + { "rcm_02.4a", 0x080000, 0x944d4f0f, BRF_GRA | CPS1_TILES }, + { "rcm_03.5a", 0x080000, 0x36f3073c, BRF_GRA | CPS1_TILES }, + { "rcm_04.6a", 0x080000, 0x54e622ff, BRF_GRA | CPS1_TILES }, + { "rcm_05.7a", 0x080000, 0x5dd131fd, BRF_GRA | CPS1_TILES }, + { "rcm_06.8a", 0x080000, 0xf0faf813, BRF_GRA | CPS1_TILES }, + { "rcm_07.9a", 0x080000, 0x826de013, BRF_GRA | CPS1_TILES }, + { "rcm_08.10a", 0x080000, 0xfbff64cf, BRF_GRA | CPS1_TILES }, + { "rcm_10.3c", 0x080000, 0x4dc8ada9, BRF_GRA | CPS1_TILES }, + { "rcm_11.4c", 0x080000, 0xf2b9ee06, BRF_GRA | CPS1_TILES }, + { "rcm_12.5c", 0x080000, 0xfed5f203, BRF_GRA | CPS1_TILES }, + { "rcm_13.6c", 0x080000, 0x5069d4a9, BRF_GRA | CPS1_TILES }, + { "rcm_14.7c", 0x080000, 0x303be3bd, BRF_GRA | CPS1_TILES }, + { "rcm_15.8c", 0x080000, 0x4f2d372f, BRF_GRA | CPS1_TILES }, + { "rcm_16.9c", 0x080000, 0x93d97fde, BRF_GRA | CPS1_TILES }, + { "rcm_17.10c", 0x080000, 0x92371042, BRF_GRA | CPS1_TILES }, + + { "rcm_09.12a", 0x020000, 0x9632d6ef, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "rcm_18.11c", 0x020000, 0x80f1f8aa, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "rcm_19.12c", 0x020000, 0xf257dbe1, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "rcm63b.1a", 0x000117, 0x84acd494, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Rockmanj) +STD_ROM_FN(Rockmanj) + +static struct BurnRomInfo MercsRomDesc[] = { + { "so2_30e.11f", 0x020000, 0xe17f9bf7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_35e.11h", 0x020000, 0x78e63575, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_31e.12f", 0x020000, 0x51204d36, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_36e.12h", 0x020000, 0x9cfba8b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2-32m.8h", 0x080000, 0x2eb5cf0c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "so2-6m.8a", 0x080000, 0xaa6102af, BRF_GRA | CPS1_TILES }, + { "so2-8m.10a", 0x080000, 0x839e6869, BRF_GRA | CPS1_TILES }, + { "so2-2m.4a", 0x080000, 0x597c2875, BRF_GRA | CPS1_TILES }, + { "so2-4m.6a", 0x080000, 0x912a9ca0, BRF_GRA | CPS1_TILES }, + { "so2_24.7d", 0x020000, 0x3f254efe, BRF_GRA | CPS1_TILES }, + { "so2_14.7c", 0x020000, 0xf5a8905e, BRF_GRA | CPS1_TILES }, + { "so2_26.9d", 0x020000, 0xf3aa5a4a, BRF_GRA | CPS1_TILES }, + { "so2_16.9c", 0x020000, 0xb43cd1a8, BRF_GRA | CPS1_TILES }, + { "so2_20.3d", 0x020000, 0x8ca751a3, BRF_GRA | CPS1_TILES }, + { "so2_10.3c", 0x020000, 0xe9f569fd, BRF_GRA | CPS1_TILES }, + { "so2_22.5d", 0x020000, 0xfce9a377, BRF_GRA | CPS1_TILES }, + { "so2_12.5c", 0x020000, 0xb7df8a06, BRF_GRA | CPS1_TILES }, + + { "so2_09.12b", 0x010000, 0xd09d7c7a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "so2_18.11c", 0x020000, 0xbbea1643, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "so2_19.12c", 0x020000, 0xac58aa71, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "o224b.1a", 0x000117, 0xc211c8cd, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "c628", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Mercs) +STD_ROM_FN(Mercs) + +static struct BurnRomInfo MercsuRomDesc[] = { + { "so2_30a.11f", 0x020000, 0xe4e725d7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_35a.11h", 0x020000, 0xe7843445, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_31a.12f", 0x020000, 0xc0b91dea, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_36a.12h", 0x020000, 0x591edf6c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2-32m.8h", 0x080000, 0x2eb5cf0c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "so2-6m.8a", 0x080000, 0xaa6102af, BRF_GRA | CPS1_TILES }, + { "so2-8m.10a", 0x080000, 0x839e6869, BRF_GRA | CPS1_TILES }, + { "so2-2m.4a", 0x080000, 0x597c2875, BRF_GRA | CPS1_TILES }, + { "so2-4m.6a", 0x080000, 0x912a9ca0, BRF_GRA | CPS1_TILES }, + { "so2_24.7d", 0x020000, 0x3f254efe, BRF_GRA | CPS1_TILES }, + { "so2_14.7c", 0x020000, 0xf5a8905e, BRF_GRA | CPS1_TILES }, + { "so2_26.9d", 0x020000, 0xf3aa5a4a, BRF_GRA | CPS1_TILES }, + { "so2_16.9c", 0x020000, 0xb43cd1a8, BRF_GRA | CPS1_TILES }, + { "so2_20.3d", 0x020000, 0x8ca751a3, BRF_GRA | CPS1_TILES }, + { "so2_10.3c", 0x020000, 0xe9f569fd, BRF_GRA | CPS1_TILES }, + { "so2_22.5d", 0x020000, 0xfce9a377, BRF_GRA | CPS1_TILES }, + { "so2_12.5c", 0x020000, 0xb7df8a06, BRF_GRA | CPS1_TILES }, + + { "so2_09.12b", 0x010000, 0xd09d7c7a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "so2_18.11c", 0x020000, 0xbbea1643, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "so2_19.12c", 0x020000, 0xac58aa71, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "o224b.1a", 0x000117, 0xc211c8cd, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "c628", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Mercsu) +STD_ROM_FN(Mercsu) + +static struct BurnRomInfo Mercsur1RomDesc[] = { + { "so2_30.11f", 0x020000, 0xe17f9bf7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_35.11h", 0x020000, 0x4477df61, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_31.12f", 0x020000, 0x51204d36, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_36.12h", 0x020000, 0x9cfba8b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2-32m.8h", 0x080000, 0x2eb5cf0c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "so2-6m.8a", 0x080000, 0xaa6102af, BRF_GRA | CPS1_TILES }, + { "so2-8m.10a", 0x080000, 0x839e6869, BRF_GRA | CPS1_TILES }, + { "so2-2m.4a", 0x080000, 0x597c2875, BRF_GRA | CPS1_TILES }, + { "so2-4m.6a", 0x080000, 0x912a9ca0, BRF_GRA | CPS1_TILES }, + { "so2_24.7d", 0x020000, 0x3f254efe, BRF_GRA | CPS1_TILES }, + { "so2_14.7c", 0x020000, 0xf5a8905e, BRF_GRA | CPS1_TILES }, + { "so2_26.9d", 0x020000, 0xf3aa5a4a, BRF_GRA | CPS1_TILES }, + { "so2_16.9c", 0x020000, 0xb43cd1a8, BRF_GRA | CPS1_TILES }, + { "so2_20.3d", 0x020000, 0x8ca751a3, BRF_GRA | CPS1_TILES }, + { "so2_10.3c", 0x020000, 0xe9f569fd, BRF_GRA | CPS1_TILES }, + { "so2_22.5d", 0x020000, 0xfce9a377, BRF_GRA | CPS1_TILES }, + { "so2_12.5c", 0x020000, 0xb7df8a06, BRF_GRA | CPS1_TILES }, + + { "so2_09.12b", 0x010000, 0xd09d7c7a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "so2_18.11c", 0x020000, 0xbbea1643, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "so2_19.12c", 0x020000, 0xac58aa71, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "o224b.1a", 0x000117, 0xc211c8cd, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, + { "c628", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Mercsur1) +STD_ROM_FN(Mercsur1) + +static struct BurnRomInfo MercsjRomDesc[] = { + { "so2_36.12f", 0x020000, 0xe17f9bf7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_42.12h", 0x020000, 0x2c3884c6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_37.13f", 0x020000, 0x51204d36, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_43.13h", 0x020000, 0x9cfba8b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_34.10f", 0x020000, 0xb8dae95f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_40.10h", 0x020000, 0xde37771c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_35.11f", 0x020000, 0x7d24394d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "so2_41.11h", 0x020000, 0x914f85e0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "so2_09.4b", 0x020000, 0x690c261d, BRF_GRA | CPS1_TILES }, + { "so2_01.4a", 0x020000, 0x31fd2715, BRF_GRA | CPS1_TILES }, + { "so2_13.9b", 0x020000, 0xb5e48282, BRF_GRA | CPS1_TILES }, + { "so2_05.9a", 0x020000, 0x54bed82c, BRF_GRA | CPS1_TILES }, + { "so2_24.5e", 0x020000, 0x78b6f0cb, BRF_GRA | CPS1_TILES }, + { "so2_17.5c", 0x020000, 0xe78bb308, BRF_GRA | CPS1_TILES }, + { "so2_38.8h", 0x020000, 0x0010a9a2, BRF_GRA | CPS1_TILES }, + { "so2_32.8f", 0x020000, 0x75dffc9a, BRF_GRA | CPS1_TILES }, + { "so2_10.5b", 0x020000, 0x2f871714, BRF_GRA | CPS1_TILES }, + { "so2_02.5a", 0x020000, 0xb4b2a0b7, BRF_GRA | CPS1_TILES }, + { "so2_14.10b", 0x020000, 0x737a744b, BRF_GRA | CPS1_TILES }, + { "so2_06.10a", 0x020000, 0x9d756f51, BRF_GRA | CPS1_TILES }, + { "so2_25.7e", 0x020000, 0x6d0e05d6, BRF_GRA | CPS1_TILES }, + { "so2_18.7c", 0x020000, 0x96f61f4e, BRF_GRA | CPS1_TILES }, + { "so2_39.9h", 0x020000, 0xd52ba336, BRF_GRA | CPS1_TILES }, + { "so2_33.9f", 0x020000, 0x39b90d25, BRF_GRA | CPS1_TILES }, + { "so2_11.7b", 0x020000, 0x3f254efe, BRF_GRA | CPS1_TILES }, + { "so2_03.7a", 0x020000, 0xf5a8905e, BRF_GRA | CPS1_TILES }, + { "so2_15.11b", 0x020000, 0xf3aa5a4a, BRF_GRA | CPS1_TILES }, + { "so2_07.11a", 0x020000, 0xb43cd1a8, BRF_GRA | CPS1_TILES }, + { "so2_26.8e", 0x020000, 0x8ca751a3, BRF_GRA | CPS1_TILES }, + { "so2_19.8c", 0x020000, 0xe9f569fd, BRF_GRA | CPS1_TILES }, + { "so2_28.10e", 0x020000, 0xfce9a377, BRF_GRA | CPS1_TILES }, + { "so2_21.10c", 0x020000, 0xb7df8a06, BRF_GRA | CPS1_TILES }, + + { "so2_23.13b", 0x010000, 0xd09d7c7a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "so2_30.12c", 0x020000, 0xbbea1643, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "so2_31.13c", 0x020000, 0xac58aa71, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "o222b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12e", 0x000117, 0xad52b90c, BRF_OPT }, + { "c628", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Mercsj) +STD_ROM_FN(Mercsj) + +static struct BurnRomInfo MswordRomDesc[] = { + { "mse_30.11f", 0x020000, 0x03fc8dbc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mse_35.11h", 0x020000, 0xd5bf66cd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mse_31.12f", 0x020000, 0x30332bcf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mse_36.12h", 0x020000, 0x8f7d6ce9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms-32m.8h", 0x080000, 0x2475ddfc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ms-5m.7a", 0x080000, 0xc00fe7e2, BRF_GRA | CPS1_TILES }, + { "ms-7m.9a", 0x080000, 0x4ccacac5, BRF_GRA | CPS1_TILES }, + { "ms-1m.3a", 0x080000, 0x0d2bbe00, BRF_GRA | CPS1_TILES }, + { "ms-3m.5a", 0x080000, 0x3a1a5bf4, BRF_GRA | CPS1_TILES }, + + { "ms_09.12b", 0x010000, 0x57b29519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ms_18.11c", 0x020000, 0xfb64e90d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ms_19.12c", 0x020000, 0x74f892b9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ms24b.1a", 0x000117, 0x636dbe6d, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Msword) +STD_ROM_FN(Msword) + +static struct BurnRomInfo Mswordr1RomDesc[] = { + { "ms_30.11f", 0x020000, 0x21c1f078, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_35.11h", 0x020000, 0xa540a73a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_31.12f", 0x020000, 0xd7e762b5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_36.12h", 0x020000, 0x66f2dcdb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms-32m.8h", 0x080000, 0x2475ddfc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ms-5m.7a", 0x080000, 0xc00fe7e2, BRF_GRA | CPS1_TILES }, + { "ms-7m.9a", 0x080000, 0x4ccacac5, BRF_GRA | CPS1_TILES }, + { "ms-1m.3a", 0x080000, 0x0d2bbe00, BRF_GRA | CPS1_TILES }, + { "ms-3m.5a", 0x080000, 0x3a1a5bf4, BRF_GRA | CPS1_TILES }, + + { "ms_09.12b", 0x010000, 0x57b29519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ms_18.11c", 0x020000, 0xfb64e90d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ms_19.12c", 0x020000, 0x74f892b9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ms24b.1a", 0x000117, 0x636dbe6d, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Mswordr1) +STD_ROM_FN(Mswordr1) + +static struct BurnRomInfo MswordjRomDesc[] = { + { "msj_36.12f", 0x020000, 0x04f0ef50, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msj_42.12h", 0x020000, 0x9fcbb9cd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msj_37.13f", 0x020000, 0x6c060d70, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msj_43.13h", 0x020000, 0xaec77787, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_34.10f", 0x020000, 0x0e59a62d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_40.10h", 0x020000, 0xbabade3a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_35.11f", 0x020000, 0x03da99d1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms_41.11h", 0x020000, 0xfadf99ea, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ms_09.4b", 0x020000, 0x4adee6f6, BRF_GRA | CPS1_TILES }, + { "ms_01.4a", 0x020000, 0xf7ab1b88, BRF_GRA | CPS1_TILES }, + { "ms_13.9b", 0x020000, 0xe01adc4b, BRF_GRA | CPS1_TILES }, + { "ms_05.9a", 0x020000, 0xf62c2369, BRF_GRA | CPS1_TILES }, + { "ms_24.5e", 0x020000, 0xbe64a3a1, BRF_GRA | CPS1_TILES }, + { "ms_17.5c", 0x020000, 0x0bc1665f, BRF_GRA | CPS1_TILES }, + { "ms_38.8h", 0x020000, 0x904a2ed5, BRF_GRA | CPS1_TILES }, + { "ms_32.8f", 0x020000, 0x3d89c530, BRF_GRA | CPS1_TILES }, + { "ms_10.5b", 0x020000, 0xf02c0718, BRF_GRA | CPS1_TILES }, + { "ms_02.5a", 0x020000, 0xd071a405, BRF_GRA | CPS1_TILES }, + { "ms_14.10b", 0x020000, 0xdfb2e4df, BRF_GRA | CPS1_TILES }, + { "ms_06.10a", 0x020000, 0xd3ce2a91, BRF_GRA | CPS1_TILES }, + { "ms_25.7e", 0x020000, 0x0f199d56, BRF_GRA | CPS1_TILES }, + { "ms_18.7c", 0x020000, 0x1ba76df2, BRF_GRA | CPS1_TILES }, + { "ms_39.9h", 0x020000, 0x01efce86, BRF_GRA | CPS1_TILES }, + { "ms_33.9f", 0x020000, 0xce25defc, BRF_GRA | CPS1_TILES }, + + { "ms_23.13b", 0x010000, 0x57b29519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ms_30.12c", 0x020000, 0xfb64e90d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ms_31.13c", 0x020000, 0x74f892b9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ms22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Mswordj) +STD_ROM_FN(Mswordj) + +static struct BurnRomInfo MsworduRomDesc[] = { + { "msu_30.11f", 0x020000, 0xd963c816, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msu_35.11h", 0x020000, 0x72f179b3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msu_31.12f", 0x020000, 0x20cd7904, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "msu_36.12h", 0x020000, 0xbf88c080, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ms-32m.8h", 0x080000, 0x2475ddfc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ms-5m.7a", 0x080000, 0xc00fe7e2, BRF_GRA | CPS1_TILES }, + { "ms-7m.9a", 0x080000, 0x4ccacac5, BRF_GRA | CPS1_TILES }, + { "ms-1m.3a", 0x080000, 0x0d2bbe00, BRF_GRA | CPS1_TILES }, + { "ms-3m.5a", 0x080000, 0x3a1a5bf4, BRF_GRA | CPS1_TILES }, + + { "ms_09.12b", 0x010000, 0x57b29519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ms_18.11c", 0x020000, 0xfb64e90d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ms_19.12c", 0x020000, 0x74f892b9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ms24b.1a", 0x000117, 0x636dbe6d, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Mswordu) +STD_ROM_FN(Mswordu) + +static struct BurnRomInfo MtwinsRomDesc[] = { + { "che_30.11f", 0x020000, 0x9a2a2db1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "che_35.11h", 0x020000, 0xa7f96b02, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "che_31.12f", 0x020000, 0xbbff8a99, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "che_36.12h", 0x020000, 0x0fa00c39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ck-32m.8h", 0x080000, 0x9b70bd41, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ck-5m.7a", 0x080000, 0x4ec75f15, BRF_GRA | CPS1_TILES }, + { "ck-7m.9a", 0x080000, 0xd85d00d6, BRF_GRA | CPS1_TILES }, + { "ck-1m.3a", 0x080000, 0xf33ca9d4, BRF_GRA | CPS1_TILES }, + { "ck-3m.5a", 0x080000, 0x0ba2047f, BRF_GRA | CPS1_TILES }, + + { "ch_09.12b", 0x010000, 0x4d4255b7, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ch_18.11c", 0x020000, 0xf909e8de, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ch_19.12c", 0x020000, 0xfc158cf7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ck24b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Mtwins) +STD_ROM_FN(Mtwins) + +static struct BurnRomInfo ChikijRomDesc[] = { + { "chj_36a.12f", 0x020000, 0xec1328d8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "chj_42a.12h", 0x020000, 0x4ae13503, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "chj_37a.13f", 0x020000, 0x46d2cf7b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "chj_43a.13h", 0x020000, 0x8d387fe8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ch_34.10f", 0x020000, 0x609ed2f9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ch_40.10h", 0x020000, 0xbe0d8301, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ch_35.11f", 0x020000, 0xb810867f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ch_41.11h", 0x020000, 0x8ad96155, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ch_09.4b", 0x020000, 0x567ab3ca, BRF_GRA | CPS1_TILES }, + { "ch_01.4a", 0x020000, 0x7f3b7b56, BRF_GRA | CPS1_TILES }, + { "ch_13.9b", 0x020000, 0x12a7a8ba, BRF_GRA | CPS1_TILES }, + { "ch_05.9a", 0x020000, 0x6c1afb9a, BRF_GRA | CPS1_TILES }, + { "ch_24.5e", 0x020000, 0x9cb6e6bc, BRF_GRA | CPS1_TILES }, + { "ch_17.5c", 0x020000, 0xfe490846, BRF_GRA | CPS1_TILES }, + { "ch_38.8h", 0x020000, 0x6e5c8cb6, BRF_GRA | CPS1_TILES }, + { "ch_32.8f", 0x020000, 0x317d27b0, BRF_GRA | CPS1_TILES }, + { "ch_10.5b", 0x020000, 0xe8251a9b, BRF_GRA | CPS1_TILES }, + { "ch_02.5a", 0x020000, 0x7c8c88fb, BRF_GRA | CPS1_TILES }, + { "ch_14.10b", 0x020000, 0x4012ec4b, BRF_GRA | CPS1_TILES }, + { "ch_06.10a", 0x020000, 0x81884b2b, BRF_GRA | CPS1_TILES }, + { "ch_25.7e", 0x020000, 0x1dfcbac5, BRF_GRA | CPS1_TILES }, + { "ch_18.7c", 0x020000, 0x516a34d1, BRF_GRA | CPS1_TILES }, + { "ch_39.9h", 0x020000, 0x872fb2a4, BRF_GRA | CPS1_TILES }, + { "ch_33.9f", 0x020000, 0x30dc5ded, BRF_GRA | CPS1_TILES }, + + { "ch_23.13b", 0x010000, 0x4d4255b7, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ch_30.12c", 0x020000, 0xf909e8de, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "ch_31.13c", 0x020000, 0xfc158cf7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ck22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Chikij) +STD_ROM_FN(Chikij) + +static struct BurnRomInfo NemoRomDesc[] = { + { "nme_30a.11f", 0x020000, 0xd2c03e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nme_35a.11h", 0x020000, 0x5fd31661, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nme_31a.12f", 0x020000, 0xb2bd4f6f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nme_36a.12h", 0x020000, 0xee9450e3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nm-32m.8h", 0x080000, 0xd6d1add3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "nm-5m.7a", 0x080000, 0x487b8747, BRF_GRA | CPS1_TILES }, + { "nm-7m.9a", 0x080000, 0x203dc8c6, BRF_GRA | CPS1_TILES }, + { "nm-1m.3a", 0x080000, 0x9e878024, BRF_GRA | CPS1_TILES }, + { "nm-3m.5a", 0x080000, 0xbb01e6b6, BRF_GRA | CPS1_TILES }, + + { "nme_09.12b", 0x010000, 0x0f4b0581, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "nme_18.11c", 0x020000, 0xbab333d4, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "nme_19.12c", 0x020000, 0x2650a0a8, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "nm24b.1a", 0x000117, 0x7b25bac6, BRF_OPT }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Nemo) +STD_ROM_FN(Nemo) + +static struct BurnRomInfo NemojRomDesc[] = { + { "nmj_36a.12f", 0x020000, 0xdaeceabb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nmj_42a.12h", 0x020000, 0x55024740, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nmj_37a.13f", 0x020000, 0x619068b6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nmj_43a.13h", 0x020000, 0xa948a53b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nm_34.10f", 0x020000, 0x5737feed, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nm_40.10h", 0x020000, 0x8a4099f3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nm_35.11f", 0x020000, 0xbd11a7f8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "nm_41.11h", 0x020000, 0x6309603d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "nm_09.4b", 0x020000, 0x9d60d286, BRF_GRA | CPS1_TILES }, + { "nm_01.4a", 0x020000, 0x8a83f7c4, BRF_GRA | CPS1_TILES }, + { "nm_13.9b", 0x020000, 0xa4909fe0, BRF_GRA | CPS1_TILES }, + { "nm_05.9a", 0x020000, 0x16db1e61, BRF_GRA | CPS1_TILES }, + { "nm_24.5e", 0x020000, 0x3312c648, BRF_GRA | CPS1_TILES }, + { "nm_17.5c", 0x020000, 0xccfc50e2, BRF_GRA | CPS1_TILES }, + { "nm_38.8h", 0x020000, 0xae98a997, BRF_GRA | CPS1_TILES }, + { "nm_32.8f", 0x020000, 0xb3704dde, BRF_GRA | CPS1_TILES }, + { "nm_10.5b", 0x020000, 0x33c1388c, BRF_GRA | CPS1_TILES }, + { "nm_02.5a", 0x020000, 0x84c69469, BRF_GRA | CPS1_TILES }, + { "nm_14.10b", 0x020000, 0x66612270, BRF_GRA | CPS1_TILES }, + { "nm_06.10a", 0x020000, 0x8b9bcf95, BRF_GRA | CPS1_TILES }, + { "nm_25.7e", 0x020000, 0xacfc84d2, BRF_GRA | CPS1_TILES }, + { "nm_18.7c", 0x020000, 0x4347deed, BRF_GRA | CPS1_TILES }, + { "nm_39.9h", 0x020000, 0x6a274ecd, BRF_GRA | CPS1_TILES }, + { "nm_33.9f", 0x020000, 0xc469dc74, BRF_GRA | CPS1_TILES }, + + { "nm_23.13b", 0x010000, 0x8d3c5a42, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "nm_30.12c", 0x020000, 0xbab333d4, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "nm_31.13c", 0x020000, 0x2650a0a8, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "nm22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Nemoj) +STD_ROM_FN(Nemoj) + +static struct BurnRomInfo Pang3RomDesc[] = { + { "pa3e_17a.11l", 0x080000, 0xa213fa80, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "pa3e_16a.10l", 0x080000, 0x7169ea67, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "pa3-01m.2c", 0x200000, 0x068a152c, BRF_GRA | CPS1_TILES }, + { "pa3-07m.2f", 0x200000, 0x3a4a619d, BRF_GRA | CPS1_TILES }, + + { "pa3_11.11f", 0x008000, 0x90a08c46, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pa3_05.10d", 0x020000, 0x73a10d5d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pa3_06.11d", 0x020000, 0xaffa4f82, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cp1b1f.1f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "cp1b8k.8k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "cp1b9ka.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Pang3) +STD_ROM_FN(Pang3) + +static struct BurnRomInfo Pang3r1RomDesc[] = { + { "pa3e_17.11l", 0x080000, 0xd7041d32, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "pa3e_16.10l", 0x080000, 0x1be9a483, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "pa3-01m.2c", 0x200000, 0x068a152c, BRF_GRA | CPS1_TILES }, + { "pa3-07m.2f", 0x200000, 0x3a4a619d, BRF_GRA | CPS1_TILES }, + + { "pa3_11.bin", 0x020000, 0xcb1423a2, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pa3_05.10d", 0x020000, 0x73a10d5d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pa3_06.11d", 0x020000, 0xaffa4f82, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cp1b1f.1f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "cp1b8k.8k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "cp1b9ka.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Pang3r1) +STD_ROM_FN(Pang3r1) + +static struct BurnRomInfo Pang3nRomDesc[] = { + { "pa3w_17.11l", 0x080000, 0x12138234, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "pa3w_16.10l", 0x080000, 0xd1ba585c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "pa3-01m.2c", 0x200000, 0x068a152c, BRF_GRA | CPS1_TILES }, + { "pa3-07m.2f", 0x200000, 0x3a4a619d, BRF_GRA | CPS1_TILES }, + + { "pa3_11.11f", 0x008000, 0x90a08c46, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pa3_05.10d", 0x020000, 0x73a10d5d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pa3_06.11d", 0x020000, 0xaffa4f82, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cp1b1f.1f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "cp1b8k.8k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "cp1b9ka.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Pang3n) +STD_ROM_FN(Pang3n) + +static struct BurnRomInfo Pang3jRomDesc[] = { + { "pa3j_17.11l", 0x080000, 0x21f6e51f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "pa3j_16.10l", 0x080000, 0xca1d7897, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "pa3-01m.2c", 0x200000, 0x068a152c, BRF_GRA | CPS1_TILES }, + { "pa3-07m.2f", 0x200000, 0x3a4a619d, BRF_GRA | CPS1_TILES }, + + { "pa3_11.11f", 0x008000, 0x90a08c46, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pa3_05.10d", 0x020000, 0x73a10d5d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pa3_06.11d", 0x020000, 0xaffa4f82, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "cp1b1f.1f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "cp1b8k.8k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "cp1b9ka.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Pang3j) +STD_ROM_FN(Pang3j) + +static struct BurnRomInfo PnickjRomDesc[] = { + { "pnij_36.12f", 0x020000, 0x2d4ffb2b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pnij_42.12h", 0x020000, 0xc085dfaf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "pnij_09.4b", 0x020000, 0x48177b0a, BRF_GRA | CPS1_TILES }, + { "pnij_01.4a", 0x020000, 0x01a0f311, BRF_GRA | CPS1_TILES }, + { "pnij_13.9b", 0x020000, 0x406451b0, BRF_GRA | CPS1_TILES }, + { "pnij_05.9a", 0x020000, 0x8c515dc0, BRF_GRA | CPS1_TILES }, + { "pnij_26.5e", 0x020000, 0xe2af981e, BRF_GRA | CPS1_TILES }, + { "pnij_18.5c", 0x020000, 0xf17a0e56, BRF_GRA | CPS1_TILES }, + { "pnij_38.8h", 0x020000, 0xeb75bd8c, BRF_GRA | CPS1_TILES }, + { "pnij_32.8f", 0x020000, 0x84560bef, BRF_GRA | CPS1_TILES }, + { "pnij_10.5b", 0x020000, 0xc2acc171, BRF_GRA | CPS1_TILES }, + { "pnij_02.5a", 0x020000, 0x0e21fc33, BRF_GRA | CPS1_TILES }, + { "pnij_14.10b", 0x020000, 0x7fe59b19, BRF_GRA | CPS1_TILES }, + { "pnij_06.10a", 0x020000, 0x79f4bfe3, BRF_GRA | CPS1_TILES }, + { "pnij_27.7e", 0x020000, 0x83d5cb0e, BRF_GRA | CPS1_TILES }, + { "pnij_19.7c", 0x020000, 0xaf08b230, BRF_GRA | CPS1_TILES }, + { "pnij_39.9h", 0x020000, 0x70fbe579, BRF_GRA | CPS1_TILES }, + { "pnij_33.9f", 0x020000, 0x3ed2c680, BRF_GRA | CPS1_TILES }, + + { "pnij_17.13b", 0x010000, 0xe86f787a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pnij_24.12c", 0x020000, 0x5092257d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pnij_25.13c", 0x020000, 0x22109aaa, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "pkb10b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Pnickj) +STD_ROM_FN(Pnickj) + +static struct BurnRomInfo PunisherRomDesc[] = { + { "pse_26.11e", 0x020000, 0x389a99d2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_30.11f", 0x020000, 0x68fb06ac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_27.12e", 0x020000, 0x3eb181c3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_31.12f", 0x020000, 0x37108e7b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_24.9e", 0x020000, 0x0f434414, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_28.9f", 0x020000, 0xb732345d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_25.10e", 0x020000, 0xb77102e2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pse_29.10f", 0x020000, 0xec037bce, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ps_21.6f", 0x080000, 0x8affa5a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ps-1m.3a", 0x080000, 0x77b7ccab, BRF_GRA | CPS1_TILES }, + { "ps-3m.5a", 0x080000, 0x0122720b, BRF_GRA | CPS1_TILES }, + { "ps-2m.4a", 0x080000, 0x64fa58d4, BRF_GRA | CPS1_TILES }, + { "ps-4m.6a", 0x080000, 0x60da42c8, BRF_GRA | CPS1_TILES }, + { "ps-5m.7a", 0x080000, 0xc54ea839, BRF_GRA | CPS1_TILES }, + { "ps-7m.9a", 0x080000, 0x04c5acbd, BRF_GRA | CPS1_TILES }, + { "ps-6m.8a", 0x080000, 0xa544f4cc, BRF_GRA | CPS1_TILES }, + { "ps-8m.10a", 0x080000, 0x8f02f436, BRF_GRA | CPS1_TILES }, + + { "ps_q.5k", 0x020000, 0x49ff4446, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ps-q1.1k", 0x080000, 0x31fd8726, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q2.2k", 0x080000, 0x980a9eef, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q3.3k", 0x080000, 0x0dd44491, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q4.4k", 0x080000, 0xbed42f03, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "ps63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Punisher) +STD_ROM_FN(Punisher) + +static struct BurnRomInfo PunisheruRomDesc[] = { + { "psu_26.11e", 0x020000, 0x9236d121, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_30.11f", 0x020000, 0x8320e501, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_27.12e", 0x020000, 0x61c960a1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_31.12f", 0x020000, 0x78d4c298, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_24.9e", 0x020000, 0x1cfecad7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_28.9f", 0x020000, 0xbdf921c1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_25.10e", 0x020000, 0xc51acc94, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psu_29.10f", 0x020000, 0x52dce1ca, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ps_21.6f", 0x080000, 0x8affa5a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ps-1m.3a", 0x080000, 0x77b7ccab, BRF_GRA | CPS1_TILES }, + { "ps-3m.5a", 0x080000, 0x0122720b, BRF_GRA | CPS1_TILES }, + { "ps-2m.4a", 0x080000, 0x64fa58d4, BRF_GRA | CPS1_TILES }, + { "ps-4m.6a", 0x080000, 0x60da42c8, BRF_GRA | CPS1_TILES }, + { "ps-5m.7a", 0x080000, 0xc54ea839, BRF_GRA | CPS1_TILES }, + { "ps-7m.9a", 0x080000, 0x04c5acbd, BRF_GRA | CPS1_TILES }, + { "ps-6m.8a", 0x080000, 0xa544f4cc, BRF_GRA | CPS1_TILES }, + { "ps-8m.10a", 0x080000, 0x8f02f436, BRF_GRA | CPS1_TILES }, + + { "ps_q.5k", 0x020000, 0x49ff4446, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ps-q1.1k", 0x080000, 0x31fd8726, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q2.2k", 0x080000, 0x980a9eef, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q3.3k", 0x080000, 0x0dd44491, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps-q4.4k", 0x080000, 0xbed42f03, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "ps63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Punisheru) +STD_ROM_FN(Punisheru) + +static struct BurnRomInfo PunisherjRomDesc[] = { + { "psj23.bin", 0x080000, 0x6b2fda52, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "psj22.bin", 0x080000, 0xe01036bc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "ps_21.rom", 0x080000, 0x8affa5a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ps_gfx1.rom", 0x080000, 0x77b7ccab, BRF_GRA | CPS1_TILES }, + { "ps_gfx3.rom", 0x080000, 0x0122720b, BRF_GRA | CPS1_TILES }, + { "ps_gfx2.rom", 0x080000, 0x64fa58d4, BRF_GRA | CPS1_TILES }, + { "ps_gfx4.rom", 0x080000, 0x60da42c8, BRF_GRA | CPS1_TILES }, + { "ps_gfx5.rom", 0x080000, 0xc54ea839, BRF_GRA | CPS1_TILES }, + { "ps_gfx7.rom", 0x080000, 0x04c5acbd, BRF_GRA | CPS1_TILES }, + { "ps_gfx6.rom", 0x080000, 0xa544f4cc, BRF_GRA | CPS1_TILES }, + { "ps_gfx8.rom", 0x080000, 0x8f02f436, BRF_GRA | CPS1_TILES }, + + { "ps_q.rom", 0x020000, 0x49ff4446, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ps_q1.rom", 0x080000, 0x31fd8726, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps_q2.rom", 0x080000, 0x980a9eef, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps_q3.rom", 0x080000, 0x0dd44491, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "ps_q4.rom", 0x080000, 0xbed42f03, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "ps63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Punisherj) +STD_ROM_FN(Punisherj) + +static struct BurnRomInfo PunipicRomDesc[] = { + { "cpu5.bin", 0x080000, 0xc3151563, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cpu3.bin", 0x080000, 0x8c2593ac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cpu4.bin", 0x080000, 0x665a5485, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "cpu2.bin", 0x080000, 0xd7b13f39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "gfx9.bin", 0x080000, 0x9b9a887a, BRF_GRA | CPS1_TILES }, + { "gfx8.bin", 0x080000, 0x2b94287a, BRF_GRA | CPS1_TILES }, + { "gfx7.bin", 0x080000, 0xe9bd74f5, BRF_GRA | CPS1_TILES }, + { "gfx6.bin", 0x080000, 0xa5e1c8a4, BRF_GRA | CPS1_TILES }, + { "gfx13.bin", 0x080000, 0x6d75a193, BRF_GRA | CPS1_TILES }, + { "gfx12.bin", 0x080000, 0xa3c205c1, BRF_GRA | CPS1_TILES }, + { "gfx11.bin", 0x080000, 0x22f2ec92, BRF_GRA | CPS1_TILES }, + { "gfx10.bin", 0x080000, 0x763974c9, BRF_GRA | CPS1_TILES }, + + { "pic16c57", 0x004000, 0x00000000, BRF_PRG | BRF_NODUMP | CPS1_PIC }, + + { "sound.bin", 0x080000, 0xaeec9dc6, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Punipic) +STD_ROM_FN(Punipic) + +static struct BurnRomInfo Punipic2RomDesc[] = { + { "prg4.bin", 0x080000, 0xc3151563, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "prg3.bin", 0x080000, 0x8c2593ac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "prg2.bin", 0x080000, 0x665a5485, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "prg1.bin", 0x080000, 0xd7b13f39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "pu11256.bin", 0x200000, 0x6581faea, BRF_GRA | CPS1_TILES }, + { "pu13478.bin", 0x200000, 0x61613de4, BRF_GRA | CPS1_TILES }, + + { "pic16c57", 0x004000, 0x00000000, BRF_PRG | BRF_NODUMP | CPS1_PIC }, + + { "sound.bin", 0x080000, 0xaeec9dc6, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + { "93c46.bin", 0x000080, 0x36ab4e7d, BRF_OPT }, +}; + +STD_ROM_PICK(Punipic2) +STD_ROM_FN(Punipic2) + +static struct BurnRomInfo Punipic3RomDesc[] = { + { "psb5b.rom", 0x080000, 0x58f42c05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psb3b.rom", 0x080000, 0x90113db4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psb4a.rom", 0x080000, 0x665a5485, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "psb2a.rom", 0x080000, 0xd7b13f39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "psb-a.rom", 0x200000, 0x57f0f5e3, BRF_GRA | CPS1_TILES }, + { "psb-b.rom", 0x200000, 0xd9eb867e, BRF_GRA | CPS1_TILES }, +}; + +STD_ROM_PICK(Punipic3) +STD_ROM_FN(Punipic3) + +static struct BurnRomInfo PunisherbzRomDesc[] = { + { "23.096", 0x080000, 0xbfa45d23, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "22.096", 0x080000, 0x092578a4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "21.096", 0x080000, 0xd21ccddb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "20.096", 0x080000, 0xf9f334ce, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "1.096", 0x080000, 0xad468e07, BRF_GRA | CPS1_TILES }, + { "2.096", 0x080000, 0xb9fdb6b5, BRF_GRA | CPS1_TILES }, + { "3.096", 0x080000, 0xbe0b1a78, BRF_GRA | CPS1_TILES }, + { "4.096", 0x080000, 0xbba67a43, BRF_GRA | CPS1_TILES }, + { "ps_gfx5.rom", 0x080000, 0xc54ea839, BRF_GRA | CPS1_TILES }, + { "ps_gfx7.rom", 0x080000, 0x04c5acbd, BRF_GRA | CPS1_TILES }, + { "ps_gfx6.rom", 0x080000, 0xa544f4cc, BRF_GRA | CPS1_TILES }, + { "ps_gfx8.rom", 0x080000, 0x8f02f436, BRF_GRA | CPS1_TILES }, + + { "9.512", 0x010000, 0xb8367eb5, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "18.010", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "19.010", 0x020000, 0xeb5ca884, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Punisherbz) +STD_ROM_FN(Punisherbz) + +static struct BurnRomInfo QadRomDesc[] = { + { "qdu_36a.12f", 0x020000, 0xde9c24a0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "qdu_42a.12h", 0x020000, 0xcfe36f0c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "qdu_37a.13f", 0x020000, 0x10d22320, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "qdu_43a.13h", 0x020000, 0x15e6beb9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "qdu_09.4b", 0x020000, 0x8c3f9f44, BRF_GRA | CPS1_TILES }, + { "qdu_01.4a", 0x020000, 0xf688cf8f, BRF_GRA | CPS1_TILES }, + { "qdu_13.9b", 0x020000, 0xafbd551b, BRF_GRA | CPS1_TILES }, + { "qdu_05.9a", 0x020000, 0xc3db0910, BRF_GRA | CPS1_TILES }, + { "qdu_24.5e", 0x020000, 0x2f1bd0ec, BRF_GRA | CPS1_TILES }, + { "qdu_17.5c", 0x020000, 0xa812f9e2, BRF_GRA | CPS1_TILES }, + { "qdu_38.8h", 0x020000, 0xccdddd1f, BRF_GRA | CPS1_TILES }, + { "qdu_32.8f", 0x020000, 0xa8d295d3, BRF_GRA | CPS1_TILES }, + + { "qdu_23.13b", 0x010000, 0xcfb5264b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "qdu_30.12c", 0x020000, 0xf190da84, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "qdu_31.13c", 0x020000, 0xb7583f73, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "qd22b.1a", 0x000117, 0x783c53ab, BRF_OPT }, // b-board PLDs + { "iob1.12e", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Qad) +STD_ROM_FN(Qad) + +static struct BurnRomInfo QadjRomDesc[] = { + { "qad_23a.8f", 0x080000, 0x4d3553de, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "qad_22a.7f", 0x080000, 0x3191ddd0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "qad_01.3a", 0x080000, 0x9d853b57, BRF_GRA | CPS1_TILES }, + { "qad_02.4a", 0x080000, 0xb35976c4, BRF_GRA | CPS1_TILES }, + { "qad_03.5a", 0x080000, 0xcea4ca8c, BRF_GRA | CPS1_TILES }, + { "qad_04.6a", 0x080000, 0x41b74d1b, BRF_GRA | CPS1_TILES }, + + { "qad_09.12a", 0x010000, 0x733161cc, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "qad_18.11c", 0x020000, 0x2bfe6f6a, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "qad_19.12c", 0x020000, 0x13d3236b, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "qd63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Qadj) +STD_ROM_FN(Qadj) + +static struct BurnRomInfo Qtono2jRomDesc[] = { + { "tn2j_30.11e", 0x020000, 0x9226eb5e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_37.11f", 0x020000, 0xd1d30da1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_31.12e", 0x020000, 0x015e6a8a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_38.12f", 0x020000, 0x1f139bcc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_28.9e", 0x020000, 0x86d27f71, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_35.9f", 0x020000, 0x7a1ab87d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_29.10e", 0x020000, 0x9c384e99, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tn2j_36.10f", 0x020000, 0x4c4b2a0a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "tn2-02m.4a", 0x080000, 0xf2016a34, BRF_GRA | CPS1_TILES }, + { "tn2-04m.6a", 0x080000, 0x094e0fb1, BRF_GRA | CPS1_TILES }, + { "tn2-01m.3a", 0x080000, 0xcb950cf9, BRF_GRA | CPS1_TILES }, + { "tn2-03m.5a", 0x080000, 0x18a5bf59, BRF_GRA | CPS1_TILES }, + { "tn2-11m.4c", 0x080000, 0xd0edd30b, BRF_GRA | CPS1_TILES }, + { "tn2-13m.6c", 0x080000, 0x426621c3, BRF_GRA | CPS1_TILES }, + { "tn2-10m.3c", 0x080000, 0xa34ece70, BRF_GRA | CPS1_TILES }, + { "tn2-12m.5c", 0x080000, 0xe04ff2f4, BRF_GRA | CPS1_TILES }, + + { "tn2j_09.12a", 0x008000, 0x6d8edcef, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tn2j_18.11c", 0x020000, 0xa40bf9a7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "tn2j_19.12c", 0x020000, 0x5b3b931e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "qtono2j.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Qtono2j) +STD_ROM_FN(Qtono2j) + +static struct BurnRomInfo Sf2RomDesc[] = { + { "sf2e_30g.11e", 0x020000, 0xfe39ee33, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_37g.11f", 0x020000, 0xfb92cd74, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_31g.12e", 0x020000, 0x69a0a301, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_38g.12f", 0x020000, 0x5e22db70, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_28g.9e", 0x020000, 0x8bf9f1e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_35g.9f", 0x020000, 0x626ef934, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2) +STD_ROM_FN(Sf2) + +static struct BurnRomInfo Sf2ebRomDesc[] = { + { "sf2e_30b.11e", 0x020000, 0x57bd7051, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_37b.11f", 0x020000, 0x62691cdd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_31b.12e", 0x020000, 0xa673143d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_38b.12f", 0x020000, 0x4c2ccef7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_28b.9e", 0x020000, 0x4009955e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_35b.9f", 0x020000, 0x8c1f3994, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2eb) +STD_ROM_FN(Sf2eb) + +static struct BurnRomInfo Sf2eeRomDesc[] = { + { "sf2e_30e.11e", 0x020000, 0xf37cd088, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_37e.11f", 0x020000, 0xc39468e6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_31e.12e", 0x020000, 0x7c4771b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_38e.12f", 0x020000, 0xa4bd0cd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_28e.9e", 0x020000, 0xe3b95625, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2e_35e.9f", 0x020000, 0x3648769a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob2.11d", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "c632b.ic1", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ee) +STD_ROM_FN(Sf2ee) + +static struct BurnRomInfo Sf2ebblRomDesc[] = { + { "12.bin", 0x040000, 0xa258b4d5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "09.bin", 0x040000, 0x59ccd474, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "11.bin", 0x040000, 0x82097d63, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "10.bin", 0x040000, 0x0c83844d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "1b_yf082.bin", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "1d_yf028.bin", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "1a_yf087.bin", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "1c_yf088.bin", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "1f_yf085.bin", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "1h_yf115.bin", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "1e_yf111.bin", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "1g_yf002.bin", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "1j_yf117.bin", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "1l_ye040.bin", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "1i_yf038.bin", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "1k_ye039.bin", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "03.bin", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "02.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "01.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + { "05.bin", 0x020000, 0xa505621e, BRF_GRA }, // extra graphics - map over normal roms to remove CAPCOM logo + { "07.bin", 0x020000, 0xde6271fb, BRF_GRA }, + { "06.bin", 0x020000, 0x23775344, BRF_GRA }, + { "08.bin", 0x020000, 0x81c9550f, BRF_GRA }, + + { "04.bin", 0x010000, 0x13ea1c44, BRF_OPT }, // unknown +}; + +STD_ROM_PICK(Sf2ebbl) +STD_ROM_FN(Sf2ebbl) + +static struct BurnRomInfo Sf2uaRomDesc[] = { + { "sf2u_30a.11e", 0x020000, 0x08beb861, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37a.11f", 0x020000, 0xb7638d69, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31a.12e", 0x020000, 0x0d5394e0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38a.12f", 0x020000, 0x42d6a79e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28a.9e", 0x020000, 0x387a175c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35a.9f", 0x020000, 0xa1a5adcc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ua) +STD_ROM_FN(Sf2ua) + +static struct BurnRomInfo Sf2ubRomDesc[] = { + { "sf2u_30b.11e", 0x020000, 0x57bd7051, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37b.11f", 0x020000, 0x4a54d479, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31b.12e", 0x020000, 0xa673143d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38b.12f", 0x020000, 0x4c2ccef7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28b.9e", 0x020000, 0x4009955e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35b.9f", 0x020000, 0x8c1f3994, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ub) +STD_ROM_FN(Sf2ub) + +static struct BurnRomInfo Sf2ucRomDesc[] = { + { "sf2u_30c.11e", 0x020000, 0x6cb59385, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37c.11f", 0x020000, 0x32e2c278, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31c.12e", 0x020000, 0xc4fff4a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38c.12f", 0x020000, 0x8210fc0e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28c.9e", 0x020000, 0x6eddd5e8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35c.9f", 0x020000, 0x6bcb404c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2uc) +STD_ROM_FN(Sf2uc) + +static struct BurnRomInfo Sf2udRomDesc[] = { + { "sf2u_30d.11e", 0x020000, 0x4bb2657c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37d.11f", 0x020000, 0xb33b42f2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31d.12e", 0x020000, 0xd57b67d7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38d.12f", 0x020000, 0x9c8916ef, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28d.9e", 0x020000, 0x175819d1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35d.9f", 0x020000, 0x82060da4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ud) +STD_ROM_FN(Sf2ud) + +static struct BurnRomInfo Sf2ueRomDesc[] = { + { "sf2u_30e.11e", 0x020000, 0xf37cd088, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37e.11f", 0x020000, 0x6c61a513, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31e.12e", 0x020000, 0x7c4771b4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38e.12f", 0x020000, 0xa4bd0cd9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28e.9e", 0x020000, 0xe3b95625, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35e.9f", 0x020000, 0x3648769a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob2.11d", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "c632b.ic1", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ue) +STD_ROM_FN(Sf2ue) + +static struct BurnRomInfo Sf2ufRomDesc[] = { + { "sf2u_30f.11e", 0x020000, 0xfe39ee33, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37f.11f", 0x020000, 0x169e7388, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31f.12e", 0x020000, 0x69a0a301, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38f.12f", 0x020000, 0x1510e4e2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28f.9e", 0x020000, 0xacd8175b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35f.9f", 0x020000, 0xc0a80bd1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2uf) +STD_ROM_FN(Sf2uf) + +static struct BurnRomInfo Sf2uiRomDesc[] = { + { "sf2u_30i.11e", 0x020000, 0xfe39ee33, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37i.11f", 0x020000, 0x9df707dd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31i.12e", 0x020000, 0x69a0a301, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38i.12f", 0x020000, 0x4cb46daf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_28i.9e", 0x020000, 0x1580be4c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35i.9f", 0x020000, 0x1468d185, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29b.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36b.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_9.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ui) +STD_ROM_FN(Sf2ui) + +static struct BurnRomInfo Sf2ukRomDesc[] = { + { "sf2u_30k.11e", 0x020000, 0x8f66076c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_37k.11f", 0x020000, 0x4e1f6a83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31k.12e", 0x020000, 0xf9f89f60, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38k.12f", 0x020000, 0x6ce0a85a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28k.9e", 0x020000, 0x8e958f31, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35k.9f", 0x020000, 0xfce76fad, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_29a.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_36a.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2-5m.4a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2-7m.6a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2-1m.3a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2-3m.5a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2-6m.4c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2-8m.6c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2-2m.3c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2-4m.5c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2-13m.4d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2-15m.6d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2-9m.3d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2-11m.5d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2uk) +STD_ROM_FN(Sf2uk) + +static struct BurnRomInfo Sf2jRomDesc[] = { + { "sf2j30.bin", 0x020000, 0x79022b31, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j37.bin", 0x020000, 0x516776ec, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j31.bin", 0x020000, 0xfe15cb39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j38.bin", 0x020000, 0x38614d70, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j28.bin", 0x020000, 0xd283187a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j35.bin", 0x020000, 0xd28158e4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_29a.bin", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36a.bin", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_06.8a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.10a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.7a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.9a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.8c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.10c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.7c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.9c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.8d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.10d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.7d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.9d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.bin", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2j) +STD_ROM_FN(Sf2j) + +static struct BurnRomInfo Sf2jaRomDesc[] = { + { "sf2j_30a.11e", 0x020000, 0x57bd7051, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_37a.11f", 0x020000, 0x1e1f6844, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_31a.12e", 0x020000, 0xa673143d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_38a.12f", 0x020000, 0x4c2ccef7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_28a.9e", 0x020000, 0x4009955e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_35a.9f", 0x020000, 0x8c1f3994, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_29a.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_36a.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_06.8a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.10a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.7a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.9a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.8c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.10c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.7c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.9c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.8d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.10d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.7d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.9d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2j_09.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2j_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2j_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2ja) +STD_ROM_FN(Sf2ja) + +static struct BurnRomInfo Sf2jcRomDesc[] = { + { "sf2j_30c.11e", 0x020000, 0x8add35ec, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_37c.11f", 0x020000, 0x0d74a256, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_31c.12e", 0x020000, 0xc4fff4a9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_38c.12f", 0x020000, 0x8210fc0e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_28c.9e", 0x020000, 0x6eddd5e8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_35c.9f", 0x020000, 0x6bcb404c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_29c.10e", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2j_36c.10f", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_06.8a", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.10a", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.7a", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.9a", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.8c", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.10c", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.7c", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.9c", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.8d", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.10d", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.7d", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.9d", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.12a", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "stf29.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11d", 0x000117, 0x3abc0700, BRF_OPT }, + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Sf2jc) +STD_ROM_FN(Sf2jc) + +static struct BurnRomInfo Sf2qp1RomDesc[] = { + { "stfii-qkn-cps-17.33", 0x080000, 0x3a9458ee, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "stfii-qkn-cps-17.34", 0x080000, 0x4ed215d8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sf2_06.bin", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.bin", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.bin", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.bin", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.bin", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.bin", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.bin", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.bin", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.bin", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.bin", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.bin", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.bin", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.bin", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS +}; + +STD_ROM_PICK(Sf2qp1) +STD_ROM_FN(Sf2qp1) + +static struct BurnRomInfo Sf2thndrRomDesc[] = { + { "17_30.11e", 0x020000, 0xd3cd6d18, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "17_37.11f", 0x020000, 0xe892716e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_31b.12e", 0x020000, 0xa673143d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_38b.12f", 0x020000, 0x4c2ccef7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_28b.9e", 0x020000, 0x4009955e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2u_35b.9f", 0x020000, 0x8c1f3994, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "17_29.10e", 0x020000, 0x8830b54d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "17_36.10f", 0x020000, 0x3f13ada3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_06.bin", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.bin", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.bin", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.bin", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.bin", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.bin", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.bin", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.bin", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.bin", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.bin", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.bin", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.bin", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.bin", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS +}; + +STD_ROM_PICK(Sf2thndr) +STD_ROM_FN(Sf2thndr) + +static struct BurnRomInfo Sf2bRomDesc[] = { + { "u3.bin", 0x020000, 0x2c9ece7c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u4.bin", 0x020000, 0x4efb4c7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_31a.bin", 0x020000, 0xa673143d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_38a.bin", 0x020000, 0x4c2ccef7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + +// { "sf2-4.bin", 0x020000, 0x76f9f91f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, +// { "sf2-3.bin", 0x020000, 0xe8f14362, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "u6.bin", 0x020000, 0x5cfc3f39, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u5.bin", 0x020000, 0x47dd24b6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sf2_29a.bin", 0x020000, 0xbb4af315, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2_36a.bin", 0x020000, 0xc02a13eb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + +// { "sf2-1.bin", 0x020000, 0x6de44671, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, +// { "sf2-2.bin", 0x020000, 0xbf0cd819, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + + + { "sf2_06.bin", 0x080000, 0x22c9cc8e, BRF_GRA | CPS1_TILES }, + { "sf2_08.bin", 0x080000, 0x57213be8, BRF_GRA | CPS1_TILES }, + { "sf2_05.bin", 0x080000, 0xba529b4f, BRF_GRA | CPS1_TILES }, + { "sf2_07.bin", 0x080000, 0x4b1b33a8, BRF_GRA | CPS1_TILES }, + { "sf2_15.bin", 0x080000, 0x2c7e2229, BRF_GRA | CPS1_TILES }, + { "sf2_17.bin", 0x080000, 0xb5548f17, BRF_GRA | CPS1_TILES }, + { "sf2_14.bin", 0x080000, 0x14b84312, BRF_GRA | CPS1_TILES }, + { "sf2_16.bin", 0x080000, 0x5e9cd89a, BRF_GRA | CPS1_TILES }, + { "sf2_25.bin", 0x080000, 0x994bfa58, BRF_GRA | CPS1_TILES }, + { "sf2_27.bin", 0x080000, 0x3e66ad9d, BRF_GRA | CPS1_TILES }, + { "sf2_24.bin", 0x080000, 0xc1befaa8, BRF_GRA | CPS1_TILES }, + { "sf2_26.bin", 0x080000, 0x0627c831, BRF_GRA | CPS1_TILES }, + + { "sf2_09.bin", 0x010000, 0xa4823a1b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sf2_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sf2_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2b) +STD_ROM_FN(Sf2b) + +static struct BurnRomInfo Sf2ceRomDesc[] = { + { "s92e_23b.8f", 0x080000, 0x0aaa1a3a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22b.7f", 0x080000, 0x2bbe15ed, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ce) +STD_ROM_FN(Sf2ce) + +static struct BurnRomInfo Sf2ceeaRomDesc[] = { + { "s92e_23a.8f", 0x080000, 0x3f846b74, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22a.7f", 0x080000, 0x99f1cca4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ceea) +STD_ROM_FN(Sf2ceea) + +static struct BurnRomInfo Sf2cejRomDesc[] = { + { "s92j_23b.8f", 0x080000, 0x140876c5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92j_22b.7f", 0x080000, 0x2fbb3bfe, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.4a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.5a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.8a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.9a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.4c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.5c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.12a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2cej) +STD_ROM_FN(Sf2cej) + +static struct BurnRomInfo Sf2ceuaRomDesc[] = { + { "s92u_23a.8f", 0x080000, 0xac44415b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22a.7f", 0x080000, 0x99f1cca4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ceua) +STD_ROM_FN(Sf2ceua) + +static struct BurnRomInfo Sf2ceubRomDesc[] = { + { "s92u_23b.8f", 0x080000, 0x996a3015, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22b.7f", 0x080000, 0x2bbe15ed, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ceub) +STD_ROM_FN(Sf2ceub) + +static struct BurnRomInfo Sf2ceucRomDesc[] = { + { "s92u_23c.8f", 0x080000, 0x0a8b6aa2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22c.7f", 0x080000, 0x5fd8630b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21b.6f", 0x080000, 0xb383cb1c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ceuc) +STD_ROM_FN(Sf2ceuc) + +static struct BurnRomInfo Sf2ceudRomDesc[] = { + { "s92u_23c.8f", 0x080000, 0x0a8b6aa2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_22c.7f", 0x080000, 0x5fd8630b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.6f", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2ceud) +STD_ROM_FN(Sf2ceud) + +static struct BurnRomInfo Sf2accRomDesc[] = { + { "sf2ca_23-c.bin", 0x080000, 0xe7c8c5a6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca_22-c.bin", 0x080000, 0x99f1cca4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca_21-c.bin", 0x040000, 0xcf7fcc8c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2acc) +STD_ROM_FN(Sf2acc) + +static struct BurnRomInfo Sf2acc2RomDesc[] = { + { "sf2ca_23-c.8f", 0x080000, 0x35f9517b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca_22-c.bin", 0x080000, 0x99f1cca4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca_21-c.6f", 0x080000, 0x2ab2034f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2acc2) +STD_ROM_FN(Sf2acc2) + +static struct BurnRomInfo Sf2accp2RomDesc[] = { + { "sf2ca-23.bin", 0x080000, 0x36c3ba2f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca-22.bin", 0x080000, 0x0550453d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ca-21.bin", 0x040000, 0x4c1c43ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2accp2) +STD_ROM_FN(Sf2accp2) + +static struct BurnRomInfo Sf2dkot2RomDesc[] = { + { "turboii.23", 0x080000, 0x9bbfe420, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "turboii.22", 0x080000, 0x3e57ba19, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "turboii.21", 0x080000, 0xed4186bd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2dkot2) +STD_ROM_FN(Sf2dkot2) + +static struct BurnRomInfo Sf2rbRomDesc[] = { + { "sf2d__23.rom", 0x080000, 0x450532b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2d__22.rom", 0x080000, 0xfe9d9cf5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.bin", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2rb) +STD_ROM_FN(Sf2rb) + +static struct BurnRomInfo Sf2rb2RomDesc[] = { + { "31.bin", 0x020000, 0x87954a41, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "27.bin", 0x020000, 0x40296ecd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "30.bin", 0x020000, 0x8141fe32, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "26.bin", 0x020000, 0xa6974195, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "29.bin", 0x020000, 0x7d9c479c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "25.bin", 0x020000, 0x9ef8f772, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "28.bin", 0x020000, 0xff728865, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "24.bin", 0x020000, 0x93579684, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2rb2) +STD_ROM_FN(Sf2rb2) + +static struct BurnRomInfo Sf2rb3RomDesc[] = { + { "sf2_ce_rb.23", 0x080000, 0x202f9e50, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2_ce_rb.22", 0x080000, 0x145e5219, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.bin", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2rb3) +STD_ROM_FN(Sf2rb3) + +static struct BurnRomInfo Sf2redRomDesc[] = { + { "sf2red.23", 0x080000, 0x40276abb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2red.22", 0x080000, 0x18daf387, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2red.21", 0x080000, 0x52c486bb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2red) +STD_ROM_FN(Sf2red) + +static struct BurnRomInfo Sf2v004RomDesc[] = { + { "sf2v004.23", 0x080000, 0x52d19f2c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2v004.22", 0x080000, 0x4b26fde7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2red.21", 0x080000, 0x52c486bb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2v004) +STD_ROM_FN(Sf2v004) + +static struct BurnRomInfo Sf2hfRomDesc[] = { + { "s2te_23.8f", 0x080000, 0x2dd72514, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2te_22.7f", 0x080000, 0xaea6e035, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2te_21.6f", 0x080000, 0xfd200288, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2hf) +STD_ROM_FN(Sf2hf) + +static struct BurnRomInfo Sf2hfuRomDesc[] = { + { "s2tu_23.8f", 0x080000, 0x89a1fc38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2tu_22.7f", 0x080000, 0xaea6e035, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2tu_21.6f", 0x080000, 0xfd200288, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92-1m.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92-3m.5a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92-2m.4a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92-4m.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92-5m.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92-7m.9a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92-6m.8a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92-8m.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92-10m.3c", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92-12m.5c", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92-11m.4c", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92-13m.6c", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.11a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2hfu) +STD_ROM_FN(Sf2hfu) + +static struct BurnRomInfo Sf2hfjRomDesc[] = { + { "s2tj_23.8f", 0x080000, 0xea73b4dc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2tj_22.7f", 0x080000, 0xaea6e035, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s2tj_21.6f", 0x080000, 0xfd200288, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.3a", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.4a", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.5a", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.6a", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.7a", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.8a", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.9a", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.10a", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s2t_10.3c", 0x080000, 0x3c042686, BRF_GRA | CPS1_TILES }, + { "s2t_11.4c", 0x080000, 0x8b7e7183, BRF_GRA | CPS1_TILES }, + { "s2t_12.5c", 0x080000, 0x293c888c, BRF_GRA | CPS1_TILES }, + { "s2t_13.6c", 0x080000, 0x842b35a4, BRF_GRA | CPS1_TILES }, + + { "s92_09.12a", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.11c", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.12c", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "s9263b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Sf2hfj) +STD_ROM_FN(Sf2hfj) + +static struct BurnRomInfo Sf2yycRomDesc[] = { + { "b12.rom", 0x0080000, 0x8f742fd5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "b14.rom", 0x0080000, 0x8831ec7f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "b11.rom", 0x0020000, 0x94a46525, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "b13.rom", 0x0020000, 0x8fb3dd47, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2yyc) +STD_ROM_FN(Sf2yyc) + +static struct BurnRomInfo KouryuRomDesc[] = { + { "u196.rom", 0x0080000, 0xb23a869d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u222.rom", 0x0080000, 0x9236a79a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u195.rom", 0x0020000, 0xc95e4443, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u221.rom", 0x0020000, 0x64e6e091, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Kouryu) +STD_ROM_FN(Kouryu) + +static struct BurnRomInfo Sf2m1RomDesc[] = { + { "222e", 0x0080000, 0x1e20d0a3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "196e", 0x0080000, 0x88cc38a3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m1) +STD_ROM_FN(Sf2m1) + +static struct BurnRomInfo Sf2m2RomDesc[] = { + { "ch222esp", 0x0080000, 0x9e6d058a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ch196esp", 0x0080000, 0xed2ff437, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m2) +STD_ROM_FN(Sf2m2) + +static struct BurnRomInfo Sf2m3RomDesc[] = { + { "u222chp", 0x0080000, 0xdb567b66, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196chp", 0x0080000, 0x95ea597e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m3) +STD_ROM_FN(Sf2m3) + +static struct BurnRomInfo Sf2m4RomDesc[] = { + { "u222ne", 0x0080000, 0x7133489e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196ne", 0x0080000, 0xb07a4f90, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m4) +STD_ROM_FN(Sf2m4) + +static struct BurnRomInfo Sf2m5RomDesc[] = { + { "u222", 0x0080000, 0x03991fba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196", 0x0080000, 0x39f15a1e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m5) +STD_ROM_FN(Sf2m5) + +static struct BurnRomInfo Sf2m6RomDesc[] = { + { "u222-6b", 0x0080000, 0x0a3692be, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196-6b", 0x0080000, 0x80454da7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m6) +STD_ROM_FN(Sf2m6) + +static struct BurnRomInfo Sf2m7RomDesc[] = { + { "u222-2i", 0x0040000, 0x1ca7adbd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196-2i", 0x0040000, 0xf758408c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u222-2s", 0x0040000, 0x720cea3e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u196-2s", 0x0040000, 0x9932832c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "s92_21a.bin", 0x0080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m7) +STD_ROM_FN(Sf2m7) + +static struct BurnRomInfo Sf2m8RomDesc[] = { + { "k4-222", 0x0080000, 0xdb567b66, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "k4-196", 0x0080000, 0x95ea597e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u221.epr", 0x0020000, 0xd8276822, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u195.epr", 0x0020000, 0x924c6ce2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m8) +STD_ROM_FN(Sf2m8) + +static struct BurnRomInfo Sf2m9RomDesc[] = { + { "sf3a-1.040", 0x0080000, 0x9e6d058a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf3a-3.040", 0x0080000, 0x518d8404, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf3a-2", 0x0020000, 0xfca4fc1e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf3a-4", 0x0020000, 0xcfdd6f54, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m9) +STD_ROM_FN(Sf2m9) + +static struct BurnRomInfo Sf2m10RomDesc[] = { + { "sfu9-1.040", 0x0080000, 0x95306baf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu9-3.040", 0x0080000, 0x21024d5f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu9-2.020", 0x0040000, 0x0b3fe5dd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu9-4.020", 0x0040000, 0xdbee7b18, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m10) +STD_ROM_FN(Sf2m10) + +static struct BurnRomInfo Sf2m11RomDesc[] = { + { "sfu7-1.040", 0x0080000, 0x866a9b31, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu7-3.040", 0x0080000, 0xf3a45593, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu7-2.010", 0x0020000, 0xd1707134, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu7-4.010", 0x0020000, 0xcd1d5666, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m11) +STD_ROM_FN(Sf2m11) + +static struct BurnRomInfo Sf2m12RomDesc[] = { + { "sfu8-1.040", 0x0080000, 0x10ec67fe, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu8-3.040", 0x0080000, 0x92eb3a1c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu8-2.010", 0x0020000, 0x1073b7b6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sfu8-4.010", 0x0020000, 0x924c6ce2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m12) +STD_ROM_FN(Sf2m12) + +static struct BurnRomInfo Sf2m13RomDesc[] = { + { "222-040.13", 0x0080000, 0xec6f5cb3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "196-040.13", 0x0080000, 0x0e9ac52b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "221-010.13", 0x0020000, 0x8226c11c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "195-010.13", 0x0020000, 0x924c6ce2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s2t_10.bin", 0x080000, 0x3c042686, BRF_GRA | CPS1_TILES }, + { "s2t_11.bin", 0x080000, 0x8b7e7183, BRF_GRA | CPS1_TILES }, + { "s2t_12.bin", 0x080000, 0x293c888c, BRF_GRA | CPS1_TILES }, + { "s2t_13.bin", 0x080000, 0x842b35a4, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2m13) +STD_ROM_FN(Sf2m13) + +static struct BurnRomInfo Sf2tlonaRomDesc[] = { + { "tl4mt.1", 0x080000, 0x158635ca, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tl4m.2", 0x080000, 0x882cd1c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u221t.1m", 0x020000, 0x1073b7b6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u195t.1m", 0x020000, 0xdb7e1f72, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2tlona) +STD_ROM_FN(Sf2tlona) + +static struct BurnRomInfo Sf2tlonbRomDesc[] = { + { "tl4m.1", 0x080000, 0xafc7bd18, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tl4m.2", 0x080000, 0x882cd1c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u221.1m", 0x020000, 0xd1707134, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u195.1m", 0x020000, 0xcd1d5666, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2tlonb) +STD_ROM_FN(Sf2tlonb) + +static struct BurnRomInfo Sf2thRomDesc[] = { + { "stf2th-7.bin", 0x0080000, 0x03991fba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "stf2th-5.bin", 0x0080000, 0x3127302c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sf2th-4.bin", 0x0020000, 0xc95e4443, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "stf2th-6.bin", 0x0020000, 0x64e6e091, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + // Some extra gfx too + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2th) +STD_ROM_FN(Sf2th) + +static struct BurnRomInfo SfzchRomDesc[] = { + { "sfzch23", 0x080000, 0x1140743f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfzch) +STD_ROM_FN(Sfzch) + +static struct BurnRomInfo SfachRomDesc[] = { + { "sfach23", 0x080000, 0x02a1a853, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfach) +STD_ROM_FN(Sfach) + +static struct BurnRomInfo SfzachRomDesc[] = { + { "sfzach23", 0x080000, 0x2562108b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfzach) +STD_ROM_FN(Sfzach) + +static struct BurnRomInfo SfzbchRomDesc[] = { + { "sfbch23", 0x080000, 0x53699f68, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfzbch) +STD_ROM_FN(Sfzbch) + +static struct BurnRomInfo SfzechRomDesc[] = { + { "sfzech23", 0x080000, 0x5ec7058f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfzech) +STD_ROM_FN(Sfzech) + +static struct BurnRomInfo SfzhchRomDesc[] = { + { "sfzhch23", 0x080000, 0x3683cce7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza22", 0x080000, 0x8d9b2480, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfzch21", 0x080000, 0x5435225d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sfza20", 0x080000, 0x806e8f38, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sfz01", 0x080000, 0x0dd53e62, BRF_GRA | CPS1_TILES }, + { "sfz02", 0x080000, 0x94c31e3f, BRF_GRA | CPS1_TILES }, + { "sfz03", 0x080000, 0x9584ac85, BRF_GRA | CPS1_TILES }, + { "sfz04", 0x080000, 0xb983624c, BRF_GRA | CPS1_TILES }, + { "sfz05", 0x080000, 0x2b47b645, BRF_GRA | CPS1_TILES }, + { "sfz06", 0x080000, 0x74fd9fb1, BRF_GRA | CPS1_TILES }, + { "sfz07", 0x080000, 0xbb2c734d, BRF_GRA | CPS1_TILES }, + { "sfz08", 0x080000, 0x454f7868, BRF_GRA | CPS1_TILES }, + { "sfz10", 0x080000, 0x2a7d675e, BRF_GRA | CPS1_TILES }, + { "sfz11", 0x080000, 0xe35546c8, BRF_GRA | CPS1_TILES }, + { "sfz12", 0x080000, 0xf122693a, BRF_GRA | CPS1_TILES }, + { "sfz13", 0x080000, 0x7cf942c8, BRF_GRA | CPS1_TILES }, + { "sfz14", 0x080000, 0x09038c81, BRF_GRA | CPS1_TILES }, + { "sfz15", 0x080000, 0x1aa17391, BRF_GRA | CPS1_TILES }, + { "sfz16", 0x080000, 0x19a5abd6, BRF_GRA | CPS1_TILES }, + { "sfz17", 0x080000, 0x248b3b73, BRF_GRA | CPS1_TILES }, + + { "sfz09", 0x010000, 0xc772628b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sfz18", 0x020000, 0x61022b2d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sfz19", 0x020000, 0x3b5886d5, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sfzhch) +STD_ROM_FN(Sfzhch) + +static struct BurnRomInfo SlammastRomDesc[] = { + { "mbe_23e.8f", 0x080000, 0x5394057a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_24b.9e", 0x020000, 0x95d5e729, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_28b.9f", 0x020000, 0xb1c7cbcb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_25b.10e", 0x020000, 0xa50d3fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_29b.10f", 0x020000, 0x08e32e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_21a.6f", 0x080000, 0xd5007b05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_20a.5f", 0x080000, 0xaeb557b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb-1m.3a", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb-3m.5a", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb-2m.4a", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb-4m.6a", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb-5m.7a", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb-7m.9a", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb-6m.8a", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb-8m.10a", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb-10m.3c", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb-12m.5c", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb-11m.4c", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb-13m.6c", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_qa.5k", 0x020000, 0xe21a03c4, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb-q1.1k", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q2.2k", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q3.3k", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q4.4k", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q5.1m", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q6.2m", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q7.3m", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q8.4m", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "mb63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Slammast) +STD_ROM_FN(Slammast) + +static struct BurnRomInfo SlammastuRomDesc[] = { + { "mbu_23e.8f", 0x080000, 0x224f0062, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbu_24b.9e", 0x020000, 0x95d5e729, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbu_28b.9f", 0x020000, 0xb1c7cbcb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbu_25b.10e", 0x020000, 0xa50d3fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbu_29b.10f", 0x020000, 0x08e32e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbu_21a.6f", 0x080000, 0xd5007b05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbu_20a.5f", 0x080000, 0xfc848af5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb-1m.3a", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb-3m.5a", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb-2m.4a", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb-4m.6a", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb-5m.7a", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb-7m.9a", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb-6m.8a", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb-8m.10a", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb-10m.3c", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb-12m.5c", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb-11m.4c", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb-13m.6c", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_qa.5k", 0x020000, 0xe21a03c4, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb-q1.1k", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q2.2k", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q3.3k", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q4.4k", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q5.1m", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q6.2m", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q7.3m", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb-q8.4m", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "mb63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d9k2.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Slammastu) +STD_ROM_FN(Slammastu) + +static struct BurnRomInfo MbomberjRomDesc[] = { + { "mbj23e", 0x080000, 0x0d06036a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_24b.rom", 0x020000, 0x95d5e729, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_28b.rom", 0x020000, 0xb1c7cbcb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_25b.rom", 0x020000, 0xa50d3fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_29b.rom", 0x020000, 0x08e32e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_21a.rom", 0x080000, 0xd5007b05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_20a.rom", 0x080000, 0xaeb557b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mbj_01.bin", 0x080000, 0xa53b1c81, BRF_GRA | CPS1_TILES }, + { "mbj_03.bin", 0x080000, 0x23fe10f6, BRF_GRA | CPS1_TILES }, + { "mbj_02.bin", 0x080000, 0xcb866c2f, BRF_GRA | CPS1_TILES }, + { "mbj_04.bin", 0x080000, 0xc9143e75, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_qa.rom", 0x020000, 0xe21a03c4, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "mb63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Mbomberj) +STD_ROM_FN(Mbomberj) + +static struct BurnRomInfo MbombrdRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbde_30.rom", 0x020000, 0xa036dc16, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "mb63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Mbombrd) +STD_ROM_FN(Mbombrd) + +static struct BurnRomInfo MbombrdjRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbdj_30.bin", 0x020000, 0xbeff31cf, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mbj_01.bin", 0x080000, 0xa53b1c81, BRF_GRA | CPS1_TILES }, + { "mbj_03.bin", 0x080000, 0x23fe10f6, BRF_GRA | CPS1_TILES }, + { "mbj_02.bin", 0x080000, 0xcb866c2f, BRF_GRA | CPS1_TILES }, + { "mbj_04.bin", 0x080000, 0xc9143e75, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "mb63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Mbombrdj) +STD_ROM_FN(Mbombrdj) + +static struct BurnRomInfo StriderRomDesc[] = { + { "30.11f", 0x020000, 0xda997474, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.11h", 0x020000, 0x5463aaa3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "31.12f", 0x020000, 0xd20786db, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "36.12h", 0x020000, 0x21aa2863, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "st-14.8h", 0x080000, 0x9b3cfc08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "st-2.8a", 0x080000, 0x4eee9aea, BRF_GRA | CPS1_TILES }, + { "st-11.10a", 0x080000, 0x2d7f21e4, BRF_GRA | CPS1_TILES }, + { "st-5.4a", 0x080000, 0x7705aa46, BRF_GRA | CPS1_TILES }, + { "st-9.6a", 0x080000, 0x5b18b722, BRF_GRA | CPS1_TILES }, + { "st-1.7a", 0x080000, 0x005f000b, BRF_GRA | CPS1_TILES }, + { "st-10.9a", 0x080000, 0xb9441519, BRF_GRA | CPS1_TILES }, + { "st-4.3a", 0x080000, 0xb7d04e8b, BRF_GRA | CPS1_TILES }, + { "st-8.5a", 0x080000, 0x6b4713b4, BRF_GRA | CPS1_TILES }, + + { "09.12b", 0x010000, 0x2ed403bc, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "18.11c", 0x020000, 0x4386bc80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "19.12c", 0x020000, 0x444536d7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "st24m1.1a", 0x000117, 0xa80d357e, BRF_OPT }, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Strider) +STD_ROM_FN(Strider) + +static struct BurnRomInfo StrideruaRomDesc[] = { + { "30.30", 0x020000, 0x66aec273, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.35", 0x020000, 0x50e0e865, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "31.31", 0x020000, 0xeae93bd1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "36.36", 0x020000, 0xb904a31d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "st-14.8h", 0x080000, 0x9b3cfc08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "st-2.8a", 0x080000, 0x4eee9aea, BRF_GRA | CPS1_TILES }, + { "st-11.10a", 0x080000, 0x2d7f21e4, BRF_GRA | CPS1_TILES }, + { "st-5.4a", 0x080000, 0x7705aa46, BRF_GRA | CPS1_TILES }, + { "st-9.6a", 0x080000, 0x5b18b722, BRF_GRA | CPS1_TILES }, + { "st-1.7a", 0x080000, 0x005f000b, BRF_GRA | CPS1_TILES }, + { "st-10.9a", 0x080000, 0xb9441519, BRF_GRA | CPS1_TILES }, + { "st-4.3a", 0x080000, 0xb7d04e8b, BRF_GRA | CPS1_TILES }, + { "st-8.5a", 0x080000, 0x6b4713b4, BRF_GRA | CPS1_TILES }, + + { "09.9", 0x010000, 0x08d63519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "18.11c", 0x020000, 0x4386bc80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "19.12c", 0x020000, 0x444536d7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "st24b2.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Striderua) +STD_ROM_FN(Striderua) + +static struct BurnRomInfo StriderjrRomDesc[] = { + { "sthj_23.8f", 0x080000, 0x046e7b12, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sthj_22.7f", 0x080000, 0x9b3cfc08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sth_01.3a", 0x080000, 0x4eee9aea, BRF_GRA | CPS1_TILES }, + { "sth_02.4a", 0x080000, 0x2d7f21e4, BRF_GRA | CPS1_TILES }, + { "sth_03.5a", 0x080000, 0x7705aa46, BRF_GRA | CPS1_TILES }, + { "sth_04.6a", 0x080000, 0x5b18b722, BRF_GRA | CPS1_TILES }, + { "sth_05.7a", 0x080000, 0x005f000b, BRF_GRA | CPS1_TILES }, + { "sth_06.8a", 0x080000, 0xb9441519, BRF_GRA | CPS1_TILES }, + { "sth_07.9a", 0x080000, 0xb7d04e8b, BRF_GRA | CPS1_TILES }, + { "sth_08.10a", 0x080000, 0x6b4713b4, BRF_GRA | CPS1_TILES }, + + { "sth_09.12a", 0x010000, 0x08d63519, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sth_18.11c", 0x020000, 0x4386bc80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sth_19.12c", 0x020000, 0x444536d7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "sth63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Striderjr) +STD_ROM_FN(Striderjr) + +static struct BurnRomInfo StriderjRomDesc[] = { + { "sth36.bin", 0x020000, 0x53c7b006, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth42.bin", 0x020000, 0x4037f65f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth37.bin", 0x020000, 0x80e8877d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth43.bin", 0x020000, 0x6b3fa466, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth34.bin", 0x020000, 0xbea770b5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth40.bin", 0x020000, 0x43b922dc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth35.bin", 0x020000, 0x5cc429da, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "sth41.bin", 0x020000, 0x50af457f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sth09.bin", 0x020000, 0x1ef6bfbd, BRF_GRA | CPS1_TILES }, + { "sth01.bin", 0x020000, 0x1e21b0c1, BRF_GRA | CPS1_TILES }, + { "sth13.bin", 0x020000, 0x063263ae, BRF_GRA | CPS1_TILES }, + { "sth05.bin", 0x020000, 0xec9f8714, BRF_GRA | CPS1_TILES }, + { "sth24.bin", 0x020000, 0x6356f4d2, BRF_GRA | CPS1_TILES }, + { "sth17.bin", 0x020000, 0xb4f73d86, BRF_GRA | CPS1_TILES }, + { "sth38.bin", 0x020000, 0xee5abfc2, BRF_GRA | CPS1_TILES }, + { "sth32.bin", 0x020000, 0x44a206a3, BRF_GRA | CPS1_TILES }, + { "sth10.bin", 0x020000, 0xdf3dd3bc, BRF_GRA | CPS1_TILES }, + { "sth02.bin", 0x020000, 0xc75f9ea0, BRF_GRA | CPS1_TILES }, + { "sth14.bin", 0x020000, 0x6c03e19d, BRF_GRA | CPS1_TILES }, + { "sth06.bin", 0x020000, 0xd84f5478, BRF_GRA | CPS1_TILES }, + { "sth25.bin", 0x020000, 0x921e506a, BRF_GRA | CPS1_TILES }, + { "sth18.bin", 0x020000, 0x5b318956, BRF_GRA | CPS1_TILES }, + { "sth39.bin", 0x020000, 0x9321d6aa, BRF_GRA | CPS1_TILES }, + { "sth33.bin", 0x020000, 0xb47ddfc7, BRF_GRA | CPS1_TILES }, + { "sth11.bin", 0x020000, 0x2484f241, BRF_GRA | CPS1_TILES }, + { "sth03.bin", 0x020000, 0xaaa07245, BRF_GRA | CPS1_TILES }, + { "sth15.bin", 0x020000, 0xe415d943, BRF_GRA | CPS1_TILES }, + { "sth07.bin", 0x020000, 0x97d072d2, BRF_GRA | CPS1_TILES }, + { "sth26.bin", 0x020000, 0x0ebfcb02, BRF_GRA | CPS1_TILES }, + { "sth19.bin", 0x020000, 0x257ce683, BRF_GRA | CPS1_TILES }, + { "sth28.bin", 0x020000, 0x98ac8cd1, BRF_GRA | CPS1_TILES }, + { "sth21.bin", 0x020000, 0x538d9423, BRF_GRA | CPS1_TILES }, + { "sth12.bin", 0x020000, 0xf670a477, BRF_GRA | CPS1_TILES }, + { "sth04.bin", 0x020000, 0x853d3e01, BRF_GRA | CPS1_TILES }, + { "sth16.bin", 0x020000, 0x4092019f, BRF_GRA | CPS1_TILES }, + { "sth08.bin", 0x020000, 0x2ce9b4c7, BRF_GRA | CPS1_TILES }, + { "sth27.bin", 0x020000, 0xf82c88d9, BRF_GRA | CPS1_TILES }, + { "sth20.bin", 0x020000, 0xeb584dd4, BRF_GRA | CPS1_TILES }, + { "sth29.bin", 0x020000, 0x34ae2997, BRF_GRA | CPS1_TILES }, + { "sth22.bin", 0x020000, 0x78dd9c48, BRF_GRA | CPS1_TILES }, + + { "sth23.bin", 0x010000, 0x2ed403bc, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "sth30.bin", 0x020000, 0x4386bc80, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "sth31.bin", 0x020000, 0x444536d7, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "st22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Striderj) +STD_ROM_FN(Striderj) + +static struct BurnRomInfo UnsquadRomDesc[] = { + { "aru_30.11f", 0x020000, 0x24d8f88d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "aru_35.11h", 0x020000, 0x8b954b59, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "aru_31.12f", 0x020000, 0x33e9694b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "aru_36.12h", 0x020000, 0x7cc8fb9e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar-32m.8h", 0x080000, 0xae1d7fb0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ar-5m.7a", 0x080000, 0xbf4575d8, BRF_GRA | CPS1_TILES }, + { "ar-7m.9a", 0x080000, 0xa02945f4, BRF_GRA | CPS1_TILES }, + { "ar-1m.3a", 0x080000, 0x5965ca8d, BRF_GRA | CPS1_TILES }, + { "ar-3m.5a", 0x080000, 0xac6db17d, BRF_GRA | CPS1_TILES }, + + { "ar_09.12b", 0x010000, 0xf3dd1367, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ar_18.11c", 0x020000, 0x584b43a9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ar24b.1a", 0x000117, 0x09a51271, BRF_OPT }, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Unsquad) +STD_ROM_FN(Unsquad) + +static struct BurnRomInfo Area88RomDesc[] = { + { "ar_36.12f", 0x020000, 0x65030392, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_42.12h", 0x020000, 0xc48170de, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_37.13f", 0x020000, 0x33e9694b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_43.13h", 0x020000, 0x7cc8fb9e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_34.10f", 0x020000, 0xf6e80386, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_40.10h", 0x020000, 0xbe36c145, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_35.11f", 0x020000, 0x86d98ff3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "ar_41.11h", 0x020000, 0x758893d3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "ar_09.4b", 0x020000, 0xdb9376f8, BRF_GRA | CPS1_TILES }, + { "ar_01.4a", 0x020000, 0x392151b4, BRF_GRA | CPS1_TILES }, + { "ar_13.9b", 0x020000, 0x81436481, BRF_GRA | CPS1_TILES }, + { "ar_05.9a", 0x020000, 0xe246ed9f, BRF_GRA | CPS1_TILES }, + { "ar_24.5e", 0x020000, 0x9cd6e2a3, BRF_GRA | CPS1_TILES }, + { "ar_17.5c", 0x020000, 0x0b8e0df4, BRF_GRA | CPS1_TILES }, + { "ar_38.8h", 0x020000, 0x8b9e75b9, BRF_GRA | CPS1_TILES }, + { "ar_32.8f", 0x020000, 0xdb6acdcf, BRF_GRA | CPS1_TILES }, + { "ar_10.5b", 0x020000, 0x4219b622, BRF_GRA | CPS1_TILES }, + { "ar_02.5a", 0x020000, 0xbac5dec5, BRF_GRA | CPS1_TILES }, + { "ar_14.10b", 0x020000, 0xe6bae179, BRF_GRA | CPS1_TILES }, + { "ar_06.10a", 0x020000, 0xc8f04223, BRF_GRA | CPS1_TILES }, + { "ar_25.7e", 0x020000, 0x15ccf981, BRF_GRA | CPS1_TILES }, + { "ar_18.7c", 0x020000, 0x9336db6a, BRF_GRA | CPS1_TILES }, + { "ar_39.9h", 0x020000, 0x9b8e1363, BRF_GRA | CPS1_TILES }, + { "ar_33.9f", 0x020000, 0x3968f4b5, BRF_GRA | CPS1_TILES }, + + { "ar_23.13c", 0x010000, 0xf3dd1367, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ar_30.12e", 0x020000, 0x584b43a9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ar22b.1a", 0x000117, 0xf1db9030, BRF_OPT }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Area88) +STD_ROM_FN(Area88) + +static struct BurnRomInfo Area88rRomDesc[] = { + { "araj_23.8f", 0x080000, 0x7045d6cb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "araj_22.7f", 0x080000, 0x9913002e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "ara_01.3a", 0x080000, 0xbf4575d8, BRF_GRA | CPS1_TILES }, + { "ara_02.4a", 0x080000, 0xa02945f4, BRF_GRA | CPS1_TILES }, + { "ara_03.5a", 0x080000, 0x5965ca8d, BRF_GRA | CPS1_TILES }, + { "ara_04.6a", 0x080000, 0xac6db17d, BRF_GRA | CPS1_TILES }, + + { "ara_09.12a", 0x020000, 0xaf88359c, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "ara_18.11c", 0x020000, 0x584b43a9, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "ara63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP },// b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic7", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + { "c632.ic1", 0x000117, 0x0fbd9270, BRF_OPT }, +}; + +STD_ROM_PICK(Area88r) +STD_ROM_FN(Area88r) + +static struct BurnRomInfo VarthRomDesc[] = { + { "vae_30b.11f", 0x020000, 0xadb8d391, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_35b.11h", 0x020000, 0x44e5548f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_31b.12f", 0x020000, 0x1749a71c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_36b.12h", 0x020000, 0x5f2e2450, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_28b.9f", 0x020000, 0xe524ca50, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_33b.9h", 0x020000, 0xc0bbf8c9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_29b.10f", 0x020000, 0x6640996a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_34b.10h", 0x020000, 0xfa59be8a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "va-5m.7a", 0x080000, 0xb1fb726e, BRF_GRA | CPS1_TILES }, + { "va-7m.9a", 0x080000, 0x4c6588cd, BRF_GRA | CPS1_TILES }, + { "va-1m.3a", 0x080000, 0x0b1ace37, BRF_GRA | CPS1_TILES }, + { "va-3m.5a", 0x080000, 0x44dfe706, BRF_GRA | CPS1_TILES }, + + { "va_09.12b", 0x010000, 0x7a99446e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "va_18.11c", 0x020000, 0xde30510e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "va_19.12c", 0x020000, 0x0610a4ac, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "va24b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Varth) +STD_ROM_FN(Varth) + +static struct BurnRomInfo Varthr1RomDesc[] = { + { "vae_30a.11f", 0x020000, 0x7fcd0091, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_35a.11h", 0x020000, 0x35cf9509, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_31a.12f", 0x020000, 0x15e5ee81, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_36a.12h", 0x020000, 0x153a201e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_28a.9f", 0x020000, 0x7a0e0d25, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_33a.9h", 0x020000, 0xf2365922, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_29a.10f", 0x020000, 0x5e2cd2c3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vae_34a.10h", 0x020000, 0x3d9bdf83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "va-5m.7a", 0x080000, 0xb1fb726e, BRF_GRA | CPS1_TILES }, + { "va-7m.9a", 0x080000, 0x4c6588cd, BRF_GRA | CPS1_TILES }, + { "va-1m.3a", 0x080000, 0x0b1ace37, BRF_GRA | CPS1_TILES }, + { "va-3m.5a", 0x080000, 0x44dfe706, BRF_GRA | CPS1_TILES }, + + { "va_09.12b", 0x010000, 0x7a99446e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "va_18.11c", 0x020000, 0xde30510e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "va_19.12c", 0x020000, 0x0610a4ac, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "va24b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.11e", 0x000117, 0x3abc0700, BRF_OPT }, +}; + +STD_ROM_PICK(Varthr1) +STD_ROM_FN(Varthr1) + +static struct BurnRomInfo VarthjRomDesc[] = { + { "vaj_36b.12f", 0x020000, 0x1d798d6a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_42b.12h", 0x020000, 0x0f720233, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_37b.13f", 0x020000, 0x24414b17, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_43b.13h", 0x020000, 0x34b4b06c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_34b.10f", 0x020000, 0x87c79aed, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_40b.10h", 0x020000, 0x210b4bd0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_35b.11f", 0x020000, 0x6b0da69f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "vaj_41b.11h", 0x020000, 0x6542c8a4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "va_09.4b", 0x020000, 0x183dfaa8, BRF_GRA | CPS1_TILES }, + { "va_01.4a", 0x020000, 0xc41312b5, BRF_GRA | CPS1_TILES }, + { "va_13.9b", 0x020000, 0x45537e69, BRF_GRA | CPS1_TILES }, + { "va_05.9a", 0x020000, 0x7065d4e9, BRF_GRA | CPS1_TILES }, + { "va_24.5e", 0x020000, 0x57191ccf, BRF_GRA | CPS1_TILES }, + { "va_17.5c", 0x020000, 0x054f5a5b, BRF_GRA | CPS1_TILES }, + { "va_38.8h", 0x020000, 0xe117a17e, BRF_GRA | CPS1_TILES }, + { "va_32.8f", 0x020000, 0x3b4f40b2, BRF_GRA | CPS1_TILES }, + { "va_10.5b", 0x020000, 0xd62750cd, BRF_GRA | CPS1_TILES }, + { "va_02.5a", 0x020000, 0x11590325, BRF_GRA | CPS1_TILES }, + { "va_14.10b", 0x020000, 0xdc2f4783, BRF_GRA | CPS1_TILES }, + { "va_06.10a", 0x020000, 0x06e833ac, BRF_GRA | CPS1_TILES }, + { "va_25.7e", 0x020000, 0x51d90690, BRF_GRA | CPS1_TILES }, + { "va_18.7c", 0x020000, 0xa17817c0, BRF_GRA | CPS1_TILES }, + { "va_39.9h", 0x020000, 0xb0b12f51, BRF_GRA | CPS1_TILES }, + { "va_33.9f", 0x020000, 0x4b003af7, BRF_GRA | CPS1_TILES }, + + { "va_23.13c", 0x010000, 0x7a99446e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "va_30.12e", 0x020000, 0xde30510e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "va_31.13e", 0x020000, 0x0610a4ac, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "va22b.1a", 0x000117, 0xbd7cd574, BRF_OPT }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Varthj) +STD_ROM_FN(Varthj) + +static struct BurnRomInfo VarthuRomDesc[] = { + { "vau_23a.8f", 0x080000, 0xfbe68726, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "vau_22a.7f", 0x080000, 0x0ed71bbd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "va-5m.3a", 0x080000, 0xb1fb726e, BRF_GRA | CPS1_TILES }, + { "va-7m.5a", 0x080000, 0x4c6588cd, BRF_GRA | CPS1_TILES }, + { "va-1m.4a", 0x080000, 0x0b1ace37, BRF_GRA | CPS1_TILES }, + { "va-3m.6a", 0x080000, 0x44dfe706, BRF_GRA | CPS1_TILES }, + + { "va_09.11a", 0x010000, 0x7a99446e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "va_18.11c", 0x020000, 0xde30510e, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "va_19.12c", 0x020000, 0x0610a4ac, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "va63b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, +}; + +STD_ROM_PICK(Varthu) +STD_ROM_FN(Varthu) + +static struct BurnRomInfo WillowRomDesc[] = { + { "wlu_30.11f", 0x020000, 0xd604dbb1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "35.11h", 0x020000, 0x7a791e77, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlu_31.12f", 0x020000, 0x0eb48a83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_36.12h", 0x020000, 0x36100209, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlm-32.8h", 0x080000, 0xdfd9f643, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "wlm-7.7a", 0x080000, 0xafa74b73, BRF_GRA | CPS1_TILES }, + { "wlm-5.9a", 0x080000, 0x12a0dc0b, BRF_GRA | CPS1_TILES }, + { "wlm-3.3a", 0x080000, 0xc6f2abce, BRF_GRA | CPS1_TILES }, + { "wlm-1.5a", 0x080000, 0x4aa4c6d3, BRF_GRA | CPS1_TILES }, + { "wl_24.7d", 0x020000, 0x6f0adee5, BRF_GRA | CPS1_TILES }, + { "wl_14.7c", 0x020000, 0x9cf3027d, BRF_GRA | CPS1_TILES }, + { "wl_26.9d", 0x020000, 0xf09c8ecf, BRF_GRA | CPS1_TILES }, + { "wl_16.9c", 0x020000, 0xe35407aa, BRF_GRA | CPS1_TILES }, + { "wl_20.3d", 0x020000, 0x84992350, BRF_GRA | CPS1_TILES }, + { "wl_10.3c", 0x020000, 0xb87b5a36, BRF_GRA | CPS1_TILES }, + { "wl_22.5d", 0x020000, 0xfd3f89f0, BRF_GRA | CPS1_TILES }, + { "wl_12.5c", 0x020000, 0x7da49d69, BRF_GRA | CPS1_TILES }, + + { "wl_09.12b", 0x010000, 0xf6b3d060, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "wl_18.11c", 0x020000, 0xbde23d4d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "wl_19.12c", 0x020000, 0x683898f5, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "wl24b.1a", 0x000117, 0x7101cdf1, BRF_OPT }, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Willow) +STD_ROM_FN(Willow) + +static struct BurnRomInfo WillowoRomDesc[] = { + { "wlu_30.11f", 0x020000, 0xd604dbb1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlu_35.11h", 0x020000, 0xdaee72fe, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlu_31.12f", 0x020000, 0x0eb48a83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlu_36.12h", 0x020000, 0x36100209, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wlm-32.8h", 0x080000, 0xdfd9f643, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "wlm-7.7a", 0x080000, 0xafa74b73, BRF_GRA | CPS1_TILES }, + { "wlm-5.9a", 0x080000, 0x12a0dc0b, BRF_GRA | CPS1_TILES }, + { "wlm-3.3a", 0x080000, 0xc6f2abce, BRF_GRA | CPS1_TILES }, + { "wlm-1.5a", 0x080000, 0x4aa4c6d3, BRF_GRA | CPS1_TILES }, + { "wl_24.7d", 0x020000, 0x6f0adee5, BRF_GRA | CPS1_TILES }, + { "wl_14.7c", 0x020000, 0x9cf3027d, BRF_GRA | CPS1_TILES }, + { "wl_26.9d", 0x020000, 0xf09c8ecf, BRF_GRA | CPS1_TILES }, + { "wl_16.9c", 0x020000, 0xe35407aa, BRF_GRA | CPS1_TILES }, + { "wl_20.3d", 0x020000, 0x84992350, BRF_GRA | CPS1_TILES }, + { "wl_10.3c", 0x020000, 0xb87b5a36, BRF_GRA | CPS1_TILES }, + { "wl_22.5d", 0x020000, 0xfd3f89f0, BRF_GRA | CPS1_TILES }, + { "wl_12.5c", 0x020000, 0x7da49d69, BRF_GRA | CPS1_TILES }, + + { "wl_09.12b", 0x010000, 0xf6b3d060, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "wl_18.11c", 0x020000, 0xbde23d4d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "wl_19.12c", 0x020000, 0x683898f5, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "wl24b.1a", 0x000117, 0x7101cdf1, BRF_OPT }, // b-board PLDs + { "lwio.11e", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Willowo) +STD_ROM_FN(Willowo) + +static struct BurnRomInfo WillowjRomDesc[] = { + { "wl_36.12f", 0x020000, 0x2b0d7cbc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_42.12h", 0x020000, 0x1ac39615, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_37.13f", 0x020000, 0x30a717fa, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_43.13h", 0x020000, 0xd0dddc9e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_34.10f", 0x020000, 0x23a84f7a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_40.10h", 0x020000, 0xc7a0ed21, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_35.11f", 0x020000, 0x5eff7951, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "wl_41.11h", 0x020000, 0x8d6477a3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "wl_09.4b", 0x020000, 0x05aa71b4, BRF_GRA | CPS1_TILES }, + { "wl_01.4a", 0x020000, 0x08c2df12, BRF_GRA | CPS1_TILES }, + { "wl_13.9b", 0x020000, 0x1f7c87cd, BRF_GRA | CPS1_TILES }, + { "wl_05.9a", 0x020000, 0xf5254bf2, BRF_GRA | CPS1_TILES }, + { "wl_24.5e", 0x020000, 0xd9d73ba1, BRF_GRA | CPS1_TILES }, + { "wl_17.5c", 0x020000, 0xa652f30c, BRF_GRA | CPS1_TILES }, + { "wl_38.8h", 0x020000, 0xf6f9111b, BRF_GRA | CPS1_TILES }, + { "wl_32.8f", 0x020000, 0x10f64027, BRF_GRA | CPS1_TILES }, + { "wl_10.5b", 0x020000, 0xdbba0a3f, BRF_GRA | CPS1_TILES }, + { "wl_02.5a", 0x020000, 0x86fba7a5, BRF_GRA | CPS1_TILES }, + { "wl_14.10b", 0x020000, 0x7d5798b2, BRF_GRA | CPS1_TILES }, + { "wl_06.10a", 0x020000, 0x1f052948, BRF_GRA | CPS1_TILES }, + { "wl_25.7e", 0x020000, 0x857d17d2, BRF_GRA | CPS1_TILES }, + { "wl_18.7c", 0x020000, 0x316c7fbc, BRF_GRA | CPS1_TILES }, + { "wl_39.9h", 0x020000, 0xe6fce9b0, BRF_GRA | CPS1_TILES }, + { "wl_33.9f", 0x020000, 0xa15d5517, BRF_GRA | CPS1_TILES }, + + { "wl_11.7b", 0x020000, 0x6f0adee5, BRF_GRA | CPS1_TILES }, + { "wl_03.7a", 0x020000, 0x9cf3027d, BRF_GRA | CPS1_TILES }, + { "wl_15.11b", 0x020000, 0xf09c8ecf, BRF_GRA | CPS1_TILES }, + { "wl_07.11a", 0x020000, 0xe35407aa, BRF_GRA | CPS1_TILES }, + { "wl_26.8e", 0x020000, 0x84992350, BRF_GRA | CPS1_TILES }, + { "wl_19.8c", 0x020000, 0xb87b5a36, BRF_GRA | CPS1_TILES }, + { "wl_28.10e", 0x020000, 0xfd3f89f0, BRF_GRA | CPS1_TILES }, + { "wl_21.10c", 0x020000, 0x7da49d69, BRF_GRA | CPS1_TILES }, + + { "wl_23.13c", 0x010000, 0xf6b3d060, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "wl_30.12e", 0x020000, 0xbde23d4d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "wl_31.13e", 0x020000, 0x683898f5, BRF_SND | CPS1_OKIM6295_SAMPLES }, + + A_BOARD_PLDS + + { "wl22b.1a", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP }, // b-board PLDs + { "lwio.12c", 0x000117, 0xad52b90c, BRF_OPT }, +}; + +STD_ROM_PICK(Willowj) +STD_ROM_FN(Willowj) + +static struct BurnRomInfo WofRomDesc[] = { + { "tk2e_23b.rom", 0x080000, 0x11fb2ed1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2e_22b.rom", 0x080000, 0x479b3f24, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "tk263b.1a", 0x000117, 0xc4b0349b, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wof) +STD_ROM_FN(Wof) + +static struct BurnRomInfo WofaRomDesc[] = { + { "tk2a_23b.rom", 0x080000, 0x2e024628, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2a_22b.rom", 0x080000, 0x900ad4cd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "tk263b.1a", 0x000117, 0xc4b0349b, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wofa) +STD_ROM_FN(Wofa) + +static struct BurnRomInfo WofuRomDesc[] = { + { "tk2u_23c.8f", 0x080000, 0x29b89c12, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2u_22c.7f", 0x080000, 0xf5af4774, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2-1m.3a", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2-3m.5a", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2-2m.4a", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2-4m.6a", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2-5m.7a", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2-7m.9a", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2-6m.8a", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2-8m.10a", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.5k", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2-q1.1k", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2-q2.2k", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2-q3.3k", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2-q4.4k", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "tk263b.1a", 0x000117, 0xc4b0349b, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs + + { "d7l1.7l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, // d-board PLDs + { "d8l1.8l", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d9k1.9k", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, + { "d10f1.10f", 0x000117, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(Wofu) +STD_ROM_FN(Wofu) + +static struct BurnRomInfo WofjRomDesc[] = { + { "tk2j23c.bin", 0x080000, 0x9b215a68, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2j22c.bin", 0x080000, 0xb74b09ac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk205.bin", 0x080000, 0xe4a44d53, BRF_GRA | CPS1_TILES }, + { "tk206.bin", 0x080000, 0x58066ba8, BRF_GRA | CPS1_TILES }, + { "tk207.bin", 0x080000, 0xd706568e, BRF_GRA | CPS1_TILES }, + { "tk208.bin", 0x080000, 0xd4a19a02, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, + + A_BOARD_QSOUND_PLDS + + { "tk263b.1a", 0x000117, 0xc4b0349b, BRF_OPT }, // b-board PLDs + { "iob1.12d", 0x000117, 0x3abc0700, BRF_OPT }, + { "bprg1.11d", 0x000117, 0x31793da7, BRF_OPT }, + + { "ioc1.ic1", 0x000117, 0x0d182081, BRF_OPT }, // c-board PLDs +}; + +STD_ROM_PICK(Wofj) +STD_ROM_FN(Wofj) + +static struct BurnRomInfo WofhfhRomDesc[] = { + { "23", 0x080000, 0x6ae4b312, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "22", 0x080000, 0x94e8d01a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "1", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "2", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "3", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "4", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "5", 0x080000, 0x34949d7b, BRF_GRA | CPS1_TILES }, + { "6", 0x080000, 0xdfa70971, BRF_GRA | CPS1_TILES }, + { "7", 0x080000, 0x073686a6, BRF_GRA | CPS1_TILES }, + { "8", 0x080000, 0x5300f8db, BRF_GRA | CPS1_TILES }, + + { "9", 0x020000, 0x86fe8a97, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "18", 0x020000, 0xc04be720, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "19", 0x020000, 0xfbb8d8c1, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Wofhfh) +STD_ROM_FN(Wofhfh) + +static struct BurnRomInfo WofahRomDesc[] = { + { "htk2a_23b.rom", 0x080000, 0x1b17fc85, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2a_22b.rom", 0x080000, 0x900ad4cd, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofah) +STD_ROM_FN(Wofah) + +static struct BurnRomInfo WofbRomDesc[] = { + { "3-f2ab.040", 0x080000, 0x61fd0a01, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "1-9207.040", 0x080000, 0x7f59e24c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "4-d4d2.010", 0x020000, 0xfe5eee87, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "2-6c41.010", 0x020000, 0x739379be, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "5-caf3.040", 0x080000, 0xc8dcaa95, BRF_GRA | CPS1_TILES }, + { "6-034f.040", 0x080000, 0x1ab0000c, BRF_GRA | CPS1_TILES }, + { "7-b0fa.040", 0x080000, 0x8425ff6b, BRF_GRA | CPS1_TILES }, + { "8-a6b7.040", 0x080000, 0x24ce197b, BRF_GRA | CPS1_TILES }, + { "9-8a2c.040", 0x080000, 0x9d20ef9b, BRF_GRA | CPS1_TILES }, + { "10-7d24.040", 0x080000, 0x90c93dd2, BRF_GRA | CPS1_TILES }, + { "11-4171.040", 0x080000, 0x219fd7e2, BRF_GRA | CPS1_TILES }, + { "12-f56b.040", 0x080000, 0xefc17c9a, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofb) +STD_ROM_FN(Wofb) + +static struct BurnRomInfo WofchRomDesc[] = { + { "tk2(ch).23", 0x080000, 0x4e0b8dee, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2(ch).22", 0x080000, 0xd0937a8d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk205.bin", 0x080000, 0xe4a44d53, BRF_GRA | CPS1_TILES }, + { "tk206.bin", 0x080000, 0x58066ba8, BRF_GRA | CPS1_TILES }, + { "tk2(ch).06", 0x080000, 0xcc9006c9, BRF_GRA | CPS1_TILES }, + { "tk208.bin", 0x080000, 0xd4a19a02, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofch) +STD_ROM_FN(Wofch) + +static struct BurnRomInfo Wof3jsRomDesc[] = { + { "3js_23.rom", 0x080000, 0x1ebb76da, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "3js_22.rom", 0x080000, 0xf41d6153, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, // First and second halves identical + { "3js_24.rom", 0x020000, 0x06ead409, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "3js_28.rom", 0x020000, 0x8ba934e6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "3js_gfx5.rom", 0x080000, 0x94b58f82, BRF_GRA | CPS1_TILES }, + { "3js_gfx7.rom", 0x080000, 0xdf4fb386, BRF_GRA | CPS1_TILES }, + { "3js_gfx6.rom", 0x080000, 0xc22c5bd8, BRF_GRA | CPS1_TILES }, + { "3js_gfx8.rom", 0x080000, 0xf9cfd08b, BRF_GRA | CPS1_TILES }, + + { "3js_09.rom", 0x010000, 0x21ce044c, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "3js_18.rom", 0x020000, 0xac6e307d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "3js_19.rom", 0x020000, 0x068741db, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Wof3js) +STD_ROM_FN(Wof3js) + +static struct BurnRomInfo Wof3sjRomDesc[] = { + { "k6b.040", 0x080000, 0x7b365108, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "k6a.040", 0x080000, 0x10488a51, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "k6a.160", 0x200000, 0xa121180d, BRF_GRA | CPS1_TILES }, + { "k6b.160", 0x200000, 0xa4db96c4, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wof3sj) +STD_ROM_FN(Wof3sj) + +static struct BurnRomInfo Wof3sjaRomDesc[] = { + { "3js.800", 0x100000, 0x812f9200, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "k6a.160", 0x200000, 0xa121180d, BRF_GRA | CPS1_TILES }, + { "k6b.160", 0x200000, 0xa4db96c4, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wof3sja) +STD_ROM_FN(Wof3sja) + +static struct BurnRomInfo WofahaRomDesc[] = { + { "htk2ah_23b.rom",0x080000, 0x6e3ff382, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2ah_22b.rom", 0x080000, 0x48fd83c6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofaha) +STD_ROM_FN(Wofaha) + +static struct BurnRomInfo WofhRomDesc[] = { + { "sgyx.800", 0x100000, 0x3703a650, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "sgyx-1.160", 0x200000, 0xa60be9f6, BRF_GRA | CPS1_TILES }, + { "sgyx-2.160", 0x200000, 0x6ad9d048, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofh) +STD_ROM_FN(Wofh) + +static struct BurnRomInfo WofhaRomDesc[] = { + { "fg-c.040", 0x080000, 0xd046fc86, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "fg-a.040", 0x080000, 0xf176ee8f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "sgyx-1.160", 0x200000, 0xa60be9f6, BRF_GRA | CPS1_TILES }, + { "sgyx-2.160", 0x200000, 0x6ad9d048, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofha) +STD_ROM_FN(Wofha) + +static struct BurnRomInfo WofjhRomDesc[] = { + { "tk2j23h.bin", 0x080000, 0x84d38575, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2j22c.bin", 0x080000, 0xb74b09ac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk205.bin", 0x080000, 0xe4a44d53, BRF_GRA | CPS1_TILES }, + { "tk206.bin", 0x080000, 0x58066ba8, BRF_GRA | CPS1_TILES }, + { "tk207.bin", 0x080000, 0xd706568e, BRF_GRA | CPS1_TILES }, + { "tk208.bin", 0x080000, 0xd4a19a02, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofjh) +STD_ROM_FN(Wofjh) + +static struct BurnRomInfo WofsjRomDesc[] = { + { "c-c47b.040", 0x080000, 0xb1809761, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "a-2402.040", 0x080000, 0x4fab4232, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofsj) +STD_ROM_FN(Wofsj) + +static struct BurnRomInfo WofsjaRomDesc[] = { + { "one.800", 0x100000, 0x0507584d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofsja) +STD_ROM_FN(Wofsja) + +static struct BurnRomInfo WofsjbRomDesc[] = { + { "c-d140.040", 0x080000, 0xe6d933a6, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "a-0050.040", 0x080000, 0x403eaead, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5.rom", 0x080000, 0x291f0f0b, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7.rom", 0x080000, 0x3edeb949, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6.rom", 0x080000, 0x1abd14d6, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8.rom", 0x080000, 0xb27948e3, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Wofsjb) +STD_ROM_FN(Wofsjb) + +static struct BurnRomInfo Cps1frogRomDesc[] = { + { "frog30-36.bin", 0x020000, 0x8eb8ddbe, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "frog35-42.bin", 0x020000, 0xacb5a988, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "frog31-37.bin", 0x020000, 0x154803cc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "frog36-43.bin", 0x020000, 0x154803cc, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "frog32-32m.bin",0x080000, 0x75660aac, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "frog05-05m.bin",0x080000, 0x7bbc4b54, BRF_GRA | CPS1_TILES }, + { "frog07-07m.bin",0x080000, 0x0beadd80, BRF_GRA | CPS1_TILES }, + { "frog01-01m.bin",0x080000, 0xf84d02bb, BRF_GRA | CPS1_TILES }, + { "frog03-03m.bin",0x080000, 0xd784a5b0, BRF_GRA | CPS1_TILES }, + + { "frog09-09.bin", 0x010000, 0x3ac7fb5c, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "frog18-18.bin", 0x020000, 0x65d1ef07, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "frog19-19.bin", 0x020000, 0x7ee8cdcd, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Cps1frog) +STD_ROM_FN(Cps1frog) + +// Game config + +typedef void (*KabukiDecode)(); +static KabukiDecode KabukiDecodeFunction; + +static INT32 GameHasStars = 0; + +struct GameConfig { + const char *DriverName; + INT32 CpsBId; + INT32 CpsMapperId; + INT32 CpsStars; + KabukiDecode DecodeFunction; +}; + +static const struct GameConfig ConfigTable[] = +{ + { "1941" , CPS_B_05 , mapper_YI24B , 0, NULL }, + { "1941u" , CPS_B_05 , mapper_YI24B , 0, NULL }, + { "1941j" , CPS_B_05 , mapper_YI24B , 0, NULL }, + { "3wonders" , CPS_B_21_BT1, mapper_RT24B , 0, NULL }, + { "3wondersu" , CPS_B_21_BT1, mapper_RT24B , 0, NULL }, + { "wonder3" , CPS_B_21_BT1, mapper_RT22B , 0, NULL }, + { "3wondersh" , CPS_B_02 , mapper_RT24B , 0, NULL }, + { "captcomm" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "captcommr1" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "captcommu" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "captcommj" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "captcommjr1" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "captcommb" , CPS_B_21_BT3, mapper_CC63B , 0, NULL }, + { "cawing" , CPS_B_16 , mapper_CA24B , 0, NULL }, + { "cawingr1" , CPS_B_16 , mapper_CA24B , 0, NULL }, + { "cawingu" , CPS_B_16 , mapper_CA24B , 0, NULL }, + { "cawingj" , CPS_B_16 , mapper_CA22B , 0, NULL }, + { "cawingb" , CPS_B_16 , mapper_CA24B , 0, NULL }, + { "cps1demo" , CPS_B_04 , mapper_sfzch , 0, NULL }, + { "cworld2j" , CPS_B_21_BT6, mapper_Q522B , 0, NULL }, + { "dino" , CPS_B_21_QS2, mapper_CD63B , 0, dino_decode }, + { "dinou" , CPS_B_21_QS2, mapper_CD63B , 0, dino_decode }, + { "dinoj" , CPS_B_21_QS2, mapper_CD63B , 0, dino_decode }, + { "dinopic" , CPS_B_21_QS2, mapper_CD63B , 0, NULL }, + { "dinopic2" , CPS_B_21_QS2, mapper_CD63B , 0, NULL }, + { "dinoeh" , CPS_B_21_QS2, mapper_CD63B , 0, dino_decode }, + { "dinoh" , CPS_B_21_DEF, mapper_CD63B , 0, dino_decode }, + { "dinoha" , CPS_B_21_DEF, mapper_CD63B , 0, dino_decode }, + { "dinohb" , CPS_B_21_QS2, mapper_CD63B , 0, dino_decode }, + { "dinohunt" , CPS_B_21_DEF, mapper_CD63B , 0, NULL }, + { "dynwar" , CPS_B_02 , mapper_TK22B , 0, NULL }, + { "dynwara" , CPS_B_02 , mapper_TK22B , 0, NULL }, + { "dynwarj" , CPS_B_02 , mapper_TK22B , 0, NULL }, + { "dynwarjr" , CPS_B_21_DEF, mapper_TK22B , 0, NULL }, + { "ffight" , CPS_B_04 , mapper_S224B , 0, NULL }, + { "ffightu" , CPS_B_04 , mapper_S224B , 0, NULL }, + { "ffightu1" , CPS_B_04 , mapper_S224B , 0, NULL }, + { "ffightua" , CPS_B_01 , mapper_S224B , 0, NULL }, + { "ffightub" , CPS_B_05 , mapper_S224B , 0, NULL }, + { "ffightj" , CPS_B_04 , mapper_S224B , 0, NULL }, + { "ffightj1" , CPS_B_01 , mapper_S224B , 0, NULL }, + { "ffightj2" , CPS_B_02 , mapper_S224B , 0, NULL }, + { "ffightjh" , CPS_B_01 , mapper_S224B , 0, NULL }, + { "forgottn" , CPS_B_01 , mapper_LW621 , 1, NULL }, + { "forgottnu" , CPS_B_01 , mapper_LW621 , 1, NULL }, + { "forgottnua" , CPS_B_01 , mapper_LWCHR , 1, NULL }, + { "lostwrld" , CPS_B_01 , mapper_LWCHR , 1, NULL }, + { "lostwrldo" , CPS_B_01 , mapper_LWCHR , 1, NULL }, + { "ghouls" , CPS_B_01 , mapper_DM620 , 0, NULL }, + { "ghoulsu" , CPS_B_01 , mapper_DM620 , 0, NULL }, + { "daimakai" , CPS_B_01 , mapper_DM22A , 0, NULL }, + { "daimakair" , CPS_B_21_DEF, mapper_DAM63B, 0, NULL }, + { "daimakb" , CPS_B_01 , mapper_DM620 , 0, NULL }, + { "knights" , CPS_B_21_BT4, mapper_KR63B , 0, NULL }, + { "knightsu" , CPS_B_21_BT4, mapper_KR63B , 0, NULL }, + { "knightsj" , CPS_B_21_BT4, mapper_KR63B , 0, NULL }, + { "knightsja" , CPS_B_21_BT4, mapper_KR63B , 0, NULL }, + { "knightsb2" , CPS_B_21_BT4, mapper_KR63B , 0, NULL }, + { "knightsb3" , CPS_B_21_DEF, mapper_KR63B , 0, NULL }, + { "knightsh" , CPS_B_21_DEF, mapper_KR63B , 0, NULL }, + { "knghtsha" , CPS_B_21_DEF, mapper_KR63B , 0, NULL }, + { "kod" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodr1" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodu" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodj" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodja" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodb" , CPS_B_21_BT2, mapper_KD29B , 0, NULL }, + { "kodh" , CPS_B_21_DEF, mapper_KD29B , 0, NULL }, + { "megaman" , CPS_B_21_DEF, mapper_RCM63B, 0, NULL }, + { "megamana" , CPS_B_21_DEF, mapper_RCM63B, 0, NULL }, + { "rockmanj" , CPS_B_21_DEF, mapper_RCM63B, 0, NULL }, + { "mercs" , CPS_B_12 , mapper_O224B , 0, NULL }, + { "mercsu" , CPS_B_12 , mapper_O224B , 0, NULL }, + { "mercsur1" , CPS_B_12 , mapper_O224B , 0, NULL }, + { "mercsj" , CPS_B_12 , mapper_O224B , 0, NULL }, + { "msword" , CPS_B_13 , mapper_MS24B , 0, NULL }, + { "mswordr1" , CPS_B_13 , mapper_MS24B , 0, NULL }, + { "mswordu" , CPS_B_13 , mapper_MS24B , 0, NULL }, + { "mswordj" , CPS_B_13 , mapper_MS24B , 0, NULL }, + { "mtwins" , CPS_B_14 , mapper_CK24B , 0, NULL }, + { "chikij" , CPS_B_14 , mapper_CK24B , 0, NULL }, + { "nemo" , CPS_B_15 , mapper_NM24B , 0, NULL }, + { "nemoj" , CPS_B_15 , mapper_NM24B , 0, NULL }, + { "pang3" , CPS_B_21_DEF, mapper_pang3 , 0, NULL }, + { "pang3r1" , CPS_B_21_DEF, mapper_pang3 , 0, NULL }, + { "pang3n" , CPS_B_21_DEF, mapper_pang3 , 0, NULL }, + { "pang3j" , CPS_B_21_DEF, mapper_pang3 , 0, NULL }, + { "pnickj" , CPS_B_21_DEF, mapper_PKB10B, 0, NULL }, + { "punisher" , CPS_B_21_QS3, mapper_PS63B , 0, punisher_decode }, + { "punisheru" , CPS_B_21_QS3, mapper_PS63B , 0, punisher_decode }, + { "punisherj" , CPS_B_21_QS3, mapper_PS63B , 0, punisher_decode }, + { "punipic" , CPS_B_21_QS3, mapper_PS63B , 0, NULL }, + { "punipic2" , CPS_B_21_QS3, mapper_PS63B , 0, NULL }, + { "punipic3" , CPS_B_21_QS3, mapper_PS63B , 0, NULL }, + { "punisherbz" , CPS_B_21_DEF, mapper_PS63B , 0, NULL }, + { "qad" , CPS_B_21_BT7, mapper_QD22B , 0, NULL }, + { "qadj" , CPS_B_21_DEF, mapper_QD63B , 0, NULL }, + { "qtono2j" , CPS_B_21_DEF, mapper_qtono2, 0, NULL }, + { "sf2" , CPS_B_11 , mapper_STF29 , 0, NULL }, + { "sf2eb" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2ee" , CPS_B_18 , mapper_STF29 , 0, NULL }, + { "sf2ebbl" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2ua" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2ub" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2uc" , CPS_B_12 , mapper_STF29 , 0, NULL }, + { "sf2ud" , CPS_B_05 , mapper_STF29 , 0, NULL }, + { "sf2ue" , CPS_B_18 , mapper_STF29 , 0, NULL }, + { "sf2uf" , CPS_B_15 , mapper_STF29 , 0, NULL }, + { "sf2ui" , CPS_B_14 , mapper_STF29 , 0, NULL }, + { "sf2uk" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2j" , CPS_B_13 , mapper_STF29 , 0, NULL }, + { "sf2ja" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2jc" , CPS_B_12 , mapper_STF29 , 0, NULL }, + { "sf2qp1" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2thndr" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2b" , CPS_B_17 , mapper_STF29 , 0, NULL }, + { "sf2ce" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2ceea" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2ceua" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2ceub" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2ceuc" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2ceud" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2cej" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2rb" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2rb2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2rb3" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2red" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2v004" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2acc" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2acc2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2accp2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2dkot2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m1" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m3" , HACK_B_2 , mapper_S9263B, 0, NULL }, + { "sf2m4" , HACK_B_1 , mapper_S9263B, 0, NULL }, + { "sf2m5" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m6" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m7" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m8" , HACK_B_2 , mapper_S9263B, 0, NULL }, + { "sf2m9" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m10" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2m11" , HACK_B_1 , mapper_S9263B, 0, NULL }, + { "sf2m12" , HACK_B_1 , mapper_S9263B, 0, NULL }, + { "sf2m13" , HACK_B_4 , mapper_S9263B, 0, NULL }, + { "sf2tlona" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2tlonb" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2th" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2yyc" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2koryu" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2hf" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2hfu" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2hfj" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "slammast" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_decode }, + { "slammastu" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_decode }, + { "mbomberj" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_decode }, + { "mbombrd" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, + { "mbombrdj" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, + { "strider" , CPS_B_01 , mapper_ST24M1, 1, NULL }, + { "striderua" , CPS_B_01 , mapper_ST24M1, 1, NULL }, + { "striderjr" , CPS_B_21_DEF, mapper_ST24M1, 1, NULL }, + { "striderj" , CPS_B_01 , mapper_ST22B , 1, NULL }, + { "unsquad" , CPS_B_11 , mapper_AR24B , 0, NULL }, + { "area88" , CPS_B_11 , mapper_AR22B , 0, NULL }, + { "area88r" , CPS_B_21_DEF, mapper_AR22B , 0, NULL }, + { "varth" , CPS_B_04 , mapper_VA63B , 0, NULL }, + { "varthr1" , CPS_B_04 , mapper_VA63B , 0, NULL }, + { "varthu" , CPS_B_04 , mapper_VA63B , 0, NULL }, + { "varthj" , CPS_B_21_BT5, mapper_VA22B , 0, NULL }, + { "willow" , CPS_B_03 , mapper_WL24B , 0, NULL }, + { "willowj" , CPS_B_03 , mapper_WL24B , 0, NULL }, + { "willowo" , CPS_B_03 , mapper_WL24B , 0, NULL }, + { "wof" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "wofa" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "wofu" , CPS_B_21_QS1, mapper_TK263B, 0, wof_decode }, + { "wofj" , CPS_B_21_QS1, mapper_TK263B, 0, wof_decode }, + { "wofhfh" , CPS_B_21_DEF, mapper_TK263B, 0, NULL }, + { "wofb" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "wof3js" , CPS_B_21_DEF, mapper_TK263B, 0, NULL }, + { "wof3sj" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wof3sja" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wofaha" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "wofah" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "wofh" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wofha" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wofjh" , CPS_B_21_QS1, mapper_TK263B, 0, wof_decode }, + { "wofsj" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wofsja" , HACK_B_3 , mapper_TK263B, 0, wof_decode }, + { "wofsjb" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, + { "sfzch" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "sfach" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "sfabch" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "sfzbch" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "sfzech" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "sfzhch" , CPS_B_21_DEF, mapper_sfzch , 0, NULL }, + { "wofch" , CPS_B_21_DEF, mapper_sfzch , 0, wof_decode }, + { "cps1frog" , CPS_B_04 , mapper_frog , 0, NULL }, + + // Not included games +/* + { "pnicku" , CPS_B_21_DEF, mapper_pnickj, 0, NULL }, // IPS + { "sf2cebr" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, // IPS + { "sf2ceh" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, // IPS + { "slammasa" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_decode }, // IPS + { "slammash" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_decode }, // IPS + { "mbombdje" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, // IPS + { "mbombrda" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, // IPS + { "mbombrdh" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, // IPS + { "mbombrdu" , CPS_B_21_QS5, mapper_MB63B , 0, slammast_decode }, // IPS + { "woffr" , CPS_B_21_DEF, mapper_TK263B, 0, wof_decode }, // IPS +*/ + +#if defined INCLUDE_DUPLICATES + { "dinob" , CPS_B_21_QS2, mapper_CD63B , 0, NULL }, + { "kl2d" , CPS_B_21_DEF, mapper_CD63B , 0, dino_decode }, + { "sf2tlonc" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2turyu" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, + { "sf2tury2" , CPS_B_21_DEF, mapper_S9263B, 0, NULL }, +#endif + + { 0 , 0 , 0 , 0, 0 } +}; + +static void SetGameConfig() +{ + const char *GameName = BurnDrvGetTextA(DRV_NAME); + const struct GameConfig *k = &ConfigTable[0]; + + while (k->DriverName) { + if (strcmp(k->DriverName, GameName) == 0) { + break; + } + ++k; + } + + if (k->DriverName) { + GameHasStars = k->CpsStars; + SetCpsBId(k->CpsBId, GameHasStars); + SetGfxMapper(k->CpsMapperId); + KabukiDecodeFunction = k->DecodeFunction; + } else { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Missing Config Data\n")); +#endif + } +} + +// Driver functions + +static UINT32 nCps68KByteswapRomNum = 0; +static UINT32 nCps68KNoByteswapRomNum = 0; +static UINT32 nCpsZ80RomNum = 0; +static UINT32 nCpsTilesRomNum = 0; +static UINT32 nCpsOkim6295RomNum = 0; +static UINT32 nCpsQsoundRomNum = 0; +static UINT32 nCpsPicRomNum = 0; + +static INT32 Cps1LoadRoms(INT32 bLoad) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + INT32 nOffset = -1; + UINT32 i = 0; + INT32 nRet = 0; + + if (!bLoad) { + do { + ri.nLen = 0; + ri.nType = 0; + BurnDrvGetRomInfo(&ri, ++nOffset); + if ((ri.nType & 0xff) == CPS1_68K_PROGRAM_BYTESWAP) { + nCpsRomLen += ri.nLen; + nCps68KByteswapRomNum++; + } + if ((ri.nType & 0xff) == CPS1_68K_PROGRAM_NO_BYTESWAP) { + nCpsRomLen += ri.nLen; + nCps68KNoByteswapRomNum++; + } + if ((ri.nType & 0xff) == CPS1_Z80_PROGRAM) { + nCpsZRomLen += ri.nLen; + nCpsZ80RomNum++; + } + if ((ri.nType & 0xff) == CPS1_TILES) { + nCpsGfxLen += ri.nLen; + nCpsTilesRomNum++; + } + if ((ri.nType & 0xff) == CPS1_PIC) { + nCpsPicRomNum++; + } + if ((ri.nType & 0xff) == CPS1_OKIM6295_SAMPLES) { + nCpsAdLen += ri.nLen; + nCpsOkim6295RomNum++; + } + if ((ri.nType & 0xff) == CPS1_QSOUND_SAMPLES) { + Cps1Qs = 1; + nCpsQSamLen += ri.nLen; + nCpsQsoundRomNum++; + } + i++; + + } while (ri.nLen); + + if (Cps1Qs) nCpsZRomLen *= 2; + if (GameHasStars) nCpsGfxLen += 0x2000; + if (PangEEP) nCpsGfxLen *= 2; + if (nCpsPicRomNum) Cps1Pic = 1; + +#if 1 && defined FBA_DEBUG + if (nCpsRomLen) bprintf(PRINT_IMPORTANT, _T("68K Rom Length %06X, (%i roms byteswapped, %i roms not byteswapped)\n"), nCpsRomLen, nCps68KByteswapRomNum, nCps68KNoByteswapRomNum); + if (nCpsZRomLen) bprintf(PRINT_IMPORTANT, _T("Z80 Rom Length %06X, (%i roms)\n"), nCpsZRomLen, nCpsZ80RomNum); + if (nCpsGfxLen) bprintf(PRINT_IMPORTANT, _T("Tile Rom Length %08X, (%i roms)\n"), nCpsGfxLen, nCpsTilesRomNum); + if (nCpsAdLen) bprintf(PRINT_IMPORTANT, _T("OKIM6295 Rom Length %08X, (%i roms)\n"), nCpsAdLen, nCpsOkim6295RomNum); + if (nCpsQSamLen) bprintf(PRINT_IMPORTANT, _T("QSound Rom Length %08X, (%i roms)\n"), nCpsQSamLen, nCpsQsoundRomNum); +#endif + } + + if (bLoad) { + INT32 Offset = 0; + + i = 0; + while (i < nCps68KByteswapRomNum + nCps68KNoByteswapRomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + if ((ri.nType & 0xff) == CPS1_68K_PROGRAM_BYTESWAP) { + nRet = BurnLoadRom(CpsRom + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(CpsRom + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == CPS1_68K_PROGRAM_NO_BYTESWAP) { + nRet = BurnLoadRom(CpsRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + + // Graphics + if (nCpsGfxLen) { + Offset = 0; + i = nCps68KByteswapRomNum + nCps68KNoByteswapRomNum; + while (i < nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum) { + if (Cps1CallbackFunction) { + Cps1CallbackFunction(i); + + i += nCpsTilesRomNum; + } else { + BurnDrvGetRomInfo(&ri, i + 0); + + if (ri.nLen < 0x80000) { + CpsLoadTilesByte(CpsGfx + Offset, i); + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 4); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 5); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 6); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 7); + Offset += ri.nLen; + + i += 8; + } else { + if (PangEEP) { + CpsLoadTilesPang(CpsGfx + Offset, i); + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + + i += 4; + } else { + if (nCpsTilesRomNum < 4) { + // Handle this seperately + i += nCpsTilesRomNum; + } else { + CpsLoadTiles(CpsGfx + Offset, i); + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + + i += 4; + } + } + } + } + } + } + + // Z80 Program + if (nCpsZRomLen) { + Offset = 0; + for (i = nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum; i < nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum + nCpsZ80RomNum; i++) { + BurnLoadRom(CpsZRom + Offset, i, 1); + + if (Cps1Qs) BurnLoadRom(CpsEncZRom + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + // Pic (skip for now) + if (nCpsPicRomNum) { + BurnDrvGetRomInfo(&ri, i); + } + + // OKIM6295 Samples + if (nCpsAdLen) { + Offset = 0; + for (i = nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum + nCpsZ80RomNum; i < nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum + nCpsZ80RomNum + nCpsOkim6295RomNum; i++) { + BurnLoadRom(CpsAd + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + // QSound Samples + if (nCpsQSamLen) { + Offset = 0; + for (i = nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum + nCpsZ80RomNum; i < nCps68KByteswapRomNum + nCps68KNoByteswapRomNum + nCpsTilesRomNum + nCpsZ80RomNum + nCpsQsoundRomNum; i++) { + BurnLoadRom((UINT8*)CpsQSam + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + } + + return nRet; +} + +typedef void (*AmendProgRom)(); +static AmendProgRom AmendProgRomCallback; + +static INT32 DrvInit() +{ + INT32 nRet = 0; + + SetGameConfig(); + + Cps1LoadRoms(0); + + Cps = 1; + nRet = CpsInit(); if (nRet != 0) return 1; + + Cps1LoadRoms(1); + + if (AmendProgRomCallback) AmendProgRomCallback(); + + SetGameConfig(); + + if (Cps1Qs) { + KabukiDecodeFunction(); + } + + nRet = CpsRunInit(); if (nRet != 0) return 1; + + return 0; +} + +static INT32 TwelveMhzInit() +{ + nCPS68KClockspeed = 12000000; + + return DrvInit(); +} + +static INT32 CaptcommbInit() +{ + INT32 nRet = 0; + + CpsLayer1XOffs = -8; + CpsLayer2XOffs = -11; + CpsLayer3XOffs = -12; + + nRet = DrvInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesCaptcomb(CpsGfx, 4); + + return nRet; +} + +UINT8 __fastcall CawingbInputRead(UINT32 a) +{ + UINT8 d = 0xff; + + switch (a) { + case 0x882000: { + d = (UINT8)~Inp000; + return d; + } + + case 0x882001: { + d = (UINT8)~Inp001; + return d; + } + + case 0x882008: { + d = (UINT8)~Inp008; + return d; + } + + case 0x88200a: { + d = (UINT8)~Cpi01A; + return d; + } + + case 0x88200c: { + d = (UINT8)~Cpi01C; + return d; + } + + case 0x88200e: { + d = (UINT8)~Cpi01E; + return d; + } + } + + return 0; +} + +void __fastcall CawingbInputWrite(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x882006: { + PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles); + + PsndCode = d; + return; + } + } + +} + +static INT32 CawingbInit() +{ + INT32 nRet = 0; + + CpsLayer1XOffs = 0xffc0; +// CpsLayer2XOffs = 0xffc0; +// CpsLayer3XOffs = 0xffc0; + + nRet = DrvInit(); + + SekOpen(0); + SekMapHandler(1, 0x882000, 0x88200f, SM_RAM); + SekSetReadByteHandler(1, CawingbInputRead); + SekSetWriteByteHandler(1, CawingbInputWrite); + SekClose(); + + return 0; +} + +void __fastcall DinopicScrollWrite(UINT32 a, UINT16 d) +{ + if (a == 0x980000) { + CpsLayer1YOffs = d; + return; + } + + if (a == 0x980002) { + CpsLayer1XOffs = d - 0x40; + return; + } + + if (a == 0x980004) { + CpsLayer2YOffs = d; + return; + } + + if (a == 0x980006) { + CpsLayer2XOffs = d - 0x40; + return; + } + + if (a == 0x980008) { + CpsLayer3YOffs = d; + return; + } + + if (a == 0x98000a) { + CpsLayer3XOffs = d - 0x40; + return; + } +} + +static INT32 DinopicInit() +{ + INT32 nRet = 0; + + Dinopic = 1; + CpsDrawSpritesInReverse = 1; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesBootleg(CpsGfx + 0x000000, 4); + CpsLoadTilesBootleg(CpsGfx + 0x200000, 8); + + BootlegSpriteRam = (UINT8*)malloc(0x2000); + + SekOpen(0); + SekMapMemory(BootlegSpriteRam, 0x990000, 0x991FFF, SM_RAM); + SekMapHandler(1, 0x980000, 0x98000b, SM_WRITE); + SekSetWriteWordHandler(1, DinopicScrollWrite); + SekClose(); + + return nRet; +} + +static void DinohCallback() +{ + // Patch Q-Sound Test ??? + *((UINT16*)(CpsRom + 0xaacf4)) = 0x4e71; +} + +static INT32 DinohInit() +{ + Cps1QsHack = 1; + AmendProgRomCallback = DinohCallback; + + return TwelveMhzInit(); +} + +static void DinohaCallback() +{ + UINT8 *TempRom = (UINT8*)malloc(0x200000); + if (TempRom) { + memcpy(TempRom, CpsRom, 0x200000); + memset(CpsRom, 0, 0x200000); + memcpy(CpsRom + 0x080000, TempRom + 0x000000, 0x80000); + memcpy(CpsRom + 0x000000, TempRom + 0x080000, 0x80000); + memcpy(CpsRom + 0x180000, TempRom + 0x100000, 0x80000); + memcpy(CpsRom + 0x100000, TempRom + 0x180000, 0x80000); + free(TempRom); + TempRom = NULL; + } + + // Patch Q-Sound Test ??? + *((UINT16*)(CpsRom + 0xaacf4)) = 0x4e71; +} + +static INT32 DinohaInit() +{ + INT32 nRet = 0; + + Cps1QsHack = 1; + AmendProgRomCallback = DinohaCallback; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 2); + + return nRet; +} + +static INT32 DinohbInit() +{ + INT32 nRet = 0; + + Dinopic = 1; + Cps1Pic = 1; + CpsDrawSpritesInReverse = 1; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 2); + + BootlegSpriteRam = (UINT8*)malloc(0x2000); + + SekOpen(0); + SekMapMemory(BootlegSpriteRam, 0x990000, 0x991FFF, SM_RAM); + SekMapHandler(1, 0x980000, 0x98000b, SM_WRITE); + SekSetWriteWordHandler(1, DinopicScrollWrite); + SekClose(); + + return nRet; +} + +UINT8 __fastcall DinohuntQSharedRamRead(UINT32 /*a*/) +{ + return 0xff; +} + +static INT32 DinohuntInit() +{ + INT32 nRet = 0; + + Dinohunt = 1; + + nRet = TwelveMhzInit(); + + SekOpen(0); + SekMapHandler(1, 0xf18000, 0xf19fff, SM_READ); + SekSetReadByteHandler(1, DinohuntQSharedRamRead); + SekClose(); + + return nRet; +} + +static INT32 ForgottnInit() +{ + INT32 nRet = 0; + + Forgottn = 1; + + nRet = DrvInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStars(CpsStar, 9); + + return nRet; +} + +static INT32 ForgottnAltGfxInit() +{ + INT32 nRet = 0; + + Forgottn = 1; + Cps1CallbackFunction = CpsLoadTilesForgottn; + + nRet = DrvInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStarsForgottnAlt(CpsStar, 15); + + return nRet; +} + +static INT32 ForgottnAltGfxuInit() +{ + INT32 nRet = 0; + + Forgottn = 1; + Cps1CallbackFunction = CpsLoadTilesForgottnu; + + nRet = DrvInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStarsForgottnAlt(CpsStar, 15); + + return nRet; +} + +static void GhoulsCallback() +{ + BurnByteswap(CpsRom + 0x080000, 0x080000); +} + +static INT32 GhoulsInit() +{ + Ghouls = 1; + AmendProgRomCallback = GhoulsCallback; + + return DrvInit(); +} + +static INT32 DaimakaiInit() +{ + Ghouls = 1; + + return DrvInit(); +} + +static INT32 DaimakbInit() +{ + Ghouls = 1; + Port6SoundWrite = 1; + + return DrvInit(); +} + +static INT32 KodbInit() +{ + INT32 nRet = 0; + + Kodb = 1; + + nRet = DrvInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesByte(CpsGfx, 2); + + return nRet; +} + +static INT32 KodhInit() +{ + Kodh = 1; + + return DrvInit(); +} + +static INT32 MercsInit() +{ + Mercs = 1; + + return DrvInit(); +} + +static INT32 Pang3nInit() +{ + PangEEP = 1; + + return TwelveMhzInit(); +} + +static void Pang3Callback() +{ + for (INT32 i = 0x80000; i < 0x100000; i += 2) { + INT32 src = CpsRom[i]; + INT32 dst = src & 0xff00; + if ( src & 0x01) dst ^= 0x04; + if ( src & 0x02) dst ^= 0x21; + if ( src & 0x04) dst ^= 0x01; + if (~src & 0x08) dst ^= 0x50; + if ( src & 0x10) dst ^= 0x40; + if ( src & 0x20) dst ^= 0x06; + if ( src & 0x40) dst ^= 0x08; + if (~src & 0x80) dst ^= 0x88; + CpsRom[i] = (UINT8)dst; + } +} + +static INT32 Pang3Init() +{ + AmendProgRomCallback = Pang3Callback; + + return Pang3nInit(); +} + +static INT32 PunipicInit() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesBootleg(CpsGfx + 0x000000, 4); + CpsLoadTilesBootleg(CpsGfx + 0x200000, 8); + + return nRet; +} + +static INT32 Punipic2Init() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesPunipic2(CpsGfx, 4); + + return nRet; +} + +static INT32 Punipic3Init() +{ + INT32 nRet = 0; + + Cps1Pic = 1; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 4); + + return nRet; +} + +static INT32 QadInit() +{ + Qad = 1; + + return TwelveMhzInit(); +} + +static INT32 Sf2ebblInit() +{ + INT32 nRet = DrvInit(); + + memset(CpsGfx + 0x400000, 0, 0x80000); + CpsLoadTilesSf2ebbl(CpsGfx + 0x400000, 19); + + Sf2Hack = 1; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + return nRet; +} + +static INT32 Sf2jcInit() +{ + Sf2jc = 1; + + return DrvInit(); +} + +static void Sf2qp1Callback() +{ + UINT8 *TempRom = (UINT8*)malloc(0x100000); + if (TempRom) { + memcpy(TempRom, CpsRom, 0x100000); + memset(CpsRom, 0, 0x100000); + memcpy(CpsRom + 0x000000, TempRom + 0x000000, 0x40000); + memcpy(CpsRom + 0x0c0000, TempRom + 0x040000, 0x40000); + memcpy(CpsRom + 0x080000, TempRom + 0x080000, 0x40000); + memcpy(CpsRom + 0x040000, TempRom + 0x0c0000, 0x40000); + free(TempRom); + TempRom = NULL; + } +} + +static INT32 Sf2qp1Init() +{ + AmendProgRomCallback = Sf2qp1Callback; + + return DrvInit(); +} + +static INT32 Sf2thndrInit() +{ + Sf2thndr = 1; + + return DrvInit(); +} + +static INT32 Sf2ceInit() +{ + nCPS68KClockspeed = 7000000; + + return DrvInit(); +} + +static void Sf2accp2Callback() +{ + CpsRom[0x11755] = 0x4e; + CpsRom[0x11756] = 0x71; +} + +static INT32 Sf2accp2Init() +{ + AmendProgRomCallback = Sf2accp2Callback; + + return Sf2ceInit(); +} + +static INT32 Sf2dkot2Init() +{ + INT32 nRet; + + nRet = Sf2ceInit(); + + SekOpen(0); + SekMapMemory(CpsRom + 0x000000, 0x280000, 0x2fffff, SM_ROM); + SekMapMemory(CpsRom + 0x080000, 0x200000, 0x27ffff, SM_ROM); + SekClose(); + + return nRet; +} + +static void Sf2rbCallback() +{ + BurnByteswap(CpsRom, 0x100000); + CpsRom[0xe5465] = 0x60; + CpsRom[0xe5464] = 0x12; +} + +static INT32 Sf2rbInit() +{ + AmendProgRomCallback = Sf2rbCallback; + + return Sf2ceInit(); +} + +static void Sf2rb2Callback() +{ + BurnByteswap(CpsRom, 0x100000); + CpsRom[0xe5333] = 0x60; + CpsRom[0xe5332] = 0x14; +} + +static INT32 Sf2rb2Init() +{ + AmendProgRomCallback = Sf2rb2Callback; + + return Sf2ceInit(); +} + +static INT32 Sf2thInit() +{ + INT32 nRet = 0; + + Sf2Hack = 1; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + nRet = Sf2ceInit(); + + return nRet; +} + +static void Sf2yycCallback() +{ + memcpy(CpsRom + 0x140000, CpsRom + 0x100000, 0x40000); + + *((UINT16*)(CpsRom + 0xe55be)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55ca)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55cc)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55ce)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55d0)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55d2)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55d4)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55d6)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55d8)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55da)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55de)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55e2)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55e4)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55e6)) = 0x4e71; + *((UINT16*)(CpsRom + 0xe55e8)) = 0x4e71; +} + +static INT32 Sf2yycInit() +{ + nCpsRomLen = 0x40000; + + Sf2Hack = 1; + AmendProgRomCallback = Sf2yycCallback; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + return Sf2ceInit(); +} + +static void Sf2koryuCallback() +{ + BurnByteswap(CpsRom, 0x140000); +} + +static INT32 Sf2koryuInit() +{ + Sf2Hack = 1; + AmendProgRomCallback = Sf2koryuCallback; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + return Sf2ceInit(); +} + +static INT32 Sf2m4Init() +{ + Sf2Hack = 1; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + return Sf2ceInit(); +} + +void __fastcall Sf2m1ScrollWrite(UINT32 a, UINT16 d) +{ + if (a == 0x980000) { + CpsReg[0x0e] = d & 0xff; + CpsReg[0x0f] = d >> 8; + return; + } + + if (a == 0x980002) { + d -= 0x40; + CpsReg[0x0c] = d & 0xff; + CpsReg[0x0d] = d >> 8; + return; + } + + if (a == 0x980004) { + CpsReg[0x12] = d & 0xff; + CpsReg[0x13] = d >> 8; + return; + } + + if (a == 0x980006) { + d -= 0x40; + CpsReg[0x10] = d & 0xff; + CpsReg[0x11] = d >> 8; + return; + } + + if (a == 0x980008) { + CpsReg[0x16] = d & 0xff; + CpsReg[0x17] = d >> 8; + return; + } + + if (a == 0x98000a) { + d -= 0x40; + CpsReg[0x14] = d & 0xff; + CpsReg[0x15] = d >> 8; + return; + } + + if (a == 0x980016) { + CpsReg[0x06] = d & 0xff; + CpsReg[0x07] = d >> 8; + return; + } + + if (a == 0x980166) { + CpsReg[0x66] = d & 0xff; + CpsReg[0x67] = d >> 8; + return; + } +} + +static INT32 Sf2m1Init() +{ + INT32 nRet = 0; + + CpsLayer2XOffs = 4; + Port6SoundWrite = 1; + + nRet = Sf2ceInit(); + + SekOpen(0); + SekMapHandler(1, 0x980000, 0x980167, SM_WRITE); + SekSetWriteWordHandler(1, Sf2m1ScrollWrite); + SekClose(); + + return nRet; +} + +static void Sf2m2Callback() +{ + *((UINT16*)(CpsRom + 0xC0680)) = 0x4E71; + *((UINT16*)(CpsRom + 0xC0682)) = 0x4E71; + *((UINT16*)(CpsRom + 0xC0684)) = 0x4E71; +} + +static INT32 Sf2m2Init() +{ + Sf2Hack = 1; + AmendProgRomCallback = Sf2m2Callback; + + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + return Sf2ceInit(); +} + +UINT8 __fastcall Sf2m3ReadByte(UINT32 a) +{ + UINT8 d = 0xff; + + switch (a) { + case 0x800010: { + d = (UINT8)~Inp010; + return d; + } + + case 0x800011: { + d = (UINT8)~Inp011; + return d; + } + + case 0x800029: { + d = (UINT8)~Inp029; + return d; + } + + case 0x800186: { + d = (UINT8)~Inp186; + return d; + } + + case 0x80002a: { + d = (UINT8)~Cpi01A; + return d; + } + + case 0x80002c: { + d = (UINT8)~Cpi01C; + return d; + } + + case 0x80002e: { + d = (UINT8)~Cpi01E; + return d; + } + } + +// bprintf(PRINT_NORMAL, _T("Read byte %x\n"), a); + + return 0; +} + +void __fastcall Sf2m3WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x800191: { + PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles); + + PsndCode = d; + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Write byte %x, %x\n"), a, d); +} + +void __fastcall Sf2m3WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x800100: { + CpsReg[0x00] = d & 0xff; + CpsReg[0x01] = d >> 8; + return; + } + + case 0x800102: { + CpsReg[0x02] = d & 0xff; + CpsReg[0x03] = d >> 8; + return; + } + + case 0x800104: { + CpsReg[0x04] = d & 0xff; + CpsReg[0x05] = d >> 8; + return; + } + + case 0x800106: { + CpsReg[0x06] = d & 0xff; + CpsReg[0x07] = d >> 8; + return; + } + + case 0x80010a: { + CpsReg[0x0a] = d & 0xff; + CpsReg[0x0b] = d >> 8; + return; + } + + case 0x800122: { + CpsReg[0x22] = d & 0xff; + CpsReg[0x23] = d >> 8; + return; + } + + case 0x80014a: { + CpsReg[0x4a] = d & 0xff; + CpsReg[0x4b] = d >> 8; + return; + } + + case 0x80014c: { + CpsReg[0x4c] = d & 0xff; + CpsReg[0x4d] = d >> 8; + return; + } + + case 0x80014e: { + CpsReg[0x4e] = d & 0xff; + CpsReg[0x4f] = d >> 8; + return; + } + + case 0x800150: { + CpsReg[0x50] = d & 0xff; + CpsReg[0x51] = d >> 8; + return; + } + + case 0x800152: { + CpsReg[0x52] = d & 0xff; + CpsReg[0x53] = d >> 8; + return; + } + + case 0x8001a8: { + CpsReg[0x08] = d & 0xff; + CpsReg[0x09] = d >> 8; + return; + } + + case 0x8001ac: { + CpsReg[0x0c] = d & 0xff; + CpsReg[0x0d] = d >> 8; + return; + } + + case 0x8001ae: { + CpsReg[0x0e] = d & 0xff; + CpsReg[0x0f] = d >> 8; + return; + } + + case 0x8001b0: { + CpsReg[0x10] = d & 0xff; + CpsReg[0x11] = d >> 8; + return; + } + + case 0x8001b2: { + CpsReg[0x12] = d & 0xff; + CpsReg[0x13] = d >> 8; + return; + } + + case 0x8001b4: { + CpsReg[0x14] = d & 0xff; + CpsReg[0x15] = d >> 8; + return; + } + + case 0x8001b6: { + CpsReg[0x16] = d & 0xff; + CpsReg[0x17] = d >> 8; + return; + } + + case 0x8001c0: { + CpsReg[0x20] = d & 0xff; + CpsReg[0x21] = d >> 8; + return; + } + + case 0x8001c4: { + CpsReg[0xc4] = d & 0xff; + CpsReg[0xc5] = d >> 8; + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Write word %x, %x\n"), a, d); +} + +static INT32 Sf2m3Init() +{ + INT32 nRet = 0; + + CpsLayer1XOffs = -16; + CpsLayer2XOffs = -16; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + nRet = Sf2ceInit(); + + SekOpen(0); + SekMapHandler(1, 0x800000, 0x800200, SM_RAM); + SekSetReadByteHandler(1, Sf2m3ReadByte); + SekSetWriteByteHandler(1, Sf2m3WriteByte); + SekSetWriteWordHandler(1, Sf2m3WriteWord); + + SekClose(); + + return nRet; +} + +static INT32 Sf2m8Init() +{ + Scroll1TileMask = 0x4fff; + Scroll3TileMask = 0x1fff; + + return Sf2m3Init(); +} + +static void Sf2m13Callback() +{ + CpsRom[0x1d22a] = 0x20; // Fix scroll +} + +static INT32 Sf2m13Init() +{ + CpsLayer1XOffs = -12; + CpsLayer2XOffs = -14; + CpsLayer3XOffs = -16; + CpsDrawSpritesInReverse = 1; + + AmendProgRomCallback = Sf2m13Callback; + + return Sf2ceInit(); +} + +static INT32 SfzchInit() +{ + INT32 nRet = 0; + + nRet = DrvInit(); + + Cps = 3; + + return nRet; +} + +static INT32 StriderInit() +{ + INT32 nRet = 0; + + nRet = DrvInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStars(CpsStar, 5); + + return nRet; +} + +static INT32 StriderjrInit() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStars(CpsStar, 2); + + return nRet; +} + +static INT32 StriderjInit() +{ + INT32 nRet = 0; + + nRet = DrvInit(); + + CpsStar = CpsGfx + nCpsGfxLen - 0x2000; + + CpsLoadStarsByte(CpsStar, 8); + + return nRet; +} + +static INT32 WofbInit() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesBootleg(CpsGfx + 0x000000, 4); + CpsLoadTilesBootleg(CpsGfx + 0x200000, 8); + + return nRet; +} + +static void Wof3jsCallback() +{ + memcpy(CpsRom + 0x0c0000, CpsRom + 0x100000, 0x40000); + memset(CpsRom + 0x100000, 0, 0x40000); +} + +static INT32 Wof3jsInit() +{ + AmendProgRomCallback = Wof3jsCallback; + + return TwelveMhzInit(); +} + +static INT32 Wof3sjInit() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 2); + + return nRet; +} + +static INT32 Wof3sjaInit() +{ + INT32 nRet = 0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 1); + + return nRet; +} + +static INT32 WofchInit() +{ + INT32 nRet = 0; + + Cps1Qs = 1; + + nRet = DrvInit(); + + Cps = 3; + + return nRet; +} + +static void WofhCallback() +{ + // Patch protection? check + CpsRom[0xf11ed] = 0x4e; + CpsRom[0xf11ec] = 0x71; + CpsRom[0xf11ef] = 0x4e; + CpsRom[0xf11ee] = 0x71; +} + +static INT32 WofhInit() +{ + INT32 nRet = 0; + + AmendProgRomCallback = WofhCallback; + + CpsLayer1XOffs = 0xffc0; + CpsLayer2XOffs = 0xffc0; + CpsLayer3XOffs = 0xffc0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 1); + + return nRet; +} + +static INT32 WofhaInit() +{ + INT32 nRet = 0; + + AmendProgRomCallback = WofhCallback; + + CpsLayer1XOffs = 0xffc0; + CpsLayer2XOffs = 0xffc0; + CpsLayer3XOffs = 0xffc0; + + nRet = TwelveMhzInit(); + + memset(CpsGfx, 0, nCpsGfxLen); + CpsLoadTilesHack160(CpsGfx, 2); + + return nRet; +} + +static INT32 DrvExit() +{ + CpsRunExit(); + CpsExit(); + + nCpsRomLen = 0; + nCpsZRomLen = 0; + nCpsGfxLen = 0; + nCpsAdLen = 0; + nCpsQSamLen = 0; + nCpsPicRomNum = 0; + + nCps68KByteswapRomNum = 0; + nCps68KNoByteswapRomNum = 0; + nCpsZ80RomNum = 0; + nCpsTilesRomNum = 0; + nCpsOkim6295RomNum = 0; + nCpsQsoundRomNum = 0; + KabukiDecodeFunction = NULL; + GameHasStars = 0; + + AmendProgRomCallback = NULL; + + CpsLayer1XOffs = 0; + CpsLayer2XOffs = 0; + CpsLayer3XOffs = 0; + CpsLayer1YOffs = 0; + CpsLayer2YOffs = 0; + CpsLayer3YOffs = 0; + CpsDrawSpritesInReverse = 0; + + Cps = 0; + Cps1Qs = 0; + Cps1Pic = 0; + Forgottn = 0; + Ghouls = 0; + Kodb = 0; + Mercs = 0; + PangEEP = 0; + Qad = 0; + Sf2jc = 0; + Sf2Hack = 0; + Dinopic = 0; + Dinohunt = 0; + Sf2thndr = 0; + Port6SoundWrite = 0; + + Cps1QsHack = 0; + + Cps1CallbackFunction = NULL; + + if (BootlegSpriteRam) { + free(BootlegSpriteRam); + BootlegSpriteRam = NULL; + } + + return 0; +} + +// Driver Definitions + +struct BurnDriver BurnDrvCps1941 = { + "1941", NULL, NULL, NULL, "1990", + "1941 - Counter Attack (World)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, FBF_19XX, + NULL, NTFODrvRomInfo, NTFODrvRomName, NULL, NULL, NTFOInputInfo, NTFODIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps1941u = { + "1941u", "1941", NULL, NULL, "1990", + "1941 - Counter Attack (900227 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, FBF_19XX, + NULL, NTFOUDrvRomInfo, NTFOUDrvRomName, NULL, NULL, NTFOInputInfo, NTFODIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps1941j = { + "1941j", "1941", NULL, NULL, "1990", + "1941 - Counter Attack (Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, FBF_19XX, + NULL, NTFOJDrvRomInfo, NTFOJDrvRomName, NULL, NULL, NTFOInputInfo, NTFODIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps3wonders = { + "3wonders", NULL, NULL, NULL, "1991", + "Three Wonders (wonder 3 910520 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_MINIGAMES, 0, + NULL, ThreeWondersRomInfo, ThreeWondersRomName, NULL, NULL, ThreeWondersInputInfo, ThreeWondersDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCps3wondersu = { + "3wondersu", "3wonders", NULL, NULL, "1991", + "Three Wonders (wonder 3 910520 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_MINIGAMES, 0, + NULL, Wonder3uRomInfo, Wonder3uRomName, NULL, NULL, ThreeWondersInputInfo, ThreeWondersDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWonder3 = { + "wonder3", "3wonders", NULL, NULL, "1991", + "Wonder 3 (910520 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_MINIGAMES, 0, + NULL, Wonder3RomInfo, Wonder3RomName, NULL, NULL, ThreeWondersInputInfo, ThreeWondersDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCps3wondersh = { + "3wondersh", "3wonders", NULL, NULL, "1991", + "Three Wonders (bootleg)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_MINIGAMES, 0, + NULL, Wonder3hRomInfo, Wonder3hRomName, NULL, NULL, ThreeWondersInputInfo, ThreeWondersDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCaptcomm = { + "captcomm", NULL, NULL, NULL, "1991", + "Captain Commando (911202 other country)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, CaptcommRomInfo, CaptcommRomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCaptcommr1 = { + "captcommr1", "captcomm", NULL, NULL, "1991", + "Captain Commando (911014 other country)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Captcommr1RomInfo, Captcommr1RomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCaptcommu = { + "captcommu", "captcomm", NULL, NULL, "1991", + "Captain Commando (910928 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, CaptcommuRomInfo, CaptcommuRomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCaptcommj = { + "captcommj", "captcomm", NULL, NULL, "1991", + "Captain Commando (911202 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, CaptcommjRomInfo, CaptcommjRomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCaptcommjr1 = { + "captcommjr1", "captcomm", NULL, NULL, "1991", + "Captain Commando (910928 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Captcommjr1RomInfo, Captcommjr1RomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsCaptcommb = { + "captcommb", "captcomm", NULL, NULL, "1991", + "Captain Commando (bootleg)\0", "Sprite issues", "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, CaptcommbRomInfo, CaptcommbRomName, NULL, NULL, CaptcommInputInfo, CaptcommDIPInfo, + CaptcommbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCawing = { + "cawing", NULL, NULL, NULL, "1990", + "Carrier Air Wing (U.S. navy 901012 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, CawingRomInfo, CawingRomName, NULL, NULL, CawingInputInfo, CawingDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCawingr1 = { + "cawingr1", "cawing", NULL, NULL, "1990", + "Carrier Air Wing (U.S. navy 901009 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, Cawingr1RomInfo, Cawingr1RomName, NULL, NULL, CawingInputInfo, CawingDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCawingu = { + "cawingu", "cawing", NULL, NULL, "1990", + "Carrier Air Wing (U.S. navy 901012 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, CawinguRomInfo, CawinguRomName, NULL, NULL, CawingInputInfo, CawingDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCawingj = { + "cawingj", "cawing", NULL, NULL, "1990", + "U.S. Navy (901012 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, CawingjRomInfo, CawingjRomName, NULL, NULL, CawingInputInfo, CawingDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsCawingb = { + "cawingb", "cawing", NULL, NULL, "1990", + "Carrier Air Wing (bootleg)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, CawingbRomInfo, CawingbRomName, NULL, NULL, CawingbInputInfo, CawingDIPInfo, + CawingbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCps1demo = { + "cps1demo", NULL, NULL, NULL, "2000", + "Chaos Demo (CPS-1)\0", NULL, "Chaos", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_CAPCOM_CPS1, GBF_MISC, 0, + NULL, Cps1demoRomInfo, Cps1demoRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCworld2j = { + "cworld2j", NULL, NULL, NULL, "1992", + "Capcom World 2 (920611 Japan)\0", NULL, "Capcom", "CPS1", + L"Capcom World 2 (\u30AF\u30A4\u30BA\uFF15 \u3042\u3069\u3079\u3093\u3061\u3083\u30FC\u304F\u3044\u305A \u304B\u3077\u3053\u3093\u308F\u30FC\u308B\u3069\uFF12 920611 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PUZZLE, 0, + NULL, Cworld2jRomInfo, Cworld2jRomName, NULL, NULL, Cworld2jInputInfo, Cworld2jDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDino = { + "dino", NULL, NULL, NULL, "1993", + "Cadillacs & Dinosaurs (930201 etc)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinoRomInfo, DinoRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinoj = { + "dinoj", "dino", NULL, NULL, "1993", + "Cadillacs Kyouryuu-Shinseiki (Cadillacs 930201 Japan)\0", NULL, "Capcom", "CPS1 / QSound", + L"Cadillacs \u6050\u7ADC\u65B0\u4E16\u7D00 (Cadillacs 930201 Japan)\0Cadillacs Kyouryuu-Shinseiki (Cadillacs 930201 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinojRomInfo, DinojRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinou = { + "dinou", "dino", NULL, NULL, "1993", + "Cadillacs & Dinosaurs (930201 USA)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinouRomInfo, DinouRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsDinopic = { + "dinopic", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs (bootleg with PIC16c57, set 1)\0", "Missing sprites, no sound", "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DinopicRomInfo, DinopicRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinopicInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsDinopic2 = { + "dinopic2", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs (bootleg with PIC16c57, set 2)\0", "Missing sprites, no sound", "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Dinopic2RomInfo, Dinopic2RomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinopicInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinoeh = { + "dinoeh", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs (hack)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinoehRomInfo, DinoehRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinoh = { + "dinoh", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs (930223 Asia TW bootleg)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinohRomInfo, DinohRomName, NULL, NULL, DinohInputInfo, DinohDIPInfo, + DinohInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinoha = { + "dinoha", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs Turbo (930223 Asia TW bootleg)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinohaRomInfo, DinohaRomName, NULL, NULL, DinohInputInfo, DinohDIPInfo, + DinohaInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsDinohb = { + "dinohb", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs Turbo (bootleg with PIC16c57)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DinohbRomInfo, DinohbRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinohbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDinohunt = { + "dinohunt", "dino", NULL, NULL, "1993", + "Dinosaur Hunter (Chinese bootleg of Cadillacs and Dinosaurs (930223 Asia TW))\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DinohuntRomInfo, DinohuntRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinohuntInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDw = { + "dynwar", NULL, NULL, NULL, "1989", + "Dynasty Wars (US set 1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DynwarRomInfo, DynwarRomName, NULL, NULL, DynwarInputInfo, DynwarDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDwa = { + "dynwara", "dynwar", NULL, NULL, "1989", + "Dynasty Wars (US set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DynwaraRomInfo, DynwaraRomName, NULL, NULL, DynwarInputInfo, DynwarDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDwj = { + "dynwarj", "dynwar", NULL, NULL, "1989", + "Tenchi wo Kurau (Japan)\0", NULL, "Capcom", "CPS1", + L"\u8EE2\u5730\u3092\u55B0\u3089\u3046 (Japan)\0Tenchi wo Kurau (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DynwarjRomInfo, DynwarjRomName, NULL, NULL, DynwarInputInfo, DynwarDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDwjr = { + "dynwarjr", "dynwar", NULL, NULL, "1989", + "Tenchi wo Kurau (Japan Resale Ver.)\0", NULL, "Capcom", "CPS1", + L"\u8EE2\u5730\u3092\u55B0\u3089\u3046 (Japan Resale Ver.)\0Tenchi wo Kurau (Japan Resale Ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, DynwarjrRomInfo, DynwarjrRomName, NULL, NULL, DynwarInputInfo, DynwarDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfight = { + "ffight", NULL, NULL, NULL, "1989", + "Final Fight (World)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightRomInfo, FfightRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightu = { + "ffightu", "ffight", NULL, NULL, "1989", + "Final Fight (USA, set 1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightuRomInfo, FfightuRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightu1 = { + "ffightu1", "ffight", NULL, NULL, "1989", + "Final Fight (USA, set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Ffightu1RomInfo, Ffightu1RomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightua = { + "ffightua", "ffight", NULL, NULL, "1989", + "Final Fight (900112 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightuaRomInfo, FfightuaRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightub = { + "ffightub", "ffight", NULL, NULL, "1989", + "Final Fight (900613 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightubRomInfo, FfightubRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightj = { + "ffightj", "ffight", NULL, NULL, "1989", + "Final Fight (Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightjRomInfo, FfightjRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightj1 = { + "ffightj1", "ffight", NULL, NULL, "1989", + "Final Fight (900112 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Ffightj1RomInfo, Ffightj1RomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightj2 = { + "ffightj2", "ffight", NULL, NULL, "1989", + "Final Fight (900305 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Ffightj2RomInfo, Ffightj2RomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsFfightjh = { + "ffightjh", "ffight", NULL, NULL, "1989", + "Street Smart / Final Fight (Japan, hack)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, FfightjhRomInfo, FfightjhRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsForgottn = { + "forgottn", NULL, NULL, NULL, "1988", + "Forgotten Worlds (World)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_HORSHOOT, 0, + NULL, ForgottnRomInfo, ForgottnRomName, NULL, NULL, ForgottnInputInfo, ForgottnDIPInfo, + ForgottnAltGfxInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsForgottnu = { + "forgottnu", "forgottn", NULL, NULL, "1988", + "Forgotten Worlds (US, B-Board 88621B-2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_HORSHOOT, 0, + NULL, ForgottnuRomInfo, ForgottnuRomName, NULL, NULL, ForgottnInputInfo, ForgottnDIPInfo, + ForgottnAltGfxuInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsForgottnua = { + "forgottnua", "forgottn", NULL, NULL, "1988", + "Forgotten Worlds (US, B-Board 88618B-?)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_HORSHOOT, 0, + NULL, ForgottnuaRomInfo, ForgottnuaRomName, NULL, NULL, ForgottnInputInfo, ForgottnDIPInfo, + ForgottnInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsLostwrld = { + "lostwrld", "forgottn", NULL, NULL, "1988", + "Lost Worlds (Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_HORSHOOT, 0, + NULL, LostwrldRomInfo, LostwrldRomName, NULL, NULL, ForgottnInputInfo, ForgottnDIPInfo, + ForgottnInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsLostwrldo = { + "lostwrldo", "forgottn", NULL, NULL, "1988", + "Lost Worlds (Japan Old ver.)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_HORSHOOT, 0, + NULL, LostwrldoRomInfo, LostwrldoRomName, NULL, NULL, ForgottnInputInfo, ForgottnDIPInfo, + ForgottnInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGhouls = { + "ghouls", NULL, NULL, NULL, "1988", + "Ghouls'n Ghosts (World)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, GhoulsRomInfo, GhoulsRomName, NULL, NULL, GhoulsInputInfo, GhoulsDIPInfo, + GhoulsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGhoulsu = { + "ghoulsu", "ghouls", NULL, NULL, "1988", + "Ghouls'n Ghosts (US)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, GhoulsuRomInfo, GhoulsuRomName, NULL, NULL, GhoulsInputInfo, GhoulsuDIPInfo, + GhoulsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDaimakai = { + "daimakai", "ghouls", NULL, NULL, "1988", + "Dai Makai-Mura (Japan)\0", NULL, "Capcom", "CPS1", + L"\u5927\u9B54\u754C\u6751 (Japan)\0Dai Makai-Mura (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, DaimakaiRomInfo, DaimakaiRomName, NULL, NULL, GhoulsInputInfo, DaimakaiDIPInfo, + DaimakaiInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDaimakair = { + "daimakair", "ghouls", NULL, NULL, "1988", + "Dai Makai-Mura (Japan Resale Ver.)\0", NULL, "Capcom", "CPS1", + L"\u5927\u9B54\u754C\u6751 (Japan Resale Ver.)\0Dai Makai-Mura (Japan Resale Ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, DaimakairRomInfo, DaimakairRomName, NULL, NULL, GhoulsInputInfo, DaimakaiDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsDaimakb = { + "daimakb", "ghouls", NULL, NULL, "1988", + "Dai Makai-Mura (Japan, bootleg)\0", "No scroll layers", "Capcom", "CPS1", + L"\u5927\u9B54\u754C\u6751 (Japan)\0Dai Makai-Mura (Japan, bootleg)\0", NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, DaimakbRomInfo, DaimakbRomName, NULL, NULL, GhoulsInputInfo, DaimakaiDIPInfo, + DaimakbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnights = { + "knights", NULL, NULL, NULL, "1991", + "Knights of the Round (911127 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnightsRomInfo, KnightsRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnightsu = { + "knightsu", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnightsuRomInfo, KnightsuRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnightsj = { + "knightsj", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 Japan, B-Board 91634B-2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnightsjRomInfo, KnightsjRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnightsja = { + "knightsja", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 Japan, B-Board 89625B-1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnightsjaRomInfo, KnightsjaRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsKnightsb2 = { + "knightsb2", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 etc bootleg set 2)\0", "Some sprite problems", "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Knightsb2RomInfo, Knightsb2RomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnightsb3 = { + "knightsb3", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 Japan bootleg set 3)\0", "Some sprite problems", "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Knightsb3RomInfo, Knightsb3RomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnightsh = { + "knightsh", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 etc bootleg set 3)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnightshRomInfo, KnightshRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKnghtsha = { + "knghtsha", "knights", NULL, NULL, "1991", + "Knights of the Round (911127 etc hack)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KnghtshaRomInfo, KnghtshaRomName, NULL, NULL, KnightsInputInfo, KnightsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKod = { + "kod", NULL, NULL, NULL, "1991", + "The King of Dragons (910805 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KodRomInfo, KodRomName, NULL, NULL, KodInputInfo, KodDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKodr1 = { + "kodr1", "kod", NULL, NULL, "1991", + "The King of Dragons (910711 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Kodr1RomInfo, Kodr1RomName, NULL, NULL, KodInputInfo, Kodr1DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKodu = { + "kodu", "kod", NULL, NULL, "1991", + "The King of Dragons (US 910910)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KoduRomInfo, KoduRomName, NULL, NULL, KodInputInfo, KodDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKodj = { + "kodj", "kod", NULL, NULL, "1991", + "The King of Dragons (Japan 910805, B-Board 90629B-3)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KodjRomInfo, KodjRomName, NULL, NULL, KodInputInfo, KodDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKodja = { + "kodja", "kod", NULL, NULL, "1991", + "The King of Dragons (Japan 910805, B-Board 89625B-1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KodjaRomInfo, KodjaRomName, NULL, NULL, KodInputInfo, KodDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsKodb = { + "kodb", "kod", NULL, NULL, "1991", + "The King of Dragons (bootleg set 1)\0", "No Sprites", "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KodbRomInfo, KodbRomName, NULL, NULL, KodInputInfo, KodDIPInfo, + KodbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKodh = { + "kodh", "kod", NULL, NULL, "1991", + "The King of Dragons (bootleg set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, KodhRomInfo, KodhRomName, NULL, NULL, KodhInputInfo, KodDIPInfo, + KodhInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegaman = { + "megaman", NULL, NULL, NULL, "1995", + "Mega Man - the power battle (951006 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MegamanRomInfo, MegamanRomName, NULL, NULL, MegamanInputInfo, MegamanDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegamana = { + "megamana", "megaman", NULL, NULL, "1995", + "Mega Man - the power battle (951006 Asia)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MegamanaRomInfo, MegamanaRomName, NULL, NULL, MegamanInputInfo, MegamanDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRockmanj = { + "rockmanj", "megaman", NULL, NULL, "1995", + "Rockman - the power battle (950922 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, RockmanjRomInfo, RockmanjRomName, NULL, NULL, MegamanInputInfo, RockmanjDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMercs = { + "mercs", NULL, NULL, NULL, "1990", + "Mercs (900302 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, MercsRomInfo, MercsRomName, NULL, NULL, MercsInputInfo, MercsDIPInfo, + MercsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsMercsu = { + "mercsu", "mercs", NULL, NULL, "1990", + "Mercs (900608 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, MercsuRomInfo, MercsuRomName, NULL, NULL, MercsInputInfo, MercsDIPInfo, + MercsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsMercsur1 = { + "mercsur1", "mercs", NULL, NULL, "1990", + "Mercs (900302 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, Mercsur1RomInfo, Mercsur1RomName, NULL, NULL, MercsInputInfo, MercsDIPInfo, + MercsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsMercsj = { + "mercsj", "mercs", NULL, NULL, "1990", + "Senjo no Ookami II (Ookami 2 900302 Japan)\0", NULL, "Capcom", "CPS1", + L"\u6226\u5834\u306E\u72FC II (Ookami 2 900302 Japan)\0Senjo no Ookami II (Ookami 2 900302 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, MercsjRomInfo, MercsjRomName, NULL, NULL, MercsInputInfo, MercsDIPInfo, + MercsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsMsword = { + "msword", NULL, NULL, NULL, "1990", + "Magic Sword - heroic fantasy (25.07.1990 other country)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, MswordRomInfo, MswordRomName, NULL, NULL, MswordInputInfo, MswordDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMswordr1 = { + "mswordr1", "msword", NULL, NULL, "1990", + "Magic Sword - heroic fantasy (23.06.1990 other country)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Mswordr1RomInfo, Mswordr1RomName, NULL, NULL, MswordInputInfo, MswordDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMswordj = { + "mswordj", "msword", NULL, NULL, "1990", + "Magic Sword (23.06.1990 Japan)\0", NULL, "Capcom", "CPS1", + L"Magic Sword (23.06.1990 Japan)\0Magic Sword\u30DE\u30B8\u30C3\u30AF\uFF65\u30BD\u30FC\u30C9\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, MswordjRomInfo, MswordjRomName, NULL, NULL, MswordInputInfo, MswordDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMswordu = { + "mswordu", "msword", NULL, NULL, "1990", + "Magic Sword - heroic fantasy (25.07.1990 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, MsworduRomInfo, MsworduRomName, NULL, NULL, MswordInputInfo, MswordDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMtwins = { + "mtwins", NULL, NULL, NULL, "1990", + "Mega Twins (chiki chiki boys 900619 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, MtwinsRomInfo, MtwinsRomName, NULL, NULL, MtwinsInputInfo, MtwinsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsChikij = { + "chikij", "mtwins", NULL, NULL, "1990", + "Chiki Chiki Boys (900619 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, ChikijRomInfo, ChikijRomName, NULL, NULL, MtwinsInputInfo, MtwinsDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNemo = { + "nemo", NULL, NULL, NULL, "1990", + "Nemo (90 11 30 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, NemoRomInfo, NemoRomName, NULL, NULL, NemoInputInfo, NemoDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNemoj = { + "nemoj", "nemo", NULL, NULL, "1990", + "Nemo (90 11 20 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2 ,HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, NemojRomInfo, NemojRomName, NULL, NULL, NemoInputInfo, NemoDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPang3 = { + "pang3", NULL, NULL, NULL, "1995", + "Pang! 3 (950601 Euro)\0", NULL, "Mitchell", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_PUZZLE, 0, + NULL, Pang3RomInfo, Pang3RomName, NULL, NULL, Pang3InputInfo, Pang3DIPInfo, + Pang3Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPang3r1 = { + "pang3r1", "pang3", NULL, NULL, "1995", + "Pang! 3 (950511 Euro)\0", NULL, "Mitchell", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_PUZZLE, 0, + NULL, Pang3r1RomInfo, Pang3r1RomName, NULL, NULL, Pang3InputInfo, Pang3DIPInfo, + Pang3Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPang3n = { + "pang3n", "pang3", NULL, NULL, "1995", + "Pang! 3 (950511 Euro, not encrypted)\0", NULL, "Mitchell", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_PUZZLE, 0, + NULL, Pang3nRomInfo, Pang3nRomName, NULL, NULL, Pang3InputInfo, Pang3DIPInfo, + Pang3nInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPang3j = { + "pang3j", "pang3", NULL, NULL, "1995", + "Pang! 3 (950511 Japan)\0", NULL, "Mitchell", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_GENERIC, GBF_PUZZLE, 0, + NULL, Pang3jRomInfo, Pang3jRomName, NULL, NULL, Pang3InputInfo, Pang3DIPInfo, + Pang3Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPnickj = { + "pnickj", NULL, NULL, NULL, "1994", + "Pnickies (940608 Japan)\0", NULL, "Compile (Capcom license)", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PUZZLE, 0, + NULL, PnickjRomInfo, PnickjRomName, NULL, NULL, PnickjInputInfo, PnickjDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPunisher = { + "punisher", NULL, NULL, NULL, "1993", + "The Punisher (930422 etc)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, PunisherRomInfo, PunisherRomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPunisheru = { + "punisheru", "punisher", NULL, NULL, "1993", + "The Punisher (930422 USA)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, PunisheruRomInfo, PunisheruRomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPunisherj = { + "punisherj", "punisher", NULL, NULL, "1993", + "The Punisher (930422 Japan)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, PunisherjRomInfo, PunisherjRomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsPunipic = { + "punipic", "punisher", NULL, NULL, "1993", + "The Punisher (bootleg with PIC16c57, set 1)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, PunipicRomInfo, PunipicRomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + PunipicInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsPunipic2 = { + "punipic2", "punisher", NULL, NULL, "1993", + "The Punisher (bootleg with PIC16c57, set 2)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Punipic2RomInfo, Punipic2RomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + Punipic2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsPunipic3 = { + "punipic3", "punisher", NULL, NULL, "1993", + "The Punisher (bootleg with PIC16c57, set 3)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Punipic3RomInfo, Punipic3RomName, NULL, NULL, PunisherInputInfo, PunisherDIPInfo, + Punipic3Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPunisherbz = { + "punisherbz", "punisher", NULL, NULL, "2002", + "Biaofeng Zhanjing (Chinese bootleg of The Punisher)\0", NULL, "bootleg", "CPS1", + L"\uFEFF\u98C6\u98A8\u6230\u8B66 (bootleg, hack)\0The Punisher: Biaofeng Zhanjing (Chinese bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, PunisherbzRomInfo, PunisherbzRomName, NULL, NULL, PunisherbzInputInfo, PunisherbzDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsQad = { + "qad", NULL, NULL, NULL, "1992", + "Quiz & Dragons (capcom quiz game 920701 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_QUIZ, 0, + NULL, QadRomInfo, QadRomName, NULL, NULL, QadInputInfo, QadDIPInfo, + QadInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsQadj = { + "qadj", "qad", NULL, NULL, "1992", + "Quiz & Dragons (940921 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_QUIZ, 0, + NULL, QadjRomInfo, QadjRomName, NULL, NULL, QadInputInfo, QadjDIPInfo, + QadInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsQtono2j = { + "qtono2j", NULL, NULL, NULL, "1995", + "Quiz Tonosama no Yabou 2 Zenkoku-ban (tonosama 2 950123 Japan)\0", NULL, "Capcom", "CPS1", + L"\u30AF\u30A4\u30BA\u6BBF\u69D8\u306E\u91CE\u671B\uFF12 (\u3068\u306E\u3055\u307E\u306E\u3084\u307C\u3046 2 950123 Japan)\0Quiz Tonosama no Yabou 2 Zenkoku-ban (tonosama 2 950123 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_QUIZ, 0, + NULL, Qtono2jRomInfo, Qtono2jRomName, NULL, NULL, Qtono2jInputInfo, Qtono2jDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2 = { + "sf2", NULL, NULL, NULL, "1991", + "Street Fighter II - the world warrior (910522 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2RomInfo, Sf2RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2eb = { + "sf2eb", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910214 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ebRomInfo, Sf2ebRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ee = { + "sf2ee", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910228 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2eeRomInfo, Sf2eeRomName, NULL, NULL, Sf2ueInputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ebbl = { + "sf2ebbl", "sf2", NULL, NULL, "1992", + "Street Fighter II - the world warrior (910214 etc, TAB Austria bootleg)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ebblRomInfo, Sf2ebblRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2ebblInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ua = { + "sf2ua", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910206 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2uaRomInfo, Sf2uaRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ub = { + "sf2ub", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910214 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ubRomInfo, Sf2ubRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2uc = { + "sf2uc", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910306 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ucRomInfo, Sf2ucRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ud = { + "sf2ud", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910318 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2udRomInfo, Sf2udRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ue = { + "sf2ue", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910228 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ueRomInfo, Sf2ueRomName, NULL, NULL, Sf2ueInputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2uf = { + "sf2uf", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910411 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ufRomInfo, Sf2ufRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ui = { + "sf2ui", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910522 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2uiRomInfo, Sf2uiRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2uk = { + "sf2uk", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (911101 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ukRomInfo, Sf2ukRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2j = { + "sf2j", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (911210 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2jRomInfo, Sf2jRomName, NULL, NULL, Sf2InputInfo, Sf2jDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ja = { + "sf2ja", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910214 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2jaRomInfo, Sf2jaRomName, NULL, NULL, Sf2InputInfo, Sf2jDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2jc = { + "sf2jc", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (910306 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2jcRomInfo, Sf2jcRomName, NULL, NULL, Sf2InputInfo, Sf2jDIPInfo, + Sf2jcInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2qp1 = { + "sf2qp1", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (bootleg, Quicken Pt-I)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2qp1RomInfo, Sf2qp1RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2qp1Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2thndr = { + "sf2thndr", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (bootleg, Thunder Edition)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2thndrRomInfo, Sf2thndrRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2thndrInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsSf2b = { + "sf2b", "sf2", NULL, NULL, "1991", + "Street Fighter II - the world warrior (bootleg)\0", "Resets itself", "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2bRomInfo, Sf2bRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ce = { + "sf2ce", NULL, NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920513 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceRomInfo, Sf2ceRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ceea = { + "sf2ceea", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920313 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceeaRomInfo, Sf2ceeaRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2cej = { + "sf2cej", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920513 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2cejRomInfo, Sf2cejRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ceua = { + "sf2ceua", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920313 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceuaRomInfo, Sf2ceuaRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ceub = { + "sf2ceub", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920513 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceubRomInfo, Sf2ceubRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ceuc = { + "sf2ceuc", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920803 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceucRomInfo, Sf2ceucRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2ceud = { + "sf2ceud", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (street fighter 2' 920803 USA, alt)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ceudRomInfo, Sf2ceudRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2acc = { + "sf2acc", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Accelerator!)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2accRomInfo, Sf2accRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2acc2 = { + "sf2acc2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Accelerator! alternate set)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2acc2RomInfo, Sf2acc2RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2accp2 = { + "sf2accp2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Accelerator Pt.II)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2accp2RomInfo, Sf2accp2RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2accp2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2dkot2 = { + "sf2dkot2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Double K.O. Turbo II)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2dkot2RomInfo, Sf2dkot2RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2dkot2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2rb = { + "sf2rb", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Rainbow set 1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2rbRomInfo, Sf2rbRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2rbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2rb2 = { + "sf2rb2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Rainbow set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2rb2RomInfo, Sf2rb2RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2rb2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2rb3 = { + "sf2rb3", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Rainbow set 3)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2rb3RomInfo, Sf2rb3RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2red = { + "sf2red", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Red Wave)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2redRomInfo, Sf2redRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2v004 = { + "sf2v004", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, V004)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2v004RomInfo, Sf2v004RomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2hf = { + "sf2hf", NULL, NULL, NULL, "1992", + "Street Fighter II' - hyper fighting (street fighter 2' T 921209 ETC)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2hfRomInfo, Sf2hfRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2hfu = { + "sf2hfu", "sf2hf", NULL, NULL, "1992", + "Street Fighter II' - hyper fighting (street fighter 2' T 921209 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2hfuRomInfo, Sf2hfuRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2hfj = { + "sf2hfj", "sf2hf", NULL, NULL, "1992", + "Street Fighter II' Turbo - hyper fighting (street fighter 2' T 921209 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2hfjRomInfo, Sf2hfjRomName, NULL, NULL, Sf2InputInfo, Sf2jDIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2yyc = { + "sf2yyc", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, YYC)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2yycRomInfo, Sf2yycRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2yycInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsKouryu = { + "sf2koryu", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (Chinese bootleg, Xiang Long)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, KouryuRomInfo, KouryuRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2koryuInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsSf2m1 = { + "sf2m1", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m1RomInfo, Sf2m1RomName, NULL, NULL, Sf2m1InputInfo, Sf2DIPInfo, + Sf2m1Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m2 = { + "sf2m2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m2RomInfo, Sf2m2RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m3 = { + "sf2m3", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M3)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m3RomInfo, Sf2m3RomName, NULL, NULL, Sf2m3InputInfo, Sf2DIPInfo, + Sf2m3Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m4 = { + "sf2m4", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M4)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m4RomInfo, Sf2m4RomName, NULL, NULL, Sf2yycInputInfo, Sf2jDIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m5 = { + "sf2m5", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M5)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m5RomInfo, Sf2m5RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m6 = { + "sf2m6", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M6)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG,2,HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m6RomInfo, Sf2m6RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m7 = { + "sf2m7", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M7)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m7RomInfo, Sf2m7RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m8 = { + "sf2m8", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M8)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m8RomInfo, Sf2m8RomName, NULL, NULL, Sf2m3InputInfo, Sf2DIPInfo, + Sf2m8Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m9 = { + "sf2m9", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M9)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m9RomInfo, Sf2m9RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m2Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m10 = { + "sf2m10", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M10)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m10RomInfo, Sf2m10RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m11 = { + "sf2m11", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M11)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m11RomInfo, Sf2m11RomName, NULL, NULL, Sf2yycInputInfo, Sf2jDIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m12 = { + "sf2m12", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M12)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m12RomInfo, Sf2m12RomName, NULL, NULL, Sf2yycInputInfo, Sf2jDIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2m13 = { + "sf2m13", "sf2hf", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, M13)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2m13RomInfo, Sf2m13RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m13Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2tlona = { + "sf2tlona", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Slay the Dragon set 1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2tlonaRomInfo, Sf2tlonaRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSf2tlonb = { + "sf2tlonb", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Slay the Dragon set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2tlonbRomInfo, Sf2tlonbRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsSf2th = { + "sf2th", "sf2hf", NULL, NULL, "1992", + "Street Fighter II' - (Turbo Hack)\0", "Resets itself", "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2thRomInfo, Sf2thRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2thInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzch = { + "sfzch", NULL, NULL, NULL, "1995", + "Street Fighter Zero (CPS Changer, 951020 Japan)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfzchRomInfo, SfzchRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfach = { + "sfach", "sfzch", NULL, NULL, "1995", + "Street Fighter Alpha (CPS Changer, 950727 Publicity US)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfachRomInfo, SfachRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzach = { + "sfzach", "sfzch", NULL, NULL, "1995", + "Street Fighter Zero (CPS Changer, 950925 Asia)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfzachRomInfo, SfzachRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzbch = { + "sfzbch", "sfzch", NULL, NULL, "1995", + "Street Fighter Zero (CPS Changer, 950727 Brazil)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfzbchRomInfo, SfzbchRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzech = { + "sfzech", "sfzch", NULL, NULL, "1995", + "Street Fighter Zero (CPS Changer, 950727 Euro)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfzechRomInfo, SfzechRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzhch = { + "sfzhch", "sfzch", NULL, NULL, "1995", + "Street Fighter Zero (CPS Changer, 950727 Hispanic)\0", NULL, "Capcom", "CPS Changer", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPSCHANGER, GBF_VSFIGHT, FBF_SF, + NULL, SfzhchRomInfo, SfzhchRomName, NULL, NULL, SfzchInputInfo, NULL, + SfzchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSlammast = { + "slammast", NULL, NULL, NULL, "1993", + "Saturday Night Slam Masters (Slam Masters 930713 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, SlammastRomInfo, SlammastRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSlammastu = { + "slammastu", "slammast", NULL, NULL, "1993", + "Saturday Night Slam Masters (slam masters 930713 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, SlammastuRomInfo, SlammastuRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMbomberj = { + "mbomberj", "slammast", NULL, NULL, "1993", + "Muscle Bomber - the body explosion (930713 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbomberjRomInfo, MbomberjRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMbombrd = { + "mbombrd", NULL, NULL, NULL, "1993", + "Muscle Bomber Duo - ultimate team battle (931206 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombrdRomInfo, MbombrdRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMbombrdj = { + "mbombrdj", "mbombrd", NULL, NULL, "1993", + "Muscle Bomber Duo - heat up warriors (931206 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombrdjRomInfo, MbombrdjRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsStrider = { + "strider", NULL, NULL, NULL, "1989", + "Strider (US set 1)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, StriderRomInfo, StriderRomName, NULL, NULL, StriderInputInfo, StriderDIPInfo, + StriderInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsStriderua = { + "striderua", "strider", NULL, NULL, "1989", + "Strider (US set 2)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE,2,HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, StrideruaRomInfo, StrideruaRomName, NULL, NULL, StriderInputInfo, StrideruaDIPInfo, + StriderInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsStriderjr = { + "striderjr", "strider", NULL, NULL, "1989", + "Strider Hiryu (Japan Resale Ver.)\0", NULL, "Capcom", "CPS1", + L"\u30B9\u30C8\u30E9\u30A4\u30C0\u30FC\u98DB\u7ADC (Japan Resale Ver.)\0Strider Hiryu (Japan Resale Ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, StriderjrRomInfo, StriderjrRomName, NULL, NULL, StriderInputInfo, StriderDIPInfo, + StriderjrInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsStriderj = { + "striderj", "strider", NULL, NULL, "1989", + "Strider Hiryu (Japan)\0", NULL, "Capcom", "CPS1", + L"\u30B9\u30C8\u30E9\u30A4\u30C0\u30FC\u98DB\u7ADC (Japan)\0Strider Hiryu (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, StriderjRomInfo, StriderjRomName, NULL, NULL, StriderInputInfo, StriderDIPInfo, + StriderjInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsUnsquad = { + "unsquad", NULL, NULL, NULL, "1989", + "U.N. Squadron (US)\0", NULL, "Daipro / Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, UnsquadRomInfo, UnsquadRomName, NULL, NULL, UnsquadInputInfo, UnsquadDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArea88 = { + "area88", "unsquad", NULL, NULL, "1989", + "Area 88 (Japan)\0", NULL, "Daipro / Capcom", "CPS1", + L"\u30A8\u30EA\u30A2\uFF18\uFF18 (Japan)\0Area 88 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, Area88RomInfo, Area88RomName, NULL, NULL, UnsquadInputInfo, UnsquadDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArea88r = { + "area88r", "unsquad", NULL, NULL, "1989", + "Area 88 (Japan Resale ver.)\0", NULL, "Daipro / Capcom", "CPS1", + L"\u30A8\u30EA\u30A2\uFF18\uFF18 (Japan Resale ver.)\0Area 88 (Japan Resale ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_HORSHOOT, 0, + NULL, Area88rRomInfo, Area88rRomName, NULL, NULL, UnsquadInputInfo, UnsquadDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVarth = { + "varth", NULL, NULL, NULL, "1992", + "Varth - operation thunderstorm (920714 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, VarthRomInfo, VarthRomName, NULL, NULL, VarthInputInfo, VarthDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsVarthr1 = { + "varthr1", "varth", NULL, NULL, "1992", + "Varth - operation thunderstorm (920612 etc)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, Varthr1RomInfo, Varthr1RomName, NULL, NULL, VarthInputInfo, VarthDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsVarthj = { + "varthj", "varth", NULL, NULL, "1992", + "Varth - operation thunderstorm (920714 Japan)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2 ,HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, VarthjRomInfo, VarthjRomName, NULL, NULL, VarthInputInfo, VarthDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsVarthu = { + "varthu", "varth", NULL, NULL, "1992", + "Varth - operation thunderstorm (920612 USA)\0", NULL, "Capcom (Romstar license)", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS1, GBF_VERSHOOT, 0, + NULL, VarthuRomInfo, VarthuRomName, NULL, NULL, VarthInputInfo, VarthDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsWillow = { + "willow", NULL, NULL, NULL, "1989", + "Willow (US)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, WillowRomInfo, WillowRomName, NULL, NULL, WillowInputInfo, WillowDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWillowo = { + "willowo", "willow", NULL, NULL, "1989", + "Willow (US old ver.)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, WillowoRomInfo, WillowoRomName, NULL, NULL, WillowInputInfo, WillowDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWillowj = { + "willowj", "willow", NULL, NULL, "1989", + "Willow (Japan, Japanese)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM, 0, + NULL, WillowjRomInfo, WillowjRomName, NULL, NULL, WillowInputInfo, WillowDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWof = { + "wof", NULL, NULL, NULL, "1992", + "Warriors of Fate (921002 etc)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofRomInfo, WofRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofa = { + "wofa", "wof", NULL, NULL, "1992", + "Sangokushi II (921005 Asia)\0", NULL, "Capcom", "CPS1 / QSound", + L"\u4E09\u56FD\u5FD7II (Sangokushi 2 921005 Asia)\0Sangokushi II (921005 Asia)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofaRomInfo, WofaRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofu = { + "wofu", "wof", NULL, NULL, "1992", + "Warriors of Fate (921031 USA)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofuRomInfo, WofuRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofj = { + "wofj", "wof", NULL, NULL, "1992", + "Tenchi wo Kurau II - Sekiheki no Tatakai (921031 Japan)\0", NULL, "Capcom", "CPS1 / QSound", + L"\u8EE2\u5730\u3092\u55B0\u3089\u3046II - \u8D64\u58C1\u306E\u6226\u3044 (Tenchi wo Kurau 2 921031 Japan)\0Tenchi wo Kurau II - Sekiheki no Tatakai (921031 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofjRomInfo, WofjRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofhfh = { + "wofhfh", "wof", NULL, NULL, "1992", + "Sangokushi II: Huo Fenghuang (Chinese bootleg)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, WofhfhRomInfo, WofhfhRomName, NULL, NULL, WofhfhInputInfo, WofhfhDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofah = { + "wofah", "wof", NULL, NULL, "1992", + "Sangokushi II (921005 Asia, bootleg set 2)\0", NULL, "bootleg", "CPS1 / QSound", + L"\u4E09\u56FD\u5FD7II (Sangokushi 2 921005 Asia bootleg set 2)\0Sangokushi II (921005 Asia bootleg set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofahRomInfo, WofahRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofb = { + "wofb", "wof", NULL, NULL, "1992", + "Warriors of Fate (bootleg)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofbRomInfo, WofbRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + WofbInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofch = { + "wofch", "wof", NULL, NULL, "1992", + "Tenchi wo Kurau II - Sekiheki no Tatakai (CPS Changer, 921031 Japan)\0", NULL, "Capcom", "CPS Changer", + L"\u8EE2\u5730\u3092\u55B0\u3089\u3046II - \u8D64\u58C1\u306E\u6226\u3044 (CPS Changer, 921031 Japan)\0Tenchi wo Kurau II - Sekiheki no Tatakai (CPS Changer, 921031 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPSCHANGER, GBF_SCRFIGHT, 0, + NULL, WofchRomInfo, WofchRomName, NULL, NULL, WofchInputInfo, NULL, + WofchInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWof3js = { + "wof3js", "wof", NULL, NULL, "1992", + "Sangokushi II: San Jian Sheng (Chinese bootleg)\0", NULL, "bootleg", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0, + NULL, Wof3jsRomInfo, Wof3jsRomName, NULL, NULL, WofhfhInputInfo, WofhfhDIPInfo, + Wof3jsInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWof3sj = { + "wof3sj", "wof", NULL, NULL, "1992", + "Sangokushi II: San Sheng Jian (Chinese bootleg set 1)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, Wof3sjRomInfo, Wof3sjRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + Wof3sjInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWof3sja = { + "wof3sja", "wof", NULL, NULL, "1992", + "Sangokushi II: San Sheng Jian (Chinese bootleg set 2)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, Wof3sjaRomInfo, Wof3sjaRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + Wof3sjaInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofaha = { + "wofaha", "wof", NULL, NULL, "1992", + "Sangokushi II (921005 Asia, bootleg)\0", NULL, "bootleg", "CPS1 / QSound", + L"\u4E09\u56FD\u5FD7II (Sangokushi 2 921005 Asia bootleg)\0Sangokushi II (921005 Asia bootleg)\0", NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofahaRomInfo, WofahaRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofh = { + "wofh", "wof", NULL, NULL, "1992", + "Sangokushi II: Sanguo Yingxiong Zhuan (Chinese bootleg set 1)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofhRomInfo, WofhRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + WofhInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofha = { + "wofha", "wof", NULL, NULL, "1992", + "Sangokushi II: Sanguo Yingxiong Zhuan (Chinese bootleg set 2)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofhaRomInfo, WofhaRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + WofhaInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsWofjh = { + "wofjh", "wof", NULL, NULL, "1992", + "Tenchi wo Kurau II - Sekiheki no Tatakai (921031 Japan bootleg)\0", NULL, "bootleg", "CPS1 / QSound", + L"\u8EE2\u5730\u3092\u55B0\u3089\u3046II - \u8D64\u58C1\u306E\u6226\u3044 (Tenchi wo Kurau 2 921031 Japan bootleg)\0Tenchi wo Kurau II - Sekiheki no Tatakai (921031 Japan bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofjhRomInfo, WofjhRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofsj = { + "wofsj", "wof", NULL, NULL, "1992", + "Sangokushi II: Sheng Jian Sanguo (Chinese bootleg set 1)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofsjRomInfo, WofsjRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofsja = { + "wofsja", "wof", NULL, NULL, "1992", + "Sangokushi II: Sheng Jian Sanguo (Chinese bootleg set 2)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofsjaRomInfo, WofsjaRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvCpsWofsjb = { + "wofsjb", "wof", NULL, NULL, "1992", + "Sangokushi II: Sheng Jian Sanguo (Chinese bootleg set 3)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WofsjbRomInfo, WofsjbRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCps1frog = { + "cps1frog", NULL, NULL, NULL, "2006", + "Frog Feast (CPS-1)\0", NULL, "Rastersoft (Homebrew)", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_CAPCOM_CPS1, GBF_MISC, 0, + NULL, Cps1frogRomInfo, Cps1frogRomName, NULL, NULL, FfightInputInfo, FfightDIPInfo, + DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Not included games + +// Pnickies (USA) +// Seems like a region hack +static struct BurnRomInfo PnickuRomDesc[] = { + { "pnij36.bin", 0x020000, 0x2d4ffb2b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "pniu42.bin", 0x020000, 0x22d20227, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "pnij09.bin", 0x020000, 0x48177b0a, BRF_GRA | CPS1_TILES }, + { "pnij01.bin", 0x020000, 0x01a0f311, BRF_GRA | CPS1_TILES }, + { "pnij13.bin", 0x020000, 0x406451b0, BRF_GRA | CPS1_TILES }, + { "pnij05.bin", 0x020000, 0x8c515dc0, BRF_GRA | CPS1_TILES }, + { "pnij26.bin", 0x020000, 0xe2af981e, BRF_GRA | CPS1_TILES }, + { "pnij18.bin", 0x020000, 0xf17a0e56, BRF_GRA | CPS1_TILES }, + { "pnij38.bin", 0x020000, 0xeb75bd8c, BRF_GRA | CPS1_TILES }, + { "pnij32.bin", 0x020000, 0x84560bef, BRF_GRA | CPS1_TILES }, + { "pnij10.bin", 0x020000, 0xc2acc171, BRF_GRA | CPS1_TILES }, + { "pnij02.bin", 0x020000, 0x0e21fc33, BRF_GRA | CPS1_TILES }, + { "pnij14.bin", 0x020000, 0x7fe59b19, BRF_GRA | CPS1_TILES }, + { "pnij06.bin", 0x020000, 0x79f4bfe3, BRF_GRA | CPS1_TILES }, + { "pnij27.bin", 0x020000, 0x83d5cb0e, BRF_GRA | CPS1_TILES }, + { "pnij19.bin", 0x020000, 0xaf08b230, BRF_GRA | CPS1_TILES }, + { "pnij39.bin", 0x020000, 0x70fbe579, BRF_GRA | CPS1_TILES }, + { "pnij33.bin", 0x020000, 0x3ed2c680, BRF_GRA | CPS1_TILES }, + + { "pnij17.bin", 0x010000, 0xe86f787a, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "pnij24.bin", 0x020000, 0x5092257d, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "pnij25.bin", 0x020000, 0x22109aaa, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Pnicku) +STD_ROM_FN(Pnicku) + +struct BurnDriverX BurnDrvCpsPnicku = { + "pnicku", "pnickj", NULL, NULL, "1994", + "Pnickies (940608 USA)\0", NULL, "Compile (Capcom license)", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_PUZZLE, 0, + NULL, PnickuRomInfo, PnickuRomName, NULL, NULL, PnickjInputInfo, PnickjDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Saturday Night Slam Masters (Asia) +// Seems to be just a region hack + +static struct BurnRomInfo SlammasaRomDesc[] = { + { "mba_23e.rom", 0x080000, 0x027e49db, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_24b.rom", 0x020000, 0x95d5e729, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_28b.rom", 0x020000, 0xb1c7cbcb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_25b.rom", 0x020000, 0xa50d3fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_29b.rom", 0x020000, 0x08e32e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_21a.rom", 0x080000, 0xd5007b05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_20a.rom", 0x080000, 0xaeb557b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_qa.rom", 0x020000, 0xe21a03c4, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Slammasa) +STD_ROM_FN(Slammasa) + +struct BurnDriverX BurnDrvCpsSlammasa = { + "slammasa", "slammast", NULL, NULL, "1993", + "Saturday Night Slam Masters (Slam Masters 930301 Asia)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, SlammasaRomInfo, SlammasaRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Saturday Night Slam Masters (Hispanic) +// Seems to be just a region hack +static struct BurnRomInfo SlammashRomDesc[] = { + { "mbh_23e.rom", 0x080000, 0xb0220f4a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_24b.rom", 0x020000, 0x95d5e729, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_28b.rom", 0x020000, 0xb1c7cbcb, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_25b.rom", 0x020000, 0xa50d3fd4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_29b.rom", 0x020000, 0x08e32e56, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbe_21a.rom", 0x080000, 0xd5007b05, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbe_20a.rom", 0x080000, 0xaeb557b0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_qa.rom", 0x020000, 0xe21a03c4, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Slammash) +STD_ROM_FN(Slammash) + +struct BurnDriverX BurnDrvCpsSlammash = { + "slammash", "slammast", NULL, NULL, "1993", + "Saturday Night Slam Masters (Slam Masters 930713 Hispanic)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, SlammashRomInfo, SlammashRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Muscle Bomber Duo (Japan E) +// Seems to be just a region hack +static struct BurnRomInfo MbombdjeRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbdje_30.rom", 0x020000, 0x61b09fb1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Mbombdje) +STD_ROM_FN(Mbombdje) + +struct BurnDriverX BurnDrvCpsMbombdje = { + "mbombdje", "mbombrd", NULL, NULL, "1993", + "Muscle Bomber Duo - heat up warriors (931206 Japan E)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombdjeRomInfo, MbombdjeRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Muscle Bomber Duo (Asia) +// Seems to be just a region hack +static struct BurnRomInfo MbombrdaRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbda_30.rom", 0x020000, 0x42eaa9da, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Mbombrda) +STD_ROM_FN(Mbombrda) + +struct BurnDriverX BurnDrvCpsMbombrda = { + "mbombrda", "mbombrd", NULL, NULL, "1993", + "Muscle Bomber Duo - ultimate team battle (931206 Asia)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombrdaRomInfo, MbombrdaRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Muscle Bomber Duo (Hispanic) +// Seems to be just a region hack +static struct BurnRomInfo MbombrdhRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbdh_30.rom", 0x020000, 0x836cea7d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Mbombrdh) +STD_ROM_FN(Mbombrdh) + +struct BurnDriverX BurnDrvCpsMbombrdh = { + "mbombrdh", "mbombrd", NULL, NULL, "1993", + "Muscle Bomber Duo - ultimate team battle (931206 Hispanic)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombrdhRomInfo, MbombrdhRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Muscle Bomber Duo (USA) +// Seems to be just a region hack +static struct BurnRomInfo MbombrduRomDesc[] = { + { "mbd_26.bin", 0x020000, 0x72b7451c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbdu_30.rom", 0x020000, 0x5c234403, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_27.bin", 0x020000, 0x4086f534, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_31.bin", 0x020000, 0x085f47f0, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_24.bin", 0x020000, 0xc20895a5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_28.bin", 0x020000, 0x2618d5e1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_25.bin", 0x020000, 0x9bdb6b11, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_29.bin", 0x020000, 0x3f52d5e5, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "mbd_21.bin", 0x080000, 0x690c026a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "mbd_20.bin", 0x080000, 0xb8b2139b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "mb_gfx01.rom", 0x080000, 0x41468e06, BRF_GRA | CPS1_TILES }, + { "mb_gfx03.rom", 0x080000, 0xf453aa9e, BRF_GRA | CPS1_TILES }, + { "mb_gfx02.rom", 0x080000, 0x2ffbfea8, BRF_GRA | CPS1_TILES }, + { "mb_gfx04.rom", 0x080000, 0x1eb9841d, BRF_GRA | CPS1_TILES }, + { "mb_05.bin", 0x080000, 0x506b9dc9, BRF_GRA | CPS1_TILES }, + { "mb_07.bin", 0x080000, 0xaff8c2fb, BRF_GRA | CPS1_TILES }, + { "mb_06.bin", 0x080000, 0xb76c70e9, BRF_GRA | CPS1_TILES }, + { "mb_08.bin", 0x080000, 0xe60c9556, BRF_GRA | CPS1_TILES }, + { "mb_10.bin", 0x080000, 0x97976ff5, BRF_GRA | CPS1_TILES }, + { "mb_12.bin", 0x080000, 0xb350a840, BRF_GRA | CPS1_TILES }, + { "mb_11.bin", 0x080000, 0x8fb94743, BRF_GRA | CPS1_TILES }, + { "mb_13.bin", 0x080000, 0xda810d5f, BRF_GRA | CPS1_TILES }, + + { "mb_q.bin", 0x020000, 0xd6fa76d1, BRF_ESS | BRF_PRG | CPS1_Z80_PROGRAM }, + + { "mb_q1.bin", 0x080000, 0x0630c3ce, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q2.bin", 0x080000, 0x354f9c21, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q3.bin", 0x080000, 0x7838487c, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q4.bin", 0x080000, 0xab66e087, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q5.bin", 0x080000, 0xc789fef2, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q6.bin", 0x080000, 0xecb81b61, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q7.bin", 0x080000, 0x041e49ba, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "mb_q8.bin", 0x080000, 0x59fe702a, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Mbombrdu) +STD_ROM_FN(Mbombrdu) + +struct BurnDriverX BurnDrvCpsMbombrdu = { + "mbombrdu", "mbombrd", NULL, NULL, "1993", + "Muscle Bomber Duo - ultimate team battle (931206 USA)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 4, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, 0, + NULL, MbombrduRomInfo, MbombrduRomName, NULL, NULL, SlammastInputInfo, SlammastDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +static struct BurnRomInfo Sf2cebrRomDesc[] = { + { "sf2cebr.23", 0x080000, 0x74e848ee, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2cebr.22", 0x080000, 0xc3c49626, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.bin", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92br_10.bin", 0x080000, 0xb3e1dd5f, BRF_GRA | CPS1_TILES }, + { "s92br_11.bin", 0x080000, 0xf13af812, BRF_GRA | CPS1_TILES }, + { "s92br_12.bin", 0x080000, 0x10ce42af, BRF_GRA | CPS1_TILES }, + { "s92br_13.bin", 0x080000, 0x32cf5af3, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2cebr) +STD_ROM_FN(Sf2cebr) + +struct BurnDriverX BurnDrvCpsSf2cebr = { + "sf2cebr", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Brazil)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2cebrRomInfo, Sf2cebrRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +static struct BurnRomInfo Sf2cehRomDesc[] = { + { "sf2ceh.23", 0x080000, 0x25dc14c8, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "sf2ceh.22", 0x080000, 0x1c9dd91c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "s92_21a.bin", 0x080000, 0x925a7877, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2ceh) +STD_ROM_FN(Sf2ceh) + +struct BurnDriverX BurnDrvCpsSf2ceh = { + "sf2ceh", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (bootleg, Hispanic)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2cehRomInfo, Sf2cehRomName, NULL, NULL, Sf2InputInfo, Sf2DIPInfo, + Sf2ceInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Warriors of Fate (French Translation) +// Very similar to wof +static struct BurnRomInfo WoffrRomDesc[] = { + { "tk2e_23bfr.rom",0x080000, 0xe006e81e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "tk2e_22b.rom", 0x080000, 0x479b3f24, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "tk2_gfx1.rom", 0x080000, 0x0d9cb9bf, BRF_GRA | CPS1_TILES }, + { "tk2_gfx3.rom", 0x080000, 0x45227027, BRF_GRA | CPS1_TILES }, + { "tk2_gfx2.rom", 0x080000, 0xc5ca2460, BRF_GRA | CPS1_TILES }, + { "tk2_gfx4.rom", 0x080000, 0xe349551c, BRF_GRA | CPS1_TILES }, + { "tk2_gfx5fr.rom",0x080000, 0x1b6bc2b2, BRF_GRA | CPS1_TILES }, + { "tk2_gfx7fr.rom",0x080000, 0x3f1e5334, BRF_GRA | CPS1_TILES }, + { "tk2_gfx6fr.rom",0x080000, 0x28c9d96f, BRF_GRA | CPS1_TILES }, + { "tk2_gfx8fr.rom",0x080000, 0xb3b9a29e, BRF_GRA | CPS1_TILES }, + + { "tk2_qa.rom", 0x020000, 0xc9183a0d, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "tk2_q1.rom", 0x080000, 0x611268cf, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q2.rom", 0x080000, 0x20f55ca9, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q3.rom", 0x080000, 0xbfcf6f52, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "tk2_q4.rom", 0x080000, 0x36642e88, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Woffr) +STD_ROM_FN(Woffr) + +struct BurnDriverX BurnDrvCpsWoffr = { + "woffr", "wof", NULL, NULL, "1992", + "Warriors of Fate (French Translation)\0", NULL, "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, WoffrRomInfo, WoffrRomName, NULL, NULL, WofInputInfo, WofDIPInfo, + TwelveMhzInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +#if defined INCLUDE_DUPLICATES + +// Cadillacs and Dinosaurs (bootleg) +// this is the same as dinopic (once the pic program is added) +static struct BurnRomInfo DinobRomDesc[] = { + { "5.bin", 0x080000, 0x96dfcbf1, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "3.bin", 0x080000, 0x13dfeb08, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "7.bin", 0x080000, 0x6133f349, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "2.bin", 0x080000, 0x0e4058ba, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "4.bin", 0x080000, 0xf3c2c98d, BRF_GRA | CPS1_TILES }, + { "8.bin", 0x080000, 0xd574befc, BRF_GRA | CPS1_TILES }, + { "9.bin", 0x080000, 0x55ef0adc, BRF_GRA | CPS1_TILES }, + { "6.bin", 0x080000, 0xcc0805fc, BRF_GRA | CPS1_TILES }, + { "13.bin", 0x080000, 0x1371f714, BRF_GRA | CPS1_TILES }, + { "12.bin", 0x080000, 0xb284c4a7, BRF_GRA | CPS1_TILES }, + { "11.bin", 0x080000, 0xb7ad3394, BRF_GRA | CPS1_TILES }, + { "10.bin", 0x080000, 0x88847705, BRF_GRA | CPS1_TILES }, + + { "pic16c57-rp", 0x002d4c, 0x5a6d393c, BRF_PRG | CPS1_PIC }, + + { "1.bin", 0x080000, 0x7d921309, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Dinob) +STD_ROM_FN(Dinob) + +struct BurnDriverX BurnDrvCpsDinob = { + "dinob", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs (identical to dinopic)\0", "Missing sprites, no sound", "Capcom", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, DinobRomInfo, DinobRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinopicInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Cadillacs and Dinosaurs Turbo (Asia Bootleg) +// this is the same as dinoha +static struct BurnRomInfo Kl2dRomDesc[] = { + { "kl2-r1.800", 0x100000, 0x4c70dca7, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + { "kl2-l2.800", 0x100000, 0xc6ae7338, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP }, + + { "cd-a.160", 0x200000, 0x7e4f9fb3, BRF_GRA | CPS1_TILES }, + { "cd-b.160", 0x200000, 0x89532d85, BRF_GRA | CPS1_TILES }, + + { "cd_q.rom", 0x020000, 0x605fdb0b, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "cd_q1.rom", 0x080000, 0x60927775, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q2.rom", 0x080000, 0x770f4c47, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q3.rom", 0x080000, 0x2f273ffc, BRF_SND | CPS1_QSOUND_SAMPLES }, + { "cd_q4.rom", 0x080000, 0x2c67821d, BRF_SND | CPS1_QSOUND_SAMPLES }, +}; + +STD_ROM_PICK(Kl2d) +STD_ROM_FN(Kl2d) + +struct BurnDriverX BurnDrvCpsKl2d = { + "kl2d", "dino", NULL, NULL, "1993", + "Cadillacs and Dinosaurs Turbo (identical to dinoha)\0", NULL, "bootleg", "CPS1 / QSound", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS1_QSOUND, GBF_SCRFIGHT, 0, + NULL, Kl2dRomInfo, Kl2dRomName, NULL, NULL, DinoInputInfo, DinoDIPInfo, + DinohaInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Street Fighter 2 Champion Edition (bootleg, Slay the Dragon) +// this is the same as sf2tlona +static struct BurnRomInfo Sf2tloncRomDesc[] = { + { "u222-f83.040", 0x100000, 0x47468198, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + { "u196-99d.040", 0x100000, 0x47d34191, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + { "u221-59e.010", 0x040000, 0x5507bac9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + { "u195-472.010", 0x040000, 0x7755a20a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2tlonc) +STD_ROM_FN(Sf2tlonc) + +static INT32 Sf2tloncInit() +{ + INT32 nRet = 0; + + nRet = Sf2m4Init(); + + memcpy(CpsRom + 0x100000, CpsRom + 0x200000, 0x80000); + + return nRet; +} + +struct BurnDriverX BurnDrvCpsSf2tlonc = { + "sf2tlonc", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (identical to sf2tlona)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2tloncRomInfo, Sf2tloncRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2tloncInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Street Fighter 2 Champion Edition (bootleg, turyu) +// this is the same as sf2tlona +static struct BurnRomInfo Sf2turyuRomDesc[] = { + {"u222-f83.040", 0x0100000, 0x47468198, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + {"u196-99d.040", 0x0100000, 0x47d34191, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + {"u221-59e.010", 0x0040000, 0x5507bac9, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + {"u195-472.010", 0x0040000, 0x7755a20a, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, // first and second halves are identical + + { "s92_01.bin", 0x0080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x0080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x0080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x0080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x0080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x0080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x0080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x0080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x0080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x0080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x0080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x0080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2turyu) +STD_ROM_FN(Sf2turyu) + +struct BurnDriverX BurnDrvCpsSf2turyu = { + "sf2turyu", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (identical to sf2tlona)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2turyuRomInfo, Sf2turyuRomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2tloncInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Street Fighter 2 Champion Edition (bootleg, turyu set 2) +// this is the same as sf2tlonb +static struct BurnRomInfo Sf2tury2RomDesc[] = { + { "tl4m.1", 0x080000, 0xafc7bd18, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "tl4m.2", 0x080000, 0x882cd1c4, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u221.1m", 0x020000, 0xd1707134, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "u195.1m", 0x020000, 0xcd1d5666, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s92_10.bin", 0x080000, 0x960687d5, BRF_GRA | CPS1_TILES }, + { "s92_11.bin", 0x080000, 0x978ecd18, BRF_GRA | CPS1_TILES }, + { "s92_12.bin", 0x080000, 0xd6ec9a0a, BRF_GRA | CPS1_TILES }, + { "s92_13.bin", 0x080000, 0xed2c67f6, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2tury2) +STD_ROM_FN(Sf2tury2) + +struct BurnDriverX BurnDrvCpsSf2tury2 = { + "sf2tury2", "sf2ce", NULL, NULL, "1992", + "Street Fighter II' - champion edition (identical to sf2tlonb)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2tury2RomInfo, Sf2tury2RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m4Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Street Fighter 2 Champion Edition (bootleg, ce13) +// same as sf2m13 +static struct BurnRomInfo Sf2ce13RomDesc[] = { + { "222-040.13", 0x0080000, 0xec6f5cb3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "196-040.13", 0x0080000, 0x0e9ac52b, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "221-010.13", 0x0020000, 0x8226c11c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + { "195-010.13", 0x0020000, 0x924c6ce2, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP }, + + { "s92_01.bin", 0x080000, 0x03b0d852, BRF_GRA | CPS1_TILES }, + { "s92_02.bin", 0x080000, 0x840289ec, BRF_GRA | CPS1_TILES }, + { "s92_03.bin", 0x080000, 0xcdb5f027, BRF_GRA | CPS1_TILES }, + { "s92_04.bin", 0x080000, 0xe2799472, BRF_GRA | CPS1_TILES }, + { "s92_05.bin", 0x080000, 0xba8a2761, BRF_GRA | CPS1_TILES }, + { "s92_06.bin", 0x080000, 0xe584bfb5, BRF_GRA | CPS1_TILES }, + { "s92_07.bin", 0x080000, 0x21e3f87d, BRF_GRA | CPS1_TILES }, + { "s92_08.bin", 0x080000, 0xbefc47df, BRF_GRA | CPS1_TILES }, + { "s2t_10.bin", 0x080000, 0x3c042686, BRF_GRA | CPS1_TILES }, + { "s2t_11.bin", 0x080000, 0x8b7e7183, BRF_GRA | CPS1_TILES }, + { "s2t_12.bin", 0x080000, 0x293c888c, BRF_GRA | CPS1_TILES }, + { "s2t_13.bin", 0x080000, 0x842b35a4, BRF_GRA | CPS1_TILES }, + + { "s92_09.bin", 0x0010000, 0x08f6b60e, BRF_PRG | CPS1_Z80_PROGRAM }, + + { "s92_18.bin", 0x0020000, 0x7f162009, BRF_SND | CPS1_OKIM6295_SAMPLES }, + { "s92_19.bin", 0x0020000, 0xbeade53f, BRF_SND | CPS1_OKIM6295_SAMPLES }, +}; + +STD_ROM_PICK(Sf2ce13) +STD_ROM_FN(Sf2ce13) + +struct BurnDriverX BurnDrvCpsSf2ce13 = { + "sf2ce13", "sf2hf", NULL, NULL, "1992", + "Street Fighter II' - champion edition (identical to sf2m13)\0", NULL, "Capcom", "CPS1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS1, GBF_VSFIGHT, FBF_SF, + NULL, Sf2ce13RomInfo, Sf2ce13RomName, NULL, NULL, Sf2yycInputInfo, Sf2DIPInfo, + Sf2m13Init, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +#endif + +#if defined INCLUDE_CPS1_PHOENIX + +#endif + +#undef INCLUDE_DUPLICATES +#undef INCLUDE_CPS1_PHOENIX + +#undef CPS1_68K_PROGRAM_BYTESWAP +#undef CPS1_68K_PROGRAM_NO_BYTESWAP +#undef CPS1_Z80_PROGRAM +#undef CPS1_TILES +#undef CPS1_OKIM6295_SAMPLES +#undef CPS1_QSOUND_SAMPLES +#undef CPS1_PIC diff --git a/src/burn/drivers/capcom/d_cps2.cpp b/src/burn/drivers/capcom/d_cps2.cpp new file mode 100644 index 00000000..fe22454b --- /dev/null +++ b/src/burn/drivers/capcom/d_cps2.cpp @@ -0,0 +1,10924 @@ +#include "cps.h" + +// Input Definitions + +static struct BurnInputInfo Cps2FightingInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weak Kick" , BIT_DIGITAL , CpsInp011+0, "p1 fire 4" }, + {"P1 Medium Kick" , BIT_DIGITAL , CpsInp011+1, "p1 fire 5" }, + {"P1 Strong Kick" , BIT_DIGITAL , CpsInp011+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weak Kick" , BIT_DIGITAL , CpsInp011+4, "p2 fire 4" }, + {"P2 Medium Kick" , BIT_DIGITAL , CpsInp011+5, "p2 fire 5" }, + {"P2 Strong Kick" , BIT_DIGITAL , CpsInp020+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Cps2Fighting) + +static struct BurnInputInfo NineXXInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(NineXX) + +static struct BurnInputInfo Nine44InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Nine44) + +static struct BurnInputInfo ArmwarInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp020+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp020+2, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp011+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp011+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp011+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp011+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp011+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp011+5, "p3 fire 2" }, + {"P3 Shot" , BIT_DIGITAL , CpsInp011+6, "p3 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Armwar) + +static struct BurnInputInfo AvspInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp020+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp020+2, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp011+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp011+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp011+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp011+0, "p3 right" }, + {"P3 Shot" , BIT_DIGITAL , CpsInp011+4, "p3 fire 1" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp011+5, "p3 fire 2" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp011+6, "p3 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Avsp) + +static struct BurnInputInfo BatcirInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp020+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp020+2, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp011+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp011+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp011+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp011+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp011+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp011+5, "p3 fire 2" }, + + {"P4 Coin" , BIT_DIGITAL , CpsInp020+7, "p4 coin" }, + {"P4 Start" , BIT_DIGITAL , CpsInp020+3, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , CpsInp010+3, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , CpsInp010+2, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , CpsInp010+1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , CpsInp010+0, "p4 right" }, + {"P4 Attack" , BIT_DIGITAL , CpsInp010+4, "p4 fire 1" }, + {"P4 Jump" , BIT_DIGITAL , CpsInp010+5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Batcir) + +static struct BurnInputInfo ChokoInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Shot2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Shot3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Choko) + +static struct BurnInputInfo CsclubInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Button 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Button 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Button 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Csclub) + +static struct BurnInputInfo CybotsInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Low Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 High Attack" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Boost" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Weapon" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Low Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 High Attack" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Boost" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Weapon" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Cybots) + +static struct BurnInputInfo DdsomInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Select" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Use" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Select" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Use" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp020+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp020+2, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp011+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp011+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp011+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp011+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp011+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp011+5, "p3 fire 2" }, + {"P3 Select" , BIT_DIGITAL , CpsInp011+6, "p3 fire 3" }, + {"P3 Use" , BIT_DIGITAL , CpsInp011+7, "p3 fire 4" }, + + {"P4 Coin" , BIT_DIGITAL , CpsInp020+7, "p4 coin" }, + {"P4 Start" , BIT_DIGITAL , CpsInp020+3, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , CpsInp010+3, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , CpsInp010+2, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , CpsInp010+1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , CpsInp010+0, "p4 right" }, + {"P4 Attack" , BIT_DIGITAL , CpsInp010+4, "p4 fire 1" }, + {"P4 Jump" , BIT_DIGITAL , CpsInp010+5, "p4 fire 2" }, + {"P4 Select" , BIT_DIGITAL , CpsInp010+6, "p4 fire 3" }, + {"P4 Use" , BIT_DIGITAL , CpsInp010+7, "p4 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Ddsom) + +static struct BurnInputInfo DdtodInputList[] = +{ + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Use" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Select" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Use" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Select" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"P3 Coin" , BIT_DIGITAL , CpsInp020+6, "p3 coin" }, + {"P3 Start" , BIT_DIGITAL , CpsInp020+2, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , CpsInp011+3, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , CpsInp011+2, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , CpsInp011+1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , CpsInp011+0, "p3 right" }, + {"P3 Attack" , BIT_DIGITAL , CpsInp011+4, "p3 fire 1" }, + {"P3 Jump" , BIT_DIGITAL , CpsInp011+5, "p3 fire 2" }, + {"P3 Use" , BIT_DIGITAL , CpsInp011+6, "p3 fire 3" }, + {"P3 Select" , BIT_DIGITAL , CpsInp011+7, "p3 fire 4" }, + + {"P4 Coin" , BIT_DIGITAL , CpsInp020+7, "p4 coin" }, + {"P4 Start" , BIT_DIGITAL , CpsInp020+3, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , CpsInp010+3, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , CpsInp010+2, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , CpsInp010+1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , CpsInp010+0, "p4 right" }, + {"P4 Attack" , BIT_DIGITAL , CpsInp010+4, "p4 fire 1" }, + {"P4 Jump" , BIT_DIGITAL , CpsInp010+5, "p4 fire 2" }, + {"P4 Use" , BIT_DIGITAL , CpsInp010+6, "p4 fire 3" }, + {"P4 Select" , BIT_DIGITAL , CpsInp010+7, "p4 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Ddtod) + +static struct BurnInputInfo DimahooInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Shot (auto)" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Shot (auto)" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Dimahoo) + +static struct BurnInputInfo EcofghtrInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Turn 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Turn 2" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Turn 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Turn 2" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Ecofghtr) + +static struct BurnInputInfo GigawingInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Gigawing) + +static struct BurnInputInfo JyangokuInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Shot2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Jyangoku) + +static struct BurnInputInfo Megaman2InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Attack" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Jump" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Select" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Attack" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Jump" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Select" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Megaman2) + +static struct BurnInputInfo Mmancp2uInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Kick" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Kick" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Mmancp2u) + +static struct BurnInputInfo MmatrixInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Mmatrix) + +static struct BurnInputInfo MpangInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Shot2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Shot2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Mpang) + +static struct BurnInputInfo ProgearInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Bomb" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Auto" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Bomb" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Auto" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Progear) + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo Pzloop2InputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4 , "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0 , "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3 , "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2 , "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1 , "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0 , "p1 right" }, + {"P1 Shot" , BIT_DIGITAL , CpsInp001+4 , "p1 fire 1" }, + A("P1 Paddle" , BIT_ANALOG_REL, &CpsInpPaddle1, "mouse x-axis"), + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5 , "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1 , "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3 , "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2 , "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1 , "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0 , "p2 right" }, + {"P2 Shot" , BIT_DIGITAL , CpsInp000+4 , "p2 fire 1" }, + A("P2 Paddle" , BIT_ANALOG_REL, &CpsInpPaddle2, "p2 z-axis" ), + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1 , "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2 , "service" }, +}; + +#undef A + +STDINPUTINFO(Pzloop2) + +static struct BurnInputInfo QndreamInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Answer 1" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Answer 2" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Answer 3" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Answer 4" , BIT_DIGITAL , CpsInp001+7, "p1 fire 4" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Answer 1" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Answer 2" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Answer 3" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Answer 4" , BIT_DIGITAL , CpsInp000+7, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &CpsReset, "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Qndream) + +static struct BurnInputInfo RingdestInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Hold" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Weak punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Strong punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + {"P1 Button 4" , BIT_DIGITAL , CpsInp011+0, "p1 fire 4" }, + {"P1 Weak kick" , BIT_DIGITAL , CpsInp011+1, "p1 fire 5" }, + {"P1 Strong kick" , BIT_DIGITAL , CpsInp011+2, "p1 fire 6" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Hold" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Weak punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Strong punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + {"P2 Button 4" , BIT_DIGITAL , CpsInp011+4, "p2 fire 4" }, + {"P2 Weak kick" , BIT_DIGITAL , CpsInp011+5, "p2 fire 5" }, + {"P2 Strong kick" , BIT_DIGITAL , CpsInp020+6, "p2 fire 6" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Ringdest) + +static struct BurnInputInfo SgemfInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Kick" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + {"P1 Special" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Kick" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + {"P2 Special" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Sgemf) + +static struct BurnInputInfo Spf2tInputList[] = { + {"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" }, + {"P1 Rotate Left" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" }, + {"P1 Rotate Right" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" }, + {"P2 Rotate Left" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" }, + {"P2 Rotate Right" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &CpsReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" }, + {"Service" , BIT_DIGITAL , CpsInp021+2, "service" }, +}; + +STDINPUTINFO(Spf2t) + +// Rom Definitions + +static struct BurnRomInfo NinexxRomDesc[] = { + { "19xu.03", 0x080000, 0x05955268, 1 | BRF_ESS | BRF_PRG }, + { "19xu.04", 0x080000, 0x3111ab7f, 1 | BRF_ESS | BRF_PRG }, + { "19xu.05", 0x080000, 0x38df4a63, 1 | BRF_ESS | BRF_PRG }, + { "19xu.06", 0x080000, 0x5c7e60d3, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexx) +STD_ROM_FN(Ninexx) + +static struct BurnRomInfo NinexxaRomDesc[] = { + { "19xa.03", 0x080000, 0x0c20fd50, 1 | BRF_ESS | BRF_PRG }, + { "19xa.04", 0x080000, 0x1fc37508, 1 | BRF_ESS | BRF_PRG }, + { "19xa.05", 0x080000, 0x6c9cc4ed, 1 | BRF_ESS | BRF_PRG }, + { "19xa.06", 0x080000, 0xca5b9f76, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxa) +STD_ROM_FN(Ninexxa) + +static struct BurnRomInfo NinexxbRomDesc[] = { + { "19xb.03a", 0x080000, 0x341bdf4a, 1 | BRF_ESS | BRF_PRG }, + { "19xb.04a", 0x080000, 0xdff8069e, 1 | BRF_ESS | BRF_PRG }, + { "19xb.05a", 0x080000, 0xa47a92a8, 1 | BRF_ESS | BRF_PRG }, + { "19xb.06a", 0x080000, 0xc52df10d, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxb) +STD_ROM_FN(Ninexxb) + +static struct BurnRomInfo NinexxhRomDesc[] = { + { "19xh.03a", 0x080000, 0x357be2ac, 1 | BRF_ESS | BRF_PRG }, + { "19xh.04a", 0x080000, 0xbb13ea3b, 1 | BRF_ESS | BRF_PRG }, + { "19xh.05a", 0x080000, 0xcbd76601, 1 | BRF_ESS | BRF_PRG }, + { "19xh.06a", 0x080000, 0xb362de8b, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxh) +STD_ROM_FN(Ninexxh) + +static struct BurnRomInfo NinexxjRomDesc[] = { + { "19xj.03a", 0x080000, 0xed08bdd1, 1 | BRF_ESS | BRF_PRG }, + { "19xj.04a", 0x080000, 0xfb8e3f29, 1 | BRF_ESS | BRF_PRG }, + { "19xj.05a", 0x080000, 0xaa508ac4, 1 | BRF_ESS | BRF_PRG }, + { "19xj.06a", 0x080000, 0xff2d785b, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxj) +STD_ROM_FN(Ninexxj) + +static struct BurnRomInfo Ninexxjr1RomDesc[] = { + { "19xj.03", 0x080000, 0x26a381ed, 1 | BRF_ESS | BRF_PRG }, + { "19xj.04", 0x080000, 0x30100cca, 1 | BRF_ESS | BRF_PRG }, + { "19xj.05", 0x080000, 0xde67e938, 1 | BRF_ESS | BRF_PRG }, + { "19xj.06", 0x080000, 0x39f9a409, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxjr1) +STD_ROM_FN(Ninexxjr1) + +static struct BurnRomInfo Nine44RomDesc[] = { + { "nffu.03", 0x080000, 0x9693CF8F, 1 | BRF_ESS | BRF_PRG }, + { "nff.04", 0x080000, 0xDBA1C66E, 1 | BRF_ESS | BRF_PRG }, + { "nffu.05", 0x080000, 0xEA813EB7, 1 | BRF_ESS | BRF_PRG }, + + { "nff.13m", 0x400000, 0xC9FCA741, 3 | BRF_GRA }, + { "nff.15m", 0x400000, 0xF809D898, 3 | BRF_GRA }, + { "nff.17m", 0x400000, 0x15BA4507, 3 | BRF_GRA }, + { "nff.19m", 0x400000, 0x3DD41B8C, 3 | BRF_GRA }, + { "nff.14m", 0x100000, 0x3FE3A54B, 3 | BRF_GRA }, + { "nff.16m", 0x100000, 0x565CD231, 3 | BRF_GRA }, + { "nff.18m", 0x100000, 0x63CA5988, 3 | BRF_GRA }, + { "nff.20m", 0x100000, 0x21EB8F3B, 3 | BRF_GRA }, + + { "nff.01", 0x020000, 0xD2E44318, 4 | BRF_ESS | BRF_PRG }, + + { "nff.11m", 0x400000, 0x243E4E05, 5 | BRF_SND }, + { "nff.12m", 0x400000, 0x4FCF1600, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nine44) +STD_ROM_FN(Nine44) + +static struct BurnRomInfo Nine44jRomDesc[] = { + { "nffj.03", 0x080000, 0x247521EF, 1 | BRF_ESS | BRF_PRG }, + { "nff.04", 0x080000, 0xDBA1C66E, 1 | BRF_ESS | BRF_PRG }, + { "nffj.05", 0x080000, 0x7F20C2EF, 1 | BRF_ESS | BRF_PRG }, + + { "nff.13m", 0x400000, 0xC9FCA741, 3 | BRF_GRA }, + { "nff.15m", 0x400000, 0xF809D898, 3 | BRF_GRA }, + { "nff.17m", 0x400000, 0x15BA4507, 3 | BRF_GRA }, + { "nff.19m", 0x400000, 0x3DD41B8C, 3 | BRF_GRA }, + { "nff.14m", 0x100000, 0x3FE3A54B, 3 | BRF_GRA }, + { "nff.16m", 0x100000, 0x565CD231, 3 | BRF_GRA }, + { "nff.18m", 0x100000, 0x63CA5988, 3 | BRF_GRA }, + { "nff.20m", 0x100000, 0x21EB8F3B, 3 | BRF_GRA }, + + { "nff.01", 0x020000, 0xD2E44318, 4 | BRF_ESS | BRF_PRG }, + + { "nff.11m", 0x400000, 0x243E4E05, 5 | BRF_SND }, + { "nff.12m", 0x400000, 0x4FCF1600, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nine44j) +STD_ROM_FN(Nine44j) + +static struct BurnRomInfo ArmwarRomDesc[] = { + { "pwge.03c", 0x080000, 0x31f74931, 1 | BRF_ESS | BRF_PRG }, + { "pwge.04c", 0x080000, 0x16f34f5f, 1 | BRF_ESS | BRF_PRG }, + { "pwge.05b", 0x080000, 0x4403ed08, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09a", 0x080000, 0x4c26baee, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwar) +STD_ROM_FN(Armwar) + +static struct BurnRomInfo Armwarr1RomDesc[] = { + { "pwge.03b", 0x080000, 0xe822e3e9, 1 | BRF_ESS | BRF_PRG }, + { "pwge.04b", 0x080000, 0x4f89de39, 1 | BRF_ESS | BRF_PRG }, + { "pwge.05a", 0x080000, 0x83df24e5, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09", 0x080000, 0xddc85ca6, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwarr1) +STD_ROM_FN(Armwarr1) + +static struct BurnRomInfo ArmwaraRomDesc[] = { + { "pwga.03a", 0x080000, 0x8d474ab1, 1 | BRF_ESS | BRF_PRG }, + { "pwga.04a", 0x080000, 0x81b5aec7, 1 | BRF_ESS | BRF_PRG }, + { "pwga.05a", 0x080000, 0x2618e819, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09", 0x080000, 0xddc85ca6, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwara) +STD_ROM_FN(Armwara) + +static struct BurnRomInfo ArmwaruRomDesc[] = { + { "pwgu.03b", 0x080000, 0x8b95497a, 1 | BRF_ESS | BRF_PRG }, + { "pwgu.04b", 0x080000, 0x29eb5661, 1 | BRF_ESS | BRF_PRG }, + { "pwgu.05b", 0x080000, 0xa54e9e44, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09a", 0x080000, 0x4c26baee, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwaru) +STD_ROM_FN(Armwaru) + +static struct BurnRomInfo Armwaru1RomDesc[] = { + { "pwgu.03a", 0x080000, 0x73d397b1, 1 | BRF_ESS | BRF_PRG }, + { "pwgu.04a", 0x080000, 0x1f1de215, 1 | BRF_ESS | BRF_PRG }, + { "pwgu.05a", 0x080000, 0x835fbe73, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09", 0x080000, 0xddc85ca6, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwaru1) +STD_ROM_FN(Armwaru1) + +static struct BurnRomInfo PgearRomDesc[] = { + { "pwgj.03a", 0x080000, 0xc79c0c02, 1 | BRF_ESS | BRF_PRG }, + { "pwgj.04a", 0x080000, 0x167c6ed8, 1 | BRF_ESS | BRF_PRG }, + { "pwgj.05a", 0x080000, 0xa63fb400, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09a", 0x080000, 0x4c26baee, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Pgear) +STD_ROM_FN(Pgear) + +static struct BurnRomInfo Pgearr1RomDesc[] = { + { "pwgj.03", 0x080000, 0xf264e74b, 1 | BRF_ESS | BRF_PRG }, + { "pwgj.04", 0x080000, 0x23a84983, 1 | BRF_ESS | BRF_PRG }, + { "pwgj.05", 0x080000, 0xbef58c62, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09", 0x080000, 0xddc85ca6, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Pgearr1) +STD_ROM_FN(Pgearr1) + +static struct BurnRomInfo AvspRomDesc[] = { + { "avpe.03d", 0x080000, 0x774334a9, 1 | BRF_ESS | BRF_PRG }, + { "avpe.04d", 0x080000, 0x7fa83769, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avp.06", 0x080000, 0x190b817f, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avsp) +STD_ROM_FN(Avsp) + +static struct BurnRomInfo AvspaRomDesc[] = { + { "avpa.03d", 0x080000, 0x6c1c1858, 1 | BRF_ESS | BRF_PRG }, + { "avpa.04d", 0x080000, 0x94f50b0c, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avp.06", 0x080000, 0x190b817f, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avspa) +STD_ROM_FN(Avspa) + +static struct BurnRomInfo AvsphRomDesc[] = { + { "avph.03d", 0x080000, 0x3e440447, 1 | BRF_ESS | BRF_PRG }, + { "avph.04d", 0x080000, 0xaf6fc82f, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avp.06", 0x080000, 0x190b817f, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avsph) +STD_ROM_FN(Avsph) + +static struct BurnRomInfo AvspjRomDesc[] = { + { "avpj.03d", 0x080000, 0x49799119, 1 | BRF_ESS | BRF_PRG }, + { "avpj.04d", 0x080000, 0x8cd2bba8, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avp.06", 0x080000, 0x190b817f, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avspj) +STD_ROM_FN(Avspj) + +static struct BurnRomInfo AvspuRomDesc[] = { + { "avpu.03d", 0x080000, 0x42757950, 1 | BRF_ESS | BRF_PRG }, + { "avpu.04d", 0x080000, 0x5abcdee6, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avp.06", 0x080000, 0x190b817f, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avspu) +STD_ROM_FN(Avspu) + +static struct BurnRomInfo BatcirRomDesc[] = { + { "btce.03", 0x080000, 0xbc60484b, 1 | BRF_ESS | BRF_PRG }, + { "btce.04", 0x080000, 0x457d55f6, 1 | BRF_ESS | BRF_PRG }, + { "btce.05", 0x080000, 0xe86560d7, 1 | BRF_ESS | BRF_PRG }, + { "btce.06", 0x080000, 0xf778e61b, 1 | BRF_ESS | BRF_PRG }, + { "btc.07", 0x080000, 0x7322d5db, 1 | BRF_ESS | BRF_PRG }, + { "btc.08", 0x080000, 0x6aac85ab, 1 | BRF_ESS | BRF_PRG }, + { "btc.09", 0x080000, 0x1203db08, 1 | BRF_ESS | BRF_PRG }, + + { "btc.13m", 0x400000, 0xdc705bad, 3 | BRF_GRA }, + { "btc.15m", 0x400000, 0xe5779a3c, 3 | BRF_GRA }, + { "btc.17m", 0x400000, 0xb33f4112, 3 | BRF_GRA }, + { "btc.19m", 0x400000, 0xa6fcdb7e, 3 | BRF_GRA }, + + { "btc.01", 0x020000, 0x1e194310, 4 | BRF_ESS | BRF_PRG }, + { "btc.02", 0x020000, 0x01aeb8e6, 4 | BRF_ESS | BRF_PRG }, + + { "btc.11m", 0x200000, 0xc27f2229, 5 | BRF_SND }, + { "btc.12m", 0x200000, 0x418a2e33, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Batcir) +STD_ROM_FN(Batcir) + +static struct BurnRomInfo BatciraRomDesc[] = { + { "btca.03", 0x080000, 0x1ad20d87, 1 | BRF_ESS | BRF_PRG }, + { "btca.04", 0x080000, 0x2b3f4dbe, 1 | BRF_ESS | BRF_PRG }, + { "btca.05", 0x080000, 0x8238a3d9, 1 | BRF_ESS | BRF_PRG }, + { "btca.06", 0x080000, 0x446c7c02, 1 | BRF_ESS | BRF_PRG }, + { "btc.07", 0x080000, 0x7322d5db, 1 | BRF_ESS | BRF_PRG }, + { "btc.08", 0x080000, 0x6aac85ab, 1 | BRF_ESS | BRF_PRG }, + { "btc.09", 0x080000, 0x1203db08, 1 | BRF_ESS | BRF_PRG }, + + { "btc.13m", 0x400000, 0xdc705bad, 3 | BRF_GRA }, + { "btc.15m", 0x400000, 0xe5779a3c, 3 | BRF_GRA }, + { "btc.17m", 0x400000, 0xb33f4112, 3 | BRF_GRA }, + { "btc.19m", 0x400000, 0xa6fcdb7e, 3 | BRF_GRA }, + + { "btc.01", 0x020000, 0x1e194310, 4 | BRF_ESS | BRF_PRG }, + { "btc.02", 0x020000, 0x01aeb8e6, 4 | BRF_ESS | BRF_PRG }, + + { "btc.11m", 0x200000, 0xc27f2229, 5 | BRF_SND }, + { "btc.12m", 0x200000, 0x418a2e33, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Batcira) +STD_ROM_FN(Batcira) + +static struct BurnRomInfo BatcirjRomDesc[] = { + { "btcj.03", 0x080000, 0x6b7e168d, 1 | BRF_ESS | BRF_PRG }, + { "btcj.04", 0x080000, 0x46ba3467, 1 | BRF_ESS | BRF_PRG }, + { "btcj.05", 0x080000, 0x0e23a859, 1 | BRF_ESS | BRF_PRG }, + { "btcj.06", 0x080000, 0xa853b59c, 1 | BRF_ESS | BRF_PRG }, + { "btc.07", 0x080000, 0x7322d5db, 1 | BRF_ESS | BRF_PRG }, + { "btc.08", 0x080000, 0x6aac85ab, 1 | BRF_ESS | BRF_PRG }, + { "btc.09", 0x080000, 0x1203db08, 1 | BRF_ESS | BRF_PRG }, + + { "btc.13m", 0x400000, 0xdc705bad, 3 | BRF_GRA }, + { "btc.15m", 0x400000, 0xe5779a3c, 3 | BRF_GRA }, + { "btc.17m", 0x400000, 0xb33f4112, 3 | BRF_GRA }, + { "btc.19m", 0x400000, 0xa6fcdb7e, 3 | BRF_GRA }, + + { "btc.01", 0x020000, 0x1e194310, 4 | BRF_ESS | BRF_PRG }, + { "btc.02", 0x020000, 0x01aeb8e6, 4 | BRF_ESS | BRF_PRG }, + + { "btc.11m", 0x200000, 0xc27f2229, 5 | BRF_SND }, + { "btc.12m", 0x200000, 0x418a2e33, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Batcirj) +STD_ROM_FN(Batcirj) + +static struct BurnRomInfo ChokoRomDesc[] = { + { "tkoj.03", 0x080000, 0x11f5452f, 1 | BRF_ESS | BRF_PRG }, + { "tkoj.04", 0x080000, 0x68655378, 1 | BRF_ESS | BRF_PRG }, + + { "tkoj1_d.simm1", 0x200000, 0x6933377d, 11 | BRF_GRA }, + { "tkoj1_c.simm1", 0x200000, 0x7f668950, 11 | BRF_GRA }, + { "tkoj1_b.simm1", 0x200000, 0xcfb68ca9, 11 | BRF_GRA }, + { "tkoj1_a.simm1", 0x200000, 0x437e21c5, 11 | BRF_GRA }, + { "tkoj3_d.simm3", 0x200000, 0xa9e32b57, 11 | BRF_GRA }, + { "tkoj3_c.simm3", 0x200000, 0xb7ab9338, 11 | BRF_GRA }, + { "tkoj3_b.simm3", 0x200000, 0x4d3f919a, 11 | BRF_GRA }, + { "tkoj3_a.simm3", 0x200000, 0xcfef17ab, 11 | BRF_GRA }, + + { "tko.01", 0x020000, 0x6eda50c2, 4 | BRF_ESS | BRF_PRG }, + + { "tkoj5_a.simm5", 0x200000, 0xab45d509, 15 | BRF_SND }, + { "tkoj5_b.simm5", 0x200000, 0xfa905c3d, 15 | BRF_SND }, +}; + +STD_ROM_PICK(Choko) +STD_ROM_FN(Choko) + +static struct BurnRomInfo CsclubRomDesc[] = { + { "csce.03a", 0x080000, 0x824082be, 1 | BRF_ESS | BRF_PRG }, + { "csce.04a", 0x080000, 0x74e6a4fe, 1 | BRF_ESS | BRF_PRG }, + { "csce.05a", 0x080000, 0x8ae0df19, 1 | BRF_ESS | BRF_PRG }, + { "csce.06a", 0x080000, 0x51f2f0d3, 1 | BRF_ESS | BRF_PRG }, + { "csce.07a", 0x080000, 0x003968fd, 1 | BRF_ESS | BRF_PRG }, + + { "csc.73", 0x080000, 0x335f07c3, 6 | BRF_GRA }, + { "csc.74", 0x080000, 0xab215357, 6 | BRF_GRA }, + { "csc.75", 0x080000, 0xa2367381, 6 | BRF_GRA }, + { "csc.76", 0x080000, 0x728aac1f, 6 | BRF_GRA }, + { "csc.63", 0x080000, 0x3711b8ca, 6 | BRF_GRA }, + { "csc.64", 0x080000, 0x828a06d8, 6 | BRF_GRA }, + { "csc.65", 0x080000, 0x86ee4569, 6 | BRF_GRA }, + { "csc.66", 0x080000, 0xc24f577f, 6 | BRF_GRA }, + { "csc.83", 0x080000, 0x0750d12a, 6 | BRF_GRA }, + { "csc.84", 0x080000, 0x90a92f39, 6 | BRF_GRA }, + { "csc.85", 0x080000, 0xd08ab012, 6 | BRF_GRA }, + { "csc.86", 0x080000, 0x41652583, 6 | BRF_GRA }, + { "csc.93", 0x080000, 0xa756c7f7, 6 | BRF_GRA }, + { "csc.94", 0x080000, 0xfb7ccc73, 6 | BRF_GRA }, + { "csc.95", 0x080000, 0x4d014297, 6 | BRF_GRA }, + { "csc.96", 0x080000, 0x6754b1ef, 6 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.51", 0x080000, 0x5a52afd5, 5 | BRF_SND }, + { "csc.52", 0x080000, 0x1408a811, 5 | BRF_SND }, + { "csc.53", 0x080000, 0x4fb9f57c, 5 | BRF_SND }, + { "csc.54", 0x080000, 0x9a8f40ec, 5 | BRF_SND }, + { "csc.55", 0x080000, 0x91529a91, 5 | BRF_SND }, + { "csc.56", 0x080000, 0x9a345334, 5 | BRF_SND }, + { "csc.57", 0x080000, 0xaedc27f2, 5 | BRF_SND }, + { "csc.58", 0x080000, 0x2300b7b3, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclub) +STD_ROM_FN(Csclub) + +static struct BurnRomInfo Csclub1RomDesc[] = { + { "csce.03", 0x080000, 0xf2c852ef, 1 | BRF_ESS | BRF_PRG }, + { "csce.04", 0x080000, 0x1184530f, 1 | BRF_ESS | BRF_PRG }, + { "csce.05", 0x080000, 0x804e2b6b, 1 | BRF_ESS | BRF_PRG }, + { "csce.06", 0x080000, 0x09277cb9, 1 | BRF_ESS | BRF_PRG }, + { "csc.07", 0x080000, 0x01b05caa, 1 | BRF_ESS | BRF_PRG }, + + { "csc.14m", 0x200000, 0xe8904afa, 3 | BRF_GRA }, + { "csc.16m", 0x200000, 0xc98c8079, 3 | BRF_GRA }, + { "csc.18m", 0x200000, 0xc030df5a, 3 | BRF_GRA }, + { "csc.20m", 0x200000, 0xb4e55863, 3 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.11m", 0x200000, 0xa027b827, 5 | BRF_SND }, + { "csc.12m", 0x200000, 0xcb7f6e55, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclub1) +STD_ROM_FN(Csclub1) + +static struct BurnRomInfo CsclubaRomDesc[] = { + { "csca.03", 0x080000, 0xb6acd708, 1 | BRF_ESS | BRF_PRG }, + { "csca.04", 0x080000, 0xd44ae35f, 1 | BRF_ESS | BRF_PRG }, + { "csca.05", 0x080000, 0x8da76aec, 1 | BRF_ESS | BRF_PRG }, + { "csca.06", 0x080000, 0xa1b7b1ee, 1 | BRF_ESS | BRF_PRG }, + { "csc.07", 0x080000, 0x01b05caa, 1 | BRF_ESS | BRF_PRG }, + + { "csc.14m", 0x200000, 0xe8904afa, 3 | BRF_GRA }, + { "csc.16m", 0x200000, 0xc98c8079, 3 | BRF_GRA }, + { "csc.18m", 0x200000, 0xc030df5a, 3 | BRF_GRA }, + { "csc.20m", 0x200000, 0xb4e55863, 3 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.11m", 0x200000, 0xa027b827, 5 | BRF_SND }, + { "csc.12m", 0x200000, 0xcb7f6e55, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Cscluba) +STD_ROM_FN(Cscluba) + +static struct BurnRomInfo CsclubhRomDesc[] = { + { "csch.03", 0x080000, 0x0dd7e46d, 1 | BRF_ESS | BRF_PRG }, + { "csch.04", 0x080000, 0x486e8143, 1 | BRF_ESS | BRF_PRG }, + { "csch.05", 0x080000, 0x9e509dfb, 1 | BRF_ESS | BRF_PRG }, + { "csch.06", 0x080000, 0x817ba313, 1 | BRF_ESS | BRF_PRG }, + { "csc.07", 0x080000, 0x01b05caa, 1 | BRF_ESS | BRF_PRG }, + + { "csc.14m", 0x200000, 0xe8904afa, 3 | BRF_GRA }, + { "csc.16m", 0x200000, 0xc98c8079, 3 | BRF_GRA }, + { "csc.18m", 0x200000, 0xc030df5a, 3 | BRF_GRA }, + { "csc.20m", 0x200000, 0xb4e55863, 3 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.11m", 0x200000, 0xa027b827, 5 | BRF_SND }, + { "csc.12m", 0x200000, 0xcb7f6e55, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclubh) +STD_ROM_FN(Csclubh) + +static struct BurnRomInfo CsclubjRomDesc[] = { + { "cscj.03", 0x080000, 0xec4ddaa2, 1 | BRF_ESS | BRF_PRG }, + { "cscj.04", 0x080000, 0x60c632bb, 1 | BRF_ESS | BRF_PRG }, + { "cscj.05", 0x080000, 0xad042003, 1 | BRF_ESS | BRF_PRG }, + { "cscj.06", 0x080000, 0x169e4d40, 1 | BRF_ESS | BRF_PRG }, + { "csc.07", 0x080000, 0x01b05caa, 1 | BRF_ESS | BRF_PRG }, + + { "csc.14m", 0x200000, 0xe8904afa, 3 | BRF_GRA }, + { "csc.16m", 0x200000, 0xc98c8079, 3 | BRF_GRA }, + { "csc.18m", 0x200000, 0xc030df5a, 3 | BRF_GRA }, + { "csc.20m", 0x200000, 0xb4e55863, 3 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.11m", 0x200000, 0xa027b827, 5 | BRF_SND }, + { "csc.12m", 0x200000, 0xcb7f6e55, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclubj) +STD_ROM_FN(Csclubj) + +static struct BurnRomInfo CsclubjrRomDesc[] = { + { "cscj.03", 0x080000, 0xec4ddaa2, 1 | BRF_ESS | BRF_PRG }, + { "cscj.04", 0x080000, 0x60c632bb, 1 | BRF_ESS | BRF_PRG }, + { "cscj.05", 0x080000, 0xad042003, 1 | BRF_ESS | BRF_PRG }, + { "cscj.06", 0x080000, 0x169e4d40, 1 | BRF_ESS | BRF_PRG }, + { "csc.07", 0x080000, 0x01b05caa, 1 | BRF_ESS | BRF_PRG }, + + { "csc.73", 0x080000, 0x335f07c3, 6 | BRF_GRA }, + { "csc.74", 0x080000, 0xab215357, 6 | BRF_GRA }, + { "csc.75", 0x080000, 0xa2367381, 6 | BRF_GRA }, + { "csc.76", 0x080000, 0x728aac1f, 6 | BRF_GRA }, + { "csc.63", 0x080000, 0x3711b8ca, 6 | BRF_GRA }, + { "csc.64", 0x080000, 0x828a06d8, 6 | BRF_GRA }, + { "csc.65", 0x080000, 0x86ee4569, 6 | BRF_GRA }, + { "csc.66", 0x080000, 0xc24f577f, 6 | BRF_GRA }, + { "csc.83", 0x080000, 0x0750d12a, 6 | BRF_GRA }, + { "csc.84", 0x080000, 0x90a92f39, 6 | BRF_GRA }, + { "csc.85", 0x080000, 0xd08ab012, 6 | BRF_GRA }, + { "csc.86", 0x080000, 0x41652583, 6 | BRF_GRA }, + { "csc.93", 0x080000, 0xa756c7f7, 6 | BRF_GRA }, + { "csc.94", 0x080000, 0xfb7ccc73, 6 | BRF_GRA }, + { "csc.95", 0x080000, 0x4d014297, 6 | BRF_GRA }, + { "csc.96", 0x080000, 0x6754b1ef, 6 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.51", 0x080000, 0x5a52afd5, 5 | BRF_SND }, + { "csc.52", 0x080000, 0x1408a811, 5 | BRF_SND }, + { "csc.53", 0x080000, 0x4fb9f57c, 5 | BRF_SND }, + { "csc.54", 0x080000, 0x9a8f40ec, 5 | BRF_SND }, + { "csc.55", 0x080000, 0x91529a91, 5 | BRF_SND }, + { "csc.56", 0x080000, 0x9a345334, 5 | BRF_SND }, + { "csc.57", 0x080000, 0xaedc27f2, 5 | BRF_SND }, + { "csc.58", 0x080000, 0x2300b7b3, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclubjr) +STD_ROM_FN(Csclubjr) + +static struct BurnRomInfo CybotsRomDesc[] = { + { "cybe.03", 0x080000, 0x234381cd, 1 | BRF_ESS | BRF_PRG }, + { "cybe.04", 0x080000, 0x80691061, 1 | BRF_ESS | BRF_PRG }, + { "cyb.05", 0x080000, 0xec40408e, 1 | BRF_ESS | BRF_PRG }, + { "cyb.06", 0x080000, 0x1ad0bed2, 1 | BRF_ESS | BRF_PRG }, + { "cyb.07", 0x080000, 0x6245a39a, 1 | BRF_ESS | BRF_PRG }, + { "cyb.08", 0x080000, 0x4b48e223, 1 | BRF_ESS | BRF_PRG }, + { "cyb.09", 0x080000, 0xe15238f6, 1 | BRF_ESS | BRF_PRG }, + { "cyb.10", 0x080000, 0x75f4003b, 1 | BRF_ESS | BRF_PRG }, + + { "cyb.13m", 0x400000, 0xf0dce192, 3 | BRF_GRA }, + { "cyb.15m", 0x400000, 0x187aa39c, 3 | BRF_GRA }, + { "cyb.17m", 0x400000, 0x8a0e4b12, 3 | BRF_GRA }, + { "cyb.19m", 0x400000, 0x34b62612, 3 | BRF_GRA }, + { "cyb.14m", 0x400000, 0xc1537957, 3 | BRF_GRA }, + { "cyb.16m", 0x400000, 0x15349e86, 3 | BRF_GRA }, + { "cyb.18m", 0x400000, 0xd83e977d, 3 | BRF_GRA }, + { "cyb.20m", 0x400000, 0x77cdad5c, 3 | BRF_GRA }, + + { "cyb.01", 0x020000, 0x9c0fb079, 4 | BRF_ESS | BRF_PRG }, + { "cyb.02", 0x020000, 0x51cb0c4e, 4 | BRF_ESS | BRF_PRG }, + + { "cyb.11m", 0x200000, 0x362ccab2, 5 | BRF_SND }, + { "cyb.12m", 0x200000, 0x7066e9cc, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Cybots) +STD_ROM_FN(Cybots) + +static struct BurnRomInfo CybotsjRomDesc[] = { + { "cybj.03", 0x080000, 0x6096eada, 1 | BRF_ESS | BRF_PRG }, + { "cybj.04", 0x080000, 0x7b0ffaa9, 1 | BRF_ESS | BRF_PRG }, + { "cyb.05", 0x080000, 0xec40408e, 1 | BRF_ESS | BRF_PRG }, + { "cyb.06", 0x080000, 0x1ad0bed2, 1 | BRF_ESS | BRF_PRG }, + { "cyb.07", 0x080000, 0x6245a39a, 1 | BRF_ESS | BRF_PRG }, + { "cyb.08", 0x080000, 0x4b48e223, 1 | BRF_ESS | BRF_PRG }, + { "cyb.09", 0x080000, 0xe15238f6, 1 | BRF_ESS | BRF_PRG }, + { "cyb.10", 0x080000, 0x75f4003b, 1 | BRF_ESS | BRF_PRG }, + + { "cyb.13m", 0x400000, 0xf0dce192, 3 | BRF_GRA }, + { "cyb.15m", 0x400000, 0x187aa39c, 3 | BRF_GRA }, + { "cyb.17m", 0x400000, 0x8a0e4b12, 3 | BRF_GRA }, + { "cyb.19m", 0x400000, 0x34b62612, 3 | BRF_GRA }, + { "cyb.14m", 0x400000, 0xc1537957, 3 | BRF_GRA }, + { "cyb.16m", 0x400000, 0x15349e86, 3 | BRF_GRA }, + { "cyb.18m", 0x400000, 0xd83e977d, 3 | BRF_GRA }, + { "cyb.20m", 0x400000, 0x77cdad5c, 3 | BRF_GRA }, + + { "cyb.01", 0x020000, 0x9c0fb079, 4 | BRF_ESS | BRF_PRG }, + { "cyb.02", 0x020000, 0x51cb0c4e, 4 | BRF_ESS | BRF_PRG }, + + { "cyb.11m", 0x200000, 0x362ccab2, 5 | BRF_SND }, + { "cyb.12m", 0x200000, 0x7066e9cc, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Cybotsj) +STD_ROM_FN(Cybotsj) + +static struct BurnRomInfo CybotsuRomDesc[] = { + { "cybu.03", 0x080000, 0xdb4da8f4, 1 | BRF_ESS | BRF_PRG }, + { "cybu.04", 0x080000, 0x1eec68ac, 1 | BRF_ESS | BRF_PRG }, + { "cyb.05", 0x080000, 0xec40408e, 1 | BRF_ESS | BRF_PRG }, + { "cyb.06", 0x080000, 0x1ad0bed2, 1 | BRF_ESS | BRF_PRG }, + { "cyb.07", 0x080000, 0x6245a39a, 1 | BRF_ESS | BRF_PRG }, + { "cyb.08", 0x080000, 0x4b48e223, 1 | BRF_ESS | BRF_PRG }, + { "cyb.09", 0x080000, 0xe15238f6, 1 | BRF_ESS | BRF_PRG }, + { "cyb.10", 0x080000, 0x75f4003b, 1 | BRF_ESS | BRF_PRG }, + + { "cyb.13m", 0x400000, 0xf0dce192, 3 | BRF_GRA }, + { "cyb.15m", 0x400000, 0x187aa39c, 3 | BRF_GRA }, + { "cyb.17m", 0x400000, 0x8a0e4b12, 3 | BRF_GRA }, + { "cyb.19m", 0x400000, 0x34b62612, 3 | BRF_GRA }, + { "cyb.14m", 0x400000, 0xc1537957, 3 | BRF_GRA }, + { "cyb.16m", 0x400000, 0x15349e86, 3 | BRF_GRA }, + { "cyb.18m", 0x400000, 0xd83e977d, 3 | BRF_GRA }, + { "cyb.20m", 0x400000, 0x77cdad5c, 3 | BRF_GRA }, + + { "cyb.01", 0x020000, 0x9c0fb079, 4 | BRF_ESS | BRF_PRG }, + { "cyb.02", 0x020000, 0x51cb0c4e, 4 | BRF_ESS | BRF_PRG }, + + { "cyb.11m", 0x200000, 0x362ccab2, 5 | BRF_SND }, + { "cyb.12m", 0x200000, 0x7066e9cc, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Cybotsu) +STD_ROM_FN(Cybotsu) + +static struct BurnRomInfo DdsomRomDesc[] = { + { "dd2e.03e", 0x080000, 0x449361AF, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.04e", 0x080000, 0x5B7052B6, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.05e", 0x080000, 0x788D5F60, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.06e", 0x080000, 0xE0807E1E, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.07", 0x080000, 0xbb777a02, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsom) +STD_ROM_FN(Ddsom) + +static struct BurnRomInfo Ddsomr1RomDesc[] = { + { "dd2e.03d", 0x080000, 0x6c084ab5, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.04d", 0x080000, 0x9b94a947, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.05d", 0x080000, 0x5d6a63c6, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.06d", 0x080000, 0x31bde8ee, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.07", 0x080000, 0xbb777a02, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomr1) +STD_ROM_FN(Ddsomr1) + +static struct BurnRomInfo Ddsomr2RomDesc[] = { + { "dd2e.03b", 0x080000, 0xcd2deb66, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.04b", 0x080000, 0xbfee43cc, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.05b", 0x080000, 0x049ab19d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.06b", 0x080000, 0x3994fb8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.07", 0x080000, 0xbb777a02, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomr2) +STD_ROM_FN(Ddsomr2) + +static struct BurnRomInfo Ddsomr3RomDesc[] = { + { "dd2e.03a", 0x080000, 0x6de67678, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.04a", 0x080000, 0x0e45739a, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.05a", 0x080000, 0x3dce8025, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.06a", 0x080000, 0x51bafbef, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.07", 0x080000, 0xbb777a02, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomr3) +STD_ROM_FN(Ddsomr3) + +static struct BurnRomInfo DdsomaRomDesc[] = { + { "dd2a.03g", 0x080000, 0x0b4fec22, 1 | BRF_ESS | BRF_PRG }, + { "dd2a.04g", 0x080000, 0x055b7019, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05g", 0x080000, 0x5eb1991c, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06g", 0x080000, 0xc26b5e55, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2.10", 0x080000, 0xad954c26, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsoma) +STD_ROM_FN(Ddsoma) + +static struct BurnRomInfo DdsombRomDesc[] = { + { "dd2b.03a", 0x080000, 0xe8ce7fbb, 1 | BRF_ESS | BRF_PRG }, + { "dd2b.04a", 0x080000, 0x6b679664, 1 | BRF_ESS | BRF_PRG }, + { "dd2b.05a", 0x080000, 0x9b2534eb, 1 | BRF_ESS | BRF_PRG }, + { "dd2b.06a", 0x080000, 0x3b21ba59, 1 | BRF_ESS | BRF_PRG }, + { "dd2b.07", 0x080000, 0xfce2558d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomb) +STD_ROM_FN(Ddsomb) + +static struct BurnRomInfo DdsomhRomDesc[] = { + { "dd2h.03a", 0x080000, 0xe472c9f3, 1 | BRF_ESS | BRF_PRG }, + { "dd2h.04a", 0x080000, 0x315a7706, 1 | BRF_ESS | BRF_PRG }, + { "dd2h.05a", 0x080000, 0x9b2534eb, 1 | BRF_ESS | BRF_PRG }, + { "dd2h.06a", 0x080000, 0x3b21ba59, 1 | BRF_ESS | BRF_PRG }, + { "dd2h.07a", 0x080000, 0xfce2558d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.08", 0x080000, 0x30970890, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.09", 0x080000, 0x99e2194d, 1 | BRF_ESS | BRF_PRG }, + { "dd2e.10", 0x080000, 0xe198805e, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomh) +STD_ROM_FN(Ddsomh) + +static struct BurnRomInfo DdsomjRomDesc[] = { + { "dd2j.03g", 0x080000, 0xe6c8c985, 1 | BRF_ESS | BRF_PRG }, + { "dd2j.04g", 0x080000, 0x8386c0bd, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05g", 0x080000, 0x5eb1991c, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06g", 0x080000, 0xc26b5e55, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2.10", 0x080000, 0xad954c26, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomj) +STD_ROM_FN(Ddsomj) + +static struct BurnRomInfo Ddsomjr1RomDesc[] = { + { "dd2j.03b", 0x080000, 0x965d74e5, 1 | BRF_ESS | BRF_PRG }, + { "dd2j.04b", 0x080000, 0x958eb8f3, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05b", 0x080000, 0xd38571ca, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06b", 0x080000, 0x6d5a3bbb, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2.10", 0x080000, 0xad954c26, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomjr1) +STD_ROM_FN(Ddsomjr1) + +static struct BurnRomInfo DdsomuRomDesc[] = { + { "dd2u.03g", 0x080000, 0xfb089b39, 1 | BRF_ESS | BRF_PRG }, + { "dd2u.04g", 0x080000, 0xcd432b73, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05g", 0x080000, 0x5eb1991c, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06g", 0x080000, 0xc26b5e55, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2.10", 0x080000, 0xad954c26, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomu) +STD_ROM_FN(Ddsomu) + +static struct BurnRomInfo Ddsomur1RomDesc[] = { + { "dd2u.03d", 0x080000, 0x0f700d84, 1 | BRF_ESS | BRF_PRG }, + { "dd2u.04d", 0x080000, 0xb99eb254, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05d", 0x080000, 0xb23061f3, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06d", 0x080000, 0x8bf1d8ce, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2.10", 0x080000, 0xad954c26, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomur1) +STD_ROM_FN(Ddsomur1) + +static struct BurnRomInfo DdtodRomDesc[] = { + { "dade.03c", 0x080000, 0x8e73533d, 1 | BRF_ESS | BRF_PRG }, + { "dade.04c", 0x080000, 0x00c2e82e, 1 | BRF_ESS | BRF_PRG }, + { "dade.05c", 0x080000, 0xea996008, 1 | BRF_ESS | BRF_PRG }, + { "dad.06a", 0x080000, 0x6225495a, 1 | BRF_ESS | BRF_PRG }, + { "dad.07a", 0x080000, 0xb3480ec3, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtod) +STD_ROM_FN(Ddtod) + +static struct BurnRomInfo Ddtodr1RomDesc[] = { + { "dade.03a", 0x080000, 0x665a035e, 1 | BRF_ESS | BRF_PRG }, + { "dade.04a", 0x080000, 0x02613207, 1 | BRF_ESS | BRF_PRG }, + { "dade.05a", 0x080000, 0x36845996, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodr1) +STD_ROM_FN(Ddtodr1) + +static struct BurnRomInfo DdtodaRomDesc[] = { + { "dada.03a", 0x080000, 0xfc6f2dd7, 1 | BRF_ESS | BRF_PRG }, + { "dada.04a", 0x080000, 0xd4be4009, 1 | BRF_ESS | BRF_PRG }, + { "dada.05a", 0x080000, 0x6712d1cf, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtoda) +STD_ROM_FN(Ddtoda) + +static struct BurnRomInfo DdtodhRomDesc[] = { + { "dadh.03c", 0x080000, 0x5750a861, 1 | BRF_ESS | BRF_PRG }, + { "dadh.04c", 0x080000, 0xcfbf1b56, 1 | BRF_ESS | BRF_PRG }, + { "dadh.05c", 0x080000, 0xa6e562ba, 1 | BRF_ESS | BRF_PRG }, + { "dad.06a", 0x080000, 0x6225495a, 1 | BRF_ESS | BRF_PRG }, + { "dad.07a", 0x080000, 0xb3480ec3, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodh) +STD_ROM_FN(Ddtodh) + +static struct BurnRomInfo Ddtodhr1RomDesc[] = { + { "dadh.03b", 0x080000, 0xae0cb98e, 1 | BRF_ESS | BRF_PRG }, + { "dadh.04b", 0x080000, 0xb5774363, 1 | BRF_ESS | BRF_PRG }, + { "dadh.05b", 0x080000, 0x6ce2a485, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodhr1) +STD_ROM_FN(Ddtodhr1) + +static struct BurnRomInfo Ddtodhr2RomDesc[] = { + { "dadh.03a", 0x080000, 0x43d04aa3, 1 | BRF_ESS | BRF_PRG }, + { "dadh.04a", 0x080000, 0x8b8d296c, 1 | BRF_ESS | BRF_PRG }, + { "dadh.05a", 0x080000, 0xdaae6b14, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodhr2) +STD_ROM_FN(Ddtodhr2) + +static struct BurnRomInfo DdtodjRomDesc[] = { + { "dadj.03c", 0x080000, 0x0b1b5798, 1 | BRF_ESS | BRF_PRG }, + { "dadj.04c", 0x080000, 0xc6a2fbc8, 1 | BRF_ESS | BRF_PRG }, + { "dadj.05c", 0x080000, 0x189b15fe, 1 | BRF_ESS | BRF_PRG }, + { "dad.06a", 0x080000, 0x6225495a, 1 | BRF_ESS | BRF_PRG }, + { "dad.07a", 0x080000, 0xb3480ec3, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodj) +STD_ROM_FN(Ddtodj) + +static struct BurnRomInfo Ddtodjr1RomDesc[] = { + { "dadj.03b", 0x080000, 0x87606b85, 1 | BRF_ESS | BRF_PRG }, + { "dadj.04b", 0x080000, 0x24d49575, 1 | BRF_ESS | BRF_PRG }, + { "dadj.05b", 0x080000, 0x56ce51f7, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodjr1) +STD_ROM_FN(Ddtodjr1) + +static struct BurnRomInfo Ddtodjr2RomDesc[] = { + { "dadj.03a", 0x080000, 0x711638dc, 1 | BRF_ESS | BRF_PRG }, + { "dadj.04a", 0x080000, 0x4869639c, 1 | BRF_ESS | BRF_PRG }, + { "dadj.05a", 0x080000, 0x484c0efa, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodjr2) +STD_ROM_FN(Ddtodjr2) + +static struct BurnRomInfo DdtoduRomDesc[] = { + { "dadu.03b", 0x080000, 0xa519905f, 1 | BRF_ESS | BRF_PRG }, + { "dadu.04b", 0x080000, 0x52562d38, 1 | BRF_ESS | BRF_PRG }, + { "dadu.05b", 0x080000, 0xee1cfbfe, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodu) +STD_ROM_FN(Ddtodu) + +static struct BurnRomInfo Ddtodur1RomDesc[] = { + { "dadu.03a", 0x080000, 0x4413f177, 1 | BRF_ESS | BRF_PRG }, + { "dadu.04a", 0x080000, 0x168de230, 1 | BRF_ESS | BRF_PRG }, + { "dadu.05a", 0x080000, 0x03d39e91, 1 | BRF_ESS | BRF_PRG }, + { "dad.06", 0x080000, 0x13aa3e56, 1 | BRF_ESS | BRF_PRG }, + { "dad.07", 0x080000, 0x431cb6dd, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodur1) +STD_ROM_FN(Ddtodur1) + +static struct BurnRomInfo DimahooRomDesc[] = { + { "gmde.03", 0x080000, 0x968FCECD, 1 | BRF_ESS | BRF_PRG }, + { "gmd.04", 0x080000, 0x37485567, 1 | BRF_ESS | BRF_PRG }, + { "gmd.05", 0x080000, 0xDA269FFB, 1 | BRF_ESS | BRF_PRG }, + { "gmd.06", 0x080000, 0x55B483C9, 1 | BRF_ESS | BRF_PRG }, + + { "gmd.13m", 0x400000, 0x80DD19F0, 3 | BRF_GRA }, + { "gmd.15m", 0x400000, 0xDFD93A78, 3 | BRF_GRA }, + { "gmd.17m", 0x400000, 0x16356520, 3 | BRF_GRA }, + { "gmd.19m", 0x400000, 0xDFC33031, 3 | BRF_GRA }, + + { "gmd.01", 0x020000, 0x3F9BC985, 4 | BRF_ESS | BRF_PRG }, + { "gmd.02", 0x020000, 0x3FD39DDE, 4 | BRF_ESS | BRF_PRG }, + + { "gmd.11m", 0x400000, 0x06A65542, 5 | BRF_SND }, + { "gmd.12m", 0x400000, 0x50BC7A31, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dimahoo) +STD_ROM_FN(Dimahoo) + +static struct BurnRomInfo GmdjRomDesc[] = { + { "gmdj.03", 0x080000, 0xCD6979E3, 1 | BRF_ESS | BRF_PRG }, + { "gmd.04", 0x080000, 0x37485567, 1 | BRF_ESS | BRF_PRG }, + { "gmd.05", 0x080000, 0xDA269FFB, 1 | BRF_ESS | BRF_PRG }, + { "gmd.06", 0x080000, 0x55B483C9, 1 | BRF_ESS | BRF_PRG }, + + { "gmd.13m", 0x400000, 0x80DD19F0, 3 | BRF_GRA }, + { "gmd.15m", 0x400000, 0xDFD93A78, 3 | BRF_GRA }, + { "gmd.17m", 0x400000, 0x16356520, 3 | BRF_GRA }, + { "gmd.19m", 0x400000, 0xDFC33031, 3 | BRF_GRA }, + + { "gmd.01", 0x020000, 0x3F9BC985, 4 | BRF_ESS | BRF_PRG }, + { "gmd.02", 0x020000, 0x3FD39DDE, 4 | BRF_ESS | BRF_PRG }, + + { "gmd.11m", 0x400000, 0x06A65542, 5 | BRF_SND }, + { "gmd.12m", 0x400000, 0x50BC7A31, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gmdj) +STD_ROM_FN(Gmdj) + +static struct BurnRomInfo DimahoouRomDesc[] = { + { "gmdu.03", 0x080000, 0x43BCB15F, 1 | BRF_ESS | BRF_PRG }, + { "gmd.04", 0x080000, 0x37485567, 1 | BRF_ESS | BRF_PRG }, + { "gmd.05", 0x080000, 0xDA269FFB, 1 | BRF_ESS | BRF_PRG }, + { "gmd.06", 0x080000, 0x55B483C9, 1 | BRF_ESS | BRF_PRG }, + + { "gmd.13m", 0x400000, 0x80DD19F0, 3 | BRF_GRA }, + { "gmd.15m", 0x400000, 0xDFD93A78, 3 | BRF_GRA }, + { "gmd.17m", 0x400000, 0x16356520, 3 | BRF_GRA }, + { "gmd.19m", 0x400000, 0xDFC33031, 3 | BRF_GRA }, + + { "gmd.01", 0x020000, 0x3F9BC985, 4 | BRF_ESS | BRF_PRG }, + { "gmd.02", 0x020000, 0x3FD39DDE, 4 | BRF_ESS | BRF_PRG }, + + { "gmd.11m", 0x400000, 0x06A65542, 5 | BRF_SND }, + { "gmd.12m", 0x400000, 0x50BC7A31, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dimahoou) +STD_ROM_FN(Dimahoou) + +static struct BurnRomInfo DstlkRomDesc[] = { + { "vame.03a", 0x080000, 0x004c9cff, 1 | BRF_ESS | BRF_PRG }, + { "vame.04a", 0x080000, 0xae413ff2, 1 | BRF_ESS | BRF_PRG }, + { "vame.05a", 0x080000, 0x60678756, 1 | BRF_ESS | BRF_PRG }, + { "vame.06a", 0x080000, 0x912870b3, 1 | BRF_ESS | BRF_PRG }, + { "vame.07a", 0x080000, 0xdabae3e8, 1 | BRF_ESS | BRF_PRG }, + { "vame.08a", 0x080000, 0x2c6e3077, 1 | BRF_ESS | BRF_PRG }, + { "vame.09a", 0x080000, 0xf16db74b, 1 | BRF_ESS | BRF_PRG }, + { "vame.10a", 0x080000, 0x701e2147, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, + +}; + +STD_ROM_PICK(Dstlk) +STD_ROM_FN(Dstlk) + +static struct BurnRomInfo DstlkaRomDesc[] = { + { "vama.03a", 0x080000, 0x294e0bec, 1 | BRF_ESS | BRF_PRG }, + { "vama.04a", 0x080000, 0xbc18e128, 1 | BRF_ESS | BRF_PRG }, + { "vama.05a", 0x080000, 0xe709fa59, 1 | BRF_ESS | BRF_PRG }, + { "vama.06a", 0x080000, 0x55e4d387, 1 | BRF_ESS | BRF_PRG }, + { "vama.07a", 0x080000, 0x24e8f981, 1 | BRF_ESS | BRF_PRG }, + { "vama.08a", 0x080000, 0x743f3a8e, 1 | BRF_ESS | BRF_PRG }, + { "vama.09a", 0x080000, 0x67fa5573, 1 | BRF_ESS | BRF_PRG }, + { "vama.10a", 0x080000, 0x5e03d747, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dstlka) +STD_ROM_FN(Dstlka) + +static struct BurnRomInfo DstlkhRomDesc[] = { + { "vamh.03c", 0x080000, 0x4d7b9e8f, 1 | BRF_ESS | BRF_PRG }, + { "vamh.04c", 0x080000, 0x2217e9a0, 1 | BRF_ESS | BRF_PRG }, + { "vamh.05c", 0x080000, 0x3a05b13c, 1 | BRF_ESS | BRF_PRG }, + { "vamh.06c", 0x080000, 0x11d70a1c, 1 | BRF_ESS | BRF_PRG }, + { "vamh.07c", 0x080000, 0xdb5a8767, 1 | BRF_ESS | BRF_PRG }, + { "vamh.08c", 0x080000, 0x2a4fd79b, 1 | BRF_ESS | BRF_PRG }, + { "vamh.09c", 0x080000, 0x15187632, 1 | BRF_ESS | BRF_PRG }, + { "vamh.10c", 0x080000, 0x192d2d81, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dstlkh) +STD_ROM_FN(Dstlkh) + +static struct BurnRomInfo DstlkuRomDesc[] = { + { "vamu.03b", 0x080000, 0x68a6343f, 1 | BRF_ESS | BRF_PRG }, + { "vamu.04b", 0x080000, 0x58161453, 1 | BRF_ESS | BRF_PRG }, + { "vamu.05b", 0x080000, 0xdfc038b8, 1 | BRF_ESS | BRF_PRG }, + { "vamu.06b", 0x080000, 0xc3842c89, 1 | BRF_ESS | BRF_PRG }, + { "vamu.07b", 0x080000, 0x25b60b6e, 1 | BRF_ESS | BRF_PRG }, + { "vamu.08b", 0x080000, 0x2113c596, 1 | BRF_ESS | BRF_PRG }, + { "vamu.09b", 0x080000, 0x2d1e9ae5, 1 | BRF_ESS | BRF_PRG }, + { "vamu.10b", 0x080000, 0x81145622, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dstlku) +STD_ROM_FN(Dstlku) + +static struct BurnRomInfo Dstlkur1RomDesc[] = { + { "vamu.03a", 0x080000, 0x628899f9, 1 | BRF_ESS | BRF_PRG }, + { "vamu.04a", 0x080000, 0x696d9b25, 1 | BRF_ESS | BRF_PRG }, + { "vamu.05a", 0x080000, 0x673ed50a, 1 | BRF_ESS | BRF_PRG }, + { "vamu.06a", 0x080000, 0xf2377be7, 1 | BRF_ESS | BRF_PRG }, + { "vamu.07a", 0x080000, 0xd8f498c4, 1 | BRF_ESS | BRF_PRG }, + { "vamu.08a", 0x080000, 0xe6a8a1a0, 1 | BRF_ESS | BRF_PRG }, + { "vamu.09a", 0x080000, 0x8dd55b24, 1 | BRF_ESS | BRF_PRG }, + { "vamu.10a", 0x080000, 0xc1a3d9be, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dstlkur1) +STD_ROM_FN(Dstlkur1) + +static struct BurnRomInfo VampjRomDesc[] = { + { "vamj.03a", 0x080000, 0xf55d3722, 1 | BRF_ESS | BRF_PRG }, + { "vamj.04b", 0x080000, 0x4d9c43c4, 1 | BRF_ESS | BRF_PRG }, + { "vamj.05a", 0x080000, 0x6c497e92, 1 | BRF_ESS | BRF_PRG }, + { "vamj.06a", 0x080000, 0xf1bbecb6, 1 | BRF_ESS | BRF_PRG }, + { "vamj.07a", 0x080000, 0x1067ad84, 1 | BRF_ESS | BRF_PRG }, + { "vamj.08a", 0x080000, 0x4b89f41f, 1 | BRF_ESS | BRF_PRG }, + { "vamj.09a", 0x080000, 0xfc0a4aac, 1 | BRF_ESS | BRF_PRG }, + { "vamj.10a", 0x080000, 0x9270c26b, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, + +}; + +STD_ROM_PICK(Vampj) +STD_ROM_FN(Vampj) + +static struct BurnRomInfo VampjaRomDesc[] = { + { "vamj.03a", 0x080000, 0xf55d3722, 1 | BRF_ESS | BRF_PRG }, + { "vamj.04a", 0x080000, 0xfdcbdae3, 1 | BRF_ESS | BRF_PRG }, + { "vamj.05a", 0x080000, 0x6c497e92, 1 | BRF_ESS | BRF_PRG }, + { "vamj.06a", 0x080000, 0xf1bbecb6, 1 | BRF_ESS | BRF_PRG }, + { "vamj.07a", 0x080000, 0x1067ad84, 1 | BRF_ESS | BRF_PRG }, + { "vamj.08a", 0x080000, 0x4b89f41f, 1 | BRF_ESS | BRF_PRG }, + { "vamj.09a", 0x080000, 0xfc0a4aac, 1 | BRF_ESS | BRF_PRG }, + { "vamj.10a", 0x080000, 0x9270c26b, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vampja) +STD_ROM_FN(Vampja) + +static struct BurnRomInfo Vampjr1RomDesc[] = { + { "vamj.03", 0x080000, 0x8895bf77, 1 | BRF_ESS | BRF_PRG }, + { "vamj.04", 0x080000, 0x5027db3d, 1 | BRF_ESS | BRF_PRG }, + { "vamj.05", 0x080000, 0x97c66fdb, 1 | BRF_ESS | BRF_PRG }, + { "vamj.06", 0x080000, 0x9b4c3426, 1 | BRF_ESS | BRF_PRG }, + { "vamj.07", 0x080000, 0x303bc4fd, 1 | BRF_ESS | BRF_PRG }, + { "vamj.08", 0x080000, 0x3dea3646, 1 | BRF_ESS | BRF_PRG }, + { "vamj.09", 0x080000, 0xc119a827, 1 | BRF_ESS | BRF_PRG }, + { "vamj.10", 0x080000, 0x46593b79, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vampjr1) +STD_ROM_FN(Vampjr1) + +static struct BurnRomInfo EcofghtrRomDesc[] = { + { "uece.03", 0x080000, 0xec2c1137, 1 | BRF_ESS | BRF_PRG }, + { "uece.04", 0x080000, 0xb35f99db, 1 | BRF_ESS | BRF_PRG }, + { "uece.05", 0x080000, 0xd9d42d31, 1 | BRF_ESS | BRF_PRG }, + { "uece.06", 0x080000, 0x9d9771cf, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtr) +STD_ROM_FN(Ecofghtr) + +static struct BurnRomInfo EcofghtraRomDesc[] = { + { "ueca.03", 0x080000, 0xbd4589b1, 1 | BRF_ESS | BRF_PRG }, + { "ueca.04", 0x080000, 0x1d134b7d, 1 | BRF_ESS | BRF_PRG }, + { "ueca.05", 0x080000, 0x9c581fc7, 1 | BRF_ESS | BRF_PRG }, + { "ueca.06", 0x080000, 0xc92a7c50, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtra) +STD_ROM_FN(Ecofghtra) + +static struct BurnRomInfo EcofghtrhRomDesc[] = { + { "uech.03", 0x080000, 0x14c9365e, 1 | BRF_ESS | BRF_PRG }, + { "uech.04", 0x080000, 0x579495dc, 1 | BRF_ESS | BRF_PRG }, + { "uech.05", 0x080000, 0x96807a8e, 1 | BRF_ESS | BRF_PRG }, + { "uech.06", 0x080000, 0x682b9dbc, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtrh) +STD_ROM_FN(Ecofghtrh) + +static struct BurnRomInfo EcofghtruRomDesc[] = { + { "uecu.03a", 0x080000, 0x22d88a4d, 1 | BRF_ESS | BRF_PRG }, + { "uecu.04a", 0x080000, 0x6436cfcd, 1 | BRF_ESS | BRF_PRG }, + { "uecu.05a", 0x080000, 0x336f121b, 1 | BRF_ESS | BRF_PRG }, + { "uecu.06a", 0x080000, 0x6f99d984, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtru) +STD_ROM_FN(Ecofghtru) + +static struct BurnRomInfo Ecofghtru1RomDesc[] = { + { "uecu.03", 0x080000, 0x6792480c, 1 | BRF_ESS | BRF_PRG }, + { "uecu.04", 0x080000, 0x95ce69d5, 1 | BRF_ESS | BRF_PRG }, + { "uecu.05", 0x080000, 0x3a1e78ad, 1 | BRF_ESS | BRF_PRG }, + { "uecu.06", 0x080000, 0xa3e2f3cc, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtru1) +STD_ROM_FN(Ecofghtru1) + +static struct BurnRomInfo UecologyRomDesc[] = { + { "uecj.03", 0x080000, 0x94c40a4c, 1 | BRF_ESS | BRF_PRG }, + { "uecj.04", 0x080000, 0x8d6e3a09, 1 | BRF_ESS | BRF_PRG }, + { "uecj.05", 0x080000, 0x8604ecd7, 1 | BRF_ESS | BRF_PRG }, + { "uecj.06", 0x080000, 0xb7e1d31f, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Uecology) +STD_ROM_FN(Uecology) + +static struct BurnRomInfo GigawingRomDesc[] = { + { "ggwu.03", 0x080000, 0xac725eb2, 1 | BRF_ESS | BRF_PRG }, + { "ggwu.04", 0x080000, 0x392f4118, 1 | BRF_ESS | BRF_PRG }, + { "ggw.05", 0x080000, 0x3239d642, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawing) +STD_ROM_FN(Gigawing) + +static struct BurnRomInfo GigawingaRomDesc[] = { + { "ggwa.03a", 0x080000, 0x116f8837, 1 | BRF_ESS | BRF_PRG }, + { "ggwa.04a", 0x080000, 0xe6e3f0c4, 1 | BRF_ESS | BRF_PRG }, + { "ggwa.05a", 0x080000, 0x465e8ac9, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawinga) +STD_ROM_FN(Gigawinga) + +static struct BurnRomInfo GigawingbRomDesc[] = { + { "ggwb.03", 0x080000, 0xa1f8a448, 1 | BRF_ESS | BRF_PRG }, + { "ggwb.04", 0x080000, 0x6a423e76, 1 | BRF_ESS | BRF_PRG }, + { "ggw.05", 0x080000, 0x3239d642, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawingb) +STD_ROM_FN(Gigawingb) + +static struct BurnRomInfo GigawinghRomDesc[] = { + { "ggwh.03a", 0x080000, 0xb9ee36eb, 1 | BRF_ESS | BRF_PRG }, + { "ggwh.04a", 0x080000, 0x72e548fe, 1 | BRF_ESS | BRF_PRG }, + { "ggw.05", 0x080000, 0x3239d642, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawingh) +STD_ROM_FN(Gigawingh) + +static struct BurnRomInfo GigawingjRomDesc[] = { + { "ggwj.03a", 0x080000, 0xfdd23b91, 1 | BRF_ESS | BRF_PRG }, + { "ggwj.04a", 0x080000, 0x8c6e093c, 1 | BRF_ESS | BRF_PRG }, + { "ggwj.05a", 0x080000, 0x43811454, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawingj) +STD_ROM_FN(Gigawingj) + +static struct BurnRomInfo Hsf2RomDesc[] = { + { "hs2u.03", 0x080000, 0xb308151e, 1 | BRF_ESS | BRF_PRG }, + { "hs2u.04", 0x080000, 0x327aa49c, 1 | BRF_ESS | BRF_PRG }, + { "hs2.05", 0x080000, 0xdde34a35, 1 | BRF_ESS | BRF_PRG }, + { "hs2.06", 0x080000, 0xf4e56dda, 1 | BRF_ESS | BRF_PRG }, + { "hs2.07", 0x080000, 0xee4420fc, 1 | BRF_ESS | BRF_PRG }, + { "hs2.08", 0x080000, 0xc9441533, 1 | BRF_ESS | BRF_PRG }, + { "hs2.09", 0x080000, 0x3fc638a8, 1 | BRF_ESS | BRF_PRG }, + { "hs2.10", 0x080000, 0x20d0f9e4, 1 | BRF_ESS | BRF_PRG }, + + { "hs2.13m", 0x800000, 0xa6ecab17, 3 | BRF_GRA }, + { "hs2.15m", 0x800000, 0x10a0ae4d, 3 | BRF_GRA }, + { "hs2.17m", 0x800000, 0xadfa7726, 3 | BRF_GRA }, + { "hs2.19m", 0x800000, 0xbb3ae322, 3 | BRF_GRA }, + + { "hs2.01", 0x020000, 0xc1a13786, 4 | BRF_ESS | BRF_PRG }, + { "hs2.02", 0x020000, 0x2d8794aa, 4 | BRF_ESS | BRF_PRG }, + + { "hs2.11m", 0x800000, 0x0e15c359, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Hsf2) +STD_ROM_FN(Hsf2) + +static struct BurnRomInfo Hsf2aRomDesc[] = { + { "hs2a.03", 0x080000, 0xd50a17e0, 1 | BRF_ESS | BRF_PRG }, + { "hs2a.04", 0x080000, 0xa27f42de, 1 | BRF_ESS | BRF_PRG }, + { "hs2.05", 0x080000, 0xdde34a35, 1 | BRF_ESS | BRF_PRG }, + { "hs2.06", 0x080000, 0xf4e56dda, 1 | BRF_ESS | BRF_PRG }, + { "hs2.07", 0x080000, 0xee4420fc, 1 | BRF_ESS | BRF_PRG }, + { "hs2.08", 0x080000, 0xc9441533, 1 | BRF_ESS | BRF_PRG }, + { "hs2.09", 0x080000, 0x3fc638a8, 1 | BRF_ESS | BRF_PRG }, + { "hs2.10", 0x080000, 0x20d0f9e4, 1 | BRF_ESS | BRF_PRG }, + + { "hs2.13m", 0x800000, 0xa6ecab17, 3 | BRF_GRA }, + { "hs2.15m", 0x800000, 0x10a0ae4d, 3 | BRF_GRA }, + { "hs2.17m", 0x800000, 0xadfa7726, 3 | BRF_GRA }, + { "hs2.19m", 0x800000, 0xbb3ae322, 3 | BRF_GRA }, + + { "hs2.01", 0x020000, 0xc1a13786, 4 | BRF_ESS | BRF_PRG }, + { "hs2.02", 0x020000, 0x2d8794aa, 4 | BRF_ESS | BRF_PRG }, + + { "hs2.11m", 0x800000, 0x0e15c359, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Hsf2a) +STD_ROM_FN(Hsf2a) + +static struct BurnRomInfo Hsf2jRomDesc[] = { + { "hs2j.03", 0x080000, 0x00738f73, 1 | BRF_ESS | BRF_PRG }, + { "hs2j.04", 0x080000, 0x40072c4a, 1 | BRF_ESS | BRF_PRG }, + { "hs2.05", 0x080000, 0xdde34a35, 1 | BRF_ESS | BRF_PRG }, + { "hs2.06", 0x080000, 0xf4e56dda, 1 | BRF_ESS | BRF_PRG }, + { "hs2.07", 0x080000, 0xee4420fc, 1 | BRF_ESS | BRF_PRG }, + { "hs2.08", 0x080000, 0xc9441533, 1 | BRF_ESS | BRF_PRG }, + { "hs2.09", 0x080000, 0x3fc638a8, 1 | BRF_ESS | BRF_PRG }, + { "hs2.10", 0x080000, 0x20d0f9e4, 1 | BRF_ESS | BRF_PRG }, + + { "hs2.13m" , 0x800000, 0xa6ecab17, 3 | BRF_GRA }, + { "hs2.15m", 0x800000, 0x10a0ae4d, 3 | BRF_GRA }, + { "hs2.17m", 0x800000, 0xadfa7726, 3 | BRF_GRA }, + { "hs2.19m", 0x800000, 0xbb3ae322, 3 | BRF_GRA }, + + { "hs2.01", 0x020000, 0xc1a13786, 4 | BRF_ESS | BRF_PRG }, + { "hs2.02", 0x020000, 0x2d8794aa, 4 | BRF_ESS | BRF_PRG }, + + { "hs2.11m", 0x800000, 0x0e15c359, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Hsf2j) +STD_ROM_FN(Hsf2j) + +static struct BurnRomInfo JyangokuRomDesc[] = { + { "majj.03", 0x080000, 0x4614a3b2, 1 | BRF_ESS | BRF_PRG }, + + { "maj1_d.simm1", 0x200000, 0xba0fe27b, 11 | BRF_GRA }, + { "maj1_c.simm1", 0x200000, 0x2cd141bf, 11 | BRF_GRA }, + { "maj1_b.simm1", 0x200000, 0xe29e4c26, 11 | BRF_GRA }, + { "maj1_a.simm1", 0x200000, 0x7f68b88a, 11 | BRF_GRA }, + { "maj3_d.simm3", 0x200000, 0x3aaeb90b, 11 | BRF_GRA }, + { "maj3_c.simm3", 0x200000, 0x97894cea, 11 | BRF_GRA }, + { "maj3_b.simm3", 0x200000, 0xec737d9d, 11 | BRF_GRA }, + { "maj3_a.simm3", 0x200000, 0xc23b6f22, 11 | BRF_GRA }, + + { "maj.01", 0x020000, 0x1fe8c213, 4 | BRF_ESS | BRF_PRG }, + + { "maj5_a.simm5", 0x200000, 0x5ad9ee53, 15 | BRF_SND }, + { "maj5_b.simm5", 0x200000, 0xefb3dbfb, 15 | BRF_SND }, +}; + +STD_ROM_PICK(Jyangoku) +STD_ROM_FN(Jyangoku) + +static struct BurnRomInfo Megaman2RomDesc[] = { + { "rm2u.03", 0x080000, 0x8ffc2cd1, 1 | BRF_ESS | BRF_PRG }, + { "rm2u.04", 0x080000, 0xbb30083a, 1 | BRF_ESS | BRF_PRG }, + { "rm2.05", 0x080000, 0x02ee9efc, 1 | BRF_ESS | BRF_PRG }, + + { "rm2.14m", 0x200000, 0x9b1f00b4, 3 | BRF_GRA }, + { "rm2.16m", 0x200000, 0xc2bb0c24, 3 | BRF_GRA }, + { "rm2.18m", 0x200000, 0x12257251, 3 | BRF_GRA }, + { "rm2.20m", 0x200000, 0xf9b6e786, 3 | BRF_GRA }, + + { "rm2.01a", 0x020000, 0xd18e7859, 4 | BRF_ESS | BRF_PRG }, + { "rm2.02", 0x020000, 0xc463ece0, 4 | BRF_ESS | BRF_PRG }, + + { "rm2.11m", 0x200000, 0x2106174d, 5 | BRF_SND }, + { "rm2.12m", 0x200000, 0x546c1636, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Megaman2) +STD_ROM_FN(Megaman2) + +static struct BurnRomInfo Megaman2aRomDesc[] = { + { "rm2a.03", 0x080000, 0x2b330ca7, 1 | BRF_ESS | BRF_PRG }, + { "rm2a.04", 0x080000, 0x8b47942b, 1 | BRF_ESS | BRF_PRG }, + { "rm2.05", 0x080000, 0x02ee9efc, 1 | BRF_ESS | BRF_PRG }, + + { "rm2.14m", 0x200000, 0x9b1f00b4, 3 | BRF_GRA }, + { "rm2.16m", 0x200000, 0xc2bb0c24, 3 | BRF_GRA }, + { "rm2.18m", 0x200000, 0x12257251, 3 | BRF_GRA }, + { "rm2.20m", 0x200000, 0xf9b6e786, 3 | BRF_GRA }, + + { "rm2.01a", 0x020000, 0xd18e7859, 4 | BRF_ESS | BRF_PRG }, + { "rm2.02", 0x020000, 0xc463ece0, 4 | BRF_ESS | BRF_PRG }, + + { "rm2.11m", 0x200000, 0x2106174d, 5 | BRF_SND }, + { "rm2.12m", 0x200000, 0x546c1636, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Megaman2a) +STD_ROM_FN(Megaman2a) + +static struct BurnRomInfo Megaman2hRomDesc[] = { + { "rm2h.03", 0x080000, 0xbb180378, 1 | BRF_ESS | BRF_PRG }, + { "rm2h.04", 0x080000, 0x205ffcd6, 1 | BRF_ESS | BRF_PRG }, + { "rm2.05", 0x080000, 0x02ee9efc, 1 | BRF_ESS | BRF_PRG }, + + { "rm2.14m", 0x200000, 0x9b1f00b4, 3 | BRF_GRA }, + { "rm2.16m", 0x200000, 0xc2bb0c24, 3 | BRF_GRA }, + { "rm2.18m", 0x200000, 0x12257251, 3 | BRF_GRA }, + { "rm2.20m", 0x200000, 0xf9b6e786, 3 | BRF_GRA }, + + { "rm2.01a", 0x020000, 0xd18e7859, 4 | BRF_ESS | BRF_PRG }, + { "rm2.02", 0x020000, 0xc463ece0, 4 | BRF_ESS | BRF_PRG }, + + { "rm2.11m", 0x200000, 0x2106174d, 5 | BRF_SND }, + { "rm2.12m", 0x200000, 0x546c1636, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Megaman2h) +STD_ROM_FN(Megaman2h) + +static struct BurnRomInfo Rockman2jRomDesc[] = { + { "rm2j.03", 0x080000, 0xdbaa1437, 1 | BRF_ESS | BRF_PRG }, + { "rm2j.04", 0x080000, 0xcf5ba612, 1 | BRF_ESS | BRF_PRG }, + { "rm2.05", 0x080000, 0x02ee9efc, 1 | BRF_ESS | BRF_PRG }, + + { "rm2.14m", 0x200000, 0x9b1f00b4, 3 | BRF_GRA }, + { "rm2.16m", 0x200000, 0xc2bb0c24, 3 | BRF_GRA }, + { "rm2.18m", 0x200000, 0x12257251, 3 | BRF_GRA }, + { "rm2.20m", 0x200000, 0xf9b6e786, 3 | BRF_GRA }, + + { "rm2.01a", 0x020000, 0xd18e7859, 4 | BRF_ESS | BRF_PRG }, + { "rm2.02", 0x020000, 0xc463ece0, 4 | BRF_ESS | BRF_PRG }, + + { "rm2.11m", 0x200000, 0x2106174d, 5 | BRF_SND }, + { "rm2.12m", 0x200000, 0x546c1636, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Rockman2j) +STD_ROM_FN(Rockman2j) + +static struct BurnRomInfo Mmancp2uRomDesc[] = { + { "rcmu.03b", 0x080000, 0xc39f037f, 1 | BRF_ESS | BRF_PRG }, + { "rcmu.04b", 0x080000, 0xcd6f5e99, 1 | BRF_ESS | BRF_PRG }, + { "rcm.05b", 0x080000, 0x4376ea95, 1 | BRF_ESS | BRF_PRG }, + + { "rcm.73", 0x080000, 0x774c6e04, 3 | BRF_GRA }, + { "rcm.63", 0x080000, 0xacad7c62, 3 | BRF_GRA }, + { "rcm.83", 0x080000, 0x6af30499, 3 | BRF_GRA }, + { "rcm.93", 0x080000, 0x7a5a5166, 3 | BRF_GRA }, + { "rcm.74", 0x080000, 0x004ec725, 3 | BRF_GRA }, + { "rcm.64", 0x080000, 0x65c0464e, 3 | BRF_GRA }, + { "rcm.84", 0x080000, 0xfb3097cc, 3 | BRF_GRA }, + { "rcm.94", 0x080000, 0x2e16557a, 3 | BRF_GRA }, + { "rcm.75", 0x080000, 0x70a73f99, 3 | BRF_GRA }, + { "rcm.65", 0x080000, 0xecedad3d, 3 | BRF_GRA }, + { "rcm.85", 0x080000, 0x3d6186d8, 3 | BRF_GRA }, + { "rcm.95", 0x080000, 0x8c7700f1, 3 | BRF_GRA }, + { "rcm.76", 0x080000, 0x89a889ad, 3 | BRF_GRA }, + { "rcm.66", 0x080000, 0x1300eb7b, 3 | BRF_GRA }, + { "rcm.86", 0x080000, 0x6d974ebd, 3 | BRF_GRA }, + { "rcm.96", 0x080000, 0x7da4cd24, 3 | BRF_GRA }, + + { "rcm.01", 0x020000, 0xd60cf8a3, 4 | BRF_ESS | BRF_PRG }, + + { "rcm.51", 0x080000, 0xb6d07080, 5 | BRF_SND }, + { "rcm.52", 0x080000, 0xdfddc493, 5 | BRF_SND }, + { "rcm.53", 0x080000, 0x6062ae3a, 5 | BRF_SND }, + { "rcm.54", 0x080000, 0x08c6f3bf, 5 | BRF_SND }, + { "rcm.55", 0x080000, 0xf97dfccc, 5 | BRF_SND }, + { "rcm.56", 0x080000, 0xade475bc, 5 | BRF_SND }, + { "rcm.57", 0x080000, 0x075effb3, 5 | BRF_SND }, + { "rcm.58", 0x080000, 0xf6c1f87b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mmancp2u) +STD_ROM_FN(Mmancp2u) + +static struct BurnRomInfo Rmancp2jRomDesc[] = { + { "rcmj.03a", 0x080000, 0x30559f60, 1 | BRF_ESS | BRF_PRG }, + { "rcmj.04a", 0x080000, 0x5efc9366, 1 | BRF_ESS | BRF_PRG }, + { "rcm.05a", 0x080000, 0x517ccde2, 1 | BRF_ESS | BRF_PRG }, + + { "rcm.73", 0x080000, 0x774c6e04, 3 | BRF_GRA }, + { "rcm.63", 0x080000, 0xacad7c62, 3 | BRF_GRA }, + { "rcm.83", 0x080000, 0x6af30499, 3 | BRF_GRA }, + { "rcm.93", 0x080000, 0x7a5a5166, 3 | BRF_GRA }, + { "rcm.74", 0x080000, 0x004ec725, 3 | BRF_GRA }, + { "rcm.64", 0x080000, 0x65c0464e, 3 | BRF_GRA }, + { "rcm.84", 0x080000, 0xfb3097cc, 3 | BRF_GRA }, + { "rcm.94", 0x080000, 0x2e16557a, 3 | BRF_GRA }, + { "rcm.75", 0x080000, 0x70a73f99, 3 | BRF_GRA }, + { "rcm.65", 0x080000, 0xecedad3d, 3 | BRF_GRA }, + { "rcm.85", 0x080000, 0x3d6186d8, 3 | BRF_GRA }, + { "rcm.95", 0x080000, 0x8c7700f1, 3 | BRF_GRA }, + { "rcm.76", 0x080000, 0x89a889ad, 3 | BRF_GRA }, + { "rcm.66", 0x080000, 0x1300eb7b, 3 | BRF_GRA }, + { "rcm.86", 0x080000, 0x6d974ebd, 3 | BRF_GRA }, + { "rcm.96", 0x080000, 0x7da4cd24, 3 | BRF_GRA }, + + { "rcm.01", 0x020000, 0xd60cf8a3, 4 | BRF_ESS | BRF_PRG }, + + { "rcm.51", 0x080000, 0xb6d07080, 5 | BRF_SND }, + { "rcm.52", 0x080000, 0xdfddc493, 5 | BRF_SND }, + { "rcm.53", 0x080000, 0x6062ae3a, 5 | BRF_SND }, + { "rcm.54", 0x080000, 0x08c6f3bf, 5 | BRF_SND }, + { "rcm.55", 0x080000, 0xf97dfccc, 5 | BRF_SND }, + { "rcm.56", 0x080000, 0xade475bc, 5 | BRF_SND }, + { "rcm.57", 0x080000, 0x075effb3, 5 | BRF_SND }, + { "rcm.58", 0x080000, 0xf6c1f87b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Rmancp2j) +STD_ROM_FN(Rmancp2j) + +static struct BurnRomInfo MmatrixRomDesc[] = { + { "mmxu.03", 0x080000, 0xAB65b599, 1 | BRF_ESS | BRF_PRG }, + { "mmxu.04", 0x080000, 0x0135FC6C, 1 | BRF_ESS | BRF_PRG }, + { "mmxu.05", 0x080000, 0xF1FD2B84, 1 | BRF_ESS | BRF_PRG }, + + { "mmx.13m", 0x400000, 0x04748718, 3 | BRF_GRA }, + { "mmx.15m", 0x400000, 0x38074F44, 3 | BRF_GRA }, + { "mmx.17m", 0x400000, 0xE4635E35, 3 | BRF_GRA }, + { "mmx.19m", 0x400000, 0x4400A3F2, 3 | BRF_GRA }, + { "mmx.14m", 0x400000, 0xD52BF491, 3 | BRF_GRA }, + { "mmx.16m", 0x400000, 0x23F70780, 3 | BRF_GRA }, + { "mmx.18m", 0x400000, 0x2562C9D5, 3 | BRF_GRA }, + { "mmx.20m", 0x400000, 0x583A9687, 3 | BRF_GRA }, + + { "mmx.01", 0x020000, 0xC57E8171, 4 | BRF_ESS | BRF_PRG }, + + { "mmx.11m", 0x400000, 0x4180B39F, 5 | BRF_SND }, + { "mmx.12m", 0x400000, 0x95E22A59, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mmatrix) +STD_ROM_FN(Mmatrix) + +static struct BurnRomInfo MmatrixjRomDesc[] = { + { "mmxj.03", 0x080000, 0x1D5DE213, 1 | BRF_ESS | BRF_PRG }, + { "mmxj.04", 0x080000, 0xD943A339, 1 | BRF_ESS | BRF_PRG }, + { "mmxj.05", 0x080000, 0x0C8B4ABB, 1 | BRF_ESS | BRF_PRG }, + + { "mmx.13m", 0x400000, 0x04748718, 3 | BRF_GRA }, + { "mmx.15m", 0x400000, 0x38074F44, 3 | BRF_GRA }, + { "mmx.17m", 0x400000, 0xE4635E35, 3 | BRF_GRA }, + { "mmx.19m", 0x400000, 0x4400A3F2, 3 | BRF_GRA }, + { "mmx.14m", 0x400000, 0xD52BF491, 3 | BRF_GRA }, + { "mmx.16m", 0x400000, 0x23F70780, 3 | BRF_GRA }, + { "mmx.18m", 0x400000, 0x2562C9D5, 3 | BRF_GRA }, + { "mmx.20m", 0x400000, 0x583A9687, 3 | BRF_GRA }, + + { "mmx.01", 0x020000, 0xC57E8171, 4 | BRF_ESS | BRF_PRG }, + + { "mmx.11m", 0x400000, 0x4180B39F, 5 | BRF_SND }, + { "mmx.12m", 0x400000, 0x95E22A59, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mmatrixj) +STD_ROM_FN(Mmatrixj) + +static struct BurnRomInfo MpangRomDesc[] = { + { "mpne.03c", 0x080000, 0xfe16fc9f, 1 | BRF_ESS | BRF_PRG }, + { "mpne.04c", 0x080000, 0x2cc5ec22, 1 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.01c", 0x200000, 0x388DB66B, 11 | BRF_GRA }, + { "mpn-simm.01d", 0x200000, 0xAFF1B494, 11 | BRF_GRA }, + { "mpn-simm.01a", 0x200000, 0xA9C4857B, 11 | BRF_GRA }, + { "mpn-simm.01b", 0x200000, 0xF759DF22, 11 | BRF_GRA }, + { "mpn-simm.03c", 0x200000, 0xDEC6B720, 11 | BRF_GRA }, + { "mpn-simm.03d", 0x200000, 0xF8774C18, 11 | BRF_GRA }, + { "mpn-simm.03a", 0x200000, 0xC2AEA4EC, 11 | BRF_GRA }, + { "mpn-simm.03b", 0x200000, 0x84D6DC33, 11 | BRF_GRA }, + + { "mpn.01", 0x020000, 0x90C7ADB6, 4 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.05a", 0x200000, 0x318A2E21, 13 | BRF_SND }, + { "mpn-simm.05b", 0x200000, 0x5462F4E8, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Mpang) +STD_ROM_FN(Mpang) + +static struct BurnRomInfo Mpangr1RomDesc[] = { + { "mpne.03b", 0x080000, 0x6ef0f9b2, 1 | BRF_ESS | BRF_PRG }, + { "mpne.04b", 0x080000, 0x30a468bb, 1 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.01c", 0x200000, 0x388DB66B, 11 | BRF_GRA }, + { "mpn-simm.01d", 0x200000, 0xAFF1B494, 11 | BRF_GRA }, + { "mpn-simm.01a", 0x200000, 0xA9C4857B, 11 | BRF_GRA }, + { "mpn-simm.01b", 0x200000, 0xF759DF22, 11 | BRF_GRA }, + { "mpn-simm.03c", 0x200000, 0xDEC6B720, 11 | BRF_GRA }, + { "mpn-simm.03d", 0x200000, 0xF8774C18, 11 | BRF_GRA }, + { "mpn-simm.03a", 0x200000, 0xC2AEA4EC, 11 | BRF_GRA }, + { "mpn-simm.03b", 0x200000, 0x84D6DC33, 11 | BRF_GRA }, + + { "mpn.01", 0x020000, 0x90C7ADB6, 4 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.05a", 0x200000, 0x318A2E21, 13 | BRF_SND }, + { "mpn-simm.05b", 0x200000, 0x5462F4E8, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Mpangr1) +STD_ROM_FN(Mpangr1) + +static struct BurnRomInfo MpanguRomDesc[] = { + { "mpnu.03", 0x080000, 0x6e7ed03c, 1 | BRF_ESS | BRF_PRG }, + { "mpnu.04", 0x080000, 0xde079131, 1 | BRF_ESS | BRF_PRG }, + + { "mpn.13m", 0x200000, 0xc5f123dc, 3 | BRF_GRA }, + { "mpn.15m", 0x200000, 0x8e033265, 3 | BRF_GRA }, + { "mpn.17m", 0x200000, 0xcfcd73d2, 3 | BRF_GRA }, + { "mpn.19m", 0x200000, 0x2db1ffbc, 3 | BRF_GRA }, + + { "mpn.01", 0x020000, 0x90C7ADB6, 4 | BRF_ESS | BRF_PRG }, + + { "mpn.q1", 0x100000, 0xd21c1f5a, 5 | BRF_SND }, + { "mpn.q2", 0x100000, 0xd22090b1, 5 | BRF_SND }, + { "mpn.q3", 0x100000, 0x60aa5ef2, 5 | BRF_SND }, + { "mpn.q4", 0x100000, 0x3a67d203, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mpangu) +STD_ROM_FN(Mpangu) + +static struct BurnRomInfo MpangjRomDesc[] = { + { "mpnj.03a", 0x080000, 0xBF597b1C, 1 | BRF_ESS | BRF_PRG }, + { "mpnj.04a", 0x080000, 0xF4A3AB0F, 1 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.01c", 0x200000, 0x388DB66B, 11 | BRF_GRA }, + { "mpn-simm.01d", 0x200000, 0xAFF1B494, 11 | BRF_GRA }, + { "mpn-simm.01a", 0x200000, 0xA9C4857B, 11 | BRF_GRA }, + { "mpn-simm.01b", 0x200000, 0xF759DF22, 11 | BRF_GRA }, + { "mpn-simm.03c", 0x200000, 0xDEC6B720, 11 | BRF_GRA }, + { "mpn-simm.03d", 0x200000, 0xF8774C18, 11 | BRF_GRA }, + { "mpn-simm.03a", 0x200000, 0xC2AEA4EC, 11 | BRF_GRA }, + { "mpn-simm.03b", 0x200000, 0x84D6DC33, 11 | BRF_GRA }, + + { "mpn.01", 0x020000, 0x90C7ADB6, 4 | BRF_ESS | BRF_PRG }, + + { "mpn-simm.05a", 0x200000, 0x318A2E21, 13 | BRF_SND }, + { "mpn-simm.05b", 0x200000, 0x5462F4E8, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Mpangj) +STD_ROM_FN(Mpangj) + +static struct BurnRomInfo MshRomDesc[] = { + { "mshe.03e", 0x080000, 0xbd951414, 1 | BRF_ESS | BRF_PRG }, + { "mshe.04e", 0x080000, 0x19dd42f2, 1 | BRF_ESS | BRF_PRG }, + { "msh.05", 0x080000, 0x6a091b9e, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Msh) +STD_ROM_FN(Msh) + +static struct BurnRomInfo MshaRomDesc[] = { + { "msha.03e", 0x080000, 0xec84ec44, 1 | BRF_ESS | BRF_PRG }, + { "msha.04e", 0x080000, 0x098b8503, 1 | BRF_ESS | BRF_PRG }, + { "msh.05", 0x080000, 0x6a091b9e, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Msha) +STD_ROM_FN(Msha) + +static struct BurnRomInfo MshbRomDesc[] = { + { "mshb.03c", 0x080000, 0x19697f74, 1 | BRF_ESS | BRF_PRG }, + { "mshb.04c", 0x080000, 0x95317a6f, 1 | BRF_ESS | BRF_PRG }, + { "msh.05a", 0x080000, 0xf37539e6, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshb) +STD_ROM_FN(Mshb) + +static struct BurnRomInfo MshhRomDesc[] = { + { "mshh.03c", 0x080000, 0x8d84b0fa, 1 | BRF_ESS | BRF_PRG }, + { "mshh.04c", 0x080000, 0xd638f601, 1 | BRF_ESS | BRF_PRG }, + { "msh.05a", 0x080000, 0xf37539e6, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshh) +STD_ROM_FN(Mshh) + +static struct BurnRomInfo MshjRomDesc[] = { + { "mshj.03g", 0x080000, 0x261f4091, 1 | BRF_ESS | BRF_PRG }, + { "mshj.04g", 0x080000, 0x61d791c6, 1 | BRF_ESS | BRF_PRG }, + { "msh.05a", 0x080000, 0xf37539e6, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshj) +STD_ROM_FN(Mshj) + +static struct BurnRomInfo Mshjr1RomDesc[] = { + { "mshj.03f", 0x080000, 0xff172fd2, 1 | BRF_ESS | BRF_PRG }, + { "mshj.04f", 0x080000, 0xebbb205a, 1 | BRF_ESS | BRF_PRG }, + { "msh.05", 0x080000, 0x6a091b9e, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshjr1) +STD_ROM_FN(Mshjr1) + +static struct BurnRomInfo MshuRomDesc[] = { + { "mshu.03", 0x080000, 0xd2805bdd, 1 | BRF_ESS | BRF_PRG }, + { "mshu.04", 0x080000, 0x743f96ff, 1 | BRF_ESS | BRF_PRG }, + { "msh.05", 0x080000, 0x6a091b9e, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshu) +STD_ROM_FN(Mshu) + +static struct BurnRomInfo MshvsfRomDesc[] = { + { "mvse.03f", 0x080000, 0xb72dc199, 1 | BRF_ESS | BRF_PRG }, + { "mvse.04f", 0x080000, 0x6ef799f9, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsf) +STD_ROM_FN(Mshvsf) + +static struct BurnRomInfo MshvsfhRomDesc[] = { + { "mvsh.03f", 0x080000, 0x4f60f41e, 1 | BRF_ESS | BRF_PRG }, + { "mvsh.04f", 0x080000, 0xdc08ec12, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfh) +STD_ROM_FN(Mshvsfh) + +static struct BurnRomInfo MshvsfaRomDesc[] = { + { "mvsa.03f", 0x080000, 0x5b863716, 1 | BRF_ESS | BRF_PRG }, + { "mvsa.04f", 0x080000, 0x4886e65f, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfa) +STD_ROM_FN(Mshvsfa) + +static struct BurnRomInfo Mshvsfa1RomDesc[] = { + { "mvsa.03", 0x080000, 0x92ef1933, 1 | BRF_ESS | BRF_PRG }, + { "mvsa.04", 0x080000, 0x4b24373c, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05", 0x080000, 0xac180c1c, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfa1) +STD_ROM_FN(Mshvsfa1) + +static struct BurnRomInfo MshvsfbRomDesc[] = { + { "mvsb.03g", 0x080000, 0x143895ef, 1 | BRF_ESS | BRF_PRG }, + { "mvsb.04g", 0x080000, 0xdd8a886c, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05d", 0x080000, 0x921fc542, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfb) +STD_ROM_FN(Mshvsfb) + +static struct BurnRomInfo Mshvsfb1RomDesc[] = { + { "mvsb.03f", 0x080000, 0x9c4bb950, 1 | BRF_ESS | BRF_PRG }, + { "mvsb.04f", 0x080000, 0xd3320d13, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfb1) +STD_ROM_FN(Mshvsfb1) + +static struct BurnRomInfo MshvsfjRomDesc[] = { + { "mvsj.03i", 0x080000, 0xd8cbb691, 1 | BRF_ESS | BRF_PRG }, + { "mvsj.04i", 0x080000, 0x32741ace, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05h", 0x080000, 0x77870dc3, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfj) +STD_ROM_FN(Mshvsfj) + +static struct BurnRomInfo Mshvsfj1RomDesc[] = { + { "mvsj.03h", 0x080000, 0xfbe2115f, 1 | BRF_ESS | BRF_PRG }, + { "mvsj.04h", 0x080000, 0xb528a367, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05g", 0x080000, 0x9515a245, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfj1) +STD_ROM_FN(Mshvsfj1) + +static struct BurnRomInfo Mshvsfj2RomDesc[] = { + { "mvsj.03g", 0x080000, 0xfdfa7e26, 1 | BRF_ESS | BRF_PRG }, + { "mvsj.04g", 0x080000, 0xc921825f, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfj2) +STD_ROM_FN(Mshvsfj2) + +static struct BurnRomInfo MshvsfuRomDesc[] = { + { "mvsu.03g", 0x080000, 0x0664ab15, 1 | BRF_ESS | BRF_PRG }, + { "mvsu.04g", 0x080000, 0x97e060ee, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05d", 0x080000, 0x921fc542, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfu) +STD_ROM_FN(Mshvsfu) + +static struct BurnRomInfo Mshvsfu1RomDesc[] = { + { "mvsu.03d", 0x080000, 0xae60a66a, 1 | BRF_ESS | BRF_PRG }, + { "mvsu.04d", 0x080000, 0x91f67d8a, 1 | BRF_ESS | BRF_PRG }, + { "mvs.05a", 0x080000, 0x1a5de0cb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfu1) +STD_ROM_FN(Mshvsfu1) + +static struct BurnRomInfo MvscRomDesc[] = { + { "mvce.03a", 0x080000, 0x824e4a90, 1 | BRF_ESS | BRF_PRG }, + { "mvce.04a", 0x080000, 0x436c5a4e, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvsc) +STD_ROM_FN(Mvsc) + +static struct BurnRomInfo Mvscr1RomDesc[] = { + { "mvce.03", 0x080000, 0xe0633fc0, 1 | BRF_ESS | BRF_PRG }, + { "mvce.04", 0x080000, 0xa450a251, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05", 0x080000, 0x7db71ce9, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06", 0x080000, 0x4b0b6d3e, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscr1) +STD_ROM_FN(Mvscr1) + +static struct BurnRomInfo MvscaRomDesc[] = { + { "mvca.03a", 0x080000, 0x2ff4ae25, 1 | BRF_ESS | BRF_PRG }, + { "mvca.04a", 0x080000, 0xf28427ef, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvsca) +STD_ROM_FN(Mvsca) + +static struct BurnRomInfo Mvscar1RomDesc[] = { + { "mvca.03", 0x080000, 0xfe5fa7b9, 1 | BRF_ESS | BRF_PRG }, + { "mvca.04", 0x080000, 0x082b701c, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05", 0x080000, 0x7db71ce9, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06", 0x080000, 0x4b0b6d3e, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscar1) +STD_ROM_FN(Mvscar1) + +static struct BurnRomInfo MvscbRomDesc[] = { + { "mvcb.03a", 0x080000, 0x7155953b, 1 | BRF_ESS | BRF_PRG }, + { "mvcb.04a", 0x080000, 0xfb117d0e, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscb) +STD_ROM_FN(Mvscb) + +static struct BurnRomInfo MvschRomDesc[] = { + { "mvch.03", 0x080000, 0x6a0ec9f7, 1 | BRF_ESS | BRF_PRG }, + { "mvch.04", 0x080000, 0x00f03fa4, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvsch) +STD_ROM_FN(Mvsch) + +static struct BurnRomInfo MvscjRomDesc[] = { + { "mvcj.03a", 0x080000, 0x3df18879, 1 | BRF_ESS | BRF_PRG }, + { "mvcj.04a", 0x080000, 0x07d212e8, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscj) +STD_ROM_FN(Mvscj) + +static struct BurnRomInfo Mvscjr1RomDesc[] = { + { "mvcj.03", 0x080000, 0x2164213f, 1 | BRF_ESS | BRF_PRG }, + { "mvcj.04", 0x080000, 0xc905c86f, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05", 0x080000, 0x7db71ce9, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06", 0x080000, 0x4b0b6d3e, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscjr1) +STD_ROM_FN(Mvscjr1) + +static struct BurnRomInfo MvscuRomDesc[] = { + { "mvcu.03d", 0x080000, 0xc6007557, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.04d", 0x080000, 0x724b2b20, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvc.07", 0x080000, 0xc3baa32b, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscu) +STD_ROM_FN(Mvscu) + +static struct BurnRomInfo Mvscur1RomDesc[] = { + { "mvcu.03", 0x080000, 0x13f2be57, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.04", 0x080000, 0x5e9b380d, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.05", 0x080000, 0x12f321be, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.06", 0x080000, 0x2f1524bc, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.07", 0x080000, 0x5fdecadb, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvcu.10", 0x080000, 0x4f36cd63, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscur1) +STD_ROM_FN(Mvscur1) + +static struct BurnRomInfo NwarrRomDesc[] = { + { "vphe.03f", 0x080000, 0xa922c44f, 1 | BRF_ESS | BRF_PRG }, + { "vphe.04c", 0x080000, 0x7312d890, 1 | BRF_ESS | BRF_PRG }, + { "vphe.05d", 0x080000, 0xcde8b506, 1 | BRF_ESS | BRF_PRG }, + { "vphe.06c", 0x080000, 0xbe99e7d0, 1 | BRF_ESS | BRF_PRG }, + { "vphe.07b", 0x080000, 0x69e0e60c, 1 | BRF_ESS | BRF_PRG }, + { "vphe.08b", 0x080000, 0xd95a3849, 1 | BRF_ESS | BRF_PRG }, + { "vphe.09b", 0x080000, 0x9882561c, 1 | BRF_ESS | BRF_PRG }, + { "vphe.10b", 0x080000, 0x976fa62f, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarr) +STD_ROM_FN(Nwarr) + +static struct BurnRomInfo NwarraRomDesc[] = { + { "vpha.03b", 0x080000, 0x0a70cdd6, 1 | BRF_ESS | BRF_PRG }, + { "vpha.04b", 0x080000, 0x70ce62e4, 1 | BRF_ESS | BRF_PRG }, + { "vpha.05b", 0x080000, 0x5692a03f, 1 | BRF_ESS | BRF_PRG }, + { "vpha.06b", 0x080000, 0xb810fe66, 1 | BRF_ESS | BRF_PRG }, + { "vpha.07b", 0x080000, 0x1be264f3, 1 | BRF_ESS | BRF_PRG }, + { "vpha.08b", 0x080000, 0x86f1ed52, 1 | BRF_ESS | BRF_PRG }, + { "vpha.09b", 0x080000, 0x7e96bd0a, 1 | BRF_ESS | BRF_PRG }, + { "vpha.10b", 0x080000, 0x58bce2fd, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarra) +STD_ROM_FN(Nwarra) + +static struct BurnRomInfo NwarrbRomDesc[] = { + { "vphb.03d", 0x080000, 0x3a426d3f, 1 | BRF_ESS | BRF_PRG }, + { "vphb.04a", 0x080000, 0x51c4bb2f, 1 | BRF_ESS | BRF_PRG }, + { "vphb.05c", 0x080000, 0xac44d997, 1 | BRF_ESS | BRF_PRG }, + { "vphb.06a", 0x080000, 0x5072a5fe, 1 | BRF_ESS | BRF_PRG }, + { "vphb.07", 0x080000, 0x9b355192, 1 | BRF_ESS | BRF_PRG }, + { "vphb.08", 0x080000, 0x42220f84, 1 | BRF_ESS | BRF_PRG }, + { "vphb.09", 0x080000, 0x029e015d, 1 | BRF_ESS | BRF_PRG }, + { "vphb.10", 0x080000, 0x37b3ce37, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarrb) +STD_ROM_FN(Nwarrb) + +static struct BurnRomInfo NwarrhRomDesc[] = { + { "vphh.03d", 0x080000, 0x6029c7be, 1 | BRF_ESS | BRF_PRG }, + { "vphh.04a", 0x080000, 0xd26625ee, 1 | BRF_ESS | BRF_PRG }, + { "vphh.05c", 0x080000, 0x73ee0b8a, 1 | BRF_ESS | BRF_PRG }, + { "vphh.06a", 0x080000, 0xa5b3a50a, 1 | BRF_ESS | BRF_PRG }, + { "vphh.07", 0x080000, 0x5fc2bdc1, 1 | BRF_ESS | BRF_PRG }, + { "vphh.08", 0x080000, 0xe65588d9, 1 | BRF_ESS | BRF_PRG }, + { "vphh.09", 0x080000, 0xa2ce6d63, 1 | BRF_ESS | BRF_PRG }, + { "vphh.10", 0x080000, 0xe2f4f4b9, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarrh) +STD_ROM_FN(Nwarrh) + +static struct BurnRomInfo NwarruRomDesc[] = { + { "vphu.03f", 0x080000, 0x85d6a359, 1 | BRF_ESS | BRF_PRG }, + { "vphu.04c", 0x080000, 0xcb7fce77, 1 | BRF_ESS | BRF_PRG }, + { "vphu.05e", 0x080000, 0xe08f2bba, 1 | BRF_ESS | BRF_PRG }, + { "vphu.06c", 0x080000, 0x08c04cdb, 1 | BRF_ESS | BRF_PRG }, + { "vphu.07b", 0x080000, 0xb5a5ab19, 1 | BRF_ESS | BRF_PRG }, + { "vphu.08b", 0x080000, 0x51bb20fb, 1 | BRF_ESS | BRF_PRG }, + { "vphu.09b", 0x080000, 0x41a64205, 1 | BRF_ESS | BRF_PRG }, + { "vphu.10b", 0x080000, 0x2b1d43ae, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarru) +STD_ROM_FN(Nwarru) + +static struct BurnRomInfo VhuntjRomDesc[] = { + { "vphj.03f", 0x080000, 0x3de2e333, 1 | BRF_ESS | BRF_PRG }, + { "vphj.04c", 0x080000, 0xc95cf304, 1 | BRF_ESS | BRF_PRG }, + { "vphj.05d", 0x080000, 0x50de5ddd, 1 | BRF_ESS | BRF_PRG }, + { "vphj.06c", 0x080000, 0xac3bd3d5, 1 | BRF_ESS | BRF_PRG }, + { "vphj.07b", 0x080000, 0x0761309f, 1 | BRF_ESS | BRF_PRG }, + { "vphj.08b", 0x080000, 0x5a5c2bf5, 1 | BRF_ESS | BRF_PRG }, + { "vphj.09b", 0x080000, 0x823d6d99, 1 | BRF_ESS | BRF_PRG }, + { "vphj.10b", 0x080000, 0x32c7d8f0, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhuntj) +STD_ROM_FN(Vhuntj) + +static struct BurnRomInfo Vhuntjr1RomDesc[] = { + { "vphj.03c", 0x080000, 0x606b682a, 1 | BRF_ESS | BRF_PRG }, + { "vphj.04b", 0x080000, 0xa3b40393, 1 | BRF_ESS | BRF_PRG }, + { "vphj.05b", 0x080000, 0xfccd5558, 1 | BRF_ESS | BRF_PRG }, + { "vphj.06b", 0x080000, 0x07e10a73, 1 | BRF_ESS | BRF_PRG }, + { "vphj.07b", 0x080000, 0x0761309f, 1 | BRF_ESS | BRF_PRG }, + { "vphj.08b", 0x080000, 0x5a5c2bf5, 1 | BRF_ESS | BRF_PRG }, + { "vphj.09b", 0x080000, 0x823d6d99, 1 | BRF_ESS | BRF_PRG }, + { "vphj.10b", 0x080000, 0x32c7d8f0, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhuntjr1) +STD_ROM_FN(Vhuntjr1) + +static struct BurnRomInfo Vhuntjr2RomDesc[] = { + { "vphj.03b", 0x080000, 0x679c3fa9, 1 | BRF_ESS | BRF_PRG }, + { "vphj.04a", 0x080000, 0xeb6e71e4, 1 | BRF_ESS | BRF_PRG }, + { "vphj.05a", 0x080000, 0xeaf634ea, 1 | BRF_ESS | BRF_PRG }, + { "vphj.06a", 0x080000, 0xb70cc6be, 1 | BRF_ESS | BRF_PRG }, + { "vphj.07a", 0x080000, 0x46ab907d, 1 | BRF_ESS | BRF_PRG }, + { "vphj.08a", 0x080000, 0x1c00355e, 1 | BRF_ESS | BRF_PRG }, + { "vphj.09a", 0x080000, 0x026e6f82, 1 | BRF_ESS | BRF_PRG }, + { "vphj.10a", 0x080000, 0xaadfb3ea, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhuntjr2) +STD_ROM_FN(Vhuntjr2) + +static struct BurnRomInfo ProgearRomDesc[] = { + { "pgau.03", 0x080000, 0x343A783E, 1 | BRF_ESS | BRF_PRG }, + { "pgau.04", 0x080000, 0x16208D79, 1 | BRF_ESS | BRF_PRG }, + + { "pga-simm.01c", 0x200000, 0x452F98B0, 11 | BRF_GRA }, + { "pga-simm.01d", 0x200000, 0x9E672092, 11 | BRF_GRA }, + { "pga-simm.01a", 0x200000, 0xAE9DDAFE, 11 | BRF_GRA }, + { "pga-simm.01b", 0x200000, 0x94D72D94, 11 | BRF_GRA }, + { "pga-simm.03c", 0x200000, 0x48A1886D, 11 | BRF_GRA }, + { "pga-simm.03d", 0x200000, 0x172D7E37, 11 | BRF_GRA }, + { "pga-simm.03a", 0x200000, 0x9EE33D98, 11 | BRF_GRA }, + { "pga-simm.03b", 0x200000, 0x848DEE32, 11 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga-simm.05a", 0x200000, 0xC0AAC80C, 13 | BRF_SND }, + { "pga-simm.05b", 0x200000, 0x37A65D86, 13 | BRF_SND }, + { "pga-simm.06a", 0x200000, 0xD3F1E934, 13 | BRF_SND }, + { "pga-simm.06b", 0x200000, 0x8B39489A, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Progear) +STD_ROM_FN(Progear) + +static struct BurnRomInfo ProgearaRomDesc[] = { + { "pgaa.03", 0x080000, 0x25E6E2CE, 1 | BRF_ESS | BRF_PRG }, + { "pgaa.04", 0x080000, 0x8104307E, 1 | BRF_ESS | BRF_PRG }, + + { "pga-simm.01c", 0x200000, 0x452F98B0, 11 | BRF_GRA }, + { "pga-simm.01d", 0x200000, 0x9E672092, 11 | BRF_GRA }, + { "pga-simm.01a", 0x200000, 0xAE9DDAFE, 11 | BRF_GRA }, + { "pga-simm.01b", 0x200000, 0x94D72D94, 11 | BRF_GRA }, + { "pga-simm.03c", 0x200000, 0x48A1886D, 11 | BRF_GRA }, + { "pga-simm.03d", 0x200000, 0x172D7E37, 11 | BRF_GRA }, + { "pga-simm.03a", 0x200000, 0x9EE33D98, 11 | BRF_GRA }, + { "pga-simm.03b", 0x200000, 0x848DEE32, 11 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga-simm.05a", 0x200000, 0xC0AAC80C, 13 | BRF_SND }, + { "pga-simm.05b", 0x200000, 0x37A65D86, 13 | BRF_SND }, + { "pga-simm.06a", 0x200000, 0xD3F1E934, 13 | BRF_SND }, + { "pga-simm.06b", 0x200000, 0x8B39489A, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Progeara) +STD_ROM_FN(Progeara) + +static struct BurnRomInfo ProgearjRomDesc[] = { + { "pgaj.03", 0x080000, 0x06DBBA54, 1 | BRF_ESS | BRF_PRG }, + { "pgaj.04", 0x080000, 0xA1F1F1BC, 1 | BRF_ESS | BRF_PRG }, + + { "pga-simm.01c", 0x200000, 0x452F98B0, 11 | BRF_GRA }, + { "pga-simm.01d", 0x200000, 0x9E672092, 11 | BRF_GRA }, + { "pga-simm.01a", 0x200000, 0xAE9DDAFE, 11 | BRF_GRA }, + { "pga-simm.01b", 0x200000, 0x94D72D94, 11 | BRF_GRA }, + { "pga-simm.03c", 0x200000, 0x48A1886D, 11 | BRF_GRA }, + { "pga-simm.03d", 0x200000, 0x172D7E37, 11 | BRF_GRA }, + { "pga-simm.03a", 0x200000, 0x9EE33D98, 11 | BRF_GRA }, + { "pga-simm.03b", 0x200000, 0x848DEE32, 11 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga-simm.05a", 0x200000, 0xC0AAC80C, 13 | BRF_SND }, + { "pga-simm.05b", 0x200000, 0x37A65D86, 13 | BRF_SND }, + { "pga-simm.06a", 0x200000, 0xD3F1E934, 13 | BRF_SND }, + { "pga-simm.06b", 0x200000, 0x8B39489A, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Progearj) +STD_ROM_FN(Progearj) + +static struct BurnRomInfo Pzloop2RomDesc[] = { + { "pl2e.03", 0x080000, 0x3b1285b2, 1 | BRF_ESS | BRF_PRG }, + { "pl2e.04", 0x080000, 0x40a2d647, 1 | BRF_ESS | BRF_PRG }, + { "pl2e.05", 0x080000, 0x0f11d818, 1 | BRF_ESS | BRF_PRG }, + { "pl2e.06", 0x080000, 0x86fbbdf4, 1 | BRF_ESS | BRF_PRG }, + + { "pl2-simm.01c", 0x200000, 0x137b13a7, 11 | BRF_GRA }, + { "pl2-simm.01d", 0x200000, 0xa2db1507, 11 | BRF_GRA }, + { "pl2-simm.01a", 0x200000, 0x7e80ff8e, 11 | BRF_GRA }, + { "pl2-simm.01b", 0x200000, 0xcd93e6ed, 11 | BRF_GRA }, + { "pl2-simm.03c", 0x200000, 0x0f52bbca, 11 | BRF_GRA }, + { "pl2-simm.03d", 0x200000, 0xa62712c3, 11 | BRF_GRA }, + { "pl2-simm.03a", 0x200000, 0xb60c9f8e, 11 | BRF_GRA }, + { "pl2-simm.03b", 0x200000, 0x83fef284, 11 | BRF_GRA }, + + { "pl2.01", 0x020000, 0x35697569, 4 | BRF_ESS | BRF_PRG }, + + { "pl2-simm.05a", 0x200000, 0x85d8fbe8, 13 | BRF_SND }, + { "pl2-simm.05b", 0x200000, 0x1ed62584, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Pzloop2) +STD_ROM_FN(Pzloop2) + +static struct BurnRomInfo Pzloop2jRomDesc[] = { + { "pl2j.03a", 0x080000, 0x0a751bd0, 1 | BRF_ESS | BRF_PRG }, + { "pl2j.04a", 0x080000, 0xc3f72afe, 1 | BRF_ESS | BRF_PRG }, + { "pl2j.05a", 0x080000, 0x6ea9dbfc, 1 | BRF_ESS | BRF_PRG }, + { "pl2j.06a", 0x080000, 0x0f14848d, 1 | BRF_ESS | BRF_PRG }, + + { "pl2-simm.01c", 0x200000, 0x137b13a7, 11 | BRF_GRA }, + { "pl2-simm.01d", 0x200000, 0xa2db1507, 11 | BRF_GRA }, + { "pl2-simm.01a", 0x200000, 0x7e80ff8e, 11 | BRF_GRA }, + { "pl2-simm.01b", 0x200000, 0xcd93e6ed, 11 | BRF_GRA }, + { "pl2-simm.03c", 0x200000, 0x0f52bbca, 11 | BRF_GRA }, + { "pl2-simm.03d", 0x200000, 0xa62712c3, 11 | BRF_GRA }, + { "pl2-simm.03a", 0x200000, 0xb60c9f8e, 11 | BRF_GRA }, + { "pl2-simm.03b", 0x200000, 0x83fef284, 11 | BRF_GRA }, + + { "pl2.01", 0x020000, 0x35697569, 4 | BRF_ESS | BRF_PRG }, + + { "pl2-simm.05a", 0x200000, 0x85d8fbe8, 13 | BRF_SND }, + { "pl2-simm.05b", 0x200000, 0x1ed62584, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Pzloop2j) +STD_ROM_FN(Pzloop2j) + +static struct BurnRomInfo QndreamRomDesc[] = { + { "tqzj.03a", 0x080000, 0x7acf3e30, 1 | BRF_ESS | BRF_PRG }, + { "tqzj.04", 0x080000, 0xf1044a87, 1 | BRF_ESS | BRF_PRG }, + { "tqzj.05", 0x080000, 0x4105ba0e, 1 | BRF_ESS | BRF_PRG }, + { "tqzj.06", 0x080000, 0xc371e8a5, 1 | BRF_ESS | BRF_PRG }, + + { "tqz.14m", 0x200000, 0x98af88a2, 3 | BRF_GRA }, + { "tqz.16m", 0x200000, 0xdf82d491, 3 | BRF_GRA }, + { "tqz.18m", 0x200000, 0x42f132ff, 3 | BRF_GRA }, + { "tqz.20m", 0x200000, 0xb2e128a3, 3 | BRF_GRA }, + + { "tqz.01", 0x020000, 0xe9ce9d0a, 4 | BRF_ESS | BRF_PRG }, + + { "tqz.11m", 0x200000, 0x78e7884f, 5 | BRF_SND }, + { "tqz.12m", 0x200000, 0x2e049b13, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Qndream) +STD_ROM_FN(Qndream) + +static struct BurnRomInfo RingdestRomDesc[] = { + { "smbe.03b", 0x080000, 0xb8016278, 1 | BRF_ESS | BRF_PRG }, + { "smbe.04b", 0x080000, 0x18c4c447, 1 | BRF_ESS | BRF_PRG }, + { "smbe.05b", 0x080000, 0x18ebda7f, 1 | BRF_ESS | BRF_PRG }, + { "smbe.06b", 0x080000, 0x89c80007, 1 | BRF_ESS | BRF_PRG }, + { "smb.07", 0x080000, 0xb9a11577, 1 | BRF_ESS | BRF_PRG }, + { "smb.08", 0x080000, 0xf931b76b, 1 | BRF_ESS | BRF_PRG }, + + { "smb.13m", 0x200000, 0xd9b2d1de, 3 | BRF_GRA }, + { "smb.15m", 0x200000, 0x9a766d92, 3 | BRF_GRA }, + { "smb.17m", 0x200000, 0x51800f0f, 3 | BRF_GRA }, + { "smb.19m", 0x200000, 0x35757e96, 3 | BRF_GRA }, + { "smb.14m", 0x200000, 0xe5bfd0e7, 3 | BRF_GRA }, + { "smb.16m", 0x200000, 0xc56c0866, 3 | BRF_GRA }, + { "smb.18m", 0x200000, 0x4ded3910, 3 | BRF_GRA }, + { "smb.20m", 0x200000, 0x26ea1ec5, 3 | BRF_GRA }, + { "smb.21m", 0x080000, 0x0a08c5fc, 3 | BRF_GRA }, + { "smb.23m", 0x080000, 0x0911b6c4, 3 | BRF_GRA }, + { "smb.25m", 0x080000, 0x82d6c4ec, 3 | BRF_GRA }, + { "smb.27m", 0x080000, 0x9b48678b, 3 | BRF_GRA }, + + { "smb.01", 0x020000, 0x0abc229a, 4 | BRF_ESS | BRF_PRG }, + { "smb.02", 0x020000, 0xd051679a, 4 | BRF_ESS | BRF_PRG }, + + { "smb.11m", 0x200000, 0xc56935f9, 5 | BRF_SND }, + { "smb.12m", 0x200000, 0x955b0782, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ringdest) +STD_ROM_FN(Ringdest) + +static struct BurnRomInfo SmbombRomDesc[] = { + { "smbj.03a", 0x080000, 0x1c5613de, 1 | BRF_ESS | BRF_PRG }, + { "smbj.04a", 0x080000, 0x29071ed7, 1 | BRF_ESS | BRF_PRG }, + { "smbj.05a", 0x080000, 0xeb20bce4, 1 | BRF_ESS | BRF_PRG }, + { "smbj.06a", 0x080000, 0x94b420cd, 1 | BRF_ESS | BRF_PRG }, + { "smb.07", 0x080000, 0xb9a11577, 1 | BRF_ESS | BRF_PRG }, + { "smb.08", 0x080000, 0xf931b76b, 1 | BRF_ESS | BRF_PRG }, + + { "smb.13m", 0x200000, 0xd9b2d1de, 3 | BRF_GRA }, + { "smb.15m", 0x200000, 0x9a766d92, 3 | BRF_GRA }, + { "smb.17m", 0x200000, 0x51800f0f, 3 | BRF_GRA }, + { "smb.19m", 0x200000, 0x35757e96, 3 | BRF_GRA }, + { "smb.14m", 0x200000, 0xe5bfd0e7, 3 | BRF_GRA }, + { "smb.16m", 0x200000, 0xc56c0866, 3 | BRF_GRA }, + { "smb.18m", 0x200000, 0x4ded3910, 3 | BRF_GRA }, + { "smb.20m", 0x200000, 0x26ea1ec5, 3 | BRF_GRA }, + { "smb.21m", 0x080000, 0x0a08c5fc, 3 | BRF_GRA }, + { "smb.23m", 0x080000, 0x0911b6c4, 3 | BRF_GRA }, + { "smb.25m", 0x080000, 0x82d6c4ec, 3 | BRF_GRA }, + { "smb.27m", 0x080000, 0x9b48678b, 3 | BRF_GRA }, + + { "smb.01", 0x020000, 0x0abc229a, 4 | BRF_ESS | BRF_PRG }, + { "smb.02", 0x020000, 0xd051679a, 4 | BRF_ESS | BRF_PRG }, + + { "smb.11m", 0x200000, 0xc56935f9, 5 | BRF_SND }, + { "smb.12m", 0x200000, 0x955b0782, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Smbomb) +STD_ROM_FN(Smbomb) + +static struct BurnRomInfo Smbombr1RomDesc[] = { + { "smbj.03", 0x080000, 0x52eafb10, 1 | BRF_ESS | BRF_PRG }, + { "smbj.04", 0x080000, 0xaa6e8078, 1 | BRF_ESS | BRF_PRG }, + { "smbj.05", 0x080000, 0xb69e7d5f, 1 | BRF_ESS | BRF_PRG }, + { "smbj.06", 0x080000, 0x8d857b56, 1 | BRF_ESS | BRF_PRG }, + { "smb.07", 0x080000, 0xb9a11577, 1 | BRF_ESS | BRF_PRG }, + { "smb.08", 0x080000, 0xf931b76b, 1 | BRF_ESS | BRF_PRG }, + + { "smb.13m", 0x200000, 0xd9b2d1de, 3 | BRF_GRA }, + { "smb.15m", 0x200000, 0x9a766d92, 3 | BRF_GRA }, + { "smb.17m", 0x200000, 0x51800f0f, 3 | BRF_GRA }, + { "smb.19m", 0x200000, 0x35757e96, 3 | BRF_GRA }, + { "smb.14m", 0x200000, 0xe5bfd0e7, 3 | BRF_GRA }, + { "smb.16m", 0x200000, 0xc56c0866, 3 | BRF_GRA }, + { "smb.18m", 0x200000, 0x4ded3910, 3 | BRF_GRA }, + { "smb.20m", 0x200000, 0x26ea1ec5, 3 | BRF_GRA }, + { "smb.21m", 0x080000, 0x0a08c5fc, 3 | BRF_GRA }, + { "smb.23m", 0x080000, 0x0911b6c4, 3 | BRF_GRA }, + { "smb.25m", 0x080000, 0x82d6c4ec, 3 | BRF_GRA }, + { "smb.27m", 0x080000, 0x9b48678b, 3 | BRF_GRA }, + + { "smb.01", 0x020000, 0x0abc229a, 4 | BRF_ESS | BRF_PRG }, + { "smb.02", 0x020000, 0xd051679a, 4 | BRF_ESS | BRF_PRG }, + + { "smb.11m", 0x200000, 0xc56935f9, 5 | BRF_SND }, + { "smb.12m", 0x200000, 0x955b0782, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Smbombr1) +STD_ROM_FN(Smbombr1) + +static struct BurnRomInfo RingdestaRomDesc[] = { + { "smba.03a", 0x080000, 0xd3744dfd, 1 | BRF_ESS | BRF_PRG }, + { "smba.04a", 0x080000, 0xf32d5b4f, 1 | BRF_ESS | BRF_PRG }, + { "smba.05a", 0x080000, 0x1016454f, 1 | BRF_ESS | BRF_PRG }, + { "smba.06a", 0x080000, 0x94b420cd, 1 | BRF_ESS | BRF_PRG }, + { "smb.07", 0x080000, 0xb9a11577, 1 | BRF_ESS | BRF_PRG }, + { "smb.08", 0x080000, 0xf931b76b, 1 | BRF_ESS | BRF_PRG }, + + { "smb.13m", 0x200000, 0xd9b2d1de, 3 | BRF_GRA }, + { "smb.15m", 0x200000, 0x9a766d92, 3 | BRF_GRA }, + { "smb.17m", 0x200000, 0x51800f0f, 3 | BRF_GRA }, + { "smb.19m", 0x200000, 0x35757e96, 3 | BRF_GRA }, + { "smb.14m", 0x200000, 0xe5bfd0e7, 3 | BRF_GRA }, + { "smb.16m", 0x200000, 0xc56c0866, 3 | BRF_GRA }, + { "smb.18m", 0x200000, 0x4ded3910, 3 | BRF_GRA }, + { "smb.20m", 0x200000, 0x26ea1ec5, 3 | BRF_GRA }, + { "smb.21m", 0x080000, 0x0a08c5fc, 3 | BRF_GRA }, + { "smb.23m", 0x080000, 0x0911b6c4, 3 | BRF_GRA }, + { "smb.25m", 0x080000, 0x82d6c4ec, 3 | BRF_GRA }, + { "smb.27m", 0x080000, 0x9b48678b, 3 | BRF_GRA }, + + { "smb.01", 0x020000, 0x0abc229a, 4 | BRF_ESS | BRF_PRG }, + { "smb.02", 0x020000, 0xd051679a, 4 | BRF_ESS | BRF_PRG }, + + { "smb.11m", 0x200000, 0xc56935f9, 5 | BRF_SND }, + { "smb.12m", 0x200000, 0x955b0782, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ringdesta) +STD_ROM_FN(Ringdesta) + +static struct BurnRomInfo SfaRomDesc[] = { + { "sfze.03d", 0x080000, 0xebf2054d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04b", 0x080000, 0x8b73b0e5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa) +STD_ROM_FN(Sfa) + +static struct BurnRomInfo Sfar1RomDesc[] = { + { "sfze.03c", 0x080000, 0xa1b69dd7, 1 | BRF_ESS | BRF_PRG }, + { "sfze.04b", 0x080000, 0xbb90acd5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfar1) +STD_ROM_FN(Sfar1) + +static struct BurnRomInfo Sfar2RomDesc[] = { + { "sfze.03b", 0x080000, 0x2bf5708e, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04a", 0x080000, 0x5f99e9a5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfar2) +STD_ROM_FN(Sfar2) + +static struct BurnRomInfo Sfar3RomDesc[] = { + { "sfze.03a", 0x080000, 0xfdbcd434, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04", 0x080000, 0x0c436d30, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05", 0x080000, 0x1f363612, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfar3) +STD_ROM_FN(Sfar3) + +static struct BurnRomInfo SfauRomDesc[] = { + { "sfzu.03a", 0x080000, 0x49fc7db9, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04a", 0x080000, 0x5f99e9a5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfau) +STD_ROM_FN(Sfau) + +static struct BurnRomInfo SfzaRomDesc[] = { + { "sfza.03a", 0x080000, 0xca91bed9, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04a", 0x080000, 0x5f99e9a5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfza) +STD_ROM_FN(Sfza) + +static struct BurnRomInfo SfzbRomDesc[] = { + { "sfzb.03g", 0x080000, 0x348862d4, 1 | BRF_ESS | BRF_PRG }, + { "sfzb.04e", 0x080000, 0x8d9b2480, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzb) +STD_ROM_FN(Sfzb) + +static struct BurnRomInfo Sfzbr1RomDesc[] = { + { "sfzb.03e", 0x080000, 0xecba89a3, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04b", 0x080000, 0x8b73b0e5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzbr1) +STD_ROM_FN(Sfzbr1) + +static struct BurnRomInfo SfzhRomDesc[] = { + { "sfzh.03d", 0x080000, 0x6e08cbe0, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04c", 0x080000, 0xbb90acd5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05c", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzh) +STD_ROM_FN(Sfzh) + +static struct BurnRomInfo Sfzhr1RomDesc[] = { + { "sfzh.03c", 0x080000, 0xbce635aa, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04a", 0x080000, 0x5f99e9a5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzhr1) +STD_ROM_FN(Sfzhr1) + +static struct BurnRomInfo SfzjRomDesc[] = { + { "sfzj.03c", 0x080000, 0xf5444120, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04b", 0x080000, 0x8b73b0e5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzj) +STD_ROM_FN(Sfzj) + +static struct BurnRomInfo Sfzjr1RomDesc[] = { + { "sfzj.03b", 0x080000, 0x844220c2, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04a", 0x080000, 0x5f99e9a5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzjr1) +STD_ROM_FN(Sfzjr1) + +static struct BurnRomInfo Sfzjr2RomDesc[] = { + { "sfzj.03a", 0x080000, 0x3cfce93c, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04", 0x080000, 0x0c436d30, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05", 0x080000, 0x1f363612, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfzjr2) +STD_ROM_FN(Sfzjr2) + +static struct BurnRomInfo Sfa2RomDesc[] = { + { "sz2e.03", 0x080000, 0x1061e6bb, 1 | BRF_ESS | BRF_PRG }, + { "sz2e.04", 0x080000, 0x22d17b26, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05", 0x080000, 0x4b442a7c, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2.07", 0x080000, 0x8e184246, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa2) +STD_ROM_FN(Sfa2) + +static struct BurnRomInfo Sfa2uRomDesc[] = { + { "sz2ua.03", 0x080000, 0xd03e504f, 1 | BRF_ESS | BRF_PRG }, + { "sz2ua.04", 0x080000, 0xfae0e9c3, 1 | BRF_ESS | BRF_PRG }, + { "sz2ua.05", 0x080000, 0xd02dd758, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.06", 0x080000, 0xc5c8eb63, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.07", 0x080000, 0x5de01cc5, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.08", 0x080000, 0xbea11d56, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa2u) +STD_ROM_FN(Sfa2u) + +static struct BurnRomInfo Sfa2ur1RomDesc[] = { + { "sz2u.03", 0x080000, 0x84a09006, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.04", 0x080000, 0xac46e5ed, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.05", 0x080000, 0x6c0c79d3, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.06", 0x080000, 0xc5c8eb63, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.07", 0x080000, 0x5de01cc5, 1 | BRF_ESS | BRF_PRG }, + { "sz2u.08", 0x080000, 0xbea11d56, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa2ur1) +STD_ROM_FN(Sfa2ur1) + +static struct BurnRomInfo Sfz2aRomDesc[] = { + { "sz2a.03a", 0x080000, 0x30d2099f, 1 | BRF_ESS | BRF_PRG }, + { "sz2a.04a", 0x080000, 0x1cc94db1, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05a", 0x080000, 0x98e8e992, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2a.07a", 0x080000, 0x0aed2494, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2a) +STD_ROM_FN(Sfz2a) + +static struct BurnRomInfo Sfz2bRomDesc[] = { + { "sz2b.03b", 0x080000, 0x1ac12812, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.04b", 0x080000, 0xe4ffaf68, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.05a", 0x080000, 0xdd224156, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.06a", 0x080000, 0xa45a75a6, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.07a", 0x080000, 0x7d19d5ec, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.08", 0x080000, 0x92b66e01, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2b) +STD_ROM_FN(Sfz2b) + +static struct BurnRomInfo Sfz2br1RomDesc[] = { + { "sz2b.03", 0x080000, 0xe6ce530b, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.04", 0x080000, 0x1605a0cb, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05", 0x080000, 0x4b442a7c, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.07", 0x080000, 0x947e8ac6, 1 | BRF_ESS | BRF_PRG }, + { "sz2b.08", 0x080000, 0x92b66e01, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2br1) +STD_ROM_FN(Sfz2br1) + +static struct BurnRomInfo Sfz2hRomDesc[] = { + { "sz2h.03" , 0x080000, 0xbfeddf5b, 1 | BRF_ESS | BRF_PRG }, + { "sz2h.04", 0x080000, 0xea5009fb, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05", 0x080000, 0x4b442a7c, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2h.07", 0x080000, 0x947e8ac6, 1 | BRF_ESS | BRF_PRG }, + { "sz2h.08", 0x080000, 0x92b66e01, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2h) +STD_ROM_FN(Sfz2h) + +static struct BurnRomInfo Sfz2jRomDesc[] = { + { "sz2j.03a", 0x080000, 0x97461e28, 1 | BRF_ESS | BRF_PRG }, + { "sz2j.04a", 0x080000, 0xae4851a9, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05a", 0x080000, 0x98e8e992, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2j.07a", 0x080000, 0xd910b2a2, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2j) +STD_ROM_FN(Sfz2j) + +static struct BurnRomInfo Sfz2nRomDesc[] = { + { "sz2n.03" , 0x080000, 0x58924741, 1 | BRF_ESS | BRF_PRG }, + { "sz2n.04", 0x080000, 0x592a17c5, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05", 0x080000, 0x4b442a7c, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2.07", 0x080000, 0x8e184246, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2n) +STD_ROM_FN(Sfz2n) + +static struct BurnRomInfo Sfz2alRomDesc[] = { + { "szaa.03", 0x080000, 0x88e7023e, 1 | BRF_ESS | BRF_PRG }, + { "szaa.04", 0x080000, 0xae8ec36e, 1 | BRF_ESS | BRF_PRG }, + { "szaa.05", 0x080000, 0xf053a55e, 1 | BRF_ESS | BRF_PRG }, + { "szaa.06", 0x080000, 0xcfc0e7a8, 1 | BRF_ESS | BRF_PRG }, + { "szaa.07", 0x080000, 0x5feb8b20, 1 | BRF_ESS | BRF_PRG }, + { "szaa.08", 0x080000, 0x6eb6d412, 1 | BRF_ESS | BRF_PRG }, + + { "sza.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sza.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sza.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sza.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sza.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sza.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sza.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sza.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sza.01", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sza.02", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sza.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sza.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2al) +STD_ROM_FN(Sfz2al) + +static struct BurnRomInfo Sfz2albRomDesc[] = { + { "szab.03", 0x080000, 0xcb436eca, 1 | BRF_ESS | BRF_PRG }, + { "szab.04", 0x080000, 0x14534bea, 1 | BRF_ESS | BRF_PRG }, + { "szab.05", 0x080000, 0x7fb10658, 1 | BRF_ESS | BRF_PRG }, + { "sza.06", 0x080000, 0x0abda2fc, 1 | BRF_ESS | BRF_PRG }, + { "sza.07", 0x080000, 0xe9430762, 1 | BRF_ESS | BRF_PRG }, + { "sza.08", 0x080000, 0xb65711a9, 1 | BRF_ESS | BRF_PRG }, + + { "sza.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sza.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sza.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sza.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sza.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sza.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sza.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sza.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sza.01", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sza.02", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sza.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sza.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2alb) +STD_ROM_FN(Sfz2alb) + +static struct BurnRomInfo Sfz2alhRomDesc[] = { + { "szah.03", 0x080000, 0x06f93d1d, 1 | BRF_ESS | BRF_PRG }, + { "szah.04", 0x080000, 0xe62ee914, 1 | BRF_ESS | BRF_PRG }, + { "szah.05", 0x080000, 0x2b7f4b20, 1 | BRF_ESS | BRF_PRG }, + { "sza.06", 0x080000, 0x0abda2fc, 1 | BRF_ESS | BRF_PRG }, + { "sza.07", 0x080000, 0xe9430762, 1 | BRF_ESS | BRF_PRG }, + { "sza.08", 0x080000, 0xb65711a9, 1 | BRF_ESS | BRF_PRG }, + + { "sza.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sza.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sza.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sza.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sza.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sza.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sza.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sza.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sza.01", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sza.02", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sza.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sza.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2alh) +STD_ROM_FN(Sfz2alh) + +static struct BurnRomInfo Sfz2aljRomDesc[] = { + { "szaj.03a", 0x080000, 0xa3802fe3, 1 | BRF_ESS | BRF_PRG }, + { "szaj.04a", 0x080000, 0xe7ca87c7, 1 | BRF_ESS | BRF_PRG }, + { "szaj.05a", 0x080000, 0xc88ebf88, 1 | BRF_ESS | BRF_PRG }, + { "szaj.06a", 0x080000, 0x35ed5b7a, 1 | BRF_ESS | BRF_PRG }, + { "szaj.07a", 0x080000, 0x975dcb3e, 1 | BRF_ESS | BRF_PRG }, + { "szaj.08a", 0x080000, 0xdc73f2d7, 1 | BRF_ESS | BRF_PRG }, + + { "sza.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sza.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sza.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sza.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sza.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sza.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sza.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sza.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sza.01", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sza.02", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sza.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sza.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2alj) +STD_ROM_FN(Sfz2alj) + +static struct BurnRomInfo Sfa3RomDesc[] = { + { "sz3e.03c", 0x080000, 0x9762b206, 1 | BRF_ESS | BRF_PRG }, + { "sz3e.04c", 0x080000, 0x5ad3f721, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3) +STD_ROM_FN(Sfa3) + +static struct BurnRomInfo Sfa3bRomDesc[] = { + { "sz3b.03", 0x080000, 0x046c9b4d, 1 | BRF_ESS | BRF_PRG }, + { "sz3b.04", 0x080000, 0xda211919, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3b) +STD_ROM_FN(Sfa3b) + +static struct BurnRomInfo Sfa3hRomDesc[] = { + { "sz3h.03c", 0x080000, 0xb3b563a3, 1 | BRF_ESS | BRF_PRG }, + { "sz3h.04c", 0x080000, 0x47891fec, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3h) +STD_ROM_FN(Sfa3h) + +static struct BurnRomInfo Sfa3hr1RomDesc[] = { + { "sz3h.03", 0x080000, 0x4b16cb3e, 1 | BRF_ESS | BRF_PRG }, + { "sz3h.04", 0x080000, 0x88ad2e6a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3hr1) +STD_ROM_FN(Sfa3hr1) + +static struct BurnRomInfo Sfa3uRomDesc[] = { + { "sz3u.03c", 0x080000, 0xe007da2e, 1 | BRF_ESS | BRF_PRG }, + { "sz3u.04c", 0x080000, 0x5f78f0e7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3u) +STD_ROM_FN(Sfa3u) + +static struct BurnRomInfo Sfa3ur1RomDesc[] = { + { "sz3u.03", 0x080000, 0xb5984a19, 1 | BRF_ESS | BRF_PRG }, + { "sz3u.04", 0x080000, 0x7e8158ba, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3ur1) +STD_ROM_FN(Sfa3ur1) + +static struct BurnRomInfo Sfz3aRomDesc[] = { + { "sz3a.03d", 0x080000, 0xd7e140d6, 1 | BRF_ESS | BRF_PRG }, + { "sz3a.04d", 0x080000, 0xe06869a2, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3a) +STD_ROM_FN(Sfz3a) + +static struct BurnRomInfo Sfz3ar1RomDesc[] = { + { "sz3a.03a", 0x080000, 0x29c681fd, 1 | BRF_ESS | BRF_PRG }, + { "sz3a.04", 0x080000, 0x9ddd1484, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3ar1) +STD_ROM_FN(Sfz3ar1) + +static struct BurnRomInfo Sfz3jRomDesc[] = { + { "sz3j.03c", 0x080000, 0xcadf4a51, 1 | BRF_ESS | BRF_PRG }, + { "sz3j.04c", 0x080000, 0xfcb31228, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3j) +STD_ROM_FN(Sfz3j) + +static struct BurnRomInfo Sfz3jr1RomDesc[] = { + { "sz3j.03a", 0x080000, 0x6ee0beae, 1 | BRF_ESS | BRF_PRG }, + { "sz3j.04a", 0x080000, 0xa6e2978d, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05a", 0x080000, 0x05964b7d, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06a", 0x080000, 0x78ce2179, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07a", 0x080000, 0x398bf52f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08a", 0x080000, 0x866d0588, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09a", 0x080000, 0x2180892c, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3jr1) +STD_ROM_FN(Sfz3jr1) + +static struct BurnRomInfo Sfz3jr2RomDesc[] = { + { "sz3j.03", 0x080000, 0xf7cb4b13, 1 | BRF_ESS | BRF_PRG }, + { "sz3j.04", 0x080000, 0x0846c29d, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3jr2) +STD_ROM_FN(Sfz3jr2) + +static struct BurnRomInfo SgemfRomDesc[] = { + { "pcfu.03", 0x080000, 0xac2e8566, 1 | BRF_ESS | BRF_PRG }, + { "pcf.04", 0x080000, 0xf4314c96, 1 | BRF_ESS | BRF_PRG }, + { "pcf.05", 0x080000, 0x215655f6, 1 | BRF_ESS | BRF_PRG }, + { "pcf.06", 0x080000, 0xea6f13ea, 1 | BRF_ESS | BRF_PRG }, + { "pcf.07", 0x080000, 0x5ac6d5ea, 1 | BRF_ESS | BRF_PRG }, + + { "pcf.13m", 0x400000, 0x22d72ab9, 3 | BRF_GRA }, + { "pcf.15m", 0x400000, 0x16a4813c, 3 | BRF_GRA }, + { "pcf.17m", 0x400000, 0x1097e035, 3 | BRF_GRA }, + { "pcf.19m", 0x400000, 0xd362d874, 3 | BRF_GRA }, + { "pcf.14m", 0x100000, 0x0383897c, 3 | BRF_GRA }, + { "pcf.16m", 0x100000, 0x76f91084, 3 | BRF_GRA }, + { "pcf.18m", 0x100000, 0x756c3754, 3 | BRF_GRA }, + { "pcf.20m", 0x100000, 0x9ec9277d, 3 | BRF_GRA }, + + { "pcf.01", 0x020000, 0x254e5f33, 4 | BRF_ESS | BRF_PRG }, + { "pcf.02", 0x020000, 0x6902f4f9, 4 | BRF_ESS | BRF_PRG }, + + { "pcf.11m", 0x400000, 0xa5dea005, 5 | BRF_SND }, + { "pcf.12m", 0x400000, 0x4ce235fe, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sgemf) +STD_ROM_FN(Sgemf) + +static struct BurnRomInfo PfghtjRomDesc[] = { + { "pcfj.03", 0x080000, 0x681da43e, 1 | BRF_ESS | BRF_PRG }, + { "pcf.04", 0x080000, 0xf4314c96, 1 | BRF_ESS | BRF_PRG }, + { "pcf.05", 0x080000, 0x215655f6, 1 | BRF_ESS | BRF_PRG }, + { "pcf.06", 0x080000, 0xea6f13ea, 1 | BRF_ESS | BRF_PRG }, + { "pcf.07", 0x080000, 0x5ac6d5ea, 1 | BRF_ESS | BRF_PRG }, + + { "pcf.13m", 0x400000, 0x22d72ab9, 3 | BRF_GRA }, + { "pcf.15m", 0x400000, 0x16a4813c, 3 | BRF_GRA }, + { "pcf.17m", 0x400000, 0x1097e035, 3 | BRF_GRA }, + { "pcf.19m", 0x400000, 0xd362d874, 3 | BRF_GRA }, + { "pcf.14m", 0x100000, 0x0383897c, 3 | BRF_GRA }, + { "pcf.16m", 0x100000, 0x76f91084, 3 | BRF_GRA }, + { "pcf.18m", 0x100000, 0x756c3754, 3 | BRF_GRA }, + { "pcf.20m", 0x100000, 0x9ec9277d, 3 | BRF_GRA }, + + { "pcf.01", 0x020000, 0x254e5f33, 4 | BRF_ESS | BRF_PRG }, + { "pcf.02", 0x020000, 0x6902f4f9, 4 | BRF_ESS | BRF_PRG }, + + { "pcf.11m", 0x400000, 0xa5dea005, 5 | BRF_SND }, + { "pcf.12m", 0x400000, 0x4ce235fe, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Pfghtj) +STD_ROM_FN(Pfghtj) + +static struct BurnRomInfo SgemfaRomDesc[] = { + { "pcfa.03", 0x080000, 0xe17c089a, 1 | BRF_ESS | BRF_PRG }, + { "pcf.04", 0x080000, 0xf4314c96, 1 | BRF_ESS | BRF_PRG }, + { "pcf.05", 0x080000, 0x215655f6, 1 | BRF_ESS | BRF_PRG }, + { "pcf.06", 0x080000, 0xea6f13ea, 1 | BRF_ESS | BRF_PRG }, + { "pcf.07", 0x080000, 0x5ac6d5ea, 1 | BRF_ESS | BRF_PRG }, + + { "pcf.13m", 0x400000, 0x22d72ab9, 3 | BRF_GRA }, + { "pcf.15m", 0x400000, 0x16a4813c, 3 | BRF_GRA }, + { "pcf.17m", 0x400000, 0x1097e035, 3 | BRF_GRA }, + { "pcf.19m", 0x400000, 0xd362d874, 3 | BRF_GRA }, + { "pcf.14m", 0x100000, 0x0383897c, 3 | BRF_GRA }, + { "pcf.16m", 0x100000, 0x76f91084, 3 | BRF_GRA }, + { "pcf.18m", 0x100000, 0x756c3754, 3 | BRF_GRA }, + { "pcf.20m", 0x100000, 0x9ec9277d, 3 | BRF_GRA }, + + { "pcf.01", 0x020000, 0x254e5f33, 4 | BRF_ESS | BRF_PRG }, + { "pcf.02", 0x020000, 0x6902f4f9, 4 | BRF_ESS | BRF_PRG }, + + { "pcf.11m", 0x400000, 0xa5dea005, 5 | BRF_SND }, + { "pcf.12m", 0x400000, 0x4ce235fe, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sgemfa) +STD_ROM_FN(Sgemfa) + +static struct BurnRomInfo SgemfhRomDesc[] = { + { "pcfh.03", 0x080000, 0xe9103347, 1 | BRF_ESS | BRF_PRG }, + { "pcf.04", 0x080000, 0xf4314c96, 1 | BRF_ESS | BRF_PRG }, + { "pcf.05", 0x080000, 0x215655f6, 1 | BRF_ESS | BRF_PRG }, + { "pcf.06", 0x080000, 0xea6f13ea, 1 | BRF_ESS | BRF_PRG }, + { "pcf.07", 0x080000, 0x5ac6d5ea, 1 | BRF_ESS | BRF_PRG }, + + { "pcf.13m", 0x400000, 0x22d72ab9, 3 | BRF_GRA }, + { "pcf.15m", 0x400000, 0x16a4813c, 3 | BRF_GRA }, + { "pcf.17m", 0x400000, 0x1097e035, 3 | BRF_GRA }, + { "pcf.19m", 0x400000, 0xd362d874, 3 | BRF_GRA }, + { "pcf.14m", 0x100000, 0x0383897c, 3 | BRF_GRA }, + { "pcf.16m", 0x100000, 0x76f91084, 3 | BRF_GRA }, + { "pcf.18m", 0x100000, 0x756c3754, 3 | BRF_GRA }, + { "pcf.20m", 0x100000, 0x9ec9277d, 3 | BRF_GRA }, + + { "pcf.01", 0x020000, 0x254e5f33, 4 | BRF_ESS | BRF_PRG }, + { "pcf.02", 0x020000, 0x6902f4f9, 4 | BRF_ESS | BRF_PRG }, + + { "pcf.11m", 0x400000, 0xa5dea005, 5 | BRF_SND }, + { "pcf.12m", 0x400000, 0x4ce235fe, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sgemfh) +STD_ROM_FN(Sgemfh) + +static struct BurnRomInfo Spf2tRomDesc[] = { + { "pzfu.03a", 0x080000, 0x346e62ef, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2t) +STD_ROM_FN(Spf2t) + +static struct BurnRomInfo Spf2taRomDesc[] = { + { "pzfa.03", 0x080000, 0x3cecfa78, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2ta) +STD_ROM_FN(Spf2ta) + +static struct BurnRomInfo Spf2thRomDesc[] = { + { "pzfh.03", 0x080000, 0x20510f2d, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2th) +STD_ROM_FN(Spf2th) + +static struct BurnRomInfo Spf2xjRomDesc[] = { + { "pzfj.03a", 0x080000, 0x2070554a, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2xj) +STD_ROM_FN(Spf2xj) + +static struct BurnRomInfo Ssf2RomDesc[] = { + { "ssfe.03", 0x080000, 0xa597745d, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.04", 0x080000, 0xb082aa67, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.05", 0x080000, 0x02b9c137, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.06", 0x080000, 0x70d470c5, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.07", 0x080000, 0x2409001d, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2) +STD_ROM_FN(Ssf2) + +static struct BurnRomInfo Ssf2aRomDesc[] = { + { "ssfa.03b", 0x080000, 0x83a059bf, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.04a", 0x080000, 0x5d873642, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.05", 0x080000, 0xf8fb4de2, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.06b", 0x080000, 0x3185d19d, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.07", 0x080000, 0x36e29217, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2a) +STD_ROM_FN(Ssf2a) + +static struct BurnRomInfo Ssf2ar1RomDesc[] = { + { "ssfa.03a", 0x080000, 0xd2a3c520, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.04a", 0x080000, 0x5d873642, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.05", 0x080000, 0xf8fb4de2, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.06", 0x080000, 0xaa8acee7, 1 | BRF_ESS | BRF_PRG }, + { "ssfa.07", 0x080000, 0x36e29217, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2ar1) +STD_ROM_FN(Ssf2ar1) + +static struct BurnRomInfo Ssf2hRomDesc[] = { + { "ssfh.03", 0x080000, 0xb086b355, 1 | BRF_ESS | BRF_PRG }, + { "ssfh.04", 0x080000, 0x1e629b29, 1 | BRF_ESS | BRF_PRG }, + { "ssfh.05", 0x080000, 0xb5997e10, 1 | BRF_ESS | BRF_PRG }, + { "ssfh.06", 0x080000, 0x793b8fad, 1 | BRF_ESS | BRF_PRG }, + { "ssfh.07", 0x080000, 0xcbb92ac3, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2h) +STD_ROM_FN(Ssf2h) + +static struct BurnRomInfo Ssf2jRomDesc[] = { + { "ssfj.03b", 0x080000, 0x5c2e356d, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.04a", 0x080000, 0x013bd55c, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.05", 0x080000, 0x0918d19a, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.06b", 0x080000, 0x014e0c6d, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.07", 0x080000, 0xeb6a9b1b, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2j) +STD_ROM_FN(Ssf2j) + +static struct BurnRomInfo Ssf2jr1RomDesc[] = { + { "ssfj.03a", 0x080000, 0x0bbf1304, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.04a", 0x080000, 0x013bd55c, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.05", 0x080000, 0x0918d19a, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.06", 0x080000, 0xd808a6cd, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.07", 0x080000, 0xeb6a9b1b, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2jr1) +STD_ROM_FN(Ssf2jr1) + +static struct BurnRomInfo Ssf2jr2RomDesc[] = { + { "ssfj.03", 0x080000, 0x7eb0efed, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.04", 0x080000, 0xd7322164, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.05", 0x080000, 0x0918d19a, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.06", 0x080000, 0xd808a6cd, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.07", 0x080000, 0xeb6a9b1b, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2jr2) +STD_ROM_FN(Ssf2jr2) + +static struct BurnRomInfo Ssf2uRomDesc[] = { + { "ssfu.03a", 0x080000, 0x72f29c33, 1 | BRF_ESS | BRF_PRG }, + { "ssfu.04a", 0x080000, 0x935cea44, 1 | BRF_ESS | BRF_PRG }, + { "ssfu.05", 0x080000, 0xa0acb28a, 1 | BRF_ESS | BRF_PRG }, + { "ssfu.06", 0x080000, 0x47413dcf, 1 | BRF_ESS | BRF_PRG }, + { "ssfu.07", 0x080000, 0xe6066077, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2u) +STD_ROM_FN(Ssf2u) + +static struct BurnRomInfo Ssf2tbRomDesc[] = { + { "ssfe.3tc", 0x080000, 0x496a8409, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.4tc", 0x080000, 0x4b45c18b, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.5t", 0x080000, 0x6a9c6444, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.6tb", 0x080000, 0xe4944fc3, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.7t", 0x080000, 0x2c9f4782, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tb) +STD_ROM_FN(Ssf2tb) + +static struct BurnRomInfo Ssf2tbr1RomDesc[] = { + { "ssfe.3t", 0x080000, 0x1e018e34, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.4t", 0x080000, 0xac92efaf, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.5t", 0x080000, 0x6a9c6444, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.6t", 0x080000, 0xf442562b, 1 | BRF_ESS | BRF_PRG }, + { "ssfe.7t", 0x080000, 0x2c9f4782, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tbr1) +STD_ROM_FN(Ssf2tbr1) + +static struct BurnRomInfo Ssf2tbjRomDesc[] = { + { "ssfj.3t", 0x080000, 0x980d4450, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.4t", 0x080000, 0xb4dc1906, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.5t", 0x080000, 0xa7e35fbc, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.6t", 0x080000, 0xcb592b30, 1 | BRF_ESS | BRF_PRG }, + { "ssfj.7t", 0x080000, 0x1f239515, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tbj) +STD_ROM_FN(Ssf2tbj) + +static struct BurnRomInfo Ssf2tRomDesc[] = { + { "sfxe.03c", 0x080000, 0x2fa1f396, 1 | BRF_ESS | BRF_PRG }, + { "sfxe.04a", 0x080000, 0xd0bc29c6, 1 | BRF_ESS | BRF_PRG }, + { "sfxe.05", 0x080000, 0x65222964, 1 | BRF_ESS | BRF_PRG }, + { "sfxe.06a", 0x080000, 0x8fe9f531, 1 | BRF_ESS | BRF_PRG }, + { "sfxe.07", 0x080000, 0x8a7d0cb6, 1 | BRF_ESS | BRF_PRG }, + { "sfxe.08", 0x080000, 0x74c24062, 1 | BRF_ESS | BRF_PRG }, + { "sfx.09", 0x080000, 0x642fae3f, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2t) +STD_ROM_FN(Ssf2t) + +static struct BurnRomInfo Ssf2taRomDesc[] = { + { "sfxa.03c", 0x080000, 0x04b9ff34, 1 | BRF_ESS | BRF_PRG }, + { "sfxa.04a", 0x080000, 0x16ea5f7a, 1 | BRF_ESS | BRF_PRG }, + { "sfxa.05", 0x080000, 0x53d61f0c, 1 | BRF_ESS | BRF_PRG }, + { "sfxa.06a", 0x080000, 0x066d09b5, 1 | BRF_ESS | BRF_PRG }, + { "sfxa.07", 0x080000, 0xa428257b, 1 | BRF_ESS | BRF_PRG }, + { "sfxa.08", 0x080000, 0x39be596c, 1 | BRF_ESS | BRF_PRG }, + { "sfx.09", 0x080000, 0x642fae3f, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2ta) +STD_ROM_FN(Ssf2ta) + +static struct BurnRomInfo Ssf2tuRomDesc[] = { + { "sfxu.03e", 0x080000, 0xd6ff689e, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.04a", 0x080000, 0x532b5ffd, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.05", 0x080000, 0xffa3c6de, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.06b", 0x080000, 0x83f9382b, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.07a", 0x080000, 0x6ab673e8, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.08", 0x080000, 0xb3c71810, 1 | BRF_ESS | BRF_PRG }, + { "sfx.09", 0x080000, 0x642fae3f, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tu) +STD_ROM_FN(Ssf2tu) + +static struct BurnRomInfo Ssf2tur1RomDesc[] = { + { "sfxu.03c", 0x080000, 0x86e4a335, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.04a", 0x080000, 0x532b5ffd, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.05", 0x080000, 0xffa3c6de, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.06a", 0x080000, 0xe4c04c99, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.07", 0x080000, 0xd8199e41, 1 | BRF_ESS | BRF_PRG }, + { "sfxu.08", 0x080000, 0xb3c71810, 1 | BRF_ESS | BRF_PRG }, + { "sfx.09", 0x080000, 0x642fae3f, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tur1) +STD_ROM_FN(Ssf2tur1) + +static struct BurnRomInfo Ssf2xjRomDesc[] = { + { "sfxj.03c", 0x080000, 0xa7417b79, 1 | BRF_ESS | BRF_PRG }, + { "sfxj.04a", 0x080000, 0xaf7767b4, 1 | BRF_ESS | BRF_PRG }, + { "sfxj.05", 0x080000, 0xf4ff18f5, 1 | BRF_ESS | BRF_PRG }, + { "sfxj.06a", 0x080000, 0x260d0370, 1 | BRF_ESS | BRF_PRG }, + { "sfxj.07", 0x080000, 0x1324d02a, 1 | BRF_ESS | BRF_PRG }, + { "sfxj.08", 0x080000, 0x2de76f10, 1 | BRF_ESS | BRF_PRG }, + { "sfx.09", 0x080000, 0x642fae3f, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2xj) +STD_ROM_FN(Ssf2xj) + +static struct BurnRomInfo Vhunt2RomDesc[] = { + { "vh2j.03a", 0x080000, 0x9ae8f186, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.04a", 0x080000, 0xe2fabf53, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.05", 0x080000, 0xde34f624, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.06", 0x080000, 0x6a3b9897, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.07", 0x080000, 0xb021c029, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.08", 0x080000, 0xac873dff, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.09", 0x080000, 0xeaefce9c, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.10", 0x080000, 0x11730952, 1 | BRF_ESS | BRF_PRG }, + + { "vh2.13m", 0x400000, 0x3b02ddaa, 3 | BRF_GRA }, + { "vh2.15m", 0x400000, 0x4e40de66, 3 | BRF_GRA }, + { "vh2.17m", 0x400000, 0xb31d00c9, 3 | BRF_GRA }, + { "vh2.19m", 0x400000, 0x149be3ab, 3 | BRF_GRA }, + { "vh2.14m", 0x400000, 0xcd09bd63, 3 | BRF_GRA }, + { "vh2.16m", 0x400000, 0xe0182c15, 3 | BRF_GRA }, + { "vh2.18m", 0x400000, 0x778dc4f6, 3 | BRF_GRA }, + { "vh2.20m", 0x400000, 0x605d9d1d, 3 | BRF_GRA }, + + { "vh2.01", 0x020000, 0x67b9f779, 4 | BRF_ESS | BRF_PRG }, + { "vh2.02", 0x020000, 0xaaf15fcb, 4 | BRF_ESS | BRF_PRG }, + + { "vh2.11m", 0x400000, 0x38922efd, 5 | BRF_SND }, + { "vh2.12m", 0x400000, 0x6e2430af, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhunt2) +STD_ROM_FN(Vhunt2) + +static struct BurnRomInfo Vhunt2r1RomDesc[] = { + { "vh2j.03", 0x080000, 0x1a5feb13, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.04", 0x080000, 0x434611a5, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.05", 0x080000, 0xde34f624, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.06", 0x080000, 0x6a3b9897, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.07", 0x080000, 0xb021c029, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.08", 0x080000, 0xac873dff, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.09", 0x080000, 0xeaefce9c, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.10", 0x080000, 0x11730952, 1 | BRF_ESS | BRF_PRG }, + + { "vh2.13m", 0x400000, 0x3b02ddaa, 3 | BRF_GRA }, + { "vh2.15m", 0x400000, 0x4e40de66, 3 | BRF_GRA }, + { "vh2.17m", 0x400000, 0xb31d00c9, 3 | BRF_GRA }, + { "vh2.19m", 0x400000, 0x149be3ab, 3 | BRF_GRA }, + { "vh2.14m", 0x400000, 0xcd09bd63, 3 | BRF_GRA }, + { "vh2.16m", 0x400000, 0xe0182c15, 3 | BRF_GRA }, + { "vh2.18m", 0x400000, 0x778dc4f6, 3 | BRF_GRA }, + { "vh2.20m", 0x400000, 0x605d9d1d, 3 | BRF_GRA }, + + { "vh2.01", 0x020000, 0x67b9f779, 4 | BRF_ESS | BRF_PRG }, + { "vh2.02", 0x020000, 0xaaf15fcb, 4 | BRF_ESS | BRF_PRG }, + + { "vh2.11m", 0x400000, 0x38922efd, 5 | BRF_SND }, + { "vh2.12m", 0x400000, 0x6e2430af, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhunt2r1) +STD_ROM_FN(Vhunt2r1) + +static struct BurnRomInfo VsavRomDesc[] = { + { "vm3e.03d", 0x080000, 0xf5962a8c, 1 | BRF_ESS | BRF_PRG }, + { "vm3e.04d", 0x080000, 0x21b40ea2, 1 | BRF_ESS | BRF_PRG }, + { "vm3.05a", 0x080000, 0x4118e00f, 1 | BRF_ESS | BRF_PRG }, + { "vm3.06a", 0x080000, 0x2f4fd3a9, 1 | BRF_ESS | BRF_PRG }, + { "vm3.07b", 0x080000, 0xcbda91b8, 1 | BRF_ESS | BRF_PRG }, + { "vm3.08a", 0x080000, 0x6ca47259, 1 | BRF_ESS | BRF_PRG }, + { "vm3.09b", 0x080000, 0xf4a339e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3.10b", 0x080000, 0xfffbb5b8, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsav) +STD_ROM_FN(Vsav) + +static struct BurnRomInfo VsavaRomDesc[] = { + { "vm3a.03d", 0x080000, 0x44c1198f, 1 | BRF_ESS | BRF_PRG }, + { "vm3a.04d", 0x080000, 0x2218b781, 1 | BRF_ESS | BRF_PRG }, + { "vm3.05a", 0x080000, 0x4118e00f, 1 | BRF_ESS | BRF_PRG }, + { "vm3.06a", 0x080000, 0x2f4fd3a9, 1 | BRF_ESS | BRF_PRG }, + { "vm3.07b", 0x080000, 0xcbda91b8, 1 | BRF_ESS | BRF_PRG }, + { "vm3.08a", 0x080000, 0x6ca47259, 1 | BRF_ESS | BRF_PRG }, + { "vm3.09b", 0x080000, 0xf4a339e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3.10b", 0x080000, 0xfffbb5b8, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsava) +STD_ROM_FN(Vsava) + +static struct BurnRomInfo VsavhRomDesc[] = { + { "vm3h.03a", 0x080000, 0x7cc62df8, 1 | BRF_ESS | BRF_PRG }, + { "vm3h.04d", 0x080000, 0xd716f3b5, 1 | BRF_ESS | BRF_PRG }, + { "vm3.05a", 0x080000, 0x4118e00f, 1 | BRF_ESS | BRF_PRG }, + { "vm3.06a", 0x080000, 0x2f4fd3a9, 1 | BRF_ESS | BRF_PRG }, + { "vm3.07b", 0x080000, 0xcbda91b8, 1 | BRF_ESS | BRF_PRG }, + { "vm3.08a", 0x080000, 0x6ca47259, 1 | BRF_ESS | BRF_PRG }, + { "vm3.09b", 0x080000, 0xf4a339e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3.10b", 0x080000, 0xfffbb5b8, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsavh) +STD_ROM_FN(Vsavh) + +static struct BurnRomInfo VsavjRomDesc[] = { + { "vm3j.03d", 0x080000, 0x2a2e74a4, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.04d", 0x080000, 0x1c2427bc, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.05a", 0x080000, 0x95ce88d5, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.06b", 0x080000, 0x2c4297e0, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.07b", 0x080000, 0xa38aaae7, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.08a", 0x080000, 0x5773e5c9, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.09b", 0x080000, 0xd064f8b9, 1 | BRF_ESS | BRF_PRG }, + { "vm3j.10b", 0x080000, 0x434518e9, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsavj) +STD_ROM_FN(Vsavj) + +static struct BurnRomInfo VsavuRomDesc[] = { + { "vm3u.03d", 0x080000, 0x1f295274, 1 | BRF_ESS | BRF_PRG }, + { "vm3u.04d", 0x080000, 0xc46adf81, 1 | BRF_ESS | BRF_PRG }, + { "vm3.05a", 0x080000, 0x4118e00f, 1 | BRF_ESS | BRF_PRG }, + { "vm3.06a", 0x080000, 0x2f4fd3a9, 1 | BRF_ESS | BRF_PRG }, + { "vm3.07b", 0x080000, 0xcbda91b8, 1 | BRF_ESS | BRF_PRG }, + { "vm3.08a", 0x080000, 0x6ca47259, 1 | BRF_ESS | BRF_PRG }, + { "vm3.09b", 0x080000, 0xf4a339e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3.10b", 0x080000, 0xfffbb5b8, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsavu) +STD_ROM_FN(Vsavu) + +static struct BurnRomInfo Vsav2RomDesc[] = { + { "vs2j.03", 0x080000, 0x89fd86b4, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.04", 0x080000, 0x107c091b, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.05", 0x080000, 0x61979638, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.06", 0x080000, 0xf37c5bc2, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.07", 0x080000, 0x8f885809, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.08", 0x080000, 0x2018c120, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.09", 0x080000, 0xfac3c217, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.10", 0x080000, 0xeb490213, 1 | BRF_ESS | BRF_PRG }, + + { "vs2.13m", 0x400000, 0x5c852f52, 3 | BRF_GRA }, + { "vs2.15m", 0x400000, 0xa20f58af, 3 | BRF_GRA }, + { "vs2.17m", 0x400000, 0x39db59ad, 3 | BRF_GRA }, + { "vs2.19m", 0x400000, 0x00c763a7, 3 | BRF_GRA }, + { "vs2.14m", 0x400000, 0xcd09bd63, 3 | BRF_GRA }, + { "vs2.16m", 0x400000, 0xe0182c15, 3 | BRF_GRA }, + { "vs2.18m", 0x400000, 0x778dc4f6, 3 | BRF_GRA }, + { "vs2.20m", 0x400000, 0x605d9d1d, 3 | BRF_GRA }, + + { "vs2.01", 0x020000, 0x35190139, 4 | BRF_ESS | BRF_PRG }, + { "vs2.02", 0x020000, 0xc32dba09, 4 | BRF_ESS | BRF_PRG }, + + { "vs2.11m", 0x400000, 0xd67e47b7, 5 | BRF_SND }, + { "vs2.12m", 0x400000, 0x6d020a14, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsav2) +STD_ROM_FN(Vsav2) + +static struct BurnRomInfo XmcotaRomDesc[] = { + { "xmne.03e", 0x080000, 0xa9a09b09, 1 | BRF_ESS | BRF_PRG }, + { "xmne.04e", 0x080000, 0x52fa2106, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcota) +STD_ROM_FN(Xmcota) + +static struct BurnRomInfo XmcotaaRomDesc[] = { + { "xmna.03e", 0x080000, 0xf1ade6e7, 1 | BRF_ESS | BRF_PRG }, + { "xmna.04e", 0x080000, 0xb5a8843d, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaa) +STD_ROM_FN(Xmcotaa) + +static struct BurnRomInfo Xmcotaar1RomDesc[] = { + { "xmna.03a", 0x080000, 0x7df8b27e, 1 | BRF_ESS | BRF_PRG }, + { "xmna.04a", 0x080000, 0xb44e30a7, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05", 0x080000, 0xc3ed62a2, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06", 0x080000, 0xf03c52e1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07", 0x080000, 0x325626b1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08", 0x080000, 0x7194ea10, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09", 0x080000, 0xae946df3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10", 0x080000, 0x32a6be1d, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaar1) +STD_ROM_FN(Xmcotaar1) + +static struct BurnRomInfo XmcotahRomDesc[] = { + { "xmnh.03", 0x080000, 0xe4b85a90, 1 | BRF_ESS | BRF_PRG }, + { "xmnh.04", 0x080000, 0x7dfe1406, 1 | BRF_ESS | BRF_PRG }, + { "xmnh.05", 0x080000, 0x87b0ed0f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmnh.10", 0x080000, 0xcb36b0a4, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotah) +STD_ROM_FN(Xmcotah) + +static struct BurnRomInfo Xmcotahr1RomDesc[] = { + { "xmnh.03d", 0x080000, 0x63b0a84f, 1 | BRF_ESS | BRF_PRG }, + { "xmnh.04d", 0x080000, 0xb1b9b727, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotahr1) +STD_ROM_FN(Xmcotahr1) + +static struct BurnRomInfo XmcotajRomDesc[] = { + { "xmnj.03e", 0x080000, 0x0df29f5f, 1 | BRF_ESS | BRF_PRG }, + { "xmnj.04e", 0x080000, 0x4a65833b, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaj) +STD_ROM_FN(Xmcotaj) + +static struct BurnRomInfo Xmcotaj1RomDesc[] = { + { "xmnj.03d", 0x080000, 0x79086d62, 1 | BRF_ESS | BRF_PRG }, + { "xmnj.04d", 0x080000, 0x38eed613, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05", 0x080000, 0xc3ed62a2, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06", 0x080000, 0xf03c52e1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07", 0x080000, 0x325626b1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08", 0x080000, 0x7194ea10, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09", 0x080000, 0xae946df3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10", 0x080000, 0x32a6be1d, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaj1) +STD_ROM_FN(Xmcotaj1) + +static struct BurnRomInfo Xmcotaj2RomDesc[] = { + { "xmnj.03b", 0x080000, 0xc8175fb3, 1 | BRF_ESS | BRF_PRG }, + { "xmnj.04b", 0x080000, 0x54b3fba3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05", 0x080000, 0xc3ed62a2, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06", 0x080000, 0xf03c52e1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07", 0x080000, 0x325626b1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08", 0x080000, 0x7194ea10, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09", 0x080000, 0xae946df3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10", 0x080000, 0x32a6be1d, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaj2) +STD_ROM_FN(Xmcotaj2) + +static struct BurnRomInfo Xmcotaj3RomDesc[] = { + { "xmnj.03a", 0x080000, 0x00761611, 1 | BRF_ESS | BRF_PRG }, + { "xmnj.04a", 0x080000, 0x614d3f60, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05", 0x080000, 0xc3ed62a2, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06", 0x080000, 0xf03c52e1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07", 0x080000, 0x325626b1, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08", 0x080000, 0x7194ea10, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09", 0x080000, 0xae946df3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10", 0x080000, 0x32a6be1d, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotaj3) +STD_ROM_FN(Xmcotaj3) + +static struct BurnRomInfo XmcotajrRomDesc[] = { + { "xmno.03a", 0x080000, 0x7ab19acf, 1 | BRF_ESS | BRF_PRG }, + { "xmno.04a", 0x080000, 0x7615dd21, 1 | BRF_ESS | BRF_PRG }, + { "xmno.05a", 0x080000, 0x0303d672, 1 | BRF_ESS | BRF_PRG }, + { "xmno.06a", 0x080000, 0x332839a5, 1 | BRF_ESS | BRF_PRG }, + { "xmno.07", 0x080000, 0x6255e8d5, 1 | BRF_ESS | BRF_PRG }, + { "xmno.08", 0x080000, 0xb8ebe77c, 1 | BRF_ESS | BRF_PRG }, + { "xmno.09", 0x080000, 0x5440d950, 1 | BRF_ESS | BRF_PRG }, + { "xmno.10a", 0x080000, 0xb8296966, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01", 0x020000, 0x7178336e, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02", 0x020000, 0x0ec58501, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotajr) +STD_ROM_FN(Xmcotajr) + +static struct BurnRomInfo XmcotauRomDesc[] = { + { "xmnu.03e", 0x080000, 0x0bafeb0e, 1 | BRF_ESS | BRF_PRG }, + { "xmnu.04e", 0x080000, 0xc29bdae3, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotau) +STD_ROM_FN(Xmcotau) + +static struct BurnRomInfo XmvsfRomDesc[] = { + { "xvse.03f", 0x080000, 0xdb06413f, 1 | BRF_ESS | BRF_PRG }, + { "xvse.04f", 0x080000, 0xef015aef, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsf) +STD_ROM_FN(Xmvsf) + +static struct BurnRomInfo Xmvsfr1RomDesc[] = { + { "xvse.03d", 0x080000, 0x5ae5bd3b, 1 | BRF_ESS | BRF_PRG }, + { "xvse.04d", 0x080000, 0x5eb9c02e, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfr1) +STD_ROM_FN(Xmvsfr1) + +static struct BurnRomInfo XmvsfaRomDesc[] = { + { "xvsa.03k", 0x080000, 0xd0cca7a8, 1 | BRF_ESS | BRF_PRG }, + { "xvsa.04k", 0x080000, 0x8c8e76fd, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfa) +STD_ROM_FN(Xmvsfa) + +static struct BurnRomInfo Xmvsfar1RomDesc[] = { + { "xvsa.03e", 0x080000, 0x9bdde21c, 1 | BRF_ESS | BRF_PRG }, + { "xvsa.04e", 0x080000, 0x33300edf, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfar1) +STD_ROM_FN(Xmvsfar1) + +static struct BurnRomInfo Xmvsfar2RomDesc[] = { + { "xvsa.03d", 0x080000, 0x2b164fd7, 1 | BRF_ESS | BRF_PRG }, + { "xvsa.04d", 0x080000, 0x2d32f039, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvsa.02", 0x020000, 0x19272e4c, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfar2) +STD_ROM_FN(Xmvsfar2) + +static struct BurnRomInfo XmvsfbRomDesc[] = { + { "xvsb.03h", 0x080000, 0x05baccca, 1 | BRF_ESS | BRF_PRG }, + { "xvsb.04h", 0x080000, 0xe350c755, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfb) +STD_ROM_FN(Xmvsfb) + +static struct BurnRomInfo XmvsfhRomDesc[] = { + { "xvsh.03a", 0x080000, 0xd4fffb04, 1 | BRF_ESS | BRF_PRG }, + { "xvsh.04a", 0x080000, 0x1b4ea638, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfh) +STD_ROM_FN(Xmvsfh) + +static struct BurnRomInfo XmvsfjRomDesc[] = { + { "xvsj.03i", 0x080000, 0xef24da96, 1 | BRF_ESS | BRF_PRG }, + { "xvsj.04i", 0x080000, 0x70a59b35, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfj) +STD_ROM_FN(Xmvsfj) + +static struct BurnRomInfo Xmvsfjr1RomDesc[] = { + { "xvsj.03d", 0x080000, 0xbeb81de9, 1 | BRF_ESS | BRF_PRG }, + { "xvsj.04d", 0x080000, 0x23d11271, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfjr1) +STD_ROM_FN(Xmvsfjr1) + +static struct BurnRomInfo Xmvsfjr2RomDesc[] = { + { "xvsj.03c", 0x080000, 0x180656a1, 1 | BRF_ESS | BRF_PRG }, + { "xvsj.04c", 0x080000, 0x5832811c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05", 0x080000, 0x030e0e1e, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06", 0x080000, 0x5d04a8ff, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfjr2) +STD_ROM_FN(Xmvsfjr2) + +static struct BurnRomInfo XmvsfuRomDesc[] = { + { "xvsu.03k", 0x080000, 0x8739ef61, 1 | BRF_ESS | BRF_PRG }, + { "xvsu.04k", 0x080000, 0xe11d35c1, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfu) +STD_ROM_FN(Xmvsfu) + +static struct BurnRomInfo Xmvsfur1RomDesc[] = { + { "xvsu.03h", 0x080000, 0x5481155a, 1 | BRF_ESS | BRF_PRG }, + { "xvsu.04h", 0x080000, 0x1e236388, 1 | BRF_ESS | BRF_PRG }, + { "xvs.05a", 0x080000, 0x7db6025d, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvs.07", 0x080000, 0x08f0abed, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfur1) +STD_ROM_FN(Xmvsfur1) + +// Driver functions + +static INT32 Pzloop2Init() +{ + Pzloop2 = 1; + + return Cps2Init(); +} + +static INT32 Ssf2Init() +{ + INT32 nRet = Cps2Init(); + + nCpsGfxScroll[3] = 0; + + return nRet; +} + +static INT32 Ssf2tbInit() +{ + Ssf2tb = 1; + + return Ssf2Init(); +} + +static INT32 Ssf2tInit() +{ + INT32 nRet; + + Ssf2t = 1; + + nRet = Cps2Init(); + + nCpsGfxScroll[3] = 0; + + return nRet; +} + +static INT32 XmcotaInit() +{ + Xmcota = 1; + + return Cps2Init(); +} + +static INT32 DrvExit() +{ + Pzloop2 = 0; + Ssf2t = 0; + Ssf2tb = 0; + Xmcota = 0; + + return CpsExit(); +} + +// Driver Definitions + +struct BurnDriver BurnDrvCps19xx = { + "19xx", NULL, NULL, NULL, "1995", + "19XX - the war against destiny (951207 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxRomInfo, NinexxRomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps19xxa = { + "19xxa", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951207 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxaRomInfo, NinexxaRomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps19xxb = { + "19xxb", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951218 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxbRomInfo, NinexxbRomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps19xxh = { + "19xxh", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951218 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxhRomInfo, NinexxhRomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps19xxj = { + "19xxj", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951225 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxjRomInfo, NinexxjRomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps19xxjr1 = { + "19xxjr1", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951207 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, Ninexxjr1RomInfo, Ninexxjr1RomName, NULL, NULL, NineXXInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps1944 = { + "1944", NULL, NULL, NULL, "2000", + "1944 - the loop master (000620 USA)\0", NULL, "Capcom / 8ing / Raizing", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, Nine44RomInfo, Nine44RomName, NULL, NULL, Nine44InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCps1944j = { + "1944j", "1944", NULL, NULL, "2000", + "1944 - the loop master (000620 Japan)\0", NULL, "Capcom / 8ing / Raizing", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, Nine44jRomInfo, Nine44jRomName, NULL, NULL, Nine44InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwar = { + "armwar", NULL, NULL, NULL, "1994", + "Armored Warriors (941024 Europe)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, ArmwarRomInfo, ArmwarRomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwarr1 = { + "armwarr1", "armwar", NULL, NULL, "1994", + "Armored Warriors (941011 Europe)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Armwarr1RomInfo, Armwarr1RomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwara = { + "armwara", "armwar", NULL, NULL, "1994", + "Armored Warriors (940920 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, ArmwaraRomInfo, ArmwaraRomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwaru = { + "armwaru", "armwar", NULL, NULL, "1994", + "Armored Warriors (941024 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, ArmwaruRomInfo, ArmwaruRomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwaru1 = { + "armwaru1", "armwar", NULL, NULL, "1994", + "Armored Warriors (940920 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Armwaru1RomInfo, Armwaru1RomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPgear = { + "pgear", "armwar", NULL, NULL, "1994", + "Powered Gear - strategic variant armor equipment (941024 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, PgearRomInfo, PgearRomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPgearr1 = { + "pgearr1", "armwar", NULL, NULL, "1994", + "Powered Gear - strategic variant armor equipment (940916 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Pgearr1RomInfo, Pgearr1RomName, NULL, NULL, ArmwarInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvsp = { + "avsp", NULL, NULL, NULL, "1994", + "Alien vs Predator (940520 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvspRomInfo, AvspRomName, NULL, NULL, AvspInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvspa = { + "avspa", "avsp", NULL, NULL, "1994", + "Alien vs Predator (940520 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvspaRomInfo, AvspaRomName, NULL, NULL, AvspInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvsph = { + "avsph", "avsp", NULL, NULL, "1994", + "Alien vs Predator (940520 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvsphRomInfo, AvsphRomName, NULL, NULL, AvspInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvspj = { + "avspj", "avsp", NULL, NULL, "1994", + "Alien vs Predator (940520 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvspjRomInfo, AvspjRomName, NULL, NULL, AvspInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvspu = { + "avspu", "avsp", NULL, NULL, "1994", + "Alien vs Predator (940520 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvspuRomInfo, AvspuRomName, NULL, NULL, AvspInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsBatcir = { + "batcir", NULL, NULL, NULL, "1997", + "Battle Circuit (970319 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, BatcirRomInfo, BatcirRomName, NULL, NULL, BatcirInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsBatcira = { + "batcira", "batcir", NULL, NULL, "1997", + "Battle Circuit (970319 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, BatciraRomInfo, BatciraRomName, NULL, NULL, BatcirInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsBatcirj = { + "batcirj", "batcir", NULL, NULL, "1997", + "Battle Circuit (970319 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, BatcirjRomInfo, BatcirjRomName, NULL, NULL, BatcirInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsChoko = { + "choko", NULL, NULL, NULL, "2001", + "Choko (010820 Japan)\0", NULL, "Mitchell", "CPS2", + L"\u9577\u6C5F (Choko 010820 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, ChokoRomInfo, ChokoRomName, NULL, NULL, ChokoInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclub = { + "csclub", NULL, NULL, NULL, "1997", + "Capcom Sports Club (971017 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, CsclubRomInfo, CsclubRomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclub1 = { + "csclub1", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, Csclub1RomInfo, Csclub1RomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCscluba = { + "cscluba", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, CsclubaRomInfo, CsclubaRomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclubh = { + "csclubh", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, CsclubhRomInfo, CsclubhRomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclubj = { + "csclubj", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, CsclubjRomInfo, CsclubjRomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclubjr = { + "csclubjr", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Japan, Rent version)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, CsclubjrRomInfo, CsclubjrRomName, NULL, NULL, CsclubInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCybots = { + "cybots", NULL, NULL, NULL, "1995", + "Cyberbots - fullmetal madness (950424 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, CybotsRomInfo, CybotsRomName, NULL, NULL, CybotsInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCybotsj = { + "cybotsj", "cybots", NULL, NULL, "1995", + "Cyberbots - fullmetal madness (950420 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, CybotsjRomInfo, CybotsjRomName, NULL, NULL, CybotsInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCybotsu = { + "cybotsu", "cybots", NULL, NULL, "1995", + "Cyberbots - fullmetal madness (950424 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, CybotsuRomInfo, CybotsuRomName, NULL, NULL, CybotsInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsom = { + "ddsom", NULL, NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960619 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomRomInfo, DdsomRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomr1 = { + "ddsomr1", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960223 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddsomr1RomInfo, Ddsomr1RomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomr2 = { + "ddsomr2", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960209 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddsomr2RomInfo, Ddsomr2RomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomr3 = { + "ddsomr3", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960208 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddsomr3RomInfo, Ddsomr3RomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsoma = { + "ddsoma", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960619 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomaRomInfo, DdsomaRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomb = { + "ddsomb", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960223 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsombRomInfo, DdsombRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomh = { + "ddsomh", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960223 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomhRomInfo, DdsomhRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomj = { + "ddsomj", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960619 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomjRomInfo, DdsomjRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomjr1 = { + "ddsomjr1", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960206 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddsomjr1RomInfo, Ddsomjr1RomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomu = { + "ddsomu", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960619 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomuRomInfo, DdsomuRomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomur1 = { + "ddsomur1", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960209 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddsomur1RomInfo, Ddsomur1RomName, NULL, NULL, DdsomInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtod = { + "ddtod", NULL, NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940412 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtodRomInfo, DdtodRomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodr1 = { + "ddtodr1", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940113 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodr1RomInfo, Ddtodr1RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtoda = { + "ddtoda", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940113 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtodaRomInfo, DdtodaRomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodh = { + "ddtodh", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940412 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtodhRomInfo, DdtodhRomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodhr1 = { + "ddtodhr1", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940125 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodhr1RomInfo, Ddtodhr1RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodhr2 = { + "ddtodhr2", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940113 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodhr2RomInfo, Ddtodhr2RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodj = { + "ddtodj", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940412 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtodjRomInfo, DdtodjRomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodjr1 = { + "ddtodjr1", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940125 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodjr1RomInfo, Ddtodjr1RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodjr2 = { + "ddtodjr2", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940113 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodjr2RomInfo, Ddtodjr2RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodu = { + "ddtodu", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940125 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtoduRomInfo, DdtoduRomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodur1 = { + "ddtodur1", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940113 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Ddtodur1RomInfo, Ddtodur1RomName, NULL, NULL, DdtodInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDimahoo = { + "dimahoo", NULL, NULL, NULL, "2000", + "Dimahoo (000121 Euro)\0", NULL, "8ing / Raizing / Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, DimahooRomInfo, DimahooRomName, NULL, NULL, DimahooInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsGreatMahouDaiJ = { + "gmahou", "dimahoo", NULL, NULL, "2000", + "Great Mahou Daisakusen (000121 Japan)\0", NULL, "8ing / Raizing / Capcom", "CPS2", + L"\u30B0\u30EC\u30FC\u30C8\u9B54\u6CD5\u5927\u4F5C\u6226 (Great Mahou Daisakusen 000121 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GmdjRomInfo, GmdjRomName, NULL, NULL, DimahooInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsDimahoou = { + "dimahoou", "dimahoo", NULL, NULL, "2000", + "Dimahoo (000121 USA)\0", NULL, "8ing / Raizing / Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, DimahoouRomInfo, DimahoouRomName, NULL, NULL, DimahooInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsDstlk = { + "dstlk", NULL, NULL, NULL, "1994", + "Darkstalkers - the night warriors (940705 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, DstlkRomInfo, DstlkRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDstlka = { + "dstlka", "dstlk", NULL, NULL, "1994", + "Darkstalkers - the night warriors (940705 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, DstlkaRomInfo, DstlkaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDstlkh = { + "dstlkh", "dstlk", NULL, NULL, "1994", + "Darkstalkers - the night warriors (940818 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, DstlkhRomInfo, DstlkhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDstlku = { + "dstlku", "dstlk", NULL, NULL, "1994", + "Darkstalkers - the night warriors (940818 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, DstlkuRomInfo, DstlkuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDstlkur1 = { + "dstlkur1", "dstlk", NULL, NULL, "1994", + "Darkstalkers - the night warriors (940705 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Dstlkur1RomInfo, Dstlkur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVampj = { + "vampj", "dstlk", NULL, NULL, "1994", + "Vampire - the night warriors (940705 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VampjRomInfo, VampjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVampja = { + "vampja", "dstlk", NULL, NULL, "1994", + "Vampire - the night warriors (940705 Japan, alt)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VampjaRomInfo, VampjaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVampjr1 = { + "vampjr1", "dstlk", NULL, NULL, "1994", + "Vampire - the night warriors (940630 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vampjr1RomInfo, Vampjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtr = { + "ecofghtr", NULL, NULL, NULL, "1993", + "Eco Fighters (931203 etc)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, EcofghtrRomInfo, EcofghtrRomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtra = { + "ecofghtra", "ecofghtr", NULL, NULL, "1993", + "Eco Fighters (931203 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, EcofghtraRomInfo, EcofghtraRomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtrh = { + "ecofghtrh", "ecofghtr", NULL, NULL, "1993", + "Eco Fighters (931203 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, EcofghtrhRomInfo, EcofghtrhRomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtru = { + "ecofghtru", "ecofghtr", NULL, NULL, "1993", + "Eco Fighters (940215 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, EcofghtruRomInfo, EcofghtruRomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtru1 = { + "ecofghtru1", "ecofghtr", NULL, NULL, "1993", + "Eco Fighters (931203 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, Ecofghtru1RomInfo, Ecofghtru1RomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsUecology = { + "uecology", "ecofghtr", NULL, NULL, "1993", + "Ultimate Ecology (931203 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, UecologyRomInfo, UecologyRomName, NULL, NULL, EcofghtrInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawing = { + "gigawing", NULL, NULL, NULL, "1999", + "Giga Wing (990222 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingRomInfo, GigawingRomName, NULL, NULL, GigawingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawinga = { + "gigawinga", "gigawing", NULL, NULL, "1999", + "Giga Wing (990222 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingaRomInfo, GigawingaRomName, NULL, NULL, GigawingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawingb = { + "gigawingb", "gigawing", NULL, NULL, "1999", + "Giga Wing (990222 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingbRomInfo, GigawingbRomName, NULL, NULL, GigawingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawingh = { + "gigawingh", "gigawing", NULL, NULL, "1999", + "Giga Wing (990222 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawinghRomInfo, GigawinghRomName, NULL, NULL, GigawingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawingj = { + "gigawingj", "gigawing", NULL, NULL, "1999", + "Giga Wing (990223 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingjRomInfo, GigawingjRomName, NULL, NULL, GigawingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsHsf2 = { + "hsf2", NULL, NULL, NULL, "2004", + "Hyper Street Fighter 2: The Anniversary Edition (040202 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Hsf2RomInfo, Hsf2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsHsf2a = { + "hsf2a", "hsf2", NULL, NULL, "2004", + "Hyper Street Fighter 2: The Anniversary Edition (040202 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Hsf2aRomInfo, Hsf2aRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsHsf2j = { + "hsf2j", "hsf2", NULL, NULL, "2004", + "Hyper Street Fighter 2: The Anniversary Edition (031222 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Hsf2jRomInfo, Hsf2jRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsJyangoku = { + "jyangoku", NULL, NULL, NULL, "1999", + "Jyangokushi -Haoh no Saihai- (990527 Japan)\0", NULL, "Mitchell", "CPS2", + L"\u96C0\u570B\u5FD7 -\u8987\u738B\u306E\u91C7\u724C- (Jyangokushi 990527 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_MAHJONG, 0, + NULL, JyangokuRomInfo, JyangokuRomName, NULL, NULL, JyangokuInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegaman2 = { + "megaman2", NULL, NULL, NULL, "1996", + "Mega Man 2 - the power fighters (960708 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Megaman2RomInfo, Megaman2RomName, NULL, NULL, Megaman2InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000 ,384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegaman2a = { + "megaman2a", "megaman2", NULL, NULL, "1996", + "Mega Man 2 - the power fighters (960708 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Megaman2aRomInfo, Megaman2aRomName, NULL, NULL, Megaman2InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000 ,384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegaman2h = { + "megaman2h", "megaman2", NULL, NULL, "1996", + "Mega Man 2 - the power fighters (960712 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Megaman2hRomInfo, Megaman2hRomName, NULL, NULL, Megaman2InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000 ,384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRockman2j = { + "rockman2j", "megaman2", NULL, NULL, "1996", + "Rockman 2 - the power fighters (960708 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Rockman2jRomInfo, Rockman2jRomName, NULL, NULL, Megaman2InputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMmancp2u = { + "mmancp2u", "megaman", NULL, NULL, "1999", + "Mega Man - The Power Battle (951006 USA, SAMPLE Version)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Mmancp2uRomInfo, Mmancp2uRomName, NULL, NULL, Mmancp2uInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRmancp2j = { + "rmancp2j", "mmancp2u", NULL, NULL, "1999", + "Rockman: The Power Battle (950922 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Rmancp2jRomInfo, Rmancp2jRomName, NULL, NULL, Mmancp2uInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMarsMatrix = { + "mmatrix", NULL, NULL, NULL, "2000", + "Mars Matrix (000412 USA)\0", NULL, "Capcom / Takumi", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, MmatrixRomInfo, MmatrixRomName, NULL, NULL, MmatrixInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMarsMatrixJ = { + "mmatrixj", "mmatrix", NULL, NULL, "2000", + "Mars Matrix (000412 Japan)\0", NULL, "Capcom / Takumi", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, MmatrixjRomInfo, MmatrixjRomName, NULL, NULL, MmatrixInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMPang = { + "mpang", NULL, NULL, NULL, "2000", + "Mighty! Pang (001010 Euro)\0", NULL, "Mitchell", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, MpangRomInfo, MpangRomName, NULL, NULL, MpangInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMPangr1 = { + "mpangr1", "mpang", NULL, NULL, "2000", + "Mighty! Pang (000925 Euro)\0", NULL, "Mitchell", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, Mpangr1RomInfo, Mpangr1RomName, NULL, NULL, MpangInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMPangu = { + "mpangu", "mpang", NULL, NULL, "2000", + "Mighty! Pang (001010 USA)\0", NULL, "Mitchell", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, 0, + NULL, MpanguRomInfo, MpanguRomName, NULL, NULL, MpangInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMPangj = { + "mpangj", "mpang", NULL, NULL, "2000", + "Mighty! Pang (001011 Japan)\0", NULL, "Mitchell", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, MpangjRomInfo, MpangjRomName, NULL, NULL, MpangInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMsh = { + "msh", NULL, NULL, NULL, "1995", + "Marvel Super Heroes (951024 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshRomInfo, MshRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMsha = { + "msha", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951024 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshaRomInfo, MshaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshb = { + "mshb", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951117 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshbRomInfo, MshbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshh = { + "mshh", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951117 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshhRomInfo, MshhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshj = { + "mshj", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951117 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshjRomInfo, MshjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshjr1 = { + "mshjr1", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951024 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Mshjr1RomInfo, Mshjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshu = { + "mshu", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951024 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshuRomInfo, MshuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsf = { + "mshvsf", NULL, NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfRomInfo, MshvsfRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfa = { + "mshvsfa", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfaRomInfo, MshvsfaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfa1 = { + "mshvsfa1", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970620 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfa1RomInfo, Mshvsfa1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfb = { + "mshvsfb", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970827 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfbRomInfo, MshvsfbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfb1 = { + "mshvsfb1", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfb1RomInfo, Mshvsfb1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfh = { + "mshvsfh", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfhRomInfo, MshvsfhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfj = { + "mshvsfj", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970707 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfjRomInfo, MshvsfjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfj1 = { + "mshvsfj1", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970702 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfj1RomInfo, Mshvsfj1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfj2 = { + "mshvsfj2", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfj2RomInfo, Mshvsfj2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfu = { + "mshvsfu", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970827 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MshvsfuRomInfo, MshvsfuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfu1 = { + "mshvsfu1", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfu1RomInfo, Mshvsfu1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvsc = { + "mvsc", NULL, NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscRomInfo, MvscRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscr1 = { + "mvscr1", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980112 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mvscr1RomInfo, Mvscr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvsca = { + "mvsca", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscaRomInfo, MvscaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscar1 = { + "mvscar1", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980112 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mvscar1RomInfo, Mvscar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscb = { + "mvscb", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscbRomInfo, MvscbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvsch = { + "mvsch", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvschRomInfo, MvschRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscj = { + "mvscj", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscjRomInfo, MvscjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscjr1 = { + "mvscjr1", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980112 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mvscjr1RomInfo, Mvscjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscu = { + "mvscu", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscuRomInfo, MvscuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscur1 = { + "mvscur1", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (971222 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mvscur1RomInfo, Mvscur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarr = { + "nwarr", NULL, NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950316 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarrRomInfo, NwarrRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarra = { + "nwarra", "nwarr", NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950302 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarraRomInfo, NwarraRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarrb = { + "nwarrb", "nwarr", NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950403 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarrbRomInfo, NwarrbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarrh = { + "nwarrh", "nwarr", NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950403 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarrhRomInfo, NwarrhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarru = { + "nwarru", "nwarr", NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950406 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarruRomInfo, NwarruRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhuntj = { + "vhuntj", "nwarr", NULL, NULL, "1995", + "Vampire Hunter - darkstalkers' revenge (950316 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VhuntjRomInfo, VhuntjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhuntjr1 = { + "vhuntjr1", "nwarr", NULL, NULL, "1995", + "Vampire Hunter - darkstalkers' revenge (950307 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vhuntjr1RomInfo, Vhuntjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhuntjr2 = { + "vhuntjr2", "nwarr", NULL, NULL, "1995", + "Vampire Hunter - darkstalkers' revenge (950302 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vhuntjr2RomInfo, Vhuntjr2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgear = { + "progear", NULL, NULL, NULL, "2001", + "Progear (010117 USA)\0", NULL, "Capcom / Cave", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearRomInfo, ProgearRomName, NULL, NULL, ProgearInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgeara = { + "progeara", "progear", NULL, NULL, "2001", + "Progear (010117 Asia)\0", NULL, "Capcom / Cave", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearaRomInfo, ProgearaRomName, NULL, NULL, ProgearInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgearj = { + "progearj", "progear", NULL, NULL, "2001", + "Progear No Arashi (010117 Japan)\0", NULL, "Capcom / Cave", "CPS2", + L"\u30D7\u30ED\u30AE\u30A2\u306E\u5D50 (Progear No Arashi 010117 Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearjRomInfo, ProgearjRomName, NULL, NULL, ProgearInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPzloop2 = { + "pzloop2", NULL, NULL, NULL, "2001", + "Puzz Loop 2 (010302 Euro)\0", NULL, "Mitchell, distritued by Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, Pzloop2RomInfo, Pzloop2RomName, NULL, NULL, Pzloop2InputInfo, NULL, + Pzloop2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPzloop2j = { + "pzloop2j", "pzloop2", NULL, NULL, "2001", + "Puzz Loop 2 (010205 Japan)\0", NULL, "Mitchell, distritued by Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_PUZZLE, 0, + NULL, Pzloop2jRomInfo, Pzloop2jRomName, NULL, NULL, Pzloop2InputInfo, NULL, + Pzloop2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsQndream = { + "qndream", NULL, NULL, NULL, "1996", + "Quiz Nanairo Dreams - nijiirochou no kiseki (nanairo dreams 960826 Japan)\0", NULL, "Capcom", "CPS2", + L"Quiz \u306A\u306A\u3044\u308D Dreams - \u8679\u8272\u753A\u306E\u5947\u8DE1 (Nanairo Dreams 960826 Japan)\0Quiz Nanairo Dreams - nijiirochou no kiseki\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_QUIZ, 0, + NULL, QndreamRomInfo, QndreamRomName, NULL, NULL, QndreamInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRingdest = { + "ringdest", NULL, NULL, NULL, "1994", + "Ring of Destruction - slammasters II (940902 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, RingdestRomInfo, RingdestRomName, NULL, NULL, RingdestInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSmbomb = { + "smbomb", "ringdest", NULL, NULL, "1994", + "Super Muscle Bomber - the international blowout (940831 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, SmbombRomInfo, SmbombRomName, NULL, NULL, RingdestInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSmbombr1 = { + "smbombr1", "ringdest", NULL, NULL, "1994", + "Super Muscle Bomber - the international blowout (940808 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Smbombr1RomInfo, Smbombr1RomName, NULL, NULL, RingdestInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRingdesta = { + "ringdesta", "ringdest", NULL, NULL, "1994", + "Ring of Destruction - slammasters II (940831 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, RingdestaRomInfo, RingdestaRomName, NULL, NULL, RingdestInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa = { + "sfa", NULL, NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950727 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfaRomInfo, SfaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfar1 = { + "sfar1", "sfa", NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950718 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfar1RomInfo, Sfar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfar2 = { + "sfar2", "sfa", NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950627 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfar2RomInfo, Sfar2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfar3 = { + "sfar3", "sfa", NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950605 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfar3RomInfo, Sfar3RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfau = { + "sfau", "sfa", NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950627 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfauRomInfo, SfauRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfza = { + "sfza", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950627 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfzaRomInfo, SfzaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzb = { + "sfzb", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (951109 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfzbRomInfo, SfzbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzbr1 = { + "sfzbr1", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950727 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfzbr1RomInfo, Sfzbr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzh = { + "sfzh", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950718 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfzhRomInfo, SfzhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzhr1 = { + "sfzhr1", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950627 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfzhr1RomInfo, Sfzhr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzj = { + "sfzj", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950727 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfzjRomInfo, SfzjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzjr1 = { + "sfzjr1", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950627 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfzjr1RomInfo, Sfzjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfzjr2 = { + "sfzjr2", "sfa", NULL, NULL, "1995", + "Street Fighter Zero (950605 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfzjr2RomInfo, Sfzjr2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa2 = { + "sfa2", NULL, NULL, NULL, "1996", + "Street Fighter Alpha 2 (960229 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa2RomInfo, Sfa2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa2u = { + "sfa2u", "sfa2", NULL, NULL, "1996", + "Street Fighter Alpha 2 (960430 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa2uRomInfo, Sfa2uRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa2ur1 = { + "sfa2ur1", "sfa2", NULL, NULL, "1996", + "Street Fighter Alpha 2 (960306 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa2ur1RomInfo, Sfa2ur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2a = { + "sfz2a", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960227 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2aRomInfo, Sfz2aRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2b = { + "sfz2b", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960531 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2bRomInfo, Sfz2bRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2br1 = { + "sfz2br1", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960304 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2br1RomInfo, Sfz2br1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2h = { + "sfz2h", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960304 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2hRomInfo, Sfz2hRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2j = { + "sfz2j", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960227 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2jRomInfo, Sfz2jRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2n = { + "sfz2n", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960229 Oceania)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2nRomInfo, Sfz2nRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2al = { + "sfz2al", NULL, NULL, NULL, "1996", + "Street Fighter Zero 2 Alpha (960826 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2alRomInfo, Sfz2alRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2alb = { + "sfz2alb", "sfz2al", NULL, NULL, "1996", + "Street Fighter Zero 2 Alpha (960813 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2albRomInfo, Sfz2albRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2alh = { + "sfz2alh", "sfz2al", NULL, NULL, "1996", + "Street Fighter Zero 2 Alpha (960813 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2alhRomInfo, Sfz2alhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2alj = { + "sfz2alj", "sfz2al", NULL, NULL, "1996", + "Street Fighter Zero 2 Alpha (960805 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2aljRomInfo, Sfz2aljRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3 = { + "sfa3", NULL, NULL, NULL, "1998", + "Street Fighter Alpha 3 (980904 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3RomInfo, Sfa3RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3b = { + "sfa3b", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980629 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3bRomInfo, Sfa3bRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3h = { + "sfa3h", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980904 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3hRomInfo, Sfa3hRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3hr1 = { + "sfa3hr1", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980629 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3hr1RomInfo, Sfa3hr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3u = { + "sfa3u", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980904 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3uRomInfo, Sfa3uRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3ur1 = { + "sfa3ur1", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980629 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3ur1RomInfo, Sfa3ur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3a = { + "sfz3a", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980904 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3aRomInfo, Sfz3aRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3ar1 = { + "sfz3ar1", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980701 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3ar1RomInfo, Sfz3ar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3j = { + "sfz3j", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980904 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3jRomInfo, Sfz3jRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3jr1 = { + "sfz3jr1", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980727 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3jr1RomInfo, Sfz3jr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3jr2 = { + "sfz3jr2", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980629 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3jr2RomInfo, Sfz3jr2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSgemf = { + "sgemf", NULL, NULL, NULL, "1997", + "Super Gem Fighter Mini Mix (970904 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SgemfRomInfo, SgemfRomName, NULL, NULL, SgemfInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsPfghtj = { + "pfghtj", "sgemf", NULL, NULL, "1997", + "Pocket Fighter (970904 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, PfghtjRomInfo, PfghtjRomName, NULL, NULL, SgemfInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSgemfa = { + "sgemfa", "sgemf", NULL, NULL, "1997", + "Super Gem Fighter Mini Mix (970904 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SgemfaRomInfo, SgemfaRomName, NULL, NULL, SgemfInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSgemfh = { + "sgemfh", "sgemf", NULL, NULL, "1997", + "Super Gem Fighter Mini Mix (970904 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SgemfhRomInfo, SgemfhRomName, NULL, NULL, SgemfInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2t = { + "spf2t", NULL, NULL, NULL, "1996", + "Super Puzzle Fighter II Turbo (Super Puzzle Fighter 2 Turbo 960620 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2tRomInfo, Spf2tRomName, NULL, NULL, Spf2tInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2xj = { + "spf2xj", "spf2t", NULL, NULL, "1996", + "Super Puzzle Fighter II X (Super Puzzle Fighter 2 X 960531 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2xjRomInfo, Spf2xjRomName, NULL, NULL, Spf2tInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2ta = { + "spf2ta", "spf2t", NULL, NULL, "1996", + "Super Puzzle Fighter II Turbo (Super Puzzle Fighter 2 Turbo 960529 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2taRomInfo, Spf2taRomName, NULL, NULL, Spf2tInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2th = { + "spf2th", "spf2t", NULL, NULL, "1996", + "Super Puzzle Fighter II Turbo (Super Puzzle Fighter 2 Turbo 960531 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2thRomInfo, Spf2thRomName, NULL, NULL, Spf2tInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2 = { + "ssf2", NULL, NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930911 etc)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2RomInfo, Ssf2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2a = { + "ssf2a", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 931005 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE,2,HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2aRomInfo, Ssf2aRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2ar1 = { + "ssf2ar1", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930914 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2ar1RomInfo, Ssf2ar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2h = { + "ssf2h", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930911 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE,2,HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2hRomInfo, Ssf2hRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2j = { + "ssf2j", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 931005 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2jRomInfo, Ssf2jRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2jr1 = { + "ssf2jr1", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930911 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2jr1RomInfo, Ssf2jr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2jr2 = { + "ssf2jr2", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930910 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2jr2RomInfo, Ssf2jr2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2u = { + "ssf2u", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930911 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2uRomInfo, Ssf2uRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tb = { + "ssf2tb", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the tournament battle (931119 etc)\0", "Linkup feature not implemented", "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tbRomInfo, Ssf2tbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tbInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tbr1 = { + "ssf2tbr1", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the tournament battle (930911 etc)\0", "Linkup feature not implemented", "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tbr1RomInfo, Ssf2tbr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tbInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tbj = { + "ssf2tbj", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the tournament battle (930911 Japan)\0", "Linkup feature not implemented", "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tbjRomInfo, Ssf2tbjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tbInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2t = { + "ssf2t", NULL, NULL, NULL, "1994", + "Super Street Fighter II Turbo (super street fighter 2 X 940223 etc)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tRomInfo, Ssf2tRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2ta = { + "ssf2ta", "ssf2t", NULL, NULL, "1994", + "Super Street Fighter II Turbo (super street fighter 2 X 940223 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2taRomInfo, Ssf2taRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tu = { + "ssf2tu", "ssf2t", NULL, NULL, "1994", + "Super Street Fighter II Turbo (super street fighter 2 X 940323 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tuRomInfo, Ssf2tuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tur1 = { + "ssf2tur1", "ssf2t", NULL, NULL, "1994", + "Super Street Fighter II Turbo (super street fighter 2 X 940223 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tur1RomInfo, Ssf2tur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2xj = { + "ssf2xj", "ssf2t", NULL, NULL, "1994", + "Super Street Fighter II X - grand master challenge (super street fighter 2 X 940223 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2xjRomInfo, Ssf2xjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhunt2 = { + "vhunt2", NULL, NULL, NULL, "1997", + "Vampire Hunter 2 - darkstalkers revenge (970929 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vhunt2RomInfo, Vhunt2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhunt2r1 = { + "vhunt2r1", "vhunt2", NULL, NULL, "1997", + "Vampire Hunter 2 - darkstalkers revenge (970913 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vhunt2r1RomInfo, Vhunt2r1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsav = { + "vsav", NULL, NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavRomInfo, VsavRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsava = { + "vsava", "vsav", NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavaRomInfo, VsavaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsavh = { + "vsavh", "vsav", NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavhRomInfo, VsavhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsavj = { + "vsavj", "vsav", NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavjRomInfo, VsavjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsavu = { + "vsavu", "vsav", NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavuRomInfo, VsavuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsav2 = { + "vsav2", NULL, NULL, NULL, "1997", + "Vampire Savior 2 - the lord of vampire (970913 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vsav2RomInfo, Vsav2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcota = { + "xmcota", NULL, NULL, NULL, "1995", + "X-Men - children of the atom (950105 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotaRomInfo, XmcotaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaa = { + "xmcotaa", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (950105 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotaaRomInfo, XmcotaaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaar1 = { + "xmcotaar1", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (941217 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Xmcotaar1RomInfo, Xmcotaar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotah = { + "xmcotah", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (950331 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2,HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotahRomInfo, XmcotahRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotahr1 = { + "xmcotahr1", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (950105 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2,HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Xmcotahr1RomInfo, Xmcotahr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaj = { + "xmcotaj", "xmcota", NULL, NULL, "1994", + "X-Men - children of the atom (950105 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotajRomInfo, XmcotajRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaj1 = { + "xmcotaj1", "xmcota", NULL, NULL, "1994", + "X-Men - children of the atom (941222 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Xmcotaj1RomInfo, Xmcotaj1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaj2 = { + "xmcotaj2", "xmcota", NULL, NULL, "1994", + "X-Men - children of the atom (941219 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Xmcotaj2RomInfo, Xmcotaj2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotaj3 = { + "xmcotaj3", "xmcota", NULL, NULL, "1994", + "X-Men - children of the atom (941217 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Xmcotaj3RomInfo, Xmcotaj3RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotajr = { + "xmcotajr", "xmcota", NULL, NULL, "1994", + "X-Men - children of the atom (941208 Japan, rent version)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotajrRomInfo, XmcotajrRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotau = { + "xmcotau", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (950105 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotauRomInfo, XmcotauRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + XmcotaInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsf = { + "xmvsf", NULL, NULL, NULL, "1996", + "X-Men vs Street Fighter (961004 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfRomInfo, XmvsfRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfr1 = { + "xmvsfr1", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (960910 Euro)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfr1RomInfo, Xmvsfr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfa = { + "xmvsfa", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961023 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfaRomInfo, XmvsfaRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfar1 = { + "xmvsfar1", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (960919 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfar1RomInfo, Xmvsfar1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfar2 = { + "xmvsfar2", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (960910 Asia)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfar2RomInfo, Xmvsfar2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfb = { + "xmvsfb", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961023 Brazil)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfbRomInfo, XmvsfbRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfh = { + "xmvsfh", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961004 Hispanic)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfhRomInfo, XmvsfhRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfj = { + "xmvsfj", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961004 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfjRomInfo, XmvsfjRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfjr1 = { + "xmvsfjr1", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (960910 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfjr1RomInfo, Xmvsfjr1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfjr2 = { + "xmvsfjr2", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (960909 Japan)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfjr2RomInfo, Xmvsfjr2RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfu = { + "xmvsfu", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961023 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, XmvsfuRomInfo, XmvsfuRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfur1 = { + "xmvsfur1", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961004 USA)\0", NULL, "Capcom", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfur1RomInfo, Xmvsfur1RomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +// Phoenix sets + +static struct BurnRomInfo NinexxdRomDesc[] = { + { "19xud.03", 0x080000, 0xf81b60e5, 1 | BRF_ESS | BRF_PRG }, + { "19xud.04", 0x080000, 0xcc44638c, 1 | BRF_ESS | BRF_PRG }, + { "19xud.05", 0x080000, 0x33a168de, 1 | BRF_ESS | BRF_PRG }, + { "19xud.06", 0x080000, 0xe0111282, 1 | BRF_ESS | BRF_PRG }, + { "19x.07", 0x080000, 0x61c0296c, 1 | BRF_ESS | BRF_PRG }, + + { "19x.13m", 0x080000, 0x427aeb18, 3 | BRF_GRA }, + { "19x.15m", 0x080000, 0x63bdbf54, 3 | BRF_GRA }, + { "19x.17m", 0x080000, 0x2dfe18b5, 3 | BRF_GRA }, + { "19x.19m", 0x080000, 0xcbef9579, 3 | BRF_GRA }, + { "19x.14m", 0x200000, 0xe916967c, 3 | BRF_GRA }, + { "19x.16m", 0x200000, 0x6e75f3db, 3 | BRF_GRA }, + { "19x.18m", 0x200000, 0x2213e798, 3 | BRF_GRA }, + { "19x.20m", 0x200000, 0xab9d5b96, 3 | BRF_GRA }, + + { "19x.01", 0x020000, 0xef55195e, 4 | BRF_ESS | BRF_PRG }, + + { "19x.11m", 0x200000, 0xd38beef3, 5 | BRF_SND }, + { "19x.12m", 0x200000, 0xd47c96e2, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ninexxd) +STD_ROM_FN(Ninexxd) + +static struct BurnRomInfo Nine44dRomDesc[] = { + { "nffud.03", 0x080000, 0x28e8aae4, 1 | BRF_ESS | BRF_PRG }, + { "nff.04", 0x080000, 0xDBA1C66E, 1 | BRF_ESS | BRF_PRG }, + { "nffu.05", 0x080000, 0xEA813EB7, 1 | BRF_ESS | BRF_PRG }, + + { "nff.13m", 0x400000, 0xC9FCA741, 3 | BRF_GRA }, + { "nff.15m", 0x400000, 0xF809D898, 3 | BRF_GRA }, + { "nff.17m", 0x400000, 0x15BA4507, 3 | BRF_GRA }, + { "nff.19m", 0x400000, 0x3DD41B8C, 3 | BRF_GRA }, + { "nff.14m", 0x100000, 0x3FE3A54B, 3 | BRF_GRA }, + { "nff.16m", 0x100000, 0x565CD231, 3 | BRF_GRA }, + { "nff.18m", 0x100000, 0x63CA5988, 3 | BRF_GRA }, + { "nff.20m", 0x100000, 0x21EB8F3B, 3 | BRF_GRA }, + + { "nff.01", 0x020000, 0xD2E44318, 4 | BRF_ESS | BRF_PRG }, + + { "nff.11m", 0x400000, 0x243E4E05, 5 | BRF_SND }, + { "nff.12m", 0x400000, 0x4FCF1600, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nine44d) +STD_ROM_FN(Nine44d) + +static struct BurnRomInfo Armwar1dRomDesc[] = { + { "pwged.03b", 0x080000, 0x496bd483, 1 | BRF_ESS | BRF_PRG }, + { "pwged.04b", 0x080000, 0x9bd6a38f, 1 | BRF_ESS | BRF_PRG }, + { "pwged.05a", 0x080000, 0x4c11d30f, 1 | BRF_ESS | BRF_PRG }, + { "pwg.06", 0x080000, 0x87a60ce8, 1 | BRF_ESS | BRF_PRG }, + { "pwg.07", 0x080000, 0xf7b148df, 1 | BRF_ESS | BRF_PRG }, + { "pwg.08", 0x080000, 0xcc62823e, 1 | BRF_ESS | BRF_PRG }, + { "pwg.09", 0x080000, 0xddc85ca6, 1 | BRF_ESS | BRF_PRG }, + { "pwg.10", 0x080000, 0x07c4fb28, 1 | BRF_ESS | BRF_PRG }, + + { "pwg.13m", 0x400000, 0xae8fe08e, 3 | BRF_GRA }, + { "pwg.15m", 0x400000, 0xdb560f58, 3 | BRF_GRA }, + { "pwg.17m", 0x400000, 0xbc475b94, 3 | BRF_GRA }, + { "pwg.19m", 0x400000, 0x07439ff7, 3 | BRF_GRA }, + { "pwg.14m", 0x100000, 0xc3f9ba63, 3 | BRF_GRA }, + { "pwg.16m", 0x100000, 0x815b0e7b, 3 | BRF_GRA }, + { "pwg.18m", 0x100000, 0x0109c71b, 3 | BRF_GRA }, + { "pwg.20m", 0x100000, 0xeb75ffbe, 3 | BRF_GRA }, + + { "pwg.01", 0x020000, 0x18a5c0e4, 4 | BRF_ESS | BRF_PRG }, + { "pwg.02", 0x020000, 0xc9dfffa6, 4 | BRF_ESS | BRF_PRG }, + + { "pwg.11m", 0x200000, 0xa78f7433, 5 | BRF_SND }, + { "pwg.12m", 0x200000, 0x77438ed0, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Armwar1d) +STD_ROM_FN(Armwar1d) + +static struct BurnRomInfo AvspdRomDesc[] = { + { "avped.03d", 0x080000, 0x66aa8aad, 1 | BRF_ESS | BRF_PRG }, + { "avped.04d", 0x080000, 0x579306c2, 1 | BRF_ESS | BRF_PRG }, + { "avp.05d", 0x080000, 0xfbfb5d7a, 1 | BRF_ESS | BRF_PRG }, + { "avpd.06", 0x080000, 0x63094539, 1 | BRF_ESS | BRF_PRG }, + + { "avp.13m", 0x200000, 0x8f8b5ae4, 3 | BRF_GRA }, + { "avp.15m", 0x200000, 0xb00280df, 3 | BRF_GRA }, + { "avp.17m", 0x200000, 0x94403195, 3 | BRF_GRA }, + { "avp.19m", 0x200000, 0xe1981245, 3 | BRF_GRA }, + { "avp.14m", 0x200000, 0xebba093e, 3 | BRF_GRA }, + { "avp.16m", 0x200000, 0xfb228297, 3 | BRF_GRA }, + { "avp.18m", 0x200000, 0x34fb7232, 3 | BRF_GRA }, + { "avp.20m", 0x200000, 0xf90baa21, 3 | BRF_GRA }, + + { "avp.01", 0x020000, 0x2d3b4220, 4 | BRF_ESS | BRF_PRG }, + + { "avp.11m", 0x200000, 0x83499817, 5 | BRF_SND }, + { "avp.12m", 0x200000, 0xf4110d49, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Avspd) +STD_ROM_FN(Avspd) + +static struct BurnRomInfo BatcirdRomDesc[] = { + { "btced.03", 0x080000, 0x0737db6d, 1 | BRF_ESS | BRF_PRG }, + { "btced.04", 0x080000, 0xef1a8823, 1 | BRF_ESS | BRF_PRG }, + { "btced.05", 0x080000, 0x20bdbb14, 1 | BRF_ESS | BRF_PRG }, + { "btced.06", 0x080000, 0xb4d8f5bc, 1 | BRF_ESS | BRF_PRG }, + { "btc.07", 0x080000, 0x7322d5db, 1 | BRF_ESS | BRF_PRG }, + { "btc.08", 0x080000, 0x6aac85ab, 1 | BRF_ESS | BRF_PRG }, + { "btc.09", 0x080000, 0x1203db08, 1 | BRF_ESS | BRF_PRG }, + + { "btc.13m", 0x400000, 0xdc705bad, 3 | BRF_GRA }, + { "btc.15m", 0x400000, 0xe5779a3c, 3 | BRF_GRA }, + { "btc.17m", 0x400000, 0xb33f4112, 3 | BRF_GRA }, + { "btc.19m", 0x400000, 0xa6fcdb7e, 3 | BRF_GRA }, + + { "btc.01", 0x020000, 0x1e194310, 4 | BRF_ESS | BRF_PRG }, + { "btc.02", 0x020000, 0x01aeb8e6, 4 | BRF_ESS | BRF_PRG }, + + { "btc.11m", 0x200000, 0xc27f2229, 5 | BRF_SND }, + { "btc.12m", 0x200000, 0x418a2e33, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Batcird) +STD_ROM_FN(Batcird) + +static struct BurnRomInfo Csclub1dRomDesc[] = { + { "csce_d.03", 0x080000, 0x5aedc6e6, 1 | BRF_ESS | BRF_PRG }, + { "csce_d.04", 0x080000, 0xa3d9aa25, 1 | BRF_ESS | BRF_PRG }, + { "csce_d.05", 0x080000, 0x0915c9d1, 1 | BRF_ESS | BRF_PRG }, + { "csce_d.06", 0x080000, 0x09c77d99, 1 | BRF_ESS | BRF_PRG }, + { "csc_d.07", 0x080000, 0x77478e25, 1 | BRF_ESS | BRF_PRG }, + + { "csc.73", 0x080000, 0x335f07c3, 6 | BRF_GRA }, + { "csc.74", 0x080000, 0xab215357, 6 | BRF_GRA }, + { "csc.75", 0x080000, 0xa2367381, 6 | BRF_GRA }, + { "csc.76", 0x080000, 0x728aac1f, 6 | BRF_GRA }, + { "csc.63", 0x080000, 0x3711b8ca, 6 | BRF_GRA }, + { "csc.64", 0x080000, 0x828a06d8, 6 | BRF_GRA }, + { "csc.65", 0x080000, 0x86ee4569, 6 | BRF_GRA }, + { "csc.66", 0x080000, 0xc24f577f, 6 | BRF_GRA }, + { "csc.83", 0x080000, 0x0750d12a, 6 | BRF_GRA }, + { "csc.84", 0x080000, 0x90a92f39, 6 | BRF_GRA }, + { "csc.85", 0x080000, 0xd08ab012, 6 | BRF_GRA }, + { "csc.86", 0x080000, 0x41652583, 6 | BRF_GRA }, + { "csc.93", 0x080000, 0xa756c7f7, 6 | BRF_GRA }, + { "csc.94", 0x080000, 0xfb7ccc73, 6 | BRF_GRA }, + { "csc.95", 0x080000, 0x4d014297, 6 | BRF_GRA }, + { "csc.96", 0x080000, 0x6754b1ef, 6 | BRF_GRA }, + + { "csc.01", 0x020000, 0xee162111, 4 | BRF_ESS | BRF_PRG }, + + { "csc.51", 0x080000, 0x5a52afd5, 5 | BRF_SND }, + { "csc.52", 0x080000, 0x1408a811, 5 | BRF_SND }, + { "csc.53", 0x080000, 0x4fb9f57c, 5 | BRF_SND }, + { "csc.54", 0x080000, 0x9a8f40ec, 5 | BRF_SND }, + { "csc.55", 0x080000, 0x91529a91, 5 | BRF_SND }, + { "csc.56", 0x080000, 0x9a345334, 5 | BRF_SND }, + { "csc.57", 0x080000, 0xaedc27f2, 5 | BRF_SND }, + { "csc.58", 0x080000, 0x2300b7b3, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Csclub1d) +STD_ROM_FN(Csclub1d) + +static struct BurnRomInfo CybotsudRomDesc[] = { + { "cybu_d.03", 0x080000, 0xee7560fb, 1 | BRF_ESS | BRF_PRG }, + { "cybu_d.04", 0x080000, 0x7e7425a0, 1 | BRF_ESS | BRF_PRG }, + { "cyb.05", 0x080000, 0xec40408e, 1 | BRF_ESS | BRF_PRG }, + { "cyb.06", 0x080000, 0x1ad0bed2, 1 | BRF_ESS | BRF_PRG }, + { "cyb.07", 0x080000, 0x6245a39a, 1 | BRF_ESS | BRF_PRG }, + { "cyb.08", 0x080000, 0x4b48e223, 1 | BRF_ESS | BRF_PRG }, + { "cyb.09", 0x080000, 0xe15238f6, 1 | BRF_ESS | BRF_PRG }, + { "cyb.10", 0x080000, 0x75f4003b, 1 | BRF_ESS | BRF_PRG }, + + { "cyb.13m", 0x400000, 0xf0dce192, 3 | BRF_GRA }, + { "cyb.15m", 0x400000, 0x187aa39c, 3 | BRF_GRA }, + { "cyb.17m", 0x400000, 0x8a0e4b12, 3 | BRF_GRA }, + { "cyb.19m", 0x400000, 0x34b62612, 3 | BRF_GRA }, + { "cyb.14m", 0x400000, 0xc1537957, 3 | BRF_GRA }, + { "cyb.16m", 0x400000, 0x15349e86, 3 | BRF_GRA }, + { "cyb.18m", 0x400000, 0xd83e977d, 3 | BRF_GRA }, + { "cyb.20m", 0x400000, 0x77cdad5c, 3 | BRF_GRA }, + + { "cyb.01", 0x020000, 0x9c0fb079, 4 | BRF_ESS | BRF_PRG }, + { "cyb.02", 0x020000, 0x51cb0c4e, 4 | BRF_ESS | BRF_PRG }, + + { "cyb.11m", 0x200000, 0x362ccab2, 5 | BRF_SND }, + { "cyb.12m", 0x200000, 0x7066e9cc, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Cybotsud) +STD_ROM_FN(Cybotsud) + +static struct BurnRomInfo DdsomudRomDesc[] = { + { "dd2ud.03g", 0x080000, 0x816f695a, 1 | BRF_ESS | BRF_PRG }, + { "dd2ud.04g", 0x080000, 0x7cc81c6b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.05g", 0x080000, 0x5eb1991c, 1 | BRF_ESS | BRF_PRG }, + { "dd2.06g", 0x080000, 0xc26b5e55, 1 | BRF_ESS | BRF_PRG }, + { "dd2.07", 0x080000, 0x909a0b8b, 1 | BRF_ESS | BRF_PRG }, + { "dd2.08", 0x080000, 0xe53c4d01, 1 | BRF_ESS | BRF_PRG }, + { "dd2.09", 0x080000, 0x5f86279f, 1 | BRF_ESS | BRF_PRG }, + { "dd2d.10", 0x080000, 0x0c172f8f, 1 | BRF_ESS | BRF_PRG }, + + { "dd2.13m", 0x400000, 0xa46b4e6e, 3 | BRF_GRA }, + { "dd2.15m", 0x400000, 0xd5fc50fc, 3 | BRF_GRA }, + { "dd2.17m", 0x400000, 0x837c0867, 3 | BRF_GRA }, + { "dd2.19m", 0x400000, 0xbb0ec21c, 3 | BRF_GRA }, + { "dd2.14m", 0x200000, 0x6d824ce2, 3 | BRF_GRA }, + { "dd2.16m", 0x200000, 0x79682ae5, 3 | BRF_GRA }, + { "dd2.18m", 0x200000, 0xacddd149, 3 | BRF_GRA }, + { "dd2.20m", 0x200000, 0x117fb0c0, 3 | BRF_GRA }, + + { "dd2.01", 0x020000, 0x99d657e5, 4 | BRF_ESS | BRF_PRG }, + { "dd2.02", 0x020000, 0x117a3824, 4 | BRF_ESS | BRF_PRG }, + + { "dd2.11m", 0x200000, 0x98d0c325, 5 | BRF_SND }, + { "dd2.12m", 0x200000, 0x5ea2e7fa, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddsomud) +STD_ROM_FN(Ddsomud) + +static struct BurnRomInfo DdtoddRomDesc[] = { + { "daded.03c", 0x080000, 0x843330f4, 1 | BRF_ESS | BRF_PRG }, + { "daded.04c", 0x080000, 0x306f14fc, 1 | BRF_ESS | BRF_PRG }, + { "daded.05c", 0x080000, 0x8c6b8328, 1 | BRF_ESS | BRF_PRG }, + { "dad.06a", 0x080000, 0x6225495a, 1 | BRF_ESS | BRF_PRG }, + { "dadd.07a", 0x080000, 0x0f0df6cc, 1 | BRF_ESS | BRF_PRG }, + + { "dad.13m", 0x200000, 0xda3cb7d6, 3 | BRF_GRA }, + { "dad.15m", 0x200000, 0x92b63172, 3 | BRF_GRA }, + { "dad.17m", 0x200000, 0xb98757f5, 3 | BRF_GRA }, + { "dad.19m", 0x200000, 0x8121ce46, 3 | BRF_GRA }, + { "dad.14m", 0x100000, 0x837e6f3f, 3 | BRF_GRA }, + { "dad.16m", 0x100000, 0xf0916bdb, 3 | BRF_GRA }, + { "dad.18m", 0x100000, 0xcef393ef, 3 | BRF_GRA }, + { "dad.20m", 0x100000, 0x8953fe9e, 3 | BRF_GRA }, + + { "dad.01", 0x020000, 0x3f5e2424, 4 | BRF_ESS | BRF_PRG }, + + { "dad.11m", 0x200000, 0x0c499b67, 5 | BRF_SND }, + { "dad.12m", 0x200000, 0x2f0b5a4e, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ddtodd) +STD_ROM_FN(Ddtodd) + +static struct BurnRomInfo DimahoudRomDesc[] = { + { "gmdud.03", 0x080000, 0x12888435, 1 | BRF_ESS | BRF_PRG }, + { "gmd.04", 0x080000, 0x37485567, 1 | BRF_ESS | BRF_PRG }, + { "gmd.05", 0x080000, 0xDA269FFB, 1 | BRF_ESS | BRF_PRG }, + { "gmdud.06", 0x080000, 0xd825efda, 1 | BRF_ESS | BRF_PRG }, + + { "gmd.13m", 0x400000, 0x80DD19F0, 3 | BRF_GRA }, + { "gmd.15m", 0x400000, 0xDFD93A78, 3 | BRF_GRA }, + { "gmd.17m", 0x400000, 0x16356520, 3 | BRF_GRA }, + { "gmd.19m", 0x400000, 0xDFC33031, 3 | BRF_GRA }, + + { "gmd.01", 0x020000, 0x3F9BC985, 4 | BRF_ESS | BRF_PRG }, + { "gmd.02", 0x020000, 0x3FD39DDE, 4 | BRF_ESS | BRF_PRG }, + + { "gmd.11m", 0x400000, 0x06A65542, 5 | BRF_SND }, + { "gmd.12m", 0x400000, 0x50BC7A31, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dimahoud) +STD_ROM_FN(Dimahoud) + +static struct BurnRomInfo Dstlku1dRomDesc[] = { + { "vamud.03a", 0x080000, 0x47b7a680, 1 | BRF_ESS | BRF_PRG }, + { "vamud.04a", 0x080000, 0x3b7a4939, 1 | BRF_ESS | BRF_PRG }, + { "vamu.05a", 0x080000, 0x673ed50a, 1 | BRF_ESS | BRF_PRG }, + { "vamu.06a", 0x080000, 0xf2377be7, 1 | BRF_ESS | BRF_PRG }, + { "vamu.07a", 0x080000, 0xd8f498c4, 1 | BRF_ESS | BRF_PRG }, + { "vamu.08a", 0x080000, 0xe6a8a1a0, 1 | BRF_ESS | BRF_PRG }, + { "vamud.09a", 0x080000, 0x8b333a19, 1 | BRF_ESS | BRF_PRG }, + { "vamu.10a", 0x080000, 0xc1a3d9be, 1 | BRF_ESS | BRF_PRG }, + + { "vam.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vam.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vam.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vam.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vam.14m", 0x100000, 0xbd87243c, 3 | BRF_GRA }, + { "vam.16m", 0x100000, 0xafec855f, 3 | BRF_GRA }, + { "vam.18m", 0x100000, 0x3a033625, 3 | BRF_GRA }, + { "vam.20m", 0x100000, 0x2bff6a89, 3 | BRF_GRA }, + + { "vam.01", 0x020000, 0x64b685d5, 4 | BRF_ESS | BRF_PRG }, + { "vam.02", 0x020000, 0xcf7c97c7, 4 | BRF_ESS | BRF_PRG }, + + { "vam.11m", 0x200000, 0x4a39deb2, 5 | BRF_SND }, + { "vam.12m", 0x200000, 0x1a3e5c03, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Dstlku1d) +STD_ROM_FN(Dstlku1d) + +static struct BurnRomInfo EcofghtrdRomDesc[] = { + { "ueced.03", 0x080000, 0xac725d2b, 1 | BRF_ESS | BRF_PRG }, + { "ueced.04", 0x080000, 0xf800138d, 1 | BRF_ESS | BRF_PRG }, + { "ueced.05", 0x080000, 0xeb6a12f2, 1 | BRF_ESS | BRF_PRG }, + { "ueced.06", 0x080000, 0x8380ec9a, 1 | BRF_ESS | BRF_PRG }, + + { "uec.13m", 0x200000, 0xdcaf1436, 3 | BRF_GRA }, + { "uec.15m", 0x200000, 0x2807df41, 3 | BRF_GRA }, + { "uec.17m", 0x200000, 0x8a708d02, 3 | BRF_GRA }, + { "uec.19m", 0x200000, 0xde7be0ef, 3 | BRF_GRA }, + { "uec.14m", 0x100000, 0x1a003558, 3 | BRF_GRA }, + { "uec.16m", 0x100000, 0x4ff8a6f9, 3 | BRF_GRA }, + { "uec.18m", 0x100000, 0xb167ae12, 3 | BRF_GRA }, + { "uec.20m", 0x100000, 0x1064bdc2, 3 | BRF_GRA }, + + { "uec.01", 0x020000, 0xc235bd15, 4 | BRF_ESS | BRF_PRG }, + + { "uec.11m", 0x200000, 0x81b25d39, 5 | BRF_SND }, + { "uec.12m", 0x200000, 0x27729e52, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ecofghtrd) +STD_ROM_FN(Ecofghtrd) + +static struct BurnRomInfo GigawingdRomDesc[] = { + { "ggwu_d.03", 0x080000, 0xdde92dfa, 1 | BRF_ESS | BRF_PRG }, + { "ggwu_d.04", 0x080000, 0xe0509ae2, 1 | BRF_ESS | BRF_PRG }, + { "ggw_d.05", 0x080000, 0x722d0042, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawingd) +STD_ROM_FN(Gigawingd) + +static struct BurnRomInfo GigawingjdRomDesc[] = { + { "ggwjd.03a", 0x080000, 0xcb1c756e, 1 | BRF_ESS | BRF_PRG }, + { "ggwjd.04a", 0x080000, 0xfa158e04, 1 | BRF_ESS | BRF_PRG }, + { "ggwjd.05a", 0x080000, 0x1c5bc4e7, 1 | BRF_ESS | BRF_PRG }, + + { "ggw.13m", 0x400000, 0x105530a4, 3 | BRF_GRA }, + { "ggw.15m", 0x400000, 0x9e774ab9, 3 | BRF_GRA }, + { "ggw.17m", 0x400000, 0x466e0ba4, 3 | BRF_GRA }, + { "ggw.19m", 0x400000, 0x840c8dea, 3 | BRF_GRA }, + + { "ggw.01", 0x020000, 0x4c6351d5, 4 | BRF_ESS | BRF_PRG }, + + { "ggw.11m", 0x400000, 0xe172acf5, 5 | BRF_SND }, + { "ggw.12m", 0x400000, 0x4bee4e8f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Gigawingjd) +STD_ROM_FN(Gigawingjd) + +static struct BurnRomInfo Hsf2dRomDesc[] = { + { "hs2ad.03", 0x080000, 0x0153d371, 1 | BRF_ESS | BRF_PRG }, + { "hs2ad.04", 0x080000, 0x0276b78a, 1 | BRF_ESS | BRF_PRG }, + { "hs2.05", 0x080000, 0xdde34a35, 1 | BRF_ESS | BRF_PRG }, + { "hs2.06", 0x080000, 0xf4e56dda, 1 | BRF_ESS | BRF_PRG }, + { "hs2.07", 0x080000, 0xee4420fc, 1 | BRF_ESS | BRF_PRG }, + { "hs2.08", 0x080000, 0xc9441533, 1 | BRF_ESS | BRF_PRG }, + { "hs2.09", 0x080000, 0x3fc638a8, 1 | BRF_ESS | BRF_PRG }, + { "hs2.10", 0x080000, 0x20d0f9e4, 1 | BRF_ESS | BRF_PRG }, + + { "hs2.13m", 0x800000, 0xa6ecab17, 3 | BRF_GRA }, + { "hs2.15m", 0x800000, 0x10a0ae4d, 3 | BRF_GRA }, + { "hs2.17m", 0x800000, 0xadfa7726, 3 | BRF_GRA }, + { "hs2.19m", 0x800000, 0xbb3ae322, 3 | BRF_GRA }, + + { "hs2.01", 0x020000, 0xc1a13786, 4 | BRF_ESS | BRF_PRG }, + { "hs2.02", 0x020000, 0x2d8794aa, 4 | BRF_ESS | BRF_PRG }, + + { "hs2.11m", 0x800000, 0x0e15c359, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Hsf2d) +STD_ROM_FN(Hsf2d) + +static struct BurnRomInfo Megamn2dRomDesc[] = { + { "rm2ud.03", 0x080000, 0xd3635f25, 1 | BRF_ESS | BRF_PRG }, + { "rm2ud.04", 0x080000, 0x768a1705, 1 | BRF_ESS | BRF_PRG }, + { "rm2.05", 0x080000, 0x02ee9efc, 1 | BRF_ESS | BRF_PRG }, + + { "rm2.14m", 0x200000, 0x9b1f00b4, 3 | BRF_GRA }, + { "rm2.16m", 0x200000, 0xc2bb0c24, 3 | BRF_GRA }, + { "rm2.18m", 0x200000, 0x12257251, 3 | BRF_GRA }, + { "rm2.20m", 0x200000, 0xf9b6e786, 3 | BRF_GRA }, + + { "rm2.01a", 0x020000, 0xd18e7859, 4 | BRF_ESS | BRF_PRG }, + { "rm2.02", 0x020000, 0xc463ece0, 4 | BRF_ESS | BRF_PRG }, + + { "rm2.11m", 0x200000, 0x2106174d, 5 | BRF_SND }, + { "rm2.12m", 0x200000, 0x546c1636, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Megamn2d) +STD_ROM_FN(Megamn2d) + +static struct BurnRomInfo MmatrixdRomDesc[] = { +#if !defined (ROM_VERIFY) + { "mmxud.03", 0x080000, 0x36711e60, 1 | BRF_ESS | BRF_PRG }, + { "mmxud.04", 0x080000, 0x4687226f, 1 | BRF_ESS | BRF_PRG }, + { "mmxud.05", 0x080000, 0x52124398, 1 | BRF_ESS | BRF_PRG }, +#else + { "mmxjd.03", 0x080000, 0x36711e60, 1 | BRF_ESS | BRF_PRG }, + { "mmxjd.04", 0x080000, 0x4687226f, 1 | BRF_ESS | BRF_PRG }, + { "mmxjd.05", 0x080000, 0x52124398, 1 | BRF_ESS | BRF_PRG }, +#endif + + { "mmx.13m", 0x400000, 0x04748718, 3 | BRF_GRA }, + { "mmx.15m", 0x400000, 0x38074F44, 3 | BRF_GRA }, + { "mmx.17m", 0x400000, 0xE4635E35, 3 | BRF_GRA }, + { "mmx.19m", 0x400000, 0x4400A3F2, 3 | BRF_GRA }, + { "mmx.14m", 0x400000, 0xD52BF491, 3 | BRF_GRA }, + { "mmx.16m", 0x400000, 0x23F70780, 3 | BRF_GRA }, + { "mmx.18m", 0x400000, 0x2562C9D5, 3 | BRF_GRA }, + { "mmx.20m", 0x400000, 0x583A9687, 3 | BRF_GRA }, + + { "mmx.01", 0x020000, 0xC57E8171, 4 | BRF_ESS | BRF_PRG }, + + { "mmx.11m", 0x400000, 0x4180B39F, 5 | BRF_SND }, + { "mmx.12m", 0x400000, 0x95E22A59, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mmatrixd) +STD_ROM_FN(Mmatrixd) + +static struct BurnRomInfo MshudRomDesc[] = { + { "mshud.03", 0x080000, 0xc1d8c4c6, 1 | BRF_ESS | BRF_PRG }, + { "mshud.04", 0x080000, 0xe73dda16, 1 | BRF_ESS | BRF_PRG }, + { "mshud.05", 0x080000, 0x3b493e84, 1 | BRF_ESS | BRF_PRG }, + { "msh.06b", 0x080000, 0x803e3fa4, 1 | BRF_ESS | BRF_PRG }, + { "msh.07a", 0x080000, 0xc45f8e27, 1 | BRF_ESS | BRF_PRG }, + { "msh.08a", 0x080000, 0x9ca6f12c, 1 | BRF_ESS | BRF_PRG }, + { "msh.09a", 0x080000, 0x82ec27af, 1 | BRF_ESS | BRF_PRG }, + { "msh.10b", 0x080000, 0x8d931196, 1 | BRF_ESS | BRF_PRG }, + + { "msh.13m", 0x400000, 0x09d14566, 3 | BRF_GRA }, + { "msh.15m", 0x400000, 0xee962057, 3 | BRF_GRA }, + { "msh.17m", 0x400000, 0x604ece14, 3 | BRF_GRA }, + { "msh.19m", 0x400000, 0x94a731e8, 3 | BRF_GRA }, + { "msh.14m", 0x400000, 0x4197973e, 3 | BRF_GRA }, + { "msh.16m", 0x400000, 0x438da4a0, 3 | BRF_GRA }, + { "msh.18m", 0x400000, 0x4db92d94, 3 | BRF_GRA }, + { "msh.20m", 0x400000, 0xa2b0c6c0, 3 | BRF_GRA }, + + { "msh.01", 0x020000, 0xc976e6f9, 4 | BRF_ESS | BRF_PRG }, + { "msh.02", 0x020000, 0xce67d0d9, 4 | BRF_ESS | BRF_PRG }, + + { "msh.11m", 0x200000, 0x37ac6d30, 5 | BRF_SND }, + { "msh.12m", 0x200000, 0xde092570, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshud) +STD_ROM_FN(Mshud) + +static struct BurnRomInfo Mshvsfu1dRomDesc[] = { + { "mvsu_d.03d", 0x080000, 0x1c88bee3, 1 | BRF_ESS | BRF_PRG }, + { "mvsu_d.04d", 0x080000, 0x1e8b2535, 1 | BRF_ESS | BRF_PRG }, + { "mvs_d.05a", 0x080000, 0x373856fb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.06a", 0x080000, 0x959f3030, 1 | BRF_ESS | BRF_PRG }, + { "mvs.07b", 0x080000, 0x7f915bdb, 1 | BRF_ESS | BRF_PRG }, + { "mvs.08a", 0x080000, 0xc2813884, 1 | BRF_ESS | BRF_PRG }, + { "mvs.09b", 0x080000, 0x3ba08818, 1 | BRF_ESS | BRF_PRG }, + { "mvs.10b", 0x080000, 0xcf0dba98, 1 | BRF_ESS | BRF_PRG }, + + { "mvs.13m", 0x400000, 0x29b05fd9, 3 | BRF_GRA }, + { "mvs.15m", 0x400000, 0xfaddccf1, 3 | BRF_GRA }, + { "mvs.17m", 0x400000, 0x97aaf4c7, 3 | BRF_GRA }, + { "mvs.19m", 0x400000, 0xcb70e915, 3 | BRF_GRA }, + { "mvs.14m", 0x400000, 0xb3b1972d, 3 | BRF_GRA }, + { "mvs.16m", 0x400000, 0x08aadb5d, 3 | BRF_GRA }, + { "mvs.18m", 0x400000, 0xc1228b35, 3 | BRF_GRA }, + { "mvs.20m", 0x400000, 0x366cc6c2, 3 | BRF_GRA }, + + { "mvs.01", 0x020000, 0x68252324, 4 | BRF_ESS | BRF_PRG }, + { "mvs.02", 0x020000, 0xb34e773d, 4 | BRF_ESS | BRF_PRG }, + + { "mvs.11m", 0x400000, 0x86219770, 5 | BRF_SND }, + { "mvs.12m", 0x400000, 0xf2fd7f68, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mshvsfu1d) +STD_ROM_FN(Mshvsfu1d) + +static struct BurnRomInfo MvscudRomDesc[] = { + { "mvcud.03d", 0x080000, 0x75cde3e5, 1 | BRF_ESS | BRF_PRG }, + { "mvcud.04d", 0x080000, 0xb32ea484, 1 | BRF_ESS | BRF_PRG }, + { "mvc.05a", 0x080000, 0x2d8c8e86, 1 | BRF_ESS | BRF_PRG }, + { "mvc.06a", 0x080000, 0x8528e1f5, 1 | BRF_ESS | BRF_PRG }, + { "mvcd.07", 0x080000, 0x205293e9, 1 | BRF_ESS | BRF_PRG }, + { "mvc.08", 0x080000, 0xbc002fcd, 1 | BRF_ESS | BRF_PRG }, + { "mvc.09", 0x080000, 0xc67b26df, 1 | BRF_ESS | BRF_PRG }, + { "mvc.10", 0x080000, 0x0fdd1e26, 1 | BRF_ESS | BRF_PRG }, + + { "mvc.13m", 0x400000, 0xfa5f74bc, 3 | BRF_GRA }, + { "mvc.15m", 0x400000, 0x71938a8f, 3 | BRF_GRA }, + { "mvc.17m", 0x400000, 0x92741d07, 3 | BRF_GRA }, + { "mvc.19m", 0x400000, 0xbcb72fc6, 3 | BRF_GRA }, + { "mvc.14m", 0x400000, 0x7f1df4e4, 3 | BRF_GRA }, + { "mvc.16m", 0x400000, 0x90bd3203, 3 | BRF_GRA }, + { "mvc.18m", 0x400000, 0x67aaf727, 3 | BRF_GRA }, + { "mvc.20m", 0x400000, 0x8b0bade8, 3 | BRF_GRA }, + + { "mvc.01", 0x020000, 0x41629e95, 4 | BRF_ESS | BRF_PRG }, + { "mvc.02", 0x020000, 0x963abf6b, 4 | BRF_ESS | BRF_PRG }, + + { "mvc.11m", 0x400000, 0x850fe663, 5 | BRF_SND }, + { "mvc.12m", 0x400000, 0x7ccb1896, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Mvscud) +STD_ROM_FN(Mvscud) + +static struct BurnRomInfo NwarrudRomDesc[] = { + { "vphud.03f", 0x080000, 0x20d4d5a8, 1 | BRF_ESS | BRF_PRG }, + { "vphud.04c", 0x080000, 0x61be9b42, 1 | BRF_ESS | BRF_PRG }, + { "vphud.05e", 0x080000, 0x1ba906d8, 1 | BRF_ESS | BRF_PRG }, + { "vphu.06c", 0x080000, 0x08c04cdb, 1 | BRF_ESS | BRF_PRG }, + { "vphu.07b", 0x080000, 0xb5a5ab19, 1 | BRF_ESS | BRF_PRG }, + { "vphu.08b", 0x080000, 0x51bb20fb, 1 | BRF_ESS | BRF_PRG }, + { "vphu.09b", 0x080000, 0x41a64205, 1 | BRF_ESS | BRF_PRG }, + { "vphud.10b", 0x080000, 0x9619adad, 1 | BRF_ESS | BRF_PRG }, + + { "vph.13m", 0x400000, 0xc51baf99, 3 | BRF_GRA }, + { "vph.15m", 0x400000, 0x3ce83c77, 3 | BRF_GRA }, + { "vph.17m", 0x400000, 0x4f2408e0, 3 | BRF_GRA }, + { "vph.19m", 0x400000, 0x9ff60250, 3 | BRF_GRA }, + { "vph.14m", 0x400000, 0x7a0e1add, 3 | BRF_GRA }, + { "vph.16m", 0x400000, 0x2f41ca75, 3 | BRF_GRA }, + { "vph.18m", 0x400000, 0x64498eed, 3 | BRF_GRA }, + { "vph.20m", 0x400000, 0x17f2433f, 3 | BRF_GRA }, + + { "vph.01", 0x020000, 0x5045dcac, 4 | BRF_ESS | BRF_PRG }, + { "vph.02", 0x020000, 0x86b60e59, 4 | BRF_ESS | BRF_PRG }, + + { "vph.11m", 0x200000, 0xe1837d33, 5 | BRF_SND }, + { "vph.12m", 0x200000, 0xfbd3cd90, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Nwarrud) +STD_ROM_FN(Nwarrud) + +static struct BurnRomInfo ProgearudRomDesc[] = { + { "pgau_d.03", 0x080000, 0xba22b9c5, 1 | BRF_ESS | BRF_PRG }, + { "pgau_d.04", 0x080000, 0xdf3927ef, 1 | BRF_ESS | BRF_PRG }, + + { "pga-simm.01c", 0x200000, 0x452F98B0, 11 | BRF_GRA }, + { "pga-simm.01d", 0x200000, 0x9E672092, 11 | BRF_GRA }, + { "pga-simm.01a", 0x200000, 0xAE9DDAFE, 11 | BRF_GRA }, + { "pga-simm.01b", 0x200000, 0x94D72D94, 11 | BRF_GRA }, + { "pga-simm.03c", 0x200000, 0x48A1886D, 11 | BRF_GRA }, + { "pga-simm.03d", 0x200000, 0x172D7E37, 11 | BRF_GRA }, + { "pga-simm.03a", 0x200000, 0x9EE33D98, 11 | BRF_GRA }, + { "pga-simm.03b", 0x200000, 0x848DEE32, 11 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga-simm.05a", 0x200000, 0xC0AAC80C, 13 | BRF_SND }, + { "pga-simm.05b", 0x200000, 0x37A65D86, 13 | BRF_SND }, + { "pga-simm.06a", 0x200000, 0xD3F1E934, 13 | BRF_SND }, + { "pga-simm.06b", 0x200000, 0x8B39489A, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Progearud) +STD_ROM_FN(Progearud) + +static struct BurnRomInfo ProgearjdRomDesc[] = { + { "pgaj_d.03", 0x080000, 0x0271f3a3, 1 | BRF_ESS | BRF_PRG }, + { "pgaj_d.04", 0x080000, 0xbe4b7799, 1 | BRF_ESS | BRF_PRG }, + + { "pga-simm.01c", 0x200000, 0x452F98B0, 11 | BRF_GRA }, + { "pga-simm.01d", 0x200000, 0x9E672092, 11 | BRF_GRA }, + { "pga-simm.01a", 0x200000, 0xAE9DDAFE, 11 | BRF_GRA }, + { "pga-simm.01b", 0x200000, 0x94D72D94, 11 | BRF_GRA }, + { "pga-simm.03c", 0x200000, 0x48A1886D, 11 | BRF_GRA }, + { "pga-simm.03d", 0x200000, 0x172D7E37, 11 | BRF_GRA }, + { "pga-simm.03a", 0x200000, 0x9EE33D98, 11 | BRF_GRA }, + { "pga-simm.03b", 0x200000, 0x848DEE32, 11 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga-simm.05a", 0x200000, 0xC0AAC80C, 13 | BRF_SND }, + { "pga-simm.05b", 0x200000, 0x37A65D86, 13 | BRF_SND }, + { "pga-simm.06a", 0x200000, 0xD3F1E934, 13 | BRF_SND }, + { "pga-simm.06b", 0x200000, 0x8B39489A, 13 | BRF_SND }, +}; + +STD_ROM_PICK(Progearjd) +STD_ROM_FN(Progearjd) + +static struct BurnRomInfo ProgearjblRomDesc[] = { + { "pgaj_bl.03", 0x080000, 0x4fef676c, 1 | BRF_ESS | BRF_PRG }, + { "pgaj_bl.04", 0x080000, 0xa069bd3b, 1 | BRF_ESS | BRF_PRG }, + + { "pga.13m", 0x400000, 0x5194c198, 3 | BRF_GRA }, + { "pga.15m", 0x400000, 0xb794e83f, 3 | BRF_GRA }, + { "pga.17m", 0x400000, 0x87f22918, 3 | BRF_GRA }, + { "pga.19m", 0x400000, 0x65ffb45b, 3 | BRF_GRA }, + + { "pga.01", 0x020000, 0xBDBFA992, 4 | BRF_ESS | BRF_PRG }, + + { "pga.11m", 0x400000, 0xabdd224e, 5 | BRF_SND }, + { "pga.12m", 0x400000, 0xdac53406, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Progearjbl) +STD_ROM_FN(Progearjbl) + +static struct BurnRomInfo RingdstdRomDesc[] = { + { "smbed.03b", 0x080000, 0xf6fba4cd, 1 | BRF_ESS | BRF_PRG }, + { "smbed.04b", 0x080000, 0x193bc493, 1 | BRF_ESS | BRF_PRG }, + { "smbed.05b", 0x080000, 0x168cccbb, 1 | BRF_ESS | BRF_PRG }, + { "smbed.06b", 0x080000, 0x04673262, 1 | BRF_ESS | BRF_PRG }, + { "smb.07", 0x080000, 0xb9a11577, 1 | BRF_ESS | BRF_PRG }, + { "smb.08", 0x080000, 0xf931b76b, 1 | BRF_ESS | BRF_PRG }, + + { "smb.13m", 0x200000, 0xd9b2d1de, 3 | BRF_GRA }, + { "smb.15m", 0x200000, 0x9a766d92, 3 | BRF_GRA }, + { "smb.17m", 0x200000, 0x51800f0f, 3 | BRF_GRA }, + { "smb.19m", 0x200000, 0x35757e96, 3 | BRF_GRA }, + { "smb.14m", 0x200000, 0xe5bfd0e7, 3 | BRF_GRA }, + { "smb.16m", 0x200000, 0xc56c0866, 3 | BRF_GRA }, + { "smb.18m", 0x200000, 0x4ded3910, 3 | BRF_GRA }, + { "smb.20m", 0x200000, 0x26ea1ec5, 3 | BRF_GRA }, + { "smb.21m", 0x080000, 0x0a08c5fc, 3 | BRF_GRA }, + { "smb.23m", 0x080000, 0x0911b6c4, 3 | BRF_GRA }, + { "smb.25m", 0x080000, 0x82d6c4ec, 3 | BRF_GRA }, + { "smb.27m", 0x080000, 0x9b48678b, 3 | BRF_GRA }, + + { "smb.01", 0x020000, 0x0abc229a, 4 | BRF_ESS | BRF_PRG }, + { "smb.02", 0x020000, 0xd051679a, 4 | BRF_ESS | BRF_PRG }, + + { "smb.11m", 0x200000, 0xc56935f9, 5 | BRF_SND }, + { "smb.12m", 0x200000, 0x955b0782, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ringdstd) +STD_ROM_FN(Ringdstd) + +static struct BurnRomInfo SfadRomDesc[] = { + { "sfzed.03d", 0x080000, 0xa1a54827, 1 | BRF_ESS | BRF_PRG }, + { "sfz.04b", 0x080000, 0x8b73b0e5, 1 | BRF_ESS | BRF_PRG }, + { "sfz.05a", 0x080000, 0x0810544d, 1 | BRF_ESS | BRF_PRG }, + { "sfz.06", 0x080000, 0x806e8f38, 1 | BRF_ESS | BRF_PRG }, + + { "sfz.14m", 0x200000, 0x90fefdb3, 3 | BRF_GRA }, + { "sfz.16m", 0x200000, 0x5354c948, 3 | BRF_GRA }, + { "sfz.18m", 0x200000, 0x41a1e790, 3 | BRF_GRA }, + { "sfz.20m", 0x200000, 0xa549df98, 3 | BRF_GRA }, + + { "sfz.01", 0x020000, 0xffffec7d, 4 | BRF_ESS | BRF_PRG }, + { "sfz.02", 0x020000, 0x45f46a08, 4 | BRF_ESS | BRF_PRG }, + + { "sfz.11m", 0x200000, 0xc4b093cd, 5 | BRF_SND }, + { "sfz.12m", 0x200000, 0x8bdbc4b4, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfad) +STD_ROM_FN(Sfad) + +static struct BurnRomInfo Sfz2adRomDesc[] = { + { "sz2ad.03a", 0x080000, 0x017f8fab, 1 | BRF_ESS | BRF_PRG }, + { "sz2ad.04a", 0x080000, 0xf50e5ea2, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05a", 0x080000, 0x98e8e992, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2a.07a", 0x080000, 0x0aed2494, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2ad) +STD_ROM_FN(Sfz2ad) + +static struct BurnRomInfo Sfz2jdRomDesc[] = { + { "sz2j_d.03a", 0x080000, 0xb7325df8, 1 | BRF_ESS | BRF_PRG }, + { "sz2j_d.04a", 0x080000, 0xa1022a3e, 1 | BRF_ESS | BRF_PRG }, + { "sz2.05a", 0x080000, 0x98e8e992, 1 | BRF_ESS | BRF_PRG }, + { "sz2.06", 0x080000, 0x5b1d49c0, 1 | BRF_ESS | BRF_PRG }, + { "sz2j.07a", 0x080000, 0xd910b2a2, 1 | BRF_ESS | BRF_PRG }, + { "sz2.08", 0x080000, 0x0fe8585d, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2jd) +STD_ROM_FN(Sfz2jd) + +static struct BurnRomInfo Sfz2aldRomDesc[] = { + { "szaad.03", 0x080000, 0x89f9483b, 1 | BRF_ESS | BRF_PRG }, + { "szaad.04", 0x080000, 0xaef27ae5, 1 | BRF_ESS | BRF_PRG }, + { "szaa.05", 0x080000, 0xf053a55e, 1 | BRF_ESS | BRF_PRG }, + { "szaa.06", 0x080000, 0xcfc0e7a8, 1 | BRF_ESS | BRF_PRG }, + { "szaa.07", 0x080000, 0x5feb8b20, 1 | BRF_ESS | BRF_PRG }, + { "szaa.08", 0x080000, 0x6eb6d412, 1 | BRF_ESS | BRF_PRG }, + + { "sz2.13m", 0x400000, 0x4d1f1f22, 3 | BRF_GRA }, + { "sz2.15m", 0x400000, 0x19cea680, 3 | BRF_GRA }, + { "sz2.17m", 0x400000, 0xe01b4588, 3 | BRF_GRA }, + { "sz2.19m", 0x400000, 0x0feeda64, 3 | BRF_GRA }, + { "sz2.14m", 0x100000, 0x0560c6aa, 3 | BRF_GRA }, + { "sz2.16m", 0x100000, 0xae940f87, 3 | BRF_GRA }, + { "sz2.18m", 0x100000, 0x4bc3c8bc, 3 | BRF_GRA }, + { "sz2.20m", 0x100000, 0x39e674c0, 3 | BRF_GRA }, + + { "sz2.01a", 0x020000, 0x1bc323cf, 4 | BRF_ESS | BRF_PRG }, + { "sz2.02a", 0x020000, 0xba6a5013, 4 | BRF_ESS | BRF_PRG }, + + { "sz2.11m", 0x200000, 0xaa47a601, 5 | BRF_SND }, + { "sz2.12m", 0x200000, 0x2237bc53, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz2ald) +STD_ROM_FN(Sfz2ald) + +static struct BurnRomInfo Sfa3udRomDesc[] = { + { "sz3ud.03c", 0x080000, 0x6db8add7, 1 | BRF_ESS | BRF_PRG }, + { "sz3ud.04c", 0x080000, 0xd9c65a26, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05c", 0x080000, 0x57fd0a40, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06c", 0x080000, 0xf6305f8b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07c", 0x080000, 0x6eab0f6f, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08c", 0x080000, 0x910c4a3b, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09c", 0x080000, 0xb29e5199, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10b", 0x080000, 0xdeb2ff52, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfa3ud) +STD_ROM_FN(Sfa3ud) + +static struct BurnRomInfo Sfz3jr2dRomDesc[] = { + { "sz3j_d.03", 0x080000, 0xb0436151, 1 | BRF_ESS | BRF_PRG }, + { "sz3j_d.04", 0x080000, 0x642d8170, 1 | BRF_ESS | BRF_PRG }, + { "sz3.05", 0x080000, 0x9b21518a, 1 | BRF_ESS | BRF_PRG }, + { "sz3.06", 0x080000, 0xe7a6c3a7, 1 | BRF_ESS | BRF_PRG }, + { "sz3.07", 0x080000, 0xec4c0cfd, 1 | BRF_ESS | BRF_PRG }, + { "sz3.08", 0x080000, 0x5c7e7240, 1 | BRF_ESS | BRF_PRG }, + { "sz3.09", 0x080000, 0xc5589553, 1 | BRF_ESS | BRF_PRG }, + { "sz3.10", 0x080000, 0xa9717252, 1 | BRF_ESS | BRF_PRG }, + + { "sz3.13m", 0x400000, 0x0f7a60d9, 3 | BRF_GRA }, + { "sz3.15m", 0x400000, 0x8e933741, 3 | BRF_GRA }, + { "sz3.17m", 0x400000, 0xd6e98147, 3 | BRF_GRA }, + { "sz3.19m", 0x400000, 0xf31a728a, 3 | BRF_GRA }, + { "sz3.14m", 0x400000, 0x5ff98297, 3 | BRF_GRA }, + { "sz3.16m", 0x400000, 0x52b5bdee, 3 | BRF_GRA }, + { "sz3.18m", 0x400000, 0x40631ed5, 3 | BRF_GRA }, + { "sz3.20m", 0x400000, 0x763409b4, 3 | BRF_GRA }, + + { "sz3.01", 0x020000, 0xde810084, 4 | BRF_ESS | BRF_PRG }, + { "sz3.02", 0x020000, 0x72445dc4, 4 | BRF_ESS | BRF_PRG }, + + { "sz3.11m", 0x400000, 0x1c89eed1, 5 | BRF_SND }, + { "sz3.12m", 0x400000, 0xf392b13a, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sfz3jr2d) +STD_ROM_FN(Sfz3jr2d) + +static struct BurnRomInfo SgemfdRomDesc[] = { + { "pcfud.03", 0x080000, 0x8b83674a, 1 | BRF_ESS | BRF_PRG }, + { "pcfd.04", 0x080000, 0xb58f1d03, 1 | BRF_ESS | BRF_PRG }, + { "pcf.05", 0x080000, 0x215655f6, 1 | BRF_ESS | BRF_PRG }, + { "pcf.06", 0x080000, 0xea6f13ea, 1 | BRF_ESS | BRF_PRG }, + { "pcf.07", 0x080000, 0x5ac6d5ea, 1 | BRF_ESS | BRF_PRG }, + + { "pcf.13m", 0x400000, 0x22d72ab9, 3 | BRF_GRA }, + { "pcf.15m", 0x400000, 0x16a4813c, 3 | BRF_GRA }, + { "pcf.17m", 0x400000, 0x1097e035, 3 | BRF_GRA }, + { "pcf.19m", 0x400000, 0xd362d874, 3 | BRF_GRA }, + { "pcf.14m", 0x100000, 0x0383897c, 3 | BRF_GRA }, + { "pcf.16m", 0x100000, 0x76f91084, 3 | BRF_GRA }, + { "pcf.18m", 0x100000, 0x756c3754, 3 | BRF_GRA }, + { "pcf.20m", 0x100000, 0x9ec9277d, 3 | BRF_GRA }, + + { "pcf.01", 0x020000, 0x254e5f33, 4 | BRF_ESS | BRF_PRG }, + { "pcf.02", 0x020000, 0x6902f4f9, 4 | BRF_ESS | BRF_PRG }, + + { "pcf.11m", 0x400000, 0xa5dea005, 5 | BRF_SND }, + { "pcf.12m", 0x400000, 0x4ce235fe, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Sgemfd) +STD_ROM_FN(Sgemfd) + +static struct BurnRomInfo Spf2tdRomDesc[] = { + { "pzfu_d.03a", 0x080000, 0x7836b903, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2td) +STD_ROM_FN(Spf2td) + +static struct BurnRomInfo Spf2xjdRomDesc[] = { + { "pzfjd.03a", 0x080000, 0x5e85ed08, 1 | BRF_ESS | BRF_PRG }, + { "pzf.04", 0x080000, 0xb80649e2, 1 | BRF_ESS | BRF_PRG }, + + { "pzf.14m", 0x100000, 0x2d4881cb, 3 | BRF_GRA }, + { "pzf.16m", 0x100000, 0x4b0fd1be, 3 | BRF_GRA }, + { "pzf.18m", 0x100000, 0xe43aac33, 3 | BRF_GRA }, + { "pzf.20m", 0x100000, 0x7f536ff1, 3 | BRF_GRA }, + + { "pzf.01", 0x020000, 0x600fb2a3, 4 | BRF_ESS | BRF_PRG }, + { "pzf.02", 0x020000, 0x496076e0, 4 | BRF_ESS | BRF_PRG }, + + { "pzf.11m", 0x200000, 0x78442743, 5 | BRF_SND }, + { "pzf.12m", 0x200000, 0x399d2c7b, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Spf2xjd) +STD_ROM_FN(Spf2xjd) + +static struct BurnRomInfo Ssf2udRomDesc[] = { + { "ssfud.03a", 0x080000, 0xfad5daf8, 1 | BRF_ESS | BRF_PRG }, + { "ssfud.04a", 0x080000, 0x0d31af65, 1 | BRF_ESS | BRF_PRG }, + { "ssfud.05", 0x080000, 0x75c651ef, 1 | BRF_ESS | BRF_PRG }, + { "ssfud.06", 0x080000, 0x85c3ec00, 1 | BRF_ESS | BRF_PRG }, + { "ssfud.07", 0x080000, 0x247e2504, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2ud) +STD_ROM_FN(Ssf2ud) + +static struct BurnRomInfo Ssf2tbdRomDesc[] = { + { "ssfed.3tc", 0x080000, 0x5d86caf8, 1 | BRF_ESS | BRF_PRG }, + { "ssfed.4tc", 0x080000, 0xf6e1f98d, 1 | BRF_ESS | BRF_PRG }, + { "ssfed.5t", 0x080000, 0x75c651ef, 1 | BRF_ESS | BRF_PRG }, + { "ssfed.6tb", 0x080000, 0x9adac7d7, 1 | BRF_ESS | BRF_PRG }, + { "ssfed.7t", 0x080000, 0x84f54db3, 1 | BRF_ESS | BRF_PRG }, + + { "ssf.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "ssf.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "ssf.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "ssf.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "ssf.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "ssf.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "ssf.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "ssf.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + + { "ssf.01", 0x020000, 0xeb247e8c, 4 | BRF_ESS | BRF_PRG }, + + { "ssf.q01", 0x080000, 0xa6f9da5c, 5 | BRF_SND }, + { "ssf.q02", 0x080000, 0x8c66ae26, 5 | BRF_SND }, + { "ssf.q03", 0x080000, 0x695cc2ca, 5 | BRF_SND }, + { "ssf.q04", 0x080000, 0x9d9ebe32, 5 | BRF_SND }, + { "ssf.q05", 0x080000, 0x4770e7b7, 5 | BRF_SND }, + { "ssf.q06", 0x080000, 0x4e79c951, 5 | BRF_SND }, + { "ssf.q07", 0x080000, 0xcdd14313, 5 | BRF_SND }, + { "ssf.q08", 0x080000, 0x6f5a088c, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2tbd) +STD_ROM_FN(Ssf2tbd) + +static struct BurnRomInfo Ssf2xjdRomDesc[] = { + { "sfxjd.03c", 0x080000, 0x316de996, 1 | BRF_ESS | BRF_PRG }, + { "sfxjd.04a", 0x080000, 0x9bf3bb2e, 1 | BRF_ESS | BRF_PRG }, + { "sfxjd.05", 0x080000, 0xc63358d0, 1 | BRF_ESS | BRF_PRG }, + { "sfxjd.06a", 0x080000, 0xccb29808, 1 | BRF_ESS | BRF_PRG }, + { "sfxjd.07", 0x080000, 0x61f94982, 1 | BRF_ESS | BRF_PRG }, + { "sfxjd.08", 0x080000, 0xd399c36c, 1 | BRF_ESS | BRF_PRG }, + { "sfxd.09", 0x080000, 0x0b3a6196, 1 | BRF_ESS | BRF_PRG }, + + { "sfx.13m", 0x200000, 0xcf94d275, 3 | BRF_GRA }, + { "sfx.15m", 0x200000, 0x5eb703af, 3 | BRF_GRA }, + { "sfx.17m", 0x200000, 0xffa60e0f, 3 | BRF_GRA }, + { "sfx.19m", 0x200000, 0x34e825c5, 3 | BRF_GRA }, + { "sfx.14m", 0x100000, 0xb7cc32e7, 3 | BRF_GRA }, + { "sfx.16m", 0x100000, 0x8376ad18, 3 | BRF_GRA }, + { "sfx.18m", 0x100000, 0xf5b1b336, 3 | BRF_GRA }, + { "sfx.20m", 0x100000, 0x459d5c6b, 3 | BRF_GRA }, + { "sfx.21m", 0x100000, 0xe32854af, 3 | BRF_GRA }, + { "sfx.23m", 0x100000, 0x760f2927, 3 | BRF_GRA }, + { "sfx.25m", 0x100000, 0x1ee90208, 3 | BRF_GRA }, + { "sfx.27m", 0x100000, 0xf814400f, 3 | BRF_GRA }, + + { "sfx.01", 0x020000, 0xb47b8835, 4 | BRF_ESS | BRF_PRG }, + { "sfx.02", 0x020000, 0x0022633f, 4 | BRF_ESS | BRF_PRG }, + + { "sfx.11m", 0x200000, 0x9bdbd476, 5 | BRF_SND }, + { "sfx.12m", 0x200000, 0xa05e3aab, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Ssf2xjd) +STD_ROM_FN(Ssf2xjd) + +static struct BurnRomInfo VsavdRomDesc[] = { + { "vm3ed.03d", 0x080000, 0x97d805e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3ed.04d", 0x080000, 0x5e07fdce, 1 | BRF_ESS | BRF_PRG }, + { "vm3.05a", 0x080000, 0x4118e00f, 1 | BRF_ESS | BRF_PRG }, + { "vm3.06a", 0x080000, 0x2f4fd3a9, 1 | BRF_ESS | BRF_PRG }, + { "vm3.07b", 0x080000, 0xcbda91b8, 1 | BRF_ESS | BRF_PRG }, + { "vm3.08a", 0x080000, 0x6ca47259, 1 | BRF_ESS | BRF_PRG }, + { "vm3.09b", 0x080000, 0xf4a339e3, 1 | BRF_ESS | BRF_PRG }, + { "vm3.10b", 0x080000, 0xfffbb5b8, 1 | BRF_ESS | BRF_PRG }, + + { "vm3.13m", 0x400000, 0xfd8a11eb, 3 | BRF_GRA }, + { "vm3.15m", 0x400000, 0xdd1e7d4e, 3 | BRF_GRA }, + { "vm3.17m", 0x400000, 0x6b89445e, 3 | BRF_GRA }, + { "vm3.19m", 0x400000, 0x3830fdc7, 3 | BRF_GRA }, + { "vm3.14m", 0x400000, 0xc1a28e6c, 3 | BRF_GRA }, + { "vm3.16m", 0x400000, 0x194a7304, 3 | BRF_GRA }, + { "vm3.18m", 0x400000, 0xdf9a9f47, 3 | BRF_GRA }, + { "vm3.20m", 0x400000, 0xc22fc3d9, 3 | BRF_GRA }, + + { "vm3.01", 0x020000, 0xf778769b, 4 | BRF_ESS | BRF_PRG }, + { "vm3.02", 0x020000, 0xcc09faa1, 4 | BRF_ESS | BRF_PRG }, + + { "vm3.11m", 0x400000, 0xe80e956e, 5 | BRF_SND }, + { "vm3.12m", 0x400000, 0x9cd71557, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsavd) +STD_ROM_FN(Vsavd) + +static struct BurnRomInfo Vhunt2dRomDesc[] = { + { "vh2j_d.03a", 0x080000, 0x696e0157, 1 | BRF_ESS | BRF_PRG }, + { "vh2j_d.04a", 0x080000, 0xced9bba3, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.05", 0x080000, 0xde34f624, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.06", 0x080000, 0x6a3b9897, 1 | BRF_ESS | BRF_PRG }, + { "vh2j_d.06", 0x080000, 0xf320ea30, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.08", 0x080000, 0xac873dff, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.09", 0x080000, 0xeaefce9c, 1 | BRF_ESS | BRF_PRG }, + { "vh2j.10", 0x080000, 0x11730952, 1 | BRF_ESS | BRF_PRG }, + + { "vh2.13m", 0x400000, 0x3b02ddaa, 3 | BRF_GRA }, + { "vh2.15m", 0x400000, 0x4e40de66, 3 | BRF_GRA }, + { "vh2.17m", 0x400000, 0xb31d00c9, 3 | BRF_GRA }, + { "vh2.19m", 0x400000, 0x149be3ab, 3 | BRF_GRA }, + { "vh2.14m", 0x400000, 0xcd09bd63, 3 | BRF_GRA }, + { "vh2.16m", 0x400000, 0xe0182c15, 3 | BRF_GRA }, + { "vh2.18m", 0x400000, 0x778dc4f6, 3 | BRF_GRA }, + { "vh2.20m", 0x400000, 0x605d9d1d, 3 | BRF_GRA }, + + { "vh2.01", 0x020000, 0x67b9f779, 4 | BRF_ESS | BRF_PRG }, + { "vh2.02", 0x020000, 0xaaf15fcb, 4 | BRF_ESS | BRF_PRG }, + + { "vh2.11m", 0x400000, 0x38922efd, 5 | BRF_SND }, + { "vh2.12m", 0x400000, 0x6e2430af, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vhunt2d) +STD_ROM_FN(Vhunt2d) + +static struct BurnRomInfo Vsav2dRomDesc[] = { + { "vs2j_d.03", 0x080000, 0x5ee19aee, 1 | BRF_ESS | BRF_PRG }, + { "vs2j_d.04", 0x080000, 0x80116c47, 1 | BRF_ESS | BRF_PRG }, + { "vs2j_d.05", 0x080000, 0xdc74a062, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.06", 0x080000, 0xf37c5bc2, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.07", 0x080000, 0x8f885809, 1 | BRF_ESS | BRF_PRG }, + { "vs2j_d.08", 0x080000, 0x97554918, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.09", 0x080000, 0xfac3c217, 1 | BRF_ESS | BRF_PRG }, + { "vs2j.10", 0x080000, 0xeb490213, 1 | BRF_ESS | BRF_PRG }, + + { "vs2.13m", 0x400000, 0x5c852f52, 3 | BRF_GRA }, + { "vs2.15m", 0x400000, 0xa20f58af, 3 | BRF_GRA }, + { "vs2.17m", 0x400000, 0x39db59ad, 3 | BRF_GRA }, + { "vs2.19m", 0x400000, 0x00c763a7, 3 | BRF_GRA }, + { "vs2.14m", 0x400000, 0xcd09bd63, 3 | BRF_GRA }, + { "vs2.16m", 0x400000, 0xe0182c15, 3 | BRF_GRA }, + { "vs2.18m", 0x400000, 0x778dc4f6, 3 | BRF_GRA }, + { "vs2.20m", 0x400000, 0x605d9d1d, 3 | BRF_GRA }, + + { "vs2.01", 0x020000, 0x35190139, 4 | BRF_ESS | BRF_PRG }, + { "vs2.02", 0x020000, 0xc32dba09, 4 | BRF_ESS | BRF_PRG }, + + { "vs2.11m", 0x400000, 0xd67e47b7, 5 | BRF_SND }, + { "vs2.12m", 0x400000, 0x6d020a14, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Vsav2d) +STD_ROM_FN(Vsav2d) + +static struct BurnRomInfo XmcotadRomDesc[] = { + { "xmned.03e", 0x080000, 0xbef56003, 1 | BRF_ESS | BRF_PRG }, + { "xmned.04e", 0x080000, 0xb1a21fa6, 1 | BRF_ESS | BRF_PRG }, + { "xmn.05a", 0x080000, 0xac0d7759, 1 | BRF_ESS | BRF_PRG }, + { "xmn.06a", 0x080000, 0x1b86a328, 1 | BRF_ESS | BRF_PRG }, + { "xmn.07a", 0x080000, 0x2c142a44, 1 | BRF_ESS | BRF_PRG }, + { "xmn.08a", 0x080000, 0xf712d44f, 1 | BRF_ESS | BRF_PRG }, + { "xmn.09a", 0x080000, 0x9241cae8, 1 | BRF_ESS | BRF_PRG }, + { "xmn.10a", 0x080000, 0x53c0eab9, 1 | BRF_ESS | BRF_PRG }, + + { "xmn.13m", 0x400000, 0xbf4df073, 3 | BRF_GRA }, + { "xmn.15m", 0x400000, 0x4d7e4cef, 3 | BRF_GRA }, + { "xmn.17m", 0x400000, 0x513eea17, 3 | BRF_GRA }, + { "xmn.19m", 0x400000, 0xd23897fc, 3 | BRF_GRA }, + { "xmn.14m", 0x400000, 0x778237b7, 3 | BRF_GRA }, + { "xmn.16m", 0x400000, 0x67b36948, 3 | BRF_GRA }, + { "xmn.18m", 0x400000, 0x015a7c4c, 3 | BRF_GRA }, + { "xmn.20m", 0x400000, 0x9dde2758, 3 | BRF_GRA }, + + { "xmn.01a", 0x020000, 0x40f479ea, 4 | BRF_ESS | BRF_PRG }, + { "xmn.02a", 0x020000, 0x39d9b5ad, 4 | BRF_ESS | BRF_PRG }, + + { "xmn.11m", 0x200000, 0xc848a6bc, 5 | BRF_SND }, + { "xmn.12m", 0x200000, 0x729c188f, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmcotad) +STD_ROM_FN(Xmcotad) + +static struct BurnRomInfo Xmvsfu1dRomDesc[] = { + { "xvsud.03h", 0x080000, 0x4e2e76b7, 1 | BRF_ESS | BRF_PRG }, + { "xvsud.04h", 0x080000, 0x290c61a7, 1 | BRF_ESS | BRF_PRG }, + { "xvsd.05a", 0x080000, 0xde347b11, 1 | BRF_ESS | BRF_PRG }, + { "xvs.06a", 0x080000, 0xe8e2c75c, 1 | BRF_ESS | BRF_PRG }, + { "xvsd.07", 0x080000, 0xf761ded7, 1 | BRF_ESS | BRF_PRG }, + { "xvs.08", 0x080000, 0x81929675, 1 | BRF_ESS | BRF_PRG }, + { "xvs.09", 0x080000, 0x9641f36b, 1 | BRF_ESS | BRF_PRG }, + + { "xvs.13m", 0x400000, 0xf6684efd, 3 | BRF_GRA }, + { "xvs.15m", 0x400000, 0x29109221, 3 | BRF_GRA }, + { "xvs.17m", 0x400000, 0x92db3474, 3 | BRF_GRA }, + { "xvs.19m", 0x400000, 0x3733473c, 3 | BRF_GRA }, + { "xvs.14m", 0x400000, 0xbcac2e41, 3 | BRF_GRA }, + { "xvs.16m", 0x400000, 0xea04a272, 3 | BRF_GRA }, + { "xvs.18m", 0x400000, 0xb0def86a, 3 | BRF_GRA }, + { "xvs.20m", 0x400000, 0x4b40ff9f, 3 | BRF_GRA }, + + { "xvs.01", 0x020000, 0x3999e93a, 4 | BRF_ESS | BRF_PRG }, + { "xvs.02", 0x020000, 0x101bdee9, 4 | BRF_ESS | BRF_PRG }, + + { "xvs.11m", 0x200000, 0x9cadcdbc, 5 | BRF_SND }, + { "xvs.12m", 0x200000, 0x7b11e460, 5 | BRF_SND }, +}; + +STD_ROM_PICK(Xmvsfu1d) +STD_ROM_FN(Xmvsfu1d) + +void __fastcall PhoenixOutputWriteByte(UINT32 a,UINT8 d) +{ + if (a >= 0xfffff0 && a <= 0xfffffb) { + CpsFrg[a & 0x0f] = d; + return; + } + + if (a >= 0xff0000 && a <= 0xffffff) { + CpsRamFF[(a - 0xff0000) ^ 1] = d; + return; + } +} + +void __fastcall PhoenixSpriteWriteByte(UINT32 a,UINT8 d) +{ + bprintf(PRINT_NORMAL, _T("Byte %x, %x\n"), a, d); +} + +void __fastcall PhoenixSpriteWriteWord(UINT32 a,UINT16 d) +{ + UINT16 *Ram = (UINT16*)CpsRam708; + INT32 Offset = (a - 0x700000) >> 1; + + Ram[Offset + 0x0000] = d; + Ram[Offset + 0x4000] = d; +} + +static INT32 PhoenixInit() +{ + INT32 nRet = Cps2Init(); + + SekOpen(0); + SekMapHandler(3, 0xFF0000, 0xFFFFFF, SM_WRITE); + SekSetWriteByteHandler(3, PhoenixOutputWriteByte); + SekMapHandler(4, 0x700000, 0x701fff, SM_WRITE); + SekSetWriteByteHandler(4, PhoenixSpriteWriteByte); + SekSetWriteWordHandler(4, PhoenixSpriteWriteWord); + SekClose(); + + return nRet; +} + +static INT32 Ssf2PhoenixInit() +{ + INT32 nRet = PhoenixInit(); + + nCpsGfxScroll[3] = 0; + + return nRet; +} + +static int Ssf2tbPhoenixInit() +{ + Ssf2tb = 1; + + return Ssf2PhoenixInit(); +} + +static INT32 Ssf2tPhoenixInit() +{ + INT32 nRet; + + Ssf2t = 1; + + nRet = PhoenixInit(); + + nCpsGfxScroll[3] = 0; + + return nRet; +} + +struct BurnDriver BurnDrvCps19xxd = { + "19xxd", "19xx", NULL, NULL, "1995", + "19XX - the war against destiny (951207 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, NinexxdRomInfo, NinexxdRomName, NULL, NULL, NineXXInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCps1944d = { + "1944d", "1944", NULL, NULL, "2000", + "1944 - the loop master (000620 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, FBF_19XX, + NULL, Nine44dRomInfo, Nine44dRomName, NULL, NULL, Nine44InputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsArmwar1d = { + "armwar1d", "armwar", NULL, NULL, "1994", + "Armored Warriors (941011 Europe Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, Armwar1dRomInfo, Armwar1dRomName, NULL, NULL, ArmwarInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsAvspd = { + "avspd", "avsp", NULL, NULL, "1994", + "Alien vs Predator (940520 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG ,3,HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, AvspdRomInfo, AvspdRomName, NULL, NULL, AvspInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsBatcird = { + "batcird", "batcir", NULL, NULL, "1997", + "Battle Circuit (970319 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, BatcirdRomInfo, BatcirdRomName, NULL, NULL, BatcirInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCsclub1d = { + "csclub1d", "csclub", NULL, NULL, "1997", + "Capcom Sports Club (970722 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_SPORTSMISC, 0, + NULL, Csclub1dRomInfo, Csclub1dRomName, NULL, NULL, CsclubInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsCybotsud = { + "cybotsud", "cybots", NULL, NULL, "1995", + "Cyberbots - fullmetal madness (950424 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, CybotsudRomInfo, CybotsudRomName, NULL, NULL, CybotsInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdsomud = { + "ddsomud", "ddsom", NULL, NULL, "1996", + "Dungeons & Dragons - shadow over mystara (960619 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdsomudRomInfo, DdsomudRomName, NULL, NULL, DdsomInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDdtodd = { + "ddtodd", "ddtod", NULL, NULL, "1994", + "Dungeons & Dragons - tower of doom (940412 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0, + NULL, DdtoddRomInfo, DdtoddRomName, NULL, NULL, DdtodInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsDimahoud = { + "dimahoud", "dimahoo", NULL, NULL, "2000", + "Dimahoo (000121 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, DimahoudRomInfo, DimahoudRomName, NULL, NULL, DimahooInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvCpsDstlku1d = { + "dstlku1d", "dstlk", NULL, NULL, "1994", + "Darkstalkers - the night warriors (940705 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Dstlku1dRomInfo, Dstlku1dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsEcofghtrd = { + "ecofghtrd", "ecofghtr", NULL, NULL, "1993", + "Eco Fighters (931203 World Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_HORSHOOT, 0, + NULL, EcofghtrdRomInfo, EcofghtrdRomName, NULL, NULL, EcofghtrInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawingd = { + "gigawingd", "gigawing", NULL, NULL, "1999", + "Giga Wing (990222 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingdRomInfo, GigawingdRomName, NULL, NULL, GigawingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsGigawingjd = { + "gigawingjd", "gigawing", NULL, NULL, "1999", + "Giga Wing (990223 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, GigawingjdRomInfo, GigawingjdRomName, NULL, NULL, GigawingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsHsf2d = { + "hsf2d", "hsf2", NULL, NULL, "2004", + "Hyper Street Fighter 2: The Anniversary Edition (040202 Asia Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Hsf2dRomInfo, Hsf2dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tPhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMegamn2d = { + "megamn2d", "megaman2", NULL, NULL, "1996", + "Mega Man 2 - the power fighters (960708 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, Megamn2dRomInfo, Megamn2dRomName, NULL, NULL, Megaman2InputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000 ,384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMarsMatrixd = { + "mmatrixd", "mmatrix", NULL, NULL, "2000", + "Mars Matrix (000412 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VERSHOOT, 0, + NULL, MmatrixdRomInfo, MmatrixdRomName, NULL, NULL, MmatrixInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshud = { + "mshud", "msh", NULL, NULL, "1995", + "Marvel Super Heroes (951024 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, MshudRomInfo, MshudRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMshvsfu1d = { + "mshvsfu1d", "mshvsf", NULL, NULL, "1997", + "Marvel Super Heroes vs Street Fighter (970625 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Mshvsfu1dRomInfo, Mshvsfu1dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsMvscud = { + "mvscud", "mvsc", NULL, NULL, "1998", + "Marvel vs Capcom - clash of super heroes (980123 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, MvscudRomInfo, MvscudRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsNwarrud = { + "nwarrud", "nwarr", NULL, NULL, "1995", + "Night Warriors - darkstalkers' revenge (950406 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, NwarrudRomInfo, NwarrudRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgearud = { + "progearud", "progear", NULL, NULL, "2001", + "Progear(010117 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearudRomInfo, ProgearudRomName, NULL, NULL, ProgearInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgearjd = { + "progearjd", "progear", NULL, NULL, "2001", + "Progear No Arashi (010117 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + L"\u30D7\u30ED\u30AE\u30A2\u306E\u5D50 (Progear No Arashi 010117 Japan Phoenix Edition)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearjdRomInfo, ProgearjdRomName, NULL, NULL, ProgearInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsProgearjbl = { + "progearjbl", "progear", NULL, NULL, "2001", + "Progear No Arashi (010117 Japan, decrypted set)\0", NULL, "bootleg", "CPS2", + L"\u30D7\u30ED\u30AE\u30A2\u306E\u5D50 (Progear No Arashi 010117 Japan, decrypted set)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2 | HARDWARE_CAPCOM_CPS2_SIMM, GBF_HORSHOOT, 0, + NULL, ProgearjblRomInfo, ProgearjblRomName, NULL, NULL, ProgearInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsRingdstd = { + "ringdstd", "ringdest", NULL, NULL, "1994", + "Ring of Destruction - slammasters II (940902 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, RingdstdRomInfo, RingdstdRomName, NULL, NULL, RingdestInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfad = { + "sfad", "sfa", NULL, NULL, "1995", + "Street Fighter Alpha - warriors' dreams (950727 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SfadRomInfo, SfadRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2ad = { + "sfz2ad", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960227 Asia Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2adRomInfo, Sfz2adRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2jd = { + "sfz2jd", "sfa2", NULL, NULL, "1996", + "Street Fighter Zero 2 (960227 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2jdRomInfo, Sfz2jdRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz2ald = { + "sfz2ald", "sfz2al", NULL, NULL, "1996", + "Street Fighter Zero 2 Alpha (960826 Asia Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG,2,HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz2aldRomInfo, Sfz2aldRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfa3ud = { + "sfa3ud", "sfa3", NULL, NULL, "1998", + "Street Fighter Alpha 3 (980904 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfa3udRomInfo, Sfa3udRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSfz3jr2d = { + "sfz3jr2d", "sfa3", NULL, NULL, "1998", + "Street Fighter Zero 3 (980629 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Sfz3jr2dRomInfo, Sfz3jr2dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSgemfd = { + "sgemfd", "sgemf", NULL, NULL, "1997", + "Super Gem Fighter Mini Mix (970904 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, SgemfdRomInfo, SgemfdRomName, NULL, NULL, SgemfInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2td = { + "spf2td", "spf2t", NULL, NULL, "1996", + "Super Puzzle Fighter II Turbo (Super Puzzle Fighter 2 Turbo 960620 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2tdRomInfo, Spf2tdRomName, NULL, NULL, Spf2tInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSpf2xjd = { + "spf2xjd", "spf2t", NULL, NULL, "1996", + "Super Puzzle Fighter II X (Super Puzzle Fighter 2 X 960531 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_PUZZLE, FBF_SF, + NULL, Spf2xjdRomInfo, Spf2xjdRomName, NULL, NULL, Spf2tInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2ud = { + "ssf2ud", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the new challengers (super street fighter 2 930911 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2udRomInfo, Ssf2udRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2tbd = { + "ssf2tbd", "ssf2", NULL, NULL, "1993", + "Super Street Fighter II - the tournament battle (931119 etc Phoenix Edition)\0", "Linkup feature not implemented", "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2tbdRomInfo, Ssf2tbdRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tbPhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsSsf2xjd = { + "ssf2xjd", "ssf2t", NULL, NULL, "1994", + "Super Street Fighter II X - grand master challenge (super street fighter 2 X 940223 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Ssf2xjdRomInfo, Ssf2xjdRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + Ssf2tPhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsavd = { + "vsavd", "vsav", NULL, NULL, "1997", + "Vampire Savior - the lord of vampire (970519 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, VsavdRomInfo, VsavdRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVhunt2d = { + "vhunt2d", "vhunt2", NULL, NULL, "1997", + "Vampire Hunter 2 - darkstalkers revenge (970913 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vhunt2dRomInfo, Vhunt2dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsVsav2d = { + "vsav2d", "vsav2", NULL, NULL, "1997", + "Vampire Savior 2 - the lord of vampire (970913 Japan Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_DSTLK, + NULL, Vsav2dRomInfo, Vsav2dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmcotad = { + "xmcotad", "xmcota", NULL, NULL, "1995", + "X-Men - children of the atom (950105 Euro Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, 0, + NULL, XmcotadRomInfo, XmcotadRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCpsXmvsfu1d = { + "xmvsfu1d", "xmvsf", NULL, NULL, "1996", + "X-Men vs Street Fighter (961004 USA Phoenix Edition)\0", NULL, "bootleg", "CPS2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF, + NULL, Xmvsfu1dRomInfo, Xmvsfu1dRomName, NULL, NULL, Cps2FightingInputInfo, NULL, + PhoenixInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan, + &CpsRecalcPal, 0x1000, 384, 224, 4, 3 +}; diff --git a/src/burn/drivers/capcom/kabuki.cpp b/src/burn/drivers/capcom/kabuki.cpp new file mode 100644 index 00000000..43850cf4 --- /dev/null +++ b/src/burn/drivers/capcom/kabuki.cpp @@ -0,0 +1,167 @@ +// This file is based on the MAME source code (see http://www.mame.net/) + +/*************************************************************************** + +"Kabuki" Z80 encryption + + +The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption +key is stored in some battery-backed RAM, therefore the chip has the annoying +habit of stopping working every few years, when the battery dies. +Check at the bottom of this text to see a list of all the known games which +use this chip. + + +How it works: +The base operation is a bit swap which affects couples of adjacent bits. +Each of the 4 couples may or may not be swapped, depending on the address of +the byte and on whether it is an opcode or data. +The decryption consists of these steps: +- bitswap +- ROL +- bitswap +- XOR with a key +- ROL +- bitswap +- ROL +- bitswap + +To know how to apply the bit swap, take the address of the byte to decode and: +- if the byte is an opcode, add addr_key to the address +- if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key +You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that +word, while the second two on bits 8-15. When a bit in the word is 1, swap the +two bits, oherwise don't. The exact couple of bits affected depends on the +game and is identified in this file with two keys: swap_key1 and swap_key2 +(which are just permutations of the numbers 0-7, not full 32-bit integers). + + +Key space size: +- swap_key1 8! = 40320 +- swap_key2 8! = 40320 +- addr_key 2^16 = 65536 +- xor_key 2^8 = 256 +- total 2.7274 * 10^16 + + +Weaknesses: +- 0x00 and 0xff, having all the bits set to the same value, are not affected + by bit permutations after the XOR. Therefore, their encryption is the same + regardless of the high 8 bits of the address, and of the value of + swap_key2. If there is a long stream of 0x00 or 0xff in the original data, + this can be used to find by brute force all the candidates for swap_key1, + xor_key, and for the low 8 bits of addr_key. This is a serious weakness + which dramatically reduces the security of the encryption. +- A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is + always encrypted as a byte with as many 0s as xor_key has 1s. So you just + need to know one 0x00 or 0xff in the unencrypted data to know how many 1s + there are in xor_key. +- Once you have restricted the range for swap_key1 and you know the number of + 1s in the xor_key, you can easily use known plaintext attacks and brute + force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN + and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s + in the clear and encrypted data, taking xor_key into account. When you have + found where the string is, use brute force to reduce the key space. + + +Known games: + swap_key1 swap_key2 addr_key xor_key +Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210 01234567 aa55 a5 +Poker Ladies " " " " "" "" +Dokaben " " " " "" "" +Dokaben 2 unknown +Pang / Buster Bros / Pomping World 01234567 76543210 6548 24 +Capcom Baseball " " " " "" "" +Capcom World 04152637 40516273 5751 43 +Adventure Quiz 2 Hatena ? no Dai-Bouken 45670123 45670123 5751 43 +Super Pang 45670123 45670123 5852 43 +Super Buster Bros 45670123 45670123 2130 12 +Super Marukin-Ban 54321076 54321076 4854 4f +Quiz Tonosama no Yabou 12345670 12345670 1111 11 +Ashita Tenki ni Naare unknown +Quiz Sangokushi 23456701 23456701 1828 18 +Block Block 02461357 64207531 0002 01 + +Warriors of Fate 01234567 54163072 5151 51 +Cadillacs and Dinosaurs 76543210 24601357 4343 43 +Punisher 67452103 75316024 2222 22 +Slam Masters 54321076 65432107 3131 19 + +***************************************************************************/ + +// #include "driver.h" +#include "cps.h" + + +static INT32 bitswap1(INT32 src,INT32 key,INT32 select) +{ + if (select & (1 << ((key >> 0) & 7))) + src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1); + if (select & (1 << ((key >> 4) & 7))) + src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1); + if (select & (1 << ((key >> 8) & 7))) + src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1); + if (select & (1 << ((key >>12) & 7))) + src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1); + + return src; +} + +static INT32 bitswap2(INT32 src,INT32 key,INT32 select) +{ + if (select & (1 << ((key >>12) & 7))) + src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1); + if (select & (1 << ((key >> 8) & 7))) + src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1); + if (select & (1 << ((key >> 4) & 7))) + src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1); + if (select & (1 << ((key >> 0) & 7))) + src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1); + + return src; +} + +static INT32 bytedecode(INT32 src,INT32 swap_key1,INT32 swap_key2,INT32 xor_key,INT32 select) +{ + src = bitswap1(src,swap_key1 & 0xffff,select & 0xff); + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap2(src,swap_key1 >> 16,select & 0xff); + src ^= xor_key; + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap2(src,swap_key2 & 0xffff,select >> 8); + src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7); + src = bitswap1(src,swap_key2 >> 16,select >> 8); + return src; +} + +void kabuki_decode(UINT8 *src,UINT8 *dest_op,UINT8 *dest_data, + INT32 base_addr,INT32 length,INT32 swap_key1,INT32 swap_key2,INT32 addr_key,INT32 xor_key) +{ + INT32 A; + INT32 select; + + for (A = 0;A < length;A++) + { + /* decode opcodes */ + select = (A + base_addr) + addr_key; + dest_op[A] = (UINT8)bytedecode(src[A],swap_key1,swap_key2,xor_key,select); + + /* decode data */ + select = ((A + base_addr) ^ 0x1fc0) + addr_key + 1; + dest_data[A] = (UINT8)bytedecode(src[A],swap_key1,swap_key2,xor_key,select); + } +} + +static void cps1_decode(INT32 swap_key1,INT32 swap_key2,INT32 addr_key,INT32 xor_key) +{ + UINT8 *rom = CpsZRom; + INT32 diff = nCpsZRomLen / 2; + + CpsZRom=rom+diff; + kabuki_decode(rom,rom+diff,rom,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key); +} + +void wof_decode(void) { cps1_decode(0x01234567,0x54163072,0x5151,0x51); } +void dino_decode(void) { cps1_decode(0x76543210,0x24601357,0x4343,0x43); } +void punisher_decode(void) { cps1_decode(0x67452103,0x75316024,0x2222,0x22); } +void slammast_decode(void) { cps1_decode(0x54321076,0x65432107,0x3131,0x19); } diff --git a/src/burn/drivers/capcom/ps.cpp b/src/burn/drivers/capcom/ps.cpp new file mode 100644 index 00000000..aef77fa9 --- /dev/null +++ b/src/burn/drivers/capcom/ps.cpp @@ -0,0 +1,86 @@ +// PSound (CPS1 sound) +#include "cps.h" +#include "driver.h" +extern "C" { + #include "ym2151.h" +} + +UINT8 PsndCode, PsndFade; // Sound code/fade sent to the z80 program + +static INT32 nSyncPeriod; +static INT32 nSyncNext; + +static INT32 nCyclesDone; + +static void drvYM2151IRQHandler(INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + ZetRun(0x0800); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +INT32 PsndInit() +{ + nCpsZ80Cycles = 4000000 * 100 / nBurnFPS; + nSyncPeriod = nCpsZ80Cycles / 32; + + // Init PSound z80 + if (PsndZInit()!= 0) { + return 1; + } + + // Init PSound mixing (not critical if it fails) + PsmInit(); + + YM2151SetIrqHandler(0, &drvYM2151IRQHandler); + + PsndCode = 0; PsndFade = 0; + + nCyclesDone = 0; + + return 0; +} + +INT32 PsndExit() +{ + PsmExit(); + PsndZExit(); + + return 0; +} + +INT32 PsndScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nCyclesDone); SCAN_VAR(nSyncNext); + PsndZScan(nAction); // Scan Z80 + SCAN_VAR(PsndCode); SCAN_VAR(PsndFade); // Scan sound info + } + return 0; +} + +void PsndNewFrame() +{ + ZetNewFrame(); + PsmNewFrame(); + nSyncNext = nSyncPeriod; + + ZetIdle(nCyclesDone % nCpsZ80Cycles); + nCyclesDone = 0; +} + +INT32 PsndSyncZ80(INT32 nCycles) +{ + while (nSyncNext < nCycles) { + PsmUpdate(nSyncNext * nBurnSoundLen / nCpsZ80Cycles); + ZetRun(nSyncNext - ZetTotalCycles()); + nSyncNext += nSyncPeriod; + } + + nCyclesDone = ZetRun(nCycles - ZetTotalCycles()); + + return 0; +} diff --git a/src/burn/drivers/capcom/ps_m.cpp b/src/burn/drivers/capcom/ps_m.cpp new file mode 100644 index 00000000..7dd7baf9 --- /dev/null +++ b/src/burn/drivers/capcom/ps_m.cpp @@ -0,0 +1,94 @@ +#include "cps.h" +#include "burn_ym2151.h" + +// CPS1 sound Mixing + +INT32 bPsmOkay = 0; // 1 if the module is okay +static INT16* WaveBuf = NULL; + +static INT32 nPos; + +INT32 PsmInit() +{ + INT32 nMemLen, nRate, nRet; + bPsmOkay = 0; // not OK yet + + if (nBurnSoundRate > 0) { + nRate = nBurnSoundRate; + } else { + nRate = 11025; + } + + if (BurnYM2151Init(3579540, 50.0)) { // Init FM sound chip + return 1; + } + + // Allocate a buffer for the intermediate sound (between YM2151 and pBurnSoundOut) + nMemLen = nBurnSoundLen * 2 * sizeof(INT16); + WaveBuf = (INT16*)malloc(nMemLen); + if (WaveBuf == NULL) { + PsmExit(); + return 1; + } + memset(WaveBuf, 0, nMemLen); // Init to silence + + // Init ADPCM + MSM6295ROM = CpsAd; + if (Forgottn) { + nRet = MSM6295Init(0, 6061, 21.5, 1); + } else { + nRet = MSM6295Init(0, 7576, 21.5, 1); + } + + if (nRet!=0) { + PsmExit(); return 1; + } + + bPsmOkay = 1; // OK + + return 0; +} + +INT32 PsmExit() +{ + bPsmOkay = 0; + + MSM6295Exit(0); + + if (WaveBuf) { + free(WaveBuf); + WaveBuf = NULL; + } + + BurnYM2151Exit(); // Exit FM sound chip + return 0; +} + +void PsmNewFrame() +{ + nPos = 0; +} + +INT32 PsmUpdate(INT32 nEnd) +{ + if (bPsmOkay == 0 || pBurnSoundOut == NULL) { + return 1; + } + + if (nEnd <= nPos) { + return 0; + } + if (nEnd > nBurnSoundLen) { + nEnd = nBurnSoundLen; + } + + // Render FM + BurnYM2151Render(pBurnSoundOut + (nPos << 1), nEnd - nPos); + + // Render ADPCM + MSM6295Render(0, pBurnSoundOut + (nPos << 1), nEnd - nPos); + + nPos = nEnd; + + return 0; +} diff --git a/src/burn/drivers/capcom/ps_z.cpp b/src/burn/drivers/capcom/ps_z.cpp new file mode 100644 index 00000000..db34ef0a --- /dev/null +++ b/src/burn/drivers/capcom/ps_z.cpp @@ -0,0 +1,208 @@ +#include "cps.h" +#include "burn_ym2151.h" + +// PSound - Z80 +static INT32 nPsndZBank = 0; +static UINT8 *PsndZRam = NULL; + +INT32 Kodb = 0; + +// Map in the memory for the current 0x8000-0xc000 bank +static INT32 PsndZBankMap() +{ + UINT8 *Bank; + UINT32 nOff = (nPsndZBank << 14) + 0x8000; + + if (nOff + 0x4000 > nCpsZRomLen) { // End of bank in out of range + nOff = 0; + } + + Bank = CpsZRom + nOff; + + // Read and fetch the bank + ZetMapArea(0x8000, 0xBFFF, 0, Bank); + ZetMapArea(0x8000, 0xBFFF, 2, Bank); + + return 0; +} + +// PSound Z80 memory write +void __fastcall PsndZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xF000: + BurnYM2151SelectRegister(d); +// bprintf(PRINT_NORMAL, "YM2151 select -> %02X\n", d); + break; + case 0xF001: + BurnYM2151WriteRegister(d); +// bprintf(PRINT_NORMAL, "YM2151 write -> %02X\n", d); + break; + case 0xF002: + MSM6295Command(0, d); + break; + case 0xF004: { + INT32 nNewBank = d & 0x0f; + if (nPsndZBank != nNewBank) { + nPsndZBank = nNewBank; + PsndZBankMap(); + } + break; + } + case 0xF006: // ??? Enable interrupt ??? + break; + +#ifdef FBA_DEBUG +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d); +#endif + + } + return; +} + +void __fastcall kodbZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xE000: + BurnYM2151SelectRegister(d); + break; + case 0xE001: + BurnYM2151WriteRegister(d); + break; + case 0xE400: + MSM6295Command(0, d); + break; + +#ifdef FBA_DEBUG +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d); +#endif + + } + return; +} + +// PSound Z80 memory read +UINT8 __fastcall PsndZRead(UINT16 a) +{ + switch (a) { + case 0xF001: + return BurnYM2151ReadStatus(); + case 0xF002: + return MSM6295ReadStatus(0); + case 0xF008: +// bprintf(PRINT_NORMAL, " -- Sound latch read (%i).\n", PsndCode); + return PsndCode; + case 0xF00A: + return PsndFade; + +#ifdef FBA_DEBUG +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a); +#endif + + } + return 0; +} + +UINT8 __fastcall kodbZRead(UINT16 a) +{ + switch (a) { + case 0xE001: + return BurnYM2151ReadStatus(); + case 0xE400: + return MSM6295ReadStatus(0); + case 0xE800: + return PsndCode; + +#ifdef FBA_DEBUG +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a); +#endif + + } + return 0; +} + +INT32 PsndZInit() +{ + if (nCpsZRomLen < 0x8000) { // Not enough Z80 Data + return 1; + } + if (CpsZRom == NULL) { + return 1; + } + + PsndZRam = (UINT8 *)malloc(0x800); + if (PsndZRam == NULL) { + return 1; + } + + ZetInit(1); + + if (Kodb) { + ZetSetReadHandler(kodbZRead); + ZetSetWriteHandler(kodbZWrite); + } else { + ZetSetReadHandler(PsndZRead); + ZetSetWriteHandler(PsndZWrite); + } + + // Read and fetch first 0x8000 of Rom + ZetMapArea(0x0000,0x7fff,0,CpsZRom); + ZetMapArea(0x0000,0x7fff,2,CpsZRom); + + // Map first Bank of Rom to 0x8000-0xc000 + nPsndZBank=0; + PsndZBankMap(); + + // Ram + ZetMapArea(0xd000,0xd7ff,0,PsndZRam); + ZetMapArea(0xd000,0xd7ff,1,PsndZRam); + ZetMapArea(0xd000,0xd7ff,2,PsndZRam); + + // Sound chip interfaces + ZetMemCallback(0xf000,0xffff,0); + ZetMemCallback(0xf000,0xffff,1); + + // In case it tries to fetch other areas + ZetMapArea(0xc000,0xcfff,2,CpsZRom); + ZetMapArea(0xd800,0xffff,2,CpsZRom); + ZetMemEnd(); + ZetClose(); + + return 0; +} + +INT32 PsndZExit() +{ + if (PsndZRam) { + free(PsndZRam); + PsndZRam = NULL; + } + + ZetExit(); + return 0; +} + +// Scan the current PSound z80 state +INT32 PsndZScan(INT32 nAction) +{ + struct BurnArea ba; + ZetScan(nAction); + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + SCAN_VAR(nPsndZBank); + + // Scan Ram + memset(&ba, 0, sizeof(ba)); + ba.szName = "Z80 RAM"; + ba.Data = PsndZRam; + ba.nLen = 0x800; + BurnAcb(&ba); + + return 0; +} diff --git a/src/burn/drivers/capcom/qs.cpp b/src/burn/drivers/capcom/qs.cpp new file mode 100644 index 00000000..87df99eb --- /dev/null +++ b/src/burn/drivers/capcom/qs.cpp @@ -0,0 +1,128 @@ +#include "cps.h" +// QSound + +static INT32 nQsndCyclesExtra; + +static INT32 qsndTimerOver(INT32, INT32) +{ +// bprintf(PRINT_NORMAL, _T(" - IRQ -> 1.\n")); + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_AUTO); + + return 0; +} + +INT32 QsndInit() +{ + INT32 nVolumeShift; + INT32 nRate; + + // Init QSound z80 + if (QsndZInit()) { + return 1; + } + BurnTimerInit(qsndTimerOver, NULL); + + if (Cps1Qs == 1) { + nCpsZ80Cycles = 6000000 * 100 / nBurnFPS; + BurnTimerAttachZet(6000000); + } else { + nCpsZ80Cycles = 8000000 * 100 / nBurnFPS; + BurnTimerAttachZet(8000000); + } + + if (nBurnSoundRate >= 0) { + nRate = nBurnSoundRate; + } else { + nRate = 11025; + } + + nVolumeShift = 0; + + // These games are too soft at normal volumes + if (strncmp(BurnDrvGetTextA(DRV_NAME), "csclub", 6) == 0) { + nVolumeShift = -1; + } +#if 0 + // These games are loud at normal volumes (no clipping) + if (strncmp(BurnDrvGetTextA(DRV_NAME), "1944", 4) == 0 || + strcmp( BurnDrvGetTextA(DRV_NAME), "dimahoo" ) == 0 || + strcmp( BurnDrvGetTextA(DRV_NAME), "gmahoo" ) == 0) + { + nVolumeShift = 1; + } +#endif + // These games are too loud at normal volumes (no clipping) + if (strncmp(BurnDrvGetTextA(DRV_NAME), "sgemf", 5) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "pfght", 5) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "mpang", 5) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "spf2", 4) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "sfa2", 4) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "sfa2", 4) == 0) + { + nVolumeShift = 1; + } + // These games are too loud at normal volumes (clipping) + if (strncmp(BurnDrvGetTextA(DRV_NAME), "19xx", 4) == 0 || + strncmp(BurnDrvGetTextA(DRV_NAME), "ddtod", 5) == 0) + { + nVolumeShift = 2; + } + + QscInit(nRate, nVolumeShift); // Init QSound chip + + return 0; +} + +void QsndReset() +{ + BurnTimerReset(); + BurnTimerSetRetrig(0, 1.0 / 252.0); + + nQsndCyclesExtra = 0; +} + +void QsndExit() +{ + QscExit(); // Exit QSound chip + QsndZExit(); +} + +INT32 QsndScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + QsndZScan(nAction); // Scan Z80 + QscScan(nAction); // Scan QSound Chip + } + + return 0; +} + +void QsndNewFrame() +{ + ZetNewFrame(); + + ZetOpen(0); + ZetIdle(nQsndCyclesExtra); + + QscNewFrame(); +} + +void QsndEndFrame() +{ + BurnTimerEndFrame(nCpsZ80Cycles); + if (pBurnSoundOut) QscUpdate(nBurnSoundLen); + + nQsndCyclesExtra = ZetTotalCycles() - nCpsZ80Cycles; + ZetClose(); +} + +void QsndSyncZ80() +{ + int nCycles = (INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles; + + if (nCycles <= ZetTotalCycles()) { + return; + } + + BurnTimerUpdate(nCycles); +} diff --git a/src/burn/drivers/capcom/qs_c.cpp b/src/burn/drivers/capcom/qs_c.cpp new file mode 100644 index 00000000..ac7d149e --- /dev/null +++ b/src/burn/drivers/capcom/qs_c.cpp @@ -0,0 +1,454 @@ +// QSound - emulator for the QSound Chip + +#include +#include "cps.h" +#include "burn_sound.h" + +static const INT32 nQscClock = 4000000; +static const INT32 nQscClockDivider = 166; + +static INT32 nQscRate = 0; +static INT32 nQscVolumeShift; + +static INT32 Tams = -1; +static INT32* Qs_s = NULL; + +static INT32 nPos; + +struct QChan { + UINT8 bKey; // 1 if channel is playing + INT8 nBank; // Bank we are currently playing a sample from + + INT8* PlayBank; // Pointer to current bank + + INT32 nPlayStart; // Start of being played + INT32 nStart; // Start of sample 16.12 + INT32 nEnd; // End of sample 16.12 + INT32 nLoop; // Loop offset from end + INT32 nPos; // Current position within the bank 16.12 + INT32 nAdvance; // Sample size + + INT32 nMasterVolume; // Master volume for the channel + INT32 nVolume[2]; // Left & right side volumes (panning) + + INT32 nPitch; // Playback frequency + + INT8 nEndBuffer[8]; // Buffer to enable correct cubic interpolation +}; + +static struct QChan QChan[16]; + +static INT32 PanningVolumes[33]; + +static void MapBank(struct QChan* pc) +{ + UINT32 nBank; + + nBank = (pc->nBank & 0x7F) << 16; // Banks are 0x10000 samples long + + // Confirm whole bank is in range: + // If bank is out of range use bank 0 instead + if ((nBank + 0x10000) > nCpsQSamLen) { + nBank = 0; + } + pc->PlayBank = (INT8*)CpsQSam + nBank; +} + +static void UpdateEndBuffer(struct QChan* pc) +{ + if (pc->bKey) { + // prepare a buffer to correctly interpolate the last 4 samples + if (nInterpolation >= 3) { + for (INT32 i = 0; i < 4; i++) { + pc->nEndBuffer[i] = pc->PlayBank[(pc->nEnd >> 12) - 4 + i]; + } + + if (pc->nLoop) { + for (INT32 i = 0, j = 0; i < 4; i++, j++) { + if (j >= (pc->nLoop >> 12)) { + j = 0; + } + pc->nEndBuffer[i + 4] = pc->PlayBank[((pc->nEnd - pc->nLoop) >> 12) + j]; + } + } else { + for (INT32 i = 0; i < 4; i++) { + pc->nEndBuffer[i + 4] = pc->nEndBuffer[3]; + } + } + } + } +} + +static void CalcAdvance(struct QChan* pc) +{ + if (nQscRate) { + pc->nAdvance = (INT64)pc->nPitch * nQscClock / nQscClockDivider / nQscRate; + } +} + +void QscReset() +{ + memset(QChan, 0, sizeof(QChan)); + + // Point all to bank 0 + for (INT32 i = 0; i < 16; i++) { + QChan[i].PlayBank = (INT8*)CpsQSam; + } +} + +void QscExit() +{ + nQscRate = 0; + + if (Qs_s) { + free(Qs_s); + Qs_s = NULL; + } + Tams = -1; +} + +INT32 QscInit(INT32 nRate, INT32 nVolumeShift) +{ + nQscRate = nRate; + + nQscVolumeShift = 10 + nVolumeShift; + + for (INT32 i = 0; i < 33; i++) { + PanningVolumes[i] = (INT32)((256.0 / sqrt(32.0)) * sqrt((double)i)); + } + + QscReset(); + + return 0; +} + +INT32 QscScan(INT32 nAction) +{ + SCAN_VAR(QChan); + + if (nAction & ACB_WRITE) { + // Update bank pointers with new banks, and recalc nAdvance + for (INT32 i = 0; i < 16; i++) { + MapBank(QChan + i); + CalcAdvance(QChan + i); + } + } + + return 0; +} + +void QscNewFrame() +{ + nPos = 0; +} + +static inline void QscSyncQsnd() +{ + if (pBurnSoundOut) QscUpdate(ZetTotalCycles() * nBurnSoundLen / nCpsZ80Cycles); +} + +void QscWrite(INT32 a, INT32 d) +{ + struct QChan* pc; + INT32 nChanNum, r; + + // unknown + if (a >= 0x90) { +// bprintf(PRINT_NORMAL, "QSound: reg 0x%02X -> 0x%02X.\n", a, d); + return; + } + + QscSyncQsnd(); + + if (a >= 0x80) { // Set panning for channel + INT32 nPan; + + nChanNum = a & 15; + + pc = QChan + nChanNum; // Find channel + nPan = (d - 0x10) & 0x3F; // nPan = 0x00 to 0x20 now + if (nPan > 0x20) { + nPan = 0x20; + } + +// bprintf(PRINT_NORMAL, "QSound: ch#%i pan -> 0x%04X\n", nChanNum, d); + + pc->nVolume[0] = PanningVolumes[0x20 - nPan]; + pc->nVolume[1] = PanningVolumes[0x00 + nPan]; + + return; + } + + // Get channel and register number + nChanNum = (a >> 3) & 15; + r = a & 7; + + // Pointer to channel info + pc = QChan + nChanNum; + + switch (r) { + case 0: { // Set bank + // Strange but true + pc = QChan + ((nChanNum + 1) & 15); + pc->nBank = d; + MapBank(pc); + UpdateEndBuffer(pc); + break; + } + case 1: { // Set sample start offset + pc->nStart = d << 12; + break; + } + case 2: { + pc->nPitch = d; + CalcAdvance(pc); + + if (d == 0) { // Key off; stop playing + pc->bKey = 0; + } + + break; + } +#if 0 + case 3: { + break; + } +#endif + case 4: { // Set sample loop offset + pc->nLoop = d << 12; + UpdateEndBuffer(pc); + break; + } + case 5: { // Set sample end offset + pc->nEnd = d << 12; + UpdateEndBuffer(pc); + break; + } + case 6: { // Set volume + pc->nMasterVolume = d; + + if (d == 0) { + pc->bKey = 0; + } else { + if (pc->bKey == 0) { // Key on; play sample + pc->nPlayStart = pc->nStart; + + pc->nPos = 0; + pc->bKey = 3; + UpdateEndBuffer(pc); + } + } + break; + } +#if 0 + case 7: { + break; + } +#endif + + } +} + +INT32 QscUpdate(INT32 nEnd) +{ + INT32 nLen; + + if (nEnd > nBurnSoundLen) { + nEnd = nBurnSoundLen; + } + + nLen = nEnd - nPos; + + if (nLen <= 0) { + return 0; + } + + if (Tams < nLen) { + if (Qs_s) { + free(Qs_s); + Qs_s = NULL; + } + Tams = nLen; + Qs_s = (INT32*)malloc(sizeof(INT32) * 2 * Tams); + } + + memset(Qs_s, 0, nLen * 2 * sizeof(INT32)); + + if (nInterpolation < 3) { + + // Go through all channels + for (INT32 c = 0; c < 16; c++) { + + // If the channel is playing, add the samples to the buffer + if (QChan[c].bKey) { + INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift; + INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift; + INT32* pTemp = Qs_s; + INT32 i = nLen; + INT32 s, p; + + if (QChan[c].bKey & 2) { + QChan[c].bKey &= ~2; + QChan[c].nPos = QChan[c].nPlayStart; + } + + while (i--) { + + p = (QChan[c].nPos >> 12) & 0xFFFF; + + // Check for end of sample + if (QChan[c].nPos >= (QChan[c].nEnd - 0x01000)) { + if (QChan[c].nLoop) { // Loop sample + if (QChan[c].nPos < QChan[c].nEnd) { + QChan[c].nEndBuffer[0] = QChan[c].PlayBank[(QChan[c].nEnd - QChan[c].nLoop) >> 12]; + } else { + QChan[c].nPos = QChan[c].nEnd - QChan[c].nLoop + (QChan[c].nPos & 0x0FFF); + p = (QChan[c].nPos >> 12) & 0xFFFF; + } + } else { + if (QChan[c].nPos < QChan[c].nEnd) { + QChan[c].nEndBuffer[0] = QChan[c].PlayBank[p]; + } else { + QChan[c].bKey = 0; // Quit playing + break; + } + } + } else { + QChan[c].nEndBuffer[0] = QChan[c].PlayBank[p + 1]; + } + + // Interpolate sample + s = QChan[c].PlayBank[p] * (1 << 6) + ((QChan[c].nPos) & ((1 << 12) - 1)) * (QChan[c].nEndBuffer[0] - QChan[c].PlayBank[p]) / (1 << 6); + + // Add to the sound currently in the buffer + pTemp[0] += s * VolL; + pTemp[1] += s * VolR; + + pTemp += 2; + + QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch + } + } + } + + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen); +#endif + } else { + BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen); + } + nPos = nEnd; + + return 0; + } + + // Go through all channels + for (INT32 c = 0; c < 16; c++) { + + // If the channel is playing, add the samples to the buffer + if (QChan[c].bKey) { + INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift; + INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift; + INT32* pTemp = Qs_s; + INT32 i = nLen; + + // handle 1st sample + if (QChan[c].bKey & 2) { + while (QChan[c].nPos < 0x1000 && i) { + INT32 p = QChan[c].nPlayStart >> 12; + INT32 s = INTERPOLATE4PS_CUSTOM(QChan[c].nPos, + 0, + QChan[c].PlayBank[p + 0], + QChan[c].PlayBank[p + 1], + QChan[c].PlayBank[p + 2], + 256); + + pTemp[0] += s * VolL; + pTemp[1] += s * VolR; + + QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch + + pTemp += 2; + i--; + } + if (i > 0) { + QChan[c].bKey &= ~2; + QChan[c].nPos = (QChan[c].nPos & 0x0FFF) + QChan[c].nPlayStart; + } + } + + if (bBurnUseMMX && i > 0) { +#if defined BUILD_X86_ASM + QChan[c].bKey = (UINT8)ChannelMix_QS_A(pTemp, i, + (char*)QChan[c].PlayBank, + QChan[c].nEnd, + &(QChan[c].nPos), + VolL, + VolR, + QChan[c].nLoop, + QChan[c].nAdvance, + (char*)QChan[c].nEndBuffer); +#endif + } else { + while (i > 0) { + INT32 s, p; + + // Check for end of sample + if (QChan[c].nPos >= (QChan[c].nEnd - 0x3000)) { + if (QChan[c].nPos < QChan[c].nEnd) { + INT32 nIndex = 4 - ((QChan[c].nEnd - QChan[c].nPos) >> 12); + s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1), + QChan[c].nEndBuffer[nIndex + 0], + QChan[c].nEndBuffer[nIndex + 1], + QChan[c].nEndBuffer[nIndex + 2], + QChan[c].nEndBuffer[nIndex + 3], + 256); + } else { + if (QChan[c].nLoop) { // Loop sample + if (QChan[c].nLoop <= 0x1000) { // Don't play, but leave bKey on + QChan[c].nPos = QChan[c].nEnd - 0x1000; + break; + } + QChan[c].nPos -= QChan[c].nLoop; + continue; + } else { + QChan[c].bKey = 0; // Stop playing + break; + } + } + } else { + p = (QChan[c].nPos >> 12) & 0xFFFF; + s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1), + QChan[c].PlayBank[p + 0], + QChan[c].PlayBank[p + 1], + QChan[c].PlayBank[p + 2], + QChan[c].PlayBank[p + 3], + 256); + } + + // Add to the sound currently in the buffer + pTemp[0] += s * VolL; + pTemp[1] += s * VolR; + + pTemp += 2; + + QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch + + i--; + } + } + } + } + + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen); +#endif + } else { + BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen); + } + nPos = nEnd; + + return 0; +} diff --git a/src/burn/drivers/capcom/qs_z.cpp b/src/burn/drivers/capcom/qs_z.cpp new file mode 100644 index 00000000..337381ff --- /dev/null +++ b/src/burn/drivers/capcom/qs_z.cpp @@ -0,0 +1,138 @@ +#include "cps.h" +// QSound - Z80 + +static INT32 nQsndZBank = 0; + +// Map in the memory for the current 0x8000-0xc000 music bank +static INT32 QsndZBankMap() +{ + UINT32 nOff; + UINT8* Bank; + nOff = nQsndZBank << 14; + nOff += 0x8000; + + if (Cps1Qs == 0) { + if (nOff + 0x4000 > nCpsZRomLen) { // End of bank is out of range + nOff = 0; + } + Bank = CpsZRom + nOff; + } else { + if (nOff + 0x4000 > (nCpsZRomLen / 2)) { + nOff = 0; + } + Bank = CpsZRom - (nCpsZRomLen / 2) + nOff; + } + + // Read and fetch the bank + ZetMapArea(0x8000, 0xbfff, 0, Bank); + if (Cps1Qs == 0) { + ZetMapArea(0x8000, 0xbfff, 2, Bank, CpsZRom + nOff); + } else { + ZetMapArea(0x8000, 0xbfff, 2, Bank); + } + + return 0; +} + +static UINT8 QscCmd[2] = {0, 0}; + +void __fastcall QsndZWrite(UINT16 a, UINT8 d) +{ + if (a == 0xd000) { + QscCmd[0] = d; + return; + } + if (a == 0xd001) { + QscCmd[1] = d; + return; + } + if (a == 0xd002) { + QscWrite(d, (QscCmd[0] << 8) | QscCmd[1]); +// bprintf(PRINT_NORMAL, _T("QSound command %02X %04X sent.\n"), d, (QscCmd[0] << 8) | QscCmd[1]); + return; + } + if (a == 0xd003) { + INT32 nNewBank = d & 0x0f; + if (nQsndZBank != nNewBank) { + nQsndZBank = nNewBank; + QsndZBankMap(); + } + } +} + +UINT8 __fastcall QsndZRead(UINT16 a) +{ + if (a == 0xd007) { // return ready all the time + return 0x80; + } + return 0; +} + +INT32 QsndZInit() +{ + if (nCpsZRomLen < 0x8000) { // Not enough Z80 Data + return 1; + } + if (CpsZRom == NULL) { + return 1; + } + + ZetInit(1); + + ZetSetReadHandler(QsndZRead); + ZetSetWriteHandler(QsndZWrite); + + // Read and fetch first 0x8000 of Rom + if (Cps1Qs) { + ZetMapArea(0x0000, 0x7FFF, 0, CpsZRom - (nCpsZRomLen / 2)); + ZetMapArea(0x0000, 0x7FFF, 2, CpsZRom, CpsZRom - (nCpsZRomLen / 2)); // If it tries to fetch this area + } else { + ZetMapArea(0x0000, 0x7FFF, 0 ,CpsZRom); + ZetMapArea(0x0000, 0x7FFF, 2, CpsZRom); + } + + // Map first Bank of Rom + nQsndZBank = 0; + QsndZBankMap(); + + ZetMapArea(0xC000, 0xCFFF, 0, CpsZRamC0); + ZetMapArea(0xC000, 0xCFFF, 1, CpsZRamC0); + ZetMapArea(0xC000, 0xCFFF, 2, CpsZRamC0); + + ZetMemCallback(0xD000, 0xEFFF, 0); + ZetMemCallback(0xD000, 0xEFFF, 1); + + if (Cps1Qs) { + ZetMapArea(0xD000, 0xEFFF, 2, CpsZRom, CpsZRom - (nCpsZRomLen / 2)); // If it tries to fetch this area + } else { + ZetMapArea(0xD000, 0xEFFF, 2, CpsZRom); + } + + ZetMapArea(0xF000, 0xFFFF, 0, CpsZRamF0); + ZetMapArea(0xF000, 0xFFFF, 1, CpsZRamF0); + ZetMapArea(0xF000, 0xFFFF, 2, CpsZRamF0); + + ZetMemEnd(); + ZetClose(); + + return 0; +} + +INT32 QsndZExit() +{ + ZetExit(); + return 0; +} + +// Scan the current QSound z80 state +INT32 QsndZScan(INT32 nAction) +{ + ZetScan(nAction); // Scan Z80 + SCAN_VAR(nQsndZBank); + + if (nAction & ACB_WRITE) { // If write, bank could have changed + QsndZBankMap(); + } + + return 0; +} diff --git a/src/burn/drivers/cave/cave.cpp b/src/burn/drivers/cave/cave.cpp new file mode 100644 index 00000000..5419c261 --- /dev/null +++ b/src/burn/drivers/cave/cave.cpp @@ -0,0 +1,47 @@ +#include "cave.h" + +INT32 nCaveXSize = 0, nCaveYSize = 0; +INT32 nCaveXOffset = 0, nCaveYOffset = 0; +INT32 nCaveExtraXOffset = 0, nCaveExtraYOffset = 0; +INT32 nCaveRowModeOffset = 0; + +INT32 CaveScanGraphics() +{ + SCAN_VAR(nCaveXOffset); + SCAN_VAR(nCaveYOffset); + + SCAN_VAR(nCaveTileBank); + + SCAN_VAR(nCaveSpriteBank); + SCAN_VAR(nCaveSpriteBankDelay); + + for (INT32 i = 0; i < 4; i++) { + SCAN_VAR(CaveTileReg[i][0]); + SCAN_VAR(CaveTileReg[i][1]); + SCAN_VAR(CaveTileReg[i][2]); + } + + return 0; +} + +// This function fills the screen with the background colour +void CaveClearScreen(UINT32 nColour) +{ + if (nColour) { + UINT32* pClear = (UINT32*)pBurnDraw; + nColour = nColour | (nColour << 16); + for (INT32 i = nCaveXSize * nCaveYSize / 16; i > 0 ; i--) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + } else { + memset(pBurnDraw, 0, nCaveXSize * nCaveYSize * sizeof(INT16)); + } +} + diff --git a/src/burn/drivers/cave/cave.h b/src/burn/drivers/cave/cave.h new file mode 100644 index 00000000..3ab6ebf7 --- /dev/null +++ b/src/burn/drivers/cave/cave.h @@ -0,0 +1,63 @@ +#include "burnint.h" +#include "eeprom.h" + +#define CAVE_REFRESHRATE (15625.0 / 271.5) + +inline static void CaveClearOpposites(UINT16* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x0003) == 0x0003) { + *nJoystickInputs &= ~0x0003; + } + if ((*nJoystickInputs & 0x000C) == 0x000C) { + *nJoystickInputs &= ~0x000C; + } +} + +// cave.cpp +extern INT32 nCaveXSize, nCaveYSize; +extern INT32 nCaveXOffset, nCaveYOffset; +extern INT32 nCaveExtraXOffset, nCaveExtraYOffset; +extern INT32 nCaveRowModeOffset; + +INT32 CaveScanGraphics(); +void CaveClearScreen(UINT32 nColour); + +// cave_palette.cpp +extern UINT32* CavePalette; + +extern UINT8* CavePalSrc; +extern UINT8 CaveRecalcPalette; + +INT32 CavePalInit(INT32 nPalSize); +INT32 CavePalExit(); +INT32 CavePalUpdate4Bit(INT32 nOffset, INT32 nNumPalettes); +INT32 CavePalUpdate8Bit(INT32 nOffset, INT32 nNumPalettes); + +void CavePalWriteByte(UINT32 nAddress, UINT8 byteValue); +void CavePalWriteWord(UINT32 nAddress, UINT16 wordValue); + +// cave_tiles.cpp +extern UINT8* CaveTileROM[4]; +extern UINT8* CaveTileRAM[4]; + +extern UINT32 CaveTileReg[4][3]; +extern INT32 nCaveTileBank; + +INT32 CaveTileRender(INT32 nMode); +void CaveTileExit(); +INT32 CaveTileInit(); +INT32 CaveTileInitLayer(INT32 nLayer, INT32 nROMSize, INT32 nBitdepth, INT32 nOffset); + +// cave_sprite.cpp +extern INT32 CaveSpriteVisibleXOffset; + +extern UINT8* CaveSpriteROM; +extern UINT8* CaveSpriteRAM; + +extern INT32 nCaveSpriteBank; +extern INT32 nCaveSpriteBankDelay; + +extern INT32 (*CaveSpriteBuffer)(); +extern INT32 CaveSpriteRender(INT32 nLowPriority, INT32 nHighPriority); +void CaveSpriteExit(); +INT32 CaveSpriteInit(INT32 nType, INT32 nROMSize); diff --git a/src/burn/drivers/cave/cave_palette.cpp b/src/burn/drivers/cave/cave_palette.cpp new file mode 100644 index 00000000..91539ee0 --- /dev/null +++ b/src/burn/drivers/cave/cave_palette.cpp @@ -0,0 +1,154 @@ +#include "cave.h" + +UINT8* CavePalSrc; +UINT8 CaveRecalcPalette; // Set to 1 to force recalculation of the entire palette + +UINT32* CavePalette = NULL; +static UINT16* CavePalCopy = NULL; + +INT32 CavePalInit(INT32 nPalSize) +{ + CavePalette = (UINT32*)malloc(nPalSize * sizeof(UINT32)); + memset(CavePalette, 0, nPalSize * sizeof(UINT32)); + + CavePalCopy = (UINT16*)malloc(nPalSize * sizeof(UINT16)); + memset(CavePalCopy, 0, nPalSize * sizeof(UINT16)); + + pBurnDrvPalette = CavePalette; + + return 0; +} + +INT32 CavePalExit() +{ + if (CavePalette) { + free(CavePalette); + CavePalette = NULL; + } + if (CavePalCopy) { + free(CavePalCopy); + CavePalCopy = NULL; + } + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x03E0) >> 2; // Red + r |= r >> 5; + g = (nColour & 0x7C00) >> 7; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +INT32 CavePalUpdate4Bit(INT32 nOffset, INT32 nNumPalettes) +{ + INT32 i, j; + + UINT16* ps = (UINT16*)CavePalSrc + nOffset; + UINT16* pc; + UINT32* pd; + + UINT16 c; + + if (CaveRecalcPalette) { + + for (i = 0; i < 0 + nNumPalettes; i++) { + + pc = CavePalCopy + (i << 8); + pd = CavePalette + (i << 8); + + for (j = 0; j < 16; j++, ps++, pc++, pd++) { + + c = *ps; + *pc = c; + *pd = CalcCol(c); + + } + } + + CaveRecalcPalette = 0; + return 0; + } + + + for (i = 0; i < 0 + nNumPalettes; i++) { + + pc = CavePalCopy + (i << 8); + pd = CavePalette + (i << 8); + + for (j = 0; j < 16; j++, ps++, pc++, pd++) { + + c = *ps; + if (*pc != c) { + *pc = c; + *pd = CalcCol(c); + } + + } + } + + return 0; +} + +INT32 CavePalUpdate8Bit(INT32 nOffset, INT32 nNumPalettes) +{ + if (CaveRecalcPalette) { + INT32 i, j; + + UINT16* ps = (UINT16*)CavePalSrc + nOffset; + UINT16* pc; + UINT32* pd; + + UINT16 c; + + for (i = 0; i < nNumPalettes; i++) { + + pc = CavePalCopy + nOffset + (i << 8); + pd = CavePalette + nOffset + (i << 8); + + for (j = 0; j < 256; j++, ps++, pc++, pd++) { + + c = *ps; + *pc = c; + *pd = CalcCol(c); + + } + } + + CaveRecalcPalette = 0; + } + + return 0; +} + +// Update the PC copy of the palette on writes to the palette memory +void CavePalWriteByte(UINT32 nAddress, UINT8 byteValue) +{ + nAddress ^= 1; + CavePalSrc[nAddress] = byteValue; // write byte + + if (*((UINT8*)(CavePalCopy + nAddress)) != byteValue) { + *((UINT8*)(CavePalCopy + nAddress)) = byteValue; + CavePalette[nAddress >> 1] = CalcCol(*(UINT16*)(CavePalSrc + (nAddress & ~0x01))); + } +} + +void CavePalWriteWord(UINT32 nAddress, UINT16 wordValue) +{ + nAddress >>= 1; + + ((UINT16*)CavePalSrc)[nAddress] = wordValue; // write word + + if (CavePalCopy[nAddress] != wordValue) { + CavePalCopy[nAddress] = wordValue; + CavePalette[nAddress] = CalcCol(wordValue); + } +} + diff --git a/src/burn/drivers/cave/cave_sprite.cpp b/src/burn/drivers/cave/cave_sprite.cpp new file mode 100644 index 00000000..28f0679c --- /dev/null +++ b/src/burn/drivers/cave/cave_sprite.cpp @@ -0,0 +1,742 @@ +// Cave hardware sprites +#include "cave.h" + +INT32 CaveSpriteVisibleXOffset; + +UINT8* CaveSpriteROM = NULL; +UINT8* CaveSpriteRAM = NULL; + +INT32 nCaveSpriteBank; +INT32 nCaveSpriteBankDelay; + +static INT32 nSpriteAddressMask; + +struct CaveSprite { + INT8 flip; + INT8 priority; + INT16 palette; + INT32 x; INT32 y; + INT32 xsize; INT32 ysize; + INT32 xzoom; INT32 yzoom; + INT32 address; +}; + +static CaveSprite* pSpriteList = NULL; + +INT32 (*CaveSpriteBuffer)(); + +static UINT8* pRow; +static UINT8* pPixel; +static UINT32* pSpriteData; +static UINT32* pSpritePalette; + +static UINT16* pZBuffer = NULL; +static UINT16* pZRow; +static UINT16* pZPixel; + +static INT32 nSpriteRow, nSpriteRowSize; +static INT32 nXPos, nYPos, nZPos; +static INT32 nXSize, nYSize; +static INT32 nSpriteXZoomSize, nSpriteYZoomSize; +static INT32 nSpriteXOffset, nSpriteYOffset; + +static INT32 nFirstSprite[4], nLastSprite[4]; + +static INT32 nTopSprite; +static INT32 nZOffset; + +typedef void (*RenderSpriteFunction)(); +static RenderSpriteFunction* RenderSprite; + +// Include the sprite rendering functions +#include "cave_sprite_func.h" + +INT32 CaveSpriteRender(INT32 nLowPriority, INT32 nHighPriority) +{ + static INT32 nMaskLeft, nMaskRight, nMaskTop, nMaskBottom; + CaveSprite* pBuffer; + + INT32 nPriorityMask = 0; + INT32 nMaxZPos = -1; + INT32 nCurrentZPos = 0x00010000; + INT32 nUseBuffer = 0x00010000; + INT32 nFunction; + + if (nLowPriority == 0) { + nZPos = -1; + nTopSprite = -1; + + nMaskLeft = nMaskTop = 9999; + nMaskRight = nMaskBottom = -1; + } + + if ((nBurnLayer & 1) == 0) { + return 0; + } + + if (nHighPriority < 3) { + for (INT32 i = nHighPriority + 1; i < 4; i++) { + if (nUseBuffer > nFirstSprite[i]) { + nUseBuffer = nFirstSprite[i]; + } + } + } + + for (INT32 i = nLowPriority; i <= nHighPriority; i++) { + if (nCurrentZPos > nFirstSprite[i]) { + nCurrentZPos = nFirstSprite[i]; + } + if (nMaxZPos < nLastSprite[i]) { + nMaxZPos = nLastSprite[i]; + } + nPriorityMask |= 8 >> i; + } + + nPriorityMask &= nSpriteEnable; + if (nPriorityMask == 0) { + return 0; + } + + for (pBuffer = pSpriteList + nCurrentZPos; nCurrentZPos <= nMaxZPos; pBuffer++, nCurrentZPos++) { + + if ((pBuffer->priority & nPriorityMask) == 0) { + continue; + } + + nXPos = pBuffer->x; + nYPos = pBuffer->y; + + pSpriteData = (UINT32*)(CaveSpriteROM + ((pBuffer->address << 8) & nSpriteAddressMask)); + pSpritePalette = CavePalette + pBuffer->palette; + + nXSize = pBuffer->xsize; + nYSize = pBuffer->ysize; + + if (pBuffer->xzoom == 0x0100 && pBuffer->yzoom == 0x0100) { // This sprite doesn't use zooming + + nSpriteRowSize = pBuffer->xsize >> 2; + + if (pBuffer->flip & 1) { // Y Flip + pSpriteData += nSpriteRowSize * (nYSize - 1); + nSpriteRowSize = -nSpriteRowSize; + } + + if (nYPos >= 0x0200) { + nYPos -= 0x0400; + } + + if (nYPos < 0) { + pSpriteData += nSpriteRowSize * -nYPos; + nYSize += nYPos; + nYPos = 0; + } + + if ((nYPos + nYSize) > nCaveYSize) { + nYSize -= (nYPos + nYSize) - nCaveYSize; + } + + if (nXPos >= 0x0200) { + nXPos -= 0x0400; + } + + if (nXPos < 0) { + if ((pBuffer->flip & 2) == 0) { + pSpriteData += (-nXPos >> 4) << 2; + } + nXSize -= -nXPos & 0xFFF0; + nXPos += -nXPos & 0xFFF0; + } + + if (nXPos + nXSize >= nCaveXSize) { + if (pBuffer->flip & 2) { + pSpriteData += ((nXPos + nXSize - nCaveXSize) >> 4) << 2; + } + nXSize -= (nXPos + nXSize - nCaveXSize) & 0xFFF0; + } + + pRow = pBurnDraw + (nYPos * nBurnPitch) + (nXPos * nBurnBpp); + + nFunction = (pBuffer->flip & 2) << 1; // X Flip + + if (nTopSprite > nCurrentZPos) { // Test ZBuffer + if (nXPos < nMaskRight && (nXPos + nXSize) >= nMaskLeft && nYPos < nMaskBottom && (nYPos + nYSize) >= nMaskTop) { + nFunction |= 1; + } + } + + if (nUseBuffer < nCurrentZPos) { // Write ZBuffer + nFunction |= 2; + + if (nXPos < nMaskLeft) { + nMaskLeft = nXPos; + } + if ((nXPos + nXSize) > nMaskRight) { + nMaskRight = nXPos + nXSize; + } + if (nYPos < nMaskTop) { + nMaskTop = nYPos; + } + if ((nYPos + nYSize) > nMaskBottom) { + nMaskBottom = nYPos + nYSize; + } + } + + if (nFunction & 3) { + pZRow = pZBuffer + (nYPos * 320) + nXPos; + nZPos = nCurrentZPos + nZOffset; + } + + nXSize = nXSize >> 2; + + RenderSprite[nFunction](); + } else { // This sprite uses zooming + nSpriteXZoomSize = 0x01000000; // * zoom factor = size of each screen pixel + + nXSize *= pBuffer->xzoom; + nXSize >>= 8; // Round to multiple of whole pixel + if (nXSize < 1) { // Make sure the sprite is at least one pixel wide + nXSize = 1; + } else { + nSpriteXZoomSize /= pBuffer->xzoom; + } + if (nSpriteXZoomSize > (pBuffer->xsize << 16)) { + nSpriteXZoomSize = pBuffer->xsize << 16; + } + nSpriteXOffset = nSpriteXZoomSize >> 1; // Make certain the pixels displayed are centered + + if (pBuffer->flip & 2) { // X Flip + nXPos += pBuffer->xsize - nXSize; + + nSpriteXOffset = (pBuffer->xsize << 16) - nSpriteXOffset; + nSpriteXZoomSize = -nSpriteXZoomSize; + } + + if (nXPos >= 0x0200) { + nXPos -= 0x0400; + } + + if (nXPos < 0) { + if (nXPos + nXSize <= 0) { + continue; + } + nXPos = -nXPos; + nSpriteXOffset += nXPos * nSpriteXZoomSize; + nXSize -= nXPos; + nXPos = 0; + } + + if (nXPos + nXSize >= nCaveXSize) { + if (nXPos >= nCaveXSize) { + continue; + } + nXSize = nCaveXSize - nXPos; + } + + nSpriteRowSize = pBuffer->xsize; // Size of each sprite row in memory + nSpriteYZoomSize = 0x01000000; // * zoom factor = size of each screen pixel + + nYSize *= pBuffer->yzoom; + nYSize >>= 8; // Round to multiple of whole pixel + if (nYSize < 1) { // Make certain the sprite is at least one pixel high + nYSize = 1; + } else { + nSpriteYZoomSize /= pBuffer->yzoom; + } + if (nSpriteYZoomSize > (pBuffer->ysize << 16)) { + nSpriteYZoomSize = pBuffer->ysize << 16; + } + nSpriteYOffset = nSpriteYZoomSize >> 1; // Make certain the pixels displayed are centered + + if (pBuffer->flip & 1) { // Y Flip + nYPos += pBuffer->ysize - nYSize; + + nSpriteYOffset = (pBuffer->ysize << 16) - nSpriteYOffset; + nSpriteYZoomSize = -nSpriteYZoomSize; + } + + if (nYPos >= 0x0200) { + nYPos -= 0x0400; + } + + if (nYPos < 0) { + if (nYPos + nYSize <= 0) { + continue; + } + nYPos = -nYPos; + nSpriteYOffset += nYPos * nSpriteYZoomSize; + nYSize -= nYPos; + nYPos = 0; + } + + if (nYPos + nYSize >= nCaveYSize) { + if (nYPos >= nCaveYSize) { + continue; + } + nYSize = nCaveYSize - nYPos; + } + + pRow = pBurnDraw + (nYPos * nBurnPitch) + (nXPos * nBurnBpp); + + nFunction = 8; + + if (pBuffer->xzoom > 0x0100 || pBuffer->yzoom > 0x0100) { + nFunction |= 4; + } + + if (nTopSprite > nCurrentZPos) { // Test ZBuffer + if (nXPos < nMaskRight && nXPos + nXSize >= nMaskLeft && nYPos < nMaskBottom && nYPos + nYSize >= nMaskTop) { + nFunction |= 1; + } + } + + if (nUseBuffer < nCurrentZPos) { // Write ZBuffer + nFunction |= 2; + + if (nXPos < nMaskLeft) { + nMaskLeft = nXPos; + } + if (nXPos + nXSize > nMaskRight) { + nMaskRight = nXPos + nXSize; + } + if (nYPos < nMaskTop) { + nMaskTop = nYPos; + } + if (nYPos + nYSize > nMaskBottom) { + nMaskBottom = nYPos + nYSize; + } + } + + if (nFunction & 3) { + pZRow = pZBuffer + (nYPos * nCaveXSize) + nXPos; + nZPos = nCurrentZPos + nZOffset; + } + + nXSize <<= 16; + nYSize <<= 16; + + RenderSprite[nFunction](); + } + } + + if (nMaxZPos > nTopSprite) { + nTopSprite = nMaxZPos; + } + + if (nHighPriority == 3) { + if (nZPos >= 0) { + nZOffset += nTopSprite; + if (nZOffset > 0xFC00) { + memset(pZBuffer, 0, nCaveXSize * nCaveYSize * sizeof(UINT16)); + nZOffset = 0; + } + } + } + + return 0; +} + +// Donpachi/DoDonpachi sprite format (no zooming) +static INT32 CaveSpriteBuffer_NoZoom() +{ + UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14)); + CaveSprite* pBuffer = pSpriteList; + INT32 nPriority; + + nFirstSprite[0] = 0x00010000; + nFirstSprite[1] = 0x00010000; + nFirstSprite[2] = 0x00010000; + nFirstSprite[3] = 0x00010000; + + nLastSprite[0] = -1; + nLastSprite[1] = -1; + nLastSprite[2] = -1; + nLastSprite[3] = -1; + + INT16 word; + INT32 x, y, xs, ys; + + for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) { + + word = pSprite[4]; + + xs = (word >> 4) & 0x01F0; + ys = (word << 4) & 0x01F0; + if (ys == 0 || xs == 0) { + continue; + } + +#if 0 + x = (pSprite[2] + nCaveExtraXOffset) & 0x03FF; +#else + x = (pSprite[2] + CaveSpriteVisibleXOffset) & 0x03FF; +#endif + if (x >= 320) { + if (x + xs <= 0x0400) { + continue; + } + } + +#if 0 + y = (pSprite[3] + nCaveExtraYOffset) & 0x03FF; +#else + y = pSprite[3] & 0x03FF; +#endif + if (y >= 240) { + if (y + ys <= 0x0400) { + continue; + } + } + + // Sprite is both active and onscreen, so add it to the buffer + + word = pSprite[0]; + + nPriority = (word >> 4) & 0x03; + if (nLastSprite[nPriority] == -1) { + nFirstSprite[nPriority] = z; + } + nLastSprite[nPriority] = z; + + pBuffer->priority = 8 >> nPriority; + + pBuffer->flip = (word >> 2) & 0x03; + pBuffer->palette = word & 0x3F00; + + pBuffer->address = pSprite[1] | ((word & 3) << 16); + + pBuffer->x = x; + pBuffer->y = y; + + pBuffer->xsize = xs; + pBuffer->ysize = ys; + + pBuffer++; + z++; + } + + return 0; +} + +// Normal sprite format (zooming) +static INT32 CaveSpriteBuffer_ZoomA() +{ + UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14)); + CaveSprite* pBuffer = pSpriteList; + INT32 nPriority; + + nFirstSprite[0] = 0x00010000; + nFirstSprite[1] = 0x00010000; + nFirstSprite[2] = 0x00010000; + nFirstSprite[3] = 0x00010000; + + nLastSprite[0] = -1; + nLastSprite[1] = -1; + nLastSprite[2] = -1; + nLastSprite[3] = -1; + + INT16 word; + INT32 x, y, xs, ys; + + for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) { + + word = pSprite[6]; + + xs = (word >> 4) & 0x01F0; + ys = (word << 4) & 0x01F0; + if (ys == 0 || xs == 0) { + continue; + } + + word = pSprite[2]; + + nPriority = (word >> 4) & 0x03; + + x = ((pSprite[0] >> 6) + CaveSpriteVisibleXOffset) & 0x03FF; +#if 0 + y = ((pSprite[1] >> 6) + nCaveExtraYOffset) & 0x03FF; +#else + y = (pSprite[1] >> 6) & 0x03FF; +#endif + + if (pSprite[4] <= 0x0100 && pSprite[5] <= 0x0100) { + if (x >= 320) { + if (x + xs <= 0x0400) { + continue; + } + } + if (y >= 240) { + if (y + ys <= 0x0400) { + continue; + } + } + } + + // Sprite is active and most likely on screen, so add it to the buffer + + if (nLastSprite[nPriority] == -1) { + nFirstSprite[nPriority] = z; + } + nLastSprite[nPriority] = z; + + pBuffer->priority = 8 >> nPriority; + + pBuffer->xzoom = pSprite[4]; + pBuffer->yzoom = pSprite[5]; + + pBuffer->xsize = xs; + pBuffer->ysize = ys; + + pBuffer->x = x; + pBuffer->y = y; + + pBuffer->flip = (word >> 2) & 0x03; + pBuffer->palette = word & 0x3F00; + + pBuffer->address = pSprite[3] | ((word & 3) << 16); + + pBuffer++; + z++; + } + + return 0; +} + +// Normal sprite format (zooming, alternate position handling) +static INT32 CaveSpriteBuffer_ZoomB() +{ + UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14)); + CaveSprite* pBuffer = pSpriteList; + INT32 nPriority; + + nFirstSprite[0] = 0x00010000; + nFirstSprite[1] = 0x00010000; + nFirstSprite[2] = 0x00010000; + nFirstSprite[3] = 0x00010000; + + nLastSprite[0] = -1; + nLastSprite[1] = -1; + nLastSprite[2] = -1; + nLastSprite[3] = -1; + + INT16 word; + INT32 x, y, xs, ys; + + for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) { + + word = pSprite[6]; + + xs = (word >> 4) & 0x01F0; + ys = (word << 4) & 0x01F0; + if (ys == 0 || xs == 0) { + continue; + } + + word = pSprite[2]; + + nPriority = (word >> 4) & 0x03; + +#if 0 + x = (pSprite[0] + nCaveExtraXOffset) & 0x03FF; +# else + x = (pSprite[0] + CaveSpriteVisibleXOffset) & 0x03FF; +#endif +#if 0 + y = (pSprite[1] + nCaveExtraYOffset) & 0x03FF; +#else + y = pSprite[1] & 0x03FF; +#endif + + if (pSprite[4] <= 0x0100 && pSprite[5] <= 0x0100) { + if (x >= nCaveXSize) { + if (x + xs <= 0x0400) { + continue; + } + } + if (y >= nCaveYSize) { + if (y + ys <= 0x0400) { + continue; + } + } + } + + // Sprite is active and most likely on screen, so add it to the buffer + + if (nLastSprite[nPriority] == -1) { + nFirstSprite[nPriority] = z; + } + nLastSprite[nPriority] = z; + + pBuffer->priority = 8 >> nPriority; + + pBuffer->xzoom = pSprite[4]; + pBuffer->yzoom = pSprite[5]; + + pBuffer->xsize = xs; + pBuffer->ysize = ys; + + pBuffer->x = x; + pBuffer->y = y; + + pBuffer->flip = (word >> 2) & 0x03; + pBuffer->palette = word & 0x3F00; + + pBuffer->address = pSprite[3] | ((word & 3) << 16); + + pBuffer++; + z++; + } + + return 0; +} + +// Power Instinct 2 sprite format (no zooming) +static INT32 CaveSpriteBuffer_PowerInstinct() +{ + UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14)); + CaveSprite* pBuffer = pSpriteList; + INT32 nPriority; + + nFirstSprite[0] = 0x00010000; + nFirstSprite[1] = 0x00010000; + nFirstSprite[2] = 0x00010000; + nFirstSprite[3] = 0x00010000; + + nLastSprite[0] = -1; + nLastSprite[1] = -1; + nLastSprite[2] = -1; + nLastSprite[3] = -1; + + INT16 word; + INT32 x, y, xs, ys; + + for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) { + + word = pSprite[4]; + + xs = (word >> 4) & 0x01F0; + ys = (word << 4) & 0x01F0; + if (ys == 0 || xs == 0) { + continue; + } + + x = (pSprite[2] + nCaveExtraXOffset) & 0x03FF; + if (x >= 320) { + if (x + xs <= 0x0400) { + continue; + } + } + + y = (pSprite[3] + nCaveExtraYOffset) & 0x03FF; + if (y >= 240) { + if (y + ys <= 0x0400) { + continue; + } + } + + // Sprite is both active and onscreen, so add it to the buffer + + word = pSprite[0]; + + nPriority = ((word >> 4) & 0x01) | 2; + if (nLastSprite[nPriority] == -1) { + nFirstSprite[nPriority] = z; + } + nLastSprite[nPriority] = z; + + pBuffer->priority = 8 >> nPriority; + + pBuffer->flip = (word >> 2) & 0x03; + pBuffer->palette = ((word >> 4) & 0x03F0) + ((word << 5) & 0xC00); + + pBuffer->address = pSprite[1] | ((word & 3) << 16); + + pBuffer->x = x; + pBuffer->y = y; + + pBuffer->xsize = xs; + pBuffer->ysize = ys; + + pBuffer++; + z++; + } + + return 0; +} + +void CaveSpriteExit() +{ + if (pSpriteList) { + free(pSpriteList); + pSpriteList = NULL; + } + + if (pZBuffer) { + free(pZBuffer); + pZBuffer = NULL; + } + + CaveSpriteVisibleXOffset = 0; + + return; +} + +INT32 CaveSpriteInit(INT32 nType, INT32 nROMSize) +{ + if (pSpriteList) { + free(pSpriteList); + } + pSpriteList = (CaveSprite*)malloc(0x0401 * sizeof(CaveSprite)); + if (pSpriteList == NULL) { + CaveSpriteExit(); + return 1; + } + + for (INT32 i = 0; i < 0x0400; i++) { + pSpriteList[i].xzoom = 0x0100; + pSpriteList[i].yzoom = 0x0100; + } + for (INT32 i = 0; i < 4; i++) { + nFirstSprite[i] = 0x00010000; + nLastSprite[i] = -1; + } + + if (pZBuffer) { + free(pZBuffer); + } + pZBuffer = (UINT16*)malloc(nCaveXSize * nCaveYSize * sizeof(UINT16)); + if (pZBuffer == NULL) { + CaveSpriteExit(); + return 1; + } + + memset(pZBuffer, 0, nCaveXSize * nCaveYSize * sizeof(UINT16)); + nZOffset = 0; + + for (nSpriteAddressMask = 1; nSpriteAddressMask < nROMSize; nSpriteAddressMask <<= 1) {} + nSpriteAddressMask--; + + switch (nType) { + case 0: + CaveSpriteBuffer = &CaveSpriteBuffer_NoZoom; + break; + case 1: + CaveSpriteBuffer = &CaveSpriteBuffer_ZoomA; + break; + case 2: + CaveSpriteBuffer = &CaveSpriteBuffer_ZoomB; + break; + case 3: + CaveSpriteBuffer = &CaveSpriteBuffer_PowerInstinct; + break; + default: + CaveSpriteExit(); + return 1; + } + + nCaveSpriteBank = 0; + nCaveSpriteBankDelay = 0; + + RenderSprite = RenderSprite_ROT0[(nCaveXSize == 320) ? 0 : 1]; + + return 0; +} diff --git a/src/burn/drivers/cave/cave_sprite_render.h b/src/burn/drivers/cave/cave_sprite_render.h new file mode 100644 index 00000000..3a7c944d --- /dev/null +++ b/src/burn/drivers/cave/cave_sprite_render.h @@ -0,0 +1,281 @@ +// Create a unique name for each of the functions +#define FN(a,b,c,d,e,f,g) RenderSprite ## a ## _ ## b ## _ROT ## c ## d ## e ## _CLIPX ## f ## g +#define FUNCTIONNAME(a,b,c,d,e,f,g) FN(a,b,c,d,e,f,g) + +#if ROT == 0 + #define ADVANCEWORD pPixel += ((BPP >> 3) * 16) + #define ADVANCEROW pRow += ((BPP >> 3) * XSIZE) +#else + #error unsupported rotation angle specified +#endif + +#if EIGHTBIT == 0 + #define DEPTH _16 +#elif EIGHTBIT == 1 + #define DEPTH _256 +#else + #error illegal eightbit value +#endif + +#define TESTCOLOUR(x) x + +#if ZBUFFER == 0 + #define ZBUF _NOZBUFFER + #define ADVANCEZWORD + #define ADVANCEZROW + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) +#elif ZBUFFER == 1 + #define ZBUF _RZBUFFER + #define ADVANCEZWORD pZPixel += 16 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) (pZPixel[a] <= nZPos) + #define WRITEZBUF(a) +#elif ZBUFFER == 2 + #define ZBUF _WZBUFFER + #define ADVANCEZWORD pZPixel += 16 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) pZPixel[a] = nZPos +#elif ZBUFFER == 3 + #define ZBUF _RWZBUFFER + #define ADVANCEZWORD pZPixel += 16 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) (pZPixel[a] <= nZPos) + #define WRITEZBUF(a) pZPixel[a] = nZPos +#else + #error unsupported zbuffer mode specified. +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + *((UINT16*)(pPixel + a * 2)) = (UINT16)pSpritePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + UINT32 nRGB = pSpritePalette[b]; \ + pPixel[a * 3 + 0] = (UINT8)nRGB; \ + pPixel[a * 3 + 1] = (UINT8)(nRGB >> 8); \ + pPixel[a * 3 + 2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + *((UINT32*)(pPixel + a * 4)) = (UINT32)pSpritePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +#if XFLIP == 0 + #define FLIP _NOFLIP +#elif XFLIP == 1 + #define FLIP _FLIPX +#else + #error illegal XFLIP value +#endif + +#if ZOOM == 0 + #define ZOOMMODE _NOZOOM +#elif ZOOM == 1 + #define ZOOMMODE _ZOOMXY +#else + #error unsupported rowscroll mode specified. +#endif + +#if XFLIP == 0 + #define OFFSET(a) a + #define CLIP(a,b) if (nColumn >= (XSIZE - a)) { continue; } \ + if (nXPos >= (0 - a)) { b } +#else + #define OFFSET(a) (15 - a) + #define CLIP(a,b) if (nColumn >= (0 - a) && nColumn < (XSIZE - a)) { b } +#endif + +#if EIGHTBIT == 0 + #define PLOT8_CLIP(x) \ + CLIP(OFFSET((x + 0)), PLOTPIXEL(OFFSET((x + 0)), nColour & 0x0F)); \ + nColour >>= 4; \ + CLIP(OFFSET((x + 1)), PLOTPIXEL(OFFSET((x + 1)), nColour & 0x0F)); \ + \ + nColour >>= 4; \ + CLIP(OFFSET((x + 2)), PLOTPIXEL(OFFSET((x + 2)), nColour & 0x0F)); \ + nColour >>= 4; \ + CLIP(OFFSET((x + 3)), PLOTPIXEL(OFFSET((x + 3)), nColour & 0x0F)); \ + \ + nColour >>= 4; \ + CLIP(OFFSET((x + 4)), PLOTPIXEL(OFFSET((x + 4)), nColour & 0x0F)); \ + nColour >>= 4; \ + CLIP(OFFSET((x + 5)), PLOTPIXEL(OFFSET((x + 5)), nColour & 0x0F)); \ + \ + nColour >>= 4; \ + CLIP(OFFSET((x + 6)), PLOTPIXEL(OFFSET((x + 6)), nColour & 0x0F)); \ + nColour >>= 4; \ + CLIP(OFFSET((x + 7)), PLOTPIXEL(OFFSET((x + 7)), nColour & 0x0F)); + + #define PLOT8_NOCLIP(x) \ + PLOTPIXEL(OFFSET((x + 0)), nColour & 0x0F); \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 1)), nColour & 0x0F); \ + \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 2)), nColour & 0x0F); \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 3)), nColour & 0x0F); \ + \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 4)), nColour & 0x0F); \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 5)), nColour & 0x0F); \ + \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 6)), nColour & 0x0F); \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET((x + 7)), nColour & 0x0F); +#else + #define PLOT4_CLIP(x) \ + CLIP(OFFSET((x + 0)), PLOTPIXEL(OFFSET((x + 0)), nColour & 0xFF)); \ + nColour >>= 8; \ + CLIP(OFFSET((x + 1)), PLOTPIXEL(OFFSET((x + 1)), nColour & 0xFF)); \ + nColour >>= 8; \ + \ + CLIP(OFFSET((x + 2)), PLOTPIXEL(OFFSET((x + 2)), nColour & 0xFF)); \ + nColour >>= 8; \ + CLIP(OFFSET((x + 3)), PLOTPIXEL(OFFSET((x + 3)), nColour & 0xFF)); + + #define PLOT4_NOCLIP(x) \ + PLOTPIXEL(OFFSET((x + 0)), nColour & 0xFF); \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET((x + 1)), nColour & 0xFF); \ + nColour >>= 8; \ + \ + PLOTPIXEL(OFFSET((x + 2)), nColour & 0xFF); \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET((x + 3)), nColour & 0xFF); +#endif + +static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,ZOOMMODE,ZBUF,DEPTH)() +{ +// Create an empty function if unsupported features are requested +#if ROT == 0 + + INT32 x, nColumn; + INT32 nColour; + + #if ZBUFFER == 0 + for (nSpriteRow = 0; nSpriteRow < nYSize; ADVANCEROW, nSpriteRow++, pSpriteData += nSpriteRowSize) { + #else + for (nSpriteRow = 0; nSpriteRow < nYSize; ADVANCEROW, ADVANCEZROW, nSpriteRow++, pSpriteData += nSpriteRowSize) { + #endif + nColumn = nXPos; + + #if ZBUFFER == 0 + #if XFLIP == 0 + for (x = (0 << EIGHTBIT), pPixel = pRow; x < nXSize; x += (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD) { + #else + for (x = nXSize - (2 << EIGHTBIT), pPixel = pRow; x >= 0; x -= (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD) { + #endif + #else + #if XFLIP == 0 + for (x = 0, pPixel = pRow, pZPixel = pZRow; x < nXSize; x += (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD, ADVANCEZWORD) { + #else + for (x = nXSize - (2 << EIGHTBIT), pPixel = pRow, pZPixel = pZRow; x >= 0; x -= (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD, ADVANCEZWORD) { + #endif + #endif + + #if EIGHTBIT == 0 + if (nColumn >= 0 && nColumn < (XSIZE - 16)) { + #if XFLIP == 0 + nColour = pSpriteData[x]; + PLOT8_NOCLIP(0); + nColour = pSpriteData[x + 1]; + PLOT8_NOCLIP(8); + #else + nColour = pSpriteData[x + 1]; + PLOT8_NOCLIP(8); + nColour = pSpriteData[x]; + PLOT8_NOCLIP(0); + #endif + } else { + #if XFLIP == 0 + nColour = pSpriteData[x]; + PLOT8_CLIP(0); + nColour = pSpriteData[x + 1]; + PLOT8_CLIP(8); + #else + nColour = pSpriteData[x + 1]; + PLOT8_CLIP(8); + nColour = pSpriteData[x]; + PLOT8_CLIP(0); + #endif + #else + if (nColumn >= 0 && nColumn < (XSIZE - 16)) { + #if XFLIP == 0 + nColour = pSpriteData[x]; + PLOT4_NOCLIP(0); + nColour = pSpriteData[x + 1]; + PLOT4_NOCLIP(4); + nColour = pSpriteData[x + 2]; + PLOT4_NOCLIP(8); + nColour = pSpriteData[x + 3]; + PLOT4_NOCLIP(12); + #else + nColour = pSpriteData[x + 3]; + PLOT4_NOCLIP(12); + nColour = pSpriteData[x + 2]; + PLOT4_NOCLIP(8); + nColour = pSpriteData[x + 1]; + PLOT4_NOCLIP(4); + nColour = pSpriteData[x]; + PLOT4_NOCLIP(0); + #endif + } else { + #if XFLIP == 0 + nColour = pSpriteData[x]; + PLOT4_CLIP(0); + nColour = pSpriteData[x + 1]; + PLOT4_CLIP(4); + nColour = pSpriteData[x + 2]; + PLOT4_CLIP(8); + nColour = pSpriteData[x + 3]; + PLOT4_CLIP(12); + #else + nColour = pSpriteData[x + 3]; + PLOT4_CLIP(12); + nColour = pSpriteData[x + 2]; + PLOT4_CLIP(8); + nColour = pSpriteData[x + 1]; + PLOT4_CLIP(4); + nColour = pSpriteData[x]; + PLOT4_CLIP(0); + #endif + #endif + } + } + } +#endif +} + +#undef PLOT4_CLIP +#undef PLOT4_NOCLIP +#undef PLOT8_CLIP +#undef PLOT8_NOCLIP +#undef OFFSET +#undef FLIP +#undef PLOTPIXEL +#undef CLIP +#undef TESTCOLOUR +#undef ADVANCEZROW +#undef ADVANCEZWORD +#undef ADVANCEROW +#undef ADVANCEWORD +#undef TESTZBUF +#undef WRITEZBUF +#undef ZBUF +#undef ZOOMMODE +#undef DEPTH +#undef FUNCTIONNAME +#undef FN + diff --git a/src/burn/drivers/cave/cave_sprite_render_zoom.h b/src/burn/drivers/cave/cave_sprite_render_zoom.h new file mode 100644 index 00000000..52c3e949 --- /dev/null +++ b/src/burn/drivers/cave/cave_sprite_render_zoom.h @@ -0,0 +1,182 @@ +// Create a unique name for each of the functions +#define FN(a,b,c,d,e,f,g) RenderSprite ## a ## _ ## b ## _ROT ## c ## d ## e ## _NOCLIP ## f ## g +#define FUNCTIONNAME(a,b,c,d,e,f,g) FN(a,b,c,d,e,f,g) + +#if ROT == 0 + #define ADVANCECOLUMN pPixel += (BPP >> 3) + #define ADVANCEROW pRow += ((BPP >> 3) * XSIZE) +#else + #error unsupported rotation angle specified +#endif + +#if EIGHTBIT == 0 + #define DEPTH _16 +#elif EIGHTBIT == 1 + #define DEPTH _256 +#else + #error illegal eightbit value +#endif + +#define TESTCOLOUR(x) x + +#if ZBUFFER == 0 + #define ZBUF _NOZBUFFER + #define ADVANCEZCOLUMN + #define ADVANCEZROW + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) +#elif ZBUFFER == 1 + #define ZBUF _RZBUFFER + #define ADVANCEZCOLUMN pZPixel += 1 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) (pZPixel[a] <= nZPos) + #define WRITEZBUF(a) +#elif ZBUFFER == 2 + #define ZBUF _WZBUFFER + #define ADVANCEZCOLUMN pZPixel += 1 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) pZPixel[a] = nZPos +#elif ZBUFFER == 3 + #define ZBUF _RWZBUFFER + #define ADVANCEZCOLUMN pZPixel += 1 + #define ADVANCEZROW pZRow += XSIZE + #define TESTZBUF(a) (pZPixel[a] <= nZPos) + #define WRITEZBUF(a) pZPixel[a] = nZPos +#else + #error unsupported zbuffer mode specified. +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + *((UINT16*)(pPixel + a * 2)) = (UINT16)pSpritePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + UINT32 nRGB = pSpritePalette[b]; \ + pPixel[a * 3 + 0] = (UINT8)nRGB; \ + pPixel[a * 3 + 1] = (UINT8)(nRGB >> 8); \ + pPixel[a * 3 + 2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + *((UINT32*)(pPixel + a * 4)) = (UINT32)pSpritePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +#if XFLIP == 0 + #define FLIP _NOFLIP +#elif XFLIP == 1 + #define FLIP _FLIPX +#else + #error illegal XFLIP value +#endif + +#if ZOOM == 0 + #define ZOOMMODE _NOZOOM +#elif ZOOM == 1 + #define ZOOMMODE _ZOOMOUT +#elif ZOOM == 2 + #define ZOOMMODE _ZOOMIN +#else + #error unsupported zoom mode specified. +#endif + +static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,ZOOMMODE,ZBUF,DEPTH)() +{ +// Create an empty function if unsupported features are requested +#if ROT == 0 && XFLIP == 0 && EIGHTBIT == 1 + + INT32 nSpriteColumn; + + INT32 nSpriteXOffset2; + + #if ZOOM == 2 + INT32 nPrevSpriteXOffset; + INT32 nPrevSpriteXOffsetStart = nSpriteXOffset & 0xFFFF0000; + INT32 nPrevSpriteYOffset = nSpriteYOffset & 0xFFFF0000; + + if (nPrevSpriteXOffsetStart == 0) { + nPrevSpriteXOffsetStart = 0xFEDC1234; + } + + if (nPrevSpriteYOffset == 0) { + nPrevSpriteYOffset = 0xFEDC1234; + } + #endif + + UINT8* pSpriteRowData = (UINT8*)pSpriteData; + + for (nSpriteRow = nYSize; nSpriteRow > 0; nSpriteRow -= 0x00010000, nSpriteYOffset += nSpriteYZoomSize) { + + #if ZOOM == 2 + if ((nSpriteYOffset & 0xFFFF0000) == (nPrevSpriteYOffset & 0xFFFF0000)) { + + ADVANCEROW; + #if ZBUFFER != 0 + ADVANCEZROW; + #endif + + continue; + } + nPrevSpriteYOffset = nSpriteYOffset; + nPrevSpriteXOffset = nPrevSpriteXOffsetStart; + #endif + pSpriteRowData = ((UINT8*)pSpriteData) + (nSpriteYOffset >> 16) * nSpriteRowSize; + + nSpriteXOffset2 = nSpriteXOffset; + + #if ZBUFFER != 0 + pZPixel = pZRow; + #endif + + for (nSpriteColumn = nXSize, pPixel = pRow; nSpriteColumn > 0; nSpriteColumn -= 0x00010000, nSpriteXOffset2 += nSpriteXZoomSize) { + + #if ZOOM == 2 + if ((nSpriteXOffset2 & 0xFFFF0000) != (nPrevSpriteXOffset & 0xFFFF0000)) { + + nPrevSpriteXOffset = nSpriteXOffset2; + #endif + PLOTPIXEL(0, pSpriteRowData[nSpriteXOffset2 >> 16]); + + #if ZOOM == 2 + } + #endif + + ADVANCECOLUMN; + #if ZBUFFER != 0 + ADVANCEZCOLUMN; + #endif + + } + + ADVANCEROW; + #if ZBUFFER != 0 + ADVANCEZROW; + #endif + } + +#endif +} + +#undef OFFSET +#undef FLIP +#undef PLOTPIXEL +#undef TESTCOLOUR +#undef ADVANCEZROW +#undef ADVANCEZCOLUMN +#undef ADVANCEROW +#undef ADVANCECOLUMN +#undef TESTZBUF +#undef WRITEZBUF +#undef ZBUF +#undef ZOOMMODE +#undef DEPTH +#undef FUNCTIONNAME +#undef FN + diff --git a/src/burn/drivers/cave/cave_tile.cpp b/src/burn/drivers/cave/cave_tile.cpp new file mode 100644 index 00000000..b1a4d3b9 --- /dev/null +++ b/src/burn/drivers/cave/cave_tile.cpp @@ -0,0 +1,981 @@ +// Cave hardware tilemaps + +#include "cave.h" + +struct CaveTile { INT16 x; INT16 y; UINT32 tile; }; + +static CaveTile* CaveTileQueueMemory[4] = { NULL, }; +static CaveTile* CaveTileQueue[4][4]; + +UINT32 CaveTileReg[4][3]; + +UINT8* CaveTileROM[4] = { NULL, }; +UINT8* CaveTileRAM[4] = { NULL, }; + +static INT8* CaveTileAttrib[4] = { NULL, }; + +INT32 nCaveTileBank = 0; + +// Used when row-select mode is enabled +static INT32* pRowScroll[4] = { NULL, }; +static INT32* pRowSelect[4] = { NULL, }; + +static INT32 nLayerXOffset[4]; +static INT32 nLayerYOffset; +static INT32 nPaletteOffset[4]; +static INT32 nPaletteSize[4]; + +static INT32 CaveTileCount[4]; +static INT32 CaveTileMax[4]; +static INT32 nTileMask[4]; + +static UINT8* pTile; +static UINT32* pTileData; +static UINT32* pTilePalette; +static INT32* pTileRowInfo; + +typedef void (*RenderTileFunction)(); +static RenderTileFunction* RenderTile; + +static INT32 nTileXPos, nTileYPos, nRowOffset; + +static INT32 nClipX8, nClipX16; +static INT32 nClipY8, nClipY16; + +// Include the tile rendering functions +#include "cave_tile_func.h" + +static void CaveQueue8x8Layer_Normal(INT32 nLayer) +{ + INT32 x, y; + INT32 bx, by, cx, cy, mx; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber; + + UINT8* pTileRAM = CaveTileRAM[nLayer]; + + UINT32 nTileOffset = 0; + if (nCaveTileBank) { + nTileOffset = 0x040000; + } + + mx = (nCaveXSize >> 3) << 2; + + bx = CaveTileReg[nLayer][0] - 0x0A + nLayerXOffset[nLayer]; + bx &= 0x01FF; + cx = (bx >> 3) << 2; + bx &= 0x0007; + + by = CaveTileReg[nLayer][1] + nLayerYOffset; + by &= 0x01FF; + cy = (by >> 3) << 8; + by &= 0x0007; + + for (y = 0; y < (31 << 8); y += (1 << 8)) { + nTileRow = (cy + y) & (0x3F << 8); + nTileYPos = (y >> 5) - by; + + if (nTileYPos <= -8 || nTileYPos >= nCaveYSize) { + continue; + } + + for (x = mx; x >= 0; x -= (1 << 2)) { + nTileColumn = (cx + x) & (0x3F << 2); + nTileNumber = *((UINT16*)(pTileRAM + 0x4000 + nTileRow + nTileColumn)) << 16; + nTileNumber |= *((UINT16*)(pTileRAM + 0x4002 + nTileRow + nTileColumn)); + + nTileNumber |= nTileOffset; + + if (CaveTileAttrib[nLayer][nTileNumber & nTileMask[nLayer]]) { + continue; + } + + nTileXPos = (x << 1) - bx; + + if (nTileXPos <= -8 || nTileXPos >= nCaveXSize) { + continue; + } + + CaveTileQueue[nLayer][nTileNumber >> 30]->x = nTileXPos; + CaveTileQueue[nLayer][nTileNumber >> 30]->y = nTileYPos; + CaveTileQueue[nLayer][nTileNumber >> 30]->tile = nTileNumber; + CaveTileQueue[nLayer][nTileNumber >> 30]++; + } + } + + return; +} + +static void Cave8x8Layer_Normal(INT32 nLayer, UINT32 nPriority) +{ + UINT32 nTileNumber; + + UINT32* pPalette = CavePalette + nPaletteOffset[nLayer]; + UINT32 nPaletteMask = 0x3F000000; + if (nPaletteSize[nLayer] == 6) { + nPaletteMask = 0x0F000000; + } + INT32 nPaletteShift = 24 - nPaletteSize[nLayer]; + + CaveTile* TileQueue = CaveTileQueue[nLayer][nPriority]; + + while ((nTileXPos = TileQueue->x) < 9999) { + nTileYPos = TileQueue->y; + nTileNumber = TileQueue->tile; + pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift); + nTileNumber &= nTileMask[nLayer]; + + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + + pTileData = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6)); + + if (nTileYPos < 0 || nTileYPos > nClipY8 || nTileXPos < 0 || nTileXPos > nClipX8) { + RenderTile[1](); + } else { + RenderTile[0](); + } + + TileQueue++; + } + + return; +} + +static void Cave8x8Layer_RowScroll(INT32 nLayer, UINT32 nPriority) +{ + INT32 x, y; + INT32 bx, by, cy; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber; + + UINT8* pTileRAM = CaveTileRAM[nLayer]; + UINT32* pPalette = CavePalette + nPaletteOffset[nLayer]; + INT32 nPaletteShift = 24 - nPaletteSize[nLayer]; + + INT32* rowscroll = pRowScroll[nLayer]; + + INT32 count = CaveTileCount[nLayer]; + + if (count >= (64 * 31)) { + return; + } + + UINT32 nTileOffset = 0; + if (nCaveTileBank) { + nTileOffset = 0x040000; + } + + bx = CaveTileReg[nLayer][0] - 0x0A + nLayerXOffset[nLayer]; + bx &= 0x01FF; + + by = CaveTileReg[nLayer][1] + nLayerYOffset; + by &= 0x01FF; + cy = (by >> 3) << 8; + by &= 0x0007; + + if (nPriority == 0) { + INT32 dy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset; + + for (y = 0; y < nCaveYSize; y++) { + rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((dy + y) & 0x01FF) << 2))) + bx; + } + } + + for (y = 0; y < (31 << 8); y += (1 << 8)) { + nTileYPos = (y >> 5) - by; + + nTileRow = (cy + y) & (0x3F << 8); + pTileRowInfo = rowscroll + nTileYPos; + + for (x = 0; x < (64 << 2); x += (1 << 2)) { + nTileColumn = x & (0x3F << 2); + nTileNumber = *((UINT16*)(pTileRAM + 0x4000 + nTileRow + nTileColumn)) << 16; + if ((nTileNumber >> 30) != nPriority) { + continue; + } + nTileNumber |= *((UINT16*)(pTileRAM + 0x4002 + nTileRow + nTileColumn)); + pTilePalette = pPalette + ((nTileNumber & 0x3F000000) >> nPaletteShift); + + nTileNumber |= nTileOffset; + nTileNumber &= nTileMask[nLayer]; + + count++; + + if (nTileYPos <= -8 || nTileYPos >= nCaveYSize) { + continue; + } + + if (*((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber))) { + continue; + } + + nTileXPos = (x << 1); + + pTile = pBurnDraw + (nTileYPos * nBurnPitch); + + pTileData = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6)); + + if (nTileYPos < 0 || nTileYPos > nClipY8 || nTileXPos < 0 || nTileXPos > nClipX8) { + RenderTile[3](); + } else { + RenderTile[2](); + } + } + } + + if (count >= (64 * 31)) { + CaveTileMax[0] -= 0x0123; + CaveTileMax[1] -= 0x0123; + CaveTileMax[2] -= 0x0123; + CaveTileMax[3] -= 0x0123; + } + CaveTileCount[nLayer] = count; + + return; +} + +static void CaveQueue16x16Layer_Normal(INT32 nLayer) +{ + INT32 x, y; + INT32 bx, by, cx, cy, mx; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber; + + UINT8* pTileRAM = CaveTileRAM[nLayer]; + + mx = (nCaveXSize >> 4) << 2; + + bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer]; + bx &= 0x01FF; + cx = (bx >> 4) << 2; + bx &= 0x000F; + + by = CaveTileReg[nLayer][1] + nLayerYOffset; + by &= 0x01FF; + cy = (by >> 4) << 7; + by &= 0x000F; + + for (y = 0; y < (16 << 7); y += (1 << 7)) { + nTileRow = (cy + y) & (0x1F << 7); + nTileYPos = (y >> 3) - by; + + if (nTileYPos <= -16 || nTileYPos >= nCaveYSize) { + continue; + } + + for (x = mx; x >= 0; x -= (1 << 2)) { + nTileColumn = (cx + x) & (0x1F << 2); + nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16; + nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn)); + + if (*((UINT32*)(CaveTileAttrib[nLayer] + ((nTileNumber << 2) & nTileMask[nLayer]))) == 0x01010101) { + continue; + } + + nTileXPos = (x << 2) - bx; + + if (nTileXPos <= -16 || nTileXPos >= nCaveXSize) { + continue; + } + + CaveTileQueue[nLayer][nTileNumber >> 30]->x = nTileXPos; + CaveTileQueue[nLayer][nTileNumber >> 30]->y = nTileYPos; + CaveTileQueue[nLayer][nTileNumber >> 30]->tile = nTileNumber; + CaveTileQueue[nLayer][nTileNumber >> 30]++; + } + } + + return; +} + +static void Cave16x16Layer_Normal(INT32 nLayer, UINT32 nPriority) +{ + UINT32 nTileNumber, nAttrib; + UINT32* pTileStart; + + UINT32* pPalette = CavePalette + nPaletteOffset[nLayer]; + INT32 nPaletteShift = 24 - nPaletteSize[nLayer]; + UINT32 nPaletteMask = 0x3F000000; + if (nPaletteSize[nLayer] == 6) { + nPaletteMask = 0x0F000000; + } + + CaveTile* TileQueue = CaveTileQueue[nLayer][nPriority]; + + while ((nTileXPos = TileQueue->x) < 9999) { + nTileYPos = TileQueue->y; + nTileNumber = TileQueue->tile; + pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift); + nTileNumber <<= 2; + nTileNumber &= nTileMask[nLayer]; + + nAttrib = *((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber)); + + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + + pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6)); + + if (nTileXPos < 0 || nTileXPos > nClipX16 || nTileYPos < 0 || nTileYPos > nClipY16) { + + if ((nAttrib & 0x000000FF) == 0) { + pTileData = pTileStart; + if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) { + if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[0](); + } else { + RenderTile[1](); + } + } + } + + nTileXPos += 8; + pTile += 8 * nBurnBpp; + if ((nAttrib & 0x0000FF00) == 0) { + if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 16; + if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[0](); + } else{ + RenderTile[1](); + } + } + } + + nTileXPos -= 8; + nTileYPos += 8; + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + if ((nAttrib & 0x00FF0000) == 0) { + if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 32; + if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[0](); + } else { + RenderTile[1](); + } + } + } + + nTileXPos += 8; + pTile += 8 * nBurnBpp; + if ((nAttrib & 0xFF000000) == 0) { + if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 48; + if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[0](); + } else { + RenderTile[1](); + } + } + } + + } else { + if ((nAttrib & 0x000000FF) == 0) { + pTileData = pTileStart; + RenderTile[0](); + } + nTileXPos += 8; + pTile += 8 * nBurnBpp; + if ((nAttrib & 0x0000FF00) == 0) { + pTileData = pTileStart + 16; + RenderTile[0](); + } + nTileXPos -= 8; + nTileYPos += 8; + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + if ((nAttrib & 0x00FF0000) == 0) { + pTileData = pTileStart + 32; + RenderTile[0](); + } + nTileXPos += 8; + pTile += 8 * nBurnBpp; + if ((nAttrib & 0xFF000000) == 0) { + pTileData = pTileStart + 48; + RenderTile[0](); + } + } + + TileQueue++; + } + + return; +} + +static void Cave16x16Layer_RowScroll(INT32 nLayer, UINT32 nPriority) +{ + INT32 x, y; + INT32 bx, by, cy; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber, nAttrib; + UINT32* pTileStart; + + UINT8* pTileRAM = CaveTileRAM[nLayer]; + UINT32* pPalette = CavePalette + nPaletteOffset[nLayer]; + INT32 nPaletteShift = 24 - nPaletteSize[nLayer]; + UINT32 nPaletteMask = 0x3F000000; + if (nPaletteSize[nLayer] == 6) { + nPaletteMask = 0x0F000000; + } + + INT32* rowscroll = pRowScroll[nLayer]; + + INT32 count = CaveTileCount[nLayer]; + + if (count >= (32 * 16)) { + return; + } + + bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer]; + bx &= 0x01FF; + + by = CaveTileReg[nLayer][1] + nLayerYOffset; + by &= 0x01FF; + cy = (by >> 4) << 7; + by &= 0x000F; + + if (nPriority == 0) { + INT32 dy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset; + + for (y = 0; y < nCaveYSize; y++) { + rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((dy + y) & 0x01FF) << 2))) + bx; + } + } + + for (y = 0; y < (16 << 7); y += (1 << 7)) { + nTileRow = (cy + y) & (0x1F << 7); + nTileYPos = (y >> 3) - by; + + pTileRowInfo = rowscroll + nTileYPos; + + for (x = 0; x < (32 << 2); x += (1 << 2)) { + nTileColumn = x & (0x1F << 2); + nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16; + if ((nTileNumber >> 30) != nPriority) { + continue; + } + nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn)); + pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift); + nTileNumber <<= 2; + nTileNumber &= nTileMask[nLayer]; + + count++; + + nAttrib = *((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber)); + if (nAttrib == 0x01010101) { + continue; + } + + nTileXPos = (x << 2); + + pTile = pBurnDraw + (nTileYPos * nBurnPitch); + + pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6)); + + if (nTileYPos < 0 || nTileYPos > nClipY16) { + if ((nAttrib & 0x000000FF) == 0) { + pTileData = pTileStart; + if (nTileYPos > -8 && nTileYPos < nCaveYSize) { + if (nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[2](); + } else { + RenderTile[3](); + } + } + } + nTileXPos += 8; + if ((nAttrib & 0x0000FF00) == 0) { + if (nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 16; + if (nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[2](); + } else { + RenderTile[3](); + } + } + } + nTileXPos -= 8; + nTileYPos += 8; + + pTileRowInfo += 8; + + pTile = pBurnDraw + (nTileYPos * nBurnPitch); + if ((nAttrib & 0x00FF0000) == 0) { + if (nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 32; + if (nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[2](); + } else { + RenderTile[3](); + } + } + } + nTileXPos += 8; + if ((nAttrib & 0xFF000000) == 0) { + if (nTileYPos > -8 && nTileYPos < nCaveYSize) { + pTileData = pTileStart + 48; + if (nTileYPos >= 0 && nTileYPos <= nClipY8) { + RenderTile[2](); + } else { + RenderTile[3](); + } + } + } + } else { + if ((nAttrib & 0x000000FF) == 0) { + pTileData = pTileStart; + RenderTile[2](); + } + nTileXPos += 8; + if ((nAttrib & 0x0000FF00) == 0) { + pTileData = pTileStart + 16; + RenderTile[2](); + } + nTileXPos -= 8; + nTileYPos += 8; + + pTileRowInfo += 8; + + pTile = pBurnDraw + (nTileYPos * nBurnPitch); + if ((nAttrib & 0x00FF0000) == 0) { + pTileData = pTileStart + 32; + RenderTile[2](); + } + nTileXPos += 8; + if ((nAttrib & 0xFF000000) == 0) { + pTileData = pTileStart + 48; + RenderTile[2](); + } + } + nTileYPos -= 8; + + pTileRowInfo -= 8; + } + } + + if (count >= (32 * 16)) { + CaveTileMax[0] -= 0x0123; + CaveTileMax[1] -= 0x0123; + CaveTileMax[2] -= 0x0123; + CaveTileMax[3] -= 0x0123; + } + CaveTileCount[nLayer] = count; + + return; +} + +static void Cave16x16Layer_RowSelect(INT32 nLayer, UINT32 nPriority) +{ + INT32 x, y, ry, rx; + INT32 bx, by, mx; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber; + UINT32* pTileStart; + + UINT8* pTileRAM = CaveTileRAM[nLayer]; + UINT32* pPalette = CavePalette + nPaletteOffset[nLayer]; + INT32 nPaletteShift = 24 - nPaletteSize[nLayer]; + UINT32 nPaletteMask = 0x3F000000; + if (nPaletteSize[nLayer] == 6) { + nPaletteMask = 0x0F000000; + } + + INT32* rowselect = pRowSelect[nLayer]; + INT32* rowscroll = pRowScroll[nLayer]; + + INT32 count = CaveTileCount[nLayer]; + + mx = nCaveXSize >> 4; + + if (count >= nCaveYSize * (mx + 1)) { + return; + } + + bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer]; + bx &= 0x01FF; + + by = CaveTileReg[nLayer][1] + nLayerYOffset; + by &= 0x01FF; + + if (nPriority == 0) { + INT32 cy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset; + + if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode + for (y = 0; y < nCaveYSize; y++) { + rowselect[y] = *((UINT16*)(pTileRAM + 0x1002 + (((cy + y) & 0x01FF) << 2))); + rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((cy + y) & 0x01FF) << 2))) + bx; + } + } else { + for (y = 0; y < nCaveYSize; y++) { + rowselect[y] = *((UINT16*)(pTileRAM + 0x1002 + (((cy + y) & 0x01FF) << 2))); + } + } + } + + for (y = 0; y < nCaveYSize; y++) { + ry = rowselect[y]; + nTileRow = ((ry >> 4) & 0x1F) << 7; + nTileYPos = y; + + if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode + rx = rowscroll[y]; + ry = (((ry & 8) << 1) + (ry & 7)) << 1; + + for (x = 0; x <= mx; x++) { + + nTileColumn = (((rx >> 4) + x) & 0x1F) << 2; + nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16; + if ((nTileNumber >> 30) != nPriority) { + continue; + } + nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn)); + pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift); + nTileNumber &= nTileMask[nLayer]; + + count++; + + if (((UINT32*)CaveTileAttrib[nLayer])[nTileNumber] == 0x01010101) { + continue; + } + + nTileXPos = (x << 4) - (rx & 15); + + if (nTileXPos <= -16 || nTileXPos >= nCaveXSize) { + continue; + } + + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + + pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 8)); + pTileStart += ry; + + pTileData = pTileStart; + if (nTileXPos >= 0 && nTileXPos <= nClipX8) { + RenderTile[4](); + } else { + RenderTile[5](); + } + nTileXPos += 8; + pTile += (nBurnBpp << 3); + pTileData = pTileStart + 16; + if (nTileXPos >= 0 && nTileXPos <= nClipX16) { + RenderTile[4](); + } else { + RenderTile[5](); + } + } + } else { + nTileXPos = - (bx & 15); + pTile = pBurnDraw + (nTileYPos * nBurnPitch) - ((bx & 15) * nBurnBpp); + + ry = (((ry & 8) << 1) + (ry & 7)) << 1; + + for (x = 0; x <= mx; x++) { + nTileColumn = (((bx >> 4) + x) & 0x1F) << 2; + nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16; + if ((nTileNumber >> 30) != nPriority) { + nTileXPos += 16; + pTile += (nBurnBpp << 4); + continue; + } + nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn)); + pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift); + nTileNumber &= nTileMask[nLayer]; + + count++; + + if (((UINT32*)CaveTileAttrib[nLayer])[nTileNumber] == 0x01010101) { + nTileXPos += 16; + pTile += (nBurnBpp << 4); + continue; + } + + pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 8)); + pTileStart += ry; + + pTileData = pTileStart; + + if (nTileXPos >= 0 && nTileXPos <= nClipX8) { + RenderTile[4](); + } else { + RenderTile[5](); + } + nTileXPos += 8; + pTile += (nBurnBpp << 3); + + pTileData = pTileStart + 16; + if (nTileXPos >= 0 && nTileXPos <= nClipX8) { + RenderTile[4](); + } else { + RenderTile[5](); + } + nTileXPos += 8; + pTile += (nBurnBpp << 3); + } + } + } + + if (count >= nCaveYSize * (mx + 1)) { + CaveTileMax[0] -= 0x0123; + CaveTileMax[1] -= 0x0123; + CaveTileMax[2] -= 0x0123; + CaveTileMax[3] -= 0x0123; + } + CaveTileCount[nLayer] = count; + + return; +} + +static void Cave16x16Layer(INT32 nLayer, UINT32 nPriority) +{ + if (CaveTileReg[nLayer][1] & 0x4000) { // Row-select mode + Cave16x16Layer_RowSelect(nLayer, nPriority); +// bprintf(PRINT_NORMAL, " Layer %d row-select mode enabled (16x16)\n", nLayer); + return; + } + + if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode + Cave16x16Layer_RowScroll(nLayer, nPriority); +// bprintf(PRINT_NORMAL, " Layer %d row-scroll mode enabled (16x16)\n", nLayer); + return; + } + + Cave16x16Layer_Normal(nLayer, nPriority); + + return; +} + +static void Cave8x8Layer(INT32 nLayer, UINT32 nPriority) +{ +#if 0 + if (CaveTileReg[nLayer][1] & 0x4000) { // Row-select mode + Cave8x8Layer_RowSelect(nLayer, nPriority); +// bprintf(PRINT_NORMAL, " Layer %d row-select mode enabled ( 8x 8)\n", nLayer); + return; + } +#else + if (CaveTileReg[nLayer][1] & 0x4000) { +// bprintf(PRINT_ERROR, " Layer %d row-select mode enabled ( 8x 8, UNSUPPORTED!)\n", nLayer); + } +#endif + + if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode + Cave8x8Layer_RowScroll(nLayer, nPriority); +// bprintf(PRINT_NORMAL, " Layer %d row-scroll mode enabled ( 8x 8)\n", nLayer); + return; + } + + Cave8x8Layer_Normal(nLayer, nPriority); + + return; +} + +INT32 CaveTileRender(INT32 nMode) +{ + UINT32 nPriority; + INT32 nLowPriority; + INT32 nLayer; + INT32 nOffset = 0; + + CaveTileCount[0] = CaveTileCount[1] = CaveTileCount[2] = CaveTileCount[3] = 0; + CaveTileMax[0] = CaveTileMax[1] = CaveTileMax[2] = CaveTileMax[3] = 0; + + nLayerYOffset = 0x12 - nCaveYOffset - nCaveExtraYOffset; + + for (nLayer = 0; nLayer < 4; nLayer++) { + + nLayerXOffset[nLayer] = nLayer + nOffset - nCaveXOffset - nCaveExtraXOffset; + + if ((CaveTileReg[nLayer][2] & 0x0010) == 0) { + + for (nPriority = 0; nPriority < 4; nPriority++) { + CaveTileQueue[nLayer][nPriority] = &CaveTileQueueMemory[nLayer][nPriority * 1536]; + } + if (nBurnLayer & (8 >> nLayer)) { + if (CaveTileReg[nLayer][1] & 0x2000) { + if (nMode && ((CaveTileReg[nLayer][0] | CaveTileReg[nLayer][1]) & 0x4000)) { + CaveTileMax[0] += 0x0123; + CaveTileMax[1] += 0x0123; + CaveTileMax[2] += 0x0123; + CaveTileMax[3] += 0x0123; + } else { + CaveQueue16x16Layer_Normal(nLayer); + } + } else { + if (nMode && (CaveTileReg[nLayer][0] & 0x4000)) { + CaveTileMax[0] += 0x0123; + CaveTileMax[1] += 0x0123; + CaveTileMax[2] += 0x0123; + CaveTileMax[3] += 0x0123; + } else { + CaveQueue8x8Layer_Normal(nLayer); + } + +// nOffset += 8; + } + } + + for (nPriority = 0; nPriority < 4; nPriority++) { + CaveTileQueue[nLayer][nPriority]->x = 9999; + CaveTileQueue[nLayer][nPriority] = &CaveTileQueueMemory[nLayer][nPriority * 1536]; + if (CaveTileQueue[nLayer][nPriority]->x < 9999) { + CaveTileMax[nPriority] += 0x123; + } + } + } + } + + nLowPriority = 0; + + for (nPriority = 0; nPriority < 4; nPriority++) { + + if (CaveTileMax[nPriority] || nPriority == 3) { + CaveSpriteRender(nLowPriority, nPriority); + nLowPriority = nPriority + 1; + } + + for (UINT32 i = 0; i < 4; i++) { + for (nLayer = 0; nLayer < 4; nLayer++) { + if ((CaveTileReg[nLayer][2] & 0x0003) == i) { + if ((CaveTileReg[nLayer][2] & 0x0010) || (nBurnLayer & (8 >> nLayer)) == 0) { + continue; + } + + if (CaveTileReg[nLayer][1] & 0x2000) { + if (nMode) { + Cave16x16Layer(nLayer, nPriority); + } else { + Cave16x16Layer_Normal(nLayer, nPriority); + } + } else { + if (nMode) { + Cave8x8Layer(nLayer, nPriority); + } else { + Cave8x8Layer_Normal(nLayer, nPriority); + } + } + } + } + } + } + + return 0; +} + +void CaveTileExit() +{ + for (INT32 nLayer = 0; nLayer < 4; nLayer++) { + if (CaveTileAttrib[nLayer]) { + free(CaveTileAttrib[nLayer]); + CaveTileAttrib[nLayer] = NULL; + } + + if (CaveTileQueueMemory[nLayer]) { + free(CaveTileQueueMemory[nLayer]); + CaveTileQueueMemory[nLayer] = NULL; + } + + if (pRowScroll[nLayer]) { + free(pRowScroll[nLayer]); + pRowScroll[nLayer] = NULL; + } + + if (pRowSelect[nLayer]) { + free(pRowSelect[nLayer]); + pRowSelect[nLayer] = NULL; + } + } + + nCaveXOffset = nCaveYOffset = 0; + nCaveRowModeOffset = 0; + nCaveExtraXOffset = nCaveExtraYOffset = 0; + + return; +} + +INT32 CaveTileInit() +{ + for (INT32 nLayer = 0; nLayer < 4; nLayer++) { + CaveTileReg[nLayer][0] = 0x0000; + CaveTileReg[nLayer][1] = 0x0000; + CaveTileReg[nLayer][2] = 0x0010; // Disable layer + } + + nCaveTileBank = 0; + + BurnDrvGetFullSize(&nCaveXSize, &nCaveYSize); + + nClipX8 = nCaveXSize - 8; + nClipX16 = nCaveXSize - 16; + nClipY8 = nCaveYSize - 8; + nClipY16 = nCaveYSize - 16; + + RenderTile = RenderTile_ROT0[(nCaveXSize == 320) ? 0 : 1]; + + return 0; +} + +INT32 CaveTileInitLayer(INT32 nLayer, INT32 nROMSize, INT32 nBitdepth, INT32 nOffset) +{ + INT32 nTileSize = (8 << 3); + INT32 nNumTiles = nROMSize / nTileSize; + + for (nTileMask[nLayer] = 1; nTileMask[nLayer] < nNumTiles; nTileMask[nLayer] <<= 1) { } + nTileMask[nLayer]--; + + if (CaveTileAttrib[nLayer]) { + free(CaveTileAttrib[nLayer]); + } + CaveTileAttrib[nLayer] = (INT8*)malloc(nTileMask[nLayer] + 1); + if (CaveTileAttrib[nLayer] == NULL) { + return 1; + } + + for (INT32 i = 0; i < nNumTiles; i++) { + bool bTransparent = true; + for (INT32 j = i * nTileSize; j < (i + 1) * nTileSize; j++) { + if (CaveTileROM[nLayer][j]) { + bTransparent = false; + break; + } + } + if (bTransparent) { + CaveTileAttrib[nLayer][i] = 1; + } else { + CaveTileAttrib[nLayer][i] = 0; + } + } + + for (INT32 i = nNumTiles; i <= nTileMask[nLayer]; i++) { + CaveTileAttrib[nLayer][i] = 1; + } + + if (CaveTileQueueMemory[nLayer]) { + free(CaveTileQueueMemory[nLayer]); + } + CaveTileQueueMemory[nLayer] = (CaveTile*)malloc(4 * 1536 * sizeof(CaveTile)); + if (CaveTileQueueMemory[nLayer] == NULL) { + return 1; + } + + if (pRowScroll[nLayer]) { + free(pRowScroll[nLayer]); + } + pRowScroll[nLayer] = (INT32*)malloc(nCaveYSize * sizeof(INT32)); + if (pRowScroll[nLayer] == NULL) { + return 1; + } + + if (pRowSelect[nLayer]) { + free(pRowSelect[nLayer]); + } + pRowSelect[nLayer] = (INT32*)malloc(nCaveYSize * sizeof(INT32)); + if (pRowSelect[nLayer] == NULL) { + return 1; + } + + nPaletteSize[nLayer] = nBitdepth; + nPaletteOffset[nLayer] = nOffset; + + CaveTileReg[nLayer][2] = 0x0000; // Enable layer + + return 0; +} diff --git a/src/burn/drivers/cave/cave_tile_render.h b/src/burn/drivers/cave/cave_tile_render.h new file mode 100644 index 00000000..bcb7f41a --- /dev/null +++ b/src/burn/drivers/cave/cave_tile_render.h @@ -0,0 +1,370 @@ +// Graphics format: 8 × 8 pixel tiles, 4/8 bits/pixel. + +// Create a unique name for each of the functions +#define FN(a,b,c,d,e,f,g,h) RenderTile ## a ## _ ## b ## _ROT ## c ## d ## e ## f ## g ## h +#define FUNCTIONNAME(a,b,c,d,e,f,g,h) FN(a,b,c,d,e,f,g,h) + +#if ROT == 0 + + #if XFLIP == 0 + #define ADVANCECOLUMN pPixel += (BPP >> 3) + #else + #error illegal XFLIP value + #endif + + #if YFLIP == 0 + #define ADVANCEROW pTileRow += ((BPP >> 3) * XSIZE) + #else + #error illegal YFLIP value + #endif + +#else + #error unsupported rotation angle specified +#endif + +#if DOCLIP == 0 + #define CLIP _NOCLIP +#elif DOCLIP == 1 + #define CLIP _CLIP +#else + #error illegal doclip value. +#endif + +#if EIGHTBIT == 0 + #define DEPTH _16 +#elif EIGHTBIT == 1 + #define DEPTH _256 +#else + #error illegal eightbit value +#endif + +#define TESTCOLOUR(x) x + +#if BPP == 16 + #define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \ + *((UINT16*)pPixel) = (UINT16)pTilePalette[a]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \ + UINT32 nRGB = pTilePalette[a]; \ + pPixel[0] = (UINT8)nRGB; \ + pPixel[1] = (UINT8)(nRGB >> 8); \ + pPixel[2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \ + *((UINT32*)pPixel) = (UINT32)pTilePalette[a]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +// For decorating the function name +#if XFLIP == 1 + #if YFLIP == 1 + #define FLIP _FLIPXY + #else + #define FLIP _FLIPX + #endif +#elif YFLIP == 1 + #define FLIP _FLIPY +#else + #define FLIP _NOFLIP +#endif + +#if ROWSELECT == 0 + #define SELECT _NOROWSELECT +#elif ROWSELECT == 1 + #define SELECT _ROWSELECT +#else + #error unsupported rowselect mode specified. +#endif + +#if ROWSCROLL == 0 + #define SCROLL _NOROWSCROLL +#elif ROWSCROLL == 1 + #define SCROLL _ROWSCROLL +#else + #error unsupported rowscroll mode specified. +#endif + +static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,SCROLL,SELECT,CLIP,DEPTH)() +{ +// Create an empty function if unsupported features are requested +#if ROT == 0 && XFLIP == 0 && YFLIP == 0 && !(ROWSCROLL == 1 && ROWSELECT == 1) && EIGHTBIT == 1 + + UINT8 *pTileRow, *pPixel; + INT32 nColour; + + #if ROWSELECT == 0 + INT32 y; + #endif + + #if ROWSELECT == 0 + for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) { + + #if DOCLIP == 1 + if (nTileYPos + y < 0) { + + #if EIGHTBIT == 0 + pTileData++; + #else + pTileData += 2; + #endif + + continue; + } + + if (nTileYPos + y >= nCaveYSize) { + return; + } + #endif + + #else + pTileRow = pTile; + #endif + + pPixel = pTileRow; + + #if ROWSCROLL == 1 + nRowOffset = (nTileXPos - pTileRowInfo[y]) & 0x01FF; + if (nRowOffset >= 0x01F8) { + nRowOffset -= 0x0200; + } + if (nRowOffset >= XSIZE) { + #if EIGHTBIT == 0 + pTileData++; + #else + pTileData += 2; + #endif + continue; + } + pPixel += (BPP >> 3) * nRowOffset; + #endif + + #if ROWSCROLL == 1 + #define XPOS nRowOffset + #else + #define XPOS nTileXPos + #endif + + #if EIGHTBIT == 0 + #if DOCLIP == 1 || ROWSCROLL == 1 + nColour = *pTileData++; + + if (XPOS <= (XSIZE - 8)) { + if (XPOS < 0) { + nColour >>= -XPOS * 4; + pPixel += -XPOS * (BPP >> 3); + } + + switch (XPOS < 0 ? -XPOS : 0) { + case 0: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 1: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 2: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 3: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 4: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 5: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 6: + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + case 7: + PLOTPIXEL(nColour & 0x0F); + } + } else { + + #define CLIPPIXEL(a,b) if (XPOS < XSIZE - (a)) { b; } + CLIPPIXEL(0, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(1, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(2, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(3, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(4, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(5, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(6, PLOTPIXEL(nColour & 0xFF)); + #undef CLIPPIXEL + + } + #else + nColour = *pTileData++; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(nColour & 0x0F); + #endif + #else + #if DOCLIP == 1 || ROWSCROLL == 1 + nColour = pTileData[0]; + + if (XPOS <= (XSIZE - 8)) { + if (XPOS < 0) { + if (XPOS < -3) { + nColour = pTileData[1]; + } + nColour >>= (-XPOS & 3) * 8; + pPixel += -XPOS * (BPP >> 3); + } + + switch (XPOS < 0 ? -XPOS : 0) { + case 0: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 1: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 2: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 3: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour = pTileData[1]; + case 4: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 5: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 6: + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + case 7: + PLOTPIXEL(nColour & 0xFF); + } + } else { + + #define CLIPPIXEL(a,b) if (XPOS < XSIZE - (a)) { b; } + CLIPPIXEL(0, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(1, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(2, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(3, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour = pTileData[1]; + CLIPPIXEL(4, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(5, PLOTPIXEL(nColour & 0xFF)); + ADVANCECOLUMN; + nColour >>= 8; + CLIPPIXEL(6, PLOTPIXEL(nColour & 0xFF)); + #undef CLIPPIXEL + + } + + pTileData += 2; + + #else + nColour = *pTileData++; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + ADVANCECOLUMN; + nColour >>= 8; + PLOTPIXEL(nColour & 0xFF); + #endif + #endif + + #undef XPOS + + #if ROWSELECT == 0 + } + #endif + +#endif +} + +#undef FLIP +#undef CLIP +#undef PLOTPIXEL +#undef TESTCLIP +#undef TESTCOLOUR +#undef ADVANCEROW +#undef ADVANCECOLUMN +#undef SCROLL +#undef SELECT +#undef DEPTH +#undef FUNCTIONNAME +#undef FN + diff --git a/src/burn/drivers/cave/d_dodonpachi.cpp b/src/burn/drivers/cave/d_dodonpachi.cpp new file mode 100644 index 00000000..7d5cd131 --- /dev/null +++ b/src/burn/drivers/cave/d_dodonpachi.cpp @@ -0,0 +1,676 @@ +// DoDonpachi +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 nSpeedhack; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo ddonpachInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(ddonpach) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall ddonpachReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: + case 0x300003: { + return YMZ280BReadStatus(); + } + + case 0x800000: + case 0x800001: { + UINT8 nRet = 6 | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800002: + case 0x800003: + case 0x800004: + case 0x800005: + case 0x800006: + case 0x800007: { + UINT8 nRet = 6 | nVideoIRQ; + return nRet; + } + + case 0xD00000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xD00001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xD00002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0xD00003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall ddonpachReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: { + return YMZ280BReadStatus(); + } + + case 0x800000: { + UINT16 nRet = 6 | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x800002: + case 0x800004: + case 0x800006: { + UINT16 nRet = 6 | nVideoIRQ; + return nRet; + } + + case 0xD00000: + return DrvInput[0] ^ 0xFFFF; + case 0xD00002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall ddonpachWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x300001: + YMZ280BSelectRegister(byteValue); + return; + case 0x300003: + YMZ280BWriteRegister(byteValue); + return; + + case 0xE00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + return; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall ddonpachWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: + YMZ280BSelectRegister(wordValue); + return; + case 0x300002: + YMZ280BWriteRegister(wordValue); + return; + + case 0x800000: + nCaveXOffset = wordValue; + return; + case 0x800002: + nCaveYOffset = wordValue; + return; + case 0x800008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x900000: + CaveTileReg[0][0] = wordValue; + return; + case 0x900002: + CaveTileReg[0][1] = wordValue; + return; + case 0x900004: + CaveTileReg[0][2] = wordValue; + return; + + case 0xA00000: + CaveTileReg[1][0] = wordValue; + return; + case 0xA00002: + CaveTileReg[1][1] = wordValue; + return; + case 0xA00004: + CaveTileReg[1][2] = wordValue; + return; + + case 0xB00000: + CaveTileReg[2][0] = wordValue; + return; + case 0xB00002: + CaveTileReg[2][1] = wordValue; + return; + case 0xB00004: + CaveTileReg[2][2] = wordValue; + return; + + case 0xE00000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + return; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } + } +} + +void __fastcall ddonpachWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall ddonpachWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + EEPROMExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate8Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x7F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1) - nSpeedhack; + + if (!nIRQPending && nCurrentPC >= 0 && nCurrentPC <= 12) { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + +// bprintf(PRINT_NORMAL, "\n"); + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + // Make sure the buffer is entirely filled. + { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x1000000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x200000; // Tile layer 2 + YMZ280BROM = Next; Next += 0x400000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1); + BurnLoadRom(CaveSpriteROM + 0x200000, 3, 1); + BurnLoadRom(CaveSpriteROM + 0x400000, 4, 1); + BurnLoadRom(CaveSpriteROM + 0x600000, 5, 1); + BurnByteswap(CaveSpriteROM, 0x800000); + NibbleSwap2(CaveSpriteROM, 0x800000); + + BurnLoadRom(CaveTileROM[0], 6, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 7, 1); + NibbleSwap2(CaveTileROM[1], 0x200000); + + UINT8* pTemp = (UINT8*)malloc(0x200000); + BurnLoadRom(pTemp, 8, 1); + for (INT32 i = 0; i < 0x0100000; i++) { + CaveTileROM[2][(i << 1) + 1] = (pTemp[(i << 1) + 0] & 15) | ((pTemp[(i << 1) + 1] & 15) << 4); + CaveTileROM[2][(i << 1) + 0] = (pTemp[(i << 1) + 0] >> 4) | (pTemp[(i << 1) + 1] & 240); + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM + 0x000000, 9, 1); + BurnLoadRom(YMZ280BROM + 0x200000, 10, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x700000, 0x703FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x704000, 0x707FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x708000, 0x70BFFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x70C000, 0x70FFFF, SM_RAM); + + SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); // + + SekSetReadWordHandler(0, ddonpachReadWord); + SekSetReadByteHandler(0, ddonpachReadByte); + SekSetWriteWordHandler(0, ddonpachWriteWord); + SekSetWriteByteHandler(0, ddonpachWriteByte); + + SekSetWriteWordHandler(1, ddonpachWriteWordPalette); + SekSetWriteByteHandler(1, ddonpachWriteBytePalette); + + SekClose(); + } + + nCaveRowModeOffset = 1; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(0, 0x1000000); + CaveTileInitLayer(0, 0x400000, 8, 0x4000); + CaveTileInitLayer(1, 0x400000, 8, 0x4000); + CaveTileInitLayer(2, 0x200000, 8, 0x4000); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + // US version: 0x0571AC - 0x0571B8 + // Japan version: 0x056DF4 - 0x056E00 + + nSpeedhack = (strcmp(BurnDrvGetTextA(DRV_NAME), "ddonpach") == 0) ? 0x0571AC : 0x056DF4; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo ddonpachRomDesc[] = { + { "b1.u27", 0x080000, 0xB5CDC8D3, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b2.u26", 0x080000, 0x6BBB063A, BRF_ESS | BRF_PRG }, // 1 + + { "u50.bin", 0x200000, 0x14B260EC, BRF_GRA }, // 2 Sprite data + { "u51.bin", 0x200000, 0xE7BA8CCE, BRF_GRA }, // 3 + { "u52.bin", 0x200000, 0x02492EE0, BRF_GRA }, // 4 + { "u53.bin", 0x200000, 0xCB4C10F0, BRF_GRA }, // 5 + + { "u60.bin", 0x200000, 0x903096A7, BRF_GRA }, // 6 Layer 0 Tile data + { "u61.bin", 0x200000, 0xD89B7631, BRF_GRA }, // 7 Layer 1 Tile data + { "u62.bin", 0x200000, 0x292BFB6B, BRF_GRA }, // 8 Layer 2 Tile data + + { "u6.bin", 0x200000, 0x9DFDAFAF, BRF_SND }, // 9 YMZ280B (AD)PCM data + { "u7.bin", 0x200000, 0x795B17D5, BRF_SND }, // 10 + + { "eeprom-ddonpach.bin", 0x0080, 0x315fb546, BRF_OPT }, +}; + + +STD_ROM_PICK(ddonpach) +STD_ROM_FN(ddonpach) + + +// Rom information +static struct BurnRomInfo ddonpachjRomDesc[] = { + { "u27.bin", 0x080000, 0x2432FF9B, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u26.bin", 0x080000, 0x4F3A914A, BRF_ESS | BRF_PRG }, // 1 + + { "u50.bin", 0x200000, 0x14B260EC, BRF_GRA }, // 2 Sprite data + { "u51.bin", 0x200000, 0xE7BA8CCE, BRF_GRA }, // 3 + { "u52.bin", 0x200000, 0x02492EE0, BRF_GRA }, // 4 + { "u53.bin", 0x200000, 0xCB4C10F0, BRF_GRA }, // 5 + + { "u60.bin", 0x200000, 0x903096A7, BRF_GRA }, // 6 Layer 0 Tile data + { "u61.bin", 0x200000, 0xD89B7631, BRF_GRA }, // 7 Layer 1 Tile data + { "u62.bin", 0x200000, 0x292BFB6B, BRF_GRA }, // 8 Layer 2 Tile data + + { "u6.bin", 0x200000, 0x9DFDAFAF, BRF_SND }, // 9 YMZ280B (AD)PCM data + { "u7.bin", 0x200000, 0x795B17D5, BRF_SND }, // 10 + + { "eeprom-ddonpach.bin", 0x0080, 0x315fb546, BRF_OPT }, +}; + + +STD_ROM_PICK(ddonpachj) +STD_ROM_FN(ddonpachj) + + +struct BurnDriver BurnDrvDoDonpachi = { + "ddonpach", NULL, NULL, NULL, "1997", + "DoDonPachi (International, master ver. 97/02/05)\0", NULL, "Atlus / Cave", "Cave", + L"\u6012\u9996\u9818\u8702 DoDonPachi (International, master ver. 97/02/05)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, ddonpachRomInfo, ddonpachRomName, NULL, NULL, ddonpachInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDoDonpachiJ = { + "ddonpachj", "ddonpach", NULL, NULL, "1997", + "DoDonPachi (Japan, master ver. 97/02/05)\0", NULL, "Atlus / Cave", "Cave", + L"\u6012\u9996\u9818\u8702 DoDonPachi (Japan, master ver. 97/02/05)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, ddonpachjRomInfo, ddonpachjRomName, NULL, NULL, ddonpachInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + + diff --git a/src/burn/drivers/cave/d_donpachi.cpp b/src/burn/drivers/cave/d_donpachi.cpp new file mode 100644 index 00000000..c4541306 --- /dev/null +++ b/src/burn/drivers/cave/d_donpachi.cpp @@ -0,0 +1,783 @@ +// Donpachi +#include "cave.h" +#include "msm6295.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 nBankSize[2] = {0x200000, 0x300000}; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static struct BurnInputInfo donpachiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(donpachi) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall donpachiReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x900000: + case 0x900001: + case 0x900002: + case 0x900003: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x900004: + case 0x900005: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x900006: + case 0x900007: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xB00001: + return MSM6295ReadStatus(0); + case 0xB00011: + return MSM6295ReadStatus(1); + + case 0xC00000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xC00001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xC00002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0xC00003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall donpachiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x900000: + case 0x900002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0x900004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x900006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xB00000: + return MSM6295ReadStatus(0); + case 0xB00010: + return MSM6295ReadStatus(1); + + case 0xC00000: + return DrvInput[0] ^ 0xFFFF; + case 0xC00002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall donpachiWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0xB00000: + case 0xB00001: + case 0xB00002: + case 0xB00003: + MSM6295Command(0, byteValue); + break; + case 0xB00010: + case 0xB00011: + case 0xB00012: + case 0xB00013: + MSM6295Command(1, byteValue); + break; + + case 0xB00020: + case 0xB00021: + case 0xB00022: + case 0xB00023: + case 0xB00024: + case 0xB00025: + case 0xB00026: + case 0xB00027: + case 0xB00028: + case 0xB00029: + case 0xB0002A: + case 0xB0002B: + case 0xB0002C: + case 0xB0002D: + case 0xB0002E: + case 0xB0002F: { + INT32 nBank = (sekAddress >> 1) & 3; + INT32 nChip = (sekAddress >> 3) & 1; + INT32 nAddress = byteValue << 16; + while (nAddress > nBankSize[nChip]) { + nAddress -= nBankSize[nChip]; + } + + if (nChip == 1) { + MSM6295SampleData[1][nBank] = MSM6295ROM + nAddress; + MSM6295SampleInfo[1][nBank] = MSM6295ROM + nAddress + (nBank << 8); + } else { + MSM6295SampleData[0][nBank] = MSM6295ROM + 0x100000 + nAddress; + if (nBank == 0) { + MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + nAddress + 0x0000; + MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + nAddress + 0x0100; + MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + nAddress + 0x0200; + MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + nAddress + 0x0300; + } + } + break; + } + + case 0xD00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall donpachiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x600000: + CaveTileReg[1][0] = wordValue; + break; + case 0x600002: + CaveTileReg[1][1] = wordValue; + break; + case 0x600004: + CaveTileReg[1][2] = wordValue; + break; + + case 0x700000: + CaveTileReg[0][0] = wordValue; + break; + case 0x700002: + CaveTileReg[0][1] = wordValue; + break; + case 0x700004: + CaveTileReg[0][2] = wordValue; + break; + + case 0x800000: + CaveTileReg[2][0] = wordValue; + break; + case 0x800002: + CaveTileReg[2][1] = wordValue; + break; + case 0x800004: + CaveTileReg[2][2] = wordValue; + break; + + case 0x900000: + nCaveXOffset = wordValue; + return; + case 0x900002: + nCaveYOffset = wordValue; + return; + case 0x900008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0xB00000: + case 0xB00002: + MSM6295Command(0, wordValue); + break; + case 0xB00010: + case 0xB00012: + MSM6295Command(1, wordValue); + break; + + case 0xB00020: + case 0xB00021: + case 0xB00022: + case 0xB00023: + case 0xB00024: + case 0xB00025: + case 0xB00026: + case 0xB00027: + case 0xB00028: + case 0xB00029: + case 0xB0002A: + case 0xB0002B: + case 0xB0002C: + case 0xB0002D: + case 0xB0002E: + case 0xB0002F: { + INT32 nBank = (sekAddress >> 1) & 3; + INT32 nChip = (sekAddress >> 3) & 1; + INT32 nAddress = wordValue << 16; + while (nAddress > nBankSize[nChip]) { + nAddress -= nBankSize[nChip]; + } + + if (nChip == 1) { + MSM6295SampleData[1][nBank] = MSM6295ROM + nAddress; + MSM6295SampleInfo[1][nBank] = MSM6295ROM + nAddress + (nBank << 8); + } else { + MSM6295SampleData[0][nBank] = MSM6295ROM + 0x100000 + nAddress; + if (nBank == 0) { + MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + nAddress + 0x0000; + MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + nAddress + 0x0100; + MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + nAddress + 0x0200; + MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + nAddress + 0x0300; + } + } + break; + } + + case 0xD00000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(1); + MSM6295Exit(0); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + MSM6295Reset(0); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate4Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x7F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + // All versions are the same + if (!nIRQPending && nCurrentPC >= 0x002ED6 && nCurrentPC <= 0x002EE2) { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + INT32 nCyclesTotal[2]; + INT32 nCyclesDone[2]; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Run 68000 + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + // Make sure the buffer is entirely filled. + { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68K program + CaveSpriteROM = Next; Next += 0x800000; + CaveTileROM[0] = Next; Next += 0x200000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x200000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x080000; // Tile layer 2 + MSM6295ROM = Next; Next += 0x300000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x001000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + BurnLoadRom(CaveSpriteROM + 0x000000, 1, 1); + BurnLoadRom(CaveSpriteROM + 0x200000, 2, 1); + BurnByteswap(CaveSpriteROM, 0x400000); + NibbleSwap2(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0], 3, 1); + NibbleSwap2(CaveTileROM[0], 0x100000); + BurnLoadRom(CaveTileROM[1], 4, 1); + NibbleSwap2(CaveTileROM[1], 0x100000); + BurnLoadRom(CaveTileROM[2], 5, 1); + NibbleSwap2(CaveTileROM[2], 0x040000); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 6, 1); + BurnLoadRom(MSM6295ROM + 0x100000, 7, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x200000, 0x207FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x300000, 0x307FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x400000, 0x403FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2] + 0x4000, 0x404000, 0x407FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x500000, 0x50FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0xA08000, 0xA08FFF, SM_RAM); // Palette RAM + + SekSetReadWordHandler(0, donpachiReadWord); + SekSetReadByteHandler(0, donpachiReadByte); + SekSetWriteWordHandler(0, donpachiWriteWord); + SekSetWriteByteHandler(0, donpachiWriteByte); + + SekClose(); + } + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(0, 0x0800000); + CaveTileInitLayer(0, 0x200000, 8, 0x4000); + CaveTileInitLayer(1, 0x200000, 8, 0x4000); + CaveTileInitLayer(2, 0x080000, 8, 0x4000); + + MSM6295Init(0, 8000, 50.0, 0); + MSM6295Init(1, 16000, 50.0, 0); + + MSM6295SampleData[0][0] = MSM6295ROM + 0x100000; + MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + 0x0000; + MSM6295SampleData[0][1] = MSM6295ROM + 0x100000; + MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + 0x0100; + MSM6295SampleData[0][2] = MSM6295ROM + 0x100000; + MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + 0x0200; + MSM6295SampleData[0][3] = MSM6295ROM + 0x100000; + MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + 0x0300; + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo donpachiRomDesc[] = { + { "prgu.u29", 0x080000, 0x89C36802, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data + { "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2 + + { "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data + { "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data + { "text.u58", 0x040000, 0x5DBA06E7, BRF_GRA }, // 5 Layer 2 Tile data + + { "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data + { "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data + + { "eeprom-donpachi.u10", 0x0080, 0x315fb546, BRF_OPT }, + + { "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT }, +}; + + +STD_ROM_PICK(donpachi) +STD_ROM_FN(donpachi) + +static struct BurnRomInfo donpachijRomDesc[] = { + { "prg.u29", 0x080000, 0x6BE14AF6, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data + { "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2 + + { "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data + { "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data + { "u58.bin", 0x040000, 0x285379FF, BRF_GRA }, // 5 Layer 2 Tile data + + { "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data + { "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data + + { "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT }, + + { "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT }, +}; + + +STD_ROM_PICK(donpachij) +STD_ROM_FN(donpachij) + +static struct BurnRomInfo donpachikrRomDesc[] = { + { "prgk.u26", 0x080000, 0xBBAF4C8B, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data + { "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2 + + { "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data + { "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data + { "u58.bin", 0x040000, 0x285379FF, BRF_GRA }, // 5 Layer 2 Tile data + + { "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data + { "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data + + { "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT }, + + { "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT }, +}; + + +STD_ROM_PICK(donpachikr) +STD_ROM_FN(donpachikr) + +static struct BurnRomInfo donpachihkRomDesc[] = { + { "37.u29", 0x080000, 0x71f39f30, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data + { "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2 + + { "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data + { "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data + { "u58.bin", 0x040000, 0x285379ff, BRF_GRA }, // 5 Layer 2 Tile data + + { "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data + { "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data + + { "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT }, + + { "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT }, +}; + + +STD_ROM_PICK(donpachihk) +STD_ROM_FN(donpachihk) + + +struct BurnDriver BurnDrvDonpachi = { + "donpachi", NULL, NULL, NULL, "1995", + "DonPachi (USA, ver. 1.12, 95/05/2x)\0", NULL, "Atlus / Cave", "Cave", + L"\u9996\u9818\u8702 DonPachi (USA, ver. 1.12, 95/05/2x)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0, + NULL, donpachiRomInfo, donpachiRomName, NULL, NULL, donpachiInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDonpachij = { + "donpachij", "donpachi", NULL, NULL, "1995", + "DonPachi (Japan, ver. 1.01, 95/05/11)\0", NULL, "Atlus / Cave", "Cave", + L"\u9996\u9818\u8702 DonPachi (Japan, ver. 1.01, 95/05/11)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0, + NULL, donpachijRomInfo, donpachijRomName, NULL, NULL, donpachiInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDonpachikr = { + "donpachikr", "donpachi", NULL, NULL, "1995", + "DonPachi (Korea, ver. 1.12, 95/05/2x)\0", NULL, "Atlus / Cave", "Cave", + L"\u9996\u9818\u8702 DonPachi (Korea, ver. 1.12, 95/05/2x)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0, + NULL, donpachikrRomInfo, donpachikrRomName, NULL, NULL, donpachiInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDonpachihk = { + "donpachihk", "donpachi", NULL, NULL, "1995", + "DonPachi (Hong Kong, ver. 1.10, 95/05/17)\0", NULL, "Atlus / Cave", "Cave", + L"\u9996\u9818\u8702 DonPachi (Hong Kong, ver. 1.10, 95/05/17)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0, + NULL, donpachihkRomInfo, donpachihkRomName, NULL, NULL, donpachiInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_esprade.cpp b/src/burn/drivers/cave/d_esprade.cpp new file mode 100644 index 00000000..b96c957f --- /dev/null +++ b/src/burn/drivers/cave/d_esprade.cpp @@ -0,0 +1,723 @@ +// E.S.P. Ra De +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 nSpeedhack; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo espradeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(esprade) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall espradeReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300003: { + return YMZ280BReadStatus(); + } + + case 0x800000: + case 0x800001: + case 0x800002: + case 0x800003: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x800004: + case 0x800005: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: + case 0x800007: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xD00001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xD00002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0xD00003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall espradeReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: { + return YMZ280BReadStatus(); + } + + case 0x800000: + case 0x800002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0x800004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00000: + return DrvInput[0] ^ 0xFFFF; + case 0xD00002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall espradeWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x300001: + YMZ280BSelectRegister(byteValue); + break; + case 0x300003: + YMZ280BWriteRegister(byteValue); + break; + + case 0xE00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall espradeWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: + YMZ280BSelectRegister(wordValue); + break; + case 0x300002: + YMZ280BWriteRegister(wordValue); + break; + + case 0x800000: + nCaveXOffset = wordValue; + return; + case 0x800002: + nCaveYOffset = wordValue; + return; + case 0x800008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x900000: + CaveTileReg[0][0] = wordValue; + break; + case 0x900002: + CaveTileReg[0][1] = wordValue; + break; + case 0x900004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xA00000: + CaveTileReg[1][0] = wordValue; + break; + case 0xA00002: + CaveTileReg[1][1] = wordValue; + break; + case 0xA00004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xB00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xB00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xB00004: + CaveTileReg[2][2] = wordValue; + break; + + case 0xE00000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +void __fastcall espradeWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall espradeWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + EEPROMExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate8Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x0000]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1) - nSpeedhack; + + if (!nIRQPending && nCurrentPC >= 0 && nCurrentPC <= 12) { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x1000000; + CaveTileROM[0] = Next; Next += 0x800000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x800000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 + YMZ280BROM = Next; Next += 0x400000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap3(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[0] = (n1 << 4) | (n2 & 0x0F); + pData[1] = (n1 & 0xF0) | (n2 >> 4); + } + + return; +} + +static void NibbleSwap4(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[1] = (n2 << 4) | (n1 & 0x0F); + pData[0] = (n2 & 0xF0) | (n1 >> 4); + } + + return; +} + + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x000000, 2, 2); + BurnLoadRom(CaveSpriteROM + 0x000001, 3, 2); + BurnLoadRom(CaveSpriteROM + 0x800000, 4, 2); + BurnLoadRom(CaveSpriteROM + 0x800001, 5, 2); + NibbleSwap3(CaveSpriteROM, 0x800000); + + BurnLoadRom(CaveTileROM[0] + 0x000000, 6, 1); + BurnLoadRom(CaveTileROM[0] + 0x400000, 7, 1); + NibbleSwap4(CaveTileROM[0], 0x400000); + BurnLoadRom(CaveTileROM[1] + 0x000000, 8, 1); + BurnLoadRom(CaveTileROM[1] + 0x400000, 9, 1); + NibbleSwap4(CaveTileROM[1], 0x400000); + BurnLoadRom(CaveTileROM[2] + 0x000000, 10, 1); + NibbleSwap4(CaveTileROM[2], 0x200000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM, 11, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x700000, 0x707FFF, SM_RAM); + + SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); // + + SekSetReadWordHandler(0, espradeReadWord); + SekSetReadByteHandler(0, espradeReadByte); + SekSetWriteWordHandler(0, espradeWriteWord); + SekSetWriteByteHandler(0, espradeWriteByte); + + SekSetWriteWordHandler(1, espradeWriteWordPalette); + SekSetWriteByteHandler(1, espradeWriteBytePalette); + + SekClose(); + } + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x1000000); + CaveTileInitLayer(0, 0x800000, 8, 0x4000); + CaveTileInitLayer(1, 0x800000, 8, 0x4000); + CaveTileInitLayer(2, 0x400000, 8, 0x4000); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + // 4/22 version: 0x04F37C - 0x04F388 + // 4/21 version: 0x04F150 - 0x04F15C + // 4/14 version: 0x04F152 - 0x04F15E + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "esprade") == 0) { + nSpeedhack = 0x04F37C; + } else { + if (strcmp(BurnDrvGetTextA(DRV_NAME), "espradej") == 0) { + nSpeedhack = 0x04F152; + } else { + nSpeedhack = 0x04F150; + } + } + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo espradeRomDesc[] = { + { "u42.int", 0x080000, 0x3B510A73, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u41.int", 0x080000, 0x97C1B649, BRF_ESS | BRF_PRG }, // 1 + + { "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data + { "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3 + { "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4 + { "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5 + + { "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data + { "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7 + { "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data + { "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9 + { "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data + + { "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data + + { "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT }, +}; + + +STD_ROM_PICK(esprade) +STD_ROM_FN(esprade) + +static struct BurnRomInfo espradejRomDesc[] = { + { "u42_ver.2", 0x080000, 0x75D03C42, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u41_ver.2", 0x080000, 0x734B3EF0, BRF_ESS | BRF_PRG }, // 1 + + { "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data + { "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3 + { "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4 + { "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5 + + { "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data + { "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7 + { "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data + { "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9 + { "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data + + { "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data + + { "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT }, +}; + + +STD_ROM_PICK(espradej) +STD_ROM_FN(espradej) + +static struct BurnRomInfo espradejoRomDesc[] = { + { "u42.bin", 0x080000, 0x0718C7E5, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u41.bin", 0x080000, 0xDEF30539, BRF_ESS | BRF_PRG }, // 1 + + { "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data + { "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3 + { "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4 + { "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5 + + { "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data + { "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7 + { "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data + { "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9 + { "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data + + { "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data + + { "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT }, +}; + + +STD_ROM_PICK(espradejo) +STD_ROM_FN(espradejo) + +struct BurnDriver BurnDrvEsprade = { + "esprade", NULL, NULL, NULL, "1998", + "ESP Ra.De. - A.D.2018 Tokyo (International, ver. 98/04/22)\0", NULL, "Atlus / Cave", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, espradeRomInfo, espradeRomName, NULL, NULL, espradeInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvEspradej = { + "espradej", "esprade", NULL, NULL, "1998", + "ESP Ra.De. (Japan, ver. 98/04/21)\0", NULL, "Atlus / Cave", "Cave", + L"ESP Ra.De. \u30A8\u30B9\u30D7\u30EC\u30A4\u30C9 (Japan, ver. 98/04/21)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, espradejRomInfo, espradejRomName, NULL, NULL, espradeInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvEspradejo = { + "espradejo", "esprade", NULL, NULL, "1998", + "ESP Ra.De. (Japan, ver. 98/04/14)\0", NULL, "Atlus / Cave", "Cave", + L"ESP Ra.De. \u30A8\u30B9\u30D7\u30EC\u30A4\u30C9 (Japan, ver. 98/04/14)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, espradejoRomInfo, espradejoRomName, NULL, NULL, espradeInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + diff --git a/src/burn/drivers/cave/d_feversos.cpp b/src/burn/drivers/cave/d_feversos.cpp new file mode 100644 index 00000000..6b944487 --- /dev/null +++ b/src/burn/drivers/cave/d_feversos.cpp @@ -0,0 +1,645 @@ +// Fever SOS / Dangun Feveron +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 nSpeedhack; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo feversosInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(feversos) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall feversosReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300003: { + return YMZ280BReadStatus(); + } + + case 0x800000: + case 0x800001: + case 0x800002: + case 0x800003: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x800004: + case 0x800005: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: + case 0x800007: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xB00000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xB00001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xB00002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0xB00003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall feversosReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: { + return YMZ280BReadStatus(); + } + + case 0x800000: + case 0x800002: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x800004: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xB00000: + return DrvInput[0] ^ 0xFFFF; + case 0xB00002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall feversosWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x300001: + YMZ280BSelectRegister(byteValue); + break; + case 0x300003: + YMZ280BWriteRegister(byteValue); + break; + + case 0xC00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall feversosWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: + YMZ280BSelectRegister(wordValue); + break; + case 0x300002: + YMZ280BWriteRegister(wordValue); + break; + + case 0x800000: + nCaveXOffset = wordValue; + return; + case 0x800002: + nCaveYOffset = wordValue; + return; + case 0x800008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x900000: + CaveTileReg[0][0] = wordValue; + break; + case 0x900002: + CaveTileReg[0][1] = wordValue; + break; + case 0x900004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xA00000: + CaveTileReg[1][0] = wordValue; + break; + case 0xA00002: + CaveTileReg[1][1] = wordValue; + break; + case 0xA00004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xC00000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + YMZ280BExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate4Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x3F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 0 && defined USE_SPEEDHACKS + UINT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && nCurrentPC >= nSpeedhack && nCurrentPC <= nSpeedhack + 0x18) { + return 1; + } +#endif + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x1000000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + YMZ280BROM = Next; Next += 0x400000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + Ram02 = Next; Next += 0x001000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x001000; // palette +// CaveVideoRegisters= Next; Next += 0x000080; + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1); + BurnLoadRom(CaveSpriteROM + 0x400000, 3, 1); + NibbleSwap1(CaveSpriteROM, 0x800000); + + BurnLoadRom(CaveTileROM[0], 4, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 5, 1); + NibbleSwap2(CaveTileROM[1], 0x200000); + + BurnLoadRom(YMZ280BROM, 6, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x0C,0x11,0x0D,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF}; +static const UINT8 default_eeprom_feversos[18] = {0x00,0x0C,0x16,0x27,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF,0x05,0x19}; /* Fever SOS (code checks for the 0x0519 or it won't boot) */ + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "dfeveron")) { + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "feversos")) { + if (!EEPROMAvailable()) EEPROMFill(default_eeprom_feversos,0, sizeof(default_eeprom_feversos)); + } + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x708000, 0x708FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram02, 0x710000, 0x710BFF, SM_ROM); + SekMapMemory(Ram02, 0x710C00, 0x710FFF, SM_RAM); + + SekSetReadWordHandler(0, feversosReadWord); + SekSetReadByteHandler(0, feversosReadByte); + SekSetWriteWordHandler(0, feversosWriteWord); + SekSetWriteByteHandler(0, feversosWriteByte); + + SekClose(); + } + + nCaveRowModeOffset = 1; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x1000000); + CaveTileInitLayer(0, 0x400000, 8, 0x4000); + CaveTileInitLayer(1, 0x400000, 8, 0x4000); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + // Fever SOS: 0x07766C - 0x077684 + // Dangun Feveron: 0x0772F2 - 0x07730A + + nSpeedhack = (strcmp(BurnDrvGetTextA(DRV_NAME), "feversos") == 0) ? 0x07766C : 0x0772F2; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo feversosRomDesc[] = { + { "cv01-u34.sos", 0x080000, 0x24EF3CE6, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "cv01-u33.sos", 0x080000, 0x64FF73FD, BRF_ESS | BRF_PRG }, // 1 + + { "cv01-u25.bin", 0x400000, 0xA6F6A95D, BRF_GRA }, // 2 Sprite data + { "cv01-u26.bin", 0x400000, 0x32EDB62A, BRF_GRA }, // 3 + + { "cv01-u50.bin", 0x200000, 0x7A344417, BRF_GRA }, // 4 Layer 0 Tile data + { "cv01-u49.bin", 0x200000, 0xD21CDDA7, BRF_GRA }, // 5 Layer 1 Tile data + + { "cv01-u19.bin", 0x400000, 0x5F5514DA, BRF_SND }, // 6 YMZ280B (AD)PCM data + + { "eeprom-feversos.bin", 0x0080, 0xd80303aa, BRF_OPT }, +}; + + +STD_ROM_PICK(feversos) +STD_ROM_FN(feversos) + +static struct BurnRomInfo dfeveronRomDesc[] = { + { "cv01-u34.bin", 0x080000, 0xBE87F19D, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "cv01-u33.bin", 0x080000, 0xE53A7DB3, BRF_ESS | BRF_PRG }, // 1 + + { "cv01-u25.bin", 0x400000, 0xA6F6A95D, BRF_GRA }, // 2 Sprite data + { "cv01-u26.bin", 0x400000, 0x32EDB62A, BRF_GRA }, // 3 + + { "cv01-u50.bin", 0x200000, 0x7A344417, BRF_GRA }, // 4 Layer 0 Tile data + { "cv01-u49.bin", 0x200000, 0xD21CDDA7, BRF_GRA }, // 5 Layer 1 Tile data + + { "cv01-u19.bin", 0x400000, 0x5F5514DA, BRF_SND }, // 6 YMZ280B (AD)PCM data + + { "eeprom-dfeveron.bin", 0x0080, 0xc3174959, BRF_OPT }, +}; + + +STD_ROM_PICK(dfeveron) +STD_ROM_FN(dfeveron) + +struct BurnDriver BurnDrvFeverSOS = { + "feversos", NULL, NULL, NULL, "1998", + "Fever SOS (International, ver. 98/09/25)\0", NULL, "Cave / Nihon System inc.", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, feversosRomInfo, feversosRomName, NULL, NULL, feversosInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDFeveron = { + "dfeveron", "feversos", NULL, NULL, "1998", + "Dangun Feveron (Japan, ver. 98/09/17)\0", NULL, "Cave / Nihon System inc.", "Cave", + L"\u5F3E\u9283 Feveron \u3060\u3093\u304C\u3093\u30D5\u30A3\u30FC\u30D0\u30ED\u30F3 (Japan, ver. 98/09/17)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, dfeveronRomInfo, dfeveronRomName, NULL, NULL, feversosInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_gaia.cpp b/src/burn/drivers/cave/d_gaia.cpp new file mode 100644 index 00000000..636e7513 --- /dev/null +++ b/src/burn/drivers/cave/d_gaia.cpp @@ -0,0 +1,887 @@ +// Gaia Crusaders +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[16] = {0, }; +static UINT8 DrvJoy2[16] = {0, }; +static UINT16 DrvInput[3] = {0, }; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static INT8 nVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo gaiaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 4, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 5, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy1 + 15, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy2 + 2, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 3, "service"}, + + {"DIP A", BIT_DIPSWITCH, (UINT8*)(DrvInput + 2) + 0, "dip"}, + {"DIP B", BIT_DIPSWITCH, (UINT8*)(DrvInput + 2) + 1, "dip"}, +}; + +STDINPUTINFO(gaia) + +static struct BurnDIPInfo gaiaDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x04, NULL}, + {0x18, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "V reverse"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x17, 0x01, 0x02, 0x02, "Off"}, + {0x17, 0x01, 0x02, 0x00, "On"}, + {0, 0xFE, 0, 2, "Language"}, + {0x17, 0x01, 0x04, 0x00, "Japanese"}, + {0x17, 0x01, 0x04, 0x04, "English"}, + {0, 0xFE, 0, 9, "Coin"}, + {0x17, 0x01, 0x78, 0x00, "1 coin 1 credit"}, + {0x17, 0x01, 0x78, 0x08, "1 coin 2 credits"}, + {0x17, 0x01, 0x78, 0x10, "1 coin 3 credits"}, + {0x17, 0x01, 0x78, 0x18, "2 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x20, "2 coins 3 credits"}, + {0x17, 0x01, 0x78, 0x28, "3 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x30, "4 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x38, "2 coins 1 credit 1 continue"}, + {0x17, 0x01, 0x78, 0x40, "Free play"}, + {0x17, 0x01, 0x78, 0x48, "Free play"}, + {0x17, 0x01, 0x78, 0x50, "Free play"}, + {0x17, 0x01, 0x78, 0x58, "Free play"}, + {0x17, 0x01, 0x78, 0x60, "Free play"}, + {0x17, 0x01, 0x78, 0x68, "Free play"}, + {0x17, 0x01, 0x78, 0x70, "Free play"}, + {0x17, 0x01, 0x78, 0x78, "Free play"}, + {0, 0xFE, 0, 2, "Continue"}, + {0x17, 0x01, 0x80, 0x80, "Off"}, + {0x17, 0x01, 0x80, 0x00, "On"}, + + // DIP 2 + {0, 0xFE, 0, 8, "Level"}, + {0x18, 0x01, 0xE0, 0x20, "Very easy"}, + {0x18, 0x01, 0xE0, 0x40, "Easy"}, + {0x18, 0x01, 0xE0, 0x00, "Medium"}, + {0x18, 0x01, 0xE0, 0x80, "Medium hard"}, + {0x18, 0x01, 0xE0, 0x60, "Hard 1"}, + {0x18, 0x01, 0xE0, 0xC0, "Hard 2"}, + {0x18, 0x01, 0xE0, 0xA0, "Very hard"}, + {0x18, 0x01, 0xE0, 0xE0, "Hardest"}, + + // Extend condition + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0x00, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/350,000"}, + {0x18, 0x00, 0xE0, 0x00, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0x20, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/300,000"}, + {0x18, 0x00, 0xE0, 0x20, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0x40, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/350,000"}, + {0x18, 0x00, 0xE0, 0x40, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0x60, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/400,000"}, + {0x18, 0x00, 0xE0, 0x60, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0x80, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/400,000"}, + {0x18, 0x00, 0xE0, 0x80, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0xA0, NULL}, + {0x18, 0x02, 0x04, 0x00, "200,000/500,000"}, + {0x18, 0x00, 0xE0, 0xA0, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0xC0, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/400,000"}, + {0x18, 0x00, 0xE0, 0xC0, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xE0, 0xE0, NULL}, + {0x18, 0x02, 0x04, 0x00, "200,000/500,000"}, + {0x18, 0x00, 0xE0, 0xE0, NULL}, + + {0, 0xFE, 0, 4, "Life"}, + {0x18, 0x01, 0x03, 0x02, "1 player"}, + {0x18, 0x01, 0x03, 0x03, "2 players"}, + {0x18, 0x01, 0x03, 0x00, "3 players"}, + {0x18, 0x01, 0x03, 0x01, "4 players"}, + {0, 0xFE, 0, 4, "Damage"}, + {0x18, 0x01, 0x18, 0x00, "+0"}, + {0x18, 0x01, 0x18, 0x08, "+1"}, + {0x18, 0x01, 0x18, 0x10, "+2"}, + {0x18, 0x01, 0x18, 0x18, "+3"}, +}; + +STDDIPINFO(gaia) + +static struct BurnDIPInfo theroesDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x04, NULL}, + {0x18, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "V reverse"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x17, 0x01, 0x02, 0x02, "Off"}, + {0x17, 0x01, 0x02, 0x00, "On"}, + {0, 0xFE, 0, 2, "Language"}, + {0x17, 0x01, 0x04, 0x00, "Chinese"}, + {0x17, 0x01, 0x04, 0x04, "English"}, + {0, 0xFE, 0, 9, "Coin"}, + {0x17, 0x01, 0x78, 0x00, "1 coin 1 credit"}, + {0x17, 0x01, 0x78, 0x08, "1 coin 2 credits"}, + {0x17, 0x01, 0x78, 0x10, "1 coin 3 credits"}, + {0x17, 0x01, 0x78, 0x18, "2 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x20, "2 coins 3 credits"}, + {0x17, 0x01, 0x78, 0x28, "3 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x30, "4 coins 1 credit"}, + {0x17, 0x01, 0x78, 0x38, "2 coins 1 credit 1 continue"}, + {0x17, 0x01, 0x78, 0x40, "Free play"}, + {0x17, 0x01, 0x78, 0x48, "Free play"}, + {0x17, 0x01, 0x78, 0x50, "Free play"}, + {0x17, 0x01, 0x78, 0x58, "Free play"}, + {0x17, 0x01, 0x78, 0x60, "Free play"}, + {0x17, 0x01, 0x78, 0x68, "Free play"}, + {0x17, 0x01, 0x78, 0x70, "Free play"}, + {0x17, 0x01, 0x78, 0x78, "Free play"}, + {0, 0xFE, 0, 2, "Continue"}, + {0x17, 0x01, 0x80, 0x80, "Off"}, + {0x17, 0x01, 0x80, 0x00, "On"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Level"}, + {0x18, 0x01, 0xC0, 0x40, "Very easy"}, + {0x18, 0x01, 0xC0, 0x00, "Medium"}, + {0x18, 0x01, 0xC0, 0x80, "Medium hard"}, + {0x18, 0x01, 0xC0, 0xC0, "Hardest"}, + + // Extend condition + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xC0, 0x00, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/350,000"}, + {0x18, 0x00, 0xC0, 0x00, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xC0, 0x40, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/300,000"}, + {0x18, 0x00, 0xC0, 0x40, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xC0, 0x80, NULL}, + {0x18, 0x02, 0x04, 0x00, "150,000/400,000"}, + {0x18, 0x00, 0xC0, 0x80, NULL}, + {0, 0xFE, 0, 2, "Extend"}, + {0x18, 0x02, 0x04, 0x04, "Nothing"}, + {0x18, 0x00, 0xC0, 0xC0, NULL}, + {0x18, 0x02, 0x04, 0x00, "200,000/500,000"}, + {0x18, 0x00, 0xC0, 0xC0, NULL}, + + {0, 0xFE, 0, 4, "Life"}, + {0x18, 0x01, 0x03, 0x02, "1 player"}, + {0x18, 0x01, 0x03, 0x03, "2 players"}, + {0x18, 0x01, 0x03, 0x00, "3 players"}, + {0x18, 0x01, 0x03, 0x01, "4 players"}, + {0, 0xFE, 0, 4, "Damage"}, + {0x18, 0x01, 0x18, 0x00, "+0"}, + {0x18, 0x01, 0x18, 0x08, "+1"}, + {0x18, 0x01, 0x18, 0x10, "+2"}, + {0x18, 0x01, 0x18, 0x18, "+3"}, +}; + +STDDIPINFO(theroes) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall gaiaReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300003: { + return YMZ280BReadStatus(); + } + +#if 0 + case 0x800000: + case 0x800001: { + UINT16 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } +#else + case 0x800000: + case 0x800001: +#endif + case 0x800002: + case 0x800003: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x800004: + case 0x800005: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: + case 0x800007: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00010: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xD00011: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xD00012: + return (DrvInput[1] >> 8) ^ 0xFF; + case 0xD00013: + return (DrvInput[1] & 0xFF) ^ 0xFF; + case 0xD00014: + return (DrvInput[2] >> 8) ^ 0xFF; + case 0xD00015: + return (DrvInput[2] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall gaiaReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: { + return YMZ280BReadStatus(); + } + +#if 0 + case 0x800000: { + UINT16 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } +#else + case 0x800000: +#endif + case 0x800002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x800004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x800006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00010: + return DrvInput[0] ^ 0xFFFF; + case 0xD00012: + return DrvInput[1] ^ 0xFFFF; + case 0xD00014: + return DrvInput[2] ^ 0xFFFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall gaiaWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x300001: + YMZ280BSelectRegister(byteValue); + break; + case 0x300003: + YMZ280BWriteRegister(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall gaiaWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: + YMZ280BSelectRegister(wordValue); + break; + case 0x300002: + YMZ280BWriteRegister(wordValue); + break; + + case 0x800000: + nCaveXOffset = wordValue; + return; + case 0x800002: + nCaveYOffset = wordValue; + return; + case 0x800008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x900000: + CaveTileReg[0][0] = wordValue; + break; + case 0x900002: + CaveTileReg[0][1] = wordValue; + break; + case 0x900004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xA00000: + CaveTileReg[1][0] = wordValue; + break; + case 0xA00002: + CaveTileReg[1][1] = wordValue; + break; + case 0xA00004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xB00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xB00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xB00004: + CaveTileReg[2][2] = wordValue; + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +void __fastcall gaiaWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall gaiaWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate8Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x0000]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static void gaiaClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0C) == 0x0C) { + *nJoystickInputs &= ~0xC; + } +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 16; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + gaiaClearOpposites(((UINT8*)DrvInput) + 0); + gaiaClearOpposites(((UINT8*)DrvInput) + 1); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 58)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 265.5); + nVBlank = 0; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!nVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + nVBlank = 1; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x1000000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 + YMZ280BROM = Next; Next += 0xC00000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x010000; + CaveTileRAM[1] = Next; Next += 0x010000; + CaveTileRAM[2] = Next; Next += 0x010000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap4(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[1] = (n2 << 4) | (n1 & 0x0F); + pData[0] = (n2 & 0xF0) | (n1 >> 4); + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1); + BurnLoadRom(CaveSpriteROM + 0x400000, 3, 1); + NibbleSwap1(CaveSpriteROM, 0x800000); + + BurnLoadRom(CaveTileROM[0] + 0x000000, 4, 1); + NibbleSwap4(CaveTileROM[0], 0x400000); + BurnLoadRom(CaveTileROM[1] + 0x000000, 5, 1); + NibbleSwap4(CaveTileROM[1], 0x400000); + BurnLoadRom(CaveTileROM[2] + 0x000000, 6, 1); + NibbleSwap4(CaveTileROM[2], 0x400000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM + 0x000000, 7, 1); + BurnLoadRom(YMZ280BROM + 0x400000, 8, 1); + BurnLoadRom(YMZ280BROM + 0x800000, 9, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + if (nAction & ACB_MEMORY_ROM) { // Scan all memory, devices & variables + ba.Data = Rom01; + ba.nLen = 0x00100000; + ba.nAddress = 0; + ba.szName = "68K ROM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + ba.Data = Ram01; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "68K RAM"; + BurnAcb(&ba); + + ba.Data = CaveTileRAM[0]; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "Tilemap 0"; + BurnAcb(&ba); + + ba.Data = CaveTileRAM[1]; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "Tilemap 1"; + BurnAcb(&ba); + + ba.Data = CaveTileRAM[2]; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "Tile layer 2"; + BurnAcb(&ba); + + ba.Data = CaveSpriteRAM; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "Sprite tables"; + BurnAcb(&ba); + + ba.Data = CavePalSrc; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "Palette"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(nVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + } + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(58.0); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x50FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x600000, 0x60FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x700000, 0x70FFFF, SM_RAM); + + SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); // + + SekSetReadWordHandler(0, gaiaReadWord); + SekSetReadByteHandler(0, gaiaReadByte); + SekSetWriteWordHandler(0, gaiaWriteWord); + SekSetWriteByteHandler(0, gaiaWriteByte); + + SekSetWriteWordHandler(1, gaiaWriteWordPalette); + SekSetWriteByteHandler(1, gaiaWriteBytePalette); + + SekClose(); + } + + nCaveRowModeOffset = 0; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(2, 0x1000000); + CaveTileInitLayer(0, 0x400000, 8, 0x4000); + CaveTileInitLayer(1, 0x400000, 8, 0x4000); + CaveTileInitLayer(2, 0x400000, 8, 0x4000); + + YMZ280BInit(16000000, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo gaiaRomDesc[] = { + { "prg1.127", 0x080000, 0x47B904B2, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "prg2.128", 0x080000, 0x469B7794, BRF_ESS | BRF_PRG }, // 1 + + { "obj1.736", 0x400000, 0xF4F84E5D, BRF_GRA }, // 2 Sprite data + { "obj2.738", 0x400000, 0x15C2A9CE, BRF_GRA }, // 3 + + { "bg1.989", 0x400000, 0x013A693D, BRF_GRA }, // 4 Layer 0 Tile data + { "bg2.995", 0x400000, 0x783CC62F, BRF_GRA }, // 5 Layer 1 Tile data + { "bg3.998", 0x400000, 0xbcd61d1c, BRF_GRA }, // 6 Layer 2 Tile data + + { "snd1.447", 0x400000, 0x92770A52, BRF_SND }, // 7 YMZ280B (AD)PCM data + { "snd2.454", 0x400000, 0x329AE1CF, BRF_SND }, // 8 + { "snd3.455", 0x400000, 0x4048D64E, BRF_SND }, // 9 +}; + + +STD_ROM_PICK(gaia) +STD_ROM_FN(gaia) + +struct BurnDriver BurnDrvGaia = { + "gaia", NULL, NULL, NULL, "1999", + "Gaia Crusaders\0", NULL, "Noise Factory", "Cave", + L"Gaia Crusaders \u5F81\u6226\u8005\0Gaia Crusaders \u30AC\u30A4\u30A2\u30AF\u30EB\u30BB\u30A4\u30C0\u30FC\u30BA\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_SCRFIGHT, 0, + NULL, gaiaRomInfo, gaiaRomName, NULL, NULL, gaiaInputInfo, gaiaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 224, 4, 3 +}; + +static struct BurnRomInfo theroesRomDesc[] = { + { "t-hero-epm1.u0127", 0x080000, 0x09db7195, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "t-hero-epm0.u0129", 0x080000, 0x2d4e3310, BRF_ESS | BRF_PRG }, // 1 + + { "t-hero-obj1.u0736", 0x400000, 0x35090f7c, BRF_GRA }, // 2 Sprite data + { "t-hero-obj2.u0738", 0x400000, 0x71605108, BRF_GRA }, // 3 + + { "t-hero-bg1.u0999", 0x400000, 0x47b0fb40, BRF_GRA }, // 4 Layer 0 Tile data + { "t-hero-bg2.u0995", 0x400000, 0xb16237a1, BRF_GRA }, // 5 Layer 1 Tile data + { "t-hero-bg3.u0998", 0x400000, 0x08eb5604, BRF_GRA }, // 6 Layer 2 Tile data + + { "crvsaders-snd1.u0447", 0x400000, 0x92770A52, BRF_SND }, // 7 YMZ280B (AD)PCM data + { "crvsaders-snd2.u0454", 0x400000, 0x329AE1CF, BRF_SND }, // 8 + { "t-hero-snd3.u0455", 0x400000, 0x52b0b2c0, BRF_SND }, // 9 +}; + +STD_ROM_PICK(theroes) +STD_ROM_FN(theroes) + +struct BurnDriver BurnDrvTheroes = { + "theroes", NULL, NULL, NULL, "2001", + "Thunder Heroes\0", NULL, "Primetec Investments", "Cave", + L"\u9739\u96F3\u82F1\u96C4 Thunder Heroes\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_SCRFIGHT, 0, + NULL, theroesRomInfo, theroesRomName, NULL, NULL, gaiaInputInfo, theroesDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/cave/d_guwange.cpp b/src/burn/drivers/cave/d_guwange.cpp new file mode 100644 index 00000000..30bc369a --- /dev/null +++ b/src/burn/drivers/cave/d_guwange.cpp @@ -0,0 +1,714 @@ +// Guwange +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[16] = {0, }; +static UINT8 DrvJoy2[16] = {0, }; +static UINT16 DrvInput[2] = {0, }; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo guwangeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 8, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 9, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 11, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 12, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 15, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy2 + 2, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 3, "service"}, +}; + +STDINPUTINFO(guwange) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall guwangeReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x800002: + case 0x800003: { + return YMZ280BReadStatus(); + } + + case 0x300000: + case 0x300001: + case 0x300002: + case 0x300003: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x300004: + case 0x300005: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x300006: + case 0x300007: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00010: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0xD00011: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0xD00012: + return (DrvInput[1] >> 8) ^ 0xFF; + case 0xD00013: + return ((DrvInput[1] & 0x7F) ^ 0x7F) | (EEPROMRead() << 7); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall guwangeReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x800002: { + return YMZ280BReadStatus(); + } + + case 0x300000: + case 0x300002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0x300004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x300006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xD00010: + return DrvInput[0] ^ 0xFFFF; + case 0xD00012: + return (DrvInput[1] ^ 0xFF7F) | (EEPROMRead() << 7); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall guwangeWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x800000: + case 0x800001: + YMZ280BSelectRegister(byteValue); + break; + case 0x800002: + case 0x800003: + YMZ280BWriteRegister(byteValue); + break; + + case 0xD00011: + EEPROMWrite(byteValue & 0x40, byteValue & 0x20, byteValue & 0x80); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall guwangeWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x300000: + nCaveXOffset = wordValue; + return; + case 0x300002: + nCaveYOffset = wordValue; + return; + case 0x300008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x800000: + YMZ280BSelectRegister(wordValue & 0xFF); + break; + case 0x800002: + YMZ280BWriteRegister(wordValue & 0xFF); + break; + + case 0x900000: + CaveTileReg[0][0] = wordValue; + break; + case 0x900002: + CaveTileReg[0][1] = wordValue; + break; + case 0x900004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xA00000: + CaveTileReg[1][0] = wordValue; + break; + case 0xA00002: + CaveTileReg[1][1] = wordValue; + break; + case 0xA00004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xB00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xB00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xB00004: + CaveTileReg[2][2] = wordValue; + break; + + case 0xD00010: + EEPROMWrite(wordValue & 0x40, wordValue & 0x20, wordValue & 0x80); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +void __fastcall guwangeWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall guwangeWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + EEPROMExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate8Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x7F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static void guwangeClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x06) == 0x06) { + *nJoystickInputs &= ~0x06; + } + if ((*nJoystickInputs & 0x18) == 0x18) { + *nJoystickInputs &= ~0x18; + } +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && nCurrentPC >= 0x06D6DE && nCurrentPC <= 0x06D6F4) { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Joysticks + DrvInput[1] = 0x0000; // Other controls + for (INT32 i = 0; i < 16; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + guwangeClearOpposites(((UINT8*)DrvInput) + 0); + guwangeClearOpposites(((UINT8*)DrvInput) + 1); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + // Make sure the buffer is entirely filled. + { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x2000000; + CaveTileROM[0] = Next; Next += 0x800000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 + YMZ280BROM = Next; Next += 0x400000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap3(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[0] = (n1 << 4) | (n2 & 0x0F); + pData[1] = (n1 & 0xF0) | (n2 >> 4); + } + + return; +} + +static void NibbleSwap4(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[1] = (n2 << 4) | (n1 & 0x0F); + pData[0] = (n2 & 0xF0) | (n1 >> 4); + } + + return; +} + + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x0000000, 2, 2); + BurnLoadRom(CaveSpriteROM + 0x0000001, 3, 2); + BurnLoadRom(CaveSpriteROM + 0x1000000, 4, 2); + BurnLoadRom(CaveSpriteROM + 0x1000001, 5, 2); + NibbleSwap3(CaveSpriteROM, 0xC00000); + +#if 1 + for (INT32 i = 0; i < 0x100000; i++) { + UINT16 nValue = rand() & 0x0101; + if (nValue & 0x0001) { + nValue |= 0x00FF; + } + if (nValue & 0x0100) { + nValue |= 0xFF00; + } + ((UINT16*)(CaveSpriteROM + 0x1800000))[i] = nValue; + ((UINT16*)(CaveSpriteROM + 0x1A00000))[i] = nValue; + ((UINT16*)(CaveSpriteROM + 0x1C00000))[i] = nValue; + ((UINT16*)(CaveSpriteROM + 0x1E00000))[i] = nValue; + } +#else + memcpy(CaveSpriteROM + 0x1800000, CaveSpriteROM + 0x1000000, 0x800000); +#endif + + BurnLoadRom(CaveTileROM[0] + 0x000000, 6, 1); + NibbleSwap4(CaveTileROM[0], 0x400000); + BurnLoadRom(CaveTileROM[1] + 0x000000, 7, 1); + NibbleSwap4(CaveTileROM[1], 0x200000); + BurnLoadRom(CaveTileROM[2] + 0x000000, 8, 1); + NibbleSwap4(CaveTileROM[2], 0x200000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM, 9, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + + CaveRecalcPalette = 1; + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x0C,0x11,0x0D,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x200000, 0x20FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x700000, 0x707FFF, SM_RAM); + + SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); // + + SekSetReadWordHandler(0, guwangeReadWord); + SekSetReadByteHandler(0, guwangeReadByte); + SekSetWriteWordHandler(0, guwangeWriteWord); + SekSetWriteByteHandler(0, guwangeWriteByte); + + SekSetWriteWordHandler(1, guwangeWriteWordPalette); + SekSetWriteByteHandler(1, guwangeWriteBytePalette); + + SekClose(); + } + + nCaveRowModeOffset = 2; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x2000000); + CaveTileInitLayer(0, 0x800000, 8, 0x4000); + CaveTileInitLayer(1, 0x400000, 8, 0x4000); + CaveTileInitLayer(2, 0x400000, 8, 0x4000); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo guwangeRomDesc[] = { + { "gu-u0127.bin", 0x080000, 0xF86B5293, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "gu-u0129.bin", 0x080000, 0x6C0E3B93, BRF_ESS | BRF_PRG }, // 1 + + { "u083.bin", 0x800000, 0xADC4B9C4, BRF_GRA }, // 2 Sprite data + { "u082.bin", 0x800000, 0x3D75876C, BRF_GRA }, // 3 + { "u086.bin", 0x400000, 0x188E4F81, BRF_GRA }, // 4 + { "u085.bin", 0x400000, 0xA7D5659E, BRF_GRA }, // 5 + + { "u101.bin", 0x800000, 0x0369491F, BRF_GRA }, // 6 Layer 0 Tile data + { "u10102.bin", 0x400000, 0xE28D6855, BRF_GRA }, // 7 Layer 1 Tile data + { "u10103.bin", 0x400000, 0x0FE91B8E, BRF_GRA }, // 8 Layer 2 Tile data + + { "u0462.bin", 0x400000, 0xB3D75691, BRF_SND }, // 9 YMZ280B (AD)PCM data + + { "atc05-1.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u0259.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u084.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u108.bin", 0x000001, 0x00000000, BRF_NODUMP }, + + { "eeprom-guwange.bin", 0x0080, 0xc3174959, BRF_OPT }, +}; + + +STD_ROM_PICK(guwange) +STD_ROM_FN(guwange) + + +struct BurnDriver BurnDrvGuwange = { + "guwange", NULL, NULL, NULL, "1999", + "Guwange (Japan, master ver. 99/06/24)\0", NULL, "Atlus / Cave", "Cave", + L"\u3050\u308F\u3093\u3052 (Japan, master ver. 99/06/24)\0Guwange\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, guwangeRomInfo, guwangeRomName, NULL, NULL, guwangeInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + + +static struct BurnRomInfo guwangesRomDesc[] = { + { "gu-u0127b.bin",0x080000, 0x64667d2e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "gu-u0129b.bin",0x080000, 0xa99C6b6c, BRF_ESS | BRF_PRG }, // 1 + + { "u083.bin", 0x800000, 0xADC4B9C4, BRF_GRA }, // 2 Sprite data + { "u082.bin", 0x800000, 0x3D75876C, BRF_GRA }, // 3 + { "u086.bin", 0x400000, 0x188E4F81, BRF_GRA }, // 4 + { "u085.bin", 0x400000, 0xA7D5659E, BRF_GRA }, // 5 + + { "u101.bin", 0x800000, 0x0369491F, BRF_GRA }, // 6 Layer 0 Tile data + { "u10102.bin", 0x400000, 0xE28D6855, BRF_GRA }, // 7 Layer 1 Tile data + { "u10103.bin", 0x400000, 0x0FE91B8E, BRF_GRA }, // 8 Layer 2 Tile data + + { "u0462.bin", 0x400000, 0xB3D75691, BRF_SND }, // 9 YMZ280B (AD)PCM data + + { "atc05-1.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u0259.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u084.bin", 0x000001, 0x00000000, BRF_NODUMP }, + { "u108.bin", 0x000001, 0x00000000, BRF_NODUMP }, + + { "eeprom-guwange.bin", 0x0080, 0xc3174959, BRF_OPT }, +}; + + +STD_ROM_PICK(guwanges) +STD_ROM_FN(guwanges) + + +struct BurnDriver BurnDrvGuwanges = { + "guwanges", "guwange", NULL, NULL, "1999", + "Guwange (Japan, special ver. 00/01/01)\0", NULL, "Atlus / Cave", "Cave", + L"\u3050\u308F\u3093\u3052 (Japan, special ver. 00/01/01)\0Guwange\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0, + NULL, guwangesRomInfo, guwangesRomName, NULL, NULL, guwangeInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_hotdogst.cpp b/src/burn/drivers/cave/d_hotdogst.cpp new file mode 100644 index 00000000..29643e2f --- /dev/null +++ b/src/burn/drivers/cave/d_hotdogst.cpp @@ -0,0 +1,757 @@ +// hotdogst +#include "cave.h" +#include "msm6295.h" +#include "burn_ym2203.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *RomZ80; +static UINT8 *Ram01, *RamZ80; +static UINT8 *MSM6295ROMSrc; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesDone[2]; + +static UINT16 DrvSoundLatch; +static UINT8 DrvZ80Bank; +static UINT8 DrvOkiBank1; +static UINT8 DrvOkiBank2; + +static struct BurnInputInfo hotdogstInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(hotdogst) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall hotdogstReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xc80002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall hotdogstWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + if (~byteValue & 0x0100) { + case 0xd00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + } + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + + } + } +} + +UINT16 __fastcall hotdogstReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xa80000: + case 0xa80002: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xa80004: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0xa80006: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + +// case 0xa8006e: { +// return 0xff; +// } + + case 0xc80000: + return DrvInput[0] ^ 0xFFFF; + case 0xC80002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall hotdogstWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0xa80000: + nCaveXOffset = wordValue; + return; + case 0xa80002: + nCaveYOffset = wordValue; + return; + + case 0xa80008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0xa8006e: { + DrvSoundLatch = wordValue; + ZetNmi(); + return; + } + + case 0xb00000: + CaveTileReg[0][0] = wordValue; + break; + case 0xb00002: + CaveTileReg[0][1] = wordValue; + break; + case 0xb00004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xb80000: + CaveTileReg[1][0] = wordValue; + break; + case 0xb80002: + CaveTileReg[1][1] = wordValue; + break; + case 0xb80004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xc00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xc00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xc00004: + CaveTileReg[2][2] = wordValue; + break; + + case 0xd00000: + if (~wordValue & 0x0100) { + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + } + case 0xd00002: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } + } +} + +UINT8 __fastcall hotdogstZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x30: { + return DrvSoundLatch & 0xff; + } + + case 0x40: { + return (DrvSoundLatch & 0xff00) >> 8; + } + + case 0x50: { + return BurnYM2203Read(0, 0); + } + + case 0x60: { + return MSM6295ReadStatus(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress); + } + } + + return 0; +} + +void __fastcall hotdogstZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: { + DrvZ80Bank = nValue & 0x0f; + + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + return; + } + + case 0x50: { + BurnYM2203Write(0, 0, nValue); + return; + } + + case 0x51: { + BurnYM2203Write(0, 1, nValue); + return; + } + + case 0x60: { + MSM6295Command(0, nValue); + return; + } + + case 0x70: { + DrvOkiBank1 = (nValue >> 0) & 0x03; + DrvOkiBank2 = (nValue >> 4) & 0x03; + + memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000); + memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue); + } + } +} + +UINT8 __fastcall hotdogstZRead(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall hotdogstZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(0); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + ZetExit(); + + BurnYM2203Exit(); + + DrvSoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1 = 0; + DrvOkiBank2 = 0; + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + DrvSoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1 = 0; + DrvOkiBank2 = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate4Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x3F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 80; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesTotal[1] = (INT32)(4000000 / CAVE_REFRESHRATE); + nCyclesDone[0] = nCyclesDone[1] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Run 68000 + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + CaveSpriteBuffer(); + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekClose(); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + RomZ80 = Next; Next += 0x040000; + CaveSpriteROM = Next; Next += 0x800000; + CaveTileROM[0] = Next; Next += 0x100000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x100000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x100000; // Tile layer 2 + MSM6295ROM = Next; Next += 0x040000; + MSM6295ROMSrc = Next; Next += 0x080000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + RamZ80 = Next; Next += 0x002000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x001000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + BurnLoadRom(Rom01 + 1, 0, 2); + BurnLoadRom(Rom01 + 0, 1, 2); + + BurnLoadRom(RomZ80, 2, 1); + + BurnLoadRom(CaveSpriteROM + 0x000000, 3, 1); + BurnLoadRom(CaveSpriteROM + 0x200000, 4, 1); + NibbleSwap1(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0], 5, 1); + NibbleSwap2(CaveTileROM[0], 0x080000); + BurnLoadRom(CaveTileROM[1], 6, 1); + NibbleSwap2(CaveTileROM[1], 0x080000); + BurnLoadRom(CaveTileROM[2], 7, 1); + NibbleSwap2(CaveTileROM[2], 0x080000); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROMSrc, 8, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvZ80Bank); + SCAN_VAR(DrvOkiBank1); + SCAN_VAR(DrvOkiBank2); + } + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetClose(); + + memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000); + memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000); + + CaveRecalcPalette = 1; + } + + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static INT32 drvZInit() +{ + ZetInit(1); + + ZetOpen(0); + + ZetSetInHandler(hotdogstZIn); + ZetSetOutHandler(hotdogstZOut); + ZetSetReadHandler(hotdogstZRead); + ZetSetWriteHandler(hotdogstZWrite); + + // ROM bank 1 + ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM + ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); // + // RAM + ZetMapArea (0xE000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xE000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xE000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +static const UINT8 default_eeprom[16] = {0xF3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x300000, 0x30FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x408000, 0x408FFF, SM_RAM); // Palette RAM + SekMapMemory(CaveTileRAM[0], 0x880000, 0x887FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x980000, 0x987FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0xf00000, 0xf0fFFF, SM_RAM); + + SekSetReadByteHandler(0, hotdogstReadByte); + SekSetWriteByteHandler(0, hotdogstWriteByte); + SekSetReadWordHandler(0, hotdogstReadWord); + SekSetWriteWordHandler(0, hotdogstWriteWord); + SekClose(); + } + + drvZInit(); + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(2, 0x0800000); + CaveTileInitLayer(0, 0x100000, 8, 0); + CaveTileInitLayer(1, 0x100000, 8, 0); + CaveTileInitLayer(2, 0x100000, 8, 0); + + nCaveExtraXOffset = -32; + nCaveExtraYOffset = 32; + + BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + + memcpy(MSM6295ROM, MSM6295ROMSrc, 0x40000); + MSM6295Init(0, 1056000 / 132, 50.0, 1); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo hotdogstRomDesc[] = { + { "mp3.u29", 0x080000, 0x1f4e5479, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "mp4.u28", 0x080000, 0x6f1c3c4b, BRF_ESS | BRF_PRG }, // 1 + + { "mp2.u19", 0x040000, 0xff979ebe, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "mp9.u55", 0x200000, 0x258d49ec, BRF_GRA }, // 3 Sprite data + { "mp8.u54", 0x200000, 0xbdb4d7b8, BRF_GRA }, // 4 + + { "mp7.u56", 0x080000, 0x87c21c50, BRF_GRA }, // 5 Layer 0 Tile data + { "mp6.u61", 0x080000, 0x4dafb288, BRF_GRA }, // 6 Layer 1 Tile data + { "mp5.u64", 0x080000, 0x9b26458c, BRF_GRA }, // 7 Layer 2 Tile data + + { "mp1.u65", 0x080000, 0x4868be1b, BRF_SND }, // 8 MSM6295 #1 ADPCM data + + { "eeprom-hotdogst.bin", 0x0080, 0x12b4f934, BRF_OPT }, +}; + + +STD_ROM_PICK(hotdogst) +STD_ROM_FN(hotdogst) + +struct BurnDriver BurnDrvhotdogst = { + "hotdogst", NULL, NULL, NULL, "1996", + "Hotdog Storm - The First Supersonics (International)\0", NULL, "Marble / ACE International", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, hotdogstRomInfo, hotdogstRomName, NULL, NULL, hotdogstInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 384, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_korokoro.cpp b/src/burn/drivers/cave/d_korokoro.cpp new file mode 100644 index 00000000..d24d40f5 --- /dev/null +++ b/src/burn/drivers/cave/d_korokoro.cpp @@ -0,0 +1,734 @@ +// Koro Koro Quest & Crusher Makochan +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[1]; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 korokoro_hopper = 0; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static const eeprom_interface eeprom_interface_93C46_8bit = +{ + 7, // address bits 7 + 8, // data bits 8 + "*110", // read 1 10 aaaaaa + "*101", // write 1 01 aaaaaa dddddddddddddddd + "*111", // erase 1 11 aaaaaa + "*10000xxxx", // lock 1 00 00xxxx + "*10011xxxx", // unlock 1 00 11xxxx + 1, + 0 +}; + +static struct BurnInputInfo KorokoroInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" }, + {"Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1" }, + {"Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 14, "service" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 12, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, +}; + +STDINPUTINFO(Korokoro) + +static struct BurnDIPInfo KorokoroDIPList[]= +{ + {0x08, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x08, 0x01, 0x20, 0x00, "On" }, + {0x08, 0x01, 0x20, 0x20, "Off" }, +}; + +STDDIPINFO(Korokoro) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + + SekSetIRQLine(2, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall korokoroReadByte(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0x1c0000: + case 0x1c0001: + case 0x300000: + case 0x300001: + return (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 0 : 4); + + case 0x1c0002: + case 0x1c0003: + case 0x300002: + case 0x300003: + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x1c0004: + case 0x1c0005: + case 0x300004: + case 0x300005: + nVideoIRQ = 1; + UpdateIRQStatus(); + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x1c0006: + case 0x1c0007: + case 0x300006: + case 0x300007: + nUnknownIRQ = 1; + UpdateIRQStatus(); + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x280000: + return ((DrvInput[0] >> 8) & 0x5F) | (korokoro_hopper ? 0x00 : 0x80) | (DrvDip[0] & 0x20); + + case 0x280001: + return DrvInput[0] & 0xFF; + + case 0x280002: + return ((DrvInput[1] >> 8) & 0xEF) | (EEPROMRead() ? 0x10 : 0x00); + + case 0x280003: + return DrvInput[1] & 0xFF; + +// default: +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall korokoroReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x1c0000: + case 0x300000: + return (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0); + + case 0x1c0002: + case 0x300002: + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x1c0004: + case 0x300004: + nVideoIRQ = 1; + UpdateIRQStatus(); + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x1c0006: + case 0x300006: + nUnknownIRQ = 1; + UpdateIRQStatus(); + return (nUnknownIRQ << 1) | nVideoIRQ; + + case 0x280000: + return (DrvInput[0] & 0x5FFF) | (korokoro_hopper ? 0x0000 : 0x8000) | ((DrvDip[0] & 0x20) << 8); + + case 0x280002: + return (DrvInput[1] & 0xEFFF) | ((EEPROMRead() & 1) ? 0x1000 : 0x0000); + +// default: +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} + +void __fastcall korokoroWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x240001: + YMZ280BSelectRegister(byteValue); + break; + + case 0x240003: + YMZ280BWriteRegister(byteValue); + break; + + case 0x280008: + case 0x280009: + // leds + break; + + case 0x28000a: + korokoro_hopper = byteValue & 0x01; + EEPROMWrite(byteValue & 0x20, byteValue & 0x10, byteValue & 0x40); + break; + +// default: +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall korokoroWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x140000: + CaveTileReg[0][0] = wordValue; + break; + case 0x140002: + CaveTileReg[0][1] = wordValue; + break; + case 0x140004: + CaveTileReg[0][2] = wordValue; + break; + + case 0x1c0000: + case 0x300000: + nCaveXOffset = wordValue; + return; + + case 0x1c0002: + case 0x300002: + nCaveYOffset = wordValue; + return; + + case 0x1c0008: + case 0x300008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x240000: + YMZ280BSelectRegister(wordValue & 0xff); + break; + + case 0x240002: + YMZ280BWriteRegister(wordValue & 0xff); + break; + + case 0x280008: + return; + + case 0x28000a: { + wordValue >>= 8; + korokoro_hopper = wordValue & 0x01; + EEPROMWrite(wordValue & 0x20, wordValue & 0x10, wordValue & 0x40); + break; + } + +// default: +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + EEPROMExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + BurnFree(Mem); + Mem = NULL; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x03E0) >> 2; // Red + r |= r >> 5; + g = (nColour & 0x7C00) >> 7; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +static void KorokoroPaletteUpdate() +{ + for (INT32 color = 0; color < 0x40; color++) { + for (INT32 pen = 0; pen < 0x10; pen++) { + CavePalette[(color << 8) | pen] = CalcCol(*(UINT16*)(CavePalSrc + ((0x3c00 | (color << 4) | pen)*2))); + } + + for (INT32 pen = 0x10; pen < 0x100; pen++) { + CavePalette[(color << 8) | pen] = CalcCol(*(UINT16*)(CavePalSrc + ((0x0000 | (color << 8) | pen)*2))); + } + } + + for (INT32 color = 0; color < 0x4000; color++) { + CavePalette[color+0x4000] = CalcCol(*(UINT16*)(CavePalSrc + color*2)); + } + + pBurnDrvPalette = CavePalette; +} + +static INT32 DrvDraw() +{ + KorokoroPaletteUpdate(); // Update the palette + CaveClearScreen(CavePalette[0x3F00]); + + CaveSpriteBuffer(); + + if (bDrawScreen) { + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0; // Player 1 + DrvInput[1] = 0; // Player 2 + for (INT32 i = 0; i < 16; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + DrvInput[0] ^= 0xffff; + DrvInput[1] ^= 0xffff; + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + SCAN_VAR(korokoro_hopper); + + CaveScanGraphics(); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + + Rom01 = Next; Next += 0x080000; // 68K program + CaveSpriteROM = Next; Next += 0x400000; + CaveTileROM[0] = Next; Next += 0x200000; // Tile layer 0 + YMZ280BROM = Next; Next += 0x200000; + + RamStart = Next; + + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 0, 1); + + BurnLoadRom(CaveSpriteROM + 0x0000000, 1, 1); + BurnLoadRom(CaveSpriteROM + 0x0100000, 2, 1); + NibbleSwap1(CaveSpriteROM + 0x0000000, 0x180000); + + BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1); + NibbleSwap2(CaveTileROM[0], 0x100000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM, 4, 1); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46_8bit); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(CaveTileRAM[0], 0x100000, 0x107FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x180000, 0x187FFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x200000, 0x207FFF, SM_RAM); + SekMapMemory(Ram01, 0x300000, 0x30FFFF, SM_RAM); + + SekSetReadWordHandler(0, korokoroReadWord); + SekSetReadByteHandler(0, korokoroReadByte); + SekSetWriteWordHandler(0, korokoroWriteWord); + SekSetWriteByteHandler(0, korokoroWriteByte); + + SekClose(); + } + + nCaveRowModeOffset = 1; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x300000); + CaveTileInitLayer(0, 0x200000, 4, 0x4400); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + + return 0; +} + +static INT32 crushermLoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 0, 1); + + BurnLoadRom(CaveSpriteROM + 0x0000000, 1, 1); + BurnLoadRom(CaveSpriteROM + 0x0100000, 2, 1); + NibbleSwap1(CaveSpriteROM + 0x0000000, 0x200000); + + BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1); + NibbleSwap2(CaveTileROM[0], 0x100000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM + 0x000000, 4, 1); + BurnLoadRom(YMZ280BROM + 0x100000, 5, 1); + + return 0; +} + +static INT32 crushermInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46_8bit); + + // Load the roms into memory + if (crushermLoadRoms()) { + return 1; + } + + { + + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(CaveTileRAM[0], 0x100000, 0x107FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x180000, 0x187FFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x200000, 0x207FFF, SM_RAM); + SekMapMemory(Ram01, 0x340000, 0x34FFFF, SM_RAM); + + SekSetReadWordHandler(0, korokoroReadWord); + SekSetReadByteHandler(0, korokoroReadByte); + SekSetWriteWordHandler(0, korokoroWriteWord); + SekSetWriteByteHandler(0, korokoroWriteByte); + + SekClose(); + } + + nCaveRowModeOffset = 1; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x400000); + CaveTileInitLayer(0, 0x200000, 4, 0x4400); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + + return 0; +} + + +// Koro Koro Quest (Japan) + +static struct BurnRomInfo korokoroRomDesc[] = { + { "mp-001_ver07.u0130", 0x080000, 0x86c7241f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "mp-001_ver01.u1066", 0x100000, 0xc5c6af7e, BRF_GRA }, // 1 Sprite data + { "mp-001_ver01.u1051", 0x080000, 0xfe5e28e8, BRF_GRA }, // 2 + + { "mp-001_ver01.u1060", 0x100000, 0xec9cf9d8, BRF_GRA }, // 3 layer 0 Tile data + + { "mp-001_ver01.u1186", 0x100000, 0xd16e7c5d, BRF_SND }, // 4 YMZ280B (AD)PCM data +}; + +STD_ROM_PICK(korokoro) +STD_ROM_FN(korokoro) + +struct BurnDriver BurnDrvKorokoro = { + "korokoro", NULL, NULL, NULL, "1999", + "Koro Koro Quest (Japan)\0", NULL, "Takumi", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_MISC, 0, + NULL, korokoroRomInfo, korokoroRomName, NULL, NULL, KorokoroInputInfo, KorokoroDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + + +// Crusher Makochan (Japan) + +static struct BurnRomInfo crushermRomDesc[] = { + { "mp-003ver01.u0130", 0x080000, 0xa4f56e6b, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "mp-003ver01.u1067", 0x100000, 0x268a4921, BRF_GRA }, // 1 Sprite data + { "mp-003ver01.u1066", 0x100000, 0x79e77a6e, BRF_GRA }, // 2 + + { "mp-003ver01.u1060", 0x100000, 0x7661893e, BRF_GRA }, // 3 layer 0 Tile data + + { "mp-003ver01.u1186", 0x100000, 0xc3aeb745, BRF_SND }, // 4 YMZ280B (AD)PCM data + { "mp-003ver01.u1187", 0x100000, 0xd9312497, BRF_SND }, // 5 +}; + +STD_ROM_PICK(crusherm) +STD_ROM_FN(crusherm) + +struct BurnDriver BurnDrvCrusherm = { + "crusherm", NULL, NULL, NULL, "1999", + "Crusher Makochan (Japan)\0", NULL, "Takumi", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_MISC, 0, + NULL, crushermRomInfo, crushermRomName, NULL, NULL, KorokoroInputInfo, KorokoroDIPInfo, + crushermInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/cave/d_mazinger.cpp b/src/burn/drivers/cave/d_mazinger.cpp new file mode 100644 index 00000000..2ad42fef --- /dev/null +++ b/src/burn/drivers/cave/d_mazinger.cpp @@ -0,0 +1,846 @@ +// mazinger +#include "cave.h" +#include "msm6295.h" +#include "burn_ym2203.h" +#include "bitswap.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *RomZ80; +static UINT8 *Ram01, *RamZ80; +static UINT8 *MSM6295ROMSrc; +static UINT8 *DefEEPROM = NULL; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesDone[2]; + +static INT32 SoundLatch; +static INT32 SoundLatchReply[48]; +static INT32 SoundLatchStatus; + +static INT32 SoundLatchReplyIndex; +static INT32 SoundLatchReplyMax; + +static UINT8 DrvZ80Bank; +static UINT8 DrvOkiBank1; +static UINT8 DrvOkiBank2; + +static struct BurnInputInfo mazingerInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(mazinger) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall mazingerReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x800002: + return (DrvInput[1] ^ 0xF7) | (EEPROMRead() << 3); + case 0x800003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall mazingerWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x900000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + + } + } +} + +UINT16 __fastcall mazingerReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300000: + case 0x300002: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x300004: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x300006: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x30006E: + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + return 0; + } + return SoundLatchReply[SoundLatchReplyIndex++]; + + case 0x800000: + return DrvInput[0] ^ 0xFFFF; + case 0x800002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall mazingerWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress >= 0x30000a && sekAddress <= 0x300066) return; + if (sekAddress >= 0x30006a && sekAddress <= 0x30006c) return; + if (sekAddress >= 0x300004 && sekAddress <= 0x300006) return; + + switch (sekAddress) { + case 0x300000: + nCaveXOffset = wordValue; + return; + case 0x300002: + nCaveYOffset = wordValue; + return; + + case 0x300008: +// CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x30006e: + SoundLatch = wordValue; + SoundLatchStatus |= 0x0C; + + ZetNmi(); + nCyclesDone[1] += ZetRun(0x0400); + return; + + case 0x600000: + CaveTileReg[1][0] = wordValue; + break; + case 0x600002: + CaveTileReg[1][1] = wordValue; + break; + case 0x600004: + CaveTileReg[1][2] = wordValue; + break; + + case 0x700000: + CaveTileReg[0][0] = wordValue; + break; + case 0x700002: + CaveTileReg[0][1] = wordValue; + break; + case 0x700004: + CaveTileReg[0][2] = wordValue; + break; + + case 0x900000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } + } +} + +void __fastcall mazingerWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xffff, byteValue); +} + +void __fastcall mazingerWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xffff, wordValue); +} + +UINT8 __fastcall mazingerZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x30: { + SoundLatchStatus |= 0x04; + return SoundLatch & 0xFF; + } + + case 0x52: { + return BurnYM2203Read(0, 0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress); + } + } + + return 0; +} + +void __fastcall mazingerZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: { + DrvZ80Bank = nValue & 0x07; + + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + return; + } + + case 0x10: + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyMax = -1; + SoundLatchReplyIndex = 0; + } + SoundLatchReplyMax++; + SoundLatchReply[SoundLatchReplyMax] = nValue; + break; + + case 0x50: { + BurnYM2203Write(0, 0, nValue); + return; + } + + case 0x51: { + BurnYM2203Write(0, 1, nValue); + return; + } + + case 0x70: { + MSM6295Command(0, nValue); + return; + } + + case 0x74: { + DrvOkiBank1 = (nValue >> 0) & 0x03; + DrvOkiBank2 = (nValue >> 4) & 0x03; + + memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000); + memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue); + } + } +} + +UINT8 __fastcall mazingerZRead(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall mazingerZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(0); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + ZetExit(); + + BurnYM2203Exit(); + + SoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1 = 0; + DrvOkiBank2 = 0; + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekRun(10000); // Need to run for a bit and reset to make it start - Watchdog would force reset? + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + SoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1 = 0; + DrvOkiBank2 = 0; + + SoundLatch = 0; + SoundLatchStatus = 0x0C; + + memset(SoundLatchReply, 0, sizeof(SoundLatchReply)); + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + + return 0; +} + +static INT32 DrvDraw() +{ + if (CaveRecalcPalette) { + CavePalUpdate8Bit(0x4400, 12); + CaveRecalcPalette = 1; + } + CavePalUpdate4Bit(0, 64); + + CaveClearScreen(CavePalette[0x3F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + + INT32 nInterleave = 80; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesTotal[1] = (INT32)(4000000 / CAVE_REFRESHRATE); + nCyclesDone[0] = nCyclesDone[1] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Run 68000 + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + CaveSpriteBuffer(); + UINT8 Temp = nCaveSpriteBank; + nCaveSpriteBank = nCaveSpriteBankDelay; + nCaveSpriteBankDelay = Temp; + + bVBlank = true; + nVideoIRQ = 0; + nUnknownIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekClose(); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + RomZ80 = Next; Next += 0x020000; + CaveSpriteROM = Next; Next += 0x800000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + MSM6295ROM = Next; Next += 0x040000; + MSM6295ROMSrc = Next; Next += 0x080000; + DefEEPROM = Next; Next += 0x000080; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + RamZ80 = Next; Next += 0x001000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + BurnLoadRom(Rom01 + 0x00000, 0, 1); + BurnLoadRom(Rom01 + 0x80000, 1, 1); + + BurnLoadRom(RomZ80, 2, 1); + + UINT8 *pTemp = (UINT8*)malloc(0x400000); + BurnLoadRom(pTemp + 0x000000, 3, 1); + BurnLoadRom(pTemp + 0x200000, 4, 1); + for (INT32 i = 0; i < 0x400000; i++) { + CaveSpriteROM[i ^ 0xdf88] = pTemp[BITSWAP24(i,23,22,21,20,19,9,7,3,15,4,17,14,18,2,16,5,11,8,6,13,1,10,12,0)]; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + NibbleSwap1(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0], 5, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + + pTemp = (UINT8*)malloc(0x200000); + BurnLoadRom(pTemp, 6, 1); + for (INT32 i = 0; i < 0x0100000; i++) { + CaveTileROM[1][(i << 1) + 1] = (pTemp[(i << 1) + 0] & 15) | ((pTemp[(i << 1) + 1] & 15) << 4); + CaveTileROM[1][(i << 1) + 0] = (pTemp[(i << 1) + 0] >> 4) | (pTemp[(i << 1) + 1] & 240); + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROMSrc, 7, 1); + + BurnLoadRom(DefEEPROM, 8, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + SCAN_VAR(SoundLatch); + SCAN_VAR(DrvZ80Bank); + SCAN_VAR(DrvOkiBank1); + SCAN_VAR(DrvOkiBank2); + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetClose(); + + memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000); + memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000); + + CaveRecalcPalette = 1; + } + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static INT32 drvZInit() +{ + ZetInit(1); + + ZetOpen(0); + + ZetSetInHandler(mazingerZIn); + ZetSetOutHandler(mazingerZOut); + ZetSetReadHandler(mazingerZRead); + ZetSetWriteHandler(mazingerZWrite); + + // ROM bank 1 + ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM + ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); // + // RAM + ZetMapArea (0xc000, 0xc7FF, 0, RamZ80 + 0x0000); // Direct Read from RAM + ZetMapArea (0xc000, 0xc7FF, 1, RamZ80 + 0x0000); // Direct Write to RAM + ZetMapArea (0xc000, 0xc7FF, 2, RamZ80 + 0x0000); // + + ZetMapArea (0xf800, 0xffFF, 0, RamZ80 + 0x0800); // Direct Read from RAM + ZetMapArea (0xf800, 0xffFF, 1, RamZ80 + 0x0800); // Direct Write to RAM + ZetMapArea (0xf800, 0xffFF, 2, RamZ80 + 0x0800); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +static const UINT8 default_eeprom[16] = {0xED,0xFF,0x00,0x00,0x12,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x200000, 0x20FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[1] + 0x4000, 0x400000, 0x403FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1] + 0x4000, 0x404000, 0x407FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0] + 0x4000, 0x500000, 0x503FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0] + 0x4000, 0x504000, 0x507FFF, SM_RAM); + SekMapMemory(CavePalSrc, 0xC08000, 0xc087FF, SM_RAM); // Palette RAM + SekMapMemory(CavePalSrc + 0x8800, 0xC08800, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0xC08800, 0xC0FFFF, SM_WRITE); // + + SekMapMemory(Rom01 + 0x80000, 0xD00000, 0xD7FFFF, SM_ROM); // CPU 0 ROM + + SekSetReadByteHandler(0, mazingerReadByte); + SekSetWriteByteHandler(0, mazingerWriteByte); + SekSetReadWordHandler(0, mazingerReadWord); + SekSetWriteWordHandler(0, mazingerWriteWord); + + SekSetWriteWordHandler(1, mazingerWriteWordPalette); + SekSetWriteByteHandler(1, mazingerWriteBytePalette); + SekClose(); + } + + drvZInit(); + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(2, 0x0800000); + CaveTileInitLayer(0, 0x400000, 8, 0x0000); + CaveTileInitLayer(1, 0x400000, 6, 0x4400); + + BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + + memcpy(MSM6295ROM, MSM6295ROMSrc, 0x40000); + MSM6295Init(0, 1056000 / 132, 100.0, 1); + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(DefEEPROM,0, 0x80); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo mazingerRomDesc[] = { + { "mzp-0.u24", 0x080000, 0x43a4279f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "mzp-1.924", 0x080000, 0xdb40acba, BRF_ESS | BRF_PRG }, // 1 + + { "mzs.u21", 0x020000, 0xc5b4f7ed, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "bp943a-2.u56", 0x200000, 0x97e13959, BRF_GRA }, // 3 Sprite data + { "bp943a-3.u55", 0x080000, 0x9c4957dd, BRF_GRA }, // 4 + + { "bp943a-1.u60", 0x200000, 0x46327415, BRF_GRA }, // 5 Layer 0 Tile data + { "bp943a-0.u63", 0x200000, 0xc1fed98a, BRF_GRA }, // 6 Layer 1 Tile data + + { "bp943a-4.u64", 0x080000, 0x3fc7f29a, BRF_SND }, // 7 MSM6295 #1 ADPCM data + + { "mazinger_world.nv", 0x0080, 0x4f6225c6, BRF_OPT }, +}; + + +STD_ROM_PICK(mazinger) +STD_ROM_FN(mazinger) + +static struct BurnRomInfo mazingerjRomDesc[] = { + { "mzp-0.u24", 0x080000, 0x43a4279f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "mzp-1.924", 0x080000, 0xdb40acba, BRF_ESS | BRF_PRG }, // 1 + + { "mzs.u21", 0x020000, 0xc5b4f7ed, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "bp943a-2.u56", 0x200000, 0x97e13959, BRF_GRA }, // 3 Sprite data + { "bp943a-3.u55", 0x080000, 0x9c4957dd, BRF_GRA }, // 4 + + { "bp943a-1.u60", 0x200000, 0x46327415, BRF_GRA }, // 5 Layer 0 Tile data + { "bp943a-0.u63", 0x200000, 0xc1fed98a, BRF_GRA }, // 6 Layer 1 Tile data + + { "bp943a-4.u64", 0x080000, 0x3fc7f29a, BRF_SND }, // 7 MSM6295 #1 ADPCM data + + { "mazinger_japan.nv", 0x0080, 0xf84a2a45, BRF_OPT }, +}; + + +STD_ROM_PICK(mazingerj) +STD_ROM_FN(mazingerj) + +struct BurnDriver BurnDrvmazinger = { + "mazinger", NULL, NULL, NULL, "1994", + "Mazinger Z (World, ver. 94/06/27)\0", NULL, "Banpresto / Dynamic Pl. Toei Animation", "Cave", + L"Mazinger Z\0\u30DE\u30B8\u30F3\u30AC\u30FC \uFF3A (World, ver. 94/06/27)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL |BDF_ORIENTATION_FLIPPED | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, mazingerRomInfo, mazingerRomName, NULL, NULL, mazingerInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvmazingerj = { + "mazingerj", "mazinger", NULL, NULL, "1994", + "Mazinger Z (Japan, ver. 94/06/27)\0", NULL, "Banpresto / Dynamic Pl. Toei Animation", "Cave", + L"Mazinger Z\0\u30DE\u30B8\u30F3\u30AC\u30FC \uFF3A (Japan, ver. 94/06/27)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL |BDF_ORIENTATION_FLIPPED | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, mazingerjRomInfo, mazingerjRomName, NULL, NULL, mazingerInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 384, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_metmqstr.cpp b/src/burn/drivers/cave/d_metmqstr.cpp new file mode 100644 index 00000000..b2eb882a --- /dev/null +++ b/src/burn/drivers/cave/d_metmqstr.cpp @@ -0,0 +1,852 @@ +// metmqstr +#include "cave.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *RomZ80; +static UINT8 *Ram01, *RamZ80; +static UINT8 *MSM6295ROMSrc1, *MSM6295ROMSrc2; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesDone[2]; + +static INT32 SoundLatch; +static INT32 SoundLatchReply[48]; +static INT32 SoundLatchStatus; + +static INT32 SoundLatchReplyIndex; +static INT32 SoundLatchReplyMax; + +static UINT8 DrvZ80Bank; +static UINT8 DrvOkiBank1_1; +static UINT8 DrvOkiBank1_2; +static UINT8 DrvOkiBank2_1; +static UINT8 DrvOkiBank2_2; + +static struct BurnInputInfo metmqstrInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 10, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 10, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(metmqstr) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall metmqstrReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall metmqstrWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + if (~byteValue & 0x0100) { + case 0xd00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + } + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + + } + } +} + +UINT16 __fastcall metmqstrReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xa80000: + case 0xa80002: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xa80004: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0xa80006: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xa8006C: + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + return 2; + } + return 0; + + case 0xa8006E: + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + return 0; + } + return SoundLatchReply[SoundLatchReplyIndex++]; + + case 0xc80000: + return DrvInput[0] ^ 0xFFFF; + case 0xc80002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall metmqstrWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress >= 0xa8000a && sekAddress <= 0xa80068) return; + if (sekAddress >= 0xa8006a && sekAddress <= 0xa8006c) return; + if (sekAddress >= 0xa80004 && sekAddress <= 0xa80006) return; + + switch (sekAddress) { + case 0xa80000: + nCaveXOffset = wordValue; + return; + case 0xa80002: + nCaveYOffset = wordValue; + return; + + case 0xa80008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0xa8006E: + SoundLatch = wordValue; + SoundLatchStatus |= 0x0C; + + ZetNmi(); + nCyclesDone[1] += ZetRun(0x0400); + return; + + case 0xb00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xb00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xb00004: + CaveTileReg[2][2] = wordValue; + break; + + case 0xb80000: + CaveTileReg[1][0] = wordValue; + break; + case 0xb80002: + CaveTileReg[1][1] = wordValue; + break; + case 0xb80004: + CaveTileReg[1][2] = wordValue; + break; + + case 0xc00000: + CaveTileReg[0][0] = wordValue; + break; + case 0xc00002: + CaveTileReg[0][1] = wordValue; + break; + case 0xc00004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xd00000: + if (~wordValue & 0x0100) { + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + } + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } + } +} + +UINT8 __fastcall metmqstrZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x20: { + return 0; + } + + case 0x30: + SoundLatchStatus |= 0x04; + return SoundLatch & 0xFF; + + case 0x40: + SoundLatchStatus |= 0x08; + return SoundLatch >> 8; + + case 0x51: + return BurnYM2151ReadStatus(); + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress); + } + } + + return 0; +} + +void __fastcall metmqstrZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: { + DrvZ80Bank = nValue & 0x0f; + + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + return; + } + + case 0x50: + BurnYM2151SelectRegister(nValue); + break; + case 0x51: + BurnYM2151WriteRegister(nValue); + break; + + case 0x60: { + MSM6295Command(0, nValue); + return; + } + + case 0x70: { + DrvOkiBank1_1 = (nValue >> 0) & 0x07; + DrvOkiBank1_2 = (nValue >> 4) & 0x07; + + memcpy(MSM6295ROM + 0x000000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_1, 0x20000); + memcpy(MSM6295ROM + 0x020000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_2, 0x20000); + return; + } + + case 0x80: { + MSM6295Command(1, nValue); + return; + } + + case 0x90: { + DrvOkiBank2_1 = (nValue >> 0) & 0x07; + DrvOkiBank2_2 = (nValue >> 4) & 0x07; + + memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_1, 0x20000); + memcpy(MSM6295ROM + 0x120000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_2, 0x20000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue); + } + } +} + +UINT8 __fastcall metmqstrZRead(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall metmqstrZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + ZetExit(); + + SoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1_1 = 0; + DrvOkiBank1_2 = 0; + DrvOkiBank2_1 = 0; + DrvOkiBank2_2 = 0; + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekRun(10000); // Need to run for a bit and reset to make it start - Watchdog would force reset? + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + SoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1_1 = 0; + DrvOkiBank1_2 = 0; + DrvOkiBank2_1 = 0; + DrvOkiBank2_2 = 0; + + SoundLatch = 0; + SoundLatchStatus = 0x0C; + + memset(SoundLatchReply, 0, sizeof(SoundLatchReply)); + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate4Bit(0, 128); + + CaveClearScreen(CavePalette[0x7F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 11; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesTotal[1] = (INT32)(8000000 / CAVE_REFRESHRATE); + nCyclesDone[0] = nCyclesDone[1] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Run 68000 + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + UINT8 Temp = nCaveSpriteBank; + nCaveSpriteBank = nCaveSpriteBankDelay; + nCaveSpriteBankDelay = Temp; + + bVBlank = true; + nVideoIRQ = 0; + nUnknownIRQ = 0; + UpdateIRQStatus(); + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + + SekClose(); + ZetClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x180000; // 68K program + RomZ80 = Next; Next += 0x040000; + CaveSpriteROM = Next; Next += 0x1000000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 + MSM6295ROM = Next; Next += 0x140000; + MSM6295ROMSrc1 = Next; Next += 0x200000; + MSM6295ROMSrc2 = Next; Next += 0x200000; + RamStart = Next; + Ram01 = Next; Next += 0x018000; // CPU #0 work RAM + RamZ80 = Next; Next += 0x002000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + BurnLoadRom(Rom01 + 0x000000, 0, 1); + BurnLoadRom(Rom01 + 0x080000, 1, 1); + BurnLoadRom(Rom01 + 0x100000, 2, 1); + + BurnLoadRom(RomZ80, 3, 1); + + BurnLoadRom(CaveSpriteROM + 0x000000, 4, 1); + BurnLoadRom(CaveSpriteROM + 0x200000, 5, 1); + BurnLoadRom(CaveSpriteROM + 0x400000, 6, 1); + BurnLoadRom(CaveSpriteROM + 0x600000, 7, 1); + NibbleSwap1(CaveSpriteROM, 0x800000); + + BurnLoadRom(CaveTileROM[0], 8, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + + BurnLoadRom(CaveTileROM[1], 9, 1); + NibbleSwap2(CaveTileROM[1], 0x200000); + + BurnLoadRom(CaveTileROM[2], 10, 1); + NibbleSwap2(CaveTileROM[2], 0x200000); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROMSrc1, 11, 1); + BurnLoadRom(MSM6295ROMSrc2, 12, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + SCAN_VAR(SoundLatch); + SCAN_VAR(DrvZ80Bank); + SCAN_VAR(DrvOkiBank1_1); + SCAN_VAR(DrvOkiBank1_2); + SCAN_VAR(DrvOkiBank2_1); + SCAN_VAR(DrvOkiBank2_2); + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetClose(); + + memcpy(MSM6295ROM + 0x000000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_1, 0x20000); + memcpy(MSM6295ROM + 0x020000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_2, 0x20000); + + memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_1, 0x20000); + memcpy(MSM6295ROM + 0x120000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_2, 0x20000); + + CaveRecalcPalette = 1; + } + } + + return 0; +} + +static INT32 drvZInit() +{ + ZetInit(1); + + ZetOpen(0); + + ZetSetInHandler(metmqstrZIn); + ZetSetOutHandler(metmqstrZOut); + ZetSetReadHandler(metmqstrZRead); + ZetSetWriteHandler(metmqstrZWrite); + + // ROM bank 1 + ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM + ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); // + // RAM + ZetMapArea (0xe000, 0xFFFF, 0, RamZ80 + 0x0000); // Direct Read from RAM + ZetMapArea (0xe000, 0xFFFF, 1, RamZ80 + 0x0000); // Direct Write to RAM + ZetMapArea (0xe000, 0xFFFF, 2, RamZ80 + 0x0000); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Rom01 + 0x080000, 0x100000, 0x17FFFF, SM_ROM); + SekMapMemory(Rom01 + 0x100000, 0x200000, 0x27FFFF, SM_ROM); + SekMapMemory(CaveTileRAM[2], 0x880000, 0x887FFF, SM_RAM); + SekMapMemory(Ram01 + 0x00000, 0x888000, 0x88FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM); + SekMapMemory(Ram01 + 0x08000, 0x908000, 0x90FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x980000, 0x987FFF, SM_RAM); + SekMapMemory(Ram01 + 0x10000, 0x988000, 0x98FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x408000, 0x408FFF, SM_RAM); // Palette RAM + SekMapMemory(CaveSpriteRAM, 0xF00000, 0xF0FFFF, SM_RAM); + SekSetReadByteHandler(0, metmqstrReadByte); + SekSetWriteByteHandler(0, metmqstrWriteByte); + SekSetReadWordHandler(0, metmqstrReadWord); + SekSetWriteWordHandler(0, metmqstrWriteWord); + SekClose(); + } + + drvZInit(); + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(2, 0x1000000); + CaveTileInitLayer(0, 0x400000, 8, 0x4000); + CaveTileInitLayer(1, 0x400000, 8, 0x4000); + CaveTileInitLayer(2, 0x400000, 8, 0x4000); + + nCaveExtraXOffset = -126; + CaveSpriteVisibleXOffset = -126; + + BurnYM2151Init(4000000, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + memcpy(MSM6295ROM, MSM6295ROMSrc1, 0x40000); + memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2, 0x40000); + MSM6295Init(0, 2000000 / 132, 100.0, 1); + MSM6295Init(1, 2000000 / 132, 100.0, 1); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo metmqstrRomDesc[] = { + { "bp947a.u25", 0x080000, 0x0a5c3442, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp947a.u28", 0x080000, 0x8c55decf, BRF_ESS | BRF_PRG }, // 1 + { "bp947a.u29", 0x080000, 0xcf0f3f3b, BRF_ESS | BRF_PRG }, // 2 + + { "bp947a.u20", 0x040000, 0xa4a36170, BRF_ESS | BRF_PRG }, // 3 Z80 Code + + { "bp947a.u49", 0x200000, 0x09749531, BRF_GRA }, // 4 Sprite data + { "bp947a.u50", 0x200000, 0x19cea8b2, BRF_GRA }, // 5 + { "bp947a.u51", 0x200000, 0xc19bed67, BRF_GRA }, // 6 + { "bp947a.u52", 0x200000, 0x70c64875, BRF_GRA }, // 7 + + { "bp947a.u48", 0x200000, 0x04ff6a3d, BRF_GRA }, // 8 Layer 0 Tile data + { "bp947a.u47", 0x200000, 0x0de42827, BRF_GRA }, // 9 Layer 2 Tile data + { "bp947a.u46", 0x200000, 0x0f9c906e, BRF_GRA }, // 10 Layer 2 Tile data + + { "bp947a.u42", 0x200000, 0x2ce8ff2a, BRF_SND }, // 11 MSM6295 #1 ADPCM data + { "bp947a.u37", 0x200000, 0xc3077c8f, BRF_SND }, // 12 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(metmqstr) +STD_ROM_FN(metmqstr) + +static struct BurnRomInfo nmasterRomDesc[] = { + { "bp947a_n.u25", 0x080000, 0x748cc514, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp947a.u28", 0x080000, 0x8c55decf, BRF_ESS | BRF_PRG }, // 1 + { "bp947a.u29", 0x080000, 0xcf0f3f3b, BRF_ESS | BRF_PRG }, // 2 + + { "bp947a.u20", 0x040000, 0xa4a36170, BRF_ESS | BRF_PRG }, // 3 Z80 Code + + { "bp947a.u49", 0x200000, 0x09749531, BRF_GRA }, // 4 Sprite data + { "bp947a.u50", 0x200000, 0x19cea8b2, BRF_GRA }, // 5 + { "bp947a.u51", 0x200000, 0xc19bed67, BRF_GRA }, // 6 + { "bp947a.u52", 0x200000, 0x70c64875, BRF_GRA }, // 7 + + { "bp947a.u48", 0x200000, 0x04ff6a3d, BRF_GRA }, // 8 Layer 0 Tile data + { "bp947a.u47", 0x200000, 0x0de42827, BRF_GRA }, // 9 Layer 2 Tile data + { "bp947a.u46", 0x200000, 0x0f9c906e, BRF_GRA }, // 10 Layer 2 Tile data + + { "bp947a.u42", 0x200000, 0x2ce8ff2a, BRF_SND }, // 11 MSM6295 #1 ADPCM data + { "bp947a.u37", 0x200000, 0xc3077c8f, BRF_SND }, // 12 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(nmaster) +STD_ROM_FN(nmaster) + +struct BurnDriver BurnDrvmetmqstr = { + "metmqstr", NULL, NULL, NULL, "1995", + "Metamoqester (International)\0", NULL, "Banpresto / Pandorabox", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, 0, + NULL, metmqstrRomInfo, metmqstrRomName, NULL, NULL, metmqstrInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvnmaster = { + "nmaster", "metmqstr", NULL, NULL, "1995", + "Oni - The Ninja Master (Japan)\0", NULL, "Banpresto / Pandorabox", "Cave", + L"\u7A4F\u5FCD - The Ninja Master (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, 0, + NULL, nmasterRomInfo, nmasterRomName, NULL, NULL, metmqstrInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 384, 240, 4, 3 +}; diff --git a/src/burn/drivers/cave/d_pwrinst2.cpp b/src/burn/drivers/cave/d_pwrinst2.cpp new file mode 100644 index 00000000..9699b1d1 --- /dev/null +++ b/src/burn/drivers/cave/d_pwrinst2.cpp @@ -0,0 +1,1212 @@ +// pwrinst2 +#include "cave.h" +#include "msm6295.h" +#include "burn_ym2203.h" +#include "bitswap.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *RomZ80; +static UINT8 *Ram01, *RamZ80; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesDone[2]; + +static INT32 SoundLatch; +static INT32 SoundLatchReply[48]; +static INT32 SoundLatchStatus; + +static INT32 SoundLatchReplyIndex; +static INT32 SoundLatchReplyMax; + +static UINT8 DrvZ80Bank; +static UINT8 DrvOkiBank1[4]; +static UINT8 DrvOkiBank2[4]; + +static struct BurnInputInfo pwrinst2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 10, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 10, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(pwrinst2) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall pwrinst2ReadByte(UINT32 sekAddress) +{ + if (sekAddress >= 0x600000 && sekAddress <= 0x6fffff) return 0; + + switch (sekAddress) { + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall pwrinst2WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + + } + } +} + +UINT16 __fastcall pwrinst2ReadWord(UINT32 sekAddress) +{ + if (sekAddress >= 0x600000 && sekAddress <= 0x6fffff) return 0; + + switch (sekAddress) { + case 0x500000: + return DrvInput[0] ^ 0xFFFF; + case 0x500002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + case 0xa80000: + case 0xa80002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0xa80004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0xa80006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xd80000: { + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + return 0; + } + return SoundLatchReply[SoundLatchReplyIndex++]; + } + + case 0xe80000: { + return ~8 + ((EEPROMRead() & 1) ? 8 : 0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall pwrinst2WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress >= 0xa8000a && sekAddress <= 0xa8007c) return; + if (sekAddress >= 0xa80004 && sekAddress <= 0xa80006) return; + + switch (sekAddress) { + case 0x700000: + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + + case 0xa80000: + nCaveXOffset = wordValue; + return; + case 0xa80002: + nCaveYOffset = wordValue; + return; + + case 0xa80008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0xb00000: + CaveTileReg[2][0] = wordValue; + break; + case 0xb00002: + CaveTileReg[2][1] = wordValue; + break; + case 0xb00004: { + switch (wordValue & 0x0f) { + case 1: wordValue = (wordValue & ~0x000f) | 0; break; + case 2: wordValue = (wordValue & ~0x000f) | 1; break; + case 4: wordValue = (wordValue & ~0x000f) | 2; break; + default: + case 8: wordValue = (wordValue & ~0x000f) | 3; break; + } + CaveTileReg[2][2] = wordValue; + break; + } + + case 0xb80000: + CaveTileReg[0][0] = wordValue; + break; + case 0xb80002: + CaveTileReg[0][1] = wordValue; + break; + case 0xb80004: { + switch (wordValue & 0x0f) { + case 1: wordValue = (wordValue & ~0x000f) | 0; break; + case 2: wordValue = (wordValue & ~0x000f) | 1; break; + case 4: wordValue = (wordValue & ~0x000f) | 2; break; + default: + case 8: wordValue = (wordValue & ~0x000f) | 3; break; + } + CaveTileReg[0][2] = wordValue; + break; + } + + case 0xc00000: + CaveTileReg[1][0] = wordValue; + break; + case 0xc00002: + CaveTileReg[1][1] = wordValue; + break; + case 0xc00004: { + switch (wordValue & 0x0f) { + case 1: wordValue = (wordValue & ~0x000f) | 0; break; + case 2: wordValue = (wordValue & ~0x000f) | 1; break; + case 4: wordValue = (wordValue & ~0x000f) | 2; break; + default: + case 8: wordValue = (wordValue & ~0x000f) | 3; break; + } + CaveTileReg[1][2] = wordValue; + break; + } + + case 0xc80000: + CaveTileReg[3][0] = wordValue; + break; + case 0xc80002: + CaveTileReg[3][1] = wordValue; + break; + case 0xc80004: { + switch (wordValue & 0x0f) { + case 1: wordValue = (wordValue & ~0x000f) | 0; break; + case 2: wordValue = (wordValue & ~0x000f) | 1; break; + case 4: wordValue = (wordValue & ~0x000f) | 2; break; + default: + case 8: wordValue = (wordValue & ~0x000f) | 3; break; + } + CaveTileReg[3][2] = wordValue; + break; + } + + case 0xe00000: { + SoundLatch = wordValue; + SoundLatchStatus |= 0x0C; + + ZetNmi(); +// nCyclesDone[1] += ZetRun(0x0400); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } + } +} + +UINT8 __fastcall pwrinst2ZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: { + return MSM6295ReadStatus(0); + } + + case 0x08: { + return MSM6295ReadStatus(1); + } + + case 0x40: { + return BurnYM2203Read(0, 0); + } + + case 0x41: { + return BurnYM2203Read(0, 1); + } + + case 0x60: { + SoundLatchStatus |= 0x08; + return SoundLatch >> 8; + } + + case 0x70: { + SoundLatchStatus |= 0x04; + return SoundLatch & 0xFF; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress); + } + } + + return 0; +} + +void __fastcall pwrinst2ZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: { + MSM6295Command(0, nValue); + return; + } + + case 0x08: { + MSM6295Command(1, nValue); + return; + } + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: { + INT32 Offset = nAddress - 0x10; + INT32 Chip = (Offset & 4) >> 2; + INT32 BankNum = Offset & 3; + UINT32 Address; + + if (Chip == 0) { + DrvOkiBank1[BankNum] = nValue; + Address = DrvOkiBank1[BankNum] * 0x10000; + MSM6295SampleData[0][BankNum] = MSM6295ROM + Address; + MSM6295SampleInfo[0][BankNum] = MSM6295ROM + Address + (BankNum << 8); + } + + if (Chip == 1) { + DrvOkiBank2[BankNum] = nValue; + Address = DrvOkiBank2[BankNum] * 0x10000; + MSM6295SampleData[1][BankNum] = MSM6295ROM + 0x400000 + Address; + MSM6295SampleInfo[1][BankNum] = MSM6295ROM + 0x400000 + Address + (BankNum << 8); + } + + return; + } + + case 0x40: { + BurnYM2203Write(0, 0, nValue); + return; + } + + case 0x41: { + BurnYM2203Write(0, 1, nValue); + return; + } + + case 0x50: { + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyMax = -1; + SoundLatchReplyIndex = 0; + } + SoundLatchReplyMax++; + SoundLatchReply[SoundLatchReplyMax] = nValue; + return; + } + + case 0x51: { + //??? + return; + } + + case 0x80: { + DrvZ80Bank = nValue & 0x07; + + ZetMapArea(0x8000, 0xbFFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x8000, 0xbFFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue); + } + } +} + +UINT8 __fastcall pwrinst2ZRead(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall pwrinst2ZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(0); + MSM6295Exit(1); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + ZetExit(); + + BurnYM2203Exit(); + + SoundLatch = 0; + DrvZ80Bank = 0; + DrvOkiBank1[0] = DrvOkiBank1[1] = DrvOkiBank1[2] = DrvOkiBank1[3] = 0; + DrvOkiBank2[0] = DrvOkiBank2[1] = DrvOkiBank2[2] = DrvOkiBank2[3] = 0; + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + SoundLatch = 0; + SoundLatchStatus = 0x0C; + + memset(SoundLatchReply, 0, sizeof(SoundLatchReply)); + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + + DrvZ80Bank = 0; + DrvOkiBank1[0] = DrvOkiBank1[1] = DrvOkiBank1[2] = DrvOkiBank1[3] = 0; + DrvOkiBank2[0] = DrvOkiBank2[1] = DrvOkiBank2[2] = DrvOkiBank2[3] = 0; + + MSM6295SampleInfo[0][0] = MSM6295ROM + 0x00000; + MSM6295SampleData[0][0] = MSM6295ROM + 0x00000; + MSM6295SampleInfo[0][1] = MSM6295ROM + 0x00100; + MSM6295SampleData[0][1] = MSM6295ROM + 0x10000; + MSM6295SampleInfo[0][2] = MSM6295ROM + 0x00200; + MSM6295SampleData[0][2] = MSM6295ROM + 0x20000; + MSM6295SampleInfo[0][3] = MSM6295ROM + 0x00300; + MSM6295SampleData[0][3] = MSM6295ROM + 0x30000; + + MSM6295SampleInfo[1][0] = MSM6295ROM + 0x400000; + MSM6295SampleData[1][0] = MSM6295ROM + 0x400000; + MSM6295SampleInfo[1][1] = MSM6295ROM + 0x400100; + MSM6295SampleData[1][1] = MSM6295ROM + 0x410000; + MSM6295SampleInfo[1][2] = MSM6295ROM + 0x400200; + MSM6295SampleData[1][2] = MSM6295ROM + 0x420000; + MSM6295SampleInfo[1][3] = MSM6295ROM + 0x400300; + MSM6295SampleData[1][3] = MSM6295ROM + 0x430000; + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x03E0) >> 2; // Red + r |= r >> 5; + g = (nColour & 0x7C00) >> 7; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)CavePalSrc, pd = CavePalette; i < 0x2800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static INT32 DrvDraw() +{ + CavePalUpdate4Bit(0, 128); + DrvCalcPalette(); + + CaveClearScreen(CavePalette[0x7f00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 11; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesTotal[1] = (INT32)(8000000 / CAVE_REFRESHRATE); + nCyclesDone[0] = nCyclesDone[1] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Run 68000 + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + +// CaveSpriteBuffer(); + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekClose(); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2203Update(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x300000; // 68K program + RomZ80 = Next; Next += 0x040000; + CaveSpriteROM = Next; Next += 0x1000000 * 2; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 + CaveTileROM[3] = Next; Next += 0x200000; // Tile layer 3 + MSM6295ROM = Next; Next += 0x800000; + RamStart = Next; + Ram01 = Next; Next += 0x028000; // CPU #0 work RAM + RamZ80 = Next; Next += 0x002000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008000; + CaveTileRAM[3] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x008000; + CavePalSrc = Next; Next += 0x005000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap2(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 LoadRoms() +{ + BurnLoadRom(Rom01 + 0x000001, 0, 2); + BurnLoadRom(Rom01 + 0x000000, 1, 2); + BurnLoadRom(Rom01 + 0x100001, 2, 2); + BurnLoadRom(Rom01 + 0x100000, 3, 2); + + BurnLoadRom(RomZ80, 4, 1); + + UINT8 *pTemp = (UINT8*)malloc(0xe00000); + BurnLoadRom(pTemp + 0x000000, 5, 1); + BurnLoadRom(pTemp + 0x200000, 6, 1); + BurnLoadRom(pTemp + 0x400000, 7, 1); + BurnLoadRom(pTemp + 0x600000, 8, 1); + BurnLoadRom(pTemp + 0x800000, 9, 1); + BurnLoadRom(pTemp + 0xa00000, 10, 1); + BurnLoadRom(pTemp + 0xc00000, 11, 1); + for (INT32 i = 0; i < 0xe00000; i++) { + INT32 j = BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7, 2,4,6,1,5,3, 0); + if (((j & 6) == 0) || ((j & 6) == 6)) j ^= 6; + CaveSpriteROM[j ^ 7] = (pTemp[i] >> 4) | (pTemp[i] << 4); + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + NibbleSwap1(CaveSpriteROM, 0xe00000); + + BurnLoadRom(CaveTileROM[0], 12, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 13, 1); + NibbleSwap2(CaveTileROM[1], 0x100000); + BurnLoadRom(CaveTileROM[2], 14, 1); + NibbleSwap2(CaveTileROM[2], 0x100000); + BurnLoadRom(CaveTileROM[3], 15, 1); + NibbleSwap2(CaveTileROM[3], 0x080000); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM + 0x000000, 16, 1); + BurnLoadRom(MSM6295ROM + 0x200000, 17, 1); + BurnLoadRom(MSM6295ROM + 0x400000, 18, 1); + BurnLoadRom(MSM6295ROM + 0x600000, 19, 1); + + return 0; +} + +static INT32 PlegendsLoadRoms() +{ + BurnLoadRom(Rom01 + 0x000001, 0, 2); + BurnLoadRom(Rom01 + 0x000000, 1, 2); + BurnLoadRom(Rom01 + 0x100001, 2, 2); + BurnLoadRom(Rom01 + 0x100000, 3, 2); + BurnLoadRom(Rom01 + 0x200001, 4, 2); + BurnLoadRom(Rom01 + 0x200000, 5, 2); + + BurnLoadRom(RomZ80, 6, 1); + + UINT8 *pTemp = (UINT8*)malloc(0x1000000); + BurnLoadRom(pTemp + 0x000000, 7, 1); + BurnLoadRom(pTemp + 0x200000, 8, 1); + BurnLoadRom(pTemp + 0x400000, 9, 1); + BurnLoadRom(pTemp + 0x600000, 10, 1); + BurnLoadRom(pTemp + 0x800000, 11, 1); + BurnLoadRom(pTemp + 0xa00000, 12, 1); + BurnLoadRom(pTemp + 0xc00000, 13, 1); + BurnLoadRom(pTemp + 0xe00000, 14, 1); + for (INT32 i = 0; i < 0x1000000; i++) { + INT32 j = BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7, 2,4,6,1,5,3, 0); + if (((j & 6) == 0) || ((j & 6) == 6)) j ^= 6; + CaveSpriteROM[j ^ 7] = (pTemp[i] >> 4) | (pTemp[i] << 4); + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + NibbleSwap1(CaveSpriteROM, 0x1000000); + + BurnLoadRom(CaveTileROM[0], 15, 1); + NibbleSwap2(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 16, 1); + NibbleSwap2(CaveTileROM[1], 0x200000); + BurnLoadRom(CaveTileROM[2], 17, 1); + NibbleSwap2(CaveTileROM[2], 0x200000); + BurnLoadRom(CaveTileROM[3], 18, 1); + NibbleSwap2(CaveTileROM[3], 0x080000); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM + 0x000000, 19, 1); + BurnLoadRom(MSM6295ROM + 0x200000, 20, 1); + BurnLoadRom(MSM6295ROM + 0x400000, 21, 1); + BurnLoadRom(MSM6295ROM + 0x600000, 22, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + SCAN_VAR(SoundLatch); + SCAN_VAR(DrvZ80Bank); + SCAN_VAR(DrvOkiBank1); + SCAN_VAR(DrvOkiBank2); + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbFFF, 0, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x8000, 0xbFFF, 2, RomZ80 + (DrvZ80Bank * 0x4000)); + ZetClose(); + +// memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000); +// memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000); + + CaveRecalcPalette = 1; + } + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 8000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 8000000; +} + +static INT32 drvZInit() +{ + ZetInit(1); + + ZetOpen(0); + + ZetSetInHandler(pwrinst2ZIn); + ZetSetOutHandler(pwrinst2ZOut); + ZetSetReadHandler(pwrinst2ZRead); + ZetSetWriteHandler(pwrinst2ZWrite); + + // ROM bank 1 + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x8000, 0xbFFF, 0, RomZ80 + 0x8000); // Direct Read from ROM + ZetMapArea (0x8000, 0xbFFF, 2, RomZ80 + 0x8000); // + // RAM + ZetMapArea (0xE000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xE000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xE000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x800000, 0x807FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x880000, 0x887FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM); + SekMapMemory(CaveTileRAM[3] + 0x4000, 0x980000, 0x983FFF, SM_RAM); + SekMapMemory(CaveTileRAM[3] + 0x4000, 0x984000, 0x987FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0xa00000, 0xa07FFF, SM_RAM); + SekMapMemory(Ram01 + 0x10000, 0xa08000, 0xa1FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0xf00000, 0xf04FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, pwrinst2ReadWord); + SekSetWriteWordHandler(0, pwrinst2WriteWord); + SekSetReadByteHandler(0, pwrinst2ReadByte); + SekSetWriteByteHandler(0, pwrinst2WriteByte); + SekClose(); + } + + drvZInit(); + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(3, 0x0e00000 * 2); + CaveTileInitLayer(0, 0x400000, 4, 0x0800); + CaveTileInitLayer(1, 0x200000, 4, 0x1000); + CaveTileInitLayer(2, 0x200000, 4, 0x1800); + CaveTileInitLayer(3, 0x100000, 4, 0x2000); + + nCaveExtraXOffset = -112; + nCaveExtraYOffset = 1; + + BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(8000000); + + MSM6295Init(0, 3000000 / 165, 50.0, 1); + MSM6295Init(1, 3000000 / 165, 50.0, 1); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "pwrinst2")) { + UINT16 *rom = (UINT16 *)Rom01; + rom[0xD46C/2] = 0xD482; // kurara dash fix 0xd400 -> 0xd482 + } + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +static INT32 PlegendsInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + + // Load the roms into memory + if (PlegendsLoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(Rom01 + 0x200000, 0x600000, 0x6FFFFF, SM_ROM); + SekMapMemory(CaveTileRAM[2], 0x800000, 0x807FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x880000, 0x887FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM); + SekMapMemory(CaveTileRAM[3] + 0x4000, 0x980000, 0x983FFF, SM_RAM); + SekMapMemory(CaveTileRAM[3] + 0x4000, 0x984000, 0x987FFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0xa00000, 0xa07FFF, SM_RAM); + SekMapMemory(Ram01 + 0x10000, 0xa08000, 0xa1FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0xf00000, 0xf04FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, pwrinst2ReadWord); + SekSetWriteWordHandler(0, pwrinst2WriteWord); + SekSetReadByteHandler(0, pwrinst2ReadByte); + SekSetWriteByteHandler(0, pwrinst2WriteByte); + SekClose(); + } + + drvZInit(); + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(3, 0x01000000 * 2); + CaveTileInitLayer(0, 0x400000, 4, 0x0800); + CaveTileInitLayer(1, 0x400000, 4, 0x1000); + CaveTileInitLayer(2, 0x400000, 4, 0x1800); + CaveTileInitLayer(3, 0x100000, 4, 0x2000); + + nCaveExtraXOffset = -112; + nCaveExtraYOffset = 1; + + BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(8000000); + + MSM6295Init(0, 3000000 / 165, 50.0, 1); + MSM6295Init(1, 3000000 / 165, 50.0, 1); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo pwrinst2RomDesc[] = { + { "g02.u45", 0x080000, 0x7b33bc43, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "g02.u44", 0x080000, 0x8f6f6637, BRF_ESS | BRF_PRG }, // 1 + { "g02.u43", 0x080000, 0x178e3d24, BRF_ESS | BRF_PRG }, // 2 + { "g02.u42", 0x080000, 0xa0b4ee99, BRF_ESS | BRF_PRG }, // 3 + + { "g02.u3a", 0x020000, 0xebea5e1e, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "g02.u61", 0x200000, 0x91e30398, BRF_GRA }, // 5 Sprite data + { "g02.u62", 0x200000, 0xd9455dd7, BRF_GRA }, // 6 + { "g02.u63", 0x200000, 0x4d20560b, BRF_GRA }, // 7 + { "g02.u64", 0x200000, 0xb17b9b6e, BRF_GRA }, // 8 + { "g02.u65", 0x200000, 0x08541878, BRF_GRA }, // 9 + { "g02.u66", 0x200000, 0xbecf2a36, BRF_GRA }, // 10 + { "g02.u67", 0x200000, 0x52fe2b8b, BRF_GRA }, // 11 + + { "g02.u78", 0x200000, 0x1eca63d2, BRF_GRA }, // 12 Layer 0 Tile data + { "g02.u81", 0x100000, 0x8a3ff685, BRF_GRA }, // 13 Layer 1 Tile data + { "g02.u89", 0x100000, 0x373e1f73, BRF_GRA }, // 14 Layer 2 Tile data + { "g02.82a", 0x080000, 0x4b3567d6, BRF_GRA }, // 15 Layer 3 Tile data + + { "g02.u53", 0x200000, 0xc4bdd9e0, BRF_SND }, // 16 MSM6295 #1 ADPCM data + { "g02.u54", 0x200000, 0x1357d50e, BRF_SND }, // 17 + { "g02.u55", 0x200000, 0x2d102898, BRF_SND }, // 18 MSM6295 #2 ADPCM data + { "g02.u56", 0x200000, 0x9ff50dda, BRF_SND }, // 19 +}; + + +STD_ROM_PICK(pwrinst2) +STD_ROM_FN(pwrinst2) + +static struct BurnRomInfo pwrinst2jRomDesc[] = { + { "g02j.u45", 0x080000, 0x42d0abd7, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "g02j.u44", 0x080000, 0x362b7af3, BRF_ESS | BRF_PRG }, // 1 + { "g02j.u43", 0x080000, 0xc94c596b, BRF_ESS | BRF_PRG }, // 2 + { "g02j.u42", 0x080000, 0x4f4c8270, BRF_ESS | BRF_PRG }, // 3 + + { "g02j.u3a", 0x020000, 0xeead01f1, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "g02.u61", 0x200000, 0x91e30398, BRF_GRA }, // 5 Sprite data + { "g02.u62", 0x200000, 0xd9455dd7, BRF_GRA }, // 6 + { "g02.u63", 0x200000, 0x4d20560b, BRF_GRA }, // 7 + { "g02.u64", 0x200000, 0xb17b9b6e, BRF_GRA }, // 8 + { "g02.u65", 0x200000, 0x08541878, BRF_GRA }, // 9 + { "g02.u66", 0x200000, 0xbecf2a36, BRF_GRA }, // 10 + { "g02.u67", 0x200000, 0x52fe2b8b, BRF_GRA }, // 11 + + { "g02.u78", 0x200000, 0x1eca63d2, BRF_GRA }, // 12 Layer 0 Tile data + { "g02.u81", 0x100000, 0x8a3ff685, BRF_GRA }, // 13 Layer 1 Tile data + { "g02.u89", 0x100000, 0x373e1f73, BRF_GRA }, // 14 Layer 2 Tile data + { "g02j.82a", 0x080000, 0x3be86fe1, BRF_GRA }, // 15 Layer 3 Tile data + + { "g02.u53", 0x200000, 0xc4bdd9e0, BRF_SND }, // 16 MSM6295 #1 ADPCM data + { "g02.u54", 0x200000, 0x1357d50e, BRF_SND }, // 17 + { "g02.u55", 0x200000, 0x2d102898, BRF_SND }, // 18 MSM6295 #2 ADPCM data + { "g02.u56", 0x200000, 0x9ff50dda, BRF_SND }, // 19 +}; + + +STD_ROM_PICK(pwrinst2j) +STD_ROM_FN(pwrinst2j) + +static struct BurnRomInfo plegendsRomDesc[] = { + { "d12.u45", 0x080000, 0xed8a2e3d, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "d13.u44", 0x080000, 0x25821731, BRF_ESS | BRF_PRG }, // 1 + { "d14.u2", 0x080000, 0xc2cb1402, BRF_ESS | BRF_PRG }, // 2 + { "d16.u3", 0x080000, 0x50a1c63e, BRF_ESS | BRF_PRG }, // 3 + { "d15.u4", 0x080000, 0x6352cec0, BRF_ESS | BRF_PRG }, // 4 + { "d17.u5", 0x080000, 0x7af810d8, BRF_ESS | BRF_PRG }, // 5 + + { "d19.u3", 0x040000, 0x47598459, BRF_ESS | BRF_PRG }, // 6 Z80 Code + + { "g02.u61", 0x200000, 0x91e30398, BRF_GRA }, // 7 Sprite data + { "g02.u62", 0x200000, 0xd9455dd7, BRF_GRA }, // 8 + { "g02.u63", 0x200000, 0x4d20560b, BRF_GRA }, // 9 + { "g02.u64", 0x200000, 0xb17b9b6e, BRF_GRA }, // 10 + { "g02.u65", 0x200000, 0x08541878, BRF_GRA }, // 11 + { "g02.u66", 0x200000, 0xbecf2a36, BRF_GRA }, // 12 + { "atgs.u1", 0x200000, 0xaa6f34a9, BRF_GRA }, // 13 + { "atgs.u2", 0x200000, 0x553eda27, BRF_GRA }, // 14 + + { "atgs.u78", 0x200000, 0x16710ecb, BRF_GRA }, // 15 Layer 0 Tile data + { "atgs.u81", 0x200000, 0xcb2aca91, BRF_GRA }, // 16 Layer 1 Tile data + { "atgs.u89", 0x200000, 0x65f45a0f, BRF_GRA }, // 17 Layer 2 Tile data + { "text.u82", 0x080000, 0xf57333ea, BRF_GRA }, // 18 Layer 3 Tile data + + { "g02.u53", 0x200000, 0xc4bdd9e0, BRF_SND }, // 19 MSM6295 #1 ADPCM data + { "g02.u54", 0x200000, 0x1357d50e, BRF_SND }, // 20 + { "g02.u55", 0x200000, 0x2d102898, BRF_SND }, // 21 MSM6295 #2 ADPCM data + { "g02.u56", 0x200000, 0x9ff50dda, BRF_SND }, // 22 +}; + + +STD_ROM_PICK(plegends) +STD_ROM_FN(plegends) + +static struct BurnRomInfo plegendsjRomDesc[] = { + { "prog.u45", 0x080000, 0x94f53db2, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "prog.u44", 0x080000, 0xdb0ad756, BRF_ESS | BRF_PRG }, // 1 + { "pr12.u2", 0x080000, 0x0e202559, BRF_ESS | BRF_PRG }, // 2 + { "pr12.u3", 0x080000, 0x54742f21, BRF_ESS | BRF_PRG }, // 3 + { "d15.u4", 0x080000, 0x6352cec0, BRF_ESS | BRF_PRG }, // 4 + { "d17.u5", 0x080000, 0x7af810d8, BRF_ESS | BRF_PRG }, // 5 + + { "sound.u3", 0x020000, 0x36f71520, BRF_ESS | BRF_PRG }, // 6 Z80 Code + + { "g02.u61", 0x200000, 0x91e30398, BRF_GRA }, // 7 Sprite data + { "g02.u62", 0x200000, 0xd9455dd7, BRF_GRA }, // 8 + { "g02.u63", 0x200000, 0x4d20560b, BRF_GRA }, // 9 + { "g02.u64", 0x200000, 0xb17b9b6e, BRF_GRA }, // 10 + { "g02.u65", 0x200000, 0x08541878, BRF_GRA }, // 11 + { "g02.u66", 0x200000, 0xbecf2a36, BRF_GRA }, // 12 + { "atgs.u1", 0x200000, 0xaa6f34a9, BRF_GRA }, // 13 + { "atgs.u2", 0x200000, 0x553eda27, BRF_GRA }, // 14 + + { "atgs.u78", 0x200000, 0x16710ecb, BRF_GRA }, // 15 Layer 0 Tile data + { "atgs.u81", 0x200000, 0xcb2aca91, BRF_GRA }, // 16 Layer 1 Tile data + { "atgs.u89", 0x200000, 0x65f45a0f, BRF_GRA }, // 17 Layer 2 Tile data + { "text.u82", 0x080000, 0xf57333ea, BRF_GRA }, // 18 Layer 3 Tile data + + { "g02.u53", 0x200000, 0xc4bdd9e0, BRF_SND }, // 19 MSM6295 #1 ADPCM data + { "g02.u54", 0x200000, 0x1357d50e, BRF_SND }, // 20 + { "g02.u55", 0x200000, 0x2d102898, BRF_SND }, // 21 MSM6295 #2 ADPCM data + { "g02.u56", 0x200000, 0x9ff50dda, BRF_SND }, // 22 +}; + + +STD_ROM_PICK(plegendsj) +STD_ROM_FN(plegendsj) + +struct BurnDriver BurnDrvPwrinst2 = { + "pwrinst2", NULL, NULL, NULL, "1994", + "Power Instinct 2 (USA, ver. 94/04/08)\0", "Bad Music from first MSM6295", "Atlus", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, FBF_PWRINST, + NULL, pwrinst2RomInfo, pwrinst2RomName, NULL, NULL, pwrinst2InputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPwrinst2j = { + "pwrinst2j", "pwrinst2", NULL, NULL, "1994", + "Gouketsuji Ichizoku 2 (Japan, ver. 94/04/08)\0", NULL, "Atlus", "Cave", + L"\u8C6A\u8840\u5BFA\u4E00\u65CF \uFF12 (Japan, ver. 94/04/08)\0Gouketsuji Ichizoku 2\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, FBF_PWRINST, + NULL, pwrinst2jRomInfo, pwrinst2jRomName, NULL, NULL, pwrinst2InputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPlegends = { + "plegends", NULL, NULL, NULL, "1995", + "Gouketsuji Gaiden Legends (USA, ver. 95/06/20)\0", NULL, "Atlus / KM International", "Cave", + L"\u8C6A\u8840\u5BFA\u5916\u4F1D Gogetsuji Legends (USA, ver. 95/06/20)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, FBF_PWRINST, + NULL, plegendsRomInfo, plegendsRomName, NULL, NULL, pwrinst2InputInfo, NULL, + PlegendsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPlegendsj = { + "plegendsj", "plegends", NULL, NULL, "1995", + "Gouketsuji Gaiden Saikyou Densetsu (Japan, ver. 95/06/20)\0", NULL, "Atlus", "Cave", + L"\u8C6A\u8840\u5BFA\u5916\u4F1D Gogetsuji \u6700\u5F37\u4F1D\u8AAC (Japan, ver. 95/06/20)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, FBF_PWRINST, + NULL, plegendsjRomInfo, plegendsjRomName, NULL, NULL, pwrinst2InputInfo, NULL, + PlegendsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/cave/d_sailormn.cpp b/src/burn/drivers/cave/d_sailormn.cpp new file mode 100644 index 00000000..946522b7 --- /dev/null +++ b/src/burn/drivers/cave/d_sailormn.cpp @@ -0,0 +1,1696 @@ +// Pretty Soldier Sailor Moon & Air Gallet +#include "cave.h" +#include "msm6295.h" +#include "burn_ym2151.h" + +#include "bitswap.h" + +#define CAVE_VBLANK_LINES (271.5 - 240) +// #define CAVE_VBLANK_LINES (12) + +static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *Rom02, *RomZ80; +static UINT8 *Ram01, *Ram02, *Ram03, *RamZ80; +static UINT8 *DefEEPROM; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static INT8 nVBlank; + +static INT32 nCurrentBank; + +static INT32 SoundLatch; +static INT32 SoundLatchReply[48]; +static INT32 SoundLatchStatus; + +static INT32 SoundLatchReplyIndex; +static INT32 SoundLatchReplyMax; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT32 nCaveCyclesDone[2]; + +INT32 nWhichGame; // 0 - sailormn/sailormno + // 1 - agallet + +static struct BurnInputInfo sailormnInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(sailormn) + +static void UpdateIRQStatus() +{ + INT32 nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +static void drvZ80Bankswitch(INT32 nBank) +{ + nBank &= 0x1F; + if (nBank != nCurrentBank) { + UINT8* nStartAddress = RomZ80 + (nBank << 14); + ZetMapArea(0x4000, 0x7FFF, 0, nStartAddress); + ZetMapArea(0x4000, 0x7FFF, 2, nStartAddress); + nCurrentBank = nBank; + } +} + +static void drvYM2151IRQHandler(INT32 nStatus) +{ + if (nStatus) { +// ZetRaiseIrq(255); +// nCaveCyclesDone[1] += ZetRun(0x0400); + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +UINT8 __fastcall sailormnZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x20: { +// bprintf(PRINT_NORMAL, "Z80 read thingie.\n"); +// int nStatus = SoundLatchStatus; +// SoundLatchStatus &= ~2; +// return nStatus; + + return 0; + } + + case 0x30: +// bprintf(PRINT_NORMAL, "Z80 read soundlatch(lo)\n"); + SoundLatchStatus |= 0x04; + return SoundLatch & 0xFF; + + case 0x40: +// bprintf(PRINT_NORMAL, "Z80 read soundlatch(hi)\n"); + SoundLatchStatus |= 0x08; + return SoundLatch >> 8; + + case 0x51: +// bprintf(PRINT_NORMAL, "YM2151 status read.\n"); + return BurnYM2151ReadStatus(); + case 0x60: +// bprintf(PRINT_NORMAL, "MSM6295 #0 status read.\n"); + return MSM6295ReadStatus(0); + case 0x80: +// bprintf(PRINT_NORMAL, "MSM6295 #1 status read.\n"); + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall sailormnZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + + case 0x00: + drvZ80Bankswitch(nValue); + break; + + case 0x10: +// SoundLatchStatus |= 0x02; +// SoundLatchReply = nValue; + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyMax = -1; + SoundLatchReplyIndex = 0; + } + SoundLatchReplyMax++; + SoundLatchReply[SoundLatchReplyMax] = nValue; + break; + + case 0x50: + BurnYM2151SelectRegister(nValue); + break; + case 0x51: +// bprintf(PRINT_NORMAL, "YM2151 reg %02X -> %02X\n", CaveCurrentYM2151Register, nValue); + BurnYM2151WriteRegister(nValue); + break; + + case 0x60: +// bprintf(PRINT_NORMAL, "MSM6295 #0 command sent.\n"); + MSM6295Command(0, nValue); + break; + case 0x70: + MSM6295SampleInfo[0][0] = MSM6295ROM + ((nValue & 0x0F) << 17); + MSM6295SampleInfo[0][1] = MSM6295ROM + ((nValue & 0x0F) << 17) + 0x0100; + MSM6295SampleInfo[0][2] = MSM6295ROM + ((nValue & 0x0F) << 17) + 0x0200; + MSM6295SampleInfo[0][3] = MSM6295ROM + ((nValue & 0x0F) << 17) + 0x0300; + MSM6295SampleData[0][0] = MSM6295ROM + ((nValue & 0x0F) << 17); + MSM6295SampleData[0][1] = MSM6295ROM + ((nValue & 0x0F) << 17) + 0x010000; + MSM6295SampleData[0][2] = MSM6295ROM + ((nValue & 0xF0) << 13); + MSM6295SampleData[0][3] = MSM6295ROM + ((nValue & 0xF0) << 13) + 0x010000; + break; + + case 0x80: +// bprintf(PRINT_NORMAL, "MSM6295 #1 command sent.\n"); + MSM6295Command(1, nValue); + break; + case 0xC0: + MSM6295SampleInfo[1][0] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17); + MSM6295SampleInfo[1][1] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17) + 0x0100; + MSM6295SampleInfo[1][2] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17) + 0x0200; + MSM6295SampleInfo[1][3] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17) + 0x0300; + MSM6295SampleData[1][0] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17); + MSM6295SampleData[1][1] = MSM6295ROM + 0x0200000 + ((nValue & 0x0F) << 17) + 0x010000; + MSM6295SampleData[1][2] = MSM6295ROM + 0x0200000 + ((nValue & 0xF0) << 13); + MSM6295SampleData[1][3] = MSM6295ROM + 0x0200000 + ((nValue & 0xF0) << 13) + 0x010000; + break; + } +} + +static INT32 drvZInit() +{ + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(sailormnZIn); + ZetSetOutHandler(sailormnZOut); + + // ROM bank 1 + ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x0000); // + // RAM + ZetMapArea (0xC000, 0xDFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xC000, 0xDFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xC000, 0xDFFF, 2, RamZ80); // + // RAM mirror + ZetMapArea (0xE000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xE000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xE000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + ZetClose(); + + return 0; +} + +UINT8 __fastcall sailormnReadByte(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + + switch (sekAddress) { + case 0xB80000: + case 0xB80001: { + UINT8 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xB80002: + case 0xB80003: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xB80004: + case 0xB80005: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0xB80006: + case 0xB80007: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x600000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0x600001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0x600002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0x600003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + +#if 0 + case 0xB8006C: + case 0xB8006D: + bprintf(PRINT_NORMAL, "Soundlatch status read (byte).\n"); +// return SoundLatchStatus & 3; + return 0; + case 0xB8006E: + case 0xB8006F: + bprintf(PRINT_NORMAL, "Sound latch read (byte).\n"); +// SoundLatchStatus = 2; +// return SoundLatchReply; + return 0; +#endif + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall sailormnReadWord(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + + switch (sekAddress) { + case 0xB80000: { + UINT16 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xB80002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0xB80004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0xB80006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0xB8006C: +// SoundLatchStatus &= ~4; +// return SoundLatchStatus & 3; + + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + return 2; + } + return 0; + + case 0xB8006E: +// bprintf(PRINT_NORMAL, "Sound latch read.\n"); +// SoundLatchStatus = 2; +// return SoundLatchReply; + + if (SoundLatchReplyIndex > SoundLatchReplyMax) { + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + return 0; + } +// bprintf(PRINT_NORMAL, "Sound latch reply read (%02X).\n", SoundLatchReply[SoundLatchReplyIndex]); + return SoundLatchReply[SoundLatchReplyIndex++]; + + case 0x600000: + return DrvInput[0] ^ 0xFFFF; + case 0x600002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall sailormnWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + + switch (sekAddress) { +// case 0xB8006E: +// SoundLatch &= 0xFF00; +// SoundLatch |= byteValue << 8; +// break; +// case 0xB8006F: +// SoundLatch &= 0x00FF; +// SoundLatch |= byteValue; +// break; + + case 0x700000: + nCaveTileBank = byteValue & 1; + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + return; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall sailormnWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + switch (sekAddress) { + case 0xA00000: + CaveTileReg[0][0] = wordValue; + return; + case 0xA00002: + CaveTileReg[0][1] = wordValue; + return; + case 0xA00004: + CaveTileReg[0][2] = wordValue; + return; + + case 0xA80000: + CaveTileReg[1][0] = wordValue; + return; + case 0xA80002: + CaveTileReg[1][1] = wordValue; + return; + case 0xA80004: + CaveTileReg[1][2] = wordValue; + return; + + case 0xB00000: + CaveTileReg[2][0] = wordValue; + return; + case 0xB00002: + CaveTileReg[2][1] = wordValue; + return; + case 0xB00004: + CaveTileReg[2][2] = wordValue; + return; + + case 0xB80000: + nCaveXOffset = wordValue; + return; + case 0xB80002: + nCaveYOffset = wordValue; + return; + case 0xB80008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0xB8006E: +// bprintf(PRINT_NORMAL, "Sound command sent: %04X\n", wordValue); + + SoundLatch = wordValue; + SoundLatchStatus |= 0x0C; + + ZetNmi(); + nCaveCyclesDone[1] += ZetRun(0x0400); + return; + + case 0x700000: + wordValue >>= 8; + nCaveTileBank = wordValue & 1; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + return; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +void __fastcall sailormnWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall sailormnWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(1); + MSM6295Exit(0); + BurnYM2151Exit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + ZetExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + nCurrentBank = -1; + drvZ80Bankswitch(0); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + SoundLatch = 0; + SoundLatchStatus = 0x0C; + + memset(SoundLatchReply, 0, sizeof(SoundLatchReply)); + SoundLatchReplyIndex = 0; + SoundLatchReplyMax = -1; + + nCaveCyclesDone[0] = nCaveCyclesDone[1] = 0; + + MSM6295Reset(0); + MSM6295Reset(1); + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvDraw() +{ + if (CaveRecalcPalette) { + CavePalUpdate8Bit(0x4400, 12); + CaveRecalcPalette = 1; + } + CavePalUpdate4Bit(0, 64); + + CaveClearScreen(CavePalette[nWhichGame ? 0x3F00 : 0x5FF0]); + + if (bDrawScreen) { +// CaveGetBitmap(); + +#if 0 + CaveTileRender(1); +#else + if (nWhichGame) { + // Air Gallet always enables row-scroll and row-select for 16x16 layers, but always without effect + // So, force tile drawing routines to ignore row-scroll and row-select + CaveTileRender(0); + } else { + CaveTileRender(1); + } +#endif + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 4; + + INT32 nCyclesTotal[2]; + + INT32 nCyclesSegment; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 10; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCaveCyclesDone[0] = 0; +#if 0 + nCyclesTotal[1] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); +#else + nCyclesTotal[1] = (INT32)(8000000 / CAVE_REFRESHRATE); +#endif + nCaveCyclesDone[1] -= nCyclesTotal[1]; + if (nCaveCyclesDone[1] < 0) { + nCaveCyclesDone[1] = 0; + } + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + nVBlank = 0; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!nVBlank && nNext > nCyclesVBlank) { + if (nCaveCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCaveCyclesDone[nCurrentCPU]; + nCaveCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + +// CaveSpriteBuffer(); + + nVBlank = 1; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCaveCyclesDone[nCurrentCPU]; + if (nVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCaveCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCaveCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCaveCyclesDone[nCurrentCPU]; + nCaveCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + } + + SekClose(); + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + } + + ZetClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68K program + Rom02 = Next; Next += 0x200000; + RomZ80 = Next; Next += 0x080000; + CaveSpriteROM = Next; Next += 0x800000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1 + if (nWhichGame) { + CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2 (agallet) + } else { + CaveTileROM[2] = Next; Next += 0x01400000; // Tile layer 2 (Sailor Moon) + } + MSM6295ROM = Next; Next += 0x400000; // MSM6295 ADPCM data + DefEEPROM = Next; Next += 0x000080; + RamStart = Next; + Ram01 = Next; Next += 0x010002; // CPU #0 work RAM + Ram02 = Next; Next += 0x008000; // + Ram03 = Next; Next += 0x004002; // + RamZ80 = Next; Next += 0x002000; + CaveTileRAM[0] = Next; Next += 0x008000; + CaveTileRAM[1] = Next; Next += 0x008000; + CaveTileRAM[2] = Next; Next += 0x008002; + CaveSpriteRAM = Next; Next += 0x010002; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void sailormnDecodeSprites(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void sailormnDecodeTiles(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[1] = *pOrg & 15; + pDest[0] = *pOrg >> 4; + } + + return; +} + +static INT32 sailormnLoadRoms() +{ + UINT8* pTemp; + + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + BurnLoadRom(Rom02, 1, 1); + + // Load Z80 ROM + BurnLoadRom(RomZ80, 2, 1); + + pTemp = (UINT8*)malloc(0x400000); + BurnLoadRom(pTemp + 0x000000, 3, 1); + BurnLoadRom(pTemp + 0x200000, 4, 1); + for (INT32 i = 0; i < 0x400000; i++) { + CaveSpriteROM[i ^ 0x950C4] = pTemp[BITSWAP24(i, 23, 22, 21, 20, 15, 10, 12, 6, 11, 1, 13, 3, 16, 17, 2, 5, 14, 7, 18, 8, 4, 19, 9, 0)]; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + sailormnDecodeSprites(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0], 5, 1); + sailormnDecodeTiles(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 6, 1); + sailormnDecodeTiles(CaveTileROM[1], 0x200000); + BurnLoadRom(CaveTileROM[2] + 0x000000, 7, 1); + BurnLoadRom(CaveTileROM[2] + 0x200000, 8, 1); + BurnLoadRom(CaveTileROM[2] + 0x400000, 9, 1); + BurnLoadRom(CaveTileROM[2] + 0x600000, 10, 1); + BurnLoadRom(CaveTileROM[2] + 0x800000, 11, 1); + sailormnDecodeTiles(CaveTileROM[2], 0xA00000); + + pTemp = (UINT8*)malloc(0x600000); + BurnLoadRom(pTemp + 0x000000, 12, 1); + BurnLoadRom(pTemp + 0x200000, 13, 1); + BurnLoadRom(pTemp + 0x400000, 14, 1); + for (INT32 i = 0; i < 0x500000; i++) { + CaveTileROM[2][(i << 2) + 0] |= (pTemp[i] & 0x03) << 4; + CaveTileROM[2][(i << 2) + 1] |= (pTemp[i] & 0x0C) << 2; + CaveTileROM[2][(i << 2) + 2] |= (pTemp[i] & 0x30); + CaveTileROM[2][(i << 2) + 3] |= (pTemp[i] & 0xC0) >> 2; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + // Load OKIM6295 data + BurnLoadRom(MSM6295ROM + 0x0000000, 15, 1); + BurnLoadRom(MSM6295ROM + 0x0200000, 16, 1); + BurnLoadRom(MSM6295ROM + 0x0280000, 16, 1); + BurnLoadRom(MSM6295ROM + 0x0300000, 16, 1); + BurnLoadRom(MSM6295ROM + 0x0380000, 16, 1); + + BurnLoadRom(DefEEPROM, 17, 1); + + return 0; +} + +static INT32 agalletLoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load Z80 ROM + BurnLoadRom(RomZ80, 1, 1); + + BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1); + BurnLoadRom(CaveSpriteROM + 0x200000, 3, 1); + sailormnDecodeSprites(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0], 4, 1); + sailormnDecodeTiles(CaveTileROM[0], 0x200000); + BurnLoadRom(CaveTileROM[1], 5, 1); + sailormnDecodeTiles(CaveTileROM[1], 0x200000); + BurnLoadRom(CaveTileROM[2], 6, 1); + sailormnDecodeTiles(CaveTileROM[2], 0x200000); + + UINT8* pTemp = (UINT8*)malloc(0x200000); + BurnLoadRom(pTemp, 7, 1); + for (INT32 i = 0; i < 0x0100000; i++) { + CaveTileROM[2][(i << 2) + 0] |= (pTemp[i] & 0x03) << 4; + CaveTileROM[2][(i << 2) + 1] |= (pTemp[i] & 0x0C) << 2; + CaveTileROM[2][(i << 2) + 2] |= (pTemp[i] & 0x30); + CaveTileROM[2][(i << 2) + 3] |= (pTemp[i] & 0xC0) >> 2; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + // Load OKIM6295 data + BurnLoadRom(MSM6295ROM + 0x0000000, 8, 1); + BurnLoadRom(MSM6295ROM + 0x0200000, 9, 1); + + BurnLoadRom(DefEEPROM, 10, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 + ZetScan(nAction); // scan Z80 + + SCAN_VAR(SoundLatch); + SCAN_VAR(SoundLatchStatus); + SCAN_VAR(SoundLatchReply); + SCAN_VAR(SoundLatchReplyIndex); + SCAN_VAR(SoundLatchReplyMax); + + SCAN_VAR(nCurrentBank); + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + BurnYM2151Scan(nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(nVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + + if (nAction & ACB_WRITE) { + INT32 nBank = nCurrentBank; + nCurrentBank = -1; + drvZ80Bankswitch(nBank); + + CaveRecalcPalette = 1; + } + } + + return 0; +} + +static const UINT8 agallet_default_eeprom[48] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff}; +static const UINT8 sailormn_default_eeprom[18] = {0xa5,0x00,0xa5,0x00,0xa5,0x00,0xa5,0x00,0xa5,0x01,0xa5,0x01,0xa5,0x04,0xa5,0x01,0xa5,0x02}; + +static INT32 gameInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + + + if (nWhichGame) { + // Load the roms into memory + if (agalletLoadRoms()) { + return 1; + } + } else { + // Load the roms into memory + if (sailormnLoadRoms()) { + return 1; + } + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x110001, SM_RAM); // ram (Air Gallet tests too far) + SekMapMemory(Rom02, 0x200000, 0x3FFFFF, SM_ROM); + SekMapMemory(Ram02, 0x400000, 0x407FFF, SM_RAM); + SekMapMemory(Ram03, 0x40C000, 0x410001, SM_RAM); // RAM (Air Gallet tests too far) + SekMapMemory(CaveSpriteRAM, 0x500000, 0x510001, SM_RAM); // Sprite RAM (Air Gallet tests too far) + SekMapMemory(CaveTileRAM[0], 0x800000, 0x807FFF, SM_RAM); + SekMapMemory(CaveTileRAM[1], 0x880000, 0x887FFF, SM_RAM); + SekMapMemory(CaveTileRAM[2], 0x900000, 0x908001, SM_RAM); // Air Gallet tests too far + + SekMapMemory(CavePalSrc, 0x408000, 0x4087FF, SM_RAM); // Palette RAM + SekMapMemory(CavePalSrc + 0x8800, 0x408800, 0x40BFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0x408800, 0x40BFFF, SM_WRITE); // + + SekSetReadWordHandler(0, sailormnReadWord); + SekSetReadByteHandler(0, sailormnReadByte); + SekSetWriteWordHandler(0, sailormnWriteWord); + SekSetWriteByteHandler(0, sailormnWriteByte); + + SekSetWriteWordHandler(1, sailormnWriteWordPalette); + SekSetWriteByteHandler(1, sailormnWriteBytePalette); + + SekClose(); + } + + drvZInit(); + + nCaveExtraXOffset = -1; + nCaveRowModeOffset = 2; + + CavePalInit(0x8000); + CaveTileInit(); + if (nWhichGame) { + CaveSpriteInit(1, 0x0800000); + } else { + CaveSpriteInit(2, 0x0800000); + } + CaveTileInitLayer(0, 0x400000, 4, 0x4400); + CaveTileInitLayer(1, 0x400000, 4, 0x4800); + if (nWhichGame) { + CaveTileInitLayer(2, 0x400000, 6, 0x4C00); + } else { + CaveTileInitLayer(2, 0x01400000, 6, 0x4C00); + } + + BurnYM2151Init(32000000 / 8, 25.0); + BurnYM2151SetIrqHandler(&drvYM2151IRQHandler); + + MSM6295Init(0, 16000, 80.0, 1); + MSM6295Init(1, 16000, 80.0, 1); + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(DefEEPROM,0, 0x80); + + bDrawScreen = true; + +#if 0 +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, " * Using speed-hacks (detecting idle loops).\n"); +#endif +#endif + + DrvDoReset(); + + return 0; +} + +static INT32 sailormnInit() +{ + nWhichGame = 0; + return gameInit(); +} + +static INT32 agalletInit() +{ + nWhichGame = 1; + return gameInit(); +} + +// Rom information + +static struct BurnRomInfo sailormnRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_europe.nv", 0x0080, 0x59a7dc50, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormn) +STD_ROM_FN(sailormn) + +static struct BurnRomInfo sailormnuRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_usa.nv", 0x0080, 0x3915abe3, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnu) +STD_ROM_FN(sailormnu) + +static struct BurnRomInfo sailormnjRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_japan.nv", 0x0080, 0xea03c30a, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnj) +STD_ROM_FN(sailormnj) + +static struct BurnRomInfo sailormnkRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_korea.nv", 0x0080, 0x0e7de398, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnk) +STD_ROM_FN(sailormnk) + +static struct BurnRomInfo sailormntRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_taiwan.nv", 0x0080, 0x6c7e8c2a, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnt) +STD_ROM_FN(sailormnt) + +static struct BurnRomInfo sailormnhRomDesc[] = { + { "bpsm945a.u45", 0x080000, 0x898C9515, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_hongkong.nv", 0x0080, 0x4d24c874, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnh) +STD_ROM_FN(sailormnh) + +static struct BurnRomInfo sailormnoRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_europe.nv", 0x0080, 0x59a7dc50, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormno) +STD_ROM_FN(sailormno) + +static struct BurnRomInfo sailormnouRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_usa.nv", 0x0080, 0x3915abe3, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnou) +STD_ROM_FN(sailormnou) + +static struct BurnRomInfo sailormnojRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_japan.nv", 0x0080, 0xea03c30a, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnoj) +STD_ROM_FN(sailormnoj) + +static struct BurnRomInfo sailormnokRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_korea.nv", 0x0080, 0x0e7de398, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnok) +STD_ROM_FN(sailormnok) + +static struct BurnRomInfo sailormnotRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_taiwan.nv", 0x0080, 0x6c7e8c2a, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnot) +STD_ROM_FN(sailormnot) + +static struct BurnRomInfo sailormnohRomDesc[] = { + { "smprg.u45", 0x080000, 0x234F1152, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bpsm.u46", 0x200000, 0x32084E80, BRF_ESS | BRF_PRG }, // 1 + + { "bpsm945a.u9", 0x080000, 0x438DE548, BRF_ESS | BRF_PRG }, // 2 Z80 code + + { "bpsm.u76", 0x200000, 0xA243A5BA, BRF_GRA }, // 3 Sprite data + { "bpsm.u77", 0x200000, 0x5179A4AC, BRF_GRA }, // 4 + + { "bpsm.u53", 0x200000, 0xB9B15F83, BRF_GRA }, // 5 Layer 0 Tile data + { "bpsm.u54", 0x200000, 0x8F00679D, BRF_GRA }, // 6 Layer 1 Tile data + + { "bpsm.u57", 0x200000, 0x86BE7B63, BRF_GRA }, // 7 Layer 2 Tile data + { "bpsm.u58", 0x200000, 0xE0BBA83B, BRF_GRA }, // 8 + { "bpsm.u62", 0x200000, 0xA1E3BFAC, BRF_GRA }, // 9 + { "bpsm.u61", 0x200000, 0x6A014B52, BRF_GRA }, // 10 + { "bpsm.u60", 0x200000, 0x992468C0, BRF_GRA }, // 11 + + { "bpsm.u65", 0x200000, 0xF60FB7B5, BRF_GRA }, // 12 + { "bpsm.u64", 0x200000, 0x6559D31C, BRF_GRA }, // 13 + { "bpsm.u63", 0x200000, 0xD57A56B4, BRF_GRA }, // 14 + + { "bpsm.u48", 0x200000, 0x498E4ED1, BRF_SND }, // 15 MSM6295 #0 ADPCM data + { "bpsm.u47", 0x080000, 0x0F2901B9, BRF_SND }, // 16 MSM6295 #1 ADPCM data + + { "sailormn_hongkong.nv", 0x0080, 0x4d24c874, BRF_OPT }, +}; + + +STD_ROM_PICK(sailormnoh) +STD_ROM_FN(sailormnoh) + +static struct BurnRomInfo agalletRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_europe.nv", 0x0080, 0xec38bf65, BRF_OPT }, +}; + + +STD_ROM_PICK(agallet) +STD_ROM_FN(agallet) + +static struct BurnRomInfo agalletuRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_usa.nv", 0x0080, 0x72e65056, BRF_OPT }, +}; + + +STD_ROM_PICK(agalletu) +STD_ROM_FN(agalletu) + +static struct BurnRomInfo agalletjRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_japan.nv", 0x0080, 0x0753f547, BRF_OPT }, +}; + + +STD_ROM_PICK(agalletj) +STD_ROM_FN(agalletj) + +static struct BurnRomInfo agalletkRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_korea.nv", 0x0080, 0x7f41c253, BRF_OPT }, +}; + + +STD_ROM_PICK(agalletk) +STD_ROM_FN(agalletk) + +static struct BurnRomInfo agallettRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_taiwan.nv", 0x0080, 0x0af46742, BRF_OPT }, +}; + + +STD_ROM_PICK(agallett) +STD_ROM_FN(agallett) + +static struct BurnRomInfo agallethRomDesc[] = { + { "bp962a.u45", 0x080000, 0x24815046, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "bp962a.u9", 0x080000, 0x06CADDBE, BRF_ESS | BRF_PRG }, // 1 Z80 code + + { "bp962a.u76", 0x200000, 0x858DA439, BRF_GRA }, // 2 Sprite data + { "bp962a.u77", 0x200000, 0xEA2BA35E, BRF_GRA }, // 3 + + { "bp962a.u53", 0x200000, 0xFCD9A107, BRF_GRA }, // 4 Layer 0 Tile data + { "bp962a.u54", 0x200000, 0x0CFA3409, BRF_GRA }, // 5 Layer 1 Tile data + { "bp962a.u57", 0x200000, 0x6D608957, BRF_GRA }, // 6 Layer 2 Tile data + { "bp962a.u65", 0x200000, 0x135FCF9A, BRF_GRA }, // 7 + + { "bp962a.u48", 0x200000, 0xAE00A1CE, BRF_SND }, // 8 MSM6295 #0 ADPCM data + { "bp962a.u47", 0x200000, 0x6D4E9737, BRF_SND }, // 9 MSM6295 #1 ADPCM data + + { "agallet_hongkong.nv", 0x0080, 0x998d1a74, BRF_OPT }, +}; + + +STD_ROM_PICK(agalleth) +STD_ROM_FN(agalleth) + +struct BurnDriver BurnDrvSailorMoon = { + "sailormn", NULL, NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, Europe)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, Europe)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnRomInfo, sailormnRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonu = { + "sailormnu", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, USA)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnuRomInfo, sailormnuRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonj = { + "sailormnj", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, Japan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnjRomInfo, sailormnjRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonk = { + "sailormnk", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, Korea)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, Korea)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnkRomInfo, sailormnkRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoont = { + "sailormnt", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, Taiwan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, Taiwan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormntRomInfo, sailormntRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonh = { + "sailormnh", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22B, Hong Kong)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22B, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnhRomInfo, sailormnhRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonO = { + "sailormno", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, Europe)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, Europe)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnoRomInfo, sailormnoRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonOu = { + "sailormnou", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, USA)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnouRomInfo, sailormnouRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonOj = { + "sailormnoj", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, Japan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnojRomInfo, sailormnojRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonOk = { + "sailormnok", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, Korea)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, Korea)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnokRomInfo, sailormnokRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonOt = { + "sailormnot", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, Taiwan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, Taiwan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnotRomInfo, sailormnotRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSailorMoonOh = { + "sailormnoh", "sailormn", NULL, NULL,"1995", + "Pretty Soldier Sailor Moon (ver. 95/03/22, Hong Kong)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Pretty Soldier Sailor Moon\0\u7F8E\u5C11\u5973\u6226\u58EB \u30BB\u30FC\u30E9\u30FC\u30E0\u30FC\u30F3 (ver. 95/03/22, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_SCRFIGHT, 0, + NULL, sailormnohRomInfo, sailormnohRomName, NULL, NULL, sailormnInputInfo, NULL, + sailormnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvAirGallet = { + "agallet", NULL, NULL, NULL,"1996", + "Air Gallet (Europe)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (Europe)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agalletRomInfo, agalletRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAirGalletu = { + "agalletu", "agallet", NULL, NULL,"1996", + "Air Gallet (USA)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agalletuRomInfo, agalletuRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAirGalletj = { + "agalletj", "agallet", NULL, NULL,"1996", + "Air Gallet (Japan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agalletjRomInfo, agalletjRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAirGalletk = { + "agalletk", "agallet", NULL, NULL,"1996", + "Air Gallet (Korea)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (Korea)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agalletkRomInfo, agalletkRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAirGallett = { + "agallett", "agallet", NULL, NULL,"1996", + "Air Gallet (Taiwan)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (Taiwan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agallettRomInfo, agallettRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAirGalleth = { + "agalleth", "agallet", NULL, NULL,"1996", + "Air Gallet (Hong Kong)\0", NULL, "BanPresto / Gazelle", "Cave", + L"Air Gallet\0\u30A2\u30EF\u30A6\u30AE\u30E3\u30EC\u30C3\u30C8 (Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0, + NULL, agallethRomInfo, agallethRomName, NULL, NULL, sailormnInputInfo, NULL, + agalletInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/cave/d_tjumpman.cpp b/src/burn/drivers/cave/d_tjumpman.cpp new file mode 100644 index 00000000..1bfe90bc --- /dev/null +++ b/src/burn/drivers/cave/d_tjumpman.cpp @@ -0,0 +1,583 @@ +// Tobikose! Jumpman +#include "cave.h" +#include "msm6295.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0, 0}; +static UINT8 DrvDip[2] = { 0, 0 }; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; +static INT8 nIRQPending; + +static INT32 nPrevCoinHack = 0; +static INT32 watchdog; +static INT32 tjumpman_hopper; + +static struct BurnInputInfo TjumpmanInputList[] = { + {"Coin", BIT_DIGITAL, DrvJoy2 + 6, "p1 coin" }, + {"1 Bet", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1" }, + {"3 Bet", BIT_DIGITAL, DrvJoy2 + 7, "p1 fire 2" }, + {"No (not)", BIT_DIGITAL, DrvJoy2 + 4, "p1 start" }, + {"Yes (do)", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4" }, + {"Pay Out", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 5" }, + {"Go", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Tjumpman) + +static struct BurnDIPInfo TjumpmanDIPList[]= +{ + {0x08, 0xff, 0xff, 0x01, NULL }, + {0x09, 0xff, 0xff, 0x08, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x08, 0x01, 0x01, 0x01, "Off" }, + {0x08, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Self Test" }, + {0x09, 0x01, 0x08, 0x08, "Off" }, + {0x09, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Tjumpman) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +static INT32 tjumpman_hopper_read() +{ + return (tjumpman_hopper && !(nCurrentFrame % 10)) ? 0 : 1; +} + +UINT8 __fastcall tjumpmanReadByte(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0x600000: + return 0xff; + + case 0x600001: + return ((DrvInput[0] & 0x76) ^ 0x76) | (DrvDip[0] & 1) | ((EEPROMRead() & 1) << 3) | (tjumpman_hopper_read() << 7); + + case 0x600002: + return 0xff; + + case 0x600003: + return ((DrvInput[1] & 0xF7) ^ 0xF7) | (DrvDip[1] & 8); + + case 0x700000: + case 0x700001: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0); + return nRet; + } + + case 0x700002: + case 0x700003: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0x700004: + case 0x700005: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x700006: + case 0x700007: { + UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x800001: + return MSM6295ReadStatus(0); + + default: { +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +UINT16 __fastcall tjumpmanReadWord(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0x600000: + return (DrvInput[0] ^ 0xFF76) | (DrvDip[0] & 1) | ((EEPROMRead() & 1) << 3) | (tjumpman_hopper_read() << 7); + + case 0x600002: + return (DrvInput[1] ^ 0xFFF7) | (DrvDip[1] & 8); + + case 0x700000: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0); + return nRet; + } + + case 0x700002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + + case 0x700004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x700006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x800000: + return MSM6295ReadStatus(0); + + default: { +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall tjumpmanWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) + { + case 0x800001: + MSM6295Command(0, byteValue); + break; + + case 0xc00000: + break; + + case 0xc00001: + tjumpman_hopper = byteValue & 0x40; + break; + + case 0xe00001: + EEPROMWrite(byteValue & 0x10, byteValue & 0x08, byteValue & 0x20); + break; + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } + } +} + +void __fastcall tjumpmanWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) + { + case 0x400000: + CaveTileReg[0][0] = wordValue; + break; + case 0x400002: + CaveTileReg[0][1] = wordValue; + break; + case 0x400004: + CaveTileReg[0][2] = wordValue; + break; + + case 0x700000: + nCaveXOffset = wordValue; + return; + case 0x700002: + nCaveYOffset = wordValue; + return; + case 0x700008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x700068: + watchdog = 0; + break; + + case 0x800000: + MSM6295Command(0, wordValue); + break; + + case 0xc00000: + tjumpman_hopper = wordValue & 0x40; + break; + + case 0xe00000: + EEPROMWrite(wordValue & 0x10, wordValue & 0x08, wordValue & 0x20); + break; + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } + } +} + +void __fastcall tjumpmanWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall tjumpmanWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + MSM6295Exit(0); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); + + BurnFree(Mem); + Mem = NULL; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + MSM6295Reset(0); + + tjumpman_hopper = 0; + watchdog = 0; +// nPrevCoinHack = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + CaveSpriteBuffer(); + CavePalUpdate8Bit(0, 128); + CaveClearScreen(CavePalette[0x7F00]); + + CaveTileRender(1); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + INT32 nCyclesTotal[1]; + INT32 nCyclesDone[1]; + + INT32 nCyclesSegment; + + watchdog++; + if (DrvReset || (watchdog > 180)) { + DrvDoReset(); + } + + DrvInput[0] = 0; + DrvInput[1] = 0; + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + + //if ((nPrevCoinHack != (DrvInput[1] & 0x0040)) && (DrvInput[1] & 0x0040)) { + // Ram01[0x24]++; + // if (Ram01[0x24] > 9) Ram01[0x24] = 9; // ? + //} + + nPrevCoinHack = DrvInput[1] & 0x0040; + + nCyclesTotal[0] = (INT32)((INT64)14000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU = 0; + INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // end of vblank + if (i == nInterleave) { + bVBlank = false; + nUnknownIRQ = 1; + UpdateIRQStatus(); + } + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8* Next; + + Next = Mem; + + Rom01 = Next; Next += 0x080000; + CaveSpriteROM = Next; Next += 0x200000; + CaveTileROM[0] = Next; Next += 0x100000; + + MSM6295ROM = Next; Next += 0x040000; + + Ram01 = Next; Next += 0x010000; // work RAM (NV!) + + RamStart = Next; + + CaveTileRAM[0] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap4(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[1] = (n2 << 4) | (n1 & 0x0F); + pData[0] = (n2 & 0xF0) | (n1 >> 4); + } + + return; +} + +static INT32 LoadRoms() +{ + BurnLoadRom(Rom01, 0, 1); + + BurnLoadRom(CaveSpriteROM + 0x000000, 1, 2); + BurnLoadRom(CaveSpriteROM + 0x000001, 2, 2); + NibbleSwap1(CaveSpriteROM, 0x100000); + + BurnLoadRom(CaveTileROM[0] + 0x00000, 3, 2); + BurnLoadRom(CaveTileROM[0] + 0x00001, 4, 2); + NibbleSwap4(CaveTileROM[0], 0x80000); + + BurnLoadRom(MSM6295ROM, 5, 1); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); + + if (nAction & ACB_VOLATILE) { + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + + MSM6295Scan(0, nAction); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + + SCAN_VAR(tjumpman_hopper); + + CaveScanGraphics(); + } + + if (nAction & ACB_NVRAM) { + ba.Data = Ram01; + ba.nLen = 0x010000; + ba.nAddress = 0x100000; + ba.szName = "NV RAM"; + BurnAcb(&ba); + } + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); + MemIndex(); + + EEPROMInit(&eeprom_interface_93C46); + + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x300000, 0x303FFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x304000, 0x307FFF, SM_RAM); // mirror + SekMapMemory(CaveSpriteRAM, 0x200000, 0x20FFFF, SM_RAM); + SekMapMemory(CavePalSrc, 0x500000, 0x50FFFF, SM_ROM); + SekSetReadWordHandler(0, tjumpmanReadWord); + SekSetReadByteHandler(0, tjumpmanReadByte); + SekSetWriteWordHandler(0, tjumpmanWriteWord); + SekSetWriteByteHandler(0, tjumpmanWriteByte); + + SekMapHandler(1, 0x500000, 0x50FFFF, SM_WRITE); + SekSetWriteWordHandler(1, tjumpmanWriteWordPalette); + SekSetWriteByteHandler(1, tjumpmanWriteBytePalette); + SekClose(); + } + + nCaveExtraXOffset = -128; // bg + CaveSpriteVisibleXOffset = -128; // sprite + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(2, 0x0200000); + CaveTileInitLayer(0, 0x100000, 8, 0x4000); + + MSM6295Init(0, 7575, 100.0, 0); + + DrvDoReset(); + + return 0; +} + + +// Tobikose! Jumpman + +static struct BurnRomInfo tjumpmanRomDesc[] = { + { "tj1_mpr-0c.u41", 0x80000, 0xde3030b8, BRF_PRG | BRF_PRG }, // 0 CPU #0 code + + { "tj1_obj-0a.u52", 0x80000, 0xb42cf8e8, BRF_GRA }, // 1 Sprite data + { "tj1_obj-1a.u53", 0x80000, 0x5f0124d7, BRF_GRA }, // 2 + + { "tj1_cha-0a.u60", 0x40000, 0x8aa08a38, BRF_GRA }, // 3 Layer 0 Tile data + { "tj1_cha-1a.u61", 0x40000, 0x50072c82, BRF_GRA }, // 4 + + { "tj1_voi-0a.u27", 0x40000, 0xb5693aae, BRF_SND }, // 5 MSM6295 #0 ADPCM data + + { "n44u3b.u3", 0x00117, 0x4cd79750, BRF_OPT }, // 6 PLDs + { "n44u1g.u1", 0x00117, 0xe226ec18, BRF_OPT }, // 7 +}; + +STD_ROM_PICK(tjumpman) +STD_ROM_FN(tjumpman) + +struct BurnDriverD BurnDrvTjumpman = { + "tjumpman", NULL, NULL, NULL, "1999", + "Tobikose! Jumpman\0", "Coin input not working?", "Namco", "Cave", + L"\u30E1\u30B0\u30EB\u3092\u3044\u308C\u3066\u306D!\0Tobikose! Jumpman\0", NULL, NULL, NULL, + BDF_16BIT_ONLY, 1, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_MISC, 0, + NULL, tjumpmanRomInfo, tjumpmanRomName, NULL, NULL, TjumpmanInputInfo, TjumpmanDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/cave/d_uopoko.cpp b/src/burn/drivers/cave/d_uopoko.cpp new file mode 100644 index 00000000..3973f2f0 --- /dev/null +++ b/src/burn/drivers/cave/d_uopoko.cpp @@ -0,0 +1,610 @@ +// Uo Poko +#include "cave.h" +#include "ymz280b.h" + +#define CAVE_VBLANK_LINES 12 + +static UINT8 DrvJoy1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT16 DrvInput[2] = {0x0000, 0x0000}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT8 nVideoIRQ; +static INT8 nSoundIRQ; +static INT8 nUnknownIRQ; + +static INT8 nIRQPending; + +static INT32 nCurrentCPU; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo uopokoInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"}, +}; + +STDINPUTINFO(uopoko) + +static void UpdateIRQStatus() +{ + nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0); + SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); +} + +UINT8 __fastcall uopokoReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300003: { + return YMZ280BReadStatus(); + } + + case 0x600000: + case 0x600001: + case 0x600002: + case 0x600003: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x600004: + case 0x600005: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x600006: + case 0x600007: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x900000: + return (DrvInput[0] >> 8) ^ 0xFF; + case 0x900001: + return (DrvInput[0] & 0xFF) ^ 0xFF; + case 0x900002: + return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3); + case 0x900003: + return (DrvInput[1] & 0xFF) ^ 0xFF; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall uopokoReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x300002: { + return YMZ280BReadStatus(); + } + + case 0x600000: + case 0x600002: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + return nRet; + } + case 0x600004: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nVideoIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + case 0x600006: { + UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ; + nUnknownIRQ = 1; + UpdateIRQStatus(); + return nRet; + } + + case 0x900000: + return DrvInput[0] ^ 0xFFFF; + case 0x900002: + return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11); + + default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall uopokoWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x300001: + YMZ280BSelectRegister(byteValue); + break; + case 0x300003: + YMZ280BWriteRegister(byteValue); + break; + + case 0xA00000: + EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall uopokoWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: + YMZ280BSelectRegister(wordValue); + break; + case 0x300002: + YMZ280BWriteRegister(wordValue); + break; + + case 0x600000: + nCaveXOffset = wordValue; + return; + case 0x600002: + nCaveYOffset = wordValue; + return; + case 0x600008: + CaveSpriteBuffer(); + nCaveSpriteBank = wordValue; + return; + + case 0x700000: + CaveTileReg[0][0] = wordValue; + break; + case 0x700002: + CaveTileReg[0][1] = wordValue; + break; + case 0x700004: + CaveTileReg[0][2] = wordValue; + break; + + case 0xA00000: { + wordValue >>= 8; + EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08); + break; + } + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + } + } +} + +void __fastcall uopokoWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + CavePalWriteByte(sekAddress & 0xFFFF, byteValue); +} + +void __fastcall uopokoWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + CavePalWriteWord(sekAddress & 0xFFFF, wordValue); +} + +static void TriggerSoundIRQ(INT32 nStatus) +{ + nSoundIRQ = nStatus ^ 1; + UpdateIRQStatus(); + + if (nIRQPending && nCurrentCPU != 0) { + nCyclesDone[0] += SekRun(0x0400); + } +} + +static INT32 DrvExit() +{ + YMZ280BExit(); + + EEPROMExit(); + + CaveTileExit(); + CaveSpriteExit(); + CavePalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + nVideoIRQ = 1; + nSoundIRQ = 1; + nUnknownIRQ = 1; + + nIRQPending = 0; + + YMZ280BReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + CavePalUpdate8Bit(0, 128); // Update the palette + CaveClearScreen(CavePalette[0x7F00]); + + if (bDrawScreen) { +// CaveGetBitmap(); + + CaveTileRender(1); // Render tiles + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Player 1 + DrvInput[1] = 0x0000; // Player 2 + for (INT32 i = 0; i < 16; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + } + CaveClearOpposites(&DrvInput[0]); + CaveClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE)); + nCyclesDone[0] = 0; + + nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Render sound segment + if ((i & 1) == 0) { + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + + // Run 68000 + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (!bVBlank && nNext > nCyclesVBlank) { + if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + nVideoIRQ = 0; + UpdateIRQStatus(); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCurrentCPU = -1; + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // 68K program + CaveSpriteROM = Next; Next += 0x800000; + CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0 + YMZ280BROM = Next; Next += 0x200000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + CaveTileRAM[0] = Next; Next += 0x008000; + CaveSpriteRAM = Next; Next += 0x010000; + CavePalSrc = Next; Next += 0x010000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void NibbleSwap1(UINT8* pData, INT32 nLen) +{ + UINT8* pOrg = pData + nLen - 1; + UINT8* pDest = pData + ((nLen - 1) << 1); + + for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) { + pDest[0] = *pOrg & 15; + pDest[1] = *pOrg >> 4; + } + + return; +} + +static void NibbleSwap4(UINT8* pData, INT32 nLen) +{ + for (INT32 i = 0; i < nLen; i++, pData += 2) { + UINT8 n1 = pData[0]; + UINT8 n2 = pData[1]; + + pData[1] = (n2 << 4) | (n1 & 0x0F); + pData[0] = (n2 & 0xF0) | (n1 >> 4); + } + + return; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01 + 0, 1, 2); + BurnLoadRom(Rom01 + 1, 0, 2); + + BurnLoadRom(CaveSpriteROM + 0x0000000, 2, 1); + NibbleSwap1(CaveSpriteROM, 0x400000); + + BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1); + NibbleSwap4(CaveTileROM[0], 0x200000); + + // Load YMZ280B data + BurnLoadRom(YMZ280BROM, 4, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020902; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + YMZ280BScan(); + + SCAN_VAR(nVideoIRQ); + SCAN_VAR(nSoundIRQ); + SCAN_VAR(nUnknownIRQ); + SCAN_VAR(bVBlank); + + CaveScanGraphics(); + + SCAN_VAR(DrvInput); + } + + return 0; +} + +static const UINT8 default_eeprom[16] = {0x00,0x03,0x08,0x00,0xFF,0xFF,0xFF,0xFF,0x08,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF}; + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(CAVE_REFRESHRATE); + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C46); + if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom)); + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM); + SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM); + + SekMapMemory(CavePalSrc, 0x800000, 0x80FFFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0x800000, 0x80FFFF, SM_WRITE); // + + SekSetReadWordHandler(0, uopokoReadWord); + SekSetReadByteHandler(0, uopokoReadByte); + SekSetWriteWordHandler(0, uopokoWriteWord); + SekSetWriteByteHandler(0, uopokoWriteByte); + + SekSetWriteWordHandler(1,uopokoWriteWordPalette); + SekSetWriteByteHandler(1, uopokoWriteBytePalette); + + SekClose(); + } + + nCaveRowModeOffset = 1; + + CavePalInit(0x8000); + CaveTileInit(); + CaveSpriteInit(1, 0x800000); + CaveTileInitLayer(0, 0x400000, 8, 0x4000); + + YMZ280BInit(16934400, &TriggerSoundIRQ, 3); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo uopokoRomDesc[] = { + { "u26.int", 0x080000, 0xb445c9ac, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u25.int", 0x080000, 0xa1258482, BRF_ESS | BRF_PRG }, // 1 + + { "u33.bin", 0x400000, 0x5D142Ad2, BRF_GRA }, // 2 Sprite data + + { "u49.bin", 0x400000, 0x12FB11BB, BRF_GRA }, // 3 Layer 0 Tile data + + { "u4.bin", 0x200000, 0xA2D0D755, BRF_SND }, // 4 YMZ280B (AD)PCM data + + { "eeprom-uopoko.bin", 0x0080, 0xf4a24b95, BRF_OPT }, +}; + + +STD_ROM_PICK(uopoko) +STD_ROM_FN(uopoko) + +static struct BurnRomInfo uopokojRomDesc[] = { + { "u26.bin", 0x080000, 0xE7EEC050, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "u25.bin", 0x080000, 0x68CB6211, BRF_ESS | BRF_PRG }, // 1 + + { "u33.bin", 0x400000, 0x5D142Ad2, BRF_GRA }, // 2 Sprite data + + { "u49.bin", 0x400000, 0x12FB11BB, BRF_GRA }, // 3 Layer 0 Tile data + + { "u4.bin", 0x200000, 0xA2D0D755, BRF_SND }, // 4 YMZ280B (AD)PCM data + + { "eeprom-uopoko.bin", 0x0080, 0xf4a24b95, BRF_OPT }, +}; + + +STD_ROM_PICK(uopokoj) +STD_ROM_FN(uopokoj) + +struct BurnDriver BurnDrvUoPoko = { + "uopoko", NULL, NULL, NULL, "1999", + "Puzzle Uo Poko (International, ver. 98/02/06)\0", NULL, "Cave / Jaleco", "Cave", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_PUZZLE, 0, + NULL, uopokoRomInfo, uopokoRomName, NULL, NULL, uopokoInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvUoPokoj = { + "uopokoj", "uopoko", NULL, NULL, "1999", + "Puzzle Uo Poko (Japan, ver. 98/02/06)\0", NULL, "Cave / Jaleco", "Cave", + L"\u30D1\u30BA\u30EB \u9B5A\u30DD\u30B3 \u3046\u304A\u307D\u3053 (Japan, ver. 98/02/06)\0Puzzle Uo Poko\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_PUZZLE, 0, + NULL, uopokojRomInfo, uopokojRomName, NULL, NULL, uopokoInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &CaveRecalcPalette, 0x8000, 320, 240, 4, 3 +}; + + + diff --git a/src/burn/drivers/cps3/cps3.h b/src/burn/drivers/cps3/cps3.h new file mode 100644 index 00000000..bd4c60ff --- /dev/null +++ b/src/burn/drivers/cps3/cps3.h @@ -0,0 +1,46 @@ +#include "burnint.h" + +#ifndef HARDWARE_CAPCOM_CPS3 + #define HARDWARE_CAPCOM_CPS3 HARDWARE_MISC_MISC +#endif + +#ifndef HARDWARE_CAPCOM_CPS3_NO_CD + #define HARDWARE_CAPCOM_CPS3_NO_CD HARDWARE_CAPCOM_CPS3 +#endif + +extern UINT8 cps3_reset; +extern UINT8 cps3_palette_change; + +extern UINT16 *Cps3CurPal; + +extern UINT32 cps3_key1, cps3_key2, cps3_isSpecial; +extern UINT32 cps3_bios_test_hack, cps3_game_test_hack; +extern UINT32 cps3_speedup_ram_address, cps3_speedup_code_address; +extern UINT8 cps3_dip; +extern UINT32 cps3_region_address, cps3_ncd_address; + +extern UINT8 Cps3But1[16]; +extern UINT8 Cps3But2[16]; +extern UINT8 Cps3But3[16]; + +INT32 cps3Init(); +INT32 cps3Exit(); +INT32 cps3Frame(); +INT32 cps3Scan(INT32 nAction,INT32 *pnMin); + +// sound + +UINT8 __fastcall cps3SndReadByte(UINT32 addr); +UINT16 __fastcall cps3SndReadWord(UINT32 addr); +UINT32 __fastcall cps3SndReadLong(UINT32 addr); + +void __fastcall cps3SndWriteByte(UINT32 addr, UINT8 data); +void __fastcall cps3SndWriteWord(UINT32 addr, UINT16 data); +void __fastcall cps3SndWriteLong(UINT32 addr, UINT32 data); + +INT32 cps3SndInit(UINT8 *); +void cps3SndReset(); +void cps3SndExit(); +void cps3SndUpdate(); + +INT32 cps3SndScan(INT32); diff --git a/src/burn/drivers/cps3/cps3run.cpp b/src/burn/drivers/cps3/cps3run.cpp new file mode 100644 index 00000000..e2f51cb8 --- /dev/null +++ b/src/burn/drivers/cps3/cps3run.cpp @@ -0,0 +1,2196 @@ +/********************************************************************** + +CPS3 Driver (preliminary) + +Decryption by Andreas Naive + +Driver by David Haywood + with help from Tomasz Slanina and ElSemi + +Sound emulation by Philip Bennett + +SCSI code by ElSemi + +********************************************************************** + +Port to FBA by OopsWare + +**********************************************************************/ + +#include "cps3.h" +#include "sh2.h" + +#define BE_GFX 1 +//#define FAST_BOOT 1 +#define SPEED_HACK 1 // Default should be 1, if not FPS would drop. + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *RomBios; +static UINT8 *RomGame; +static UINT8 *RomGame_D; +static UINT8 *RomUser; + +static UINT8 *RamMain; +static UINT32 *RamSpr; +static UINT16 *RamPal; + +static UINT32 *RamCRam; + +static UINT32 *RamSS; + +static UINT32 *RamVReg; + +static UINT8 *RamC000; +static UINT8 *RamC000_D; + +static UINT16 *EEPROM; + +UINT16 *Cps3CurPal; +static UINT32 *RamScreen; + +UINT8 cps3_reset = 0; +UINT8 cps3_palette_change = 0; + +UINT32 cps3_key1, cps3_key2, cps3_isSpecial; +UINT32 cps3_bios_test_hack, cps3_game_test_hack; +UINT32 cps3_speedup_ram_address, cps3_speedup_code_address; +UINT8 cps3_dip; +UINT32 cps3_region_address, cps3_ncd_address; + +static UINT32 cps3_data_rom_size; + +UINT8 Cps3But1[16]; +UINT8 Cps3But2[16]; +UINT8 Cps3But3[16]; + +static UINT16 Cps3Input[4] = {0, 0, 0, 0}; + +static UINT32 ss_bank_base = 0; +static UINT32 ss_pal_base = 0; + +static UINT32 cram_bank = 0; +static UINT16 cps3_current_eeprom_read = 0; +static UINT32 gfxflash_bank = 0; + +static UINT32 paldma_source = 0; +static UINT32 paldma_dest = 0; +static UINT32 paldma_fade = 0; +static UINT32 paldma_length = 0; + +static UINT32 chardma_source = 0; +static UINT32 chardma_table_address = 0; + +static INT32 cps3_gfx_width, cps3_gfx_height; +static INT32 cps3_gfx_max_x, cps3_gfx_max_y; + + +// -- AMD/Fujitsu 29F016 -------------------------------------------------- + +enum { + FM_NORMAL, // normal read/write + FM_READID, // read ID + FM_READSTATUS, // read status + FM_WRITEPART1, // first half of programming, awaiting second + FM_CLEARPART1, // first half of clear, awaiting second + FM_SETMASTER, // first half of set master lock, awaiting on/off + FM_READAMDID1, // part 1 of alt ID sequence + FM_READAMDID2, // part 2 of alt ID sequence + FM_READAMDID3, // part 3 of alt ID sequence + FM_ERASEAMD1, // part 1 of AMD erase sequence + FM_ERASEAMD2, // part 2 of AMD erase sequence + FM_ERASEAMD3, // part 3 of AMD erase sequence + FM_ERASEAMD4, // part 4 of AMD erase sequence + FM_BYTEPROGRAM +}; + +typedef struct +{ + INT32 status; + INT32 flash_mode; + INT32 flash_master_lock; +} flash_chip; + +static flash_chip main_flash; + +void cps3_flash_init(flash_chip * chip/*, void *data*/) +{ + memset(chip, 0, sizeof(flash_chip)); + chip->status = 0x80; + chip->flash_mode = FM_NORMAL; + chip->flash_master_lock = 0; +} + +UINT32 cps3_flash_read(flash_chip * chip, UINT32 addr) +{ + switch( chip->flash_mode ) { + case FM_READAMDID3: + case FM_READID: + + switch (addr & 0x7fffff) { + case 0: return 0x04040404; //(c->maker_id << 0) | (c->maker_id << 8) | (c->maker_id << 16) | (c->maker_id << 24); + case 4: return 0xadadadad; //(c->device_id << 0) | (c->device_id << 8) | (c->device_id << 16) | (c->device_id << 24); + case 8: return 0x00000000; + //case 12: return (c->flash_master_lock) ? 0x01010101 : 0x00000000 + } + return 0; + + case FM_ERASEAMD4: + chip->status ^= ( 1 << 6 ) | ( 1 << 2 ); + case FM_READSTATUS: + return (chip->status << 0) | (chip->status << 8) | (chip->status << 16) | (chip->status << 24); + + case FM_NORMAL: + default: + // + return 0; + } +} + +void cps3_flash_write(flash_chip * chip, UINT32 addr, UINT32 data) +{ + bprintf(1, _T("FLASH to write long value %8x to location %8x\n"), data, addr); + + switch( chip->flash_mode ) { + case FM_NORMAL: + case FM_READSTATUS: + case FM_READID: + case FM_READAMDID3: + switch( data & 0xff ) { + case 0xf0: + case 0xff: chip->flash_mode = FM_NORMAL; break; + case 0x90: chip->flash_mode = FM_READID; break; + case 0x40: + case 0x10: chip->flash_mode = FM_WRITEPART1;break; + case 0x50: // clear status reg + chip->status = 0x80; + chip->flash_mode = FM_READSTATUS; + break; + case 0x20: chip->flash_mode = FM_CLEARPART1;break; + case 0x60: chip->flash_mode = FM_SETMASTER; break; + case 0x70: chip->flash_mode = FM_READSTATUS;break; + case 0xaa: // AMD ID select part 1 + if ((addr & 0xffff) == (0x555 << 2)) + chip->flash_mode = FM_READAMDID1; + break; + default: + //logerror( "Unknown flash mode byte %x\n", data & 0xff ); + //bprintf(1, _T("FLASH to write long value %8x to location %8x\n"), data, addr); + break; + } + break; + case FM_READAMDID1: + if ((addr & 0xffff) == (0x2aa <<2) && (data & 0xff) == 0x55 ) { + chip->flash_mode = FM_READAMDID2; + } else { + //logerror( "unexpected %08x=%02x in FM_READAMDID1\n", address, data & 0xff ); + chip->flash_mode = FM_NORMAL; + } + break; + case FM_READAMDID2: + if ((addr & 0xffff) == (0x555<<2) && (data & 0xff) == 0x90) { + chip->flash_mode = FM_READAMDID3; + } else if((addr & 0xffff) == (0x555<<2) && (data & 0xff) == 0x80) { + chip->flash_mode = FM_ERASEAMD1; + } else if((addr & 0xffff) == (0x555<<2) && (data & 0xff) == 0xa0) { + chip->flash_mode = FM_BYTEPROGRAM; + } else if((addr & 0xffff) == (0x555<<2) && (data & 0xff) == 0xf0) { + chip->flash_mode = FM_NORMAL; + } else { + // logerror( "unexpected %08x=%02x in FM_READAMDID2\n", address, data & 0xff ); + chip->flash_mode = FM_NORMAL; + } + break; + } +} + +// ------------------------------------------------------------------------ + +inline static void Cps3ClearOpposites(UINT16* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +// ------------------------------------------------------------------------ + +static UINT16 rotate_left(UINT16 value, INT32 n) +{ + INT32 aux = value>>(16-n); + return ((value<> 16) ^ 0xffff; + val = rotxor(val, key2 >> 16); + val ^= (address & 0xffff) ^ (key2 & 0xffff); + return val | (val << 16); +} + +static void cps3_decrypt_bios(void) +{ + UINT32 * coderegion = (UINT32 *)RomBios; + for (INT32 i=0; i<0x20000; i+=4) { + UINT32 xormask = cps3_mask(i, cps3_key1, cps3_key2); + /* a bit of a hack, don't decrypt the FLASH commands which are transfered by SH2 DMA */ + if ( (i<0x1ff00) || (i>0x1ff6b) ) + coderegion[i/4] ^= xormask; + } +} + +static void cps3_decrypt_game(void) +{ + UINT32 * coderegion = (UINT32 *)RomGame; + UINT32 * decrypt_coderegion = (UINT32 *)RomGame_D; + + for (INT32 i=0; i<0x1000000; i+=4) { + UINT32 xormask = cps3_mask(i + 0x06000000, cps3_key1, cps3_key2); + decrypt_coderegion[i/4] = coderegion[i/4] ^ xormask; + } +} + + +static INT32 last_normal_byte = 0; + +static UINT32 process_byte( UINT8 real_byte, UINT32 destination, INT32 max_length ) +{ + UINT8 * dest = (UINT8 *) RamCRam; + //printf("process byte for destination %08x\n", destination); + destination &= 0x7fffff; + + if (real_byte&0x40) { + INT32 tranfercount = 0; + //printf("Set RLE Mode\n"); + INT32 cps3_rle_length = (real_byte&0x3f)+1; + //printf("RLE Operation (length %08x\n", cps3_rle_length ); + while (cps3_rle_length) { +#if BE_GFX + dest[((destination+tranfercount)&0x7fffff)] = (last_normal_byte&0x3f); +#else + dest[((destination+tranfercount)&0x7fffff)^3] = (last_normal_byte&0x3f); +#endif + //cps3_char_ram_dirty[((destination+tranfercount)&0x7fffff)/0x100] = 1; + //cps3_char_ram_is_dirty = 1; + //printf("RLE WRite Byte %08x, %02x\n", destination+tranfercount, real_byte); + + tranfercount++; + cps3_rle_length--; + max_length--; + if ((destination+tranfercount) > 0x7fffff) return max_length; + // if (max_length==0) return max_length; // this is meant to abort the transfer if we exceed dest length,, not working + } + return tranfercount; + } else { + //printf("Write Normal Data\n"); +#if BE_GFX + dest[(destination&0x7fffff)] = real_byte; +#else + dest[(destination&0x7fffff)^3] = real_byte; +#endif + last_normal_byte = real_byte; + //cps3_char_ram_dirty[(destination&0x7fffff)/0x100] = 1; + //cps3_char_ram_is_dirty = 1; + return 1; + } +} + +static void cps3_do_char_dma( UINT32 real_source, UINT32 real_destination, UINT32 real_length ) +{ + UINT8 * sourcedata = RomUser; + INT32 length_remaining = real_length; + last_normal_byte = 0; + while (length_remaining) { + UINT8 current_byte = sourcedata[ real_source ^ 0 ]; + real_source++; + + if (current_byte & 0x80) { + UINT8 real_byte; + UINT32 length_processed; + current_byte &= 0x7f; + + real_byte = sourcedata[ (chardma_table_address+current_byte*2+0) ^ 0 ]; + //if (real_byte&0x80) return; + length_processed = process_byte( real_byte, real_destination, length_remaining ); + length_remaining -= length_processed; // subtract the number of bytes the operation has taken + real_destination += length_processed; // add it onto the destination + if (real_destination>0x7fffff) return; + if (length_remaining<=0) return; // if we've expired, exit + + real_byte = sourcedata[ (chardma_table_address+current_byte*2+1) ^ 0 ]; + //if (real_byte&0x80) return; + length_processed = process_byte( real_byte, real_destination, length_remaining ); + length_remaining -= length_processed; // subtract the number of bytes the operation has taken + real_destination += length_processed; // add it onto the destination + if (real_destination>0x7fffff) return; + if (length_remaining<=0) return; // if we've expired, exit + } else { + UINT32 length_processed; + length_processed = process_byte( current_byte, real_destination, length_remaining ); + length_remaining -= length_processed; // subtract the number of bytes the operation has taken + real_destination += length_processed; // add it onto the destination + if (real_destination>0x7fffff) return; + if (length_remaining<=0) return; // if we've expired, exit + } + } +} + +static UINT16 lastb; +static UINT16 lastb2; + +static UINT32 ProcessByte8(UINT8 b, UINT32 dst_offset) +{ + UINT8 * destRAM = (UINT8 *) RamCRam; + INT32 l=0; + + if(lastb==lastb2) { //rle + INT32 rle=(b+1)&0xff; + + for(INT32 i=0;i=real_length) + return; + } + } +} + +static void cps3_process_character_dma(UINT32 address) +{ + for (INT32 i=0; i<0x1000; i+=3) { + UINT32 dat1 = RamCRam[i+0+(address)]; + UINT32 dat2 = RamCRam[i+1+(address)]; + UINT32 dat3 = RamCRam[i+2+(address)]; + UINT32 real_source = (dat3<<1)-0x400000; + UINT32 real_destination = dat2<<3; + UINT32 real_length = (((dat1&0x001fffff)+1)<<3); + + if (dat1==0x01000000) break; // end of list marker + if (dat1==0x13131313) break; // our default fill + + switch ( dat1 & 0x00e00000 ) { + case 0x00800000: + chardma_table_address = real_source; + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + break; + case 0x00400000: + cps3_do_char_dma( real_source, real_destination, real_length ); + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + break; + case 0x00600000: + //bprintf(PRINT_NORMAL, _T("Character DMA (alt) start %08x to %08x with %d\n"), real_source, real_destination, real_length); + /* 8bpp DMA decompression + - this is used on SFIII NG Sean's Stage ONLY */ + cps3_do_alt_char_dma( real_source, real_destination, real_length ); + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + break; + case 0x00000000: + // Red Earth need this. 8192 byte trans to 0x00003000 (from 0x007ec000???) + // seems some stars(6bit alpha) without compress + //bprintf(PRINT_NORMAL, _T("Character DMA (redearth) start %08x to %08x with %d\n"), real_source, real_destination, real_length); + memcpy( (UINT8 *)RamCRam + real_destination, RomUser + real_source, real_length ); + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + break; + default: + bprintf(PRINT_NORMAL, _T("Character DMA Unknown DMA List Command Type %08x\n"), dat1); + } + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + RomBios = Next; Next += 0x0080000; + + RomUser = Next; Next += cps3_data_rom_size; // 0x5000000; + + RamStart = Next; + + RomGame = Next; Next += 0x1000000; + RomGame_D = Next; Next += 0x1000000; + + RamC000 = Next; Next += 0x0000400; + RamC000_D = Next; Next += 0x0000400; + + RamMain = Next; Next += 0x0080000; + + RamPal = (UINT16 *) Next; Next += 0x0040000; + RamSpr = (UINT32 *) Next; Next += 0x0080000; + + RamCRam = (UINT32 *) Next; Next += 0x0800000; + RamSS = (UINT32 *) Next; Next += 0x0010000; + + RamVReg = (UINT32 *) Next; Next += 0x0000100; + + EEPROM = (UINT16 *) Next; Next += 0x0000400; + + RamEnd = Next; + + Cps3CurPal = (UINT16 *) Next; Next += 0x040002; // iq_132 - layer disable + RamScreen = (UINT32 *) Next; Next += (512 * 2) * (224 * 2 + 32) * sizeof(UINT32); + + MemEnd = Next; + return 0; +} + +UINT8 __fastcall cps3ReadByte(UINT32 addr) +{ + addr &= 0xc7ffffff; + +// switch (addr) { +// +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %8x\n"), addr); +// } + return 0; +} + +UINT16 __fastcall cps3ReadWord(UINT32 addr) +{ + addr &= 0xc7ffffff; + + switch (addr) { + + // redearth will read this !!! +#if 0 + case 0x040c0000: + return RamVReg[0] >> 16; + case 0x040c0002: + return RamVReg[0] & 0xffff; + case 0x040c0004: + return RamVReg[1] >> 16; + case 0x040c0006: + return RamVReg[1] & 0xffff; +#else + case 0x040c0000: + case 0x040c0002: + case 0x040c0004: + case 0x040c0006: + return 0; +#endif + // cps3_vbl_r + case 0x040c000c: + case 0x040c000e: + return 0; + + case 0x05000000: return ~Cps3Input[1]; + case 0x05000002: return ~Cps3Input[0]; + case 0x05000004: return ~Cps3Input[3]; + case 0x05000006: return ~Cps3Input[2]; + + case 0x05140000: + case 0x05140002: + // cd-rom read + + break; + + default: + if ((addr >= 0x05000a00) && (addr < 0x05000a20)) { + // cps3_unk_io_r + return 0xffff; + } else + if ((addr >= 0x05001000) && (addr < 0x05001204)) { + // EEPROM + addr -= 0x05001000; + if (addr >= 0x100 && addr < 0x180) { + cps3_current_eeprom_read = EEPROM[((addr-0x100) >> 1) ^ 1]; + } else + if (addr == 0x202) + return cps3_current_eeprom_read; + } else + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %8x\n"), addr); + } + return 0; +} + +UINT32 __fastcall cps3ReadLong(UINT32 addr) +{ + addr &= 0xc7ffffff; + + switch (addr) { + case 0x04200000: + bprintf(PRINT_NORMAL, _T("GFX Read Flash ID, cram bank %04x gfx flash bank: %04x\n"), cram_bank, gfxflash_bank); + return 0x0404adad; + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read long value of location %8x\n"), addr); + } + return 0; +} + +void __fastcall cps3WriteByte(UINT32 addr, UINT8 data) +{ + addr &= 0xc7ffffff; + + switch (addr) { + + // cps3_ss_bank_base_w + case 0x05050020: ss_bank_base = ( ss_bank_base & 0x00ffffff ) | (data << 24); break; + case 0x05050021: ss_bank_base = ( ss_bank_base & 0xff00ffff ) | (data << 16); break; + case 0x05050022: ss_bank_base = ( ss_bank_base & 0xffff00ff ) | (data << 8); break; + case 0x05050023: ss_bank_base = ( ss_bank_base & 0xffffff00 ) | (data << 0); break; + + // cps3_ss_pal_base_w + case 0x05050024: ss_pal_base = ( ss_pal_base & 0x00ff ) | (data << 8); break; + case 0x05050025: ss_pal_base = ( ss_pal_base & 0xff00 ) | (data << 0); break; + case 0x05050026: break; + case 0x05050027: break; + + default: + if ((addr >= 0x05050000) && (addr < 0x05060000)) { + // VideoReg + + } else + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %02x to location %8x\n"), data, addr); + } +} + +void __fastcall cps3WriteWord(UINT32 addr, UINT16 data) +{ + addr &= 0xc7ffffff; + + switch (addr) { + + case 0x040c0084: break; + case 0x040c0086: + if (cram_bank != data) { + cram_bank = data & 7; + //bprintf(PRINT_NORMAL, _T("CRAM bank set to %d\n"), data); + Sh2MapMemory(((UINT8 *)RamCRam) + (cram_bank << 20), 0x04100000, 0x041fffff, SM_RAM); + } + break; + + case 0x040c0088: + //case 0x040c008a: + gfxflash_bank = data - 2; + //bprintf(PRINT_NORMAL, _T("gfxflash bank set to %04x\n"), data); + break; + + // cps3_characterdma_w + //case 0x040c0094: + case 0x040c0096: + chardma_source = data; + break; + case 0x040c0098: + //case 0x040c009a: + if (data & 0x0040) + cps3_process_character_dma( chardma_source | ((data & 0x003f) << 16) ); + break; + + // cps3_palettedma_w + case 0x040c00a0: paldma_source = (paldma_source & 0x0000ffff) | (data << 16); break; + case 0x040c00a2: paldma_source = (paldma_source & 0xffff0000) | (data << 0); break; + case 0x040c00a4: paldma_dest = (paldma_dest & 0x0000ffff) | (data << 16); break; + case 0x040c00a6: paldma_dest = (paldma_dest & 0xffff0000) | (data << 0); break; + case 0x040c00a8: paldma_fade = (paldma_fade & 0x0000ffff) | (data << 16); break; + case 0x040c00aa: paldma_fade = (paldma_fade & 0xffff0000) | (data << 0); break; + case 0x040c00ac: paldma_length = data; break; + case 0x040c00ae: + //bprintf(PRINT_NORMAL, _T("palettedma [%04x] from %08x to %08x fade %08x size %d\n"), data, (paldma_source << 1), paldma_dest, paldma_fade, paldma_length); + if (data & 0x0002) { + for (UINT32 i=0; i> 8); + + UINT32 r = (coldata & 0x001F) >> 0; + UINT32 g = (coldata & 0x03E0) >> 5; + UINT32 b = (coldata & 0x7C00) >> 10; + if (paldma_fade!=0) { + INT32 fade; + fade = (paldma_fade & 0x3f000000)>>24; r = (r*fade)>>5; if (r>0x1f) r = 0x1f; + fade = (paldma_fade & 0x003f0000)>>16; g = (g*fade)>>5; if (g>0x1f) g = 0x1f; + fade = (paldma_fade & 0x0000003f)>> 0; b = (b*fade)>>5; if (b>0x1f) b = 0x1f; + coldata = (r << 0) | (g << 5) | (b << 10); + } + + r = r << 3; + g = g << 3; + b = b << 3; + + RamPal[(paldma_dest + i) ^ 1] = coldata; + Cps3CurPal[(paldma_dest + i) ] = BurnHighCol(r, g, b, 0); + } + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + } + break; + + case 0x04200554: + case 0x04200aaa: + // gfx flash command + // "0xaa 0x55 0x90" set flash to get id + // "0xaa 0x55 0xf0" set flash to normal read + break; + + // cps3_ss_bank_base_w + case 0x05050020: ss_bank_base = ( ss_bank_base & 0x0000ffff ) | (data << 16); break; + case 0x05050022: ss_bank_base = ( ss_bank_base & 0xffff0000 ) | (data << 0); break; + + // cps3_ss_pal_base_w + case 0x05050024: ss_pal_base = data; break; + case 0x05050026: break; + + case 0x05100000: + Sh2SetIRQLine(12, SH2_IRQSTATUS_NONE); + break; + case 0x05110000: + Sh2SetIRQLine(10, SH2_IRQSTATUS_NONE); + break; + + case 0x05140000: + case 0x05140002: + // cd-rom read + + break; + + default: + if ((addr >= 0x040c0000) && (addr < 0x040c0100)) { + // 0x040C0000 ~ 0x040C001f : cps3_unk_vidregs + // 0x040C0020 ~ 0x040C002b : tilemap20_regs_base + // 0x040C0030 ~ 0x040C003b : tilemap30_regs_base + // 0x040C0040 ~ 0x040C004b : tilemap40_regs_base + // 0x040C0050 ~ 0x040C005b : tilemap50_regs_base + // 0x040C0060 ~ 0x040C007f : cps3_fullscreenzoom + + addr &= 0xff; + ((UINT16 *)RamVReg)[ (addr >> 1) ^ 1 ] = data; + + } else + if ((addr >= 0x05000000) && (addr < 0x05001000)) { + + + } else + if ((addr >= 0x05001000) && (addr < 0x05001204)) { + // EEPROM + addr -= 0x05001000; + if ((addr>=0x080) && (addr<0x100)) + EEPROM[((addr-0x080) >> 1) ^ 1] = data; + } else + if ((addr >= 0x05050000) && (addr < 0x05060000)) { + // unknow i/o + + } else + + bprintf(PRINT_NORMAL, _T("Attempt to write word value %04x to location %8x\n"), data, addr); + } +} + +void __fastcall cps3WriteLong(UINT32 addr, UINT32 data) +{ + addr &= 0xc7ffffff; + + switch (addr) { + case 0x07ff000c: + case 0x07ff0048: + // some unknown data write by DMA 0 while bootup + break; + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write long value %8x to location %8x\n"), data, addr); + } +} + +void __fastcall cps3C0WriteByte(UINT32 addr, UINT8 data) +{ + bprintf(PRINT_NORMAL, _T("C0 Attempt to write byte value %2x to location %8x\n"), data, addr); +} + +void __fastcall cps3C0WriteWord(UINT32 addr, UINT16 data) +{ + bprintf(PRINT_NORMAL, _T("C0 Attempt to write word value %4x to location %8x\n"), data, addr); +} + +void __fastcall cps3C0WriteLong(UINT32 addr, UINT32 data) +{ + if (addr < 0xc0000400) { + *(UINT32 *)(RamC000 + (addr & 0x3ff)) = data; + *(UINT32 *)(RamC000_D + (addr & 0x3ff)) = data ^ cps3_mask(addr, cps3_key1, cps3_key2); + return ; + } + bprintf(PRINT_NORMAL, _T("C0 Attempt to write long value %8x to location %8x\n"), data, addr); +} + +// If fastboot != 1 + +UINT8 __fastcall cps3RomReadByte(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read byte value of location %8x\n"), addr); + addr &= 0xc7ffffff; + addr ^= 0x03; +/* UINT32 pc = Sh2GetPC(0); + if (pc == cps3_bios_test_hack || pc == cps3_game_test_hack){ + bprintf(PRINT_NORMAL, _T("CPS3 Hack : read byte from %08x\n"), addr); + return *(RomGame + (addr & 0x00ffffff)); + } */ + return *(RomGame_D + (addr & 0x00ffffff)); +} + +UINT16 __fastcall cps3RomReadWord(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read word value of location %8x\n"), addr); + addr &= 0xc7ffffff; + addr ^= 0x02; +/* UINT32 pc = Sh2GetPC(0); + if (pc == cps3_bios_test_hack || pc == cps3_game_test_hack){ + bprintf(PRINT_NORMAL, _T("CPS3 Hack : read word from %08x\n"), addr); + return *(UINT16 *)(RomGame + (addr & 0x00ffffff)); + } */ + return *(UINT16 *)(RomGame_D + (addr & 0x00ffffff)); +} + +UINT32 __fastcall cps3RomReadLong(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read long value of location %8x\n"), addr); + addr &= 0xc7ffffff; + + UINT32 retvalue = cps3_flash_read(&main_flash, addr); + if ( main_flash.flash_mode == FM_NORMAL ) + retvalue = *(UINT32 *)(RomGame_D + (addr & 0x00ffffff)); + + UINT32 pc = Sh2GetPC(0); + if (pc == cps3_bios_test_hack || pc == cps3_game_test_hack){ + if ( main_flash.flash_mode == FM_NORMAL ) + retvalue = *(UINT32 *)(RomGame + (addr & 0x00ffffff)); + bprintf(2, _T("CPS3 Hack : read long from %08x [%08x]\n"), addr, retvalue ); + } + return retvalue; +} + +void __fastcall cps3RomWriteByte(UINT32 addr, UINT8 data) +{ + bprintf(PRINT_NORMAL, _T("Rom Attempt to write byte value %2x to location %8x\n"), data, addr); +} + +void __fastcall cps3RomWriteWord(UINT32 addr, UINT16 data) +{ + bprintf(PRINT_NORMAL, _T("Rom Attempt to write word value %4x to location %8x\n"), data, addr); +} + +void __fastcall cps3RomWriteLong(UINT32 addr, UINT32 data) +{ +// bprintf(1, _T("Rom Attempt to write long value %8x to location %8x\n"), data, addr); + addr &= 0x00ffffff; + cps3_flash_write(&main_flash, addr, data); + + if ( main_flash.flash_mode == FM_NORMAL ) { + bprintf(1, _T("Rom Attempt to write long value %8x to location %8x\n"), data, addr); + *(UINT32 *)(RomGame + addr) = data; + *(UINT32 *)(RomGame_D + addr) = data ^ cps3_mask(addr + 0x06000000, cps3_key1, cps3_key2); + } +} + +UINT8 __fastcall cps3RomReadByteSpe(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read byte value of location %8x\n"), addr); + addr &= 0xc7ffffff; + addr ^= 0x03; + return *(RomGame + (addr & 0x00ffffff)); +} + +UINT16 __fastcall cps3RomReadWordSpe(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read word value of location %8x\n"), addr); + addr &= 0xc7ffffff; + addr ^= 0x02; + return *(UINT16 *)(RomGame + (addr & 0x00ffffff)); +} + +UINT32 __fastcall cps3RomReadLongSpe(UINT32 addr) +{ +// bprintf(PRINT_NORMAL, _T("Rom Attempt to read long value of location %8x\n"), addr); + addr &= 0xc7ffffff; + + UINT32 retvalue = cps3_flash_read(&main_flash, addr); + if ( main_flash.flash_mode == FM_NORMAL ) + retvalue = *(UINT32 *)(RomGame + (addr & 0x00ffffff)); + + return retvalue; +} + +//------------------ + +UINT8 __fastcall cps3VidReadByte(UINT32 addr) +{ + bprintf(PRINT_NORMAL, _T("Video Attempt to read byte value of location %8x\n"), addr); +// addr &= 0xc7ffffff; + return 0; +} + +UINT16 __fastcall cps3VidReadWord(UINT32 addr) +{ + bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %8x\n"), addr); +// addr &= 0xc7ffffff; + return 0; +} + +UINT32 __fastcall cps3VidReadLong(UINT32 addr) +{ + bprintf(PRINT_NORMAL, _T("Video Attempt to read long value of location %8x\n"), addr); +// addr &= 0xc7ffffff; + return 0; +} + +void __fastcall cps3VidWriteByte(UINT32 addr, UINT8 data) +{ + bprintf(PRINT_NORMAL, _T("Video Attempt to write byte value %2x to location %8x\n"), data, addr); +} + +void __fastcall cps3VidWriteWord(UINT32 addr, UINT16 data) +{ + addr &= 0xc7ffffff; + if ((addr >= 0x04080000) && (addr < 0x040c0000)) { + // Palette + UINT32 palindex = (addr - 0x04080000) >> 1; + RamPal[palindex ^ 1] = data; + + INT32 r = (data & 0x001F) << 3; // Red + INT32 g = (data & 0x03E0) >> 2; // Green + INT32 b = (data & 0x7C00) >> 7; // Blue + + r |= r >> 5; + g |= g >> 5; + b |= b >> 5; + + Cps3CurPal[palindex] = BurnHighCol(r, g, b, 0); + + } else + bprintf(PRINT_NORMAL, _T("Video Attempt to write word value %4x to location %8x\n"), data, addr); +} + +void __fastcall cps3VidWriteLong(UINT32 addr, UINT32 data) +{ + addr &= 0xc7ffffff; + if ((addr >= 0x04080000) && (addr < 0x040c0000)) { + + if ( data != 0 ) + bprintf(PRINT_NORMAL, _T("Video Attempt to write long value %8x to location %8x\n"), data, addr); + + + } else + bprintf(PRINT_NORMAL, _T("Video Attempt to write long value %8x to location %8x\n"), data, addr); +} + + +UINT8 __fastcall cps3RamReadByte(UINT32 addr) +{ + if (addr == cps3_speedup_ram_address ) + if (Sh2GetPC(0) == cps3_speedup_code_address) + Sh2BurnUntilInt(0); + + addr &= 0x7ffff; + return *(RamMain + (addr ^ 0x03)); +} + +UINT16 __fastcall cps3RamReadWord(UINT32 addr) +{ + //bprintf(PRINT_NORMAL, _T("Ram Attempt to read long value of location %8x\n"), addr); + addr &= 0x7ffff; + + if (addr == cps3_speedup_ram_address ) + if (Sh2GetPC(0) == cps3_speedup_code_address) { + bprintf(PRINT_NORMAL, _T("Ram Attempt to read long value of location %8x\n"), addr); + Sh2BurnUntilInt(0); + } + + return *(UINT16 *)(RamMain + (addr ^ 0x02)); +} + + +UINT32 __fastcall cps3RamReadLong(UINT32 addr) +{ + if (addr == cps3_speedup_ram_address ) + if (Sh2GetPC(0) == cps3_speedup_code_address) + Sh2BurnUntilInt(0); + + addr &= 0x7ffff; + return *(UINT32 *)(RamMain + addr); +} + +// CPS3 Region Patch +static void Cps3PatchRegion() +{ + if ( cps3_region_address ) { + + bprintf(0, _T("Region: %02x -> %02x\n"), RomBios[cps3_region_address], (RomBios[cps3_region_address] & 0xf0) | (cps3_dip & 0x0f)); + + RomBios[cps3_region_address] = (RomBios[cps3_region_address] & 0xf0) | (cps3_dip & 0x7f); + if ( cps3_ncd_address ) { + if (cps3_dip & 0x10) + RomBios[cps3_ncd_address] |= 0x01; + else + RomBios[cps3_ncd_address] &= 0xfe; + } + } +} + +static INT32 Cps3Reset() +{ + // re-map cram_bank + cram_bank = 0; + Sh2MapMemory((UINT8 *)RamCRam, 0x04100000, 0x041fffff, SM_RAM); + + Cps3PatchRegion(); + + // [CD-ROM not emulated] All CHD drivers cause a Guru Meditation with the normal bios boot. + if(!BurnDrvGetHardwareCode() & HARDWARE_CAPCOM_CPS3_NO_CD){ + // normal boot + Sh2Reset( *(UINT32 *)(RomBios + 0), *(UINT32 *)(RomBios + 4) ); + } else { + // fast boot + if (cps3_isSpecial) { + Sh2Reset( *(UINT32 *)(RomGame + 0), *(UINT32 *)(RomGame + 4) ); + Sh2SetVBR(0x06000000); + } else { + Sh2Reset( *(UINT32 *)(RomGame_D + 0), *(UINT32 *)(RomGame_D + 4) ); + Sh2SetVBR(0x06000000); + } + } + + if (cps3_dip & 0x80) { + EEPROM[0x11] = 0x100 + (EEPROM[0x11] & 0xff); + EEPROM[0x29] = 0x100 + (EEPROM[0x29] & 0xff); + } else { + EEPROM[0x11] = 0x000 + (EEPROM[0x11] & 0xff); + EEPROM[0x29] = 0x000 + (EEPROM[0x29] & 0xff); + } + + cps3_current_eeprom_read = 0; + cps3SndReset(); + cps3_reset = 0; + return 0; +} + +static void be_to_le(UINT8 * p, INT32 size) +{ + UINT8 c; + for(INT32 i=0; i (cps3_gfx_width - 8)) || (y > (cps3_gfx_height - 8))) return; + UINT16 * dst = (UINT16 *) pBurnDraw; + UINT8 * src = (UINT8 *)RamSS; + UINT16 * color = Cps3CurPal + (pal << 4); + dst += (y * cps3_gfx_width + x); + src += code * 64; + + if ( flipy ) { + + dst += cps3_gfx_width * 7; + if ( flipx ) + for(INT32 i=0; i<8; i++, dst-= cps3_gfx_width, src += 8) { + if ( src[ 2] & 0xf ) dst[7] = color [ src[ 2] & 0xf ]; + if ( src[ 2] >> 4 ) dst[6] = color [ src[ 2] >> 4 ]; + if ( src[ 0] & 0xf ) dst[5] = color [ src[ 0] & 0xf ]; + if ( src[ 0] >> 4 ) dst[4] = color [ src[ 0] >> 4 ]; + if ( src[ 6] & 0xf ) dst[3] = color [ src[ 6] & 0xf ]; + if ( src[ 6] >> 4 ) dst[2] = color [ src[ 6] >> 4 ]; + if ( src[ 4] & 0xf ) dst[1] = color [ src[ 4] & 0xf ]; + if ( src[ 4] >> 4 ) dst[0] = color [ src[ 4] >> 4 ]; + } + else + for(INT32 i=0; i<8; i++, dst-= cps3_gfx_width, src += 8) { + if ( src[ 2] & 0xf ) dst[0] = color [ src[ 2] & 0xf ]; + if ( src[ 2] >> 4 ) dst[1] = color [ src[ 2] >> 4 ]; + if ( src[ 0] & 0xf ) dst[2] = color [ src[ 0] & 0xf ]; + if ( src[ 0] >> 4 ) dst[3] = color [ src[ 0] >> 4 ]; + if ( src[ 6] & 0xf ) dst[4] = color [ src[ 6] & 0xf ]; + if ( src[ 6] >> 4 ) dst[5] = color [ src[ 6] >> 4 ]; + if ( src[ 4] & 0xf ) dst[6] = color [ src[ 4] & 0xf ]; + if ( src[ 4] >> 4 ) dst[7] = color [ src[ 4] >> 4 ]; + } + + } else { + if ( flipx ) + for(INT32 i=0; i<8; i++, dst+= cps3_gfx_width, src += 8) { + if ( src[ 2] & 0xf ) dst[7] = color [ src[ 2] & 0xf ]; + if ( src[ 2] >> 4 ) dst[6] = color [ src[ 2] >> 4 ]; + if ( src[ 0] & 0xf ) dst[5] = color [ src[ 0] & 0xf ]; + if ( src[ 0] >> 4 ) dst[4] = color [ src[ 0] >> 4 ]; + if ( src[ 6] & 0xf ) dst[3] = color [ src[ 6] & 0xf ]; + if ( src[ 6] >> 4 ) dst[2] = color [ src[ 6] >> 4 ]; + if ( src[ 4] & 0xf ) dst[1] = color [ src[ 4] & 0xf ]; + if ( src[ 4] >> 4 ) dst[0] = color [ src[ 4] >> 4 ]; + } + else + for(INT32 i=0; i<8; i++, dst+= cps3_gfx_width, src += 8) { + if ( src[ 2] & 0xf ) dst[0] = color [ src[ 2] & 0xf ]; + if ( src[ 2] >> 4 ) dst[1] = color [ src[ 2] >> 4 ]; + if ( src[ 0] & 0xf ) dst[2] = color [ src[ 0] & 0xf ]; + if ( src[ 0] >> 4 ) dst[3] = color [ src[ 0] >> 4 ]; + if ( src[ 6] & 0xf ) dst[4] = color [ src[ 6] & 0xf ]; + if ( src[ 6] >> 4 ) dst[5] = color [ src[ 6] >> 4 ]; + if ( src[ 4] & 0xf ) dst[6] = color [ src[ 4] & 0xf ]; + if ( src[ 4] >> 4 ) dst[7] = color [ src[ 4] >> 4 ]; + } + } + +} + +static void cps3_drawgfxzoom_1(UINT32 code, UINT32 pal, INT32 flipx, INT32 flipy, INT32 x, INT32 y, INT32 drawline) +{ + UINT32 * dst = RamScreen; + UINT8 * src = (UINT8 *) RamCRam; + dst += (drawline * 1024 + x); + +#if BE_GFX + + if ( flipy ) { + src += code * 256 + 16 * (15 - (drawline - y)); + if ( flipx ) { + if ( src[ 0] ) dst[15] = src[ 0] | pal; + if ( src[ 1] ) dst[14] = src[ 1] | pal; + if ( src[ 2] ) dst[13] = src[ 2] | pal; + if ( src[ 3] ) dst[12] = src[ 3] | pal; + if ( src[ 4] ) dst[11] = src[ 4] | pal; + if ( src[ 5] ) dst[10] = src[ 5] | pal; + if ( src[ 6] ) dst[ 9] = src[ 6] | pal; + if ( src[ 7] ) dst[ 8] = src[ 7] | pal; + if ( src[ 8] ) dst[ 7] = src[ 8] | pal; + if ( src[ 9] ) dst[ 6] = src[ 9] | pal; + if ( src[10] ) dst[ 5] = src[10] | pal; + if ( src[11] ) dst[ 4] = src[11] | pal; + if ( src[12] ) dst[ 3] = src[12] | pal; + if ( src[13] ) dst[ 2] = src[13] | pal; + if ( src[14] ) dst[ 1] = src[14] | pal; + if ( src[15] ) dst[ 0] = src[15] | pal; + } else { + if ( src[ 0] ) dst[ 0] = src[ 0] | pal; + if ( src[ 1] ) dst[ 1] = src[ 1] | pal; + if ( src[ 2] ) dst[ 2] = src[ 2] | pal; + if ( src[ 3] ) dst[ 3] = src[ 3] | pal; + if ( src[ 4] ) dst[ 4] = src[ 4] | pal; + if ( src[ 5] ) dst[ 5] = src[ 5] | pal; + if ( src[ 6] ) dst[ 6] = src[ 6] | pal; + if ( src[ 7] ) dst[ 7] = src[ 7] | pal; + if ( src[ 8] ) dst[ 8] = src[ 8] | pal; + if ( src[ 9] ) dst[ 9] = src[ 9] | pal; + if ( src[10] ) dst[10] = src[10] | pal; + if ( src[11] ) dst[11] = src[11] | pal; + if ( src[12] ) dst[12] = src[12] | pal; + if ( src[13] ) dst[13] = src[13] | pal; + if ( src[14] ) dst[14] = src[14] | pal; + if ( src[15] ) dst[15] = src[15] | pal; + } + } else { + src += code * 256 + 16 * (drawline - y); + if ( flipx ) { + if ( src[ 0] ) dst[15] = src[ 0] | pal; + if ( src[ 1] ) dst[14] = src[ 1] | pal; + if ( src[ 2] ) dst[13] = src[ 2] | pal; + if ( src[ 3] ) dst[12] = src[ 3] | pal; + if ( src[ 4] ) dst[11] = src[ 4] | pal; + if ( src[ 5] ) dst[10] = src[ 5] | pal; + if ( src[ 6] ) dst[ 9] = src[ 6] | pal; + if ( src[ 7] ) dst[ 8] = src[ 7] | pal; + if ( src[ 8] ) dst[ 7] = src[ 8] | pal; + if ( src[ 9] ) dst[ 6] = src[ 9] | pal; + if ( src[10] ) dst[ 5] = src[10] | pal; + if ( src[11] ) dst[ 4] = src[11] | pal; + if ( src[12] ) dst[ 3] = src[12] | pal; + if ( src[13] ) dst[ 2] = src[13] | pal; + if ( src[14] ) dst[ 1] = src[14] | pal; + if ( src[15] ) dst[ 0] = src[15] | pal; + } else { + if ( src[ 0] ) dst[ 0] = src[ 0] | pal; + if ( src[ 1] ) dst[ 1] = src[ 1] | pal; + if ( src[ 2] ) dst[ 2] = src[ 2] | pal; + if ( src[ 3] ) dst[ 3] = src[ 3] | pal; + if ( src[ 4] ) dst[ 4] = src[ 4] | pal; + if ( src[ 5] ) dst[ 5] = src[ 5] | pal; + if ( src[ 6] ) dst[ 6] = src[ 6] | pal; + if ( src[ 7] ) dst[ 7] = src[ 7] | pal; + if ( src[ 8] ) dst[ 8] = src[ 8] | pal; + if ( src[ 9] ) dst[ 9] = src[ 9] | pal; + if ( src[10] ) dst[10] = src[10] | pal; + if ( src[11] ) dst[11] = src[11] | pal; + if ( src[12] ) dst[12] = src[12] | pal; + if ( src[13] ) dst[13] = src[13] | pal; + if ( src[14] ) dst[14] = src[14] | pal; + if ( src[15] ) dst[15] = src[15] | pal; + } + } + +#else + + if ( flipy ) { + src += code * 256 + 16 * (15 - (drawline - y)); + if ( flipx ) { + if ( src[ 3] ) dst[15] = src[ 3] | pal; + if ( src[ 2] ) dst[14] = src[ 2] | pal; + if ( src[ 1] ) dst[13] = src[ 1] | pal; + if ( src[ 0] ) dst[12] = src[ 0] | pal; + if ( src[ 7] ) dst[11] = src[ 7] | pal; + if ( src[ 6] ) dst[10] = src[ 6] | pal; + if ( src[ 5] ) dst[ 9] = src[ 5] | pal; + if ( src[ 4] ) dst[ 8] = src[ 4] | pal; + if ( src[11] ) dst[ 7] = src[11] | pal; + if ( src[10] ) dst[ 6] = src[10] | pal; + if ( src[ 9] ) dst[ 5] = src[ 9] | pal; + if ( src[ 8] ) dst[ 4] = src[ 8] | pal; + if ( src[15] ) dst[ 3] = src[15] | pal; + if ( src[14] ) dst[ 2] = src[14] | pal; + if ( src[13] ) dst[ 1] = src[13] | pal; + if ( src[12] ) dst[ 0] = src[12] | pal; + } else { + if ( src[ 3] ) dst[ 0] = src[ 3] | pal; + if ( src[ 2] ) dst[ 1] = src[ 2] | pal; + if ( src[ 1] ) dst[ 2] = src[ 1] | pal; + if ( src[ 0] ) dst[ 3] = src[ 0] | pal; + if ( src[ 7] ) dst[ 4] = src[ 7] | pal; + if ( src[ 6] ) dst[ 5] = src[ 6] | pal; + if ( src[ 5] ) dst[ 6] = src[ 5] | pal; + if ( src[ 4] ) dst[ 7] = src[ 4] | pal; + if ( src[11] ) dst[ 8] = src[11] | pal; + if ( src[10] ) dst[ 9] = src[10] | pal; + if ( src[ 9] ) dst[10] = src[ 9] | pal; + if ( src[ 8] ) dst[11] = src[ 8] | pal; + if ( src[15] ) dst[12] = src[15] | pal; + if ( src[14] ) dst[13] = src[14] | pal; + if ( src[13] ) dst[14] = src[13] | pal; + if ( src[12] ) dst[15] = src[12] | pal; + } + } else { + src += code * 256 + 16 * (drawline - y); + if ( flipx ) { + if ( src[ 3] ) dst[15] = src[ 3] | pal; + if ( src[ 2] ) dst[14] = src[ 2] | pal; + if ( src[ 1] ) dst[13] = src[ 1] | pal; + if ( src[ 0] ) dst[12] = src[ 0] | pal; + if ( src[ 7] ) dst[11] = src[ 7] | pal; + if ( src[ 6] ) dst[10] = src[ 6] | pal; + if ( src[ 5] ) dst[ 9] = src[ 5] | pal; + if ( src[ 4] ) dst[ 8] = src[ 4] | pal; + if ( src[11] ) dst[ 7] = src[11] | pal; + if ( src[10] ) dst[ 6] = src[10] | pal; + if ( src[ 9] ) dst[ 5] = src[ 9] | pal; + if ( src[ 8] ) dst[ 4] = src[ 8] | pal; + if ( src[15] ) dst[ 3] = src[15] | pal; + if ( src[14] ) dst[ 2] = src[14] | pal; + if ( src[13] ) dst[ 1] = src[13] | pal; + if ( src[12] ) dst[ 0] = src[12] | pal; + } else { + if ( src[ 3] ) dst[ 0] = src[ 3] | pal; + if ( src[ 2] ) dst[ 1] = src[ 2] | pal; + if ( src[ 1] ) dst[ 2] = src[ 1] | pal; + if ( src[ 0] ) dst[ 3] = src[ 0] | pal; + if ( src[ 7] ) dst[ 4] = src[ 7] | pal; + if ( src[ 6] ) dst[ 5] = src[ 6] | pal; + if ( src[ 5] ) dst[ 6] = src[ 5] | pal; + if ( src[ 4] ) dst[ 7] = src[ 4] | pal; + if ( src[11] ) dst[ 8] = src[11] | pal; + if ( src[10] ) dst[ 9] = src[10] | pal; + if ( src[ 9] ) dst[10] = src[ 9] | pal; + if ( src[ 8] ) dst[11] = src[ 8] | pal; + if ( src[15] ) dst[12] = src[15] | pal; + if ( src[14] ) dst[13] = src[14] | pal; + if ( src[13] ) dst[14] = src[13] | pal; + if ( src[12] ) dst[15] = src[12] | pal; + } + } + +#endif +} + +static void cps3_drawgfxzoom_2(UINT32 code, UINT32 pal, INT32 flipx, INT32 flipy, INT32 sx, INT32 sy, INT32 scalex, INT32 scaley, INT32 alpha) +{ + //if (!scalex || !scaley) return; + + UINT8 * source_base = (UINT8 *) RamCRam + code * 256; + + INT32 sprite_screen_height = (scaley * 16 + 0x8000) >> 16; + INT32 sprite_screen_width = (scalex * 16 + 0x8000) >> 16; + if (sprite_screen_width && sprite_screen_height) { + // compute sprite increment per screen pixel + INT32 dx = (16 << 16) / sprite_screen_width; + INT32 dy = (16 << 16) / sprite_screen_height; + + INT32 ex = sx + sprite_screen_width; + INT32 ey = sy + sprite_screen_height; + + INT32 x_index_base; + INT32 y_index; + + if( flipx ) { + x_index_base = (sprite_screen_width - 1) * dx; + dx = -dx; + } else + x_index_base = 0; + + if( flipy ) { + y_index = (sprite_screen_height - 1) * dy; + dy = -dy; + } else + y_index = 0; + + { + if( sx < 0) + { /* clip left */ + INT32 pixels = 0-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if( sy < 0 ) + { /* clip top */ + INT32 pixels = 0-sy; + sy += pixels; + y_index += pixels*dy; + } + if( ex > cps3_gfx_max_x+1 ) + { /* clip right */ + INT32 pixels = ex-cps3_gfx_max_x-1; + ex -= pixels; + } + if( ey > cps3_gfx_max_y+1 ) + { /* clip bottom */ + INT32 pixels = ey-cps3_gfx_max_y-1; + ey -= pixels; + } + } + + if( ex > sx ) { + switch( alpha ) { + case 0: + for( INT32 y=sy; y>16) * 16; + UINT32 * dest = RamScreen + y * 512 * 2; + INT32 x_index = x_index_base; + for(INT32 x=sx; x>16) ]; +#else + UINT8 c = source[ (x_index>>16) ^ 3 ]; +#endif + if( c ) dest[x] = pal | c; + x_index += dx; + } + y_index += dy; + } + break; + case 6: + for( INT32 y=sy; y>16) * 16; + UINT32 * dest = RamScreen + y * 512 * 2; + INT32 x_index = x_index_base; + for(INT32 x=sx; x>16)]; +#else + UINT8 c = source[ (x_index>>16) ^ 3 ]; +#endif + dest[x] |= ((c&0x0000f) << 13); + x_index += dx; + } + y_index += dy; + } + break; + case 8: + for( INT32 y=sy; y>16) * 16; + UINT32 * dest = RamScreen + y * 512 * 2; + INT32 x_index = x_index_base; + for(INT32 x=sx; x>16) ]; +#else + UINT8 c = source[ (x_index>>16) ^ 3 ]; +#endif + +/* + * 0x00000 ~ 0x07fff : normal color for sprites + * 0x08000 ~ 0x0ffff : alpha color for sprites's shadow or other effect + * + * 0x10000 ~ 0x17fff : normal color for sprites ?? (redearth) + * 0x18000 ~ 0x1ffff : fire alpha ?? (redearth) + * 0x17e00 ~ 0x17fff : foreground ?? (jojo) + */ + if (c) { + // jojo intro + + // global local bground alpha + // -------- -------- -------- ----- + // 0x12400 0x12700 0x00500 10 : title in intro (jojo) + // 0x00000 0x0008f 0x06a40 10 : avatar shadow in intro (jojo) + // 0x00100 0x0008f 0x06a40 10 : star in avatar shadow in intro (jojo) + + // 0x00000 0x00000 0x01180 10 : charactor select background mask (sfiii3) + // 0x00000 0x00000 0x0???? 10 : charactor shadow (sfiii3) + + // 0x00000 0x11d00 0x01640 01 : magic transview (redearth) + + dest[x] |= 0x8000; + + // this bit seems correct to magic effect for redearth + // but got jojo's title to black in it's intro + // is here difference between global palette and local palette ?? + if (pal&0x10000) dest[x] |= 0x10000; + + // jojo intro , a alpha effect star in avatar's shadow + // this bit seems to disable alpha effect + //if (pal & 0x100) dest[x] &= 0x17fff; + + + } + x_index += dx; + } + y_index += dy; + } + break; + } + + } + } +} + + + +static void cps3_draw_tilemapsprite_line(INT32 drawline, UINT32 * regs ) +{ + INT32 scrolly = ((regs[0]&0x0000ffff)>>0)+4; + INT32 line = drawline + scrolly; + line &= 0x3ff; + + if (!(regs[1]&0x00008000)) return; + + { + UINT32 mapbase = (regs[2]&0x007f0000)>>16; + UINT32 linebase= (regs[2]&0x7f000000)>>24; + INT32 linescroll_enable = (regs[1]&0x00004000); + + INT32 scrollx; + INT32 tileline = (line/16)+1; + INT32 tilesubline = line % 16; + + //rectangle clip; + + mapbase = mapbase << 10; + linebase = linebase << 10; + + if (!linescroll_enable) { + scrollx = (regs[0]&0xffff0000)>>16; + } else { + // printf("linebase %08x\n", linebase); + scrollx = (regs[0]&0xffff0000)>>16; + scrollx+= (RamSpr[linebase+((line+16-4)&0x3ff)]>>16)&0x3ff; + } + +// drawline &= 0x3ff; + + if (drawline>cps3_gfx_max_y+4) return; + + //clip.min_x = cliprect->min_x; + //clip.max_x = cliprect->max_x; + //clip.min_y = drawline; + //clip.max_y = drawline; + +//if (Cps3But2[9]) +// bprintf(0, _T("TILE LINE %4d %5d %5d %d\n"), drawline, scrollx, scrolly, linescroll_enable>>14); + + for (INT32 x=0;x<(cps3_gfx_max_x/16)+2;x++) { + + UINT32 dat; + INT32 tileno; + INT32 colour; + INT32 bpp; + INT32 xflip,yflip; + + dat = RamSpr[mapbase+((tileline&63)*64)+((x+scrollx/16)&63)]; + tileno = (dat & 0xffff0000)>>17; + colour = (dat & 0x000001ff)>>0; + bpp = (dat & 0x0000200)>>9; + yflip = (dat & 0x00000800)>>11; + xflip = (dat & 0x00001000)>>12; + + //if (!bpp) Machine->gfx[1]->color_granularity=256; + //else Machine->gfx[1]->color_granularity=64; + if (!bpp) colour <<= 8; + else colour <<= 6; + + //colour &= 0x1ffff; + +//if (Cps3But2[9] && x==0) +// bprintf(0, _T(" %08x %08x %5d %5d\n"),tileno, colour, (x*16)-scrollx%16,drawline-tilesubline); + + //if (cps3_char_ram_dirty[tileno]) { + // decodechar(Machine->gfx[1], tileno, (UINT8*)cps3_char_ram, &cps3_tiles16x16_layout); + // cps3_char_ram_dirty[tileno] = 0; + //} + + //cps3_drawgfxzoom(bitmap, Machine->gfx[1],tileno,colour,xflip,yflip,(x*16)-scrollx%16,drawline-tilesubline,&clip,CPS3_TRANSPARENCY_PEN_INDEX,0, 0x10000, 0x10000, NULL, 0); + cps3_drawgfxzoom_1(tileno,colour,xflip,yflip,(x*16)-scrollx%16,drawline-tilesubline, drawline); + } + } +} + +static INT32 WideScreenFrameDelay = 0; + +static void DrvDraw() +{ + INT32 bg_drawn[4] = { 0, 0, 0, 0 }; + + // registers are normally 002a006f 01ef01c6 + // widescreen mode = 00230076 026501c6 + // only SFIII2 uses widescreen, I don't know exactly which register controls it + //if (((RamVReg[ 6 * 4 + 1 ]&0xffff0000)>>16) != 0x01ef) { + // bprintf(0, _T("Wide Screen Mode %08x\n"), RamVReg[ 6 * 4 + 1 ]); + //} + + // fullscreenzoom 0x40 for normal size + // 0x80 for double size + // 0x20 for half size + UINT32 fullscreenzoom = RamVReg[ 6 * 4 + 3 ] & 0xff; // cps3_fullscreenzoom[3] + UINT32 fullscreenzoomwidecheck = RamVReg[6 * 4 + 1]; + + if (((fullscreenzoomwidecheck & 0xffff0000) >> 16) == 0x0265) { + INT32 Width, Height; + BurnDrvGetVisibleSize(&Width, &Height); + + if (Width != 496) { + BurnDrvSetVisibleSize(496, 224); + BurnDrvSetAspect(16, 9); + Reinitialise(); + WideScreenFrameDelay = GetCurrentFrame() + 1; + } + } else { + INT32 Width, Height; + BurnDrvGetVisibleSize(&Width, &Height); + + if (Width != 384) { + BurnDrvSetVisibleSize(384, 224); + BurnDrvSetAspect(4, 3); + Reinitialise(); + WideScreenFrameDelay = GetCurrentFrame() + 1; + } + } + + if (fullscreenzoom > 0x80) fullscreenzoom = 0x80; + UINT32 fsz = (fullscreenzoom << (16 - 6)); + + cps3_gfx_max_x = ((cps3_gfx_width * fsz) >> 16) - 1; // 384 ( 496 for SFIII2 Only) + cps3_gfx_max_y = ((cps3_gfx_height * fsz) >> 16) - 1; // 224 + +#if 0 +if (Cps3But2[9]) { + bprintf(0, _T("New Frame -------------------\n")); + + FILE * f = fopen("RamSpr.dump", "wb+"); + fwrite(RamSpr, 1, 0x0080000, f); + fclose(f); + + f = fopen("RamVReg.dump", "wb+"); + fwrite(RamVReg, 1, 0x0000100, f); + fclose(f); + + f = fopen("RamPal.dump", "wb+"); + fwrite(RamPal, 1, 0x0040000, f); + fclose(f); + + f = fopen("Cps3CurPal.raw", "wb+"); + fwrite(Cps3CurPal, 1, 0x0040000, f); + fclose(f); + + + f = fopen("RamCRam.dump", "wb+"); + fwrite(RamCRam, 1, 0x0800000, f); + fclose(f); + + f = fopen("RamScreen.dump", "wb+"); + fwrite(RamScreen + 512 * 2 * 16 + 16, 1, 512 * 2 * 224 * 2 * 2, f); + fclose(f); + + //RamScreen = (UINT32 *) Next; Next += (512 * 2) * (224 * 2 + 32) * sizeof(UINT32); +} +#endif + + if (nBurnLayer & 1) // iq_132 - layer disable + { + // Clear Screen Buffer + //memset(RamScreen, 0, 512 * 448 * sizeof(UINT32)); + UINT32 * pscr = RamScreen; + INT32 clrsz = (cps3_gfx_max_x + 1) * sizeof(INT32); + for(INT32 yy = 0; yy<=cps3_gfx_max_y; yy++, pscr += 512*2) + memset(pscr, 0, clrsz); + } + // iq_132 - layer disable + else + { + Cps3CurPal[0x20000] = BurnHighCol(0xff, 0x00, 0xff, 0); // ma-fucking-genta + + INT32 i; + for (i = 0; i < 1024 * 448; i++) { + RamScreen[i] = 0x20000; + } + } + // iq_132 - layer disable + + // Draw Sprites + { + for (INT32 i=0x00000/4;i<0x2000/4;i+=4) { + INT32 xpos = (RamSpr[i+1]&0x03ff0000)>>16; + INT32 ypos = (RamSpr[i+1]&0x000003ff)>>0; + + INT32 gscroll = (RamSpr[i+0]&0x70000000)>>28; + INT32 length = (RamSpr[i+0]&0x01ff0000)>>14; // how many entries in the sprite table + UINT32 start= (RamSpr[i+0]&0x00007ff0)>>4; + + INT32 whichbpp = (RamSpr[i+2]&0x40000000)>>30; // not 100% sure if this is right, jojo title / characters + INT32 whichpal = (RamSpr[i+2]&0x20000000)>>29; + INT32 global_xflip = (RamSpr[i+2]&0x10000000)>>28; + INT32 global_yflip = (RamSpr[i+2]&0x08000000)>>27; + INT32 global_alpha = (RamSpr[i+2]&0x04000000)>>26; // alpha / shadow? set on sfiii2 shadows, and big black image in jojo intro + INT32 global_bpp = (RamSpr[i+2]&0x02000000)>>25; + INT32 global_pal = (RamSpr[i+2]&0x01ff0000)>>16; + + INT32 gscrollx = (RamVReg[gscroll]&0x03ff0000)>>16; + INT32 gscrolly = (RamVReg[gscroll]&0x000003ff)>>0; + + start = (start * 0x100) >> 2; + + if ((RamSpr[i+0]&0xf0000000) == 0x80000000) break; + + for (INT32 j=0; j>17; + INT32 count; + INT32 xpos2 = (value2 & 0x03ff0000)>>16; + INT32 ypos2 = (value2 & 0x000003ff)>>0; + INT32 flipx = (value1 & 0x00001000)>>12; + INT32 flipy = (value1 & 0x00000800)>>11; + INT32 alpha = (value1 & 0x00000400)>>10; //? this one is used for alpha effects on warzard + INT32 bpp = (value1 & 0x00000200)>>9; + INT32 pal = (value1 & 0x000001ff); + + /* these are the sizes to actually draw */ + INT32 ysizedraw2 = ((value3 & 0x7f000000)>>24); + INT32 xsizedraw2 = ((value3 & 0x007f0000)>>16); + INT32 xx,yy; + + INT32 tilestable[4] = { 8,1,2,4 }; + INT32 ysize2 = ((value3 & 0x0000000c)>>2); + INT32 xsize2 = ((value3 & 0x00000003)>>0); + UINT32 xinc,yinc; + + // invalid sprite ysize of 0 tiles + if (ysize2==0) continue; + + // xsize of 0 tiles seems to be a special command to draw tilemaps + if (xsize2==0) { + + if (nBurnLayer & 1) // iq_132 - layer disable + { + + INT32 tilemapnum = ((value3 & 0x00000030)>>4); + INT32 startline;// = value2 & 0x3ff; + INT32 endline; + INT32 height = (value3 & 0x7f000000)>>24; + UINT32 * regs; + //UINT32 * tmapregs[4] = { tilemap20_regs_base, tilemap30_regs_base, tilemap40_regs_base, tilemap50_regs_base }; + //regs = tmapregs[tilemapnum]; + regs = RamVReg + 8 + tilemapnum * 4; + endline = value2; + startline = endline - height; + + startline &=0x3ff; + endline &=0x3ff; + + //printf("tilemap draw %01x %02x %02x %02x\n",tilemapnum, value2, height, regs[0]&0x000003ff ); + //printf("tilemap draw %01x %d %d\n",tilemapnum, startline, endline ); + //bprintf(0, _T("tilemap draw %01x %d %d\n"),tilemapnum, startline, endline ); + + // Urgh, the startline / endline seem to be direct screen co-ordinates regardless of fullscreen zoom + // which probably means the fullscreen zoom is applied when rendering everything, not aftewards + + //for (uu=startline;uu>16); + else xpos2+= (xsize2)*((16*xinc)>>16); + + if (flipy) ypos2-= ysize2*((16*yinc)>>16); +#else + if (!flipx) xpos2-= (((xsize2+1)*16*xinc)>>16); + else xpos2+= (((xsize2)*16*xinc)>>16); + + if (flipy) ypos2-= ((ysize2*16*yinc)>>16); +#endif + { + count = 0; + for (xx=0;xx>16) ); + else current_xpos = (xpos+xpos2-xx*((16*xinc)>>16)); +#else + if (!flipx) current_xpos = (xpos+xpos2+((xx*16*xinc)>>16) ); + else current_xpos = (xpos+xpos2-((xx*16*xinc)>>16)); +#endif + //current_xpos += rand()&0x3ff; + current_xpos += gscrollx; + current_xpos += 1; + current_xpos &=0x3ff; + if (current_xpos&0x200) current_xpos-=0x400; + + for (yy=0;yy>16)); + else current_ypos = (ypos+ypos2-yy*((16*yinc)>>16)); +#else + if (flipy) current_ypos = (ypos+ypos2+((yy*16*yinc)>>16)); + else current_ypos = (ypos+ypos2-((yy*16*yinc)>>16)); +#endif + current_ypos += gscrolly; + current_ypos = 0x3ff-current_ypos; + current_ypos -= 17; + current_ypos &=0x3ff; + + if (current_ypos&0x200) current_ypos-=0x400; + + //if ( (whichbpp) && (cpu_getcurrentframe() & 1)) continue; + + /* use the palette value from the main list or the sublists? */ + if (whichpal) actualpal = global_pal; + else actualpal = pal; + + /* use the bpp value from the main list or the sublists? */ + INT32 color_granularity; + if (whichbpp) { + if (!global_bpp) color_granularity = 8; + else color_granularity = 6; + } else { + if (!bpp) color_granularity = 8; + else color_granularity = 6; + } + actualpal <<= color_granularity; + + { + INT32 realtileno = tileno+count; + +//if (Cps3But2[9]) +// bprintf(0, _T("%08x %08x %08x %d %d %5d %5d %4x %4x %d %02x\n"), realtileno,global_pal, pal, 0^flipx, 0^flipy, current_xpos,current_ypos,xinc,yinc, color_granularity, (global_alpha << 4) | alpha ); + + if ( realtileno ) { + if (global_alpha || alpha) { + + // fix jojo's title in it's intro ??? + if ( global_alpha && (global_pal & 0x100)) + actualpal &= 0x0ffff; + + //cps3_drawgfxzoom(renderbuffer_bitmap, machine->gfx[1],realtileno,actualpal,0^flipx,0^flipy,current_xpos,current_ypos,&renderbuffer_clip,CPS3_TRANSPARENCY_PEN_INDEX_BLEND,0,xinc,yinc, NULL, 0); + cps3_drawgfxzoom_2(realtileno,actualpal,0^flipx,0^flipy,current_xpos,current_ypos,xinc,yinc, color_granularity); + + } else { + //cps3_drawgfxzoom(renderbuffer_bitmap, machine->gfx[1],realtileno,actualpal,0^flipx,0^flipy,current_xpos,current_ypos,&renderbuffer_clip,CPS3_TRANSPARENCY_PEN_INDEX,0,xinc,yinc, NULL, 0); + cps3_drawgfxzoom_2(realtileno,actualpal,0^flipx,0^flipy,current_xpos,current_ypos,xinc,yinc, 0); + } + } + count++; + } + } + } + } + } + } + } + } + + //copy screen from pBurnDraw with zoom + { + UINT32 srcx, srcy = 0; + UINT32 * srcbitmap; + UINT16 * dstbitmap = (UINT16 * )pBurnDraw; + + for (INT32 rendery=0; rendery<224; rendery++) { + srcbitmap = RamScreen + (srcy >> 16) * 512 * 2; + srcx=0; + for (INT32 renderx=0; renderx>16] ]; + srcx += fsz; + } + srcy += fsz; + } + } + + + // fg layer + if (nBurnLayer & 2) // iq_132 -- layer disable + { + // bank select? (sfiii2 intro) + INT32 count = (ss_bank_base & 0x01000000) ? 0x0000 : 0x0800; + for (INT32 y=0; y<32; y++) { + for (INT32 x=0; x<64; x++) { + UINT32 data = RamSS[count]; // +0x800 = 2nd bank, used on sfiii2 intro.. + UINT32 tile = (data >> 16) & 0x1ff; + INT32 pal = (data & 0x003f) >> 1; + INT32 flipx = (data & 0x0080) >> 7; + INT32 flipy = (data & 0x0040) >> 6; + pal += ss_pal_base << 5; + tile+=0x200; + //cps3_drawgfxzoom(bitmap, machine->gfx[0],tile,pal,flipx,flipy,x*8,y*8,cliprect,CPS3_TRANSPARENCY_PEN,0,0x10000,0x10000,NULL,0); + cps3_drawgfxzoom_0(tile,pal,flipx,flipy,x*8,y*8); + count++; + } + } + } + + +} + +static INT32 cps_int10_cnt = 0; + +INT32 cps3Frame() +{ + if (cps3_reset) + Cps3Reset(); + + if (cps3_palette_change) { + for(INT32 i=0;i<0x0020000;i++) { + INT32 data = RamPal[i ^ 1]; + INT32 r = (data & 0x001F) << 3; // Red + INT32 g = (data & 0x03E0) >> 2; // Green + INT32 b = (data & 0x7C00) >> 7; // Blue + r |= r >> 5; + g |= g >> 5; + b |= b >> 5; + Cps3CurPal[i] = BurnHighCol(r, g, b, 0); + } + cps3_palette_change = 0; + } + + if (WideScreenFrameDelay == GetCurrentFrame()) { + BurnDrvGetVisibleSize(&cps3_gfx_width, &cps3_gfx_height); + WideScreenFrameDelay = 0; + } + +// EEPROM[0x11] = 0x100 + (EEPROM[0x11] & 0xff); +// EEPROM[0x29] = 0x100 + (EEPROM[0x29] & 0xff); + + Cps3Input[0] = 0; + Cps3Input[1] = 0; + //Cps3Input[2] = 0; + Cps3Input[3] = 0; + for (INT32 i=0; i<16; i++) { + Cps3Input[0] |= (Cps3But1[i] & 1) << i; + Cps3Input[1] |= (Cps3But2[i] & 1) << i; + Cps3Input[3] |= (Cps3But3[i] & 1) << i; + } + + // Clear Opposites + Cps3ClearOpposites(&Cps3Input[0]); + Cps3ClearOpposites(&Cps3Input[1]); + + for (INT32 i=0; i<4; i++) { + + Sh2Run(6250000 * 4 / 60 / 4); + + if (cps_int10_cnt >= 2) { + cps_int10_cnt = 0; + Sh2SetIRQLine(10, SH2_IRQSTATUS_AUTO); + } else cps_int10_cnt++; + + } + Sh2SetIRQLine(12, SH2_IRQSTATUS_AUTO); + + cps3SndUpdate(); + +// bprintf(0, _T("PC: %08x\n"), Sh2GetPC(0)); + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +INT32 cps3Scan(INT32 nAction, INT32 *pnMin) +{ + if (pnMin) *pnMin = 0x029672; + + struct BurnArea ba; + + if (nAction & ACB_NVRAM) { + // Save EEPROM configuration + ba.Data = EEPROM; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "EEPROM RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { + + ba.Data = RamMain; + ba.nLen = 0x0080000; + ba.nAddress = 0; + ba.szName = "Main RAM"; + BurnAcb(&ba); + + ba.Data = RamSpr; + ba.nLen = 0x0080000; + ba.nAddress = 0; + ba.szName = "Sprite RAM"; + BurnAcb(&ba); + + ba.Data = RamSS; + ba.nLen = 0x0010000; + ba.nAddress = 0; + ba.szName = "Char ROM"; + BurnAcb(&ba); + + ba.Data = RamVReg; + ba.nLen = 0x0000100; + ba.nAddress = 0; + ba.szName = "Video REG"; + BurnAcb(&ba); + + ba.Data = RamC000; + ba.nLen = 0x0000400 * 2; + ba.nAddress = 0; + ba.szName = "RAM C000"; + BurnAcb(&ba); + + ba.Data = RamPal; + ba.nLen = 0x0040000; + ba.nAddress = 0; + ba.szName = "Palette"; + BurnAcb(&ba); + + ba.Data = RamCRam; + ba.nLen = 0x0800000; + ba.nAddress = 0; + ba.szName = "Sprite ROM"; + BurnAcb(&ba); + +/* // so huge. need not backup it while NOCD + // otherwize, need backup gfx also + ba.Data = RomGame; + ba.nLen = 0x1000000; + ba.nAddress = 0; + ba.szName = "Game ROM"; + BurnAcb(&ba); +*/ + } + + if (nAction & ACB_DRIVER_DATA) { + + Sh2Scan(nAction); + cps3SndScan(nAction); + + SCAN_VAR(Cps3Input); + + SCAN_VAR(ss_bank_base); + SCAN_VAR(ss_pal_base); + SCAN_VAR(cram_bank); + SCAN_VAR(cps3_current_eeprom_read); + SCAN_VAR(gfxflash_bank); + + SCAN_VAR(paldma_source); + SCAN_VAR(paldma_dest); + SCAN_VAR(paldma_fade); + SCAN_VAR(paldma_length); + + SCAN_VAR(chardma_source); + SCAN_VAR(chardma_table_address); + + //SCAN_VAR(main_flash); + + //SCAN_VAR(last_normal_byte); + //SCAN_VAR(lastb); + //SCAN_VAR(lastb2); + + SCAN_VAR(cps_int10_cnt); + + if (nAction & ACB_WRITE) { + + // rebuild current palette + cps3_palette_change = 1; + + // remap RamCRam + Sh2MapMemory(((UINT8 *)RamCRam) + (cram_bank << 20), 0x04100000, 0x041fffff, SM_RAM); + + } + + } + + return 0; +} diff --git a/src/burn/drivers/cps3/cps3snd.cpp b/src/burn/drivers/cps3/cps3snd.cpp new file mode 100644 index 00000000..a7997a75 --- /dev/null +++ b/src/burn/drivers/cps3/cps3snd.cpp @@ -0,0 +1,215 @@ +#include "cps3.h" + +#define CPS3_VOICES 16 + +#define CPS3_SND_INT_RATE (nBurnFPS / 100) +#define CPS3_SND_RATE (42954500 / 3 / 384) +#define CPS3_SND_BUFFER_SIZE (CPS3_SND_RATE / CPS3_SND_INT_RATE) +#define CPS3_SND_LINEAR_SHIFT 12 + +typedef struct { + UINT16 regs[16]; + UINT32 pos; + UINT16 frac; +} cps3_voice; + +typedef struct { + cps3_voice voice[CPS3_VOICES]; + UINT16 key; + + UINT8 * rombase; + UINT32 delta; + +} cps3snd_chip; + +static cps3snd_chip * chip; + +UINT8 __fastcall cps3SndReadByte(UINT32 addr) +{ + addr &= 0x000003ff; + bprintf(PRINT_NORMAL, _T("SND Attempt to read byte value of location %8x\n"), addr); + return 0; +} + +UINT16 __fastcall cps3SndReadWord(UINT32 addr) +{ + addr &= 0x000003ff; + + if (addr < 0x200) { + return chip->voice[addr >> 5].regs[(addr>>1) & 0xf]; + } else + if (addr == 0x200) { + return chip->key; + } else + + bprintf(PRINT_NORMAL, _T("SND Attempt to read word value of location %8x\n"), addr); + return 0; +} + +UINT32 __fastcall cps3SndReadLong(UINT32 addr) +{ + addr &= 0x000003ff; + + bprintf(PRINT_NORMAL, _T("SND Attempt to read long value of location %8x\n"), addr); + return 0; +} + +void __fastcall cps3SndWriteByte(UINT32 addr, UINT8 data) +{ + addr &= 0x000003ff; + bprintf(PRINT_NORMAL, _T("SND Attempt to write byte value %2x to location %8x\n"), data, addr); +} + +void __fastcall cps3SndWriteWord(UINT32 addr, UINT16 data) +{ + addr &= 0x000003ff; + + if (addr < 0x200) { + chip->voice[addr >> 5].regs[(addr>>1) & 0xf] = data; + //bprintf(PRINT_NORMAL, _T("SND Attempt to write word value %4x to Chip[%02d][%02d] %s\n"), data, addr >> 5, (addr>>2) & 7, (addr & 0x02) ? "lo" : "hi" ); + } else + if (addr == 0x200) { + UINT16 key = data; + for (INT32 i = 0; i < CPS3_VOICES; i++) { + // Key off -> Key on + if ((key & (1 << i)) && !(chip->key & (1 << i))) { + chip->voice[i].frac = 0; + chip->voice[i].pos = 0; + } + } + chip->key = key; + } else + bprintf(PRINT_NORMAL, _T("SND Attempt to write word value %4x to location %8x\n"), data, addr); + +} + +void __fastcall cps3SndWriteLong(UINT32 addr, UINT32 data) +{ + //addr &= 0x000003ff; + bprintf(PRINT_NORMAL, _T("SND Attempt to write long value %8x to location %8x\n"), data, addr); +} + +INT32 cps3SndInit(UINT8 * sndrom) +{ + chip = (cps3snd_chip *) malloc( sizeof(cps3snd_chip) ); + if ( chip ) { + memset( chip, 0, sizeof(cps3snd_chip) ); + chip->rombase = sndrom; + + /* + * CPS-3 Sound chip clock: 42954500 / 3 / 384 = 37286.89 + * Sound interupt 80Hz + */ + + if (nBurnSoundRate) { + //chip->delta = 37286.9 / nBurnSoundRate; + chip->delta = (CPS3_SND_BUFFER_SIZE << CPS3_SND_LINEAR_SHIFT) / nBurnSoundLen; + //bprintf(0, _T("BurnSnd %08x, %d, %d\n"), chip->delta, chip->burnlen, nBurnSoundLen); + } + + return 0; + } + return 1; +} + +void cps3SndReset() +{ +} + +void cps3SndExit() +{ + if (chip) { + free( chip ); + chip = NULL; + } +} + +void cps3SndUpdate() +{ + if (!pBurnSoundOut) { + // TODO: ??? + // chip->key = 0; + return; + } + + memset(pBurnSoundOut, 0, nBurnSoundLen * 2 * 2 ); + INT8 * base = (INT8 *)chip->rombase; + cps3_voice *vptr = &chip->voice[0]; + + for(INT32 i=0; ikey & (1 << i)) { + + UINT32 start = ((vptr->regs[ 3] << 16) | vptr->regs[ 2]) - 0x400000; + UINT32 end = ((vptr->regs[11] << 16) | vptr->regs[10]) - 0x400000; + UINT32 loop = ((vptr->regs[ 9] << 16) | vptr->regs[ 7]) - 0x400000; + UINT32 step = ( vptr->regs[ 6] * chip->delta ) >> CPS3_SND_LINEAR_SHIFT; + + //INT32 vol_l = ((signed short)vptr->regs[15] * 12) >> 4; + //INT32 vol_r = ((signed short)vptr->regs[14] * 12) >> 4; + INT32 vol_l = (INT16)vptr->regs[15]; + INT32 vol_r = (INT16)vptr->regs[14]; + + UINT32 pos = vptr->pos; + UINT32 frac = vptr->frac; + + /* Go through the buffer and add voice contributions */ + INT16 * buffer = (INT16 *)pBurnSoundOut; + + for (INT32 j=0; j> 12); + frac &= 0xfff; + + if (start + pos >= end) { + if (vptr->regs[5]) { + pos = loop - start; + } else { + chip->key &= ~(1 << i); + break; + } + } + + // 8bit sample store with 16bit bigend ??? + sample = base[(start + pos) ^ 1]; + frac += step; + +#if 1 + INT32 sample_l; + + sample_l = ((sample * vol_r) >> 8) + buffer[0]; + if (sample_l > 32767) buffer[0] = 32767; + else if (sample_l < -32768) buffer[0] = -32768; + else buffer[0] = sample_l; + + sample_l = ((sample * vol_l) >> 8) + buffer[1]; + if (sample_l > 32767) buffer[1] = 32767; + else if (sample_l < -32768) buffer[1] = -32768; + else buffer[1] = sample_l; +#else + buffer[0] += (sample * (vol_l >> 8)); + buffer[1] += (sample * (vol_r >> 8)); +#endif + + buffer += 2; + } + + + vptr->pos = pos; + vptr->frac = frac; + } + } + +} + +INT32 cps3SndScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + + SCAN_VAR( chip->voice ); + SCAN_VAR( chip->key ); + + } + return 0; +} + diff --git a/src/burn/drivers/cps3/d_cps3.cpp b/src/burn/drivers/cps3/d_cps3.cpp new file mode 100644 index 00000000..787e2007 --- /dev/null +++ b/src/burn/drivers/cps3/d_cps3.cpp @@ -0,0 +1,1204 @@ +// ------------------------------------------------------------------------------------ +// Capcom Play System III Drivers for FB Alpha (2007 - 2008). +// ------------------------------------------------------------------------------------ +// +// v1 [ OopsWare ] +// - Original drivers release. +// +// v2 [ CaptainCPS-X ] +// - Verified drivers. +// - Updated DIPs. +// - Updated some Inits. +// - Added some Comments. +// +// v3 [ BisonSAS ] +// - Added default game regions DIPs. +// - Added unicode titles for "jojo" and "jojoba". +// - Changed the redeartn BIOS to "warzard_euro.29f400.u2". +// - Added "HARDWARE_CAPCOM_CPS3_NO_CD" flag for NOCD sets. +// +// v4 [ CaptainCPS-X ] +// - Updated comments & organized structures of code. +// - Revised code for compatibility with FB Alpha Enhanced. +// +// More info: http://neosource.1emu.net/forums/index.php +// +// ------------------------------------------------------------------------------------ + +#include "cps3.h" + +static struct BurnInputInfo cps3InputList[] = { + {"P1 Coin", BIT_DIGITAL, Cps3But2 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, Cps3But2 + 12, "p1 start" }, + + {"P1 Up", BIT_DIGITAL, Cps3But1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, Cps3But1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, Cps3But1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, Cps3But1 + 3, "p1 right" }, + {"P1 Weak Punch", BIT_DIGITAL, Cps3But1 + 4, "p1 fire 1" }, + {"P1 Medium Punch", BIT_DIGITAL, Cps3But1 + 5, "p1 fire 2" }, + {"P1 Strong Punch", BIT_DIGITAL, Cps3But1 + 6, "p1 fire 3" }, + {"P1 Weak Kick", BIT_DIGITAL, Cps3But3 + 3, "p1 fire 4" }, + {"P1 Medium Kick", BIT_DIGITAL, Cps3But3 + 2, "p1 fire 5" }, + {"P1 Strong Kick", BIT_DIGITAL, Cps3But3 + 1, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, Cps3But2 + 9, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, Cps3But2 + 13, "p2 start" }, + + {"P2 Up", BIT_DIGITAL, Cps3But1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, Cps3But1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, Cps3But1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, Cps3But1 + 11, "p2 right" }, + {"P2 Weak Punch", BIT_DIGITAL, Cps3But1 + 12, "p2 fire 1" }, + {"P2 Medium Punch", BIT_DIGITAL, Cps3But1 + 13, "p2 fire 2" }, + {"P2 Strong Punch", BIT_DIGITAL, Cps3But1 + 14, "p2 fire 3" }, + {"P2 Weak Kick", BIT_DIGITAL, Cps3But3 + 4, "p2 fire 4" }, + {"P2 Medium Kick", BIT_DIGITAL, Cps3But3 + 5, "p2 fire 5" }, + {"P2 Strong Kick", BIT_DIGITAL, Cps3But2 + 10, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &cps3_reset, "reset" }, + {"Diagnostic", BIT_DIGITAL, Cps3But2 + 1, "diag" }, + {"Service", BIT_DIGITAL, Cps3But2 + 0, "service" }, + {"Region", BIT_DIPSWITCH, &cps3_dip, "dip" }, +}; + +STDINPUTINFO(cps3) + +// ------------------------------------------------------------------------------------ + +static struct BurnDIPInfo regionDIPList[] = { + + // Region + {0, 0xFD, 0, 7, "Region"}, + {0x1B, 0x01, 0xFF, 0x01, "Japan"}, + {0x1B, 0x01, 0xFF, 0x02, "Asia"}, + {0x1B, 0x01, 0xFF, 0x03, "Euro"}, + {0x1B, 0x01, 0xFF, 0x04, "USA"}, + {0x1B, 0x01, 0xFF, 0x05, "Hispanic"}, + {0x1B, 0x01, 0xFF, 0x06, "Brazil"}, + {0x1B, 0x01, 0xFF, 0x07, "Oceania"}, + {0x1B, 0x01, 0xFF, 0x08, "Asia"}, + {0x1B, 0x01, 0xFF, 0x00, "XXXXXX"}, + +// {0, 0xFE, 0, 2, "NO CD"}, +// {0x1B, 0x01, 0x10, 0x00, "No"}, +// {0x1B, 0x01, 0x10, 0x10, "Yes"}, +}; + +static struct BurnDIPInfo jojobaRegionDIPList[] = { + + // Region + {0, 0xFD, 0, 8, "Region"}, + {0x1B, 0x01, 0xFF, 0x01, "Japan"}, + {0x1B, 0x01, 0xFF, 0x02, "Asia"}, + {0x1B, 0x01, 0xFF, 0x03, "Euro"}, + {0x1B, 0x01, 0xFF, 0x04, "USA"}, + {0x1B, 0x01, 0xFF, 0x05, "Hispanic"}, + {0x1B, 0x01, 0xFF, 0x06, "Brazil"}, + {0x1B, 0x01, 0xFF, 0x07, "Oceania"}, + {0x1B, 0x01, 0xFF, 0x08, "Korea"}, // fake region? + {0x1B, 0x01, 0xFF, 0x00, "XXXXXX"}, +}; + +static struct BurnDIPInfo redeartnRegionDIPList[] = { + + // Region + {0, 0xFD, 0, 7, "Region"}, + {0x1B, 0x01, 0xFF, 0x51, "Japan"}, + {0x1B, 0x01, 0xFF, 0x52, "Asia"}, + {0x1B, 0x01, 0xFF, 0x53, "Euro"}, + {0x1B, 0x01, 0xFF, 0x54, "USA"}, + {0x1B, 0x01, 0xFF, 0x55, "Hispanic"}, + {0x1B, 0x01, 0xFF, 0x56, "Brazil"}, + {0x1B, 0x01, 0xFF, 0x57, "Oceania"}, + {0x1B, 0x01, 0xFF, 0x58, "Asia"}, + {0x1B, 0x01, 0xFF, 0x50, "Japan"}, +}; + +static struct BurnDIPInfo sfiiiDIPList[] = { + + // Region + {0, 0xFD, 0, 7, "Region"}, + {0x1B, 0x01, 0x0F, 0x01, "Japan"}, + {0x1B, 0x01, 0x0F, 0x02, "Asia"}, + {0x1B, 0x01, 0x0F, 0x03, "Euro"}, + {0x1B, 0x01, 0x0F, 0x04, "USA"}, + {0x1B, 0x01, 0x0F, 0x05, "Hispanic"}, + {0x1B, 0x01, 0x0F, 0x06, "Brazil"}, + {0x1B, 0x01, 0x0F, 0x07, "Oceania"}, + {0x1B, 0x01, 0x0F, 0x08, "Asia"}, + {0x1B, 0x01, 0x0F, 0x00, "XXXXXX"}, + + {0, 0xFD, 0, 2, "Fake Widescreen DIP"}, + {0x1B, 0x01, 0x80, 0x80, "Widescreen"}, + {0x1B, 0x01, 0x80, 0x00, "Normal"}, + +// {0, 0xFE, 0, 2, "NO CD"}, +// {0x1B, 0x01, 0x10, 0x00, "No"}, +// {0x1B, 0x01, 0x10, 0x10, "Yes"}, +}; + +static struct BurnDIPInfo japanRegionDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x01, NULL}, +}; + +static struct BurnDIPInfo asiaRegionDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x02, NULL}, +}; + +static struct BurnDIPInfo euroRegionDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x03, NULL}, +}; + +static struct BurnDIPInfo usaRegionDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x04, NULL}, +}; + +static struct BurnDIPInfo hispanicRegionDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x05, NULL}, +}; + +static struct BurnDIPInfo euroRedeartnDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x53, NULL}, +}; + +static struct BurnDIPInfo japanwarzardDIPList[] = { + + // Defaults + {0x1B, 0xFF, 0xFF, 0x51, NULL}, +}; + +STDDIPINFOEXT(japan, region, japanRegion) +STDDIPINFOEXT(asia, region, asiaRegion) +//STDDIPINFOEXT(euro, region, euroRegion) +STDDIPINFOEXT(usa, region, usaRegion) +STDDIPINFOEXT(jojoba, jojobaRegion, japanRegion) +STDDIPINFOEXT(jojobane, jojobaRegion, euroRegion) +STDDIPINFOEXT(redearth, redeartnRegion, euroRedeartn) +STDDIPINFOEXT(redeartn, redeartnRegion, euroRedeartn) +STDDIPINFOEXT(warzard, redeartnRegion, japanwarzard) +STDDIPINFOEXT(sfiiihispanic, sfiii, hispanicRegion) +STDDIPINFOEXT(sfiiijapan, sfiii, japanRegion) +STDDIPINFOEXT(sfiiiasia, sfiii, asiaRegion) +STDDIPINFOEXT(sfiiiusa, sfiii, usaRegion) + +// ----------------------------------------------- +// Street Fighter III: New Generation (USA 970204) +// ----------------------------------------------- +static struct BurnRomInfo sfiiiRomDesc[] = { + + { "sfiii_usa.29f400.u2", + 0x080000, 0xfb172a8e, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xe896dc27, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x98c2d07c, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7115a396, BRF_GRA }, + { "40", 0x800000, 0x839f0972, BRF_GRA }, + { "41", 0x800000, 0x8a8b252c, BRF_GRA }, + { "50", 0x400000, 0x58933dc2, BRF_GRA }, +#endif + +// { "sf3000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiii) +STD_ROM_FN(sfiii) + +// ------------------------------------------------- +// Street Fighter III: New Generation (Japan 970204) +// ------------------------------------------------- +static struct BurnRomInfo sfiiijRomDesc[] = { + + { "sfiii_japan.29f400.u2", + 0x080000, 0x74205250, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xe896dc27, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x98c2d07c, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7115a396, BRF_GRA }, + { "40", 0x800000, 0x839f0972, BRF_GRA }, + { "41", 0x800000, 0x8a8b252c, BRF_GRA }, + { "50", 0x400000, 0x58933dc2, BRF_GRA }, +#endif + +// { "sf3000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiiij) +STD_ROM_FN(sfiiij) + +// ---------------------------------------------------- +// Street Fighter III: New Generation (Hispanic 970204) +// ---------------------------------------------------- +static struct BurnRomInfo sfiiihRomDesc[] = { + + { "sfiii_hispanic.29f400.u2", + 0x080000, 0xd2b3cd48, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xe896dc27, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x98c2d07c, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7115a396, BRF_GRA }, + { "40", 0x800000, 0x839f0972, BRF_GRA }, + { "41", 0x800000, 0x8a8b252c, BRF_GRA }, + { "50", 0x400000, 0x58933dc2, BRF_GRA }, +#endif + +// { "sf3000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiiih) +STD_ROM_FN(sfiiih) + +// -------------------------------------------------------- +// Street Fighter III: New Generation (Asia 970204, NO CD) +// -------------------------------------------------------- +static struct BurnRomInfo sfiiinRomDesc[] = { + + { "sfiii_asia_nocd.29f400.u2", + 0x080000, 0x73e32463, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0xe896dc27, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x98c2d07c, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7115a396, BRF_GRA }, + { "40", 0x800000, 0x839f0972, BRF_GRA }, + { "41", 0x800000, 0x8a8b252c, BRF_GRA }, + { "50", 0x400000, 0x58933dc2, BRF_GRA }, +}; + +STD_ROM_PICK(sfiiin) +STD_ROM_FN(sfiiin) + +// -------------------------------------------------------- +// Street Fighter III 2nd Impact: Giant Attack (USA 970930) +// -------------------------------------------------------- +static struct BurnRomInfo sfiii2RomDesc[] = { + + { "sfiii2_usa.29f400.u2", + 0x080000, 0x75dd72e0, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x682b014a, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x38090460, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x77c197c0, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7470a6f2, BRF_GRA }, + { "40", 0x800000, 0x01a85ced, BRF_GRA }, + { "41", 0x800000, 0xfb346d74, BRF_GRA }, + { "50", 0x800000, 0x32f79449, BRF_GRA }, + { "51", 0x800000, 0x1102b8eb, BRF_GRA }, +#endif + +// { "3ga000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiii2) +STD_ROM_FN(sfiii2) + +// ---------------------------------------------------------- +// Street Fighter III 2nd Impact: Giant Attack (Japan 970930) +// ---------------------------------------------------------- +static struct BurnRomInfo sfiii2jRomDesc[] = { + + { "sfiii2_japan.29f400.u2", + 0x080000, 0xfaea0a3e, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x682b014a, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x38090460, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x77c197c0, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7470a6f2, BRF_GRA }, + { "40", 0x800000, 0x01a85ced, BRF_GRA }, + { "41", 0x800000, 0xfb346d74, BRF_GRA }, + { "50", 0x800000, 0x32f79449, BRF_GRA }, + { "51", 0x800000, 0x1102b8eb, BRF_GRA }, +#endif + +// { "3ga000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiii2j) +STD_ROM_FN(sfiii2j) + +// ---------------------------------------------------------------- +// Street Fighter III 2nd Impact: Giant Attack (Asia 970930, NO CD) +// ---------------------------------------------------------------- +static struct BurnRomInfo sfiii2nRomDesc[] = { + + { "sfiii2_asia_nocd.29f400.u2", + 0x080000, 0xfd297c0d, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0x682b014a, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x38090460, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x77c197c0, BRF_GRA }, // cd content region + { "31", 0x800000, 0x7470a6f2, BRF_GRA }, + { "40", 0x800000, 0x01a85ced, BRF_GRA }, + { "41", 0x800000, 0xfb346d74, BRF_GRA }, + { "50", 0x800000, 0x32f79449, BRF_GRA }, + { "51", 0x800000, 0x1102b8eb, BRF_GRA }, +}; + +STD_ROM_PICK(sfiii2n) +STD_ROM_FN(sfiii2n) + +// ---------------------------------------------------------------- +// Street Fighter III 3rd Strike: Fight for the Future (USA 990608) +// ---------------------------------------------------------------- +static struct BurnRomInfo sfiii3RomDesc[] = { + + { "sfiii3_usa.29f400.u2", + 0x080000, 0xecc545c1, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xba7f76b2, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x5ca8faba, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xb37cf960, BRF_GRA }, // cd content region + { "31", 0x800000, 0x450ec982, BRF_GRA }, + { "40", 0x800000, 0x632c965f, BRF_GRA }, + { "41", 0x800000, 0x7a4c5f33, BRF_GRA }, + { "50", 0x800000, 0x8562358e, BRF_GRA }, + { "51", 0x800000, 0x7baf234b, BRF_GRA }, + { "60", 0x800000, 0xbc9487b7, BRF_GRA }, + { "61", 0x800000, 0xb813a1b1, BRF_GRA }, +#endif + +// { "33s000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiii3) +STD_ROM_FN(sfiii3) + +// ---------------------------------------------------------------- +// Street Fighter III 3rd Strike: Fight for the Future (USA 990512) +// ---------------------------------------------------------------- +static struct BurnRomInfo sfiii3aRomDesc[] = { + + { "sfiii3_usa.29f400.u2", + 0x080000, 0xecc545c1, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x77233d39, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x5ca8faba, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xb37cf960, BRF_GRA }, // cd content region + { "31", 0x800000, 0x450ec982, BRF_GRA }, + { "40", 0x800000, 0x632c965f, BRF_GRA }, + { "41", 0x800000, 0x7a4c5f33, BRF_GRA }, + { "50", 0x800000, 0x8562358e, BRF_GRA }, + { "51", 0x800000, 0x7baf234b, BRF_GRA }, + { "60", 0x800000, 0xbc9487b7, BRF_GRA }, + { "61", 0x800000, 0xb813a1b1, BRF_GRA }, +#endif + +// { "cap-33s-2", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(sfiii3a) +STD_ROM_FN(sfiii3a) + +// ------------------------------------------------------------------------- +// Street Fighter III 3rd Strike: Fight for the Future (Japan 990608, NO CD) +// ------------------------------------------------------------------------- +static struct BurnRomInfo sfiii3anRomDesc[] = { + + { "sfiii3_japan_nocd.29f400.u2", + 0x080000, 0x1edc6366, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0x77233d39, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x5ca8faba, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xb37cf960, BRF_GRA }, // cd content region + { "31", 0x800000, 0x450ec982, BRF_GRA }, + { "40", 0x800000, 0x632c965f, BRF_GRA }, + { "41", 0x800000, 0x7a4c5f33, BRF_GRA }, + { "50", 0x800000, 0x8562358e, BRF_GRA }, + { "51", 0x800000, 0x7baf234b, BRF_GRA }, + { "60", 0x800000, 0xbc9487b7, BRF_GRA }, + { "61", 0x800000, 0xb813a1b1, BRF_GRA }, +}; + +STD_ROM_PICK(sfiii3an) +STD_ROM_FN(sfiii3an) + +// ------------------------------------------------------------------------- +// Street Fighter III 3rd Strike: Fight for the Future (Japan 990512, NO CD) +// ------------------------------------------------------------------------- +static struct BurnRomInfo sfiii3nRomDesc[] = { + + { "sfiii3_japan_nocd.29f400.u2", + 0x080000, 0x1edc6366, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0xba7f76b2, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x5ca8faba, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xb37cf960, BRF_GRA }, // cd content region + { "31", 0x800000, 0x450ec982, BRF_GRA }, + { "40", 0x800000, 0x632c965f, BRF_GRA }, + { "41", 0x800000, 0x7a4c5f33, BRF_GRA }, + { "50", 0x800000, 0x8562358e, BRF_GRA }, + { "51", 0x800000, 0x7baf234b, BRF_GRA }, + { "60", 0x800000, 0xbc9487b7, BRF_GRA }, + { "61", 0x800000, 0xb813a1b1, BRF_GRA }, +}; + +STD_ROM_PICK(sfiii3n) +STD_ROM_FN(sfiii3n) + +// ------------------------------------------------------- +// JoJo no Kimyouna Bouken / JoJo's Venture (USA 990108) +// ------------------------------------------------------- +static struct BurnRomInfo jojoRomDesc[] = { + + { "jojo_usa.29f400.u2", + 0x080000, 0x8d40f7be, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xbc612872, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0e1daddf, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +#endif + +// { "jjk000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(jojo) +STD_ROM_FN(jojo) + +// ------------------------------------------------------- +// JoJo no Kimyouna Bouken / JoJo's Venture (USA 981202) +// ------------------------------------------------------- +static struct BurnRomInfo jojoaRomDesc[] = { + + { "jojo_usa.29f400.u2", + 0x080000, 0x8d40f7be, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xe40dc123, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0571e37c, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +#endif + +// { "cap-jjk-160", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(jojoa) +STD_ROM_FN(jojoa) + +// ------------------------------------------------------- +// JoJo no Kimyouna Bouken / JoJo's Venture (Japan 990108) +// ------------------------------------------------------- +static struct BurnRomInfo jojojRomDesc[] = { + + { "jojo_japan.29f400.u2", + 0x080000, 0x02778f60, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xbc612872, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0e1daddf, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +#endif + +// { "jjk000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(jojoj) +STD_ROM_FN(jojoj) + +// ------------------------------------------------------- +// JoJo no Kimyouna Bouken / JoJo's Venture (Japan 981202) +// ------------------------------------------------------- +static struct BurnRomInfo jojoajRomDesc[] = { + + { "jojo_japan.29f400.u2", + 0x080000, 0x02778f60, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xe40dc123, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0571e37c, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +#endif + +// { "cap-jjk-160", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(jojoaj) +STD_ROM_FN(jojoaj) + +// ------------------------------------------------------------- +// JoJo's Venture / JoJo no Kimyouna Bouken (Asia 990108, NO CD) +// ------------------------------------------------------------- +static struct BurnRomInfo jojonRomDesc[] = { + + { "jojo_asia_nocd.29f400.u2", + 0x080000, 0x05b4f953, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0xbc612872, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0e1daddf, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +}; + +STD_ROM_PICK(jojon) +STD_ROM_FN(jojon) + +// ------------------------------------------------------------- +// JoJo's Venture / JoJo no Kimyouna Bouken (Asia 981202, NO CD) +// ------------------------------------------------------------- +static struct BurnRomInfo jojoanRomDesc[] = { + + { "jojo_asia_nocd.29f400.u2", + 0x080000, 0x05b4f953, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0xe40dc123, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x0571e37c, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0x1d99181b, BRF_GRA }, // cd content region + { "31", 0x800000, 0x6889fbda, BRF_GRA }, + { "40", 0x800000, 0x8069f9de, BRF_GRA }, + { "41", 0x800000, 0x9c426823, BRF_GRA }, + { "50", 0x400000, 0x1c749cc7, BRF_GRA }, +}; + +STD_ROM_PICK(jojoan) +STD_ROM_FN(jojoan) + +// --------------------------------------------------------------------------------- +// JoJo no Kimyouna Bouken: Miraie no Isan / JoJo's Bizarre Adventure (Japan 990913) +// --------------------------------------------------------------------------------- +static struct BurnRomInfo jojobaRomDesc[] = { + + { "jojoba_japan.29f400.u2", + 0x080000, 0x3085478c, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x6e2490f6, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x1293892b, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xd25c5005, BRF_GRA }, // cd content region + { "31", 0x800000, 0x51bb3dba, BRF_GRA }, + { "40", 0x800000, 0x94dc26d4, BRF_GRA }, + { "41", 0x800000, 0x1c53ee62, BRF_GRA }, + { "50", 0x800000, 0x36e416ed, BRF_GRA }, + { "51", 0x800000, 0xeedf19ca, BRF_GRA }, +#endif + +// { "jjm000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(jojoba) +STD_ROM_FN(jojoba) + +// ---------------------------------------------------------------------------------------- +// JoJo no Kimyouna Bouken: Miraie no Isan / JoJo's Bizarre Adventure (Japan 990913, NO CD) +// ---------------------------------------------------------------------------------------- +static struct BurnRomInfo jojobanRomDesc[] = { + + { "jojoba_japan_nocd.29f400.u2", + 0x080000, 0x4dab19f5, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0x6e2490f6, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x1293892b, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xd25c5005, BRF_GRA }, // cd content region + { "31", 0x800000, 0x51bb3dba, BRF_GRA }, + { "40", 0x800000, 0x94dc26d4, BRF_GRA }, + { "41", 0x800000, 0x1c53ee62, BRF_GRA }, + { "50", 0x800000, 0x36e416ed, BRF_GRA }, + { "51", 0x800000, 0xeedf19ca, BRF_GRA }, +}; + +STD_ROM_PICK(jojoban) +STD_ROM_FN(jojoban) + +// --------------------------------------------------------------------------------------- +// JoJo's Bizarre Adventure / JoJo no Kimyouna Bouken: Miraie no Isan (Euro 990913, NO CD) +// --------------------------------------------------------------------------------------- +static struct BurnRomInfo jojobaneRomDesc[] = { + + { "jojoba_euro_nocd.29f400.u2", + 0x080000, 0x1ee2d679, BRF_ESS | BRF_BIOS }, // SH-2 Bios + + { "10", 0x800000, 0x6e2490f6, BRF_ESS | BRF_PRG }, // SH-2 Code + { "20", 0x800000, 0x1293892b, BRF_ESS | BRF_PRG }, + + { "30", 0x800000, 0xd25c5005, BRF_GRA }, // cd content region + { "31", 0x800000, 0x51bb3dba, BRF_GRA }, + { "40", 0x800000, 0x94dc26d4, BRF_GRA }, + { "41", 0x800000, 0x1c53ee62, BRF_GRA }, + { "50", 0x800000, 0x36e416ed, BRF_GRA }, + { "51", 0x800000, 0xeedf19ca, BRF_GRA }, +}; + +STD_ROM_PICK(jojobane) +STD_ROM_FN(jojobane) + +// ---------------------------------- +// Red Earth / War-Zard (Euro 961121) +// ---------------------------------- +static struct BurnRomInfo redearthRomDesc[] = { + + { "warzard_euro.29f400.u2", + 0x080000, 0x02e0f336, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x68188016, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +#endif + +// { "wzd000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(redearth) +STD_ROM_FN(redearth) + +// ----------------------------------- +// War-Zard / Red Earth (Japan 961121) +// ----------------------------------- +static struct BurnRomInfo warzardRomDesc[] = { + + { "warzard_japan.29f400.u2", + 0x080000, 0xf8e2f0c6, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0x68188016, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +#endif + +// { "wzd000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(warzard) +STD_ROM_FN(warzard) + +// ----------------------------------------- +// Red Earth / War-Zard (Euro 961121, NO CD) +// ----------------------------------------- +static struct BurnRomInfo redeartnRomDesc[] = { + +#if !defined (ROM_VERIFY) + { "warzard_euro.29f400.u2",0x080000, 0x02e0f336, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#else + { "redearth_nocd.bios", 0x080000, 0x00000000, BRF_ESS | BRF_BIOS | BRF_NODUMP }, // SH-2 Bios +#endif + + { "10", 0x800000, 0x68188016, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +}; + +STD_ROM_PICK(redeartn) +STD_ROM_FN(redeartn) + +// ---------------------------------- +// Red Earth / War-Zard (Euro 961023) +// ---------------------------------- +static struct BurnRomInfo redearthaRomDesc[] = { + + { "warzard_euro.29f400.u2", + 0x080000, 0x02e0f336, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xb3db2393, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +#endif + +// { "wzd000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(redeartha) +STD_ROM_FN(redeartha) + +// ----------------------------------- +// War-Zard / Red Earth (Japan 961023) +// ----------------------------------- +static struct BurnRomInfo warzardaRomDesc[] = { + + { "warzard_japan.29f400.u2", + 0x080000, 0xf8e2f0c6, BRF_ESS | BRF_BIOS }, // SH-2 Bios + +#if !defined (ROM_VERIFY) + { "10", 0x800000, 0xb3db2393, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +#endif + +// { "wzd000", 0x000000, 0x00000000, BRF_ESS | BRF_CHD }, // CD-ROM +}; + +STD_ROM_PICK(warzarda) +STD_ROM_FN(warzarda) + +// ----------------------------------------- +// Red Earth / War-Zard (Euro 961023, NO CD) +// ----------------------------------------- +static struct BurnRomInfo redeartnaRomDesc[] = { + +#if !defined (ROM_VERIFY) + { "warzard_euro.29f400.u2",0x080000, 0x02e0f336, BRF_ESS | BRF_BIOS }, // SH-2 Bios +#else + { "redearth_nocd.bios", 0x080000, 0x00000000, BRF_ESS | BRF_BIOS | BRF_NODUMP }, // SH-2 Bios +#endif + + { "10", 0x800000, 0xb3db2393, BRF_ESS | BRF_PRG }, // SH-2 Code + + { "30", 0x800000, 0x074cab4d, BRF_GRA }, // cd content region + { "31", 0x800000, 0x14e2cad4, BRF_GRA }, + { "40", 0x800000, 0x72d98890, BRF_GRA }, + { "41", 0x800000, 0x88ccb33c, BRF_GRA }, + { "50", 0x400000, 0x2f5b44bd, BRF_GRA }, +}; + +STD_ROM_PICK(redeartna) +STD_ROM_FN(redeartna) + +// ------------------------------------------------------------------------------------ + +static INT32 sfiiiInit() +{ + cps3_key1 = 0xb5fe053e; + cps3_key2 = 0xfc03925a; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x000166b4; + cps3_game_test_hack = 0x063cdff4; + + cps3_speedup_ram_address = 0x0200cc6c; + cps3_speedup_code_address = 0x06000884; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 sfiii2Init() +{ + cps3_key1 = 0x00000000; + cps3_key2 = 0x00000000; + cps3_isSpecial = 1; + + cps3_bios_test_hack = 0x00000000; + cps3_game_test_hack = 0x00000000; + + cps3_speedup_ram_address = 0x0200dfe4; + cps3_speedup_code_address = 0x06000884; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 sfiii3Init() +{ + cps3_key1 = 0xa55432b4; + cps3_key2 = 0x0c129981; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x00011c44; + cps3_game_test_hack = 0x0613ab48; + + cps3_speedup_ram_address = 0x0200d794; + cps3_speedup_code_address = 0x06000884; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 jojoInit() +{ + cps3_key1 = 0x02203ee3; + cps3_key2 = 0x01301972; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x00011c2c; + cps3_game_test_hack = 0x06172568; + + cps3_speedup_ram_address = 0x020223d8; + cps3_speedup_code_address = 0x0600065c; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 jojobaInit() +{ + cps3_key1 = 0x23323ee3; + cps3_key2 = 0x03021972; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x00011c90; + cps3_game_test_hack = 0x061c45bc; + + cps3_speedup_ram_address = 0x020267dc; + cps3_speedup_code_address = 0x0600065c; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 jojoaltInit() +{ + cps3_key1 = 0x02203ee3; + cps3_key2 = 0x01301972; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x00011c2c; + cps3_game_test_hack = 0x06172568; + + cps3_speedup_ram_address = 0x020223c0; + cps3_speedup_code_address = 0x0600065c; + + cps3_region_address = 0x0001fec8; + cps3_ncd_address = 0x0001fecf; + + return cps3Init(); +} + +static INT32 redearthInit() +{ + cps3_key1 = 0x9e300ab1; + cps3_key2 = 0xa175b82c; + cps3_isSpecial = 0; + + cps3_bios_test_hack = 0x00016530; + cps3_game_test_hack = 0x060105f0; + + cps3_speedup_ram_address = 0x0202136c; + cps3_speedup_code_address = 0x0600194e; + + cps3_region_address = 0x0001fed8; + cps3_ncd_address = 0x00000000; + + return cps3Init(); +} + + +struct BurnDriver BurnDrvSfiii = { + "sfiii", NULL, NULL, NULL, "1997", + "Street Fighter III: New Generation (USA 970204)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiiiRomInfo, sfiiiRomName, NULL, NULL, cps3InputInfo, sfiiiusaDIPInfo, + sfiiiInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiiij = { + "sfiiij", "sfiii", NULL, NULL, "1997", + "Street Fighter III: New Generation (Japan 970204)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiiijRomInfo, sfiiijRomName, NULL, NULL, cps3InputInfo, sfiiijapanDIPInfo, + sfiiiInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiiih = { + "sfiiih", "sfiii", NULL, NULL, "1997", + "Street Fighter III: New Generation (Hispanic 970204)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiiihRomInfo, sfiiihRomName, NULL, NULL, cps3InputInfo, sfiiihispanicDIPInfo, + sfiiiInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiiin = { + "sfiiin", "sfiii", NULL, NULL, "1997", + "Street Fighter III: New Generation (Asia 970204, NO CD)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, FBF_SF, + NULL, sfiiinRomInfo, sfiiinRomName, NULL, NULL, cps3InputInfo, sfiiiasiaDIPInfo, + sfiiiInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii2 = { + "sfiii2", NULL, NULL, NULL, "1997", + "Street Fighter III 2nd Impact: Giant Attack (USA 970930)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiii2RomInfo, sfiii2RomName, NULL, NULL, cps3InputInfo, usaDIPInfo, + sfiii2Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii2j = { + "sfiii2j", "sfiii2", NULL, NULL, "1997", + "Street Fighter III 2nd Impact: Giant Attack (Japan 970930)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiii2jRomInfo, sfiii2jRomName, NULL, NULL, cps3InputInfo, japanDIPInfo, + sfiii2Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii2n = { + "sfiii2n", "sfiii2", NULL, NULL, "1997", + "Street Fighter III 2nd Impact: Giant Attack (Asia 970930, NO CD)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, FBF_SF, + NULL, sfiii2nRomInfo, sfiii2nRomName, NULL, NULL, cps3InputInfo, asiaDIPInfo, + sfiii2Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii3 = { + "sfiii3", NULL, NULL, NULL, "1999", + "Street Fighter III 3rd Strike: Fight for the Future (USA 990608)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiii3RomInfo, sfiii3RomName, NULL, NULL, cps3InputInfo, usaDIPInfo, + sfiii3Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii3a = { + "sfiii3a", "sfiii3", NULL, NULL, "1999", + "Street Fighter III 3rd Strike: Fight for the Future (USA 990512)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF, + NULL, sfiii3aRomInfo, sfiii3aRomName, NULL, NULL, cps3InputInfo, usaDIPInfo, + sfiii3Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii3n = { + "sfiii3n", "sfiii3", NULL, NULL, "1999", + "Street Fighter III 3rd Strike: Fight for the Future (Japan 990608, NO CD)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, FBF_SF, + NULL, sfiii3nRomInfo, sfiii3nRomName, NULL, NULL, cps3InputInfo, japanDIPInfo, + sfiii3Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSfiii3an = { + "sfiii3an", "sfiii3", NULL, NULL, "1999", + "Street Fighter III 3rd Strike: Fight for the Future (Japan 990512, NO CD)\0", NULL, "Capcom", "CPS-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, FBF_SF, + NULL, sfiii3anRomInfo, sfiii3anRomName, NULL, NULL, cps3InputInfo, japanDIPInfo, + sfiii3Init, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojo = { + "jojo", NULL, NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (USA 990108)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A\0JoJo's Venture (USA 990108)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, jojoRomInfo, jojoRomName, NULL, NULL, cps3InputInfo, usaDIPInfo, + jojoInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoa = { + "jojoa", "jojo", NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (USA 981202)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A\0JoJo's Venture (USA 981202)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, jojoaRomInfo, jojoaRomName, NULL, NULL, cps3InputInfo, usaDIPInfo, + jojoaltInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoj = { + "jojoj", "jojo", NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (Japan 990108)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A\0JoJo's Venture (Japan 990108)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, jojojRomInfo, jojojRomName, NULL, NULL, cps3InputInfo, japanDIPInfo, + jojoInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoaj = { + "jojoaj", "jojo", NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (Japan 981202)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A\0JoJo's Venture (Japan 981202)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, jojoajRomInfo, jojoajRomName, NULL, NULL, cps3InputInfo, japanDIPInfo, + jojoaltInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojon = { + "jojon", "jojo", NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (Asia 990108, NO CD)\0", NULL, "Capcom", "CPS-3", + L"JoJo's Venture\0\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A (Asia 990108, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, jojonRomInfo, jojonRomName, NULL, NULL, cps3InputInfo, asiaDIPInfo, + jojoInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoan = { + "jojoan", "jojo", NULL, NULL, "1998", + "JoJo's Venture / JoJo no Kimyouna Bouken (Asia 981202, NO CD)\0", NULL, "Capcom", "CPS-3", + L"JoJo's Venture\0\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A (Asia 981202, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, jojoanRomInfo, jojoanRomName, NULL, NULL, cps3InputInfo, asiaDIPInfo, + jojoaltInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoba = { + "jojoba", NULL, NULL, NULL, "1999", + "JoJo's Bizarre Adventure: Heritage for the Future / JoJo no Kimyouna Bouken: Miraie no Isan (Japan 990913)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A: \u672A\u6765\u3078\u306E\u907A\u7523\0JoJo's Bizarre Adventure (Japan 990913)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, jojobaRomInfo, jojobaRomName, NULL, NULL, cps3InputInfo, jojobaDIPInfo, + jojobaInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojoban = { + "jojoban", "jojoba", NULL, NULL, "1999", + "JoJo's Bizarre Adventure: Heritage for the Future / JoJo no Kimyouna Bouken: Miraie no Isan (Japan 990913, NO CD)\0", NULL, "Capcom", "CPS-3", + L"\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A: \u672A\u6765\u3078\u306E\u907A\u7523\0JoJo's Bizarre Adventure (Japan 990913, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, jojobanRomInfo, jojobanRomName, NULL, NULL, cps3InputInfo, jojobaDIPInfo, + jojobaInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJojobane = { + "jojobane", "jojoba", NULL, NULL, "1999", + "JoJo's Bizarre Adventure: Heritage for the Future / JoJo no Kimyouna Bouken: Miraie no Isan (Euro 990913, NO CD)\0", NULL, "Capcom", "CPS-3", + L"JoJo's Bizarre Adventure\0\u30B8\u30E7\u30B8\u30E7\u306E \u5947\u5999\u306A\u5192\u967A: \u672A\u6765\u3078\u306E\u907A\u7523 (Euro 990913, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, jojobaneRomInfo, jojobaneRomName, NULL, NULL, cps3InputInfo, jojobaneDIPInfo, + jojobaInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRedearth = { + "redearth", NULL, NULL, NULL, "1996", + "Red Earth / War-Zard (Euro 961121)\0", NULL, "Capcom", "CPS-3", + L"Red Earth\0War-Zard (Euro 961121)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, redearthRomInfo, redearthRomName, NULL, NULL, cps3InputInfo, redearthDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWarzard = { + "warzard", "redearth", NULL, NULL, "1996", + "War-Zard / Red Earth (Japan 961121)\0", NULL, "Capcom", "CPS-3", + L"War-Zard\0Red Earth (Japan 961121)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, warzardRomInfo, warzardRomName, NULL, NULL, cps3InputInfo, warzardDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRedeartn = { + "redeartn", "redearth", NULL, NULL, "1996", + "Red Earth / War-Zard (Euro 961121, NO CD)\0", NULL, "Capcom", "CPS-3", + L"Red Earth\0War-Zard (Euro 961121, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, redeartnRomInfo, redeartnRomName, NULL, NULL, cps3InputInfo, redeartnDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRedeartha = { + "redeartha", "redearth", NULL, NULL, "1996", + "Red Earth / War-Zard (Euro 961023)\0", NULL, "Capcom", "CPS-3", + L"Red Earth\0War-Zard (Euro 961023)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, redearthaRomInfo, redearthaRomName, NULL, NULL, cps3InputInfo, redearthDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWarzarda = { + "warzarda", "redearth", NULL, NULL, "1996", + "War-Zard / Red Earth (Japan 961023)\0", NULL, "Capcom", "CPS-3", + L"War-Zard\0Red Earth (Japan 961023)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, 0, + NULL, warzardaRomInfo, warzardaRomName, NULL, NULL, cps3InputInfo, warzardDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRedeartna = { + "redeartna", "redearth", NULL, NULL, "1996", + "Red Earth / War-Zard (Euro 961023, NO CD)\0", NULL, "Capcom", "CPS-3", + L"Red Earth\0War-Zard (Euro 961023, NO CD)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAPCOM_CPS3 | HARDWARE_CAPCOM_CPS3_NO_CD, GBF_VSFIGHT, 0, + NULL, redeartnaRomInfo, redeartnaRomName, NULL, NULL, cps3InputInfo, redeartnDIPInfo, + redearthInit, cps3Exit, cps3Frame, NULL, cps3Scan, &cps3_palette_change, 0x40000, + 384, 224, 4, 3 +}; diff --git a/src/burn/drivers/d_parent.cpp b/src/burn/drivers/d_parent.cpp new file mode 100644 index 00000000..ae8a0841 --- /dev/null +++ b/src/burn/drivers/d_parent.cpp @@ -0,0 +1,343 @@ +// A module for keeping parents who have no driver in FBA + +#include "burnint.h" + +static UINT8 ParentReset = 0; + +static struct BurnInputInfo ParentInputList[] = { + {"Reset" , BIT_DIGITAL , &ParentReset , "reset" }, +}; + +STDINPUTINFO(Parent) + +static INT32 ParentInit() +{ + return 1; +} + +static INT32 ParentExit() +{ + return 0; +} + +static struct BurnRomInfo BagmanRomDesc[] = { + { "e9_b05.bin", 0x01000, 0xe0156191, BRF_ESS | BRF_PRG }, + { "f9_b06.bin", 0x01000, 0x7b758982, BRF_ESS | BRF_PRG }, + { "f9_b07.bin", 0x01000, 0x302a077b, BRF_ESS | BRF_PRG }, + { "k9_b08.bin", 0x01000, 0xf04293cb, BRF_ESS | BRF_PRG }, + { "m9_b09s.bin", 0x01000, 0x68e83e4f, BRF_ESS | BRF_PRG }, + { "n9_b10.bin", 0x01000, 0x1d6579f7, BRF_ESS | BRF_PRG }, + + { "e1_b02.bin", 0x01000, 0x4a0a6b55, BRF_ESS | BRF_PRG }, + { "j1_b04.bin", 0x01000, 0xc680ef04, BRF_ESS | BRF_PRG }, + + { "c1_b01.bin", 0x01000, 0x705193b2, BRF_ESS | BRF_PRG }, + { "f1_b03s.bin", 0x01000, 0xdba1eda7, BRF_ESS | BRF_PRG }, + + { "p3.bin", 0x00020, 0x2a855523, BRF_GRA }, + { "r3.bin", 0x00020, 0xae6f1019, BRF_GRA }, + { "r6.bin", 0x00020, 0xc58a4f6a, BRF_GRA }, + + { "r9_b11.bin", 0x01000, 0x2e0057ff, BRF_SND }, + { "t9_b12.bin", 0x01000, 0xb2120edd, BRF_SND }, +}; + +STD_ROM_PICK(Bagman) +STD_ROM_FN(Bagman) + +struct BurnDriver BurnDrvBagman = { + "bagman", NULL, NULL, NULL, "1982", + "Bagman\0", "Parent set for working drivers", "Valadon Automation", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, BagmanRomInfo, BagmanRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo CkongRomDesc[] = { + { "falcon7", 0x01000, 0x2171cac3, BRF_ESS | BRF_PRG }, + { "falcon8", 0x01000, 0x88b83ff7, BRF_ESS | BRF_PRG }, + { "falcon9", 0x01000, 0xcff2af47, BRF_ESS | BRF_PRG }, + { "falcon10", 0x01000, 0x6b2ecf23, BRF_ESS | BRF_PRG }, + { "falcon11", 0x01000, 0x327dcadf, BRF_ESS | BRF_PRG }, + + { "falcon6", 0x01000, 0xa8916dc8, BRF_GRA }, + { "falcon5", 0x01000, 0xcd3b5dde, BRF_GRA }, + { "falcon4", 0x01000, 0xb62a0367, BRF_GRA }, + { "falcon3", 0x01000, 0x61122c5e, BRF_GRA }, + + { "falcon2", 0x00800, 0xf67c80f1, BRF_GRA }, + { "falcon1", 0x00800, 0x80eb517d, BRF_GRA }, + + { "ck6v.bin", 0x00020, 0x751c3325, BRF_GRA }, + { "ck6u.bin", 0x00020, 0xab1940fa, BRF_GRA }, + { "ck6t.bin", 0x00020, 0xb4e827a5, BRF_GRA }, + + { "falcon13", 0x01000, 0x5f0bcdfb, BRF_SND }, + { "falcon12", 0x01000, 0x9003ffbd, BRF_SND }, +}; + +STD_ROM_PICK(Ckong) +STD_ROM_FN(Ckong) + +struct BurnDriver BurnDrvCkong = { + "ckong", NULL, NULL, NULL, "1981", + "Crazy Kong Part II (set 1)\0", "Parent set for working drivers", "Falcon", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, CkongRomInfo, CkongRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo DkongjrRomDesc[] = { + { "dkj.5b", 0x02000, 0xdea28158, BRF_ESS | BRF_PRG }, + { "dkj.5c", 0x02000, 0x6fb5faf6, BRF_ESS | BRF_PRG }, + { "dkj.5e", 0x02000, 0xd042b6a8, BRF_ESS | BRF_PRG }, + + { "c_3h.bin", 0x01000, 0x715da5f8, BRF_ESS | BRF_PRG }, + + { "dkj.3n", 0x01000, 0x8d51aca9, BRF_ESS | BRF_PRG }, + { "dkj.3p", 0x01000, 0x4ef64ba5, BRF_ESS | BRF_PRG }, + + { "v_7c.bin", 0x00800, 0xdc7f4164, BRF_ESS | BRF_PRG }, + { "v_7d.bin", 0x00800, 0x0ce7dcf6, BRF_ESS | BRF_PRG }, + { "v_7e.bin", 0x00800, 0x24d1ff17, BRF_ESS | BRF_PRG }, + { "v_7f.bin", 0x00800, 0x0f8c083f, BRF_ESS | BRF_PRG }, + + { "c-2e.bpr", 0x00100, 0x463dc7ad, BRF_GRA }, + { "c-2f.bpr", 0x00100, 0x47ba0042, BRF_GRA }, + { "v-2n.bpr", 0x00100, 0xdbf185bf, BRF_GRA }, +}; + +STD_ROM_PICK(Dkongjr) +STD_ROM_FN(Dkongjr) + +struct BurnDriver BurnDrvDkongjr = { + "dkongjr", NULL, NULL, NULL, "1982", + "Donkey Kong Junior (US)\0", "Parent set for working drivers", "Nintendo of America", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DkongjrRomInfo, DkongjrRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo DockmanRomDesc[] = { + { "pe1.19", 0x01000, 0xeef2ec54, BRF_ESS | BRF_PRG }, + { "pe2.18", 0x01000, 0xbc48d16b, BRF_ESS | BRF_PRG }, + { "pe3.17", 0x01000, 0x1c923057, BRF_ESS | BRF_PRG }, + { "pe4.16", 0x01000, 0x23af1cba, BRF_ESS | BRF_PRG }, + { "pe5.15", 0x01000, 0x39dbe429, BRF_ESS | BRF_PRG }, + + { "pe7.22", 0x00800, 0xd2094e4a, BRF_ESS | BRF_PRG }, + { "pe6.23", 0x00800, 0x1cf447f4, BRF_ESS | BRF_PRG }, + + { "pe8.9", 0x01000, 0x4d8c2974, BRF_GRA }, + { "pe9.8", 0x01000, 0x4e4ea162, BRF_GRA }, + + { "mb7051.3", 0x00020, 0x6440dc61, BRF_GRA }, +}; + +STD_ROM_PICK(Dockman) +STD_ROM_FN(Dockman) + +struct BurnDriver BurnDrvDockman = { + "dockman", NULL, NULL, NULL, "1982", + "Dock Man\0", "Parent set for working drivers", "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DockmanRomInfo, DockmanRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo EightballactRomDesc[] = { + { "8b-dk.5e", 0x01000, 0x166c1c9b, BRF_ESS | BRF_PRG }, + { "8b-dk.5c", 0x01000, 0x9ec87baa, BRF_ESS | BRF_PRG }, + { "8b-dk.5b", 0x01000, 0xf836a962, BRF_ESS | BRF_PRG }, + { "8b-dk.5a", 0x01000, 0xd45866d4, BRF_ESS | BRF_PRG }, + + { "8b-dk.3h", 0x00800, 0xa8752c60, BRF_ESS | BRF_PRG }, + + { "8b-dk.3n", 0x00800, 0x44830867, BRF_GRA }, + { "8b-dk.3p", 0x00800, 0x6148c6f2, BRF_GRA }, + + { "8b-dk.7c", 0x00800, 0xe34409f5, BRF_GRA }, + { "8b-dk.7d", 0x00800, 0xb4dc37ca, BRF_GRA }, + { "8b-dk.7e", 0x00800, 0x655af8a8, BRF_GRA }, + { "8b-dk.7f", 0x00800, 0xa29b2763, BRF_GRA }, + + { "8b.2e", 0x00100, 0xc7379a12, BRF_GRA }, + { "8b.2f", 0x00100, 0x116612b4, BRF_GRA }, + { "8b.2n", 0x00100, 0x30586988, BRF_GRA }, + + { "82s147.prm", 0x00200, 0x46e5bc92, BRF_GRA }, + + { "pls153h.bin", 0x000eb, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(Eightballact) +STD_ROM_FN(Eightballact) + +struct BurnDriver BurnDrvEightballact = { + "8ballact", NULL, NULL, NULL, "1984", + "Eight Ball Action (DK conversion)\0", "Parent set for working drivers", "Seatongrove Ltd (Magic Eletronics USA licence)", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, EightballactRomInfo, EightballactRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 256, 224, 4, 3 +}; + +static struct BurnRomInfo HunchbakRomDesc[] = { + { "hb-gp1.bin", 0x01000, 0xaf801d54, BRF_ESS | BRF_PRG }, + { "hb-gp2.bin", 0x01000, 0xb448cc8e, BRF_ESS | BRF_PRG }, + { "hb-gp3.bin", 0x01000, 0x57c6ea7b, BRF_ESS | BRF_PRG }, + { "hb-gp4.bin", 0x01000, 0x7f91287b, BRF_ESS | BRF_PRG }, + { "hb-gp5.bin", 0x01000, 0x1dd5755c, BRF_ESS | BRF_PRG }, + + { "6c.sdp1", 0x01000, 0xf9ba2854, BRF_ESS | BRF_PRG }, + + { "8a.sp1", 0x00800, 0xed1cd201, BRF_SND }, + + { "11a.cp1", 0x00800, 0xf256b047, BRF_GRA }, + { "10a.cp2", 0x00800, 0xb870c64f, BRF_GRA }, + { "9a.cp3", 0x00800, 0x9a7dab88, BRF_GRA }, + + { "5b.bin", 0x00800, 0xf055a624, BRF_SND }, + + { "82s185.10h", 0x00800, 0xc205bca6, BRF_GRA }, + { "82s123.10k", 0x00020, 0xb5221cec, BRF_GRA }, +}; + +STD_ROM_PICK(Hunchbak) +STD_ROM_FN(Hunchbak) + +struct BurnDriver BurnDrvHunchbak = { + "hunchbak", NULL, NULL, NULL, "1983", + "Hunchback (set 1)\0", "Parent set for working drivers", "Century Electronics", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, HunchbakRomInfo, HunchbakRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo HuncholyRomDesc[] = { + { "ho-gp1.bin", 0x01000, 0x4f17cda7, BRF_ESS | BRF_PRG }, + { "ho-gp2.bin", 0x01000, 0x70fa52c7, BRF_ESS | BRF_PRG }, + { "ho-gp3.bin", 0x01000, 0x931934b1, BRF_ESS | BRF_PRG }, + { "ho-gp4.bin", 0x01000, 0xaf5cd501, BRF_ESS | BRF_PRG }, + { "ho-gp5.bin", 0x01000, 0x658e8974, BRF_ESS | BRF_PRG }, + + { "ho-sdp1.bin", 0x01000, 0x3efb3ffd, BRF_ESS | BRF_PRG }, + + { "ho-sp1.bin", 0x01000, 0x3fd39b1e, BRF_SND }, + + { "ho-cp1.bin", 0x00800, 0xc6c73d46, BRF_GRA }, + { "ho-cp2.bin", 0x00800, 0xe596371c, BRF_GRA }, + { "ho-cp3.bin", 0x00800, 0x11fae1cf, BRF_GRA }, + + { "5b.bin", 0x00800, 0xf055a624, BRF_SND }, + + { "82s185.10h", 0x00800, 0xc205bca6, BRF_GRA }, + { "82s123.10k", 0x00020, 0xb5221cec, BRF_GRA }, +}; + +STD_ROM_PICK(Huncholy) +STD_ROM_FN(Huncholy) + +struct BurnDriver BurnDrvHuncholy = { + "huncholy", NULL, NULL, NULL, "1984", + "Hunchback Olympic\0", "Parent set for working drivers", "Seatongrove Ltd", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, HuncholyRomInfo, HuncholyRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 224, 256, 3, 4 +}; + +static struct BurnRomInfo ManiacsqRomDesc[] = { + { "d8-d15.1m", 0x20000, 0x9121d1b6, BRF_ESS | BRF_PRG }, + { "d0-d7.1m", 0x20000, 0xa95cfd2a, BRF_ESS | BRF_PRG }, + + { "d0-d7.4m", 0x80000, 0xd8551b2f, BRF_GRA }, + { "d8-d15.4m", 0x80000, 0xb269c427, BRF_GRA }, + { "d16-d23.1m", 0x20000, 0xaf4ea5e7, BRF_GRA }, + { "d24-d31.1m", 0x20000, 0x578c3588, BRF_GRA }, +}; + +STD_ROM_PICK(Maniacsq) +STD_ROM_FN(Maniacsq) + +struct BurnDriver BurnDrvManiacsq = { + "maniacsq", NULL, NULL, NULL, "1996", + "Maniac Square (unprotected)\0", "Parent set for working drivers", "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, ManiacsqRomInfo, ManiacsqRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 256, 224, 4, 3 +}; + +static struct BurnRomInfo PhoenixRomDesc[] = { + { "ic45", 0x00800, 0x9f68086b, BRF_ESS | BRF_PRG }, + { "ic46", 0x00800, 0x273a4a82, BRF_ESS | BRF_PRG }, + { "ic47", 0x00800, 0x3d4284b9, BRF_ESS | BRF_PRG }, + { "ic48", 0x00800, 0xcb5d9915, BRF_ESS | BRF_PRG }, + { "h5-ic49.5a", 0x00800, 0xa105e4e7, BRF_ESS | BRF_PRG }, + { "h6-ic50.6a", 0x00800, 0xac5e9ec1, BRF_ESS | BRF_PRG }, + { "h7-ic51.7a", 0x00800, 0x2eab35b4, BRF_ESS | BRF_PRG }, + { "h8-ic52.8a", 0x00800, 0xaff8e9c5, BRF_ESS | BRF_PRG }, + + { "ic23.3d", 0x00800, 0x3c7e623f, BRF_GRA }, + { "ic24.4d", 0x00800, 0x59916d3b, BRF_GRA }, + { "b1-ic39.3b", 0x00800, 0x53413e8f, BRF_GRA }, + { "b2-ic40.4b", 0x00800, 0x0be2ba91, BRF_GRA }, + + { "mmi6301.ic40", 0x00100, 0x79350b25, BRF_GRA }, + { "mmi6301.ic41", 0x00100, 0xe176b768, BRF_GRA }, +}; + +STD_ROM_PICK(Phoenix) +STD_ROM_FN(Phoenix) + +struct BurnDriver BurnDrvPhoenix = { + "phoenix", NULL, NULL, NULL, "1980", + "Phoenix (Amstar)\0", "Parent set for working drivers", "Amstar", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, PhoenixRomInfo, PhoenixRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 208, 256, 3, 4 +}; + +static struct BurnRomInfo ThepitRomDesc[] = { + { "pit1.bin", 0x01000, 0x71affecc, BRF_ESS | BRF_PRG }, + { "pit2.bin", 0x01000, 0x894063cd, BRF_ESS | BRF_PRG }, + { "pit3.bin", 0x01000, 0x1b488543, BRF_ESS | BRF_PRG }, + { "pit4.bin", 0x01000, 0xe941e848, BRF_ESS | BRF_PRG }, + { "pit5.bin", 0x01000, 0xe0643c95, BRF_ESS | BRF_PRG }, + + { "pit6.bin", 0x00800, 0x1b79dfb6, BRF_ESS | BRF_PRG }, + + { "pit8.bin", 0x00800, 0x69502afc, BRF_GRA }, + { "pit7.bin", 0x00800, 0xd901b353, BRF_GRA }, + + { "82s123.ic4", 0x00020, 0xa758b567, BRF_GRA }, +}; + +STD_ROM_PICK(Thepit) +STD_ROM_FN(Thepit) + +struct BurnDriver BurnDrvThepit = { + "thepit", NULL, NULL, NULL, "1992", + "The Pit\0", "Parent set for working drivers", "Taito", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, ThepitRomInfo, ThepitRomName, NULL, NULL, ParentInputInfo, NULL, + ParentInit, ParentExit, NULL, NULL, NULL, + NULL, 0, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/galaxian/d_galaxian.cpp b/src/burn/drivers/galaxian/d_galaxian.cpp new file mode 100644 index 00000000..f9162e78 --- /dev/null +++ b/src/burn/drivers/galaxian/d_galaxian.cpp @@ -0,0 +1,20973 @@ +#include "gal.h" + +static INT32 ScrambleInit(); + +// Input definitions (alphabetical) +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} +static struct BurnInputInfo Ad2083InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort1 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort1 + 2, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 0, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort1 + 4, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Ad2083) + +static struct BurnInputInfo AmidarInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Amidar) + +static struct BurnInputInfo AnteaterInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort2 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 6, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Anteater) + +static struct BurnInputInfo AnteatergInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort2 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort2 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort2 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort2 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort2 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Anteaterg) + +static struct BurnInputInfo AnteaterukInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Anteateruk) + +static struct BurnInputInfo AtlantisInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Atlantis) + +static struct BurnInputInfo AzurianInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 1, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 0, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 3, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 2, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 5, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Azurian) + +static struct BurnInputInfo BagmanmcInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort0 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 0, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 5, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 3, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 6, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Bagmanmc) + +static struct BurnInputInfo Batman2InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 7, "p1 fire 2" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Batman2) + +static struct BurnInputInfo BlkholeInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Blkhole) + +static struct BurnInputInfo BongoInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 5, "p1 up" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 up" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Bongo) + +static struct BurnInputInfo CalipsoInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + + {"P1 Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , GalInputPort2 + 0, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , GalInputPort0 + 0, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Calipso) + +static struct BurnInputInfo CheckmanjInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort2 + 1, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort2 + 0, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Checkmanj) + +static struct BurnInputInfo CheckmanInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 coin" }, + {"Start 1/P1 Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 0, "p2 coin" }, + {"Start 2/P1 Fire 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 4, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Checkman) + +static struct BurnInputInfo CkonggInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 6, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Ckongg) + +static struct BurnInputInfo CkongsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Ckongs) + +static struct BurnInputInfo DambustrInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 0, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort0 + 2, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort1 + 5, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort1 + 4, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort1 + 3, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort1 + 2, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort1 + 1, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , GalInputPort0 + 7, "p1 fire 3" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Dambustr) + +static struct BurnInputInfo DarkplntInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + + {"Left" , BIT_DIGITAL , GalInputPort3 + 0, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort3 + 1, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 2, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , GalInputPort0 + 0, "p1 fire 3" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Darkplnt) + +static struct BurnInputInfo DevilfsgInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Devilfsg) + +static struct BurnInputInfo DevilfshInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Devilfsh) + +static struct BurnInputInfo DingoInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort2 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Dingo) + +static struct BurnInputInfo DkongjrmInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 5, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Dkongjrm) + +static struct BurnInputInfo DrivfrcgInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort1 + 1, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Drivfrcg) + +static struct BurnInputInfo ExplorerInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 0, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Explorer) + +static struct BurnInputInfo Fourin1InputList[] = { + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"GM Dip 1" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, + {"SC Dip 2" , BIT_DIPSWITCH , GalDip + 4 , "dip" }, + {"GX Dip 3" , BIT_DIPSWITCH , GalDip + 5 , "dip" }, + {"GC Dip 4" , BIT_DIPSWITCH , GalDip + 6 , "dip" }, +}; + +STDINPUTINFO(Fourin1) + +static struct BurnInputInfo FroggInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Frogg) + +static struct BurnInputInfo FroggerInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Frogger) + +static struct BurnInputInfo FroggermcInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Froggermc) + +static struct BurnInputInfo GalaxianInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Galaxian) + +static struct BurnInputInfo GmgalaxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"GM Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"GM Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"GM Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"GX Dip 1" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, + {"GX Dip 2" , BIT_DIPSWITCH , GalDip + 4 , "dip" }, + {"GX Dip 3" , BIT_DIPSWITCH , GalDip + 5 , "dip" }, + {"Game Select Switch", BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Gmgalax) + +static struct BurnInputInfo HotshockInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort1 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort1 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 0, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort1 + 5, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Hotshock) + +static struct BurnInputInfo HunchbkgInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 fire 1" }, + + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Hunchbkg) + +static struct BurnInputInfo HunchbksInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Hunchbks) + +static struct BurnInputInfo HustlerInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 1, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Hustler) + +static struct BurnInputInfo JumpbugInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort1 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Jumpbug) + +static struct BurnInputInfo KingballInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Fake Dip" , BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Kingball) + +static struct BurnInputInfo CkongmcInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 1, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Ckongmc) + +static struct BurnInputInfo LadybuggInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort2 + 5, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Ladybugg) + +static struct BurnInputInfo LeversInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort1 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"P2 Up" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , GalInputPort1 + 7, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Levers) + +static struct BurnInputInfo LosttombInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort0 + 0, "p2 start" }, + + {"Left Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"Left Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"left Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Left Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 6, "p1 fire 1" }, + + {"Right Up" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"Right Down" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"Right Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right Right" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Losttomb) + +static struct BurnInputInfo LuctodayInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 7, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Luctoday) + +static struct BurnInputInfo MarsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"P1 Left Stick Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"P1 Left Stick Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"P1 Left Stick Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"P1 Left Stick Right", BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"P1 Rght Stick Up" , BIT_DIGITAL , GalInputPort2 + 7, "p3 up" }, + {"P1 Rght Stick Down" , BIT_DIGITAL , GalInputPort2 + 5, "p3 down" }, + {"P1 Rght Stick Left" , BIT_DIGITAL , GalInputPort0 + 3, "p3 left" }, + {"P1 Rght Stick Right", BIT_DIGITAL , GalInputPort0 + 2, "p3 right" }, + + {"P2 Left Stick Up" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"P2 Left Stick Down" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"P2 Left Stick Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"P2 Left Stick Right", BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"P2 Rght Stick Up" , BIT_DIGITAL , GalInputPort3 + 7, "p4 up" }, + {"P2 Rght Stick Down" , BIT_DIGITAL , GalInputPort3 + 5, "p4 down" }, + {"P2 Rght Stick Left" , BIT_DIGITAL , GalInputPort1 + 3, "p4 left" }, + {"P2 Rght Stick Right", BIT_DIGITAL , GalInputPort1 + 2, "p4 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 1, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Mars) + +static struct BurnInputInfo MoonwarInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 3, "p2 start" }, + + {"Hyper Flip / Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 2" }, + + A("Dial" , BIT_ANALOG_REL, &GalAnalogPort0 , "p1 z-axis" ), + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort1 + 6, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , GalInputPort1 + 5, "p1 fire 3" }, + + A("Dial (Cocktail)" , BIT_ANALOG_REL, &GalAnalogPort1 , "p2 z-axis" ), + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 fire 1" }, + {"Fire 3 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 5, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Moonwar) + +static struct BurnInputInfo MrkougarInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Mrkougar) + +static struct BurnInputInfo MshuttleInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 5, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Mshuttle) + +static struct BurnInputInfo OmegaInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Omega) + +static struct BurnInputInfo OrbitronInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Orbitron) + +static struct BurnInputInfo Ozon1InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"P2 Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Ozon1) + +static struct BurnInputInfo PacmanblInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Pacmanbl) + +static struct BurnInputInfo Phoenxp2InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Phoenxp2) + +static struct BurnInputInfo PicsesInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 0, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Picses) + +static struct BurnInputInfo PorterInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 1, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Porter) + +static struct BurnInputInfo RacknrolInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 5, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Racknrol) + +static struct BurnInputInfo RescueInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort2 + 6, "p2 start" }, + + {"P1 Left Stick Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"P1 Left Stick Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"P1 Left Stick Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"P1 Left Stick Right", BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"P1 Rght Stick Up" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"P1 Rght Stick Down" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"P1 Rght Stick Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"P1 Rght Stick Right", BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 0, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Rescue) + +static struct BurnInputInfo RockclimInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"P1 Left Stick Up" , BIT_DIGITAL , GalInputPort1 + 4, "p1 up" }, + {"P1 Left Stick Down" , BIT_DIGITAL , GalInputPort1 + 5, "p1 down" }, + {"P1 Left Stick Left" , BIT_DIGITAL , GalInputPort1 + 2, "p1 left" }, + {"P1 Left Stick Right", BIT_DIGITAL , GalInputPort1 + 3, "p1 right" }, + {"P1 Rght Stick Up" , BIT_DIGITAL , GalInputPort0 + 4, "p2 up" }, + {"P1 Rght Stick Down" , BIT_DIGITAL , GalInputPort0 + 5, "p2 down" }, + {"P1 Rght Stick Left" , BIT_DIGITAL , GalInputPort0 + 2, "p2 left" }, + {"P1 Rght Stick Right", BIT_DIGITAL , GalInputPort0 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , &GalFakeDip , "dip" }, +}; + +STDINPUTINFO(Rockclim) + +static struct BurnInputInfo ScorpionmcInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 coin" }, + {"Start 1 / Fire 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2 / Fire 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 5, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 0, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Scorpionmc) + +static struct BurnInputInfo AracnisInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 6, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 0, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH , GalDip + 3 , "dip" }, +}; + +STDINPUTINFO(Aracnis) + +static struct BurnInputInfo Scramb2InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 2, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Scramb2) + +static struct BurnInputInfo ScramblbInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Scramblb) + +static struct BurnInputInfo ScrambleInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Scramble) + +static struct BurnInputInfo SfxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Sfx) + +static struct BurnInputInfo SkybaseInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort2 + 6, "p1 fire 2" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 7, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Skybase) + +static struct BurnInputInfo SmooncrsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Smooncrs) + +static struct BurnInputInfo SpdcoinInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort0 + 3, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Spdcoin) + +static struct BurnInputInfo StratgyxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Stratgyx) + +static struct BurnInputInfo StreakngInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Streakng) + +static struct BurnInputInfo SuperbonInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort0 + 0, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort1 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort1 + 6, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Superbon) + +static struct BurnInputInfo TazmaniaInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort2 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 0, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 6, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Tazmania) + +static struct BurnInputInfo TazzmangInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1 / Fire 2" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 7, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Tazzmang) + +static struct BurnInputInfo TdpgalInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 5, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Tdpgal) + +static struct BurnInputInfo TheendInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , GalInputPort0 + 1, "p1 fire 2" }, + + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Theend) + +static struct BurnInputInfo ThepitmInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 7, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 5, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Thepitm) + +static struct BurnInputInfo TurtlesInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort2 + 4, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort2 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort2 + 0, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Service" , BIT_DIGITAL , GalInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Turtles) + +static struct BurnInputInfo WarofbugInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , GalInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 1, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Warofbug) + +static struct BurnInputInfo ZigzagInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , GalInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , GalInputPort1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , GalInputPort1 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , GalInputPort0 + 5, "p1 up" }, + {"Down" , BIT_DIGITAL , GalInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , GalInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , GalInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , GalInputPort0 + 4, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 5, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , GalInputPort0 + 7, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , GalInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &GalReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , GalDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , GalDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , GalDip + 2 , "dip" }, +}; + +STDINPUTINFO(Zigzag) + +#undef A + +// Dip Switch defintions (alphabetical) +static struct BurnDIPInfo Ad2083DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x10, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0d, 0x01, 0x0f, 0x08, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x0f, 0x09, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0f, 0x0a, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0b, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x01, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x0c, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x0d, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x02, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0e, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x0f, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0x0f, 0x03, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x04, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x05, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x07, "1 Coin 8 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x0d, 0x01, 0xf0, 0x80, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xf0, 0x90, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xf0, 0xa0, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xb0, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x10, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xf0, 0xc0, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0xf0, 0xd0, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x20, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xe0, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0xf0, 0xf0, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0xf0, 0x30, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x40, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0xf0, 0x50, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0xf0, 0x70, "1 Coin 8 Plays" }, + + // Dip 4 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x03, "2" }, + {0x0e, 0x01, 0x03, 0x02, "3" }, + {0x0e, 0x01, 0x03, 0x01, "4" }, + {0x0e, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x0c, 0x0c, "None" }, + {0x0e, 0x01, 0x0c, 0x08, "100000" }, + {0x0e, 0x01, 0x0c, 0x04, "150000" }, + {0x0e, 0x01, 0x0c, 0x00, "200000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x10, 0x10, "Upright" }, + {0x0e, 0x01, 0x10, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ad2083) + +static struct BurnDIPInfo AmidarDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x06, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x03, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "30000 50000" }, + {0x12, 0x01, 0x04, 0x00, "50000 50000" }, + + // Dip 4 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x13, 0x01, 0x0f, 0x0b, "4 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0d, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x0f, 0x07, "4 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x0f, 0x01, "2 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x08, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 5 Plays" }, + {0x13, 0x01, 0x0f, 0x04, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x0f, 0x02, "1 Coin 5 Plays" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x13, 0x01, 0x0f, 0x0f, "Free Play" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x13, 0x01, 0xf0, 0xb0, "4 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 2 Plays" }, + {0x13, 0x01, 0xf0, 0x70, "4 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Plays" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 2 Plays" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 5 Plays" }, + {0x13, 0x01, 0xf0, 0x40, "1 Coin 3 Plays" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x13, 0x01, 0xf0, 0x20, "1 Coin 5 Plays" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Plays" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x13, 0x01, 0xf0, 0xf0, "Disable All Coins" }, +}; + +STDDIPINFO(Amidar) + +static struct BurnDIPInfo AmidaroDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x02, NULL }, + {0x12, 0xff, 0xff, 0x06, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "1" }, + {0x11, 0x01, 0x03, 0x01, "2" }, + {0x11, 0x01, 0x03, 0x02, "3" }, + {0x11, 0x01, 0x03, 0x03, "4" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Level Progression" }, + {0x12, 0x01, 0x02, 0x02, "Slow" }, + {0x12, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "30000 70000" }, + {0x12, 0x01, 0x04, 0x00, "50000 80000" }, + + // Dip 4 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x13, 0x01, 0x0f, 0x0b, "4 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0d, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x0f, 0x07, "4 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x0f, 0x01, "2 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x08, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 5 Plays" }, + {0x13, 0x01, 0x0f, 0x04, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x0f, 0x02, "1 Coin 5 Plays" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x13, 0x01, 0x0f, 0x0f, "Free Play" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x13, 0x01, 0xf0, 0xb0, "4 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 2 Plays" }, + {0x13, 0x01, 0xf0, 0x70, "4 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Plays" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 2 Plays" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 5 Plays" }, + {0x13, 0x01, 0xf0, 0x40, "1 Coin 3 Plays" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x13, 0x01, 0xf0, 0x20, "1 Coin 5 Plays" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Plays" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x13, 0x01, 0xf0, 0xf0, "Disable All Coins" }, +}; + +STDDIPINFO(Amidaro) + +static struct BurnDIPInfo AmidarsDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x01, NULL }, + {0x12, 0xff, 0xff, 0x0a, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "2" }, + {0x11, 0x01, 0x03, 0x01, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x03, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x12, 0x01, 0x02, 0x02, "A 1C/1P B 1C/6P" }, + {0x12, 0x01, 0x02, 0x00, "A 2C/1P B 1C/3P" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x08, "Upright" }, + {0x12, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Amidars) + +static struct BurnDIPInfo AmidaruDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x06, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x03, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "30000 70000" }, + {0x12, 0x01, 0x04, 0x00, "50000 80000" }, + + // Dip 4 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x13, 0x01, 0x0f, 0x0b, "4 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 1 Play" }, + {0x13, 0x01, 0x0f, 0x0d, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x0f, 0x07, "4 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x0f, 0x01, "2 Coins 3 Plays" }, + {0x13, 0x01, 0x0f, 0x08, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 5 Plays" }, + {0x13, 0x01, 0x0f, 0x04, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x0f, 0x02, "1 Coin 5 Plays" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x13, 0x01, 0x0f, 0x0f, "Free Play" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x13, 0x01, 0xf0, 0xb0, "4 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Play" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 2 Plays" }, + {0x13, 0x01, 0xf0, 0x70, "4 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Plays" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins 3 Plays" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 2 Plays" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 5 Plays" }, + {0x13, 0x01, 0xf0, 0x40, "1 Coin 3 Plays" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x13, 0x01, 0xf0, 0x20, "1 Coin 5 Plays" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Plays" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x13, 0x01, 0xf0, 0xf0, "Disable All Coins" }, +}; + +STDDIPINFO(Amidaru) + +static struct BurnDIPInfo AnteaterDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x02, NULL }, + {0x11, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x01, 0x00, "3" }, + {0x10, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x00, "Off" }, + {0x10, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x11, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x11, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x11, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x00, "Upright" }, + {0x11, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Anteater) + +static struct BurnDIPInfo AnteatergDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x02, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0f, 0x01, 0x02, 0x00, "A 1C/1P B 1C/5P" }, + {0x0f, 0x01, 0x02, 0x02, "A 2C/1P B 1C/3P" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x0c, 0x00, "3" }, + {0x0f, 0x01, 0x0c, 0x04, "4" }, + {0x0f, 0x01, 0x0c, 0x08, "5" }, + {0x0f, 0x01, 0x0c, 0x0c, "6" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Upright" }, + {0x10, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x00, "Off" }, + {0x10, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 +}; + +STDDIPINFO(Anteaterg) + +static struct BurnDIPInfo AnteaterukDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x02, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Upright" }, + {0x10, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x00, "Off" }, + {0x10, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x11, 0x01, 0x02, 0x00, "A 1C/1P B 1C/5P" }, + {0x11, 0x01, 0x02, 0x02, "A 2C/1P B 1C/3P" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x00, "3" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x08, "5" }, + {0x11, 0x01, 0x0c, 0x0c, "6" }, +}; + +STDDIPINFO(Anteateruk) + +static struct BurnDIPInfo ArmorcarDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x02, NULL }, + {0x13, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x12, 0x01, 0x01, 0x00, "3" }, + {0x12, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x13, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x13, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x13, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x08, 0x00, "Upright" }, + {0x13, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Armorcar) + +static struct BurnDIPInfo AtlantisDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x01, NULL }, + {0x13, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x01, 0x01, "Upright" }, + {0x12, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x12, 0x01, 0x02, 0x00, "3" }, + {0x12, 0x01, 0x02, 0x02, "5" }, + + // Dip 3 + {0 , 0xfe, 0 , 3 , "Coinage" }, + {0x13, 0x01, 0x0e, 0x0c, "A 1C/3P B 2C/1P" }, + {0x13, 0x01, 0x0e, 0x0e, "A 1C/6P B 1C/1P" }, + {0x13, 0x01, 0x0e, 0x0a, "A 1C/99P B 1C/99P" }, +}; + +STDDIPINFO(Atlantis) + +static struct BurnDIPInfo AtlantisbDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x80, NULL }, + {0x11, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x10, 0x01, 0x40, 0x40, "2 Coins 1 Play" }, + {0x10, 0x01, 0x40, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x10, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x02, 0x00, "Easy" }, + {0x11, 0x01, 0x02, 0x02, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x04, "3" }, + {0x11, 0x01, 0x04, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x08, "Upright" }, + {0x11, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Atlantisb) + +static struct BurnDIPInfo AzurianDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x80, 0x00, "3" }, + {0x0f, 0x01, 0x80, 0x80, "5" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x01, 0x01, "2 Coins 1 Play" }, + {0x10, 0x01, 0x01, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x02, 0x00, "5000" }, + {0x10, 0x01, 0x02, 0x02, "7000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x08, 0x00, "Upright" }, + {0x10, 0x01, 0x08, 0x08, "Cocktail" }, + + // Fake Dip + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x03, 0x03, "Easy" }, + {0x11, 0x01, 0x03, 0x01, "Normal" }, + {0x11, 0x01, 0x03, 0x02, "Hard" }, + {0x11, 0x01, 0x03, 0x00, "Very Hard" }, +}; + +STDDIPINFO(Azurian) + +static struct BurnDIPInfo BagmanmcDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x80, NULL }, + {0x11, 0xff, 0xff, 0x7e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x03, "2" }, + {0x11, 0x01, 0x03, 0x02, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x11, 0x01, 0x04, 0x00, "A 2C/1P B 1C/1P" }, + {0x11, 0x01, 0x04, 0x04, "A 1C/1P B 1C/2P" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x18, 0x18, "Easy" }, + {0x11, 0x01, 0x18, 0x10, "Medium" }, + {0x11, 0x01, 0x18, 0x08, "Hard" }, + {0x11, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x11, 0x01, 0x20, 0x20, "English" }, + {0x11, 0x01, 0x20, 0x00, "French" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x40, 0x40, "30000" }, + {0x11, 0x01, 0x40, 0x00, "40000" }, +}; + +STDDIPINFO(Bagmanmc) + +static struct BurnDIPInfo Batman2DIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0xc0, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0e, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + {0x0e, 0x01, 0x40, 0x00, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0e, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0e, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0f, 0x01, 0x01, 0x00, "30000" }, + {0x0f, 0x01, 0x01, 0x01, "50000" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x04, 0x00, "3" }, + {0x0f, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x08, 0x00, "Upright" }, + {0x0f, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Batman2) + +static struct BurnDIPInfo BlkholeDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0x00, NULL }, + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0xc0, 0xc0, "2 Coins 1 Play" }, + {0x0b, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0b, 0x01, 0xc0, 0x40, "1 Coin 2 Plays" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 3 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0c, 0x01, 0x01, 0x00, "5000" }, + {0x0c, 0x01, 0x01, 0x01, "10000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x02, 0x02, "Upright" }, + {0x0c, 0x01, 0x02, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Blkhole) + +static struct BurnDIPInfo BongoDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0x00, NULL }, + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x40, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + + // Dip 4 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0d, 0x01, 0x06, 0x00, "2" }, + {0x0d, 0x01, 0x06, 0x02, "3" }, + {0x0d, 0x01, 0x06, 0x04, "4" }, + {0x0d, 0x01, 0x06, 0x06, "5" }, + + {0 , 0xfe, 0 , 2 , "Infinite Lives" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0d, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x80, 0x00, "Upright" }, + {0x0d, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(Bongo) + +static struct BurnDIPInfo CalipsoDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x02, NULL }, + {0x0f, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x01, 0x00, "3" }, + {0x0e, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x02, 0x00, "Off" }, + {0x0e, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x06, 0x06, "1 Coin 2 Plays" }, + {0x0f, 0x01, 0x06, 0x02, "1 Coin 3 Plays" }, + {0x0f, 0x01, 0x06, 0x00, "1 Coin 4 Plays" }, +}; + +STDDIPINFO(Calipso) + +static struct BurnDIPInfo CatacombDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x40, NULL }, + {0x0d, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0d, 0x01, 0x04, 0x04, "3" }, + {0x0d, 0x01, 0x04, 0x00, "5" }, +}; + +STDDIPINFO(Catacomb) + +static struct BurnDIPInfo CavelonDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x02, NULL }, + {0x13, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x01, 0x00, "Upright" }, + {0x12, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x12, 0x01, 0x02, 0x02, "A 1C/1P B 1C/6P" }, + {0x12, 0x01, 0x02, 0x00, "A 2C/1P B 1C/3P" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x06, 0x00, "2" }, + {0x13, 0x01, 0x06, 0x04, "3" }, + {0x13, 0x01, 0x06, 0x02, "4" }, + {0x13, 0x01, 0x06, 0x06, "5" }, +}; + +STDDIPINFO(Cavelon) + +static struct BurnDIPInfo CheckmanjDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x12, 0x01, 0x40, 0x40, "A 2C/1P B 1C/3P" }, + {0x12, 0x01, 0x40, 0x00, "A 1C/1P B 1C/6P" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x80, 0x00, "Upright" }, + {0x12, 0x01, 0x80, 0x80, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x00, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x02, "5" }, + {0x13, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x13, 0x01, 0x04, 0x00, "100000" }, + {0x13, 0x01, 0x04, 0x04, "200000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty increases at level"}, + {0x13, 0x01, 0x08, 0x08, "3" }, + {0x13, 0x01, 0x08, 0x00, "5" }, +}; + +STDDIPINFO(Checkmanj) + +static struct BurnDIPInfo CheckmanDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x40, 0x40, "A 2C/1P B 1C/3P" }, + {0x10, 0x01, 0x40, 0x00, "A 1C/1P B 1C/6P" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x04, 0x00, "100000" }, + {0x11, 0x01, 0x04, 0x04, "200000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty increases at level"}, + {0x11, 0x01, 0x08, 0x08, "3" }, + {0x11, 0x01, 0x08, 0x00, "5" }, +}; + +STDDIPINFO(Checkman) + +static struct BurnDIPInfo CkonggDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x80, NULL }, + {0x11, 0xff, 0xff, 0x0a, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x40, 0x00, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x40, 0x40, "1 Coin 4 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "1" }, + {0x11, 0x01, 0x03, 0x01, "2" }, + {0x11, 0x01, 0x03, 0x02, "3" }, + {0x11, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x08, 0x08, "500000" }, + {0x11, 0x01, 0x08, 0x00, "750000" }, +}; + +STDDIPINFO(Ckongg) + +static struct BurnDIPInfo CkongsDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x02, 0x02, "Upright" }, + {0x11, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x00, "3" }, + {0x11, 0x01, 0x04, 0x04, "4" }, +}; + +STDDIPINFO(Ckongs) + +static struct BurnDIPInfo DambustrDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Clear Swear Words" }, + {0x0c, 0x01, 0x20, 0x00, "Off" }, + {0x0c, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Second Coin Counter" }, + {0x0d, 0x01, 0x40, 0x00, "Off" }, + {0x0d, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0d, 0x01, 0x80, 0x80, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x80, 0x00, "1 Coin 1 Play" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x00, "3" }, + {0x0e, 0x01, 0x03, 0x01, "4" }, + {0x0e, 0x01, 0x03, 0x02, "5" }, + {0x0e, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Game Test Mode" }, + {0x0e, 0x01, 0x04, 0x00, "Off" }, + {0x0e, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Union Jack" }, + {0x0e, 0x01, 0x08, 0x08, "Off" }, + {0x0e, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Dambustr) + +static struct BurnDIPInfo DarkplntDIPList[]= +{ + // Default Values + {0x08, 0xff, 0xff, 0x00, NULL }, + {0x09, 0xff, 0xff, 0x02, NULL }, + {0x0a, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Occurrence" }, + {0x09, 0x01, 0x01, 0x00, "Once" }, + {0x09, 0x01, 0x01, 0x01, "Everytime" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x09, 0x01, 0x02, 0x02, "1" }, + {0x09, 0x01, 0x02, 0x00, "2" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0a, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x0a, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x0a, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x0a, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0a, 0x01, 0x08, 0x08, "100000" }, + {0x0a, 0x01, 0x08, 0x00, "200000" }, +}; + +STDDIPINFO(Darkplnt) + +static struct BurnDIPInfo DevilfsgDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0xc0, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x10, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x10, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x10, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x01, 0x00, "10000" }, + {0x11, 0x01, 0x01, 0x01, "15000" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x00, "4" }, + {0x11, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x00, "Upright" }, + {0x11, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Devilfsg) + +static struct BurnDIPInfo DevilfshDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x03, NULL }, + {0x11, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x01, 0x01, "10000" }, + {0x10, 0x01, 0x01, 0x00, "15000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x02, 0x02, "Upright" }, + {0x10, 0x01, 0x02, 0x00, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x02, 0x02, "4" }, + {0x11, 0x01, 0x02, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x11, 0x01, 0x04, 0x04, "2 Coins 1 Play" }, + {0x11, 0x01, 0x04, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x11, 0x01, 0x08, 0x00, "1 Coin 3 Plays" }, + {0x11, 0x01, 0x08, 0x08, "1 Coin 5 Plays" }, +}; + +STDDIPINFO(Devilfsh) + +static struct BurnDIPInfo DingoDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x80, NULL }, + {0x11, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x00, "Upright" }, + {0x10, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x80, 0x40, "A 2C/1P B 1C/3P" }, + {0x10, 0x01, 0x80, 0x80, "A 1C/1P B 1C/5P" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x03, 0x00, "Easy" }, + {0x11, 0x01, 0x03, 0x01, "Medium" }, + {0x11, 0x01, 0x03, 0x02, "Hard" }, + {0x11, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x00, "3" }, + {0x11, 0x01, 0x04, 0x04, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x08, 0x00, "20000" }, + {0x11, 0x01, 0x08, 0x08, "40000" }, +}; + +STDDIPINFO(Dingo) + +static struct BurnDIPInfo DkongjrmDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x08, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0xc0, 0xc0, "3 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Coin Multiplier" }, + {0x10, 0x01, 0x01, 0x00, "x1" }, + {0x10, 0x01, 0x01, 0x01, "x2" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x06, 0x00, "3" }, + {0x10, 0x01, 0x06, 0x02, "4" }, + {0x10, 0x01, 0x06, 0x04, "5" }, + {0x10, 0x01, 0x06, 0x06, "6" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x08, 0x08, "Upright" }, + {0x10, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Dkongjrm) + +static struct BurnDIPInfo DrivfrcgDIPList[]= +{ + // Default Values + {0x07, 0xff, 0xff, 0x00, NULL }, + {0x08, 0xff, 0xff, 0x00, NULL }, + {0x09, 0xff, 0xff, 0x00, NULL }, + {0x0a, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x08, 0x01, 0x40, 0x40, "A 2C/1P B 1C/3P" }, + {0x08, 0x01, 0x40, 0x00, "A 1C/1P B 1C/5P" }, + + // Dip 3 + + // Dip 4 +}; + +STDDIPINFO(Drivfrcg) + +static struct BurnDIPInfo Eagle2DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x80, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x40, 0x00, "30000" }, + {0x0c, 0x01, 0x40, 0x40, "50000" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0c, 0x01, 0x80, 0x80, "English" }, + {0x0c, 0x01, 0x80, 0x00, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x0d, 0x01, 0x0c, 0x00, "Off" }, + {0x0d, 0x01, 0x0c, 0x0c, "On" }, +}; + +STDDIPINFO(Eagle2) + +static struct BurnDIPInfo ExodusDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0xc0, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x40, 0x00, "Off" }, + {0x0b, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "7000" }, + {0x0d, 0x01, 0x01, 0x01, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0d, 0x01, 0x04, 0x00, "3" }, + {0x0d, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x00, "Upright" }, + {0x0d, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Exodus) + +static struct BurnDIPInfo ExplorerDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0d, 0x01, 0x0f, 0x08, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x0f, 0x09, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0f, 0x0a, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0b, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x01, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x0c, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x0d, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x02, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0e, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x0f, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0x0f, 0x03, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x04, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x05, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x07, "1 Coin 8 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x0d, 0x01, 0xf0, 0x80, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xf0, 0x90, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xf0, 0xa0, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xb0, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x10, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xf0, 0xc0, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0xf0, 0xd0, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x20, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xe0, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0xf0, 0xf0, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0xf0, 0x30, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x40, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0xf0, 0x50, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0xf0, 0x70, "1 Coin 8 Plays" }, + + // Dip 4 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x00, "2" }, + {0x0e, 0x01, 0x03, 0x01, "3" }, + {0x0e, 0x01, 0x03, 0x02, "4" }, + {0x0e, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x0e, 0x01, 0x1c, 0x04, "10000" }, + {0x0e, 0x01, 0x1c, 0x0c, "15000" }, + {0x0e, 0x01, 0x1c, 0x14, "20000" }, + {0x0e, 0x01, 0x1c, 0x1c, "25000" }, + {0x0e, 0x01, 0x1c, 0x00, "30000" }, + {0x0e, 0x01, 0x1c, 0x08, "50000" }, + {0x0e, 0x01, 0x1c, 0x10, "70000" }, + {0x0e, 0x01, 0x1c, 0x18, "80000" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x80, 0x00, "Off" }, + {0x0e, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Explorer) + +static struct BurnDIPInfo FantaziaDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x40, 0x00, "30000" }, + {0x0c, 0x01, 0x40, 0x40, "50000" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Fantazia) + +static struct BurnDIPInfo Fourin1DIPList[]= +{ + // Defaults + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x20, 0x00, "Upright" }, + {0x0e, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x04, 0x00, "3" }, + {0x10, 0x01, 0x04, 0x04, "5" }, + + // Ghost Muncher Pt 3 + {0 , 0xfe, 0 , 4 , "Bonus Life (Ghost Muncher)"}, + {0x11, 0x01, 0x03, 0x01, "10000" }, + {0x11, 0x01, 0x03, 0x02, "15000" }, + {0x11, 0x01, 0x03, 0x03, "20000" }, + {0x11, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Coinage (Ghost Muncher)"}, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x00, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xc0, 0xc0, "Free Play" }, + + // Scramble Pt 2 + {0 , 0xfe, 0 , 2 , "Allow Continue (Scramble)"}, + {0x12, 0x01, 0x08, 0x08, "No" }, + {0x12, 0x01, 0x08, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Coinage (Scramble)" }, + {0x12, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xc0, 0x00, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xc0, 0xc0, "Free Play" }, + + // Galaxian Pt 5 + {0 , 0xfe, 0 , 4 , "Bonus Life (Galaxian)" }, + {0x13, 0x01, 0x03, 0x01, "4000" }, + {0x13, 0x01, 0x03, 0x02, "5000" }, + {0x13, 0x01, 0x03, 0x03, "7000" }, + {0x13, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 3 , "Coinage (Galaxian)" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "Free Play" }, + + // Galactic Convoy + {0 , 0xfe, 0 , 2 , "Bonus Life (Galactic Convoy)"}, + {0x14, 0x01, 0x01, 0x00, "50000" }, + {0x14, 0x01, 0x01, 0x01, "80000" }, + + {0 , 0xfe, 0 , 3 , "Coinage (Galactic Convoy)"}, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xc0, 0x00, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xc0, 0xc0, "Free Play" }, +}; + +STDDIPINFO(Fourin1) + +static struct BurnDIPInfo FroggDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0xc0, NULL }, + {0x10, 0xff, 0xff, 0x05, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0xc0, 0xc0, "3" }, + {0x0f, 0x01, 0xc0, 0x80, "5" }, + {0x0f, 0x01, 0xc0, 0x40, "7" }, + {0x0f, 0x01, 0xc0, 0x00, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x01, "Upright" }, + {0x10, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x04, 0x00, "2 Coins 1 Credit" }, + {0x10, 0x01, 0x04, 0x04, "1 Coin 1 Credit" }, +}; + +STDDIPINFO(Frogg) + +static struct BurnDIPInfo FroggerDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x03, NULL }, + {0x10, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x03, "3" }, + {0x0f, 0x01, 0x03, 0x02, "5" }, + {0x0f, 0x01, 0x03, 0x01, "7" }, + {0x0f, 0x01, 0x03, 0x00, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x04, "A 2C/1P B 2C/1P C 2C/1P"}, + {0x10, 0x01, 0x06, 0x02, "A 2C/1P B 1C/3P C 2C/1P"}, + {0x10, 0x01, 0x06, 0x06, "A 1C/1P B 1C/1P C 1C/1P"}, + {0x10, 0x01, 0x06, 0x00, "A 1C/1P B 1C/6P C 1C/1P"}, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x08, 0x08, "Upright" }, + {0x10, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Frogger) + +static struct BurnDIPInfo FroggermcDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0xc0, NULL }, + {0x10, 0xff, 0xff, 0x07, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0xc0, 0xc0, "3" }, + {0x0f, 0x01, 0xc0, 0x80, "5" }, + {0x0f, 0x01, 0xc0, 0x40, "7" }, + {0x0f, 0x01, 0xc0, 0x00, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x01, "Upright" }, + {0x10, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x02, "A 2C/1P B 2C/1P C 2C/1P"}, + {0x10, 0x01, 0x06, 0x04, "A 2C/1P B 1C/3P C 2C/1P"}, + {0x10, 0x01, 0x06, 0x06, "A 1C/1P B 1C/1P C 1C/1P"}, + {0x10, 0x01, 0x06, 0x00, "A 1C/1P B 1C/6P C 1C/1P"}, +}; + +STDDIPINFO(Froggermc) + +static struct BurnDIPInfo GalaxianDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x00, "7000" }, + {0x0e, 0x01, 0x03, 0x01, "10000" }, + {0x0e, 0x01, 0x03, 0x02, "12000" }, + {0x0e, 0x01, 0x03, 0x03, "20000" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "2" }, + {0x0e, 0x01, 0x04, 0x04, "3" }, +}; + +STDDIPINFO(Galaxian) + +static struct BurnDIPInfo GmgalaxDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x40, NULL }, + {0x10, 0xff, 0xff, 0x06, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Ghost Muncher Dip 1 + {0 , 0xfe, 0 , 2 , "GM - Cabinet" }, + {0x0e, 0x01, 0x20, 0x00, "Upright" }, + {0x0e, 0x01, 0x20, 0x20, "Cocktail" }, + + // Ghost Muncher Dip 2 + {0 , 0xfe, 0 , 4 , "GM - Bonus Life" }, + {0x0f, 0x01, 0xc0, 0x40, "10000" }, + {0x0f, 0x01, 0xc0, 0x80, "15000" }, + {0x0f, 0x01, 0xc0, 0xc0, "20000" }, + {0x0f, 0x01, 0xc0, 0x00, "None" }, + + // Ghost Muncher Dip 3 + {0 , 0xfe, 0 , 4 , "GM - Coinage" }, + {0x10, 0x01, 0x03, 0x00, "2 Coins 1 Play" }, + {0x10, 0x01, 0x03, 0x02, "1 Coin 1 Play" }, + {0x10, 0x01, 0x03, 0x01, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x03, 0x03, "Freeplay" }, + + {0 , 0xfe, 0 , 4 , "GM - Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "1" }, + {0x10, 0x01, 0x0c, 0x08, "2" }, + {0x10, 0x01, 0x0c, 0x04, "3" }, + {0x10, 0x01, 0x0c, 0x00, "4" }, + + // Galaxian Dip 1 + {0 , 0xfe, 0 , 2 , "GX - Cabinet" }, + {0x11, 0x01, 0x20, 0x00, "Upright" }, + {0x11, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "GX - Service Mode" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + // Galaxian Dip 2 + {0 , 0xfe, 0 , 4 , "GX - Coinage" }, + {0x12, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x12, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x12, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x12, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Galaxian Dip 3 + {0 , 0xfe, 0 , 4 , "GX - Bonus Life" }, + {0x13, 0x01, 0x03, 0x01, "4000" }, + {0x13, 0x01, 0x03, 0x02, "5000" }, + {0x13, 0x01, 0x03, 0x03, "7000" }, + {0x13, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "GX - Lives" }, + {0x13, 0x01, 0x04, 0x00, "3" }, + {0x13, 0x01, 0x04, 0x04, "5" }, + + // Select switch + {0 , 0xfe, 0 , 2 , "Game Select" }, + {0x14, 0x01, 0x01, 0x00, "Ghost Muncher" }, + {0x14, 0x01, 0x01, 0x01, "Galaxian" }, +}; + +STDDIPINFO(Gmgalax) + +static struct BurnDIPInfo GteikokbDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0xc0, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "7000" }, + {0x0d, 0x01, 0x01, 0x01, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0d, 0x01, 0x04, 0x00, "3" }, + {0x0d, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x00, "Upright" }, + {0x0d, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Gteikokb) + +static struct BurnDIPInfo Gteikob2DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0xc0, NULL }, + {0x0d, 0xff, 0xff, 0x08, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "7000" }, + {0x0d, 0x01, 0x01, 0x01, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0d, 0x01, 0x04, 0x00, "3" }, + {0x0d, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x08, "Upright" }, + {0x0d, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Gteikob2) + +static struct BurnDIPInfo HotshockDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x05, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0d, 0x01, 0xf0, 0x80, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xf0, 0x90, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xf0, 0xa0, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xb0, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x10, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xf0, 0xc0, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0xf0, 0xd0, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x20, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0xf0, 0xe0, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0xf0, 0xf0, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0xf0, 0x30, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0xf0, 0x40, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0xf0, 0x50, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0xf0, 0x60, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0xf0, 0x70, "1 Coin 8 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x0d, 0x01, 0x0f, 0x08, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x0f, 0x09, "2 Coins 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0f, 0x0a, "2 Coins 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0b, "2 Coins 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x01, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0f, 0x0c, "2 Coins 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x0d, "2 Coins 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x02, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0f, 0x0e, "2 Coins 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x0f, "2 Coins 8 Plays" }, + {0x0d, 0x01, 0x0f, 0x03, "1 Coin 4 Plays" }, + {0x0d, 0x01, 0x0f, 0x04, "1 Coin 5 Plays" }, + {0x0d, 0x01, 0x0f, 0x05, "1 Coin 6 Plays" }, + {0x0d, 0x01, 0x0f, 0x06, "1 Coin 7 Plays" }, + {0x0d, 0x01, 0x0f, 0x07, "1 Coin 8 Plays" }, + + // Dip 4 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x00, "2" }, + {0x0e, 0x01, 0x03, 0x01, "3" }, + {0x0e, 0x01, 0x03, 0x02, "4" }, + {0x0e, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0e, 0x01, 0x04, 0x04, "English" }, + {0x0e, 0x01, 0x04, 0x00, "Italian" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x18, 0x00, "75000" }, + {0x0e, 0x01, 0x18, 0x08, "150000" }, + {0x0e, 0x01, 0x18, 0x10, "200000" }, + {0x0e, 0x01, 0x18, 0x18, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x80, 0x00, "Upright" }, + {0x0e, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(Hotshock) + +static struct BurnDIPInfo HunchbkgDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x01, 0x00, "Upright" }, + {0x0e, 0x01, 0x01, 0x01, "Cocktail" }, +}; + +STDDIPINFO(Hunchbkg) + +static struct BurnDIPInfo HunchbksDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x02, NULL }, + {0x13, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x12, 0x01, 0x01, 0x00, "3" }, + {0x12, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x02, 0x00, "A 2C/1P B 1C/3P" }, + {0x12, 0x01, 0x02, 0x02, "A 1C/1P B 1C/5P" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x06, 0x06, "10000" }, + {0x13, 0x01, 0x06, 0x04, "20000" }, + {0x13, 0x01, 0x06, 0x02, "40000" }, + {0x13, 0x01, 0x06, 0x00, "80000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Hunchbks) + +static struct BurnDIPInfo HustlerDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x02, NULL }, + {0x12, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x01, 0x01, "1" }, + {0x11, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 2 , "Infinite Lives" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x06, 0x02, "3 Coins 1 Play" }, + {0x12, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x12, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x12, 0x01, 0x06, 0x00, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x08, "Upright" }, + {0x12, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Hustler) + +static struct BurnDIPInfo JumpbugDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x20, 0x00, "Upright" }, + {0x0f, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x40, 0x40, "Easy" }, + {0x10, 0x01, 0x40, 0x00, "Hard" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x01, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x03, "5" }, + {0x11, 0x01, 0x03, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x0c, 0x04, "A 2C/1P B 2C/1P" }, + {0x11, 0x01, 0x0c, 0x08, "A 2C/1P B 1C/3P" }, + {0x11, 0x01, 0x0c, 0x00, "A 1C/1P B 1C/1P" }, + {0x11, 0x01, 0x0c, 0x0c, "A 1C/1P B 1C/6P" }, +}; + +STDDIPINFO(Jumpbug) + +static struct BurnDIPInfo KingballDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x40, NULL }, + {0x0e, 0xff, 0xff, 0x04, NULL }, + {0x0f, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0xc0, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xc0, 0x40, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0x00, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x00, "10000" }, + {0x0e, 0x01, 0x03, 0x01, "12000" }, + {0x0e, 0x01, 0x03, 0x02, "15000" }, + {0x0e, 0x01, 0x03, 0x03, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "2" }, + {0x0e, 0x01, 0x04, 0x04, "3" }, + + // Fake dip + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x01, 0x00, "Off" }, + {0x0f, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Speech" }, + {0x0f, 0x01, 0x02, 0x00, "Off" }, + {0x0f, 0x01, 0x02, 0x02, "On" }, +}; + +STDDIPINFO(Kingball) + +static struct BurnDIPInfo CkongmcDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x0a, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x00, "1" }, + {0x0e, 0x01, 0x03, 0x01, "2" }, + {0x0e, 0x01, 0x03, 0x02, "3" }, + {0x0e, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0e, 0x01, 0x08, 0x08, "500000" }, + {0x0e, 0x01, 0x08, 0x00, "750000" }, +}; + +STDDIPINFO(Ckongmc) + +static struct BurnDIPInfo LadybuggDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x00, "Upright" }, + {0x10, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x80, 0x00, "A 1C/1P B 1C/5P" }, + {0x10, 0x01, 0x80, 0x80, "A 2C/1P B 1C/3P" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x03, 0x00, "Easiest" }, + {0x11, 0x01, 0x03, 0x01, "Easy" }, + {0x11, 0x01, 0x03, 0x02, "Hard" }, + {0x11, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x00, "3" }, + {0x11, 0x01, 0x04, 0x04, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x08, 0x00, "20000" }, + {0x11, 0x01, 0x08, 0x08, "40000" }, +}; + +STDDIPINFO(Ladybugg) + +static struct BurnDIPInfo LeversDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(Levers) + +static struct BurnDIPInfo LosttombDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x02, NULL }, + {0x10, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x02, "3" }, + {0x0f, 0x01, 0x03, 0x01, "5" }, + {0x0f, 0x01, 0x03, 0x00, "Free Play" }, + {0x0f, 0x01, 0x03, 0x03, "Invulnerability" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x10, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x10, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x10, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, +}; + +STDDIPINFO(Losttomb) + +static struct BurnDIPInfo LuctodayDIPList[]= +{ + // Default Values + {0x07, 0xff, 0xff, 0x00, NULL }, + {0x08, 0xff, 0xff, 0x00, NULL }, + {0x09, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 +}; + +STDDIPINFO(Luctoday) + +static struct BurnDIPInfo MarsDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x03, NULL }, + {0x18, 0xff, 0xff, 0x0e, NULL }, + {0x19, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x17, 0x01, 0x02, 0x00, "2 Coins 1 Play" }, + {0x17, 0x01, 0x02, 0x02, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x17, 0x01, 0x01, 0x01, "1 Coin 3 Plays" }, + {0x17, 0x01, 0x01, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x18, 0x01, 0x02, 0x02, "Upright" }, + {0x18, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x18, 0x01, 0x08, 0x08, "3" }, + {0x18, 0x01, 0x08, 0x00, "255" }, +}; + +STDDIPINFO(Mars) + +static struct BurnDIPInfo MimonkeyDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x03, NULL }, + {0x13, 0xff, 0xff, 0xae, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x06, 0x00, "3 Coins 1 Play" }, + {0x13, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x13, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x13, 0x01, 0x06, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x08, 0x08, "Upright" }, + {0x13, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Infinite Lives" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Mimonkey) + +static struct BurnDIPInfo MimonscoDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x01, NULL }, + {0x13, 0xff, 0xff, 0xae, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "1" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x01, "3" }, + {0x12, 0x01, 0x03, 0x00, "4" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x06, 0x00, "3 Coins 1 Play" }, + {0x13, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x13, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x13, 0x01, 0x06, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x08, 0x08, "Upright" }, + {0x13, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Infinite Lives" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Mimonsco) + +static struct BurnDIPInfo MinefldDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x02, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Starting Level" }, + {0x0e, 0x01, 0x02, 0x00, "1" }, + {0x0e, 0x01, 0x02, 0x02, "3" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x01, 0x00, "3" }, + {0x0f, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x02, 0x00, "Off" }, + {0x0f, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x02, 0x00, "1 Coin 1 Play" }, + {0x10, 0x01, 0x02, 0x02, "A 1C/2P B 2C/1P" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x0c, 0x00, "Easy" }, + {0x10, 0x01, 0x0c, 0x04, "Medium" }, + {0x10, 0x01, 0x0c, 0x08, "Hard" }, + {0x10, 0x01, 0x0c, 0x0c, "Hardest" }, +}; + +STDDIPINFO(Minefld) + +static struct BurnDIPInfo Moonal2DIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x01, "4000" }, + {0x0e, 0x01, 0x03, 0x02, "5000" }, + {0x0e, 0x01, 0x03, 0x03, "7000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, +}; + +STDDIPINFO(Moonal2) + +static struct BurnDIPInfo MooncrgxDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0xc0, NULL }, + {0x0d, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x01, "30000" }, + {0x0d, 0x01, 0x01, 0x00, "50000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x00, "Upright" }, + {0x0d, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Mooncrgx) + +static struct BurnDIPInfo MooncrsaDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x80, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x40, 0x00, "30000" }, + {0x0c, 0x01, 0x40, 0x40, "50000" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0c, 0x01, 0x80, 0x80, "English" }, + {0x0c, 0x01, 0x80, 0x00, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Mooncrsa) + +static struct BurnDIPInfo MooncrsgDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x40, 0x00, "30000" }, + {0x0c, 0x01, 0x40, 0x40, "50000" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Mooncrsg) + +static struct BurnDIPInfo MooncrstDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x80, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x40, 0x00, "30000" }, + {0x0c, 0x01, 0x40, 0x40, "50000" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0c, 0x01, 0x80, 0x80, "English" }, + {0x0c, 0x01, 0x80, 0x00, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Mooncrst) + +static struct BurnDIPInfo MoonqsrDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x20, 0x00, "Upright" }, + {0x0b, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x00, "Easy" }, + {0x0c, 0x01, 0xc0, 0x40, "Medium" }, + {0x0c, 0x01, 0xc0, 0x80, "Hard" }, + {0x0c, 0x01, 0xc0, 0xc0, "Hardest" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Moonqsr) + +static struct BurnDIPInfo MoonwarDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x03, NULL }, + {0x0f, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x03, "3" }, + {0x0e, 0x01, 0x03, 0x02, "4" }, + {0x0e, 0x01, 0x03, 0x01, "5" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x06, 0x06, "1 Coin 2 Plays" }, + {0x0f, 0x01, 0x06, 0x02, "1 Coin 3 Plays" }, + {0x0f, 0x01, 0x06, 0x00, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x08, 0x08, "Upright" }, + {0x0f, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Moonwar) + +static struct BurnDIPInfo MoonwaraDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x03, NULL }, + {0x0f, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x03, "3" }, + {0x0e, 0x01, 0x03, 0x02, "4" }, + {0x0e, 0x01, 0x03, 0x01, "5" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x06, 0x04, "1 Coin 2 Plays" }, + {0x0f, 0x01, 0x06, 0x02, "1 Coin 3 Plays" }, + {0x0f, 0x01, 0x06, 0x00, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x08, 0x08, "Upright" }, + {0x0f, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Moonwara) + +static struct BurnDIPInfo MrkougarDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x03, NULL }, + {0x0e, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0d, 0x01, 0x02, 0x00, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x02, 0x02, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0d, 0x01, 0x01, 0x01, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x01, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x02, 0x02, "Upright" }, + {0x0e, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x04, "3" }, + {0x0e, 0x01, 0x04, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x08, 0x00, "Easy" }, + {0x0e, 0x01, 0x08, 0x08, "Hard" }, +}; + +STDDIPINFO(Mrkougar) + +static struct BurnDIPInfo MshuttleDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x80, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x80, 0x80, "Upright" }, + {0x0e, 0x01, 0x80, 0x00, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x00, "3" }, + {0x0f, 0x01, 0x03, 0x01, "4" }, + {0x0f, 0x01, 0x03, 0x02, "5" }, + {0x0f, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0f, 0x01, 0x04, 0x00, "20000" }, + {0x0f, 0x01, 0x04, 0x04, "30000" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x18, 0x18, "3 Coins 1 Play" }, + {0x0e, 0x01, 0x18, 0x10, "3 Coins 1 Play" }, + {0x0e, 0x01, 0x18, 0x08, "2 Coins 1 Play" }, + {0x0e, 0x01, 0x18, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0x60, 0x00, "1 Coin 1 Play" }, + {0x0e, 0x01, 0x60, 0x20, "1 Coin 2 Plays" }, + {0x0e, 0x01, 0x60, 0x40, "1 Coin 3 Plays" }, + {0x0e, 0x01, 0x60, 0x60, "1 Coin 4 Plays" }, +}; + +STDDIPINFO(Mshuttle) + +static struct BurnDIPInfo Newsin7DIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x03, 0x00, "A 1C/1P B 2C/1P" }, + {0x10, 0x01, 0x03, 0x02, "A 1C/3P B 3C/1P" }, + {0x10, 0x01, 0x03, 0x01, "A 1C/2P B 1C/1P" }, + {0x10, 0x01, 0x03, 0x03, "A 1C/4P B 4C/1P" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x02, 0x00, "Upright" }, + {0x11, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x08, 0x08, "3" }, + {0x11, 0x01, 0x08, 0x00, "5" }, +}; + +STDDIPINFO(Newsin7) + +static struct BurnDIPInfo OmegaDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0xc0, NULL }, + {0x0d, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0c, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0c, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0c, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0c, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "10000" }, + {0x0d, 0x01, 0x01, 0x01, "20000" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0d, 0x01, 0x04, 0x00, "3" }, + {0x0d, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x00, "Upright" }, + {0x0d, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Omega) + +static struct BurnDIPInfo OrbitronDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x40, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x10, 0x01, 0x60, 0x00, "A 2C/1P B 1C/3P" }, + {0x10, 0x01, 0x60, 0x40, "A 1C/1P B 1C/6P" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x04, "2" }, + {0x11, 0x01, 0x04, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x00, "Upright" }, + {0x11, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Orbitron) + +static struct BurnDIPInfo Ozon1DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x02, NULL }, + {0x0d, 0xff, 0xff, 0x06, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x03, 0x03, "3" }, + {0x0c, 0x01, 0x03, 0x02, "4" }, + {0x0c, 0x01, 0x03, 0x01, "5" }, + {0x0c, 0x01, 0x03, 0x00, "6" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x06, 0x06, "A 1C/1P B 2C/1P" }, + {0x0d, 0x01, 0x06, 0x04, "A 1C/2P B 1C/1P" }, + {0x0d, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x0d, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, +}; + +STDDIPINFO(Ozon1) + +static struct BurnDIPInfo PacmanblDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0xc0, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0e, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0e, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0e, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0e, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0f, 0x01, 0x01, 0x00, "15000" }, + {0x0f, 0x01, 0x01, 0x01, "20000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0f, 0x01, 0x02, 0x00, "Easy" }, + {0x0f, 0x01, 0x02, 0x02, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x04, 0x00, "3" }, + {0x0f, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x08, 0x00, "Upright" }, + {0x0f, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Pacmanbl) + +static struct BurnDIPInfo Phoenxp2DIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0xc0, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x10, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x10, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x10, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x02, 0x00, "Easy" }, + {0x11, 0x01, 0x02, 0x02, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x04, 0x00, "3" }, + {0x11, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x00, "Upright" }, + {0x11, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Phoenxp2) + +static struct BurnDIPInfo PiscesDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0c, 0x01, 0x40, 0x00, "3" }, + {0x0c, 0x01, 0x40, 0x40, "4" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x80, 0x00, "Upright" }, + {0x0c, 0x01, 0x80, 0x80, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "10000" }, + {0x0d, 0x01, 0x01, 0x01, "20000" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x02, 0x02, "A 2C/1P B 1C/3P" }, + {0x0d, 0x01, 0x02, 0x00, "A 1C/1P B 1C/6P" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0d, 0x01, 0x04, 0x00, "Easy" }, + {0x0d, 0x01, 0x04, 0x04, "Hard" }, +}; + +STDDIPINFO(Pisces) + +static struct BurnDIPInfo PiscesbDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0c, 0x01, 0x40, 0x00, "3" }, + {0x0c, 0x01, 0x40, 0x40, "4" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x80, 0x00, "Upright" }, + {0x0c, 0x01, 0x80, 0x80, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x01, 0x00, "10000" }, + {0x0d, 0x01, 0x01, 0x01, "20000" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x02, 0x02, "A 2C/1P B 1C/2P 2C/5P" }, + {0x0d, 0x01, 0x02, 0x00, "A 1C/1P B 1C/5P" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0d, 0x01, 0x04, 0x00, "Easy" }, + {0x0d, 0x01, 0x04, 0x04, "Hard" }, +}; + +STDDIPINFO(Piscesb) + +static struct BurnDIPInfo PorterDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 +}; + +STDDIPINFO(Porter) + +static struct BurnDIPInfo RacknrolDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0x00, NULL }, + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 +}; + +STDDIPINFO(Racknrol) + +static struct BurnDIPInfo RedufoDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0xc0, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Coin A" }, + {0x0d, 0x01, 0x40, 0x00, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x40, 0x40, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Coin B" }, + {0x0d, 0x01, 0x80, 0x80, "1 Coin 3 Plays" }, + {0x0d, 0x01, 0x80, 0x00, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0e, 0x01, 0x01, 0x00, "7000" }, + {0x0e, 0x01, 0x01, 0x01, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x08, 0x00, "Upright" }, + {0x0e, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Redufo) + +static struct BurnDIPInfo RedufobDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "A 2C/1P B 1C/3P" }, + {0x0d, 0x01, 0xc0, 0x00, "A 1C/1P B 1C/6P" }, + {0x0d, 0x01, 0xc0, 0x80, "A 1C/2P B 1C/12P" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x01, "4000" }, + {0x0e, 0x01, 0x03, 0x02, "5000" }, + {0x0e, 0x01, 0x03, 0x03, "7000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, +}; + +STDDIPINFO(Redufob) + +static struct BurnDIPInfo RescueDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x02, NULL }, + {0x10, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Starting Level" }, + {0x0e, 0x01, 0x02, 0x00, "1" }, + {0x0e, 0x01, 0x02, 0x02, "3" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x01, 0x00, "3" }, + {0x0f, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x02, 0x00, "Off" }, + {0x0f, 0x01, 0x02, 0x02, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x10, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x10, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x10, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x08, 0x08, "Easy" }, + {0x10, 0x01, 0x08, 0x00, "Hard" }, +}; + +STDDIPINFO(Rescue) + +static struct BurnDIPInfo RockclimDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x40, NULL }, + {0x0e, 0xff, 0xff, 0xc0, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0e, 0x01, 0x40, 0x00, "30000" }, + {0x0e, 0x01, 0x40, 0x40, "50000" }, + + {0 , 0xfe, 0 , 2 , "Coin Slots" }, + {0x0e, 0x01, 0x80, 0x80, "1" }, + {0x0e, 0x01, 0x80, 0x00, "2" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x00, "3" }, + {0x0f, 0x01, 0x03, 0x01, "4" }, + {0x0f, 0x01, 0x03, 0x02, "5" }, + {0x0f, 0x01, 0x03, 0x03, "6" }, + + // Dip 4 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x10, 0x01, 0x0f, 0x00, "9 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x01, "8 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x02, "7 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x03, "6 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x04, "5 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x05, "4 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x06, "3 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x07, "2 Coins 1 Play" }, + {0x10, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x10, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x10, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + {0x10, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x10, 0x01, 0x0f, 0x09, "1 Coin 7 Plays" }, + {0x10, 0x01, 0x0f, 0x08, "1 Coin 8 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x10, 0x01, 0xf0, 0x00, "9 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x10, "8 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x20, "7 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x30, "6 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x40, "5 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x50, "4 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x60, "3 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0x70, "2 Coins 1 Play" }, + {0x10, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Plays" }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 3 Plays" }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Plays" }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 6 Plays" }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 7 Plays" }, + {0x10, 0x01, 0xf0, 0x80, "1 Coin 8 Plays" }, +}; + +STDDIPINFO(Rockclim) + +static struct BurnDIPInfo ScobraDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x13, 0x01, 0x02, 0x02, "3" }, + {0x13, 0x01, 0x02, 0x00, "4" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x14, 0x01, 0x06, 0x02, "2 Coins 1 Play" }, + {0x14, 0x01, 0x06, 0x00, "4 Coins 3 Plays" }, + {0x14, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x14, 0x01, 0x06, 0x06, "1 Coin 99 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Scobra) + +static struct BurnDIPInfo ScobrasDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x0c, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x13, 0x01, 0x02, 0x02, "3" }, + {0x13, 0x01, 0x02, 0x00, "5" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x14, 0x01, 0x06, 0x02, "2 Coins 1 Play" }, + {0x14, 0x01, 0x06, 0x00, "4 Coins 3 Plays" }, + {0x14, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x14, 0x01, 0x06, 0x06, "1 Coin 99 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Scobras) + +static struct BurnDIPInfo ScorpionDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x04, 0x00, "3" }, + {0x12, 0x01, 0x04, 0x01, "4" }, + {0x12, 0x01, 0x04, 0x02, "5" }, + {0x12, 0x01, 0x04, 0x03, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x04, 0x04, "Upright" }, + {0x13, 0x01, 0x04, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x13, 0x01, 0x08, 0x00, "A 1C/1P B 1C/1P" }, + {0x13, 0x01, 0x08, 0x08, "A 1C/1P B 1C/3P" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0xa0, 0x00, "Normal" }, + {0x13, 0x01, 0xa0, 0x20, "Medium" }, + {0x13, 0x01, 0xa0, 0x80, "Hard" }, + {0x13, 0x01, 0xa0, 0xa0, "Very Hard" }, +}; + +STDDIPINFO(Scorpion) + +static struct BurnDIPInfo ScorpionmcDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x40, NULL }, + {0x11, 0xff, 0xff, 0x04, NULL }, + {0x12, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0xc0, 0x00, "Easy" }, + {0x10, 0x01, 0xc0, 0x40, "Normal" }, + {0x10, 0x01, 0xc0, 0x80, "Hard" }, + {0x10, 0x01, 0xc0, 0xc0, "Hardest" }, + + // Dip 3 + {0 , 0xfe, 0 , 3 , "Lives" }, + {0x11, 0x01, 0x0c, 0x00, "2" }, + {0x11, 0x01, 0x0c, 0x04, "3" }, + {0x11, 0x01, 0x0c, 0x08, "4" }, + + // Dip 4 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x01, 0x00, "Upright" }, + {0x12, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x06, 0x00, "2 Coins 1 Play" }, + {0x12, 0x01, 0x06, 0x02, "1 Coin 1 Play" }, + {0x12, 0x01, 0x06, 0x04, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x06, 0x06, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Scorpionmc) + +static struct BurnDIPInfo AracnisDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x20, NULL }, + {0x0c, 0xff, 0xff, 0xf8, NULL }, + {0x0d, 0xff, 0xff, 0xfd, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x03, 0x00, "2 Coins 1 Play" }, + {0x0d, 0x01, 0x03, 0x01, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0x03, 0x03, "1 Coin 3 Plays" }, + + // Dip 4 +}; + +STDDIPINFO(Aracnis) + +static struct BurnDIPInfo Scramb2DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x03, NULL }, + {0x13, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x13, 0x01, 0x06, 0x04, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x06, 0x02, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x06, 0x00, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x08, 0x08, "Upright" }, + {0x13, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Scramb2) + +static struct BurnDIPInfo ScramblbDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x40, 0x00, "Upright" }, + {0x11, 0x01, 0x40, 0x40, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + {0x12, 0x01, 0x03, 0x01, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x03, 0x02, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x03, 0x03, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x00, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x08, "5" }, + {0x12, 0x01, 0x0c, 0x0c, "255" }, +}; + +STDDIPINFO(Scramblb) + +static struct BurnDIPInfo ScrambleDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x14, 0x01, 0x06, 0x06, "A 1C/1P B 2C/1P C 1C/1P"}, + {0x14, 0x01, 0x06, 0x04, "A 1C/2P B 1C/1P C 1C/2P"}, + {0x14, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P C 1C/3P"}, + {0x14, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P C 1C/4P"}, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Scramble) + +static struct BurnDIPInfo SfxDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x08, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x01, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x03, "5" }, + {0x13, 0x01, 0x03, 0x00, "Invulerability" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x14, 0x01, 0x06, 0x06, "3 Coins 1 Play" }, + {0x14, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x14, 0x01, 0x06, 0x00, "1 Coin 1 Play" }, + {0x14, 0x01, 0x06, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Sfx) + +static struct BurnDIPInfo SkybaseDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 1 Play (2 to start)"}, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x40, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x03, 0x00, "3" }, + {0x0e, 0x01, 0x03, 0x01, "4" }, + {0x0e, 0x01, 0x03, 0x02, "5" }, + {0x0e, 0x01, 0x03, 0x03, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x0c, 0x00, "10000" }, + {0x0e, 0x01, 0x0c, 0x40, "15000" }, + {0x0e, 0x01, 0x0c, 0x40, "20000" }, + {0x0e, 0x01, 0x0c, 0x40, "None" }, +}; + +STDDIPINFO(Skybase) + +static struct BurnDIPInfo SmooncrsDIPList[]= +{ + // Default Values + {0x08, 0xff, 0xff, 0x00, NULL }, + {0x09, 0xff, 0xff, 0xc0, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x08, 0x01, 0x20, 0x00, "Upright" }, + {0x08, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x09, 0x01, 0x40, 0x40, "Easy" }, + {0x09, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Players Bullet Speed" }, + {0x09, 0x01, 0x80, 0x00, "Slow" }, + {0x09, 0x01, 0x80, 0x80, "Fast" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x03, 0x03, "4 Coins 1 Play" }, + {0x10, 0x01, 0x03, 0x02, "3 Coins 1 Play" }, + {0x10, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x10, 0x01, 0x03, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0x0c, 0x00, "1 Coin 1 Play" }, + {0x10, 0x01, 0x0c, 0x04, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x0c, 0x08, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x0c, 0x0c, "Freeplay" }, +}; + +STDDIPINFO(Smooncrs) + +static struct BurnDIPInfo SpacbattDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "A 2C/1P B 1C/3P" }, + {0x0d, 0x01, 0xc0, 0x00, "A 1C/1P B 1C/6P" }, + {0x0d, 0x01, 0xc0, 0x80, "A 1C/2P B 1C/6P" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x01, "4000" }, + {0x0e, 0x01, 0x03, 0x02, "5000" }, + {0x0e, 0x01, 0x03, 0x03, "7000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, +}; + +STDDIPINFO(Spacbatt) + +static struct BurnDIPInfo SpdcoinDIPList[]= +{ + // Default Values + {0x07, 0xff, 0xff, 0x00, NULL }, + {0x08, 0xff, 0xff, 0x03, NULL }, + {0x09, 0xff, 0xff, 0x06, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x08, 0x01, 0x01, 0x01, "Off" }, + {0x08, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x08, 0x01, 0x02, 0x02, "Off" }, + {0x08, 0x01, 0x02, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x09, 0x01, 0x04, 0x04, "Easy" }, + {0x09, 0x01, 0x04, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x09, 0x01, 0x08, 0x00, "3" }, + {0x09, 0x01, 0x08, 0x08, "5" }, +}; + +STDDIPINFO(Spdcoin) + +static struct BurnDIPInfo StratgyxDIPList[] = +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x08, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Stratgyx) + +static struct BurnDIPInfo StreakngDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x40, NULL }, + {0x0e, 0xff, 0xff, 0x06, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0d, 0x01, 0xc0, 0x40, "10000" }, + {0x0d, 0x01, 0xc0, 0x81, "15000" }, + {0x0d, 0x01, 0xc0, 0xc0, "20000" }, + {0x0d, 0x01, 0xc0, 0x00, "None" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x00, "2 Coins 1 Play" }, + {0x0e, 0x01, 0x03, 0x02, "1 Coin 1 Play" }, + {0x0e, 0x01, 0x03, 0x01, "1 Coin 2 Plays" }, + {0x0e, 0x01, 0x03, 0x03, "Freeplay" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x0c, "1" }, + {0x0e, 0x01, 0x0c, 0x08, "2" }, + {0x0e, 0x01, 0x0c, 0x04, "3" }, + {0x0e, 0x01, 0x0c, 0x00, "5" }, +}; + +STDDIPINFO(Streakng) + +static struct BurnDIPInfo StrfbombDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x03, NULL }, + {0x14, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "255" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x14, 0x01, 0x06, 0x06, "A 1C/2P B 4C/1P C 1C/2P"}, + {0x14, 0x01, 0x06, 0x04, "A 1C/3P B 2C/1P C 1C/3P"}, + {0x14, 0x01, 0x06, 0x02, "A 1C/4P B 3C/1P C 1C/4P"}, + {0x14, 0x01, 0x06, 0x00, "A 1C/5P B 1C/1P C 1C/5P"}, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Strfbomb) + +static struct BurnDIPInfo SuperbonDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x00, NULL }, + {0x0c, 0xff, 0xff, 0x02, NULL }, + {0x0d, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x03, 0x02, "3" }, + {0x0c, 0x01, 0x03, 0x01, "5" }, + {0x0c, 0x01, 0x03, 0x00, "Free Play" }, + {0x0c, 0x01, 0x03, 0x03, "Invulnerability" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x06, 0x04, "1 Coin 1 Play" }, + {0x0d, 0x01, 0x06, 0x06, "A 1C/2P B 2C/1P" }, + {0x0d, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P" }, + {0x0d, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P" }, +}; + +STDDIPINFO(Superbon) + +static struct BurnDIPInfo SupergDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x01, "4000" }, + {0x0e, 0x01, 0x03, 0x02, "5000" }, + {0x0e, 0x01, 0x03, 0x03, "7000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, +}; + +STDDIPINFO(Superg) + +static struct BurnDIPInfo SwarmDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x00, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0d, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x01, "10000" }, + {0x0e, 0x01, 0x03, 0x02, "20000" }, + {0x0e, 0x01, 0x03, 0x03, "40000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "4" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x08, 0x00, "Easy" }, + {0x0e, 0x01, 0x08, 0x08, "Hard" }, +}; + +STDDIPINFO(Swarm) + +static struct BurnDIPInfo TazzmangDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x04, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x06, 0x00, "A 4C/1P B 1C/4P" }, + {0x11, 0x01, 0x06, 0x02, "A 3C/1P B 1C/3P" }, + {0x11, 0x01, 0x06, 0x06, "A 2C/1P B 1C/2P" }, + {0x11, 0x01, 0x06, 0x04, "A 1C/1P B 1C/1P" }, +}; + +STDDIPINFO(Tazzmang) + +static struct BurnDIPInfo TheendDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x03, NULL }, + {0x10, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x03, "3" }, + {0x0f, 0x01, 0x03, 0x02, "4" }, + {0x0f, 0x01, 0x03, 0x01, "5" }, + {0x0f, 0x01, 0x03, 0x00, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x02, "3 Coins 1 Play" }, + {0x10, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x10, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x10, 0x01, 0x06, 0x00, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x08, 0x08, "Upright" }, + {0x10, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Theend) + +static struct BurnDIPInfo ThepitmDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0c, 0x01, 0x04, 0x00, "Off" }, + {0x0c, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x08, 0x00, "Upright" }, + {0x11, 0x01, 0x08, 0x08, "Cocktail" }, +}; + +STDDIPINFO(Thepitm) + +static struct BurnDIPInfo TriplepDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x03, NULL }, + {0x12, 0xff, 0xff, 0xae, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x01, "5" }, + {0x11, 0x01, 0x03, 0x00, "256" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x06, 0x04, "A 1C/2P B 1C/1P C 1C/2C"}, + {0x12, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P C 1C/3C"}, + {0x12, 0x01, 0x06, 0x06, "A 1C/1P B 2C/1P C 1C/1C"}, + {0x12, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P C 1C/4C"}, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x08, "Upright" }, + {0x12, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Rack Test" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Triplep) + +static struct BurnDIPInfo TurpinDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x03, NULL }, + {0x12, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x01, "7" }, + {0x11, 0x01, 0x03, 0x00, "126" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x06, 0x00, "4 Coins 1 Play" }, + {0x12, 0x01, 0x06, 0x04, "2 Coins 1 Play" }, + {0x12, 0x01, 0x06, 0x06, "1 Coin 1 Play" }, + {0x12, 0x01, 0x06, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x08, "Upright" }, + {0x12, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Turpin) + +static struct BurnDIPInfo TurtlesDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x03, NULL }, + {0x12, 0xff, 0xff, 0x0e, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x01, "5" }, + {0x11, 0x01, 0x03, 0x00, "126" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x12, 0x01, 0x06, 0x06, "A 1C/1P B 2C/1P C 1C/1P"}, + {0x12, 0x01, 0x06, 0x04, "A 1C/2P B 1C/1P C 1C/2P"}, + {0x12, 0x01, 0x06, 0x02, "A 1C/3P B 3C/1P C 1C/3P"}, + {0x12, 0x01, 0x06, 0x00, "A 1C/4P B 4C/1P C 1C/4P"}, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x08, "Upright" }, + {0x12, 0x01, 0x08, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Turtles) + +static struct BurnDIPInfo VpoolDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x20, NULL }, + {0x0d, 0xff, 0xff, 0xe0, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + + // Dip 3 +}; + +STDDIPINFO(Vpool) + +static struct BurnDIPInfo WarofbugDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x0a, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x20, 0x00, "Upright" }, + {0x0f, 0x01, 0x20, 0x20, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 3 , "Coinage" }, + {0x10, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x10, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x10, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "1" }, + {0x11, 0x01, 0x03, 0x01, "2" }, + {0x11, 0x01, 0x03, 0x02, "3" }, + {0x11, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x08, 0x08, "500000" }, + {0x11, 0x01, 0x08, 0x00, "700000" }, +}; + +STDDIPINFO(Warofbug) + +static struct BurnDIPInfo ZerotimeDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x00, NULL }, + {0x0d, 0xff, 0xff, 0x40, NULL }, + {0x0e, 0xff, 0xff, 0x03, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x20, 0x00, "Upright" }, + {0x0c, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0x40, "A 1C/1P 2C/3P B 1C/2P" }, + {0x0d, 0x01, 0xc0, 0xc0, "A 1C/1P 2C/3P B 1C/3P" }, + {0x0d, 0x01, 0xc0, 0x00, "A 1C/2P 2C/4P B 1C/4P" }, + {0x0d, 0x01, 0xc0, 0x80, "A 1C/2P 2C/5P B 1C/5P" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x03, 0x03, "6000" }, + {0x0e, 0x01, 0x03, 0x02, "7000" }, + {0x0e, 0x01, 0x03, 0x01, "9000" }, + {0x0e, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0e, 0x01, 0x04, 0x00, "3" }, + {0x0e, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x08, 0x00, "Easy" }, + {0x0e, 0x01, 0x08, 0x08, "Hard" }, +}; + +STDDIPINFO(Zerotime) + +static struct BurnDIPInfo ZigzagDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0x00, NULL }, + {0x10, 0xff, 0xff, 0x02, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x0f, 0x01, 0xc0, 0xc0, "Freeplay" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x01, 0x00, "3" }, + {0x10, 0x01, 0x01, 0x01, "4" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x02, 0x02, "Upright" }, + {0x10, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x0c, 0x00, "10000 60000" }, + {0x10, 0x01, 0x0c, 0x04, "20000 60000" }, + {0x10, 0x01, 0x0c, 0x08, "30000 60000" }, + {0x10, 0x01, 0x0c, 0x0c, "40000 60000" }, +}; + +STDDIPINFO(Zigzag) + +// Drivers +// Basic Galaxian Hardware +static struct BurnRomInfo GalaxianRomDesc[] = { + { "galmidw.u", 0x00800, 0x745e2d61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.v", 0x00800, 0x9c999a40, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.w", 0x00800, 0xb5894925, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.y", 0x00800, 0x6b3ca10b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l", 0x00800, 0x1b933207, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h.bin", 0x00800, 0x39fb43a4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k.bin", 0x00800, 0x7e3f56a2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxian) +STD_ROM_FN(Galaxian) + +static struct BurnRomInfo GalaxianaRomDesc[] = { + { "7f.bin", 0x01000, 0x4335b1de, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7j.bin", 0x01000, 0x4e6f66a1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l.bin", 0x00800, 0x5341d75a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h.bin", 0x00800, 0x39fb43a4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k.bin", 0x00800, 0x7e3f56a2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxiana) +STD_ROM_FN(Galaxiana) + +static struct BurnRomInfo GalaxianmRomDesc[] = { + { "galmidw.u", 0x00800, 0x745e2d61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.v", 0x00800, 0x9c999a40, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.w", 0x00800, 0xb5894925, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.y", 0x00800, 0x6b3ca10b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.z", 0x00800, 0xcb24f797, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galaxian.j1", 0x00800, 0x84decf98, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galaxian.l1", 0x00800, 0xc31ada9e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxianm) +STD_ROM_FN(Galaxianm) + +static struct BurnRomInfo GalaxianmoRomDesc[] = { + { "galaxian.u", 0x00800, 0xfac42d34, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galaxian.v", 0x00800, 0xf58283e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galaxian.w", 0x00800, 0x4c7031c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galaxian.y", 0x00800, 0x96a7ac94, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l.bin", 0x00800, 0x5341d75a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galaxian.j1", 0x00800, 0x84decf98, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galaxian.l1", 0x00800, 0xc31ada9e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxianmo) +STD_ROM_FN(Galaxianmo) + +static struct BurnRomInfo GalaxiantRomDesc[] = { + { "gl-03.8g", 0x00800, 0xe8f3aa67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "gl-04.8f", 0x00800, 0xf58283e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "gl-05.8e", 0x00800, 0x4c7031c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "gl-06.8d", 0x00800, 0x097d92a2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "gl-07.8c", 0x00800, 0x5341d75a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "gl-01.1j", 0x00800, 0x968b6016, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "gl-02.1k", 0x00800, 0xd14f7510, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxiant) +STD_ROM_FN(Galaxiant) + +struct BurnDriver BurnDrvGalaxian = { + "galaxian", NULL, NULL, NULL, "1979", + "Galaxian (Namco set 1)\0", NULL, "Namco", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxianRomInfo, GalaxianRomName, NULL, NULL, GalaxianInputInfo, GalaxianDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalaxiana = { + "galaxiana", "galaxian", NULL, NULL, "1979", + "Galaxian (Namco set 2)\0", NULL, "Namco", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxianaRomInfo, GalaxianaRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalaxianm = { + "galaxianm", "galaxian", NULL, NULL, "1979", + "Galaxian (Midway set 1)\0", NULL, "Namco (Midway license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxianmRomInfo, GalaxianmRomName, NULL, NULL, GalaxianInputInfo, GalaxianDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalaxianmo = { + "galaxianmo", "galaxian", NULL, NULL, "1979", + "Galaxian (Midway set 2)\0", NULL, "Namco (Midway license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxianmoRomInfo, GalaxianmoRomName, NULL, NULL, GalaxianInputInfo, GalaxianDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalaxiant = { + "galaxiant", "galaxian", NULL, NULL, "1979", + "Galaxian (Taito)\0", NULL, "Namco (Taito license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxiantRomInfo, GalaxiantRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Galaxian Rip-Offs on basic Galaxian Hardware +static struct BurnRomInfo MoonalnRomDesc[] = { + { "galx.u", 0x00800, 0x79e4007d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg2.bin", 0x00800, 0x59580b30, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg3.bin", 0x00800, 0xb64e9d12, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "superg.y", 0x00800, 0x9463f753, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg5.bin", 0x00800, 0x8bb78987, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ca1.bin", 0x00800, 0x074271dd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ca2.bin", 0x00800, 0x84d90397, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonaln) +STD_ROM_FN(Moonaln) + +static struct BurnRomInfo SupergRomDesc[] = { + { "7f.bin", 0x01000, 0x4335b1de, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "superg.w", 0x00800, 0xddeabdae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "superg.y", 0x00800, 0x9463f753, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "superg.z", 0x00800, 0xe6312e35, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galmidw.1j", 0x00800, 0x84decf98, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galmidw.1k", 0x00800, 0xc31ada9e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Superg) +STD_ROM_FN(Superg) + +static struct BurnRomInfo GalturboRomDesc[] = { + { "galturbo.u", 0x00800, 0xe8f3aa67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx.v", 0x00800, 0xbc16064e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "superg.w", 0x00800, 0xddeabdae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galturbo.y", 0x00800, 0xa44f450f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galturbo.z", 0x00800, 0x3247f3d4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galturbo.1h", 0x00800, 0xa713fd1a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galturbo.1k", 0x00800, 0x28511790, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galturbo) +STD_ROM_FN(Galturbo) + +static struct BurnRomInfo GalapxRomDesc[] = { + { "galx.u", 0x00800, 0x79e4007d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx.v", 0x00800, 0xbc16064e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx.w", 0x00800, 0x72d2d3ee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx.y", 0x00800, 0xafe397f3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx.z", 0x00800, 0x778c0d3c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galx.1h", 0x00800, 0xe8810654, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galx.1k", 0x00800, 0xcbe84a76, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galapx) +STD_ROM_FN(Galapx) + +static struct BurnRomInfo Galap1RomDesc[] = { + { "7f.bin", 0x01000, 0x4335b1de, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galaxian.w", 0x00800, 0x4c7031c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx_1_4.rom", 0x00800, 0xe71e1d9e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galx_1_5.rom", 0x00800, 0x6e65a3b2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galmidw.1j", 0x00800, 0x84decf98, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galmidw.1k", 0x00800, 0xc31ada9e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galap1) +STD_ROM_FN(Galap1) + +static struct BurnRomInfo Galap4RomDesc[] = { + { "galnamco.u", 0x00800, 0xacfde501, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galnamco.v", 0x00800, 0x65cf3c77, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galnamco.w", 0x00800, 0x9eef9ae6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galnamco.y", 0x00800, 0x56a5ddd1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galnamco.z", 0x00800, 0xf4bc7262, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "galx_4c1.rom", 0x00800, 0xd5e88ab4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "galx_4c2.rom", 0x00800, 0xa57b83e4, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galap4) +STD_ROM_FN(Galap4) + +static struct BurnRomInfo SwarmRomDesc[] = { + { "swarm1.bin", 0x00800, 0x21eba3d0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "swarm2.bin", 0x00800, 0xf3a436cd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "swarm3.bin", 0x00800, 0x2915e38b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "swarm4.bin", 0x00800, 0x8bbbf486, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "swarm5.bin", 0x00800, 0xf1b1987e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "swarma.bin", 0x00800, 0xef8657bb, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "swarmb.bin", 0x00800, 0x60c4bd31, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Swarm) +STD_ROM_FN(Swarm) + +static struct BurnRomInfo ZerotimeRomDesc[] = { + { "zt-p01c.016", 0x00800, 0x90a2bc61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zt-2.016", 0x00800, 0xa433067e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zt-3.016", 0x00800, 0xaaf038d4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zt-4.016", 0x00800, 0x786d690a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zt-5.016", 0x00800, 0xaf9260d7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ztc-2.016", 0x00800, 0x1b13ca05, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ztc-1.016", 0x00800, 0x5cd7df03, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Zerotime) +STD_ROM_FN(Zerotime) + +static struct BurnRomInfo StarfghtRomDesc[] = { + { "ja.1", 0x00400, 0xc6ab558b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb.2", 0x00400, 0x34b99fed, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jc.3", 0x00400, 0x30e28016, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jd.4", 0x00400, 0xde7e7770, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "je.5", 0x00400, 0xa916c919, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jf.6", 0x00400, 0x9175882b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jg.7", 0x00400, 0x707c0f02, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jh.8", 0x00400, 0x5dd26461, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ji.9", 0x00400, 0x6651fe93, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jj.10", 0x00400, 0x12c721b9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "k1.7a", 0x00800, 0x977e37cf, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k2.9a", 0x00800, 0x15e387ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.7f", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Starfght) +STD_ROM_FN(Starfght) + +static struct BurnRomInfo GalaxbsfRomDesc[] = { + { "1.bn", 0x00400, 0xcc37b774, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.bn", 0x00400, 0xc6d21f03, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.bn", 0x00400, 0x30e28016, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.bn", 0x00400, 0xde7e7770, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.bn", 0x00400, 0xa916c919, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.bn", 0x00400, 0x9175882b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7.bn", 0x00400, 0x1237b9da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.bn", 0x00400, 0x78c53607, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "9.bn", 0x00400, 0x901894cc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "10.bn", 0x00400, 0x5876f695, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "11.bn", 0x00800, 0x39fb43a4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "12.bn", 0x00800, 0x7e3f56a2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Galaxbsf) +STD_ROM_FN(Galaxbsf) + +static struct BurnRomInfo Kamakazi3RomDesc[] = { + { "f_r_a.bin", 0x00800, 0xe8f3aa67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f_a.bin", 0x00800, 0xf58283e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f_b.bin", 0x00800, 0xddeabdae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f_r_c.bin", 0x00800, 0xc8530a88, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f_r_d.bin", 0x00800, 0xda2d77e0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "r_b.bin", 0x00800, 0x977e37cf, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "r_a.bin", 0x00800, 0xd0ba22c9, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Kamakazi3) +STD_ROM_FN(Kamakazi3) + +static struct BurnRomInfo SupergxRomDesc[] = { + { "sg1", 0x00800, 0xb83f4578, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sg2", 0x00800, 0xd12ca054, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sg3", 0x00800, 0x53714cb1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sg4", 0x00800, 0x2f36fc69, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sg5", 0x00800, 0x1e0ed4fd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sg6", 0x00800, 0x4f3d97a8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sgg1", 0x00800, 0xa1287bf6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sgg2", 0x00800, 0x528f1481, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "supergx.prm", 0x00020, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Supergx) +STD_ROM_FN(Supergx) + +static struct BurnRomInfo TstgalxRomDesc[] = { + { "test.u", 0x00800, 0x0614cd7f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.v", 0x00800, 0x9c999a40, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.w", 0x00800, 0xb5894925, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "galmidw.y", 0x00800, 0x6b3ca10b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l", 0x00800, 0x1b933207, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h.bin", 0x00800, 0x39fb43a4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k.bin", 0x00800, 0x7e3f56a2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Tstgalx) +STD_ROM_FN(Tstgalx) + +static INT32 SupergxInit() +{ + INT32 nRet; + + GalTilesSharedRomSize = 0x1000; + GalPromRomSize = 0x20; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + HardCodeGalaxianPROM(); + + return nRet; +} + +struct BurnDriver BurnDrvMoonaln = { + "moonaln", "galaxian", NULL, NULL, "1979", + "Moon Alien\0", NULL, "Nichibutsu (Karateco license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MoonalnRomInfo, MoonalnRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSuperg = { + "superg", "galaxian", NULL, NULL, "1979", + "Super Galaxians (galaxiaj hack)\0", NULL, "hack", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SupergRomInfo, SupergRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalturbo = { + "galturbo", "galaxian", NULL, NULL, "1979", + "Galaxian Turbo (superg hack)\0", NULL, "hack", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalturboRomInfo, GalturboRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalapx = { + "galapx", "galaxian", NULL, NULL, "1979", + "Galaxian Part X (moonaln hack)\0", NULL, "hack", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalapxRomInfo, GalapxRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalap1 = { + "galap1", "galaxian", NULL, NULL, "1979", + "Space Invaders Galactica (galaxiaj hack)\0", NULL, "hack", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Galap1RomInfo, Galap1RomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalap4 = { + "galap4", "galaxian", NULL, NULL, "1979", + "Galaxian Part 4 (hack)\0", NULL, "G.G.I", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Galap4RomInfo, Galap4RomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSwarm = { + "swarm", "galaxian", NULL, NULL, "1979", + "Swarm (bootleg?)\0", NULL, "Sebelectro", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SwarmRomInfo, SwarmRomName, NULL, NULL, GalaxianInputInfo, SwarmDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvZerotime = { + "zerotime", "galaxian", NULL, NULL, "1979", + "Zero Time\0", NULL, "Petaco S.A", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, ZerotimeRomInfo, ZerotimeRomName, NULL, NULL, GalaxianInputInfo, ZerotimeDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvStarfght = { + "starfght", "galaxian", NULL, NULL, "1979", + "Star Fighter\0", NULL, "Juetel", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, StarfghtRomInfo, StarfghtRomName, NULL, NULL, GalaxianInputInfo, SwarmDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGalaxbsf = { + "galaxbsf", "galaxian", NULL, NULL, "1979", + "Galaxian (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GalaxbsfRomInfo, GalaxbsfRomName, NULL, NULL, GalaxianInputInfo, GalaxianDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvKamakazi3 = { + "kamakazi3", "galaxian", NULL, NULL, "1979", + "Kamakazi III (superg hack)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Kamakazi3RomInfo, Kamakazi3RomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvSupergx = { + "supergx", "galaxian", NULL, NULL, "1980", + "Super GX\0", "Bad Dump", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SupergxRomInfo, SupergxRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + SupergxInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTstgalx = { + "tst_galx", "galaxian", NULL, NULL, "1979", + "Galaxian Test ROM\0", NULL, "Test ROM", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_PROTOTYPE, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, TstgalxRomInfo, TstgalxRomName, NULL, NULL, GalaxianInputInfo, GalaxianDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Other games on basic Galaxian hardware +static struct BurnRomInfo BlkholeRomDesc[] = { + { "bh1", 0x00800, 0x64998819, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bh2", 0x00800, 0x26f26ce4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bh3", 0x00800, 0x3418bc45, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bh4", 0x00800, 0x735ff481, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bh5", 0x00800, 0x3f657be9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bh6", 0x00800, 0xa057ab35, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "bh7", 0x00800, 0x975ba821, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "bh8", 0x00800, 0x03d11020, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Blkhole) +STD_ROM_FN(Blkhole) + +static struct BurnRomInfo OrbitronRomDesc[] = { + { "orbitron.3", 0x00800, 0x419f9c9b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "orbitron.4", 0x00800, 0x44ad56ac, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "orbitron.1", 0x00800, 0xda3f5168, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "orbitron.2", 0x00800, 0xa3b813fc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "orbitron.5", 0x00800, 0x20cd8bb8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "orbitron.6", 0x00800, 0x2c91b83f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "orbitron.7", 0x00800, 0x46f4cca4, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Orbitron) +STD_ROM_FN(Orbitron) + +static struct BurnRomInfo LuctodayRomDesc[] = { + { "ltprog1.bin", 0x00800, 0x59c389b9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ltprog2.bin", 0x00800, 0xac3893b1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ltchar2.bin", 0x00800, 0x8cd73bdc, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ltchar1.bin", 0x00800, 0xb5ba9946, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "74s288.ch", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Luctoday) +STD_ROM_FN(Luctoday) + +static struct BurnRomInfo ChewingRomDesc[] = { + { "1.bin", 0x01000, 0x7470b347, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l.bin", 0x00800, 0x78ebed36, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "2.bin", 0x00800, 0x88c605f3, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "3.bin", 0x00800, 0x77ac016a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "74s288.ch", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Chewing) +STD_ROM_FN(Chewing) + +static struct BurnRomInfo CatacombRomDesc[] = { + { "catacomb.u", 0x00800, 0x35cc28d2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "catacomb.v", 0x00800, 0x1d1ce133, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "catacomb.w", 0x00800, 0x479bbde7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "catacomb.y", 0x00800, 0x5e3da534, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "cat-gfx1", 0x00800, 0xe871e65c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "cat-gfx2", 0x00800, 0xb14dafaa, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Catacomb) +STD_ROM_FN(Catacomb) + +static struct BurnRomInfo OmegaRomDesc[] = { + { "omega1.bin", 0x00800, 0xfc2a096b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omega2.bin", 0x00800, 0xad100357, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omega3.bin", 0x00800, 0xd7e3be79, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omega4.bin", 0x00800, 0x42068171, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omega5.bin", 0x00800, 0xd8a93383, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omega6.bin", 0x00800, 0x32a42f44, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "omega1h.bin", 0x00800, 0x527fd384, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "omega1k.bin", 0x00800, 0x36de42c6, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331-1j.86", 0x00020, 0x6a0c7d87, BRF_OPT | BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Omega) +STD_ROM_FN(Omega) + +static struct BurnRomInfo WarofbugRomDesc[] = { + { "warofbug.u", 0x00800, 0xb8dfb7e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "warofbug.v", 0x00800, 0xfd8854e0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "warofbug.w", 0x00800, 0x4495aa14, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "warofbug.y", 0x00800, 0xc14a541f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "warofbug.z", 0x00800, 0xc167fe55, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "warofbug.1k", 0x00800, 0x8100fa85, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "warofbug.1j", 0x00800, 0xd1220ae9, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "warofbug.clr", 0x00020, 0x8688e64b, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Warofbug) +STD_ROM_FN(Warofbug) + +static struct BurnRomInfo WarofbuggRomDesc[] = { + { "wotbg-u-1.bin", 0x00800, 0xf43ff0a8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "wotbg-v-2.bin", 0x00800, 0xeb7a028b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "wotbg-w-3.bin", 0x00800, 0x693e0e50, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "wotbg-y-4.bin", 0x00800, 0x885d4982, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "wotbg-z-5.bin", 0x00800, 0x60041ef2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "warofbug.1k", 0x00800, 0x8100fa85, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "warofbug.1j", 0x00800, 0xd1220ae9, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "warofbug.clr", 0x00020, 0x8688e64b, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Warofbugg) +STD_ROM_FN(Warofbugg) + +static struct BurnRomInfo RedufoRomDesc[] = { + { "redufo.1", 0x00800, 0x6a3b873c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.2", 0x00800, 0x202eda3b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.3", 0x00800, 0xbf7030e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.4", 0x00800, 0x8c1c2ef9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.5", 0x00800, 0xef965b24, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.6", 0x00800, 0x58b3e39b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "redufo.7", 0x00800, 0xfd07d811, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "redufo.8", 0x00800, 0xb34c7cb4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "redufo.9", 0x00800, 0x50a2d447, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "tbp18s030n.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Redufo) +STD_ROM_FN(Redufo) + +static struct BurnRomInfo RedufobRomDesc[] = { + { "ru1a", 0x00800, 0x5a8e4f37, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ru2a", 0x00800, 0xc624f52d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ru3a", 0x00800, 0xe1030d1c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ru4a", 0x00800, 0x7692069e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ru5a", 0x00800, 0xcb648ff3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ru6a", 0x00800, 0xe1a9f58e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ruhja", 0x00800, 0x8a422b0d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rukla", 0x00800, 0x1eb84cb1, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Redufob) +STD_ROM_FN(Redufob) + +static struct BurnRomInfo ExodusRomDesc[] = { + { "exodus1.bin", 0x00800, 0x5dfe65e1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus2.bin", 0x00800, 0x6559222f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus3.bin", 0x00800, 0xbf7030e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus4.bin", 0x00800, 0x3607909e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus9.bin", 0x00800, 0x994a90c4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus10.bin", 0x00800, 0xfbd11187, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "exodus11.bin", 0x00800, 0xfd07d811, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "exodus5.bin", 0x00800, 0xb34c7cb4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "exodus6.bin", 0x00800, 0x50a2d447, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Exodus) +STD_ROM_FN(Exodus) + +static struct BurnRomInfo TdpgalRomDesc[] = { + { "1.bin", 0x00800, 0x7be819fe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.bin", 0x00800, 0x70c83a5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.bin", 0x00800, 0x475eb5a0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.bin", 0x00800, 0x20a71943, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.bin", 0x00800, 0x72c4f2dc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.bin", 0x00800, 0xfa4e2be4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "8.bin", 0x00800, 0xd701b1d4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "7.bin", 0x00800, 0x3113bcfd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "bprom.bin", 0x00020, 0x2b4cf53f, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Tdpgal) +STD_ROM_FN(Tdpgal) + +static struct BurnRomInfo AzurianRomDesc[] = { + { "pgm.1", 0x01000, 0x17a0fca7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pgm.2", 0x01000, 0x14659848, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pgm.3", 0x01000, 0x8f60fb97, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "gfx.1", 0x00800, 0xf5afb803, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "gfx.2", 0x00800, 0xae96e5d1, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Azurian) +STD_ROM_FN(Azurian) + +static struct BurnRomInfo TazzmangRomDesc[] = { + { "tazzm1.4k", 0x01000, 0xa14480a1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tazzm2.5j", 0x01000, 0x5609f5db, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tazzm3.6f", 0x01000, 0xfe7f7002, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tazzm4.7e", 0x01000, 0xc9ca1d0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tazzm5.7l", 0x01000, 0xf50cd8a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tazzm6.7l", 0x01000, 0x5cf2e7d2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "tazm8.1lk", 0x00800, 0x2c5b612b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tazzm7.1jh", 0x00800, 0x3f5ff3ac, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Tazzmang) +STD_ROM_FN(Tazzmang) + +static struct BurnRomInfo ScramblbRomDesc[] = { + { "scramble.1k", 0x00800, 0x9e025c4a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.2k", 0x00800, 0x306f783e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.3k", 0x00800, 0x0500b701, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.4k", 0x00800, 0xdd380a22, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.5k", 0x00800, 0xdf0b9648, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.1j", 0x00800, 0xb8c07b3c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.2j", 0x00800, 0x88ac07a0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scramble.3j", 0x00800, 0xc67d57ca, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5f.k", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h.k", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scramblb) +STD_ROM_FN(Scramblb) + +static struct BurnRomInfo Scramb2RomDesc[] = { + { "r1.7f1", 0x00800, 0x4a43148c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r1.7f2", 0x00800, 0x215a3b86, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r2.7h1", 0x00800, 0x28779444, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r2.7h2", 0x00800, 0x5b4b300b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r3.7k1", 0x00800, 0xb478aa53, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r3.7k2", 0x00800, 0xc33f072e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r4.7l1", 0x00800, 0x88ac07a0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "r4.7l2", 0x00800, 0x321fd003, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "r6.1j", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "r5.1l", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scramb2) +STD_ROM_FN(Scramb2) + +UINT8 __fastcall AzurianZ80Read(UINT16 a) +{ + switch (a) { + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return ((GalInput[1] | GalDip[1]) & ~0x40) | ((GalFakeDip & 0x01) << 6); + } + + case 0x7000: { + return ((GalInput[2] | GalDip[2]) & ~0x04) | ((GalFakeDip & 0x02) << 1); + } + + case 0x7800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +UINT8 __fastcall TazzmangZ80Read(UINT16 a) +{ + switch (a) { + case 0x9800: + case 0xb800: { + // watchdog read + return 0xff; + } + + case 0xa000: + case 0xa7ff: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall TazzmangZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x8800 && a <= 0x88ff) { + INT32 Offset = a - 0x8800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall ScramblbZ80Read(UINT16 a) +{ + switch (a) { + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: { + return GalInput[2] | GalDip[2]; + } + + case 0x7800: { + // watchdog read + return 0xff; + } + + case 0x8102: { + switch (ZetPc(-1)) { + case 0x1da: return 0x80; + case 0x1e4: return 0x00; + } + return 0xff; + } + + case 0x8202: { + switch (ZetPc(-1)) { + case 0x1ca: return 0x90; + } + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall ScramblbZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + // coin_lock_w + return; + } + + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + GalaxianLfoFreqWrite(a - 0x6004, d); + return; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + GalaxianSoundWrite(a - 0x6800, d); + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7002: { + // coin_count_0_w + return; + } + + case 0x7003: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Scramb2Z80Read(UINT16 a) +{ + if (a >= 0x5800 && a <= 0x5fff) return 0x25; + + switch (a) { + case 0x6000: + case 0x6001: + case 0x6002: + case 0x6003: + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + int Offset = a - 0x6000; + return ((0xff - GalInput[0] - GalDip[0]) >> Offset) & 0x01; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + int Offset = a - 0x6800; + return ((0xff - GalInput[1] - GalDip[1]) >> Offset) & 0x01; + } + + case 0x7000: { + // watchdog read + return 0xff; + } + + case 0x7800: + case 0x7801: + case 0x7802: + case 0x7803: + case 0x7804: + case 0x7805: + case 0x7806: + case 0x7807: { + INT32 Offset = a - 0x7800; + return ((0xff - GalInput[2] - GalDip[2]) >> Offset) & 0x01; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Scramb2Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: + case 0x6002: + case 0x6003: + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: + case 0x7000: + case 0x7001: + case 0x7002: + case 0x7003: + case 0x7004: + case 0x7005: + case 0x7006: + case 0x7007: { + // Probably PPI writes that the bootleggers didn't use + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_count_0_w + return; + } + + case 0x6803: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x6804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void OrbitronRearrangeRom() +{ + GalTempRom = (UINT8*)malloc(0x2000); + + memcpy(GalTempRom, GalZ80Rom1, 0x2000); + memcpy(GalZ80Rom1 + 0x0600, GalTempRom + 0x0000, 0x200); + memcpy(GalZ80Rom1 + 0x0400, GalTempRom + 0x0200, 0x200); + memcpy(GalZ80Rom1 + 0x0200, GalTempRom + 0x0400, 0x200); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0600, 0x200); + memcpy(GalZ80Rom1 + 0x0e00, GalTempRom + 0x0800, 0x200); + memcpy(GalZ80Rom1 + 0x0c00, GalTempRom + 0x0a00, 0x200); + memcpy(GalZ80Rom1 + 0x0a00, GalTempRom + 0x0c00, 0x200); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x0e00, 0x200); + memcpy(GalZ80Rom1 + 0x1600, GalTempRom + 0x1000, 0x200); + memcpy(GalZ80Rom1 + 0x1400, GalTempRom + 0x1200, 0x200); + memcpy(GalZ80Rom1 + 0x1200, GalTempRom + 0x1400, 0x200); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x1600, 0x200); + memcpy(GalZ80Rom1 + 0x1e00, GalTempRom + 0x1800, 0x200); + memcpy(GalZ80Rom1 + 0x1c00, GalTempRom + 0x1a00, 0x200); + memcpy(GalZ80Rom1 + 0x1a00, GalTempRom + 0x1c00, 0x200); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x1e00, 0x200); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } +} + +static INT32 OrbitronInit() +{ + GalPostLoadCallbackFunction = OrbitronRearrangeRom; + + return GalInit(); +} + +static void LuctodayRearrangeRom() +{ + memcpy(GalZ80Rom1 + 0x2000, GalZ80Rom1 + 0x0800, 0x800); + memset(GalZ80Rom1 + 0x0800, 0, 0x800); +} + +static INT32 LuctodayInit() +{ + GalZ80Rom1Size = 0x1800; + GalPostLoadCallbackFunction = LuctodayRearrangeRom; + + return GalInit(); +} + +static void ChewingRearrangeRom() +{ + memcpy(GalZ80Rom1 + 0x2000, GalZ80Rom1 + 0x1000, 0x800); + memset(GalZ80Rom1 + 0x1000, 0, 0x800); +} + +static INT32 ChewingInit() +{ + GalZ80Rom1Size = 0x1000; + GalPostLoadCallbackFunction = ChewingRearrangeRom; + + return GalInit(); +} + +static void CatacombRearrangeRom() +{ + memcpy(GalZ80Rom1 + 0x2000, GalZ80Rom1 + 0x1800, 0x800); + memset(GalZ80Rom1 + 0x1800, 0, 0x800); +} + +static INT32 CatacombInit() +{ + GalZ80Rom1Size = 0x800; + GalPostLoadCallbackFunction = CatacombRearrangeRom; + + return GalInit(); +} + +static void TdpgalPostLoad() +{ + ZetOpen(0); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetClose(); +} + +static INT32 TdpgalInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = TdpgalPostLoad; + + nRet = GalInit(); + + return nRet; +} + +static void AzurianPostLoad() +{ + ZetOpen(0); + ZetSetReadHandler(AzurianZ80Read); + ZetClose(); +} + +static INT32 AzurianInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = AzurianPostLoad; + + nRet = GalInit(); + + GalDrawBulletsFunction = ScrambleDrawBullets; + + return nRet; +} + +static void TazzmangPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(TazzmangZ80Read); + ZetSetWriteHandler(TazzmangZ80Write); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0x8800, 0x88ff, 0, GalSpriteRam); + ZetMapArea(0x8800, 0x88ff, 2, GalSpriteRam); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetClose(); +} + +static INT32 TazzmangInit() +{ + GalPostLoadCallbackFunction = TazzmangPostLoad; + + return GalInit(); +} + +static void MapScramblb() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(ScramblbZ80Read); + ZetSetWriteHandler(ScramblbZ80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 0, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 1, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 ScramblbInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScramblb; + + nRet = GalInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + return nRet; +} + +static void Scramb2PostLoad() +{ + MapScramblb(); + + ZetOpen(0); + ZetSetReadHandler(Scramb2Z80Read); + ZetSetWriteHandler(Scramb2Z80Write); + ZetClose(); +} + +static INT32 Scramb2Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Scramb2PostLoad; + + nRet = GalInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + return nRet; +} + +struct BurnDriver BurnDrvBlkhole = { + "blkhole", NULL, NULL, NULL, "1981", + "Black Hole\0", NULL, "TDS", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, BlkholeRomInfo, BlkholeRomName, NULL, NULL, BlkholeInputInfo, BlkholeDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvOrbitron = { + "orbitron", NULL, NULL, NULL, "19??", + "Orbitron\0", NULL, "Signatron USA", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SHOOT, 0, + NULL, OrbitronRomInfo, OrbitronRomName, NULL, NULL, OrbitronInputInfo, OrbitronDIPInfo, + OrbitronInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLuctoday = { + "luctoday", NULL, NULL, NULL, "1980", + "Lucky Today\0", "Bad colours", "Sigma", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_GALAXIAN, GBF_CASINO, 0, + NULL, LuctodayRomInfo, LuctodayRomName, NULL, NULL, LuctodayInputInfo, LuctodayDIPInfo, + LuctodayInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvChewing = { + "chewing", "luctoday", NULL, NULL, "1980", + "Chewing Gum\0", NULL, "unknown", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_CASINO, 0, + NULL, ChewingRomInfo, ChewingRomName, NULL, NULL, LuctodayInputInfo, LuctodayDIPInfo, + ChewingInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCatacomb = { + "catacomb", NULL, NULL, NULL, "1982", + "Catacomb\0", "Bad Colours", "MTM Games", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, CatacombRomInfo, CatacombRomName, NULL, NULL, OmegaInputInfo, CatacombDIPInfo, + CatacombInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvOmega = { + "omega", "theend", NULL, NULL, "19??", + "Omega\0", NULL, "bootleg?", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, OmegaRomInfo, OmegaRomName, NULL, NULL, OmegaInputInfo, OmegaDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvWarofbug = { + "warofbug", NULL, NULL, NULL, "1981", + "War of the Bugs or Monsterous Manouvers in a Mushroom Maze\0", NULL, "Armenia", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, WarofbugRomInfo, WarofbugRomName, NULL, NULL, WarofbugInputInfo, WarofbugDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvWarofbugg = { + "warofbugg", "warofbug", NULL, NULL, "1981", + "War of the Bugs or Monsterous Manouvers in a Mushroom Maze (German)\0", NULL, "Armenia", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, WarofbuggRomInfo, WarofbuggRomName, NULL, NULL, WarofbugInputInfo, WarofbugDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRedufo = { + "redufo", NULL, NULL, NULL, "1981", + "Defend the Terra Attack on the Red UFO\0", NULL, "Artic", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, RedufoRomInfo, RedufoRomName, NULL, NULL, GalaxianInputInfo, RedufoDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRedufob = { + "redufob", "redufo", NULL, NULL, "1981", + "Defend the Terra Attack on the Red UFO (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, RedufobRomInfo, RedufobRomName, NULL, NULL, GalaxianInputInfo, RedufobDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvExodus = { + "exodus", "redufo", NULL, NULL, "19??", + "Exodus (bootleg?)\0", NULL, "Subelectro", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, ExodusRomInfo, ExodusRomName, NULL, NULL, OmegaInputInfo, ExodusDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTdpgal = { + "tdpgal", NULL, NULL, NULL, "1983", + "Triple Draw Poker\0", NULL, "Design Labs / Thomas Automatics", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_CASINO, 0, + NULL, TdpgalRomInfo, TdpgalRomName, NULL, NULL, TdpgalInputInfo, NULL, + TdpgalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAzurian = { + "azurian", NULL, NULL, NULL, "1982", + "Azurian Attack\0", NULL, "Rait Electronics Ltd", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SHOOT, 0, + NULL, AzurianRomInfo, AzurianRomName, NULL, NULL, AzurianInputInfo, AzurianDIPInfo, + AzurianInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTazzmang = { + "tazzmang", "tazmania", NULL, NULL, "1982", + "Tazz-Mania (Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TazzmangRomInfo, TazzmangRomName, NULL, NULL, TazzmangInputInfo, TazzmangDIPInfo, + TazzmangInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScramblb = { + "scramblb", "scramble", NULL, NULL, "1981", + "Scramble (bootleg on Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScramblbRomInfo, ScramblbRomName, NULL, NULL, ScramblbInputInfo, ScramblbDIPInfo, + ScramblbInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScramb2 = { + "scramb2", "scramble", NULL, NULL, "1981", + "Scramble (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, Scramb2RomInfo, Scramb2RomName, NULL, NULL, Scramb2InputInfo, Scramb2DIPInfo, + Scramb2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Extra chars controlled via bank at 0x6002 +static struct BurnRomInfo PiscesRomDesc[] = { + { "p1.bin", 0x00800, 0x40c5b0e4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p2.bin", 0x00800, 0x055f9762, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p3.bin", 0x00800, 0x3073dd04, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p4.bin", 0x00800, 0x44aaf525, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p5.bin", 0x00800, 0xfade512b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p6.bin", 0x00800, 0x5ab2822f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "g09.bin", 0x00800, 0x9503a23a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g11.bin", 0x00800, 0x0adfc3fe, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g10.bin", 0x00800, 0x3e61f849, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g12.bin", 0x00800, 0x7130e9eb, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colour.bin", 0x00020, 0x57a45057, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Pisces) +STD_ROM_FN(Pisces) + +static struct BurnRomInfo PiscesbRomDesc[] = { + { "pisces.a1", 0x00800, 0x856b8e1f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p2.bin", 0x00800, 0x055f9762, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pisces.b2", 0x00800, 0x5540f2e4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p4.bin", 0x00800, 0x44aaf525, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p5.bin", 0x00800, 0xfade512b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p6.bin", 0x00800, 0x5ab2822f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "g09.bin", 0x00800, 0x9503a23a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g11.bin", 0x00800, 0x0adfc3fe, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g10.bin", 0x00800, 0x3e61f849, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g12.bin", 0x00800, 0x7130e9eb, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colour.bin", 0x00020, 0x57a45057, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Piscesb) +STD_ROM_FN(Piscesb) + +static struct BurnRomInfo OmniRomDesc[] = { + { "omni1.7f", 0x01000, 0xa9b7acc6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omni2.7j", 0x01000, 0x6ade29b7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "omni3.7f", 0x01000, 0x9e37bb24, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "omni5b.l1", 0x00800, 0x9503a23a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "omni6c.j22", 0x00800, 0x0adfc3fe, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "omni4a.j1", 0x00800, 0x3e61f849, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "omni7d.l2", 0x00800, 0x7130e9eb, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colour.bin", 0x00020, 0x57a45057, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Omni) +STD_ROM_FN(Omni) + +static struct BurnRomInfo UniwarsRomDesc[] = { + { "f07_1a.bin", 0x00800, 0xd975af10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "h07_2a.bin", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "k07_3a.bin", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m07_4a.bin", 0x00800, 0xddc80bc5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "d08p_5a.bin", 0x00800, 0x62354351, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "gg6", 0x00800, 0x270a3f4d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m08p_7a.bin", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "n08p_8a.bin", 0x00800, 0x797d45c7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "egg10", 0x00800, 0x012941e0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h01_2.bin", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "egg9", 0x00800, 0xfc8b58fd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "uniwars.clr", 0x00020, 0x25c79518, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Uniwars) +STD_ROM_FN(Uniwars) + +static struct BurnRomInfo GteikokuRomDesc[] = { + { "f07_1a.bin", 0x00800, 0xd975af10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "h07_2a.bin", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "k07_3a.bin", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m07_4a.bin", 0x00800, 0xddc80bc5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "d08p_5a.bin", 0x00800, 0x62354351, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e08p_6a.bin", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m08p_7a.bin", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "n08p_8a.bin", 0x00800, 0x797d45c7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "h01_1.bin", 0x00800, 0x8313c959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h01_2.bin", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_1.bin", 0x00800, 0xc9d4537e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Gteikoku) +STD_ROM_FN(Gteikoku) + +static struct BurnRomInfo GteikokbRomDesc[] = { + { "1.bin", 0x00800, 0xbf00252f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.bin", 0x00800, 0xf712b7d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "k07_3a.bin", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.bin", 0x00800, 0x808a39a8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.bin", 0x00800, 0x36fe6e67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.bin", 0x00800, 0xc5ea67e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m08p_7a.bin", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.bin", 0x00800, 0x28df3229, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "h01_1.bin", 0x00800, 0x8313c959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h01_2.bin", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_1.bin", 0x00800, 0xc9d4537e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Gteikokb) +STD_ROM_FN(Gteikokb) + +static struct BurnRomInfo Gteikob2RomDesc[] = { + { "94gnog.bin", 0x00800, 0x67ec3235, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "92gnog.bin", 0x00800, 0x813c41f2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "k07_3a.bin", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "1gnog.bin", 0x00800, 0x49ff9658, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.bin", 0x00800, 0x36fe6e67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e08p_6a.bin", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m08p_7a.bin", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "98gnog.bin", 0x00800, 0xe9d4ad3c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "h01_1.bin", 0x00800, 0x8313c959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h01_2.bin", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_1.bin", 0x00800, 0xc9d4537e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Gteikob2) +STD_ROM_FN(Gteikob2) + +static struct BurnRomInfo SpacbattRomDesc[] = { + { "sb1", 0x00800, 0xd975af10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb2", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb3", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb4", 0x00800, 0x8229835c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb5", 0x00800, 0xf51ef930, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb6", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb7", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb8", 0x00800, 0xe59ff1ae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sb12", 0x00800, 0x8313c959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sb14", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sb11", 0x00800, 0xc9d4537e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sb13", 0x00800, 0x92454380, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spacbatt) +STD_ROM_FN(Spacbatt) + +static struct BurnRomInfo Spacbat2RomDesc[] = { + { "sb1", 0x00800, 0xd975af10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb2", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb.3", 0x00800, 0xc25ce4c1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb4", 0x00800, 0x8229835c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb5", 0x00800, 0xf51ef930, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb6", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb7", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sb8", 0x00800, 0xe59ff1ae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sb12", 0x00800, 0x8313c959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sb14", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sb11", 0x00800, 0xc9d4537e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spacbat2) +STD_ROM_FN(Spacbat2) + +static struct BurnRomInfo SpacemprRomDesc[] = { + { "uw01", 0x00800, 0x7c64fb92, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw02", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw03", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw04", 0x00800, 0x84885060, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw05", 0x00800, 0xe342371d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw06", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw07", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "uw08", 0x00800, 0xa237c394, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "uw10", 0x00800, 0xaf069cba, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "uw12", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "uw09", 0x00800, 0xff2c20d5, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "uw11", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spacempr) +STD_ROM_FN(Spacempr) + +static struct BurnRomInfo SkyraidrRomDesc[] = { + { "f07_1a.bin", 0x00800, 0xd975af10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "h07_2a.bin", 0x00800, 0xb2ed14c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "k07_3a.bin", 0x00800, 0x945f4160, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sr.04", 0x00800, 0x9f61d1f8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sr.05", 0x00800, 0x4352af0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sr.06", 0x00800, 0xd915a389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m08p_7a.bin", 0x00800, 0xc9245346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "n08p_8a.bin", 0x00800, 0x797d45c7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sr.10", 0x00800, 0xaf069cba, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h01_2.bin", 0x00800, 0xc26132af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "sr.09", 0x00800, 0xff2c20d5, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k01_2.bin", 0x00800, 0xdcc2b33b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "uniwars.clr", 0x00020, 0x25c79518, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Skyraidr) +STD_ROM_FN(Skyraidr) + +void __fastcall PiscesZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5800 && a <= 0x58ff) { + INT32 Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + GalGfxBank[0] = d; + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + GalaxianLfoFreqWrite(a - 0x6004, d); + return; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + GalaxianSoundWrite(a - 0x6800, d); + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void PiscesInstallGfxBankHandler() +{ + ZetOpen(0); + ZetSetWriteHandler(PiscesZ80Write); + ZetClose(); +} + +static INT32 PiscesInit() +{ + GalPostLoadCallbackFunction = PiscesInstallGfxBankHandler; + GalExtendTileInfoFunction = PiscesExtendTileInfo; + GalExtendSpriteInfoFunction = PiscesExtendSpriteInfo; + + return GalInit(); +} + +struct BurnDriver BurnDrvPisces = { + "pisces", NULL, NULL, NULL, "19??", + "Pisces\0", NULL, "Subelectro", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, PiscesRomInfo, PiscesRomName, NULL, NULL, PicsesInputInfo, PiscesDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvPiscesb = { + "piscesb", "pisces", NULL, NULL, "19??", + "Pisces (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, PiscesbRomInfo, PiscesbRomName, NULL, NULL, PicsesInputInfo, PiscesbDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvOmni = { + "omni", "pisces", NULL, NULL, "19??", + "Omni\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, OmniRomInfo, OmniRomName, NULL, NULL, OmegaInputInfo, PiscesbDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvUniwars = { + "uniwars", NULL, NULL, NULL, "1980", + "UniWar S\0", NULL, "Irem", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, UniwarsRomInfo, UniwarsRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGteikoku = { + "gteikoku", "uniwars", NULL, NULL, "1980", + "Gingateikoku No Gyakushu\0", NULL, "Irem", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GteikokuRomInfo, GteikokuRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGteikokb = { + "gteikokb", "uniwars", NULL, NULL, "1980", + "Gingateikoku No Gyakushu (bootleg set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, GteikokbRomInfo, GteikokbRomName, NULL, NULL, OmegaInputInfo, GteikokbDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGteikob2 = { + "gteikob2", "uniwars", NULL, NULL, "1980", + "Gingateikoku No Gyakushu (bootleg set 2)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Gteikob2RomInfo, Gteikob2RomName, NULL, NULL, OmegaInputInfo, Gteikob2DIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpacbatt = { + "spacbatt", "uniwars", NULL, NULL, "1980", + "Space Battle (bootleg set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SpacbattRomInfo, SpacbattRomName, NULL, NULL, GalaxianInputInfo, SpacbattDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpacbat2 = { + "spacbat2", "uniwars", NULL, NULL, "1980", + "Space Battle (bootleg set 2)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Spacbat2RomInfo, Spacbat2RomName, NULL, NULL, GalaxianInputInfo, SpacbattDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpacempr = { + "spacempr", "uniwars", NULL, NULL, "1980", + "Space Empire (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SpacemprRomInfo, SpacemprRomName, NULL, NULL, GalaxianInputInfo, SpacbattDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSkyraidr = { + "skyraidr", "uniwars", NULL, NULL, "1980", + "Sky Raiders\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SkyraidrRomInfo, SkyraidrRomName, NULL, NULL, GalaxianInputInfo, SupergDIPInfo, + PiscesInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Extra chars contolled via different banking at 0x6002 +static struct BurnRomInfo Batman2RomDesc[] = { + { "01.bin", 0x00800, 0x150fbca5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "02.bin", 0x00800, 0xb1624fd0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "03.bin", 0x00800, 0x93774188, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "04.bin", 0x00800, 0x8a94ec6c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "05.bin", 0x00800, 0xa3669461, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "06.bin", 0x00800, 0xfa1efbfe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "07.bin", 0x00800, 0x9b77debd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "08.bin", 0x00800, 0x6466177e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "09.bin", 0x00800, 0x1a657b1f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "11.bin", 0x00800, 0x7a2b48e5, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "10.bin", 0x00800, 0x9b570016, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "12.bin", 0x00800, 0x73956244, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Batman2) +STD_ROM_FN(Batman2) + +static struct BurnRomInfo LadybuggRomDesc[] = { + { "lbuggx.1", 0x00800, 0xe67e241d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.2", 0x00800, 0x3cb1fb9a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.3", 0x00800, 0x0937009e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.4", 0x00800, 0x3e773f62, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.5", 0x00800, 0x2b0d42e5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.6", 0x00800, 0x159f9433, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.7", 0x00800, 0xf2be06d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lbuggx.8", 0x00800, 0x646fe79f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "lbuggx.a", 0x01000, 0x7efb9dc5, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "lbuggx.b", 0x01000, 0x351d4ddc, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "lbuggx.clr", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Ladybugg) +STD_ROM_FN(Ladybugg) + +static INT32 Batman2Init() +{ + GalPostLoadCallbackFunction = PiscesInstallGfxBankHandler; + GalExtendTileInfoFunction = Batman2ExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + return GalInit(); +} + +static INT32 LadybuggInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = PiscesInstallGfxBankHandler; + GalExtendTileInfoFunction = Batman2ExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + nRet = GalInit(); + + UINT8 *TempRom = (UINT8*)malloc(0x1000); + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + memcpy(GalTempRom + 0x0800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x0000, TempRom + 0x0800, 0x800); + BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + memcpy(GalTempRom + 0x1800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1000, TempRom + 0x0800, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + return nRet; +} + +struct BurnDriver BurnDrvBatman2 = { + "batman2", "phoenix", NULL, NULL, "1981", + "Batman Part 2\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Batman2RomInfo, Batman2RomName, NULL, NULL, Batman2InputInfo, Batman2DIPInfo, + Batman2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLadybugg = { + "ladybugg", "ladybug", NULL, NULL, "1983", + "Lady Bug (bootleg on Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, LadybuggRomInfo, LadybuggRomName, NULL, NULL, LadybuggInputInfo, LadybuggDIPInfo, + LadybuggInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Seperate sprite/tile roms +static struct BurnRomInfo StreakngRomDesc[] = { + { "sk1", 0x01000, 0xc8866ccb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sk2", 0x01000, 0x7caea29b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sk3", 0x01000, 0x7b4bfa76, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "sk4", 0x01000, 0x056fc921, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sk5", 0x01000, 0xd27f1e0c, BRF_GRA | GAL_ROM_TILES_CHARS }, + + { "sk6", 0x01000, 0xa7089588, BRF_GRA | GAL_ROM_TILES_SPRITES }, + + { "sk.bpr", 0x00020, 0xbce79607, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Streakng) +STD_ROM_FN(Streakng) + +static struct BurnRomInfo StreakngaRomDesc[] = { + { "st1.bin", 0x00800, 0xc827e124, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "st2.bin", 0x00800, 0xb01d4f8f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "st3.bin", 0x00800, 0xc7a9c493, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "st4.bin", 0x00800, 0x12487c75, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5st.bin", 0x00800, 0xf9f9e2be, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6st.bin", 0x00800, 0xc22fe6c2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7st.bin", 0x00800, 0x9cd7869a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8st.bin", 0x00800, 0x5e750ad3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "11.bin", 0x00800, 0xcddd8924, BRF_GRA | GAL_ROM_TILES_CHARS }, + { "12.bin", 0x00800, 0x10cda095, BRF_GRA | GAL_ROM_TILES_CHARS }, + + { "9.bin", 0x00800, 0x6a2a8a0f, BRF_GRA | GAL_ROM_TILES_SPRITES }, + { "10.bin", 0x00800, 0x3563dfbe, BRF_GRA | GAL_ROM_TILES_SPRITES }, + + { "sk.bpr", 0x00020, 0xbce79607, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Streaknga) +STD_ROM_FN(Streaknga) + +static struct BurnRomInfo PacmanblRomDesc[] = { + { "1", 0x00800, 0x6718df42, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2", 0x00800, 0x33be3648, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3", 0x00800, 0xf98c0ceb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4", 0x00800, 0xa9cd0082, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5", 0x00800, 0x6d475afc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6", 0x00800, 0xcbe863d3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7", 0x00800, 0x7daef758, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "12", 0x00800, 0xb2ed320b, BRF_GRA | GAL_ROM_TILES_CHARS }, + { "11", 0x00800, 0xab88b2c4, BRF_GRA | GAL_ROM_TILES_CHARS }, + + { "10", 0x00800, 0x44a45b72, BRF_GRA | GAL_ROM_TILES_SPRITES }, + { "9", 0x00800, 0xfa84659f, BRF_GRA | GAL_ROM_TILES_SPRITES }, + + { "sn74s288n.6l", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Pacmanbl) +STD_ROM_FN(Pacmanbl) + +static struct BurnRomInfo PacmanblaRomDesc[] = { + { "rom1.bin", 0x01000, 0x75e4f967, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2.bin", 0x01000, 0x5b2e4293, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom3.bin", 0x01000, 0xc06e30a4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom4.bin", 0x01000, 0x592b4ba8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rom5.bin", 0x01000, 0xf2d8c01e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom6.bin", 0x01000, 0x346a1720, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "sn74s288n.6l", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Pacmanbla) +STD_ROM_FN(Pacmanbla) + +static struct BurnRomInfo Phoenxp2RomDesc[] = { + { "1", 0x00800, 0xf6dcfd51, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2", 0x00800, 0xde951936, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3", 0x00800, 0x7a3af2da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4", 0x00800, 0xc820ad32, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5", 0x00800, 0x08e83233, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6", 0x00800, 0xf31fb9d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7", 0x00800, 0xd3a480c1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8", 0x00800, 0xedf9779e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "10", 0x00800, 0x9b570016, BRF_GRA | GAL_ROM_TILES_CHARS }, + { "09", 0x00800, 0x1a657b1f, BRF_GRA | GAL_ROM_TILES_CHARS }, + + { "12", 0x00800, 0x73956244, BRF_GRA | GAL_ROM_TILES_SPRITES }, + { "11", 0x00800, 0x7a2b48e5, BRF_GRA | GAL_ROM_TILES_SPRITES }, + + { "sn74s288n.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Phoenxp2) +STD_ROM_FN(Phoenxp2) + +static struct BurnRomInfo AtlantisbRomDesc[] = { + { "1", 0x00800, 0x2b612351, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2", 0x00800, 0xb1c970e9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3", 0x00800, 0x63c3783e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4", 0x00800, 0x45f7cf34, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5", 0x00800, 0xf335b96b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6", 0x00800, 0xa50bf8d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "8", 0x00800, 0x55cd5acd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "7", 0x00800, 0x72e773b8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "sn74s288n.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Atlantisb) +STD_ROM_FN(Atlantisb) + +static INT32 PacmanblInit() +{ + INT32 nRet = GalInit(); + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void PacmanblaRearrangeRom() +{ + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } +} + +static INT32 PacmanblaInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = PacmanblaRearrangeRom; + + nRet = PacmanblInit(); + + GalNumChars = 0x100; + GalNumSprites = 0x40; + CharPlaneOffsets[1] = 0x4000; + SpritePlaneOffsets[1] = 0x4000; + + UINT8 *TempRom = (UINT8*)malloc(0x2000); + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(TempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + memcpy(GalTempRom + 0x0000, TempRom + 0x0800, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x1800, 0x800); + memcpy(GalTempRom + 0x1000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1800, TempRom + 0x1000, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom + 0x1000, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + return nRet; +} + +static void AtlantisbRearrangeRom() +{ + GalTempRom = (UINT8*)malloc(0x3000); + + memcpy(GalTempRom, GalZ80Rom1, 0x3000); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x1000); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x1000, 0x2000); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } +} + +static INT32 AtlantisbInit() +{ + GalZ80Rom1Size = 0x1000; + + GalPostLoadCallbackFunction = AtlantisbRearrangeRom; + + return GalInit(); +} + +struct BurnDriver BurnDrvStreakng = { + "streakng", NULL, NULL, NULL, "1981", + "Streaking (set 1)\0", "Bad Colours", "Shoei", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, StreakngRomInfo, StreakngRomName, NULL, NULL, StreakngInputInfo, StreakngDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvStreaknga = { + "streaknga", "streakng", NULL, NULL, "1981", + "Streaking (set 2)\0", "Bad Colours", "Shoei", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, StreakngaRomInfo, StreakngaRomName, NULL, NULL, StreakngInputInfo, StreakngDIPInfo, + GalInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvPacmanbl = { + "pacmanbl", "puckman", NULL, NULL, "1981", + "Pac-Man (Galaxian hardware, set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, PacmanblRomInfo, PacmanblRomName, NULL, NULL, PacmanblInputInfo, PacmanblDIPInfo, + PacmanblInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvPacmanbla = { + "pacmanbla", "puckman", NULL, NULL, "1981", + "Pac-Man (Galaxian hardware, set 2)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, PacmanblaRomInfo, PacmanblaRomName, NULL, NULL, PacmanblInputInfo, PacmanblDIPInfo, + PacmanblaInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvPhoenxp2 = { + "phoenxp2", "phoenix", NULL, NULL, "1981", + "Phoenix Part 2\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Phoenxp2RomInfo, Phoenxp2RomName, NULL, NULL, Phoenxp2InputInfo, Phoenxp2DIPInfo, + PacmanblInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAtlantisb = { + "atlantisb", "atlantis", NULL, NULL, "1981", + "Battle of Atlantis (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, AtlantisbRomInfo, AtlantisbRomName, NULL, NULL, Phoenxp2InputInfo, AtlantisbDIPInfo, + AtlantisbInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Seperate sprite/tile roms with IRQ0 instead of NMI +static struct BurnRomInfo DevilfsgRomDesc[] = { + { "dfish1.7f", 0x01000, 0x2ab19698, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "dfish2.7h", 0x01000, 0x4e77f097, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "dfish3.7k", 0x01000, 0x3f16a4c6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "dfish4.7m", 0x01000, 0x11fc7e59, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "dfish5.1h", 0x01000, 0xace6e31f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "dfish6.1k", 0x01000, 0xd7a6c4c4, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Devilfsg) +STD_ROM_FN(Devilfsg) + +static void DevilfsgRearrangeRom() +{ + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } +} + +static INT32 DevilfsgInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DevilfsgRearrangeRom; + + nRet = GalInit(); + + GalNumChars = 0x100; + GalNumSprites = 0x40; + CharPlaneOffsets[1] = 0x4000; + SpritePlaneOffsets[1] = 0x4000; + + UINT8 *TempRom = (UINT8*)malloc(0x2000); + GalTempRom = (UINT8*)malloc(0x1000); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x0000, TempRom + 0x0800, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x1800, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + memcpy(GalTempRom + 0x0000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x1000, 0x800); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + GalIrqType = GAL_IRQ_TYPE_IRQ0; + + return nRet; +} + +struct BurnDriver BurnDrvDevilfsg = { + "devilfsg", "devilfsh", NULL, NULL, "1984", + "Devil Fish (Galaxian hardware, bootleg?)\0", NULL, "Vision / Artic", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, DevilfsgRomInfo, DevilfsgRomName, NULL, NULL, DevilfsgInputInfo, DevilfsgDIPInfo, + DevilfsgInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Sound hardware replaced with AY8910 +static struct BurnRomInfo ZigzagRomDesc[] = { + { "zz_d1.7l", 0x01000, 0x8cc08d81, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d2.7k", 0x01000, 0x326d8d45, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d4.7f", 0x01000, 0xa94ed92a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d3.7h", 0x01000, 0xce5e7a00, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "zz_6.1h", 0x01000, 0x780c162a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "zz_5.1k", 0x01000, 0xf3cdfec5, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "zzbpr_e9.bin", 0x00020, 0xaa486dd0, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Zigzag) +STD_ROM_FN(Zigzag) + +static struct BurnRomInfo Zigzag2RomDesc[] = { + { "z1.7l", 0x01000, 0x4c28349a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d2.7k", 0x01000, 0x326d8d45, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d4.7f", 0x01000, 0xa94ed92a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "zz_d3.7h", 0x01000, 0xce5e7a00, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "zz_6.1h", 0x01000, 0x780c162a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "zz_5.1k", 0x01000, 0xf3cdfec5, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "zzbpr_e9.bin", 0x00020, 0xaa486dd0, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Zigzag2) +STD_ROM_FN(Zigzag2) + +static struct BurnRomInfo Ozon1RomDesc[] = { + { "rom1.bin", 0x01000, 0x54899e8b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2.bin", 0x01000, 0x3c90fbfc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom3.bin", 0x01000, 0x79fe313b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rom7.bin", 0x00800, 0x464285e8, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom8.bin", 0x00800, 0x92056dcc, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "ozon1.clr", 0x00020, 0x605ea6e9, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Ozon1) +STD_ROM_FN(Ozon1) + +void __fastcall ZigzagZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x4800 && a <= 0x4fff) { + INT32 Offset = a - 0x4800; + + switch (Offset & 0x300) { + case 0x000: { + if ((Offset & 1) != 0) { + if ((Offset & 2) == 0) { + AY8910Write(0, 1, ZigzagAYLatch); + } else { + AY8910Write(0, 0, ZigzagAYLatch); + } + } + break; + } + + case 0x100: { + ZigzagAYLatch = Offset & 0xff; + break; + } + } + return; + } + + if (a >= 0x5800 && a <= 0x58ff) { + INT32 Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + // coin_lock_w + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7002: { + ZetMapArea(0x2000, 0x2fff, 0, GalZ80Rom1 + 0x2000 + (0x1000 * (d & 1))); + ZetMapArea(0x2000, 0x2fff, 2, GalZ80Rom1 + 0x2000 + (0x1000 * (d & 1))); + ZetMapArea(0x3000, 0x3fff, 0, GalZ80Rom1 + 0x2000 + (0x1000 * (~d & 1))); + ZetMapArea(0x3000, 0x3fff, 2, GalZ80Rom1 + 0x2000 + (0x1000 * (~d & 1))); + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + // watchdog write + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Ozon1Z80Read(UINT16 a) +{ + switch (a) { + case 0x8100: { + return 0xff - (GalInput[0] | GalDip[0]); + } + + case 0x8101: { + return 0xff - (GalInput[1] | GalDip[1]); + } + + case 0x8102: { + return 0xff - (GalInput[2] | GalDip[2]); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Ozon1Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6801: { + // ??? + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_counter_0_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall Ozon1Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + AY8910Write(0, 1, d); + return; + } + + case 0x01: { + AY8910Write(0, 0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static void ZigzagInstallHandler() +{ + ZetOpen(0); + ZetSetWriteHandler(ZigzagZ80Write); + ZetClose(); +} + +static INT32 ZigzagInit() +{ + INT32 nRet; + + GalSoundType = GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910; + GalPostLoadCallbackFunction = ZigzagInstallHandler; + + nRet = GalInit(); + + GalNumChars = 0x100; + GalNumSprites = 0x40; + CharPlaneOffsets[1] = 0x4000; + SpritePlaneOffsets[1] = 0x4000; + + UINT8 *TempRom = (UINT8*)malloc(0x2000); + GalTempRom = (UINT8*)malloc(0x1000); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x0000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x1000, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + memcpy(GalTempRom + 0x0000, TempRom + 0x0800, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x1800, 0x800); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + GalDrawBulletsFunction = NULL; + + GalSoundVolumeShift = 3; + + return nRet; +} + +static void Ozon1PostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(Ozon1Z80Read); + ZetSetWriteHandler(Ozon1Z80Write); + ZetSetOutHandler(Ozon1Z80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x43ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x43ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x43ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 0, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 1, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +static INT32 Ozon1Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Ozon1PostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910; + + nRet = GalInit(); + + GalDrawBulletsFunction = NULL; + GalRenderBackgroundFunction = NULL; + + return nRet; +} + +struct BurnDriver BurnDrvZigzag = { + "zigzag", NULL, NULL, NULL, "1982", + "Zig Zag (Galaxian hardware, set 1)\0", NULL, "LAX", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, ZigzagRomInfo, ZigzagRomName, NULL, NULL, ZigzagInputInfo, ZigzagDIPInfo, + ZigzagInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvZigzag2 = { + "zigzag2", "zigzag", NULL, NULL, "1982", + "Zig Zag (Galaxian hardware, set 2)\0", NULL, "LAX", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Zigzag2RomInfo, Zigzag2RomName, NULL, NULL, ZigzagInputInfo, ZigzagDIPInfo, + ZigzagInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvOzon1 = { + "ozon1", NULL, NULL, NULL, "1983", + "Ozon I\0", NULL, "Proma", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Ozon1RomInfo, Ozon1RomName, NULL, NULL, Ozon1InputInfo, Ozon1DIPInfo, + Ozon1Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Multi-game select via external switch +static struct BurnRomInfo GmgalaxRomDesc[] = { + { "pcb1_pm1.bin", 0x01000, 0x19338c70, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_pm2.bin", 0x01000, 0x18db074d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_pm3.bin", 0x01000, 0xabb98b1d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_pm4.bin", 0x01000, 0x2403c78e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_gx1.bin", 0x01000, 0x2faa9f53, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_gx2.bin", 0x01000, 0x121c5f16, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "pcb1_gx3.bin", 0x01000, 0x02d81a21, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "pcb2gfx1.bin", 0x01000, 0x7021bbc0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "pcb2gfx3.bin", 0x01000, 0x089c922b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "pcb2gfx2.bin", 0x01000, 0x51bf58ee, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "pcb2gfx4.bin", 0x01000, 0x908fd0dc, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "gmgalax2.clr", 0x00020, 0x499f4440, BRF_GRA | GAL_ROM_PROM }, + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Gmgalax) +STD_ROM_FN(Gmgalax) + +UINT8 __fastcall GmgalaxZ80Read(UINT16 a) +{ + switch (a) { + case 0x6000: { + return GalInput[0] | ((GmgalaxSelectedGame) ? GalDip[3] : GalDip[0]); + } + + case 0x6800: { + return GalInput[1] | ((GmgalaxSelectedGame) ? GalDip[4] : GalDip[1]); + } + + case 0x7000: { + return GalInput[2] | ((GmgalaxSelectedGame) ? GalDip[5] : GalDip[2]); + } + + case 0x7800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +static void GmgalaxPostLoad() +{ + ZetOpen(0); + ZetSetReadHandler(GmgalaxZ80Read); + ZetClose(); +} + +static INT32 GmgalaxInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = GmgalaxPostLoad; + GalZ80Rom1Size = 0x1000; + + nRet = GalInit(); + + UINT8 *TempRom = (UINT8*)malloc(0x1000); + GalTempRom = (UINT8*)malloc(0x4000); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x0000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x0800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1800, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x2000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x3000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x2800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x3800, TempRom + 0x0800, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + GalExtendTileInfoFunction = GmgalaxExtendTileInfo; + GalExtendSpriteInfoFunction = GmgalaxExtendSpriteInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + GameIsGmgalax = 1; + + return nRet; +} + +struct BurnDriver BurnDrvGmgalax = { + "gmgalax", NULL, NULL, NULL, "1981", + "Ghostmuncher Galaxian (bootleg)\0", NULL, "LAX", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, GmgalaxRomInfo, GmgalaxRomName, NULL, NULL, GmgalaxInputInfo, GmgalaxDIPInfo, + GmgalaxInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Multi-game select via menu, with different graphic and sprite roms +static struct BurnRomInfo Fourin1RomDesc[] = { + { "rom1a", 0x01000, 0xce1af4d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1b", 0x01000, 0x18484f9b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1c", 0x01000, 0x83248a8b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1d", 0x01000, 0x053f6da0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1e", 0x01000, 0x43c546f3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1f", 0x01000, 0x3a086b46, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1g", 0x01000, 0xac0e2050, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1h", 0x01000, 0xdc11a513, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1i", 0x01000, 0xa5fb6be4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom1j", 0x01000, 0x9054cfbe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2c", 0x01000, 0x7cd98e11, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2d", 0x01000, 0x9402f32e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2e", 0x01000, 0x468e81df, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2g", 0x01000, 0xb1ce3976, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2h", 0x01000, 0x7eab5670, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2i", 0x01000, 0x44565ac5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rom4b", 0x01000, 0x7e6495af, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom3b", 0x01000, 0x7475f72f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom4c", 0x00800, 0x3355d46d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom3c", 0x00800, 0xac755a25, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom4d", 0x01000, 0xbbdddb65, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom3d", 0x01000, 0x91a00204, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom4e", 0x01000, 0x0cb9e297, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom3e", 0x01000, 0xa1fe77f9, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Fourin1) +STD_ROM_FN(Fourin1) + +UINT8 __fastcall Fourin1Z80Read(UINT16 a) +{ + switch (a) { + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return ((GalInput[1] | GalDip[1]) & ~0xc0) | (GalDip[3 + Fourin1Bank] & 0xc0); + } + + case 0x7000: { + return ((GalInput[2] | GalDip[2]) & 0x04) | (GalDip[3 + Fourin1Bank] & ~0xc4); + } + + case 0x7800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Fourin1Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5800 && a <= 0x58ff) { + INT32 Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + // coin_lock_w + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + GalaxianLfoFreqWrite(a - 0x6004, d); + return; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + GalaxianSoundWrite(a - 0x6800, d); + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + case 0x8000: { + Fourin1Bank = d & 0x03; + ZetMapArea(0x0000, 0x3fff, 0, GalZ80Rom1 + 0x2000 + (Fourin1Bank * 0x4000)); + ZetMapArea(0x0000, 0x3fff, 2, GalZ80Rom1 + 0x2000 + (Fourin1Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void Fourin1PostLoad() +{ + GalTempRom = (UINT8*)malloc(0x3000); + memcpy(GalTempRom, GalZ80Rom1 + 0xd000, 0x3000); + memset(GalZ80Rom1 + 0xd000, 0xff, 0x1000); + memcpy(GalZ80Rom1 + 0xe000, GalTempRom, 0x3000); + memset(GalZ80Rom1 + 0x11000, 0xff, 0x1000); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + for (UINT32 i = 0; i < GalZ80Rom1Size; i++) { + GalZ80Rom1[i] = GalZ80Rom1[i] ^ (i & 0xff); + } + + ZetOpen(0); + ZetSetReadHandler(Fourin1Z80Read); + ZetSetWriteHandler(Fourin1Z80Write); + ZetMapArea(0x0000, 0x3fff, 0, GalZ80Rom1 + 0x2000 + (Fourin1Bank * 0x4000)); + ZetMapArea(0x0000, 0x3fff, 2, GalZ80Rom1 + 0x2000 + (Fourin1Bank * 0x4000)); + ZetMapArea(0xc000, 0xdfff, 0, GalZ80Rom1); + ZetMapArea(0xc000, 0xdfff, 2, GalZ80Rom1); + ZetClose(); +} + +static INT32 Fourin1Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Fourin1PostLoad; + GalZ80Rom1Size = 0x2000; + GalTilesSharedRomSize = 0x1000; + + nRet = GalInit(); + + GalNumChars = 1024; + GalNumSprites = 256; + CharPlaneOffsets[1] = GalNumChars * 8 * 8; + SpritePlaneOffsets[1] = GalNumSprites * 16 * 16; + + UINT8 *TempRom = (UINT8*)malloc(0x1000); + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x4000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x0000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x6000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x2000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x4800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x0800, TempRom + 0x0000, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x6800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x2800, TempRom + 0x0000, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 4, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x5000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 5, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x7000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x3000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 6, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x5800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1800, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 7, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x7800, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x3800, TempRom + 0x0800, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom + 0x4000, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + GalExtendTileInfoFunction = Fourin1ExtendTileInfo; + GalExtendSpriteInfoFunction = Fourin1ExtendSpriteInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +struct BurnDriver BurnDrvFourin1 = { + "4in1", NULL, NULL, NULL, "1981", + "4 Fun in 1\0", NULL, "Armenia / Food and Fun", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Fourin1RomInfo, Fourin1RomName, NULL, NULL, Fourin1InputInfo, Fourin1DIPInfo, + Fourin1Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Moon Cresta on Galaxian hardware with different memory map +static struct BurnRomInfo MooncrstRomDesc[] = { + { "mc1", 0x00800, 0x7d954a7a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc2", 0x00800, 0x44bb7cfa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc3", 0x00800, 0x9c412104, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc4", 0x00800, 0x7e9b1ab5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc5.7r", 0x00800, 0x16c759af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc6.8d", 0x00800, 0x69bcafdb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc7.8e", 0x00800, 0xb50dbc46, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc8", 0x00800, 0x18ca312b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mcs_b", 0x00800, 0xfb0f1f81, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_a", 0x00800, 0x631ebb5a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrst) +STD_ROM_FN(Mooncrst) + +static struct BurnRomInfo MooncrstukRomDesc[] = { + { "mc1", 0x00800, 0x7d954a7a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc2", 0x00800, 0x44bb7cfa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc3", 0x00800, 0x9c412104, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc4", 0x00800, 0x7e9b1ab5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc5.7r", 0x00800, 0x16c759af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc6.8d", 0x00800, 0x69bcafdb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc7.8e", 0x00800, 0xb50dbc46, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8_uk.bin", 0x00800, 0xce727ad4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mcs_b", 0x00800, 0xfb0f1f81, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_a", 0x00800, 0x631ebb5a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrstuk) +STD_ROM_FN(Mooncrstuk) + +static struct BurnRomInfo MooncrstuRomDesc[] = { + { "smc1f", 0x00800, 0x389ca0d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "smc2f", 0x00800, 0x410ab430, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "smc3f", 0x00800, 0xa6b4144b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "smc4f", 0x00800, 0x4cc046fe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr199", 0x00800, 0x6e84a927, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "smc8f", 0x00800, 0xf42164c5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mcs_b", 0x00800, 0xfb0f1f81, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_a", 0x00800, 0x631ebb5a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrstu) +STD_ROM_FN(Mooncrstu) + +static struct BurnRomInfo MooncrstoRomDesc[] = { + { "mc1.7d", 0x00800, 0x92a86aac, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc2.7e", 0x00800, 0x438c2b4b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc3.7j", 0x00800, 0x67e3d21d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc4.7p", 0x00800, 0xf4db39f6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc5.7r", 0x00800, 0x16c759af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc6.8d", 0x00800, 0x69bcafdb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc7.8e", 0x00800, 0xb50dbc46, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mc8.8h", 0x00800, 0x7e2b1928, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mcs_b", 0x00800, 0xfb0f1f81, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_a", 0x00800, 0x631ebb5a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrsto) +STD_ROM_FN(Mooncrsto) + +static struct BurnRomInfo MooncrstgRomDesc[] = { + { "epr194", 0x00800, 0x0e5582b1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr195", 0x00800, 0x12cb201b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr196", 0x00800, 0x18255614, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr197", 0x00800, 0x05ac1466, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr198", 0x00800, 0xc28a2e8f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr199", 0x00800, 0x5a4571de, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr200", 0x00800, 0xb7c85bf1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr201", 0x00800, 0x2caba07f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr203", 0x00800, 0xbe26b561, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr202", 0x00800, 0x26c7e800, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrstg) +STD_ROM_FN(Mooncrstg) + +static void MooncrstEncryptedPostLoad() +{ + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 Data = GalZ80Rom1[Offset]; + UINT8 Res = Data; + if (BIT(Data, 1)) Res ^= 0x40; + if (BIT(Data, 5)) Res ^= 0x04; + if ((Offset & 1) == 0) Res = BITSWAP08(Res, 7, 2, 5, 4, 3, 6, 1, 0); + GalZ80Rom1[Offset] = Res; + } + + MapMooncrst(); +} + +static INT32 MooncrstEncryptedInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MooncrstEncryptedPostLoad; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +static INT32 MooncrstInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapMooncrst; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvMooncrst = { + "mooncrst", NULL, NULL, NULL, "1980", + "Moon Cresta (Nichibutsu)\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrstRomInfo, MooncrstRomName, NULL, NULL, OmegaInputInfo, MooncrstDIPInfo, + MooncrstEncryptedInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrstuk = { + "mooncrstuk", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (Nichibutsu UK)\0", NULL, "Nichibutsu UK", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrstukRomInfo, MooncrstukRomName, NULL, NULL, OmegaInputInfo, MooncrstDIPInfo, + MooncrstEncryptedInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrstu = { + "mooncrstu", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (Nichibutsu USA, unencrypted)\0", NULL, "Nichibutsu USA", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrstuRomInfo, MooncrstuRomName, NULL, NULL, OmegaInputInfo, MooncrstDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrsto = { + "mooncrsto", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (Nichibutsu, old rev)\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrstoRomInfo, MooncrstoRomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + MooncrstEncryptedInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrstg = { + "mooncrstg", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (Gremlin)\0", NULL, "Gremlin", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrstgRomInfo, MooncrstgRomName, NULL, NULL, OmegaInputInfo, MooncrsgDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Straight Moon Cresta Rip-Offs on basic Moon Cresta hardware +static struct BurnRomInfo MooncrsbRomDesc[] = { + { "bepr194", 0x00800, 0x6a23ec6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr195", 0x00800, 0xee262ff2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr199", 0x00800, 0x6e84a927, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr201", 0x00800, 0x66da55d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr203", 0x00800, 0xbe26b561, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr202", 0x00800, 0x26c7e800, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrsb) +STD_ROM_FN(Mooncrsb) + +static struct BurnRomInfo Mooncrs2RomDesc[] = { + { "f8.bin", 0x00800, 0xd36003e5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr195", 0x00800, 0xee262ff2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bepr199", 0x00800, 0x6e84a927, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m7.bin", 0x00800, 0x957ee078, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h_1_10.bin", 0x00800, 0x528da705, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "12.chr", 0x00800, 0x5a4b17ea, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k_1_11.bin", 0x00800, 0x4e79ff6b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "11.chr", 0x00800, 0xe0edccbd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrs2) +STD_ROM_FN(Mooncrs2) + +static struct BurnRomInfo Mooncrs3RomDesc[] = { + { "b1.7f", 0x01000, 0x0b28cd8a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b2.7h", 0x01000, 0x74a6f0ca, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b3.7j", 0x01000, 0xeeb34cc9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b4.7k", 0x01000, 0x714330e5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "o.1h", 0x00800, 0x528da705, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "q.1h", 0x00800, 0x5a4b17ea, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "p.1k", 0x00800, 0x4e79ff6b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "r.1k", 0x00800, 0xe0edccbd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrs3) +STD_ROM_FN(Mooncrs3) + +static struct BurnRomInfo FantaziaRomDesc[] = { + { "f01.bin", 0x00800, 0xd3e23863, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f02.bin", 0x00800, 0x63fa4149, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f09.bin", 0x00800, 0x75fd5ca1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f10.bin", 0x00800, 0xe4da2dd4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f11.bin", 0x00800, 0x42869646, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f12.bin", 0x00800, 0xa48d7fb0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h_1_10.bin", 0x00800, 0x528da705, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k_1_11.bin", 0x00800, 0x4e79ff6b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "fantazia.clr", 0x00020, 0xa84ff0af, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Fantazia) +STD_ROM_FN(Fantazia) + +static struct BurnRomInfo EagleRomDesc[] = { + { "e1", 0x00800, 0x224c9526, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e2", 0x00800, 0xcc538ebd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e6", 0x00800, 0x0dea20d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e8", 0x00800, 0xc437a876, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "e10", 0x00800, 0x40ce58bf, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e12", 0x00800, 0x628fdeed, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e9", 0x00800, 0xba664099, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e11", 0x00800, 0xee4ec5fd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Eagle) +STD_ROM_FN(Eagle) + +static struct BurnRomInfo Eagle2RomDesc[] = { + { "e1.7f", 0x00800, 0x45aab7a3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e2", 0x00800, 0xcc538ebd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e6.6", 0x00800, 0x9f09f8c6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e8", 0x00800, 0xc437a876, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "e10.2", 0x00800, 0x25b38ebd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e12", 0x00800, 0x628fdeed, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e9", 0x00800, 0xba664099, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e11", 0x00800, 0xee4ec5fd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Eagle2) +STD_ROM_FN(Eagle2) + +static struct BurnRomInfo Eagle3RomDesc[] = { + { "e1", 0x00800, 0x224c9526, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e2", 0x00800, 0xcc538ebd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f03.bin", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f04.bin", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e6", 0x00800, 0x0dea20d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e8", 0x00800, 0xc437a876, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "e10a", 0x00800, 0xe3c63d4c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e12", 0x00800, 0x628fdeed, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e9a", 0x00800, 0x59429e47, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "e11", 0x00800, 0xee4ec5fd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Eagle3) +STD_ROM_FN(Eagle3) + +static struct BurnRomInfo SpctbirdRomDesc[] = { + { "tssa-7f", 0x00800, 0x45aab7a3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-7h", 0x00800, 0x8b328f48, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-7k", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-7m", 0x00800, 0x99c9166d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-5", 0x00800, 0x797b6261, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-6", 0x00800, 0x4825692c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tssa-8", 0x00800, 0xc9b77b85, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "tssb-2", 0x00800, 0x7d23e1f2, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tssb-4", 0x00800, 0xe4977833, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tssb-1", 0x00800, 0x9b9267c3, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tssb-3", 0x00800, 0x5ca5e233, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spctbird) +STD_ROM_FN(Spctbird) + +static struct BurnRomInfo SmooncrsRomDesc[] = { + { "927", 0x00800, 0x55c5b994, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "928a", 0x00800, 0x77ae26d3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "929", 0x00800, 0x716eaa10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "930", 0x00800, 0xcea864f2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "931", 0x00800, 0x702c5f51, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "932a", 0x00800, 0xe6a2039f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "933", 0x00800, 0x73783cee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "934", 0x00800, 0xc1a14aa2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr203", 0x00800, 0xbe26b561, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_d", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr202", 0x00800, 0x26c7e800, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mcs_c", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Smooncrs) +STD_ROM_FN(Smooncrs) + +static struct BurnRomInfo SstarcrsRomDesc[] = { + { "ss1", 0x00800, 0x2ff72897, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss2", 0x00800, 0x565e7880, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss3", 0x00800, 0xa1939def, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss4", 0x00800, 0xa332e012, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss5", 0x00800, 0xb9e58453, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss6", 0x00800, 0x7cbb5bc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss7", 0x00800, 0x57713b91, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ss8", 0x00800, 0xc857e898, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ss10", 0x00800, 0x2a95b8ea, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ss12", 0x00800, 0xb92c4c30, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ss9", 0x00800, 0x3661e084, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ss11", 0x00800, 0x95613048, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Sstarcrs) +STD_ROM_FN(Sstarcrs) + +static struct BurnRomInfo MooncmwRomDesc[] = { + { "60.1x", 0x00800, 0x322859e6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "61.2x", 0x00800, 0xc249902d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "62.3x", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "63.4x", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "64.5x", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "65.6x", 0x00800, 0x6e84a927, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "66.7x", 0x00800, 0xf23cd8ce, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "67.8x", 0x00800, 0x66da55d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "68.1h", 0x01000, 0x78663d86, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "69.1k", 0x01000, 0x162c50d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom-sn74s288n-71.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncmw) +STD_ROM_FN(Mooncmw) + +static struct BurnRomInfo SpcdragRomDesc[] = { + { "a.bin", 0x00800, 0x38cc9839, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b.bin", 0x00800, 0x419fa8d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "c.bin", 0x00800, 0xa1939def, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "d.bin", 0x00800, 0xcbcf17c5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "em.bin", 0x00800, 0xeb81c19c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fm.bin", 0x00800, 0x757b7672, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g.bin", 0x00800, 0x57713b91, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "h.bin", 0x00800, 0x159ad847, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "203.bin", 0x00800, 0xa2e82527, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "172.bin", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "202.bin", 0x00800, 0x80c3ad74, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "171.bin", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spcdrag) +STD_ROM_FN(Spcdrag) + +static struct BurnRomInfo SpcdragaRomDesc[] = { + { "1.7g", 0x00800, 0x38cc9839, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.7g", 0x00800, 0x29e00ae4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.7g", 0x00800, 0xa1939def, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.7g", 0x00800, 0x068f8830, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.10g", 0x00800, 0x32cd9adc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.10g", 0x00800, 0x50db67c5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7.10g", 0x00800, 0x22415271, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.10g", 0x00800, 0x159ad847, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "a2.7a", 0x00800, 0x38b042dd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "a4.7a", 0x00800, 0x5a4b17ea, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "a1.9a", 0x00800, 0x24441ab3, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "a3.9a", 0x00800, 0xe0edccbd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom_6331.10f", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spcdraga) +STD_ROM_FN(Spcdraga) + +static struct BurnRomInfo SteraRomDesc[] = { + { "stera.1", 0x00800, 0xcd04fea8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.2", 0x00800, 0xccd1878e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.3", 0x00800, 0x29a2b0ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.4", 0x00800, 0x4c6a5a6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.5", 0x00800, 0x06d378a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.6", 0x00800, 0x6e84a927, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.7", 0x00800, 0xb45af1e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "stera.8", 0x00800, 0x37f19956, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "stera.10", 0x00800, 0x528da705, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "stera.12", 0x00800, 0x13932a15, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "stera.11", 0x00800, 0x4e79ff6b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "stera.9", 0x00800, 0x24cfd145, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "stera.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Stera) +STD_ROM_FN(Stera) + +static struct BurnRomInfo MooncrgxRomDesc[] = { + { "1", 0x00800, 0x84cf420b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2", 0x00800, 0x4c2a61a1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3", 0x00800, 0x1962523a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4", 0x00800, 0x75dca896, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5", 0x00800, 0x32483039, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6", 0x00800, 0x43f2ab89, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7", 0x00800, 0x1e9c168c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8", 0x00800, 0x5e09da94, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h_1_10.bin", 0x00800, 0x528da705, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "12.chr", 0x00800, 0x5a4b17ea, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "9.chr", 0x00800, 0x70df525c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "11.chr", 0x00800, 0xe0edccbd, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mooncrgx) +STD_ROM_FN(Mooncrgx) + +static struct BurnRomInfo MoonqsrRomDesc[] = { + { "mq1", 0x00800, 0x132c13ec, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq2", 0x00800, 0xc8eb74f1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq3", 0x00800, 0x33965a89, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq4", 0x00800, 0xa3861d17, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq5", 0x00800, 0x8bcf9c67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq6", 0x00800, 0x5750cda9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq7", 0x00800, 0x78d7fe5b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mq8", 0x00800, 0x4919eed5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mqb", 0x00800, 0xb55ec806, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mqd", 0x00800, 0x9e7d0e13, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mqa", 0x00800, 0x66eee0db, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mqc", 0x00800, 0xa6db5b0d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "vid_e6.bin", 0x00020, 0x0b878b54, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonqsr) +STD_ROM_FN(Moonqsr) + +static struct BurnRomInfo Moonal2RomDesc[] = { + { "ali1", 0x00400, 0x0dcecab4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali2", 0x00400, 0xc6ee75a7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali3", 0x00400, 0xcd1be7e9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali4", 0x00400, 0x83b03f08, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali5", 0x00400, 0x6f3cf61d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali6", 0x00400, 0xe169d432, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali7", 0x00400, 0x41f64b73, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali8", 0x00400, 0xf72ee876, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali9", 0x00400, 0xb7fb763c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali10", 0x00400, 0xb1059179, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali11", 0x00400, 0x9e79a1c6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ali13.1h", 0x00800, 0xa1287bf6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ali12.1k", 0x00800, 0x528f1481, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonal2) +STD_ROM_FN(Moonal2) + +static struct BurnRomInfo Moonal2bRomDesc[] = { + { "ali1", 0x00400, 0x0dcecab4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali2", 0x00400, 0xc6ee75a7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "md-2", 0x00800, 0x8318b187, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali5", 0x00400, 0x6f3cf61d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali6", 0x00400, 0xe169d432, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali7", 0x00400, 0x41f64b73, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali8", 0x00400, 0xf72ee876, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali9", 0x00400, 0xb7fb763c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali10", 0x00400, 0xb1059179, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "md-6", 0x00800, 0x9cc973e0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ali13.1h", 0x00800, 0xa1287bf6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ali12.1k", 0x00800, 0x528f1481, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bpr", 0x00020, 0xc3ac9467, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonal2b) +STD_ROM_FN(Moonal2b) + +static struct BurnRomInfo ThepitmRomDesc[] = { + { "1.bin", 0x00800, 0x0f78d6ea, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.bin", 0x00800, 0xebacc6eb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.bin", 0x00800, 0x14fd0706, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.bin", 0x00800, 0x613e920f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.bin", 0x00800, 0x5a791f3f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.bin", 0x00800, 0x0bb37f51, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7.bin", 0x00800, 0x4dfdec6f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.bin", 0x00800, 0xa39a9189, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "9.bin", 0x00800, 0x2eb90e07, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1h.bin", 0x00800, 0x00dce65f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "1k.bin", 0x00800, 0x3ec0056e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6l.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Thepitm) +STD_ROM_FN(Thepitm) + +void __fastcall MooncrgxZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5800 && a <= 0x58ff) { + INT32 Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: + case 0x6002: { + GalGfxBank[a - 0x6000] = d; + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + GalaxianLfoFreqWrite(a - 0x6004, d); + return; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + GalaxianSoundWrite(a - 0x6800, d); + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall MoonqsrZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb000: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + } + + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +void __fastcall ThepitmZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void Mooncrs2RearrangeGfx() +{ + UINT8* TempRom = (UINT8*)malloc(0x800); + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); + BurnLoadRom(TempRom, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + memcpy(GalTempRom + 0x0800, TempRom + 0x0000, 0x200); + memcpy(GalTempRom + 0x0c00, TempRom + 0x0200, 0x200); + memcpy(GalTempRom + 0x0a00, TempRom + 0x0400, 0x200); + memcpy(GalTempRom + 0x0e00, TempRom + 0x0600, 0x200); + BurnLoadRom(TempRom, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); + memcpy(GalTempRom + 0x1800, TempRom + 0x0000, 0x200); + memcpy(GalTempRom + 0x1c00, TempRom + 0x0200, 0x200); + memcpy(GalTempRom + 0x1a00, TempRom + 0x0400, 0x200); + memcpy(GalTempRom + 0x1e00, TempRom + 0x0600, 0x200); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } +} + +static INT32 Mooncrs2Init() +{ + GalPostLoadCallbackFunction = MapMooncrst; + + INT32 nRet = GalInit(); + + Mooncrs2RearrangeGfx(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +static void Mooncrs3PostLoad() +{ + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapMooncrst(); +} + +static INT32 Mooncrs3Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Mooncrs3PostLoad; + + nRet = GalInit(); + + Mooncrs2RearrangeGfx(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +static void MooncrgxInstallHandler() +{ + ZetOpen(0); + ZetSetWriteHandler(MooncrgxZ80Write); + ZetClose(); +} + +static INT32 MooncrgxInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MooncrgxInstallHandler; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +static void MoonqsrDecrypt() +{ + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 Data = GalZ80Rom1[Offset]; + UINT8 Res = Data; + if (BIT(Data, 1)) Res ^= 0x40; + if (BIT(Data, 5)) Res ^= 0x04; + if ((Offset & 1) == 0) Res = BITSWAP08(Res, 7, 2, 5, 4, 3, 6, 1, 0); + GalZ80Rom1Op[Offset] = Res; + } + + MapMooncrst(); + + ZetOpen(0); + ZetSetWriteHandler(MoonqsrZ80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1Op, GalZ80Rom1); + ZetClose(); +} + +static INT32 MoonqsrInit() +{ + INT32 nRet; + + GalZ80Rom1Op = (UINT8*)malloc(0x4000); + + GalPostLoadCallbackFunction = MoonqsrDecrypt; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MoonqsrExtendTileInfo; + GalExtendSpriteInfoFunction = MoonqsrExtendSpriteInfo; + + return nRet; +} + +static INT32 Moonal2Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapMooncrst; + + nRet = GalInit(); + + return nRet; +} + +static void ThepitmPostLoad() +{ + MapMooncrst(); + + ZetOpen(0); + ZetMapArea(0x0000, 0x47ff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x47ff, 2, GalZ80Rom1); + ZetSetWriteHandler(ThepitmZ80Write); + ZetClose(); +} + +static INT32 ThepitmInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = ThepitmPostLoad; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvMooncrsb = { + "mooncrsb", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (bootleg set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrsbRomInfo, MooncrsbRomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrs2 = { + "mooncrs2", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (bootleg set 2)\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Mooncrs2RomInfo, Mooncrs2RomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + Mooncrs2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrs3 = { + "mooncrs3", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (bootleg set 3)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Mooncrs3RomInfo, Mooncrs3RomName, NULL, NULL, OmegaInputInfo, MooncrstDIPInfo, + Mooncrs3Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFantazia = { + "fantazia", "mooncrst", NULL, NULL, "1980", + "Fantazia (bootleg?)\0", NULL, "SubElectro", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, FantaziaRomInfo, FantaziaRomName, NULL, NULL, OmegaInputInfo, FantaziaDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvEagle = { + "eagle", "mooncrst", NULL, NULL, "1980", + "Eagle (set 1)\0", NULL, "Centuri", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, EagleRomInfo, EagleRomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + Mooncrs2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvEagle2 = { + "eagle2", "mooncrst", NULL, NULL, "1980", + "Eagle (set 2)\0", NULL, "Centuri", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Eagle2RomInfo, Eagle2RomName, NULL, NULL, OmegaInputInfo, Eagle2DIPInfo, + Mooncrs2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvEagle3 = { + "eagle3", "mooncrst", NULL, NULL, "1980", + "Eagle (set 3)\0", NULL, "Centuri", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Eagle3RomInfo, Eagle3RomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + Mooncrs2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpctbird = { + "spctbird", "mooncrst", NULL, NULL, "1981?", + "Space Thunderbird\0", NULL, "Fortrek", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SpctbirdRomInfo, SpctbirdRomName, NULL, NULL, OmegaInputInfo, Eagle2DIPInfo, + Mooncrs2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSmooncrs = { + "smooncrs", "mooncrst", NULL, NULL, "1981?", + "Super Moon Cresta\0", NULL, "Gremlin", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SmooncrsRomInfo, SmooncrsRomName, NULL, NULL, SmooncrsInputInfo, SmooncrsDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSstarcrs = { + "sstarcrs", "mooncrst", NULL, NULL, "1980?", + "Super Star Crest\0", NULL, "Nichibutsu (Taito do Brasil license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SstarcrsRomInfo, SstarcrsRomName, NULL, NULL, OmegaInputInfo, MooncrsgDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncmw = { + "mooncmw", "mooncrst", NULL, NULL, "198?", + "Moon War (Moon Cresta bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncmwRomInfo, MooncmwRomName, NULL, NULL, OmegaInputInfo, MooncrsaDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpcdrag = { + "spcdrag", "mooncrst", NULL, NULL, "1980", + "Space Dragon (Moon Cresta bootleg, set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SpcdragRomInfo, SpcdragRomName, NULL, NULL, SmooncrsInputInfo, SmooncrsDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpcdraga = { + "spcdraga", "mooncrst", NULL, NULL, "1980", + "Space Dragon (Moon Cresta bootleg, set 2)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SpcdragaRomInfo, SpcdragaRomName, NULL, NULL, SmooncrsInputInfo, SmooncrsDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvStera = { + "stera", "mooncrst", NULL, NULL, "1980", + "Steraranger (Moon Cresta bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SteraRomInfo, SteraRomName, NULL, NULL, SmooncrsInputInfo, SmooncrsDIPInfo, + MooncrstInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMooncrgx = { + "mooncrgx", "mooncrst", NULL, NULL, "1980", + "Moon Cresta (Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MooncrgxRomInfo, MooncrgxRomName, NULL, NULL, OmegaInputInfo, MooncrgxDIPInfo, + MooncrgxInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMoonqsr = { + "moonqsr", NULL, NULL, NULL, "1980", + "Moon Quasar\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MoonqsrRomInfo, MoonqsrRomName, NULL, NULL, OmegaInputInfo, MoonqsrDIPInfo, + MoonqsrInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMoonal2 = { + "moonal2", "galaxian", NULL, NULL, "1980", + "Moon Alien Part 2\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Moonal2RomInfo, Moonal2RomName, NULL, NULL, GalaxianInputInfo, Moonal2DIPInfo, + Moonal2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMoonal2b = { + "moonal2b", "galaxian", NULL, NULL, "1980", + "Moon Alien Part 2 (older version)\0", NULL, "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Moonal2bRomInfo, Moonal2bRomName, NULL, NULL, GalaxianInputInfo, Moonal2DIPInfo, + Moonal2Init, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvThepitm = { + "thepitm", "thepit", NULL, NULL, "198?", + "The Pit (bootleg on Moon Quasar hardware)\0", NULL, "bootleg (KZH)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, ThepitmRomInfo, ThepitmRomName, NULL, NULL, ThepitmInputInfo, ThepitmDIPInfo, + ThepitmInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Other games on basic Moon Cresta hardware +static struct BurnRomInfo SkybaseRomDesc[] = { + { "skybase.9a", 0x01000, 0x845b87a5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "skybase.8a", 0x01000, 0x096785c2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "skybase.7a", 0x01000, 0xd50c715b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "skybase.6a", 0x01000, 0xf57edb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "skybase.5a", 0x01000, 0x50365d95, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "skybase.4a", 0x01000, 0xcbd6647f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "skybase.7t", 0x01000, 0x9b471686, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "skybase.8t", 0x01000, 0x1cf723da, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "skybase.10t", 0x01000, 0xfe02e72c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "skybase.9t", 0x01000, 0x0871291f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.bpr", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Skybase) +STD_ROM_FN(Skybase) + +static struct BurnRomInfo BagmanmcRomDesc[] = { + { "b1.bin", 0x01000, 0xb74c75ee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b2.bin", 0x01000, 0xa7d99916, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b3.bin", 0x01000, 0xc78f5360, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b4.bin", 0x01000, 0xeebd3bd1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b5.bin", 0x01000, 0x0fe24b8c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b6.bin", 0x01000, 0xf50390e7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "g1-u.bin", 0x01000, 0xb63cfae4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g2-u.bin", 0x01000, 0xa2790089, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g1-l.bin", 0x00800, 0x2ae6b5ab, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g2-l.bin", 0x00800, 0x98b37397, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "bagmanmc.clr", 0x00020, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Bagmanmc) +STD_ROM_FN(Bagmanmc) + +static struct BurnRomInfo DkongjrmRomDesc[] = { + { "a1", 0x01000, 0x299486e9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "a2", 0x01000, 0xa74a193b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b2", 0x01000, 0x7bc4f236, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "c1", 0x01000, 0x0f594c21, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "d1", 0x01000, 0xcf7d7296, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "e2", 0x01000, 0xf7528a52, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "f1", 0x01000, 0x9b1d4cc5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "v_3pa.bin", 0x01000, 0x4974ffef, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "a2.gfx", 0x01000, 0x51845eaf, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "v_3na.bin", 0x01000, 0xa95c4c63, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "b2.gfx", 0x01000, 0x7b39c3d0, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "hustler.clr", 0x00020, 0xaa1f7f5e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Dkongjrm) +STD_ROM_FN(Dkongjrm) + +static struct BurnRomInfo VpoolRomDesc[] = { + { "vidpool1.bin", 0x01000, 0x333f4732, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vidpool2.bin", 0x01000, 0xeea6c0f1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vidpool3.bin", 0x01000, 0x309972a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vidpool4.bin", 0x01000, 0xc4f71c1d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hustler.5f", 0x00800, 0x0bdfad0e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hustler.5h", 0x00800, 0x8e062177, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "hustler.clr", 0x00020, 0xaa1f7f5e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Vpool) +STD_ROM_FN(Vpool) + +static struct BurnRomInfo CkonggRomDesc[] = { + { "g_ck1.bin", 0x01000, 0xa4323b94, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ck2.bin", 0x01000, 0x1e532996, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ck3.bin", 0x01000, 0x65157cde, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ck4.bin", 0x01000, 0x43827bc6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ck5.bin", 0x01000, 0xa74ed96e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ck7.bin", 0x00800, 0x2c4d8129, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ckvid10.bin", 0x01000, 0x7866d2cb, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ckvid7.bin", 0x01000, 0x7311a101, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "ck_cp.bin", 0x00020, 0x7e0b79cb, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Ckongg) +STD_ROM_FN(Ckongg) + +static struct BurnRomInfo CkongmcRomDesc[] = { + { "kc1.bin", 0x01000, 0xa87fc828, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc2.bin", 0x01000, 0x94a13dec, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc3.bin", 0x01000, 0x5efc6705, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc4.bin", 0x01000, 0xac917d66, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc5.bin", 0x00800, 0x5a9ee1ed, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc6.bin", 0x00800, 0xf787431e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "kc7.bin", 0x00800, 0x7a185e31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "kc8carat.bin", 0x01000, 0x7866d2cb, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "kc9carat.bin", 0x01000, 0x7311a101, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "ck_cp.bin", 0x00020, 0x7e0b79cb, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Ckongmc) +STD_ROM_FN(Ckongmc) + +static struct BurnRomInfo PorterRomDesc[] = { + { "port1.bin", 0x01000, 0xbabaf7fe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "port2.bin", 0x01000, 0x8f7eb0e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "port3.bin", 0x01000, 0x683939b5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "port4.bin", 0x01000, 0x6a65d58d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "port5.bin", 0x00800, 0x2978a9aa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "port6.bin", 0x00800, 0x7ecdffb5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "port7.bin", 0x01000, 0x603294f9, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "port8.bin", 0x01000, 0xb66a763d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.6l", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Porter) +STD_ROM_FN(Porter) + +UINT8 __fastcall BagmanmcZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall BagmanmcZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall DkongjrmZ80Read(UINT16 a) +{ + if (a >= 0xa000 && a <= 0xa0ff) { + return GalInput[0] | GalDip[0]; + } + + if (a >= 0xa800 && a <= 0xa8ff) { + return GalInput[1] | GalDip[1]; + } + + if (a >= 0xb000 && a <= 0xb0ff) { + return GalInput[2] | GalDip[2]; + } + + switch (a) { + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall DkongjrmZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: +// case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb000: { + GalGfxBank[0] = d; + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall CkonggZ80Read(UINT16 a) +{ + switch (a) { + case 0xc000: { + return GalInput[0] | GalDip[0]; + } + + case 0xc400: { + return GalInput[1] | GalDip[1]; + } + + case 0xc800: { + return GalInput[2] | GalDip[2]; + } + + case 0xcc00: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall CkonggZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xc400: + case 0xc401: + case 0xc402: + case 0xc403: + case 0xc404: + case 0xc405: + case 0xc406: + case 0xc407: { + GalaxianSoundWrite(a - 0xc400, d); + return; + } + + case 0xc801: { + GalIrqFire = d & 1; + return; + } + + case 0xc804: { + // link apparently cut + return; + } + + case 0xc806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xc807: { + GalFlipScreenY = d & 1; + return; + } + + case 0xcc00: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall CkongmcZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall CkongmcZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xc806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xc807: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void SkybaseAlterZ80() +{ + MapMooncrst(); + + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetClose(); +} + +static INT32 SkybaseInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = SkybaseAlterZ80; + + nRet = GalInit(); + + GalExtendTileInfoFunction = SkybaseExtendTileInfo; + GalExtendSpriteInfoFunction = SkybaseExtendSpriteInfo; + + return nRet; +} + +static void BagmanmcPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(BagmanmcZ80Read); + ZetSetWriteHandler(BagmanmcZ80Write); + ZetMapArea(0x0000, GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x6000, 0x67ff, 0, GalZ80Ram1); + ZetMapArea(0x6000, 0x67ff, 1, GalZ80Ram1); + ZetMapArea(0x6000, 0x67ff, 2, GalZ80Ram1); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 BagmanmcInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = BagmanmcPostLoad; + GalPromRomSize = 0x20; + + nRet = GalInit(); + + GalNumChars = 512; + GalNumSprites = 64; + CharPlaneOffsets[1] = GalNumChars * 8 * 8; + SpritePlaneOffsets[1] = GalNumSprites * 16 * 16; + + UINT8 *TempRom = (UINT8*)malloc(0x1000); + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x0000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x2000, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x1000, TempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x2800, TempRom + 0x0800, 0x800); + nRet = BurnLoadRom(GalTempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1800, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom + 0x2000, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + HardCodeMooncrstPROM(); + + GalIrqType = GAL_IRQ_TYPE_IRQ0; + GalExtendTileInfoFunction = PiscesExtendTileInfo; + + return nRet; +} + +static void DkongjrmPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(DkongjrmZ80Read); + ZetSetWriteHandler(DkongjrmZ80Write); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x6000, 0x6fff, 0, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 1, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 2, GalZ80Ram1); + ZetMapArea(0x7000, 0x7fff, 0, GalZ80Rom1 + 0x6000); + ZetMapArea(0x7000, 0x7fff, 2, GalZ80Rom1 + 0x6000); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 DkongjrmInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DkongjrmPostLoad; + + nRet = GalInit(); + + GalRenderBackgroundFunction = NULL; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = PiscesExtendTileInfo; + GalExtendSpriteInfoFunction = DkongjrmExtendSpriteInfo; + + GalRenderFrameFunction = DkongjrmRenderFrame; + + return nRet; +} + +static void VpoolPostLoad() +{ + MapMooncrst(); + + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + ZetOpen(0); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetClose(); +} + +static INT32 VpoolInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = VpoolPostLoad; + + nRet = GalInit(); + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void CkonggMapZ80() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(CkonggZ80Read); + ZetSetWriteHandler(CkonggZ80Write); + ZetMapArea(0x0000, 0x57ff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x57ff, 2, GalZ80Rom1); + ZetMapArea(0x6000, 0x6fff, 0, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 1, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 2, GalZ80Ram1); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetClose(); +} + +static void CkonggPostLoad() +{ + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x2400, GalTempRom + 0x0000, 0x400); + memcpy(GalZ80Rom1 + 0x1c00, GalTempRom + 0x0400, 0x400); + memcpy(GalZ80Rom1 + 0x4800, GalTempRom + 0x0800, 0x400); + memcpy(GalZ80Rom1 + 0x0c00, GalTempRom + 0x0c00, 0x400); + memcpy(GalZ80Rom1 + 0x4400, GalTempRom + 0x1000, 0x400); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x1400, 0x400); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x1800, 0x400); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1c00, 0x400); + memcpy(GalZ80Rom1 + 0x3400, GalTempRom + 0x2000, 0x400); + memcpy(GalZ80Rom1 + 0x4c00, GalTempRom + 0x2400, 0x400); + memcpy(GalZ80Rom1 + 0x5000, GalTempRom + 0x2800, 0x400); + memcpy(GalZ80Rom1 + 0x0400, GalTempRom + 0x2c00, 0x400); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x3000, 0x400); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3400, 0x400); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x3800, 0x400); + memcpy(GalZ80Rom1 + 0x4000, GalTempRom + 0x3c00, 0x400); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x4000, 0x400); + memcpy(GalZ80Rom1 + 0x5400, GalTempRom + 0x4400, 0x400); + memcpy(GalZ80Rom1 + 0x2c00, GalTempRom + 0x4800, 0x400); + memcpy(GalZ80Rom1 + 0x1400, GalTempRom + 0x4c00, 0x400); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x5000, 0x400); + memcpy(GalZ80Rom1 + 0x3c00, GalTempRom + 0x5400, 0x400); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + CkonggMapZ80(); +} + +static INT32 CkonggInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CkonggPostLoad; + + nRet = GalInit(); + + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void CkongmcPostLoad() +{ + GalTempRom = (UINT8*)malloc(0x4000); + memcpy(GalTempRom, GalZ80Rom1, 0x4000); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + CkonggMapZ80(); + + ZetOpen(0); + ZetSetReadHandler(CkongmcZ80Read); + ZetSetWriteHandler(CkongmcZ80Write); + ZetClose(); +} + +static INT32 CkongmcInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CkongmcPostLoad; + + nRet = GalInit(); + + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void PorterPostLoad() +{ + GalTempRom = (UINT8*)malloc(0x4000); + memcpy(GalTempRom, GalZ80Rom1, 0x4000); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x0800, 0x800); + memcpy(GalZ80Rom1 + 0x0800, GalTempRom + 0x1000, 0x800); + memcpy(GalZ80Rom1 + 0x2800, GalTempRom + 0x1800, 0x800); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x800); + memcpy(GalZ80Rom1 + 0x3000, GalTempRom + 0x2800, 0x800); + memcpy(GalZ80Rom1 + 0x1800, GalTempRom + 0x3000, 0x800); + memcpy(GalZ80Rom1 + 0x3800, GalTempRom + 0x3800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapMooncrst(); + + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetClose(); +} + +static INT32 PorterInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = PorterPostLoad; + + nRet = GalInit(); + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvSkybase = { + "skybase", NULL, NULL, NULL, "1982", + "Sky Base\0", NULL, "Omori Electric Co. Ltd", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, SkybaseRomInfo, SkybaseRomName, NULL, NULL, SkybaseInputInfo, SkybaseDIPInfo, + SkybaseInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvBagmanmc = { + "bagmanmc", "bagman", NULL, NULL, "1982", + "Bagman (Moon Cresta hardware)\0", "Bad Colours", "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, BagmanmcRomInfo, BagmanmcRomName, NULL, NULL, BagmanmcInputInfo, BagmanmcDIPInfo, + BagmanmcInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDkongjrm = { + "dkongjrm", "dkongjr", NULL, NULL, "1982", + "Donkey Kong Jr. (Moon Cresta hardware)\0", "Bad Colours", "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, DkongjrmRomInfo, DkongjrmRomName, NULL, NULL, DkongjrmInputInfo, DkongjrmDIPInfo, + DkongjrmInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvVpool = { + "vpool", "hustler", NULL, NULL, "1980", + "Video Pool (bootleg on Moon Cresta hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, VpoolRomInfo, VpoolRomName, NULL, NULL, GalaxianInputInfo, VpoolDIPInfo, + VpoolInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCkongg = { + "ckongg", "ckong", NULL, NULL, "1981", + "Crazy Kong (bootleg on Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, CkonggRomInfo, CkonggRomName, NULL, NULL, CkonggInputInfo, CkonggDIPInfo, + CkonggInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCkongmc = { + "ckongmc", "ckong", NULL, NULL, "1981", + "Crazy Kong (bootleg on Moon Cresta hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, CkongmcRomInfo, CkongmcRomName, NULL, NULL, CkongmcInputInfo, CkongmcDIPInfo, + CkongmcInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvPorter = { + "porter", "dockman", NULL, NULL, "19??", + "Port Man (bootleg on Moon Cresta hardware)\0", NULL, "Nova Games Ltd", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, PorterRomInfo, PorterRomName, NULL, NULL, PorterInputInfo, PorterDIPInfo, + PorterInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Custom background +static struct BurnRomInfo RockclimRomDesc[] = { + { "lc01.a1", 0x01000, 0x8601ae8d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lc02.a2", 0x01000, 0x2dde9d4c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lc03.a3", 0x01000, 0x82c48a67, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lc04.a4", 0x01000, 0x7cd3a04a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lc05.a5", 0x01000, 0x5e542149, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lc06.a6", 0x01000, 0xb2bdca64, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "lc08.a9", 0x00800, 0x7f18e1ef, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "lc07.a7", 0x00800, 0xf18b50ac, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "lc10.c9", 0x00800, 0xdec5781b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "lc09.c7", 0x00800, 0x06c0b5de, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "lc11.f4", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, + { "lc12.e9", 0x00020, 0xf6e76547, BRF_GRA | GAL_ROM_PROM }, + + { "lc13.g5", 0x01000, 0x19475f2b, BRF_GRA }, + { "lc14.g7", 0x01000, 0xcc96d1db, BRF_GRA }, +}; + +STD_ROM_PICK(Rockclim) +STD_ROM_FN(Rockclim) + +UINT8 __fastcall RockclimZ80Read(UINT16 a) +{ + switch (a) { + case 0x8800: { + return GalInput[3] | GalDip[3]; + } + + case 0xa000: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall RockclimZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x4800: { + RockclimScrollX = (RockclimScrollX & 0xff00) | d; + return; + } + + case 0x4801: { + RockclimScrollX = (RockclimScrollX & 0xff) | (d << 8); + return; + } + + case 0x4802: { + RockclimScrollY = (RockclimScrollY & 0xff00) | d; + return; + } + + case 0x4803: { + RockclimScrollY = (RockclimScrollY & 0xff) | (d << 8); + return; + } + + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb000: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void RockclimPostLoad() +{ + MapMooncrst(); + + GalVideoRam2 = (UINT8*)malloc(0x800); + + ZetOpen(0); + ZetSetReadHandler(RockclimZ80Read); + ZetSetWriteHandler(RockclimZ80Write); + ZetMapArea(0x4000, 0x47ff, 0, GalVideoRam2); + ZetMapArea(0x4000, 0x47ff, 1, GalVideoRam2); + ZetMapArea(0x4000, 0x47ff, 2, GalVideoRam2); + ZetMapArea(0x5000, 0x53ff, 0, GalZ80Ram1 + 0x400); + ZetMapArea(0x5000, 0x53ff, 1, GalZ80Ram1 + 0x400); + ZetMapArea(0x5000, 0x53ff, 2, GalZ80Ram1 + 0x400); + ZetMapArea(0x6000, 0x7fff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x6000, 0x7fff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static INT32 RockclimInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = RockclimPostLoad; + RockclimTiles = (UINT8*)malloc(0x100 * 8 * 8); + + nRet = GalInit(); + + INT32 RockclimPlaneOffsets[4] = {4, 0, 0x8004, 0x8000}; + INT32 RockclimCharXOffsets[8] = {3, 2, 1, 0, 11, 10, 9, 8}; + INT32 RockclimCharYOffsets[8] = {0, 16, 32, 48, 64, 80, 96, 112}; + + GalTempRom = (UINT8*)malloc(0x2000); + nRet = BurnLoadRom(GalTempRom + 0x0000, 12, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, 13, 1); if (nRet) return 1; + GfxDecode(256, 4, 8, 8, RockclimPlaneOffsets, RockclimCharXOffsets, RockclimCharYOffsets, 0x80, GalTempRom, RockclimTiles); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalCalcPaletteFunction = RockclimCalcPalette; + GalRenderBackgroundFunction = RockclimDrawBackground; + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = RockclimExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvRockclim = { + "rockclim", NULL, NULL, NULL, "1981", + "Rock Climber\0", NULL, "Taito", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, RockclimRomInfo, RockclimRomName, NULL, NULL, RockclimInputInfo, RockclimDIPInfo, + RockclimInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +// Extra roms and sound hardware replaced with AY8910 +static struct BurnRomInfo JumpbugRomDesc[] = { + { "jb1", 0x01000, 0x415aa1b7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb2", 0x01000, 0xb1c27510, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb3", 0x01000, 0x97c24be2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb4", 0x01000, 0x66751d12, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb5", 0x01000, 0xe2d66faf, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb6", 0x01000, 0x49e0bdfd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb7", 0x00800, 0x83d71302, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "jbl", 0x00800, 0x9a091b0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbm", 0x00800, 0x8a0fc082, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbn", 0x00800, 0x155186e0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbi", 0x00800, 0x7749b111, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbj", 0x00800, 0x06e8d7df, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbk", 0x00800, 0xb8dbddf3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Jumpbug) +STD_ROM_FN(Jumpbug) + +static struct BurnRomInfo JumpbugbRomDesc[] = { + { "jb1", 0x01000, 0x415aa1b7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb2", 0x01000, 0xb1c27510, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb3b", 0x01000, 0xcb8b8a0f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb4", 0x01000, 0x66751d12, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb5b", 0x01000, 0x7553b5e2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb6b", 0x01000, 0x47be9843, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "jb7b", 0x00800, 0x460aed61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "jbl", 0x00800, 0x9a091b0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbm", 0x00800, 0x8a0fc082, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbn", 0x00800, 0x155186e0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbi", 0x00800, 0x7749b111, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbj", 0x00800, 0x06e8d7df, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "jbk", 0x00800, 0xb8dbddf3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "l06_prom.bin", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Jumpbugb) +STD_ROM_FN(Jumpbugb) + +static struct BurnRomInfo LeversRomDesc[] = { + { "g96059.a8", 0x01000, 0x9550627a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g96060.d8", 0x01000, 0x5ac64646, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g96061.e8", 0x01000, 0x9db8e520, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g96062.h8", 0x01000, 0x7c8e8b3a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g96063.j8", 0x01000, 0xfa61e793, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "g96064.l8", 0x01000, 0xf797f389, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "g95948.n1", 0x00800, 0xd8a0c692, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g95949.s1", 0x00800, 0x3660a552, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g95946.j1", 0x00800, 0x73b61b2d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g95947.m1", 0x00800, 0x72ff67e2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "g960lev.clr", 0x00020, 0x01febbbe, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Levers) +STD_ROM_FN(Levers) + +static struct BurnRomInfo BongoRomDesc[] = { + { "bg1.bin", 0x01000, 0xde9a8ec6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bg2.bin", 0x01000, 0xa19da662, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bg3.bin", 0x01000, 0x9f6f2150, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bg4.bin", 0x01000, 0xf80372d2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bg5.bin", 0x01000, 0xfc92eade, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "bg6.bin", 0x01000, 0x561d9e5d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "b-h.bin", 0x01000, 0xfc79d103, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "b-k.bin", 0x01000, 0x94d17bf3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "b-clr.bin", 0x00020, 0xc4761ada, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Bongo) +STD_ROM_FN(Bongo) + +void __fastcall BongoZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + // watchdog write? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall BongoZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + return AY8910Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall BongoZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + AY8910Write(0, 0, d); + return; + } + + case 0x01: { + AY8910Write(0, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static INT32 JumpbugInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapJumpbug; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910; + + nRet = GalInit(); + + GalRenderBackgroundFunction = JumpbugDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = JumpbugExtendTileInfo; + GalExtendSpriteInfoFunction = JumpbugExtendSpriteInfo; + + GalSoundVolumeShift = 3; + + return nRet; +} + +static void LeversPostLoad() +{ + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memset(GalZ80Rom1, 0, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x1000); + memcpy(GalZ80Rom1 + 0x2000, GalTempRom + 0x1000, GalZ80Rom1Size - 0x2000); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapJumpbug(); +} + +static INT32 LeversInit() +{ + INT32 nRet; + + GalZ80Rom1Size = 0x1000; + GalTilesSharedRomSize = 0x1000; + + GalPostLoadCallbackFunction = LeversPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1800, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x2800, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = JumpbugDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = JumpbugExtendTileInfo; + GalExtendSpriteInfoFunction = JumpbugExtendSpriteInfo; + + GalSoundVolumeShift = 2; + + return nRet; +} + +static void BongoPostLoad() +{ + MapMooncrst(); + + ZetOpen(0); + ZetSetWriteHandler(BongoZ80Write); + ZetSetInHandler(BongoZ80PortRead); + ZetSetOutHandler(BongoZ80PortWrite); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x8400, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8400, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8400, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0x9400, 0x97ff, 0, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 1, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 2, GalVideoRam); + ZetClose(); +} + +static INT32 BongoInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = BongoPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_BONGOAY8910; + + nRet = GalInit(); + + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + GalSoundVolumeShift = 3; + + return nRet; +} + +struct BurnDriver BurnDrvJumpbug = { + "jumpbug", NULL, NULL, NULL, "1981", + "Jump Bug\0", NULL, "Rock-ola", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, JumpbugRomInfo, JumpbugRomName, NULL, NULL, JumpbugInputInfo, JumpbugDIPInfo, + JumpbugInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvJumpbugb = { + "jumpbugb", "jumpbug", NULL, NULL, "1981", + "Jump Bug (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, JumpbugbRomInfo, JumpbugbRomName, NULL, NULL, JumpbugInputInfo, JumpbugDIPInfo, + JumpbugInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLevers = { + "levers", NULL, NULL, NULL, "1983", + "Levers\0", NULL, "Rock-ola", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, LeversRomInfo, LeversRomName, NULL, NULL, LeversInputInfo, LeversDIPInfo, + LeversInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvBongo = { + "bongo", NULL, NULL, NULL, "1983", + "Bongo\0", NULL, "Jetsoft", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, BongoRomInfo, BongoRomName, NULL, NULL, BongoInputInfo, BongoDIPInfo, + BongoInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Second Z80 driving AY8910 +static struct BurnRomInfo CheckmanRomDesc[] = { + { "cm1", 0x00800, 0xe8cbdd28, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm2", 0x00800, 0xb8432d4d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm3", 0x00800, 0x15a97f61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm4", 0x00800, 0x8c12ecc0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm5", 0x00800, 0x2352cfd6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "cm13", 0x00800, 0x0b09a3e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "cm14", 0x00800, 0x47f043be, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "cm11", 0x00800, 0x8d1bcca0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "cm9", 0x00800, 0x3cd5c751, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "checkman.clr", 0x00020, 0x57a45057, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Checkman) +STD_ROM_FN(Checkman) + +static struct BurnRomInfo CheckmanjRomDesc[] = { + { "cm_1.bin", 0x01000, 0x456a118f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm_2.bin", 0x01000, 0x146b2c44, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cm_3.bin", 0x00800, 0x73e1c945, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "cm_4.bin", 0x01000, 0x923cffa1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "cm_6.bin", 0x00800, 0x476a7cc3, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "cm_5.bin", 0x00800, 0xb3df2b5f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "checkman.clr", 0x00020, 0x57a45057, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Checkmanj) +STD_ROM_FN(Checkmanj) + +static struct BurnRomInfo DingoRomDesc[] = { + { "003.e7", 0x01000, 0xd088550f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "004.h7", 0x01000, 0xa228446a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "005.j7", 0x00800, 0x14d680bb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "6.7l", 0x01000, 0x047092e0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "001.h1", 0x00800, 0x1ab1dd4d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "002.k1", 0x00800, 0x4be375ee, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "18s030.l6", 0x00020, 0x3061d0f9, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Dingo) +STD_ROM_FN(Dingo) + +static struct BurnRomInfo DingoeRomDesc[] = { + { "unk.2b", 0x01000, 0x0df7ac6d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "unk.2d", 0x01000, 0x0881e204, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "unk.3b", 0x01000, 0x0b6aeab5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "unk.1c", 0x00800, 0x8e354c38, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "unk.1d", 0x00800, 0x092878d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "unk.4d", 0x00800, 0x76a00a56, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "unk.4b", 0x00800, 0x5acf57aa, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123n.001", 0x00020, 0x02b11865, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Dingoe) +STD_ROM_FN(Dingoe) + +void __fastcall CheckmanZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + GalSoundLatch = d; + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + } + + bprintf(PRINT_NORMAL, _T("IO Write %x, %x\n"), a, d); +} + +void __fastcall CheckmanZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + } + + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +UINT8 __fastcall CheckmanSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x03: { + return GalSoundLatch; + } + + case 0x06: { + return AY8910Read(0); + } + } + + bprintf(PRINT_NORMAL, _T("Sound IO Read %x\n"), a); + return 0xff; +} + +void __fastcall CheckmanSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x04: { + AY8910Write(0, 0, d); + return; + } + + case 0x05: { + AY8910Write(0, 1, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Sound IO Write %x, %x\n"), a, d); +} + +UINT8 __fastcall CheckmanjZ80Read(UINT16 a) +{ + switch (a) { + case 0x3800: { + switch (ZetPc(-1)) { + case 0x0f15: return 0xf5; + case 0x0f8f: return 0x7c; + case 0x10b3: return 0x7c; + case 0x10e0: return 0x00; + case 0x10f1: return 0xaa; + case 0x1402: return 0xaa; + } + return 0xff; + } + + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: { + return GalInput[2] | GalDip[2]; + } + + case 0x7800: { + // watchdog read + return 0xff; + } + } + + bprintf(PRINT_NORMAL, _T("Prog Read %x\n"), a); + return 0xff; +} + +void __fastcall CheckmanjZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5800 && a <= 0x58ff) { + INT32 Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + // coin_lock_w + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalSoundLatch = d; + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +UINT8 __fastcall CheckmanjSoundZ80Read(UINT16 a) +{ + switch (a) { + case 0xa002: { + return AY8910Read(0); + } + } + + bprintf(PRINT_NORMAL, _T("Sound Prog Read %x\n"), a); + return 0xff; +} + +void __fastcall CheckmanjSoundZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xa000: { + AY8910Write(0, 0, d); + return; + } + + case 0xa001: { + AY8910Write(0, 1, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Sound Prog Write %x, %x\n"), a, d); +} + +UINT8 __fastcall DingoZ80Read(UINT16 a) +{ + switch (a) { + case 0x3000: { + return 0xaa; + } + + case 0x3035: { + return 0x8c; + } + + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: { + return GalInput[2] | GalDip[2]; + } + + case 0x7800: { + // watchdog read + return 0xff; + } + } + + bprintf(PRINT_NORMAL, _T("Prog Read %x\n"), a); + return 0xff; +} + +static void CheckmanInitSoundCPU() +{ + ZetOpen(1); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2); + ZetMapArea(0x2000, 0x23ff, 0, GalZ80Ram2); + ZetMapArea(0x2000, 0x23ff, 1, GalZ80Ram2); + ZetMapArea(0x2000, 0x23ff, 2, GalZ80Ram2); + ZetMemEnd(); + ZetSetInHandler(CheckmanSoundZ80PortRead); + ZetSetOutHandler(CheckmanSoundZ80PortWrite); + ZetClose(); + + nGalCyclesTotal[1] = 1620000 / 60; +} + +static void CheckmanPostLoad() +{ + static const UINT8 XORTable[8][4] = { + { 6, 0, 6, 0 }, + { 5, 1, 5, 1 }, + { 4, 2, 6, 1 }, + { 2, 4, 5, 0 }, + { 4, 6, 1, 5 }, + { 0, 6, 2, 5 }, + { 0, 2, 0, 2 }, + { 1, 4, 1, 4 } + }; + + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 Data = GalZ80Rom1[Offset]; + UINT32 Line = Offset & 0x07; + + Data ^= (BIT(Data, XORTable[Line][0]) << XORTable[Line][1]) | (BIT(Data, XORTable[Line][2]) << XORTable[Line][3]); + GalZ80Rom1[Offset] = Data; + } + + MapMooncrst(); + ZetOpen(0); + ZetSetWriteHandler(CheckmanZ80Write); + ZetSetOutHandler(CheckmanZ80PortWrite); + ZetClose(); + + CheckmanInitSoundCPU(); +} + +static INT32 CheckmanInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CheckmanPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910; + GalTilesSharedRomSize = 0x1000; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + memcpy(GalTempRom + 0x0800, GalTempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1800, GalTempRom + 0x1000, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalExtendTileInfoFunction = MooncrstExtendTileInfo; + GalExtendSpriteInfoFunction = MooncrstExtendSpriteInfo; + + return nRet; +} + +static void CheckmanjInitSoundCPU() +{ + ZetOpen(1); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2); + ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram2); + ZetMemEnd(); + ZetSetReadHandler(CheckmanjSoundZ80Read); + ZetSetWriteHandler(CheckmanjSoundZ80Write); + ZetClose(); + + nGalCyclesTotal[1] = 1620000 / 60; +} + +static void CheckmanjPostLoad() +{ + ZetOpen(0); + ZetSetReadHandler(CheckmanjZ80Read); + ZetSetWriteHandler(CheckmanjZ80Write); + ZetClose(); + + CheckmanjInitSoundCPU(); +} + +static INT32 CheckmanjInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CheckmanjPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910; + + nRet = GalInit(); + + return nRet; +} + +static void DingoPostLoad() +{ + ZetOpen(0); + ZetSetReadHandler(DingoZ80Read); + ZetSetWriteHandler(CheckmanjZ80Write); + ZetMapArea(0x5400, 0x57ff, 0, GalVideoRam); + ZetMapArea(0x5400, 0x57ff, 1, GalVideoRam); + ZetMapArea(0x5400, 0x57ff, 2, GalVideoRam); + ZetClose(); + + CheckmanjInitSoundCPU(); +} + +static INT32 DingoInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DingoPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910; + + nRet = GalInit(); + + GalSoundVolumeShift = 0; + + return nRet; +} + +static void DingoePostLoad() +{ + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 Data = GalZ80Rom1[Offset]; + + Data ^= BIT(Data, 2) << 4; + Data ^= BIT(Data, 5) << 0; + Data ^= 0x02; + + if (Offset & 0x02) Data = BITSWAP08(Data, 7, 6, 5, 0, 3, 2, 1, 4); + GalZ80Rom1[Offset] = Data; + } + + MapMooncrst(); + ZetOpen(0); + ZetSetWriteHandler(CheckmanZ80Write); + ZetSetOutHandler(CheckmanZ80PortWrite); + ZetClose(); + + CheckmanInitSoundCPU(); +} + +static INT32 DingoeInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DingoePostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910; + + nRet = GalInit(); + + return nRet; +} + +struct BurnDriver BurnDrvCheckman = { + "checkman", NULL, NULL, NULL, "1982", + "Check Man\0", NULL, "Zilex-Zenitone", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, CheckmanRomInfo, CheckmanRomName, NULL, NULL, CheckmanInputInfo, CheckmanDIPInfo, + CheckmanInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCheckmanj = { + "checkmanj", "checkman", NULL, NULL, "1982", + "Check Man (Japan)\0", NULL, "Jaleco", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, CheckmanjRomInfo, CheckmanjRomName, NULL, NULL, CheckmanjInputInfo, CheckmanjDIPInfo, + CheckmanjInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDingo = { + "dingo", NULL, NULL, NULL, "1983", + "Dingo\0", NULL, "Ashby Computers and Graphics LTD. (Jaleco license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, DingoRomInfo, DingoRomName, NULL, NULL, DingoInputInfo, DingoDIPInfo, + DingoInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvDingoe = { + "dingoe", "dingo", NULL, NULL, "1983", + "Dingo (encrypted)\0", "Encrypted", "Ashby Computers and Graphics LTD. (Jaleco license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, DingoeRomInfo, DingoeRomName, NULL, NULL, DingoInputInfo, DingoDIPInfo, + DingoeInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Crazy climber sound plus AY8910, and INT instead of NMI +static struct BurnRomInfo MshuttleRomDesc[] = { + { "my05", 0x01000, 0x83574af1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my04", 0x01000, 0x1cfae2c8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my03", 0x01000, 0xc8b8a368, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my02", 0x01000, 0xb6aeee6e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my01", 0x01000, 0xdef82adc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "my09", 0x01000, 0x3601b380, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my11", 0x00800, 0xb659e932, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my08", 0x01000, 0x992b06cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my10", 0x00800, 0xd860e6ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mscprom1.bin", 0x00020, 0xea0d1af0, BRF_GRA | GAL_ROM_PROM }, + + { "my07", 0x01000, 0x522a2920, BRF_SND | BRF_OPT }, // Samples + { "my06", 0x01000, 0x466415f2, BRF_SND | BRF_OPT }, +}; + +STD_ROM_PICK(Mshuttle) +STD_ROM_FN(Mshuttle) + +static struct BurnRomInfo Mshuttle2RomDesc[] = { + { "my05", 0x01000, 0x83574af1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my04", 0x01000, 0x1cfae2c8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my03", 0x01000, 0xc8b8a368, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my02", 0x01000, 0x9804061c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "my01", 0x01000, 0xca746a61, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "my09", 0x01000, 0x3601b380, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my11", 0x00800, 0xd860e6ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my08", 0x01000, 0x992b06cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my10", 0x00800, 0xd860e6ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mscprom1.bin", 0x00020, 0xea0d1af0, BRF_GRA | GAL_ROM_PROM }, + + { "my07", 0x01000, 0x522a2920, BRF_SND | BRF_OPT }, // Samples + { "my06", 0x01000, 0x6d2dd711, BRF_SND | BRF_OPT }, +}; + +STD_ROM_PICK(Mshuttle2) +STD_ROM_FN(Mshuttle2) + +static struct BurnRomInfo MshuttlejRomDesc[] = { + { "mcs.5", 0x01000, 0xa5a292b4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.4", 0x01000, 0xacdc0f9e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.3", 0x01000, 0xc1e3f5d8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.2", 0x01000, 0x14577703, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.1", 0x01000, 0x27d46772, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "my09", 0x01000, 0x3601b380, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my11", 0x00800, 0xb659e932, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my08", 0x01000, 0x992b06cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my10", 0x00800, 0xd860e6ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mscprom1.bin", 0x00020, 0xea0d1af0, BRF_GRA | GAL_ROM_PROM }, + + { "my07", 0x01000, 0x522a2920, BRF_SND | BRF_OPT }, // Samples + { "my06", 0x01000, 0x6d2dd711, BRF_SND | BRF_OPT }, +}; + +STD_ROM_PICK(Mshuttlej) +STD_ROM_FN(Mshuttlej) + +static struct BurnRomInfo Mshuttlej2RomDesc[] = { + { "ali5.bin", 0x01000, 0x320fe630, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.4", 0x01000, 0xacdc0f9e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mcs.3", 0x01000, 0xc1e3f5d8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali2.bin", 0x01000, 0x9ed169e1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ali1.bin", 0x01000, 0x7f8a52d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "my09", 0x01000, 0x3601b380, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my11", 0x00800, 0xb659e932, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my08", 0x01000, 0x992b06cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "my10", 0x00800, 0xd860e6ce, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mscprom1.bin", 0x00020, 0xea0d1af0, BRF_GRA | GAL_ROM_PROM }, + + { "my07", 0x01000, 0x522a2920, BRF_SND | BRF_OPT }, // Samples + { "my06.4r", 0x01000, 0x4162be4d, BRF_SND | BRF_OPT }, +}; + +STD_ROM_PICK(Mshuttlej2) +STD_ROM_FN(Mshuttlej2) + +UINT8 __fastcall MshuttleZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x0c: { + if (!MshuttleAY8910CS) return AY8910Read(0); + return 0xff; + } + } + + bprintf(PRINT_NORMAL, _T("IO Read %x\n"), a); + return 0xff; +} + +void __fastcall MshuttleZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x08: { + if (!MshuttleAY8910CS) AY8910Write(0, 0, d); + return; + } + + case 0x09: { + if (!MshuttleAY8910CS) AY8910Write(0, 1, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("IO Write %x, %x\n"), a, d); +} + +void __fastcall MshuttleZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: { + GalIrqFire = d & 1; + return; + } + + case 0xa001: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xa002: { + GalFlipScreenX = d & 1; + GalFlipScreenY = d & 1; + return; + } + + case 0xa004: { + // cclimber_sample_trigger_w + return; + } + + case 0xa007: { + MshuttleAY8910CS = d & 1; + return; + } + + case 0xa800: { + // cclimber_sample_rate_w + return; + } + + case 0xb000: { + // cclimber_sample_volume_w + return; + } + } + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +static void MapMshuttle() +{ + MapMooncrst(); + ZetOpen(0); + ZetMapArea(0x0000, 0x4fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x4fff, 2, GalZ80Rom1Op, GalZ80Rom1); + ZetSetWriteHandler(MshuttleZ80Write); + ZetSetInHandler(MshuttleZ80PortRead); + ZetSetOutHandler(MshuttleZ80PortWrite); + ZetClose(); +} + +static void MshuttleDecrypt() +{ + GalZ80Rom1Op = (UINT8*)malloc(GalZ80Rom1Size); + + static const UINT8 ConvTable[8][16] = { + { 0x40, 0x41, 0x44, 0x15, 0x05, 0x51, 0x54, 0x55, 0x50, 0x00, 0x01, 0x04, (UINT8)-1, 0x10, 0x11, 0x14 }, + { 0x45, 0x51, 0x55, 0x44, 0x40, 0x11, 0x05, 0x41, 0x10, 0x14, 0x54, 0x50, 0x15, 0x04, 0x00, 0x01 }, + { 0x11, 0x14, 0x10, 0x00, 0x44, 0x05, (UINT8)-1, 0x04, 0x45, 0x15, 0x55, 0x50, (UINT8)-1, 0x01, 0x54, 0x51 }, + { 0x14, 0x01, 0x11, 0x10, 0x50, 0x15, 0x00, 0x40, 0x04, 0x51, 0x45, 0x05, 0x55, 0x54, (UINT8)-1, 0x44 }, + { 0x04, 0x10, (UINT8)-1, 0x40, 0x15, 0x41, 0x50, 0x50, 0x11, (UINT8)-1, 0x14, 0x00, 0x51, 0x45, 0x55, 0x01 }, + { 0x44, 0x45, 0x00, 0x51, (UINT8)-1, (UINT8)-1, 0x15, 0x11, 0x01, 0x10, 0x04, 0x55, 0x05, 0x40, 0x50, 0x41 }, + { 0x51, 0x00, 0x01, 0x05, 0x04, 0x55, 0x54, 0x50, 0x41, (UINT8)-1, 0x11, 0x15, 0x14, 0x10, 0x44, 0x40 }, + { 0x05, 0x04, 0x51, 0x01, (UINT8)-1, (UINT8)-1, 0x55, (UINT8)-1, 0x00, 0x50, 0x15, 0x14, 0x44, 0x41, 0x40, 0x54 }, + }; + + for (UINT32 Offset = 0x0000; Offset < GalZ80Rom1Size; Offset++) { + INT32 i, j; + UINT8 Src; + + Src = GalZ80Rom1[Offset]; + i = (Offset & 1) | (Src & 0x02) | ((Src & 0x80) >> 5); + j = (Src & 0x01) | ((Src & 0x04) >> 1) | ((Src & 0x10) >> 2) | ((Src & 0x40) >> 3); + + GalZ80Rom1Op[Offset] = (Src & 0xaa) | ConvTable[i][j]; + } + + MapMshuttle(); +} + +static void MShuttleCommonInit() +{ + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + BurnLoadRom(GalTempRom + 0x2000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); + BurnLoadRom(GalTempRom + 0x3000, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalDrawBulletsFunction = MshuttleDrawBullets; + GalExtendTileInfoFunction = MshuttleExtendTileInfo; + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + GalIrqType = GAL_IRQ_TYPE_IRQ0; +} + +static INT32 MshuttleInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MshuttleDecrypt; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910; + GalTilesSharedRomSize = 0x1000; + + nRet = GalInit(); + + MShuttleCommonInit(); + + return nRet; +} + +static void MshuttlejDecrypt() +{ + GalZ80Rom1Op = (UINT8*)malloc(GalZ80Rom1Size); + + static const UINT8 ConvTable[8][16] = { + { 0x41, 0x54, 0x51, 0x14, 0x05, 0x10, 0x01, 0x55, 0x44, 0x11, 0x00, 0x50, 0x15, 0x40, 0x04, 0x45 }, + { 0x50, 0x11, 0x40, 0x55, 0x51, 0x14, 0x45, 0x04, 0x54, 0x15, 0x10, 0x05, 0x44, 0x01, 0x00, 0x41 }, + { 0x44, 0x11, 0x00, 0x50, 0x41, 0x54, 0x04, 0x14, 0x15, 0x40, 0x51, 0x55, 0x05, 0x10, 0x01, 0x45 }, + { 0x10, 0x50, 0x54, 0x55, 0x01, 0x44, 0x40, 0x04, 0x14, 0x11, 0x00, 0x41, 0x45, 0x15, 0x51, 0x05 }, + { 0x14, 0x41, 0x01, 0x44, 0x04, 0x50, 0x51, 0x45, 0x11, 0x40, 0x54, 0x15, 0x10, 0x00, 0x55, 0x05 }, + { 0x01, 0x05, 0x41, 0x45, 0x54, 0x50, 0x55, 0x10, 0x11, 0x15, 0x51, 0x14, 0x44, 0x40, 0x04, 0x00 }, + { 0x05, 0x55, 0x00, 0x50, 0x11, 0x40, 0x54, 0x14, 0x45, 0x51, 0x10, 0x04, 0x44, 0x01, 0x41, 0x15 }, + { 0x55, 0x50, 0x15, 0x10, 0x01, 0x04, 0x41, 0x44, 0x45, 0x40, 0x05, 0x00, 0x11, 0x14, 0x51, 0x54 }, + }; + + for (UINT32 Offset = 0x0000; Offset < GalZ80Rom1Size; Offset++) { + INT32 i, j; + UINT8 Src; + + Src = GalZ80Rom1[Offset]; + i = (Offset & 1) | (Src & 0x02) | ((Src & 0x80) >> 5); + j = (Src & 0x01) | ((Src & 0x04) >> 1) | ((Src & 0x10) >> 2) | ((Src & 0x40) >> 3); + + GalZ80Rom1Op[Offset] = (Src & 0xaa) | ConvTable[i][j]; + } + + MapMshuttle(); +} + +static INT32 MshuttlejInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MshuttlejDecrypt; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910; + GalTilesSharedRomSize = 0x1000; + + nRet = GalInit(); + + MShuttleCommonInit(); + + return nRet; +} + +struct BurnDriver BurnDrvMshuttle = { + "mshuttle", NULL, NULL, NULL, "1981", + "Moon Shuttle (US?)\0", "Incomplete Sound", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MshuttleRomInfo, MshuttleRomName, NULL, NULL, MshuttleInputInfo, MshuttleDIPInfo, + MshuttleInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMshuttle2 = { + "mshuttle2", "mshuttle", NULL, NULL, "1981", + "Moon Shuttle (US? set 2)\0", "Incomplete Sound", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Mshuttle2RomInfo, Mshuttle2RomName, NULL, NULL, MshuttleInputInfo, MshuttleDIPInfo, + MshuttleInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMshuttlej = { + "mshuttlej", "mshuttle", NULL, NULL, "1981", + "Moon Shuttle (Japan)\0", "Incomplete Sound", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, MshuttlejRomInfo, MshuttlejRomName, NULL, NULL, MshuttleInputInfo, MshuttleDIPInfo, + MshuttlejInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMshuttlej2 = { + "mshuttlej2", "mshuttle", NULL, NULL, "1981", + "Moon Shuttle (Japan set 2)\0", "Incomplete Sound", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, Mshuttlej2RomInfo, Mshuttlej2RomName, NULL, NULL, MshuttleInputInfo, MshuttleDIPInfo, + MshuttlejInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +// Second Z80 driving DAC +static struct BurnRomInfo KingballRomDesc[] = { + { "prg1.7f", 0x01000, 0x6cb49046, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg2.7j", 0x01000, 0xc223b416, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg3.7l", 0x00800, 0x453634c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "kbe1.ic4", 0x00800, 0x5be2c80a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbe2.ic5", 0x00800, 0xbb59e965, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbe3.ic6", 0x00800, 0x1c94dd31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbe2.ic7", 0x00800, 0xbb59e965, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "chg1.1h", 0x00800, 0x9cd550e7, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "chg2.1k", 0x00800, 0xa206757d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "kb2-1", 0x00020, 0x15dd5b16, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Kingball) +STD_ROM_FN(Kingball) + +static struct BurnRomInfo KingballjRomDesc[] = { + { "prg1.7f", 0x01000, 0x6cb49046, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg2.7j", 0x01000, 0xc223b416, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg3.7l", 0x00800, 0x453634c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "kbj1.ic4", 0x00800, 0xba16beb7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbj2.ic5", 0x00800, 0x56686a63, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbj3.ic6", 0x00800, 0xfbc570a5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "kbj2.ic7", 0x00800, 0x56686a63, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "chg1.1h", 0x00800, 0x9cd550e7, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "chg2.1k", 0x00800, 0xa206757d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "kb2-1", 0x00020, 0x15dd5b16, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Kingballj) +STD_ROM_FN(Kingballj) + +UINT8 __fastcall KingballZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + if (KingballSpeechDip) { + return GalInput[0] | GalDip[0] | ((GalFakeDip & 0x02) ? 0x40 : 0x00); + } else { + return GalInput[0] | GalDip[0] | ((GalFakeDip & 0x01) ? 0x40 : 0x00); + } + } + + case 0xa800: { + return ((GalInput[1] | GalDip[1]) & ~0x20) | (rand() & 0x20); + } + + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall KingballZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb000: { + KingballSound = (KingballSound & ~0x01) | d; + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb002: { + KingballSound = (KingballSound & ~0x02) | (d << 1); + GalSoundLatch = KingballSound | 0xf0; + return; + } + + case 0xb003: { + KingballSpeechDip = d; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KingballSoundZ80Read(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall KingballSoundZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KingballSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return GalSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall KingballSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DACWrite(0, d ^ 0xff); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static void KingballPostLoad() +{ + MapMooncrst(); + + ZetOpen(0); + ZetSetReadHandler(KingballZ80Read); + ZetSetWriteHandler(KingballZ80Write); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(KingballSoundZ80Read); + ZetSetWriteHandler(KingballSoundZ80Write); + ZetSetInHandler(KingballSoundZ80PortRead); + ZetSetOutHandler(KingballSoundZ80PortWrite); + ZetMapArea(0x0000, 0x1fff, 0, GalZ80Rom2); + ZetMapArea(0x0000, 0x1fff, 2, GalZ80Rom2); + ZetMemEnd(); + ZetClose(); + + nGalCyclesTotal[1] = (5000000 / 2) / 60; +} + +static INT32 KingballInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = KingballPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC; + GalTilesSharedRomSize = 0x1000; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + memcpy(GalTempRom + 0x0800, GalTempRom + 0x0000, 0x800); + memcpy(GalTempRom + 0x1800, GalTempRom + 0x1000, 0x800); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + return nRet; +} + +struct BurnDriver BurnDrvKingball = { + "kingball", NULL, NULL, NULL, "1980", + "King & Balloon (US)\0", NULL, "Namco", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, KingballRomInfo, KingballRomName, NULL, NULL, KingballInputInfo, KingballDIPInfo, + KingballInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvKingballj = { + "kingballj", "kingball", NULL, NULL, "1980", + "King & Balloon (Japan)\0", NULL, "Namco", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, KingballjRomInfo, KingballjRomName, NULL, NULL, KingballInputInfo, KingballDIPInfo, + KingballInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Frogger based hardware +static struct BurnRomInfo FroggerRomDesc[] = { + { "frogger.26", 0x01000, 0x597696d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "frogger.27", 0x01000, 0xb6e6fcc3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "frsm3.7", 0x01000, 0xaca22ae0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "frogger.608", 0x00800, 0xe8ab0256, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.609", 0x00800, 0x7380a48f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.610", 0x00800, 0x31d7eb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "frogger.607", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "frogger.606", 0x00800, 0xf524ee30, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Frogger) +STD_ROM_FN(Frogger) + +static struct BurnRomInfo Froggers1RomDesc[] = { + { "frogger.26", 0x01000, 0x597696d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "frogger.27", 0x01000, 0xb6e6fcc3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "frogger.34", 0x01000, 0xed866bab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr-608.ic32", 0x00800, 0xe8ab0256, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr-609.ic33", 0x00800, 0x7380a48f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr-610.ic34", 0x00800, 0x31d7eb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr-607.ic101", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr-606.ic102", 0x00800, 0xf524ee30, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Froggers1) +STD_ROM_FN(Froggers1) + +static struct BurnRomInfo Froggers2RomDesc[] = { + { "epr-1012.ic5", 0x01000, 0xefab0c79, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1013a.ic6", 0x01000, 0xaeca9c13, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1014.ic7", 0x01000, 0xdd251066, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1015.ic8", 0x01000, 0xbf293a02, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr-608.ic32", 0x00800, 0xe8ab0256, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr-609.ic33", 0x00800, 0x7380a48f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr-610.ic34", 0x00800, 0x31d7eb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr-607.ic101", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr-606.ic102", 0x00800, 0xf524ee30, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Froggers2) +STD_ROM_FN(Froggers2) + +static struct BurnRomInfo FroggermcRomDesc[] = { + { "epr-1031.15", 0x01000, 0x4b7c8d11, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1032.16", 0x01000, 0xac00b9d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1033.33", 0x01000, 0xbc1d6fbc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr-1034.34", 0x01000, 0x9efe7399, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr-1082.42", 0x01000, 0x802843c2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr-1035.43", 0x00800, 0x14e74148, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr-1037.1h", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr-1036.1k", 0x00800, 0x658745f8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Froggermc) +STD_ROM_FN(Froggermc) + +static struct BurnRomInfo FroggersRomDesc[] = { + { "vid_d2.bin", 0x00800, 0xc103066e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_e2.bin", 0x00800, 0xf08bc094, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_f2.bin", 0x00800, 0x637a2ff8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_h2.bin", 0x00800, 0x04c027a5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_j2.bin", 0x00800, 0xfbdfbe74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_l2.bin", 0x00800, 0x8a4389e1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "frogger.608", 0x00800, 0xe8ab0256, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.609", 0x00800, 0x7380a48f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.610", 0x00800, 0x31d7eb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "frogger.607", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr-1036.1k", 0x00800, 0x658745f8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Froggers) +STD_ROM_FN(Froggers) + +static struct BurnRomInfo FrogfRomDesc[] = { + { "6.bin", 0x01000, 0x8ff0a973, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7.bin", 0x01000, 0x3087bb4b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.bin", 0x01000, 0xc3869d12, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "frogger.608", 0x00800, 0xe8ab0256, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.609", 0x00800, 0x7380a48f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "frogger.610", 0x00800, 0x31d7eb27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "frogger.607", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr-1036.1k", 0x00800, 0x658745f8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Frogf) +STD_ROM_FN(Frogf) + +static struct BurnRomInfo FroggRomDesc[] = { + { "p1.bin", 0x00800, 0x1762b266, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p2.bin", 0x00800, 0x322f3916, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p3.bin", 0x00800, 0x28bd6151, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p4.bin", 0x00800, 0x5a69ab18, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p5.bin", 0x00800, 0xb4f17745, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p6.bin", 0x00800, 0x34be71b5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p7.bin", 0x00800, 0xde3edc8c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "k.bin", 0x00800, 0x05f7d883, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "h.bin", 0x00800, 0x658745f8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr-91.6l", 0x00020, 0x413703bf, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Frogg) +STD_ROM_FN(Frogg) + +void __fastcall FroggermcZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa800: { + GalSoundLatch = d; + return; + } + + case 0xb000: { + GalIrqFire = d & 1; + return; + } + + case 0xb001: { + if (!(d & 1)) { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + } + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall FrogfZ80Read(UINT16 a) +{ + if (a >= 0xc000) { + UINT32 Offset = a - 0xc000; + UINT8 Result = 0xff; + if (Offset & 0x1000) Result &= ppi8255_r(0, (Offset >> 3) & 3); + if (Offset & 0x2000) Result &= ppi8255_r(1, (Offset >> 3) & 3); + return Result; + } + + switch (a) { + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall FrogfZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x90ff) { + INT32 Offset = a - 0x9000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xc000) { + INT32 Offset = a - 0xc000; + if (Offset & 0x1000) ppi8255_w(0, (Offset >> 3) & 3, d); + if (Offset & 0x2000) ppi8255_w(1, (Offset >> 3) & 3, d); + return; + } + + switch (a) { + case 0xa802: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa804: { + GalIrqFire = d & 1; + return; + } + + case 0xa806: { + GalFlipScreenY = d & 1; + return; + } + + case 0xa809: { + // coin_count_1_w + return; + } + + case 0xa80e: { + // coin_count_0_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void FroggerEncGfxPostLoad() +{ + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(GalTempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + for (UINT32 Offset = 0x0800; Offset < 0x1000; Offset++) GalTempRom[Offset] = BITSWAP08(GalTempRom[Offset], 7, 6, 5, 4, 3, 2, 0, 1); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapFrogger(); +} + +static INT32 FroggerEncGfxInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = FroggerEncGfxPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + FroggerAdjust = 1; + + GalRenderBackgroundFunction = FroggerDrawBackground; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = FroggerExtendTileInfo; + GalExtendSpriteInfoFunction = FroggerExtendSpriteInfo; + + KonamiPPIInit(); + + return nRet; +} + +static void FroggermcPostLoad() +{ + MapMooncrst(); + + ZetOpen(0); + ZetSetWriteHandler(FroggermcZ80Write); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetClose(); +} + +static INT32 FroggermcInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = FroggermcPostLoad; +// GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + GalRenderBackgroundFunction = FroggerDrawBackground; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = FroggerExtendTileInfo; + GalExtendSpriteInfoFunction = FroggerExtendSpriteInfo; + + return nRet; +} + +static INT32 FroggersInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTheend; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + KonamiPPIInit(); + + GalRenderBackgroundFunction = FroggerDrawBackground; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = FroggerExtendTileInfo; + GalExtendSpriteInfoFunction = FroggerExtendSpriteInfo; + + return nRet; +} + +static void FrogfPostLoad() +{ + MapFrogger(); + + ZetOpen(0); + ZetSetReadHandler(FrogfZ80Read); + ZetSetWriteHandler(FrogfZ80Write); + ZetMemCallback(0x8800, 0xffff, 0); + ZetMemCallback(0x8800, 0xffff, 1); + ZetMemCallback(0x8800, 0xffff, 2); + ZetMapArea(0x8800, 0x8bff, 0, GalVideoRam); + ZetMapArea(0x8800, 0x8bff, 1, GalVideoRam); + ZetMapArea(0x8800, 0x8bff, 2, GalVideoRam); + ZetMapArea(0x9000, 0x90ff, 0, GalSpriteRam); + ZetMapArea(0x9000, 0x90ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 FrogfInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = FrogfPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + KonamiPPIInit(); + + GalRenderBackgroundFunction = FroggerDrawBackground; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = FroggerExtendTileInfo; + GalExtendSpriteInfoFunction = FroggerExtendSpriteInfo; + + return nRet; +} + +static void FroggPostLoad() +{ + ZetOpen(0); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetClose(); +} + +static INT32 FroggInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = FroggPostLoad; + + nRet = GalInit(); + + GalRenderBackgroundFunction = FroggerDrawBackground; + GalExtendTileInfoFunction = FroggerExtendTileInfo; + GalExtendSpriteInfoFunction = FroggerExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvFrogger = { + "frogger", NULL, NULL, NULL, "1981", + "Frogger\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, FroggerRomInfo, FroggerRomName, NULL, NULL, FroggerInputInfo, FroggerDIPInfo, + FroggerEncGfxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFroggers1 = { + "froggers1", "frogger", NULL, NULL, "1981", + "Frogger (Sega set 1)\0", NULL, "Konami (Sega license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, Froggers1RomInfo, Froggers1RomName, NULL, NULL, FroggerInputInfo, FroggerDIPInfo, + FroggerEncGfxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFroggers2 = { + "froggers2", "frogger", NULL, NULL, "1981", + "Frogger (Sega set 2)\0", NULL, "Konami (Sega license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, Froggers2RomInfo, Froggers2RomName, NULL, NULL, FroggerInputInfo, FroggerDIPInfo, + FroggerEncGfxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFroggermc = { + "froggermc", "frogger", NULL, NULL, "1981", + "Frogger (Moon Cresta hardware)\0", "No Sound", "Konami (Sega license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, FroggermcRomInfo, FroggermcRomName, NULL, NULL, FroggermcInputInfo, FroggermcDIPInfo, + FroggermcInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFroggers = { + "froggers", "frogger", NULL, NULL, "1981", + "Frog\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, FroggersRomInfo, FroggersRomName, NULL, NULL, FroggerInputInfo, FroggerDIPInfo, + FroggersInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFrogf = { + "frogf", "frogger", NULL, NULL, "1981", + "Frog (Falcon bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, FrogfRomInfo, FrogfRomName, NULL, NULL, FroggerInputInfo, FroggerDIPInfo, + FrogfInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFrogg = { + "frogg", "frogger", NULL, NULL, "1981", + "Frog (Galaxian hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, FroggRomInfo, FroggRomName, NULL, NULL, FroggInputInfo, FroggDIPInfo, + FroggInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Turtles based hardware +static struct BurnRomInfo TurtlesRomDesc[] = { + { "turt_vid.2c", 0x01000, 0xec5e61fb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "turt_vid.2e", 0x01000, 0xfd10821e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "turt_vid.2f", 0x01000, 0xddcfc5fa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "turt_vid.2h", 0x01000, 0x9e71696c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "turt_vid.2j", 0x01000, 0xfcd49fef, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "turt_snd.5c", 0x01000, 0xf0c30f9a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "turt_snd.5d", 0x01000, 0xaf5fc43c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "turt_vid.5h", 0x00800, 0xe5999d52, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "turt_vid.5f", 0x00800, 0xc3ffd655, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "turtles.clr", 0x00020, 0xf3ef02dd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Turtles) +STD_ROM_FN(Turtles) + +static struct BurnRomInfo TurpinRomDesc[] = { + { "m1", 0x01000, 0x89177473, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m2", 0x01000, 0x4c6ca5c6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m3", 0x01000, 0x62291652, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "turt_vid.2h", 0x01000, 0x9e71696c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "m5", 0x01000, 0x7d2600f2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "turt_snd.5c", 0x01000, 0xf0c30f9a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "turt_snd.5d", 0x01000, 0xaf5fc43c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "turt_vid.5h", 0x00800, 0xe5999d52, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "turt_vid.5f", 0x00800, 0xc3ffd655, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "turtles.clr", 0x00020, 0xf3ef02dd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Turpin) +STD_ROM_FN(Turpin) + +static struct BurnRomInfo SixhundredRomDesc[] = { + { "600_vid.2c", 0x01000, 0x8ee090ae, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "600_vid.2e", 0x01000, 0x45bfaff2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "600_vid.2f", 0x01000, 0x9f4c8ed7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "600_vid.2h", 0x01000, 0xa92ef056, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "600_vid.2j", 0x01000, 0x6dadd72d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "600_snd.5c", 0x01000, 0x1773c68e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "600_snd.5d", 0x01000, 0xa311b998, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "600_vid.5h", 0x00800, 0x006c3d56, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "600_vid.5f", 0x00800, 0x7dbc0426, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "turtles.clr", 0x00020, 0xf3ef02dd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Sixhundred) +STD_ROM_FN(Sixhundred) + +static struct BurnRomInfo TurpinsRomDesc[] = { + { "t1.bin", 0x01000, 0x89dd50cc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "t3.bin", 0x01000, 0x9562dc29, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "t4.bin", 0x01000, 0x62291652, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "t5.bin", 0x01000, 0x804118e8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "t2.bin", 0x01000, 0x8024f678, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "8tur.bin", 0x01000, 0xc97ed8ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5tur.bin", 0x01000, 0xaf5fc43c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "tur.4f", 0x00800, 0xe5999d52, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tur.5f", 0x00800, 0xc3ffd655, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "turtles.clr", 0x00020, 0xf3ef02dd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Turpins) +STD_ROM_FN(Turpins) + +static struct BurnRomInfo AmidarRomDesc[] = { + { "1.2c", 0x01000, 0x621b74de, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.2e", 0x01000, 0x38538b98, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.2f", 0x01000, 0x099ecb24, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.2h", 0x01000, 0xba149a93, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.2j", 0x01000, 0xeecc1abf, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "s1.5c", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "s2.5d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "c2.5f", 0x00800, 0x2cfe5ede, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "c2.5d", 0x00800, 0x57c4fd0d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidar) +STD_ROM_FN(Amidar) + +static struct BurnRomInfo Amidar1RomDesc[] = { + { "amidar.2c", 0x01000, 0xc294bf27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidar.2e", 0x01000, 0xe6e96826, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidar.2f", 0x01000, 0x3656be6f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidar.2h", 0x01000, 0x1be170bd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "amidar.5c", 0x01000, 0xc4b66ae4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "amidar.5d", 0x01000, 0x806785af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "amidar.5f", 0x00800, 0x5e51e84d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "amidar.5h", 0x00800, 0x2f7f1c30, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidar1) +STD_ROM_FN(Amidar1) + +static struct BurnRomInfo AmidaruRomDesc[] = { + { "amidarus.2c", 0x01000, 0x951e0792, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidarus.2e", 0x01000, 0xa1a3a136, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidarus.2f", 0x01000, 0xa5121bf5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidarus.2h", 0x01000, 0x051d1c7f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "amidarus.2j", 0x01000, 0x351f00d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "amidarus.5c", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "amidarus.5d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "amidarus.5f", 0x00800, 0x2cfe5ede, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "amidarus.5h", 0x00800, 0x57c4fd0d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidaru) +STD_ROM_FN(Amidaru) + +static struct BurnRomInfo AmidaroRomDesc[] = { + { "107.2cd", 0x01000, 0xc52536be, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "108.2fg", 0x01000, 0x38538b98, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "109.2fg", 0x01000, 0x69907f0f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "110.2h", 0x01000, 0xba149a93, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "111.2j", 0x01000, 0x20d01c2e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "amidarus.5c", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "amidarus.5d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "amidarus.5f", 0x00800, 0x2cfe5ede, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "113.5h", 0x00800, 0xbcdce168, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidaro) +STD_ROM_FN(Amidaro) + +static struct BurnRomInfo AmidarbRomDesc[] = { + { "ami2gor.2c", 0x01000, 0x9ad2dcd2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.2f", 0x01000, 0x66282ff5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.2j", 0x01000, 0xb0860e31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.2m", 0x01000, 0x4a4086c9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "8.11d", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "9.9d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5.5f", 0x00800, 0x2082ad0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "6.5h", 0x00800, 0x3029f94f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "n82s123n.6e", 0x00020, 0x01004d3f, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidarb) +STD_ROM_FN(Amidarb) + +static struct BurnRomInfo AmigoRomDesc[] = { + { "2732.a1", 0x01000, 0x930dc856, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2732.a2", 0x01000, 0x66282ff5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2732.a3", 0x01000, 0xe9d3dc76, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2732.a4", 0x01000, 0x4a4086c9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "amidarus.5c", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "amidarus.5d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "2716.a6", 0x00800, 0x2082ad0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "2716.a5", 0x00800, 0x3029f94f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amigo) +STD_ROM_FN(Amigo) + +static struct BurnRomInfo AmidarsRomDesc[] = { + { "am2d", 0x00800, 0x24b79547, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2e", 0x00800, 0x4c64161e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2f", 0x00800, 0xb3987a72, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2h", 0x00800, 0x29873461, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2j", 0x00800, 0x0fdd54d8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2l", 0x00800, 0x5382f7ed, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2m", 0x00800, 0x1d7109e9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "am2p", 0x00800, 0xc9163ac6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "amidarus.5c", 0x01000, 0x8ca7b750, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "amidarus.5d", 0x01000, 0x9b5bdc0a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "2716.a6", 0x00800, 0x2082ad0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "2716.a5", 0x00800, 0x3029f94f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "amidar.clr", 0x00020, 0xf940dcc3, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Amidars) +STD_ROM_FN(Amidars) + +UINT8 __fastcall TurpinsZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + return 0xff - GalInput[0] - GalDip[0]; + } + + case 0xa001: { + return 0xff - GalInput[1] - GalDip[1]; + } + + case 0xa002: { + return 0xff - GalInput[2] - GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall TurpinsZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: { + GalBackgroundRed = d & 1; + return; + } + + case 0xa020: { + GalBackgroundGreen = d & 1; + return; + } + + case 0xa028: { + GalBackgroundBlue = d & 1; + return; + } + + + case 0xa030: { + // coin_count_0_w + return; + } + + case 0xa038: { + // coin_count_1_w + return; + } + + + case 0xa801: { + GalIrqFire = d & 1; + return; + } + + case 0xa806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 TurtlesInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTurtles; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = TurtlesDrawBackground; + GalDrawBulletsFunction = NULL; + + KonamiPPIInit(); + + return nRet; +} + +static void TurpinsPostLoad() +{ + MapTurtles(); + + ZetOpen(0); + ZetSetReadHandler(TurpinsZ80Read); + ZetSetWriteHandler(TurpinsZ80Write); + ZetClose(); +} + +static INT32 TurpinsInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = TurpinsPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = TurtlesDrawBackground; + GalDrawBulletsFunction = NULL; + + return nRet; +} + +struct BurnDriver BurnDrvTurtles = { + "turtles", NULL, NULL, NULL, "1981", + "Turtles\0", NULL, "Konami (Stern license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TurtlesRomInfo, TurtlesRomName, NULL, NULL, TurtlesInputInfo, TurtlesDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTurpin = { + "turpin", "turtles", NULL, NULL, "1981", + "Turpin\0", NULL, "Konami (Sega license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TurpinRomInfo, TurpinRomName, NULL, NULL, TurtlesInputInfo, TurpinDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSixhundred = { + "600", "turtles", NULL, NULL, "1981", + "600\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, SixhundredRomInfo, SixhundredRomName, NULL, NULL, TurtlesInputInfo, TurtlesDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTurpins = { + "turpins", "turtles", NULL, NULL, "1981", + "Turpin (bootleg on Scramble hardware)\0", "No Sound", "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TurpinsRomInfo, TurpinsRomName, NULL, NULL, TurtlesInputInfo, TurtlesDIPInfo, + TurpinsInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidar = { + "amidar", NULL, NULL, NULL, "1981", + "Amidar\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmidarRomInfo, AmidarRomName, NULL, NULL, AmidarInputInfo, AmidaruDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidar1 = { + "amidar1", "amidar", NULL, NULL, "1981", + "Amidar (older)\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Amidar1RomInfo, Amidar1RomName, NULL, NULL, AmidarInputInfo, AmidarDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidaru = { + "amidaru", "amidar", NULL, NULL, "1982", + "Amidar (Stern)\0", NULL, "Konami (Stern license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmidaruRomInfo, AmidaruRomName, NULL, NULL, AmidarInputInfo, AmidaruDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidaro = { + "amidaro", "amidar", NULL, NULL, "1982", + "Amidar (Olympia)\0", NULL, "Konami (Olympia license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmidaroRomInfo, AmidaroRomName, NULL, NULL, AmidarInputInfo, AmidaroDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidarb = { + "amidarb", "amidar", NULL, NULL, "1982", + "Amidar (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmidarbRomInfo, AmidarbRomName, NULL, NULL, AmidarInputInfo, AmidaruDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmigo = { + "amigo", "amidar", NULL, NULL, "1982", + "Amigo\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmigoRomInfo, AmigoRomName, NULL, NULL, AmidarInputInfo, AmidaruDIPInfo, + TurtlesInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAmidars = { + "amidars", "amidar", NULL, NULL, "1982", + "Amidar (Scramble hardware)\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AmidarsRomInfo, AmidarsRomName, NULL, NULL, AmidarInputInfo, AmidarsDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// The End / Scramble based hardware +static struct BurnRomInfo TheendRomDesc[] = { + { "ic13_1t.bin", 0x00800, 0x93e555ba, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic14_2t.bin", 0x00800, 0x2de7ad27, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic15_3t.bin", 0x00800, 0x035f750b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic16_4t.bin", 0x00800, 0x61286b5c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic17_5t.bin", 0x00800, 0x434a8f68, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic18_6t.bin", 0x00800, 0xdc4cc786, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ic56_1.bin", 0x00800, 0x7a141f29, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ic55_2.bin", 0x00800, 0x218497c1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ic30_2c.bin", 0x00800, 0x68ccf7bf, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ic31_1c.bin", 0x00800, 0x4a48c999, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6331-1j.86", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Theend) +STD_ROM_FN(Theend) + +static struct BurnRomInfo TheendsRomDesc[] = { + { "ic13", 0x00800, 0x90e5ab14, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic14", 0x00800, 0x950f0a07, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic15", 0x00800, 0x6786bcf5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic16", 0x00800, 0x380a0017, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic17", 0x00800, 0xaf067b7f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic18", 0x00800, 0xa0411b93, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ic56", 0x00800, 0x3b2c2f70, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ic55", 0x00800, 0xe0429e50, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ic30", 0x00800, 0x527fd384, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ic31", 0x00800, 0xaf6d09b6, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6331-1j.86", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Theends) +STD_ROM_FN(Theends) + +static struct BurnRomInfo ScrambleRomDesc[] = { + { "s1.2d", 0x00800, 0xea35ccaa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s2.2e", 0x00800, 0xe7bba1b3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s3.2f", 0x00800, 0x12d7fc3e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s4.2h", 0x00800, 0xb59360eb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s5.2j", 0x00800, 0x4919a91c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s6.2l", 0x00800, 0x26a4547b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s7.2m", 0x00800, 0x0bb49470, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "s8.2p", 0x00800, 0x6a5740e5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "c2.5f", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "c1.5h", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scramble) +STD_ROM_FN(Scramble) + +static struct BurnRomInfo ScramblesRomDesc[] = { + { "2d", 0x00800, 0xb89207a1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x00800, 0xe9b4b9eb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f", 0x00800, 0xa1f14f4c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h", 0x00800, 0x591bc0d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x00800, 0x22f11b6b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l", 0x00800, 0x705ffe49, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2m", 0x00800, 0xea26c35c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2p", 0x00800, 0x94d8f5e3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f", 0x00800, 0x5f30311a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h", 0x00800, 0x516e029e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scrambles) +STD_ROM_FN(Scrambles) + +static struct BurnRomInfo ScramblebfRomDesc[] = { + { "scf1.2d", 0x00800, 0xb126aa1f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scf2.2e", 0x00800, 0xce25fb77, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns3.2f", 0x00800, 0xeec265ee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns4.2h", 0x00800, 0xdd380a22, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns5.2j", 0x00800, 0x92980e72, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns6.2l", 0x00800, 0x9fd96374, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns7.2m", 0x00800, 0x88ac07a0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scns8.2p", 0x00800, 0x75232e09, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1ns.5c", 0x00800, 0xbe037cf6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "c2.5f", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "c1.5h", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scramblebf) +STD_ROM_FN(Scramblebf) + +static struct BurnRomInfo ScramblebbRomDesc[] = { + { "1", 0x00800, 0x8ba174c4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2", 0x00800, 0x43cb40a4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3", 0x00800, 0xeec265ee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4", 0x00800, 0xdd380a22, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5", 0x00800, 0x92980e72, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6", 0x00800, 0x9fd96374, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7", 0x00800, 0x88ac07a0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8", 0x00800, 0x75232e09, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "9", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "10", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scramblebb) +STD_ROM_FN(Scramblebb) + +static struct BurnRomInfo StrfbombRomDesc[] = { + { "1.2c", 0x00800, 0xb102aaa0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.2e", 0x00800, 0xd4155703, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.2f", 0x00800, 0xa9568c89, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.2h", 0x00800, 0x663b6c35, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.2j", 0x00800, 0x4919a91c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.2l", 0x00800, 0x4ec66ae3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7.2m", 0x00800, 0x0feb0192, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8.2p", 0x00800, 0x280a6142, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "9.5f", 0x00800, 0x3abeff25, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "10.5h", 0x00800, 0x79ecacbe, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Strfbomb) +STD_ROM_FN(Strfbomb) + +static struct BurnRomInfo ExplorerRomDesc[] = { + { "10l.bin", 0x01000, 0xd5adf626, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "9l.bin", 0x01000, 0x48e32788, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "8l.bin", 0x01000, 0xc0dbdbde, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "7l.bin", 0x01000, 0x9b30d227, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "3f.bin", 0x01000, 0x9faf18cf, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "4b.bin", 0x00800, 0xe910b5c3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "c2.5f", 0x00800, 0x4708845b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "c1.5h", 0x00800, 0x11fd2887, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Explorer) +STD_ROM_FN(Explorer) + +static struct BurnRomInfo AtlantisRomDesc[] = { + { "2c", 0x00800, 0x0e485b9a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x00800, 0xc1640513, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f", 0x00800, 0xeec265ee, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h", 0x00800, 0xa5d2e442, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x00800, 0x45f7cf34, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l", 0x00800, 0xf335b96b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f", 0x00800, 0x57f9c6b9, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h", 0x00800, 0xe989f325, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Atlantis) +STD_ROM_FN(Atlantis) + +static struct BurnRomInfo Atlantis2RomDesc[] = { + { "rom1", 0x00800, 0xad348089, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom2", 0x00800, 0xcaa705d1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom3", 0x00800, 0xe420641d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom4", 0x00800, 0x04792d90, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x00800, 0x45f7cf34, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom6", 0x00800, 0xb297bd4b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom7", 0x00800, 0xa50bf8d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rom8", 0x00800, 0xd2c5c984, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ot1.5c", 0x00800, 0xbcd297f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot2.5d", 0x00800, 0xde7912da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ot3.5e", 0x00800, 0xba2fa933, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "rom9", 0x00800, 0x55cd5acd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom10", 0x00800, 0x72e773b8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Atlantis2) +STD_ROM_FN(Atlantis2) + +static struct BurnRomInfo CkongsRomDesc[] = { + { "vid_2c.bin", 0x01000, 0x49a8c234, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2e.bin", 0x01000, 0xf1b667f1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2f.bin", 0x01000, 0xb194b75d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2h.bin", 0x01000, 0x2052ba8a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2j.bin", 0x01000, 0xb377afd0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2l.bin", 0x01000, 0xfe65e691, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "turt_snd.5c", 0x01000, 0xf0c30f9a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "snd_5d.bin", 0x01000, 0x892c9547, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "vid_5f.bin", 0x01000, 0x7866d2cb, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "vid_5h.bin", 0x01000, 0x7311a101, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "vid_6e.bin", 0x00020, 0x5039af97, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Ckongs) +STD_ROM_FN(Ckongs) + +static struct BurnRomInfo MarsRomDesc[] = { + { "u26.3", 0x00800, 0x2f88892c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u56.4", 0x00800, 0x9e6bcbf7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u69.5", 0x00800, 0xdf496e6e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u98.6", 0x00800, 0x75f274bb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u114.7", 0x00800, 0x497fd8d0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u133.8", 0x00800, 0x3d4cd59f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "u39.9", 0x00800, 0xbb5968b9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "u51.10", 0x00800, 0x75fd7720, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "u78.11", 0x00800, 0x72a492da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "u72.1", 0x00800, 0x279789d0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "u101.2", 0x00800, 0xc5dc627f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mars) +STD_ROM_FN(Mars) + +static struct BurnRomInfo DevilfshRomDesc[] = { + { "u26.1", 0x00800, 0xec047d71, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u56.2", 0x00800, 0x0138ade9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u69.3", 0x00800, 0x5dd0b3fc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u98.4", 0x00800, 0xded0b745, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u114.5", 0x00800, 0x5fd40176, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u133.6", 0x00800, 0x03538336, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u143.7", 0x00800, 0x64676081, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "u163.8", 0x00800, 0xbc3d6770, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "u39.9", 0x00800, 0x09987e2e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "u51.10", 0x00800, 0x1e2b1471, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "u78.11", 0x00800, 0x45279aaa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "u72.12", 0x01000, 0x5406508e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "u101.13", 0x01000, 0x8c4018b6, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Devilfsh) +STD_ROM_FN(Devilfsh) + +static struct BurnRomInfo Newsin7RomDesc[] = { + { "newsin.1", 0x01000, 0xe6c23fe0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "newsin.2", 0x01000, 0x3d477b5f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "newsin.3", 0x01000, 0x7dfa9af0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "newsin.4", 0x01000, 0xd1b0ba19, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "newsin.5", 0x01000, 0x06275d59, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "newsin.13", 0x00800, 0xd88489a2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "newsin.12", 0x00800, 0xb154a7af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "newsin.11", 0x00800, 0x7ade709b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "newsin.9", 0x01000, 0x6b87adff, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "newsin.8", 0x01000, 0x0c5b895a, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "newsin.7", 0x01000, 0x6bc5d64f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "newsin.6", 0x00020, 0x5cf2cd8d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Newsin7) +STD_ROM_FN(Newsin7) + +static struct BurnRomInfo MrkougarRomDesc[] = { + { "2732-7.bin", 0x01000, 0xfd060ffb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2732-6.bin", 0x01000, 0x9e05d868, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2732-5.bin", 0x01000, 0xcbc7c536, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "atw-6w-2.bin", 0x01000, 0xaf42a371, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6y-3.bin", 0x01000, 0x862b8902, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6z-4.bin", 0x01000, 0xa0396cc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "2732-1.bin", 0x01000, 0x60ef1d43, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mrkougar) +STD_ROM_FN(Mrkougar) + +static struct BurnRomInfo Mrkougar2RomDesc[] = { + { "atw-7l-7.bin", 0x01000, 0x7b34b198, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "atw-7k-6.bin", 0x01000, 0xfbca23c7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "atw-7h-5.bin", 0x01000, 0x05b257a2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "atw-6w-2.bin", 0x01000, 0xaf42a371, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6y-3.bin", 0x01000, 0x862b8902, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6z-4.bin", 0x01000, 0xa0396cc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "atw-1h-1.bin", 0x01000, 0x38fdfb63, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "atw-prom.bin", 0x00020, 0xc65db188, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mrkougar2) +STD_ROM_FN(Mrkougar2) + +static struct BurnRomInfo MrkougbRomDesc[] = { + { "p01.bin", 0x00800, 0xdea0cde1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p02.bin", 0x00800, 0xc8017751, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p03.bin", 0x00800, 0xb8921984, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p04.bin", 0x00800, 0xb3c9754c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p05.bin", 0x00800, 0x8d94adbc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p06.bin", 0x00800, 0xacc921ff, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "atw-6w-2.bin", 0x01000, 0xaf42a371, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6y-3.bin", 0x01000, 0x862b8902, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6z-4.bin", 0x01000, 0xa0396cc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "g07.bin", 0x00800, 0x0ecfd116, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g08.bin", 0x00800, 0x00bfa3c6, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "atw-prom.bin", 0x00020, 0xc65db188, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mrkougb) +STD_ROM_FN(Mrkougb) + +static struct BurnRomInfo Mrkougb2RomDesc[] = { + { "mrk1.bin", 0x00800, 0xfc93acb9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p02.bin", 0x00800, 0xc8017751, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p03.bin", 0x00800, 0xb8921984, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p04.bin", 0x00800, 0xb3c9754c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p05.bin", 0x00800, 0x8d94adbc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p06.bin", 0x00800, 0xacc921ff, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "atw-6w-2.bin", 0x01000, 0xaf42a371, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6y-3.bin", 0x01000, 0x862b8902, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "atw-6z-4.bin", 0x01000, 0xa0396cc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "g07.bin", 0x00800, 0x0ecfd116, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "g08.bin", 0x00800, 0x00bfa3c6, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "atw-prom.bin", 0x00020, 0xc65db188, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mrkougb2) +STD_ROM_FN(Mrkougb2) + +static struct BurnRomInfo HotshockRomDesc[] = { + { "0d.l10", 0x01000, 0x3e8aeaeb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "1d.l9", 0x01000, 0x0eab3246, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2d.l8", 0x01000, 0xe646bde3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3d.l7", 0x01000, 0x5bde9312, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "6d.b3", 0x01000, 0xc5e02651, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "7d.b4", 0x01000, 0x49dc113d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "4d.h3", 0x01000, 0x751c850e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5d.h5", 0x01000, 0xfc74282e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "18s030.1k", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Hotshock) +STD_ROM_FN(Hotshock) + +static struct BurnRomInfo HotshockbRomDesc[] = { + { "hotshock.l10", 0x01000, 0x401078f7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hotshock.l9", 0x01000, 0xaf76c237, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hotshock.l8", 0x01000, 0x30486031, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hotshock.l7", 0x01000, 0x5bde9312, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hotshock.b3", 0x01000, 0x0092f0e2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "hotshock.b4", 0x01000, 0xc2135a44, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "hotshock.h4", 0x01000, 0x60bdaea9, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hotshock.h5", 0x01000, 0x4ef17453, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Hotshockb) +STD_ROM_FN(Hotshockb) + +static struct BurnRomInfo ConquerRomDesc[] = { + { "conquer3.l10", 0x01000, 0xa33a824f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "conquer2.l9", 0x01000, 0x3ffa8285, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "conquer1.l8", 0x01000, 0x9ded2dff, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "conquer6.b3", 0x01000, 0xd363b2ea, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "conquer7.b4", 0x01000, 0xe6a63d71, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "conquer4.h3", 0x01000, 0xac533893, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "conquer5.h5", 0x01000, 0xd884fd49, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Conquer) +STD_ROM_FN(Conquer) + +static struct BurnRomInfo CavelonRomDesc[] = { + { "2.bin", 0x02000, 0xa3b353ac, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "1.bin", 0x02000, 0x3f62efd6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.bin", 0x02000, 0x39d74e4e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "1c_snd.bin", 0x00800, 0xf58dcf55, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "h.bin", 0x01000, 0xd44fcd6f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k.bin", 0x01000, 0x59bc7f9e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "cavelon.clr", 0x00020, 0xd133356b, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Cavelon) +STD_ROM_FN(Cavelon) + +static struct BurnRomInfo MimonscrRomDesc[] = { + { "mm1", 0x01000, 0x0399a0c4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm2", 0x01000, 0x2c5e971e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm3", 0x01000, 0x24ce1ce3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm4", 0x01000, 0xc83fb639, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm5", 0x01000, 0xa9f12dfc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm6", 0x01000, 0xe492a40c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm7", 0x01000, 0x5339928d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm8", 0x01000, 0xeee7a12e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mmsound1", 0x01000, 0x2d14c527, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "mmsnd2a", 0x01000, 0x35ed0f96, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "mmgfx1", 0x02000, 0x4af47337, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mmgfx2", 0x02000, 0xdef47da8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "c01s.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mimonscr) +STD_ROM_FN(Mimonscr) + +UINT8 __fastcall ExplorerZ80Read(UINT16 a) +{ + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + case 0x8000: { + return GalInput[0] | GalDip[0]; + } + + case 0x8001: { + return GalInput[1] | GalDip[1]; + } + + case 0x8002: { + return GalInput[2] | GalDip[2]; + } + + case 0x8003: { + return GalInput[3] | GalDip[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall ExplorerZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x5100 && a <= 0x51ff) { + INT32 Offset = a - 0x5100; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_count_0_w + return; + } + + case 0x6803: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x6804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7000: { + // watchdog write + return; + } + + case 0x8000: { + GalSoundLatch = d; + return; + } + + case 0x9000: { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall CkongsZ80Read(UINT16 a) +{ + switch (a) { + case 0x7000: + case 0x7001: + case 0x7002: + case 0x7003: { + return ppi8255_r(0, a - 0x7000); + } + + case 0x7800: + case 0x7801: + case 0x7802: + case 0x7803: { + return ppi8255_r(1, a - 0x7800); + } + + case 0xb000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall CkongsZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x7000: + case 0x7001: + case 0x7002: + case 0x7003: { + ppi8255_w(0, a - 0x7000, d); + return; + } + + case 0x7800: + case 0x7801: + case 0x7802: + case 0x7803: { + ppi8255_w(1, a - 0x7800, d); + return; + } + + case 0xa801: { + GalIrqFire = d & 1; + return; + } + + case 0xa806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa807: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb000: { + // watchdog write + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MarsZ80Read(UINT16 a) +{ + if (a >= 0x8100 && a <= 0x810f) { + INT32 Offset = a - 0x8100; + return ppi8255_r(0, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01)); + } + + if (a >= 0x8200 && a <= 0x820f) { + INT32 Offset = a - 0x8200; + return ppi8255_r(1, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01)); + } + + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall MarsZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8100 && a <= 0x810f) { + INT32 Offset = a - 0x8100; + ppi8255_w(0, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + if (a >= 0x8200 && a <= 0x820f) { + INT32 Offset = a - 0x8200; + ppi8255_w(1, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + switch (a) { + case 0x6800: { + // coin_count_1_w + return; + } + + case 0x6801: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6802: { + GalIrqFire = d & 1; + return; + } + + case 0x6808: { + // coin_count_0_w + return; + } + + case 0x6809: { + GalFlipScreenX = d & 1; + return; + } + + case 0x680b: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Newsin7Z80Read(UINT16 a) +{ + if (a >= 0x8200 && a <= 0x820f) { + INT32 Offset = a - 0x8200; + return ppi8255_r(1, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01)); + } + + if (a >= 0xc100 && a <= 0xc10f) { + INT32 Offset = a - 0xc100; + return ppi8255_r(0, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01)); + } + + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Newsin7Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8200 && a <= 0x820f) { + INT32 Offset = a - 0x8200; + ppi8255_w(1, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + if (a >= 0xc100 && a <= 0xc10f) { + INT32 Offset = a - 0xc100; + ppi8255_w(0, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + switch (a) { + case 0x6800: { + // coin_count_1_w + return; + } + + case 0x6801: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6802: { + GalIrqFire = d & 1; + return; + } + + case 0x6808: { + // coin_count_0_w + return; + } + + case 0x6809: { + GalFlipScreenX = d & 1; + return; + } + + case 0x680b: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall MrkougarZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8100 && a <= 0x810f) { + INT32 Offset = a - 0x8100; + ppi8255_w(0, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + if (a >= 0x8200 && a <= 0x820f) { + INT32 Offset = a - 0x8200; + ppi8255_w(1, ((Offset >> 2) & 0x02) | ((Offset >> 1) & 0x01), d); + return; + } + + switch (a) { + case 0x6800: { + // coin_count_1_w + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6808: { + // coin_count_0_w + return; + } + + case 0x6809: { + GalFlipScreenX = d & 1; + return; + } + + case 0x680b: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall HotshockZ80Read(UINT16 a) +{ + switch (a) { + case 0x8000: { + return GalInput[0] | GalDip[0]; + } + + case 0x8001: { + return GalInput[1] | GalDip[1]; + } + + case 0x8002: { + return GalInput[2] | GalDip[2]; + } + + case 0x8003: { + return GalInput[3] | GalDip[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall HotshockZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: { + // coin_count_2_w + return; + } + + case 0x6002: { + // coin_count_1_w + return; + } + + case 0x6004: { + GalFlipScreenX = d & 1; + GalFlipScreenY = d & 1; + return; + } + + case 0x6005: { + // coin_count_0_w + return; + } + + case 0x6006: { + GalGfxBank[0] = d & 1; + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x7000: { + // watchdog write + return; + } + + case 0x8000: { + GalSoundLatch = d; + return; + } + + case 0x9000: { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall HotshockSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x20: { + return AY8910Read(0); + } + + case 0x40: { + return AY8910Read(1); + } + } + + bprintf(PRINT_NORMAL, _T("Sound Port Read %x\n"), a); + + return 0; +} + +void __fastcall HotshockSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x10: { + AY8910Write(0, 0, d); + return; + } + + case 0x20: { + AY8910Write(0, 1, d); + return; + } + + case 0x40: { + AY8910Write(1, 1, d); + return; + } + + case 0x80: { + AY8910Write(1, 0, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Sound Port Write %x, %x\n"), a, d); +} + +static void CavelonDoBankSwitch() +{ + CavelonBankSwitch = !CavelonBankSwitch; + ZetMapArea(0x0000, 0x1fff, 0, GalZ80Rom1 + ((CavelonBankSwitch) ? 0x4000 : 0x0000)); + ZetMapArea(0x0000, 0x1fff, 2, GalZ80Rom1 + ((CavelonBankSwitch) ? 0x4000 : 0x0000)); +} + +UINT8 __fastcall CavelonZ80Read(UINT16 a) +{ + if (a >= 0x8000) { + CavelonDoBankSwitch(); + UINT32 Offset = a - 0x8000; + UINT8 Result = 0xff; + if (Offset & 0x0100) Result &= ppi8255_r(0, Offset & 3); + if (Offset & 0x0200) Result &= ppi8255_r(1, Offset & 3); + return Result; + } + + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall CavelonZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8000) { + CavelonDoBankSwitch(); + INT32 Offset = a - 0x8000; + if (Offset & 0x0100) ppi8255_w(0, Offset & 3, d); + if (Offset & 0x0200) ppi8255_w(1, Offset & 3, d); + return; + } + + switch (a) { + case 0x2000: + case 0x3800: + case 0x3801: { + // write in rom area + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_count_0_w + return; + } + + case 0x6803: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x6804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MimonscrZ80Read(UINT16 a) +{ + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + case 0x8100: + case 0x8101: + case 0x8102: + case 0x8103: { + return ppi8255_r(0, a - 0x8100); + } + + case 0x8200: + case 0x8201: + case 0x8202: + case 0x8203: { + return ppi8255_r(1, a - 0x8200); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall MimonscrZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6800: { + GalGfxBank[0] = d & 1; + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + GalGfxBank[1] = d & 1; + return; + } + + case 0x6803: { + // ??? + return; + } + + case 0x6804: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x6805: { + // ??? + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + case 0x8100: + case 0x8101: + case 0x8102: + case 0x8103: { + ppi8255_w(0, a - 0x8100, d); + return; + } + + case 0x8200: + case 0x8201: + case 0x8202: + case 0x8203: { + ppi8255_w(1, a - 0x8200, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 TheendInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTheend; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = GalaxianDrawBackground; + GalDrawBulletsFunction = TheendDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static UINT8 ScramblePPIReadIN2() +{ + UINT8 Val = (ScrambleProtectionResult >> 7) & 1; + + if (Val) { + return 0x5f - GalInput[2] - GalDip[2]; + } else { + return 0xff - GalInput[2] - GalDip[2]; + } +} + +static UINT8 ScrambleProtectionRead() +{ + return ScrambleProtectionResult; +} + +static void ScrambleProtectionWrite(UINT8 d) +{ + ScrambleProtectionState = (ScrambleProtectionState << 4) | (d & 0x0f); + + switch (ScrambleProtectionState & 0xfff) { + case 0xf09: ScrambleProtectionResult = 0xff; return; + case 0xa49: ScrambleProtectionResult = 0xbf; return; + case 0x319: ScrambleProtectionResult = 0x4f; return; + case 0x5c9: ScrambleProtectionResult = 0x6f; return; + + // scrambles + case 0x246: ScrambleProtectionResult ^= 0x80; return; + case 0xb5f: ScrambleProtectionResult = 0x6f; return; + } +} + +static INT32 ScrambleInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTheend; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + PPI0PortReadC = ScramblePPIReadIN2; + PPI1PortReadC = ScrambleProtectionRead; + PPI1PortWriteC = ScrambleProtectionWrite; + + return nRet; +} + +static void ExplorerPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetReadHandler(ExplorerZ80Read); + ZetSetWriteHandler(ExplorerZ80Write); + ZetMapArea(0x5100, 0x51ff, 0, GalSpriteRam); + ZetMapArea(0x5100, 0x51ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 ExplorerInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = ExplorerPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 AtlantisInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTheend; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static void CkongsPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(CkongsZ80Read); + ZetSetWriteHandler(CkongsZ80Write); + ZetMapArea(0x0000, 0x5fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x5fff, 2, GalZ80Rom1); + ZetMapArea(0x6000, 0x6fff, 0, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 1, GalZ80Ram1); + ZetMapArea(0x6000, 0x6fff, 2, GalZ80Ram1); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 0, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 1, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 CkongsInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CkongsPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + KonamiPPIInit(); + + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void MarsDecrypt() +{ + for (UINT32 i = 0; i < GalZ80Rom1Size; i += 16) { + UINT8 SwapBuffer[16]; + + for (UINT32 j = 0; j < 16; j++) { + INT32 NewOffset = BITSWAP08(j, 7, 6, 5, 4, 2, 0, 3, 1); + SwapBuffer[j] = GalZ80Rom1[i + NewOffset]; + } + memcpy(GalZ80Rom1 + i, SwapBuffer, 16); + } +} + +static void MarsPostLoad() +{ + MarsDecrypt(); + + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(MarsZ80Read); + ZetSetWriteHandler(MarsZ80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetClose(); +} + +static INT32 MarsInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MarsPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 0; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 DevilfshInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MarsPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalNumChars = 0x100; + GalNumSprites = 0x40; + CharPlaneOffsets[1] = 0x8000; + SpritePlaneOffsets[1] = 0x8000; + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom + 0x800, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 0; + + KonamiPPIInit(); + + return nRet; +} + +static void Newsin7PostLoad() +{ + MarsDecrypt(); + + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(Newsin7Z80Read); + ZetSetWriteHandler(Newsin7Z80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetMapArea(0xa000, 0xafff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0xa000, 0xafff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static INT32 Newsin7Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Newsin7PostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalNumChars = 0x100; + GalNumSprites = 0x40; + + INT32 Newsin7PlaneOffsets[3] = {0x10000, 0, 0x8000}; + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x2000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 3, 8, 8, Newsin7PlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 3, 16, 16, Newsin7PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom + 0x800, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalColourDepth = 3; + GalSpriteClipStart = 0; + GalSpriteClipEnd = 246; + + GalSoundVolumeShift = 0; + + KonamiPPIInit(); + + return nRet; +} + +static void MapMrkougar() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(MarsZ80Read); + ZetSetWriteHandler(MrkougarZ80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 0, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 1, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetClose(); +} + +static void MrkougarPostLoad() +{ + MarsDecrypt(); + + MapMrkougar(); +} + +static INT32 MrkougarInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MrkougarPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + INT32 MrkougarPlaneOffsets[2] = {0, 4}; + INT32 MrkougarCharXOffsets[8] = {64, 65, 66, 67, 0, 1, 2, 3}; + INT32 MrkougarCharYOffsets[8] = {0, 8, 16, 24, 32, 40, 48, 56}; + INT32 MrkougarSpriteXOffsets[16] = {64, 65, 66, 67, 0, 1, 2, 3, 192, 193, 194, 195, 128, 129, 130, 131}; + INT32 MrkougarSpriteYOffsets[16] = {0, 8, 16, 24, 32, 40, 48, 56, 256, 264, 272, 280, 288, 296, 304, 312}; + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + GfxDecode(GalNumChars, 2, 8, 8, MrkougarPlaneOffsets, MrkougarCharXOffsets, MrkougarCharYOffsets, 0x80, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, MrkougarPlaneOffsets, MrkougarSpriteXOffsets, MrkougarSpriteYOffsets, 0x200, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 MrkougbInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapMrkougar; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static void HotshockPostLoad() +{ + MapMrkougar(); + + ZetOpen(0); + ZetSetReadHandler(HotshockZ80Read); + ZetSetWriteHandler(HotshockZ80Write); + ZetClose(); + + GalZ80Rom1[0x2ef9] = 0xc9; +} + +static INT32 HotshockInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HotshockPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + ZetOpen(1); + ZetSetInHandler(HotshockSoundZ80PortRead); + ZetSetOutHandler(HotshockSoundZ80PortWrite); + ZetClose(); + + GalExtendTileInfoFunction = PiscesExtendTileInfo; + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + GalSoundVolumeShift = 0; + + return nRet; +} + +static void ConquerPostLoad() +{ + MapMrkougar(); + + ZetOpen(0); + ZetSetReadHandler(HotshockZ80Read); + ZetSetWriteHandler(HotshockZ80Write); + ZetClose(); +} + +static INT32 ConquerInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = ConquerPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + ZetOpen(1); + ZetSetInHandler(HotshockSoundZ80PortRead); + ZetSetOutHandler(HotshockSoundZ80PortWrite); + ZetClose(); + + GalExtendTileInfoFunction = PiscesExtendTileInfo; + + GalSoundVolumeShift = 0; + + return nRet; +} + +static void CavelonPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetReadHandler(CavelonZ80Read); + ZetSetWriteHandler(CavelonZ80Write); + ZetClose(); +} + +static INT32 CavelonInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = CavelonPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + GalSoundVolumeShift = 2; + + KonamiPPIInit(); + + return nRet; +} + +static void MimonscrPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(MimonscrZ80Read); + ZetSetWriteHandler(MimonscrZ80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x43ff, 0, GalVideoRam); + ZetMapArea(0x4000, 0x43ff, 1, GalVideoRam); + ZetMapArea(0x4000, 0x43ff, 2, GalVideoRam); + ZetMapArea(0x4400, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4400, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4400, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetMapArea(0xc000, 0xffff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0xc000, 0xffff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static INT32 MimonscrInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MimonscrPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = MimonkeyExtendTileInfo; + GalExtendSpriteInfoFunction = MimonkeyExtendSpriteInfo; + + KonamiPPIInit(); + + return nRet; +} + +struct BurnDriver BurnDrvTheend = { + "theend", NULL, NULL, NULL, "1980", + "The End\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, TheendRomInfo, TheendRomName, NULL, NULL, TheendInputInfo, TheendDIPInfo, + TheendInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTheends = { + "theends", "theend", NULL, NULL, "1980", + "The End (Stern)\0", NULL, "Konami (Stern license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, TheendsRomInfo, TheendsRomName, NULL, NULL, TheendInputInfo, TheendDIPInfo, + TheendInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScramble = { + "scramble", NULL, NULL, NULL, "1981", + "Scramble\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScrambleRomInfo, ScrambleRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScrambles = { + "scrambles", "scramble", NULL, NULL, "1981", + "Scramble (Stern)\0", NULL, "Konami (Stern license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScramblesRomInfo, ScramblesRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScramblebf = { + "scramblebf", "scramble", NULL, NULL, "1981", + "Scramble (Karateko, French bootleg)\0", NULL, "Karateko (bootleg)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScramblebfRomInfo, ScramblebfRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScramblebb = { + "scramblebb", "scramble", NULL, NULL, "1981", + "Scramble (bootleg?)\0", NULL, "bootleg?", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScramblebbRomInfo, ScramblebbRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvStrfbomb = { + "strfbomb", "scramble", NULL, NULL, "1981", + "Strafe Bomb\0", NULL, "Omni", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, StrfbombRomInfo, StrfbombRomName, NULL, NULL, ScrambleInputInfo, StrfbombDIPInfo, + ScrambleInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvExplorer = { + "explorer", "scramble", NULL, NULL, "1981", + "Explorer\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ExplorerRomInfo, ExplorerRomName, NULL, NULL, ExplorerInputInfo, ExplorerDIPInfo, + ExplorerInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAtlantis = { + "atlantis", NULL, NULL, NULL, "1981", + "Battle of Atlantis (set 1)\0", NULL, "Comsoft", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, AtlantisRomInfo, AtlantisRomName, NULL, NULL, AtlantisInputInfo, AtlantisDIPInfo, + AtlantisInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAtlantis2 = { + "atlantis2", "atlantis", NULL, NULL, "1981", + "Battle of Atlantis (set 2)\0", NULL, "Comsoft", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, Atlantis2RomInfo, Atlantis2RomName, NULL, NULL, AtlantisInputInfo, AtlantisDIPInfo, + AtlantisInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCkongs = { + "ckongs", "ckong", NULL, NULL, "1981", + "Crazy Kong (Scramble hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, CkongsRomInfo, CkongsRomName, NULL, NULL, CkongsInputInfo, CkongsDIPInfo, + CkongsInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMars = { + "mars", NULL, NULL, NULL, "1981", + "Mars\0", NULL, "Artic", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MarsRomInfo, MarsRomName, NULL, NULL, MarsInputInfo, MarsDIPInfo, + MarsInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDevilfsh = { + "devilfsh", NULL, NULL, NULL, "1982", + "Devil Fish\0", NULL, "Artic", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, DevilfshRomInfo, DevilfshRomName, NULL, NULL, DevilfshInputInfo, DevilfshDIPInfo, + DevilfshInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNewsin7 = { + "newsin7", NULL, NULL, NULL, "1983", + "New Sinbad 7\0", NULL, "ATW USA, Inc.", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Newsin7RomInfo, Newsin7RomName, NULL, NULL, DevilfshInputInfo, Newsin7DIPInfo, + Newsin7Init, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMrkougar = { + "mrkougar", NULL, NULL, NULL, "1984", + "Mr. Kougar\0", NULL, "ATW", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, MrkougarRomInfo, MrkougarRomName, NULL, NULL, MrkougarInputInfo, MrkougarDIPInfo, + MrkougarInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMrkougar2 = { + "mrkougar2", "mrkougar", NULL, NULL, "1983", + "Mr. Kougar (earlier)\0", NULL, "ATW", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, Mrkougar2RomInfo, Mrkougar2RomName, NULL, NULL, MrkougarInputInfo, MrkougarDIPInfo, + MrkougarInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMrkougb = { + "mrkougb", "mrkougar", NULL, NULL, "1983", + "Mr. Kougar (bootleg set 1)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, MrkougbRomInfo, MrkougbRomName, NULL, NULL, MrkougarInputInfo, MrkougarDIPInfo, + MrkougbInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMrkougb2 = { + "mrkougb2", "mrkougar", NULL, NULL, "1983", + "Mr. Kougar (bootleg set 2)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, Mrkougb2RomInfo, Mrkougb2RomName, NULL, NULL, MrkougarInputInfo, MrkougarDIPInfo, + MrkougbInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHotshock = { + "hotshock", NULL, NULL, NULL, "1982", + "Hot Shocker\0", NULL, "E.G. Felaco (Domino license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, HotshockRomInfo, HotshockRomName, NULL, NULL, HotshockInputInfo, HotshockDIPInfo, + HotshockInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHotshockb = { + "hotshockb", "hotshock", NULL, NULL, "1982", + "Hot Shocker (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, HotshockbRomInfo, HotshockbRomName, NULL, NULL, HotshockInputInfo, HotshockDIPInfo, + HotshockInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvConquer = { + "conquer", NULL, NULL, NULL, "1982", + "Conquer\0", "Bad dump", "unknown", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, ConquerRomInfo, ConquerRomName, NULL, NULL, HotshockInputInfo, HotshockDIPInfo, + ConquerInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCavelon = { + "cavelon", NULL, NULL, NULL, "1983", + "Cavelon\0", NULL, "Jetsoft", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, CavelonRomInfo, CavelonRomName, NULL, NULL, AtlantisInputInfo, CavelonDIPInfo, + CavelonInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMimonscr = { + "mimonscr", "mimonkey", NULL, NULL, "198?", + "Mighty Monkey (bootleg on Scramble hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MimonscrRomInfo, MimonscrRomName, NULL, NULL, AtlantisInputInfo, MimonkeyDIPInfo, + MimonscrInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Scramble based hardware with one CPU and one AY8910 +static struct BurnRomInfo TriplepRomDesc[] = { + { "triplep.2g", 0x01000, 0xc583a93d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "triplep.2h", 0x01000, 0xc03ddc49, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "triplep.2k", 0x01000, 0xe83ca6b5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "triplep.2l", 0x01000, 0x982cc3b9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "triplep.5f", 0x00800, 0xd51cbd6f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "triplep.5h", 0x00800, 0xf21c0059, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "tripprom.6e", 0x00020, 0x624f75df, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Triplep) +STD_ROM_FN(Triplep) + +static struct BurnRomInfo KnockoutRomDesc[] = { + { "knockout.2h", 0x01000, 0xeaaa848e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "knockout.2k", 0x01000, 0xbc26d2c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "knockout.2l", 0x01000, 0x02025c10, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "knockout.2m", 0x01000, 0xe9abc42b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "triplep.5f", 0x00800, 0xd51cbd6f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "triplep.5h", 0x00800, 0xf21c0059, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "tripprom.6e", 0x00020, 0x624f75df, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Knockout) +STD_ROM_FN(Knockout) + +static struct BurnRomInfo MarinerRomDesc[] = { + { "tp1.2h", 0x01000, 0xdac1dfd0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm2.2k", 0x01000, 0xefe7ca28, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm3.2l", 0x01000, 0x027881a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm4.2m", 0x01000, 0xa0fde7dc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm5.2p", 0x01000, 0xd7ebcb8e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "tm8.5f", 0x01000, 0x70ae611f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tm9.5h", 0x01000, 0x8e4e999e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "t4.6e", 0x00020, 0xca42b6dd, BRF_GRA | GAL_ROM_PROM }, + { "t6.6p", 0x00100, 0xad208ccc, BRF_GRA | GAL_ROM_PROM }, // Background colour + { "t5.7p", 0x00020, 0x1bd88cff, BRF_GRA | GAL_ROM_PROM }, // Char banking and star placement +}; + +STD_ROM_PICK(Mariner) +STD_ROM_FN(Mariner) + +static struct BurnRomInfo EighthundredfathRomDesc[] = { + { "tu1.2h", 0x01000, 0x5dd3d42f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm2.2k", 0x01000, 0xefe7ca28, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm3.2l", 0x01000, 0x027881a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tm4.2m", 0x01000, 0xa0fde7dc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "tu5.2p", 0x01000, 0xf864a8a6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "tm8.5f", 0x01000, 0x70ae611f, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "tm9.5h", 0x01000, 0x8e4e999e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "t4.6e", 0x00020, 0xca42b6dd, BRF_GRA | GAL_ROM_PROM }, + { "t6.6p", 0x00100, 0xad208ccc, BRF_GRA | GAL_ROM_PROM }, // Background colour + { "t5.7p", 0x00020, 0x1bd88cff, BRF_GRA | GAL_ROM_PROM }, // Char banking and star placement +}; + +STD_ROM_PICK(Eighthundredfath) +STD_ROM_FN(Eighthundredfath) + +UINT8 __fastcall TriplepZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + // ??? + return 0; + } + + case 0x01: { + return AY8910Read(0); + } + + case 0x02: { + if (ZetPc(-1) == 0x015a) return 0xff; + if (ZetPc(-1) == 0x0886) return 0x05; + return 0; + } + + case 0x03: { + if (ZetPc(-1) == 0x015d) return 0x04; + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall TriplepZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + AY8910Write(0, 1, d); + return; + } + + case 0x01: { + AY8910Write(0, 0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MarinerZ80Read(UINT16 a) +{ + if (a >= 0x8000) { + if (a == 0xb401) return 0x07; + if (a == 0x9008) return 0x03; + + UINT32 Offset = a - 0x8000; + UINT8 Result = 0xff; + if (Offset & 0x0100) Result &= ppi8255_r(0, Offset & 3); + if (Offset & 0x0200) Result &= ppi8255_r(1, Offset & 3); + return Result; + } + + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +static void TriplepPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetInHandler(TriplepZ80PortRead); + ZetSetOutHandler(TriplepZ80PortWrite); + ZetClose(); +} + +static INT32 TriplepInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = TriplepPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910; + + nRet = GalInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + PPI1PortWriteA = NULL; + PPI1PortWriteB = NULL; + + return nRet; +} + +static void MarinerPostLoad() +{ + GalTempRom = (UINT8*)malloc(0x1000); + memcpy(GalTempRom, GalZ80Rom1 + 0x4000, 0x1000); + memcpy(GalZ80Rom1 + 0x4800, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x4000, GalTempRom + 0x0800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapTheend(); + + ZetOpen(0); + ZetSetReadHandler(MarinerZ80Read); + ZetSetInHandler(TriplepZ80PortRead); + ZetSetOutHandler(TriplepZ80PortWrite); + ZetMapArea(0x5800, 0x67ff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x5800, 0x67ff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static INT32 MarinerInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MarinerPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910; + + nRet = GalInit(); + + GalCalcPaletteFunction = MarinerCalcPalette; + GalRenderBackgroundFunction = MarinerDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = MarinerExtendTileInfo; + + KonamiPPIInit(); + PPI1PortWriteA = NULL; + PPI1PortWriteB = NULL; + + return nRet; +} + +struct BurnDriver BurnDrvTriplep = { + "triplep", NULL, NULL, NULL, "1982", + "Triple Punch\0", NULL, "KKI", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TriplepRomInfo, TriplepRomName, NULL, NULL, AmidarInputInfo, TriplepDIPInfo, + TriplepInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvKnockout = { + "knockout", "triplep", NULL, NULL, "1982", + "Knock Out!!\0", NULL, "KKK", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, KnockoutRomInfo, KnockoutRomName, NULL, NULL, AmidarInputInfo, TriplepDIPInfo, + TriplepInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMariner = { + "mariner", NULL, NULL, NULL, "1981", + "Mariner\0", NULL, "Armenip", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MarinerRomInfo, MarinerRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + MarinerInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvEighthundredfath = { + "800fath", "mariner", NULL, NULL, "1981", + "800 Fathoms\0", NULL, "Amenip (US Billiards Inc. license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE |BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, EighthundredfathRomInfo, EighthundredfathRomName, NULL, NULL, ScrambleInputInfo, ScrambleDIPInfo, + MarinerInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Scorpion hardware - based on Scramble but with a third AY8910 and a speech chip +static struct BurnRomInfo ScorpionRomDesc[] = { + { "1.2d", 0x01000, 0xba1219b4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2.2f", 0x01000, 0xc3909ab6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "3.2g", 0x01000, 0x43261352, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "4.2h", 0x01000, 0xaba2276a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.2k", 0x01000, 0x952f78f2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "32_a4.7c", 0x01000, 0x361b8a36, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "32_a5.7d", 0x01000, 0xaddecdd4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "32_f5.5f", 0x01000, 0x1e5da9d6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "32_h5.5h", 0x01000, 0xa57adb0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, + + { "32_a3.6e", 0x01000, 0x279ae6f9, BRF_OPT | BRF_SND }, // Speech samples? + { "32_a2.6d", 0x01000, 0x90352dd4, BRF_OPT | BRF_SND }, + { "32_a1.6c", 0x01000, 0x3bf2452d, BRF_OPT | BRF_SND }, +}; + +STD_ROM_PICK(Scorpion) +STD_ROM_FN(Scorpion) + +static struct BurnRomInfo ScorpionaRomDesc[] = { + { "scor_d2.bin", 0x01000, 0xc5b9daeb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scor_e2.bin", 0x01000, 0x82308d05, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scor_g2.bin", 0x01000, 0x756b09cd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scor_h2.bin", 0x01000, 0xa0457b93, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scor_l2.bin", 0x00800, 0x6623da33, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scor_k2.bin", 0x00800, 0x42ec34d8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "32_a4.7c", 0x01000, 0x361b8a36, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "32_a5.7d", 0x01000, 0xaddecdd4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "scor_f5.bin", 0x01000, 0x60180a38, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "32_h5.5h", 0x01000, 0xa57adb0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, + + { "scor_a3.bin", 0x01000, 0x04abf178, BRF_OPT | BRF_SND }, // Speech samples? + { "scor_a2.bin", 0x01000, 0x452d6354, BRF_OPT | BRF_SND }, + { "32_a1.6c", 0x01000, 0x3bf2452d, BRF_OPT | BRF_SND }, +}; + +STD_ROM_PICK(Scorpiona) +STD_ROM_FN(Scorpiona) + +static struct BurnRomInfo ScorpionbRomDesc[] = { + { "ic109.2d", 0x01000, 0xf54688c9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic110.2e", 0x01000, 0x91aaaa12, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic111.2g", 0x01000, 0x4c3720da, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic112.2h", 0x01000, 0x53e2a983, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ic113.2k", 0x01000, 0xe4ad299a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "32_a4.7c", 0x01000, 0x361b8a36, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ic13.7d", 0x01000, 0xaddecdd4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ic72.5f", 0x01000, 0x1e5da9d6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ic73.5h", 0x01000, 0xa57adb0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, + + { "ic25.6e", 0x01000, 0x04abf178, BRF_OPT | BRF_SND }, // Speech samples? + { "ic24.6d", 0x01000, 0x90352dd4, BRF_OPT | BRF_SND }, + { "ic23.6c", 0x01000, 0x3bf2452d, BRF_OPT | BRF_SND }, +}; + +STD_ROM_PICK(Scorpionb) +STD_ROM_FN(Scorpionb) + +static struct BurnRomInfo ScorpionmcRomDesc[] = { + { "p1.bin", 0x00800, 0x58818d88, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p2.bin", 0x00800, 0x8bec5f9f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p3.bin", 0x00800, 0x24b7fdff, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p4.bin", 0x00800, 0x9082e2f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p5.bin", 0x00800, 0x20387fc0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p6.bin", 0x00800, 0xf66c48e1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p7.bin", 0x00800, 0x931e34c7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p8.bin", 0x00800, 0xab5ab61d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p9.bin", 0x01000, 0xb551b974, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "p10.bin", 0x00800, 0xa7bd8d20, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "h.bin", 0x01000, 0x1e5da9d6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "k.bin", 0x01000, 0xa57adb0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331.bpr", 0x00020, 0x6a0c7d87, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scorpionmc) +STD_ROM_FN(Scorpionmc) + +static struct BurnRomInfo AracnisRomDesc[] = { + { "00sc.bin", 0x01000, 0xc7e0d6b9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "01sc.bin", 0x01000, 0x03eb27dc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "02sc.bin", 0x01000, 0xf3d49d4f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "03sc.bin", 0x01000, 0x0e741984, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "05sc.bin", 0x01000, 0xf27ee3e4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "06sc.bin", 0x00800, 0xfdfc2c82, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "08sc.1h", 0x01000, 0x1e5da9d6, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "07sc.1k", 0x01000, 0xa57adb0a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mmi6331-1.6l", 0x00020, 0x24652bc4, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Aracnis) +STD_ROM_FN(Aracnis) + +UINT8 __fastcall ScorpionmcZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0xb001: { + return GalInput[2] | GalDip[2]; + } + + case 0xb002: { + return GalInput[3] | GalDip[3]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall ScorpionmcZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb001: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall ScorpionSoundZ80Read(UINT16 a) +{ + switch (a) { + case 0x3000: { + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0xff; +} + +UINT8 __fastcall ScorpionSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + UINT8 Result = 0xff; + if (a & 0x08) Result &= AY8910Read(2); + if (a & 0x20) Result &= AY8910Read(0); + if (a & 0x80) Result &= AY8910Read(1); + return Result; +} + +void __fastcall ScorpionSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a & 0x04) AY8910Write(2, 0, d); + if (a & 0x08) AY8910Write(2, 1, d); + if (a & 0x10) AY8910Write(0, 0, d); + if (a & 0x20) AY8910Write(0, 1, d); + if (a & 0x40) AY8910Write(1, 0, d); + if (a & 0x80) AY8910Write(1, 1, d); +} + +static UINT8 ScorpionProtectionRead() +{ + UINT16 ParityBits; + UINT8 Parity = 0; + + for (ParityBits = ScrambleProtectionState & 0xce29; ParityBits != 0; ParityBits >>= 1) { + if (ParityBits & 1) Parity++; + } + + return Parity; +} + +static void ScorpionProtectionWrite(UINT8 d) +{ + if (!(d & 0x20)) ScrambleProtectionState = 0x0000; + if (!(d & 0x10)) ScrambleProtectionState = (ScrambleProtectionState << 1) | (~ScorpionProtectionRead() & 1); +} + +static void ScorpionPostLoad() +{ + GalTempRom = (UINT8*)malloc(0x1000); + memcpy(GalTempRom, GalZ80Rom1 + 0x4000, 0x1000); + memcpy(GalZ80Rom1 + 0x4800, GalTempRom + 0x0000, 0x800); + memcpy(GalZ80Rom1 + 0x4000, GalTempRom + 0x0800, 0x800); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + MapTheend(); + + ZetOpen(0); + ZetMapArea(0x5800, 0x67ff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x5800, 0x67ff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static INT32 ScorpionInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = ScorpionPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + ZetOpen(1); + ZetSetReadHandler(ScorpionSoundZ80Read); + ZetSetInHandler(ScorpionSoundZ80PortRead); + ZetSetOutHandler(ScorpionSoundZ80PortWrite); + ZetClose(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = Batman2ExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + KonamiPPIInit(); + PPI1PortReadC = ScorpionProtectionRead; + PPI1PortWriteC = ScorpionProtectionWrite; + + return nRet; +} + +static void ScorpionmcPostLoad() +{ + MapMooncrst(); + + ZetOpen(0); + ZetSetReadHandler(ScorpionmcZ80Read); + ZetSetWriteHandler(ScorpionmcZ80Write); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x5000, 0x67ff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x5000, 0x67ff, 2, GalZ80Rom1 + 0x4000); + ZetMapArea(0x9400, 0x97ff, 0, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 1, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 2, GalVideoRam); + ZetClose(); +} + +static INT32 ScorpionmcInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = ScorpionmcPostLoad; + + nRet = GalInit(); + + GalExtendTileInfoFunction = Batman2ExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + return nRet; +} + +struct BurnDriver BurnDrvScorpion = { + "scorpion", NULL, NULL, NULL, "1982", + "Scorpion (set 1)\0", "Incomplete Sound", "Zaccaria", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScorpionRomInfo, ScorpionRomName, NULL, NULL, AtlantisInputInfo, ScorpionDIPInfo, + ScorpionInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScorpiona = { + "scorpiona", "scorpion", NULL, NULL, "1982", + "Scorpion (set 2)\0", "Incomplete Sound", "Zaccaria", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScorpionaRomInfo, ScorpionaRomName, NULL, NULL, AtlantisInputInfo, ScorpionDIPInfo, + ScorpionInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScorpionb = { + "scorpionb", "scorpion", NULL, NULL, "1982", + "Scorpion (set 3)\0", "Incomplete Sound", "Zaccaria", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScorpionbRomInfo, ScorpionbRomName, NULL, NULL, AtlantisInputInfo, ScorpionDIPInfo, + ScorpionInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScorpionmc = { + "scorpionmc", "scorpion", NULL, NULL, "19??", + "Scorpion (Moon Cresta hardware)\0", NULL, "Dorneer", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScorpionmcRomInfo, ScorpionmcRomName, NULL, NULL, ScorpionmcInputInfo, ScorpionmcDIPInfo, + ScorpionmcInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAracnis = { + "aracnis", "scorpion", NULL, NULL, "19??", + "Aracnis (bootleg of Scorpion on Moon Cresta hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, AracnisRomInfo, AracnisRomName, NULL, NULL, AracnisInputInfo, AracnisDIPInfo, + ScorpionmcInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// A.D. 2083 hardware - based on Scramble with TMS5100A for speech +static struct BurnRomInfo Ad2083RomDesc[] = { + { "ad0.10o", 0x02000, 0x4d34325a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ad1.9o", 0x02000, 0x0f37134b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ad2.8o", 0x02000, 0xbcfa655f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ad3.7o", 0x02000, 0x60655225, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ad1s.3d", 0x02000, 0x80f39b0f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ad2s.4d", 0x01000, 0x5177fe2b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ad4.5k", 0x02000, 0x388cdd21, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ad5.3k", 0x02000, 0xf53f3449, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom-am27s19dc.1m", 0x00020, 0x2759aebd, BRF_GRA | GAL_ROM_PROM }, + + { "ad1v.9a", 0x01000, 0x4cb93fff, BRF_OPT | BRF_SND }, // TMS5110A data + { "ad2v.10a", 0x01000, 0x4b530ea7, BRF_OPT | BRF_SND }, // TMS5110A data + { "prom-sn74s188.8a", 0x00020, 0xc58a4f6a, BRF_OPT | BRF_SND }, // TMS5110A data +}; + +STD_ROM_PICK(Ad2083) +STD_ROM_FN(Ad2083) + +UINT8 __fastcall Ad2083Z80Read(UINT16 a) +{ + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + case 0x8000: { + return GalInput[0] | GalDip[0]; + } + + case 0x8001: { + return GalInput[1] | GalDip[1]; + } + + case 0x8002: { + return GalInput[2] | GalDip[2]; + } + + case 0x8003: { + return GalInput[3] | GalDip[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Ad2083Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6004: { + GalFlipScreenX = d & 1; + GalFlipScreenY = d & 1; + return; + } + + case 0x6800: { + // coin_counter_2_w + return; + } + + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_counter_0_w + return; + } + + case 0x6803: { + GalBackgroundBlue = d & 1; + return; + } + + case 0x6805: { + // coin_counter_1_w + return; + } + + case 0x6806: { + GalBackgroundRed = d & 1; + return; + } + + case 0x6807: { + GalBackgroundGreen = d & 1; + return; + } + + case 0x8000: { + GalSoundLatch = d; + return; + } + + case 0x9000: { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static void Ad2083PostLoad() +{ + UINT8 c; + + for (UINT32 i = 0; i < GalZ80Rom1Size; i++) { + c = GalZ80Rom1[i] ^ 0x35; + c = BITSWAP08(c, 6, 2, 5, 1, 7, 3, 4, 0); + GalZ80Rom1[i] = c; + } + + MapTheend(); + + ZetOpen(0); + ZetSetReadHandler(Ad2083Z80Read); + ZetSetWriteHandler(Ad2083Z80Write); + ZetMapArea(0xa000, 0xdfff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0xa000, 0xdfff, 2, GalZ80Rom1 + 0x4000); + ZetMapArea(0xe800, 0xebff, 0, GalZ80Ram1 + 0x800); + ZetMapArea(0xe800, 0xebff, 1, GalZ80Ram1 + 0x800); + ZetMapArea(0xe800, 0xebff, 2, GalZ80Ram1 + 0x800); + ZetClose(); +} + +static INT32 Ad2083Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = Ad2083PostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_AD2083AY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + ZetOpen(1); + ZetSetInHandler(HotshockSoundZ80PortRead); + ZetSetOutHandler(HotshockSoundZ80PortWrite); + ZetClose(); + + GalRenderBackgroundFunction = TurtlesDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = Ad2083ExtendTileInfo; + GalExtendSpriteInfoFunction = Ad2083ExtendSpriteInfo; + + GalSoundVolumeShift = 0; + + return nRet; +} + +struct BurnDriver BurnDrvAd2083 = { + "ad2083", NULL, NULL, NULL, "1983", + "A.D. 2083\0", "Incomplete Sound", "Midcoin", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, Ad2083RomInfo, Ad2083RomName, NULL, NULL, Ad2083InputInfo, Ad2083DIPInfo, + Ad2083Init, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// SF-X hardware - based on Scramble with extra Z80 and 8255 driving a DAC based sample player +static struct BurnRomInfo SfxRomDesc[] = { + { "sfx_b-0.1j", 0x02000, 0xe5bc6952, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "1.1c", 0x01000, 0x1b3c48e7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "22.1d", 0x01000, 0xed44950d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "23.1e", 0x01000, 0xf44a3ca0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "27.1a", 0x01000, 0xed86839f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "24.1g", 0x01000, 0xe6d7dc74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "5.1h", 0x01000, 0xd1e8d390, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5.5j", 0x01000, 0x59028fb6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "6.6j", 0x01000, 0x5427670f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "1.1j", 0x01000, 0x2f172c58, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "2.2j", 0x01000, 0xa6ad2f6b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "3.3j", 0x01000, 0xfa1274fa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "4.4j", 0x01000, 0x1cd33f3a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "10.3h", 0x01000, 0xb833a15b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "11.4h", 0x01000, 0xcbd76ec2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + + { "28.5a", 0x01000, 0xd73a8252, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "29.5c", 0x01000, 0x1401ccf2, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6331.9g", 0x00020, 0xca1d9ccd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Sfx) +STD_ROM_FN(Sfx) + +static struct BurnRomInfo SkelagonRomDesc[] = { + { "31.bin", 0x01000, 0xae6f8647, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "32.bin", 0x01000, 0xa28c5838, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "33.bin", 0x01000, 0x32f7e99c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "37.bin", 0x01000, 0x47f68a31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "24.bin", 0x01000, 0xe6d7dc74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "35.bin", 0x01000, 0x5b2a0158, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "36.bin", 0x01000, 0xf53ead29, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5.5j", 0x01000, 0x59028fb6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "6.6j", 0x01000, 0x5427670f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "1.1j", 0x01000, 0x2f172c58, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "2.2j", 0x01000, 0xa6ad2f6b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "3.3j", 0x01000, 0xfa1274fa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "4.4j", 0x01000, 0x1cd33f3a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "10.bin", 0x01000, 0x2c719de2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "8.bin", 0x01000, 0x350379dd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + + { "38.bin", 0x01000, 0x2fffa8b1, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "39.bin", 0x01000, 0xa854b5de, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6331.9g", 0x00020, 0xca1d9ccd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Skelagon) +STD_ROM_FN(Skelagon) + +static struct BurnRomInfo MonsterzRomDesc[] = { + { "b-1e.a1", 0x01000, 0x97886542, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b-2e.c1", 0x01000, 0x184ffcb4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b-3e.d1", 0x01000, 0xb7b10ac7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b-4e.e1", 0x01000, 0xfb02c736, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b-5e.g1", 0x01000, 0xb2788ab9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b-6e.h1", 0x01000, 0x77d7aa8d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "a-1e.k1", 0x01000, 0xb88ba44e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "a-2.k2", 0x01000, 0x8913c94e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "a-3e.k3", 0x01000, 0xa8fa5095, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "a-4.k4", 0x01000, 0x93f81317, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "a-5e.k5", 0x01000, 0xb5bcdb4e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "a-6.k6", 0x01000, 0x24832b2e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "a-7e.k7", 0x01000, 0x20ebea81, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "a-8.k8", 0x01000, 0xb833a15b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + { "a-9.k9", 0x01000, 0xcbd76ec2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG3 }, + + { "b-7e.a5", 0x01000, 0xddd4158d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "b-8e.c5", 0x01000, 0xb1331b4c, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.g9", 0x00020, 0xb7ea00d7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Monsterz) +STD_ROM_FN(Monsterz) + +void __fastcall SfxZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8000) { + INT32 Offset = a - 0x8000; + if (Offset & 0x0100) ppi8255_w(0, Offset & 3, d); + if (Offset & 0x0200) ppi8255_w(1, Offset & 3, d); + return; + } + + switch (a) { + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_count_0_w + return; + } + + case 0x6800: { + GalBackgroundRed = d & 1; + return; + } + + case 0x6803: { + GalBackgroundBlue = d & 1; + return; + } + + case 0x6804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6805: { + GalBackgroundGreen = d & 1; + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall SfxSampleZ80Read(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall SfxSampleZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall SfxSampleZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Port Read => %02X\n"), a); + } + } + + return 0xff; +} + +void __fastcall SfxSampleZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static UINT8 SfxSoundLatch2Read() +{ + bprintf(PRINT_NORMAL, _T("Sound Latch2 Read\n")); + return GalSoundLatch2; +} + +static void SfxPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetWriteHandler(SfxZ80Write); + ZetMapArea(0x7000, 0x7fff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x7000, 0x7fff, 2, GalZ80Rom1 + 0x4000); + ZetMapArea(0xc000, 0xefff, 0, GalZ80Rom1 + 0x5000); + ZetMapArea(0xc000, 0xefff, 2, GalZ80Rom1 + 0x5000); + ZetClose(); + + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memcpy(GalZ80Rom1 + 0x0000, GalTempRom + 0x0000, 0x1000); + memcpy(GalZ80Rom1 + 0x7000, GalTempRom + 0x1000, 0x1000); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x2000, 0x6000); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + ZetOpen(2); + ZetSetReadHandler(SfxSampleZ80Read); + ZetSetWriteHandler(SfxSampleZ80Write); + ZetSetInHandler(SfxSampleZ80PortRead); + ZetSetOutHandler(SfxSampleZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 0, GalZ80Rom3); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 2, GalZ80Rom3); + ZetClose(); +} + +static INT32 SfxInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = SfxPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = UpperExtendTileInfo; + + ppi8255_init(3); + PPI0PortReadA = KonamiPPIReadIN0; + PPI0PortReadB = KonamiPPIReadIN1; + PPI0PortReadC = KonamiPPIReadIN2; + PPI1PortReadC = KonamiPPIReadIN3; + PPI1PortWriteA = KonamiSoundLatchWrite; + PPI1PortWriteB = KonamiSoundControlWrite; + PPI2PortReadA = SfxSoundLatch2Read; + + SfxTilemap = 1; + GalOrientationFlipX = 1; + + GalSoundVolumeShift = 3; + + return nRet; +} + +static void SkelagonPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetWriteHandler(SfxZ80Write); + ZetMapArea(0x7000, 0x7fff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x7000, 0x7fff, 2, GalZ80Rom1 + 0x4000); + ZetMapArea(0xc000, 0xefff, 0, GalZ80Rom1 + 0x5000); + ZetMapArea(0xc000, 0xefff, 2, GalZ80Rom1 + 0x5000); + ZetClose(); + + GalTempRom = (UINT8*)malloc(GalZ80Rom1Size); + memcpy(GalTempRom, GalZ80Rom1, GalZ80Rom1Size); + memset(GalZ80Rom1, 0xff, 0x1000); + memcpy(GalZ80Rom1 + 0x1000, GalTempRom + 0x0000, 0x7000); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + ZetOpen(2); + ZetSetReadHandler(SfxSampleZ80Read); + ZetSetWriteHandler(SfxSampleZ80Write); + ZetSetInHandler(SfxSampleZ80PortRead); + ZetSetOutHandler(SfxSampleZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 0, GalZ80Rom3); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 2, GalZ80Rom3); + ZetClose(); +} + +static INT32 SkelagonInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = SkelagonPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC; + GalZ80Rom1Size = 0x1000; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = UpperExtendTileInfo; + + ppi8255_init(3); + PPI0PortReadA = KonamiPPIReadIN0; + PPI0PortReadB = KonamiPPIReadIN1; + PPI0PortReadC = KonamiPPIReadIN2; + PPI1PortReadC = KonamiPPIReadIN3; + PPI1PortWriteA = KonamiSoundLatchWrite; + PPI1PortWriteB = KonamiSoundControlWrite; + PPI2PortReadA = SfxSoundLatch2Read; + + SfxTilemap = 1; + GalOrientationFlipX = 1; + + return nRet; +} + +static void MonsterzPostLoad() +{ + MapTheend(); + + ZetOpen(0); + ZetSetWriteHandler(SfxZ80Write); + ZetMapArea(0xc000, 0xdfff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0xc000, 0xdfff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(SfxSampleZ80Read); + ZetSetWriteHandler(SfxSampleZ80Write); + ZetSetInHandler(SfxSampleZ80PortRead); + ZetSetOutHandler(SfxSampleZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 0, GalZ80Rom3); + ZetMapArea(0x0000, GalZ80Rom3Size - 1, 2, GalZ80Rom3); + ZetClose(); + + GalTempRom = (UINT8*)malloc(GalZ80Rom3Size); + memcpy(GalTempRom, GalZ80Rom3, GalZ80Rom3Size); + memcpy(GalZ80Rom3 + 0x0000, GalTempRom + 0x0000, 0x3000); + memset(GalZ80Rom3 + 0x3000, 0xff, 0x1000); + memcpy(GalZ80Rom3 + 0x4000, GalTempRom + 0x3000, 0x2000); +} + +static INT32 MonsterzInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MonsterzPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC; + GalZ80Rom3Size = 0x1000; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = UpperExtendTileInfo; + + ppi8255_init(3); + PPI0PortReadA = KonamiPPIReadIN0; + PPI0PortReadB = KonamiPPIReadIN1; + PPI0PortReadC = KonamiPPIReadIN2; + PPI1PortReadC = KonamiPPIReadIN3; + PPI1PortWriteA = KonamiSoundLatchWrite; + PPI1PortWriteB = KonamiSoundControlWrite; + PPI2PortReadA = SfxSoundLatch2Read; + + SfxTilemap = 1; + GalOrientationFlipX = 1; + + return nRet; +} + +struct BurnDriver BurnDrvSfx = { + "sfx", NULL, NULL, NULL, "1983", + "SF-X\0", "Incomplete Sound", "Nichibutsu", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, SfxRomInfo, SfxRomName, NULL, NULL, SfxInputInfo, SfxDIPInfo, + SfxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvSkelagon = { + "skelagon", "sfx", NULL, NULL, "1983", + "Skelagon\0", "Bad Dump", "Nichibutsu USA", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, SkelagonRomInfo, SkelagonRomName, NULL, NULL, SfxInputInfo, SfxDIPInfo, + SkelagonInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvMonsterz = { + "monsterz", NULL, NULL, NULL, "19??", + "Monster Zero\0", "Protected", "Nihon", "Galaxian", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MonsterzRomInfo, MonsterzRomName, NULL, NULL, SfxInputInfo, SfxDIPInfo, + MonsterzInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +// Super Cobra based hardware +static struct BurnRomInfo ScobraRomDesc[] = { + { "epr1265.2c", 0x01000, 0xa0744b3f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x01000, 0x8e7245cd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1267.2f", 0x01000, 0x47a4e6fb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h", 0x01000, 0x7244f21c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1269.2j", 0x01000, 0xe1f8a801, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l", 0x01000, 0xd52affde, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5c", 0x00800, 0xd4346959, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5d", 0x00800, 0xcc025d95, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5e", 0x00800, 0x1628c53f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr1274.5h", 0x00800, 0x64d113b4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr1273.5f", 0x00800, 0xa96316d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x9b87f90d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scobra) +STD_ROM_FN(Scobra) + +static struct BurnRomInfo ScobrasRomDesc[] = { + { "scobra2c.bin", 0x01000, 0xe15ade38, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2e.bin", 0x01000, 0xa270e44d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2f.bin", 0x01000, 0xbdd70346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2h.bin", 0x01000, 0xdca5ec31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2j.bin", 0x01000, 0x0d8f6b6e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2l.bin", 0x01000, 0x6f80f3a9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr1275.5c", 0x00800, 0xdeeb0dd3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1276.5d", 0x00800, 0x872c1a74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1277.5e", 0x00800, 0xccd7a110, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr1274.5h", 0x00800, 0x64d113b4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr1273.5f", 0x00800, 0xa96316d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x9b87f90d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scobras) +STD_ROM_FN(Scobras) + +static struct BurnRomInfo ScobraseRomDesc[] = { + { "epr1265.2c", 0x01000, 0xa0744b3f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1266.2e", 0x01000, 0x65306279, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1267.2f", 0x01000, 0x47a4e6fb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1268.2h", 0x01000, 0x53eecaf2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1269.2j", 0x01000, 0xe1f8a801, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "epr1270.2l", 0x01000, 0xf7709710, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr1275.5c", 0x00800, 0xdeeb0dd3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1276.5d", 0x00800, 0x872c1a74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1277.5e", 0x00800, 0xccd7a110, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr1274.5h", 0x00800, 0x64d113b4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr1273.5f", 0x00800, 0xa96316d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "pr1278.6e", 0x00020, 0xfd35c561, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scobrase) +STD_ROM_FN(Scobrase) + +static struct BurnRomInfo ScobrabRomDesc[] = { + { "vid_2c.bin", 0x00800, 0xaeddf391, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "vid_2e.bin", 0x00800, 0x72b57eb7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2e.bin", 0x01000, 0xa270e44d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2f.bin", 0x01000, 0xbdd70346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2h.bin", 0x01000, 0xdca5ec31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2j.bin", 0x01000, 0x0d8f6b6e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2l.bin", 0x01000, 0x6f80f3a9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr1275.5c", 0x00800, 0xdeeb0dd3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1276.5d", 0x00800, 0x872c1a74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1277.5e", 0x00800, 0xccd7a110, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr1274.5h", 0x00800, 0x64d113b4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr1273.5f", 0x00800, 0xa96316d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x9b87f90d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Scobrab) +STD_ROM_FN(Scobrab) + +static struct BurnRomInfo SuprheliRomDesc[] = { + { "1.2c", 0x01000, 0xb25141d8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2e.bin", 0x01000, 0xa270e44d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2f.bin", 0x01000, 0xbdd70346, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2h.bin", 0x01000, 0xdca5ec31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "scobra2j.bin", 0x01000, 0x0d8f6b6e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "6.2l", 0x01000, 0x10a474d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "epr1275.5c", 0x00800, 0xdeeb0dd3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "epr1276.5d", 0x00800, 0x872c1a74, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "9.9d", 0x00800, 0x2b69b8f3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "epr1274.5h", 0x00800, 0x64d113b4, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "epr1273.5f", 0x00800, 0xa96316d3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "k.6e", 0x00020, 0xfd35c561, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Suprheli) +STD_ROM_FN(Suprheli) + +static struct BurnRomInfo LosttombRomDesc[] = { + { "2c", 0x01000, 0xd6176d2c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x01000, 0xa5f55f4a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f", 0x01000, 0x0169fa3c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h-easy", 0x01000, 0x054481b6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x01000, 0x249ee040, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l", 0x01000, 0xc7d2e608, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2m", 0x01000, 0xbc4bc5b1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5c", 0x00800, 0xb899be2a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5d", 0x00800, 0x6907af31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f", 0x00800, 0x61f137e7, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h", 0x00800, 0x5581de5f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "ltprom", 0x00020, 0x1108b816, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Losttomb) +STD_ROM_FN(Losttomb) + +static struct BurnRomInfo LosttombhRomDesc[] = { + { "2c", 0x01000, 0xd6176d2c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x01000, 0xa5f55f4a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f", 0x01000, 0x0169fa3c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "lthard", 0x01000, 0xe32cbf0e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x01000, 0x249ee040, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l", 0x01000, 0xc7d2e608, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2m", 0x01000, 0xbc4bc5b1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5c", 0x00800, 0xb899be2a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5d", 0x00800, 0x6907af31, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f", 0x00800, 0x61f137e7, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h", 0x00800, 0x5581de5f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "ltprom", 0x00020, 0x1108b816, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Losttombh) +STD_ROM_FN(Losttombh) + +static struct BurnRomInfo ArmorcarRomDesc[] = { + { "cpu.2c", 0x01000, 0x0d7bfdfb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cpu.2e", 0x01000, 0x76463213, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cpu.2f", 0x01000, 0x2cc6d5f0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cpu.2h", 0x01000, 0x61278dbb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "cpu.2j", 0x01000, 0xfb158d8c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sound.5c", 0x00800, 0x54ee7753, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "sound.5d", 0x00800, 0x5218fec0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "cpu.5f", 0x00800, 0x8a3da4d1, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "cpu.5h", 0x00800, 0x85bdb113, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x9b87f90d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Armorcar) +STD_ROM_FN(Armorcar) + +static struct BurnRomInfo Armorcar2RomDesc[] = { + { "2c", 0x01000, 0xe393bd2f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x01000, 0xb7d443af, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2g", 0x01000, 0xe67380a4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h", 0x01000, 0x72af7b37, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j", 0x01000, 0xe6b0dd7f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "sound.5c", 0x00800, 0x54ee7753, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "sound.5d", 0x00800, 0x5218fec0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "cpu.5f", 0x00800, 0x8a3da4d1, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "cpu.5h", 0x00800, 0x85bdb113, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x9b87f90d, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Armorcar2) +STD_ROM_FN(Armorcar2) + +static struct BurnRomInfo TazmaniaRomDesc[] = { + { "2c.cpu", 0x01000, 0x932c5a06, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e.cpu", 0x01000, 0xef17ce65, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f.cpu", 0x01000, 0x43c7c39d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h.cpu", 0x01000, 0xbe829694, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j.cpu", 0x01000, 0x6e197271, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2k.cpu", 0x01000, 0xa1eb453b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rom0.snd", 0x00800, 0xb8d741f1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f.cpu", 0x00800, 0x2c5b612b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h.cpu", 0x00800, 0x3f5ff3ac, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colr6f.cpu", 0x00020, 0xfce333c7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Tazmania) +STD_ROM_FN(Tazmania) + +static struct BurnRomInfo Tazmani2RomDesc[] = { + { "2ck.cpu", 0x01000, 0xbf0492bf, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2ek.cpu", 0x01000, 0x6636c4d0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2fk.cpu", 0x01000, 0xce59a57b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2hk.cpu", 0x01000, 0x8bda3380, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2jk.cpu", 0x01000, 0xa4095e35, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2kk.cpu", 0x01000, 0xf308ca36, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rom0.snd", 0x00800, 0xb8d741f1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f.cpu", 0x00800, 0x2c5b612b, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h.cpu", 0x00800, 0x3f5ff3ac, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colr6f.cpu", 0x00020, 0xfce333c7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Tazmani2) +STD_ROM_FN(Tazmani2) + +static struct BurnRomInfo AnteaterRomDesc[] = { + { "ra1-2c", 0x01000, 0x58bc9393, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ra1-2e", 0x01000, 0x574fc6f6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ra1-2f", 0x01000, 0x2f7c1fe5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ra1-2h", 0x01000, 0xae8a5da3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ra4-5c", 0x00800, 0x87300b4f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ra4-5d", 0x00800, 0xaf4e5ffe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ra6-5f", 0x00800, 0x4c3f8a08, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ra6-5h", 0x00800, 0xb30c7c9f, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colr6f.cpu", 0x00020, 0xfce333c7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Anteater) +STD_ROM_FN(Anteater) + +static struct BurnRomInfo AnteatergRomDesc[] = { + { "prg_2.bin", 0x02000, 0x2ba793a8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "prg_1.bin", 0x02000, 0x7a798af5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ra4-5c", 0x00800, 0x87300b4f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ra4-5d", 0x00800, 0xaf4e5ffe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "gfx_1.bin", 0x00800, 0x1e2824b1, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "gfx_2.bin", 0x00800, 0x784319b3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colr6f.cpu", 0x00020, 0xfce333c7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Anteaterg) +STD_ROM_FN(Anteaterg) + +static struct BurnRomInfo AnteaterukRomDesc[] = { + { "ant1.bin", 0x02000, 0x69debc90, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ant2.bin", 0x02000, 0xab352805, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ra4-5c", 0x00800, 0x87300b4f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ra4-5d", 0x00800, 0xaf4e5ffe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "gfx_1.bin", 0x00800, 0x1e2824b1, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "gfx_2.bin", 0x00800, 0x784319b3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "colr6f.cpu", 0x00020, 0xfce333c7, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Anteateruk) +STD_ROM_FN(Anteateruk) + +static struct BurnRomInfo SpdcoinRomDesc[] = { + { "spdcoin.2c", 0x01000, 0x65cf1e49, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "spdcoin.2e", 0x01000, 0x1ee59232, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "spdcoin.5c", 0x00800, 0xb4cf64b7, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "spdcoin.5d", 0x00800, 0x92304df0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "spdcoin.5f", 0x00800, 0xdd5f1dbc, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "spdcoin.5h", 0x00800, 0xab1fe81b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "spdcoin.clr", 0x00020, 0x1a2ccc56, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Spdcoin) +STD_ROM_FN(Spdcoin) + +static struct BurnRomInfo SuperbonRomDesc[] = { + { "2d.cpu", 0x01000, 0x60c0ba18, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e.cpu", 0x01000, 0xddcf44bf, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f.cpu", 0x01000, 0xbb66c2d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h.cpu", 0x01000, 0x74f4f04d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j.cpu", 0x01000, 0x78effb08, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l.cpu", 0x01000, 0xe9dcecbd, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2m.cpu", 0x01000, 0x3ed0337e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5c", 0x00800, 0xb899be2a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "5d.snd", 0x00800, 0x80640a04, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f.cpu", 0x00800, 0x5b9d4686, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h.cpu", 0x00800, 0x58c29927, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "superbon.clr", 0x00020, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(Superbon) +STD_ROM_FN(Superbon) + +static struct BurnRomInfo CalipsoRomDesc[] = { + { "calipso.2c", 0x01000, 0x0fcb703c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "calipso.2e", 0x01000, 0xc6622f14, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "calipso.2f", 0x01000, 0x7bacbaba, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "calipso.2h", 0x01000, 0xa3a8111b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "calipso.2j", 0x01000, 0xfcbd7b9e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "calipso.2l", 0x01000, 0xf7630cab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "calipso.5c", 0x00800, 0x9cbc65ab, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "calipso.5d", 0x00800, 0xa225ee3b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "calipso.5f", 0x02000, 0xfd4252e9, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "calipso.5h", 0x02000, 0x1663a73a, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "calipso.clr", 0x00020, 0x01165832, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Calipso) +STD_ROM_FN(Calipso) + +static struct BurnRomInfo MoonwarRomDesc[] = { + { "mw2.2c", 0x01000, 0x7c11b4d9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mw2.2e", 0x01000, 0x1b6362be, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mw2.2f", 0x01000, 0x4fd8ba4b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mw2.2h", 0x01000, 0x56879f0d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mw2.5c", 0x00800, 0xc26231eb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "mw2.5d", 0x00800, 0xbb48a646, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "mw2.5f", 0x00800, 0xc5fa1aa0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mw2.5h", 0x00800, 0xa6ccc652, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mw2.clr", 0x00020, 0x99614c6c, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonwar) +STD_ROM_FN(Moonwar) + +static struct BurnRomInfo MoonwaraRomDesc[] = { + { "2c", 0x01000, 0xbc20b734, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e", 0x01000, 0xdb6ffec2, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f", 0x01000, 0x378931b8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h", 0x01000, 0x031dbc2c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mw2.5c", 0x00800, 0xc26231eb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "mw2.5d", 0x00800, 0xbb48a646, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "mw2.5f", 0x00800, 0xc5fa1aa0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mw2.5h", 0x00800, 0xa6ccc652, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "moonwara.clr", 0x00020, 0xf58d4f58, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Moonwara) +STD_ROM_FN(Moonwara) + +static struct BurnRomInfo StratgyxRomDesc[] = { + { "2c_1.bin", 0x01000, 0xeec01237, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e_2.bin", 0x01000, 0x926cb2d5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f_3.bin", 0x01000, 0x849e2504, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h_4.bin", 0x01000, 0x8a64069b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j_5.bin", 0x01000, 0x78b9b898, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l_6.bin", 0x01000, 0x20bae414, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "s1.bin", 0x01000, 0x713a5db8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "s2.bin", 0x01000, 0x46079411, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f_c2.bin", 0x00800, 0x7121b679, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h_c1.bin", 0x00800, 0xd105ad91, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "strategy.6e", 0x00020, 0x51a629e1, BRF_GRA | GAL_ROM_PROM }, + { "strategy.10k", 0x00020, 0xd95c0318, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Stratgyx) +STD_ROM_FN(Stratgyx) + +static struct BurnRomInfo StratgysRomDesc[] = { + { "2c.cpu", 0x01000, 0xf2aaaf2b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2e.cpu", 0x01000, 0x5873fdc8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f.cpu", 0x01000, 0x532d604f, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h.cpu", 0x01000, 0x82b1d95e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j.cpu", 0x01000, 0x66e84cde, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l.cpu", 0x01000, 0x62b032d0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "s1.bin", 0x01000, 0x713a5db8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "s2.bin", 0x01000, 0x46079411, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f.cpu", 0x00800, 0xf4aa5ddd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h.cpu", 0x00800, 0x548e4635, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "strategy.6e", 0x00020, 0x51a629e1, BRF_GRA | GAL_ROM_PROM }, + { "strategy.10k", 0x00020, 0xd95c0318, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Stratgys) +STD_ROM_FN(Stratgys) + +static struct BurnRomInfo StrongxRomDesc[] = { + { "strongx.2d", 0x01000, 0xc2f7268c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "strongx.2e", 0x01000, 0x91059422, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2f_3.bin", 0x01000, 0x849e2504, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2h_4.bin", 0x01000, 0x8a64069b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2j_5.bin", 0x01000, 0x78b9b898, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "2l_6.bin", 0x01000, 0x20bae414, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "s1.bin", 0x01000, 0x713a5db8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "s2.bin", 0x01000, 0x46079411, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "5f_c2.bin", 0x00800, 0x7121b679, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h_c1.bin", 0x00800, 0xd105ad91, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "strategy.6e", 0x00020, 0x51a629e1, BRF_GRA | GAL_ROM_PROM }, + { "strategy.10k", 0x00020, 0xd95c0318, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Strongx) +STD_ROM_FN(Strongx) + +static struct BurnRomInfo DarkplntRomDesc[] = { + { "drkplt2c.dat", 0x01000, 0x5a0ca559, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2e.dat", 0x01000, 0x52e2117d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2g.dat", 0x01000, 0x4093219c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2j.dat", 0x01000, 0xb974c78d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2k.dat", 0x01000, 0x71a37385, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2l.dat", 0x01000, 0x5ad25154, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2m.dat", 0x01000, 0x8d2f0122, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "drkplt2p.dat", 0x01000, 0x2d66253b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5c.snd", 0x01000, 0x672b9454, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "drkplt5f.dat", 0x00800, 0x2af0ee66, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "drkplt5h.dat", 0x00800, 0x66ef3225, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6e.cpu", 0x00020, 0x86b6e124, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Darkplnt) +STD_ROM_FN(Darkplnt) + +static struct BurnRomInfo RescueRomDesc[] = { + { "rb15acpu.bin", 0x01000, 0xd7e654ba, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15bcpu.bin", 0x01000, 0xa93ea158, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15ccpu.bin", 0x01000, 0x058cd3d0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15dcpu.bin", 0x01000, 0xd6505742, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15ecpu.bin", 0x01000, 0x604df3a4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rb15csnd.bin", 0x00800, 0x8b24bf17, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "rb15dsnd.bin", 0x00800, 0xd96e4fb3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "rb15fcpu.bin", 0x00800, 0x4489d20c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rb15hcpu.bin", 0x00800, 0x5512c547, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "rescue.clr", 0x00020, 0x40c6bcbd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Rescue) +STD_ROM_FN(Rescue) + +static struct BurnRomInfo AponowRomDesc[] = { + { "aponow01.rom", 0x01000, 0x33011579, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "aponow02.rom", 0x01000, 0xd477573e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "aponow03.rom", 0x01000, 0x46c41898, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15dcpu.bin", 0x01000, 0xd6505742, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "rb15ecpu.bin", 0x01000, 0x604df3a4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "rb15csnd.bin", 0x00800, 0x8b24bf17, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "rb15dsnd.bin", 0x00800, 0xd96e4fb3, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "rb15fcpu.bin", 0x00800, 0x4489d20c, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rb15hcpu.bin", 0x00800, 0x5512c547, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "rescue.clr", 0x00020, 0x40c6bcbd, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Aponow) +STD_ROM_FN(Aponow) + +static struct BurnRomInfo MinefldRomDesc[] = { + { "ma22c", 0x01000, 0x1367a035, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ma22e", 0x01000, 0x68946d21, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ma22f", 0x01000, 0x7663aee5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ma22h", 0x01000, 0x9787475d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ma22j", 0x01000, 0x2ceceb54, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "ma22l", 0x01000, 0x85138fc9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "ma15c", 0x00800, 0x8bef736b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "ma15d", 0x00800, 0xf67b3f97, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "ma15f", 0x00800, 0x9f703006, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "ma15h", 0x00800, 0xed0dccb1, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "minefld.clr", 0x00020, 0x1877368e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Minefld) +STD_ROM_FN(Minefld) + +static struct BurnRomInfo HustlerRomDesc[] = { + { "hustler.1", 0x01000, 0x94479a3e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hustler.2", 0x01000, 0x3cc67bcc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hustler.3", 0x01000, 0x9422226a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hustler.6", 0x00800, 0x7a946544, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "hustler.7", 0x00800, 0x3db57351, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "hustler.5f", 0x00800, 0x0bdfad0e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hustler.5h", 0x00800, 0x8e062177, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "hustler.clr", 0x00020, 0xaa1f7f5e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Hustler) +STD_ROM_FN(Hustler) + +static struct BurnRomInfo BilliardRomDesc[] = { + { "a", 0x01000, 0xb7eb50c0, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "b", 0x01000, 0x988fe1c5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "c", 0x01000, 0x7b8de793, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hustler.6", 0x00800, 0x7a946544, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "hustler.7", 0x00800, 0x3db57351, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "hustler.5f", 0x00800, 0x0bdfad0e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hustler.5h", 0x00800, 0x8e062177, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "hustler.clr", 0x00020, 0xaa1f7f5e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Billiard) +STD_ROM_FN(Billiard) + +static struct BurnRomInfo HustlerbRomDesc[] = { + { "hustler.2c", 0x01000, 0x3a1ac6a9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hustler.2f", 0x01000, 0xdc6752ec, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "hustler.2j", 0x01000, 0x27c1e0f8, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hustler.11d", 0x00800, 0xb559bfde, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "hustler.10d", 0x00800, 0x6ef96cfb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "hustler.5f", 0x00800, 0x0bdfad0e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hustler.5h", 0x00800, 0x8e062177, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "hustler.clr", 0x00020, 0xaa1f7f5e, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Hustlerb) +STD_ROM_FN(Hustlerb) + +static struct BurnRomInfo MimonkeyRomDesc[] = { + { "mm1.2e", 0x01000, 0x9019f1b1, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm2.2e", 0x01000, 0x043e97d6, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm3.2f", 0x01000, 0x1052726a, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm4.2h", 0x01000, 0x7b3f35ff, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm5.2j", 0x01000, 0xb4e5c32d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm6.2l", 0x01000, 0x409036c4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm7.2m", 0x01000, 0x119c08fa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "mm8.2p", 0x01000, 0xf7989f04, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mm13.11d", 0x01000, 0x2d14c527, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "mm14.10d", 0x01000, 0x35ed0f96, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "mm12.5h", 0x01000, 0xf73a8412, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mm10.5h", 0x01000, 0x3828c9db, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mm11.5f", 0x01000, 0x9e0e9289, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mm9.5f", 0x01000, 0x92085b0c, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mimonkey) +STD_ROM_FN(Mimonkey) + +static struct BurnRomInfo MimonscoRomDesc[] = { + { "fra_1a", 0x01000, 0x8e7a7379, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_1b", 0x01000, 0xab08cbfe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_2a", 0x01000, 0x2d4da24d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_2b", 0x01000, 0x8d88fc7c, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_3a", 0x01000, 0xb4e5c32d, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_3b", 0x01000, 0x409036c4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_4a", 0x01000, 0x119c08fa, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "fra_4b", 0x01000, 0xd700fd03, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "mmsound1", 0x01000, 0x2d14c527, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + { "mmsnd2a", 0x01000, 0x35ed0f96, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG2 }, + + { "mmgfx1", 0x02000, 0x4af47337, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "mmgfx2", 0x02000, 0xdef47da8, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, +}; + +STD_ROM_PICK(Mimonsco) +STD_ROM_FN(Mimonsco) + +UINT8 __fastcall Tazmani2Z80Read(UINT16 a) +{ + if (a >= 0xa000 && a <= 0xa00f) { + return ppi8255_r(0, (a - 0xa000) >> 2); + } + + if (a >= 0xa800 && a <= 0xa80f) { + return ppi8255_r(1, (a - 0xa800) >> 2); + } + + switch (a) { + case 0x9800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Tazmani2Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x8800 && a <= 0x88ff) { + INT32 Offset = a - 0x8800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xa000 && a <= 0xa00f) { + ppi8255_w(0, (a - 0xa000) >> 2, d); + return; + } + + if (a >= 0xa800 && a <= 0xa80f) { + ppi8255_w(1, (a - 0xa800) >> 2, d); + return; + } + + switch (a) { + case 0xb000: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb002: { + GalBackgroundEnable = d & 1; + return; + } + + case 0xb004: { + GalIrqFire = d & 1; + return; + } + + case 0xb006: { + // coin_count_0_w + return; + } + + case 0xb00c: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb00e: { + GalFlipScreenX = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall AnteatergZ80Read(UINT16 a) +{ + switch (a) { + case 0xf521: { + // watchdog read + return 0xff; + } + + case 0xf612: { + return ppi8255_r(0, 0); + } + + case 0xf631: { + return ppi8255_r(0, 1); + } + + case 0xf710: { + return ppi8255_r(0, 2); + } + + case 0xf753: { + return ppi8255_r(0, 3); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall AnteatergZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x2000 && a <= 0x20ff) { + INT32 Offset = a - 0x2000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x2423: { + ppi8255_w(1, 3, d); + return; + } + + case 0x2450: { + ppi8255_w(1, 0, d); + return; + } + + case 0x2511: { + ppi8255_w(1, 1, d); + return; + } + + case 0x2621: { + GalIrqFire = d & 1; + return; + } + + case 0x2624: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x2647: { + GalFlipScreenY = d & 1; + return; + } + + case 0x2653: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x2702: { + // coin_count_0_w + return; + } + + case 0x2736: { + GalFlipScreenX = d & 1; + return; + } + + case 0xf612: { + ppi8255_w(0, 0, d); + return; + } + + case 0xf631: { + ppi8255_w(0, 1, d); + return; + } + + case 0xf710: { + ppi8255_w(0, 2, d); + return; + } + + case 0xf753: { + ppi8255_w(0, 3, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall AnteatgbZ80Read(UINT16 a) +{ + switch (a) { + case 0x145b: { + // watchdog read + return 0xff; + } + + case 0xf300: + case 0xf301: + case 0xf302: + case 0xf303: { + return ppi8255_r(0, a - 0xf300); + } + + case 0xfe00: + case 0xfe01: + case 0xfe02: + case 0xfe03: { + return ppi8255_r(1, a - 0xfe00); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall AnteatgbZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x1200 && a <= 0x12ff) { + INT32 Offset = a - 0x1200; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x1171: { + GalIrqFire = d & 1; + return; + } + + case 0x1172: { + // coin_count_0_w + return; + } + + case 0x1173: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x1174: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x1176: { + GalFlipScreenX = d & 1; + return; + } + + case 0x1177: { + GalFlipScreenY = d & 1; + return; + } + + case 0xf300: + case 0xf301: + case 0xf302: + case 0xf303: { + ppi8255_w(0, a - 0xf300, d); + return; + } + + case 0xfe00: + case 0xfe01: + case 0xfe02: + case 0xfe03: { + ppi8255_w(1, a - 0xfe00, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall StratgyxZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x8800 && a <= 0x88ff) { + INT32 Offset = a - 0x8800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xa000 && a <= 0xa00f) { + ppi8255_w(0, (a - 0xa000) >> 2, d); + return; + } + + if (a >= 0xa800 && a <= 0xa80f) { + ppi8255_w(1, (a - 0xa800) >> 2, d); + return; + } + + switch (a) { + case 0xb000: { + GalBackgroundGreen = d & 1; + return; + } + + case 0xb002: { + GalBackgroundBlue = d & 1; + return; + } + + case 0xb004: { + GalIrqFire = d & 1; + return; + } + + case 0xb006: { + // coin_count_0_w + return; + } + + case 0xb00a: { + GalBackgroundRed = d & 1; + return; + } + + case 0xb00c: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb00e: { + GalFlipScreenX = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall DarkplntZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x8800 && a <= 0x88ff) { + INT32 Offset = a - 0x8800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xa000 && a <= 0xa00f) { + ppi8255_w(0, (a - 0xa000) >> 2, d); + return; + } + + if (a >= 0xa800 && a <= 0xa80f) { + ppi8255_w(1, (a - 0xa800) >> 2, d); + return; + } + + switch (a) { + case 0xb000: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb002: { + GalBackgroundEnable = d & 1; + return; + } + + case 0xb004: { + GalIrqFire = d & 1; + return; + } + + case 0xb006: { + // coin_count_0_w + return; + } + + case 0xb00a: { + DarkplntBulletColour = d & 1; + return; + } + + case 0xb00c: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb00e: { + GalFlipScreenX = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall HustlerZ80Read(UINT16 a) +{ + if (a >= 0xd000 && a <= 0xd01f) { + return ppi8255_r(0, (a - 0xd000) >> 3); + } + + if (a >= 0xe000 && a <= 0xe01f) { + return ppi8255_r(1, (a - 0xe000) >> 3); + } + + switch (a) { + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall HustlerZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x90ff) { + INT32 Offset = a - 0x9000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xd000 && a <= 0xd01f) { + ppi8255_w(0, (a - 0xd000) >> 3, d); + return; + } + + if (a >= 0xe000 && a <= 0xe01f) { + ppi8255_w(1, (a - 0xe000) >> 3, d); + return; + } + + switch (a) { + case 0xa802: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa804: { + GalIrqFire = d & 1; + return; + } + + case 0xa806: { + GalFlipScreenY = d & 1; + return; + } + + case 0xa80e: { + // coin_count_0_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall HustlerbZ80Read(UINT16 a) +{ + switch (a) { + case 0xb000: { + // watchdog read + return 0xff; + } + + case 0xc100: + case 0xc101: + case 0xc102: + case 0xc103: { + return ppi8255_r(0, a - 0xc100); + } + + case 0xc200: + case 0xc201: + case 0xc202: + case 0xc203: { + return ppi8255_r(1, a - 0xc200); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall HustlerbZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x90ff) { + INT32 Offset = a - 0x9000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa801: { + GalIrqFire = d & 1; + return; + } + + case 0xa802: { + // coin_count_0_w + return; + } + + case 0xa806: { + GalFlipScreenY = d & 1; + return; + } + + case 0xa807: { + GalFlipScreenX = d & 1; + return; + } + + case 0xc100: + case 0xc101: + case 0xc102: + case 0xc103: { + ppi8255_w(0, a - 0xc100, d); + return; + } + + case 0xc200: + case 0xc201: + case 0xc202: + case 0xc203: { + ppi8255_w(1, a - 0xc200, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall HustlerbSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x80: { + return AY8910Read(0); + } + } + + return 0xff; +} + +void __fastcall HustlerbSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x40: { + AY8910Write(0, 0, d); + return; + } + + case 0x80: { + AY8910Write(0, 1, d); + return; + } + } +} + +void __fastcall MimonkeyZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x90ff) { + INT32 Offset = a - 0x9000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x9800: + case 0x9801: + case 0x9802: + case 0x9803: { + ppi8255_w(0, a - 0x9800, d); + return; + } + + case 0xa000: + case 0xa001: + case 0xa002: + case 0xa003: { + ppi8255_w(1, a - 0xa000, d); + return; + } + + case 0xa800: { + GalGfxBank[0] = d & 1; + return; + } + + case 0xa801: { + GalIrqFire = d & 1; + return; + } + + case 0xa802: { + GalGfxBank[1] = d & 1; + return; + } + + case 0xa803: { + // ??? + return; + } + + case 0xa804: { + GalBackgroundEnable = d & 1; + return; + } + + case 0xa805: { + // ??? + return; + } + + case 0xa806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 ScobraInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 LosttombInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8 *TempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(TempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + for (UINT32 Offset = 0; Offset < GalTilesSharedRomSize; Offset++) { + UINT32 SrcOffset = Offset & 0xa7f; + SrcOffset |= ((BIT(Offset, 1) & BIT(Offset, 8)) | ((1 ^ BIT(Offset, 1)) & (BIT(Offset, 10)))) << 7; + SrcOffset |= (BIT(Offset, 7) ^ (BIT(Offset, 1) & (BIT(Offset, 7) ^ BIT(Offset, 10)))) << 8; + SrcOffset |= ((BIT(Offset, 1) & BIT(Offset, 7)) | ((1 ^ BIT(Offset, 1)) & (BIT(Offset, 8)))) << 10; + GalTempRom[Offset] = TempRom[SrcOffset]; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static void MapTazmani2() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(Tazmani2Z80Read); + ZetSetWriteHandler(Tazmani2Z80Write); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0x8800, 0x88ff, 0, GalSpriteRam); + ZetMapArea(0x8800, 0x88ff, 2, GalSpriteRam); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMemEnd(); + ZetClose(); +} + +static INT32 Tazmani2Init() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapTazmani2; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 AnteaterInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8 *TempRom = (UINT8*)malloc(GalTilesSharedRomSize); + BurnLoadRom(TempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); + BurnLoadRom(TempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); + for (UINT32 Offset = 0; Offset < GalTilesSharedRomSize; Offset++) { + UINT32 SrcOffset = Offset & 0x9bf; + SrcOffset |= (BIT(Offset, 4) ^ BIT(Offset, 9) ^ (BIT(Offset, 2) & BIT(Offset, 10))) << 6; + SrcOffset |= (BIT(Offset, 2) ^ BIT(Offset, 10)) << 9; + SrcOffset |= (BIT(Offset, 0) ^ BIT(Offset, 6) ^ 1) << 10; + GalTempRom[Offset] = TempRom[SrcOffset]; + } + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalRenderBackgroundFunction = AnteaterDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static void AnteatergPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(AnteatergZ80Read); + ZetSetWriteHandler(AnteatergZ80Write); + ZetMapArea(0x0000, 0x03ff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x03ff, 2, GalZ80Rom1); + ZetMapArea(0x0400, 0x0bff, 0, GalZ80Ram1); + ZetMapArea(0x0400, 0x0bff, 1, GalZ80Ram1); + ZetMapArea(0x0400, 0x0bff, 2, GalZ80Ram1); + ZetMapArea(0x0c00, 0x0fff, 0, GalVideoRam); + ZetMapArea(0x0c00, 0x0fff, 1, GalVideoRam); + ZetMapArea(0x0c00, 0x0fff, 2, GalVideoRam); + ZetMapArea(0x2000, 0x20ff, 0, GalSpriteRam); + ZetMapArea(0x2000, 0x20ff, 2, GalSpriteRam); + ZetMapArea(0x4600, 0x4fff, 0, GalZ80Rom1 + 0x0400); + ZetMapArea(0x4600, 0x4fff, 2, GalZ80Rom1 + 0x0400); + ZetMapArea(0x6400, 0x7aff, 0, GalZ80Rom1 + 0x0e00); + ZetMapArea(0x6400, 0x7aff, 2, GalZ80Rom1 + 0x0e00); + ZetMapArea(0x7c00, 0x7fff, 0, GalVideoRam); + ZetMapArea(0x7c00, 0x7fff, 1, GalVideoRam); + ZetMapArea(0x7c00, 0x7fff, 2, GalVideoRam); + ZetMapArea(0x8300, 0x98ff, 0, GalZ80Rom1 + 0x2500); + ZetMapArea(0x8300, 0x98ff, 2, GalZ80Rom1 + 0x2500); + ZetMapArea(0xa300, 0xa7ff, 0, GalZ80Rom1 + 0x3b00); + ZetMapArea(0xa300, 0xa7ff, 2, GalZ80Rom1 + 0x3b00); + ZetMemEnd(); + ZetClose(); +} + +static INT32 AnteatergInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = AnteatergPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = AnteaterDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static void AnteaterukPostLoad() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(AnteatgbZ80Read); + ZetSetWriteHandler(AnteatgbZ80Write); + ZetMapArea(0x0000, 0x03ff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x03ff, 2, GalZ80Rom1); + ZetMapArea(0x0400, 0x0bff, 0, GalZ80Ram1); + ZetMapArea(0x0400, 0x0bff, 1, GalZ80Ram1); + ZetMapArea(0x0400, 0x0bff, 2, GalZ80Ram1); + ZetMapArea(0x0c00, 0x0fff, 0, GalVideoRam); + ZetMapArea(0x0c00, 0x0fff, 1, GalVideoRam); + ZetMapArea(0x0c00, 0x0fff, 2, GalVideoRam); + ZetMapArea(0x1200, 0x12ff, 0, GalSpriteRam); + ZetMapArea(0x1200, 0x12ff, 2, GalSpriteRam); + ZetMapArea(0x4600, 0x4fff, 0, GalZ80Rom1 + 0x0400); + ZetMapArea(0x4600, 0x4fff, 2, GalZ80Rom1 + 0x0400); + ZetMapArea(0x6400, 0x7aff, 0, GalZ80Rom1 + 0x0e00); + ZetMapArea(0x6400, 0x7aff, 2, GalZ80Rom1 + 0x0e00); + ZetMapArea(0x8300, 0x98ff, 0, GalZ80Rom1 + 0x2500); + ZetMapArea(0x8300, 0x98ff, 2, GalZ80Rom1 + 0x2500); + ZetMapArea(0xa300, 0xa7ff, 0, GalZ80Rom1 + 0x3b00); + ZetMapArea(0xa300, 0xa7ff, 2, GalZ80Rom1 + 0x3b00); + ZetMemEnd(); + ZetClose(); +} + +static INT32 AnteaterukInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = AnteaterukPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static void SuperbonPostLoad() +{ + MapScobra(); + + for (UINT32 Offset = 0; Offset < 0x1000; Offset++) { + switch (Offset & 0x280) { + case 0x000: GalZ80Rom1[Offset] ^= 0x92; break; + case 0x080: GalZ80Rom1[Offset] ^= 0x82; break; + case 0x200: GalZ80Rom1[Offset] ^= 0x12; break; + case 0x280: GalZ80Rom1[Offset] ^= 0x10; break; + } + } +} + +static INT32 SuperbonInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = SuperbonPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + GalPromRomSize = 0x20; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + HardCodeGalaxianPROM(); + + return nRet; +} + +static INT32 CalipsoInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendSpriteInfoFunction = CalipsoExtendSpriteInfo; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static UINT8 MoonwarPPIReadIN0() +{ + UINT8 Dial1 = (GalAnalogPort0 >> 8) & 0xff; + UINT8 Dial2 = (GalAnalogPort1 >> 8) & 0xff; + UINT8 Input0 = 0xff - GalInput[0] - GalDip[0]; + UINT8 Sign; + UINT8 Delta; + + if (Dial1 >= 0xfc || (Dial1 >= 0x01 && Dial1 <= 0x04)) Dial1 = 0; + if (Dial1 >= 0xf8) Dial1 = 0xfd; + if (Dial1 >= 0x01 && Dial1 <= 0x07) Dial1 = 0x02; + + if (Dial2 >= 0xfc || (Dial2 >= 0x01 && Dial2 <= 0x04)) Dial2 = 0; + if (Dial2 >= 0xf8) Dial2 = 0xfd; + if (Dial2 >= 0x01 && Dial2 <= 0x07) Dial2 = 0x02; + + Delta = (MoonwarPortSelect ? Dial1 : Dial2); + Sign = (Delta & 0x80) >> 3; + Delta &= 0x0f; + + return (Input0 & 0xe0) | Delta | Sign; +} + +static void MoonwarPortSelectWrite(UINT8 d) +{ + MoonwarPortSelect = d & 0x10; +} + +static INT32 MoonwarInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = MoonwarDrawBullets; + + KonamiPPIInit(); + + PPI0PortReadA = MoonwarPPIReadIN0; + PPI0PortWriteC = MoonwarPortSelectWrite; + + return nRet; +} + +static void StratgyxPostLoad() +{ + MapTazmani2(); + + ZetOpen(0); + ZetSetWriteHandler(StratgyxZ80Write); + ZetClose(); +} + +static INT32 StratgyxInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = StratgyxPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalCalcPaletteFunction = StratgyxCalcPalette; + GalRenderBackgroundFunction = StratgyxDrawBackground; + + KonamiPPIInit(); + + return nRet; +} + +static void DarkplntPostLoad() +{ + MapTazmani2(); + + ZetOpen(0); + ZetSetWriteHandler(DarkplntZ80Write); + ZetClose(); +} + +static INT16 DarkplntDial = 0; +static UINT32 DarkplntDialFrameNumberRead = 0; + +static UINT8 DarkplntPPIReadIN1() +{ + UINT32 CurrentFrame = GetCurrentFrame(); + + if (DarkplntDialFrameNumberRead != CurrentFrame) { + if (GalInputPort3[0]) DarkplntDial -= 0x01; + if (GalInputPort3[1]) DarkplntDial += 0x01; + if (DarkplntDial > 0xfc) DarkplntDial = 0x00; + if (DarkplntDial < 0) DarkplntDial = 0xfc; + DarkplntDialFrameNumberRead = CurrentFrame; + } + + static const UINT8 remap[] = {0x03, 0x02, 0x00, 0x01, 0x21, 0x20, 0x22, 0x23, 0x33, 0x32, 0x30, 0x31, 0x11, 0x10, 0x12, 0x13, 0x17, 0x16, 0x14, 0x15, 0x35, 0x34, 0x36, 0x37, 0x3f, 0x3e, 0x3c, 0x3d, 0x1d, 0x1c, 0x1e, 0x1f, 0x1b, 0x1a, 0x18, 0x19, 0x39, 0x38, 0x3a, 0x3b, 0x2b, 0x2a, 0x28, 0x29, 0x09, 0x08, 0x0a, 0x0b, 0x0f, 0x0e, 0x0c, 0x0d, 0x2d, 0x2c, 0x2e, 0x2f, 0x27, 0x26, 0x24, 0x25, 0x05, 0x04, 0x06, 0x07 }; + + return 0xff - GalInput[1] - GalDip[1] - remap[DarkplntDial >> 2]; +} + +static INT32 DarkplntInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DarkplntPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalCalcPaletteFunction = DarkplntCalcPalette; + GalDrawBulletsFunction = DarkplntDrawBullets; + + GalSoundVolumeShift = 2; + + KonamiPPIInit(); + PPI0PortReadB = DarkplntPPIReadIN1; + + return nRet; +} + +static INT32 RescueInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8* TempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(TempRom, GalTempRom, GalTilesSharedRomSize); + for (UINT32 Offset = 0; Offset < GalTilesSharedRomSize; Offset++) { + UINT32 j = Offset & 0xa7f; + j |= (BIT(Offset, 3) ^ BIT(Offset, 10)) << 7; + j |= (BIT(Offset, 1) ^ BIT(Offset, 7)) << 8; + j |= (BIT(Offset, 0) ^ BIT(Offset, 8)) << 10; + GalTempRom[Offset] = TempRom[j]; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalCalcPaletteFunction = RescueCalcPalette; + GalRenderBackgroundFunction = RescueDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 MinefldInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapScobra; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8* TempRom = (UINT8*)malloc(GalTilesSharedRomSize); + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x0800, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(TempRom, GalTempRom, GalTilesSharedRomSize); + for (UINT32 Offset = 0; Offset < GalTilesSharedRomSize; Offset++) { + UINT32 j = Offset & 0xd5f; + j |= (BIT(Offset, 3) ^ BIT(Offset, 7)) << 5; + j |= (BIT(Offset, 2) ^ BIT(Offset, 9) ^ (BIT(Offset, 0) & BIT(Offset, 5)) ^ (BIT(Offset, 3) & BIT(Offset, 7) & (BIT(Offset, 0) ^ BIT(Offset, 5)))) << 7; + j |= (BIT(Offset, 0) ^ BIT(Offset, 5) ^ (BIT(Offset, 3) & BIT(Offset, 7))) << 9; + GalTempRom[Offset] = TempRom[j]; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalCalcPaletteFunction = MinefldCalcPalette; + GalRenderBackgroundFunction = MinefldDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 2; + + KonamiPPIInit(); + + return nRet; +} + +static void HustlerPostLoad() +{ + MapScobra(); + + ZetOpen(0); + ZetSetReadHandler(HustlerZ80Read); + ZetSetWriteHandler(HustlerZ80Write); + ZetClose(); + + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 XorMask; + INT32 Bits[8]; + + for (UINT32 i = 0; i < 8; i++) Bits[i] = (Offset >> i) & 1; + + XorMask = 0xff; + if (Bits[0] ^ Bits[1]) XorMask ^= 0x01; + if (Bits[3] ^ Bits[6]) XorMask ^= 0x02; + if (Bits[4] ^ Bits[5]) XorMask ^= 0x04; + if (Bits[0] ^ Bits[2]) XorMask ^= 0x08; + if (Bits[2] ^ Bits[3]) XorMask ^= 0x10; + if (Bits[1] ^ Bits[5]) XorMask ^= 0x20; + if (Bits[0] ^ Bits[7]) XorMask ^= 0x40; + if (Bits[4] ^ Bits[6]) XorMask ^= 0x80; + + GalZ80Rom1[Offset] ^= XorMask; + } +} + +static INT32 HustlerInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HustlerPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void BilliardPostLoad() +{ + MapScobra(); + + ZetOpen(0); + ZetSetReadHandler(HustlerZ80Read); + ZetSetWriteHandler(HustlerZ80Write); + ZetClose(); + + for (UINT32 Offset = 0; Offset < GalZ80Rom1Size; Offset++) { + UINT8 XorMask; + INT32 Bits[8]; + + for (UINT32 i = 0; i < 8; i++) Bits[i] = (Offset >> i) & 1; + + XorMask = 0x55; + if (Bits[2] ^ ( Bits[3] & Bits[6])) XorMask ^= 0x01; + if (Bits[4] ^ ( Bits[5] & Bits[7])) XorMask ^= 0x02; + if (Bits[0] ^ ( Bits[7] & !Bits[3])) XorMask ^= 0x04; + if (Bits[3] ^ (!Bits[0] & Bits[2])) XorMask ^= 0x08; + if (Bits[5] ^ (!Bits[4] & Bits[1])) XorMask ^= 0x10; + if (Bits[6] ^ (!Bits[2] & !Bits[5])) XorMask ^= 0x20; + if (Bits[1] ^ (!Bits[6] & !Bits[4])) XorMask ^= 0x40; + if (Bits[7] ^ (!Bits[1] & Bits[0])) XorMask ^= 0x80; + + GalZ80Rom1[Offset] ^= XorMask; + GalZ80Rom1[Offset] = BITSWAP08(GalZ80Rom1[Offset], 6, 1, 2, 5, 4, 3, 0, 7); + } +} + +static INT32 BilliardInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = BilliardPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + FroggerSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void HustlerbPostLoad() +{ + MapScobra(); + + ZetOpen(0); + ZetSetReadHandler(HustlerbZ80Read); + ZetSetWriteHandler(HustlerbZ80Write); + ZetClose(); + + FroggerSoundNoEncryptionInit(); + ZetOpen(1); + ZetSetInHandler(HustlerbSoundZ80PortRead); + ZetSetOutHandler(HustlerbSoundZ80PortWrite); + ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram2); + ZetClose(); +} + +static INT32 HustlerbInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HustlerbPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910; + + nRet = GalInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + KonamiPPIInit(); + + GalSpriteClipStart = 7; + GalSpriteClipEnd = 246; + + return nRet; +} + +static void MapMimonkey() +{ + MapScobra(); + + ZetOpen(0); + ZetSetWriteHandler(MimonkeyZ80Write); + ZetMemCallback(0x4000, 0x7fff, 0); + ZetMemCallback(0x4000, 0x7fff, 2); + ZetMapArea(0xc000, 0xffff, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0xc000, 0xffff, 2, GalZ80Rom1 + 0x4000); + ZetClose(); +} + +static void MimonkeyPostLoad() +{ + static const UINT8 XorTable[16][16] = { + { 0x03, 0x03, 0x05, 0x07, 0x85, 0x00, 0x85, 0x85, 0x80, 0x80, 0x06, 0x03, 0x03, 0x00, 0x00, 0x81 }, + { 0x83, 0x87, 0x03, 0x87, 0x06, 0x00, 0x06, 0x04, 0x02, 0x00, 0x84, 0x84, 0x04, 0x00, 0x01, 0x83 }, + { 0x82, 0x82, 0x84, 0x02, 0x04, 0x00, 0x00, 0x03, 0x82, 0x00, 0x06, 0x80, 0x03, 0x00, 0x81, 0x07 }, + { 0x06, 0x06, 0x82, 0x81, 0x85, 0x00, 0x04, 0x07, 0x81, 0x05, 0x04, 0x00, 0x03, 0x00, 0x82, 0x84 }, + { 0x07, 0x07, 0x80, 0x07, 0x07, 0x00, 0x85, 0x86, 0x00, 0x07, 0x06, 0x04, 0x85, 0x00, 0x86, 0x85 }, + { 0x81, 0x83, 0x02, 0x02, 0x87, 0x00, 0x86, 0x03, 0x04, 0x06, 0x80, 0x05, 0x87, 0x00, 0x81, 0x81 }, + { 0x01, 0x01, 0x00, 0x07, 0x07, 0x00, 0x01, 0x01, 0x07, 0x07, 0x06, 0x00, 0x06, 0x00, 0x07, 0x07 }, + { 0x80, 0x87, 0x81, 0x87, 0x83, 0x00, 0x84, 0x01, 0x01, 0x86, 0x86, 0x80, 0x86, 0x00, 0x86, 0x86 }, + { 0x03, 0x03, 0x05, 0x07, 0x85, 0x00, 0x85, 0x85, 0x80, 0x80, 0x06, 0x03, 0x03, 0x00, 0x00, 0x81 }, + { 0x83, 0x87, 0x03, 0x87, 0x06, 0x00, 0x06, 0x04, 0x02, 0x00, 0x84, 0x84, 0x04, 0x00, 0x01, 0x83 }, + { 0x82, 0x82, 0x84, 0x02, 0x04, 0x00, 0x00, 0x03, 0x82, 0x00, 0x06, 0x80, 0x03, 0x00, 0x81, 0x07 }, + { 0x06, 0x06, 0x82, 0x81, 0x85, 0x00, 0x04, 0x07, 0x81, 0x05, 0x04, 0x00, 0x03, 0x00, 0x82, 0x84 }, + { 0x07, 0x07, 0x80, 0x07, 0x07, 0x00, 0x85, 0x86, 0x00, 0x07, 0x06, 0x04, 0x85, 0x00, 0x86, 0x85 }, + { 0x81, 0x83, 0x02, 0x02, 0x87, 0x00, 0x86, 0x03, 0x04, 0x06, 0x80, 0x05, 0x87, 0x00, 0x81, 0x81 }, + { 0x01, 0x01, 0x00, 0x07, 0x07, 0x00, 0x01, 0x01, 0x07, 0x07, 0x06, 0x00, 0x06, 0x00, 0x07, 0x07 }, + { 0x80, 0x87, 0x81, 0x87, 0x83, 0x00, 0x84, 0x01, 0x01, 0x86, 0x86, 0x80, 0x86, 0x00, 0x86, 0x86 } + }; + + INT32 Ctr = 0, Line, Col; + + for (INT32 Offset = 0; Offset < 0x4000; Offset++) { + Line = (Ctr & 0x07) | ((Ctr & 0x200) >> 6); + Col = ((GalZ80Rom1[Offset] & 0x80) >> 4) | (GalZ80Rom1[Offset] & 0x07); + GalZ80Rom1[Offset] = GalZ80Rom1[Offset] ^ XorTable[Line][Col]; + Ctr++; + } + + MapMimonkey(); +} + +static INT32 MimonkeyInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MimonkeyPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = MimonkeyExtendTileInfo; + GalExtendSpriteInfoFunction = MimonkeyExtendSpriteInfo; + + KonamiPPIInit(); + + return nRet; +} + +static INT32 MimonscoInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = MapMimonkey; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910; + + nRet = GalInit(); + KonamiSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = MimonkeyExtendTileInfo; + GalExtendSpriteInfoFunction = MimonkeyExtendSpriteInfo; + + KonamiPPIInit(); + + return nRet; +} + +struct BurnDriver BurnDrvScobra = { + "scobra", NULL, NULL, NULL, "1981", + "Super Cobra\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScobraRomInfo, ScobraRomName, NULL, NULL, SfxInputInfo, ScobraDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScobras = { + "scobras", "scobra", NULL, NULL, "1981", + "Super Cobra (Stern)\0", NULL, "Konami (Stern license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScobrasRomInfo, ScobrasRomName, NULL, NULL, SfxInputInfo, ScobrasDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScobrase = { + "scobrase", "scobra", NULL, NULL, "1981", + "Super Cobra (Sega)\0", NULL, "Konami (Sega license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScobraseRomInfo, ScobraseRomName, NULL, NULL, SfxInputInfo, ScobrasDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvScobrab = { + "scobrab", "scobra", NULL, NULL, "1981", + "Super Cobra (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, ScobrabRomInfo, ScobrabRomName, NULL, NULL, SfxInputInfo, ScobrasDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSuprheli = { + "suprheli", "scobra", NULL, NULL, "1981", + "Super Heli (Super Cobra bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, SuprheliRomInfo, SuprheliRomName, NULL, NULL, SfxInputInfo, ScobrasDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLosttomb = { + "losttomb", NULL, NULL, NULL, "1982", + "Lost Tomb (Easy)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, LosttombRomInfo, LosttombRomName, NULL, NULL, LosttombInputInfo, LosttombDIPInfo, + LosttombInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLosttombh = { + "losttombh", "losttomb", NULL, NULL, "1982", + "Lost Tomb (Hard)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, LosttombhRomInfo, LosttombhRomName, NULL, NULL, LosttombInputInfo, LosttombDIPInfo, + LosttombInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvArmorcar = { + "armorcar", NULL, NULL, NULL, "1981", + "Armored Car (set 1)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, ArmorcarRomInfo, ArmorcarRomName, NULL, NULL, AtlantisInputInfo, ArmorcarDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvArmorcar2 = { + "armorcar2", "armorcar", NULL, NULL, "1981", + "Armored Car (set 2)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Armorcar2RomInfo, Armorcar2RomName, NULL, NULL, AtlantisInputInfo, ArmorcarDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTazmania = { + "tazmania", NULL, NULL, NULL, "1982", + "Tazz-Mania (set 1)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, TazmaniaRomInfo, TazmaniaRomName, NULL, NULL, TazmaniaInputInfo, ArmorcarDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTazmani2 = { + "tazmani2", "tazmania", NULL, NULL, "1982", + "Tazz-Mania (set 2)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, Tazmani2RomInfo, Tazmani2RomName, NULL, NULL, TazmaniaInputInfo, ArmorcarDIPInfo, + Tazmani2Init, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAnteater = { + "anteater", NULL, NULL, NULL, "1982", + "Anteater\0", NULL, "Stern (Tago license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AnteaterRomInfo, AnteaterRomName, NULL, NULL, AnteaterInputInfo, AnteaterDIPInfo, + AnteaterInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAnteaterg = { + "anteaterg", "anteater", NULL, NULL, "1983", + "Ameisenbaer (German)\0", NULL, "TV-Tuning (F.E.G. license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AnteatergRomInfo, AnteatergRomName, NULL, NULL, AnteatergInputInfo, AnteatergDIPInfo, + AnteatergInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAnteateruk = { + "anteateruk", "anteater", NULL, NULL, "1983", + "The Anteater (UK)\0", NULL, "Free Enterprise Games", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, AnteaterukRomInfo, AnteaterukRomName, NULL, NULL, AnteaterukInputInfo, AnteaterukDIPInfo, + AnteaterukInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSpdcoin = { + "spdcoin", NULL, NULL, NULL, "1984", + "Speed Coin (prototype)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_PROTOTYPE, 2, HARDWARE_GALAXIAN, GBF_MISC, 0, + NULL, SpdcoinRomInfo, SpdcoinRomName, NULL, NULL, SpdcoinInputInfo, SpdcoinDIPInfo, + ScobraInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSuperbon = { + "superbon", NULL, NULL, NULL, "1985", + "Agent Super Bond (scobra hardware)\0", "Bad Colours", "Signaton USA", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, SuperbonRomInfo, SuperbonRomName, NULL, NULL, SuperbonInputInfo, SuperbonDIPInfo, + SuperbonInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCalipso = { + "calipso", NULL, NULL, NULL, "1982", + "Calipso\0", NULL, "Stern (Tago license)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_MAZE, 0, + NULL, CalipsoRomInfo, CalipsoRomName, NULL, NULL, CalipsoInputInfo, CalipsoDIPInfo, + CalipsoInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMoonwar = { + "moonwar", NULL, NULL, NULL, "1981", + "Moonwar\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SHOOT, 0, + NULL, MoonwarRomInfo, MoonwarRomName, NULL, NULL, MoonwarInputInfo, MoonwarDIPInfo, + MoonwarInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMoonwara = { + "moonwara", "moonwar", NULL, NULL, "1981", + "Moonwar (older)\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SHOOT, 0, + NULL, MoonwaraRomInfo, MoonwaraRomName, NULL, NULL, MoonwarInputInfo, MoonwaraDIPInfo, + MoonwarInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvStratgyx = { + "stratgyx", NULL, NULL, NULL, "1981", + "Strategy X\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, StratgyxRomInfo, StratgyxRomName, NULL, NULL, StratgyxInputInfo, StratgyxDIPInfo, + StratgyxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvStratgys = { + "stratgys", "stratgyx", NULL, NULL, "1981", + "Strategy X (Stern)\0", NULL, "Konami (Stern License)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, StratgysRomInfo, StratgysRomName, NULL, NULL, StratgyxInputInfo, StratgyxDIPInfo, + StratgyxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvStrongx = { + "strongx", "stratgyx", NULL, NULL, "1982", + "Strong X\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_VERSHOOT, 0, + NULL, StrongxRomInfo, StrongxRomName, NULL, NULL, StratgyxInputInfo, StratgyxDIPInfo, + StratgyxInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDarkplnt = { + "darkplnt", NULL, NULL, NULL, "1982", + "Dark Planet\0", "Dial doesn't work very well", "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SHOOT, 0, + NULL, DarkplntRomInfo, DarkplntRomName, NULL, NULL, DarkplntInputInfo, DarkplntDIPInfo, + DarkplntInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRescue = { + "rescue", NULL, NULL, NULL, "1982", + "Rescue\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, RescueRomInfo, RescueRomName, NULL, NULL, RescueInputInfo, RescueDIPInfo, + RescueInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvAponow = { + "aponow", "rescue", NULL, NULL, "1982", + "Apocaljpse Now\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, AponowRomInfo, AponowRomName, NULL, NULL, RescueInputInfo, RescueDIPInfo, + RescueInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMinefld = { + "minefld", NULL, NULL, NULL, "1983", + "Minefield\0", NULL, "Stern", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MinefldRomInfo, MinefldRomName, NULL, NULL, RescueInputInfo, MinefldDIPInfo, + MinefldInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHustler = { + "hustler", NULL, NULL, NULL, "1981", + "Video Hustler\0", NULL, "Konami", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, HustlerRomInfo, HustlerRomName, NULL, NULL, HustlerInputInfo, HustlerDIPInfo, + HustlerInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvBilliard = { + "billiard", "hustler", NULL, NULL, "1981", + "The Billiards\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, BilliardRomInfo, BilliardRomName, NULL, NULL, HustlerInputInfo, HustlerDIPInfo, + BilliardInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHustlerb = { + "hustlerb", "hustler", NULL, NULL, "1981", + "Video Hustler (bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, HustlerbRomInfo, HustlerbRomName, NULL, NULL, HustlerInputInfo, HustlerDIPInfo, + HustlerbInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMimonkey = { + "mimonkey", NULL, NULL, NULL, "198?", + "Mighty Monkey\0", NULL, "Universal Video Games", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MimonkeyRomInfo, MimonkeyRomName, NULL, NULL, AtlantisInputInfo, MimonkeyDIPInfo, + MimonkeyInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMimonsco = { + "mimonsco", "mimonkey", NULL, NULL, "198?", + "Mighty Monkey (bootleg on Super Cobra hardware)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, MimonscoRomInfo, MimonscoRomName, NULL, NULL, AtlantisInputInfo, MimonscoDIPInfo, + MimonscoInit, KonamiExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// Dambusters based hardware - background can take priority over all graphics except high colour chars +static struct BurnRomInfo DambustrRomDesc[] = { + { "db11a.pr11", 0x01000, 0x427bd3fb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db9a.pr9", 0x01000, 0x57164563, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db10a.pr10", 0x01000, 0x075b9c5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db12a.pr12", 0x01000, 0xed01a68b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db8a.pr8", 0x01000, 0xfd041ff4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db6a.pr6", 0x01000, 0x448db54b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db7a.pr7", 0x01000, 0x675b1f5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db5a.pr5", 0x01000, 0x75659ecc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "db3a.pr3", 0x01000, 0x9e9a9710, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db1a.pr1", 0x01000, 0x4cb964cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db4a.pr3", 0x01000, 0xd9d2df33, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db2a.pr2", 0x01000, 0x0a0a6af5, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mi-7603-5.ic4", 0x00020, 0xf131f92f, BRF_GRA | GAL_ROM_PROM }, + + { "mi-7603-5.ic3", 0x00020, 0xe2a54c47, BRF_OPT }, // timing? +}; + +STD_ROM_PICK(Dambustr) +STD_ROM_FN(Dambustr) + +static struct BurnRomInfo DambustraRomDesc[] = { + { "db11.pr11", 0x01000, 0x427bd3fb, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db9a.pr9", 0x01000, 0x57164563, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db10a.pr10", 0x01000, 0x075b9c5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db12a.pr12", 0x01000, 0xed01a68b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db8a.pr8", 0x01000, 0xfd041ff4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db6.pr6", 0x01000, 0x56d301a9, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db7a.pr7", 0x01000, 0x675b1f5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db5a.pr5", 0x01000, 0x75659ecc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "db3a.rom", 0x01000, 0x2347e26e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db1a.pr1", 0x01000, 0x4cb964cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db4a.pr3", 0x01000, 0xd9d2df33, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db2a.pr2", 0x01000, 0x0a0a6af5, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mi-7603-5.ic4", 0x00020, 0xf131f92f, BRF_GRA | GAL_ROM_PROM }, + + { "mi-7603-5.ic3", 0x00020, 0xe2a54c47, BRF_OPT }, // timing? +}; + +STD_ROM_PICK(Dambustra) +STD_ROM_FN(Dambustra) + +static struct BurnRomInfo DambustrukRomDesc[] = { + { "db11.bin", 0x01000, 0x9e6b34fe, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db9.pr9", 0x01000, 0x57164563, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db10p.bin", 0x01000, 0xc129c57b, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db12.bin", 0x01000, 0xea4c65f5, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db8.pr8", 0x01000, 0xfd041ff4, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db6p.bin", 0x01000, 0x35dcee01, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db7.pr7", 0x01000, 0x675b1f5e, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + { "db5.pr5", 0x01000, 0x75659ecc, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "db3.pr3", 0x01000, 0x9e9a9710, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db1ap.pr1", 0x01000, 0x4cb964cd, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db4.pr3", 0x01000, 0xd9d2df33, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "db2.pr2", 0x01000, 0x0a0a6af5, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "mi-7603-5.ic4", 0x00020, 0xf131f92f, BRF_GRA | GAL_ROM_PROM }, + + { "mi-7603-5.ic3", 0x00020, 0xe2a54c47, BRF_OPT }, // timing? +}; + +STD_ROM_PICK(Dambustruk) +STD_ROM_FN(Dambustruk) + +UINT8 __fastcall DambustrZ80Read(UINT16 a) +{ + if (a >= 0xd900 && a <= 0xdbff) { + // ??? + return 0xff; + } + + switch (a) { + case 0xe000: { + return GalInput[0] | GalDip[0]; + } + + case 0xe800: { + return GalInput[1] | GalDip[1]; + } + + case 0xf000: { + return GalInput[2] | GalDip[2]; + } + + case 0xf800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall DambustrZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xd800 && a <= 0xd8ff) { + INT32 Offset = a - 0xd800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xd900 && a <= 0xdbff) { + // ??? + return; + } + + switch (a) { + case 0x8000: { + DambustrBgColour1 = (BIT(d, 2) << 2) | (BIT(d, 1) << 1) | BIT(d, 0); + DambustrBgColour2 = (BIT(d, 6) << 2) | (BIT(d, 5) << 1) | BIT(d, 4); + DambustrBgPriority = BIT(d, 3); + GalGfxBank[0] = BIT(d, 7); + return; + } + + case 0x8001: { + DambustrBgSplitLine = d; + return; + } + + case 0xe002: + case 0xe003: { + // coin_count_0_w + return; + } + + case 0xe004: + case 0xe005: + case 0xe006: + case 0xe007: { + GalaxianLfoFreqWrite(a - 0xe004, d); + return; + } + + case 0xe800: + case 0xe801: + case 0xe802: + case 0xe803: + case 0xe804: + case 0xe805: + case 0xe806: + case 0xe807: { + GalaxianSoundWrite(a - 0xe800, d); + return; + } + + case 0xf001: { + GalIrqFire = d & 1; + return; + } + + case 0xf004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xf006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xf007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xf800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall DambustrZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall DambustrZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static void DambustrPostLoad() +{ + UINT8 Temp; + + GalTempRom = (UINT8*)malloc(0x4000); + memcpy(GalTempRom, GalZ80Rom1, 0x4000); + for (INT32 i = 0; i < 0x4000; i++) { + GalZ80Rom1[i] = GalTempRom[BITSWAP16(i, 15, 14, 13, 12, 4, 10, 9, 8, 7, 6, 5, 3, 11, 2, 1, 0)]; + } + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + for (INT32 i = 0; i < 0x1000; i++) { + Temp = GalZ80Rom1[0x5000 + i]; + GalZ80Rom1[0x5000 + i] = GalZ80Rom1[0x6000 + i]; + GalZ80Rom1[0x6000 + i] = GalZ80Rom1[0x1000 + i]; + GalZ80Rom1[0x1000 + i] = Temp; + } + + for (INT32 i = 0; i < 0x1000; i++) { + GalZ80Rom1[0x1000 + i] = BITSWAP08(GalZ80Rom1[0x1000 + i], 7, 6, 5, 1, 3, 2, 4, 0); + GalZ80Rom1[0x4000 + i] = BITSWAP08(GalZ80Rom1[0x4000 + i], 7, 6, 5, 1, 3, 2, 4, 0); + GalZ80Rom1[0x5000 + i] = BITSWAP08(GalZ80Rom1[0x5000 + i], 7, 6, 5, 1, 3, 2, 4, 0); + } + + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(DambustrZ80Read); + ZetSetWriteHandler(DambustrZ80Write); + ZetSetInHandler(DambustrZ80PortRead); + ZetSetOutHandler(DambustrZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0xc000, 0xc7ff, 0, GalZ80Ram1); + ZetMapArea(0xc000, 0xc7ff, 1, GalZ80Ram1); + ZetMapArea(0xc000, 0xc7ff, 2, GalZ80Ram1); + ZetMapArea(0xd000, 0xd3ff, 0, GalVideoRam); + ZetMapArea(0xd000, 0xd3ff, 1, GalVideoRam); + ZetMapArea(0xd000, 0xd3ff, 2, GalVideoRam); + ZetMapArea(0xd400, 0xd7ff, 0, GalVideoRam); + ZetMapArea(0xd400, 0xd7ff, 1, GalVideoRam); + ZetMapArea(0xd400, 0xd7ff, 2, GalVideoRam); + ZetMapArea(0xd800, 0xd8ff, 0, GalSpriteRam); + ZetMapArea(0xd800, 0xd8ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +static INT32 DambustrInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DambustrPostLoad; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8 Temp[16]; + nRet = BurnLoadRom(GalTempRom + 0x0000, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x1000, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x2000, GAL_ROM_OFFSET_TILES_SHARED + 2, 1); if (nRet) return 1; + nRet = BurnLoadRom(GalTempRom + 0x3000, GAL_ROM_OFFSET_TILES_SHARED + 3, 1); if (nRet) return 1; + for (UINT32 i = 0; i < GalTilesSharedRomSize; i += 16) { + UINT32 j; + + for (j = 0; j < 16; j++) { + Temp[j] = GalTempRom[i + j]; + } + + for (j = 0; j < 8; j++) { + GalTempRom[i + j + 0] = Temp[(j * 2) + 0]; + GalTempRom[i + j + 8] = Temp[(j * 2) + 1]; + } + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalCalcPaletteFunction = DambustrCalcPalette; + GalRenderBackgroundFunction = DambustrDrawBackground; + GalDrawBulletsFunction = DambustrDrawBullets; + GalExtendTileInfoFunction = DambustrExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + GalRenderFrameFunction = DambustrRenderFrame; + + GalSpriteClipStart = 0; + GalSpriteClipEnd = 255; + + GalVideoRam2 = (UINT8*)malloc(0x400); + + return nRet; +} + +struct BurnDriver BurnDrvDambustr = { + "dambustr", NULL, NULL, NULL, "1981", + "Dambusters (US, set 1)\0", NULL, "South West Research", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, DambustrRomInfo, DambustrRomName, NULL, NULL, DambustrInputInfo, DambustrDIPInfo, + DambustrInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDambustra = { + "dambustra", "dambustr", NULL, NULL, "1981", + "Dambusters (US, set 2)\0", NULL, "South West Research", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, DambustraRomInfo, DambustraRomName, NULL, NULL, DambustrInputInfo, DambustrDIPInfo, + DambustrInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDambustruk = { + "dambustruk", "dambustr", NULL, NULL, "1981", + "Dambusters (UK)\0", NULL, "South West Research", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_GALAXIAN, GBF_HORSHOOT, 0, + NULL, DambustrukRomInfo, DambustrukRomName, NULL, NULL, DambustrInputInfo, DambustrDIPInfo, + DambustrInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +// S2650 Based Games +static struct BurnRomInfo HunchbkgRomDesc[] = { + { "gal_hb_kl", 0x00800, 0x3977650e, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "gal_hb_hj", 0x00800, 0xdb489c3d, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "gal_hb_cp", 0x00020, 0xcbff6762, BRF_GRA | GAL_ROM_PROM }, + + { "gal_hb_1", 0x00800, 0x46590e9b, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_2", 0x00800, 0x4e6e671c, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_3", 0x00800, 0xd29dc242, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_4", 0x00800, 0xd409d292, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_5", 0x00800, 0x29d3a8c4, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_6", 0x00800, 0xb016fd15, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_7", 0x00800, 0xd2731d27, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "gal_hb_8", 0x00800, 0xe4b1a666, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, +}; + +STD_ROM_PICK(Hunchbkg) +STD_ROM_FN(Hunchbkg) + +static struct BurnRomInfo DrivfrcgRomDesc[] = { + { "dfgj2.bin", 0x01000, 0x8e19f1e7, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "dfgj1.bin", 0x01000, 0x86b60ca8, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "dfgl2.bin", 0x01000, 0xea5e9959, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "dfgl1.bin", 0x01000, 0xb7ed195c, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "top.clr", 0x00020, 0x3110ddae, BRF_GRA | GAL_ROM_PROM }, + { "bot.clr", 0x00020, 0x0f0782af, BRF_GRA | GAL_ROM_PROM }, + + { "dfgp1.bin", 0x01000, 0x52d5e77d, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "dfgp2.bin", 0x01000, 0x9cf4dbce, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "dfgp3.bin", 0x01000, 0x79763f62, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "dfgp4.bin", 0x01000, 0xdd95338b, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, +}; + +STD_ROM_PICK(Drivfrcg) +STD_ROM_FN(Drivfrcg) + +static struct BurnRomInfo DrivfrcbRomDesc[] = { + { "df1.bin", 0x02000, 0x8adc3de0, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "df2.bin", 0x02000, 0x6d95ec35, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "top.clr", 0x00020, 0x3110ddae, BRF_GRA | GAL_ROM_PROM }, + { "bot.clr", 0x00020, 0x0f0782af, BRF_GRA | GAL_ROM_PROM }, + + { "dfp.bin", 0x04000, 0xb5b2981d, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, +}; + +STD_ROM_PICK(Drivfrcb) +STD_ROM_FN(Drivfrcb) + +static struct BurnRomInfo RacknrolRomDesc[] = { + { "horz_g.bin", 0x04000, 0x97069ad5, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "horz_r.bin", 0x04000, 0xff64e84b, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.bin", 0x00020, 0x737802bf, BRF_GRA | GAL_ROM_PROM }, + + { "horz_p.bin", 0x04000, 0x32ca5b43, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + + { "82s147.bin", 0x00200, 0xaace7fa5, BRF_OPT }, // unknown +}; + +STD_ROM_PICK(Racknrol) +STD_ROM_FN(Racknrol) + +static struct BurnRomInfo HexpoolRomDesc[] = { + { "vert_g.bin", 0x04000, 0x7e257e80, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "vert_r.bin", 0x04000, 0xc5f0851e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.bin", 0x00020, 0x737802bf, BRF_GRA | GAL_ROM_PROM }, + + { "vert_p.bin", 0x04000, 0xbdb078fc, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + + { "82s147.bin", 0x00200, 0xaace7fa5, BRF_OPT }, // unknown +}; + +STD_ROM_PICK(Hexpool) +STD_ROM_FN(Hexpool) + +static struct BurnRomInfo HexpoolaRomDesc[] = { + { "rom.1m", 0x04000, 0x7e257e80, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "rom.1l", 0x04000, 0xc5f0851e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "82s123.11r", 0x00020, 0xdeb2fcf4, BRF_GRA | GAL_ROM_PROM }, + + { "rom.4l", 0x04000, 0x2ca8018d, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + + { "82s147.5pr", 0x00200, 0xcf496b1e, BRF_OPT }, // unknown + + { "82s153.6pr.bin",0x000eb, 0xbc07939a, BRF_OPT }, // PLD +}; + +STD_ROM_PICK(Hexpoola) +STD_ROM_FN(Hexpoola) + +static struct BurnRomInfo HunchbksRomDesc[] = { + { "11d_snd.bin", 0x00800, 0x88226086, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "5f_hb09.bin", 0x00800, 0xdb489c3d, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "5h_hb10.bin", 0x00800, 0x3977650e, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "6e_prom.bin", 0x00020, 0x01004d3f, BRF_GRA | GAL_ROM_PROM }, + + { "2c_hb01.bin", 0x00800, 0x8bebd834, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2e_hb02.bin", 0x00800, 0x07de4229, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2f_hb03.bin", 0x00800, 0xb75a0dfc, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2h_hb04.bin", 0x00800, 0xf3206264, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2j_hb05.bin", 0x00800, 0x1bb78728, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2l_hb06.bin", 0x00800, 0xf25ed680, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2m_hb07.bin", 0x00800, 0xc72e0e17, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "2p_hb08.bin", 0x00800, 0x412087b0, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, +}; + +STD_ROM_PICK(Hunchbks) +STD_ROM_FN(Hunchbks) + +static struct BurnRomInfo HncholmsRomDesc[] = { + { "hncholym.5c", 0x00800, 0xe7758775, BRF_ESS | BRF_PRG | GAL_ROM_Z80_PROG1 }, + + { "hncholym.5f", 0x01000, 0x75ad3542, BRF_GRA | GAL_ROM_TILES_SHARED }, + { "hncholym.5h", 0x01000, 0x6fec9dd3, BRF_GRA | GAL_ROM_TILES_SHARED }, + + { "prom.6e", 0x00020, 0x4e3caeab, BRF_GRA | GAL_ROM_PROM }, + + { "hncholym.2d", 0x00800, 0xfb453f9c, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2e", 0x00800, 0xb1429420, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2f", 0x00800, 0xafc98e28, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2h", 0x00800, 0x6785bf17, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2j", 0x00800, 0x0e1e4133, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2l", 0x00800, 0x6e982609, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2m", 0x00800, 0xb9141914, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + { "hncholym.2p", 0x00800, 0xca37b55b, BRF_ESS | BRF_PRG | GAL_ROM_S2650_PROG1 }, + + { "82s147.1a", 0x00200, 0xd461a48b, BRF_OPT }, +}; + +STD_ROM_PICK(Hncholms) +STD_ROM_FN(Hncholms) + +UINT8 HunchbkgS2650Read(UINT16 Address) +{ + switch (Address) { + case 0x1500: + case 0x3500: + case 0x5500: + case 0x7500: { + return GalInput[0] | GalDip[0]; + } + + case 0x1580: + case 0x3580: + case 0x5580: + case 0x7580: { + return GalInput[1] | GalDip[1]; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + return GalInput[2] | GalDip[2]; + } + + case 0x1680: + case 0x3680: + case 0x5680: + case 0x7680: { + // ??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Read %04x\n"), Address); + } + } + + return 0; +} + +void HunchbkgS2650Write(UINT16 Address, UINT8 Data) +{ + if ((Address >= 0x1480 && Address <= 0x14ff) || (Address >= 0x3480 && Address <= 0x34ff) || (Address >= 0x5480 && Address <= 0x54ff) || (Address >= 0x7480 && Address <= 0x74ff)) { + INT32 Offset = Address & 0x7f; + + GalSpriteRam[Offset] = Data; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = Data; + } + } + + return; + } + + switch (Address) { + case 0x1503: + case 0x3503: + case 0x5503: + case 0x7503: { + // coin_count_0_w + return; + } + + case 0x1580: + case 0x1581: + case 0x1582:{ + GalaxianSoundWrite(Address - 0x1580, Data); + return; + } + + case 0x3580: + case 0x3581: + case 0x3582:{ + GalaxianSoundWrite(Address - 0x3580, Data); + return; + } + + case 0x5580: + case 0x5581: + case 0x5582:{ + GalaxianSoundWrite(Address - 0x5580, Data); + return; + } + + case 0x7580: + case 0x7581: + case 0x7582:{ + GalaxianSoundWrite(Address - 0x7580, Data); + return; + } + + case 0x1583: + case 0x3583: + case 0x5583: + case 0x7583: { + // nop + return; + } + + case 0x1584: + case 0x1585: + case 0x1586: + case 0x1587: { + GalaxianLfoFreqWrite(Address - 0x1584, Data); + return; + } + + case 0x3584: + case 0x3585: + case 0x3586: + case 0x3587: { + GalaxianLfoFreqWrite(Address - 0x3584, Data); + return; + } + + case 0x5584: + case 0x5585: + case 0x5586: + case 0x5587: { + GalaxianLfoFreqWrite(Address - 0x5584, Data); + return; + } + + case 0x7584: + case 0x7585: + case 0x7586: + case 0x7587: { + GalaxianLfoFreqWrite(Address - 0x7584, Data); + return; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + // nop + return; + } + + case 0x1601: + case 0x3601: + case 0x5601: + case 0x7601: { + // nop + return; + } + + case 0x1604: + case 0x3604: + case 0x5604: + case 0x7604: { + // nop + return; + } + + case 0x1606: + case 0x3606: + case 0x5606: + case 0x7606: { + GalFlipScreenX = Data & 1; + return; + } + + case 0x1607: + case 0x3607: + case 0x5607: + case 0x7607: { + GalFlipScreenY = Data & 1; + return; + } + + case 0x1680: + case 0x3680: + case 0x5680: + case 0x7680: { + GalPitch = Data; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Write %04x, %02x\n"), Address, Data); + } + } +} + +UINT8 HunchbkgS2650PortRead(UINT16 Port) +{ + switch (Port) { + case S2650_DATA_PORT: { + // nop + return 0; + } + + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +void HunchbkgS2650PortWrite(UINT16 Port, UINT8 Data) +{ + switch (Port) { + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Write %04x, %02x\n"), Port, Data); + } + } +} + +UINT8 DrivfrcgS2650Read(UINT16 Address) +{ + switch (Address) { + case 0x1500: + case 0x3500: + case 0x5500: + case 0x7500: { + return GalInput[0] | GalDip[0]; + } + + case 0x1580: + case 0x3580: + case 0x5580: + case 0x7580: { + return GalInput[1] | GalDip[1]; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + return GalInput[2] | GalDip[2]; + } + + case 0x1700: + case 0x3700: + case 0x5700: + case 0x7700: { + return GalInput[3] | GalDip[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Read %04x\n"), Address); + } + } + + return 0; +} + +void DrivfrcgS2650Write(UINT16 Address, UINT8 Data) +{ + if ((Address >= 0x1480 && Address <= 0x14ff) || (Address >= 0x3480 && Address <= 0x34ff) || (Address >= 0x5480 && Address <= 0x54ff) || (Address >= 0x7480 && Address <= 0x74ff)) { + INT32 Offset = Address & 0x7f; + + GalSpriteRam[Offset] = Data; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = Data; + } + } + + return; + } + + switch (Address) { + case 0x1503: + case 0x3503: + case 0x5503: + case 0x7503: { + // coin_count_0_w + return; + } + + case 0x1580: + case 0x1581: + case 0x1582:{ + GalaxianSoundWrite(Address - 0x1580, Data); + return; + } + + case 0x3580: + case 0x3581: + case 0x3582:{ + GalaxianSoundWrite(Address - 0x3580, Data); + return; + } + + case 0x5580: + case 0x5581: + case 0x5582:{ + GalaxianSoundWrite(Address - 0x5580, Data); + return; + } + + case 0x7580: + case 0x7581: + case 0x7582:{ + GalaxianSoundWrite(Address - 0x7580, Data); + return; + } + + case 0x1583: + case 0x3583: + case 0x5583: + case 0x7583: { + // nop + return; + } + + case 0x1585: + case 0x3585: + case 0x5585: + case 0x7585: { + // nop + return; + } + + case 0x1586: + case 0x1587: { + GalaxianLfoFreqWrite(Address - 0x1586, Data); + return; + } + + case 0x3586: + case 0x3587: { + GalaxianLfoFreqWrite(Address - 0x3586, Data); + return; + } + + case 0x5586: + case 0x5587: { + GalaxianLfoFreqWrite(Address - 0x5586, Data); + return; + } + + case 0x7586: + case 0x7587: { + GalaxianLfoFreqWrite(Address - 0x7586, Data); + return; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + GalPitch = Data; + return; + } + + case 0x1700: + case 0x1701: { + // nop + return; + } + + case 0x1704: + case 0x1705: + case 0x1706: + case 0x1707: + case 0x3704: + case 0x3705: + case 0x3706: + case 0x3707: + case 0x5704: + case 0x5705: + case 0x5706: + case 0x5707: + case 0x7704: + case 0x7705: + case 0x7706: + case 0x7707: { + INT32 Offset = Address & 0x03; + GalVol = (GalVol & ~(1 << Offset)) | ((Data & 1) << Offset); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Write %04x, %02x\n"), Address, Data); + } + } +} + +UINT8 DrivfrcgS2650PortRead(UINT16 Port) +{ + switch (Port) { + case 0x00: { + switch (s2650GetPc()) { + case 0x02e: + case 0x297: { + return 0x01; + } + } + bprintf(PRINT_NORMAL, _T("%x\n"), s2650GetPc()); + return 0x00; + } + + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +void DrivfrcgS2650PortWrite(UINT16 Port, UINT8 Data) +{ + switch (Port) { + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Write %04x, %02x\n"), Port, Data); + } + } +} + +UINT8 RacknrolS2650Read(UINT16 Address) +{ + switch (Address) { + case 0x1500: + case 0x3500: + case 0x5500: + case 0x7500: { + return GalInput[0] | GalDip[0]; + } + + case 0x1580: + case 0x3580: + case 0x5580: + case 0x7580: { + return GalInput[1] | GalDip[1]; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + return GalInput[2] | GalDip[2]; + } + + case 0x1680: + case 0x3680: + case 0x5680: + case 0x7680: { + // ??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Read %04x\n"), Address); + } + } + + return 0; +} + +void RacknrolS2650Write(UINT16 Address, UINT8 Data) +{ + if ((Address >= 0x1400 && Address <= 0x14ff) || (Address >= 0x3400 && Address <= 0x34ff) || (Address >= 0x5400 && Address <= 0x54ff) || (Address >= 0x7400 && Address <= 0x74ff)) { + INT32 Offset = Address & 0xff; + + GalSpriteRam[Offset] = Data; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = Data; + } + } + + return; + } + + switch (Address) { + case 0x1601: + case 0x3601: + case 0x5601: + case 0x7601: { + // nop + return; + } + + case 0x1606: + case 0x3606: + case 0x5606: + case 0x7606: { + GalFlipScreenX = Data & 1; + return; + } + + case 0x1607: + case 0x3607: + case 0x5607: + case 0x7607: { + GalFlipScreenY = Data & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Write %04x, %02x\n"), Address, Data); + } + } +} + +UINT8 RacknrolS2650PortRead(UINT16 Port) +{ + switch (Port) { + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +void RacknrolS2650PortWrite(UINT16 Port, UINT8 Data) +{ + if (Port >= 0x0020 && Port <= 0x003f) { + GalGfxBank[Port - 0x0020] = Data; + return; + } + + switch (Port) { + case 0x001d: { + SN76496Write(0, Data); + return; + } + + case 0x001e: { + SN76496Write(1, Data); + return; + } + + case 0x001f: { + SN76496Write(2, Data); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Write %04x, %02x\n"), Port, Data); + } + } +} + +UINT8 HexpoolaS2650PortRead(UINT16 Port) +{ + switch (Port) { + case 0x0000: { + // nop + return 0; + } + + case S2650_DATA_PORT: { + switch (s2650GetPc()) { + case 0x22: return 0x00; + case 0x31: return 0x01; + } + return 0; + } + + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +void HexpoolaS2650PortWrite(UINT16 Port, UINT8 Data) +{ + if (Port >= 0x0020 && Port <= 0x003f) { + GalGfxBank[Port - 0x0020] = Data; + return; + } + + switch (Port) { + case S2650_DATA_PORT: { + SN76496Write(0, Data); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Write %04x, %02x\n"), Port, Data); + } + } +} + +UINT8 HunchbksS2650Read(UINT16 Address) +{ + switch (Address) { + case 0x1210: + case 0x1211: + case 0x1212: + case 0x1213: + case 0x3210: + case 0x3211: + case 0x3212: + case 0x3213: + case 0x5210: + case 0x5211: + case 0x5212: + case 0x5213: + case 0x7210: + case 0x7211: + case 0x7212: + case 0x7213: { + return ppi8255_r(0, Address & 0x03); + } + + case 0x1500: + case 0x1501: + case 0x1502: + case 0x1503: + case 0x3500: + case 0x3501: + case 0x3502: + case 0x3503: + case 0x5500: + case 0x5501: + case 0x5502: + case 0x5503: + case 0x7500: + case 0x7501: + case 0x7502: + case 0x7503: { + return ppi8255_r(0, Address & 0x03); + } + + case 0x1680: + case 0x3680: + case 0x5680: + case 0x7680: { + // watchdog read + return 0; + } + + case 0x1780: + case 0x3780: + case 0x5780: + case 0x7780: { + // watchdog read + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Read %04x\n"), Address); + } + } + + return 0; +} + +void HunchbksS2650Write(UINT16 Address, UINT8 Data) +{ + if ((Address >= 0x1400 && Address <= 0x14ff) || (Address >= 0x3400 && Address <= 0x34ff) || (Address >= 0x5400 && Address <= 0x54ff) || (Address >= 0x7400 && Address <= 0x74ff)) { + INT32 Offset = Address & 0xff; + + GalSpriteRam[Offset] = Data; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = Data; + } + } + + return; + } + + switch (Address) { + case 0x1210: + case 0x1211: + case 0x1212: + case 0x1213: + case 0x3210: + case 0x3211: + case 0x3212: + case 0x3213: + case 0x5210: + case 0x5211: + case 0x5212: + case 0x5213: + case 0x7210: + case 0x7211: + case 0x7212: + case 0x7213: { + ppi8255_w(1, Address & 0x03, Data); + return; + } + + case 0x1500: + case 0x1501: + case 0x1502: + case 0x1503: + case 0x3500: + case 0x3501: + case 0x3502: + case 0x3503: + case 0x5500: + case 0x5501: + case 0x5502: + case 0x5503: + case 0x7500: + case 0x7501: + case 0x7502: + case 0x7503: { + ppi8255_w(0, Address & 0x03, Data); + return; + } + + case 0x1600: + case 0x3600: + case 0x5600: + case 0x7600: { + // nop + return; + } + + case 0x1601: + case 0x3601: + case 0x5601: + case 0x7601: { + // nop + return; + } + + case 0x1606: + case 0x3606: + case 0x5606: + case 0x7606: { + GalFlipScreenX = Data & 1; + return; + } + + case 0x1607: + case 0x3607: + case 0x5607: + case 0x7607: { + GalFlipScreenY = Data & 1; + return; + } + + case 0x1700: + case 0x1701: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Write %04x, %02x\n"), Address, Data); + } + } +} + +UINT8 HunchbksS2650PortRead(UINT16 Port) +{ + switch (Port) { + case S2650_DATA_PORT: { + // nop + return 0; + } + + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +void HunchbksS2650PortWrite(UINT16 Port, UINT8 Data) +{ + switch (Port) { + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Write %04x, %02x\n"), Port, Data); + } + } +} + +UINT8 HncholmsS2650PortRead(UINT16 Port) +{ + switch (Port) { + case 0x0000: { + switch (s2650GetPc()) { + case 0x02b: return 1; + case 0xa27: return 1; + } + return 0; + } + + case S2650_DATA_PORT: { + // nop + return 0; + } + + case S2650_SENSE_PORT: { + return GalVBlank ? 0x80 : 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("S2650 #1 Port Read %04x\n"), Port); + } + } + + return 0; +} + +static INT32 GalS2650ReturnVector(INT32) +{ + return 0x03; +} + +static void S2650PostLoad() +{ + s2650Init(1); + s2650Open(0); + s2650MapMemory(GalS2650Rom1 + 0x0000, 0x0000, 0x0fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x1480, 0x14ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x1800, 0x1bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x1c00, 0x1fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x1000, 0x2000, 0x2fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x3480, 0x34ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x3800, 0x3bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x3c00, 0x3fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x2000, 0x4000, 0x4fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x5480, 0x54ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x5800, 0x5bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x5c00, 0x5fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x3000, 0x6000, 0x6fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x7480, 0x74ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x7800, 0x7bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x7c00, 0x7fff, S2650_RAM); + s2650SetReadHandler(HunchbkgS2650Read); + s2650SetWriteHandler(HunchbkgS2650Write); + s2650SetInHandler(HunchbkgS2650PortRead); + s2650SetOutHandler(HunchbkgS2650PortWrite); + s2650SetIrqCallback(GalS2650ReturnVector); + s2650Close(); +} + +static INT32 HunchbkgInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = S2650PostLoad; + + nRet = GalInit(); + + return nRet; +} + +static void DrivfrcgPostLoad() +{ + GalTempRom = (UINT8*)malloc(GalS2650Rom1Size); + memcpy(GalTempRom, GalS2650Rom1, GalS2650Rom1Size); + memcpy(GalS2650Rom1 + 0x1800, GalTempRom + 0x0000, 0x400); + memcpy(GalS2650Rom1 + 0x1c00, GalTempRom + 0x0400, 0x400); + memcpy(GalS2650Rom1 + 0x0000, GalTempRom + 0x0800, 0x400); + memcpy(GalS2650Rom1 + 0x0400, GalTempRom + 0x0c00, 0x400); + memcpy(GalS2650Rom1 + 0x0800, GalTempRom + 0x1000, 0x400); + memcpy(GalS2650Rom1 + 0x0c00, GalTempRom + 0x1400, 0x400); + memcpy(GalS2650Rom1 + 0x1000, GalTempRom + 0x1800, 0x400); + memcpy(GalS2650Rom1 + 0x1400, GalTempRom + 0x1c00, 0x400); + memcpy(GalS2650Rom1 + 0x3800, GalTempRom + 0x2000, 0x400); + memcpy(GalS2650Rom1 + 0x3c00, GalTempRom + 0x2400, 0x400); + memcpy(GalS2650Rom1 + 0x2000, GalTempRom + 0x2800, 0x400); + memcpy(GalS2650Rom1 + 0x2400, GalTempRom + 0x2c00, 0x400); + memcpy(GalS2650Rom1 + 0x2800, GalTempRom + 0x3000, 0x400); + memcpy(GalS2650Rom1 + 0x2c00, GalTempRom + 0x3400, 0x400); + memcpy(GalS2650Rom1 + 0x3000, GalTempRom + 0x3800, 0x400); + memcpy(GalS2650Rom1 + 0x3400, GalTempRom + 0x3c00, 0x400); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + S2650PostLoad(); + s2650Open(0); + s2650SetReadHandler(DrivfrcgS2650Read); + s2650SetWriteHandler(DrivfrcgS2650Write); + s2650SetInHandler(DrivfrcgS2650PortRead); + s2650SetOutHandler(DrivfrcgS2650PortWrite); + s2650Close(); +} + +static INT32 DrivfrcgInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DrivfrcgPostLoad; + + nRet = GalInit(); + + GalCalcPaletteFunction = RockclimCalcPalette; + GalExtendTileInfoFunction = Ad2083ExtendTileInfo; + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + return nRet; +} + +static INT32 DrivfrcbInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = DrivfrcgPostLoad; + + nRet = GalInit(); + + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + UINT8 *TempRom = (UINT8*)malloc(0x2000); + nRet = BurnLoadRom(TempRom, GAL_ROM_OFFSET_TILES_SHARED + 0, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x1000, TempRom + 0x0000, 0x1000); + memcpy(GalTempRom + 0x0000, TempRom + 0x1000, 0x1000); + nRet = BurnLoadRom(TempRom, GAL_ROM_OFFSET_TILES_SHARED + 1, 1); if (nRet) return 1; + memcpy(GalTempRom + 0x3000, TempRom + 0x0000, 0x1000); + memcpy(GalTempRom + 0x2000, TempRom + 0x1000, 0x1000); + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + + GalCalcPaletteFunction = RockclimCalcPalette; + GalExtendTileInfoFunction = Ad2083ExtendTileInfo; + GalExtendSpriteInfoFunction = MshuttleExtendSpriteInfo; + + return nRet; +} + +static void RacknrolPostLoad() +{ + s2650Init(1); + s2650Open(0); + s2650MapMemory(GalS2650Rom1 + 0x0000, 0x0000, 0x0fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x1400, 0x14ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x1800, 0x1bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x1c00, 0x1fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x1000, 0x2000, 0x2fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x3400, 0x34ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x3800, 0x3bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x3c00, 0x3fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x2000, 0x4000, 0x4fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x5400, 0x54ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x5800, 0x5bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x5c00, 0x5fff, S2650_RAM); + s2650MapMemory(GalS2650Rom1 + 0x3000, 0x6000, 0x6fff, S2650_ROM); + s2650MapMemory(GalSpriteRam, 0x7400, 0x74ff, S2650_READ); + s2650MapMemory(GalVideoRam, 0x7800, 0x7bff, S2650_RAM); + s2650MapMemory(GalZ80Ram1, 0x7c00, 0x7fff, S2650_RAM); + s2650SetReadHandler(RacknrolS2650Read); + s2650SetWriteHandler(RacknrolS2650Write); + s2650SetInHandler(RacknrolS2650PortRead); + s2650SetOutHandler(RacknrolS2650PortWrite); + s2650SetIrqCallback(GalS2650ReturnVector); + s2650Close(); +} + +static INT32 RacknrolInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = RacknrolPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496; + + nRet = GalInit(); + + GalExtendTileInfoFunction = RacknrolExtendTileInfo; + + return nRet; +} + +static void HexpoolaPostLoad() +{ + RacknrolPostLoad(); + + s2650Open(0); + s2650SetInHandler(HexpoolaS2650PortRead); + s2650SetOutHandler(HexpoolaS2650PortWrite); + s2650Close(); +} + +static INT32 HexpoolaInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HexpoolaPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496; + + nRet = GalInit(); + + GalExtendTileInfoFunction = RacknrolExtendTileInfo; + + return nRet; +} + +static void HunchbksPostLoad() +{ + RacknrolPostLoad(); + s2650Open(0); + s2650SetReadHandler(HunchbksS2650Read); + s2650SetWriteHandler(HunchbksS2650Write); + s2650SetInHandler(HunchbksS2650PortRead); + s2650SetOutHandler(HunchbksS2650PortWrite); + s2650Close(); + + ZetInit(1); +} + +static INT32 HunchbksInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HunchbksPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910; + + nRet = GalInit(); + HunchbksSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + PPI1PortWriteB = HunchbksSoundControlWrite; + + return nRet; +} + +static void HncholmsPostLoad() +{ + RacknrolPostLoad(); + s2650Open(0); + s2650SetReadHandler(HunchbksS2650Read); + s2650SetWriteHandler(HunchbksS2650Write); + s2650SetInHandler(HncholmsS2650PortRead); + s2650SetOutHandler(HunchbksS2650PortWrite); + s2650Close(); + + ZetInit(1); +} + +static INT32 HncholmsInit() +{ + INT32 nRet; + + GalPostLoadCallbackFunction = HncholmsPostLoad; + GalSoundType = GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910; + + nRet = GalInit(); + HunchbksSoundInit(); + + GalRenderBackgroundFunction = ScrambleDrawBackground; + GalDrawBulletsFunction = ScrambleDrawBullets; + GalExtendTileInfoFunction = Batman2ExtendTileInfo; + GalExtendSpriteInfoFunction = UpperExtendSpriteInfo; + + nGalCyclesTotal[0] = (18432000 / 6 / 2 / 2) / 60; + + GalSoundVolumeShift = 3; + + KonamiPPIInit(); + PPI1PortWriteB = HunchbksSoundControlWrite; + + return nRet; +} + +struct BurnDriver BurnDrvHunchbkg = { + "hunchbkg", "hunchbak", NULL, NULL, "1981", + "Hunchback (Galaxian hardware)\0", NULL, "Century Electronics", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, HunchbkgRomInfo, HunchbkgRomName, NULL, NULL, HunchbkgInputInfo, HunchbkgDIPInfo, + HunchbkgInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDrivfrcg = { + "drivfrcg", "drivfrcp", NULL, NULL, "1984", + "Driving Force (Galaxian conversion)\0", NULL, "Shinkai Inc. (Magic Eletronics USA licence)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_RACING, 0, + NULL, DrivfrcgRomInfo, DrivfrcgRomName, NULL, NULL, DrivfrcgInputInfo, DrivfrcgDIPInfo, + DrivfrcgInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvDrivfrcb = { + "drivfrcb", "drivfrcp", NULL, NULL, "1985", + "Driving Force (Galaxian conversion bootleg)\0", NULL, "bootleg", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_RACING, 0, + NULL, DrivfrcbRomInfo, DrivfrcbRomName, NULL, NULL, DrivfrcgInputInfo, DrivfrcgDIPInfo, + DrivfrcbInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRacknrol = { + "racknrol", NULL, NULL, NULL, "1986", + "Rack + Roll\0", NULL, "Status (Shinkai License)", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, RacknrolRomInfo, RacknrolRomName, NULL, NULL, RacknrolInputInfo, RacknrolDIPInfo, + RacknrolInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHexpool = { + "hexpool", "racknrol", NULL, NULL, "1986", + "Hex Pool (Shinkai)\0", NULL, "Shinkai", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, HexpoolRomInfo, HexpoolRomName, NULL, NULL, RacknrolInputInfo, RacknrolDIPInfo, + RacknrolInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHexpoola = { + "hexpoola", "racknrol", NULL, NULL, "1985", + "Hex Pool (Senko)\0", NULL, "Senko", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, HexpoolaRomInfo, HexpoolaRomName, NULL, NULL, RacknrolInputInfo, RacknrolDIPInfo, + HexpoolaInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHunchbks = { + "hunchbks", "hunchbak", NULL, NULL, "1983", + "Hunchback (Scramble hardware)\0", NULL, "Century Electronics", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_PLATFORM, 0, + NULL, HunchbksRomInfo, HunchbksRomName, NULL, NULL, HunchbksInputInfo, HunchbksDIPInfo, + HunchbksInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHncholms = { + "hncholms", "huncholy", NULL, NULL, "1984", + "Hunchback Olympic (Scramble hardware)\0", "Imperfect Sound", "Century Electronics", "Galaxian", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_GALAXIAN, GBF_SPORTSMISC, 0, + NULL, HncholmsRomInfo, HncholmsRomName, NULL, NULL, HunchbksInputInfo, HunchbksDIPInfo, + HncholmsInit, GalExit, GalFrame, NULL, GalScan, + NULL, 392, 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/galaxian/gal.h b/src/burn/drivers/galaxian/gal.h new file mode 100644 index 00000000..63e028fe --- /dev/null +++ b/src/burn/drivers/galaxian/gal.h @@ -0,0 +1,316 @@ +#include "tiles_generic.h" +#include "dac.h" +#include "8255ppi.h" +#include "bitswap.h" +#include "s2650_intf.h" +#include "sn76496.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +// ROM types +#define GAL_ROM_Z80_PROG1 1 +#define GAL_ROM_Z80_PROG2 2 +#define GAL_ROM_Z80_PROG3 3 +#define GAL_ROM_TILES_SHARED 4 +#define GAL_ROM_TILES_CHARS 5 +#define GAL_ROM_TILES_SPRITES 6 +#define GAL_ROM_PROM 7 +#define GAL_ROM_S2650_PROG1 8 + +#define GAL_ROM_OFFSET_Z80_PROG2 GalZ80Rom1Num +#define GAL_ROM_OFFSET_Z80_PROG3 GalZ80Rom1Num + GalZ80Rom2Num +#define GAL_ROM_OFFSET_TILES_SHARED GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num +#define GAL_ROM_OFFSET_TILES_CHARS GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum +#define GAL_ROM_OFFSET_TILES_SPRITES GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum +#define GAL_ROM_OFFSET_PROM GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum + GalTilesSpriteRomNum +#define GAL_ROM_OFFSET_S2650_PROG1 GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum + GalTilesSpriteRomNum + GalPromRomNum + +// IRQ types +#define GAL_IRQ_TYPE_NMI 1 +#define GAL_IRQ_TYPE_IRQ0 2 + +// Sound hardware types +#define GAL_SOUND_HARDWARE_TYPE_GALAXIAN 1 +#define GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 2 +#define GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 3 +#define GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 4 +#define GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 5 +#define GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 6 +#define GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC 7 +#define GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 8 +#define GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 9 +#define GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 10 +#define GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 11 +#define GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC 12 +#define GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 13 +#define GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 14 +#define GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 15 +#define GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496 16 +#define GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910 17 + +// Palette Numbers +#define GAL_PALETTE_NUM_COLOURS_PROM 64 +#define GAL_PALETTE_NUM_COLOURS_STARS 64 +#define GAL_PALETTE_NUM_COLOURS_BULLETS 8 +#define GAL_PALETTE_NUM_COLOURS_BACKGROUND 256 +#define GAL_PALETTE_STARS_OFFSET GAL_PALETTE_NUM_COLOURS_PROM +#define GAL_PALETTE_BULLETS_OFFSET GAL_PALETTE_NUM_COLOURS_PROM + GAL_PALETTE_NUM_COLOURS_STARS +#define GAL_PALETTE_BACKGROUND_OFFSET GAL_PALETTE_NUM_COLOURS_PROM + GAL_PALETTE_NUM_COLOURS_STARS + GAL_PALETTE_NUM_COLOURS_BULLETS + +// gal_gfx.cpp +extern UINT8 GalFlipScreenX; +extern UINT8 GalFlipScreenY; +extern UINT8 *GalGfxBank; +extern UINT8 GalPaletteBank; +extern UINT8 GalSpriteClipStart; +extern UINT8 GalSpriteClipEnd; +extern UINT8 FroggerAdjust; +extern UINT8 GalBackgroundRed; +extern UINT8 GalBackgroundGreen; +extern UINT8 GalBackgroundBlue; +extern UINT8 GalBackgroundEnable; +extern UINT8 SfxTilemap; +extern UINT8 GalOrientationFlipX; +extern UINT8 GalColourDepth; +extern UINT8 DarkplntBulletColour; +extern UINT8 DambustrBgColour1; +extern UINT8 DambustrBgColour2; +extern UINT8 DambustrBgPriority; +extern UINT8 DambustrBgSplitLine; +extern UINT8 *RockclimTiles; +extern UINT16 RockclimScrollX; +extern UINT16 RockclimScrollY; +extern INT32 CharPlaneOffsets[2]; +extern INT32 CharXOffsets[8]; +extern INT32 CharYOffsets[8]; +extern INT32 SpritePlaneOffsets[2]; +extern INT32 SpriteXOffsets[16]; +extern INT32 SpriteYOffsets[16]; + +typedef void (*GalRenderBackground)(); +extern GalRenderBackground GalRenderBackgroundFunction; +typedef void (*GalCalcPalette)(); +extern GalCalcPalette GalCalcPaletteFunction; +typedef void (*GalDrawBullet)(INT32, INT32, INT32); +extern GalDrawBullet GalDrawBulletsFunction; +typedef void (*GalExtendTileInfo)(UINT16*, INT32*, INT32, INT32); +extern GalExtendTileInfo GalExtendTileInfoFunction; +typedef void (*GalExtendSpriteInfo)(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8*); +extern GalExtendSpriteInfo GalExtendSpriteInfoFunction; +typedef void (*GalRenderFrame)(); +extern GalRenderFrame GalRenderFrameFunction; + +void UpperExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void UpperExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void PiscesExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void PiscesExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void Batman2ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void GmgalaxExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void GmgalaxExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void MooncrstExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void MooncrstExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void MoonqsrExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32); +void MoonqsrExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void SkybaseExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void SkybaseExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void RockclimExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void JumpbugExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void JumpbugExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void FroggerExtendTileInfo(UINT16*, INT32 *Colour, INT32, INT32); +void FroggerExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8 *Colour); +void CalipsoExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8 *yFlip, UINT16 *Code, UINT8*); +void MshuttleExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32); +void MshuttleExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void Fourin1ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void Fourin1ExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void DkongjrmExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*); +void MarinerExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x); +void MimonkeyExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32); +void MimonkeyExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*); +void DambustrExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x); +void Ad2083ExtendTileInfo(UINT16 *Code, INT32 *Colour, INT32 Attr, INT32); +void Ad2083ExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*); +void RacknrolExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x); +void HardCodeGalaxianPROM(); +void HardCodeMooncrstPROM(); +void GalaxianCalcPalette(); +void RockclimCalcPalette(); +void MarinerCalcPalette(); +void StratgyxCalcPalette(); +void RescueCalcPalette(); +void MinefldCalcPalette(); +void DarkplntCalcPalette(); +void DambustrCalcPalette(); +void GalaxianDrawBackground(); +void RockclimDrawBackground(); +void JumpbugDrawBackground(); +void FroggerDrawBackground(); +void TurtlesDrawBackground(); +void ScrambleDrawBackground(); +void AnteaterDrawBackground(); +void MarinerDrawBackground(); +void StratgyxDrawBackground(); +void RescueDrawBackground(); +void MinefldDrawBackground(); +void DambustrDrawBackground(); +void GalaxianDrawBullets(INT32 Offs, INT32 x, INT32 y); +void TheendDrawBullets(INT32 Offs, INT32 x, INT32 y); +void ScrambleDrawBullets(INT32, INT32 x, INT32 y); +void MoonwarDrawBullets(INT32, INT32 x, INT32 y); +void MshuttleDrawBullets(INT32, INT32 x, INT32 y); +void DarkplntDrawBullets(INT32, INT32 x, INT32 y); +void DambustrDrawBullets(INT32 Offs, INT32 x, INT32 y); +void GalDraw(); +void DkongjrmRenderFrame(); +void DambustrRenderFrame(); + +// gal_run.cpp +extern UINT8 GalInputPort0[8]; +extern UINT8 GalInputPort1[8]; +extern UINT8 GalInputPort2[8]; +extern UINT8 GalInputPort3[8]; +extern UINT8 GalDip[7]; +extern UINT8 GalInput[4]; +extern UINT8 GalReset; +extern UINT8 GalFakeDip; +extern INT32 GalAnalogPort0; +extern INT32 GalAnalogPort1; + +extern UINT8 *GalMem; +extern UINT8 *GalMemEnd; +extern UINT8 *GalRamStart; +extern UINT8 *GalRamEnd; +extern UINT8 *GalZ80Rom1; +extern UINT8 *GalZ80Rom1Op; +extern UINT8 *GalZ80Rom2; +extern UINT8 *GalZ80Rom3; +extern UINT8 *GalS2650Rom1; +extern UINT8 *GalZ80Ram1; +extern UINT8 *GalZ80Ram2; +extern UINT8 *GalVideoRam; +extern UINT8 *GalVideoRam2; +extern UINT8 *GalSpriteRam; +extern UINT8 *GalScrollVals; +extern UINT8 *GalProm; +extern UINT8 *GalChars; +extern UINT8 *GalSprites; +extern UINT8 *GalTempRom; +extern UINT32 *GalPalette; +extern UINT32 GalZ80Rom1Size; +extern UINT32 GalZ80Rom1Num; +extern UINT32 GalZ80Rom2Size; +extern UINT32 GalZ80Rom2Num; +extern UINT32 GalZ80Rom3Size; +extern UINT32 GalZ80Rom3Num; +extern UINT32 GalS2650Rom1Size; +extern UINT32 GalS2650Rom1Num; +extern UINT32 GalTilesSharedRomSize; +extern UINT32 GalTilesSharedRomNum; +extern UINT32 GalTilesCharRomSize; +extern UINT32 GalTilesCharRomNum; +extern UINT32 GalNumChars; +extern UINT32 GalTilesSpriteRomSize; +extern UINT32 GalTilesSpriteRomNum; +extern UINT32 GalNumSprites; +extern UINT32 GalPromRomSize; +extern UINT32 GalPromRomNum; + +typedef void (*GalPostLoadCallback)(); +extern GalPostLoadCallback GalPostLoadCallbackFunction; + +extern UINT8 GalIrqType; +extern UINT8 GalIrqFire; +extern INT32 nGalCyclesDone[3], nGalCyclesTotal[3]; + +extern UINT8 ZigzagAYLatch; +extern UINT8 GalSoundLatch; +extern UINT8 GalSoundLatch2; +extern UINT8 KingballSound; +extern UINT8 KonamiSoundControl; +extern UINT8 SfxSampleControl; +extern UINT8 KingballSpeechDip; +extern UINT16 ScrambleProtectionState; +extern UINT8 ScrambleProtectionResult; +extern UINT8 MoonwarPortSelect; +extern UINT8 MshuttleAY8910CS; +extern UINT8 GmgalaxSelectedGame; +extern UINT8 Fourin1Bank; +extern UINT8 GameIsGmgalax; +extern UINT8 CavelonBankSwitch; +extern UINT8 GalVBlank; + +UINT8 KonamiPPIReadIN0(); +UINT8 KonamiPPIReadIN1(); +UINT8 KonamiPPIReadIN2(); +UINT8 KonamiPPIReadIN3(); +INT32 GalInit(); +void MapMooncrst(); +void MapJumpbug(); +void MapFrogger(); +void KonamiPPIInit(); +void MapTheend(); +void MapTurtles(); +void MapScobra(); +INT32 GalExit(); +INT32 KonamiExit(); +INT32 GalFrame(); +INT32 GalScan(INT32 nAction, INT32 *pnMin); + +// gal_sound.cpp +extern INT16* pFMBuffer; +extern INT16* pAY8910Buffer[9]; +extern UINT8 GalSoundType; +extern UINT8 GalSoundVolumeShift; +extern UINT8 HunchbksSoundIrqFire; +extern UINT8 GalLastPort2; +extern UINT8 GalShootEnable; +extern UINT8 GalNoiseEnable; +extern INT32 GalNoiseVolume; +extern double GalShootWavePos; +extern double GalNoiseWavePos; +extern INT32 GalPitch; +extern INT32 GalVol; +extern INT32 GalLfoVolume[3]; +extern double GalLfoFreq; +extern double GalLfoFreqFrameVar; +extern INT32 GalLfoBit[4]; + +void GalSoundReset(); +void GalSoundInit(); +void GalSoundExit(); +void GalSoundScan(INT32 nAction, INT32 *pnMin); +UINT8 CheckmajPortARead(UINT32); +UINT8 BongoDipSwitchRead(UINT32); +UINT8 KonamiSoundLatchRead(UINT32); +UINT8 KonamiSoundTimerRead(UINT32); +UINT8 FroggerSoundTimerRead(UINT32); +UINT8 HunchbksSoundTimerRead(UINT32); +void KonamiSoundLatchWrite(UINT8 d); +void KonamiSoundControlWrite(UINT8 d); +void HunchbksSoundControlWrite(UINT8 d); +void SfxSoundLatch2Write(UINT32, UINT32 d); +void SfxSampleControlWrite(UINT32, UINT32 d); +void FroggerSoundInit(); +void FroggerSoundNoEncryptionInit(); +void KonamiSoundInit(); +void HunchbksSoundInit(); +void GalRenderSoundSamples(INT16 *pSoundBuf, INT32 nLength); +void GalaxianSoundWrite(UINT32 Offset, UINT8 d); +void GalaxianLfoFreqWrite(UINT32 Offset, UINT8 d); +void GalaxianSoundUpdateTimers(); + +// gal_stars.cpp +extern INT32 GalStarsEnable; +extern INT32 GalStarsScrollPos; +extern INT32 GalStarsBlinkState; +extern INT32 GalBlinkTimerStartFrame; + +void GalInitStars(); +void GalaxianRenderStarLayer(); +void JumpbugRenderStarLayer(); +void ScrambleRenderStarLayer(); +void MarinerRenderStarLayer(); +void RescueRenderStarLayer(); diff --git a/src/burn/drivers/galaxian/gal_gfx.cpp b/src/burn/drivers/galaxian/gal_gfx.cpp new file mode 100644 index 00000000..bc1a5d93 --- /dev/null +++ b/src/burn/drivers/galaxian/gal_gfx.cpp @@ -0,0 +1,1255 @@ +#include "gal.h" + +GalRenderBackground GalRenderBackgroundFunction; +GalCalcPalette GalCalcPaletteFunction; +GalDrawBullet GalDrawBulletsFunction; +GalExtendTileInfo GalExtendTileInfoFunction; +GalExtendSpriteInfo GalExtendSpriteInfoFunction; +GalRenderFrame GalRenderFrameFunction; + +UINT8 GalFlipScreenX; +UINT8 GalFlipScreenY; +UINT8 *GalGfxBank; +UINT8 GalPaletteBank; +UINT8 GalSpriteClipStart; +UINT8 GalSpriteClipEnd; +UINT8 FroggerAdjust; +UINT8 GalBackgroundRed; +UINT8 GalBackgroundGreen; +UINT8 GalBackgroundBlue; +UINT8 GalBackgroundEnable; +UINT8 SfxTilemap; +UINT8 GalOrientationFlipX; +UINT8 GalColourDepth; +UINT8 DarkplntBulletColour; +UINT8 DambustrBgColour1; +UINT8 DambustrBgColour2; +UINT8 DambustrBgPriority; +UINT8 DambustrBgSplitLine; +UINT8 *RockclimTiles; +UINT16 RockclimScrollX; +UINT16 RockclimScrollY; + +// Graphics decode helpers +INT32 CharPlaneOffsets[2] = { 0, 0x4000 }; +INT32 CharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +INT32 SpritePlaneOffsets[2] = { 0, 0x4000 }; +INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; +INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + +// Tile extend helpers +void UpperExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code += 0x100; +} + +void PiscesExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code |= GalGfxBank[0] << 8; +} + +void Batman2ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + if (*Code & 0x80) *Code |= GalGfxBank[0] << 8; +} + +void GmgalaxExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code |= GalGfxBank[0] << 9; +} + +void MooncrstExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + if (GalGfxBank[2] && (*Code & 0xc0) == 0x80) *Code = (*Code & 0x3f) | (GalGfxBank[0] << 6) | (GalGfxBank[1] << 7) | 0x0100; +} + +void MoonqsrExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32) +{ + *Code |= (Attr & 0x20) << 3; +} + +void SkybaseExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code |= GalGfxBank[2] << 8; +} + +void JumpbugExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + if ((*Code & 0xc0) == 0x80 && (GalGfxBank[2] & 0x01)) *Code += 128 + ((GalGfxBank[0] & 0x01) << 6) + ((GalGfxBank[1] & 0x01) << 7) + ((~GalGfxBank[4] & 0x01) << 8); +} + +void FroggerExtendTileInfo(UINT16*, INT32 *Colour, INT32, INT32) +{ + *Colour = ((*Colour >> 1) & 0x03) | ((*Colour << 2) & 0x04); +} + +void MshuttleExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32) +{ + *Code |= (Attr & 0x30) << 4; +} + +void Fourin1ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code |= Fourin1Bank << 8; +} + +void MarinerExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x) +{ + UINT8 *Prom = GalProm + 0x120; + + *Code |= (Prom[x] & 0x01) << 8; +} + +void MimonkeyExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32) +{ + *Code |= (GalGfxBank[0] << 8) | (GalGfxBank[1] << 9); +} + +void DambustrExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x) +{ + if (GalGfxBank[0] == 0) { + *Code |= 0x300; + } else { + if (x == 28) { + *Code |= 0x300; + } else { + *Code &= 0xff; + } + } +} + +void Ad2083ExtendTileInfo(UINT16 *Code, INT32 *Colour, INT32 Attr, INT32) +{ + INT32 Bank = Attr & 0x30; + *Code |= (Bank << 4); + *Colour |= ((Attr & 0x40) >> 3); +} + +void RacknrolExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x) +{ + UINT8 Bank = GalGfxBank[x] & 7; + *Code |= Bank << 8; +} + +// Sprite extend helpers +void UpperExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code += 0x40; +} + +void PiscesExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= GalGfxBank[0] << 6; +} + +void GmgalaxExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= (GalGfxBank[0] << 7) | 0x40; +} + +void MooncrstExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + if (GalGfxBank[2] && (*Code & 0x30) == 0x20) *Code = (*Code & 0x0f) | (GalGfxBank[0] << 4) | (GalGfxBank[1] << 5) | 0x40; +} + +void MoonqsrExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= (Base[2] & 0x20) << 1; +} + +void SkybaseExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= GalGfxBank[2] << 6; +} + +void RockclimExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + if (GalGfxBank[2]) *Code |= 0x40; +} + +void JumpbugExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + if ((*Code & 0x30) == 0x20 && (GalGfxBank[2] & 0x01) != 0) *Code += 32 + ((GalGfxBank[0] & 0x01) << 4) + ((GalGfxBank[1] & 0x01) << 5) + ((~GalGfxBank[4] & 0x01) << 6); +} + +void FroggerExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8 *Colour) +{ + *Colour = ((*Colour >> 1) & 0x03) | ((*Colour << 2) & 0x04); +} + +void CalipsoExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8 *yFlip, UINT16 *Code, UINT8*) +{ + *Code = Base[1]; + *xFlip = 0; + *yFlip = 0; +} + +void MshuttleExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= (Base[2] & 0x30) << 2; +} + +void Fourin1ExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= Fourin1Bank << 6; +} + +void DkongjrmExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*) +{ + *Code = (Base[1] & 0x7f) | 0x80; + *xFlip = 0; +} + +void MimonkeyExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*) +{ + *Code |= (GalGfxBank[0] << 6) | (GalGfxBank[1] << 7); +} + +void Ad2083ExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*) +{ + *Code = (Base[1] & 0x7f) | ((Base[2] & 0x30) << 2); + *xFlip = 0; +} + +// Hardcode a Galaxian PROM for any games that are missing a PROM dump +void HardCodeGalaxianPROM() +{ + GalProm[0x00]= 0x00; + GalProm[0x01]= 0x00; + GalProm[0x02]= 0x00; + GalProm[0x03]= 0xf6; + GalProm[0x04]= 0x00; + GalProm[0x05]= 0x16; + GalProm[0x06]= 0xc0; + GalProm[0x07]= 0x3f; + GalProm[0x08]= 0x00; + GalProm[0x09]= 0xd8; + GalProm[0x0a]= 0x07; + GalProm[0x0b]= 0x3f; + GalProm[0x0c]= 0x00; + GalProm[0x0d]= 0xc0; + GalProm[0x0e]= 0xc4; + GalProm[0x0f]= 0x07; + GalProm[0x10]= 0x00; + GalProm[0x11]= 0xc0; + GalProm[0x12]= 0xa0; + GalProm[0x13]= 0x07; + GalProm[0x14]= 0x00; + GalProm[0x15]= 0x00; + GalProm[0x16]= 0x00; + GalProm[0x17]= 0x07; + GalProm[0x18]= 0x00; + GalProm[0x19]= 0xf6; + GalProm[0x1a]= 0x07; + GalProm[0x1b]= 0xf0; + GalProm[0x1c]= 0x00; + GalProm[0x1d]= 0x76; + GalProm[0x1e]= 0x07; + GalProm[0x1f]= 0xc6; +} + +void HardCodeMooncrstPROM() +{ + GalProm[0x00]= 0x00; + GalProm[0x01]= 0x7a; + GalProm[0x02]= 0x36; + GalProm[0x03]= 0x07; + GalProm[0x04]= 0x00; + GalProm[0x05]= 0xf0; + GalProm[0x06]= 0x38; + GalProm[0x07]= 0x1f; + GalProm[0x08]= 0x00; + GalProm[0x09]= 0xc7; + GalProm[0x0a]= 0xf0; + GalProm[0x0b]= 0x3f; + GalProm[0x0c]= 0x00; + GalProm[0x0d]= 0xdb; + GalProm[0x0e]= 0xc6; + GalProm[0x0f]= 0x38; + GalProm[0x10]= 0x00; + GalProm[0x11]= 0x36; + GalProm[0x12]= 0x07; + GalProm[0x13]= 0xf0; + GalProm[0x14]= 0x00; + GalProm[0x15]= 0x33; + GalProm[0x16]= 0x3f; + GalProm[0x17]= 0xdb; + GalProm[0x18]= 0x00; + GalProm[0x19]= 0x3f; + GalProm[0x1a]= 0x57; + GalProm[0x1b]= 0xc6; + GalProm[0x1c]= 0x00; + GalProm[0x1d]= 0xc6; + GalProm[0x1e]= 0x3f; + GalProm[0x1f]= 0xff; +} + +// Pallet generation +#define RGB_MAXIMUM 224 +#define MAX_NETS 3 +#define MAX_RES_PER_NET 18 +#define Combine2Weights(tab,w0,w1) ((INT32)(((tab)[0]*(w0) + (tab)[1]*(w1)) + 0.5)) +#define Combine3Weights(tab,w0,w1,w2) ((INT32)(((tab)[0]*(w0) + (tab)[1]*(w1) + (tab)[2]*(w2)) + 0.5)) + +static double ComputeResistorWeights(INT32 MinVal, INT32 MaxVal, double Scaler, INT32 Count1, const INT32 *Resistances1, double *Weights1, INT32 PullDown1, INT32 PullUp1, INT32 Count2, const INT32 *Resistances2, double *Weights2, INT32 PullDown2, INT32 PullUp2, INT32 Count3, const INT32 *Resistances3, double *Weights3, INT32 PullDown3, INT32 PullUp3) +{ + INT32 NetworksNum; + + INT32 ResCount[MAX_NETS]; + double r[MAX_NETS][MAX_RES_PER_NET]; + double w[MAX_NETS][MAX_RES_PER_NET]; + double ws[MAX_NETS][MAX_RES_PER_NET]; + INT32 r_pd[MAX_NETS]; + INT32 r_pu[MAX_NETS]; + + double MaxOut[MAX_NETS]; + double *Out[MAX_NETS]; + + INT32 i, j, n; + double Scale; + double Max; + + NetworksNum = 0; + for (n = 0; n < MAX_NETS; n++) { + INT32 Count, pd, pu; + const INT32 *Resistances; + double *Weights; + + switch (n) { + case 0: { + Count = Count1; + Resistances = Resistances1; + Weights = Weights1; + pd = PullDown1; + pu = PullUp1; + break; + } + + case 1: { + Count = Count2; + Resistances = Resistances2; + Weights = Weights2; + pd = PullDown2; + pu = PullUp2; + break; + } + + case 2: + default: { + Count = Count3; + Resistances = Resistances3; + Weights = Weights3; + pd = PullDown3; + pu = PullUp3; + break; + } + } + + if (Count > 0) { + ResCount[NetworksNum] = Count; + for (i = 0; i < Count; i++) { + r[NetworksNum][i] = 1.0 * Resistances[i]; + } + Out[NetworksNum] = Weights; + r_pd[NetworksNum] = pd; + r_pu[NetworksNum] = pu; + NetworksNum++; + } + } + + for (i = 0; i < NetworksNum; i++) { + double R0, R1, Vout, Dst; + + for (n = 0; n < ResCount[i]; n++) { + R0 = (r_pd[i] == 0) ? 1.0 / 1e12 : 1.0 / r_pd[i]; + R1 = (r_pu[i] == 0) ? 1.0 / 1e12 : 1.0 / r_pu[i]; + + for (j = 0; j < ResCount[i]; j++) { + if (j == n) { + if (r[i][j] != 0.0) R1 += 1.0 / r[i][j]; + } else { + if (r[i][j] != 0.0) R0 += 1.0 / r[i][j]; + } + } + + R0 = 1.0/R0; + R1 = 1.0/R1; + Vout = (MaxVal - MinVal) * R0 / (R1 + R0) + MinVal; + + Dst = (Vout < MinVal) ? MinVal : (Vout > MaxVal) ? MaxVal : Vout; + + w[i][n] = Dst; + } + } + + j = 0; + Max = 0.0; + for (i = 0; i < NetworksNum; i++) { + double Sum = 0.0; + + for (n = 0; n < ResCount[i]; n++) Sum += w[i][n]; + + MaxOut[i] = Sum; + if (Max < Sum) { + Max = Sum; + j = i; + } + } + + if (Scaler < 0.0) { + Scale = ((double)MaxVal) / MaxOut[j]; + } else { + Scale = Scaler; + } + + for (i = 0; i < NetworksNum; i++) { + for (n = 0; n < ResCount[i]; n++) { + ws[i][n] = w[i][n] * Scale; + (Out[i])[n] = ws[i][n]; + } + } + + return Scale; + +} + +void GalaxianCalcPalette() +{ + static const INT32 RGBResistances[3] = {1000, 470, 220}; + double rWeights[3], gWeights[3], bWeights[2]; + + ComputeResistorWeights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0); + + // Colour PROM + for (INT32 i = 0; i < 32; i++) { + UINT8 Bit0, Bit1, Bit2, r, g, b; + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2); + r = Combine3Weights(rWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5); + g = Combine3Weights(gWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7); + b = Combine2Weights(bWeights, Bit0, Bit1); + + GalPalette[i] = BurnHighCol(r, g, b, 0); + } + + // Stars + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) { + INT32 Bits, r, g, b; + INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff}; + + Bits = (i >> 0) & 0x03; + r = Map[Bits]; + Bits = (i >> 2) & 0x03; + g = Map[Bits]; + Bits = (i >> 4) & 0x03; + b = Map[Bits]; + + GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0); + } + + // Bullets + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) { + GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0); + } + GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0); +} + +void RockclimCalcPalette() +{ + static const INT32 RGBResistances[3] = {1000, 470, 220}; + double rWeights[3], gWeights[3], bWeights[2]; + + ComputeResistorWeights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0); + + // Colour PROM + for (INT32 i = 0; i < 64; i++) { + UINT8 Bit0, Bit1, Bit2, r, g, b; + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2); + r = Combine3Weights(rWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5); + g = Combine3Weights(gWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7); + b = Combine2Weights(bWeights, Bit0, Bit1); + + GalPalette[i] = BurnHighCol(r, g, b, 0); + } + + // Stars + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) { + INT32 Bits, r, g, b; + INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff}; + + Bits = (i >> 0) & 0x03; + r = Map[Bits]; + Bits = (i >> 2) & 0x03; + g = Map[Bits]; + Bits = (i >> 4) & 0x03; + b = Map[Bits]; + + GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0); + } + + // Bullets + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) { + GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0); + } + GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0); +} + +void MarinerCalcPalette() +{ + GalaxianCalcPalette(); + + for (INT32 i = 0; i < 16; i++) { + INT32 b = 0x0e * BIT(i, 0) + 0x1f * BIT(i, 1) + 0x43 * BIT(i, 2) + 0x8f * BIT(i, 3); + GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, b, 0); + } +} + +void StratgyxCalcPalette() +{ + GalaxianCalcPalette(); + + for (INT32 i = 0; i < 8; i++) { + INT32 r = BIT(i, 0) * 0x7c; + INT32 g = BIT(i, 1) * 0x3c; + INT32 b = BIT(i, 2) * 0x47; + GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0); + } +} + +void RescueCalcPalette() +{ + GalaxianCalcPalette(); + + for (INT32 i = 0; i < 128; i++) { + INT32 b = i * 2; + GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, b, 0); + } +} + +void MinefldCalcPalette() +{ + RescueCalcPalette(); + + for (INT32 i = 0; i < 128; i++) { + INT32 r = (INT32)(i * 1.5); + INT32 g = (INT32)(i * 0.75); + INT32 b = i / 2; + GalPalette[i + 128 + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0); + } +} + +void DarkplntCalcPalette() +{ + static const INT32 RGBResistances[3] = {1000, 470, 220}; + double rWeights[3], gWeights[3], bWeights[2]; + + ComputeResistorWeights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0); + + // Colour PROM + for (INT32 i = 0; i < 32; i++) { + UINT8 Bit0, Bit1, Bit2, r, g, b; + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2); + r = Combine3Weights(rWeights, Bit0, Bit1, Bit2); + + g = 0; + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5); + b = Combine2Weights(bWeights, Bit0, Bit1); + + GalPalette[i] = BurnHighCol(r, g, b, 0); + } + + // Stars + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) { + INT32 Bits, r, g, b; + INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff}; + + Bits = (i >> 0) & 0x03; + r = Map[Bits]; + Bits = (i >> 2) & 0x03; + g = Map[Bits]; + Bits = (i >> 4) & 0x03; + b = Map[Bits]; + + GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0); + } + + // Bullets + GalPalette[0 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xef, 0x00, 0x00, 0); + GalPalette[1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0x00, 0x00, 0xef, 0); +} + +void DambustrCalcPalette() +{ + static const INT32 RGBResistances[3] = {1000, 470, 220}; + double rWeights[3], gWeights[3], bWeights[2]; + + ComputeResistorWeights(0, RGB_MAXIMUM, -1.0, 3, &RGBResistances[0], rWeights, 470, 0, 3, &RGBResistances[0], gWeights, 470, 0, 2, &RGBResistances[1], bWeights, 470, 0); + + // Colour PROM + for (INT32 i = 0; i < 32; i++) { + UINT8 Bit0, Bit1, Bit2, r, g, b; + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],0); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],1); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],2); + b = Combine3Weights(rWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],3); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],4); + Bit2 = BIT(GalProm[i + (GalPaletteBank * 0x20)],5); + r = Combine3Weights(gWeights, Bit0, Bit1, Bit2); + + Bit0 = BIT(GalProm[i + (GalPaletteBank * 0x20)],6); + Bit1 = BIT(GalProm[i + (GalPaletteBank * 0x20)],7); + g = Combine2Weights(bWeights, Bit0, Bit1); + + GalPalette[i] = BurnHighCol(r, g, b, 0); + } + + // Stars + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_STARS; i++) { + INT32 Bits, r, g, b; + INT32 Map[4] = {0x00, 0x88, 0xcc, 0xff}; + + Bits = (i >> 0) & 0x03; + r = Map[Bits]; + Bits = (i >> 2) & 0x03; + g = Map[Bits]; + Bits = (i >> 4) & 0x03; + b = Map[Bits]; + + GalPalette[i + GAL_PALETTE_STARS_OFFSET] = BurnHighCol(r, g, b, 0); + } + + // Bullets + for (INT32 i = 0; i < GAL_PALETTE_NUM_COLOURS_BULLETS - 1; i++) { + GalPalette[i + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0xff, 0); + } + GalPalette[GAL_PALETTE_NUM_COLOURS_BULLETS - 1 + GAL_PALETTE_BULLETS_OFFSET] = BurnHighCol(0xff, 0xff, 0x00, 0); + + for (INT32 i = 0; i < 8; i++) { + INT32 r = BIT(i, 0) * 0x47; + INT32 g = BIT(i, 1) * 0x47; + INT32 b = BIT(i, 2) * 0x4f; + GalPalette[i + GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(r, g, b, 0); + } +} + +#undef RGB_MAXIMUM +#undef MAX_NETS +#undef MAX_RES_PER_NET +#undef Combine_2Weights +#undef Combine_3Weights + +// Background and Stars rendering +void GalaxianDrawBackground() +{ + if (GalStarsEnable) GalaxianRenderStarLayer(); +} + +void RockclimDrawBackground() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = GalVideoRam2[TileIndex]; + Colour = 0; + + x = 8 * mx; + y = 8 * my; + + x -= RockclimScrollX & 0x1ff; + y -= RockclimScrollY & 0xff; + + if (x < -8) x += 512; + if (y < -8) y += 256; + + y -= 16; + + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 4, 32, RockclimTiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 32, RockclimTiles); + } + + TileIndex++; + } + } +} + +void JumpbugDrawBackground() +{ + if (GalStarsEnable) JumpbugRenderStarLayer(); +} + +void FroggerDrawBackground() +{ + GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x47, 0); + + if (GalFlipScreenX) { + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = nScreenWidth - 1; x > 128 - 8; x--) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } else { + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < 128 + 8; x++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } +} + +void TurtlesDrawBackground() +{ + GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(GalBackgroundRed * 0x55, GalBackgroundGreen * 0x47, GalBackgroundBlue * 0x55, 0); + + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < nScreenWidth; x++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } +} + +void ScrambleDrawBackground() +{ + GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x56, 0); + + if (GalBackgroundEnable) { + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < nScreenWidth; x++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } + + if (GalStarsEnable) ScrambleRenderStarLayer(); +} + +void AnteaterDrawBackground() +{ + GalPalette[GAL_PALETTE_BACKGROUND_OFFSET] = BurnHighCol(0, 0, 0x56, 0); + + if (GalBackgroundEnable) { + if (GalFlipScreenX) { + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = nScreenWidth - 1; x > 256 - 56; x--) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } else { + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < 56; x++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } + } +} + +void MarinerDrawBackground() +{ + UINT8 *BgColourProm = GalProm + 0x20; + INT32 x; + + if (GalFlipScreenX) { + for (x = 0; x < 32; x++) { + INT32 Colour; + + if (x == 0) { + Colour = 0; + } else { + Colour = BgColourProm[0x20 + x - 1]; + } + + INT32 xStart = 8 * (31 - x); + for (INT32 sy = 0; sy < nScreenHeight; sy++) { + for (INT32 sx = xStart; sx < xStart + 8; sx++) { + pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour; + } + } + } + } else { + for (x = 0; x < 32; x++) { + INT32 Colour; + + if (x == 31) { + Colour = 0; + } else { + Colour = BgColourProm[x + 1]; + } + + INT32 xStart = x * 8; + for (INT32 sy = 0; sy < nScreenHeight; sy++) { + for (INT32 sx = xStart; sx < xStart + 8; sx++) { + pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour; + } + } + } + } + + if (GalStarsEnable) MarinerRenderStarLayer(); +} + +void StratgyxDrawBackground() +{ + UINT8 *BgColourProm = GalProm + 0x20; + + for (INT32 x = 0; x < 32; x++) { + INT32 xStart, Colour = 0; + + if ((~BgColourProm[x] & 0x02) && GalBackgroundRed) Colour |= 0x01; + if ((~BgColourProm[x] & 0x02) && GalBackgroundGreen) Colour |= 0x02; + if ((~BgColourProm[x] & 0x01) && GalBackgroundBlue) Colour |= 0x04; + + if (GalFlipScreenX) { + xStart = 8 * (31 - x); + } else { + xStart = 8 * x; + } + + for (INT32 sy = 0; sy < nScreenHeight; sy++) { + for (INT32 sx = xStart; sx < xStart + 8; sx++) { + pTransDraw[(sy * nScreenWidth) + sx] = GAL_PALETTE_BACKGROUND_OFFSET + Colour; + } + } + } +} + +void RescueDrawBackground() +{ + if (GalBackgroundEnable) { + INT32 x; + + for (x = 0; x < 128; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + x; + } + } + + for (x = 0; x < 120; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + (x + 128)] = GAL_PALETTE_BACKGROUND_OFFSET + x + 8; + } + } + + for (x = 0; x < 8; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + (x + 248)] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } + + if (GalStarsEnable) RescueRenderStarLayer(); +} + +void MinefldDrawBackground() +{ + if (GalBackgroundEnable) { + INT32 x; + + for (x = 0; x < 128; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + x; + } + } + + for (x = 0; x < 120; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + (x + 128)] = GAL_PALETTE_BACKGROUND_OFFSET + x + 128; + } + } + + for (x = 0; x < 8; x++) { + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + (x + 248)] = GAL_PALETTE_BACKGROUND_OFFSET; + } + } + } + + if (GalStarsEnable) RescueRenderStarLayer(); +} + +void DambustrDrawBackground() +{ + INT32 xClipStart = GalFlipScreenX ? 254 - DambustrBgSplitLine : 0; + INT32 xClipEnd = GalFlipScreenX ? 0 : 254 - DambustrBgSplitLine; + + for (INT32 x = 0; x < 256 - DambustrBgSplitLine; x++) { + if (DambustrBgPriority && (x < xClipStart || x > xClipEnd)) continue; + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + ((GalFlipScreenX) ? DambustrBgColour2 : DambustrBgColour1); + } + } + + for (INT32 x = 255; x > 256 - DambustrBgSplitLine; x--) { + if (DambustrBgPriority && (x < xClipStart || x > xClipEnd)) continue; + for (INT32 y = 0; y < nScreenHeight; y++) { + pTransDraw[(y * nScreenWidth) + x] = GAL_PALETTE_BACKGROUND_OFFSET + ((GalFlipScreenX) ? DambustrBgColour1 : DambustrBgColour2); + } + } + + if (GalStarsEnable && !DambustrBgPriority) GalaxianRenderStarLayer(); +} + +// Char Layer rendering +static void GalRenderBgLayer(UINT8 *pVideoRam) +{ + INT32 mx, my, Attr, Colour, x, y, TileIndex = 0, RamPos; + UINT16 Code; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + RamPos = TileIndex & 0x1f; + Code = pVideoRam[TileIndex]; + Attr = GalSpriteRam[(RamPos * 2) + 1]; + Colour = Attr & ((GalColourDepth == 3) ? 0x03 : 0x07); + + if (GalExtendTileInfoFunction) GalExtendTileInfoFunction(&Code, &Colour, Attr, RamPos); + + if (SfxTilemap) { + x = 8 * my; + y = 8 * mx; + } else { + x = 8 * mx; + y = 8 * my; + } + + y -= 16; + + if (GalFlipScreenX) x = nScreenWidth - 8 - x; + if (GalFlipScreenY) y = nScreenHeight - 8 - y; + + INT32 px, py; + + UINT32 nPalette = Colour << GalColourDepth; + + for (py = 0; py < 8; py++) { + for (px = 0; px < 8; px++) { + UINT8 c = GalChars[(Code * 64) + (py * 8) + px]; + if (GalFlipScreenX) c = GalChars[(Code * 64) + (py * 8) + (7 - px)]; + if (GalFlipScreenY) c = GalChars[(Code * 64) + ((7 - py) * 8) + px]; + if (GalFlipScreenX && GalFlipScreenY) c = GalChars[(Code * 64) + ((7 - py) * 8) + (7 - px)]; + + if (c) { + INT32 xPos = x + px; + INT32 yPos = y + py; + + if (SfxTilemap) { + if (GalFlipScreenX) { + xPos += GalScrollVals[mx]; + } else { + xPos -= GalScrollVals[mx]; + } + + if (xPos < 0) xPos += 256; + if (xPos > 255) xPos -= 256; + } else { + if (GalFlipScreenY) { + yPos += GalScrollVals[mx]; + } else { + yPos -= GalScrollVals[mx]; + } + + if (yPos < 0) yPos += 256; + if (yPos > 255) yPos -= 256; + } + + if (GalOrientationFlipX) { + xPos = nScreenWidth - 1 - xPos; + } + + if (yPos >= 0 && yPos < nScreenHeight) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + + TileIndex++; + } + } +} + +// Sprite Rendering +static void GalRenderSprites(const UINT8 *SpriteBase) +{ + INT32 SprNum; + INT32 ClipOfs = GalFlipScreenX ? 16 : 0; + INT32 xMin = GalSpriteClipStart - ClipOfs; + INT32 xMax = GalSpriteClipEnd - ClipOfs + 1; + + for (SprNum = 7; SprNum >= 0; SprNum--) { + const UINT8 *Base = &SpriteBase[SprNum * 4]; + UINT8 Base0 = FroggerAdjust ? ((Base[0] >> 4) | (Base[0] << 4)) : Base[0]; + INT32 sy = 240 - (Base0 - (SprNum < 3)); + UINT16 Code = Base[1] & 0x3f; + UINT8 xFlip = Base[1] & 0x40; + UINT8 yFlip = Base[1] & 0x80; + UINT8 Colour = Base[2] & ((GalColourDepth == 3) ? 0x03 : 0x07); + INT32 sx = Base[3]; + + if (GalExtendSpriteInfoFunction) GalExtendSpriteInfoFunction(Base, &sx, &sy, &xFlip, &yFlip, &Code, &Colour); + + if (GalFlipScreenX) { + sx = 242 - sx; + xFlip = !xFlip; + } + + if (sx < xMin || sx > xMax) continue; + + if (GalFlipScreenY) { + sy = 240 - sy; + yFlip = !yFlip; + } + + sy -= 16; + + if (GalOrientationFlipX) { + sx = 242 - 1 - sx; + xFlip = !xFlip; + } + + if (sx > 16 && sx < (nScreenWidth - 16) && sy > 16 && sy < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, GalColourDepth, 0, 0, GalSprites); + } + } + } + } +} + +// Bullet rendering +static inline void GalDrawPixel(INT32 x, INT32 y, INT32 Colour) +{ + if (y >= 0 && y < nScreenHeight && x >= 0 && x < nScreenWidth) { + pTransDraw[(y * nScreenWidth) + x] = Colour; + } +} + +void GalaxianDrawBullets(INT32 Offs, INT32 x, INT32 y) +{ + x -= 4; + + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); +} + +void TheendDrawBullets(INT32 Offs, INT32 x, INT32 y) +{ + x -= 4; + + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0xff, 0x00, 0xff, 0); + + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); + GalDrawPixel(x++, y, GAL_PALETTE_BULLETS_OFFSET + Offs); +} + +void ScrambleDrawBullets(INT32, INT32 x, INT32 y) +{ + x -= 6; + + GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + 7); +} + +void MoonwarDrawBullets(INT32, INT32 x, INT32 y) +{ + x -= 6; + + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0xef, 0xef, 0x97, 0); + + GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + 7); +} + +void MshuttleDrawBullets(INT32, INT32 x, INT32 y) +{ + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 0] = BurnHighCol(0xff, 0xff, 0xff, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 1] = BurnHighCol(0xff, 0xff, 0x00, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 2] = BurnHighCol(0x00, 0xff, 0xff, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 3] = BurnHighCol(0x00, 0xff, 0x00, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 4] = BurnHighCol(0xff, 0x00, 0xff, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 5] = BurnHighCol(0xff, 0x00, 0x00, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 6] = BurnHighCol(0x00, 0x00, 0xff, 0); + GalPalette[GAL_PALETTE_BULLETS_OFFSET + 7] = BurnHighCol(0x00, 0x00, 0x00, 0); + + --x; + GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET + + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET + + 4); + --x; + GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET + + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET + + 4); + --x; + GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET + + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET + + 4); + --x; + GalDrawPixel(x, y, ((x & 0x40) == 0) ? GAL_PALETTE_BULLETS_OFFSET + + ((x >> 2) & 7) : GAL_PALETTE_BULLETS_OFFSET + + 4); +} + +void DarkplntDrawBullets(INT32, INT32 x, INT32 y) +{ + if (GalFlipScreenX) x++; + + x -= 6; + + GalDrawPixel(x, y, GAL_PALETTE_BULLETS_OFFSET + DarkplntBulletColour); +} + +void DambustrDrawBullets(INT32 Offs, INT32 x, INT32 y) +{ + INT32 Colour; + + if (GalFlipScreenX) x++; + + x -= 6; + + for (INT32 i = 0; i < 2; i++) { + if (Offs < 16) { + Colour = GAL_PALETTE_BULLETS_OFFSET + 7; + y--; + } else { + Colour = GAL_PALETTE_BULLETS_OFFSET; + x--; + } + } + + GalDrawPixel(x, y, Colour); +} + +static void GalDrawBullets(const UINT8 *Base) +{ + for (INT32 y = 0; y < nScreenHeight; y++) { + UINT8 Shell = 0xff; + UINT8 Missile = 0xff; + UINT8 yEff; + INT32 Which; + + yEff = (GalFlipScreenY) ? (y + 16 - 1) ^ 255 : y + 16 - 1; + + for (Which = 0; Which < 3; Which++) { + if ((UINT8)(Base[Which * 4 + 1] + yEff) == 0xff) Shell = Which; + } + + yEff = (GalFlipScreenY) ? (y + 16) ^ 255 : y + 16; + + for (Which = 3; Which < 8; Which++) { + if ((UINT8)(Base[Which * 4 + 1] + yEff) == 0xff) { + if (Which != 7) { + Shell = Which; + } else { + Missile = Which; + } + } + } + + if (Shell != 0xff) GalDrawBulletsFunction(Shell, (GalOrientationFlipX) ? Base[Shell * 4 + 3] : 255 - Base[Shell * 4 + 3], y); + if (Missile != 0xff) GalDrawBulletsFunction(Missile, (GalOrientationFlipX) ? Base[Missile * 4 + 3] : 255 - Base[Missile * 4 + 3], y); + } +} + +// Render a frame +void GalDraw() +{ + if (GalRenderFrameFunction) { + GalRenderFrameFunction(); + } else { + BurnTransferClear(); + GalCalcPaletteFunction(); + if (GalRenderBackgroundFunction) GalRenderBackgroundFunction(); + GalRenderBgLayer(GalVideoRam); + GalRenderSprites(&GalSpriteRam[0x40]); + if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]); + BurnTransferCopy(GalPalette); + } +} + +void DkongjrmRenderFrame() +{ + BurnTransferClear(); + GalCalcPaletteFunction(); + if (GalRenderBackgroundFunction) GalRenderBackgroundFunction(); + GalRenderBgLayer(GalVideoRam); + GalRenderSprites(&GalSpriteRam[0x40]); + GalRenderSprites(&GalSpriteRam[0x60]); + GalRenderSprites(&GalSpriteRam[0xc0]); + GalRenderSprites(&GalSpriteRam[0xe0]); + if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]); + BurnTransferCopy(GalPalette); +} + +void DambustrRenderFrame() +{ + BurnTransferClear(); + GalCalcPaletteFunction(); + if (GalRenderBackgroundFunction) GalRenderBackgroundFunction(); + GalRenderBgLayer(GalVideoRam); + GalRenderSprites(&GalSpriteRam[0x40]); + if (GalDrawBulletsFunction) GalDrawBullets(&GalSpriteRam[0x60]); + if (DambustrBgPriority) { + if (GalRenderBackgroundFunction) GalRenderBackgroundFunction(); + memset(GalVideoRam2, 0x20, 0x400); + for (INT32 i = 0; i < 32; i++) { + INT32 Colour = GalSpriteRam[(i << 1) | 1] & 7; + if (Colour > 3) { + for (INT32 j = 0; j < 32; j++) GalVideoRam2[(32 * j) + i] = GalVideoRam[(32 * j) + i]; + } + } + GalRenderBgLayer(GalVideoRam2); + } + BurnTransferCopy(GalPalette); +} diff --git a/src/burn/drivers/galaxian/gal_run.cpp b/src/burn/drivers/galaxian/gal_run.cpp new file mode 100644 index 00000000..6e171198 --- /dev/null +++ b/src/burn/drivers/galaxian/gal_run.cpp @@ -0,0 +1,1960 @@ +#include "gal.h" + +UINT8 GalInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 GalInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 GalInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 GalInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 GalDip[7] = {0, 0, 0, 0, 0, 0, 0}; +UINT8 GalInput[4] = {0x00, 0x00, 0x00, 0x00}; +UINT8 GalReset = 0; +UINT8 GalFakeDip = 0; +INT32 GalAnalogPort0 = 0; +INT32 GalAnalogPort1 = 0; + +UINT8 *GalMem = NULL; +UINT8 *GalMemEnd = NULL; +UINT8 *GalRamStart = NULL; +UINT8 *GalRamEnd = NULL; +UINT8 *GalZ80Rom1 = NULL; +UINT8 *GalZ80Rom1Op = NULL; +UINT8 *GalZ80Rom2 = NULL; +UINT8 *GalZ80Rom3 = NULL; +UINT8 *GalS2650Rom1 = NULL; +UINT8 *GalZ80Ram1 = NULL; +UINT8 *GalZ80Ram2 = NULL; +UINT8 *GalVideoRam = NULL; +UINT8 *GalVideoRam2 = NULL; +UINT8 *GalSpriteRam = NULL; +UINT8 *GalScrollVals = NULL; +UINT8 *GalProm = NULL; +UINT8 *GalChars = NULL; +UINT8 *GalSprites = NULL; +UINT8 *GalTempRom = NULL; +UINT32 *GalPalette = NULL; + +UINT32 GalZ80Rom1Size = 0; +UINT32 GalZ80Rom1Num = 0; +UINT32 GalZ80Rom2Size = 0; +UINT32 GalZ80Rom2Num = 0; +UINT32 GalZ80Rom3Size = 0; +UINT32 GalZ80Rom3Num = 0; +UINT32 GalS2650Rom1Size = 0; +UINT32 GalS2650Rom1Num = 0; +UINT32 GalTilesSharedRomSize = 0; +UINT32 GalTilesSharedRomNum = 0; +UINT32 GalTilesCharRomSize = 0; +UINT32 GalTilesCharRomNum = 0; +UINT32 GalNumChars = 0; +UINT32 GalTilesSpriteRomSize = 0; +UINT32 GalTilesSpriteRomNum = 0; +UINT32 GalNumSprites = 0; +UINT32 GalPromRomSize = 0; +UINT32 GalPromRomNum = 0; + +GalPostLoadCallback GalPostLoadCallbackFunction; + +// CPU Control +UINT8 GalIrqType; +UINT8 GalIrqFire; +INT32 nGalCyclesDone[3], nGalCyclesTotal[3]; +static INT32 nGalCyclesSegment; + +// Misc variables +UINT8 ZigzagAYLatch; +UINT8 GalSoundLatch; +UINT8 GalSoundLatch2; +UINT8 KingballSound; +UINT8 KingballSpeechDip; +UINT8 KonamiSoundControl; +UINT8 SfxSampleControl; +UINT16 ScrambleProtectionState; +UINT8 ScrambleProtectionResult; +UINT8 MoonwarPortSelect; +UINT8 MshuttleAY8910CS; +UINT8 GmgalaxSelectedGame; +UINT8 Fourin1Bank; +UINT8 GameIsGmgalax; +UINT8 CavelonBankSwitch; +UINT8 GalVBlank; + +static inline void GalMakeInputs() +{ + // Reset Inputs + GalInput[0] = GalInput[1] = GalInput[2] = GalInput[3] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + GalInput[0] |= (GalInputPort0[i] & 1) << i; + GalInput[1] |= (GalInputPort1[i] & 1) << i; + GalInput[2] |= (GalInputPort2[i] & 1) << i; + GalInput[3] |= (GalInputPort3[i] & 1) << i; + } +} + +static INT32 GalMemIndex() +{ + UINT8 *Next; Next = GalMem; + + GalZ80Rom1 = Next; Next += GalZ80Rom1Size; + GalZ80Rom2 = Next; Next += GalZ80Rom2Size; + GalZ80Rom3 = Next; Next += GalZ80Rom3Size; + GalS2650Rom1 = Next; Next += GalS2650Rom1Size; + GalProm = Next; Next += GalPromRomSize; + + GalRamStart = Next; + + GalZ80Ram1 = Next; Next += 0x01000; + GalVideoRam = Next; Next += 0x00400; + GalSpriteRam = Next; Next += 0x00100; + GalScrollVals = Next; Next += 0x00020; + GalGfxBank = Next; Next += 0x0001f; + + if (GalZ80Rom2Size) { + GalZ80Ram2 = Next; Next += 0x00400; + } + + GalRamEnd = Next; + + GalChars = Next; Next += GalNumChars * 8 * 8; + GalSprites = Next; Next += GalNumSprites * 16 * 16; + GalPalette = (UINT32*)Next; Next += (GAL_PALETTE_NUM_COLOURS_PROM + GAL_PALETTE_NUM_COLOURS_STARS + GAL_PALETTE_NUM_COLOURS_BULLETS + GAL_PALETTE_NUM_COLOURS_BACKGROUND) * sizeof(UINT32); + + GalMemEnd = Next; + + return 0; +} + +static INT32 GalDoReset() +{ + if (GalS2650Rom1Size) { + s2650Open(0); + s2650Reset(); + s2650Close(); + } + + if (GalZ80Rom1Size) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + if (GalZ80Rom2Size) { + ZetOpen(1); + ZetReset(); + ZetClose(); + } + + if (GalZ80Rom3Size) { + ZetOpen(2); + ZetReset(); + ZetClose(); + } + + GalSoundReset(); + HiscoreReset(); + + GalIrqFire = 0; + GalFlipScreenX = 0; + GalFlipScreenY = 0; + ZigzagAYLatch = 0; + GalSoundLatch = 0; + GalSoundLatch2 = 0; + KingballSpeechDip = 0; + KingballSound = 0; + GalStarsEnable = 0; + GalStarsScrollPos = 0; + GalBackgroundRed = 0; + GalBackgroundGreen = 0; + GalBackgroundBlue = 0; + GalBackgroundEnable = 0; + ScrambleProtectionState = 0; + ScrambleProtectionResult = 0; + MoonwarPortSelect = 0; + MshuttleAY8910CS = 0; + Fourin1Bank = 0; + CavelonBankSwitch = 0; + GalVBlank = 0; + + return 0; +} + +static INT32 GalLoadRoms(bool bLoad) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + INT32 nOffset = -1; + UINT32 i; + INT32 nRet = 0; + + if (!bLoad) { + do { + ri.nLen = 0; + ri.nType = 0; + BurnDrvGetRomInfo(&ri, ++nOffset); + if ((ri.nType & 0xff) == GAL_ROM_Z80_PROG1) { + GalZ80Rom1Size += ri.nLen; + GalZ80Rom1Num++; + } + if ((ri.nType & 0xff) == GAL_ROM_Z80_PROG2) { + GalZ80Rom2Size += ri.nLen; + GalZ80Rom2Num++; + } + if ((ri.nType & 0xff) == GAL_ROM_Z80_PROG3) { + GalZ80Rom3Size += ri.nLen; + GalZ80Rom3Num++; + } + if ((ri.nType & 0xff) == GAL_ROM_TILES_SHARED) { + GalTilesSharedRomSize += ri.nLen; + GalTilesSharedRomNum++; + } + if ((ri.nType & 0xff) == GAL_ROM_TILES_CHARS) { + GalTilesCharRomSize += ri.nLen; + GalTilesCharRomNum++; + } + if ((ri.nType & 0xff) == GAL_ROM_TILES_SPRITES) { + GalTilesSpriteRomSize += ri.nLen; + GalTilesSpriteRomNum++; + } + if ((ri.nType & 0xff) == GAL_ROM_PROM) { + GalPromRomSize += ri.nLen; + GalPromRomNum++; + } + if ((ri.nType & 0xff) == GAL_ROM_S2650_PROG1) { + GalS2650Rom1Size += ri.nLen; + GalS2650Rom1Num++; + } + } while (ri.nLen); + + if (GalTilesSharedRomSize) { + GalNumChars = GalTilesSharedRomSize / 16; + GalNumSprites = GalTilesSharedRomSize / 64; + CharPlaneOffsets[1] = GalTilesSharedRomSize * 4; + SpritePlaneOffsets[1] = GalTilesSharedRomSize * 4; + } + + if (GalTilesCharRomSize) { + GalNumChars = GalTilesCharRomSize / 16; + CharPlaneOffsets[1] = GalTilesCharRomSize * 4; + } + + if (GalTilesSpriteRomSize) { + GalNumSprites = GalTilesSpriteRomSize / 64; + SpritePlaneOffsets[1] = GalTilesSpriteRomSize * 4; + } + +#if 1 && defined FBA_DEBUG + if (GalZ80Rom1Size) bprintf(PRINT_NORMAL, _T("Z80 #1 Rom Size: 0x%X (%i roms)\n"), GalZ80Rom1Size, GalZ80Rom1Num); + if (GalZ80Rom2Size) bprintf(PRINT_NORMAL, _T("Z80 #2 Rom Size: 0x%X (%i roms)\n"), GalZ80Rom2Size, GalZ80Rom2Num); + if (GalZ80Rom3Size) bprintf(PRINT_NORMAL, _T("Z80 #3 Rom Size: 0x%X (%i roms)\n"), GalZ80Rom3Size, GalZ80Rom3Num); + if (GalS2650Rom1Size) bprintf(PRINT_NORMAL, _T("S2650 #1 Rom Size: 0x%X (%i roms)\n"), GalS2650Rom1Size, GalS2650Rom1Num); + if (GalTilesSharedRomSize) bprintf(PRINT_NORMAL, _T("Shared Tile Rom Size: 0x%X (%i roms, 0x%X Chars, 0x%X Sprites)\n"), GalTilesSharedRomSize, GalTilesSharedRomNum, GalNumChars, GalNumSprites); + if (GalTilesCharRomSize) bprintf(PRINT_NORMAL, _T("Char Rom Size: 0x%X (%i roms, 0x%X Chars)\n"), GalTilesCharRomSize, GalTilesCharRomNum, GalNumChars); + if (GalTilesSpriteRomSize) bprintf(PRINT_NORMAL, _T("Sprite Rom Size: 0x%X (%i roms, 0x%X Sprites)\n"), GalTilesSpriteRomSize, GalTilesSpriteRomNum, GalNumSprites); + if (GalPromRomSize) bprintf(PRINT_NORMAL, _T("PROM Rom Size: 0x%X (%i roms)\n"), GalPromRomSize, GalPromRomNum); +#endif + } + + if (bLoad) { + INT32 Offset; + + // Z80 #1 Program Roms + Offset = 0; + for (i = 0; i < GalZ80Rom1Num; i++) { + nRet = BurnLoadRom(GalZ80Rom1 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + + // Z80 #2 Program Roms + if (GalZ80Rom2Size) { + Offset = 0; + for (i = GAL_ROM_OFFSET_Z80_PROG2; i < GAL_ROM_OFFSET_Z80_PROG2 + GalZ80Rom2Num; i++) { + nRet = BurnLoadRom(GalZ80Rom2 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // Z80 #3 Program Roms + if (GalZ80Rom3Size) { + Offset = 0; + for (i = GAL_ROM_OFFSET_Z80_PROG3; i < GAL_ROM_OFFSET_Z80_PROG3 + GalZ80Rom3Num; i++) { + nRet = BurnLoadRom(GalZ80Rom3 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // Shared Tile Roms + if (GalTilesSharedRomSize) { + Offset = 0; + GalTempRom = (UINT8*)malloc(GalTilesSharedRomSize); + for (i = GAL_ROM_OFFSET_TILES_SHARED; i < GAL_ROM_OFFSET_TILES_SHARED + GalTilesSharedRomNum; i++) { + nRet = BurnLoadRom(GalTempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + } + + // Char Tile Roms + if (GalTilesCharRomSize) { + Offset = 0; + GalTempRom = (UINT8*)malloc(GalTilesCharRomSize); + for (i = GAL_ROM_OFFSET_TILES_CHARS; i < GAL_ROM_OFFSET_TILES_CHARS + GalTilesCharRomNum; i++) { + nRet = BurnLoadRom(GalTempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + GfxDecode(GalNumChars, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, GalTempRom, GalChars); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + } + + // Sprite Tile Roms + if (GalTilesSpriteRomSize) { + Offset = 0; + GalTempRom = (UINT8*)malloc(GalTilesSpriteRomSize); + for (i = GAL_ROM_OFFSET_TILES_SPRITES; i < GAL_ROM_OFFSET_TILES_SPRITES + GalTilesSpriteRomNum; i++) { + nRet = BurnLoadRom(GalTempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + GfxDecode(GalNumSprites, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, GalTempRom, GalSprites); + if (GalTempRom) { + free(GalTempRom); + GalTempRom = NULL; + } + } + + // Prom + if (GalPromRomSize) { + Offset = 0; + for (i = GAL_ROM_OFFSET_PROM; i < GAL_ROM_OFFSET_PROM + GalPromRomNum; i++) { + nRet = BurnLoadRom(GalProm + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // S2650 #1 Program Roms + if (GalS2650Rom1Size) { + Offset = 0; + for (i = GAL_ROM_OFFSET_S2650_PROG1; i < GAL_ROM_OFFSET_S2650_PROG1 + GalS2650Rom1Num; i++) { + nRet = BurnLoadRom(GalS2650Rom1 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + } + + return nRet; +} + +// Konami PPI Handlers +UINT8 KonamiPPIReadIN0() +{ + return 0xff - GalInput[0] - GalDip[0]; +} + +UINT8 KonamiPPIReadIN1() +{ + return 0xff - GalInput[1] - GalDip[1]; +} + +UINT8 KonamiPPIReadIN2() +{ + return 0xff - GalInput[2] - GalDip[2]; +} + +UINT8 KonamiPPIReadIN3() +{ + return 0xff - GalInput[3] - GalDip[3]; +} + +void KonamiPPIInit() +{ + ppi8255_init(2); + PPI0PortReadA = KonamiPPIReadIN0; + PPI0PortReadB = KonamiPPIReadIN1; + PPI0PortReadC = KonamiPPIReadIN2; + PPI1PortReadC = KonamiPPIReadIN3; + PPI1PortWriteA = KonamiSoundLatchWrite; + PPI1PortWriteB = KonamiSoundControlWrite; +} + +// Galaxian Memory Map +UINT8 __fastcall GalaxianZ80Read(UINT16 a) +{ + switch (a) { + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: { + return GalInput[2] | GalDip[2]; + } + + case 0x7800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall GalaxianZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5800 && a <= 0x58ff) { + int Offset = a - 0x5800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x6000: + case 0x6001: { + // start_lamp_w + return; + } + + case 0x6002: { + // coin_lock_w + return; + } + + case 0x6003: { + // coin_count_0_w + return; + } + + case 0x6004: + case 0x6005: + case 0x6006: + case 0x6007: { + GalaxianLfoFreqWrite(a - 0x6004, d); + return; + } + + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + GalaxianSoundWrite(a - 0x6800, d); + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall GalaxianZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall GalaxianZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +INT32 GalInit() +{ + INT32 nLen; + + GalLoadRoms(0); + + if (!GalSoundType) GalSoundType = GAL_SOUND_HARDWARE_TYPE_GALAXIAN; + + // Allocate and Blank all required memory + GalMem = NULL; + GalMemIndex(); + nLen = GalMemEnd - (UINT8 *)0; + if ((GalMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(GalMem, 0, nLen); + GalMemIndex(); + + if (GalLoadRoms(1)) return 1; + + // Setup the Z80 emulation + if (GalSoundType != GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + if (GalZ80Rom3Size) { + ZetInit(3); + } else { + if (GalZ80Rom2Size) { + ZetInit(2); + } else { + if (GalZ80Rom1Size) { + ZetInit(1); + } + } + } + if (GalZ80Rom1Size) { + ZetOpen(0); + ZetSetReadHandler(GalaxianZ80Read); + ZetSetWriteHandler(GalaxianZ80Write); + ZetSetInHandler(GalaxianZ80PortRead); + ZetSetOutHandler(GalaxianZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x43ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x43ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x43ff, 2, GalZ80Ram1); + ZetMapArea(0x4400, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4400, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4400, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x5000, 0x53ff, 0, GalVideoRam); + ZetMapArea(0x5000, 0x53ff, 1, GalVideoRam); + ZetMapArea(0x5000, 0x53ff, 2, GalVideoRam); + ZetMapArea(0x5800, 0x58ff, 0, GalSpriteRam); + ZetMapArea(0x5800, 0x58ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); + } + } + + nGalCyclesTotal[0] = (18432000 / 3 / 2) / 60; + + if (GalPostLoadCallbackFunction) GalPostLoadCallbackFunction(); + + GalCalcPaletteFunction = GalaxianCalcPalette; + GalRenderBackgroundFunction = GalaxianDrawBackground; + GalDrawBulletsFunction = GalaxianDrawBullets; + + GalIrqType = GAL_IRQ_TYPE_NMI; + + GalSpriteClipStart = 16; + GalSpriteClipEnd = 255; + + GalSoundInit(); + + GalInitStars(); + + GenericTilesInit(); + + GalColourDepth = 2; + + // Reset the driver + GalDoReset(); + + return 0; +} + +// Moon Cresta Memory Map +UINT8 __fastcall MooncrstZ80Read(UINT16 a) +{ + switch (a) { + case 0xa000: { + return GalInput[0] | GalDip[0]; + } + + case 0xa800: { + return GalInput[1] | GalDip[1]; + } + + case 0xb000: { + return GalInput[2] | GalDip[2]; + } + + case 0xb800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall MooncrstZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + int Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: { + GalGfxBank[a - 0xa000] = d; + return; + } + + case 0xa003: { + // coin_count_0_w + return; + } + + case 0xa004: + case 0xa005: + case 0xa006: + case 0xa007: { + GalaxianLfoFreqWrite(a - 0xa004, d); + return; + } + + case 0xa800: + case 0xa801: + case 0xa802: + case 0xa803: + case 0xa804: + case 0xa805: + case 0xa806: + case 0xa807: { + GalaxianSoundWrite(a - 0xa800, d); + return; + } + + case 0xb000: { + GalIrqFire = d & 1; + return; + } + + case 0xb004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xb006: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb007: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb800: { + GalPitch = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MooncrstZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall MooncrstZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapMooncrst() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(MooncrstZ80Read); + ZetSetWriteHandler(MooncrstZ80Write); + ZetSetInHandler(MooncrstZ80PortRead); + ZetSetOutHandler(MooncrstZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size >= 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram1); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +// Jumpbug Memory Map +UINT8 __fastcall JumpbugZ80Read(UINT16 a) +{ + if (a >= 0xb000 && a <= 0xbfff) { + INT32 Offset = a - 0xb000; + + switch (Offset) { + case 0x114: return 0x4f; + case 0x118: return 0xd3; + case 0x214: return 0xcf; + case 0x235: return 0x02; + case 0x311: return 0xff; + } + } + + switch (a) { + case 0x6000: { + return GalInput[0] | GalDip[0]; + } + + case 0x6800: { + return GalInput[1] | GalDip[1]; + } + + case 0x7000: { + return GalInput[2] | GalDip[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall JumpbugZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x5800: { + AY8910Write(0, 1, d); + return; + } + + case 0x5900: { + AY8910Write(0, 0, d); + return; + } + + case 0x6002: + case 0x6003: + case 0x6004: + case 0x6005: + case 0x6006: { + GalGfxBank[a - 0x6002] = d; + return; + } + + case 0x7001: { + GalIrqFire = d & 1; + return; + } + + case 0x7002: { + // coin_count_0_w + return; + } + + case 0x7004: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x7006: { + GalFlipScreenX = d & 1; + return; + } + + case 0x7007: { + GalFlipScreenY = d & 1; + return; + } + + case 0x7800: { + // watchdog write + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall JumpbugZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall JumpbugZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapJumpbug() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(JumpbugZ80Read); + ZetSetWriteHandler(JumpbugZ80Write); + ZetSetInHandler(JumpbugZ80PortRead); + ZetSetOutHandler(JumpbugZ80PortWrite); + ZetMapArea(0x0000, 0x3fff, 0, GalZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 0, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 1, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetMapArea(0x8000, GalZ80Rom1Size + 0x4000 - 1, 0, GalZ80Rom1 + 0x4000); + ZetMapArea(0x8000, GalZ80Rom1Size + 0x4000 - 1, 2, GalZ80Rom1 + 0x4000); + ZetMemEnd(); + ZetClose(); +} + +// Frogger Memory Map +UINT8 __fastcall FroggerZ80Read(UINT16 a) +{ + if (a >= 0xc000) { + UINT32 Offset = a - 0xc000; + UINT8 Result = 0xff; + if (Offset & 0x1000) Result &= ppi8255_r(1, (Offset >> 1) & 3); + if (Offset & 0x2000) Result &= ppi8255_r(0, (Offset >> 1) & 3); + return Result; + } + + switch (a) { + case 0x8800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall FroggerZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xb000 && a <= 0xb0ff) { + INT32 Offset = a - 0xb000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + d = (d >> 4) | (d << 4); + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xc000) { + INT32 Offset = a - 0xc000; + if (Offset & 0x1000) ppi8255_w(1, (Offset >> 1) & 3, d); + if (Offset & 0x2000) ppi8255_w(0, (Offset >> 1) & 3, d); + return; + } + + switch (a) { + case 0xb808: { + GalIrqFire = d & 1; + return; + } + + case 0xb80c: { + GalFlipScreenY = d & 1; + return; + } + + case 0xb810: { + GalFlipScreenX = d & 1; + return; + } + + case 0xb818: { + // coin_count_0_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall FroggerZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall FroggerZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapFrogger() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(FroggerZ80Read); + ZetSetWriteHandler(FroggerZ80Write); + ZetSetInHandler(FroggerZ80PortRead); + ZetSetOutHandler(FroggerZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0xa800, 0xabff, 0, GalVideoRam); + ZetMapArea(0xa800, 0xabff, 1, GalVideoRam); + ZetMapArea(0xa800, 0xabff, 2, GalVideoRam); + ZetMapArea(0xb000, 0xb0ff, 0, GalSpriteRam); + ZetMapArea(0xb000, 0xb0ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +// The End Memory Map +UINT8 __fastcall TheendZ80Read(UINT16 a) +{ + if (a >= 0x8000) { + UINT32 Offset = a - 0x8000; + UINT8 Result = 0xff; + if (Offset & 0x0100) Result &= ppi8255_r(0, Offset & 3); + if (Offset & 0x0200) Result &= ppi8255_r(1, Offset & 3); + return Result; + } + + switch (a) { + case 0x7000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall TheendZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x5000 && a <= 0x50ff) { + INT32 Offset = a - 0x5000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0x8000) { + INT32 Offset = a - 0x8000; + if (Offset & 0x0100) ppi8255_w(0, Offset & 3, d); + if (Offset & 0x0200) ppi8255_w(1, Offset & 3, d); + return; + } + + switch (a) { + case 0x6801: { + GalIrqFire = d & 1; + return; + } + + case 0x6802: { + // coin_count_0_w + return; + } + + case 0x6803: { + GalBackgroundEnable = d & 1; + return; + } + + case 0x6804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0x6806: { + GalFlipScreenX = d & 1; + return; + } + + case 0x6807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall TheendZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall TheendZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapTheend() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(TheendZ80Read); + ZetSetWriteHandler(TheendZ80Write); + ZetSetInHandler(TheendZ80PortRead); + ZetSetOutHandler(TheendZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x4000) ? 0x3fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x4000, 0x47ff, 0, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 1, GalZ80Ram1); + ZetMapArea(0x4000, 0x47ff, 2, GalZ80Ram1); + ZetMapArea(0x4800, 0x4bff, 0, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 1, GalVideoRam); + ZetMapArea(0x4800, 0x4bff, 2, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 0, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 1, GalVideoRam); + ZetMapArea(0x4c00, 0x4fff, 2, GalVideoRam); + ZetMapArea(0x5000, 0x50ff, 0, GalSpriteRam); + ZetMapArea(0x5000, 0x50ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +// Turtles Memory Map +UINT8 __fastcall TurtlesZ80Read(UINT16 a) +{ + if (a >= 0xb000 && a <= 0xb03f) { + UINT32 Offset = a - 0xb000; + return ppi8255_r(0, (Offset >> 4) & 3); + } + + if (a >= 0xb800 && a <= 0xb83f) { + UINT32 Offset = a - 0xb800; + return ppi8255_r(1, (Offset >> 4) & 3); + } + + switch (a) { + case 0xa800: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall TurtlesZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9800 && a <= 0x98ff) { + INT32 Offset = a - 0x9800; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + if (a >= 0xb000 && a <= 0xb03f) { + UINT32 Offset = a - 0xb000; + ppi8255_w(0, (Offset >> 4) & 3, d); + return; + } + + if (a >= 0xb800 && a <= 0xb83f) { + UINT32 Offset = a - 0xb800; + ppi8255_w(1, (Offset >> 4) & 3, d); + return; + } + + switch (a) { + case 0xa000: { + GalBackgroundRed = d & 1; + return; + } + + case 0xa008: { + GalIrqFire = d & 1; + return; + } + + case 0xa010: { + GalFlipScreenY = d & 1; + return; + } + + case 0xa018: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa020: { + GalBackgroundGreen = d & 1; + return; + } + + case 0xa028: { + GalBackgroundBlue = d & 1; + return; + } + + case 0xa030: { + // coin_count_0_w + return; + } + + case 0xa038: { + // coin_count_1_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall TurtlesZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall TurtlesZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapTurtles() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(TurtlesZ80Read); + ZetSetWriteHandler(TurtlesZ80Write); + ZetSetInHandler(TurtlesZ80PortRead); + ZetSetOutHandler(TurtlesZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0x9000, 0x93ff, 0, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 1, GalVideoRam); + ZetMapArea(0x9000, 0x93ff, 2, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 0, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 1, GalVideoRam); + ZetMapArea(0x9400, 0x97ff, 2, GalVideoRam); + ZetMapArea(0x9800, 0x98ff, 0, GalSpriteRam); + ZetMapArea(0x9800, 0x98ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +// Super Cobra Memory Map +UINT8 __fastcall ScobraZ80Read(UINT16 a) +{ + switch (a) { + case 0x9800: + case 0x9801: + case 0x9802: + case 0x9803: { + return ppi8255_r(0, a - 0x9800); + } + + case 0xa000: + case 0xa001: + case 0xa002: + case 0xa003: { + return ppi8255_r(1, a - 0xa000); + } + + case 0xb000: { + // watchdog read + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall ScobraZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x90ff) { + INT32 Offset = a - 0x9000; + + GalSpriteRam[Offset] = d; + + if (Offset < 0x40) { + if ((Offset & 0x01) == 0) { + GalScrollVals[Offset >> 1] = d; + } + } + + return; + } + + switch (a) { + case 0x9800: + case 0x9801: + case 0x9802: + case 0x9803: { + return ppi8255_w(0, a - 0x9800, d); + } + + case 0xa000: + case 0xa001: + case 0xa002: + case 0xa003: { + return ppi8255_w(1, a - 0xa000, d); + } + + case 0xa801: { + GalIrqFire = d & 1; + return; + } + + case 0xa802: { + // coin_count_0_w + return; + } + + case 0xa803: { + GalBackgroundEnable = d & 1; + return; + } + + case 0xa804: { + GalStarsEnable = d & 0x01; + if (!GalStarsEnable) GalStarsScrollPos = -1; + return; + } + + case 0xa806: { + GalFlipScreenX = d & 1; + return; + } + + case 0xa807: { + GalFlipScreenY = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall ScobraZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0xff; +} + +void __fastcall ScobraZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void MapScobra() +{ + ZetOpen(0); + ZetMemCallback(0x0000, 0xffff, 0); + ZetMemCallback(0x0000, 0xffff, 1); + ZetMemCallback(0x0000, 0xffff, 2); + ZetSetReadHandler(ScobraZ80Read); + ZetSetWriteHandler(ScobraZ80Write); + ZetSetInHandler(ScobraZ80PortRead); + ZetSetOutHandler(ScobraZ80PortWrite); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, (GalZ80Rom1Size > 0x8000) ? 0x7fff : GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 1, GalZ80Ram1); + ZetMapArea(0x8000, 0x87ff, 2, GalZ80Ram1); + ZetMapArea(0x8800, 0x8bff, 0, GalVideoRam); + ZetMapArea(0x8800, 0x8bff, 1, GalVideoRam); + ZetMapArea(0x8800, 0x8bff, 2, GalVideoRam); + ZetMapArea(0x8c00, 0x8fff, 0, GalVideoRam); + ZetMapArea(0x8c00, 0x8fff, 1, GalVideoRam); + ZetMapArea(0x8c00, 0x8fff, 2, GalVideoRam); + ZetMapArea(0x9000, 0x90ff, 0, GalSpriteRam); + ZetMapArea(0x9000, 0x90ff, 2, GalSpriteRam); + ZetMemEnd(); + ZetClose(); +} + +INT32 GalExit() +{ + ZetExit(); + + GenericTilesExit(); + + if (GalMem) { + free(GalMem); + GalMem = NULL; + } + + if (GalZ80Rom1Op) { + free(GalZ80Rom1Op); + GalZ80Rom1Op = NULL; + } + + if (GalVideoRam2) { + free(GalVideoRam2); + GalVideoRam2 = NULL; + } + + if (RockclimTiles) { + free(RockclimTiles); + RockclimTiles = NULL; + } + + GalSoundExit(); + + GalIrqFire = 0; + GalIrqType = 0; + GalSoundType = 0; + GalSoundVolumeShift = 0; + GalFlipScreenX = 0; + GalFlipScreenY = 0; + ZigzagAYLatch = 0; + GalSoundLatch = 0; + GalSoundLatch2 = 0; + KingballSpeechDip = 0; + KingballSound = 0; + KonamiSoundControl = 0; + SfxSampleControl = 0; + GmgalaxSelectedGame = 0; + GalPaletteBank = 0; + GalSpriteClipStart = 0; + GalSpriteClipEnd = 0; + FroggerAdjust = 0; + GalBackgroundRed = 0; + GalBackgroundGreen = 0; + GalBackgroundBlue = 0; + GalBackgroundEnable = 0; + ScrambleProtectionState = 0; + ScrambleProtectionResult = 0; + + GalZ80Rom1Size = 0; + GalZ80Rom1Num = 0; + GalZ80Rom2Size = 0; + GalZ80Rom2Num = 0; + GalZ80Rom3Size = 0; + GalZ80Rom3Num = 0; + GalS2650Rom1Size = 0; + GalS2650Rom1Num = 0; + GalTilesSharedRomSize = 0; + GalTilesSharedRomNum = 0; + GalTilesCharRomSize = 0; + GalTilesCharRomNum = 0; + GalNumChars = 0; + GalTilesSpriteRomSize = 0; + GalTilesSpriteRomNum = 0; + GalNumSprites = 0; + GalPromRomSize = 0; + GalPromRomNum = 0; + + GalPostLoadCallbackFunction = NULL; + GalRenderBackgroundFunction = NULL; + GalCalcPaletteFunction = NULL; + GalDrawBulletsFunction = NULL; + GalExtendTileInfoFunction = NULL; + GalExtendSpriteInfoFunction = NULL; + GalRenderFrameFunction = NULL; + + SfxTilemap = 0; + GalOrientationFlipX = 0; + MoonwarPortSelect = 0; + MshuttleAY8910CS = 0; + Fourin1Bank = 0; + GameIsGmgalax = 0; + CavelonBankSwitch = 0; + DarkplntBulletColour = 0; + DambustrBgColour1 = 0; + DambustrBgColour2 = 0; + DambustrBgPriority = 0; + DambustrBgSplitLine = 0; + RockclimScrollX = 0; + RockclimScrollY = 0; + GalVBlank = 0; + + GalColourDepth = 0; + + return 0; +} + +INT32 KonamiExit() +{ + ppi8255_exit(); + + return GalExit(); +} + +INT32 GalFrame() +{ + INT32 nInterleave = 8; + INT32 nSoundBufferPos = 0; + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN) { + nInterleave = nBurnSoundLen; + GalaxianSoundUpdateTimers(); + } + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) nInterleave = nBurnSoundLen / 4; + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910) nInterleave = 32; + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) nInterleave = nBurnSoundLen; + + INT32 nIrqInterleaveFire = nInterleave / 4; + + if (GalReset) GalDoReset(); + + if (GameIsGmgalax && (GmgalaxSelectedGame != GalFakeDip)) { + GmgalaxSelectedGame = GalFakeDip; + INT32 nAddress = 0x0000; + if (GmgalaxSelectedGame == 1) nAddress = 0x4000; + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, GalZ80Rom1 + nAddress); + ZetMapArea(0x0000, 0x3fff, 2 ,GalZ80Rom1 + nAddress); + ZetClose(); + + GalGfxBank[0] = 0; + if (GmgalaxSelectedGame == 1) GalGfxBank[0] = 1; + GalPaletteBank = 0; + if (GmgalaxSelectedGame == 1) GalPaletteBank = 1; + + GalDoReset(); + } + + GalMakeInputs(); + GalVBlank = 0; + + if (GalZ80Rom1Size) ZetNewFrame(); + + nGalCyclesDone[0] = nGalCyclesDone[1] = nGalCyclesDone[2] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + if (GalZ80Rom1Size && GalSoundType != GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesDone[nCurrentCPU] += ZetRun(nGalCyclesSegment); + if (i == nIrqInterleaveFire && GalIrqFire) { + if (GalIrqType == GAL_IRQ_TYPE_NMI) ZetNmi(); + if (GalIrqType == GAL_IRQ_TYPE_IRQ0) ZetRaiseIrq(0); + GalIrqFire = 0; + } + ZetClose(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910) { + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesDone[nCurrentCPU] += ZetRun(nGalCyclesSegment); + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910) ZetRaiseIrq(0); + ZetClose(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910) { + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesSegment = ZetRun(nGalCyclesSegment); + nGalCyclesDone[nCurrentCPU] += nGalCyclesSegment; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nGalCyclesDone[nCurrentCPU] += ZetRun(300); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + nGalCyclesDone[nCurrentCPU] += ZetRun(300); + ZetClose(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + // Run Z80 #3 + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesDone[nCurrentCPU] += ZetRun(nGalCyclesSegment); + ZetClose(); + } + + // Run S2650 #1 + if (GalS2650Rom1Size) { + nCurrentCPU = 0; + s2650Open(nCurrentCPU); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesDone[nCurrentCPU] += s2650Run(nGalCyclesSegment); + if (i == nIrqInterleaveFire) { + GalVBlank = 1; + s2650_set_irq_line(0, 1); + s2650Run(0); + s2650_set_irq_line(0, 0); + s2650Run(0); + } + s2650Close(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nGalCyclesTotal[nCurrentCPU] / nInterleave; + nGalCyclesSegment = nNext - nGalCyclesDone[nCurrentCPU]; + nGalCyclesDone[nCurrentCPU] += ZetRun(nGalCyclesSegment); + if (HunchbksSoundIrqFire) ZetRaiseIrq(0); + ZetClose(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN) { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + GalRenderSoundSamples(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + } + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + } + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[1][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[2][n] >> GalSoundVolumeShift; + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + nSample += pAY8910Buffer[3][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[4][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[5][n] >> GalSoundVolumeShift; + } + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + nSample += pAY8910Buffer[6][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[7][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[8][n] >> GalSoundVolumeShift; + } + + if (nSample < -32768) { + nSample = -32768; + } else { + if (nSample > 32767) { + nSample = 32767; + } + } + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC/* || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC*/) { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + GalRenderSoundSamples(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + SN76496Update(0, pSoundBuf, nSegmentLength); + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) { + SN76496Update(1, pSoundBuf, nSegmentLength); + SN76496Update(2, pSoundBuf, nSegmentLength); + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN) { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + GalRenderSoundSamples(pSoundBuf, nSegmentLength); + } + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + } + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + } + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[1][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[2][n] >> GalSoundVolumeShift; + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + nSample += pAY8910Buffer[3][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[4][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[5][n] >> GalSoundVolumeShift; + } + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + nSample += pAY8910Buffer[6][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[7][n] >> GalSoundVolumeShift; + nSample += pAY8910Buffer[8][n] >> GalSoundVolumeShift; + } + + if (nSample < -32768) { + nSample = -32768; + } else { + if (nSample > 32767) { + nSample = 32767; + } + } + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC/* || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC*/) { + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + GalRenderSoundSamples(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + } + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + SN76496Update(0, pSoundBuf, nSegmentLength); + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) { + SN76496Update(1, pSoundBuf, nSegmentLength); + SN76496Update(2, pSoundBuf, nSegmentLength); + } + } + } + + if (pBurnDraw) GalDraw(); + + return 0; +} + +INT32 GalScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029703; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = GalRamStart; + ba.nLen = GalRamEnd - GalRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + if (GalZ80Rom1Size) ZetScan(nAction); + ppi8255_scan(); + if (GalS2650Rom1Size) s2650Scan(nAction, pnMin); + + GalSoundScan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(GalInput); + SCAN_VAR(GalAnalogPort0); + SCAN_VAR(GalAnalogPort1); + SCAN_VAR(GalIrqFire); + SCAN_VAR(nGalCyclesDone); + SCAN_VAR(nGalCyclesSegment); + SCAN_VAR(ZigzagAYLatch); + SCAN_VAR(GalSoundLatch); + SCAN_VAR(GalSoundLatch2); + SCAN_VAR(KingballSound); + SCAN_VAR(KingballSpeechDip); + SCAN_VAR(KonamiSoundControl); + SCAN_VAR(SfxSampleControl); + SCAN_VAR(ScrambleProtectionResult); + SCAN_VAR(MoonwarPortSelect); + SCAN_VAR(MshuttleAY8910CS); + SCAN_VAR(GmgalaxSelectedGame); + SCAN_VAR(Fourin1Bank); + SCAN_VAR(CavelonBankSwitch); + SCAN_VAR(GalFlipScreenX); + SCAN_VAR(GalFlipScreenY); + SCAN_VAR(GalPaletteBank); + SCAN_VAR(GalBackgroundRed); + SCAN_VAR(GalBackgroundGreen); + SCAN_VAR(GalBackgroundBlue); + SCAN_VAR(GalBackgroundEnable); + SCAN_VAR(DarkplntBulletColour); + SCAN_VAR(DambustrBgColour1); + SCAN_VAR(DambustrBgColour2); + SCAN_VAR(DambustrBgPriority); + SCAN_VAR(DambustrBgSplitLine); + SCAN_VAR(RockclimScrollX); + SCAN_VAR(RockclimScrollY); + SCAN_VAR(GalStarsEnable); + SCAN_VAR(GalStarsScrollPos); + SCAN_VAR(GalStarsBlinkState); + SCAN_VAR(GalVBlank); + } + + return 0; +} diff --git a/src/burn/drivers/galaxian/gal_sound.cpp b/src/burn/drivers/galaxian/gal_sound.cpp new file mode 100644 index 00000000..0d9452b3 --- /dev/null +++ b/src/burn/drivers/galaxian/gal_sound.cpp @@ -0,0 +1,943 @@ +#include "gal.h" + +INT16* pFMBuffer; +INT16* pAY8910Buffer[9]; + +UINT8 GalSoundType; +UINT8 GalSoundVolumeShift; +UINT8 HunchbksSoundIrqFire; + +#define XTAL 18432000 +#define RNG_RATE (XTAL / 3) +#define NOISE_RATE (XTAL / 3 / 192 / 2 / 2) +#define NOISE_LENGTH (NOISE_RATE * 4) +#define NOISE_AMPLITUDE (70 * 256) +#define SHOOT_VOLUME 0.50f +#define SHOOT_SEC 2 +#define R41__ 100000 +#define R44__ 10000 +#define R45__ 22000 +#define R46__ 10000 +#define R47__ 2200 +#define R48__ 2200 +#define C25__ 0.000001 +#define C27__ 0.00000001 +#define C28__ 0.000047 +#define C29__ 0.00000001 +#define IC8L3_L 0.2 +#define IC8L3_H 4.5 +#define NOISE_L 0.2 +#define NOISE_H 4.5 +#define SHOOT_KEYON_TIME 0.1 +#define NE555_FM_ADJUST_RATE 0.80 +#define TOOTHSAW_LENGTH 16 +#define TOOTHSAW_VOLUME 0.36f +#define TOOTHSAW_AMPLITUDE (64*256) +#define V(r0,r1) 2 * TOOTHSAW_AMPLITUDE * (r0) / (r0 + r1) - TOOTHSAW_AMPLITUDE +#define STEPS 16 +#define LFO_VOLUME 0.06f +#define MINFREQ (139 - 139 / 3) +#define MAXFREQ (139 + 139 / 3) + +static INT16 *GalNoiseWave; +static INT16 *GalShootWave; +static UINT32 GalShootLength; +static UINT32 GalShootRate; +UINT8 GalLastPort2 = 0; +UINT8 GalShootEnable; +UINT8 GalNoiseEnable; +INT32 GalNoiseVolume; +double GalShootWavePos; +double GalNoiseWavePos; +double GalLfoWavePos[3]; +INT32 GalPitch; +INT32 GalVol; +static double GalCounter; +static INT32 GalCountDown; +INT32 GalLfoVolume[3]; +double GalLfoFreq; +double GalLfoFreqFrameVar; +INT32 GalLfoBit[4]; + +static INT16 GalToneWave[4][TOOTHSAW_LENGTH]; + +static const INT16 GalBackgroundWave[32] = +{ + 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + -0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000, + -0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000, +}; + +void GalSoundReset() +{ + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) { + AY8910Reset(0); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Reset(0); + AY8910Reset(1); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + AY8910Reset(0); + AY8910Reset(1); + AY8910Reset(2); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + DACReset(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) { + GalLastPort2 = 0; + GalShootEnable = 0; + GalNoiseEnable = 0; + GalNoiseVolume = 0; + GalShootWavePos = 0; + GalNoiseWavePos = 0; + GalLfoWavePos[0] = GalLfoWavePos[1] = GalLfoWavePos[2] = 0; + GalPitch = 0xff; + GalVol = 0; + GalCounter = 0; + GalCountDown = 0; + GalLfoVolume[0] = GalLfoVolume[1] = GalLfoVolume[2] = 0; + GalLfoFreq = MAXFREQ; + GalLfoFreqFrameVar = 0; + GalLfoBit[0] = GalLfoBit[1] = GalLfoBit[2] = GalLfoBit[3] = 0; + } +} + +void GalSoundInit() +{ + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) { + pFMBuffer = (INT16*)malloc(nBurnSoundLen * 3 * sizeof(INT16)); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + pFMBuffer = (INT16*)malloc(nBurnSoundLen * 6 * sizeof(INT16)); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + pFMBuffer = (INT16*)malloc(nBurnSoundLen * 9 * sizeof(INT16)); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + pAY8910Buffer[6] = pFMBuffer + nBurnSoundLen * 6; + pAY8910Buffer[7] = pFMBuffer + nBurnSoundLen * 7; + pAY8910Buffer[8] = pFMBuffer + nBurnSoundLen * 8; + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910) { + AY8910Init(0, 1789750, nBurnSoundRate, NULL, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) { + AY8910Init(0, 1789750, nBurnSoundRate, &BongoDipSwitchRead, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910) { + AY8910Init(0, 1620000, nBurnSoundRate, &CheckmajPortARead, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910) { + // Port A Write - cclimber_sample_select_w + AY8910Init(0, 18432000 / 3 / 4, nBurnSoundRate, NULL, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &FroggerSoundTimerRead, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundTimerRead, NULL, NULL, NULL); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL); + AY8910Init(2, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundTimerRead, NULL, NULL, NULL); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, NULL, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, &SfxSoundLatch2Write, &SfxSampleControlWrite); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + DACInit(0, 0, 1); + DACSetVolShift(0, 2); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) { + SN76496Init(0, 18432000 / 3 / 2, 0); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) { + SN76496Init(0, 18432000 / 3 / 2, 0); + SN76496Init(1, 18432000 / 3 / 2, 1); + SN76496Init(2, 18432000 / 3 / 2, 1); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &HunchbksSoundTimerRead, NULL, NULL); + } + + GalSoundVolumeShift = 1; + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) { + GalShootEnable = 0; + GalShootWavePos = 0; + INT32 CountDown, Generator, Bit1, Bit2; + + GalNoiseWave = (INT16*)malloc(NOISE_LENGTH * sizeof(INT16)); + + GalShootRate = 22050; + GalShootLength = SHOOT_SEC * GalShootRate; + GalShootWave = (INT16*)malloc(GalShootLength * sizeof(INT16)); + + Generator = 0; + CountDown = NOISE_RATE / 2; + for (INT32 i = 0; i < NOISE_LENGTH; i++) { + CountDown -= RNG_RATE; + while (CountDown < 0) { + Generator <<= 1; + Bit1 = (~Generator >> 17) & 1; + Bit2 = (Generator >> 5) & 1; + if (Bit1 ^ Bit2) Generator |= 1; + CountDown += NOISE_RATE; + } + GalNoiseWave[i] = ((Generator >> 17) & 1) ? NOISE_AMPLITUDE : -NOISE_AMPLITUDE; + } + + double v = 5.0; + double vK = (GalShootRate) ? exp(-1 / (R41__ * C25__) / GalShootRate) : 0; + double IC8L3 = IC8L3_L; + INT32 IC8Lcnt = (INT32)(SHOOT_KEYON_TIME * GalShootRate); + double c28v = IC8L3_H - (IC8L3_H - (NOISE_H + NOISE_L) / 2) / (R46__ + R47__ + R48__) * R47__; + double c28K = (GalShootRate) ? exp(-1 / (22000 * 0.000047 ) / GalShootRate) : 0; + double c29v = IC8L3_H - (IC8L3_H - (NOISE_H + NOISE_L) / 2) / (R46__ + R47__ + R48__) * (R47__ + R48__); + double c29K1 = (GalShootRate) ? exp(-1 / (22000 * 0.00000001 ) / GalShootRate) : 0; + double c29K2 = (GalShootRate) ? exp(-1 / (100000 * 0.00000001 ) / GalShootRate) : 0; + double ne555cnt = 0; + double ne555step = (GalShootRate) ? ((1.44 / ((R44__ + R45__ * 2) * C27__)) / GalShootRate) : 0; + double ne555duty = (double)(R44__ + R45__) / (R44__ + R45__ * 2); + double ne555sr; + double ncnt = 0.0; + double nstep = (GalShootRate) ? ((double)NOISE_RATE / GalShootRate) : 0; + double noise_sh2; + + for (UINT32 i = 0; i < GalShootLength; i++) { + noise_sh2 = GalNoiseWave[(INT32)ncnt % NOISE_LENGTH] == NOISE_AMPLITUDE ? NOISE_H : NOISE_L; + ncnt += nstep; + ne555sr = c29v * NE555_FM_ADJUST_RATE / (5.0 * 2 / 3); + ne555cnt += ne555step; + if (ne555cnt >= ne555sr) ne555cnt -= ne555sr; + if (ne555cnt < ne555sr * ne555duty) { + GalShootWave[i] = (INT16)(v / 5 * 0x7fff); + if(IC8L3 == IC8L3_H) v *= vK; + } else { + GalShootWave[i] = 0; + } + c28v += (IC8L3 - c28v) - (IC8L3 - c28v) * c28K; + c28v += (c29v - c28v) - (c29v - c28v) * c28K; + c29v += (c28v - c29v) - (c28v - c29v) * c29K1; + c29v += (noise_sh2 - c29v) - (noise_sh2 - c29v) * c29K2; + if(IC8L3 == IC8L3_L && --IC8Lcnt == 0) IC8L3 = IC8L3_H; + } + + memset(GalToneWave, 0, sizeof(GalToneWave)); + + for (UINT32 i = 0; i < TOOTHSAW_LENGTH; i++ ) { + double r0a = 1.0 / 1e12, r1a = 1.0 / 1e12; + double r0b = 1.0 / 1e12, r1b = 1.0 / 1e12; + + if (i & 1) { + r1a += 1.0 / 33000; + r1b += 1.0 / 33000; + } else { + r0a += 1.0 / 33000; + r0b += 1.0 / 33000; + } + if (i & 4) { + r1a += 1.0 / 22000; + r1b += 1.0 / 22000; + } else { + r0a += 1.0 / 22000; + r0b += 1.0 / 22000; + } + GalToneWave[0][i] = (INT16)(V(1.0 / r0a, 1.0 / r1a)); + + if (i & 4) { + r1a += 1.0 / 10000; + } else { + r0a += 1.0 / 10000; + } + GalToneWave[1][i] = (INT16)(V(1.0 / r0a, 1.0 / r1a)); + + if (i & 8) { + r1b += 1.0 / 15000; + } else { + r0b += 1.0 / 15000; + } + GalToneWave[2][i] = (INT16)(V(1.0 / r0b, 1.0 / r1b)); + + if (i & 4) { + r0b += 1.0 / 10000; + } else { + r1b += 1.0 / 10000; + } + GalToneWave[3][i] = (INT16)(V(1.0 / r0b, 1.0 / r1b)); + } + + GalPitch = 0xff; + GalVol = 0; + + GalLfoFreq = MAXFREQ; + GalLfoFreqFrameVar = 0; + } +} + +void GalSoundExit() +{ + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) { + AY8910Exit(0); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Exit(0); + AY8910Exit(1); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) { + AY8910Exit(0); + AY8910Exit(1); + AY8910Exit(2); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + DACExit(); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) { + SN76496Exit(); + } + + if (pFMBuffer) { + free(pFMBuffer); + pFMBuffer = NULL; + for (INT32 i = 0; i < 9; i++) pAY8910Buffer[i] = NULL; + } + + if (GalNoiseWave) { + free(GalNoiseWave); + GalNoiseWave = NULL; + } + + if (GalShootWave) { + free(GalShootWave); + GalShootWave = NULL; + } + + HunchbksSoundIrqFire = 0; + GalShootLength = 0; + GalShootRate = 0; + GalLastPort2 = 0; + GalShootEnable = 0; + GalNoiseEnable = 0; + GalNoiseVolume = 0; + GalShootWavePos = 0; + GalNoiseWavePos = 0; + GalLfoWavePos[0] = GalLfoWavePos[1] = GalLfoWavePos[2] = 0; + GalPitch = 0; + GalVol = 0; + GalCounter = 0; + GalCountDown = 0; + GalLfoVolume[0] = GalLfoVolume[1] = GalLfoVolume[2] = 0; + GalLfoFreq = 0; + GalLfoFreqFrameVar = 0; + GalLfoBit[0] = GalLfoBit[1] = GalLfoBit[2] = GalLfoBit[3] = 0; + memset(GalToneWave, 0, sizeof(GalToneWave)); +} + +void GalSoundScan(INT32 nAction, INT32 *pnMin) +{ + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) { + SCAN_VAR(GalLastPort2); + SCAN_VAR(GalShootEnable); + SCAN_VAR(GalNoiseEnable); + SCAN_VAR(GalNoiseVolume); + SCAN_VAR(GalShootWavePos); + SCAN_VAR(GalNoiseWavePos); + SCAN_VAR(GalLfoWavePos); + SCAN_VAR(GalPitch); + SCAN_VAR(GalVol); + SCAN_VAR(GalCounter); + SCAN_VAR(GalCountDown); + SCAN_VAR(GalLfoVolume); + SCAN_VAR(GalLfoFreq); + SCAN_VAR(GalLfoFreqFrameVar); + SCAN_VAR(GalLfoBit); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) { + AY8910Scan(nAction, pnMin); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) { + DACScan(nAction, pnMin); + } + + if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) { + SN76496Scan(nAction, pnMin); + } +} + +// AY8910 Port Handlers +UINT8 CheckmajPortARead(UINT32) +{ + return GalSoundLatch; +} + +UINT8 BongoDipSwitchRead(UINT32) +{ + return GalInput[3] | GalDip[3]; +} + +UINT8 KonamiSoundLatchRead(UINT32) +{ + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return GalSoundLatch; +} + +UINT8 KonamiSoundTimerRead(UINT32) +{ + INT32 nActiveCPU = ZetGetActive(); + UINT32 Cycles; + + if (nActiveCPU == 1) { + Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2); + } else { + ZetClose(); + ZetOpen(1); + Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2); + ZetClose(); + ZetOpen(nActiveCPU); + } + + UINT8 HiBit = 0; + + if (Cycles >= 16 * 16 * 2 * 8 * 5) { + HiBit = 1; + Cycles -= 16 * 16 * 2 * 8 * 5; + } + + return (HiBit << 7) | (BIT(Cycles, 14) << 6) | (BIT(Cycles, 13) << 5) | (BIT(Cycles, 11) << 4) | 0x0e; +} + +UINT8 FroggerSoundTimerRead(UINT32) +{ + UINT8 KonamiValue = KonamiSoundTimerRead(0); + return BITSWAP08(KonamiValue, 7, 6, 3, 4, 5, 2, 1, 0); +} + +UINT8 HunchbksSoundTimerRead(UINT32) +{ + INT32 nActiveCPU = ZetGetActive(); + UINT32 Cycles; + + if (nActiveCPU == 0) { + Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2); + } else { + ZetOpen(0); + Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2); + ZetClose(); + } + + UINT8 HiBit = 0; + + if (Cycles >= 16 * 16 * 2 * 8 * 5) { + HiBit = 1; + Cycles -= 16 * 16 * 2 * 8 * 5; + } + + return (HiBit << 7) | (BIT(Cycles, 14) << 6) | (BIT(Cycles, 13) << 5) | (BIT(Cycles, 11) << 4) | 0x0e; +} + +void KonamiSoundLatchWrite(UINT8 d) +{ + GalSoundLatch = d; +} + +void KonamiSoundControlWrite(UINT8 d) +{ + UINT8 Old = KonamiSoundControl; + KonamiSoundControl = d; + + if ((Old & 0x08) && !(d & 0x08)) { + INT32 nActiveCPU = ZetGetActive(); + + if (nActiveCPU == 1) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(nActiveCPU); + } + } + + /* bit 4 is sound disable */ +// sound_global_enable(~data & 0x10); +} + +void HunchbksSoundControlWrite(UINT8 d) +{ + UINT8 Old = KonamiSoundControl; + KonamiSoundControl = d; + + HunchbksSoundIrqFire = 0; + + if ((Old & 0x08) && !(d & 0x08)) { + HunchbksSoundIrqFire = 1; + } + + /* bit 4 is sound disable */ +// sound_global_enable(~data & 0x10); +} + +void SfxSoundLatch2Write(UINT32, UINT32 d) +{ + GalSoundLatch2 = d & 0xff; +} + +void SfxSampleControlWrite(UINT32, UINT32 d) +{ + UINT8 Old = SfxSampleControl; + + d &= 0xff; + SfxSampleControl = d; + + if ((Old & 0x01) && !(d & 0x01)) { + INT32 nActiveCPU = ZetGetActive(); + + if (nActiveCPU == 1) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(nActiveCPU); + } + } +} + +// Frogger Sound CPU Memory Map +UINT8 __fastcall FroggerSoundZ80Read(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall FroggerSoundZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x6000 && a <= 0x6fff) { + // konami_sound_filter_w + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall FroggerSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + UINT8 Result = 0xff; + if (a & 0x40) Result &= AY8910Read(0); + return Result; +} + +void __fastcall FroggerSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a & 0x40) { + AY8910Write(0, 1, d); + } else { + if (a & 0x80) { + AY8910Write(0, 0, d); + } + } +} + +void FroggerSoundNoEncryptionInit() +{ + ZetOpen(1); + ZetSetReadHandler(FroggerSoundZ80Read); + ZetSetWriteHandler(FroggerSoundZ80Write); + ZetSetInHandler(FroggerSoundZ80PortRead); + ZetSetOutHandler(FroggerSoundZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2); + ZetMapArea(0x4000, 0x43ff, 0, GalZ80Ram2); + ZetMapArea(0x4000, 0x43ff, 1, GalZ80Ram2); + ZetMapArea(0x4000, 0x43ff, 2, GalZ80Ram2); + ZetMemEnd(); + ZetClose(); + + nGalCyclesTotal[1] = (14318000 / 8) / 60; +} + +void FroggerSoundInit() +{ + FroggerSoundNoEncryptionInit(); + + for (UINT32 Offset = 0; Offset < 0x0800; Offset++) GalZ80Rom2[Offset] = BITSWAP08(GalZ80Rom2[Offset], 7, 6, 5, 4, 3, 2, 0, 1); +} + +// Konami Sound CPU Memory Map +UINT8 __fastcall KonamiSoundZ80Read(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0xff; +} + +void __fastcall KonamiSoundZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0x9000 && a <= 0x9fff) { + // konami_sound_filter_w + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KonamiSoundZ80PortRead(UINT16 a) +{ + a &= 0xff; + + UINT8 Result = 0xff; + if (a & 0x20) Result &= AY8910Read(0); + if (a & 0x80) Result &= AY8910Read(1); + return Result; +} + +void __fastcall KonamiSoundZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a & 0x10) { + AY8910Write(0, 0, d); + } else { + if (a & 0x20) { + AY8910Write(0, 1, d); + } + } + + if (a & 0x40) { + AY8910Write(1, 0, d); + } else { + if (a & 0x80) { + AY8910Write(1, 1, d); + } + } +} + +void KonamiSoundInit() +{ + ZetOpen(1); + ZetSetReadHandler(KonamiSoundZ80Read); + ZetSetWriteHandler(KonamiSoundZ80Write); + ZetSetInHandler(KonamiSoundZ80PortRead); + ZetSetOutHandler(KonamiSoundZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2); + ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2); + ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram2); + ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram2); + ZetMemEnd(); + ZetClose(); + + nGalCyclesTotal[1] = (14318000 / 8) / 60; +} + +void HunchbksSoundInit() +{ + ZetOpen(0); + ZetSetReadHandler(KonamiSoundZ80Read); + ZetSetWriteHandler(KonamiSoundZ80Write); + ZetSetInHandler(KonamiSoundZ80PortRead); + ZetSetOutHandler(KonamiSoundZ80PortWrite); + ZetMapArea(0x0000, GalZ80Rom1Size - 1, 0, GalZ80Rom1); + ZetMapArea(0x0000, GalZ80Rom1Size - 1, 2, GalZ80Rom1); + ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram1 + 0x400); + ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram1 + 0x400); + ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram1 + 0x400); + ZetMapArea(0x8400, 0x87ff, 0, GalZ80Ram1 + 0x400); + ZetMapArea(0x8400, 0x87ff, 1, GalZ80Ram1 + 0x400); + ZetMapArea(0x8400, 0x87ff, 2, GalZ80Ram1 + 0x400); + ZetMapArea(0x8800, 0x8bff, 0, GalZ80Ram1 + 0x400); + ZetMapArea(0x8800, 0x8bff, 1, GalZ80Ram1 + 0x400); + ZetMapArea(0x8800, 0x8bff, 2, GalZ80Ram1 + 0x400); + ZetMapArea(0x8c00, 0x8fff, 0, GalZ80Ram1 + 0x400); + ZetMapArea(0x8c00, 0x8fff, 1, GalZ80Ram1 + 0x400); + ZetMapArea(0x8c00, 0x8fff, 2, GalZ80Ram1 + 0x400); + ZetMemEnd(); + ZetClose(); + + nGalCyclesTotal[1] = (14318000 / 8) / 60; +} + +// Galaxian samples +static void GalRenderShootSample(INT16 *pSoundBuf, INT32 nLength) +{ + double Addr = GalShootWavePos; + double Step = (double)GalShootRate / nBurnSoundRate; + + for (INT32 i = 0; i < nLength; i += 2) { + INT16 Sample = (INT16)(GalShootWave[(INT32)Addr] * SHOOT_VOLUME); + Sample >>= 4; + + pSoundBuf[i + 0] += Sample; + pSoundBuf[i + 1] += Sample; + + Addr += Step; + } + + GalShootWavePos = Addr; + if (GalShootWavePos > GalShootLength) { + GalShootWavePos = 0; + GalShootEnable = 0; + } +} + +static void GalRenderNoiseSample(INT16 *pSoundBuf, INT32 nLength) +{ + double Addr = GalNoiseWavePos; + double Step = (double)NOISE_RATE / nBurnSoundRate; + + for (INT32 i = 0; i < nLength; i += 2) { + INT16 Sample = (INT16)(GalNoiseWave[(INT32)Addr] * (GalNoiseVolume / 100)); + Sample >>= 4; + + pSoundBuf[i + 0] += Sample; + pSoundBuf[i + 1] += Sample; + + Addr += Step; + } + + GalNoiseWavePos = Addr; + if (GalNoiseWavePos > NOISE_LENGTH) { + GalNoiseWavePos = 0; + } +} + +static void GalRenderToneWave(INT16 *pSoundBuf, INT32 nLength) +{ + INT32 i,j; + INT16 *w = GalToneWave[GalVol]; + + if (GalPitch != 0xff) { + for (i = 0; i < nLength; i += 2) { + INT32 mix = 0; + + for (j = 0; j < STEPS; j++) { + if (GalCountDown >= 256) { + GalCounter = GalCounter + ((double)96000 / nBurnSoundRate); + if (GalCounter > TOOTHSAW_LENGTH) GalCounter = 0; + GalCountDown = GalPitch; + } + GalCountDown++; + + mix += w[(INT32)GalCounter]; + } + + INT16 Sample = mix / STEPS; + Sample >>= 4; + + pSoundBuf[i + 0] = Sample; + pSoundBuf[i + 1] = Sample; + } + } +} + +static void GalRenderLfoWaveSample(INT32 nLfoWave, INT16 *pSoundBuf, INT32 nLength) +{ + double Addr = GalLfoWavePos[nLfoWave]; + double Step = (double)(sizeof(GalBackgroundWave) * GalLfoFreq * (100 + 2 * 470) / (100 + 2 * 470)) / nBurnSoundRate; + + for (INT32 i = 0; i < nLength; i += 2) { + INT16 Sample = (INT16)(GalBackgroundWave[(INT32)Addr] * (GalLfoVolume[nLfoWave] ? LFO_VOLUME : 0)); + Sample >>= 4; + + pSoundBuf[i + 0] += Sample; + pSoundBuf[i + 1] += Sample; + + Addr += Step; + } + + GalLfoWavePos[nLfoWave] = Addr; + if (GalLfoWavePos[nLfoWave] > 32) { + GalLfoWavePos[nLfoWave] = 0; + } +} + +void GalRenderSoundSamples(INT16 *pSoundBuf, INT32 nLength) +{ + memset(pSoundBuf, 0, nLength * 2 * sizeof(INT16)); + + GalRenderToneWave(pSoundBuf, nLength); + GalRenderNoiseSample(pSoundBuf, nLength); + if (GalShootEnable) GalRenderShootSample(pSoundBuf, nLength); + GalRenderLfoWaveSample(0, pSoundBuf, nLength); + GalRenderLfoWaveSample(1, pSoundBuf, nLength); + GalRenderLfoWaveSample(2, pSoundBuf, nLength); +} + +void GalaxianSoundWrite(UINT32 Offset, UINT8 d) +{ + d &= 0x01; + + switch (Offset & 0x07) { + case 0x00: + case 0x01: + case 0x02: { + GalLfoVolume[Offset] = d; + return; + } + + case 0x03: { + GalNoiseEnable = d & 1; + if (GalNoiseEnable) { + GalNoiseVolume = 100; + GalNoiseWavePos = 0; + } + return; + } + + case 0x04: { + return; + } + + case 0x05: { + if (d & 1 && !(GalLastPort2 & 1) ) { + GalShootEnable = 1; + GalShootWavePos = 0; + } + GalLastPort2 = d; + return; + } + + case 0x06: + case 0x07: { + GalVol = (GalVol & ~(1 << (Offset & 0x01))) | ((d & 1) << (Offset & 0x01)); + return; + } + } +} + +void GalaxianLfoFreqWrite(UINT32 Offset, UINT8 d) +{ + double r0, r1, rx = 100000.0; + + if ((d & 0x01) == GalLfoBit[Offset]) return; + + GalLfoBit[Offset] = d & 0x01; + + r0 = 1.0 / 330000; + r1 = 1.0 / 1e12; + + if (GalLfoBit[0]) { + r1 += 1.0 / 1000000; + } else { + r0 += 1.0 / 1000000; + } + + if (GalLfoBit[1]) { + r1 += 1.0 / 470000; + } else { + r0 += 1.0 / 470000; + } + + if (GalLfoBit[2]) { + r1 += 1.0 / 220000; + } else { + r0 += 1.0 / 220000; + } + + if (GalLfoBit[3]) { + r1 += 1.0 / 100000; + } else { + r0 += 1.0 / 100000; + } + + r0 = 1.0 / r0; + r1 = 1.0 / r1; + + rx = rx + 2000000.0 * r0 / (r0 + r1); + + GalLfoFreqFrameVar = (1000000000 / ((MAXFREQ - MINFREQ) * 639 * rx)) * 100; + + bprintf(PRINT_NORMAL, _T("Offset %x, rx %f, %f\n"), Offset, (MAXFREQ - MINFREQ) * 639 * rx, GalLfoFreqFrameVar); +} + +void GalaxianSoundUpdateTimers() +{ + if (GetCurrentFrame() % 3) { + if (!GalNoiseEnable && GalNoiseVolume > 0) { + GalNoiseVolume -= (GalNoiseVolume / 10) + 1; + } + } + + if (GalLfoFreq > MINFREQ) { + GalLfoFreq -= GalLfoFreqFrameVar; + } else { + GalLfoFreq = MAXFREQ; + } +} diff --git a/src/burn/drivers/galaxian/gal_stars.cpp b/src/burn/drivers/galaxian/gal_stars.cpp new file mode 100644 index 00000000..a63f0235 --- /dev/null +++ b/src/burn/drivers/galaxian/gal_stars.cpp @@ -0,0 +1,241 @@ +#include "gal.h" + +// This module is not accurate to the arcade hardware - it is ported from my previous Galaxian driver for FBA, +// which was based on an old version of MAME. It is considered "good enough" for the purpose of giving the impression +// of the star layers without being totally accurate + +struct Star +{ + INT32 x, y, Colour; +}; + +static struct Star Stars[252]; + +INT32 GalStarsEnable = 0; +INT32 GalStarsScrollPos = 0; +INT32 GalStarsBlinkState = 0; +INT32 GalBlinkTimerStartFrame = 0; +static double GalBlinkEveryFrames = (0.693 * (100000 + 2.0 + 10000) * 0.00001) * (16000.0 / 132 / 2); + +void GalInitStars() +{ + INT32 nStars, Generator, x, y; + + GalStarsEnable = 0; + GalStarsScrollPos = -1; + GalStarsBlinkState = 0; + + nStars = 0; + Generator = 0; + + for (y = 255; y >= 0; y--) { + for (x = 511; x >= 0; x--) { + INT32 Bit0; + + Bit0 = ((~Generator >> 16) & 0x01) ^ ((Generator >> 4) & 0x01); + + Generator = (Generator << 1) | Bit0; + + if (((~Generator >> 16) & 0x01) && (Generator & 0xff) == 0xff) { + INT32 Colour; + + Colour = (~(Generator >> 8)) & 0x3f; + + if (Colour) { + Stars[nStars].x = x; + Stars[nStars].y = y; + Stars[nStars].Colour = Colour; + + nStars++; + } + } + } + } +} + +static INT32 GalCheckStarsBlinkState() +{ + INT32 CurrentFrame = GetCurrentFrame(); + + if ((CurrentFrame - GalBlinkTimerStartFrame) >= (INT32)GalBlinkEveryFrames) { + GalBlinkTimerStartFrame = CurrentFrame; + return 1; + } + + return 0; +} + +static inline void GalPlotStar(INT32 x, INT32 y, INT32 Colour) +{ + if (y >= 0 && y < nScreenHeight && x >= 0 && x < nScreenWidth) { + pTransDraw[(y * nScreenWidth) + x] = Colour + GAL_PALETTE_STARS_OFFSET; + } +} + +void GalaxianRenderStarLayer() +{ + GalStarsScrollPos++; + + for (INT32 Offs = 0; Offs < 252; Offs++) { + INT32 x, y; + + x = ((Stars[Offs].x + GalStarsScrollPos) & 0x01ff) >>1; + y = (Stars[Offs].y + ((GalStarsScrollPos + Stars[Offs].x) >> 9)) & 0xff; + + if ((y & 0x01) ^ ((x >> 3) & 0x01)) { + if (GalFlipScreenX) x = 255 - x; + if (GalFlipScreenY) y = 255 - y; + y -= 16; + GalPlotStar(x, y, Stars[Offs].Colour); + } + } +} + +void JumpbugRenderStarLayer() +{ + if (GalCheckStarsBlinkState()) GalStarsBlinkState++; + + for (INT32 Offs = 0; Offs < 252; Offs++) { + INT32 x, y; + + x = Stars[Offs].x >> 1; + y = Stars[Offs].y >> 1; + + if ((y & 0x01) ^ ((x >> 3) & 0x01)) { + switch (GalStarsBlinkState & 0x03) { + case 0: { + if (!(Stars[Offs].Colour & 0x01)) continue; + break; + } + + case 1: { + if (!(Stars[Offs].Colour & 0x04)) continue; + break; + } + + case 2: { + if (!(Stars[Offs].y & 0x02)) continue; + break; + } + + case 3: { + break; + } + } + + x = Stars[Offs].x >> 1; + y = Stars[Offs].y & 0xff; + + if (x >= 240) continue; + + if (GalFlipScreenX) x = 255 - x; + if (GalFlipScreenY) y = 255 - y; + y -= 16; + GalPlotStar(x, y, Stars[Offs].Colour); + } + } +} + +void ScrambleRenderStarLayer() +{ + if (GalCheckStarsBlinkState()) GalStarsBlinkState++; + + for (INT32 Offs = 0; Offs < 252; Offs++) { + INT32 x, y; + + x = Stars[Offs].x >> 1; + y = Stars[Offs].y; + + if ((y & 0x01) ^ ((x >> 3) & 0x01)) { + switch (GalStarsBlinkState & 0x03) { + case 0: { + if (!(Stars[Offs].Colour & 0x01)) continue; + break; + } + + case 1: { + if (!(Stars[Offs].Colour & 0x04)) continue; + break; + } + + case 2: { + if (!(Stars[Offs].y & 0x02)) continue; + break; + } + + case 3: { + break; + } + } + + if (GalFlipScreenX) x = 255 - x; + if (GalFlipScreenY) y = 255 - y; + y -= 16; + GalPlotStar(x, y, Stars[Offs].Colour); + } + } +} + +void MarinerRenderStarLayer() +{ + UINT8 *Prom = GalProm + 0x120; + + GalStarsScrollPos++; + + for (INT32 Offs = 0; Offs < 252; Offs++) { + INT32 x, y; + + x = ((Stars[Offs].x + GalStarsScrollPos) & 0x01ff) >>1; + y = (Stars[Offs].y + ((GalStarsScrollPos + Stars[Offs].x) >> 9)) & 0xff; + + if ((y & 0x01) ^ ((x >> 3) & 0x01)) { + if (GalFlipScreenX) x = 255 - x; + if (GalFlipScreenY) y = 255 - y; + y -= 16; + + if (Prom[((x / 8) + 1) & 0x1f] & 0x04) { + GalPlotStar(x, y, Stars[Offs].Colour); + } + } + } +} + +void RescueRenderStarLayer() +{ + if (GalCheckStarsBlinkState()) GalStarsBlinkState++; + + for (INT32 Offs = 0; Offs < 252; Offs++) { + INT32 x, y; + + x = Stars[Offs].x >> 1; + y = Stars[Offs].y; + + if (x < 128 && ((y & 0x01) ^ ((x >> 3) & 0x01))) { + switch (GalStarsBlinkState & 0x03) { + case 0: { + if (!(Stars[Offs].Colour & 0x01)) continue; + break; + } + + case 1: { + if (!(Stars[Offs].Colour & 0x04)) continue; + break; + } + + case 2: { + if (!(Stars[Offs].y & 0x02)) continue; + break; + } + + case 3: { + break; + } + } + + if (GalFlipScreenX) x = 255 - x; + if (GalFlipScreenY) y = 255 - y; + y -= 16; + GalPlotStar(x, y, Stars[Offs].Colour); + } + } +} diff --git a/src/burn/drivers/irem/d_m62.cpp b/src/burn/drivers/irem/d_m62.cpp new file mode 100644 index 00000000..ad31af36 --- /dev/null +++ b/src/burn/drivers/irem/d_m62.cpp @@ -0,0 +1,5022 @@ +#include "tiles_generic.h" +#include "m6800_intf.h" +#include "msm5205.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static UINT8 M62InputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 M62InputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 M62InputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 M62Dip[2] = {0, 0}; +static UINT8 M62Input[3] = {0x00, 0x00, 0x00}; +static UINT8 M62Reset = 0; + +static UINT32 M62Z80RomSize = 0; +static UINT32 M62PromSize = 0; +static UINT32 M62NumTiles = 0; +static UINT32 M62NumSprites = 0; +static UINT32 M62NumChars = 0; +static UINT32 M62SpriteRamSize = 0; +static UINT32 M62CharRamSize = 0; +static UINT32 M62ScrollRamSize = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *M62Z80Rom = NULL; +static UINT8 *M62M6803Rom = NULL; +static UINT8 *M62TileRam = NULL; +static UINT8 *M62SpriteRam = NULL; +static UINT8 *M62CharRam = NULL; +static UINT8 *M62ScrollRam = NULL; +static UINT8 *M62Z80Ram = NULL; +static UINT8 *M62M6803Ram = NULL; +static UINT8 *M62Tiles = NULL; +static UINT8 *M62Sprites = NULL; +static UINT8 *M62Chars = NULL; +static UINT8 *M62PromData = NULL; +static UINT8 *M62TempRom = NULL; +static UINT32 *M62Palette = NULL; +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[6]; + +static INT32 M62BackgroundHScroll; +static INT32 M62BackgroundVScroll; +static INT32 M62CharHScroll; +static INT32 M62CharVScroll; +static INT32 M62FlipScreen; +static INT32 M62SpriteHeightPromOffset; +static UINT8 M62SoundLatch; +static UINT8 M62Port1; +static UINT8 M62Port2; +static UINT8 M62SlaveMSM5205VClckReset; +static UINT32 M62PaletteEntries; +static UINT32 M62Z80Clock; +static UINT32 M62M6803Clock; +static UINT8 M62BankControl[2]; +static UINT8 Ldrun2BankSwap; +static UINT8 Ldrun3TopBottomMask; +static UINT8 KidnikiBackgroundBank; +static UINT8 SpelunkrPaletteBank; +static INT32 M62BgxTileDim = 0; +static INT32 M62BgyTileDim = 0; +static INT32 M62CharxTileDim = 0; +static INT32 M62CharyTileDim = 0; + +typedef void (*M62Render)(); +static M62Render M62RenderFunction; +static void KungfumDraw(); +static void BattroadDraw(); +static void LdrunDraw(); +static void Ldrun3Draw(); +static void Ldrun4Draw(); +static void LotlotDraw(); +static void KidnikiDraw(); +static void SpelunkrDraw(); +static void Spelunk2Draw(); +static void YoujyudnDraw(); +static void HorizonDraw(); + +typedef void (*M62ExtendTileInfo)(INT32*, INT32*, INT32*, INT32*); +static M62ExtendTileInfo M62ExtendTileInfoFunction; +static void BattroadExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip); +static void LdrunExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip); +static void Ldrun2ExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip); +static void Ldrun4ExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*); +static void LotlotExtendTile(INT32* Code, INT32* Colour, INT32*, INT32* xFlip); +static void KidnikiExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*); +static void SpelunkrExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*); +static void Spelunk2ExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*); +static void YoujyudnExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*); +static void HorizonExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*); + +typedef void (*M62ExtendCharInfo)(INT32*, INT32*, INT32*, INT32*); +static M62ExtendCharInfo M62ExtendCharInfoFunction; +static void BattroadExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*); +static void LotlotExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*); +static void SpelunkrExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*); +static void YoujyudnExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*); + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo M62InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , M62InputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , M62InputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , M62InputPort2 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , M62InputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , M62InputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , M62InputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , M62InputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , M62InputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , M62InputPort1 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , M62InputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 7, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , M62InputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &M62Reset , "reset" }, + {"Service" , BIT_DIGITAL , M62InputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, M62Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, M62Dip + 1 , "dip" }, +}; + +STDINPUTINFO(M62) + +static inline void M62ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void M62MakeInputs() +{ + M62Input[0] = M62Input[1] = M62Input[2] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + M62Input[0] |= (M62InputPort0[i] & 1) << i; + M62Input[1] |= (M62InputPort1[i] & 1) << i; + M62Input[2] |= (M62InputPort2[i] & 1) << i; + } + + M62ClearOpposites(&M62Input[0]); + M62ClearOpposites(&M62Input[1]); +} + +#define IREM_Z80_COINAGE_TYPE3 \ + {0 , 0xfe, 0 , 15 , "Coinage" }, \ + {0x12, 0x02, 0xf0, 0x90, "7 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xa0, "6 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xb0, "5 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xc0, "4 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xd0, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xe0, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xf0, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x70, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x60, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x50, "1 Coin 4 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x40, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x30, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x20, "1 Coin 7 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x10, "1 Coin 8 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x00, "Freeplay" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + \ + {0 , 0xfe, 0 , 4 , "Coin A" }, \ + {0x12, 0x82, 0x30, 0x10, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x20, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x30, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x00, "Free Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0 , 0xfe, 0 , 4 , "Coin B" }, \ + {0x12, 0x82, 0xc0, 0xc0, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x80, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x40, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x00, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + +#define IREM_Z80_COINAGE_TYPE4 \ + {0 , 0xfe, 0 , 16 , "Coinage" }, \ + {0x12, 0x02, 0xf0, 0xa0, "6 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xb0, "5 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xc0, "4 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xd0, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x10, "8 Coins 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xe0, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x20, "5 Coins 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x30, "3 Coins 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xf0, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x40, "2 Coins 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x90, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x80, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x70, "1 Coin 4 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x60, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x50, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x00, "Freeplay" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + \ + {0 , 0xfe, 0 , 4 , "Coin A" }, \ + {0x12, 0x82, 0x30, 0x00, "5 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x10, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x20, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x30, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0 , 0xfe, 0 , 4 , "Coin B" }, \ + {0x12, 0x82, 0xc0, 0xc0, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x80, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x40, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x00, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + +#define IREM_Z80_COINAGE_TYPE5 \ + {0 , 0xfe, 0 , 16 , "Coinage" }, \ + {0x12, 0x02, 0xf0, 0x00, "8 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xa0, "6 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xb0, "5 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xc0, "4 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xd0, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xe0, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x10, "5 Coins 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x20, "3 Coins 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x30, "3 Coins 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0xf0, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x40, "2 Coins 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x90, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x80, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x70, "1 Coin 4 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x60, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x02, 0xf0, 0x50, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + \ + {0 , 0xfe, 0 , 4 , "Coin A" }, \ + {0x12, 0x82, 0x30, 0x00, "5 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x10, "3 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x20, "2 Coins 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0x30, 0x30, "1 Coin 1 Play" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0 , 0xfe, 0 , 4 , "Coin B" }, \ + {0x12, 0x82, 0xc0, 0xc0, "1 Coin 2 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x80, "1 Coin 3 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x40, "1 Coin 5 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + {0x12, 0x82, 0xc0, 0x00, "1 Coin 6 Plays" }, \ + {0x13, 0x00, 0x04, 0x04, NULL }, \ + +static struct BurnDIPInfo KungfumDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x01, 0x01, "Easy" }, + {0x12, 0x01, 0x01, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Energy Loss" }, + {0x12, 0x01, 0x02, 0x02, "Slow" }, + {0x12, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE3 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion Mode" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Selection Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Kungfum) + +static struct BurnDIPInfo BattroadDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Fuel Decrease" }, + {0x12, 0x01, 0x03, 0x03, "Slow" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x04, 0x04, "Easy" }, + {0x12, 0x01, 0x04, 0x00, "Hard" }, + + IREM_Z80_COINAGE_TYPE3 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Battroad) + +static struct BurnDIPInfo LdrunDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Timer" }, + {0x12, 0x01, 0x03, 0x03, "Slow" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE3 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Selection Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ldrun) + +static struct BurnDIPInfo Ldrun2DIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x12, 0x01, 0x01, 0x01, "Slow" }, + {0x12, 0x01, 0x01, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Game Speed" }, + {0x12, 0x01, 0x02, 0x00, "Low" }, + {0x12, 0x01, 0x02, 0x02, "High" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE3 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Selection Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ldrun2) + +static struct BurnDIPInfo Ldrun4DIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x12, 0x01, 0x01, 0x01, "Slow" }, + {0x12, 0x01, 0x01, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x12, 0x01, 0x02, 0x00, "1 Credit" }, + {0x12, 0x01, 0x02, 0x02, "2 Credits" }, + + {0 , 0xfe, 0 , 4 , "1 Player Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE3 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "2 Players Lives" }, + {0x13, 0x01, 0x02, 0x02, "5" }, + {0x13, 0x01, 0x02, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Allow 2 Player Game" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Selection Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ldrun4) + +static struct BurnDIPInfo LotlotDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xf5, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Speed" }, + {0x12, 0x01, 0x03, 0x03, "Very Slow" }, + {0x12, 0x01, 0x03, 0x02, "Slow" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Very Fast" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "1" }, + {0x12, 0x01, 0x0c, 0x0c, "2" }, + {0x12, 0x01, 0x0c, 0x04, "3" }, + {0x12, 0x01, 0x0c, 0x00, "4" }, + + IREM_Z80_COINAGE_TYPE4 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Lotlot) + +static struct BurnDIPInfo KidnikiDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x04, 0x04, "Normal" }, + {0x12, 0x01, 0x04, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x08, 0x08, "50000" }, + {0x12, 0x01, 0x08, 0x00, "80000" }, + + IREM_Z80_COINAGE_TYPE4 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Game Repeats" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Kidniki) + +static struct BurnDIPInfo SpelunkrDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xf5, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Energy Decrease" }, + {0x12, 0x01, 0x03, 0x03, "Slow" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE4 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Teleport" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Spelunkr) + +static struct BurnDIPInfo Spelunk2DIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Energy Decrease" }, + {0x12, 0x01, 0x03, 0x03, "Slow" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE4 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Spelunk2) + +static struct BurnDIPInfo YoujyudnDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + IREM_Z80_COINAGE_TYPE4 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x13, 0x01, 0x08, 0x08, "20000 60000" }, + {0x13, 0x01, 0x08, 0x00, "40000 80000" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Selection Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Youjyudn) + +static struct BurnDIPInfo HorizonDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x0c, 0x00, "100 and 80k" }, + {0x12, 0x01, 0x0c, 0x0c, "40k and every 80k" }, + {0x12, 0x01, 0x0c, 0x08, "60k and every 100k" }, + {0x12, 0x01, 0x0c, 0x04, "80k and every 120k" }, + + IREM_Z80_COINAGE_TYPE5 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Frame Advance" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Horizon) + +static struct BurnRomInfo KungfumRomDesc[] = { + { "a-4e-c.bin", 0x04000, 0xb6e2d083, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "a-4d-c.bin", 0x04000, 0x7532918e, BRF_ESS | BRF_PRG }, // 1 + + { "a-3e-.bin", 0x02000, 0x58e87ab0, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + { "a-3f-.bin", 0x02000, 0xc81e31ea, BRF_ESS | BRF_PRG }, // 3 + { "a-3h-.bin", 0x02000, 0xd99fb995, BRF_ESS | BRF_PRG }, // 4 + + { "g-4c-a.bin", 0x02000, 0x6b2cc9c8, BRF_GRA }, // 5 Characters + { "g-4d-a.bin", 0x02000, 0xc648f558, BRF_GRA }, // 6 + { "g-4e-a.bin", 0x02000, 0xfbe9276e, BRF_GRA }, // 7 + + { "b-4k-.bin", 0x02000, 0x16fb5150, BRF_GRA }, // 8 Sprites + { "b-4f-.bin", 0x02000, 0x67745a33, BRF_GRA }, // 9 + { "b-4l-.bin", 0x02000, 0xbd1c2261, BRF_GRA }, // 10 + { "b-4h-.bin", 0x02000, 0x8ac5ed3a, BRF_GRA }, // 11 + { "b-3n-.bin", 0x02000, 0x28a213aa, BRF_GRA }, // 12 + { "b-4n-.bin", 0x02000, 0xd5228df3, BRF_GRA }, // 13 + { "b-4m-.bin", 0x02000, 0xb16de4f2, BRF_GRA }, // 14 + { "b-3m-.bin", 0x02000, 0xeba0d66b, BRF_GRA }, // 15 + { "b-4c-.bin", 0x02000, 0x01298885, BRF_GRA }, // 16 + { "b-4e-.bin", 0x02000, 0xc77b87d4, BRF_GRA }, // 17 + { "b-4d-.bin", 0x02000, 0x6a70615f, BRF_GRA }, // 18 + { "b-4a-.bin", 0x02000, 0x6189d626, BRF_GRA }, // 19 + + { "g-1j-.bin", 0x00100, 0x668e6bca, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "b-1m-.bin", 0x00100, 0x76c05a9c, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "g-1f-.bin", 0x00100, 0x964b6495, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "b-1n-.bin", 0x00100, 0x23f06b99, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "g-1h-.bin", 0x00100, 0x550563e1, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "b-1l-.bin", 0x00100, 0x35e45021, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "b-5f-.bin", 0x00020, 0x7a601c3d, BRF_GRA }, // 26 PROM (Sprite Height) + { "b-6f-.bin", 0x00100, 0x82c20d12, BRF_GRA }, // 27 PROM (Video Timing) +}; + +STD_ROM_PICK(Kungfum) +STD_ROM_FN(Kungfum) + +static struct BurnRomInfo KungfumdRomDesc[] = { + { "snx_a-4e-d", 0x04000, 0xfc330a46, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "snx_a-4d-d", 0x04000, 0x1b2fd32f, BRF_ESS | BRF_PRG }, // 1 + + { "snx_a-3d-b", 0x04000, 0x85ca7956, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + { "snx_a-3f-b", 0x04000, 0x3ef1100a, BRF_ESS | BRF_PRG }, // 3 + + { "g-4c-a.bin", 0x02000, 0x6b2cc9c8, BRF_GRA }, // 4 Characters + { "g-4d-a.bin", 0x02000, 0xc648f558, BRF_GRA }, // 5 + { "g-4e-a.bin", 0x02000, 0xfbe9276e, BRF_GRA }, // 6 + + { "snx_b-4k-b", 0x04000, 0x85591db2, BRF_GRA }, // 7 Sprites + { "snx_b-4f-b", 0x04000, 0xed719d7b, BRF_GRA }, // 8 + { "snx_b-3n-b", 0x04000, 0x05fcce8b, BRF_GRA }, // 9 + { "snx_b-4n-b", 0x04000, 0xdc675003, BRF_GRA }, // 10 + { "snx_b-4c-b", 0x04000, 0x1df11d81, BRF_GRA }, // 11 + { "snx_b-4e-b", 0x04000, 0x2d3b69dd, BRF_GRA }, // 12 + + { "g-1j-.bin", 0x00100, 0x668e6bca, BRF_GRA }, // 13 PROM (Tile Palette Red Component) + { "b-1m-.bin", 0x00100, 0x76c05a9c, BRF_GRA }, // 14 PROM (Sprite Palette Red Component) + { "g-1f-.bin", 0x00100, 0x964b6495, BRF_GRA }, // 15 PROM (Tile Palette Green Component) + { "b-1n-.bin", 0x00100, 0x23f06b99, BRF_GRA }, // 16 PROM (Sprite Palette Green Component) + { "g-1h-.bin", 0x00100, 0x550563e1, BRF_GRA }, // 17 PROM (Tile Palette Blue Component) + { "b-1l-.bin", 0x00100, 0x35e45021, BRF_GRA }, // 18 PROM (Sprite Palette Blue Component) + { "b-5f-.bin", 0x00020, 0x7a601c3d, BRF_GRA }, // 19 PROM (Sprite Height) + { "b-6f-.bin", 0x00100, 0x82c20d12, BRF_GRA }, // 20 PROM (Video Timing) +}; + +STD_ROM_PICK(Kungfumd) +STD_ROM_FN(Kungfumd) + +static struct BurnRomInfo SpartanxRomDesc[] = { + { "a-4e-c-j.bin", 0x04000, 0x32a0a9a6, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "a-4d-c-j.bin", 0x04000, 0x3173ea78, BRF_ESS | BRF_PRG }, // 1 + + { "a-3e-.bin", 0x02000, 0x58e87ab0, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + { "a-3f-.bin", 0x02000, 0xc81e31ea, BRF_ESS | BRF_PRG }, // 3 + { "a-3h-.bin", 0x02000, 0xd99fb995, BRF_ESS | BRF_PRG }, // 4 + + { "g-4c-a-j.bin", 0x02000, 0x8af9c5a6, BRF_GRA }, // 5 Characters + { "g-4d-a-j.bin", 0x02000, 0xb8300c72, BRF_GRA }, // 6 + { "g-4e-a-j.bin", 0x02000, 0xb50429cd, BRF_GRA }, // 7 + + { "b-4k-.bin", 0x02000, 0x16fb5150, BRF_GRA }, // 8 Sprites + { "b-4f-.bin", 0x02000, 0x67745a33, BRF_GRA }, // 9 + { "b-4l-.bin", 0x02000, 0xbd1c2261, BRF_GRA }, // 10 + { "b-4h-.bin", 0x02000, 0x8ac5ed3a, BRF_GRA }, // 11 + { "b-3n-.bin", 0x02000, 0x28a213aa, BRF_GRA }, // 12 + { "b-4n-.bin", 0x02000, 0xd5228df3, BRF_GRA }, // 13 + { "b-4m-.bin", 0x02000, 0xb16de4f2, BRF_GRA }, // 14 + { "b-3m-.bin", 0x02000, 0xeba0d66b, BRF_GRA }, // 15 + { "b-4c-.bin", 0x02000, 0x01298885, BRF_GRA }, // 16 + { "b-4e-.bin", 0x02000, 0xc77b87d4, BRF_GRA }, // 17 + { "b-4d-.bin", 0x02000, 0x6a70615f, BRF_GRA }, // 18 + { "b-4a-.bin", 0x02000, 0x6189d626, BRF_GRA }, // 19 + + { "g-1j-.bin", 0x00100, 0x668e6bca, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "b-1m-.bin", 0x00100, 0x76c05a9c, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "g-1f-.bin", 0x00100, 0x964b6495, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "b-1n-.bin", 0x00100, 0x23f06b99, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "g-1h-.bin", 0x00100, 0x550563e1, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "b-1l-.bin", 0x00100, 0x35e45021, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "b-5f-.bin", 0x00020, 0x7a601c3d, BRF_GRA }, // 26 PROM (Sprite Height) + { "b-6f-.bin", 0x00100, 0x82c20d12, BRF_GRA }, // 27 PROM (Video Timing) +}; + +STD_ROM_PICK(Spartanx) +STD_ROM_FN(Spartanx) + +static struct BurnRomInfo KungfubRomDesc[] = { + { "c5.5h", 0x04000, 0x5d8e791d, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "c4.5k", 0x04000, 0x4000e2b8, BRF_ESS | BRF_PRG }, // 1 + + { "a-3e-.bin", 0x02000, 0x58e87ab0, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + { "a-3f-.bin", 0x02000, 0xc81e31ea, BRF_ESS | BRF_PRG }, // 3 + { "a-3h-.bin", 0x02000, 0xd99fb995, BRF_ESS | BRF_PRG }, // 4 + + { "g-4c-a.bin", 0x02000, 0x6b2cc9c8, BRF_GRA }, // 5 Characters + { "g-4d-a.bin", 0x02000, 0xc648f558, BRF_GRA }, // 6 + { "g-4e-a.bin", 0x02000, 0xfbe9276e, BRF_GRA }, // 7 + + { "b-4k-.bin", 0x02000, 0x16fb5150, BRF_GRA }, // 8 Sprites + { "b-4f-.bin", 0x02000, 0x67745a33, BRF_GRA }, // 9 + { "b-4l-.bin", 0x02000, 0xbd1c2261, BRF_GRA }, // 10 + { "b-4h-.bin", 0x02000, 0x8ac5ed3a, BRF_GRA }, // 11 + { "b-3n-.bin", 0x02000, 0x28a213aa, BRF_GRA }, // 12 + { "b-4n-.bin", 0x02000, 0xd5228df3, BRF_GRA }, // 13 + { "b-4m-.bin", 0x02000, 0xb16de4f2, BRF_GRA }, // 14 + { "b-3m-.bin", 0x02000, 0xeba0d66b, BRF_GRA }, // 15 + { "b-4c-.bin", 0x02000, 0x01298885, BRF_GRA }, // 16 + { "b-4e-.bin", 0x02000, 0xc77b87d4, BRF_GRA }, // 17 + { "b-4d-.bin", 0x02000, 0x6a70615f, BRF_GRA }, // 18 + { "b-4a-.bin", 0x02000, 0x6189d626, BRF_GRA }, // 19 + + { "tbp24s10-main-1c.bin", 0x00100, 0x668e6bca, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "tbp24s10-gfx-1r.bin", 0x00100, 0x76c05a9c, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "tbp24s10-main-1a.bin", 0x00100, 0x964b6495, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "tbp24s10-gfx-1s.bin", 0x00100, 0x23f06b99, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "tbp24s10-main-1b.bin", 0x00100, 0x550563e1, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "tbp24s10-gfx-1p.bin", 0x00100, 0x35e45021, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "18s030-gfx-8t.bin", 0x00020, 0x7a601c3d, BRF_GRA }, // 26 PROM (Sprite Height) + { "tbp24s10-gfx-9k.bin", 0x00100, 0x82c20d12, BRF_GRA }, // 27 PROM (Video Timing) + { "18s030-gfx-10a.bin", 0x00020, 0x3858acd0, BRF_OPT }, // 27 + { "18s030-gfx-5d.bin", 0x00020, 0x51304fcd, BRF_OPT }, // 28 + { "18s030-gfx-5e.bin", 0x00020, 0x51304fcd, BRF_OPT }, // 29 + { "18s030-gfx-6l.bin", 0x00020, 0x3858acd0, BRF_OPT }, // 30 + { "tbp24s10-gfx-3b.bin", 0x00100, 0xe6506ef4, BRF_OPT }, // 31 + { "tbp24s10-gfx-4a.bin", 0x00100, 0xe0aa8869, BRF_OPT }, // 32 + { "tbp24s10-gfx-4c.bin", 0x00100, 0xb43d094f, BRF_OPT }, // 33 + { "tbp24s10-gfx-6d.bin", 0x00100, 0x48bb39c9, BRF_OPT }, // 34 + { "tbp24s10-gfx-6e.bin", 0x00100, 0x48bb39c9, BRF_OPT }, // 35 + { "tbp24s10-gfx-6m.bin", 0x00100, 0x9f7a1a4d, BRF_OPT }, // 36 + { "tbp24s10-gfx-6n.bin", 0x00100, 0x35e5b39e, BRF_OPT }, // 37 + { "tbp24s10-gfx-8a.bin", 0x00100, 0x35e5b39e, BRF_OPT }, // 38 + { "tbp24s10-gfx-9a.bin", 0x00100, 0x9f7a1a4d, BRF_OPT }, // 39 + { "tbp24s10-gfx-9k.bin", 0x00100, 0x82c20d12, BRF_OPT }, // 40 + { "tbp24s10-main-8b.bin", 0x00100, 0x180fbc57, BRF_OPT }, // 41 + { "tbp24s10-main-8c.bin", 0x00100, 0x3bb32e5a, BRF_OPT }, // 42 + { "tbp24s10-main-8d.bin", 0x00100, 0x599c319f, BRF_OPT }, // 43 +}; + +STD_ROM_PICK(Kungfub) +STD_ROM_FN(Kungfub) + +static struct BurnRomInfo Kungfub2RomDesc[] = { + { "kf4", 0x04000, 0x3f65313f, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "kf5", 0x04000, 0x9ea325f3, BRF_ESS | BRF_PRG }, // 1 + + { "a-3e-.bin", 0x02000, 0x58e87ab0, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + { "a-3f-.bin", 0x02000, 0xc81e31ea, BRF_ESS | BRF_PRG }, // 3 + { "a-3h-.bin", 0x02000, 0xd99fb995, BRF_ESS | BRF_PRG }, // 4 + + { "g-4c-a.bin", 0x02000, 0x6b2cc9c8, BRF_GRA }, // 5 Characters + { "g-4d-a.bin", 0x02000, 0xc648f558, BRF_GRA }, // 6 + { "g-4e-a.bin", 0x02000, 0xfbe9276e, BRF_GRA }, // 7 + + { "b-4k-.bin", 0x02000, 0x16fb5150, BRF_GRA }, // 8 Sprites + { "b-4f-.bin", 0x02000, 0x67745a33, BRF_GRA }, // 9 + { "b-4l-.bin", 0x02000, 0xbd1c2261, BRF_GRA }, // 10 + { "b-4h-.bin", 0x02000, 0x8ac5ed3a, BRF_GRA }, // 11 + { "b-3n-.bin", 0x02000, 0x28a213aa, BRF_GRA }, // 12 + { "b-4n-.bin", 0x02000, 0xd5228df3, BRF_GRA }, // 13 + { "b-4m-.bin", 0x02000, 0xb16de4f2, BRF_GRA }, // 14 + { "b-3m-.bin", 0x02000, 0xeba0d66b, BRF_GRA }, // 15 + { "b-4c-.bin", 0x02000, 0x01298885, BRF_GRA }, // 16 + { "b-4e-.bin", 0x02000, 0xc77b87d4, BRF_GRA }, // 17 + { "b-4d-.bin", 0x02000, 0x6a70615f, BRF_GRA }, // 18 + { "b-4a-.bin", 0x02000, 0x6189d626, BRF_GRA }, // 19 + + { "g-1j-.bin", 0x00100, 0x668e6bca, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "b-1m-.bin", 0x00100, 0x76c05a9c, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "g-1f-.bin", 0x00100, 0x964b6495, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "b-1n-.bin", 0x00100, 0x23f06b99, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "g-1h-.bin", 0x00100, 0x550563e1, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "b-1l-.bin", 0x00100, 0x35e45021, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "b-5f-.bin", 0x00020, 0x7a601c3d, BRF_GRA }, // 26 PROM (Sprite Height) + { "b-6f-.bin", 0x00100, 0x82c20d12, BRF_GRA }, // 27 PROM (Video Timing) +}; + +STD_ROM_PICK(Kungfub2) +STD_ROM_FN(Kungfub2) + +static struct BurnRomInfo BattroadRomDesc[] = { + { "br-a-4e.b", 0x02000, 0x9bf14768, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "br-a-4d.b", 0x02000, 0x39ca1627, BRF_ESS | BRF_PRG }, // 1 + { "br-a-4b.b", 0x02000, 0x1865bb22, BRF_ESS | BRF_PRG }, // 2 + { "br-a-4a", 0x02000, 0x65b61c21, BRF_ESS | BRF_PRG }, // 3 + { "br-c-7c", 0x02000, 0x2e1eca52, BRF_ESS | BRF_PRG }, // 4 + { "br-c-7l", 0x02000, 0xf2178578, BRF_ESS | BRF_PRG }, // 5 + { "br-c-7d", 0x02000, 0x3aa9fa30, BRF_ESS | BRF_PRG }, // 6 + { "br-c-7b", 0x02000, 0x0b31b90b, BRF_ESS | BRF_PRG }, // 7 + { "br-c-7a", 0x02000, 0xec3b0080, BRF_ESS | BRF_PRG }, // 8 + { "br-c-7k", 0x02000, 0xedc75f7f, BRF_ESS | BRF_PRG }, // 9 + + { "br-a-3e", 0x02000, 0xa7140871, BRF_ESS | BRF_PRG }, // 10 M6803 Program Code + { "br-a-3f", 0x02000, 0x1bb51b30, BRF_ESS | BRF_PRG }, // 11 + { "br-a-3h", 0x02000, 0xafb3e083, BRF_ESS | BRF_PRG }, // 12 + + { "br-c-6h", 0x02000, 0xca50841c, BRF_GRA }, // 13 Tiles + { "br-c-6n", 0x02000, 0x7d53163a, BRF_GRA }, // 14 + { "br-c-6k", 0x02000, 0x5951e12a, BRF_GRA }, // 15 + + { "br-b-4k.a", 0x02000, 0xd3c5e85b, BRF_GRA }, // 16 Sprites + { "br-b-4f.a", 0x02000, 0x4354232a, BRF_GRA }, // 17 + { "br-b-3n.a", 0x02000, 0x2668dbef, BRF_GRA }, // 18 + { "br-b-4n.a", 0x02000, 0xc719a324, BRF_GRA }, // 19 + { "br-b-4c.a", 0x02000, 0x0b3193bf, BRF_GRA }, // 20 + { "br-b-4e.a", 0x02000, 0x3662e8fb, BRF_GRA }, // 21 + + { "br-c-1b", 0x02000, 0x8088911e, BRF_GRA }, // 22 Chars + { "br-c-1c", 0x02000, 0x3d78b653, BRF_GRA }, // 23 + + { "br-c-3j", 0x00100, 0xaceaed79, BRF_GRA }, // 24 PROM (Tile Palette Red Component) + { "br-b-1m", 0x00100, 0x3bd30c7d, BRF_GRA }, // 25 PROM (Sprite Palette Red Component) + { "br-c-3l", 0x00100, 0x7cf6f380, BRF_GRA }, // 26 PROM (Tile Palette Green Component) + { "br-b-1n", 0x00100, 0xb7f3dc3b, BRF_GRA }, // 27 PROM (Sprite Palette Green Component) + { "br-c-3k", 0x00100, 0xd90e4a54, BRF_GRA }, // 28 PROM (Tile Palette Blue Component) + { "br-b-1l", 0x00100, 0x5271c7d8, BRF_GRA }, // 29 PROM (Sprite Palette Blue Component) + { "br-b-5p", 0x00020, 0xce746937, BRF_GRA }, // 30 PROM (Sprite Height) + { "br-b-6f", 0x00100, 0x82c20d12, BRF_GRA }, // 31 PROM (Video Timing) + { "br-c-1j", 0x00020, 0x78eb5d77, BRF_GRA }, // 32 PROM (Char Palette) +}; + +STD_ROM_PICK(Battroad) +STD_ROM_FN(Battroad) + +static struct BurnRomInfo LdrunRomDesc[] = { + { "lr-a-4e", 0x02000, 0x5d7e2a4d, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr-a-4d", 0x02000, 0x96f20473, BRF_ESS | BRF_PRG }, // 1 + { "lr-a-4b", 0x02000, 0xb041c4a9, BRF_ESS | BRF_PRG }, // 2 + { "lr-a-4a", 0x02000, 0x645e42aa, BRF_ESS | BRF_PRG }, // 3 + + { "lr-a-3f", 0x02000, 0x7a96accd, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "lr-a-3h", 0x02000, 0x3f7f3939, BRF_ESS | BRF_PRG }, // 5 + + { "lr-e-2d", 0x02000, 0x24f9b58d, BRF_GRA }, // 6 Characters + { "lr-e-2j", 0x02000, 0x43175e08, BRF_GRA }, // 7 + { "lr-e-2f", 0x02000, 0xe0317124, BRF_GRA }, // 8 + + { "lr-b-4k", 0x02000, 0x8141403e, BRF_GRA }, // 9 Sprites + { "lr-b-3n", 0x02000, 0x55154154, BRF_GRA }, // 10 + { "lr-b-4c", 0x02000, 0x924e34d0, BRF_GRA }, // 11 + + { "lr-e-3m", 0x00100, 0x53040416, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "lr-b-1m", 0x00100, 0x4bae1c25, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "lr-e-3l", 0x00100, 0x67786037, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "lr-b-1n", 0x00100, 0x9cd3db94, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "lr-e-3n", 0x00100, 0x5b716837, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "lr-b-1l", 0x00100, 0x08d8cf9a, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "lr-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 26 PROM (Sprite Height) + { "lr-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 27 PROM (Video Timing) +}; + +STD_ROM_PICK(Ldrun) +STD_ROM_FN(Ldrun) + +static struct BurnRomInfo LdrunaRomDesc[] = { + { "roma4c", 0x02000, 0x279421e1, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr-a-4d", 0x02000, 0x96f20473, BRF_ESS | BRF_PRG }, // 1 + { "roma4b", 0x02000, 0x3c464bad, BRF_ESS | BRF_PRG }, // 2 + { "roma4a", 0x02000, 0x899df8e0, BRF_ESS | BRF_PRG }, // 3 + + { "lr-a-3f", 0x02000, 0x7a96accd, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "lr-a-3h", 0x02000, 0x3f7f3939, BRF_ESS | BRF_PRG }, // 5 + + { "lr-e-2d", 0x02000, 0x24f9b58d, BRF_GRA }, // 6 Characters + { "lr-e-2j", 0x02000, 0x43175e08, BRF_GRA }, // 7 + { "lr-e-2f", 0x02000, 0xe0317124, BRF_GRA }, // 8 + + { "lr-b-4k", 0x02000, 0x8141403e, BRF_GRA }, // 9 Sprites + { "lr-b-3n", 0x02000, 0x55154154, BRF_GRA }, // 10 + { "lr-b-4c", 0x02000, 0x924e34d0, BRF_GRA }, // 11 + + { "lr-e-3m", 0x00100, 0x53040416, BRF_GRA }, // 20 PROM (Tile Palette Red Component) + { "lr-b-1m", 0x00100, 0x4bae1c25, BRF_GRA }, // 21 PROM (Sprite Palette Red Component) + { "lr-e-3l", 0x00100, 0x67786037, BRF_GRA }, // 22 PROM (Tile Palette Green Component) + { "lr-b-1n", 0x00100, 0x9cd3db94, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "lr-e-3n", 0x00100, 0x5b716837, BRF_GRA }, // 24 PROM (Tile Palette Blue Component) + { "lr-b-1l", 0x00100, 0x08d8cf9a, BRF_GRA }, // 25 PROM (Sprite Palette Blue Component) + { "lr-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 26 PROM (Sprite Height) + { "lr-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 27 PROM (Video Timing) +}; + +STD_ROM_PICK(Ldruna) +STD_ROM_FN(Ldruna) + +static struct BurnRomInfo Ldrun2RomDesc[] = { + { "lr2-a-4e.a", 0x02000, 0x22313327, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr2-a-4d", 0x02000, 0xef645179, BRF_ESS | BRF_PRG }, // 1 + { "lr2-a-4a.a", 0x02000, 0xb11ddf59, BRF_ESS | BRF_PRG }, // 2 + { "lr2-a-4a", 0x02000, 0x470cc8a1, BRF_ESS | BRF_PRG }, // 3 + { "lr2-h-1c.a", 0x02000, 0x7ebcadbc, BRF_ESS | BRF_PRG }, // 4 + { "lr2-h-1d.a", 0x02000, 0x64cbb7f9, BRF_ESS | BRF_PRG }, // 5 + + { "lr2-a-3e", 0x02000, 0x853f3898, BRF_ESS | BRF_PRG }, // 6 M6803 Program Code + { "lr2-a-3f", 0x02000, 0x7a96accd, BRF_ESS | BRF_PRG }, // 7 + { "lr2-a-3h", 0x02000, 0x2a0e83ca, BRF_ESS | BRF_PRG }, // 8 + + { "lr2-h-1e", 0x02000, 0x9d63a8ff, BRF_GRA }, // 9 Characters + { "lr2-h-1j", 0x02000, 0x40332bbd, BRF_GRA }, // 10 + { "lr2-h-1h", 0x02000, 0x9404727d, BRF_GRA }, // 11 + + { "lr2-b-4k", 0x02000, 0x79909871, BRF_GRA }, // 12 Sprites + { "lr2-b-4f", 0x02000, 0x06ba1ef4, BRF_GRA }, // 13 + { "lr2-b-3n", 0x02000, 0x3cc5893f, BRF_GRA }, // 14 + { "lr2-b-4n", 0x02000, 0x49c12f42, BRF_GRA }, // 15 + { "lr2-b-4c", 0x02000, 0xfbe6d24c, BRF_GRA }, // 16 + { "lr2-b-4e", 0x02000, 0x75172d1f, BRF_GRA }, // 17 + + { "lr2-h-3m", 0x00100, 0x2c5d834b, BRF_GRA }, // 18 PROM (Tile Palette Red Component) + { "lr2-b-1m", 0x00100, 0x4ec9bb3d, BRF_GRA }, // 19 PROM (Sprite Palette Red Component) + { "lr2-h-3l", 0x00100, 0x3ae69aca, BRF_GRA }, // 20 PROM (Tile Palette Green Component) + { "lr2-b-1n", 0x00100, 0x1daf1fa4, BRF_GRA }, // 21 PROM (Sprite Palette Green Component) + { "lr2-h-3n", 0x00100, 0x2b28aec5, BRF_GRA }, // 22 PROM (Tile Palette Blue Component) + { "lr2-b-1l", 0x00100, 0xc8fb708a, BRF_GRA }, // 23 PROM (Sprite Palette Blue Component) + { "lr2-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 24 PROM (Sprite Height) + { "lr2-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 25 PROM (Video Timing) +}; + +STD_ROM_PICK(Ldrun2) +STD_ROM_FN(Ldrun2) + +static struct BurnRomInfo Ldrun3RomDesc[] = { + { "lr3a4eb.bin", 0x04000, 0x09affc47, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr3a4db.bin", 0x04000, 0x23a02178, BRF_ESS | BRF_PRG }, // 1 + { "lr3a4bb.bin", 0x04000, 0x3d501a1a, BRF_ESS | BRF_PRG }, // 2 + + { "lr3-a-3d", 0x04000, 0x28be68cd, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + { "lr3-a-3f", 0x04000, 0xcb7186b7, BRF_ESS | BRF_PRG }, // 4 + + { "lr3-n-2a", 0x04000, 0xf9b74dee, BRF_GRA }, // 5 Characters + { "lr3-n-2c", 0x04000, 0xfef707ba, BRF_GRA }, // 6 + { "lr3-n-2b", 0x04000, 0xaf3d27b9, BRF_GRA }, // 7 + + { "lr3b4kb.bin", 0x04000, 0x21ecd8c5, BRF_GRA }, // 8 Sprites + { "snxb4fb.bin", 0x04000, 0xed719d7b, BRF_GRA }, // 9 + { "lr3b3nb.bin", 0x04000, 0xda8cffab, BRF_GRA }, // 10 + { "snxb4nb.bin", 0x04000, 0xdc675003, BRF_GRA }, // 11 + { "snxb4cb.bin", 0x04000, 0x585aa244, BRF_GRA }, // 12 + { "snxb4eb.bin", 0x04000, 0x2d3b69dd, BRF_GRA }, // 13 + + { "lr3-n-2l", 0x00100, 0xe880b86b, BRF_GRA }, // 14 PROM (Tile Palette Red Component) + { "lr3-b-1m", 0x00100, 0xf02d7167, BRF_GRA }, // 15 PROM (Sprite Palette Red Component) + { "lr3-n-2k", 0x00100, 0x047ee051, BRF_GRA }, // 16 PROM (Tile Palette Green Component) + { "lr3-b-1n", 0x00100, 0x9e37f181, BRF_GRA }, // 17 PROM (Sprite Palette Green Component) + { "lr3-n-2m", 0x00100, 0x69ad8678, BRF_GRA }, // 18 PROM (Tile Palette Blue Component) + { "lr3-b-1l", 0x00100, 0x5b11c41d, BRF_GRA }, // 19 PROM (Sprite Palette Blue Component) + { "lr3-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 20 PROM (Sprite Height) + { "lr3-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 21 PROM (Video Timing) + { "lr3-n-4f", 0x00100, 0xdf674be9, BRF_OPT }, // 22 PROM (Unknown) +}; + +STD_ROM_PICK(Ldrun3) +STD_ROM_FN(Ldrun3) + +static struct BurnRomInfo Ldrun3jRomDesc[] = { + { "lr3-a-4e", 0x04000, 0x5b334e8e, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr3-a-4d.a", 0x04000, 0xa84bc931, BRF_ESS | BRF_PRG }, // 1 + { "lr3-a-4b.a", 0x04000, 0xbe09031d, BRF_ESS | BRF_PRG }, // 2 + + { "lr3-a-3d", 0x04000, 0x28be68cd, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + { "lr3-a-3f", 0x04000, 0xcb7186b7, BRF_ESS | BRF_PRG }, // 4 + + { "lr3-n-2a", 0x04000, 0xf9b74dee, BRF_GRA }, // 5 Characters + { "lr3-n-2c", 0x04000, 0xfef707ba, BRF_GRA }, // 6 + { "lr3-n-2b", 0x04000, 0xaf3d27b9, BRF_GRA }, // 7 + + { "lr3-b-4k", 0x04000, 0x63f070c7, BRF_GRA }, // 8 Sprites + { "lr3-b-3n", 0x04000, 0xeab7ad91, BRF_GRA }, // 9 + { "lr3-b-4c", 0x04000, 0x1a460a46, BRF_GRA }, // 10 + + { "lr3-n-2l", 0x00100, 0xe880b86b, BRF_GRA }, // 11 PROM (Tile Palette Red Component) + { "lr3-b-1m", 0x00100, 0xf02d7167, BRF_GRA }, // 12 PROM (Sprite Palette Red Component) + { "lr3-n-2k", 0x00100, 0x047ee051, BRF_GRA }, // 13 PROM (Tile Palette Green Component) + { "lr3-b-1n", 0x00100, 0x9e37f181, BRF_GRA }, // 14 PROM (Sprite Palette Green Component) + { "lr3-n-2m", 0x00100, 0x69ad8678, BRF_GRA }, // 15 PROM (Tile Palette Blue Component) + { "lr3-b-1l", 0x00100, 0x5b11c41d, BRF_GRA }, // 16 PROM (Sprite Palette Blue Component) + { "lr3-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 17 PROM (Sprite Height) + { "lr3-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 18 PROM (Video Timing) + { "lr3-n-4f", 0x00100, 0xdf674be9, BRF_OPT }, // 19 PROM (Unknown) +}; + +STD_ROM_PICK(Ldrun3j) +STD_ROM_FN(Ldrun3j) + +static struct BurnRomInfo Ldrun4RomDesc[] = { + { "lr4-a-4e", 0x04000, 0x5383e9bf, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lr4-a-4d.c", 0x04000, 0x298afa36, BRF_ESS | BRF_PRG }, // 1 + { "lr4-v-4k", 0x08000, 0x8b248abd, BRF_ESS | BRF_PRG }, // 2 + + { "lr4-a-3d", 0x04000, 0x86c6d445, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + { "lr4-a-3f", 0x04000, 0x097c6c0a, BRF_ESS | BRF_PRG }, // 4 + + { "lr4-v-2b", 0x04000, 0x4118e60a, BRF_GRA }, // 5 Characters + { "lr4-v-2d", 0x04000, 0x542bb5b5, BRF_GRA }, // 6 + { "lr4-v-2c", 0x04000, 0xc765266c, BRF_GRA }, // 7 + + { "lr4-b-4k", 0x04000, 0xe7fe620c, BRF_GRA }, // 8 Sprites + { "lr4-b-4f", 0x04000, 0x6f0403db, BRF_GRA }, // 9 + { "lr4-b-3n", 0x04000, 0xad1fba1b, BRF_GRA }, // 10 + { "lr4-b-4n", 0x04000, 0x0e568fab, BRF_GRA }, // 11 + { "lr4-b-4c", 0x04000, 0x82c53669, BRF_GRA }, // 12 + { "lr4-b-4e", 0x04000, 0x767a1352, BRF_GRA }, // 13 + + { "lr4-v-1m", 0x00100, 0xfe51bf1d, BRF_GRA }, // 14 PROM (Tile Palette Red Component) + { "lr4-b-1m", 0x00100, 0x5d8d17d0, BRF_GRA }, // 15 PROM (Sprite Palette Red Component) + { "lr4-v-1n", 0x00100, 0xda0658e5, BRF_GRA }, // 16 PROM (Tile Palette Green Component) + { "lr4-b-1n", 0x00100, 0xda1129d2, BRF_GRA }, // 17 PROM (Sprite Palette Green Component) + { "lr4-v-1p", 0x00100, 0x0df23ebe, BRF_GRA }, // 18 PROM (Tile Palette Blue Component) + { "lr4-b-1l", 0x00100, 0x0d89b692, BRF_GRA }, // 19 PROM (Sprite Palette Blue Component) + { "lr4-b-5p", 0x00020, 0xe01f69e2, BRF_GRA }, // 20 PROM (Sprite Height) + { "lr4-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 21 PROM (Video Timing) + { "lr4-v-4h", 0x00100, 0xdf674be9, BRF_OPT }, // 22 PROM (Unknown) +}; + +STD_ROM_PICK(Ldrun4) +STD_ROM_FN(Ldrun4) + +static struct BurnRomInfo LotlotRomDesc[] = { + { "lot-a-4e", 0x04000, 0x2913d08f, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "lot-a-4d", 0x04000, 0x0443095f, BRF_ESS | BRF_PRG }, // 1 + + { "lot-a-3h", 0x02000, 0x0781cee7, BRF_ESS | BRF_PRG }, // 2 M6803 Program Code + + { "lot-k-4a", 0x02000, 0x1b3695f4, BRF_GRA }, // 3 Tiles + { "lot-k-4c", 0x02000, 0xbd2b0730, BRF_GRA }, // 4 + { "lot-k-4b", 0x02000, 0x930ddd55, BRF_GRA }, // 5 + + { "lot-b-4k", 0x02000, 0xfd27cb90, BRF_GRA }, // 6 Sprites + { "lot-b-3n", 0x02000, 0xbd486fff, BRF_GRA }, // 7 + { "lot-b-4c", 0x02000, 0x3026ee6c, BRF_GRA }, // 8 + + { "lot-k-4p", 0x02000, 0x3b7d95ba, BRF_GRA }, // 9 Characters + { "lot-k-4l", 0x02000, 0xf98dca1f, BRF_GRA }, // 10 + { "lot-k-4n", 0x02000, 0xf0cd76a5, BRF_GRA }, // 11 + + { "lot-k-2f", 0x00100, 0xb820a05e, BRF_GRA }, // 12 PROM (Tile Palette Red Component) + { "lot-b-1m", 0x00100, 0xc146461d, BRF_GRA }, // 13 PROM (Sprite Palette Red Component) + { "lot-k-2l", 0x00100, 0xac3e230d, BRF_GRA }, // 14 PROM (Char Palette Red Component) + { "lot-k-2e", 0x00100, 0x9b1fa005, BRF_GRA }, // 15 PROM (Tile Palette Green Component) + { "lot-b-1n", 0x00100, 0x01e07db6, BRF_GRA }, // 16 PROM (Sprite Palette Green Component) + { "lot-k-2k", 0x00100, 0x1811ad2b, BRF_GRA }, // 17 PROM (Char Palette Green Component) + { "lot-k-2d", 0x00100, 0x315ed9a8, BRF_GRA }, // 18 PROM (Tile Palette Blue Component) + { "lot-b-1l", 0x00100, 0x8b6fcde3, BRF_GRA }, // 19 PROM (Sprite Palette Blue Component) + { "lot-k-2j", 0x00100, 0xe791ef2a, BRF_GRA }, // 20 PROM (Char Palette Blue Component) + { "lot-b-5p", 0x00020, 0x110b21fd, BRF_GRA }, // 21 PROM (Sprite Height) + { "lot-b-6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 22 PROM (Video Timing) + { "lot-k-7e", 0x00200, 0x6cef0fbd, BRF_GRA }, // 23 PROM (Unknown) + { "lot-k-7h", 0x00200, 0x04442bee, BRF_GRA }, // 24 PROM (Unknown) +}; + +STD_ROM_PICK(Lotlot) +STD_ROM_FN(Lotlot) + +static struct BurnRomInfo KidnikiRomDesc[] = { + { "ky_a-4e-g.bin", 0x04000, 0x2edcbcd7, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "dr03.4cd", 0x04000, 0xdba20934, BRF_ESS | BRF_PRG }, // 1 + { "ky_t-8k-g.bin", 0x08000, 0xdbc42f31, BRF_ESS | BRF_PRG }, // 2 + { "dr12.8l", 0x10000, 0xc0b255fd, BRF_ESS | BRF_PRG }, // 3 + + { "dr00.3a", 0x04000, 0x458309f7, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "dr01.3cd", 0x04000, 0xe66897bd, BRF_ESS | BRF_PRG }, // 5 + { "dr02.3f", 0x04000, 0xf9e31e26, BRF_ESS | BRF_PRG }, // 6 + + { "dr06.2b", 0x08000, 0x4d9a970f, BRF_GRA }, // 7 Tiles + { "dr07.2dc", 0x08000, 0xab59a4c4, BRF_GRA }, // 8 + { "dr05.2a", 0x08000, 0x2e6dad0c, BRF_GRA }, // 9 + + { "dr21.4k", 0x04000, 0xa06cea9a, BRF_GRA }, // 10 Sprites + { "dr19.4f", 0x04000, 0xb34605ad, BRF_GRA }, // 11 + { "dr22.4l", 0x04000, 0x41303de8, BRF_GRA }, // 12 + { "dr20.4jh", 0x04000, 0x5fbe6f61, BRF_GRA }, // 13 + { "dr14.3p", 0x04000, 0x76cfbcbc, BRF_GRA }, // 14 + { "dr24.4p", 0x04000, 0xd51c8db5, BRF_GRA }, // 15 + { "dr23.4nm", 0x04000, 0x03469df8, BRF_GRA }, // 16 + { "dr13.3nm", 0x04000, 0xd5c3dfe0, BRF_GRA }, // 17 + { "dr16.4cb", 0x04000, 0xf1d1bb93, BRF_GRA }, // 18 + { "dr18.4e", 0x04000, 0xedb7f25b, BRF_GRA }, // 19 + { "dr17.4dc", 0x04000, 0x4fb87868, BRF_GRA }, // 20 + { "dr15.4a", 0x04000, 0xe0b88de5, BRF_GRA }, // 21 + + { "dr08.4l", 0x04000, 0x32d50643, BRF_GRA }, // 22 Characters + { "dr09.4m", 0x04000, 0x17df6f95, BRF_GRA }, // 23 + { "dr10.4n", 0x04000, 0x820ce252, BRF_GRA }, // 24 + + { "dr25.3f", 0x00100, 0x8e91430b, BRF_GRA }, // 25 PROM (Tile Palette Red Component) + { "dr30.1m", 0x00100, 0x28c73263, BRF_GRA }, // 26 PROM (Sprite Palette Red Component) + { "dr26.3h", 0x00100, 0xb563b93f, BRF_GRA }, // 27 PROM (Tile Palette Green Component) + { "dr31.1n", 0x00100, 0x3529210e, BRF_GRA }, // 28 PROM (Sprite Palette Green Component) + { "dr27.3j", 0x00100, 0x70d668ef, BRF_GRA }, // 29 PROM (Tile Palette Blue Component) + { "dr29.1l", 0x00100, 0x1173a754, BRF_GRA }, // 30 PROM (Sprite Palette Blue Component) + { "dr32.5p", 0x00020, 0x11cd1f2e, BRF_GRA }, // 31 PROM (Sprite Height) + { "dr33.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 32 PROM (Video Timing) + { "dr28.8f", 0x00200, 0x6cef0fbd, BRF_OPT }, // 33 PROM (Unknown) +}; + +STD_ROM_PICK(Kidniki) +STD_ROM_FN(Kidniki) + +static struct BurnRomInfo KidnikiuRomDesc[] = { + { "dr04.4e", 0x04000, 0x80431858, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "dr03.4cd", 0x04000, 0xdba20934, BRF_ESS | BRF_PRG }, // 1 + { "dr11.8k", 0x08000, 0x04d82d93, BRF_ESS | BRF_PRG }, // 2 + { "dr12.8l", 0x10000, 0xc0b255fd, BRF_ESS | BRF_PRG }, // 3 + + { "dr00.3a", 0x04000, 0x458309f7, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "dr01.3cd", 0x04000, 0xe66897bd, BRF_ESS | BRF_PRG }, // 5 + { "dr02.3f", 0x04000, 0xf9e31e26, BRF_ESS | BRF_PRG }, // 6 + + { "dr06.2b", 0x08000, 0x4d9a970f, BRF_GRA }, // 7 Tiles + { "dr07.2dc", 0x08000, 0xab59a4c4, BRF_GRA }, // 8 + { "dr05.2a", 0x08000, 0x2e6dad0c, BRF_GRA }, // 9 + + { "dr21.4k", 0x04000, 0xa06cea9a, BRF_GRA }, // 10 Sprites + { "dr19.4f", 0x04000, 0xb34605ad, BRF_GRA }, // 11 + { "dr22.4l", 0x04000, 0x41303de8, BRF_GRA }, // 12 + { "dr20.4jh", 0x04000, 0x5fbe6f61, BRF_GRA }, // 13 + { "dr14.3p", 0x04000, 0x76cfbcbc, BRF_GRA }, // 14 + { "dr24.4p", 0x04000, 0xd51c8db5, BRF_GRA }, // 15 + { "dr23.4nm", 0x04000, 0x03469df8, BRF_GRA }, // 16 + { "dr13.3nm", 0x04000, 0xd5c3dfe0, BRF_GRA }, // 17 + { "dr16.4cb", 0x04000, 0xf1d1bb93, BRF_GRA }, // 18 + { "dr18.4e", 0x04000, 0xedb7f25b, BRF_GRA }, // 19 + { "dr17.4dc", 0x04000, 0x4fb87868, BRF_GRA }, // 20 + { "dr15.4a", 0x04000, 0xe0b88de5, BRF_GRA }, // 21 + + { "dr08.4l", 0x04000, 0x32d50643, BRF_GRA }, // 22 Characters + { "dr09.4m", 0x04000, 0x17df6f95, BRF_GRA }, // 23 + { "dr10.4n", 0x04000, 0x820ce252, BRF_GRA }, // 24 + + { "dr25.3f", 0x00100, 0x8e91430b, BRF_GRA }, // 25 PROM (Tile Palette Red Component) + { "dr30.1m", 0x00100, 0x28c73263, BRF_GRA }, // 26 PROM (Sprite Palette Red Component) + { "dr26.3h", 0x00100, 0xb563b93f, BRF_GRA }, // 27 PROM (Tile Palette Green Component) + { "dr31.1n", 0x00100, 0x3529210e, BRF_GRA }, // 28 PROM (Sprite Palette Green Component) + { "dr27.3j", 0x00100, 0x70d668ef, BRF_GRA }, // 29 PROM (Tile Palette Blue Component) + { "dr29.1l", 0x00100, 0x1173a754, BRF_GRA }, // 30 PROM (Sprite Palette Blue Component) + { "dr32.5p", 0x00020, 0x11cd1f2e, BRF_GRA }, // 31 PROM (Sprite Height) + { "dr33.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 32 PROM (Video Timing) + { "dr28.8f", 0x00200, 0x6cef0fbd, BRF_OPT }, // 33 PROM (Unknown) +}; + +STD_ROM_PICK(Kidnikiu) +STD_ROM_FN(Kidnikiu) + +static struct BurnRomInfo YanchamrRomDesc[] = { + { "ky_a-4e-.bin", 0x04000, 0xc73ad2d6, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "ky_a-4d-.bin", 0x04000, 0x401af828, BRF_ESS | BRF_PRG }, // 1 + { "ky_t-8k-.bin", 0x08000, 0xe967de88, BRF_ESS | BRF_PRG }, // 2 + { "ky_t-8l-.bin", 0x08000, 0xa929110b, BRF_ESS | BRF_PRG }, // 3 + + { "ky_a-3a-.bin", 0x04000, 0xcb365f3b, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "dr01.3cd", 0x04000, 0xe66897bd, BRF_ESS | BRF_PRG }, // 5 + { "dr02.3f", 0x04000, 0xf9e31e26, BRF_ESS | BRF_PRG }, // 6 + + { "ky_t-2c-.bin", 0x08000, 0xcb9761fc, BRF_GRA }, // 7 Tiles + { "ky_t-2d-.bin", 0x08000, 0x59732741, BRF_GRA }, // 8 + { "ky_t-2a-.bin", 0x08000, 0x0370fd82, BRF_GRA }, // 9 + + { "ky_b-4k-.bin", 0x04000, 0x263a9d10, BRF_GRA }, // 10 Sprites + { "ky_b-4f-.bin", 0x04000, 0x86e3d4a8, BRF_GRA }, // 11 + { "ky_b-4l-.bin", 0x04000, 0x19fa7558, BRF_GRA }, // 12 + { "ky_b-4h-.bin", 0x04000, 0x93e6665c, BRF_GRA }, // 13 + { "ky_b-3n-.bin", 0x04000, 0x0287c525, BRF_GRA }, // 14 + { "ky_b-4n-.bin", 0x04000, 0x764946e0, BRF_GRA }, // 15 + { "ky_b-4m-.bin", 0x04000, 0xeced5db9, BRF_GRA }, // 16 + { "ky_b-3m-.bin", 0x04000, 0xbe6cee44, BRF_GRA }, // 17 + { "ky_b-4c-.bin", 0x04000, 0x84d6b65d, BRF_GRA }, // 18 + { "ky_b-4e-.bin", 0x04000, 0xf91f9273, BRF_GRA }, // 19 + { "ky_b-4d-.bin", 0x04000, 0xa2fc15f0, BRF_GRA }, // 20 + { "ky_b-4a-.bin", 0x04000, 0xff2b9c8a, BRF_GRA }, // 21 + + { "ky_t-4l-.bin", 0x04000, 0x1d0a9253, BRF_GRA }, // 22 Characters + { "ky_t-4m-.bin", 0x04000, 0x4075c396, BRF_GRA }, // 23 + { "ky_t-4n-.bin", 0x04000, 0x7564f2ff, BRF_GRA }, // 24 + + { "dr25.3f", 0x00100, 0x8e91430b, BRF_GRA }, // 25 PROM (Tile Palette Red Component) + { "dr30.1m", 0x00100, 0x28c73263, BRF_GRA }, // 26 PROM (Sprite Palette Red Component) + { "dr26.3h", 0x00100, 0xb563b93f, BRF_GRA }, // 27 PROM (Tile Palette Green Component) + { "dr31.1n", 0x00100, 0x3529210e, BRF_GRA }, // 28 PROM (Sprite Palette Green Component) + { "dr27.3j", 0x00100, 0x70d668ef, BRF_GRA }, // 29 PROM (Tile Palette Blue Component) + { "dr29.1l", 0x00100, 0x1173a754, BRF_GRA }, // 30 PROM (Sprite Palette Blue Component) + { "dr32.5p", 0x00020, 0x11cd1f2e, BRF_GRA }, // 31 PROM (Sprite Height) + { "dr33.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 32 PROM (Video Timing) + { "dr28.8f", 0x00200, 0x6cef0fbd, BRF_OPT }, // 33 PROM (Unknown) +}; + +STD_ROM_PICK(Yanchamr) +STD_ROM_FN(Yanchamr) + +static struct BurnRomInfo LitheroRomDesc[] = { + { "4.bin", 0x08000, 0x80903766, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "11.bin", 0x08000, 0x7a1ef8cb, BRF_ESS | BRF_PRG }, // 1 + { "12.bin", 0x08000, 0xa929110b, BRF_ESS | BRF_PRG }, // 2 + + { "ky_a-3a-.bin", 0x04000, 0xcb365f3b, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + { "dr01.3cd", 0x04000, 0xe66897bd, BRF_ESS | BRF_PRG }, // 4 + { "dr02.3f", 0x04000, 0xf9e31e26, BRF_ESS | BRF_PRG }, // 5 + + { "7.bin", 0x08000, 0xb55e8d19, BRF_GRA }, // 6 Tiles + { "6.bin", 0x08000, 0x7bbbb209, BRF_GRA }, // 7 + { "5.bin", 0x08000, 0x0370fd82, BRF_GRA }, // 8 + + { "16.bin", 0x08000, 0x5045a507, BRF_GRA }, // 9 Sprites + { "15.bin", 0x08000, 0x946b16a0, BRF_GRA }, // 10 + { "18.bin", 0x08000, 0x901b69ff, BRF_GRA }, // 11 + { "17.bin", 0x08000, 0x504eed93, BRF_GRA }, // 12 + { "14.bin", 0x08000, 0x429d760b, BRF_GRA }, // 13 + { "13.bin", 0x08000, 0x1700cd64, BRF_GRA }, // 14 + + { "8.bin", 0x04000, 0x4f388d63, BRF_GRA }, // 15 Characters + { "9.bin", 0x04000, 0xdaafa2c1, BRF_GRA }, // 16 + { "10.bin", 0x04000, 0x60649d19, BRF_GRA }, // 17 + + { "dr25.3f", 0x00100, 0x8e91430b, BRF_GRA }, // 18 PROM (Tile Palette Red Component) + { "dr30.1m", 0x00100, 0x28c73263, BRF_GRA }, // 19 PROM (Sprite Palette Red Component) + { "dr26.3h", 0x00100, 0xb563b93f, BRF_GRA }, // 20 PROM (Tile Palette Green Component) + { "dr31.1n", 0x00100, 0x3529210e, BRF_GRA }, // 21 PROM (Sprite Palette Green Component) + { "dr27.3j", 0x00100, 0x70d668ef, BRF_GRA }, // 22 PROM (Tile Palette Blue Component) + { "dr29.1l", 0x00100, 0x1173a754, BRF_GRA }, // 23 PROM (Sprite Palette Blue Component) + { "dr32.5p", 0x00020, 0x11cd1f2e, BRF_GRA }, // 24 PROM (Sprite Height) + { "dr33.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 25 PROM (Video Timing) + { "dr28.8f", 0x00200, 0x6cef0fbd, BRF_OPT }, // 26 PROM (Unknown) +}; + +STD_ROM_PICK(Lithero) +STD_ROM_FN(Lithero) + +static struct BurnRomInfo SpelunkrRomDesc[] = { + { "spra.4e", 0x04000, 0xcf811201, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "spra.4d", 0x04000, 0xbb4faa4f, BRF_ESS | BRF_PRG }, // 1 + { "sprm.7c", 0x04000, 0xfb6197e2, BRF_ESS | BRF_PRG }, // 2 + { "sprm.7b", 0x04000, 0x26bb25a4, BRF_ESS | BRF_PRG }, // 3 + + { "spra.3d", 0x04000, 0x4110363c, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "spra.3f", 0x04000, 0x67a9d2e6, BRF_ESS | BRF_PRG }, // 5 + + { "sprm.1d", 0x04000, 0x4ef7ae89, BRF_GRA }, // 6 Tiles + { "sprm.1e", 0x04000, 0xa3755180, BRF_GRA }, // 7 + { "sprm.3c", 0x04000, 0xb4008e6a, BRF_GRA }, // 8 + { "sprm.3b", 0x04000, 0xf61cf012, BRF_GRA }, // 9 + { "sprm.1c", 0x04000, 0x58b21c76, BRF_GRA }, // 10 + { "sprm.1b", 0x04000, 0xa95cb3e5, BRF_GRA }, // 11 + + { "sprb.4k", 0x04000, 0xe7f0e861, BRF_GRA }, // 12 Sprites + { "sprb.4f", 0x04000, 0x32663097, BRF_GRA }, // 13 + { "sprb.3p", 0x04000, 0x8fbaf373, BRF_GRA }, // 14 + { "sprb.4p", 0x04000, 0x37069b76, BRF_GRA }, // 15 + { "sprb.4c", 0x04000, 0xcfe46a88, BRF_GRA }, // 16 + { "sprb.4e", 0x04000, 0x11c48979, BRF_GRA }, // 17 + + { "sprm.4p", 0x04000, 0x4dfe2e63, BRF_GRA }, // 18 Characters + { "sprm.4l", 0x04000, 0x239f2cd4, BRF_GRA }, // 19 + { "sprm.4m", 0x04000, 0xd6d07d70, BRF_GRA }, // 20 + + { "sprm.2k", 0x00100, 0xfd8fa991, BRF_GRA }, // 21 PROM (Tile Palette Red Component) + { "sprb.1m", 0x00100, 0x8d8cccad, BRF_GRA }, // 22 PROM (Sprite Palette Red Component) + { "sprm.2j", 0x00100, 0x0e3890b4, BRF_GRA }, // 23 PROM (Tile Palette Green Component) + { "sprb.1n", 0x00100, 0xc40e1cb2, BRF_GRA }, // 24 PROM (Sprite Palette Green Component) + { "sprm.2h", 0x00100, 0x0478082b, BRF_GRA }, // 25 PROM (Tile Palette Blue Component) + { "sprb.1l", 0x00100, 0x3ec46248, BRF_GRA }, // 26 PROM (Sprite Palette Blue Component) + { "sprb.5p", 0x00020, 0x746c6238, BRF_GRA }, // 27 PROM (Sprite Height) + { "sprb.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 28 PROM (Video Timing) + { "sprm.8h", 0x00200, 0x875cc442, BRF_OPT }, // 29 PROM (Unknown) +}; + +STD_ROM_PICK(Spelunkr) +STD_ROM_FN(Spelunkr) + +static struct BurnRomInfo SpelunkrjRomDesc[] = { + { "spr_a4ec.bin", 0x04000, 0x4e94a80c, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "spr_a4dd.bin", 0x04000, 0xe7c0cbce, BRF_ESS | BRF_PRG }, // 1 + { "spr_m7cc.bin", 0x04000, 0x57598a36, BRF_ESS | BRF_PRG }, // 2 + { "spr_m7bd.bin", 0x04000, 0xecf5137f, BRF_ESS | BRF_PRG }, // 3 + + { "spra.3d", 0x04000, 0x4110363c, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + { "spra.3f", 0x04000, 0x67a9d2e6, BRF_ESS | BRF_PRG }, // 5 + + { "sprm.1d", 0x04000, 0x4ef7ae89, BRF_GRA }, // 6 Tiles + { "sprm.1e", 0x04000, 0xa3755180, BRF_GRA }, // 7 + { "sprm.3c", 0x04000, 0xb4008e6a, BRF_GRA }, // 8 + { "sprm.3b", 0x04000, 0xf61cf012, BRF_GRA }, // 9 + { "sprm.1c", 0x04000, 0x58b21c76, BRF_GRA }, // 10 + { "sprm.1b", 0x04000, 0xa95cb3e5, BRF_GRA }, // 11 + + { "sprb.4k", 0x04000, 0xe7f0e861, BRF_GRA }, // 12 Sprites + { "sprb.4f", 0x04000, 0x32663097, BRF_GRA }, // 13 + { "sprb.3p", 0x04000, 0x8fbaf373, BRF_GRA }, // 14 + { "sprb.4p", 0x04000, 0x37069b76, BRF_GRA }, // 15 + { "sprb.4c", 0x04000, 0xcfe46a88, BRF_GRA }, // 16 + { "sprb.4e", 0x04000, 0x11c48979, BRF_GRA }, // 17 + + { "sprm.4p", 0x04000, 0x4dfe2e63, BRF_GRA }, // 18 Characters + { "sprm.4l", 0x04000, 0x239f2cd4, BRF_GRA }, // 19 + { "sprm.4m", 0x04000, 0xd6d07d70, BRF_GRA }, // 20 + + { "sprm.2k", 0x00100, 0xfd8fa991, BRF_GRA }, // 21 PROM (Tile Palette Red Component) + { "sprb.1m", 0x00100, 0x8d8cccad, BRF_GRA }, // 22 PROM (Sprite Palette Red Component) + { "sprm.2j", 0x00100, 0x0e3890b4, BRF_GRA }, // 23 PROM (Tile Palette Green Component) + { "sprb.1n", 0x00100, 0xc40e1cb2, BRF_GRA }, // 24 PROM (Sprite Palette Green Component) + { "sprm.2h", 0x00100, 0x0478082b, BRF_GRA }, // 25 PROM (Tile Palette Blue Component) + { "sprb.1l", 0x00100, 0x3ec46248, BRF_GRA }, // 26 PROM (Sprite Palette Blue Component) + { "sprb.5p", 0x00020, 0x746c6238, BRF_GRA }, // 27 PROM (Sprite Height) + { "sprb.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 28 PROM (Video Timing) + { "sprm.8h", 0x00200, 0x875cc442, BRF_OPT }, // 29 PROM (Unknown) +}; + +STD_ROM_PICK(Spelunkrj) +STD_ROM_FN(Spelunkrj) + +static struct BurnRomInfo Spelunk2RomDesc[] = { + { "sp2-a.4e", 0x04000, 0x96c04bbb, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "sp2-a.4d", 0x04000, 0xcb38c2ff, BRF_ESS | BRF_PRG }, // 1 + { "sp2-r.7d", 0x08000, 0x558837ea, BRF_ESS | BRF_PRG }, // 2 + { "sp2-r.7c", 0x08000, 0x4b380162, BRF_ESS | BRF_PRG }, // 3 + { "sp2-r.7b", 0x04000, 0x7709a1fe, BRF_ESS | BRF_PRG }, // 4 + + { "sp2-a.3d", 0x04000, 0x839ec7e2, BRF_ESS | BRF_PRG }, // 5 M6803 Program Code + { "sp2-a.3f", 0x04000, 0xad3ce898, BRF_ESS | BRF_PRG }, // 6 + + { "sp2-r.1d", 0x08000, 0xc19fa4c9, BRF_GRA }, // 7 Tiles + { "sp2-r.3b", 0x08000, 0x366604af, BRF_GRA }, // 8 + { "sp2-r.1b", 0x08000, 0x3a0c4d47, BRF_GRA }, // 9 + + { "sp2-b.4k", 0x04000, 0x6cb67a17, BRF_GRA }, // 10 Sprites + { "sp2-b.4f", 0x04000, 0xe4a1166f, BRF_GRA }, // 11 + { "sp2-b.3n", 0x04000, 0xf59e8b76, BRF_GRA }, // 12 + { "sp2-b.4n", 0x04000, 0xfa65bac9, BRF_GRA }, // 13 + { "sp2-b.4c", 0x04000, 0x1caf7013, BRF_GRA }, // 14 + { "sp2-b.4e", 0x04000, 0x780a463b, BRF_GRA }, // 15 + + { "sp2-r.4l", 0x04000, 0x6a4b2d8b, BRF_GRA }, // 16 Characters + { "sp2-r.4m", 0x04000, 0xe1368b61, BRF_GRA }, // 17 + { "sp2-r.4p", 0x04000, 0xfc138e13, BRF_GRA }, // 18 + + { "sp2-r.1k", 0x00200, 0x31c1bcdc, BRF_GRA }, // 19 PROM (Char Palette Red and Green Component) + { "sp2-r.2k", 0x00100, 0x1cf5987e, BRF_GRA }, // 20 PROM (Char Palette Blue Component) + { "sp2-r.2j", 0x00100, 0x1acbe2a5, BRF_GRA }, // 21 PROM (Char Palette Blue Component) + { "sp2-b.1m", 0x00100, 0x906104c7, BRF_GRA }, // 22 PROM (Sprite Palette Red Component) + { "sp2-b.1n", 0x00100, 0x5a564c06, BRF_GRA }, // 23 PROM (Sprite Palette Green Component) + { "sp2-b.1l", 0x00100, 0x8f4a2e3c, BRF_GRA }, // 24 PROM (Sprite Palette Blue Component) + { "sp2-b.5p", 0x00020, 0xcd126f6a, BRF_GRA }, // 25 PROM (Sprite Height) + { "sp2-b.6f", 0x00100, 0x34d88d3c, BRF_GRA }, // 26 PROM (Video Timing) + { "sp2-r.8j", 0x00200, 0x875cc442, BRF_OPT }, // 27 PROM (Unknown) + + { "ampal16r4a-sp2-r-3h.bin", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, // 28 PAL +}; + +STD_ROM_PICK(Spelunk2) +STD_ROM_FN(Spelunk2) + +static struct BurnRomInfo YoujyudnRomDesc[] = { + { "yju_a4eb.bin", 0x04000, 0x0d356bdc, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "yju_a4db.bin", 0x04000, 0xc169be13, BRF_ESS | BRF_PRG }, // 1 + { "yju_p4cb.0", 0x04000, 0x60baf3b1, BRF_ESS | BRF_PRG }, // 2 + { "yju_p4eb.1", 0x04000, 0x8d0521f8, BRF_ESS | BRF_PRG }, // 3 + + { "yju_a3fb.bin", 0x04000, 0xe15c8030, BRF_ESS | BRF_PRG }, // 4 M6803 Program Code + + { "yju_p3bb.0", 0x08000, 0xc017913c, BRF_GRA }, // 5 Tiles + { "yju_p1bb.1", 0x08000, 0x94627523, BRF_GRA }, // 6 + { "yju_p1cb.2", 0x08000, 0x6a378c56, BRF_GRA }, // 7 + + { "yju_b4ka.00", 0x04000, 0x1bbb864a, BRF_GRA }, // 8 Sprites + { "yju_b4fa.01", 0x04000, 0x14b4dd24, BRF_GRA }, // 9 + { "yju_b3na.10", 0x04000, 0x68879321, BRF_GRA }, // 10 + { "yju_b4na.11", 0x04000, 0x2860a68b, BRF_GRA }, // 11 + { "yju_b4ca.20", 0x04000, 0xab365829, BRF_GRA }, // 12 + { "yju_b4ea.21", 0x04000, 0xb36c31e4, BRF_GRA }, // 13 + + { "yju_p4lb.2", 0x04000, 0x87878d9b, BRF_GRA }, // 14 Characters + { "yju_p4mb.1", 0x04000, 0x1e1a0d09, BRF_GRA }, // 15 + { "yju_p4pb.0", 0x04000, 0xb4ab520b, BRF_GRA }, // 16 + + { "yju_p2jb.bpr", 0x00100, 0xa4483631, BRF_GRA }, // 17 PROM (Tile Palette Red Component) + { "yju_b1ma.r", 0x00100, 0xa8340e13, BRF_GRA }, // 18 PROM (Sprite Palette Red Component) + { "yju_p2kb.bpr", 0x00100, 0x85481103, BRF_GRA }, // 19 PROM (Tile Palette Green Component) + { "yju_b1na.g", 0x00100, 0xf5b4bc41, BRF_GRA }, // 20 PROM (Sprite Palette Green Component) + { "yju_p2hb.bpr", 0x00100, 0xa6fd355c, BRF_GRA }, // 21 PROM (Tile Palette Blue Component) + { "yju_b1la.b", 0x00100, 0x45e10491, BRF_GRA }, // 22 PROM (Sprite Palette Blue Component) + { "yju_b-5p.bpr", 0x00020, 0x2095e6a3, BRF_GRA }, // 23 PROM (Sprite Height) + { "yju_b-6f.bpr", 0x00100, 0x82c20d12, BRF_GRA }, // 24 PROM (Video Timing) + { "yju_p-8d.bpr", 0x00200, 0x6cef0fbd, BRF_OPT }, // 25 PROM (Unknown) + + { "yju_b-pal16r4a-8m.pal", 0x00104, 0x3ece8e61, BRF_OPT }, // 26 PAL +}; + +STD_ROM_PICK(Youjyudn) +STD_ROM_FN(Youjyudn) + +static struct BurnRomInfo HorizonRomDesc[] = { + { "hrza-4e", 0x04000, 0x98b96ba2, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "hrza-4d", 0x04000, 0x06b06ac7, BRF_ESS | BRF_PRG }, // 1 + { "hrza-4b", 0x04000, 0x39c0bd02, BRF_ESS | BRF_PRG }, // 2 + + { "hrza-3f", 0x04000, 0x7412c99f, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + + { "hrzd-4d", 0x02000, 0xb93ed581, BRF_GRA }, // 4 Tiles + { "hrzd-4c", 0x02000, 0x1cf73b53, BRF_GRA }, // 5 + { "hrzd-4a", 0x02000, 0xeace8d53, BRF_GRA }, // 6 + + { "hrzb-4k.00", 0x04000, 0x11d2f3a1, BRF_GRA }, // 7 Sprites + { "hrzb-4f.01", 0x04000, 0x356902ea, BRF_GRA }, // 8 + { "hrzb-3n.10", 0x04000, 0x87078a02, BRF_GRA }, // 9 + { "hrzb-4n.11", 0x04000, 0x5019cb1f, BRF_GRA }, // 10 + { "hrzb-4c.20", 0x04000, 0x90b385e7, BRF_GRA }, // 11 + { "hrzb-4e.21", 0x04000, 0xd05d77a2, BRF_GRA }, // 12 + + { "hrzd-1d", 0x00100, 0xb33b08f9, BRF_GRA }, // 13 PROM (Tile Palette Red Component) + { "hrzb-1m.r", 0x00100, 0x0871690a, BRF_GRA }, // 14 PROM (Sprite Palette Red Component) + { "hrzd-1c", 0x00100, 0x6e696f3a, BRF_GRA }, // 15 PROM (Tile Palette Green Component) + { "hrzb-1n.g", 0x00100, 0xf247d0a9, BRF_GRA }, // 16 PROM (Sprite Palette Green Component) + { "hrzd-1e", 0x00100, 0x1fa60379, BRF_GRA }, // 17 PROM (Tile Palette Blue Component) + { "hrzb-1l.b", 0x00100, 0x9ad0a0c8, BRF_GRA }, // 18 PROM (Sprite Palette Blue Component) + { "hrzb-5p", 0x00020, 0x208b49e9, BRF_GRA }, // 19 PROM (Sprite Height) + { "hrzb-6f", 0x00100, 0x82c20d12, BRF_GRA }, // 20 PROM (Video Timing) +}; + +STD_ROM_PICK(Horizon) +STD_ROM_FN(Horizon) + +static INT32 M62MemIndex() +{ + UINT8 *Next; Next = Mem; + + if (!M62BgxTileDim) M62BgxTileDim = 8; + if (!M62BgyTileDim) M62BgyTileDim = 8; + if (!M62CharxTileDim) M62CharxTileDim = 8; + if (!M62CharyTileDim) M62CharyTileDim = 8; + if (!M62SpriteRamSize) M62SpriteRamSize = 0x100; + + M62Z80Rom = Next; Next += M62Z80RomSize; + M62M6803Rom = Next; Next += 0x0c000; + + RamStart = Next; + + M62SpriteRam = Next; Next += M62SpriteRamSize; + M62TileRam = Next; Next += 0x02000; + if (M62CharRamSize) M62CharRam = Next; Next += M62CharRamSize; + if (M62ScrollRamSize) M62ScrollRam = Next; Next += M62ScrollRamSize; + M62Z80Ram = Next; Next += 0x01000; + M62M6803Ram = Next; Next += 0x00080; + + RamEnd = Next; + + M62Tiles = Next; Next += M62NumTiles * M62BgxTileDim * M62BgyTileDim; + M62Sprites = Next; Next += M62NumSprites * 16 * 16; + if (M62NumChars) M62Chars = Next; Next += M62NumChars * M62CharxTileDim * M62CharyTileDim; + M62Palette = (UINT32*)Next; Next += M62PaletteEntries * sizeof(UINT32); + M62PromData = Next; Next += M62PromSize; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static INT32 M62DoReset() +{ + ZetOpen(0); + ZetReset(); + ZetClose(); + + M6803Reset(); + + AY8910Reset(0); + AY8910Reset(1); + + MSM5205Reset(); + + M62BackgroundHScroll = 0; + M62BackgroundVScroll = 0; + M62CharHScroll = 0; + M62CharVScroll = 0; + M62FlipScreen = 0; + M62SoundLatch = 0; + M62Port1 = 0; + M62Port2 = 0; + M62SlaveMSM5205VClckReset = 0; + M62BankControl[0] = M62BankControl[1] = 0; + Ldrun2BankSwap = 0; + Ldrun3TopBottomMask = 0; + KidnikiBackgroundBank = 0; + SpelunkrPaletteBank = 0; + + return 0; +} + +UINT8 __fastcall M62Z80Read(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall M62Z80Write(UINT16 a, UINT8 d) +{ + if (a <= 0xbfff) return; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KungfumZ80Read(UINT16 a) +{ + switch (a) { + case 0xf000: + case 0xf001: + case 0xf002: + case 0xf003: { + // ??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall KungfumZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xa000: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0xb000: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Ldrun3Z80Read(UINT16 a) +{ + switch (a) { + case 0xc800: { + return 0x05; + } + + case 0xcc00: { + return 0x07; + } + + case 0xcfff: { + return 0x07; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Ldrun4Z80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + INT32 BankAddress = 0x8000 + ((d & 0x01) * 0x4000); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + BankAddress); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall SpelunkrZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xd000: { + M62BackgroundVScroll = (M62BackgroundVScroll & 0xff00) | d; + return; + } + + case 0xd001: { + M62BackgroundVScroll = (M62BackgroundVScroll & 0x00ff) | (d << 8); + return; + } + + case 0xd002: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0xd003: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + case 0xd004: { + INT32 BankAddress = 0x8000 + ((d & 0x03) * 0x2000); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + BankAddress); + return; + } + + case 0xd005: { + SpelunkrPaletteBank = d & 0x01; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall Spelunk2Z80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xd000: { + M62BackgroundVScroll = (M62BackgroundVScroll & 0xff00) | d; + return; + } + + case 0xd001: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0xd002: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (((d & 0x02) >> 1) << 8); + M62BackgroundVScroll = (M62BackgroundVScroll & 0x00ff) | ((d & 0x01) << 8); + SpelunkrPaletteBank = (d & 0x0c) >> 2; + return; + } + + case 0xd003: { + INT32 BankAddress1 = 0x18000 + (((d & 0xc0) >> 6) * 0x1000); + INT32 BankAddress2 = 0x08000 + (((d & 0x3c) >> 2) * 0x1000); + ZetMapArea(0x8000, 0x8fff, 0, M62Z80Rom + BankAddress1); + ZetMapArea(0x8000, 0x8fff, 2, M62Z80Rom + BankAddress1); + ZetMapArea(0x9000, 0x9fff, 0, M62Z80Rom + BankAddress2); + ZetMapArea(0x9000, 0x9fff, 2, M62Z80Rom + BankAddress2); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall M62Z80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - M62Input[0]; + } + + case 0x01: { + return 0xff - M62Input[1]; + } + + case 0x02: { + return 0xff - M62Input[2]; + } + + case 0x03: { + return M62Dip[0]; + } + + case 0x04: { + return M62Dip[1]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall M62Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + if ((d & 0x80) == 0) { + M62SoundLatch = d & 0x7f; + } else { + M6803SetIRQ(M6803_IRQ_LINE, M6803_IRQSTATUS_ACK); + } + return; + } + + case 0x01: { + d ^= ~M62Dip[1] & 0x01; + M62FlipScreen = d & 0x01; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall BattroadZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: { + M62BackgroundVScroll = (M62BackgroundVScroll & 0xff00) | d; + return; + } + + case 0x81: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + case 0x82: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0x83: { + INT32 BankAddress = 0x8000 + ((d & 0x0f) * 0x2000); + ZetMapArea(0xa000, 0xbfff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0xa000, 0xbfff, 2, M62Z80Rom + BankAddress); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Ldrun2Z80PortRead(UINT16 a) +{ + a &= 0xff; + + if (a <= 0x04) return M62Z80PortRead(a); + + switch (a) { + case 0x80: { + if (Ldrun2BankSwap) { + Ldrun2BankSwap--; + if (Ldrun2BankSwap == 0) { + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + 0xa000); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + 0xa000); + } + } + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall Ldrun2Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: + case 0x81: { + static const INT32 Banks[30] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }; + INT32 Offset = a - 0x80; + + M62BankControl[Offset] = d; + + if (Offset == 0x00) { + if (d >= 1 && d <= 30) { + INT32 BankAddress = 0x8000 + (Banks[d - 1] * 0x2000); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + BankAddress); + } + } else { + if (M62BankControl[0] == 0x01 && d == 0x0d) { + Ldrun2BankSwap = 2; + } else { + Ldrun2BankSwap = 0; + } + } + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall Ldrun3Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: { + M62BackgroundVScroll = (M62BackgroundVScroll & 0xff00) | d; + return; + } + + case 0x81: { + Ldrun3TopBottomMask = d & 0x01; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall Ldrun4Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: { + // ??? + return; + } + + case 0x81: { + // ??? + return; + } + + case 0x82: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + case 0x83: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KidnikiZ80PortRead(UINT16 a) +{ + a &= 0xff; + + if (a <= 0x04) return M62Z80PortRead(a); + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall KidnikiZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0x81: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + case 0x82: { + M62CharVScroll = (M62CharVScroll & 0xff00) | d; + return; + } + + case 0x83: { + M62CharVScroll = (M62CharVScroll & 0x00ff) | (d << 8); + return; + } + + case 0x84: { + KidnikiBackgroundBank = d & 0x01; + return; + } + + case 0x85: { + INT32 BankAddress = 0x8000 + ((d & 0x0f) * 0x2000); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + BankAddress); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall YoujyudnZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + if (a <= 0x01) { + M62Z80PortWrite(a, d); + return; + } + + switch (a) { + case 0x80: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0x00ff) | (d << 8); + return; + } + + case 0x81: { + M62BackgroundHScroll = (M62BackgroundHScroll & 0xff00) | d; + return; + } + + case 0x83: { + INT32 BankAddress = 0x8000 + ((d & 0x01) * 0x4000); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + BankAddress); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + BankAddress); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 M62M6803ReadByte(UINT16 a) +{ + if (a <= 0x001f) { + return m6803_internal_registers_r(a); + } + + if (a >= 0x0080 && a <= 0x00ff) { + return M62M6803Ram[a - 0x0080]; + } + + bprintf(PRINT_NORMAL, _T("M6803 Read Byte -> %04X\n"), a); + + return 0; +} + +void M62M6803WriteByte(UINT16 a, UINT8 d) +{ + if (a <= 0x001f) { + m6803_internal_registers_w(a, d); + return; + } + + if (a >= 0x0080 && a <= 0x00ff) { + M62M6803Ram[a - 0x0080] = d; + return; + } + + switch (a) { + case 0x0800: { + M6803SetIRQ(M6803_IRQ_LINE, M6803_IRQSTATUS_NONE); + return; + } + + case 0x0801: { + MSM5205DataWrite(0, d); + return; + } + + case 0x0802: { + MSM5205DataWrite(1, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("M6803 Write Byte -> %04X, %02X\n"), a, d); +} + +UINT8 M62M6803ReadPort(UINT16 a) +{ + switch (a) { + case M6803_PORT1: { + if (M62Port2 & 0x08) return AY8910Read(0); + if (M62Port2 & 0x10) return AY8910Read(1); + return 0xff; + } + + case M6803_PORT2: { + return 0; + } + } + + bprintf(PRINT_NORMAL, _T("M6803 Read Port -> %04X\n"), a); + + return 0; +} + +void M62M6803WritePort(UINT16 a, UINT8 d) +{ + switch (a) { + case M6803_PORT1: { + M62Port1 = d; + return; + } + + case M6803_PORT2: { + if ((M62Port2 & 0x01) && !(d & 0x01)) { + if (M62Port2 & 0x04) { + if (M62Port2 & 0x08) { + AY8910Write(0, 0, M62Port1); + } + if (M62Port2 & 0x10) { + AY8910Write(1, 0, M62Port1); + } + } else { + if (M62Port2 & 0x08) { + AY8910Write(0, 1, M62Port1); + } + if (M62Port2 & 0x10) { + AY8910Write(1, 1, M62Port1); + } + } + } + + M62Port2 = d; + return; + } + } + + bprintf(PRINT_NORMAL, _T("M6803 Write Port -> %04X, %02X\n"), a, d); +} + +static INT32 Tile1024PlaneOffsets[3] = { 0x20000, 0x10000, 0 }; +static INT32 Tile2048PlaneOffsets[3] = { 0x40000, 0x20000, 0 }; +static INT32 Tile4096PlaneOffsets[3] = { 0x80000, 0x40000, 0 }; +static INT32 TileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TileYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 KungfumSpritePlaneOffsets[3] = { 0x80000, 0x40000, 0 }; +static INT32 BattroadSpritePlaneOffsets[3] = { 0x40000, 0x20000, 0 }; +static INT32 LdrunSpritePlaneOffsets[3] = { 0x20000, 0x10000, 0 }; +static INT32 KidnikiSpritePlaneOffsets[3] = { 0x100000, 0x80000, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 BattroadCharPlaneOffsets[2] = { 0, 0x10000 }; +static INT32 LotlotPlaneOffsets[3] = { 0, 0x10000, 0x20000 }; +static INT32 LotlotXOffsets[12] = { 0, 1, 2, 3, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 LotlotYOffsets[10] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72 }; +static INT32 KidnikiPlaneOffsets[3] = { 0, 0x20000, 0x40000 }; +static INT32 KidnikiXOffsets[12] = { 0, 1, 2, 3, 64, 65, 66, 67, 68, 69, 70, 71 }; +static INT32 KidnikiYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 Spelunk2PlaneOffsets[3] = { 0, 0x20000, 0x40000 }; +static INT32 Spelunk2XOffsets[12] = { 0, 1, 2, 3, 0x10000, 0x10001, 0x10002, 0x10003, 0x10004, 0x10005, 0x10006, 0x10007 }; +static INT32 Spelunk2YOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 YoujyudnTilePlaneOffsets[3] = { 0x40000, 0x20000, 0 }; +static INT32 YoujyudnTileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 YoujyudnTileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +UINT8 M62SoundLatchRead(UINT32) +{ + return M62SoundLatch; +} + +static void AY8910_0PortBWrite(UINT32, UINT32 d) +{ + MSM5205PlaymodeWrite(0, (d >> 2) & 0x07); + MSM5205PlaymodeWrite(1, ((d >> 2) & 0x04) | 0x03); + + MSM5205ResetWrite(0, d & 0x01); + MSM5205ResetWrite(1, d & 0x02); +} + +inline static INT32 M62SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / M62Z80Clock); +} + +static void M62MSM5205Vck0() +{ + M6803SetIRQ(M6803_INPUT_LINE_NMI, M6803_IRQSTATUS_AUTO); + M62SlaveMSM5205VClckReset = 1; +} + +static INT32 M62MemInit() +{ + INT32 nLen; + + M62PaletteEntries = BurnDrvGetPaletteEntries(); + + Mem = NULL; + M62MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + M62MemIndex(); + + return 0; +} + +static INT32 KungfumLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x06000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x0a000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 7, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x06000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0a000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0e000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x12000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x16000, 19, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 27, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 KungfumdLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 6, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 12, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 20, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 BattroadLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x0c000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x02000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x06000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0a000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0c000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0e000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x14000, 9, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x06000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x0a000, 12, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 15, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x06000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0a000, 21, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, BattroadSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 23, 1); if (nRet != 0) return 1; + GfxDecode(M62NumChars, 2, M62CharxTileDim, M62CharyTileDim, BattroadCharPlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 30, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 31, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00720, 32, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 LdrunLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x06000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x02000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x06000, 3, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x0a000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x06000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 8, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x06000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, LdrunSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 19, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 Ldrun2LoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x0c000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x02000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x06000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0a000, 5, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x06000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x0a000, 8, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x06000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0a000, 17, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, BattroadSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 25, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 Ldrun3LoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 7, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile2048PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 13, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 21, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 Ldrun3jLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x0c000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 7, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile2048PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x0c000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, BattroadSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 18, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 LotlotLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x06000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x0a000, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x06000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 5, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, LotlotPlaneOffsets, LotlotXOffsets, LotlotYOffsets, 0x100, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x06000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 8, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, LdrunSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x06000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, LotlotPlaneOffsets, LotlotXOffsets, LotlotYOffsets, 0x100, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00700, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00800, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00900, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00920, 22, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 KidnikiLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x30000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x10000, 3, 1); if (nRet != 0) return 1; + memcpy(M62Z80Rom + 0x20000, M62Z80Rom + 0x18000, 0x8000); + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 6, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile4096PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x18000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x1c000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x20000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x24000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x28000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x2c000, 21, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KidnikiSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 24, 1); if (nRet != 0) return 1; + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, KidnikiPlaneOffsets, KidnikiXOffsets, KidnikiYOffsets, 0x80, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 30, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 31, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 32, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 LitheroLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x30000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile4096PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x18000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x20000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x28000, 14, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KidnikiSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x30000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 17, 1); if (nRet != 0) return 1; + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, KidnikiPlaneOffsets, KidnikiXOffsets, KidnikiYOffsets, 0x80, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 25, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 SpelunkrLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0c000, 3, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 11, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile4096PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 17, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x18000); + UINT8 *pTemp = (UINT8*)malloc(0x18000); + nRet = BurnLoadRom(pTemp + 0x00000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x04000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x08000, 20, 1); if (nRet != 0) return 1; + memcpy(M62TempRom + 0x0000, pTemp + 0x0000, 0x800); + memcpy(M62TempRom + 0x2000, pTemp + 0x0800, 0x800); + memcpy(M62TempRom + 0x0800, pTemp + 0x1000, 0x800); + memcpy(M62TempRom + 0x2800, pTemp + 0x1800, 0x800); + memcpy(M62TempRom + 0x1000, pTemp + 0x2000, 0x800); + memcpy(M62TempRom + 0x3000, pTemp + 0x2800, 0x800); + memcpy(M62TempRom + 0x0800, pTemp + 0x3000, 0x800); + memcpy(M62TempRom + 0x3800, pTemp + 0x3800, 0x800); + memcpy(M62TempRom + 0x4000, pTemp + 0x4000, 0x800); + memcpy(M62TempRom + 0x6000, pTemp + 0x4800, 0x800); + memcpy(M62TempRom + 0x4800, pTemp + 0x5000, 0x800); + memcpy(M62TempRom + 0x6800, pTemp + 0x5800, 0x800); + memcpy(M62TempRom + 0x5000, pTemp + 0x6000, 0x800); + memcpy(M62TempRom + 0x7000, pTemp + 0x6800, 0x800); + memcpy(M62TempRom + 0x5800, pTemp + 0x7000, 0x800); + memcpy(M62TempRom + 0x7800, pTemp + 0x7800, 0x800); + memcpy(M62TempRom + 0x8000, pTemp + 0x8000, 0x800); + memcpy(M62TempRom + 0xa000, pTemp + 0x8800, 0x800); + memcpy(M62TempRom + 0x8800, pTemp + 0x9000, 0x800); + memcpy(M62TempRom + 0xa800, pTemp + 0x9800, 0x800); + memcpy(M62TempRom + 0x9000, pTemp + 0xa000, 0x800); + memcpy(M62TempRom + 0xb000, pTemp + 0xa800, 0x800); + memcpy(M62TempRom + 0x9800, pTemp + 0xb000, 0x800); + memcpy(M62TempRom + 0xb800, pTemp + 0xb800, 0x800); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, Spelunk2PlaneOffsets, Spelunk2XOffsets, Spelunk2YOffsets, 0x40, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 28, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 Spelunk2LoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x10000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x18000, 4, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x04000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 6, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile4096PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 15, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x18000); + UINT8 *pTemp = (UINT8*)malloc(0x18000); + nRet = BurnLoadRom(pTemp + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x04000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x08000, 18, 1); if (nRet != 0) return 1; + memcpy(M62TempRom + 0x0000, pTemp + 0x0000, 0x800); + memcpy(M62TempRom + 0x2000, pTemp + 0x0800, 0x800); + memcpy(M62TempRom + 0x0800, pTemp + 0x1000, 0x800); + memcpy(M62TempRom + 0x2800, pTemp + 0x1800, 0x800); + memcpy(M62TempRom + 0x1000, pTemp + 0x2000, 0x800); + memcpy(M62TempRom + 0x3000, pTemp + 0x2800, 0x800); + memcpy(M62TempRom + 0x0800, pTemp + 0x3000, 0x800); + memcpy(M62TempRom + 0x3800, pTemp + 0x3800, 0x800); + memcpy(M62TempRom + 0x4000, pTemp + 0x4000, 0x800); + memcpy(M62TempRom + 0x6000, pTemp + 0x4800, 0x800); + memcpy(M62TempRom + 0x4800, pTemp + 0x5000, 0x800); + memcpy(M62TempRom + 0x6800, pTemp + 0x5800, 0x800); + memcpy(M62TempRom + 0x5000, pTemp + 0x6000, 0x800); + memcpy(M62TempRom + 0x7000, pTemp + 0x6800, 0x800); + memcpy(M62TempRom + 0x5800, pTemp + 0x7000, 0x800); + memcpy(M62TempRom + 0x7800, pTemp + 0x7800, 0x800); + memcpy(M62TempRom + 0x8000, pTemp + 0x8000, 0x800); + memcpy(M62TempRom + 0xa000, pTemp + 0x8800, 0x800); + memcpy(M62TempRom + 0x8800, pTemp + 0x9000, 0x800); + memcpy(M62TempRom + 0xa800, pTemp + 0x9800, 0x800); + memcpy(M62TempRom + 0x9000, pTemp + 0xa000, 0x800); + memcpy(M62TempRom + 0xb000, pTemp + 0xa800, 0x800); + memcpy(M62TempRom + 0x9800, pTemp + 0xb000, 0x800); + memcpy(M62TempRom + 0xb800, pTemp + 0xb800, 0x800); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, Spelunk2PlaneOffsets, Spelunk2XOffsets, Spelunk2YOffsets, 0x40, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00700, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00720, 26, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 YoujyudnLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x0c000, 3, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + UINT8 *pTemp = (UINT8*)malloc(0x18000); + nRet = BurnLoadRom(pTemp + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(pTemp + 0x10000, 7, 1); if (nRet != 0) return 1; + memcpy(M62TempRom + 0x0000, pTemp + 0x04000, 0x4000); + memcpy(M62TempRom + 0x4000, pTemp + 0x0c000, 0x4000); + memcpy(M62TempRom + 0x8000, pTemp + 0x14000, 0x4000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, YoujyudnTilePlaneOffsets, YoujyudnTileXOffsets, YoujyudnTileYOffsets, 0x80, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 13, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load and decode the chars + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 16, 1); if (nRet != 0) return 1; + GfxDecode(M62NumChars, 3, M62CharxTileDim, M62CharyTileDim, KidnikiPlaneOffsets, KidnikiXOffsets, KidnikiYOffsets, 0x80, M62TempRom, M62Chars); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 24, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static INT32 HorizonLoadRoms() +{ + INT32 nRet = 0; + + M62TempRom = (UINT8 *)malloc(0x18000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(M62Z80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62Z80Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(M62M6803Rom + 0x08000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x02000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 6, 1); if (nRet != 0) return 1; + GfxDecode(M62NumTiles, 3, M62BgxTileDim, M62BgyTileDim, Tile1024PlaneOffsets, TileXOffsets, TileYOffsets, 0x40, M62TempRom, M62Tiles); + + // Load and decode the sprites + memset(M62TempRom, 0, 0x18000); + nRet = BurnLoadRom(M62TempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x04000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x08000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x0c000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62TempRom + 0x14000, 12, 1); if (nRet != 0) return 1; + GfxDecode(M62NumSprites, 3, 16, 16, KungfumSpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, M62TempRom, M62Sprites); + + // Load the Proms + nRet = BurnLoadRom(M62PromData + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00100, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00200, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00300, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00400, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00500, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00600, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(M62PromData + 0x00620, 20, 1); if (nRet != 0) return 1; + + if (M62TempRom) { + free(M62TempRom); + M62TempRom = NULL; + } + + return 0; +} + +static void M62MachineInit() +{ + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(M62Z80Read); + ZetSetWriteHandler(M62Z80Write); + ZetSetInHandler(M62Z80PortRead); + ZetSetOutHandler(M62Z80PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, M62Z80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, M62Z80Rom ); + ZetMapArea(0xc000, 0xc0ff, 0, M62SpriteRam); + ZetMapArea(0xc000, 0xc0ff, 1, M62SpriteRam); + ZetMapArea(0xc000, 0xc0ff, 2, M62SpriteRam); + ZetMapArea(0xd000, 0xdfff, 0, M62TileRam ); + ZetMapArea(0xd000, 0xdfff, 1, M62TileRam ); + ZetMapArea(0xd000, 0xdfff, 2, M62TileRam ); + ZetMapArea(0xe000, 0xefff, 0, M62Z80Ram ); + ZetMapArea(0xe000, 0xefff, 1, M62Z80Ram ); + ZetMapArea(0xe000, 0xefff, 2, M62Z80Ram ); + ZetMemEnd(); + ZetClose(); + + M6803Init(1); + M6803MapMemory(M62M6803Rom, 0x4000, 0xffff, M6803_ROM); + M6803SetReadByteHandler(M62M6803ReadByte); + M6803SetWriteByteHandler(M62M6803WriteByte); + M6803SetReadPortHandler(M62M6803ReadPort); + M6803SetWritePortHandler(M62M6803WritePort); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 894886, nBurnSoundRate, &M62SoundLatchRead, NULL, NULL, &AY8910_0PortBWrite); + AY8910Init(1, 894886, nBurnSoundRate, NULL, NULL, NULL, NULL); + + MSM5205Init(0, M62SynchroniseStream, 384000, M62MSM5205Vck0, MSM5205_S96_4B, 50, 1); + MSM5205Init(1, M62SynchroniseStream, 384000, NULL, MSM5205_SEX_4B, 50, 1); + + GenericTilesInit(); + + M62Z80Clock = 4000000; + M62M6803Clock = 894886; + + M62SpriteHeightPromOffset = (M62PaletteEntries & 0xf00) * 3; + +// BurnSetRefreshRate(55.0); +} + +static INT32 KungfumMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetReadHandler(KungfumZ80Read); + ZetSetWriteHandler(KungfumZ80Write); + ZetMemEnd(); + ZetClose(); + + M62Z80Clock = 3072000; + M62RenderFunction = KungfumDraw; + + M62DoReset(); + + return 0; +} + +static INT32 BattroadMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetOutHandler(BattroadZ80PortWrite); + ZetMapArea(0xa000, 0xbfff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0xa000, 0xbfff, 2, M62Z80Rom + 0x8000); + ZetMapArea(0xc800, 0xcfff, 0, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 1, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 2, M62CharRam ); + ZetMemEnd(); + ZetClose(); + + M62Z80Clock = 3072000; + + M62RenderFunction = BattroadDraw; + M62ExtendTileInfoFunction = BattroadExtendTile; + M62ExtendCharInfoFunction = BattroadExtendChar; + + M62DoReset(); + + return 0; +} + +static INT32 LdrunMachineInit() +{ + M62MachineInit(); + + M62RenderFunction = LdrunDraw; + M62ExtendTileInfoFunction = LdrunExtendTile; + + M62DoReset(); + + return 0; +} + +static INT32 Ldrun2MachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetInHandler(Ldrun2Z80PortRead); + ZetSetOutHandler(Ldrun2Z80PortWrite); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + 0x8000); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = LdrunDraw; + M62ExtendTileInfoFunction = Ldrun2ExtendTile; + + M62DoReset(); + + return 0; +} + +static INT32 Ldrun3MachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetReadHandler(Ldrun3Z80Read); + ZetSetOutHandler(Ldrun3Z80PortWrite); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + 0x8000); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = Ldrun3Draw; + M62ExtendTileInfoFunction = Ldrun2ExtendTile; + + M62DoReset(); + + return 0; +} + +static INT32 Ldrun4MachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetWriteHandler(Ldrun4Z80Write); + ZetSetOutHandler(Ldrun4Z80PortWrite); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + 0x8000); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = Ldrun4Draw; + M62ExtendTileInfoFunction = Ldrun4ExtendTile; + + M62DoReset(); + + return 0; +} + +static INT32 LotlotMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetMapArea(0xa000, 0xafff, 0, M62CharRam); + ZetMapArea(0xa000, 0xafff, 1, M62CharRam); + ZetMapArea(0xa000, 0xafff, 2, M62CharRam); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = LotlotDraw; + M62ExtendTileInfoFunction = LotlotExtendTile; + M62ExtendCharInfoFunction = LotlotExtendChar; + + M62DoReset(); + + return 0; +} + +static INT32 KidnikiMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetInHandler(KidnikiZ80PortRead); + ZetSetOutHandler(KidnikiZ80PortWrite); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + 0x8000); + ZetMapArea(0xa000, 0xafff, 0, M62TileRam ); + ZetMapArea(0xa000, 0xafff, 1, M62TileRam ); + ZetMapArea(0xa000, 0xafff, 2, M62TileRam ); + ZetMapArea(0xd000, 0xdfff, 0, M62CharRam ); + ZetMapArea(0xd000, 0xdfff, 1, M62CharRam ); + ZetMapArea(0xd000, 0xdfff, 2, M62CharRam ); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = KidnikiDraw; + M62ExtendTileInfoFunction = KidnikiExtendTile; + M62ExtendCharInfoFunction = LotlotExtendChar; + + M62DoReset(); + + return 0; +} + +static INT32 SpelunkrMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetWriteHandler(SpelunkrZ80Write); + ZetMapArea(0x8000, 0x9fff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0x9fff, 2, M62Z80Rom + 0x8000); + ZetMapArea(0xa000, 0xbfff, 0, M62TileRam ); + ZetMapArea(0xa000, 0xbfff, 1, M62TileRam ); + ZetMapArea(0xa000, 0xbfff, 2, M62TileRam ); + ZetMapArea(0xc800, 0xcfff, 0, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 1, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 2, M62CharRam ); + ZetMemCallback(0xd000, 0xdfff, 0); + ZetMemCallback(0xd000, 0xdfff, 1); + ZetMemCallback(0xd000, 0xdfff, 2); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = SpelunkrDraw; + M62ExtendTileInfoFunction = SpelunkrExtendTile; + M62ExtendCharInfoFunction = SpelunkrExtendChar; + + M62DoReset(); + + return 0; +} + +static INT32 Spelunk2MachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetWriteHandler(Spelunk2Z80Write); + ZetMapArea(0x8000, 0x8fff, 0, M62Z80Rom + 0x18000); + ZetMapArea(0x8000, 0x8fff, 2, M62Z80Rom + 0x18000); + ZetMapArea(0x9000, 0x9fff, 0, M62Z80Rom + 0x08000); + ZetMapArea(0x9000, 0x9fff, 2, M62Z80Rom + 0x08000); + ZetMapArea(0xa000, 0xbfff, 0, M62TileRam ); + ZetMapArea(0xa000, 0xbfff, 1, M62TileRam ); + ZetMapArea(0xa000, 0xbfff, 2, M62TileRam ); + ZetMapArea(0xc800, 0xcfff, 0, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 1, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 2, M62CharRam ); + ZetMemCallback(0xd000, 0xdfff, 0); + ZetMemCallback(0xd000, 0xdfff, 1); + ZetMemCallback(0xd000, 0xdfff, 2); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = Spelunk2Draw; + M62ExtendTileInfoFunction = Spelunk2ExtendTile; + M62ExtendCharInfoFunction = SpelunkrExtendChar; + + M62SpriteHeightPromOffset = 0x700; + + M62DoReset(); + + return 0; +} + +static INT32 YoujyudnMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetSetOutHandler(YoujyudnZ80PortWrite); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + 0x8000); + ZetMapArea(0xc800, 0xcfff, 0, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 1, M62CharRam ); + ZetMapArea(0xc800, 0xcfff, 2, M62CharRam ); + ZetMemCallback(0xd800, 0xdfff, 0); + ZetMemCallback(0xd800, 0xdfff, 1); + ZetMemCallback(0xd800, 0xdfff, 2); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = YoujyudnDraw; + M62ExtendTileInfoFunction = YoujyudnExtendTile; + M62ExtendCharInfoFunction = YoujyudnExtendChar; + + M62Z80Clock = 3072000; + + M62DoReset(); + + return 0; +} + +static INT32 HorizonMachineInit() +{ + M62MachineInit(); + + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, M62Z80Rom + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, M62Z80Rom + 0x8000); + ZetMapArea(0xc000, 0xc1ff, 0, M62SpriteRam ); + ZetMapArea(0xc000, 0xc1ff, 1, M62SpriteRam ); + ZetMapArea(0xc000, 0xc1ff, 2, M62SpriteRam ); + ZetMapArea(0xc800, 0xc83f, 0, M62ScrollRam ); + ZetMapArea(0xc800, 0xc83f, 1, M62ScrollRam ); + ZetMapArea(0xc800, 0xc83f, 2, M62ScrollRam ); + ZetMemEnd(); + ZetClose(); + + M62RenderFunction = HorizonDraw; + M62ExtendTileInfoFunction = HorizonExtendTile; + + M62DoReset(); + + return 0; +} + +static INT32 KungfumInit() +{ + M62Z80RomSize = 0x8000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x400; + + if (M62MemInit()) return 1; + if (KungfumLoadRoms()) return 1; + if (KungfumMachineInit()) return 1; + + return 0; +} + +static INT32 KungfumdInit() +{ + M62Z80RomSize = 0x8000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x400; + + if (M62MemInit()) return 1; + if (KungfumdLoadRoms()) return 1; + if (KungfumMachineInit()) return 1; + + return 0; +} + +static INT32 BattroadInit() +{ + M62Z80RomSize = 0x16000; + M62PromSize = 0x740; + M62NumTiles = 0x400; + M62NumSprites = 0x200; + M62NumChars = 0x400; + M62CharRamSize = 0x800; + + if (M62MemInit()) return 1; + if (BattroadLoadRoms()) return 1; + if (BattroadMachineInit()) return 1; + + return 0; +} + +static INT32 LdrunInit() +{ + M62Z80RomSize = 0x8000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x100; + + if (M62MemInit()) return 1; + if (LdrunLoadRoms()) return 1; + if (LdrunMachineInit()) return 1; + + return 0; +} + +static INT32 Ldrun2Init() +{ + M62Z80RomSize = 0xc000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x200; + + if (M62MemInit()) return 1; + if (Ldrun2LoadRoms()) return 1; + if (Ldrun2MachineInit()) return 1; + + return 0; +} + +static INT32 Ldrun3Init() +{ + M62Z80RomSize = 0xc000; + M62PromSize = 0x720; + M62NumTiles = 0x800; + M62NumSprites = 0x400; + + if (M62MemInit()) return 1; + if (Ldrun3LoadRoms()) return 1; + if (Ldrun3MachineInit()) return 1; + + return 0; +} + +static INT32 Ldrun3jInit() +{ + M62Z80RomSize = 0xc000; + M62PromSize = 0x720; + M62NumTiles = 0x800; + M62NumSprites = 0x200; + + if (M62MemInit()) return 1; + if (Ldrun3jLoadRoms()) return 1; + if (Ldrun3MachineInit()) return 1; + + return 0; +} + +static INT32 Ldrun4Init() +{ + M62Z80RomSize = 0x10000; + M62PromSize = 0x720; + M62NumTiles = 0x800; + M62NumSprites = 0x400; + + if (M62MemInit()) return 1; + if (Ldrun3LoadRoms()) return 1; + if (Ldrun4MachineInit()) return 1; + + return 0; +} + +static INT32 LotlotInit() +{ + M62Z80RomSize = 0x8000; + M62PromSize = 0xa20; + M62NumTiles = 0x100; + M62NumSprites = 0x100; + M62NumChars = 0x100; + M62CharRamSize = 0x1000; + M62BgxTileDim = 12; + M62BgyTileDim = 10; + M62CharxTileDim = 12; + M62CharyTileDim = 10; + + if (M62MemInit()) return 1; + if (LotlotLoadRoms()) return 1; + if (LotlotMachineInit()) return 1; + + return 0; +} + +static INT32 KidnikiInit() +{ + M62Z80RomSize = 0x28000; + M62PromSize = 0x720; + M62NumTiles = 0x1000; + M62NumSprites = 0x800; + M62NumChars = 0x400; + M62CharRamSize = 0x1000; + M62BgxTileDim = 8; + M62BgyTileDim = 8; + M62CharxTileDim = 12; + M62CharyTileDim = 8; + + if (M62MemInit()) return 1; + if (KidnikiLoadRoms()) return 1; + if (KidnikiMachineInit()) return 1; + + return 0; +} + +static INT32 LitheroInit() +{ + M62Z80RomSize = 0x28000; + M62PromSize = 0x720; + M62NumTiles = 0x1000; + M62NumSprites = 0x800; + M62NumChars = 0x400; + M62CharRamSize = 0x1000; + M62BgxTileDim = 8; + M62BgyTileDim = 8; + M62CharxTileDim = 12; + M62CharyTileDim = 8; + + if (M62MemInit()) return 1; + if (LitheroLoadRoms()) return 1; + if (KidnikiMachineInit()) return 1; + + return 0; +} + +static INT32 SpelunkrInit() +{ + M62Z80RomSize = 0x10000; + M62PromSize = 0x720; + M62NumTiles = 0x1000; + M62NumSprites = 0x400; + M62NumChars = 0x200; + M62CharRamSize = 0x800; + M62BgxTileDim = 8; + M62BgyTileDim = 8; + M62CharxTileDim = 12; + M62CharyTileDim = 8; + + if (M62MemInit()) return 1; + if (SpelunkrLoadRoms()) return 1; + if (SpelunkrMachineInit()) return 1; + + return 0; +} + +static INT32 Spelunk2Init() +{ + M62Z80RomSize = 0x1c000; + M62PromSize = 0x820; + M62NumTiles = 0x1000; + M62NumSprites = 0x400; + M62NumChars = 0x200; + M62CharRamSize = 0x800; + M62BgxTileDim = 8; + M62BgyTileDim = 8; + M62CharxTileDim = 12; + M62CharyTileDim = 8; + + if (M62MemInit()) return 1; + if (Spelunk2LoadRoms()) return 1; + if (Spelunk2MachineInit()) return 1; + + return 0; +} + +static INT32 YoujyudnInit() +{ + M62Z80RomSize = 0x10000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x400; + M62NumChars = 0x400; + M62CharRamSize = 0x800; + M62BgxTileDim = 8; + M62BgyTileDim = 16; + M62CharxTileDim = 12; + M62CharyTileDim = 8; + + if (M62MemInit()) return 1; + if (YoujyudnLoadRoms()) return 1; + if (YoujyudnMachineInit()) return 1; + + return 0; +} + +static INT32 HorizonInit() +{ + M62Z80RomSize = 0xc000; + M62PromSize = 0x720; + M62NumTiles = 0x400; + M62NumSprites = 0x400; + M62SpriteRamSize = 0x200; + M62ScrollRamSize = 0x40; + + if (M62MemInit()) return 1; + if (HorizonLoadRoms()) return 1; + if (HorizonMachineInit()) return 1; + + return 0; +} + +static INT32 M62Exit() +{ + ZetExit(); + M6800Exit(); + AY8910Exit(0); + AY8910Exit(1); + MSM5205Exit(); + + GenericTilesExit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + M62Z80RomSize = 0; + M62PromSize = 0; + M62NumTiles = 0; + M62NumSprites = 0; + M62NumChars = 0; + M62SpriteRamSize = 0; + M62CharRamSize = 0; + M62ScrollRamSize = 0; + + M62BackgroundHScroll = 0; + M62BackgroundVScroll = 0; + M62CharHScroll = 0; + M62CharVScroll = 0; + M62FlipScreen = 0; + M62SoundLatch = 0; + M62Port1 = 0; + M62Port2 = 0; + M62SlaveMSM5205VClckReset = 0; + M62PaletteEntries = 0; + M62Z80Clock = 0; + M62M6803Clock = 0; + M62RenderFunction = NULL; + M62ExtendTileInfoFunction = NULL; + M62ExtendCharInfoFunction = NULL; + M62BankControl[0] = M62BankControl[1] = 0; + Ldrun2BankSwap = 0; + Ldrun3TopBottomMask = 0; + KidnikiBackgroundBank = 0; + SpelunkrPaletteBank = 0; + M62BgxTileDim = 0; + M62BgyTileDim = 0; + M62CharxTileDim = 0; + M62CharyTileDim = 0; + M62SpriteHeightPromOffset = 0; + + return 0; +} + +static void M62CalcPalette() +{ + UINT8 *ColourProm = (UINT8*)M62PromData; + + for (UINT32 i = 0; i < M62PaletteEntries; i++) { + INT32 Bit0, Bit1, Bit2, Bit3, r, g, b; + + Bit0 = (ColourProm[M62PaletteEntries * 0] >> 0) & 0x01; + Bit1 = (ColourProm[M62PaletteEntries * 0] >> 1) & 0x01; + Bit2 = (ColourProm[M62PaletteEntries * 0] >> 2) & 0x01; + Bit3 = (ColourProm[M62PaletteEntries * 0] >> 3) & 0x01; + r = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[M62PaletteEntries * 1] >> 0) & 0x01; + Bit1 = (ColourProm[M62PaletteEntries * 1] >> 1) & 0x01; + Bit2 = (ColourProm[M62PaletteEntries * 1] >> 2) & 0x01; + Bit3 = (ColourProm[M62PaletteEntries * 1] >> 3) & 0x01; + g = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[M62PaletteEntries * 2] >> 0) & 0x01; + Bit1 = (ColourProm[M62PaletteEntries * 2] >> 1) & 0x01; + Bit2 = (ColourProm[M62PaletteEntries * 2] >> 2) & 0x01; + Bit3 = (ColourProm[M62PaletteEntries * 2] >> 3) & 0x01; + b = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + M62Palette[i] = BurnHighCol(r, g, b, 0); + + ColourProm++; + } +} + +static void BattroadCalcPalette() +{ + UINT8 *ColourProm = (UINT8*)M62PromData; + + for (UINT32 i = 0; i < 0x200; i++) { + INT32 Bit0, Bit1, Bit2, Bit3, r, g, b; + + Bit0 = (ColourProm[0x000] >> 0) & 0x01; + Bit1 = (ColourProm[0x000] >> 1) & 0x01; + Bit2 = (ColourProm[0x000] >> 2) & 0x01; + Bit3 = (ColourProm[0x000] >> 3) & 0x01; + r = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x200] >> 0) & 0x01; + Bit1 = (ColourProm[0x200] >> 1) & 0x01; + Bit2 = (ColourProm[0x200] >> 2) & 0x01; + Bit3 = (ColourProm[0x200] >> 3) & 0x01; + g = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x400] >> 0) & 0x01; + Bit1 = (ColourProm[0x400] >> 1) & 0x01; + Bit2 = (ColourProm[0x400] >> 2) & 0x01; + Bit3 = (ColourProm[0x400] >> 3) & 0x01; + b = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + M62Palette[i] = BurnHighCol(r, g, b, 0); + + ColourProm++; + } + + ColourProm = (UINT8*)M62PromData + 0x720; + + for (UINT32 i = 0; i < 0x20; i++) { + INT32 Bit0, Bit1, Bit2, r, g, b; + + Bit0 = (ColourProm[i] >> 0) & 0x01; + Bit1 = (ColourProm[i] >> 1) & 0x01; + Bit2 = (ColourProm[i] >> 2) & 0x01; + r = 0x21 * Bit0 + 0x47 * Bit1 + 0x97 * Bit2; + + Bit0 = (ColourProm[i] >> 3) & 0x01; + Bit1 = (ColourProm[i] >> 4) & 0x01; + Bit2 = (ColourProm[i] >> 5) & 0x01; + g = 0x21 * Bit0 + 0x47 * Bit1 + 0x97 * Bit2; + + Bit0 = 0; + Bit1 = (ColourProm[i] >> 6) & 0x01; + Bit2 = (ColourProm[i] >> 7) & 0x01; + b = 0x21 * Bit0 + 0x47 * Bit1 + 0x97 * Bit2; + + M62Palette[i + 0x200] = BurnHighCol(r, g, b, 0); + } +} + +static void Spelunk2CalcPalette() +{ + UINT8 *ColourProm = (UINT8*)M62PromData; + + for (UINT32 i = 0; i < 0x200; i++) { + INT32 Bit0, Bit1, Bit2, Bit3, r, g, b; + + Bit0 = (ColourProm[0x000] >> 0) & 0x01; + Bit1 = (ColourProm[0x000] >> 1) & 0x01; + Bit2 = (ColourProm[0x000] >> 2) & 0x01; + Bit3 = (ColourProm[0x000] >> 3) & 0x01; + r = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x000] >> 4) & 0x01; + Bit1 = (ColourProm[0x000] >> 5) & 0x01; + Bit2 = (ColourProm[0x000] >> 6) & 0x01; + Bit3 = (ColourProm[0x000] >> 7) & 0x01; + g = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x200] >> 0) & 0x01; + Bit1 = (ColourProm[0x200] >> 1) & 0x01; + Bit2 = (ColourProm[0x200] >> 2) & 0x01; + Bit3 = (ColourProm[0x200] >> 3) & 0x01; + b = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + M62Palette[i] = BurnHighCol(r, g, b, 0); + + ColourProm++; + } + + ColourProm += 0x200; + + for (UINT32 i = 0; i < 0x100; i++) { + INT32 Bit0, Bit1, Bit2, Bit3, r, g, b; + + Bit0 = (ColourProm[0x000] >> 0) & 0x01; + Bit1 = (ColourProm[0x000] >> 1) & 0x01; + Bit2 = (ColourProm[0x000] >> 2) & 0x01; + Bit3 = (ColourProm[0x000] >> 3) & 0x01; + r = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x100] >> 0) & 0x01; + Bit1 = (ColourProm[0x100] >> 1) & 0x01; + Bit2 = (ColourProm[0x100] >> 2) & 0x01; + Bit3 = (ColourProm[0x100] >> 3) & 0x01; + g = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + Bit0 = (ColourProm[0x200] >> 0) & 0x01; + Bit1 = (ColourProm[0x200] >> 1) & 0x01; + Bit2 = (ColourProm[0x200] >> 2) & 0x01; + Bit3 = (ColourProm[0x200] >> 3) & 0x01; + b = 0x0e * Bit0 + 0x1f * Bit1 + 0x43 * Bit2 + 0x8f * Bit3; + + M62Palette[i + 0x200] = BurnHighCol(r, g, b, 0); + + ColourProm++; + } +} + +static void BattroadExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip) +{ + *Code |= ((*Colour & 0x40) << 3) | ((*Colour & 0x10) << 4); + + *xFlip = *Colour & 0x20; + + if (((*Colour & 0x1f) >> 1) >= 0x04) { + *Priority = 1; + } else { + *Priority = 0; + } + + *Colour &= 0x0f; +} + +static void LdrunExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip) +{ + *Code |= (*Colour & 0xc0) << 2; + + *xFlip = *Colour & 0x20; + + if (((*Colour & 0x1f) >> 1) >= 0x0c) { + *Priority = 1; + } else { + *Priority = 0; + } + + *Colour &= 0x1f; +} + +static void Ldrun2ExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32* xFlip) +{ + *Code |= (*Colour & 0xc0) << 2; + + *xFlip = *Colour & 0x20; + + if (((*Colour & 0x1f) >> 1) >= 0x04) { + *Priority = 1; + } else { + *Priority = 0; + } + + *Colour &= 0x1f; +} + +static void Ldrun4ExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= ((*Colour & 0xc0) << 2) | ((*Colour & 0x20) << 5); + *Colour &= 0x1f; +} + +static void LotlotExtendTile(INT32* Code, INT32* Colour, INT32*, INT32* xFlip) +{ + *Code |= (*Colour & 0xc0) << 2; + *xFlip = *Colour & 0x20; + *Colour &= 0x1f; +} + +static void KidnikiExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*) +{ + *Code |= ((*Colour & 0xe0) << 3) | (KidnikiBackgroundBank << 11); + *Priority = ((*Colour & 0xe0) == 0xe0) ? 1 : 0; + *Colour &= 0x1f; +} + +static void SpelunkrExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= ((*Colour & 0x10) << 4) | ((*Colour & 0x20) << 6) | ((*Colour & 0xc0) << 3); + *Colour &= 0x0f | (SpelunkrPaletteBank << 4); +} + +static void Spelunk2ExtendTile(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= ((*Colour & 0xf0) << 4); + *Colour &= 0x0f | (SpelunkrPaletteBank << 4); +} + +static void YoujyudnExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*) +{ + *Code |= (*Colour & 0x60) << 3; + if (((*Colour & 0x1f) >> 1) >= 0x08) { + *Priority = 1; + } else { + *Priority = 0; + } + *Colour &= 0x1f; +} + +static void HorizonExtendTile(INT32* Code, INT32* Colour, INT32* Priority, INT32*) +{ + *Code |= ((*Colour & 0xc0) << 2) | ((*Colour & 0x20) << 5); + if (((*Colour & 0x1f) >> 1) >= 0x08) { + *Priority = 1; + } else { + *Priority = 0; + } + *Colour &= 0x1f; +} + +static void M62RenderBgLayer(INT32 PriorityToRender, INT32 xOffset, INT32 yOffset, INT32 Cols, INT32 Rows, INT32 Transparent) +{ + INT32 Code, mx, my, Colour, x, y, TileIndex = 0, Priority, xFlip, yFlip; + + for (my = 0; my < Rows; my++) { + for (mx = 0; mx < Cols; mx++) { + Code = M62TileRam[TileIndex << 1]; + Colour = M62TileRam[(TileIndex << 1) | 0x01]; + Priority = 0; + xFlip = 0; + yFlip = 0; + + if (M62ExtendTileInfoFunction) M62ExtendTileInfoFunction(&Code, &Colour, &Priority, &xFlip); + Code &= (M62NumTiles - 1); + + x = M62BgxTileDim * mx; + y = M62BgyTileDim * my; + + if (M62FlipScreen) { + xFlip = !xFlip; + yFlip = !yFlip; + + y = (Rows * M62BgyTileDim) - M62BgyTileDim - y; + x = (Cols * M62BgxTileDim) - M62BgxTileDim - x; + } + + x -= xOffset; + y -= yOffset; + + if (M62FlipScreen) { + x += M62BackgroundHScroll & (Cols * M62BgxTileDim - 1); + } else { + x -= M62BackgroundHScroll & (Cols * M62BgxTileDim - 1); + } + + y -= M62BackgroundVScroll & (Rows * M62BgyTileDim - 1); + + INT32 px, py; + + UINT32 nPalette = Colour << 3; + + if (Priority == PriorityToRender) { + for (py = 0; py < M62BgyTileDim; py++) { + for (px = 0; px < M62BgxTileDim; px++) { + UINT8 c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + (py * M62BgxTileDim) + px]; + if (xFlip) c = M62Tiles[(Code *M62BgxTileDim * M62BgyTileDim) + (py * M62BgxTileDim) + (M62BgxTileDim - 1 - px)]; + if (yFlip) c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + ((M62BgyTileDim - 1 - py) * M62BgxTileDim) + px]; + if (xFlip && yFlip) c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + ((M62BgyTileDim - 1 - py) * M62BgxTileDim) + (M62BgxTileDim - 1 - px)]; + + if (Transparent && c == 0x00) continue; + + INT32 xPos = x + px; + INT32 yPos = y + py; + + if (M62ScrollRamSize) { +// tilemap_set_scrollx(state->bg_tilemap, i, state->scrollram[i << 1] | (state->scrollram[(i << 1) | 1] << 8)); + + xPos -= (M62ScrollRam[my << 1] | (M62ScrollRam[(my << 1) | 0x01] << 8)) & (Cols * M62BgxTileDim - 1); + } + + if (xPos < 0) xPos += Cols * M62BgxTileDim; + if (xPos > (Cols * M62BgxTileDim - 1)) xPos -= Cols * M62BgxTileDim; + + if (yPos < 0) yPos += Rows * M62BgyTileDim; + if (yPos > (Rows * M62BgyTileDim - 1)) yPos -= Rows * M62BgyTileDim; + + if (yPos >= 0 && yPos < nScreenHeight) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + + TileIndex++; + } + } +} + +static void KungfumRenderBgLayer(INT32 PriorityToRender, INT32 Cols, INT32 Rows, INT32 Transparent) +{ + INT32 Code, mx, my, Colour, x, y, TileIndex = 0, Priority, xFlip, yFlip; + + for (my = 0; my < Rows; my++) { + for (mx = 0; mx < Cols; mx++) { + Code = M62TileRam[TileIndex]; + Colour = M62TileRam[TileIndex + 0x800]; + xFlip = Colour & 0x20; + yFlip = 0; + + Code |= (Colour & 0xc0) << 2; + Code &= (M62NumTiles - 1); + + if ((TileIndex / 64) << 6 || ((Colour & 0x1f) >> 1) > 0x0c) { + Priority = 1; + } else { + Priority = 0; + } + + x = M62BgxTileDim * mx; + y = M62BgyTileDim * my; + + if (M62FlipScreen) { + xFlip = !xFlip; + yFlip = !yFlip; + + y = (Rows * M62BgyTileDim - 1) - M62BgyTileDim - y; + x = (Cols * M62BgxTileDim - 1) - M62BgxTileDim - x; + } + + x -= 128; + + INT32 px, py; + + UINT32 nPalette = (Colour & 0x1f) << 3; + + if (Priority == PriorityToRender) { + for (py = 0; py < M62BgyTileDim; py++) { + for (px = 0; px < M62BgxTileDim; px++) { + UINT8 c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + (py * M62BgxTileDim) + px]; + if (xFlip) c = M62Tiles[(Code *M62BgxTileDim * M62BgyTileDim) + (py * M62BgxTileDim) + (M62BgxTileDim - 1 - px)]; + if (yFlip) c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + ((M62BgyTileDim - 1 - py) * M62BgxTileDim) + px]; + if (xFlip && yFlip) c = M62Tiles[(Code * M62BgxTileDim * M62BgyTileDim) + ((M62BgyTileDim - 1 - py) * M62BgxTileDim) + (M62BgxTileDim - 1 - px)]; + + if (Transparent && c == 0x00) continue; + + INT32 xPos = x + px; + INT32 yPos = y + py; + + if (my >= 6) { + if (M62FlipScreen) { + xPos += M62BackgroundHScroll & (Cols * M62BgxTileDim - 1); + } else { + xPos -= M62BackgroundHScroll & (Cols * M62BgxTileDim - 1); + } + } + + if (xPos < 0) xPos += Cols * M62BgxTileDim; + if (xPos > (Cols * M62BgxTileDim - 1)) xPos -= Cols * M62BgxTileDim; + + if (yPos < 0) yPos += Rows * M62BgyTileDim; + if (yPos > (Rows * M62BgyTileDim - 1)) yPos -= Rows * M62BgyTileDim; + + if (yPos >= 0 && yPos < nScreenHeight) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + + TileIndex++; + } + } +} + +static void M62RenderSprites(INT32 ColourMask, INT32 PriorityMask, INT32 Priority, INT32 VisibleOffset, INT32 PaletteOffset) +{ + for (UINT32 Offset = 0; Offset < M62SpriteRamSize; Offset += 8) { + INT32 i, Incr, Code, Colour, xFlip, yFlip, sx, sy; + + if ((M62SpriteRam[Offset] & PriorityMask) == Priority) { + Code = M62SpriteRam[Offset + 4] + ((M62SpriteRam[Offset + 5] & 0x07) << 8); + Colour = M62SpriteRam[Offset + 0] & ColourMask; + sx = 256 * (M62SpriteRam[Offset + 7] & 1) + M62SpriteRam[Offset + 6], + sy = 256 + 128 - 15 - (256 * (M62SpriteRam[Offset + 3] & 1) + M62SpriteRam[Offset + 2]), + xFlip = M62SpriteRam[Offset + 5] & 0x40; + yFlip = M62SpriteRam[Offset + 5] & 0x80; + + i = M62PromData[M62SpriteHeightPromOffset + ((Code >> 5) & 0x1f)]; + if (i == 1) { + // double height + Code &= ~1; + sy -= 16; + } else if (i == 2) { + // quadruple height + i = 3; + Code &= ~3; + sy -= 3*16; + } + + if (M62FlipScreen) { + sx = 496 - sx; + sy = 242 - (i * 16) - sy; + xFlip = !xFlip; + yFlip = !yFlip; + } + + if (yFlip) { + Incr = -1; + Code += i; + } else { + Incr = 1; + } + + sx -= VisibleOffset; + + do { + INT32 DrawCode = Code + (i * Incr); + INT32 DrawY = sy + (i * 16); + DrawCode &= (M62NumSprites - 1); + + if (sx > 15 && sx < (nScreenWidth - 16) && DrawY > 15 && DrawY < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } else { + Render16x16Tile_Mask(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, DrawCode, sx, DrawY, Colour, 3, 0, PaletteOffset, M62Sprites); + } + } + } + + i--; + } while (i >= 0); + } + } +} + +static void BattroadExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= ((*Colour & 0x40) << 3) | ((*Colour & 0x10) << 4); + *Colour &= 0x0f; +} + +static void LotlotExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= (*Colour & 0xc0) << 2; + *Colour &= 0x1f; +} + +static void SpelunkrExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= (*Colour & 0x10) << 4; + *Colour &= 0x0f | (SpelunkrPaletteBank << 4); +} + +static void YoujyudnExtendChar(INT32* Code, INT32* Colour, INT32*, INT32*) +{ + *Code |= (*Colour & 0xc0) << 2; + *Colour &= 0x0f; +} + +static void M62RenderCharLayer(INT32 Cols, INT32 Rows, INT32 ColourDepth, INT32 xOffset, INT32 yOffset, INT32 PaletteOffset) +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, xFlip, yFlip; + + for (my = 0; my < Rows; my++) { + for (mx = 0; mx < Cols; mx++) { + Code = M62CharRam[TileIndex << 1]; + Colour = M62CharRam[(TileIndex << 1) | 0x01]; + xFlip = 0; + yFlip = 0; + + if (M62ExtendCharInfoFunction) M62ExtendCharInfoFunction(&Code, &Colour, 0, 0); + Code &= (M62NumChars - 1); + + x = M62CharxTileDim * mx; + y = M62CharyTileDim * my; + + x -= xOffset; + y -= yOffset; + + if (M62FlipScreen) { + x += M62CharHScroll & (Cols * M62CharxTileDim - 1); + } else { + x -= M62CharHScroll & (Cols * M62CharxTileDim - 1); + } + + y -= M62CharVScroll & (Rows * M62CharyTileDim - 1); + + INT32 px, py; + + UINT32 nPalette = Colour << ColourDepth; + + for (py = 0; py < M62CharyTileDim; py++) { + for (px = 0; px < M62CharxTileDim; px++) { + UINT8 c = M62Chars[(Code * M62CharxTileDim * M62CharyTileDim) + (py * M62CharxTileDim) + px]; + if (xFlip) c = M62Chars[(Code *M62CharxTileDim * M62CharyTileDim) + (py * M62CharxTileDim) + (M62CharxTileDim - 1 - px)]; + if (yFlip) c = M62Chars[(Code * M62CharxTileDim * M62CharyTileDim) + ((M62CharyTileDim - 1 - py) * M62CharxTileDim) + px]; + if (xFlip && yFlip) c = M62Chars[(Code * M62CharxTileDim * M62CharyTileDim) + ((M62CharyTileDim - 1 - py) * M62CharxTileDim) + (M62CharxTileDim - 1 - px)]; + + if (c != 0) { + INT32 xPos = x + px; + INT32 yPos = y + py; + + if (xPos < 0) xPos += Cols * M62CharxTileDim; + if (xPos > (Cols * M62CharxTileDim - 1)) xPos -= Cols * M62CharxTileDim; + + if (yPos < 0) yPos += Rows * M62CharyTileDim; + if (yPos > (Rows * M62CharyTileDim - 1)) yPos -= Rows * M62CharyTileDim; + + if (yPos >= 0 && yPos < nScreenHeight) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette | PaletteOffset; + } + } + } + } + } + + TileIndex++; + } + } +} + +static void KungfumDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + KungfumRenderBgLayer(0, 64, 32, 0); + KungfumRenderBgLayer(1, 64, 32, 0); + M62RenderSprites(0x1f, 0, 0, 128, 256); + KungfumRenderBgLayer(0, 64, 32, 1); + BurnTransferCopy(M62Palette); +} + +static void BattroadDraw() +{ + BurnTransferClear(); + BattroadCalcPalette(); + M62RenderBgLayer(0, 128, 0, 64, 32, 0); + M62RenderBgLayer(1, 128, 0, 64, 32, 0); + M62RenderSprites(0x0f, 0x10, 0x00, 128, 256); + M62RenderBgLayer(1, 128, 0, 64, 32, 1); + M62RenderSprites(0x0f, 0x10, 0x10, 128, 256); + M62RenderCharLayer(32, 32, 2, 0, 0, 512); + BurnTransferCopy(M62Palette); +} + +static void LdrunDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64, 0, 64, 32, 0); + M62RenderBgLayer(1, 64, 0, 64, 32, 0); + M62RenderSprites(0x0f, 0x10, 0x00, 64, 256); + M62RenderBgLayer(1, 64, 0, 64, 32, 1); + M62RenderSprites(0x0f, 0x10, 0x10, 64, 256); + BurnTransferCopy(M62Palette); +} + +static void Ldrun3Draw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64, 0, 64, 32, 0); + M62RenderBgLayer(1, 64, 0, 64, 32, 0); + M62RenderSprites(0x0f, 0x10, 0x00, 64, 256); + M62RenderBgLayer(1, 64, 0, 64, 32, 1); + M62RenderSprites(0x0f, 0x10, 0x10, 64, 256); + + if (Ldrun3TopBottomMask) { + INT32 x, y; + + for (x = 0; x < nScreenWidth; x++) { + for (y = 0; y < 8; y++) { + pTransDraw[(y * nScreenWidth) + x] = BurnHighCol(0, 0, 0, 0); + pTransDraw[((y + 248) * nScreenWidth) + x] = BurnHighCol(0, 0, 0, 0); + } + } + } + + BurnTransferCopy(M62Palette); +} + +static void Ldrun4Draw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64 - 2, 0, 64, 32, 0); + M62RenderSprites(0x0f, 0x00, 0x00, 64, 256); + BurnTransferCopy(M62Palette); +} + +static void LotlotDraw() +{ + M62BackgroundVScroll = 32; + M62BackgroundHScroll = -64; + + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64, 0, 32, 64, 0); + M62RenderCharLayer(32, 64, 3, -64 + 64, 32, 512); + M62RenderSprites(0x1f, 0x00, 0x00, 64, 256); + BurnTransferCopy(M62Palette); +} + +static void KidnikiDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64, 0, 64, 32, 0); + M62RenderBgLayer(1, 64, 0, 64, 32, 0); + M62RenderSprites(0x1f, 0x00, 0x00, 64, 256); + M62RenderBgLayer(1, 64, 0, 64, 32, 1); + M62RenderCharLayer(32, 64, 3, 0, 128, 0); + BurnTransferCopy(M62Palette); +} + +static void SpelunkrDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 64, 128, 64, 64, 0); + M62RenderSprites(0x1f, 0x00, 0x00, 64, 256); + M62RenderCharLayer(32, 32, 3, 0, 0, 0); + BurnTransferCopy(M62Palette); +} + +static void Spelunk2Draw() +{ + BurnTransferClear(); + Spelunk2CalcPalette(); + M62RenderBgLayer(0, 64 - 1, 128, 64, 64, 0); + M62RenderSprites(0x1f, 0x00, 0x00, 64, 512); + M62RenderCharLayer(32, 32, 3, 64 - 65, 0, 0); + BurnTransferCopy(M62Palette); +} + +static void YoujyudnDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 128, 0, 64, 16, 0); + M62RenderBgLayer(1, 128, 0, 64, 16, 0); + M62RenderSprites(0x1f, 0x00, 0x00, 128, 256); + M62RenderBgLayer(1, 128, 0, 64, 16, 1); + M62RenderCharLayer(32, 32, 3, 64, 0, 128); + BurnTransferCopy(M62Palette); +} + +static void HorizonDraw() +{ + BurnTransferClear(); + M62CalcPalette(); + M62RenderBgLayer(0, 128, 0, 64, 32, 0); + M62RenderBgLayer(1, 128, 0, 64, 32, 0); + M62RenderSprites(0x1f, 0x00, 0x00, 128, 256); + M62RenderBgLayer(1, 128, 0, 64, 32, 1); + BurnTransferCopy(M62Palette); +} + +static INT32 M62Frame() +{ + INT32 nInterleave = MSM5205CalcInterleave(0, M62Z80Clock); + INT32 nSoundBufferPos = 0; + + if (M62Reset) M62DoReset(); + + M62MakeInputs(); + +// nCyclesTotal[0] = M62Z80Clock / 55; +// nCyclesTotal[1] = M62M6803Clock / 55; + nCyclesTotal[0] = M62Z80Clock / 60; + nCyclesTotal[1] = M62M6803Clock / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + M6803NewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = M6803Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + if (nSample < -32768) { + nSample = -32768; + } else { + if (nSample > 32767) { + nSample = 32767; + } + } + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + + MSM5205Update(); + if (M62SlaveMSM5205VClckReset) { + MSM5205VCLKWrite(1, 1); + MSM5205VCLKWrite(1, 0); + M62SlaveMSM5205VClckReset = 0; + } + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + if (nSample < -32768) { + nSample = -32768; + } else { + if (nSample > 32767) { + nSample = 32767; + } + } + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + MSM5205Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + if (M62RenderFunction) M62RenderFunction(); + } + + return 0; +} + +static INT32 M62Scan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029709; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + } + + return 0; +} + +struct BurnDriver BurnDrvKungfum = { + "kungfum", NULL, NULL, NULL, "1984", + "Kung-Fu Master\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, KungfumRomInfo, KungfumRomName, NULL, NULL, M62InputInfo, KungfumDIPInfo, + KungfumInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKungfumd = { + "kungfumd", "kungfum", NULL, NULL, "1984", + "Kung-Fu Master (Data East)\0", NULL, "Irem (Data East License)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, KungfumdRomInfo, KungfumdRomName, NULL, NULL, M62InputInfo, KungfumDIPInfo, + KungfumdInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvSpartanx = { + "spartanx", "kungfum", NULL, NULL, "1984", + "Spartan X (Japan)\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, SpartanxRomInfo, SpartanxRomName, NULL, NULL, M62InputInfo, KungfumDIPInfo, + KungfumInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKungfub = { + "kungfub", "kungfum", NULL, NULL, "1984", + "Kung-Fu Master (bootleg set 1)\0", NULL, "bootleg", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, KungfubRomInfo, KungfubRomName, NULL, NULL, M62InputInfo, KungfumDIPInfo, + KungfumInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKungfub2 = { + "kungfub2", "kungfum", NULL, NULL, "1984", + "Kung-Fu Master (bootleg set 2)\0", NULL, "bootleg", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, Kungfub2RomInfo, Kungfub2RomName, NULL, NULL, M62InputInfo, KungfumDIPInfo, + KungfumInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvBattroad = { + "battroad", NULL, NULL, NULL, "1984", + "The Battle-Road\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_IREM_M62, GBF_SCRFIGHT, 0, + NULL, BattroadRomInfo, BattroadRomName, NULL, NULL, M62InputInfo, BattroadDIPInfo, + BattroadInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x220, 256, 256, 3, 4 +}; + +struct BurnDriver BurnDrvLdrun = { + "ldrun", NULL, NULL, NULL, "1984", + "Lode Runner (set 1)\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, LdrunRomInfo, LdrunRomName, NULL, NULL, M62InputInfo, LdrunDIPInfo, + LdrunInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLdruna = { + "ldruna", "ldrun", NULL, NULL, "1984", + "Lode Runner (set 2)\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, LdrunaRomInfo, LdrunaRomName, NULL, NULL, M62InputInfo, LdrunDIPInfo, + LdrunInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLdrun2 = { + "ldrun2", NULL, NULL, NULL, "1984", + "Lode Runner II - The Bungeling Strikes Back\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, Ldrun2RomInfo, Ldrun2RomName, NULL, NULL, M62InputInfo, Ldrun2DIPInfo, + Ldrun2Init, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLdrun3 = { + "ldrun3", NULL, NULL, NULL, "1985", + "Lode Runner III - The Golden Labyrinth\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, Ldrun3RomInfo, Ldrun3RomName, NULL, NULL, M62InputInfo, Ldrun2DIPInfo, + Ldrun3Init, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLdrun3j = { + "ldrun3j", "ldrun3", NULL, NULL, "1985", + "Lode Runner III - Majin No Fukkatsu\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, Ldrun3jRomInfo, Ldrun3jRomName, NULL, NULL, M62InputInfo, Ldrun2DIPInfo, + Ldrun3jInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLdrun4 = { + "ldrun4", NULL, NULL, NULL, "1986", + "Lode Runner IV - Teikoku Karano Dasshutsu\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, Ldrun4RomInfo, Ldrun4RomName, NULL, NULL, M62InputInfo, Ldrun4DIPInfo, + Ldrun4Init, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLotlot = { + "lotlot", NULL, NULL, NULL, "1985", + "Lot Lot\0", NULL, "Irem (licensed from Tokuma Shoten)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PUZZLE, 0, + NULL, LotlotRomInfo, LotlotRomName, NULL, NULL, M62InputInfo, LotlotDIPInfo, + LotlotInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x300, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKidniki = { + "kidniki", NULL, NULL, NULL, "1986", + "Kid Niki - Radical Ninja (World)\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, KidnikiRomInfo, KidnikiRomName, NULL, NULL, M62InputInfo, KidnikiDIPInfo, + KidnikiInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKidnikiu = { + "kidnikiu", "kidniki", NULL, NULL, "1986", + "Kid Niki - Radical Ninja (US)\0", NULL, "Irem (Data East USA license)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, KidnikiuRomInfo, KidnikiuRomName, NULL, NULL, M62InputInfo, KidnikiDIPInfo, + KidnikiInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvYanchamr = { + "yanchamr", "kidniki", NULL, NULL, "1986", + "Kaiketsu Yanchamaru (Japan)\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, YanchamrRomInfo, YanchamrRomName, NULL, NULL, M62InputInfo, KidnikiDIPInfo, + KidnikiInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvLithero = { + "lithero", "kidniki", NULL, NULL, "1987", + "Little Hero\0", NULL, "bootleg", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, LitheroRomInfo, LitheroRomName, NULL, NULL, M62InputInfo, KidnikiDIPInfo, + LitheroInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvSpelunkr = { + "spelunkr", NULL, NULL, NULL, "1985", + "Spelunker\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, SpelunkrRomInfo, SpelunkrRomName, NULL, NULL, M62InputInfo, SpelunkrDIPInfo, + SpelunkrInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvSpelunkrj = { + "spelunkrj", "spelunkr", NULL, NULL, "1985", + "Spelunker (Japan)\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, SpelunkrjRomInfo, SpelunkrjRomName, NULL, NULL, M62InputInfo, SpelunkrDIPInfo, + SpelunkrInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvSpelunk2 = { + "spelunk2", NULL, NULL, NULL, "1986", + "Spelunker II\0", NULL, "Irem (licensed from Broderbund)", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_PLATFORM, 0, + NULL, Spelunk2RomInfo, Spelunk2RomName, NULL, NULL, M62InputInfo, Spelunk2DIPInfo, + Spelunk2Init, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x300, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvYoujyudn = { + "youjyudn", NULL, NULL, NULL, "1986", + "Youjyuden (Japan)\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M62, GBF_VERSHOOT, 0, + NULL, YoujyudnRomInfo, YoujyudnRomName, NULL, NULL, M62InputInfo, YoujyudnDIPInfo, + YoujyudnInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHorizon = { + "horizon", NULL, NULL, NULL, "1985", + "Horizon\0", NULL, "Irem", "Irem M62", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M62, GBF_HORSHOOT, 0, + NULL, HorizonRomInfo, HorizonRomName, NULL, NULL, M62InputInfo, HorizonDIPInfo, + HorizonInit, M62Exit, M62Frame, NULL, M62Scan, + NULL, 0x200, 256, 256, 4, 3 +}; diff --git a/src/burn/drivers/irem/d_m63.cpp b/src/burn/drivers/irem/d_m63.cpp new file mode 100644 index 00000000..5bd7cad0 --- /dev/null +++ b/src/burn/drivers/irem/d_m63.cpp @@ -0,0 +1,1152 @@ +// FB Alpha Irem M63 driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "i8039.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvI8039ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *DrvSampleROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvColRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvScrRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *interrupt_enable; +static UINT8 *flipscreen; +static UINT8 *palette_bank; +static UINT8 *sound_status; + +static INT16 *pAY8910Buffer[6]; + +static UINT8 m63_sound_p1; +static UINT8 m63_sound_p2; +static UINT8 sound_irq = 0; +static INT32 sample_pos = 0; +static INT32 sample_sel = -1; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static INT32 sy_offset; +static INT32 char_color_offset; +static INT32 sound_interrupt_count; + +static struct BurnInputInfo WilytowrInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 6, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Wilytowr) + +static struct BurnInputInfo FghtbsktInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 0, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 0, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Fghtbskt) + +static struct BurnDIPInfo WilytowrDIPList[]= +{ + {0x10, 0xff, 0xff, 0x01, NULL }, + {0x11, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x10, 0x01, 0x03, 0x00, "2" }, + {0x10, 0x01, 0x03, 0x01, "3" }, + {0x10, 0x01, 0x03, 0x02, "4" }, + {0x10, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Points Rate" }, + {0x10, 0x01, 0x0c, 0x00, "Normal" }, + {0x10, 0x01, 0x0c, 0x04, "x1.2" }, + {0x10, 0x01, 0x0c, 0x08, "x1.4" }, + {0x10, 0x01, 0x0c, 0x0c, "x1.6" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x10, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x30, 0x30, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x10, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xc0, 0x80, "1 Coin 5 Credits" }, + {0x10, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x10, 0x01, 0xf0, 0x60, "7 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x50, "6 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x40, "5 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x30, "4 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x20, "3 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x10, "2 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x10, 0x01, 0xf0, 0x80, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 6 Credits" }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 7 Credits" }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 8 Credits" }, + {0x10, 0x01, 0xf0, 0x70, "1 Coin 9 Credits" }, + {0x10, 0x01, 0xf0, 0xf0, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x01, 0x00, "Off" }, + {0x11, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x02, 0x02, "Upright" }, + {0x11, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x11, 0x01, 0x04, 0x00, "Mode 1" }, + {0x11, 0x01, 0x04, 0x04, "Mode 2" }, + + {0 , 0xfe, 0 , 0, "Stop Mode (Cheat)" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Wilytowr) + +static struct BurnDIPInfo FghtbsktDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xc4, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x0f, 0x01, 0x03, 0x03, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0x03, 0x00, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x0f, 0x01, 0x0c, 0x04, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0x0c, 0x00, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0x0c, 0x08, "1 Coin 4 Credits" }, + {0x0f, 0x01, 0x0c, 0x0c, "99 Credits / Sound Test" }, + + {0 , 0xfe, 0 , 2, "Time Count Down" }, + {0x0f, 0x01, 0x20, 0x00, "Slow" }, + {0x0f, 0x01, 0x20, 0x20, "Too Fast" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0f, 0x01, 0x40, 0x40, "Upright" }, + {0x0f, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Fghtbskt) + +void __fastcall m63_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf000: + *interrupt_enable = data ? 1 : 0; + return; + + case 0xf002: + *flipscreen = ~data & 0x01; + return; + + case 0xf003: + *palette_bank = data & 0x01; + return; + + case 0xf006: + case 0xf007: + // coin counters (offset) + return; + + case 0xf800: + *soundlatch = data; + return; + + case 0xf801: + return; // nop + + case 0xf803: + I8039SetIrqState(1); + return; + } +} + +UINT8 __fastcall m63_main_read(UINT16 address) +{ + switch (address) + { + case 0xf000: // fghtbskt + return *sound_status; + + case 0xf800: + case 0xf001: // fghtbskt + return DrvInputs[0]; + + case 0xf801: + case 0xf002: // fghtbskt + return DrvInputs[1]; + + case 0xf802: + case 0xf003: // fghtbskt + return DrvDips[0]; + + case 0xf806: + return DrvDips[1]; + } + + return 0; +} + +void __fastcall fghtbskt_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf000: + I8039SetIrqState(1); + return; + + case 0xf002: + *soundlatch = data; + return; + + case 0xf801: + *interrupt_enable = data ? 1 : 0; + return; + + case 0xf802: + *flipscreen = data ? 1 : 0; + // if (flipscreen) ? tile_flipx : 0 + return; + + case 0xf807: + if (data & 0x01) { + sample_sel = ((data & 0xf0) << 8); + sample_pos = 0; + } + return; + + case 0xf001: + case 0xf800: + case 0xf803: + case 0xf804: + case 0xf805: + case 0xf806: + return; // nop + } +} + +UINT8 __fastcall m63_sound_read(UINT32 address) +{ + return DrvI8039ROM[address & 0x0fff]; +} + +void __fastcall m63_sound_write_port(UINT32 port, UINT8 data) +{ + if ((port & 0xff00) == 0x0000) { + if ((m63_sound_p2 & 0xf0) == 0xe0) + { + AY8910Write(0, 0, port & 0xff); + } + else if ((m63_sound_p2 & 0xf0) == 0xa0) + { + AY8910Write(0, 1, port & 0xff); + } + else if ((m63_sound_p1 & 0xe0) == 0x60 && sy_offset != 240) + { + AY8910Write(1, 0, port & 0xff); + } + else if ((m63_sound_p1 & 0xe0) == 0x40 && sy_offset != 240) + { + AY8910Write(1, 1, port & 0xff); + } + else if ((m63_sound_p2 & 0xf0) == 0x70) + { + *sound_status = port & 0xff; + } + + return; + } + + switch (port) + { + case 0x101: + m63_sound_p1 = data; + return; + + case 0x102: + m63_sound_p2 = data; + if ((data & 0xf0) == 0x50) I8039SetIrqState(0); + return; + } +} + +UINT8 __fastcall m63_sound_read_port(UINT32 port) +{ + if ((port & 0xff00) == 0x0000) { + if ((m63_sound_p2 & 0xf0) == 0x60) { + return *soundlatch; + } + else if ((m63_sound_p2 & 0xf0) == 0x70) + { + return DrvSndROM[((m63_sound_p1 & 0x1f) << 8) | (port & 0xff)]; + } + + return 0xff; + } + + switch (port) + { + case 0x111: + if (sound_irq) { + sound_irq = 0; + return 1; + } + return 0; + } + + return 0; +} + +static void m63PaletteRecalc() +{ + for (INT32 i = 0; i < 256; i++) + { + INT32 bit0 = (DrvColPROM[i] >> 0) & 0x01; + INT32 bit1 = (DrvColPROM[i] >> 1) & 0x01; + INT32 bit2 = (DrvColPROM[i] >> 2) & 0x01; + INT32 bit3 = (DrvColPROM[i] >> 3) & 0x01; + INT32 r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 256] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 256] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 256] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 256] >> 3) & 0x01; + INT32 g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 2*256] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 2*256] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 2*256] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 2*256] >> 3) & 0x01; + INT32 b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + DrvPalette[i] = BurnHighCol(r,g,b,0); + } + + for (INT32 i = 0; i < 4; i++) + { + INT32 bit0 = (DrvColPROM[0x300+i] >> 0) & 0x01; + INT32 bit1 = (DrvColPROM[0x300+i] >> 1) & 0x01; + INT32 bit2 = (DrvColPROM[0x300+i] >> 2) & 0x01; + INT32 r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (DrvColPROM[0x300+i] >> 3) & 0x01; + bit1 = (DrvColPROM[0x300+i] >> 4) & 0x01; + bit2 = (DrvColPROM[0x300+i] >> 5) & 0x01; + INT32 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (DrvColPROM[0x300+i] >> 6) & 0x01; + bit1 = (DrvColPROM[0x300+i] >> 7) & 0x01; + INT32 b = 0x4f * bit0 + 0xa8 * bit1; + + DrvPalette[0x100+i] = BurnHighCol(r,g,b,0); + } +} + +static void m63_main_map() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xd000, 0xdfff, 0, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 1, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 2, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe1ff, 0, DrvZ80RAM1); + ZetMapArea(0xe000, 0xe1ff, 1, DrvZ80RAM1); + ZetMapArea(0xe000, 0xe1ff, 2, DrvZ80RAM1); + ZetMapArea(0xe200, 0xe2ff, 0, DrvSprRAM); + ZetMapArea(0xe200, 0xe2ff, 1, DrvSprRAM); + ZetMapArea(0xe200, 0xe2ff, 2, DrvSprRAM); + ZetMapArea(0xe300, 0xe3ff, 0, DrvScrRAM); + ZetMapArea(0xe300, 0xe3ff, 1, DrvScrRAM); + ZetMapArea(0xe300, 0xe3ff, 2, DrvScrRAM); + ZetMapArea(0xe400, 0xe7ff, 0, DrvVidRAM1); + ZetMapArea(0xe400, 0xe7ff, 1, DrvVidRAM1); + ZetMapArea(0xe400, 0xe7ff, 2, DrvVidRAM1); + ZetMapArea(0xe800, 0xebff, 0, DrvVidRAM0); + ZetMapArea(0xe800, 0xebff, 1, DrvVidRAM0); + ZetMapArea(0xe800, 0xebff, 2, DrvVidRAM0); + ZetMapArea(0xec00, 0xefff, 0, DrvColRAM); + ZetMapArea(0xec00, 0xefff, 1, DrvColRAM); + ZetMapArea(0xec00, 0xefff, 2, DrvColRAM); + ZetSetWriteHandler(m63_main_write); + ZetSetReadHandler(m63_main_read); + ZetMemEnd(); + ZetClose(); +} + +static void fghtbskt_main_map() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM0); + ZetMapArea(0xd000, 0xd1ff, 0, DrvZ80RAM1); + ZetMapArea(0xd000, 0xd1ff, 1, DrvZ80RAM1); + ZetMapArea(0xd000, 0xd1ff, 2, DrvZ80RAM1); + ZetMapArea(0xd200, 0xd2ff, 0, DrvSprRAM); + ZetMapArea(0xd200, 0xd2ff, 1, DrvSprRAM); + ZetMapArea(0xd200, 0xd2ff, 2, DrvSprRAM); + ZetMapArea(0xd300, 0xd3ff, 0, DrvScrRAM); + ZetMapArea(0xd300, 0xd3ff, 1, DrvScrRAM); + ZetMapArea(0xd300, 0xd3ff, 2, DrvScrRAM); + ZetMapArea(0xd400, 0xd7ff, 0, DrvVidRAM1); + ZetMapArea(0xd400, 0xd7ff, 1, DrvVidRAM1); + ZetMapArea(0xd400, 0xd7ff, 2, DrvVidRAM1); + ZetMapArea(0xd800, 0xdbff, 0, DrvVidRAM0); + ZetMapArea(0xd800, 0xdbff, 1, DrvVidRAM0); + ZetMapArea(0xd800, 0xdbff, 2, DrvVidRAM0); + ZetMapArea(0xdc00, 0xdfff, 0, DrvColRAM); + ZetMapArea(0xdc00, 0xdfff, 1, DrvColRAM); + ZetMapArea(0xdc00, 0xdfff, 2, DrvColRAM); + ZetSetWriteHandler(fghtbskt_main_write); + ZetSetReadHandler(m63_main_read); + ZetMemEnd(); + ZetClose(); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + I8039Reset(); + + AY8910Reset(0); + AY8910Reset(1); + + m63_sound_p1 = 0; + m63_sound_p2 = 0; + sound_irq = 0; + sample_pos = 0; + sample_sel = -1; + + DrvRecalc = 1; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[2] = { 0x8000, 0x0000 }; + INT32 Plane1[3] = { (0x2000*8)*2, (0x2000*8)*1, (0x2000*8)*0 }; + INT32 Plane2[3] = { (0x4000*8)*2, (0x4000*8)*1, (0x4000*8)*0 }; + INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, (0x2000*8)+0, (0x2000*8)+1, (0x2000*8)+2, (0x2000*8)+3, (0x2000*8)+4, (0x2000*8)+5, (0x2000*8)+6, (0x2000*8)+7 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }; + + UINT8 *tmp = (UINT8*)malloc(0xc000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x2000); + + GfxDecode(0x0100, 2, 8, 8, Plane0, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x6000); + + GfxDecode(0x0400, 3, 8, 8, Plane1, XOffs, YOffs, 0x040, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0xc000); + + GfxDecode(0x0200, 3, 16, 16, Plane2, XOffs, YOffs, 0x080, tmp, DrvGfxROM2); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x010000; + DrvI8039ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x008000; + DrvGfxROM1 = Next; Next += 0x010000; + DrvGfxROM2 = Next; Next += 0x020000; + + DrvSampleROM = Next; Next += 0x010000; + + DrvSndROM = Next; Next += 0x002000; + + DrvColPROM = Next; Next += 0x000400; + + DrvPalette = (UINT32*)Next; Next += 0x0104 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x001000; + DrvZ80RAM1 = Next; Next += 0x000200; + DrvVidRAM0 = Next; Next += 0x000400; + DrvVidRAM1 = Next; Next += 0x000400; + DrvColRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000100; + DrvScrRAM = Next; Next += 0x000100; + + soundlatch = Next; Next += 0x000001; + interrupt_enable = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + palette_bank = Next; Next += 0x000001; + sound_status = Next; Next += 0x000001; + + RamEnd = Next; + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + } + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit(void (*pMapMainCPU)(), INT32 (*pRomLoadCallback)(), INT32 syoffset, INT32 charcoloroff, INT32 sndirqcount) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pRomLoadCallback()) return 1; + + DrvGfxDecode(); + + pMapMainCPU(); + + I8039Init(NULL); + I8039SetProgramReadHandler(m63_sound_read); + I8039SetCPUOpReadHandler(m63_sound_read); + I8039SetCPUOpReadArgHandler(m63_sound_read); + I8039SetIOReadHandler(m63_sound_read_port); + I8039SetIOWriteHandler(m63_sound_write_port); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + sy_offset = syoffset; + char_color_offset = charcoloroff; + sound_interrupt_count = sndirqcount; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + I8039Exit(); + + AY8910Exit(0); + AY8910Exit(1); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 wilytowerLoadRoms() +{ + if (BurnLoadRom(DrvZ80ROM + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x04000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x06000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x08000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x0a000, 5, 1)) return 1; + + if (BurnLoadRom(DrvI8039ROM, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x01000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x02000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x04000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x02000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x06000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0a000, 17, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 18, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 19, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 20, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 21, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00300, 22, 1)) return 1; + + return 0; +} + +static INT32 fghtbsktLoadRoms() +{ + if (BurnLoadRom(DrvZ80ROM + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x04000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x08000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x0a000, 4, 1)) return 1; + + if (BurnLoadRom(DrvI8039ROM, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + memcpy (DrvGfxROM0 + 0x1000, DrvGfxROM0 + 0x0800, 0x0800); + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x02000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x04000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x02000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x06000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0a000, 15, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 16, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 17, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 18, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 19, 1)) return 1; + + if (BurnLoadRom(DrvSampleROM + 0x00000, 20, 1)) return 1; + if (BurnLoadRom(DrvSampleROM + 0x02000, 21, 1)) return 1; + if (BurnLoadRom(DrvSampleROM + 0x04000, 22, 1)) return 1; + if (BurnLoadRom(DrvSampleROM + 0x06000, 23, 1)) return 1; + if (BurnLoadRom(DrvSampleROM + 0x08000, 24, 1)) return 1; + + return 0; +} + +static INT32 wilytowrInit() +{ + return DrvInit(m63_main_map, wilytowerLoadRoms, 238, 0x100, 60); +} + +static INT32 atomboyInit() +{ + return DrvInit(m63_main_map, wilytowerLoadRoms, 238, 0x100, 60/2); +} + +static INT32 fghtbsktInit() +{ + return DrvInit(fghtbskt_main_map, fghtbsktLoadRoms, 240, 0x010, 60/2); +} + +static void draw_bg_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= DrvScrRAM[(offs & 0x1f) * 8] + 16; + if (sy < -7) sy += 256; + if (sy >= nScreenHeight) continue; + + INT32 attr = DrvColRAM[offs]; + INT32 code = DrvVidRAM0[offs] | ((attr & 0x30) << 4); + INT32 color = (attr & 0x0f) | (*palette_bank << 4); + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, 248 - sx, 216 - sy, color, 3, 0, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM1); + } + } +} + +static void draw_fg_layer() +{ + for (INT32 offs = (256/8)*(16/8); offs < (32 * 32) - ((256/8)*(16/8)); offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = ((offs >> 5) << 3) - 16; + + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, DrvVidRAM1[offs], 248 - sx, 216 - sy, 0, 2, 0, char_color_offset, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, DrvVidRAM1[offs], sx, sy, 0, 2, 0, char_color_offset, DrvGfxROM0); + } + } +} + +static void draw_sprite_tile(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy) +{ + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM2); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0x100; offs += 4) + { + INT32 sx = DrvSprRAM[offs + 3]; + INT32 attr = DrvSprRAM[offs + 2]; + INT32 code = (DrvSprRAM[offs + 1]) | ((attr & 0x10) << 4); + INT32 sy = (sy_offset - DrvSprRAM[offs]) - 16; + + INT32 color = (attr & 0x0f) | (*palette_bank << 4); + INT32 flipx = (attr & 0x20); + INT32 flipy = 0; + + if (*flipscreen) + { + sx = 240 - sx; + sy = sy_offset - sy; + flipx = !flipx; + flipy = !flipy; + } + + draw_sprite_tile(code, color, sx, sy, flipx, flipy); + + if (sx > 0xf0) { + draw_sprite_tile(code, color, sx, sy, flipx, flipy); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + m63PaletteRecalc(); + DrvRecalc = 0; + } + + draw_bg_layer(); + draw_sprites(); + draw_fg_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void sample_render(short *pSoundBuf, INT32 nLength) +{ + if (sample_sel == -1) return; + + double Addr = sample_pos + sample_sel; + double Step = (double)8000 / nBurnSoundRate; + + for (INT32 i = 0; i < nLength && Addr < 0xa000; i += 2, Addr += Step) { + short Sample = (short)((DrvSampleROM[(int)Addr]^0x80) << 8); + + pSoundBuf[i ] += Sample; + pSoundBuf[i + 1] += Sample; + } + + sample_pos = (int)Addr; + if (Addr >= 0xa000) sample_sel = -1; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0, 2); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nCyclesTotal[2] = { 3000000 / 60, 3000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + INT32 nInterleave = 100; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += ZetRun(nCyclesTotal[0] / nInterleave); + nCyclesDone[1] += I8039Run(nCyclesTotal[1] / nInterleave); + } + + if (sound_interrupt_count == 30) { + if (nCurrentFrame & 1) sound_irq = 1; + } else { + sound_irq = 1; + } + + if (*interrupt_enable) ZetNmi(); + + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + AY8910Update(0, &pAY8910Buffer[3], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + nSample += pAY8910Buffer[3][n]; + nSample += pAY8910Buffer[4][n]; + nSample += pAY8910Buffer[5][n]; + + nSample /= 8; + + if (nSample < -32768) { + nSample = -32768; + } else { + if (nSample > 32767) { + nSample = 32767; + } + } + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + + sample_render(pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + I8039Scan(nAction, pnMin); + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(m63_sound_p1); + SCAN_VAR(m63_sound_p2); + SCAN_VAR(sound_irq); + SCAN_VAR(sample_pos); + SCAN_VAR(sample_sel); + } + + return 0; +} + + +// Wily Tower + +static struct BurnRomInfo wilytowrRomDesc[] = { + { "wt4e.bin", 0x2000, 0xa38e4b8a, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 code + { "wt4h.bin", 0x2000, 0xc1405ceb, 1 | BRF_PRG | BRF_ESS }, // 1 + { "wt4j.bin", 0x2000, 0x379fb1c3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "wt4k.bin", 0x2000, 0x2dd6f9c7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "wt_a-4m.bin", 0x2000, 0xc1f8a7d5, 1 | BRF_PRG | BRF_ESS }, // 4 + { "wt_a-4n.bin", 0x2000, 0xb212f7d2, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "wt4d.bin", 0x1000, 0x25a171bf, 2 | BRF_PRG | BRF_ESS }, // 6 I8039 code + + { "wt_b-5e.bin", 0x1000, 0xfe45df43, 3 | BRF_GRA }, // 7 Characters + { "wt_b-5f.bin", 0x1000, 0x87a17eff, 3 | BRF_GRA }, // 8 + + { "wtb5a.bin", 0x2000, 0xefc1cbfa, 4 | BRF_GRA }, // 9 Tiles + { "wtb5b.bin", 0x2000, 0xab4bfd07, 4 | BRF_GRA }, // 10 + { "wtb5d.bin", 0x2000, 0x40f23e1d, 4 | BRF_GRA }, // 11 + + { "wt2j.bin", 0x1000, 0xd1bf0670, 5 | BRF_GRA }, // 12 Sprites + { "wt3k.bin", 0x1000, 0x83c39a0e, 5 | BRF_GRA }, // 13 + { "wt_a-3m.bin", 0x1000, 0xe7e468ae, 5 | BRF_GRA }, // 14 + { "wt_a-3n.bin", 0x1000, 0x0741d1a9, 5 | BRF_GRA }, // 15 + { "wt_a-3p.bin", 0x1000, 0x7299f362, 5 | BRF_GRA }, // 16 + { "wt_a-3s.bin", 0x1000, 0x9b37d50d, 5 | BRF_GRA }, // 17 + + { "wt_a-6d.bin", 0x1000, 0xa5dde29b, 6 | BRF_SND }, // 18 Sound data + + { "wt_a-5s-.bpr", 0x0100, 0x041950e7, 7 | BRF_GRA }, // 19 Color PROMs + { "wt_a-5r-.bpr", 0x0100, 0xbc04bf25, 7 | BRF_GRA }, // 20 + { "wt_a-5p-.bpr", 0x0100, 0xed819a19, 7 | BRF_GRA }, // 21 + { "wt_b-9l-.bpr", 0x0020, 0xd2728744, 7 | BRF_GRA }, // 22 +}; + +STD_ROM_PICK(wilytowr) +STD_ROM_FN(wilytowr) + +struct BurnDriver BurnDrvWilytowr = { + "wilytowr", NULL, NULL, NULL, "1984", + "Wily Tower\0", NULL, "Irem", "M63", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_IREM_M63, GBF_PLATFORM, 0, + NULL, wilytowrRomInfo, wilytowrRomName, NULL, NULL, WilytowrInputInfo, WilytowrDIPInfo, + wilytowrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x104, + 256, 224, 4, 3 +}; + + +// Atomic Boy (revision B) + +static struct BurnRomInfo atomboyRomDesc[] = { + { "wt_a-4e.bin", 0x2000, 0xf7978185, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 code + { "wt_a-4h.bin", 0x2000, 0x0ca9950b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "wt_a-4j.bin", 0x2000, 0x1badbc65, 1 | BRF_PRG | BRF_ESS }, // 2 + { "wt_a-4k.bin", 0x2000, 0x5a341f75, 1 | BRF_PRG | BRF_ESS }, // 3 + { "wt_a-4m.bin", 0x2000, 0xc1f8a7d5, 1 | BRF_PRG | BRF_ESS }, // 4 + { "wt_a-4n.bin", 0x2000, 0xb212f7d2, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "wt_a-4d-b.bin", 0x2000, 0x793ea53f, 2 | BRF_PRG | BRF_ESS }, // 6 I8039 code + + { "wt_b-5e.bin", 0x1000, 0xfe45df43, 3 | BRF_GRA }, // 7 Characters + { "wt_b-5f.bin", 0x1000, 0x87a17eff, 3 | BRF_GRA }, // 8 + + { "wt_b-5a.bin", 0x2000, 0xda22c452, 4 | BRF_GRA }, // 9 Tiles + { "wt_b-5b.bin", 0x2000, 0x4fb25a1f, 4 | BRF_GRA }, // 10 + { "wt_b-5d.bin", 0x2000, 0x75be2604, 4 | BRF_GRA }, // 11 + + { "wt_a-3j-b.bin", 0x2000, 0x996470f1, 5 | BRF_GRA }, // 12 Sprites + { "wt_a-3k-b.bin", 0x2000, 0x8f4ec45c, 5 | BRF_GRA }, // 13 + { "wt_a-3m-b.bin", 0x2000, 0x4ac40358, 5 | BRF_GRA }, // 14 + { "wt_a-3n-b.bin", 0x2000, 0x709eef5b, 5 | BRF_GRA }, // 15 + { "wt_a-3p-b.bin", 0x2000, 0x3018b840, 5 | BRF_GRA }, // 16 + { "wt_a-3s-b.bin", 0x2000, 0x05a251d4, 5 | BRF_GRA }, // 17 + + { "wt_a-6d.bin", 0x1000, 0xa5dde29b, 6 | BRF_SND }, // 18 Sound data + + { "wt_a-5s-b.bpr", 0x0100, 0x991e2a04, 7 | BRF_GRA }, // 19 Color PROMs + { "wt_a-5r-b.bpr", 0x0100, 0xfb3822b7, 7 | BRF_GRA }, // 20 + { "wt_a-5p-b.bpr", 0x0100, 0x95849f7d, 7 | BRF_GRA }, // 21 + { "wt_b-9l-.bpr", 0x0020, 0xd2728744, 7 | BRF_GRA }, // 22 +}; + +STD_ROM_PICK(atomboy) +STD_ROM_FN(atomboy) + +struct BurnDriver BurnDrvAtomboy = { + "atomboy", "wilytowr", NULL, NULL, "1985", + "Atomic Boy (revision B)\0", NULL, "Irem (Memetron license)", "M63", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_IREM_M63, GBF_PLATFORM, 0, + NULL, atomboyRomInfo, atomboyRomName, NULL, NULL, WilytowrInputInfo, WilytowrDIPInfo, + atomboyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x104, + 256, 224, 4, 3 +}; + + +// Atomic Boy (revision A) + +static struct BurnRomInfo atomboyaRomDesc[] = { + { "wt_a-4e.bin", 0x2000, 0xf7978185, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 code + { "wt_a-4h.bin", 0x2000, 0x0ca9950b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "wt_a-4j.bin", 0x2000, 0x1badbc65, 1 | BRF_PRG | BRF_ESS }, // 2 + { "wt_a-4k.bin", 0x2000, 0x5a341f75, 1 | BRF_PRG | BRF_ESS }, // 3 + { "wt_a-4m.bin", 0x2000, 0xc1f8a7d5, 1 | BRF_PRG | BRF_ESS }, // 4 + { "wt_a-4n.bin", 0x2000, 0xb212f7d2, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "wt_a-4d.bin", 0x1000, 0x3d43361e, 2 | BRF_PRG | BRF_ESS }, // 6 I8039 code + + { "wt_b-5e.bin", 0x1000, 0xfe45df43, 3 | BRF_GRA }, // 7 Characters + { "wt_b-5f.bin", 0x1000, 0x87a17eff, 3 | BRF_GRA }, // 8 + + { "wt_b-5a.bin", 0x2000, 0xda22c452, 4 | BRF_GRA }, // 9 Tiles + { "wt_b-5b.bin", 0x2000, 0x4fb25a1f, 4 | BRF_GRA }, // 10 + { "wt_b-5d.bin", 0x2000, 0x75be2604, 4 | BRF_GRA }, // 11 + + { "wt_a-3j.bin", 0x1000, 0xb30ca38f, 5 | BRF_GRA }, // 12 Sprites + { "wt_a-3k.bin", 0x1000, 0x9a77eb73, 5 | BRF_GRA }, // 13 + { "wt_a-3m.bin", 0x1000, 0xe7e468ae, 5 | BRF_GRA }, // 14 + { "wt_a-3n.bin", 0x1000, 0x0741d1a9, 5 | BRF_GRA }, // 15 + { "wt_a-3p.bin", 0x1000, 0x7299f362, 5 | BRF_GRA }, // 16 + { "wt_a-3s.bin", 0x1000, 0x9b37d50d, 5 | BRF_GRA }, // 17 + + { "wt_a-6d.bin", 0x1000, 0xa5dde29b, 6 | BRF_SND }, // 18 Sound data + + { "wt_a-5s-.bpr", 0x0100, 0x041950e7, 7 | BRF_GRA }, // 19 Color PROMs + { "wt_a-5r-.bpr", 0x0100, 0xbc04bf25, 7 | BRF_GRA }, // 20 + { "wt_a-5p-.bpr", 0x0100, 0xed819a19, 7 | BRF_GRA }, // 21 + { "wt_b-9l-.bpr", 0x0020, 0xd2728744, 7 | BRF_GRA }, // 22 +}; + +STD_ROM_PICK(atomboya) +STD_ROM_FN(atomboya) + +struct BurnDriver BurnDrvAtomboya = { + "atomboya", "wilytowr", NULL, NULL, "1985", + "Atomic Boy (revision A)\0", NULL, "Irem (Memetron license)", "M63", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_IREM_M63, GBF_PLATFORM, 0, + NULL, atomboyaRomInfo, atomboyaRomName, NULL, NULL, WilytowrInputInfo, WilytowrDIPInfo, + atomboyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x104, + 256, 224, 4, 3 +}; + + +// Fighting Basketball + +static struct BurnRomInfo fghtbsktRomDesc[] = { + { "fb14.0f", 0x2000, 0x82032853, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 code + { "fb13.2f", 0x2000, 0x5306df0f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fb12.3f", 0x2000, 0xee9210d4, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fb10.6f", 0x2000, 0x6b47efba, 1 | BRF_PRG | BRF_ESS }, // 3 + { "fb09.7f", 0x2000, 0xbe69e087, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "fb07.0b", 0x1000, 0x50432dbd, 2 | BRF_PRG | BRF_ESS }, // 5 I8039 code + + { "fb08.12f", 0x1000, 0x271cd7b8, 3 | BRF_GRA }, // 6 Characters + + { "fb21.25e", 0x2000, 0x02843591, 4 | BRF_GRA }, // 7 Tiles + { "fb22.23e", 0x2000, 0xcd51d8e7, 4 | BRF_GRA }, // 8 + { "fb23.22e", 0x2000, 0x62bcac87, 4 | BRF_GRA }, // 9 + + { "fb16.35a", 0x2000, 0xa5df1652, 5 | BRF_GRA }, // 10 Sprites + { "fb15.37a", 0x2000, 0x59c4de06, 5 | BRF_GRA }, // 11 + { "fb18.32a", 0x2000, 0xc23ddcd7, 5 | BRF_GRA }, // 12 + { "fb17.34a", 0x2000, 0x7db28013, 5 | BRF_GRA }, // 13 + { "fb20.29a", 0x2000, 0x1a1b48f8, 5 | BRF_GRA }, // 14 + { "fb19.31a", 0x2000, 0x7ff7e321, 5 | BRF_GRA }, // 15 + + { "fb06.12a", 0x2000, 0xbea3df99, 6 | BRF_SND }, // 16 Sound data + + { "fb_r.9e", 0x0100, 0xc5cdc8ba, 7 | BRF_GRA }, // 17 Color PROMs + { "fb_g.10e", 0x0100, 0x1460c936, 7 | BRF_GRA }, // 18 + { "fb_b.11e", 0x0100, 0xfca5bf0e, 7 | BRF_GRA }, // 19 + + { "fb01.42a", 0x2000, 0x1200b220, 8 | BRF_SND }, // 20 Samples + { "fb02.41a", 0x2000, 0x0b67aa82, 8 | BRF_SND }, // 21 + { "fb03.40a", 0x2000, 0xc71269ed, 8 | BRF_SND }, // 22 + { "fb04.39a", 0x2000, 0x02ddc42d, 8 | BRF_SND }, // 23 + { "fb05.38a", 0x2000, 0x72ea6b49, 8 | BRF_SND }, // 24 +}; + +STD_ROM_PICK(fghtbskt) +STD_ROM_FN(fghtbskt) + +struct BurnDriver BurnDrvFghtbskt = { + "fghtbskt", NULL, NULL, NULL, "1984", + "Fighting Basketball\0", NULL, "Paradise Co. Ltd.", "M63", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M63, GBF_SPORTSMISC, 0, + NULL, fghtbsktRomInfo, fghtbsktRomName, NULL, NULL, FghtbsktInputInfo, FghtbsktDIPInfo, + fghtbsktInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/irem/d_m72.cpp b/src/burn/drivers/irem/d_m72.cpp new file mode 100644 index 00000000..0a951902 --- /dev/null +++ b/src/burn/drivers/irem/d_m72.cpp @@ -0,0 +1,3928 @@ +// FB Alpha Irem M72 driver module +// Based on MAME driver by Nicola Salmoria and Nao + +/* + to do: + clean + fix/improve sound + poundfor inputs +*/ + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "vez.h" +#include "irem_cpu.h" +#include "dac.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvV30ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvV30RAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT8 *DrvProtRAM; +static UINT8 *DrvRowScroll; +static UINT8 *DrvSprRAM2; + +static UINT8 *scroll; + +static UINT8 *RamPrioBitmap; +static INT16 *dacbuffer; + +static UINT8 *soundlatch; +static UINT8 *video_enable; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; +static INT32 ym2151_previous = 0; +static UINT8 irqvector; +static INT32 sample_address; +static INT32 irq_raster_position; +static INT32 z80_reset = 0; +static INT32 majtitle_rowscroll_enable = 0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[5]; +static UINT8 DrvReset; + +const static INT32 nInterleave = 284; +static INT32 nCurrentCycles; +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; + +static INT32 ym2151_frame = 0; +static INT32 m72_video_type = 0; +static INT32 z80_nmi_enable = 0; +static INT32 enable_z80_reset = 0; // only if z80 is not rom-based! +static INT32 m72_irq_base = 0x80; +static INT32 code_mask[4]; +static INT32 graphics_length[4]; +static INT32 video_offsets[2] = { 0, 0 }; + +enum { Z80_NO_NMI=0, Z80_REAL_NMI, Z80_FAKE_NMI }; +enum { VECTOR_INIT, YM2151_ASSERT, YM2151_CLEAR, Z80_ASSERT, Z80_CLEAR }; + + +static struct BurnInputInfo CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common) + +static struct BurnInputInfo PoundforInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 2, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 0, "p1 start"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + // save space for analog inputs + {"P2 Button 3", BIT_DIGITAL, DrvJoy5 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy5 + 6, "p2 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 3, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 1, "p2 start"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy4 + 6, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p2 fire 2"}, + + // save space for analog inputs... + {"P2 Button 5", BIT_DIGITAL, DrvJoy5 + 6, "p2 fire 5"}, + {"P2 Button 6", BIT_DIGITAL, DrvJoy5 + 6, "p2 fire 6"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 4, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Poundfor) + +static struct BurnDIPInfo Dip2CoinDIPList[]= +{ + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x17, 0x01, 0x08, 0x08, "Mode 1" }, + {0x17, 0x01, 0x08, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x17, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Cont." }, + {0x17, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x17, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x17, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x17, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x17, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x17, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x17, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x17, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x17, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x17, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +static struct BurnDIPInfo Dip1CoinDIPList[]= +{ + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x16, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x16, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x16, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x16, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x16, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x16, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x16, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x16, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x17, 0x01, 0x04, 0x04, "Mode 1" }, + {0x17, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2, "Stop Mode" }, + {0x17, 0x01, 0x20, 0x20, "Off" }, + {0x17, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x80, 0x80, "Off" }, + {0x17, 0x01, 0x80, 0x00, "On" }, +}; + +static struct BurnDIPInfo RtypeDIPList[]= +{ + {0x16, 0xff, 0xff, 0xfb, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x16, 0x01, 0x08, 0x00, "50K 150K 250K 400K 600K" }, + {0x16, 0x01, 0x08, 0x08, "100K 200K 350K 500K 700K" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x17, 0x01, 0x08, 0x08, "Normal" }, + {0x17, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x17, 0x01, 0x10, 0x00, "No" }, + {0x17, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFOEXT(Rtype, Dip1Coin, Rtype ) + +static struct BurnDIPInfo RtypepDIPList[]= +{ + {0x16, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, +}; + +STDDIPINFOEXT(Rtypep, Rtype, Rtypep ) + +static struct BurnDIPInfo XmultiplDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Very Easy" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Normal" }, + {0x16, 0x01, 0x03, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x0c, 0x08, "1" }, + {0x16, 0x01, 0x0c, 0x04, "2" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright (single)" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + {0x17, 0x01, 0x02, 0x00, "Upright (double) On" }, + {0x17, 0x01, 0x02, 0x02, "Upright (double) Off" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Upright (double) Mode" }, + {0x17, 0x01, 0x10, 0x10, "Off" }, + {0x17, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x17, 0x01, 0x20, 0x00, "No" }, + {0x17, 0x01, 0x20, 0x20, "Yes" }, +}; + +STDDIPINFOEXT(Xmultipl, Dip1Coin, Xmultipl ) + +static struct BurnDIPInfo DbreedDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xf5, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x08, 0x08, "Off" }, + {0x17, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x17, 0x01, 0x10, 0x00, "No" }, + {0x17, 0x01, 0x10, 0x10, "Yes" }, +}; + +STDDIPINFOEXT(Dbreed, Dip1Coin, Dbreed ) + +static struct BurnDIPInfo BchopperDIPList[]= +{ + {0x16, 0xff, 0xff, 0xfb, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x00, "1" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x16, 0x01, 0x08, 0x08, "80K 200K 350K" }, + {0x16, 0x01, 0x08, 0x00, "100K 250K 400K" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x17, 0x01, 0x08, 0x08, "Normal" }, + {0x17, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x17, 0x01, 0x10, 0x00, "No" }, + {0x17, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFOEXT(Bchopper, Dip1Coin, Bchopper ) + +static struct BurnDIPInfo NspiritDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xf5, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + {0x16, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x08, 0x08, "Off" }, + {0x17, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x17, 0x01, 0x10, 0x00, "No" }, + {0x17, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFOEXT(Nspirit, Dip1Coin, Nspirit ) + +static struct BurnDIPInfo ImgfightDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xe5, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x08, "Hard" }, + {0x16, 0x01, 0x0c, 0x04, "Hardest" }, + {0x16, 0x01, 0x0c, 0x00, "Debug Mode 2 lap" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x08, 0x08, "Off" }, + {0x17, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFOEXT(Imgfight, Dip1Coin, Imgfight ) + +static struct BurnDIPInfo Rtype2DIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + {0x16, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x02, 0x00, "Off" }, + {0x17, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x17, 0x01, 0x18, 0x10, "Upright" }, + {0x17, 0x01, 0x18, 0x00, "Upright (2P)" }, + {0x17, 0x01, 0x18, 0x18, "Cocktail" }, +}; + +STDDIPINFOEXT(Rtype2, Dip1Coin, Rtype2 ) + +static struct BurnDIPInfo LohtDIPList[]= +{ + {0x16, 0xff, 0xff, 0xfb, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x00, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x02, "4" }, + {0x16, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x02, 0x00, "Upright" }, + {0x17, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x17, 0x01, 0x18, 0x00, "Easy" }, + {0x17, 0x01, 0x18, 0x18, "Normal" }, + {0x17, 0x01, 0x18, 0x10, "Hard" }, + {0x17, 0x01, 0x18, 0x08, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFOEXT(Loht, Dip1Coin, Loht ) + +static struct BurnDIPInfo AirduelDIPList[]= +{ + {0x16, 0xff, 0xff, 0xbf, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFOEXT(Airduel, Dip2Coin, Airduel ) + +static struct BurnDIPInfo GallopDIPList[]= +{ + {0x16, 0xff, 0xff, 0xbf, NULL }, + {0x17, 0xff, 0xff, 0xf9, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 0, "Allow Continue" }, + {0x16, 0x01, 0x20, 0x00, "No" }, + {0x16, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x17, 0x01, 0x06, 0x00, "Upright" }, + {0x17, 0x01, 0x06, 0x02, "Upright (2P)" }, + {0x17, 0x01, 0x06, 0x06, "Cocktail" }, +}; + +STDDIPINFOEXT(Gallop, Dip2Coin, Gallop ) + +static struct BurnDIPInfo KengoDIPList[]= +{ + {0x16, 0xff, 0xff, 0xbf, NULL }, + {0x17, 0xff, 0xff, 0xf9, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x20, 0x00, "No" }, + {0x16, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFOEXT(Kengo, Dip2Coin, Kengo ) + +static struct BurnDIPInfo HharryDIPList[]= +{ + {0x16, 0xff, 0xff, 0xbf, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Continue Limit" }, + {0x16, 0x01, 0x10, 0x00, "No" }, + {0x16, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x20, 0x00, "No" }, + {0x16, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x17, 0x01, 0x06, 0x04, "Upright" }, + {0x17, 0x01, 0x06, 0x00, "Upright (2P)" }, + {0x17, 0x01, 0x06, 0x06, "Cocktail" }, +}; + +STDDIPINFOEXT(Hharry, Dip2Coin, Hharry ) + +static struct BurnDIPInfo PoundforDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xbf, NULL }, + {0x0f, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Round Time" }, + {0x0e, 0x01, 0x03, 0x02, "60" }, + {0x0e, 0x01, 0x03, 0x03, "90" }, + {0x0e, 0x01, 0x03, 0x01, "120" }, + {0x0e, 0x01, 0x03, 0x00, "150" }, + + {0 , 0xfe, 0 , 2, "Matches/Credit (2P)" }, + {0x0e, 0x01, 0x04, 0x04, "1" }, + {0x0e, 0x01, 0x04, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Rounds/Match" }, + {0x0e, 0x01, 0x08, 0x08, "2" }, + {0x0e, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x0e, 0x01, 0x10, 0x10, "Normal" }, + {0x0e, 0x01, 0x10, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Trackball Size" }, + {0x0e, 0x01, 0x20, 0x20, "Small" }, + {0x0e, 0x01, 0x20, 0x00, "Large" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0f, 0x01, 0x01, 0x01, "Off" }, + {0x0f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x0f, 0x01, 0x06, 0x04, "Upright" }, + {0x0f, 0x01, 0x06, 0x02, "Upright (2P)" }, + {0x0f, 0x01, 0x06, 0x06, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x0f, 0x01, 0x08, 0x08, "Mode 1" }, + {0x0f, 0x01, 0x08, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x0f, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x0f, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x0f, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x0f, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x0f, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x0f, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0xf0, 0x10, "1 Coin/1 Credit, 1 Coin/Cont."}, + {0x0f, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x0f, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x0f, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x0f, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x0f, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Poundfor) + +//-------------------------------------------------------------------------------------------------------------------------------------------------- +// Protection handlers + +static const UINT8 *protection_code = NULL; +static const UINT8 *protection_crc = NULL; +static const INT32 *protection_sample_offsets = NULL; + +static UINT8 protection_read(INT32 address) +{ + if (address == 0xb0ffb) { + if (protection_code != NULL) { + memcpy (DrvProtRAM, protection_code, 96); + } + } + + return DrvProtRAM[address & 0xfff]; +} + +static void protection_write(INT32 address, UINT8 data) +{ + DrvProtRAM[address & 0xfff] = data ^ 0xff; + + if (address == 0xb0fff && data == 0) { + if (protection_crc != NULL) { + memcpy (DrvProtRAM + 0xfe0, protection_crc, 18); + } + } +} + +static void protection_sample_offset_write(UINT8 data) +{ + if (protection_sample_offsets != NULL) { + if (data < protection_sample_offsets[0]) { + sample_address = protection_sample_offsets[data+1]; + } + } +} + +static void m72_install_protection(const UINT8 *code, const UINT8 *crc, const INT32 *offs) +{ + protection_code = code; + protection_crc = crc; + protection_sample_offsets = offs; +} + +#define install_protection(name) m72_install_protection(name##_code, name##_crc, name##_sample_offsets) + +/* Battle Chopper / Mr. Heli */ +static const INT32 bchopper_sample_offsets[7] = { 6, 0x0000, 0x0010, 0x2510, 0x6510, 0x8510, 0x9310 }; + +static const UINT8 bchopper_code[96] = +{ + 0x68,0x00,0xa0, // push 0a000h + 0x1f, // pop ds + 0xc6,0x06,0x38,0x38,0x53, // mov [3838h], byte 053h + 0xc6,0x06,0x3a,0x38,0x41, // mov [383ah], byte 041h + 0xc6,0x06,0x3c,0x38,0x4d, // mov [383ch], byte 04dh + 0xc6,0x06,0x3e,0x38,0x4f, // mov [383eh], byte 04fh + 0xc6,0x06,0x40,0x38,0x54, // mov [3840h], byte 054h + 0xc6,0x06,0x42,0x38,0x4f, // mov [3842h], byte 04fh + 0x68,0x00,0xb0, // push 0b000h + 0x1f, // pop ds + 0xc6,0x06,0x00,0x09,0x49^0xff, // mov [0900h], byte 049h + 0xc6,0x06,0x00,0x0a,0x49^0xff, // mov [0a00h], byte 049h + 0xc6,0x06,0x00,0x0b,0x49^0xff, // mov [0b00h], byte 049h + 0xc6,0x06,0x00,0x00,0xcb^0xff, // mov [0000h], byte 0cbh ; retf : bypass protection check during the game + 0x68,0x00,0xd0, // push 0d000h + 0x1f, // pop ds + // the following is for mrheli only, the game checks for + // "This game can only be played in Japan..." message in the video text buffer + // the message is nowhere to be found in the ROMs, so has to be displayed by the mcu + 0xc6,0x06,0x70,0x16,0x77, // mov [1670h], byte 077h + 0xea,0x68,0x01,0x40,0x00 // jmp 0040:$0168 +}; + +static const UINT8 bchopper_crc[18] = { + 0x1a,0x12,0x5c,0x08,0x84,0xb6,0x73,0xd1,0x54,0x91,0x94,0xeb,0x00,0x00 +}; + +static const UINT8 mrheli_crc[18] = { + 0x24,0x21,0x1f,0x14,0xf9,0x28,0xfb,0x47,0x4c,0x77,0x9e,0xc2,0x00,0x00 +}; + +/* X Multiply */ +static const INT32 xmultiplm72_sample_offsets[4] = { 3, 0x0000, 0x0020, 0x1a40 }; + +static const UINT8 xmultiplm72_code[96] = { + 0xea,0x30,0x02,0x00,0x0e // jmp 0e00:$0230 +}; + +static const UINT8 xmultiplm72_crc[18] = { + 0x73,0x82,0x4e,0x3f, 0xfc,0x56,0x59,0x06,0x05,0x48,0xa8,0xf4,0x00,0x00 +}; + +/* Dragon Breed */ +static const INT32 dbreedm72_sample_offsets[10] = { 9, 0x00000, 0x00020, 0x02c40, 0x08160, 0x0c8c0, 0x0ffe0, 0x13000, 0x15820, 0x15f40 }; + +static const UINT8 dbreedm72_code[96] = { + 0xea,0x6c,0x00,0x00,0x00 // jmp 0000:$006c +}; + +static const UINT8 dbreedm72_crc[18] ={ + 0xa4,0x96,0x5f,0xc0, 0xab,0x49,0x9f,0x19,0x84,0xe6,0xd6,0xca,0x00,0x00 +}; + +/* Ninja Spirit */ +static const INT32 nspirit_sample_offsets[10] = { 9, 0x0000, 0x0020, 0x2020, 0, 0x5720, 0, 0x7b60, 0x9b60, 0xc360 }; + +static const UINT8 nspirit_code[96] = +{ + 0x68,0x00,0xa0, // push 0a000h + 0x1f, // pop ds + 0xc6,0x06,0x38,0x38,0x4e, // mov [3838h], byte 04eh + 0xc6,0x06,0x3a,0x38,0x49, // mov [383ah], byte 049h + 0xc6,0x06,0x3c,0x38,0x4e, // mov [383ch], byte 04eh + 0xc6,0x06,0x3e,0x38,0x44, // mov [383eh], byte 044h + 0xc6,0x06,0x40,0x38,0x4f, // mov [3840h], byte 04fh + 0xc6,0x06,0x42,0x38,0x55, // mov [3842h], byte 055h + 0x68,0x00,0xb0, // push 0b000h + 0x1f, // pop ds + 0xc6,0x06,0x00,0x09,0x49^0xff, // mov [0900h], byte 049h + 0xc6,0x06,0x00,0x0a,0x49^0xff, // mov [0a00h], byte 049h + 0xc6,0x06,0x00,0x0b,0x49^0xff, // mov [0b00h], byte 049h + 0x68,0x00,0xd0, // push 0d000h + 0x1f, // pop ds + // the following is for nspiritj only, the game checks for + // "This game can only be played in Japan..." message in the video text buffer + // the message is nowhere to be found in the ROMs, so has to be displayed by the mcu + 0xc6,0x06,0x70,0x16,0x57, // mov [1670h], byte 057h + 0xc6,0x06,0x71,0x16,0x00, // mov [1671h], byte 000h + 0xea,0x00,0x00,0x40,0x00 // jmp 0040:$0000 +}; + +static const UINT8 nspirit_crc[18] = { + 0xfe,0x94,0x6e,0x4e, 0xc8,0x33,0xa7,0x2d,0xf2,0xa3,0xf9,0xe1, 0xa9,0x6c,0x02,0x95, 0x00,0x00 +}; + +static const UINT8 nspiritj_crc[18] = { + 0x26,0xa3,0xa5,0xe9, 0xc8,0x33,0xa7,0x2d,0xf2,0xa3,0xf9,0xe1, 0xbc,0x6c,0x01,0x95, 0x00,0x00 +}; + +/* Image Fight */ +static const INT32 imgfight_sample_offsets[8] = { 7, 0x0000, 0x0020, 0x44e0, 0x98a0, 0xc820, 0xf7a0, 0x108c0 }; + +static const UINT8 imgfight_code[96] = +{ + 0x68,0x00,0xa0, // push 0a000h + 0x1f, // pop ds + 0xc6,0x06,0x38,0x38,0x50, // mov [3838h], byte 050h + 0xc6,0x06,0x3a,0x38,0x49, // mov [383ah], byte 049h + 0xc6,0x06,0x3c,0x38,0x43, // mov [383ch], byte 043h + 0xc6,0x06,0x3e,0x38,0x4b, // mov [383eh], byte 04bh + 0xc6,0x06,0x40,0x38,0x45, // mov [3840h], byte 045h + 0xc6,0x06,0x42,0x38,0x54, // mov [3842h], byte 054h + 0x68,0x00,0xb0, // push 0b000h + 0x1f, // pop ds + 0xc6,0x06,0x00,0x09,0x49^0xff, // mov [0900h], byte 049h + 0xc6,0x06,0x00,0x0a,0x49^0xff, // mov [0a00h], byte 049h + 0xc6,0x06,0x00,0x0b,0x49^0xff, // mov [0b00h], byte 049h + 0xc6,0x06,0x20,0x09,0x49^0xff, // mov [0920h], byte 049h + 0xc6,0x06,0x21,0x09,0x4d^0xff, // mov [0921h], byte 04dh + 0xc6,0x06,0x22,0x09,0x41^0xff, // mov [0922h], byte 041h + 0xc6,0x06,0x23,0x09,0x47^0xff, // mov [0923h], byte 047h + 0x68,0x00,0xd0, // push 0d000h + 0x1f, // pop ds + // the game checks for + // "This game can only be played in Japan..." message in the video text buffer + // the message is nowhere to be found in the ROMs, so has to be displayed by the mcu + 0xc6,0x06,0xb0,0x1c,0x57, // mov [1cb0h], byte 057h + 0xea,0x00,0x00,0x40,0x00 // jmp 0040:$0000 +}; + +static const UINT8 imgfight_crc[18] = { + 0x7e,0xcc,0xec,0x03, 0x04,0x33,0xb6,0xc5, 0xbf,0x37,0x92,0x94, 0x00,0x00 +}; + +/* Air Duel */ +static const INT32 airduel_sample_offsets[17] = { + 16, + 0x00000, 0x00020, 0x03ec0, 0x05640, 0x06dc0, 0x083a0, 0x0c000, 0x0eb60, + 0x112e0, 0x13dc0, 0x16520, 0x16d60, 0x18ae0, 0x1a5a0, 0x1bf00, 0x1c340 }; + +static const UINT8 airduel_code[96] = +{ + 0x68,0x00,0xd0, // push 0d000h + 0x1f, // pop ds + // the game checks for + // "This game can only be played in Japan..." message in the video text buffer + // the message is nowhere to be found in the ROMs, so has to be displayed by the mcu + 0xc6,0x06,0xc0,0x1c,0x57, // mov [1cc0h], byte 057h + 0xea,0x69,0x0b,0x00,0x00 // jmp 0000:$0b69 +}; + +static const UINT8 airduel_crc[18] = { + 0x72,0x9c,0xca,0x85, 0xc9,0x12,0xcc,0xea, 0x00,0x00 +}; + +/* Daiku no Gensan */ +static const INT32 dkgenm72_sample_offsets[29] = { + 28, + 0x00000, 0x00020, 0x01800, 0x02da0, 0x03be0, 0x05ae0, 0x06100, 0x06de0, + 0x07260, 0x07a60, 0x08720, 0x0a5c0, 0x0c3c0, 0x0c7a0, 0x0e140, 0x0fb00, + 0x10fa0, 0x10fc0, 0x10fe0, 0x11f40, 0x12b20, 0x130a0, 0x13c60, 0x14740, + 0x153c0, 0x197e0, 0x1af40, 0x1c080 }; + +static const UINT8 dkgenm72_code[96] = { + 0xea,0x3d,0x00,0x00,0x10 // jmp 1000:$003d +}; + +static const UINT8 dkgenm72_crc[18] = { + 0xc8,0xb4,0xdc,0xf8, 0xd3,0xba,0x48,0xed,0x79,0x08,0x1c,0xb3, 0x00,0x00 +}; + +/* Legend of Hero Tonma */ +static const INT32 loht_sample_offsets[8] = { 7, 0x0000, 0x0020, 0, 0x2c40, 0x4320, 0x7120, 0xb200 }; + +static const UINT8 loht_code[96] = +{ + 0x68,0x00,0xa0, // push 0a000h + 0x1f, // pop ds + 0xc6,0x06,0x3c,0x38,0x47, // mov [383ch], byte 047h + 0xc6,0x06,0x3d,0x38,0x47, // mov [383dh], byte 047h + 0xc6,0x06,0x42,0x38,0x44, // mov [3842h], byte 044h + 0xc6,0x06,0x43,0x38,0x44, // mov [3843h], byte 044h + 0x68,0x00,0xb0, // push 0b000h + 0x1f, // pop ds + 0xc6,0x06,0x00,0x09,0x49^0xff, // mov [0900h], byte 049h + 0xc6,0x06,0x00,0x0a,0x49^0xff, // mov [0a00h], byte 049h + 0xc6,0x06,0x00,0x0b,0x49^0xff, // mov [0b00h], byte 049h + + 0x68,0x00,0xd0, // push 0d000h // Japan set only + 0x1f, // pop ds // Japan set only + 0xc6,0x06,0x70,0x16,0x57, // mov [1670h], byte 057h // Japan set only - checks this (W) of WARNING + + 0xea,0x5d,0x01,0x40,0x00 // jmp 0040:$015d +}; + +static const UINT8 loht_crc[18] = { + 0x39,0x00,0x82,0xae, 0x2c,0x9d,0x4b,0x73,0xfb,0xac,0xd4,0x6d, 0x6d,0x5b,0x77,0xc0, 0x00,0x00 +}; + +/* Gallop - Armed police Unit */ +static const INT32 gallop_sample_offsets[32] = { + 31, + 0x00000, 0x00020, 0x00040, 0x01360, 0x02580, 0x04f20, 0x06240, 0x076e0, + 0x08660, 0x092a0, 0x09ba0, 0x0a560, 0x0cee0, 0x0de20, 0x0e620, 0x0f1c0, + 0x10200, 0x10220, 0x10240, 0x11380, 0x12760, 0x12780, 0x127a0, 0x13c40, + 0x140a0, 0x16760, 0x17e40, 0x18ee0, 0x19f60, 0x1bbc0, 0x1cee0 }; + +//-------------------------------------------------------------------------------------------------------------------------------------------------- + + +static void setvector_callback(INT32 param) +{ + switch (param) + { + case VECTOR_INIT: irqvector = 0xff; break; + case YM2151_ASSERT: irqvector &= 0xef; break; + case YM2151_CLEAR: irqvector |= 0x10; break; + case Z80_ASSERT: irqvector &= 0xdf; break; + case Z80_CLEAR: irqvector |= 0x20; break; + } + + ZetSetVector(irqvector); + ZetSetIRQLine(0, (irqvector == 0xff) ? ZET_IRQSTATUS_NONE : ZET_IRQSTATUS_ACK); +} + +static void sync_cpus() +{ + INT32 cycles = (INT32)((float)(VezTotalCycles() * 0.447443125)); + + cycles -= nCyclesDone[1]; + + if (cycles > 0) { + if (z80_reset == 0) { + nCyclesDone[1] += ZetRun(cycles); + } else { + nCyclesDone[1] += cycles; + ZetIdle(cycles); + } + } +} + +static void sync_ym2151() +{ + if (z80_reset) return; + + INT32 cycles = ((nBurnSoundLen * ZetTotalCycles()) / nCyclesTotal[1]) + 1; + + if (cycles != ym2151_previous) { + if (cycles > nBurnSoundLen) return; + + if ((INT32)nCurrentFrame != ym2151_frame) { + ym2151_previous = 0; + ym2151_frame = (INT32)nCurrentFrame; + } + + if (cycles > 0) { + BurnYM2151Render(pBurnSoundOut + (ym2151_previous * 2), cycles - ym2151_previous); + } + + ym2151_previous = cycles; + } +} + +static void palette_write(INT32 offset, INT32 offset2) +{ + if (offset & 1) return; + + UINT16 *pal = (UINT16*)DrvPalRAM; + offset = (offset / 2) & 0x00ff; + + INT32 offset3 = offset; + if (offset2) { + offset3 |= 0x0100; + pal += 0x1000 / 2; + } + + INT32 r = pal[offset + 0x000] & 0x1f; + INT32 g = pal[offset + 0x200] & 0x1f; + INT32 b = pal[offset + 0x400] & 0x1f; + + DrvPalette[offset3] = BurnHighCol((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), 0); +} + +UINT8 __fastcall m72_main_read(UINT32 address) +{ + if ((address & 0xff000) == 0xb0000) { + return protection_read(address); + } + + return 0; +} + +void __fastcall m72_main_write(UINT32 address, UINT8 data) +{ + if ((address & 0xff000) == 0xb0000) { + protection_write(address, data); + return; + } + + if ((address & 0xff000) == 0xc8000) { + if (address & 1) data = 0xff; + DrvPalRAM[(address & 0xdff) | 0x0000] = DrvPalRAM[(address & 0xdff) | 0x0200] = data | 0xe0; + palette_write(address, 0); + return; + } + + if ((address & 0xff000) == 0xcc000) { + if (address & 1) data = 0xff; + DrvPalRAM[(address & 0xdff) | 0x1000] = DrvPalRAM[(address & 0xdff) | 0x1200] = data | 0xe0; + palette_write(address, 1); + return; + } +} + +void __fastcall rtype2_main_write(UINT32 address, UINT8 data) +{ + if ((address & 0xff000) == 0xc8000 || (address & 0xff000) == 0xa0000 || (address & 0xff000) == 0xcc000) { + if (address & 1) data = 0xff; + DrvPalRAM[(address & 0xdff) | 0x0000] = DrvPalRAM[(address & 0xdff) | 0x0200] = data | 0xe0; + palette_write(address, 0); + return; + } + + if ((address & 0xff000) == 0xd8000 || (address & 0xff000) == 0xa8000 || (address & 0xff000) == 0xa4000) { + if (address & 1) data = 0xff; + DrvPalRAM[(address & 0xdff) | 0x1000] = DrvPalRAM[(address & 0xdff) | 0x1200] = data | 0xe0; + palette_write(address, 1); + return; + } + + switch (address) + { + case 0xb0000: + case 0xe0000: // majtitle + irq_raster_position = (irq_raster_position & 0xff00) | (data << 0); + return; + + case 0xb0001: + case 0xe0001: // majtitle + irq_raster_position = (irq_raster_position & 0x00ff) | (data << 8); + return; + + case 0xbc000: + // case 0xbc001: + case 0xec000: // majtitle + // case 0xec001: + memcpy (DrvSprBuf, DrvSprRAM, 0x0400); + return; + } +} + +void __fastcall m72_main_write_port(UINT32 port, UINT8 data) +{ +// bprintf (0, _T("%2.2x, %2.2x wp\n"), port, data); + + switch (port) + { + case 0x00: + bprintf (0, _T("%2.2x, %2.2x mwp\n"), port, data); + // sync_cpus(); + *soundlatch = data; + setvector_callback(Z80_ASSERT); + return; + + case 0x01: + return; + + case 0x02: +// case 0x03: + { + // coin counter = data & 3 (&1 = 0, &2 = 1) + // flipscreen = ((data & 0x04) >> 2) ^ ((~input_port_read(space->machine, "DSW") >> 8) & 1); + + video_enable[0] = data & 0x08; + + // bprintf (0, _T("%x\n"), data & 0x10); + if (enable_z80_reset) { + sync_cpus(); + sync_ym2151(); + if (data & 0x10) { + z80_reset = 0; + } else { + ZetReset(); + setvector_callback(VECTOR_INIT); + z80_reset = 1; + } + } + } + return; + + case 0x04: + case 0x05: + memcpy (DrvSprBuf, DrvSprRAM, 0x0400); + return; + + case 0x06: + irq_raster_position = (irq_raster_position & 0xff00) | (data << 0); + return; + + case 0x07: + irq_raster_position = (irq_raster_position & 0x00ff) | (data << 8); + return; + + case 0x40: + case 0x41: + case 0x42: + case 0x43: // nop + bprintf (0, _T("%2.2x, %2.2x\n"), port, data); + return; + + case 0x80: + case 0x81:// scrolly1 + case 0x82: + case 0x83:// scrollx1 + case 0x84: + case 0x85:// scrolly2 + case 0x86: + case 0x87:// scrollx2 + scroll[port & 0x07] = data; + return; + + // case 0x8e: + case 0x8f: + majtitle_rowscroll_enable = data ? 1 : 0; + return; + + case 0xc0: + protection_sample_offset_write(data); + return; + } +} + +static UINT16 poundfor_trackball_r(INT32 offset) +{ + static INT32 prev[4],diff[4]; +// static const char *const axisnames[] = { "TRACK0_X", "TRACK0_Y", "TRACK1_X", "TRACK1_Y" }; + +#if 0 + if (offset == 0) + { + INT32 i,curr; + + for (i = 0;i < 4;i++) + { + curr = input_port_read(space->machine, axisnames[i]); + diff[i] = (curr - prev[i]); + prev[i] = curr; + } + } +#endif + prev[0] = 0; + diff[0] = diff[1] = diff[2] = diff[3] = ~0; + INT32 input = DrvInputs[0] | (DrvInputs[3] << 8); + + switch (offset) + { + default: + case 0: + return (diff[0] & 0xff) | ((diff[2] & 0xff) << 8); + case 1: + return ((diff[0] >> 8) & 0x1f) | (diff[2] & 0x1f00) | (~input & 0xe0e0); + case 2: + return (diff[1] & 0xff) | ((diff[3] & 0xff) << 8); + case 3: + return ((diff[1] >> 8) & 0x1f) | (diff[3] & 0x1f00); + } + + return 0; +} + +UINT8 __fastcall m72_main_read_port(UINT32 port) +{ + switch (port) + { + case 0x00: return DrvInputs[0]; + case 0x01: return DrvInputs[1]; + case 0x02: return DrvInputs[2]; + case 0x03: return 0xff; + case 0x04: return DrvDips[0]; + case 0x05: return DrvDips[1]; + } + + if ((port & 0xf8) == 0x08) { + INT32 ret = poundfor_trackball_r((port / 2) & 0x03); + if (port & 1) return ret >> 8; + else return ret; + } + + return 0; +} + +void __fastcall m72_sound_write_port(UINT16 port, UINT8 data) +{ +// bprintf (0, _T("%2.2x, %2.2x wp\n"), port & 0xff, data); + + switch (port & 0xff) + { + case 0x00: + case 0x40: // poundfor + BurnYM2151SelectRegister(data); + return; + + case 0x01: + case 0x41: // poundfor + sync_ym2151(); + BurnYM2151WriteRegister(data); + return; + + case 0x06: + case 0x42: // poundfor + case 0x83: // rtype2 + setvector_callback(Z80_CLEAR); + return; + + case 0x10: // poundfor + case 0x11: + sample_address >>= 4; + sample_address = (sample_address & 0xff00) | (data << 0); + sample_address <<= 4; + return; + + case 0x12: + case 0x13: // poundfor + sample_address >>= 4; + sample_address = (sample_address & 0x00ff) | (data << 8); + sample_address <<= 4; + return; + + case 0x80: // rtype2 + sample_address >>= 5; + sample_address = (sample_address & 0xff00) | (data << 0); + sample_address <<= 5; + return; + + case 0x81: // rtype2 + sample_address >>= 5; + sample_address = (sample_address & 0x00ff) | (data << 8); + sample_address <<= 5; + return; + + case 0x82: + DACSignedWrite(0, data); + sample_address = (sample_address + 1) & 0x3ffff; + return; + } +} + +UINT8 __fastcall m72_sound_read_port(UINT16 port) +{ +// if ((port & 0xff) != 0x84 && (port & 0xfe) != 0x00) bprintf (0, _T("%2.2x, rp\n"), port & 0xff); + + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x40: // poundfor + case 0x41: // poundfor + return BurnYM2151ReadStatus(); + + case 0x80: // rtype2 + case 0x42: // poundfor + case 0x02: + return *soundlatch; + + case 0x84: + sync_ym2151(); + return DrvSndROM[sample_address & 0x3ffff]; + } + + return 0; +} + +static void m72YM2151IRQHandler(INT32 nStatus) +{ + setvector_callback(nStatus ? YM2151_ASSERT : YM2151_CLEAR); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + VezOpen(0); + VezReset(); + VezClose(); + + ZetOpen(0); + ZetReset(); + setvector_callback(VECTOR_INIT); + if (enable_z80_reset) { + z80_reset = 1; + } + ZetClose(); + + BurnYM2151Reset(); + DACReset(); + + ym2151_previous = 0; + sample_address = 0; + irq_raster_position = -1; + + return 0; +} + +static void common_main_cpu_map(INT32 romaddr, INT32 ramaddr) +{ + VezInit(0, V30_TYPE); + + VezOpen(0); + VezMapArea(0x00000, (romaddr-1), 0, DrvV30ROM + 0x000000); + VezMapArea(0x00000, (romaddr-1), 2, DrvV30ROM + 0x000000); + VezMapArea(0x00000+ramaddr, 0x03fff+ramaddr, 0, DrvV30RAM); + VezMapArea(0x00000+ramaddr, 0x03fff+ramaddr, 1, DrvV30RAM); + VezMapArea(0x00000+ramaddr, 0x03fff+ramaddr, 2, DrvV30RAM); +// VezMapArea(0xb0000, 0xb0fff, 2, DrvProtRAM); + VezMapArea(0xc0000, 0xc0fff, 0, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 1, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 2, DrvSprRAM); + VezMapArea(0xc8000, 0xc8fff, 0, DrvPalRAM); +// VezMapArea(0xc8000, 0xc8fff, 1, DrvPalRAM); + VezMapArea(0xc8000, 0xc8fff, 2, DrvPalRAM); + VezMapArea(0xcc000, 0xccfff, 0, DrvPalRAM + 0x1000); +// VezMapArea(0xcc000, 0xccfff, 1, DrvPalRAM + 0x1000); + VezMapArea(0xcc000, 0xccfff, 2, DrvPalRAM + 0x1000); + VezMapArea(0xd0000, 0xd3fff, 0, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 1, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 2, DrvVidRAM0); + VezMapArea(0xd8000, 0xdbfff, 0, DrvVidRAM1); + VezMapArea(0xd8000, 0xdbfff, 1, DrvVidRAM1); + VezMapArea(0xd8000, 0xdbfff, 2, DrvVidRAM1); + VezMapArea(0xe0000, 0xeffff, 0, DrvZ80RAM); + VezMapArea(0xe0000, 0xeffff, 1, DrvZ80RAM); + VezMapArea(0xe0000, 0xeffff, 2, DrvZ80RAM); + VezMapArea(0xff800, 0xfffff, 0, DrvV30ROM + 0x0ff800); + VezMapArea(0xff800, 0xfffff, 2, DrvV30ROM + 0x0ff800); + VezSetReadHandler(m72_main_read); + VezSetWriteHandler(m72_main_write); + VezSetReadPort(m72_main_read_port); + VezSetWritePort(m72_main_write_port); + VezClose(); +} + +static void common_040000_040000() { common_main_cpu_map(0x40000, 0x40000); } +static void common_080000_080000() { common_main_cpu_map(0x80000, 0x80000); } +static void common_080000_088000() { common_main_cpu_map(0x80000, 0x88000); } +static void common_080000_090000() { common_main_cpu_map(0x80000, 0x90000); } +static void common_080000_09c000() { common_main_cpu_map(0x80000, 0x9c000); } +static void common_080000_0a0000() { common_main_cpu_map(0x80000, 0xa0000); } + +static void rtype2_main_cpu_map() +{ + VezInit(0, V30_TYPE); + + VezOpen(0); + VezMapArea(0x00000, 0x7ffff, 0, DrvV30ROM + 0x000000); + VezMapArea(0x00000, 0x7ffff, 2, DrvV30ROM + 0x000000); + VezMapArea(0xc0000, 0xc0fff, 0, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 1, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 2, DrvSprRAM); + VezMapArea(0xc8000, 0xc8fff, 0, DrvPalRAM); +// VezMapArea(0xc8000, 0xc8fff, 1, DrvPalRAM); + VezMapArea(0xc8000, 0xc8fff, 2, DrvPalRAM); + VezMapArea(0xd0000, 0xd3fff, 0, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 1, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 2, DrvVidRAM0); + VezMapArea(0xd4000, 0xd7fff, 0, DrvVidRAM1); + VezMapArea(0xd4000, 0xd7fff, 1, DrvVidRAM1); + VezMapArea(0xd4000, 0xd7fff, 2, DrvVidRAM1); + VezMapArea(0xd8000, 0xd8fff, 0, DrvPalRAM + 0x1000); +// VezMapArea(0xd8000, 0xd8fff, 1, DrvPalRAM + 0x1000); + VezMapArea(0xd8000, 0xd8fff, 2, DrvPalRAM + 0x1000); + VezMapArea(0xe0000, 0xe3fff, 0, DrvV30RAM); + VezMapArea(0xe0000, 0xe3fff, 1, DrvV30RAM); + VezMapArea(0xe0000, 0xe3fff, 2, DrvV30RAM); + VezMapArea(0xff800, 0xfffff, 0, DrvV30ROM + 0x0ff800); + VezMapArea(0xff800, 0xfffff, 2, DrvV30ROM + 0x0ff800); + VezSetReadHandler(m72_main_read); + VezSetWriteHandler(rtype2_main_write); + VezSetReadPort(m72_main_read_port); + VezSetWritePort(m72_main_write_port); + VezClose(); +} + +static void hharryu_main_cpu_map() +{ + VezInit(0, V30_TYPE); + + VezOpen(0); + VezMapArea(0x00000, 0x7ffff, 0, DrvV30ROM + 0x000000); + VezMapArea(0x00000, 0x7ffff, 2, DrvV30ROM + 0x000000); + VezMapArea(0x80000, 0x83fff, 0, DrvVidRAM0); // kengo + VezMapArea(0x80000, 0x83fff, 1, DrvVidRAM0); + VezMapArea(0x80000, 0x83fff, 2, DrvVidRAM0); + VezMapArea(0x84000, 0x87fff, 0, DrvVidRAM1); // kengo + VezMapArea(0x84000, 0x87fff, 1, DrvVidRAM1); + VezMapArea(0x84000, 0x87fff, 2, DrvVidRAM1); + VezMapArea(0xa0000, 0xa0fff, 0, DrvPalRAM); +// VezMapArea(0xa0000, 0xa0fff, 1, DrvPalRAM); + VezMapArea(0xa0000, 0xa0fff, 2, DrvPalRAM); + VezMapArea(0xa8000, 0xa8fff, 0, DrvPalRAM + 0x1000); +// VezMapArea(0xa8000, 0xa8fff, 1, DrvPalRAM + 0x1000); + VezMapArea(0xa8000, 0xa8fff, 2, DrvPalRAM + 0x1000); + VezMapArea(0xc0000, 0xc0fff, 0, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 1, DrvSprRAM); + VezMapArea(0xc0000, 0xc0fff, 2, DrvSprRAM); + VezMapArea(0xd0000, 0xd3fff, 0, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 1, DrvVidRAM0); + VezMapArea(0xd0000, 0xd3fff, 2, DrvVidRAM0); + VezMapArea(0xd4000, 0xd7fff, 0, DrvVidRAM1); + VezMapArea(0xd4000, 0xd7fff, 1, DrvVidRAM1); + VezMapArea(0xd4000, 0xd7fff, 2, DrvVidRAM1); + VezMapArea(0xe0000, 0xe3fff, 0, DrvV30RAM); + VezMapArea(0xe0000, 0xe3fff, 1, DrvV30RAM); + VezMapArea(0xe0000, 0xe3fff, 2, DrvV30RAM); + VezMapArea(0xff800, 0xfffff, 0, DrvV30ROM + 0x0ff800); + VezMapArea(0xff800, 0xfffff, 2, DrvV30ROM + 0x0ff800); + VezSetReadHandler(m72_main_read); + VezSetWriteHandler(rtype2_main_write); + VezSetReadPort(m72_main_read_port); + VezSetWritePort(m72_main_write_port); + VezClose(); +} + +static void majtitle_main_cpu_map() +{ + VezInit(0, V30_TYPE); + + VezOpen(0); + VezMapArea(0x00000, 0x7ffff, 0, DrvV30ROM + 0x000000); + VezMapArea(0x00000, 0x7ffff, 2, DrvV30ROM + 0x000000); + VezMapArea(0xa0000, 0xa07ff, 0, DrvRowScroll); + VezMapArea(0xa0000, 0xa07ff, 1, DrvRowScroll); + VezMapArea(0xa0000, 0xa07ff, 2, DrvRowScroll); + VezMapArea(0xa4000, 0xa4fff, 0, DrvPalRAM + 0x1000); +// VezMapArea(0xa4000, 0xa4fff, 1, DrvPalRAM + 0x1000); + VezMapArea(0xa4000, 0xa4fff, 2, DrvPalRAM + 0x1000); + VezMapArea(0xac000, 0xaffff, 0, DrvVidRAM0); + VezMapArea(0xac000, 0xaffff, 1, DrvVidRAM0); + VezMapArea(0xac000, 0xaffff, 2, DrvVidRAM0); + VezMapArea(0xb0000, 0xbffff, 0, DrvVidRAM1); + VezMapArea(0xb0000, 0xbffff, 1, DrvVidRAM1); + VezMapArea(0xb0000, 0xbffff, 2, DrvVidRAM1); + VezMapArea(0xc0000, 0xc07ff, 0, DrvSprRAM); + VezMapArea(0xc0000, 0xc07ff, 1, DrvSprRAM); + VezMapArea(0xc0000, 0xc07ff, 2, DrvSprRAM); + VezMapArea(0xc8000, 0xc87ff, 0, DrvSprRAM2); + VezMapArea(0xc8000, 0xc87ff, 1, DrvSprRAM2); + VezMapArea(0xc8000, 0xc87ff, 2, DrvSprRAM2); + VezMapArea(0xcc000, 0xccfff, 0, DrvPalRAM); +// VezMapArea(0xcc000, 0xccfff, 1, DrvPalRAM); + VezMapArea(0xcc000, 0xccfff, 2, DrvPalRAM); + VezMapArea(0xd0000, 0xd3fff, 0, DrvV30RAM); + VezMapArea(0xd0000, 0xd3fff, 1, DrvV30RAM); + VezMapArea(0xd0000, 0xd3fff, 2, DrvV30RAM); + VezMapArea(0xff800, 0xfffff, 0, DrvV30ROM + 0x0ff800); + VezMapArea(0xff800, 0xfffff, 2, DrvV30ROM + 0x0ff800); + VezSetReadHandler(m72_main_read); + VezSetWriteHandler(rtype2_main_write); + VezSetReadPort(m72_main_read_port); + VezSetWritePort(m72_main_write_port); + VezClose(); +} + +static void sound_ram_map() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0x0000, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0x0000, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(m72_sound_write_port); + ZetSetInHandler(m72_sound_read_port); + ZetMemEnd(); + ZetClose(); + + enable_z80_reset = 1; +} + +static void sound_rom_map() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(m72_sound_write_port); + ZetSetInHandler(m72_sound_read_port); + ZetMemEnd(); + ZetClose(); + + enable_z80_reset = 0; +} + +static INT32 DrvGfxDecode(UINT8 *gfx, INT32 len, INT32 type) +{ + INT32 Planes[4] = { ((len / 4) * 8) * 3, ((len / 4) * 8) * 2, ((len / 4) * 8) * 1, ((len / 4) * 8) * 0 }; + INT32 XOffs[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 }; + INT32 YOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + UINT8 *tmp = (UINT8*)malloc(len); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, gfx, len); + + if (type) { + GfxDecode((len * 2) / ( 8 * 8), 4, 8, 8, Planes, XOffs, YOffs, 0x040, tmp, gfx); + } else { + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Planes, XOffs, YOffs, 0x100, tmp, gfx); + } + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static INT32 GetRoms(INT32 bLoad) +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *V30ROM = DrvV30ROM; + UINT8 *Z80ROM = DrvZ80ROM; + UINT8 *GFXROM0 = DrvGfxROM0; + UINT8 *GFXROM1 = DrvGfxROM1; + UINT8 *GFXROM2 = DrvGfxROM2; + UINT8 *GFXROM3 = DrvGfxROM3; + UINT8 *SNDROM = DrvSndROM; + INT32 pglen = 0; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 15) == 1) { + if (bLoad) { + if (BurnLoadRom(V30ROM + 1, i + 0, 2)) return 1; + if (BurnLoadRom(V30ROM + 0, i + 1, 2)) return 1; + } + V30ROM += ri.nLen * 2; + i++; + continue; + } + + if ((ri.nType & 15) == 6) { + if (bLoad) if (BurnLoadRom(Z80ROM , i, 1)) return 1; + Z80ROM += ri.nLen; + continue; + } + + if ((ri.nType & 15) == 2) { + if (bLoad) if (BurnLoadRom(GFXROM0, i, 1)) return 1; + GFXROM0 += ri.nLen; + + if (pglen == 0x10000 && ri.nLen == 0x8000) { // rtype fix + if (bLoad) if (BurnLoadRom(GFXROM0, i, 1)) return 1; + GFXROM0 += ri.nLen; + } + pglen = ri.nLen; + continue; + } + + if ((ri.nType & 15) == 3) { + if (bLoad) if (BurnLoadRom(GFXROM1, i, 1)) return 1; + GFXROM1 += ri.nLen; + continue; + } + + if ((ri.nType & 15) == 4) { + if (bLoad) if (BurnLoadRom(GFXROM2, i, 1)) return 1; + GFXROM2 += ri.nLen; + continue; + } + + if ((ri.nType & 15) == 14) { + if (bLoad) if (BurnLoadRom(GFXROM3, i, 1)) return 1; + GFXROM3 += ri.nLen; + continue; + } + + if ((ri.nType & 15) == 5) { + if (bLoad) if (BurnLoadRom(SNDROM , i, 1)) return 1; + SNDROM += ri.nLen; + continue; + } + } + + if (bLoad) { + // copy irq vectors + memcpy (DrvV30ROM + 0xffff0, V30ROM - 0x10, 0x010); + + // mirror sound rom + INT32 sndlen = SNDROM - DrvSndROM; + if (sndlen < 0x40000 && sndlen) { + for (INT32 i = 0; i < 0x40000; i++) { + DrvSndROM[i] = DrvSndROM[i % sndlen]; + } + } + + DrvGfxDecode(DrvGfxROM0, graphics_length[0], 0); + DrvGfxDecode(DrvGfxROM1, graphics_length[1], 1); + + if (graphics_length[2] > 2) { + DrvGfxDecode(DrvGfxROM2, graphics_length[2], 1); + } else { + DrvGfxROM2 = DrvGfxROM1; + code_mask[2] = code_mask[1]; + } + + if (graphics_length[3] > 2) { + DrvGfxDecode(DrvGfxROM3, graphics_length[3], 0); + } else { + code_mask[3] = 0; + } + } else { + graphics_length[0] = GFXROM0 - DrvGfxROM0; + graphics_length[1] = GFXROM1 - DrvGfxROM1; + graphics_length[2] = GFXROM2 - DrvGfxROM2; + graphics_length[3] = GFXROM3 - DrvGfxROM3; + + for (INT32 i = 1, j = 0; j < 4; graphics_length[j] = i, j++, i = 1) { + while (i < graphics_length[j]) i <<= 1; + } + + code_mask[0] = ((graphics_length[0] * 2) - 1) / (16 * 16); + code_mask[1] = ((graphics_length[1] * 2) - 1) / (8 * 8); + code_mask[2] = ((graphics_length[2] * 2) - 1) / (8 * 8); + code_mask[3] = ((graphics_length[3] * 2) - 1) / (16 * 16); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvV30ROM = Next; Next += 0x200000; + DrvZ80ROM = Next; Next += 0x010000; + DrvGfxROM0 = Next; Next += graphics_length[0] * 2; + DrvGfxROM1 = Next; Next += graphics_length[1] * 2; + DrvGfxROM2 = Next; Next += graphics_length[2] * 2; + DrvGfxROM3 = Next; Next += graphics_length[3] * 2; + DrvSndROM = Next; Next += 0x040000; + + RamPrioBitmap = Next; Next += nScreenWidth * nScreenHeight; + dacbuffer = (INT16*)Next; Next += 284 * 2 * sizeof(INT16); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x010000; + DrvSprRAM = Next; Next += 0x001000; + DrvSprRAM2 = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x001000; + DrvVidRAM0 = Next; Next += 0x004000; + DrvVidRAM1 = Next; Next += 0x010000; + DrvV30RAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x002000; + DrvProtRAM = Next; Next += 0x001000; + DrvRowScroll = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + video_enable = Next; Next += 0x000001; + + scroll = Next; Next += 0x000008; + + RamEnd = Next; + + DrvPalette = (UINT32 *) Next; Next += 0x200 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + + +static INT32 DrvInit(void (*pCPUMapCallback)(), void (*pSNDMapCallback)(), INT32 (*pRomLoadCallback)(), INT32 irqbase, INT32 z80_nmi, INT32 video_type) +{ + BurnSetRefreshRate(55.00); + + GenericTilesInit(); + + GetRoms(0); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (GetRoms(1)) return 1; + + if (pCPUMapCallback) { + pCPUMapCallback(); + } + + if (pSNDMapCallback) { + pSNDMapCallback(); + } + + if (pRomLoadCallback) { + if (pRomLoadCallback()) return 1; + } + + m72_irq_base = irqbase; + z80_nmi_enable = z80_nmi; + m72_video_type = video_type; + + switch (video_type) + { + case 0: // m72 + video_offsets[0] = video_offsets[1] = 0; + break; + + case 1: // rtype + case 3: // majtitle + video_offsets[0] = video_offsets[1] = -4; + break; + + case 2: // hharry + video_offsets[0] = -4; + video_offsets[1] = -6; + break; + + case 4: // poundfor + video_offsets[0] = video_offsets[1] = -6; + m72_video_type = 1; // rtype + break; + } + + BurnYM2151Init(3579545, 100.0); + YM2151SetIrqHandler(0, &m72YM2151IRQHandler); + + DACInit(0, 0, 0); + DACSetVolShift(0, 2); // 25% of max + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2151Exit(); + DACExit(); + + ZetExit(); + VezExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + m72_video_type = 0; + enable_z80_reset = 0; + z80_nmi_enable = 0; + + m72_install_protection(NULL,NULL,NULL); + + video_offsets[0] = video_offsets[1] = 0; + + return 0; +} + +static void draw_layer(INT32 layer, INT32 forcelayer, INT32 type, INT32 start, INT32 finish) // bg = layer 1, fg = layer 0 +{ + INT32 codeand = code_mask[1+layer]; + UINT16 *vram = (UINT16*)(layer ? DrvVidRAM1 : DrvVidRAM0); + UINT8 *gfx = (layer) ? DrvGfxROM2 : DrvGfxROM1; + + // layer, prio, forcelayer + const UINT16 transmask[2][3][2] = { + { { 0xffff, 0x0001 }, { 0x00ff, 0xff01 }, { 0x0001, 0xffff } }, + { { 0xffff, 0x0000 }, { 0x00ff, 0xff00 }, { (type == 0) ? 0x0007 : 0x0001, (type == 0) ? 0xfff8 : 0xfffe } } + }; + + INT32 scrolly = scroll[layer * 4 + 0] | (scroll[layer * 4 + 1] << 8); + INT32 scrollx = scroll[layer * 4 + 2] | (scroll[layer * 4 + 3] << 8); + + scrolly = (scrolly + 128) & 0x1ff; + scrollx = (scrollx + 64 + video_offsets[layer]) & 0x1ff; + + UINT16 *xscroll = (UINT16*)DrvRowScroll; + + for (INT32 sy = start; sy < finish; sy++) + { + UINT16 *dest = pTransDraw + (sy * nScreenWidth); + UINT8 *pri = RamPrioBitmap + (sy * nScreenWidth); + + INT32 scrolly1 = (scrolly + sy) & 0x1ff; + INT32 romoff1 = (scrolly1 & 0x07) << 3; + + for (INT32 sx = 0; sx < nScreenWidth + 8; sx+=8) + { + INT32 flipy, flipx, prio, scrollx1, offs; + + if (majtitle_rowscroll_enable && type == 3 && layer == 1) { + scrollx1 = 256 + xscroll[scrolly1] + sx + 64 + video_offsets[1]; + } else { + scrollx1 = scrollx + sx; + if (type == 3 && layer == 1) scrollx1 += 256; + } + + if (type == 3 && layer == 1) { + scrollx1 &= 0x3ff; + offs = ((scrolly1 >> 3) << 8) | (scrollx1 >> 3); + } else { + scrollx1 &= 0x1ff; + offs = ((scrolly1 >> 3) << 6) | (scrollx1 >> 3); + } + + INT32 code = vram[offs * 2 + 0]; + INT32 color = vram[offs * 2 + 1]; + + if (type == 1||type==3) { + flipy = color & 0x0040; + flipx = color & 0x0020; + prio = (color & 0x0100) ? 2 : (color & 0x80) ? 1 : 0; + } else { + flipy = code & 0x8000; + flipx = code & 0x4000; + prio = (color & 0x80) ? 2 : ((color & 0x40) ? 1 : 0); + } + + INT32 mask = transmask[layer][prio][forcelayer]; + + code &= codeand; + color = ((color & 0x000f) << 4) | 0x100; + prio = 1 << prio; + + { + INT32 scrollx0 = scrollx1 & 0x07; + INT32 x_xor = 0; + INT32 romoff = romoff1; + if (flipy) romoff ^= 0x38; + if (flipx) x_xor = 7; + + UINT8 *rom = gfx + (code * 0x40) + romoff; + + INT32 xx = sx - scrollx0; + + for (INT32 x = 0; x < 8; x++, xx++) { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = rom[x ^ x_xor]; + if (mask & (1 << pxl)) continue; + + dest[xx] = pxl | color; + pri[xx] = prio; + } + } + } + } +} + +INT32 start_screen = 0; + +static void draw_sprites() +{ + UINT16 *sprram = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0; offs < 0x400/2;) + { + INT32 sx = -256+(sprram[offs+3] & 0x3ff); + INT32 attr = sprram[offs+2]; + INT32 code = sprram[offs+1]; + INT32 sy = 384-(sprram[offs+0] & 0x1ff); + + INT32 color = attr & 0x0f; + INT32 flipx = attr & 0x0800; + INT32 flipy = attr & 0x0400; + + INT32 w = 1 << ((attr & 0xc000) >> 14); + INT32 h = 1 << ((attr & 0x3000) >> 12); + sy -= 16 * h; + + sy -= start_screen; + sx -= 64; // ? +#if 0 + if (*flipscreen) + { + sx = 512 - 16*w - sx; + sy = 284 - 16*h - sy; + flipx = !flipx; + flipy = !flipy; + } +#endif + + for (INT32 x = 0;x < w;x++) + { + for (INT32 y = 0;y < h;y++) + { + INT32 c = code; + + if (flipx) c += 8*(w-1-x); + else c += 8*x; + if (flipy) c += h-1-y; + else c += y; + + c &= code_mask[0]; + + INT32 xx = sx + 16 * x; + INT32 yy = sy + 16 * y; + + if (xx < -15 || yy < -15 || xx >= nScreenWidth || yy >= nScreenHeight) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM0); + } + } + } + } + + offs += w*4; + } +} + +static void majtitle_draw_sprites() +{ + UINT16 *spriteram16_2 = (UINT16*)DrvSprRAM2; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 code,color,sx,sy,flipx,flipy,w,h,x,y; + + code = spriteram16_2[offs+1]; + color = spriteram16_2[offs+2] & 0x0f; + sx = -256+(spriteram16_2[offs+3] & 0x3ff); + sy = 384-(spriteram16_2[offs+0] & 0x1ff); + flipx = spriteram16_2[offs+2] & 0x0800; + flipy = spriteram16_2[offs+2] & 0x0400; + + w = 1;// << ((spriteram16_2[offs+2] & 0xc000) >> 14); + h = 1 << ((spriteram16_2[offs+2] & 0x3000) >> 12); + sy -= 16 * h; + + sy -= start_screen; + sx -= 64; // ? +#if 0 + if (flip_screen_get(machine)) + { + sx = 512 - 16*w - sx; + sy = 256 - 16*h - sy; + flipx = !flipx; + flipy = !flipy; + } +#endif + + for (x = 0;x < w;x++) + { + for (y = 0;y < h;y++) + { + INT32 c = code; + + if (flipx) c += 8*(w-1-x); + else c += 8*x; + if (flipy) c += h-1-y; + else c += y; + + c &= code_mask[3]; + + INT32 xx = sx + 16 * x; + INT32 yy = sy + 16 * y; + + if (xx < -15 || yy < -15 || xx >= nScreenWidth || yy >= nScreenHeight) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, xx, yy, color, 4, 0, 0, DrvGfxROM3); + } + } + } + } + } +} + +static void dodrawline(INT32 start, INT32 finish) +{ + if (*video_enable) return; + + draw_layer(1, 1, m72_video_type, start, finish); + draw_layer(0, 1, m72_video_type, start, finish); + + // hacky hack for drawing sprites in scanline... slow. + start_screen = start; + UINT16 *ptr = pTransDraw; + INT32 scrn = nScreenHeight; + pTransDraw += start * nScreenWidth; + nScreenHeight = finish - start; + if (m72_video_type == 3) majtitle_draw_sprites(); + draw_sprites(); + pTransDraw = ptr; + nScreenHeight = scrn; + + draw_layer(1, 0, m72_video_type, start, finish); + draw_layer(0, 0, m72_video_type, start, finish); +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x200; i++) { + palette_write((i & 0xff) * 2, i >> 8); + } + DrvRecalc = 0; + } + +// if (*video_enable) { +// BurnTransferClear(); +// BurnTransferCopy(DrvPalette); +// return 0; +// } + +// draw_layer(1, 1, 0, nScreenHeight); +// draw_layer(0, 1, 0, nScreenHeight); +// draw_sprites(); +// draw_layer(1, 0, 0, nScreenHeight); +// draw_layer(0, 0, 0, nScreenHeight); + + BurnTransferCopy(DrvPalette); + + BurnTransferClear(); + + return 0; +} + +static void compile_inputs() +{ + memset (DrvInputs, 0xff, 5); + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } +} + +static INT32 nPreviousLine = 0; + +static void scanline_interrupts(INT32 scanline) +{ + if (scanline == (irq_raster_position - 128) && scanline < 256) { + if (nPreviousLine <= scanline && scanline < nScreenHeight) { + dodrawline(nPreviousLine, scanline+1); + nPreviousLine = scanline + 1; + } + + VezSetIRQLineAndVector(0, (m72_irq_base + 8)/4, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(0, (m72_irq_base + 8)/4, VEZ_IRQSTATUS_NONE); + } + else if (scanline == 256) // vblank + { + if (nPreviousLine < nScreenHeight) { + dodrawline(nPreviousLine, nScreenHeight); + nPreviousLine = 0; + } + + VezSetIRQLineAndVector(0, (m72_irq_base + 0)/4, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(0, (m72_irq_base + 0)/4, VEZ_IRQSTATUS_NONE); + + } + + if (nPreviousLine >= nScreenHeight) nPreviousLine = 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + VezNewFrame(); + ZetNewFrame(); + + compile_inputs(); + + // overclocking... + nCyclesTotal[0] = (INT32)((INT64)(8000000 / 55) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesTotal[1] = (INT32)((INT64)(3579545 / 55) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesDone[0] = nCyclesDone[1] = 0; + + VezOpen(0); + ZetOpen(0); + +memset (pBurnSoundOut, 0, nBurnSoundLen * sizeof(INT16)); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCurrentCycles = ((nCyclesTotal[0] / nInterleave) * 1) / 8; // scanline is 87.5% of scanline time + + for (INT32 j = 0; j < 7; j++) { // increase cpu sync + nCyclesDone[0] += VezRun(nCurrentCycles); + sync_cpus(); + sync_ym2151(); + } + + scanline_interrupts(i); // run at hblank? + + nCurrentCycles = ((nCyclesTotal[0] / nInterleave) * 1) / 8; // horizontal blank is 12.5% of scanline + + nCyclesDone[0] += VezRun(nCurrentCycles); + // vertical lines are ~90% of video time, vblank is ~10% + + if (z80_reset == 0) { + //nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave); + sync_cpus(); + sync_ym2151(); + if (i & 1) { + if (z80_nmi_enable == Z80_FAKE_NMI) { + if (DrvSndROM[sample_address]) { + DACSignedWrite(0, DrvSndROM[sample_address]); + sample_address = (sample_address + 1) & 0x3ffff; + } + } else if (z80_nmi_enable == Z80_REAL_NMI) { + ZetNmi(); + } + + DACUpdate(dacbuffer + i, 1); + } + } else { + //nCyclesDone[1] += nCyclesTotal[1] / nInterleave; + sync_cpus(); + sync_ym2151(); + //ZetIdle(nCyclesTotal[1] / nInterleave); + } + + // if (i == 35 || i == 71 || i == 106 || i == 142 || i == 177 || i == 213 || i == 148 || i == 283) { + // INT32 len = nBurnSoundLen / 8; + // BurnYM2151Render(pBurnSoundOut + (len * 2) * (i/35), len); + // } + } + + if (pBurnSoundOut) { + sync_ym2151(); + // memset (pBurnSoundOut, 0, nBurnSoundLen * sizeof(INT16)); + // BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + + float step = (142.000000) / nBurnSoundLen; + + INT16 *pbuf = pBurnSoundOut; + for (INT32 i = 0; i < nBurnSoundLen; i++, pbuf+=2) { + INT32 o = (INT32)((float)(i * step)); + pbuf[0] += dacbuffer[o * 2 + 0]; + pbuf[1] += dacbuffer[o * 2 + 1]; + } + } + + VezClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + + + +// R-Type (World) + +static struct BurnRomInfo rtypeRomDesc[] = { + { "rt_r-h0-b.1b", 0x10000, 0x591c7754, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt_r-l0-b.3b", 0x10000, 0xa1928df0, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt_r-h1-b.1c", 0x10000, 0xa9d71eca, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt_r-l1-b.3c", 0x10000, 0x0df3573d, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "rt_r-00.1h", 0x10000, 0xdad53bc0, 0x02 | BRF_GRA }, // 4 Sprites + { "rt_r-01.1j", 0x08000, 0x5e441e7f, 0x02 | BRF_GRA }, // 5 + { "rt_r-10.1k", 0x10000, 0xd6a66298, 0x02 | BRF_GRA }, // 6 + { "rt_r-11.1l", 0x08000, 0x791df4f8, 0x02 | BRF_GRA }, // 7 + { "rt_r-20.3h", 0x10000, 0xfc247c8a, 0x02 | BRF_GRA }, // 8 + { "rt_r-21.3j", 0x08000, 0xed793841, 0x02 | BRF_GRA }, // 9 + { "rt_r-30.3k", 0x10000, 0xeb02a1cb, 0x02 | BRF_GRA }, // 10 + { "rt_r-31.3l", 0x08000, 0x8558355d, 0x02 | BRF_GRA }, // 11 + + { "rt_b-a0.3c", 0x08000, 0x4e212fb0, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "rt_b-a1.3d", 0x08000, 0x8a65bdff, 0x03 | BRF_GRA }, // 13 + { "rt_b-a2.3a", 0x08000, 0x5a4ae5b9, 0x03 | BRF_GRA }, // 14 + { "rt_b-a3.3e", 0x08000, 0x73327606, 0x03 | BRF_GRA }, // 15 + + { "rt_b-b0.3j", 0x08000, 0xa7b17491, 0x04 | BRF_GRA }, // 16 Background Tiles + { "rt_b-b1.3k", 0x08000, 0xb9709686, 0x04 | BRF_GRA }, // 17 + { "rt_b-b2.3h", 0x08000, 0x433b229a, 0x04 | BRF_GRA }, // 18 + { "rt_b-b3.3f", 0x08000, 0xad89b072, 0x04 | BRF_GRA }, // 19 +}; + +STD_ROM_PICK(rtype) +STD_ROM_FN(rtype) + +static INT32 rtypeInit() +{ + return DrvInit(common_040000_040000, sound_ram_map, NULL, 0x80, Z80_NO_NMI, 0); +} + +struct BurnDriver BurnDrvRtype = { + "rtype", NULL, NULL, NULL, "1987", + "R-Type (World)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtypeRomInfo, rtypeRomName, NULL, NULL, CommonInputInfo, RtypeDIPInfo, + rtypeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type (Japan) + +static struct BurnRomInfo rtypejRomDesc[] = { + { "rt_r-h0-.1b", 0x10000, 0xc2940df2, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt_r-l0-.3b", 0x10000, 0x858cc0f6, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt_r-h1-.1c", 0x10000, 0x5bcededa, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt_r-l1-.3c", 0x10000, 0x4821141c, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "rt_r-00.1h", 0x10000, 0xdad53bc0, 0x02 | BRF_GRA }, // 4 Sprites + { "rt_r-01.1j", 0x08000, 0x5e441e7f, 0x02 | BRF_GRA }, // 5 + { "rt_r-10.1k", 0x10000, 0xd6a66298, 0x02 | BRF_GRA }, // 6 + { "rt_r-11.1l", 0x08000, 0x791df4f8, 0x02 | BRF_GRA }, // 7 + { "rt_r-20.3h", 0x10000, 0xfc247c8a, 0x02 | BRF_GRA }, // 8 + { "rt_r-21.3j", 0x08000, 0xed793841, 0x02 | BRF_GRA }, // 9 + { "rt_r-30.3k", 0x10000, 0xeb02a1cb, 0x02 | BRF_GRA }, // 10 + { "rt_r-31.3l", 0x08000, 0x8558355d, 0x02 | BRF_GRA }, // 11 + + { "rt_b-a0.3c", 0x08000, 0x4e212fb0, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "rt_b-a1.3d", 0x08000, 0x8a65bdff, 0x03 | BRF_GRA }, // 13 + { "rt_b-a2.3a", 0x08000, 0x5a4ae5b9, 0x03 | BRF_GRA }, // 14 + { "rt_b-a3.3e", 0x08000, 0x73327606, 0x03 | BRF_GRA }, // 15 + + { "rt_b-b0.3j", 0x08000, 0xa7b17491, 0x04 | BRF_GRA }, // 16 Background Tiles + { "rt_b-b1.3k", 0x08000, 0xb9709686, 0x04 | BRF_GRA }, // 17 + { "rt_b-b2.3h", 0x08000, 0x433b229a, 0x04 | BRF_GRA }, // 18 + { "rt_b-b3.3f", 0x08000, 0xad89b072, 0x04 | BRF_GRA }, // 19 +}; + +STD_ROM_PICK(rtypej) +STD_ROM_FN(rtypej) + +struct BurnDriver BurnDrvRtypej = { + "rtypej", "rtype", NULL, NULL, "1987", + "R-Type (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtypejRomInfo, rtypejRomName, NULL, NULL, CommonInputInfo, RtypeDIPInfo, + rtypeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type (Japan prototype) + +static struct BurnRomInfo rtypejpRomDesc[] = { + { "db_b1.bin", 0x10000, 0xc1865141, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "db_a1.bin", 0x10000, 0x5ad2bd90, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "db_b2.bin", 0x10000, 0xb4f6407e, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "db_a2.bin", 0x10000, 0x6098d86f, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "rt_r-00.1h", 0x10000, 0xdad53bc0, 0x02 | BRF_GRA }, // 4 Sprites + { "rt_r-01.1j", 0x08000, 0x5e441e7f, 0x02 | BRF_GRA }, // 5 + { "rt_r-10.1k", 0x10000, 0xd6a66298, 0x02 | BRF_GRA }, // 6 + { "rt_r-11.1l", 0x08000, 0x791df4f8, 0x02 | BRF_GRA }, // 7 + { "rt_r-20.3h", 0x10000, 0xfc247c8a, 0x02 | BRF_GRA }, // 8 + { "rt_r-21.3j", 0x08000, 0xed793841, 0x02 | BRF_GRA }, // 9 + { "rt_r-30.3k", 0x10000, 0xeb02a1cb, 0x02 | BRF_GRA }, // 10 + { "rt_r-31.3l", 0x08000, 0x8558355d, 0x02 | BRF_GRA }, // 11 + + { "rt_b-a0.3c", 0x08000, 0x4e212fb0, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "rt_b-a1.3d", 0x08000, 0x8a65bdff, 0x03 | BRF_GRA }, // 13 + { "rt_b-a2.3a", 0x08000, 0x5a4ae5b9, 0x03 | BRF_GRA }, // 14 + { "rt_b-a3.3e", 0x08000, 0x73327606, 0x03 | BRF_GRA }, // 15 + + { "rt_b-b0.3j", 0x08000, 0xa7b17491, 0x04 | BRF_GRA }, // 16 Background Tiles + { "rt_b-b1.3k", 0x08000, 0xb9709686, 0x04 | BRF_GRA }, // 17 + { "rt_b-b2.3h", 0x08000, 0x433b229a, 0x04 | BRF_GRA }, // 18 + { "rt_b-b3.3f", 0x08000, 0xad89b072, 0x04 | BRF_GRA }, // 19 +}; + +STD_ROM_PICK(rtypejp) +STD_ROM_FN(rtypejp) + +struct BurnDriver BurnDrvRtypejp = { + "rtypejp", "rtype", NULL, NULL, "1987", + "R-Type (Japan prototype)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtypejpRomInfo, rtypejpRomName, NULL, NULL, CommonInputInfo, RtypepDIPInfo, + rtypeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type (US) + +static struct BurnRomInfo rtypeuRomDesc[] = { + { "rt_r-h0-a.1b", 0x10000, 0x36008a4e, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt_r-l0-a.3b", 0x10000, 0x4aaa668e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt_r-h1-a.1c", 0x10000, 0x7ebb2a53, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt_r-l1-a.3c", 0x10000, 0xc28b103b, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "rt_r-00.1h", 0x10000, 0xdad53bc0, 0x02 | BRF_GRA }, // 4 Sprites + { "rt_r-01.1j", 0x08000, 0x5e441e7f, 0x02 | BRF_GRA }, // 5 + { "rt_r-10.1k", 0x10000, 0xd6a66298, 0x02 | BRF_GRA }, // 6 + { "rt_r-11.1l", 0x08000, 0x791df4f8, 0x02 | BRF_GRA }, // 7 + { "rt_r-20.3h", 0x10000, 0xfc247c8a, 0x02 | BRF_GRA }, // 8 + { "rt_r-21.3j", 0x08000, 0xed793841, 0x02 | BRF_GRA }, // 9 + { "rt_r-30.3k", 0x10000, 0xeb02a1cb, 0x02 | BRF_GRA }, // 10 + { "rt_r-31.3l", 0x08000, 0x8558355d, 0x02 | BRF_GRA }, // 11 + + { "rt_b-a0.3c", 0x08000, 0x4e212fb0, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "rt_b-a1.3d", 0x08000, 0x8a65bdff, 0x03 | BRF_GRA }, // 13 + { "rt_b-a2.3a", 0x08000, 0x5a4ae5b9, 0x03 | BRF_GRA }, // 14 + { "rt_b-a3.3e", 0x08000, 0x73327606, 0x03 | BRF_GRA }, // 15 + + { "rt_b-b0.3j", 0x08000, 0xa7b17491, 0x04 | BRF_GRA }, // 16 Background Tiles + { "rt_b-b1.3k", 0x08000, 0xb9709686, 0x04 | BRF_GRA }, // 17 + { "rt_b-b2.3h", 0x08000, 0x433b229a, 0x04 | BRF_GRA }, // 18 + { "rt_b-b3.3f", 0x08000, 0xad89b072, 0x04 | BRF_GRA }, // 19 + + { "m72_a-8l-.ic66", 0x00100, 0xb460c438, 0x00 | BRF_OPT }, // 20 Proms + { "m72_a-9l-.ic75", 0x00100, 0xa4f2c4bc, 0x00 | BRF_OPT }, // 21 + + { "m72_r-3a-.bin", 0x00001, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 22 PLDs + { "m72_a-3d-.bin", 0x00001, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 23 + { "m72_a-4d-.bin", 0x00001, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 24 +}; + +STD_ROM_PICK(rtypeu) +STD_ROM_FN(rtypeu) + +struct BurnDriver BurnDrvRtypeu = { + "rtypeu", "rtype", NULL, NULL, "1987", + "R-Type (US)\0", NULL, "Irem (Nintendo of America license)", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtypeuRomInfo, rtypeuRomName, NULL, NULL, CommonInputInfo, RtypeDIPInfo, + rtypeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type (World bootleg) + +static struct BurnRomInfo rtypebRomDesc[] = { + { "7.512", 0x10000, 0xeacc8024, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "1.512", 0x10000, 0x2e5fe27b, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "8.512", 0x10000, 0x22cc4950, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "2.512", 0x10000, 0xada7b90e, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "rt_r-00.1h", 0x10000, 0xdad53bc0, 0x02 | BRF_GRA }, // 4 Sprites + { "rt_r-01.1j", 0x08000, 0x5e441e7f, 0x02 | BRF_GRA }, // 5 + { "rt_r-10.1k", 0x10000, 0xd6a66298, 0x02 | BRF_GRA }, // 6 + { "rt_r-11.1l", 0x08000, 0x791df4f8, 0x02 | BRF_GRA }, // 7 + { "rt_r-20.3h", 0x10000, 0xfc247c8a, 0x02 | BRF_GRA }, // 8 + { "rt_r-21.3j", 0x08000, 0xed793841, 0x02 | BRF_GRA }, // 9 + { "rt_r-30.3k", 0x10000, 0xeb02a1cb, 0x02 | BRF_GRA }, // 10 + { "rt_r-31.3l", 0x08000, 0x8558355d, 0x02 | BRF_GRA }, // 11 + + { "rt_b-a0.3c", 0x08000, 0x4e212fb0, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "rt_b-a1.3d", 0x08000, 0x8a65bdff, 0x03 | BRF_GRA }, // 13 + { "rt_b-a2.3a", 0x08000, 0x5a4ae5b9, 0x03 | BRF_GRA }, // 14 + { "rt_b-a3.3e", 0x08000, 0x73327606, 0x03 | BRF_GRA }, // 15 + + { "rt_b-b0.3j", 0x08000, 0xa7b17491, 0x04 | BRF_GRA }, // 16 Background Tiles + { "rt_b-b1.3k", 0x08000, 0xb9709686, 0x04 | BRF_GRA }, // 17 + { "rt_b-b2.3h", 0x08000, 0x433b229a, 0x04 | BRF_GRA }, // 18 + { "rt_b-b3.3f", 0x08000, 0xad89b072, 0x04 | BRF_GRA }, // 19 +}; + +STD_ROM_PICK(rtypeb) +STD_ROM_FN(rtypeb) + +struct BurnDriver BurnDrvRtypeb = { + "rtypeb", "rtype", NULL, NULL, "1987", + "R-Type (World bootleg)\0", NULL, "bootleg", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtypebRomInfo, rtypebRomName, NULL, NULL, CommonInputInfo, RtypeDIPInfo, + rtypeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// X Multiply (World, M81) + +static struct BurnRomInfo xmultiplRomDesc[] = { + { "xm-a-h1-.ic58", 0x20000, 0x449048cf, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "xm-a-l1-.ic67", 0x20000, 0x26ce39b0, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "xm-a-h0-.ic59", 0x10000, 0x509bc970, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "xm-a-l0-.ic68", 0x10000, 0x490a9ebc, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "xm-a-sp-.ic14", 0x10000, 0x006eef56, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "t44.00", 0x20000, 0xdb45186e, 0x02 | BRF_GRA }, // 5 Sprites + { "t45.01", 0x20000, 0x4d0764d4, 0x02 | BRF_GRA }, // 6 + { "t46.10", 0x20000, 0xf0c465a4, 0x02 | BRF_GRA }, // 7 + { "t47.11", 0x20000, 0x1263b24b, 0x02 | BRF_GRA }, // 8 + { "t48.20", 0x20000, 0x4129944f, 0x02 | BRF_GRA }, // 9 + { "t49.21", 0x20000, 0x2346e6f9, 0x02 | BRF_GRA }, // 10 + { "t50.30", 0x20000, 0xe322543e, 0x02 | BRF_GRA }, // 11 + { "t51.31", 0x20000, 0x229bf7b1, 0x02 | BRF_GRA }, // 12 + + { "t53.a0", 0x20000, 0x1a082494, 0x03 | BRF_GRA }, // 13 Foreground Tiles + { "t54.a1", 0x20000, 0x076c16c5, 0x03 | BRF_GRA }, // 14 + { "t55.a2", 0x20000, 0x25d877a5, 0x03 | BRF_GRA }, // 15 + { "t56.a3", 0x20000, 0x5b1213f5, 0x03 | BRF_GRA }, // 16 + + { "t57.b0", 0x20000, 0x0a84e0c7, 0x04 | BRF_GRA }, // 17 Background Tiles + { "t58.b1", 0x20000, 0xa874121d, 0x04 | BRF_GRA }, // 18 + { "t59.b2", 0x20000, 0x69deb990, 0x04 | BRF_GRA }, // 19 + { "t60.b3", 0x20000, 0x14c69f99, 0x04 | BRF_GRA }, // 20 + + { "t52.v0", 0x20000, 0x2db1bd80, 0x05 | BRF_SND }, // 21 DAC Samples + + { "m81_a-9l-.ic72", 0x00100, 0xb460c438, 0x00 | BRF_OPT }, // 22 Proms + { "m81_a-9p-.ic74", 0x00100, 0xa4f2c4bc, 0x00 | BRF_OPT }, // 23 +}; + +STD_ROM_PICK(xmultipl) +STD_ROM_FN(xmultipl) + +static INT32 xmultiplInit() +{ + return DrvInit(common_080000_09c000, sound_rom_map, NULL, 0x20, Z80_REAL_NMI, 0); +} + +struct BurnDriver BurnDrvXmultipl = { + "xmultipl", NULL, NULL, NULL, "1989", + "X Multiply (World, M81)\0", NULL, "Irem", "M81", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, xmultiplRomInfo, xmultiplRomName, NULL, NULL, CommonInputInfo, XmultiplDIPInfo, + xmultiplInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// X Multiply (Japan, M72) + +static struct BurnRomInfo xmultiplm72RomDesc[] = { + { "ch3.h3", 0x20000, 0x20685021, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "cl3.l3", 0x20000, 0x93fdd200, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ch0.h0", 0x10000, 0x9438dd8a, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "cl0.l0", 0x10000, 0x06a9e213, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "t44.00", 0x20000, 0xdb45186e, 0x02 | BRF_GRA }, // 4 Sprites + { "t45.01", 0x20000, 0x4d0764d4, 0x02 | BRF_GRA }, // 5 + { "t46.10", 0x20000, 0xf0c465a4, 0x02 | BRF_GRA }, // 6 + { "t47.11", 0x20000, 0x1263b24b, 0x02 | BRF_GRA }, // 7 + { "t48.20", 0x20000, 0x4129944f, 0x02 | BRF_GRA }, // 8 + { "t49.21", 0x20000, 0x2346e6f9, 0x02 | BRF_GRA }, // 9 + { "t50.30", 0x20000, 0xe322543e, 0x02 | BRF_GRA }, // 10 + { "t51.31", 0x20000, 0x229bf7b1, 0x02 | BRF_GRA }, // 11 + + { "t53.a0", 0x20000, 0x1a082494, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "t54.a1", 0x20000, 0x076c16c5, 0x03 | BRF_GRA }, // 13 + { "t55.a2", 0x20000, 0x25d877a5, 0x03 | BRF_GRA }, // 14 + { "t56.a3", 0x20000, 0x5b1213f5, 0x03 | BRF_GRA }, // 15 + + { "t57.b0", 0x20000, 0x0a84e0c7, 0x04 | BRF_GRA }, // 16 Background Tiles + { "t58.b1", 0x20000, 0xa874121d, 0x04 | BRF_GRA }, // 17 + { "t59.b2", 0x20000, 0x69deb990, 0x04 | BRF_GRA }, // 18 + { "t60.b3", 0x20000, 0x14c69f99, 0x04 | BRF_GRA }, // 19 + + { "t52.v0", 0x20000, 0x2db1bd80, 0x05 | BRF_SND }, // 20 DAC Samples + + { "xmultipl_i8751h.bin",0x01000, 0xc8ceb3cd, 0x00 | BRF_OPT }, // 21 i8751 Code +}; + +STD_ROM_PICK(xmultiplm72) +STD_ROM_FN(xmultiplm72) + +static INT32 xmultiplm72Init() +{ + install_protection(xmultiplm72); + + return DrvInit(common_080000_080000, sound_ram_map, NULL, 0x20, Z80_REAL_NMI, 0); +} + +struct BurnDriver BurnDrvXmultiplm72 = { + "xmultiplm72", "xmultipl", NULL, NULL, "1989", + "X Multiply (Japan, M72)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, xmultiplm72RomInfo, xmultiplm72RomName, NULL, NULL, CommonInputInfo, XmultiplDIPInfo, + xmultiplm72Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Dragon Breed (M81 PCB version) + +static struct BurnRomInfo dbreedRomDesc[] = { + { "db-a-h0-.59", 0x20000, 0xe1177267, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "db-a-l0-.68", 0x20000, 0xd82b167e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "db-a-sp-.14", 0x10000, 0x54a61560, 0x06 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "db_k800m.00", 0x20000, 0xc027a8cf, 0x02 | BRF_GRA }, // 3 Sprites + { "db_k801m.10", 0x20000, 0x093faf33, 0x02 | BRF_GRA }, // 4 + { "db_k802m.20", 0x20000, 0x055b4c59, 0x02 | BRF_GRA }, // 5 + { "db_k803m.30", 0x20000, 0x8ed63922, 0x02 | BRF_GRA }, // 6 + + { "db_k804m.a0", 0x20000, 0x4c83e92e, 0x03 | BRF_GRA }, // 7 Foreground & Background Tiles + { "db_k805m.a1", 0x20000, 0x835ef268, 0x03 | BRF_GRA }, // 8 + { "db_k806m.a2", 0x20000, 0x5117f114, 0x03 | BRF_GRA }, // 9 + { "db_k807m.a3", 0x20000, 0x8eb0c978, 0x03 | BRF_GRA }, // 10 + + { "db_a-v0.rom", 0x20000, 0x312f7282, 0x05 | BRF_SND }, // 11 DAC Samples +}; + +STD_ROM_PICK(dbreed) +STD_ROM_FN(dbreed) + +static INT32 dbreedRomLoadCallback() +{ + memcpy (DrvV30ROM + 0x60000, DrvV30ROM + 0x20000, 0x20000); + + return 0; +} + +static INT32 dbreedInit() +{ + return DrvInit(common_080000_088000, sound_rom_map, dbreedRomLoadCallback, 0x20, Z80_REAL_NMI, 2); +} + +struct BurnDriver BurnDrvDbreed = { + "dbreed", NULL, NULL, NULL, "1989", + "Dragon Breed (M81 PCB version)\0", NULL, "Irem", "M81", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, dbreedRomInfo, dbreedRomName, NULL, NULL, CommonInputInfo, DbreedDIPInfo, + dbreedInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Dragon Breed (M72 PCB version) + +static struct BurnRomInfo dbreedm72RomDesc[] = { + { "db_c-h3.rom", 0x20000, 0x4bf3063c, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "db_c-l3.rom", 0x20000, 0xe4b89b79, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "db_c-h0.rom", 0x10000, 0x5aa79fb2, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "db_c-l0.rom", 0x10000, 0xed0f5e06, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "db_k800m.00", 0x20000, 0xc027a8cf, 0x02 | BRF_GRA }, // 4 Sprites + { "db_k801m.10", 0x20000, 0x093faf33, 0x02 | BRF_GRA }, // 5 + { "db_k802m.20", 0x20000, 0x055b4c59, 0x02 | BRF_GRA }, // 6 + { "db_k803m.30", 0x20000, 0x8ed63922, 0x02 | BRF_GRA }, // 7 + + { "db_k804m.a0", 0x20000, 0x4c83e92e, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "db_k805m.a1", 0x20000, 0x835ef268, 0x03 | BRF_GRA }, // 9 + { "db_k806m.a2", 0x20000, 0x5117f114, 0x03 | BRF_GRA }, // 10 + { "db_k807m.a3", 0x20000, 0x8eb0c978, 0x03 | BRF_GRA }, // 11 + + { "db_k804m.b0", 0x20000, 0x4c83e92e, 0x04 | BRF_GRA }, // 12 Background Tiles + { "db_k805m.b1", 0x20000, 0x835ef268, 0x04 | BRF_GRA }, // 13 + { "db_k806m.b2", 0x20000, 0x5117f114, 0x04 | BRF_GRA }, // 14 + { "db_k807m.b3", 0x20000, 0x8eb0c978, 0x04 | BRF_GRA }, // 15 + + { "db_c-v0.rom", 0x20000, 0x312f7282, 0x05 | BRF_SND }, // 16 DAC Samples + + { "dbreedm72_i8751.mcu",0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 17 i8751 Code +}; + +STD_ROM_PICK(dbreedm72) +STD_ROM_FN(dbreedm72) + +static INT32 dbreedm72RomLoadCallback() +{ + memcpy (DrvV30ROM + 0x60000, DrvV30ROM + 0x40000, 0x20000); + + return 0; +} + +static INT32 dbreedm72Init() +{ + install_protection(dbreedm72); + + return DrvInit(common_080000_090000, sound_ram_map, dbreedm72RomLoadCallback, 0x20, Z80_REAL_NMI, 0); +} + +struct BurnDriver BurnDrvDbreedm72 = { + "dbreedm72", "dbreed", NULL, NULL, "1989", + "Dragon Breed (M72 PCB version)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, dbreedm72RomInfo, dbreedm72RomName, NULL, NULL, CommonInputInfo, DbreedDIPInfo, + dbreedm72Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Battle Chopper + +static struct BurnRomInfo bchopperRomDesc[] = { + { "c-h0-b.rom", 0x10000, 0xf2feab16, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "c-l0-b.rom", 0x10000, 0x9f887096, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "c-h1-b.rom", 0x10000, 0xa995d64f, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "c-l1-b.rom", 0x10000, 0x41dda999, 0x01 | BRF_PRG | BRF_ESS }, // 3 + { "c-h3-b.rom", 0x10000, 0xab9451ca, 0x01 | BRF_PRG | BRF_ESS }, // 4 + { "c-l3-b.rom", 0x10000, 0x11562221, 0x01 | BRF_PRG | BRF_ESS }, // 5 + + { "c-00-a.rom", 0x10000, 0xf6e6e660, 0x02 | BRF_GRA }, // 6 Sprites + { "c-01-b.rom", 0x10000, 0x708cdd37, 0x02 | BRF_GRA }, // 7 + { "c-10-a.rom", 0x10000, 0x292c8520, 0x02 | BRF_GRA }, // 8 + { "c-11-b.rom", 0x10000, 0x20904cf3, 0x02 | BRF_GRA }, // 9 + { "c-20-a.rom", 0x10000, 0x1ab50c23, 0x02 | BRF_GRA }, // 10 + { "c-21-b.rom", 0x10000, 0xc823d34c, 0x02 | BRF_GRA }, // 11 + { "c-30-a.rom", 0x10000, 0x11f6c56b, 0x02 | BRF_GRA }, // 12 + { "c-31-b.rom", 0x10000, 0x23134ec5, 0x02 | BRF_GRA }, // 13 + + { "b-a0-b.rom", 0x10000, 0xe46ed7bf, 0x03 | BRF_GRA }, // 14 Foreground Tiles + { "b-a1-b.rom", 0x10000, 0x590605ff, 0x03 | BRF_GRA }, // 15 + { "b-a2-b.rom", 0x10000, 0xf8158226, 0x03 | BRF_GRA }, // 16 + { "b-a3-b.rom", 0x10000, 0x0f07b9b7, 0x03 | BRF_GRA }, // 17 + + { "b-b0-.rom", 0x10000, 0xb5b95776, 0x04 | BRF_GRA }, // 18 Background Tiles + { "b-b1-.rom", 0x10000, 0x74ca16ee, 0x04 | BRF_GRA }, // 19 + { "b-b2-.rom", 0x10000, 0xb82cca04, 0x04 | BRF_GRA }, // 20 + { "b-b3-.rom", 0x10000, 0xa7afc920, 0x04 | BRF_GRA }, // 21 + + { "c-v0-b.rom", 0x10000, 0xd0c27e58, 0x05 | BRF_SND }, // 22 DAC Samples + + { "bchopper_i8751.mcu", 0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 23 i8751 Code +}; + +STD_ROM_PICK(bchopper) +STD_ROM_FN(bchopper) + +static INT32 bchopperInit() +{ + install_protection(bchopper); + + return DrvInit(common_080000_0a0000, sound_ram_map, dbreedm72RomLoadCallback, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvBchopper = { + "bchopper", NULL, NULL, NULL, "1987", + "Battle Chopper\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, bchopperRomInfo, bchopperRomName, NULL, NULL, CommonInputInfo, BchopperDIPInfo, + bchopperInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Mr. HELI no Dai-Bouken + +static struct BurnRomInfo mrheliRomDesc[] = { + { "mh-c-h0.bin", 0x10000, 0xe2ca5646, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "mh-c-l0.bin", 0x10000, 0x643e23cd, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "mh-c-h1.bin", 0x10000, 0x8974e84d, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "mh-c-l1.bin", 0x10000, 0x5f8bda69, 0x01 | BRF_PRG | BRF_ESS }, // 3 + { "mh-c-h3.bin", 0x10000, 0x143f596e, 0x01 | BRF_PRG | BRF_ESS }, // 4 + { "mh-c-l3.bin", 0x10000, 0xc0982536, 0x01 | BRF_PRG | BRF_ESS }, // 5 + + { "mh-c-00.bin", 0x20000, 0xdec4e121, 0x02 | BRF_GRA }, // 6 Sprites + { "mh-c-10.bin", 0x20000, 0x7aaa151e, 0x02 | BRF_GRA }, // 7 + { "mh-c-20.bin", 0x20000, 0xeae0de74, 0x02 | BRF_GRA }, // 8 + { "mh-c-30.bin", 0x20000, 0x01d5052f, 0x02 | BRF_GRA }, // 9 + + { "mh-b-a0.bin", 0x10000, 0x6a0db256, 0x03 | BRF_GRA }, // 10 Foreground Tiles + { "mh-b-a1.bin", 0x10000, 0x14ec9795, 0x03 | BRF_GRA }, // 11 + { "mh-b-a2.bin", 0x10000, 0xdfcb510e, 0x03 | BRF_GRA }, // 12 + { "mh-b-a3.bin", 0x10000, 0x957e329b, 0x03 | BRF_GRA }, // 13 + + { "b-b0-.rom", 0x10000, 0xb5b95776, 0x04 | BRF_GRA }, // 14 Background Tiles + { "b-b1-.rom", 0x10000, 0x74ca16ee, 0x04 | BRF_GRA }, // 15 + { "b-b2-.rom", 0x10000, 0xb82cca04, 0x04 | BRF_GRA }, // 16 + { "b-b3-.rom", 0x10000, 0xa7afc920, 0x04 | BRF_GRA }, // 17 + + { "c-v0-b.rom", 0x10000, 0xd0c27e58, 0x05 | BRF_SND }, // 18 DAC Samples + + { "mrheli_i8751.mcu", 0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 19 i8751 Code +}; + +STD_ROM_PICK(mrheli) +STD_ROM_FN(mrheli) + +static INT32 mrheliInit() +{ + m72_install_protection(bchopper_code, mrheli_crc, bchopper_sample_offsets); + + return DrvInit(common_080000_0a0000, sound_ram_map, dbreedm72RomLoadCallback, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvMrheli = { + "mrheli", "bchopper", NULL, NULL, "1987", + "Mr. HELI no Dai-Bouken\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, mrheliRomInfo, mrheliRomName, NULL, NULL, CommonInputInfo, BchopperDIPInfo, + mrheliInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Ninja Spirit + +static struct BurnRomInfo nspiritRomDesc[] = { + { "nin-c-h0.rom", 0x10000, 0x035692fa, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "nin-c-l0.rom", 0x10000, 0x9a405898, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "nin-c-h1.rom", 0x10000, 0xcbc10586, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "nin-c-l1.rom", 0x10000, 0xb75c9a4d, 0x01 | BRF_PRG | BRF_ESS }, // 3 + { "nin-c-h2.rom", 0x10000, 0x8ad818fa, 0x01 | BRF_PRG | BRF_ESS }, // 4 + { "nin-c-l2.rom", 0x10000, 0xc52ca78c, 0x01 | BRF_PRG | BRF_ESS }, // 5 + { "nin-c-h3.rom", 0x10000, 0x501104ef, 0x01 | BRF_PRG | BRF_ESS }, // 6 + { "nin-c-l3.rom", 0x10000, 0xfd7408b8, 0x01 | BRF_PRG | BRF_ESS }, // 7 + + { "nin-r00.rom", 0x20000, 0x5f61d30b, 0x02 | BRF_GRA }, // 8 Sprites + { "nin-r10.rom", 0x20000, 0x0caad107, 0x02 | BRF_GRA }, // 9 + { "nin-r20.rom", 0x20000, 0xef3617d3, 0x02 | BRF_GRA }, // 10 + { "nin-r30.rom", 0x20000, 0x175d2a24, 0x02 | BRF_GRA }, // 11 + + { "nin-b-a0.rom", 0x10000, 0x63f8f658, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "nin-b-a1.rom", 0x10000, 0x75eb8306, 0x03 | BRF_GRA }, // 13 + { "nin-b-a2.rom", 0x10000, 0xdf532172, 0x03 | BRF_GRA }, // 14 + { "nin-b-a3.rom", 0x10000, 0x4dedd64c, 0x03 | BRF_GRA }, // 15 + + { "nin-b0.rom", 0x10000, 0x1b0e08a6, 0x04 | BRF_GRA }, // 16 Background Tiles + { "nin-b1.rom", 0x10000, 0x728727f0, 0x04 | BRF_GRA }, // 17 + { "nin-b2.rom", 0x10000, 0xf87efd75, 0x04 | BRF_GRA }, // 18 + { "nin-b3.rom", 0x10000, 0x98856cb4, 0x04 | BRF_GRA }, // 19 + + { "nin-v0.rom", 0x10000, 0xa32e8caf, 0x05 | BRF_SND }, // 20 DAC Samples + + { "nspirit_i8751.mcu", 0x01000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 21 i8751 Code +}; + +STD_ROM_PICK(nspirit) +STD_ROM_FN(nspirit) + +static INT32 nspiritInit() +{ + install_protection(nspirit); + + return DrvInit(common_080000_0a0000, sound_ram_map, NULL, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvNspirit = { + "nspirit", NULL, NULL, NULL, "1988", + "Ninja Spirit\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, nspiritRomInfo, nspiritRomName, NULL, NULL, CommonInputInfo, NspiritDIPInfo, + nspiritInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Saigo no Nindou (Japan) + +static struct BurnRomInfo nspiritjRomDesc[] = { + { "c-h0", 0x10000, 0x8603fab2, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "c-l0", 0x10000, 0xe520fa35, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "nin-c-h1.rom", 0x10000, 0xcbc10586, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "nin-c-l1.rom", 0x10000, 0xb75c9a4d, 0x01 | BRF_PRG | BRF_ESS }, // 3 + { "nin-c-h2.rom", 0x10000, 0x8ad818fa, 0x01 | BRF_PRG | BRF_ESS }, // 4 + { "nin-c-l2.rom", 0x10000, 0xc52ca78c, 0x01 | BRF_PRG | BRF_ESS }, // 5 + { "c-h3", 0x10000, 0x95b63a61, 0x01 | BRF_PRG | BRF_ESS }, // 6 + { "c-l3", 0x10000, 0xe754a87a, 0x01 | BRF_PRG | BRF_ESS }, // 7 + + { "nin-r00.rom", 0x20000, 0x5f61d30b, 0x02 | BRF_GRA }, // 8 Sprites + { "nin-r10.rom", 0x20000, 0x0caad107, 0x02 | BRF_GRA }, // 9 + { "nin-r20.rom", 0x20000, 0xef3617d3, 0x02 | BRF_GRA }, // 10 + { "nin-r30.rom", 0x20000, 0x175d2a24, 0x02 | BRF_GRA }, // 11 + + { "nin-b-a0.rom", 0x10000, 0x63f8f658, 0x03 | BRF_GRA }, // 12 Foreground Tiles + { "nin-b-a1.rom", 0x10000, 0x75eb8306, 0x03 | BRF_GRA }, // 13 + { "nin-b-a2.rom", 0x10000, 0xdf532172, 0x03 | BRF_GRA }, // 14 + { "nin-b-a3.rom", 0x10000, 0x4dedd64c, 0x03 | BRF_GRA }, // 15 + + { "nin-b0.rom", 0x10000, 0x1b0e08a6, 0x04 | BRF_GRA }, // 16 Background Tiles + { "nin-b1.rom", 0x10000, 0x728727f0, 0x04 | BRF_GRA }, // 17 + { "nin-b2.rom", 0x10000, 0xf87efd75, 0x04 | BRF_GRA }, // 18 + { "nin-b3.rom", 0x10000, 0x98856cb4, 0x04 | BRF_GRA }, // 19 + + { "nin-v0.rom", 0x10000, 0xa32e8caf, 0x05 | BRF_SND }, // 20 DAC Samples + + { "nin_c-pr.bin", 0x01000, 0x802d440a, 0x00 | BRF_OPT }, // 21 i8751 Code +}; + +STD_ROM_PICK(nspiritj) +STD_ROM_FN(nspiritj) + +static INT32 nspiritjInit() +{ + m72_install_protection(nspirit_code, nspiritj_crc, nspirit_sample_offsets); + + return DrvInit(common_080000_0a0000, sound_ram_map, NULL, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvNspiritj = { + "nspiritj", "nspirit", NULL, NULL, "1988", + "Saigo no Nindou (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, nspiritjRomInfo, nspiritjRomName, NULL, NULL, CommonInputInfo, NspiritDIPInfo, + nspiritjInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Image Fight (Japan, revision A) + +static struct BurnRomInfo imgfightRomDesc[] = { + { "if-c-h0-a.bin", 0x10000, 0xf5c94464, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "if-c-l0-a.bin", 0x10000, 0x87c534fe, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "if-c-h3.bin", 0x20000, 0xea030541, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "if-c-l3.bin", 0x20000, 0xc66ae348, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "if-c-00.bin", 0x20000, 0x745e6638, 0x02 | BRF_GRA }, // 4 Sprites + { "if-c-10.bin", 0x20000, 0xb7108449, 0x02 | BRF_GRA }, // 5 + { "if-c-20.bin", 0x20000, 0xaef33cba, 0x02 | BRF_GRA }, // 6 + { "if-c-30.bin", 0x20000, 0x1f98e695, 0x02 | BRF_GRA }, // 7 + + { "if-a-a0.bin", 0x10000, 0x34ee2d77, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "if-a-a1.bin", 0x10000, 0x6bd2845b, 0x03 | BRF_GRA }, // 9 + { "if-a-a2.bin", 0x10000, 0x090d50e5, 0x03 | BRF_GRA }, // 10 + { "if-a-a3.bin", 0x10000, 0x3a8e3083, 0x03 | BRF_GRA }, // 11 + + { "if-a-b0.bin", 0x10000, 0xb425c829, 0x04 | BRF_GRA }, // 12 Background Tiles + { "if-a-b1.bin", 0x10000, 0xe9bfe23e, 0x04 | BRF_GRA }, // 13 + { "if-a-b2.bin", 0x10000, 0x256e50f2, 0x04 | BRF_GRA }, // 14 + { "if-a-b3.bin", 0x10000, 0x4c682785, 0x04 | BRF_GRA }, // 15 + + { "if-c-v0.bin", 0x10000, 0xcb64a194, 0x05 | BRF_SND }, // 16 DAC Samples + { "if-c-v1.bin", 0x10000, 0x45b68bf5, 0x05 | BRF_SND }, // 17 + + { "imgfight_i8751h.bin",0x01000, 0xef0d5098, 0x00 | BRF_OPT }, // 18 i8751 Code +}; + +STD_ROM_PICK(imgfight) +STD_ROM_FN(imgfight) + +static INT32 imgfightRomLoadCallback() +{ + memcpy (DrvV30ROM + 0x40000, DrvV30ROM + 0x20000, 0x40000); + + return 0; +} + +static INT32 imgfightInit() +{ + install_protection(imgfight); + + return DrvInit(common_080000_0a0000, sound_ram_map, imgfightRomLoadCallback, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvImgfight = { + "imgfight", NULL, NULL, NULL, "1988", + "Image Fight (Japan, revision A)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_VERSHOOT, 0, + NULL, imgfightRomInfo, imgfightRomName, NULL, NULL, CommonInputInfo, ImgfightDIPInfo, + imgfightInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// Image Fight (Japan) + +static struct BurnRomInfo imgfightoRomDesc[] = { + { "if-c-h0.bin", 0x10000, 0x592d2d80, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "if-c-l0.bin", 0x10000, 0x61f89056, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "if-c-h3.bin", 0x20000, 0xea030541, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "if-c-l3.bin", 0x20000, 0xc66ae348, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "if-c-00.bin", 0x20000, 0x745e6638, 0x02 | BRF_GRA }, // 4 Sprites + { "if-c-10.bin", 0x20000, 0xb7108449, 0x02 | BRF_GRA }, // 5 + { "if-c-20.bin", 0x20000, 0xaef33cba, 0x02 | BRF_GRA }, // 6 + { "if-c-30.bin", 0x20000, 0x1f98e695, 0x02 | BRF_GRA }, // 7 + + { "if-a-a0.bin", 0x10000, 0x34ee2d77, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "if-a-a1.bin", 0x10000, 0x6bd2845b, 0x03 | BRF_GRA }, // 9 + { "if-a-a2.bin", 0x10000, 0x090d50e5, 0x03 | BRF_GRA }, // 10 + { "if-a-a3.bin", 0x10000, 0x3a8e3083, 0x03 | BRF_GRA }, // 11 + + { "if-a-b0.bin", 0x10000, 0xb425c829, 0x04 | BRF_GRA }, // 12 Background Tiles + { "if-a-b1.bin", 0x10000, 0xe9bfe23e, 0x04 | BRF_GRA }, // 13 + { "if-a-b2.bin", 0x10000, 0x256e50f2, 0x04 | BRF_GRA }, // 14 + { "if-a-b3.bin", 0x10000, 0x4c682785, 0x04 | BRF_GRA }, // 15 + + { "if-c-v0.bin", 0x10000, 0xcb64a194, 0x05 | BRF_SND }, // 16 DAC Samples + { "if-c-v1.bin", 0x10000, 0x45b68bf5, 0x05 | BRF_SND }, // 17 + + { "imgfight_i8751h.bin",0x01000, 0xef0d5098, 0x00 | BRF_OPT }, // 18 i8751 Code +}; + +STD_ROM_PICK(imgfighto) +STD_ROM_FN(imgfighto) + +struct BurnDriver BurnDrvImgfighto = { + "imgfighto", "imgfight", NULL, NULL, "1988", + "Image Fight (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_VERSHOOT, 0, + NULL, imgfightoRomInfo, imgfightoRomName, NULL, NULL, CommonInputInfo, ImgfightDIPInfo, + imgfightInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// Air Duel (Japan) + +static struct BurnRomInfo airduelRomDesc[] = { + { "ad-c-h0.bin", 0x20000, 0x12140276, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ad-c-l0.bin", 0x20000, 0x4ac0b91d, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ad-c-h3.bin", 0x20000, 0x9f7cfca3, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ad-c-l3.bin", 0x20000, 0x9dd343f7, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ad-00.bin", 0x20000, 0x2f0d599b, 0x02 | BRF_GRA }, // 4 Sprites + { "ad-10.bin", 0x20000, 0x9865856b, 0x02 | BRF_GRA }, // 5 + { "ad-20.bin", 0x20000, 0xd392aef2, 0x02 | BRF_GRA }, // 6 + { "ad-30.bin", 0x20000, 0x923240c3, 0x02 | BRF_GRA }, // 7 + + { "ad-a0.bin", 0x20000, 0xce134b47, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "ad-a1.bin", 0x20000, 0x097fd853, 0x03 | BRF_GRA }, // 9 + { "ad-a2.bin", 0x20000, 0x6a94c1b9, 0x03 | BRF_GRA }, // 10 + { "ad-a3.bin", 0x20000, 0x6637c349, 0x03 | BRF_GRA }, // 11 + + { "ad-b0.bin", 0x20000, 0xce134b47, 0x04 | BRF_GRA }, // 12 Background Tiles + { "ad-b1.bin", 0x20000, 0x097fd853, 0x04 | BRF_GRA }, // 13 + { "ad-b2.bin", 0x20000, 0x6a94c1b9, 0x04 | BRF_GRA }, // 14 + { "ad-b3.bin", 0x20000, 0x6637c349, 0x04 | BRF_GRA }, // 15 + + { "ad-v0.bin", 0x20000, 0x339f474d, 0x05 | BRF_SND }, // 16 DAC Samples + + { "airduel_i8751.mcu", 0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 17 i8751 Code +}; + +STD_ROM_PICK(airduel) +STD_ROM_FN(airduel) + +static INT32 airduelInit() +{ + install_protection(airduel); + + return DrvInit(common_080000_0a0000, sound_ram_map, NULL, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvAirduel = { + "airduel", NULL, NULL, NULL, "1990", + "Air Duel (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_VERSHOOT, 0, + NULL, airduelRomInfo, airduelRomName, NULL, NULL, CommonInputInfo, AirduelDIPInfo, + airduelInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// R-Type II + +static struct BurnRomInfo rtype2RomDesc[] = { + { "rt2-a-h0-d.54", 0x20000, 0xd8ece6f4, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt2-a-l0-d.60", 0x20000, 0x32cfb2e4, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt2-a-h1-d.53", 0x20000, 0x4f6e9b15, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt2-a-l1-d.59", 0x20000, 0x0fd123bf, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ic17.4f", 0x10000, 0x73ffecb4, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ic31.6l", 0x20000, 0x2cd8f913, 0x02 | BRF_GRA }, // 5 Sprites + { "ic21.4l", 0x20000, 0x5033066d, 0x02 | BRF_GRA }, // 6 + { "ic32.6m", 0x20000, 0xec3a0450, 0x02 | BRF_GRA }, // 7 + { "ic22.4m", 0x20000, 0xdb6176fc, 0x02 | BRF_GRA }, // 8 + + { "ic50.7s", 0x20000, 0xf3f8736e, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ic51.7u", 0x20000, 0xb4c543af, 0x03 | BRF_GRA }, // 10 + { "ic56.8s", 0x20000, 0x4cb80d66, 0x03 | BRF_GRA }, // 11 + { "ic57.8u", 0x20000, 0xbee128e0, 0x03 | BRF_GRA }, // 12 + { "ic65.9r", 0x20000, 0x2dc9c71a, 0x03 | BRF_GRA }, // 13 + { "ic66.9u", 0x20000, 0x7533c428, 0x03 | BRF_GRA }, // 14 + { "ic63.9m", 0x20000, 0xa6ad67f2, 0x03 | BRF_GRA }, // 15 + { "ic64.9p", 0x20000, 0x3686d555, 0x03 | BRF_GRA }, // 16 + + { "ic14.4c", 0x20000, 0x637172d5, 0x05 | BRF_SND }, // 17 DAC Samples +}; + +STD_ROM_PICK(rtype2) +STD_ROM_FN(rtype2) + +static INT32 rtype2Init() +{ + return DrvInit(rtype2_main_cpu_map, sound_rom_map, NULL, 0x80, Z80_REAL_NMI, 1); +} + +struct BurnDriver BurnDrvRtype2 = { + "rtype2", NULL, NULL, NULL, "1989", + "R-Type II\0", NULL, "Irem", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtype2RomInfo, rtype2RomName, NULL, NULL, CommonInputInfo, Rtype2DIPInfo, + rtype2Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type II (Japan) + +static struct BurnRomInfo rtype2jRomDesc[] = { + { "rt2-a-h0.54", 0x20000, 0x7857ccf6, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt2-a-l0.60", 0x20000, 0xcb22cd6e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt2-a-h1.53", 0x20000, 0x49e75d28, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt2-a-l1.59", 0x20000, 0x12ec1676, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ic17.4f", 0x10000, 0x73ffecb4, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ic31.6l", 0x20000, 0x2cd8f913, 0x02 | BRF_GRA }, // 5 Sprites + { "ic21.4l", 0x20000, 0x5033066d, 0x02 | BRF_GRA }, // 6 + { "ic32.6m", 0x20000, 0xec3a0450, 0x02 | BRF_GRA }, // 7 + { "ic22.4m", 0x20000, 0xdb6176fc, 0x02 | BRF_GRA }, // 8 + + { "ic50.7s", 0x20000, 0xf3f8736e, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ic51.7u", 0x20000, 0xb4c543af, 0x03 | BRF_GRA }, // 10 + { "ic56.8s", 0x20000, 0x4cb80d66, 0x03 | BRF_GRA }, // 11 + { "ic57.8u", 0x20000, 0xbee128e0, 0x03 | BRF_GRA }, // 12 + { "ic65.9r", 0x20000, 0x2dc9c71a, 0x03 | BRF_GRA }, // 13 + { "ic66.9u", 0x20000, 0x7533c428, 0x03 | BRF_GRA }, // 14 + { "ic63.9m", 0x20000, 0xa6ad67f2, 0x03 | BRF_GRA }, // 15 + { "ic64.9p", 0x20000, 0x3686d555, 0x03 | BRF_GRA }, // 16 + + { "ic14.4c", 0x20000, 0x637172d5, 0x05 | BRF_SND }, // 17 DAC Samples +}; + +STD_ROM_PICK(rtype2j) +STD_ROM_FN(rtype2j) + +struct BurnDriver BurnDrvRtype2j = { + "rtype2j", "rtype2", NULL, NULL, "1989", + "R-Type II (Japan)\0", NULL, "Irem", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtype2jRomInfo, rtype2jRomName, NULL, NULL, CommonInputInfo, Rtype2DIPInfo, + rtype2Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// R-Type II (Japan, revision C) + +static struct BurnRomInfo rtype2jcRomDesc[] = { + { "rt2-a-h0-c.54", 0x20000, 0xef9a9990, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rt2-a-l0-c.60", 0x20000, 0xd8b9da64, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "rt2-a-h1-c.53", 0x20000, 0x1b1870f4, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "rt2-a-l1-c.59", 0x20000, 0x60fdff35, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ic17.4f", 0x10000, 0x73ffecb4, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ic31.6l", 0x20000, 0x2cd8f913, 0x02 | BRF_GRA }, // 5 Sprites + { "ic21.4l", 0x20000, 0x5033066d, 0x02 | BRF_GRA }, // 6 + { "ic32.6m", 0x20000, 0xec3a0450, 0x02 | BRF_GRA }, // 7 + { "ic22.4m", 0x20000, 0xdb6176fc, 0x02 | BRF_GRA }, // 8 + + { "ic50.7s", 0x20000, 0xf3f8736e, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ic51.7u", 0x20000, 0xb4c543af, 0x03 | BRF_GRA }, // 10 + { "ic56.8s", 0x20000, 0x4cb80d66, 0x03 | BRF_GRA }, // 11 + { "ic57.8u", 0x20000, 0xbee128e0, 0x03 | BRF_GRA }, // 12 + { "ic65.9r", 0x20000, 0x2dc9c71a, 0x03 | BRF_GRA }, // 13 + { "ic66.9u", 0x20000, 0x7533c428, 0x03 | BRF_GRA }, // 14 + { "ic63.9m", 0x20000, 0xa6ad67f2, 0x03 | BRF_GRA }, // 15 + { "ic64.9p", 0x20000, 0x3686d555, 0x03 | BRF_GRA }, // 16 + + { "ic14.4c", 0x20000, 0x637172d5, 0x05 | BRF_SND }, // 17 DAC Samples +}; + +STD_ROM_PICK(rtype2jc) +STD_ROM_FN(rtype2jc) + +struct BurnDriver BurnDrvRtype2jc = { + "rtype2jc", "rtype2", NULL, NULL, "1989", + "R-Type II (Japan, revision C)\0", NULL, "Irem", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, rtype2jcRomInfo, rtype2jcRomName, NULL, NULL, CommonInputInfo, Rtype2DIPInfo, + rtype2Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Hammerin' Harry (World) + +static struct BurnRomInfo hharryRomDesc[] = { + { "a-h0-v.rom", 0x20000, 0xc52802a5, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "a-l0-v.rom", 0x20000, 0xf463074c, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "a-h1-0.rom", 0x10000, 0x3ae21335, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "a-l1-0.rom", 0x10000, 0xbc6ac5f9, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "a-sp-0.rom", 0x10000, 0x80e210e7, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "hh_00.rom", 0x20000, 0xec5127ef, 0x02 | BRF_GRA }, // 5 Sprites + { "hh_10.rom", 0x20000, 0xdef65294, 0x02 | BRF_GRA }, // 6 + { "hh_20.rom", 0x20000, 0xbb0d6ad4, 0x02 | BRF_GRA }, // 7 + { "hh_30.rom", 0x20000, 0x4351044e, 0x02 | BRF_GRA }, // 8 + + { "hh_a0.rom", 0x20000, 0xc577ba5f, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "hh_a1.rom", 0x20000, 0x429d12ab, 0x03 | BRF_GRA }, // 10 + { "hh_a2.rom", 0x20000, 0xb5b163b0, 0x03 | BRF_GRA }, // 11 + { "hh_a3.rom", 0x20000, 0x8ef566a1, 0x03 | BRF_GRA }, // 12 + + { "a-v0-0.rom", 0x20000, 0xfaaacaff, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(hharry) +STD_ROM_FN(hharry) + +static INT32 hharryInit() +{ + return DrvInit(common_080000_0a0000, sound_rom_map, dbreedm72RomLoadCallback, 0x20, Z80_REAL_NMI, 2); +} + +struct BurnDriver BurnDrvHharry = { + "hharry", NULL, NULL, NULL, "1990", + "Hammerin' Harry (World)\0", NULL, "Irem", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hharryRomInfo, hharryRomName, NULL, NULL, CommonInputInfo, HharryDIPInfo, + hharryInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Hammerin' Harry (US) + +static struct BurnRomInfo hharryuRomDesc[] = { + { "a-ho-u.8d", 0x20000, 0xede7f755, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "a-lo-u.9d", 0x20000, 0xdf0726ae, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "a-h1-f.8b", 0x10000, 0x31b741c5, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "a-l1-f.9b", 0x10000, 0xb23e966c, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "a-sp-0.rom", 0x10000, 0x80e210e7, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "hh_00.rom", 0x20000, 0xec5127ef, 0x02 | BRF_GRA }, // 5 Sprites + { "hh_10.rom", 0x20000, 0xdef65294, 0x02 | BRF_GRA }, // 6 + { "hh_20.rom", 0x20000, 0xbb0d6ad4, 0x02 | BRF_GRA }, // 7 + { "hh_30.rom", 0x20000, 0x4351044e, 0x02 | BRF_GRA }, // 8 + + { "hh_a0.rom", 0x20000, 0xc577ba5f, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "hh_a1.rom", 0x20000, 0x429d12ab, 0x03 | BRF_GRA }, // 10 + { "hh_a2.rom", 0x20000, 0xb5b163b0, 0x03 | BRF_GRA }, // 11 + { "hh_a3.rom", 0x20000, 0x8ef566a1, 0x03 | BRF_GRA }, // 12 + + { "a-v0-0.rom", 0x20000, 0xfaaacaff, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(hharryu) +STD_ROM_FN(hharryu) + +static INT32 hharryuInit() +{ + return DrvInit(hharryu_main_cpu_map, sound_rom_map, dbreedm72RomLoadCallback, 0x20, Z80_REAL_NMI, 1); +} + +struct BurnDriver BurnDrvHharryu = { + "hharryu", "hharry", NULL, NULL, "1990", + "Hammerin' Harry (US)\0", NULL, "Irem America", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hharryuRomInfo, hharryuRomName, NULL, NULL, CommonInputInfo, HharryDIPInfo, + hharryuInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Daiku no Gensan (Japan, M82) + +static struct BurnRomInfo dkgensanRomDesc[] = { + { "gen-a-h0.bin", 0x20000, 0x07a45f6d, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "gen-a-l0.bin", 0x20000, 0x46478fea, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "gen-a-h1.bin", 0x10000, 0x54e5b73c, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "gen-a-l1.bin", 0x10000, 0x894f8a9f, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "gen-a-sp.bin", 0x10000, 0xe83cfc2c, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "hh_00.rom", 0x20000, 0xec5127ef, 0x02 | BRF_GRA }, // 5 Sprites + { "hh_10.rom", 0x20000, 0xdef65294, 0x02 | BRF_GRA }, // 6 + { "hh_20.rom", 0x20000, 0xbb0d6ad4, 0x02 | BRF_GRA }, // 7 + { "hh_30.rom", 0x20000, 0x4351044e, 0x02 | BRF_GRA }, // 8 + + { "hh_a0.rom", 0x20000, 0xc577ba5f, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "hh_a1.rom", 0x20000, 0x429d12ab, 0x03 | BRF_GRA }, // 10 + { "hh_a2.rom", 0x20000, 0xb5b163b0, 0x03 | BRF_GRA }, // 11 + { "hh_a3.rom", 0x20000, 0x8ef566a1, 0x03 | BRF_GRA }, // 12 + + { "gen-vo.bin", 0x20000, 0xd8595c66, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(dkgensan) +STD_ROM_FN(dkgensan) + +struct BurnDriver BurnDrvDkgensan = { + "dkgensan", "hharry", NULL, NULL, "1990", + "Daiku no Gensan (Japan, M82)\0", NULL, "Irem", "M82", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, dkgensanRomInfo, dkgensanRomName, NULL, NULL, CommonInputInfo, HharryDIPInfo, + hharryuInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Daiku no Gensan (Japan, M72) + +static struct BurnRomInfo dkgensanm72RomDesc[] = { + { "ge72-h0.bin", 0x20000, 0xa0ad992c, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ge72-l0.bin", 0x20000, 0x996396f0, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ge72-h3.bin", 0x10000, 0xd8b86005, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ge72-l3.bin", 0x10000, 0x23d303a5, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "hh_00.rom", 0x20000, 0xec5127ef, 0x02 | BRF_GRA }, // 4 Sprites + { "hh_10.rom", 0x20000, 0xdef65294, 0x02 | BRF_GRA }, // 5 + { "hh_20.rom", 0x20000, 0xbb0d6ad4, 0x02 | BRF_GRA }, // 6 + { "hh_30.rom", 0x20000, 0x4351044e, 0x02 | BRF_GRA }, // 7 + + { "ge72b-a0.bin", 0x10000, 0xf5f56b2a, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "ge72-a1.bin", 0x10000, 0xd194ea08, 0x03 | BRF_GRA }, // 9 + { "ge72-a2.bin", 0x10000, 0x2b06bcc3, 0x03 | BRF_GRA }, // 10 + { "ge72-a3.bin", 0x10000, 0x94b96bfa, 0x03 | BRF_GRA }, // 11 + + { "ge72-b0.bin", 0x10000, 0x208796b3, 0x04 | BRF_GRA }, // 12 Background Tiles + { "ge72-b1.bin", 0x10000, 0xb4a7f490, 0x04 | BRF_GRA }, // 13 + { "ge72b-b2.bin", 0x10000, 0x34fe8f7f, 0x04 | BRF_GRA }, // 14 + { "ge72b-b3.bin", 0x10000, 0x4b0e92f4, 0x04 | BRF_GRA }, // 15 + + { "gen-vo.bin", 0x20000, 0xd8595c66, 0x05 | BRF_SND }, // 16 DAC Samples + + { "dkgenm72_i8751.mcu", 0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 17 i8751 Code +}; + +STD_ROM_PICK(dkgensanm72) +STD_ROM_FN(dkgensanm72) + +static INT32 dkgensanm72Init() +{ + install_protection(dkgenm72); + + return DrvInit(common_080000_0a0000, sound_ram_map, dbreedm72RomLoadCallback, 0x20, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvDkgensanm72 = { + "dkgensanm72", "hharry", NULL, NULL, "1990", + "Daiku no Gensan (Japan, M72)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, dkgensanm72RomInfo, dkgensanm72RomName, NULL, NULL, CommonInputInfo, HharryDIPInfo, + dkgensanm72Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Ken-Go + +static struct BurnRomInfo kengoRomDesc[] = { + { "ken_d-h0.rom", 0x20000, 0xf4ddeea5, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ken_d-l0.rom", 0x20000, 0x04dc0f81, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "ken_d-sp.rom", 0x10000, 0x233ca1cf, 0x06 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "ken_m31.rom", 0x20000, 0xe00b95a6, 0x02 | BRF_GRA }, // 3 Sprites + { "ken_m21.rom", 0x20000, 0xd7722f87, 0x02 | BRF_GRA }, // 4 + { "ken_m32.rom", 0x20000, 0x30a844c4, 0x02 | BRF_GRA }, // 5 + { "ken_m22.rom", 0x20000, 0xa00dac85, 0x02 | BRF_GRA }, // 6 + + { "ken_m51.rom", 0x20000, 0x1646cf4f, 0x03 | BRF_GRA }, // 7 Foreground & Background Tiles + { "ken_m57.rom", 0x20000, 0xa9f88d90, 0x03 | BRF_GRA }, // 8 + { "ken_m66.rom", 0x20000, 0xe9d17645, 0x03 | BRF_GRA }, // 9 + { "ken_m64.rom", 0x20000, 0xdf46709b, 0x03 | BRF_GRA }, // 10 + + { "ken_m14.rom", 0x20000, 0x6651e9b7, 0x05 | BRF_SND }, // 11 DAC Samples +}; + +STD_ROM_PICK(kengo) +STD_ROM_FN(kengo) + +static INT32 kengoInit() +{ + INT32 nRet = DrvInit(hharryu_main_cpu_map, sound_rom_map, NULL, 0x60, Z80_REAL_NMI, 1); + + if (nRet == 0) { + VezOpen(0); + VezSetDecode((UINT8*)gunforce_decryption_table); + VezClose(); + } + + return nRet; +} + +struct BurnDriver BurnDrvKengo = { + "kengo", NULL, NULL, NULL, "1991", + "Ken-Go\0", NULL, "Irem", "M84?", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, kengoRomInfo, kengoRomName, NULL, NULL, CommonInputInfo, KengoDIPInfo, + kengoInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Cosmic Cop (World) + +static struct BurnRomInfo cosmccopRomDesc[] = { + { "cc-d-h0b.bin", 0x40000, 0x38958b01, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "cc-d-l0b.bin", 0x40000, 0xeff87f70, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "cc-d-sp.bin", 0x10000, 0x3e3ace60, 0x06 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "cc-c-00.bin", 0x20000, 0x9d99deaa, 0x02 | BRF_GRA }, // 3 Sprites + { "cc-c-10.bin", 0x20000, 0x7eb083ed, 0x02 | BRF_GRA }, // 4 + { "cc-c-20.bin", 0x20000, 0x9421489e, 0x02 | BRF_GRA }, // 5 + { "cc-c-30.bin", 0x20000, 0x920ec735, 0x02 | BRF_GRA }, // 6 + + { "cc-d-g00.bin", 0x20000, 0xe7f3d772, 0x03 | BRF_GRA }, // 7 Foreground & Background Tiles + { "cc-d-g10.bin", 0x20000, 0x418b4e4c, 0x03 | BRF_GRA }, // 8 + { "cc-d-g20.bin", 0x20000, 0xa4b558eb, 0x03 | BRF_GRA }, // 9 + { "cc-d-g30.bin", 0x20000, 0xf64a3166, 0x03 | BRF_GRA }, // 10 + + { "cc-c-v0.bin", 0x20000, 0x6247bade, 0x05 | BRF_SND }, // 11 DAC Samples +}; + +STD_ROM_PICK(cosmccop) +STD_ROM_FN(cosmccop) + +static INT32 cosmccopInit() +{ + return DrvInit(hharryu_main_cpu_map, sound_rom_map, NULL, 0x60, Z80_REAL_NMI, 1); +} + +struct BurnDriver BurnDrvCosmccop = { + "cosmccop", NULL, NULL, NULL, "1991", + "Cosmic Cop (World)\0", NULL, "Irem", "M84", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, cosmccopRomInfo, cosmccopRomName, NULL, NULL, CommonInputInfo, GallopDIPInfo, + cosmccopInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Gallop - Armed police Unit (Japan) + +static struct BurnRomInfo gallopRomDesc[] = { + { "cc-c-h0.bin", 0x20000, 0x2217dcd0, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "cc-c-l0.bin", 0x20000, 0xff39d7fb, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "cc-c-h3.bin", 0x20000, 0x9b2bbab9, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "cc-c-l3.bin", 0x20000, 0xacd3278e, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "cc-c-00.bin", 0x20000, 0x9d99deaa, 0x02 | BRF_GRA }, // 4 Sprites + { "cc-c-10.bin", 0x20000, 0x7eb083ed, 0x02 | BRF_GRA }, // 5 + { "cc-c-20.bin", 0x20000, 0x9421489e, 0x02 | BRF_GRA }, // 6 + { "cc-c-30.bin", 0x20000, 0x920ec735, 0x02 | BRF_GRA }, // 7 + + { "cc-b-a0.bin", 0x10000, 0xa33472bd, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "cc-b-a1.bin", 0x10000, 0x118b1f2d, 0x03 | BRF_GRA }, // 9 + { "cc-b-a2.bin", 0x10000, 0x83cebf48, 0x03 | BRF_GRA }, // 10 + { "cc-b-a3.bin", 0x10000, 0x572903fc, 0x03 | BRF_GRA }, // 11 + + { "cc-b-b0.bin", 0x10000, 0x0df5b439, 0x04 | BRF_GRA }, // 12 Background Tiles + { "cc-b-b1.bin", 0x10000, 0x010b778f, 0x04 | BRF_GRA }, // 13 + { "cc-b-b2.bin", 0x10000, 0xbda9f6fb, 0x04 | BRF_GRA }, // 14 + { "cc-b-b3.bin", 0x10000, 0xd361ba3f, 0x04 | BRF_GRA }, // 15 + + { "cc-c-v0.bin", 0x20000, 0x6247bade, 0x05 | BRF_SND }, // 16 DAC Samples +}; + +STD_ROM_PICK(gallop) +STD_ROM_FN(gallop) + +static INT32 gallopInit() +{ + protection_sample_offsets = gallop_sample_offsets; + + return DrvInit(common_080000_0a0000, sound_ram_map, NULL, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvGallop = { + "gallop", "cosmccop", NULL, NULL, "1991", + "Gallop - Armed police Unit (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_HORSHOOT, 0, + NULL, gallopRomInfo, gallopRomName, NULL, NULL, CommonInputInfo, GallopDIPInfo, + gallopInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + + +// Legend of Hero Tonma + +static struct BurnRomInfo lohtRomDesc[] = { + { "tom_c-h0.rom", 0x20000, 0xa63204b6, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "tom_c-l0.rom", 0x20000, 0xe788002f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "tom_c-h3-", 0x20000, 0x714778b5, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "tom_c-l3-", 0x20000, 0x2f049b03, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "tom_m53.rom", 0x20000, 0x0b83265f, 0x02 | BRF_GRA }, // 4 Sprites + { "tom_m51.rom", 0x20000, 0x8ec5f6f3, 0x02 | BRF_GRA }, // 5 + { "tom_m49.rom", 0x20000, 0xa41d3bfd, 0x02 | BRF_GRA }, // 6 + { "tom_m47.rom", 0x20000, 0x9d81a25b, 0x02 | BRF_GRA }, // 7 + + { "tom_m21.rom", 0x10000, 0x3ca3e771, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "tom_m22.rom", 0x10000, 0x7a05ee2f, 0x03 | BRF_GRA }, // 9 + { "tom_m20.rom", 0x10000, 0x79aa2335, 0x03 | BRF_GRA }, // 10 + { "tom_m23.rom", 0x10000, 0x789e8b24, 0x03 | BRF_GRA }, // 11 + + { "tom_m26.rom", 0x10000, 0x44626bf6, 0x04 | BRF_GRA }, // 12 Background Tiles + { "tom_m27.rom", 0x10000, 0x464952cf, 0x04 | BRF_GRA }, // 13 + { "tom_m25.rom", 0x10000, 0x3db9b2c7, 0x04 | BRF_GRA }, // 14 + { "tom_m24.rom", 0x10000, 0xf01fe899, 0x04 | BRF_GRA }, // 15 + + { "tom_m44.rom", 0x10000, 0x3ed51d1f, 0x05 | BRF_SND }, // 16 DAC Samples + + { "loht_i8751.mcu", 0x10000, 0x00000000, 0x00 | BRF_OPT | BRF_NODUMP }, // 17 i8751 Code +}; + +STD_ROM_PICK(loht) +STD_ROM_FN(loht) + +static INT32 lohtInit() +{ + install_protection(loht); + + return DrvInit(common_080000_0a0000, sound_ram_map, NULL, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvLoht = { + "loht", NULL, NULL, NULL, "1989", + "Legend of Hero Tonma\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, lohtRomInfo, lohtRomName, NULL, NULL, CommonInputInfo, LohtDIPInfo, + lohtInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Legend of Hero Tonma (Japan) + +static struct BurnRomInfo lohtjRomDesc[] = { + { "tom_c-h0-", 0x20000, 0x2a752998, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "tom_c-l0-", 0x20000, 0xa224d928, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "tom_c-h3-", 0x20000, 0x714778b5, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "tom_c-l3-", 0x20000, 0x2f049b03, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "r200", 0x20000, 0x0b83265f, 0x02 | BRF_GRA }, // 4 Sprites + { "r210", 0x20000, 0x8ec5f6f3, 0x02 | BRF_GRA }, // 5 + { "r220", 0x20000, 0xa41d3bfd, 0x02 | BRF_GRA }, // 6 + { "r230", 0x20000, 0x9d81a25b, 0x02 | BRF_GRA }, // 7 + + { "r2a0.a0", 0x10000, 0x3ca3e771, 0x03 | BRF_GRA }, // 8 Foreground Tiles + { "r2a1.a1", 0x10000, 0x7a05ee2f, 0x03 | BRF_GRA }, // 9 + { "r2a2.a2", 0x10000, 0x79aa2335, 0x03 | BRF_GRA }, // 10 + { "r2a3.a3", 0x10000, 0x789e8b24, 0x03 | BRF_GRA }, // 11 + + { "078.b0", 0x10000, 0x44626bf6, 0x04 | BRF_GRA }, // 12 Background Tiles + { "079.b1", 0x10000, 0x464952cf, 0x04 | BRF_GRA }, // 13 + { "080.b2", 0x10000, 0x3db9b2c7, 0x04 | BRF_GRA }, // 14 + { "081.b3", 0x10000, 0xf01fe899, 0x04 | BRF_GRA }, // 15 + + { "082", 0x10000, 0x3ed51d1f, 0x05 | BRF_SND }, // 16 DAC Samples + + { "tom_c-pr.bin", 0x01000, 0x9fa9b496, 0x00 | BRF_OPT }, // 17 i8751 Code +}; + +STD_ROM_PICK(lohtj) +STD_ROM_FN(lohtj) + +struct BurnDriver BurnDrvLohtj = { + "lohtj", "loht", NULL, NULL, "1989", + "Legend of Hero Tonma (Japan)\0", NULL, "Irem", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, lohtjRomInfo, lohtjRomName, NULL, NULL, CommonInputInfo, LohtDIPInfo, + lohtInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + +static INT32 lohtbRomLoadCallback() +{ + // Hack the program rom to work for now + UINT8 _0x400[216] = { + 0xFA, 0xB9, 0xFF, 0xFF, 0xE2, 0xFE, 0xB8, 0x17, 0x00, 0xE7, 0x40, 0xB8, 0x20, 0x00, 0xE7, 0x42, + 0xB8, 0x0F, 0x00, 0xE7, 0x42, 0xB8, 0x00, 0xA0, 0x8E, 0xD0, 0x8E, 0xD8, 0xBE, 0x00, 0x3F, 0xB0, + 0x00, 0x88, 0x04, 0x3A, 0x04, 0x75, 0x08, 0x46, 0xFE, 0xC0, 0x75, 0xF5, 0xE9, 0x18, 0x00, 0x33, + 0xF6, 0xE9, 0x03, 0x00, 0xBE, 0x40, 0x00, 0xB8, 0x00, 0xB0, 0x8E, 0xD8, 0xC7, 0x06, 0xFE, 0x0F, + 0x00, 0x00, 0xEA, 0x62, 0x11, 0x00, 0x00, 0xE5, 0x04, 0x0F, 0x19, 0xC0, 0x0F, 0x74, 0xE0, 0xBC, + 0x00, 0x40, 0x33, 0xDB, 0xB9, 0x00, 0x10, 0xB8, 0x00, 0xB0, 0x8E, 0xD8, 0x8A, 0xC3, 0x02, 0xC7, + 0x88, 0x07, 0x43, 0xE2, 0xF7, 0x33, 0xC9, 0xFE, 0xC9, 0x75, 0xFC, 0xFE, 0xCD, 0x75, 0xF8, 0x33, + 0xDB, 0xB9, 0x00, 0x10, 0x8A, 0xC3, 0x02, 0xC7, 0x34, 0xFF, 0x3A, 0x07, 0x75, 0xB6, 0x43, 0xE2, + 0xF3, 0x33, 0xDB, 0xB9, 0xFC, 0x0F, 0xFE, 0x07, 0x43, 0xE2, 0xFB, 0x90, 0x90, 0x90, 0x9A, 0x00, + 0x00, 0x00, 0xB0, 0x73, 0xF6, 0x90, 0x90, 0x90, 0xB8, 0x00, 0xB0, 0x8E, 0xC0, 0x33, 0xD2, 0x42, + 0x81, 0xE2, 0x01, 0x00, 0xBF, 0xB2, 0x04, 0xE8, 0x7B, 0x00, 0xE8, 0x3E, 0x00, 0xEB, 0xF0, 0x90, + 0x90, 0x90, 0x0B, 0x38, 0x29, 0x43, 0x4F, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x31, + 0x39, 0x38, 0x39, 0x20, 0x49, 0x52, 0x45, 0x4D, 0x20, 0x43, 0x4F, 0x52, 0x50, 0x4F, 0x52, 0x41, + 0x54, 0x49, 0x4F, 0x4E, 0x0B, 0x50, 0x2B, 0x41 + }; + + memcpy (DrvV30ROM + 0x00400, _0x400, 216); + + DrvV30ROM[0x3FC] = 0x88; + DrvV30ROM[0x3FD] = 0x05; + DrvV30ROM[0xB42] = 0x1E; + DrvV30ROM[0xB43] = 0x06; + DrvV30ROM[0xB44] = 0xB8; + DrvV30ROM[0x405B] = 0x05; + DrvV30ROM[0x4066] = 0x05; + DrvV30ROM[0x103DA] = 0xB0; + DrvV30ROM[0x103DD] = 0xFE; + DrvV30ROM[0x103DE] = 0x06; + DrvV30ROM[0x103DF] = 0xFE; + DrvV30ROM[0x103E0] = 0x0F; + DrvV30ROM[0x103E1] = 0xE5; + DrvV30ROM[0x103E2] = 0x02; + DrvV30ROM[0x103E3] = 0xA9; + DrvV30ROM[0x103E4] = 0x20; + DrvV30ROM[0x103E5] = 0x00; + DrvV30ROM[0x103E6] = 0x75; + DrvV30ROM[0x103E7] = 0x05; + DrvV30ROM[0x103E8] = 0xEA; + DrvV30ROM[0x103E9] = 0x2F; + DrvV30ROM[0x103EA] = 0x04; + DrvV30ROM[0x103EB] = 0x00; + DrvV30ROM[0x103EC] = 0x00; + DrvV30ROM[0x103ED] = 0xB8; + DrvV30ROM[0x10459] = 0xE7; + DrvV30ROM[0x1045A] = 0x04; + DrvV30ROM[0x1045B] = 0xE5; + DrvV30ROM[0x1045C] = 0x02; + DrvV30ROM[0x1045D] = 0x25; + DrvV30ROM[0x1045E] = 0x80; + DrvV30ROM[0x1045F] = 0x00; + DrvV30ROM[0x10460] = 0x74; + DrvV30ROM[0x10461] = 0xF9; + DrvV30ROM[0x10462] = 0x36; + DrvV30ROM[0x10463] = 0xA1; + DrvV30ROM[0x10464] = 0xB2; + DrvV30ROM[0x10465] = 0x23; + DrvV30ROM[0x10466] = 0xE7; + DrvV30ROM[0x10467] = 0x82; + DrvV30ROM[0x10468] = 0x36; + DrvV30ROM[0x10469] = 0xA1; + DrvV30ROM[0x1046A] = 0xB6; + DrvV30ROM[0x1046B] = 0x23; + DrvV30ROM[0x1046C] = 0xE7; + DrvV30ROM[0x104B4] = 0x32; + DrvV30ROM[0x104B5] = 0xE4; + DrvV30ROM[0x104B6] = 0x3C; + DrvV30ROM[0x104B7] = 0x7F; + DrvV30ROM[0x104B8] = 0x72; + DrvV30ROM[0x10577] = 0x47; + DrvV30ROM[0x10578] = 0xDC; + DrvV30ROM[0x10585] = 0x61; + DrvV30ROM[0x10586] = 0x07; + DrvV30ROM[0x10587] = 0x1F; + DrvV30ROM[0x10599] = 0x00; + DrvV30ROM[0x10793] = 0xE7; + DrvV30ROM[0x10794] = 0x02; + DrvV30ROM[0x1E1C0] = 0xBA; + DrvV30ROM[0x1EA29] = 0xE7; + DrvV30ROM[0x1EA2A] = 0x02; + + // invert graphics roms + for (INT32 i = 0; i < 0x80000; i++) { + DrvGfxROM1[i] ^= 0x0f; + DrvGfxROM2[i] ^= 0x0f; + } + + return 0; +} + +// Legend of Hero Tonma (bootleg, set 1) + +static struct BurnRomInfo lohtbRomDesc[] = { + { "lohtb03.b", 0x20000, 0x8b845a70, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "lohtb05.d", 0x20000, 0xe90f7623, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "lohtb02.a", 0x20000, 0x714778b5, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "lohtb04.c", 0x20000, 0x2f049b03, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "lohtb01.02", 0x10000, 0xe4bd8f03, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "lohtb14.11", 0x10000, 0xdf5ac5ee, 0x02 | BRF_GRA }, // 5 Sprites + { "lohtb18.15", 0x10000, 0xd7ecf849, 0x02 | BRF_GRA }, // 6 + { "lohtb15.12", 0x10000, 0x45220b01, 0x02 | BRF_GRA }, // 7 + { "lohtb19.16", 0x10000, 0x35d1a808, 0x02 | BRF_GRA }, // 8 + { "lohtb16.13", 0x10000, 0x25b85cfc, 0x02 | BRF_GRA }, // 9 + { "lohtb20.17", 0x10000, 0x464d8579, 0x02 | BRF_GRA }, // 10 + { "lohtb17.14", 0x10000, 0x763fa4ec, 0x02 | BRF_GRA }, // 11 + { "lohtb21.18", 0x10000, 0xa73568c7, 0x02 | BRF_GRA }, // 12 + + { "lohtb13.10", 0x10000, 0x359f17d4, 0x03 | BRF_GRA }, // 13 Foreground Tiles + { "lohtb11.08", 0x10000, 0x73391e8a, 0x03 | BRF_GRA }, // 14 + { "lohtb09.06", 0x10000, 0x7096d390, 0x03 | BRF_GRA }, // 15 + { "lohtb07.04", 0x10000, 0x71a27b81, 0x03 | BRF_GRA }, // 16 + + { "lohtb12.09", 0x10000, 0x4d5e9b53, 0x04 | BRF_GRA }, // 17 Background Tiles + { "lohtb10.07", 0x10000, 0x4f75a26a, 0x04 | BRF_GRA }, // 18 + { "lohtb08.05", 0x10000, 0x34854262, 0x04 | BRF_GRA }, // 19 + { "lohtb06.03", 0x10000, 0xf923183c, 0x04 | BRF_GRA }, // 20 +}; + +STD_ROM_PICK(lohtb) +STD_ROM_FN(lohtb) + +static INT32 lohtbInit() +{ + install_protection(loht); + + return DrvInit(common_080000_0a0000, sound_ram_map, lohtbRomLoadCallback, 0x80, Z80_FAKE_NMI, 0); +} + +struct BurnDriver BurnDrvLohtb = { + "lohtb", "loht", NULL, NULL, "1989", + "Legend of Hero Tonma (bootleg, set 1)\0", NULL, "bootleg", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, lohtbRomInfo, lohtbRomName, NULL, NULL, CommonInputInfo, LohtDIPInfo, + lohtbInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Legend of Hero Tonma (bootleg, set 2) + +static struct BurnRomInfo lohtb2RomDesc[] = { + { "loht-a2.bin", 0x10000, 0xccc90e54, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "loht-a10.bin", 0x10000, 0x3aa06730, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "loht-a3.bin", 0x10000, 0xff8a98de, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "loht-a11.bin", 0x10000, 0xeab1d7bc, 0x01 | BRF_PRG | BRF_ESS }, // 3 + { "loht-a5.bin", 0x10000, 0x79e007ec, 0x01 | BRF_PRG | BRF_ESS }, // 4 + { "loht-a13.bin", 0x10000, 0xb951346e, 0x01 | BRF_PRG | BRF_ESS }, // 5 + { "loht-a4.bin", 0x10000, 0x254ea4d5, 0x01 | BRF_PRG | BRF_ESS }, // 6 + { "loht-a12.bin", 0x10000, 0xcfb0390d, 0x01 | BRF_PRG | BRF_ESS }, // 7 + + { "loht-a16.bin", 0x10000, 0xdf5ac5ee, 0x02 | BRF_GRA }, // 8 Sprites + { "loht-a17.bin", 0x10000, 0xd7ecf849, 0x02 | BRF_GRA }, // 9 + { "loht-a8.bin", 0x10000, 0x45220b01, 0x02 | BRF_GRA }, // 10 + { "loht-a9.bin", 0x10000, 0x4af9bb3c, 0x02 | BRF_GRA }, // 11 + { "loht-a14.bin", 0x10000, 0x25b85cfc, 0x02 | BRF_GRA }, // 12 + { "loht-a15.bin", 0x10000, 0x464d8579, 0x02 | BRF_GRA }, // 13 + { "loht-a6.bin", 0x10000, 0x763fa4ec, 0x02 | BRF_GRA }, // 14 + { "loht-a7.bin", 0x10000, 0xa73568c7, 0x02 | BRF_GRA }, // 15 + + { "loht-a19.bin", 0x10000, 0x3ca3e771, 0x03 | BRF_GRA }, // 16 Foreground Tiles + { "loht-a20.bin", 0x10000, 0x7a05ee2f, 0x03 | BRF_GRA }, // 17 + { "loht-a18.bin", 0x10000, 0x79aa2335, 0x03 | BRF_GRA }, // 18 + { "loht-a21.bin", 0x10000, 0x789e8b24, 0x03 | BRF_GRA }, // 19 + + { "loht-a24.bin", 0x10000, 0x44626bf6, 0x04 | BRF_GRA }, // 20 Background Tiles + { "loht-a25.bin", 0x10000, 0x464952cf, 0x04 | BRF_GRA }, // 21 + { "loht-a23.bin", 0x10000, 0x3db9b2c7, 0x04 | BRF_GRA }, // 22 + { "loht-a22.bin", 0x10000, 0xf01fe899, 0x04 | BRF_GRA }, // 23 + + { "loht-a1.bin", 0x10000, 0x3ed51d1f, 0x05 | BRF_SND }, // 24 DAC Samples + + { "loht-a26.bin", 0x02000, 0xac901e17, 0x00 | BRF_OPT }, // 25 i8751 Code +}; + +STD_ROM_PICK(lohtb2) +STD_ROM_FN(lohtb2) + +struct BurnDriver BurnDrvLohtb2 = { + "lohtb2", "loht", NULL, NULL, "1989", + "Legend of Hero Tonma (bootleg, set 2)\0", NULL, "bootleg", "M72", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M72, GBF_SCRFIGHT, 0, + NULL, lohtb2RomInfo, lohtb2RomName, NULL, NULL, CommonInputInfo, LohtDIPInfo, + lohtInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Pound for Pound (World) + +static struct BurnRomInfo poundforRomDesc[] = { + { "ppa-h0-b.9e", 0x20000, 0x50d4a2d8, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ppa-l0-b.9d", 0x20000, 0xbd997942, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ppa-h1.9f", 0x20000, 0xf6c82f48, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ppa-l1.9c", 0x20000, 0x5b07b087, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ppa-sp.4j", 0x10000, 0x3f458a5b, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ppb-n0.bin", 0x40000, 0x951a41f8, 0x02 | BRF_GRA }, // 5 Sprites + { "ppb-n1.bin", 0x40000, 0xc609b7f2, 0x02 | BRF_GRA }, // 6 + { "ppb-n2.bin", 0x40000, 0x318c0b5f, 0x02 | BRF_GRA }, // 7 + { "ppb-n3.bin", 0x40000, 0x93dc9490, 0x02 | BRF_GRA }, // 8 + + { "ppa-g00.bin", 0x20000, 0x8a88a174, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ppa-g10.bin", 0x20000, 0xe48a66ac, 0x03 | BRF_GRA }, // 10 + { "ppa-g20.bin", 0x20000, 0x12b93e79, 0x03 | BRF_GRA }, // 11 + { "ppa-g30.bin", 0x20000, 0xfaa39aee, 0x03 | BRF_GRA }, // 12 + + { "ppa-v0.bin", 0x40000, 0x03321664, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(poundfor) +STD_ROM_FN(poundfor) + +static INT32 poundforInit() +{ + return DrvInit(rtype2_main_cpu_map, sound_rom_map, NULL, 0x80, Z80_FAKE_NMI, 4); +} + +struct BurnDriver BurnDrvPoundfor = { + "poundfor", NULL, NULL, NULL, "1990", + "Pound for Pound (World)\0", NULL, "Irem", "M85", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_SPORTSMISC, 0, + NULL, poundforRomInfo, poundforRomName, NULL, NULL, PoundforInputInfo, PoundforDIPInfo, + poundforInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// Pound for Pound (Japan) + +static struct BurnRomInfo poundforjRomDesc[] = { + { "ppa-h0-.9e", 0x20000, 0xf0165e3b, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ppa-l0-.9d", 0x20000, 0xf954f99f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ppa-h1.9f", 0x20000, 0xf6c82f48, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ppa-l1.9c", 0x20000, 0x5b07b087, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ppa-sp.4j", 0x10000, 0x3f458a5b, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ppb-n0.bin", 0x40000, 0x951a41f8, 0x02 | BRF_GRA }, // 5 Sprites + { "ppb-n1.bin", 0x40000, 0xc609b7f2, 0x02 | BRF_GRA }, // 6 + { "ppb-n2.bin", 0x40000, 0x318c0b5f, 0x02 | BRF_GRA }, // 7 + { "ppb-n3.bin", 0x40000, 0x93dc9490, 0x02 | BRF_GRA }, // 8 + + { "ppa-g00.bin", 0x20000, 0x8a88a174, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ppa-g10.bin", 0x20000, 0xe48a66ac, 0x03 | BRF_GRA }, // 10 + { "ppa-g20.bin", 0x20000, 0x12b93e79, 0x03 | BRF_GRA }, // 11 + { "ppa-g30.bin", 0x20000, 0xfaa39aee, 0x03 | BRF_GRA }, // 12 + + { "ppa-v0.bin", 0x40000, 0x03321664, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(poundforj) +STD_ROM_FN(poundforj) + +struct BurnDriver BurnDrvPoundforj = { + "poundforj", "poundfor", NULL, NULL, "1990", + "Pound for Pound (Japan)\0", NULL, "Irem", "M85", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_SPORTSMISC, 0, + NULL, poundforjRomInfo, poundforjRomName, NULL, NULL, PoundforInputInfo, PoundforDIPInfo, + poundforInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// Pound for Pound (US) + +static struct BurnRomInfo poundforuRomDesc[] = { + { "ppa-ho-a.9e", 0x20000, 0xff4c83a4, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "ppa-lo-a.9d", 0x20000, 0x3374ce8f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ppa-h1.9f", 0x20000, 0xf6c82f48, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ppa-l1.9c", 0x20000, 0x5b07b087, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ppa-sp.4j", 0x10000, 0x3f458a5b, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ppb-n0.bin", 0x40000, 0x951a41f8, 0x02 | BRF_GRA }, // 5 Sprites + { "ppb-n1.bin", 0x40000, 0xc609b7f2, 0x02 | BRF_GRA }, // 6 + { "ppb-n2.bin", 0x40000, 0x318c0b5f, 0x02 | BRF_GRA }, // 7 + { "ppb-n3.bin", 0x40000, 0x93dc9490, 0x02 | BRF_GRA }, // 8 + + { "ppa-g00.bin", 0x20000, 0x8a88a174, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "ppa-g10.bin", 0x20000, 0xe48a66ac, 0x03 | BRF_GRA }, // 10 + { "ppa-g20.bin", 0x20000, 0x12b93e79, 0x03 | BRF_GRA }, // 11 + { "ppa-g30.bin", 0x20000, 0xfaa39aee, 0x03 | BRF_GRA }, // 12 + + { "ppa-v0.bin", 0x40000, 0x03321664, 0x05 | BRF_SND }, // 13 DAC Samples +}; + +STD_ROM_PICK(poundforu) +STD_ROM_FN(poundforu) + +struct BurnDriver BurnDrvPoundforu = { + "poundforu", "poundfor", NULL, NULL, "1990", + "Pound for Pound (US)\0", NULL, "Irem America", "M85", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M72, GBF_SPORTSMISC, 0, + NULL, poundforuRomInfo, poundforuRomName, NULL, NULL, PoundforInputInfo, PoundforDIPInfo, + poundforInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 384, 3, 4 +}; + + +// Major Title (World) + +static struct BurnRomInfo majtitleRomDesc[] = { + { "mt_h0-a.bin", 0x20000, 0x36aadb67, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "mt_l0-a.bin", 0x20000, 0x2e1b6242, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "mt_h1-a.bin", 0x20000, 0xe1402a22, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "mt_l1-a.bin", 0x20000, 0x0efa409a, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "mt_sp.bin", 0x10000, 0xe44260a9, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "mt_n0.bin", 0x40000, 0x5618cddc, 0x02 | BRF_GRA }, // 5 Sprites + { "mt_n1.bin", 0x40000, 0x483b873b, 0x02 | BRF_GRA }, // 6 + { "mt_n2.bin", 0x40000, 0x4f5d665b, 0x02 | BRF_GRA }, // 7 + { "mt_n3.bin", 0x40000, 0x83571549, 0x02 | BRF_GRA }, // 8 + + { "mt_c0.bin", 0x20000, 0x780e7a02, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "mt_c1.bin", 0x20000, 0x45ad1381, 0x03 | BRF_GRA }, // 10 + { "mt_c2.bin", 0x20000, 0x5df5856d, 0x03 | BRF_GRA }, // 11 + { "mt_c3.bin", 0x20000, 0xf5316cc8, 0x03 | BRF_GRA }, // 12 + + { "mt_f0.bin", 0x20000, 0x2d5e05d5, 0x0e | BRF_GRA }, // 13 Sprites + { "mt_f1.bin", 0x20000, 0xc68cd65f, 0x0e | BRF_GRA }, // 14 + { "mt_f2.bin", 0x20000, 0xa71feb2d, 0x0e | BRF_GRA }, // 15 + { "mt_f3.bin", 0x20000, 0x179f7562, 0x0e | BRF_GRA }, // 16 + + { "mt_vo.bin", 0x20000, 0xeb24bb2c, 0x05 | BRF_SND }, // 17 DAC Samples +}; + +STD_ROM_PICK(majtitle) +STD_ROM_FN(majtitle) + +static INT32 majtitleInit() +{ + return DrvInit(majtitle_main_cpu_map, sound_rom_map, NULL, 0x80, Z80_REAL_NMI, 3); +} + +struct BurnDriver BurnDrvMajtitle = { + "majtitle", NULL, NULL, NULL, "1990", + "Major Title (World)\0", NULL, "Irem", "M84", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M72, GBF_SPORTSMISC, 0, + NULL, majtitleRomInfo, majtitleRomName, NULL, NULL, CommonInputInfo, Rtype2DIPInfo, + majtitleInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; + + +// Major Title (Japan) + +static struct BurnRomInfo majtitlejRomDesc[] = { + { "mt_h0.bin", 0x20000, 0xb9682c70, 0x01 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "mt_l0.bin", 0x20000, 0x702c9fd6, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "mt_h1.bin", 0x20000, 0xd9e97c30, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "mt_l1.bin", 0x20000, 0x8dbd91b5, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "mt_sp.bin", 0x10000, 0xe44260a9, 0x06 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "mt_n0.bin", 0x40000, 0x5618cddc, 0x02 | BRF_GRA }, // 5 Sprites + { "mt_n1.bin", 0x40000, 0x483b873b, 0x02 | BRF_GRA }, // 6 + { "mt_n2.bin", 0x40000, 0x4f5d665b, 0x02 | BRF_GRA }, // 7 + { "mt_n3.bin", 0x40000, 0x83571549, 0x02 | BRF_GRA }, // 8 + + { "mt_c0.bin", 0x20000, 0x780e7a02, 0x03 | BRF_GRA }, // 9 Foreground & Background Tiles + { "mt_c1.bin", 0x20000, 0x45ad1381, 0x03 | BRF_GRA }, // 10 + { "mt_c2.bin", 0x20000, 0x5df5856d, 0x03 | BRF_GRA }, // 11 + { "mt_c3.bin", 0x20000, 0xf5316cc8, 0x03 | BRF_GRA }, // 12 + + { "mt_f0.bin", 0x20000, 0x2d5e05d5, 0x0e | BRF_GRA }, // 13 Sprites + { "mt_f1.bin", 0x20000, 0xc68cd65f, 0x0e | BRF_GRA }, // 14 + { "mt_f2.bin", 0x20000, 0xa71feb2d, 0x0e | BRF_GRA }, // 15 + { "mt_f3.bin", 0x20000, 0x179f7562, 0x0e | BRF_GRA }, // 16 + + { "mt_vo.bin", 0x20000, 0xeb24bb2c, 0x05 | BRF_SND }, // 17 DAC Samples +}; + +STD_ROM_PICK(majtitlej) +STD_ROM_FN(majtitlej) + +struct BurnDriver BurnDrvMajtitlej = { + "majtitlej", "majtitle", NULL, NULL, "1990", + "Major Title (Japan)\0", NULL, "Irem", "M84", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M72, GBF_SPORTSMISC, 0, + NULL, majtitlejRomInfo, majtitlejRomName, NULL, NULL, CommonInputInfo, Rtype2DIPInfo, + majtitleInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 256, 4, 3 +}; diff --git a/src/burn/drivers/irem/d_m90.cpp b/src/burn/drivers/irem/d_m90.cpp new file mode 100644 index 00000000..e1b079eb --- /dev/null +++ b/src/burn/drivers/irem/d_m90.cpp @@ -0,0 +1,1828 @@ +// FB Alpha Irem M90 driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "vez.h" +#include "irem_cpu.h" +#include "dac.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvV30ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvV30RAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; + +static UINT8 *m90_video_control; + +static UINT8 *RamPrioBitmap; +static INT16 *dacbuffer; + +static UINT8 *soundlatch; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 irqvector; +static INT32 sample_address; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[5]; +static UINT8 DrvReset; + +static INT32 vblank; +static INT32 code_mask[2]; +static INT32 video_offsets[2] = { 0, 0 }; + +enum { VECTOR_INIT, YM2151_ASSERT, YM2151_CLEAR, Z80_ASSERT, Z80_CLEAR }; + +static struct BurnInputInfo p4commonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy4 + 5, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy4 + 4, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 3, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 2, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 0, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 7, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 6, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy5 + 5, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy5 + 4, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy5 + 3, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy5 + 2, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy5 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy5 + 0, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy5 + 7, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy5 + 6, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(p4common) + +static struct BurnInputInfo p2commonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(p2common) + +static struct BurnInputInfo Quizf1InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Quizf1) + +static struct BurnInputInfo Matchit2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Matchit2) + +static struct BurnDIPInfo DynablstDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x02, "2" }, + {0x22, 0x01, 0x03, 0x03, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + {0x22, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Medium" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + {0x22, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Game Title" }, + {0x22, 0x01, 0x10, 0x10, "Dynablaster" }, + {0x22, 0x01, 0x10, 0x00, "Bomber Man" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Cabinet" }, + {0x23, 0x01, 0x06, 0x04, "2 Player Upright" }, + {0x23, 0x01, 0x06, 0x06, "4 Player Upright A" }, + {0x23, 0x01, 0x06, 0x02, "4 Player Upright B" }, + {0x23, 0x01, 0x06, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Dynablst) + +static struct BurnDIPInfo AtompunkDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x02, "2" }, + {0x22, 0x01, 0x03, 0x03, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + {0x22, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Medium" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + {0x22, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Unknown" }, + {0x22, 0x01, 0x10, 0x10, "Off" }, + {0x22, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Cabinet" }, + {0x23, 0x01, 0x06, 0x04, "2 Player Upright" }, + {0x23, 0x01, 0x06, 0x06, "4 Player Upright A" }, + {0x23, 0x01, 0x06, 0x02, "4 Player Upright B" }, + {0x23, 0x01, 0x06, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Atompunk) + +static struct BurnDIPInfo BombrmanDIPList[]= +{ + {0x12, 0xff, 0xff, 0xaf, NULL }, + {0x13, 0xff, 0xff, 0xf9, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Bombrman) + +static struct BurnDIPInfo HasamuDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Unknown" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Hasamu) + +static struct BurnDIPInfo RiskchalDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Riskchal) + +static struct BurnDIPInfo BbmanwDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x02, "2" }, + {0x22, 0x01, 0x03, 0x03, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + {0x22, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Medium" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + {0x22, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Game Title" }, + {0x22, 0x01, 0x10, 0x10, "Bomber Man World" }, + {0x22, 0x01, 0x10, 0x00, "New Dyna Blaster Global Quest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Cabinet" }, + {0x23, 0x01, 0x06, 0x04, "2 Player" }, + {0x23, 0x01, 0x06, 0x06, "4 Player Seprate Coins" }, + {0x23, 0x01, 0x06, 0x02, "4 Player Shared Coins" }, + {0x23, 0x01, 0x06, 0x00, "4 Player 1&2 3&4 Share Coins" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Bbmanw) + +static struct BurnDIPInfo BbmanwjDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x02, "2" }, + {0x22, 0x01, 0x03, 0x03, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + {0x22, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Medium" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + {0x22, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Cabinet" }, + {0x23, 0x01, 0x06, 0x04, "2 Player" }, + {0x23, 0x01, 0x06, 0x06, "4 Player Seprate Coins" }, + {0x23, 0x01, 0x06, 0x02, "4 Player Shared Coins" }, + {0x23, 0x01, 0x06, 0x00, "4 Player 1&2 3&4 Share Coins" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Bbmanwj) + +static struct BurnDIPInfo Quizf1DIPList[]= +{ + {0x16, 0xff, 0xff, 0x9f, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Input Device" }, + {0x16, 0x01, 0x20, 0x20, "Joystick" }, + {0x16, 0x01, 0x20, 0x00, "Buttons" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x17, 0x01, 0x08, 0x08, "1" }, + {0x17, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x17, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x17, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x17, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x17, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x17, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x17, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x17, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x17, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x17, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x17, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x17, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x17, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Quizf1) + +static struct BurnDIPInfo Matchit2DIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Girls Mode" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "China Tiles" }, + {0x14, 0x01, 0x02, 0x02, "Mahjong" }, + {0x14, 0x01, 0x02, 0x00, "Alpha-Numeric" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x00, "Very Hard" }, + {0x14, 0x01, 0x0c, 0x04, "Hard" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + + {0 , 0xfe, 0 , 4, "Timer Speed" }, + {0x14, 0x01, 0x30, 0x00, "Very Hard" }, + {0x14, 0x01, 0x30, 0x10, "Hard" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + + {0 , 0xfe, 0 , 2, "Title Screen" }, + {0x14, 0x01, 0x40, 0x40, "Match It II" }, + {0x14, 0x01, 0x40, 0x00, "Shisensho II" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 3, "Language" }, + {0x15, 0x01, 0x06, 0x06, "English" }, + {0x15, 0x01, 0x06, 0x04, "German" }, + {0x15, 0x01, 0x06, 0x02, "Korean" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x15, 0x01, 0x08, 0x08, "1" }, + {0x15, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x15, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Matchit2) + +static struct BurnDIPInfo Shisen2DIPList[]= +{ + {0x14, 0xff, 0xff, 0xbf, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Girls Mode" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x00, "Very Hard" }, + {0x14, 0x01, 0x0c, 0x04, "Hard" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + + {0 , 0xfe, 0 , 4, "Timer Speed" }, + {0x14, 0x01, 0x30, 0x00, "Very Hard" }, + {0x14, 0x01, 0x30, 0x10, "Hard" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x15, 0x01, 0x08, 0x08, "1" }, + {0x15, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x15, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Shisen2) + +static void setvector_callback(INT32 param) +{ + switch (param) + { + case VECTOR_INIT: irqvector = 0xff; break; + case YM2151_ASSERT: irqvector &= 0xef; break; + case YM2151_CLEAR: irqvector |= 0x10; break; + case Z80_ASSERT: irqvector &= 0xdf; break; + case Z80_CLEAR: irqvector |= 0x20; break; + } + + ZetSetVector(irqvector); + ZetSetIRQLine(0, (irqvector == 0xff) ? ZET_IRQSTATUS_NONE : ZET_IRQSTATUS_ACK); +} + +static inline void update_palette_entry(INT32 entry) +{ + UINT16 d = *((UINT16*)(DrvPalRAM + entry)); + UINT8 r = (d >> 0) & 0x1f; + UINT8 g = (d >> 5) & 0x1f; + UINT8 b = (d >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[entry / 2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall m90_main_write(UINT32 address, UINT8 data) +{ + if ((address & 0xffc00) == 0xe0000) { + DrvPalRAM[address & 0x3ff] = data; + update_palette_entry(address & 0x3fe); + return; + } +} + +UINT8 __fastcall m90_main_read(UINT32 /*address*/) +{ + return 0; +} + +void __fastcall m90_main_write_port(UINT32 port, UINT8 data) +{ +bprintf (0, _T("Writing %2.2x to port %2.2x wp\n"), data, port); + + if ((port & ~0x0f) == 0x80) { + m90_video_control[port & 0x0f] = data; + return; + } + + switch (port) + { + case 0x00: + // case 0x01: + *soundlatch = data; + setvector_callback(Z80_ASSERT); + return; + + case 0x02: + // case 0x03: + // coin counter + return; + + case 0x04: + //case 0x05: + { + INT32 bankaddress = 0x100000 + 0x10000 * (data & 0x0f); + VezMapArea(0x80000, 0x8ffff, 0, DrvV30ROM + bankaddress); + VezMapArea(0x80000, 0x8ffff, 2, DrvV30ROM + bankaddress); + } + return; + + case 0x90: + // case 0x91: // nop dynablsb + return; + + //default: + // bprintf (0, _T("Writing %2.2x to port %2.2x wp\n"), data, port); + // break; + } +} + +UINT8 __fastcall m90_main_read_port(UINT32 port) +{ +bprintf (0, _T("Reading port: %2.2x\n"), port); + + switch (port) + { + case 0x00: return DrvInputs[0]; + case 0x01: return DrvInputs[1]; + case 0x02: return (DrvInputs[2] & 0x7f) | vblank; // system + // case 0x03: return 0xff; // ? + case 0x04: return DrvDips[0]; + case 0x05: return DrvDips[1]; + case 0x06: return DrvInputs[3]; + case 0x07: return DrvInputs[4]; + + //default: + // bprintf (0, _T("Reading port: %2.2x\n"), port); + // break; + } + + return 0; +} + +void __fastcall m90_sound_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x40: // bbmanw + BurnYM2151SelectRegister(data); + return; + + case 0x01: + case 0x41: // bbmanw + BurnYM2151WriteRegister(data); + return; + + case 0x80: + sample_address >>= 5; + sample_address = (sample_address & 0x00ff) | (data << 8); + sample_address <<= 5; + return; + + case 0x81: + sample_address >>= 5; + sample_address = (sample_address & 0xff00) | (data << 0); + sample_address <<= 5; + return; + + case 0x82: + DACSignedWrite(0, data); + sample_address = (sample_address + 1) & 0x3ffff; + return; + + case 0x42: // bbmanw + case 0x83: + setvector_callback(Z80_CLEAR); + return; + } +} + +UINT8 __fastcall m90_sound_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x40: // bbmanw + case 0x41: + return BurnYM2151ReadStatus(); + + case 0x42: // bbmanw + case 0x80: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0x84: + return DrvSndROM[sample_address & 0x3fff]; + } + + return 0; +} + +static void m72YM2151IRQHandler(INT32 nStatus) +{ + setvector_callback(nStatus ? YM2151_ASSERT : YM2151_CLEAR); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + VezOpen(0); + VezReset(); + VezClose(); + + ZetOpen(0); + ZetReset(); + setvector_callback(VECTOR_INIT); + ZetClose(); + + BurnYM2151Reset(); + DACReset(); + + sample_address = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvV30ROM = Next; Next += 0x200000; + DrvZ80ROM = Next; Next += 0x010000; + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvSndROM = Next; Next += 0x180000; + + RamPrioBitmap = Next; Next += nScreenWidth * nScreenHeight; + dacbuffer = (INT16*)Next; Next += 128 * 8 * 2 * sizeof(INT16); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x010000; + DrvV30RAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvZ80RAM = Next; Next += 0x001000; + + soundlatch = Next; Next += 0x000001; + + m90_video_control = Next; Next += 0x000010; + + RamEnd = Next; + + DrvPalette = (UINT32 *) Next; Next += 0x0200 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvLoadRoms(INT32 codesize, INT32 samples, INT32 bank) +{ + if (BurnLoadRom(DrvV30ROM + 1, 0, 2)) return 1; + if (BurnLoadRom(DrvV30ROM + 0, 1, 2)) return 1; + + if (codesize == 0x40000) { + memcpy (DrvV30ROM + 0x7fff0, DrvV30ROM + 0x3fff0, 0x10); + } + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 6, 1)) return 1; + + if (samples) { + if (BurnLoadRom(DrvSndROM, 7, 1)) return 1; + + if (samples < 0x40000) { + memcpy (DrvSndROM + 0x20000, DrvSndROM + 0x00000, 0x20000); + } + } + + if (bank) { + if (BurnLoadRom(DrvV30ROM + 0x100001, 8, 2)) return 1; + if (BurnLoadRom(DrvV30ROM + 0x100000, 9, 2)) return 1; + } + + return 0; +} + +static void map_main_cpu(UINT8 *decrypt_table, INT32 codesize, INT32 spriteram) +{ + VezInit(0, V35_TYPE, 32000000/2); + + VezOpen(0); + if (decrypt_table != NULL) { + VezSetDecode(decrypt_table); + } + + VezMapArea(0x00000, (codesize-1), 0, DrvV30ROM + 0x000000); + VezMapArea(0x00000, (codesize-1), 2, DrvV30ROM + 0x000000); + VezMapArea(0x80000, 0x8ffff, 0, DrvV30ROM + 0x100000); + VezMapArea(0x80000, 0x8ffff, 2, DrvV30ROM + 0x100000); + VezMapArea(0xa0000, 0xa3fff, 0, DrvV30RAM); + VezMapArea(0xa0000, 0xa3fff, 1, DrvV30RAM); + VezMapArea(0xa0000, 0xa3fff, 2, DrvV30RAM); + VezMapArea(0xd0000, 0xdffff, 0, DrvVidRAM); + VezMapArea(0xd0000, 0xdffff, 1, DrvVidRAM); + VezMapArea(0xd0000, 0xdffff, 2, DrvVidRAM); + VezMapArea(0xe0000, 0xe07ff, 0, DrvPalRAM); +// VezMapArea(0xe0000, 0xe07ff, 1, DrvPalRAM); + VezMapArea(0xe0000, 0xe07ff, 2, DrvPalRAM); + VezMapArea(0xff800, 0xfffff, 0, DrvV30ROM + 0x07f800); + VezMapArea(0xff800, 0xfffff, 2, DrvV30ROM + 0x07f800); + + if (spriteram) { + VezMapArea(0x00000 + spriteram, 0x00fff + spriteram, 0, DrvSprRAM); // 00e - fff // ?? + VezMapArea(0x00000 + spriteram, 0x00fff + spriteram, 1, DrvSprRAM); + VezMapArea(0x00000 + spriteram, 0x00fff + spriteram, 2, DrvSprRAM); + } + + VezSetReadHandler(m90_main_read); + VezSetWriteHandler(m90_main_write); + VezSetReadPort(m90_main_read_port); + VezSetWritePort(m90_main_write_port); + VezClose(); +} + +static void DrvGfxDecode() +{ + INT32 Plane[4] = { 0x180000 * 8, 0x100000 * 8, 0x080000 * 8, 0x000000 * 8 }; + INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 16*8+0, 16*8+1, 16*8+2, 16*8+3, 16*8+4, 16*8+5, 16*8+6, 16*8+7 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }; + + UINT8 *tmp = (UINT8*)malloc(0x200000); + if (tmp == NULL) { + return; + } + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x10000, 4, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + GfxDecode(0x04000, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + if (tmp) { + free (tmp); + tmp = NULL; + } +} + +static INT32 DrvInit(INT32 codesize, INT32 gfxlen, INT32 samples, INT32 bank, INT32 spriteram, const UINT8 *decrypt_table) +{ + GenericTilesInit(); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (DrvLoadRoms(codesize, samples, bank)) return 1; + + DrvGfxDecode(); + + map_main_cpu((UINT8*)decrypt_table, codesize, spriteram); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(m90_sound_write_port); + ZetSetInHandler(m90_sound_read_port); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 15.0); + YM2151SetIrqHandler(0, &m72YM2151IRQHandler); + + DACInit(0, 0, 0); + DACSetVolShift(0, 4); // 1/16th of max + + code_mask[0] = ((gfxlen * 2) - 1) / (8 * 8); + code_mask[1] = ((gfxlen * 2) - 1) / (16 * 16); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2151Exit(); + DACExit(); + + ZetExit(); + VezExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + video_offsets[0] = video_offsets[1] = 0; + + return 0; +} + +static void RenderTilePrio(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height, UINT8 *pri, INT32 prio) +{ + if (sx <= (0-width) || sx >= nScreenWidth || sy <= (0-height) || sy >= nScreenHeight) return; + + INT32 flip = 0; + if (flipy) flip |= (height - 1) * width; + if (flipx) flip |= width - 1; + + gfx += code * width * height; + + for (INT32 y = 0; y < height; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 x = 0; x < width; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((y * width) + x) ^ flip]; + + if (pxl == 0) continue; + + if ((prio & (1 << pri[sy * nScreenWidth + sx])) == 0) { + dest[sy * nScreenWidth + sx] = pxl | color; + pri[sy * nScreenWidth + sx] = 7; + } + } + + sx -= width; + } +} + +static void draw_sprites() +{ + INT32 pri_ctrl = m90_video_control[14] & 0x03; + UINT16 *sram = (UINT16*)(DrvVidRAM + 0xee00); + + for (INT32 offs = 0x1f2/2; offs >= 0; offs -= 3) + { + INT32 sy = sram[offs + 0]; + INT32 code = sram[offs + 1]; + INT32 sx = sram[offs + 2]; + + INT32 flipy = sy & 0x8000; + INT32 flipx = sx & 0x0200; + INT32 multi = 1 << ((sy & 0x6000) >> 13); + INT32 color = (sy >> 9) & 0x0f; + + sx = ((sx - video_offsets[0]) & 0x1ff) - 16; + sy = (512 - ((sy + video_offsets[1]) & 0x1ff)) - (16 * multi); + + INT32 prio = 0x82; + if (pri_ctrl & 0x01) { + if ((color & 0x08) == 0x08) prio = 0x80; + } else if (pri_ctrl & 0x02) { + if ((color & 0x0c) == 0x0c) prio = 0x80; + } + + for (INT32 i = 0; i < multi; i++) { + RenderTilePrio(pTransDraw, DrvGfxROM1, (code + (flipy ? multi-1 - i : i)) & code_mask[1], (color << 4)|0x100, sx, sy+i*16, flipx, flipy, 16, 16, RamPrioBitmap, prio); + } + } +} + +static void draw_layer(INT32 layer) +{ + INT32 control = m90_video_control[10 + (layer * 2)]; + + if (control & 0x10) return; // disable layer + + INT32 enable_rowscroll = control & 0x20; + INT32 enable_colscroll = control & 0x40; + + INT32 wide = (control & 0x04) ? 128 : 64; + + INT32 trans = layer ? 0xff : 0; + + INT32 pmask = (wide == 128) ? 2 : 3; + UINT16 *vram = (UINT16*)(DrvVidRAM + (control & pmask) * 0x4000); + + UINT16 scrollx = ((m90_video_control[(layer*4)+2] << 0) | (m90_video_control[(layer*4)+3] << 8)) + video_offsets[0]; + UINT16 scrolly = ((m90_video_control[(layer*4)+0] << 0) | (m90_video_control[(layer*4)+1] << 8)) + video_offsets[1]; + + scrollx += layer ? -2 : 2; + scrollx += ((wide & 0x80) * 2); + + UINT16 *xscroll = (UINT16*)(DrvVidRAM + 0xf000 + (layer * 0x400)); + UINT16 *yscroll = (UINT16*)(DrvVidRAM + 0xf800 + (layer * 0x400)); + + for (INT32 sy = 0; sy < nScreenHeight; sy++) + { + INT32 scrollx_1 = scrollx; + INT32 scrolly_1 = 0; + UINT16 *dest = pTransDraw + (sy * nScreenWidth); + UINT8 *pri = RamPrioBitmap + (sy * nScreenWidth); + + if (enable_rowscroll) scrollx_1 += xscroll[sy]; + + if (enable_colscroll) { + scrolly_1 += (scrolly + sy + yscroll[sy] + 128) & 0x1ff; + } else { + scrolly_1 += (scrolly + sy) & 0x1ff; + } + + INT32 romoff_1 = (scrolly_1 & 0x07) << 3; + + for (INT32 sx = 0; sx < nScreenWidth + 8; sx+=8) + { + INT32 scrollx_2 = (scrollx_1 + sx) & ((wide * 8) - 1); + + INT32 offs = ((scrolly_1 / 8) * wide) | (scrollx_2 / 8); + + INT32 code = vram[offs * 2 + 0] & code_mask[0]; + INT32 color = vram[offs * 2 + 1]; + + INT32 flipy = color & 0x80; + INT32 flipx = color & 0x40; + INT32 group =(color & 0x30) ? 0 : 1; + color &= 0x0f; + + { + color <<= 4; + INT32 x_xor = 0; + INT32 romoff = romoff_1; + if (flipy) romoff ^= 0x38; + if (flipx) x_xor = 7; + + UINT8 *rom = DrvGfxROM0 + (code * 0x40) + romoff; + + INT32 xx = sx - (scrollx_2&0x7); + + for (INT32 x = 0; x < 8; x++, xx++) { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = rom[x ^ x_xor]; + if (pxl == trans) continue; + + dest[xx] = pxl | color; + pri[xx] = 1 << group; + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i+=2) { + update_palette_entry(i); + } + DrvRecalc = 0; + } + + if ((m90_video_control[14] & 0x04) == 0) { + if (m90_video_control[12] & 0x10) { + memset (RamPrioBitmap, 0, nScreenWidth * nScreenHeight); + BurnTransferClear(); + } else { + if (nBurnLayer & 1) draw_layer(1); + } + + if (nBurnLayer & 2) draw_layer(0); + + if (nBurnLayer & 4) draw_sprites(); + } else { + BurnTransferClear(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void compile_inputs() +{ + memset (DrvInputs, 0xff, 5); + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + compile_inputs(); + + INT32 nInterleave = 128; // nmi pulses for sound cpu + INT32 nCyclesTotal[2]; + INT32 nCyclesDone[2]; + + // overclocking... + nCyclesTotal[0] = (INT32)((INT64)(8000000 / 60) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesTotal[1] = (INT32)((INT64)(3579545 / 60) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesDone[0] = nCyclesDone[1] = 0; + + VezOpen(0); + ZetOpen(0); + + vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += VezRun(nCyclesTotal[0] / nInterleave); + + if (i == (nInterleave - 1)) + { + VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP0, 0xff, VEZ_IRQSTATUS_ACK); + VezRun(0); + VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP0, 0xff, VEZ_IRQSTATUS_NONE); + } + + nCyclesDone[1] += ZetRun((nCyclesTotal[1] / nInterleave) / 4); + if (nBurnSoundLen) DACUpdate(dacbuffer + i * 8, 1); + nCyclesDone[1] += ZetRun((nCyclesTotal[1] / nInterleave) / 4); + if (nBurnSoundLen) DACUpdate(dacbuffer + i * 8, 1); + nCyclesDone[1] += ZetRun((nCyclesTotal[1] / nInterleave) / 4); + if (nBurnSoundLen) DACUpdate(dacbuffer + i * 8, 1); + nCyclesDone[1] += ZetRun((nCyclesTotal[1] / nInterleave) / 4); + if (nBurnSoundLen) DACUpdate(dacbuffer + i * 8, 1); + ZetNmi(); + + if (i == 124) vblank = 0x80; + } + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + + float step = (nInterleave * 4.000000) / nBurnSoundLen; + + for (INT32 i = 0; i < nBurnSoundLen*2; i++) { + pBurnSoundOut[i] += dacbuffer[(INT32)((float)(i * step))]; + } + } + + VezClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + + +// Hasamu (Japan) + +static struct BurnRomInfo hasamuRomDesc[] = { + { "hasc-p1.bin", 0x20000, 0x53df9834, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "hasc-p0.bin", 0x20000, 0xdff0ba6e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "hasc-sp.bin", 0x10000, 0x259b1687, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "hasc-c0.bin", 0x20000, 0xdd5a2174, 3 | BRF_GRA }, // 3 Tiles and sprites + { "hasc-c1.bin", 0x20000, 0x76b8217c, 3 | BRF_GRA }, // 4 + { "hasc-c2.bin", 0x20000, 0xd90f9a68, 3 | BRF_GRA }, // 5 + { "hasc-c3.bin", 0x20000, 0x6cfe0d39, 3 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(hasamu) +STD_ROM_FN(hasamu) + +static INT32 hasamuInit() +{ + video_offsets[0] = 48; + video_offsets[1] = 136; + return DrvInit(0x40000, 0x80000, 0x00000, 0, 0, gunforce_decryption_table); +} + +struct BurnDriver BurnDrvHasamu = { + "hasamu", NULL, NULL, NULL, "1991", + "Hasamu (Japan)\0", NULL, "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, hasamuRomInfo, hasamuRomName, NULL, NULL, p2commonInputInfo, HasamuDIPInfo, + hasamuInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Dynablaster / Bomber Man + +static struct BurnRomInfo dynablstRomDesc[] = { + { "bbm-cp1e.62", 0x20000, 0x27667681, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm-cp0e.65", 0x20000, 0x95db7a67, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm-sp.23", 0x10000, 0x251090cd, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm-c0.66", 0x40000, 0x695d2019, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm-c1.67", 0x40000, 0x4c7c8bbc, 3 | BRF_GRA }, // 4 + { "bbm-c2.68", 0x40000, 0x0700d406, 3 | BRF_GRA }, // 5 + { "bbm-c3.69", 0x40000, 0x3c3613af, 3 | BRF_GRA }, // 6 + + { "bbm-v0.20", 0x20000, 0x0fa803fe, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(dynablst) +STD_ROM_FN(dynablst) + +static INT32 dynablstInit() +{ + video_offsets[0] = 80; + video_offsets[1] = 136; + return DrvInit(0x40000, 0x100000, 0x20000, 0, 0, bomberman_decryption_table); +} + +struct BurnDriver BurnDrvDynablst = { + "dynablst", NULL, NULL, NULL, "1991", + "Dynablaster / Bomber Man\0", NULL, "Irem (licensed from Hudson Soft)", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, dynablstRomInfo, dynablstRomName, NULL, NULL, p4commonInputInfo, DynablstDIPInfo, + dynablstInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Bomber Man (Japan) + +static struct BurnRomInfo bombrmanRomDesc[] = { + { "bbm-p1.62", 0x20000, 0x982bd166, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm-p0.65", 0x20000, 0x0a20afcc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm-sp.23", 0x10000, 0x251090cd, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm-c0.66", 0x40000, 0x695d2019, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm-c1.67", 0x40000, 0x4c7c8bbc, 3 | BRF_GRA }, // 4 + { "bbm-c2.68", 0x40000, 0x0700d406, 3 | BRF_GRA }, // 5 + { "bbm-c3.69", 0x40000, 0x3c3613af, 3 | BRF_GRA }, // 6 + + { "bbm-v0.20", 0x20000, 0x0fa803fe, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(bombrman) +STD_ROM_FN(bombrman) + +struct BurnDriver BurnDrvBombrman = { + "bombrman", "dynablst", NULL, NULL, "1991", + "Bomber Man (Japan)\0", NULL, "Irem (licensed from Hudson Soft)", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, bombrmanRomInfo, bombrmanRomName, NULL, NULL, p2commonInputInfo, BombrmanDIPInfo, + dynablstInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Atomic Punk (US) + +static struct BurnRomInfo atompunkRomDesc[] = { + { "bbm-cp0d.65", 0x20000, 0x860c0479, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm-cp1d.62", 0x20000, 0xbe57bf74, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm-sp.23", 0x10000, 0x251090cd, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm-c0.66", 0x40000, 0x695d2019, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm-c1.67", 0x40000, 0x4c7c8bbc, 3 | BRF_GRA }, // 4 + { "bbm-c2.68", 0x40000, 0x0700d406, 3 | BRF_GRA }, // 5 + { "bbm-c3.69", 0x40000, 0x3c3613af, 3 | BRF_GRA }, // 6 + + { "bbm-v0.20", 0x20000, 0x0fa803fe, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(atompunk) +STD_ROM_FN(atompunk) + +struct BurnDriver BurnDrvAtompunk = { + "atompunk", "dynablst", NULL, NULL, "1991", + "Atomic Punk (US)\0", NULL, "Irem America (licensed from Hudson Soft)", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, atompunkRomInfo, atompunkRomName, NULL, NULL, p4commonInputInfo, AtompunkDIPInfo, + dynablstInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Bomber Man World / New Dyna Blaster - Global Quest + +static struct BurnRomInfo bbmanwRomDesc[] = { + { "bbm2-h0-b.77", 0x40000, 0x567d3709, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm2-l0-b.79", 0x40000, 0xe762c22b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm2-sp.33", 0x10000, 0x6bc1689e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm2-c0.81", 0x40000, 0xe7ce058a, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm2-c1.82", 0x40000, 0x636a78a9, 3 | BRF_GRA }, // 4 + { "bbm2-c2.83", 0x40000, 0x9ac2142f, 3 | BRF_GRA }, // 5 + { "bbm2-c3.84", 0x40000, 0x47af1750, 3 | BRF_GRA }, // 6 + + { "bbm2-v0.30", 0x20000, 0x4ad889ed, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(bbmanw) +STD_ROM_FN(bbmanw) + +static INT32 bbmanwInit() +{ + video_offsets[0] = 80; + video_offsets[1] = 136; + return DrvInit(0x80000, 0x100000, 0x20000, 0, 0, dynablaster_decryption_table); +} + +struct BurnDriver BurnDrvBbmanw = { + "bbmanw", NULL, NULL, NULL, "1992", + "Bomber Man World / New Dyna Blaster - Global Quest\0", NULL, "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, bbmanwRomInfo, bbmanwRomName, NULL, NULL, p4commonInputInfo, BbmanwDIPInfo, + bbmanwInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Bomber Man World (Japan) + +static struct BurnRomInfo bbmanwjRomDesc[] = { + { "bbm2-h0.77", 0x40000, 0xe1407b91, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm2-l0.79", 0x40000, 0x20873b49, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm2-sp-b.bin", 0x10000, 0xb8d8108c, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm2-c0.81", 0x40000, 0xe7ce058a, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm2-c1.82", 0x40000, 0x636a78a9, 3 | BRF_GRA }, // 4 + { "bbm2-c2.83", 0x40000, 0x9ac2142f, 3 | BRF_GRA }, // 5 + { "bbm2-c3.84", 0x40000, 0x47af1750, 3 | BRF_GRA }, // 6 + + { "bbm2-v0-b.30", 0x20000, 0x0ae655ff, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(bbmanwj) +STD_ROM_FN(bbmanwj) + +struct BurnDriver BurnDrvBbmanwj = { + "bbmanwj", "bbmanw", NULL, NULL, "1992", + "Bomber Man World (Japan)\0", NULL, "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, bbmanwjRomInfo, bbmanwjRomName, NULL, NULL, p4commonInputInfo, BbmanwjDIPInfo, + bbmanwInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// New Atomic Punk - Global Quest (US) + +static struct BurnRomInfo newapunkRomDesc[] = { + { "bbm2-h0-a.77", 0x40000, 0x7d858682, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "bbm2-l0-a.79", 0x40000, 0xc7568031, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bbm2-sp.33", 0x10000, 0x6bc1689e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bbm2-c0.81", 0x40000, 0xe7ce058a, 3 | BRF_GRA }, // 3 Tiles and sprites + { "bbm2-c1.82", 0x40000, 0x636a78a9, 3 | BRF_GRA }, // 4 + { "bbm2-c2.83", 0x40000, 0x9ac2142f, 3 | BRF_GRA }, // 5 + { "bbm2-c3.84", 0x40000, 0x47af1750, 3 | BRF_GRA }, // 6 + + { "bbm2-v0.30", 0x20000, 0x4ad889ed, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(newapunk) +STD_ROM_FN(newapunk) + +struct BurnDriver BurnDrvNewapunk = { + "newapunk", "bbmanw", NULL, NULL, "1992", + "New Atomic Punk - Global Quest (US)\0", NULL, "Irem America", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, newapunkRomInfo, newapunkRomName, NULL, NULL, p4commonInputInfo, BbmanwjDIPInfo, + bbmanwInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Quiz F1 1-2 Finish (Japan) + +static struct BurnRomInfo quizf1RomDesc[] = { + { "qf1-h0-.77", 0x40000, 0x280e3049, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "qf1-l0-.79", 0x40000, 0x94588a6f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "qf1-sp-.33", 0x10000, 0x0664fa9f, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "qf1-c0-.81", 0x80000, 0xc26b521e, 3 | BRF_GRA }, // 3 Tiles and sprites + { "qf1-c1-.82", 0x80000, 0xdb9d7394, 3 | BRF_GRA }, // 4 + { "qf1-c2-.83", 0x80000, 0x0b1460ae, 3 | BRF_GRA }, // 5 + { "qf1-c3-.84", 0x80000, 0x2d32ff37, 3 | BRF_GRA }, // 6 + + { "qf1-v0-.30", 0x40000, 0xb8d16e7c, 4 | BRF_SND }, // 7 Samples + + { "qf1-h1-.78", 0x80000, 0xc6c2eb2b, 5 | BRF_PRG | BRF_ESS }, // 8 V30 banked code + { "qf1-l1-.80", 0x80000, 0x3132c144, 5 | BRF_PRG | BRF_ESS }, // 9 +}; + +STD_ROM_PICK(quizf1) +STD_ROM_FN(quizf1) + +static INT32 quizf1Init() +{ + video_offsets[0] = 48; + video_offsets[1] = 128; + return DrvInit(0x80000, 0x200000, 0x40000, 0x100000, 0, lethalth_decryption_table); +} + +struct BurnDriver BurnDrvQuizf1 = { + "quizf1", NULL, NULL, NULL, "1992", + "Quiz F1 1-2 Finish (Japan)\0", NULL, "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, quizf1RomInfo, quizf1RomName, NULL, NULL, Quizf1InputInfo, Quizf1DIPInfo, + quizf1Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Risky Challenge + +static struct BurnRomInfo riskchalRomDesc[] = { + { "rc_h0.ic77", 0x40000, 0x4c9b5344, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "rc_l0.ic79", 0x40000, 0x0455895a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "l4_a-sp.ic33", 0x10000, 0xbb80094e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "rc_c0.rom", 0x80000, 0x84d0b907, 3 | BRF_GRA }, // 3 Tiles and sprites + { "rc_c1.rom", 0x80000, 0xcb3784ef, 3 | BRF_GRA }, // 4 + { "rc_c2.rom", 0x80000, 0x687164d7, 3 | BRF_GRA }, // 5 + { "rc_c3.rom", 0x80000, 0xc86be6af, 3 | BRF_GRA }, // 6 + + { "rc_v0.rom", 0x40000, 0xcddac360, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(riskchal) +STD_ROM_FN(riskchal) + +static INT32 riskchalInit() +{ + video_offsets[0] = 80; + video_offsets[1] = 136; + return DrvInit(0x80000, 0x200000, 0x40000, 0, 0, gussun_decryption_table); +} + +struct BurnDriver BurnDrvRiskchal = { + "riskchal", NULL, NULL, NULL, "1993", + "Risky Challenge\0", "Unemulated CPU functions", "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, riskchalRomInfo, riskchalRomName, NULL, NULL, p2commonInputInfo, RiskchalDIPInfo, + riskchalInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Gussun Oyoyo (Japan) + +static struct BurnRomInfo gussunRomDesc[] = { + { "l4_a-h0.ic77", 0x40000, 0x9d585e61, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "l4_a-l0.ic79", 0x40000, 0xc7b4c519, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "l4_a-sp.ic33", 0x10000, 0xbb80094e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "rc_c0.rom", 0x80000, 0x84d0b907, 3 | BRF_GRA }, // 3 Tiles and sprites + { "rc_c1.rom", 0x80000, 0xcb3784ef, 3 | BRF_GRA }, // 4 + { "rc_c2.rom", 0x80000, 0x687164d7, 3 | BRF_GRA }, // 5 + { "rc_c3.rom", 0x80000, 0xc86be6af, 3 | BRF_GRA }, // 6 + + { "rc_v0.rom", 0x40000, 0xcddac360, 4 | BRF_SND }, // 7 Samples +}; + +STD_ROM_PICK(gussun) +STD_ROM_FN(gussun) + +struct BurnDriver BurnDrvGussun = { + "gussun", "riskchal", NULL, NULL, "1993", + "Gussun Oyoyo (Japan)\0", "Unemulated CPU functions", "Irem", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, gussunRomInfo, gussunRomName, NULL, NULL, p2commonInputInfo, RiskchalDIPInfo, + riskchalInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Match It II + +static struct BurnRomInfo matchit2RomDesc[] = { + { "sis2-h0-b.bin", 0x40000, 0x9a2556ac, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "sis2-l0-b.bin", 0x40000, 0xd35d948a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sis2-sp-.rom", 0x10000, 0x6fc0ff3a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "ic81.rom", 0x80000, 0x5a7cb88f, 3 | BRF_GRA }, // 3 Tiles and sprites + { "ic82.rom", 0x80000, 0x54a7852c, 3 | BRF_GRA }, // 4 + { "ic83.rom", 0x80000, 0x2bd65dc6, 3 | BRF_GRA }, // 5 + { "ic84.rom", 0x80000, 0x876d5fdb, 3 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(matchit2) +STD_ROM_FN(matchit2) + +static INT32 matchit2Init() +{ + video_offsets[0] = 48; + video_offsets[1] = 128; + return DrvInit(0x80000, 0x200000, 0, 0, 0, matchit2_decryption_table); +} + +struct BurnDriver BurnDrvMatchit2 = { + "matchit2", NULL, NULL, NULL, "1993", + "Match It II\0", NULL, "Tamtex", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, matchit2RomInfo, matchit2RomName, NULL, NULL, Matchit2InputInfo, Matchit2DIPInfo, + matchit2Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Shisensho II + +static struct BurnRomInfo shisen2RomDesc[] = { + { "sis2-h0-.rom", 0x40000, 0x6fae0aea, 1 | BRF_PRG | BRF_ESS }, // 0 V30 Code + { "sis2-l0-.rom", 0x40000, 0x2af25182, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sis2-sp-.rom", 0x10000, 0x6fc0ff3a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "ic81.rom", 0x80000, 0x5a7cb88f, 3 | BRF_GRA }, // 3 Tiles and sprites + { "ic82.rom", 0x80000, 0x54a7852c, 3 | BRF_GRA }, // 4 + { "ic83.rom", 0x80000, 0x2bd65dc6, 3 | BRF_GRA }, // 5 + { "ic84.rom", 0x80000, 0x876d5fdb, 3 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(shisen2) +STD_ROM_FN(shisen2) + +struct BurnDriver BurnDrvShisen2 = { + "shisen2", "matchit2", NULL, NULL, "1993", + "Shisensho II\0", NULL, "Tamtex", "M90", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M90, GBF_MISC, 0, + NULL, shisen2RomInfo, shisen2RomName, NULL, NULL, Matchit2InputInfo, Shisen2DIPInfo, + matchit2Init, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; diff --git a/src/burn/drivers/irem/d_m92.cpp b/src/burn/drivers/irem/d_m92.cpp new file mode 100644 index 00000000..c113afde --- /dev/null +++ b/src/burn/drivers/irem/d_m92.cpp @@ -0,0 +1,3763 @@ +// FB Alpha Irem M92 system driver +// Based on MAME driver by Bryan McPhail +// Original port from MAME by OopsWare + +/* + save state + ssoldier graphics + ym sound is slow... + background alignment (bmasters, inthunt) +*/ + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "vez.h" +#include "msm6295.h" // ppan +#include "irem_cpu.h" +#include "iremga20.h" + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart; +static UINT8 *RamEnd; +static UINT8 *DrvV33ROM; +static UINT8 *DrvV30ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvV33RAM; +static UINT8 *DrvV30RAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT8 *DrvEEPROM; + +static UINT8 *pf_control[4]; + +static UINT8 *sound_status; +static UINT8 *sound_latch; + +static UINT8 *RamPrioBitmap; + +static UINT32 *DrvPalette; +static UINT8 bRecalcPalette = 0; + +static UINT32 PalBank; + +static INT32 sprite_extent = 0; +static UINT8 m92_sprite_buffer_busy; +static INT32 m92_sprite_list; +static INT32 m92_sprite_buffer_timer; +static INT32 m92_raster_irq_position = 0; + +static UINT8 DrvButton[8]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvInput[8]; +static UINT8 DrvReset = 0; + +static INT32 m92_irq_vectorbase; +static INT32 graphics_mask[2] = { 0, 0 }; + +static INT32 nInterleave = 256; // 256 scanlines +static INT32 nCyclesDone[2] = { 0, 0 }; +static INT32 nCyclesTotal[2] = { 0, 0 }; + +static INT32 m92_kludge = 0; +static INT32 nPrevScreenPos = 0; +static INT32 nScreenOffsets[2] = { 0, 0 }; // x,y (ppan) + +static INT32 msm6295_bank; + +typedef struct _m92_layer m92_layer; +struct _m92_layer +{ + INT32 enable; + INT32 wide; + INT32 enable_rowscroll; + + UINT16 scrollx; + UINT16 scrolly; + + UINT16 *scroll; + UINT16 *vram; +}; + +static struct _m92_layer *m92_layers[3]; + +enum { VECTOR_INIT, YM2151_ASSERT, YM2151_CLEAR, V30_ASSERT, V30_CLEAR }; + +static struct BurnInputInfo p2CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvButton + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 5, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvInput + 6, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvInput + 7, "dip" }, +}; + +STDINPUTINFO(p2Common) + +static struct BurnInputInfo p3CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 4, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 3, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 2, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 0, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 7, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 6, "p3 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvButton + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 5, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvInput + 6, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvInput + 7, "dip" }, +}; + +STDINPUTINFO(p3Common) + +static struct BurnInputInfo p4CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 4, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 3, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 2, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 0, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 7, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 6, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy4 + 5, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy4 + 4, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 3, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 2, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 0, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 7, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 6, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvButton + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 5, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvInput + 6, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvInput + 7, "dip" }, +}; + +STDINPUTINFO(p4Common) + +static struct BurnInputInfo PsoldierInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy4 + 1, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy4 + 2, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy4 + 3, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy4 + 5, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy4 + 6, "p2 fire 5" }, + {"P2 Button 6", BIT_DIGITAL, DrvJoy4 + 7, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvButton + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 5, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvInput + 6, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvInput + 7, "dip" }, +}; + +STDINPUTINFO(Psoldier) + +static struct BurnDIPInfo BmasterDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "1" }, + {0x12, 0x01, 0x03, 0x03, "2" }, + {0x12, 0x01, 0x03, 0x02, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x10, 0x10, "300k only" }, + {0x12, 0x01, 0x10, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Bmaster) + +static struct BurnDIPInfo GunforceDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x10, 0x00, "15000 35000 75000 120000" }, + {0x12, 0x01, 0x10, 0x10, "20000 40000 90000 150000" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Gunforce) + + +static struct BurnDIPInfo MysticriDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x10, 0x00, "15000 35000 60000" }, + {0x12, 0x01, 0x10, 0x10, "20000 50000 90000" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Mysticri) + +static struct BurnDIPInfo Gunforc2DIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "3" }, + {0x12, 0x01, 0x03, 0x03, "2" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "1" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x10, 0x00, "15000 35000 75000 120000" }, + {0x12, 0x01, 0x10, 0x10, "20000 40000 90000 150000" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Gunforc2) + +static struct BurnDIPInfo RtypeleoDIPList[]= +{ + {0x12, 0xff, 0xff, 0xaf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Rtypeleo) + +static struct BurnDIPInfo InthuntDIPList[]= +{ + {0x12, 0xff, 0xff, 0xaf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x12, 0x01, 0x20, 0x20, "No" }, + {0x12, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif +}; + +STDDIPINFO(Inthunt) + +static struct BurnDIPInfo LethalthDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Continuous Play" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "No" }, + {0x12, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x13, 0x01, 0x04, 0x04, "Common" }, + {0x13, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "1" }, + {0x13, 0x01, 0x08, 0x00, "2" }, + +#if 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +#else + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +#endif + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x03, 0x02, "500K & 1M" }, + {0x14, 0x01, 0x03, 0x03, "700K & 1.5M" }, + {0x14, 0x01, 0x03, 0x00, "700K, 1.5M, 3M & 4.5M" }, + {0x14, 0x01, 0x03, 0x01, "1M & 2M" }, +}; + +STDDIPINFO(Lethalth) + +static struct BurnDIPInfo UccopsDIPList[]= +{ + {0x1a, 0xff, 0xff, 0xae, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x1a, 0x01, 0x03, 0x00, "1" }, + {0x1a, 0x01, 0x03, 0x03, "2" }, + {0x1a, 0x01, 0x03, 0x02, "3" }, + {0x1a, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1a, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x1a, 0x01, 0x0c, 0x08, "Easy" }, + {0x1a, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1a, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x1a, 0x01, 0x20, 0x00, "No" }, + {0x1a, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1a, 0x01, 0x40, 0x40, "Off" }, + {0x1a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1a, 0x01, 0x80, 0x80, "Off" }, + {0x1a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1b, 0x01, 0x01, 0x01, "Off" }, + {0x1b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x1b, 0x01, 0x02, 0x02, "2 Players" }, + {0x1b, 0x01, 0x02, 0x00, "4 Players" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x1b, 0x01, 0x04, 0x04, "Common" }, + {0x1b, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x1b, 0x01, 0x08, 0x08, "1" }, + {0x1b, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x1b, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x1b, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x1b, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x1b, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x1b, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x1b, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x1b, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x1b, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Uccops) + +static struct BurnDIPInfo HookDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + {0x24, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x00, "1" }, + {0x22, 0x01, 0x03, 0x03, "2" }, + {0x22, 0x01, 0x03, 0x02, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Normal" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x23, 0x01, 0x02, 0x02, "2 Players" }, + {0x23, 0x01, 0x02, 0x00, "4 Players" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x23, 0x01, 0x04, 0x04, "Common" }, + {0x23, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Hook) + +static struct BurnDIPInfo NbbatmanDIPList[]= +{ + {0x22, 0xff, 0xff, 0x9f, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + {0x24, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x22, 0x01, 0x03, 0x00, "1" }, + {0x22, 0x01, 0x03, 0x03, "2" }, + {0x22, 0x01, 0x03, 0x02, "3" }, + {0x22, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Normal" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + {0x22, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x22, 0x01, 0x20, 0x20, "No" }, + {0x22, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x23, 0x01, 0x02, 0x02, "2 Players" }, + {0x23, 0x01, 0x02, 0x00, "4 Players" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x23, 0x01, 0x04, 0x04, "Common" }, + {0x23, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Nbbatman) + +static struct BurnDIPInfo Majtitl2DIPList[]= +{ + {0x22, 0xff, 0xff, 0x9f, NULL }, + {0x23, 0xff, 0xff, 0xfd, NULL }, + {0x24, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Given Holes/Stroke Play" }, + {0x22, 0x01, 0x01, 0x00, "1" }, + {0x22, 0x01, 0x01, 0x01, "2" }, + + {0 , 0xfe, 0 , 2, "Given Holes/Match or Skins" }, + {0x22, 0x01, 0x02, 0x00, "1" }, + {0x22, 0x01, 0x02, 0x02, "2" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x22, 0x01, 0x04, 0x04, "Normal" }, + {0x22, 0x01, 0x04, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Joystick Configuration" }, + {0x22, 0x01, 0x08, 0x08, "Upright" }, + {0x22, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Number of Joysticks" }, + {0x22, 0x01, 0x10, 0x10, "2 Joysticks" }, + {0x22, 0x01, 0x10, 0x00, "4 Joysticks" }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x22, 0x01, 0x20, 0x20, "No" }, + {0x22, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x23, 0x01, 0x02, 0x00, "Upright" }, + {0x23, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x23, 0x01, 0x04, 0x04, "Common" }, + {0x23, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Ticket Dispenser" }, + {0x24, 0x01, 0x01, 0x01, "Off" }, + {0x24, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Points Per Ticket" }, + {0x24, 0x01, 0x06, 0x06, "1 PoINT32 - 1 Ticket" }, + {0x24, 0x01, 0x06, 0x04, "2 Points - 1 Ticket" }, + {0x24, 0x01, 0x06, 0x02, "5 Points - 1 Ticket" }, + {0x24, 0x01, 0x06, 0x00, "10 Points - 1 Ticket" }, + + {0 , 0xfe, 0 , 2, "Deltronics Model" }, + {0x24, 0x01, 0x80, 0x80, "DL 1275" }, + {0x24, 0x01, 0x80, 0x00, "DL 4SS" }, +}; + +STDDIPINFO(Majtitl2) + +static struct BurnDIPInfo Dsoccr94jDIPList[]= +{ + {0x22, 0xff, 0xff, 0xbf, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + {0x24, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x22, 0x01, 0x03, 0x00, "1:30" }, + {0x22, 0x01, 0x03, 0x03, "2:00" }, + {0x22, 0x01, 0x03, 0x02, "2:30" }, + {0x22, 0x01, 0x03, 0x01, "3:00" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x0c, 0x00, "Very Easy" }, + {0x22, 0x01, 0x0c, 0x08, "Easy" }, + {0x22, 0x01, 0x0c, 0x0c, "Normal" }, + {0x22, 0x01, 0x0c, 0x04, "Hard" }, + + {0 , 0xfe, 0 , 2, "Game Mode" }, + {0x22, 0x01, 0x10, 0x10, "Match Mode" }, + {0x22, 0x01, 0x10, 0x00, "Power Mode" }, + + {0 , 0xfe, 0 , 2, "Starting Button" }, + {0x22, 0x01, 0x20, 0x00, "Button 1" }, + {0x22, 0x01, 0x20, 0x20, "Start Button" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x23, 0x01, 0x02, 0x02, "2 Players" }, + {0x23, 0x01, 0x02, 0x00, "4 Players" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x23, 0x01, 0x04, 0x04, "Common" }, + {0x23, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x23, 0x01, 0x08, 0x08, "1" }, + {0x23, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x23, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x23, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x23, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x23, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x23, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x23, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x23, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x23, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x23, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x23, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x23, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Player Power" }, + {0x24, 0x01, 0x03, 0x00, "500" }, + {0x24, 0x01, 0x03, 0x03, "1000" }, + {0x24, 0x01, 0x03, 0x01, "1500" }, + {0x24, 0x01, 0x03, 0x02, "2000" }, +}; + +STDDIPINFO(Dsoccr94j) + +static struct BurnDIPInfo PsoldierDIPList[]= +{ + {0x1a, 0xff, 0xff, 0x9f, NULL }, + {0x1b, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 2, "Any Button to Start" }, + {0x1a, 0x01, 0x20, 0x20, "No" }, + {0x1a, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1a, 0x01, 0x40, 0x40, "Off" }, + {0x1a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1a, 0x01, 0x80, 0x80, "Off" }, + {0x1a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1b, 0x01, 0x01, 0x01, "Off" }, + {0x1b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x1b, 0x01, 0x04, 0x04, "Common" }, + {0x1b, 0x01, 0x04, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x1b, 0x01, 0x08, 0x08, "1" }, + {0x1b, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x1b, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x1b, 0x01, 0xf0, 0x10, "2 Coins to Start/1 to Continue" }, + {0x1b, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x1b, 0x01, 0xf0, 0x20, "4 Coins 3 Credits" }, + {0x1b, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x1b, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x1b, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x1b, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x1b, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Psoldier) + +inline static UINT32 CalcCol(INT32 offs) +{ + INT32 nColour = DrvPalRAM[offs + 0] | (DrvPalRAM[offs + 1] << 8); + INT32 r, g, b; + + r = (nColour & 0x001F) << 3; + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; + g |= g >> 5; + b = (nColour & 0x7C00) >> 7; + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +static void m92YM2151IRQHandler(INT32 nStatus) +{ + VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP0, 0xff/*default*/, nStatus ? VEZ_IRQSTATUS_ACK : VEZ_IRQSTATUS_NONE); + VezRun(100); +} + +UINT8 __fastcall m92ReadByte(UINT32 address) +{ + if ((address & 0xff800) == 0xf8800 ) + return DrvPalRAM[ address - 0xf8800 + PalBank ]; + + if ((address & 0xfc000) == 0xf0000 ) { + if (address & 1) { + return 0xff; + } else { + return DrvEEPROM[(address & 0x3fff) / 2]; + } + } + + return 0; +} + +void __fastcall m92WriteByte(UINT32 address, UINT8 data) +{ + if ((address & 0xff800) == 0xf8800 ) { + DrvPalRAM[ address - 0xf8800 + PalBank ] = data; + if (address & 1) { + INT32 offs = (address - 0xf8800 + PalBank) >> 1; + DrvPalette[offs] = CalcCol( offs << 1 ); + } + return; + } + + if ((address & 0xfc001) == 0xf0000 ) { + DrvEEPROM[(address & 0x3fff) / 2] = data; + return; + } + + switch (address) + { + case 0xf9000: + sprite_extent = (sprite_extent & 0xff00) | (data << 0); + return; + + case 0xf9001: + sprite_extent = (sprite_extent & 0x00ff) | (data << 8); + return; + + case 0xf9004: + m92_sprite_list = (data==8) ? (((0x100 - sprite_extent)&0xff)*4) : 0x400; + return; + + case 0xf9008: + m92_sprite_buffer_busy = 0; + m92_sprite_buffer_timer = 1; + VezRunEnd(); + return; + + case 0xf9800: + PalBank = (data & 0x02) ? 0x0800 : 0x0000; + return; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), data, address); + } +} + +UINT8 __fastcall m92ReadPort(UINT32 port) +{ + switch (port) + { + case 0x00: return ~DrvInput[0]; // player 1 + case 0x01: return ~DrvInput[1]; // player 2 + case 0x02: return (~DrvInput[4] & 0x7F) | m92_sprite_buffer_busy; + case 0x03: return DrvInput[7]; // dip 3 + case 0x04: return DrvInput[5]; // dip 1 + case 0x05: return DrvInput[6]; // dip 2 + case 0x06: return ~DrvInput[2]; // player 3 + case 0x07: return ~DrvInput[3]; // player 4 + + case 0x08: VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 12)/4, VEZ_IRQSTATUS_NONE); return sound_status[0]; + case 0x09: VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 12)/4, VEZ_IRQSTATUS_NONE); return sound_status[1]; + + case 0x18: return (m92_kludge == 3) ? MSM6295ReadStatus(0) : 0; // ppan + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of port %x\n"), port); + } + return 0; +} + +static void set_pf_info(INT32 layer, INT32 data) +{ + struct _m92_layer *ptr = m92_layers[layer]; + + if (data & 0x10) { + ptr->enable = 0; + } else { + ptr->enable = 1; + ptr->wide = (data & 0x04) ? 128 : 64; + } + + ptr->enable_rowscroll = data & 0x40; + + ptr->vram = (UINT16*)(DrvVidRAM + ((data & 0x03) * 0x4000)); +} + +static void set_pf_scroll(INT32 layer) +{ + struct _m92_layer *ptr = m92_layers[layer]; + + ptr->scrollx = (pf_control[layer][4] << 0) | (pf_control[layer][5] << 8); + ptr->scrolly = (pf_control[layer][0] << 0) | (pf_control[layer][1] << 8); +} + +void __fastcall m92WritePort(UINT32 port, UINT8 data) +{ + switch (port) + { + case 0x00: + // case 0x01: + sound_latch[0] = data; + VezClose(); + VezOpen(1); + VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP1, 0xff/*default*/, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP1, 0xff/*default*/, VEZ_IRQSTATUS_NONE); + VezRun(10); + VezClose(); + VezOpen(0); + return; + + case 0x02: + case 0x03: + //m92_coincounter_w + return; + + case 0x10: // ppan + if (m92_kludge == 3) { + if (msm6295_bank != (data + 1)) { + msm6295_bank = (data & 3) + 1; + memcpy (DrvSndROM + 0x20000, DrvSndROM + 0x100000 + msm6295_bank * 0x20000, 0x20000); + } + } + return; + + case 0x18: // ppan + if (m92_kludge == 3) MSM6295Command(0, data); + return; + + case 0x20: + // case 0x21: + // m92_bankswitch_w + if (m92_kludge != 1) { // lethalth + VezMapArea(0xa0000, 0xbffff, 0, DrvV33ROM + 0x100000 + (data&0x7)*0x10000); + VezMapArea(0xa0000, 0xbffff, 2, DrvV33ROM + 0x100000 + (data&0x7)*0x10000); + } + return; + + // case 0x40: // Interrupt controller, only written to at bootup + // case 0x41: + // case 0x42: + // case 0x43: + // return; + + case 0x80: pf_control[0][0] = data; set_pf_scroll(0); return; + case 0x81: pf_control[0][1] = data; set_pf_scroll(0); return; + case 0x82: pf_control[0][2] = data; return; + case 0x83: pf_control[0][3] = data; return; + case 0x84: pf_control[0][4] = data; set_pf_scroll(0); return; + case 0x85: pf_control[0][5] = data; set_pf_scroll(0); return; + case 0x86: pf_control[0][6] = data; return; + case 0x87: pf_control[0][7] = data; return; + case 0x88: pf_control[1][0] = data; set_pf_scroll(1); return; + case 0x89: pf_control[1][1] = data; set_pf_scroll(1); return; + case 0x8a: pf_control[1][2] = data; return; + case 0x8b: pf_control[1][3] = data; return; + case 0x8c: pf_control[1][4] = data; set_pf_scroll(1); return; + case 0x8d: pf_control[1][5] = data; set_pf_scroll(1); return; + case 0x8e: pf_control[1][6] = data; return; + case 0x8f: pf_control[1][7] = data; return; + case 0x90: pf_control[2][0] = data; set_pf_scroll(2); return; + case 0x91: pf_control[2][1] = data; set_pf_scroll(2); return; + case 0x92: pf_control[2][2] = data; return; + case 0x93: pf_control[2][3] = data; return; + case 0x94: pf_control[2][4] = data; set_pf_scroll(2); return; + case 0x95: pf_control[2][5] = data; set_pf_scroll(2); return; + case 0x96: pf_control[2][6] = data; return; + case 0x97: pf_control[2][7] = data; return; + case 0x98: pf_control[3][0] = data; set_pf_info(0, data); return; + case 0x99: pf_control[3][1] = data; return; + case 0x9a: pf_control[3][2] = data; set_pf_info(1, data); return; + case 0x9b: pf_control[3][3] = data; return; + case 0x9c: pf_control[3][4] = data; set_pf_info(2, data); return; + case 0x9d: pf_control[3][5] = data; return; + case 0x9e: pf_control[3][6] = data; + m92_raster_irq_position = ((pf_control[3][7]<<8) | pf_control[3][6]) - 128; + return; + case 0x9f: pf_control[3][7] = data; + m92_raster_irq_position = ((pf_control[3][7]<<8) | pf_control[3][6]) - 128; + return; + + case 0xc0: + case 0xc1:// sound reset + return; + + //default: + // bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to port %x\n"), data, port); + } +} + +UINT8 __fastcall m92SndReadByte(UINT32 address) +{ + if ((address & 0xfffc0) == 0xa8000) { + return iremga20_read( 0, (address & 0x0003f) / 2 ); + } + + switch (address) + { + case 0xa8042: + return BurnYM2151ReadStatus(); + + case 0xa8044: +// VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP1, 0xff/*default*/, VEZ_IRQSTATUS_NONE); + return sound_latch[0]; + + case 0xa8045: + return 0xff; // soundlatch high bits, always 0xff + +// default: +// bprintf(PRINT_NORMAL, _T("V30 Attempt to read byte value of location %x\n"), address); + } + return 0; +} + +void __fastcall m92SndWriteByte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffc0) == 0xa8000) { + iremga20_write( 0, (address & 0x0003f) / 2, data ); + return; + } + + if ((address & 0xfff00) == 0x9ff00) { // NOP + return; + } + + switch (address) + { + case 0xa8040: + // case 0xa8041: + BurnYM2151SelectRegister(data); + return; + + case 0xa8042: + // case 0xa8043: + BurnYM2151WriteRegister(data); + return; + + case 0xa8044: + // case 0xa8045: +// VezSetIRQLineAndVector(NEC_INPUT_LINE_INTP1, 0xff/*default*/, VEZ_IRQSTATUS_NONE); + return; + + case 0xa8046: + // case 0xa8047: + sound_status[0] = data; + VezClose(); + VezOpen(0); + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 12)/4, VEZ_IRQSTATUS_ACK); + VezClose(); + VezOpen(1); + return; + + // default: + // bprintf(PRINT_NORMAL, _T("V30 Attempt to write byte value %x to location %x\n"), data, address); + } +} + +static INT32 DrvDoReset() +{ + memset (RamStart, 0, RamEnd - RamStart); + + VezOpen(0); + VezReset(); + VezClose(); + + VezOpen(1); + VezReset(); + VezClose(); + + BurnYM2151Reset(); + iremga20_reset(0); + if (m92_kludge == 3) { // ppan + MSM6295Reset(0); + msm6295_bank = -1; + m92WritePort(0x10, 0); // set bank + } + + if (m92_kludge == 1) sound_status[0] = 0x80; + + m92_sprite_buffer_busy = 0x80; + m92_sprite_buffer_timer = 0; + PalBank = 0; + + { + struct _m92_layer *ptr; + for (INT32 i = 0; i < 3; i++) { + ptr = m92_layers[i]; + ptr->scroll = (UINT16*)(DrvVidRAM + (0xf400 + 0x400 * i)); + } + } + + return 0; +} + +static void loadDecodeGfx01(UINT8 *tmp, INT32 rid, INT32 shift, INT32 size) +{ + UINT8 * pgfx = DrvGfxROM0; + + BurnLoadRom(tmp, rid, 1); + + for (INT32 i=0; i<(size/8); i++) { + for( INT32 y=0;y<8;y++, tmp++, pgfx+=8) { + for ( INT32 j=0;j<8;j++) { + pgfx[j] |= ((tmp[0]>>(j^7))&1)<>(~j&7))&1)<> (7-(i&7)))&1)<= nScreenWidth || sy <= (0-height) || sy >= nScreenHeight) return; + + INT32 flip = 0; + if (flipy) flip |= (height - 1) * width; + if (flipx) flip |= width - 1; + + gfx += code * width * height; + + for (INT32 y = 0; y < height; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 x = 0; x < width; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((y * width) + x) ^ flip]; + + if (pxl == 0) continue; + + if ((prio & (1 << pri[sy * nScreenWidth + sx])) == 0) { + dest[sy * nScreenWidth + sx] = pxl | color; + pri[sy * nScreenWidth + sx] = 7; + } + } + + sx -= width; + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprBuf; + + for (INT32 k=0; k<8; k++) + { + for (INT32 offs = 0; offs < m92_sprite_list; ) + { + INT32 y = (((384 - 16 - (ram[offs+0] & 0x1ff)) - nScreenOffsets[1]) & 0x1ff) - 8; + INT32 x = (ram[offs+3] & 0x1ff) - 96; + + INT32 pri_s = (ram[offs+0] & 0xe000) >> 13; + INT32 pri_b = (ram[offs+2] & 0x0080) ? 0x80 : 0x82; + INT32 code = ram[offs+1]; + INT32 color = ram[offs+2] & 0x007f; + + INT32 flipx = ram[offs+2] & 0x0100; + INT32 flipy = ram[offs+2] & 0x0200; + INT32 y_multi= 1 << ((ram[offs+0] >> 9) & 3); + INT32 x_multi= 1 << ((ram[offs+0] >> 11) & 3); + + offs += 4 * x_multi; + if (pri_s != k) continue; + + if (flipx) x+=16 * (x_multi - 1); + + for (INT32 j = 0; j < x_multi; j++) + { + INT32 s_ptr = j * 8; + if (!flipy) s_ptr += y_multi-1; + + x &= 0x1ff; + + for (INT32 i=0; i 0x1f0) RenderTilePrio(pTransDraw, DrvGfxROM1, (code + s_ptr) & graphics_mask[1], color << 4, x-512, y-i*16, flipx, flipy, 16, 16, RamPrioBitmap, pri_b); + + if (flipy) s_ptr++; else s_ptr--; + } + + if (flipx) x-=16; else x+=16; + } + } + } +} + +static void draw_layer_byline(INT32 start, INT32 finish, INT32 layer, INT32 forcelayer) +{ + struct _m92_layer *ptr = m92_layers[layer]; + + if (ptr->enable == 0) return; + + INT32 wide = ptr->wide; + INT32 scrolly = (ptr->scrolly + 136 - nScreenOffsets[1]) & 0x1ff; + INT32 scrollx = ((ptr->scrollx - nScreenOffsets[0]) - (2 * layer - ((wide & 0x80)<<1))) + 80; + + const UINT16 transmask[3][3][2] = { // layer, group, value + { { 0xffff, 0x0001 }, { 0x00ff, 0xff01 }, { 0x0001, 0xffff } }, + { { 0xffff, 0x0001 }, { 0x00ff, 0xff01 }, { 0x0001, 0xffff } }, + { { 0xffff, 0x0000 }, { 0x00ff, 0xff00 }, { 0x0001, 0xfffe } } + }; + + INT32 priority = 1 << forcelayer; + + for (INT32 sy = start; sy < finish; sy++) + { + UINT16 *dest = pTransDraw + (sy * nScreenWidth); + UINT8 *pri = RamPrioBitmap + (sy * nScreenWidth); + + INT32 scrollx_1 = scrollx; + if (ptr->enable_rowscroll) scrollx_1 += ptr->scroll[(sy+scrolly)&0x1ff]; + INT32 scrolly_1 = (scrolly + sy) & 0x1ff; + INT32 romoff_1 = (scrolly_1 & 0x07) << 3; + + for (INT32 sx = 0; sx < nScreenWidth + 8; sx+=8) + { + INT32 offs = ((scrolly_1 / 8) * wide) + (((scrollx_1 + sx) / 8) & (wide - 1)); + INT32 attr = ptr->vram[(offs * 2) + 1]; + INT32 code = ptr->vram[(offs * 2) + 0] | ((attr & 0x8000) << 1); + INT32 color =(attr & 0x007f) << 4; + INT32 flipy = attr & 0x0400; + INT32 flipx = attr & 0x0200; + + INT32 group = 0; + if (attr & 0x0180) group = (attr & 0x0100) ? 2 : 1; + + { + INT32 x_xor = 0; + INT32 romoff = romoff_1; + if (flipy) romoff ^= 0x38; + if (flipx) x_xor = 7; + + UINT8 *rom = DrvGfxROM0 + ((code & graphics_mask[0]) * 0x40) + romoff; + INT32 mask = transmask[layer][group][forcelayer]; + + INT32 xx = sx - (scrollx_1&0x7); + + for (INT32 x = 0; x < 8; x++, xx++) { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = rom[x ^ x_xor]; + if (mask & (1 << pxl)) continue; + + dest[xx] = pxl | color; + pri[xx] = priority; + } + } + } + } +} + +static void DrawLayers(INT32 start, INT32 finish) +{ + memset (RamPrioBitmap + (start * nScreenWidth), 0, nScreenWidth * (finish - start)); // clear priority + + if (~nBurnLayer & 1) memset (pTransDraw + (start * nScreenWidth), 0, nScreenWidth * (finish - start) * sizeof(INT16)); + + if (~pf_control[3][4] & 0x10) { + if (nBurnLayer & 1) draw_layer_byline(start, finish, 2, 1); + if (nBurnLayer & 1) draw_layer_byline(start, finish, 2, 0); + } else { + memset (pTransDraw + (start * nScreenWidth), 0, nScreenWidth * (finish - start) * sizeof(INT16)); + } + + if (nBurnLayer & 2) draw_layer_byline(start, finish, 1, 1); + if (nBurnLayer & 2) draw_layer_byline(start, finish, 1, 0); + if (nBurnLayer & 4) draw_layer_byline(start, finish, 0, 1); + if (nBurnLayer & 4) draw_layer_byline(start, finish, 0, 0); +} + +static INT32 DrvDraw() +{ + if (bRecalcPalette) { + for (INT32 i=0; i<0x800;i++) + DrvPalette[i] = CalcCol(i<<1); + bRecalcPalette = 0; + } + +// DrawLayers(0, nScreenHeight); + + if (nBurnLayer & 8) draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvReDraw() +{ + if (bRecalcPalette) { + for (INT32 i=0; i<0x800;i++) + DrvPalette[i] = CalcCol(i<<1); + bRecalcPalette = 0; + } + + DrawLayers(0, nScreenHeight); + + if (nBurnLayer & 8) draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void compile_inputs() +{ + memset (DrvInput, 0, 5); + + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvJoy3[i] & 1) << i; + DrvInput[3] |= (DrvJoy4[i] & 1) << i; + DrvInput[4] |= (DrvButton[i] & 1) << i; + } +} + +static void scanline_interrupts(INT32 prev, INT32 segment, INT32 scanline) +{ + if (m92_sprite_buffer_timer) { + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + nCyclesDone[0] += VezRun(347); + m92_sprite_buffer_busy = 0x80; + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 4)/4, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 4)/4, VEZ_IRQSTATUS_NONE); + nCyclesDone[0] += VezRun(segment - (VezTotalCycles() - prev)); + + m92_sprite_buffer_timer = 0; + } + + if (scanline == m92_raster_irq_position) { + + if (scanline>=8 && scanline < 248 && nPrevScreenPos != (scanline-8)+1) { + if (nPrevScreenPos >= 0 && nPrevScreenPos <= 239) + DrawLayers(nPrevScreenPos, (scanline-8)+1); + nPrevScreenPos = (scanline-8)+1; + } + + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 8)/4, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 8)/4, VEZ_IRQSTATUS_NONE); + + } + else if (scanline == 248) // vblank + { + if (nPrevScreenPos != 240) { + DrawLayers(nPrevScreenPos, 240); + } + nPrevScreenPos = 0; + + if (pBurnDraw) { + DrvDraw(); + } + + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 0)/4, VEZ_IRQSTATUS_ACK); + VezRun(10); + VezSetIRQLineAndVector(0, (m92_irq_vectorbase + 0)/4, VEZ_IRQSTATUS_NONE); + + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + VezNewFrame(); + + compile_inputs(); + + // overclocking... + INT32 nSoundBufferPos = 0; + nCyclesTotal[0] = (INT32)((INT64)(9000000 / 60) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesTotal[1] = (INT32)((INT64)(7159090 / 60) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesDone[0] = nCyclesDone[1] = 0; + + if (pBurnSoundOut) { + memset (pBurnSoundOut, 0, nBurnSoundLen * sizeof(INT16)); + } + + for (INT32 i = 0; i < nInterleave; i++) + { + VezOpen(0); + UINT32 segment = nCyclesTotal[0] / nInterleave; + INT32 prev = VezTotalCycles(); + + nCyclesDone[0] += VezRun(segment); + scanline_interrupts(prev, segment, i); // update at hblank? + VezClose(); + + VezOpen(1); + segment = nCyclesTotal[1] / nInterleave; + segment += segment * i; + while (VezTotalCycles() < segment) { + nCyclesDone[1] += VezRun(segment - VezTotalCycles()); + } + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + BurnYM2151Render(pSoundBuf, nSegmentLength); + iremga20_update(0, pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + VezClose(); + } + + VezOpen(1); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + iremga20_update(0, pSoundBuf, nSegmentLength); + } + } + + VezClose(); + + return 0; +} + +static INT32 PpanFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + compile_inputs(); + + // overclocking... + nCyclesTotal[0] = (INT32)((INT64)(9000000 / 60) * nBurnCPUSpeedAdjust / 0x0100); + nCyclesDone[0] = 0; + + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += VezRun(nCyclesTotal[0] / nInterleave); + + scanline_interrupts(0,0,i); + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin) + { + *pnMin = 0x029671; + } + + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) + { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + if (nAction & ACB_WRITE) { + bRecalcPalette = 1; + + struct _m92_layer *ptr; + for (INT32 i = 0; i < 3; i++) { + ptr = m92_layers[i]; + ptr->scroll = (UINT16*)(DrvVidRAM + (0xf400 + 0x400 * i)); + } + + set_pf_info(0, pf_control[3][0]); + set_pf_info(1, pf_control[3][2]); + set_pf_info(2, pf_control[3][4]); + } + } + + if (nAction & ACB_DRIVER_DATA) + { + VezScan(nAction); + + iremga20_scan(0, nAction, pnMin); + + SCAN_VAR(PalBank); + + SCAN_VAR(m92_raster_irq_position); + SCAN_VAR(sprite_extent); + SCAN_VAR(m92_sprite_list); + SCAN_VAR(m92_sprite_buffer_busy); + SCAN_VAR(m92_sprite_buffer_timer); + + if (m92_kludge == 3) { // ppan + MSM6295Scan(0, nAction); + + SCAN_VAR(msm6295_bank); + + INT32 temp = msm6295_bank; + msm6295_bank = -1; + m92WritePort(0x10, temp); + } + } + + return 0; +} + + +//----------------------------------------------------------------------------------------------------------------------------- + + +// Hook (World) + +static struct BurnRomInfo hookRomDesc[] = { + { "h-h0-d.3h", 0x040000, 0x40189ff6, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "h-l0-d.3h", 0x040000, 0x14567690, 1 | BRF_PRG | BRF_ESS }, // 1 + { "h-h1.rom", 0x020000, 0x264ba1f0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "h-l1.rom", 0x020000, 0xf9913731, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "h-sh0.rom", 0x010000, 0x86a4e56e, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "h-sl0.rom", 0x010000, 0x10fd9676, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "hook-c0.rom", 0x040000, 0xdec63dcf, 3 | BRF_GRA }, // 6 Background Tiles + { "hook-c1.rom", 0x040000, 0xe4eb0b92, 3 | BRF_GRA }, // 7 + { "hook-c2.rom", 0x040000, 0xa52b320b, 3 | BRF_GRA }, // 8 + { "hook-c3.rom", 0x040000, 0x7ef67731, 3 | BRF_GRA }, // 9 + + { "hook-000.rom", 0x100000, 0xccceac30, 4 | BRF_GRA }, // 10 Sprites + { "hook-010.rom", 0x100000, 0x8ac8da67, 4 | BRF_GRA }, // 11 + { "hook-020.rom", 0x100000, 0x8847af9a, 4 | BRF_GRA }, // 12 + { "hook-030.rom", 0x100000, 0x239e877e, 4 | BRF_GRA }, // 13 + + { "hook-da.rom", 0x080000, 0x88cd0212, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(hook) +STD_ROM_FN(hook) + +static INT32 hookRomLoad() +{ + return RomLoad(0x080000, 0x040000, 0x100000, 0, 0); +} + +static INT32 hookInit() +{ + return DrvInit(hookRomLoad, hook_decryption_table, 1, 0x80, 0x100000, 0x400000); +} + +struct BurnDriver BurnDrvHook = { + "hook", NULL, NULL, NULL, "1992", + "Hook (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, hookRomInfo, hookRomName, NULL, NULL, p4CommonInputInfo, HookDIPInfo, + hookInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Hook (US) + +static struct BurnRomInfo hookuRomDesc[] = { + { "h-h0-c.3h", 0x040000, 0x84cc239e, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "h-l0-c.5h", 0x040000, 0x45e194fe, 1 | BRF_PRG | BRF_ESS }, // 1 + { "h-h1.rom", 0x020000, 0x264ba1f0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "h-l1.rom", 0x020000, 0xf9913731, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "h-sh0.rom", 0x010000, 0x86a4e56e, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "h-sl0.rom", 0x010000, 0x10fd9676, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "hook-c0.rom", 0x040000, 0xdec63dcf, 3 | BRF_GRA }, // 6 Background Tiles + { "hook-c1.rom", 0x040000, 0xe4eb0b92, 3 | BRF_GRA }, // 7 + { "hook-c2.rom", 0x040000, 0xa52b320b, 3 | BRF_GRA }, // 8 + { "hook-c3.rom", 0x040000, 0x7ef67731, 3 | BRF_GRA }, // 9 + + { "hook-000.rom", 0x100000, 0xccceac30, 4 | BRF_GRA }, // 10 Sprites + { "hook-010.rom", 0x100000, 0x8ac8da67, 4 | BRF_GRA }, // 11 + { "hook-020.rom", 0x100000, 0x8847af9a, 4 | BRF_GRA }, // 12 + { "hook-030.rom", 0x100000, 0x239e877e, 4 | BRF_GRA }, // 13 + + { "hook-da.rom", 0x080000, 0x88cd0212, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(hooku) +STD_ROM_FN(hooku) + +struct BurnDriver BurnDrvHooku = { + "hooku", "hook", NULL, NULL, "1992", + "Hook (US)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, hookuRomInfo, hookuRomName, NULL, NULL, p4CommonInputInfo, HookDIPInfo, + hookInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Hook (Japan) + +static struct BurnRomInfo hookjRomDesc[] = { + { "h-h0-g.3h", 0x040000, 0x5964c886, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "h-l0-g.5h", 0x040000, 0x7f7433f2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "h-h1.rom", 0x020000, 0x264ba1f0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "h-l1.rom", 0x020000, 0xf9913731, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "h-sh0-a.3l", 0x010000, 0xbd3d1f61, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "h-sl0-a.3n", 0x010000, 0x76371def, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "hook-c0.rom", 0x040000, 0xdec63dcf, 3 | BRF_GRA }, // 6 Background Tiles + { "hook-c1.rom", 0x040000, 0xe4eb0b92, 3 | BRF_GRA }, // 7 + { "hook-c2.rom", 0x040000, 0xa52b320b, 3 | BRF_GRA }, // 8 + { "hook-c3.rom", 0x040000, 0x7ef67731, 3 | BRF_GRA }, // 9 + + { "hook-000.rom", 0x100000, 0xccceac30, 4 | BRF_GRA }, // 10 Sprites + { "hook-010.rom", 0x100000, 0x8ac8da67, 4 | BRF_GRA }, // 11 + { "hook-020.rom", 0x100000, 0x8847af9a, 4 | BRF_GRA }, // 12 + { "hook-030.rom", 0x100000, 0x239e877e, 4 | BRF_GRA }, // 13 + + { "hook-da.rom", 0x080000, 0x88cd0212, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(hookj) +STD_ROM_FN(hookj) + +struct BurnDriver BurnDrvHookj = { + "hookj", "hook", NULL, NULL, "1992", + "Hook (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, hookjRomInfo, hookjRomName, NULL, NULL, p4CommonInputInfo, HookDIPInfo, + hookInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Peter Pan (bootleg of Hook) + +static struct BurnRomInfo ppanRomDesc[] = { + { "1.u6", 0x80000, 0xb135dd6e, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "2.u5", 0x80000, 0x7785289c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "7.u114", 0x40000, 0xdec63dcf, 2 | BRF_PRG | BRF_ESS }, // 2 Background Tiles + { "6.u115", 0x40000, 0xe4eb0b92, 2 | BRF_PRG | BRF_ESS }, // 3 + { "5.u116", 0x40000, 0xa52b320b, 2 | BRF_PRG | BRF_ESS }, // 4 + { "4.u117", 0x40000, 0x7ef67731, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "15.u106", 0x80000, 0xcdfc2f78, 3 | BRF_GRA }, // 6 Sprites + { "14.u110", 0x80000, 0x87e767f0, 3 | BRF_GRA }, // 7 + { "13.u107", 0x80000, 0xe07f2abe, 3 | BRF_GRA }, // 8 + { "12.u111", 0x80000, 0xf446150e, 3 | BRF_GRA }, // 9 + { "11.u108", 0x80000, 0x5c114daa, 3 | BRF_GRA }, // 10 + { "10.u112", 0x80000, 0xfa11fa40, 3 | BRF_GRA }, // 11 + { "9.u109", 0x80000, 0x9d466b1a, 3 | BRF_GRA }, // 12 + { "8.u113", 0x80000, 0xd08a5f6b, 3 | BRF_GRA }, // 13 + + { "3.u122", 0x80000, 0xd0d37028, 4 | BRF_GRA }, // 14 OKI M6295 Samples +}; + +STD_ROM_PICK(ppan) +STD_ROM_FN(ppan) + +static INT32 ppanRomLoad() +{ + if (BurnLoadRom(DrvV33ROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(DrvV33ROM + 0x000000, 1, 2)) return 1; + + UINT8 *tmp = (UINT8 *)malloc(0x080000); + if (tmp == NULL) { + return 1; + } + + loadDecodeGfx01(tmp, 2, 0, 0x40000); + loadDecodeGfx01(tmp, 3, 1, 0x40000); + loadDecodeGfx01(tmp, 4, 2, 0x40000); + loadDecodeGfx01(tmp, 5, 3, 0x40000); + + DrvGfxROM1 += 0x400000; + + loadDecodeGfx02(tmp, 7, 0, 0x80000); + loadDecodeGfx02(tmp, 9, 1, 0x80000); + loadDecodeGfx02(tmp, 11, 2, 0x80000); + loadDecodeGfx02(tmp, 13, 3, 0x80000); + + DrvGfxROM1 -= 0x400000; + + loadDecodeGfx02(tmp, 6, 0, 0x80000); + loadDecodeGfx02(tmp, 8, 1, 0x80000); + loadDecodeGfx02(tmp, 10, 2, 0x80000); + loadDecodeGfx02(tmp, 12, 3, 0x80000); + + if (BurnLoadRom(DrvSndROM + 0x100000, 14, 1)) return 1; + memcpy (DrvSndROM, DrvSndROM + 0x100000, 0x40000); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + DrvSprBuf = DrvSprRAM; // no sprite buffer!! + + return 0; +} + +static INT32 PpanInit() +{ + m92_kludge = 3; + nScreenOffsets[1] = 120; // ? + return DrvInit(ppanRomLoad, NULL, 1, 0x80, 0x100000, 0x400000); +} + +struct BurnDriver BurnDrvPpan = { + "ppan", "hook", NULL, NULL, "1992", + "Peter Pan (bootleg of Hook)\0", "Imperfect graphics", "bootleg", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, ppanRomInfo, ppanRomName, NULL, NULL, p4CommonInputInfo, HookDIPInfo, + PpanInit, DrvExit, PpanFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// In The Hunt (World) + +static struct BurnRomInfo inthuntRomDesc[] = { + { "ith-h0-d.bin", 0x040000, 0x52f8e7a6, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "ith-l0-d.bin", 0x040000, 0x5db79eb7, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ith-h1-b.bin", 0x020000, 0xfc2899df, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ith-l1-b.bin", 0x020000, 0x955a605a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ith-sh0.rom", 0x010000, 0x209c8b7f, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "ith-sl0.rom", 0x010000, 0x18472d65, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "ith_ic26.rom", 0x080000, 0x4c1818cf, 3 | BRF_GRA }, // 6 Background Tiles + { "ith_ic25.rom", 0x080000, 0x91145bae, 3 | BRF_GRA }, // 7 + { "ith_ic24.rom", 0x080000, 0xfc03fe3b, 3 | BRF_GRA }, // 8 + { "ith_ic23.rom", 0x080000, 0xee156a0a, 3 | BRF_GRA }, // 9 + + { "ith_ic34.rom", 0x100000, 0xa019766e, 4 | BRF_GRA }, // 10 Sprites + { "ith_ic35.rom", 0x100000, 0x3fca3073, 4 | BRF_GRA }, // 11 + { "ith_ic36.rom", 0x100000, 0x20d1b28b, 4 | BRF_GRA }, // 12 + { "ith_ic37.rom", 0x100000, 0x90b6fd4b, 4 | BRF_GRA }, // 13 + + { "ith_ic9.rom", 0x080000, 0x318ee71a, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(inthunt) +STD_ROM_FN(inthunt) + +static INT32 inthuntRomLoad() +{ + return RomLoad(0x080000, 0x080000, 0x100000, 0, 0); +} + +static INT32 inthuntInit() +{ + return DrvInit(inthuntRomLoad, inthunt_decryption_table, 1, 0x80, 0x200000, 0x400000); +} + +struct BurnDriver BurnDrvInthunt = { + "inthunt", NULL, NULL, NULL, "1993", + "In The Hunt (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, inthuntRomInfo, inthuntRomName, NULL, NULL, p2CommonInputInfo, InthuntDIPInfo, + inthuntInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// In The Hunt (US) + +static struct BurnRomInfo inthuntuRomDesc[] = { + { "ith-h0-c.bin", 0x040000, 0x563dcec0, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "ith-l0-c.bin", 0x040000, 0x1638c705, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ith-h1-a.bin", 0x020000, 0x0253065f, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ith-l1-a.bin", 0x020000, 0xa57d688d, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ith-sh0.rom", 0x010000, 0x209c8b7f, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "ith-sl0.rom", 0x010000, 0x18472d65, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "ith_ic26.rom", 0x080000, 0x4c1818cf, 3 | BRF_GRA }, // 6 Background Tiles + { "ith_ic25.rom", 0x080000, 0x91145bae, 3 | BRF_GRA }, // 7 + { "ith_ic24.rom", 0x080000, 0xfc03fe3b, 3 | BRF_GRA }, // 8 + { "ith_ic23.rom", 0x080000, 0xee156a0a, 3 | BRF_GRA }, // 9 + + { "ith_ic34.rom", 0x100000, 0xa019766e, 4 | BRF_GRA }, // 10 Sprites + { "ith_ic35.rom", 0x100000, 0x3fca3073, 4 | BRF_GRA }, // 11 + { "ith_ic36.rom", 0x100000, 0x20d1b28b, 4 | BRF_GRA }, // 12 + { "ith_ic37.rom", 0x100000, 0x90b6fd4b, 4 | BRF_GRA }, // 13 + + { "ith_ic9.rom", 0x080000, 0x318ee71a, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(inthuntu) +STD_ROM_FN(inthuntu) + +struct BurnDriver BurnDrvInthuntu = { + "inthuntu", "inthunt", NULL, NULL, "1993", + "In The Hunt (US)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, inthuntuRomInfo, inthuntuRomName, NULL, NULL, p2CommonInputInfo, InthuntDIPInfo, + inthuntInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Kaitei Daisensou (Japan) + +static struct BurnRomInfo kaiteidsRomDesc[] = { + { "ith-h0j.bin", 0x040000, 0xdc1dec36, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "ith-l0j.bin", 0x040000, 0x8835d704, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ith-h1j.bin", 0x020000, 0x5a7b212d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ith-l1j.bin", 0x020000, 0x4c084494, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ith-sh0.rom", 0x010000, 0x209c8b7f, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "ith-sl0.rom", 0x010000, 0x18472d65, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "ith_ic26.rom", 0x080000, 0x4c1818cf, 3 | BRF_GRA }, // 6 Background Tiles + { "ith_ic25.rom", 0x080000, 0x91145bae, 3 | BRF_GRA }, // 7 + { "ith_ic24.rom", 0x080000, 0xfc03fe3b, 3 | BRF_GRA }, // 8 + { "ith_ic23.rom", 0x080000, 0xee156a0a, 3 | BRF_GRA }, // 9 + + { "ith_ic34.rom", 0x100000, 0xa019766e, 4 | BRF_GRA }, // 10 Sprites + { "ith_ic35.rom", 0x100000, 0x3fca3073, 4 | BRF_GRA }, // 11 + { "ith_ic36.rom", 0x100000, 0x20d1b28b, 4 | BRF_GRA }, // 12 + { "ith_ic37.rom", 0x100000, 0x90b6fd4b, 4 | BRF_GRA }, // 13 + + { "ith_ic9.rom", 0x080000, 0x318ee71a, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(kaiteids) +STD_ROM_FN(kaiteids) + +struct BurnDriver BurnDrvKaiteids = { + "kaiteids", "inthunt", NULL, NULL, "1993", + "Kaitei Daisensou (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + L"Kaitei Daisensou (Japan)\0\u776D\u955E\u2759\u2662\u894E\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, kaiteidsRomInfo, kaiteidsRomName, NULL, NULL, p2CommonInputInfo, InthuntDIPInfo, + inthuntInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// R-Type Leo (World) + +static struct BurnRomInfo rtypeleoRomDesc[] = { + { "rtl-h0-c.bin", 0x040000, 0x5fef7fa1, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "rtl-l0-c.bin", 0x040000, 0x8156456b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rtl-h1-d.bin", 0x020000, 0x352ff444, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rtl-l1-d.bin", 0x020000, 0xfd34ea46, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "rtl-sh0a.bin", 0x010000, 0xe518b4e3, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "rtl-sl0a.bin", 0x010000, 0x896f0d36, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "rtl-c0.bin", 0x080000, 0xfb588d7c, 3 | BRF_GRA }, // 6 Background Tiles + { "rtl-c1.bin", 0x080000, 0xe5541bff, 3 | BRF_GRA }, // 7 + { "rtl-c2.bin", 0x080000, 0xfaa9ae27, 3 | BRF_GRA }, // 8 + { "rtl-c3.bin", 0x080000, 0x3a2343f6, 3 | BRF_GRA }, // 9 + + { "rtl-000.bin", 0x100000, 0x82a06870, 4 | BRF_GRA }, // 10 Sprites + { "rtl-010.bin", 0x100000, 0x417e7a56, 4 | BRF_GRA }, // 11 + { "rtl-020.bin", 0x100000, 0xf9a3f3a1, 4 | BRF_GRA }, // 12 + { "rtl-030.bin", 0x100000, 0x03528d95, 4 | BRF_GRA }, // 13 + + { "rtl-da.bin", 0x080000, 0xdbebd1ff, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(rtypeleo) +STD_ROM_FN(rtypeleo) + +static INT32 rtypeleoRomLoad() +{ + return RomLoad(0x080000, 0x080000, 0x100000, 0, 0); +} + +static INT32 rtypeleoInit() +{ + return DrvInit(rtypeleoRomLoad, rtypeleo_decryption_table, 1, 0x20, 0x200000, 0x400000); +} + +struct BurnDriver BurnDrvRtypeleo = { + "rtypeleo", NULL, NULL, NULL, "1992", + "R-Type Leo (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, rtypeleoRomInfo, rtypeleoRomName, NULL, NULL, p2CommonInputInfo, RtypeleoDIPInfo, + rtypeleoInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// R-Type Leo (Japan) + +static struct BurnRomInfo rtypelejRomDesc[] = { + { "rtl-h0-d.bin", 0x040000, 0x3dbac89f, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "rtl-l0-d.bin", 0x040000, 0xf85a2537, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rtl-h1-d.bin", 0x020000, 0x352ff444, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rtl-l1-d.bin", 0x020000, 0xfd34ea46, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "rtl-sh0a.bin", 0x010000, 0xe518b4e3, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "rtl-sl0a.bin", 0x010000, 0x896f0d36, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "rtl-c0.bin", 0x080000, 0xfb588d7c, 3 | BRF_GRA }, // 6 Background Tiles + { "rtl-c1.bin", 0x080000, 0xe5541bff, 3 | BRF_GRA }, // 7 + { "rtl-c2.bin", 0x080000, 0xfaa9ae27, 3 | BRF_GRA }, // 8 + { "rtl-c3.bin", 0x080000, 0x3a2343f6, 3 | BRF_GRA }, // 9 + + { "rtl-000.bin", 0x100000, 0x82a06870, 4 | BRF_GRA }, // 10 Sprites + { "rtl-010.bin", 0x100000, 0x417e7a56, 4 | BRF_GRA }, // 11 + { "rtl-020.bin", 0x100000, 0xf9a3f3a1, 4 | BRF_GRA }, // 12 + { "rtl-030.bin", 0x100000, 0x03528d95, 4 | BRF_GRA }, // 13 + + { "rtl-da.bin", 0x080000, 0xdbebd1ff, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(rtypelej) +STD_ROM_FN(rtypelej) + +struct BurnDriver BurnDrvRtypelej = { + "rtypeleoj", "rtypeleo", NULL, NULL, "1992", + "R-Type Leo (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, rtypelejRomInfo, rtypelejRomName, NULL, NULL, p2CommonInputInfo, RtypeleoDIPInfo, + rtypeleoInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Blade Master (World) + +static struct BurnRomInfo bmasterRomDesc[] = { + { "bm_d-h0-b.5m", 0x040000, 0x49b257c7, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "bm_d-l0-b.5f", 0x040000, 0xa873523e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bm_d-h1-b.5l", 0x010000, 0x082b7158, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bm_d-l1-b.5j", 0x010000, 0x6ff0c04e, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "bm_d-sh0.rom", 0x010000, 0x9f7c075b, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "bm_d-sl0.rom", 0x010000, 0x1fa87c89, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "bm_c0.rom", 0x040000, 0x2cc966b8, 3 | BRF_GRA }, // 6 Background Tiles + { "bm_c1.rom", 0x040000, 0x46df773e, 3 | BRF_GRA }, // 7 + { "bm_c2.rom", 0x040000, 0x05b867bd, 3 | BRF_GRA }, // 8 + { "bm_c3.rom", 0x040000, 0x0a2227a4, 3 | BRF_GRA }, // 9 + + { "bm_000.rom", 0x080000, 0x339fc9f3, 4 | BRF_GRA }, // 10 Sprites + { "bm_010.rom", 0x080000, 0x6a14377d, 4 | BRF_GRA }, // 11 + { "bm_020.rom", 0x080000, 0x31532198, 4 | BRF_GRA }, // 12 + { "bm_030.rom", 0x080000, 0xd1a041d3, 4 | BRF_GRA }, // 13 + + { "bm_da.rom", 0x080000, 0x62ce5798, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(bmaster) +STD_ROM_FN(bmaster) + +static INT32 bmasterRomLoad() +{ + return RomLoad(0x080000, 0x040000, 0x080000, 0, 0); +} + +static INT32 bmasterInit() +{ + return DrvInit(bmasterRomLoad, bomberman_decryption_table, 1, 0x80, 0x100000, 0x200000); +} + +struct BurnDriver BurnDrvBmaster = { + "bmaster", NULL, NULL, NULL, "1991", + "Blade Master (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, bmasterRomInfo, bmasterRomName, NULL, NULL, p2CommonInputInfo, BmasterDIPInfo, + bmasterInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Cross Blades! (Japan) + +static struct BurnRomInfo crossbldRomDesc[] = { + { "bm_d-h0.3h", 0x040000, 0xa28a5821, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "bm_d-l0.5h", 0x040000, 0xa504f1a0, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bm_d-h1.3e", 0x010000, 0x18da6c47, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bm_d-l1.5e", 0x010000, 0xa65c1b42, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "bm_d-sh0.rom", 0x010000, 0x9f7c075b, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "bm_d-sl0.rom", 0x010000, 0x1fa87c89, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "bm_c0.rom", 0x040000, 0x2cc966b8, 3 | BRF_GRA }, // 6 Background Tiles + { "bm_c1.rom", 0x040000, 0x46df773e, 3 | BRF_GRA }, // 7 + { "bm_c2.rom", 0x040000, 0x05b867bd, 3 | BRF_GRA }, // 8 + { "bm_c3.rom", 0x040000, 0x0a2227a4, 3 | BRF_GRA }, // 9 + + { "bm_000.rom", 0x080000, 0x339fc9f3, 4 | BRF_GRA }, // 10 Sprites + { "bm_010.rom", 0x080000, 0x6a14377d, 4 | BRF_GRA }, // 11 + { "bm_020.rom", 0x080000, 0x31532198, 4 | BRF_GRA }, // 12 + { "bm_030.rom", 0x080000, 0xd1a041d3, 4 | BRF_GRA }, // 13 + + { "bm_da.rom", 0x080000, 0x62ce5798, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(crossbld) +STD_ROM_FN(crossbld) + +struct BurnDriver BurnDrvCrossbld = { + "crossbld", "bmaster", NULL, NULL, "1991", + "Cross Blades! (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, crossbldRomInfo, crossbldRomName, NULL, NULL, p2CommonInputInfo, BmasterDIPInfo, + bmasterInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Mystic Riders (World) + +static struct BurnRomInfo mysticriRomDesc[] = { + { "mr-h0-b.bin", 0x040000, 0xd529f887, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "mr-l0-b.bin", 0x040000, 0xa457ab44, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mr-h1-b.bin", 0x010000, 0xe17649b9, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mr-l1-b.bin", 0x010000, 0xa87c62b4, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mr-sh0.bin", 0x010000, 0x50d335e4, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mr-sl0.bin", 0x010000, 0x0fa32721, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "mr-c0.bin", 0x040000, 0x872a8fad, 3 | BRF_GRA }, // 6 Background Tiles + { "mr-c1.bin", 0x040000, 0xd2ffb27a, 3 | BRF_GRA }, // 7 + { "mr-c2.bin", 0x040000, 0x62bff287, 3 | BRF_GRA }, // 8 + { "mr-c3.bin", 0x040000, 0xd0da62ab, 3 | BRF_GRA }, // 9 + + { "mr-o00.bin", 0x080000, 0xa0f9ce16, 4 | BRF_GRA }, // 10 Sprites + { "mr-o10.bin", 0x080000, 0x4e70a9e9, 4 | BRF_GRA }, // 11 + { "mr-o20.bin", 0x080000, 0xb9c468fc, 4 | BRF_GRA }, // 12 + { "mr-o30.bin", 0x080000, 0xcc32433a, 4 | BRF_GRA }, // 13 + + { "mr-da.bin", 0x040000, 0x1a11fc59, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(mysticri) +STD_ROM_FN(mysticri) + +static INT32 mysticriInit() +{ + return DrvInit(bmasterRomLoad, mysticri_decryption_table, 1, 0x80, 0x100000, 0x200000); +} + +struct BurnDriver BurnDrvMysticri = { + "mysticri", NULL, NULL, NULL, "1992", + "Mystic Riders (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, mysticriRomInfo, mysticriRomName, NULL, NULL, p2CommonInputInfo, MysticriDIPInfo, + mysticriInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Gun Hohki (Japan) + +static struct BurnRomInfo gunhohkiRomDesc[] = { + { "mr-h0.bin", 0x040000, 0x83352270, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "mr-l0.bin", 0x040000, 0x9db308ae, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mr-h1.bin", 0x010000, 0xc9532b60, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mr-l1.bin", 0x010000, 0x6349b520, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mr-sh0.bin", 0x010000, 0x50d335e4, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mr-sl0.bin", 0x010000, 0x0fa32721, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "mr-c0.bin", 0x040000, 0x872a8fad, 3 | BRF_GRA }, // 6 Background Tiles + { "mr-c1.bin", 0x040000, 0xd2ffb27a, 3 | BRF_GRA }, // 7 + { "mr-c2.bin", 0x040000, 0x62bff287, 3 | BRF_GRA }, // 8 + { "mr-c3.bin", 0x040000, 0xd0da62ab, 3 | BRF_GRA }, // 9 + + { "mr-o00.bin", 0x080000, 0xa0f9ce16, 4 | BRF_GRA }, // 10 Sprites + { "mr-o10.bin", 0x080000, 0x4e70a9e9, 4 | BRF_GRA }, // 11 + { "mr-o20.bin", 0x080000, 0xb9c468fc, 4 | BRF_GRA }, // 12 + { "mr-o30.bin", 0x080000, 0xcc32433a, 4 | BRF_GRA }, // 13 + + { "mr-da.bin", 0x040000, 0x1a11fc59, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(gunhohki) +STD_ROM_FN(gunhohki) + +struct BurnDriver BurnDrvGunhohki = { + "gunhohki", "mysticri", NULL, NULL, "1992", + "Gun Hohki (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, gunhohkiRomInfo, gunhohkiRomName, NULL, NULL, p2CommonInputInfo, MysticriDIPInfo, + mysticriInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Mystic Riders (bootleg?) + +static struct BurnRomInfo mysticribRomDesc[] = { + { "h0", 0x040000, 0xe38c1f56, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "l0", 0x040000, 0x77846e48, 1 | BRF_PRG | BRF_ESS }, // 1 + { "h1", 0x010000, 0x4dcb085b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "l1", 0x010000, 0x88df4f70, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "sh0", 0x010000, 0xfc7221ee, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "sl0", 0x010000, 0x65c809e6, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "mr-c0.bin", 0x040000, 0x872a8fad, 3 | BRF_GRA }, // 6 Background Tiles + { "mr-c1.bin", 0x040000, 0xd2ffb27a, 3 | BRF_GRA }, // 7 + { "mr-c2.bin", 0x040000, 0x62bff287, 3 | BRF_GRA }, // 8 + { "mr-c3.bin", 0x040000, 0xd0da62ab, 3 | BRF_GRA }, // 9 + + { "mr-o00.bin", 0x080000, 0xa0f9ce16, 4 | BRF_GRA }, // 10 Sprites + { "mr-o10.bin", 0x080000, 0x4e70a9e9, 4 | BRF_GRA }, // 11 + { "mr-o20.bin", 0x080000, 0xb9c468fc, 4 | BRF_GRA }, // 12 + { "mr-o30.bin", 0x080000, 0xcc32433a, 4 | BRF_GRA }, // 13 + + { "mr-da.bin", 0x040000, 0x1a11fc59, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(mysticrib) +STD_ROM_FN(mysticrib) + +struct BurnDriver BurnDrvMysticrib = { + "mysticrib", "mysticri", NULL, NULL, "1992", + "Mystic Riders (bootleg?)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_HORSHOOT, 0, + NULL, mysticribRomInfo, mysticribRomName, NULL, NULL, p2CommonInputInfo, MysticriDIPInfo, + mysticriInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Gunforce - Battle Fire Engulfed Terror Island (World) + +static struct BurnRomInfo gunforceRomDesc[] = { + { "gf_h0-c.5m", 0x020000, 0xc09bb634, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "gf_l0-c.5f", 0x020000, 0x1bef6f7d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gf_h1-c.5l", 0x020000, 0xc84188b7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gf_l1-c.5j", 0x020000, 0xb189f72a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "gf_sh0.rom", 0x010000, 0x3f8f16e0, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "gf_sl0.rom", 0x010000, 0xdb0b13a3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "gf_c0.rom", 0x040000, 0xb3b74979, 3 | BRF_GRA }, // 6 Background Tiles + { "gf_c1.rom", 0x040000, 0xf5c8590a, 3 | BRF_GRA }, // 7 + { "gf_c2.rom", 0x040000, 0x30f9fb64, 3 | BRF_GRA }, // 8 + { "gf_c3.rom", 0x040000, 0x87b3e621, 3 | BRF_GRA }, // 9 + + { "gf_000.rom", 0x040000, 0x209e8e8d, 4 | BRF_GRA }, // 10 Sprites + { "gf_010.rom", 0x040000, 0x6e6e7808, 4 | BRF_GRA }, // 11 + { "gf_020.rom", 0x040000, 0x6f5c3cb0, 4 | BRF_GRA }, // 12 + { "gf_030.rom", 0x040000, 0x18978a9f, 4 | BRF_GRA }, // 13 + + { "gf-da.rom", 0x020000, 0x933ba935, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(gunforce) +STD_ROM_FN(gunforce) + +static INT32 gunforceRomLoad() +{ + return RomLoad(0x040000, 0x040000, 0x040000, 0, 0); +} + +static INT32 gunforceInit() +{ + return DrvInit(gunforceRomLoad, gunforce_decryption_table, 1, 0x80, 0x100000, 0x100000); +} + +struct BurnDriver BurnDrvGunforce = { + "gunforce", NULL, NULL, NULL, "1991", + "Gunforce - Battle Fire Engulfed Terror Island (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_PLATFORM, 0, + NULL, gunforceRomInfo, gunforceRomName, NULL, NULL, p2CommonInputInfo, GunforceDIPInfo, + gunforceInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Gunforce - Battle Fire Engulfed Terror Island (Japan) + +static struct BurnRomInfo gunforcejRomDesc[] = { + { "gfb_h0-e.5m", 0x020000, 0x43c36e0f, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "gfb_l0-e.5f", 0x020000, 0x24a558d8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gfb_h1-e.5l", 0x020000, 0xd9744f5d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gfb_l1-e.5j", 0x020000, 0xa0f7b61b, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "gf_sh0.rom", 0x010000, 0x3f8f16e0, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "gf_sl0.rom", 0x010000, 0xdb0b13a3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "gf_c0.rom", 0x040000, 0xb3b74979, 3 | BRF_GRA }, // 6 Background Tiles + { "gf_c1.rom", 0x040000, 0xf5c8590a, 3 | BRF_GRA }, // 7 + { "gf_c2.rom", 0x040000, 0x30f9fb64, 3 | BRF_GRA }, // 8 + { "gf_c3.rom", 0x040000, 0x87b3e621, 3 | BRF_GRA }, // 9 + + { "gf_000.rom", 0x040000, 0x209e8e8d, 4 | BRF_GRA }, // 10 Sprites + { "gf_010.rom", 0x040000, 0x6e6e7808, 4 | BRF_GRA }, // 11 + { "gf_020.rom", 0x040000, 0x6f5c3cb0, 4 | BRF_GRA }, // 12 + { "gf_030.rom", 0x040000, 0x18978a9f, 4 | BRF_GRA }, // 13 + + { "gf-da.rom", 0x020000, 0x933ba935, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(gunforcej) +STD_ROM_FN(gunforcej) + +struct BurnDriver BurnDrvGunforcej = { + "gunforcej", "gunforce", NULL, NULL, "1991", + "Gunforce - Battle Fire Engulfed Terror Island (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_PLATFORM, 0, + NULL, gunforcejRomInfo, gunforcejRomName, NULL, NULL, p2CommonInputInfo, GunforceDIPInfo, + gunforceInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Gunforce - Battle Fire Engulfed Terror Island (US) + +static struct BurnRomInfo gunforceuRomDesc[] = { + { "gf_h0-d.5m", 0x020000, 0xa6db7b5c, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "gf_l0-d.5f", 0x020000, 0x82cf55f6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gf_h1-d.5l", 0x020000, 0x08a3736c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gf_l1-d.5j", 0x020000, 0x435f524f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "gf_sh0.rom", 0x010000, 0x3f8f16e0, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "gf_sl0.rom", 0x010000, 0xdb0b13a3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "gf_c0.rom", 0x040000, 0xb3b74979, 3 | BRF_GRA }, // 6 Background Tiles + { "gf_c1.rom", 0x040000, 0xf5c8590a, 3 | BRF_GRA }, // 7 + { "gf_c2.rom", 0x040000, 0x30f9fb64, 3 | BRF_GRA }, // 8 + { "gf_c3.rom", 0x040000, 0x87b3e621, 3 | BRF_GRA }, // 9 + + { "gf_000.rom", 0x040000, 0x209e8e8d, 4 | BRF_GRA }, // 10 Sprites + { "gf_010.rom", 0x040000, 0x6e6e7808, 4 | BRF_GRA }, // 11 + { "gf_020.rom", 0x040000, 0x6f5c3cb0, 4 | BRF_GRA }, // 12 + { "gf_030.rom", 0x040000, 0x18978a9f, 4 | BRF_GRA }, // 13 + + { "gf-da.rom", 0x020000, 0x933ba935, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(gunforceu) +STD_ROM_FN(gunforceu) + +struct BurnDriver BurnDrvGunforceu = { + "gunforceu", "gunforce", NULL, NULL, "1991", + "Gunforce - Battle Fire Engulfed Terror Island (US)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_PLATFORM, 0, + NULL, gunforceuRomInfo, gunforceuRomName, NULL, NULL, p2CommonInputInfo, GunforceDIPInfo, + gunforceInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Undercover Cops (World) + +static struct BurnRomInfo uccopsRomDesc[] = { + { "uc_h0.rom", 0x040000, 0x240aa5f7, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "uc_l0.rom", 0x040000, 0xdf9a4826, 1 | BRF_PRG | BRF_ESS }, // 1 + { "uc_h1.rom", 0x020000, 0x8d29bcd6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "uc_l1.rom", 0x020000, 0xa8a402d8, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "uc_sh0.rom", 0x010000, 0xdf90b198, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "uc_sl0.rom", 0x010000, 0x96c11aac, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "uc_w38m.rom", 0x080000, 0x130a40e5, 3 | BRF_GRA }, // 6 Background Tiles + { "uc_w39m.rom", 0x080000, 0xe42ca144, 3 | BRF_GRA }, // 7 + { "uc_w40m.rom", 0x080000, 0xc2961648, 3 | BRF_GRA }, // 8 + { "uc_w41m.rom", 0x080000, 0xf5334b80, 3 | BRF_GRA }, // 9 + + { "uc_k16m.rom", 0x100000, 0x4a225f09, 4 | BRF_GRA }, // 10 Sprites + { "uc_k17m.rom", 0x100000, 0xe4ed9a54, 4 | BRF_GRA }, // 11 + { "uc_k18m.rom", 0x100000, 0xa626eb12, 4 | BRF_GRA }, // 12 + { "uc_k19m.rom", 0x100000, 0x5df46549, 4 | BRF_GRA }, // 13 + + { "uc_w42.rom", 0x080000, 0xd17d3fd6, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(uccops) +STD_ROM_FN(uccops) + +static INT32 uccopsRomLoad() +{ + return RomLoad(0x080000, 0x080000, 0x100000, 0, 0); +} + +static INT32 uccopsInit() +{ + return DrvInit(uccopsRomLoad, dynablaster_decryption_table, 1, 0x80, 0x200000, 0x400000); +} + +struct BurnDriver BurnDrvUccops = { + "uccops", NULL, NULL, NULL, "1992", + "Undercover Cops (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, uccopsRomInfo, uccopsRomName, NULL, NULL, p3CommonInputInfo, UccopsDIPInfo, + uccopsInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Undercover Cops (US) + +static struct BurnRomInfo uccopsuRomDesc[] = { + { "uc_h0.rom", 0x040000, 0x240aa5f7, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "uc_l0.rom", 0x040000, 0xdf9a4826, 1 | BRF_PRG | BRF_ESS }, // 1 + { "uc_h1-g.rom", 0x020000, 0x6b8ca2de, 1 | BRF_PRG | BRF_ESS }, // 2 + { "uc_l1-g.rom", 0x020000, 0x2bdec7dd, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "uc_sh0.rom", 0x010000, 0xdf90b198, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "uc_sl0.rom", 0x010000, 0x96c11aac, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "uc_w38m.rom", 0x080000, 0x130a40e5, 3 | BRF_GRA }, // 6 Background Tiles + { "uc_w39m.rom", 0x080000, 0xe42ca144, 3 | BRF_GRA }, // 7 + { "uc_w40m.rom", 0x080000, 0xc2961648, 3 | BRF_GRA }, // 8 + { "uc_w41m.rom", 0x080000, 0xf5334b80, 3 | BRF_GRA }, // 9 + + { "uc_k16m.rom", 0x100000, 0x4a225f09, 4 | BRF_GRA }, // 10 Sprites + { "uc_k17m.rom", 0x100000, 0xe4ed9a54, 4 | BRF_GRA }, // 11 + { "uc_k18m.rom", 0x100000, 0xa626eb12, 4 | BRF_GRA }, // 12 + { "uc_k19m.rom", 0x100000, 0x5df46549, 4 | BRF_GRA }, // 13 + + { "uc_w42.rom", 0x080000, 0xd17d3fd6, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(uccopsu) +STD_ROM_FN(uccopsu) + +struct BurnDriver BurnDrvUccopsu = { + "uccopsu", "uccops", NULL, NULL, "1992", + "Undercover Cops (US)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, uccopsuRomInfo, uccopsuRomName, NULL, NULL, p3CommonInputInfo, UccopsDIPInfo, + uccopsInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Undercover Cops (Alpha Renewal Version) + +static struct BurnRomInfo uccopsarRomDesc[] = { + { "uc_h0_a.ic28", 0x040000, 0x9e17cada, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "uc_l0_a.ic39", 0x040000, 0x4a4e3208, 1 | BRF_PRG | BRF_ESS }, // 1 + { "uc_h1.ic27", 0x020000, 0x79d79742, 1 | BRF_PRG | BRF_ESS }, // 2 + { "uc_l1.ic38", 0x020000, 0x37211581, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "uc_sh0.ic30", 0x010000, 0xf0ca1b03, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "uc_sl0.ic31", 0x010000, 0xd1661723, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "uc_c0.ic26", 0x080000, 0x6a419a36, 3 | BRF_GRA }, // 6 Background Tiles + { "uc_c1.ic25", 0x080000, 0xd703ecc7, 3 | BRF_GRA }, // 7 + { "uc_c2.ic24", 0x080000, 0x96397ac6, 3 | BRF_GRA }, // 8 + { "uc_c3.ic23", 0x080000, 0x5d07d10d, 3 | BRF_GRA }, // 9 + + { "uc_030.ic37", 0x100000, 0x97f7775e, 4 | BRF_GRA }, // 10 Sprites + { "uc_020.ic36", 0x100000, 0x5e0b1d65, 4 | BRF_GRA }, // 11 + { "uc_010.ic35", 0x100000, 0xbdc224b3, 4 | BRF_GRA }, // 12 + { "uc_000.ic34", 0x100000, 0x7526daec, 4 | BRF_GRA }, // 13 + + { "uc_da.bin", 0x080000, 0x0b2855e9, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(uccopsar) +STD_ROM_FN(uccopsar) + +struct BurnDriver BurnDrvUccopsar = { + "uccopsar", "uccops", NULL, NULL, "1992", + "Undercover Cops (Alpha Renewal Version)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, uccopsarRomInfo, uccopsarRomName, NULL, NULL, p3CommonInputInfo, UccopsDIPInfo, + uccopsInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Undercover Cops (Japan) + +static struct BurnRomInfo uccopsjRomDesc[] = { + { "uc_h0_a.ic28", 0x040000, 0x9e17cada, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "uc_l0_a.ic39", 0x040000, 0x4a4e3208, 1 | BRF_PRG | BRF_ESS }, // 1 + { "uc_h1_a.ic27", 0x020000, 0x83f78dea, 1 | BRF_PRG | BRF_ESS }, // 2 + { "uc_l1_a.ic38", 0x020000, 0x19628280, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "uc_sh0.ic30", 0x010000, 0xf0ca1b03, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "uc_sl0.ic31", 0x010000, 0xd1661723, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "uc_c0.ic26", 0x080000, 0x6a419a36, 3 | BRF_GRA }, // 6 Background Tiles + { "uc_c1.ic25", 0x080000, 0xd703ecc7, 3 | BRF_GRA }, // 7 + { "uc_c2.ic24", 0x080000, 0x96397ac6, 3 | BRF_GRA }, // 8 + { "uc_c3.ic23", 0x080000, 0x5d07d10d, 3 | BRF_GRA }, // 9 + + { "uc_030.ic37", 0x100000, 0x97f7775e, 4 | BRF_GRA }, // 10 Sprites + { "uc_020.ic36", 0x100000, 0x5e0b1d65, 4 | BRF_GRA }, // 11 + { "uc_010.ic35", 0x100000, 0xbdc224b3, 4 | BRF_GRA }, // 12 + { "uc_000.ic34", 0x100000, 0x7526daec, 4 | BRF_GRA }, // 13 + + { "uc_da.bin", 0x080000, 0x0b2855e9, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(uccopsj) +STD_ROM_FN(uccopsj) + +struct BurnDriver BurnDrvUccopsj = { + "uccopsj", "uccops", NULL, NULL, "1992", + "Undercover Cops (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, uccopsjRomInfo, uccopsjRomName, NULL, NULL, p3CommonInputInfo, UccopsDIPInfo, + uccopsInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Gunforce 2 (US) + +static struct BurnRomInfo gunforc2RomDesc[] = { + { "a2-h0-a.6h", 0x040000, 0x49965e22, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "a2-l0-a.8h", 0x040000, 0x8c88b278, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a2-h1-a.6f", 0x040000, 0x34280b88, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a2-l1-a.8f", 0x040000, 0xc8c13f51, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "a2_sh0.3l", 0x010000, 0x2e2d103d, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "a2_sl0.5l", 0x010000, 0x2287e0b3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "a2_c0.1a", 0x080000, 0x68b8f574, 3 | BRF_GRA }, // 6 Background Tiles + { "a2_c1.1b", 0x080000, 0x0b9efe67, 3 | BRF_GRA }, // 7 + { "a2_c2.3a", 0x080000, 0x7a9e9978, 3 | BRF_GRA }, // 8 + { "a2_c3.3b", 0x080000, 0x1395ee6d, 3 | BRF_GRA }, // 9 + + { "a2_000.8a", 0x100000, 0x38e03147, 4 | BRF_GRA }, // 10 Sprites + { "a2_010.8b", 0x100000, 0x1d5b05f8, 4 | BRF_GRA }, // 11 + { "a2_020.8c", 0x100000, 0xf2f461cc, 4 | BRF_GRA }, // 12 + { "a2_030.8d", 0x100000, 0x97609d9d, 4 | BRF_GRA }, // 13 + + { "a2_da.1l", 0x100000, 0x3c8cdb6a, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(gunforc2) +STD_ROM_FN(gunforc2) + +static INT32 gunforc2RomLoad() +{ + return RomLoad(0x100000, 0x080000, 0x100000, 0, 0); +} + +static INT32 gunforc2Init() +{ + INT32 nRet; + + nRet = DrvInit(gunforc2RomLoad, lethalth_decryption_table, 1, 0x80, 0x200000, 0x400000); + + if (nRet == 0) { + memcpy (DrvV33ROM + 0x80000, DrvV33ROM + 0x100000, 0x20000); + } + + return nRet; +} + +struct BurnDriver BurnDrvGunforc2 = { + "gunforc2", NULL, NULL, NULL, "1994", + "Gunforce 2 (US)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_PLATFORM, 0, + NULL, gunforc2RomInfo, gunforc2RomName, NULL, NULL, p2CommonInputInfo, Gunforc2DIPInfo, + gunforc2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Geostorm (Japan) + +static struct BurnRomInfo geostormRomDesc[] = { + { "geo-h0.bin", 0x040000, 0x9be58d09, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "geo-l0.bin", 0x040000, 0x59abb75d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a2-h1-a.6f", 0x040000, 0x34280b88, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a2-l1-a.8f", 0x040000, 0xc8c13f51, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "a2_sh0.3l", 0x010000, 0x2e2d103d, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "a2_sl0.5l", 0x010000, 0x2287e0b3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "a2_c0.1a", 0x080000, 0x68b8f574, 3 | BRF_GRA }, // 6 Background Tiles + { "a2_c1.1b", 0x080000, 0x0b9efe67, 3 | BRF_GRA }, // 7 + { "a2_c2.3a", 0x080000, 0x7a9e9978, 3 | BRF_GRA }, // 8 + { "a2_c3.3b", 0x080000, 0x1395ee6d, 3 | BRF_GRA }, // 9 + + { "a2_000.8a", 0x100000, 0x38e03147, 4 | BRF_GRA }, // 10 Sprites + { "a2_010.8b", 0x100000, 0x1d5b05f8, 4 | BRF_GRA }, // 11 + { "a2_020.8c", 0x100000, 0xf2f461cc, 4 | BRF_GRA }, // 12 + { "a2_030.8d", 0x100000, 0x97609d9d, 4 | BRF_GRA }, // 13 + + { "a2_da.1l", 0x100000, 0x3c8cdb6a, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(geostorm) +STD_ROM_FN(geostorm) + +struct BurnDriver BurnDrvGeostorm = { + "geostorm", "gunforc2", NULL, NULL, "1994", + "Geostorm (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_PLATFORM, 0, + NULL, geostormRomInfo, geostormRomName, NULL, NULL, p2CommonInputInfo, Gunforc2DIPInfo, + gunforc2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Ninja Baseball Batman (US) + +static struct BurnRomInfo nbbatmanRomDesc[] = { + { "a1-h0-a.34", 0x040000, 0x24a9b794, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "a1-l0-a.31", 0x040000, 0x846d7716, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a1-h1-.33", 0x040000, 0x3ce2aab5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a1-l1-.32", 0x040000, 0x116d9bcc, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "a1-sh0-.14", 0x010000, 0xb7fae3e6, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "a1-sl0-.17", 0x010000, 0xb26d54fc, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "lh534k0c.9", 0x080000, 0x314a0c6d, 3 | BRF_GRA }, // 6 Background Tiles + { "lh534k0e.10", 0x080000, 0xdc31675b, 3 | BRF_GRA }, // 7 + { "lh534k0f.11", 0x080000, 0xe15d8bfb, 3 | BRF_GRA }, // 8 + { "lh534k0g.12", 0x080000, 0x888d71a3, 3 | BRF_GRA }, // 9 + + { "lh538393.42", 0x100000, 0x26cdd224, 4 | BRF_GRA }, // 10 Sprites + { "lh538394.43", 0x100000, 0x4bbe94fa, 4 | BRF_GRA }, // 11 + { "lh538395.44", 0x100000, 0x2a533b5e, 4 | BRF_GRA }, // 12 + { "lh538396.45", 0x100000, 0x863a66fa, 4 | BRF_GRA }, // 13 + + { "lh534k0k.8", 0x080000, 0x735e6380, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(nbbatman) +STD_ROM_FN(nbbatman) + +static INT32 nbbatmanInit() +{ + INT32 nRet; + + nRet = DrvInit(gunforc2RomLoad, leagueman_decryption_table, 1, 0x80, 0x200000, 0x400000); + + if (nRet == 0) { + memcpy (DrvV33ROM + 0x80000, DrvV33ROM + 0x100000, 0x20000); + } + + return nRet; +} + +struct BurnDriver BurnDrvNbbatman = { + "nbbatman", NULL, NULL, NULL, "1993", + "Ninja Baseball Batman (US)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, nbbatmanRomInfo, nbbatmanRomName, NULL, NULL, p4CommonInputInfo, NbbatmanDIPInfo, + nbbatmanInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Yakyuu Kakutou League-Man (Japan) + +static struct BurnRomInfo leaguemnRomDesc[] = { + { "lma1-h0.34", 0x040000, 0x47c54204, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "lma1-l0.31", 0x040000, 0x1d062c82, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a1-h1-.33", 0x040000, 0x3ce2aab5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a1-l1-.32", 0x040000, 0x116d9bcc, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "a1-sh0-.14", 0x010000, 0xb7fae3e6, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "a1-sl0-.17", 0x010000, 0xb26d54fc, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "lh534k0c.9", 0x080000, 0x314a0c6d, 3 | BRF_GRA }, // 6 Background Tiles + { "lh534k0e.10", 0x080000, 0xdc31675b, 3 | BRF_GRA }, // 7 + { "lh534k0f.11", 0x080000, 0xe15d8bfb, 3 | BRF_GRA }, // 8 + { "lh534k0g.12", 0x080000, 0x888d71a3, 3 | BRF_GRA }, // 9 + + { "lh538393.42", 0x100000, 0x26cdd224, 4 | BRF_GRA }, // 10 Sprites + { "lh538394.43", 0x100000, 0x4bbe94fa, 4 | BRF_GRA }, // 11 + { "lh538395.44", 0x100000, 0x2a533b5e, 4 | BRF_GRA }, // 12 + { "lh538396.45", 0x100000, 0x863a66fa, 4 | BRF_GRA }, // 13 + + { "lh534k0k.8", 0x080000, 0x735e6380, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(leaguemn) +STD_ROM_FN(leaguemn) + +struct BurnDriver BurnDrvLeaguemn = { + "leaguemn", "nbbatman", NULL, NULL, "1993", + "Yakyuu Kakutou League-Man (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IREM_M92, GBF_SCRFIGHT, 0, + NULL, leaguemnRomInfo, leaguemnRomName, NULL, NULL, p4CommonInputInfo, NbbatmanDIPInfo, + nbbatmanInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Lethal Thunder (World) + +static struct BurnRomInfo lethalthRomDesc[] = { + { "lt_d-h0.rom", 0x020000, 0x20c68935, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "lt_d-l0.rom", 0x020000, 0xe1432fb3, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lt_d-h1.rom", 0x020000, 0xd7dd3d48, 1 | BRF_PRG | BRF_ESS }, // 2 + { "lt_d-l1.rom", 0x020000, 0xb94b3bd8, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "lt_d-sh0.rom", 0x010000, 0xaf5b224f, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "lt_d-sl0.rom", 0x010000, 0xcb3faac3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "lt_7a.rom", 0x040000, 0xada0fd50, 3 | BRF_GRA }, // 6 Background Tiles + { "lt_7b.rom", 0x040000, 0xd2596883, 3 | BRF_GRA }, // 7 + { "lt_7d.rom", 0x040000, 0x2de637ef, 3 | BRF_GRA }, // 8 + { "lt_7h.rom", 0x040000, 0x9f6585cd, 3 | BRF_GRA }, // 9 + + { "lt_7j.rom", 0x040000, 0xbaf8863e, 4 | BRF_GRA }, // 10 Sprites + { "lt_7l.rom", 0x040000, 0x40fd50af, 4 | BRF_GRA }, // 11 + { "lt_7s.rom", 0x040000, 0xc8e970df, 4 | BRF_GRA }, // 12 + { "lt_7y.rom", 0x040000, 0xf5436708, 4 | BRF_GRA }, // 13 + + { "lt_8a.rom", 0x040000, 0x357762a2, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(lethalth) +STD_ROM_FN(lethalth) + +static INT32 lethalthRomLoad() +{ + m92_kludge = 1; + return RomLoad(0x040000, 0x040000, 0x040000, 0, 0); +} + +static INT32 lethalthInit() +{ + return DrvInit(lethalthRomLoad, lethalth_decryption_table, 0, 0x20, 0x100000, 0x100000); +} + +struct BurnDriver BurnDrvLethalth = { + "lethalth", NULL, NULL, NULL, "1991", + "Lethal Thunder (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M92, GBF_VERSHOOT, 0, + NULL, lethalthRomInfo, lethalthRomName, NULL, NULL, p2CommonInputInfo, LethalthDIPInfo, + lethalthInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Thunder Blaster (Japan) + +static struct BurnRomInfo thndblstRomDesc[] = { + { "lt_d-h0j.rom", 0x020000, 0xdc218a18, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "lt_d-l0j.rom", 0x020000, 0xae9a3f81, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lt_d-h1.rom", 0x020000, 0xd7dd3d48, 1 | BRF_PRG | BRF_ESS }, // 2 + { "lt_d-l1.rom", 0x020000, 0xb94b3bd8, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "lt_d-sh0.rom", 0x010000, 0xaf5b224f, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "lt_d-sl0.rom", 0x010000, 0xcb3faac3, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "lt_7a.rom", 0x040000, 0xada0fd50, 3 | BRF_GRA }, // 6 Background Tiles + { "lt_7b.rom", 0x040000, 0xd2596883, 3 | BRF_GRA }, // 7 + { "lt_7d.rom", 0x040000, 0x2de637ef, 3 | BRF_GRA }, // 8 + { "lt_7h.rom", 0x040000, 0x9f6585cd, 3 | BRF_GRA }, // 9 + + { "lt_7j.rom", 0x040000, 0xbaf8863e, 4 | BRF_GRA }, // 10 Sprites + { "lt_7l.rom", 0x040000, 0x40fd50af, 4 | BRF_GRA }, // 11 + { "lt_7s.rom", 0x040000, 0xc8e970df, 4 | BRF_GRA }, // 12 + { "lt_7y.rom", 0x040000, 0xf5436708, 4 | BRF_GRA }, // 13 + + { "lt_8a.rom", 0x040000, 0x357762a2, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(thndblst) +STD_ROM_FN(thndblst) + +struct BurnDriver BurnDrvThndblst = { + "thndblst", "lethalth", NULL, NULL, "1991", + "Thunder Blaster (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_IREM_M92, GBF_VERSHOOT, 0, + NULL, thndblstRomInfo, thndblstRomName, NULL, NULL, p2CommonInputInfo, LethalthDIPInfo, + lethalthInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Dream Soccer '94 + +static struct BurnRomInfo dsoccr94RomDesc[] = { + { "ds_h0-c.rom", 0x040000, 0xd01d3fd7, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "ds_l0-c.rom", 0x040000, 0x8af0afe2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ds_h1-c.rom", 0x040000, 0x6109041b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ds_l1-c.rom", 0x040000, 0x97a01f6b, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ds_sh0.rom", 0x010000, 0x23fe6ffc, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "ds_sl0.rom", 0x010000, 0x768132e5, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "ds_c00.rom", 0x100000, 0x2d31d418, 3 | BRF_GRA }, // 6 Background Tiles + { "ds_c10.rom", 0x100000, 0x57f7bcd3, 3 | BRF_GRA }, // 7 + { "ds_c01.rom", 0x100000, 0x9d31a464, 3 | BRF_GRA }, // 8 + { "ds_c11.rom", 0x100000, 0xa372e79f, 3 | BRF_GRA }, // 9 + + { "ds_000.rom", 0x100000, 0x366b3e29, 4 | BRF_GRA }, // 10 Sprites + { "ds_010.rom", 0x100000, 0x28a4cc40, 4 | BRF_GRA }, // 11 + { "ds_020.rom", 0x100000, 0x5a310f7f, 4 | BRF_GRA }, // 12 + { "ds_030.rom", 0x100000, 0x328b1f45, 4 | BRF_GRA }, // 13 + + { "ds_da0.rom", 0x100000, 0x67fc52fd, 5 | BRF_SND }, // 14 Irem GA20 Samples +}; + +STD_ROM_PICK(dsoccr94) +STD_ROM_FN(dsoccr94) + +static INT32 NullInit() +{ + return 1; +} + +struct BurnDriver BurnDrvDsoccr94 = { + "dsoccr94", NULL, NULL, NULL, "1994", + "Dream Soccer '94\0", "Imperfect sound and graphics", "Irem (Data East Corporation license)", "M107", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_IREM_M92, GBF_SPORTSFOOTBALL, 0, + NULL, dsoccr94RomInfo, dsoccr94RomName, NULL, NULL, p4CommonInputInfo, NULL, + NullInit, DrvExit, DrvFrame, DrvReDraw, NULL, NULL, 0, + 256, 256, 4, 3 +}; + + +// Dream Soccer '94 (Japan) + +static struct BurnRomInfo dsoccr94jRomDesc[] = { + { "a3_-h0-e.bin", 0x040000, 0x8de1dbcd, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "a3_-l0-e.bin", 0x040000, 0xd3df8bfd, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ds_h1-c.rom", 0x040000, 0x6109041b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ds_l1-c.rom", 0x040000, 0x97a01f6b, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ds_sh0.rom", 0x010000, 0x23fe6ffc, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "ds_sl0.rom", 0x010000, 0x768132e5, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "c0.bin", 0x100000, 0x83ea8a47, 3 | BRF_GRA }, // 6 Background Tiles + { "c1.bin", 0x100000, 0x64063e6d, 3 | BRF_GRA }, // 7 + { "c2.bin", 0x100000, 0xcc1f621a, 3 | BRF_GRA }, // 8 + { "c3.bin", 0x100000, 0x515829e1, 3 | BRF_GRA }, // 9 + + { "a3-o00-w.bin", 0x080000, 0xb094e5ad, 4 | BRF_GRA }, // 10 Sprites + { "a3-o01-w.bin", 0x080000, 0x91f34018, 4 | BRF_GRA }, // 11 + { "a3-o10-w.bin", 0x080000, 0xedddeef4, 4 | BRF_GRA }, // 12 + { "a3-o11-w.bin", 0x080000, 0x274a9526, 4 | BRF_GRA }, // 13 + { "a3-o20-w.bin", 0x080000, 0x32064393, 4 | BRF_GRA }, // 14 + { "a3-o21-w.bin", 0x080000, 0x57bae3d9, 4 | BRF_GRA }, // 15 + { "a3-o30-w.bin", 0x080000, 0xbe838e2f, 4 | BRF_GRA }, // 16 + { "a3-o31-w.bin", 0x080000, 0xbf899f0d, 4 | BRF_GRA }, // 17 + + { "ds_da0.rom", 0x100000, 0x67fc52fd, 5 | BRF_SND }, // 18 Irem GA20 Samples +}; + +STD_ROM_PICK(dsoccr94j) +STD_ROM_FN(dsoccr94j) + +static INT32 dsoccr94jRomLoad() +{ + return RomLoad(0x100000, 0x100000, 0x100000, 1, 0); +} + +static INT32 dsoccr94jInit() +{ + return DrvInit(dsoccr94jRomLoad, dsoccr94_decryption_table, 1, 0x80, 0x400000, 0x400000); +} + +struct BurnDriver BurnDrvDsoccr94j = { + "dsoccr94j", "dsoccr94", NULL, NULL, "1994", + "Dream Soccer '94 (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IREM_M92, GBF_SPORTSFOOTBALL, 0, + NULL, dsoccr94jRomInfo, dsoccr94jRomName, NULL, NULL, p4CommonInputInfo, Dsoccr94jDIPInfo, + dsoccr94jInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Superior Soldiers (US) + +static struct BurnRomInfo ssoldierRomDesc[] = { + { "f3-h0-h.bin", 0x040000, 0xb63fb9da, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "f3-l0-h.bin", 0x040000, 0x419361a2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "f3-h1-a.bin", 0x020000, 0xe3d9f619, 1 | BRF_PRG | BRF_ESS }, // 2 + { "f3-l1-a.bin", 0x020000, 0x8cb5c396, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "f3_sh0.sh0", 0x010000, 0x90b55e5e, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "f3_sl0.sl0", 0x010000, 0x77c16d57, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "f3_w50.c0", 0x040000, 0x47e788ee, 3 | BRF_GRA }, // 6 Background Tiles + { "f3_w51.c1", 0x040000, 0x8e535e3f, 3 | BRF_GRA }, // 7 + { "f3_w52.c2", 0x040000, 0xa6eb2e56, 3 | BRF_GRA }, // 8 + { "f3_w53.c3", 0x040000, 0x2f992807, 3 | BRF_GRA }, // 9 + + { "f3_w37.000", 0x100000, 0xfd4cda03, 4 | BRF_GRA }, // 10 Sprites + { "f3_w38.001", 0x100000, 0x755bab10, 4 | BRF_GRA }, // 11 + { "f3_w39.010", 0x100000, 0xb21ced92, 4 | BRF_GRA }, // 12 + { "f3_w40.011", 0x100000, 0x2e906889, 4 | BRF_GRA }, // 13 + { "f3_w41.020", 0x100000, 0x02455d10, 4 | BRF_GRA }, // 14 + { "f3_w42.021", 0x100000, 0x124589b9, 4 | BRF_GRA }, // 15 + { "f3_w43.030", 0x100000, 0xdae7327a, 4 | BRF_GRA }, // 16 + { "f3_w44.031", 0x100000, 0xd0fc84ac, 4 | BRF_GRA }, // 17 + + { "f3_w95.da", 0x080000, 0xf7ca432b, 5 | BRF_SND }, // 18 Irem GA20 Samples +}; + +STD_ROM_PICK(ssoldier) +STD_ROM_FN(ssoldier) + +static INT32 ssoldierRomLoad() +{ + return RomLoad(0x080000, 0x040000, 0x200000, 1, 0); +} + +static INT32 ssoldierInit() +{ + m92_kludge = 1; + + return DrvInit(ssoldierRomLoad, psoldier_decryption_table, 1, 0x20, 0x100000, 0x800000); +} + +struct BurnDriver BurnDrvSsoldier = { + "ssoldier", NULL, NULL, NULL, "1993", + "Superior Soldiers (US)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_VSFIGHT, 0, + NULL, ssoldierRomInfo, ssoldierRomName, NULL, NULL, PsoldierInputInfo, PsoldierDIPInfo, + ssoldierInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Perfect Soldiers (Japan) + +static struct BurnRomInfo psoldierRomDesc[] = { + { "f3_h0-d.bin", 0x040000, 0x38f131fd, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "f3_l0-d.bin", 0x040000, 0x1662969c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "f3_h1-.bin", 0x040000, 0xc8d1947c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "f3_l1-.bin", 0x040000, 0x7b9492fc, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "f3_sh0.sh0", 0x010000, 0x90b55e5e, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "f3_sl0.sl0", 0x010000, 0x77c16d57, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "f3_w50.c0", 0x040000, 0x47e788ee, 3 | BRF_GRA }, // 6 Background Tiles + { "f3_w51.c1", 0x040000, 0x8e535e3f, 3 | BRF_GRA }, // 7 + { "f3_w52.c2", 0x040000, 0xa6eb2e56, 3 | BRF_GRA }, // 8 + { "f3_w53.c3", 0x040000, 0x2f992807, 3 | BRF_GRA }, // 9 + + { "f3_w37.000", 0x100000, 0xfd4cda03, 4 | BRF_GRA }, // 10 Sprites + { "f3_w38.001", 0x100000, 0x755bab10, 4 | BRF_GRA }, // 11 + { "f3_w39.010", 0x100000, 0xb21ced92, 4 | BRF_GRA }, // 12 + { "f3_w40.011", 0x100000, 0x2e906889, 4 | BRF_GRA }, // 13 + { "f3_w41.020", 0x100000, 0x02455d10, 4 | BRF_GRA }, // 14 + { "f3_w42.021", 0x100000, 0x124589b9, 4 | BRF_GRA }, // 15 + { "f3_w43.030", 0x100000, 0xdae7327a, 4 | BRF_GRA }, // 16 + { "f3_w44.031", 0x100000, 0xd0fc84ac, 4 | BRF_GRA }, // 17 + + { "f3_w95.da", 0x080000, 0xf7ca432b, 5 | BRF_SND }, // 18 Irem GA20 Samples +}; + +STD_ROM_PICK(psoldier) +STD_ROM_FN(psoldier) + +struct BurnDriver BurnDrvPsoldier = { + "psoldier", "ssoldier", NULL, NULL, "1993", + "Perfect Soldiers (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_VSFIGHT, 0, + NULL, psoldierRomInfo, psoldierRomName, NULL, NULL, PsoldierInputInfo, PsoldierDIPInfo, + ssoldierInit, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Major Title 2 (World) + +static struct BurnRomInfo majtitl2RomDesc[] = { + { "mt2-h0-b.5m", 0x040000, 0xb163b12e, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "mt2-l0-b.5f", 0x040000, 0x6f3b5d9d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "is-h1.5l", 0x040000, 0x9ba8e1f2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "is-l1.5j", 0x040000, 0xe4e00626, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mt2sh0", 0x010000, 0x1ecbea43, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mt2sl0", 0x010000, 0x8fd5b531, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "c0", 0x040000, 0x7e61e4b5, 3 | BRF_GRA }, // 6 Background Tiles + { "c1", 0x040000, 0x0a667564, 3 | BRF_GRA }, // 7 + { "c2", 0x040000, 0x5eb44312, 3 | BRF_GRA }, // 8 + { "c3", 0x040000, 0xf2866294, 3 | BRF_GRA }, // 9 + + { "k30", 0x100000, 0x8c9a2678, 4 | BRF_GRA }, // 10 Sprites + { "k31", 0x100000, 0x5455df78, 4 | BRF_GRA }, // 11 + { "k32", 0x100000, 0x3a258c41, 4 | BRF_GRA }, // 12 + { "k33", 0x100000, 0xc1e91a14, 4 | BRF_GRA }, // 13 + + { "da", 0x080000, 0x713b9e9f, 5 | BRF_SND }, // 14 Irem GA20 Samples + + { "mt2eep", 0x000800, 0x208af971, 6 | BRF_PRG | BRF_ESS }, // 15 EEPROM data + + { "pal16l8-m92-a-3m.ic11", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 16 plds + { "pal16l8-m92-a-7j.ic41", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 17 + { "pal16l8-m92-a-9j.ic51", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 18 + { "pal16l8-m92-b-2l.ic7", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 19 + { "pal16l8-m92-b-7h.ic47", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(majtitl2) +STD_ROM_FN(majtitl2) + +static INT32 majtitl2RomLoad() +{ + return RomLoad(0x100000, 0x040000, 0x100000, 0, 15); +} + +static INT32 majtitl2Init() +{ + m92_kludge = 2; + return DrvInit(majtitl2RomLoad, majtitl2_decryption_table, 1, 0x80, 0x100000, 0x400000); +} + +struct BurnDriver BurnDrvMajtitl2 = { + "majtitl2", NULL, NULL, NULL, "1992", + "Major Title 2 (World)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_IREM_M92, GBF_SPORTSMISC, 0, + NULL, majtitl2RomInfo, majtitl2RomName, NULL, NULL, p4CommonInputInfo, Majtitl2DIPInfo, + majtitl2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Major Title 2 (Japan) + +static struct BurnRomInfo majtitl2jRomDesc[] = { + { "mt2-h0", 0x040000, 0x8a8d71ad, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "mt2-l1", 0x040000, 0xdd4fff51, 1 | BRF_PRG | BRF_ESS }, // 1 + { "is-h1.5l", 0x040000, 0x9ba8e1f2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "is-l1.5j", 0x040000, 0xe4e00626, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mt2sh0", 0x010000, 0x1ecbea43, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mt2sl0", 0x010000, 0x8fd5b531, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "c0", 0x040000, 0x7e61e4b5, 3 | BRF_GRA }, // 6 Background Tiles + { "c1", 0x040000, 0x0a667564, 3 | BRF_GRA }, // 7 + { "c2", 0x040000, 0x5eb44312, 3 | BRF_GRA }, // 8 + { "c3", 0x040000, 0xf2866294, 3 | BRF_GRA }, // 9 + + { "k30", 0x100000, 0x8c9a2678, 4 | BRF_GRA }, // 10 Sprites + { "k31", 0x100000, 0x5455df78, 4 | BRF_GRA }, // 11 + { "k32", 0x100000, 0x3a258c41, 4 | BRF_GRA }, // 12 + { "k33", 0x100000, 0xc1e91a14, 4 | BRF_GRA }, // 13 + + { "da", 0x080000, 0x713b9e9f, 5 | BRF_SND }, // 14 Irem GA20 Samples + + { "mt2eep", 0x000800, 0x208af971, 6 | BRF_PRG | BRF_ESS }, // 15 EEPROM data + + { "pal16l8-m92-a-3m.ic11", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 16 plds + { "pal16l8-m92-a-7j.ic41", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 17 + { "pal16l8-m92-a-9j.ic51", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 18 + { "pal16l8-m92-b-2l.ic7", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 19 + { "pal16l8-m92-b-7h.ic47", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(majtitl2j) +STD_ROM_FN(majtitl2j) + +struct BurnDriver BurnDrvMajtitl2j = { + "majtitl2j", "majtitl2", NULL, NULL, "1992", + "Major Title 2 (Japan)\0", "Imperfect sound and graphics", "Irem", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_SPORTSMISC, 0, + NULL, majtitl2jRomInfo, majtitl2jRomName, NULL, NULL, p4CommonInputInfo, Majtitl2DIPInfo, + majtitl2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// The Irem Skins Game (US set 1) + +static struct BurnRomInfo skingameRomDesc[] = { + { "is-h0-d.5m", 0x040000, 0x80940abb, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "is-l0-d.5f", 0x040000, 0xb84beed6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "is-h1.5l", 0x040000, 0x9ba8e1f2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "is-l1.5j", 0x040000, 0xe4e00626, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mt2sh0", 0x010000, 0x1ecbea43, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mt2sl0", 0x010000, 0x8fd5b531, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "c0", 0x040000, 0x7e61e4b5, 3 | BRF_GRA }, // 6 Background Tiles + { "c1", 0x040000, 0x0a667564, 3 | BRF_GRA }, // 7 + { "c2", 0x040000, 0x5eb44312, 3 | BRF_GRA }, // 8 + { "c3", 0x040000, 0xf2866294, 3 | BRF_GRA }, // 9 + + { "k30", 0x100000, 0x8c9a2678, 4 | BRF_GRA }, // 10 Sprites + { "k31", 0x100000, 0x5455df78, 4 | BRF_GRA }, // 11 + { "k32", 0x100000, 0x3a258c41, 4 | BRF_GRA }, // 12 + { "k33", 0x100000, 0xc1e91a14, 4 | BRF_GRA }, // 13 + + { "da", 0x080000, 0x713b9e9f, 5 | BRF_SND }, // 14 Irem GA20 Samples + + { "mt2eep", 0x000800, 0x208af971, 6 | BRF_PRG | BRF_ESS }, // 15 EEPROM data + + { "pal16l8-m92-a-3m.ic11", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 16 plds + { "pal16l8-m92-a-7j.ic41", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 17 + { "pal16l8-m92-a-9j.ic51", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 18 + { "pal16l8-m92-b-2l.ic7", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 19 + { "pal16l8-m92-b-7h.ic47", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(skingame) +STD_ROM_FN(skingame) + +struct BurnDriver BurnDrvSkingame = { + "skingame", "majtitl2", NULL, NULL, "1992", + "The Irem Skins Game (US set 1)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_SPORTSMISC, 0, + NULL, skingameRomInfo, skingameRomName, NULL, NULL, p4CommonInputInfo, Majtitl2DIPInfo, + majtitl2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// The Irem Skins Game (US set 2) + +static struct BurnRomInfo skingame2RomDesc[] = { + { "mt2-h0-a.5m", 0x040000, 0x7c6dbbc7, 1 | BRF_PRG | BRF_ESS }, // 0 V33 Code + { "mt2-l0-a.5f", 0x040000, 0x9de5f689, 1 | BRF_PRG | BRF_ESS }, // 1 + { "is-h1.5l", 0x040000, 0x9ba8e1f2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "is-l1.5j", 0x040000, 0xe4e00626, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "mt2sh0", 0x010000, 0x1ecbea43, 2 | BRF_PRG | BRF_ESS }, // 4 V30 Code + { "mt2sl0", 0x010000, 0x8fd5b531, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "c0", 0x040000, 0x7e61e4b5, 3 | BRF_GRA }, // 6 Background Tiles + { "c1", 0x040000, 0x0a667564, 3 | BRF_GRA }, // 7 + { "c2", 0x040000, 0x5eb44312, 3 | BRF_GRA }, // 8 + { "c3", 0x040000, 0xf2866294, 3 | BRF_GRA }, // 9 + + { "k30", 0x100000, 0x8c9a2678, 4 | BRF_GRA }, // 10 Sprites + { "k31", 0x100000, 0x5455df78, 4 | BRF_GRA }, // 11 + { "k32", 0x100000, 0x3a258c41, 4 | BRF_GRA }, // 12 + { "k33", 0x100000, 0xc1e91a14, 4 | BRF_GRA }, // 13 + + { "da", 0x080000, 0x713b9e9f, 5 | BRF_SND }, // 14 Irem GA20 Samples + + { "mt2eep", 0x000800, 0x208af971, 6 | BRF_PRG | BRF_ESS }, // 15 EEPROM data + + { "pal16l8-m92-a-3m.ic11", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 16 plds + { "pal16l8-m92-a-7j.ic41", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 17 + { "pal16l8-m92-a-9j.ic51", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 18 + { "pal16l8-m92-b-2l.ic7", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 19 + { "pal16l8-m92-b-7h.ic47", 0x000104, 0x00000000, 7 | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(skingame2) +STD_ROM_FN(skingame2) + +struct BurnDriver BurnDrvSkingame2 = { + "skingame2", "majtitl2", NULL, NULL, "1992", + "The Irem Skins Game (US set 2)\0", "Imperfect sound and graphics", "Irem America", "M92", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_IREM_M92, GBF_SPORTSMISC, 0, + NULL, skingame2RomInfo, skingame2RomName, NULL, NULL, p4CommonInputInfo, Majtitl2DIPInfo, + majtitl2Init, DrvExit, DrvFrame, DrvReDraw, DrvScan, &bRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + diff --git a/src/burn/drivers/irem/irem_cpu.cpp b/src/burn/drivers/irem/irem_cpu.cpp new file mode 100644 index 00000000..43132876 --- /dev/null +++ b/src/burn/drivers/irem/irem_cpu.cpp @@ -0,0 +1,657 @@ +/***************************************************************************** + + Irem Custom V35+ CPU + -- has internal 256 byte lookup table, handled in realtime. Bomberman + World runs encrypted code from RAM, Risky Challenge expects to be able + to run code in emulation (non-encrypted) mode for some subroutines.. + + Hasamu Nanao 08J27261A1 011 9102KK700 + Gunforce Nanao 08J27261A1 011 9106KK701 + Ken-Go Nanao 08J27261A1 011 9102KK701 + Bomberman Nanao 08J27261A1 012 9123KK200 + Atomic Punk Nanao 08J27291A1 012 9128KK440 + Blade Master / Cross Blades! Nanao 08J27291A1 012 9123KK740 + Quiz F-1 1,2 Finish Nanao 08J27291A4 014 9147KK700 + Gunforce 2 Nanao 08J27291A4 014 9247KK700 + Lethal Thunder Nanao 08J27291A4 014 9147KK700 + Bomberman World / New Atomic Punk Nanao 08J27291A5 015 9219KK700 + Undercover Cops Nanao 08J27291A5 015 9219KK700 + Gun Hohki Nanao 08J27291A6 016 9217NK700 + Skins Game Nanao 08J27291A7 017 + Hook Nanao 08J27291A8 018 9237NK700 + + R-Type Leo Irem D8000021A1 019 9242NK700 + Fire Barrel Irem D8000010A1 019 9243NK700 + In The Hunt Irem D8000011A1 020 + Risky Challenge/Gussun Oyoyo Irem D8000019A1 022 9331NK700 + Match It II/Shisensho II Irem D8000020A1 023 9320NK700 + World PK Soccer/Kick for the Goal Irem D8000021A1 024 9335NK701 + Ninja Baseball Batman Irem D8000021A1 024 9335NK700 + Perfect Soldiers Irem D8000022A1 + Dream Soccer '94 Irem D8000023A1 026 + + Please let me know if you can fill in any of the blanks. + + Emulation by Bryan McPhail, mish@tendril.co.uk, thanks to Chris Hardy too! + +*****************************************************************************/ + + + +#include "burnint.h" +#include "irem_cpu.h" + + +// CAVEATS: +// 0x80 and 0x82 pre- opcodes can easily be confused. They perform exactly the same +// function when operating on memory, but when working with registers one affects +// byte registers and the other word registers. Gunforce, Blade Master and +// Lethal Thunder had this error. + +//double check 0x00 0x22 0x28 0x4a 0x34 in these tables + +#define xxxx 0x90/* Unknown */ + +const UINT8 gunforce_decryption_table[256] = { + 0xff,xxxx,xxxx,0x2c,xxxx,xxxx,0x43,0x88, xxxx,0x13,0x0a,0xbd,0xba,0x60,0xea,xxxx, /* 00 */ + xxxx,xxxx,0xf2,0x29,0xb3,0x22,xxxx,0x0c, 0xa9,0x5f,0x9d,0x07,xxxx,xxxx,0x0b,0xbb, /* 10 */ + 0x8a,xxxx,xxxx,xxxx,0x3a,0x3c,0x5a,0x38, 0x99,xxxx,0xf8,0x89,xxxx,0x91,xxxx,0x55, /* 20 */ + 0xac,0x40,0x73,xxxx,0x59,xxxx,0xfc,xxxx, 0x50,0xfa,xxxx,0x25,xxxx,0x34,0x47,0xb7, /* 30 */ + xxxx,xxxx,xxxx,0x49,xxxx,0x0f,0x8b,0x05, 0xc3,0xa5,0xbf,0x83,0x86,0xc5,xxxx,xxxx, /* 40 */ + 0x28,0x77,0x24,0xb4,xxxx,0x92,xxxx,0x3b, 0x5e,0xb6,0x80,0x0d,0x2e,0xab,0xe7,xxxx, /* 50 */ + 0x48,xxxx,0xad,0xc0,xxxx,0x1b,0xc6,0xa3, 0x04,xxxx,xxxx,xxxx,0x16,0xb0,0x7d,0x98, /* 60 */ + 0x87,0x46,0x8c,xxxx,xxxx,0xfe,xxxx,0xcf, xxxx,0x68,0x84,xxxx,0xd2,xxxx,0x18,0x51, /* 70 */ + 0x76,0xa4,0x36,0x52,0xfb,xxxx,0xb9,xxxx, xxxx,0xb1,0x1c,0x21,0xe6,0xb5,0x17,0x27, /* 80 */ + 0x3d,0x45,0xbe,0xae,xxxx,0x4a,0x0e,0xe5, xxxx,0x58,0x1f,0x61,0xf3,0x02,xxxx,0xe8, /* 90 */ + xxxx,xxxx,xxxx,0xf7,0x56,0x96,xxxx,0xbc, 0x4f,xxxx,xxxx,0x79,0xd0,xxxx,0x2a,0x12, /* A0 */ + 0x4e,0xb8,xxxx,0x41,xxxx,0x90,0xd3,xxxx, 0x2d,0x33,0xf6,xxxx,xxxx,0x14,xxxx,0x32, /* B0 */ + 0x5d,0xa8,0x53,0x26,0x2b,0x20,0x81,0x75, 0x7f,0x3e,xxxx,xxxx,0x00,0x93,xxxx,0xb2, /* C0 */ + 0x57,xxxx,0xa0,xxxx,0x39,xxxx,xxxx,0x72, xxxx,0x01,0x42,0x74,0x9c,0x1e,xxxx,0x5b, /* D0 */ + xxxx,0xf9,xxxx,0x2f,0x85,xxxx,0xeb,0xa2, xxxx,0xe2,0x11,xxxx,0x4b,0x7e,xxxx,0x78, /* E0 */ + xxxx,xxxx,0x09,0xa1,0x03,xxxx,0x23,0xc1, 0x8e,0xe9,0xd1,0x7c,xxxx,xxxx,0xc7,0x06, /* F0 */ +}; +// 0x13 (0x29) guess +// 0x18 (0xa9) guess +// 0x50 (0x28) guess +// 0x63 (0xc0) guess +// 0x7e (0x18) opcode is right but arguments could be swapped +// 0xcc (0x00) guess +// 0xea (0x11) guess +// 0x51 (0x77) guess (kengo) +// 0x96 (0x0e) complete guess (kengo), maybe wrong but I don't see what it could be + + +//double check 22 (boot bomb at 2a000) +//47a7 (46e0 in boot) - hmm + +// 0x00 is NOT 0x20 (no context in bomberman) + +const UINT8 bomberman_decryption_table[256] = { + xxxx,xxxx,0x79,xxxx,0x9d,0x48,xxxx,xxxx, xxxx,xxxx,0x2e,xxxx,xxxx,0xa5,0x72,xxxx, /* 00 */ + 0x46,0x5b,0xb1,0x3a,0xc3,xxxx,0x35,xxxx, xxxx,0x23,xxxx,0x99,xxxx,0x05,xxxx,0x3c, /* 10 */ + 0x3b,0x76,0x11,xxxx,xxxx,0x4b,xxxx,0x92, xxxx,0x32,0x5d,xxxx,0xf7,0x5a,0x9c,xxxx, /* 20 */ + 0x26,0x40,0x89,xxxx,xxxx,xxxx,xxxx,0x57, xxxx,xxxx,xxxx,xxxx,xxxx,0xba,0x53,0xbb, /* 30 */ + 0x42,0x59,0x2f,xxxx,0x77,xxxx,xxxx,0x4f, 0xbf,0x4a,0xcb,0x86,0x62,0x7d,xxxx,0xb8, /* 40 */ + xxxx,0x34,xxxx,0x5f,xxxx,0x7f,0xf8,0x80, 0xa0,0x84,0x12,0x52,xxxx,xxxx,xxxx,0x47, /* 50 */ + xxxx,0x2b,0x88,0xf9,xxxx,0xa3,0x83,xxxx, 0x75,0x87,xxxx,0xab,0xeb,xxxx,0xfe,xxxx, /* 60 */ + xxxx,0xaf,0xd0,0x2c,0xd1,0xe6,0x90,0x43, 0xa2,0xe7,0x85,0xe2,0x49,0x22,0x29,xxxx, /* 70 */ + 0x7c,xxxx,xxxx,0x9a,xxxx,xxxx,0xb9,xxxx, 0x14,0xcf,0x33,0x02,xxxx,xxxx,xxxx,0x73, /* 80 */ + xxxx,0xc5,xxxx,xxxx,xxxx,0xf3,0xf6,0x24, xxxx,0x56,0xd3,xxxx,0x09,0x01,xxxx,xxxx, /* 90 */ + 0x03,0x2d,0x1b,xxxx,0xf5,0xbe,xxxx,xxxx, 0xfb,0x8e,0x21,0x8d,0x0b,xxxx,xxxx,0xb2, /* A0 */ + 0xfc,0xfa,0xc6,xxxx,0xe8,0xd2,xxxx,0x08, 0x0a,0xa8,0x78,0xff,xxxx,0xb5,xxxx,xxxx, /* B0 */ + 0xc7,0x06,0x18,xxxx,xxxx,0x1e,0x7e,0xb0, 0x0e,0x0f,xxxx,xxxx,0x0c,0xaa,0x55,xxxx, /* C0 */ + xxxx,0x74,0x3d,xxxx,xxxx,0x38,0x27,0x50, xxxx,0xb6,0x5e,0x8b,0x07,0xe5,0x39,0xea, /* D0 */ + 0xbd,xxxx,0x81,0xb7,xxxx,0x8a,0x0d,xxxx, 0x58,0xa1,0xa9,0x36,xxxx,0xc4,xxxx,0x8f, /* E0 */ + 0x8c,0x1f,0x51,0x04,0xf2,xxxx,0xb3,0xb4, 0xe9,0x2a,xxxx,xxxx,xxxx,0x25,xxxx,0xbc, /* F0 */ +}; +// 49 -> 4a (verified in a bombrman PCB) + +const UINT8 lethalth_decryption_table[256] = { + 0x7f,0x26,0x5d,xxxx,0xba,xxxx,0x1e,0x5e, 0xb8,xxxx,0xbc,0xe8,0x01,xxxx,0x4a,0x25, /* 00 */ +// ssss !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + xxxx,0xbd,xxxx,0x22,0x10,xxxx,0x02,0x57, 0x70,xxxx,0x7e,xxxx,0xe7,0x52,xxxx,0xa9, /* 10 */ +// !!!! !!!! !!!! ???? !!!! !!!! gggg + xxxx,xxxx,0xc6,0x06,0xa0,0xfe,0xcf,0x8e, 0x43,0x8f,0x2d,xxxx,0xd4,0x85,0x75,0xa2, /* 20 */ +// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + 0x3d,xxxx,xxxx,0x38,0x7c,0x89,0xd1,0x80, 0x3b,0x72,0x07,xxxx,0x42,0x37,0x0a,0x18, /* 30 */ +// gggg !!!! ???? !!!! !!!! !!!! !!!! !!!! !!!! ssss !!!! + 0x88,0xb4,0x98,0x8b,0xb9,0x9c,0xad,0x0e, 0x2b,xxxx,0xbf,xxxx,0x55,xxxx,0x56,0xb0, /* 40 */ +// !!!! pppp !!!! !!!! !!!! !!!! gggg !!!! !!!! !!!! !!!! + 0x93,0x91,xxxx,0xeb,xxxx,0x50,0x41,0x29, 0x47,xxxx,xxxx,0x60,xxxx,0xab,xxxx,xxxx, /* 50 */ +// pppp !!!! !!!! !!!! !!!! !!!! !!!! !!!! + 0xc3,0xe2,0xd0,0xb2,0x11,0x79,xxxx,0x08, xxxx,0xfb,xxxx,0x2c,0x23,xxxx,0x28,0x0d, /* 60 */ +// !!!! !!!! !!!! !!!! ???? !!!! !!!! + xxxx,xxxx,xxxx,0x83,0x3c,xxxx,0x1b,0x34, 0x5b,xxxx,0x40,xxxx,xxxx,0x04,0xfc,0xcd, /* 70 */ +// !!!! !!!! !!!! !!!! !!!! ssss + 0xb1,0xf3,0x8a,xxxx,xxxx,0x87,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xbe,0x84,0x1f,0xe6, /* 80 */ +// !!!! !!!! !!!! !!!! !!!! + 0xff,xxxx,0x12,xxxx,0xb5,0x36,xxxx,0xb3, xxxx,xxxx,xxxx,0xd2,0x4e,xxxx,xxxx,xxxx, /* 90 */ +// !!!! !!!! !!!! + 0xa5,xxxx,xxxx,0xc7,xxxx,0x27,0x0b,xxxx, 0x20,xxxx,xxxx,xxxx,xxxx,xxxx,0x61,0x7d, /* A0 */ +// !!!! !!!! !!!! !!!! ???? + xxxx,xxxx,0x86,0x0f,xxxx,0xb7,xxxx,0x4f, xxxx,xxxx,0xc0,0xfd,xxxx,0x39,xxxx,0x77, /* B0 */ +// !!!! !!!! !!!! !!!! !!!! + 0x05,0x3a,xxxx,0x48,0x92,0x76,0x3e,0x03, xxxx,0xf8,xxxx,0x59,0xa8,0x5f,0xf9,0xbb, /* C0 */ +// !!!! !!!! pppp !!!! !!!! !!!! !!!! !!!! + 0x81,0xfa,0x9d,0xe9,0x2e,0xa1,0xc1,0x33, xxxx,0x78,xxxx,0x0c,xxxx,0x24,0xaa,0xac, /* D0 */ +// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! ???? !!!! !!!! + xxxx,0xb6,xxxx,0xea,xxxx,0x73,0xe5,0x58, 0x00,0xf7,xxxx,0x74,xxxx,0x76,xxxx,0xa3, /* E0 */ +// !!!! gggg !!!! !!!! !!!! !!!! ???? !!!! + xxxx,0x5a,0xf6,0x32,0x46,0x2a,xxxx,xxxx, 0x53,0x4b,0x90,0x0d,0x51,0x68,0x99,0x13, /* F0 */ +// !!!! !!!! !!!! !!!! !!!! !!!! !!!! ???? !!!! !!!! +}; +/* +missing opcode: + +"!!!!" -> checked against gussun +"gggg" -> very probably +"pppp" -> probably +"ssss" -> sure +"????" -> missing + + +1a -> (78,7c,7e) -> +34 -> (78,7c,7e) -> 78 + +65 -> (79, +af -> (79,7d) (strange 71) -> +d9 -> (11e07 from 11de6) (70,78 -> to handle a01ce=000-7d0 -> 0x78 +ed -> (p76,78,7c,7e) -> +fb -> + +probably: +42 -> 0x98 (083a3) +50 -> 0x93 (083a7) +c5 -> (18d56 - from 1844f) (71,73,76,79,7a,7d,7e) -> to handle level number (a008d=00-0f) -> 0x76 + +very probably: +48 -> 0x2b +e5 -> 0x73 + +sure: +00 -> 0x7f +3d -> 0x37 +7f -> 0xcd (little machine in the game - 16058) + +*/ +// 0x2c (0xd4) complete guess +// 0x2d (0x85) complete guess +// 0xc4 (0x92) guess +// 0xbb (0xfd) guess +// 0x46 (0xad) guess - risky challenge use same code +// 0x6e (0x28) guess +// 0x76 (0x1b) guess +// 0x8d (0x84) guess +// 0xa6 (0x0b) guess - risky challenge use same code +// 0xa8 (0x20) guess +// 0xbd (0x39) guess - risky challenge use same code +// 0xc3 (0x48) guess +// and our collection of conditional branches: +// 0xbf (0x7d) >= (monitor test) +// 0x34 (0x7c) < or <= (seems more like <) | these two are used toghether +// 0xaf (0x7f) > or >= (seems more like >) | +// 0xed (0x7e) <= or < (seems more like <=) +// 0x00 (0x7f) > ? | these two are used toghether +// 0x1a (0x7c) < ? | (rowscroll on pink screen on startup) +// 0xc5 (0x7a) completely in the dark (game start after car seelction) + + +const UINT8 dynablaster_decryption_table[256] = { + 0x1f,0x51,0x84,xxxx,0x3d,0x09,0x0d,xxxx, xxxx,0x57,xxxx,xxxx,xxxx,0x32,0x11,xxxx, /* 00 */ + xxxx,0x9c,xxxx,xxxx,0x4b,xxxx,xxxx,0x03, xxxx,xxxx,xxxx,0x89,0xb0,xxxx,xxxx,xxxx, /* 10 */ + xxxx,0xbb,0x18,0xbe,0x53,0x21,0x55,0x7c, xxxx,xxxx,0x47,0x58,0xf6,xxxx,xxxx,0xb2, /* 20 */ + 0x06,xxxx,0x2b,xxxx,0x2f,0x0b,0xfc, 0x91 , xxxx,xxxx,0xfa,0x81,0x83,0x40,0x38,xxxx, /* 30 */ + xxxx,xxxx,0x49,0x85,0xd1,0xf5,0x07,0xe2, 0x5e,0x1e,xxxx,0x04,xxxx,xxxx,xxxx,0xb1, /* 40 */ + 0xc7,xxxx,0x96, 0xf2 /*0xaf*/, 0xb6,0xd2,0xc3,xxxx, 0x87,0xba,0xcb,0x88,xxxx,0xb9,0xd0,0xb5, /* 50 */ + 0x9a,0x80,0xa2,0x72,xxxx,0xb4,xxxx,0xaa, 0x26,0x7d,0x52,0x33,0x2e,0xbc,0x08,0x79, /* 60 */ + 0x48,xxxx,0x76,0x36,0x02,xxxx,0x5b,0x12, 0x8b,0xe7,xxxx,xxxx,xxxx,0xab,xxxx,0x4f, /* 70 */ + xxxx,xxxx,0xa8,0xe5,0x39,0x0e,0xa9,xxxx, xxxx,0x14,xxxx,0xff, 0x7f/*0x75*/ ,xxxx,xxxx,0x27, /* 80 */ + xxxx,0x01,xxxx,xxxx,0xe6,0x8a,0xd3,xxxx, xxxx,0x8e,0x56,0xa5,0x92,xxxx,xxxx,0xf9, /* 90 */ + 0x22,xxxx,0x5f,xxxx,xxxx,0xa1,xxxx,0x74, 0xb8,xxxx,0x46,0x05,0xeb,0xcf,0xbf,0x5d, /* a0 */ + 0x24,xxxx,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx, 0x59,0x8d,0x3c,0xf8,0xc5,xxxx,0xf3,0x4e, /* b0 */ + xxxx,xxxx,0x50,0xc6,0xe9,0xfe,0x0a,xxxx, 0x99,0x86,xxxx,xxxx,0xaf ,0x8c/*0x8e*/,0x42,0xf7, /* c0 */ + xxxx,0x41,xxxx,0xa3,xxxx,0x3a,0x2a,0x43, xxxx,0xb3,0xe8,xxxx,0xc4,0x35,0x78,0x25, /* d0 */ + 0x75,xxxx,0xb7,xxxx,0x23,xxxx, xxxx/*0xe2*/,0x8f, xxxx,xxxx,0x2c,xxxx,0x77,0x7e,xxxx,0x0f, /* e0 */ + 0x0c,0xa0,0xbd,xxxx,xxxx,0x2d,0x29,0xea, xxxx,0x3b,0x73,xxxx,0xfb,0x20,xxxx,0x5a /* f0 */ +}; +//double check 0x00/0xa0 AND. +//double check 0x8c (0x7d jg) +//double check 0xfd (0x20 AND) - 9d2 in code +//double check 0xd1 (0x41 INC cw) used in uccops and dynablaster (LOOKS GOOD) + +//AND fd (0x20) +//0x37 (91) guess from dynablaster title screen + +// BM - 0x61 NOT 82, but instead 0x80 verified in both Atomic Punk and UCCops +// 0x22 is 0x18 (SBB) verified from Gunforce +// 0x5b seems confirmed (previous commented out as 0x36) +// NS I expected 0x32 to be 0x1b (SBB) like in gunforce, but startup tests fail in bbmanw. +// therefore it seems to be 0x2b (SUB) +// NS010718 0xa0 was 0x00 (ADDB), verified to be 0x22 (ANDB) + + +const UINT8 mysticri_decryption_table[256] = { + xxxx,0x57,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xbf,0x43,xxxx,xxxx,xxxx,xxxx,0xfc,xxxx, /* 00 */ + xxxx,xxxx,xxxx,xxxx,xxxx,0x52,0xa3,0x26, xxxx,0xc7,xxxx,0x0f,xxxx,0x0c,xxxx,xxxx, /* 10 */ + xxxx,xxxx,0xff,xxxx,xxxx,0x02,xxxx,xxxx, 0x2e,xxxx,0x5f,xxxx,xxxx,xxxx,0x73,0x50, /* 20 */ + 0xb2,0x3a,xxxx,xxxx,0xbb,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */ + xxxx,xxxx,0x8e,0x3c,0x42,xxxx,xxxx,0xb9, xxxx,xxxx,0x2a,xxxx,0x47,0xa0,0x2b,0x03, /* 40 */ + 0xb5,0x1f,xxxx,0xaa,xxxx,0xfb,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx, /* 50 */ + 0x2c,xxxx,xxxx,0xc6,xxxx,xxxx,0xb1,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xa2,xxxx, /* 60 */ + 0xe9,0xe8,xxxx,xxxx,0x86,xxxx,0x8b,xxxx, xxxx,xxxx,xxxx,xxxx,0x5b,0x72,xxxx,xxxx, /* 70 */ + xxxx,xxxx,0x5d,0x0a,xxxx,xxxx,0x89,xxxx, 0xb0,0x88,xxxx,xxxx,xxxx,0x87,0x75,0xbd, /* 80 */ + xxxx,0x51,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x5a,0x58,xxxx,xxxx,0x56, /* 90 */ + xxxx,0x8a,xxxx,0x55,xxxx,xxxx,xxxx,0xb4, 0x08,xxxx,0xf6,xxxx,xxxx,0x9d,xxxx,0xbc, /* A0 */ + 0x0b,xxxx,xxxx,0x5e,xxxx,xxxx,xxxx,0x22, 0x36,xxxx,0x1e,xxxx,0xb6,0xba,0x23,xxxx, /* B0 */ + 0x20,xxxx,xxxx,xxxx,0x59,0x53,xxxx,0x04, 0x81,xxxx,xxxx,0xf3,xxxx,xxxx,0x3b,0x06, /* C0 */ + xxxx,0x79,0x83,0x9c,xxxx,0x18,0x80,xxxx, 0xc3,xxxx,xxxx,xxxx,0x32,xxxx,0xcf,xxxx, /* D0 */ + 0xeb,xxxx,xxxx,0x33,xxxx,0xfa,xxxx,xxxx, 0xd2,xxxx,0x24,xxxx,0x74,0x41,0xb8,xxxx, /* E0 */ + xxxx,xxxx,0xd0,0x07,xxxx,xxxx,xxxx,xxxx, xxxx,0x46,xxxx,0xea,0xfe,0x78,xxxx,xxxx, /* F0 */ +}; +// 0xd5 (0x18) opcode is right but arguments could be swapped +// 0x4e (0x2b) not sure, could be 0x1b + + +const UINT8 majtitl2_decryption_table[256] = { + 0x87,xxxx,0x78,0xaa,xxxx,xxxx,xxxx,0x2c, 0x32,0x0a,0x0f,xxxx,0x5e,xxxx,0xc6,0x8a, /* 00 */ + 0x33,xxxx,xxxx,xxxx,xxxx,0xea,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x24,0x55, /* 10 */ + xxxx,xxxx,xxxx,0x89,0xfb,xxxx,0x59,0x02, xxxx,xxxx,0x5d,xxxx,xxxx,xxxx,0x36,xxxx, /* 20 */ + xxxx,0x06,0x79,xxxx,xxxx,0x1e,0x07,xxxx, xxxx,xxxx,0x83,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */ + 0x9d,xxxx,xxxx,0x74,xxxx,xxxx,xxxx,0x0c, 0x58,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */ + 0x3c,xxxx,0x03,xxxx,xxxx,0xfa,0x43,xxxx, 0xbf,xxxx,xxxx,0x75,xxxx,0x88,xxxx,0x80, /* 50 */ + xxxx,0xa3,xxxx,0xfe,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x3a,xxxx,xxxx,xxxx, /* 60 */ + 0x2b,xxxx,xxxx,xxxx,xxxx,0xe9,0x5f,xxxx, 0x46,xxxx,0x41,xxxx,0x18,0xb8,xxxx,xxxx, /* 70 */ + 0xb4,0x5a,0xb1,xxxx,xxxx,0x50,0xe8,0x20, xxxx,0xb2,xxxx,xxxx,xxxx,xxxx,xxxx,0x51, /* 80 */ + xxxx,xxxx,xxxx,0x56,xxxx,xxxx,xxxx,xxxx, xxxx,0xcf,xxxx,xxxx,xxxx,0xc3,xxxx,xxxx, /* 90 */ + xxxx,xxxx,xxxx,xxxx,0x0b,xxxx,xxxx,0xb5, 0x57,xxxx,xxxx,0xc7,0x3b,xxxx,xxxx,xxxx, /* A0 */ + xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,0xeb,xxxx, 0x38,xxxx,0xa0,0x08,xxxx,0x86,0xb0,xxxx, /* B0 */ + 0x42,0x1f,0x73,xxxx,0xf6,xxxx,xxxx,xxxx, 0x53,xxxx,0x52,xxxx,0x04,0xbd,xxxx,xxxx, /* C0 */ + 0x26,0xff,0x2e,xxxx,0x81,xxxx,0x47,xxxx, xxxx,xxxx,xxxx,0xd0,0x22,xxxx,xxxx,0xb9, /* D0 */ + 0x23,xxxx,0xf3,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xd2,0x8b,0xba,xxxx,xxxx,xxxx,0x5b, /* E0 */ + xxxx,xxxx,0x9c,xxxx,xxxx,xxxx,xxxx,0xfc, 0xbc,0xa2,0x2a,xxxx,xxxx,0x8e,0xbb,xxxx, /* F0 */ +}; +// 0x7c (0x18) opcode is right but arguments could be swapped +// 0x70 (0x2b) not sure, could be 0x1b + + +const UINT8 hook_decryption_table[256] = { + 0xb6,0x20,0x22,xxxx,0x0f,0x57,0x59,0xc6, 0xeb,xxxx,0xb0,0xbb,0x3b,xxxx,xxxx,xxxx, /* 00 */ + 0x36,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xfe,xxxx,xxxx,xxxx,xxxx,xxxx,0xa0, /* 10 */ + 0x2e,xxxx,0x0b,xxxx,xxxx,0x58,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,0x80,xxxx,xxxx, /* 20 */ + 0x33,xxxx,xxxx,0xbf,0x55,xxxx,xxxx,xxxx, 0x53,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */ + 0x47,0x74,xxxx,0xb1,0xb4,xxxx,xxxx,0x88, xxxx,xxxx,0x38,0xcf,xxxx,0x8e,xxxx,xxxx, /* 40 */ + xxxx,0xc7,xxxx,0x32,xxxx,0x52,0x3c,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,0x72, /* 50 */ + xxxx,0x73,xxxx,0x5a,xxxx,0x43,xxxx,xxxx, xxxx,xxxx,0x41,0xe9,0xbd,xxxx,0xb2,0xd2, /* 60 */ + xxxx,0xaa,0xa2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x26,xxxx,xxxx,0x8a,xxxx, /* 70 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x18, xxxx,0x9d,xxxx,xxxx,xxxx,0x5d,xxxx,0x46, /* 80 */ + xxxx,xxxx,xxxx,0xf6,0xc3,0xa3,0x1e,0x07, 0x5f,0x81,xxxx,0x0c,xxxx,0xb8,xxxx,0x75, /* 90 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x79, /* A0 */ + xxxx,0x5e,xxxx,xxxx,0x06,xxxx,0xff,xxxx, 0x5b,0x24,xxxx,0x2b,xxxx,xxxx,xxxx,0x02, /* B0 */ + 0x86,xxxx,xxxx,0xfb,xxxx,xxxx,0x50,0xfc, 0x08,xxxx,xxxx,xxxx,0x03,xxxx,0xb9,xxxx, /* C0 */ + xxxx,0xbc,0xe8,0x1f,0xfa,0x42,xxxx,xxxx, 0x89,xxxx,0x23,0x87,xxxx,0x2a,xxxx,xxxx, /* D0 */ + 0x8b,xxxx,0xf3,0xea,0x04,0x2c,0xb5,xxxx, 0x0a,xxxx,0x51,xxxx,xxxx,0x3a,xxxx,0x9c, /* E0 */ + xxxx,xxxx,0x78,xxxx,0xba,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xd0,0x56,xxxx,xxxx, /* F0 */ +}; +// 0x87 (0x18) opcode is right but arguments could be swapped +// 0xbb (0x2b) not sure, could be 0x1b + + +const UINT8 rtypeleo_decryption_table[256] = { + 0x5d,xxxx,0xc6,xxxx,xxxx,xxxx,0x2a,0x3a,xxxx,xxxx,xxxx,0x86,xxxx,0x22,xxxx,0xf3, /* 00 */ + xxxx,xxxx,xxxx,xxxx,xxxx,0x38,0xf7,0x42,0x04,xxxx,xxxx,0x1f,0x4b,xxxx,xxxx,0x58, /* 10 */ + 0x57,0x2e,xxxx,xxxx,0x53,xxxx,0xb9,xxxx,xxxx,xxxx,xxxx,xxxx,0x20,0x55,xxxx,0x3d, /* 20 */ + 0xa0,xxxx,xxxx,0x0c,0x03,xxxx,0x83,xxxx,xxxx,xxxx,0x8a,0x00,xxxx,0xaa,xxxx,xxxx, /* 30 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x41,0x0a,0x26,0x8b,0x56,0x5e,xxxx, /* 40 */ + xxxx,0x74,xxxx,xxxx,xxxx,xxxx,0x06,xxxx,xxxx,0x89,0x5b,0xc7,0x43,xxxx,xxxx,xxxx, /* 50 */ + xxxx,0xb6,xxxx,0x3b,xxxx,xxxx,xxxx,xxxx,xxxx,0x36,0xea,0x80,xxxx,xxxx,xxxx,0x5f, /* 60 */ + xxxx,0x0f,xxxx,xxxx,xxxx,0x46,xxxx,xxxx,0x3c,0x8e,xxxx,0xa3,0x87,xxxx,xxxx,xxxx, /* 70 */ + 0x2b,0xfb,0x47,0x0b,xxxx,0xfc,0x02,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x72,0x2c, /* 80 */ + 0x33,xxxx,xxxx,xxxx,xxxx,xxxx,0x9d,0xbd,xxxx,0xb2,xxxx,0x78,0x75,0xb8,xxxx,xxxx, /* 90 */ + xxxx,xxxx,xxxx,xxxx,0xcf,0x5a,0x88,xxxx,xxxx,xxxx,0xc3,xxxx,0xeb,0xfa,xxxx,0x32, /* A0 */ + xxxx,xxxx,xxxx,0x52,0xb4,xxxx,xxxx,xxxx,xxxx,0xbc,xxxx,xxxx,xxxx,0xb1,0x59,0x50, /* B0 */ + xxxx,xxxx,0xb5,xxxx,0x08,0xa2,0xbf,0xbb,0x1e,0x9c,xxxx,0x73,xxxx,0xd0,xxxx,xxxx, /* C0 */ + xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0x79,xxxx,xxxx,0x24,0x23,xxxx,xxxx,0xb0,0x07,0xff, /* D0 */ + xxxx,0xba,0xf6,0x51,xxxx,xxxx,xxxx,0xfe,xxxx,0x92,xxxx,xxxx,xxxx,xxxx,0xe9,xxxx, /* E0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xe8,0xd2,xxxx,0x18,xxxx,xxxx,xxxx,0xd1,xxxx,xxxx, /* F0 */ +// ^^^^ +}; +// 0xf9 (0x18) opcode is right but arguments could be swapped +// 0x80 (0x2b) not sure, could be 0x1b +// 0x16 (0x01) guess (wrong?) +// fixed 0x16 = 0xf7 mapping +// 3d = correct + +const UINT8 inthunt_decryption_table[256] = { + 0x1f,xxxx,0xbb,0x50,xxxx,0x58,0x42,0x57, xxxx,xxxx,0xe9,xxxx,xxxx,xxxx,xxxx,0x0b, /* 00 */ + xxxx,xxxx,0x9d,0x9c,xxxx,xxxx,0x1e,xxxx, xxxx,0xb4,0x5b,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */ + xxxx,xxxx,0x78,0xc7,xxxx,xxxx,0x83,xxxx, xxxx,0x0c,0xb0,0x04,xxxx,xxxx,xxxx,xxxx, /* 20 */ + xxxx,xxxx,xxxx,xxxx,0x3b,0xc3,0xb5,0x47, xxxx,xxxx,xxxx,xxxx,0x59,xxxx,xxxx,xxxx, /* 30 */ + xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx,xxxx, 0x5f,0xa3,0xfa,xxxx,0xe8,0x36,0x75,xxxx, /* 40 */ + 0x88,0x33,xxxx,xxxx,xxxx,xxxx,0x43,xxxx, xxxx,0x87,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */ + xxxx,xxxx,xxxx,xxxx,0x8e,0xf3,0x56,xxxx, xxxx,xxxx,xxxx,0x26,0xff,xxxx,xxxx,xxxx, /* 60 */ + xxxx,xxxx,xxxx,0x2a,xxxx,0x8a,xxxx,0x18, xxxx,xxxx,0x03,0x89,0x24,xxxx,xxxx,xxxx, /* 70 */ + 0x0a,xxxx,0xeb,xxxx,0x86,xxxx,xxxx,xxxx, 0x79,0x3a,xxxx,xxxx,xxxx,xxxx,0xa0,xxxx, /* 80 */ + 0xea,xxxx,xxxx,xxxx,xxxx,xxxx,0x2c,xxxx, 0xc6,xxxx,xxxx,0x46,xxxx,0xaa,0xb6,0x5e, /* 90 */ + xxxx,xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,xxxx, xxxx,xxxx,0xba,xxxx,0xb9,0x53,0xa2,xxxx, /* A0 */ + xxxx,0x07,xxxx,xxxx,xxxx,0x3c,0x32,xxxx, 0x2b,xxxx,0xb8,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */ + 0xbd,xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0xd0, 0x08,xxxx,0x55,0x06,0xcf,xxxx,xxxx,0xfc, /* C0 */ + xxxx,xxxx,xxxx,0xb1,0xbf,xxxx,xxxx,0x51, 0x52,xxxx,0x5d,xxxx,0x5a,xxxx,0xb2,xxxx, /* D0 */ + 0xfe,xxxx,xxxx,0x22,0x20,0x72,0xf6,0x80, 0x02,0x2e,xxxx,0x74,0x0f,xxxx,xxxx,xxxx, /* E0 */ + xxxx,xxxx,xxxx,xxxx,0xbc,0x41,xxxx,0xfb, 0x73,xxxx,xxxx,xxxx,0x23,0xd2,xxxx,xxxx, /* F0 */ +}; +// 0x77 (0x18) opcode is right but arguments could be swapped +// 0xb8 (0x2b) not sure, could be 0x1b + +const UINT8 gussun_decryption_table[256] = { + 0x63,xxxx,xxxx,0x36,xxxx,0x52,0xb1,0x5b, 0x68,0xcd,xxxx,xxxx,xxxx,0xa8,xxxx,xxxx, /* 00 */ +// gggg gggg gggg gggg + xxxx,xxxx,0x75,0x24,0x08,0x83,0x32,0xe9, xxxx,0x79,xxxx,0x8f,0x22,xxxx,0xac,xxxx, /* 10 */ +// pppp pppp gggg + 0x5d,0xa5,0x11,0x51,0x0a,0x29,xxxx,xxxx ,0xf8,0x98,0x91,0x40,0x28,0x00,0x03,0x5f, /* 20 */ +// gggg gggg gggg gggg gggg gggg pppp + 0x26,xxxx,xxxx,0x8b,0x2f,0x02,xxxx,xxxx, 0x8e,0xab,xxxx,xxxx,0xbc,0x90,0xb3,xxxx, /* 30 */ +// gggg + 0x09,xxxx,0xc6,xxxx,xxxx,0x3a,xxxx,xxxx, xxxx,0x74,0x61,xxxx,0x33,xxxx,xxxx,xxxx, /* 40 */ +// gggg + xxxx,0x53,0xa0,0xc0,0xc3,0x41,0xfc,0xe7, xxxx,0x2c,0x7c,0x2b,xxxx,0x4f,0xba,0x2a, /* 50 */ +// gggg gggg gggg pppp gggg gggg + 0xb0,xxxx,0x21,0x7d,xxxx,xxxx,0xb5,0x07, 0xb9,xxxx,0x27,0x46,0xf9,xxxx,xxxx,xxxx, /* 60 */ +// pppp pppp gggg gggg + xxxx,0xea,0x72,0x73,0xad,0xd1,0x3b,0x5e, 0xe5,0x57,xxxx,0x0d,0xfd,xxxx,0x92,0x3c, /* 70 */ +// gggg pppp gggg gggg + xxxx,0x86,0x78,0x7f,0x30,0x25,0x2d,xxxx, 0x9a,0xeb,0x04,0x0b,0xa2,0xb8,0xf6,xxxx, /* 80 */ +// pppp gggg gggg pppp gggg + xxxx,xxxx,0x9d,xxxx,0xbb,xxxx,xxxx,0xcb, 0xa9,0xcf,xxxx,0x60,0x43,0x56,xxxx,xxxx, /* 90 */ +// gggg gggg + xxxx,0xa3,xxxx,xxxx,0x12,xxxx,0xfa,0xb4, xxxx,0x81,0xe6,0x48,0x80,0x8c,0xd4,xxxx, /* a0 */ +// gggg gggg pppp gggg gggg + 0x42,xxxx,0x84,0xb6,0x77,0x3d,0x3e,xxxx, xxxx,0x0c,0x4b,xxxx,0xa4,xxxx,xxxx,xxxx, /* b0 */ +// gggg gggg pppp gggg gggg pppp pppp gggg + xxxx,0xff,0x47,xxxx,0x55,0x1e,xxxx,0x59, 0x93,xxxx,xxxx,xxxx,0x88,0xc1,0x01,0xb2, /* c0 */ +// gggg + 0x85,0x2e,0x06,0xc7,0x05,xxxx,0x8a,0x5a, 0x58,0xbe,xxxx,0x4e,xxxx,0x1f,0x23,xxxx, /* d0 */ +// gggg gggg + 0xe8,xxxx,0x89,0xa1,0xd0,xxxx,xxxx,0xe2, 0x38,0xfe,0x50,0x9c,xxxx,xxxx,xxxx,0x49, /* e0 */ +// gggg gggg + 0xfb,0x20,0xf3,xxxx,xxxx,0x0f,xxxx,xxxx, xxxx,0x76,0xf7,0xbd,0x39,0x7e,0xbf,xxxx, /* f0 */ +// pppp gggg gggg gggg +}; + + +/* +missing opcode: + +" " -> checked against hasamu (i.e. you can compare gussun from 2002a and hasamu from 54a0) +"gggg" -> very probably +"pppp" -> probably +"????" -> missing + +rz probably: +14 -> 08 (2097b 20980 - routine from 2097a) (08 30) to handle the player number -> 08 +19 -> 79 (1df45 routine from 1df27 / 2282f - routine from 2281f to 22871) no 70,78,7a,7b,7c,7e,7f(ok) ok 79,7d +5a -> 7c (195eb - (222fc - routine from 222ed to ) (7x j...) no 70,71,79,7a,7b ok (78,7c) -> 7c +63 -> 7d (1df7f, 1df8c, 1df95, 21f08 - routine from 1df27 to ) no 70,78,7a,7b,7c,7e,7f(ok) ok 79,7d +7b -> 0d +82 -> 78 (78,7c) -> 78 +86 -> 2d +ab -> 48 (1956f - routine from 194e1 to 19619 - bp 19567) (when the water go up) -> 48 +b3 -> b6 (216b6 - 216cf - 16663 (when you rotate a piece) - 175f1 - 17d2a - 17d36) -> b6 +b9 -> 0c (21210 - routine from 2117e to ) 2 bytes -> to handle messages in level 0 (learning level) +ba -> 4b (1094d, 10b28 - routine from 10948 to 10b73) one byte -> probably 4b +f1 -> 20 to handle the player number + +rz guess: +06 -> b1 (22872 - routine from 22872 to 2289d) +09 -> cd (22a17 - routine from 229ed to 22a1a) +0d -> a8 ( +1b -> 8f (1d8f9 - routine from 1d8c7 to 1d8fc) - three bytes (pop instruction for the push in 1d8e6) +22 -> 11 (1deff - routine from 1dee8 to 1df26) -> 11 - to handle sprite animation +25 -> 29 (195a0 - routine from 194e1 to ) (19,29) +28 -> f8 ( +29 -> 98 (1df22 - routine from 1dee8 to 1df26) -> 98 - to handle sprite animation +2b -> 40 (1d4d2 1db81 1dba9 - routine from 1d4b2 to 1d4de) -> 40 +2c -> 28 (20333 - routine from 2032a to 20366) (18,28) +2d -> 00 (1df1d - routine from 1dee8 to 1df26) -> 00 - to handle sprite animation +34 -> 2f (20381 - routine from 2037b to 20391) - used to handle number of lives and game over +40 -> 09 +52 -> a0 +55 -> 41 +59 -> 2c (220cf - 2037f - routine from 2202f to ) 2bytes (2c, +5b -> 2b (used in "Service Mode" / "CHARACTER menu") +5d -> 4f +62 -> 21 (1cf86 1cfa3 - routine from 1cf61 to 1cff4) (water in level 1) (01 11 19 29) +66 -> b5 (1daaf - routine from 1da61 to 1daca) - two bytes (colors effect) +6a -> 27 (20368 - routine from 20368 to 2037a) - used to limit the max lives number +73 -> 73 (1d4f7 - routine from 1d4df to 1d539) -> (no 70,71,72,74,75,76,77,78,79,7a,7b,7c,7d,7e,7f) - ok 73 +7c -> fd +7e -> 92 (1e095 - routine from 1e073 to 1e0cf) +83 -> 7f (194cd - routine from) no 70,78,79,7a,7b,7c,7d,7e ok 77(no) ok 7f +84 -> 08 (1d8f1 - routine from 1d8c7 to 1d8fc) - three bytes (ok 30) (sprite animation) -> 30 +88 -> 9a +92 -> 9d +97 -> cb +a4 -> 12 (02,12) - routine from 1d392 -> 12 +a7 -> b4 (2029a - routine from 20290 to +ad -> 8c (1d559, 1d8d4 - routine from 1d547 - ; routine from 1d8b8 to 1d8fc) .............................. +ae -> d4 (20215 - ) used when you insert a coin to handle the "coin number" in decimal +b0 -> 42 (routine from 128db) +b2 -> 84 (20a8b - 20acc) 20,21,84,85 (scroll down the object) - to handle the player number +b4 -> 77 (1d03a, 1d57a - routine from 1d4df ) no 70,71,76,78,79,7a,7b,7c,7d,7e,7f ok 77 +b6 -> 3e +bc -> a4 +c2 -> 47 (22881, 220ff - routine from 22872 to 22885) +d0 -> 85 (routine from 16a3e) (when you rotate a piece) +db -> 4e (18b1a) +eb -> 9c +ef -> 49 (dec CW) (used in "Service Mode" / "CHARACTER menu") +f9 -> 76 (16d02(f 16cfa)-16598-165a1-18de7(f 18dc4) no 71(no),77(no),(icons? 70,76,78,7a,7c,7e),79,7d,7f(no) maybe 76 +fb -> bd +fd -> 7e (1d659 - routine from 1d63c to 1d65e) no 70,76,77,78,79,7a,7b, 7c,7d,7e,7f ok 7e + +missing V35+ core: +0f 92 -> of 92 not supported (1011d before STI instruction) (for now no effects) + +------------------------------------------------------------------------------------------------------------- + +AS notes: +0x1e is lodsb not lds,noted from 2344f +0x16 is xor r8,r8 not xor r16,r16 +0xc8 not inc aw but xch bw,aw +0xcd is 0xc1 not 0xbd(palette at startup) +0x97 guess,but seems right(228c1),known to *not* be ret %Iw. +0x00 wrong(for sure it needs a one byte operand due to push es called at one point...) +0x19 guess (0x82 PRE) +0xc2 guess,it could be dec iy... + +above - c8 (inc aw) guess from stos code +0xc5 -> 1e (push ds) guess (pop ds soon after) right? +0xa9 -> 81 (not 0x82 PRE) guess from 237df +0xcd -> c1 total guess (wrong but 3 bytes) +*/ + +/* +e0100 palette sub-routine: +12485: 23 push es +12486: 27 C2 mov es,dw +12488: D7 C0 xor aw,aw +1248A: D7 FF xor iy,iy +1248C: 44 00 01 mov cw,$0100 +1248F: 81 5D repe stosw +12491: 95 22 06 97 39 mov byte ss:[$3997],$FF +12497: 3A pop es +12498: 60 ret + +d1a86 + +unk +add bw,bw [d8] +add ix,sp [e6] +add iy,sp [e7] +clc +ret +*/ + +const UINT8 leagueman_decryption_table[256] = { + xxxx,xxxx,xxxx,0x55,0xbb,xxxx,0x23,0x79, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x38,xxxx, /* 00 */ + 0x01,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0x3d,xxxx,xxxx,xxxx,0xba,xxxx,0x1e,xxxx, /* 10 */ + 0x2c,0x46,xxxx,0xb5,xxxx,0x4b,xxxx,0xfe, xxxx,xxxx,0xfb,0x2e,xxxx,xxxx,0x36,0x04, /* 20 */ + 0xcf,xxxx,0xf3,0x5a,0x8a,0x0c,0x9c,xxxx, xxxx,xxxx,0xb2,0x50,xxxx,xxxx,xxxx,0x5f, /* 30 */ + xxxx,xxxx,0x24,xxxx,xxxx,0x41,0x2b,xxxx, 0xe9,xxxx,0x08,0x3b,xxxx,xxxx,xxxx,xxxx, /* 40 */ + xxxx,0xd2,0x51,xxxx,xxxx,xxxx,0x22,xxxx, 0xeb,0x3a,0x5b,0xa2,0xb1,0x80,xxxx,xxxx, /* 50 */ + xxxx,xxxx,xxxx,xxxx,0x59,0xb4,0x88,xxxx, xxxx,0xbf,0xd1,xxxx,0xb9,0x57,xxxx,xxxx, /* 60 */ + 0x72,xxxx,0x73,xxxx,xxxx,xxxx,xxxx,0x0f, xxxx,xxxx,xxxx,xxxx,0x56,xxxx,xxxx,0xc6, /* 70 */ + xxxx,xxxx,xxxx,xxxx,xxxx,0x2a,0x8e,xxxx, 0x81,0xa3,0x58,xxxx,0xaa,0x78,0x89,xxxx, /* 80 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xbd,xxxx, xxxx,xxxx,0xff,xxxx,xxxx,xxxx,0x07,0x53, /* 90 */ + 0xa0,xxxx,xxxx,0x5e,0xb0,xxxx,0x83,0xf6, xxxx,0x26,0x32,xxxx,xxxx,xxxx,0x74,0x0a, /* A0 */ + 0x18,xxxx,xxxx,xxxx,0x75,0x03,xxxx,xxxx, 0xb6,0x02,xxxx,xxxx,0x43,xxxx,0xb8,xxxx, /* B0 */ + 0xe8,xxxx,0xfc,xxxx,0x20,0xc3,xxxx,0x06, xxxx,0x1f,0x86,0x00,xxxx,xxxx,xxxx,0xd0, /* C0 */ + 0x47,xxxx,0x87,xxxx,xxxx,0x9d,0x3c,0xc7, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */ + xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,0x33,xxxx, xxxx,xxxx,xxxx,xxxx,0xfa,0x42,xxxx,xxxx, /* E0 */ + xxxx,xxxx,xxxx,0xea,xxxx,0x52,xxxx,0x5d, xxxx,xxxx,xxxx,xxxx,0xbc,xxxx,xxxx,xxxx, /* F0 */ +}; +// 0x25 (0x4b) guess +// 0x10 (0x01) guess (wrong?) + + +const UINT8 psoldier_decryption_table[256] = { + xxxx,xxxx,xxxx,0x8a,xxxx,0xaa,xxxx,xxxx, xxxx,0x20,0x23,0x55,xxxx,0xb5,0x0a,xxxx, /* 00 */ + xxxx,0x46,xxxx,0xb6,xxxx,0x74,0x8b,xxxx, xxxx,0xba,0x01,xxxx,xxxx,0x5a,0x86,0xfb, /* 10 */ + 0xb2,xxxx,0xb0,xxxx,0x42,0x06,0x1e,0x08, 0x22,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx,0x73, /* 20 */ + xxxx,xxxx,0x5f,xxxx,xxxx,0xd0,xxxx,0xff, xxxx,xxxx,0xbd,xxxx,0x03,xxxx,0xb9,xxxx, /* 30 */ + xxxx,xxxx,xxxx,0x51,0x5e,0x24,xxxx,xxxx, xxxx,xxxx,xxxx,0x58,0x59,xxxx,xxxx,xxxx, /* 40 */ + 0x52,xxxx,xxxx,xxxx,0xa0,xxxx,xxxx,0x02, 0xd2,xxxx,0x79,0x26,0x3a,0x0f,0xcf,0xb4, /* 50 */ + 0xf3,xxxx,xxxx,0x50,xxxx,0x75,0xb1,xxxx, 0xd1,0x47,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */ + 0xc6,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,xxxx, xxxx,xxxx,xxxx,xxxx,0x53,0x41,xxxx,xxxx, /* 70 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x04,xxxx, xxxx,xxxx,xxxx,0x2c,xxxx,0xbf,xxxx,xxxx, /* 80 */ + xxxx,xxxx,0xe8,xxxx,xxxx,0x78,xxxx,0xbb, xxxx,xxxx,0x1f,0x2b,0x87,xxxx,0x4b,0x56, /* 90 */ + 0x36,0x33,xxxx,xxxx,xxxx,0x9c,0xc3,xxxx, xxxx,0x81,xxxx,0xe9,xxxx,0xfa,xxxx,xxxx, /* A0 */ + xxxx,0x72,xxxx,0xa2,xxxx,xxxx,0xc7,xxxx, xxxx,0x92,xxxx,xxxx,0x88,xxxx,xxxx,xxxx, /* B0 */ + 0x3b,xxxx,0x0c,xxxx,0x80,xxxx,xxxx,xxxx, xxxx,0x2e,xxxx,xxxx,xxxx,0x57,xxxx,0x8e, /* C0 */ + 0x07,xxxx,0xa3,xxxx,xxxx,xxxx,0x3d,xxxx, 0xfe,xxxx,xxxx,0xfc,0xea,xxxx,0x38,xxxx, /* D0 */ + 0x3c,0xf6,xxxx,xxxx,xxxx,0x18,xxxx,xxxx, 0xb8,xxxx,xxxx,xxxx,0x2a,0x5d,0x5b,xxxx, /* E0 */ + xxxx,0x43,0x32,xxxx,xxxx,xxxx,0xeb,xxxx, xxxx,xxxx,xxxx,xxxx,0x83,0x89,xxxx,xxxx, /* F0 */ +}; +// 0x9e (0x4b) guess +// 0x1a (0x01) guess (wrong?) + + +const UINT8 dsoccr94_decryption_table[256] = { + xxxx,0xd1,xxxx,xxxx,xxxx,0x79,0x2e,xxxx, xxxx,xxxx,0x5a,0x0f,xxxx,xxxx,0x43,xxxx, /* 00 */ + xxxx,xxxx,0xe8,0x50,xxxx,xxxx,xxxx,0xa0, 0x5d,0x22,xxxx,xxxx,0xb2,0x3a,xxxx,xxxx, /* 10 */ + 0xf6,0x8a,0x41,xxxx,xxxx,0x81,xxxx,xxxx, xxxx,xxxx,0x2b,0x58,xxxx,xxxx,xxxx,0xc6, /* 20 */ + xxxx,xxxx,0xb9,xxxx,xxxx,0x2a,xxxx,0x3c, xxxx,0x80,0x26,xxxx,0xb0,xxxx,0x47,xxxx, /* 30 */ + xxxx,xxxx,0x0a,0x55,xxxx,xxxx,xxxx,0x88, xxxx,xxxx,0x87,xxxx,xxxx,0xb4,0x0c,xxxx, /* 40 */ + 0x73,0x53,xxxx,xxxx,0x3b,0x1f,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */ + 0x01,xxxx,xxxx,xxxx,xxxx,0x1e,xxxx,xxxx, 0xc3,xxxx,0xa3,0x74,xxxx,0x32,0x42,0x75, /* 60 */ + 0xfc,xxxx,0xb8,xxxx,0x33,xxxx,0x5e,xxxx, xxxx,0xaa,xxxx,xxxx,0x04,xxxx,0x9c,0xba, /* 70 */ + xxxx,xxxx,0x24,0x89,xxxx,xxxx,0xea,xxxx, 0x23,xxxx,xxxx,xxxx,0xbb,xxxx,xxxx,0xc7, /* 80 */ + xxxx,0x8e,xxxx,0x52,xxxx,0x18,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,xxxx,xxxx, /* 90 */ + 0xfa,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xb1,xxxx,xxxx,xxxx,xxxx,0x57,0x78,0xa2, /* A0 */ + xxxx,0x3d,0x51,xxxx,xxxx,0xbf,0x46,0x2c, xxxx,xxxx,0xfb,xxxx,xxxx,xxxx,xxxx,0x38, /* B0 */ + 0x56,xxxx,0xcf,xxxx,0x08,xxxx,xxxx,xxxx, 0x5b,0x07,xxxx,xxxx,xxxx,0x20,0x9d,xxxx, /* C0 */ + 0x03,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,0x86, 0x59,xxxx,0x02,xxxx,0xff,0xd2,0x8b,xxxx, /* D0 */ + xxxx,0xd0,xxxx,xxxx,xxxx,xxxx,xxxx,0xe9, 0x06,xxxx,0x5f,0xf3,xxxx,0xb5,xxxx,xxxx, /* E0 */ + 0xeb,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,xxxx, 0x36,xxxx,xxxx,xxxx,xxxx,0xbd,0xfe,xxxx, /* F0 */ +}; + +// 0x95 (0x18) opcode is right but arguments could be swapped +// 0x2a (0x2b) not sure, could be 0x1b +// 0x60 (0x01) guess (wrong?) + + +/* preliminary table by Pierpaolo Prazzoli */ +const UINT8 matchit2_decryption_table[256] = { + xxxx,0x86,0x0a,xxxx,0x32,0x01,0x81,0xbe, 0xea,xxxx,0xbb,xxxx,xxxx,xxxx,0xa5,0xf6, /* 00 */ +// new new new new new new new new new + 0x5d,0x8c,0xf3,0xc4,0x42,0x5a,0x22,0x26, xxxx,0x58,xxxx,0xfd,0x59,0x53,0x80,0x09, /* 10 */ +// new new new new !!!! new !!!! new !!!! new new new !!!! + xxxx,0x1e,0x48,0xe2,0x50,xxxx,0xc3,0x23, xxxx,xxxx,0xe9,xxxx,0x40,0x83,0xa3,0x46, /* 20 */ +// new new new new new new new new new new + 0x49,0xb4,0xa9,xxxx,0xd3,0x8b,0xe8,0xb8, 0xa0,xxxx,xxxx,xxxx,0x84,xxxx,xxxx,xxxx, /* 30 */ +// !!!! ???? new !!!! new new new new + xxxx,xxxx,xxxx,xxxx,0x14,xxxx,0x25,xxxx, xxxx,0x5e,xxxx,0x87,0x56,0xb9,0x4a,0x39, /* 40 */ +// new new new new new new new new + 0x89,xxxx,xxxx,xxxx,xxxx,0x1f,0xa4,xxxx, 0xf8,0x5f,0x21,0xb3,0x5b,xxxx,0x8d,xxxx, /* 50 */ +// new new !!!! new new !!!! new new + xxxx,0xc5,0x7c,0x07,xxxx,0x88,0xba,0x47, 0x35,0xfb,xxxx,0x7f,xxxx,xxxx,0xc6,0xeb, /* 60 */ +// new !!!! new new new new new new !!!! new + xxxx,0xc7,xxxx,xxxx,0xd2,0xa1,0x72,0x79, 0xfe,0x24,0xab,0x2a,0xbc,0x0d,0x8f,0x7e, /* 70 */ +// !!!! new new new new new new new new new !!!! + xxxx,0x7d,xxxx,0xe7,0x2d,xxxx,xxxx,0x57, 0x0b,0xa2,xxxx,0x9d,xxxx,xxxx,0x74,0x85, /* 80 */ +// !!!! new new new new new new new new + 0xaf,0x2f,0x8a,0xe6,0x08,xxxx,0xff,xxxx, xxxx,0x1c,xxxx,xxxx,0x02,xxxx,xxxx,xxxx, /* 90 */ +// new !!!! new new new new !!!! new + 0x43,0x04,xxxx,xxxx,0xbf,0x3b,0x93,0x38, xxxx,xxxx,xxxx,0x77,xxxx,0xb0,xxxx,0x3a, /* A0 */ +// new new new new new new new new new + 0xfc,xxxx,0xb5,xxxx,xxxx,xxxx,xxxx,0x05, 0x52,0x76,0x2b,0xe5,0xbd,xxxx,0x0e,0xb1, /* B0 */ +// new new new new new new new new new !!!! + 0x73,xxxx,xxxx,0x45,0x92,0x99,xxxx,0xf7, 0x3d,0xd0,0xb6,0x36,0xf9,0xfa,0x0f,xxxx, /* C0 */ +// new new new new new new new !!!! new new + 0x75,xxxx,0xaa,0x9c,xxxx,0x11,xxxx,xxxx, 0x27,0x4b,xxxx,0x2c,0x51,0x2e,0x4d,xxxx, /* D0 */ +// new !!!! new new new new new new new !!!! + 0x55,0x3c,xxxx,0xb7,xxxx,0xd1,0x8e,xxxx, 0xb2,xxxx,0x78,xxxx,0x12,xxxx,0x29,0x0c, /* E0 */ +// new new new ???? new new new new new new new + 0x33,xxxx,0xf2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0x03,0x06,0xa8,xxxx,xxxx,0xcf,xxxx, /* F0 */ +// new new new new new new +}; +/* +Unknown (marked "????") + +from shisen 2: +E4 -> pc: b08; f458, 1920 (99% 1 byte at boot and sometimes when a piece is selected) + b65c (after one match is finished with the girl on the background or when you finish some levels in the other modes) + +Found (marked "!!!!") +14 -> pc: 8b2a -> 42 +16 -> pc: 1714, 1804, 1a70, 1cc3 (00 10 13 1C 20 21 22 34 D4 D5 after a match) -> 22 +1B -> pc: 630e (it's used to update the high score) -> FD +1F -> pc: f30, f35, af74, 153a, 6dd8, 674f -> 09 +30 -> pc: 19af, 1986 -> 49 +31 -> pc: c804, c813, c822, 1358, c303, c312, c321, 1315, 1338 (2 bytes opcode) -> B4 +34 -> pc: 42cd -> D3 +4E -> pc: 7ac3, 7ae8 (after a 2 players match and in a 2 players match in "stalemate") -> 4a +56 -> pc: 6587 (can be 6C, 6D, 6E, 6F, A4, A6, A7, AA, AC, AD, AE at boot) -> A4 +5A -> pc: ae83 (after an item is selected) (00 10 13 15 1B -1C already used- 1D 21 28) -> 21 (it's used to evidence tiles similar to the one selected) +62 -> pc: 5b3f (jump 71, 7C) -> 7C +6B -> pc: 1810, 1936 (jump) -> 7F +74 -> pc: ca75 -> D2 +7F -> pc: 6b7e, 51d7, 5a8c, 5a9a, 5996 (jump: 7C, 7E) -> 7E +81 -> pc: 599d (jump: 7D, 7F) -> 7D +91 -> pc: 6e0c, 96ef, 96d0 (1 byte opcode) -> 2F +99 -> pc: 96f7, 9702 (after undo button is pressed) -> 1C (it's used to update the score when the you undo the moves) +BF -> pc: 6af3, 6b01, ca73, ab39 (2 bytes opcode) -> B1 +C4 -> pc: deb4 -> 92 from bbmanw +EC -> pc: 966e, 9679 -> 12 from bbmanw +D2 -> pc: 631c (it's used to update the high score) (6C, 6E, A6, AA, AE) -> AA + +the ones marked with "new" are checked against dynablst and bomberman tables +*/ + + +const UINT8 test_decryption_table[256] = { + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 00 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 20 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 70 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 80 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 90 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* A0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* C0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* E0 */ + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* F0 */ +}; + + +void irem_cpu_decrypt(INT32 /*cpu*/,const UINT8 *decryption_table, UINT8 *src, UINT8 *dest, INT32 size) +{ + for (INT32 A = 0;A < size;A++) + { + dest[A] = decryption_table[src[A]]; + } +} diff --git a/src/burn/drivers/irem/irem_cpu.h b/src/burn/drivers/irem/irem_cpu.h new file mode 100644 index 00000000..efd85edf --- /dev/null +++ b/src/burn/drivers/irem/irem_cpu.h @@ -0,0 +1,18 @@ +extern const UINT8 gunforce_decryption_table[]; +extern const UINT8 bomberman_decryption_table[]; +extern const UINT8 lethalth_decryption_table[]; +extern const UINT8 dynablaster_decryption_table[]; +extern const UINT8 mysticri_decryption_table[]; +extern const UINT8 majtitl2_decryption_table[]; +extern const UINT8 hook_decryption_table[]; +extern const UINT8 rtypeleo_decryption_table[]; +extern const UINT8 inthunt_decryption_table[]; +extern const UINT8 gussun_decryption_table[]; +extern const UINT8 leagueman_decryption_table[]; +extern const UINT8 psoldier_decryption_table[]; +extern const UINT8 dsoccr94_decryption_table[]; +extern const UINT8 matchit2_decryption_table[]; + +extern const UINT8 test_decryption_table[]; + +extern void irem_cpu_decrypt(INT32 cpu,const UINT8 *decryption_table, UINT8 *src,UINT8 *dest, INT32 size); diff --git a/src/burn/drivers/konami/d_88games.cpp b/src/burn/drivers/konami/d_88games.cpp new file mode 100644 index 00000000..87b39d7c --- /dev/null +++ b/src/burn/drivers/konami/d_88games.cpp @@ -0,0 +1,846 @@ +// FB Alpha '88 Games driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "UPD7759.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvGfxROMExp2; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvNVRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvBank; + +static INT32 videobank; +static INT32 zoomreadroms; +static INT32 k88games_priority; +static INT32 UPD7759Device; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo games88InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 3, "p3 start" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy3 + 2, "p3 fire 3" }, + + {"P4 Start", BIT_DIGITAL, DrvJoy3 + 7, "p4 start" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(games88) + +static struct BurnDIPInfo games88DIPList[]= +{ + {0x14, 0xff, 0xff, 0xf0, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x7b, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x10, 0x10, "Off" }, +// {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "World Records" }, + {0x14, 0x01, 0x20, 0x20, "Don't Erase" }, + {0x14, 0x01, 0x20, 0x00, "Erase on Reset" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "No Coin B" }, + +// {0 , 0xfe, 0 , 4, "Cabinet" }, +// {0x16, 0x01, 0x06, 0x06, "Cocktail" }, +// {0x16, 0x01, 0x06, 0x04, "Cocktail (A)" }, +// {0x16, 0x01, 0x06, 0x02, "Upright" }, +// {0x16, 0x01, 0x06, 0x00, "Upright (D)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x60, 0x60, "Easy" }, + {0x16, 0x01, 0x60, 0x40, "Normal" }, + {0x16, 0x01, 0x60, 0x20, "Hard" }, + {0x16, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(games88) + +void games88_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x5f84: + zoomreadroms = data & 0x04; + return; + + case 0x5f88: + // watchdog + return; + + case 0x5f8c: + *soundlatch = data; + return; + + case 0x5f90: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } + + if ((address & 0xf800) == 0x3800) + { + if (videobank) + DrvBankRAM[address & 0x7ff] = data; + else + K051316Write(0, address & 0x7ff, data); + + return; + } + + if ((address & 0xfff0) == 0x5fc0) { + K051316WriteCtrl(0, address & 0x0f, data); + return; + } + + if ((address & 0xc000) == 0x4000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 games88_main_read(UINT16 address) +{ + switch (address) + { + case 0x5f94: + return (DrvInputs[0] & 0x0f) | (DrvDips[0] & 0xf0); + + case 0x5f95: + return DrvInputs[1]; + + case 0x5f96: + return DrvInputs[2]; + + case 0x5f97: + return DrvDips[1]; + + case 0x5f9b: + return DrvDips[2]; + } + + if ((address & 0xf800) == 0x3800) + { + if (videobank) { + return DrvBankRAM[address & 0x7ff]; + } else { + if (zoomreadroms) { + return K051316ReadRom(0, address & 0x7ff); // k051316_rom_0 + } else { + return K051316Read(0, address & 0x7ff); // k051316_0 + } + } + } + + if ((address & 0xc000) == 0x4000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +void __fastcall games88_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + UPD7759PortWrite(UPD7759Device, data); + return; + + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xe000: + UPD7759Device = (data & 4) >> 2; + UPD7759ResetWrite(UPD7759Device, data & 2); + UPD7759StartWrite(UPD7759Device, data & 1); + return; + } +} + +UINT8 __fastcall games88_sound_read(UINT16 address) +{ + switch (address) + { + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc000: + case 0xc001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void games88_set_lines(INT32 lines) +{ + nDrvBank[0] = lines; + + INT32 nBank = 0x10000 + (lines & 0x07) * 0x2000; + + konamiMapMemory(DrvKonROM + nBank, 0x0000, 0x0fff, KON_ROM); + + if (lines & 8) { + konamiMapMemory(DrvPalRAM, 0x1000, 0x1fff, KON_RAM); + } else { + konamiMapMemory(DrvKonROM + nBank + 0x1000, 0x1000, 0x1fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x0000, 0x1000, 0x1fff, KON_WRITE); // unmap writes + } + + videobank = lines & 0x10; + K052109RMRDLine = lines & 0x20; + k88games_priority = lines & 0x80; +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + INT32 layer_colorbase[3] = { 64, 0, 16 }; + + *code |= ((*color & 0x0f) << 8) | (bank << 12); + *color = layer_colorbase[layer] + ((*color & 0xf0) >> 4); +} + +static void K051960Callback(INT32 */*code*/, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = (*color & 0x20) >> 5; + *color = 32 + (*color & 0x0f); +} + +static void K051316Callback(INT32 *code,INT32 *color,INT32 *flags) +{ + *flags = *color & 0x40; + *code |= ((*color & 0x07) << 8); + *color = 48 + ((*color & 0x38) >> 3) + ((*color & 0x80) >> 4); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + UPD7759Reset(); + + videobank = 0; + zoomreadroms = 0; + k88games_priority = 0; + UPD7759Device = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x020000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x040000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + DrvGfxROMExp2 = Next; Next += 0x080000; + + DrvSndROM0 = Next; Next += 0x020000; + DrvSndROM1 = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001000; + DrvPalRAM = Next; Next += 0x001000; + DrvNVRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + nDrvBank = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x008000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x010000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060001, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 25, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 26, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 27, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 28, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x020000, 29, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x030000, 30, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 31, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x010000, 32, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 33, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x010000, 34, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvPalRAM + 0x0000, 0x1000, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonRAM, 0x2000, 0x2fff, KON_RAM); + konamiMapMemory(DrvNVRAM, 0x3000, 0x37ff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x8000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(games88_main_write); + konamiSetReadHandler(games88_main_read); + konamiSetlinesCallback(games88_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(games88_sound_write); + ZetSetReadHandler(games88_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 75.0); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSndROM0); + UPD7759Init(1, UPD7759_STANDARD_CLOCK, DrvSndROM1); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(0, 0); + + K051960Init(DrvGfxROM1, 0xfffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(0, 0); + + K051316Init(0, DrvGfxROM2, DrvGfxROMExp2, 0x3ffff, K051316Callback, 4, 0); + K051316SetOffset(0, -104, -16); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + BurnYM2151Exit(); + UPD7759Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x1000); + } + + K052109UpdateScroll(); + + if (k88games_priority) + { + K052109RenderLayer(0, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + K052109RenderLayer(1, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 0); + K051316_zoom_draw(0, 4); + } + else + { + K052109RenderLayer(2, 1, DrvGfxROMExp0); + K051316_zoom_draw(0, 4); + K051960SpritesRender(DrvGfxROMExp1, 0); + K052109RenderLayer(1, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + UPD7759Update(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + UPD7759Update(1, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + UPD7759Scan(0, nAction, pnMin); + UPD7759Scan(0, nAction, pnMin); + + KonamiICScan(nAction); + + SCAN_VAR(videobank); + SCAN_VAR(zoomreadroms); + SCAN_VAR(k88games_priority); + SCAN_VAR(UPD7759Device); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + games88_set_lines(nDrvBank[0]); + konamiClose(); + } + + return 0; +} + + +// '88 Games + +static struct BurnRomInfo games88RomDesc[] = { + { "861m01.k18", 0x08000, 0x4a4e2959, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu + { "861m02.k16", 0x10000, 0xe19f15f6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles + { "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4 + { "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5 + { "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6 + { "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7 + { "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8 + { "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9 + { "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10 + + { "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles + { "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12 + { "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13 + { "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14 + { "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15 + { "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16 + { "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17 + { "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18 + { "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19 + { "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20 + { "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21 + { "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22 + { "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23 + { "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24 + { "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25 + { "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26 + + { "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles + { "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28 + { "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29 + { "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30 + + { "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples + { "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32 + + { "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples + { "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34 + + { "861.g3", 0x00100, 0x429785db, 0 | BRF_OPT }, // 31 Priority Prom +}; + +STD_ROM_PICK(games88) +STD_ROM_FN(games88) + +struct BurnDriver BurnDrvgames88 = { + "88games", NULL, NULL, NULL, "1988", + "'88 Games\0", NULL, "Konami", "GX861", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, games88RomInfo, games88RomName, NULL, NULL, games88InputInfo, games88DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Konami '88 + +static struct BurnRomInfo konami88RomDesc[] = { + { "861.e03", 0x08000, 0x55979bd9, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu + { "861.e02", 0x10000, 0x5b7e98a6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles + { "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4 + { "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5 + { "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6 + { "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7 + { "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8 + { "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9 + { "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10 + + { "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles + { "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12 + { "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13 + { "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14 + { "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15 + { "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16 + { "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17 + { "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18 + { "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19 + { "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20 + { "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21 + { "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22 + { "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23 + { "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24 + { "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25 + { "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26 + + { "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles + { "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28 + { "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29 + { "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30 + + { "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples + { "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32 + + { "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples + { "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34 + + { "861.g3", 0x00100, 0x429785db, 0 | BRF_OPT }, // 31 Priority Prom +}; + +STD_ROM_PICK(konami88) +STD_ROM_FN(konami88) + +struct BurnDriver BurnDrvKonami88 = { + "konami88", "88games", NULL, NULL, "1988", + "Konami '88\0", NULL, "Konami", "GX861", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, konami88RomInfo, konami88RomName, NULL, NULL, games88InputInfo, games88DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Hyper Sports Special (Japan) + +static struct BurnRomInfo hypsptspRomDesc[] = { + { "861f03.k18", 0x08000, 0x8c61aebd, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu + { "861f02.k16", 0x10000, 0xd2460c28, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles + { "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4 + { "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5 + { "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6 + { "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7 + { "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8 + { "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9 + { "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10 + + { "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles + { "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12 + { "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13 + { "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14 + { "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15 + { "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16 + { "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17 + { "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18 + { "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19 + { "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20 + { "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21 + { "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22 + { "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23 + { "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24 + { "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25 + { "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26 + + { "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles + { "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28 + { "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29 + { "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30 + + { "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples + { "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32 + + { "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples + { "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34 + + { "861.g3", 0x00100, 0x429785db, 8 | BRF_OPT }, // 31 Priority Prom +}; + +STD_ROM_PICK(hypsptsp) +STD_ROM_FN(hypsptsp) + +struct BurnDriver BurnDrvHypsptsp = { + "hypsptsp", "88games", NULL, NULL, "1988", + "Hyper Sports Special (Japan)\0", NULL, "Konami", "GX861", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, hypsptspRomInfo, hypsptspRomName, NULL, NULL, games88InputInfo, games88DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_ajax.cpp b/src/burn/drivers/konami/d_ajax.cpp new file mode 100644 index 00000000..3bc8f0ef --- /dev/null +++ b/src/burn/drivers/konami/d_ajax.cpp @@ -0,0 +1,940 @@ +// FB Alpha Ajax driver module +// Based on MAME driver by Manuel Abadia + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" +#include "m6809_intf.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvShareRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvBankRom; + +static UINT8 DrvInputs[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static INT32 firq_enable; +static INT32 ajax_priority; + +static struct BurnInputInfo AjaxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Ajax) + +static struct BurnDIPInfo AjaxDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x52, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x15, 0x01, 0x04, 0x00, "Upright" }, +// {0x15, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "30000 150000" }, + {0x15, 0x01, 0x18, 0x10, "50000 200000" }, + {0x15, 0x01, 0x18, 0x08, "30000" }, + {0x15, 0x01, 0x18, 0x00, "50000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x16, 0x01, 0x01, 0x01, "Off" }, +// {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x02, 0x02, "Single" }, + {0x16, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Control in 3D Stages" }, + {0x16, 0x01, 0x08, 0x08, "Normal" }, + {0x16, 0x01, 0x08, 0x00, "Inverted" }, +}; + +STDDIPINFO(Ajax) + +static void ajax_main_bankswitch(INT32 data) +{ + nDrvBankRom[0] = data; + + INT32 nBank = 0x10000 + ((data & 0x80) << 9) + ((data & 7) << 13); + + ajax_priority = data & 0x08; + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM); +} + +void ajax_main_write(UINT16 address, UINT8 data) +{ + if (address <= 0x1c0) + { + switch ((address & 0x01c0) >> 6) + { + case 0x0000: + if (address == 0 && firq_enable) { + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); + } + break; + + case 0x0001: + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + break; + + case 0x0002: + *soundlatch = data; + break; + + case 0x0003: + ajax_main_bankswitch(data); + break; + } + } + + if ((address & 0xfff8) == 0x0800) { + K051937Write(address & 7, data); + return; + } + + if ((address & 0xfc00) == 0x0c00) { + K051960Write(address & 0x3ff, data); + return; + } +} + +UINT8 ajax_main_read(UINT16 address) +{ + if (address <= 0x01c0) { + switch ((address & 0x1c0) >> 6) + { + case 0x0000: + return konamiTotalCycles() & 0xff; // rand + + case 0x0004: + return DrvInputs[2]; + + case 0x0006: + switch (address & 3) { + case 0: + return DrvInputs[0]; + + case 1: + return DrvInputs[1]; + + case 2: + return DrvDips[0]; + + case 3: + return DrvDips[1]; + } + return 0; + + case 0x0007: + return DrvDips[2]; + } + } + + if ((address & 0xfff8) == 0x0800) { + return K051937Read(address & 7); + } + + if ((address & 0xfc00) == 0x0c00) { + return K051960Read(address & 0x3ff); + } + + return 0; +} + +static void ajax_sub_bankswitch(UINT8 data) +{ + nDrvBankRom[1] = data; + + K052109RMRDLine = data & 0x40; + + K051316WrapEnable(0, data & 0x20); + + firq_enable = data & 0x10; + + INT32 nBank = ((data & 0x0f) << 13) + 0x10000; + M6809MapMemory(DrvM6809ROM + nBank, 0x8000, 0x9fff, M6809_ROM); +} + +void ajax_sub_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0x0000) { + K051316Write(0, address & 0x7ff, data); + return; + } + + if ((address & 0xfff0) == 0x0800) { + K051316WriteCtrl(0, address & 0x0f, data); + return; + } + + if (address == 0x1800) { + ajax_sub_bankswitch(data); + return; + } + + if ((address & 0xc000) == 0x4000) { + K052109Write(address & 0x3fff, data); + return; + } +} + +UINT8 ajax_sub_read(UINT16 address) +{ + if ((address & 0xf800) == 0x0000) { + return K051316Read(0, address & 0x7ff); + } + + if ((address & 0xf800) == 0x1000) { + return K051316ReadRom(0, address & 0x7ff); + } + + if ((address & 0xc000) == 0x4000) { + return K052109Read(address & 0x3fff); + } + + return 0; +} + +void __fastcall ajax_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xa000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(1, address & 0x0f, data); + return; + } + + switch (address) + { + case 0x9000: + k007232_set_bank(0, (data >> 1) & 1, (data >> 0) & 1 ); + k007232_set_bank(1, (data >> 4) & 3, (data >> 2) & 3 ); + return; + + case 0xb80c: + K007232SetVolume(1, 0, (data & 0x0f) * 0x11/2, (data & 0x0f) * 0x11/2); + return; + + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall ajax_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xa000) { + return K007232ReadReg(0, address & 0x0f); + } + + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(1, address & 0x0f); + } + + switch (address) + { + case 0xc000: + case 0xc001: + return BurnYM2151ReadStatus(); + + case 0xe000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + INT32 layer_colorbase[3] = { 64, 0, 32 }; + + *code |= ((*color & 0x0f) << 8) | (bank << 12); + *code &= 0x3fff; + *color = layer_colorbase[layer] + ((*color & 0xf0) >> 4); +} + +static void K051960Callback(INT32 *code, INT32 *color,INT32 *priority, INT32 *) +{ + *priority = 0; + if ( *color & 0x10) *priority = 1; + if (~*color & 0x40) *priority = 2; + if ( *color & 0x20) *priority = 3; + *color = 16 + (*color & 0x0f); + *code &= 0x1fff; +} + +static void K051316Callback(INT32 *code,INT32 *color,INT32 *) +{ + *code |= ((*color & 0x07) << 8); + *code &= 0x7ff; + *color = 6 + ((*color & 0x08) >> 3); +} + +static void DrvK007232VolCallback0(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void DrvK007232VolCallback1(INT32 v) +{ + K007232SetVolume(1, 0, (v & 0x0f) * 0x11/2, (v & 0x0f) * 0x11/2); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + firq_enable = 0; + ajax_priority = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x030000; + DrvM6809ROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM0 = Next; Next += 0x040000; + DrvSndROM1 = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvShareRAM = Next; Next += 0x002000; + DrvKonRAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x001000 + 0x1000; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + nDrvBankRom = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x020000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x010000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x28000, 0x8000); + + if (BurnLoadRom(DrvM6809ROM + 0x20000, 2, 1)) return 1; + memcpy (DrvM6809ROM + 0xa000, DrvM6809ROM + 0x22000, 0x6000); + if (BurnLoadRom(DrvM6809ROM + 0x10000, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "ajax") == 0) { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020001, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060001, 12, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020001, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 25, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 26, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 27, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 28, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 29, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 30, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 31, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x010000, 32, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x020000, 33, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x030000, 34, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 35, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x010000, 36, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x020000, 37, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x030000, 38, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x040000, 39, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x050000, 40, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x060000, 41, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x070000, 42, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 12, 1)) return 1; + } + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvPalRAM, 0x1000, 0x1fff, KON_RAM); + konamiMapMemory(DrvShareRAM, 0x2000, 0x3fff, KON_RAM); + konamiMapMemory(DrvKonRAM, 0x4000, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(ajax_main_write); + konamiSetReadHandler(ajax_main_read); + konamiClose(); + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvShareRAM, 0x2000, 0x3fff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x10000, 0x8000, 0x9fff, M6809_ROM); + M6809MapMemory(DrvM6809ROM + 0x0a000, 0xa000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(ajax_sub_write); + M6809SetReadByteHandler(ajax_sub_read); + M6809Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(ajax_sound_write); + ZetSetReadHandler(ajax_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 25.0); + + K007232Init(0, 3579545, DrvSndROM0, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback0); + + K007232Init(1, 3579545, DrvSndROM1, 0x80000); + K007232SetPortWriteHandler(1, DrvK007232VolCallback1); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0xfffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + K051316Init(0, DrvGfxROM2, DrvGfxROM2, 0x7ffff, K051316Callback, 7, 0); + K051316SetOffset(0, -112, -16); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + M6809Exit(); + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x1000); + } + + K052109UpdateScroll(); + + BurnTransferClear(); + + if (nBurnLayer & 1) K052109RenderLayer(2, 0, DrvGfxROMExp0); + + if (ajax_priority) + { + if (nBurnLayer & 2) K051316_zoom_draw(0, 4); + if (nBurnLayer & 4) K052109RenderLayer(1, 0, DrvGfxROMExp0); + } + else + { + if (nBurnLayer & 4) K052109RenderLayer(1, 0, DrvGfxROMExp0); + if (nBurnLayer & 2) K051316_zoom_draw(0, 4); + } + +// needs work... + if (nSpriteEnable & 1) K051960SpritesRender(DrvGfxROMExp1, 3); + if (nSpriteEnable & 2) K051960SpritesRender(DrvGfxROMExp1, 2); + if (nSpriteEnable & 4) K051960SpritesRender(DrvGfxROMExp1, 1); + if (nSpriteEnable & 8) K051960SpritesRender(DrvGfxROMExp1, 0); + + if (nBurnLayer & 8) K052109RenderLayer(0, 0, DrvGfxROMExp0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + INT32 nCyclesTotal[3] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + ZetOpen(0); + M6809Open(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nCyclesDone[1] += M6809Run(nSegment - nCyclesDone[1]); + nSegment = (nCyclesTotal[2] / nInterleave) * (i + 1); + + nCyclesDone[2] += ZetRun(nSegment - nCyclesDone[2]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + K007232Update(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K051960_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + K007232Update(1, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + M6809Close(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + M6809Scan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + ajax_main_bankswitch(nDrvBankRom[0]); + konamiClose(); + + M6809Open(0); + ajax_sub_bankswitch(nDrvBankRom[1]); + M6809Close(); + } + + return 0; +} + + +// Ajax + +static struct BurnRomInfo ajaxRomDesc[] = { + { "770_m01.n11", 0x10000, 0x4a64e53a, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "770_l02.n12", 0x10000, 0xad7d592b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "770_l05.i16", 0x08000, 0xed64fbb2, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code + { "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3 + + { "770_h03.f16", 0x08000, 0x2ffd2afc, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "770c13-a.f3", 0x10000, 0x4ef6fff2, 4 | BRF_GRA }, // 5 K052109 Tiles + { "770c13-c.f4", 0x10000, 0x97ffbab6, 4 | BRF_GRA }, // 6 + { "770c13-b.e3", 0x10000, 0x86fdd706, 4 | BRF_GRA }, // 7 + { "770c13-d.e4", 0x10000, 0x7d7acb2d, 4 | BRF_GRA }, // 8 + { "770c12-a.f5", 0x10000, 0x6c0ade68, 4 | BRF_GRA }, // 9 + { "770c12-c.f6", 0x10000, 0x61fc39cc, 4 | BRF_GRA }, // 10 + { "770c12-b.e5", 0x10000, 0x5f221cc6, 4 | BRF_GRA }, // 11 + { "770c12-d.e6", 0x10000, 0xf1edb2f4, 4 | BRF_GRA }, // 12 + + { "770c09-a.f8", 0x10000, 0x76690fb8, 5 | BRF_GRA }, // 13 K051960 Tiles + { "770c09-e.f9", 0x10000, 0x17b482c9, 5 | BRF_GRA }, // 14 + { "770c09-b.e8", 0x10000, 0xcd1709d1, 5 | BRF_GRA }, // 15 + { "770c09-f.e9", 0x10000, 0xcba4b47e, 5 | BRF_GRA }, // 16 + { "770c09-c.d8", 0x10000, 0xbfd080b8, 5 | BRF_GRA }, // 17 + { "770c09-g.d9", 0x10000, 0x77d58ea0, 5 | BRF_GRA }, // 18 + { "770c09-d.c8", 0x10000, 0x6f955600, 5 | BRF_GRA }, // 19 + { "770c09-h.c9", 0x10000, 0x494a9090, 5 | BRF_GRA }, // 20 + { "770c08-a.f10", 0x10000, 0xefd29a56, 5 | BRF_GRA }, // 21 + { "770c08-e.f11", 0x10000, 0x6d43afde, 5 | BRF_GRA }, // 22 + { "770c08-b.e10", 0x10000, 0xf3374014, 5 | BRF_GRA }, // 23 + { "770c08-f.e11", 0x10000, 0xf5ba59aa, 5 | BRF_GRA }, // 24 + { "770c08-c.d10", 0x10000, 0x28e7088f, 5 | BRF_GRA }, // 25 + { "770c08-g.d11", 0x10000, 0x17da8f6d, 5 | BRF_GRA }, // 26 + { "770c08-d.c10", 0x10000, 0x91591777, 5 | BRF_GRA }, // 27 + { "770c08-h.c11", 0x10000, 0xd97d4b15, 5 | BRF_GRA }, // 28 + + { "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 29 K051960 Tiles + { "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 30 + + { "770c10-a.a7", 0x10000, 0xe45ec094, 7 | BRF_SND }, // 31 K007232 #0 Samples + { "770c10-b.a6", 0x10000, 0x349db7d3, 7 | BRF_SND }, // 32 + { "770c10-c.a5", 0x10000, 0x71cb1f05, 7 | BRF_SND }, // 33 + { "770c10-d.a4", 0x10000, 0xe8ab1844, 7 | BRF_SND }, // 34 + + { "770c11-a.c6", 0x10000, 0x8cccd9e0, 8 | BRF_SND }, // 35 K007232 #1 Samples + { "770c11-b.c5", 0x10000, 0x0af2fedd, 8 | BRF_SND }, // 36 + { "770c11-c.c4", 0x10000, 0x7471f24a, 8 | BRF_SND }, // 37 + { "770c11-d.c3", 0x10000, 0xa58be323, 8 | BRF_SND }, // 38 + { "770c11-e.b7", 0x10000, 0xdd553541, 8 | BRF_SND }, // 39 + { "770c11-f.b6", 0x10000, 0x3f78bd0f, 8 | BRF_SND }, // 40 + { "770c11-g.b5", 0x10000, 0x078c51b2, 8 | BRF_SND }, // 41 + { "770c11-h.b4", 0x10000, 0x7300c2e1, 8 | BRF_SND }, // 42 + + { "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 43 Timing Prom (unused) +}; + +STD_ROM_PICK(ajax) +STD_ROM_FN(ajax) + +struct BurnDriver BurnDrvAjax = { + "ajax", NULL, NULL, NULL, "1987", + "Ajax\0", NULL, "Konami", "GX770", + L"Ajax\0\u30A8\u30FC\u30B8\u30E3\u30C3\u30AF\u30B9\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0, + NULL, ajaxRomInfo, ajaxRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 288, 3, 4 +}; + + +// Typhoon + +static struct BurnRomInfo typhoonRomDesc[] = { + { "770_k01.n11", 0x10000, 0x5ba74a22, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "770_k02.n12", 0x10000, 0x3bcf782a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "770_k05.i16", 0x08000, 0x0f1bebbb, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code + { "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3 + + { "770_h03.f16", 0x08000, 0x2ffd2afc, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "770c13", 0x40000, 0xb859ca4e, 4 | BRF_GRA }, // 5 K052109 Tiles + { "770c12", 0x40000, 0x50d14b72, 4 | BRF_GRA }, // 6 + + { "770c09", 0x80000, 0x1ab4a7ff, 5 | BRF_GRA }, // 7 K051960 Tiles + { "770c08", 0x80000, 0xa8e80586, 5 | BRF_GRA }, // 8 + + { "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 9 K051960 Tiles + { "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 10 + + { "770c10", 0x40000, 0x7fac825f, 7 | BRF_SND }, // 11 K007232 #0 Samples + + { "770c11", 0x80000, 0x299a615a, 8 | BRF_SND }, // 12 K007232 #1 Samples + + { "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 13 Timing Prom (unused) +}; + +STD_ROM_PICK(typhoon) +STD_ROM_FN(typhoon) + +struct BurnDriver BurnDrvTyphoon = { + "typhoon", "ajax", NULL, NULL, "1987", + "Typhoon\0", NULL, "Konami", "GX770", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0, + NULL, typhoonRomInfo, typhoonRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 288, 3, 4 +}; + + +// Ajax (Japan) + +static struct BurnRomInfo ajaxjRomDesc[] = { + { "770_l01.n11", 0x10000, 0x7cea5274, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "770_l02.n12", 0x10000, 0xad7d592b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "770_l05.i16", 0x08000, 0xed64fbb2, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 code + { "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3 + + { "770_f03.f16", 0x08000, 0x3fe914fd, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "770c13", 0x40000, 0xb859ca4e, 4 | BRF_GRA }, // 5 K052109 Tiles + { "770c12", 0x40000, 0x50d14b72, 4 | BRF_GRA }, // 6 + + { "770c09", 0x80000, 0x1ab4a7ff, 5 | BRF_GRA }, // 7 K051960 Tiles + { "770c08", 0x80000, 0xa8e80586, 5 | BRF_GRA }, // 8 + + { "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 9 K051960 Tiles + { "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 10 + + { "770c10", 0x40000, 0x7fac825f, 7 | BRF_SND }, // 11 K007232 #0 Samples + + { "770c11", 0x80000, 0x299a615a, 8 | BRF_SND }, // 12 K007232 #1 Samples + + { "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 13 Timing Prom (unused) +}; + +STD_ROM_PICK(ajaxj) +STD_ROM_FN(ajaxj) + +struct BurnDriver BurnDrvAjaxj = { + "ajaxj", "ajax", NULL, NULL, "1987", + "Ajax (Japan)\0", NULL, "Konami", "GX770", + L"Ajax\0\u30A8\u30FC\u30B8\u30E3\u30C3\u30AF\u30B9 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0, + NULL, ajaxjRomInfo, ajaxjRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/konami/d_aliens.cpp b/src/burn/drivers/konami/d_aliens.cpp new file mode 100644 index 00000000..1ad53345 --- /dev/null +++ b/src/burn/drivers/konami/d_aliens.cpp @@ -0,0 +1,854 @@ +// FB Alpha Aliens driver module +// Based on MAME driver by Manuel Abadia + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvRamBank; +static UINT8 *nDrvKonamiBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static struct BurnInputInfo AliensInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Aliens) + +static struct BurnDIPInfo AliensDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x5e, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "No Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "1" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x01, "3" }, + {0x13, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x01, 0x01, "Off" }, +// {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Aliens) + +static void set_ram_bank(INT32 data) +{ + nDrvRamBank[0] = data; + + if (data & 0x20) { + konamiMapMemory(DrvPalRAM, 0x0000, 0x03ff, KON_RAM); + } else { + konamiMapMemory(DrvBankRAM, 0x0000, 0x03ff, KON_RAM); + } +} + +void aliens_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x5f88: + set_ram_bank(data & 0x20); + K052109RMRDLine = data & 0x40; + return; + + case 0x5f8c: + *soundlatch = data; + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + + //ZetRaiseIrq(0xff); + return; + } + + if ((address & 0xc000) == 0x4000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 aliens_main_read(UINT16 address) +{ + switch (address) + { + case 0x5f80: + return DrvDips[2]; + + case 0x5f81: + return DrvInputs[0]; + + case 0x5f82: + return DrvInputs[1]; + + case 0x5f83: + return DrvDips[1]; + + case 0x5f84: + return DrvDips[0]; + + case 0x5f88: + // watchdog reset + return 0; + } + + if ((address & 0xc000) == 0x4000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +void __fastcall aliens_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xe000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xa000: + BurnYM2151SelectRegister(data); + return; + + case 0xa001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall aliens_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xe000) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xa000: + case 0xa001: + return BurnYM2151ReadStatus(); + + case 0xc000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + INT32 bank_A = ((data >> 1) & 0x01); + INT32 bank_B = ((data) & 0x01); + + k007232_set_bank(0, bank_A, bank_B ); +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void aliens_set_lines(INT32 lines) +{ + nDrvKonamiBank[0] = lines; + + INT32 nBank = (lines & 0x1f) * 0x2000; + + konamiMapMemory(DrvKonROM + 0x10000 + nBank, 0x2000, 0x3fff, KON_ROM); +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x3f) << 8) | (bank << 14); + *code &= 0xffff; + *color = (layer << 2) + ((*color & 0xc0) >> 6); +} + +static void K051960Callback(INT32 *code, INT32 *color,INT32 *priority, INT32 *shadow) +{ + switch (*color & 0x70) + { + case 0x10: *priority = 0x00; break; + case 0x00: *priority = 0x01; break; + case 0x40: *priority = 0x02; break; + + case 0x20: + case 0x60: *priority = 0x03; break; + + // when are these used? + case 0x50: *priority = 0x04; break; + case 0x30: + case 0x70: *priority = 0x05; break; + } + *code |= (*color & 0x80) << 6; + *code &= 0x3fff; + *color = 16 + (*color & 0x0f); + *shadow = 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROMExp0 = Next; Next += 0x400000; + DrvGfxROMExp1 = Next; Next += 0x400000; + + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x200 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000400; + DrvKonRAM = Next; Next += 0x001c00; + DrvPalRAM = Next; Next += 0x000400; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvRamBank = Next; Next += 0x000001; + nDrvKonamiBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x200000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x200000); + + GfxDecode(0x10000, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x04000, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x030000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x010000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x38000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x180000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 11, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvBankRAM, 0x0000, 0x03ff, KON_RAM); + konamiMapMemory(DrvKonRAM, 0x0400, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x2000, 0x3fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(aliens_main_write); + konamiSetReadHandler(aliens_main_read); + konamiSetlinesCallback(aliens_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(aliens_sound_write); + ZetSetReadHandler(aliens_sound_read); + ZetMemEnd(); + ZetClose(); + + K052109Init(DrvGfxROM0, 0x1fffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0x1fffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + K007232Init(0, 3579545, DrvSndROM, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x400); + } + + K052109UpdateScroll(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x0040; + } + + K051960SpritesRender(DrvGfxROMExp1, 3); + K052109RenderLayer(1, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 0); + + K051960SpritesRender(DrvGfxROMExp1, 4); + K051960SpritesRender(DrvGfxROMExp1, 5); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvDips[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = nBurnSoundLen; + INT32 nCyclesTotal[2] = { 6000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K051960_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + set_ram_bank(nDrvRamBank[0]); + aliens_set_lines(nDrvKonamiBank[0]); + konamiClose(); + } + + return 0; +} + + +// Aliens (World set 1) + +static struct BurnRomInfo aliensRomDesc[] = { + { "875_j02.e24", 0x10000, 0x56c20971, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_j01.c24", 0x20000, 0x6a529cd6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_b03.g04", 0x08000, 0x1ac4d283, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliens) +STD_ROM_FN(aliens) + +struct BurnDriver BurnDrvAliens = { + "aliens", NULL, NULL, NULL, "1990", + "Aliens (World set 1)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliensRomInfo, aliensRomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (World set 2) + +static struct BurnRomInfo aliens2RomDesc[] = { + { "875_p02.e24", 0x10000, 0x4edd707d, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_n01.c24", 0x20000, 0x106cf59c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_b03.g04", 0x08000, 0x1ac4d283, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliens2) +STD_ROM_FN(aliens2) + +struct BurnDriver BurnDrvAliens2 = { + "aliens2", "aliens", NULL, NULL, "1990", + "Aliens (World set 2)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliens2RomInfo, aliens2RomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (World set 3) + +static struct BurnRomInfo aliens3RomDesc[] = { + { "875_w3_2.e24", 0x10000, 0xf917f7b5, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_w3_1.c24", 0x20000, 0x3c0006fb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_b03.g04", 0x08000, 0x1ac4d283, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliens3) +STD_ROM_FN(aliens3) + +struct BurnDriver BurnDrvAliens3 = { + "aliens3", "aliens", NULL, NULL, "1990", + "Aliens (World set 3)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliens3RomInfo, aliens3RomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (US) + +static struct BurnRomInfo aliensuRomDesc[] = { + { "875_n02.e24", 0x10000, 0x24dd612e, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_n01.c24", 0x20000, 0x106cf59c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_b03.g04", 0x08000, 0x1ac4d283, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliensu) +STD_ROM_FN(aliensu) + +struct BurnDriver BurnDrvAliensu = { + "aliensu", "aliens", NULL, NULL, "1990", + "Aliens (US)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliensuRomInfo, aliensuRomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (Japan set 1) + +static struct BurnRomInfo aliensjRomDesc[] = { + { "875_m02.e24", 0x10000, 0x54a774e5, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_m01.c24", 0x20000, 0x1663d3dc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_k03.g04", 0x08000, 0xbd86264d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliensj) +STD_ROM_FN(aliensj) + +struct BurnDriver BurnDrvAliensj = { + "aliensj", "aliens", NULL, NULL, "1990", + "Aliens (Japan set 1)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliensjRomInfo, aliensjRomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (Japan set 2) + +static struct BurnRomInfo aliensj2RomDesc[] = { + { "875_j2_2.e24", 0x10000, 0x4bb84952, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_m01.c24", 0x20000, 0x1663d3dc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_k03.g04", 0x08000, 0xbd86264d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliensj2) +STD_ROM_FN(aliensj2) + +struct BurnDriver BurnDrvAliensj2 = { + "aliensj2", "aliens", NULL, NULL, "1990", + "Aliens (Japan set 2)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliensj2RomInfo, aliensj2RomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Aliens (Asia) + +static struct BurnRomInfo aliensaRomDesc[] = { + { "875_r02.e24", 0x10000, 0x973e4f11, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + { "875_m01.c24", 0x20000, 0x1663d3dc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "875_k03.g04", 0x08000, 0xbd86264d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "875b11.k13", 0x80000, 0x89c5c885, 3 | BRF_GRA }, // 3 Background Tiles + { "875b07.j13", 0x40000, 0xe9c56d66, 3 | BRF_GRA }, // 4 + { "875b12.k19", 0x80000, 0xea6bdc17, 3 | BRF_GRA }, // 5 + { "875b08.j19", 0x40000, 0xf9387966, 3 | BRF_GRA }, // 6 + + { "875b10.k08", 0x80000, 0x0b1035b1, 4 | BRF_GRA }, // 7 Sprites + { "875b06.j08", 0x40000, 0x081a0566, 4 | BRF_GRA }, // 8 + { "875b09.k02", 0x80000, 0xe76b3c19, 4 | BRF_GRA }, // 9 + { "875b05.j02", 0x40000, 0x19a261f2, 4 | BRF_GRA }, // 10 + + { "875b04.e05", 0x40000, 0x4e209ac8, 5 | BRF_SND }, // 11 K007232 Samples + + { "821a08.h14", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 12 Timing Proms +}; + +STD_ROM_PICK(aliensa) +STD_ROM_FN(aliensa) + +struct BurnDriver BurnDrvAliensa = { + "aliensa", "aliens", NULL, NULL, "1990", + "Aliens (Asia)\0", NULL, "Konami", "GX875", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, aliensaRomInfo, aliensaRomName, NULL, NULL, AliensInputInfo, AliensDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_blockhl.cpp b/src/burn/drivers/konami/d_blockhl.cpp new file mode 100644 index 00000000..13b4f002 --- /dev/null +++ b/src/burn/drivers/konami/d_blockhl.cpp @@ -0,0 +1,589 @@ +// FB Alpha Block Hole driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvKonamiBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo BlockhlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Blockhl) + +static struct BurnDIPInfo BlockhlDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x5f, NULL }, + {0x16, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x15, 0x01, 0x01, 0x01, "1" }, + {0x15, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x16, 0x01, 0x10, 0x10, "Off" }, +// {0x16, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Blockhl) + +void blockhl_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1f84: + *soundlatch = data; + return; + + case 0x1f88: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x1f8c: + // watchdog + return; + } + + if ((address & 0xc000) == 0x0000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 blockhl_main_read(UINT16 address) +{ + switch (address) + { + case 0x1f94: + return DrvDips[2] | (DrvInputs[2] & 0x0f); + + case 0x1f95: + return DrvInputs[0]; + + case 0x1f96: + return DrvInputs[1]; + + case 0x1f97: + return DrvDips[0]; + + case 0x1f98: + return DrvDips[1]; + } + + if ((address & 0xc000) == 0x0000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +void __fastcall blockhl_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall blockhl_sound_read(UINT16 address) +{ + switch (address) + { + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void blockhl_set_lines(INT32 lines) +{ + INT32 nBank = (lines & 0x03) * 0x2000; + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM); + + if (~lines & 0x20) { + konamiMapMemory(DrvPalRAM, 0x5800, 0x5fff, KON_RAM); + } else { + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + } + + K052109RMRDLine = lines & 0x40; + + nDrvKonamiBank[0] = lines; +} + +static void K052109Callback(INT32 layer, INT32, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x0f) << 8); + *code &= 0xfff; + *color = (layer << 4) + ((*color & 0xe0) >> 5); +} + +static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = (*color & 0x10) >> 4; + + *code &= 0x3ff; + *color = 0x30 + (*color & 0x0f); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x010000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x020000; + DrvGfxROMExp0 = Next; Next += 0x040000; + DrvGfxROMExp1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001800; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvKonamiBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x20000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x20000); + + GfxDecode(0x01000, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x00400, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010001, 5, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010001, 9, 2)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x4000, 0x57ff, KON_RAM); + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x00000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(blockhl_main_write); + konamiSetReadHandler(blockhl_main_read); + konamiSetlinesCallback(blockhl_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(blockhl_sound_write); + ZetSetReadHandler(blockhl_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + + K052109Init(DrvGfxROM0, 0x1ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0x1ffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x800); + } + + K052109UpdateScroll(); + + K052109RenderLayer(2, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 0); + K052109RenderLayer(1, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled && (nDrvKonamiBank[0] & 0x03) == 0) + konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + blockhl_set_lines(nDrvKonamiBank[0]); + konamiClose(); + } + + return 0; +} + + +// Block Hole + +static struct BurnRomInfo blockhlRomDesc[] = { + { "973l02.e21", 0x10000, 0xe14f849a, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "973d01.g6", 0x08000, 0xeeee9d92, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "973f07.k15", 0x08000, 0x1a8cd9b4, 3 | BRF_GRA }, // 2 Background Tiles + { "973f08.k18", 0x08000, 0x952b51a6, 3 | BRF_GRA }, // 3 + { "973f09.k20", 0x08000, 0x77841594, 3 | BRF_GRA }, // 4 + { "973f10.k23", 0x08000, 0x09039fab, 3 | BRF_GRA }, // 5 + + { "973f06.k12", 0x08000, 0x51acfdb6, 4 | BRF_GRA }, // 6 Sprites + { "973f05.k9", 0x08000, 0x4cfea298, 4 | BRF_GRA }, // 7 + { "973f04.k7", 0x08000, 0x69ca41bd, 4 | BRF_GRA }, // 8 + { "973f03.k4", 0x08000, 0x21e98472, 4 | BRF_GRA }, // 9 + + { "973a11.h10", 0x00100, 0x46d28fe9, 5 | BRF_OPT }, // 10 Proms +}; + +STD_ROM_PICK(blockhl) +STD_ROM_FN(blockhl) + +struct BurnDriver BurnDrvBlockhl = { + "blockhl", NULL, NULL, NULL, "1989", + "Block Hole\0", NULL, "Konami", "GX973", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_PUZZLE, 0, + NULL, blockhlRomInfo, blockhlRomName, NULL, NULL, BlockhlInputInfo, BlockhlDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Quarth (Japan) + +static struct BurnRomInfo quarthRomDesc[] = { + { "973j02.e21", 0x10000, 0x27a90118, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "973d01.g6", 0x08000, 0xeeee9d92, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "973e07.k15", 0x08000, 0x0bd6b0f8, 3 | BRF_GRA }, // 2 Background Tiles + { "973e08.k18", 0x08000, 0x104d0d5f, 3 | BRF_GRA }, // 3 + { "973e09.k20", 0x08000, 0xbd3a6f24, 3 | BRF_GRA }, // 4 + { "973e10.k23", 0x08000, 0xcf5e4b86, 3 | BRF_GRA }, // 5 + + { "973e06.k12", 0x08000, 0x0d58af85, 4 | BRF_GRA }, // 6 Sprites + { "973e05.k9", 0x08000, 0x15d822cb, 4 | BRF_GRA }, // 7 + { "973e04.k7", 0x08000, 0xd70f4a2c, 4 | BRF_GRA }, // 8 + { "973e03.k4", 0x08000, 0x2c5a4b4b, 4 | BRF_GRA }, // 9 + + { "973a11.h10", 0x00100, 0x46d28fe9, 5 | BRF_OPT }, // 10 Proms +}; + +STD_ROM_PICK(quarth) +STD_ROM_FN(quarth) + +struct BurnDriver BurnDrvQuarth = { + "quarth", "blockhl", NULL, NULL, "1989", + "Quarth (Japan)\0", NULL, "Konami", "GX973", + L"Quarth\0\u30AF\u30A9\u30FC\u30B9 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PUZZLE, 0, + NULL, quarthRomInfo, quarthRomName, NULL, NULL, BlockhlInputInfo, BlockhlDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_bottom9.cpp b/src/burn/drivers/konami/d_bottom9.cpp new file mode 100644 index 00000000..43981f37 --- /dev/null +++ b/src/burn/drivers/konami/d_bottom9.cpp @@ -0,0 +1,929 @@ +// FB Alpha Bottom of the Nineth driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "konamiic.h" +#include "k007232.h" +#include "m6809_intf.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvGfxROMExp2; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvM6809RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nmi_enable; +static UINT8 *nDrvBank; + +static INT32 bottom9_video_enable; +static INT32 zoomreadroms; +static INT32 K052109_selected; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static struct BurnInputInfo Bottom9InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Bottom9) + +static struct BurnDIPInfo Bottom9DIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x4c, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x00, "4 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x00, "4 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 8, "Play Time" }, + {0x13, 0x01, 0x07, 0x07, "1'00" }, + {0x13, 0x01, 0x07, 0x06, "1'10" }, + {0x13, 0x01, 0x07, 0x05, "1'20" }, + {0x13, 0x01, 0x07, 0x04, "1'30" }, + {0x13, 0x01, 0x07, 0x03, "1'40" }, + {0x13, 0x01, 0x07, 0x02, "1'50" }, + {0x13, 0x01, 0x07, 0x01, "2'00" }, + {0x13, 0x01, 0x07, 0x00, "2'10" }, + + {0 , 0xfe, 0 , 4, "Bonus Time" }, + {0x13, 0x01, 0x18, 0x18, "00" }, + {0x13, 0x01, 0x18, 0x10, "20" }, + {0x13, 0x01, 0x18, 0x08, "30" }, + {0x13, 0x01, 0x18, 0x00, "40" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x10, 0x10, "Off" }, +// {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Fielder Control" }, + {0x14, 0x01, 0x80, 0x80, "Normal" }, + {0x14, 0x01, 0x80, 0x00, "Auto" }, +}; + +STDDIPINFO(Bottom9) + +static struct BurnDIPInfo MstadiumDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x49, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x00, "4 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x00, "4 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Play Inning" }, + {0x13, 0x01, 0x03, 0x03, "1 Inning" }, + {0x13, 0x01, 0x03, 0x02, "2 Inning" }, + {0x13, 0x01, 0x03, 0x01, "3 Inning" }, + {0x13, 0x01, 0x03, 0x00, "4 Inning" }, + + {0 , 0xfe, 0 , 4, "Play Inning Time" }, + {0x13, 0x01, 0x0c, 0x0c, "06 Min" }, + {0x13, 0x01, 0x0c, 0x08, "08 Min" }, + {0x13, 0x01, 0x0c, 0x04, "10 Min" }, + {0x13, 0x01, 0x0c, 0x00, "12 Min" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x10, 0x10, "Off" }, +// {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Fielder Control" }, + {0x14, 0x01, 0x80, 0x80, "Normal" }, + {0x14, 0x01, 0x80, 0x00, "Auto" }, +}; + +STDDIPINFO(Mstadium) + +static void bankswitch(INT32 data) +{ + nDrvBank[0] = data; + + INT32 offs = 0x10000 + (data & 0x1e) * 0x1000; + + M6809MapMemory(DrvM6809ROM + offs, 0x6000, 0x7fff, M6809_ROM); +} + +void bottom9_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1f80: + bankswitch(data); + return; + + case 0x1f90: + { + K052109RMRDLine = data & 0x04; + bottom9_video_enable = ~data & 0x08; + zoomreadroms = data & 0x10; + K052109_selected = data & 0x20; + } + return; + + case 0x1fa0: + // watchdog + return; + + case 0x1fb0: + *soundlatch = data; + return; + + case 0x1fc0: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } + + if ((address & 0xfff0) == 0x1ff0) { + K051316WriteCtrl(0, address & 0x0f, data); + return; + } + + if (K052109_selected == 0) { + if ((address & 0xf800) == 0x0000) { + K051316Write(0, address & 0x7ff, data); + return; + } + + if ((address & 0xf800) == 0x2000) { + DrvPalRAM[address & 0x7ff] = data; + return; + } + } + + if ((address & 0xc000) == 0x0000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 bottom9_main_read(UINT16 address) +{ + switch (address) + { + case 0x1fd0: + return (DrvInputs[2] & 0x0f) | (DrvDips[2] & 0xf0); + + case 0x1fd1: + return DrvInputs[0]; + + case 0x1fd2: + return DrvInputs[1]; + + case 0x1fd3: + return DrvDips[0]; + + case 0x1fe0: + return DrvDips[1]; + } + + + if (K052109_selected == 0) { + if ((address & 0xf800) == 0x0000) { + if (zoomreadroms) + return K051316ReadRom(0, address & 0x7ff); + else + return K051316Read(0, address & 0x7ff); + } + + if ((address & 0xf800) == 0x2000) { + return DrvPalRAM[address & 0x7ff]; + } + } + + if ((address & 0xc000) == 0x0000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +static void sound_bank_w(INT32 data) +{ + k007232_set_bank(0, (data >> 0) & 0x03, (data >> 2) & 0x03); + k007232_set_bank(1, (data >> 4) & 0x03, (data >> 6) & 0x03); +} + +void __fastcall bottom9_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xa000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(1, address & 0x0f, data); + return; + } + + switch (address) + { + case 0x9000: + sound_bank_w(data); + return; + + case 0xf000: + *nmi_enable = data; + return; + } +} + +UINT8 __fastcall bottom9_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xa000) { + return K007232ReadReg(0, address & 0x0f); + } + + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(1, address & 0x0f); + } + + switch (address) + { + case 0xd000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= (*color & 0x3f) << 8; + *color = ((layer & 2) << 3) | ((*color & 0xc0) >> 6); +} + +static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = (*color & 0x30) >> 4; + *color = 0x20 + (*color & 0x0f); + *code &= 0x1fff; +} + +static void K051316Callback(INT32 *code,INT32 *color,INT32 *flags) +{ + *flags = (*color & 0x40) >> 6; + *code |= ((*color & 0x03) << 8); + *color = 0x30 | ((*color & 0x3c) >> 2); +} + +static void DrvK007232VolCallback0(int v) +{ + K007232SetVolume(0,0,(v >> 4) * 0x11,0); + K007232SetVolume(0,1,0,(v & 0x0f) * 0x11); +} + +static void DrvK007232VolCallback1(INT32 v) +{ + K007232SetVolume(1,0,(v >> 4) * 0x11,0); + K007232SetVolume(1,1,0,(v & 0x0f) * 0x11); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + KonamiICReset(); + + bottom9_video_enable = 0; + zoomreadroms = 0; + K052109_selected = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x020000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + DrvGfxROMExp2 = Next; Next += 0x040000; + + DrvSndROM0 = Next; Next += 0x040000; + DrvSndROM1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvM6809RAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + nmi_enable = Next; Next += 0x000001; + nDrvBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x000000, 1, 1)) return 1; + memcpy (DrvM6809ROM + 0x20000, DrvM6809ROM + 0x00000, 0x8000); + memcpy (DrvM6809ROM + 0x28000, DrvM6809ROM + 0x00000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060001, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 25, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 26, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 27, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 28, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 29, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x010000, 30, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x020000, 31, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x030000, 32, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 33, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x010000, 34, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x020000, 35, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x030000, 36, 1)) return 1; + + DrvGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809RAM, 0x4000, 0x5fff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x10000, 0x6000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvM6809ROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(bottom9_main_write); + M6809SetReadByteHandler(bottom9_main_read); + M6809Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(bottom9_sound_write); + ZetSetReadHandler(bottom9_sound_read); + ZetMemEnd(); + ZetClose(); + + K007232Init(0, 3579545, DrvSndROM0, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback0); + + K007232Init(1, 3579545, DrvSndROM1, 0x40000); + K007232SetPortWriteHandler(1, DrvK007232VolCallback1); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0xfffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + K051316Init(0, DrvGfxROM2, DrvGfxROMExp2, 0x1ffff, K051316Callback, 4, 0); + K051316SetOffset(0, -112, -16); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + M6809Exit(); + ZetExit(); + + K007232Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x800); + } + + K052109UpdateScroll(); + + BurnTransferClear(); + + K051960SpritesRender(DrvGfxROMExp1, 1); + K051316_zoom_draw(0, 0); + K051960SpritesRender(DrvGfxROMExp1, 0); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + K051960SpritesRender(DrvGfxROMExp1, 3); + K052109RenderLayer(1, 0, DrvGfxROMExp0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x06) == 0) DrvInputs[0] |= 0x06; + if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18; + if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06; + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + } + + INT32 nInterleave = 8; + INT32 nCyclesTotal[2] = { 2000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + M6809Open(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += M6809Run(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + if (*nmi_enable) ZetNmi(); + } + + if (K052109_irq_enabled) M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + memset(pBurnSoundOut, 0, nBurnSoundLen * sizeof(INT16) * 2); + K007232Update(0, pBurnSoundOut, nBurnSoundLen); + K007232Update(1, pBurnSoundOut, nBurnSoundLen); + } + + M6809Close(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6809Scan(nAction); + ZetScan(nAction); + + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + + SCAN_VAR(bottom9_video_enable); + SCAN_VAR(zoomreadroms); + SCAN_VAR(K052109_selected); + } + + if (nAction & ACB_WRITE) { + M6809Open(0); + bankswitch(nDrvBank[0]); + M6809Close(); + } + + return 0; +} + + +// Bottom of the Ninth (ver. T) + +static struct BurnRomInfo bottom9RomDesc[] = { + { "891n03.k17", 0x10000, 0x8b083ff3, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "891-t02.k15", 0x10000, 0x2c10ced2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "891j01.g8", 0x08000, 0x31b0a0a8, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "891e10c", 0x10000, 0x209b0431, 3 | BRF_GRA }, // 3 K052109 Tiles + { "891e10a", 0x10000, 0x8020a9e8, 3 | BRF_GRA }, // 4 + { "891e10d", 0x10000, 0x16d5fd7a, 3 | BRF_GRA }, // 5 + { "891e10b", 0x10000, 0x30121cc0, 3 | BRF_GRA }, // 6 + { "891e09c", 0x10000, 0x9dcaefbf, 3 | BRF_GRA }, // 7 + { "891e09a", 0x10000, 0x56b0ead9, 3 | BRF_GRA }, // 8 + { "891e09d", 0x10000, 0x4e1335e6, 3 | BRF_GRA }, // 9 + { "891e09b", 0x10000, 0xb6f914fb, 3 | BRF_GRA }, // 10 + + { "891e06e", 0x10000, 0x0b04db1c, 4 | BRF_GRA }, // 11 K051960 Tiles + { "891e06a", 0x10000, 0x5ee37327, 4 | BRF_GRA }, // 12 + { "891e06f", 0x10000, 0xf9ada524, 4 | BRF_GRA }, // 13 + { "891e06b", 0x10000, 0x2295dfaa, 4 | BRF_GRA }, // 14 + { "891e06g", 0x10000, 0x04abf78f, 4 | BRF_GRA }, // 15 + { "891e06c", 0x10000, 0xdbdb0d55, 4 | BRF_GRA }, // 16 + { "891e06h", 0x10000, 0x5d5ded8c, 4 | BRF_GRA }, // 17 + { "891e06d", 0x10000, 0xf9ecbd71, 4 | BRF_GRA }, // 18 + { "891e05e", 0x10000, 0xb356e729, 4 | BRF_GRA }, // 19 + { "891e05a", 0x10000, 0xbfd5487e, 4 | BRF_GRA }, // 20 + { "891e05f", 0x10000, 0xecdd11c5, 4 | BRF_GRA }, // 21 + { "891e05b", 0x10000, 0xaba18d24, 4 | BRF_GRA }, // 22 + { "891e05g", 0x10000, 0xc315f9ae, 4 | BRF_GRA }, // 23 + { "891e05c", 0x10000, 0x21fcbc6f, 4 | BRF_GRA }, // 24 + { "891e05h", 0x10000, 0xb0aba53b, 4 | BRF_GRA }, // 25 + { "891e05d", 0x10000, 0xf6d3f886, 4 | BRF_GRA }, // 26 + + { "891e07a", 0x10000, 0xb8d8b939, 5 | BRF_GRA }, // 27 K051316 Tiles + { "891e07b", 0x10000, 0x83b2f92d, 5 | BRF_GRA }, // 28 + + { "891e08a", 0x10000, 0xcef667bf, 6 | BRF_GRA }, // 29 K007232 #0 Samples + { "891e08b", 0x10000, 0xf7c14a7a, 6 | BRF_GRA }, // 30 + { "891e08c", 0x10000, 0x756b7f3c, 6 | BRF_GRA }, // 31 + { "891e08d", 0x10000, 0xcd0d7305, 6 | BRF_GRA }, // 32 + + { "891e04a", 0x10000, 0xdaebbc74, 7 | BRF_GRA }, // 33 K007232 #1 Samples + { "891e04b", 0x10000, 0x5ffb9ad1, 7 | BRF_GRA }, // 34 + { "891e04c", 0x10000, 0x2dbbf16b, 7 | BRF_GRA }, // 35 + { "891e04d", 0x10000, 0x8b0cd2cc, 7 | BRF_GRA }, // 36 + + { "891b11.f23", 0x00100, 0xecb854aa, 8 | BRF_OPT }, // 37 Priority Proms +}; + +STD_ROM_PICK(bottom9) +STD_ROM_FN(bottom9) + +struct BurnDriver BurnDrvBottom9 = { + "bottom9", NULL, NULL, NULL, "1989", + "Bottom of the Ninth (ver. T)\0", NULL, "Konami", "GX891", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, bottom9RomInfo, bottom9RomName, NULL, NULL, Bottom9InputInfo, Bottom9DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Bottom of the Ninth (ver. N) + +static struct BurnRomInfo bottom9nRomDesc[] = { + { "891n03.k17", 0x10000, 0x8b083ff3, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "891n02.k15", 0x10000, 0xd44d9ed4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "891j01.g8", 0x08000, 0x31b0a0a8, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "891e10c", 0x10000, 0x209b0431, 3 | BRF_GRA }, // 3 K052109 Tiles + { "891e10a", 0x10000, 0x8020a9e8, 3 | BRF_GRA }, // 4 + { "891e10d", 0x10000, 0x16d5fd7a, 3 | BRF_GRA }, // 5 + { "891e10b", 0x10000, 0x30121cc0, 3 | BRF_GRA }, // 6 + { "891e09c", 0x10000, 0x9dcaefbf, 3 | BRF_GRA }, // 7 + { "891e09a", 0x10000, 0x56b0ead9, 3 | BRF_GRA }, // 8 + { "891e09d", 0x10000, 0x4e1335e6, 3 | BRF_GRA }, // 9 + { "891e09b", 0x10000, 0xb6f914fb, 3 | BRF_GRA }, // 10 + + { "891e06e", 0x10000, 0x0b04db1c, 4 | BRF_GRA }, // 11 K051960 Tiles + { "891e06a", 0x10000, 0x5ee37327, 4 | BRF_GRA }, // 12 + { "891e06f", 0x10000, 0xf9ada524, 4 | BRF_GRA }, // 13 + { "891e06b", 0x10000, 0x2295dfaa, 4 | BRF_GRA }, // 14 + { "891e06g", 0x10000, 0x04abf78f, 4 | BRF_GRA }, // 15 + { "891e06c", 0x10000, 0xdbdb0d55, 4 | BRF_GRA }, // 16 + { "891e06h", 0x10000, 0x5d5ded8c, 4 | BRF_GRA }, // 17 + { "891e06d", 0x10000, 0xf9ecbd71, 4 | BRF_GRA }, // 18 + { "891e05e", 0x10000, 0xb356e729, 4 | BRF_GRA }, // 19 + { "891e05a", 0x10000, 0xbfd5487e, 4 | BRF_GRA }, // 20 + { "891e05f", 0x10000, 0xecdd11c5, 4 | BRF_GRA }, // 21 + { "891e05b", 0x10000, 0xaba18d24, 4 | BRF_GRA }, // 22 + { "891e05g", 0x10000, 0xc315f9ae, 4 | BRF_GRA }, // 23 + { "891e05c", 0x10000, 0x21fcbc6f, 4 | BRF_GRA }, // 24 + { "891e05h", 0x10000, 0xb0aba53b, 4 | BRF_GRA }, // 25 + { "891e05d", 0x10000, 0xf6d3f886, 4 | BRF_GRA }, // 26 + + { "891e07a", 0x10000, 0xb8d8b939, 5 | BRF_GRA }, // 27 K051316 Tiles + { "891e07b", 0x10000, 0x83b2f92d, 5 | BRF_GRA }, // 28 + + { "891e08a", 0x10000, 0xcef667bf, 6 | BRF_GRA }, // 29 K007232 #0 Samples + { "891e08b", 0x10000, 0xf7c14a7a, 6 | BRF_GRA }, // 30 + { "891e08c", 0x10000, 0x756b7f3c, 6 | BRF_GRA }, // 31 + { "891e08d", 0x10000, 0xcd0d7305, 6 | BRF_GRA }, // 32 + + { "891e04a", 0x10000, 0xdaebbc74, 7 | BRF_GRA }, // 33 K007232 #1 Samples + { "891e04b", 0x10000, 0x5ffb9ad1, 7 | BRF_GRA }, // 34 + { "891e04c", 0x10000, 0x2dbbf16b, 7 | BRF_GRA }, // 35 + { "891e04d", 0x10000, 0x8b0cd2cc, 7 | BRF_GRA }, // 36 + + { "891b11.f23", 0x00100, 0xecb854aa, 8 | BRF_OPT }, // 37 Priority Proms +}; + +STD_ROM_PICK(bottom9n) +STD_ROM_FN(bottom9n) + +struct BurnDriver BurnDrvBottom9n = { + "bottom9n", "bottom9", NULL, NULL, "1989", + "Bottom of the Ninth (ver. N)\0", NULL, "Konami", "GX891", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, bottom9nRomInfo, bottom9nRomName, NULL, NULL, Bottom9InputInfo, Bottom9DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Main Stadium (Japan ver. 4) + +static struct BurnRomInfo mstadiumRomDesc[] = { + { "891-403.k17", 0x10000, 0x1c00c4e8, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "891-402.k15", 0x10000, 0xb850bbce, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "891w01.g8", 0x08000, 0xedec565a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "891e10c", 0x10000, 0x209b0431, 3 | BRF_GRA }, // 3 K052109 Tiles + { "891e10a", 0x10000, 0x8020a9e8, 3 | BRF_GRA }, // 4 + { "891e10d", 0x10000, 0x16d5fd7a, 3 | BRF_GRA }, // 5 + { "891e10b", 0x10000, 0x30121cc0, 3 | BRF_GRA }, // 6 + { "891e09c", 0x10000, 0x9dcaefbf, 3 | BRF_GRA }, // 7 + { "891e09a", 0x10000, 0x56b0ead9, 3 | BRF_GRA }, // 8 + { "891e09d", 0x10000, 0x4e1335e6, 3 | BRF_GRA }, // 9 + { "891e09b", 0x10000, 0xb6f914fb, 3 | BRF_GRA }, // 10 + + { "891e06e", 0x10000, 0x0b04db1c, 4 | BRF_GRA }, // 11 K051960 Tiles + { "891e06a", 0x10000, 0x5ee37327, 4 | BRF_GRA }, // 12 + { "891e06f", 0x10000, 0xf9ada524, 4 | BRF_GRA }, // 13 + { "891e06b", 0x10000, 0x2295dfaa, 4 | BRF_GRA }, // 14 + { "891e06g", 0x10000, 0x04abf78f, 4 | BRF_GRA }, // 15 + { "891e06c", 0x10000, 0xdbdb0d55, 4 | BRF_GRA }, // 16 + { "891e06h", 0x10000, 0x5d5ded8c, 4 | BRF_GRA }, // 17 + { "891e06d", 0x10000, 0xf9ecbd71, 4 | BRF_GRA }, // 18 + { "891e05e", 0x10000, 0xb356e729, 4 | BRF_GRA }, // 19 + { "891e05a", 0x10000, 0xbfd5487e, 4 | BRF_GRA }, // 20 + { "891e05f", 0x10000, 0xecdd11c5, 4 | BRF_GRA }, // 21 + { "891e05b", 0x10000, 0xaba18d24, 4 | BRF_GRA }, // 22 + { "891e05g", 0x10000, 0xc315f9ae, 4 | BRF_GRA }, // 23 + { "891e05c", 0x10000, 0x21fcbc6f, 4 | BRF_GRA }, // 24 + { "891e05h", 0x10000, 0xb0aba53b, 4 | BRF_GRA }, // 25 + { "891e05d", 0x10000, 0xf6d3f886, 4 | BRF_GRA }, // 26 + + { "891e07a", 0x10000, 0xb8d8b939, 5 | BRF_GRA }, // 27 K051316 Tiles + { "891e07b", 0x10000, 0x83b2f92d, 5 | BRF_GRA }, // 28 + + { "891e08a", 0x10000, 0xcef667bf, 6 | BRF_GRA }, // 29 K007232 #0 Samples + { "891e08b", 0x10000, 0xf7c14a7a, 6 | BRF_GRA }, // 30 + { "891e08c", 0x10000, 0x756b7f3c, 6 | BRF_GRA }, // 31 + { "891e08d", 0x10000, 0xcd0d7305, 6 | BRF_GRA }, // 32 + + { "891e04a", 0x10000, 0xdaebbc74, 7 | BRF_GRA }, // 33 K007232 #1 Samples + { "891e04b", 0x10000, 0x5ffb9ad1, 7 | BRF_GRA }, // 34 + { "891e04c", 0x10000, 0x2dbbf16b, 7 | BRF_GRA }, // 35 + { "891e04d", 0x10000, 0x8b0cd2cc, 7 | BRF_GRA }, // 36 + + { "891b11.f23", 0x00100, 0xecb854aa, 8 | BRF_OPT }, // 37 Priority Proms +}; + +STD_ROM_PICK(mstadium) +STD_ROM_FN(mstadium) + +struct BurnDriver BurnDrvMstadium = { + "mstadium", "bottom9", NULL, NULL, "1989", + "Main Stadium (Japan ver. 4)\0", NULL, "Konami", "GX891", + L"Main Stadium\0\u30E1\u30A4\u30F3\u30B9\u30BF\u30B8\u30A2\u30E0 (Japan ver. 4)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, mstadiumRomInfo, mstadiumRomName, NULL, NULL, Bottom9InputInfo, MstadiumDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_contra.cpp b/src/burn/drivers/konami/d_contra.cpp new file mode 100644 index 00000000..7a915b92 --- /dev/null +++ b/src/burn/drivers/konami/d_contra.cpp @@ -0,0 +1,1232 @@ +// FB Alpha Contra driver module +// Based on MAME driver by Carlos A. Lozano, Phil Stroffolino, Jose T. Gomez, and Eric Hustvedt + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "m6809_intf.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM0; +static UINT8 *DrvM6809ROM1; +static UINT8 *DrvM6809RAM0; +static UINT8 *DrvM6809RAM1; +static UINT8 *DrvM6809RAM2; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPROMs; +static UINT8 *DrvColTable; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgCRAM; +static UINT8 *DrvFgVRAM; +static UINT8 *DrvTxCRAM; +static UINT8 *DrvTxVRAM; +static UINT8 *DrvBgCRAM; +static UINT8 *DrvBgVRAM; +static UINT8 *DrvSprRAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; +static UINT8 *pDrvSprRAM0; +static UINT8 *pDrvSprRAM1; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvInputs[3]; +static UINT8 DrvDip[3]; +static UINT8 DrvReset; + +static UINT8 trigger_sound_irq; + +static UINT8 soundlatch; +static UINT8 nBankData; + +static UINT8 K007121_ctrlram[2][8]; +static INT32 K007121_flipscreen[2]; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 1, "p2 coin" }, + + {"Start 1" , BIT_DIGITAL , DrvJoy1 + 3, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvJoy1 + 4, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p1 right" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 3, "p1 down" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 3, "p2 down" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset, "reset" }, + {"Service" , BIT_DIGITAL , DrvJoy1 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2, "dip" }, +}; + +STDINPUTINFO(Drv) + + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x5a, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0x12, 0xfe, 0, 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0x12, 0xfe, 0, 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, // 4 in test mode + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0x13, 0xfe, 0, 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "30000 70000" }, + {0x13, 0x01, 0x18, 0x10, "40000 80000" }, + {0x13, 0x01, 0x18, 0x08, "40000" }, + {0x13, 0x01, 0x18, 0x00, "50000" }, + + {0x13, 0xfe, 0, 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0x13, 0xfe, 0, 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0x14, 0xfe, 0, 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0x14, 0xfe, 0, 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0x14, 0xfe, 0, 2, "Sound" }, + {0x14, 0x01, 0x08, 0x00, "Mono" }, + {0x14, 0x01, 0x08, 0x08, "Stereo" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo CabinetDIPList[]= +{ + + {0x13, 0xfe, 0, 2, "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0x14, 0xfe, 0, 2, "Upright Controls" }, + {0x14, 0x02, 0x02, 0x02, "Single" }, + {0x13, 0x00, 0x04, 0x00, NULL}, + {0x14, 0x02, 0x02, 0x00, "Dual" }, + {0x13, 0x00, 0x04, 0x00, NULL}, +}; + +STDDIPINFOEXT(Gryzor, Drv, Cabinet) + +static void K007121_ctrl_w(INT32 chip, INT32 offset, INT32 data) +{ + if (offset == 7) K007121_flipscreen[chip] = data & 0x08; + + K007121_ctrlram[chip][offset] = data; +} + +static void contra_K007121_ctrl_0_w(INT32 offset, INT32 data) +{ + if (offset == 3) + { + if (data & 0x08) + memcpy (pDrvSprRAM0, DrvSprRAM + 0x000, 0x800); + else + memcpy (pDrvSprRAM0, DrvSprRAM + 0x800, 0x800); + } + + K007121_ctrl_w(0,offset,data); +} + +static void contra_K007121_ctrl_1_w(INT32 offset, INT32 data) +{ + if (offset == 3) + { + if (data&0x8) + memcpy(pDrvSprRAM1, DrvM6809RAM1 + 0x0800, 0x800); + else + memcpy(pDrvSprRAM1, DrvM6809RAM1 + 0x1000, 0x800); + } + + K007121_ctrl_w(1,offset,data); +} + +void contra_bankswitch_w(INT32 data) +{ + nBankData = data & 0x0f; + INT32 bankaddress = 0x10000 + nBankData * 0x2000; + + if (bankaddress < 0x28000) + M6809MapMemory(DrvM6809ROM0 + bankaddress, 0x6000, 0x7fff, M6809_ROM); +} + +UINT8 DrvContraM6809ReadByte(UINT16 address) +{ + switch (address) + { + case 0x0010: + case 0x0011: + case 0x0012: + return DrvInputs[address & 3]; + + case 0x0014: + case 0x0015: + case 0x0016: + return DrvDip[address & 3]; + } + + return 0; +} + +void DrvContraM6809WriteByte(UINT16 address, UINT8 data) +{ + if ((address & 0xff00) == 0x0c00) { + INT32 offset = address & 0xff; + + DrvPalRAM[offset] = data; + + UINT16 col = DrvPalRAM[offset & ~1] | (DrvPalRAM[offset | 1] << 8); + + UINT8 r, g, b; + + r = (col >> 0) & 0x1f; + r = (r << 3) | (r >> 2); + + g = (col >> 5) & 0x1f; + g = (g << 3) | (g >> 2); + + b = (col >> 10) & 0x1f; + b = (b << 3) | (b >> 2); + + UINT32 color = (r << 16) | (g << 8) | b; + + DrvRecalc = 1; + Palette[offset >> 1] = color; + + return; + } + + switch (address) + { + case 0x0000: + case 0x0001: + case 0x0002: + case 0x0003: + case 0x0004: + case 0x0005: + case 0x0006: + case 0x0007: + contra_K007121_ctrl_0_w(address & 7, data); + return; + + case 0x0018: + // coin counter + return; + + case 0x001a: + trigger_sound_irq = 1; + return; + + case 0x001c: + soundlatch = data; + return; + + case 0x0060: + case 0x0061: + case 0x0062: + case 0x0063: + case 0x0064: + case 0x0065: + case 0x0066: + case 0x0067: + contra_K007121_ctrl_1_w(address & 7, data); + return; + + case 0x7000: + contra_bankswitch_w(data); + return; + } +} + +UINT8 DrvContraM6809SoundReadByte(UINT16 address) +{ + switch (address) + { + case 0x0000: + return soundlatch; + + case 0x2001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +void DrvContraM6809SoundWriteByte(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x2000: + BurnYM2151SelectRegister(data); + return; + + case 0x2001: + BurnYM2151WriteRegister(data); + return; + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM0 = Next; Next += 0x030000; + DrvM6809ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + + DrvPROMs = Next; Next += 0x000400; + + DrvColTable = Next; Next += 0x001000; + + DrvPalette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + AllRam = Next; + + DrvM6809RAM0 = Next; Next += 0x001000; + DrvM6809RAM1 = Next; Next += 0x001800; + DrvM6809RAM2 = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000100; + DrvFgCRAM = Next; Next += 0x000400; + DrvFgVRAM = Next; Next += 0x000400; + DrvTxCRAM = Next; Next += 0x000400; + DrvTxVRAM = Next; Next += 0x000400; + DrvBgCRAM = Next; Next += 0x000400; + DrvBgVRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x001000; + + pDrvSprRAM0 = Next; Next += 0x000800; + pDrvSprRAM1 = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x00080 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode(UINT8 *src) +{ + INT32 Plane[4] = { 0, 1, 2, 3 }; + INT32 XOffs[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; + INT32 YOffs[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + + UINT8 *tmp = (UINT8*)malloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, src, 0x80000); + + GfxDecode(0x4000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, src); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static INT32 DrvColorTableInit() +{ + for (INT32 chip = 0; chip < 2; chip++) + { + for (INT32 pal = 0; pal < 8; pal++) + { + INT32 clut = ((chip << 1) | (pal & 1)) << 8; + + for (INT32 i = 0; i < 0x100; i++) + { + UINT8 ctabentry; + + if (((pal & 0x01) == 0) && (DrvPROMs[clut | i] == 0)) + ctabentry = 0; + else + ctabentry = (pal << 4) | (DrvPROMs[clut | i] & 0x0f); + + DrvColTable[(chip << 11) | (pal << 8) | i] = ctabentry; + } + } + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + memset (K007121_ctrlram, 0, 2 * 8); + memset (K007121_flipscreen, 0, 2 * sizeof(INT32)); + + for (INT32 i = 0; i < 2; i++) { + M6809Open(i); + M6809Reset(); + M6809Close(); + } + + BurnYM2151Reset(); + + trigger_sound_irq = 0; + soundlatch = 0; + nBankData = 0; + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_ACK); + } else { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM0 + 0x00000, 0, 1)) return 1; + memcpy (DrvM6809ROM0 + 0x20000, DrvM6809ROM0, 0x08000); + if (BurnLoadRom(DrvM6809ROM0 + 0x10000, 1, 1)) return 1; + + if (BurnLoadRom(DrvM6809ROM1 + 0x08000, 2, 1)) return 1; + + if (BurnDrvGetFlags() & BDF_BOOTLEG) + { + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x10000, 3 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + i * 0x10000, 11 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvPROMs + i * 0x100, i + 18, 1)) return 1; + } + } else { + if (BurnLoadRom(DrvGfxROM0 + 0, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 1, 4, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 1, 6, 2)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvPROMs + i * 0x100, i + 7, 1)) return 1; + } + } + + DrvGfxDecode(DrvGfxROM0); + DrvGfxDecode(DrvGfxROM1); + + DrvColorTableInit(); + } + + M6809Init(2); + M6809Open(0); + M6809MapMemory(DrvPalRAM, 0x0c00, 0x0cff, M6809_ROM); + M6809MapMemory(DrvM6809RAM0, 0x1000, 0x1fff, M6809_RAM); + M6809MapMemory(DrvFgCRAM, 0x2000, 0x23ff, M6809_RAM); + M6809MapMemory(DrvFgVRAM, 0x2400, 0x27ff, M6809_RAM); + M6809MapMemory(DrvTxCRAM, 0x2800, 0x2bff, M6809_RAM); + M6809MapMemory(DrvTxVRAM, 0x2c00, 0x2fff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x3000, 0x3fff, M6809_RAM); + M6809MapMemory(DrvBgCRAM, 0x4000, 0x43ff, M6809_RAM); + M6809MapMemory(DrvBgVRAM, 0x4400, 0x47ff, M6809_RAM); + M6809MapMemory(DrvM6809RAM1, 0x4800, 0x5fff, M6809_RAM); +// M6809MapMemory(DrvM6809ROM0 + 0x10000, 0x6000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvM6809ROM0 + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(DrvContraM6809ReadByte); + M6809SetWriteByteHandler(DrvContraM6809WriteByte); + M6809Close(); + + M6809Open(1); + M6809MapMemory(DrvM6809RAM2, 0x6000, 0x67ff, M6809_RAM); + M6809MapMemory(DrvM6809ROM1 + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(DrvContraM6809SoundReadByte); + M6809SetWriteByteHandler(DrvContraM6809SoundWriteByte); + M6809Close(); + + BurnYM2151Init(3579545, 60.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + M6809Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void draw_bg() +{ + INT32 bit0 = (K007121_ctrlram[1][0x05] >> 0) & 0x03; + INT32 bit1 = (K007121_ctrlram[1][0x05] >> 2) & 0x03; + INT32 bit2 = (K007121_ctrlram[1][0x05] >> 4) & 0x03; + INT32 bit3 = (K007121_ctrlram[1][0x05] >> 6) & 0x03; + INT32 mask = (K007121_ctrlram[1][0x04] & 0xf0) >> 4; + INT32 scrollx = K007121_ctrlram[1][0x00] - 40; + INT32 scrolly = K007121_ctrlram[1][0x02]; + INT32 flipscreen = K007121_flipscreen[1]; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sx -= scrollx; + sy -= scrolly; + if (sx < -7) sx += 296; + if (sy < -7) sy += 256; + sy -= 16; + + INT32 attr = DrvBgCRAM[offs]; + + INT32 bank = ((attr & 0x80) >> 7) | + ((attr >> (bit0+2)) & 0x02) | + ((attr >> (bit1+1)) & 0x04) | + ((attr >> (bit2 )) & 0x08) | + ((attr >> (bit3-1)) & 0x10) | + ((K007121_ctrlram[1][0x03] & 0x01) << 5); + + bank = (bank & ~(mask << 1)) | ((K007121_ctrlram[0][0x04] & mask) << 1); + + INT32 color = ((K007121_ctrlram[1][6]&0x30)*2+16)+(attr&7); + + INT32 code = DrvBgVRAM[offs] | (bank << 8); + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (280 - sx)-8, 224 - sy, color, 4, 0x800, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0x800, DrvGfxROM1); + } + } +} + +static void draw_fg() +{ + INT32 bit0 = (K007121_ctrlram[0][0x05] >> 0) & 0x03; + INT32 bit1 = (K007121_ctrlram[0][0x05] >> 2) & 0x03; + INT32 bit2 = (K007121_ctrlram[0][0x05] >> 4) & 0x03; + INT32 bit3 = (K007121_ctrlram[0][0x05] >> 6) & 0x03; + INT32 mask = (K007121_ctrlram[0][0x04] & 0xf0) >> 4; + INT32 scrollx = K007121_ctrlram[0][0x00] - 40; + INT32 scrolly = K007121_ctrlram[0][0x02]; + INT32 flipscreen = K007121_flipscreen[0]; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sx -= scrollx; + sy -= scrolly; + if (sx < -7) sx += 296; + if (sy < -7) sy += 256; + + sy -= 16; + + INT32 attr = DrvFgCRAM[offs]; + + INT32 bank = ((attr & 0x80) >> 7) | + ((attr >> (bit0+2)) & 0x02) | + ((attr >> (bit1+1)) & 0x04) | + ((attr >> (bit2 )) & 0x08) | + ((attr >> (bit3-1)) & 0x10) | + ((K007121_ctrlram[0][0x03] & 0x01) << 5); + + bank = (bank & ~(mask << 1)) | ((K007121_ctrlram[0][0x04] & mask) << 1); + + INT32 color = ((K007121_ctrlram[0][6]&0x30)*2+16)+(attr&7); + + INT32 code = DrvFgVRAM[offs] | (bank << 8); + + if (flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, (280 - sx)-8, 224 - sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_tx() +{ + INT32 bit0 = (K007121_ctrlram[0][0x05] >> 0) & 0x03; + INT32 bit1 = (K007121_ctrlram[0][0x05] >> 2) & 0x03; + INT32 bit2 = (K007121_ctrlram[0][0x05] >> 4) & 0x03; + INT32 bit3 = (K007121_ctrlram[0][0x05] >> 6) & 0x03; + INT32 flipscreen = K007121_flipscreen[0]; + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + if (sx > 39) continue; + INT32 sy = (offs >> 5) << 3; + + INT32 attr = DrvTxCRAM[offs]; + + INT32 bank = ((attr & 0x80) >> 7) | + ((attr >> (bit0+2)) & 0x02) | + ((attr >> (bit1+1)) & 0x04) | + ((attr >> (bit2 )) & 0x08) | + ((attr >> (bit3-1)) & 0x10); + + INT32 color = ((K007121_ctrlram[0][6]&0x30)*2+16)+(attr&7); + + INT32 code = DrvTxVRAM[offs] | (bank << 8); + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (sx ^ 0xf8) + 24, (sy ^ 0xf8) - 16, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM0); + } + } +} + + +static void K007121_sprites_draw(INT32 chip, UINT8 *gfx_base, UINT8 *ctable, + const UINT8 *source, INT32 base_color, + INT32 global_x_offset, INT32 global_y_offset, + INT32 bank_base, INT32 pri_mask, INT32 color_offset) +{ + INT32 flipscreen = K007121_flipscreen[chip]; + INT32 i,num,inc,offs[5],trans; + INT32 is_flakatck = (ctable == NULL); + + if (is_flakatck) + { + num = 0x40; + inc = -0x20; + source += 0x3f << 5; + offs[0] = 0x0e; + offs[1] = 0x0f; + offs[2] = 0x06; + offs[3] = 0x04; + offs[4] = 0x08; + trans = 0; + } + else + { + num = 0x40; + + inc = 5; + offs[0] = 0x00; + offs[1] = 0x01; + offs[2] = 0x02; + offs[3] = 0x03; + offs[4] = 0x04; + trans = 0; + + if (pri_mask != -1) + { + source += (num-1)*inc; + inc = -inc; + } + } + + for (i = 0;i < num;i++) + { + INT32 number = source[offs[0]]; + INT32 sprite_bank = source[offs[1]] & 0x0f; + INT32 sx = source[offs[3]]; + INT32 sy = source[offs[2]]; + INT32 attr = source[offs[4]]; + INT32 color = base_color + ((source[offs[1]] & 0xf0) >> 4); + INT32 xflip = attr & 0x10; + INT32 yflip = attr & 0x20; + INT32 width,height; + INT32 transparent_color = 0; + static const INT32 x_offset[4] = {0x0,0x1,0x4,0x5}; + static const INT32 y_offset[4] = {0x0,0x2,0x8,0xa}; + INT32 x,y, ex, ey; + + if (attr & 0x01) sx -= 256; + if (sy >= 240) sy -= 256; + + number += ((sprite_bank & 0x3) << 8) + ((attr & 0xc0) << 4); + number = number << 2; + number += (sprite_bank >> 2) & 3; + + if (!is_flakatck || source[0x00]) + { + number += bank_base; + + switch (attr & 0x0e) + { + case 0x06: width = height = 1; break; + case 0x04: width = 1; height = 2; number &= (~2); break; + case 0x02: width = 2; height = 1; number &= (~1); break; + case 0x00: width = height = 2; number &= (~3); break; + case 0x08: width = height = 4; number &= (~3); break; + default: width = 1; height = 1; + } + + for (y = 0; y < height; y++) + { + for (x = 0;x < width;x++) + { + ex = xflip ? (width-1-x) : x; + ey = yflip ? (height-1-y) : y; + + if (flipscreen) + { + if (pri_mask != -1) + ;// not implemented + else + if (yflip) { + if (xflip) { + Render8x8Tile_Mask_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], 248-(sx+x*8)-global_x_offset+24, 248-(sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], 248-(sx+x*8)-global_x_offset+24, 248-(sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } + } else { + if (xflip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], 248-(sx+x*8)-global_x_offset+24, 248-(sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], 248-(sx+x*8)-global_x_offset+24, 248-(sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } + } + } + else + { + if (pri_mask != -1) + ;// not implemented + else + if (yflip) { + if (xflip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], global_x_offset+sx+x*8, (sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], global_x_offset+sx+x*8, (sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } + } else { + if (xflip) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], global_x_offset+sx+x*8, (sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, number + x_offset[ex] + y_offset[ey], global_x_offset+sx+x*8, (sy+y*8)+global_y_offset, color, 4, transparent_color, color_offset, gfx_base); + } + } + } + } + } + } + + source += inc; + } +} + +static void draw_sprites(INT32 bank, UINT8 *gfx_base, INT32 color_offset) +{ + INT32 base_color = (K007121_ctrlram[bank][6]&0x30)<<1; + const UINT8 *source = bank ? pDrvSprRAM1 : pDrvSprRAM0; + + K007121_sprites_draw(bank, gfx_base, DrvColTable, source, base_color, 40, -16, 0, -1, color_offset); +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i++) { + INT32 rgb = Palette[DrvColTable[i]]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + draw_bg(); + draw_fg(); + + draw_sprites(0, DrvGfxROM0, 0x000); + draw_sprites(1, DrvGfxROM1, 0x800); + + draw_tx(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0 ; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + INT32 nCyclesSegment = 0; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 1500000 / 60, 2000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + M6809Open(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + if (i == (nInterleave - 1)) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + M6809Close(); + + nCurrentCPU = 1; + M6809Open(nCurrentCPU); + if (trigger_sound_irq) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + trigger_sound_irq = 0; + } + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + M6809Close(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + M6809Open(1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + M6809Close(); + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029696; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = K007121_ctrlram; + ba.nLen = 2 * 8; + ba.szName = "K007121 Control RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + M6809Scan(nAction); + + BurnYM2151Scan(nAction); + + SCAN_VAR(K007121_flipscreen[0]); + SCAN_VAR(K007121_flipscreen[1]); + SCAN_VAR(soundlatch); + SCAN_VAR(nBankData); + + if (nAction & ACB_WRITE) { + M6809Open(0); + contra_bankswitch_w(nBankData); + M6809Close(); + } + } + + return 0; +} + + +// Contra (US, Set 1) + +static struct BurnRomInfo contraRomDesc[] = { + { "633m03.18a", 0x10000, 0xd045e1da, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633i02.17a", 0x10000, 0xb2f7bd9a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "633e04.7d", 0x40000, 0x14ddc542, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "633e05.7f", 0x40000, 0x42185044, 3 | BRF_GRA }, // 4 + + { "633e06.16d", 0x40000, 0x9cf6faae, 4 | BRF_GRA }, // 5 Chip 1 Tiles + { "633e07.16f", 0x40000, 0xf2d06638, 4 | BRF_GRA }, // 6 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 7 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 8 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 9 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 10 + + { "007766.20d.bin", 0x1, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(contra) +STD_ROM_FN(contra) + +struct BurnDriver BurnDrvContra = { + "contra", NULL, NULL, NULL, "1987", + "Contra (US, Set 1)\0", NULL, "Konami", "GX633", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, contraRomInfo, contraRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Contra (US, Set 2) + +static struct BurnRomInfo contra1RomDesc[] = { + { "633e03.18a", 0x10000, 0x7fc0d8cf, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633i02.17a", 0x10000, 0xb2f7bd9a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "633e04.7d", 0x40000, 0x14ddc542, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "633e05.7f", 0x40000, 0x42185044, 3 | BRF_GRA }, // 4 + + { "633e06.16d", 0x40000, 0x9cf6faae, 4 | BRF_GRA }, // 5 Chip 1 Tiles + { "633e07.16f", 0x40000, 0xf2d06638, 4 | BRF_GRA }, // 6 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 7 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 8 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 9 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 10 + + { "007766.20d.bin", 0x1, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(contra1) +STD_ROM_FN(contra1) + +struct BurnDriver BurnDrvContra1 = { + "contra1", "contra", NULL, NULL, "1987", + "Contra (US, Set 2)\0", NULL, "Konami", "GX633", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, contra1RomInfo, contra1RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Contra (bootleg) + +static struct BurnRomInfo contrabRomDesc[] = { + { "633m03.18a", 0x10000, 0xd045e1da, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633i02.17a", 0x10000, 0xb2f7bd9a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "g-7.rom", 0x10000, 0x57f467d2, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "g-10.rom", 0x10000, 0xe6db9685, 3 | BRF_GRA }, // 4 + { "g-9.rom", 0x10000, 0x875c61de, 3 | BRF_GRA }, // 5 + { "g-8.rom", 0x10000, 0x642765d6, 3 | BRF_GRA }, // 6 + { "g-15.rom", 0x10000, 0xdaa2324b, 3 | BRF_GRA }, // 7 + { "g-16.rom", 0x10000, 0xe27cc835, 3 | BRF_GRA }, // 8 + { "g-17.rom", 0x10000, 0xce4330b9, 3 | BRF_GRA }, // 9 + { "g-18.rom", 0x10000, 0x1571ce42, 3 | BRF_GRA }, // 10 + + { "g-4.rom", 0x10000, 0x2cc7e52c, 4 | BRF_GRA }, // 11 Chip 1 Tiles + { "g-5.rom", 0x10000, 0xe01a5b9c, 4 | BRF_GRA }, // 12 + { "g-6.rom", 0x10000, 0xaeea6744, 4 | BRF_GRA }, // 13 + { "g-14.rom", 0x10000, 0x765afdc7, 4 | BRF_GRA }, // 14 + { "g-11.rom", 0x10000, 0xbd9ba92c, 4 | BRF_GRA }, // 15 + { "g-12.rom", 0x10000, 0xd0be7ec2, 4 | BRF_GRA }, // 16 + { "g-13.rom", 0x10000, 0x2b513d12, 4 | BRF_GRA }, // 17 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 18 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 19 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 20 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 21 + + { "conprom.53", 0x00100, 0x05a1da7e, 0 | BRF_OPT }, // 22 +}; + +STD_ROM_PICK(contrab) +STD_ROM_FN(contrab) + +struct BurnDriver BurnDrvContrab = { + "contrab", "contra", NULL, NULL, "1987", + "Contra (bootleg)\0", NULL, "Konami", "GX633", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, contrabRomInfo, contrabRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Contra (Japan) + +static struct BurnRomInfo contrajRomDesc[] = { + { "633n03.18a", 0x10000, 0xfedab568, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633k02.17a", 0x10000, 0x5d5f7438, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "633e04.7d", 0x40000, 0x14ddc542, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "633e05.7f", 0x40000, 0x42185044, 3 | BRF_GRA }, // 4 + + { "633e06.16d", 0x40000, 0x9cf6faae, 4 | BRF_GRA }, // 5 Chip 1 Tiles + { "633e07.16f", 0x40000, 0xf2d06638, 4 | BRF_GRA }, // 6 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 7 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 8 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 9 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 10 + + { "007766.20d.bin", 0x1, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(contraj) +STD_ROM_FN(contraj) + +struct BurnDriver BurnDrvContraj = { + "contraj", "contra", NULL, NULL, "1987", + "Contra (Japan)\0", NULL, "Konami", "GX633", + L"\u9B42\u6597\u7F85 \u30B3\u30F3\u30C8\u30E9 (Japan)\0Contra\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, contrajRomInfo, contrajRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Contra (Japan bootleg) + +static struct BurnRomInfo contrajbRomDesc[] = { + { "g-2.18a", 0x10000, 0xbdb9196d, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633k02.17a", 0x10000, 0x5d5f7438, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "g-7.rom", 0x10000, 0x57f467d2, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "g-10.rom", 0x10000, 0xe6db9685, 3 | BRF_GRA }, // 4 + { "g-9.rom", 0x10000, 0x875c61de, 3 | BRF_GRA }, // 5 + { "g-8.rom", 0x10000, 0x642765d6, 3 | BRF_GRA }, // 6 + { "g-15.rom", 0x10000, 0xdaa2324b, 3 | BRF_GRA }, // 7 + { "g-16.rom", 0x10000, 0xe27cc835, 3 | BRF_GRA }, // 8 + { "g-17.rom", 0x10000, 0xce4330b9, 3 | BRF_GRA }, // 9 + { "g-18.rom", 0x10000, 0x1571ce42, 3 | BRF_GRA }, // 10 + + { "g-4.rom", 0x10000, 0x2cc7e52c, 4 | BRF_GRA }, // 11 Chip 1 Tiles + { "g-5.rom", 0x10000, 0xe01a5b9c, 4 | BRF_GRA }, // 12 + { "g-6.rom", 0x10000, 0xaeea6744, 4 | BRF_GRA }, // 13 + { "g-14.rom", 0x10000, 0x765afdc7, 4 | BRF_GRA }, // 14 + { "g-11.rom", 0x10000, 0xbd9ba92c, 4 | BRF_GRA }, // 15 + { "g-12.rom", 0x10000, 0xd0be7ec2, 4 | BRF_GRA }, // 16 + { "g-13.rom", 0x10000, 0x2b513d12, 4 | BRF_GRA }, // 17 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 18 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 19 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 20 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 21 +}; + +STD_ROM_PICK(contrajb) +STD_ROM_FN(contrajb) + +struct BurnDriver BurnDrvContrajb = { + "contrajb", "contra", NULL, NULL, "1987", + "Contra (Japan bootleg)\0", NULL, "Konami", "GX633", + L"\u9B42\u6597\u7F85 \u30B3\u30F3\u30C8\u30E9 (Japan bootleg)\0Contra\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, contrajbRomInfo, contrajbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Gryzor (Set 1) + +static struct BurnRomInfo gryzorRomDesc[] = { + { "g2.18a", 0x10000, 0x92ca77bd, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "g3.17a", 0x10000, 0xbbd9e95e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "633e04.7d", 0x40000, 0x14ddc542, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "633e05.7f", 0x40000, 0x42185044, 3 | BRF_GRA }, // 4 + + { "633e06.16d", 0x40000, 0x9cf6faae, 4 | BRF_GRA }, // 5 Chip 1 Tiles + { "633e07.16f", 0x40000, 0xf2d06638, 4 | BRF_GRA }, // 6 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 7 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 8 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 9 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 10 + + { "007766.20d.bin", 0x1, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(gryzor) +STD_ROM_FN(gryzor) + +struct BurnDriver BurnDrvGryzor = { + "gryzor", "contra", NULL, NULL, "1987", + "Gryzor (Set 1)\0", NULL, "Konami", "GX633", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, gryzorRomInfo, gryzorRomName, NULL, NULL, DrvInputInfo, GryzorDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + + +// Gryzor (Set 2) + +static struct BurnRomInfo gryzoraRomDesc[] = { + { "633j03.18a", 0x10000, 0x20919162, 1 | BRF_PRG | BRF_ESS }, // 0 m6809 #0 Code + { "633j02.17a", 0x10000, 0xb5922f9a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "633e01.12a", 0x08000, 0xd1549255, 2 | BRF_PRG | BRF_ESS }, // 2 m6809 #1 Code + + { "633e04.7d", 0x40000, 0x14ddc542, 3 | BRF_GRA }, // 3 Chip 0 Tiles + { "633e05.7f", 0x40000, 0x42185044, 3 | BRF_GRA }, // 4 + + { "633e06.16d", 0x40000, 0x9cf6faae, 4 | BRF_GRA }, // 5 Chip 1 Tiles + { "633e07.16f", 0x40000, 0xf2d06638, 4 | BRF_GRA }, // 6 + + { "633e08.10g", 0x00100, 0x9f0949fa, 5 | BRF_GRA }, // 7 Color Proms + { "633e09.12g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 8 + { "633f10.18g", 0x00100, 0x2b244d84, 5 | BRF_GRA }, // 9 + { "633f11.20g", 0x00100, 0x14ca5e19, 5 | BRF_GRA }, // 10 + + { "007766.20d.bin", 0x1, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(gryzora) +STD_ROM_FN(gryzora) + +struct BurnDriver BurnDrvGryzora = { + "gryzora", "contra", NULL, NULL, "1987", + "Gryzor (Set 2)\0", NULL, "Konami", "GX633", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, gryzoraRomInfo, gryzoraRomName, NULL, NULL, DrvInputInfo, GryzorDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 280, 3, 4 +}; + diff --git a/src/burn/drivers/konami/d_crimfght.cpp b/src/burn/drivers/konami/d_crimfght.cpp new file mode 100644 index 00000000..a574132f --- /dev/null +++ b/src/burn/drivers/konami/d_crimfght.cpp @@ -0,0 +1,798 @@ +// FB Alpha Crime Fighters driver module +// Based on MAME driver by Manuel Abadia + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvRamBank; +static UINT8 *nDrvKonamiBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[5]; +static UINT8 DrvReset; + +static struct BurnInputInfo CrimfghtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy5 + 2, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy5 + 3, "p4 coin" }, + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvJoy5 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy5 + 5, "service2"}, + {"Service 3", BIT_DIGITAL, DrvJoy5 + 6, "service3"}, + {"Service 4", BIT_DIGITAL, DrvJoy5 + 7, "service4"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Crimfght) + +static struct BurnInputInfo CrimfgtjInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service 1", BIT_DIGITAL, DrvJoy5 + 4, "service"}, + {"Service 2", BIT_DIGITAL, DrvJoy5 + 5, "service2"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip"}, +}; + +STDINPUTINFO(Crimfgtj) + +static struct BurnDIPInfo CrimfghtDIPList[]= +{ + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0x5f, NULL }, + {0x23, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x21, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x21, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x21, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x21, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x21, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x21, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x21, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x21, 0x01, 0x0f, 0x00, "1 Coin 99 Credits" }, + +/* {0 , 0xfe, 0 , 16, "Coin B" }, + {0x21, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x21, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x21, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x21, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x21, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x21, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x21, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x21, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x21, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x21, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x21, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x21, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x21, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x21, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x21, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x21, 0x01, 0xf0, 0x00, "No Coin B" },*/ + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x60, 0x60, "Easy" }, + {0x22, 0x01, 0x60, 0x40, "Normal" }, + {0x22, 0x01, 0x60, 0x20, "Difficult" }, + {0x22, 0x01, 0x60, 0x00, "Very difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x23, 0x01, 0x01, 0x01, "Off" }, +// {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x23, 0x01, 0x04, 0x00, "Off" }, + {0x23, 0x01, 0x04, 0x04, "On" }, +}; + +STDDIPINFO(Crimfght) + +static struct BurnDIPInfo CrimfgtjDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x5f, NULL }, + {0x17, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "Not Use" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x03, "1" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x01, "3" }, + {0x16, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x60, 0x60, "Easy" }, + {0x16, 0x01, 0x60, 0x40, "Normal" }, + {0x16, 0x01, 0x60, 0x20, "Difficult" }, + {0x16, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x17, 0x01, 0x01, 0x01, "Off" }, +// {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x04, 0x00, "Off" }, + {0x17, 0x01, 0x04, 0x04, "On" }, +}; + +STDDIPINFO(Crimfgtj) + +static void set_ram_bank(INT32 data) +{ + nDrvRamBank[0] = data; + + if (data & 0x20) { + konamiMapMemory(DrvPalRAM, 0x0000, 0x03ff, KON_RAM); + } else { + konamiMapMemory(DrvBankRAM, 0x0000, 0x03ff, KON_RAM); + } +} + +void crimfght_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3f8c: + *soundlatch = data; + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + break; + } + + if (address >= 0x2000 && address <= 0x5fff) { + K052109_051960_w(address - 0x2000, data); + return; + } +} + +UINT8 crimfght_main_read(UINT16 address) +{ + switch (address) + { + case 0x3f80: + return DrvInputs[4]; + + case 0x3f81: + return DrvInputs[0]; + + case 0x3f82: + return DrvInputs[1]; + + case 0x3f83: + return DrvDips[1]; + + case 0x3f84: + return DrvDips[2]; + + case 0x3f85: + return DrvInputs[2]; + + case 0x3f86: + return DrvInputs[3]; + + case 0x3f87: + return DrvDips[0]; + + case 0x3f88: + // watchdog reset + return 0; + } + + if (address >= 0x2000 && address <= 0x5fff) { + return K052109_051960_r(address - 0x2000); + } + + return 0; +} + +void __fastcall crimfght_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xe000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xa000: + BurnYM2151SelectRegister(data); + return; + + case 0xa001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall crimfght_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xe000) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xa000: + case 0xa001: + return BurnYM2151ReadStatus(); + + case 0xc000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + INT32 bank_A = ((data >> 1) & 0x01); + INT32 bank_B = ((data) & 0x01); + + k007232_set_bank(0, bank_A, bank_B); +} + +static void crimfght_set_lines(INT32 lines) +{ + nDrvKonamiBank[0] = lines; + + set_ram_bank(lines & 0x20); + K052109RMRDLine = lines & 0x40; + + INT32 nBank = 0x10000 + ((lines & 0x0f) * 0x2000); + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM); +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *flipx, INT32 *) +{ + *flipx = *color & 0x20; + *code |= ((*color & 0x1f) << 8) | (bank << 13); + *code &= 0x3fff; + *color = (layer << 2) + ((*color & 0xc0) >> 6); +} + +static void K051960Callback(INT32 *code, INT32 *color,INT32 *priority, INT32 *shadow) +{ + switch (*color & 0x70) + { + case 0x10: *priority = 0; break; + case 0x00: *priority = 1; break; + case 0x40: *priority = 2; break; + case 0x20: *priority = 3; break; + } + + *code |= (*color & 0x80) << 6; + *code &= 0x1fff; + *color = 16 + (*color & 0x0f); + *shadow = 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x200 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000400; + DrvKonRAM = Next; Next += 0x001c00; + DrvPalRAM = Next; Next += 0x000400; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvRamBank = Next; Next += 0x000001; + nDrvKonamiBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x4000, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x2000, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x28000, 0x8000); + memset (DrvKonROM + 0x28000, 0, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 6, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvBankRAM, 0x0000, 0x03ff, KON_RAM); + konamiMapMemory(DrvKonRAM, 0x0400, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(crimfght_main_write); + konamiSetReadHandler(crimfght_main_read); + konamiSetlinesCallback(crimfght_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(crimfght_sound_write); + ZetSetReadHandler(crimfght_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + K007232Init(0, 3579545, DrvSndROM, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(-2, 0); + + K051960Init(DrvGfxROM1, 0xfffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(-2, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x400); + } + + K052109UpdateScroll(); + + K052109RenderLayer(1, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[3] & 0x0c) == 0) DrvInputs[3] |= 0x0c; + if ((DrvInputs[3] & 0x03) == 0) DrvInputs[3] |= 0x03; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + set_ram_bank(nDrvRamBank[0]); + crimfght_set_lines(nDrvKonamiBank[0]); + konamiClose(); + } + + return 0; +} + + +// Crime Fighters (US 4 players) + +static struct BurnRomInfo crimfghtRomDesc[] = { + { "821l02.f24", 0x20000, 0x588e7da6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + + { "821l01.h4", 0x08000, 0x0faca89e, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "821k06.k13", 0x40000, 0xa1eadb24, 3 | BRF_GRA }, // 2 Background Tiles + { "821k07.k19", 0x40000, 0x060019fa, 3 | BRF_GRA }, // 3 + + { "821k04.k2", 0x80000, 0x00e0291b, 4 | BRF_GRA }, // 4 Sprites + { "821k05.k8", 0x80000, 0xe09ea05d, 4 | BRF_GRA }, // 5 + + { "821k03.e5", 0x40000, 0xfef8505a, 5 | BRF_SND }, // 6 K007232 Samples + + { "821a08.i15", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 7 Proms +}; + +STD_ROM_PICK(crimfght) +STD_ROM_FN(crimfght) + +struct BurnDriver BurnDrvCrimfght = { + "crimfght", NULL, NULL, NULL, "1989", + "Crime Fighters (US 4 players)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, crimfghtRomInfo, crimfghtRomName, NULL, NULL, CrimfghtInputInfo, CrimfghtDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Crime Fighters (Japan 2 Players) + +static struct BurnRomInfo crimfgtjRomDesc[] = { + { "821p02.bin", 0x20000, 0xf33fa2e1, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + + { "821l01.h4", 0x08000, 0x0faca89e, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "821k06.k13", 0x40000, 0xa1eadb24, 3 | BRF_GRA }, // 2 Background Tiles + { "821k07.k19", 0x40000, 0x060019fa, 3 | BRF_GRA }, // 3 + + { "821k04.k2", 0x80000, 0x00e0291b, 4 | BRF_GRA }, // 4 Sprites + { "821k05.k8", 0x80000, 0xe09ea05d, 4 | BRF_GRA }, // 5 + + { "821k03.e5", 0x40000, 0xfef8505a, 5 | BRF_SND }, // 6 K007232 Samples + + { "821a08.i15", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 7 Proms +}; + +STD_ROM_PICK(crimfgtj) +STD_ROM_FN(crimfgtj) + +struct BurnDriver BurnDrvCrimfgtj = { + "crimfghtj", "crimfght", NULL, NULL, "1989", + "Crime Fighters (Japan 2 Players)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, crimfgtjRomInfo, crimfgtjRomName, NULL, NULL, CrimfgtjInputInfo, CrimfgtjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Crime Fighters (World 2 Players) + +static struct BurnRomInfo crimfgt2RomDesc[] = { + { "crimefb.r02",0x20000, 0x4ecdd923, 1 | BRF_PRG | BRF_ESS }, // 0 Konami CPU Code + + { "821l01.h4", 0x08000, 0x0faca89e, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "821k06.k13", 0x40000, 0xa1eadb24, 3 | BRF_GRA }, // 2 Background Tiles + { "821k07.k19", 0x40000, 0x060019fa, 3 | BRF_GRA }, // 3 + + { "821k04.k2", 0x80000, 0x00e0291b, 4 | BRF_GRA }, // 4 Sprites + { "821k05.k8", 0x80000, 0xe09ea05d, 4 | BRF_GRA }, // 5 + + { "821k03.e5", 0x40000, 0xfef8505a, 5 | BRF_SND }, // 6 K007232 Samples + + { "821a08.i15", 0x00100, 0x7da55800, 6 | BRF_OPT }, // 7 Proms +}; + +STD_ROM_PICK(crimfgt2) +STD_ROM_FN(crimfgt2) + +struct BurnDriver BurnDrvCrimfgt2 = { + "crimfght2", "crimfght", NULL, NULL, "1989", + "Crime Fighters (World 2 Players)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, crimfgt2RomInfo, crimfgt2RomName, NULL, NULL, CrimfgtjInputInfo, CrimfgtjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_gbusters.cpp b/src/burn/drivers/konami/d_gbusters.cpp new file mode 100644 index 00000000..3f029447 --- /dev/null +++ b/src/burn/drivers/konami/d_gbusters.cpp @@ -0,0 +1,698 @@ +// FB Alpha Gang Busters driver module +// Based on MAME by Manuel Abadia + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvRamBank; +static UINT8 *nDrvKonamiBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo GbustersInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Gbusters) + +static struct BurnDIPInfo GbustersDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x56, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Bullets" }, + {0x13, 0x01, 0x04, 0x04, "50" }, + {0x13, 0x01, 0x04, 0x00, "60" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "50k, 200k & 400k" }, + {0x13, 0x01, 0x18, 0x10, "70k, 250k & 500k" }, + {0x13, 0x01, 0x18, 0x08, "50k" }, + {0x13, 0x01, 0x18, 0x00, "70k" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x01, 0x01, "Off" }, +// {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Gbusters) + +static void set_ram_bank(INT32 data) +{ + nDrvRamBank[0] = data; + + if (~data & 0x01) { + konamiMapMemory(DrvPalRAM, 0x5800, 0x5fff, KON_RAM); + } else { + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + } +} + +void gbusters_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1f80: + set_ram_bank(data); + return; + + case 0x1f84: + *soundlatch = data; + return; + + case 0x1f88: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + + return; + + case 0x1f8c: + // watchdog + return; + + case 0x1f98: + K052109RMRDLine = data & 0x01; + return; + } + + if ((address & 0xc000) == 0x0000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 gbusters_main_read(UINT16 address) +{ + switch (address) + { + case 0x1f90: + return DrvInputs[0]; + + case 0x1f91: + return DrvInputs[1]; + + case 0x1f92: + return DrvInputs[2]; + + case 0x1f93: + return DrvDips[2]; + + case 0x1f94: + return DrvDips[0]; + + case 0x1f95: + return DrvDips[1]; + } + + if ((address & 0xc000) == 0x0000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +static void gbusters_snd_bankswitch_w(INT32 data) +{ + INT32 bank_B = ((data >> 2) & 0x01); + INT32 bank_A = ((data) & 0x01); + k007232_set_bank(0, bank_A, bank_B ); +} + +void __fastcall gbusters_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xf000: + gbusters_snd_bankswitch_w(data); + return; + } +} + +UINT8 __fastcall gbusters_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void gbusters_set_lines(INT32 lines) +{ + INT32 nBank = 0x10000 + (lines & 0x0f) * 0x2000; + + nDrvKonamiBank[1] = lines; + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM); +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + INT32 layer_colorbase[3] = { 0x30, 0x00, 0x10 }; + + *code |= ((*color & 0x0d) << 8) | ((*color & 0x10) << 5) | (bank << 12); + *code &= 0x3fff; + *color = layer_colorbase[layer] + ((*color & 0xe0) >> 5); +} + +static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = (*color & 0x30) >> 4; + *color = 0x20 + (*color & 0x0f); + *code &= 0x0fff; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x100000; + + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001800; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvRamBank = Next; Next += 0x000001; + nDrvKonamiBank = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x80000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x80000); + + GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x01000, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x000000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x020000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x10000, DrvKonROM + 0x00000, 0x08000); + memcpy (DrvKonROM + 0x18000, DrvKonROM + 0x00000, 0x08000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 7, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x4000, 0x57ff, KON_RAM); + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(gbusters_main_write); + konamiSetReadHandler(gbusters_main_read); + konamiSetlinesCallback(gbusters_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(gbusters_sound_write); + ZetSetReadHandler(gbusters_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + + K007232Init(0, 3579545, DrvSndROM, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0x7ffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x800); + } + + K052109UpdateScroll(); + + if (nDrvRamBank[0] & 0x08) + { + + if (nBurnLayer & 1) K052109RenderLayer(2, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + if (nBurnLayer & 2) K052109RenderLayer(1, 0, DrvGfxROMExp0); + } + else + { + if (nBurnLayer & 4) K052109RenderLayer(1, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + if (nBurnLayer & 8) K052109RenderLayer(2, 0, DrvGfxROMExp0); + } + + K051960SpritesRender(DrvGfxROMExp1, 1); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = nBurnSoundLen; + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + set_ram_bank(nDrvRamBank[0]); + gbusters_set_lines(nDrvKonamiBank[1]); + konamiClose(); + } + + return 0; +} + + +// Gang Busters (set 1) + +static struct BurnRomInfo gbustersRomDesc[] = { + { "878n02.k13", 0x10000, 0x51697aaa, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "878j03.k15", 0x10000, 0x3943a065, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "878h01.f8", 0x08000, 0x96feafaa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "878c07.h27", 0x40000, 0xeeed912c, 3 | BRF_GRA }, // 3 Background Tiles + { "878c08.k27", 0x40000, 0x4d14626d, 3 | BRF_GRA }, // 4 + + { "878c05.h5", 0x40000, 0x01f4aea5, 4 | BRF_GRA }, // 5 Sprites + { "878c06.k5", 0x40000, 0xedfaaaaf, 4 | BRF_GRA }, // 6 + + { "878c04.d5", 0x40000, 0x9e982d1c, 5 | BRF_SND }, // 7 K007232 Samples + + { "878a09.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 8 Proms +}; + +STD_ROM_PICK(gbusters) +STD_ROM_FN(gbusters) + +struct BurnDriver BurnDrvGbusters = { + "gbusters", NULL, NULL, NULL, "1988", + "Gang Busters (set 1)\0", NULL, "Konami", "GX878", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, gbustersRomInfo, gbustersRomName, NULL, NULL, GbustersInputInfo, GbustersDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 288, 3, 4 +}; + + +// Gang Busters (set 2) + +static struct BurnRomInfo gbusteraRomDesc[] = { + { "878_02.k13", 0x10000, 0x57178414, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "878_03.k15", 0x10000, 0x6c59e660, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "878h01.f8", 0x08000, 0x96feafaa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "878c07.h27", 0x40000, 0xeeed912c, 3 | BRF_GRA }, // 3 Background Tiles + { "878c08.k27", 0x40000, 0x4d14626d, 3 | BRF_GRA }, // 4 + + { "878c05.h5", 0x40000, 0x01f4aea5, 4 | BRF_GRA }, // 5 Sprites + { "878c06.k5", 0x40000, 0xedfaaaaf, 4 | BRF_GRA }, // 6 + + { "878c04.d5", 0x40000, 0x9e982d1c, 5 | BRF_SND }, // 7 K007232 Samples + + { "878a09.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 8 Proms +}; + +STD_ROM_PICK(gbustera) +STD_ROM_FN(gbustera) + +struct BurnDriver BurnDrvGbustera = { + "gbustersa", "gbusters", NULL, NULL, "1988", + "Gang Busters (set 2)\0", NULL, "Konami", "GX878", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, gbusteraRomInfo, gbusteraRomName, NULL, NULL, GbustersInputInfo, GbustersDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 288, 3, 4 +}; + + +// Crazy Cop (Japan) + +static struct BurnRomInfo crazycopRomDesc[] = { + { "878m02.k13", 0x10000, 0x9c1c9f52, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "878j03.k15", 0x10000, 0x3943a065, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "878h01.f8", 0x08000, 0x96feafaa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "878c07.h27", 0x40000, 0xeeed912c, 3 | BRF_GRA }, // 3 Background Tiles + { "878c08.k27", 0x40000, 0x4d14626d, 3 | BRF_GRA }, // 4 + + { "878c05.h5", 0x40000, 0x01f4aea5, 4 | BRF_GRA }, // 5 Sprites + { "878c06.k5", 0x40000, 0xedfaaaaf, 4 | BRF_GRA }, // 6 + + { "878c04.d5", 0x40000, 0x9e982d1c, 5 | BRF_SND }, // 7 K007232 Samples + + { "878a09.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 8 Proms +}; + +STD_ROM_PICK(crazycop) +STD_ROM_FN(crazycop) + +struct BurnDriver BurnDrvCrazycop = { + "crazycop", "gbusters", NULL, NULL, "1988", + "Crazy Cop (Japan)\0", NULL, "Konami", "GX878", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, crazycopRomInfo, crazycopRomName, NULL, NULL, GbustersInputInfo, GbustersDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/konami/d_gradius3.cpp b/src/burn/drivers/konami/d_gradius3.cpp new file mode 100644 index 00000000..d13440a5 --- /dev/null +++ b/src/burn/drivers/konami/d_gradius3.cpp @@ -0,0 +1,973 @@ +// FB Alpha Gradius 3 driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM0; +static UINT8 *Drv68KROM1; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvShareRAM; +static UINT8 *DrvShareRAM2; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; + +static INT32 gradius3_priority; +static INT32 gradius3_cpub_enable; +static INT32 irqA_enable; +static INT32 irqB_mask; + +static INT32 interrupt_triggered = 0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT16 DrvInputs[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo Gradius3InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Gradius3) + +static struct BurnDIPInfo Gradius3DIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x5a, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x15, 0x01, 0x04, 0x00, "Upright" }, +// {0x15, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "20000 and every 70000" }, + {0x15, 0x01, 0x18, 0x10, "100000 and every 100000" }, + {0x15, 0x01, 0x18, 0x08, "50000" }, + {0x15, 0x01, 0x18, 0x00, "100000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Hard" }, + {0x15, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x16, 0x01, 0x01, 0x01, "Off" }, +// {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x02, 0x02, "Single" }, + {0x16, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Gradius3) + +void __fastcall gradius3_main_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0x14c000 && address <= 0x153fff) { + address -= 0x14c000; + K052109Write(address / 2, data); + return; + } +} + +void __fastcall gradius3_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x0c0000: + case 0x0c0001: + { + // if enabling CPU B, burn off some cycles to keep things sync'd. + if (gradius3_cpub_enable & 8 && ~data & 8) { + INT32 cycles_to_burn = SekTotalCycles(); + SekClose(); + SekOpen(1); + SekIdle(cycles_to_burn - SekTotalCycles()); + SekClose(); + SekOpen(0); + } + + gradius3_priority = data & 0x04; + gradius3_cpub_enable = data & 0x08; + irqA_enable = data & 0x20; + } + return; + + case 0x0d8000: + case 0x0d8001: + interrupt_triggered = irqB_mask & 0x04; + return; + + case 0x0e0000: + case 0x0e0001: + // watchdog + return; + + case 0x0e8000: + *soundlatch = data; + return; + + case 0x0f0000: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + + return; + } + + if (address >= 0x14c000 && address <= 0x153fff) { + address -= 0x14c000; + K052109Write(address / 2, data); + return; + } +} + +UINT16 __fastcall gradius3_main_read_word(UINT32 address) +{ + if (address >= 0x14c000 && address <= 0x153fff) { + address -= 0x14c000; + return K052109Read(address / 2); + } + + return 0; +} + +UINT8 __fastcall gradius3_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x0c8000: + case 0x0c8001: + return DrvInputs[0]; + + case 0x0c8002: + case 0x0c8003: + return DrvInputs[1]; + + case 0x0c8004: + case 0x0c8005: + return DrvInputs[2]; + + case 0x0c8006: + case 0x0c8007: + return DrvDips[2]; + + case 0x0d0000: + case 0x0d0001: + return DrvDips[0]; + + case 0x0d0002: + case 0x0d0003: + return DrvDips[1]; + } + + if (address >= 0x14c000 && address <= 0x153fff) { + address -= 0x14c000; + return K052109Read(address / 2); + } + + return 0; +} + +void __fastcall gradius3_sub_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffffe) == 0x140000) { + irqB_mask = (data >> 8) & 0x07; + return; + } + + if (address >= 0x24c000 && address <= 0x253fff) { + address -= 0x24c000; + K052109Write(address / 2, data); + return; + } + + if ((address & 0xffffff0) == 0x2c0000) { + address -= 0x2c0000; + K051937Write(address / 2, data); + return; + } + + if ((address & 0xffff800) == 0x2c0800) { + address -= 0x2c0800; + K051960Write(address /2, data); + return; + } +} + +void __fastcall gradius3_sub_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffffe) == 0x140000) { + irqB_mask = data & 0x07; + return; + } + + if (address >= 0x24c000 && address <= 0x253fff) { + address -= 0x24c000; + K052109Write(address / 2, data); + return; + } + + if ((address & 0xffffff0) == 0x2c0000) { + address -= 0x2c0000; + K051937Write(address / 2, data); + return; + } + + if ((address & 0xffff800) == 0x2c0800) { + address -= 0x2c0800; + K051960Write(address /2, data); + return; + } +} + +UINT16 __fastcall gradius3_sub_read_word(UINT32 address) +{ + if (address >= 0x24c000 && address <= 0x253fff) { + address -= 0x24c000; + return K052109Read(address / 2); + } + + if ((address & 0xffffff0) == 0x2c0000) { + address -= 0x2c0000; + return K051937Read(address / 2); + } + + if ((address & 0xffff800) == 0x2c0800) { + address -= 0x2c0800; + return K051960Read(address / 2); + } + + return 0; +} + +UINT8 __fastcall gradius3_sub_read_byte(UINT32 address) +{ + if (address >= 0x24c000 && address <= 0x253fff) { + address -= 0x24c000; + return K052109Read(address / 2); + } + + if ((address & 0xffffff0) == 0x2c0000) { + address -= 0x2c0000; + return K051937Read(address / 2); + } + + if ((address & 0xffff800) == 0x2c0800) { + address -= 0x2c0800; + return K051960Read(address / 2); + } + + return 0; +} + +static void k007232_bank(INT32 , INT32 data) +{ + INT32 bank_A = (data >> 0) & 0x03; + INT32 bank_B = (data >> 2) & 0x03; + + k007232_set_bank(0, bank_A, bank_B); +} + +void __fastcall gradius3_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xf020) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xf000: + k007232_bank(0, data); + return; + + case 0xf030: + BurnYM2151SelectRegister(data); + return; + + case 0xf031: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall gradius3_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xf020) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xf010: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xf031: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void K052109Callback(INT32 layer, INT32, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + INT32 layer_colorbase[3] = { 0, 32, 48 }; + + *code |= ((*color & 0x01) << 8) | ((*color & 0x1c) << 7); + *code &= 0xfff; + *color = layer_colorbase[layer] + ((*color & 0xe0) >> 5); +} + +static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = (*color & 0x60) >> 5; + + *code |= (*color & 0x01) << 13; + *code &= 0x3fff; + *color = 0x10 + ((*color & 0x1e) >> 1); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + SekOpen(1); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + gradius3_priority = 0; + gradius3_cpub_enable = 0; + irqA_enable = 0; + irqB_mask = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM0 = Next; Next += 0x100000; + Drv68KROM1 = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROMExp0 = Next; Next += 0x040000; + DrvGfxROMExp1 = Next; Next += 0x400000; + + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + Drv68KRAM0 = Next; Next += 0x004000; + Drv68KRAM1 = Next; Next += 0x004000; + DrvShareRAM = Next; Next += 0x004000; + DrvShareRAM2 = Next; Next += 0x020000; + DrvPalRAM = Next; Next += 0x001000; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000, 0x01, 0x002, 0x003 }; + INT32 XOffs[16] = { 2*4, 3*4, 0*4, 1*4, 6*4, 7*4, 4*4, 5*4, + 32*8+2*4, 32*8+3*4, 32*8+0*4, 32*8+1*4, 32*8+6*4, 32*8+7*4, 32*8+4*4, 32*8+5*4 }; + INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, + 64*8+0*32, 64*8+1*32, 64*8+2*32, 64*8+3*32, 64*8+4*32, 64*8+5*32, 64*8+6*32, 64*8+7*32 }; + + konami_rom_deinterleave_2(DrvGfxROM1, 0x200000); + + GfxDecode(0x04000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM0 + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(Drv68KROM1 + 0x000001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x040000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x080001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x080000, 7, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x0c0001, 8, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x0c0000, 9, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1c0000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1c0001, 20, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 21, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x040000, 22, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x060000, 23, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM0, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM0, 0x040000, 0x043fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvShareRAM, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvShareRAM2, 0x180000, 0x19ffff, SM_RAM); + SekSetWriteWordHandler(0, gradius3_main_write_word); + SekSetWriteByteHandler(0, gradius3_main_write_byte); + SekSetReadWordHandler(0, gradius3_main_read_word); + SekSetReadByteHandler(0, gradius3_main_read_byte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Drv68KROM1, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM1, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvShareRAM, 0x200000, 0x203fff, SM_RAM); + SekMapMemory(DrvShareRAM2, 0x280000, 0x29ffff, SM_RAM); + SekMapMemory(DrvGfxROM1, 0x400000, 0x5fffff, SM_ROM); + SekSetWriteWordHandler(0, gradius3_sub_write_word); + SekSetWriteByteHandler(0, gradius3_sub_write_byte); + SekSetReadWordHandler(0, gradius3_sub_read_word); + SekSetReadByteHandler(0, gradius3_sub_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + ZetSetWriteHandler(gradius3_sound_write); + ZetSetReadHandler(gradius3_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + + K007232Init(0, 3579545, DrvSndROM, 0x80000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + K052109Init(DrvShareRAM2, 0x1ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(-8, 0); + + K051960Init(DrvGfxROM1, 0x1fffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(-8, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + SekExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static inline void character_ram_decode() +{ + for (INT32 i = 0; i < 0x20000; i++) + { + INT32 t = DrvShareRAM2[i ^ 1]; + + DrvGfxROMExp0[i * 2 + 0] = t >> 4; + DrvGfxROMExp0[i * 2 + 1] = t & 0x0f; + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + r = (p[i] >> 10) & 0x1f; + g = (p[i] >> 5) & 0x1f; + b = (p[i] >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + K052109Write(0x1d80,0x10); + K052109Write(0x1f00,0x32); + + K052109UpdateScroll(); + + character_ram_decode(); + + if (gradius3_priority == 0) + { + if (nSpriteEnable & 1) K052109RenderLayer(1, 1, DrvGfxROMExp0); + + if (nBurnLayer & 4) K051960SpritesRender(DrvGfxROMExp1, 3); + + if (nBurnLayer & 2) K051960SpritesRender(DrvGfxROMExp1, 1); + + if (nBurnLayer & 8) K051960SpritesRender(DrvGfxROMExp1, 0); + + if (nSpriteEnable & 2) K052109RenderLayer(2, 0, DrvGfxROMExp0); + + if (nSpriteEnable & 4) K052109RenderLayer(0, 0, DrvGfxROMExp0); + + if (nBurnLayer & 1) K051960SpritesRender(DrvGfxROMExp1, 2); + } + else + { + + if (nSpriteEnable & 1) K052109RenderLayer(0, 1, DrvGfxROMExp0); + if (nSpriteEnable & 2) K052109RenderLayer(1, 0, DrvGfxROMExp0); + if (nSpriteEnable & 4) K052109RenderLayer(2, 0, DrvGfxROMExp0); +#if 1 + if (nBurnLayer & 1) K051960SpritesRender(DrvGfxROMExp1, 2); + if (nBurnLayer & 2) K051960SpritesRender(DrvGfxROMExp1, 1); + if (nBurnLayer & 4) K051960SpritesRender(DrvGfxROMExp1, 3); + if (nBurnLayer & 8) K051960SpritesRender(DrvGfxROMExp1, 0); +#endif + } + + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3 * sizeof(short)); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + SekNewFrame(); + + INT32 nCycleSegment; + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + INT32 nCyclesTotal[3] = { 10000000 / 60, 10000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + SekOpen(0); + nCycleSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + nCyclesDone[0] += SekRun(nCycleSegment - nCyclesDone[0]); + if (i == nInterleave - 1 && irqA_enable) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (gradius3_cpub_enable) { + SekOpen(1); + nCycleSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + nCyclesDone[1] += SekRun(nCycleSegment - SekTotalCycles()); + if (interrupt_triggered) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave - 1) && (irqB_mask & 1)) + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + if (i == ((nInterleave / 2) - 1) && (irqB_mask & 2)) + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + nCycleSegment = (nCyclesTotal[2] / nInterleave) * (i + 1); + nCyclesDone[2] += ZetRun(nCycleSegment - nCyclesDone[2]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + interrupt_triggered = 0; + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + + SCAN_VAR(gradius3_priority); + SCAN_VAR(gradius3_cpub_enable); + SCAN_VAR(irqA_enable); + SCAN_VAR(irqB_mask); + } + + if (nAction & ACB_WRITE) { + character_ram_decode(); + } + + return 0; +} + + +// Gradius III (Japan) + +static struct BurnRomInfo gradius3RomDesc[] = { + { "945_s13.f15", 0x20000, 0x70c240a2, 1 | BRF_PRG | BRF_ESS }, // 0 68k #0 Code + { "945_s12.e15", 0x20000, 0xbbc300d4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "945_m09.r17", 0x20000, 0xb4a6df25, 2 | BRF_PRG | BRF_ESS }, // 2 68k #1 Code + { "945_m08.n17", 0x20000, 0x74e981d2, 2 | BRF_PRG | BRF_ESS }, // 3 + { "945_l06b.r11", 0x20000, 0x83772304, 2 | BRF_PRG | BRF_ESS }, // 4 + { "945_l06a.n11", 0x20000, 0xe1fd75b6, 2 | BRF_PRG | BRF_ESS }, // 5 + { "945_l07c.r15", 0x20000, 0xc1e399b6, 2 | BRF_PRG | BRF_ESS }, // 6 + { "945_l07a.n15", 0x20000, 0x96222d04, 2 | BRF_PRG | BRF_ESS }, // 7 + { "945_l07d.r13", 0x20000, 0x4c16d4bd, 2 | BRF_PRG | BRF_ESS }, // 8 + { "945_l07b.n13", 0x20000, 0x5e209d01, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "945_m05.d9", 0x10000, 0xc8c45365, 3 | BRF_PRG | BRF_ESS }, // 10 Z80 Code + + { "945_a02.l3", 0x80000, 0x4dfffd74, 4 | BRF_GRA }, // 11 Sprites + { "945_l04a.k6", 0x20000, 0x884e21ee, 4 | BRF_GRA }, // 12 + { "945_l04c.m6", 0x20000, 0x45bcd921, 4 | BRF_GRA }, // 13 + { "945_l04b.k8", 0x20000, 0x843bc67d, 4 | BRF_GRA }, // 14 + { "945_l04d.m8", 0x20000, 0x0a98d08e, 4 | BRF_GRA }, // 15 + { "945_a01.h3", 0x80000, 0x339d6dd2, 4 | BRF_GRA }, // 16 + { "945_l03a.e6", 0x20000, 0xa67ef087, 4 | BRF_GRA }, // 17 + { "945_l03c.h6", 0x20000, 0xa56be17a, 4 | BRF_GRA }, // 18 + { "945_l03b.e8", 0x20000, 0x933e68b9, 4 | BRF_GRA }, // 19 + { "945_l03d.h8", 0x20000, 0xf375e87b, 4 | BRF_GRA }, // 20 + + { "945_a10.b15", 0x40000, 0x1d083e10, 5 | BRF_SND }, // 21 K007232 + { "945_l11a.c18", 0x20000, 0x6043f4eb, 5 | BRF_SND }, // 22 + { "945_l11b.c20", 0x20000, 0x89ea3baf, 5 | BRF_SND }, // 23 + + { "945l14.j28", 0x00100, 0xc778c189, 6 | BRF_OPT }, // 24 Prom +}; + +STD_ROM_PICK(gradius3) +STD_ROM_FN(gradius3) + +struct BurnDriver BurnDrvGradius3 = { + "gradius3", NULL, NULL, NULL, "1989", + "Gradius III (Japan)\0", NULL, "Konami", "GX945", + L"Gradius III \u4F1D\u8AAC\u304B\u3089\u795E\u8A71\u3078 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, gradius3RomInfo, gradius3RomName, NULL, NULL, Gradius3InputInfo, Gradius3DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Gradius III (Asia) + +static struct BurnRomInfo grdius3aRomDesc[] = { + { "945_13.f15", 0x20000, 0x9974fe6b, 1 | BRF_PRG | BRF_ESS }, // 0 68k #0 Code + { "945_12.e15", 0x20000, 0xe9771b91, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "945_m09.r17", 0x20000, 0xb4a6df25, 2 | BRF_PRG | BRF_ESS }, // 2 68k #1 Code + { "945_m08.n17", 0x20000, 0x74e981d2, 2 | BRF_PRG | BRF_ESS }, // 3 + { "945_l06b.r11", 0x20000, 0x83772304, 2 | BRF_PRG | BRF_ESS }, // 4 + { "945_l06a.n11", 0x20000, 0xe1fd75b6, 2 | BRF_PRG | BRF_ESS }, // 5 + { "945_l07c.r15", 0x20000, 0xc1e399b6, 2 | BRF_PRG | BRF_ESS }, // 6 + { "945_l07a.n15", 0x20000, 0x96222d04, 2 | BRF_PRG | BRF_ESS }, // 7 + { "945_l07d.r13", 0x20000, 0x4c16d4bd, 2 | BRF_PRG | BRF_ESS }, // 8 + { "945_l07b.n13", 0x20000, 0x5e209d01, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "945_m05.d9", 0x10000, 0xc8c45365, 3 | BRF_PRG | BRF_ESS }, // 10 Z80 Code + + { "945_a02.l3", 0x80000, 0x4dfffd74, 4 | BRF_GRA }, // 11 Sprites + { "945_l04a.k6", 0x20000, 0x884e21ee, 4 | BRF_GRA }, // 12 + { "945_l04c.m6", 0x20000, 0x45bcd921, 4 | BRF_GRA }, // 13 + { "945_l04b.k8", 0x20000, 0x843bc67d, 4 | BRF_GRA }, // 14 + { "945_l04d.m8", 0x20000, 0x0a98d08e, 4 | BRF_GRA }, // 15 + { "945_a01.h3", 0x80000, 0x339d6dd2, 4 | BRF_GRA }, // 16 + { "945_l03a.e6", 0x20000, 0xa67ef087, 4 | BRF_GRA }, // 17 + { "945_l03c.h6", 0x20000, 0xa56be17a, 4 | BRF_GRA }, // 18 + { "945_l03b.e8", 0x20000, 0x933e68b9, 4 | BRF_GRA }, // 19 + { "945_l03d.h8", 0x20000, 0xf375e87b, 4 | BRF_GRA }, // 20 + + { "945_a10.b15", 0x40000, 0x1d083e10, 5 | BRF_SND }, // 21 K007232 + { "945_l11a.c18", 0x20000, 0x6043f4eb, 5 | BRF_SND }, // 22 + { "945_l11b.c20", 0x20000, 0x89ea3baf, 5 | BRF_SND }, // 23 + + { "945l14.j28", 0x00100, 0xc778c189, 6 | BRF_OPT }, // 24 Prom +}; + +STD_ROM_PICK(grdius3a) +STD_ROM_FN(grdius3a) + +struct BurnDriver BurnDrvGrdius3a = { + "gradius3a", "gradius3", NULL, NULL, "1989", + "Gradius III (Asia)\0", NULL, "Konami", "GX945", + L"Gradius III \u4F1D\u8AAC\u304B\u3089\u795E\u8A71\u3078 (Asia)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, grdius3aRomInfo, grdius3aRomName, NULL, NULL, Gradius3InputInfo, Gradius3DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Gradius III (World ?) + +static struct BurnRomInfo grdius3eRomDesc[] = { + { "945_r13.f15", 0x20000, 0xcffd103f, 1 | BRF_PRG | BRF_ESS }, // 0 68k #0 Code + { "945_r12.e15", 0x20000, 0x0b968ef6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "945_m09.r17", 0x20000, 0xb4a6df25, 2 | BRF_PRG | BRF_ESS }, // 2 68k #1 Code + { "945_m08.n17", 0x20000, 0x74e981d2, 2 | BRF_PRG | BRF_ESS }, // 3 + { "945_l06b.r11", 0x20000, 0x83772304, 2 | BRF_PRG | BRF_ESS }, // 4 + { "945_l06a.n11", 0x20000, 0xe1fd75b6, 2 | BRF_PRG | BRF_ESS }, // 5 + { "945_l07c.r15", 0x20000, 0xc1e399b6, 2 | BRF_PRG | BRF_ESS }, // 6 + { "945_l07a.n15", 0x20000, 0x96222d04, 2 | BRF_PRG | BRF_ESS }, // 7 + { "945_l07d.r13", 0x20000, 0x4c16d4bd, 2 | BRF_PRG | BRF_ESS }, // 8 + { "945_l07b.n13", 0x20000, 0x5e209d01, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "945_m05.d9", 0x10000, 0xc8c45365, 3 | BRF_PRG | BRF_ESS }, // 10 Z80 Code + + { "945_a02.l3", 0x80000, 0x4dfffd74, 4 | BRF_GRA }, // 11 Sprites + { "945_l04a.k6", 0x20000, 0x884e21ee, 4 | BRF_GRA }, // 12 + { "945_l04c.m6", 0x20000, 0x45bcd921, 4 | BRF_GRA }, // 13 + { "945_l04b.k8", 0x20000, 0x843bc67d, 4 | BRF_GRA }, // 14 + { "945_l04d.m8", 0x20000, 0x0a98d08e, 4 | BRF_GRA }, // 15 + { "945_a01.h3", 0x80000, 0x339d6dd2, 4 | BRF_GRA }, // 16 + { "945_l03a.e6", 0x20000, 0xa67ef087, 4 | BRF_GRA }, // 17 + { "945_l03c.h6", 0x20000, 0xa56be17a, 4 | BRF_GRA }, // 18 + { "945_l03b.e8", 0x20000, 0x933e68b9, 4 | BRF_GRA }, // 19 + { "945_l03d.h8", 0x20000, 0xf375e87b, 4 | BRF_GRA }, // 20 + + { "945_a10.b15", 0x40000, 0x1d083e10, 5 | BRF_SND }, // 21 K007232 + { "945_l11a.c18", 0x20000, 0x6043f4eb, 5 | BRF_SND }, // 22 + { "945_l11b.c20", 0x20000, 0x89ea3baf, 5 | BRF_SND }, // 23 + + { "945l14.j28", 0x00100, 0xc778c189, 6 | BRF_OPT }, // 24 Prom +}; + +STD_ROM_PICK(grdius3e) +STD_ROM_FN(grdius3e) + +struct BurnDriver BurnDrvGrdius3e = { + "gradius3e", "gradius3", NULL, NULL, "1989", + "Gradius III (World)\0", NULL, "Konami", "GX945", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, grdius3eRomInfo, grdius3eRomName, NULL, NULL, Gradius3InputInfo, Gradius3DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_hcastle.cpp b/src/burn/drivers/konami/d_hcastle.cpp new file mode 100644 index 00000000..2ea7cf8a --- /dev/null +++ b/src/burn/drivers/konami/d_hcastle.cpp @@ -0,0 +1,975 @@ +// FB Alpha Haunted Castle / Akuma-Jou Dracula driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "burn_ym3812.h" +#include "K051649.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *nDrvKonBank; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPalROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvKonRAM0; +static UINT8 *DrvKonRAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPf1RAM; +static UINT8 *DrvPf2RAM; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSprRAM2; +static UINT8 *DrvSprBuf1; +static UINT8 *DrvSprBuf2; +static UINT8 *DrvPf1Ctrl; +static UINT8 *DrvPf2Ctrl; +static UINT8 *DrvZ80RAM; +static UINT8 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static UINT8 *soundlatch; +static UINT8 *gfxbank; + +static INT32 watchdog; + +static struct BurnInputInfo HcastleInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Hcastle) + +static struct BurnDIPInfo HcastleDIPList[]= +{ + {0x12, 0xff, 0xff, 0x53, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x04, 0x00, "Upright" }, + {0x12, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x18, 0x18, "Easy" }, + {0x12, 0x01, 0x18, 0x10, "Normal" }, + {0x12, 0x01, 0x18, 0x08, "Hard" }, + {0x12, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Damage" }, + {0x12, 0x01, 0x60, 0x60, "Small" }, + {0x12, 0x01, 0x60, 0x40, "Normal" }, + {0x12, 0x01, 0x60, 0x20, "Big" }, + {0x12, 0x01, 0x60, 0x00, "Biggest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x14, 0x01, 0x02, 0x02, "Single" }, + {0x14, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x08, 0x08, "No" }, + {0x14, 0x01, 0x08, 0x00, "Yes" }, +}; + +STDDIPINFO(Hcastle) + +static void bankswitch(INT32 data) +{ + *nDrvKonBank = data & 0x0f; + INT32 bankaddress = *nDrvKonBank * 0x2000; + + konamiMapMemory(DrvKonROM + 0x10000 + bankaddress, 0x6000, 0x7fff, KON_ROM); +} + +static void playfield_write(INT32 address, INT32 data, UINT8 *ctrl, UINT8 *spr, UINT8 *buf) +{ + address &= 7; + + if (address == 3) { // buffer sprites + memcpy (buf, spr + ((data & 8) << 8), 0x800); + } + + ctrl[address & 7] = data; +} + +void hcastle_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff8) == 0x0000) { + playfield_write(address, data, DrvPf1Ctrl, DrvSprRAM1, DrvSprBuf1); + return; + } + + if ((address & 0xfff8) == 0x0200) { + playfield_write(address, data, DrvPf2Ctrl, DrvSprRAM2, DrvSprBuf2); + return; + } + + if ((address & 0xff00) == 0x0000) { + DrvKonRAM0[address & 0xff] = data; + return; + } + + if ((address & 0xff00) == 0x0200) { + DrvKonRAM1[address & 0xff] = data; + return; + } + + switch (address) + { + case 0x0400: + bankswitch(data); + return; + + case 0x0404: + *soundlatch = data; + return; + + case 0x0408: + { + float t = konamiTotalCycles() * 1.19318167; + t -= ZetTotalCycles(); + if (t > 1) ZetRun((INT32)t); + + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + return; + + case 0x040c: + watchdog = 0; + return; + + case 0x0410: + + return; + + case 0x0418: + *gfxbank = data; + return; + } +} + +UINT8 hcastle_read(UINT16 address) +{ + switch (address) + { + case 0x0410: + case 0x0411: + case 0x0412: + return DrvInputs[address & 3]; + + case 0x0413: + return DrvDips[2]; + + case 0x0414: + return DrvDips[1]; + + case 0x0415: + return DrvDips[0]; + + case 0x0418: + return *gfxbank; + } + + return 0; +} + +static void sound_bankswitch(INT32 data) +{ + INT32 bank_A=(data&0x3); + INT32 bank_B=((data>>2)&0x3); + bank_A=bank_B; + k007232_set_bank(0, bank_A, bank_B ); +} + +void __fastcall hcastle_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xff80) == 0x9800) { + K051649WaveformWrite(address & 0x7f, data); + return; + } + + if ((address & 0xfff0) == 0x9880) { + address &= 0x000f; + + if (address <= 0x09) { + K051649FrequencyWrite(address & 0x0f, data); + return; + } + + if (address == 0x0f) { + K051649KeyonoffWrite(data); + return; + } + + if (address >= 0x0a) { + K051649VolumeWrite(address - 0x988a, data); + } + + return; + } + + if (address >= 0xb000 && address <= 0xb00d) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xa000: + case 0xa001: + BurnYM3812Write(address & 1, data); + return; + + case 0xc000: + sound_bankswitch(data); + return; + } +} + +UINT8 __fastcall hcastle_sound_read(UINT16 address) +{ + if (address >= 0xb000 && address <= 0xb00d) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xa000: + case 0xa001: + return BurnYM3812Read(address & 1); + + case 0xd000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + K051649Reset(); + BurnYM3812Reset(); + + watchdog = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + + DrvPalROM = Next; Next += 0x000400; + + DrvSndROM = Next; Next += 0x080000; + + Palette = Next; Next += 0x001000; + DrvPalette = (UINT32*)Next; Next += 0x1000 * sizeof(UINT32); + + AllRam = Next; + + DrvKonRAM0 = Next; Next += 0x000100; + DrvKonRAM1 = Next; Next += 0x000100; + DrvPalRAM = Next; Next += 0x002000; + DrvPf1RAM = Next; Next += 0x001000; + DrvPf2RAM = Next; Next += 0x001000; + DrvSprRAM1 = Next; Next += 0x001000; + DrvSprRAM2 = Next; Next += 0x001000; + DrvSprBuf1 = Next; Next += 0x000800; + DrvSprBuf2 = Next; Next += 0x000800; + + DrvPf1Ctrl = Next; Next += 0x000008; + DrvPf2Ctrl = Next; Next += 0x000008; + + DrvZ80RAM = Next; Next += 0x000800; + + nDrvKonBank = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + gfxbank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[8] = { 0x008, 0x00c, 0x000, 0x004, 0x018, 0x01c, 0x010, 0x014 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + UINT8 *tmp = (UINT8*)malloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x100000); + + GfxDecode(0x8000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x8000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 chip = 0; chip < 2; chip++) + { + for (INT32 pal = 0; pal < 8; pal++) + { + INT32 clut = (chip << 1) | (pal & 1); + + for (INT32 i = 0; i < 0x100; i++) + { + UINT8 ctabentry; + + if (((pal & 0x01) == 0) && (DrvPalROM[(clut << 8) | i] == 0)) + ctabentry = 0; + else + ctabentry = (pal << 4) | (DrvPalROM[(clut << 8) | i] & 0x0f); + + Palette[(chip << 11) | (pal << 8) | i] = ctabentry; + } + } + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x10000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x80000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvPalROM + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvPalROM + 0x00100, 9, 1)) return 1; + if (BurnLoadRom(DrvPalROM + 0x00200, 10, 1)) return 1; + if (BurnLoadRom(DrvPalROM + 0x00300, 11, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM0, 0x0000, 0x00ff, KON_ROM); //020-03f + konamiMapMemory(DrvKonRAM1, 0x0200, 0x02ff, KON_ROM); //220-23f + konamiMapMemory(DrvPalRAM, 0x0600, 0x1fff, KON_RAM); + konamiMapMemory(DrvPf1RAM, 0x2000, 0x2fff, KON_RAM); + konamiMapMemory(DrvSprRAM1, 0x3000, 0x3fff, KON_RAM); + konamiMapMemory(DrvPf2RAM, 0x4000, 0x4fff, KON_RAM); + konamiMapMemory(DrvSprRAM2, 0x5000, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(hcastle_write); + konamiSetReadHandler(hcastle_read); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(hcastle_sound_write); + ZetSetReadHandler(hcastle_sound_read); + ZetClose(); + + BurnYM3812Init(3579545, NULL, DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + K007232Init(0, 3579545, DrvSndROM, 0x80000); // no idea... + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + K051649Init(3579545/2, 0.64); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM3812Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void draw_layer(UINT8 *ram, UINT8 *ctrl, UINT8 *gfx, INT32 colbase, INT32 base, INT32 t) +{ + INT32 bit0 = ((ctrl[0x05] >> 0) & 0x03) + 2; + INT32 bit1 = ((ctrl[0x05] >> 2) & 0x03) + 1; + INT32 bit2 = ((ctrl[0x05] >> 4) & 0x03) + 0; + INT32 bit3 = ((ctrl[0x05] >> 6) & 0x03) - 1; + INT32 col = ((ctrl[0x06] << 1) & 0x60) | colbase; + + if (ctrl[0x03] & 0x01) base += 0x2000; + + INT32 scrollx = ((ctrl[0x01] << 8) | ctrl[0x00]) & 0x1ff; + INT32 scrolly = ctrl[0x02] & 0xff; + + INT32 tilemap_flip = ctrl[0x07] & 0x08; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 0x200; + sy -= scrolly; + if (sy < -7) sy += 0x100; + + // if (sx >= nScreenWidth || sy < 9 || sy > 240) continue; + + INT32 ofst = (offs & 0x1f) + ((offs >> 1) & 0x3e0) + ((offs & 0x20) << 6); + + INT32 attr = ram[ofst]; + INT32 code = ram[ofst + 0x400]; + INT32 color = (attr & 0x07) | col; + INT32 bank = ((attr & 0x80) >> 7) | ((attr >> bit0) & 0x02) | ((attr >> bit1) & 0x04) | ((attr >> bit2) & 0x08) | ((attr >> bit3) & 0x10); + + code += (bank << 8) + base; + + if (tilemap_flip) { + sx = 0xf8 - sx; + sy = 0xf8 - sy; + + if (t) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy-16, color, 4, 0, gfx); + } + } else { + if (t) { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy-16, color, 4, 0, gfx); + } + } + } +} + +static void draw_sprites(INT32 bank, UINT8 *source, UINT8 *ctrl, UINT8 *gfx, INT32 col) +{ + INT32 bank_base = (bank == 0) ? 0x4000 * (*gfxbank & 1) : 0; + + INT32 base_color = ((ctrl[6] & 0x30) << 1) + col; + INT32 flipscreen = ctrl[7] & 0x08; + + static const INT32 x_offset[4] = { 0x00, 0x01, 0x04, 0x05 }; + static const INT32 y_offset[4] = { 0x00, 0x02, 0x08, 0x0a }; + + for (INT32 i = 0; i < 0x40; i++) + { + INT32 number = source[0]; + INT32 sbank = source[1] & 0x0f; + INT32 sy = source[2]; + INT32 sx = source[3]; + INT32 attr = source[4]; + INT32 xflip = source[4] & 0x10; + INT32 yflip = source[4] & 0x20; + INT32 color = base_color + ((source[1] & 0xf0) >> 4); + INT32 width, height; + + if (attr & 0x01) sx -= 256; + if (sy >= 240) sy -= 256; + + number += ((sbank & 3) << 8) + ((attr & 0xc0) << 4); + number = (number << 2) | ((sbank >> 2) & 3); + number += bank_base; + + switch (attr & 0x0e) + { + case 0x06: width = 1; height = 1; break; + case 0x04: width = 1; height = 2; number &= (~2); break; + case 0x02: width = 2; height = 1; number &= (~1); break; + case 0x00: width = 2; height = 2; number &= (~3); break; + case 0x08: width = 4; height = 4; number &= (~3); break; + default: width = 1; height = 1; + } + + for (INT32 y = 0; y < height; y++) + { + INT32 yy = sy + y * 8; + INT32 ey = yflip ? (height-1-y) : y; + + for (INT32 x = 0; x < width; x++) + { + INT32 ex = xflip ? (width-1-x) : x; + INT32 xx = sx + x * 8; + + INT32 code = number + x_offset[ex] + y_offset[ey]; + + if (flipscreen) { + if (yflip ^ 0x20) { + if (xflip ^ 0x10) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, 248-xx, (248-yy)-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, 248-xx, (248-yy)-16, color, 4, 0, 0, gfx); + } + } else { + if (xflip ^ 0x10) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, 248-xx, (248-yy)-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, 248-xx, (248-yy)-16, color, 4, 0, 0, gfx); + } + } + } else { + if (yflip) { + if (xflip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, xx, yy-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, xx, yy-16, color, 4, 0, 0, gfx); + } + } else { + if (xflip) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, xx, yy-16, color, 4, 0, 0, gfx); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, xx, yy-16, color, 4, 0, 0, gfx); + } + } + } + } + } + + source += 5; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT32 tmp[0x80]; + + for (INT32 i = 0; i < 0x100; i+=2) { + UINT16 d = DrvPalRAM[i + 1] | (DrvPalRAM[i] << 8); + r = (d >> 0) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + tmp[i/2] = BurnHighCol(r, g, b, 0); + } + + for (INT32 i = 0; i < 0x1000; i++) { + DrvPalette[i] = tmp[Palette[i]]; + } + } + + BurnTransferClear(); + + if ((*gfxbank & 0x04) == 0) + { + if (nBurnLayer & 1) draw_layer(DrvPf2RAM, DrvPf2Ctrl, DrvGfxROM1, 0x90, ((*gfxbank & 2) >> 1) * 0x4000, 0); + if (nSpriteEnable & 1) draw_sprites(0, DrvSprBuf1, DrvPf1Ctrl, DrvGfxROM0, 0x00); + if (nSpriteEnable & 2) draw_sprites(1, DrvSprBuf2, DrvPf2Ctrl, DrvGfxROM1, 0x80); + if (nBurnLayer & 2) draw_layer(DrvPf1RAM, DrvPf1Ctrl, DrvGfxROM0, 0x10, 0x0000, 1); + } + else + { + if (nBurnLayer & 1) draw_layer(DrvPf2RAM, DrvPf2Ctrl, DrvGfxROM1, 0x90, ((*gfxbank & 2) >> 1) * 0x4000, 0); + if (nBurnLayer & 2) draw_layer(DrvPf1RAM, DrvPf1Ctrl, DrvGfxROM0, 0x10, 0x0000, 1); + if (nSpriteEnable & 1) draw_sprites(0, DrvSprBuf1, DrvPf1Ctrl, DrvGfxROM0, 0x00); + if (nSpriteEnable & 2) draw_sprites(1, DrvSprBuf2, DrvPf2Ctrl, DrvGfxROM1, 0x80); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + if (watchdog++ == 60) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + + ZetOpen(0); + konamiOpen(0); + + konamiRun(nCyclesTotal[0]); + konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + BurnTimerEndFrameYM3812(nCyclesTotal[1] - ZetTotalCycles()); + + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + K007232Update(0, pBurnSoundOut, nBurnSoundLen); + K051649Update(pBurnSoundOut, nBurnSoundLen); + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + K007232Scan(nAction, pnMin); + K051649Scan(nAction, pnMin); + + SCAN_VAR(watchdog); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + bankswitch(*nDrvKonBank); + konamiClose(); + } + + return 0; +} + + +// Haunted Castle (ver. M) + +static struct BurnRomInfo hcastleRomDesc[] = { + { "m03.k12", 0x08000, 0xd85e743d, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "b06.k8", 0x20000, 0xabd07866, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "768.e01", 0x08000, 0xb9fff184, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "768c09.g21", 0x80000, 0xe3be3fdd, 3 | BRF_GRA }, // 3 Bank #0 Tiles + { "768c08.g19", 0x80000, 0x9633db8b, 3 | BRF_GRA }, // 4 + + { "768c04.j5", 0x80000, 0x2960680e, 4 | BRF_GRA }, // 5 Bank #1 Tiles + { "768c05.j6", 0x80000, 0x65a2f227, 4 | BRF_GRA }, // 6 + + { "768c07.e17", 0x80000, 0x01f9889c, 5 | BRF_SND }, // 7 K007232 Samples + + { "768c13.j21", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 8 Color Proms + { "768c14.j22", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 9 + { "768c11.i4", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 10 + { "768c10.i3", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 11 + + { "768b12.d20", 0x00100, 0x362544b8, 0 | BRF_GRA | BRF_OPT }, // 12 Priority Prom +}; + +STD_ROM_PICK(hcastle) +STD_ROM_FN(hcastle) + +struct BurnDriver BurnDrvHcastle = { + "hcastle", NULL, NULL, NULL, "1988", + "Haunted Castle (ver. M)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hcastleRomInfo, hcastleRomName, NULL, NULL, HcastleInputInfo, HcastleDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Haunted Castle (ver. K) + +static struct BurnRomInfo hcastleoRomDesc[] = { + { "768.k03", 0x08000, 0x40ce4f38, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "768.g06", 0x20000, 0xcdade920, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "768.e01", 0x08000, 0xb9fff184, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "768c09.g21", 0x80000, 0xe3be3fdd, 3 | BRF_GRA }, // 3 Bank #0 Tiles + { "768c08.g19", 0x80000, 0x9633db8b, 3 | BRF_GRA }, // 4 + + { "768c04.j5", 0x80000, 0x2960680e, 4 | BRF_GRA }, // 5 Bank #1 Tiles + { "768c05.j6", 0x80000, 0x65a2f227, 4 | BRF_GRA }, // 6 + + { "768c07.e17", 0x80000, 0x01f9889c, 5 | BRF_SND }, // 7 K007232 Samples + + { "768c13.j21", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 8 Color Proms + { "768c14.j22", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 9 + { "768c11.i4", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 10 + { "768c10.i3", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 11 + + { "768b12.d20", 0x00100, 0x362544b8, 0 | BRF_GRA | BRF_OPT }, // 12 Priority Prom +}; + +STD_ROM_PICK(hcastleo) +STD_ROM_FN(hcastleo) + +struct BurnDriver BurnDrvHcastleo = { + "hcastleo", "hcastle", NULL, NULL, "1988", + "Haunted Castle (ver. K)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hcastleoRomInfo, hcastleoRomName, NULL, NULL, HcastleInputInfo, HcastleDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Akuma-Jou Dracula (Japan ver. P) + +static struct BurnRomInfo hcastlejRomDesc[] = { + { "768p03.k12", 0x08000, 0xd509e340, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "768j06.k8", 0x20000, 0x42283c3e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "768.e01", 0x08000, 0xb9fff184, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "768c09.g21", 0x80000, 0xe3be3fdd, 3 | BRF_GRA }, // 3 Bank #0 Tiles + { "768c08.g19", 0x80000, 0x9633db8b, 3 | BRF_GRA }, // 4 + + { "768c04.j5", 0x80000, 0x2960680e, 4 | BRF_GRA }, // 5 Bank #1 Tiles + { "768c05.j6", 0x80000, 0x65a2f227, 4 | BRF_GRA }, // 6 + + { "768c07.e17", 0x80000, 0x01f9889c, 5 | BRF_SND }, // 7 K007232 Samples + + { "768c13.j21", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 8 Color Proms + { "768c14.j22", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 9 + { "768c11.i4", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 10 + { "768c10.i3", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 11 + + { "768b12.d20", 0x00100, 0x362544b8, 0 | BRF_GRA | BRF_OPT }, // 12 Priority Prom +}; + +STD_ROM_PICK(hcastlej) +STD_ROM_FN(hcastlej) + +struct BurnDriver BurnDrvHcastlej = { + "hcastlej", "hcastle", NULL, NULL, "1988", + "Akuma-Jou Dracula (Japan ver. P)\0", NULL, "Konami", "Miscellaneous", + L"\u60AA\u9B54\u57CE \u30C9\u30E9\u30AD\u30E5\u30E9 (Japan ver. P)\0Akuma-Jou Dracula\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hcastlejRomInfo, hcastlejRomName, NULL, NULL, HcastleInputInfo, HcastleDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Akuma-Jou Dracula (Japan ver. N) + +static struct BurnRomInfo hcastljoRomDesc[] = { + { "768n03.k12", 0x08000, 0x3e4dca2a, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "768j06.k8", 0x20000, 0x42283c3e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "768.e01", 0x08000, 0xb9fff184, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "768c09.g21", 0x80000, 0xe3be3fdd, 3 | BRF_GRA }, // 3 Bank #0 Tiles + { "768c08.g19", 0x80000, 0x9633db8b, 3 | BRF_GRA }, // 4 + + { "768c04.j5", 0x80000, 0x2960680e, 4 | BRF_GRA }, // 5 Bank #1 Tiles + { "768c05.j6", 0x80000, 0x65a2f227, 4 | BRF_GRA }, // 6 + + { "768c07.e17", 0x80000, 0x01f9889c, 5 | BRF_SND }, // 7 K007232 Samples + + { "768c13.j21", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 8 Color Proms + { "768c14.j22", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 9 + { "768c11.i4", 0x00100, 0xf5de80cb, 6 | BRF_GRA }, // 10 + { "768c10.i3", 0x00100, 0xb32071b7, 6 | BRF_GRA }, // 11 + + { "768b12.d20", 0x00100, 0x362544b8, 0 | BRF_GRA | BRF_OPT }, // 12 Priority Prom +}; + +STD_ROM_PICK(hcastljo) +STD_ROM_FN(hcastljo) + +struct BurnDriver BurnDrvHcastljo = { + "hcastljo", "hcastle", NULL, NULL, "1988", + "Akuma-Jou Dracula (Japan ver. N)\0", NULL, "Konami", "Miscellaneous", + L"\u60AA\u9B54\u57CE \u30C9\u30E9\u30AD\u30E5\u30E9 (Japan ver. N)\0Akuma-Jou Dracula\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, hcastljoRomInfo, hcastljoRomName, NULL, NULL, HcastleInputInfo, HcastleDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_hexion.cpp b/src/burn/drivers/konami/d_hexion.cpp new file mode 100644 index 00000000..1d473a06 --- /dev/null +++ b/src/burn/drivers/konami/d_hexion.cpp @@ -0,0 +1,620 @@ +// FB Alpha Hexion driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "K051649.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *MemEnd; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvGfxROMExp; +static UINT8 *DrvSndROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvUnkRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *flipscreen; + +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static INT32 cpubank; +static INT32 bankctrl; +static INT32 rambank; +static INT32 pmcbank; +static INT32 gfxrom_select; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo HexionInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Hexion) + +static struct BurnDIPInfo HexionDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x4f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x13, 0x01, 0x70, 0x70, "Easiest" }, + {0x13, 0x01, 0x70, 0x60, "Very Easy" }, + {0x13, 0x01, 0x70, 0x50, "Easy" }, + {0x13, 0x01, 0x70, 0x40, "Medium" }, + {0x13, 0x01, 0x70, 0x30, "Medium Hard" }, + {0x13, 0x01, 0x70, 0x20, "Hard" }, + {0x13, 0x01, 0x70, 0x10, "Very Hard" }, + {0x13, 0x01, 0x70, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Hexion) + +static void bankswitch(INT32 data) +{ + cpubank = data & 0x0f; + + ZetMapArea(0x8000, 0x9fff, 0, DrvZ80ROM + (cpubank << 13)); + ZetMapArea(0x8000, 0x9fff, 2, DrvZ80ROM + (cpubank << 13)); +} + +void __fastcall hexion_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xdfff: + bankctrl = data; + return; + + case 0xf200: + MSM6295Command(0, data); + return; + + case 0xf480: + { + if (data & 0x40) { + memset (DrvVidRAM + ((DrvUnkRAM[0] & 1) << 13), DrvUnkRAM[1], 0x2000); + } + + pmcbank = data & 0x80; + + bankswitch(data); + } + return; + + case 0xf4c0: + *flipscreen = data & 0x20; + return; + + case 0xf500: + gfxrom_select = data; + return; + } + + if ((address & 0xe000) == 0xc000) { + if (bankctrl == 3 && address == 0xc000 && (data & 0xfe) == 0) { + rambank = data & 1; + return; + } + if (pmcbank) { + if (bankctrl == 0) { + DrvVidRAM[(rambank << 13) + (address & 0x1fff)] = data; + return; + } + if (bankctrl == 2 && address < 0xc800) { + DrvUnkRAM[address & 0x7ff] = data; + return; + } + } + return; + } + + if ((address & 0xff80) == 0xe800) { + K051649WaveformWrite(address & 0x7f, data); + return; + } + + if ((address & 0xfff0) == 0xe880) { + if (address <= 0xe889) { + K051649FrequencyWrite(address & 0x0f, data); + return; + } + + if (address == 0xe88f) { + K051649KeyonoffWrite(data); + return; + } + + if (address >= 0xe88a) { + K051649VolumeWrite(address - 0xe88a, data); + return; + } + + return; + } +} + +UINT8 __fastcall hexion_read(UINT16 address) +{ + switch (address) + { + case 0xf400: + return DrvDips[0]; + + case 0xf401: + return DrvDips[1]; + + case 0xf402: + return DrvInputs[0]; + + case 0xf403: + return DrvInputs[1]; + + case 0xf440: + return DrvDips[2]; + + case 0xf441: + return DrvInputs[2] & 0xf7; + + case 0xf540: + return 0; // watchdog + } + + if ((address & 0xe000) == 0xc000) { + if (gfxrom_select && address < 0xd000) + return DrvGfxROM[((gfxrom_select & 0x7f) << 12) + (address & 0xfff)]; + + if (bankctrl == 0) + return DrvVidRAM[(rambank << 13) + (address & 0x1fff)]; + + if (bankctrl == 2 && address < 0xd800) + return DrvUnkRAM[address & 0x7ff]; + + return 0; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + bankswitch(4); + ZetClose(); + + K051649Reset(); + + cpubank = 0; + bankctrl = 0; + rambank = 0; + pmcbank = 0; + gfxrom_select = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM = Next; Next += 0x080000; + DrvGfxROMExp = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvColPROM = Next; Next += 0x000300; + + DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + Palette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + AllRam = Next; + + DrvUnkRAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x006000; + DrvZ80RAM = Next; Next += 0x002000; + + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000000, 0x000001, 0x000002, 0x000003 }; + INT32 XOffs[8] = { 0x200000, 0x200004, 0x000000, 0x000004, 0x200008, 0x20000c, 0x000008, 0x00000c }; + INT32 YOffs[8] = { 0x000000, 0x000010, 0x000020, 0x000030, 0x000040, 0x000050, 0x000060, 0x000070 }; + + UINT8 *tmp = (UINT8*)malloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x80000); + + GfxDecode(0x4000, 4, 8, 8, Plane, XOffs, YOffs, 0x080, tmp, DrvGfxROMExp); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) + { + INT32 bit0,bit1,bit2,bit3,r,g,b; + + bit0 = (DrvColPROM[i + 0x000] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x000] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x000] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x000] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 0x100] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x100] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x100] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x100] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 0x200] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x200] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x200] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x200] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM, 1, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x40000, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 3, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x000, 4, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x100, 5, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x200, 6, 1)) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xa000, 0xbfff, 0, DrvZ80RAM); + ZetMapArea(0xa000, 0xbfff, 1, DrvZ80RAM); + ZetMapArea(0xa000, 0xbfff, 2, DrvZ80RAM); + ZetSetWriteHandler(hexion_write); + ZetSetReadHandler(hexion_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132, 25.0, 0); + + K051649Init(1500000, 1.00); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + + ZetExit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_layer(INT32 offset, INT32 transparent, INT32 pos) +{ + UINT8 *vram = DrvVidRAM + offset; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + INT32 code = vram[0] | ((vram[1] & 0x3f) << 8); + INT32 color = vram[2] & 0x0f; + vram += 4; + + if (*flipscreen) { + sx ^= 0x1f8; + sy ^= 0x0f8; + + if (transparent) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx-pos, sy+pos, color, 4, 0, 0, DrvGfxROMExp); + } else { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx-pos, sy+pos, color, 4, 0, DrvGfxROMExp); + } + + // wrap + if (pos == 0) continue; + if (sx == 0) Render8x8Tile_Clip(pTransDraw, code, sx + 508, sy, color, 4, 0, DrvGfxROMExp); + if (sy == 252) Render8x8Tile_Clip(pTransDraw, code, sx, sy - 256, color, 4, 0, DrvGfxROMExp); + } else { + if (transparent) { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx+pos, sy-pos, color, 4, 0, 0, DrvGfxROMExp); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx+pos, sy-pos, color, 4, 0, DrvGfxROMExp); + } + + // wrap + if (pos == 0) continue; + if (sy == 0) Render8x8Tile_Clip(pTransDraw, code, sx, sy + 252, color, 4, 0, DrvGfxROMExp); + if (sx == 504) Render8x8Tile_Clip(pTransDraw, code, sx - 508, sy, color, 4, 0, DrvGfxROMExp); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x100; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + draw_layer(0x2000, 0, 4); + draw_layer(0x0000, 1, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + } + + ZetNewFrame(); + + INT32 nCyclesTotal[1] = { 6000000 / 60 }; + INT32 nCyclesDone[1] = { 0 }; + + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = ZetRun(nCyclesSegment); + if (i == (nInterleave / 3)) ZetNmi(); + if (i == ((nInterleave / 3) * 2)) ZetNmi(); + if (i == nInterleave - 1) ZetRaiseIrq(0); + nCyclesDone[0] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + MSM6295Render(0, pSoundBuf, nSegmentLength); + K051649Update(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + MSM6295Render(0, pSoundBuf, nSegmentLength); + K051649Update(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029705; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + MSM6295Scan(0, nAction); + K051649Scan(nAction, pnMin); + + SCAN_VAR(cpubank); + SCAN_VAR(bankctrl); + SCAN_VAR(rambank); + SCAN_VAR(pmcbank); + SCAN_VAR(gfxrom_select); + } + + ZetOpen(0); + bankswitch(cpubank); + ZetClose(); + + return 0; +} + + +// Hexion (Japan ver. JAB) + +static struct BurnRomInfo hexionRomDesc[] = { + { "122jab01.bin", 0x20000, 0xeabc6dd1, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + + { "122a07.bin", 0x40000, 0x22ae55e3, 2 | BRF_GRA }, // 1 Tiles + { "122a06.bin", 0x40000, 0x438f4388, 2 | BRF_GRA }, // 2 + + { "122a05.bin", 0x40000, 0xbcc831bf, 3 | BRF_SND }, // 3 M6296 Samples + + { "122a04.10b", 0x00100, 0x506eb8c6, 4 | BRF_GRA }, // 4 Color PROMs + { "122a03.11b", 0x00100, 0x590c4f64, 4 | BRF_GRA }, // 5 + { "122a02.13b", 0x00100, 0x5734305c, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(hexion) +STD_ROM_FN(hexion) + +struct BurnDriver BurnDrvHexion = { + "hexion", NULL, NULL, NULL, "1992", + "Hexion (Japan ver. JAB)\0", NULL, "Konami", "GX122", + L"Hexion\0\u30D8\u30AF\u30B7\u30AA\u30F3 (Japan ver. JAB)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_PUZZLE, 0, + NULL, hexionRomInfo, hexionRomName, NULL, NULL, HexionInputInfo, HexionDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 512, 256, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_mainevt.cpp b/src/burn/drivers/konami/d_mainevt.cpp new file mode 100644 index 00000000..3bccbabc --- /dev/null +++ b/src/burn/drivers/konami/d_mainevt.cpp @@ -0,0 +1,1251 @@ +// FB Alpha The Main Event / Devastators driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "hd6309_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "UPD7759.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *DrvHD6309ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvHD6309RAM; +static UINT8 *DrvZ80RAM; +static UINT8 *soundlatch; +static UINT8 *irq_enable; +static UINT8 *nmi_enable; + +static UINT8 *nDrvBank; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[5]; +static UINT8 DrvReset; + +static INT32 nGame; + +static struct BurnInputInfo MainevtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 5, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 4, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy1 + 3, "p4 coin" }, + {"P4 Up", BIT_DIGITAL, DrvJoy5 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy5 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy5 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy5 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy5 + 5, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy5 + 4, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy1 + 5, "service2" }, + {"Service 3", BIT_DIGITAL, DrvJoy1 + 6, "service3" }, + {"Service 4", BIT_DIGITAL, DrvJoy1 + 7, "service4" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Mainevt) + +static struct BurnInputInfo Mainevt2pInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy1 + 5, "service2" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Mainevt2p) + +static struct BurnInputInfo DevstorsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Devstors) + +static struct BurnDIPInfo MainevtDIPList[]= +{ + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0x57, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x21, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x21, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x21, 0x01, 0x0f, 0x00, "4 Coins 5 Credits" }, + {0x21, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x21, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x21, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x21, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x21, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus Energy" }, + {0x22, 0x01, 0x18, 0x00, "60" }, + {0x22, 0x01, 0x18, 0x08, "70" }, + {0x22, 0x01, 0x18, 0x10, "80" }, + {0x22, 0x01, 0x18, 0x18, "90" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x60, 0x60, "Easy" }, + {0x22, 0x01, 0x60, 0x40, "Normal" }, + {0x22, 0x01, 0x60, 0x20, "Hard" }, + {0x22, 0x01, 0x60, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x23, 0x01, 0x04, 0x04, "Off" }, + {0x23, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Mainevt) + +static struct BurnDIPInfo Mainevt2pDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x57, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x00, "4 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x00, "4 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus Energy" }, + {0x16, 0x01, 0x18, 0x00, "60" }, + {0x16, 0x01, 0x18, 0x08, "70" }, + {0x16, 0x01, 0x18, 0x10, "80" }, + {0x16, 0x01, 0x18, 0x18, "90" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x60, 0x60, "Easy" }, + {0x16, 0x01, 0x60, 0x40, "Normal" }, + {0x16, 0x01, 0x60, 0x20, "Hard" }, + {0x16, 0x01, 0x60, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x04, 0x04, "Off" }, + {0x17, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Mainevt2p) + +static struct BurnDIPInfo DevstorsDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x5e, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "150 and every 200" }, + {0x13, 0x01, 0x18, 0x10, "150 and every 250" }, + {0x13, 0x01, 0x18, 0x08, "150 Only" }, + {0x13, 0x01, 0x18, 0x00, "200 Only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Devstors) + +static struct BurnDIPInfo Devstors2DIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x52, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "150 and every 200" }, + {0x13, 0x01, 0x18, 0x10, "150 and every 250" }, + {0x13, 0x01, 0x18, 0x08, "150 Only" }, + {0x13, 0x01, 0x18, 0x00, "200 Only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Devstors2) + +static void bankswitch(INT32 data) +{ + nDrvBank[0] = data & 3; + + INT32 nBank = 0x10000 + nDrvBank[0] * 0x2000; + + HD6309MapMemory(DrvHD6309ROM + nBank, 0x6000, 0x7fff, HD6309_ROM); + + K052109RMRDLine = data & 0x40; +} + +UINT8 mainevt_main_read(UINT16 address) +{ + switch (address) + { + case 0x1f94: + return DrvInputs[0]; + + case 0x1f95: + return DrvInputs[1]; + + case 0x1f96: + return DrvInputs[2]; + + case 0x1f97: + return DrvDips[0]; + + case 0x1f98: + return DrvDips[2]; + + case 0x1f99: + return DrvInputs[3]; + + case 0x1f9a: + return DrvInputs[4]; + + case 0x1f9b: + return DrvDips[1]; + } + + if ((address & 0xffe0) == 0x1fa0 && nGame) { + return K051733Read(address); + } + + if ((address & 0xc000) == 0x0000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +void mainevt_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1f80: + bankswitch(data); + return; + + case 0x1f84: + *soundlatch = data; + return; + + case 0x1f88: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x1f90: + return; + + case 0x1fb2: + *nmi_enable = data; + return; + } + + if ((address & 0xffe0) == 0x1fa0 && nGame) { + K051733Write(address, data); + return; + } + + if ((address & 0xc000) == 0x0000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +static void soundbankswitch(INT32 data) +{ + INT32 bank_A,bank_B,bank_C; + + nDrvBank[1] = data; + + bank_A = data & 3; + bank_B = (data >> 2) & 3; + bank_C = 0x20000 + ((data >> 4) & 0x03) * 0x20000; + + k007232_set_bank(0, bank_A, bank_B ); + + memcpy (DrvSndROM1, DrvSndROM1 + bank_C, 0x20000); +} + +void __fastcall mainevt_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + UPD7759PortWrite(0, data); + return; + + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xe000: + UPD7759ResetWrite(0, data & 2); + UPD7759StartWrite(0, data & 1); + + *irq_enable = data & 4; + return; + + case 0xf000: + soundbankswitch(data); + return; + } + + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } +} + +UINT8 __fastcall mainevt_sound_read(UINT16 address) +{ + switch (address) + { + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc000: + case 0xc001: + return BurnYM2151ReadStatus(); + + case 0xd000: + return UPD7759BusyRead(0); + + } + + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(0, address & 0x0f); + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32 , INT32 *code, INT32 *color, INT32 *flipx, INT32 *priority) +{ + *flipx = *color & 0x02; + + if (layer == 2) *priority = (*color >> 5) & 1; + + *code |= ((*color & 0x01) << 8) | ((*color & 0x1c) << 7); + *color = ((layer & 2) << 1) + ((layer & 1) << 2) + ((*color & 0xc0) >> 6); +} + +static void DvK052109Callback(INT32 layer, INT32, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x01) << 8) | ((*color & 0x3c) << 7); + *color = ((layer & 2) << 1) + ((*color & 0xc0) >> 6); +} + +static void K051960Callback(INT32 *, INT32 *color, INT32 *priority, INT32 *) +{ + if (*color & 0x20) *priority = 0; + else if (*color & 0x40) *priority = 1; + else *priority = 2; + + *color = 0x0c + (*color & 0x03); +} + +static void DvK051960Callback(INT32 *, INT32 *color, INT32 *, INT32 *) +{ + *color = 0x08 + (*color & 0x07); +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + HD6309Open(0); + HD6309Reset(); + HD6309Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + UPD7759Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvHD6309ROM = Next; Next += 0x020000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x080000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM0 = Next; Next += 0x080000; + DrvSndROM1 = Next; Next += 0x0a0000; + + DrvPalette = (UINT32*)Next; Next += 0x100 * sizeof(UINT32); + + AllRam = Next; + + DrvHD6309RAM = Next; Next += 0x002000; + DrvZ80RAM = Next; Next += 0x000400; + + soundlatch = Next; Next += 0x000001; + + irq_enable = Next; Next += 0x000001; + nmi_enable = Next; Next += 0x000001; + + nDrvBank = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode(INT32 gfxlen0) +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, gfxlen0); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(gfxlen0/0x20, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit(INT32 type) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + nGame = type; + + INT32 gfx0_offset = 0x10000 << nGame; + + { + if (BurnLoadRom(DrvHD6309ROM + 0x010000, 0, 1)) return 1; + memcpy (DrvHD6309ROM + 0x08000, DrvHD6309ROM + 0x18000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + gfx0_offset + 0, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + gfx0_offset + 1, 5, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 9, 1)) return 1; + memcpy (DrvSndROM1, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(gfx0_offset * 2); + } + + HD6309Init(1); + HD6309Open(0); + HD6309MapMemory(DrvHD6309RAM, 0x4000, 0x5fff, HD6309_RAM); + HD6309MapMemory(DrvHD6309ROM + 0x10000, 0x6000, 0x7fff, HD6309_ROM); + HD6309MapMemory(DrvHD6309ROM + 0x08000, 0x8000, 0xffff, HD6309_ROM); + HD6309SetWriteByteHandler(mainevt_main_write); + HD6309SetReadByteHandler(mainevt_main_read); + HD6309Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x83ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x83ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x83ff, 2, DrvZ80RAM); + ZetSetWriteHandler(mainevt_sound_write); + ZetSetReadHandler(mainevt_sound_read); + ZetMemEnd(); + ZetClose(); + + K052109Init(DrvGfxROM0, (gfx0_offset * 2) - 1); + K052109SetCallback(nGame ? DvK052109Callback : K052109Callback); + K052109AdjustScroll(nGame ? 0 : 8, 0); + + K051960Init(DrvGfxROM1, 0xfffff); + K051960SetCallback(nGame ? DvK051960Callback : K051960Callback); + K051960SetSpriteOffset(nGame ? 0 : 8, 0); + + K007232Init(0, 3579545, DrvSndROM0, 0x80000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + BurnYM2151Init(3579545, 75.0); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSndROM1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + HD6309Exit(); + ZetExit(); + + K007232Exit(); + UPD7759Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvHD6309RAM + 0x1e00, DrvPalette, 0x200); + } + + K052109UpdateScroll(); + + if (nGame) + { + K052109RenderLayer(1, 1, DrvGfxROMExp0); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + + K051960SpritesRender(DrvGfxROMExp1, 0); + + K052109RenderLayer(0, 0, DrvGfxROMExp0); + } + else + { + if (nBurnLayer & 1) K052109RenderLayer(1, 1, DrvGfxROMExp0); + + if (nBurnLayer & 2) K052109RenderLayer(2 | 0x10, 0, DrvGfxROMExp0); + + if (nSpriteEnable & 2) K051960SpritesRender(DrvGfxROMExp1, 1); + + if (nBurnLayer & 4) K052109RenderLayer(2 | 0x00, 0, DrvGfxROMExp0); + + if (nSpriteEnable & 4) K051960SpritesRender(DrvGfxROMExp1, 0); // makes sense... + + if (nSpriteEnable & 1) K051960SpritesRender(DrvGfxROMExp1, 2); + + if (nBurnLayer & 8) K052109RenderLayer(0, 0, DrvGfxROMExp0); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[3] & 0x0c) == 0) DrvInputs[3] |= 0x0c; + if ((DrvInputs[3] & 0x03) == 0) DrvInputs[3] |= 0x03; + if ((DrvInputs[4] & 0x0c) == 0) DrvInputs[4] |= 0x0c; + if ((DrvInputs[4] & 0x03) == 0) DrvInputs[4] |= 0x03; + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = nBurnSoundLen; + INT32 nCyclesTotal[2] = { 12000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + HD6309Open(0); + + INT32 nCyclesSoundIrq = nInterleave / (8 >> nGame); + INT32 nCyclesSoundIrqTrigger = nCyclesSoundIrq; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += HD6309Run(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (i == nCyclesSoundIrqTrigger-1) { + nCyclesSoundIrqTrigger+=nCyclesSoundIrq; + if (*irq_enable) { + if (nGame) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + else ZetNmi(); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (nGame) { + if (nmi_enable[0]) HD6309SetIRQ(0x20, HD6309_IRQSTATUS_AUTO); // nmi + } else { + if (K052109_irq_enabled) HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_AUTO); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + HD6309Close(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + return 1; // hd6309 isn't hooked up... + + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + HD6309Scan(nAction); + ZetScan(nAction); + + UPD7759Scan(0, nAction, pnMin); + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + HD6309Open(0); + bankswitch(nDrvBank[0]); + HD6309Close(); + + soundbankswitch(nDrvBank[1]); + } + + return 0; +} + + +// The Main Event (4 Players ver. Y) + +static struct BurnRomInfo mainevtRomDesc[] = { + { "799c02.k11", 0x10000, 0xe2e7dbd5, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "799c01.f7", 0x08000, 0x447c4c5c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "799c06.f22", 0x08000, 0xf839cb58, 3 | BRF_GRA }, // 2 K052109 Tiles + { "799c07.h22", 0x08000, 0x176df538, 3 | BRF_GRA }, // 3 + { "799c08.j22", 0x08000, 0xd01e0078, 3 | BRF_GRA }, // 4 + { "799c09.k22", 0x08000, 0x9baec75e, 3 | BRF_GRA }, // 5 + + { "799b04.h4", 0x80000, 0x323e0c2b, 4 | BRF_GRA }, // 6 K051960 Tiles + { "799b05.k4", 0x80000, 0x571c5831, 4 | BRF_GRA }, // 7 + + { "799b03.d4", 0x80000, 0xf1cfd342, 5 | BRF_SND }, // 8 K007232 Samples + + { "799b06.c22", 0x80000, 0x2c8c47d7, 6 | BRF_GRA }, // 9 UPD7759 + + { "63s141n.k14", 0x00100, 0x61f6c8d1, 7 | BRF_OPT }, // 10 Priority Prom +}; + +STD_ROM_PICK(mainevt) +STD_ROM_FN(mainevt) + +static INT32 mainevtInit() +{ + return DrvInit(0); +} + + +struct BurnDriver BurnDrvMainevt = { + "mainevt", NULL, NULL, NULL, "1988", + "The Main Event (4 Players ver. Y)\0", NULL, "Konami", "GX799", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, mainevtRomInfo, mainevtRomName, NULL, NULL, MainevtInputInfo, MainevtDIPInfo, + mainevtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 288, 224, 4, 3 +}; + + +// The Main Event (4 Players ver. F) + +static struct BurnRomInfo mainevtoRomDesc[] = { + { "799_02.k11", 0x10000, 0xc143596b, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "799c01.f7", 0x08000, 0x447c4c5c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "799c06.f22", 0x08000, 0xf839cb58, 3 | BRF_GRA }, // 2 K052109 Tiles + { "799c07.h22", 0x08000, 0x176df538, 3 | BRF_GRA }, // 3 + { "799c08.j22", 0x08000, 0xd01e0078, 3 | BRF_GRA }, // 4 + { "799c09.k22", 0x08000, 0x9baec75e, 3 | BRF_GRA }, // 5 + + { "799b04.h4", 0x80000, 0x323e0c2b, 4 | BRF_GRA }, // 6 K051960 Tiles + { "799b05.k4", 0x80000, 0x571c5831, 4 | BRF_GRA }, // 7 + + { "799b03.d4", 0x80000, 0xf1cfd342, 5 | BRF_SND }, // 8 K007232 Samples + + { "799b06.c22", 0x80000, 0x2c8c47d7, 6 | BRF_GRA }, // 9 UPD7759 + + { "63s141n.k14", 0x00100, 0x61f6c8d1, 7 | BRF_OPT }, // 10 Priority Prom +}; + +STD_ROM_PICK(mainevto) +STD_ROM_FN(mainevto) + +struct BurnDriver BurnDrvMainevto = { + "mainevto", "mainevt", NULL, NULL, "1988", + "The Main Event (4 Players ver. F)\0", NULL, "Konami", "GX799", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, mainevtoRomInfo, mainevtoRomName, NULL, NULL, MainevtInputInfo, MainevtDIPInfo, + mainevtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 288, 224, 4, 3 +}; + + +// The Main Event (2 Players ver. X) + +static struct BurnRomInfo mainevt2pRomDesc[] = { + { "799x02.k11", 0x10000, 0x42cfc650, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "799c01.f7", 0x08000, 0x447c4c5c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "799c06.f22", 0x08000, 0xf839cb58, 3 | BRF_GRA }, // 2 K052109 Tiles + { "799c07.h22", 0x08000, 0x176df538, 3 | BRF_GRA }, // 3 + { "799c08.j22", 0x08000, 0xd01e0078, 3 | BRF_GRA }, // 4 + { "799c09.k22", 0x08000, 0x9baec75e, 3 | BRF_GRA }, // 5 + + { "799b04.h4", 0x80000, 0x323e0c2b, 4 | BRF_GRA }, // 6 K051960 Tiles + { "799b05.k4", 0x80000, 0x571c5831, 4 | BRF_GRA }, // 7 + + { "799b03.d4", 0x80000, 0xf1cfd342, 5 | BRF_SND }, // 8 K007232 Samples + + { "799b06.c22", 0x80000, 0x2c8c47d7, 6 | BRF_GRA }, // 9 UPD7759 + + { "63s141n.k14", 0x00100, 0x61f6c8d1, 7 | BRF_OPT }, // 10 Priority Prom +}; + +STD_ROM_PICK(mainevt2p) +STD_ROM_FN(mainevt2p) + +struct BurnDriver BurnDrvMainevt2p = { + "mainevt2p", "mainevt", NULL, NULL, "1988", + "The Main Event (2 Players ver. X)\0", NULL, "Konami", "GX799", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, mainevt2pRomInfo, mainevt2pRomName, NULL, NULL, Mainevt2pInputInfo, Mainevt2pDIPInfo, + mainevtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 288, 224, 4, 3 +}; + + +// Ring no Ohja (Japan 2 Players ver. N) + +static struct BurnRomInfo ringohjaRomDesc[] = { + { "799n02.k11", 0x10000, 0xf9305dd0, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "799c01.f7", 0x08000, 0x447c4c5c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "799c06.f22", 0x08000, 0xf839cb58, 3 | BRF_GRA }, // 2 K052109 Tiles + { "799c07.h22", 0x08000, 0x176df538, 3 | BRF_GRA }, // 3 + { "799c08.j22", 0x08000, 0xd01e0078, 3 | BRF_GRA }, // 4 + { "799c09.k22", 0x08000, 0x9baec75e, 3 | BRF_GRA }, // 5 + + { "799b04.h4", 0x80000, 0x323e0c2b, 4 | BRF_GRA }, // 6 K051960 Tiles + { "799b05.k4", 0x80000, 0x571c5831, 4 | BRF_GRA }, // 7 + + { "799b03.d4", 0x80000, 0xf1cfd342, 5 | BRF_SND }, // 8 K007232 Samples + + { "799b06.c22", 0x80000, 0x2c8c47d7, 6 | BRF_GRA }, // 9 UPD7759 + + { "63s141n.k14", 0x00100, 0x61f6c8d1, 7 | BRF_OPT }, // 10 Priority Prom +}; + +STD_ROM_PICK(ringohja) +STD_ROM_FN(ringohja) + +struct BurnDriver BurnDrvRingohja = { + "ringohja", "mainevt", NULL, NULL, "1988", + "Ring no Ohja (Japan 2 Players ver. N)\0", NULL, "Konami", "GX799", + L"\u30EA\u30F3\u30B0\u306E \u738B\u8005 (Japan 2 Players ver. N)\0Ring no Ohja\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, ringohjaRomInfo, ringohjaRomName, NULL, NULL, Mainevt2pInputInfo, Mainevt2pDIPInfo, + mainevtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 288, 224, 4, 3 +}; + + +// Devastators (ver. Z) + +static struct BurnRomInfo devstorsRomDesc[] = { + { "890z02.k11", 0x10000, 0xebeb306f, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "890k01.f7", 0x08000, 0xd44b3eb0, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "890f06.f22", 0x10000, 0x26592155, 3 | BRF_GRA }, // 2 K052109 Tiles + { "890f07.h22", 0x10000, 0x6c74fa2e, 3 | BRF_GRA }, // 3 + { "890f08.j22", 0x10000, 0x29e12e80, 3 | BRF_GRA }, // 4 + { "890f09.k22", 0x10000, 0x67ca40d5, 3 | BRF_GRA }, // 5 + + { "890f04.h4", 0x80000, 0xf16cd1fa, 4 | BRF_GRA }, // 6 K051960 Tiles + { "890f05.k4", 0x80000, 0xda37db05, 4 | BRF_GRA }, // 7 + + { "890f03.d4", 0x80000, 0x19065031, 6 | BRF_GRA }, // 8 K007232 Samples + + { "63s141n.k14", 0x00100, 0xd3620106, 5 | BRF_OPT }, // 9 Priority Prom +}; + +STD_ROM_PICK(devstors) +STD_ROM_FN(devstors) + +static INT32 devstorsInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvDevstors = { + "devstors", NULL, NULL, NULL, "1988", + "Devastators (ver. Z)\0", NULL, "Konami", "GX890", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, devstorsRomInfo, devstorsRomName, NULL, NULL, DevstorsInputInfo, DevstorsDIPInfo, + devstorsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 224, 304, 3, 4 +}; + + +// Devastators (ver. X) + +static struct BurnRomInfo devstors2RomDesc[] = { + { "890x02.k11", 0x10000, 0xe58ebb35, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "890k01.f7", 0x08000, 0xd44b3eb0, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "890f06.f22", 0x10000, 0x26592155, 3 | BRF_GRA }, // 2 K052109 Tiles + { "890f07.h22", 0x10000, 0x6c74fa2e, 3 | BRF_GRA }, // 3 + { "890f08.j22", 0x10000, 0x29e12e80, 3 | BRF_GRA }, // 4 + { "890f09.k22", 0x10000, 0x67ca40d5, 3 | BRF_GRA }, // 5 + + { "890f04.h4", 0x80000, 0xf16cd1fa, 4 | BRF_GRA }, // 6 K051960 Tiles + { "890f05.k4", 0x80000, 0xda37db05, 4 | BRF_GRA }, // 7 + + { "890f03.d4", 0x80000, 0x19065031, 6 | BRF_GRA }, // 8 K007232 Samples + + { "63s141n.k14", 0x00100, 0xd3620106, 5 | BRF_OPT }, // 9 Priority Prom +}; + +STD_ROM_PICK(devstors2) +STD_ROM_FN(devstors2) + +struct BurnDriver BurnDrvDevstors2 = { + "devstors2", "devstors", NULL, NULL, "1988", + "Devastators (ver. X)\0", NULL, "Konami", "GX890", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, devstors2RomInfo, devstors2RomName, NULL, NULL, DevstorsInputInfo, Devstors2DIPInfo, + devstorsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 224, 304, 3, 4 +}; + + +// Devastators (ver. V) + +static struct BurnRomInfo devstors3RomDesc[] = { + { "890k02.k11", 0x10000, 0x52f4ccdd, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "890k01.f7", 0x08000, 0xd44b3eb0, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "890f06.f22", 0x10000, 0x26592155, 3 | BRF_GRA }, // 2 K052109 Tiles + { "890f07.h22", 0x10000, 0x6c74fa2e, 3 | BRF_GRA }, // 3 + { "890f08.j22", 0x10000, 0x29e12e80, 3 | BRF_GRA }, // 4 + { "890f09.k22", 0x10000, 0x67ca40d5, 3 | BRF_GRA }, // 5 + + { "890f04.h4", 0x80000, 0xf16cd1fa, 4 | BRF_GRA }, // 6 K051960 Tiles + { "890f05.k4", 0x80000, 0xda37db05, 4 | BRF_GRA }, // 7 + + { "890f03.d4", 0x80000, 0x19065031, 6 | BRF_GRA }, // 8 K007232 Samples + + { "63s141n.k14", 0x00100, 0xd3620106, 5 | BRF_OPT }, // 9 Priority Prom +}; + +STD_ROM_PICK(devstors3) +STD_ROM_FN(devstors3) + +struct BurnDriver BurnDrvDevstors3 = { + "devstors3", "devstors", NULL, NULL, "1988", + "Devastators (ver. V)\0", NULL, "Konami", "GX890", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, devstors3RomInfo, devstors3RomName, NULL, NULL, DevstorsInputInfo, DevstorsDIPInfo, + devstorsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 224, 304, 3, 4 +}; + + +// Garuka (Japan ver. W) + +static struct BurnRomInfo garukaRomDesc[] = { + { "890w02.k11", 0x10000, 0xb2f6f538, 1 | BRF_PRG | BRF_ESS }, // 0 HD6309 Code + + { "890k01.f7", 0x08000, 0xd44b3eb0, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "890f06.f22", 0x10000, 0x26592155, 3 | BRF_GRA }, // 2 K052109 Tiles + { "890f07.h22", 0x10000, 0x6c74fa2e, 3 | BRF_GRA }, // 3 + { "890f08.j22", 0x10000, 0x29e12e80, 3 | BRF_GRA }, // 4 + { "890f09.k22", 0x10000, 0x67ca40d5, 3 | BRF_GRA }, // 5 + + { "890f04.h4", 0x80000, 0xf16cd1fa, 4 | BRF_GRA }, // 6 K051960 Tiles + { "890f05.k4", 0x80000, 0xda37db05, 4 | BRF_GRA }, // 7 + + { "890f03.d4", 0x80000, 0x19065031, 6 | BRF_GRA }, // 8 K007232 Samples + + { "63s141n.k14", 0x00100, 0xd3620106, 5 | BRF_OPT }, // 9 Priority Prom +}; + +STD_ROM_PICK(garuka) +STD_ROM_FN(garuka) + +struct BurnDriver BurnDrvGaruka = { + "garuka", "devstors", NULL, NULL, "1988", + "Garuka (Japan ver. W)\0", NULL, "Konami", "GX890", + L"\u9913\u6D41\u798D (Japan ver. W)\0Garuka\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, garukaRomInfo, garukaRomName, NULL, NULL, DevstorsInputInfo, Devstors2DIPInfo, + devstorsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 224, 304, 3, 4 +}; diff --git a/src/burn/drivers/konami/d_parodius.cpp b/src/burn/drivers/konami/d_parodius.cpp new file mode 100644 index 00000000..cc3a8ec4 --- /dev/null +++ b/src/burn/drivers/konami/d_parodius.cpp @@ -0,0 +1,768 @@ +// FB Alpha Parodius Da! driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "k053260.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *nDrvRomBank; + +static INT32 layer_colorbase[3]; +static INT32 sprite_colorbase; +static INT32 layerpri[3]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static INT32 nCyclesDone[2]; + +static struct BurnInputInfo ParodiusInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, DrvJoy3 + 1, "diag" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Parodius) + +static struct BurnDIPInfo ParodiusDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x5a, NULL }, + {0x17, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x03, "2" }, + {0x16, 0x01, 0x03, 0x02, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "7" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x16, 0x01, 0x04, 0x00, "Upright" }, +// {0x16, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x18, 0x18, "20000 80000" }, + {0x16, 0x01, 0x18, 0x10, "30000 100000" }, + {0x16, 0x01, 0x18, 0x08, "20000" }, + {0x16, 0x01, 0x18, 0x00, "70000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x60, 0x60, "Easy" }, + {0x16, 0x01, 0x60, 0x40, "Normal" }, + {0x16, 0x01, 0x60, 0x20, "Difficult" }, + {0x16, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x17, 0x01, 0x10, 0x10, "Off" }, +// {0x17, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x17, 0x01, 0x20, 0x20, "Single" }, + {0x17, 0x01, 0x20, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Parodius) + +void parodius_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3fc0: + K052109RMRDLine = data & 0x08; + return; + + case 0x3fc4: + nDrvRomBank[1] = data; + return; + + case 0x3fc8: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x3fcc: + case 0x3fcd: + K053260Write(0, address & 1, data); + return; + } + + if ((address & 0xf800) == 0x0000) { + if (nDrvRomBank[1] & 1) { + DrvPalRAM[((nDrvRomBank[1] & 0x04) << 9) + address] = data; + } else { + DrvBankRAM[address] = data; + } + return; + } + + if ((address & 0xfff0) == 0x3fa0) { + K053244Write(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0x3fb0) { + K053251Write(address & 0x0f, data); + return; + } + + if ((address & 0xf800) == 0x2000) { + if (nDrvRomBank[1] & 0x02) { + K053245Write(0, address & 0x7ff, data); + return; + } + } + + if (address >= 0x2000 && address <= 0x5fff) { + K052109Write(address - 0x2000, data); + } +} + +UINT8 parodius_main_read(UINT16 address) +{ + switch (address) + { + case 0x3f8c: + return DrvInputs[0]; + + case 0x3f8d: + return DrvInputs[1]; + + case 0x3f8e: + return (DrvDips[2] & 0xf0) | (DrvInputs[2] & 0x0f); + + case 0x3f8f: + return DrvDips[0]; + + case 0x3f90: + return DrvDips[1]; + + case 0x3fc0: // watchdog + return 0; + + case 0x3fcc: + case 0x3fcd: + return K053260Read(0, (address & 1)+2); + } + + if ((address & 0xf800) == 0x0000) { + if (nDrvRomBank[1] & 1) { + return DrvPalRAM[((nDrvRomBank[1] & 0x04) << 9) + address]; + } else { + return DrvBankRAM[address]; + } + } + + if ((address & 0xfff0) == 0x3fa0) { + return K053244Read(0, address & 0x0f); + } + + if ((address & 0xf800) == 0x2000) { + if (nDrvRomBank[1] & 0x02) { + return K053245Read(0, address & 0x7ff); + } + } + + if (address >= 0x2000 && address <= 0x5fff) { + return K052109Read(address - 0x2000); + } + + return 0; +} + +void __fastcall parodius_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + BurnYM2151SelectRegister(data); + return; + + case 0xf801: + BurnYM2151WriteRegister(data); + return; + + case 0xfa00: + nCyclesDone[1] += ZetRun(100); + ZetNmi(); + return; + } + + if (address >= 0xfc00 && address <= 0xfc2f) { + K053260Write(0, address & 0x3f, data); + } +} + +UINT8 __fastcall parodius_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + return 0xff; + case 0xf801: + return BurnYM2151ReadStatus(); + } + + if (address >= 0xfc00 && address <= 0xfc2f) { + if ((address & 0x3e) == 0x00) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + + return K053260Read(0, address & 0x3f); + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *flags, INT32 *) +{ + *flags = (*color & 0x80) >> 7; + *code |= ((*color & 0x03) << 8) | ((*color & 0x10) << 6) | ((*color & 0x0c) << 9) | (bank << 13); + *color = layer_colorbase[layer] + ((*color & 0xe0) >> 5); +} + +static void K053245Callback(INT32 *code, INT32 *color, INT32 *priority) +{ + INT32 pri = 0x20 | ((*color & 0x60) >> 2); + if (pri <= layerpri[2]) *priority = 0; + else if (pri > layerpri[2] && pri <= layerpri[1]) *priority = 1; + else if (pri > layerpri[1] && pri <= layerpri[0]) *priority = 2; + else *priority = 3; + + *code &= 0x1fff; + *color = sprite_colorbase + (*color & 0x1f); +} + +static void parodius_set_lines(INT32 lines) +{ + nDrvRomBank[0] = lines; + + konamiMapMemory(DrvKonROM + 0x10000 + ((~lines & 0x0f) * 0x4000), 0x6000, 0x9fff, KON_ROM); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + K053260Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x050000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM = Next; Next += 0x080000; + + Palette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001800; + DrvPalRAM = Next; Next += 0x001000; + + DrvZ80RAM = Next; Next += 0x000800; + + nDrvRomBank = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x100000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x8000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + + K053245GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x100000); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x030000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x48000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 7, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x0800, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x9fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x0a000, 0xa000, 0xffff, KON_ROM); + konamiSetWriteHandler(parodius_main_write); + konamiSetReadHandler(parodius_main_read); + konamiSetlinesCallback(parodius_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(parodius_sound_write); + ZetSetReadHandler(parodius_sound_read); + ZetMemEnd(); + ZetClose(); + + K052109Init(DrvGfxROM0, 0xfffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvGfxROM1, 0xfffff, K053245Callback); + K053245SetSpriteOffset(0, -112, -16); + + BurnYM2151Init(3579545, 70.0); + + K053260Init(0, 3579545, DrvSndROM, 0x80000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + BurnYM2151Exit(); + K053260Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + K052109UpdateScroll(); + + INT32 bg_colorbase, layer[3]; + + bg_colorbase = K053251GetPaletteIndex(0); + sprite_colorbase = K053251GetPaletteIndex(1); + layer_colorbase[0] = K053251GetPaletteIndex(2); + layer_colorbase[1] = K053251GetPaletteIndex(4); + layer_colorbase[2] = K053251GetPaletteIndex(3); + + layerpri[0] = K053251GetPriority(2); + layerpri[1] = K053251GetPriority(4); + layerpri[2] = K053251GetPriority(3); + layer[0] = 0; + layer[1] = 1; + layer[2] = 2; + + sortlayers(layer,layerpri); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * bg_colorbase; + } + + if (nBurnLayer & 1) K052109RenderLayer(layer[0], 0, DrvGfxROMExp0); + if (nSpriteEnable & 4) K053245SpritesRender(0, DrvGfxROMExp1, 2); // right? + if (nSpriteEnable & 8) K053245SpritesRender(0, DrvGfxROMExp1, 3); + if (nBurnLayer & 2) K052109RenderLayer(layer[1], 0, DrvGfxROMExp0); + if (nSpriteEnable & 2) K053245SpritesRender(0, DrvGfxROMExp1, 1); + if (nBurnLayer & 4) K052109RenderLayer(layer[2], 0, DrvGfxROMExp0); + + if (nSpriteEnable & 1) K053245SpritesRender(0, DrvGfxROMExp1, 0); // used (back)? + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + konamiNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x06) == 0) DrvInputs[0] |= 0x06; + if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18; + if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06; + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + } + + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = konamiRun(nCyclesSegment); + nCyclesDone[0] += nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[1] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + + KonamiICScan(nAction); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + parodius_set_lines(nDrvRomBank[0]); + konamiClose(); + } + + return 0; +} + + +// Parodius DA! (World, set 1) + +static struct BurnRomInfo parodiusRomDesc[] = { + { "955l01.bin", 0x20000, 0x49a658eb, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "955l02.bin", 0x20000, 0x161d7322, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "955e03.bin", 0x10000, 0x940aa356, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "955d07.bin", 0x80000, 0x89473fec, 3 | BRF_GRA }, // 3 Background Tiles + { "955d08.bin", 0x80000, 0x43d5cda1, 3 | BRF_GRA }, // 4 + + { "955d05.bin", 0x80000, 0x7a1e55e0, 4 | BRF_GRA }, // 5 Sprites + { "955d06.bin", 0x80000, 0xf4252875, 4 | BRF_GRA }, // 6 + + { "955d04.bin", 0x80000, 0xe671491a, 5 | BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(parodius) +STD_ROM_FN(parodius) + +struct BurnDriver BurnDrvParodius = { + "parodius", NULL, NULL, NULL, "1990", + "Parodius DA! (World, set 1)\0", NULL, "Konami", "GX955", + L"Parodius \u30D1\u30ED\u30C7\u30A3\u30A6\u30B9\u3060\uFF01 \uFF0D\u795E\u8A71\u304B\u3089\u304A\u7B11\u3044\u3078\uFF0D (World, set 1)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, parodiusRomInfo, parodiusRomName, NULL, NULL, ParodiusInputInfo, ParodiusDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Parodius DA! (World, set 2) + +static struct BurnRomInfo parodiusaRomDesc[] = { + { "2.f5", 0x20000, 0x26a6410b, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "3.h5", 0x20000, 0x9410dbf2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "955e03.bin", 0x10000, 0x940aa356, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "955d07.bin", 0x80000, 0x89473fec, 3 | BRF_GRA }, // 3 Background Tiles + { "955d08.bin", 0x80000, 0x43d5cda1, 3 | BRF_GRA }, // 4 + + { "955d05.bin", 0x80000, 0x7a1e55e0, 4 | BRF_GRA }, // 5 Sprites + { "955d06.bin", 0x80000, 0xf4252875, 4 | BRF_GRA }, // 6 + + { "955d04.bin", 0x80000, 0xe671491a, 5 | BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(parodiusa) +STD_ROM_FN(parodiusa) + +struct BurnDriver BurnDrvParodiusa = { + "parodiusa", "parodius", NULL, NULL, "1990", + "Parodius DA! (World, set 2)\0", NULL, "Konami", "GX955", + L"Parodius \u30D1\u30ED\u30C7\u30A3\u30A6\u30B9\u3060\uFF01 \uFF0D\u795E\u8A71\u304B\u3089\u304A\u7B11\u3044\u3078\uFF0D (World, set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, parodiusaRomInfo, parodiusaRomName, NULL, NULL, ParodiusInputInfo, ParodiusDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Parodius DA! (Japan) + +static struct BurnRomInfo parodisjRomDesc[] = { + { "955e01.bin", 0x20000, 0x49baa334, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "955e02.bin", 0x20000, 0x14010d6f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "955e03.bin", 0x10000, 0x940aa356, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "955d07.bin", 0x80000, 0x89473fec, 3 | BRF_GRA }, // 3 Background Tiles + { "955d08.bin", 0x80000, 0x43d5cda1, 3 | BRF_GRA }, // 4 + + { "955d05.bin", 0x80000, 0x7a1e55e0, 4 | BRF_GRA }, // 5 Sprites + { "955d06.bin", 0x80000, 0xf4252875, 4 | BRF_GRA }, // 6 + + { "955d04.bin", 0x80000, 0xe671491a, 5 | BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(parodisj) +STD_ROM_FN(parodisj) + +struct BurnDriver BurnDrvParodisj = { + "parodiusj", "parodius", NULL, NULL, "1990", + "Parodius DA! (Japan)\0", NULL, "Konami", "GX955", + L"Parodius \u30D1\u30ED\u30C7\u30A3\u30A6\u30B9\u3060\uFF01 \uFF0D\u795E\u8A71\u304B\u3089\u304A\u7B11\u3044\u3078\uFF0D (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, parodisjRomInfo, parodisjRomName, NULL, NULL, ParodiusInputInfo, ParodiusDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_rollerg.cpp b/src/burn/drivers/konami/d_rollerg.cpp new file mode 100644 index 00000000..ce3d091f --- /dev/null +++ b/src/burn/drivers/konami/d_rollerg.cpp @@ -0,0 +1,642 @@ +// FB Alpha Roller Games driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "k053260.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT32 readzoomroms; +static UINT8 *nDrvBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo RollergInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 6, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 6, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 4, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Rollerg) + +static struct BurnDIPInfo RollergDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x56, NULL }, + {0x14, 0xff, 0xff, 0x0f, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "No Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "1" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x01, "3" }, + {0x13, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Energy" }, + {0x13, 0x01, 0x18, 0x00, "1/2 for Stage Winner" }, + {0x13, 0x01, 0x18, 0x08, "1/4 for Stage Winner" }, + {0x13, 0x01, 0x18, 0x10, "1/4 for Cycle Winner" }, + {0x13, 0x01, 0x18, 0x18, "None" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x01, 0x01, "Off" }, +// {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Rollerg) + +void rollerg_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0010: + readzoomroms = data & 0x04; + K051316WrapEnable(0, data & 0x20); + return; + + case 0x0020: + // watchdog + return; + + case 0x0030: + case 0x0031: + K053260Write(0, address & 1, data); + return; + + case 0x0040: + ZetSetVector(0xff); + // ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } + + if ((address & 0xfff0) == 0x0200) { + K051316WriteCtrl(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0x0300) { + K053244Write(0, address & 0x0f, data); + return; + } + + if ((address & 0xf800) == 0x0800) { + K051316Write(0, address & 0x7ff, data); + return; + } + + if ((address & 0xf800) == 0x1000) { + K053245Write(0, address & 0x7ff, data); + return; + } +} + +UINT8 rollerg_main_read(UINT16 address) +{ + switch (address) + { + case 0x0020: // watchdog + return 0; + + case 0x0030: + case 0x0031: + return K053260Read(0, (address & 1)+2); + + case 0x0050: + return DrvInputs[0]; + + case 0x0051: + return DrvInputs[1]; + + case 0x0052: + return (DrvInputs[2] & 0xf0) | (DrvDips[2] & 0x0f); + + case 0x0053: + return DrvDips[0]; + + case 0x0060: + return DrvDips[1]; + + case 0x0061: + return 0x7f; + } + + if ((address & 0xfff0) == 0x0300) { + return K053244Read(0, address & 0x0f); + } + + if ((address & 0xf800) == 0x0800) { + if (readzoomroms) + return K051316ReadRom(0, address & 0x7ff); + else + return K051316Read(0, address & 0x7ff); + } + + if ((address & 0xf800) == 0x1000) { + return K053245Read(0, address & 0x7ff); + } + + return 0; +} + +void __fastcall rollerg_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: + case 0xc001: + BurnYM3812Write(address & 1, data); + return; + + case 0xfc00: + ZetRun(100); + ZetNmi(); + return; + } + + if (address >= 0xa000 && address <= 0xa02f) { + K053260Write(0, address & 0x3f, data); + return; + } +} + +UINT8 __fastcall rollerg_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + case 0xc001: + return BurnYM3812Read(address & 1); + } + + if (address >= 0xa000 && address <= 0xa02f) { + // not sure... + if ((address & 0x3e) == 0x00) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + + return K053260Read(0, address & 0x3f); + } + + return 0; +} + +static void rollerg_set_lines(INT32 lines) +{ + nDrvBank[0] = lines; + + INT32 offs = 0x10000 + ((lines & 0x07) * 0x4000); + + konamiMapMemory(DrvKonROM + offs, 0x4000, 0x7fff, KON_ROM); +} + +static void K053245Callback(INT32 *, INT32 *color, INT32 *priority) +{ + *priority = *color & 0x10; + *color = 16 + (*color & 0x0f); +} + +static void K051316Callback(INT32 *code, INT32 *color, INT32 *flags) +{ + *flags = (*color & 0xc0) >> 6; + *code |= ((*color & 0x0f) << 8); + *color = ((*color & 0x30) >> 4); +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + K053260Reset(0); + BurnYM3812Reset(); + + KonamiICReset(); + + readzoomroms = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROMExp0 = Next; Next += 0x400000; + DrvGfxROMExp1 = Next; Next += 0x100000; + + DrvSndROM = Next; Next += 0x080000; + + Palette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvKonRAM = Next; Next += 0x001b00; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + nDrvBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x28000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 6, 1)) return 1; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x200000); + + K053245GfxDecode(DrvGfxROM0, DrvGfxROMExp0, 0x200000); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvPalRAM, 0x1800, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonRAM, 0x2000, 0x3aff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x4000, 0x4000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x8000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(rollerg_main_write); + konamiSetReadHandler(rollerg_main_read); + konamiSetlinesCallback(rollerg_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(rollerg_sound_write); + ZetSetReadHandler(rollerg_sound_read); + ZetMemEnd(); + ZetClose(); + + K053245Init(0, DrvGfxROM0, 0x1fffff, K053245Callback); + K053245SetSpriteOffset(0, -112, 17); + + K051316Init(0, DrvGfxROM1, DrvGfxROMExp1, 0x7ffff, K051316Callback, 4, 0); + K051316SetOffset(0, -90, -15); + + BurnYM3812Init(3579545, NULL, DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + K053260Init(0, 3579545, DrvSndROM, 0x80000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + BurnYM3812Exit(); + K053260Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x800 / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + K053245SpritesRender(0, DrvGfxROMExp0, 0x00); + K051316_zoom_draw(0, 1); + K053245SpritesRender(0, DrvGfxROMExp0, 0x10); + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + konamiNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18; + if ((DrvInputs[0] & 0x60) == 0) DrvInputs[0] |= 0x60; + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + if ((DrvInputs[1] & 0x60) == 0) DrvInputs[1] |= 0x60; + } + + INT32 nInterleave = nBurnSoundLen; + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = konamiRun(nCyclesSegment); + nCyclesDone[0] += nCyclesSegment; + + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + } + + konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + K053260Update(0, pBurnSoundOut, nBurnSoundLen); + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + K053260Scan(nAction); + + KonamiICScan(nAction); + + SCAN_VAR(readzoomroms); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + rollerg_set_lines(nDrvBank[0]); + konamiClose(); + } + + return 0; +} + + +// Rollergames (US) + +static struct BurnRomInfo rollergRomDesc[] = { + { "999m02.g7", 0x020000, 0x3df8db93, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "999m01.e11", 0x008000, 0x1fcfb22f, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "999h06.k2", 0x100000, 0xeda05130, 3 | BRF_GRA }, // 2 K053245 Tiles + { "999h05.k8", 0x100000, 0x5f321c7d, 3 | BRF_GRA }, // 3 + + { "999h03.d23", 0x040000, 0xea1edbd2, 4 | BRF_GRA }, // 4 K051316 Tiles + { "999h04.f23", 0x040000, 0xc1a35355, 4 | BRF_GRA }, // 5 + + { "999h09.c5", 0x080000, 0xc5188783, 5 | BRF_SND }, // 6 K053260 Samples +}; + +STD_ROM_PICK(rollerg) +STD_ROM_FN(rollerg) + +struct BurnDriver BurnDrvRollerg = { + "rollerg", NULL, NULL, NULL, "1991", + "Rollergames (US)\0", NULL, "Konami", "GX999", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, rollergRomInfo, rollergRomName, NULL, NULL, RollergInputInfo, RollergDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Rollergames (Japan) + +static struct BurnRomInfo rollergjRomDesc[] = { + { "999v02.bin", 0x020000, 0x0dd8c3ac, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "999m01.e11", 0x008000, 0x1fcfb22f, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "999h06.k2", 0x100000, 0xeda05130, 3 | BRF_GRA }, // 2 K053245 Tiles + { "999h05.k8", 0x100000, 0x5f321c7d, 3 | BRF_GRA }, // 3 + + { "999h03.d23", 0x040000, 0xea1edbd2, 4 | BRF_GRA }, // 4 K051316 Tiles + { "999h04.f23", 0x040000, 0xc1a35355, 4 | BRF_GRA }, // 5 + + { "999h09.c5", 0x080000, 0xc5188783, 5 | BRF_SND }, // 6 K053260 Samples +}; + +STD_ROM_PICK(rollergj) +STD_ROM_FN(rollergj) + +struct BurnDriver BurnDrvRollergj = { + "rollergj", "rollerg", NULL, NULL, "1991", + "Rollergames (Japan)\0", NULL, "Konami", "GX999", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, rollergjRomInfo, rollergjRomName, NULL, NULL, RollergInputInfo, RollergDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_simpsons.cpp b/src/burn/drivers/konami/d_simpsons.cpp new file mode 100644 index 00000000..ed1c2940 --- /dev/null +++ b/src/burn/drivers/konami/d_simpsons.cpp @@ -0,0 +1,1000 @@ +// FB Alpha The Simpsons driver module +// Based on MAME driver by Ernesto Corvi and various others + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "k053260.h" +#include "eeprom.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *nDrvBank; + +static INT32 videobank; +static INT32 init_eeprom_count; +static INT32 simpsons_firq_enabled; +static INT32 K053246Irq; + +static INT32 bg_colorbase; +static INT32 sprite_colorbase; +static INT32 layer_colorbase[3]; +static INT32 layerpri[3]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDiag; +static UINT8 DrvReset; +static UINT8 DrvInputs[5]; + +static INT32 nCyclesDone[2]; + +static struct BurnInputInfo SimpsonsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy5 + 2, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy5 + 3, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy4 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2" }, + + {"Diagnostics", BIT_DIGITAL, &DrvDiag, "diag" }, + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, +}; + +STDINPUTINFO(Simpsons) + +static struct BurnInputInfo Simpsons2pInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Diagnostics", BIT_DIGITAL, &DrvDiag, "diag" }, + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, +}; + +STDINPUTINFO(Simpsons2p) + +void simpsons_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1fa0: + case 0x1fa1: + case 0x1fa2: + case 0x1fa3: + case 0x1fa4: + case 0x1fa5: + case 0x1fa6: + case 0x1fa7: + K053246Write(address & 7, data); + return; + + case 0x1fc0: + K052109RMRDLine = data & 0x08; + K053246_set_OBJCHA_line(~data & 0x20); + return; + + case 0x1fc2: + { + if (data == 0xff) return; // ok? + + EEPROMWrite((data & 0x10) >> 3, (data & 0x08) >> 3, (data & 0x80) >> 7); + + videobank = data & 3; + simpsons_firq_enabled = data & 0x04; + } + return; + + case 0x1fc6: + case 0x1fc7: + K053260Write(0, address & 1, data); + return; + } + + if ((address & 0xf000) == 0x0000) { + if (videobank & 1) { + DrvPalRAM[address & 0x0fff] = data; + return; + } + } + + if ((address & 0xfff0) == 0x1fb0) { + K053251Write(address & 0x0f, data); + return; + } + + if ((address & 0xe000) == 0x2000) { + if (videobank & 2) { + address ^= 1; + DrvSprRAM[address & 0x1fff] = data; + return; + } + } + + if ((address & 0xc000) == 0x0000) { + K052109Write(address & 0x3fff, data); + return; + } +} + +UINT8 simpsons_main_read(UINT16 address) +{ + switch (address) + { + case 0x1f81: + { + INT32 res = ((EEPROMRead() & 1) << 4) | 0x20 | (~DrvDiag & 1); + + if (init_eeprom_count > 0) + { + init_eeprom_count--; + res &= 0xfe; + } + return res; + } + + case 0x1f80: + return DrvInputs[4]; + + case 0x1f90: + return DrvInputs[0]; + + case 0x1f91: + return DrvInputs[1]; + + case 0x1f92: + return DrvInputs[2]; + + case 0x1f93: + return DrvInputs[3]; + + case 0x1fc4: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return 0; + + case 0x1fc6: + case 0x1fc7: + return K053260Read(0, (address & 1)+2); + + case 0x1fc8: + case 0x1fc9: + return K053246Read(address & 1); + + case 0x1fca: + return 0; // watchdog + } + + if ((address & 0xf000) == 0x0000) { + if (videobank & 1) { + return DrvPalRAM[address & 0x0fff]; + } + } + + if ((address & 0xe000) == 0x2000) { + if (videobank & 2) { + address ^= 1; + return DrvSprRAM[address & 0x1fff]; + } + } + + if ((address & 0xc000) == 0x0000) { + return K052109Read(address & 0x3fff); + } + + return 0; +} + +static void DrvZ80Bankswitch(INT32 data) +{ + data &= 0x07; + if (data < 2) return; + + INT32 nBank = (data & 7) * 0x4000; + + nDrvBank[1] = data; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + nBank); +} + +void __fastcall simpsons_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + BurnYM2151SelectRegister(data); + return; + + case 0xf801: + BurnYM2151WriteRegister(data); + return; + + case 0xfa00: + nCyclesDone[1] += ZetRun(100); + ZetNmi(); + return; + + case 0xfe00: + DrvZ80Bankswitch(data); + return; + } + + if (address >= 0xfc00 && address < 0xfc30) { + K053260Write(0, address & 0xff, data); + return; + } +} + +UINT8 __fastcall simpsons_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + return 0xff; + case 0xf801: + return BurnYM2151ReadStatus(); + } + + if (address >= 0xfc00 && address < 0xfc30) { + if ((address & 0x3f) == 0x01) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + + return K053260Read(0, address & 0xff); + } + + return 0; +} + +static void simpsons_set_lines(INT32 lines) +{ + nDrvBank[0] = lines; + + INT32 nBank = (lines & 0x3f) * 0x2000; + + konamiMapMemory(DrvKonROM + 0x10000 + nBank, 0x6000, 0x7fff, KON_ROM); +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x3f) << 8) | (bank << 14); + *color = layer_colorbase[layer] + ((*color & 0xc0) >> 6); + *code &= 0x7fff; +} + +static void K053247Callback(INT32 *code, INT32 *color, INT32 *priority) +{ + INT32 pri = (*color & 0x0f80) >> 6; + if (pri <= layerpri[2]) *priority = 0; + else if (pri > layerpri[2] && pri <= layerpri[1]) *priority = 1; + else if (pri > layerpri[1] && pri <= layerpri[0]) *priority = 2; + else *priority = 3; + + *color = sprite_colorbase + (*color & 0x001f); + + *code &= 0x7fff; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + K053260Reset(0); + + EEPROMReset(); + + videobank = 0; + + if (EEPROMAvailable()) { + init_eeprom_count = 0; + } else { + init_eeprom_count = 10; + } + + simpsons_firq_enabled = 0; + K053246Irq = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x090000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROMExp1 = Next; Next += 0x800000; + + DrvSndROM = Next; Next += 0x200000; + + Palette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + + DrvKonRAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x002000; + + nDrvBank = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x100000); + konami_rom_deinterleave_4(DrvGfxROM1, 0x400000); + + GfxDecode(0x8000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + + K053247GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x400000); + + return 0; +} + +static const eeprom_interface simpsons_eeprom_intf = +{ + 7, // address bits + 8, // data bits + "011000", // read command + "011100", // write command + 0, // erase command + "0100000000000", // lock command + "0100110000000", // unlock command + 0, + 0 +}; + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x030000, 1, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x050000, 2, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x070000, 3, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x88000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x100000, 12, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x4000, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(simpsons_main_write); + konamiSetReadHandler(simpsons_main_read); + konamiSetlinesCallback(simpsons_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x08000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x08000); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(simpsons_sound_write); + ZetSetReadHandler(simpsons_sound_read); + ZetMemEnd(); + ZetClose(); + + EEPROMInit(&simpsons_eeprom_intf); + + K052109Init(DrvGfxROM0, 0x0fffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K053247Init(DrvGfxROM1, 0x3fffff, K053247Callback, 0x03 /* shadows & highlights */); + K053247SetSpriteOffset(-59, 39); + + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSndROM, 0x140000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + EEPROMExit(); + + BurnYM2151Exit(); + K053260Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void simpsons_objdma() +{ + INT32 counter, num_inactive; + UINT8 *dstptr; + UINT16 *src, *dst; + + K053247Export(&dstptr, 0, 0, 0, &counter); + src = (UINT16*)DrvSprRAM; + dst = (UINT16*)dstptr; + num_inactive = counter = 256; + + do { + if ((*src & 0x8000) && (*src & 0xff)) + { + memcpy(dst, src, 0x10); + dst += 8; + num_inactive--; + } + src += 8; + } + while (--counter); + + if (num_inactive) do { *dst = 0; dst += 8; } while (--num_inactive); +} + +static void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + K052109UpdateScroll(); + + INT32 layer[3]; + + bg_colorbase = K053251GetPaletteIndex(0); + sprite_colorbase = K053251GetPaletteIndex(1); + layer_colorbase[0] = K053251GetPaletteIndex(2); + layer_colorbase[1] = K053251GetPaletteIndex(3); + layer_colorbase[2] = K053251GetPaletteIndex(4); + + layerpri[0] = K053251GetPriority(2); + layerpri[1] = K053251GetPriority(3); + layerpri[2] = K053251GetPriority(4); + layer[0] = 0; + layer[1] = 1; + layer[2] = 2; + + sortlayers(layer,layerpri); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * bg_colorbase; + } + + if (nSpriteEnable & 8) K053247SpritesRender(DrvGfxROMExp1, 3); // title (simpsons behind clouds) + if (nBurnLayer & 1) K052109RenderLayer(layer[0], 0, DrvGfxROMExp0); // title (back-most cloud) + if (nSpriteEnable & 4) K053247SpritesRender(DrvGfxROMExp1, 2); // smithers' on first stage + if (nBurnLayer & 2) K052109RenderLayer(layer[1], 0, DrvGfxROMExp0); // main layer (buildings, stage 1) + if (nSpriteEnable & 2) K053247SpritesRender(DrvGfxROMExp1, 1); // smithers' thugs on stage 1 + if (nBurnLayer & 4) K052109RenderLayer(layer[2], 0, DrvGfxROMExp0); // game over text + if (nSpriteEnable & 1) K053247SpritesRender(DrvGfxROMExp1, 0); // not used? seems to make sense here... + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + konamiNewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[3] & 0x0c) == 0) DrvInputs[3] |= 0x0c; + if ((DrvInputs[3] & 0x03) == 0) DrvInputs[3] |= 0x03; + } + + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = konamiRun(nCyclesSegment); + nCyclesDone[0] += nCyclesSegment; + + if (i == 1 && K053246Irq && simpsons_firq_enabled) { + konamiSetIrqLine(KONAMI_FIRQ_LINE, KONAMI_HOLD_LINE); + } + + K053246Irq = K053246_is_IRQ_enabled(); + + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[1] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K053246Irq) simpsons_objdma(); + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K053260Scan(nAction); + + KonamiICScan(nAction); + + EEPROMScan(nAction, pnMin); + + SCAN_VAR(videobank); + SCAN_VAR(init_eeprom_count); + SCAN_VAR(simpsons_firq_enabled); + SCAN_VAR(K053246Irq); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + simpsons_set_lines(nDrvBank[0]); + konamiClose(); + + ZetOpen(0); + DrvZ80Bankswitch(nDrvBank[1]); + ZetClose(); + } + + return 0; +} + + +// The Simpsons (4 Players World, set 1) + +static struct BurnRomInfo simpsonsRomDesc[] = { + { "072-g02.16c", 0x020000, 0x580ce1d6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-g01.17c", 0x020000, 0x9f843def, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-j13.13c", 0x020000, 0xaade2abd, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-j12.15c", 0x020000, 0x479e12f2, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-e03.6g", 0x020000, 0x866b7a35, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons.nv", 0x000080, 0xec3f0449, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons) +STD_ROM_FN(simpsons) + +struct BurnDriver BurnDrvSimpsons = { + "simpsons", NULL, NULL, NULL, "1991", + "The Simpsons (4 Players World, set 1)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsonsRomInfo, simpsonsRomName, NULL, NULL, SimpsonsInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// The Simpsons (4 Players World, set 2) + +static struct BurnRomInfo simpsons4paRomDesc[] = { + { "072-g02.16c", 0x020000, 0x580ce1d6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-g01.17c", 0x020000, 0x9f843def, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-m13.13c", 0x020000, 0xf36c9423, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-l12.15c", 0x020000, 0x84f9d9ba, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-e03.6g", 0x020000, 0x866b7a35, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons4pa.nv", 0x000080, 0xec3f0449, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons4pa) +STD_ROM_FN(simpsons4pa) + +struct BurnDriver BurnDrvSimpsons4pa = { + "simpsons4pa", "simpsons", NULL, NULL, "1991", + "The Simpsons (4 Players World, set 2)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsons4paRomInfo, simpsons4paRomName, NULL, NULL, SimpsonsInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// The Simpsons (2 Players World, set 1) + +static struct BurnRomInfo simpsons2pRomDesc[] = { + { "072-g02.16c", 0x020000, 0x580ce1d6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-p01.17c", 0x020000, 0x07ceeaea, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-013.13c", 0x020000, 0x8781105a, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-012.15c", 0x020000, 0x244f9289, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-g03.6g", 0x020000, 0x76c1850c, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons2p.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons2p) +STD_ROM_FN(simpsons2p) + +struct BurnDriver BurnDrvSimpsons2p = { + "simpsons2p", "simpsons", NULL, NULL, "1991", + "The Simpsons (2 Players World, set 1)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsons2pRomInfo, simpsons2pRomName, NULL, NULL, Simpsons2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// The Simpsons (2 Players World, set 2) + +static struct BurnRomInfo simpsons2p2RomDesc[] = { + { "072-g02.16c", 0x020000, 0x580ce1d6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-p01.17c", 0x020000, 0x07ceeaea, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-_13.13c", 0x020000, 0x54e6df66, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-_12.15c", 0x020000, 0x96636225, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-g03.6g", 0x020000, 0x76c1850c, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons2p2.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons2p2) +STD_ROM_FN(simpsons2p2) + +struct BurnDriver BurnDrvSimpsons2p2 = { + "simpsons2p2", "simpsons", NULL, NULL, "1991", + "The Simpsons (2 Players World, set 2)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsons2p2RomInfo, simpsons2p2RomName, NULL, NULL, SimpsonsInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// The Simpsons (2 Players Asia) + +static struct BurnRomInfo simpsons2paRomDesc[] = { + { "072-g02.16c", 0x020000, 0x580ce1d6, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-p01.17c", 0x020000, 0x07ceeaea, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-113.13c", 0x020000, 0x8781105a, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-112.15c", 0x020000, 0x3bd69404, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-e03.6g", 0x020000, 0x866b7a35, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons2pa.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons2pa) +STD_ROM_FN(simpsons2pa) + +struct BurnDriver BurnDrvSimpsons2pa = { + "simpsons2pa", "simpsons", NULL, NULL, "1991", + "The Simpsons (2 Players Asia)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsons2paRomInfo, simpsons2paRomName, NULL, NULL, Simpsons2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// The Simpsons (2 Players Japan) + +static struct BurnRomInfo simpsons2pjRomDesc[] = { + { "072-s02.16c", 0x020000, 0x265f7a47, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "072-t01.17c", 0x020000, 0x91de5c2d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "072-213.13c", 0x020000, 0xb326a9ae, 1 | BRF_PRG | BRF_ESS }, // 2 + { "072-212.15c", 0x020000, 0x584d9d37, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "072-g03.6g", 0x020000, 0x76c1850c, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "072-b07.18h", 0x080000, 0xba1ec910, 3 | BRF_GRA }, // 5 K052109 Tiles + { "072-b06.16h", 0x080000, 0xcf2bbcab, 3 | BRF_GRA }, // 6 + + { "072-b08.3n", 0x100000, 0x7de500ad, 4 | BRF_GRA }, // 7 K053247 Tiles + { "072-b09.8n", 0x100000, 0xaa085093, 4 | BRF_GRA }, // 8 + { "072-b10.12n", 0x100000, 0x577dbd53, 4 | BRF_GRA }, // 9 + { "072-b11.16l", 0x100000, 0x55fab05d, 4 | BRF_GRA }, // 10 + + { "072-d05.1f", 0x100000, 0x1397a73b, 5 | BRF_SND }, // 11 K053260 Samples + { "072-d04.1d", 0x040000, 0x78778013, 5 | BRF_SND }, // 12 + + { "simpsons2pj.nv", 0x000080, 0x3550a54e, BRF_OPT }, +}; + +STD_ROM_PICK(simpsons2pj) +STD_ROM_FN(simpsons2pj) + +struct BurnDriver BurnDrvSimpsons2pj = { + "simpsons2pj", "simpsons", NULL, NULL, "1991", + "The Simpsons (2 Players Japan)\0", NULL, "Konami", "GX072", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, simpsons2pjRomInfo, simpsons2pjRomName, NULL, NULL, Simpsons2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_spy.cpp b/src/burn/drivers/konami/d_spy.cpp new file mode 100644 index 00000000..d3607298 --- /dev/null +++ b/src/burn/drivers/konami/d_spy.cpp @@ -0,0 +1,811 @@ +// FB Alpha S.P.Y. driver module +// Based on MAME driver by Nicola Salmoria and Acho A. Tang + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "burn_ym3812.h" +#include "konamiic.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvBankRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPMCRAM; +static UINT8 *DrvM6809RAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; + +static UINT8 *nDrvRomBank; + +static INT32 spy_video_enable; +static INT32 Drv3f90old; +static INT32 nRamBank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[8]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static struct BurnInputInfo SpyInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Spy) + +static struct BurnDIPInfo SpyDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x5e, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "10k and every 20k" }, + {0x13, 0x01, 0x18, 0x10, "20k and every 30k" }, + {0x13, 0x01, 0x18, 0x08, "20k only" }, + {0x13, 0x01, 0x18, 0x00, "30k only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x10, 0x10, "Off" }, +// {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Power" }, + {0x14, 0x01, 0x20, 0x20, "Normal" }, + {0x14, 0x01, 0x20, 0x00, "Strong" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x14, 0x01, 0x80, 0x80, "Unlimited" }, + {0x14, 0x01, 0x80, 0x00, "5 Times" }, +}; + +STDDIPINFO(Spy) + +static void DrvSetRAMBank(UINT8 bank, UINT8 data) +{ + nDrvRomBank[1] = bank; + nDrvRomBank[2] = data; + + if (data & 0x10) { + M6809MapMemory(DrvPalRAM, 0x0000, 0x07ff, M6809_RAM); + } else if (data & 0x20) { + if (bank & 0x80) { + M6809MapMemory(DrvPMCRAM, 0x0000, 0x07ff, M6809_RAM); + } else { + // unmap + M6809MapMemory(DrvM6809ROM + 0x800, 0x0000, 0x07ff, M6809_ROM); + M6809MapMemory(DrvM6809ROM + 0x000, 0x0000, 0x07ff, M6809_WRITE); + } + } else { + M6809MapMemory(DrvBankRAM, 0x0000, 0x07ff, M6809_RAM); + } +} + +static void spy_collision() +{ +#define MAX_SPRITES 64 +#define DEF_NEAR_PLANE 0x6400 +#define NEAR_PLANE_ZOOM 0x0100 +#define FAR_PLANE_ZOOM 0x0000 +#define pmcram DrvPMCRAM + + INT32 op1, x1, w1, z1, d1, y1, h1; + INT32 op2, x2, w2, z2, d2, y2, h2; + INT32 mode, i, loopend, nearplane; + + mode = pmcram[0x1]; + op1 = pmcram[0x2]; + if (op1 == 1) + { + x1 = (pmcram[0x3]<<8) + pmcram[0x4]; + w1 = (pmcram[0x5]<<8) + pmcram[0x6]; + z1 = (pmcram[0x7]<<8) + pmcram[0x8]; + d1 = (pmcram[0x9]<<8) + pmcram[0xa]; + y1 = (pmcram[0xb]<<8) + pmcram[0xc]; + h1 = (pmcram[0xd]<<8) + pmcram[0xe]; + + for (i=16; i<14*MAX_SPRITES + 2; i+=14) + { + op2 = pmcram[i]; + if (op2 || mode==0x0c) + { + x2 = (pmcram[i+0x1]<<8) + pmcram[i+0x2]; + w2 = (pmcram[i+0x3]<<8) + pmcram[i+0x4]; + z2 = (pmcram[i+0x5]<<8) + pmcram[i+0x6]; + d2 = (pmcram[i+0x7]<<8) + pmcram[i+0x8]; + y2 = (pmcram[i+0x9]<<8) + pmcram[i+0xa]; + h2 = (pmcram[i+0xb]<<8) + pmcram[i+0xc]; + + if (w2==0x58 && d2==0x04 && h2==0x10 && y2==0x30) h2 = y2; + + if ( (abs(x1-x2) 1) + { + loopend = (pmcram[0]<<8) + pmcram[1]; + nearplane = (pmcram[2]<<8) + pmcram[3]; + + if (loopend > MAX_SPRITES) loopend = MAX_SPRITES; + if (!nearplane) nearplane = DEF_NEAR_PLANE; + + loopend = (loopend<<1) + 4; + + for (i=4; i> 8; + pmcram[i+1] = op2 & 0xff; + } + + memset(pmcram+loopend, 0, 0x800-loopend); + } +} + +static void spy_3f90_w(INT32 data) +{ + K052109RMRDLine = data & 0x04; + + spy_video_enable = (~data & 0x08); + + nRamBank = data & 0xb0; + + DrvSetRAMBank(data & 0x80, data & 0x30); + + if ((data & 0x40) && (~Drv3f90old & 0x40)) + { + spy_collision(); + + M6809SetIRQ(1 /*FIRQ*/, M6809_IRQSTATUS_ACK); + M6809Run(105); // delay or the M6809 won't read it... + M6809SetIRQ(1 /*FIRQ*/, M6809_IRQSTATUS_NONE); + } + + Drv3f90old = data; +} + +static void bankswitch(INT32 data) +{ + nDrvRomBank[0] = data; + + INT32 nBank; + if (data & 0x10) { + nBank = 0x20000 + (data & 0x06) * 0x1000; + } else { + nBank = 0x10000 + (data & 0x0e) * 0x1000; + } + + M6809MapMemory(DrvM6809ROM + nBank, 0x6000, 0x7fff, M6809_ROM); +} + +void spy_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3f80: + bankswitch(data); + return; + + case 0x3f90: + spy_3f90_w(data); + return; + + case 0x3fa0: + // watchdog + return; + + case 0x3fb0: + *soundlatch = data; + return; + + case 0x3fc0: + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } + + if (address >= 0x2000 && address <= 0x5fff) { + K052109_051960_w(address - 0x2000, data); + return; + } +} + +UINT8 spy_main_read(UINT16 address) +{ + switch (address) + { + case 0x3fd0: + return (DrvInputs[2] & 0x0f) | (DrvDips[2] & 0xf0); + + case 0x3fd1: + return DrvInputs[0]; + + case 0x3fd2: + return DrvInputs[1]; + + case 0x3fd3: + return DrvDips[0]; + + case 0x3fe0: + return DrvDips[1]; + } + + if (address >= 0x2000 && address <= 0x5fff) { + return K052109_051960_r(address - 0x2000); + } + + return 0; +} + +static void sound_bankswitch(INT32 data) +{ + INT32 bank_A,bank_B; + + bank_A = (data >> 0) & 0x03; + bank_B = (data >> 2) & 0x03; + k007232_set_bank(0,bank_A,bank_B); + + bank_A = (data >> 4) & 0x03; + bank_B = (data >> 6) & 0x03; + k007232_set_bank(1,bank_A,bank_B); +} + +void __fastcall spy_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xa000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(1, address & 0x0f, data); + return; + } + + switch (address) + { + case 0x9000: + sound_bankswitch(data); + return; + + case 0xc000: + case 0xc001: + BurnYM3812Write(address & 1, data); + return; + } +} + +UINT8 __fastcall spy_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xa000) { + return K007232ReadReg(0, address & 0x0f); + } + + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(1, address & 0x0f); + } + + switch (address) + { + case 0xc000: + case 0xc001: + return BurnYM3812Read(address & 1); + + case 0xd000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *flags, INT32 *) +{ + INT32 colorbase[3] = { 0x30, 0, 0x10 }; + + *flags = *color & 0x20; + *code |= ((*color & 0x03) << 8) | ((*color & 0x10) << 6) | ((*color & 0x0c) << 9) | (bank << 13); + *color = colorbase[layer] + ((*color & 0xc0) >> 6); +} + +static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + *priority = 0x00; + if ( *color & 0x10) *priority = 1; + if (~*color & 0x20) *priority = 2; + + *color = 0x20 | (*color & 0x0f); + + *code = *code & 0x1fff; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) ZetNmi(); +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static void DrvK007232VolCallback0(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void DrvK007232VolCallback1(INT32 v) +{ + K007232SetVolume(1, 0, (v >> 4) * 0x11, 0); + K007232SetVolume(1, 1, 0, (v & 0x0f) * 0x11); +} + +static int DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + KonamiICReset(); + + BurnYM3812Reset(); + + spy_video_enable = 0; + Drv3f90old = 0; + nRamBank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x030000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM0 = Next; Next += 0x040000; + DrvSndROM1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvPMCRAM = Next; Next += 0x000800; + DrvBankRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + DrvM6809RAM = Next; Next += 0x001800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvRomBank = Next; Next += 0x000003; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000); + + GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x020000, 1, 1)) return 1; + memcpy (DrvM6809ROM + 0x08000, DrvM6809ROM + 0x28000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 8, 1)) return 1; + + DrvGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809RAM, 0x0800, 0x1aff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x10000, 0x6000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvM6809ROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(spy_main_write); + M6809SetReadByteHandler(spy_main_read); + M6809Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(spy_sound_write); + ZetSetReadHandler(spy_sound_read); + ZetMemEnd(); + ZetClose(); + + K052109Init(DrvGfxROM0, 0x07ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(-2, 0); + + K051960Init(DrvGfxROM1, 0x0fffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(0, 0); + + BurnYM3812Init(3579545, &DrvFMIRQHandler, DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + K007232Init(0, 3579545, DrvSndROM0, 0x40000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback0); + + K007232Init(1, 3579545, DrvSndROM1, 0x40000); + K007232SetPortWriteHandler(1, DrvK007232VolCallback1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + M6809Exit(); + ZetExit(); + + BurnYM3812Exit(); + + K007232Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x800); + } + + K052109UpdateScroll(); + + if (spy_video_enable) { + K052109RenderLayer(1, 1, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 2); + K052109RenderLayer(2, 0, DrvGfxROMExp0); + K051960SpritesRender(DrvGfxROMExp1, 1); + K051960SpritesRender(DrvGfxROMExp1, 0); + K052109RenderLayer(0, 0, DrvGfxROMExp0); + } else { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x0300; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + + for (INT32 i = 0 ; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + if ((DrvInputs[0] & 0x06) == 0) DrvInputs[0] |= 0x06; + if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18; + if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06; + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + } + + INT32 nCyclesSegment; + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + M6809Open(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + nCyclesSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + nCyclesDone[0] += M6809Run(nCyclesSegment - nCyclesDone[0]); + + nCyclesSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + nCyclesDone[1] += BurnTimerUpdateYM3812(nCyclesSegment - nCyclesDone[1]); + } + + if (K052109_irq_enabled) M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + K007232Update(0, pBurnSoundOut, nBurnSoundLen); + K007232Update(1, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + M6809Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6809Scan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(spy_video_enable); + SCAN_VAR(Drv3f90old); + SCAN_VAR(nRamBank); + } + + if (nAction & ACB_WRITE) { + M6809Open(0); + bankswitch(nDrvRomBank[0]); + DrvSetRAMBank(nDrvRomBank[1], nDrvRomBank[2]); + M6809Close(); + } + + return 0; +} + + +// S.P.Y. - Special Project Y (World ver. N) + +static struct BurnRomInfo spyRomDesc[] = { + { "857n03.bin", 0x10000, 0x97993b38, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "857n02.bin", 0x10000, 0x31a97efe, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "857d01.bin", 0x08000, 0xaad4210f, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "857b09.bin", 0x40000, 0xb8780966, 3 | BRF_GRA }, // 3 Background Tiles + { "857b08.bin", 0x40000, 0x3e4d8d50, 3 | BRF_GRA }, // 4 + + { "857b06.bin", 0x80000, 0x7b515fb1, 4 | BRF_GRA }, // 5 Sprites + { "857b05.bin", 0x80000, 0x27b0f73b, 4 | BRF_GRA }, // 6 + + { "857b07.bin", 0x40000, 0xce3512d4, 5 | BRF_SND }, // 7 K007232 #0 Samples + + { "857b04.bin", 0x40000, 0x20b83c13, 6 | BRF_SND }, // 8 K007232 #1 Samples + + { "857a10.bin", 0x00100, 0x32758507, 7 | BRF_OPT }, // 9 Proms +}; + +STD_ROM_PICK(spy) +STD_ROM_FN(spy) + +struct BurnDriver BurnDrvSpy = { + "spy", NULL, NULL, NULL, "1989", + "S.P.Y. - Special Project Y (World ver. N)\0", NULL, "Konami", "GX857", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, spyRomInfo, spyRomName, NULL, NULL, SpyInputInfo, SpyDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 304, 216, 4, 3 +}; + + +// S.P.Y. - Special Project Y (US ver. M) + +static struct BurnRomInfo spyuRomDesc[] = { + { "857m03.bin", 0x10000, 0x3bd87fa4, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "857m02.bin", 0x10000, 0x306cc659, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "857d01.bin", 0x08000, 0xaad4210f, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "857b09.bin", 0x40000, 0xb8780966, 3 | BRF_GRA }, // 3 Background Tiles + { "857b08.bin", 0x40000, 0x3e4d8d50, 3 | BRF_GRA }, // 4 + + { "857b06.bin", 0x80000, 0x7b515fb1, 4 | BRF_GRA }, // 5 Sprites + { "857b05.bin", 0x80000, 0x27b0f73b, 4 | BRF_GRA }, // 6 + + { "857b07.bin", 0x40000, 0xce3512d4, 5 | BRF_SND }, // 7 K007232 #0 Samples + + { "857b04.bin", 0x40000, 0x20b83c13, 6 | BRF_SND }, // 8 K007232 #1 Samples + + { "857a10.bin", 0x00100, 0x32758507, 7 | BRF_OPT }, // 9 Proms +}; + +STD_ROM_PICK(spyu) +STD_ROM_FN(spyu) + +struct BurnDriver BurnDrvSpyu = { + "spyu", "spy", NULL, NULL, "1989", + "S.P.Y. - Special Project Y (US ver. M)\0", NULL, "Konami", "GX857", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, spyuRomInfo, spyuRomName, NULL, NULL, SpyInputInfo, SpyDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 304, 216, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_surpratk.cpp b/src/burn/drivers/konami/d_surpratk.cpp new file mode 100644 index 00000000..d52c7b02 --- /dev/null +++ b/src/burn/drivers/konami/d_surpratk.cpp @@ -0,0 +1,641 @@ +// FB Alpha Surprise Attack driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "konami_intf.h" +#include "konamiic.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *nDrvRomBank; +static INT32 videobank; + +static INT32 layer_colorbase[3]; +static INT32 sprite_colorbase; +static INT32 layerpri[3]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static struct BurnInputInfo SurpratkInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Test", BIT_DIGITAL, DrvJoy3 + 1, "diag" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Surpratk) + +static struct BurnDIPInfo SuratkjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x5a, NULL }, + {0x15, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x03, "2" }, + {0x14, 0x01, 0x03, 0x02, "3" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + {0x14, 0x01, 0x03, 0x00, "7" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x14, 0x01, 0x04, 0x00, "Upright" }, +// {0x14, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x60, 0x60, "Easy" }, + {0x14, 0x01, 0x60, 0x40, "Normal" }, + {0x14, 0x01, 0x60, 0x20, "Difficult" }, + {0x14, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x15, 0x01, 0x10, 0x10, "Off" }, +// {0x15, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x15, 0x01, 0x20, 0x20, "Single" }, + {0x15, 0x01, 0x20, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, +}; + +static struct BurnDIPInfo BonusQuizDIPList[]= +{ + {0 , 0xfe, 0 , 2, "Bonus Quiz" }, + {0x15, 0x01, 0x80, 0x80, "Include" }, + {0x15, 0x01, 0x80, 0x00, "Except" }, +}; + +STDDIPINFO(Suratkj) +STDDIPINFOEXT(Surpratk, Suratkj, BonusQuiz) + +UINT8 supratk_read(UINT16 address) +{ + switch (address) + { + case 0x5f8c: + return DrvInputs[0]; + + case 0x5f8d: + return DrvInputs[1]; + + case 0x5f8e: + return (DrvInputs[2] & 0x0f) | (DrvDips[2] & 0xf0); + + case 0x5f8f: + return DrvDips[0]; + + case 0x5f90: + return DrvDips[1]; + + case 0x5fc0: + // watchdog + return 0; + } + + if ((address & 0xf800) == 0x0000) { + if (videobank & 0x02) { + return DrvPalRAM[((videobank & 4) << 9) + address]; + } else if (videobank & 0x01) { + return K053245Read(0, address); + } + return DrvBankRAM[address]; + } + + if ((address & 0xfff0) == 0x5fa0) { + return K053244Read(0, address & 0x0f); + } + + if ((address & 0xc000) == 0x4000) { + return K052109Read(address & 0x3fff); + } + + return 0; +} + +void supratk_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x5fc0: + K052109RMRDLine = data & 0x08; + return; + + case 0x5fc4: + videobank = data; + return; + + case 0x5fd0: + BurnYM2151SelectRegister(data); + return; + + case 0x5fd1: + BurnYM2151WriteRegister(data); + return; + } + + if ((address & 0xf800) == 0x0000) { + if (videobank & 0x02) { + DrvPalRAM[((videobank & 4) << 9) + address] = data; + return; + } else if (videobank & 0x01) { + K053245Write(0, address, data); + return; + } + DrvBankRAM[address] = data; + return; + } + + if ((address & 0xfff0) == 0x5fa0) { + K053244Write(0, address & 0x0f, data); + return; + } + + if ((address & 0xfff0) == 0x5fb0) { + K053251Write(address & 0x0f, data); + return; + } + + if ((address & 0xc000) == 0x4000) { + K052109Write(address & 0x3fff, data); + return; + } +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *flags, INT32 *) +{ + *flags = (*color & 0x80) >> 7; + *code |= ((*color & 0x03) << 8) | ((*color & 0x10) << 6) | ((*color & 0x0c) << 9) | (bank << 13); + *color = layer_colorbase[layer] + ((*color & 0x60) >> 5); +} + +static void K053245Callback(INT32 *code, INT32 *color, INT32 *priority) +{ + INT32 pri = 0x20 | ((*color & 0x60) >> 2); + if (pri <= layerpri[2]) *priority = 0; + else if (pri > layerpri[2] && pri <= layerpri[1]) *priority = 1; + else if (pri > layerpri[1] && pri <= layerpri[0]) *priority = 2; + else *priority = 3; + + *code &= 0xfff; + *color = sprite_colorbase + (*color & 0x1f); +} + +static void supratk_set_lines(INT32 lines) +{ + nDrvRomBank[0] = lines; + konamiMapMemory(DrvKonROM + 0x10000 + ((lines & 0x1f) * 0x2000), 0x2000, 0x3fff, KON_ROM); +} + +static void DrvYM2151IRQHandler(INT32 nStatus) +{ + konamiSetIrqLine(KONAMI_FIRQ_LINE, nStatus ? 3 /* use 3 as ACK */ : 0); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + videobank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROMExp0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROMExp1 = Next; Next += 0x100000; + + DrvKonROM = Next; Next += 0x050000; + + Palette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001800; + DrvPalRAM = Next; Next += 0x001000; + + nDrvRomBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x080000); + konami_rom_deinterleave_2(DrvGfxROM1, 0x080000); + + GfxDecode(0x4000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + + K053245GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x80000); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + int nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x030000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x48000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 5, 1)) return 1; + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x0800, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x2000, 0x3fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(supratk_write); + konamiSetReadHandler(supratk_read); + konamiSetlinesCallback(supratk_set_lines); + konamiClose(); + + K052109Init(DrvGfxROM0, 0x7ffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvGfxROM1, 0x7ffff, K053245Callback); + K053245SetSpriteOffset(0, -112, 16); + + BurnYM2151Init(3579545, 100.0); + YM2151SetIrqHandler(0, &DrvYM2151IRQHandler); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + K053245Exit(); + + konamiExit(); + + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +// stolen directly from mame +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + K052109UpdateScroll(); + + INT32 bg_colorbase, layer[3]; + + bg_colorbase = K053251GetPaletteIndex(0); + sprite_colorbase = K053251GetPaletteIndex(1); + layer_colorbase[0] = K053251GetPaletteIndex(2); + layer_colorbase[1] = K053251GetPaletteIndex(4); + layer_colorbase[2] = K053251GetPaletteIndex(3); + + layerpri[0] = K053251GetPriority(2); + layerpri[1] = K053251GetPriority(4); + layerpri[2] = K053251GetPriority(3); + layer[0] = 0; + layer[1] = 1; + layer[2] = 2; + + sortlayers(layer,layerpri); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * bg_colorbase; + } + + if (nBurnLayer & 1) K052109RenderLayer(layer[0], 0, DrvGfxROMExp0); + if (nSpriteEnable & 4) K053245SpritesRender(0, DrvGfxROMExp1, 2); // right? + if (nSpriteEnable & 8) K053245SpritesRender(0, DrvGfxROMExp1, 3); + if (nBurnLayer & 2) K052109RenderLayer(layer[1], 0, DrvGfxROMExp0); + if (nSpriteEnable & 2) K053245SpritesRender(0, DrvGfxROMExp1, 1); + if (nBurnLayer & 4) K052109RenderLayer(layer[2], 0, DrvGfxROMExp0); + + if (nSpriteEnable & 1) K053245SpritesRender(0, DrvGfxROMExp1, 0); // used? + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18; + if ((DrvInputs[0] & 0x06) == 0) DrvInputs[0] |= 0x06; + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06; + } + + konamiOpen(0); + konamiRun((((3000000 / 60) * 133) / 100) /* 33% overclock */); + + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + } + + konamiClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + + BurnYM2151Scan(nAction); + + KonamiICScan(nAction); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(videobank); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + supratk_set_lines(nDrvRomBank[0]); + konamiClose(); + } + + return 0; +} + + +// Surprise Attack (World ver. K) + +static struct BurnRomInfo suratkRomDesc[] = { + { "911j01.f5", 0x20000, 0x1e647881, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "911k02.h5", 0x20000, 0xef10e7b6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "911d05.bin", 0x40000, 0x308d2319, 2 | BRF_GRA }, // 2 Background Tiles + { "911d06.bin", 0x40000, 0x91cc9b32, 2 | BRF_GRA }, // 3 + + { "911d03.bin", 0x40000, 0xe34ff182, 3 | BRF_GRA }, // 4 Sprites + { "911d04.bin", 0x40000, 0x20700bd2, 3 | BRF_GRA }, // 5 +}; + +STD_ROM_PICK(suratk) +STD_ROM_FN(suratk) + +struct BurnDriver BurnDrvSuratk = { + "suratk", NULL, NULL, NULL, "1990", + "Surprise Attack (World ver. K)\0", NULL, "Konami", "GX911", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT | GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, suratkRomInfo, suratkRomName, NULL, NULL, SurpratkInputInfo, SurpratkDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Surprise Attack (Asia ver. L) + +static struct BurnRomInfo suratkaRomDesc[] = { + { "911j01.f5", 0x20000, 0x1e647881, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "911l02.h5", 0x20000, 0x11db8288, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "911d05.bin", 0x40000, 0x308d2319, 2 | BRF_GRA }, // 2 Background Tiles + { "911d06.bin", 0x40000, 0x91cc9b32, 2 | BRF_GRA }, // 3 + + { "911d03.bin", 0x40000, 0xe34ff182, 3 | BRF_GRA }, // 4 Sprites + { "911d04.bin", 0x40000, 0x20700bd2, 3 | BRF_GRA }, // 5 +}; + +STD_ROM_PICK(suratka) +STD_ROM_FN(suratka) + +struct BurnDriver BurnDrvSuratka = { + "suratka", "suratk", NULL, NULL, "1990", + "Surprise Attack (Asia ver. L)\0", NULL, "Konami", "GX911", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT | GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, suratkaRomInfo, suratkaRomName, NULL, NULL, SurpratkInputInfo, SurpratkDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Surprise Attack (Japan ver. M) + +static struct BurnRomInfo suratkjRomDesc[] = { + { "911m01.f5", 0x20000, 0xee5b2cc8, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "911m02.h5", 0x20000, 0x5d4148a8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "911d05.bin", 0x40000, 0x308d2319, 2 | BRF_GRA }, // 2 Background Tiles + { "911d06.bin", 0x40000, 0x91cc9b32, 2 | BRF_GRA }, // 3 + + { "911d03.bin", 0x40000, 0xe34ff182, 3 | BRF_GRA }, // 4 Sprites + { "911d04.bin", 0x40000, 0x20700bd2, 3 | BRF_GRA }, // 5 +}; + +STD_ROM_PICK(suratkj) +STD_ROM_FN(suratkj) + +struct BurnDriver BurnDrvSuratkj = { + "suratkj", "suratk", NULL, NULL, "1990", + "Surprise Attack (Japan ver. M)\0", NULL, "Konami", "GX911", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT | GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, suratkjRomInfo, suratkjRomName, NULL, NULL, SurpratkInputInfo, SuratkjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_thunderx.cpp b/src/burn/drivers/konami/d_thunderx.cpp new file mode 100644 index 00000000..498990a7 --- /dev/null +++ b/src/burn/drivers/konami/d_thunderx.cpp @@ -0,0 +1,1174 @@ +// FB Alpha Thunder X / Super Contra driver module +// Based on MAME driver by by Bryan McPhail, Manuel Abadia, and Eddie Edwards + +#include "tiles_generic.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvBankRAM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nDrvKonamiBank; + +static UINT8 *pmcram; +static UINT8 thunderx_1f98_data; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static INT32 thunderx = 0; + +static struct BurnInputInfo ThunderxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip"}, +}; + +STDINPUTINFO(Thunderx) + +static struct BurnDIPInfo ScontraDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x5a, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "30000 200000" }, + {0x13, 0x01, 0x18, 0x10, "50000 300000" }, + {0x13, 0x01, 0x18, 0x08, "30000" }, + {0x13, 0x01, 0x18, 0x00, "50000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x01, 0x01, "Off" }, +// {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Continue Limit" }, + {0x14, 0x01, 0x08, 0x08, "3" }, + {0x14, 0x01, 0x08, 0x00, "5" }, +}; + +STDDIPINFO(Scontra) + +static struct BurnDIPInfo ThunderxDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x52, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Award Bonus Life" }, + {0x13, 0x01, 0x04, 0x04, "No" }, + {0x13, 0x01, 0x04, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "30000 200000" }, + {0x13, 0x01, 0x18, 0x10, "50000 300000" }, + {0x13, 0x01, 0x18, 0x08, "30000" }, + {0x13, 0x01, 0x18, 0x00, "50000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x01, 0x01, "Off" }, +// {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Thunderx) + +static void run_collisions(INT32 s0, INT32 e0, INT32 s1, INT32 e1, INT32 cm, INT32 hm) +{ + INT32 ii, jj; + UINT8 *p0, *p1; + + p0 = &pmcram[16 + 5*s0]; + for (ii = s0; ii < e0; ii++, p0 += 5) + { + INT32 l0,r0,b0,t0; + + // check valid + if (!(p0[0] & cm)) continue; + + // get area + l0 = p0[3] - p0[1]; + r0 = p0[3] + p0[1]; + t0 = p0[4] - p0[2]; + b0 = p0[4] + p0[2]; + + p1 = &pmcram[16 + 5*s1]; + for (jj = s1; jj < e1; jj++,p1 += 5) + { + INT32 l1,r1,b1,t1; + + // check valid + if (!(p1[0] & hm)) continue; + + // get area + l1 = p1[3] - p1[1]; + r1 = p1[3] + p1[1]; + t1 = p1[4] - p1[2]; + b1 = p1[4] + p1[2]; + + // overlap check + if (l1 >= r0) continue; + if (l0 >= r1) continue; + if (t1 >= b0) continue; + if (t0 >= b1) continue; + + // set flags + p0[0] = (p0[0] & 0x9f) | (p1[0] & 0x04) | 0x10; + p1[0] = (p1[0] & 0x9f) | 0x10; + } + } +} + +static void calculate_collisions() +{ + INT32 X0,Y0; + INT32 X1,Y1; + INT32 CM,HM; + + Y0 = pmcram[0]; + Y0 = (Y0 << 8) + pmcram[1]; + Y0 = (Y0 - 15) / 5; + Y1 = (pmcram[2] - 15) / 5; + + if (pmcram[5] < 16) + { + // US Thunder Cross uses this form + X0 = pmcram[5]; + X0 = (X0 << 8) + pmcram[6]; + X0 = (X0 - 16) / 5; + X1 = (pmcram[7] - 16) / 5; + } + else + { + // Japan Thunder Cross uses this form + X0 = (pmcram[5] - 16) / 5; + X1 = (pmcram[6] - 16) / 5; + } + + CM = pmcram[3]; + HM = pmcram[4]; + + run_collisions(X0,Y0,X1,Y1,CM,HM); +} + +static void thunderx_1f98_w(UINT8 data) +{ + K052109RMRDLine = data & 0x01; + + if ((data & 4) && !(thunderx_1f98_data & 4)) + { + calculate_collisions(); + + konamiRun(10); + + konamiSetIrqLine(KONAMI_FIRQ_LINE, KONAMI_HOLD_LINE); // must be delayed + } + + thunderx_1f98_data = data; +} + +static void scontra_bankswitch(INT32 data) +{ + nDrvKonamiBank[0] = data; + + if (~data & 0x10) { + konamiMapMemory(DrvPalRAM, 0x5800, 0x5fff, KON_RAM); + } else { + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + } + + INT32 nBank = 0x10000 + (data & 0x0f) * 0x2000; + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, SM_ROM); +} + +static void thunderx_videobank(INT32 data) +{ + nDrvKonamiBank[0] = data; + + if (data & 0x01) { + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + } else if (data & 0x10) { + if (thunderx_1f98_data & 2) { + konamiMapMemory(pmcram + 0x800, 0x5800, 0x5fff, KON_RAM); + } else { + konamiMapMemory(pmcram, 0x5800, 0x5fff, KON_RAM); // junk? + } + } else { + konamiMapMemory(DrvPalRAM, 0x5800, 0x5fff, KON_RAM); + } +} + +void scontra_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1f80: + if (thunderx) { + thunderx_videobank(data); + } else { + scontra_bankswitch(data); + } + return; + + case 0x1f84: + *soundlatch = data; + return; + + case 0x1f88: + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x1f8c: + // watchdog + return; + + case 0x1f98: + thunderx_1f98_w(data); + return; + } + + if (address < 0x4000) { + K052109_051960_w(address & 0x3fff, data); + return; + } +} + +UINT8 scontra_main_read(UINT16 address) +{ + switch (address) + { + case 0x1f90: + return DrvInputs[0]; + + case 0x1f91: + return DrvInputs[1]; + + case 0x1f92: + return DrvInputs[2]; + + case 0x1f93: + return DrvDips[2]; + + case 0x1f94: + return DrvDips[0]; + + case 0x1f95: + return DrvDips[1]; + + case 0x1f98: + return thunderx_1f98_data; + } + + if (address < 0x4000) { + return K052109_051960_r(address & 0x3fff); + } + + return 0; +} + +static void scontra_snd_bankswitch_w(INT32 data) +{ + INT32 bank_A = (data & 0x03); + INT32 bank_B = ((data >> 2) & 0x03); + k007232_set_bank(0, bank_A, bank_B ); +} + +void __fastcall scontra_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } + + switch (address) + { + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xf000: + scontra_snd_bankswitch_w(data); + return; + } +} + +UINT8 __fastcall scontra_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(0, address & 0x0f); + } + + switch (address) + { + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + INT32 layer_colorbase[3] = { 48, 0, 16 }; + + *code |= ((*color & 0x1f) << 8) | (bank << 13); + *color = layer_colorbase[layer] + ((*color & 0xe0) >> 5); +} + +static void K051960Callback(INT32 *, INT32 *color,INT32 *priority, INT32 *shadow) +{ + *priority = (*color & 0x30) >> 4; + *color = 0x20 + (*color & 0x0f); + *shadow = 0; +} + +static void thunderx_set_lines(INT32 lines) +{ + nDrvKonamiBank[0] = lines; + + INT32 nBank = 0x10000 + (((lines & 0x0f) ^ 0x08) * 0x2000); + if (nBank >= 0x28000) nBank -= 0x20000; + + konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x200000; + DrvGfxROMExp1 = Next; Next += 0x200000; + + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvBankRAM = Next; Next += 0x000800; + DrvKonRAM = Next; Next += 0x001800; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + nDrvKonamiBank = Next; Next += 0x000002; + + pmcram = Next; Next += 0x001000; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x100000 >> thunderx); + konami_rom_deinterleave_2(DrvGfxROM1, 0x100000 >> thunderx); + + GfxDecode(0x08000 >> thunderx, 4, 8, 8, Plane0, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x02000 >> thunderx, 4, 16, 16, Plane1, XOffs, YOffs, 0x400, DrvGfxROM1, DrvGfxROMExp1); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (strncmp(BurnDrvGetTextA(DRV_NAME), "scontra", 7) == 0) { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x020000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x18000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060001, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080001, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c0000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c0001, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0e0000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0e0001, 14, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060001, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 25, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 26, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 27, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 28, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 29, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 30, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 31, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x010000, 32, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x020000, 33, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x030000, 34, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x040000, 35, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x050000, 36, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x060000, 37, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x070000, 38, 1)) return 1; + } else { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + if (BurnLoadRom(DrvKonROM + 0x020000, 1, 1)) return 1; + memcpy (DrvKonROM + 0x8000, DrvKonROM + 0x28000, 0x8000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060001, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060001, 18, 2)) return 1; + + thunderx = 1; + } + + DrvGfxDecode(); + } + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x4000, 0x57ff, KON_RAM); + konamiMapMemory(DrvBankRAM, 0x5800, 0x5fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(scontra_main_write); + konamiSetReadHandler(scontra_main_read); + konamiSetlinesCallback(thunderx_set_lines); + konamiClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(scontra_sound_write); + ZetSetReadHandler(scontra_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 25.0); + + K007232Init(0, 3579545, DrvSndROM, 0x80000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + K052109Init(DrvGfxROM0, 0x0fffff >> thunderx); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvGfxROM1, 0x0fffff >> thunderx); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(8, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + thunderx = 0; + + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + K007232Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x800); + } + + K052109UpdateScroll(); + +// K051960SpritesRender(DrvGfxROMExp1, 3); + + if (nDrvKonamiBank[0] & 0x08) + { + if (nBurnLayer & 1) K052109RenderLayer(2, 1, DrvGfxROMExp0); + if (nBurnLayer & 2) K052109RenderLayer(1, 0, DrvGfxROMExp0); + } + else + { + if (nBurnLayer & 8) K052109RenderLayer(2, 1, DrvGfxROMExp0); + if (nBurnLayer & 4) K052109RenderLayer(1, 0, DrvGfxROMExp0); + } + + K051960SpritesRender(DrvGfxROMExp1, 2); + + K051960SpritesRender(DrvGfxROMExp1, 1); + + K051960SpritesRender(DrvGfxROMExp1, 0); // mask? + + K052109RenderLayer(0, 0, DrvGfxROMExp0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + konamiNewFrame(); + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 1000; + INT32 nCyclesTotal[2] = { 3000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + konamiOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]); + + nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K007232Scan(nAction, pnMin); + + KonamiICScan(nAction); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(thunderx_1f98_data); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + if (thunderx) { + thunderx_videobank(nDrvKonamiBank[0]); + thunderx_set_lines(nDrvKonamiBank[1]); + } else { + scontra_bankswitch(nDrvKonamiBank[0]); + } + konamiClose(); + } + + return 0; +} + + +// Super Contra + +static struct BurnRomInfo scontraRomDesc[] = { + { "775-e02.k11", 0x10000, 0xa61c0ead, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "775-e03.k13", 0x10000, 0x00b02622, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "775-c01.bin", 0x08000, 0x0ced785a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "775-a07a.bin", 0x20000, 0xe716bdf3, 3 | BRF_GRA }, // 3 Background Tiles + { "775-a07e.bin", 0x20000, 0x0986e3a5, 3 | BRF_GRA }, // 4 + { "775-f07c.bin", 0x10000, 0xb0b30915, 3 | BRF_GRA }, // 5 + { "775-f07g.bin", 0x10000, 0xfbed827d, 3 | BRF_GRA }, // 6 + { "775-f07d.bin", 0x10000, 0xf184be8e, 3 | BRF_GRA }, // 7 + { "775-f07h.bin", 0x10000, 0x7b56c348, 3 | BRF_GRA }, // 8 + { "775-a08a.bin", 0x20000, 0x3ddd11a4, 3 | BRF_GRA }, // 9 + { "775-a08e.bin", 0x20000, 0x1007d963, 3 | BRF_GRA }, // 10 + { "775-f08c.bin", 0x10000, 0x53abdaec, 3 | BRF_GRA }, // 11 + { "775-f08g.bin", 0x10000, 0x3df85a6e, 3 | BRF_GRA }, // 12 + { "775-f08d.bin", 0x10000, 0x102dcace, 3 | BRF_GRA }, // 13 + { "775-f08h.bin", 0x10000, 0xad9d7016, 3 | BRF_GRA }, // 14 + + { "775-a05a.bin", 0x10000, 0xa0767045, 4 | BRF_GRA }, // 15 Sprites + { "775-a05e.bin", 0x10000, 0x2f656f08, 4 | BRF_GRA }, // 16 + { "775-a05b.bin", 0x10000, 0xab8ad4fd, 4 | BRF_GRA }, // 17 + { "775-a05f.bin", 0x10000, 0x1c0eb1b6, 4 | BRF_GRA }, // 18 + { "775-f05c.bin", 0x10000, 0x5647761e, 4 | BRF_GRA }, // 19 + { "775-f05g.bin", 0x10000, 0xa1692cca, 4 | BRF_GRA }, // 20 + { "775-f05d.bin", 0x10000, 0xad676a6f, 4 | BRF_GRA }, // 21 + { "775-f05h.bin", 0x10000, 0x3f925bcf, 4 | BRF_GRA }, // 22 + { "775-a06a.bin", 0x10000, 0x77a34ad0, 4 | BRF_GRA }, // 23 + { "775-a06e.bin", 0x10000, 0x8a910c94, 4 | BRF_GRA }, // 24 + { "775-a06b.bin", 0x10000, 0x563fb565, 4 | BRF_GRA }, // 25 + { "775-a06f.bin", 0x10000, 0xe14995c0, 4 | BRF_GRA }, // 26 + { "775-f06c.bin", 0x10000, 0x5ee6f3c1, 4 | BRF_GRA }, // 27 + { "775-f06g.bin", 0x10000, 0x2645274d, 4 | BRF_GRA }, // 28 + { "775-f06d.bin", 0x10000, 0xc8b764fa, 4 | BRF_GRA }, // 29 + { "775-f06h.bin", 0x10000, 0xd6595f59, 4 | BRF_GRA }, // 30 + + { "775-a04a.bin", 0x10000, 0x7efb2e0f, 5 | BRF_SND }, // 31 K007232 Samples + { "775-a04b.bin", 0x10000, 0xf41a2b33, 5 | BRF_SND }, // 32 + { "775-a04c.bin", 0x10000, 0xe4e58f14, 5 | BRF_SND }, // 33 + { "775-a04d.bin", 0x10000, 0xd46736f6, 5 | BRF_SND }, // 34 + { "775-f04e.bin", 0x10000, 0xfbf7e363, 5 | BRF_SND }, // 35 + { "775-f04f.bin", 0x10000, 0xb031ef2d, 5 | BRF_SND }, // 36 + { "775-f04g.bin", 0x10000, 0xee107bbb, 5 | BRF_SND }, // 37 + { "775-f04h.bin", 0x10000, 0xfb0fab46, 5 | BRF_SND }, // 38 + + { "775a09.b19", 0x00100, 0x46d1e0df, 6 | BRF_OPT }, // 39 Proms +}; + +STD_ROM_PICK(scontra) +STD_ROM_FN(scontra) + +struct BurnDriver BurnDrvScontra = { + "scontra", NULL, NULL, NULL, "1988", + "Super Contra\0", NULL, "Konami", "GX775", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_HORSHOOT, 0, + NULL, scontraRomInfo, scontraRomName, NULL, NULL, ThunderxInputInfo, ScontraDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 288, 3, 4 +}; + + +// Super Contra (Japan) + +static struct BurnRomInfo scontrajRomDesc[] = { + { "775-f02.bin", 0x10000, 0x8d5933a7, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "775-f03.bin", 0x10000, 0x1ef63d80, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "775-c01.bin", 0x08000, 0x0ced785a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "775-a07a.bin", 0x20000, 0xe716bdf3, 3 | BRF_GRA }, // 3 Background Tiles + { "775-a07e.bin", 0x20000, 0x0986e3a5, 3 | BRF_GRA }, // 4 + { "775-f07c.bin", 0x10000, 0xb0b30915, 3 | BRF_GRA }, // 5 + { "775-f07g.bin", 0x10000, 0xfbed827d, 3 | BRF_GRA }, // 6 + { "775-f07d.bin", 0x10000, 0xf184be8e, 3 | BRF_GRA }, // 7 + { "775-f07h.bin", 0x10000, 0x7b56c348, 3 | BRF_GRA }, // 8 + { "775-a08a.bin", 0x20000, 0x3ddd11a4, 3 | BRF_GRA }, // 9 + { "775-a08e.bin", 0x20000, 0x1007d963, 3 | BRF_GRA }, // 10 + { "775-f08c.bin", 0x10000, 0x53abdaec, 3 | BRF_GRA }, // 11 + { "775-f08g.bin", 0x10000, 0x3df85a6e, 3 | BRF_GRA }, // 12 + { "775-f08d.bin", 0x10000, 0x102dcace, 3 | BRF_GRA }, // 13 + { "775-f08h.bin", 0x10000, 0xad9d7016, 3 | BRF_GRA }, // 14 + + { "775-a05a.bin", 0x10000, 0xa0767045, 4 | BRF_GRA }, // 15 Sprites + { "775-a05e.bin", 0x10000, 0x2f656f08, 4 | BRF_GRA }, // 16 + { "775-a05b.bin", 0x10000, 0xab8ad4fd, 4 | BRF_GRA }, // 17 + { "775-a05f.bin", 0x10000, 0x1c0eb1b6, 4 | BRF_GRA }, // 18 + { "775-f05c.bin", 0x10000, 0x5647761e, 4 | BRF_GRA }, // 19 + { "775-f05g.bin", 0x10000, 0xa1692cca, 4 | BRF_GRA }, // 20 + { "775-f05d.bin", 0x10000, 0xad676a6f, 4 | BRF_GRA }, // 21 + { "775-f05h.bin", 0x10000, 0x3f925bcf, 4 | BRF_GRA }, // 22 + { "775-a06a.bin", 0x10000, 0x77a34ad0, 4 | BRF_GRA }, // 23 + { "775-a06e.bin", 0x10000, 0x8a910c94, 4 | BRF_GRA }, // 24 + { "775-a06b.bin", 0x10000, 0x563fb565, 4 | BRF_GRA }, // 25 + { "775-a06f.bin", 0x10000, 0xe14995c0, 4 | BRF_GRA }, // 26 + { "775-f06c.bin", 0x10000, 0x5ee6f3c1, 4 | BRF_GRA }, // 27 + { "775-f06g.bin", 0x10000, 0x2645274d, 4 | BRF_GRA }, // 28 + { "775-f06d.bin", 0x10000, 0xc8b764fa, 4 | BRF_GRA }, // 29 + { "775-f06h.bin", 0x10000, 0xd6595f59, 4 | BRF_GRA }, // 30 + + { "775-a04a.bin", 0x10000, 0x7efb2e0f, 5 | BRF_SND }, // 31 K007232 Samples + { "775-a04b.bin", 0x10000, 0xf41a2b33, 5 | BRF_SND }, // 32 + { "775-a04c.bin", 0x10000, 0xe4e58f14, 5 | BRF_SND }, // 33 + { "775-a04d.bin", 0x10000, 0xd46736f6, 5 | BRF_SND }, // 34 + { "775-f04e.bin", 0x10000, 0xfbf7e363, 5 | BRF_SND }, // 35 + { "775-f04f.bin", 0x10000, 0xb031ef2d, 5 | BRF_SND }, // 36 + { "775-f04g.bin", 0x10000, 0xee107bbb, 5 | BRF_SND }, // 37 + { "775-f04h.bin", 0x10000, 0xfb0fab46, 5 | BRF_SND }, // 38 + + { "775a09.b19", 0x00100, 0x46d1e0df, 6 | BRF_OPT }, // 39 Proms +}; + +STD_ROM_PICK(scontraj) +STD_ROM_FN(scontraj) + +struct BurnDriver BurnDrvScontraj = { + "scontraj", "scontra", NULL, NULL, "1988", + "Super Contra (Japan)\0", NULL, "Konami", "GX775", + L"Super \u9B42\u6597\u7F85 \u30A8\u30A4\u30EA\u30A2\u30F3 \u306E\u9006\u8972 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT | GBF_HORSHOOT, 0, + NULL, scontrajRomInfo, scontrajRomName, NULL, NULL, ThunderxInputInfo, ScontraDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 288, 3, 4 +}; + + +// Thunder Cross (set 1) + +static struct BurnRomInfo thunderxRomDesc[] = { + { "873-s03.k15", 0x10000, 0x2aec2699, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "873-s02.k13", 0x10000, 0x6619333a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "873-f01.f8", 0x08000, 0xea35ffa3, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "873c06a.f6", 0x10000, 0x0e340b67, 3 | BRF_GRA }, // 3 Background Tiles + { "873c06c.f5", 0x10000, 0xef0e72cd, 3 | BRF_GRA }, // 4 + { "873c06b.e6", 0x10000, 0x97ad202e, 3 | BRF_GRA }, // 5 + { "873c06d.e5", 0x10000, 0x8393d42e, 3 | BRF_GRA }, // 6 + { "873c07a.f4", 0x10000, 0xa8aab84f, 3 | BRF_GRA }, // 7 + { "873c07c.f3", 0x10000, 0x2521009a, 3 | BRF_GRA }, // 8 + { "873c07b.e4", 0x10000, 0x12a2b8ba, 3 | BRF_GRA }, // 9 + { "873c07d.e3", 0x10000, 0xfae9f965, 3 | BRF_GRA }, // 10 + + { "873c04a.f11", 0x10000, 0xf7740bf3, 4 | BRF_GRA }, // 11 Sprites + { "873c04c.f10", 0x10000, 0x5dacbd2b, 4 | BRF_GRA }, // 12 + { "873c04b.e11", 0x10000, 0x9ac581da, 4 | BRF_GRA }, // 13 + { "873c04d.e10", 0x10000, 0x44a4668c, 4 | BRF_GRA }, // 14 + { "873c05a.f9", 0x10000, 0xd73e107d, 4 | BRF_GRA }, // 15 + { "873c05c.f8", 0x10000, 0x59903200, 4 | BRF_GRA }, // 16 + { "873c05b.e9", 0x10000, 0x81059b99, 4 | BRF_GRA }, // 17 + { "873c05d.e8", 0x10000, 0x7fa3d7df, 4 | BRF_GRA }, // 18 + + { "873a08.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 19 Proms +}; + +STD_ROM_PICK(thunderx) +STD_ROM_FN(thunderx) + +struct BurnDriver BurnDrvThunderx = { + "thunderx", NULL, NULL, NULL, "1988", + "Thunder Cross (set 1)\0", NULL, "Konami", "GX873", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, thunderxRomInfo, thunderxRomName, NULL, NULL, ThunderxInputInfo, ThunderxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Thunder Cross (set 2) + +static struct BurnRomInfo thunderxaRomDesc[] = { + { "873-k03.k15", 0x10000, 0x276817ad, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "873-k02.k13", 0x10000, 0x80cc1c45, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "873-h01.f8", 0x08000, 0x990b7a7c, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "873c06a.f6", 0x10000, 0x0e340b67, 3 | BRF_GRA }, // 3 Background Tiles + { "873c06c.f5", 0x10000, 0xef0e72cd, 3 | BRF_GRA }, // 4 + { "873c06b.e6", 0x10000, 0x97ad202e, 3 | BRF_GRA }, // 5 + { "873c06d.e5", 0x10000, 0x8393d42e, 3 | BRF_GRA }, // 6 + { "873c07a.f4", 0x10000, 0xa8aab84f, 3 | BRF_GRA }, // 7 + { "873c07c.f3", 0x10000, 0x2521009a, 3 | BRF_GRA }, // 8 + { "873c07b.e4", 0x10000, 0x12a2b8ba, 3 | BRF_GRA }, // 9 + { "873c07d.e3", 0x10000, 0xfae9f965, 3 | BRF_GRA }, // 10 + + { "873c04a.f11", 0x10000, 0xf7740bf3, 4 | BRF_GRA }, // 11 Sprites + { "873c04c.f10", 0x10000, 0x5dacbd2b, 4 | BRF_GRA }, // 12 + { "873c04b.e11", 0x10000, 0x9ac581da, 4 | BRF_GRA }, // 13 + { "873c04d.e10", 0x10000, 0x44a4668c, 4 | BRF_GRA }, // 14 + { "873c05a.f9", 0x10000, 0xd73e107d, 4 | BRF_GRA }, // 15 + { "873c05c.f8", 0x10000, 0x59903200, 4 | BRF_GRA }, // 16 + { "873c05b.e9", 0x10000, 0x81059b99, 4 | BRF_GRA }, // 17 + { "873c05d.e8", 0x10000, 0x7fa3d7df, 4 | BRF_GRA }, // 18 + + { "873a08.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 19 Proms +}; + +STD_ROM_PICK(thunderxa) +STD_ROM_FN(thunderxa) + +struct BurnDriver BurnDrvThunderxa = { + "thunderxa", "thunderx", NULL, NULL, "1988", + "Thunder Cross (set 2)\0", NULL, "Konami", "GX873", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, thunderxaRomInfo, thunderxaRomName, NULL, NULL, ThunderxInputInfo, ThunderxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Thunder Cross (set 3) + +static struct BurnRomInfo thunderxbRomDesc[] = { + { "873-03.k15", 0x10000, 0x36680a4e, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "873-02.k13", 0x10000, 0xc58b2c34, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "873-f01.f8", 0x08000, 0xea35ffa3, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "873c06a.f6", 0x10000, 0x0e340b67, 3 | BRF_GRA }, // 3 Background Tiles + { "873c06c.f5", 0x10000, 0xef0e72cd, 3 | BRF_GRA }, // 4 + { "873c06b.e6", 0x10000, 0x97ad202e, 3 | BRF_GRA }, // 5 + { "873c06d.e5", 0x10000, 0x8393d42e, 3 | BRF_GRA }, // 6 + { "873c07a.f4", 0x10000, 0xa8aab84f, 3 | BRF_GRA }, // 7 + { "873c07c.f3", 0x10000, 0x2521009a, 3 | BRF_GRA }, // 8 + { "873c07b.e4", 0x10000, 0x12a2b8ba, 3 | BRF_GRA }, // 9 + { "873c07d.e3", 0x10000, 0xfae9f965, 3 | BRF_GRA }, // 10 + + { "873c04a.f11", 0x10000, 0xf7740bf3, 4 | BRF_GRA }, // 11 Sprites + { "873c04c.f10", 0x10000, 0x5dacbd2b, 4 | BRF_GRA }, // 12 + { "873c04b.e11", 0x10000, 0x9ac581da, 4 | BRF_GRA }, // 13 + { "873c04d.e10", 0x10000, 0x44a4668c, 4 | BRF_GRA }, // 14 + { "873c05a.f9", 0x10000, 0xd73e107d, 4 | BRF_GRA }, // 15 + { "873c05c.f8", 0x10000, 0x59903200, 4 | BRF_GRA }, // 16 + { "873c05b.e9", 0x10000, 0x81059b99, 4 | BRF_GRA }, // 17 + { "873c05d.e8", 0x10000, 0x7fa3d7df, 4 | BRF_GRA }, // 18 + + { "873a08.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 19 Proms +}; + +STD_ROM_PICK(thunderxb) +STD_ROM_FN(thunderxb) + +struct BurnDriver BurnDrvThunderxb = { + "thunderxb", "thunderx", NULL, NULL, "1988", + "Thunder Cross (set 3)\0", NULL, "Konami", "GX873", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, thunderxbRomInfo, thunderxbRomName, NULL, NULL, ThunderxInputInfo, ThunderxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; + + +// Thunder Cross (Japan) + +static struct BurnRomInfo thunderxjRomDesc[] = { + { "873-n03.k15", 0x10000, 0xa01e2e3e, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + { "873-n02.k13", 0x10000, 0x55afa2cc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "873-f01.f8", 0x08000, 0xea35ffa3, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "873c06a.f6", 0x10000, 0x0e340b67, 3 | BRF_GRA }, // 3 Background Tiles + { "873c06c.f5", 0x10000, 0xef0e72cd, 3 | BRF_GRA }, // 4 + { "873c06b.e6", 0x10000, 0x97ad202e, 3 | BRF_GRA }, // 5 + { "873c06d.e5", 0x10000, 0x8393d42e, 3 | BRF_GRA }, // 6 + { "873c07a.f4", 0x10000, 0xa8aab84f, 3 | BRF_GRA }, // 7 + { "873c07c.f3", 0x10000, 0x2521009a, 3 | BRF_GRA }, // 8 + { "873c07b.e4", 0x10000, 0x12a2b8ba, 3 | BRF_GRA }, // 9 + { "873c07d.e3", 0x10000, 0xfae9f965, 3 | BRF_GRA }, // 10 + + { "873c04a.f11", 0x10000, 0xf7740bf3, 4 | BRF_GRA }, // 11 Sprites + { "873c04c.f10", 0x10000, 0x5dacbd2b, 4 | BRF_GRA }, // 12 + { "873c04b.e11", 0x10000, 0x9ac581da, 4 | BRF_GRA }, // 13 + { "873c04d.e10", 0x10000, 0x44a4668c, 4 | BRF_GRA }, // 14 + { "873c05a.f9", 0x10000, 0xd73e107d, 4 | BRF_GRA }, // 15 + { "873c05c.f8", 0x10000, 0x59903200, 4 | BRF_GRA }, // 16 + { "873c05b.e9", 0x10000, 0x81059b99, 4 | BRF_GRA }, // 17 + { "873c05d.e8", 0x10000, 0x7fa3d7df, 4 | BRF_GRA }, // 18 + + { "873a08.f20", 0x00100, 0xe2d09a1b, 6 | BRF_OPT }, // 19 Proms +}; + +STD_ROM_PICK(thunderxj) +STD_ROM_FN(thunderxj) + +struct BurnDriver BurnDrvThunderxj = { + "thunderxj", "thunderx", NULL, NULL, "1988", + "Thunder Cross (Japan)\0", NULL, "Konami", "GX873", + L"Thunder Cross\0\u30B5\u30F3\u30C0\u30FC\u30AF\u30ED\u30B9 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, thunderxjRomInfo, thunderxjRomName, NULL, NULL, ThunderxInputInfo, ThunderxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_tmnt.cpp b/src/burn/drivers/konami/d_tmnt.cpp new file mode 100644 index 00000000..75c59348 --- /dev/null +++ b/src/burn/drivers/konami/d_tmnt.cpp @@ -0,0 +1,6557 @@ +#include "tiles_generic.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "upd7759.h" +#include "k007232.h" +#include "k053260.h" +#include "eeprom.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort5[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[3] = {0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvSoundRom = NULL; +static UINT8 *DrvUPD7759CRom = NULL; +static UINT8 *DrvTileRom = NULL; +static UINT8 *DrvSpriteRom = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvNvRam = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *Palette; +static UINT32 *DrvPalette = NULL; +static INT16 *DrvTitleSample = NULL; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static UINT8 bIrqEnable; +static INT32 LayerColourBase[3]; +static INT32 SpriteColourBase; +static INT32 LayerPri[3]; +static UINT8 DrvSoundLatch; +static INT32 PriorityFlag; + +static INT32 dim_c, dim_v; + +static INT32 DrvNvRamBank; +static INT32 CuebrickSndIrqFire; +static INT32 BlswhstlTileRomBank; + +static INT32 TitleSoundLatch; +static INT32 PlayTitleSample; +double TitleSamplePos = 0; + +static UINT8 DrvVBlank; + +static INT32 InitEEPROMCount; + +static const eeprom_interface BlswhstlEEPROMInterface = +{ + 7, + 8, + "011000", + "011100", + 0, + "0100000000000", + "0100110000000", + 0, + 0 +}; + +static const eeprom_interface thndrx2_eeprom_interface = +{ + 7, + 8, + "011000", + "010100", + 0, + "0100000000000", + "0100110000000", + 0, + 0 +}; + +static struct BurnInputInfo TmntInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvInputPort0 + 2, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , DrvInputPort0 + 3, "p4 coin" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort3 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort3 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort3 + 0, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort3 + 1, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , DrvInputPort4 + 2, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvInputPort4 + 3, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvInputPort4 + 0, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvInputPort4 + 1, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , DrvInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , DrvInputPort4 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service 1" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort0 + 5, "service2" }, + {"Service 3" , BIT_DIGITAL , DrvInputPort0 + 6, "service3" }, + {"Service 4" , BIT_DIGITAL , DrvInputPort0 + 7, "service4" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Tmnt) + +static struct BurnInputInfo Tmnt2pInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service 1" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort0 + 5, "service2" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Tmnt2p) + +static struct BurnInputInfo MiaInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 4, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Mia) + +static struct BurnInputInfo BlswhstlInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 2, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort0 + 3, "diag" }, +}; + +STDINPUTINFO(Blswhstl) + +static struct BurnInputInfo Ssriders4pInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvInputPort0 + 2, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , DrvInputPort0 + 3, "p4 coin" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort3 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort3 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort3 + 0, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort3 + 1, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , DrvInputPort4 + 2, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvInputPort4 + 3, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvInputPort4 + 0, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvInputPort4 + 1, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , DrvInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , DrvInputPort4 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service 1" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort0 + 5, "service2" }, + {"Service 3" , BIT_DIGITAL , DrvInputPort0 + 6, "service3" }, + {"Service 4" , BIT_DIGITAL , DrvInputPort0 + 7, "service4" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort5 + 7, "diag" }, +}; + +STDINPUTINFO(Ssriders4p) + +static struct BurnInputInfo SsridersInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service 1" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort0 + 5, "service2" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort5 + 7, "diag" }, +}; + +STDINPUTINFO(Ssriders) + +static struct BurnInputInfo Ssriders4psInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , DrvInputPort0 + 2, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , DrvInputPort3 + 7, "p3 start" }, + {"Coin 4" , BIT_DIGITAL , DrvInputPort0 + 3, "p4 coin" }, + {"Start 4" , BIT_DIGITAL , DrvInputPort4 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort3 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort3 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort3 + 0, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort3 + 1, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , DrvInputPort4 + 2, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvInputPort4 + 3, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvInputPort4 + 0, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvInputPort4 + 1, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , DrvInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , DrvInputPort4 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service 1" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort0 + 5, "service2" }, + {"Service 3" , BIT_DIGITAL , DrvInputPort0 + 6, "service3" }, + {"Service 4" , BIT_DIGITAL , DrvInputPort0 + 7, "service4" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort5 + 7, "diag" }, +}; + +STDINPUTINFO(Ssriders4ps) + +static struct BurnInputInfo Thndrx2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort1 + 0, "p1 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvInputPort0 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvInputPort0 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvInputPort0 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvInputPort0 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvInputPort0 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort1 + 1, "p2 coin" }, + + {"P2 Start", BIT_DIGITAL, DrvInputPort2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvInputPort2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvInputPort2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvInputPort2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvInputPort2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvInputPort1 + 2, "service" }, + {"Diagnostics", BIT_DIGITAL, DrvInputPort1 + 3, "diag" }, +}; + +STDINPUTINFO(Thndrx2) + +static struct BurnInputInfo LgtnfghtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort0 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvInputPort0 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvInputPort1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvInputPort1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvInputPort1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvInputPort1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvInputPort1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort0 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvInputPort0 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvInputPort2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvInputPort2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvInputPort2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvInputPort2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvInputPort2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvInputPort0 + 6, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDip + 2, "dip" }, +}; + +STDINPUTINFO(Lgtnfght) + +static struct BurnInputInfo QgakumonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort0 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvInputPort1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort1 + 3, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvInputPort1 + 0, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvInputPort1 + 1, "p1 fire 4" }, + {"P1 Push", BIT_DIGITAL, DrvInputPort1 + 4, "p1 fire 5" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort0 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvInputPort2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 2, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 3, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvInputPort2 + 0, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvInputPort2 + 1, "p2 fire 4" }, + {"P2 Push", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 5" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvInputPort0 + 4, "service" }, + {"Diagnostics", BIT_DIGITAL, DrvInputPort5 + 7, "diag" }, +}; + +STDINPUTINFO(Qgakumon) + +static struct BurnInputInfo PunkshotInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort0 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvInputPort1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvInputPort1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvInputPort1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvInputPort1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort0 + 1, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvInputPort2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvInputPort2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvInputPort2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvInputPort2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvInputPort0 + 2, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvInputPort3 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvInputPort3 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvInputPort3 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvInputPort3 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvInputPort3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvInputPort3 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvInputPort0 + 3, "p4 coin" }, + {"P4 Up", BIT_DIGITAL, DrvInputPort4 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvInputPort4 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvInputPort4 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvInputPort4 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvInputPort4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvInputPort4 + 5, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvInputPort0 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvInputPort0 + 5, "service2" }, + {"Service 3", BIT_DIGITAL, DrvInputPort0 + 6, "service3" }, + {"Service 4", BIT_DIGITAL, DrvInputPort0 + 7, "service4" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDip + 2, "dip" }, +}; + +STDINPUTINFO(Punkshot) + +static struct BurnInputInfo Punkshot2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort0 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvInputPort5 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvInputPort1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvInputPort1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvInputPort1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvInputPort1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort0 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvInputPort5 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvInputPort2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvInputPort2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvInputPort2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvInputPort2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvInputPort0 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDip + 2, "dip" }, +}; + +STDINPUTINFO(Punkshot2) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = DrvInput[3] = DrvInput[4] = DrvInput[5] = 0x00; + + // Compile Digital Inputs + for (int i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + DrvInput[3] |= (DrvInputPort3[i] & 1) << i; + DrvInput[4] |= (DrvInputPort4[i] & 1) << i; + DrvInput[5] |= (DrvInputPort5[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); + DrvClearOpposites(&DrvInput[3]); + DrvClearOpposites(&DrvInput[4]); +} + +static inline void SsridersMakeInputs() +{ + DrvMakeInputs(); + + DrvInput[5] ^= 0xf6; + //if (DrvInputPort5[7]) DrvInput[5] -= 0x80; +} + +static struct BurnDIPInfo TmntDIPList[]= +{ + // Default Values + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0x5e, NULL }, + {0x23, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x21, 0x01, 0x0f, 0x00, "5 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x21, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x21, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x21, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x21, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x21, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x21, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x22, 0x01, 0x03, 0x03, "1" }, + {0x22, 0x01, 0x03, 0x02, "2" }, + {0x22, 0x01, 0x03, 0x01, "3" }, + {0x22, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x22, 0x01, 0x60, 0x60, "Easy" }, + {0x22, 0x01, 0x60, 0x40, "Normal" }, + {0x22, 0x01, 0x60, 0x20, "Difficult" }, + {0x22, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x23, 0x01, 0x01, 0x01, "Off" }, + {0x23, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x23, 0x01, 0x04, 0x04, "Off" }, + {0x23, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Tmnt) + +static struct BurnDIPInfo Tmnt2pDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x5e, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x13, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x03, "1" }, + {0x14, 0x01, 0x03, 0x02, "2" }, + {0x14, 0x01, 0x03, 0x01, "3" }, + {0x14, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x60, 0x60, "Easy" }, + {0x14, 0x01, 0x60, 0x40, "Normal" }, + {0x14, 0x01, 0x60, 0x20, "Difficult" }, + {0x14, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Tmnt2p) + +static struct BurnDIPInfo MiaDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x56, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "30k 80k" }, + {0x15, 0x01, 0x18, 0x10, "50k 100k" }, + {0x15, 0x01, 0x18, 0x08, "50k" }, + {0x15, 0x01, 0x18, 0x00, "100k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "VRAM Character Check" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Mia) + +static struct BurnDIPInfo LgtnfghtDIPList[]= +{ + {0x14, 0xff, 0xff, 0x5e, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x03, "2" }, + {0x14, 0x01, 0x03, 0x02, "3" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + {0x14, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x18, 0x18, "100000 400000" }, + {0x14, 0x01, 0x18, 0x10, "150000 500000" }, + {0x14, 0x01, 0x18, 0x08, "200000" }, + {0x14, 0x01, 0x18, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x60, 0x60, "Easy" }, + {0x14, 0x01, 0x60, 0x40, "Medium" }, + {0x14, 0x01, 0x60, 0x20, "Hard" }, + {0x14, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "No Coin B" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Sound" }, + {0x16, 0x01, 0x02, 0x02, "Mono" }, + {0x16, 0x01, 0x02, 0x00, "Stereo" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Lgtnfght) + +static struct BurnDIPInfo PunkshotDIPList[]= +{ + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0x7f, NULL }, + {0x23, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x21, 0x01, 0x0f, 0x00, "5 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x21, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x21, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x21, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x21, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x21, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x21, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x21, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x21, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x21, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 2, "Continue" }, + {0x21, 0x01, 0x10, 0x10, "Normal" }, + {0x21, 0x01, 0x10, 0x00, "1 Coin" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x22, 0x01, 0x03, 0x03, "30" }, + {0x22, 0x01, 0x03, 0x02, "40" }, + {0x22, 0x01, 0x03, 0x01, "50" }, + {0x22, 0x01, 0x03, 0x00, "60" }, + + {0 , 0xfe, 0 , 4, "Period Length" }, + {0x22, 0x01, 0x0c, 0x0c, "2 Minutes" }, + {0x22, 0x01, 0x0c, 0x08, "3 Minutes" }, + {0x22, 0x01, 0x0c, 0x04, "4 Minutes" }, + {0x22, 0x01, 0x0c, 0x00, "5 Minutes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x22, 0x01, 0x60, 0x60, "Easy" }, + {0x22, 0x01, 0x60, 0x40, "Medium" }, + {0x22, 0x01, 0x60, 0x20, "Hard" }, + {0x22, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x23, 0x01, 0x10, 0x10, "Off" }, + {0x23, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x23, 0x01, 0x40, 0x40, "Off" }, + {0x23, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x23, 0x01, 0x80, 0x80, "Off" }, + {0x23, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Punkshot) + +static struct BurnDIPInfo Punkshot2DIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x12, 0x01, 0x0f, 0x00, "5 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 2, "Continue" }, + {0x12, 0x01, 0x10, 0x10, "Normal" }, + {0x12, 0x01, 0x10, 0x00, "1 Coin" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x13, 0x01, 0x03, 0x03, "40" }, + {0x13, 0x01, 0x03, 0x02, "50" }, + {0x13, 0x01, 0x03, 0x01, "60" }, + {0x13, 0x01, 0x03, 0x00, "70" }, + + {0 , 0xfe, 0 , 4, "Period Length" }, + {0x13, 0x01, 0x0c, 0x0c, "3 Minutes" }, + {0x13, 0x01, 0x0c, 0x08, "4 Minutes" }, + {0x13, 0x01, 0x0c, 0x04, "5 Minutes" }, + {0x13, 0x01, 0x0c, 0x00, "6 Minutes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Medium" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Punkshot2) + +static struct BurnDIPInfo PunkshotjDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "No Coin B" }, + + {0 , 0xfe, 0 , 4, "Period Time" }, + {0x13, 0x01, 0x0c, 0x0c, "1 Minute" }, + {0x13, 0x01, 0x0c, 0x08, "2 Minutes" }, + {0x13, 0x01, 0x0c, 0x04, "3 Minutes" }, + {0x13, 0x01, 0x0c, 0x00, "4 Minutes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Medium" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Punkshotj) + +static struct BurnRomInfo TmntRomDesc[] = { + { "963-x23.j17", 0x020000, 0xa9549004, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-x24.k17", 0x020000, 0xe5cc9067, BRF_ESS | BRF_PRG }, // 1 + { "963-x21.j15", 0x010000, 0x5789cf92, BRF_ESS | BRF_PRG }, // 2 + { "963-x22.k15", 0x010000, 0x0a74e277, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmnt) +STD_ROM_FN(Tmnt) + +static struct BurnRomInfo TmntuRomDesc[] = { + { "963-r23.j17", 0x020000, 0xa7f61195, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-r24.k17", 0x020000, 0x661e056a, BRF_ESS | BRF_PRG }, // 1 + { "963-r21.j15", 0x010000, 0xde047bb6, BRF_ESS | BRF_PRG }, // 2 + { "963-r22.k15", 0x010000, 0xd86a0888, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmntu) +STD_ROM_FN(Tmntu) + +static struct BurnRomInfo TmntuaRomDesc[] = { + { "963-j23.j17", 0x020000, 0xf77314e2, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-j24.k17", 0x020000, 0x47f662d3, BRF_ESS | BRF_PRG }, // 1 + { "963-j21.j15", 0x010000, 0x7bee9fe8, BRF_ESS | BRF_PRG }, // 2 + { "963-j22.k15", 0x010000, 0x2efed09f, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmntua) +STD_ROM_FN(Tmntua) + +static struct BurnRomInfo TmhtRomDesc[] = { + { "963-f23.j17", 0x020000, 0x9cb5e461, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-f24.k17", 0x020000, 0x2d902fab, BRF_ESS | BRF_PRG }, // 1 + { "963-f21.j15", 0x010000, 0x9fa25378, BRF_ESS | BRF_PRG }, // 2 + { "963-f22.k15", 0x010000, 0x2127ee53, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmht) +STD_ROM_FN(Tmht) + +static struct BurnRomInfo TmhtaRomDesc[] = { + { "963-s23.j17", 0x020000, 0xb5af7eee, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-s24.k17", 0x020000, 0xbcb8ce8b, BRF_ESS | BRF_PRG }, // 1 + { "963-s21.j15", 0x010000, 0x0b88bfa6, BRF_ESS | BRF_PRG }, // 2 + { "963-s22.k15", 0x010000, 0x44ce6d4b, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmhta) +STD_ROM_FN(Tmhta) + +static struct BurnRomInfo TmntjRomDesc[] = { + { "963_223.j17", 0x020000, 0x0d34a5ff, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963_224.k17", 0x020000, 0x2fd453f2, BRF_ESS | BRF_PRG }, // 1 + { "963_221.j15", 0x010000, 0xfa8e25fd, BRF_ESS | BRF_PRG }, // 2 + { "963_222.k15", 0x010000, 0xca437a4f, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmntj) +STD_ROM_FN(Tmntj) + +static struct BurnRomInfo Tmht2pRomDesc[] = { + { "963-u23.j17", 0x020000, 0x58bec748, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-u24.k17", 0x020000, 0xdce87c8d, BRF_ESS | BRF_PRG }, // 1 + { "963-u21.j15", 0x010000, 0xabce5ead, BRF_ESS | BRF_PRG }, // 2 + { "963-u22.k15", 0x010000, 0x4ecc8d6b, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmht2p) +STD_ROM_FN(Tmht2p) + +static struct BurnRomInfo Tmht2paRomDesc[] = { + { "963-_23.j17", 0x020000, 0x8698061a, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-_24.k17", 0x020000, 0x4036c075, BRF_ESS | BRF_PRG }, // 1 + { "963-_21.j15", 0x010000, 0xddcc979c, BRF_ESS | BRF_PRG }, // 2 + { "963-_22.k15", 0x010000, 0x71a38d27, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmht2pa) +STD_ROM_FN(Tmht2pa) + +static struct BurnRomInfo Tmnt2pjRomDesc[] = { + { "963-123.j17", 0x020000, 0x6a3527c9, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "963-124.k17", 0x020000, 0x2c4bfa15, BRF_ESS | BRF_PRG }, // 1 + { "963-121.j15", 0x010000, 0x4181b733, BRF_ESS | BRF_PRG }, // 2 + { "963-122.k15", 0x010000, 0xc64eb5ff, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmnt2pj) +STD_ROM_FN(Tmnt2pj) + +static struct BurnRomInfo Tmnt2poRomDesc[] = { + { "tmnt123.j17", 0x020000, 0x2d905183, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "tmnt124.k17", 0x020000, 0xe0125352, BRF_ESS | BRF_PRG }, // 1 + { "tmnt21.j15", 0x010000, 0x12deeafb, BRF_ESS | BRF_PRG }, // 2 + { "tmnt22.k15", 0x010000, 0xaec4f1c3, BRF_ESS | BRF_PRG }, // 3 + + { "963e20.g13", 0x008000, 0x1692a6d6, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "963a28.h27", 0x080000, 0xdb4769a8, BRF_GRA }, // 5 Tiles + { "963a29.k27", 0x080000, 0x8069cd2e, BRF_GRA }, // 6 + + { "963a17.h4", 0x080000, 0xb5239a44, BRF_GRA }, // 7 Sprites + { "963a18.h6", 0x080000, 0xdd51adef, BRF_GRA }, // 8 + { "963a15.k4", 0x080000, 0x1f324eed, BRF_GRA }, // 9 + { "963a16.k6", 0x080000, 0xd4bd9984, BRF_GRA }, // 10 + + { "963a30.g7", 0x000100, 0xabd82680, BRF_GRA }, // 11 PROMs + { "963a31.g19", 0x000100, 0xf8004a1c, BRF_GRA }, // 12 + + { "963a26.c13", 0x020000, 0xe2ac3063, BRF_SND }, // 13 K007232 Samples + + { "963a27.d18", 0x020000, 0x2dfd674b, BRF_SND }, // 14 UP7759C Samples + + { "963a25.d5", 0x080000, 0xfca078c7, BRF_SND }, // 15 Title Music Sample +}; + +STD_ROM_PICK(Tmnt2po) +STD_ROM_FN(Tmnt2po) + +static struct BurnRomInfo MiaRomDesc[] = { + { "808t20.h17", 0x020000, 0x6f0acb1d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "808t21.j17", 0x020000, 0x42a30416, BRF_ESS | BRF_PRG }, // 1 + + { "808e03.f4", 0x008000, 0x3d93a7cd, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "808e12.f28", 0x010000, 0xd62f1fde, BRF_GRA }, // 3 Tiles + { "808e13.h28", 0x010000, 0x1fa708f4, BRF_GRA }, // 4 + { "808e22.i28", 0x010000, 0x73d758f6, BRF_GRA }, // 5 + { "808e23.k28", 0x010000, 0x8ff08b21, BRF_GRA }, // 6 + + { "808d17.j4", 0x080000, 0xd1299082, BRF_GRA }, // 7 Sprites + { "808d15.h4", 0x080000, 0x2b22a6b6, BRF_GRA }, // 8 + + { "808a18.f16", 0x000100, 0xeb95aede, BRF_GRA }, // 9 PROMs + + { "808d01.d4", 0x020000, 0xfd4d37c0, BRF_SND }, // 10 K007232 Samples +}; + +STD_ROM_PICK(Mia) +STD_ROM_FN(Mia) + +static struct BurnRomInfo Mia2RomDesc[] = { + { "808s20.h17", 0x020000, 0xcaa2897f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "808s21.j17", 0x020000, 0x3d892ffb, BRF_ESS | BRF_PRG }, // 1 + + { "808e03.f4", 0x008000, 0x3d93a7cd, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "808e12.f28", 0x010000, 0xd62f1fde, BRF_GRA }, // 3 Tiles + { "808e13.h28", 0x010000, 0x1fa708f4, BRF_GRA }, // 4 + { "808e22.i28", 0x010000, 0x73d758f6, BRF_GRA }, // 5 + { "808e23.k28", 0x010000, 0x8ff08b21, BRF_GRA }, // 6 + + { "808d17.j4", 0x080000, 0xd1299082, BRF_GRA }, // 7 Sprites + { "808d15.h4", 0x080000, 0x2b22a6b6, BRF_GRA }, // 8 + + { "808a18.f16", 0x000100, 0xeb95aede, BRF_GRA }, // 9 PROMs + + { "808d01.d4", 0x020000, 0xfd4d37c0, BRF_SND }, // 10 K007232 Samples +}; + +STD_ROM_PICK(Mia2) +STD_ROM_FN(Mia2) + +static struct BurnRomInfo CuebrickRomDesc[] = { + { "903d25.g12", 0x010000, 0x8d575663, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "903d24.f12", 0x010000, 0x2973625d, BRF_ESS | BRF_PRG }, // 1 + + { "903c29.k21", 0x010000, 0xfada986d, BRF_GRA }, // 2 Tiles + { "903c27.k17", 0x010000, 0x5bd4b8e1, BRF_GRA }, // 3 + { "903c28.k19", 0x010000, 0x80d2bfaf, BRF_GRA }, // 4 + { "903c26.k15", 0x010000, 0xf808fa3d, BRF_GRA }, // 5 + + { "903d23.k12", 0x010000, 0xc39fc9fd, BRF_GRA }, // 6 Sprites + { "903d21.k8", 0x010000, 0x3c7bf8cd, BRF_GRA }, // 7 + { "903d22.k10", 0x010000, 0x95ad8591, BRF_GRA }, // 8 + { "903d20.k6", 0x010000, 0x2872a1bb, BRF_GRA }, // 9 +}; + +STD_ROM_PICK(Cuebrick) +STD_ROM_FN(Cuebrick) + +static struct BurnRomInfo BlswhstlRomDesc[] = { + { "060_l02.e09", 0x020000, 0xe8b7b234, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "060_l03.g09", 0x020000, 0x3c26d281, BRF_ESS | BRF_PRG }, // 1 + { "060_l09.e11", 0x020000, 0x14628736, BRF_ESS | BRF_PRG }, // 2 + { "060_l10.g11", 0x020000, 0xf738ad4a, BRF_ESS | BRF_PRG }, // 3 + + { "060j01.f3", 0x010000, 0xf9d9a673, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "060e07.k16", 0x080000, 0xc400edf3, BRF_GRA }, // 5 Tiles + { "060e08.k12", 0x080000, 0x70dddba1, BRF_GRA }, // 6 + + { "060e06.k7", 0x080000, 0x09381492, BRF_GRA }, // 7 Sprites + { "060e05.k3", 0x080000, 0x32454241, BRF_GRA }, // 8 + + { "060e04.d1", 0x100000, 0xc680395d, BRF_SND }, // 9 K053260 Samples + + { "blswhstl.nv", 0x000080, 0x87434e3f, BRF_OPT }, +}; + +STD_ROM_PICK(Blswhstl) +STD_ROM_FN(Blswhstl) + +static struct BurnRomInfo DetatwinRomDesc[] = { + { "060_j02.e09", 0x020000, 0x11b761ac, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "060_j03.g09", 0x020000, 0x8d0b588c, BRF_ESS | BRF_PRG }, // 1 + { "060_j09.e11", 0x020000, 0xf2a5f15f, BRF_ESS | BRF_PRG }, // 2 + { "060_j10.g11", 0x020000, 0x36eefdbc, BRF_ESS | BRF_PRG }, // 3 + + { "060j01.f3", 0x010000, 0xf9d9a673, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "060e07.k16", 0x080000, 0xc400edf3, BRF_GRA }, // 5 Tiles + { "060e08.k12", 0x080000, 0x70dddba1, BRF_GRA }, // 6 + + { "060e06.k7", 0x080000, 0x09381492, BRF_GRA }, // 7 Sprites + { "060e05.k3", 0x080000, 0x32454241, BRF_GRA }, // 8 + + { "060e04.d1", 0x100000, 0xc680395d, BRF_SND }, // 9 K053260 Samples + + { "blswhstl.nv", 0x000080, 0x87434e3f, BRF_OPT }, +}; + +STD_ROM_PICK(Detatwin) +STD_ROM_FN(Detatwin) + +static struct BurnRomInfo SsridersRomDesc[] = { + { "064eac02.8e", 0x040000, 0x5a5425f4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064eac03.8g", 0x040000, 0x093c00fb, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_eac.nv", 0x000080, 0xf6d641a7, BRF_OPT }, +}; + +STD_ROM_PICK(Ssriders) +STD_ROM_FN(Ssriders) + +static struct BurnRomInfo SsridersebdRomDesc[] = { + { "064ebd02.8e", 0x040000, 0x8deef9ac, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064ebd03.8g", 0x040000, 0x2370c107, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_ebd.nv", 0x000080, 0xcbc903f6, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersebd) +STD_ROM_FN(Ssridersebd) + +static struct BurnRomInfo SsridersebcRomDesc[] = { + { "064ebc02.8e", 0x040000, 0x9bd7d164, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064ebc03.8g", 0x040000, 0x40fd4165, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_ebc.nv", 0x000080, 0x1918e90f, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersebc) +STD_ROM_FN(Ssridersebc) + +static struct BurnRomInfo SsridersudaRomDesc[] = { + { "064uda02.8e", 0x040000, 0x5129a6b7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064uda03.8g", 0x040000, 0x9f887214, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_uda.nv", 0x000080, 0x148c6d64, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersuda) +STD_ROM_FN(Ssridersuda) + +static struct BurnRomInfo SsriderseaaRomDesc[] = { + { "064eaa02.8e", 0x040000, 0x4844660f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064eaa03.8g", 0x040000, 0x0b9bcc7c, BRF_ESS | BRF_PRG }, // 1 + { "064eaa04.10e", 0x020000, 0x5d917c1c, BRF_ESS | BRF_PRG }, // 2 + { "064eaa05.10g", 0x020000, 0xf4647b74, BRF_ESS | BRF_PRG }, // 3 + + { "064eaa01.2f", 0x010000, 0xbce45d82, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_eaa.nv", 0x000080, 0x74a45ef5, BRF_OPT }, +}; + +STD_ROM_PICK(Ssriderseaa) +STD_ROM_FN(Ssriderseaa) + +static struct BurnRomInfo SsridersuacRomDesc[] = { + { "064uac02.8e", 0x040000, 0x870473b6, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064uac03.8g", 0x040000, 0xeadf289a, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_uac.nv", 0x000080, 0x26c8f1a0, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersuac) +STD_ROM_FN(Ssridersuac) + +static struct BurnRomInfo SsridersubcRomDesc[] = { + { "064ubc02.8e", 0x040000, 0xaca7fda5, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064ubc03.8g", 0x040000, 0xbb1fdeff, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_ubc.nv", 0x000080, 0x31c5504f, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersubc) +STD_ROM_FN(Ssridersubc) + +static struct BurnRomInfo SsridersabdRomDesc[] = { + { "064abd02.8e", 0x040000, 0x713406cb, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064abd03.8g", 0x040000, 0x680feb3c, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_abd.nv", 0x000080, 0xbfdafedf, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersabd) +STD_ROM_FN(Ssridersabd) + +static struct BurnRomInfo SsridersaddRomDesc[] = { + { "064add02.8e", 0x040000, 0x06b0138e, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064add03.8g", 0x040000, 0x03eb8b91, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_add.nv", 0x000080, 0xf06242d5, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersadd) +STD_ROM_FN(Ssridersadd) + +static struct BurnRomInfo SsridersjbdRomDesc[] = { + { "064jbd02.8e", 0x040000, 0x7acdc1e3, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "064jbd03.8g", 0x040000, 0x6a424918, BRF_ESS | BRF_PRG }, // 1 + { "064eab04.10e", 0x020000, 0xef2315bd, BRF_ESS | BRF_PRG }, // 2 + { "064eab05.10g", 0x020000, 0x51d6fbc4, BRF_ESS | BRF_PRG }, // 3 + + { "064e01.2f", 0x010000, 0x44b9bc52, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 5 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 6 + + { "064e09.7l", 0x100000, 0x4160c372, BRF_GRA }, // 7 Sprites + { "064e07.3l", 0x100000, 0x64dd673c, BRF_GRA }, // 8 + + { "064e06.1d", 0x100000, 0x59810df9, BRF_SND }, // 9 K053260 Samples + + { "ssriders_jbd.nv", 0x000080, 0x006200e3, BRF_OPT }, +}; + +STD_ROM_PICK(Ssridersjbd) +STD_ROM_FN(Ssridersjbd) + +static struct BurnRomInfo ssridersbRomDesc[] = { + { "sunsetb.03", 0x080000, 0x37ffe90b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "sunsetb.04", 0x080000, 0x8ff647b7, BRF_ESS | BRF_PRG }, // 1 + + { "064e12.16k", 0x080000, 0xe2bdc619, BRF_GRA }, // 2 Tiles + { "064e11.12k", 0x080000, 0x2d8ca8b0, BRF_GRA }, // 3 + + { "sunsetb.05", 0x080000, 0x8a0ff31a, BRF_GRA }, // 4 Sprites + { "sunsetb.06", 0x080000, 0xfdf2c887, BRF_GRA }, // 5 + { "sunsetb.07", 0x080000, 0xa545b1ed, BRF_GRA }, // 6 + { "sunsetb.08", 0x080000, 0xf867cd38, BRF_GRA }, // 7 + + { "sunsetb.01", 0x080000, 0x1a8b5ca2, BRF_SND }, // 8 OKI Samples + { "sunsetb.02", 0x080000, 0x5d485523, BRF_SND }, // 9 +}; + +STD_ROM_PICK(ssridersb) +STD_ROM_FN(ssridersb) + +static struct BurnRomInfo thndrx2RomDesc[] = { + { "073-ea-l02.11c", 0x020000, 0xeae02b51, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "073-ea-l03.12c", 0x020000, 0x738ed007, BRF_ESS | BRF_PRG }, // 1 + + { "073-c01.4f", 0x010000, 0x44ebe83c, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "073-c06.16k", 0x080000, 0x24e22b42, BRF_GRA }, // 3 Tiles + { "073-c05.12k", 0x080000, 0x952a935f, BRF_GRA }, // 4 + + { "073-c07.7k", 0x080000, 0x14e93f38, BRF_GRA }, // 5 Sprites + { "073-c08.3k", 0x080000, 0x09fab3ab, BRF_GRA }, // 6 + + { "073-b04.2d", 0x080000, 0x05287a0b, BRF_SND }, // 7 K053260 Samples + + { "thndrx2.nv", 0x000080, 0xca613e98, BRF_OPT }, +}; + +STD_ROM_PICK(thndrx2) +STD_ROM_FN(thndrx2) + +static struct BurnRomInfo thndrx2aRomDesc[] = { + { "073-aa-m02.11c", 0x020000, 0x5b5b4cc0, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "073-aa-m03.12c", 0x020000, 0x320435a8, BRF_ESS | BRF_PRG }, // 1 + + { "073-c01.4f", 0x010000, 0x44ebe83c, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "073-c06.16k", 0x080000, 0x24e22b42, BRF_GRA }, // 3 Tiles + { "073-c05.12k", 0x080000, 0x952a935f, BRF_GRA }, // 4 + + { "073-c07.7k", 0x080000, 0x14e93f38, BRF_GRA }, // 5 Sprites + { "073-c08.3k", 0x080000, 0x09fab3ab, BRF_GRA }, // 6 + + { "073-b04.2d", 0x080000, 0x05287a0b, BRF_SND }, // 7 K053260 Samples + + { "thndrx2a.nv", 0x000080, 0xf7893d00, BRF_OPT }, +}; + +STD_ROM_PICK(thndrx2a) +STD_ROM_FN(thndrx2a) + +static struct BurnRomInfo thndrx2jRomDesc[] = { + { "073-ja-k02.11c", 0x020000, 0x0c8b2d3f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "073-ja-k03.12c", 0x020000, 0x3803b427, BRF_ESS | BRF_PRG }, // 1 + + { "073-c01.4f", 0x010000, 0x44ebe83c, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "073-c06.16k", 0x080000, 0x24e22b42, BRF_GRA }, // 3 Tiles + { "073-c05.12k", 0x080000, 0x952a935f, BRF_GRA }, // 4 + + { "073-c07.7k", 0x080000, 0x14e93f38, BRF_GRA }, // 5 Sprites + { "073-c08.3k", 0x080000, 0x09fab3ab, BRF_GRA }, // 6 + + { "073-b04.2d", 0x080000, 0x05287a0b, BRF_SND }, // 7 K053260 Samples + + { "thndrx2j.nv", 0x000080, 0x83b4799b, BRF_OPT }, +}; + +STD_ROM_PICK(thndrx2j) +STD_ROM_FN(thndrx2j) + +static struct BurnRomInfo lgtnfghtRomDesc[] = { + { "939k02.e11", 0x020000, 0x2dfefa53, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "939k03.e15", 0x020000, 0x14f0c454, BRF_ESS | BRF_PRG }, // 1 + + { "939e01.d7", 0x008000, 0x4a5fc848, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "939a07.k14", 0x080000, 0x7955dfcf, BRF_GRA }, // 3 Tiles + { "939a08.k19", 0x080000, 0xed95b385, BRF_GRA }, // 4 + + { "939a06.k8", 0x080000, 0xe393c206, BRF_GRA }, // 5 Sprites + { "939a05.k2", 0x080000, 0x3662d47a, BRF_GRA }, // 6 + + { "939a04.c5", 0x080000, 0xc24e2b6e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(lgtnfght) +STD_ROM_FN(lgtnfght) + +static struct BurnRomInfo lgtnfghtuRomDesc[] = { + { "939m02.e11", 0x020000, 0x61a12184, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "939m03.e15", 0x020000, 0x6db6659d, BRF_ESS | BRF_PRG }, // 1 + + { "939e01.d7", 0x008000, 0x4a5fc848, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "939a07.k14", 0x080000, 0x7955dfcf, BRF_GRA }, // 3 Tiles + { "939a08.k19", 0x080000, 0xed95b385, BRF_GRA }, // 4 + + { "939a06.k8", 0x080000, 0xe393c206, BRF_GRA }, // 5 Sprites + { "939a05.k2", 0x080000, 0x3662d47a, BRF_GRA }, // 6 + + { "939a04.c5", 0x080000, 0xc24e2b6e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(lgtnfghtu) +STD_ROM_FN(lgtnfghtu) + +static struct BurnRomInfo lgtnfghtaRomDesc[] = { + { "939j_02.e11", 0x020000, 0xbbbb4a74, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "939j_03.e15", 0x020000, 0x8d4da7b7, BRF_ESS | BRF_PRG }, // 1 + + { "939e01.d7", 0x008000, 0x4a5fc848, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "939a07.k14", 0x080000, 0x7955dfcf, BRF_GRA }, // 3 Tiles + { "939a08.k19", 0x080000, 0xed95b385, BRF_GRA }, // 4 + + { "939a06.k8", 0x080000, 0xe393c206, BRF_GRA }, // 5 Sprites + { "939a05.k2", 0x080000, 0x3662d47a, BRF_GRA }, // 6 + + { "939a04.c5", 0x080000, 0xc24e2b6e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(lgtnfghta) +STD_ROM_FN(lgtnfghta) + +static struct BurnRomInfo trigonRomDesc[] = { + { "939j02.e11", 0x020000, 0x38381d1b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "939j03.e15", 0x020000, 0xb5beddcd, BRF_ESS | BRF_PRG }, // 1 + + { "939e01.d7", 0x008000, 0x4a5fc848, BRF_ESS | BRF_PRG }, // 2 Z80 Code + + { "939a07.k14", 0x080000, 0x7955dfcf, BRF_GRA }, // 3 Tiles + { "939a08.k19", 0x080000, 0xed95b385, BRF_GRA }, // 4 + + { "939a06.k8", 0x080000, 0xe393c206, BRF_GRA }, // 5 Sprites + { "939a05.k2", 0x080000, 0x3662d47a, BRF_GRA }, // 6 + + { "939a04.c5", 0x080000, 0xc24e2b6e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(trigon) +STD_ROM_FN(trigon) + +static struct BurnRomInfo tmnt2RomDesc[] = { + { "063uaa02.e8", 0x020000, 0x58d5c93d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "063uaa03.g8", 0x020000, 0x0541fec9, BRF_ESS | BRF_PRG }, // 1 + { "063uaa04.e10", 0x020000, 0x1d441a7d, BRF_ESS | BRF_PRG }, // 2 + { "063uaa05.g10", 0x020000, 0x9c428273, BRF_ESS | BRF_PRG }, // 3 + + { "063b01", 0x010000, 0x364f548a, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "063b12", 0x080000, 0xd3283d19, BRF_GRA }, // 5 Tiles + { "063b11", 0x080000, 0x6ebc0c15, BRF_GRA }, // 6 + + { "063b09", 0x100000, 0x2d7a9d2a, BRF_GRA }, // 7 Sprites + { "063b10", 0x080000, 0xf2dd296e, BRF_GRA }, // 8 + { "063b07", 0x100000, 0xd9bee7bf, BRF_GRA }, // 9 + { "063b08", 0x080000, 0x3b1ae36f, BRF_GRA }, // 10 + + { "063b06", 0x200000, 0x1e510aa5, BRF_SND }, // 11 K053260 Samples + + { "tmnt2_uaa.nv", 0x000080, 0x284357bd, BRF_OPT }, +}; + +STD_ROM_PICK(tmnt2) +STD_ROM_FN(tmnt2) + +static struct BurnRomInfo tmnt22puRomDesc[] = { + { "063uda02.e8", 0x020000, 0xaadffe3a, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "063uda03.g8", 0x020000, 0x125687a8, BRF_ESS | BRF_PRG }, // 1 + { "063uda04.e10", 0x020000, 0xfb5c7ded, BRF_ESS | BRF_PRG }, // 2 + { "063uda05.g10", 0x020000, 0x3c40fe66, BRF_ESS | BRF_PRG }, // 3 + + { "063b01", 0x010000, 0x364f548a, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "063b12", 0x080000, 0xd3283d19, BRF_GRA }, // 5 Tiles + { "063b11", 0x080000, 0x6ebc0c15, BRF_GRA }, // 6 + + { "063b09", 0x100000, 0x2d7a9d2a, BRF_GRA }, // 7 Sprites + { "063b10", 0x080000, 0xf2dd296e, BRF_GRA }, // 8 + { "063b07", 0x100000, 0xd9bee7bf, BRF_GRA }, // 9 + { "063b08", 0x080000, 0x3b1ae36f, BRF_GRA }, // 10 + + { "063b06", 0x200000, 0x1e510aa5, BRF_SND }, // 11 K053260 Samples + + { "tmnt2_uda.nv", 0x000080, 0x44928d33, BRF_OPT }, +}; + +STD_ROM_PICK(tmnt22pu) +STD_ROM_FN(tmnt22pu) + +static struct BurnRomInfo tmht22peRomDesc[] = { + { "063eba02.e8", 0x020000, 0x99409094, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "063eba03.g8", 0x020000, 0x4d65650f, BRF_ESS | BRF_PRG }, // 1 + { "063eba04.e10", 0x020000, 0xf6e3b9c7, BRF_ESS | BRF_PRG }, // 2 + { "063eba05.g10", 0x020000, 0x1bad6696, BRF_ESS | BRF_PRG }, // 3 + + { "063b01", 0x010000, 0x364f548a, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "063b12", 0x080000, 0xd3283d19, BRF_GRA }, // 5 Tiles + { "063b11", 0x080000, 0x6ebc0c15, BRF_GRA }, // 6 + + { "063b09", 0x100000, 0x2d7a9d2a, BRF_GRA }, // 7 Sprites + { "063b10", 0x080000, 0xf2dd296e, BRF_GRA }, // 8 + { "063b07", 0x100000, 0xd9bee7bf, BRF_GRA }, // 9 + { "063b08", 0x080000, 0x3b1ae36f, BRF_GRA }, // 10 + + { "063b06", 0x200000, 0x1e510aa5, BRF_SND }, // 11 K053260 Samples + + { "tmnt2_eba.nv", 0x000080, 0xc0a3ed50, BRF_OPT }, +}; + +STD_ROM_PICK(tmht22pe) +STD_ROM_FN(tmht22pe) + +static struct BurnRomInfo tmnt2aRomDesc[] = { + { "063ada02.e8", 0x020000, 0x4f11b587, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "063ada03.g8", 0x020000, 0x82a1b9ac, BRF_ESS | BRF_PRG }, // 1 + { "063ada04.e10", 0x020000, 0x05ad187a, BRF_ESS | BRF_PRG }, // 2 + { "063ada05.g10", 0x020000, 0xd4826547, BRF_ESS | BRF_PRG }, // 3 + + { "063b01", 0x010000, 0x364f548a, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "063b12", 0x080000, 0xd3283d19, BRF_GRA }, // 5 Tiles + { "063b11", 0x080000, 0x6ebc0c15, BRF_GRA }, // 6 + + { "063b09", 0x100000, 0x2d7a9d2a, BRF_GRA }, // 7 Sprites + { "063b10", 0x080000, 0xf2dd296e, BRF_GRA }, // 8 + { "063b07", 0x100000, 0xd9bee7bf, BRF_GRA }, // 9 + { "063b08", 0x080000, 0x3b1ae36f, BRF_GRA }, // 10 + + { "063b06", 0x200000, 0x1e510aa5, BRF_SND }, // 11 K053260 Samples + + { "tmnt2_ada.nv", 0x000080, 0x063068a0, BRF_OPT }, +}; + +STD_ROM_PICK(tmnt2a) +STD_ROM_FN(tmnt2a) + +static struct BurnRomInfo qgakumonRomDesc[] = { + { "248jaa02.8e", 0x040000, 0xfab79410, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "248jaa03.8g", 0x040000, 0x8d888ef3, BRF_ESS | BRF_PRG }, // 1 + { "248jaa04.10e", 0x040000, 0x56cb16cb, BRF_ESS | BRF_PRG }, // 2 + { "248jaa05.10g", 0x040000, 0x27614fcd, BRF_ESS | BRF_PRG }, // 3 + + { "248a01.2f", 0x010000, 0xa8a41cc6, BRF_ESS | BRF_PRG }, // 4 Z80 Code + + { "248a12.16k", 0x080000, 0x62870987, BRF_GRA }, // 5 Tiles + { "248a11.12k", 0x080000, 0xfad2dbfd, BRF_GRA }, // 6 + + { "248a09.7l", 0x100000, 0xa176e205, BRF_GRA }, // 7 Sprites + { "248a07.3l", 0x100000, 0x9595589f, BRF_GRA }, // 8 + + { "248a06.1d", 0x200000, 0x0fba1def, BRF_SND }, // 9 K053260 Samples + + { "qgakumon.nv", 0x000080, 0x847bd238, BRF_OPT }, +}; + +STD_ROM_PICK(qgakumon) +STD_ROM_FN(qgakumon) + +static struct BurnRomInfo punkshotRomDesc[] = { + { "907-j02.i7", 0x020000, 0xdbb3a23b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "907-j03.i10", 0x020000, 0x2151d1ab, BRF_ESS | BRF_PRG }, // 1 + + { "907f01.e8", 0x008000, 0xf040c484, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "907d06.e23", 0x040000, 0xf5cc38f4, BRF_GRA }, // 3 Tiles + { "907d05.e22", 0x040000, 0xe25774c1, BRF_GRA }, // 4 + + { "907d07.k2", 0x100000, 0xb0fe4543, BRF_GRA }, // 5 Sprites + { "907d08.k7", 0x100000, 0xd5ac8d9d, BRF_GRA }, // 6 + + { "907d04.d3", 0x080000, 0x090feb5e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(punkshot) +STD_ROM_FN(punkshot) + +static struct BurnRomInfo punkshot2RomDesc[] = { + { "907m02.i7", 0x020000, 0x59e14575, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "907m03.i10", 0x020000, 0xadb14b1e, BRF_ESS | BRF_PRG }, // 1 + + { "907f01.e8", 0x008000, 0xf040c484, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "907d06.e23", 0x040000, 0xf5cc38f4, BRF_GRA }, // 3 Tiles + { "907d05.e22", 0x040000, 0xe25774c1, BRF_GRA }, // 4 + + { "907d07.k2", 0x100000, 0xb0fe4543, BRF_GRA }, // 5 Sprites + { "907d08.k7", 0x100000, 0xd5ac8d9d, BRF_GRA }, // 6 + + { "907d04.d3", 0x080000, 0x090feb5e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(punkshot2) +STD_ROM_FN(punkshot2) + +static struct BurnRomInfo punkshotjRomDesc[] = { + { "907z02.i7", 0x020000, 0x7a3a5c89, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "907z03.i10", 0x020000, 0x22a3d9d6, BRF_ESS | BRF_PRG }, // 1 + + { "907f01.e8", 0x008000, 0xf040c484, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "907d06.e23", 0x040000, 0xf5cc38f4, BRF_GRA }, // 3 Tiles + { "907d05.e22", 0x040000, 0xe25774c1, BRF_GRA }, // 4 + + { "907d07.k2", 0x100000, 0xb0fe4543, BRF_GRA }, // 5 Sprites + { "907d08.k7", 0x100000, 0xd5ac8d9d, BRF_GRA }, // 6 + + { "907d04.d3", 0x080000, 0x090feb5e, BRF_SND }, // 7 K053260 Samples +}; + +STD_ROM_PICK(punkshotj) +STD_ROM_FN(punkshotj) + +static INT32 TmntMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x060000; + DrvZ80Rom = Next; Next += 0x008000; + DrvSoundRom = Next; Next += 0x020000; + DrvUPD7759CRom = Next; Next += 0x020000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x200000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvTitleSample = (INT16*)Next; Next += 0x40000 * sizeof(INT16); + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x004000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 MiaMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x040000; + DrvZ80Rom = Next; Next += 0x008000; + DrvSoundRom = Next; Next += 0x020000; + DrvTileRom = Next; Next += 0x040000; + DrvSpriteRom = Next; Next += 0x100000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x008000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvTiles = Next; Next += 0x002000 * 8 * 8; + DrvSprites = Next; Next += 0x002000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 CuebrickMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x020000; + DrvTileRom = Next; Next += 0x040000; + DrvSpriteRom = Next; Next += 0x040000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x008000; + DrvPaletteRam = Next; Next += 0x001000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvTiles = Next; Next += 0x002000 * 8 * 8; + DrvSprites = Next; Next += 0x001000 * 16 * 16; + DrvNvRam = Next; Next += 0x400 * 0x20; + + MemEnd = Next; + + return 0; +} + +static INT32 BlswhstlMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x080000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x100000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x100000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + DrvSpriteRam = Next; Next += 0x004000; + + RamEnd = Next; + + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x002000 * 16 * 16; + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 SsridersMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x0c0000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x100000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x200000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004080; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + DrvSpriteRam = Next; Next += 0x004000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x004000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 Tmnt2MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x100000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x200000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x400000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x005080; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + DrvSpriteRam = Next; Next += 0x004000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x008000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 Thndrx2MemIndex() +{ + UINT8 *Next; Next = Mem; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + + RamEnd = Next; + + Drv68KRom = Next; Next += 0x080000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x080000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x100000; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x002000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 LgtnfghtMemIndex() +{ + UINT8 *Next; Next = Mem; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + DrvSpriteRam = Next; Next += 0x004000; + + RamEnd = Next; + + Drv68KRom = Next; Next += 0x080000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x080000; + DrvTileRom = Next; Next += 0x100000; + DrvSpriteRom = Next; Next += 0x100000; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + DrvTiles = Next; Next += 0x008000 * 8 * 8; + DrvSprites = Next; Next += 0x002000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 PunkshotMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x040000; + DrvZ80Rom = Next; Next += 0x010000; + DrvSoundRom = Next; Next += 0x080000; + DrvTileRom = Next; Next += 0x080000; + DrvSpriteRom = Next; Next += 0x200000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvZ80Ram = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x001000; + + RamEnd = Next; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00810 * sizeof(UINT32); + DrvTiles = Next; Next += 0x004000 * 8 * 8; + DrvSprites = Next; Next += 0x004000 * 16 * 16; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + bIrqEnable = 0; + DrvSoundLatch = 0; + TitleSoundLatch = 0; + PlayTitleSample = 0; + TitleSamplePos = 0; + PriorityFlag = 0; + + return 0; +} + +static INT32 TmntDoReset() +{ + INT32 nRet = DrvDoReset(); + + UPD7759Reset(); + + UPD7759StartWrite(0, 0); + UPD7759ResetWrite(0, 1); + + return nRet; +} + +static INT32 CuebrickDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + bIrqEnable = 0; + DrvNvRamBank = 0; + PriorityFlag = 0; + CuebrickSndIrqFire = 0; + + return 0; +} + +static INT32 BlswhstlDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + K053260Reset(0); + + KonamiICReset(); + + EEPROMReset(); + + if (EEPROMAvailable()) { + InitEEPROMCount = 0; + } else { + InitEEPROMCount = 10; + } + + BlswhstlTileRomBank = 0; + + K052109_irq_enabled = 0; + + return 0; +} + +static INT32 SsridersDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + K053260Reset(0); + + KonamiICReset(); + + EEPROMReset(); + + if (EEPROMAvailable()) { + InitEEPROMCount = 0; + } else { + InitEEPROMCount = 10; + } + + K052109_irq_enabled = 0; + DrvVBlank = 0; + + dim_c = 0; + dim_v = 0; + + return 0; +} + +static INT32 PunkshotDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + K053260Reset(0); + + KonamiICReset(); + + K052109_irq_enabled = 0; + DrvVBlank = 0; + + return 0; +} + +UINT8 __fastcall Tmnt68KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x100000) + K051937ByteRead(0x140000) + K051960ByteRead(0x140400) + + switch (a) { + case 0x0a0001: { + return 0xff - DrvInput[0]; + } + + case 0x0a0003: { + return 0xff - DrvInput[1]; + } + + case 0x0a0005: { + return 0xff - DrvInput[2]; + } + + case 0x0a0007: { + return 0xff - DrvInput[3]; + } + + case 0x0a0011: { + return DrvDip[0]; + } + + case 0x0a0013: { + return DrvDip[1]; + } + + case 0x0a0015: { + return 0xff - DrvInput[4]; + } + + case 0x0a0019: { + return DrvDip[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Tmnt68KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x100000) + K015937ByteWrite(0x140000) + K051960ByteWrite(0x140400) + + switch (a) { + case 0x0a0001: { + static INT32 Last; + if (Last == 0x08 && (d & 0x08) == 0) { + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + } + Last = d & 0x08; + + bIrqEnable = (d & 0x20) ? 1 : 0; + + K052109RMRDLine = d & 0x80; + return; + } + + case 0x0a0009: { + DrvSoundLatch = d; + return; + } + + case 0x0a0011: { + // watchdog write + return; + } + + case 0x0c0001: { + PriorityFlag = (d & 0x0c) >> 2; + return; + } + + case 0x10e801: { + // nop??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Tmnt68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Tmnt68KWriteWord(UINT32 a, UINT16 d) +{ + K051960WordWrite(0x140400) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Mia68KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x100000) + K051937ByteRead(0x140000) + K051960ByteRead(0x140400) + + switch (a) { + case 0x0a0001: { + return 0xff - DrvInput[0]; + } + + case 0x0a0003: { + return 0xff - DrvInput[1]; + } + + case 0x0a0005: { + return 0xff - DrvInput[2]; + } + + case 0x0a0011: { + return DrvDip[0]; + } + + case 0x0a0013: { + return DrvDip[1]; + } + + case 0x0a0019: { + return DrvDip[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Mia68KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x100000) + K015937ByteWrite(0x140000) + K051960ByteWrite(0x140400) + + switch (a) { + case 0x0a0001: { + static INT32 Last; + if (Last == 0x08 && (d & 0x08) == 0) { + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + } + Last = d & 0x08; + + bIrqEnable = (d & 0x20) ? 1 : 0; + + K052109RMRDLine = d & 0x80; + return; + } + + case 0x0a0009: { + DrvSoundLatch = d; + return; + } + + case 0x0a0011: { + // watchdog write + return; + } + + case 0x10e801: { + // nop??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Mia68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Mia68KWriteWord(UINT32 a, UINT16 d) +{ + K051960WordWrite(0x140400) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Cuebrick68KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x100000) + K051937ByteRead(0x140000) + K051960ByteRead(0x140400) + + if (a >= 0x0b0000 && a <= 0x0b03ff) { + return DrvNvRam[(a - 0x0b0000) + (DrvNvRamBank * 0x400)]; + } + + switch (a) { + case 0x0a0001: { + return 0xff - DrvInput[0]; + } + + case 0x0a0003: { + return 0xff - DrvInput[1]; + } + + case 0x0a0005: { + return 0xff - DrvInput[2]; + } + + case 0x0a0011: { + return DrvDip[1]; + } + + case 0x0a0013: { + return DrvDip[0]; + } + + case 0x0a0019: { + return DrvDip[2]; + } + + case 0x0c0000: + return 0xff; + + case 0x0c0002: { + return BurnYM2151ReadStatus(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Cuebrick68KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x100000) + K015937ByteWrite(0x140000) + K051960ByteWrite(0x140400) + + if (a >= 0x0b0000 && a <= 0x0b03ff) { + DrvNvRam[(a - 0x0b0000) + (DrvNvRamBank * 0x400)] = d; + return; + } + + switch (a) { + case 0x0a0001: { + bIrqEnable = (d & 0x20) ? 1 : 0; + + K052109RMRDLine = d & 0x80; + return; + } + + case 0x0a0011: { + // watchdog write + return; + } + + case 0x0b0400: { + DrvNvRamBank = d; + return; + } + + case 0x0c0000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x0c0002: { + BurnYM2151WriteRegister(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Cuebrick68KReadWord(UINT32 a) +{ + if (a >= 0x0b0000 && a <= 0x0b03ff) { + SEK_DEF_READ_WORD(0, a); + return 0; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Cuebrick68KWriteWord(UINT32 a, UINT16 d) +{ + K051960WordWrite(0x140400) + + if (a >= 0x0b0000 && a <= 0x0b03ff) { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Blswhstl68KReadByte(UINT32 a) +{ + if (a >= 0x180000 && a <= 0x183fff) { + INT32 Offset = (a - 0x180000) >> 1; + + if (a & 1) { + return K052109Read(Offset + 0x2000); + } else { + return K052109Read(Offset + 0x0000); + } + } + + if (a >= 0x300000 && a <= 0x303fff) { + INT32 Offset = (a - 0x300000); + + if (Offset & (0x31 << 1)) { + return DrvSpriteRam[Offset ^ 1]; + } else { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + return K053245ReadWord(0, Offset/2) >> ((~a & 1) << 3); + } + } + + if (a >= 0x500000 && a <= 0x50003f) { + INT32 Offset = (a - 0x500000) >> 1; + if (a & 1) { + return K054000Read(Offset); + } else { + return 0; + } + } + + if (a >= 0x680000 && a <= 0x68001f) { + INT32 Offset = (a - 0x680000) >> 1; + Offset &= ~1; + + if (a & 1) { + return K053244Read(0, Offset + 1); + } else { + return K053244Read(0, Offset + 0); + } + } + + switch (a) { + case 0x700001: { + return 0xff - DrvInput[1]; + } + + case 0x700003: { + return 0xff - DrvInput[2]; + } + + case 0x700005: { + UINT8 Res; + static INT32 Toggle; + + Res = 0xff - DrvInput[0]; + + if (InitEEPROMCount) { + InitEEPROMCount--; + Res &= 0xf7; + } + + Toggle ^= 0x40; + + return Res ^ Toggle; + } + + case 0x700007: { + return 0xfe | (EEPROMRead() & 0x01); + } + + case 0x780601: + case 0x780603: { + INT32 Offset = (a - 0x780601) >> 1; + return K053260Read(0, Offset + 2); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Blswhstl68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x180000 && a <= 0x183fff) { + INT32 Offset = (a - 0x180000) >> 1; + + if (a & 1) { + K052109Write(Offset + 0x2000, d); + } else { + K052109Write(Offset + 0x0000, d); + } + return; + } + + if (a >= 0x300000 && a <= 0x303fff) { + INT32 Offset = (a - 0x300000); + DrvSpriteRam[Offset ^ 1] = d; + + if (!(Offset & (0x31 << 1))) { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + + INT32 data = K053245ReadWord(0, Offset/2); + + if (a & 1) { + data &= 0xff00; + data |= d; + } else { + data &= 0x00ff; + data |= d << 8; + } + + K053245WriteWord(0, Offset / 2, data); + } + return; + } + + if (a >= 0x500000 && a <= 0x50003f) { + INT32 Offset = (a - 0x500000) >> 1; + if (a & 1) K054000Write(Offset, d); + return; + } + + if (a >= 0x680000 && a <= 0x68001f) { + INT32 Offset = (a - 0x680000) >> 1; + Offset &= ~1; + + if (a & 1) { + K053244Write(0, Offset + 1, d); + } else { + K053244Write(0, Offset + 0, d); + } + return; + } + + if (a >= 0x780700 && a <= 0x78071f) { + K053251Write((a - 0x780700) >> 1, d); + return; + } + + switch (a) { + case 0x700201: { + EEPROMWrite(d & 0x04, d & 0x02, d & 0x01); + return; + } + + case 0x700301: { + K052109RMRDLine = d & 0x08; + BlswhstlTileRomBank = (d & 0x80) >> 7; + return; + } + + case 0x700401: { + // watchdog write + return; + } + + case 0x780601: { + K053260Write(0, 0, d); + return; + } + + case 0x780605: { + ZetOpen(0); + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Blswhstl68KReadWord(UINT32 a) +{ + if (a >= 0x300000 && a <= 0x303fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0x300000) >> 1; + + if (Offset & 0x31) { + return SpriteRam[Offset]; + } else { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + return K053245ReadWord(0, Offset); + } + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Blswhstl68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x180000 && a <= 0x183fff) { + INT32 Offset = (a - 0x180000) >> 1; + + K052109Write(Offset + 0x2000, d >> 8); + K052109Write(Offset + 0x0000, d & 0xff); + return; + } + + if (a >= 0x300000 && a <= 0x303fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0x300000) >> 1; + SpriteRam[Offset] = d; + + if (!(Offset & 0x0031)) { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + K053245WriteWord(0, Offset, d); + } + return; + } + + if (a >= 0x500000 && a <= 0x50003f) { + INT32 Offset = (a - 0x500000) >> 1; + K054000Write(Offset, d & 0xff); + return; + } + + if (a >= 0x680000 && a <= 0x68001f) { + INT32 Offset = (a - 0x680000) >> 1; + Offset &= ~1; + + K053244Write(0, Offset + 1, d & 0xff); + K053244Write(0, Offset + 0, d >> 8); + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +static void tmnt2_protection_write() +{ + UINT32 src_addr, dst_addr, mod_addr, attr1, code, attr2, cbase, cmod, color; + INT32 xoffs, yoffs, xmod, ymod, zmod, xzoom, yzoom, i; + UINT16 *mcu; + UINT16 src[4], mod[24]; + UINT8 keepaspect, xlock, ylock, zlock; + + mcu = (UINT16*)(Drv68KRam + 0x4800); + if ((mcu[8] & 0xff00) != 0x8200) return; + + src_addr = (mcu[0] | (mcu[1]&0xff)<<16) >> 1; + dst_addr = (mcu[2] | (mcu[3]&0xff)<<16) >> 1; + mod_addr = (mcu[4] | (mcu[5]&0xff)<<16) >> 1; + zlock = (mcu[8] & 0xff) == 0x0001; + + for (i=0; i< 4; i++) src[i] = SekReadWord((src_addr + i) * 2); + for (i=0; i<24; i++) mod[i] = SekReadWord((mod_addr + i) * 2); + + code = src[0]; // code + + i= src[1]; + attr1 = i>>2 & 0x3f00; // flip y, flip x and sprite size + attr2 = i & 0x380; // mirror y, mirror x, shadow + cbase = i & 0x01f; // base color + cmod = mod[0x2a/2]>>8; + color = (cbase != 0x0f && cmod <= 0x1f && !zlock) ? cmod : cbase; + + xoffs = (INT16)src[2]; // local x + yoffs = (INT16)src[3]; // local y + + i = mod[0]; + attr2 |= i & 0x0060; // priority + keepaspect = (i & 0x0014) == 0x0014; + if (i & 0x8000) { attr1 |= 0x8000; } // active + if (keepaspect) { attr1 |= 0x4000; } // keep aspect + if (i & 0x4000) { attr1 ^= 0x1000; xoffs = -xoffs; } // flip x + + xmod = (INT16)mod[6]; // global x + ymod = (INT16)mod[7]; // global y + zmod = (INT16)mod[8]; // global z + xzoom = mod[0x1c/2]; + yzoom = (keepaspect) ? xzoom : mod[0x1e/2]; + + ylock = xlock = (i & 0x0020 && (!xzoom || xzoom == 0x100)); + + if (!xlock) + { + i = xzoom - 0x4f00; + if (i > 0) + { + i >>= 8; + xoffs += (INT32)(pow(i, /*1.898461*/1.891292) * xoffs / 599.250121); + } + else if (i < 0) + { + i = (i>>3) + (i>>4) + (i>>5) + (i>>6) + xzoom; + xoffs = (i > 0) ? (xoffs * i / 0x4f00) : 0; + } + } + if (!ylock) + { + i = yzoom - 0x4f00; + if (i > 0) + { + i >>= 8; + yoffs += (INT32)(pow(i, /*1.898461*/1.891292) * yoffs / 599.250121); + } + else if (i < 0) + { + i = (i>>3) + (i>>4) + (i>>5) + (i>>6) + yzoom; + yoffs = (i > 0) ? (yoffs * i / 0x4f00) : 0; + } + + } + if (!zlock) yoffs += zmod; + xoffs += xmod; + yoffs += ymod; + + SekWriteWord((dst_addr + 0) * 2, attr1); + SekWriteWord((dst_addr + 2) * 2, code); + SekWriteWord((dst_addr + 4) * 2, (UINT32)yoffs); + SekWriteWord((dst_addr + 6) * 2, (UINT32)xoffs); + SekWriteWord((dst_addr + 12) * 2, attr2 | color); +} + +void __fastcall Tmnt268KProtWord(UINT32 a, UINT16 d) +{ + *((UINT16*)(Drv68KRam + 0x4800 + (a & 0x1e))) = d; +} + +void __fastcall Tmnt268KProtByte(UINT32 a, UINT8 d) +{ + a &= 0x1f; + Drv68KRam[0x4801 ^ a] = d; + + if (a == 0x18) tmnt2_protection_write(); +} + +static UINT16 ssriders_protection_r() +{ + INT32 data = SekReadWord(0x105a0a); + INT32 cmd = SekReadWord(0x1058fc); + + switch (cmd) + { + case 0x100b: + return 0x0064; + + case 0x6003: + return data & 0x000f; + + case 0x6004: + return data & 0x001f; + + case 0x6000: + return data & 0x0001; + + case 0x0000: + return data & 0x00ff; + + case 0x6007: + return data & 0x00ff; + + case 0x8abc: + /* collision table */ + data = -SekReadWord(0x105818); + data = ((data / 8 - 4) & 0x1f) * 0x40; + data += ((SekReadWord(0x105cb0) + + 256*K052109Read(0x1a01) + K052109Read(0x1a00) - 6) / 8 + 12) & 0x3f; + return data; + + default: + return 0xffff; + } +} + +static void ssriders_protection_w(INT32 offset) +{ + offset >>= 1; + + if (offset == 1) + { + INT32 logical_pri,hardware_pri; + + /* create sprite priority attributes */ + hardware_pri = 1; + for (logical_pri = 1;logical_pri < 0x100;logical_pri <<= 1) + { + INT32 i; + + for (i = 0;i < 128;i++) + { + if ((SekReadWord(0x180006 + 128*i) >> 8) == (UINT16)logical_pri) + { + K053245Write(0,((8*i) * 2)+1,hardware_pri); + hardware_pri++; + } + } + } + } +} + +UINT8 __fastcall Ssriders68KReadByte(UINT32 a) +{ + if (a >= 0x180000 && a <= 0x183fff) { + INT32 Offset = (a - 0x180000); + + if (Offset & (0x31 << 1)) { + return DrvSpriteRam[Offset ^ 1]; + } else { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + return K053245ReadWord(0, Offset / 2) >> ((~a & 1) << 3); + } + } + + if ((a & 0xffff80) == 0x1c0500) { + return Drv68KRam[0x4001 ^ (a & 0x7f)]; + } + + if (a >= 0x5a0000 && a <= 0x5a001f) { + INT32 Offset = (a - 0x5a0000) >> 1; + Offset &= ~1; + + if (a & 1) { + return K053244Read(0, Offset + 1); + } else { + return K053244Read(0, Offset + 0); + } + } + + if (a >= 0x600000 && a <= 0x603fff) { + INT32 Offset = (a - 0x600000) >> 1; + + if (a & 1) { + return K052109Read(Offset + 0x2000); + } else { + return K052109Read(Offset + 0x0000); + } + } + + switch (a) { + case 0x1c0800: + case 0x1c0801: + return ssriders_protection_r() >> ((~a & 1) << 3); + + case 0x1c0001: { + return 0xff - DrvInput[1]; + } + + case 0x1c0003: { + return 0xff - DrvInput[2]; + } + + case 0x1c0005: { + return 0xff - DrvInput[3]; + } + + case 0x1c0007: { + return 0xff - DrvInput[4]; + } + + case 0x1c0101: { + return 0xff - DrvInput[0]; + } + + case 0x1c0103: { + UINT8 Res; + static INT32 Toggle; + + Res = DrvInput[5]; + if (DrvVBlank) Res |= 0x08; + Res |= EEPROMRead() & 0x01; + + if (InitEEPROMCount) { + InitEEPROMCount--; + Res &= 0x7f; + } + + Toggle ^= 0x04; + + return Res ^ Toggle; + } + + case 0x1c0401: { + // watchdog read + return 0; + } + + case 0x5c0601: + case 0x5c0603: { + INT32 Offset = (a - 0x5c0601) >> 1; + return K053260Read(0, Offset + 2); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ssriders68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x180000 && a <= 0x183fff) { + INT32 Offset = (a - 0x180000); + DrvSpriteRam[Offset ^ 1] = d; + + if (!(Offset & (0x31 << 1))) { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + + INT32 data = K053245ReadWord(0, Offset/2); + + if (a & 1) { + data &= 0xff00; + data |= d; + } else { + data &= 0x00ff; + data |= d << 8; + } + + K053245WriteWord(0, Offset/2, data); + + } + return; + } + + if ((a & ~3) == 0x1c0800) { + bprintf (0, _T("protection write byte %x %x\n"), a, d); + return; + } + + // extra ram for tmnt2 + if ((a & 0xffff80) == 0x1c0500) { + Drv68KRam[0x4001 ^ (a & 0x7f)] = d; + //*((UINT16*)(Drv68KRam + 0x4000 + (a & 0x7e))) = d; + return; + } + + if (a >= 0x5a0000 && a <= 0x5a001f) { + INT32 Offset = (a - 0x5a0000) >> 1; + Offset &= ~1; + + K053244Write(0, Offset + 1, d & 0xff); + K053244Write(0, Offset + 0, d >> 8); + return; + } + + if (a >= 0x5c0700 && a <= 0x5c071f) { + K053251Write((a - 0x5c0700) >> 1, d); + return; + } + + if (a >= 0x600000 && a <= 0x603fff) { + INT32 Offset = (a - 0x600000) >> 1; + + if (a & 1) { + K052109Write(Offset + 0x2000, d); + } else { + K052109Write(Offset + 0x0000, d); + } + return; + } + + switch (a) { + case 0x1c0201: { + EEPROMWrite(d & 0x04, d & 0x02, d & 0x01); + K053244BankSelect(0, ((d & 0x20) >> 5) << 2); + dim_c = d & 0x18; + return; + } + + case 0x1c0301: { + K052109RMRDLine = d & 0x08; + dim_v = (d & 0x70) >> 4; + return; + } + + case 0x5c0601: { + K053260Write(0, 0, d); + return; + } + + case 0x5c0605: { + ZetOpen(0); + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0x1c0401: { + // watchdog write + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ssriders68KReadWord(UINT32 a) +{ + if (a >= 0x180000 && a <= 0x183fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0x180000) >> 1; + + if (Offset & 0x31) { + return SpriteRam[Offset]; + } else { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + return K053245ReadWord(0, Offset); + } + } + + if ((a & 0xffff80) == 0x1c0500) { + return *((UINT16*)(Drv68KRam + 0x4000 + (a & 0x7e))); + } + + if (a == 0x1c0800) return ssriders_protection_r(); + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ssriders68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x180000 && a <= 0x183fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0x180000) >> 1; + SpriteRam[Offset] = d; + + if (!(Offset & 0x0031)) { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + K053245WriteWord(0, Offset, d); + } + return; + } + + if (a >= 0x5a0000 && a <= 0x5a001f) { + INT32 Offset = (a - 0x5a0000) >> 1; + Offset &= ~1; + + K053244Write(0, Offset + 1, d & 0xff); + K053244Write(0, Offset + 0, d >> 8); + return; + } + + if ((a & 0xffff80) == 0x1c0500) { + *((UINT16*)(Drv68KRam + 0x4000 + (a & 0x7e))) = d; + return; + } + + if (a == 0x1c0802) { + ssriders_protection_w(2); + return; + } + + switch (a) { + case 0x1c0800: + case 0x1c0802: { + ssriders_protection_w(a - 0x1c0800); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Thndrx268KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x600000) + K051937ByteRead(0x700000) + + if ((a & 0xffffc00) == 0x700400) { + return K051960Read(a & 0x3ff); + } + + if (a >= 0x500000 && a <= 0x50003f) { + INT32 Offset = (a - 0x500000) >> 1; + if (a & 1) { + return K054000Read(Offset); + } else { + return 0; + } + } + + switch (a) + { + case 0x400001: + case 0x400003: + return K053260Read(0, ((a & 2) >> 1) + 2); + + case 0x500200: + { + INT32 ret = DrvInput[1]^0xff; + if (InitEEPROMCount) { + ret &= 0xf7; + InitEEPROMCount--; + } + return ret; + } + + case 0x500201: + return DrvInput[0]^0xff; + + case 0x500202: + { + static INT32 toggle; + toggle ^= 0x08; + INT32 ret = 0xfe; + ret |= (EEPROMRead() & 1); + ret ^= toggle; + + return ret; + } + + case 0x500203: + return DrvInput[2]^0xff; + } + + + return 0; +} + +void __fastcall Thndrx268KWriteWord(UINT32 a, UINT16 d) +{ + if ((a & 0xffffc00) == 0x700400) { + K051960Write((a & 0x3fe) | 0, d >> 8); + K051960Write((a & 0x3fe) | 1, d & 0xff); + return; + } +} + +void __fastcall Thndrx268KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x600000) + K015937ByteWrite(0x700000) + + if ((a & 0xffffc00) == 0x700400) { + K051960Write(a & 0x3ff, d); + return; + } + + if (a >= 0x300000 && a <= 0x30001f) { + if (a & 1) K053251Write((a - 0x300000) >> 1, d); + return; + } + + if (a >= 0x500000 && a <= 0x50003f) { + INT32 Offset = (a - 0x500000) >> 1; + if (a & 1) K054000Write(Offset, d); + return; + } + + switch (a) + { + case 0x400001: + K053260Write(0, 0, d); + return; + + case 0x500101: + { + EEPROMWriteBit(d & 0x01); + EEPROMSetCSLine((d & 0x02) ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE); + EEPROMSetClockLine((d & 0x04) ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE); + + // EEPROMWrite(d & 0x04, d & 0x02, d & 0x01); + + static INT32 last; + if (last == 0 && (d & 0x20) != 0) { + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + last = d & 0x20; + + K052109RMRDLine = d & 0x40; + } + return; + } +} + +UINT16 __fastcall Lgtnfght68KReadWord(UINT32 a) +{ + if (a >= 0xb0000 && a <= 0xb3fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0xb0000) >> 1; + + if (Offset & 0x31) { + return SpriteRam[Offset]; + } else { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + return K053245ReadWord(0, Offset); + } + } + + return 0; +} + +UINT8 __fastcall Lgtnfght68KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x100000) + + if (a >= 0xb0000 && a <= 0xb3fff) { + INT32 Offset = (a - 0xb0000); + + if (Offset & (0x31 << 1)) { + return DrvSpriteRam[Offset ^ 1]; + } else { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + return K053245ReadWord(0, Offset / 2) >> ((~a & 1) << 3); + } + } + + if (a >= 0xc0000 && a <= 0xc001f) { + INT32 Offset = (a - 0xc0000) >> 1; + Offset &= ~1; + + if (a & 1) { + return K053244Read(0, Offset + 1); + } else { + return K053244Read(0, Offset + 0); + } + } + + switch (a) + { + case 0x0a0001: + return ~DrvInput[0] & 0xfb; + + case 0x0a0003: + return ~DrvInput[1]; + + case 0x0a0005: + return ~DrvInput[2]; + + case 0x0a0007: + return DrvDip[0]; + + case 0x0a0009: + return DrvDip[1]; + + case 0x0a0011: + return DrvDip[2]; + + case 0x0a0021: + case 0x0a0023: + return K053260Read(0, ((a & 2) >> 1) + 2); // k053260 + } + + return 0; +} + +void __fastcall Lgtnfght68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0xb0000 && a <= 0xb3fff) { + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + INT32 Offset = (a - 0xb0000) >> 1; + SpriteRam[Offset] = d; + + if (!(Offset & 0x0031)) { + Offset = ((Offset & 0x000e) >> 1) | ((Offset & 0x1fc0) >> 3); + K053245WriteWord(0, Offset, d); + } + return; + } +} + +void __fastcall Lgtnfght68KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x100000) + + if (a >= 0x0e0000 && a <= 0x0e001f) { + K053251Write((a - 0x0e0000) >> 1, d); + return; + } + + if (a >= 0xb0000 && a <= 0xb3fff) { + INT32 Offset = (a - 0xb0000); + DrvSpriteRam[Offset ^ 1] = d; + + if (!(Offset & (0x31 << 1))) { + Offset = ((Offset & (0x000e << 1)) >> 1) | ((Offset & (0x1fc0 << 1)) >> 3); + + INT32 data = K053245ReadWord(0, Offset/2); + + if (a & 1) { + data &= 0xff00; + data |= d; + } else { + data &= 0x00ff; + data |= d << 8; + } + + K053245WriteWord(0, Offset/2, data); + + } + return; + } + + if (a >= 0xc0000 && a <= 0xc001f) { + INT32 Offset = (a - 0xc0000) >> 1; + Offset &= ~1; + + K053244Write(0, Offset + 1, d & 0xff); + K053244Write(0, Offset + 0, d >> 8); + return; + } + + switch (a) + { + case 0xa0019: + { + static INT32 last; + if (last == 0 && (d & 0x4) != 0) { + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + last = d & 0x4; + + K052109RMRDLine = d & 0x8; + } + return; + + case 0xa0021: + K053260Write(0, 0, d); + return; + + case 0xa0029: // watchdog + return; + } +} + +UINT16 __fastcall Punkshot68KReadWord(UINT32 a) +{ + if ((a & 0xfffc00) == 0x110400) { + return K051960Read((a & 0x3fe) | 1) | (K051960Read((a & 0x3fe) | 0) << 8); + } + + return 0; +} + +UINT8 __fastcall Punkshot68KReadByte(UINT32 a) +{ + K052109WordNoA12Read(0x100000) + K051937ByteRead(0x110000) + K051960ByteRead(0x110400) + + switch (a) + { + case 0x0a0000: + return DrvDip[1]; + + case 0x0a0001: + return DrvDip[0]; + + case 0x0a0003: + return ~DrvInput[0]; + + case 0x0a0002: + return DrvDip[2] | (~DrvInput[5] & 0x0f); + + case 0x0a0005: + return ~DrvInput[3]; + + case 0x0a0004: + return ~DrvInput[4]; + + case 0x0a0007: + return ~DrvInput[1]; + + case 0x0a0006: + return ~DrvInput[2]; + + case 0x0a0041: + case 0x0a0043: + return K053260Read(0, ((a & 2) >> 1) | 2); + + case 0xfffffc: + case 0xfffffd: + case 0xfffffe: + case 0xffffff: + return rand(); + } + + return 0; +} + +void __fastcall Punkshot68KWriteWord(UINT32 a, UINT16 d) +{ + if ((a & 0xfffc00) == 0x110400) { + K051960Write((a & 0x3fe) | 0, d >> 8); + K051960Write((a & 0x3fe) | 1, d & 0xff); + + return; + } + + if ((a & 0xff8000) == 0x100000) { + SekWriteByte(a+1, d & 0xff); + return; + } +} + +void __fastcall Punkshot68KWriteByte(UINT32 a, UINT8 d) +{ + K052109WordNoA12Write(0x100000) + K015937ByteWrite(0x110000) + K051960ByteWrite(0x110400) + + if ((a & 0xffffe1) == 0xa0061) { + K053251Write((a & 0x1f) >> 1, d); + return; + } + + switch (a) + { + case 0x0a0020: + case 0x0a0021: + { + static INT32 last; + K052109RMRDLine = d & 0x08; + + if (last == 0x04 && (d & 0x04) == 0x00) { + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + + last = d & 0x04; + } + return; + + case 0x0a0041: + K053260Write(0, 0, d); + return; + + case 0x0a0081: + // watchdog + return; + } +} + +UINT8 __fastcall TmntZ80Read(UINT16 a) +{ + if (a >= 0xb000 && a <= 0xb00d) { + return K007232ReadReg(0, a - 0xb000); + } + + switch (a) { + case 0x9000: { + return TitleSoundLatch; + } + + case 0xa000: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + case 0xc001: { + return BurnYM2151ReadStatus(); + } + + case 0xf000: { + return UPD7759BusyRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TmntZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xb000 && a <= 0xb00d) { + K007232WriteReg(0, (a - 0xb000), d); + return; + } + + switch (a) { + case 0x9000: { + TitleSoundLatch = d; + if (d & 0x04) { + PlayTitleSample = 1; + } else { + PlayTitleSample = 0; + TitleSamplePos = 0; + } + + UPD7759ResetWrite(0, d & 2); + return; + } + + case 0xc000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xc001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xd000: { + UPD7759PortWrite(0, d); + return; + } + + case 0xe000: { + UPD7759StartWrite(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MiaZ80Read(UINT16 a) +{ + if (a >= 0xb000 && a <= 0xb00d) { + return K007232ReadReg(0, a - 0xb000); + } + + switch (a) { + case 0xa000: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + case 0xc001: { + return BurnYM2151ReadStatus(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall MiaZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xb000 && a <= 0xb00d) { + K007232WriteReg(0, (a - 0xb000), d); + return; + } + + switch (a) { + case 0xc000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xc001: { + BurnYM2151WriteRegister(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall BlswhstlZ80Read(UINT16 a) +{ + if (a >= 0xfa00 && a <= 0xfa2f) { + if (a == 0xfa00) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return K053260Read(0, a - 0xfa00); + } + + switch (a) { + case 0xf801: { + return BurnYM2151ReadStatus(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall BlswhstlZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xfa00 && a <= 0xfa2f) { + K053260Write(0, (a - 0xfa00), d); + return; + } + + switch (a) { + case 0xf800: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xf801: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xfc00: { // tmnt2 needs this + ZetRun(100); + ZetNmi(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall Thndrx2Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xfc00 && a <= 0xfc2f) { + K053260Write(0, (a - 0xfc00), d); + return; + } + + switch (a) + { + case 0xf800: + case 0xf810: + BurnYM2151SelectRegister(d); + return; + + case 0xf801: + case 0xf811: + BurnYM2151WriteRegister(d); + return; + + case 0xfa00: + ZetRun(100); + ZetNmi(); + return; + } +} + +UINT8 __fastcall Thndrx2Z80Read(UINT16 a) +{ + if (a >= 0xfc00 && a <= 0xfc2f) { + if (a == 0xfc00) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return K053260Read(0, a - 0xfc00); + } + + switch (a) + { + case 0xf801: + case 0xf811: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +void __fastcall LgtnfghtZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xc000 && a <= 0xc02f) { + K053260Write(0, (a - 0xc000), d); + return; + } + + switch (a) + { + case 0xa000: + BurnYM2151SelectRegister(d); + return; + + case 0xa001: + BurnYM2151WriteRegister(d); + return; + } +} + +UINT8 __fastcall LgtnfghtZ80Read(UINT16 a) +{ + if (a >= 0xc000 && a <= 0xc02f) { + if (a == 0xc000) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return K053260Read(0, a - 0xc000); + } + + switch (a) + { + case 0xa001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void shuffle(UINT16 *buf, INT32 len) +{ + INT32 i; + UINT16 t; + + if (len == 2) return; + + if (len % 4) return; + + len /= 2; + + for (i = 0;i < len/2;i++) { + t = buf[len/2 + i]; + buf[len/2 + i] = buf[len + i]; + buf[len + i] = t; + } + + shuffle(buf,len); + shuffle(buf + len,len); +} + +static void byte_shuffle(UINT8 *buf, INT32 len) +{ + INT32 i; + UINT8 t; + + if (len == 2) return; + + if (len % 4) return; + + len /= 2; + + for (i = 0;i < len/2;i++) { + t = buf[len/2 + i]; + buf[len/2 + i] = buf[len + i]; + buf[len + i] = t; + } + + byte_shuffle(buf,len); + byte_shuffle(buf + len,len); +} + +static void TmntUnscrambleGfx(UINT8 *pSrc, INT32 nLength) +{ + INT32 bits[32]; + for (INT32 i = 0; i < nLength; i += 4) { + for (INT32 j = 0; j < 4; j++) { + for (INT32 k = 0; k < 8; k++) { + bits[8*j + k] = (pSrc[i + j] >> k) & 1; + } + } + + for (INT32 j = 0; j < 4; j++) { + pSrc[i + j] = 0; + for (INT32 k = 0; k < 8; k++) { + pSrc[i + j] |= bits[j + 4*k] << k; + } + } + } +} + +static void TmntUnscrambleSprites() +{ + BurnLoadRom(DrvTempRom + 0x200000, 11, 1); + UINT8 *SpriteConvTable = DrvTempRom + 0x200000; + + memcpy(DrvTempRom, DrvSpriteRom, 0x200000); + + for (INT32 A = 0; A < 0x80000; A++) { + INT32 B, i, entry; + INT32 bits[10]; + + static const UINT8 bit_pick_table[10][8] = { + { 3, 3, 3, 3, 3, 3, 3, 3 }, + { 0, 0, 5, 5, 5, 5, 5, 5 }, + { 1, 1, 0, 0, 0, 7, 7, 7 }, + { 2, 2, 1, 1, 1, 0, 0, 9 }, + { 4, 4, 2, 2, 2, 1, 1, 0 }, + { 5, 6, 4, 4, 4, 2, 2, 1 }, + { 6, 5, 6, 6, 6, 4, 4, 2 }, + { 7, 7, 7, 7, 8, 6, 6, 4 }, + { 8, 8, 8, 8, 7, 8, 8, 6 }, + { 9, 9, 9, 9, 9, 9, 9, 8 } + }; + + entry = SpriteConvTable[(A & 0x7f800) >> 11] & 7; + + for (i = 0;i < 10;i++) + bits[i] = (A >> i) & 0x01; + + B = A & 0x7fc00; + + for (i = 0; i < 10;i++) B |= bits[bit_pick_table[i][entry]] << i; + + DrvSpriteRom[4*A+0] = DrvTempRom[4*B+0]; + DrvSpriteRom[4*A+1] = DrvTempRom[4*B+1]; + DrvSpriteRom[4*A+2] = DrvTempRom[4*B+2]; + DrvSpriteRom[4*A+3] = DrvTempRom[4*B+3]; + } +} + +static void MiaUnscrambleSprites() +{ + memcpy(DrvTempRom, DrvSpriteRom, 0x100000); + + for (INT32 A = 0; A < 0x40000; A++) { + INT32 B, i; + INT32 bits[8]; + for (i = 0; i < 8; i++) bits[i] = (A >> i) & 0x01; + + B = A & 0x3ff00; + + if ((A & 0x3c000) == 0x3c000) { + B |= bits[3] << 0; + B |= bits[5] << 1; + B |= bits[0] << 2; + B |= bits[1] << 3; + B |= bits[2] << 4; + B |= bits[4] << 5; + B |= bits[6] << 6; + B |= bits[7] << 7; + } else { + B |= bits[3] << 0; + B |= bits[5] << 1; + B |= bits[7] << 2; + B |= bits[0] << 3; + B |= bits[1] << 4; + B |= bits[2] << 5; + B |= bits[4] << 6; + B |= bits[6] << 7; + } + + DrvSpriteRom[4*A+0] = DrvTempRom[4*B+0]; + DrvSpriteRom[4*A+1] = DrvTempRom[4*B+1]; + DrvSpriteRom[4*A+2] = DrvTempRom[4*B+2]; + DrvSpriteRom[4*A+3] = DrvTempRom[4*B+3]; + } +} + +static void TmntDecodeTitleSample() +{ + for (INT32 i = 0; i < 0x40000; i++) { + INT32 val = DrvTempRom[2 * i + 0] + (DrvTempRom[(2 * i) + 1] << 8); + INT32 expo = val >> 13; + + val = (val >> 3) & (0x3ff); + val -= 0x200; + + val <<= (expo-3); + + DrvTitleSample[i] = val; + } +} + +static INT32 TilePlaneOffsets[4] = { 24, 16, 8, 0 }; +static INT32 TileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TileYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 24, 16, 8, 0 }; +static INT32 SpritePlaneOffsets2[4] = { 0, 8, 16, 24 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 256, 257, 258, 259, 260, 261, 262, 263 }; +static INT32 SpriteYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; + +static void K052109TmntCallback(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32* /*xFlip*/, INT32 *) +{ + *Code |= ((*Colour & 0x03) << 8) | ((*Colour & 0x10) << 6) | ((*Colour & 0x0c) << 9) | (Bank << 13); + *Colour = LayerColourBase[Layer] + ((*Colour & 0xe0) >> 5); +} + +static void K052109MiaCallback(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *) +{ + *xFlip = *Colour & 0x04; + + if (Layer == 0) { + *Code |= ((*Colour & 0x01) << 8); + *Colour = LayerColourBase[Layer] + ((*Colour & 0x80) >> 5) + ((*Colour & 0x10) >> 1); + } else { + *Code |= ((*Colour & 0x01) << 8) | ((*Colour & 0x18) << 6) | (Bank << 11); + *Colour = LayerColourBase[Layer] + ((*Colour & 0xe0) >> 5); + } +} + +static void K052109CuebrickCallback(INT32 Layer, INT32 /*Bank*/, INT32 *Code, INT32 *Colour, INT32 */*xFlip*/, INT32 *) +{ + if (K052109RMRDLine == 0 && Layer == 0) { + *Code |= ((*Colour & 0x01) << 8); + *Colour = LayerColourBase[Layer] + ((*Colour & 0x80) >> 5) + ((*Colour & 0x10) >> 1); + } else { + *Code |= ((*Colour & 0x0f) << 8); + *Colour = LayerColourBase[Layer] + ((*Colour & 0xe0) >> 5); + } +} + +static void K052109BlswhstlCallback(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 */*Flags*/, INT32 */*Priority*/) +{ + *Code |= ((*Colour & 0x01) << 8) | ((*Colour & 0x10) << 5) | ((*Colour & 0x0c) << 8) | (Bank << 12) | (BlswhstlTileRomBank << 14); + *Colour = LayerColourBase[Layer] + ((*Colour & 0xe0) >> 5); +} + +static void K051960TmntCallback(INT32 *Code, INT32 *Colour, INT32* /*Priority*/, INT32* /*Shadow*/) +{ + *Code |= (*Colour & 0x10) << 9; + *Colour = SpriteColourBase + (*Colour & 0x0f); +} + +static void K051960MiaCallback(INT32* /*Code*/, INT32 *Colour, INT32* /*Priority*/, INT32* /*Shadow*/) +{ + *Colour = SpriteColourBase + (*Colour & 0x0f); +} + +static void K051960CuebrickCallback(INT32* Code, INT32 *Colour, INT32* /*Priority*/, INT32* /*Shadow*/) +{ + *Colour = SpriteColourBase + (*Colour & 0x0f); + *Code &= 0xfff; +} + +static void K051960Thndrx2Callback(INT32* code, INT32 *color, INT32* priority, INT32* /*shadow*/) +{ + INT32 pri = 0x20 | ((*color & 0x60) >> 2); + if (pri <= LayerPri[2]) *priority = 0; + else if (pri > LayerPri[2] && pri <= LayerPri[1]) *priority = 1; + else if (pri > LayerPri[1] && pri <= LayerPri[0]) *priority = 2; + else *priority = 3; + + *code &= 0x1fff; + *color = SpriteColourBase + (*color & 0x0f); +} + +static void K051960PunkshotCallback(INT32 *code, INT32 *color, INT32 *priority, INT32 *) +{ + INT32 pri = 0x20 | ((*color & 0x60) >> 2); + if (pri <= LayerPri[2]) *priority = 0; + else if (pri > LayerPri[2] && pri <= LayerPri[1]) *priority = 1; + else if (pri > LayerPri[1] && pri <= LayerPri[0]) *priority = 2; + else *priority = 3; + + *code |= (*color & 0x10) << 9; + *code &= 0x3fff; + *color = SpriteColourBase + (*color & 0x0f); +} + +static void K053245BlswhstlCallback(INT32 *Code, INT32 *Colour, INT32 *Priority) +{ + INT32 Pri = 0x20 | ((*Colour & 0x60) >> 2); + if (Pri <= LayerPri[2]) *Priority = 0; + else if (Pri > LayerPri[2] && Pri <= LayerPri[1]) *Priority = 1; + else if (Pri > LayerPri[1] && Pri <= LayerPri[0]) *Priority = 2; + else *Priority = 3; + + *Code &= 0x1fff; + *Colour = SpriteColourBase + (*Colour & 0x1f); +} + +static void K053245SsridersCallback(INT32 */*Code*/, INT32 *Colour, INT32 *Priority) +{ + INT32 Pri = 0x20 | ((*Colour & 0x60) >> 2); + if (Pri <= LayerPri[2]) *Priority = 0; + else if (Pri > LayerPri[2] && Pri <= LayerPri[1]) *Priority = 1; + else if (Pri > LayerPri[1] && Pri <= LayerPri[0]) *Priority = 2; + else *Priority = 3; + + *Colour = SpriteColourBase + (*Colour & 0x1f); +} + +static void K053245LgtnfghtCallback(INT32 *code, INT32 *color, INT32 *priority) +{ + INT32 pri = 0x20 | ((*color & 0x60) >> 2); + if (pri <= LayerPri[2]) *priority = 0; + else if (pri > LayerPri[2] && pri <= LayerPri[1]) *priority = 1; + else if (pri > LayerPri[1] && pri <= LayerPri[0]) *priority = 2; + else *priority = 3; + + *color = SpriteColourBase + (*color & 0x1f); + *code &= 0x3fff; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static void CuebrickYM2151IrqHandler(INT32 Irq) +{ + CuebrickSndIrqFire = Irq; +} + +static INT32 TmntInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + TmntMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + TmntMemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K051960Init(DrvSpriteRom, 0x1fffff); + K051960SetCallback(K051960TmntCallback); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 6, 1); if (nRet != 0) return 1; + shuffle((UINT16*)DrvTileRom, 0x080000); + TmntUnscrambleGfx(DrvTileRom, 0x100000); + GfxDecode(0x100000 / 32, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + DrvTempRom = (UINT8 *)malloc(0x200100); + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x080000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x100000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x180000, 10, 1); if (nRet != 0) return 1; + shuffle((UINT16*)DrvSpriteRom, 0x100000); + TmntUnscrambleGfx(DrvSpriteRom, 0x200000); + TmntUnscrambleSprites(); + + // Decode the sprites + GfxDecode(0x200000 / 128, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x400, DrvSpriteRom, DrvSprites); + + // Load K007232 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 13, 1); if (nRet != 0) return 1; + + // Load UPD7759C Sample Roms + nRet = BurnLoadRom(DrvUPD7759CRom + 0x00000, 14, 1); if (nRet != 0) return 1; + + // Load title sample + memset(DrvTempRom, 0, 0x080000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + TmntDecodeTitleSample(); + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x080000, 0x080fff, SM_RAM); + SekSetReadWordHandler(0, Tmnt68KReadWord); + SekSetWriteWordHandler(0, Tmnt68KWriteWord); + SekSetReadByteHandler(0, Tmnt68KReadByte); + SekSetWriteByteHandler(0, Tmnt68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(TmntZ80Read); + ZetSetWriteHandler(TmntZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K007232Init(0, 3579545, DrvSoundRom, 0x20000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvUPD7759CRom); + + GenericTilesInit(); + + LayerColourBase[0] = 0; + LayerColourBase[1] = 32; + LayerColourBase[2] = 40; + SpriteColourBase = 16; + + // Reset the driver + TmntDoReset(); + + return 0; +} + +static INT32 MiaInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MiaMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MiaMemIndex(); + + K052109Init(DrvTileRom, 0x03ffff); + K052109SetCallback(K052109MiaCallback); + K051960Init(DrvSpriteRom, 0x0fffff); + K051960SetCallback(K051960MiaCallback); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x000001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x020000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x020001, 6, 2); if (nRet != 0) return 1; + shuffle((UINT16*)DrvTileRom, 0x020000); + TmntUnscrambleGfx(DrvTileRom, 0x040000); + GfxDecode(0x2000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + DrvTempRom = (UINT8 *)malloc(0x100000); + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x080000, 8, 1); if (nRet != 0) return 1; + shuffle((UINT16*)DrvSpriteRom, 0x080000); + TmntUnscrambleGfx(DrvSpriteRom, 0x100000); + MiaUnscrambleSprites(); + + // Decode the sprites + GfxDecode(0x2000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x400, DrvSpriteRom, DrvSprites); + + // Load K007232 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 10, 1); if (nRet != 0) return 1; + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRam + 0x0000 , 0x040000, 0x043fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x080000, 0x080fff, SM_RAM); + SekSetReadWordHandler(0, Mia68KReadWord); + SekSetWriteWordHandler(0, Mia68KWriteWord); + SekSetReadByteHandler(0, Mia68KReadByte); + SekSetWriteByteHandler(0, Mia68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(MiaZ80Read); + ZetSetWriteHandler(MiaZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K007232Init(0, 3579545, DrvSoundRom, 0x20000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + GenericTilesInit(); + + LayerColourBase[0] = 0; + LayerColourBase[1] = 32; + LayerColourBase[2] = 40; + SpriteColourBase = 16; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 CuebrickInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + CuebrickMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + CuebrickMemIndex(); + + K052109Init(DrvTileRom, 0x03ffff); + K052109SetCallback(K052109CuebrickCallback); + + K051960Init(DrvSpriteRom, 0x03ffff); + K051960SetCallback(K051960CuebrickCallback); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x000001, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x020000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x020001, 5, 2); if (nRet != 0) return 1; + byte_shuffle(DrvTileRom, 0x040000); + GfxDecode(0x2000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x020000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x020001, 9, 2); if (nRet != 0) return 1; + byte_shuffle(DrvSpriteRom, 0x040000); + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x400, DrvSpriteRom, DrvSprites); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Drv68KRam + 0x0000 , 0x040000, 0x043fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x080000, 0x080fff, SM_RAM); + SekSetReadWordHandler(0, Cuebrick68KReadWord); + SekSetWriteWordHandler(0, Cuebrick68KWriteWord); + SekSetReadByteHandler(0, Cuebrick68KReadByte); + SekSetWriteByteHandler(0, Cuebrick68KWriteByte); + SekClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&CuebrickYM2151IrqHandler); + + GenericTilesInit(); + + LayerColourBase[0] = 0; + LayerColourBase[1] = 32; + LayerColourBase[2] = 40; + SpriteColourBase = 16; + + // Reset the driver + CuebrickDoReset(); + + return 0; +} + +static INT32 BlswhstlInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + BlswhstlMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + BlswhstlMemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109BlswhstlCallback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvSpriteRom, 0xfffff, K053245BlswhstlCallback); + K053245SetSpriteOffset(0, -112, 16); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 6, 1); if (nRet != 0) return 1; + BurnByteswap(DrvTileRom, 0x100000); + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x080000, 8, 1); if (nRet != 0) return 1; + BurnByteswap(DrvSpriteRom, 0x100000); + konami_rom_deinterleave_2(DrvSpriteRom, 0x100000); + K053245GfxDecode(DrvSpriteRom, DrvSprites, 0x100000); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x204000, 0x207fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x400000, 0x400fff, SM_RAM); + SekSetReadWordHandler(0, Blswhstl68KReadWord); + SekSetWriteWordHandler(0, Blswhstl68KWriteWord); + SekSetReadByteHandler(0, Blswhstl68KReadByte); + SekSetWriteByteHandler(0, Blswhstl68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(BlswhstlZ80Read); + ZetSetWriteHandler(BlswhstlZ80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x100000); + + EEPROMInit(&BlswhstlEEPROMInterface); + + GenericTilesInit(); + + // Reset the driver + BlswhstlDoReset(); + + return 0; +} + +static INT32 SsridersInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + SsridersMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + SsridersMemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvSpriteRom, 0x1fffff, K053245LgtnfghtCallback); + K053245SetSpriteOffset(0, -368, 528); + K05324xSetZRejection(0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x080001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x080000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x100000, 8, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x200000); + K053245GfxDecode(DrvSpriteRom, DrvSprites, 0x200000); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x140fff, SM_RAM); + SekSetReadWordHandler(0, Ssriders68KReadWord); + SekSetWriteWordHandler(0, Ssriders68KWriteWord); + SekSetReadByteHandler(0, Ssriders68KReadByte); + SekSetWriteByteHandler(0, Ssriders68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(BlswhstlZ80Read); + ZetSetWriteHandler(BlswhstlZ80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x100000); + + EEPROMInit(&BlswhstlEEPROMInterface); + + GenericTilesInit(); + + // Reset the driver + SsridersDoReset(); + + return 0; +} + +static INT32 Thndrx2Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + Thndrx2MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Thndrx2MemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvSpriteRom, 0x0fffff); + K051960SetCallback(K051960Thndrx2Callback); + K051960SetSpriteOffset(8, 0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 4, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x080000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x100000); + GfxDecode(0x2000, 4, 16, 16, SpritePlaneOffsets2, SpriteXOffsets, SpriteYOffsets, 0x400, DrvSpriteRom, DrvSprites); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 7, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekSetWriteWordHandler(0, Thndrx268KWriteWord); + SekSetReadByteHandler(0, Thndrx268KReadByte); + SekSetWriteByteHandler(0, Thndrx268KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Thndrx2Z80Read); + ZetSetWriteHandler(Thndrx2Z80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x80000); + + EEPROMInit(&thndrx2_eeprom_interface); + + GenericTilesInit(); + + // Reset the driver + SsridersDoReset(); + + return 0; +} + +static INT32 LgtnfghtInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + LgtnfghtMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + LgtnfghtMemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvSpriteRom, 0x0fffff, K053245LgtnfghtCallback); + K053245SetSpriteOffset(0, -368, 528); + K05324xSetZRejection(0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 4, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x080000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x100000); + K053245GfxDecode(DrvSpriteRom, DrvSprites, 0x100000); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 7, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPaletteRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(Drv68KRam , 0x090000, 0x093fff, SM_RAM); + SekSetReadWordHandler(0, Lgtnfght68KReadWord); + SekSetWriteWordHandler(0, Lgtnfght68KWriteWord); + SekSetReadByteHandler(0, Lgtnfght68KReadByte); + SekSetWriteByteHandler(0, Lgtnfght68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(LgtnfghtZ80Read); + ZetSetWriteHandler(LgtnfghtZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x80000); + + EEPROMInit(&thndrx2_eeprom_interface); + + GenericTilesInit(); + + // Reset the driver + SsridersDoReset(); + + return 0; +} + +static INT32 Tmnt2Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + Tmnt2MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Tmnt2MemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(8, 0); + + K053245Init(0, DrvSpriteRom, 0x3fffff, K053245SsridersCallback); + K053245SetSpriteOffset(0, -368, 272); + K05324xSetZRejection(0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x040000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x100000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x200000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x300000, 10, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x400000); + K053245GfxDecode(DrvSpriteRom, DrvSprites, 0x400000); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 11, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x140fff, SM_RAM); + SekSetReadWordHandler(0, Ssriders68KReadWord); + SekSetWriteWordHandler(0, Ssriders68KWriteWord); + SekSetReadByteHandler(0, Ssriders68KReadByte); + SekSetWriteByteHandler(0, Ssriders68KWriteByte); + + SekMapHandler(1, 0x1c0800, 0x1c081f, SM_WRITE); + SekSetWriteWordHandler(1, Tmnt268KProtWord); + SekSetWriteByteHandler(1, Tmnt268KProtByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(BlswhstlZ80Read); + ZetSetWriteHandler(BlswhstlZ80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x200000); + + EEPROMInit(&BlswhstlEEPROMInterface); + + GenericTilesInit(); + + // Reset the driver + SsridersDoReset(); + + return 0; +} + +static INT32 QgakumonInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + Tmnt2MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Tmnt2MemIndex(); + + K052109Init(DrvTileRom, 0x0fffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(0, 0); + + K053245Init(0, DrvSpriteRom, 0x3fffff, K053245SsridersCallback); + K053245SetSpriteOffset(0, -360, 272); + K05324xSetZRejection(0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x080001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x080000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x080000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x100000); + GfxDecode(0x8000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x200000, 8, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x400000); + K053245GfxDecode(DrvSpriteRom, DrvSprites, 0x400000); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x140fff, SM_RAM); + SekSetReadWordHandler(0, Ssriders68KReadWord); + SekSetWriteWordHandler(0, Ssriders68KWriteWord); + SekSetReadByteHandler(0, Ssriders68KReadByte); + SekSetWriteByteHandler(0, Ssriders68KWriteByte); + + SekMapHandler(1, 0x1c0800, 0x1c081f, SM_WRITE); + SekSetWriteWordHandler(1, Tmnt268KProtWord); + SekSetWriteByteHandler(1, Tmnt268KProtByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(BlswhstlZ80Read); + ZetSetWriteHandler(BlswhstlZ80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x200000); + + EEPROMInit(&BlswhstlEEPROMInterface); + + GenericTilesInit(); + + // Reset the driver + SsridersDoReset(); + + return 0; +} + +static INT32 PunkshotInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + PunkshotMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PunkshotMemIndex(); + + K052109Init(DrvTileRom, 0x07ffff); + K052109SetCallback(K052109TmntCallback); + K052109AdjustScroll(8, 0); + + K051960Init(DrvSpriteRom, 0x1fffff); + K051960SetCallback(K051960PunkshotCallback); + K051960SetSpriteOffset(8, 0); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTileRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTileRom + 0x040000, 4, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvTileRom, 0x80000); + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTileRom, DrvTiles); + + // Load the sprites + nRet = BurnLoadRom(DrvSpriteRom + 0x000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSpriteRom + 0x100000, 6, 1); if (nRet != 0) return 1; + konami_rom_deinterleave_2(DrvSpriteRom, 0x200000); + GfxDecode(0x4000, 4, 16, 16, SpritePlaneOffsets2, SpriteXOffsets, SpriteYOffsets, 0x400, DrvSpriteRom, DrvSprites); + + // Load K053260 Sample Roms + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 7, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x080000, 0x083fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x090000, 0x090fff, SM_RAM); + SekSetReadWordHandler(0, Punkshot68KReadWord); + SekSetWriteWordHandler(0, Punkshot68KWriteWord); + SekSetReadByteHandler(0, Punkshot68KReadByte); + SekSetWriteByteHandler(0, Punkshot68KWriteByte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Thndrx2Z80Read); + ZetSetWriteHandler(Thndrx2Z80Write); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom ); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + + K053260Init(0, 3579545, DrvSoundRom, 0x80000); + + GenericTilesInit(); + + srand ( time(NULL) ); + + // Reset the driver + PunkshotDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + ZetExit(); + + BurnYM2151Exit(); + UPD7759Exit(); + K007232Exit(); + + GenericTilesExit(); + + KonamiICExit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + bIrqEnable = 0; + DrvSoundLatch = 0; + TitleSoundLatch = 0; + PlayTitleSample = 0; + TitleSamplePos = 0; + SpriteColourBase = 0; + memset(LayerColourBase, 0, 3); + memset(LayerPri, 0, 3); + PriorityFlag = 0; + + DrvNvRamBank = 0; + CuebrickSndIrqFire = 0; + BlswhstlTileRomBank = 0; + DrvVBlank = 0; + InitEEPROMCount = 0; + + return 0; +} + +static INT32 DrvEEPROMExit() +{ + EEPROMExit(); + + return DrvExit(); +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +static void DrvCalcPalette() +{ + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + + for (INT32 i = 0; i < 0x800; i += 2) { + INT32 Offset = i & ~1; + UINT32 Data = (PaletteRam[Offset] << 8) | PaletteRam[Offset + 1]; + + Palette[Offset >> 1] = (pal5bit(Data >> 0) << 16) | (pal5bit(Data >> 5) << 8) | pal5bit(Data >> 10); + DrvPalette[Offset >> 1] = BurnHighCol(pal5bit(Data >> 0), pal5bit(Data >> 5), pal5bit(Data >> 10), 0); + } +} + +static void BlswhstlCalcPalette() +{ + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + + for (INT32 i = 0; i < 0x800; i++) { + UINT32 Data = PaletteRam[i]; + + Palette[i] = (pal5bit(Data >> 0) << 16) | (pal5bit(Data >> 5) << 8) | pal5bit(Data >> 10); + DrvPalette[i] = BurnHighCol(pal5bit(Data >> 0), pal5bit(Data >> 5), pal5bit(Data >> 10), 0); + } +} + +static void TmntDraw() +{ + DrvCalcPalette(); + K052109UpdateScroll(); + + K052109RenderLayer(2, 1, DrvTiles); + if ((PriorityFlag & 1) == 1) K051960SpritesRender(DrvSprites, -1); + K052109RenderLayer(1, 0, DrvTiles); + if ((PriorityFlag & 1) == 0) K051960SpritesRender(DrvSprites, -1); + K052109RenderLayer(0, 0, DrvTiles); + + BurnTransferCopy(DrvPalette); +} + +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static inline void BlswhstlCalcPaletteWithContrast(INT32 i, INT32 brt) +{ + INT32 r,g,b; + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + + UINT32 Data = PaletteRam[i]; + + r = pal5bit(Data >> 0); + g = pal5bit(Data >> 5); + b = pal5bit(Data >> 10); + + r = (r * brt) / 100; + g = (g * brt) / 100; + b = (b * brt) / 100; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); +} + +static void PaletteDim(INT32 dimslayer) +{ + INT32 i, dim, en, cb, ce, brt; + + dim = dim_v | ((~dim_c & 0x10) >> 1); + en = (K053251GetPriority(5) && K053251GetPriority(5) != 0x3e); + + brt = 100; + if (en) brt -= 40*dim/8; + + if (brt < 100) { + cb = LayerColourBase[dimslayer] << 4; + ce = cb + 128; + + for (i = 0; i < cb; i++) + BlswhstlCalcPaletteWithContrast(i, brt); + + for (i = cb; i < ce; i++) // text + BlswhstlCalcPaletteWithContrast(i, 100); + + for (i = ce; i < 2048; i++) + BlswhstlCalcPaletteWithContrast(i, brt); + } else { + BlswhstlCalcPalette(); + } +} + +static void BlswhstlDraw() +{ + INT32 Layer[3]; + + K052109UpdateScroll(); + + INT32 BGColourBase = K053251GetPaletteIndex(0); + SpriteColourBase = K053251GetPaletteIndex(1); + LayerColourBase[0] = K053251GetPaletteIndex(2); + LayerColourBase[1] = K053251GetPaletteIndex(4); + LayerColourBase[2] = K053251GetPaletteIndex(3); + + LayerPri[0] = K053251GetPriority(2); + LayerPri[1] = K053251GetPriority(4); + LayerPri[2] = K053251GetPriority(3); + Layer[0] = 0; + Layer[1] = 1; + Layer[2] = 2; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * BGColourBase; + } + + sortlayers(Layer, LayerPri); + + PaletteDim(Layer[2]); + + K053245SpritesRender(0, DrvSprites, 3); + if (nBurnLayer & 1) K052109RenderLayer(Layer[0], 0, DrvTiles); + K053245SpritesRender(0, DrvSprites, 2); + if (nBurnLayer & 2) K052109RenderLayer(Layer[1], 0, DrvTiles); + K053245SpritesRender(0, DrvSprites, 1); + K053245SpritesRender(0, DrvSprites, 0); + if (nBurnLayer & 4) K052109RenderLayer(Layer[2], 0, DrvTiles); + + KonamiBlendCopy(Palette, DrvPalette); +} + +static INT32 Thndrx2Draw() +{ + INT32 Layer[3]; + + BlswhstlCalcPalette(); + K052109UpdateScroll(); + + INT32 BGColourBase = K053251GetPaletteIndex(0); + SpriteColourBase = K053251GetPaletteIndex(1); + LayerColourBase[0] = K053251GetPaletteIndex(2); + LayerColourBase[1] = K053251GetPaletteIndex(4); + LayerColourBase[2] = K053251GetPaletteIndex(3); + + LayerPri[0] = K053251GetPriority(2); + LayerPri[1] = K053251GetPriority(4); + LayerPri[2] = K053251GetPriority(3); + Layer[0] = 0; + Layer[1] = 1; + Layer[2] = 2; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * BGColourBase; + } + + sortlayers(Layer, LayerPri); + + if (nSpriteEnable & 8) K051960SpritesRender(DrvSprites, 3); + if (nBurnLayer & 1) K052109RenderLayer(Layer[0], 0, DrvTiles); + if (nSpriteEnable & 4) K051960SpritesRender(DrvSprites, 2); + if (nBurnLayer & 2) K052109RenderLayer(Layer[1], 0, DrvTiles); + if (nSpriteEnable & 2) K051960SpritesRender(DrvSprites, 1); + if (nSpriteEnable & 1) K051960SpritesRender(DrvSprites, 0); + if (nBurnLayer & 4) K052109RenderLayer(Layer[2], 0, DrvTiles); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 PunkshotDraw() +{ + INT32 Layer[3]; + + BlswhstlCalcPalette(); + K052109UpdateScroll(); + +// INT32 BGColourBase = K053251GetPaletteIndex(0); + SpriteColourBase = K053251GetPaletteIndex(1); + LayerColourBase[0] = K053251GetPaletteIndex(2); + LayerColourBase[1] = K053251GetPaletteIndex(4); + LayerColourBase[2] = K053251GetPaletteIndex(3); + + LayerPri[0] = K053251GetPriority(2); + LayerPri[1] = K053251GetPriority(4); + LayerPri[2] = K053251GetPriority(3); + Layer[0] = 0; + Layer[1] = 1; + Layer[2] = 2; + + sortlayers(Layer, LayerPri); + +// if (nSpriteEnable & 8) K051960SpritesRender(DrvSprites, 3); // not sure... + if (nBurnLayer & 1) K052109RenderLayer(Layer[0], 1, DrvTiles); + if (nSpriteEnable & 4) K051960SpritesRender(DrvSprites, 2); + if (nBurnLayer & 2) K052109RenderLayer(Layer[1], 0, DrvTiles); + if (nSpriteEnable & 2) K051960SpritesRender(DrvSprites, 1); + if (nBurnLayer & 4) K052109RenderLayer(Layer[2], 0, DrvTiles); + if (nSpriteEnable & 1) K051960SpritesRender(DrvSprites, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void RenderTitleSample(INT16 *pSoundBuf, INT32 nLength) +{ + double Addr = TitleSamplePos; + double Step = (double)20000 / nBurnSoundRate; + + for (INT32 i = 0; i < nLength; i += 2) { + if (Addr > 0x3ffff) break; + INT16 Sample = DrvTitleSample[(INT32)Addr]; + + pSoundBuf[i + 0] += Sample; + pSoundBuf[i + 1] += Sample; + + Addr += Step; + } + + TitleSamplePos = Addr; +} + +static INT32 TmntFrame() +{ + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + + if (DrvReset) TmntDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1) && bIrqEnable) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + if (PlayTitleSample) RenderTitleSample(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + if (PlayTitleSample) RenderTitleSample(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) TmntDraw(); + + return 0; +} + +static INT32 MiaFrame() +{ + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1) && bIrqEnable) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) TmntDraw(); + + return 0; +} + +static INT32 CuebrickFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) CuebrickDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesDone[0] = 0; + + SekNewFrame(); + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1) && bIrqEnable) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + if (CuebrickSndIrqFire) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + SekClose(); + + if (pBurnDraw) TmntDraw(); + + return 0; +} + +static INT32 BlswhstlFrame() +{ + INT32 nInterleave = 32; + INT32 nSoundBufferPos = 0; + + if (DrvReset) BlswhstlDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1) && K052109_irq_enabled) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) BlswhstlDraw(); + + K053245ClearBuffer(0); + + return 0; +} + +static INT32 SsridersFrame() +{ + INT32 nInterleave = 262; + INT32 nSoundBufferPos = 0; + + if (DrvReset) SsridersDoReset(); + + SsridersMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 19) DrvVBlank = 0; + if (i == 243) DrvVBlank = 1; + if (i == 243 && K052109_irq_enabled) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) BlswhstlDraw(); + + return 0; +} + +static INT32 Thndrx2Frame() +{ + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + if (DrvReset) SsridersDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) Thndrx2Draw(); + + return 0; +} + +static INT32 LgtnfghtFrame() +{ + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + if (DrvReset) SsridersDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) BlswhstlDraw(); + + return 0; +} + +static INT32 Tmnt2Frame() +{ + INT32 nInterleave = 262; + INT32 nSoundBufferPos = 0; + + if (DrvReset) SsridersDoReset(); + + SsridersMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 8000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 19) DrvVBlank = 0; + if (i == 243) DrvVBlank = 1; + if (i == 243 && K052109_irq_enabled) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) BlswhstlDraw(); + + return 0; +} + +static INT32 PunkshotFrame() +{ + INT32 nInterleave = 256; + INT32 nSoundBufferPos = 0; + + if (DrvReset) PunkshotDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (K052109_irq_enabled) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) PunkshotDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029693; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + KonamiICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + BurnYM2151Scan(nAction); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(bIrqEnable); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(TitleSoundLatch); + SCAN_VAR(PlayTitleSample); + SCAN_VAR(TitleSamplePos); + SCAN_VAR(PriorityFlag); + } + + return 0; +} + +static INT32 TmntScan(INT32 nAction, INT32 *pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + K007232Scan(nAction, pnMin); + UPD7759Scan(0, nAction, pnMin); + } + + return DrvScan(nAction, pnMin); +} + +static INT32 MiaScan(INT32 nAction, INT32 *pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + K007232Scan(nAction, pnMin); + } + + return DrvScan(nAction, pnMin); +} + +static INT32 CuebrickScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (nAction & ACB_NVRAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = DrvNvRam; + ba.nLen = 0x400 * 0x20; + ba.szName = "NV RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + KonamiICScan(nAction); + SCAN_VAR(CuebrickSndIrqFire); + } + + return DrvScan(nAction, pnMin); +} + +static INT32 BlswhstlScan(INT32 nAction, INT32 *pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + K053260Scan(nAction); + + SCAN_VAR(InitEEPROMCount); + } + + EEPROMScan(nAction, pnMin); + + return DrvScan(nAction, pnMin); +} + +static INT32 SsridersScan(INT32 nAction, INT32 *pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + K053260Scan(nAction); + + SCAN_VAR(InitEEPROMCount); + SCAN_VAR(DrvVBlank); + } + + EEPROMScan(nAction, pnMin); + + return DrvScan(nAction, pnMin); +} + +static INT32 Thndrx2aScan(INT32 nAction, INT32 *pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + K053260Scan(nAction); + } + + return DrvScan(nAction, pnMin); +} + +struct BurnDriver BurnDrvTmnt = { + "tmnt", NULL, NULL, NULL, "1989", + "Teenage Mutant Ninja Turtles (World 4 Players)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmntRomInfo, TmntRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmntu = { + "tmntu", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Ninja Turtles (US 4 Players, set 1)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmntuRomInfo, TmntuRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmntua = { + "tmntua", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Ninja Turtles (US 4 Players, set 2)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmntuaRomInfo, TmntuaRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht = { + "tmht", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Hero Turtles (UK 4 Players, set 1)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmhtRomInfo, TmhtRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmhta = { + "tmhta", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Hero Turtles (UK 4 Players, set 2)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmhtaRomInfo, TmhtaRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmntj = { + "tmntj", "tmnt", NULL, NULL, "1990", + "Teenage Mutant Ninja Turtles (Japan 4 Players)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, TmntjRomInfo, TmntjRomName, NULL, NULL, TmntInputInfo, TmntDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht2p = { + "tmht2p", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Hero Turtles (UK 2 Players, set 1)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, Tmht2pRomInfo, Tmht2pRomName, NULL, NULL, Tmnt2pInputInfo, Tmnt2pDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht2pa = { + "tmht2pa", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Hero Turtles (UK 2 Players, set 2)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, Tmht2paRomInfo, Tmht2paRomName, NULL, NULL, Tmnt2pInputInfo, Tmnt2pDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht2pj = { + "tmnt2pj", "tmnt", NULL, NULL, "1990", + "Teenage Mutant Ninja Turtles (Japan 2 Players)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, Tmnt2pjRomInfo, Tmnt2pjRomName, NULL, NULL, Tmnt2pInputInfo, Tmnt2pDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht2po = { + "tmnt2po", "tmnt", NULL, NULL, "1989", + "Teenage Mutant Ninja Turtles (Oceania 2 Players)\0", NULL, "Konami", "GX963", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, Tmnt2poRomInfo, Tmnt2poRomName, NULL, NULL, Tmnt2pInputInfo, Tmnt2pDIPInfo, + TmntInit, DrvExit, TmntFrame, NULL, TmntScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMia = { + "mia", NULL, NULL, NULL, "1989", + "M.I.A. - Missing in Action (ver. T)\0", NULL, "Konami", "GX808", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, MiaRomInfo, MiaRomName, NULL, NULL, MiaInputInfo, MiaDIPInfo, + MiaInit, DrvExit, MiaFrame, NULL, MiaScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMia2 = { + "mia2", "mia", NULL, NULL, "1989", + "M.I.A. - Missing in Action (ver. S)\0", NULL, "Konami", "GX808", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, Mia2RomInfo, Mia2RomName, NULL, NULL, MiaInputInfo, MiaDIPInfo, + MiaInit, DrvExit, MiaFrame, NULL, MiaScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCuebrick = { + "cuebrick", NULL, NULL, NULL, "1989", + "Cue Brick (World ver. D)\0", NULL, "Konami", "GX903", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_KONAMI_68K_Z80, GBF_PUZZLE, 0, + NULL, CuebrickRomInfo, CuebrickRomName, NULL, NULL, MiaInputInfo, MiaDIPInfo, + CuebrickInit, DrvExit, CuebrickFrame, NULL, CuebrickScan, + NULL, 0x400, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBlswhstl = { + "blswhstl", NULL, NULL, NULL, "1991", + "Bells & Whistles (ver. L)\0", NULL, "Konami", "GX060", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, BlswhstlRomInfo, BlswhstlRomName, NULL, NULL, BlswhstlInputInfo, NULL, + BlswhstlInit, DrvEEPROMExit, BlswhstlFrame, NULL, BlswhstlScan, + NULL, 0x810, 224, 280, 3, 4 +}; + +struct BurnDriver BurnDrvDetatwin = { + "detatwin", "blswhstl", NULL, NULL, "1991", + "Detana!! Twin Bee (Japan ver. J)\0", NULL, "Konami", "GX060", + L"\u51FA\u305F\u306A!! Twin Bee \u30C4\u30A4\u30F3\u30D3\u30FC (Japan ver. J)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, DetatwinRomInfo, DetatwinRomName, NULL, NULL, BlswhstlInputInfo, NULL, + BlswhstlInit, DrvEEPROMExit, BlswhstlFrame, NULL, BlswhstlScan, + NULL, 0x810, 224, 280, 3, 4 +}; + +struct BurnDriver BurnDrvSsriders = { + "ssriders", NULL, NULL, NULL, "1991", + "Sunset Riders (4 Players ver. EAC)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersRomInfo, SsridersRomName, NULL, NULL, Ssriders4pInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersebd = { + "ssridersebd", "ssriders", NULL, NULL, "1991", + "Sunset Riders (2 Players ver. EBD)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersebdRomInfo, SsridersebdRomName, NULL, NULL, SsridersInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersebc = { + "ssridersebc", "ssriders", NULL, NULL, "1991", + "Sunset Riders (2 Players ver. EBC)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersebcRomInfo, SsridersebcRomName, NULL, NULL, SsridersInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersuda = { + "ssridersuda", "ssriders", NULL, NULL, "1991", + "Sunset Riders (4 Players ver. UDA)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersudaRomInfo, SsridersudaRomName, NULL, NULL, Ssriders4psInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsriderseaa = { + "ssriderseaa", "ssriders", NULL, NULL, "1991", + "Sunset Riders (4 Players ver. EAA)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsriderseaaRomInfo, SsriderseaaRomName, NULL, NULL, Ssriders4psInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersuac = { + "ssridersuac", "ssriders", NULL, NULL, "1991", + "Sunset Riders (4 Players ver. UAC)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersuacRomInfo, SsridersuacRomName, NULL, NULL, Ssriders4pInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersubc = { + "ssridersubc", "ssriders", NULL, NULL, "1991", + "Sunset Riders (2 Players ver. UBC)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersubcRomInfo, SsridersubcRomName, NULL, NULL, SsridersInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersabd = { + "ssridersabd", "ssriders", NULL, NULL, "1991", + "Sunset Riders (2 Players ver. ABD)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersabdRomInfo, SsridersabdRomName, NULL, NULL, SsridersInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersadd = { + "ssridersadd", "ssriders", NULL, NULL, "1991", + "Sunset Riders (4 Players ver. ADD)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersaddRomInfo, SsridersaddRomName, NULL, NULL, Ssriders4psInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsridersjbd = { + "ssridersjbd", "ssriders", NULL, NULL, "1991", + "Sunset Riders (2 Players ver. JBD)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, SsridersjbdRomInfo, SsridersjbdRomName, NULL, NULL, SsridersInputInfo, NULL, + SsridersInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +static int SsridersbInit() +{ + return 1; +} + +struct BurnDriverD BurnDrvSsridersb = { + "ssridersb", "ssriders", NULL, NULL, "1991", + "Sunset Riders (bootleg 4 Players ver. ADD)\0", NULL, "Konami", "GX064", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_KONAMI_68K_Z80, GBF_PLATFORM, 0, + NULL, ssridersbRomInfo, ssridersbRomName, NULL, NULL, Ssriders4psInputInfo, NULL, + SsridersbInit, DrvEEPROMExit, SsridersFrame, NULL, SsridersScan, + NULL, 0x810, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThndrx2 = { + "thndrx2", NULL, NULL, NULL, "1991", + "Thunder Cross II (World)\0", NULL, "Konami", "GX073", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_KONAMI_68K_Z80, GBF_HORSHOOT, 0, + NULL, thndrx2RomInfo, thndrx2RomName, NULL, NULL, Thndrx2InputInfo, NULL, + Thndrx2Init, DrvEEPROMExit, Thndrx2Frame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThndrx2a = { + "thndrx2a", "thndrx2", NULL, NULL, "1991", + "Thunder Cross II (Asia)\0", NULL, "Konami", "GX073", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_HORSHOOT, 0, + NULL, thndrx2aRomInfo, thndrx2aRomName, NULL, NULL, Thndrx2InputInfo, NULL, + Thndrx2Init, DrvEEPROMExit, Thndrx2Frame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThndrx2j = { + "thndrx2j", "thndrx2", NULL, NULL, "1991", + "Thunder Cross II (Japan)\0", NULL, "Konami", "GX073", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_HORSHOOT, 0, + NULL, thndrx2jRomInfo, thndrx2jRomName, NULL, NULL, Thndrx2InputInfo, NULL, + Thndrx2Init, DrvEEPROMExit, Thndrx2Frame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLgtnfght = { + "lgtnfght", NULL, NULL, NULL, "1990", + "Lightning Fighters (World)\0", NULL, "Konami", "GX939", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, lgtnfghtRomInfo, lgtnfghtRomName, NULL, NULL, LgtnfghtInputInfo, LgtnfghtDIPInfo, + LgtnfghtInit, DrvExit, LgtnfghtFrame, NULL, Thndrx2aScan, + NULL, 0x800, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvLgtnfghtu = { + "lgtnfghtu", "lgtnfght", NULL, NULL, "1990", + "Lightning Fighters (US)\0", NULL, "Konami", "GX939", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, lgtnfghtuRomInfo, lgtnfghtuRomName, NULL, NULL, LgtnfghtInputInfo, LgtnfghtDIPInfo, + LgtnfghtInit, DrvExit, LgtnfghtFrame, NULL, Thndrx2aScan, + NULL, 0x800, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvLgtnfghta = { + "lgtnfghta", "lgtnfght", NULL, NULL, "1990", + "Lightning Fighters (Asia)\0", NULL, "Konami", "GX939", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, lgtnfghtaRomInfo, lgtnfghtaRomName, NULL, NULL, LgtnfghtInputInfo, LgtnfghtDIPInfo, + LgtnfghtInit, DrvExit, LgtnfghtFrame, NULL, Thndrx2aScan, + NULL, 0x800, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvTrigon = { + "trigon", "lgtnfght", NULL, NULL, "1990", + "Trigon (Japan)\0", NULL, "Konami", "GX939", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_KONAMI_68K_Z80, GBF_VERSHOOT, 0, + NULL, trigonRomInfo, trigonRomName, NULL, NULL, LgtnfghtInputInfo, LgtnfghtDIPInfo, + LgtnfghtInit, DrvExit, LgtnfghtFrame, NULL, Thndrx2aScan, + NULL, 0x800, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvTmnt2 = { + "tmnt2", NULL, NULL, NULL, "1991", + "Teenage Mutant Ninja Turtles - Turtles in Time (4 Players ver. UAA)\0", NULL, "Konami", "GX063", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, tmnt2RomInfo, tmnt2RomName, NULL, NULL, Ssriders4pInputInfo, NULL, + Tmnt2Init, DrvEEPROMExit, Tmnt2Frame, NULL, SsridersScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmnt22pu = { + "tmnt22pu", "tmnt2", NULL, NULL, "1991", + "Teenage Mutant Ninja Turtles - Turtles in Time (2 Players ver. UDA)\0", NULL, "Konami", "GX063", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, tmnt22puRomInfo, tmnt22puRomName, NULL, NULL, SsridersInputInfo, NULL, + Tmnt2Init, DrvEEPROMExit, Tmnt2Frame, NULL, SsridersScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmht22pe = { + "tmht22pe", "tmnt2", NULL, NULL, "1991", + "Teenage Mutant Hero Turtles - Turtles in Time (2 Players ver. EBA)\0", NULL, "Konami", "GX063", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, tmht22peRomInfo, tmht22peRomName, NULL, NULL, SsridersInputInfo, NULL, + Tmnt2Init, DrvEEPROMExit, Tmnt2Frame, NULL, SsridersScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTmnt2a = { + "tmnt2a", "tmnt2", NULL, NULL, "1991", + "Teenage Mutant Ninja Turtles - Turtles in Time (4 Players ver. ADA)\0", NULL, "Konami", "GX063", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_KONAMI_68K_Z80, GBF_SCRFIGHT, 0, + NULL, tmnt2aRomInfo, tmnt2aRomName, NULL, NULL, Ssriders4psInputInfo, NULL, + Tmnt2Init, DrvEEPROMExit, Tmnt2Frame, NULL, SsridersScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQgakumon = { + "qgakumon", NULL, NULL, NULL, "1993", + "Quiz Gakumon no Susume (Japan ver. JA1 Type H)\0", NULL, "Konami", "GX248", + L"\u30AF\u30A4\u30BA \u5B66\u554F\u30CE\u30B9\u30B9\u30E1 Gakumon no Susume (Japan ver. JA1 Type H)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_KONAMI_68K_Z80, GBF_QUIZ, 0, + NULL, qgakumonRomInfo, qgakumonRomName, NULL, NULL, QgakumonInputInfo, NULL, + QgakumonInit, DrvEEPROMExit, Tmnt2Frame, NULL, SsridersScan, + NULL, 0x800, 304, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPunkshot = { + "punkshot", NULL, NULL, NULL, "1990", + "Punk Shot (US 4 Players)\0", NULL, "Konami", "GX907", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_KONAMI_68K_Z80, GBF_SPORTSMISC, 0, + NULL, punkshotRomInfo, punkshotRomName, NULL, NULL, PunkshotInputInfo, PunkshotDIPInfo, + PunkshotInit, DrvExit, PunkshotFrame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPunkshot2 = { + "punkshot2", "punkshot", NULL, NULL, "1990", + "Punk Shot (US 2 Players)\0", NULL, "Konami", "GX907", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SPORTSMISC, 0, + NULL, punkshot2RomInfo, punkshot2RomName, NULL, NULL, Punkshot2InputInfo, Punkshot2DIPInfo, + PunkshotInit, DrvExit, PunkshotFrame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPunkshotj = { + "punkshotj", "punkshot", NULL, NULL, "1990", + "Punk Shot (Japan 2 Players)\0", NULL, "Konami", "GX907", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KONAMI_68K_Z80, GBF_SPORTSMISC, 0, + NULL, punkshotjRomInfo, punkshotjRomName, NULL, NULL, Punkshot2InputInfo, PunkshotjDIPInfo, + PunkshotInit, DrvExit, PunkshotFrame, NULL, Thndrx2aScan, + NULL, 0x800, 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_twin16.cpp b/src/burn/drivers/konami/d_twin16.cpp new file mode 100644 index 00000000..64e6f24f --- /dev/null +++ b/src/burn/drivers/konami/d_twin16.cpp @@ -0,0 +1,2272 @@ +// FB Alpha Twin16 driver module +// Based on MAME driver by Phil Stroffolino + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "UPD7759.h" +#include "k007232.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *Drv68KROM0; +static UINT8 *Drv68KROM1; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvShareRAM; +static UINT8 *Drv68KRAM0; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM2; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvNvRAM; +static UINT8 *DrvNvRAMBank; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvFgRAM; +static UINT8 *DrvTileRAM; +static UINT8 *DrvSprGfxRAM; +static UINT8 *DrvGfxExp; + +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 *scrollx; +static UINT16 *scrolly; + +static UINT8 *soundlatch; +static UINT8 *soundlatch2; + +static INT32 video_register; +static INT32 gfx_bank; + +static INT32 twin16_CPUA_register; +static INT32 twin16_CPUB_register; + +static INT32 need_process_spriteram; +static INT32 twin16_custom_video; +static INT32 is_vulcan = 0; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvInputs[4]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo DevilwInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Map Button", BIT_DIGITAL, DrvJoy1 + 3, "service2" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Devilw) + +static struct BurnInputInfo DarkadvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy4 + 6, "p3 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy1 + 7, "service2" }, + {"Service 3", BIT_DIGITAL, DrvJoy2 + 7, "service3" }, + {"Map Button", BIT_DIGITAL, DrvJoy1 + 3, "service4" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Darkadv) + +#define coinage_dips(offs) \ + {0 , 0xfe, 0 , 16, "Coin A" }, \ + {offs, 0x01, 0x0f, 0x02, "4 Coins 1 Credit " }, \ + {offs, 0x01, 0x0f, 0x05, "3 Coins 1 Credit " }, \ + {offs, 0x01, 0x0f, 0x08, "2 Coins 1 Credit " }, \ + {offs, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, \ + {offs, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, \ + {offs, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit " }, \ + {offs, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, \ + {offs, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, \ + {offs, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {offs, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, \ + {offs, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {offs, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {offs, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {offs, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {offs, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, \ + {offs, 0x01, 0x0f, 0x00, "Free Play" }, \ + \ + {0 , 0xfe, 0 , 16, "Coin B" }, \ + {offs, 0x01, 0xf0, 0x20, "4 Coins 1 Credit " }, \ + {offs, 0x01, 0xf0, 0x50, "3 Coins 1 Credit " }, \ + {offs, 0x01, 0xf0, 0x80, "2 Coins 1 Credit " }, \ + {offs, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, \ + {offs, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, \ + {offs, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit " }, \ + {offs, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, \ + {offs, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, \ + {offs, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {offs, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, \ + {offs, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {offs, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {offs, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {offs, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {offs, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, \ + {offs, 0x01, 0xf0, 0x00, "Disabled" }, + +static struct BurnDIPInfo DevilwDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x5e, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + coinage_dips(0x13) + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x03, "2" }, + {0x14, 0x01, 0x03, 0x02, "3" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + {0x14, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x60, 0x60, "Easy" }, + {0x14, 0x01, 0x60, 0x40, "Normal" }, + {0x14, 0x01, 0x60, 0x20, "Difficult" }, + {0x14, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Devilw) + +static struct BurnDIPInfo DarkadvDIPList[]= +{ + {0x1d, 0xff, 0xff, 0xff, NULL }, + {0x1e, 0xff, 0xff, 0x5e, NULL }, + {0x1f, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x1d, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x1d, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x1d, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x1d, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x1d, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x1d, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x1d, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x1d, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x1d, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x1d, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x1d, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x1d, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x1d, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x1d, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x1d, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x1d, 0x01, 0x0f, 0x00, "Invalid" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x1e, 0x01, 0x03, 0x03, "2" }, + {0x1e, 0x01, 0x03, 0x02, "3" }, + {0x1e, 0x01, 0x03, 0x01, "5" }, + {0x1e, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1e, 0x01, 0x60, 0x60, "Easy" }, + {0x1e, 0x01, 0x60, 0x40, "Normal" }, + {0x1e, 0x01, 0x60, 0x20, "Difficult" }, + {0x1e, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1e, 0x01, 0x80, 0x80, "Off" }, + {0x1e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1f, 0x01, 0x01, 0x01, "Off" }, + {0x1f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1f, 0x01, 0x04, 0x04, "Off" }, + {0x1f, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Darkadv) + +static struct BurnDIPInfo VulcanDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x5a, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + + coinage_dips(0x14) + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "4" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x15, 0x01, 0x04, 0x00, "Upright" }, + {0x15, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "20K 70K" }, + {0x15, 0x01, 0x18, 0x10, "30K 80K" }, + {0x15, 0x01, 0x18, 0x08, "20K" }, + {0x15, 0x01, 0x18, 0x00, "70K" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x02, 0x02, "Single" }, + {0x16, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Vulcan) + +static struct BurnDIPInfo Gradius2DIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x5a, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + + coinage_dips(0x14) + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "4" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x15, 0x01, 0x04, 0x00, "Upright" }, + {0x15, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "20K 150K" }, + {0x15, 0x01, 0x18, 0x10, "30K 200K" }, + {0x15, 0x01, 0x18, 0x08, "20K" }, + {0x15, 0x01, 0x18, 0x00, "70K" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x02, 0x02, "Single" }, + {0x16, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Gradius2) + +static struct BurnDIPInfo FroundDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x42, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + + coinage_dips(0x14) + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x15, 0x01, 0x03, 0x03, "18" }, + {0x15, 0x01, 0x03, 0x02, "20" }, + {0x15, 0x01, 0x03, 0x01, "22" }, + {0x15, 0x01, 0x03, 0x00, "24" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Fround) + +static struct BurnDIPInfo MiajDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x52, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + coinage_dips(0x14) + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x18, 0x18, "30K 80K" }, + {0x15, 0x01, 0x18, 0x10, "50K 100K" }, + {0x15, 0x01, 0x18, 0x08, "50K" }, + {0x15, 0x01, 0x18, 0x00, "100K" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Difficult" }, + {0x15, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "VRAM Character Check" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(Miaj) + +static struct BurnDIPInfo CuebrckjDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x5a, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + coinage_dips(0x14) + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "1" }, + {0x15, 0x01, 0x03, 0x02, "2" }, + {0x15, 0x01, 0x03, 0x01, "3" }, + {0x15, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x15, 0x01, 0x04, 0x00, "Upright" }, + {0x15, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Machine Name" }, + {0x15, 0x01, 0x18, 0x18, "None" }, + {0x15, 0x01, 0x18, 0x10, "Lewis" }, + {0x15, 0x01, 0x18, 0x08, "Johnson" }, + {0x15, 0x01, 0x18, 0x00, "George" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Normal" }, + {0x15, 0x01, 0x60, 0x20, "Hard" }, + {0x15, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x02, 0x02, "Single" }, + {0x16, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Mode" }, + {0x16, 0x01, 0x08, 0x08, "3" }, + {0x16, 0x01, 0x08, 0x00, "4" }, +}; + +STDDIPINFO(Cuebrckj) + +static void twin16_spriteram_process() +{ + INT32 dx = scrollx[0]; + INT32 dy = scrolly[0]; + + UINT16 *spriteram16 = (UINT16*)DrvSprRAM; + UINT16 *source = spriteram16; + UINT16 *finish = spriteram16 + 0x1800; + + memset(&spriteram16[0x1800], 0, 0x800); + + while (source < finish) + { + INT32 priority = source[0]; + if (priority & 0x8000 ) + { + UINT16 *dest = &spriteram16[0x1800 + ((priority & 0xff) << 2)]; + + INT32 xpos = (source[4] << 16) | source[5]; + INT32 ypos = (source[6] << 16) | source[7]; + + INT32 attributes = source[2]&0x03ff; + if (priority & 0x0200) attributes |= 0x4000; + + attributes |= 0x8000; + + dest[0] = source[3]; + dest[1] = ((xpos >> 8) - dx) & 0xffff; + dest[2] = ((ypos >> 8) - dy) & 0xffff; + dest[3] = attributes; + } + + source += 0x50/2; + } + + need_process_spriteram = 0; +} + +static void fround_CPU_register_w(INT32 data) +{ + INT32 old = twin16_CPUA_register; + twin16_CPUA_register = data; + if (twin16_CPUA_register != old) + { + if ((old & 0x08) == 0 && (twin16_CPUA_register & 0x08)) { + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + } +} + +static void twin16_CPUA_register_w(INT32 data) +{ + if (twin16_CPUA_register != data) + { + if ((twin16_CPUA_register & 0x08) == 0 && (data & 0x08)) { + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + + if ((twin16_CPUA_register & 0x40) && (data & 0x40) == 0) + twin16_spriteram_process(); + + if ((twin16_CPUA_register & 0x10) == 0 && (data & 0x10)) { + SekClose(); + SekOpen(1); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + SekOpen(0); + } + + twin16_CPUA_register = data; + } +} + +static void twin16_CPUB_register_w(INT32 data) +{ + INT32 old = twin16_CPUB_register; + twin16_CPUB_register = data; + if (twin16_CPUB_register != old) + { + if ((old & 0x01) == 0 && (twin16_CPUB_register & 0x01)) + { + SekClose(); + SekOpen(0); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + SekOpen(1); + } + + INT32 offset = (twin16_CPUB_register & 4) << 17; + SekMapMemory(DrvGfxROM1 + 0x100000 + offset, 0x700000, 0x77ffff, SM_ROM); + } +} + +void __fastcall twin16_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0xc0002: + case 0xc0006: + case 0xc000a: + scrollx[((address - 2) & 0x0c) >> 2] = data; + return; + + case 0xc0004: + case 0xc0008: + case 0xc000c: + scrolly[((address - 4) & 0x0c) >> 2] = data; + return; + + case 0xe0000: + gfx_bank = data; + return; + } +} + +void __fastcall twin16_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xa0001: + if (twin16_custom_video == 1) { + fround_CPU_register_w(data); + } else { + twin16_CPUA_register_w(data); + } + return; + + case 0xa0008: + case 0xa0009: + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0xa0011: // watchdog + return; + + case 0xb0400: + { + *DrvNvRAMBank = data & 0x1f; + int offset = data & 0x1f; + SekMapMemory(DrvNvRAM + offset * 0x400, 0x0b0000, 0x0b03ff, SM_RAM); + } + return; + + case 0xc0001: + video_register = data; + return; + } +} + +UINT16 __fastcall twin16_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x0c000e: + case 0x0c000f: { + static INT32 ret = 0; + ret = 1-ret; + return ret; + } + + case 0x0a0000: + case 0x0a0002: + case 0x0a0004: + case 0x0a0006: + return DrvInputs[(address - 0xa0000)/2]; + + case 0x0a0010: + return DrvDips[1]; + + case 0x0a0012: + return DrvDips[0]; + + case 0x0a0018: + return DrvDips[2]; + } + + return 0; +} + +UINT8 __fastcall twin16_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x0c000e: + case 0x0c000f: { + static INT32 ret = 0; + ret = 1-ret; + return ret; + } + + case 0x0a0000: + case 0x0a0001: + case 0x0a0002: + case 0x0a0003: + case 0x0a0004: + case 0x0a0005: + case 0x0a0006: + case 0x0a0007: + return DrvInputs[(address - 0xa0000)/2]; + + case 0x0a0010: + case 0x0a0011: + return DrvDips[1]; + + case 0x0a0012: + case 0x0a0013: + return DrvDips[0]; + + case 0x0a0018: + case 0x0a0019: + return DrvDips[2]; + } + + return 0; +} + +static inline void twin16_tile_write(INT32 offset) +{ + DrvGfxExp[(offset << 1) + 2] = DrvTileRAM[offset + 0] >> 4; + DrvGfxExp[(offset << 1) + 3] = DrvTileRAM[offset + 0] & 0x0f; + DrvGfxExp[(offset << 1) + 0] = DrvTileRAM[offset + 1] >> 4; + DrvGfxExp[(offset << 1) + 1] = DrvTileRAM[offset + 1] & 0x0f; +} + +void __fastcall twin16_sub_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfc0000) == 0x500000) { + INT32 offset = address & 0x3ffff; + *((UINT16*)(DrvTileRAM + offset)) = data; + twin16_tile_write(offset); + return; + } +} + +void __fastcall twin16_sub_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xa0001: + twin16_CPUB_register_w(data); + return; + } + + if ((address & 0xfc0000) == 0x500000) { + INT32 offset = address & 0x3ffff; + DrvTileRAM[offset^1] = data; + twin16_tile_write(offset & ~1); + return; + } +} + +void __fastcall twin16_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + *soundlatch2 = data; + UPD7759ResetWrite(0, data & 2); + return; + + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xd000: + UPD7759PortWrite(0, data); + return; + + case 0xe000: + UPD7759StartWrite(0, data & 1); + return; + } + + if ((address & 0xfff0) == 0xb000) { + K007232WriteReg(0, address & 0x0f, data); + return; + } +} + +UINT8 __fastcall twin16_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9000: + return *soundlatch2; + + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xc000: + case 0xc001: + return BurnYM2151ReadStatus(); + + case 0xf000: + return UPD7759BusyRead(0) ? 1 : 0; + } + + if ((address & 0xfff0) == 0xb000) { + return K007232ReadReg(0, address & 0x0f); + } + + return 0; +} + +static void DrvK007232VolCallback(INT32 v) +{ + K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0); + K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + SekOpen(1); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + UPD7759Reset(); + + gfx_bank = 0x3210; // for other than fround + video_register = 0; + + twin16_CPUA_register = 0; + twin16_CPUB_register = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM0 = Next; Next += 0x040000; + Drv68KROM1 = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x008000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x020000; + + DrvSndROM0 = Next; Next += 0x020000; + DrvSndROM1 = Next; Next += 0x020000; + + DrvGfxExp = Next; Next += 0x400000; + DrvNvRAM = Next; Next += 0x008000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x004000; + DrvSprBuf = Next; Next += 0x004000; + DrvShareRAM = Next; Next += 0x010000; + Drv68KRAM0 = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x001000; + DrvVidRAM2 = Next; Next += 0x006000; + DrvVidRAM = Next; Next += 0x004000; + Drv68KRAM1 = Next; Next += 0x004000; + DrvFgRAM = Next; Next += 0x004000; + DrvTileRAM = Next; Next += 0x040000; + DrvSprGfxRAM = Next; Next += 0x020000; + + DrvZ80RAM = Next; Next += 0x001000; + + DrvNvRAMBank = Next; Next += 0x000001; + + scrollx = (UINT16*)Next; Next += 0x00004 * sizeof(UINT16); + scrolly = (UINT16*)Next; Next += 0x00004 * sizeof(UINT16); + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void expand4bpp(UINT8 *src, UINT8 *dst, INT32 len) +{ + for (INT32 i = len-1; i > 0; i--) { + dst[i * 2 + 0] = src[i] >> 4; + dst[i * 2 + 1] = src[i] & 0x0f; + } +} + +static void gfxdecode() +{ + UINT16 *src = (UINT16*)DrvGfxROM1; + UINT16 *dst = (UINT16*)malloc(0x200000); + for (INT32 i = 0; i < 0x80000; i++) + { + dst[i * 2 + 0] = src[i + 0x80000]; + dst[i * 2 + 1] = src[i + 0x00000]; + } + + memcpy (src, dst, 0x200000); +} + +static INT32 load68k(UINT8 *rom, INT32 offs) +{ + if (BurnLoadRom(rom + 0x000001, offs+0, 2)) return 1; + if (BurnLoadRom(rom + 0x000000, offs+1, 2)) return 1; + if (BurnLoadRom(rom + 0x020001, offs+2, 2)) return 1; + if (BurnLoadRom(rom + 0x020000, offs+3, 2)) return 1; + + return 0; +} + +static INT32 DrvInit(INT32 (pLoadCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + gfxdecode(); + expand4bpp(DrvGfxROM0, DrvGfxROM0, 0x4000); + + if (twin16_custom_video == 1) + { + BurnByteswap(DrvGfxROM1, 0x200000); + expand4bpp(DrvGfxROM1, DrvGfxExp, 0x200000); + BurnByteswap(DrvGfxROM1, 0x200000); + } + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM0, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvShareRAM, 0x040000, 0x04ffff, SM_RAM); + SekMapMemory(Drv68KRAM0, 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvNvRAM, 0x0b0000, 0x0b03ff, SM_RAM); + SekMapMemory(DrvVidRAM2, 0x100000, 0x105fff, SM_RAM); + SekMapMemory(DrvVidRAM, 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x140000, 0x143fff, SM_RAM); + SekMapMemory(DrvGfxROM1, 0x500000, 0x6fffff, SM_ROM); + SekSetWriteWordHandler(0, twin16_main_write_word); + SekSetWriteByteHandler(0, twin16_main_write_byte); + SekSetReadWordHandler(0, twin16_main_read_word); + SekSetReadByteHandler(0, twin16_main_read_byte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Drv68KROM1, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvShareRAM, 0x040000, 0x04ffff, SM_RAM); + SekMapMemory(Drv68KRAM1, 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvGfxROM2, 0x080000, 0x09ffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x400000, 0x403fff, SM_RAM); + SekMapMemory(DrvVidRAM, 0x480000, 0x483fff, SM_RAM); + SekMapMemory(DrvTileRAM, 0x500000, 0x53ffff, SM_ROM); + SekMapMemory(DrvGfxROM1, 0x600000, 0x6fffff, SM_ROM); + SekMapMemory(DrvGfxROM1 + 0x100000, 0x700000, 0x77ffff, SM_ROM); + SekMapMemory(DrvSprGfxRAM, 0x780000, 0x79ffff, SM_RAM); + SekSetWriteWordHandler(0, twin16_sub_write_word); + SekSetWriteByteHandler(0, twin16_sub_write_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x8fff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x8fff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x8fff, 2, DrvZ80RAM); + ZetSetWriteHandler(twin16_sound_write); + ZetSetReadHandler(twin16_sound_read); + ZetMemEnd(); + ZetClose(); + + K007232Init(0, 3579545, DrvSndROM0, 0x20000); + K007232SetPortWriteHandler(0, DrvK007232VolCallback); + + BurnYM2151Init(3579580, 75.0); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSndROM1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + + K007232Exit(); + UPD7759Exit(); + BurnYM2151Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + is_vulcan = 0; + twin16_custom_video = 0; + + return 0; +} + +static inline void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i+=2) + { + INT32 d = ((p[i+0] & 0xff) << 8) | (p[i+1] & 0xff); + + r = (d >> 0) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i/2] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_fg_layer() +{ + INT32 flipx = (video_register & 2) ? 0x1f8 : 0; + INT32 flipy = (video_register & 1) ? 0x0f8 : 0; + + UINT16 *vram = (UINT16*)DrvVidRAM2; + + for (INT32 offs = 0x80; offs < 0x780; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx ^= flipx; + sy ^= flipy; + + if (flipx) sx -= 192; + sy -= 16; + + if (sx >= nScreenWidth) continue; + + INT32 attr = vram[offs]; + INT32 code = attr & 0x1ff; + INT32 color = (attr >> 9) & 0x0f; + + if (code == 0) continue; + + if (sx >= 0 && sx < nScreenWidth-7 && sy >= 0 && sy < nScreenHeight-7) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } + } +} + +static void draw_layer(INT32 opaque) +{ + INT32 o = 0; + INT32 banks[4]; + if (((video_register & 8) >> 3) != opaque) o = 1; + + UINT16 *vram = (UINT16*)(DrvVidRAM + (o << 13)); + banks[3] = gfx_bank >> 12; + banks[2] = (gfx_bank >> 8) & 0x0f; + banks[1] = (gfx_bank >> 4) & 0x0f; + banks[0] = gfx_bank & 0xf; + + INT32 dx = scrollx[1+o]; + INT32 dy = scrolly[1+o]; + + INT32 flipx = 0; + INT32 flipy = 0; + + if (video_register & 2) { + dx = 256-dx-64; + flipx = 1; + } + + if (video_register & 1) { + dy = 256-dy; + flipy = 1; + } + if (is_vulcan) flipy ^= 1; + + INT32 palette = o; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + if (video_register & 2) sx ^= 0x1f8; + if (video_register & 1) sy ^= 0x1f8; + + sx = (sx - dx) & 0x1ff; + sy = (sy - dy) & 0x1ff; + if (sx >= 320) sx-=512; + if (sy >= 256) sy-=512; + + sy -= 16; + + INT32 code = vram[offs]; + INT32 color = (0x20 + (code >> 13) + 8 * palette); + code = (code & 0x7ff) | (banks[(code >> 11) & 3] << 11); + + if (sx >= 0 && sx < nScreenWidth-7 && sy >= 0 && sy < nScreenHeight-7) { + if (opaque) { + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } else { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } + } else { + if (flipx) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } + } + } else { + if (code == 0) continue; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } + } + } + } else { + if (sy < -7 || sy >= nScreenHeight || sx >= nScreenWidth) continue; + + if (opaque) { + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxExp); + } + } + } else { + if (code == 0) continue; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxExp); + } + } + } + } + } +} + +static void draw_sprite(UINT16 *pen_data, INT32 pal_base, INT32 xpos, INT32 ypos, INT32 width, INT32 height, INT32 flipx, INT32 flipy) +{ + if (xpos >= 320) xpos -= 0x10000; + if (ypos >= 256) ypos -= 0x10000; + + for (INT32 y = 0; y < height; y++) + { + INT32 sy = (flipy) ? (ypos + height - 1 - y) : (ypos + y); + + if (sy >= 16 && sy < 240) + { + UINT16 *dest = pTransDraw + (sy - 16) * nScreenWidth; + + for (INT32 x = 0; x < width; x++) + { + INT32 sx = (flipx) ? (xpos + width - 1 - x) : (xpos + x); + + if (sx >= 0 && sx < 320) + { + INT32 pen = pen_data[x/4]; + + pen = (pen >> ((~x & 3) << 2)) & 0x0f; + + if (pen) dest[sx] = pal_base + pen; + } + } + } + + pen_data += width/4; + } +} + +static void draw_sprites(INT32 priority) +{ + UINT16 *twin16_sprite_gfx_ram = (UINT16*)DrvSprGfxRAM; + UINT16 *twin16_gfx_rom = (UINT16*)DrvGfxROM1; + UINT16 *buffered_spriteram16 = (UINT16*)DrvSprBuf; + + UINT16 *source = 0x1800+buffered_spriteram16; + UINT16 *finish = 0x1800+buffered_spriteram16 + 0x800 - 4; + + for (; source < finish; source += 4) + { + INT32 attributes = source[3]; + INT32 prio = (attributes&0x4000) >> 14; + if (prio != priority) continue; + + INT32 code = source[0]; + + if (code != 0xffff && attributes & 0x8000) + { + INT32 xpos = source[1]; + INT32 ypos = source[2]; + + INT32 pal_base = ((attributes&0xf)+0x10)*16; + INT32 height = 16<<((attributes>>6)&0x3); + INT32 width = 16<<((attributes>>4)&0x3); + INT32 flipy = attributes&0x0200; + INT32 flipx = attributes&0x0100; + UINT16 *pen_data = 0; + + if( twin16_custom_video == 1 ) + { + pen_data = twin16_gfx_rom + 0x80000; + } + else + { + switch( (code>>12)&0x3 ) + { + case 0: + pen_data = twin16_gfx_rom; + break; + + case 1: + pen_data = twin16_gfx_rom + 0x40000; + break; + + case 2: + pen_data = twin16_gfx_rom + 0x80000; + if( code&0x4000 ) pen_data += 0x40000; + break; + + case 3: + pen_data = twin16_sprite_gfx_ram; + break; + } + + code &= 0xfff; + } + + if (height == 64 && width == 64) + { + code &= ~8; + } + else if (height == 32 && width == 32) + { + code &= ~3; + } + else if (height == 32 && width == 16) + { + code &= ~1; + } + else if (height == 16 && width == 32) + { + code &= ~1; + } + + pen_data += code << 6; + + if( video_register&1 ) + { + if (ypos>65000) ypos=ypos-65536; + ypos = 256-ypos-height; + flipy = !flipy; + } + if( video_register&2 ) + { + if (xpos>65000) xpos=xpos-65536; + xpos = 320-xpos-width; + flipx = !flipx; + } + + draw_sprite(pen_data, pal_base, xpos, ypos, width, height, flipx, flipy); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + if (nBurnLayer & 1) draw_layer(1); + if (nSpriteEnable & 1) draw_sprites(1); + if (nBurnLayer & 2) draw_layer(0); + if (nSpriteEnable & 2) draw_sprites(0); + if (nBurnLayer & 4) draw_fg_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 5 * sizeof(short)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[3] & 0x0c) == 0) DrvInputs[3] |= 0x0c; + if ((DrvInputs[3] & 0x03) == 0) DrvInputs[3] |= 0x03; + } + + INT32 nSegment; + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 100; + if (twin16_custom_video == 0 && is_vulcan == 0) nInterleave = 1000; // devilw + + INT32 nTotalCycles[3] = { (twin16_custom_video == 1) ? 10000000 / 60 : 9216000 / 60, 9216000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + SekOpen(0); + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nSegment); + if ((twin16_CPUA_register & 0x20) && i == nInterleave-1) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (twin16_custom_video != 1) { + SekOpen(1); + nCyclesDone[1] += SekRun(nSegment); + if ((twin16_CPUB_register & 0x02) && i == nInterleave-1) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + nSegment = (nTotalCycles[2] - nCyclesDone[2]) / (nInterleave - i); + + nCyclesDone[1] += ZetRun(nSegment); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + UPD7759Update(0, pSoundBuf, nSegmentLength); + K007232Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + if(~twin16_CPUA_register & 0x40 && need_process_spriteram) + twin16_spriteram_process(); + + need_process_spriteram = 1; + + memcpy (DrvSprBuf, DrvSprRAM, 0x4000); + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.nAddress = 0x000000; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM) { + ba.Data = DrvNvRAM; + ba.nLen = 0x008000; + ba.nAddress = 0xb00000; + ba.szName = "Cue Brick NV RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + UPD7759Scan(0, nAction, pnMin); + BurnYM2151Scan(nAction); + // K007232Scan(nAction, pnMin); // crash... + + SCAN_VAR(gfx_bank); + SCAN_VAR(video_register); + SCAN_VAR(twin16_CPUA_register); + SCAN_VAR(twin16_CPUB_register); + } + + if (nAction & ACB_WRITE) { + if (twin16_custom_video != 1) { + for (INT32 i = 0; i < 0x40000; i+=2) { + twin16_tile_write(i); + } + } + + SekOpen(0); + SekMapMemory(DrvNvRAM + (*DrvNvRAMBank * 0x400), 0x0b0000, 0x0b03ff, SM_RAM); + SekClose(); + + SekOpen(1); + INT32 offset = (twin16_CPUB_register & 4) << 17; + SekMapMemory(DrvGfxROM1 + 0x100000 + offset, 0x700000, 0x77ffff, SM_ROM); + SekClose(); + } + + return 0; +} + + +// Devil World + +static struct BurnRomInfo devilwRomDesc[] = { + { "687_t05.6n", 0x10000, 0x8ab7dc61, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "687_t04.4n", 0x10000, 0xc69924da, 1 | BRF_PRG | BRF_ESS }, // 1 + { "687_t09.6r", 0x10000, 0xfae97de0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "687_t08.4r", 0x10000, 0x8c898d67, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "687_q07.10n", 0x10000, 0x53110c0b, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "687_q06.8n", 0x10000, 0x9c53a0c5, 2 | BRF_PRG | BRF_ESS }, // 5 + { "687_q13.10s", 0x10000, 0x36ae6014, 2 | BRF_PRG | BRF_ESS }, // 6 + { "687_q12.8s", 0x10000, 0x6d012167, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "687_l03.10a", 0x08000, 0x7201983c, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "687_m14.d8", 0x04000, 0xd7338557, 4 | BRF_GRA }, // 9 Characters + + { "687i17.p16", 0x80000, 0x66cb3923, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "687i18.p18", 0x80000, 0xa1c7d0db, 5 | BRF_GRA }, // 11 + { "687i15.p13", 0x80000, 0xeec8c5b2, 5 | BRF_GRA }, // 12 + { "687i16.p15", 0x80000, 0x746cf48b, 5 | BRF_GRA }, // 13 + + { "687_l11.10r", 0x10000, 0x399deee8, 6 | BRF_GRA }, // 14 Sprites / Bg Tiles + { "687_l10.8r", 0x10000, 0x117c91ee, 6 | BRF_GRA }, // 15 + + { "687_i01.5a", 0x20000, 0xd4992dfb, 7 | BRF_SND }, // 16 K007232 Samples + + { "687_i02.7c", 0x20000, 0xe5947501, 8 | BRF_SND }, // 17 UPD7759 Samples +}; + +STD_ROM_PICK(devilw) +STD_ROM_FN(devilw) + +static INT32 devilwCallback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + if (load68k(Drv68KROM1, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 13, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 15, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 16, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 17, 1)) return 1; + + return 0; +} + +static INT32 devilwInit() +{ + twin16_custom_video = 0; + + return DrvInit(devilwCallback); +} + +struct BurnDriver BurnDrvDevilw = { + "devilw", NULL, NULL, NULL, "1987", + "Devil World\0", NULL, "Konami", "GX687", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, devilwRomInfo, devilwRomName, NULL, NULL, DevilwInputInfo, DevilwDIPInfo, + devilwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Majuu no Ohkoku + +static struct BurnRomInfo majuuRomDesc[] = { + { "687_s05.6n", 0x10000, 0xbd99b434, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "687_s04.4n", 0x10000, 0x3df732e2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "687_s09.6r", 0x10000, 0x1f6efec3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "687_s08.4r", 0x10000, 0x8a16c8c6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "687_q07.10n", 0x10000, 0x53110c0b, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "687_q06.8n", 0x10000, 0x9c53a0c5, 2 | BRF_PRG | BRF_ESS }, // 5 + { "687_q13.10s", 0x10000, 0x36ae6014, 2 | BRF_PRG | BRF_ESS }, // 6 + { "687_q12.8s", 0x10000, 0x6d012167, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "687_l03.10a", 0x08000, 0x7201983c, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "687_l14.d8", 0x04000, 0x20ecccd6, 4 | BRF_GRA }, // 9 Characters + + { "687i17.p16", 0x80000, 0x66cb3923, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "687i18.p18", 0x80000, 0xa1c7d0db, 5 | BRF_GRA }, // 11 + { "687i15.p13", 0x80000, 0xeec8c5b2, 5 | BRF_GRA }, // 12 + { "687i16.p15", 0x80000, 0x746cf48b, 5 | BRF_GRA }, // 13 + + { "687_l11.10r", 0x10000, 0x399deee8, 6 | BRF_GRA }, // 14 Sprites / Bg Tiles + { "687_l10.8r", 0x10000, 0x117c91ee, 6 | BRF_GRA }, // 15 + + { "687_i01.5a", 0x20000, 0xd4992dfb, 7 | BRF_SND }, // 16 K007232 Samples + + { "687_i02.7c", 0x20000, 0xe5947501, 8 | BRF_SND }, // 17 UPD7759 Samples +}; + +STD_ROM_PICK(majuu) +STD_ROM_FN(majuu) + +struct BurnDriver BurnDrvMajuu = { + "majuu", "devilw", NULL, NULL, "1987", + "Majuu no Ohkoku\0", NULL, "Konami", "GX687", + L"\u9B54\u7363\u306E\u738B\u56FD\0Majuu no Ohkoku\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, majuuRomInfo, majuuRomName, NULL, NULL, DevilwInputInfo, DevilwDIPInfo, + devilwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Dark Adventure + +static struct BurnRomInfo darkadvRomDesc[] = { + { "687_n05.6n", 0x10000, 0xa9195b0b, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "687_n04.4n", 0x10000, 0x65b55105, 1 | BRF_PRG | BRF_ESS }, // 1 + { "687_n09.6r", 0x10000, 0x1c6b594c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "687_n08.4r", 0x10000, 0xa9603196, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "687_n07.10n", 0x10000, 0x6154322a, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "687_n06.8n", 0x10000, 0x37a72e8b, 2 | BRF_PRG | BRF_ESS }, // 5 + { "687_n13.10s", 0x10000, 0xf1c252af, 2 | BRF_PRG | BRF_ESS }, // 6 + { "687_n12.8s", 0x10000, 0xda221944, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "687_n03.10a", 0x08000, 0xa24c682f, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "687_n14.d8", 0x04000, 0xc76ac6d2, 4 | BRF_GRA }, // 9 Characters + + { "687i17.p16", 0x80000, 0x66cb3923, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "687i18.p18", 0x80000, 0xa1c7d0db, 5 | BRF_GRA }, // 11 + { "687i15.p13", 0x80000, 0xeec8c5b2, 5 | BRF_GRA }, // 12 + { "687i16.p15", 0x80000, 0x746cf48b, 5 | BRF_GRA }, // 13 + + { "687_l11.10r", 0x10000, 0x399deee8, 6 | BRF_GRA }, // 14 Sprites / Bg Tiles + { "687_l10.8r", 0x10000, 0x117c91ee, 6 | BRF_GRA }, // 15 + + { "687_i01.5a", 0x20000, 0xd4992dfb, 7 | BRF_SND }, // 16 K007232 Samples + + { "687_i02.7c", 0x20000, 0xe5947501, 8 | BRF_SND }, // 17 UPD7759 Samples +}; + +STD_ROM_PICK(darkadv) +STD_ROM_FN(darkadv) + +struct BurnDriver BurnDrvDarkadv = { + "darkadv", "devilw", NULL, NULL, "1987", + "Dark Adventure\0", NULL, "Konami", "GX687", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0, + NULL, darkadvRomInfo, darkadvRomName, NULL, NULL, DarkadvInputInfo, DarkadvDIPInfo, + devilwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Vulcan Venture (New) + +static struct BurnRomInfo vulcanRomDesc[] = { + { "785_w05.6n", 0x10000, 0x6e0e99cd, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_w04.4n", 0x10000, 0x23ec74ca, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_w09.6r", 0x10000, 0x377e4f28, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_w08.4r", 0x10000, 0x813d41ea, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_p07.10n", 0x10000, 0x686d549d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_p06.8n", 0x10000, 0x70c94bee, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_p13.10s", 0x10000, 0x478fdb0a, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_p12.8s", 0x10000, 0x38ea402a, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + + { "785_h14.d8", 0x04000, 0x02f4b16f, 4 | BRF_GRA }, // 9 Characters + + { "785f17.p16", 0x80000, 0x8fbec1a4, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "785f18.p18", 0x80000, 0x50d61e38, 5 | BRF_GRA }, // 11 + { "785f15.p13", 0x80000, 0xaf96aef3, 5 | BRF_GRA }, // 12 + { "785f16.p15", 0x80000, 0xb858df1f, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_SND }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_SND }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(vulcan) +STD_ROM_FN(vulcan) + +static INT32 vulcanCallback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + if (load68k(Drv68KROM1, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 13, 1)) return 1; + + BurnByteswap(DrvGfxROM1, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 16, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 17, 1)) return 1; + + return 0; +} + +static INT32 vulcanInit() +{ + is_vulcan = 1; + twin16_custom_video = 0; + + return DrvInit(vulcanCallback); +} + +struct BurnDriver BurnDrvVulcan = { + "vulcan", NULL, NULL, NULL, "1988", + "Vulcan Venture (New)\0", NULL, "Konami", "GX785", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, vulcanRomInfo, vulcanRomName, NULL, NULL, DrvInputInfo, VulcanDIPInfo, + vulcanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Vulcan Venture (Old) + +static struct BurnRomInfo vulcanaRomDesc[] = { + { "785_r05.6n", 0x10000, 0x1777a57b, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_r04.4n", 0x10000, 0x790cbdf3, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_u09.6r", 0x10000, 0x1aba7010, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_k08.4r", 0x10000, 0x36bb1be1, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_p07.10n", 0x10000, 0x686d549d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_p06.8n", 0x10000, 0x70c94bee, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_p13.10s", 0x10000, 0x478fdb0a, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_p12.8s", 0x10000, 0x38ea402a, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "785_h14.d8", 0x04000, 0x02f4b16f, 4 | BRF_GRA }, // 9 Characters + + { "785f17.p16", 0x80000, 0x8fbec1a4, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "785f18.p18", 0x80000, 0x50d61e38, 5 | BRF_GRA }, // 11 + { "785f15.p13", 0x80000, 0xaf96aef3, 5 | BRF_GRA }, // 12 + { "785f16.p15", 0x80000, 0xb858df1f, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_SND }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_SND }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(vulcana) +STD_ROM_FN(vulcana) + +struct BurnDriver BurnDrvVulcana = { + "vulcana", "vulcan", NULL, NULL, "1988", + "Vulcan Venture (Old)\0", NULL, "Konami", "GX785", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, vulcanaRomInfo, vulcanaRomName, NULL, NULL, DrvInputInfo, VulcanDIPInfo, + vulcanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Vulcan Venture (Oldest) + +static struct BurnRomInfo vulcanbRomDesc[] = { + { "785_n05.6n", 0x10000, 0x6371d475, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_n04.4n", 0x10000, 0xb6f24b9e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_r09.6r", 0x10000, 0xfbfd1543, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_r08.4r", 0x10000, 0x36bb1be1, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_g07.10n", 0x10000, 0xee09dd5d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_g06.8n", 0x10000, 0x85ab7af7, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_g13.10s", 0x10000, 0x274f325d, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_g12.8s", 0x10000, 0x1625f933, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "785_h14.d8", 0x04000, 0x02f4b16f, 4 | BRF_GRA }, // 9 Characters + + { "785f17.p16", 0x80000, 0x8fbec1a4, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "785f18.p18", 0x80000, 0x50d61e38, 5 | BRF_GRA }, // 11 + { "785f15.p13", 0x80000, 0xaf96aef3, 5 | BRF_GRA }, // 12 + { "785f16.p15", 0x80000, 0xb858df1f, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_SND }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_SND }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(vulcanb) +STD_ROM_FN(vulcanb) + +struct BurnDriver BurnDrvVulcanb = { + "vulcanb", "vulcan", NULL, NULL, "1988", + "Vulcan Venture (Oldest)\0", NULL, "Konami", "GX785", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, vulcanbRomInfo, vulcanbRomName, NULL, NULL, DrvInputInfo, VulcanDIPInfo, + vulcanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Gradius II - GOFER no Yabou (Japan New ver.) + +static struct BurnRomInfo gradius2RomDesc[] = { + { "785_x05.6n", 0x10000, 0x8a23a7b8, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_x04.4n", 0x10000, 0x88e466ce, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_x09.6r", 0x10000, 0x3f3d7d7a, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_x08.4r", 0x10000, 0xc39c8efd, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_p07.10n", 0x10000, 0x686d549d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_p06.8n", 0x10000, 0x70c94bee, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_p13.10s", 0x10000, 0x478fdb0a, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_p12.8s", 0x10000, 0x38ea402a, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "785_g14.d8", 0x04000, 0x9dcdad9d, 4 | BRF_GRA }, // 9 Characters + + { "gr2.p16", 0x80000, 0x4e7a7b82, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "gr2.p18", 0x80000, 0x3f604e9a, 5 | BRF_GRA }, // 11 + { "gr2.p13", 0x80000, 0x5bd239ac, 5 | BRF_GRA }, // 12 + { "gr2.p15", 0x80000, 0x95c6b8a3, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_SND }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_SND }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(gradius2) +STD_ROM_FN(gradius2) + +static INT32 gradius2Callback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + if (load68k(Drv68KROM1, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 13, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 16, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 17, 1)) return 1; + + return 0; +} + +static INT32 gradius2Init() +{ + is_vulcan = 1; + twin16_custom_video = 0; + + return DrvInit(gradius2Callback); +} + +struct BurnDriver BurnDrvGradius2 = { + "gradius2", "vulcan", NULL, NULL, "1988", + "Gradius II - GOFER no Yabou (Japan New ver.)\0", NULL, "Konami", "GX785", + L"Gradius II - GOFER \u306E\u91CE\u671B (Japan New ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, gradius2RomInfo, gradius2RomName, NULL, NULL, DrvInputInfo, Gradius2DIPInfo, + gradius2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Gradius II - GOFER no Yabou (Japan Old ver.) + +static struct BurnRomInfo gradius2aRomDesc[] = { + { "785_p05.6n", 0x10000, 0x4db0e736, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_p04.4n", 0x10000, 0x765b99e6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_t09.6r", 0x10000, 0x4e3f4965, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_j08.4r", 0x10000, 0x2b1c9108, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_p07.10n", 0x10000, 0x686d549d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_p06.8n", 0x10000, 0x70c94bee, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_p13.10s", 0x10000, 0x478fdb0a, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_p12.8s", 0x10000, 0x38ea402a, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "785_g14.d8", 0x04000, 0x9dcdad9d, 4 | BRF_GRA }, // 9 Characters + + { "785f17.p16", 0x80000, 0x8fbec1a4, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "785f18.p18", 0x80000, 0x50d61e38, 5 | BRF_GRA }, // 11 + { "785f15.p13", 0x80000, 0xaf96aef3, 5 | BRF_GRA }, // 12 + { "785f16.p15", 0x80000, 0xb858df1f, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_SND }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_SND }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(gradius2a) +STD_ROM_FN(gradius2a) + +struct BurnDriver BurnDrvGradius2a = { + "gradius2a", "vulcan", NULL, NULL, "1988", + "Gradius II - GOFER no Yabou (Japan Old ver.)\0", NULL, "Konami", "GX785", + L"Gradius II - GOFER \u306E\u91CE\u671B (Japan Old ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, gradius2aRomInfo, gradius2aRomName, NULL, NULL, DrvInputInfo, VulcanDIPInfo, + vulcanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Gradius II - GOFER no Yabou (Japan Older ver.) + +static struct BurnRomInfo gradius2bRomDesc[] = { + { "785_p05.6n", 0x10000, 0x4db0e736, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "785_p04.4n", 0x10000, 0x765b99e6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "785_j09.6r", 0x10000, 0x6d96a7e3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "785_j08.4r", 0x10000, 0x2b1c9108, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "785_p07.10n", 0x10000, 0x686d549d, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "785_p06.8n", 0x10000, 0x70c94bee, 2 | BRF_PRG | BRF_ESS }, // 5 + { "785_p13.10s", 0x10000, 0x478fdb0a, 2 | BRF_PRG | BRF_ESS }, // 6 + { "785_p12.8s", 0x10000, 0x38ea402a, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "785_g03.10a", 0x08000, 0x67a3b50d, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "785_g14.d8", 0x04000, 0x9dcdad9d, 4 | BRF_GRA }, // 9 Characters + + { "785f17.p16", 0x80000, 0x8fbec1a4, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "785f18.p18", 0x80000, 0x50d61e38, 5 | BRF_GRA }, // 11 + { "785f15.p13", 0x80000, 0xaf96aef3, 5 | BRF_GRA }, // 12 + { "785f16.p15", 0x80000, 0xb858df1f, 5 | BRF_GRA }, // 13 + + { "785_f01.5a", 0x20000, 0xa0d8d69e, 7 | BRF_GRA }, // 14 K007232 Samples + + { "785_f02.7c", 0x20000, 0xc39f5ca4, 8 | BRF_GRA }, // 15 UPD7759 Samples +}; + +STD_ROM_PICK(gradius2b) +STD_ROM_FN(gradius2b) + +struct BurnDriver BurnDrvGradius2b = { + "gradius2b", "vulcan", NULL, NULL, "1988", + "Gradius II - GOFER no Yabou (Japan Older ver.)\0", NULL, "Konami", "GX785", + L"Gradius II - GOFER \u306E\u91CE\u671B (Japan Older ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_HORSHOOT, 0, + NULL, gradius2bRomInfo, gradius2bRomName, NULL, NULL, DrvInputInfo, VulcanDIPInfo, + vulcanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// The Final Round (ver. M) + +static struct BurnRomInfo froundRomDesc[] = { + { "870_m21.bin", 0x20000, 0x436dbffb, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "870_m20.bin", 0x20000, 0xb1c79d6a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "870_f03.10a", 0x08000, 0xa645c727, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "870_f14.d8", 0x04000, 0xc9b46615, 4 | BRF_PRG | BRF_ESS }, // 3 Characters + + { "870c18.p18", 0x80000, 0x07927fe8, 5 | BRF_GRA }, // 4 Sprites / Bg Tiles + { "870c17.p16", 0x80000, 0x2bc99ff8, 5 | BRF_GRA }, // 5 + { "870c16.p15", 0x80000, 0x41df6a1b, 5 | BRF_GRA }, // 6 + { "870c15.p13", 0x80000, 0x8c9281df, 5 | BRF_GRA }, // 7 + + { "870_c01.5a", 0x20000, 0x6af96546, 7 | BRF_GRA }, // 8 K007232 Samples + + { "870_c02.7c", 0x20000, 0x54e12c6d, 8 | BRF_GRA }, // 9 UPD7759 Samples +}; + +STD_ROM_PICK(fround) +STD_ROM_FN(fround) + +static INT32 froundCallback() +{ + if (BurnLoadRom(Drv68KROM0 + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 9, 1)) return 1; + + return 0; +} + +static INT32 froundInit() +{ + twin16_custom_video = 1; + + return DrvInit(froundCallback); +} + +struct BurnDriver BurnDrvFround = { + "fround", NULL, NULL, NULL, "1988", + "The Final Round (ver. M)\0", NULL, "Konami", "GX870", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, froundRomInfo, froundRomName, NULL, NULL, DrvInputInfo, FroundDIPInfo, + froundInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// The Final Round (ver. L) + +static struct BurnRomInfo froundlRomDesc[] = { + { "870_l21.bin", 0x20000, 0xe21a3a19, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "870_l20.bin", 0x20000, 0x0ce9786f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "870_f03.10a", 0x08000, 0xa645c727, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "870_f14.d8", 0x04000, 0xc9b46615, 4 | BRF_PRG | BRF_ESS }, // 3 Characters + + { "870c18.p18", 0x80000, 0x07927fe8, 5 | BRF_GRA }, // 4 Sprites / Bg Tiles + { "870c17.p16", 0x80000, 0x2bc99ff8, 5 | BRF_GRA }, // 5 + { "870c16.p15", 0x80000, 0x41df6a1b, 5 | BRF_GRA }, // 6 + { "870c15.p13", 0x80000, 0x8c9281df, 5 | BRF_GRA }, // 7 + + { "870_c01.5a", 0x20000, 0x6af96546, 7 | BRF_GRA }, // 8 K007232 Samples + + { "870_c02.7c", 0x20000, 0x54e12c6d, 8 | BRF_GRA }, // 9 UPD7759 Samples +}; + +STD_ROM_PICK(froundl) +STD_ROM_FN(froundl) + +struct BurnDriver BurnDrvFroundl = { + "froundl", "fround", NULL, NULL, "1988", + "The Final Round (ver. L)\0", NULL, "Konami", "GX870", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, froundlRomInfo, froundlRomName, NULL, NULL, DrvInputInfo, FroundDIPInfo, + froundInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Hard Puncher (Japan) + +static struct BurnRomInfo hpuncherRomDesc[] = { + { "870_h05.6n", 0x10000, 0x2bcfeef3, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "870_h04.4n", 0x10000, 0xb9f97fd3, 1 | BRF_PRG | BRF_ESS }, // 1 + { "870_h09.6r", 0x10000, 0x96a4f8b1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "870_h08.4r", 0x10000, 0x46d65156, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "870_h07.10n", 0x10000, 0xb4dda612, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "870_h06.8n", 0x10000, 0x696ba702, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "870_g03.10a", 0x08000, 0xdb9c10c8, 3 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "870_f14.d8", 0x04000, 0xc9b46615, 4 | BRF_GRA }, // 7 Characters + + { "870c17.p16", 0x80000, 0x2bc99ff8, 5 | BRF_GRA }, // 8 Sprites / Bg Tiles + { "870c18.p18", 0x80000, 0x07927fe8, 5 | BRF_GRA }, // 9 + { "870c15.p13", 0x80000, 0x8c9281df, 5 | BRF_GRA }, // 10 + { "870c16.p15", 0x80000, 0x41df6a1b, 5 | BRF_GRA }, // 11 + + { "870_c01.5a", 0x20000, 0x6af96546, 7 | BRF_GRA }, // 12 K007232 Samples + + { "870_c02.7c", 0x20000, 0x54e12c6d, 8 | BRF_GRA }, // 13 UPD7759 Samples +}; + +STD_ROM_PICK(hpuncher) +STD_ROM_FN(hpuncher) + +static INT32 hpuncherCallback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + + if (BurnLoadRom(Drv68KROM1 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x000000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 13, 1)) return 1; + + return 0; +} + +static INT32 hpuncherInit() +{ + twin16_custom_video = 2; + + return DrvInit(hpuncherCallback); +} + +struct BurnDriver BurnDrvHpuncher = { + "hpuncher", "fround", NULL, NULL, "1988", + "Hard Puncher (Japan)\0", NULL, "Konami", "GX870", + L"Hard Puncher \uFF0D\u8840\u307E\u307F\u308C\u306E\u6804\u5149\uFF0D (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0, + NULL, hpuncherRomInfo, hpuncherRomName, NULL, NULL, DrvInputInfo, FroundDIPInfo, + hpuncherInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// M.I.A. - Missing in Action (Japan) + +static struct BurnRomInfo miajRomDesc[] = { + { "808_r05.6n", 0x10000, 0x91fd83f4, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "808_r04.4n", 0x10000, 0xf1c8c597, 1 | BRF_PRG | BRF_ESS }, // 1 + { "808_r09.6r", 0x10000, 0xf74d4467, 1 | BRF_PRG | BRF_ESS }, // 2 + { "808_r08.4r", 0x10000, 0x26f21704, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "808_e07.10n", 0x10000, 0x297bdcea, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "808_e06.8n", 0x10000, 0x8f576b33, 2 | BRF_PRG | BRF_ESS }, // 5 + { "808_e13.10s", 0x10000, 0x1fa708f4, 2 | BRF_PRG | BRF_ESS }, // 6 + { "808_e12.8s", 0x10000, 0xd62f1fde, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "808_e03.10a", 0x08000, 0x3d93a7cd, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "808_e14.d8", 0x04000, 0xb9d36525, 4 | BRF_GRA }, // 9 Characters + + { "808d17.p16", 0x80000, 0xd1299082, 5 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "808d15.p13", 0x80000, 0x2b22a6b6, 5 | BRF_GRA }, // 11 + + { "808_d01.5a", 0x20000, 0xfd4d37c0, 7 | BRF_GRA }, // 12 K007232 Samples +}; + +STD_ROM_PICK(miaj) +STD_ROM_FN(miaj) + +static INT32 miajCallback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + if (load68k(Drv68KROM1, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 12, 1)) return 1; + + return 0; +} + +static INT32 miajInit() +{ + twin16_custom_video = 2; + + return DrvInit(miajCallback); +} + +struct BurnDriver BurnDrvMiaj = { + "miaj", "mia", NULL, NULL, "1989", + "M.I.A. - Missing in Action (Japan)\0", NULL, "Konami", "GX808", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PLATFORM, 0, + NULL, miajRomInfo, miajRomName, NULL, NULL, DrvInputInfo, MiajDIPInfo, + miajInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; + + +// Cue Brick (Japan) + +static struct BurnRomInfo cuebrckjRomDesc[] = { + { "903_e05.6n", 0x10000, 0x8b556220, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "903_e04.4n", 0x10000, 0xbf9c7927, 1 | BRF_PRG | BRF_ESS }, // 1 + { "903_e09.6r", 0x10000, 0x2a77554d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "903_e08.4r", 0x10000, 0xc0a430c1, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "903_d07.10n", 0x10000, 0xfc0edce7, 2 | BRF_PRG | BRF_ESS }, // 4 68K #1 Code + { "903_d06.8n", 0x10000, 0xb2cef6fe, 2 | BRF_PRG | BRF_ESS }, // 5 + { "903_e13.10s", 0x10000, 0x4fb5fb80, 2 | BRF_PRG | BRF_ESS }, // 6 + { "903_e12.8s", 0x10000, 0x883e3097, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "903_d03.10a", 0x08000, 0x455e855a, 3 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "903_e14.d8", 0x04000, 0xddbebbd5, 4 | BRF_GRA }, // 9 Characters + + { "903_e11.10r", 0x10000, 0x5c41faf8, 6 | BRF_GRA }, // 10 Sprites / Bg Tiles + { "903_e10.8r", 0x10000, 0x417576d4, 6 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(cuebrckj) +STD_ROM_FN(cuebrckj) + +static INT32 cuebrckjCallback() +{ + if (load68k(Drv68KROM0, 0)) return 1; + if (load68k(Drv68KROM1, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 2)) return 1; + + return 0; +} + +static INT32 cuebrckjInit() +{ + twin16_custom_video = 2; + + return DrvInit(cuebrckjCallback); +} + +struct BurnDriver BurnDrvCuebrckj = { + "cuebrickj", "cuebrick", NULL, NULL, "1989", + "Cue Brick (Japan)\0", NULL, "Konami", "GX903", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_PUZZLE, 0, + NULL, cuebrckjRomInfo, cuebrckjRomName, NULL, NULL, DrvInputInfo, CuebrckjDIPInfo, + cuebrckjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_ultraman.cpp b/src/burn/drivers/konami/d_ultraman.cpp new file mode 100644 index 00000000..40ae3311 --- /dev/null +++ b/src/burn/drivers/konami/d_ultraman.cpp @@ -0,0 +1,695 @@ +// FB Alpha Ultraman driver module +// Based on MAME driver by Manuel Abadia + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" +#include "konamiic.h" + +static UINT8 *AllMem; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvGfxROMExp2; +static UINT8 *DrvGfxROMExp3; +static UINT8 *DrvSndROM; +static UINT8 *AllRam; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *soundlatch; +static UINT8 *RamEnd; +static UINT8 *MemEnd; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT32 bank0; +static INT32 bank1; +static INT32 bank2; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static struct BurnInputInfo UltramanInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 7, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 7, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, DrvJoy1 + 4, "diag" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 5, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ultraman) + +static struct BurnDIPInfo UltramanDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x74, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "No Coin B" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x04, 0x00, "No" }, + {0x16, 0x01, 0x04, 0x04, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x08, 0x08, "Off" }, + {0x16, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x30, 0x10, "Easy" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x20, "Hard" }, + {0x16, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Upright Controls" }, + {0x16, 0x01, 0x40, 0x40, "Single" }, + {0x16, 0x01, 0x40, 0x00, "Dual" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x16, 0x01, 0x80, 0x00, "Upright" }, +// {0x16, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(Ultraman) + +void __fastcall ultraman_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x1c0019: + { + if (((data & 0x02) >> 1) != bank0) { + bank0 = (data & 0x02) >> 1; + K051316RedrawTiles(0); + } + + if (((data & 0x08) >> 3) != bank1) { + bank1 = (data & 0x08) >> 3; + K051316RedrawTiles(1); + } + + if (((data & 0x20) >> 5) != bank2) { + bank2 = (data & 0x20) >> 5; + K051316RedrawTiles(2); + } + + K051316WrapEnable(0,data & 0x01); + K051316WrapEnable(1,data & 0x04); + K051316WrapEnable(2,data & 0x10); + } + return; + + case 0x1c0021: + ZetNmi(); + return; + + case 0x1c0029: + *soundlatch = data; + return; + + case 0x1c0031: // watchdog + return; + } + + if ((address & 0xfff001) == 0x204001) { + K051316Write(0, (address >> 1) & 0x7ff, data); + return; + } + + if ((address & 0xfff001) == 0x205001) { + K051316Write(1, (address >> 1) & 0x7ff, data); + return; + } + + if ((address & 0xfff001) == 0x206001) { + K051316Write(2, (address >> 1) & 0x7ff, data); + return; + } + + if ((address & 0xffffe1) == 0x207f81) { + K051316WriteCtrl(0, (address >> 1) & 0x0f, data); + return; + } + + if ((address & 0xffffe1) == 0x207fa1) { + K051316WriteCtrl(1, (address >> 1) & 0x0f, data); + return; + } + + if ((address & 0xffffe1) == 0x207fc1) { + K051316WriteCtrl(2, (address >> 1) & 0x0f, data); + return; + } + + if ((address & 0xfffff1) == 0x304001) { + K051937Write((address >> 1) & 0x007, data); + return; + } + + if ((address & 0xfff801) == 0x304801) { + K051960Write((address >> 1) & 0x3ff, data); + return; + } + +} + +UINT8 __fastcall ultraman_read_byte(UINT32 address) +{ + switch (address) + { + case 0x1c0001: + return DrvInputs[0]; + + case 0x1c0003: + return DrvInputs[1]; + + case 0x1c0005: + return DrvInputs[2]; + + case 0x1c0007: + return DrvDips[0]; + + case 0x1c0009: + return DrvDips[1]; + } + + if ((address & 0xfff000) == 0x204000) { + return K051316Read(0, (address >> 1) & 0x7ff); + } + + if ((address & 0xfff000) == 0x205000) { + return K051316Read(1, (address >> 1) & 0x7ff); + } + + if ((address & 0xfff000) == 0x206000) { + return K051316Read(2, (address >> 1) & 0x7ff); + } + + if ((address & 0xfffff0) == 0x304000) { + return K051937Read((address >> 1) & 0x007); + } + + if ((address & 0xfff800) == 0x304800) { + return K051960Read((address >> 1) & 0x3ff); + } + + return 0; +} + +void __fastcall ultraman_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xd000: + return; + + case 0xe000: + MSM6295Command(0, data); + return; + + case 0xf000: + BurnYM2151SelectRegister(data); + return; + + case 0xf001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall ultraman_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + return *soundlatch; + + case 0xe000: + return MSM6295ReadStatus(0); + + case 0xf000: + case 0xf001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void K051960Callback(INT32 *, INT32 *color, INT32 *priority, INT32 *shadow) +{ + *priority = (*color & 0x80) >> 7; + *color = 0xc0 + ((*color & 0x7e) >> 1); + *shadow = 0; +} + +static void K051316Callback0(INT32 *code, INT32 *color, INT32 *) +{ + *code |= ((*color & 0x07) << 8) | (bank0 << 11); + *color = ((*color & 0xf8) >> 3); +} + +static void K051316Callback1(INT32 *code, INT32 *color, INT32 *) +{ + *code |= ((*color & 0x07) << 8) | (bank1 << 11); + *color = 0x40 + ((*color & 0xf8) >> 3); +} + +static void K051316Callback2(INT32 *code, INT32 *color, INT32 *) +{ + *code |= ((*color & 0x07) << 8) | (bank2 << 11); + *color = 0x80 + ((*color & 0xf8) >> 3); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + KonamiICReset(); + + bank0 = bank1 = bank2 = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROM3 = Next; Next += 0x080000; + DrvGfxROMExp0 = Next; Next += 0x200000; + DrvGfxROMExp1 = Next; Next += 0x100000; + DrvGfxROMExp2 = Next; Next += 0x100000; + DrvGfxROMExp3 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x2000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x004000; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x000, 0x008, 0x010, 0x018 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + INT32 Plane1[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs1[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x020, 0x024, 0x028, 0x02c, 0x030, 0x034, 0x038, 0x03c }; + INT32 YOffs1[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x100000); + + GfxDecode(0x02000, 4, 16, 16, Plane0, XOffs0, YOffs0, 0x400, DrvGfxROM0, DrvGfxROMExp0); + GfxDecode(0x01000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, DrvGfxROM1, DrvGfxROMExp1); + GfxDecode(0x01000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, DrvGfxROM2, DrvGfxROMExp2); + GfxDecode(0x01000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, DrvGfxROM3, DrvGfxROMExp3); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x020000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x060000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x040000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x060000, 16, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 17, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x08ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x180000, 0x183fff, SM_RAM); + SekSetWriteByteHandler(0, ultraman_write_byte); + SekSetReadByteHandler(0, ultraman_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0xbfff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80RAM); + ZetSetWriteHandler(ultraman_sound_write); + ZetSetReadHandler(ultraman_sound_read); + ZetMemEnd(); + ZetClose(); + + K051960Init(DrvGfxROM0, 0xfffff); + K051960SetCallback(K051960Callback); + K051960SetSpriteOffset(9, 0); + + K051316Init(0, DrvGfxROM1, DrvGfxROMExp1, 0x7ffff, K051316Callback0, 4, 0); + K051316SetOffset(0, -105, -16); + + K051316Init(1, DrvGfxROM2, DrvGfxROMExp2, 0x7ffff, K051316Callback1, 4, 0); + K051316SetOffset(1, -105, -16); + + K051316Init(2, DrvGfxROM3, DrvGfxROMExp3, 0x7ffff, K051316Callback2, 4, 0); + K051316SetOffset(2, -105, -16); + + BurnYM2151Init(4000000, 100.0); + + MSM6295Init(0, 1056000 / 132, 50.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + SekExit(); + ZetExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x4000 / 2; i++) { + r = (p[i] >> 10) & 0x1f; + g = (p[i] >> 5) & 0x1f; + b = (p[i] >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + BurnTransferClear(); + + K051316_zoom_draw(2, 0); + K051316_zoom_draw(1, 0); + K051960SpritesRender(DrvGfxROMExp0, 0); + K051316_zoom_draw(0, 0); + K051960SpritesRender(DrvGfxROMExp0, 1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18; + if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06; + if ((DrvInputs[2] & 0x18) == 0) DrvInputs[2] |= 0x18; + if ((DrvInputs[2] & 0x06) == 0) DrvInputs[2] |= 0x06; + } + + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 12000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCyclesSegment = nCyclesTotal[0] / nInterleave; + + nCyclesDone[0] += SekRun(nCyclesSegment); + + nCyclesSegment = nCyclesTotal[1] / nInterleave; + + nCyclesDone[1] += ZetRun(nCyclesSegment); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + KonamiICScan(nAction); + + SCAN_VAR(bank0); + SCAN_VAR(bank1); + SCAN_VAR(bank2); + } + + return 0; +} + + +// Ultraman (Japan) + +static struct BurnRomInfo ultramanRomDesc[] = { + { "910-b01.c11", 0x20000, 0x3d9e4323, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "910-b02.d11", 0x20000, 0xd24c82e9, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "910-a05.d05", 0x08000, 0xebaef189, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "910-a19.l04", 0x80000, 0x2dc9ffdc, 3 | BRF_GRA }, // 3 K051960 Sprites + { "910-a20.l01", 0x80000, 0xa4298dce, 3 | BRF_GRA }, // 4 + + { "910-a07.j15", 0x20000, 0x8b43a64e, 4 | BRF_GRA }, // 5 K051316 #0 Tiles + { "910-a08.j16", 0x20000, 0xc3829826, 4 | BRF_GRA }, // 6 + { "910-a09.j18", 0x20000, 0xee10b519, 4 | BRF_GRA }, // 7 + { "910-a10.j19", 0x20000, 0xcffbb0c3, 4 | BRF_GRA }, // 8 + + { "910-a11.l15", 0x20000, 0x17a5581d, 5 | BRF_GRA }, // 9 K051316 #1 Tiles + { "910-a12.l16", 0x20000, 0x39763fb5, 5 | BRF_GRA }, // 10 + { "910-a13.l18", 0x20000, 0x66b25a4f, 5 | BRF_GRA }, // 11 + { "910-a14.l19", 0x20000, 0x09fbd412, 5 | BRF_GRA }, // 12 + + { "910-a15.m15", 0x20000, 0x6d5bfbb7, 6 | BRF_GRA }, // 13 K051316 #2 Tiles + { "910-a16.m16", 0x20000, 0x5f6f8c3d, 6 | BRF_GRA }, // 14 + { "910-a17.m18", 0x20000, 0x1f3ec4ff, 6 | BRF_GRA }, // 15 + { "910-a18.m19", 0x20000, 0xfdc42929, 6 | BRF_GRA }, // 16 + + { "910-a06.c06", 0x40000, 0x28fa99c9, 7 | BRF_SND }, // 17 MSM6295 Samples + + { "910-a21.f14", 0x00100, 0x64460fbc, 0 | BRF_OPT }, // 18 Priority Prom +}; + +STD_ROM_PICK(ultraman) +STD_ROM_FN(ultraman) + +struct BurnDriver BurnDrvUltraman = { + "ultraman", NULL, NULL, NULL, "1991", + "Ultraman (Japan)\0", NULL, "Banpresto / Bandai", "GX910", + L"\uFEFF\u30A6\u30EB\u30c8\u30E9\u30DE\u30f3 \u7A7A\u60F3\u7279\u64AE\u30B7\u30EA\u30FC\u30BA (Japan)\0Ultraman\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, ultramanRomInfo, ultramanRomName, NULL, NULL, UltramanInputInfo, UltramanDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_vendetta.cpp b/src/burn/drivers/konami/d_vendetta.cpp new file mode 100644 index 00000000..7afdc706 --- /dev/null +++ b/src/burn/drivers/konami/d_vendetta.cpp @@ -0,0 +1,1236 @@ +// FB Alpha Vendetta / Crime Fighters 2 / Escape Kids driver module +// Based on MAME driver by Ernesto Corvi + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "konami_intf.h" +#include "konamiic.h" +#include "k053260.h" +#include "eeprom.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvKonROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *DrvKonRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *nDrvBank; + +static INT32 videobank; +static INT32 init_eeprom_count; +static INT32 irq_enabled; +static INT32 vblank = 0; +static INT32 bankoffset; + +static INT32 bg_colorbase; +static INT32 sprite_colorbase; +static INT32 layer_colorbase[3]; +static INT32 layerpri[3]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvJoy6; +static UINT8 DrvReset; +static UINT8 DrvInputs[5]; + +static INT32 nCyclesDone[2]; + +static struct BurnInputInfo Vendet4pInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 0, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy4 + 7, "p4 coin" }, + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 0, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, &DrvJoy6, "diag" }, +}; + +STDINPUTINFO(Vendet4p) + +static struct BurnInputInfo VendettaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy5 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy5 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, &DrvJoy6, "diag" }, + {"Service", BIT_DIGITAL, DrvJoy5 + 4, "service" }, +}; + +STDINPUTINFO(Vendetta) + +static struct BurnInputInfo EsckidsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy5 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy5 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy5 + 2, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 0, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy4 + 7, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy5 + 3, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 0, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, &DrvJoy6, "diag" }, + {"Service 1", BIT_DIGITAL, DrvJoy5 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy5 + 5, "service2" }, + {"Service 3", BIT_DIGITAL, DrvJoy5 + 6, "service3" }, + {"Service 4", BIT_DIGITAL, DrvJoy5 + 7, "service4" }, +}; + +STDINPUTINFO(Esckids) + +static struct BurnInputInfo EsckidsjInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy5 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy5 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, &DrvJoy6, "diag" }, + {"Service 1", BIT_DIGITAL, DrvJoy5 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy5 + 5, "service2" }, +}; + +STDINPUTINFO(Esckidsj) + +void vendetta_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x5fe0: + K052109RMRDLine = data & 0x08; + K053246_set_OBJCHA_line(data & 0x20); + return; + + case 0x5fe2: + { + if (data == 0xff) return; + + EEPROMWrite(data & 0x10, data & 0x08, data & 0x20); + + irq_enabled = (data >> 6) & 1; + + videobank = data & 1; + } + return; + + case 0x5fe4: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x5fe6: + case 0x5fe7: + K053260Write(0, address & 1, data); + return; + } + + if ((address & 0xffe0) == 0x5f80) { + K054000Write(address, data); + return; + } + + if ((address & 0xfff0) == 0x5fa0) { + K053251Write(address & 0x0f, data); + return; + } + + if ((address & 0xfff8) == 0x5fb0) { + K053246Write(address & 7, data); + return; + } + + if (videobank) { + if ((address & 0xf000) == 0x4000) { + address ^= 1; + K053247Write(address & 0x0fff, data); + return; + } + + if ((address & 0xf000) == 0x6000) { + DrvPalRAM[address & 0xfff] = data; + return; + } + } + + if ((address & 0xc000) == 0x4000) { + K052109Write(address & 0x3fff, data); + return; + } +} + +UINT8 vendetta_main_read(UINT16 address) +{ + switch (address) + { + case 0x5fc0: + return DrvInputs[0]; + + case 0x5fc1: + return DrvInputs[1]; + + case 0x5fc2: + return DrvInputs[2]; + + case 0x5fc3: + return DrvInputs[3]; + + case 0x5fd0: + { + INT32 res = (EEPROMRead() & 1) | vblank | ((DrvJoy6 << 2) ^ 0xf6); + + if (init_eeprom_count > 0) + { + init_eeprom_count--; + res &= 0xfb; + } + return res; + } + + case 0x5fd1: + return DrvInputs[4]; + + case 0x5fe4: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return 0; + + case 0x5fe6: + case 0x5fe7: + return K053260Read(0, (address & 1)+2); + + case 0x5fe8: + case 0x5fe9: + return K053246Read(address & 1); + + case 0x5fea: + return 0; // watchdog + } + + if ((address & 0xffe0) == 0x5f80) { + return K054000Read(address); + } + + if (videobank) { + if ((address & 0xf000) == 0x4000) { + address ^= 1; + return K053247Read(address & 0x0fff); + } + + if ((address & 0xf000) == 0x6000) { + return DrvPalRAM[address & 0x0fff]; + } + } + + if ((address & 0xc000) == 0x4000) { + return K052109Read(address & 0x3fff); + } + + return 0; +} + +void esckids_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3fd0: + K052109RMRDLine = data & 0x08; + K053246_set_OBJCHA_line(data & 0x20); + return; + + case 0x3fd2: + { + if (data == 0xff) return; + + EEPROMWrite(data & 0x10, data & 0x08, data & 0x20); + + irq_enabled = (data >> 6) & 1; + + videobank = data & 1; + } + return; + + case 0x3fd4: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x3fd6: + case 0x3fd7: + K053260Write(0, address & 1, data); + return; + } + + if ((address & 0xfff0) == 0x3fb0) { + K053251Write(address & 0x0f, data); + return; + } + + if ((address & 0xfff8) == 0x3fa0) { + K053246Write(address & 7, data); + return; + } + + if (videobank) { + if ((address & 0xf000) == 0x2000) { + address ^= 1; + K053247Write(address & 0x0fff, data); + return; + } + + if ((address & 0xf000) == 0x4000) { + DrvPalRAM[address & 0xfff] = data; + return; + } + } + + if (address >= 0x2000 && address <= 0x5fff) { + K052109Write(address - 0x2000, data); + return; + } +} + +UINT8 esckids_main_read(UINT16 address) +{ + switch (address) + { + case 0x3f80: + return DrvInputs[0]; + + case 0x3f81: + return DrvInputs[1]; + + case 0x3f82: + return DrvInputs[2]; + + case 0x3f83: + return DrvInputs[3]; + + case 0x3f92: + { + INT32 res = (EEPROMRead() & 1) | vblank | ((DrvJoy6 << 2) ^ 0xf6); + + if (init_eeprom_count > 0) + { + init_eeprom_count--; + res &= 0xfb; + } + return res; + } + + case 0x3f93: + return DrvInputs[4]; + + case 0x3fd4: + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return 0; + + case 0x3fd6: + case 0x3fd7: + return K053260Read(0, (address & 1)+2); + + case 0x3fd8: + case 0x3fd9: + return K053246Read(address & 1); + + } + + if (videobank) { + if ((address & 0xf000) == 0x2000) { + address ^= 1; + return K053247Read(address & 0x0fff); + } + + if ((address & 0xf000) == 0x4000) { + return DrvPalRAM[address & 0x0fff]; + } + } + + if (address >= 0x2000 && address <= 0x5fff) { + return K052109Read(address - 0x2000); + } + + return 0; +} + +void __fastcall vendetta_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + BurnYM2151SelectRegister(data); + return; + + case 0xf801: + BurnYM2151WriteRegister(data); + return; + + case 0xfa00: + nCyclesDone[1] += ZetRun(100); + ZetNmi(); + return; + } + + if (address >= 0xfc00 && address < 0xfc30) { + K053260Write(0, address & 0xff, data); + return; + } +} + +UINT8 __fastcall vendetta_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + return 0xff; + case 0xf801: + return BurnYM2151ReadStatus(); + } + + if (address >= 0xfc00 && address < 0xfc30) { + if ((address & 0x3f) == 0x01) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + + return K053260Read(0, address & 0xff); + } + + return 0; +} + +static void vendetta_set_lines(INT32 lines) +{ + nDrvBank[0] = lines; + + if (lines < 0x1c) { + konamiMapMemory(DrvKonROM + 0x10000 + (lines * 0x2000), 0x0000 | bankoffset, 0x1fff | bankoffset, KON_ROM); + } +} + +static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x03) << 8) | ((*color & 0x30) << 6) | ((*color & 0x0c) << 10) | (bank << 14); + *color = layer_colorbase[layer] + ((*color & 0xc0) >> 6); +} + +static void EsckidsK052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *) +{ + *code |= ((*color & 0x03) << 8) | ((*color & 0x10) << 6) | ((*color & 0x0c) << 9) | (bank << 13); + *color = layer_colorbase[layer] + ((*color & 0xe0) >> 5); +} + +static void K053247Callback(INT32 *code, INT32 *color, INT32 *priority) +{ + INT32 pri = (*color & 0x03e0) >> 4; + if (pri <= layerpri[2]) *priority = 0; + else if (pri > layerpri[2] && pri <= layerpri[1]) *priority = 1; + else if (pri > layerpri[1] && pri <= layerpri[0]) *priority = 2; + else *priority = 3; + + *code &= 0x7fff; + + *color = sprite_colorbase + (*color & 0x001f); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + konamiOpen(0); + konamiReset(); + konamiClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + KonamiICReset(); + + K053260Reset(0); + + EEPROMReset(); + + videobank = 0; + + if (EEPROMAvailable()) { + init_eeprom_count = 0; + } else { + init_eeprom_count = 1000; + } + + irq_enabled = 0; + videobank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvKonROM = Next; Next += 0x050000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROMExp0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROMExp1 = Next; Next += 0x800000; + + DrvSndROM = Next; Next += 0x100000; + + Palette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + + DrvKonRAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x001000; + + nDrvBank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x100000); + konami_rom_deinterleave_4(DrvGfxROM1, 0x400000); + + GfxDecode(0x8000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + + K053247GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x400000); + + return 0; +} + +static const eeprom_interface vendetta_eeprom_intf = +{ + 7, // address bits + 8, // data bits + "011000", // read command + "011100", // write command + 0, // erase command + "0100000000000", // lock command + "0100110000000", // unlock command + 0, + 0 +}; + +static INT32 DrvInit(INT32 nGame) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvKonROM + 0x010000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 8, 1)) return 1; + + DrvGfxDecode(); + } + + if (nGame) // escape kids + { + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x28000, 0x8000); + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonRAM, 0x0000, 0x1fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(esckids_main_write); + konamiSetReadHandler(esckids_main_read); + konamiSetlinesCallback(vendetta_set_lines); + konamiClose(); + + K052109Init(DrvGfxROM0, 0x0fffff); + K052109SetCallback(EsckidsK052109Callback); + K052109AdjustScroll(8, -8); + + K053247Init(DrvGfxROM1, 0x3fffff, K053247Callback, 1); + K053247SetSpriteOffset(-11, 14); + + bankoffset = 0x6000; + } else { + memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x48000, 0x8000); + + konamiInit(1); + konamiOpen(0); + konamiMapMemory(DrvKonROM + 0x10000, 0x0000, 0x1fff, KON_ROM); + konamiMapMemory(DrvKonRAM, 0x2000, 0x3fff, KON_RAM); + konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM); + konamiSetWriteHandler(vendetta_main_write); + konamiSetReadHandler(vendetta_main_read); + konamiSetlinesCallback(vendetta_set_lines); + konamiClose(); + + K052109Init(DrvGfxROM0, 0x0fffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(0, 0); + + K053247Init(DrvGfxROM1, 0x3fffff, K053247Callback, 1); + K053247SetSpriteOffset(-53, 22); + + bankoffset = 0; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(vendetta_sound_write); + ZetSetReadHandler(vendetta_sound_read); + ZetMemEnd(); + ZetClose(); + + EEPROMInit(&vendetta_eeprom_intf); + + BurnYM2151Init(3579545, 100.0); + + K053260Init(0, 3579545, DrvSndROM, 0x100000 >> nGame); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + konamiExit(); + ZetExit(); + + EEPROMExit(); + + BurnYM2151Exit(); + K053260Exit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[i] = (r << 16) | (g << 8) | b; + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + K052109UpdateScroll(); + + INT32 layer[3]; + + bg_colorbase = K053251GetPaletteIndex(0); + sprite_colorbase = K053251GetPaletteIndex(1); + layer_colorbase[0] = K053251GetPaletteIndex(2); + layer_colorbase[1] = K053251GetPaletteIndex(3); + layer_colorbase[2] = K053251GetPaletteIndex(4); + + layerpri[0] = K053251GetPriority(2); + layerpri[1] = K053251GetPriority(3); + layerpri[2] = K053251GetPriority(4); + layer[0] = 0; + layer[1] = 1; + layer[2] = 2; + + sortlayers(layer,layerpri); + + BurnTransferClear(); + + // this order makes sense... + if (nSpriteEnable & 8) K053247SpritesRender(DrvGfxROMExp1, 0); + + if (nBurnLayer & 1) K052109RenderLayer(layer[0], 1, DrvGfxROMExp0); + + if (nBurnLayer & 2) K052109RenderLayer(layer[1], 0, DrvGfxROMExp0); + + if (nSpriteEnable & 4) K053247SpritesRender(DrvGfxROMExp1, 1); + if (nSpriteEnable & 2) K053247SpritesRender(DrvGfxROMExp1, 2); + + if (nBurnLayer & 4) K052109RenderLayer(layer[2], 0, DrvGfxROMExp0); + + if (nSpriteEnable & 1) K053247SpritesRender(DrvGfxROMExp1, 3); + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + konamiNewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[3] & 0x0c) == 0) DrvInputs[3] |= 0x0c; + if ((DrvInputs[3] & 0x03) == 0) DrvInputs[3] |= 0x03; + } + + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 6000000 / 60, 3579545 / 60 }; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetOpen(0); + konamiOpen(0); + + vblank = 8; + + INT32 trigger_vblank = (nInterleave / 256) * 240; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = konamiRun(nCyclesSegment); + nCyclesDone[0] += nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[1] += nCyclesSegment; + + if (i == trigger_vblank) vblank = 0; // or 8? + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K053260Update(0, pSoundBuf, nSegmentLength); + } + } + + konamiClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + konamiCpuScan(nAction, pnMin); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + K053260Scan(nAction); + + KonamiICScan(nAction); + + EEPROMScan(nAction, pnMin); + + SCAN_VAR(irq_enabled); + SCAN_VAR(videobank); + SCAN_VAR(nCyclesDone[1]); + } + + if (nAction & ACB_WRITE) { + konamiOpen(0); + vendetta_set_lines(nDrvBank[0]); + konamiClose(); + } + + return 0; +} + + +// Vendetta (World 4 Players ver. T) + +static struct BurnRomInfo vendettaRomDesc[] = { + { "081t01", 0x040000, 0xe76267f5, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendetta.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(vendetta) +STD_ROM_FN(vendetta) + +static INT32 VendettaInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvVendetta = { + "vendetta", NULL, NULL, NULL, "1991", + "Vendetta (World 4 Players ver. T)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendettaRomInfo, vendettaRomName, NULL, NULL, Vendet4pInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Vendetta (World 4 Players ver. R) + +static struct BurnRomInfo vendettarRomDesc[] = { + { "081r01", 0x040000, 0x84796281, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendettar.nv", 0x000080, 0xec3f0449, BRF_OPT }, +}; + +STD_ROM_PICK(vendettar) +STD_ROM_FN(vendettar) + +struct BurnDriver BurnDrvVendettar = { + "vendettar", "vendetta", NULL, NULL, "1991", + "Vendetta (World 4 Players ver. R)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendettarRomInfo, vendettarRomName, NULL, NULL, Vendet4pInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Vendetta (World 2 Players ver. W) + +static struct BurnRomInfo vendetta2pRomDesc[] = { + { "081w01", 0x040000, 0xcee57132, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendetta.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(vendetta2p) +STD_ROM_FN(vendetta2p) + +struct BurnDriver BurnDrvVendetta2p = { + "vendetta2p", "vendetta", NULL, NULL, "1991", + "Vendetta (World 2 Players ver. W)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendetta2pRomInfo, vendetta2pRomName, NULL, NULL, VendettaInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Vendetta (Asia 2 Players ver. U) + +static struct BurnRomInfo vendetta2puRomDesc[] = { + { "081u01", 0x040000, 0xb4d9ade5, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendetta.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(vendetta2pu) +STD_ROM_FN(vendetta2pu) + +struct BurnDriver BurnDrvVendetta2pu = { + "vendetta2pu", "vendetta", NULL, NULL, "1991", + "Vendetta (Asia 2 Players ver. U)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendetta2puRomInfo, vendetta2puRomName, NULL, NULL, VendettaInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Vendetta (Asia 2 Players ver. D) + +static struct BurnRomInfo vendetta2pdRomDesc[] = { + { "081d01", 0x040000, 0x335da495, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendetta.nv", 0x000080, 0xfbac4e30, BRF_OPT }, +}; + +STD_ROM_PICK(vendetta2pd) +STD_ROM_FN(vendetta2pd) + +struct BurnDriver BurnDrvVendetta2pd = { + "vendetta2pd", "vendetta", NULL, NULL, "1991", + "Vendetta (Asia 2 Players ver. D)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendetta2pdRomInfo, vendetta2pdRomName, NULL, NULL, VendettaInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Crime Fighters 2 (Japan 2 Players ver. P) + +static struct BurnRomInfo vendettajRomDesc[] = { + { "081p01", 0x040000, 0x5fe30242, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "081b02", 0x010000, 0x4c604d9b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "081a09", 0x080000, 0xb4c777a9, 3 | BRF_GRA }, // 2 K052109 Tiles + { "081a08", 0x080000, 0x272ac8d9, 3 | BRF_GRA }, // 3 + + { "081a04", 0x100000, 0x464b9aa4, 4 | BRF_GRA }, // 4 K053247 Tiles + { "081a05", 0x100000, 0x4e173759, 4 | BRF_GRA }, // 5 + { "081a06", 0x100000, 0xe9fe6d80, 4 | BRF_GRA }, // 6 + { "081a07", 0x100000, 0x8a22b29a, 4 | BRF_GRA }, // 7 + + { "081a03", 0x100000, 0x14b6baea, 5 | BRF_SND }, // 8 K053260 Samples + + { "vendettaj.nv", 0x000080, 0x3550a54e, BRF_OPT }, +}; + +STD_ROM_PICK(vendettaj) +STD_ROM_FN(vendettaj) + +struct BurnDriver BurnDrvVendettaj = { + "vendettaj", "vendetta", NULL, NULL, "1991", + "Crime Fighters 2 (Japan 2 Players ver. P)\0", NULL, "Konami", "GX081", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, vendettajRomInfo, vendettajRomName, NULL, NULL, VendettaInputInfo, NULL, + VendettaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 304, 224, 4, 3 +}; + + +// Escape Kids (Asia, 4 Players) + +static struct BurnRomInfo esckidsRomDesc[] = { + { "17c.bin", 0x020000, 0x9dfba99c, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "975f02", 0x010000, 0x994fb229, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "975c09", 0x080000, 0xbc52210e, 3 | BRF_GRA }, // 2 K052109 Tiles + { "975c08", 0x080000, 0xfcff9256, 3 | BRF_GRA }, // 3 + + { "975c04", 0x100000, 0x15688a6f, 4 | BRF_GRA }, // 4 K053247 Tiles + { "975c05", 0x100000, 0x1ff33bb7, 4 | BRF_GRA }, // 5 + { "975c06", 0x100000, 0x36d410f9, 4 | BRF_GRA }, // 6 + { "975c07", 0x100000, 0x97ec541e, 4 | BRF_GRA }, // 7 + + { "975c03", 0x080000, 0xdc4a1707, 5 | BRF_SND }, // 8 K053260 Samples + + { "esckids.nv", 0x000080, 0xa8522e1f, BRF_OPT }, +}; + +STD_ROM_PICK(esckids) +STD_ROM_FN(esckids) + +static INT32 EsckidsInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvEsckids = { + "esckids", NULL, NULL, NULL, "1991", + "Escape Kids (Asia, 4 Players)\0", NULL, "Konami", "GX975", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, esckidsRomInfo, esckidsRomName, NULL, NULL, EsckidsInputInfo, NULL, + EsckidsInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x800, + 288, 240, 4, 3 +}; + + +// Escape Kids (Japan, 2 Players) + +static struct BurnRomInfo esckidsjRomDesc[] = { + { "975r01", 0x020000, 0x7b5c5572, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code + + { "975f02", 0x010000, 0x994fb229, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "975c09", 0x080000, 0xbc52210e, 3 | BRF_GRA }, // 2 K052109 Tiles + { "975c08", 0x080000, 0xfcff9256, 3 | BRF_GRA }, // 3 + + { "975c04", 0x100000, 0x15688a6f, 4 | BRF_GRA }, // 4 K053247 Tiles + { "975c05", 0x100000, 0x1ff33bb7, 4 | BRF_GRA }, // 5 + { "975c06", 0x100000, 0x36d410f9, 4 | BRF_GRA }, // 6 + { "975c07", 0x100000, 0x97ec541e, 4 | BRF_GRA }, // 7 + + { "975c03", 0x080000, 0xdc4a1707, 5 | BRF_SND }, // 8 K053260 Samples + + { "esckidsj.nv", 0x000080, 0x985e2a2d, BRF_OPT }, +}; + +STD_ROM_PICK(esckidsj) +STD_ROM_FN(esckidsj) + +struct BurnDriver BurnDrvEsckidsj = { + "esckidsj", "esckids", NULL, NULL, "1991", + "Escape Kids (Japan, 2 Players)\0", NULL, "Konami", "GX975", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_MISC, 0, + NULL, esckidsjRomInfo, esckidsjRomName, NULL, NULL, EsckidsjInputInfo, NULL, + EsckidsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 240, 4, 3 +}; diff --git a/src/burn/drivers/konami/d_xmen.cpp b/src/burn/drivers/konami/d_xmen.cpp new file mode 100644 index 00000000..db1c4bb6 --- /dev/null +++ b/src/burn/drivers/konami/d_xmen.cpp @@ -0,0 +1,1008 @@ +// FB Alpha X-Men driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "konamiic.h" +#include "burn_ym2151.h" +#include "k054539.h" +#include "eeprom.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROMExp0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROMExp1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *nDrvZ80Bank; + +static INT32 interrupt_enable; +static INT32 init_eeprom_count; + +static INT32 sprite_colorbase; +static INT32 bg_colorbase; +static INT32 layerpri[3]; +static INT32 layer_colorbase[3]; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static struct BurnInputInfo XmenInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 10, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy2 + 8, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy2 + 9, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy2 + 10, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy2 + 11, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p3 fire 3" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy1 + 15, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy3 + 11, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy1 + 8, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy1 + 9, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy1 + 10, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy1 + 11, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, DrvJoy3 + 14, "diag" }, +}; + +STDINPUTINFO(Xmen) + +static struct BurnInputInfo Xmen2pInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, DrvJoy3 + 14, "diag" }, + {"Service 1", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy3 + 1, "service2" }, +}; + +STDINPUTINFO(Xmen2p) + +void __fastcall xmen_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x108000: + K052109RMRDLine = data & 0x02; + K053246_set_OBJCHA_line(data & 0x01); + return; + + case 0x108001: + EEPROMWrite(data & 0x08, data & 0x10, data & 0x04); + return; + + case 0x10804d: + *soundlatch = data; + return; + + case 0x10804e: + case 0x10804f: + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x10a001: + // watchdog + return; + + case 0x18fa01: + interrupt_enable = data & 0x04; + return; + } + + if (address >= 0x18c000 && address <= 0x197fff) { + if (address & 1) K052109Write((address - 0x18c000) >> 1, data); + return; + } + + if ((address & 0xfff000) == 0x100000) { + K053247Write((address & 0xfff) ^ 1, data); + return; + } + + if ((address & 0xfffff8) == 0x108020) { + K053246Write((address & 0x007)^1, data); + return; + } + + if ((address & 0xffffe0) == 0x108060) { + if (address & 1) K053251Write((address >> 1) & 0x0f, data); + return; + } +} + +void __fastcall xmen_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0x100000) { + K053247Write(address & 0xffe, data | 0x10000); + return; + } + + if ((address & 0xfffff8) == 0x108020) { + K053246Write((address & 0x006) | 0, data & 0xff); + K053246Write((address & 0x006) | 1, data >> 8); + return; + } +} + +UINT8 __fastcall xmen_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x108054: + case 0x108055: + return *soundlatch2; + + case 0x10a000: + case 0x10a001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x10a002: + case 0x10a003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x10a004: + if (init_eeprom_count > 0) { + init_eeprom_count--; + return 0xbf; + } + return DrvInputs[2] >> 8; + + case 0x10a005: // eeprom_r + init_eeprom_count--; + return (DrvInputs[2] & 0xbf) | (EEPROMRead() << 6); + + case 0x10a00c: + case 0x10a00d: + return K053246Read(~address & 1); + } + + if ((address & 0xfff000) == 0x100000) { + return K053247Read((address & 0xfff)^1); + } + + if (address >= 0x18c000 && address <= 0x197fff) { + return K052109Read((address - 0x18c000) >> 1); + } + + return 0; +} + +UINT16 __fastcall xmen_main_read_word(UINT32 /*address*/) +{ + return 0; +} + +static void bankswitch(INT32 bank) +{ + nDrvZ80Bank[0] = bank & 7; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + nDrvZ80Bank[0] * 0x4000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + nDrvZ80Bank[0] * 0x4000); +} + +void __fastcall xmen_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe800: + case 0xec00: + BurnYM2151SelectRegister(data); + return; + + case 0xe801: + case 0xec01: + BurnYM2151WriteRegister(data); + return; + + case 0xf000: + *soundlatch2 = data; + return; + + case 0xf800: + bankswitch(data); + return; + } + + if (address >= 0xe000 && address <= 0xe22f) { + return K054539Write(0, address & 0x3ff, data); + } +} + +UINT8 __fastcall xmen_sound_read(UINT16 address) +{ + switch (address) + { + case 0xe800: + case 0xe801: + case 0xec00: + case 0xec01: + return BurnYM2151ReadStatus(); + + case 0xf002: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + if (address >= 0xe000 && address <= 0xe22f) { + return K054539Read(0, address & 0x3ff); + } + + return 0; +} + +static void K052109Callback(INT32 layer, INT32 , INT32 *, INT32 *color, INT32 *, INT32 *) +{ + if (layer == 0) + *color = layer_colorbase[layer] + ((*color & 0xf0) >> 4); + else + *color = layer_colorbase[layer] + ((*color & 0x7c) >> 2); +} + +static void K053247Callback(INT32 *code, INT32 *color, INT32 *priority_mask) +{ + INT32 pri = (*color & 0x00e0) >> 4; + if (pri <= layerpri[2]) *priority_mask = 0; + else if (pri > layerpri[2] && pri <= layerpri[1]) *priority_mask = 1; + else if (pri > layerpri[1] && pri <= layerpri[0]) *priority_mask = 2; + else *priority_mask = 3; + + *color = sprite_colorbase + (*color & 0x001f); + *code &= 0x7fff; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + K054539Reset(0); + + KonamiICReset(); + + EEPROMReset(); + + if (EEPROMAvailable()) { + init_eeprom_count = 0; + } else { + init_eeprom_count = 10; + } + + interrupt_enable = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROMExp0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROMExp1 = Next; Next += 0x800000; + + DrvSndROM = Next; Next += 0x200000; + + Palette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + AllRam = Next; + + DrvPalRAM = Next; Next += 0x001000; + Drv68KRAM = Next; Next += 0x005000; + + DrvZ80RAM = Next; Next += 0x002000; + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + + nDrvZ80Bank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x018, 0x010, 0x008, 0x000 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + konami_rom_deinterleave_2(DrvGfxROM0, 0x200000); + konami_rom_deinterleave_4(DrvGfxROM1, 0x400000); + + GfxDecode(0x10000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, DrvGfxROM0, DrvGfxROMExp0); + + K053247GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x400000); + + return 0; +} + +static const eeprom_interface xmen_eeprom_intf = +{ + 7, // address bits + 8, // data bits + "011000", // read command + "011100", // write command + 0, // erase command + "0100000000000", // lock command + "0100110000000", // unlock command + 0, + 0 +}; + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 11, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM + 0x00000, 0x101000, 0x101fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x104000, 0x104fff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x01000, 0x110000, 0x113fff, SM_RAM); + SekSetWriteByteHandler(0, xmen_main_write_byte); + SekSetWriteWordHandler(0, xmen_main_write_word); + SekSetReadByteHandler(0, xmen_main_read_byte); + SekSetReadWordHandler(0, xmen_main_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x8000); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM); + ZetSetWriteHandler(xmen_sound_write); + ZetSetReadHandler(xmen_sound_read); + ZetMemEnd(); + ZetClose(); + + EEPROMInit(&xmen_eeprom_intf); + + K052109Init(DrvGfxROM0, 0x1fffff); + K052109SetCallback(K052109Callback); + K052109AdjustScroll(8, 0); + + K053247Init(DrvGfxROM1, 0x3fffff, K053247Callback, 1); + K053247SetSpriteOffset(-510, 158); + + BurnYM2151Init(4000000, 80.0); + + K054539Init(0, 48000, DrvSndROM, 0x200000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + KonamiICExit(); + + SekExit(); + ZetExit(); + + BurnYM2151Exit(); + K054539Exit(); + + EEPROMExit(); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + return 0; +} + +static void sortlayers(INT32 *layer,INT32 *pri) +{ +#define SWAP(a,b) \ + if (pri[a] < pri[b]) \ + { \ + INT32 t; \ + t = pri[a]; pri[a] = pri[b]; pri[b] = t; \ + t = layer[a]; layer[a] = layer[b]; layer[b] = t; \ + } + + SWAP(0,1) + SWAP(0,2) + SWAP(1,2) +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + INT32 d = p[i]; + + r = (d >> 0) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[i] = (r << 16) | (g << 8) | b; + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + K052109UpdateScroll(); + + INT32 layer[3]; + + bg_colorbase = K053251GetPaletteIndex(4); + sprite_colorbase = K053251GetPaletteIndex(1); + layer_colorbase[0] = K053251GetPaletteIndex(3); + layer_colorbase[1] = K053251GetPaletteIndex(0); + layer_colorbase[2] = K053251GetPaletteIndex(2); + + layerpri[0] = K053251GetPriority(3); + layerpri[1] = K053251GetPriority(0); + layerpri[2] = K053251GetPriority(2); + layer[0] = 0; + layer[1] = 1; + layer[2] = 2; + + sortlayers(layer,layerpri); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 16 * bg_colorbase+1; + } + + if (nSpriteEnable & 8) K053247SpritesRender(DrvGfxROMExp1, 3); + + if (nBurnLayer & 1) K052109RenderLayer(layer[0], 0, DrvGfxROMExp0); + + if (nBurnLayer & 2) K052109RenderLayer(layer[1], 0, DrvGfxROMExp0); + +if (nBurnLayer & 8) { + if (nSpriteEnable & 1) K053247SpritesRender(DrvGfxROMExp1, 0); + if (nSpriteEnable & 2) K053247SpritesRender(DrvGfxROMExp1, 1); + if (nSpriteEnable & 4) K053247SpritesRender(DrvGfxROMExp1, 2); +} + + if (nBurnLayer & 4) K052109RenderLayer(layer[2], 0, DrvGfxROMExp0); + + KonamiBlendCopy(Palette, DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3 * sizeof(short)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear Opposites + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[0] & 0x0c) == 0) DrvInputs[0] |= 0x0c; + if ((DrvInputs[0] & 0x03) == 0) DrvInputs[0] |= 0x03; + if ((DrvInputs[1] & 0xc00) == 0) DrvInputs[1] |= 0xc00; + if ((DrvInputs[1] & 0x300) == 0) DrvInputs[1] |= 0x300; + if ((DrvInputs[0] & 0xc00) == 0) DrvInputs[0] |= 0xc00; + if ((DrvInputs[0] & 0x300) == 0) DrvInputs[0] |= 0x300; + } + + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 16000000 / 60, 8000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCyclesSegment; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesSegment = SekRun(nCyclesSegment); + nCyclesDone[0] += nCyclesSegment; + + if (i == (nInterleave / 2) && interrupt_enable) { + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + } + + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[1] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + K054539Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (interrupt_enable) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + K054539Update(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029705; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + + K054539Scan(nAction); + + KonamiICScan(nAction); + EEPROMScan(nAction, pnMin); + + SCAN_VAR(interrupt_enable); + SCAN_VAR(init_eeprom_count); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(nDrvZ80Bank[0]); + ZetClose(); + } + + EEPROMScan(nAction, pnMin); + + return 0; +} + + +// X-Men (4 Players ver UBB) + +static struct BurnRomInfo xmenRomDesc[] = { + { "065-ubb04.10d", 0x020000, 0xf896c93b, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-ubb05.10f", 0x020000, 0xe02e5d64, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_ubb.nv", 0x000080, 0x52f334ba, BRF_OPT }, +}; + +STD_ROM_PICK(xmen) +STD_ROM_FN(xmen) + +struct BurnDriver BurnDrvXmen = { + "xmen", NULL, NULL, NULL, "1992", + "X-Men (4 Players ver UBB)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmenRomInfo, xmenRomName, NULL, NULL, XmenInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (4 Players ver EBA) + +static struct BurnRomInfo xmeneRomDesc[] = { + { "065-eba04.10d", 0x020000, 0x3588c5ec, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-eba05.10f", 0x020000, 0x79ce32f8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_eba.nv", 0x000080, 0x37f8e77a, BRF_OPT }, +}; + +STD_ROM_PICK(xmene) +STD_ROM_FN(xmene) + +struct BurnDriver BurnDrvXmene = { + "xmene", "xmen", NULL, NULL, "1992", + "X-Men (4 Players ver EBA)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmeneRomInfo, xmeneRomName, NULL, NULL, XmenInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (4 Players ver JBA) + +static struct BurnRomInfo xmenjRomDesc[] = { + { "065-jba04.10d", 0x020000, 0xd86cf5eb, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-jba05.10f", 0x020000, 0xabbc8126, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_jba.nv", 0x000080, 0x7439cea7, BRF_OPT }, +}; + +STD_ROM_PICK(xmenj) +STD_ROM_FN(xmenj) + +struct BurnDriver BurnDrvXmenj = { + "xmenj", "xmen", NULL, NULL, "1992", + "X-Men (4 Players ver JBA)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmenjRomInfo, xmenjRomName, NULL, NULL, XmenInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (2 Players ver EAA) + +static struct BurnRomInfo xmen2peRomDesc[] = { + { "065-eaa04.10d", 0x020000, 0x502861e7, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-eaa05.10f", 0x020000, 0xca6071bf, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_eaa.nv", 0x000080, 0x1cbcb653, BRF_OPT }, +}; + +STD_ROM_PICK(xmen2pe) +STD_ROM_FN(xmen2pe) + +struct BurnDriver BurnDrvXmen2pe = { + "xmen2pe", "xmen", NULL, NULL, "1992", + "X-Men (2 Players ver EAA)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmen2peRomInfo, xmen2peRomName, NULL, NULL, Xmen2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (2 Players ver AAA) + +static struct BurnRomInfo xmen2paRomDesc[] = { + { "065-aaa04.10d", 0x020000, 0x7f8b27c2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-aaa05.10f", 0x020000, 0x841ed636, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_aaa.nv", 0x000080, 0x750fd447, BRF_OPT }, +}; + +STD_ROM_PICK(xmen2pa) +STD_ROM_FN(xmen2pa) + +struct BurnDriver BurnDrvXmen2pa = { + "xmen2pa", "xmen", NULL, NULL, "1992", + "X-Men (2 Players ver AAA)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmen2paRomInfo, xmen2paRomName, NULL, NULL, Xmen2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (2 Players ver JAA) + +static struct BurnRomInfo xmen2pjRomDesc[] = { + { "065-jaa04.10d", 0x020000, 0x66746339, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-jaa05.10f", 0x020000, 0x1215b706, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.9d", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.9f", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.6f", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.15l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.16l", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.2h", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.2l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.1h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.1l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1f", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_jaa.nv", 0x000080, 0x849a9e19, BRF_OPT }, +}; + +STD_ROM_PICK(xmen2pj) +STD_ROM_FN(xmen2pj) + +struct BurnDriver BurnDrvXmen2pj = { + "xmen2pj", "xmen", NULL, NULL, "1992", + "X-Men (2 Players ver JAA)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmen2pjRomInfo, xmen2pjRomName, NULL, NULL, Xmen2pInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// X-Men (6 Players ver ECB) + +static struct BurnRomInfo xmen6pRomDesc[] = { + { "065-ecb04.18g", 0x020000, 0x258eb21f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-ecb05.18j", 0x020000, 0x25997bcd, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.17g", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.17j", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.7b", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.1l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.1h", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.12l", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.17l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.22h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.22l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1d", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_ecb.nv", 0x000080, 0x462c6e1a, BRF_OPT }, +}; + +STD_ROM_PICK(xmen6p) +STD_ROM_FN(xmen6p) + +struct BurnDriverD BurnDrvXmen6p = { + "xmen6p", "xmen", NULL, NULL, "1992", + "X-Men (6 Players ver ECB)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_CLONE, 6, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmen6pRomInfo, xmen6pRomName, NULL, NULL, XmenInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 256, 4, 3 +}; + + +// X-Men (6 Players ver UCB) + +static struct BurnRomInfo xmen6puRomDesc[] = { + { "065-ucb04.18g", 0x020000, 0x0f09b8e0, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "065-ucb05.18j", 0x020000, 0x867becbf, 1 | BRF_PRG | BRF_ESS }, // 1 + { "065-a02.17g", 0x040000, 0xb31dc44c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "065-a03.17j", 0x040000, 0x13842fe6, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "065-a01.7b", 0x020000, 0x147d3a4d, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "065-a08.1l", 0x100000, 0x6b649aca, 3 | BRF_GRA }, // 5 Background Tiles + { "065-a07.1h", 0x100000, 0xc5dc8fc4, 3 | BRF_GRA }, // 6 + + { "065-a09.12l", 0x100000, 0xea05d52f, 4 | BRF_GRA }, // 7 Sprites + { "065-a10.17l", 0x100000, 0x96b91802, 4 | BRF_GRA }, // 8 + { "065-a12.22h", 0x100000, 0x321ed07a, 4 | BRF_GRA }, // 9 + { "065-a11.22l", 0x100000, 0x46da948e, 4 | BRF_GRA }, // 10 + + { "065-a06.1d", 0x200000, 0x5adbcee0, 5 | BRF_SND }, // 11 K054539 Samples + + { "xmen_ucb.nv", 0x000080, 0xf3d0f682, BRF_OPT }, +}; + +STD_ROM_PICK(xmen6pu) +STD_ROM_FN(xmen6pu) + +struct BurnDriverD BurnDrvXmen6pu = { + "xmen6pu", "xmen", NULL, NULL, "1992", + "X-Men (6 Players ver UCB)\0", NULL, "Konami", "GX065", + NULL, NULL, NULL, NULL, + BDF_CLONE, 6, HARDWARE_PREFIX_KONAMI, GBF_SCRFIGHT, 0, + NULL, xmen6puRomInfo, xmen6puRomName, NULL, NULL, XmenInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 256, 4, 3 +}; diff --git a/src/burn/drivers/konami/k051316.cpp b/src/burn/drivers/konami/k051316.cpp new file mode 100644 index 00000000..c3eca676 --- /dev/null +++ b/src/burn/drivers/konami/k051316.cpp @@ -0,0 +1,284 @@ +#include "tiles_generic.h" +#include "konamiic.h" + +static UINT16 *K051316TileMap[3]; +static void (*K051316Callback[3])(INT32 *code,INT32 *color,INT32 *flags); +static INT32 K051316Depth[3]; +static INT32 K051316TransColor[3]; +static UINT8 *K051316Gfx[3]; +static UINT8 *K051316GfxExp[3]; +static INT32 K051316Mask[3]; +static INT32 K051316Offs[3][2]; + +static UINT8 *K051316Ram[3]; +static UINT8 K051316Ctrl[3][16]; +static UINT8 K051316Wrap[3]; + +// Decode 4bpp graphics +static void K051316GfxExpand(UINT8 *src, UINT8 *dst, INT32 len) +{ + for (INT32 i = 0; i < len; i++) { + INT32 d = src[i]; + dst[i * 2 + 0] = d >> 4; + dst[i * 2 + 1] = d & 0x0f; + } +} + +void K051316Init(INT32 chip, UINT8 *gfx, UINT8 *gfxexp, INT32 mask, void (*callback)(INT32 *code,INT32 *color,INT32 *flags), INT32 bpp, INT32 transp) +{ + K051316Ram[chip] = (UINT8*)malloc(0x800); + K051316TileMap[chip] = (UINT16*)malloc(((32 * 16) * (32 * 16)) * sizeof(UINT16)); + + K051316Callback[chip] = callback; + + K051316Depth[chip] = bpp; + K051316Gfx[chip] = gfx; + K051316GfxExp[chip] = gfxexp; + + K051316Mask[chip] = mask; + + if (bpp == 4) { + K051316GfxExpand(gfx, gfxexp, mask+1); + } + + KonamiIC_K051316InUse = 1; + + K051316Offs[chip][0] = K051316Offs[chip][1] = 0; + + K051316TransColor[chip] = transp; +} + +void K051316Reset() +{ + for (INT32 i = 0; i < 3; i++) + { + if (K051316Ram[i]) { + memset (K051316Ram[i], 0, 0x800); + } + + memset (K051316Ctrl[i], 0, 16); + + K051316Wrap[i] = 0; + + if (K051316TileMap[i]) { + memset (K051316TileMap[i], 0, (32 * 16) * (32 * 16) * sizeof(short)); + } + } +} + +void K051316Exit() +{ + for (INT32 i = 0; i < 3; i++) + { + if (K051316Ram[i]) { + free (K051316Ram[i]); + } + K051316Ram[i] = NULL; + + if (K051316TileMap[i]) { + free (K051316TileMap[i]); + } + K051316TileMap[i] = NULL; + + K051316Callback[i] = NULL; + } +} + +void K051316SetOffset(INT32 chip, INT32 xoffs, INT32 yoffs) +{ + K051316Offs[chip][0] = xoffs; + K051316Offs[chip][1] = yoffs; +} + +UINT8 K051316ReadRom(INT32 chip, INT32 offset) +{ + if ((K051316Ctrl[chip][0x0e] & 0x01) == 0) + { + INT32 addr = offset + (K051316Ctrl[chip][0x0c] << 11) + (K051316Ctrl[chip][0x0d] << 19); + if (K051316Depth[chip] <= 4) addr /= 2; + addr &= K051316Mask[chip]; + + return K051316Gfx[chip][addr]; + } + + return 0; +} + +UINT8 K051316Read(INT32 chip, INT32 offset) +{ + return K051316Ram[chip][offset]; +} + +static inline void K051316_write_tile(INT32 offset, INT32 chip) +{ + offset &= 0x3ff; + + INT32 sx = (offset & 0x1f) << 4; + INT32 sy = (offset >> 5) << 4; + + INT32 code = K051316Ram[chip][offset]; + INT32 color = K051316Ram[chip][offset + 0x400]; + INT32 flags = 0; + + (*K051316Callback[chip])(&code,&color,&flags); + + UINT8 *src = K051316GfxExp[chip] + (code * 16 * 16); + UINT16 *dst; + + color <<= K051316Depth[chip]; + + INT32 flipx = flags & 1; + INT32 flipy = flags & 2; + if (flipx) flipx = 0x0f; + if (flipy) flipy = 0x0f; + + for (INT32 y = 0; y < 16; y++, sy++) + { + dst = K051316TileMap[chip] + ((sy << 9) + sx); + + for (INT32 x = 0; x < 16; x++) + { + INT32 pxl = src[((y^flipy) << 4) | (x ^ flipx)]; + + if (pxl != K051316TransColor[chip]) { + dst[x] = color | pxl; + } else { + dst[x] = 0x8000 | color | pxl; + } + } + } +} + +void K051316Write(INT32 chip, INT32 offset, INT32 data) +{ + K051316Ram[chip][offset] = data; + K051316_write_tile(offset & 0x3ff, chip); +} + +void K051316WriteCtrl(INT32 chip, INT32 offset, INT32 data) +{ + K051316Ctrl[chip][offset & 0x0f] = data; +} + +void K051316WrapEnable(INT32 chip, INT32 status) +{ + K051316Wrap[chip] = status; +} + +static inline void copy_roz(INT32 chip, UINT32 startx, UINT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, INT32 wrap, INT32 transp) +{ + UINT16 *dst = pTransDraw; + UINT16 *src = K051316TileMap[chip]; + + UINT32 hshift = 512 << 16; + UINT32 wshift = 512 << 16; + + for (INT32 sy = 0; sy < nScreenHeight; sy++, startx+=incyx, starty+=incyy) + { + UINT32 cx = startx; + UINT32 cy = starty; + + if (wrap) { + if (transp) { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) + { + INT32 pxl = src[(((cy >> 16) & 0x1ff) << 9) | ((cx >> 16) & 0x1ff)]; + + if (!(pxl & 0x8000)) { + *dst = pxl; + } + } + } else { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) { + *dst = src[(((cy >> 16) & 0x1ff) << 9) | ((cx >> 16) & 0x1ff)] & 0x7fff; + } + } + } else { + if (transp) { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) + { + if (cx < wshift && cy < hshift) { + INT32 pxl = src[(((cy >> 16) & 0x1ff) << 9) | ((cx >> 16) & 0x1ff)]; + if (!(pxl & 0x8000)) { + *dst = pxl; + } + } + } + } else { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) + { + UINT32 pos = ((cy >> 16) << 9) | (cx >> 16); + + if (pos >= 0x40000) continue; + + *dst = src[pos] & 0x7fff; + } + } + } + } +} + +void K051316_zoom_draw(INT32 chip, INT32 /*flags*/) +{ + UINT32 startx,starty; + INT32 incxx,incxy,incyx,incyy; + + startx = 256 * ((INT16)(256 * K051316Ctrl[chip][0x00] + K051316Ctrl[chip][0x01])); + incxx = (INT16)(256 * K051316Ctrl[chip][0x02] + K051316Ctrl[chip][0x03]); + incyx = (INT16)(256 * K051316Ctrl[chip][0x04] + K051316Ctrl[chip][0x05]); + starty = 256 * ((INT16)(256 * K051316Ctrl[chip][0x06] + K051316Ctrl[chip][0x07])); + incxy = (INT16)(256 * K051316Ctrl[chip][0x08] + K051316Ctrl[chip][0x09]); + incyy = (INT16)(256 * K051316Ctrl[chip][0x0a] + K051316Ctrl[chip][0x0b]); + + startx -= (16 + K051316Offs[chip][1]) * incyx; + starty -= (16 + K051316Offs[chip][1]) * incyy; + + startx -= (89 + K051316Offs[chip][0]) * incxx; + starty -= (89 + K051316Offs[chip][0]) * incxy; + + copy_roz(chip, startx << 5,starty << 5,incxx << 5,incxy << 5,incyx << 5,incyy << 5, K051316Wrap[chip], K051316TransColor[chip]+1); // transp.. +} + +void K051316RedrawTiles(INT32 chip) +{ + if (K051316Ram[chip]) { + for (INT32 j = 0; j < 0x400; j++) { + K051316_write_tile(j, chip); + } + } +} + +void K051316Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + for (INT32 i = 0; i < 3; i++) { + if (K051316Ram[i]) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K051316Ram[i]; + ba.nLen = 0x800; + ba.szName = "K052109 Ram"; + BurnAcb(&ba); + } + + memset(&ba, 0, sizeof(ba)); + ba.Data = K051316Ctrl[i]; + ba.nLen = 0x010; + ba.szName = "K052109 Control"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(K051316Wrap[0]); + SCAN_VAR(K051316Wrap[1]); + SCAN_VAR(K051316Wrap[2]); + } + + if (nAction & ACB_WRITE) { + K051316RedrawTiles(0); + K051316RedrawTiles(1); + K051316RedrawTiles(2); + } +} diff --git a/src/burn/drivers/konami/k051733.cpp b/src/burn/drivers/konami/k051733.cpp new file mode 100644 index 00000000..155fa7b2 --- /dev/null +++ b/src/burn/drivers/konami/k051733.cpp @@ -0,0 +1,111 @@ +#include "burnint.h" + +static UINT8 K051733Ram[0x20]; + +void K051733Reset() +{ + memset (K051733Ram, 0, 0x20); +} + +void K051733Write(INT32 offset, INT32 data) +{ + K051733Ram[offset & 0x1f] = data; +} + +static INT32 int_sqrt(UINT32 op) +{ + UINT32 i,step; + + i = 0x8000; + step = 0x4000; + while (step) + { + if (i*i == op) return i; + else if (i*i > op) i -= step; + else i += step; + step >>= 1; + } + return i; +} + +UINT8 K051733Read(INT32 offset) +{ + INT32 op1 = (K051733Ram[0x00] << 8) | K051733Ram[0x01]; + INT32 op2 = (K051733Ram[0x02] << 8) | K051733Ram[0x03]; + INT32 op3 = (K051733Ram[0x04] << 8) | K051733Ram[0x05]; + INT32 rad = (K051733Ram[0x06] << 8) | K051733Ram[0x07]; + INT32 yobj1c = (K051733Ram[0x08] << 8) | K051733Ram[0x09]; + INT32 xobj1c = (K051733Ram[0x0a] << 8) | K051733Ram[0x0b]; + INT32 yobj2c = (K051733Ram[0x0c] << 8) | K051733Ram[0x0d]; + INT32 xobj2c = (K051733Ram[0x0e] << 8) | K051733Ram[0x0f]; + + offset &= 0x1f; + + switch (offset) + { + case 0x00: + if (op2) return (op1 / op2) >> 8; + else return 0xff; + + case 0x01: + if (op2) return (op1 / op2) & 0xff; + else return 0xff; + + case 0x02: + if (op2) return (op1 % op2) >> 8; + else return 0xff; + + case 0x03: + if (op2) return (op1 % op2) & 0xff; + else return 0xff; + + case 0x04: + return int_sqrt(op3<<16) >> 8; + + case 0x05: + return int_sqrt(op3<<16) & 0xff; + + case 0x06: + return K051733Ram[0x13]; + + case 0x07:{ + if (xobj1c + rad < xobj2c) + return 0x80; + + if (xobj2c + rad < xobj1c) + return 0x80; + + if (yobj1c + rad < yobj2c) + return 0x80; + + if (yobj2c + rad < yobj1c) + return 0x80; + + return 0; + } + + case 0x0e: + return ~K051733Ram[offset]; + + case 0x0f: + return ~K051733Ram[offset]; + + default: + return K051733Ram[offset]; + } + + return 0; +} + +void K051733Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K051733Ram; + ba.nLen = 0x20; + ba.szName = "K051733 Ram"; + BurnAcb(&ba); + } +} diff --git a/src/burn/drivers/konami/k051960.cpp b/src/burn/drivers/konami/k051960.cpp new file mode 100644 index 00000000..b4f13f3f --- /dev/null +++ b/src/burn/drivers/konami/k051960.cpp @@ -0,0 +1,291 @@ +// K051960 + +#include "tiles_generic.h" +#include "konamiic.h" + +INT32 K051960_irq_enabled; +INT32 K051960_nmi_enabled; +INT32 K051960_spriteflip; + +static UINT8 *K051960Ram = NULL; +static UINT8 K051960SpriteRomBank[3]; +INT32 K051960ReadRoms; +static INT32 K051960RomOffset; +static UINT32 K051960RomMask; +static UINT8 *K051960Rom; +static UINT8 blank_tile[0x100]; + +static INT32 nSpriteXOffset; +static INT32 nSpriteYOffset; + +typedef void (*K051960_Callback)(INT32 *Code, INT32 *Colour, INT32 *Priority, INT32 *Shadow); +static K051960_Callback K051960Callback; + +void K051960SpritesRender(UINT8 *pSrc, INT32 Priority) +{ +#define NUM_SPRITES 128 + INT32 Offset, PriCode; + INT32 SortedList[NUM_SPRITES]; + + for (Offset = 0; Offset < NUM_SPRITES; Offset++) SortedList[Offset] = -1; + + for (Offset = 0; Offset < 0x400; Offset += 8) { + if (K051960Ram[Offset] & 0x80) { + SortedList[K051960Ram[Offset] & 0x7f] = Offset; + } + } + + for (PriCode = 0; PriCode < NUM_SPRITES; PriCode++) { + INT32 ox, oy, Code, Colour, Pri, Shadow, Size, w, h, x, y, xFlip, yFlip, xZoom, yZoom; + + static const INT32 xOffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 }; + static const INT32 yOffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 }; + static const INT32 Width[8] = { 1, 2, 1, 2, 4, 2, 4, 8 }; + static const INT32 Height[8] = { 1, 1, 2, 2, 2, 4, 4, 8 }; + + Offset = SortedList[PriCode]; + if (Offset == -1) continue; + + Code = K051960Ram[Offset + 2] + ((K051960Ram[Offset + 1] & 0x1f) << 8); + Colour = K051960Ram[Offset + 3] & 0xff; + Pri = 0; + Shadow = Colour & 0x80; + K051960Callback(&Code, &Colour, &Pri, &Shadow); + + if (Priority != -1) { + if (Pri != Priority) continue; // not the best way to go about this... + } + + Size = (K051960Ram[Offset + 1] & 0xe0) >> 5; + w = Width[Size]; + h = Height[Size]; + + if (w >= 2) Code &= ~0x01; + if (h >= 2) Code &= ~0x02; + if (w >= 4) Code &= ~0x04; + if (h >= 4) Code &= ~0x08; + if (w >= 8) Code &= ~0x10; + if (h >= 8) Code &= ~0x20; + + ox = (256 * K051960Ram[Offset + 6] + K051960Ram[Offset + 7]) & 0x01ff; + oy = 256 - ((256 * K051960Ram[Offset + 4] + K051960Ram[Offset + 5]) & 0x01ff); + + xFlip = K051960Ram[Offset + 6] & 0x02; + yFlip = K051960Ram[Offset + 4] & 0x02; + xZoom = (K051960Ram[Offset + 6] & 0xfc) >> 2; + yZoom = (K051960Ram[Offset + 4] & 0xfc) >> 2; + xZoom = 0x10000 / 128 * (128 - xZoom); + yZoom = 0x10000 / 128 * (128 - yZoom); + + if (xZoom == 0x10000 && yZoom == 0x10000) { + INT32 sx,sy; + + for (y = 0; y < h; y++) { + sy = oy + 16 * y; + sy -= nSpriteYOffset; + sy -= 16; + + for (x = 0; x < w; x++) { + INT32 c = Code; + + sx = ox + 16 * x; + if (xFlip) c += xOffset[(w - 1 - x)]; + else c += xOffset[x]; + if (yFlip) c += yOffset[(h - 1 - y)]; + else c += yOffset[y]; + + sx &= 0x1ff; + sx -= 104; + sx -= nSpriteXOffset; + + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, sy, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, sy, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, sy, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, sy, Colour, 4, 0, 0, pSrc); + } + } + } + } + } else { + INT32 sx, sy, zw, zh; + + for (y = 0; y < h; y++) { + sy = oy + ((yZoom * y + (1 << 11)) >> 12); + zh = (oy + ((yZoom * (y + 1) + (1 << 11)) >> 12)) - sy; + sy -=nSpriteYOffset; + sy -= 16; + + for (x = 0; x < w; x++) { + INT32 c = Code; + + sx = ox + ((xZoom * x + (1 << 11)) >> 12); + zw = (ox + ((xZoom * (x + 1) + (1 << 11)) >> 12)) - sx; + if (xFlip) c += xOffset[(w - 1 - x)]; + else c += xOffset[x]; + if (yFlip) c += yOffset[(h - 1 - y)]; + else c += yOffset[y]; + + sx &= 0x1ff; + sx -= 104; + sx -= nSpriteXOffset; + + RenderZoomedTile(pTransDraw, pSrc, c, Colour << 4 /*assume 4 bpp*/, 0, sx, sy, xFlip, yFlip, 16, 16, zw << 12, zh << 12); + } + } + } + } +} + +UINT8 K0519060FetchRomData(UINT32 Offset) +{ + INT32 Code, Colour, Pri, Shadow, Off1, Addr; + + Addr = K051960RomOffset + (K051960SpriteRomBank[0] << 8) + ((K051960SpriteRomBank[1] & 0x03) << 16); + Code = (Addr & 0x3ffe0) >> 5; + Off1 = Addr & 0x1f; + Colour = ((K051960SpriteRomBank[1] & 0xfc) >> 2) + ((K051960SpriteRomBank[2] & 0x03) << 6); + Pri = 0; + Shadow = Colour & 0x80; + K051960Callback(&Code, &Colour, &Pri, &Shadow); + + Addr = (Code << 7) | (Off1 << 2) | Offset; + Addr &= K051960RomMask; + + return K051960Rom[Addr]; +} + +UINT8 K051960Read(UINT32 Offset) +{ + if (K051960ReadRoms) { + K051960RomOffset = (Offset & 0x3fc) >> 2; + K0519060FetchRomData(Offset & 3); + } + + return K051960Ram[Offset]; +} + +void K051960Write(UINT32 Offset, UINT8 Data) +{ + K051960Ram[Offset] = Data; +} + +void K051960SetCallback(void (*Callback)(INT32 *Code, INT32 *Colour, INT32 *Priority, INT32 *Shadow)) +{ + K051960Callback = Callback; +} + +void K051960SetSpriteOffset(INT32 x, INT32 y) +{ + nSpriteXOffset = x; + nSpriteYOffset = y; +} + +void K051960Reset() +{ + memset(K051960SpriteRomBank, 0, 3); + K051960ReadRoms = 0; + K051960RomOffset = 0; + + K051960_irq_enabled = 0; + K051960_nmi_enabled = 0; + K051960_spriteflip = 0; +} + +void K051960Init(UINT8* pRomSrc, UINT32 RomMask) +{ + nSpriteXOffset = nSpriteYOffset = 0; + + K051960Ram = (UINT8*)malloc(0x400); + + K051960RomMask = RomMask; + + K051960Rom = pRomSrc; + + KonamiIC_K051960InUse = 1; + + memset (blank_tile, 0, 0x100); + + nSpriteXOffset = nSpriteYOffset = 0; +} + +void K051960Exit() +{ + if (K051960Ram) { + free(K051960Ram); + K051960Ram = NULL; + } + + K051960Callback = NULL; + K051960RomMask = 0; + K051960Rom = NULL; + + memset(K051960SpriteRomBank, 0, 3); + K051960ReadRoms = 0; + K051960RomOffset = 0; + + K051960Callback = NULL; +} + +void K051960Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K051960Ram; + ba.nLen = 0x400; + ba.szName = "K051960 Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(K051960SpriteRomBank); + SCAN_VAR(K051960ReadRoms); + SCAN_VAR(K051960RomOffset); + SCAN_VAR(K051960_irq_enabled); + SCAN_VAR(K051960_nmi_enabled); + SCAN_VAR(K051960_spriteflip); + } +} + +void K051937Write(UINT32 Offset, UINT8 Data) +{ + if (Offset == 0) { + K051960_irq_enabled = Data & 0x01; + K051960_nmi_enabled = Data & 0x04; + K051960_spriteflip = Data & 0x08; + K051960ReadRoms = Data & 0x20; + return; + } + + if (Offset >= 2 && Offset <= 4) { + K051960SpriteRomBank[Offset - 2] = Data; + return; + } +} + +UINT8 K051937Read(UINT32 Offset) +{ + if (K051960ReadRoms && Offset >= 4 && Offset < 8) + { + return K0519060FetchRomData(Offset & 3); + } + else + { + if (Offset == 0) + { + static INT32 counter; + return (counter++) & 1; + } + + return 0; + } +} + diff --git a/src/burn/drivers/konami/k052109.cpp b/src/burn/drivers/konami/k052109.cpp new file mode 100644 index 00000000..cce1f050 --- /dev/null +++ b/src/burn/drivers/konami/k052109.cpp @@ -0,0 +1,554 @@ +// K052109 + +#include "tiles_generic.h" +#include "konamiic.h" + +static UINT8 *K052109Ram = NULL; + +typedef void (*K052109_Callback)(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *Priority); +static K052109_Callback K052109Callback; +static INT32 K052109ScrollX[3]; +static INT32 K052109ScrollY[3]; +static UINT8 K052109ScrollCtrl; +static UINT8 K052109CharRomBank[4]; +static UINT8 K052109CharRomBank2[4]; +INT32 K052109RMRDLine; +static UINT8 K052109RomSubBank; +static UINT32 K052109RomMask; +static UINT8 *K052109Rom; +static INT32 K052109FlipEnable; +INT32 K052109_irq_enabled; + +static INT32 K052109ScrollXOff[3]; +static INT32 K052109ScrollYOff[3]; + +static INT32 K052109EnableRows[3]; +static INT32 K052109EnableLine[3]; +static INT32 K052109ScrollRows[3][256]; +static INT32 K052109EnableCols[3]; +static INT32 K052109ScrollCols[3][64]; + +static INT32 has_extra_video_ram = 0; // xmen kludge + +void K052109UpdateScroll() +{ + K052109EnableLine[2] = K052109EnableLine[1] = 0; + K052109EnableRows[2] = K052109EnableRows[1] = 0; + K052109EnableCols[2] = K052109EnableCols[1] = 0; + + if ((K052109ScrollCtrl & 0x03) == 0x02) // row scroll + { + UINT8 *scrollram = &K052109Ram[0x1a00]; + + K052109ScrollY[1] = K052109Ram[0x180c]; + K052109EnableRows[1] = 1; + + K052109ScrollX[1] = 0; + + for (INT32 offs = 0;offs < 32;offs++) + { + INT32 xscroll = scrollram[2*(offs * 8)+0] + 256 * scrollram[2*(offs*8)+1]; + xscroll -= 6; + K052109ScrollRows[1][offs] = xscroll & 0x1ff; + } + } else { + if ((K052109ScrollCtrl & 0x03) == 0x03) { // line scroll + UINT8 *scrollram = &K052109Ram[0x1a00]; + + K052109ScrollY[1] = K052109Ram[0x180c]; + K052109ScrollX[1] = 0; + + K052109EnableLine[1] = 1; + + for (INT32 offs = 0;offs < 256;offs++) + { + INT32 xscroll = scrollram[2*offs+0] + 256 * scrollram[2*offs+1]; + xscroll -= 6; + K052109ScrollRows[1][offs] = xscroll & 0x1ff; + } + } else { + if ((K052109ScrollCtrl & 0x04) == 0x04) { // column scroll + UINT8 *scrollram = &K052109Ram[0x1800]; + + K052109ScrollX[1] = ((K052109Ram[0x1a00] | (K052109Ram[0x1a01] << 8)) - 6) & 0x1ff; + K052109ScrollY[1] = 0; + K052109EnableCols[1] = 1; + + for (INT32 offs = 0; offs < 512; offs++) { + K052109ScrollCols[1][((offs+K052109ScrollX[1]) & 0x1ff) / 8] = scrollram[offs/8]; + } + + + } else { // scroll + K052109ScrollX[1] = (K052109Ram[0x1a00] + (K052109Ram[0x1a01] << 8) - 6) & 0x1ff; + K052109ScrollY[1] = K052109Ram[0x180c]; + } + } + } + + if ((K052109ScrollCtrl & 0x18) == 0x10) { + UINT8 *scrollram = &K052109Ram[0x3a00]; + + K052109ScrollY[2] = K052109Ram[0x380c]; + K052109ScrollX[2] = 0; + + K052109EnableRows[2] = 1; + + for (INT32 offs = 0;offs < 32;offs++) + { + INT32 xscroll = scrollram[2*(offs * 8)+0] + 256 * scrollram[2*(offs * 8)+1]; + xscroll -= 6; + K052109ScrollRows[2][offs] = xscroll & 0x1ff; + } + } else { + if ((K052109ScrollCtrl & 0x18) == 0x18) { // line scroll + UINT8 *scrollram = &K052109Ram[0x3a00]; + + K052109ScrollY[2] = K052109Ram[0x380c]; + K052109ScrollX[2] = 0; + + K052109EnableLine[2] = 1; + + for (INT32 offs = 0;offs < 256;offs++) + { + K052109ScrollRows[2][offs] = ((scrollram[2*offs+0] + (scrollram[2*offs+1] << 8)) - 6) & 0x1ff; + } + } else { + if ((K052109ScrollCtrl & 0x20) == 0x20) { // column scroll + UINT8 *scrollram = &K052109Ram[0x3800]; + + K052109ScrollX[2] = ((K052109Ram[0x3a00] | (K052109Ram[0x3a01] << 8)) - 6) & 0x1ff; + K052109ScrollY[2] = 0; + K052109EnableCols[2] = 1; + + for (INT32 offs = 0; offs < 512; offs++) { + K052109ScrollCols[2][((offs+K052109ScrollX[2]) & 0x1ff) / 8] = scrollram[offs/8]; + } + + } else { // scroll + K052109ScrollX[2] = (K052109Ram[0x3a00] + (K052109Ram[0x3a01] << 8) - 6) & 0x1ff; + K052109ScrollY[2] = K052109Ram[0x380c]; + } + } + } +} + +void K052109AdjustScroll(INT32 x, INT32 y) +{ + for (INT32 i = 0; i < 3; i++) { + K052109ScrollXOff[i] = x; + K052109ScrollYOff[i] = y; + } +} + +void K052109RenderLayerLineScroll(INT32 nLayer, INT32 Opaque, UINT8 *pSrc) +{ + UINT16 *dst = pTransDraw; + + INT32 Priority = nLayer >> 4; + nLayer &= 0x03; + + for (INT32 my = 0; my < 256; my++) { + + INT32 y2 = (my - (K052109ScrollYOff[nLayer] + 16)) & 0xff; + if (y2 < 0 || y2 >= nScreenHeight) continue; + + for (INT32 mx = 0; mx < 64; mx++) { + INT32 TileIndex = ((my >> 3) << 6) | mx; + + INT32 Colour = K052109Ram[TileIndex + 0x0000]; + INT32 Code = K052109Ram[TileIndex + 0x2000] + (K052109Ram[TileIndex + 0x4000] << 8); + + if (nLayer == 1) { + Colour = K052109Ram[TileIndex + 0x0800]; + Code = K052109Ram[TileIndex + 0x2800] + (K052109Ram[TileIndex + 0x4800] << 8); + } + + if (nLayer == 2) { + Colour = K052109Ram[TileIndex + 0x1000]; + Code = K052109Ram[TileIndex + 0x3000] + (K052109Ram[TileIndex + 0x5000] << 8); + } + + INT32 Bank = K052109CharRomBank[(Colour & 0x0c) >> 2]; + if (has_extra_video_ram) Bank = (Colour & 0x0c) >> 2; /* kludge for X-Men */ + + Colour = (Colour & 0xf3) | ((Bank & 0x03) << 2); + Bank >>= 2; + + INT32 yFlip = Colour & 0x02; + INT32 xFlip = 0; + + INT32 Prio = 0; + + K052109Callback(nLayer, Bank, &Code, &Colour, &xFlip, &Prio); + + if (Prio != Priority) continue; + + if (xFlip && !(K052109FlipEnable & 1)) xFlip = 0; + if (yFlip && !(K052109FlipEnable & 2)) yFlip = 0; + + INT32 x = 8 * mx; + INT32 y = my; + + y -= (K052109ScrollY[nLayer] + K052109ScrollYOff[nLayer] + 16) & 0xff; + if (K052109EnableLine[nLayer]) x -= (104 + K052109ScrollRows[nLayer][my] + K052109ScrollXOff[nLayer]) & 0x1ff; + + if (x < -8) x += 512; + if (y < -8) y += 256; + + if (x >= nScreenWidth) continue; + + UINT8 *src = pSrc + (Code * 0x40); + src += (yFlip ? (~y & 7) : (y & 7)) << 3; + + if (xFlip) xFlip = 0x07; + + INT32 col = Colour << 4; + + for (INT32 xx = 0; xx < 8; xx++, x++) { + if (x < 0 || x >= nScreenWidth) continue; + + INT32 pxl = src[xx ^ xFlip]; + if (!Opaque && !pxl) continue; + + dst[x] = col | pxl; + } + } + + dst += nScreenWidth; + } +} + +void K052109RenderLayer(INT32 nLayer, INT32 Opaque, UINT8 *pSrc) +{ + if (K052109EnableLine[nLayer]) { + K052109RenderLayerLineScroll(nLayer, Opaque, pSrc); + return; + } + + INT32 mx, my, Bank, Code, Colour, x, y, xFlip = 0, yFlip, Priority, TileIndex = 0; + + Priority = nLayer >> 4; + nLayer &= 0x03; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (my << 6) | mx; + + Colour = K052109Ram[TileIndex + 0x0000]; + Code = K052109Ram[TileIndex + 0x2000] + (K052109Ram[TileIndex + 0x4000] << 8); + + if (nLayer == 1) { + Colour = K052109Ram[TileIndex + 0x0800]; + Code = K052109Ram[TileIndex + 0x2800] + (K052109Ram[TileIndex + 0x4800] << 8); + } + + if (nLayer == 2) { + Colour = K052109Ram[TileIndex + 0x1000]; + Code = K052109Ram[TileIndex + 0x3000] + (K052109Ram[TileIndex + 0x5000] << 8); + } + + Bank = K052109CharRomBank[(Colour & 0x0c) >> 2]; + if (has_extra_video_ram) Bank = (Colour & 0x0c) >> 2; /* kludge for X-Men */ + + Colour = (Colour & 0xf3) | ((Bank & 0x03) << 2); + Bank >>= 2; + + yFlip = Colour & 0x02; + + INT32 Prio = 0; + + K052109Callback(nLayer, Bank, &Code, &Colour, &xFlip, &Prio); + + if (Prio != Priority) continue; + + if (xFlip && !(K052109FlipEnable & 1)) xFlip = 0; + if (yFlip && !(K052109FlipEnable & 2)) yFlip = 0; + + x = 8 * mx; + y = 8 * my; + + INT32 scrollx = K052109ScrollX[nLayer] + K052109ScrollXOff[nLayer]; + INT32 scrolly = K052109ScrollY[nLayer] + K052109ScrollYOff[nLayer]; + + if (K052109EnableRows[nLayer]) scrollx += K052109ScrollRows[nLayer][(((my << 3) - scrolly) & 0xff) >> 3]; + if (K052109EnableCols[nLayer]) scrolly += K052109ScrollCols[nLayer][mx]; + + x -= (scrollx + 104) & 0x1ff; + y -= (scrolly + 16) & 0xff; + + if (x < -8) x += 512; + if (y < -8) y += 256; + + if (x >= nScreenWidth || y >= nScreenHeight) continue; + + if (Opaque) { + if (x >= 0 && x <= (nScreenWidth - 8) && y >= 0 && y <= (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } + } + } else { + if (x >= 0 && x <= (nScreenWidth - 8) && y >= 0 && y <= (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } + } + } + } +} + +UINT8 K052109Read(UINT32 Offset) +{ + if (Offset > 0x5fff) return 0; + + if (K052109RMRDLine) { + INT32 Flags = 0; + INT32 Code = (Offset & 0x1fff) >> 5; + INT32 Colour = K052109RomSubBank; + INT32 Bank = K052109CharRomBank[(Colour & 0x0c) >> 2] >> 2; + Bank |= (K052109CharRomBank2[(Colour & 0x0c) >> 2] >> 2); + + if (has_extra_video_ram) + Code |= Colour << 8; /* kludge for X-Men */ + else + K052109Callback(0, Bank, &Code, &Colour, &Flags, &Flags /*actually priority*/); + + INT32 Addr = (Code << 5) + (Offset & 0x1f); + Addr &= K052109RomMask; + + return K052109Rom[Addr]; + } + + return K052109Ram[Offset]; +} + +void K052109Write(UINT32 Offset, UINT8 Data) +{ + if (Offset > 0x5fff) return; + + K052109Ram[Offset] = Data; + + if (Offset >= 0x4000) has_extra_video_ram = 1; /* kludge for X-Men */ + + if ((Offset & 0x1fff) >= 0x1800) { + switch (Offset) { + case 0x1c80: { + K052109ScrollCtrl = Data; + return; + } + + case 0x1d00: { + K052109_irq_enabled = Data & 0x04; + return; + } + + case 0x1d80: { + K052109CharRomBank[0] = Data & 0x0f; + K052109CharRomBank[1] = (Data >> 4) & 0x0f; + return; + } + + case 0x1e00: // Normal.. + case 0x3e00: // Suprise Attack + { + K052109RomSubBank = Data; + return; + } + + case 0x1e80: { + // flip + K052109FlipEnable = ((Data & 0x06) >> 1); + return; + } + + case 0x1f00: { + K052109CharRomBank[2] = Data & 0x0f; + K052109CharRomBank[3] = (Data >> 4) & 0x0f; + return; + } + + case 0x3d80: // Surprise Attack (rom test) + { +// K052109CharRomBank2[0]; +// K052109CharRomBank2[1]; + return; + } + + case 0x3f00: // Surprise Attack (rom test) + { +// K052109CharRomBank2[2]; +// K052109CharRomBank2[3]; + return; + } + + case 0x180c: + case 0x180d: + case 0x1a00: + case 0x1a01: + case 0x380c: + case 0x380d: + case 0x3a00: + case 0x3a01: { + // Scroll Writes + return; + } + + case 0x1c00: { + //??? + return; + } + } + } +} + +void K052109SetCallback(void (*Callback)(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *Priority)) +{ + K052109Callback = Callback; +} + +void K052109Reset() +{ + memset(K052109ScrollX, 0, 3 * sizeof(INT32)); + memset(K052109ScrollY, 0, 3 * sizeof(INT32)); + K052109ScrollCtrl = 0; + memset(K052109CharRomBank, 0, 4); + memset(K052109CharRomBank2,0, 4); + K052109RMRDLine = 0; + K052109RomSubBank = 0; + K052109_irq_enabled = 0; + memset (K052109Ram, 0, 0x6000); + + memset (K052109EnableRows, 0, 3 * sizeof(INT32)); + memset (K052109EnableLine, 0, 3 * sizeof(INT32)); + memset (K052109ScrollRows, 0, 256 * 3 * sizeof(INT32)); + memset (K052109EnableCols, 0, 3 * sizeof(INT32)); + memset (K052109ScrollCols, 0, 64 * 3 * sizeof(INT32)); +} + +void K052109Init(UINT8 *pRomSrc, UINT32 RomMask) +{ + K052109Ram = (UINT8*)malloc(0x6000); + + K052109RomMask = RomMask; + + K052109Rom = pRomSrc; + + KonamiIC_K052109InUse = 1; + + for (INT32 i = 0; i < 3; i++) { + K052109ScrollXOff[i]=0; + K052109ScrollYOff[i]=0; + } + + has_extra_video_ram = 0; +} + +void K052109Exit() +{ + if (K052109Ram) { + free(K052109Ram); + K052109Ram = NULL; + } + + K052109Callback = NULL; + K052109RomMask = 0; + K052109Rom = NULL; + + memset(K052109ScrollX, 0, 3); + memset(K052109ScrollY, 0, 3); + K052109ScrollCtrl = 0; + memset(K052109CharRomBank, 0, 4); + K052109RMRDLine = 0; + K052109RomSubBank = 0; + K052109FlipEnable = 0; + K052109_irq_enabled = 0; + + has_extra_video_ram = 0; +} + +void K052109Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K052109Ram; + ba.nLen = 0x6000; + ba.szName = "K052109 Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(K052109ScrollX[0]); + SCAN_VAR(K052109ScrollX[1]); + SCAN_VAR(K052109ScrollX[2]); + SCAN_VAR(K052109ScrollY[0]); + SCAN_VAR(K052109ScrollY[1]); + SCAN_VAR(K052109ScrollY[2]); + SCAN_VAR(K052109ScrollCtrl); + SCAN_VAR(K052109ScrollCtrl); + SCAN_VAR(K052109CharRomBank[0]); + SCAN_VAR(K052109CharRomBank[1]); + SCAN_VAR(K052109CharRomBank[2]); + SCAN_VAR(K052109CharRomBank[3]); + SCAN_VAR(K052109CharRomBank2[0]); + SCAN_VAR(K052109CharRomBank2[1]); + SCAN_VAR(K052109CharRomBank2[2]); + SCAN_VAR(K052109CharRomBank2[3]); + SCAN_VAR(K052109RMRDLine); + SCAN_VAR(K052109RomSubBank); + SCAN_VAR(K052109FlipEnable); + SCAN_VAR(K052109_irq_enabled); + SCAN_VAR(has_extra_video_ram); + } +} diff --git a/src/burn/drivers/konami/k053245.cpp b/src/burn/drivers/konami/k053245.cpp new file mode 100644 index 00000000..b2032048 --- /dev/null +++ b/src/burn/drivers/konami/k053245.cpp @@ -0,0 +1,453 @@ +#include "tiles_generic.h" +#include "konamiic.h" + +static void (*K053245Callback[2])(INT32 *code,INT32 *color,INT32 *priority); + +static UINT8 *K053245Ram[2]; +static UINT8 *K053245Buf[2]; +static UINT8 *K053245Gfx[2]; +static INT32 K053245Mask[2]; +static INT32 K053245_dx[2]; +static INT32 K053245_dy[2]; + +static UINT16 *K053245Temp = NULL; + +static UINT8 K053244Regs[2][0x10]; +static INT32 K053244Bank[2]; + +static INT32 K053245Active = 0; + +// Init, Reset, Exit + +INT32 K053245Reset() +{ + for (INT32 i = 0; i < K053245Active; i++) { + memset (K053245Ram[i], 0, 0x800); + memset (K053245Buf[i], 0, 0x800); + memset (K053244Regs[i], 0, 0x10); + + K053244Bank[i] = 0; + } + + return 0; +} + +void K053245GfxDecode(UINT8 *src, UINT8 *dst, INT32 len) +{ + INT32 Plane[4] = { 24, 16, 8, 0 }; + INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8*32+0, 8*32+1, 8*32+2, 8*32+3, 8*32+4, 8*32+5, 8*32+6, 8*32+7 }; + INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32,16*32, 17*32, 18*32, 19*32, 20*32, 21*32, 22*32, 23*32 }; + + GfxDecode(len >> 7, 4, 16, 16, Plane, XOffs, YOffs, 0x400, src, dst); +} + +void K053245Init(INT32 chip, UINT8 *gfx, INT32 mask, void (*callback)(INT32 *code,INT32 *color,INT32 *priority)) +{ + K053245Ram[chip] = (UINT8*)malloc(0x800); // enough + K053245Buf[chip] = (UINT8*)malloc(0x800); // enough + + K053245Mask[chip] = mask; + + K053245Gfx[chip] = gfx; + + K053245Callback[chip] = callback; + + K053245Active++; + + KonamiIC_K053245InUse = 1; + + if (konami_temp_screen == NULL) { + INT32 width, height; + BurnDrvGetVisibleSize(&width, &height); + konami_temp_screen = (UINT16*)malloc(width * height * 2); + } + + K053245Temp = konami_temp_screen; + + K053245Reset(); +} + +void K053245Exit() +{ + K053245Temp = NULL; + + for (INT32 i = 0; i < K053245Active; i++) { + if (K053245Ram[i]) { + free (K053245Ram[i]); + K053245Ram[i] = NULL; + } + if (K053245Buf[i]) { + free (K053245Buf[i]); + K053245Buf[i] = NULL; + } + + K053245_dx[i] = 0; + K053245_dy[i] = 0; + } + + K053245Active = 0; +} + +// Useful functions + +void K053245SetSpriteOffset(INT32 chip,INT32 offsx, INT32 offsy) +{ + K053245_dx[chip] = offsx; + K053245_dy[chip] = offsy; +} + +void K053245ClearBuffer(INT32 chip) +{ + UINT16 *buf = (UINT16*)K053245Buf[chip]; + + for (INT32 i = 0; i < 0x800/2; i+=8) buf[i] = 0; +} + +void K053245UpdateBuffer(INT32 chip) +{ + memcpy (K053245Buf[chip], K053245Ram[chip], 0x800); +} + +void K053244BankSelect(INT32 chip, INT32 bank) +{ + K053244Bank[chip] = bank; +} + + +// 8 bit read/write handlers + +UINT8 K053245Read(INT32 chip, INT32 offset) +{ + return K053245Ram[chip][offset ^ 1]; // +} + +void K053245Write(INT32 chip, INT32 offset, INT32 data) +{ + K053245Ram[chip][offset ^ 1] = data; // +} + +UINT16 K053245ReadWord(INT32 chip, INT32 offset) +{ + UINT16 *ret = (UINT16*)K053245Ram[chip]; + +#if 0 + INT32 r = ret[offset]; + + return (r << 8) | (r >> 8); +#else + return ret[offset]; +#endif +} + +void K053245WriteWord(INT32 chip, INT32 offset, INT32 data) +{ + UINT16 *ret = (UINT16*)K053245Ram[chip]; + +#if 0 + ret[offset] = (data << 8) | (data >> 8); +#else + ret[offset] = data; +#endif +} + +UINT8 K053244Read(INT32 chip, INT32 offset) +{ + if (K053244Regs[chip][5] & 0x10 && (offset & 0x0c) == 0x0c) + { + INT32 addr = (K053244Bank[chip] << 19) | ((K053244Regs[chip][11] & 0x07) << 18); + addr |= (K053244Regs[chip][8] << 10) | (K053244Regs[chip][ 9] << 2); + addr |= (offset & 3) ^ 1; + addr &= K053245Mask[chip]; + + return K053245Gfx[chip][addr]; + } + else if (offset == 0x06) { + K053245UpdateBuffer(chip); + } + + return 0; +} + +void K053244Write(INT32 chip, INT32 offset, INT32 data) +{ + K053244Regs[chip][offset] = data; + + if (offset == 0x06) { + K053245UpdateBuffer(chip); + } +} + +// Sprite Rendering + +static void RenderZoomedShadowTile(UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 width, INT32 height, INT32 zoomx, INT32 zoomy) +{ + INT32 h = ((zoomy << 4) + 0x8000) >> 16; + INT32 w = ((zoomx << 4) + 0x8000) >> 16; + + if (!h || !w || sx + w < 0 || sy + h < 0 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + if (fy) fy = (height-1)*width; + if (fx) fy |= (width-1); + + INT32 hz = (height << 12) / h; + INT32 wz = (width << 12) / w; + + INT32 starty = 0, startx = 0, endy = h, endx = w; + if (sy < 0) starty = 0 - sy; + if (sx < 0) startx = 0 - sx; + if (sy + h >= nScreenHeight) endy -= (h + sy) - nScreenHeight; + if (sx + w >= nScreenWidth ) endx -= (w + sx) - nScreenWidth; + + UINT8 *src = gfx + (code * width * height); + UINT16 *dst = konami_temp_screen + (sy + starty) * nScreenWidth + sx; + UINT16 *pTemp = pTransDraw + (sy + starty) * nScreenWidth + sx; + + INT32 or1 = 0x8000; + + for (INT32 y = starty; y < endy; y++) + { + INT32 zy = ((y * hz) >> 12) * width; + + for (INT32 x = startx; x < endx; x++) + { + INT32 pxl = src[(zy + ((x * wz) >> 12)) ^ fy]; + + if (pxl) { + if (pxl == 15) { + dst[x] = color | pxl; + pTemp[x] |= or1; + } else { + pTemp[x] = color | pxl; + } + } + } + + dst += nScreenWidth; + pTemp += nScreenWidth; + } +} + +void K053245SpritesRender(INT32 chip, UINT8 *gfxdata, INT32 priority) +{ +#define NUM_SPRITES 128 + INT32 offs,pri_code,i; + INT32 sortedlist[NUM_SPRITES]; + INT32 flipscreenX, flipscreenY, spriteoffsX, spriteoffsY; + + flipscreenX = K053244Regs[chip][5] & 0x01; + flipscreenY = K053244Regs[chip][5] & 0x02; + spriteoffsX = (K053244Regs[chip][0] << 8) | K053244Regs[chip][1]; + spriteoffsY = (K053244Regs[chip][2] << 8) | K053244Regs[chip][3]; + + for (offs = 0;offs < NUM_SPRITES;offs++) + sortedlist[offs] = -1; + + UINT16 *sprbuf = (UINT16*)K053245Buf[chip]; + + /* prebuild a sorted table */ + for (i=0x800/2, offs=0; offs> 2) + ((code & 0x0008) << 1) + + ((code & 0x0004) >> 1) + ((code & 0x0002) << 2)); + color = sprbuf[offs+6] & 0x00ff; + pri = 0; + + (*K053245Callback[chip])(&code,&color,&pri); + + if (pri != priority) continue;//------------------------------------------------------- OK?? + + size = (sprbuf[offs] & 0x0f00) >> 8; + + w = 1 << (size & 0x03); + h = 1 << ((size >> 2) & 0x03); + + /* zoom control: + 0x40 = normal scale + <0x40 enlarge (0x20 = double size) + >0x40 reduce (0x80 = half size) + */ + zoomy = sprbuf[offs+4]; + if (zoomy > 0x2000) continue; + if (zoomy) zoomy = (0x400000+zoomy/2) / zoomy; + else zoomy = 2 * 0x400000; + if ((sprbuf[offs] & 0x4000) == 0) + { + zoomx = sprbuf[offs+5]; + if (zoomx > 0x2000) continue; + if (zoomx) zoomx = (0x400000+zoomx/2) / zoomx; + else zoomx = 2 * 0x400000; +// else zoomx = zoomy; /* workaround for TMNT2 */ + } + else zoomx = zoomy; + + ox = sprbuf[offs+3] + spriteoffsX; + oy = sprbuf[offs+2]; + + ox += K053245_dx[chip]; + oy += K053245_dy[chip]; + + flipx = sprbuf[offs] & 0x1000; + flipy = sprbuf[offs] & 0x2000; + mirrorx = sprbuf[offs+6] & 0x0100; + if (mirrorx) flipx = 0; // documented and confirmed + mirrory = sprbuf[offs+6] & 0x0200; + shadow = sprbuf[offs+6] & 0x0080; + + if (flipscreenX) + { + ox = 512 - ox; + if (!mirrorx) flipx = !flipx; + } + if (flipscreenY) + { + oy = -oy; + if (!mirrory) flipy = !flipy; + } + + ox = (ox + 0x5d) & 0x3ff; + if (ox >= 768) ox -= 1024; + oy = (-(oy + spriteoffsY + 0x07)) & 0x3ff; + if (oy >= 640) oy -= 1024; + + /* the coordinates given are for the *center* of the sprite */ + ox -= (zoomx * w) >> 13; + oy -= (zoomy * h) >> 13; + + for (y = 0;y < h;y++) + { + INT32 sx,sy,zw,zh; + + sy = oy + ((zoomy * y + (1<<11)) >> 12); + zh = (oy + ((zoomy * (y+1) + (1<<11)) >> 12)) - sy; + + for (x = 0;x < w;x++) + { + INT32 c,fx,fy; + + sx = ox + ((zoomx * x + (1<<11)) >> 12); + zw = (ox + ((zoomx * (x+1) + (1<<11)) >> 12)) - sx; + c = code; + if (mirrorx) + { + if ((flipx == 0) ^ (2*x < w)) + { + /* mirror left/right */ + c += (w-x-1); + fx = 1; + } + else + { + c += x; + fx = 0; + } + } + else + { + if (flipx) c += w-1-x; + else c += x; + fx = flipx; + } + if (mirrory) + { + if ((flipy == 0) ^ (2*y >= h)) + { + /* mirror top/bottom */ + c += 8*(h-y-1); + fy = 1; + } + else + { + c += 8*y; + fy = 0; + } + } + else + { + if (flipy) c += 8*(h-1-y); + else c += 8*y; + fy = flipy; + } + + c = (c & 0x3f) | (code & ~0x3f); + + if (shadow) { + RenderZoomedShadowTile(gfxdata, c, color << 4, sx, sy, fx, fy, 16, 16, zw << 12, zh << 12); + continue; + } + + if (zoomx == 0x10000 && zoomy == 0x10000) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxdata); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxdata); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxdata); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxdata); + } + } + } + else + { + RenderZoomedTile(pTransDraw, gfxdata, c, color << 4, 0, sx, sy, fx, fy, 16, 16, zw << 12, zh << 12); + } + } + } + } +} + +void K053245Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + for (INT32 i = 0; i < 2; i++) { + if (K053245Ram[i]) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K053245Ram[i]; + ba.nLen = 0x800; + ba.szName = "K053245 Ram"; + BurnAcb(&ba); + + ba.Data = K053245Buf[i]; + ba.nLen = 0x800; + ba.szName = "K053245 Buffer"; + BurnAcb(&ba); + } + + memset(&ba, 0, sizeof(ba)); + ba.Data = K053244Regs[i]; + ba.nLen = 0x010; + ba.szName = "K053244 Registers"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(K053244Bank[0]); + SCAN_VAR(K053244Bank[1]); + } +} diff --git a/src/burn/drivers/konami/k053247.cpp b/src/burn/drivers/konami/k053247.cpp new file mode 100644 index 00000000..ca5954e2 --- /dev/null +++ b/src/burn/drivers/konami/k053247.cpp @@ -0,0 +1,566 @@ +#include "tiles_generic.h" +#include "konamiic.h" + +#define K053247_CUSTOMSHADOW 0x20000000 +#define K053247_SHDSHIFT 20 + +static UINT8 K053246Regs[8]; +static UINT8 K053246_OBJCHA_line; +static UINT8 *K053247Ram; +static UINT16 K053247Regs[16]; + +static UINT8 *K053246Gfx; +static UINT32 K053246Mask; + +static UINT16 *K053247Temp = NULL; + +static INT32 K053247_dx; +static INT32 K053247_dy; +static INT32 K053247_wraparound; + +static INT32 K053247Flags; + +static void (*K053247Callback)(INT32 *code, INT32 *color, INT32 *priority); + +void K053247Reset() +{ + memset (K053247Ram, 0, 0x1000); + memset (K053247Regs, 0, 16 * sizeof (UINT16)); + memset (K053246Regs, 0, 8); + + K053246_OBJCHA_line = 0; // clear +} + +void K053247Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K053247Ram; + ba.nLen = 0x1000; + ba.szName = "K053247 Ram"; + BurnAcb(&ba); + + ba.Data = K053247Regs; + ba.nLen = 0x0010 * sizeof(UINT16); + ba.szName = "K053247 Regs"; + BurnAcb(&ba); + + ba.Data = K053246Regs; + ba.nLen = 0x0008; + ba.szName = "K053246 Regs"; + BurnAcb(&ba); + + SCAN_VAR(K053246_OBJCHA_line); + SCAN_VAR(K053247_wraparound); + } +} + +void K053247Init(UINT8 *gfxrom, INT32 gfxlen, void (*Callback)(INT32 *code, INT32 *color, INT32 *priority), INT32 flags) +{ + K053247Ram = (UINT8*)malloc(0x1000); + + K053246Gfx = gfxrom; + K053246Mask = gfxlen; + + K053247Callback = Callback; + + K053247_dx = 0; + K053247_dy = 0; + K053247_wraparound = 1; + + if (konami_temp_screen == NULL) { + INT32 width, height; + BurnDrvGetVisibleSize(&width, &height); + konami_temp_screen = (UINT16*)malloc(width * height * 2); + } + + K053247Temp = konami_temp_screen; + + K053247Flags = flags; // 0x02 highlight, 0x01 shadow + + KonamiIC_K053247InUse = 1; +} + +void K053247Exit() +{ + K053247Temp = NULL; + + if (K053247Ram) { + free (K053247Ram); + K053247Ram = NULL; + } + + K053247Flags = 0; + + memset (K053247Regs, 0, 16 * sizeof(UINT16)); +} + +void K053247Export(UINT8 **ram, UINT8 **gfx, void (**callback)(INT32 *, INT32 *, INT32 *), INT32 *dx, INT32 *dy) +{ + if (ram) *ram = K053247Ram; + if (gfx) *gfx = K053246Gfx; + + if (dx) *dx = K053247_dx; + if (dy) *dy = K053247_dy; + + if(callback) *callback = K053247Callback; +} + +void K053247GfxDecode(UINT8 *src, UINT8 *dst, INT32 len) // 16x16 +{ + for (INT32 i = 0; i < len; i++) + { + INT32 t = src[i^1]; + dst[(i << 1) + 0] = t >> 4; + dst[(i << 1) + 1] = t & 0x0f; + } +} + +void K053247SetSpriteOffset(INT32 offsx, INT32 offsy) +{ + K053247_dx = offsx; + K053247_dy = offsy; +} + +void K053247WrapEnable(INT32 status) +{ + K053247_wraparound = status; +} + +UINT8 K053247Read(INT32 offset) +{ + return K053247Ram[offset & 0xfff]; +} + +void K053247Write(INT32 offset, INT32 data) +{ + if (data & 0x10000) { // use word + *((UINT16*)(K053247Ram + (offset & 0xffe))) = data; + } else { + K053247Ram[offset & 0xfff] = data; + } +} + +UINT8 K053246Read(INT32 offset) +{ + if (K053246_OBJCHA_line) // assert_line + { + INT32 addr; + + addr = (K053246Regs[6] << 17) | (K053246Regs[7] << 9) | (K053246Regs[4] << 1) | ((offset & 1) ^ 1); + addr &= K053246Mask; + + return K053246Gfx[addr]; + } + else + { + return 0; + } +} + +void K053246Write(INT32 offset, INT32 data) +{ + if (data & 0x10000) { // handle it as a word + *((UINT16*)(K053246Regs + (offset & 6))) = data; + } else { + K053246Regs[offset & 7] = data; + } +} + +void K053246_set_OBJCHA_line(INT32 state) +{ + K053246_OBJCHA_line = state; +} + +INT32 K053246_is_IRQ_enabled() +{ + return K053246Regs[5] & 0x10; +} + +static void RenderZoomedShadowTile(UINT8 *gfx, INT32 code, INT32 color, UINT8 *t, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 width, INT32 height, INT32 zoomx, INT32 zoomy, INT32 highlight) +{ + INT32 h = ((zoomy << 4) + 0x8000) >> 16; + INT32 w = ((zoomx << 4) + 0x8000) >> 16; + + if (!h || !w || sx + w < 0 || sy + h < 0 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + if (fy) fy = (height-1)*width; + if (fx) fy |= (width-1); + + INT32 hz = (height << 12) / h; + INT32 wz = (width << 12) / w; + + INT32 starty = 0, startx = 0, endy = h, endx = w; + if (sy < 0) starty = 0 - sy; + if (sx < 0) startx = 0 - sx; + if (sy + h >= nScreenHeight) endy -= (h + sy) - nScreenHeight; + if (sx + w >= nScreenWidth ) endx -= (w + sx) - nScreenWidth; + + UINT8 *src = gfx + (code * width * height); + UINT16 *dst = K053247Temp + (sy + starty) * nScreenWidth + sx; + UINT16 *pTemp = pTransDraw + (sy + starty) * nScreenWidth + sx; + + INT32 or1 = 0x8000 >> highlight; + + for (INT32 y = starty; y < endy; y++) + { + INT32 zy = ((y * hz) >> 12) * width; + + for (INT32 x = startx; x < endx; x++) + { + INT32 pxl = src[(zy + ((x * wz) >> 12)) ^ fy]; + + if (pxl) { + if (t[pxl] == 2) { + dst[x] = color | pxl; + pTemp[x] |= or1; + } else { + pTemp[x] = color | pxl; + } + } + } + + dst += nScreenWidth; + pTemp += nScreenWidth; + } +} + +void K053247SpritesRender(UINT8 *gfxbase, INT32 priority) +{ +#define NUM_SPRITES 256 + + UINT8 dtable[256]; + UINT8 stable[256]; + UINT8 *wtable; + + memset(dtable, 1, 256); + dtable[0] = 0; + memset(stable, 2, 256); + stable[0] = 0; + + static const INT32 xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 }; + static const INT32 yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 }; + + INT32 sortedlist[NUM_SPRITES]; + INT32 offs,zcode; + INT32 ox,oy,color,code,size,w,h,x,y,xa,ya,flipx,flipy,mirrorx,mirrory,shadow,zoomx,zoomy,primask; + INT32 nozoom,count,temp,shdmask; + + INT32 flipscreenx = K053246Regs[5] & 0x01; + INT32 flipscreeny = K053246Regs[5] & 0x02; + INT32 offx = (INT16)((K053246Regs[0] << 8) | K053246Regs[1]); + INT32 offy = (INT16)((K053246Regs[2] << 8) | K053246Regs[3]); + + UINT16 *SprRam = (UINT16*)K053247Ram; + + INT32 screen_width = nScreenWidth-1; + + if (K053247Flags & 1) { + if (K053247Flags & 2) { + shdmask = 3; + } else { + shdmask = 0; + } + } else { + shdmask = -1; + } + + // Prebuild a sorted table by descending Z-order. + zcode = K05324xZRejection; + offs = count = 0; + + if (zcode == -1) + { + for (; offs<0x800; offs+=8) + if (SprRam[offs] & 0x8000) sortedlist[count++] = offs; + } + else + { + for (; offs<0x800; offs+=8) + if ((SprRam[offs] & 0x8000) && ((SprRam[offs] & 0xff) != zcode)) sortedlist[count++] = offs; + } + + w = count; + count--; + h = count; + + if (!(K053247Regs[0xc/2] & 0x10)) + { + // sort objects in decending order(smaller z closer) when OPSET PRI is clear + for (y=0; y= code) { zcode = code; sortedlist[x] = offs; sortedlist[y] = offs = temp; } + } + } + } + + for (INT32 i = 0; i <= count; i++) + { + offs = sortedlist[i]; + + code = SprRam[offs+1]; + shadow = color = SprRam[offs+6]; + primask = 0; + + (*K053247Callback)(&code,&color,&primask); + + if (primask != priority) continue; //--------------------------------------- fix me! + + temp = SprRam[offs]; + + size = (temp & 0x0f00) >> 8; + w = 1 << (size & 0x03); + h = 1 << ((size >> 2) & 0x03); + + /* the sprite can start at any point in the 8x8 grid. We have to */ + /* adjust the offsets to draw it correctly. Simpsons does this all the time. */ + xa = 0; + ya = 0; + if (code & 0x01) xa += 1; + if (code & 0x02) ya += 1; + if (code & 0x04) xa += 2; + if (code & 0x08) ya += 2; + if (code & 0x10) xa += 4; + if (code & 0x20) ya += 4; + code &= ~0x3f; + + oy = (INT16)SprRam[offs+2]; + ox = (INT16)SprRam[offs+3]; + + if (K053247_wraparound) + { + offx &= 0x3ff; + offy &= 0x3ff; + oy &= 0x3ff; + ox &= 0x3ff; + } + + y = zoomy = SprRam[offs+4] & 0x3ff; + if (zoomy) zoomy = (0x400000+(zoomy>>1)) / zoomy; else zoomy = 0x800000; + if (!(temp & 0x4000)) + { + x = zoomx = SprRam[offs+5] & 0x3ff; + if (zoomx) zoomx = (0x400000+(zoomx>>1)) / zoomx; + else zoomx = 0x800000; + } + else { zoomx = zoomy; x = y; } + + if ( K053246Regs[5] & 0x08 ) // Check only "Bit #3 is '1'?" (NOTE: good guess) + { + zoomx >>= 1; // Fix sprite width to HALF size + ox = (ox >> 1) + 1; // Fix sprite draw position + if (flipscreenx) ox += screen_width; + nozoom = 0; + } + else + nozoom = (x == 0x40 && y == 0x40); + + flipx = temp & 0x1000; + flipy = temp & 0x2000; + mirrorx = shadow & 0x4000; + if (mirrorx) flipx = 0; // documented and confirmed + mirrory = shadow & 0x8000; + + INT32 highlight = 0; + + wtable = dtable; + if (color == -1) + { + // drop the entire sprite to shadow unconditionally + if (shdmask < 0) continue; + color = 0; + shadow = -1; + wtable = stable; + } + else + { + if (shdmask >= 0) + { + shadow = (color & 0x20000000) ? (color >> 20) : (shadow >> 10); + if (shadow &= 3) { + if (((shadow-1) & shdmask) == 1) highlight = 1; + } + } + else + shadow = 0; + } + + color &= 0xffff; // strip attribute flags + + if (flipscreenx) + { + ox = -ox; + if (!mirrorx) flipx = !flipx; + } + if (flipscreeny) + { + oy = -oy; + if (!mirrory) flipy = !flipy; + } + + // apply wrapping and global offsets + if (K053247_wraparound) + { + ox = ( ox - offx) & 0x3ff; + oy = (-oy - offy) & 0x3ff; + if (ox >= 0x300) ox -= 0x400; + if (oy >= 0x280) oy -= 0x400; + } + else + { + ox = ox - offx; + oy = -oy - offy; + } + ox += K053247_dx; + oy -= K053247_dy; + + ox = ((ox+16) & 0x3ff) - 16; + oy = ((oy+16) & 0x3ff) - 16; + + // apply global and display window offsets + + /* the coordinates given are for the *center* of the sprite */ + ox -= (zoomx * w) >> 13; + oy -= (zoomy * h) >> 13; + + dtable[15] = shadow ? 2 : 1; + + for (y = 0;y < h;y++) + { + INT32 sx,sy,zw,zh; + + sy = oy + ((zoomy * y + (1<<11)) >> 12); + zh = (oy + ((zoomy * (y+1) + (1<<11)) >> 12)) - sy; + + for (x = 0;x < w;x++) + { + INT32 c,fx,fy; + + sx = ox + ((zoomx * x + (1<<11)) >> 12); + zw = (ox + ((zoomx * (x+1) + (1<<11)) >> 12)) - sx; + c = code; + if (mirrorx) + { + if ((flipx == 0) ^ ((x<<1) < w)) + { + /* mirror left/right */ + c += xoffset[(w-1-x+xa)&7]; + fx = 1; + } + else + { + c += xoffset[(x+xa)&7]; + fx = 0; + } + } + else + { + if (flipx) c += xoffset[(w-1-x+xa)&7]; + else c += xoffset[(x+xa)&7]; + fx = flipx; + } + + if (mirrory) + { + if ((flipy == 0) ^ ((y<<1) >= h)) + { + /* mirror top/bottom */ + c += yoffset[(h-1-y+ya)&7]; + fy = 1; + } + else + { + c += yoffset[(y+ya)&7]; + fy = 0; + } + } + else + { + if (flipy) c += yoffset[(h-1-y+ya)&7]; + else c += yoffset[(y+ya)&7]; + fy = flipy; + } + + if (shadow || wtable == stable) { + if (mirrory && h == 1) + RenderZoomedShadowTile(gfxbase, c, color << 4, wtable, sx, sy, flipx, !flipy, 16, 16, zw << 12, zh << 12, highlight); + + RenderZoomedShadowTile(gfxbase, c, color << 4, wtable, sx, sy, flipx, flipy, 16, 16, zw << 12, zh << 12, highlight); + continue; + } + + if (mirrory && h == 1) + { + if (nozoom) + { + if (!flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } + } + } + else + { + RenderZoomedTile(pTransDraw, gfxbase, c, color << 4, 0, sx, sy, fx, !fy, 16, 16, (zw << 16) >> 4, (zh << 16) >> 4); + } + } + + if (nozoom) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, sy, color, 4, 0, 0, gfxbase); + } + } + } + else + { + RenderZoomedTile(pTransDraw, gfxbase, c, color << 4, 0, sx, sy, fx, fy, 16, 16, (zw << 16) >> 4, (zh << 16) >> 4); + } + + + } // end of X loop + } // end of Y loop + + } // end of sprite-list loop +#undef NUM_SPRITES +} diff --git a/src/burn/drivers/konami/k053251.cpp b/src/burn/drivers/konami/k053251.cpp new file mode 100644 index 00000000..8b96ad96 --- /dev/null +++ b/src/burn/drivers/konami/k053251.cpp @@ -0,0 +1,60 @@ +#include "burnint.h" + +static UINT8 K053251Ram[0x10]; +static INT32 K053251PalIndex[6]; + +void K053251Reset() +{ + memset (K053251Ram, 0, 16); + memset (K053251PalIndex, 0, 5 * sizeof(INT32)); +} + +void K053251Write(INT32 offset, INT32 data) +{ + data &= 0x3f; + offset &= 0x0f; + + K053251Ram[offset] = (UINT8)data; + + if (offset == 9) + { + for (INT32 i = 0; i < 3; i++) { + K053251PalIndex[0+i] = 32 * ((data >> 2*i) & 0x03); + } + } + else if (offset == 10) + { + for (INT32 i = 0; i < 2; i++) { + K053251PalIndex[3+i] = 16 * ((data >> 3*i) & 0x07); + } + } +} + +INT32 K053251GetPriority(INT32 idx) +{ + return K053251Ram[idx & 0x0f]; +} + +INT32 K053251GetPaletteIndex(INT32 idx) +{ + return K053251PalIndex[idx]; +} + +void K053251Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K053251Ram; + ba.nLen = 0x10; + ba.szName = "K053251 Ram"; + BurnAcb(&ba); + + SCAN_VAR(K053251PalIndex[0]); + SCAN_VAR(K053251PalIndex[1]); + SCAN_VAR(K053251PalIndex[2]); + SCAN_VAR(K053251PalIndex[3]); + SCAN_VAR(K053251PalIndex[4]); + } +} diff --git a/src/burn/drivers/konami/k053936.cpp b/src/burn/drivers/konami/k053936.cpp new file mode 100644 index 00000000..cea87d3b --- /dev/null +++ b/src/burn/drivers/konami/k053936.cpp @@ -0,0 +1,275 @@ +#include "tiles_generic.h" +#include "konamiic.h" + +#define MAX_K053936 2 + +static INT32 nRamLen[MAX_K053936] = { 0, 0 }; +static INT32 nWidth[MAX_K053936] = { 0, 0 }; +static INT32 nHeight[MAX_K053936] = { 0, 0 }; +static UINT16 *tscreen[MAX_K053936] = { NULL, NULL }; +static UINT8 *ramptr[MAX_K053936] = { NULL, NULL }; +static UINT8 *rambuf[MAX_K053936] = { NULL, NULL }; + +static INT32 K053936Wrap[MAX_K053936] = { 0, 0 }; +static INT32 K053936Offset[MAX_K053936][2] = { { 0, 0 }, { 0, 0 } }; + +static void (*pTileCallback0)(INT32 offset, UINT16 *ram, INT32 *code, INT32 *color, INT32 *sx, INT32 *sy, INT32 *fx, INT32 *fy); +static void (*pTileCallback1)(INT32 offset, UINT16 *ram, INT32 *code, INT32 *color, INT32 *sx, INT32 *sy, INT32 *fx, INT32 *fy); + +void K053936Reset() +{ + for (INT32 i = 0; i < MAX_K053936; i++) { + if (rambuf[i]) { + memset (rambuf[i], 0, nRamLen[i]); + } + } +} + +void K053936Init(INT32 chip, UINT8 *ram, INT32 len, INT32 w, INT32 h, void (*pCallback)(INT32 offset, UINT16 *ram, INT32 *code, INT32 *color, INT32 *sx, INT32 *sy, INT32 *fx, INT32 *fy)) +{ + ramptr[chip] = ram; + + nRamLen[chip] = len; + + if (rambuf[chip] == NULL) { + rambuf[chip] = (UINT8*)malloc(len); + } + + nWidth[chip] = w; + nHeight[chip] = h; + + if (tscreen[chip] == NULL) { + tscreen[chip] = (UINT16*)malloc(w * h * 2); + } + + if (chip == 0) { + pTileCallback0 = pCallback; + } + if (chip == 1) { + pTileCallback1 = pCallback; + } + + KonamiIC_K053936InUse = 1; +} + +void K053936Exit() +{ + for (INT32 i = 0; i < MAX_K053936; i++) { + nRamLen[i] = 0; + nWidth[i] = 0; + nHeight[i] = 0; + if (tscreen[i] != NULL) { + free (tscreen[i]); + tscreen[i] = NULL; + } + ramptr[i] = NULL; + if (rambuf[i] != NULL) { + free (rambuf[i]); + rambuf[i] = NULL; + } + K053936Wrap[i] = 0; + K053936Offset[i][0] = K053936Offset[i][1] = 0; + } +} + +void K053936PredrawTiles(INT32 chip, UINT8 *gfx, INT32 transparent, INT32 tcol) +{ + INT32 twidth = nWidth[chip]; + UINT16 *ram = (UINT16*)ramptr[chip]; + UINT16 *buf = (UINT16*)rambuf[chip]; + + for (INT32 i = 0; i < nRamLen[chip] / 2; i++) + { + if (ram[i] != buf[i]) { + INT32 sx; + INT32 sy; + INT32 code; + INT32 color; + INT32 fx; + INT32 fy; + + if (chip) { + pTileCallback1(i, ram, &code, &color, &sx, &sy, &fx, &fy); + } else { + pTileCallback0(i, ram, &code, &color, &sx, &sy, &fx, &fy); + } + + // draw tile + { + if (fy) fy = 0xf0; + if (fx) fy |= 0x0f; + + UINT8 *src = gfx + (code * 16 * 16); + UINT16 *sdst = tscreen[chip] + (sy * twidth) + sx; + + for (INT32 y = 0; y < 16; y++) { + for (INT32 x = 0; x < 16; x++) { + INT32 pxl = src[((y << 4) | x) ^ fy]; + if (transparent) { + if (pxl == tcol) pxl |= 0x8000; + } + + sdst[x] = pxl | color; + } + sdst += twidth; + } + } + } + buf[i] = ram[i]; + } +} + +static inline void copy_roz(INT32 chip, INT32 minx, INT32 maxx, INT32 miny, INT32 maxy, UINT32 startx, UINT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, INT32 transp) +{ + UINT16 *dst = pTransDraw; + UINT16 *src = tscreen[chip]; + + INT32 hmask = nHeight[chip] - 1; + INT32 wmask = nWidth[chip] - 1; + + INT32 wrap = K053936Wrap[chip]; + + for (INT32 sy = miny; sy < maxy; sy++, startx+=incyx, starty+=incyy) + { + UINT32 cx = startx; + UINT32 cy = starty; + + if (transp) { + if (wrap) { + for (INT32 x = minx; x < maxx; x++, cx+=incxx, cy+=incxy, dst++) + { + INT32 pxl = src[(((cy >> 16) & hmask) << 10) + ((cx >> 16) & wmask)]; + + if (!(pxl & 0x8000)) { + *dst = pxl; + } + } + } else { + for (INT32 x = minx; x < maxx; x++, cx+=incxx, cy+=incxy, dst++) + { + INT32 yy = cy >> 16; + if (yy > hmask || yy < 0) continue; + INT32 xx = cx >> 16; + if (xx > wmask || xx < 0) continue; + + INT32 pxl = src[(yy << 10) + xx]; + + if (!(pxl & 0x8000)) { + *dst = pxl; + } + } + } + } else { + if (wrap) { + for (INT32 x = minx; x < maxx; x++, cx+=incxx, cy+=incxy, dst++) { + *dst = src[(((cy >> 16) & hmask) << 10) + ((cx >> 16) & wmask)] & 0x7fff; + } + } else { + for (INT32 x = minx; x < maxx; x++, cx+=incxx, cy+=incxy, dst++) { + INT32 yy = cy >> 16; + if (yy > hmask || yy < 0) continue; + INT32 xx = cx >> 16; + if (xx > wmask || xx < 0) continue; + + *dst = src[(yy << 10) + xx] & 0x7fff; + } + } + } + } +} + +void K053936Draw(INT32 chip, UINT16 *ctrl, UINT16 *linectrl, INT32 transp) +{ + if (ctrl[0x07] & 0x0040 && linectrl) // Super! + { + UINT32 startx,starty; + INT32 incxx,incxy; + + INT32 minx, maxx, maxy, miny, y; + + if ((ctrl[0x07] & 0x0002) && ctrl[0x09]) // glfgreat + { + minx = ctrl[0x08] + K053936Offset[chip][0]+2; + maxx = ctrl[0x09] + K053936Offset[chip][0]+2 - 1; + if (minx < 0) minx = 0; + if (maxx > nScreenWidth) maxx = nScreenWidth; + + y = ctrl[0x0a] + K053936Offset[chip][1]-2; + if (y < 0) y = 0; + maxy = ctrl[0x0b] + K053936Offset[chip][1]-2 - 1; + if (maxy > nScreenHeight) maxy = nScreenHeight; + } + else + { + minx = 0; + maxx = nScreenWidth; + + y = 0; + maxy = nScreenHeight; + } + + while (y <= maxy) + { + UINT16 *lineaddr = linectrl + 4*((y - K053936Offset[chip][1]) & 0x1ff); + miny = maxy = y; + + startx = 256 * (INT16)(lineaddr[0] + ctrl[0x00]); + starty = 256 * (INT16)(lineaddr[1] + ctrl[0x01]); + incxx = (INT16)(lineaddr[2]); + incxy = (INT16)(lineaddr[3]); + + if (ctrl[0x06] & 0x8000) incxx *= 256; + if (ctrl[0x06] & 0x0080) incxy *= 256; + + startx -= K053936Offset[chip][0] * incxx; + starty -= K053936Offset[chip][0] * incxy; + + copy_roz(chip, minx, maxx, miny, maxy, startx << 5, starty << 5, incxx << 5, incxy << 5, 0, 0, transp); + + y++; + } + } + else // simple + { + UINT32 startx,starty; + INT32 incxx,incxy,incyx,incyy; + + startx = 256 * (INT16)(ctrl[0x00]); + starty = 256 * (INT16)(ctrl[0x01]); + incyx = (INT16)(ctrl[0x02]); + incyy = (INT16)(ctrl[0x03]); + incxx = (INT16)(ctrl[0x04]); + incxy = (INT16)(ctrl[0x05]); + + if (ctrl[0x06] & 0x4000) { incyx *= 256; incyy *= 256; } + if (ctrl[0x06] & 0x0040) { incxx *= 256; incxy *= 256; } + + startx -= K053936Offset[chip][1] * incyx; + starty -= K053936Offset[chip][1] * incyy; + + startx -= K053936Offset[chip][0] * incxx; + starty -= K053936Offset[chip][0] * incxy; + + copy_roz(chip, 0, nScreenWidth, 0, nScreenHeight, startx << 5, starty << 5, incxx << 5, incxy << 5, incyx << 5, incyy << 5, transp); + } +} + +void K053936EnableWrap(INT32 chip, INT32 status) +{ + K053936Wrap[chip] = status; +} + +void K053936SetOffset(INT32 chip, INT32 xoffs, INT32 yoffs) +{ + K053936Offset[chip][0] = xoffs; + K053936Offset[chip][1] = yoffs; +} + +void K053936Scan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(K053936Wrap[0]); + SCAN_VAR(K053936Wrap[1]); + } +} + diff --git a/src/burn/drivers/konami/k054000.cpp b/src/burn/drivers/konami/k054000.cpp new file mode 100644 index 00000000..fd0cd35a --- /dev/null +++ b/src/burn/drivers/konami/k054000.cpp @@ -0,0 +1,55 @@ + +#include "burnint.h" + +static UINT8 K054000Ram[0x20]; + +void K054000Reset() +{ + memset (K054000Ram, 0, 0x20); +} + +void K054000Write(INT32 offset, INT32 data) +{ + K054000Ram[offset & 0x1f] = data; +} + +UINT8 K054000Read(INT32 offset) +{ + INT32 Acx,Acy,Aax,Aay; + INT32 Bcx,Bcy,Bax,Bay; + + offset &= 0x1f; + if (offset != 0x18) return 0; + + Acx = (K054000Ram[0x01] << 16) | (K054000Ram[0x02] << 8) | K054000Ram[0x03]; + Acy = (K054000Ram[0x09] << 16) | (K054000Ram[0x0a] << 8) | K054000Ram[0x0b]; + if (K054000Ram[0x04] == 0xff) Acx+=3; + if (K054000Ram[0x0c] == 0xff) Acy+=3; + Aax = K054000Ram[0x06] + 1; + Aay = K054000Ram[0x07] + 1; + + Bcx = (K054000Ram[0x15] << 16) | (K054000Ram[0x16] << 8) | K054000Ram[0x17]; + Bcy = (K054000Ram[0x11] << 16) | (K054000Ram[0x12] << 8) | K054000Ram[0x13]; + Bax = K054000Ram[0x0e] + 1; + Bay = K054000Ram[0x0f] + 1; + + if (Acx + Aax < Bcx - Bax) return 1; + if (Bcx + Bax < Acx - Aax) return 1; + if (Acy + Aay < Bcy - Bay) return 1; + if (Bcy + Bay < Acy - Aay) return 1; + + return 0; +} + +void K054000Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = K054000Ram; + ba.nLen = 0x20; + ba.szName = "K054000 Ram"; + BurnAcb(&ba); + } +} diff --git a/src/burn/drivers/konami/konamiic.cpp b/src/burn/drivers/konami/konamiic.cpp new file mode 100644 index 00000000..5ee925ba --- /dev/null +++ b/src/burn/drivers/konami/konamiic.cpp @@ -0,0 +1,179 @@ +#include "tiles_generic.h" +#include "konamiic.h" + +UINT32 KonamiIC_K051960InUse = 0; +UINT32 KonamiIC_K052109InUse = 0; +UINT32 KonamiIC_K051316InUse = 0; +UINT32 KonamiIC_K053245InUse = 0; +UINT32 KonamiIC_K053247InUse = 0; +UINT32 KonamiIC_K053936InUse = 0; + +UINT16 *konami_temp_screen = NULL; +INT32 K05324xZRejection = -1; + +void K05324xSetZRejection(INT32 z) +{ + K05324xZRejection = z; +} + +UINT8 K052109_051960_r(INT32 offset) +{ + if (K052109RMRDLine == 0) + { + if (offset >= 0x3800 && offset < 0x3808) + return K051937Read(offset - 0x3800); + else if (offset < 0x3c00) + return K052109Read(offset); + else + return K051960Read(offset - 0x3c00); + } + else return K052109Read(offset); +} + +void K052109_051960_w(INT32 offset, INT32 data) +{ + if (offset >= 0x3800 && offset < 0x3808) + K051937Write(offset - 0x3800,data); + else if (offset < 0x3c00) + K052109Write(offset, data); + else + K051960Write(offset - 0x3c00,data); +} + +static void shuffle(UINT16 *buf, INT32 len) +{ + if (len == 2 || len & 3) return; + + len >>= 1; + + for (INT32 i = 0; i < len/2; i++) + { + INT32 t = buf[len/2 + i]; + buf[len/2 + i] = buf[len + i]; + buf[len + i] = t; + } + + shuffle(buf, len); + shuffle(buf + len, len); +} + +void konami_rom_deinterleave_2(UINT8 *src, INT32 len) +{ + shuffle((UINT16*)src,len/2); +} + +void konami_rom_deinterleave_4(UINT8 *src, INT32 len) +{ + konami_rom_deinterleave_2(src, len); + konami_rom_deinterleave_2(src, len); +} + +// xbbbbbgggggrrrrr (used mostly by Konami-custom cpu games) +void KonamiRecalcPal(UINT8 *src, UINT32 *dst, INT32 len) +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)src; + for (INT32 i = 0; i < len / 2; i++) { + UINT16 d = (p[i] << 8) | (p[i] >> 8); + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + dst[i] = BurnHighCol(r, g, b, 0); + } +} + +void KonamiICReset() +{ + if (KonamiIC_K051960InUse) K051960Reset(); + if (KonamiIC_K052109InUse) K052109Reset(); + if (KonamiIC_K051316InUse) K051316Reset(); + if (KonamiIC_K053245InUse) K053245Reset(); + if (KonamiIC_K053247InUse) K053247Reset(); + if (KonamiIC_K053936InUse) K053936Reset(); + + // No init's, so always reset these + K053251Reset(); + K054000Reset(); + K051733Reset(); +} + +void KonamiICExit() +{ + if (konami_temp_screen) { + free (konami_temp_screen); + konami_temp_screen = NULL; + } + + if (KonamiIC_K051960InUse) K051960Exit(); + if (KonamiIC_K052109InUse) K052109Exit(); + if (KonamiIC_K051316InUse) K051316Exit(); + if (KonamiIC_K053245InUse) K053245Exit(); + if (KonamiIC_K053247InUse) K053247Exit(); + if (KonamiIC_K053936InUse) K053936Exit(); + + KonamiIC_K051960InUse = 0; + KonamiIC_K052109InUse = 0; + KonamiIC_K051316InUse = 0; + KonamiIC_K053245InUse = 0; + KonamiIC_K053247InUse = 0; + + K05324xZRejection = -1; +} + +void KonamiICScan(INT32 nAction) +{ + if (KonamiIC_K051960InUse) K051960Scan(nAction); + if (KonamiIC_K052109InUse) K052109Scan(nAction); + if (KonamiIC_K051316InUse) K051316Scan(nAction); + if (KonamiIC_K053245InUse) K053245Scan(nAction); + if (KonamiIC_K053247InUse) K053247Scan(nAction); + if (KonamiIC_K053936InUse) K053936Scan(nAction); + + K053251Scan(nAction); + K054000Scan(nAction); + K051733Scan(nAction); +} + +/* + Transfer and blend pixels + + * highlights are right? where is this used? + * also, has a limitation of 0x4000 colors, some games may need more. +*/ +void KonamiBlendCopy(UINT32 *palette /* 32-bit color */, UINT32 *drvpalette /* n-bit color */) +{ + UINT8 *dst = pBurnDraw; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) + { + if (pTransDraw[i] >= 0x4000) // shadow & highlight + { + UINT32 source = palette[pTransDraw[i] & 0x3fff]; + UINT32 blend = palette[konami_temp_screen[i] & 0x3fff]; + + INT32 a = 0x99; // shadow (255 * 0.60) + if (pTransDraw[i] & 0x4000) a = 0xa9; // highlight (255 * (1 / 0.60)) & 0xff; (0x1a9 otherwise) right? + + INT32 ad = 256 - a; + + // ripped from MAME... + UINT32 p = ((((source & 0x0000ff) * a + (blend & 0x0000ff) * ad) >> 8)) | + ((((source & 0x00ff00) * a + (blend & 0x00ff00) * ad) >> 8) & 0x00ff00) | + ((((source & 0xff0000) * a + (blend & 0xff0000) * ad) >> 8) & 0xff0000); + + PutPix(dst, BurnHighCol(p >> 16, p >> 8, p, 0)); + } + else // normal + { + PutPix(dst, drvpalette[pTransDraw[i]]); + } + + dst += nBurnBpp; + } +} diff --git a/src/burn/drivers/konami/konamiic.h b/src/burn/drivers/konami/konamiic.h new file mode 100644 index 00000000..b3a5d6ea --- /dev/null +++ b/src/burn/drivers/konami/konamiic.h @@ -0,0 +1,238 @@ +// konamiic.cpp +//--------------------------------------------------------------------------------------------------------------- +extern UINT32 KonamiIC_K051960InUse; +extern UINT32 KonamiIC_K052109InUse; +extern UINT32 KonamiIC_K051316InUse; +extern UINT32 KonamiIC_K053245InUse; +extern UINT32 KonamiIC_K053247InUse; +extern UINT32 KonamiIC_K053936InUse; + +extern UINT16 *konami_temp_screen; +void KonamiBlendCopy(UINT32 *palette /* 32-bit color */, UINT32 *drvpalette /* n-bit color */); + +extern INT32 K05324xZRejection; +void K05324xSetZRejection(INT32 z); + +void KonamiICReset(); +void KonamiICExit(); +void KonamiICScan(INT32 nAction); + +void konami_rom_deinterleave_2(UINT8 *src, INT32 len); +void konami_rom_deinterleave_4(UINT8 *src, INT32 len); + +void KonamiRecalcPal(UINT8 *src, UINT32 *dst, INT32 len); + + +void K052109_051960_w(INT32 offset, INT32 data); +UINT8 K052109_051960_r(INT32 offset); + +// k051960.cpp +//--------------------------------------------------------------------------------------------------------------- +extern INT32 K051960ReadRoms; +extern INT32 K052109_irq_enabled; +void K051960SpritesRender(UINT8 *pSrc, INT32 priority); +UINT8 K0519060FetchRomData(UINT32 Offset); +UINT8 K051960Read(UINT32 Offset); +void K051960Write(UINT32 Offset, UINT8 Data); +void K051960SetCallback(void (*Callback)(INT32 *Code, INT32 *Colour, INT32 *Priority, INT32 *Shadow)); +void K051960SetSpriteOffset(INT32 x, INT32 y); +void K051960Reset(); +void K051960Init(UINT8* pRomSrc, UINT32 RomMask); +void K051960Exit(); +void K051960Scan(INT32 nAction); +void K051937Write(UINT32 Offset, UINT8 Data); +UINT8 K051937Read(UINT32 Offset); + +// k052109.cpp +//--------------------------------------------------------------------------------------------------------------- +extern INT32 K052109RMRDLine; +extern INT32 K051960_irq_enabled; +extern INT32 K051960_nmi_enabled; +extern INT32 K051960_spriteflip; + +void K052109UpdateScroll(); +void K052109AdjustScroll(INT32 x, INT32 y); +void K052109RenderLayer(INT32 nLayer, INT32 Opaque, UINT8 *pSrc); +UINT8 K052109Read(UINT32 Offset); +void K052109Write(UINT32 Offset, UINT8 Data); +void K052109SetCallback(void (*Callback)(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *priority)); +void K052109Reset(); +void K052109Init(UINT8 *pRomSrc, UINT32 RomMask); +void K052109Exit(); +void K052109Scan(INT32 nAction); + +#define K051960ByteRead(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 0x3ff) { \ + return K051960Read(a - nStartAddress); \ +} + +#define K051960ByteWrite(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 0x3ff) { \ + K051960Write((a - nStartAddress), d); \ + return; \ +} + +#define K051960WordWrite(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 0x3ff) { \ + if (a & 1) { \ + K051960Write((a - nStartAddress) + 1, d & 0xff); \ + } else { \ + K051960Write((a - nStartAddress) + 0, (d >> 8) & 0xff); \ + } \ + return; \ +} + +#define K051937ByteRead(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 7) { \ + INT32 Offset = (a - nStartAddress); \ + \ + if (Offset == 0) { \ + static INT32 Counter; \ + return (Counter++) & 1; \ + } \ + \ + if (K051960ReadRoms && (Offset >= 0x04 && Offset <= 0x07)) { \ + return K0519060FetchRomData(Offset & 3); \ + } \ + \ + return 0; \ +} + +#define K015937ByteWrite(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 7) { \ + K051937Write((a - nStartAddress), d); \ + return; \ +} + +#define K052109WordNoA12Read(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 0x7fff) { \ + INT32 Offset = (a - nStartAddress) >> 1; \ + Offset = ((Offset & 0x3000) >> 1) | (Offset & 0x07ff); \ + \ + if (a & 1) { \ + return K052109Read(Offset + 0x2000); \ + } else { \ + return K052109Read(Offset + 0x0000); \ + } \ +} + + +#define K052109WordNoA12Write(nStartAddress) \ +if (a >= nStartAddress && a <= nStartAddress + 0x7fff) { \ + INT32 Offset = (a - nStartAddress) >> 1; \ + Offset = ((Offset & 0x3000) >> 1) | (Offset & 0x07ff); \ + \ + if (a & 1) { \ + K052109Write(Offset + 0x2000, d); \ + } else { \ + K052109Write(Offset + 0x0000, d); \ + } \ + return; \ +} + +// K051316.cpp +//--------------------------------------------------------------------------------------------------------------- +void K051316Init(INT32 chip, UINT8 *gfx, UINT8 *gfxexp, INT32 mask, void (*callback)(INT32 *code,INT32 *color,INT32 *flags), INT32 bpp, INT32 transp); +void K051316Reset(); +void K051316Exit(); + +void K051316RedrawTiles(INT32 chip); + +UINT8 K051316ReadRom(INT32 chip, INT32 offset); +UINT8 K051316Read(INT32 chip, INT32 offset); +void K051316Write(INT32 chip, INT32 offset, INT32 data); + +void K051316WriteCtrl(INT32 chip, INT32 offset, INT32 data); +void K051316WrapEnable(INT32 chip, INT32 status); +void K051316SetOffset(INT32 chip, INT32 xoffs, INT32 yoffs); +void K051316_zoom_draw(INT32 chip, INT32 flags); +void K051316Scan(INT32 nAction); + +// K053245.cpp +//--------------------------------------------------------------------------------------------------------------- +INT32 K053245Reset(); +void K053245GfxDecode(UINT8 *src, UINT8 *dst, INT32 len); +void K053245Init(INT32 chip, UINT8 *gfx, INT32 mask, void (*callback)(INT32 *code,INT32 *color,INT32 *priority)); +void K053245Exit(); + +void K053245SpritesRender(INT32 chip, UINT8 *gfxdata, INT32 priority); + +void K053245SetSpriteOffset(INT32 chip,INT32 offsx, INT32 offsy); +void K053245ClearBuffer(INT32 chip); +void K053245UpdateBuffer(INT32 chip); +void K053244BankSelect(INT32 chip, INT32 bank); + +UINT16 K053245ReadWord(INT32 chip, INT32 offset); +void K053245WriteWord(INT32 chip, INT32 offset, INT32 data); + +UINT8 K053245Read(INT32 chip, INT32 offset); +void K053245Write(INT32 chip, INT32 offset, INT32 data); +UINT8 K053244Read(INT32 chip, INT32 offset); +void K053244Write(INT32 chip, INT32 offset, INT32 data); + +void K053245Scan(INT32 nAction); + +// K053251.cpp +//--------------------------------------------------------------------------------------------------------------- +void K053251Reset(); + +void K053251Write(INT32 offset, INT32 data); + +INT32 K053251GetPriority(INT32 idx); +INT32 K053251GetPaletteIndex(INT32 idx); + +void K053251Write(INT32 offset, INT32 data); +INT32 K053251GetPriority(INT32 idx); +INT32 K053251GetPaletteIndex(INT32 idx); + +void K053251Scan(INT32 nAction); + +// K053247.cpp +//--------------------------------------------------------------------------------------------------------------- +void K053247Reset(); +void K053247Init(UINT8 *gfxrom, INT32 gfxlen, void (*Callback)(INT32 *code, INT32 *color, INT32 *priority), INT32 flags); +void K053247Exit(); +void K053247Scan(INT32 nAction); + +void K053247Export(UINT8 **ram, UINT8 **gfx, void (**callback)(INT32 *, INT32 *, INT32 *), INT32 *dx, INT32 *dy); +void K053247GfxDecode(UINT8 *src, UINT8 *dst, INT32 len); // 16x16 +void K053247SetSpriteOffset(INT32 offsx, INT32 offsy); +void K053247WrapEnable(INT32 status); + +void K053246_set_OBJCHA_line(INT32 state); // 1 assert, 0 clear +INT32 K053246_is_IRQ_enabled(); + +UINT8 K053247Read(INT32 offset); +void K053247Write(INT32 offset, INT32 data); +UINT8 K053246Read(INT32 offset); +void K053246Write(INT32 offset, INT32 data); + +void K053247SpritesRender(UINT8 *gfxbase, INT32 priority); + +// k054000.cpp +//------------------------------------------------------------------------------------------ +void K054000Reset(); +void K054000Write(INT32 offset, INT32 data); +UINT8 K054000Read(INT32 address); +void K054000Scan(INT32 nAction); + +// K051733.cpp +//------------------------------------------------------------------------------------------ +void K051733Reset(); +void K051733Write(INT32 offset, INT32 data); +UINT8 K051733Read(INT32 offset); +void K051733Scan(INT32 nAction); + +// K053936.cpp +//------------------------------------------------------------------------------------------ +void K053936Init(INT32 chip, UINT8 *ram, INT32 len, INT32 w, INT32 h, void (*pCallback)(INT32 offset, UINT16 *ram, INT32 *code, INT32 *color, INT32 *sx, INT32 *sy, INT32 *fx, INT32 *fy)); +void K053936Reset(); +void K053936Exit(); +void K053936Scan(INT32 nAction); + +void K053936EnableWrap(INT32 chip, INT32 status); +void K053936SetOffset(INT32 chip, INT32 xoffs, INT32 yoffs); + +void K053936PredrawTiles(INT32 chip, UINT8 *gfx, INT32 transparent, INT32 tcol /*transparent color*/); +void K053936Draw(INT32 chip, UINT16 *ctrl, UINT16 *linectrl, INT32 transp); + diff --git a/src/burn/drivers/megadrive/d_megadrive.cpp b/src/burn/drivers/megadrive/d_megadrive.cpp new file mode 100644 index 00000000..2aa0f5fc --- /dev/null +++ b/src/burn/drivers/megadrive/d_megadrive.cpp @@ -0,0 +1,40515 @@ +#include "burnint.h" +#include "megadrive.h" + +// Driver generated by database on http://www.barryharris.me.uk + +static struct BurnInputInfo MegadriveInputList[] = { + {"P1 Start", BIT_DIGITAL, MegadriveJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, MegadriveJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, MegadriveJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, MegadriveJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, MegadriveJoy1 + 3, "p1 right" }, + {"P1 Button A", BIT_DIGITAL, MegadriveJoy1 + 6, "p1 fire 1" }, + {"P1 Button B", BIT_DIGITAL, MegadriveJoy1 + 4, "p1 fire 2" }, + {"P1 Button C", BIT_DIGITAL, MegadriveJoy1 + 5, "p1 fire 3" }, + {"P1 Button X", BIT_DIGITAL, MegadriveJoy1 + 10, "p1 fire 4" }, + {"P1 Button Y", BIT_DIGITAL, MegadriveJoy1 + 9, "p1 fire 5" }, + {"P1 Button Z", BIT_DIGITAL, MegadriveJoy1 + 8, "p1 fire 6" }, + {"P1 Mode", BIT_DIGITAL, MegadriveJoy1 + 11, "p1 select" }, + + {"P2 Start", BIT_DIGITAL, MegadriveJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, MegadriveJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, MegadriveJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, MegadriveJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, MegadriveJoy2 + 3, "p2 right" }, + {"P2 Button A", BIT_DIGITAL, MegadriveJoy2 + 6, "p2 fire 1" }, + {"P2 Button B", BIT_DIGITAL, MegadriveJoy2 + 4, "p2 fire 2" }, + {"P2 Button C", BIT_DIGITAL, MegadriveJoy2 + 5, "p2 fire 3" }, + {"P2 Button X", BIT_DIGITAL, MegadriveJoy2 + 10, "p2 fire 4" }, + {"P2 Button Y", BIT_DIGITAL, MegadriveJoy2 + 9, "p2 fire 5" }, + {"P2 Button Z", BIT_DIGITAL, MegadriveJoy2 + 8, "p2 fire 6" }, + {"P2 Mode", BIT_DIGITAL, MegadriveJoy2 + 11, "p2 select" }, + + {"Reset", BIT_DIGITAL, &MegadriveReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, MegadriveDIP + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, MegadriveDIP + 1, "dip" }, +}; + +STDINPUTINFO(Megadrive) + +static struct BurnInputInfo Megadrive4pInputList[] = { + {"P1 Start", BIT_DIGITAL, MegadriveJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, MegadriveJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, MegadriveJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, MegadriveJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, MegadriveJoy1 + 3, "p1 right" }, + {"P1 Button A", BIT_DIGITAL, MegadriveJoy1 + 6, "p1 fire 1" }, + {"P1 Button B", BIT_DIGITAL, MegadriveJoy1 + 4, "p1 fire 2" }, + {"P1 Button C", BIT_DIGITAL, MegadriveJoy1 + 5, "p1 fire 3" }, + {"P1 Button X", BIT_DIGITAL, MegadriveJoy1 + 10, "p1 fire 4" }, + {"P1 Button Y", BIT_DIGITAL, MegadriveJoy1 + 9, "p1 fire 5" }, + {"P1 Button Z", BIT_DIGITAL, MegadriveJoy1 + 8, "p1 fire 6" }, + {"P1 Mode", BIT_DIGITAL, MegadriveJoy1 + 11, "p1 select" }, + + {"P2 Start", BIT_DIGITAL, MegadriveJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, MegadriveJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, MegadriveJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, MegadriveJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, MegadriveJoy2 + 3, "p2 right" }, + {"P2 Button A", BIT_DIGITAL, MegadriveJoy2 + 6, "p2 fire 1" }, + {"P2 Button B", BIT_DIGITAL, MegadriveJoy2 + 4, "p2 fire 2" }, + {"P2 Button C", BIT_DIGITAL, MegadriveJoy2 + 5, "p2 fire 3" }, + {"P2 Button X", BIT_DIGITAL, MegadriveJoy2 + 10, "p2 fire 4" }, + {"P2 Button Y", BIT_DIGITAL, MegadriveJoy2 + 9, "p2 fire 5" }, + {"P2 Button Z", BIT_DIGITAL, MegadriveJoy2 + 8, "p2 fire 6" }, + {"P2 Mode", BIT_DIGITAL, MegadriveJoy2 + 11, "p2 select" }, + + {"P3 Start", BIT_DIGITAL, MegadriveJoy3 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, MegadriveJoy3 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, MegadriveJoy3 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, MegadriveJoy3 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, MegadriveJoy3 + 3, "p3 right" }, + {"P3 Button A", BIT_DIGITAL, MegadriveJoy3 + 6, "p3 fire 1" }, + {"P3 Button B", BIT_DIGITAL, MegadriveJoy3 + 4, "p3 fire 2" }, + {"P3 Button C", BIT_DIGITAL, MegadriveJoy3 + 5, "p3 fire 3" }, + {"P3 Button X", BIT_DIGITAL, MegadriveJoy3 + 10, "p3 fire 4" }, + {"P3 Button Y", BIT_DIGITAL, MegadriveJoy3 + 9, "p3 fire 5" }, + {"P3 Button Z", BIT_DIGITAL, MegadriveJoy3 + 8, "p3 fire 6" }, + {"P3 Mode", BIT_DIGITAL, MegadriveJoy3 + 11, "p3 select" }, + + {"P4 Start", BIT_DIGITAL, MegadriveJoy4 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, MegadriveJoy4 + 0, "p4 up" }, + {"P4 Down", BIT_DIGITAL, MegadriveJoy4 + 1, "p4 down" }, + {"P4 Left", BIT_DIGITAL, MegadriveJoy4 + 2, "p4 left" }, + {"P4 Right", BIT_DIGITAL, MegadriveJoy4 + 3, "p4 right" }, + {"P4 Button A", BIT_DIGITAL, MegadriveJoy4 + 6, "p4 fire 1" }, + {"P4 Button B", BIT_DIGITAL, MegadriveJoy4 + 4, "p4 fire 2" }, + {"P4 Button C", BIT_DIGITAL, MegadriveJoy4 + 5, "p4 fire 3" }, + {"P4 Button X", BIT_DIGITAL, MegadriveJoy4 + 10, "p4 fire 4" }, + {"P4 Button Y", BIT_DIGITAL, MegadriveJoy4 + 9, "p4 fire 5" }, + {"P4 Button Z", BIT_DIGITAL, MegadriveJoy4 + 8, "p4 fire 6" }, + {"P4 Mode", BIT_DIGITAL, MegadriveJoy4 + 11, "p4 select" }, + + {"Reset", BIT_DIGITAL, &MegadriveReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, MegadriveDIP + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, MegadriveDIP + 1, "dip" }, +}; + +STDINPUTINFO(Megadrive4p) + +static struct BurnDIPInfo MegadriveDIPList[] = { + {0x1a, 0xff, 0xff, 0x01, NULL }, + + {0, 0xfe, 0, 5, "Hardware" }, + {0x19, 0x01, 0xc1, 0x01, "Auto Detect" }, + {0x19, 0x01, 0xc1, 0x00, "Japan NTSC" }, + {0x19, 0x01, 0xc1, 0x40, "Japan PAL" }, + {0x19, 0x01, 0xc1, 0x80, "USA" }, + {0x19, 0x01, 0xc1, 0xc0, "Europe" }, + + {0, 0xfe, 0, 2, "CD-ROM" }, + {0x19, 0x01, 0x20, 0x20, "No" }, + {0x19, 0x01, 0x20, 0x00, "Yes" }, + + {0, 0xfe, 0, 3, "32-Col Mode Draw" }, + {0x1a, 0x01, 0x03, 0x00, "No Change" }, + {0x1a, 0x01, 0x03, 0x01, "Center" }, + {0x1a, 0x01, 0x03, 0x02, "Inner Zoom" }, +}; + +static struct BurnDIPInfo AutoDetectRegionDIPList[] = { + {0x19, 0xff, 0xff, 0x21, NULL}, +}; + +static struct BurnDIPInfo Megadrive4pDIPList[] = { + {0x32, 0xff, 0xff, 0x01, NULL }, + + {0, 0xfe, 0, 5, "Hardware" }, + {0x31, 0x01, 0xc1, 0x01, "Auto Detect" }, + {0x31, 0x01, 0xc1, 0x00, "Japan NTSC" }, + {0x31, 0x01, 0xc1, 0x40, "Japan PAL" }, + {0x31, 0x01, 0xc1, 0x80, "USA" }, + {0x31, 0x01, 0xc1, 0xc0, "Europe" }, + + {0, 0xfe, 0, 2, "CD-ROM" }, + {0x31, 0x01, 0x20, 0x20, "No" }, + {0x31, 0x01, 0x20, 0x00, "Yes" }, + + {0, 0xfe, 0, 3, "32-Col Mode Draw" }, + {0x32, 0x01, 0x03, 0x00, "No Change" }, + {0x32, 0x01, 0x03, 0x01, "Center" }, + {0x32, 0x01, 0x03, 0x02, "Inner Zoom" }, +}; + + static struct BurnDIPInfo AutoDetectRegion4pDIPList[] = { + {0x31, 0xff, 0xff, 0x21, NULL}, +}; + +STDDIPINFOEXT(Megadrive, AutoDetectRegion, Megadrive) +STDDIPINFOEXT(Megadrive4p, AutoDetectRegion4p, Megadrive4p) + +INT32 MegadriveGetZipName(char** pszName, UINT32 i) +{ + static char szFilename[MAX_PATH]; + char* pszGameName = NULL; + + if (pszName == NULL) { + return 1; + } + + if (i == 0) { + pszGameName = BurnDrvGetTextA(DRV_NAME); + } else { + pszGameName = BurnDrvGetTextA(DRV_PARENT); + } + + if (pszGameName == NULL) { + *pszName = NULL; + return 1; + } + + // remove the "md_" + for (UINT32 j = 0; j < strlen(pszGameName); j++) { + szFilename[j] = pszGameName[j + 3]; + } + strcat(szFilename, ".zip"); + + *pszName = szFilename; + + return 0; +} + +// F-22 Interceptor (Euro, USA, 199109) +static struct BurnRomInfo md_f22aRomDesc[] = { + { "f-22_intercept_f-202-4.u1", 0x080000, 0x649771f8, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "f-22_intercept_f-202-1.u2", 0x020000, 0xd3d7cbb8, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_080000 }, +}; + +STD_ROM_PICK(md_f22a) +STD_ROM_FN(md_f22a) + +struct BurnDriver BurnDrvmd_f22a = { + "md_f22a", "md_f22", NULL, NULL, "1991", + "F-22 Interceptor (Euro, USA, 199109)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f22aRomInfo, md_f22aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA 97 Gold Edition (Euro, USA) +static struct BurnRomInfo md_fifa97RomDesc[] = { + { "fifa_97_b1", 0x200000, 0x2bedb061, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa97) +STD_ROM_FN(md_fifa97) + +struct BurnDriver BurnDrvmd_fifa97 = { + "md_fifa97", NULL, NULL, NULL, "1996", + "FIFA 97 Gold Edition (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa97RomInfo, md_fifa97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Bond 007 - The Duel (Euro, Rev. A) +static struct BurnRomInfo md_jb007RomDesc[] = { + { "mpr-15312a", 0x080000, 0x66635364, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jb007) +STD_ROM_FN(md_jb007) + +struct BurnDriver BurnDrvmd_jb007 = { + "md_jb007", NULL, NULL, NULL, "1992", + "James Bond 007 - The Duel (Euro, Rev. A)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jb007RomInfo, md_jb007RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Pond - Underwater Agent (Euro, USA) +static struct BurnRomInfo md_jpondRomDesc[] = { + { "james_pond_u1_jam03", 0x080000, 0xd0e7b466, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpond) +STD_ROM_FN(md_jpond) + +struct BurnDriver BurnDrvmd_jpond = { + "md_jpond", NULL, NULL, NULL, "1993", + "James Pond - Underwater Agent (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpondRomInfo, md_jpondRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Pond II - Codename Robocod (Euro, USA) +static struct BurnRomInfo md_jpond2RomDesc[] = { + { "pond_ii_robocod_ro_b02", 0x080000, 0xc32b5d66, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpond2) +STD_ROM_FN(md_jpond2) + +struct BurnDriver BurnDrvmd_jpond2 = { + "md_jpond2", NULL, NULL, NULL, "1991", + "James Pond II - Codename Robocod (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpond2RomInfo, md_jpond2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lotus Turbo Challenge (Euro, USA) +static struct BurnRomInfo md_lotustRomDesc[] = { + { "lotus_turbo_lot03", 0x100000, 0xb83ccb7a, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lotust) +STD_ROM_FN(md_lotust) + +struct BurnDriver BurnDrvmd_lotust = { + "md_lotust", NULL, NULL, NULL, "1992", + "Lotus Turbo Challenge (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lotustRomInfo, md_lotustRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL '94 (Euro, USA) +static struct BurnRomInfo md_nhl94RomDesc[] = { + { "nhl94_hl9402", 0x100000, 0xacecd225, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhl94) +STD_ROM_FN(md_nhl94) + +struct BurnDriver BurnDrvmd_nhl94 = { + "md_nhl94", NULL, NULL, NULL, "1993", + "NHL '94 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhl94RomInfo, md_nhl94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf II (Euro, USA) +static struct BurnRomInfo md_pga2aRomDesc[] = { + { "pga_tour_golf_pgt04", 0x100000, 0x8d980bb4, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga2a) +STD_ROM_FN(md_pga2a) + +struct BurnDriver BurnDrvmd_pga2a = { + "md_pga2a", "md_pga2", NULL, NULL, "1992", + "PGA Tour Golf II (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pga2aRomInfo, md_pga2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rise of the Robots (Euro) +static struct BurnRomInfo md_riserbotRomDesc[] = { + { "es133-1_rise_of_the_robots.u1", 0x200000, 0xed583ef7, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "es133-2_rise_of_the_robots.u2", 0x100000, 0xfcf18470, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_200000 }, +}; + +STD_ROM_PICK(md_riserbot) +STD_ROM_FN(md_riserbot) + +struct BurnDriver BurnDrvmd_riserbot = { + "md_riserbot", NULL, NULL, NULL, "1994", + "Rise of the Robots (Euro)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_riserbotRomInfo, md_riserbotRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Splatterhouse Part 2 (Jpn) +static struct BurnRomInfo md_splatt2jRomDesc[] = { + { "sh2j", 0x100000, 0xadbd991b, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_splatt2j) +STD_ROM_FN(md_splatt2j) + +struct BurnDriver BurnDrvmd_splatt2j = { + "md_splatt2j", "md_splatt2", NULL, NULL, "1992", + "Splatterhouse Part 2 (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_splatt2jRomInfo, md_splatt2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zero Tolerance (Euro, USA) +static struct BurnRomInfo md_zerotolRomDesc[] = { + { "zetsg_lo_7500-00034a.u2", 0x100000, 0xb9c2d518, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000000 }, + { "zetsg_hi_7500-00033a.u1", 0x100000, 0xaf362b8c, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000001 }, +}; + +STD_ROM_PICK(md_zerotol) +STD_ROM_FN(md_zerotol) + +struct BurnDriver BurnDrvmd_zerotol = { + "md_zerotol", NULL, NULL, NULL, "1994", + "Zero Tolerance (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zerotolRomInfo, md_zerotolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Euro) +static struct BurnRomInfo md_advbatrRomDesc[] = { + { "mpr-18019.ic1", 0x200000, 0x355e8c39, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatr) +STD_ROM_FN(md_advbatr) + +struct BurnDriver BurnDrvmd_advbatr = { + "md_advbatr", NULL, NULL, NULL, "1995", + "The Adventures of Batman & Robin (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrRomInfo, md_advbatrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Mighty Max (Euro) +static struct BurnRomInfo md_mightmaxRomDesc[] = { + { "mpr-17434.ic1", 0x100000, 0x24f1a3bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mightmax) +STD_ROM_FN(md_mightmax) + +struct BurnDriver BurnDrvmd_mightmax = { + "md_mightmax", NULL, NULL, NULL, "1994", + "The Adventures of Mighty Max (Euro)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mightmaxRomInfo, md_mightmaxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alex Kidd in the Enchanted Castle (Euro, Rev. A) +static struct BurnRomInfo md_alexkiddRomDesc[] = { + { "mpr-12608a.ic1", 0x040000, 0x778a0f00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alexkidd) +STD_ROM_FN(md_alexkidd) + +struct BurnDriver BurnDrvmd_alexkidd = { + "md_alexkidd", NULL, NULL, NULL, "1990", + "Alex Kidd in the Enchanted Castle (Euro, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alexkiddRomInfo, md_alexkiddRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alisia Dragoon (Euro) +static struct BurnRomInfo md_alisiadRomDesc[] = { + { "mpr-14680.ic1", 0x100000, 0x28165bd1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alisiad) +STD_ROM_FN(md_alisiad) + +struct BurnDriver BurnDrvmd_alisiad = { + "md_alisiad", NULL, NULL, NULL, "1992", + "Alisia Dragoon (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alisiadRomInfo, md_alisiadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Andre Agassi Tennis (Euro) +static struct BurnRomInfo md_agassiRomDesc[] = { + { "mpr-15488.ic1", 0x080000, 0x224256c7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_agassi) +STD_ROM_FN(md_agassi) + +struct BurnDriver BurnDrvmd_agassi = { + "md_agassi", NULL, NULL, NULL, "1992", + "Andre Agassi Tennis (Euro)\0", NULL, "TecMagik", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_agassiRomInfo, md_agassiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Another World (Euro) +static struct BurnRomInfo md_anotherwRomDesc[] = { + { "mpr-15498.ic1", 0x100000, 0xe9742041, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_anotherw) +STD_ROM_FN(md_anotherw) + +struct BurnDriver BurnDrvmd_anotherw = { + "md_anotherw", NULL, NULL, NULL, "1993", + "Another World (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_anotherwRomInfo, md_anotherwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arcade Classics (Euro, USA) +static struct BurnRomInfo md_arcadeclRomDesc[] = { + { "mpr-18815.ic1", 0x080000, 0x8aed2090, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arcadecl) +STD_ROM_FN(md_arcadecl) + +struct BurnDriver BurnDrvmd_arcadecl = { + "md_arcadecl", NULL, NULL, NULL, "1996", + "Arcade Classics (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arcadeclRomInfo, md_arcadeclRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Art Alive (World) +static struct BurnRomInfo md_artaliveRomDesc[] = { + { "mpr-14384.ic1", 0x020000, 0xf1b72cdd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_artalive) +STD_ROM_FN(md_artalive) + +struct BurnDriver BurnDrvmd_artalive = { + "md_artalive", NULL, NULL, NULL, "1991", + "Art Alive (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_artaliveRomInfo, md_artaliveRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage (Euro, USA, Rev. A) ~ Bare Knuckle - Ikari no Tetsuken (Jpn, Rev. A) +static struct BurnRomInfo md_sorRomDesc[] = { + { "mpr-14125a.ic1", 0x080000, 0x4052e845, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor) +STD_ROM_FN(md_sor) + +struct BurnDriver BurnDrvmd_sor = { + "md_sor", NULL, NULL, NULL, "1991", + "Streets of Rage (Euro, USA, Rev. A) ~ Bare Knuckle - Ikari no Tetsuken (Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sorRomInfo, md_sorRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage (Euro, USA) ~ Bare Knuckle - Ikari no Tetsuken (Jpn) +static struct BurnRomInfo md_soraRomDesc[] = { + { "mpr-14125.ic1", 0x080000, 0xbff227c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sora) +STD_ROM_FN(md_sora) + +struct BurnDriver BurnDrvmd_sora = { + "md_sora", "md_sor", NULL, NULL, "1991", + "Streets of Rage (Euro, USA) ~ Bare Knuckle - Ikari no Tetsuken (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soraRomInfo, md_soraRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman (Euro) +static struct BurnRomInfo md_batmanRomDesc[] = { + { "mpr-14561.ic1", 0x080000, 0x61c60c35, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batman) +STD_ROM_FN(md_batman) + +struct BurnDriver BurnDrvmd_batman = { + "md_batman", NULL, NULL, NULL, "1990", + "Batman (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanRomInfo, md_batmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ferrari Grand Prix Challenge (Euro, Rev. A) +static struct BurnRomInfo md_ferrariRomDesc[] = { + { "mpr-14770a.ic1", 0x100000, 0x250111df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ferrari) +STD_ROM_FN(md_ferrari) + +struct BurnDriver BurnDrvmd_ferrari = { + "md_ferrari", NULL, NULL, NULL, "1992", + "Ferrari Grand Prix Challenge (Euro, Rev. A)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ferrariRomInfo, md_ferrariRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Game Toshokan (Jpn, Rev. A) +static struct BurnRomInfo md_gametoRomDesc[] = { + { "mpr-12750a.ic1", 0x020000, 0xc185c819, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gameto) +STD_ROM_FN(md_gameto) + +struct BurnDriver BurnDrvmd_gameto = { + "md_gameto", NULL, NULL, NULL, "1990", + "Game Toshokan (Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_gametoRomInfo, md_gametoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ghouls 'n Ghosts (Euro, USA, Kor, Rev. A) +static struct BurnRomInfo md_ghoulsRomDesc[] = { + { "mpr-12605a.ic1", 0x020000, 0xd367c3cc, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "mpr-12606a.ic2", 0x080000, 0xf56444c6, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_020000 }, +}; + +STD_ROM_PICK(md_ghouls) +STD_ROM_FN(md_ghouls) + +struct BurnDriver BurnDrvmd_ghouls = { + "md_ghouls", NULL, NULL, NULL, "1989", + "Ghouls 'n Ghosts (Euro, USA, Kor, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ghoulsRomInfo, md_ghoulsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ghouls 'n Ghosts (Euro, USA) +static struct BurnRomInfo md_ghouls1RomDesc[] = { + { "mpr-12605.ic1", 0x020000, 0x1066c6ab, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "mpr-12606.ic2", 0x080000, 0xceebc56f, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_020000 }, +}; + +STD_ROM_PICK(md_ghouls1) +STD_ROM_FN(md_ghouls1) + +struct BurnDriver BurnDrvmd_ghouls1 = { + "md_ghouls1", "md_ghouls", NULL, NULL, "1989", + "Ghouls 'n Ghosts (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ghouls1RomInfo, md_ghouls1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Greatest Heavyweights (Euro) +static struct BurnRomInfo md_ghwRomDesc[] = { + { "mpr-16211.ic1", 0x200000, 0x9778c181, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ghw) +STD_ROM_FN(md_ghw) + +struct BurnDriver BurnDrvmd_ghw = { + "md_ghw", NULL, NULL, NULL, "1994", + "Greatest Heavyweights (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_ghwRomInfo, md_ghwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Home Alone (Euro, USA) +static struct BurnRomInfo md_homeaRomDesc[] = { + { "mpr-14996.ic1", 0x080000, 0xaa0d4387, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_homea) +STD_ROM_FN(md_homea) + +struct BurnDriver BurnDrvmd_homea = { + "md_homea", NULL, NULL, NULL, "1992", + "Home Alone (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_homeaRomInfo, md_homeaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Joe Montana II Sports Talk Football (World) +static struct BurnRomInfo md_joemont2aRomDesc[] = { + { "mpr-14356.ic1", 0x100000, 0xf2363a4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_joemont2a) +STD_ROM_FN(md_joemont2a) + +struct BurnDriver BurnDrvmd_joemont2a = { + "md_joemont2a", "md_joemont2", NULL, NULL, "1991", + "Joe Montana II Sports Talk Football (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_joemont2aRomInfo, md_joemont2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Talmit's Adventure (Euro) +static struct BurnRomInfo md_talmitRomDesc[] = { + { "lrog453-eta.bin", 0x100000, 0x05dc3ffc, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_talmit) +STD_ROM_FN(md_talmit) + +struct BurnDriver BurnDrvmd_talmit = { + "md_talmit", NULL, NULL, NULL, "1991", + "Talmit's Adventure (Euro)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_talmitRomInfo, md_talmitRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marvel Land (Jpn) +static struct BurnRomInfo md_mvlndjRomDesc[] = { + { "lrog452-mml.bin", 0x100000, 0x5d162d21, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mvlndj) +STD_ROM_FN(md_mvlndj) + +struct BurnDriver BurnDrvmd_mvlndj = { + "md_mvlndj", "md_talmit", NULL, NULL, "1991", + "Marvel Land (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mvlndjRomInfo, md_mvlndjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Bomberman (Euro, Kor) +static struct BurnRomInfo md_megabombRomDesc[] = { + { "mpr-17108.ic1", 0x100000, 0x54ab3beb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megabomb) +STD_ROM_FN(md_megabomb) + +struct BurnDriver BurnDrvmd_megabomb = { + "md_megabomb", NULL, NULL, NULL, "1994", + "Mega Bomberman (Euro, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megabombRomInfo, md_megabombRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 6 Vol. 3 (Euro) +static struct BurnRomInfo md_megaga63RomDesc[] = { + { "mpr-18871.ic1", 0x300000, 0xfe3e7e4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga63) +STD_ROM_FN(md_megaga63) + +struct BurnDriver BurnDrvmd_megaga63 = { + "md_megaga63", NULL, NULL, NULL, "1995", + "Mega Games 6 Vol. 3 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga63RomInfo, md_megaga63RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines 2 - Turbo Tournament (Euro, J-Cart) +static struct BurnRomInfo md_microm2RomDesc[] = { + { "mdm_2bead.bin", 0x100000, 0x42bfb7eb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_microm2) +STD_ROM_FN(md_microm2) + +struct BurnDriver BurnDrvmd_microm2 = { + "md_microm2", NULL, NULL, NULL, "1994", + "Micro Machines 2 - Turbo Tournament (Euro, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_microm2RomInfo, md_microm2RomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines Turbo Tournament 96 (Euro, v1.1, J-Cart) +static struct BurnRomInfo md_micro96RomDesc[] = { + { "mm96mdeddb.bin", 0x100000, 0x23319d0d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_micro96) +STD_ROM_FN(md_micro96) + +struct BurnDriver BurnDrvmd_micro96 = { + "md_micro96", NULL, NULL, NULL, "1995", + "Micro Machines Turbo Tournament 96 (Euro, v1.1, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_micro96RomInfo, md_micro96RomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pete Sampras Tennis (Euro, USA, J-Cart) +static struct BurnRomInfo md_psamprasRomDesc[] = { + { "mdst6636.bin", 0x100000, 0x94e505b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psampras) +STD_ROM_FN(md_psampras) + +struct BurnDriver BurnDrvmd_psampras = { + "md_psampras", NULL, NULL, NULL, "1994", + "Pete Sampras Tennis (Euro, USA, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART, GBF_MISC, 0, + MegadriveGetZipName, md_psamprasRomInfo, md_psamprasRomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II (Euro, USA, Rev. A) +static struct BurnRomInfo md_pstar2RomDesc[] = { + { "mpr-12851a.ic1", 0x080000, 0x74714110, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "mpr-12852a.ic2", 0x080000, 0xe304231a, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_080000 }, +}; + +STD_ROM_PICK(md_pstar2) +STD_ROM_FN(md_pstar2) + +struct BurnDriver BurnDrvmd_pstar2 = { + "md_pstar2", NULL, NULL, NULL, "1989", + "Phantasy Star II (Euro, USA, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar2RomInfo, md_pstar2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force II (Euro) +static struct BurnRomInfo md_shinfrc2RomDesc[] = { + { "mpr-16933.ic1", 0x200000, 0x83cb46d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrc2) +STD_ROM_FN(md_shinfrc2) + +struct BurnDriver BurnDrvmd_shinfrc2 = { + "md_shinfrc2", NULL, NULL, NULL, "1994", + "Shining Force II (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrc2RomInfo, md_shinfrc2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Smurfs (Euro, Rev. A) +static struct BurnRomInfo md_smurfsRomDesc[] = { + { "mpr-17019a.ic1", 0x100000, 0x88b30eff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smurfs) +STD_ROM_FN(md_smurfs) + +struct BurnDriver BurnDrvmd_smurfs = { + "md_smurfs", NULL, NULL, NULL, "1995", + "The Smurfs (Euro, Rev. A)\0", NULL, "Infogrames", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smurfsRomInfo, md_smurfsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soleil (Spa) +static struct BurnRomInfo md_soleilsRomDesc[] = { + { "mpr-17512.ic1", 0x200000, 0x9ed4c323, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soleils) +STD_ROM_FN(md_soleils) + +struct BurnDriver BurnDrvmd_soleils = { + "md_soleils", "md_soleil", NULL, NULL, "1994", + "Soleil (Spa)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_soleilsRomInfo, md_soleilsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soleil (Fra) +static struct BurnRomInfo md_soleilfRomDesc[] = { + { "mpr-17513.ic1", 0x200000, 0x08dc1ead, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soleilf) +STD_ROM_FN(md_soleilf) + +struct BurnDriver BurnDrvmd_soleilf = { + "md_soleilf", "md_soleil", NULL, NULL, "1994", + "Soleil (Fra)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_soleilfRomInfo, md_soleilfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soleil (Ger) +static struct BurnRomInfo md_soleilgRomDesc[] = { + { "mpr-17514.ic1", 0x200000, 0x332b9ecd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soleilg) +STD_ROM_FN(md_soleilg) + +struct BurnDriver BurnDrvmd_soleilg = { + "md_soleilg", "md_soleil", NULL, NULL, "1994", + "Soleil (Ger)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_soleilgRomInfo, md_soleilgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 3 (Euro) +static struct BurnRomInfo md_sonic3RomDesc[] = { + { "mpr-16342.ic1", 0x200000, 0x6a632503, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3) +STD_ROM_FN(md_sonic3) + +struct BurnDriver BurnDrvmd_sonic3 = { + "md_sonic3", NULL, NULL, NULL, "1994", + "Sonic the Hedgehog 3 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3RomInfo, md_sonic3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 3 (Jpn, Kor) +static struct BurnRomInfo md_sonic3jRomDesc[] = { + { "mpr-16343.ic1", 0x200000, 0xf4951d1f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3j) +STD_ROM_FN(md_sonic3j) + +struct BurnDriver BurnDrvmd_sonic3j = { + "md_sonic3j", "md_sonic3", NULL, NULL, "1994", + "Sonic the Hedgehog 3 (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3jRomInfo, md_sonic3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Compilation (Euro, Earlier) +static struct BurnRomInfo md_soniccmp1RomDesc[] = { + { "mpr-18203.ic1", 0x200000, 0xfe61c79e, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "mpr-18204.ic2", 0x100000, 0x21d42146, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_200000 }, +}; + +STD_ROM_PICK(md_soniccmp1) +STD_ROM_FN(md_soniccmp1) + +struct BurnDriver BurnDrvmd_soniccmp1 = { + "md_soniccmp1", "md_soniccmp", NULL, NULL, "1995", + "Sonic Compilation (Euro, Earlier)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soniccmp1RomInfo, md_soniccmp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Spinball (Euro) +static struct BurnRomInfo md_sspinRomDesc[] = { + { "mpr-16077.ic1", 0x100000, 0xaea0786d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sspin) +STD_ROM_FN(md_sspin) + +struct BurnDriver BurnDrvmd_sspin = { + "md_sspin", NULL, NULL, NULL, "1993", + "Sonic Spinball (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sspinRomInfo, md_sspinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Space Harrier II (World) +static struct BurnRomInfo md_sharrRomDesc[] = { + { "mpr-12355.ic1", 0x080000, 0xe5c9cbb0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sharr) +STD_ROM_FN(md_sharr) + +struct BurnDriver BurnDrvmd_sharr = { + "md_sharr", NULL, NULL, NULL, "1989", + "Space Harrier II (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sharrRomInfo, md_sharrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor - A Successor of The Light (Fra) +static struct BurnRomInfo md_thorfRomDesc[] = { + { "mpr-17720.ic1", 0x200000, 0x5385f970, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, + { "mpr-17721.ic2", 0x100000, 0x158fa2aa, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_200000 }, +}; + +STD_ROM_PICK(md_thorf) +STD_ROM_FN(md_thorf) + +struct BurnDriver BurnDrvmd_thorf = { + "md_thorf", "md_thor", NULL, NULL, "1995", + "The Story of Thor - A Successor of The Light (Fra)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorfRomInfo, md_thorfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Monaco GP (Euro, Jpn, Rev. A) +static struct BurnRomInfo md_smgpRomDesc[] = { + { "mpr-13250a.ic1", 0x080000, 0xbe91b28a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgp) +STD_ROM_FN(md_smgp) + +struct BurnDriver BurnDrvmd_smgp = { + "md_smgp", NULL, NULL, NULL, "1990", + "Super Monaco GP (Euro, Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smgpRomInfo, md_smgpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Smash TV (Euro, USA) +static struct BurnRomInfo md_ssmashtvRomDesc[] = { + { "mpr-15040.ic1", 0x080000, 0xf22412b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssmashtv) +STD_ROM_FN(md_ssmashtv) + +struct BurnDriver BurnDrvmd_ssmashtv = { + "md_ssmashtv", NULL, NULL, NULL, "1992", + "Super Smash TV (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ssmashtvRomInfo, md_ssmashtvRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Addams Family (Euro, USA) +static struct BurnRomInfo md_addfamRomDesc[] = { + { "mpr-16147.ic1", 0x100000, 0x71f58614, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_addfam) +STD_ROM_FN(md_addfam) + +struct BurnDriver BurnDrvmd_addfam = { + "md_addfam", NULL, NULL, NULL, "1994", + "The Addams Family (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_addfamRomInfo, md_addfamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Light Crusader (Euro) +static struct BurnRomInfo md_lightcRomDesc[] = { + { "mpr-18090.ic1", 0x200000, 0x52c7252b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightc) +STD_ROM_FN(md_lightc) + +struct BurnDriver BurnDrvmd_lightc = { + "md_lightc", NULL, NULL, NULL, "1995", + "Light Crusader (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lightcRomInfo, md_lightcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN Speed World (USA, Prototype) +static struct BurnRomInfo md_espnsppRomDesc[] = { + { "u4.bin", 0x080000, 0x525788b1, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000000 }, + { "u5.bin", 0x080000, 0xada9c9a8, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000001 }, + { "u1.bin", 0x080000, 0xe8ee1029, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_100000 }, + { "u2.bin", 0x080000, 0x0f3ec491, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_100001 }, +}; + +STD_ROM_PICK(md_espnspp) +STD_ROM_FN(md_espnspp) + +struct BurnDriver BurnDrvmd_espnspp = { + "md_espnspp", "md_espnsp", NULL, NULL, "1994", + "ESPN Speed World (USA, Prototype)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_espnsppRomInfo, md_espnsppRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN Sunday Night NFL (USA, Prototype) +static struct BurnRomInfo md_espnnflpRomDesc[] = { + { "u4.bin", 0x080000, 0x9f427221, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000000 }, + { "u5.bin", 0x080000, 0x3445f0e8, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_000001 }, + { "u1.bin", 0x080000, 0x5d05efc5, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_100000 }, + { "u2.bin", 0x080000, 0x7ae6fd4b, BRF_PRG | SEGA_MD_ROM_LOAD16_BYTE | SEGA_MD_ROM_OFFS_100001 }, +}; + +STD_ROM_PICK(md_espnnflp) +STD_ROM_FN(md_espnnflp) + +struct BurnDriver BurnDrvmd_espnnflp = { + "md_espnnflp", "md_espnnfl", NULL, NULL, "1994", + "ESPN Sunday Night NFL (USA, Prototype)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_espnnflpRomInfo, md_espnnflpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Incredible Crash Dummies (Euro, USA) +static struct BurnRomInfo md_crashdumRomDesc[] = { + { "mpr-16259.ic1", 0x100000, 0x1f6e574a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crashdum) +STD_ROM_FN(md_crashdum) + +struct BurnDriver BurnDrvmd_crashdum = { + "md_crashdum", NULL, NULL, NULL, "1993", + "The Incredible Crash Dummies (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crashdumRomInfo, md_crashdumRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESWAT - City Under Siege (Euro, USA, Rev. A) +static struct BurnRomInfo md_eswatRomDesc[] = { + { "mpr-13192a.ic1", 0x080000, 0xe72f8a36, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eswat) +STD_ROM_FN(md_eswat) + +struct BurnDriver BurnDrvmd_eswat = { + "md_eswat", NULL, NULL, NULL, "1990", + "ESWAT - City Under Siege (Euro, USA, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eswatRomInfo, md_eswatRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Evander Holyfield's 'Real Deal' Boxing (World) +static struct BurnRomInfo md_evanderRomDesc[] = { + { "mpr-14860.ic1", 0x080000, 0x4fef37c8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_evander) +STD_ROM_FN(md_evander) + +struct BurnDriver BurnDrvmd_evander = { + "md_evander", NULL, NULL, NULL, "1992", + "Evander Holyfield's 'Real Deal' Boxing (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_evanderRomInfo, md_evanderRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ex-Mutants (Euro, USA) +static struct BurnRomInfo md_exmutantRomDesc[] = { + { "mpr-15225.ic1", 0x100000, 0x33b1979f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exmutant) +STD_ROM_FN(md_exmutant) + +struct BurnDriver BurnDrvmd_exmutant = { + "md_exmutant", NULL, NULL, NULL, "1992", + "Ex-Mutants (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exmutantRomInfo, md_exmutantRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Galaxy Force II (World, Rev. B) +static struct BurnRomInfo md_gforce2RomDesc[] = { + { "mpr-14248b.ic1", 0x100000, 0xd15f5c3c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gforce2) +STD_ROM_FN(md_gforce2) + +struct BurnDriver BurnDrvmd_gforce2 = { + "md_gforce2", NULL, NULL, NULL, "1991", + "Galaxy Force II (World, Rev. B)\0", NULL, "CRI ~ Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gforce2RomInfo, md_gforce2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mutant League Football (Euro, USA) +static struct BurnRomInfo md_mutantlfRomDesc[] = { + { "mlf03.u1", 0x100000, 0xdce29c9d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mutantlf) +STD_ROM_FN(md_mutantlf) + +struct BurnDriver BurnDrvmd_mutantlf = { + "md_mutantlf", NULL, NULL, NULL, "1993", + "Mutant League Football (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mutantlfRomInfo, md_mutantlfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pink Goes to Hollywood (Euro, USA) +static struct BurnRomInfo md_pinkRomDesc[] = { + { "mpr-16065.ic1", 0x100000, 0xb5804771, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pink) +STD_ROM_FN(md_pink) + +struct BurnDriver BurnDrvmd_pink = { + "md_pink", NULL, NULL, NULL, "1993", + "Pink Goes to Hollywood (Euro, USA)\0", NULL, "TecMagik", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pinkRomInfo, md_pinkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man and X-Men - Arcade's Revenge (Euro, USA) +static struct BurnRomInfo md_spidxmenRomDesc[] = { + { "mpr-15709.ic1", 0x100000, 0x4a4414ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidxmen) +STD_ROM_FN(md_spidxmen) + +struct BurnDriver BurnDrvmd_spidxmen = { + "md_spidxmen", NULL, NULL, NULL, "1994", + "Spider-Man and X-Men - Arcade's Revenge (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidxmenRomInfo, md_spidxmenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zoom! (World) +static struct BurnRomInfo md_zoomRomDesc[] = { + { "mpr-12807.ic1", 0x040000, 0x724d6965, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zoom) +STD_ROM_FN(md_zoom) + +struct BurnDriver BurnDrvmd_zoom = { + "md_zoom", NULL, NULL, NULL, "1990", + "Zoom! (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zoomRomInfo, md_zoomRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zany Golf (Euro, USA, v1.1) +static struct BurnRomInfo md_zanygolfRomDesc[] = { + { "zany golf (euro, usa) (v1.1).bin", 0x080000, 0x74ed7607, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zanygolf) +STD_ROM_FN(md_zanygolf) + +struct BurnDriver BurnDrvmd_zanygolf = { + "md_zanygolf", NULL, NULL, NULL, "1990", + "Zany Golf (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zanygolfRomInfo, md_zanygolfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bugs Bunny in Double Trouble (Euro) +static struct BurnRomInfo md_bugsbunRomDesc[] = { + { "mpr-18887.ic1", 0x200000, 0xcec0a0bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bugsbun) +STD_ROM_FN(md_bugsbun) + +struct BurnDriver BurnDrvmd_bugsbun = { + "md_bugsbun", NULL, NULL, NULL, "1996", + "Bugs Bunny in Double Trouble (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bugsbunRomInfo, md_bugsbunRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kid Chameleon (Euro, Korea, USA) +static struct BurnRomInfo md_kidchamRomDesc[] = { + { "mpr-14557.ic1", 0x100000, 0xce36e6cc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kidcham) +STD_ROM_FN(md_kidcham) + +struct BurnDriver BurnDrvmd_kidcham = { + "md_kidcham", NULL, NULL, NULL, "1992", + "Kid Chameleon (Euro, Korea, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kidchamRomInfo, md_kidchamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA Soccer 95 (Kor) +static struct BurnRomInfo md_fifa95kRomDesc[] = { + { "lh5370hd.bin", 0x200000, 0x012591f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa95k) +STD_ROM_FN(md_fifa95k) + +struct BurnDriver BurnDrvmd_fifa95k = { + "md_fifa95k", "md_fifa95", NULL, NULL, "1994", + "FIFA Soccer 95 (Kor)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa95kRomInfo, md_fifa95kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 13 Ma Jiang - 98 Mei Shao Nu Pian (Chi) +static struct BurnRomInfo md_13mahjanRomDesc[] = { + { "13 mahjong 98 (unl).bin", 0x0a0000, 0x68b372f6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_13mahjan) +STD_ROM_FN(md_13mahjan) + +struct BurnDriver BurnDrvmd_13mahjan = { + "md_13mahjan", NULL, NULL, NULL, "1998", + "13 Ma Jiang - 98 Mei Shao Nu Pian (Chi)\0", NULL, "BBD", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_13mahjanRomInfo, md_13mahjanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 16 Ton (Jpn, SegaNet) +static struct BurnRomInfo md_16tonRomDesc[] = { + { "16 ton (jpn) (sn).bin", 0x040000, 0x537f04b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_16ton) +STD_ROM_FN(md_16ton) + +struct BurnDriver BurnDrvmd_16ton = { + "md_16ton", NULL, NULL, NULL, "1991", + "16 Ton (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_16tonRomInfo, md_16tonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 16 Ton (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_16tongnkRomDesc[] = { + { "16 ton (jpn) (gnk).bin", 0x040000, 0x98149eaf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_16tongnk) +STD_ROM_FN(md_16tongnk) + +struct BurnDriver BurnDrvmd_16tongnk = { + "md_16tongnk", "md_16ton", NULL, NULL, "1991", + "16 Ton (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_16tongnkRomInfo, md_16tongnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 16 Zhang Ma Jiang (Chi) +static struct BurnRomInfo md_16zhanRomDesc[] = { + { "16 zhang ma jiang (chi) (unl).bin", 0x100000, 0x36407c82, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_16zhan) +STD_ROM_FN(md_16zhan) + +struct BurnDriver BurnDrvmd_16zhan = { + "md_16zhan", NULL, NULL, NULL, "199?", + "16 Zhang Ma Jiang (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_16zhanRomInfo, md_16zhanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 3 Ninjas Kick Back (USA) +static struct BurnRomInfo md_3ninjaRomDesc[] = { + { "3 ninjas kick back (usa).bin", 0x200000, 0xe5a24999, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_3ninja) +STD_ROM_FN(md_3ninja) + +struct BurnDriver BurnDrvmd_3ninja = { + "md_3ninja", NULL, NULL, NULL, "1994", + "3 Ninjas Kick Back (USA)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_3ninjaRomInfo, md_3ninjaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 3 in 1 Flashback - World Champ. Soccer - Tecmo World Cup 92 (Pirate) +static struct BurnRomInfo md_3in1flRomDesc[] = { + { "3-in-1 flashback - world champ. soccer - tecmo world cup 92 (pirate).bin", 0x200000, 0xa8fd28d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_3in1fl) +STD_ROM_FN(md_3in1fl) + +struct BurnDriver BurnDrvmd_3in1fl = { + "md_3in1fl", NULL, NULL, NULL, "199?", + "3 in 1 Flashback - World Champ. Soccer - Tecmo World Cup 92 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_3in1flRomInfo, md_3in1flRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 3 in 1 Road Rash - Ms. Pac-Man - Block Out (Pirate) +static struct BurnRomInfo md_3in1roRomDesc[] = { + { "3-in-1 road rash - ms. pac-man - block out (pirate).bin", 0x100000, 0x13c96154, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_3in1ro) +STD_ROM_FN(md_3in1ro) + +struct BurnDriver BurnDrvmd_3in1ro = { + "md_3in1ro", NULL, NULL, NULL, "199?", + "3 in 1 Road Rash - Ms. Pac-Man - Block Out (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_3in1roRomInfo, md_3in1roRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 6-Pak (USA) +static struct BurnRomInfo md_6pakRomDesc[] = { + { "6-pak (usa).bin", 0x300000, 0x1a6f45dc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_6pak) +STD_ROM_FN(md_6pak) + +struct BurnDriver BurnDrvmd_6pak = { + "md_6pak", NULL, NULL, NULL, "1996", + "6-Pak (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_6pakRomInfo, md_6pakRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 688 Attack Sub (Euro, USA) +static struct BurnRomInfo md_688atsubRomDesc[] = { + { "mpr-13956.bin", 0x100000, 0xf2c58bf7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_688atsub) +STD_ROM_FN(md_688atsub) + +struct BurnDriver BurnDrvmd_688atsub = { + "md_688atsub", NULL, NULL, NULL, "1991", + "688 Attack Sub (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_688atsubRomInfo, md_688atsubRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// A Ressha de Ikou MD - Take the ''A'' Train (Jpn) +static struct BurnRomInfo md_aresshikRomDesc[] = { + { "a ressha de ikou md (jpn).bin", 0x080000, 0x3d45de4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aresshik) +STD_ROM_FN(md_aresshik) + +struct BurnDriver BurnDrvmd_aresshik = { + "md_aresshik", NULL, NULL, NULL, "1992", + "A Ressha de Ikou MD - Take the ''A'' Train (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_aresshikRomInfo, md_aresshikRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aa Harimanada (Jpn) +static struct BurnRomInfo md_aaharimaRomDesc[] = { + { "aa harimanada (jpn).bin", 0x200000, 0x065f6021, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aaharima) +STD_ROM_FN(md_aaharima) + +struct BurnDriver BurnDrvmd_aaharima = { + "md_aaharima", NULL, NULL, NULL, "1993", + "Aa Harimanada (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aaharimaRomInfo, md_aaharimaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// AAAHH!!! Real Monsters (Euro) +static struct BurnRomInfo md_aaahhrmRomDesc[] = { + { "aaahh!!! real monsters (euro).bin", 0x200000, 0x7ad115ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aaahhrm) +STD_ROM_FN(md_aaahhrm) + +struct BurnDriver BurnDrvmd_aaahhrm = { + "md_aaahhrm", NULL, NULL, NULL, "1995", + "AAAHH!!! Real Monsters (Euro)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aaahhrmRomInfo, md_aaahhrmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// AAAHH!!! Real Monsters (USA) +static struct BurnRomInfo md_aaahhrmuRomDesc[] = { + { "aaahh!!! real monsters (usa).bin", 0x200000, 0xfdc80bfc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aaahhrmu) +STD_ROM_FN(md_aaahhrmu) + +struct BurnDriver BurnDrvmd_aaahhrmu = { + "md_aaahhrmu", "md_aaahhrm", NULL, NULL, "1995", + "AAAHH!!! Real Monsters (USA)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aaahhrmuRomInfo, md_aaahhrmuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Action 52 (USA) +static struct BurnRomInfo md_action52RomDesc[] = { + { "action 52 (usa) (unl).bin", 0x200000, 0x29ff58ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_action52) +STD_ROM_FN(md_action52) + +struct BurnDriver BurnDrvmd_action52 = { + "md_action52", NULL, NULL, NULL, "1993", + "Action 52 (USA)\0", NULL, "Active Enterprises", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_action52RomInfo, md_action52RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Action 52 (USA, Alt) +static struct BurnRomInfo md_action52aRomDesc[] = { + { "action 52 (usa) (alt) (unl).bin", 0x200000, 0x8809d666, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_action52a) +STD_ROM_FN(md_action52a) + +struct BurnDriver BurnDrvmd_action52a = { + "md_action52a", "md_action52", NULL, NULL, "1993", + "Action 52 (USA, Alt)\0", NULL, "Active Enterprises", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_action52aRomInfo, md_action52aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Addams Family Values (Euro) +static struct BurnRomInfo md_addfamvRomDesc[] = { + { "addams family values (euro).bin", 0x200000, 0xb906b992, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_addfamv) +STD_ROM_FN(md_addfamv) + +struct BurnDriver BurnDrvmd_addfamv = { + "md_addfamv", NULL, NULL, NULL, "1994", + "Addams Family Values (Euro)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_addfamvRomInfo, md_addfamvRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Addams Family (USA, Prototype) +static struct BurnRomInfo md_addfamp1RomDesc[] = { + { "addams family, the (usa) (beta).bin", 0x100000, 0x2803a5ca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_addfamp1) +STD_ROM_FN(md_addfamp1) + +struct BurnDriver BurnDrvmd_addfamp1 = { + "md_addfamp1", "md_addfam", NULL, NULL, "1994", + "The Addams Family (USA, Prototype)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_addfamp1RomInfo, md_addfamp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Addams Family (USA, Prototype, Alt) +static struct BurnRomInfo md_addfamp2RomDesc[] = { + { "addams family, the (usa) (beta) (alt).bin", 0x100000, 0x3a173e1f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_addfamp2) +STD_ROM_FN(md_addfamp2) + +struct BurnDriver BurnDrvmd_addfamp2 = { + "md_addfamp2", "md_addfam", NULL, NULL, "1994", + "The Addams Family (USA, Prototype, Alt)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_addfamp2RomInfo, md_addfamp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Advanced Daisenryaku - Deutsch Dengeki Sakusen (Jpn, Rev. A) +static struct BurnRomInfo md_advdaiRomDesc[] = { + { "mpr-13842a.bin", 0x100000, 0xe0d5e18a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advdai) +STD_ROM_FN(md_advdai) + +struct BurnDriver BurnDrvmd_advdai = { + "md_advdai", NULL, NULL, NULL, "1991", + "Advanced Daisenryaku - Deutsch Dengeki Sakusen (Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_advdaiRomInfo, md_advdaiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950406) +static struct BurnRomInfo md_advbatrp12RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 06, 1995).bin", 0x200000, 0xf05cf389, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp12) +STD_ROM_FN(md_advbatrp12) + +struct BurnDriver BurnDrvmd_advbatrp12 = { + "md_advbatrp12", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950406)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp12RomInfo, md_advbatrp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950410) +static struct BurnRomInfo md_advbatrp11RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 10, 1995).bin", 0x200000, 0xd4f3a070, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp11) +STD_ROM_FN(md_advbatrp11) + +struct BurnDriver BurnDrvmd_advbatrp11 = { + "md_advbatrp11", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950410)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp11RomInfo, md_advbatrp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950411) +static struct BurnRomInfo md_advbatrp10RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 11, 1995).bin", 0x200000, 0xb5b5a290, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp10) +STD_ROM_FN(md_advbatrp10) + +struct BurnDriver BurnDrvmd_advbatrp10 = { + "md_advbatrp10", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950411)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp10RomInfo, md_advbatrp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950418) +static struct BurnRomInfo md_advbatrp09RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 18, 1995).bin", 0x200000, 0x6874142b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp09) +STD_ROM_FN(md_advbatrp09) + +struct BurnDriver BurnDrvmd_advbatrp09 = { + "md_advbatrp09", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950418)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp09RomInfo, md_advbatrp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950419) +static struct BurnRomInfo md_advbatrp08RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 19, 1995).bin", 0x200000, 0x7002da56, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp08) +STD_ROM_FN(md_advbatrp08) + +struct BurnDriver BurnDrvmd_advbatrp08 = { + "md_advbatrp08", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950419)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp08RomInfo, md_advbatrp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950421) +static struct BurnRomInfo md_advbatrp07RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 21, 1995).bin", 0x200000, 0x61f02f13, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp07) +STD_ROM_FN(md_advbatrp07) + +struct BurnDriver BurnDrvmd_advbatrp07 = { + "md_advbatrp07", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950421)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp07RomInfo, md_advbatrp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950422) +static struct BurnRomInfo md_advbatrp06RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 22, 1995).bin", 0x200000, 0xeb8236b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp06) +STD_ROM_FN(md_advbatrp06) + +struct BurnDriver BurnDrvmd_advbatrp06 = { + "md_advbatrp06", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950422)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp06RomInfo, md_advbatrp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950424) +static struct BurnRomInfo md_advbatrp05RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 24, 1995).bin", 0x200000, 0x253947f8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp05) +STD_ROM_FN(md_advbatrp05) + +struct BurnDriver BurnDrvmd_advbatrp05 = { + "md_advbatrp05", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950424)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp05RomInfo, md_advbatrp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950426) +static struct BurnRomInfo md_advbatrp04RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 26, 1995).bin", 0x200000, 0xbc79f7ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp04) +STD_ROM_FN(md_advbatrp04) + +struct BurnDriver BurnDrvmd_advbatrp04 = { + "md_advbatrp04", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950426)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp04RomInfo, md_advbatrp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950427) +static struct BurnRomInfo md_advbatrp03RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 27, 1995).bin", 0x200000, 0xfdac8190, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp03) +STD_ROM_FN(md_advbatrp03) + +struct BurnDriver BurnDrvmd_advbatrp03 = { + "md_advbatrp03", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950427)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp03RomInfo, md_advbatrp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950428) +static struct BurnRomInfo md_advbatrp02RomDesc[] = { + { "adventures of batman & robin, the (prototype - apr 28, 1995).bin", 0x200000, 0x27a1524b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp02) +STD_ROM_FN(md_advbatrp02) + +struct BurnDriver BurnDrvmd_advbatrp02 = { + "md_advbatrp02", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950428)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp02RomInfo, md_advbatrp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (Prototype, 19950501) +static struct BurnRomInfo md_advbatrp01RomDesc[] = { + { "adventures of batman & robin, the (prototype - may 01, 1995).bin", 0x200000, 0x589aa203, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatrp01) +STD_ROM_FN(md_advbatrp01) + +struct BurnDriver BurnDrvmd_advbatrp01 = { + "md_advbatrp01", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (Prototype, 19950501)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatrp01RomInfo, md_advbatrp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Batman & Robin (USA) +static struct BurnRomInfo md_advbatruRomDesc[] = { + { "adventures of batman & robin, the (usa).bin", 0x200000, 0x0caaa4ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_advbatru) +STD_ROM_FN(md_advbatru) + +struct BurnDriver BurnDrvmd_advbatru = { + "md_advbatru", "md_advbatr", NULL, NULL, "1995", + "The Adventures of Batman & Robin (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_advbatruRomInfo, md_advbatruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Mighty Max (USA) +static struct BurnRomInfo md_mightmaxuRomDesc[] = { + { "adventures of mighty max, the (usa).bin", 0x100000, 0x55f13a00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mightmaxu) +STD_ROM_FN(md_mightmaxu) + +struct BurnDriver BurnDrvmd_mightmaxu = { + "md_mightmaxu", "md_mightmax", NULL, NULL, "1994", + "The Adventures of Mighty Max (USA)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mightmaxuRomInfo, md_mightmaxuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Adventures of Rocky and Bullwinkle and Friends (USA) +static struct BurnRomInfo md_rockybwRomDesc[] = { + { "adventures of rocky and bullwinkle and friends, the (usa).bin", 0x100000, 0xef02d57b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rockybw) +STD_ROM_FN(md_rockybw) + +struct BurnDriver BurnDrvmd_rockybw = { + "md_rockybw", NULL, NULL, NULL, "1993", + "The Adventures of Rocky and Bullwinkle and Friends (USA)\0", NULL, "Absolute Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rockybwRomInfo, md_rockybwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Adventurous Boy - Mao Xian Xiao Zi (Chi) +static struct BurnRomInfo md_adveboyRomDesc[] = { + { "adventurous boy - mao xian xiao zi (chi) (unl).bin", 0x080000, 0xd4403913, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_adveboy) +STD_ROM_FN(md_adveboy) + +struct BurnDriver BurnDrvmd_adveboy = { + "md_adveboy", NULL, NULL, NULL, "199?", + "Adventurous Boy - Mao Xian Xiao Zi (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_adveboyRomInfo, md_adveboyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero the Acro-Bat (Euro) +static struct BurnRomInfo md_aeroRomDesc[] = { + { "mpr-16603.bin", 0x100000, 0x1a3eaf57, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aero) +STD_ROM_FN(md_aero) + +struct BurnDriver BurnDrvmd_aero = { + "md_aero", NULL, NULL, NULL, "1993", + "Aero the Acro-Bat (Euro)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aeroRomInfo, md_aeroRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero the Acro-Bat (Prototype) +static struct BurnRomInfo md_aeropRomDesc[] = { + { "aero the acro-bat (beta).bin", 0x100000, 0xdcd14b10, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aerop) +STD_ROM_FN(md_aerop) + +struct BurnDriver BurnDrvmd_aerop = { + "md_aerop", "md_aero", NULL, NULL, "1993", + "Aero the Acro-Bat (Prototype)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aeropRomInfo, md_aeropRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero the Acro-Bat (USA) +static struct BurnRomInfo md_aerouRomDesc[] = { + { "aero the acro-bat (usa).bin", 0x100000, 0xa3a7a8b5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aerou) +STD_ROM_FN(md_aerou) + +struct BurnDriver BurnDrvmd_aerou = { + "md_aerou", "md_aero", NULL, NULL, "1993", + "Aero the Acro-Bat (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aerouRomInfo, md_aerouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero the Acro-Bat 2 (Euro) +static struct BurnRomInfo md_aero2RomDesc[] = { + { "mpr-17303.bin", 0x200000, 0xa451f9a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aero2) +STD_ROM_FN(md_aero2) + +struct BurnDriver BurnDrvmd_aero2 = { + "md_aero2", NULL, NULL, NULL, "1994", + "Aero the Acro-Bat 2 (Euro)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aero2RomInfo, md_aero2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero the Acro-Bat 2 (USA) +static struct BurnRomInfo md_aero2uRomDesc[] = { + { "aero the acro-bat 2 (usa).bin", 0x200000, 0x39eb74eb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aero2u) +STD_ROM_FN(md_aero2u) + +struct BurnDriver BurnDrvmd_aero2u = { + "md_aero2u", "md_aero2", NULL, NULL, "1994", + "Aero the Acro-Bat 2 (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aero2uRomInfo, md_aero2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aerobiz (USA) +static struct BurnRomInfo md_aerobizRomDesc[] = { + { "aerobiz (usa).bin", 0x100000, 0xcfaa9bce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aerobiz) +STD_ROM_FN(md_aerobiz) + +struct BurnDriver BurnDrvmd_aerobiz = { + "md_aerobiz", NULL, NULL, NULL, "1992", + "Aerobiz (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_aerobizRomInfo, md_aerobizRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Air Management - Oozora ni Kakeru (Jpn) +static struct BurnRomInfo md_airmanagRomDesc[] = { + { "air management - oozora ni kakeru (jpn).bin", 0x100000, 0xb3db0c71, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_airmanag) +STD_ROM_FN(md_airmanag) + +struct BurnDriver BurnDrvmd_airmanag = { + "md_airmanag", "md_aerobiz", NULL, NULL, "1992", + "Air Management - Oozora ni Kakeru (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_airmanagRomInfo, md_airmanagRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aerobiz Supersonic (USA) +static struct BurnRomInfo md_aerobizsRomDesc[] = { + { "aerobiz supersonic (usa).bin", 0x100000, 0x9377f1b5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aerobizs) +STD_ROM_FN(md_aerobizs) + +struct BurnDriver BurnDrvmd_aerobizs = { + "md_aerobizs", NULL, NULL, NULL, "1994", + "Aerobiz Supersonic (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_aerobizsRomInfo, md_aerobizsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Air Management II - Koukuuou o Mezase (Jpn) +static struct BurnRomInfo md_airmang2RomDesc[] = { + { "air management ii - koukuuou o mezase (jpn).bin", 0x100000, 0x4582817b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_airmang2) +STD_ROM_FN(md_airmang2) + +struct BurnDriver BurnDrvmd_airmang2 = { + "md_airmang2", "md_aerobizs", NULL, NULL, "1994", + "Air Management II - Koukuuou o Mezase (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_airmang2RomInfo, md_airmang2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// After Burner II (Euro, USA) +static struct BurnRomInfo md_aburner2RomDesc[] = { + { "mpr-13261.bin", 0x080000, 0xccafe00e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aburner2) +STD_ROM_FN(md_aburner2) + +struct BurnDriver BurnDrvmd_aburner2 = { + "md_aburner2", NULL, NULL, NULL, "1990", + "After Burner II (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aburner2RomInfo, md_aburner2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// After Burner II (Jpn) +static struct BurnRomInfo md_aburner2jRomDesc[] = { + { "mpr-12941.bin", 0x080000, 0x4ff37e66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aburner2j) +STD_ROM_FN(md_aburner2j) + +struct BurnDriver BurnDrvmd_aburner2j = { + "md_aburner2j", "md_aburner2", NULL, NULL, "1990", + "After Burner II (Jpn)\0", NULL, "Denpa Shinbunsha", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aburner2jRomInfo, md_aburner2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Air Buster: Trouble Specialty Raid Unit (USA) +static struct BurnRomInfo md_airbustrRomDesc[] = { + { "air buster (usa).bin", 0x080000, 0xf3d65baa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_airbustr) +STD_ROM_FN(md_airbustr) + +struct BurnDriver BurnDrvmd_airbustr = { + "md_airbustr", NULL, NULL, NULL, "1991", + "Air Buster: Trouble Specialty Raid Unit (USA)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_airbustrRomInfo, md_airbustrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aero Blasters: Trouble Specialty Raid Unit (Jpn) +static struct BurnRomInfo md_aeroblstRomDesc[] = { + { "aero blasters (jpn).bin", 0x080000, 0xa00da987, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aeroblst) +STD_ROM_FN(md_aeroblst) + +struct BurnDriver BurnDrvmd_aeroblst = { + "md_aeroblst", "md_airbustr", NULL, NULL, "1991", + "Aero Blasters: Trouble Specialty Raid Unit (Jpn)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aeroblstRomInfo, md_aeroblstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Air Diver (USA) +static struct BurnRomInfo md_airdiverRomDesc[] = { + { "air diver (usa).bin", 0x080000, 0x2041885e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_airdiver) +STD_ROM_FN(md_airdiver) + +struct BurnDriver BurnDrvmd_airdiver = { + "md_airdiver", NULL, NULL, NULL, "1990", + "Air Diver (USA)\0", NULL, "Seismic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_airdiverRomInfo, md_airdiverRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Air Diver (Jpn) +static struct BurnRomInfo md_airdiverjRomDesc[] = { + { "air diver (jpn).bin", 0x080000, 0x9e2d5b91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_airdiverj) +STD_ROM_FN(md_airdiverj) + +struct BurnDriver BurnDrvmd_airdiverj = { + "md_airdiverj", "md_airdiver", NULL, NULL, "1990", + "Air Diver (Jpn)\0", NULL, "Asmik Ace", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_airdiverjRomInfo, md_airdiverjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Aladdin (Euro) +static struct BurnRomInfo md_aladdinRomDesc[] = { + { "mpr-15939.bin", 0x200000, 0xd1845e8f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aladdin) +STD_ROM_FN(md_aladdin) + +struct BurnDriver BurnDrvmd_aladdin = { + "md_aladdin", NULL, NULL, NULL, "1993", + "Disney's Aladdin (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aladdinRomInfo, md_aladdinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Aladdin (Jpn) +static struct BurnRomInfo md_aladdinjRomDesc[] = { + { "aladdin (jpn).bin", 0x200000, 0xfb5aacf0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aladdinj) +STD_ROM_FN(md_aladdinj) + +struct BurnDriver BurnDrvmd_aladdinj = { + "md_aladdinj", "md_aladdin", NULL, NULL, "1993", + "Disney's Aladdin (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aladdinjRomInfo, md_aladdinjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Aladdin (USA) +static struct BurnRomInfo md_aladdinuRomDesc[] = { + { "aladdin (usa).bin", 0x200000, 0xed427ea9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aladdinu) +STD_ROM_FN(md_aladdinu) + +struct BurnDriver BurnDrvmd_aladdinu = { + "md_aladdinu", "md_aladdin", NULL, NULL, "1993", + "Disney's Aladdin (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aladdinuRomInfo, md_aladdinuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Aladdin (USA, Prototype) +static struct BurnRomInfo md_aladdinupRomDesc[] = { + { "aladdin (usa) (beta).bin", 0x200000, 0x8c60ef73, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aladdinup) +STD_ROM_FN(md_aladdinup) + +struct BurnDriver BurnDrvmd_aladdinup = { + "md_aladdinup", "md_aladdin", NULL, NULL, "1993", + "Disney's Aladdin (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aladdinupRomInfo, md_aladdinupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aladdin II +static struct BurnRomInfo md_aladdin2RomDesc[] = { + { "aladdin ii (unl).bin", 0x200000, 0xbe5f9397, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aladdin2) +STD_ROM_FN(md_aladdin2) + +struct BurnDriver BurnDrvmd_aladdin2 = { + "md_aladdin2", NULL, NULL, NULL, "199?", + "Aladdin II\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aladdin2RomInfo, md_aladdin2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alex Kidd in the Enchanted Castle (Euro) +static struct BurnRomInfo md_alexkidd1RomDesc[] = { + { "alex kidd in the enchanted castle (euro).bin", 0x040000, 0xc3a52529, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alexkidd1) +STD_ROM_FN(md_alexkidd1) + +struct BurnDriver BurnDrvmd_alexkidd1 = { + "md_alexkidd1", "md_alexkidd", NULL, NULL, "1990", + "Alex Kidd in the Enchanted Castle (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alexkidd1RomInfo, md_alexkidd1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alex Kidd in the Enchanted Castle (Jpn) +static struct BurnRomInfo md_alexkiddjRomDesc[] = { + { "alex kidd - tenkuu majou (jpn).bin", 0x040000, 0x8a5ed856, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alexkiddj) +STD_ROM_FN(md_alexkiddj) + +struct BurnDriver BurnDrvmd_alexkiddj = { + "md_alexkiddj", "md_alexkidd", NULL, NULL, "1989", + "Alex Kidd in the Enchanted Castle (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alexkiddjRomInfo, md_alexkiddjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alex Kidd - Cheongong Maseong (Kor) +static struct BurnRomInfo md_alexkiddkRomDesc[] = { + { "alex kidd - cheongong maseong (kor).bin", 0x040000, 0x5b0678fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alexkiddk) +STD_ROM_FN(md_alexkiddk) + +struct BurnDriver BurnDrvmd_alexkiddk = { + "md_alexkiddk", "md_alexkidd", NULL, NULL, "1990", + "Alex Kidd - Cheongong Maseong (Kor)\0", NULL, "Samsung", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alexkiddkRomInfo, md_alexkiddkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alex Kidd in the Enchanted Castle (USA) +static struct BurnRomInfo md_alexkidduRomDesc[] = { + { "alex kidd in the enchanted castle (usa).bin", 0x040000, 0x47dba0ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alexkiddu) +STD_ROM_FN(md_alexkiddu) + +struct BurnDriver BurnDrvmd_alexkiddu = { + "md_alexkiddu", "md_alexkidd", NULL, NULL, "1989", + "Alex Kidd in the Enchanted Castle (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alexkidduRomInfo, md_alexkidduRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alien³ (Euro, USA, Rev. A) +static struct BurnRomInfo md_alien3RomDesc[] = { + { "mpr-15061a.bin", 0x080000, 0xb327fd1b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alien3) +STD_ROM_FN(md_alien3) + +struct BurnDriver BurnDrvmd_alien3 = { + "md_alien3", NULL, NULL, NULL, "1993", + "Alien3 (Euro, USA, Rev. A)\0", NULL, "Arena Entertainment", "Sega Megadrive", + L"Alien\u00b3 (Euro, USA, Rev. A)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alien3RomInfo, md_alien3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alien³ (Euro, USA) +static struct BurnRomInfo md_alien3aRomDesc[] = { + { "mpr-15061.bin", 0x080000, 0xa3b00d6e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alien3a) +STD_ROM_FN(md_alien3a) + +struct BurnDriver BurnDrvmd_alien3a = { + "md_alien3a", "md_alien3", NULL, NULL, "1993", + "Alien3 (Euro, USA)\0", NULL, "Arena Entertainment", "Sega Megadrive", + L"Alien\u00b3 (Euro, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alien3aRomInfo, md_alien3aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alien Soldier (Euro) +static struct BurnRomInfo md_aliensRomDesc[] = { + { "alien soldier (euro).bin", 0x200000, 0x0496e06c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aliens) +STD_ROM_FN(md_aliens) + +struct BurnDriver BurnDrvmd_aliens = { + "md_aliens", NULL, NULL, NULL, "1995", + "Alien Soldier (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aliensRomInfo, md_aliensRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alien Soldier (Jpn) +static struct BurnRomInfo md_aliensjRomDesc[] = { + { "alien soldier (jpn).bin", 0x200000, 0x90fa1539, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aliensj) +STD_ROM_FN(md_aliensj) + +struct BurnDriver BurnDrvmd_aliensj = { + "md_aliensj", "md_aliens", NULL, NULL, "1995", + "Alien Soldier (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aliensjRomInfo, md_aliensjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alien Storm (World) +static struct BurnRomInfo md_alienstmRomDesc[] = { + { "mpr-13941.bin", 0x080000, 0xf5ac8de5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alienstm) +STD_ROM_FN(md_alienstm) + +struct BurnDriver BurnDrvmd_alienstm = { + "md_alienstm", NULL, NULL, NULL, "1991", + "Alien Storm (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alienstmRomInfo, md_alienstmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alisia Dragoon (Jpn) +static struct BurnRomInfo md_alisiadjRomDesc[] = { + { "alisia dragoon (jpn).bin", 0x100000, 0x4d476722, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alisiadj) +STD_ROM_FN(md_alisiadj) + +struct BurnDriver BurnDrvmd_alisiadj = { + "md_alisiadj", "md_alisiad", NULL, NULL, "1992", + "Alisia Dragoon (Jpn)\0", NULL, "Game Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alisiadjRomInfo, md_alisiadjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Alisia Dragoon (USA) +static struct BurnRomInfo md_alisiaduRomDesc[] = { + { "alisia dragoon (usa).bin", 0x100000, 0xd28d5c40, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_alisiadu) +STD_ROM_FN(md_alisiadu) + +struct BurnDriver BurnDrvmd_alisiadu = { + "md_alisiadu", "md_alisiad", NULL, NULL, "1992", + "Alisia Dragoon (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_alisiaduRomInfo, md_alisiaduRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Altered Beast (Euro, USA) +static struct BurnRomInfo md_altbeastRomDesc[] = { + { "mpr-12538.bin", 0x080000, 0x154d59bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_altbeast) +STD_ROM_FN(md_altbeast) + +struct BurnDriver BurnDrvmd_altbeast = { + "md_altbeast", NULL, NULL, NULL, "1989", + "Altered Beast (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_altbeastRomInfo, md_altbeastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Juuouki (Jpn, v1.1) +static struct BurnRomInfo md_juuoukiRomDesc[] = { + { "juuouki (jpn) (v1.1).bin", 0x080000, 0xb2233e87, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_juuouki) +STD_ROM_FN(md_juuouki) + +struct BurnDriver BurnDrvmd_juuouki = { + "md_juuouki", "md_altbeast", NULL, NULL, "1988", + "Juuouki (Jpn, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_juuoukiRomInfo, md_juuoukiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Juuouki (Jpn) +static struct BurnRomInfo md_juuouki1RomDesc[] = { + { "juuouki (jpn).bin", 0x080000, 0x1b7c96c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_juuouki1) +STD_ROM_FN(md_juuouki1) + +struct BurnDriver BurnDrvmd_juuouki1 = { + "md_juuouki1", "md_altbeast", NULL, NULL, "1988", + "Juuouki (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_juuouki1RomInfo, md_juuouki1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// American Gladiators (USA) +static struct BurnRomInfo md_amergladRomDesc[] = { + { "american gladiators (usa).bin", 0x100000, 0x9952fa85, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_amerglad) +STD_ROM_FN(md_amerglad) + +struct BurnDriver BurnDrvmd_amerglad = { + "md_amerglad", NULL, NULL, NULL, "1992", + "American Gladiators (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_amergladRomInfo, md_amergladRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Andre Agassi Tennis (USA) +static struct BurnRomInfo md_agassiuRomDesc[] = { + { "andre agassi tennis (usa).bin", 0x080000, 0xe755dd51, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_agassiu) +STD_ROM_FN(md_agassiu) + +struct BurnDriver BurnDrvmd_agassiu = { + "md_agassiu", "md_agassi", NULL, NULL, "1992", + "Andre Agassi Tennis (USA)\0", NULL, "TecMagik", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_agassiuRomInfo, md_agassiuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Andre Agassi Tennis (USA, Prototype) +static struct BurnRomInfo md_agassiupRomDesc[] = { + { "andre agassi tennis (usa) (beta).bin", 0x080000, 0x3bbf700d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_agassiup) +STD_ROM_FN(md_agassiup) + +struct BurnDriver BurnDrvmd_agassiup = { + "md_agassiup", "md_agassi", NULL, NULL, "1992", + "Andre Agassi Tennis (USA, Prototype)\0", NULL, "TecMagik", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_agassiupRomInfo, md_agassiupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Animaniacs (Euro) +static struct BurnRomInfo md_animanRomDesc[] = { + { "fx014a1.bin", 0x100000, 0x92b6f255, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_animan) +STD_ROM_FN(md_animan) + +struct BurnDriver BurnDrvmd_animan = { + "md_animan", NULL, NULL, NULL, "1994", + "Animaniacs (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_animanRomInfo, md_animanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Animaniacs (USA) +static struct BurnRomInfo md_animanuRomDesc[] = { + { "animaniacs (usa).bin", 0x100000, 0x86224d86, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_animanu) +STD_ROM_FN(md_animanu) + +struct BurnDriver BurnDrvmd_animanu = { + "md_animanu", "md_animan", NULL, NULL, "1994", + "Animaniacs (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_animanuRomInfo, md_animanuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Out of This World (USA) +static struct BurnRomInfo md_ootwRomDesc[] = { + { "out of this world (usa).bin", 0x100000, 0x2da36e01, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ootw) +STD_ROM_FN(md_ootw) + +struct BurnDriver BurnDrvmd_ootw = { + "md_ootw", "md_anotherw", NULL, NULL, "1993", + "Out of This World (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ootwRomInfo, md_ootwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Out of this World (Prototype) +static struct BurnRomInfo md_ootwpRomDesc[] = { + { "out of this world (beta).bin", 0x100000, 0x3aad905a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ootwp) +STD_ROM_FN(md_ootwp) + +struct BurnDriver BurnDrvmd_ootwp = { + "md_ootwp", "md_anotherw", NULL, NULL, "1993", + "Out of this World (Prototype)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ootwpRomInfo, md_ootwpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aq Renkan Awa (Chi) +static struct BurnRomInfo md_aqrenkRomDesc[] = { + { "aq renkan awa (chi) (unl).bin", 0x100000, 0x2c6cbd77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aqrenk) +STD_ROM_FN(md_aqrenk) + +struct BurnDriver BurnDrvmd_aqrenk = { + "md_aqrenk", NULL, NULL, NULL, "1995", + "Aq Renkan Awa (Chi)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aqrenkRomInfo, md_aqrenkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Aquatic Games Starring James Pond and the Aquabats (Euro, USA) +static struct BurnRomInfo md_aquaticgRomDesc[] = { + { "aqua01.bin", 0x080000, 0x400f4ba7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aquaticg) +STD_ROM_FN(md_aquaticg) + +struct BurnDriver BurnDrvmd_aquaticg = { + "md_aquaticg", NULL, NULL, NULL, "1992", + "The Aquatic Games Starring James Pond and the Aquabats (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aquaticgRomInfo, md_aquaticgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arch Rivals (Euro, USA) +static struct BurnRomInfo md_archrivlRomDesc[] = { + { "mpr-14764.bin", 0x080000, 0xe389d7e7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_archrivl) +STD_ROM_FN(md_archrivl) + +struct BurnDriver BurnDrvmd_archrivl = { + "md_archrivl", NULL, NULL, NULL, "1992", + "Arch Rivals (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_archrivlRomInfo, md_archrivlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arcus Odyssey (USA) +static struct BurnRomInfo md_arcusRomDesc[] = { + { "arcus odyssey (usa).bin", 0x100000, 0xbc4d9b20, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arcus) +STD_ROM_FN(md_arcus) + +struct BurnDriver BurnDrvmd_arcus = { + "md_arcus", NULL, NULL, NULL, "1991", + "Arcus Odyssey (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arcusRomInfo, md_arcusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arcus Odyssey (Jpn) +static struct BurnRomInfo md_arcusjRomDesc[] = { + { "arcus odyssey (jpn).bin", 0x100000, 0x41c5fb4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arcusj) +STD_ROM_FN(md_arcusj) + +struct BurnDriver BurnDrvmd_arcusj = { + "md_arcusj", "md_arcus", NULL, NULL, "1991", + "Arcus Odyssey (Jpn)\0", NULL, "Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arcusjRomInfo, md_arcusjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Ariel the Little Mermaid (Euro, USA) +static struct BurnRomInfo md_arielRomDesc[] = { + { "mpr-15153.bin", 0x080000, 0x58e297df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ariel) +STD_ROM_FN(md_ariel) + +struct BurnDriver BurnDrvmd_ariel = { + "md_ariel", NULL, NULL, NULL, "1992", + "Disney's Ariel the Little Mermaid (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arielRomInfo, md_arielRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arnold Palmer Tournament Golf (Euro, USA) +static struct BurnRomInfo md_arnoldpRomDesc[] = { + { "mpr-12645.bin", 0x080000, 0x35b995ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arnoldp) +STD_ROM_FN(md_arnoldp) + +struct BurnDriver BurnDrvmd_arnoldp = { + "md_arnoldp", NULL, NULL, NULL, "1989", + "Arnold Palmer Tournament Golf (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arnoldpRomInfo, md_arnoldpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Naomichi Ozaki no Super Masters (Jpn) +static struct BurnRomInfo md_smastersRomDesc[] = { + { "naomichi ozaki no super masters (jpn).bin", 0x080000, 0x088ba825, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smasters) +STD_ROM_FN(md_smasters) + +struct BurnDriver BurnDrvmd_smasters = { + "md_smasters", "md_arnoldp", NULL, NULL, "1989", + "Naomichi Ozaki no Super Masters (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smastersRomInfo, md_smastersRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arrow Flash (World) +static struct BurnRomInfo md_arrowRomDesc[] = { + { "mpr-13396.bin", 0x080000, 0xd49f8444, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arrow) +STD_ROM_FN(md_arrow) + +struct BurnDriver BurnDrvmd_arrow = { + "md_arrow", NULL, NULL, NULL, "1990", + "Arrow Flash (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arrowRomInfo, md_arrowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Arrow Flash (World, Alt) +static struct BurnRomInfo md_arrow1RomDesc[] = { + { "arrow flash (world) (alt).bin", 0x080000, 0x4d89e66b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arrow1) +STD_ROM_FN(md_arrow1) + +struct BurnDriver BurnDrvmd_arrow1 = { + "md_arrow1", "md_arrow", NULL, NULL, "1990", + "Arrow Flash (World, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arrow1RomInfo, md_arrow1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Art of Fighting (Euro) +static struct BurnRomInfo md_aofRomDesc[] = { + { "art of fighting (euro).bin", 0x200000, 0x9970c422, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aof) +STD_ROM_FN(md_aof) + +struct BurnDriver BurnDrvmd_aof = { + "md_aof", NULL, NULL, NULL, "1994", + "Art of Fighting (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aofRomInfo, md_aofRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Art of Fighting (Prototype, 19940711) +static struct BurnRomInfo md_aofpRomDesc[] = { + { "art of fighting (prototype - jul 11, 1994).bin", 0x200000, 0x19ce567d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aofp) +STD_ROM_FN(md_aofp) + +struct BurnDriver BurnDrvmd_aofp = { + "md_aofp", "md_aof", NULL, NULL, "1994", + "Art of Fighting (Prototype, 19940711)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aofpRomInfo, md_aofpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Art of Fighting (USA) +static struct BurnRomInfo md_aofuRomDesc[] = { + { "art of fighting (usa).bin", 0x200000, 0xc9a57e07, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aofu) +STD_ROM_FN(md_aofu) + +struct BurnDriver BurnDrvmd_aofu = { + "md_aofu", "md_aof", NULL, NULL, "1994", + "Art of Fighting (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aofuRomInfo, md_aofuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ryuuko no Ken (Jpn) +static struct BurnRomInfo md_ryuukoRomDesc[] = { + { "ryuuko no ken (jpn).bin", 0x200000, 0x054cf5f6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ryuuko) +STD_ROM_FN(md_ryuuko) + +struct BurnDriver BurnDrvmd_ryuuko = { + "md_ryuuko", "md_aof", NULL, NULL, "1994", + "Ryuuko no Ken (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ryuukoRomInfo, md_ryuukoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Astérix and the Great Rescue (Euro) +static struct BurnRomInfo md_asterixRomDesc[] = { + { "mpr-15961+mpr-15962.bin", 0x200000, 0x4735fee6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_asterix) +STD_ROM_FN(md_asterix) + +struct BurnDriver BurnDrvmd_asterix = { + "md_asterix", NULL, NULL, NULL, "1993", + "Asterix and the Great Rescue (Euro)\0", NULL, "Sega", "Sega Megadrive", + L"Ast\u00e9rix and the Great Rescue (Euro)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_asterixRomInfo, md_asterixRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Astérix and the Great Rescue (USA) +static struct BurnRomInfo md_asterixuRomDesc[] = { + { "asterix and the great rescue (usa).bin", 0x200000, 0x7f112cd8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_asterixu) +STD_ROM_FN(md_asterixu) + +struct BurnDriver BurnDrvmd_asterixu = { + "md_asterixu", "md_asterix", NULL, NULL, "1994", + "Asterix and the Great Rescue (USA)\0", NULL, "Sega", "Sega Megadrive", + L"Ast\u00e9rix and the Great Rescue (USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_asterixuRomInfo, md_asterixuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Astérix and the Power of the Gods (Euro) +static struct BurnRomInfo md_asterpgRomDesc[] = { + { "mpr-17719.bin", 0x200000, 0x4ff1d83f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_asterpg) +STD_ROM_FN(md_asterpg) + +struct BurnDriver BurnDrvmd_asterpg = { + "md_asterpg", NULL, NULL, NULL, "1995", + "Asterix and the Power of the Gods (Euro)\0", NULL, "Sega", "Sega Megadrive", + L"Ast\u00e9rix and the Power of the Gods (Euro)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_asterpgRomInfo, md_asterpgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Astérix and the Power of the Gods (Euro, Prototype) +static struct BurnRomInfo md_asterpgpRomDesc[] = { + { "asterix and the power of the gods (euro) (beta).bin", 0x200000, 0x45c8b5b7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_asterpgp) +STD_ROM_FN(md_asterpgp) + +struct BurnDriver BurnDrvmd_asterpgp = { + "md_asterpgp", "md_asterpg", NULL, NULL, "1995", + "Asterix and the Power of the Gods (Euro, Prototype)\0", NULL, "Sega", "Sega Megadrive", + L"Ast\u00e9rix and the Power of the Gods (Euro, Prototype)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_asterpgpRomInfo, md_asterpgpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Atomic Robo-Kid (USA) +static struct BurnRomInfo md_atomroboRomDesc[] = { + { "atomic robo-kid (usa).bin", 0x080000, 0x7cd8169e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atomrobo) +STD_ROM_FN(md_atomrobo) + +struct BurnDriver BurnDrvmd_atomrobo = { + "md_atomrobo", NULL, NULL, NULL, "1990", + "Atomic Robo-Kid (USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_atomroboRomInfo, md_atomroboRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Atomic Robo-Kid (Jpn) +static struct BurnRomInfo md_atomrobojRomDesc[] = { + { "mpr-13483.bin", 0x080000, 0xe833067e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atomroboj) +STD_ROM_FN(md_atomroboj) + +struct BurnDriver BurnDrvmd_atomroboj = { + "md_atomroboj", "md_atomrobo", NULL, NULL, "1990", + "Atomic Robo-Kid (Jpn)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_atomrobojRomInfo, md_atomrobojRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Atomic Runner (Euro) +static struct BurnRomInfo md_atomrunRomDesc[] = { + { "mpr-15286.bin", 0x100000, 0xb3c05418, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atomrun) +STD_ROM_FN(md_atomrun) + +struct BurnDriver BurnDrvmd_atomrun = { + "md_atomrun", NULL, NULL, NULL, "1992", + "Atomic Runner (Euro)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_atomrunRomInfo, md_atomrunRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Atomic Runner (USA) +static struct BurnRomInfo md_atomrunuRomDesc[] = { + { "atomic runner (usa).bin", 0x100000, 0x0677c210, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atomrunu) +STD_ROM_FN(md_atomrunu) + +struct BurnDriver BurnDrvmd_atomrunu = { + "md_atomrunu", "md_atomrun", NULL, NULL, "1992", + "Atomic Runner (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_atomrunuRomInfo, md_atomrunuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chelnov (Jpn) +static struct BurnRomInfo md_chelnovRomDesc[] = { + { "chelnov (jpn).bin", 0x100000, 0xb2fe74d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chelnov) +STD_ROM_FN(md_chelnov) + +struct BurnDriver BurnDrvmd_chelnov = { + "md_chelnov", "md_atomrun", NULL, NULL, "1992", + "Chelnov (Jpn)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chelnovRomInfo, md_chelnovRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour (Euro) +static struct BurnRomInfo md_atptourRomDesc[] = { + { "atp tour (euro).bin", 0x200000, 0x1a3da8c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptour) +STD_ROM_FN(md_atptour) + +struct BurnDriver BurnDrvmd_atptour = { + "md_atptour", NULL, NULL, NULL, "1995", + "ATP Tour (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourRomInfo, md_atptourRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940802) +static struct BurnRomInfo md_atptourp4RomDesc[] = { + { "atp tour championship tennis (prototype - aug 02, 1994).bin", 0x200000, 0x686a9fa1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp4) +STD_ROM_FN(md_atptourp4) + +struct BurnDriver BurnDrvmd_atptourp4 = { + "md_atptourp4", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940802)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp4RomInfo, md_atptourp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940805) +static struct BurnRomInfo md_atptourp3RomDesc[] = { + { "atp tour championship tennis (prototype - aug 05, 1994).bin", 0x200000, 0xa1fef967, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp3) +STD_ROM_FN(md_atptourp3) + +struct BurnDriver BurnDrvmd_atptourp3 = { + "md_atptourp3", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940805)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp3RomInfo, md_atptourp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940808) +static struct BurnRomInfo md_atptourp2RomDesc[] = { + { "atp tour championship tennis (prototype - aug 08, 1994).bin", 0x200000, 0xe6398864, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp2) +STD_ROM_FN(md_atptourp2) + +struct BurnDriver BurnDrvmd_atptourp2 = { + "md_atptourp2", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940808)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp2RomInfo, md_atptourp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940719) +static struct BurnRomInfo md_atptourp6RomDesc[] = { + { "atp tour championship tennis (prototype - jul 19, 1994).bin", 0x200000, 0xcb927488, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp6) +STD_ROM_FN(md_atptourp6) + +struct BurnDriver BurnDrvmd_atptourp6 = { + "md_atptourp6", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940719)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp6RomInfo, md_atptourp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940723) +static struct BurnRomInfo md_atptourp5RomDesc[] = { + { "atp tour championship tennis (prototype - jul 23, 1994).bin", 0x200000, 0xa15d5051, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp5) +STD_ROM_FN(md_atptourp5) + +struct BurnDriver BurnDrvmd_atptourp5 = { + "md_atptourp5", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940723)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp5RomInfo, md_atptourp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940509) +static struct BurnRomInfo md_atptourp7RomDesc[] = { + { "atp tour championship tennis (prototype - may 09, 1994).bin", 0x200000, 0xb17a8dbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp7) +STD_ROM_FN(md_atptourp7) + +struct BurnDriver BurnDrvmd_atptourp7 = { + "md_atptourp7", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940509)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp7RomInfo, md_atptourp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (Prototype, 19940908) +static struct BurnRomInfo md_atptourp1RomDesc[] = { + { "atp tour championship tennis (prototype - sep 08, 1994).bin", 0x200000, 0xb83f4ca4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptourp1) +STD_ROM_FN(md_atptourp1) + +struct BurnDriver BurnDrvmd_atptourp1 = { + "md_atptourp1", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (Prototype, 19940908)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptourp1RomInfo, md_atptourp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ATP Tour Championship Tennis (USA) +static struct BurnRomInfo md_atptouruRomDesc[] = { + { "atp tour championship tennis (usa).bin", 0x200000, 0x8c822884, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_atptouru) +STD_ROM_FN(md_atptouru) + +struct BurnDriver BurnDrvmd_atptouru = { + "md_atptouru", "md_atptour", NULL, NULL, "1994", + "ATP Tour Championship Tennis (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_atptouruRomInfo, md_atptouruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Australian Rugby League (Euro) +static struct BurnRomInfo md_austrarlRomDesc[] = { + { "australian rugby league (euro).bin", 0x200000, 0xac5bc26a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_austrarl) +STD_ROM_FN(md_austrarl) + +struct BurnDriver BurnDrvmd_austrarl = { + "md_austrarl", NULL, NULL, NULL, "1994", + "Australian Rugby League (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_austrarlRomInfo, md_austrarlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Awesome Possum (USA) +static struct BurnRomInfo md_awepossmRomDesc[] = { + { "awesome possum (usa).bin", 0x200000, 0x1f07577f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_awepossm) +STD_ROM_FN(md_awepossm) + +struct BurnDriver BurnDrvmd_awepossm = { + "md_awepossm", NULL, NULL, NULL, "1993", + "Awesome Possum (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_awepossmRomInfo, md_awepossmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Awesome Possum (USA, Prototype) +static struct BurnRomInfo md_awepossmpRomDesc[] = { + { "awesome possum (usa) (beta).bin", 0x200000, 0x0158dc53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_awepossmp) +STD_ROM_FN(md_awepossmp) + +struct BurnDriver BurnDrvmd_awepossmp = { + "md_awepossmp", "md_awepossm", NULL, NULL, "1993", + "Awesome Possum (USA, Prototype)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_awepossmpRomInfo, md_awepossmpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aworg (Jpn, SegaNet) +static struct BurnRomInfo md_aworgRomDesc[] = { + { "aworg (jpn) (sn).bin", 0x040000, 0x069c27c1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aworg) +STD_ROM_FN(md_aworg) + +struct BurnDriver BurnDrvmd_aworg = { + "md_aworg", NULL, NULL, NULL, "1991", + "Aworg (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_aworgRomInfo, md_aworgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// AWS Pro Moves Soccer (USA) +static struct BurnRomInfo md_awsproRomDesc[] = { + { "aws pro moves soccer (usa).bin", 0x080000, 0x707017e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_awspro) +STD_ROM_FN(md_awspro) + +struct BurnDriver BurnDrvmd_awspro = { + "md_awspro", NULL, NULL, NULL, "1993", + "AWS Pro Moves Soccer (USA)\0", NULL, "ASCII Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_awsproRomInfo, md_awsproRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ayrton Senna's Super Monaco GP II (Euro, Jpn) +static struct BurnRomInfo md_smgp2RomDesc[] = { + { "mpr-14861.bin", 0x100000, 0x60af0f76, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgp2) +STD_ROM_FN(md_smgp2) + +struct BurnDriver BurnDrvmd_smgp2 = { + "md_smgp2", NULL, NULL, NULL, "1992", + "Ayrton Senna's Super Monaco GP II (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_smgp2RomInfo, md_smgp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ayrton Senna's Super Monaco GP II (USA) +static struct BurnRomInfo md_smgp2uRomDesc[] = { + { "ayrton senna's super monaco gp ii (usa).bin", 0x100000, 0xeac8ded6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgp2u) +STD_ROM_FN(md_smgp2u) + +struct BurnDriver BurnDrvmd_smgp2u = { + "md_smgp2u", "md_smgp2", NULL, NULL, "1992", + "Ayrton Senna's Super Monaco GP II (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_smgp2uRomInfo, md_smgp2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// B.O.B. (Euro, USA) +static struct BurnRomInfo md_bobRomDesc[] = { + { "b.o.b. (euro, usa).bin", 0x100000, 0xeaa2acb7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bob) +STD_ROM_FN(md_bob) + +struct BurnDriver BurnDrvmd_bob = { + "md_bob", NULL, NULL, NULL, "1993", + "B.O.B. (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bobRomInfo, md_bobRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// B.O.B. (USA, Prototype) +static struct BurnRomInfo md_bobpRomDesc[] = { + { "b.o.b. (usa) (beta).bin", 0x100000, 0xe3e8421e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bobp) +STD_ROM_FN(md_bobp) + +struct BurnDriver BurnDrvmd_bobp = { + "md_bobp", "md_bob", NULL, NULL, "1993", + "B.O.B. (USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bobpRomInfo, md_bobpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Space Funky B.O.B. (Jpn) +static struct BurnRomInfo md_spacefbRomDesc[] = { + { "space funky b.o.b. (jpn).bin", 0x100000, 0xe9310d3b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spacefb) +STD_ROM_FN(md_spacefb) + +struct BurnDriver BurnDrvmd_spacefb = { + "md_spacefb", "md_bob", NULL, NULL, "1993", + "Space Funky B.O.B. (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spacefbRomInfo, md_spacefbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Baby Boom (Prototype, 19940811) +static struct BurnRomInfo md_babyboomRomDesc[] = { + { "baby boom (prototype - aug 11, 1994).bin", 0x200000, 0xbd697054, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_babyboom) +STD_ROM_FN(md_babyboom) + +struct BurnDriver BurnDrvmd_babyboom = { + "md_babyboom", NULL, NULL, NULL, "199?", + "Baby Boom (Prototype, 19940811)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_babyboomRomInfo, md_babyboomRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Baby Boom (Prototype, 19940603) +static struct BurnRomInfo md_babyboom1RomDesc[] = { + { "baby boom (prototype - jun 03, 1994).bin", 0x200000, 0xc0d97f6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_babyboom1) +STD_ROM_FN(md_babyboom1) + +struct BurnDriver BurnDrvmd_babyboom1 = { + "md_babyboom1", "md_babyboom", NULL, NULL, "199?", + "Baby Boom (Prototype, 19940603)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_babyboom1RomInfo, md_babyboom1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Baby Boom (Prototype, 19940606) +static struct BurnRomInfo md_babyboom2RomDesc[] = { + { "baby boom (prototype - jun 06, 1994).bin", 0x200000, 0x6e0cf48d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_babyboom2) +STD_ROM_FN(md_babyboom2) + +struct BurnDriver BurnDrvmd_babyboom2 = { + "md_babyboom2", "md_babyboom", NULL, NULL, "199?", + "Baby Boom (Prototype, 19940606)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_babyboom2RomInfo, md_babyboom2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Baby's Day Out (USA, Prototype) +static struct BurnRomInfo md_babydRomDesc[] = { + { "baby's day out (usa) (prototype).bin", 0x100000, 0xb2e7cc49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_babyd) +STD_ROM_FN(md_babyd) + +struct BurnDriver BurnDrvmd_babyd = { + "md_babyd", NULL, NULL, NULL, "199?", + "Baby's Day Out (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_babydRomInfo, md_babydRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Baby's Day Out (USA, Prototype, Earlier) +static struct BurnRomInfo md_babydoRomDesc[] = { + { "baby's day out (usa) (prototype) (earlier).bin", 0x100000, 0x459b891c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_babydo) +STD_ROM_FN(md_babydo) + +struct BurnDriver BurnDrvmd_babydo = { + "md_babydo", "md_babyd", NULL, NULL, "199?", + "Baby's Day Out (USA, Prototype, Earlier)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_babydoRomInfo, md_babydoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Back to the Future Part III (Euro) +static struct BurnRomInfo md_backtof3RomDesc[] = { + { "mpr-14328.bin", 0x080000, 0x2737f92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_backtof3) +STD_ROM_FN(md_backtof3) + +struct BurnDriver BurnDrvmd_backtof3 = { + "md_backtof3", NULL, NULL, NULL, "1991", + "Back to the Future Part III (Euro)\0", NULL, "Imageworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_backtof3RomInfo, md_backtof3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Back to the Future Part III (USA) +static struct BurnRomInfo md_backtof3uRomDesc[] = { + { "back to the future part iii (usa).bin", 0x080000, 0x66a388c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_backtof3u) +STD_ROM_FN(md_backtof3u) + +struct BurnDriver BurnDrvmd_backtof3u = { + "md_backtof3u", "md_backtof3", NULL, NULL, "1991", + "Back to the Future Part III (USA)\0", NULL, "Arena Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_backtof3uRomInfo, md_backtof3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bahamut Senki (Jpn) +static struct BurnRomInfo md_bahamutsRomDesc[] = { + { "mpr-13677.bin", 0x080000, 0xb1e268da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bahamuts) +STD_ROM_FN(md_bahamuts) + +struct BurnDriver BurnDrvmd_bahamuts = { + "md_bahamuts", NULL, NULL, NULL, "1991", + "Bahamut Senki (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_bahamutsRomInfo, md_bahamutsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ball Jacks (Euro, Jpn) +static struct BurnRomInfo md_balljackRomDesc[] = { + { "ball jacks (euro, jpn).bin", 0x040000, 0xf5c3c54f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_balljack) +STD_ROM_FN(md_balljack) + +struct BurnDriver BurnDrvmd_balljack = { + "md_balljack", NULL, NULL, NULL, "1993", + "Ball Jacks (Euro, Jpn)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_balljackRomInfo, md_balljackRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ballz 3D (Euro, USA) +static struct BurnRomInfo md_ballz3dRomDesc[] = { + { "ballz 3d - fighting at its ballziest (euro, usa).bin", 0x200000, 0xb362b705, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ballz3d) +STD_ROM_FN(md_ballz3d) + +struct BurnDriver BurnDrvmd_ballz3d = { + "md_ballz3d", NULL, NULL, NULL, "1994", + "Ballz 3D (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ballz3dRomInfo, md_ballz3dRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barbie Super Model (USA) +static struct BurnRomInfo md_barbiesmRomDesc[] = { + { "barbie super model (usa).bin", 0x100000, 0x81c9662b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barbiesm) +STD_ROM_FN(md_barbiesm) + +struct BurnDriver BurnDrvmd_barbiesm = { + "md_barbiesm", NULL, NULL, NULL, "1992", + "Barbie Super Model (USA)\0", NULL, "Hi Tech Expressions", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barbiesmRomInfo, md_barbiesmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barbie Vacation Adventure (USA, Prototype) +static struct BurnRomInfo md_barbvacRomDesc[] = { + { "barbie vacation adventure (usa) (prototype).bin", 0x100000, 0x10e0ba69, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barbvac) +STD_ROM_FN(md_barbvac) + +struct BurnDriver BurnDrvmd_barbvac = { + "md_barbvac", NULL, NULL, NULL, "1994", + "Barbie Vacation Adventure (USA, Prototype)\0", NULL, "Hi Tech Expressions", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barbvacRomInfo, md_barbvacRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barkley Shut Up and Jam! (Euro, USA) +static struct BurnRomInfo md_barkleyRomDesc[] = { + { "barkley shut up and jam! (euro, usa).bin", 0x100000, 0x63fbf497, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barkley) +STD_ROM_FN(md_barkley) + +struct BurnDriver BurnDrvmd_barkley = { + "md_barkley", NULL, NULL, NULL, "1993", + "Barkley Shut Up and Jam! (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barkleyRomInfo, md_barkleyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barkley Shut Up and Jam! 2 (USA) +static struct BurnRomInfo md_barkley2RomDesc[] = { + { "barkley shut up and jam! 2 (usa).bin", 0x200000, 0x321bb6bd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barkley2) +STD_ROM_FN(md_barkley2) + +struct BurnDriver BurnDrvmd_barkley2 = { + "md_barkley2", NULL, NULL, NULL, "1995", + "Barkley Shut Up and Jam! 2 (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_barkley2RomInfo, md_barkley2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barkley Shut Up and Jam! 2 (USA, Prototype) +static struct BurnRomInfo md_barkley2pRomDesc[] = { + { "barkley shut up and jam! 2 (usa) (beta).bin", 0x200000, 0xde27357b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barkley2p) +STD_ROM_FN(md_barkley2p) + +struct BurnDriver BurnDrvmd_barkley2p = { + "md_barkley2p", "md_barkley2", NULL, NULL, "1995", + "Barkley Shut Up and Jam! 2 (USA, Prototype)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barkley2pRomInfo, md_barkley2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barney's Hide & Seek Game (USA) +static struct BurnRomInfo md_barneyRomDesc[] = { + { "barney's hide & seek game (usa).bin", 0x100000, 0x1efa9d53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barney) +STD_ROM_FN(md_barney) + +struct BurnDriver BurnDrvmd_barney = { + "md_barney", NULL, NULL, NULL, "1993", + "Barney's Hide & Seek Game (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barneyRomInfo, md_barneyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Barver Battle Saga - Tai Kong Zhan Shi (Chi) +static struct BurnRomInfo md_barverRomDesc[] = { + { "barver battle saga - tai kong zhan shi (chi) (unl).bin", 0x200000, 0xd37a37c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_barver) +STD_ROM_FN(md_barver) + +struct BurnDriver BurnDrvmd_barver = { + "md_barver", NULL, NULL, NULL, "199?", + "Barver Battle Saga - Tai Kong Zhan Shi (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_barverRomInfo, md_barverRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bass Masters Classic (USA) +static struct BurnRomInfo md_bassmaRomDesc[] = { + { "bass masters classic (usa).bin", 0x200000, 0xcf1ff00a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bassma) +STD_ROM_FN(md_bassma) + +struct BurnDriver BurnDrvmd_bassma = { + "md_bassma", NULL, NULL, NULL, "1995", + "Bass Masters Classic (USA)\0", NULL, "Black Pearl", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bassmaRomInfo, md_bassmaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bass Masters Classic - Pro Edition (USA) +static struct BurnRomInfo md_bassmpRomDesc[] = { + { "bass masters classic - pro edition (usa).bin", 0x200000, 0x9eddeb3d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bassmp) +STD_ROM_FN(md_bassmp) + +struct BurnDriver BurnDrvmd_bassmp = { + "md_bassmp", NULL, NULL, NULL, "1996", + "Bass Masters Classic - Pro Edition (USA)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bassmpRomInfo, md_bassmpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman (Jpn) +static struct BurnRomInfo md_batmanjRomDesc[] = { + { "batman (jpn).bin", 0x080000, 0xd7b4febf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batmanj) +STD_ROM_FN(md_batmanj) + +struct BurnDriver BurnDrvmd_batmanj = { + "md_batmanj", "md_batman", NULL, NULL, "1990", + "Batman (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanjRomInfo, md_batmanjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman (USA) +static struct BurnRomInfo md_batmanuRomDesc[] = { + { "batman (usa).bin", 0x080000, 0x017410ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batmanu) +STD_ROM_FN(md_batmanu) + +struct BurnDriver BurnDrvmd_batmanu = { + "md_batmanu", "md_batman", NULL, NULL, "1990", + "Batman (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanuRomInfo, md_batmanuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman - Revenge of the Joker (USA) +static struct BurnRomInfo md_batmanrjRomDesc[] = { + { "batman - revenge of the joker (usa).bin", 0x100000, 0xcaa044a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batmanrj) +STD_ROM_FN(md_batmanrj) + +struct BurnDriver BurnDrvmd_batmanrj = { + "md_batmanrj", NULL, NULL, NULL, "1992", + "Batman - Revenge of the Joker (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanrjRomInfo, md_batmanrjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman Forever (World) +static struct BurnRomInfo md_batmanfrRomDesc[] = { + { "batman forever (world).bin", 0x300000, 0x8b723d01, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batmanfr) +STD_ROM_FN(md_batmanfr) + +struct BurnDriver BurnDrvmd_batmanfr = { + "md_batmanfr", NULL, NULL, NULL, "1995", + "Batman Forever (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanfrRomInfo, md_batmanfrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Batman Returns (World) +static struct BurnRomInfo md_batmanrtRomDesc[] = { + { "mpr-14998.bin", 0x100000, 0x4a3225c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_batmanrt) +STD_ROM_FN(md_batmanrt) + +struct BurnDriver BurnDrvmd_batmanrt = { + "md_batmanrt", NULL, NULL, NULL, "1992", + "Batman Returns (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_batmanrtRomInfo, md_batmanrtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battle Golfer Yui (Jpn) +static struct BurnRomInfo md_battlyuiRomDesc[] = { + { "battle golfer yui (jpn).bin", 0x080000, 0x4aa03e4e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_battlyui) +STD_ROM_FN(md_battlyui) + +struct BurnDriver BurnDrvmd_battlyui = { + "md_battlyui", NULL, NULL, NULL, "1991", + "Battle Golfer Yui (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_battlyuiRomInfo, md_battlyuiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battle Mania Daiginjou (Jpn, Kor) +static struct BurnRomInfo md_btlmanidRomDesc[] = { + { "battle mania daiginjou (jpn, kor).bin", 0x100000, 0x312fa0f2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_btlmanid) +STD_ROM_FN(md_btlmanid) + +struct BurnDriver BurnDrvmd_btlmanid = { + "md_btlmanid", NULL, NULL, NULL, "1993", + "Battle Mania Daiginjou (Jpn, Kor)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_btlmanidRomInfo, md_btlmanidRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battle Squadron (Euro, USA) +static struct BurnRomInfo md_battlesqRomDesc[] = { + { "battle squadron (euro, usa).bin", 0x080000, 0x0feaa8bf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_battlesq) +STD_ROM_FN(md_battlesq) + +struct BurnDriver BurnDrvmd_battlesq = { + "md_battlesq", NULL, NULL, NULL, "1990", + "Battle Squadron (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_battlesqRomInfo, md_battlesqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battlemaster (USA) +static struct BurnRomInfo md_battlemsRomDesc[] = { + { "battlemaster (usa).bin", 0x080000, 0xfd2b35e3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_battlems) +STD_ROM_FN(md_battlems) + +struct BurnDriver BurnDrvmd_battlems = { + "md_battlems", NULL, NULL, NULL, "1991", + "Battlemaster (USA)\0", NULL, "Arena Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_battlemsRomInfo, md_battlemsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// BattleTech (USA) +static struct BurnRomInfo md_battletcRomDesc[] = { + { "battletech - a game of armored combat (usa).bin", 0x200000, 0x409e5d14, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_battletc) +STD_ROM_FN(md_battletc) + +struct BurnDriver BurnDrvmd_battletc = { + "md_battletc", NULL, NULL, NULL, "1994", + "BattleTech (USA)\0", NULL, "Extreme Entertainment Group", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_battletcRomInfo, md_battletcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battletoads & Double Dragon - The Ultimate Team (USA) +static struct BurnRomInfo md_btoadsddRomDesc[] = { + { "battletoads & double dragon (usa).bin", 0x100000, 0x8239dd17, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_btoadsdd) +STD_ROM_FN(md_btoadsdd) + +struct BurnDriver BurnDrvmd_btoadsdd = { + "md_btoadsdd", NULL, NULL, NULL, "1993", + "Battletoads & Double Dragon - The Ultimate Team (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_btoadsddRomInfo, md_btoadsddRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battletoads (World) +static struct BurnRomInfo md_btoadsRomDesc[] = { + { "battletoads (world).bin", 0x080000, 0xd10e103a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_btoads) +STD_ROM_FN(md_btoads) + +struct BurnDriver BurnDrvmd_btoads = { + "md_btoads", NULL, NULL, NULL, "1991", + "Battletoads (World)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_btoadsRomInfo, md_btoadsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beastball (Prototype) +static struct BurnRomInfo md_beastbalRomDesc[] = { + { "beast ball.bin", 0x0fb8e0, 0x6a176576, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beastbal) +STD_ROM_FN(md_beastbal) + +struct BurnDriver BurnDrvmd_beastbal = { + "md_beastbal", NULL, NULL, NULL, "199?", + "Beastball (Prototype)\0", NULL, "Spectrum Holobyte", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beastbalRomInfo, md_beastbalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beast Wrestler (USA) +static struct BurnRomInfo md_beastwRomDesc[] = { + { "beast wrestler (usa).bin", 0x100000, 0x0ca5bb64, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beastw) +STD_ROM_FN(md_beastw) + +struct BurnDriver BurnDrvmd_beastw = { + "md_beastw", NULL, NULL, NULL, "1991", + "Beast Wrestler (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beastwRomInfo, md_beastwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beast Warriors (Jpn) +static struct BurnRomInfo md_beastwjRomDesc[] = { + { "beast warriors (jpn).bin", 0x100000, 0x4646c694, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beastwj) +STD_ROM_FN(md_beastwj) + +struct BurnDriver BurnDrvmd_beastwj = { + "md_beastwj", "md_beastw", NULL, NULL, "1991", + "Beast Warriors (Jpn)\0", NULL, "Riot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beastwjRomInfo, md_beastwjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Beauty and the Beast - Belle's Quest (USA) +static struct BurnRomInfo md_beautyRomDesc[] = { + { "beauty and the beast - belle's quest (usa).bin", 0x100000, 0xbefb6fae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beauty) +STD_ROM_FN(md_beauty) + +struct BurnDriver BurnDrvmd_beauty = { + "md_beauty", NULL, NULL, NULL, "1993", + "Disney's Beauty and the Beast - Belle's Quest (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beautyRomInfo, md_beautyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's Beauty and the Beast - Roar of the Beast (USA) +static struct BurnRomInfo md_beautyrbRomDesc[] = { + { "beauty and the beast - roar of the beast (usa).bin", 0x100000, 0x13e7b519, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beautyrb) +STD_ROM_FN(md_beautyrb) + +struct BurnDriver BurnDrvmd_beautyrb = { + "md_beautyrb", NULL, NULL, NULL, "1993", + "Disney's Beauty and the Beast - Roar of the Beast (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beautyrbRomInfo, md_beautyrbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beavis and Butt-Head (Euro) +static struct BurnRomInfo md_beavisRomDesc[] = { + { "beavis and butt-head (euro).bin", 0x200000, 0xc7b6435e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beavis) +STD_ROM_FN(md_beavis) + +struct BurnDriver BurnDrvmd_beavis = { + "md_beavis", NULL, NULL, NULL, "1994", + "Beavis and Butt-Head (Euro)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beavisRomInfo, md_beavisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beavis and Butt-Head (USA) +static struct BurnRomInfo md_beavisuRomDesc[] = { + { "beavis and butt-head (usa).bin", 0x200000, 0xf5d7b948, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beavisu) +STD_ROM_FN(md_beavisu) + +struct BurnDriver BurnDrvmd_beavisu = { + "md_beavisu", "md_beavis", NULL, NULL, "1994", + "Beavis and Butt-Head (USA)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beavisuRomInfo, md_beavisuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beavis and Butt-Head (USA, Prototype) +static struct BurnRomInfo md_beavisupRomDesc[] = { + { "beavis and butt-head (usa) (beta).bin", 0x200000, 0x81ed5335, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beavisup) +STD_ROM_FN(md_beavisup) + +struct BurnDriver BurnDrvmd_beavisup = { + "md_beavisup", "md_beavis", NULL, NULL, "1994", + "Beavis and Butt-Head (USA, Prototype)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beavisupRomInfo, md_beavisupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (USA) +static struct BurnRomInfo md_berensRomDesc[] = { + { "berenstain bears' camping adventure, the (usa).bin", 0x100000, 0x1f86237b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berens) +STD_ROM_FN(md_berens) + +struct BurnDriver BurnDrvmd_berens = { + "md_berens", NULL, NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensRomInfo, md_berensRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940428) +static struct BurnRomInfo md_berensp19RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - apr 28, 1994).bin", 0x100000, 0xf222e946, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp19) +STD_ROM_FN(md_berensp19) + +struct BurnDriver BurnDrvmd_berensp19 = { + "md_berensp19", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940428)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp19RomInfo, md_berensp19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940429) +static struct BurnRomInfo md_berensp18RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - apr 29, 1994).bin", 0x100000, 0xe21493b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp18) +STD_ROM_FN(md_berensp18) + +struct BurnDriver BurnDrvmd_berensp18 = { + "md_berensp18", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940429)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp18RomInfo, md_berensp18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940801) +static struct BurnRomInfo md_berensp05RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - aug 01, 1994).bin", 0x100000, 0xb7cd465c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp05) +STD_ROM_FN(md_berensp05) + +struct BurnDriver BurnDrvmd_berensp05 = { + "md_berensp05", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940801)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp05RomInfo, md_berensp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940802) +static struct BurnRomInfo md_berensp04RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - aug 02, 1994).bin", 0x100000, 0x383ad564, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp04) +STD_ROM_FN(md_berensp04) + +struct BurnDriver BurnDrvmd_berensp04 = { + "md_berensp04", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940802)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp04RomInfo, md_berensp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940803) +static struct BurnRomInfo md_berensp03RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - aug 03, 1994).bin", 0x100000, 0x18f268a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp03) +STD_ROM_FN(md_berensp03) + +struct BurnDriver BurnDrvmd_berensp03 = { + "md_berensp03", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940803)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp03RomInfo, md_berensp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940805) +static struct BurnRomInfo md_berensp02RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - aug 05, 1994).bin", 0x100000, 0x24159b6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp02) +STD_ROM_FN(md_berensp02) + +struct BurnDriver BurnDrvmd_berensp02 = { + "md_berensp02", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940805)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp02RomInfo, md_berensp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940808) +static struct BurnRomInfo md_berensp01RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - aug 08, 1994).bin", 0x100000, 0x58b6b0fc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp01) +STD_ROM_FN(md_berensp01) + +struct BurnDriver BurnDrvmd_berensp01 = { + "md_berensp01", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940808)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp01RomInfo, md_berensp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940709) +static struct BurnRomInfo md_berensp08RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - jul 09, 1994).bin", 0x100000, 0xbf6aa405, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp08) +STD_ROM_FN(md_berensp08) + +struct BurnDriver BurnDrvmd_berensp08 = { + "md_berensp08", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940709)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp08RomInfo, md_berensp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940716) +static struct BurnRomInfo md_berensp07RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - jul 16, 1994).bin", 0x100000, 0xc84aad8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp07) +STD_ROM_FN(md_berensp07) + +struct BurnDriver BurnDrvmd_berensp07 = { + "md_berensp07", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940716)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp07RomInfo, md_berensp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940720) +static struct BurnRomInfo md_berensp06RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - jul 20, 1994).bin", 0x100000, 0xabee4c5e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp06) +STD_ROM_FN(md_berensp06) + +struct BurnDriver BurnDrvmd_berensp06 = { + "md_berensp06", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940720)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp06RomInfo, md_berensp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940602) +static struct BurnRomInfo md_berensp10RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - jun 02, 1994).bin", 0x100000, 0x83cf19e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp10) +STD_ROM_FN(md_berensp10) + +struct BurnDriver BurnDrvmd_berensp10 = { + "md_berensp10", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940602)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp10RomInfo, md_berensp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940610) +static struct BurnRomInfo md_berensp09RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - jun 10, 1994).bin", 0x100000, 0xa748e2cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp09) +STD_ROM_FN(md_berensp09) + +struct BurnDriver BurnDrvmd_berensp09 = { + "md_berensp09", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940610)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp09RomInfo, md_berensp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940323) +static struct BurnRomInfo md_berensp20RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - mar 23, 1994).bin", 0x100000, 0xbfbcd7cc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp20) +STD_ROM_FN(md_berensp20) + +struct BurnDriver BurnDrvmd_berensp20 = { + "md_berensp20", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940323)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp20RomInfo, md_berensp20RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940506) +static struct BurnRomInfo md_berensp17RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 06, 1994).bin", 0x100000, 0x713c14d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp17) +STD_ROM_FN(md_berensp17) + +struct BurnDriver BurnDrvmd_berensp17 = { + "md_berensp17", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940506)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp17RomInfo, md_berensp17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940511) +static struct BurnRomInfo md_berensp16RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 11, 1994).bin", 0x100000, 0xf7b81c6a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp16) +STD_ROM_FN(md_berensp16) + +struct BurnDriver BurnDrvmd_berensp16 = { + "md_berensp16", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940511)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp16RomInfo, md_berensp16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940517) +static struct BurnRomInfo md_berensp15RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 17, 1994).bin", 0x100000, 0xe1855ade, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp15) +STD_ROM_FN(md_berensp15) + +struct BurnDriver BurnDrvmd_berensp15 = { + "md_berensp15", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940517)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp15RomInfo, md_berensp15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940519) +static struct BurnRomInfo md_berensp14RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 19, 1994).bin", 0x100000, 0x07c9f71f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp14) +STD_ROM_FN(md_berensp14) + +struct BurnDriver BurnDrvmd_berensp14 = { + "md_berensp14", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940519)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp14RomInfo, md_berensp14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940523) +static struct BurnRomInfo md_berensp13RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 23, 1994).bin", 0x100000, 0x913887b7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp13) +STD_ROM_FN(md_berensp13) + +struct BurnDriver BurnDrvmd_berensp13 = { + "md_berensp13", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940523)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp13RomInfo, md_berensp13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940526) +static struct BurnRomInfo md_berensp12RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 26, 1994).bin", 0x100000, 0xd33c0fa4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp12) +STD_ROM_FN(md_berensp12) + +struct BurnDriver BurnDrvmd_berensp12 = { + "md_berensp12", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940526)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp12RomInfo, md_berensp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Berenstain Bears' Camping Adventure (Prototype, 19940530) +static struct BurnRomInfo md_berensp11RomDesc[] = { + { "berenstain bears' camping adventure, the (prototype - may 30, 1994).bin", 0x100000, 0x9c3bf429, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_berensp11) +STD_ROM_FN(md_berensp11) + +struct BurnDriver BurnDrvmd_berensp11 = { + "md_berensp11", "md_berens", NULL, NULL, "1994", + "The Berenstain Bears' Camping Adventure (Prototype, 19940530)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_berensp11RomInfo, md_berensp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Best of the Best - Championship Karate (USA) +static struct BurnRomInfo md_bestofRomDesc[] = { + { "best of the best - championship karate (usa).bin", 0x100000, 0xc3d6a5d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bestof) +STD_ROM_FN(md_bestof) + +struct BurnDriver BurnDrvmd_bestof = { + "md_bestof", NULL, NULL, NULL, "1993", + "Best of the Best - Championship Karate (USA)\0", NULL, "Electro Brain", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bestofRomInfo, md_bestofRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Best of the Best - Championship Karate (Euro, Prototype) +static struct BurnRomInfo md_bestofpRomDesc[] = { + { "best of the best - championship karate (euro) (beta).bin", 0x100000, 0xf842240b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bestofp) +STD_ROM_FN(md_bestofp) + +struct BurnDriver BurnDrvmd_bestofp = { + "md_bestofp", "md_bestof", NULL, NULL, "1993", + "Best of the Best - Championship Karate (Euro, Prototype)\0", NULL, "Electro Brain", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bestofpRomInfo, md_bestofpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Kick Boxing (Jpn, Kor) +static struct BurnRomInfo md_kickboxRomDesc[] = { + { "mpr-15333.bin", 0x100000, 0x9bdc230c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kickbox) +STD_ROM_FN(md_kickbox) + +struct BurnDriver BurnDrvmd_kickbox = { + "md_kickbox", "md_bestof", NULL, NULL, "1993", + "The Kick Boxing (Jpn, Kor)\0", NULL, "Micro World", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kickboxRomInfo, md_kickboxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beyond Zero Tolerance (USA, Prototype) +static struct BurnRomInfo md_beyondztRomDesc[] = { + { "beyond zero tolerance (usa) (prototype).bin", 0x200000, 0xc61ed2ed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beyondzt) +STD_ROM_FN(md_beyondzt) + +struct BurnDriver BurnDrvmd_beyondzt = { + "md_beyondzt", NULL, NULL, NULL, "1995", + "Beyond Zero Tolerance (USA, Prototype)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beyondztRomInfo, md_beyondztRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bible Adventures (USA) +static struct BurnRomInfo md_bibleadvRomDesc[] = { + { "bible adventures (usa) (unl).bin", 0x080000, 0x64446b77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bibleadv) +STD_ROM_FN(md_bibleadv) + +struct BurnDriver BurnDrvmd_bibleadv = { + "md_bibleadv", NULL, NULL, NULL, "1995", + "Bible Adventures (USA)\0", NULL, "Wisdom Tree", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bibleadvRomInfo, md_bibleadvRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bill Walsh College Football (Euro, USA) +static struct BurnRomInfo md_billwlshRomDesc[] = { + { "bwcf01.bin", 0x100000, 0x3ed83362, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_billwlsh) +STD_ROM_FN(md_billwlsh) + +struct BurnDriver BurnDrvmd_billwlsh = { + "md_billwlsh", NULL, NULL, NULL, "1993", + "Bill Walsh College Football (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_billwlshRomInfo, md_billwlshRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bill Walsh College Football 95 (USA) +static struct BurnRomInfo md_billwl95RomDesc[] = { + { "bill walsh college football 95 (usa).bin", 0x200000, 0xa582f45a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_billwl95) +STD_ROM_FN(md_billwl95) + +struct BurnDriver BurnDrvmd_billwl95 = { + "md_billwl95", NULL, NULL, NULL, "1994", + "Bill Walsh College Football 95 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_billwl95RomInfo, md_billwl95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bimini Run (USA) +static struct BurnRomInfo md_biminiRomDesc[] = { + { "bimini run (usa).bin", 0x080000, 0xd4dc5188, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bimini) +STD_ROM_FN(md_bimini) + +struct BurnDriver BurnDrvmd_bimini = { + "md_bimini", NULL, NULL, NULL, "1990", + "Bimini Run (USA)\0", NULL, "Nuvision Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_biminiRomInfo, md_biminiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bio Hazard Battle (Euro, USA) +static struct BurnRomInfo md_biohazrbRomDesc[] = { + { "mpr-15204.bin", 0x100000, 0x95b0ea2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_biohazrb) +STD_ROM_FN(md_biohazrb) + +struct BurnDriver BurnDrvmd_biohazrb = { + "md_biohazrb", NULL, NULL, NULL, "1992", + "Bio Hazard Battle (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_biohazrbRomInfo, md_biohazrbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bio Hazard Battle (USA, Prototype) +static struct BurnRomInfo md_biohazrbpRomDesc[] = { + { "bio hazard battle (usa) (beta).bin", 0x100000, 0xdd10dd1a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_biohazrbp) +STD_ROM_FN(md_biohazrbp) + +struct BurnDriver BurnDrvmd_biohazrbp = { + "md_biohazrbp", "md_biohazrb", NULL, NULL, "1992", + "Bio Hazard Battle (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_biohazrbpRomInfo, md_biohazrbpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crying - Aseimei Sensou (Jpn) +static struct BurnRomInfo md_cryingRomDesc[] = { + { "crying - aseimei sensou (jpn).bin", 0x100000, 0x4aba1d6a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crying) +STD_ROM_FN(md_crying) + +struct BurnDriver BurnDrvmd_crying = { + "md_crying", "md_biohazrb", NULL, NULL, "1992", + "Crying - Aseimei Sensou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cryingRomInfo, md_cryingRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blades of Vengeance (Euro, USA) +static struct BurnRomInfo md_bladevenRomDesc[] = { + { "blades of vengeance (euro, usa).bin", 0x100000, 0x74c65a49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bladeven) +STD_ROM_FN(md_bladeven) + +struct BurnDriver BurnDrvmd_bladeven = { + "md_bladeven", NULL, NULL, NULL, "1993", + "Blades of Vengeance (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bladevenRomInfo, md_bladevenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blaster Master 2 (USA) +static struct BurnRomInfo md_blastRomDesc[] = { + { "blaster master 2 (usa).bin", 0x100000, 0xc11e4ba1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_blast) +STD_ROM_FN(md_blast) + +struct BurnDriver BurnDrvmd_blast = { + "md_blast", NULL, NULL, NULL, "1993", + "Blaster Master 2 (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_blastRomInfo, md_blastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blaster Master 2 (USA, Prototype) +static struct BurnRomInfo md_blastpRomDesc[] = { + { "blaster master 2 (usa) (beta).bin", 0x100000, 0x08f78c70, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_blastp) +STD_ROM_FN(md_blastp) + +struct BurnDriver BurnDrvmd_blastp = { + "md_blastp", "md_blast", NULL, NULL, "1993", + "Blaster Master 2 (USA, Prototype)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_blastpRomInfo, md_blastpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blockbuster World Video Game Championship II (USA) +static struct BurnRomInfo md_blockbRomDesc[] = { + { "blockbuster world video game championship ii (usa).bin", 0x400000, 0x4385e366, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_blockb) +STD_ROM_FN(md_blockb) + +struct BurnDriver BurnDrvmd_blockb = { + "md_blockb", NULL, NULL, NULL, "1995", + "Blockbuster World Video Game Championship II (USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_blockbRomInfo, md_blockbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blockout (World) +static struct BurnRomInfo md_blockoRomDesc[] = { + { "bloc-u1_blo03+bloc-u2_blo03.bin,mpr-14247.bin", 0x020000, 0x5e2966f1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_blocko) +STD_ROM_FN(md_blocko) + +struct BurnDriver BurnDrvmd_blocko = { + "md_blocko", NULL, NULL, NULL, "1991", + "Blockout (World)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_blockoRomInfo, md_blockoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bloodshot ~ Battle Frenzy (Euro) +static struct BurnRomInfo md_bloodshtRomDesc[] = { + { "es210.bin", 0x200000, 0xf9f2bceb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bloodsht) +STD_ROM_FN(md_bloodsht) + +struct BurnDriver BurnDrvmd_bloodsht = { + "md_bloodsht", NULL, NULL, NULL, "1994", + "Bloodshot ~ Battle Frenzy (Euro)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bloodshtRomInfo, md_bloodshtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Blue Almanac (Jpn) +static struct BurnRomInfo md_bluealmaRomDesc[] = { + { "blue almanac (jpn).bin", 0x100000, 0x7222ebb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bluealma) +STD_ROM_FN(md_bluealma) + +struct BurnDriver BurnDrvmd_bluealma = { + "md_bluealma", NULL, NULL, NULL, "1991", + "Blue Almanac (Jpn)\0", NULL, "Kodansha", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_bluealmaRomInfo, md_bluealmaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Euro) +static struct BurnRomInfo md_bodycoRomDesc[] = { + { "body count (euro).bin", 0x100000, 0x3575a030, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodyco) +STD_ROM_FN(md_bodyco) + +struct BurnDriver BurnDrvmd_bodyco = { + "md_bodyco", NULL, NULL, NULL, "1994", + "Body Count (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycoRomInfo, md_bodycoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Euro, Prototype) +static struct BurnRomInfo md_bodycopRomDesc[] = { + { "body count (euro) (beta).bin", 0x100000, 0xb4ffb6ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop) +STD_ROM_FN(md_bodycop) + +struct BurnDriver BurnDrvmd_bodycop = { + "md_bodycop", "md_bodyco", NULL, NULL, "1994", + "Body Count (Euro, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycopRomInfo, md_bodycopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Prototype, 19940208) +static struct BurnRomInfo md_bodycop4RomDesc[] = { + { "body count (prototype - feb 08, 1994).bin", 0x0ff900, 0xc5fed897, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop4) +STD_ROM_FN(md_bodycop4) + +struct BurnDriver BurnDrvmd_bodycop4 = { + "md_bodycop4", "md_bodyco", NULL, NULL, "1994", + "Body Count (Prototype, 19940208)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycop4RomInfo, md_bodycop4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Prototype, 19940127) +static struct BurnRomInfo md_bodycop5RomDesc[] = { + { "body count (prototype - jan 27, 1994).bin", 0x100000, 0x66ca4e71, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop5) +STD_ROM_FN(md_bodycop5) + +struct BurnDriver BurnDrvmd_bodycop5 = { + "md_bodycop5", "md_bodyco", NULL, NULL, "1994", + "Body Count (Prototype, 19940127)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycop5RomInfo, md_bodycop5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Prototype, 19940303) +static struct BurnRomInfo md_bodycop3RomDesc[] = { + { "body count (prototype - mar 03, 1994).bin", 0x100000, 0x6abc6e77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop3) +STD_ROM_FN(md_bodycop3) + +struct BurnDriver BurnDrvmd_bodycop3 = { + "md_bodycop3", "md_bodyco", NULL, NULL, "1994", + "Body Count (Prototype, 19940303)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycop3RomInfo, md_bodycop3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Prototype, 19940308) +static struct BurnRomInfo md_bodycop2RomDesc[] = { + { "body count (prototype - mar 08, 1994).bin", 0x100000, 0x8965213f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop2) +STD_ROM_FN(md_bodycop2) + +struct BurnDriver BurnDrvmd_bodycop2 = { + "md_bodycop2", "md_bodyco", NULL, NULL, "1994", + "Body Count (Prototype, 19940308)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycop2RomInfo, md_bodycop2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Body Count (Prototype, 19940309) +static struct BurnRomInfo md_bodycop1RomDesc[] = { + { "body count (prototype - mar 09, 1994).bin", 0x100000, 0x649607d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bodycop1) +STD_ROM_FN(md_bodycop1) + +struct BurnDriver BurnDrvmd_bodycop1 = { + "md_bodycop1", "md_bodyco", NULL, NULL, "1994", + "Body Count (Prototype, 19940309)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bodycop1RomInfo, md_bodycop1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonanza Bros. (Euro, Jpn, Rev. A) +static struct BurnRomInfo md_bnzabrosRomDesc[] = { + { "mpr-13905a.bin", 0x080000, 0xc6aac589, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bnzabros) +STD_ROM_FN(md_bnzabros) + +struct BurnDriver BurnDrvmd_bnzabros = { + "md_bnzabros", NULL, NULL, NULL, "1991", + "Bonanza Bros. (Euro, Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bnzabrosRomInfo, md_bnzabrosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonanza Bros. (Euro, Jpn) +static struct BurnRomInfo md_bnzabros1RomDesc[] = { + { "bonanza bros. (euro, jpn).bin", 0x080000, 0xadf6476c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bnzabros1) +STD_ROM_FN(md_bnzabros1) + +struct BurnDriver BurnDrvmd_bnzabros1 = { + "md_bnzabros1", "md_bnzabros", NULL, NULL, "1991", + "Bonanza Bros. (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bnzabros1RomInfo, md_bnzabros1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonanza Bros. (USA, Kor) +static struct BurnRomInfo md_bnzabrosuRomDesc[] = { + { "bonanza bros. (usa, kor).bin", 0x080000, 0x20d1ad4c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bnzabrosu) +STD_ROM_FN(md_bnzabrosu) + +struct BurnDriver BurnDrvmd_bnzabrosu = { + "md_bnzabrosu", "md_bnzabros", NULL, NULL, "1991", + "Bonanza Bros. (USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bnzabrosuRomInfo, md_bnzabrosuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Euro, USA) +static struct BurnRomInfo md_bonkersRomDesc[] = { + { "bonkers (euro, usa).bin", 0x100000, 0xd1e66017, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkers) +STD_ROM_FN(md_bonkers) + +struct BurnDriver BurnDrvmd_bonkers = { + "md_bonkers", NULL, NULL, NULL, "1994", + "Bonkers (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersRomInfo, md_bonkersRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Prototype, 19940328) +static struct BurnRomInfo md_bonkersp5RomDesc[] = { + { "bonkers (prototype - mar 28, 1994).bin", 0x100000, 0xcd67c588, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkersp5) +STD_ROM_FN(md_bonkersp5) + +struct BurnDriver BurnDrvmd_bonkersp5 = { + "md_bonkersp5", "md_bonkers", NULL, NULL, "1994", + "Bonkers (Prototype, 19940328)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersp5RomInfo, md_bonkersp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Prototype, 19940503) +static struct BurnRomInfo md_bonkersp4RomDesc[] = { + { "bonkers (prototype - may 03, 1994).bin", 0x100000, 0xe4cd0d61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkersp4) +STD_ROM_FN(md_bonkersp4) + +struct BurnDriver BurnDrvmd_bonkersp4 = { + "md_bonkersp4", "md_bonkers", NULL, NULL, "1994", + "Bonkers (Prototype, 19940503)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersp4RomInfo, md_bonkersp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Prototype, 19941004) +static struct BurnRomInfo md_bonkersp3RomDesc[] = { + { "bonkers (prototype - oct 04, 1994).bin", 0x100000, 0x913cc834, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkersp3) +STD_ROM_FN(md_bonkersp3) + +struct BurnDriver BurnDrvmd_bonkersp3 = { + "md_bonkersp3", "md_bonkers", NULL, NULL, "1994", + "Bonkers (Prototype, 19941004)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersp3RomInfo, md_bonkersp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Prototype, 19941025) +static struct BurnRomInfo md_bonkersp2RomDesc[] = { + { "bonkers (prototype - oct 25, 1994).bin", 0x100000, 0x3e5edc4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkersp2) +STD_ROM_FN(md_bonkersp2) + +struct BurnDriver BurnDrvmd_bonkersp2 = { + "md_bonkersp2", "md_bonkers", NULL, NULL, "1994", + "Bonkers (Prototype, 19941025)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersp2RomInfo, md_bonkersp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bonkers (Prototype, 19941029) +static struct BurnRomInfo md_bonkersp1RomDesc[] = { + { "bonkers (prototype - oct 29, 1994).bin", 0x100000, 0x7b84793e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bonkersp1) +STD_ROM_FN(md_bonkersp1) + +struct BurnDriver BurnDrvmd_bonkersp1 = { + "md_bonkersp1", "md_bonkers", NULL, NULL, "1994", + "Bonkers (Prototype, 19941029)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bonkersp1RomInfo, md_bonkersp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Boogerman - A Pick and Flick Adventure (Euro) +static struct BurnRomInfo md_boogerRomDesc[] = { + { "boogerman - a pick and flick adventure (euro).bin", 0x300000, 0xdbc4340c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_booger) +STD_ROM_FN(md_booger) + +struct BurnDriver BurnDrvmd_booger = { + "md_booger", NULL, NULL, NULL, "1994", + "Boogerman - A Pick and Flick Adventure (Euro)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_boogerRomInfo, md_boogerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Boogerman - A Pick and Flick Adventure (USA) +static struct BurnRomInfo md_boogeruRomDesc[] = { + { "boogerman - a pick and flick adventure (usa).bin", 0x300000, 0x1a7a2bec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_boogeru) +STD_ROM_FN(md_boogeru) + +struct BurnDriver BurnDrvmd_boogeru = { + "md_boogeru", "md_booger", NULL, NULL, "1994", + "Boogerman - A Pick and Flick Adventure (USA)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_boogeruRomInfo, md_boogeruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Boxing Legends of the Ring (USA) +static struct BurnRomInfo md_boxlgndRomDesc[] = { + { "boxing legends of the ring (usa).bin", 0x100000, 0x00f225ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_boxlgnd) +STD_ROM_FN(md_boxlgnd) + +struct BurnDriver BurnDrvmd_boxlgnd = { + "md_boxlgnd", NULL, NULL, NULL, "1993", + "Boxing Legends of the Ring (USA)\0", NULL, "Electro Brain", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_boxlgndRomInfo, md_boxlgndRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chavez II (USA) +static struct BurnRomInfo md_chavezRomDesc[] = { + { "chavez ii (usa).bin", 0x100000, 0x5bc0dbb8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chavez) +STD_ROM_FN(md_chavez) + +struct BurnDriver BurnDrvmd_chavez = { + "md_chavez", "md_boxlgnd", NULL, NULL, "1993", + "Chavez II (USA)\0", NULL, "American Softworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chavezRomInfo, md_chavezRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bram Stoker's Dracula (Euro) +static struct BurnRomInfo md_draculaRomDesc[] = { + { "bram stoker's dracula (euro).bin", 0x100000, 0x9ba5a063, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dracula) +STD_ROM_FN(md_dracula) + +struct BurnDriver BurnDrvmd_dracula = { + "md_dracula", NULL, NULL, NULL, "1993", + "Bram Stoker's Dracula (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_draculaRomInfo, md_draculaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bram Stoker's Dracula (USA) +static struct BurnRomInfo md_draculauRomDesc[] = { + { "bram stoker's dracula (usa).bin", 0x100000, 0x077084a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_draculau) +STD_ROM_FN(md_draculau) + +struct BurnDriver BurnDrvmd_draculau = { + "md_draculau", "md_dracula", NULL, NULL, "1993", + "Bram Stoker's Dracula (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_draculauRomInfo, md_draculauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brett Hull Hockey '95 (USA) +static struct BurnRomInfo md_bretthulRomDesc[] = { + { "brett hull hockey '95 (usa).bin", 0x200000, 0xf7775a09, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bretthul) +STD_ROM_FN(md_bretthul) + +struct BurnDriver BurnDrvmd_bretthul = { + "md_bretthul", NULL, NULL, NULL, "1994", + "Brett Hull Hockey '95 (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_bretthulRomInfo, md_bretthulRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brian Lara Cricket (Euro, 199506) +static struct BurnRomInfo md_brianlarRomDesc[] = { + { "brian lara cricket (euro) (june 1995).bin", 0x100000, 0x408cf5c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brianlar) +STD_ROM_FN(md_brianlar) + +struct BurnDriver BurnDrvmd_brianlar = { + "md_brianlar", NULL, NULL, NULL, "1995", + "Brian Lara Cricket (Euro, 199506)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_brianlarRomInfo, md_brianlarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brian Lara Cricket (Euro, 199503) +static struct BurnRomInfo md_brianlar1RomDesc[] = { + { "brian lara cricket (euro) (march 1995).bin", 0x100000, 0x90f5c2b7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brianlar1) +STD_ROM_FN(md_brianlar1) + +struct BurnDriver BurnDrvmd_brianlar1 = { + "md_brianlar1", "md_brianlar", NULL, NULL, "1995", + "Brian Lara Cricket (Euro, 199503)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_brianlar1RomInfo, md_brianlar1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brian Lara Cricket 96 (Euro, 199604) +static struct BurnRomInfo md_brianl96RomDesc[] = { + { "brian lara cricket 96 (euro) (april 1996).bin", 0x100000, 0xfe52f7e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brianl96) +STD_ROM_FN(md_brianl96) + +struct BurnDriver BurnDrvmd_brianl96 = { + "md_brianl96", NULL, NULL, NULL, "1996", + "Brian Lara Cricket 96 (Euro, 199604)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CODE_MASTERS, GBF_MISC, 0, + MegadriveGetZipName, md_brianl96RomInfo, md_brianl96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brian Lara Cricket 96 (Euro, 199603) +static struct BurnRomInfo md_brianl96aRomDesc[] = { + { "mdbl_9844.bin", 0x100000, 0xfa3024af, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brianl96a) +STD_ROM_FN(md_brianl96a) + +struct BurnDriver BurnDrvmd_brianl96a = { + "md_brianl96a", "md_brianl96", NULL, NULL, "1996", + "Brian Lara Cricket 96 (Euro, 199603)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CODE_MASTERS, GBF_MISC, 0, + MegadriveGetZipName, md_brianl96aRomInfo, md_brianl96aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brutal - Paws of Fury (Euro) +static struct BurnRomInfo md_brutalRomDesc[] = { + { "brutal - paws of fury (euro).bin", 0x200000, 0x7e9a8d32, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brutal) +STD_ROM_FN(md_brutal) + +struct BurnDriver BurnDrvmd_brutal = { + "md_brutal", NULL, NULL, NULL, "1994", + "Brutal - Paws of Fury (Euro)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_brutalRomInfo, md_brutalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Brutal - Paws of Fury (USA) +static struct BurnRomInfo md_brutaluRomDesc[] = { + { "brutal - paws of fury (usa).bin", 0x200000, 0x98d502cd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_brutalu) +STD_ROM_FN(md_brutalu) + +struct BurnDriver BurnDrvmd_brutalu = { + "md_brutalu", "md_brutal", NULL, NULL, "1994", + "Brutal - Paws of Fury (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_brutaluRomInfo, md_brutaluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubba'n'Stix (Euro) +static struct BurnRomInfo md_bubbaRomDesc[] = { + { "bubba'n'stix (euro).bin", 0x100000, 0xb467432e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubba) +STD_ROM_FN(md_bubba) + +struct BurnDriver BurnDrvmd_bubba = { + "md_bubba", NULL, NULL, NULL, "1994", + "Bubba'n'Stix (Euro)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubbaRomInfo, md_bubbaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubba'n'Stix (Euro, Prototype) +static struct BurnRomInfo md_bubbabRomDesc[] = { + { "bubba'n'stix (euro) (beta).bin", 0x100000, 0xa8731cb4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubbab) +STD_ROM_FN(md_bubbab) + +struct BurnDriver BurnDrvmd_bubbab = { + "md_bubbab", "md_bubba", NULL, NULL, "1994", + "Bubba'n'Stix (Euro, Prototype)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubbabRomInfo, md_bubbabRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubba'n'Stix (USA) +static struct BurnRomInfo md_bubbauRomDesc[] = { + { "bubba'n'stix - a strategy adventure (usa).bin", 0x100000, 0xd45cb46f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubbau) +STD_ROM_FN(md_bubbau) + +struct BurnDriver BurnDrvmd_bubbau = { + "md_bubbau", "md_bubba", NULL, NULL, "1993", + "Bubba'n'Stix (USA)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubbauRomInfo, md_bubbauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubble and Squeak (Euro) +static struct BurnRomInfo md_bubbleRomDesc[] = { + { "bubble and squeak (euro).bin", 0x080000, 0x86151bf1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubble) +STD_ROM_FN(md_bubble) + +struct BurnDriver BurnDrvmd_bubble = { + "md_bubble", NULL, NULL, NULL, "1994", + "Bubble and Squeak (Euro)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubbleRomInfo, md_bubbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubble and Squeak (USA) +static struct BurnRomInfo md_bubbleuRomDesc[] = { + { "bubble and squeak (usa).bin", 0x080000, 0x28c4a006, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubbleu) +STD_ROM_FN(md_bubbleu) + +struct BurnDriver BurnDrvmd_bubbleu = { + "md_bubbleu", "md_bubble", NULL, NULL, "1994", + "Bubble and Squeak (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubbleuRomInfo, md_bubbleuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubsy in Claws Encounters of the Furred Kind (Euro, USA) +static struct BurnRomInfo md_bubsyRomDesc[] = { + { "bubsy in claws encounters of the furred kind (euro, usa).bin", 0x200000, 0x3e30d365, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubsy) +STD_ROM_FN(md_bubsy) + +struct BurnDriver BurnDrvmd_bubsy = { + "md_bubsy", NULL, NULL, NULL, "1993", + "Bubsy in Claws Encounters of the Furred Kind (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubsyRomInfo, md_bubsyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bubsy II (Euro, USA) +static struct BurnRomInfo md_bubsy2RomDesc[] = { + { "bu2sg.bin", 0x200000, 0xf8beff56, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bubsy2) +STD_ROM_FN(md_bubsy2) + +struct BurnDriver BurnDrvmd_bubsy2 = { + "md_bubsy2", NULL, NULL, NULL, "1994", + "Bubsy II (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bubsy2RomInfo, md_bubsy2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Buck Rogers - Countdown to Doomsday (Euro, USA) +static struct BurnRomInfo md_buckrogRomDesc[] = { + { "buc05.bin", 0x100000, 0x44e3bfff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_buckrog) +STD_ROM_FN(md_buckrog) + +struct BurnDriver BurnDrvmd_buckrog = { + "md_buckrog", NULL, NULL, NULL, "1991", + "Buck Rogers - Countdown to Doomsday (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_buckrogRomInfo, md_buckrogRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Budokan - The Martial Spirit (Euro) +static struct BurnRomInfo md_budokanRomDesc[] = { + { "budokan - the martial spirit (euro).bin", 0x080000, 0x97add5bd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_budokan) +STD_ROM_FN(md_budokan) + +struct BurnDriver BurnDrvmd_budokan = { + "md_budokan", NULL, NULL, NULL, "1990", + "Budokan - The Martial Spirit (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_budokanRomInfo, md_budokanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Budokan - The Martial Spirit (USA) +static struct BurnRomInfo md_budokanuRomDesc[] = { + { "budokan - the martial spirit (usa).bin", 0x080000, 0xacd9f5fc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_budokanu) +STD_ROM_FN(md_budokanu) + +struct BurnDriver BurnDrvmd_budokanu = { + "md_budokanu", "md_budokan", NULL, NULL, "1990", + "Budokan - The Martial Spirit (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_budokanuRomInfo, md_budokanuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bugs Bunny in Double Trouble (USA) +static struct BurnRomInfo md_bugsbunuRomDesc[] = { + { "bugs bunny in double trouble (usa).bin", 0x200000, 0x365305a2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bugsbunu) +STD_ROM_FN(md_bugsbunu) + +struct BurnDriver BurnDrvmd_bugsbunu = { + "md_bugsbunu", "md_bugsbun", NULL, NULL, "1996", + "Bugs Bunny in Double Trouble (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bugsbunuRomInfo, md_bugsbunuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bulls versus Blazers and the NBA Playoffs (Euro, USA) +static struct BurnRomInfo md_bullvsblRomDesc[] = { + { "bulls versus blazers and the nba playoffs (euro, usa).bin", 0x100000, 0xd4e4b4e8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bullvsbl) +STD_ROM_FN(md_bullvsbl) + +struct BurnDriver BurnDrvmd_bullvsbl = { + "md_bullvsbl", NULL, NULL, NULL, "1993", + "Bulls versus Blazers and the NBA Playoffs (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bullvsblRomInfo, md_bullvsblRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bulls Vs Lakers and the NBA Playoffs (Euro, USA) +static struct BurnRomInfo md_bullvslaRomDesc[] = { + { "bulls vs lakers and the nba playoffs (euro, usa).bin", 0x100000, 0xe56023a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bullvsla) +STD_ROM_FN(md_bullvsla) + +struct BurnDriver BurnDrvmd_bullvsla = { + "md_bullvsla", NULL, NULL, NULL, "1992", + "Bulls Vs Lakers and the NBA Playoffs (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bullvslaRomInfo, md_bullvslaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Burning Force (Euro) +static struct BurnRomInfo md_burnforcRomDesc[] = { + { "burning force (euro).bin", 0x080000, 0x776ff6ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_burnforc) +STD_ROM_FN(md_burnforc) + +struct BurnDriver BurnDrvmd_burnforc = { + "md_burnforc", NULL, NULL, NULL, "1991", + "Burning Force (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_burnforcRomInfo, md_burnforcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Burning Force (Jpn) +static struct BurnRomInfo md_burnforcjRomDesc[] = { + { "burning force (jpn).bin", 0x080000, 0x0c1deb47, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_burnforcj) +STD_ROM_FN(md_burnforcj) + +struct BurnDriver BurnDrvmd_burnforcj = { + "md_burnforcj", "md_burnforc", NULL, NULL, "1990", + "Burning Force (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_burnforcjRomInfo, md_burnforcjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Burning Force (USA) +static struct BurnRomInfo md_burnforcuRomDesc[] = { + { "burning force (usa).bin", 0x080000, 0xbdc8f02c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_burnforcu) +STD_ROM_FN(md_burnforcu) + +struct BurnDriver BurnDrvmd_burnforcu = { + "md_burnforcu", "md_burnforc", NULL, NULL, "1990", + "Burning Force (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_burnforcuRomInfo, md_burnforcuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cadash (USA, Asia, Kor) +static struct BurnRomInfo md_cadashRomDesc[] = { + { "cadash (usa, asia, kor).bin", 0x080000, 0x13bdf374, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cadash) +STD_ROM_FN(md_cadash) + +struct BurnDriver BurnDrvmd_cadash = { + "md_cadash", NULL, NULL, NULL, "1992", + "Cadash (USA, Asia, Kor)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cadashRomInfo, md_cadashRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Caesars Palace (USA) +static struct BurnRomInfo md_caesarsRomDesc[] = { + { "caesars palace (usa).bin", 0x080000, 0x8fdaa9bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_caesars) +STD_ROM_FN(md_caesars) + +struct BurnDriver BurnDrvmd_caesars = { + "md_caesars", NULL, NULL, NULL, "1993", + "Caesars Palace (USA)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_caesarsRomInfo, md_caesarsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cal Ripken Jr. Baseball (USA) +static struct BurnRomInfo md_calripRomDesc[] = { + { "cal ripken jr. baseball (usa).bin", 0x100000, 0x9b1c96c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_calrip) +STD_ROM_FN(md_calrip) + +struct BurnDriver BurnDrvmd_calrip = { + "md_calrip", NULL, NULL, NULL, "1992", + "Cal Ripken Jr. Baseball (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_calripRomInfo, md_calripRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cal.50 - Caliber Fifty (USA) +static struct BurnRomInfo md_cal50RomDesc[] = { + { "caliber .50 (usa).bin", 0x100000, 0x44f4fa05, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cal50) +STD_ROM_FN(md_cal50) + +struct BurnDriver BurnDrvmd_cal50 = { + "md_cal50", NULL, NULL, NULL, "1991", + "Cal.50 - Caliber Fifty (USA)\0", NULL, "Mentrix Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cal50RomInfo, md_cal50RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// California Games (Euro, USA) +static struct BurnRomInfo md_calgamesRomDesc[] = { + { "mpr-14372.bin", 0x080000, 0x43b1b672, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_calgames) +STD_ROM_FN(md_calgames) + +struct BurnDriver BurnDrvmd_calgames = { + "md_calgames", NULL, NULL, NULL, "1991", + "California Games (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_calgamesRomInfo, md_calgamesRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cannon Fodder (Euro) +static struct BurnRomInfo md_cannonRomDesc[] = { + { "cannon fodder (euro).bin", 0x180000, 0xad217654, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cannon) +STD_ROM_FN(md_cannon) + +struct BurnDriver BurnDrvmd_cannon = { + "md_cannon", NULL, NULL, NULL, "1994", + "Cannon Fodder (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cannonRomInfo, md_cannonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Captain America and the Avengers (Euro) +static struct BurnRomInfo md_captavenRomDesc[] = { + { "mpr-15499.bin", 0x100000, 0x43225612, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_captaven) +STD_ROM_FN(md_captaven) + +struct BurnDriver BurnDrvmd_captaven = { + "md_captaven", NULL, NULL, NULL, "1992", + "Captain America and the Avengers (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_captavenRomInfo, md_captavenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Captain America and the Avengers (USA) +static struct BurnRomInfo md_captavenuRomDesc[] = { + { "captain america and the avengers (usa).bin", 0x100000, 0xe0639ca2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_captavenu) +STD_ROM_FN(md_captavenu) + +struct BurnDriver BurnDrvmd_captavenu = { + "md_captavenu", "md_captaven", NULL, NULL, "1992", + "Captain America and the Avengers (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_captavenuRomInfo, md_captavenuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Captain America and the Avengers (USA, Prototype) +static struct BurnRomInfo md_captavenupRomDesc[] = { + { "captain america and the avengers (usa) (beta).bin", 0x100000, 0xbaac59c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_captavenup) +STD_ROM_FN(md_captavenup) + +struct BurnDriver BurnDrvmd_captavenup = { + "md_captavenup", "md_captaven", NULL, NULL, "1992", + "Captain America and the Avengers (USA, Prototype)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_captavenupRomInfo, md_captavenupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Captain Planet and the Planeteers (Euro) +static struct BurnRomInfo md_captplanRomDesc[] = { + { "captain planet and the planeteers (euro).bin", 0x080000, 0x7672efa5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_captplan) +STD_ROM_FN(md_captplan) + +struct BurnDriver BurnDrvmd_captplan = { + "md_captplan", NULL, NULL, NULL, "1993", + "Captain Planet and the Planeteers (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_captplanRomInfo, md_captplanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Captain Planet and the Planeteers (USA) +static struct BurnRomInfo md_captplanuRomDesc[] = { + { "captain planet and the planeteers (usa).bin", 0x080000, 0xbf2cbd3a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_captplanu) +STD_ROM_FN(md_captplanu) + +struct BurnDriver BurnDrvmd_captplanu = { + "md_captplanu", "md_captplan", NULL, NULL, "1993", + "Captain Planet and the Planeteers (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_captplanuRomInfo, md_captplanuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Castle of Illusion Starring Mickey Mouse (Euro, USA) +static struct BurnRomInfo md_castlillRomDesc[] = { + { "castle of illusion starring mickey mouse (euro, usa).bin", 0x080000, 0xba4e9fd0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_castlill) +STD_ROM_FN(md_castlill) + +struct BurnDriver BurnDrvmd_castlill = { + "md_castlill", NULL, NULL, NULL, "1990", + "Castle of Illusion Starring Mickey Mouse (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_castlillRomInfo, md_castlillRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Castle of Illusion - Fushigi no Oshiro Daibouken (Jpn) +static struct BurnRomInfo md_castlilljRomDesc[] = { + { "mpr-13498.bin", 0x080000, 0xce8333c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_castlillj) +STD_ROM_FN(md_castlillj) + +struct BurnDriver BurnDrvmd_castlillj = { + "md_castlillj", "md_castlill", NULL, NULL, "1990", + "Castle of Illusion - Fushigi no Oshiro Daibouken (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_castlilljRomInfo, md_castlilljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Castlevania - The New Generation (Euro) +static struct BurnRomInfo md_cvaniaRomDesc[] = { + { "castlevania - the new generation (euro).bin", 0x100000, 0x4dd4e4a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cvania) +STD_ROM_FN(md_cvania) + +struct BurnDriver BurnDrvmd_cvania = { + "md_cvania", NULL, NULL, NULL, "1994", + "Castlevania - The New Generation (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cvaniaRomInfo, md_cvaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Castlevania - The New Generation (Euro, Prototype) +static struct BurnRomInfo md_cvaniapRomDesc[] = { + { "castlevania - the new generation (euro) (beta).bin", 0x100000, 0x84cd103a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cvaniap) +STD_ROM_FN(md_cvaniap) + +struct BurnDriver BurnDrvmd_cvaniap = { + "md_cvaniap", "md_cvania", NULL, NULL, "1994", + "Castlevania - The New Generation (Euro, Prototype)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cvaniapRomInfo, md_cvaniapRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Castlevania - Bloodlines (USA) +static struct BurnRomInfo md_cvaniauRomDesc[] = { + { "castlevania - bloodlines (usa).bin", 0x100000, 0xfb1ea6df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cvaniau) +STD_ROM_FN(md_cvaniau) + +struct BurnDriver BurnDrvmd_cvaniau = { + "md_cvaniau", "md_cvania", NULL, NULL, "1994", + "Castlevania - Bloodlines (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cvaniauRomInfo, md_cvaniauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Akumajou Dracula - Vampire Killer (Jpn) +static struct BurnRomInfo md_akumajouRomDesc[] = { + { "akumajou dracula - vampire killer (jpn).bin", 0x100000, 0x91b57d2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_akumajou) +STD_ROM_FN(md_akumajou) + +struct BurnDriver BurnDrvmd_akumajou = { + "md_akumajou", "md_cvania", NULL, NULL, "1994", + "Akumajou Dracula - Vampire Killer (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_akumajouRomInfo, md_akumajouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Centurion - Defender of Rome (Euro, USA) +static struct BurnRomInfo md_centurRomDesc[] = { + { "centurion - defender of rome (euro, usa).bin", 0x0c0000, 0x21283b14, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_centur) +STD_ROM_FN(md_centur) + +struct BurnDriver BurnDrvmd_centur = { + "md_centur", NULL, NULL, NULL, "1991", + "Centurion - Defender of Rome (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_centurRomInfo, md_centurRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chakan (Euro, USA) +static struct BurnRomInfo md_chakanRomDesc[] = { + { "chakan (euro, usa).bin", 0x100000, 0x046a48de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chakan) +STD_ROM_FN(md_chakan) + +struct BurnDriver BurnDrvmd_chakan = { + "md_chakan", NULL, NULL, NULL, "1992", + "Chakan (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chakanRomInfo, md_chakanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Champions World Class Soccer (World) +static struct BurnRomInfo md_champwcsRomDesc[] = { + { "s357.bin", 0x100000, 0x883e33db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_champwcs) +STD_ROM_FN(md_champwcs) + +struct BurnDriver BurnDrvmd_champwcs = { + "md_champwcs", NULL, NULL, NULL, "1993", + "Champions World Class Soccer (World)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_champwcsRomInfo, md_champwcsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Championship Bowling (USA) +static struct BurnRomInfo md_champbowRomDesc[] = { + { "championship bowling (usa).bin", 0x080000, 0x1bf92520, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_champbow) +STD_ROM_FN(md_champbow) + +struct BurnDriver BurnDrvmd_champbow = { + "md_champbow", NULL, NULL, NULL, "1993", + "Championship Bowling (USA)\0", NULL, "Mentrix Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_champbowRomInfo, md_champbowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Boogie Woogie Bowling (Jpn) +static struct BurnRomInfo md_boogieRomDesc[] = { + { "boogie woogie bowling (jpn).bin", 0x080000, 0xccf52828, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_boogie) +STD_ROM_FN(md_boogie) + +struct BurnDriver BurnDrvmd_boogie = { + "md_boogie", "md_champbow", NULL, NULL, "1993", + "Boogie Woogie Bowling (Jpn)\0", NULL, "Visco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_boogieRomInfo, md_boogieRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Championship Pool (USA) +static struct BurnRomInfo md_champlRomDesc[] = { + { "championship pool (usa).bin", 0x100000, 0x253512cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_champl) +STD_ROM_FN(md_champl) + +struct BurnDriver BurnDrvmd_champl = { + "md_champl", NULL, NULL, NULL, "1993", + "Championship Pool (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_champlRomInfo, md_champlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Championship Pro-Am (USA) +static struct BurnRomInfo md_cproamRomDesc[] = { + { "championship pro-am (usa).bin", 0x040000, 0xb496de28, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cproam) +STD_ROM_FN(md_cproam) + +struct BurnDriver BurnDrvmd_cproam = { + "md_cproam", NULL, NULL, NULL, "1992", + "Championship Pro-Am (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cproamRomInfo, md_cproamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chao Ji Da Fu Weng (Chi) +static struct BurnRomInfo md_cjfuwengRomDesc[] = { + { "chao ji da fu weng (chi) (unl).bin", 0x100000, 0x2e2ea687, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cjfuweng) +STD_ROM_FN(md_cjfuweng) + +struct BurnDriver BurnDrvmd_cjfuweng = { + "md_cjfuweng", NULL, NULL, NULL, "199?", + "Chao Ji Da Fu Weng (Chi)\0", NULL, "Gametec?", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cjfuwengRomInfo, md_cjfuwengRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Chaos Engine (Euro) +static struct BurnRomInfo md_chaosengRomDesc[] = { + { "chaos engine, the (euro).bin", 0x180000, 0xbd9eecf4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chaoseng) +STD_ROM_FN(md_chaoseng) + +struct BurnDriver BurnDrvmd_chaoseng = { + "md_chaoseng", NULL, NULL, NULL, "1992", + "The Chaos Engine (Euro)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chaosengRomInfo, md_chaosengRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soldiers of Fortune (USA) +static struct BurnRomInfo md_soldfortRomDesc[] = { + { "soldiers of fortune (usa).bin", 0x180000, 0xa84d28a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soldfort) +STD_ROM_FN(md_soldfort) + +struct BurnDriver BurnDrvmd_soldfort = { + "md_soldfort", "md_chaoseng", NULL, NULL, "1993", + "Soldiers of Fortune (USA)\0", NULL, "Spectrum Holobyte", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soldfortRomInfo, md_soldfortRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Chaos Engine 2 (Euro, Prototype) +static struct BurnRomInfo md_chaosen2RomDesc[] = { + { "chaos engine 2, the (euro) (prototype).bin", 0x100000, 0x3fb045c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chaosen2) +STD_ROM_FN(md_chaosen2) + +struct BurnDriver BurnDrvmd_chaosen2 = { + "md_chaosen2", NULL, NULL, NULL, "199?", + "The Chaos Engine 2 (Euro, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chaosen2RomInfo, md_chaosen2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chase H.Q. II (USA) +static struct BurnRomInfo md_chasehq2RomDesc[] = { + { "chase h.q. ii (usa).bin", 0x080000, 0xf39e4bf2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chasehq2) +STD_ROM_FN(md_chasehq2) + +struct BurnDriver BurnDrvmd_chasehq2 = { + "md_chasehq2", NULL, NULL, NULL, "1992", + "Chase H.Q. II (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chasehq2RomInfo, md_chasehq2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super H.Q. (Jpn) +static struct BurnRomInfo md_superhqRomDesc[] = { + { "super h.q. (jpn).bin", 0x080000, 0xab2c52b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_superhq) +STD_ROM_FN(md_superhq) + +struct BurnDriver BurnDrvmd_superhq = { + "md_superhq", "md_chasehq2", NULL, NULL, "1992", + "Super H.Q. (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_superhqRomInfo, md_superhqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cheese Cat-Astrophe Starring Speedy Gonzales (Euro) +static struct BurnRomInfo md_cheeseRomDesc[] = { + { "cheese cat-astrophe starring speedy gonzales (euro).bin", 0x200000, 0xff634b28, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cheese) +STD_ROM_FN(md_cheese) + +struct BurnDriver BurnDrvmd_cheese = { + "md_cheese", NULL, NULL, NULL, "1995", + "Cheese Cat-Astrophe Starring Speedy Gonzales (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cheeseRomInfo, md_cheeseRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chester Cheetah - Too Cool to Fool (USA) +static struct BurnRomInfo md_chesterRomDesc[] = { + { "chester cheetah - too cool to fool (usa).bin", 0x100000, 0x250e3ec3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chester) +STD_ROM_FN(md_chester) + +struct BurnDriver BurnDrvmd_chester = { + "md_chester", NULL, NULL, NULL, "1992", + "Chester Cheetah - Too Cool to Fool (USA)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chesterRomInfo, md_chesterRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chester Cheetah - Wild Wild Quest (USA) +static struct BurnRomInfo md_chesterwRomDesc[] = { + { "chester cheetah - wild wild quest (usa).bin", 0x100000, 0xb97b735d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chesterw) +STD_ROM_FN(md_chesterw) + +struct BurnDriver BurnDrvmd_chesterw = { + "md_chesterw", NULL, NULL, NULL, "1992", + "Chester Cheetah - Wild Wild Quest (USA)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chesterwRomInfo, md_chesterwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chi Chi's Pro Challenge Golf (USA) +static struct BurnRomInfo md_chichiRomDesc[] = { + { "chi chi's pro challenge golf (usa).bin", 0x100000, 0x9c3973a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chichi) +STD_ROM_FN(md_chichi) + +struct BurnDriver BurnDrvmd_chichi = { + "md_chichi", NULL, NULL, NULL, "1993", + "Chi Chi's Pro Challenge Golf (USA)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chichiRomInfo, md_chichiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chibi Maruko-chan - Wakuwaku Shopping (Jpn) +static struct BurnRomInfo md_chibimarRomDesc[] = { + { "chibi maruko-chan - wakuwaku shopping (jpn).bin", 0x080000, 0x91a144b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chibimar) +STD_ROM_FN(md_chibimar) + +struct BurnDriver BurnDrvmd_chibimar = { + "md_chibimar", NULL, NULL, NULL, "1992", + "Chibi Maruko-chan - Wakuwaku Shopping (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chibimarRomInfo, md_chibimarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chiki Chiki Boys (Euro, USA) +static struct BurnRomInfo md_chikiRomDesc[] = { + { "chiki chiki boys (euro, usa).bin", 0x100000, 0x813a7d62, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chiki) +STD_ROM_FN(md_chiki) + +struct BurnDriver BurnDrvmd_chiki = { + "md_chiki", NULL, NULL, NULL, "1992", + "Chiki Chiki Boys (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chikiRomInfo, md_chikiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chiki Chiki Boys (Jpn, Kor) +static struct BurnRomInfo md_chikijRomDesc[] = { + { "chiki chiki boys (jpn, kor).bin", 0x100000, 0x06918c17, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chikij) +STD_ROM_FN(md_chikij) + +struct BurnDriver BurnDrvmd_chikij = { + "md_chikij", "md_chiki", NULL, NULL, "1992", + "Chiki Chiki Boys (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chikijRomInfo, md_chikijRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chinese Chess +static struct BurnRomInfo md_chinesecRomDesc[] = { + { "chinese chess (unl).bin", 0x080000, 0x475215a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chinesec) +STD_ROM_FN(md_chinesec) + +struct BurnDriver BurnDrvmd_chinesec = { + "md_chinesec", NULL, NULL, NULL, "199?", + "Chinese Chess\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chinesecRomInfo, md_chinesecRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock (Euro) +static struct BurnRomInfo md_chuckrckRomDesc[] = { + { "chuck rock (euro).bin", 0x100000, 0x7cd40bea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chuckrck) +STD_ROM_FN(md_chuckrck) + +struct BurnDriver BurnDrvmd_chuckrck = { + "md_chuckrck", NULL, NULL, NULL, "1992", + "Chuck Rock (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chuckrckRomInfo, md_chuckrckRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock (USA) +static struct BurnRomInfo md_chuckrckuRomDesc[] = { + { "chuck rock (usa).bin", 0x100000, 0xf8ac454a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chuckrcku) +STD_ROM_FN(md_chuckrcku) + +struct BurnDriver BurnDrvmd_chuckrcku = { + "md_chuckrcku", "md_chuckrck", NULL, NULL, "1992", + "Chuck Rock (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chuckrckuRomInfo, md_chuckrckuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock II - Son of Chuck (Euro) +static struct BurnRomInfo md_chukrck2RomDesc[] = { + { "chuck rock ii - son of chuck (euro).bin", 0x100000, 0x1ade9488, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chukrck2) +STD_ROM_FN(md_chukrck2) + +struct BurnDriver BurnDrvmd_chukrck2 = { + "md_chukrck2", NULL, NULL, NULL, "1993", + "Chuck Rock II - Son of Chuck (Euro)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chukrck2RomInfo, md_chukrck2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock II (Jpn) +static struct BurnRomInfo md_chukrck2jRomDesc[] = { + { "chuck rock ii (jpn).bin", 0x100000, 0xbfd24be8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chukrck2j) +STD_ROM_FN(md_chukrck2j) + +struct BurnDriver BurnDrvmd_chukrck2j = { + "md_chukrck2j", "md_chukrck2", NULL, NULL, "1994", + "Chuck Rock II (Jpn)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chukrck2jRomInfo, md_chukrck2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock II - Son of Chuck (USA) +static struct BurnRomInfo md_chukrck2uRomDesc[] = { + { "chuck rock ii - son of chuck (usa).bin", 0x100000, 0x408b1cdb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chukrck2u) +STD_ROM_FN(md_chukrck2u) + +struct BurnDriver BurnDrvmd_chukrck2u = { + "md_chukrck2u", "md_chukrck2", NULL, NULL, "1993", + "Chuck Rock II - Son of Chuck (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chukrck2uRomInfo, md_chukrck2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck Rock II - Son of Chuck (USA, Prototype) +static struct BurnRomInfo md_chukrck2upRomDesc[] = { + { "chuck rock ii - son of chuck (usa) (beta).bin", 0x100000, 0xd6a3b324, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chukrck2up) +STD_ROM_FN(md_chukrck2up) + +struct BurnDriver BurnDrvmd_chukrck2up = { + "md_chukrck2up", "md_chukrck2", NULL, NULL, "1993", + "Chuck Rock II - Son of Chuck (USA, Prototype)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chukrck2upRomInfo, md_chukrck2upRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chuck's Excellent Art Tool Animator (USA) +static struct BurnRomInfo md_chucksRomDesc[] = { + { "chuck's excellent art tool animator (usa) (unl).bin", 0x060000, 0x6360ee58, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chucks) +STD_ROM_FN(md_chucks) + +struct BurnDriver BurnDrvmd_chucks = { + "md_chucks", NULL, NULL, NULL, "199?", + "Chuck's Excellent Art Tool Animator (USA)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chucksRomInfo, md_chucksRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Classic Collection (Euro) +static struct BurnRomInfo md_classiccRomDesc[] = { + { "classic collection (euro).bin", 0x200000, 0x73f948b1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_classicc) +STD_ROM_FN(md_classicc) + +struct BurnDriver BurnDrvmd_classicc = { + "md_classicc", NULL, NULL, NULL, "1994", + "Classic Collection (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_classiccRomInfo, md_classiccRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Clay Fighter (Euro) +static struct BurnRomInfo md_clayRomDesc[] = { + { "mpr-17510.bin", 0x200000, 0x1aaf7707, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_clay) +STD_ROM_FN(md_clay) + +struct BurnDriver BurnDrvmd_clay = { + "md_clay", NULL, NULL, NULL, "1994", + "Clay Fighter (Euro)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_clayRomInfo, md_clayRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Clay Fighter (USA) +static struct BurnRomInfo md_clayuRomDesc[] = { + { "clay fighter (usa).bin", 0x200000, 0xb12c1bc1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_clayu) +STD_ROM_FN(md_clayu) + +struct BurnDriver BurnDrvmd_clayu = { + "md_clayu", "md_clay", NULL, NULL, "1994", + "Clay Fighter (USA)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_clayuRomInfo, md_clayuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cliffhanger (Euro) +static struct BurnRomInfo md_cliffRomDesc[] = { + { "cliffhanger (euro).bin", 0x100000, 0x35bff1fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cliff) +STD_ROM_FN(md_cliff) + +struct BurnDriver BurnDrvmd_cliff = { + "md_cliff", NULL, NULL, NULL, "1993", + "Cliffhanger (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cliffRomInfo, md_cliffRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cliffhanger (Prototype) +static struct BurnRomInfo md_cliffpRomDesc[] = { + { "cliffhanger (beta).bin", 0x100000, 0x628251fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cliffp) +STD_ROM_FN(md_cliffp) + +struct BurnDriver BurnDrvmd_cliffp = { + "md_cliffp", "md_cliff", NULL, NULL, "1993", + "Cliffhanger (Prototype)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cliffpRomInfo, md_cliffpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cliffhanger (USA) +static struct BurnRomInfo md_cliffuRomDesc[] = { + { "cliffhanger (usa).bin", 0x100000, 0x9cbf44d3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cliffu) +STD_ROM_FN(md_cliffu) + +struct BurnDriver BurnDrvmd_cliffu = { + "md_cliffu", "md_cliff", NULL, NULL, "1993", + "Cliffhanger (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cliffuRomInfo, md_cliffuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Clue (USA) +static struct BurnRomInfo md_clueRomDesc[] = { + { "clue (usa).bin", 0x080000, 0x7753a296, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_clue) +STD_ROM_FN(md_clue) + +struct BurnDriver BurnDrvmd_clue = { + "md_clue", NULL, NULL, NULL, "1992", + "Clue (USA)\0", NULL, "Parker Brothers", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_clueRomInfo, md_clueRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Coach K College Basketball (USA) +static struct BurnRomInfo md_coachkRomDesc[] = { + { "coach k college basketball (usa).bin", 0x200000, 0x67c309c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_coachk) +STD_ROM_FN(md_coachk) + +struct BurnDriver BurnDrvmd_coachk = { + "md_coachk", NULL, NULL, NULL, "1995", + "Coach K College Basketball (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_coachkRomInfo, md_coachkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football USA 96 (USA) +static struct BurnRomInfo md_colleg96RomDesc[] = { + { "college football usa 96 (usa).bin", 0x200000, 0xb9075385, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_colleg96) +STD_ROM_FN(md_colleg96) + +struct BurnDriver BurnDrvmd_colleg96 = { + "md_colleg96", NULL, NULL, NULL, "1995", + "College Football USA 96 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_colleg96RomInfo, md_colleg96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football USA 97 (USA) +static struct BurnRomInfo md_colleg97RomDesc[] = { + { "college football usa 97 (usa).bin", 0x200000, 0x2ebb90a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_colleg97) +STD_ROM_FN(md_colleg97) + +struct BurnDriver BurnDrvmd_colleg97 = { + "md_colleg97", NULL, NULL, NULL, "1996", + "College Football USA 97 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_colleg97RomInfo, md_colleg97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (USA) +static struct BurnRomInfo md_collncRomDesc[] = { + { "college football's national championship (usa).bin", 0x200000, 0x172c5dbb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnc) +STD_ROM_FN(md_collnc) + +struct BurnDriver BurnDrvmd_collnc = { + "md_collnc", NULL, NULL, NULL, "1994", + "College Football's National Championship (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncRomInfo, md_collncRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940413) +static struct BurnRomInfo md_collncp19RomDesc[] = { + { "college football's national championship (prototype - apr 13, 1994).bin", 0x200000, 0xd9772def, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp19) +STD_ROM_FN(md_collncp19) + +struct BurnDriver BurnDrvmd_collncp19 = { + "md_collncp19", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940413)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp19RomInfo, md_collncp19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940418) +static struct BurnRomInfo md_collncp18RomDesc[] = { + { "college football's national championship (prototype - apr 18, 1994).bin", 0x200000, 0xe0a1705f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp18) +STD_ROM_FN(md_collncp18) + +struct BurnDriver BurnDrvmd_collncp18 = { + "md_collncp18", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940418)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp18RomInfo, md_collncp18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940419) +static struct BurnRomInfo md_collncp17RomDesc[] = { + { "college football's national championship (prototype - apr 19, 1994).bin", 0x200000, 0xd5fe66c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp17) +STD_ROM_FN(md_collncp17) + +struct BurnDriver BurnDrvmd_collncp17 = { + "md_collncp17", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940419)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp17RomInfo, md_collncp17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940429) +static struct BurnRomInfo md_collncp16RomDesc[] = { + { "college football's national championship (prototype - apr 29, 1994).bin", 0x200000, 0x99da1973, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp16) +STD_ROM_FN(md_collncp16) + +struct BurnDriver BurnDrvmd_collncp16 = { + "md_collncp16", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940429)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp16RomInfo, md_collncp16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940601) +static struct BurnRomInfo md_collncp08RomDesc[] = { + { "college football's national championship (prototype - jun 01, 1994).bin", 0x200000, 0x994dbc8f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp08) +STD_ROM_FN(md_collncp08) + +struct BurnDriver BurnDrvmd_collncp08 = { + "md_collncp08", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940601)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp08RomInfo, md_collncp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940603) +static struct BurnRomInfo md_collncp07RomDesc[] = { + { "college football's national championship (prototype - jun 03, 1994).bin", 0x200000, 0x9ca29321, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp07) +STD_ROM_FN(md_collncp07) + +struct BurnDriver BurnDrvmd_collncp07 = { + "md_collncp07", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940603)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp07RomInfo, md_collncp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940607) +static struct BurnRomInfo md_collncp06RomDesc[] = { + { "college football's national championship (prototype - jun 07, 1994).bin", 0x200000, 0xb40b791e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp06) +STD_ROM_FN(md_collncp06) + +struct BurnDriver BurnDrvmd_collncp06 = { + "md_collncp06", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940607)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp06RomInfo, md_collncp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940608) +static struct BurnRomInfo md_collncp05RomDesc[] = { + { "college football's national championship (prototype - jun 08, 1994).bin", 0x200000, 0xd008debc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp05) +STD_ROM_FN(md_collncp05) + +struct BurnDriver BurnDrvmd_collncp05 = { + "md_collncp05", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940608)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp05RomInfo, md_collncp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940614) +static struct BurnRomInfo md_collncp04RomDesc[] = { + { "college football's national championship (prototype - jun 14, 1994).bin", 0x200000, 0xecef7de7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp04) +STD_ROM_FN(md_collncp04) + +struct BurnDriver BurnDrvmd_collncp04 = { + "md_collncp04", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940614)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp04RomInfo, md_collncp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940615) +static struct BurnRomInfo md_collncp03RomDesc[] = { + { "college football's national championship (prototype - jun 15, 1994).bin", 0x200000, 0xc7e5a998, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collncp03) +STD_ROM_FN(md_collncp03) + +struct BurnDriver BurnDrvmd_collncp03 = { + "md_collncp03", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940615)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collncp03RomInfo, md_collncp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940618) +static struct BurnRomInfo md_collnp02RomDesc[] = { + { "college football's national championship (prototype - jun 18, 1994).bin", 0x200000, 0x74988a9d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp02) +STD_ROM_FN(md_collnp02) + +struct BurnDriver BurnDrvmd_collnp02 = { + "md_collnp02", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940618)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp02RomInfo, md_collnp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940620) +static struct BurnRomInfo md_collnp01RomDesc[] = { + { "college football's national championship (prototype - jun 20, 1994).bin", 0x200000, 0x898c17fa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp01) +STD_ROM_FN(md_collnp01) + +struct BurnDriver BurnDrvmd_collnp01 = { + "md_collnp01", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940620)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp01RomInfo, md_collnp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940503) +static struct BurnRomInfo md_collnp15RomDesc[] = { + { "college football's national championship (prototype - may 03, 1994).bin", 0x200000, 0xdb1a3f66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp15) +STD_ROM_FN(md_collnp15) + +struct BurnDriver BurnDrvmd_collnp15 = { + "md_collnp15", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940503)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp15RomInfo, md_collnp15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940506) +static struct BurnRomInfo md_collnp14RomDesc[] = { + { "college football's national championship (prototype - may 06, 1994).bin", 0x200000, 0x0a538e75, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp14) +STD_ROM_FN(md_collnp14) + +struct BurnDriver BurnDrvmd_collnp14 = { + "md_collnp14", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940506)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp14RomInfo, md_collnp14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940511-A) +static struct BurnRomInfo md_collnp13RomDesc[] = { + { "college football's national championship (prototype - may 11, 1994 - a).bin", 0x200000, 0xce65b294, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp13) +STD_ROM_FN(md_collnp13) + +struct BurnDriver BurnDrvmd_collnp13 = { + "md_collnp13", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940511-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp13RomInfo, md_collnp13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940517-A) +static struct BurnRomInfo md_collnp12RomDesc[] = { + { "college football's national championship (prototype - may 17, 1994 - a).bin", 0x200000, 0x8cfd4c86, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp12) +STD_ROM_FN(md_collnp12) + +struct BurnDriver BurnDrvmd_collnp12 = { + "md_collnp12", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940517-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp12RomInfo, md_collnp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940520) +static struct BurnRomInfo md_collnp11RomDesc[] = { + { "college football's national championship (prototype - may 20, 1994).bin", 0x200000, 0xf285385e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp11) +STD_ROM_FN(md_collnp11) + +struct BurnDriver BurnDrvmd_collnp11 = { + "md_collnp11", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940520)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp11RomInfo, md_collnp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940525) +static struct BurnRomInfo md_collnp10RomDesc[] = { + { "college football's national championship (prototype - may 25, 1994).bin", 0x200000, 0x482e334a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp10) +STD_ROM_FN(md_collnp10) + +struct BurnDriver BurnDrvmd_collnp10 = { + "md_collnp10", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940525)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp10RomInfo, md_collnp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship (Prototype, 19940531) +static struct BurnRomInfo md_collnp09RomDesc[] = { + { "college football's national championship (prototype - may 31, 1994).bin", 0x200000, 0xc6766745, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnp09) +STD_ROM_FN(md_collnp09) + +struct BurnDriver BurnDrvmd_collnp09 = { + "md_collnp09", "md_collnc", NULL, NULL, "1994", + "College Football's National Championship (Prototype, 19940531)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnp09RomInfo, md_collnp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Football's National Championship II (USA) +static struct BurnRomInfo md_collnc2RomDesc[] = { + { "college football's national championship ii (usa).bin", 0x200000, 0x65b64413, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collnc2) +STD_ROM_FN(md_collnc2) + +struct BurnDriver BurnDrvmd_collnc2 = { + "md_collnc2", NULL, NULL, NULL, "1995", + "College Football's National Championship II (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_collnc2RomInfo, md_collnc2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// College Slam (USA) +static struct BurnRomInfo md_collslamRomDesc[] = { + { "college slam (usa).bin", 0x400000, 0x96a42431, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_collslam) +STD_ROM_FN(md_collslam) + +struct BurnDriver BurnDrvmd_collslam = { + "md_collslam", NULL, NULL, NULL, "1996", + "College Slam (USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_C_SLAM, GBF_MISC, 0, + MegadriveGetZipName, md_collslamRomInfo, md_collslamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Columns (World, v1.1) +static struct BurnRomInfo md_columnsRomDesc[] = { + { "columns (world) (v1.1).bin", 0x020000, 0xd783c244, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_columns) +STD_ROM_FN(md_columns) + +struct BurnDriver BurnDrvmd_columns = { + "md_columns", NULL, NULL, NULL, "1990", + "Columns (World, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_columnsRomInfo, md_columnsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Columns (World) +static struct BurnRomInfo md_columns1RomDesc[] = { + { "mpr-13193.bin", 0x020000, 0x03163d7a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_columns1) +STD_ROM_FN(md_columns1) + +struct BurnDriver BurnDrvmd_columns1 = { + "md_columns1", "md_columns", NULL, NULL, "1990", + "Columns (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_columns1RomInfo, md_columns1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Columns III - Revenge of Columns (USA) +static struct BurnRomInfo md_columns3RomDesc[] = { + { "columns iii - revenge of columns (usa).bin", 0x080000, 0xdc678f6d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_columns3) +STD_ROM_FN(md_columns3) + +struct BurnDriver BurnDrvmd_columns3 = { + "md_columns3", NULL, NULL, NULL, "1993", + "Columns III - Revenge of Columns (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_columns3RomInfo, md_columns3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Columns III - Taiketsu! Columns World (Jpn, Kor) +static struct BurnRomInfo md_columns3jRomDesc[] = { + { "columns iii - taiketsu! columns world (jpn, kor).bin", 0x080000, 0xcd07462f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_columns3j) +STD_ROM_FN(md_columns3j) + +struct BurnDriver BurnDrvmd_columns3j = { + "md_columns3j", "md_columns3", NULL, NULL, "1993", + "Columns III - Taiketsu! Columns World (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_columns3jRomInfo, md_columns3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Combat Aces (Prototype) +static struct BurnRomInfo md_combatRomDesc[] = { + { "combat aces (beta).bin", 0x080000, 0x84560d5a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_combat) +STD_ROM_FN(md_combat) + +struct BurnDriver BurnDrvmd_combat = { + "md_combat", NULL, NULL, NULL, "199?", + "Combat Aces (Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_combatRomInfo, md_combatRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Combat Cars (Euro, USA) +static struct BurnRomInfo md_combatcaRomDesc[] = { + { "combat cars (euro, usa).bin", 0x100000, 0xe439b101, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_combatca) +STD_ROM_FN(md_combatca) + +struct BurnDriver BurnDrvmd_combatca = { + "md_combatca", NULL, NULL, NULL, "1994", + "Combat Cars (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_combatcaRomInfo, md_combatcaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Euro) +static struct BurnRomInfo md_comixRomDesc[] = { + { "mpr-18301.bin", 0x200000, 0x1318e923, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comix) +STD_ROM_FN(md_comix) + +struct BurnDriver BurnDrvmd_comix = { + "md_comix", NULL, NULL, NULL, "1995", + "Comix Zone (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixRomInfo, md_comixRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Euro, Prototype, 19950628) +static struct BurnRomInfo md_comixpRomDesc[] = { + { "comix zone (euro) (prototype - jun 28, 1995).bin", 0x200000, 0x939efd4c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixp) +STD_ROM_FN(md_comixp) + +struct BurnDriver BurnDrvmd_comixp = { + "md_comixp", "md_comix", NULL, NULL, "1995", + "Comix Zone (Euro, Prototype, 19950628)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixpRomInfo, md_comixpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Jpn) +static struct BurnRomInfo md_comixjRomDesc[] = { + { "comix zone (jpn).bin", 0x200000, 0x7a6027b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixj) +STD_ROM_FN(md_comixj) + +struct BurnDriver BurnDrvmd_comixj = { + "md_comixj", "md_comix", NULL, NULL, "1995", + "Comix Zone (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixjRomInfo, md_comixjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950712) +static struct BurnRomInfo md_comixup01RomDesc[] = { + { "comix zone (prototype - jul 12, 1995).bin", 0x200000, 0xe28c89c1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup01) +STD_ROM_FN(md_comixup01) + +struct BurnDriver BurnDrvmd_comixup01 = { + "md_comixup01", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950712)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup01RomInfo, md_comixup01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950601-B) +static struct BurnRomInfo md_comixup08RomDesc[] = { + { "comix zone (prototype - jun 01, 1995 - b).bin", 0x200000, 0xbbe03cb6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup08) +STD_ROM_FN(md_comixup08) + +struct BurnDriver BurnDrvmd_comixup08 = { + "md_comixup08", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950601-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup08RomInfo, md_comixup08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950601-C) +static struct BurnRomInfo md_comixup07RomDesc[] = { + { "comix zone (prototype - jun 01, 1995 - c).bin", 0x200000, 0x413b9a94, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup07) +STD_ROM_FN(md_comixup07) + +struct BurnDriver BurnDrvmd_comixup07 = { + "md_comixup07", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950601-C)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup07RomInfo, md_comixup07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950601-D) +static struct BurnRomInfo md_comixup06RomDesc[] = { + { "comix zone (prototype - jun 01, 1995 - d).bin", 0x200000, 0x9ae93c9d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup06) +STD_ROM_FN(md_comixup06) + +struct BurnDriver BurnDrvmd_comixup06 = { + "md_comixup06", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950601-D)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup06RomInfo, md_comixup06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950601) +static struct BurnRomInfo md_comixup05RomDesc[] = { + { "comix zone (prototype - jun 01, 1995).bin", 0x200000, 0xba506835, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup05) +STD_ROM_FN(md_comixup05) + +struct BurnDriver BurnDrvmd_comixup05 = { + "md_comixup05", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950601)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup05RomInfo, md_comixup05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950602-B) +static struct BurnRomInfo md_comixup04RomDesc[] = { + { "comix zone (prototype - jun 02, 1995 - b).bin", 0x200000, 0xb5f0dae5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup04) +STD_ROM_FN(md_comixup04) + +struct BurnDriver BurnDrvmd_comixup04 = { + "md_comixup04", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950602-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup04RomInfo, md_comixup04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950602) +static struct BurnRomInfo md_comixup03RomDesc[] = { + { "comix zone (prototype - jun 02, 1995).bin", 0x200000, 0x1a4abcf3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup03) +STD_ROM_FN(md_comixup03) + +struct BurnDriver BurnDrvmd_comixup03 = { + "md_comixup03", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950602)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup03RomInfo, md_comixup03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950603) +static struct BurnRomInfo md_comixup02RomDesc[] = { + { "comix zone (prototype - jun 03, 1995).bin", 0x200000, 0xaff32614, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup02) +STD_ROM_FN(md_comixup02) + +struct BurnDriver BurnDrvmd_comixup02 = { + "md_comixup02", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950603)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup02RomInfo, md_comixup02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950526) +static struct BurnRomInfo md_comixup10RomDesc[] = { + { "comix zone (prototype - may 26, 1995).bin", 0x200000, 0x36029a1f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup10) +STD_ROM_FN(md_comixup10) + +struct BurnDriver BurnDrvmd_comixup10 = { + "md_comixup10", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950526)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup10RomInfo, md_comixup10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Prototype, 19950530) +static struct BurnRomInfo md_comixup09RomDesc[] = { + { "comix zone (prototype - may 30, 1995).bin", 0x200000, 0xa72eca2c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup09) +STD_ROM_FN(md_comixup09) + +struct BurnDriver BurnDrvmd_comixup09 = { + "md_comixup09", "md_comix", NULL, NULL, "1995", + "Comix Zone (Prototype, 19950530)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixup09RomInfo, md_comixup09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Kor, Prototype, 19950609) +static struct BurnRomInfo md_comixkpRomDesc[] = { + { "comix zone (kor) (prototype - jun 09, 1995).bin", 0x200000, 0xe45a15f4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixkp) +STD_ROM_FN(md_comixkp) + +struct BurnDriver BurnDrvmd_comixkp = { + "md_comixkp", "md_comix", NULL, NULL, "1995", + "Comix Zone (Kor, Prototype, 19950609)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixkpRomInfo, md_comixkpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (Sega Channel, Prototype, 19950612) +static struct BurnRomInfo md_comixscRomDesc[] = { + { "comix zone (sega channel) (prototype - jun 12, 1995).bin", 0x200000, 0xc77db9e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixsc) +STD_ROM_FN(md_comixsc) + +struct BurnDriver BurnDrvmd_comixsc = { + "md_comixsc", "md_comix", NULL, NULL, "1995", + "Comix Zone (Sega Channel, Prototype, 19950612)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixscRomInfo, md_comixscRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (USA) +static struct BurnRomInfo md_comixuRomDesc[] = { + { "comix zone (usa).bin", 0x200000, 0x17da0354, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixu) +STD_ROM_FN(md_comixu) + +struct BurnDriver BurnDrvmd_comixu = { + "md_comixu", "md_comix", NULL, NULL, "1995", + "Comix Zone (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixuRomInfo, md_comixuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Comix Zone (USA, Prototype) +static struct BurnRomInfo md_comixupRomDesc[] = { + { "comix zone (usa) (beta).bin", 0x200000, 0x2efcb6ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comixup) +STD_ROM_FN(md_comixup) + +struct BurnDriver BurnDrvmd_comixup = { + "md_comixup", "md_comix", NULL, NULL, "1995", + "Comix Zone (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comixupRomInfo, md_comixupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Congo (Prototype) +static struct BurnRomInfo md_congoRomDesc[] = { + { "congo (unknown) (prototype).bin", 0x0f7d36, 0x13746716, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_congo) +STD_ROM_FN(md_congo) + +struct BurnDriver BurnDrvmd_congo = { + "md_congo", NULL, NULL, NULL, "199?", + "Congo (Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_congoRomInfo, md_congoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cool Spot (Euro) +static struct BurnRomInfo md_coolspRomDesc[] = { + { "mpr-15477.bin", 0x100000, 0x5f09fa41, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_coolsp) +STD_ROM_FN(md_coolsp) + +struct BurnDriver BurnDrvmd_coolsp = { + "md_coolsp", NULL, NULL, NULL, "1994", + "Cool Spot (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_coolspRomInfo, md_coolspRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cool Spot (Jpn, Kor) +static struct BurnRomInfo md_coolspjRomDesc[] = { + { "cool spot (jpn, kor).bin", 0x100000, 0xe869efb1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_coolspj) +STD_ROM_FN(md_coolspj) + +struct BurnDriver BurnDrvmd_coolspj = { + "md_coolspj", "md_coolsp", NULL, NULL, "1994", + "Cool Spot (Jpn, Kor)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_coolspjRomInfo, md_coolspjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cool Spot (USA) +static struct BurnRomInfo md_coolspuRomDesc[] = { + { "cool spot (usa).bin", 0x100000, 0xf024c1a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_coolspu) +STD_ROM_FN(md_coolspu) + +struct BurnDriver BurnDrvmd_coolspu = { + "md_coolspu", "md_coolsp", NULL, NULL, "1994", + "Cool Spot (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_coolspuRomInfo, md_coolspuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cool Spot (USA, Prototype) +static struct BurnRomInfo md_coolspupRomDesc[] = { + { "cool spot (usa) (beta).bin", 0x100000, 0x0ebaa4a8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_coolspup) +STD_ROM_FN(md_coolspup) + +struct BurnDriver BurnDrvmd_coolspup = { + "md_coolspup", "md_coolsp", NULL, NULL, "1994", + "Cool Spot (USA, Prototype)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_coolspupRomInfo, md_coolspupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Corporation (Euro) +static struct BurnRomInfo md_corporatRomDesc[] = { + { "mpr-15065.bin", 0x100000, 0xa80d18aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_corporat) +STD_ROM_FN(md_corporat) + +struct BurnDriver BurnDrvmd_corporat = { + "md_corporat", NULL, NULL, NULL, "1992", + "Corporation (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_corporatRomInfo, md_corporatRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cyber-Cop (USA) +static struct BurnRomInfo md_cybercopRomDesc[] = { + { "cyber-cop (usa).bin", 0x100000, 0x01e719c8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cybercop) +STD_ROM_FN(md_cybercop) + +struct BurnDriver BurnDrvmd_cybercop = { + "md_cybercop", "md_corporat", NULL, NULL, "1992", + "Cyber-Cop (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cybercopRomInfo, md_cybercopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cosmic Spacehead (Euro, USA) +static struct BurnRomInfo md_cosmicRomDesc[] = { + { "cosmic spacehead (euro, usa).bin", 0x100000, 0xc593d31c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cosmic) +STD_ROM_FN(md_cosmic) + +struct BurnDriver BurnDrvmd_cosmic = { + "md_cosmic", NULL, NULL, NULL, "1993", + "Cosmic Spacehead (Euro, USA)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cosmicRomInfo, md_cosmicRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crack Down (Euro, Jpn, Rev. A) +static struct BurnRomInfo md_crkdownRomDesc[] = { + { "mpr-13578a.bin", 0x080000, 0xd012a47a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crkdown) +STD_ROM_FN(md_crkdown) + +struct BurnDriver BurnDrvmd_crkdown = { + "md_crkdown", NULL, NULL, NULL, "1990", + "Crack Down (Euro, Jpn, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crkdownRomInfo, md_crkdownRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crack Down (Euro, Jpn) +static struct BurnRomInfo md_crkdown1RomDesc[] = { + { "crack down (euro, jpn).bin", 0x080000, 0x538aaa5d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crkdown1) +STD_ROM_FN(md_crkdown1) + +struct BurnDriver BurnDrvmd_crkdown1 = { + "md_crkdown1", "md_crkdown", NULL, NULL, "1990", + "Crack Down (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crkdown1RomInfo, md_crkdown1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crack Down (USA) +static struct BurnRomInfo md_crkdownuRomDesc[] = { + { "crack down (usa).bin", 0x080000, 0xb9ce9051, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crkdownu) +STD_ROM_FN(md_crkdownu) + +struct BurnDriver BurnDrvmd_crkdownu = { + "md_crkdownu", "md_crkdown", NULL, NULL, "1991", + "Crack Down (USA)\0", NULL, "Sage's Creation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crkdownuRomInfo, md_crkdownuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crayon Shin-chan - Arashi o Yobu Enji (Jpn) +static struct BurnRomInfo md_crayonRomDesc[] = { + { "crayon shin-chan - arashi o yobu enji (jpn).bin", 0x200000, 0x97fc42d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crayon) +STD_ROM_FN(md_crayon) + +struct BurnDriver BurnDrvmd_crayon = { + "md_crayon", NULL, NULL, NULL, "1994", + "Crayon Shin-chan - Arashi o Yobu Enji (Jpn)\0", NULL, "Ma-Ba", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crayonRomInfo, md_crayonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cross Fire (USA) +static struct BurnRomInfo md_crossfRomDesc[] = { + { "cross fire (usa).bin", 0x080000, 0xcc73f3a9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crossf) +STD_ROM_FN(md_crossf) + +struct BurnDriver BurnDrvmd_crossf = { + "md_crossf", NULL, NULL, NULL, "1991", + "Cross Fire (USA)\0", NULL, "Kyugo Boueki", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crossfRomInfo, md_crossfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Airwolf (Jpn) +static struct BurnRomInfo md_superairRomDesc[] = { + { "mpr-13814.bin", 0x080000, 0xfa451982, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_superair) +STD_ROM_FN(md_superair) + +struct BurnDriver BurnDrvmd_superair = { + "md_superair", "md_crossf", NULL, NULL, "1991", + "Super Airwolf (Jpn)\0", NULL, "Kyugo Boueki", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_superairRomInfo, md_superairRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crue Ball (Euro, USA) +static struct BurnRomInfo md_crueballRomDesc[] = { + { "crue06.bin", 0x080000, 0x4b195fc0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crueball) +STD_ROM_FN(md_crueball) + +struct BurnDriver BurnDrvmd_crueball = { + "md_crueball", NULL, NULL, NULL, "1992", + "Crue Ball (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crueballRomInfo, md_crueballRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crue Ball (Jpn) +static struct BurnRomInfo md_crueballjRomDesc[] = { + { "crue ball (jpn).bin", 0x080000, 0x514c53e2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crueballj) +STD_ROM_FN(md_crueballj) + +struct BurnDriver BurnDrvmd_crueballj = { + "md_crueballj", "md_crueball", NULL, NULL, "1993", + "Crue Ball (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crueballjRomInfo, md_crueballjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Twisted Flipper (USA, Prototype) +static struct BurnRomInfo md_twistedfRomDesc[] = { + { "twisted flipper (usa) (beta).bin", 0x080000, 0x6dd47554, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twistedf) +STD_ROM_FN(md_twistedf) + +struct BurnDriver BurnDrvmd_twistedf = { + "md_twistedf", "md_crueball", NULL, NULL, "199?", + "Twisted Flipper (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twistedfRomInfo, md_twistedfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (USA) +static struct BurnRomInfo md_crystlptRomDesc[] = { + { "crystal's pony tale (usa).bin", 0x100000, 0x6cf7a4df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlpt) +STD_ROM_FN(md_crystlpt) + +struct BurnDriver BurnDrvmd_crystlpt = { + "md_crystlpt", NULL, NULL, NULL, "1994", + "Crystal's Pony Tale (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptRomInfo, md_crystlptRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940701) +static struct BurnRomInfo md_crystlptp06RomDesc[] = { + { "crystal's pony tale (prototype - jul 01, 1994).bin", 0x100000, 0x16ac2e4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp06) +STD_ROM_FN(md_crystlptp06) + +struct BurnDriver BurnDrvmd_crystlptp06 = { + "md_crystlptp06", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940701)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp06RomInfo, md_crystlptp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940702) +static struct BurnRomInfo md_crystlptp05RomDesc[] = { + { "crystal's pony tale (prototype - jul 02, 1994).bin", 0x100000, 0x24bc4354, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp05) +STD_ROM_FN(md_crystlptp05) + +struct BurnDriver BurnDrvmd_crystlptp05 = { + "md_crystlptp05", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940702)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp05RomInfo, md_crystlptp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940703) +static struct BurnRomInfo md_crystlptp04RomDesc[] = { + { "crystal's pony tale (prototype - jul 03, 1994).bin", 0x100000, 0x6d67a87c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp04) +STD_ROM_FN(md_crystlptp04) + +struct BurnDriver BurnDrvmd_crystlptp04 = { + "md_crystlptp04", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940703)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp04RomInfo, md_crystlptp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940712-B) +static struct BurnRomInfo md_crystlptp03RomDesc[] = { + { "crystal's pony tale (prototype - jul 12, 1994 - b).bin", 0x100000, 0x3577dc72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp03) +STD_ROM_FN(md_crystlptp03) + +struct BurnDriver BurnDrvmd_crystlptp03 = { + "md_crystlptp03", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940712-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp03RomInfo, md_crystlptp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940712) +static struct BurnRomInfo md_crystlptp02RomDesc[] = { + { "crystal's pony tale (prototype - jul 12, 1994).bin", 0x0ff554, 0x2bfc0a53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp02) +STD_ROM_FN(md_crystlptp02) + +struct BurnDriver BurnDrvmd_crystlptp02 = { + "md_crystlptp02", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940712)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp02RomInfo, md_crystlptp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940713) +static struct BurnRomInfo md_crystlptp01RomDesc[] = { + { "crystal's pony tale (prototype - jul 13, 1994).bin", 0x100000, 0xc67b6dba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp01) +STD_ROM_FN(md_crystlptp01) + +struct BurnDriver BurnDrvmd_crystlptp01 = { + "md_crystlptp01", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940713)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp01RomInfo, md_crystlptp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940601) +static struct BurnRomInfo md_crystlptp12RomDesc[] = { + { "crystal's pony tale (prototype - jun 01, 1994).bin", 0x100000, 0x14c6347c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp12) +STD_ROM_FN(md_crystlptp12) + +struct BurnDriver BurnDrvmd_crystlptp12 = { + "md_crystlptp12", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940601)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp12RomInfo, md_crystlptp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940606) +static struct BurnRomInfo md_crystlptp11RomDesc[] = { + { "crystal's pony tale (prototype - jun 06, 1994).bin", 0x100000, 0x83e8cac9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp11) +STD_ROM_FN(md_crystlptp11) + +struct BurnDriver BurnDrvmd_crystlptp11 = { + "md_crystlptp11", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940606)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp11RomInfo, md_crystlptp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940610) +static struct BurnRomInfo md_crystlptp10RomDesc[] = { + { "crystal's pony tale (prototype - jun 10, 1994).bin", 0x100000, 0x9e1dd267, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp10) +STD_ROM_FN(md_crystlptp10) + +struct BurnDriver BurnDrvmd_crystlptp10 = { + "md_crystlptp10", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940610)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp10RomInfo, md_crystlptp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940623) +static struct BurnRomInfo md_crystlptp09RomDesc[] = { + { "crystal's pony tale (prototype - jun 23, 1994).bin", 0x100000, 0x4ccc19af, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp09) +STD_ROM_FN(md_crystlptp09) + +struct BurnDriver BurnDrvmd_crystlptp09 = { + "md_crystlptp09", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940623)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp09RomInfo, md_crystlptp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940628) +static struct BurnRomInfo md_crystlptp08RomDesc[] = { + { "crystal's pony tale (prototype - jun 28, 1994).bin", 0x100000, 0x03be7f66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp08) +STD_ROM_FN(md_crystlptp08) + +struct BurnDriver BurnDrvmd_crystlptp08 = { + "md_crystlptp08", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940628)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp08RomInfo, md_crystlptp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940630) +static struct BurnRomInfo md_crystlptp07RomDesc[] = { + { "crystal's pony tale (prototype - jun 30, 1994).bin", 0x100000, 0xdd8c73fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp07) +STD_ROM_FN(md_crystlptp07) + +struct BurnDriver BurnDrvmd_crystlptp07 = { + "md_crystlptp07", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940630)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp07RomInfo, md_crystlptp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940511) +static struct BurnRomInfo md_crystlptp15RomDesc[] = { + { "crystal's pony tale (prototype - may 11, 1994).bin", 0x100000, 0xeac9d74b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp15) +STD_ROM_FN(md_crystlptp15) + +struct BurnDriver BurnDrvmd_crystlptp15 = { + "md_crystlptp15", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940511)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp15RomInfo, md_crystlptp15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940519) +static struct BurnRomInfo md_crystlptp14RomDesc[] = { + { "crystal's pony tale (prototype - may 19, 1994).bin", 0x100000, 0xdc50b741, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp14) +STD_ROM_FN(md_crystlptp14) + +struct BurnDriver BurnDrvmd_crystlptp14 = { + "md_crystlptp14", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940519)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp14RomInfo, md_crystlptp14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crystal's Pony Tale (Prototype, 19940526) +static struct BurnRomInfo md_crystlptp13RomDesc[] = { + { "crystal's pony tale (prototype - may 26, 1994).bin", 0x100000, 0xa2eaba55, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crystlptp13) +STD_ROM_FN(md_crystlptp13) + +struct BurnDriver BurnDrvmd_crystlptp13 = { + "md_crystlptp13", "md_crystlpt", NULL, NULL, "1994", + "Crystal's Pony Tale (Prototype, 19940526)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crystlptp13RomInfo, md_crystlptp13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Curse (Jpn) +static struct BurnRomInfo md_curseRomDesc[] = { + { "curse (jpn).bin", 0x080000, 0xa4fbf9a9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_curse) +STD_ROM_FN(md_curse) + +struct BurnDriver BurnDrvmd_curse = { + "md_curse", NULL, NULL, NULL, "1989", + "Curse (Jpn)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_curseRomInfo, md_curseRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cutie Suzuki no Ringside Angel (Jpn) +static struct BurnRomInfo md_cutiesuzRomDesc[] = { + { "cutie suzuki no ringside angel (jpn).bin", 0x080000, 0x13795dca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cutiesuz) +STD_ROM_FN(md_cutiesuz) + +struct BurnDriver BurnDrvmd_cutiesuz = { + "md_cutiesuz", NULL, NULL, NULL, "1990", + "Cutie Suzuki no Ringside Angel (Jpn)\0", NULL, "Asmik Ace", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cutiesuzRomInfo, md_cutiesuzRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// CutThroat Island (Euro, USA) +static struct BurnRomInfo md_cutthrRomDesc[] = { + { "cutthroat island (euro, usa).bin", 0x200000, 0xebabbc70, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cutthr) +STD_ROM_FN(md_cutthr) + +struct BurnDriver BurnDrvmd_cutthr = { + "md_cutthr", NULL, NULL, NULL, "1995", + "CutThroat Island (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cutthrRomInfo, md_cutthrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// CyberBall (World) +static struct BurnRomInfo md_cyberbalRomDesc[] = { + { "mpr-13201.bin", 0x080000, 0x76120e96, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cyberbal) +STD_ROM_FN(md_cyberbal) + +struct BurnDriver BurnDrvmd_cyberbal = { + "md_cyberbal", NULL, NULL, NULL, "1990", + "CyberBall (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cyberbalRomInfo, md_cyberbalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cyborg Justice (Euro, USA) +static struct BurnRomInfo md_cyborgjRomDesc[] = { + { "mpr-15468.bin", 0x080000, 0xab0d1269, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cyborgj) +STD_ROM_FN(md_cyborgj) + +struct BurnDriver BurnDrvmd_cyborgj = { + "md_cyborgj", NULL, NULL, NULL, "1993", + "Cyborg Justice (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cyborgjRomInfo, md_cyborgjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cyborg Justice (Prototype) +static struct BurnRomInfo md_cyborgjpRomDesc[] = { + { "cyborg justice (beta).bin", 0x080000, 0x91daf11e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cyborgjp) +STD_ROM_FN(md_cyborgjp) + +struct BurnDriver BurnDrvmd_cyborgjp = { + "md_cyborgjp", "md_cyborgj", NULL, NULL, "1993", + "Cyborg Justice (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cyborgjpRomInfo, md_cyborgjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daffy Duck in Hollywood (Euro) +static struct BurnRomInfo md_daffyRomDesc[] = { + { "daffy duck in hollywood (euro).bin", 0x200000, 0x1fdc66b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daffy) +STD_ROM_FN(md_daffy) + +struct BurnDriver BurnDrvmd_daffy = { + "md_daffy", NULL, NULL, NULL, "1994", + "Daffy Duck in Hollywood (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daffyRomInfo, md_daffyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daffy Duck in Hollywood (Euro, Prototype) +static struct BurnRomInfo md_daffypRomDesc[] = { + { "daffy duck in hollywood (euro) (beta).bin", 0x200000, 0x0eaa4740, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daffyp) +STD_ROM_FN(md_daffyp) + +struct BurnDriver BurnDrvmd_daffyp = { + "md_daffyp", "md_daffy", NULL, NULL, "1994", + "Daffy Duck in Hollywood (Euro, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daffypRomInfo, md_daffypRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dahna Megami Tanjou (Jpn) +static struct BurnRomInfo md_dahnamRomDesc[] = { + { "dahna megami tanjou (jpn).bin", 0x100000, 0x4602584f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dahnam) +STD_ROM_FN(md_dahnam) + +struct BurnDriver BurnDrvmd_dahnam = { + "md_dahnam", NULL, NULL, NULL, "1991", + "Dahna Megami Tanjou (Jpn)\0", NULL, "IGS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dahnamRomInfo, md_dahnamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dahna (Kor) +static struct BurnRomInfo md_dahnamkRomDesc[] = { + { "mpr-14636.bin", 0x100000, 0x10829ea1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dahnamk) +STD_ROM_FN(md_dahnamk) + +struct BurnDriver BurnDrvmd_dahnamk = { + "md_dahnamk", "md_dahnam", NULL, NULL, "199?", + "Dahna (Kor)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dahnamkRomInfo, md_dahnamkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hercules +static struct BurnRomInfo md_herculRomDesc[] = { + { "hercules (unl).bin", 0x100000, 0xff75d9d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hercul) +STD_ROM_FN(md_hercul) + +struct BurnDriver BurnDrvmd_hercul = { + "md_hercul", "md_dahnam", NULL, NULL, "199?", + "Hercules\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_herculRomInfo, md_herculRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dangerous Seed (Jpn) +static struct BurnRomInfo md_dangseedRomDesc[] = { + { "dangerous seed (jpn).bin", 0x080000, 0xa2990031, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dangseed) +STD_ROM_FN(md_dangseed) + +struct BurnDriver BurnDrvmd_dangseed = { + "md_dangseed", NULL, NULL, NULL, "1990", + "Dangerous Seed (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dangseedRomInfo, md_dangseedRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dark Castle (Euro, USA) +static struct BurnRomInfo md_darkcastRomDesc[] = { + { "dark castle (euro, usa).bin", 0x080000, 0x0464aca4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_darkcast) +STD_ROM_FN(md_darkcast) + +struct BurnDriver BurnDrvmd_darkcast = { + "md_darkcast", NULL, NULL, NULL, "1991", + "Dark Castle (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_darkcastRomInfo, md_darkcastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Darwin 4081 (Jpn, Kor) +static struct BurnRomInfo md_darwinRomDesc[] = { + { "darwin 4081 (jpn, kor).bin", 0x080000, 0x7a33b0cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_darwin) +STD_ROM_FN(md_darwin) + +struct BurnDriver BurnDrvmd_darwin = { + "md_darwin", NULL, NULL, NULL, "1990", + "Darwin 4081 (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_darwinRomInfo, md_darwinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dashin' Desperadoes (USA) +static struct BurnRomInfo md_dashRomDesc[] = { + { "dashin' desperadoes (usa).bin", 0x100000, 0xdcb76fb7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dash) +STD_ROM_FN(md_dash) + +struct BurnDriver BurnDrvmd_dash = { + "md_dash", NULL, NULL, NULL, "1993", + "Dashin' Desperadoes (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dashRomInfo, md_dashRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dashin' Desperadoes (USA, Prototype) +static struct BurnRomInfo md_dashp1RomDesc[] = { + { "dashin' desperadoes (usa) (beta).bin", 0x100000, 0x98d224a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dashp1) +STD_ROM_FN(md_dashp1) + +struct BurnDriver BurnDrvmd_dashp1 = { + "md_dashp1", "md_dash", NULL, NULL, "1993", + "Dashin' Desperadoes (USA, Prototype)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dashp1RomInfo, md_dashp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dashin' Desperadoes (USA, Prototype, Alt) +static struct BurnRomInfo md_dashp2RomDesc[] = { + { "dashin' desperadoes (beta).bin", 0x100000, 0xadaffc3f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dashp2) +STD_ROM_FN(md_dashp2) + +struct BurnDriver BurnDrvmd_dashp2 = { + "md_dashp2", "md_dash", NULL, NULL, "1993", + "Dashin' Desperadoes (USA, Prototype, Alt)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dashp2RomInfo, md_dashp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// David Crane's Amazing Tennis (USA) +static struct BurnRomInfo md_davidcRomDesc[] = { + { "david crane's amazing tennis (usa).bin", 0x100000, 0x9177088c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_davidc) +STD_ROM_FN(md_davidc) + +struct BurnDriver BurnDrvmd_davidc = { + "md_davidc", NULL, NULL, NULL, "1992", + "David Crane's Amazing Tennis (USA)\0", NULL, "Absolute Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_davidcRomInfo, md_davidcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// David Robinson's Supreme Court (Euro, USA) +static struct BurnRomInfo md_drscRomDesc[] = { + { "mpr-14835.bin", 0x080000, 0x512b7599, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_drsc) +STD_ROM_FN(md_drsc) + +struct BurnDriver BurnDrvmd_drsc = { + "md_drsc", NULL, NULL, NULL, "1992", + "David Robinson's Supreme Court (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_drscRomInfo, md_drscRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// David Robinson Basketball (Jpn) +static struct BurnRomInfo md_drscjRomDesc[] = { + { "david robinson basketball (jpn).bin", 0x080000, 0x56164b00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_drscj) +STD_ROM_FN(md_drscj) + +struct BurnDriver BurnDrvmd_drscj = { + "md_drscj", "md_drsc", NULL, NULL, "1992", + "David Robinson Basketball (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_drscjRomInfo, md_drscjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Davis Cup World Tour (Euro, USA, 199307) +static struct BurnRomInfo md_daviscupRomDesc[] = { + { "davis cup world tour (euro, usa) (july 1993).bin", 0x100000, 0x894686f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daviscup) +STD_ROM_FN(md_daviscup) + +struct BurnDriver BurnDrvmd_daviscup = { + "md_daviscup", NULL, NULL, NULL, "1993", + "Davis Cup World Tour (Euro, USA, 199307)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daviscupRomInfo, md_daviscupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Davis Cup World Tour (Euro, USA, 199306) +static struct BurnRomInfo md_daviscupaRomDesc[] = { + { "davis cup world tour (euro, usa) (june 1993).bin", 0x100000, 0x7c6b0646, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daviscupa) +STD_ROM_FN(md_daviscupa) + +struct BurnDriver BurnDrvmd_daviscupa = { + "md_daviscupa", "md_daviscup", NULL, NULL, "1993", + "Davis Cup World Tour (Euro, USA, 199306)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daviscupaRomInfo, md_daviscupaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Davis Cup World Tour Tennis 2 (Prototype 1) +static struct BurnRomInfo md_daviscp2RomDesc[] = { + { "davis cup world tour tennis 2 (beta 1).bin", 0x200000, 0x6f4183c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daviscp2) +STD_ROM_FN(md_daviscp2) + +struct BurnDriver BurnDrvmd_daviscp2 = { + "md_daviscp2", NULL, NULL, NULL, "199?", + "Davis Cup World Tour Tennis 2 (Prototype 1)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daviscp2RomInfo, md_daviscp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Davis Cup II (USA, Prototype) +static struct BurnRomInfo md_daviscp2aRomDesc[] = { + { "davis cup ii (usa) (prototype).bin", 0x200000, 0x76f2bed8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daviscp2a) +STD_ROM_FN(md_daviscp2a) + +struct BurnDriver BurnDrvmd_daviscp2a = { + "md_daviscp2a", "md_daviscp2", NULL, NULL, "199?", + "Davis Cup II (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daviscp2aRomInfo, md_daviscp2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daze Before Christmas (Oceania) +static struct BurnRomInfo md_dazeRomDesc[] = { + { "daze before christmas (aus).bin", 0x200000, 0xb95e25c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daze) +STD_ROM_FN(md_daze) + +struct BurnDriver BurnDrvmd_daze = { + "md_daze", NULL, NULL, NULL, "1994", + "Daze Before Christmas (Oceania)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dazeRomInfo, md_dazeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daze Before Christmas (Oceania, Prototype) +static struct BurnRomInfo md_dazepRomDesc[] = { + { "daze before christmas (aus) (beta).bin", 0x200000, 0x317c9491, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dazep) +STD_ROM_FN(md_dazep) + +struct BurnDriver BurnDrvmd_dazep = { + "md_dazep", "md_daze", NULL, NULL, "1994", + "Daze Before Christmas (Oceania, Prototype)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dazepRomInfo, md_dazepRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Deadly Moves (USA) +static struct BurnRomInfo md_deadlymvRomDesc[] = { + { "deadly moves (usa).bin", 0x100000, 0x35cbd237, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_deadlymv) +STD_ROM_FN(md_deadlymv) + +struct BurnDriver BurnDrvmd_deadlymv = { + "md_deadlymv", NULL, NULL, NULL, "1992", + "Deadly Moves (USA)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_deadlymvRomInfo, md_deadlymvRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Power Athlete (Jpn, Kor) +static struct BurnRomInfo md_powerathRomDesc[] = { + { "power athlete (jpn, kor).bin", 0x100000, 0xb41b77cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_powerath) +STD_ROM_FN(md_powerath) + +struct BurnDriver BurnDrvmd_powerath = { + "md_powerath", "md_deadlymv", NULL, NULL, "1992", + "Power Athlete (Jpn, Kor)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_powerathRomInfo, md_powerathRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Death and Return of Superman (USA) +static struct BurnRomInfo md_deathretRomDesc[] = { + { "death and return of superman, the (usa).bin", 0x200000, 0x982242d3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_deathret) +STD_ROM_FN(md_deathret) + +struct BurnDriver BurnDrvmd_deathret = { + "md_deathret", NULL, NULL, NULL, "1995", + "The Death and Return of Superman (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_deathretRomInfo, md_deathretRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Death Duel (USA) +static struct BurnRomInfo md_deathdlRomDesc[] = { + { "death duel (usa).bin", 0x100000, 0xa9804dcc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_deathdl) +STD_ROM_FN(md_deathdl) + +struct BurnDriver BurnDrvmd_deathdl = { + "md_deathdl", NULL, NULL, NULL, "1992", + "Death Duel (USA)\0", NULL, "Razorsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_deathdlRomInfo, md_deathdlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// DecapAttack (Euro, USA, Kor) +static struct BurnRomInfo md_decapattRomDesc[] = { + { "mpr-14249.bin", 0x080000, 0x73dc0dd8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_decapatt) +STD_ROM_FN(md_decapatt) + +struct BurnDriver BurnDrvmd_decapatt = { + "md_decapatt", NULL, NULL, NULL, "1991", + "DecapAttack (Euro, USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_decapattRomInfo, md_decapattRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Demolition Man (Euro, USA) +static struct BurnRomInfo md_demomanRomDesc[] = { + { "demolition man (euro, usa).bin", 0x200000, 0x5ff71877, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_demoman) +STD_ROM_FN(md_demoman) + +struct BurnDriver BurnDrvmd_demoman = { + "md_demoman", NULL, NULL, NULL, "1995", + "Demolition Man (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_demomanRomInfo, md_demomanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Demolition Man (USA, Prototype) +static struct BurnRomInfo md_demomanpRomDesc[] = { + { "demolition man (usa) (beta).bin", 0x200000, 0x57ffad7a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_demomanp) +STD_ROM_FN(md_demomanp) + +struct BurnDriver BurnDrvmd_demomanp = { + "md_demomanp", "md_demoman", NULL, NULL, "1995", + "Demolition Man (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_demomanpRomInfo, md_demomanpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Euro, USA) +static struct BurnRomInfo md_desrtdemRomDesc[] = { + { "desert demolition starring road runner and wile e. coyote (euro, usa).bin", 0x100000, 0xc287343d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdem) +STD_ROM_FN(md_desrtdem) + +struct BurnDriver BurnDrvmd_desrtdem = { + "md_desrtdem", NULL, NULL, NULL, "1994", + "Desert Demolition (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemRomInfo, md_desrtdemRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941206) +static struct BurnRomInfo md_desrtdemp9RomDesc[] = { + { "desert demolition (prototype - dec 06, 1994).bin", 0x0ed0ad, 0xd27fe9e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp9) +STD_ROM_FN(md_desrtdemp9) + +struct BurnDriver BurnDrvmd_desrtdemp9 = { + "md_desrtdemp9", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941206)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp9RomInfo, md_desrtdemp9RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941208) +static struct BurnRomInfo md_desrtdemp8RomDesc[] = { + { "desert demolition (prototype - dec 08, 1994).bin", 0x0fdfb8, 0x69aaeab6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp8) +STD_ROM_FN(md_desrtdemp8) + +struct BurnDriver BurnDrvmd_desrtdemp8 = { + "md_desrtdemp8", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941208)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp8RomInfo, md_desrtdemp8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941212-B) +static struct BurnRomInfo md_desrtdemp7RomDesc[] = { + { "desert demolition (prototype - dec 12, 1994 - b).bin", 0x100000, 0x16f19283, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp7) +STD_ROM_FN(md_desrtdemp7) + +struct BurnDriver BurnDrvmd_desrtdemp7 = { + "md_desrtdemp7", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941212-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp7RomInfo, md_desrtdemp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941212) +static struct BurnRomInfo md_desrtdemp6RomDesc[] = { + { "desert demolition (prototype - dec 12, 1994).bin", 0x0ec988, 0x5dad49d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp6) +STD_ROM_FN(md_desrtdemp6) + +struct BurnDriver BurnDrvmd_desrtdemp6 = { + "md_desrtdemp6", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941212)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp6RomInfo, md_desrtdemp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941213) +static struct BurnRomInfo md_desrtdemp5RomDesc[] = { + { "desert demolition (prototype - dec 13, 1994).bin", 0x0fde9c, 0x375dee15, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp5) +STD_ROM_FN(md_desrtdemp5) + +struct BurnDriver BurnDrvmd_desrtdemp5 = { + "md_desrtdemp5", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941213)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp5RomInfo, md_desrtdemp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941214) +static struct BurnRomInfo md_desrtdemp4RomDesc[] = { + { "desert demolition (prototype - dec 14, 1994).bin", 0x0fde9c, 0x39f9f304, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp4) +STD_ROM_FN(md_desrtdemp4) + +struct BurnDriver BurnDrvmd_desrtdemp4 = { + "md_desrtdemp4", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941214)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp4RomInfo, md_desrtdemp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941215) +static struct BurnRomInfo md_desrtdemp3RomDesc[] = { + { "desert demolition (prototype - dec 15, 1994).bin", 0x0fde9c, 0x5109736a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp3) +STD_ROM_FN(md_desrtdemp3) + +struct BurnDriver BurnDrvmd_desrtdemp3 = { + "md_desrtdemp3", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941215)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp3RomInfo, md_desrtdemp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941216) +static struct BurnRomInfo md_desrtdemp2RomDesc[] = { + { "desert demolition (prototype - dec 16, 1994).bin", 0x100000, 0x573fabfb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp2) +STD_ROM_FN(md_desrtdemp2) + +struct BurnDriver BurnDrvmd_desrtdemp2 = { + "md_desrtdemp2", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941216)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp2RomInfo, md_desrtdemp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Demolition (Prototype, 19941219) +static struct BurnRomInfo md_desrtdemp1RomDesc[] = { + { "desert demolition (prototype - dec 19, 1994).bin", 0x0fde9c, 0xb0ece758, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_desrtdemp1) +STD_ROM_FN(md_desrtdemp1) + +struct BurnDriver BurnDrvmd_desrtdemp1 = { + "md_desrtdemp1", "md_desrtdem", NULL, NULL, "1994", + "Desert Demolition (Prototype, 19941219)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_desrtdemp1RomInfo, md_desrtdemp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Strike (Euro, USA) +static struct BurnRomInfo md_dstrikeRomDesc[] = { + { "desert strike (euro, usa).bin", 0x100000, 0x67a9860b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dstrike) +STD_ROM_FN(md_dstrike) + +struct BurnDriver BurnDrvmd_dstrike = { + "md_dstrike", NULL, NULL, NULL, "1992", + "Desert Strike (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dstrikeRomInfo, md_dstrikeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Desert Strike (Jpn, Kor) +static struct BurnRomInfo md_dstrikejRomDesc[] = { + { "desert strike (jpn, kor).bin", 0x100000, 0x1e740145, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dstrikej) +STD_ROM_FN(md_dstrikej) + +struct BurnDriver BurnDrvmd_dstrikej = { + "md_dstrikej", "md_dstrike", NULL, NULL, "1993", + "Desert Strike (Jpn, Kor)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dstrikejRomInfo, md_dstrikejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Devilish - The Next Possession (USA) +static struct BurnRomInfo md_devilishRomDesc[] = { + { "devilish - the next possession (usa).bin", 0x080000, 0xd3f300ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_devilish) +STD_ROM_FN(md_devilish) + +struct BurnDriver BurnDrvmd_devilish = { + "md_devilish", NULL, NULL, NULL, "1992", + "Devilish - The Next Possession (USA)\0", NULL, "Sage's Creation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_devilishRomInfo, md_devilishRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bad Omen (Jpn, Kor) +static struct BurnRomInfo md_badomenRomDesc[] = { + { "bad omen (jpn, kor).bin", 0x080000, 0x975693ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_badomen) +STD_ROM_FN(md_badomen) + +struct BurnDriver BurnDrvmd_badomen = { + "md_badomen", "md_devilish", NULL, NULL, "1992", + "Bad Omen (Jpn, Kor)\0", NULL, "Hot-B", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_badomenRomInfo, md_badomenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dial Q o Mawase! (Jpn) +static struct BurnRomInfo md_dialqoRomDesc[] = { + { "dial q o mawase! (jpn) (unl).bin", 0x100000, 0xc632e5af, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dialqo) +STD_ROM_FN(md_dialqo) + +struct BurnDriver BurnDrvmd_dialqo = { + "md_dialqo", NULL, NULL, NULL, "199?", + "Dial Q o Mawase! (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dialqoRomInfo, md_dialqoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dick Tracy (World) +static struct BurnRomInfo md_dicktrRomDesc[] = { + { "mpr-13661.bin", 0x080000, 0xef887533, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dicktr) +STD_ROM_FN(md_dicktr) + +struct BurnDriver BurnDrvmd_dicktr = { + "md_dicktr", NULL, NULL, NULL, "1991", + "Dick Tracy (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dicktrRomInfo, md_dicktrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dick Vitale's 'Awesome, Baby!' College Hoops (USA) +static struct BurnRomInfo md_dickvitlRomDesc[] = { + { "dick vitale's 'awesome, baby!' college hoops (usa).bin", 0x200000, 0x1312cf22, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dickvitl) +STD_ROM_FN(md_dickvitl) + +struct BurnDriver BurnDrvmd_dickvitl = { + "md_dickvitl", NULL, NULL, NULL, "1994", + "Dick Vitale's 'Awesome, Baby!' College Hoops (USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dickvitlRomInfo, md_dickvitlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dino Dini's Soccer (Euro) +static struct BurnRomInfo md_dinodiniRomDesc[] = { + { "dino dini's soccer (euro).bin", 0x100000, 0x4608f53a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinodini) +STD_ROM_FN(md_dinodini) + +struct BurnDriver BurnDrvmd_dinodini = { + "md_dinodini", NULL, NULL, NULL, "1994", + "Dino Dini's Soccer (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dinodiniRomInfo, md_dinodiniRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dino Land (USA) +static struct BurnRomInfo md_dinolandRomDesc[] = { + { "dino land (usa).bin", 0x080000, 0x5fe351b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinoland) +STD_ROM_FN(md_dinoland) + +struct BurnDriver BurnDrvmd_dinoland = { + "md_dinoland", NULL, NULL, NULL, "1991", + "Dino Land (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinolandRomInfo, md_dinolandRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chou Touryuu Retsuden - Dino Land (Jpn) +static struct BurnRomInfo md_dinolandjRomDesc[] = { + { "chou touryuu retsuden - dino land (jpn).bin", 0x080000, 0x81f939de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinolandj) +STD_ROM_FN(md_dinolandj) + +struct BurnDriver BurnDrvmd_dinolandj = { + "md_dinolandj", "md_dinoland", NULL, NULL, "1991", + "Chou Touryuu Retsuden - Dino Land (Jpn)\0", NULL, "Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinolandjRomInfo, md_dinolandjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// A Dinosaur's Tale (USA) +static struct BurnRomInfo md_dinotaleRomDesc[] = { + { "dinosaur's tale, a (usa).bin", 0x100000, 0x70155b5b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinotale) +STD_ROM_FN(md_dinotale) + +struct BurnDriver BurnDrvmd_dinotale = { + "md_dinotale", NULL, NULL, NULL, "1993", + "A Dinosaur's Tale (USA)\0", NULL, "Hi-Tech Expression", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinotaleRomInfo, md_dinotaleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dinosaurs for Hire (USA) +static struct BurnRomInfo md_dinohireRomDesc[] = { + { "dinosaurs for hire (usa).bin", 0x100000, 0x39351146, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinohire) +STD_ROM_FN(md_dinohire) + +struct BurnDriver BurnDrvmd_dinohire = { + "md_dinohire", NULL, NULL, NULL, "1993", + "Dinosaurs for Hire (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinohireRomInfo, md_dinohireRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dinosaurs for Hire (Prototype, 19930426) +static struct BurnRomInfo md_dinohirep3RomDesc[] = { + { "dinosaurs for hire (prototype - apr 26, 1993).bin", 0x100000, 0x54c77d3e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinohirep3) +STD_ROM_FN(md_dinohirep3) + +struct BurnDriver BurnDrvmd_dinohirep3 = { + "md_dinohirep3", "md_dinohire", NULL, NULL, "1993", + "Dinosaurs for Hire (Prototype, 19930426)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinohirep3RomInfo, md_dinohirep3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dinosaurs for Hire (Prototype, 19930427) +static struct BurnRomInfo md_dinohirep2RomDesc[] = { + { "dinosaurs for hire (prototype - apr 27, 1993).bin", 0x100000, 0x16000453, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinohirep2) +STD_ROM_FN(md_dinohirep2) + +struct BurnDriver BurnDrvmd_dinohirep2 = { + "md_dinohirep2", "md_dinohire", NULL, NULL, "1993", + "Dinosaurs for Hire (Prototype, 19930427)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinohirep2RomInfo, md_dinohirep2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dinosaurs for Hire (Prototype, 19930502) +static struct BurnRomInfo md_dinohirep1RomDesc[] = { + { "dinosaurs for hire (prototype - may 02, 1993).bin", 0x100000, 0x8954dee9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dinohirep1) +STD_ROM_FN(md_dinohirep1) + +struct BurnDriver BurnDrvmd_dinohirep1 = { + "md_dinohirep1", "md_dinohire", NULL, NULL, "1993", + "Dinosaurs for Hire (Prototype, 19930502)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dinohirep1RomInfo, md_dinohirep1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Disney Collection - Mickey and Donald (Euro) +static struct BurnRomInfo md_disneyclRomDesc[] = { + { "disney collection, the (euro).bin", 0x100000, 0xadfde883, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_disneycl) +STD_ROM_FN(md_disneycl) + +struct BurnDriver BurnDrvmd_disneycl = { + "md_disneycl", NULL, NULL, NULL, "1996", + "The Disney Collection - Mickey and Donald (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_disneyclRomInfo, md_disneyclRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Divine Sealing (Jpn) +static struct BurnRomInfo md_divineRomDesc[] = { + { "divine sealing (jpn) (unl).bin", 0x100000, 0xca72973c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_divine) +STD_ROM_FN(md_divine) + +struct BurnDriver BurnDrvmd_divine = { + "md_divine", NULL, NULL, NULL, "1991", + "Divine Sealing (Jpn)\0", NULL, "CYX", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_divineRomInfo, md_divineRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// DJ Boy (Euro) +static struct BurnRomInfo md_djboyRomDesc[] = { + { "mpr-14560.bin", 0x080000, 0x860e749a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_djboy) +STD_ROM_FN(md_djboy) + +struct BurnDriver BurnDrvmd_djboy = { + "md_djboy", NULL, NULL, NULL, "1991", + "DJ Boy (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_djboyRomInfo, md_djboyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// DJ Boy (Jpn) +static struct BurnRomInfo md_djboyjRomDesc[] = { + { "dj boy (jpn).bin", 0x080000, 0x202abaa8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_djboyj) +STD_ROM_FN(md_djboyj) + +struct BurnDriver BurnDrvmd_djboyj = { + "md_djboyj", "md_djboy", NULL, NULL, "1990", + "DJ Boy (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_djboyjRomInfo, md_djboyjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// DJ Boy (USA) +static struct BurnRomInfo md_djboyuRomDesc[] = { + { "dj boy (usa).bin", 0x080000, 0xdc9f02db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_djboyu) +STD_ROM_FN(md_djboyu) + +struct BurnDriver BurnDrvmd_djboyu = { + "md_djboyu", "md_djboy", NULL, NULL, "1990", + "DJ Boy (USA)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_djboyuRomInfo, md_djboyuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ikazuse! Koi no Doki Doki Penguin Land MD (Jpn, SegaNet) +static struct BurnRomInfo md_dokidokiRomDesc[] = { + { "ikazuse! koi no doki doki penguin land md (jpn) (sn).bin", 0x040000, 0x0053bfd6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dokidoki) +STD_ROM_FN(md_dokidoki) + +struct BurnDriver BurnDrvmd_dokidoki = { + "md_dokidoki", NULL, NULL, NULL, "1991", + "Ikazuse! Koi no Doki Doki Penguin Land MD (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dokidokiRomInfo, md_dokidokiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ikazuse! Koi no Doki Doki Penguin Land MD (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_dokidokignkRomDesc[] = { + { "ikazuse! koi no doki doki penguin land md (jpn) (gnk).bin", 0x040000, 0x22736650, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dokidokignk) +STD_ROM_FN(md_dokidokignk) + +struct BurnDriver BurnDrvmd_dokidokignk = { + "md_dokidokignk", "md_dokidoki", NULL, NULL, "1991", + "Ikazuse! Koi no Doki Doki Penguin Land MD (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dokidokignkRomInfo, md_dokidokignkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dominus (USA, Prototype) +static struct BurnRomInfo md_dominusRomDesc[] = { + { "dominus (usa) (prototype).bin", 0x0c0000, 0x30006ebd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dominus) +STD_ROM_FN(md_dominus) + +struct BurnDriver BurnDrvmd_dominus = { + "md_dominus", NULL, NULL, NULL, "199?", + "Dominus (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dominusRomInfo, md_dominusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Donald in Maui Mallard (Euro) +static struct BurnRomInfo md_mauimallRomDesc[] = { + { "donald in maui mallard (euro).bin", 0x300000, 0xb2dd857f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mauimall) +STD_ROM_FN(md_mauimall) + +struct BurnDriver BurnDrvmd_mauimall = { + "md_mauimall", NULL, NULL, NULL, "1995", + "Donald in Maui Mallard (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mauimallRomInfo, md_mauimallRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Doom Troopers - The Mutant Chronicles (USA) +static struct BurnRomInfo md_doomtrRomDesc[] = { + { "doom troopers - the mutant chronicles (usa).bin", 0x200000, 0x11194414, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_doomtr) +STD_ROM_FN(md_doomtr) + +struct BurnDriver BurnDrvmd_doomtr = { + "md_doomtr", NULL, NULL, NULL, "1995", + "Doom Troopers - The Mutant Chronicles (USA)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_doomtrRomInfo, md_doomtrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Doraemon - Yume Dorobou to 7-nin no Gozans (Jpn) +static struct BurnRomInfo md_doraemonRomDesc[] = { + { "doraemon - yume dorobou to 7-nin no gozans (jpn).bin", 0x080000, 0xeeed1130, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_doraemon) +STD_ROM_FN(md_doraemon) + +struct BurnDriver BurnDrvmd_doraemon = { + "md_doraemon", NULL, NULL, NULL, "1993", + "Doraemon - Yume Dorobou to 7-nin no Gozans (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_doraemonRomInfo, md_doraemonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Clutch (Euro) +static struct BurnRomInfo md_doubleclRomDesc[] = { + { "double clutch (euro).bin", 0x040000, 0xd98c623c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_doublecl) +STD_ROM_FN(md_doublecl) + +struct BurnDriver BurnDrvmd_doublecl = { + "md_doublecl", NULL, NULL, NULL, "1992", + "Double Clutch (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_doubleclRomInfo, md_doubleclRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Dragon (Euro, USA) +static struct BurnRomInfo md_ddragonRomDesc[] = { + { "double dragon (euro, usa).bin", 0x080000, 0x054f5d53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddragon) +STD_ROM_FN(md_ddragon) + +struct BurnDriver BurnDrvmd_ddragon = { + "md_ddragon", NULL, NULL, NULL, "1993", + "Double Dragon (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ddragonRomInfo, md_ddragonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Dragon II - The Revenge (Jpn) +static struct BurnRomInfo md_ddragon2RomDesc[] = { + { "double dragon ii - the revenge (jpn).bin", 0x080000, 0xa8bfdbd6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddragon2) +STD_ROM_FN(md_ddragon2) + +struct BurnDriver BurnDrvmd_ddragon2 = { + "md_ddragon2", NULL, NULL, NULL, "1991", + "Double Dragon II - The Revenge (Jpn)\0", NULL, "Palsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ddragon2RomInfo, md_ddragon2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Dragon 3 - The Arcade Game (Euro, USA) +static struct BurnRomInfo md_ddragon3RomDesc[] = { + { "double dragon 3 - the arcade game (euro, usa).bin", 0x100000, 0xb36ab75c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddragon3) +STD_ROM_FN(md_ddragon3) + +struct BurnDriver BurnDrvmd_ddragon3 = { + "md_ddragon3", NULL, NULL, NULL, "1992", + "Double Dragon 3 - The Arcade Game (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ddragon3RomInfo, md_ddragon3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Dragon V - The Shadow Falls (USA) +static struct BurnRomInfo md_ddragon5RomDesc[] = { + { "double dragon v - the shadow falls (usa).bin", 0x300000, 0x27e59e35, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddragon5) +STD_ROM_FN(md_ddragon5) + +struct BurnDriver BurnDrvmd_ddragon5 = { + "md_ddragon5", NULL, NULL, NULL, "1994", + "Double Dragon V - The Shadow Falls (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ddragon5RomInfo, md_ddragon5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dr. Robotnik's Mean Bean Machine (Euro) +static struct BurnRomInfo md_drrobotnRomDesc[] = { + { "dr. robotnik's mean bean machine (euro).bin", 0x100000, 0x70680706, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_drrobotn) +STD_ROM_FN(md_drrobotn) + +struct BurnDriver BurnDrvmd_drrobotn = { + "md_drrobotn", NULL, NULL, NULL, "1993", + "Dr. Robotnik's Mean Bean Machine (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_drrobotnRomInfo, md_drrobotnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dr. Robotnik's Mean Bean Machine (USA, Prototype) +static struct BurnRomInfo md_drrobotn1RomDesc[] = { + { "dr. robotnik's mean bean machine (usa) (beta).bin", 0x100000, 0x4d0e5273, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_drrobotn1) +STD_ROM_FN(md_drrobotn1) + +struct BurnDriver BurnDrvmd_drrobotn1 = { + "md_drrobotn1", "md_drrobotn", NULL, NULL, "1993", + "Dr. Robotnik's Mean Bean Machine (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_drrobotn1RomInfo, md_drrobotn1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dr. Robotnik's Mean Bean Machine (USA) +static struct BurnRomInfo md_drrobotnuRomDesc[] = { + { "dr. robotnik's mean bean machine (usa).bin", 0x100000, 0xc7ca517f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_drrobotnu) +STD_ROM_FN(md_drrobotnu) + +struct BurnDriver BurnDrvmd_drrobotnu = { + "md_drrobotnu", "md_drrobotn", NULL, NULL, "1993", + "Dr. Robotnik's Mean Bean Machine (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_drrobotnuRomInfo, md_drrobotnuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dong Gu Ri Te Chi Jak Jeon (Kor) +static struct BurnRomInfo md_dongguriRomDesc[] = { + { "dong gu ri te chi jak jeon (kor).bin", 0x100000, 0xe32f0b1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dongguri) +STD_ROM_FN(md_dongguri) + +struct BurnDriver BurnDrvmd_dongguri = { + "md_dongguri", "md_drrobotn", NULL, NULL, "199?", + "Dong Gu Ri Te Chi Jak Jeon (Kor)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dongguriRomInfo, md_dongguriRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon - The Bruce Lee Story (Euro) +static struct BurnRomInfo md_dragonRomDesc[] = { + { "dragon - the bruce lee story (euro).bin", 0x200000, 0xfdeed51d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dragon) +STD_ROM_FN(md_dragon) + +struct BurnDriver BurnDrvmd_dragon = { + "md_dragon", NULL, NULL, NULL, "1993", + "Dragon - The Bruce Lee Story (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dragonRomInfo, md_dragonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon - The Bruce Lee Story (USA) +static struct BurnRomInfo md_dragonuRomDesc[] = { + { "dragon - the bruce lee story (usa).bin", 0x200000, 0xefe850e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dragonu) +STD_ROM_FN(md_dragonu) + +struct BurnDriver BurnDrvmd_dragonu = { + "md_dragonu", "md_dragon", NULL, NULL, "1994", + "Dragon - The Bruce Lee Story (USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dragonuRomInfo, md_dragonuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon Ball Z - Buyuu Retsuden (Jpn) +static struct BurnRomInfo md_dbzRomDesc[] = { + { "dragon ball z - buyuu retsuden (jpn).bin", 0x200000, 0xaf8f3371, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dbz) +STD_ROM_FN(md_dbz) + +struct BurnDriver BurnDrvmd_dbz = { + "md_dbz", NULL, NULL, NULL, "1994", + "Dragon Ball Z - Buyuu Retsuden (Jpn)\0", NULL, "Bandai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dbzRomInfo, md_dbzRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon Ball Z - L'Appel du Destin (Fra) +static struct BurnRomInfo md_dbzfRomDesc[] = { + { "dragon ball z - l'appel du destin (france).bin", 0x200000, 0xf035c737, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dbzf) +STD_ROM_FN(md_dbzf) + +struct BurnDriver BurnDrvmd_dbzf = { + "md_dbzf", "md_dbz", NULL, NULL, "1994", + "Dragon Ball Z - L'Appel du Destin (Fra)\0", NULL, "Bandai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dbzfRomInfo, md_dbzfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon Slayer - Eiyuu Densetsu (Jpn) +static struct BurnRomInfo md_dslayerRomDesc[] = { + { "dragon slayer - eiyuu densetsu (jpn).bin", 0x200000, 0x01bc1604, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dslayer) +STD_ROM_FN(md_dslayer) + +struct BurnDriver BurnDrvmd_dslayer = { + "md_dslayer", NULL, NULL, NULL, "1994", + "Dragon Slayer - Eiyuu Densetsu (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dslayerRomInfo, md_dslayerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon Slayer - Eiyuu Densetsu II (Jpn) +static struct BurnRomInfo md_dslayer2RomDesc[] = { + { "dragon slayer - eiyuu densetsu ii (jpn).bin", 0x200000, 0x46924dc3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dslayer2) +STD_ROM_FN(md_dslayer2) + +struct BurnDriver BurnDrvmd_dslayer2 = { + "md_dslayer2", NULL, NULL, NULL, "1995", + "Dragon Slayer - Eiyuu Densetsu II (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dslayer2RomInfo, md_dslayer2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon's Eye Plus - Shanghai III (Jpn) +static struct BurnRomInfo md_shangai3RomDesc[] = { + { "dragon's eye plus - shanghai iii (jpn).bin", 0x040000, 0x81f0c3cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangai3) +STD_ROM_FN(md_shangai3) + +struct BurnDriver BurnDrvmd_shangai3 = { + "md_shangai3", NULL, NULL, NULL, "1991", + "Dragon's Eye Plus - Shanghai III (Jpn)\0", NULL, "Home Data", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangai3RomInfo, md_shangai3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon's Fury (Euro, USA) +static struct BurnRomInfo md_dfuryRomDesc[] = { + { "dragon's fury (euro, usa).bin", 0x080000, 0x58037bc6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dfury) +STD_ROM_FN(md_dfury) + +struct BurnDriver BurnDrvmd_dfury = { + "md_dfury", NULL, NULL, NULL, "1992", + "Dragon's Fury (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dfuryRomInfo, md_dfuryRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon's Lair (USA, Prototype) +static struct BurnRomInfo md_dlairRomDesc[] = { + { "dragon's lair (usa, prototype).bin", 0x080000, 0xa33eb522, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dlair) +STD_ROM_FN(md_dlair) + +struct BurnDriver BurnDrvmd_dlair = { + "md_dlair", NULL, NULL, NULL, "199?", + "Dragon's Lair (USA, Prototype)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dlairRomInfo, md_dlairRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Devil Crash MD (Jpn) +static struct BurnRomInfo md_devlcrshRomDesc[] = { + { "devil crash md (jpn).bin", 0x080000, 0x4c4caad8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_devlcrsh) +STD_ROM_FN(md_devlcrsh) + +struct BurnDriver BurnDrvmd_devlcrsh = { + "md_devlcrsh", "md_dfury", NULL, NULL, "1993", + "Devil Crash MD (Jpn)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_devlcrshRomInfo, md_devlcrshRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon's Revenge (Euro, USA) +static struct BurnRomInfo md_dragnrevRomDesc[] = { + { "dragon's revenge (euro, usa).bin", 0x100000, 0x841edbc0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dragnrev) +STD_ROM_FN(md_dragnrev) + +struct BurnDriver BurnDrvmd_dragnrev = { + "md_dragnrev", NULL, NULL, NULL, "1993", + "Dragon's Revenge (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dragnrevRomInfo, md_dragnrevRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dragon's Revenge (Jpn) +static struct BurnRomInfo md_dragnrevjRomDesc[] = { + { "dragon's revenge (japan).bin", 0x100000, 0xd8d2efd7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dragnrevj) +STD_ROM_FN(md_dragnrevj) + +struct BurnDriver BurnDrvmd_dragnrevj = { + "md_dragnrevj", "md_dragnrev", NULL, NULL, "1993", + "Dragon's Revenge (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dragnrevjRomInfo, md_dragnrevjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Duke Nukem 3D (Bra) +static struct BurnRomInfo md_dukenk3dRomDesc[] = { + { "duke nukem 3d (bra).bin", 0x400000, 0x6bd2accb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dukenk3d) +STD_ROM_FN(md_dukenk3d) + +struct BurnDriver BurnDrvmd_dukenk3d = { + "md_dukenk3d", NULL, NULL, NULL, "1998", + "Duke Nukem 3D (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dukenk3dRomInfo, md_dukenk3dRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dune II - Battle for Arrakis (Euro) +static struct BurnRomInfo md_dune2RomDesc[] = { + { "dune ii - battle for arrakis (euro).bin", 0x100000, 0xb58ae71d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dune2) +STD_ROM_FN(md_dune2) + +struct BurnDriver BurnDrvmd_dune2 = { + "md_dune2", NULL, NULL, NULL, "1993", + "Dune II - Battle for Arrakis (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dune2RomInfo, md_dune2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dune II - Kampf um den Wustenplaneten (Ger) +static struct BurnRomInfo md_dune2gRomDesc[] = { + { "dune ii - kampf um den wustenplaneten (germany).bin", 0x100000, 0x39790728, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dune2g) +STD_ROM_FN(md_dune2g) + +struct BurnDriver BurnDrvmd_dune2g = { + "md_dune2g", "md_dune2", NULL, NULL, "1993", + "Dune II - Kampf um den Wustenplaneten (Ger)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dune2gRomInfo, md_dune2gRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dune - The Battle for Arrakis (USA) +static struct BurnRomInfo md_duneuRomDesc[] = { + { "dune - the battle for arrakis (usa).bin", 0x100000, 0x4dea40ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_duneu) +STD_ROM_FN(md_duneu) + +struct BurnDriver BurnDrvmd_duneu = { + "md_duneu", "md_dune2", NULL, NULL, "1993", + "Dune - The Battle for Arrakis (USA)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_duneuRomInfo, md_duneuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dungeons & Dragons - Warriors of the Eternal Sun (Euro, USA) +static struct BurnRomInfo md_ddwaresRomDesc[] = { + { "dungeons & dragons - warriors of the eternal sun (euro, usa).bin", 0x100000, 0xaf4a9cd7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddwares) +STD_ROM_FN(md_ddwares) + +struct BurnDriver BurnDrvmd_ddwares = { + "md_ddwares", NULL, NULL, NULL, "1992", + "Dungeons & Dragons - Warriors of the Eternal Sun (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ddwaresRomInfo, md_ddwaresRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dyna Brothers (Jpn) +static struct BurnRomInfo md_dynabrRomDesc[] = { + { "dyna brothers (jpn).bin", 0x100000, 0x360c1b20, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynabr) +STD_ROM_FN(md_dynabr) + +struct BurnDriver BurnDrvmd_dynabr = { + "md_dynabr", NULL, NULL, NULL, "1992", + "Dyna Brothers (Jpn)\0", NULL, "CRI", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dynabrRomInfo, md_dynabrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dyna Brothers 2 (Jpn) +static struct BurnRomInfo md_dynabr2RomDesc[] = { + { "dyna brothers 2 (jpn).bin", 0x200000, 0x47e0a64e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynabr2) +STD_ROM_FN(md_dynabr2) + +struct BurnDriver BurnDrvmd_dynabr2 = { + "md_dynabr2", NULL, NULL, NULL, "1993", + "Dyna Brothers 2 (Jpn)\0", NULL, "CRI", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dynabr2RomInfo, md_dynabr2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dyna Brothers 2 - Sega Channel Special (Jpn, Sega Channel) +static struct BurnRomInfo md_dynabr2spRomDesc[] = { + { "dyna brothers 2 - sega channel special (jpn).bin", 0x280000, 0xba3554bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynabr2sp) +STD_ROM_FN(md_dynabr2sp) + +struct BurnDriver BurnDrvmd_dynabr2sp = { + "md_dynabr2sp", "md_dynabr2", NULL, NULL, "1991", + "Dyna Brothers 2 - Sega Channel Special (Jpn, Sega Channel)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dynabr2spRomInfo, md_dynabr2spRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Duke (World, Rev. A) +static struct BurnRomInfo md_dyndukeRomDesc[] = { + { "mpr-13438a.bin", 0x080000, 0x246f0bda, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynduke) +STD_ROM_FN(md_dynduke) + +struct BurnDriver BurnDrvmd_dynduke = { + "md_dynduke", NULL, NULL, NULL, "1990", + "Dynamite Duke (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dyndukeRomInfo, md_dyndukeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Duke (World) +static struct BurnRomInfo md_dynduke1RomDesc[] = { + { "mpr-13438.bin", 0x080000, 0x39d01c8c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynduke1) +STD_ROM_FN(md_dynduke1) + +struct BurnDriver BurnDrvmd_dynduke1 = { + "md_dynduke1", "md_dynduke", NULL, NULL, "1990", + "Dynamite Duke (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dynduke1RomInfo, md_dynduke1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Euro, USA) +static struct BurnRomInfo md_dheadRomDesc[] = { + { "mpr-16990.bin", 0x200000, 0x3dfeeb77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dhead) +STD_ROM_FN(md_dhead) + +struct BurnDriver BurnDrvmd_dhead = { + "md_dhead", NULL, NULL, NULL, "1994", + "Dynamite Headdy (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadRomInfo, md_dheadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Jpn) +static struct BurnRomInfo md_dheadjRomDesc[] = { + { "dynamite headdy (jpn).bin", 0x200000, 0xd03cdb53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dheadj) +STD_ROM_FN(md_dheadj) + +struct BurnDriver BurnDrvmd_dheadj = { + "md_dheadj", "md_dhead", NULL, NULL, "1994", + "Dynamite Headdy (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadjRomInfo, md_dheadjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Jpn, Prototype) +static struct BurnRomInfo md_dheadjpRomDesc[] = { + { "dynamite headdy (jpn) (beta).bin", 0x200000, 0x5c25e934, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dheadjp) +STD_ROM_FN(md_dheadjp) + +struct BurnDriver BurnDrvmd_dheadjp = { + "md_dheadjp", "md_dhead", NULL, NULL, "1994", + "Dynamite Headdy (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadjpRomInfo, md_dheadjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Prototype, 19940614-CABEZA) +static struct BurnRomInfo md_dheadp3RomDesc[] = { + { "dynamite headdy (prototype - jun 14, 1994 - cabeza).bin", 0x200000, 0x971ef24c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dheadp3) +STD_ROM_FN(md_dheadp3) + +struct BurnDriver BurnDrvmd_dheadp3 = { + "md_dheadp3", "md_dhead", NULL, NULL, "1994", + "Dynamite Headdy (Prototype, 19940614-CABEZA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadp3RomInfo, md_dheadp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Prototype, 19940616) +static struct BurnRomInfo md_dheadp2RomDesc[] = { + { "dynamite headdy (prototype - jun 16, 1994).bin", 0x200000, 0xf8a96719, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dheadp2) +STD_ROM_FN(md_dheadp2) + +struct BurnDriver BurnDrvmd_dheadp2 = { + "md_dheadp2", "md_dhead", NULL, NULL, "1994", + "Dynamite Headdy (Prototype, 19940616)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadp2RomInfo, md_dheadp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dynamite Headdy (Prototype, 19940622) +static struct BurnRomInfo md_dheadp1RomDesc[] = { + { "dynamite headdy (prototype - jun 22, 1994).bin", 0x200000, 0x61001ec8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dheadp1) +STD_ROM_FN(md_dheadp1) + +struct BurnDriver BurnDrvmd_dheadp1 = { + "md_dheadp1", "md_dhead", NULL, NULL, "1994", + "Dynamite Headdy (Prototype, 19940622)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dheadp1RomInfo, md_dheadp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// EA Hockey (Euro) +static struct BurnRomInfo md_eahockeyRomDesc[] = { + { "ea hockey (euro).bin", 0x080000, 0x9bfc279c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eahockey) +STD_ROM_FN(md_eahockey) + +struct BurnDriver BurnDrvmd_eahockey = { + "md_eahockey", NULL, NULL, NULL, "1991", + "EA Hockey (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eahockeyRomInfo, md_eahockeyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// EA Hockey (Jpn) +static struct BurnRomInfo md_eahockeyjRomDesc[] = { + { "ea hockey (jpn).bin", 0x080000, 0x9dcdc894, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eahockeyj) +STD_ROM_FN(md_eahockeyj) + +struct BurnDriver BurnDrvmd_eahockeyj = { + "md_eahockeyj", "md_eahockey", NULL, NULL, "1992", + "EA Hockey (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eahockeyjRomInfo, md_eahockeyjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL Hockey (USA) +static struct BurnRomInfo md_nhlhocRomDesc[] = { + { "nhl hockey (usa).bin", 0x080000, 0x2641653f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlhoc) +STD_ROM_FN(md_nhlhoc) + +struct BurnDriver BurnDrvmd_nhlhoc = { + "md_nhlhoc", NULL, NULL, NULL, "1991", + "NHL Hockey (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlhocRomInfo, md_nhlhocRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// EA Sports Double Header (Euro) +static struct BurnRomInfo md_easportsRomDesc[] = { + { "ea304.bin", 0x100000, 0xa0b54cbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_easports) +STD_ROM_FN(md_easports) + +struct BurnDriver BurnDrvmd_easports = { + "md_easports", NULL, NULL, NULL, "1993", + "EA Sports Double Header (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_easportsRomInfo, md_easportsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earnest Evans (USA) +static struct BurnRomInfo md_earnestRomDesc[] = { + { "earnest evans (usa).bin", 0x100000, 0xa243816d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_earnest) +STD_ROM_FN(md_earnest) + +struct BurnDriver BurnDrvmd_earnest = { + "md_earnest", NULL, NULL, NULL, "1992", + "Earnest Evans (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_earnestRomInfo, md_earnestRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earthworm Jim (Euro) +static struct BurnRomInfo md_ejimRomDesc[] = { + { "earthworm jim (euro).bin", 0x300000, 0x1c07b337, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ejim) +STD_ROM_FN(md_ejim) + +struct BurnDriver BurnDrvmd_ejim = { + "md_ejim", NULL, NULL, NULL, "1994", + "Earthworm Jim (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ejimRomInfo, md_ejimRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earthworm Jim (USA) +static struct BurnRomInfo md_ejimuRomDesc[] = { + { "earthworm jim (usa).bin", 0x300000, 0xdf3acf59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ejimu) +STD_ROM_FN(md_ejimu) + +struct BurnDriver BurnDrvmd_ejimu = { + "md_ejimu", "md_ejim", NULL, NULL, "1994", + "Earthworm Jim (USA)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ejimuRomInfo, md_ejimuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earthworm Jim 2 (Euro) +static struct BurnRomInfo md_ejim2RomDesc[] = { + { "earthworm jim 2 (euro).bin", 0x300000, 0xaf235fdf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ejim2) +STD_ROM_FN(md_ejim2) + +struct BurnDriver BurnDrvmd_ejim2 = { + "md_ejim2", NULL, NULL, NULL, "1995", + "Earthworm Jim 2 (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ejim2RomInfo, md_ejim2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earthworm Jim 2 (USA) +static struct BurnRomInfo md_ejim2uRomDesc[] = { + { "earthworm jim 2 (usa).bin", 0x300000, 0xd57f8ba7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ejim2u) +STD_ROM_FN(md_ejim2u) + +struct BurnDriver BurnDrvmd_ejim2u = { + "md_ejim2u", "md_ejim2", NULL, NULL, "1996", + "Earthworm Jim 2 (USA)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ejim2uRomInfo, md_ejim2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco the Dolphin (Euro, USA, Kor) +static struct BurnRomInfo md_eccoRomDesc[] = { + { "mpr-15265.bin", 0x100000, 0x45547390, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco) +STD_ROM_FN(md_ecco) + +struct BurnDriver BurnDrvmd_ecco = { + "md_ecco", NULL, NULL, NULL, "1993", + "Ecco the Dolphin (Euro, USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eccoRomInfo, md_eccoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco the Dolphin (Jpn) +static struct BurnRomInfo md_eccojRomDesc[] = { + { "mpr-15702.bin", 0x100000, 0x6520304d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eccoj) +STD_ROM_FN(md_eccoj) + +struct BurnDriver BurnDrvmd_eccoj = { + "md_eccoj", "md_ecco", NULL, NULL, "1993", + "Ecco the Dolphin (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eccojRomInfo, md_eccojRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (Euro) +static struct BurnRomInfo md_ecco2RomDesc[] = { + { "ecco - the tides of time (euro).bin", 0x200000, 0x7b1bf89c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2) +STD_ROM_FN(md_ecco2) + +struct BurnDriver BurnDrvmd_ecco2 = { + "md_ecco2", NULL, NULL, NULL, "1994", + "Ecco - The Tides of Time (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2RomInfo, md_ecco2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (Prototype) +static struct BurnRomInfo md_ecco2pRomDesc[] = { + { "ecco - the tides of time (beta).bin", 0x200000, 0x8db60749, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2p) +STD_ROM_FN(md_ecco2p) + +struct BurnDriver BurnDrvmd_ecco2p = { + "md_ecco2p", "md_ecco2", NULL, NULL, "1994", + "Ecco - The Tides of Time (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2pRomInfo, md_ecco2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (Prototype, Alt) +static struct BurnRomInfo md_ecco2p1RomDesc[] = { + { "ecco - the tides of time (beta, alt).bin", 0x200000, 0x1d1470ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2p1) +STD_ROM_FN(md_ecco2p1) + +struct BurnDriver BurnDrvmd_ecco2p1 = { + "md_ecco2p1", "md_ecco2", NULL, NULL, "1994", + "Ecco - The Tides of Time (Prototype, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2p1RomInfo, md_ecco2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (Prototype, 19940429) +static struct BurnRomInfo md_ecco2p2RomDesc[] = { + { "ecco ii - the tides of time (prototype - apr 29, 1994).bin", 0x200000, 0x5af83ecb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2p2) +STD_ROM_FN(md_ecco2p2) + +struct BurnDriver BurnDrvmd_ecco2p2 = { + "md_ecco2p2", "md_ecco2", NULL, NULL, "1994", + "Ecco - The Tides of Time (Prototype, 19940429)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2p2RomInfo, md_ecco2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco the Dolphin II (Jpn) +static struct BurnRomInfo md_ecco2jRomDesc[] = { + { "mpr-16996.bin", 0x200000, 0x062d439c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2j) +STD_ROM_FN(md_ecco2j) + +struct BurnDriver BurnDrvmd_ecco2j = { + "md_ecco2j", "md_ecco2", NULL, NULL, "1994", + "Ecco the Dolphin II (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2jRomInfo, md_ecco2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (Prototype X11, 19940413) +static struct BurnRomInfo md_ecco2px11RomDesc[] = { + { "ecco - the tides of time (prototype x11 - apr 13, 1994).bin", 0x200000, 0xb5d64817, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2px11) +STD_ROM_FN(md_ecco2px11) + +struct BurnDriver BurnDrvmd_ecco2px11 = { + "md_ecco2px11", "md_ecco2", NULL, NULL, "1994", + "Ecco - The Tides of Time (Prototype X11, 19940413)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2px11RomInfo, md_ecco2px11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco - The Tides of Time (USA) +static struct BurnRomInfo md_ecco2uRomDesc[] = { + { "ecco - the tides of time (usa).bin", 0x200000, 0xccb21f98, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ecco2u) +STD_ROM_FN(md_ecco2u) + +struct BurnDriver BurnDrvmd_ecco2u = { + "md_ecco2u", "md_ecco2", NULL, NULL, "1994", + "Ecco - The Tides of Time (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ecco2uRomInfo, md_ecco2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco Jr. (USA, Oceania, 199502) +static struct BurnRomInfo md_eccojrRomDesc[] = { + { "ecco jr. (usa, aus) (february 1995).bin", 0x100000, 0x6c6f4b89, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eccojr) +STD_ROM_FN(md_eccojr) + +struct BurnDriver BurnDrvmd_eccojr = { + "md_eccojr", NULL, NULL, NULL, "1995", + "Ecco Jr. (USA, Oceania, 199502)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eccojrRomInfo, md_eccojrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ecco Jr. (USA, Oceania, 199503) +static struct BurnRomInfo md_eccojr1RomDesc[] = { + { "ecco jr. (usa, aus) (march 1995).bin", 0x100000, 0x3c517975, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eccojr1) +STD_ROM_FN(md_eccojr1) + +struct BurnDriver BurnDrvmd_eccojr1 = { + "md_eccojr1", "md_eccojr", NULL, NULL, "1995", + "Ecco Jr. (USA, Oceania, 199503)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eccojr1RomInfo, md_eccojr1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// El Viento (USA) +static struct BurnRomInfo md_elvientRomDesc[] = { + { "mpr-14336.bin", 0x100000, 0x070a1ceb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elvient) +STD_ROM_FN(md_elvient) + +struct BurnDriver BurnDrvmd_elvient = { + "md_elvient", NULL, NULL, NULL, "1991", + "El Viento (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_elvientRomInfo, md_elvientRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// El Viento (Jpn) +static struct BurnRomInfo md_elvientjRomDesc[] = { + { "el viento (jpn).bin", 0x100000, 0x6091c36e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elvientj) +STD_ROM_FN(md_elvientj) + +struct BurnDriver BurnDrvmd_elvientj = { + "md_elvientj", "md_elvient", NULL, NULL, "1991", + "El Viento (Jpn)\0", NULL, "Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_elvientjRomInfo, md_elvientjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Elemental Master (USA) +static struct BurnRomInfo md_elemastRomDesc[] = { + { "elemental master (usa).bin", 0x080000, 0x390918c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elemast) +STD_ROM_FN(md_elemast) + +struct BurnDriver BurnDrvmd_elemast = { + "md_elemast", NULL, NULL, NULL, "1993", + "Elemental Master (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_elemastRomInfo, md_elemastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Elemental Master (Jpn) +static struct BurnRomInfo md_elemastjRomDesc[] = { + { "elemental master (jpn).bin", 0x080000, 0x5f553e29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elemastj) +STD_ROM_FN(md_elemastj) + +struct BurnDriver BurnDrvmd_elemastj = { + "md_elemastj", "md_elemast", NULL, NULL, "1990", + "Elemental Master (Jpn)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_elemastjRomInfo, md_elemastjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eliminate Down (Jpn) +static struct BurnRomInfo md_elimdownRomDesc[] = { + { "eliminate down (jpn).bin", 0x100000, 0x48467542, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elimdown) +STD_ROM_FN(md_elimdown) + +struct BurnDriver BurnDrvmd_elimdown = { + "md_elimdown", NULL, NULL, NULL, "1993", + "Eliminate Down (Jpn)\0", NULL, "Soft Vision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_elimdownRomInfo, md_elimdownRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Elitserien 95 (Swe) +static struct BurnRomInfo md_elit95RomDesc[] = { + { "swed9584.bin", 0x200000, 0xe10a25c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elit95) +STD_ROM_FN(md_elit95) + +struct BurnDriver BurnDrvmd_elit95 = { + "md_elit95", NULL, NULL, NULL, "1994", + "Elitserien 95 (Swe)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_elit95RomInfo, md_elit95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Elitserien 96 (Swe) +static struct BurnRomInfo md_elit96RomDesc[] = { + { "elitserien 96 (sweden).bin", 0x200000, 0x9821d0a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_elit96) +STD_ROM_FN(md_elit96) + +struct BurnDriver BurnDrvmd_elit96 = { + "md_elit96", NULL, NULL, NULL, "1995", + "Elitserien 96 (Swe)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_elit96RomInfo, md_elit96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Empire of Steel (Euro) +static struct BurnRomInfo md_empirestRomDesc[] = { + { "empire of steel (euro).bin", 0x100000, 0xe5517b77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_empirest) +STD_ROM_FN(md_empirest) + +struct BurnDriver BurnDrvmd_empirest = { + "md_empirest", NULL, NULL, NULL, "1992", + "Empire of Steel (Euro)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_empirestRomInfo, md_empirestRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Steel Empire (USA) +static struct BurnRomInfo md_steelempRomDesc[] = { + { "steel empire (usa).bin", 0x100000, 0xd0e7a0b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_steelemp) +STD_ROM_FN(md_steelemp) + +struct BurnDriver BurnDrvmd_steelemp = { + "md_steelemp", "md_empirest", NULL, NULL, "1992", + "Steel Empire (USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_steelempRomInfo, md_steelempRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Koutetsu Teikoku (Jpn) +static struct BurnRomInfo md_koutetsuRomDesc[] = { + { "koutetsu teikoku (jpn).bin", 0x100000, 0x755d0b8a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_koutetsu) +STD_ROM_FN(md_koutetsu) + +struct BurnDriver BurnDrvmd_koutetsu = { + "md_koutetsu", "md_empirest", NULL, NULL, "1992", + "Koutetsu Teikoku (Jpn)\0", NULL, "Hot-B", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_koutetsuRomInfo, md_koutetsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Euro) +static struct BurnRomInfo md_tazemRomDesc[] = { + { "taz in escape from mars (euro).bin", 0x200000, 0x62100099, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazem) +STD_ROM_FN(md_tazem) + +struct BurnDriver BurnDrvmd_tazem = { + "md_tazem", NULL, NULL, NULL, "1994", + "Taz in Escape from Mars (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemRomInfo, md_tazemRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940418) +static struct BurnRomInfo md_tazemp10RomDesc[] = { + { "taz in escape from mars (prototype - apr 18, 1994).bin", 0x200000, 0xbfa776ec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp10) +STD_ROM_FN(md_tazemp10) + +struct BurnDriver BurnDrvmd_tazemp10 = { + "md_tazemp10", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940418)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp10RomInfo, md_tazemp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940602) +static struct BurnRomInfo md_tazemp06RomDesc[] = { + { "taz in escape from mars (prototype - jun 02, 1994).bin", 0x200000, 0x39f345c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp06) +STD_ROM_FN(md_tazemp06) + +struct BurnDriver BurnDrvmd_tazemp06 = { + "md_tazemp06", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940602)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp06RomInfo, md_tazemp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940607) +static struct BurnRomInfo md_tazemp05RomDesc[] = { + { "taz in escape from mars (prototype - jun 07, 1994).bin", 0x200000, 0x3481e709, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp05) +STD_ROM_FN(md_tazemp05) + +struct BurnDriver BurnDrvmd_tazemp05 = { + "md_tazemp05", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940607)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp05RomInfo, md_tazemp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940610) +static struct BurnRomInfo md_tazemp04RomDesc[] = { + { "taz in escape from mars (prototype - jun 10, 1994).bin", 0x200000, 0x832f4cb4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp04) +STD_ROM_FN(md_tazemp04) + +struct BurnDriver BurnDrvmd_tazemp04 = { + "md_tazemp04", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940610)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp04RomInfo, md_tazemp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940614) +static struct BurnRomInfo md_tazemp03RomDesc[] = { + { "taz in escape from mars (prototype - jun 14, 1994).bin", 0x200000, 0x2badb65b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp03) +STD_ROM_FN(md_tazemp03) + +struct BurnDriver BurnDrvmd_tazemp03 = { + "md_tazemp03", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940614)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp03RomInfo, md_tazemp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940618-A) +static struct BurnRomInfo md_tazemp02RomDesc[] = { + { "taz in escape from mars (prototype - jun 18, 1994 - a).bin", 0x200000, 0x3c4b1e9c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp02) +STD_ROM_FN(md_tazemp02) + +struct BurnDriver BurnDrvmd_tazemp02 = { + "md_tazemp02", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940618-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp02RomInfo, md_tazemp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940620) +static struct BurnRomInfo md_tazemp01RomDesc[] = { + { "taz in escape from mars (prototype - jun 20, 1994).bin", 0x200000, 0xf00f4203, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp01) +STD_ROM_FN(md_tazemp01) + +struct BurnDriver BurnDrvmd_tazemp01 = { + "md_tazemp01", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940620)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp01RomInfo, md_tazemp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940309) +static struct BurnRomInfo md_tazemp11RomDesc[] = { + { "taz in escape from mars (prototype - mar 09, 1994).bin", 0x1d9936, 0xe3c2271e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp11) +STD_ROM_FN(md_tazemp11) + +struct BurnDriver BurnDrvmd_tazemp11 = { + "md_tazemp11", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940309)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp11RomInfo, md_tazemp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940509) +static struct BurnRomInfo md_tazemp09RomDesc[] = { + { "taz in escape from mars (prototype - may 09, 1994).bin", 0x200000, 0x11727086, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp09) +STD_ROM_FN(md_tazemp09) + +struct BurnDriver BurnDrvmd_tazemp09 = { + "md_tazemp09", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940509)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp09RomInfo, md_tazemp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940518) +static struct BurnRomInfo md_tazemp08RomDesc[] = { + { "taz in escape from mars (prototype - may 18, 1994).bin", 0x0b9584, 0x6e2666de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp08) +STD_ROM_FN(md_tazemp08) + +struct BurnDriver BurnDrvmd_tazemp08 = { + "md_tazemp08", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940518)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp08RomInfo, md_tazemp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (Prototype, 19940523) +static struct BurnRomInfo md_tazemp07RomDesc[] = { + { "taz in escape from mars (prototype - may 23, 1994).bin", 0x200000, 0xea344fd2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemp07) +STD_ROM_FN(md_tazemp07) + +struct BurnDriver BurnDrvmd_tazemp07 = { + "md_tazemp07", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (Prototype, 19940523)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemp07RomInfo, md_tazemp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz in Escape from Mars (USA) +static struct BurnRomInfo md_tazemuRomDesc[] = { + { "taz in escape from mars (usa).bin", 0x200000, 0x62009f8c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazemu) +STD_ROM_FN(md_tazemu) + +struct BurnDriver BurnDrvmd_tazemu = { + "md_tazemu", "md_tazem", NULL, NULL, "1994", + "Taz in Escape from Mars (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazemuRomInfo, md_tazemuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN Baseball Tonight (USA) +static struct BurnRomInfo md_espnbbRomDesc[] = { + { "espn baseball tonight (usa).bin", 0x200000, 0x96d8440c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_espnbb) +STD_ROM_FN(md_espnbb) + +struct BurnDriver BurnDrvmd_espnbb = { + "md_espnbb", NULL, NULL, NULL, "1995", + "ESPN Baseball Tonight (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_espnbbRomInfo, md_espnbbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN National Hockey Night (USA) +static struct BurnRomInfo md_espnhnRomDesc[] = { + { "espn national hockey night (usa).bin", 0x200000, 0x1d08828c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_espnhn) +STD_ROM_FN(md_espnhn) + +struct BurnDriver BurnDrvmd_espnhn = { + "md_espnhn", NULL, NULL, NULL, "1994", + "ESPN National Hockey Night (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_espnhnRomInfo, md_espnhnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN National Hockey Night (USA, Prototype) +static struct BurnRomInfo md_espnhnpRomDesc[] = { + { "espn national hockey night (usa) (beta).bin", 0x200000, 0xa427814a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_espnhnp) +STD_ROM_FN(md_espnhnp) + +struct BurnDriver BurnDrvmd_espnhnp = { + "md_espnhnp", "md_espnhn", NULL, NULL, "1994", + "ESPN National Hockey Night (USA, Prototype)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_espnhnpRomInfo, md_espnhnpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN Speed World (USA) +static struct BurnRomInfo md_espnspRomDesc[] = { + { "espn speed world (usa).bin", 0x200000, 0xf50be478, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_espnsp) +STD_ROM_FN(md_espnsp) + +struct BurnDriver BurnDrvmd_espnsp = { + "md_espnsp", NULL, NULL, NULL, "1994", + "ESPN Speed World (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_espnspRomInfo, md_espnspRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// ESPN Sunday Night NFL (USA) +static struct BurnRomInfo md_espnnflRomDesc[] = { + { "espn sunday night nfl (usa).bin", 0x200000, 0x61e9c309, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_espnnfl) +STD_ROM_FN(md_espnnfl) + +struct BurnDriver BurnDrvmd_espnnfl = { + "md_espnnfl", NULL, NULL, NULL, "1994", + "ESPN Sunday Night NFL (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_espnnflRomInfo, md_espnnflRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Cyber Police ESWAT (Jpn, Rev. 0) +static struct BurnRomInfo md_eswatjRomDesc[] = { + { "mpr-13192.bin", 0x080000, 0x87b636a2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eswatj) +STD_ROM_FN(md_eswatj) + +struct BurnDriver BurnDrvmd_eswatj = { + "md_eswatj", "md_eswat", NULL, NULL, "1990", + "Cyber Police ESWAT (Jpn, Rev. 0)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eswatjRomInfo, md_eswatjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eternal Champions (Euro) +static struct BurnRomInfo md_eternalcRomDesc[] = { + { "mpr-16212+mpr-16213.bin", 0x300000, 0xb9512f5e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eternalc) +STD_ROM_FN(md_eternalc) + +struct BurnDriver BurnDrvmd_eternalc = { + "md_eternalc", NULL, NULL, NULL, "1994", + "Eternal Champions (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eternalcRomInfo, md_eternalcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eternal Champions (Euro, Prototype) +static struct BurnRomInfo md_eternalcbRomDesc[] = { + { "eternal champions (euro) (beta).bin", 0x300000, 0xe0665f06, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eternalcb) +STD_ROM_FN(md_eternalcb) + +struct BurnDriver BurnDrvmd_eternalcb = { + "md_eternalcb", "md_eternalc", NULL, NULL, "1994", + "Eternal Champions (Euro, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eternalcbRomInfo, md_eternalcbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eternal Champions (Jpn, Kor) +static struct BurnRomInfo md_eternalcjRomDesc[] = { + { "eternal champions (jpn, kor).bin", 0x300000, 0x66aa3c64, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eternalcj) +STD_ROM_FN(md_eternalcj) + +struct BurnDriver BurnDrvmd_eternalcj = { + "md_eternalcj", "md_eternalc", NULL, NULL, "1994", + "Eternal Champions (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eternalcjRomInfo, md_eternalcjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eternal Champions (Jpn, Prototype, 19931117) +static struct BurnRomInfo md_eternalcjpRomDesc[] = { + { "eternal champions (jpn) (prototype - nov 17, 1993).bin", 0x2ff4b0, 0xc486b439, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eternalcjp) +STD_ROM_FN(md_eternalcjp) + +struct BurnDriver BurnDrvmd_eternalcjp = { + "md_eternalcjp", "md_eternalc", NULL, NULL, "1994", + "Eternal Champions (Jpn, Prototype, 19931117)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eternalcjpRomInfo, md_eternalcjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Eternal Champions (USA) +static struct BurnRomInfo md_eternalcuRomDesc[] = { + { "eternal champions (usa).bin", 0x300000, 0x48f1a42e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_eternalcu) +STD_ROM_FN(md_eternalcu) + +struct BurnDriver BurnDrvmd_eternalcu = { + "md_eternalcu", "md_eternalc", NULL, NULL, "1994", + "Eternal Champions (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_eternalcuRomInfo, md_eternalcuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// European Club Soccer (Euro) +static struct BurnRomInfo md_euroclubRomDesc[] = { + { "mpr-14776.bin", 0x080000, 0x6a5cf104, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_euroclub) +STD_ROM_FN(md_euroclub) + +struct BurnDriver BurnDrvmd_euroclub = { + "md_euroclub", NULL, NULL, NULL, "1992", + "European Club Soccer (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_euroclubRomInfo, md_euroclubRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Trophy Soccer (USA) +static struct BurnRomInfo md_worldtsRomDesc[] = { + { "world trophy soccer (usa).bin", 0x080000, 0x6e3edc7c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worldts) +STD_ROM_FN(md_worldts) + +struct BurnDriver BurnDrvmd_worldts = { + "md_worldts", "md_euroclub", NULL, NULL, "1992", + "World Trophy Soccer (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_worldtsRomInfo, md_worldtsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// J. League Champion Soccer (Jpn) +static struct BurnRomInfo md_jlcsRomDesc[] = { + { "j. league champion soccer (jpn).bin", 0x080000, 0x453c405e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jlcs) +STD_ROM_FN(md_jlcs) + +struct BurnDriver BurnDrvmd_jlcs = { + "md_jlcs", "md_euroclub", NULL, NULL, "1993", + "J. League Champion Soccer (Jpn)\0", NULL, "Game Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jlcsRomInfo, md_jlcsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exile (USA) +static struct BurnRomInfo md_exileRomDesc[] = { + { "exile (usa).bin", 0x100000, 0x1b569dc2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exile) +STD_ROM_FN(md_exile) + +struct BurnDriver BurnDrvmd_exile = { + "md_exile", NULL, NULL, NULL, "1991", + "Exile (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_exileRomInfo, md_exileRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exile - Toki no Hazama e (Jpn) +static struct BurnRomInfo md_exilejRomDesc[] = { + { "exile - toki no hazama e (jpn).bin", 0x100000, 0x880bf311, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exilej) +STD_ROM_FN(md_exilej) + +struct BurnDriver BurnDrvmd_exilej = { + "md_exilej", "md_exile", NULL, NULL, "1991", + "Exile - Toki no Hazama e (Jpn)\0", NULL, "Riot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_exilejRomInfo, md_exilejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exo Squad (Euro) +static struct BurnRomInfo md_exosqRomDesc[] = { + { "exo squad (euro).bin", 0x100000, 0xb599b9f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exosq) +STD_ROM_FN(md_exosq) + +struct BurnDriver BurnDrvmd_exosq = { + "md_exosq", NULL, NULL, NULL, "1995", + "Exo Squad (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exosqRomInfo, md_exosqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exo Squad (USA) +static struct BurnRomInfo md_exosquRomDesc[] = { + { "exo squad (usa).bin", 0x100000, 0x10ec03f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exosqu) +STD_ROM_FN(md_exosqu) + +struct BurnDriver BurnDrvmd_exosqu = { + "md_exosqu", "md_exosq", NULL, NULL, "1995", + "Exo Squad (USA)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exosquRomInfo, md_exosquRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exo Squad (USA, Prototype) +static struct BurnRomInfo md_exosqupRomDesc[] = { + { "exo squad (usa) (beta).bin", 0x100000, 0x70edf964, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exosqup) +STD_ROM_FN(md_exosqup) + +struct BurnDriver BurnDrvmd_exosqup = { + "md_exosqup", "md_exosq", NULL, NULL, "1995", + "Exo Squad (USA, Prototype)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exosqupRomInfo, md_exosqupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Exodus - Journey to the Promised Land (USA) +static struct BurnRomInfo md_exodusRomDesc[] = { + { "exodus - journey to the promised land (usa) (unl).bin", 0x080000, 0x22e6fc04, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exodus) +STD_ROM_FN(md_exodus) + +struct BurnDriver BurnDrvmd_exodus = { + "md_exodus", NULL, NULL, NULL, "1993", + "Exodus - Journey to the Promised Land (USA)\0", NULL, "Wisdom Tree", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exodusRomInfo, md_exodusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-117 Night Storm (Euro, USA) +static struct BurnRomInfo md_f117RomDesc[] = { + { "f-117 night storm (euro, usa).bin", 0x200000, 0x1bf67a07, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f117) +STD_ROM_FN(md_f117) + +struct BurnDriver BurnDrvmd_f117 = { + "md_f117", NULL, NULL, NULL, "1993", + "F-117 Night Storm (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f117RomInfo, md_f117RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-117 Stealth - Operation Night Storm (Jpn) +static struct BurnRomInfo md_f117jRomDesc[] = { + { "f-117 stealth - operation night storm (jpn).bin", 0x200000, 0xea6e421a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f117j) +STD_ROM_FN(md_f117j) + +struct BurnDriver BurnDrvmd_f117j = { + "md_f117j", "md_f117", NULL, NULL, "1994", + "F-117 Stealth - Operation Night Storm (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f117jRomInfo, md_f117jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-15 Strike Eagle II (Euro) +static struct BurnRomInfo md_f15strRomDesc[] = { + { "f-15 strike eagle ii (euro).bin", 0x100000, 0xe98ee370, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f15str) +STD_ROM_FN(md_f15str) + +struct BurnDriver BurnDrvmd_f15str = { + "md_f15str", NULL, NULL, NULL, "1993", + "F-15 Strike Eagle II (Euro)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f15strRomInfo, md_f15strRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-15 Strike Eagle II (USA) +static struct BurnRomInfo md_f15struRomDesc[] = { + { "f-15 strike eagle ii (usa).bin", 0x100000, 0x412c4d60, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f15stru) +STD_ROM_FN(md_f15stru) + +struct BurnDriver BurnDrvmd_f15stru = { + "md_f15stru", "md_f15str", NULL, NULL, "1993", + "F-15 Strike Eagle II (USA)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f15struRomInfo, md_f15struRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-15 Strike Eagle II (USA, Prototype) +static struct BurnRomInfo md_f15strupRomDesc[] = { + { "f-15 strike eagle ii (usa) (beta).bin", 0x100000, 0xfd4f5a01, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f15strup) +STD_ROM_FN(md_f15strup) + +struct BurnDriver BurnDrvmd_f15strup = { + "md_f15strup", "md_f15str", NULL, NULL, "1993", + "F-15 Strike Eagle II (USA, Prototype)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f15strupRomInfo, md_f15strupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-22 Interceptor (Euro, USA, 199206) +static struct BurnRomInfo md_f22RomDesc[] = { + { "f-22 interceptor (euro, usa) (june 1992).bin", 0x0c0000, 0xdd19b2b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f22) +STD_ROM_FN(md_f22) + +struct BurnDriver BurnDrvmd_f22 = { + "md_f22", NULL, NULL, NULL, "1991", + "F-22 Interceptor (Euro, USA, 199206)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f22RomInfo, md_f22RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-22 Interceptor (Euro, USA, Prototype) +static struct BurnRomInfo md_f22pRomDesc[] = { + { "f-22 interceptor (euro, usa) (beta).bin", 0x0c0000, 0xd6a880a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f22p) +STD_ROM_FN(md_f22p) + +struct BurnDriver BurnDrvmd_f22p = { + "md_f22p", "md_f22", NULL, NULL, "1991", + "F-22 Interceptor (Euro, USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f22pRomInfo, md_f22pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F-22 Interceptor (Jpn) +static struct BurnRomInfo md_f22jRomDesc[] = { + { "f-22 interceptor (jpn).bin", 0x0c0000, 0xfb55c785, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f22j) +STD_ROM_FN(md_f22j) + +struct BurnDriver BurnDrvmd_f22j = { + "md_f22j", "md_f22", NULL, NULL, "1993", + "F-22 Interceptor (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f22jRomInfo, md_f22jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F1 (Euro) +static struct BurnRomInfo md_f1RomDesc[] = { + { "mpr-15834.bin", 0x100000, 0xfbdd4520, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f1) +STD_ROM_FN(md_f1) + +struct BurnDriver BurnDrvmd_f1 = { + "md_f1", NULL, NULL, NULL, "1993", + "F1 (Euro)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_f1RomInfo, md_f1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Formula One (USA) +static struct BurnRomInfo md_formula1RomDesc[] = { + { "formula one (usa).bin", 0x100000, 0xccd73738, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_formula1) +STD_ROM_FN(md_formula1) + +struct BurnDriver BurnDrvmd_formula1 = { + "md_formula1", "md_f1", NULL, NULL, "1993", + "Formula One (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_formula1RomInfo, md_formula1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F1 - World Championship Edition (Euro) +static struct BurnRomInfo md_f1wcRomDesc[] = { + { "f1 - world championship edition (euro).bin", 0x200000, 0x74cee0a7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f1wc) +STD_ROM_FN(md_f1wc) + +struct BurnDriver BurnDrvmd_f1wc = { + "md_f1wc", NULL, NULL, NULL, "1993", + "F1 - World Championship Edition (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f1wcRomInfo, md_f1wcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F1 - World Championship Edition (Euro, Prototype) +static struct BurnRomInfo md_f1wcpRomDesc[] = { + { "f1 - world championship edition (euro) (beta).bin", 0x200000, 0x2269ed6b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f1wcp) +STD_ROM_FN(md_f1wcp) + +struct BurnDriver BurnDrvmd_f1wcp = { + "md_f1wcp", "md_f1wc", NULL, NULL, "1993", + "F1 - World Championship Edition (Euro, Prototype)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_f1wcpRomInfo, md_f1wcpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// F1 Circus MD (Jpn) +static struct BurnRomInfo md_f1circusRomDesc[] = { + { "f1 circus md (jpn).bin", 0x080000, 0x5d30befb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_f1circus) +STD_ROM_FN(md_f1circus) + +struct BurnDriver BurnDrvmd_f1circus = { + "md_f1circus", NULL, NULL, NULL, "1991", + "F1 Circus MD (Jpn)\0", NULL, "Nichibutsu", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_f1circusRomInfo, md_f1circusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Faery Tale Adventure (Euro, USA) +static struct BurnRomInfo md_faerytalRomDesc[] = { + { "faery tale adventure, the (euro, usa).bin", 0x080000, 0x963f4969, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_faerytal) +STD_ROM_FN(md_faerytal) + +struct BurnDriver BurnDrvmd_faerytal = { + "md_faerytal", NULL, NULL, NULL, "1991", + "The Faery Tale Adventure (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_faerytalRomInfo, md_faerytalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Family Feud (USA) +static struct BurnRomInfo md_famfeudRomDesc[] = { + { "family feud (usa).bin", 0x080000, 0x1aa628b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_famfeud) +STD_ROM_FN(md_famfeud) + +struct BurnDriver BurnDrvmd_famfeud = { + "md_famfeud", NULL, NULL, NULL, "1993", + "Family Feud (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_famfeudRomInfo, md_famfeudRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fantasia (World, Rev. A) +static struct BurnRomInfo md_fantasiaRomDesc[] = { + { "mpr-14028a.bin", 0x080000, 0xfc43df2d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fantasia) +STD_ROM_FN(md_fantasia) + +struct BurnDriver BurnDrvmd_fantasia = { + "md_fantasia", NULL, NULL, NULL, "1991", + "Fantasia (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fantasiaRomInfo, md_fantasiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fantasia (World) +static struct BurnRomInfo md_fantasia1RomDesc[] = { + { "mpr-14028.bin", 0x080000, 0xd351b242, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fantasia1) +STD_ROM_FN(md_fantasia1) + +struct BurnDriver BurnDrvmd_fantasia1 = { + "md_fantasia1", "md_fantasia", NULL, NULL, "1991", + "Fantasia (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fantasia1RomInfo, md_fantasia1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fantastic Dizzy (Euro, USA) +static struct BurnRomInfo md_fantdizRomDesc[] = { + { "fantastic dizzy (euro, usa).bin", 0x080000, 0x46447e7a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fantdiz) +STD_ROM_FN(md_fantdiz) + +struct BurnDriver BurnDrvmd_fantdiz = { + "md_fantdiz", NULL, NULL, NULL, "1991", + "Fantastic Dizzy (Euro, USA)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fantdizRomInfo, md_fantdizRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fantastic Dizzy (Euro, USA, Alt) +static struct BurnRomInfo md_fantdiz1RomDesc[] = { + { "fantastic dizzy (euro, usa) (alt).bin", 0x080000, 0x86b2a235, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fantdiz1) +STD_ROM_FN(md_fantdiz1) + +struct BurnDriver BurnDrvmd_fantdiz1 = { + "md_fantdiz1", "md_fantdiz", NULL, NULL, "1991", + "Fantastic Dizzy (Euro, USA, Alt)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fantdiz1RomInfo, md_fantdiz1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fastest 1 (Jpn) +static struct BurnRomInfo md_fastest1RomDesc[] = { + { "fastest 1 (jpn).bin", 0x080000, 0xbb43f0de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fastest1) +STD_ROM_FN(md_fastest1) + +struct BurnDriver BurnDrvmd_fastest1 = { + "md_fastest1", NULL, NULL, NULL, "1991", + "Fastest 1 (Jpn)\0", NULL, "Human Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_fastest1RomInfo, md_fastest1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatal Fury (Euro, Kor) +static struct BurnRomInfo md_fatfuryRomDesc[] = { + { "fatal fury (euro, kor).bin", 0x180000, 0x2e730a91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatfury) +STD_ROM_FN(md_fatfury) + +struct BurnDriver BurnDrvmd_fatfury = { + "md_fatfury", NULL, NULL, NULL, "1993", + "Fatal Fury (Euro, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatfuryRomInfo, md_fatfuryRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatal Fury (USA) +static struct BurnRomInfo md_fatfuryuRomDesc[] = { + { "fatal fury (usa).bin", 0x180000, 0x98d49170, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatfuryu) +STD_ROM_FN(md_fatfuryu) + +struct BurnDriver BurnDrvmd_fatfuryu = { + "md_fatfuryu", "md_fatfury", NULL, NULL, "1993", + "Fatal Fury (USA)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatfuryuRomInfo, md_fatfuryuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Garou Densetsu - Shukumei no Tatakai (Jpn) +static struct BurnRomInfo md_garouRomDesc[] = { + { "garou densetsu - shukumei no tatakai (jpn).bin", 0x180000, 0xbf3e3fa4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_garou) +STD_ROM_FN(md_garou) + +struct BurnDriver BurnDrvmd_garou = { + "md_garou", "md_fatfury", NULL, NULL, "1993", + "Garou Densetsu - Shukumei no Tatakai (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_garouRomInfo, md_garouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatal Fury 2 (USA, Kor) +static struct BurnRomInfo md_fatfury2RomDesc[] = { + { "fatal fury 2 (usa, kor).bin", 0x300000, 0x1b1754cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatfury2) +STD_ROM_FN(md_fatfury2) + +struct BurnDriver BurnDrvmd_fatfury2 = { + "md_fatfury2", NULL, NULL, NULL, "1994", + "Fatal Fury 2 (USA, Kor)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatfury2RomInfo, md_fatfury2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Garou Densetsu 2 - Aratanaru Tatakai (Jpn) +static struct BurnRomInfo md_garou2RomDesc[] = { + { "mpr-16704+mpr-16710.bin", 0x300000, 0x2af4427f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_garou2) +STD_ROM_FN(md_garou2) + +struct BurnDriver BurnDrvmd_garou2 = { + "md_garou2", "md_fatfury2", NULL, NULL, "1994", + "Garou Densetsu 2 - Aratanaru Tatakai (Jpn)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_garou2RomInfo, md_garou2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatal Labyrinth (Euro, USA) +static struct BurnRomInfo md_fatallabRomDesc[] = { + { "fatal labyrinth (euro, usa).bin", 0x020000, 0x5f0bd984, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatallab) +STD_ROM_FN(md_fatallab) + +struct BurnDriver BurnDrvmd_fatallab = { + "md_fatallab", NULL, NULL, NULL, "1991", + "Fatal Labyrinth (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatallabRomInfo, md_fatallabRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi no Meikyuu - Labyrinth of Death (Jpn, SegaNet) +static struct BurnRomInfo md_labdeathRomDesc[] = { + { "shi no meikyuu - labyrinth of death (jpn) (sn).bin", 0x040000, 0xa6d7e02d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_labdeath) +STD_ROM_FN(md_labdeath) + +struct BurnDriver BurnDrvmd_labdeath = { + "md_labdeath", "md_fatallab", NULL, NULL, "1991", + "Shi no Meikyuu - Labyrinth of Death (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_labdeathRomInfo, md_labdeathRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi no Meikyuu - Labyrinth of Death (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_labdeathgnkRomDesc[] = { + { "shi no meikyuu - labyrinth of death (jpn) (gnk).bin", 0x020000, 0x40c44cd3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_labdeathgnk) +STD_ROM_FN(md_labdeathgnk) + +struct BurnDriver BurnDrvmd_labdeathgnk = { + "md_labdeathgnk", "md_fatallab", NULL, NULL, "1991", + "Shi no Meikyuu - Labyrinth of Death (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_labdeathgnkRomInfo, md_labdeathgnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatal Rewind (Euro, USA) +static struct BurnRomInfo md_fatalrewRomDesc[] = { + { "fatal rewind (euro, usa).bin", 0x080000, 0xe91aed05, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatalrew) +STD_ROM_FN(md_fatalrew) + +struct BurnDriver BurnDrvmd_fatalrew = { + "md_fatalrew", NULL, NULL, NULL, "1991", + "Fatal Rewind (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatalrewRomInfo, md_fatalrewRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Killing Game Show (Jpn) +static struct BurnRomInfo md_killshowRomDesc[] = { + { "killing game show, the (jpn).bin", 0x100000, 0xb8e7668a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_killshow) +STD_ROM_FN(md_killshow) + +struct BurnDriver BurnDrvmd_killshow = { + "md_killshow", "md_fatalrew", NULL, NULL, "1993", + "The Killing Game Show (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_killshowRomInfo, md_killshowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Feng Kuang Tao Hua Yuan (Chi) +static struct BurnRomInfo md_fengkuRomDesc[] = { + { "feng kuang tao hua yuan (chi) (unl).bin", 0x100000, 0x8d40d64f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fengku) +STD_ROM_FN(md_fengku) + +struct BurnDriver BurnDrvmd_fengku = { + "md_fengku", NULL, NULL, NULL, "199?", + "Feng Kuang Tao Hua Yuan (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fengkuRomInfo, md_fengkuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Feng Shen Ying Jie Chuan (Chi) +static struct BurnRomInfo md_fengshRomDesc[] = { + { "feng shen ying jie chuan (chi) (unl).bin", 0x200000, 0x6a382b60, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fengsh) +STD_ROM_FN(md_fengsh) + +struct BurnDriver BurnDrvmd_fengsh = { + "md_fengsh", NULL, NULL, NULL, "1996", + "Feng Shen Ying Jie Chuan (Chi)\0", NULL, "Chuanpu Technologies", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fengshRomInfo, md_fengshRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Férias Frustradas do Pica-Pau (Bra) +static struct BurnRomInfo md_feriasRomDesc[] = { + { "ferias frustradas do pica-pau (bra).bin", 0x100000, 0x7b2e416d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ferias) +STD_ROM_FN(md_ferias) + +struct BurnDriver BurnDrvmd_ferias = { + "md_ferias", NULL, NULL, NULL, "1995", + "Ferias Frustradas do Pica-Pau (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + L"F\u00e9rias Frustradas do Pica-Pau (Bra)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_feriasRomInfo, md_feriasRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ferrari Grand Prix Challenge (Prototype) +static struct BurnRomInfo md_ferraripRomDesc[] = { + { "ferrari grand prix challenge (beta).bin", 0x100000, 0xd48d02d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ferrarip) +STD_ROM_FN(md_ferrarip) + +struct BurnDriver BurnDrvmd_ferrarip = { + "md_ferrarip", "md_ferrari", NULL, NULL, "1992", + "Ferrari Grand Prix Challenge (Prototype)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ferraripRomInfo, md_ferraripRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ferrari Grand Prix Challenge (USA) +static struct BurnRomInfo md_ferrariuRomDesc[] = { + { "ferrari grand prix challenge (usa).bin", 0x100000, 0xf73f6bec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ferrariu) +STD_ROM_FN(md_ferrariu) + +struct BurnDriver BurnDrvmd_ferrariu = { + "md_ferrariu", "md_ferrari", NULL, NULL, "1992", + "Ferrari Grand Prix Challenge (USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ferrariuRomInfo, md_ferrariuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fever Pitch Soccer (Euro) +static struct BurnRomInfo md_feverpRomDesc[] = { + { "fever pitch soccer (euro).bin", 0x200000, 0xfac29677, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_feverp) +STD_ROM_FN(md_feverp) + +struct BurnDriver BurnDrvmd_feverp = { + "md_feverp", NULL, NULL, NULL, "1995", + "Fever Pitch Soccer (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_feverpRomInfo, md_feverpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Head-On Soccer (USA) +static struct BurnRomInfo md_headonRomDesc[] = { + { "head-on soccer (usa).bin", 0x200000, 0xdcffa327, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_headon) +STD_ROM_FN(md_headon) + +struct BurnDriver BurnDrvmd_headon = { + "md_headon", "md_feverp", NULL, NULL, "1995", + "Head-On Soccer (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_headonRomInfo, md_headonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fido Dido (USA, Prototype) +static struct BurnRomInfo md_fidodidoRomDesc[] = { + { "fido dido (usa) (prototype).bin", 0x100000, 0xc6d4a240, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fidodido) +STD_ROM_FN(md_fidodido) + +struct BurnDriver BurnDrvmd_fidodido = { + "md_fidodido", NULL, NULL, NULL, "1994", + "Fido Dido (USA, Prototype)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fidodidoRomInfo, md_fidodidoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA International Soccer (Euro, USA) +static struct BurnRomInfo md_fifaRomDesc[] = { + { "soccer10.bin", 0x200000, 0xbddbb763, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa) +STD_ROM_FN(md_fifa) + +struct BurnDriver BurnDrvmd_fifa = { + "md_fifa", NULL, NULL, NULL, "1994", + "FIFA International Soccer (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifaRomInfo, md_fifaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA Soccer 95 (Euro, USA) +static struct BurnRomInfo md_fifa95RomDesc[] = { + { "fifa95b1.bin", 0x200000, 0xb389d036, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa95) +STD_ROM_FN(md_fifa95) + +struct BurnDriver BurnDrvmd_fifa95 = { + "md_fifa95", NULL, NULL, NULL, "1994", + "FIFA Soccer 95 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_fifa95RomInfo, md_fifa95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Futbol Argentino 98 - Pasion de Multitudes (Pirate) +static struct BurnRomInfo md_futbolRomDesc[] = { + { "futbol argentino 98 - pasion de multitudes (unl).bin", 0x200000, 0x5c015888, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_futbol) +STD_ROM_FN(md_futbol) + +struct BurnDriver BurnDrvmd_futbol = { + "md_futbol", "md_fifa95", NULL, NULL, "199?", + "Futbol Argentino 98 - Pasion de Multitudes (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_futbolRomInfo, md_futbolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA Soccer 96 (Euro, USA) +static struct BurnRomInfo md_fifa96RomDesc[] = { + { "fifa01.bin", 0x200000, 0xbad30ffa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa96) +STD_ROM_FN(md_fifa96) + +struct BurnDriver BurnDrvmd_fifa96 = { + "md_fifa96", NULL, NULL, NULL, "1995", + "FIFA Soccer 96 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_fifa96RomInfo, md_fifa96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA Soccer 99 (Pirate) +static struct BurnRomInfo md_fifa99RomDesc[] = { + { "fifa soccer 99 (pirate) (unl).bin", 0x200000, 0xc5c5a4b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa99) +STD_ROM_FN(md_fifa99) + +struct BurnDriver BurnDrvmd_fifa99 = { + "md_fifa99", "md_fifa96", NULL, NULL, "199?", + "FIFA Soccer 99 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_fifa99RomInfo, md_fifa99RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA Soccer 2000 Gold Edition (Pirate) +static struct BurnRomInfo md_fifa2kRomDesc[] = { + { "fifa soccer 2000 gold edition (pirate) (unl).bin", 0x200000, 0x647df504, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa2k) +STD_ROM_FN(md_fifa2k) + +struct BurnDriver BurnDrvmd_fifa2k = { + "md_fifa2k", "md_fifa97", NULL, NULL, "199?", + "FIFA Soccer 2000 Gold Edition (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa2kRomInfo, md_fifa2kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA 98 - Road to World Cup (Euro) +static struct BurnRomInfo md_fifa98RomDesc[] = { + { "fifa 98 - road to world cup (euro).bin", 0x200000, 0x96947f57, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa98) +STD_ROM_FN(md_fifa98) + +struct BurnDriver BurnDrvmd_fifa98 = { + "md_fifa98", NULL, NULL, NULL, "1997", + "FIFA 98 - Road to World Cup (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_fifa98RomInfo, md_fifa98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fighting Masters (USA) +static struct BurnRomInfo md_fightmRomDesc[] = { + { "fighting masters (usa).bin", 0x080000, 0x5f51983b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fightm) +STD_ROM_FN(md_fightm) + +struct BurnDriver BurnDrvmd_fightm = { + "md_fightm", NULL, NULL, NULL, "1992", + "Fighting Masters (USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fightmRomInfo, md_fightmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fighting Masters (Jpn, Kor) +static struct BurnRomInfo md_fightmjRomDesc[] = { + { "fighting masters (jpn, kor).bin", 0x080000, 0x39be80ec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fightmj) +STD_ROM_FN(md_fightmj) + +struct BurnDriver BurnDrvmd_fightmj = { + "md_fightmj", "md_fightm", NULL, NULL, "1991", + "Fighting Masters (Jpn, Kor)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fightmjRomInfo, md_fightmjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Final Zone (USA) ~ FZ Senki Axis (Jpn) +static struct BurnRomInfo md_finalzonRomDesc[] = { + { "final zone -- fz senki axis (usa, jpn).bin", 0x080000, 0x731fa4a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_finalzon) +STD_ROM_FN(md_finalzon) + +struct BurnDriver BurnDrvmd_finalzon = { + "md_finalzon", NULL, NULL, NULL, "1990", + "Final Zone (USA) ~ FZ Senki Axis (Jpn)\0", NULL, "Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_finalzonRomInfo, md_finalzonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fire Mustang (Jpn) +static struct BurnRomInfo md_firemustRomDesc[] = { + { "fire mustang (jpn).bin", 0x080000, 0xeb7e36c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_firemust) +STD_ROM_FN(md_firemust) + +struct BurnDriver BurnDrvmd_firemust = { + "md_firemust", NULL, NULL, NULL, "1991", + "Fire Mustang (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_firemustRomInfo, md_firemustRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fire Shark (Euro) +static struct BurnRomInfo md_fireshrkRomDesc[] = { + { "mpr-14341.bin", 0x080000, 0x2351ce61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fireshrk) +STD_ROM_FN(md_fireshrk) + +struct BurnDriver BurnDrvmd_fireshrk = { + "md_fireshrk", NULL, NULL, NULL, "1991", + "Fire Shark (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fireshrkRomInfo, md_fireshrkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fire Shark (USA) +static struct BurnRomInfo md_fireshrkuRomDesc[] = { + { "fire shark (usa).bin", 0x080000, 0x570b5024, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fireshrku) +STD_ROM_FN(md_fireshrku) + +struct BurnDriver BurnDrvmd_fireshrku = { + "md_fireshrku", "md_fireshrk", NULL, NULL, "1990", + "Fire Shark (USA)\0", NULL, "Dreamworks Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fireshrkuRomInfo, md_fireshrkuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fire Shark (USA, Alt) +static struct BurnRomInfo md_fireshrku1RomDesc[] = { + { "fire shark (usa) (alt).bin", 0x080000, 0x9c175146, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fireshrku1) +STD_ROM_FN(md_fireshrku1) + +struct BurnDriver BurnDrvmd_fireshrku1 = { + "md_fireshrku1", "md_fireshrk", NULL, NULL, "1990", + "Fire Shark (USA, Alt)\0", NULL, "Dreamworks Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fireshrku1RomInfo, md_fireshrku1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Same! Same! Same! (Jpn) +static struct BurnRomInfo md_samesameRomDesc[] = { + { "mpr-13301.bin", 0x080000, 0x77bbd841, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_samesame) +STD_ROM_FN(md_samesame) + +struct BurnDriver BurnDrvmd_samesame = { + "md_samesame", "md_fireshrk", NULL, NULL, "1990", + "Same! Same! Same! (Jpn)\0", NULL, "Toaplan", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_samesameRomInfo, md_samesameRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flashback (Euro, Rev. A) +static struct BurnRomInfo md_flashbRomDesc[] = { + { "mpr-15410a.bin", 0x180000, 0x6f311c83, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flashb) +STD_ROM_FN(md_flashb) + +struct BurnDriver BurnDrvmd_flashb = { + "md_flashb", NULL, NULL, NULL, "1993", + "Flashback (Euro, Rev. A)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flashbRomInfo, md_flashbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flashback (Jpn) +static struct BurnRomInfo md_flashbjRomDesc[] = { + { "flashback (jpn).bin", 0x180000, 0xb790e3b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flashbj) +STD_ROM_FN(md_flashbj) + +struct BurnDriver BurnDrvmd_flashbj = { + "md_flashbj", "md_flashb", NULL, NULL, "1993", + "Flashback (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flashbjRomInfo, md_flashbjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flashback - The Quest for Identity (USA) +static struct BurnRomInfo md_flashbuRomDesc[] = { + { "flashback - the quest for identity (usa).bin", 0x180000, 0x23a9616d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flashbu) +STD_ROM_FN(md_flashbu) + +struct BurnDriver BurnDrvmd_flashbu = { + "md_flashbu", "md_flashb", NULL, NULL, "1993", + "Flashback - The Quest for Identity (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flashbuRomInfo, md_flashbuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flashback - The Quest for Identity (USA, Alt) +static struct BurnRomInfo md_flashbu1RomDesc[] = { + { "flashback - the quest for identity (usa) (alt).bin", 0x180000, 0x33cd2b65, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flashbu1) +STD_ROM_FN(md_flashbu1) + +struct BurnDriver BurnDrvmd_flashbu1 = { + "md_flashbu1", "md_flashb", NULL, NULL, "1993", + "Flashback - The Quest for Identity (USA, Alt)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flashbu1RomInfo, md_flashbu1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flash Point (Jpn, Prototype) +static struct BurnRomInfo md_flashpRomDesc[] = { + { "flash point (japan) (proto).bin", 0x020000, 0x0655074d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flashp) +STD_ROM_FN(md_flashp) + +struct BurnDriver BurnDrvmd_flashp = { + "md_flashp", NULL, NULL, NULL, "199?", + "Flash Point (Jpn, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flashpRomInfo, md_flashpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flicky (Euro, USA) +static struct BurnRomInfo md_flickyRomDesc[] = { + { "flicky (euro, usa).bin", 0x020000, 0x4291c8ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flicky) +STD_ROM_FN(md_flicky) + +struct BurnDriver BurnDrvmd_flicky = { + "md_flicky", NULL, NULL, NULL, "1991", + "Flicky (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flickyRomInfo, md_flickyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flink (Euro) +static struct BurnRomInfo md_flinkRomDesc[] = { + { "flink (euro).bin", 0x100000, 0xbef9a4f4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flink) +STD_ROM_FN(md_flink) + +struct BurnDriver BurnDrvmd_flink = { + "md_flink", NULL, NULL, NULL, "1994", + "Flink (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flinkRomInfo, md_flinkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Flintstones (Euro) +static struct BurnRomInfo md_flintRomDesc[] = { + { "flintstones, the (euro).bin", 0x080000, 0x21845d61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flint) +STD_ROM_FN(md_flint) + +struct BurnDriver BurnDrvmd_flint = { + "md_flint", NULL, NULL, NULL, "1993", + "The Flintstones (Euro)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flintRomInfo, md_flintRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flintstone (Jpn) +static struct BurnRomInfo md_flintjRomDesc[] = { + { "flintstone (jpn).bin", 0x080000, 0x920a3031, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flintj) +STD_ROM_FN(md_flintj) + +struct BurnDriver BurnDrvmd_flintj = { + "md_flintj", "md_flint", NULL, NULL, "1993", + "Flintstone (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flintjRomInfo, md_flintjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Flintstones (USA) +static struct BurnRomInfo md_flintuRomDesc[] = { + { "flintstones, the (usa).bin", 0x080000, 0x7c982c59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flintu) +STD_ROM_FN(md_flintu) + +struct BurnDriver BurnDrvmd_flintu = { + "md_flintu", "md_flint", NULL, NULL, "1993", + "The Flintstones (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_flintuRomInfo, md_flintuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Foreman for Real (World) +static struct BurnRomInfo md_foremanRomDesc[] = { + { "foreman for real (world).bin", 0x300000, 0x36248f90, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_foreman) +STD_ROM_FN(md_foreman) + +struct BurnDriver BurnDrvmd_foreman = { + "md_foreman", NULL, NULL, NULL, "1995", + "Foreman for Real (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_foremanRomInfo, md_foremanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Forgotten Worlds (World, v1.1) +static struct BurnRomInfo md_forgottnRomDesc[] = { + { "forgotten worlds (world) (v1.1).bin", 0x080000, 0x95513985, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_forgottn) +STD_ROM_FN(md_forgottn) + +struct BurnDriver BurnDrvmd_forgottn = { + "md_forgottn", NULL, NULL, NULL, "1989", + "Forgotten Worlds (World, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_forgottnRomInfo, md_forgottnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Forgotten Worlds (World) +static struct BurnRomInfo md_forgottn1RomDesc[] = { + { "mpr-12672.bin", 0x080000, 0xd0ee6434, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_forgottn1) +STD_ROM_FN(md_forgottn1) + +struct BurnDriver BurnDrvmd_forgottn1 = { + "md_forgottn1", "md_forgottn", NULL, NULL, "1989", + "Forgotten Worlds (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_forgottn1RomInfo, md_forgottn1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mary Shelley's Frankenstein (USA) +static struct BurnRomInfo md_frankenRomDesc[] = { + { "mary shelley's frankenstein (usa).bin", 0x200000, 0x48993dc3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_franken) +STD_ROM_FN(md_franken) + +struct BurnDriver BurnDrvmd_franken = { + "md_franken", NULL, NULL, NULL, "1994", + "Mary Shelley's Frankenstein (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_frankenRomInfo, md_frankenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Frank Thomas Big Hurt Baseball (Euro, USA) +static struct BurnRomInfo md_franktRomDesc[] = { + { "frank thomas big hurt baseball (euro, usa).bin", 0x400000, 0x863e0950, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_frankt) +STD_ROM_FN(md_frankt) + +struct BurnDriver BurnDrvmd_frankt = { + "md_frankt", NULL, NULL, NULL, "1995", + "Frank Thomas Big Hurt Baseball (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_C_SLAM, GBF_MISC, 0, + MegadriveGetZipName, md_franktRomInfo, md_franktRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Frogger (USA) +static struct BurnRomInfo md_froggerRomDesc[] = { + { "frogger (usa).bin", 0x080000, 0xea2e48c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_frogger) +STD_ROM_FN(md_frogger) + +struct BurnDriver BurnDrvmd_frogger = { + "md_frogger", NULL, NULL, NULL, "1998", + "Frogger (USA)\0", NULL, "Majesco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_froggerRomInfo, md_froggerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fun 'N Games (Euro) +static struct BurnRomInfo md_funngameRomDesc[] = { + { "fun 'n' games (euro).bin", 0x100000, 0xda4ab3cd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_funngame) +STD_ROM_FN(md_funngame) + +struct BurnDriver BurnDrvmd_funngame = { + "md_funngame", NULL, NULL, NULL, "1993", + "Fun 'N Games (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_funngameRomInfo, md_funngameRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fun 'N' Games (USA) +static struct BurnRomInfo md_funngameuRomDesc[] = { + { "fun 'n' games (usa).bin", 0x100000, 0xb5ae351d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_funngameu) +STD_ROM_FN(md_funngameu) + +struct BurnDriver BurnDrvmd_funngameu = { + "md_funngameu", "md_funngame", NULL, NULL, "1993", + "Fun 'N' Games (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_funngameuRomInfo, md_funngameuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fun Car Rally (USA, Prototype) +static struct BurnRomInfo md_funcarRomDesc[] = { + { "fun car rally (usa) (prototype).bin", 0x100000, 0x42e27845, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_funcar) +STD_ROM_FN(md_funcar) + +struct BurnDriver BurnDrvmd_funcar = { + "md_funcar", NULL, NULL, NULL, "199?", + "Fun Car Rally (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_funcarRomInfo, md_funcarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// G-LOC Air Battle (World) +static struct BurnRomInfo md_glocRomDesc[] = { + { "mpr-15326.bin", 0x100000, 0xf2af886e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gloc) +STD_ROM_FN(md_gloc) + +struct BurnDriver BurnDrvmd_gloc = { + "md_gloc", NULL, NULL, NULL, "1993", + "G-LOC Air Battle (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_glocRomInfo, md_glocRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// G-LOC Air Battle (World, Prototype) +static struct BurnRomInfo md_glocpRomDesc[] = { + { "g-loc air battle (world) (beta).bin", 0x100000, 0x175c7e63, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_glocp) +STD_ROM_FN(md_glocp) + +struct BurnDriver BurnDrvmd_glocp = { + "md_glocp", "md_gloc", NULL, NULL, "1993", + "G-LOC Air Battle (World, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_glocpRomInfo, md_glocpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gadget Twins (USA) +static struct BurnRomInfo md_gadgetRomDesc[] = { + { "gadget twins (usa).bin", 0x100000, 0x7ae5e248, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gadget) +STD_ROM_FN(md_gadget) + +struct BurnDriver BurnDrvmd_gadget = { + "md_gadget", NULL, NULL, NULL, "1992", + "Gadget Twins (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gadgetRomInfo, md_gadgetRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gaiares (Jpn, USA) +static struct BurnRomInfo md_gaiaresRomDesc[] = { + { "gaiares (usa, jpn).bin", 0x100000, 0x5d8bf68b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gaiares) +STD_ROM_FN(md_gaiares) + +struct BurnDriver BurnDrvmd_gaiares = { + "md_gaiares", NULL, NULL, NULL, "1990", + "Gaiares (Jpn, USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gaiaresRomInfo, md_gaiaresRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gain Ground (World) +static struct BurnRomInfo md_gaingrndRomDesc[] = { + { "gain ground (world).bin", 0x080000, 0x8641a2ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gaingrnd) +STD_ROM_FN(md_gaingrnd) + +struct BurnDriver BurnDrvmd_gaingrnd = { + "md_gaingrnd", NULL, NULL, NULL, "1991", + "Gain Ground (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gaingrndRomInfo, md_gaingrndRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gain Ground (World, Alt) +static struct BurnRomInfo md_gaingrnd1RomDesc[] = { + { "gain ground (world) (alt).bin", 0x080000, 0x83e7b8ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gaingrnd1) +STD_ROM_FN(md_gaingrnd1) + +struct BurnDriver BurnDrvmd_gaingrnd1 = { + "md_gaingrnd1", "md_gaingrnd", NULL, NULL, "1991", + "Gain Ground (World, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gaingrnd1RomInfo, md_gaingrnd1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Galaxy Force II (World) +static struct BurnRomInfo md_gforce2aRomDesc[] = { + { "galaxy force ii (world).bin", 0x100000, 0xcae883c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gforce2a) +STD_ROM_FN(md_gforce2a) + +struct BurnDriver BurnDrvmd_gforce2a = { + "md_gforce2a", "md_gforce2", NULL, NULL, "1991", + "Galaxy Force II (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gforce2aRomInfo, md_gforce2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gambler Jiko Chuushinha - Katayama Masayuki no Mahjong Doujou (Jpn) +static struct BurnRomInfo md_gamblerjRomDesc[] = { + { "gambler jiko chuushinha - katayama masayuki no mahjong doujou (jpn).bin", 0x080000, 0x05650b7a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gamblerj) +STD_ROM_FN(md_gamblerj) + +struct BurnDriver BurnDrvmd_gamblerj = { + "md_gamblerj", NULL, NULL, NULL, "1990", + "Gambler Jiko Chuushinha - Katayama Masayuki no Mahjong Doujou (Jpn)\0", NULL, "Game Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gamblerjRomInfo, md_gamblerjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Game no Kandume Otokuyou (Jpn) +static struct BurnRomInfo md_gamenkoRomDesc[] = { + { "game no kandume otokuyou (jpn).bin", 0x300000, 0xcdad7e6b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gamenko) +STD_ROM_FN(md_gamenko) + +struct BurnDriver BurnDrvmd_gamenko = { + "md_gamenko", NULL, NULL, NULL, "199?", + "Game no Kandume Otokuyou (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_GAME_KANDUME, GBF_MISC, 0, + MegadriveGetZipName, md_gamenkoRomInfo, md_gamenkoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Garfield - Caught in the Act (Euro, USA) +static struct BurnRomInfo md_garfieldRomDesc[] = { + { "garfield - caught in the act (euro, usa).bin", 0x200000, 0xf0ff078e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_garfield) +STD_ROM_FN(md_garfield) + +struct BurnDriver BurnDrvmd_garfield = { + "md_garfield", NULL, NULL, NULL, "1995", + "Garfield - Caught in the Act (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_garfieldRomInfo, md_garfieldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gargoyles (USA) +static struct BurnRomInfo md_gargoyleRomDesc[] = { + { "gargoyles (usa).bin", 0x300000, 0x2d965364, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gargoyle) +STD_ROM_FN(md_gargoyle) + +struct BurnDriver BurnDrvmd_gargoyle = { + "md_gargoyle", NULL, NULL, NULL, "1995", + "Gargoyles (USA)\0", NULL, "Disney Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gargoyleRomInfo, md_gargoyleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gauntlet IV (Euro, USA, 199309) +static struct BurnRomInfo md_gauntl4RomDesc[] = { + { "gauntlet iv (euro, usa) (september 1993).bin", 0x100000, 0xf9d60510, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gauntl4) +STD_ROM_FN(md_gauntl4) + +struct BurnDriver BurnDrvmd_gauntl4 = { + "md_gauntl4", NULL, NULL, NULL, "1993", + "Gauntlet IV (Euro, USA, 199309)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gauntl4RomInfo, md_gauntl4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gauntlet IV (Euro, USA, 199308) +static struct BurnRomInfo md_gauntl4aRomDesc[] = { + { "gauntlet iv (euro, usa) (august 1993).bin", 0x100000, 0x3bf46dce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gauntl4a) +STD_ROM_FN(md_gauntl4a) + +struct BurnDriver BurnDrvmd_gauntl4a = { + "md_gauntl4a", "md_gauntl4", NULL, NULL, "1993", + "Gauntlet IV (Euro, USA, 199308)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gauntl4aRomInfo, md_gauntl4aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gauntlet (Jpn) +static struct BurnRomInfo md_gauntljRomDesc[] = { + { "gauntlet (jpn).bin", 0x100000, 0xf9872055, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gauntlj) +STD_ROM_FN(md_gauntlj) + +struct BurnDriver BurnDrvmd_gauntlj = { + "md_gauntlj", "md_gauntl4", NULL, NULL, "1993", + "Gauntlet (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gauntljRomInfo, md_gauntljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gemfire (USA) +static struct BurnRomInfo md_gemfireRomDesc[] = { + { "gemfire (usa).bin", 0x100000, 0x3d36135b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gemfire) +STD_ROM_FN(md_gemfire) + +struct BurnDriver BurnDrvmd_gemfire = { + "md_gemfire", NULL, NULL, NULL, "1992", + "Gemfire (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_gemfireRomInfo, md_gemfireRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Royal Blood (Jpn) +static struct BurnRomInfo md_royalbldRomDesc[] = { + { "royal blood (jpn).bin", 0x100000, 0x0e0107f1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_royalbld) +STD_ROM_FN(md_royalbld) + +struct BurnDriver BurnDrvmd_royalbld = { + "md_royalbld", "md_gemfire", NULL, NULL, "1992", + "Royal Blood (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_royalbldRomInfo, md_royalbldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// General Chaos (Euro, USA) +static struct BurnRomInfo md_genchaosRomDesc[] = { + { "general chaos (euro, usa).bin", 0x100000, 0xf1ecc4df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_genchaos) +STD_ROM_FN(md_genchaos) + +struct BurnDriver BurnDrvmd_genchaos = { + "md_genchaos", NULL, NULL, NULL, "1994", + "General Chaos (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_genchaosRomInfo, md_genchaosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// General Chaos Daikonsen (Jpn) +static struct BurnRomInfo md_genchaosjRomDesc[] = { + { "general chaos daikonsen (jpn).bin", 0x100000, 0x05cc7369, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_genchaosj) +STD_ROM_FN(md_genchaosj) + +struct BurnDriver BurnDrvmd_genchaosj = { + "md_genchaosj", "md_genchaos", NULL, NULL, "1994", + "General Chaos Daikonsen (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_genchaosjRomInfo, md_genchaosjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Generations Lost (Euro, USA) +static struct BurnRomInfo md_genelostRomDesc[] = { + { "generations lost (euro, usa).bin", 0x100000, 0x131f36a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_genelost) +STD_ROM_FN(md_genelost) + +struct BurnDriver BurnDrvmd_genelost = { + "md_genelost", NULL, NULL, NULL, "1994", + "Generations Lost (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_genelostRomInfo, md_genelostRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Genghis Khan II - Clan of the Gray Wolf (USA) +static struct BurnRomInfo md_genghisRomDesc[] = { + { "genghis khan ii - clan of the gray wolf (usa).bin", 0x100000, 0x87a281ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_genghis) +STD_ROM_FN(md_genghis) + +struct BurnDriver BurnDrvmd_genghis = { + "md_genghis", NULL, NULL, NULL, "1993", + "Genghis Khan II - Clan of the Gray Wolf (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_genghisRomInfo, md_genghisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Aoki Ookami to Shiroki Meshika - Genchou Hishi (Jpn) +static struct BurnRomInfo md_aokiooRomDesc[] = { + { "aoki ookami to shiroki meshika - genchou hishi (jpn).bin", 0x140000, 0x10be1d93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_aokioo) +STD_ROM_FN(md_aokioo) + +struct BurnDriver BurnDrvmd_aokioo = { + "md_aokioo", "md_genghis", NULL, NULL, "1993", + "Aoki Ookami to Shiroki Meshika - Genchou Hishi (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_aokiooRomInfo, md_aokiooRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// George Foreman's KO Boxing (Euro) +static struct BurnRomInfo md_georgekoRomDesc[] = { + { "george foreman's ko boxing (euro).bin", 0x100000, 0xbd556381, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_georgeko) +STD_ROM_FN(md_georgeko) + +struct BurnDriver BurnDrvmd_georgeko = { + "md_georgeko", NULL, NULL, NULL, "1992", + "George Foreman's KO Boxing (Euro)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_georgekoRomInfo, md_georgekoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// George Foreman's KO Boxing (USA) +static struct BurnRomInfo md_georgekouRomDesc[] = { + { "george foreman's ko boxing (usa).bin", 0x100000, 0xe1fdc787, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_georgekou) +STD_ROM_FN(md_georgekou) + +struct BurnDriver BurnDrvmd_georgekou = { + "md_georgekou", "md_georgeko", NULL, NULL, "1992", + "George Foreman's KO Boxing (USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_georgekouRomInfo, md_georgekouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ghostbusters (World, v1.1) +static struct BurnRomInfo md_ghostbstRomDesc[] = { + { "ghostbusters (world) (v1.1).bin", 0x080000, 0x792df93b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ghostbst) +STD_ROM_FN(md_ghostbst) + +struct BurnDriver BurnDrvmd_ghostbst = { + "md_ghostbst", NULL, NULL, NULL, "1990", + "Ghostbusters (World, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ghostbstRomInfo, md_ghostbstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ghostbusters (World) +static struct BurnRomInfo md_ghostbst1RomDesc[] = { + { "ghostbusters (world).bin", 0x080000, 0x00419da3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ghostbst1) +STD_ROM_FN(md_ghostbst1) + +struct BurnDriver BurnDrvmd_ghostbst1 = { + "md_ghostbst1", "md_ghostbst", NULL, NULL, "1990", + "Ghostbusters (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ghostbst1RomInfo, md_ghostbst1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dai Makaimura (Jpn) +static struct BurnRomInfo md_daimakaiRomDesc[] = { + { "dai makaimura (jpn).bin", 0x0a0000, 0x5659f379, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daimakai) +STD_ROM_FN(md_daimakai) + +struct BurnDriver BurnDrvmd_daimakai = { + "md_daimakai", "md_ghouls", NULL, NULL, "1989", + "Dai Makaimura (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_daimakaiRomInfo, md_daimakaiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// GleyLancer (Jpn) +static struct BurnRomInfo md_gleylancRomDesc[] = { + { "advanced busterhawk gleylancer (jpn).bin", 0x100000, 0x42cf9b5b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gleylanc) +STD_ROM_FN(md_gleylanc) + +struct BurnDriver BurnDrvmd_gleylanc = { + "md_gleylanc", NULL, NULL, NULL, "1992", + "GleyLancer (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gleylancRomInfo, md_gleylancRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Global Gladiators (Euro) +static struct BurnRomInfo md_globgladRomDesc[] = { + { "mpr-15237.bin", 0x100000, 0x5c218c6a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_globglad) +STD_ROM_FN(md_globglad) + +struct BurnDriver BurnDrvmd_globglad = { + "md_globglad", NULL, NULL, NULL, "1993", + "Global Gladiators (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_globgladRomInfo, md_globgladRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mick & Mack as the Global Gladiators (USA) +static struct BurnRomInfo md_mickmackRomDesc[] = { + { "mick & mack as the global gladiators (usa).bin", 0x100000, 0x40f17bb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mickmack) +STD_ROM_FN(md_mickmack) + +struct BurnDriver BurnDrvmd_mickmack = { + "md_mickmack", "md_globglad", NULL, NULL, "1992", + "Mick & Mack as the Global Gladiators (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mickmackRomInfo, md_mickmackRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mick & Mack as the Global Gladiators (USA, Prototype) +static struct BurnRomInfo md_mickmackpRomDesc[] = { + { "mick & mack as the global gladiators (usa) (beta).bin", 0x100000, 0x08c2af21, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mickmackp) +STD_ROM_FN(md_mickmackp) + +struct BurnDriver BurnDrvmd_mickmackp = { + "md_mickmackp", "md_globglad", NULL, NULL, "1992", + "Mick & Mack as the Global Gladiators (USA, Prototype)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mickmackpRomInfo, md_mickmackpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gods (Euro) +static struct BurnRomInfo md_godsRomDesc[] = { + { "gods (euro).bin", 0x100000, 0x6c415016, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gods) +STD_ROM_FN(md_gods) + +struct BurnDriver BurnDrvmd_gods = { + "md_gods", NULL, NULL, NULL, "1993", + "Gods (Euro)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_godsRomInfo, md_godsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gods (Jpn) +static struct BurnRomInfo md_godsjRomDesc[] = { + { "gods (jpn).bin", 0x100000, 0xe4f50206, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_godsj) +STD_ROM_FN(md_godsj) + +struct BurnDriver BurnDrvmd_godsj = { + "md_godsj", "md_gods", NULL, NULL, "1993", + "Gods (Jpn)\0", NULL, "PCM Complete", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_godsjRomInfo, md_godsjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gods (USA) +static struct BurnRomInfo md_godsuRomDesc[] = { + { "gods (usa).bin", 0x100000, 0xfd234ccd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_godsu) +STD_ROM_FN(md_godsu) + +struct BurnDriver BurnDrvmd_godsu = { + "md_godsu", "md_gods", NULL, NULL, "1992", + "Gods (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_godsuRomInfo, md_godsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gods (USA, Prototype) +static struct BurnRomInfo md_godsupRomDesc[] = { + { "gods (usa) (beta).bin", 0x100000, 0x2c06bb64, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_godsup) +STD_ROM_FN(md_godsup) + +struct BurnDriver BurnDrvmd_godsup = { + "md_godsup", "md_gods", NULL, NULL, "1992", + "Gods (USA, Prototype)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_godsupRomInfo, md_godsupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden Axe (World, v1.1) +static struct BurnRomInfo md_goldnaxeRomDesc[] = { + { "golden axe (world) (v1.1).bin", 0x080000, 0x665d7df9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goldnaxe) +STD_ROM_FN(md_goldnaxe) + +struct BurnDriver BurnDrvmd_goldnaxe = { + "md_goldnaxe", NULL, NULL, NULL, "1989", + "Golden Axe (World, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goldnaxeRomInfo, md_goldnaxeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden Axe (World) +static struct BurnRomInfo md_goldnaxe1RomDesc[] = { + { "mpr-12806.bin", 0x080000, 0xe8182b90, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goldnaxe1) +STD_ROM_FN(md_goldnaxe1) + +struct BurnDriver BurnDrvmd_goldnaxe1 = { + "md_goldnaxe1", "md_goldnaxe", NULL, NULL, "1989", + "Golden Axe (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goldnaxe1RomInfo, md_goldnaxe1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden Axe II (World) +static struct BurnRomInfo md_goldnax2RomDesc[] = { + { "mpr-14272.bin", 0x080000, 0x725e0a18, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goldnax2) +STD_ROM_FN(md_goldnax2) + +struct BurnDriver BurnDrvmd_goldnax2 = { + "md_goldnax2", NULL, NULL, NULL, "1991", + "Golden Axe II (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goldnax2RomInfo, md_goldnax2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden Axe II (World, Prototype) +static struct BurnRomInfo md_goldnax2pRomDesc[] = { + { "golden axe ii (world) (beta).bin", 0x080000, 0xe62ea1bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goldnax2p) +STD_ROM_FN(md_goldnax2p) + +struct BurnDriver BurnDrvmd_goldnax2p = { + "md_goldnax2p", "md_goldnax2", NULL, NULL, "1991", + "Golden Axe II (World, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goldnax2pRomInfo, md_goldnax2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden Axe III (Jpn) +static struct BurnRomInfo md_goldnax3RomDesc[] = { + { "golden axe iii (jpn).bin", 0x100000, 0xc7862ea3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goldnax3) +STD_ROM_FN(md_goldnax3) + +struct BurnDriver BurnDrvmd_goldnax3 = { + "md_goldnax3", NULL, NULL, NULL, "1993", + "Golden Axe III (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goldnax3RomInfo, md_goldnax3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Uchuu Senkan Gomora (Jpn) +static struct BurnRomInfo md_gomoraRomDesc[] = { + { "uchuu senkan gomora (jpn).bin", 0x100000, 0xc511e8d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gomora) +STD_ROM_FN(md_gomora) + +struct BurnDriver BurnDrvmd_gomora = { + "md_gomora", NULL, NULL, NULL, "1991", + "Uchuu Senkan Gomora (Jpn)\0", NULL, "UPL", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gomoraRomInfo, md_gomoraRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Goofy's Hysterical History Tour (USA) +static struct BurnRomInfo md_goofyRomDesc[] = { + { "goofy's hysterical history tour (usa).bin", 0x100000, 0x4e1cc833, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_goofy) +STD_ROM_FN(md_goofy) + +struct BurnDriver BurnDrvmd_goofy = { + "md_goofy", NULL, NULL, NULL, "1993", + "Goofy's Hysterical History Tour (USA)\0", NULL, " Absolute Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_goofyRomInfo, md_goofyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gouketsuji Ichizoku (Jpn) +static struct BurnRomInfo md_gouketsuRomDesc[] = { + { "gouketsuji ichizoku (jpn).bin", 0x300000, 0xabe9c415, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gouketsu) +STD_ROM_FN(md_gouketsu) + +struct BurnDriver BurnDrvmd_gouketsu = { + "md_gouketsu", NULL, NULL, NULL, "1994", + "Gouketsuji Ichizoku (Jpn)\0", NULL, "Atlus", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gouketsuRomInfo, md_gouketsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Granada (Jpn, USA, v1.1) +static struct BurnRomInfo md_granadaRomDesc[] = { + { "granada (usa, jpn) (v1.1).bin", 0x080000, 0xe89d1e66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_granada) +STD_ROM_FN(md_granada) + +struct BurnDriver BurnDrvmd_granada = { + "md_granada", NULL, NULL, NULL, "1990", + "Granada (Jpn, USA, v1.1)\0", NULL, "Renovation ~ Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_granadaRomInfo, md_granadaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Granada (Jpn, USA) +static struct BurnRomInfo md_granada1RomDesc[] = { + { "granada (usa, jpn).bin", 0x080000, 0x7f45719b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_granada1) +STD_ROM_FN(md_granada1) + +struct BurnDriver BurnDrvmd_granada1 = { + "md_granada1", "md_granada", NULL, NULL, "1990", + "Granada (Jpn, USA)\0", NULL, "Renovation ~ Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_granada1RomInfo, md_granada1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// GrandSlam - The Tennis Tournament (Euro) +static struct BurnRomInfo md_grandslRomDesc[] = { + { "mpr-15208.bin", 0x080000, 0x8c2670de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_grandsl) +STD_ROM_FN(md_grandsl) + +struct BurnDriver BurnDrvmd_grandsl = { + "md_grandsl", NULL, NULL, NULL, "1992", + "GrandSlam - The Tennis Tournament (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_grandslRomInfo, md_grandslRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// GrandSlam - The Tennis Tournament '92 (Jpn) +static struct BurnRomInfo md_grandsljRomDesc[] = { + { "grandslam - the tennis tournament '92 (jpn).bin", 0x080000, 0x30cf37d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_grandslj) +STD_ROM_FN(md_grandslj) + +struct BurnDriver BurnDrvmd_grandslj = { + "md_grandslj", "md_grandsl", NULL, NULL, "1992", + "GrandSlam - The Tennis Tournament '92 (Jpn)\0", NULL, "Nippon Telenet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_grandsljRomInfo, md_grandsljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jennifer Capriati Tennis (USA) +static struct BurnRomInfo md_jennifctRomDesc[] = { + { "jennifer capriati tennis (usa).bin", 0x080000, 0xab2abc8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jennifct) +STD_ROM_FN(md_jennifct) + +struct BurnDriver BurnDrvmd_jennifct = { + "md_jennifct", "md_grandsl", NULL, NULL, "1992", + "Jennifer Capriati Tennis (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jennifctRomInfo, md_jennifctRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Great Circus Mystery - Mickey to Minnie Magical Adventure 2 (Jpn) +static struct BurnRomInfo md_greatcirjRomDesc[] = { + { "great circus mystery - mickey to minnie magical adventure 2 (jpn).bin", 0x200000, 0x5aa0f3a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_greatcirj) +STD_ROM_FN(md_greatcirj) + +struct BurnDriver BurnDrvmd_greatcirj = { + "md_greatcirj", "md_greatcir", NULL, NULL, "1994", + "Great Circus Mystery - Mickey to Minnie Magical Adventure 2 (Jpn)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_greatcirjRomInfo, md_greatcirjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Great Circus Mystery Starring Mickey & Minnie (USA) +static struct BurnRomInfo md_greatcirRomDesc[] = { + { "great circus mystery starring mickey & minnie, the (usa).bin", 0x200000, 0x14744883, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_greatcir) +STD_ROM_FN(md_greatcir) + +struct BurnDriver BurnDrvmd_greatcir = { + "md_greatcir", NULL, NULL, NULL, "1994", + "The Great Circus Mystery Starring Mickey & Minnie (USA)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_greatcirRomInfo, md_greatcirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Great Waldo Search (USA) +static struct BurnRomInfo md_greatwsRomDesc[] = { + { "great waldo search, the (usa).bin", 0x100000, 0x8c5c93b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_greatws) +STD_ROM_FN(md_greatws) + +struct BurnDriver BurnDrvmd_greatws = { + "md_greatws", NULL, NULL, NULL, "1992", + "The Great Waldo Search (USA)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_greatwsRomInfo, md_greatwsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Greatest Heavyweights (Jpn) +static struct BurnRomInfo md_ghwjRomDesc[] = { + { "greatest heavyweights (jpn).bin", 0x200000, 0x7ef8b162, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ghwj) +STD_ROM_FN(md_ghwj) + +struct BurnDriver BurnDrvmd_ghwj = { + "md_ghwj", "md_ghw", NULL, NULL, "1994", + "Greatest Heavyweights (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_ghwjRomInfo, md_ghwjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Greatest Heavyweights (USA) +static struct BurnRomInfo md_ghwuRomDesc[] = { + { "greatest heavyweights (usa).bin", 0x200000, 0x6e3621d5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ghwu) +STD_ROM_FN(md_ghwu) + +struct BurnDriver BurnDrvmd_ghwu = { + "md_ghwu", "md_ghw", NULL, NULL, "1994", + "Greatest Heavyweights (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_ghwuRomInfo, md_ghwuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Greendog - The Beached Surfer Dude! (Euro, USA) +static struct BurnRomInfo md_greendogRomDesc[] = { + { "mpr-14993.bin", 0x080000, 0xc4820a03, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_greendog) +STD_ROM_FN(md_greendog) + +struct BurnDriver BurnDrvmd_greendog = { + "md_greendog", NULL, NULL, NULL, "1992", + "Greendog - The Beached Surfer Dude! (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_greendogRomInfo, md_greendogRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Grind Stormer (USA) +static struct BurnRomInfo md_grindstRomDesc[] = { + { "grind stormer (usa).bin", 0x100000, 0x7e6bef15, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_grindst) +STD_ROM_FN(md_grindst) + +struct BurnDriver BurnDrvmd_grindst = { + "md_grindst", NULL, NULL, NULL, "1994", + "Grind Stormer (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_grindstRomInfo, md_grindstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// V-Five (Jpn) +static struct BurnRomInfo md_vfiveRomDesc[] = { + { "v-v (jpn).bin", 0x100000, 0xad9d0ec0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vfive) +STD_ROM_FN(md_vfive) + +struct BurnDriver BurnDrvmd_vfive = { + "md_vfive", "md_grindst", NULL, NULL, "1994", + "V-Five (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vfiveRomInfo, md_vfiveRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Growl (USA) +static struct BurnRomInfo md_growlRomDesc[] = { + { "growl (usa).bin", 0x080000, 0xf60ef143, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_growl) +STD_ROM_FN(md_growl) + +struct BurnDriver BurnDrvmd_growl = { + "md_growl", NULL, NULL, NULL, "1991", + "Growl (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_growlRomInfo, md_growlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Runark (Jpn, Kor) +static struct BurnRomInfo md_runarkRomDesc[] = { + { "runark (jpn, kor).bin", 0x080000, 0x0894d8fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_runark) +STD_ROM_FN(md_runark) + +struct BurnDriver BurnDrvmd_runark = { + "md_runark", "md_growl", NULL, NULL, "1991", + "Runark (Jpn, Kor)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_runarkRomInfo, md_runarkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gunship (Euro) +static struct BurnRomInfo md_gunshipRomDesc[] = { + { "gunship (euro).bin", 0x100000, 0xda1440c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gunship) +STD_ROM_FN(md_gunship) + +struct BurnDriver BurnDrvmd_gunship = { + "md_gunship", NULL, NULL, NULL, "1993", + "Gunship (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gunshipRomInfo, md_gunshipRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gunstar Heroes (Euro) +static struct BurnRomInfo md_gunstarRomDesc[] = { + { "gunstar heroes (euro).bin", 0x100000, 0x866ed9d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gunstar) +STD_ROM_FN(md_gunstar) + +struct BurnDriver BurnDrvmd_gunstar = { + "md_gunstar", NULL, NULL, NULL, "1993", + "Gunstar Heroes (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gunstarRomInfo, md_gunstarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gunstar Heroes (Jpn) +static struct BurnRomInfo md_gunstarjRomDesc[] = { + { "gunstar heroes (jpn).bin", 0x100000, 0x1cfd0383, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gunstarj) +STD_ROM_FN(md_gunstarj) + +struct BurnDriver BurnDrvmd_gunstarj = { + "md_gunstarj", "md_gunstar", NULL, NULL, "1993", + "Gunstar Heroes (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gunstarjRomInfo, md_gunstarjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gunstar Heroes (Jpn, Sample) +static struct BurnRomInfo md_gunstarjsRomDesc[] = { + { "gunstar heroes (jpn) (sample).bin", 0x100000, 0x6f90b502, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gunstarjs) +STD_ROM_FN(md_gunstarjs) + +struct BurnDriver BurnDrvmd_gunstarjs = { + "md_gunstarjs", "md_gunstar", NULL, NULL, "1993", + "Gunstar Heroes (Jpn, Sample)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gunstarjsRomInfo, md_gunstarjsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gunstar Heroes (USA) +static struct BurnRomInfo md_gunstaruRomDesc[] = { + { "gunstar heroes (usa).bin", 0x100000, 0xb813cf0d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gunstaru) +STD_ROM_FN(md_gunstaru) + +struct BurnDriver BurnDrvmd_gunstaru = { + "md_gunstaru", "md_gunstar", NULL, NULL, "1993", + "Gunstar Heroes (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gunstaruRomInfo, md_gunstaruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gynoug (Euro) +static struct BurnRomInfo md_gynougRomDesc[] = { + { "mpr-14439.bin", 0x080000, 0x03405102, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gynoug) +STD_ROM_FN(md_gynoug) + +struct BurnDriver BurnDrvmd_gynoug = { + "md_gynoug", NULL, NULL, NULL, "1991", + "Gynoug (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gynougRomInfo, md_gynougRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gynoug (Jpn) +static struct BurnRomInfo md_gynougjRomDesc[] = { + { "gynoug (jpn).bin", 0x080000, 0x1b69241f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gynougj) +STD_ROM_FN(md_gynougj) + +struct BurnDriver BurnDrvmd_gynougj = { + "md_gynougj", "md_gynoug", NULL, NULL, "1991", + "Gynoug (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gynougjRomInfo, md_gynougjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wings of Wor (USA) +static struct BurnRomInfo md_wingsworRomDesc[] = { + { "wings of wor (usa).bin", 0x080000, 0x210a2fcd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wingswor) +STD_ROM_FN(md_wingswor) + +struct BurnDriver BurnDrvmd_wingswor = { + "md_wingswor", "md_gynoug", NULL, NULL, "1991", + "Wings of Wor (USA)\0", NULL, "Dreamworks Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wingsworRomInfo, md_wingsworRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hard Drivin' (World) +static struct BurnRomInfo md_harddrivRomDesc[] = { + { "mpr-13489.bin", 0x040000, 0x3225baaf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_harddriv) +STD_ROM_FN(md_harddriv) + +struct BurnDriver BurnDrvmd_harddriv = { + "md_harddriv", NULL, NULL, NULL, "1991", + "Hard Drivin' (World)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_harddrivRomInfo, md_harddrivRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// HardBall '94 (Euro, USA) +static struct BurnRomInfo md_hardbl94RomDesc[] = { + { "hardball '94 (euro, usa).bin", 0x200000, 0xea9c4878, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hardbl94) +STD_ROM_FN(md_hardbl94) + +struct BurnDriver BurnDrvmd_hardbl94 = { + "md_hardbl94", NULL, NULL, NULL, "1994", + "HardBall '94 (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_hardbl94RomInfo, md_hardbl94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// HardBall '95 (USA) +static struct BurnRomInfo md_hardbl95RomDesc[] = { + { "hardball '95 (usa).bin", 0x300000, 0xed10bc9e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hardbl95) +STD_ROM_FN(md_hardbl95) + +struct BurnDriver BurnDrvmd_hardbl95 = { + "md_hardbl95", NULL, NULL, NULL, "1995", + "HardBall '95 (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hardbl95RomInfo, md_hardbl95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// HardBall III (USA) +static struct BurnRomInfo md_hardbal3RomDesc[] = { + { "hardball iii (usa).bin", 0x200000, 0xa4f2f011, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hardbal3) +STD_ROM_FN(md_hardbal3) + +struct BurnDriver BurnDrvmd_hardbal3 = { + "md_hardbal3", NULL, NULL, NULL, "1993", + "HardBall III (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hardbal3RomInfo, md_hardbal3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// HardBall! (USA) +static struct BurnRomInfo md_hardballRomDesc[] = { + { "hardball! (usa).bin", 0x100000, 0xbd1b9a04, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hardball) +STD_ROM_FN(md_hardball) + +struct BurnDriver BurnDrvmd_hardball = { + "md_hardball", NULL, NULL, NULL, "1991", + "HardBall! (USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hardballRomInfo, md_hardballRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Haunting Starring Polterguy (Euro, USA) +static struct BurnRomInfo md_hauntingRomDesc[] = { + { "haunting starring polterguy (euro, usa).bin", 0x200000, 0xc9fc876d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_haunting) +STD_ROM_FN(md_haunting) + +struct BurnDriver BurnDrvmd_haunting = { + "md_haunting", NULL, NULL, NULL, "1993", + "Haunting Starring Polterguy (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hauntingRomInfo, md_hauntingRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Capt'n Havoc (Euro) +static struct BurnRomInfo md_havocRomDesc[] = { + { "capt'n havoc (euro).bin", 0x100000, 0x76e6d20d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_havoc) +STD_ROM_FN(md_havoc) + +struct BurnDriver BurnDrvmd_havoc = { + "md_havoc", NULL, NULL, NULL, "1994", + "Capt'n Havoc (Euro)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_havocRomInfo, md_havocRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// High Seas Havoc (USA) +static struct BurnRomInfo md_havocuRomDesc[] = { + { "high seas havoc (usa).bin", 0x100000, 0x17be551c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_havocu) +STD_ROM_FN(md_havocu) + +struct BurnDriver BurnDrvmd_havocu = { + "md_havocu", "md_havoc", NULL, NULL, "1993", + "High Seas Havoc (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_havocuRomInfo, md_havocuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Heavy Nova (USA) +static struct BurnRomInfo md_heavynovRomDesc[] = { + { "heavy nova (usa).bin", 0x100000, 0xf6b6a9d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_heavynov) +STD_ROM_FN(md_heavynov) + +struct BurnDriver BurnDrvmd_heavynov = { + "md_heavynov", NULL, NULL, NULL, "1992", + "Heavy Nova (USA)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_heavynovRomInfo, md_heavynovRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Heavy Unit - Mega Drive Special (Jpn) +static struct BurnRomInfo md_hvyunitRomDesc[] = { + { "heavy unit - mega drive special (jpn).bin", 0x080000, 0x1acbe608, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hvyunit) +STD_ROM_FN(md_hvyunit) + +struct BurnDriver BurnDrvmd_hvyunit = { + "md_hvyunit", NULL, NULL, NULL, "1990", + "Heavy Unit - Mega Drive Special (Jpn)\0", NULL, "Toho", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hvyunitRomInfo, md_hvyunitRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hei Tao 2 - Super Big 2 (Chi) +static struct BurnRomInfo md_heitaoRomDesc[] = { + { "hei tao 2 - super big 2 (chi) (unl).bin", 0x100000, 0x31449113, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_heitao) +STD_ROM_FN(md_heitao) + +struct BurnDriver BurnDrvmd_heitao = { + "md_heitao", NULL, NULL, NULL, "199?", + "Hei Tao 2 - Super Big 2 (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_heitaoRomInfo, md_heitaoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hellfire (Euro) +static struct BurnRomInfo md_hellfireRomDesc[] = { + { "mpr-14430.bin", 0x080000, 0xcf30acec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hellfire) +STD_ROM_FN(md_hellfire) + +struct BurnDriver BurnDrvmd_hellfire = { + "md_hellfire", NULL, NULL, NULL, "1991", + "Hellfire (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hellfireRomInfo, md_hellfireRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hellfire (Jpn) +static struct BurnRomInfo md_hellfirejRomDesc[] = { + { "hellfire (jpn).bin", 0x080000, 0x8e5e13ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hellfirej) +STD_ROM_FN(md_hellfirej) + +struct BurnDriver BurnDrvmd_hellfirej = { + "md_hellfirej", "md_hellfire", NULL, NULL, "1990", + "Hellfire (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hellfirejRomInfo, md_hellfirejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hellfire (USA) +static struct BurnRomInfo md_hellfireuRomDesc[] = { + { "hellfire (usa).bin", 0x080000, 0x184018f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hellfireu) +STD_ROM_FN(md_hellfireu) + +struct BurnDriver BurnDrvmd_hellfireu = { + "md_hellfireu", "md_hellfire", NULL, NULL, "1991", + "Hellfire (USA)\0", NULL, "Seismic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hellfireuRomInfo, md_hellfireuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Herzog Zwei (Euro, USA) +static struct BurnRomInfo md_herzogRomDesc[] = { + { "herzog zwei (euro, usa).bin", 0x080000, 0xa605b65b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_herzog) +STD_ROM_FN(md_herzog) + +struct BurnDriver BurnDrvmd_herzog = { + "md_herzog", NULL, NULL, NULL, "1990", + "Herzog Zwei (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_herzogRomInfo, md_herzogRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Herzog Zwei (Jpn) +static struct BurnRomInfo md_herzogjRomDesc[] = { + { "herzog zwei (jpn).bin", 0x080000, 0x4cf676b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_herzogj) +STD_ROM_FN(md_herzogj) + +struct BurnDriver BurnDrvmd_herzogj = { + "md_herzogj", "md_herzog", NULL, NULL, "1989", + "Herzog Zwei (Jpn)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_herzogjRomInfo, md_herzogjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hit the Ice (USA) +static struct BurnRomInfo md_hiticeRomDesc[] = { + { "hit the ice (usa).bin", 0x080000, 0x85b23606, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hitice) +STD_ROM_FN(md_hitice) + +struct BurnDriver BurnDrvmd_hitice = { + "md_hitice", NULL, NULL, NULL, "1992", + "Hit the Ice (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hiticeRomInfo, md_hiticeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Home Alone (USA, Prototype) +static struct BurnRomInfo md_homeapRomDesc[] = { + { "home alone (usa) (beta).bin", 0x100000, 0x3a235fb9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_homeap) +STD_ROM_FN(md_homeap) + +struct BurnDriver BurnDrvmd_homeap = { + "md_homeap", "md_homea", NULL, NULL, "1992", + "Home Alone (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_homeapRomInfo, md_homeapRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Home Alone 2 - Lost in New York (USA) +static struct BurnRomInfo md_homea2RomDesc[] = { + { "home alone 2 - lost in new york (usa).bin", 0x080000, 0xcbf87c14, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_homea2) +STD_ROM_FN(md_homea2) + +struct BurnDriver BurnDrvmd_homea2 = { + "md_homea2", NULL, NULL, NULL, "1993", + "Home Alone 2 - Lost in New York (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_homea2RomInfo, md_homea2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Honoo no Toukyuuji Dodge Danpei (Jpn) +static struct BurnRomInfo md_dodgedanRomDesc[] = { + { "mpr-14856.bin", 0x080000, 0x630f07c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dodgedan) +STD_ROM_FN(md_dodgedan) + +struct BurnDriver BurnDrvmd_dodgedan = { + "md_dodgedan", NULL, NULL, NULL, "1992", + "Honoo no Toukyuuji Dodge Danpei (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dodgedanRomInfo, md_dodgedanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hook (USA) +static struct BurnRomInfo md_hookRomDesc[] = { + { "hook (usa).bin", 0x100000, 0x2c48e712, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hook) +STD_ROM_FN(md_hook) + +struct BurnDriver BurnDrvmd_hook = { + "md_hook", NULL, NULL, NULL, "1992", + "Hook (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hookRomInfo, md_hookRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Humans (USA) +static struct BurnRomInfo md_humansRomDesc[] = { + { "humans, the (usa).bin", 0x100000, 0xa0cf4366, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_humans) +STD_ROM_FN(md_humans) + +struct BurnDriver BurnDrvmd_humans = { + "md_humans", NULL, NULL, NULL, "1992", + "The Humans (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_humansRomInfo, md_humansRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hurricanes (Euro) +static struct BurnRomInfo md_hurricanRomDesc[] = { + { "hurricanes (euro).bin", 0x200000, 0xdeccc874, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hurrican) +STD_ROM_FN(md_hurrican) + +struct BurnDriver BurnDrvmd_hurrican = { + "md_hurrican", NULL, NULL, NULL, "1994", + "Hurricanes (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hurricanRomInfo, md_hurricanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Hybrid Front (Jpn) +static struct BurnRomInfo md_hybridfRomDesc[] = { + { "hybrid front, the (jpn).bin", 0x200000, 0xa1f1cfe7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hybridf) +STD_ROM_FN(md_hybridf) + +struct BurnDriver BurnDrvmd_hybridf = { + "md_hybridf", NULL, NULL, NULL, "1994", + "The Hybrid Front (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_hybridfRomInfo, md_hybridfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Hybrid Front (Jpn, Prototype) +static struct BurnRomInfo md_hybridfpRomDesc[] = { + { "hybrid front, the (jpn) (beta).bin", 0x300000, 0x04f02687, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hybridfp) +STD_ROM_FN(md_hybridfp) + +struct BurnDriver BurnDrvmd_hybridfp = { + "md_hybridfp", "md_hybridf", NULL, NULL, "1994", + "The Hybrid Front (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_hybridfpRomInfo, md_hybridfpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyokkori Hyoutanjima - Daitouryou o Mezase! (Jpn) +static struct BurnRomInfo md_hyokkoRomDesc[] = { + { "hyokkori hyoutanjima - daitouryou o mezase! (jpn).bin", 0x080000, 0x72253bdb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hyokko) +STD_ROM_FN(md_hyokko) + +struct BurnDriver BurnDrvmd_hyokko = { + "md_hyokko", NULL, NULL, NULL, "1992", + "Hyokkori Hyoutanjima - Daitouryou o Mezase! (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hyokkoRomInfo, md_hyokkoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyper Dunk (Euro) +static struct BurnRomInfo md_hyperdRomDesc[] = { + { "hyper dunk (euro).bin", 0x200000, 0xf27c576a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hyperd) +STD_ROM_FN(md_hyperd) + +struct BurnDriver BurnDrvmd_hyperd = { + "md_hyperd", NULL, NULL, NULL, "1994", + "Hyper Dunk (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hyperdRomInfo, md_hyperdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyper Dunk - The Playoff Edition (Jpn) +static struct BurnRomInfo md_hyperdjRomDesc[] = { + { "fz009a1.bin", 0x200000, 0x5baf53d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hyperdj) +STD_ROM_FN(md_hyperdj) + +struct BurnDriver BurnDrvmd_hyperdj = { + "md_hyperdj", "md_hyperd", NULL, NULL, "1994", + "Hyper Dunk - The Playoff Edition (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hyperdjRomInfo, md_hyperdjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyper Dunk - The Playoff Edition (Jpn, Prototype) +static struct BurnRomInfo md_hyperdjpRomDesc[] = { + { "hyper dunk - the playoff edition (jpn) (beta).in", 0x200000, 0xdb124bbb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hyperdjp) +STD_ROM_FN(md_hyperdjp) + +struct BurnDriver BurnDrvmd_hyperdjp = { + "md_hyperdjp", "md_hyperd", NULL, NULL, "1994", + "Hyper Dunk - The Playoff Edition (Jpn, Prototype)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hyperdjpRomInfo, md_hyperdjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Double Dribble - The Playoff Edition (USA) +static struct BurnRomInfo md_ddribbleRomDesc[] = { + { "double dribble - the playoff edition (usa).bin", 0x200000, 0x8352b1d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ddribble) +STD_ROM_FN(md_ddribble) + +struct BurnDriver BurnDrvmd_ddribble = { + "md_ddribble", "md_hyperd", NULL, NULL, "1994", + "Double Dribble - The Playoff Edition (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ddribbleRomInfo, md_ddribbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyper Marbles (Jpn, SegaNet) +static struct BurnRomInfo md_hypermRomDesc[] = { + { "hyper marbles (jpn) (sn).bin", 0x040000, 0x83bb2799, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hyperm) +STD_ROM_FN(md_hyperm) + +struct BurnDriver BurnDrvmd_hyperm = { + "md_hyperm", NULL, NULL, NULL, "1991", + "Hyper Marbles (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hypermRomInfo, md_hypermRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hyper Marbles (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_hypermgnkRomDesc[] = { + { "hyper marbles (jpn) (gnk).bin", 0x040000, 0x9ed72146, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hypermgnk) +STD_ROM_FN(md_hypermgnk) + +struct BurnDriver BurnDrvmd_hypermgnk = { + "md_hypermgnk", "md_hyperm", NULL, NULL, "1991", + "Hyper Marbles (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hypermgnkRomInfo, md_hypermgnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// IMG International Tour Tennis (Euro, USA) +static struct BurnRomInfo md_imgittRomDesc[] = { + { "img international tour tennis (euro, usa).bin", 0x200000, 0xe04ffc2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_imgitt) +STD_ROM_FN(md_imgitt) + +struct BurnDriver BurnDrvmd_imgitt = { + "md_imgitt", NULL, NULL, NULL, "1994", + "IMG International Tour Tennis (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_imgittRomInfo, md_imgittRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Immortal (Euro, USA) +static struct BurnRomInfo md_immortalRomDesc[] = { + { "immortal, the (euro, usa).bin", 0x100000, 0xf653c508, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_immortal) +STD_ROM_FN(md_immortal) + +struct BurnDriver BurnDrvmd_immortal = { + "md_immortal", NULL, NULL, NULL, "1993", + "The Immortal (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_immortalRomInfo, md_immortalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wizard of the Immortal (Jpn) +static struct BurnRomInfo md_immortaljRomDesc[] = { + { "wizard of the immortal (jpn).bin", 0x200000, 0xc99fad92, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_immortalj) +STD_ROM_FN(md_immortalj) + +struct BurnDriver BurnDrvmd_immortalj = { + "md_immortalj", "md_immortal", NULL, NULL, "1993", + "Wizard of the Immortal (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_immortaljRomInfo, md_immortaljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Incredible Crash Dummies (USA, Prototype) +static struct BurnRomInfo md_crashdumpRomDesc[] = { + { "incredible crash dummies, the (usa) (beta).bin", 0x100000, 0x623a920f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crashdump) +STD_ROM_FN(md_crashdump) + +struct BurnDriver BurnDrvmd_crashdump = { + "md_crashdump", "md_crashdum", NULL, NULL, "1993", + "The Incredible Crash Dummies (USA, Prototype)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crashdumpRomInfo, md_crashdumpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Incredible Hulk (Euro, USA) +static struct BurnRomInfo md_incrhulkRomDesc[] = { + { "incredible hulk, the (euro, usa).bin", 0x200000, 0x84a5a2dc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_incrhulk) +STD_ROM_FN(md_incrhulk) + +struct BurnDriver BurnDrvmd_incrhulk = { + "md_incrhulk", NULL, NULL, NULL, "1994", + "The Incredible Hulk (Euro, USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_incrhulkRomInfo, md_incrhulkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Indiana Jones and the Last Crusade (Euro) +static struct BurnRomInfo md_indycrusRomDesc[] = { + { "mpr-15207.bin", 0x100000, 0xeb8f4374, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_indycrus) +STD_ROM_FN(md_indycrus) + +struct BurnDriver BurnDrvmd_indycrus = { + "md_indycrus", NULL, NULL, NULL, "1992", + "Indiana Jones and the Last Crusade (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_indycrusRomInfo, md_indycrusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Indiana Jones and the Last Crusade (USA) +static struct BurnRomInfo md_indycrusuRomDesc[] = { + { "indiana jones and the last crusade (usa).bin", 0x100000, 0x3599a3fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_indycrusu) +STD_ROM_FN(md_indycrusu) + +struct BurnDriver BurnDrvmd_indycrusu = { + "md_indycrusu", "md_indycrus", NULL, NULL, "1992", + "Indiana Jones and the Last Crusade (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_indycrusuRomInfo, md_indycrusuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Insector X (USA) +static struct BurnRomInfo md_insectxRomDesc[] = { + { "insector x (usa).bin", 0x080000, 0x70626304, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_insectx) +STD_ROM_FN(md_insectx) + +struct BurnDriver BurnDrvmd_insectx = { + "md_insectx", NULL, NULL, NULL, "1990", + "Insector X (USA)\0", NULL, "Sage's Creation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_insectxRomInfo, md_insectxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Insector X (Jpn, Kor) +static struct BurnRomInfo md_insectxjRomDesc[] = { + { "insector x (jpn, kor).bin", 0x080000, 0x9625c434, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_insectxj) +STD_ROM_FN(md_insectxj) + +struct BurnDriver BurnDrvmd_insectxj = { + "md_insectxj", "md_insectx", NULL, NULL, "1990", + "Insector X (Jpn, Kor)\0", NULL, "Hot-B", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_insectxjRomInfo, md_insectxjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (USA) +static struct BurnRomInfo md_instchRomDesc[] = { + { "instruments of chaos starring young indiana jones (usa).bin", 0x100000, 0x4e384ef0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instch) +STD_ROM_FN(md_instch) + +struct BurnDriver BurnDrvmd_instch = { + "md_instch", NULL, NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchRomInfo, md_instchRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (USA, Prototype) +static struct BurnRomInfo md_instchp1RomDesc[] = { + { "instruments of chaos starring young indiana jones (usa) (beta).bin", 0x180000, 0xad6c2050, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp1) +STD_ROM_FN(md_instchp1) + +struct BurnDriver BurnDrvmd_instchp1 = { + "md_instchp1", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp1RomInfo, md_instchp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19941229) +static struct BurnRomInfo md_instchp2RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - dec 29, 1994).bin", 0x100000, 0x94b02351, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp2) +STD_ROM_FN(md_instchp2) + +struct BurnDriver BurnDrvmd_instchp2 = { + "md_instchp2", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19941229)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp2RomInfo, md_instchp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19941228-A) +static struct BurnRomInfo md_instchp3RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - dec 28, 1994 - a).bin", 0x0ff73c, 0xf285ad46, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp3) +STD_ROM_FN(md_instchp3) + +struct BurnDriver BurnDrvmd_instchp3 = { + "md_instchp3", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19941228-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp3RomInfo, md_instchp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940101) +static struct BurnRomInfo md_instchp8RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - jan 01, 1994).bin", 0x100000, 0x263f1a4c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp8) +STD_ROM_FN(md_instchp8) + +struct BurnDriver BurnDrvmd_instchp8 = { + "md_instchp8", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940101)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp8RomInfo, md_instchp8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940103) +static struct BurnRomInfo md_instchp7RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - jan 03, 1994).bin", 0x100000, 0x3c46d83d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp7) +STD_ROM_FN(md_instchp7) + +struct BurnDriver BurnDrvmd_instchp7 = { + "md_instchp7", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940103)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp7RomInfo, md_instchp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940126) +static struct BurnRomInfo md_instchp6RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - jan 26, 1994).bin", 0x100000, 0xf3498542, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp6) +STD_ROM_FN(md_instchp6) + +struct BurnDriver BurnDrvmd_instchp6 = { + "md_instchp6", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940126)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp6RomInfo, md_instchp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940127) +static struct BurnRomInfo md_instchp5RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - jan 27, 1994).bin", 0x100000, 0xf43112c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp5) +STD_ROM_FN(md_instchp5) + +struct BurnDriver BurnDrvmd_instchp5 = { + "md_instchp5", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940127)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp5RomInfo, md_instchp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940923-A) +static struct BurnRomInfo md_instchp4RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - sep 23, 1994 - a).bin", 0x0fe3c4, 0x14443a29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp4) +STD_ROM_FN(md_instchp4) + +struct BurnDriver BurnDrvmd_instchp4 = { + "md_instchp4", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19940923-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp4RomInfo, md_instchp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Instruments of Chaos Starring Young Indiana Jones (Prototype, 19931228) +static struct BurnRomInfo md_instchp9RomDesc[] = { + { "instruments of chaos starring young indiana jones (prototype - dec 28, 1993).bin", 0x100000, 0x51ca641c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_instchp9) +STD_ROM_FN(md_instchp9) + +struct BurnDriver BurnDrvmd_instchp9 = { + "md_instchp9", "md_instch", NULL, NULL, "1994", + "Instruments of Chaos Starring Young Indiana Jones (Prototype, 19931228)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_instchp9RomInfo, md_instchp9RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// International Rugby (Euro) +static struct BurnRomInfo md_intrugbyRomDesc[] = { + { "international rugby (euro).bin", 0x080000, 0xd97d1699, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_intrugby) +STD_ROM_FN(md_intrugby) + +struct BurnDriver BurnDrvmd_intrugby = { + "md_intrugby", NULL, NULL, NULL, "1993", + "International Rugby (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_intrugbyRomInfo, md_intrugbyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// International Superstar Soccer Deluxe (Euro) +static struct BurnRomInfo md_issdxRomDesc[] = { + { "international superstar soccer deluxe (euro).bin", 0x200000, 0x9bb3b180, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_issdx) +STD_ROM_FN(md_issdx) + +struct BurnDriver BurnDrvmd_issdx = { + "md_issdx", NULL, NULL, NULL, "1996", + "International Superstar Soccer Deluxe (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_issdxRomInfo, md_issdxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ronaldinho 98 (Pirate) +static struct BurnRomInfo md_ronaldRomDesc[] = { + { "ronaldinho 98 (pirate).bin", 0x200000, 0xdd27c84e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ronald) +STD_ROM_FN(md_ronald) + +struct BurnDriver BurnDrvmd_ronald = { + "md_ronald", "md_issdx", NULL, NULL, "199?", + "Ronaldinho 98 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ronaldRomInfo, md_ronaldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ishido - The Way of Stones (USA) +static struct BurnRomInfo md_ishidoRomDesc[] = { + { "mb834200a.bin", 0x020000, 0xb1de7d5e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ishido) +STD_ROM_FN(md_ishido) + +struct BurnDriver BurnDrvmd_ishido = { + "md_ishido", NULL, NULL, NULL, "1990", + "Ishido - The Way of Stones (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ishidoRomInfo, md_ishidoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// It Came from the Desert (USA) +static struct BurnRomInfo md_itcameRomDesc[] = { + { "it came from the desert (usa).bin", 0x080000, 0x25afb4f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_itcame) +STD_ROM_FN(md_itcame) + +struct BurnDriver BurnDrvmd_itcame = { + "md_itcame", NULL, NULL, NULL, "1990", + "It Came from the Desert (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_itcameRomInfo, md_itcameRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Itchy and Scratchy Game (USA, Prototype) +static struct BurnRomInfo md_itchyRomDesc[] = { + { "itchy and scratchy game, the (usa) (prototype).bin", 0x100000, 0x81b7725d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_itchy) +STD_ROM_FN(md_itchy) + +struct BurnDriver BurnDrvmd_itchy = { + "md_itchy", NULL, NULL, NULL, "1994", + "The Itchy and Scratchy Game (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_itchyRomInfo, md_itchyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Izzy's Quest for the Olympic Rings (Euro, USA) +static struct BurnRomInfo md_izzyqstRomDesc[] = { + { "izzy's quest for the olympic rings (euro, usa).bin", 0x200000, 0x77b416e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_izzyqst) +STD_ROM_FN(md_izzyqst) + +struct BurnDriver BurnDrvmd_izzyqst = { + "md_izzyqst", NULL, NULL, NULL, "1995", + "Izzy's Quest for the Olympic Rings (Euro, USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_izzyqstRomInfo, md_izzyqstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// J. League Pro Striker (Jpn, v1.3) +static struct BurnRomInfo md_jlpsRomDesc[] = { + { "j. league pro striker (jpn) (v1.3).bin", 0x100000, 0x2d5b7a11, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jlps) +STD_ROM_FN(md_jlps) + +struct BurnDriver BurnDrvmd_jlps = { + "md_jlps", NULL, NULL, NULL, "1993", + "J. League Pro Striker (Jpn, v1.3)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_jlpsRomInfo, md_jlpsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// J. League Pro Striker (Jpn, v1.0) +static struct BurnRomInfo md_jlpsaRomDesc[] = { + { "j. league pro striker (jpn) (v1.0).bin", 0x100000, 0xec229156, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jlpsa) +STD_ROM_FN(md_jlpsa) + +struct BurnDriver BurnDrvmd_jlpsa = { + "md_jlpsa", "md_jlps", NULL, NULL, "1993", + "J. League Pro Striker (Jpn, v1.0)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_jlpsaRomInfo, md_jlpsaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// J. League Pro Striker 2 (Jpn) +static struct BurnRomInfo md_jlps2RomDesc[] = { + { "mpr-16857.bin", 0x200000, 0x9fe71002, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jlps2) +STD_ROM_FN(md_jlps2) + +struct BurnDriver BurnDrvmd_jlps2 = { + "md_jlps2", NULL, NULL, NULL, "1994", + "J. League Pro Striker 2 (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_jlps2RomInfo, md_jlps2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Striker Final Stage (Jpn) +static struct BurnRomInfo md_prostrfsRomDesc[] = { + { "j. league pro striker final stage (jpn).bin", 0x200000, 0xe35e25fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_prostrfs) +STD_ROM_FN(md_prostrfs) + +struct BurnDriver BurnDrvmd_prostrfs = { + "md_prostrfs", NULL, NULL, NULL, "1995", + "Pro Striker Final Stage (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_prostrfsRomInfo, md_prostrfsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// J. League Pro Striker Perfect (Jpn) +static struct BurnRomInfo md_jlpspRomDesc[] = { + { "mpr-16267.bin", 0x100000, 0x0abed379, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jlpsp) +STD_ROM_FN(md_jlpsp) + +struct BurnDriver BurnDrvmd_jlpsp = { + "md_jlpsp", NULL, NULL, NULL, "1993", + "J. League Pro Striker Perfect (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_jlpspRomInfo, md_jlpspRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jack Nicklaus' Power Challenge Golf (Euro, USA) +static struct BurnRomInfo md_jacknickRomDesc[] = { + { "jack nicklaus' power challenge golf (euro, usa).bin", 0x100000, 0x5545e909, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jacknick) +STD_ROM_FN(md_jacknick) + +struct BurnDriver BurnDrvmd_jacknick = { + "md_jacknick", NULL, NULL, NULL, "1993", + "Jack Nicklaus' Power Challenge Golf (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_jacknickRomInfo, md_jacknickRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James 'Buster' Douglas Knockout Boxing (Euro, USA) +static struct BurnRomInfo md_jbdougkoRomDesc[] = { + { "mpr-13262.bin", 0x080000, 0x87bbcf2a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jbdougko) +STD_ROM_FN(md_jbdougko) + +struct BurnDriver BurnDrvmd_jbdougko = { + "md_jbdougko", NULL, NULL, NULL, "1990", + "James 'Buster' Douglas Knockout Boxing (Euro, USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jbdougkoRomInfo, md_jbdougkoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Final Blow (Jpn) +static struct BurnRomInfo md_finalbRomDesc[] = { + { "final blow (jpn).bin", 0x080000, 0x48ad505d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_finalb) +STD_ROM_FN(md_finalb) + +struct BurnDriver BurnDrvmd_finalb = { + "md_finalb", "md_jbdougko", NULL, NULL, "1990", + "Final Blow (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_finalbRomInfo, md_finalbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Bond 007 - The Duel (USA) +static struct BurnRomInfo md_jb007uRomDesc[] = { + { "james bond 007 - the duel (usa).bin", 0x080000, 0x4e614548, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jb007u) +STD_ROM_FN(md_jb007u) + +struct BurnDriver BurnDrvmd_jb007u = { + "md_jb007u", "md_jb007", NULL, NULL, "1992", + "James Bond 007 - The Duel (USA)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jb007uRomInfo, md_jb007uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 007 Shitou - The Duel (Jpn) +static struct BurnRomInfo md_007shitouRomDesc[] = { + { "007 shitou - the duel (jpn).bin", 0x080000, 0xaeb4b262, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_007shitou) +STD_ROM_FN(md_007shitou) + +struct BurnDriver BurnDrvmd_007shitou = { + "md_007shitou", "md_jb007", NULL, NULL, "1993", + "007 Shitou - The Duel (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_007shitouRomInfo, md_007shitouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Pond II - Codename Robocod (Jpn, Kor) +static struct BurnRomInfo md_jpond2jRomDesc[] = { + { "james pond ii - codename robocod (jpn, kor).bin", 0x080000, 0x98794702, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpond2j) +STD_ROM_FN(md_jpond2j) + +struct BurnDriver BurnDrvmd_jpond2j = { + "md_jpond2j", "md_jpond2", NULL, NULL, "1993", + "James Pond II - Codename Robocod (Jpn, Kor)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpond2jRomInfo, md_jpond2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// James Pond 3 - Operation Starfish (Euro, USA) +static struct BurnRomInfo md_jpond3RomDesc[] = { + { "james pond 3 - operation starfish (euro, usa).bin", 0x200000, 0x26f64b2a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpond3) +STD_ROM_FN(md_jpond3) + +struct BurnDriver BurnDrvmd_jpond3 = { + "md_jpond3", NULL, NULL, NULL, "1993", + "James Pond 3 - Operation Starfish (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpond3RomInfo, md_jpond3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jammit (USA) +static struct BurnRomInfo md_jammitRomDesc[] = { + { "jammit (usa).bin", 0x200000, 0xd91b52b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jammit) +STD_ROM_FN(md_jammit) + +struct BurnDriver BurnDrvmd_jammit = { + "md_jammit", NULL, NULL, NULL, "1994", + "Jammit (USA)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jammitRomInfo, md_jammitRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Janou Touryuumon (Jpn) +static struct BurnRomInfo md_janoutRomDesc[] = { + { "janou touryuumon (jpn).bin", 0x100000, 0xb5ef97c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_janout) +STD_ROM_FN(md_janout) + +struct BurnDriver BurnDrvmd_janout = { + "md_janout", NULL, NULL, NULL, "1993", + "Janou Touryuumon (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_janoutRomInfo, md_janoutRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jantei Monogatari (Jpn) +static struct BurnRomInfo md_janteiRomDesc[] = { + { "jantei monogatari (jpn).bin", 0x100000, 0x8a1b19ad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jantei) +STD_ROM_FN(md_jantei) + +struct BurnDriver BurnDrvmd_jantei = { + "md_jantei", NULL, NULL, NULL, "1991", + "Jantei Monogatari (Jpn)\0", NULL, "Reno", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_janteiRomInfo, md_janteiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jelly Boy (Euro, Prototype) +static struct BurnRomInfo md_jellyboyRomDesc[] = { + { "jelly boy (euro) (prototype).bin", 0x100000, 0x7cfadc16, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jellyboy) +STD_ROM_FN(md_jellyboy) + +struct BurnDriver BurnDrvmd_jellyboy = { + "md_jellyboy", NULL, NULL, NULL, "199?", + "Jelly Boy (Euro, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jellyboyRomInfo, md_jellyboyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jeopardy! (USA) +static struct BurnRomInfo md_jeopardyRomDesc[] = { + { "jeopardy! (usa).bin", 0x080000, 0x56cff3f1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jeopardy) +STD_ROM_FN(md_jeopardy) + +struct BurnDriver BurnDrvmd_jeopardy = { + "md_jeopardy", NULL, NULL, NULL, "1992", + "Jeopardy! (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jeopardyRomInfo, md_jeopardyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jeopardy! Deluxe (USA) +static struct BurnRomInfo md_jeoparddRomDesc[] = { + { "jeopardy! deluxe (usa).bin", 0x080000, 0x25e2f9d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jeopardd) +STD_ROM_FN(md_jeopardd) + +struct BurnDriver BurnDrvmd_jeopardd = { + "md_jeopardd", NULL, NULL, NULL, "1993", + "Jeopardy! Deluxe (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jeoparddRomInfo, md_jeoparddRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jeopardy! Sports Edition (USA) +static struct BurnRomInfo md_jeopardsRomDesc[] = { + { "jeopardy! sports edition (usa).bin", 0x080000, 0x13f924d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jeopards) +STD_ROM_FN(md_jeopards) + +struct BurnDriver BurnDrvmd_jeopards = { + "md_jeopards", NULL, NULL, NULL, "1993", + "Jeopardy! Sports Edition (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jeopardsRomInfo, md_jeopardsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jerry Glanville's Pigskin Footbrawl (USA) +static struct BurnRomInfo md_pigskinfRomDesc[] = { + { "jerry glanville's pigskin footbrawl (usa).bin", 0x100000, 0xe7f48d30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pigskinf) +STD_ROM_FN(md_pigskinf) + +struct BurnDriver BurnDrvmd_pigskinf = { + "md_pigskinf", NULL, NULL, NULL, "1992", + "Jerry Glanville's Pigskin Footbrawl (USA)\0", NULL, "Razorsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pigskinfRomInfo, md_pigskinfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jewel Master (Euro, USA, Rev. A) +static struct BurnRomInfo md_jewelmsRomDesc[] = { + { "mpr-14118a.bin", 0x080000, 0xcee98813, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jewelms) +STD_ROM_FN(md_jewelms) + +struct BurnDriver BurnDrvmd_jewelms = { + "md_jewelms", NULL, NULL, NULL, "1991", + "Jewel Master (Euro, USA, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jewelmsRomInfo, md_jewelmsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jewel Master (Jpn) +static struct BurnRomInfo md_jewelmsjRomDesc[] = { + { "jewel master (jpn).bin", 0x080000, 0x2cf6926c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jewelmsj) +STD_ROM_FN(md_jewelmsj) + +struct BurnDriver BurnDrvmd_jewelmsj = { + "md_jewelmsj", "md_jewelms", NULL, NULL, "1991", + "Jewel Master (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jewelmsjRomInfo, md_jewelmsjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jim Power - The Arcade Game (USA, Prototype) +static struct BurnRomInfo md_jimpowRomDesc[] = { + { "jim power - the arcade game (usa) (prototype) (bad dump).bin", 0x100000, 0x1cf3238b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jimpow) +STD_ROM_FN(md_jimpow) + +struct BurnDriver BurnDrvmd_jimpow = { + "md_jimpow", NULL, NULL, NULL, "199?", + "Jim Power - The Arcade Game (USA, Prototype)\0", NULL, "Loriciel", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jimpowRomInfo, md_jimpowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jimmy White's Whirlwind Snooker (Euro) +static struct BurnRomInfo md_jimmywwsRomDesc[] = { + { "jimmy white's whirlwind snooker (euro).bin", 0x080000, 0x0aef5b1f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jimmywws) +STD_ROM_FN(md_jimmywws) + +struct BurnDriver BurnDrvmd_jimmywws = { + "md_jimmywws", NULL, NULL, NULL, "1991", + "Jimmy White's Whirlwind Snooker (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jimmywwsRomInfo, md_jimmywwsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jiu Ji Ma Jiang II - Ye Yan Bian (Chi) +static struct BurnRomInfo md_jiujimRomDesc[] = { + { "jiu ji ma jiang ii - ye yan bian (chi) (unl).bin", 0x100000, 0xe9829b22, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jiujim) +STD_ROM_FN(md_jiujim) + +struct BurnDriver BurnDrvmd_jiujim = { + "md_jiujim", NULL, NULL, NULL, "199?", + "Jiu Ji Ma Jiang II - Ye Yan Bian (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jiujimRomInfo, md_jiujimRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Joe & Mac (USA) +static struct BurnRomInfo md_joemacRomDesc[] = { + { "joe & mac (usa).bin", 0x100000, 0x85bcc1c7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_joemac) +STD_ROM_FN(md_joemac) + +struct BurnDriver BurnDrvmd_joemac = { + "md_joemac", NULL, NULL, NULL, "1991", + "Joe & Mac (USA)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_joemacRomInfo, md_joemacRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Joe Montana Football (World) +static struct BurnRomInfo md_joemontRomDesc[] = { + { "mpr-13654.bin", 0x080000, 0x8aa6a1dd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_joemont) +STD_ROM_FN(md_joemont) + +struct BurnDriver BurnDrvmd_joemont = { + "md_joemont", NULL, NULL, NULL, "1990", + "Joe Montana Football (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_joemontRomInfo, md_joemontRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Joe Montana II Sports Talk Football (World, Rev. A) +static struct BurnRomInfo md_joemont2RomDesc[] = { + { "mpr-14356a.bin", 0x100000, 0xa45da893, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_joemont2) +STD_ROM_FN(md_joemont2) + +struct BurnDriver BurnDrvmd_joemont2 = { + "md_joemont2", NULL, NULL, NULL, "1991", + "Joe Montana II Sports Talk Football (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_joemont2RomInfo, md_joemont2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// John Madden Football '92 (Euro, USA) +static struct BurnRomInfo md_madden92RomDesc[] = { + { "john madden football '92 (euro, usa).bin", 0x080000, 0x046e3945, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden92) +STD_ROM_FN(md_madden92) + +struct BurnDriver BurnDrvmd_madden92 = { + "md_madden92", NULL, NULL, NULL, "1991", + "John Madden Football '92 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madden92RomInfo, md_madden92RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// John Madden Football '93 (Euro, USA) +static struct BurnRomInfo md_madden93RomDesc[] = { + { "jmf302.bin", 0x100000, 0xca323b3e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden93) +STD_ROM_FN(md_madden93) + +struct BurnDriver BurnDrvmd_madden93 = { + "md_madden93", NULL, NULL, NULL, "1992", + "John Madden Football '93 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madden93RomInfo, md_madden93RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// John Madden Football '93 - Championship Edition (USA) +static struct BurnRomInfo md_madd93ceRomDesc[] = { + { "john madden football '93 - championship edition (usa).bin", 0x100000, 0xca534b1a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madd93ce) +STD_ROM_FN(md_madd93ce) + +struct BurnDriver BurnDrvmd_madd93ce = { + "md_madd93ce", NULL, NULL, NULL, "1992", + "John Madden Football '93 - Championship Edition (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madd93ceRomInfo, md_madd93ceRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// John Madden Football (Euro, USA) +static struct BurnRomInfo md_maddenRomDesc[] = { + { "john madden football (euro, usa).bin", 0x080000, 0x90fb8818, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden) +STD_ROM_FN(md_madden) + +struct BurnDriver BurnDrvmd_madden = { + "md_madden", NULL, NULL, NULL, "1990", + "John Madden Football (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_maddenRomInfo, md_maddenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// John Madden Football - Pro Football (Jpn) +static struct BurnRomInfo md_maddenjRomDesc[] = { + { "john madden football - pro football (jpn).bin", 0x080000, 0x0460611c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_maddenj) +STD_ROM_FN(md_maddenj) + +struct BurnDriver BurnDrvmd_maddenj = { + "md_maddenj", "md_madden", NULL, NULL, "1992", + "John Madden Football - Pro Football (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_maddenjRomInfo, md_maddenjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jordan Vs Bird (Euro, USA, v1.1) +static struct BurnRomInfo md_jordanbRomDesc[] = { + { "jordan vs bird (euro, usa) (v1.1).bin", 0x080000, 0x4d3ddd7c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jordanb) +STD_ROM_FN(md_jordanb) + +struct BurnDriver BurnDrvmd_jordanb = { + "md_jordanb", NULL, NULL, NULL, "1992", + "Jordan Vs Bird (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jordanbRomInfo, md_jordanbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jordan Vs Bird (Euro, USA) +static struct BurnRomInfo md_jordanb1RomDesc[] = { + { "jordan vs bird (euro, usa).bin", 0x080000, 0x22d77e6d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jordanb1) +STD_ROM_FN(md_jordanb1) + +struct BurnDriver BurnDrvmd_jordanb1 = { + "md_jordanb1", "md_jordanb", NULL, NULL, "1992", + "Jordan Vs Bird (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jordanb1RomInfo, md_jordanb1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jordan Vs Bird - One on One (Jpn) +static struct BurnRomInfo md_jordanbjRomDesc[] = { + { "jordan vs bird - one on one (jpn).bin", 0x080000, 0x8837e896, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jordanbj) +STD_ROM_FN(md_jordanbj) + +struct BurnDriver BurnDrvmd_jordanbj = { + "md_jordanbj", "md_jordanb", NULL, NULL, "1993", + "Jordan Vs Bird - One on One (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jordanbjRomInfo, md_jordanbjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Joshua & The Battle of Jericho (USA) +static struct BurnRomInfo md_joshuaRomDesc[] = { + { "joshua & the battle of jericho (usa) (unl).bin", 0x040000, 0xda9e25aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_joshua) +STD_ROM_FN(md_joshua) + +struct BurnDriver BurnDrvmd_joshua = { + "md_joshua", NULL, NULL, NULL, "1992", + "Joshua & The Battle of Jericho (USA)\0", NULL, "Wisdom Tree", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_joshuaRomInfo, md_joshuaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Judge Dredd (World) +static struct BurnRomInfo md_jdreddRomDesc[] = { + { "judge dredd (world).bin", 0x200000, 0xea342ed8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jdredd) +STD_ROM_FN(md_jdredd) + +struct BurnDriver BurnDrvmd_jdredd = { + "md_jdredd", NULL, NULL, NULL, "1995", + "Judge Dredd (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jdreddRomInfo, md_jdreddRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Judge Dredd (USA, Prototype, Alt) +static struct BurnRomInfo md_jdreddp2RomDesc[] = { + { "judge dredd (usa) (beta) (alt).bin", 0x200000, 0xe649f784, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jdreddp2) +STD_ROM_FN(md_jdreddp2) + +struct BurnDriver BurnDrvmd_jdreddp2 = { + "md_jdreddp2", "md_jdredd", NULL, NULL, "1995", + "Judge Dredd (USA, Prototype, Alt)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jdreddp2RomInfo, md_jdreddp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Judge Dredd (USA, Prototype) +static struct BurnRomInfo md_jdreddp1RomDesc[] = { + { "judge dredd (usa) (beta).bin", 0x200000, 0x8d46f4da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jdreddp1) +STD_ROM_FN(md_jdreddp1) + +struct BurnDriver BurnDrvmd_jdreddp1 = { + "md_jdreddp1", "md_jdredd", NULL, NULL, "1995", + "Judge Dredd (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jdreddp1RomInfo, md_jdreddp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Junction (Jpn, USA) +static struct BurnRomInfo md_junctionRomDesc[] = { + { "junction (usa, jpn).bin", 0x080000, 0x94cdce8d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_junction) +STD_ROM_FN(md_junction) + +struct BurnDriver BurnDrvmd_junction = { + "md_junction", NULL, NULL, NULL, "1990", + "Junction (Jpn, USA)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_junctionRomInfo, md_junctionRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's The Jungle Book (Euro) +static struct BurnRomInfo md_jungleRomDesc[] = { + { "jungle book, the (euro).bin", 0x200000, 0xb9709a99, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jungle) +STD_ROM_FN(md_jungle) + +struct BurnDriver BurnDrvmd_jungle = { + "md_jungle", NULL, NULL, NULL, "1994", + "Disney's The Jungle Book (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jungleRomInfo, md_jungleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Disney's The Jungle Book (USA) +static struct BurnRomInfo md_jungleuRomDesc[] = { + { "jungle book, the (usa).bin", 0x200000, 0x3fb6d92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jungleu) +STD_ROM_FN(md_jungleu) + +struct BurnDriver BurnDrvmd_jungleu = { + "md_jungleu", "md_jungle", NULL, NULL, "1994", + "Disney's The Jungle Book (USA)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jungleuRomInfo, md_jungleuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jungle Strike (Euro, USA) +static struct BurnRomInfo md_jstrikeRomDesc[] = { + { "jungle strike (euro, usa).bin", 0x200000, 0xa5d29735, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jstrike) +STD_ROM_FN(md_jstrike) + +struct BurnDriver BurnDrvmd_jstrike = { + "md_jstrike", NULL, NULL, NULL, "1993", + "Jungle Strike (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jstrikeRomInfo, md_jstrikeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jungle Strike (USA, Prototype) +static struct BurnRomInfo md_jstrikepRomDesc[] = { + { "jungle strike (usa) (beta).bin", 0x200000, 0x0cd540d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jstrikep) +STD_ROM_FN(md_jstrikep) + +struct BurnDriver BurnDrvmd_jstrikep = { + "md_jstrikep", "md_jstrike", NULL, NULL, "1993", + "Jungle Strike (USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jstrikepRomInfo, md_jstrikepRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jungle Strike - Uketsugareta Kyouki (Jpn) +static struct BurnRomInfo md_jstrikejRomDesc[] = { + { "jungle strike - uketsugareta kyouki (jpn).bin", 0x200000, 0xba7a870b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jstrikej) +STD_ROM_FN(md_jstrikej) + +struct BurnDriver BurnDrvmd_jstrikej = { + "md_jstrikej", "md_jstrike", NULL, NULL, "1993", + "Jungle Strike - Uketsugareta Kyouki (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jstrikejRomInfo, md_jstrikejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park (Euro) +static struct BurnRomInfo md_jparkRomDesc[] = { + { "mpr-15679.bin", 0x200000, 0x448341f6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpark) +STD_ROM_FN(md_jpark) + +struct BurnDriver BurnDrvmd_jpark = { + "md_jpark", NULL, NULL, NULL, "1993", + "Jurassic Park (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jparkRomInfo, md_jparkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park (Jpn) +static struct BurnRomInfo md_jparkjRomDesc[] = { + { "jurassic park (jpn).bin", 0x200000, 0xec8e5783, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jparkj) +STD_ROM_FN(md_jparkj) + +struct BurnDriver BurnDrvmd_jparkj = { + "md_jparkj", "md_jpark", NULL, NULL, "1993", + "Jurassic Park (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jparkjRomInfo, md_jparkjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park (USA) +static struct BurnRomInfo md_jparkuRomDesc[] = { + { "jurassic park (usa).bin", 0x200000, 0x7b31deef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jparku) +STD_ROM_FN(md_jparku) + +struct BurnDriver BurnDrvmd_jparku = { + "md_jparku", "md_jpark", NULL, NULL, "1993", + "Jurassic Park (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jparkuRomInfo, md_jparkuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park (USA, Prototype) +static struct BurnRomInfo md_jparkupRomDesc[] = { + { "jurassic park (usa) (beta).bin", 0x200000, 0xcf890eed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jparkup) +STD_ROM_FN(md_jparkup) + +struct BurnDriver BurnDrvmd_jparkup = { + "md_jparkup", "md_jpark", NULL, NULL, "1993", + "Jurassic Park (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jparkupRomInfo, md_jparkupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Euro, USA) +static struct BurnRomInfo md_jpramRomDesc[] = { + { "jurassic park - rampage edition (euro, usa).bin", 0x200000, 0x98b4aa1b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpram) +STD_ROM_FN(md_jpram) + +struct BurnDriver BurnDrvmd_jpram = { + "md_jpram", NULL, NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramRomInfo, md_jpramRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940708) +static struct BurnRomInfo md_jpramp6RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 08, 1994).bin", 0x200000, 0xf4c78bd0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp6) +STD_ROM_FN(md_jpramp6) + +struct BurnDriver BurnDrvmd_jpramp6 = { + "md_jpramp6", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940708)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp6RomInfo, md_jpramp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940713) +static struct BurnRomInfo md_jpramp5RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 13, 1994).bin", 0x200000, 0x8475a105, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp5) +STD_ROM_FN(md_jpramp5) + +struct BurnDriver BurnDrvmd_jpramp5 = { + "md_jpramp5", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940713)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp5RomInfo, md_jpramp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940714) +static struct BurnRomInfo md_jpramp4RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 14, 1994).bin", 0x200000, 0x9bf0e28d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp4) +STD_ROM_FN(md_jpramp4) + +struct BurnDriver BurnDrvmd_jpramp4 = { + "md_jpramp4", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940714)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp4RomInfo, md_jpramp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940715) +static struct BurnRomInfo md_jpramp3RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 15, 1994).bin", 0x200000, 0xd2202be5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp3) +STD_ROM_FN(md_jpramp3) + +struct BurnDriver BurnDrvmd_jpramp3 = { + "md_jpramp3", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940715)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp3RomInfo, md_jpramp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940717) +static struct BurnRomInfo md_jpramp2RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 17, 1994).bin", 0x200000, 0x2eae6140, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp2) +STD_ROM_FN(md_jpramp2) + +struct BurnDriver BurnDrvmd_jpramp2 = { + "md_jpramp2", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940717)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp2RomInfo, md_jpramp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940718) +static struct BurnRomInfo md_jpramp1RomDesc[] = { + { "jurassic park - rampage edition (prototype - jul 18, 1994).bin", 0x200000, 0x1a62b826, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp1) +STD_ROM_FN(md_jpramp1) + +struct BurnDriver BurnDrvmd_jpramp1 = { + "md_jpramp1", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940718)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp1RomInfo, md_jpramp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940620) +static struct BurnRomInfo md_jpramp9RomDesc[] = { + { "jurassic park - rampage edition (prototype - jun 20, 1994).bin", 0x1f6e60, 0x1280fa5c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp9) +STD_ROM_FN(md_jpramp9) + +struct BurnDriver BurnDrvmd_jpramp9 = { + "md_jpramp9", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940620)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp9RomInfo, md_jpramp9RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940622) +static struct BurnRomInfo md_jpramp8RomDesc[] = { + { "jurassic park - rampage edition (prototype - jun 22, 1994).bin", 0x200000, 0x53582f2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp8) +STD_ROM_FN(md_jpramp8) + +struct BurnDriver BurnDrvmd_jpramp8 = { + "md_jpramp8", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940622)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp8RomInfo, md_jpramp8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jurassic Park - Rampage Edition (Prototype, 19940630) +static struct BurnRomInfo md_jpramp7RomDesc[] = { + { "jurassic park - rampage edition (prototype - jun 30, 1994).bin", 0x200000, 0xbff4b396, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jpramp7) +STD_ROM_FN(md_jpramp7) + +struct BurnDriver BurnDrvmd_jpramp7 = { + "md_jpramp7", "md_jpram", NULL, NULL, "1994", + "Jurassic Park - Rampage Edition (Prototype, 19940630)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jpramp7RomInfo, md_jpramp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Justice League Task Force (World) +static struct BurnRomInfo md_jleagtfRomDesc[] = { + { "justice league task force (world).bin", 0x300000, 0x2a60ebe9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_jleagtf) +STD_ROM_FN(md_jleagtf) + +struct BurnDriver BurnDrvmd_jleagtf = { + "md_jleagtf", NULL, NULL, NULL, "1995", + "Justice League Task Force (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_jleagtfRomInfo, md_jleagtfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ka-Ge-Ki - Fists of Steel (USA) +static struct BurnRomInfo md_kagekiRomDesc[] = { + { "ka-ge-ki - fists of steel (usa).bin", 0x100000, 0xeffc0fa6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kageki) +STD_ROM_FN(md_kageki) + +struct BurnDriver BurnDrvmd_kageki = { + "md_kageki", NULL, NULL, NULL, "1991", + "Ka-Ge-Ki - Fists of Steel (USA)\0", NULL, "Sage's Creation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kagekiRomInfo, md_kagekiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ka-Ge-Ki (Jpn) +static struct BurnRomInfo md_kagekijRomDesc[] = { + { "ka-ge-ki (jpn).bin", 0x100000, 0x391866a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kagekij) +STD_ROM_FN(md_kagekij) + +struct BurnDriver BurnDrvmd_kagekij = { + "md_kagekij", "md_kageki", NULL, NULL, "1991", + "Ka-Ge-Ki (Jpn)\0", NULL, "Hot-B", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kagekijRomInfo, md_kagekijRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kawasaki Superbike Challenge (Euro, USA) +static struct BurnRomInfo md_kawasakiRomDesc[] = { + { "kawasaki superbike challenge (euro, usa).bin", 0x100000, 0x631cc8e9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kawasaki) +STD_ROM_FN(md_kawasaki) + +struct BurnDriver BurnDrvmd_kawasaki = { + "md_kawasaki", NULL, NULL, NULL, "1994", + "Kawasaki Superbike Challenge (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kawasakiRomInfo, md_kawasakiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kawasaki Superbike Challenge (USA, Prototype) +static struct BurnRomInfo md_kawasakipRomDesc[] = { + { "kawasaki superbike challenge (usa) (beta).bin", 0x100000, 0x55934d1b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kawasakip) +STD_ROM_FN(md_kawasakip) + +struct BurnDriver BurnDrvmd_kawasakip = { + "md_kawasakip", "md_kawasaki", NULL, NULL, "1994", + "Kawasaki Superbike Challenge (USA, Prototype)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kawasakipRomInfo, md_kawasakipRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kick Off 3 - European Challenge (Euro) +static struct BurnRomInfo md_kickoff3RomDesc[] = { + { "kick off 3 - european challenge (euro).bin", 0x100000, 0xbc37401a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kickoff3) +STD_ROM_FN(md_kickoff3) + +struct BurnDriver BurnDrvmd_kickoff3 = { + "md_kickoff3", NULL, NULL, NULL, "1994", + "Kick Off 3 - European Challenge (Euro)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kickoff3RomInfo, md_kickoff3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chameleon Kid (Jpn) +static struct BurnRomInfo md_kidchamjRomDesc[] = { + { "chameleon kid (jpn).bin", 0x100000, 0x50217c80, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kidchamj) +STD_ROM_FN(md_kidchamj) + +struct BurnDriver BurnDrvmd_kidchamj = { + "md_kidchamj", "md_kidcham", NULL, NULL, "1992", + "Chameleon Kid (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kidchamjRomInfo, md_kidchamjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kidou Keisatsu Patlabor - 98-shiki Kidou Seyo! (Jpn) +static struct BurnRomInfo md_patlaborRomDesc[] = { + { "kidou keisatsu patlabor - 98-shiki kidou seyo! (jpn).bin", 0x080000, 0x21a0e749, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_patlabor) +STD_ROM_FN(md_patlabor) + +struct BurnDriver BurnDrvmd_patlabor = { + "md_patlabor", NULL, NULL, NULL, "1992", + "Kidou Keisatsu Patlabor - 98-shiki Kidou Seyo! (Jpn)\0", NULL, "Ma-Ba", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_patlaborRomInfo, md_patlaborRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tougiou King Colossus (Jpn) +static struct BurnRomInfo md_kingcolRomDesc[] = { + { "mpr-14929.bin", 0x100000, 0xffe7b3c7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kingcol) +STD_ROM_FN(md_kingcol) + +struct BurnDriver BurnDrvmd_kingcol = { + "md_kingcol", NULL, NULL, NULL, "1992", + "Tougiou King Colossus (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_kingcolRomInfo, md_kingcolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King of the Monsters (Euro) +static struct BurnRomInfo md_kotmRomDesc[] = { + { "king of the monsters (euro).bin", 0x100000, 0x7a94fd49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kotm) +STD_ROM_FN(md_kotm) + +struct BurnDriver BurnDrvmd_kotm = { + "md_kotm", NULL, NULL, NULL, "1993", + "King of the Monsters (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kotmRomInfo, md_kotmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King of the Monsters (USA) +static struct BurnRomInfo md_kotmuRomDesc[] = { + { "king of the monsters (usa).bin", 0x100000, 0xf390d406, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kotmu) +STD_ROM_FN(md_kotmu) + +struct BurnDriver BurnDrvmd_kotmu = { + "md_kotmu", "md_kotm", NULL, NULL, "1993", + "King of the Monsters (USA)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kotmuRomInfo, md_kotmuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King of the Monsters (Jpn) +static struct BurnRomInfo md_kotmjRomDesc[] = { + { "king of the monsters (jpn).bin", 0x100000, 0x3af7e74e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kotmj) +STD_ROM_FN(md_kotmj) + +struct BurnDriver BurnDrvmd_kotmj = { + "md_kotmj", "md_kotm", NULL, NULL, "1993", + "King of the Monsters (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kotmjRomInfo, md_kotmjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King of the Monsters 2 (USA) +static struct BurnRomInfo md_kotm2RomDesc[] = { + { "king of the monsters 2 (usa).bin", 0x200000, 0xee1638ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kotm2) +STD_ROM_FN(md_kotm2) + +struct BurnDriver BurnDrvmd_kotm2 = { + "md_kotm2", NULL, NULL, NULL, "1994", + "King of the Monsters 2 (USA)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kotm2RomInfo, md_kotm2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King Salmon - The Big Catch (USA) +static struct BurnRomInfo md_kingsalRomDesc[] = { + { "king salmon - the big catch (usa).bin", 0x080000, 0xf516e7d9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kingsal) +STD_ROM_FN(md_kingsal) + +struct BurnDriver BurnDrvmd_kingsal = { + "md_kingsal", NULL, NULL, NULL, "1993", + "King Salmon - The Big Catch (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kingsalRomInfo, md_kingsalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King Salmon (Jpn) +static struct BurnRomInfo md_kingsaljRomDesc[] = { + { "king salmon (jpn).bin", 0x080000, 0x2cfc9f61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kingsalj) +STD_ROM_FN(md_kingsalj) + +struct BurnDriver BurnDrvmd_kingsalj = { + "md_kingsalj", "md_kingsal", NULL, NULL, "1992", + "King Salmon (Jpn)\0", NULL, "Hot-B", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kingsaljRomInfo, md_kingsaljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// King's Bounty - The Conqueror's Quest (Euro, USA) +static struct BurnRomInfo md_kingsbtyRomDesc[] = { + { "king's bounty - the conqueror's quest (euro, usa).bin", 0x080000, 0xaa68a92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kingsbty) +STD_ROM_FN(md_kingsbty) + +struct BurnDriver BurnDrvmd_kingsbty = { + "md_kingsbty", NULL, NULL, NULL, "1991", + "King's Bounty - The Conqueror's Quest (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kingsbtyRomInfo, md_kingsbtyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kishi Densetsu (Jpn) +static struct BurnRomInfo md_kishidenRomDesc[] = { + { "kishi densetsu (jpn).bin", 0x180000, 0x22e1f04a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kishiden) +STD_ROM_FN(md_kishiden) + +struct BurnDriver BurnDrvmd_kishiden = { + "md_kishiden", NULL, NULL, NULL, "1993", + "Kishi Densetsu (Jpn)\0", NULL, "Kodansha", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_kishidenRomInfo, md_kishidenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kiss Shot (Jpn, SegaNet) +static struct BurnRomInfo md_kissshotRomDesc[] = { + { "kiss shot (jpn) (sn).bin", 0x040000, 0xe487088c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kissshot) +STD_ROM_FN(md_kissshot) + +struct BurnDriver BurnDrvmd_kissshot = { + "md_kissshot", NULL, NULL, NULL, "1991", + "Kiss Shot (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kissshotRomInfo, md_kissshotRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Klax (Euro, USA) +static struct BurnRomInfo md_klaxRomDesc[] = { + { "klax (euro, usa).bin", 0x040000, 0x248cd09e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_klax) +STD_ROM_FN(md_klax) + +struct BurnDriver BurnDrvmd_klax = { + "md_klax", NULL, NULL, NULL, "1990", + "Klax (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_klaxRomInfo, md_klaxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Klax (Jpn) +static struct BurnRomInfo md_klaxjRomDesc[] = { + { "klax (jpn).bin", 0x040000, 0x1afcc1da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_klaxj) +STD_ROM_FN(md_klaxj) + +struct BurnDriver BurnDrvmd_klaxj = { + "md_klaxj", "md_klax", NULL, NULL, "1990", + "Klax (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_klaxjRomInfo, md_klaxjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Krusty's Super Fun House (Euro, USA, v1.1) +static struct BurnRomInfo md_krustyRomDesc[] = { + { "krusty's super fun house (euro, usa) (v1.1).bin", 0x080000, 0x56976261, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_krusty) +STD_ROM_FN(md_krusty) + +struct BurnDriver BurnDrvmd_krusty = { + "md_krusty", NULL, NULL, NULL, "1992", + "Krusty's Super Fun House (Euro, USA, v1.1)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_krustyRomInfo, md_krustyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Krusty's Super Fun House (Euro, USA) +static struct BurnRomInfo md_krusty1RomDesc[] = { + { "krusty's super fun house (euro, usa).bin", 0x080000, 0xf764005e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_krusty1) +STD_ROM_FN(md_krusty1) + +struct BurnDriver BurnDrvmd_krusty1 = { + "md_krusty1", "md_krusty", NULL, NULL, "1992", + "Krusty's Super Fun House (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_krusty1RomInfo, md_krusty1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kyuukai Douchuuki (Jpn) +static struct BurnRomInfo md_kyukaidkRomDesc[] = { + { "kyuukai douchuuki (jpn).bin", 0x080000, 0xde48dce3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kyukaidk) +STD_ROM_FN(md_kyukaidk) + +struct BurnDriver BurnDrvmd_kyukaidk = { + "md_kyukaidk", NULL, NULL, NULL, "1991", + "Kyuukai Douchuuki (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kyukaidkRomInfo, md_kyukaidkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// La Russa Baseball 95 (USA, Oceania) +static struct BurnRomInfo md_larussaRomDesc[] = { + { "la russa baseball 95 (usa, aus).bin", 0x200000, 0x3f848a92, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_larussa) +STD_ROM_FN(md_larussa) + +struct BurnDriver BurnDrvmd_larussa = { + "md_larussa", NULL, NULL, NULL, "1994", + "La Russa Baseball 95 (USA, Oceania)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_larussaRomInfo, md_larussaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lakers versus Celtics and the NBA Playoffs (USA) +static struct BurnRomInfo md_lakersRomDesc[] = { + { "lakers versus celtics and the nba playoffs (usa).bin", 0x080000, 0x0e33fc75, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lakers) +STD_ROM_FN(md_lakers) + +struct BurnDriver BurnDrvmd_lakers = { + "md_lakers", NULL, NULL, NULL, "1991", + "Lakers versus Celtics and the NBA Playoffs (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lakersRomInfo, md_lakersRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker - The Treasures of King Nole (Euro) +static struct BurnRomInfo md_landstlkRomDesc[] = { + { "landstalker - the treasures of king nole (euro).bin", 0x200000, 0xe3c65277, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlk) +STD_ROM_FN(md_landstlk) + +struct BurnDriver BurnDrvmd_landstlk = { + "md_landstlk", NULL, NULL, NULL, "1993", + "Landstalker - The Treasures of King Nole (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkRomInfo, md_landstlkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker - Le Tresor du Roi Nole (Fra) +static struct BurnRomInfo md_landstlkfRomDesc[] = { + { "landstalker - le tresor du roi nole (france).bin", 0x200000, 0x5de7d917, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlkf) +STD_ROM_FN(md_landstlkf) + +struct BurnDriver BurnDrvmd_landstlkf = { + "md_landstlkf", "md_landstlk", NULL, NULL, "1993", + "Landstalker - Le Tresor du Roi Nole (Fra)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkfRomInfo, md_landstlkfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker - Die Schatze von Konig Nolo (Ger) +static struct BurnRomInfo md_landstlkgRomDesc[] = { + { "landstalker - die schatze von konig nolo (germany).bin", 0x200000, 0x10fedb8f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlkg) +STD_ROM_FN(md_landstlkg) + +struct BurnDriver BurnDrvmd_landstlkg = { + "md_landstlkg", "md_landstlk", NULL, NULL, "1993", + "Landstalker - Die Schatze von Konig Nolo (Ger)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkgRomInfo, md_landstlkgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker - Koutei no Zaihou (Jpn) +static struct BurnRomInfo md_landstlkjRomDesc[] = { + { "landstalker - koutei no zaihou (jpn).bin", 0x200000, 0x60d4cedb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlkj) +STD_ROM_FN(md_landstlkj) + +struct BurnDriver BurnDrvmd_landstlkj = { + "md_landstlkj", "md_landstlk", NULL, NULL, "1992", + "Landstalker - Koutei no Zaihou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkjRomInfo, md_landstlkjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker (USA) +static struct BurnRomInfo md_landstlkuRomDesc[] = { + { "landstalker (usa).bin", 0x200000, 0xfbbb5b97, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlku) +STD_ROM_FN(md_landstlku) + +struct BurnDriver BurnDrvmd_landstlku = { + "md_landstlku", "md_landstlk", NULL, NULL, "1992", + "Landstalker (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkuRomInfo, md_landstlkuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Landstalker (USA, Prototype) +static struct BurnRomInfo md_landstlkupRomDesc[] = { + { "landstalker (usa) (beta).bin", 0x200000, 0x70483d03, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_landstlkup) +STD_ROM_FN(md_landstlkup) + +struct BurnDriver BurnDrvmd_landstlkup = { + "md_landstlkup", "md_landstlk", NULL, NULL, "1992", + "Landstalker (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_landstlkupRomInfo, md_landstlkupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Langrisser (Jpn) +static struct BurnRomInfo md_langrissRomDesc[] = { + { "mpr-13845.bin", 0x080000, 0xb6ea5016, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_langriss) +STD_ROM_FN(md_langriss) + +struct BurnDriver BurnDrvmd_langriss = { + "md_langriss", NULL, NULL, NULL, "1991", + "Langrisser (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_langrissRomInfo, md_langrissRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Langrisser II (Jpn, v1.2) +static struct BurnRomInfo md_langris2RomDesc[] = { + { "langrisser ii (jpn) (v1.2).bin", 0x200000, 0x4967c9f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_langris2) +STD_ROM_FN(md_langris2) + +struct BurnDriver BurnDrvmd_langris2 = { + "md_langris2", NULL, NULL, NULL, "1994", + "Langrisser II (Jpn, v1.2)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_langris2RomInfo, md_langris2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Langrisser II (Jpn, v1.1) +static struct BurnRomInfo md_langris2aRomDesc[] = { + { "langrisser ii (jpn) (v1.1).bin", 0x200000, 0x0caa0593, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_langris2a) +STD_ROM_FN(md_langris2a) + +struct BurnDriver BurnDrvmd_langris2a = { + "md_langris2a", "md_langris2", NULL, NULL, "1994", + "Langrisser II (Jpn, v1.1)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_langris2aRomInfo, md_langris2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Langrisser II (Jpn) +static struct BurnRomInfo md_langris2bRomDesc[] = { + { "langrisser ii (jpn).bin", 0x200000, 0x7f891dfc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_langris2b) +STD_ROM_FN(md_langris2b) + +struct BurnDriver BurnDrvmd_langris2b = { + "md_langris2b", "md_langris2", NULL, NULL, "1994", + "Langrisser II (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_langris2bRomInfo, md_langris2bRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Last Action Hero (Euro, USA) +static struct BurnRomInfo md_lastactRomDesc[] = { + { "last action hero (euro, usa).bin", 0x100000, 0x15357dde, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lastact) +STD_ROM_FN(md_lastact) + +struct BurnDriver BurnDrvmd_lastact = { + "md_lastact", NULL, NULL, NULL, "1993", + "Last Action Hero (Euro, USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lastactRomInfo, md_lastactRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Last Battle (Euro, USA, Kor) +static struct BurnRomInfo md_lastbtleRomDesc[] = { + { "mpr-12578.bin", 0x080000, 0xbbfaad77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lastbtle) +STD_ROM_FN(md_lastbtle) + +struct BurnDriver BurnDrvmd_lastbtle = { + "md_lastbtle", NULL, NULL, NULL, "1989", + "Last Battle (Euro, USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lastbtleRomInfo, md_lastbtleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hokuto no Ken - Shin Seikimatsu Kyuuseishu Densetsu (Jpn) +static struct BurnRomInfo md_hokutoRomDesc[] = { + { "hokuto no ken - shin seikimatsu kyuuseishu densetsu (jpn).bin", 0x080000, 0x1b6585e7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hokuto) +STD_ROM_FN(md_hokuto) + +struct BurnDriver BurnDrvmd_hokuto = { + "md_hokuto", "md_lastbtle", NULL, NULL, "1989", + "Hokuto no Ken - Shin Seikimatsu Kyuuseishu Densetsu (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hokutoRomInfo, md_hokutoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lawnmower Man (Euro, USA) +static struct BurnRomInfo md_lawnmowrRomDesc[] = { + { "lawnmower man, the (euro, usa).bin", 0x100000, 0xa7cacd59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lawnmowr) +STD_ROM_FN(md_lawnmowr) + +struct BurnDriver BurnDrvmd_lawnmowr = { + "md_lawnmowr", NULL, NULL, NULL, "1994", + "The Lawnmower Man (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lawnmowrRomInfo, md_lawnmowrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Galahad (Euro, USA) +static struct BurnRomInfo md_galahadRomDesc[] = { + { "gal01.bin", 0x100000, 0x679557bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_galahad) +STD_ROM_FN(md_galahad) + +struct BurnDriver BurnDrvmd_galahad = { + "md_galahad", NULL, NULL, NULL, "1992", + "Galahad (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_galahadRomInfo, md_galahadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lemmings (Euro) +static struct BurnRomInfo md_lemmingsRomDesc[] = { + { "mpr-15233.bin", 0x100000, 0x6a1a4579, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lemmings) +STD_ROM_FN(md_lemmings) + +struct BurnDriver BurnDrvmd_lemmings = { + "md_lemmings", NULL, NULL, NULL, "1992", + "Lemmings (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lemmingsRomInfo, md_lemmingsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lemmings (Jpn, USA, Kor, v1.1) +static struct BurnRomInfo md_lemmingsjuRomDesc[] = { + { "sunsoft_lem8_j.bin", 0x100000, 0x68c70362, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lemmingsju) +STD_ROM_FN(md_lemmingsju) + +struct BurnDriver BurnDrvmd_lemmingsju = { + "md_lemmingsju", "md_lemmings", NULL, NULL, "1992", + "Lemmings (Jpn, USA, Kor, v1.1)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lemmingsjuRomInfo, md_lemmingsjuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lemmings (Jpn, USA) +static struct BurnRomInfo md_lemmingsju1RomDesc[] = { + { "lemmings (usa, jpn).bin", 0x100000, 0xf015c2ad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lemmingsju1) +STD_ROM_FN(md_lemmingsju1) + +struct BurnDriver BurnDrvmd_lemmingsju1 = { + "md_lemmingsju1", "md_lemmings", NULL, NULL, "1992", + "Lemmings (Jpn, USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lemmingsju1RomInfo, md_lemmingsju1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lemmings 2 - The Tribes (Euro) +static struct BurnRomInfo md_lemming2RomDesc[] = { + { "lemmings 2 - the tribes (euro).bin", 0x200000, 0x741eb624, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lemming2) +STD_ROM_FN(md_lemming2) + +struct BurnDriver BurnDrvmd_lemming2 = { + "md_lemming2", NULL, NULL, NULL, "1994", + "Lemmings 2 - The Tribes (Euro)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lemming2RomInfo, md_lemming2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lemmings 2 - The Tribes (USA) +static struct BurnRomInfo md_lemming2uRomDesc[] = { + { "lemmings 2 - the tribes (usa).bin", 0x200000, 0xde59a3a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lemming2u) +STD_ROM_FN(md_lemming2u) + +struct BurnDriver BurnDrvmd_lemming2u = { + "md_lemming2u", "md_lemming2", NULL, NULL, "1994", + "Lemmings 2 - The Tribes (USA)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lemming2uRomInfo, md_lemming2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lethal Enforcers (Euro) +static struct BurnRomInfo md_lethalenRomDesc[] = { + { "lethal enforcers (euro).bin", 0x200000, 0xca2bf99d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lethalen) +STD_ROM_FN(md_lethalen) + +struct BurnDriver BurnDrvmd_lethalen = { + "md_lethalen", NULL, NULL, NULL, "1993", + "Lethal Enforcers (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lethalenRomInfo, md_lethalenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lethal Enforcers (Jpn) +static struct BurnRomInfo md_lethalenjRomDesc[] = { + { "fz008.bin", 0x200000, 0xf25f1e49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lethalenj) +STD_ROM_FN(md_lethalenj) + +struct BurnDriver BurnDrvmd_lethalenj = { + "md_lethalenj", "md_lethalen", NULL, NULL, "1993", + "Lethal Enforcers (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lethalenjRomInfo, md_lethalenjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lethal Enforcers (USA) +static struct BurnRomInfo md_lethalenuRomDesc[] = { + { "lethal enforcers (usa).bin", 0x200000, 0x51d9a84a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lethalenu) +STD_ROM_FN(md_lethalenu) + +struct BurnDriver BurnDrvmd_lethalenu = { + "md_lethalenu", "md_lethalen", NULL, NULL, "1993", + "Lethal Enforcers (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lethalenuRomInfo, md_lethalenuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lethal Enforcers II - Gun Fighters (Euro) +static struct BurnRomInfo md_le2RomDesc[] = { + { "lethal enforcers ii - gun fighters (euro).bin", 0x200000, 0x4bfe045c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_le2) +STD_ROM_FN(md_le2) + +struct BurnDriver BurnDrvmd_le2 = { + "md_le2", NULL, NULL, NULL, "1994", + "Lethal Enforcers II - Gun Fighters (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_le2RomInfo, md_le2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lethal Enforcers II - Gun Fighters (USA) +static struct BurnRomInfo md_le2uRomDesc[] = { + { "lethal enforcers ii - gun fighters (usa).bin", 0x200000, 0xe5fdd28b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_le2u) +STD_ROM_FN(md_le2u) + +struct BurnDriver BurnDrvmd_le2u = { + "md_le2u", "md_le2", NULL, NULL, "1994", + "Lethal Enforcers II - Gun Fighters (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_le2uRomInfo, md_le2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// LHX Attack Chopper (Euro, USA) +static struct BurnRomInfo md_lhxRomDesc[] = { + { "lhx04.bin", 0x100000, 0x70c3428d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lhx) +STD_ROM_FN(md_lhx) + +struct BurnDriver BurnDrvmd_lhx = { + "md_lhx", NULL, NULL, NULL, "1992", + "LHX Attack Chopper (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lhxRomInfo, md_lhxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// LHX Attack Chopper (Jpn) +static struct BurnRomInfo md_lhxjRomDesc[] = { + { "lhx attack chopper (jpn).bin", 0x100000, 0x224ff103, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lhxj) +STD_ROM_FN(md_lhxj) + +struct BurnDriver BurnDrvmd_lhxj = { + "md_lhxj", "md_lhx", NULL, NULL, "1993", + "LHX Attack Chopper (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lhxjRomInfo, md_lhxjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Liberty or Death (USA) +static struct BurnRomInfo md_libertyRomDesc[] = { + { "liberty or death (usa).bin", 0x200000, 0x2adb0364, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_liberty) +STD_ROM_FN(md_liberty) + +struct BurnDriver BurnDrvmd_liberty = { + "md_liberty", NULL, NULL, NULL, "1994", + "Liberty or Death (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_libertyRomInfo, md_libertyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Light Crusader (Jpn) +static struct BurnRomInfo md_lightcjRomDesc[] = { + { "light crusader (jpn).bin", 0x200000, 0x237076a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightcj) +STD_ROM_FN(md_lightcj) + +struct BurnDriver BurnDrvmd_lightcj = { + "md_lightcj", "md_lightc", NULL, NULL, "1995", + "Light Crusader (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lightcjRomInfo, md_lightcjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Light Crusader (Kor) +static struct BurnRomInfo md_lightckRomDesc[] = { + { "light crusader (kor).bin", 0x200000, 0x6d0cbcb2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightck) +STD_ROM_FN(md_lightck) + +struct BurnDriver BurnDrvmd_lightck = { + "md_lightck", "md_lightc", NULL, NULL, "1995", + "Light Crusader (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lightckRomInfo, md_lightckRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Light Crusader (Prototype, 19950608) +static struct BurnRomInfo md_lightcpRomDesc[] = { + { "light crusader (prototype - jun 08, 1995).bin", 0x200000, 0xe350ccfa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightcp) +STD_ROM_FN(md_lightcp) + +struct BurnDriver BurnDrvmd_lightcp = { + "md_lightcp", "md_lightc", NULL, NULL, "1995", + "Light Crusader (Prototype, 19950608)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lightcpRomInfo, md_lightcpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Light Crusader (USA) +static struct BurnRomInfo md_lightcuRomDesc[] = { + { "light crusader (usa).bin", 0x200000, 0xbeb715dc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightcu) +STD_ROM_FN(md_lightcu) + +struct BurnDriver BurnDrvmd_lightcu = { + "md_lightcu", "md_lightc", NULL, NULL, "1995", + "Light Crusader (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lightcuRomInfo, md_lightcuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lion King (World) +static struct BurnRomInfo md_lionkingRomDesc[] = { + { "mpr-17270.bin", 0x300000, 0x5696a5bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionking) +STD_ROM_FN(md_lionking) + +struct BurnDriver BurnDrvmd_lionking = { + "md_lionking", NULL, NULL, NULL, "1994", + "The Lion King (World)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lionkingRomInfo, md_lionkingRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lobo (USA, Prototype) +static struct BurnRomInfo md_loboRomDesc[] = { + { "lobo (usa) (prototype).bin", 0x300000, 0xb5e09338, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lobo) +STD_ROM_FN(md_lobo) + +struct BurnDriver BurnDrvmd_lobo = { + "md_lobo", NULL, NULL, NULL, "1996", + "Lobo (USA, Prototype)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_loboRomInfo, md_loboRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Long (Chi) +static struct BurnRomInfo md_longRomDesc[] = { + { "long (chi) (unl).bin", 0x040000, 0x1b86e623, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_long) +STD_ROM_FN(md_long) + +struct BurnDriver BurnDrvmd_long = { + "md_long", NULL, NULL, NULL, "199?", + "Long (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_longRomInfo, md_longRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lord Monarch - Tokoton Sentou Densetsu (Jpn) +static struct BurnRomInfo md_lordmonRomDesc[] = { + { "lord monarch - tokoton sentou densetsu (jpn).bin", 0x200000, 0x238bf5db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lordmon) +STD_ROM_FN(md_lordmon) + +struct BurnDriver BurnDrvmd_lordmon = { + "md_lordmon", NULL, NULL, NULL, "1994", + "Lord Monarch - Tokoton Sentou Densetsu (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_lordmonRomInfo, md_lordmonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lost Vikings (Euro) +static struct BurnRomInfo md_lostvikRomDesc[] = { + { "lost vikings, the (euro).bin", 0x100000, 0x1f14efc6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lostvik) +STD_ROM_FN(md_lostvik) + +struct BurnDriver BurnDrvmd_lostvik = { + "md_lostvik", NULL, NULL, NULL, "1993", + "The Lost Vikings (Euro)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lostvikRomInfo, md_lostvikRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lost Vikings (Euro, Prototype) +static struct BurnRomInfo md_lostvikpRomDesc[] = { + { "lost vikings, the (euro) (beta).bin", 0x100000, 0x17bed25f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lostvikp) +STD_ROM_FN(md_lostvikp) + +struct BurnDriver BurnDrvmd_lostvikp = { + "md_lostvikp", "md_lostvik", NULL, NULL, "1993", + "The Lost Vikings (Euro, Prototype)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lostvikpRomInfo, md_lostvikpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lost Vikings (USA) +static struct BurnRomInfo md_lostvikuRomDesc[] = { + { "lost vikings, the (usa).bin", 0x100000, 0x7ba49edb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lostviku) +STD_ROM_FN(md_lostviku) + +struct BurnDriver BurnDrvmd_lostviku = { + "md_lostviku", "md_lostvik", NULL, NULL, "1992", + "The Lost Vikings (USA)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lostvikuRomInfo, md_lostvikuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lost World - Jurassic Park (Euro, USA) +static struct BurnRomInfo md_lostwrldRomDesc[] = { + { "lost world, the - jurassic park (euro, usa).bin", 0x400000, 0x140a284c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lostwrld) +STD_ROM_FN(md_lostwrld) + +struct BurnDriver BurnDrvmd_lostwrld = { + "md_lostwrld", NULL, NULL, NULL, "1997", + "The Lost World - Jurassic Park (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lostwrldRomInfo, md_lostwrldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lotus II (Euro, USA) +static struct BurnRomInfo md_lotus2RomDesc[] = { + { "lot205.bin", 0x100000, 0x1d8ee010, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lotus2) +STD_ROM_FN(md_lotus2) + +struct BurnDriver BurnDrvmd_lotus2 = { + "md_lotus2", NULL, NULL, NULL, "1993", + "Lotus II (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lotus2RomInfo, md_lotus2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lotus II (USA, Prototype) +static struct BurnRomInfo md_lotus2pRomDesc[] = { + { "lotus ii (usa) (beta).bin", 0x100000, 0x2997b7d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lotus2p) +STD_ROM_FN(md_lotus2p) + +struct BurnDriver BurnDrvmd_lotus2p = { + "md_lotus2p", "md_lotus2", NULL, NULL, "1993", + "Lotus II (USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lotus2pRomInfo, md_lotus2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// M-1 Abrams Battle Tank (Euro, USA) +static struct BurnRomInfo md_m1abramsRomDesc[] = { + { "m-1 abrams battle tank (euro, usa).bin", 0x080000, 0x1e2f74cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_m1abrams) +STD_ROM_FN(md_m1abrams) + +struct BurnDriver BurnDrvmd_m1abrams = { + "md_m1abrams", NULL, NULL, NULL, "1991", + "M-1 Abrams Battle Tank (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_m1abramsRomInfo, md_m1abramsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ma Qiao E Mo Ta - Devilish Mahjong Tower (Chi) +static struct BurnRomInfo md_maqiaoRomDesc[] = { + { "ma qiao e mo ta - devilish mahjong tower (chi) (unl).bin", 0x100000, 0x12e35994, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_maqiao) +STD_ROM_FN(md_maqiao) + +struct BurnDriver BurnDrvmd_maqiao = { + "md_maqiao", NULL, NULL, NULL, "1994", + "Ma Qiao E Mo Ta - Devilish Mahjong Tower (Chi)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_maqiaoRomInfo, md_maqiaoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madden NFL '94 (Euro, USA) +static struct BurnRomInfo md_madden94RomDesc[] = { + { "madden nfl '94 (euro, usa).bin", 0x200000, 0xd14b811b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden94) +STD_ROM_FN(md_madden94) + +struct BurnDriver BurnDrvmd_madden94 = { + "md_madden94", NULL, NULL, NULL, "1994", + "Madden NFL '94 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_madden94RomInfo, md_madden94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madden NFL 95 (Euro, USA) +static struct BurnRomInfo md_madden95RomDesc[] = { + { "madden nfl 95 (euro, usa).bin", 0x200000, 0xdb0be0c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden95) +STD_ROM_FN(md_madden95) + +struct BurnDriver BurnDrvmd_madden95 = { + "md_madden95", NULL, NULL, NULL, "1994", + "Madden NFL 95 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_madden95RomInfo, md_madden95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madden NFL 96 (Euro, USA) +static struct BurnRomInfo md_madden96RomDesc[] = { + { "madden nfl 96 (euro, usa).bin", 0x200000, 0xf126918b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden96) +STD_ROM_FN(md_madden96) + +struct BurnDriver BurnDrvmd_madden96 = { + "md_madden96", NULL, NULL, NULL, "1995", + "Madden NFL 96 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_madden96RomInfo, md_madden96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madden NFL 97 (Euro, USA) +static struct BurnRomInfo md_madden97RomDesc[] = { + { "madden nfl 97 (euro, usa).bin", 0x200000, 0xc4b4e112, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden97) +STD_ROM_FN(md_madden97) + +struct BurnDriver BurnDrvmd_madden97 = { + "md_madden97", NULL, NULL, NULL, "1997", + "Madden NFL 97 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_madden97RomInfo, md_madden97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madden NFL 98 (USA) +static struct BurnRomInfo md_madden98RomDesc[] = { + { "madden nfl 98 (usa).bin", 0x200000, 0xe051ea62, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madden98) +STD_ROM_FN(md_madden98) + +struct BurnDriver BurnDrvmd_madden98 = { + "md_madden98", NULL, NULL, NULL, "1997", + "Madden NFL 98 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madden98RomInfo, md_madden98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madou Monogatari I (Jpn) +static struct BurnRomInfo md_madoumRomDesc[] = { + { "madou monogatari i (jpn).bin", 0x200000, 0xdd82c401, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madoum) +STD_ROM_FN(md_madoum) + +struct BurnDriver BurnDrvmd_madoum = { + "md_madoum", NULL, NULL, NULL, "1996", + "Madou Monogatari I (Jpn)\0", NULL, "Compile", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_madoumRomInfo, md_madoumRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (USA) +static struct BurnRomInfo md_msbRomDesc[] = { + { "magic school bus, the (usa).bin", 0x100000, 0x1a5d4412, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msb) +STD_ROM_FN(md_msb) + +struct BurnDriver BurnDrvmd_msb = { + "md_msb", NULL, NULL, NULL, "1995", + "Scholastic's The Magic School Bus (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbRomInfo, md_msbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950411) +static struct BurnRomInfo md_msbp05RomDesc[] = { + { "magic school bus, the (prototype - apr 11, 1995).bin", 0x0fdfbc, 0x883023bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp05) +STD_ROM_FN(md_msbp05) + +struct BurnDriver BurnDrvmd_msbp05 = { + "md_msbp05", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950411)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp05RomInfo, md_msbp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950421) +static struct BurnRomInfo md_msbp04RomDesc[] = { + { "magic school bus, the (prototype - apr 21, 1995).bin", 0x0fcfdc, 0x7844b7ad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp04) +STD_ROM_FN(md_msbp04) + +struct BurnDriver BurnDrvmd_msbp04 = { + "md_msbp04", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950421)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp04RomInfo, md_msbp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950425) +static struct BurnRomInfo md_msbp03RomDesc[] = { + { "magic school bus, the (prototype - apr 25, 1995).bin", 0x0fd5e0, 0xb6bd2d87, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp03) +STD_ROM_FN(md_msbp03) + +struct BurnDriver BurnDrvmd_msbp03 = { + "md_msbp03", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950425)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp03RomInfo, md_msbp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950428) +static struct BurnRomInfo md_msbp02RomDesc[] = { + { "magic school bus, the (prototype - apr 28, 1995).bin", 0x0fe89c, 0x9b6bae87, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp02) +STD_ROM_FN(md_msbp02) + +struct BurnDriver BurnDrvmd_msbp02 = { + "md_msbp02", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950428)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp02RomInfo, md_msbp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950202) +static struct BurnRomInfo md_msbp11RomDesc[] = { + { "magic school bus, the (prototype - feb 02, 1995).bin", 0x100000, 0x7805b5c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp11) +STD_ROM_FN(md_msbp11) + +struct BurnDriver BurnDrvmd_msbp11 = { + "md_msbp11", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp11RomInfo, md_msbp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950217) +static struct BurnRomInfo md_msbp10RomDesc[] = { + { "magic school bus, the (prototype - feb 17, 1995).bin", 0x0df6bc, 0x2b7a88c0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp10) +STD_ROM_FN(md_msbp10) + +struct BurnDriver BurnDrvmd_msbp10 = { + "md_msbp10", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950217)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp10RomInfo, md_msbp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950112) +static struct BurnRomInfo md_msbp12RomDesc[] = { + { "magic school bus, the (prototype - jan 12, 1995).bin", 0x0eb2e4, 0x946346f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp12) +STD_ROM_FN(md_msbp12) + +struct BurnDriver BurnDrvmd_msbp12 = { + "md_msbp12", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950112)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp12RomInfo, md_msbp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950307) +static struct BurnRomInfo md_msbp09RomDesc[] = { + { "magic school bus, the (prototype - mar 07, 1995).bin", 0x0e9aa8, 0x26c71eb8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp09) +STD_ROM_FN(md_msbp09) + +struct BurnDriver BurnDrvmd_msbp09 = { + "md_msbp09", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950307)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp09RomInfo, md_msbp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950314) +static struct BurnRomInfo md_msbp08RomDesc[] = { + { "magic school bus, the (prototype - mar 14, 1995).bin", 0x0f1c30, 0x37a6a1af, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp08) +STD_ROM_FN(md_msbp08) + +struct BurnDriver BurnDrvmd_msbp08 = { + "md_msbp08", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950314)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp08RomInfo, md_msbp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Magic School Bus (Prototype, 19950327) +static struct BurnRomInfo md_msbp07RomDesc[] = { + { "magic school bus, the (prototype - mar 27, 1995).bin", 0x0f52e8, 0xb065da40, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp07) +STD_ROM_FN(md_msbp07) + +struct BurnDriver BurnDrvmd_msbp07 = { + "md_msbp07", "md_msb", NULL, NULL, "1995", + "The Magic School Bus (Prototype, 19950327)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp07RomInfo, md_msbp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950331) +static struct BurnRomInfo md_msbp06RomDesc[] = { + { "magic school bus, the (prototype - mar 31, 1995).bin", 0x0f93c0, 0xcd788def, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp06) +STD_ROM_FN(md_msbp06) + +struct BurnDriver BurnDrvmd_msbp06 = { + "md_msbp06", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950331)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp06RomInfo, md_msbp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scholastic's The Magic School Bus (Prototype, 19950505) +static struct BurnRomInfo md_msbp01RomDesc[] = { + { "magic school bus, the (prototype - may 05, 1995).bin", 0x0fea00, 0xa2315f1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_msbp01) +STD_ROM_FN(md_msbp01) + +struct BurnDriver BurnDrvmd_msbp01 = { + "md_msbp01", "md_msb", NULL, NULL, "1995", + "Scholastic's The Magic School Bus (Prototype, 19950505)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_msbp01RomInfo, md_msbp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Magical Hat no Buttobi Turbo! Daibouken (Jpn) +static struct BurnRomInfo md_magichatRomDesc[] = { + { "magical hat no buttobi turbo! daibouken (jpn).bin", 0x080000, 0xe43e853d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_magichat) +STD_ROM_FN(md_magichat) + +struct BurnDriver BurnDrvmd_magichat = { + "md_magichat", NULL, NULL, NULL, "1990", + "Magical Hat no Buttobi Turbo! Daibouken (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_magichatRomInfo, md_magichatRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Magical Taruruuto-kun (Jpn) +static struct BurnRomInfo md_magtaruRomDesc[] = { + { "magical taruruuto-kun (jpn).bin", 0x080000, 0xf11060a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_magtaru) +STD_ROM_FN(md_magtaru) + +struct BurnDriver BurnDrvmd_magtaru = { + "md_magtaru", NULL, NULL, NULL, "1992", + "Magical Taruruuto-kun (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_magtaruRomInfo, md_magtaruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mahjong Cop Ryuu - Shiro Ookami no Yabou (Jpn) +static struct BurnRomInfo md_mahjongcRomDesc[] = { + { "mahjong cop ryuu - shiro ookami no yabou (jpn).bin", 0x040000, 0x1ccbc782, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mahjongc) +STD_ROM_FN(md_mahjongc) + +struct BurnDriver BurnDrvmd_mahjongc = { + "md_mahjongc", NULL, NULL, NULL, "1989", + "Mahjong Cop Ryuu - Shiro Ookami no Yabou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mahjongcRomInfo, md_mahjongcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mamono Hunter Youko - Dai 7 no Keishou (Jpn) +static struct BurnRomInfo md_mamonoRomDesc[] = { + { "mamono hunter youko - dai 7 no keishou (jpn).bin", 0x080000, 0x10bb359b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mamono) +STD_ROM_FN(md_mamono) + +struct BurnDriver BurnDrvmd_mamono = { + "md_mamono", NULL, NULL, NULL, "1991", + "Mamono Hunter Youko - Dai 7 no Keishou (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mamonoRomInfo, md_mamonoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// S.S. Lucifer - Man Overboard! (Euro) +static struct BurnRomInfo md_manoverRomDesc[] = { + { "mdss12c4.bin", 0x100000, 0xcae0e3a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_manover) +STD_ROM_FN(md_manover) + +struct BurnDriver BurnDrvmd_manover = { + "md_manover", NULL, NULL, NULL, "1994", + "S.S. Lucifer - Man Overboard! (Euro)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_manoverRomInfo, md_manoverRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Newman Haas Indy Car Featuring Nigel Mansell ~ Nigel Mansell Indy Car (World) +static struct BurnRomInfo md_mansellRomDesc[] = { + { "newman haas indy car featuring nigel mansell -- nigel mansell indy car (world).bin", 0x200000, 0x1233a229, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mansell) +STD_ROM_FN(md_mansell) + +struct BurnDriver BurnDrvmd_mansell = { + "md_mansell", NULL, NULL, NULL, "1994", + "Newman Haas Indy Car Featuring Nigel Mansell ~ Nigel Mansell Indy Car (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mansellRomInfo, md_mansellRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marble Madness (Euro, USA) +static struct BurnRomInfo md_marbleRomDesc[] = { + { "mar01.bin", 0x080000, 0x79eba28a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_marble) +STD_ROM_FN(md_marble) + +struct BurnDriver BurnDrvmd_marble = { + "md_marble", NULL, NULL, NULL, "1993", + "Marble Madness (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_marbleRomInfo, md_marbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mario Andretti Racing (Euro, USA) +static struct BurnRomInfo md_marioandRomDesc[] = { + { "mario andretti racing (euro, usa).bin", 0x200000, 0x7f1dc0aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_marioand) +STD_ROM_FN(md_marioand) + +struct BurnDriver BurnDrvmd_marioand = { + "md_marioand", NULL, NULL, NULL, "1994", + "Mario Andretti Racing (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_marioandRomInfo, md_marioandRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mario Lemieux Hockey (Euro, USA) +static struct BurnRomInfo md_mariolhRomDesc[] = { + { "mpr-14376.bin", 0x080000, 0xf664eb6c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mariolh) +STD_ROM_FN(md_mariolh) + +struct BurnDriver BurnDrvmd_mariolh = { + "md_mariolh", NULL, NULL, NULL, "1991", + "Mario Lemieux Hockey (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mariolhRomInfo, md_mariolhRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marko's Magic Football (Euro) +static struct BurnRomInfo md_markoRomDesc[] = { + { "mpr-16825.bin", 0x200000, 0x2307b905, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_marko) +STD_ROM_FN(md_marko) + +struct BurnDriver BurnDrvmd_marko = { + "md_marko", NULL, NULL, NULL, "1994", + "Marko's Magic Football (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_markoRomInfo, md_markoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marko's Magic Football (Euro, Prototype) +static struct BurnRomInfo md_markopRomDesc[] = { + { "marko's magic football (euro) (beta).bin", 0x200000, 0x0273e564, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_markop) +STD_ROM_FN(md_markop) + +struct BurnDriver BurnDrvmd_markop = { + "md_markop", "md_marko", NULL, NULL, "1994", + "Marko's Magic Football (Euro, Prototype)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_markopRomInfo, md_markopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marko's Magic Football (USA) +static struct BurnRomInfo md_markouRomDesc[] = { + { "marko's magic football (usa).bin", 0x200000, 0x2b8c8cce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_markou) +STD_ROM_FN(md_markou) + +struct BurnDriver BurnDrvmd_markou = { + "md_markou", "md_marko", NULL, NULL, "1994", + "Marko's Magic Football (USA)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_markouRomInfo, md_markouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marsupilami (Euro) +static struct BurnRomInfo md_marsupRomDesc[] = { + { "marsupilami (euro).bin", 0x200000, 0xe09bbd70, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_marsup) +STD_ROM_FN(md_marsup) + +struct BurnDriver BurnDrvmd_marsup = { + "md_marsup", NULL, NULL, NULL, "1995", + "Marsupilami (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_marsupRomInfo, md_marsupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marsupilami (USA) +static struct BurnRomInfo md_marsupuRomDesc[] = { + { "marsupilami (usa).bin", 0x200000, 0xc76558df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_marsupu) +STD_ROM_FN(md_marsupu) + +struct BurnDriver BurnDrvmd_marsupu = { + "md_marsupu", "md_marsup", NULL, NULL, "1995", + "Marsupilami (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_marsupuRomInfo, md_marsupuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Master of Monsters (USA) +static struct BurnRomInfo md_mastermRomDesc[] = { + { "master of monsters (usa).bin", 0x080000, 0x91354820, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_masterm) +STD_ROM_FN(md_masterm) + +struct BurnDriver BurnDrvmd_masterm = { + "md_masterm", NULL, NULL, NULL, "1991", + "Master of Monsters (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_mastermRomInfo, md_mastermRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Master of Monsters (Jpn) +static struct BurnRomInfo md_mastermjRomDesc[] = { + { "mpr-14120.bin", 0x080000, 0xd51ee8c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mastermj) +STD_ROM_FN(md_mastermj) + +struct BurnDriver BurnDrvmd_mastermj = { + "md_mastermj", "md_masterm", NULL, NULL, "1991", + "Master of Monsters (Jpn)\0", NULL, "Toshiba EMI", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_mastermjRomInfo, md_mastermjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Master of Weapon (Jpn) +static struct BurnRomInfo md_mweaponRomDesc[] = { + { "master of weapon (jpn).bin", 0x080000, 0x12ad6178, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mweapon) +STD_ROM_FN(md_mweapon) + +struct BurnDriver BurnDrvmd_mweapon = { + "md_mweapon", NULL, NULL, NULL, "1991", + "Master of Weapon (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mweaponRomInfo, md_mweaponRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Maten no Soumetsu (Jpn) +static struct BurnRomInfo md_matenRomDesc[] = { + { "maten no soumetsu (jpn).bin", 0x100000, 0xb804a105, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_maten) +STD_ROM_FN(md_maten) + +struct BurnDriver BurnDrvmd_maten = { + "md_maten", NULL, NULL, NULL, "1993", + "Maten no Soumetsu (Jpn)\0", NULL, "Kodansha", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_matenRomInfo, md_matenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Math Blaster - Episode 1 (USA) +static struct BurnRomInfo md_mathblstRomDesc[] = { + { "math blaster - episode 1 (usa).bin", 0x100000, 0xd055a462, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mathblst) +STD_ROM_FN(md_mathblst) + +struct BurnDriver BurnDrvmd_mathblst = { + "md_mathblst", NULL, NULL, NULL, "1994", + "Math Blaster - Episode 1 (USA)\0", NULL, "Davidson & Associates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mathblstRomInfo, md_mathblstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mazin Wars (Euro) +static struct BurnRomInfo md_mazinwarRomDesc[] = { + { "mazin wars (euro).bin", 0x100000, 0x4b07a105, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mazinwar) +STD_ROM_FN(md_mazinwar) + +struct BurnDriver BurnDrvmd_mazinwar = { + "md_mazinwar", NULL, NULL, NULL, "1993", + "Mazin Wars (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mazinwarRomInfo, md_mazinwarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mazin Saga (Asia) +static struct BurnRomInfo md_mazinsagaRomDesc[] = { + { "mazin saga (asia).bin", 0x100000, 0x36459b59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mazinsaga) +STD_ROM_FN(md_mazinsaga) + +struct BurnDriver BurnDrvmd_mazinsaga = { + "md_mazinsaga", "md_mazinwar", NULL, NULL, "1993", + "Mazin Saga (Asia)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mazinsagaRomInfo, md_mazinsagaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mazin Saga (Jpn, Kor) +static struct BurnRomInfo md_mazinsagjRomDesc[] = { + { "mazin saga (jpn, kor).bin", 0x100000, 0x45b3a34b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mazinsagj) +STD_ROM_FN(md_mazinsagj) + +struct BurnDriver BurnDrvmd_mazinsagj = { + "md_mazinsagj", "md_mazinwar", NULL, NULL, "1993", + "Mazin Saga (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mazinsagjRomInfo, md_mazinsagjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mazin Saga - Mutant Fighter (USA) +static struct BurnRomInfo md_mazinsaguRomDesc[] = { + { "mazin saga - mutant fighter (usa).bin", 0x100000, 0x1bd9fef1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mazinsagu) +STD_ROM_FN(md_mazinsagu) + +struct BurnDriver BurnDrvmd_mazinsagu = { + "md_mazinsagu", "md_mazinwar", NULL, NULL, "1993", + "Mazin Saga - Mutant Fighter (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mazinsaguRomInfo, md_mazinsaguRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// McDonald's Treasure Land Adventure (Euro) +static struct BurnRomInfo md_mcdonaldRomDesc[] = { + { "mcdonald's treasure land adventure (euro).bin", 0x100000, 0x6ab6a8da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mcdonald) +STD_ROM_FN(md_mcdonald) + +struct BurnDriver BurnDrvmd_mcdonald = { + "md_mcdonald", NULL, NULL, NULL, "1993", + "McDonald's Treasure Land Adventure (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mcdonaldRomInfo, md_mcdonaldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// McDonald's Treasure Land Adventure (Jpn) +static struct BurnRomInfo md_mcdonaldjRomDesc[] = { + { "mcdonald's treasure land adventure (jpn).bin", 0x100000, 0xfebcfd06, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mcdonaldj) +STD_ROM_FN(md_mcdonaldj) + +struct BurnDriver BurnDrvmd_mcdonaldj = { + "md_mcdonaldj", "md_mcdonald", NULL, NULL, "1993", + "McDonald's Treasure Land Adventure (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mcdonaldjRomInfo, md_mcdonaldjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// McDonald's Treasure Land Adventure (Jpn, Prototype) +static struct BurnRomInfo md_mcdonaldjpRomDesc[] = { + { "mcdonald's treasure land adventure (jpn) (beta).bin", 0x100000, 0x7bf477e8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mcdonaldjp) +STD_ROM_FN(md_mcdonaldjp) + +struct BurnDriver BurnDrvmd_mcdonaldjp = { + "md_mcdonaldjp", "md_mcdonald", NULL, NULL, "1993", + "McDonald's Treasure Land Adventure (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mcdonaldjpRomInfo, md_mcdonaldjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// McDonald's Treasure Land Adventure (USA) +static struct BurnRomInfo md_mcdonalduRomDesc[] = { + { "mcdonald's treasure land adventure (usa).bin", 0x100000, 0x04ef4899, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mcdonaldu) +STD_ROM_FN(md_mcdonaldu) + +struct BurnDriver BurnDrvmd_mcdonaldu = { + "md_mcdonaldu", "md_mcdonald", NULL, NULL, "1993", + "McDonald's Treasure Land Adventure (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mcdonalduRomInfo, md_mcdonalduRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Medal City (Jpn, SegaNet) +static struct BurnRomInfo md_medalcRomDesc[] = { + { "medal city (jpn) (sn).bin", 0x040000, 0x3ef4135d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_medalc) +STD_ROM_FN(md_medalc) + +struct BurnDriver BurnDrvmd_medalc = { + "md_medalc", NULL, NULL, NULL, "1991", + "Medal City (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_medalcRomInfo, md_medalcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Bomberman (USA) +static struct BurnRomInfo md_megabombuRomDesc[] = { + { "mega bomberman (usa).bin", 0x100000, 0x4bd6667d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megabombu) +STD_ROM_FN(md_megabombu) + +struct BurnDriver BurnDrvmd_megabombu = { + "md_megabombu", "md_megabomb", NULL, NULL, "1994", + "Mega Bomberman (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megabombuRomInfo, md_megabombuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Bomberman - 8 Player Demo +static struct BurnRomInfo md_megabm8RomDesc[] = { + { "mega bomberman - 8 player demo (unl).bin", 0x100000, 0xd41c0d81, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megabm8) +STD_ROM_FN(md_megabm8) + +struct BurnDriver BurnDrvmd_megabm8 = { + "md_megabm8", NULL, NULL, NULL, "199?", + "Mega Bomberman - 8 Player Demo\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megabm8RomInfo, md_megabm8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games I (Euro) +static struct BurnRomInfo md_megaga1RomDesc[] = { + { "mpr-15009.bin", 0x100000, 0xdb753224, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga1) +STD_ROM_FN(md_megaga1) + +struct BurnDriver BurnDrvmd_megaga1 = { + "md_megaga1", NULL, NULL, NULL, "1992", + "Mega Games I (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga1RomInfo, md_megaga1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 2 (Euro) +static struct BurnRomInfo md_megaga2RomDesc[] = { + { "mega games 2 (euro).bin", 0x200000, 0x30d59f2f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga2) +STD_ROM_FN(md_megaga2) + +struct BurnDriver BurnDrvmd_megaga2 = { + "md_megaga2", NULL, NULL, NULL, "1993", + "Mega Games 2 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga2RomInfo, md_megaga2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 3 (Euro, Asia) +static struct BurnRomInfo md_megaga3RomDesc[] = { + { "mega games 3 (euro, asia).bin", 0x200000, 0xb4247d98, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga3) +STD_ROM_FN(md_megaga3) + +struct BurnDriver BurnDrvmd_megaga3 = { + "md_megaga3", NULL, NULL, NULL, "1993", + "Mega Games 3 (Euro, Asia)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga3RomInfo, md_megaga3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 6 Vol. 1 (Euro) +static struct BurnRomInfo md_megaga61RomDesc[] = { + { "mpr-18002+mpr18003.bin", 0x300000, 0xb66fb80d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga61) +STD_ROM_FN(md_megaga61) + +struct BurnDriver BurnDrvmd_megaga61 = { + "md_megaga61", NULL, NULL, NULL, "1995", + "Mega Games 6 Vol. 1 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga61RomInfo, md_megaga61RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 6 Vol. 2 (Euro) +static struct BurnRomInfo md_megaga62RomDesc[] = { + { "mega games 6 vol. 2 (euro).bin", 0x300000, 0xe8d10db9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga62) +STD_ROM_FN(md_megaga62) + +struct BurnDriver BurnDrvmd_megaga62 = { + "md_megaga62", NULL, NULL, NULL, "1995", + "Mega Games 6 Vol. 2 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga62RomInfo, md_megaga62RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Games 10 (Bra) +static struct BurnRomInfo md_megaga10RomDesc[] = { + { "mega games 10 (bra).bin", 0x400000, 0xc19ae368, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaga10) +STD_ROM_FN(md_megaga10) + +struct BurnDriver BurnDrvmd_megaga10 = { + "md_megaga10", NULL, NULL, NULL, "199?", + "Mega Games 10 (Bra)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaga10RomInfo, md_megaga10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Man - The Wily Wars (Euro) +static struct BurnRomInfo md_megamanRomDesc[] = { + { "mega man - the wily wars (euro).bin", 0x200000, 0xdcf6e8b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaman) +STD_ROM_FN(md_megaman) + +struct BurnDriver BurnDrvmd_megaman = { + "md_megaman", NULL, NULL, NULL, "1994", + "Mega Man - The Wily Wars (Euro)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_megamanRomInfo, md_megamanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rockman Mega World (Jpn) +static struct BurnRomInfo md_rockmanRomDesc[] = { + { "rockman mega world (jpn).bin", 0x200000, 0x4d87235e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rockman) +STD_ROM_FN(md_rockman) + +struct BurnDriver BurnDrvmd_rockman = { + "md_rockman", "md_megaman", NULL, NULL, "1994", + "Rockman Mega World (Jpn)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_rockmanRomInfo, md_rockmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rockman Mega World (Jpn, Alt) +static struct BurnRomInfo md_rockman1RomDesc[] = { + { "rockman mega world (jpn) (alt).bin", 0x200000, 0x85c956ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rockman1) +STD_ROM_FN(md_rockman1) + +struct BurnDriver BurnDrvmd_rockman1 = { + "md_rockman1", "md_megaman", NULL, NULL, "1994", + "Rockman Mega World (Jpn, Alt)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rockman1RomInfo, md_rockman1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega SWIV (Euro) +static struct BurnRomInfo md_megaswivRomDesc[] = { + { "mega swiv (euro).bin", 0x100000, 0x78c2f046, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaswiv) +STD_ROM_FN(md_megaswiv) + +struct BurnDriver BurnDrvmd_megaswiv = { + "md_megaswiv", NULL, NULL, NULL, "1994", + "Mega SWIV (Euro)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaswivRomInfo, md_megaswivRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega SWIV (Euro, Pirate) +static struct BurnRomInfo md_megaswivbRomDesc[] = { + { "mega swiv (euro) (pirate).bin", 0x100000, 0x1ec66bf7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaswivb) +STD_ROM_FN(md_megaswivb) + +struct BurnDriver BurnDrvmd_megaswivb = { + "md_megaswivb", "md_megaswiv", NULL, NULL, "1994", + "Mega SWIV (Euro, Pirate)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaswivbRomInfo, md_megaswivbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Turrican (Euro) +static struct BurnRomInfo md_megaturrRomDesc[] = { + { "mega turrican (euro).bin", 0x100000, 0xb1d15d0f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaturr) +STD_ROM_FN(md_megaturr) + +struct BurnDriver BurnDrvmd_megaturr = { + "md_megaturr", NULL, NULL, NULL, "1994", + "Mega Turrican (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaturrRomInfo, md_megaturrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Turrican (USA) +static struct BurnRomInfo md_megaturruRomDesc[] = { + { "mega turrican (usa).bin", 0x100000, 0xfe898cc9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaturru) +STD_ROM_FN(md_megaturru) + +struct BurnDriver BurnDrvmd_megaturru = { + "md_megaturru", "md_megaturr", NULL, NULL, "1994", + "Mega Turrican (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaturruRomInfo, md_megaturruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega-Lo-Mania (Euro, v1.1) +static struct BurnRomInfo md_megaloRomDesc[] = { + { "mega-lo-mania (euro) (v1.1).bin", 0x100000, 0xab9fed30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megalo) +STD_ROM_FN(md_megalo) + +struct BurnDriver BurnDrvmd_megalo = { + "md_megalo", NULL, NULL, NULL, "1992", + "Mega-Lo-Mania (Euro, v1.1)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaloRomInfo, md_megaloRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega-Lo-Mania (Euro) +static struct BurnRomInfo md_megalo1RomDesc[] = { + { "mpr-15230.bin", 0x100000, 0x2148d56d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megalo1) +STD_ROM_FN(md_megalo1) + +struct BurnDriver BurnDrvmd_megalo1 = { + "md_megalo1", "md_megalo", NULL, NULL, "1992", + "Mega-Lo-Mania (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megalo1RomInfo, md_megalo1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega-Lo-Mania (Fra) +static struct BurnRomInfo md_megalofRomDesc[] = { + { "mega-lo-mania (france).bin", 0x100000, 0x3b3231ed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megalof) +STD_ROM_FN(md_megalof) + +struct BurnDriver BurnDrvmd_megalof = { + "md_megalof", "md_megalo", NULL, NULL, "1992", + "Mega-Lo-Mania (Fra)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megalofRomInfo, md_megalofRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega-Lo-Mania (Jpn) +static struct BurnRomInfo md_megalojRomDesc[] = { + { "mega-lo-mania (jpn).bin", 0x100000, 0xa60d8619, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaloj) +STD_ROM_FN(md_megaloj) + +struct BurnDriver BurnDrvmd_megaloj = { + "md_megaloj", "md_megalo", NULL, NULL, "1993", + "Mega-Lo-Mania (Jpn)\0", NULL, "CRI", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megalojRomInfo, md_megalojRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tyrants - Fight through Time (USA) +static struct BurnRomInfo md_tyrantRomDesc[] = { + { "tyrants - fight through time (usa).bin", 0x100000, 0xa744921e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tyrant) +STD_ROM_FN(md_tyrant) + +struct BurnDriver BurnDrvmd_tyrant = { + "md_tyrant", "md_megalo", NULL, NULL, "1992", + "Tyrants - Fight through Time (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tyrantRomInfo, md_tyrantRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MegaMind (Jpn, SegaNet) +static struct BurnRomInfo md_megamindRomDesc[] = { + { "megamind (jpn) (sn).bin", 0x040000, 0x76df2ae2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megamind) +STD_ROM_FN(md_megamind) + +struct BurnDriver BurnDrvmd_megamind = { + "md_megamind", NULL, NULL, NULL, "1991", + "MegaMind (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megamindRomInfo, md_megamindRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MegaPanel (Jpn) +static struct BurnRomInfo md_megapanlRomDesc[] = { + { "megapanel (jpn).bin", 0x040000, 0x6240f579, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megapanl) +STD_ROM_FN(md_megapanl) + +struct BurnDriver BurnDrvmd_megapanl = { + "md_megapanl", NULL, NULL, NULL, "1990", + "MegaPanel (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megapanlRomInfo, md_megapanlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Menacer 6-Game Cartridge (Euro, USA) +static struct BurnRomInfo md_menacerRomDesc[] = { + { "mpr-15075.bin", 0x100000, 0x936b85f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_menacer) +STD_ROM_FN(md_menacer) + +struct BurnDriver BurnDrvmd_menacer = { + "md_menacer", NULL, NULL, NULL, "1992", + "Menacer 6-Game Cartridge (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_menacerRomInfo, md_menacerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Meng Huan Shui Guo Pan - 777 Casino (Chi) +static struct BurnRomInfo md_menghuRomDesc[] = { + { "meng huan shui guo pan - 777 casino (chi) (unl).bin", 0x100000, 0x42dc03e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_menghu) +STD_ROM_FN(md_menghu) + +struct BurnDriver BurnDrvmd_menghu = { + "md_menghu", NULL, NULL, NULL, "199?", + "Meng Huan Shui Guo Pan - 777 Casino (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_menghuRomInfo, md_menghuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mercs (Euro, USA) ~ Senjou no Ookami II (Jpn) +static struct BurnRomInfo md_mercsRomDesc[] = { + { "mpr-14242.bin", 0x100000, 0x16113a72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mercs) +STD_ROM_FN(md_mercs) + +struct BurnDriver BurnDrvmd_mercs = { + "md_mercs", NULL, NULL, NULL, "1991", + "Mercs (Euro, USA) ~ Senjou no Ookami II (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mercsRomInfo, md_mercsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Metal Fangs (Jpn) +static struct BurnRomInfo md_metalfRomDesc[] = { + { "metal fangs (jpn).bin", 0x080000, 0xa8df1c4c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_metalf) +STD_ROM_FN(md_metalf) + +struct BurnDriver BurnDrvmd_metalf = { + "md_metalf", NULL, NULL, NULL, "1993", + "Metal Fangs (Jpn)\0", NULL, "Victor Interactive Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_metalfRomInfo, md_metalfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Michael Jackson's Moonwalker (World, Rev. A) +static struct BurnRomInfo md_mwalkRomDesc[] = { + { "mpr-13285a.bin", 0x080000, 0x11ce1f9e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mwalk) +STD_ROM_FN(md_mwalk) + +struct BurnDriver BurnDrvmd_mwalk = { + "md_mwalk", NULL, NULL, NULL, "1990", + "Michael Jackson's Moonwalker (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mwalkRomInfo, md_mwalkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Michael Jackson's Moonwalker (World) +static struct BurnRomInfo md_mwalk1RomDesc[] = { + { "mpr-13285.bin", 0x080000, 0x6a70791b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mwalk1) +STD_ROM_FN(md_mwalk1) + +struct BurnDriver BurnDrvmd_mwalk1 = { + "md_mwalk1", "md_mwalk", NULL, NULL, "1990", + "Michael Jackson's Moonwalker (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mwalk1RomInfo, md_mwalk1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mickey Mania - The Timeless Adventures of Mickey Mouse (Euro) +static struct BurnRomInfo md_mmaniaRomDesc[] = { + { "mpr-17089.bin", 0x200000, 0xcb5a8b85, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmania) +STD_ROM_FN(md_mmania) + +struct BurnDriver BurnDrvmd_mmania = { + "md_mmania", NULL, NULL, NULL, "1994", + "Mickey Mania - The Timeless Adventures of Mickey Mouse (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmaniaRomInfo, md_mmaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mickey Mania - The Timeless Adventures of Mickey Mouse (Jpn) +static struct BurnRomInfo md_mmaniajRomDesc[] = { + { "mickey mania - the timeless adventures of mickey mouse (jpn).bin", 0x200000, 0x23180cf7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmaniaj) +STD_ROM_FN(md_mmaniaj) + +struct BurnDriver BurnDrvmd_mmaniaj = { + "md_mmaniaj", "md_mmania", NULL, NULL, "1995", + "Mickey Mania - The Timeless Adventures of Mickey Mouse (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmaniajRomInfo, md_mmaniajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mickey Mania - The Timeless Adventures of Mickey Mouse (USA) +static struct BurnRomInfo md_mmaniauRomDesc[] = { + { "mickey mania - the timeless adventures of mickey mouse (usa).bin", 0x200000, 0x629e5963, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmaniau) +STD_ROM_FN(md_mmaniau) + +struct BurnDriver BurnDrvmd_mmaniau = { + "md_mmaniau", "md_mmania", NULL, NULL, "1994", + "Mickey Mania - The Timeless Adventures of Mickey Mouse (USA)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmaniauRomInfo, md_mmaniauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mickey Mania - The Timeless Adventures of Mickey Mouse (USA, Prototype) +static struct BurnRomInfo md_mmaniaupRomDesc[] = { + { "mickey mania - the timeless adventures of mickey mouse (usa) (beta).bin", 0x200000, 0x7fc1bdf0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmaniaup) +STD_ROM_FN(md_mmaniaup) + +struct BurnDriver BurnDrvmd_mmaniaup = { + "md_mmaniaup", "md_mmania", NULL, NULL, "1994", + "Mickey Mania - The Timeless Adventures of Mickey Mouse (USA, Prototype)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmaniaupRomInfo, md_mmaniaupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mickey's Ultimate Challenge (USA) +static struct BurnRomInfo md_mickeyucRomDesc[] = { + { "mickey's ultimate challenge (usa).bin", 0x100000, 0x30b512ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mickeyuc) +STD_ROM_FN(md_mickeyuc) + +struct BurnDriver BurnDrvmd_mickeyuc = { + "md_mickeyuc", NULL, NULL, NULL, "1994", + "Mickey's Ultimate Challenge (USA)\0", NULL, "High Tech Expressions", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mickeyucRomInfo, md_mickeyucRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines (Euro, USA) +static struct BurnRomInfo md_micromRomDesc[] = { + { "mdmm_acd3.bin", 0x080000, 0x50081a0b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_microm) +STD_ROM_FN(md_microm) + +struct BurnDriver BurnDrvmd_microm = { + "md_microm", NULL, NULL, NULL, "1993", + "Micro Machines (Euro, USA)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_micromRomInfo, md_micromRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines (Euro, USA, Alt) +static struct BurnRomInfo md_micromaRomDesc[] = { + { "micro machines (euro, usa) (alt).bin", 0x080000, 0xe5cf560d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_microma) +STD_ROM_FN(md_microma) + +struct BurnDriver BurnDrvmd_microma = { + "md_microma", "md_microm", NULL, NULL, "1993", + "Micro Machines (Euro, USA, Alt)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_micromaRomInfo, md_micromaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines (Euro, USA, Alt 2) +static struct BurnRomInfo md_micrombRomDesc[] = { + { "micro machines (euro, usa) (alt2).bin", 0x080000, 0x7ffbd1ad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_micromb) +STD_ROM_FN(md_micromb) + +struct BurnDriver BurnDrvmd_micromb = { + "md_micromb", "md_microm", NULL, NULL, "1993", + "Micro Machines (Euro, USA, Alt 2)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_micrombRomInfo, md_micrombRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines (Can) +static struct BurnRomInfo md_micromcnRomDesc[] = { + { "micro machines (canada).bin", 0x080000, 0x54e4cff1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_micromcn) +STD_ROM_FN(md_micromcn) + +struct BurnDriver BurnDrvmd_micromcn = { + "md_micromcn", "md_microm", NULL, NULL, "1993", + "Micro Machines (Can)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_micromcnRomInfo, md_micromcnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines Turbo Tournament 96 (Euro, J-Cart) +static struct BurnRomInfo md_micro96aRomDesc[] = { + { "mm96md7cc3.bin", 0x100000, 0x7492b1de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_micro96a) +STD_ROM_FN(md_micro96a) + +struct BurnDriver BurnDrvmd_micro96a = { + "md_micro96a", "md_micro96", NULL, NULL, "1995", + "Micro Machines Turbo Tournament 96 (Euro, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_micro96aRomInfo, md_micro96aRomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines 2 - Turbo Tournament (Euro, J-Cart, Alt) +static struct BurnRomInfo md_microm2aRomDesc[] = { + { "micro machines 2 - turbo tournament (euro) (j-cart) (alt).bin", 0x100000, 0x01c22a5d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_microm2a) +STD_ROM_FN(md_microm2a) + +struct BurnDriver BurnDrvmd_microm2a = { + "md_microm2a", "md_microm2", NULL, NULL, "1994", + "Micro Machines 2 - Turbo Tournament (Euro, J-Cart, Alt)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_microm2aRomInfo, md_microm2aRomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Micro Machines Military (Euro, J-Cart) +static struct BurnRomInfo md_micrommRomDesc[] = { + { "micro machines military (euro) (j-cart).bin", 0x100000, 0xb3abb15e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_micromm) +STD_ROM_FN(md_micromm) + +struct BurnDriver BurnDrvmd_micromm = { + "md_micromm", NULL, NULL, NULL, "1996", + "Micro Machines Military (Euro, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 4, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_micrommRomInfo, md_micrommRomName, NULL, NULL, Megadrive4pInputInfo, Megadrive4pDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Midnight Resistance (USA) +static struct BurnRomInfo md_midresRomDesc[] = { + { "midnight resistance (usa).bin", 0x100000, 0x187c6af6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_midres) +STD_ROM_FN(md_midres) + +struct BurnDriver BurnDrvmd_midres = { + "md_midres", NULL, NULL, NULL, "1991", + "Midnight Resistance (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_midresRomInfo, md_midresRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Midnight Resistance (Jpn) +static struct BurnRomInfo md_midresjRomDesc[] = { + { "midnight resistance (jpn).bin", 0x100000, 0x8f3f6e4d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_midresj) +STD_ROM_FN(md_midresj) + +struct BurnDriver BurnDrvmd_midresj = { + "md_midresj", "md_midres", NULL, NULL, "1991", + "Midnight Resistance (Jpn)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_midresjRomInfo, md_midresjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Midway Presents Arcade's Greatest Hits (Euro) +static struct BurnRomInfo md_midwayRomDesc[] = { + { "midway presents arcade's greatest hits (euro).bin", 0x080000, 0xc0dce0e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_midway) +STD_ROM_FN(md_midway) + +struct BurnDriver BurnDrvmd_midway = { + "md_midway", NULL, NULL, NULL, "1996", + "Midway Presents Arcade's Greatest Hits (Euro)\0", NULL, "Midway", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_midwayRomInfo, md_midwayRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mig-29 Fighter Pilot (Euro) +static struct BurnRomInfo md_mig29RomDesc[] = { + { "mpr-15659.bin", 0x100000, 0x70b0a5d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mig29) +STD_ROM_FN(md_mig29) + +struct BurnDriver BurnDrvmd_mig29 = { + "md_mig29", NULL, NULL, NULL, "1993", + "Mig-29 Fighter Pilot (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mig29RomInfo, md_mig29RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mig-29 Fighter Pilot (Jpn) +static struct BurnRomInfo md_mig29jRomDesc[] = { + { "mig-29 fighter pilot (jpn).bin", 0x100000, 0x3d239046, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mig29j) +STD_ROM_FN(md_mig29j) + +struct BurnDriver BurnDrvmd_mig29j = { + "md_mig29j", "md_mig29", NULL, NULL, "1993", + "Mig-29 Fighter Pilot (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mig29jRomInfo, md_mig29jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mig-29 Fighter Pilot (USA) +static struct BurnRomInfo md_mig29uRomDesc[] = { + { "mig-29 fighter pilot (usa).bin", 0x100000, 0x59ccabb2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mig29u) +STD_ROM_FN(md_mig29u) + +struct BurnDriver BurnDrvmd_mig29u = { + "md_mig29u", "md_mig29", NULL, NULL, "1993", + "Mig-29 Fighter Pilot (USA)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mig29uRomInfo, md_mig29uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Might and Magic - Gates to Another World (Euro, USA) +static struct BurnRomInfo md_mightmagRomDesc[] = { + { "might and magic - gates to another world (euro, usa).bin", 0x0c0000, 0xf509145f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mightmag) +STD_ROM_FN(md_mightmag) + +struct BurnDriver BurnDrvmd_mightmag = { + "md_mightmag", NULL, NULL, NULL, "1991", + "Might and Magic - Gates to Another World (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mightmagRomInfo, md_mightmagRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Might and Magic III - Isles of Terra (USA, Prototype) +static struct BurnRomInfo md_mmagic3pRomDesc[] = { + { "might and magic iii - isles of terra (usa) (prototype).bin", 0x200000, 0x6ef7104a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmagic3p) +STD_ROM_FN(md_mmagic3p) + +struct BurnDriver BurnDrvmd_mmagic3p = { + "md_mmagic3p", NULL, NULL, NULL, "199?", + "Might and Magic III - Isles of Terra (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmagic3pRomInfo, md_mmagic3pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Euro) +static struct BurnRomInfo md_mmprRomDesc[] = { + { "mighty morphin power rangers (euro).bin", 0x200000, 0x7f96e663, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmpr) +STD_ROM_FN(md_mmpr) + +struct BurnDriver BurnDrvmd_mmpr = { + "md_mmpr", NULL, NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprRomInfo, md_mmprRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (USA) +static struct BurnRomInfo md_mmpruRomDesc[] = { + { "mighty morphin power rangers (usa).bin", 0x200000, 0x715158a9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmpru) +STD_ROM_FN(md_mmpru) + +struct BurnDriver BurnDrvmd_mmpru = { + "md_mmpru", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmpruRomInfo, md_mmpruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940804) +static struct BurnRomInfo md_mmprp4RomDesc[] = { + { "mighty morphin power rangers (prototype - aug 04, 1994).bin", 0x200000, 0xf3ae5aaf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp4) +STD_ROM_FN(md_mmprp4) + +struct BurnDriver BurnDrvmd_mmprp4 = { + "md_mmprp4", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940804)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp4RomInfo, md_mmprp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940808) +static struct BurnRomInfo md_mmprp3RomDesc[] = { + { "mighty morphin power rangers (prototype - aug 08, 1994).bin", 0x200000, 0x57644549, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp3) +STD_ROM_FN(md_mmprp3) + +struct BurnDriver BurnDrvmd_mmprp3 = { + "md_mmprp3", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940808)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp3RomInfo, md_mmprp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940809) +static struct BurnRomInfo md_mmprp2RomDesc[] = { + { "mighty morphin power rangers (prototype - aug 09, 1994).bin", 0x200000, 0x4356fe0a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp2) +STD_ROM_FN(md_mmprp2) + +struct BurnDriver BurnDrvmd_mmprp2 = { + "md_mmprp2", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940809)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp2RomInfo, md_mmprp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940810) +static struct BurnRomInfo md_mmprp1RomDesc[] = { + { "mighty morphin power rangers (prototype - aug 10, 1994).bin", 0x200000, 0xe79cd214, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp1) +STD_ROM_FN(md_mmprp1) + +struct BurnDriver BurnDrvmd_mmprp1 = { + "md_mmprp1", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940810)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp1RomInfo, md_mmprp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940708) +static struct BurnRomInfo md_mmprp6RomDesc[] = { + { "mighty morphin power rangers (prototype - jul 08, 1994).bin", 0x200000, 0xe6916c54, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp6) +STD_ROM_FN(md_mmprp6) + +struct BurnDriver BurnDrvmd_mmprp6 = { + "md_mmprp6", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940708)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp6RomInfo, md_mmprp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers (Prototype, 19940718) +static struct BurnRomInfo md_mmprp5RomDesc[] = { + { "mighty morphin power rangers (prototype - jul 18, 1994).bin", 0x200000, 0x5accdb1a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprp5) +STD_ROM_FN(md_mmprp5) + +struct BurnDriver BurnDrvmd_mmprp5 = { + "md_mmprp5", "md_mmpr", NULL, NULL, "1994", + "Mighty Morphin Power Rangers (Prototype, 19940718)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprp5RomInfo, md_mmprp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (Euro) +static struct BurnRomInfo md_mmprtmRomDesc[] = { + { "mighty morphin power rangers - the movie (euro).bin", 0x200000, 0x254a4972, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtm) +STD_ROM_FN(md_mmprtm) + +struct BurnDriver BurnDrvmd_mmprtm = { + "md_mmprtm", NULL, NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmRomInfo, md_mmprtmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (USA) +static struct BurnRomInfo md_mmprtmuRomDesc[] = { + { "mighty morphin power rangers - the movie (usa).bin", 0x200000, 0xaa941cbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtmu) +STD_ROM_FN(md_mmprtmu) + +struct BurnDriver BurnDrvmd_mmprtmu = { + "md_mmprtmu", "md_mmprtm", NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmuRomInfo, md_mmprtmuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (Prototype, 19950713) +static struct BurnRomInfo md_mmprtmp4RomDesc[] = { + { "mighty morphin power rangers - the movie (prototype - jul 13, 1995).bin", 0x200000, 0x227bf7fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtmp4) +STD_ROM_FN(md_mmprtmp4) + +struct BurnDriver BurnDrvmd_mmprtmp4 = { + "md_mmprtmp4", "md_mmprtm", NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (Prototype, 19950713)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmp4RomInfo, md_mmprtmp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (Prototype, 19950717) +static struct BurnRomInfo md_mmprtmp3RomDesc[] = { + { "mighty morphin power rangers - the movie (prototype - jul 17, 1995).bin", 0x200000, 0x579de657, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtmp3) +STD_ROM_FN(md_mmprtmp3) + +struct BurnDriver BurnDrvmd_mmprtmp3 = { + "md_mmprtmp3", "md_mmprtm", NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (Prototype, 19950717)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmp3RomInfo, md_mmprtmp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (Prototype, 19950722) +static struct BurnRomInfo md_mmprtmp2RomDesc[] = { + { "mighty morphin power rangers - the movie (prototype - jul 22, 1995).bin", 0x200000, 0xc2ca3a8b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtmp2) +STD_ROM_FN(md_mmprtmp2) + +struct BurnDriver BurnDrvmd_mmprtmp2 = { + "md_mmprtmp2", "md_mmprtm", NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (Prototype, 19950722)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmp2RomInfo, md_mmprtmp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Movie (Prototype, 19950724) +static struct BurnRomInfo md_mmprtmp1RomDesc[] = { + { "mighty morphin power rangers - the movie (prototype - jul 24, 1995).bin", 0x200000, 0x3429fa3a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprtmp1) +STD_ROM_FN(md_mmprtmp1) + +struct BurnDriver BurnDrvmd_mmprtmp1 = { + "md_mmprtmp1", "md_mmprtm", NULL, NULL, "1995", + "Mighty Morphin Power Rangers - The Movie (Prototype, 19950724)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprtmp1RomInfo, md_mmprtmp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mike Ditka Power Football (Euro, USA) +static struct BurnRomInfo md_mikediRomDesc[] = { + { "mike ditka power football (euro, usa).bin", 0x100000, 0x6078b310, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mikedi) +STD_ROM_FN(md_mikedi) + +struct BurnDriver BurnDrvmd_mikedi = { + "md_mikedi", NULL, NULL, NULL, "1991", + "Mike Ditka Power Football (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mikediRomInfo, md_mikediRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mike Ditka Power Football (Euro, USA, Alt) +static struct BurnRomInfo md_mikedi1RomDesc[] = { + { "mike ditka power football (euro, usa) (alt).bin", 0x100000, 0xde50ca8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mikedi1) +STD_ROM_FN(md_mikedi1) + +struct BurnDriver BurnDrvmd_mikedi1 = { + "md_mikedi1", "md_mikedi", NULL, NULL, "1991", + "Mike Ditka Power Football (Euro, USA, Alt)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mikedi1RomInfo, md_mikedi1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Minnesota Fats - Pool Legend (USA) +static struct BurnRomInfo md_minnesotRomDesc[] = { + { "minnesota fats - pool legend (usa).bin", 0x100000, 0x38174f40, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_minnesot) +STD_ROM_FN(md_minnesot) + +struct BurnDriver BurnDrvmd_minnesot = { + "md_minnesot", NULL, NULL, NULL, "1995", + "Minnesota Fats - Pool Legend (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_minnesotRomInfo, md_minnesotRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chou Kyuukai Miracle Nine (Jpn) +static struct BurnRomInfo md_miracle9RomDesc[] = { + { "chou kyuukai miracle nine (jpn).bin", 0x200000, 0x6d8c2206, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_miracle9) +STD_ROM_FN(md_miracle9) + +struct BurnDriver BurnDrvmd_miracle9 = { + "md_miracle9", NULL, NULL, NULL, "1995", + "Chou Kyuukai Miracle Nine (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_miracle9RomInfo, md_miracle9RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Miracle Piano Teaching System (USA) +static struct BurnRomInfo md_mpianoRomDesc[] = { + { "miracle piano teaching system, the (usa).bin", 0x080000, 0xa719542e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mpiano) +STD_ROM_FN(md_mpiano) + +struct BurnDriver BurnDrvmd_mpiano = { + "md_mpiano", NULL, NULL, NULL, "1992", + "The Miracle Piano Teaching System (USA)\0", NULL, "Software Toolworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mpianoRomInfo, md_mpianoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MK 5 - Mortal Combat - SubZero +static struct BurnRomInfo md_mk5morRomDesc[] = { + { "mk 5 - mortal combat - subzero (unl).bin", 0x200000, 0x11e367a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk5mor) +STD_ROM_FN(md_mk5mor) + +struct BurnDriver BurnDrvmd_mk5mor = { + "md_mk5mor", NULL, NULL, NULL, "199?", + "MK 5 - Mortal Combat - SubZero\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mk5morRomInfo, md_mk5morRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MK 5 - Mortal Combat - SubZero (Pirate) +static struct BurnRomInfo md_mk5mor1RomDesc[] = { + { "mk 5 - mortal combat - subzero (unl) (pirate).bin", 0x200000, 0x41203006, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk5mor1) +STD_ROM_FN(md_mk5mor1) + +struct BurnDriver BurnDrvmd_mk5mor1 = { + "md_mk5mor1", "md_mk5mor", NULL, NULL, "199?", + "MK 5 - Mortal Combat - SubZero (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mk5mor1RomInfo, md_mk5mor1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MLBPA Baseball (USA) +static struct BurnRomInfo md_mlbpabRomDesc[] = { + { "mlbpa baseball (usa).bin", 0x200000, 0x14a8064d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mlbpab) +STD_ROM_FN(md_mlbpab) + +struct BurnDriver BurnDrvmd_mlbpab = { + "md_mlbpab", NULL, NULL, NULL, "1992", + "MLBPA Baseball (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_mlbpabRomInfo, md_mlbpabRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Monopoly (USA) +static struct BurnRomInfo md_monopolyRomDesc[] = { + { "monopoly (usa).bin", 0x080000, 0xc10268da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_monopoly) +STD_ROM_FN(md_monopoly) + +struct BurnDriver BurnDrvmd_monopoly = { + "md_monopoly", NULL, NULL, NULL, "1992", + "Monopoly (USA)\0", NULL, "Parker Brothers", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_monopolyRomInfo, md_monopolyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Monopoly (USA, Prototype) +static struct BurnRomInfo md_monopolypRomDesc[] = { + { "monopoly (usa) (beta).bin", 0x080000, 0xdfbcc3fa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_monopolyp) +STD_ROM_FN(md_monopolyp) + +struct BurnDriver BurnDrvmd_monopolyp = { + "md_monopolyp", "md_monopoly", NULL, NULL, "1992", + "Monopoly (USA, Prototype)\0", NULL, "Parker Brothers", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_monopolypRomInfo, md_monopolypRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Monster World IV (Jpn) +static struct BurnRomInfo md_mworld4RomDesc[] = { + { "monster world iv (jpn).bin", 0x200000, 0x36a3aaa4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mworld4) +STD_ROM_FN(md_mworld4) + +struct BurnDriver BurnDrvmd_mworld4 = { + "md_mworld4", NULL, NULL, NULL, "1994", + "Monster World IV (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_mworld4RomInfo, md_mworld4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mortal Kombat (World, v1.1) +static struct BurnRomInfo md_mkRomDesc[] = { + { "mortal kombat (world) (v1.1).bin", 0x200000, 0x33f19ab6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk) +STD_ROM_FN(md_mk) + +struct BurnDriver BurnDrvmd_mk = { + "md_mk", NULL, NULL, NULL, "1993", + "Mortal Kombat (World, v1.1)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mkRomInfo, md_mkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mortal Kombat (World) +static struct BurnRomInfo md_mkaRomDesc[] = { + { "s215_ver_1.00.bin", 0x200000, 0x1aa3a207, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mka) +STD_ROM_FN(md_mka) + +struct BurnDriver BurnDrvmd_mka = { + "md_mka", "md_mk", NULL, NULL, "1993", + "Mortal Kombat (World)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mkaRomInfo, md_mkaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mortal Kombat II (World) +static struct BurnRomInfo md_mk2RomDesc[] = { + { "s376-u2.1+s382-u1.1.bin", 0x300000, 0xa9e013d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk2) +STD_ROM_FN(md_mk2) + +struct BurnDriver BurnDrvmd_mk2 = { + "md_mk2", NULL, NULL, NULL, "1994", + "Mortal Kombat II (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mk2RomInfo, md_mk2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mortal Kombat 3 (Euro) +static struct BurnRomInfo md_mk3RomDesc[] = { + { "mortal_kombat_3_pal.bin", 0x400000, 0xaf6de3e8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk3) +STD_ROM_FN(md_mk3) + +struct BurnDriver BurnDrvmd_mk3 = { + "md_mk3", NULL, NULL, NULL, "1995", + "Mortal Kombat 3 (Euro)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mk3RomInfo, md_mk3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mortal Kombat 3 (USA) +static struct BurnRomInfo md_mk3uRomDesc[] = { + { "mortal kombat 3 (usa).bin", 0x400000, 0xdd638af6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mk3u) +STD_ROM_FN(md_mk3u) + +struct BurnDriver BurnDrvmd_mk3u = { + "md_mk3u", "md_mk3", NULL, NULL, "1995", + "Mortal Kombat 3 (USA)\0", NULL, "Williams", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mk3uRomInfo, md_mk3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mr. Nutz (Euro) +static struct BurnRomInfo md_mrnutzRomDesc[] = { + { "mr. nutz (euro).bin", 0x100000, 0x0786ea0b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mrnutz) +STD_ROM_FN(md_mrnutz) + +struct BurnDriver BurnDrvmd_mrnutz = { + "md_mrnutz", NULL, NULL, NULL, "1994", + "Mr. Nutz (Euro)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mrnutzRomInfo, md_mrnutzRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ms. Pac-Man (Euro, USA) +static struct BurnRomInfo md_mspacmanRomDesc[] = { + { "ms. pac-man (euro, usa).bin", 0x020000, 0xaf041be6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mspacman) +STD_ROM_FN(md_mspacman) + +struct BurnDriver BurnDrvmd_mspacman = { + "md_mspacman", NULL, NULL, NULL, "1991", + "Ms. Pac-Man (Euro, USA)\0", NULL, "Tengen ~ Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mspacmanRomInfo, md_mspacmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ms. Pac-Man (Pirate, Ripped from Golden 10 in 1) +static struct BurnRomInfo md_mspacmanpirRomDesc[] = { + { "ms. pac-man (usa) (pirate).bin", 0x020000, 0x39b51b26, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mspacmanpir) +STD_ROM_FN(md_mspacmanpir) + +struct BurnDriver BurnDrvmd_mspacmanpir = { + "md_mspacmanpir", "md_mspacman", NULL, NULL, "199?", + "Ms. Pac-Man (Pirate, Ripped from Golden 10 in 1)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mspacmanpirRomInfo, md_mspacmanpirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Muhammad Ali Heavyweight Boxing (Euro) +static struct BurnRomInfo md_muhammRomDesc[] = { + { "muhammad ali heavyweight boxing (euro).bin", 0x100000, 0x8ea4717b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_muhamm) +STD_ROM_FN(md_muhamm) + +struct BurnDriver BurnDrvmd_muhamm = { + "md_muhamm", NULL, NULL, NULL, "1992", + "Muhammad Ali Heavyweight Boxing (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_muhammRomInfo, md_muhammRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Muhammad Ali Heavyweight Boxing (USA) +static struct BurnRomInfo md_muhammuRomDesc[] = { + { "muhammad ali heavyweight boxing (usa).bin", 0x100000, 0xb638b6a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_muhammu) +STD_ROM_FN(md_muhammu) + +struct BurnDriver BurnDrvmd_muhammu = { + "md_muhammu", "md_muhamm", NULL, NULL, "1992", + "Muhammad Ali Heavyweight Boxing (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_muhammuRomInfo, md_muhammuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Muhammad Ali Heavyweight Boxing (USA, Prototype) +static struct BurnRomInfo md_muhammupRomDesc[] = { + { "muhammad ali heavyweight boxing (usa) (beta).bin", 0x100000, 0x7b852653, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_muhammup) +STD_ROM_FN(md_muhammup) + +struct BurnDriver BurnDrvmd_muhammup = { + "md_muhammup", "md_muhamm", NULL, NULL, "1992", + "Muhammad Ali Heavyweight Boxing (USA, Prototype)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_muhammupRomInfo, md_muhammupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MUSHA - Metallic Uniframe Super Hybrid Armor (USA) +static struct BurnRomInfo md_mushaRomDesc[] = { + { "musha - metallic uniframe super hybrid armor (usa).bin", 0x080000, 0x58a7f7b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_musha) +STD_ROM_FN(md_musha) + +struct BurnDriver BurnDrvmd_musha = { + "md_musha", NULL, NULL, NULL, "1990", + "MUSHA - Metallic Uniframe Super Hybrid Armor (USA)\0", NULL, "Seismic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mushaRomInfo, md_mushaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Musha Aleste - Full Metal Fighter Ellinor (Jpn) +static struct BurnRomInfo md_mushajRomDesc[] = { + { "musha aleste - full metal fighter ellinor (jpn).bin", 0x080000, 0x8fde18ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mushaj) +STD_ROM_FN(md_mushaj) + +struct BurnDriver BurnDrvmd_mushaj = { + "md_mushaj", "md_musha", NULL, NULL, "1990", + "Musha Aleste - Full Metal Fighter Ellinor (Jpn)\0", NULL, "Toaplan", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mushajRomInfo, md_mushajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mutant League Football (Jpn) +static struct BurnRomInfo md_mutantlfjRomDesc[] = { + { "mutant league football (jpn).bin", 0x100000, 0x2a97e6af, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mutantlfj) +STD_ROM_FN(md_mutantlfj) + +struct BurnDriver BurnDrvmd_mutantlfj = { + "md_mutantlfj", "md_mutantlf", NULL, NULL, "1993", + "Mutant League Football (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mutantlfjRomInfo, md_mutantlfjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mutant League Hockey (Euro, USA) +static struct BurnRomInfo md_mlhockeyRomDesc[] = { + { "mutant league hockey (euro, usa).bin", 0x200000, 0x3529180f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mlhockey) +STD_ROM_FN(md_mlhockey) + +struct BurnDriver BurnDrvmd_mlhockey = { + "md_mlhockey", NULL, NULL, NULL, "1994", + "Mutant League Hockey (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mlhockeyRomInfo, md_mlhockeyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mystic Defender (Euro, USA, Rev. A) +static struct BurnRomInfo md_mystdefRomDesc[] = { + { "mpr-12707a.bin", 0x080000, 0x50fd5d93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mystdef) +STD_ROM_FN(md_mystdef) + +struct BurnDriver BurnDrvmd_mystdef = { + "md_mystdef", NULL, NULL, NULL, "1989", + "Mystic Defender (Euro, USA, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mystdefRomInfo, md_mystdefRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mystic Defender (Euro, USA) +static struct BurnRomInfo md_mystdefaRomDesc[] = { + { "mpr-12707.bin", 0x080000, 0xf9ce1ab8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mystdefa) +STD_ROM_FN(md_mystdefa) + +struct BurnDriver BurnDrvmd_mystdefa = { + "md_mystdefa", "md_mystdef", NULL, NULL, "1989", + "Mystic Defender (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mystdefaRomInfo, md_mystdefaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kujaku Ou 2 - Geneijou (Jpn) +static struct BurnRomInfo md_kujakuRomDesc[] = { + { "kujaku ou 2 - geneijou (jpn).bin", 0x060000, 0xaffd56bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kujaku) +STD_ROM_FN(md_kujaku) + +struct BurnDriver BurnDrvmd_kujaku = { + "md_kujaku", "md_mystdef", NULL, NULL, "1989", + "Kujaku Ou 2 - Geneijou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kujakuRomInfo, md_kujakuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// On Dal Jang Goon (Kor) +static struct BurnRomInfo md_ondalRomDesc[] = { + { "on dal jang goon (kor).bin", 0x080000, 0x67ccb1ca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ondal) +STD_ROM_FN(md_ondal) + +struct BurnDriver BurnDrvmd_ondal = { + "md_ondal", "md_mystdef", NULL, NULL, "1990?", + "On Dal Jang Goon (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ondalRomInfo, md_ondalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mystical Fighter (USA) +static struct BurnRomInfo md_mysticfRomDesc[] = { + { "mystical fighter (usa).bin", 0x080000, 0xb2f2a69b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mysticf) +STD_ROM_FN(md_mysticf) + +struct BurnDriver BurnDrvmd_mysticf = { + "md_mysticf", NULL, NULL, NULL, "1992", + "Mystical Fighter (USA)\0", NULL, "Dreamworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mysticfRomInfo, md_mysticfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Maou Renjishi (Jpn) +static struct BurnRomInfo md_maourenRomDesc[] = { + { "maou renjishi (jpn).bin", 0x080000, 0x24a7f28c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_maouren) +STD_ROM_FN(md_maouren) + +struct BurnDriver BurnDrvmd_maouren = { + "md_maouren", "md_mysticf", NULL, NULL, "1991", + "Maou Renjishi (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_maourenRomInfo, md_maourenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fushigi no Umi no Nadia (Jpn) +static struct BurnRomInfo md_nadiaRomDesc[] = { + { "namcot_mfn_mb838200-20.bin", 0x100000, 0x4762062a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nadia) +STD_ROM_FN(md_nadia) + +struct BurnDriver BurnDrvmd_nadia = { + "md_nadia", NULL, NULL, NULL, "1991", + "Fushigi no Umi no Nadia (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nadiaRomInfo, md_nadiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nakajima Satoru Kanshuu F1 Grand Prix (Jpn) +static struct BurnRomInfo md_nakaf1gpRomDesc[] = { + { "nakajima satoru kanshuu f1 grand prix (jpn).bin", 0x100000, 0x93be47cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nakaf1gp) +STD_ROM_FN(md_nakaf1gp) + +struct BurnDriver BurnDrvmd_nakaf1gp = { + "md_nakaf1gp", NULL, NULL, NULL, "1991", + "Nakajima Satoru Kanshuu F1 Grand Prix (Jpn)\0", NULL, "Varie", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nakaf1gpRomInfo, md_nakaf1gpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nakajima Satoru Kanshuu F1 Hero MD (Jpn) +static struct BurnRomInfo md_nakaf1heRomDesc[] = { + { "nakajima satoru kanshuu f1 hero md (jpn).bin", 0x100000, 0x24f87987, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nakaf1he) +STD_ROM_FN(md_nakaf1he) + +struct BurnDriver BurnDrvmd_nakaf1he = { + "md_nakaf1he", NULL, NULL, NULL, "1992", + "Nakajima Satoru Kanshuu F1 Hero MD (Jpn)\0", NULL, "Varie", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nakaf1heRomInfo, md_nakaf1heRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nakajima Satoru Kanshuu F1 Super License (Jpn) +static struct BurnRomInfo md_nakaf1slRomDesc[] = { + { "nakajima satoru kanshuu f1 super license (jpn).bin", 0x100000, 0x8774bc79, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nakaf1sl) +STD_ROM_FN(md_nakaf1sl) + +struct BurnDriver BurnDrvmd_nakaf1sl = { + "md_nakaf1sl", NULL, NULL, NULL, "1992", + "Nakajima Satoru Kanshuu F1 Super License (Jpn)\0", NULL, "Varie", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nakaf1slRomInfo, md_nakaf1slRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action (USA) +static struct BurnRomInfo md_nbaactRomDesc[] = { + { "nba action (usa).bin", 0x200000, 0x99c348ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact) +STD_ROM_FN(md_nbaact) + +struct BurnDriver BurnDrvmd_nbaact = { + "md_nbaact", NULL, NULL, NULL, "1994", + "NBA Action (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaactRomInfo, md_nbaactRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action (Prototype, 19940104) +static struct BurnRomInfo md_nbaactp3RomDesc[] = { + { "nba action (prototype - jan 04, 1994).bin", 0x200000, 0x2491df2f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaactp3) +STD_ROM_FN(md_nbaactp3) + +struct BurnDriver BurnDrvmd_nbaactp3 = { + "md_nbaactp3", "md_nbaact", NULL, NULL, "1994", + "NBA Action (Prototype, 19940104)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbaactp3RomInfo, md_nbaactp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action (Prototype, 19940116) +static struct BurnRomInfo md_nbaactp2RomDesc[] = { + { "nba action (prototype - jan 16, 1994).bin", 0x200000, 0xfe43c79d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaactp2) +STD_ROM_FN(md_nbaactp2) + +struct BurnDriver BurnDrvmd_nbaactp2 = { + "md_nbaactp2", "md_nbaact", NULL, NULL, "1994", + "NBA Action (Prototype, 19940116)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaactp2RomInfo, md_nbaactp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action (Prototype, 19940127, broken - C08 missing) +static struct BurnRomInfo md_nbaactp1RomDesc[] = { + { "nba action (prototype - jan 27, 1994) (broken - c08 missing).bin", 0x200000, 0x176a4bc5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaactp1) +STD_ROM_FN(md_nbaactp1) + +struct BurnDriver BurnDrvmd_nbaactp1 = { + "md_nbaactp1", "md_nbaact", NULL, NULL, "1994", + "NBA Action (Prototype, 19940127, broken - C08 missing)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaactp1RomInfo, md_nbaactp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Euro, USA) +static struct BurnRomInfo md_nbaact95RomDesc[] = { + { "nba action '95 starring david robinson (euro, usa).bin", 0x200000, 0xaa7006d6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95) +STD_ROM_FN(md_nbaact95) + +struct BurnDriver BurnDrvmd_nbaact95 = { + "md_nbaact95", NULL, NULL, NULL, "1995", + "NBA Action '95 (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95RomInfo, md_nbaact95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941202-B) +static struct BurnRomInfo md_nbaact95p23RomDesc[] = { + { "nba action '95 (prototype - dec 02, 1994 - b).bin", 0x200000, 0x04bf6f6e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p23) +STD_ROM_FN(md_nbaact95p23) + +struct BurnDriver BurnDrvmd_nbaact95p23 = { + "md_nbaact95p23", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941202-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p23RomInfo, md_nbaact95p23RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941209) +static struct BurnRomInfo md_nbaact95p22RomDesc[] = { + { "nba action '95 (prototype - dec 09, 1994).bin", 0x200000, 0x2b198487, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p22) +STD_ROM_FN(md_nbaact95p22) + +struct BurnDriver BurnDrvmd_nbaact95p22 = { + "md_nbaact95p22", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941209)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p22RomInfo, md_nbaact95p22RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941215) +static struct BurnRomInfo md_nbaact95p21RomDesc[] = { + { "nba action '95 (prototype - dec 15, 1994).bin", 0x200000, 0x10a3b46d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p21) +STD_ROM_FN(md_nbaact95p21) + +struct BurnDriver BurnDrvmd_nbaact95p21 = { + "md_nbaact95p21", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941215)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p21RomInfo, md_nbaact95p21RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941222-A) +static struct BurnRomInfo md_nbaact95p20RomDesc[] = { + { "nba action '95 (prototype - dec 22, 1994 - a).bin", 0x200000, 0xf92ba323, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p20) +STD_ROM_FN(md_nbaact95p20) + +struct BurnDriver BurnDrvmd_nbaact95p20 = { + "md_nbaact95p20", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941222-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p20RomInfo, md_nbaact95p20RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941224-A) +static struct BurnRomInfo md_nbaact95p19RomDesc[] = { + { "nba action '95 (prototype - dec 24, 1994 - a).bin", 0x200000, 0xddb04550, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p19) +STD_ROM_FN(md_nbaact95p19) + +struct BurnDriver BurnDrvmd_nbaact95p19 = { + "md_nbaact95p19", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941224-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p19RomInfo, md_nbaact95p19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941229) +static struct BurnRomInfo md_nbaact95p18RomDesc[] = { + { "nba action '95 (prototype - dec 29, 1994).bin", 0x200000, 0xdcebe32a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p18) +STD_ROM_FN(md_nbaact95p18) + +struct BurnDriver BurnDrvmd_nbaact95p18 = { + "md_nbaact95p18", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941229)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p18RomInfo, md_nbaact95p18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941230) +static struct BurnRomInfo md_nbaact95p17RomDesc[] = { + { "nba action '95 (prototype - dec 30, 1994).bin", 0x200000, 0xd87956c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p17) +STD_ROM_FN(md_nbaact95p17) + +struct BurnDriver BurnDrvmd_nbaact95p17 = { + "md_nbaact95p17", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941230)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p17RomInfo, md_nbaact95p17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941231) +static struct BurnRomInfo md_nbaact95p16RomDesc[] = { + { "nba action '95 (prototype - dec 31, 1994).bin", 0x200000, 0x582a378f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p16) +STD_ROM_FN(md_nbaact95p16) + +struct BurnDriver BurnDrvmd_nbaact95p16 = { + "md_nbaact95p16", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941231)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p16RomInfo, md_nbaact95p16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950201, Alt) +static struct BurnRomInfo md_nbaact95p03RomDesc[] = { + { "nba action '95 (prototype - feb 01, 1995).bin", 0x200000, 0x2c02a79d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p03) +STD_ROM_FN(md_nbaact95p03) + +struct BurnDriver BurnDrvmd_nbaact95p03 = { + "md_nbaact95p03", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950201, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p03RomInfo, md_nbaact95p03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950201) +static struct BurnRomInfo md_nbaact95p02RomDesc[] = { + { "nba action '95 (prototype - feb 1, 1995).bin", 0x1ff49e, 0xc4a0a624, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p02) +STD_ROM_FN(md_nbaact95p02) + +struct BurnDriver BurnDrvmd_nbaact95p02 = { + "md_nbaact95p02", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950201)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p02RomInfo, md_nbaact95p02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950202) +static struct BurnRomInfo md_nbaact95p01RomDesc[] = { + { "nba action '95 (prototype - feb 2, 1995).bin", 0x1fe1f0, 0xa9167903, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p01) +STD_ROM_FN(md_nbaact95p01) + +struct BurnDriver BurnDrvmd_nbaact95p01 = { + "md_nbaact95p01", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p01RomInfo, md_nbaact95p01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950103) +static struct BurnRomInfo md_nbaact95p15RomDesc[] = { + { "nba action '95 (prototype - jan 03, 1995).bin", 0x200000, 0x374af160, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p15) +STD_ROM_FN(md_nbaact95p15) + +struct BurnDriver BurnDrvmd_nbaact95p15 = { + "md_nbaact95p15", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950103)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p15RomInfo, md_nbaact95p15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950108) +static struct BurnRomInfo md_nbaact95p14RomDesc[] = { + { "nba action '95 (prototype - jan 08, 1995).bin", 0x200000, 0x0a6b7b9e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p14) +STD_ROM_FN(md_nbaact95p14) + +struct BurnDriver BurnDrvmd_nbaact95p14 = { + "md_nbaact95p14", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950108)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p14RomInfo, md_nbaact95p14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950112) +static struct BurnRomInfo md_nbaact95p13RomDesc[] = { + { "nba action '95 (prototype - jan 12, 1995).bin", 0x200000, 0xb47ff025, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p13) +STD_ROM_FN(md_nbaact95p13) + +struct BurnDriver BurnDrvmd_nbaact95p13 = { + "md_nbaact95p13", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950112)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p13RomInfo, md_nbaact95p13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950115-A) +static struct BurnRomInfo md_nbaact95p12RomDesc[] = { + { "nba action '95 (prototype - jan 15, 1995 - a).bin", 0x200000, 0x9c6a1f27, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p12) +STD_ROM_FN(md_nbaact95p12) + +struct BurnDriver BurnDrvmd_nbaact95p12 = { + "md_nbaact95p12", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950115-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p12RomInfo, md_nbaact95p12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950121) +static struct BurnRomInfo md_nbaact95p11RomDesc[] = { + { "nba action '95 (prototype - jan 21, 1995).bin", 0x200000, 0xe337bdfb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p11) +STD_ROM_FN(md_nbaact95p11) + +struct BurnDriver BurnDrvmd_nbaact95p11 = { + "md_nbaact95p11", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950121)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p11RomInfo, md_nbaact95p11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950122-B) +static struct BurnRomInfo md_nbaact95p10RomDesc[] = { + { "nba action '95 (prototype - jan 22, 1995 - b).bin", 0x200000, 0x7bd7ca47, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p10) +STD_ROM_FN(md_nbaact95p10) + +struct BurnDriver BurnDrvmd_nbaact95p10 = { + "md_nbaact95p10", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950122-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p10RomInfo, md_nbaact95p10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950124-B) +static struct BurnRomInfo md_nbaact95p09RomDesc[] = { + { "nba action '95 (prototype - jan 24, 1995 - b).bin", 0x200000, 0x15abcf41, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p09) +STD_ROM_FN(md_nbaact95p09) + +struct BurnDriver BurnDrvmd_nbaact95p09 = { + "md_nbaact95p09", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950124-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p09RomInfo, md_nbaact95p09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950127-A) +static struct BurnRomInfo md_nbaact95p08RomDesc[] = { + { "nba action '95 (prototype - jan 27, 1995 - a).bin", 0x1fe190, 0x79c7fb00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p08) +STD_ROM_FN(md_nbaact95p08) + +struct BurnDriver BurnDrvmd_nbaact95p08 = { + "md_nbaact95p08", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950127-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p08RomInfo, md_nbaact95p08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950127-B) +static struct BurnRomInfo md_nbaact95p07RomDesc[] = { + { "nba action '95 (prototype - jan 27, 1995 - b).bin", 0x1fe190, 0xef7f608b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p07) +STD_ROM_FN(md_nbaact95p07) + +struct BurnDriver BurnDrvmd_nbaact95p07 = { + "md_nbaact95p07", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950127-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p07RomInfo, md_nbaact95p07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950128-A) +static struct BurnRomInfo md_nbaact95p06RomDesc[] = { + { "nba action '95 (prototype - jan 28, 1995 - a).bin", 0x200000, 0x57c2c69c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p06) +STD_ROM_FN(md_nbaact95p06) + +struct BurnDriver BurnDrvmd_nbaact95p06 = { + "md_nbaact95p06", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950128-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p06RomInfo, md_nbaact95p06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950128) +static struct BurnRomInfo md_nbaact95p05RomDesc[] = { + { "nba action '95 (prototype - jan 28, 1995).bin", 0x1fe19e, 0x97d7075d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p05) +STD_ROM_FN(md_nbaact95p05) + +struct BurnDriver BurnDrvmd_nbaact95p05 = { + "md_nbaact95p05", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950128)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p05RomInfo, md_nbaact95p05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19950130) +static struct BurnRomInfo md_nbaact95p04RomDesc[] = { + { "nba action '95 (prototype - jan 30, 1995).bin", 0x200000, 0x2fac80b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p04) +STD_ROM_FN(md_nbaact95p04) + +struct BurnDriver BurnDrvmd_nbaact95p04 = { + "md_nbaact95p04", "md_nbaact95", NULL, NULL, "1995", + "NBA Action '95 (Prototype, 19950130)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p04RomInfo, md_nbaact95p04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941118) +static struct BurnRomInfo md_nbaact95p25RomDesc[] = { + { "nba action '95 (prototype - nov 18, 1994).bin", 0x200000, 0x2d411e4b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p25) +STD_ROM_FN(md_nbaact95p25) + +struct BurnDriver BurnDrvmd_nbaact95p25 = { + "md_nbaact95p25", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941118)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p25RomInfo, md_nbaact95p25RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Action '95 (Prototype, 19941123-A) +static struct BurnRomInfo md_nbaact95p24RomDesc[] = { + { "nba action '95 (prototype - nov 23, 1994 - a).bin", 0x200000, 0x4650cfcc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaact95p24) +STD_ROM_FN(md_nbaact95p24) + +struct BurnDriver BurnDrvmd_nbaact95p24 = { + "md_nbaact95p24", "md_nbaact95", NULL, NULL, "1994", + "NBA Action '95 (Prototype, 19941123-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaact95p24RomInfo, md_nbaact95p24RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA All-Star Challenge (Euro, USA) +static struct BurnRomInfo md_nbaallstRomDesc[] = { + { "nba all-star challenge (euro, usa).bin", 0x100000, 0xc4674adf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaallst) +STD_ROM_FN(md_nbaallst) + +struct BurnDriver BurnDrvmd_nbaallst = { + "md_nbaallst", NULL, NULL, NULL, "1992", + "NBA All-Star Challenge (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbaallstRomInfo, md_nbaallstRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Hang Time (Euro) +static struct BurnRomInfo md_nbahangRomDesc[] = { + { "nba hang time (euro).bin", 0x300000, 0xedb4d4aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbahang) +STD_ROM_FN(md_nbahang) + +struct BurnDriver BurnDrvmd_nbahang = { + "md_nbahang", NULL, NULL, NULL, "1996", + "NBA Hang Time (Euro)\0", NULL, "Midway", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbahangRomInfo, md_nbahangRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Hang Time (USA) +static struct BurnRomInfo md_nbahanguRomDesc[] = { + { "nba hang time (usa).bin", 0x300000, 0x176b0338, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbahangu) +STD_ROM_FN(md_nbahangu) + +struct BurnDriver BurnDrvmd_nbahangu = { + "md_nbahangu", "md_nbahang", NULL, NULL, "1996", + "NBA Hang Time (USA)\0", NULL, "Midway", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbahanguRomInfo, md_nbahanguRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Jam (Euro, USA, v1.1) +static struct BurnRomInfo md_nbajamRomDesc[] = { + { "nba jam (euro, usa) (v1.1).bin", 0x200000, 0xeb8360e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbajam) +STD_ROM_FN(md_nbajam) + +struct BurnDriver BurnDrvmd_nbajam = { + "md_nbajam", NULL, NULL, NULL, "1993", + "NBA Jam (Euro, USA, v1.1)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbajamRomInfo, md_nbajamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Jam (Euro, USA) +static struct BurnRomInfo md_nbajam1RomDesc[] = { + { "s285_ver_1.00.bin", 0x200000, 0x10fa248f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbajam1) +STD_ROM_FN(md_nbajam1) + +struct BurnDriver BurnDrvmd_nbajam1 = { + "md_nbajam1", "md_nbajam", NULL, NULL, "1993", + "NBA Jam (Euro, USA)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbajam1RomInfo, md_nbajam1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Jam (Jpn) +static struct BurnRomInfo md_nbajamjRomDesc[] = { + { "nba jam (jpn).bin", 0x200000, 0xa6c6305a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbajamj) +STD_ROM_FN(md_nbajamj) + +struct BurnDriver BurnDrvmd_nbajamj = { + "md_nbajamj", "md_nbajam", NULL, NULL, "1994", + "NBA Jam (Jpn)\0", NULL, "Acclaim Japan", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbajamjRomInfo, md_nbajamjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Jam Tournament Edition (World) +static struct BurnRomInfo md_nbajamteRomDesc[] = { + { "nba jam tournament edition (world).bin", 0x300000, 0xe9ffcb37, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbajamte) +STD_ROM_FN(md_nbajamte) + +struct BurnDriver BurnDrvmd_nbajamte = { + "md_nbajamte", NULL, NULL, NULL, "1995", + "NBA Jam Tournament Edition (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE, GBF_MISC, 0, + MegadriveGetZipName, md_nbajamteRomInfo, md_nbajamteRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Jam Tournament Edition (World, 2002 Fix Release) +static struct BurnRomInfo md_nbajamtefRomDesc[] = { + { "nba jam tournament edition (world) (fixed).bin", 0x300000, 0x6e25ebf0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbajamtef) +STD_ROM_FN(md_nbajamtef) + +struct BurnDriver BurnDrvmd_nbajamtef = { + "md_nbajamtef", "md_nbajamte", NULL, NULL, "2002?", + "NBA Jam Tournament Edition (World, 2002 Fix Release)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE, GBF_MISC, 0, + MegadriveGetZipName, md_nbajamtefRomInfo, md_nbajamtefRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Live 95 (Euro, USA) +static struct BurnRomInfo md_nbaliv95RomDesc[] = { + { "nba live 95 (euro, usa).bin", 0x200000, 0x66018abc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaliv95) +STD_ROM_FN(md_nbaliv95) + +struct BurnDriver BurnDrvmd_nbaliv95 = { + "md_nbaliv95", NULL, NULL, NULL, "1994", + "NBA Live 95 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaliv95RomInfo, md_nbaliv95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Live 95 (Kor) +static struct BurnRomInfo md_nbaliv95kRomDesc[] = { + { "lh5370hc.bin", 0x200000, 0x779c1244, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaliv95k) +STD_ROM_FN(md_nbaliv95k) + +struct BurnDriver BurnDrvmd_nbaliv95k = { + "md_nbaliv95k", "md_nbaliv95", NULL, NULL, "1994", + "NBA Live 95 (Kor)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbaliv95kRomInfo, md_nbaliv95kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Live 96 (Euro, USA) +static struct BurnRomInfo md_nbaliv96RomDesc[] = { + { "nba live 96 (euro, usa).bin", 0x200000, 0x49de0062, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaliv96) +STD_ROM_FN(md_nbaliv96) + +struct BurnDriver BurnDrvmd_nbaliv96 = { + "md_nbaliv96", NULL, NULL, NULL, "1995", + "NBA Live 96 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaliv96RomInfo, md_nbaliv96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Live 97 (Euro, USA) +static struct BurnRomInfo md_nbaliv97RomDesc[] = { + { "nba live 97 (euro, usa).bin", 0x200000, 0x7024843a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaliv97) +STD_ROM_FN(md_nbaliv97) + +struct BurnDriver BurnDrvmd_nbaliv97 = { + "md_nbaliv97", NULL, NULL, NULL, "1996", + "NBA Live 97 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbaliv97RomInfo, md_nbaliv97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Live 98 (USA) +static struct BurnRomInfo md_nbaliv98RomDesc[] = { + { "nba live 98 (usa).bin", 0x200000, 0x23473a8a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbaliv98) +STD_ROM_FN(md_nbaliv98) + +struct BurnDriver BurnDrvmd_nbaliv98 = { + "md_nbaliv98", NULL, NULL, NULL, "1997", + "NBA Live 98 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nbaliv98RomInfo, md_nbaliv98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Playoffs - Bulls Vs Blazers (Jpn) +static struct BurnRomInfo md_bullvsbljRomDesc[] = { + { "nba playoffs - bulls vs blazers (jpn).bin", 0x100000, 0xeae8c000, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bullvsblj) +STD_ROM_FN(md_bullvsblj) + +struct BurnDriver BurnDrvmd_bullvsblj = { + "md_bullvsblj", "md_bullvsbl", NULL, NULL, "1993", + "NBA Playoffs - Bulls Vs Blazers (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bullvsbljRomInfo, md_bullvsbljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Playoffs - Bulls Vs Blazers (Jpn, Alt) +static struct BurnRomInfo md_bullvsblj1RomDesc[] = { + { "nba playoffs - bulls vs blazers (jpn) (alt).bin", 0x100000, 0x4565ce1f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bullvsblj1) +STD_ROM_FN(md_bullvsblj1) + +struct BurnDriver BurnDrvmd_bullvsblj1 = { + "md_bullvsblj1", "md_bullvsbl", NULL, NULL, "1993", + "NBA Playoffs - Bulls Vs Blazers (Jpn, Alt)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bullvsblj1RomInfo, md_bullvsblj1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Pro Basketball - Bulls Vs Lakers (Jpn) +static struct BurnRomInfo md_bullvslajRomDesc[] = { + { "nba pro basketball - bulls vs lakers (jpn).bin", 0x100000, 0x4416ce39, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bullvslaj) +STD_ROM_FN(md_bullvslaj) + +struct BurnDriver BurnDrvmd_bullvslaj = { + "md_bullvslaj", "md_bullvsla", NULL, NULL, "1993", + "NBA Pro Basketball - Bulls Vs Lakers (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bullvslajRomInfo, md_bullvslajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Pro Basketball '94 (Jpn) +static struct BurnRomInfo md_nbapro94RomDesc[] = { + { "nba pro basketball '94 (jpn).bin", 0x200000, 0xeea19bce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbapro94) +STD_ROM_FN(md_nbapro94) + +struct BurnDriver BurnDrvmd_nbapro94 = { + "md_nbapro94", NULL, NULL, NULL, "1994", + "NBA Pro Basketball '94 (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbapro94RomInfo, md_nbapro94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Showdown '94 (Euro, USA) +static struct BurnRomInfo md_nbashowRomDesc[] = { + { "nba showdown '94 (euro, usa).bin", 0x200000, 0x160b7090, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbashow) +STD_ROM_FN(md_nbashow) + +struct BurnDriver BurnDrvmd_nbashow = { + "md_nbashow", NULL, NULL, NULL, "1994", + "NBA Showdown '94 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbashowRomInfo, md_nbashowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA Showdown '94 (USA, Prototype) +static struct BurnRomInfo md_nbashowpRomDesc[] = { + { "nba showdown '94 (usa) (beta).bin", 0x200000, 0x6643a308, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nbashowp) +STD_ROM_FN(md_nbashowp) + +struct BurnDriver BurnDrvmd_nbashowp = { + "md_nbashowp", "md_nbashow", NULL, NULL, "1994", + "NBA Showdown '94 (USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nbashowpRomInfo, md_nbashowpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NCAA Final Four Basketball (USA) +static struct BurnRomInfo md_ncaabaskRomDesc[] = { + { "ncaa final four basketball (usa).bin", 0x180000, 0xed0c1303, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ncaabask) +STD_ROM_FN(md_ncaabask) + +struct BurnDriver BurnDrvmd_ncaabask = { + "md_ncaabask", NULL, NULL, NULL, "1994", + "NCAA Final Four Basketball (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ncaabaskRomInfo, md_ncaabaskRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NCAA Football (USA) +static struct BurnRomInfo md_ncaafootRomDesc[] = { + { "ncaa football (usa).bin", 0x100000, 0x081012f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ncaafoot) +STD_ROM_FN(md_ncaafoot) + +struct BurnDriver BurnDrvmd_ncaafoot = { + "md_ncaafoot", NULL, NULL, NULL, "1994", + "NCAA Football (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ncaafootRomInfo, md_ncaafootRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nekketsu Koukou Dodgeball Bu - Soccer Hen MD (Jpn) +static struct BurnRomInfo md_nekketsuRomDesc[] = { + { "nekketsu koukou dodgeball bu - soccer hen md (jpn).bin", 0x080000, 0xf49c3a86, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nekketsu) +STD_ROM_FN(md_nekketsu) + +struct BurnDriver BurnDrvmd_nekketsu = { + "md_nekketsu", NULL, NULL, NULL, "1992", + "Nekketsu Koukou Dodgeball Bu - Soccer Hen MD (Jpn)\0", NULL, "Palsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nekketsuRomInfo, md_nekketsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// New 3D Golf Simulation Devil's Course (Jpn) +static struct BurnRomInfo md_n3dgdeviRomDesc[] = { + { "new 3d golf simulation devil's course (jpn).bin", 0x180000, 0xbd090c67, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_n3dgdevi) +STD_ROM_FN(md_n3dgdevi) + +struct BurnDriver BurnDrvmd_n3dgdevi = { + "md_n3dgdevi", NULL, NULL, NULL, "1994", + "New 3D Golf Simulation Devil's Course (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_n3dgdeviRomInfo, md_n3dgdeviRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// New 3D Golf Simulation Harukanaru Augusta (Jpn) +static struct BurnRomInfo md_n3dgauguRomDesc[] = { + { "mpr-16076.bin", 0x180000, 0xd2a9bf92, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_n3dgaugu) +STD_ROM_FN(md_n3dgaugu) + +struct BurnDriver BurnDrvmd_n3dgaugu = { + "md_n3dgaugu", NULL, NULL, NULL, "1993", + "New 3D Golf Simulation Harukanaru Augusta (Jpn)\0", NULL, "T & E Soft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_n3dgauguRomInfo, md_n3dgauguRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// New 3D Golf Simulation Waialae no Kiseki (Jpn) +static struct BurnRomInfo md_n3dgwaiaRomDesc[] = { + { "new 3d golf simulation waialae no kiseki (jpn).bin", 0x180000, 0xcbe2c1f6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_n3dgwaia) +STD_ROM_FN(md_n3dgwaia) + +struct BurnDriver BurnDrvmd_n3dgwaia = { + "md_n3dgwaia", NULL, NULL, NULL, "1994", + "New 3D Golf Simulation Waialae no Kiseki (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_n3dgwaiaRomInfo, md_n3dgwaiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Euro, USA) +static struct BurnRomInfo md_nfl95RomDesc[] = { + { "nfl '95 (euro, usa).bin", 0x200000, 0xb58e4a81, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95) +STD_ROM_FN(md_nfl95) + +struct BurnDriver BurnDrvmd_nfl95 = { + "md_nfl95", NULL, NULL, NULL, "1994", + "NFL '95 (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95RomInfo, md_nfl95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940801) +static struct BurnRomInfo md_nfl95p21RomDesc[] = { + { "nfl '95 (prototype - aug 01, 1994).bin", 0x200000, 0x5a57ea4e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p21) +STD_ROM_FN(md_nfl95p21) + +struct BurnDriver BurnDrvmd_nfl95p21 = { + "md_nfl95p21", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940801)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p21RomInfo, md_nfl95p21RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940805) +static struct BurnRomInfo md_nfl95p20RomDesc[] = { + { "nfl '95 (prototype - aug 05, 1994).bin", 0x200000, 0x88d51773, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p20) +STD_ROM_FN(md_nfl95p20) + +struct BurnDriver BurnDrvmd_nfl95p20 = { + "md_nfl95p20", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940805)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p20RomInfo, md_nfl95p20RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940810) +static struct BurnRomInfo md_nfl95p19RomDesc[] = { + { "nfl '95 (prototype - aug 10, 1994).bin", 0x200000, 0xa3c5710b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p19) +STD_ROM_FN(md_nfl95p19) + +struct BurnDriver BurnDrvmd_nfl95p19 = { + "md_nfl95p19", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940810)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p19RomInfo, md_nfl95p19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940812) +static struct BurnRomInfo md_nfl95p18RomDesc[] = { + { "nfl '95 (prototype - aug 12, 1994).bin", 0x200000, 0x3d23633b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p18) +STD_ROM_FN(md_nfl95p18) + +struct BurnDriver BurnDrvmd_nfl95p18 = { + "md_nfl95p18", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940812)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p18RomInfo, md_nfl95p18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940812, Alt) +static struct BurnRomInfo md_nfl95p17RomDesc[] = { + { "nfl '95 (prototype - aug 12, 1994 - b).bin", 0x200000, 0xcc86a259, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p17) +STD_ROM_FN(md_nfl95p17) + +struct BurnDriver BurnDrvmd_nfl95p17 = { + "md_nfl95p17", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940812, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p17RomInfo, md_nfl95p17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940817-B) +static struct BurnRomInfo md_nfl95p16RomDesc[] = { + { "nfl '95 (prototype - aug 17, 1994 - b).bin", 0x200000, 0xa6015c29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p16) +STD_ROM_FN(md_nfl95p16) + +struct BurnDriver BurnDrvmd_nfl95p16 = { + "md_nfl95p16", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940817-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p16RomInfo, md_nfl95p16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940817) +static struct BurnRomInfo md_nfl95p15RomDesc[] = { + { "nfl '95 (prototype - aug 17, 1994).bin", 0x200000, 0x655966c8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p15) +STD_ROM_FN(md_nfl95p15) + +struct BurnDriver BurnDrvmd_nfl95p15 = { + "md_nfl95p15", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940817)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p15RomInfo, md_nfl95p15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940822) +static struct BurnRomInfo md_nfl95p14RomDesc[] = { + { "nfl '95 (prototype - aug 22, 1994).bin", 0x200000, 0xb01434e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p14) +STD_ROM_FN(md_nfl95p14) + +struct BurnDriver BurnDrvmd_nfl95p14 = { + "md_nfl95p14", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940822)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p14RomInfo, md_nfl95p14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940830) +static struct BurnRomInfo md_nfl95p13RomDesc[] = { + { "nfl '95 (prototype - aug 30, 1994).bin", 0x200000, 0xd0e0a436, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p13) +STD_ROM_FN(md_nfl95p13) + +struct BurnDriver BurnDrvmd_nfl95p13 = { + "md_nfl95p13", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940830)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p13RomInfo, md_nfl95p13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940831) +static struct BurnRomInfo md_nfl95p12RomDesc[] = { + { "nfl '95 (prototype - aug 31, 1994).bin", 0x200000, 0xc360521e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p12) +STD_ROM_FN(md_nfl95p12) + +struct BurnDriver BurnDrvmd_nfl95p12 = { + "md_nfl95p12", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940831)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p12RomInfo, md_nfl95p12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940901) +static struct BurnRomInfo md_nfl95p11RomDesc[] = { + { "nfl '95 (prototype - sep 01, 1994).bin", 0x200000, 0x9240fcaa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p11) +STD_ROM_FN(md_nfl95p11) + +struct BurnDriver BurnDrvmd_nfl95p11 = { + "md_nfl95p11", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940901)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p11RomInfo, md_nfl95p11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940902) +static struct BurnRomInfo md_nfl95p10RomDesc[] = { + { "nfl '95 (prototype - sep 02, 1994).bin", 0x200000, 0xff049a49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p10) +STD_ROM_FN(md_nfl95p10) + +struct BurnDriver BurnDrvmd_nfl95p10 = { + "md_nfl95p10", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940902)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p10RomInfo, md_nfl95p10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940904) +static struct BurnRomInfo md_nfl95p09RomDesc[] = { + { "nfl '95 (prototype - sep 04, 1994).bin", 0x200000, 0x60604d40, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p09) +STD_ROM_FN(md_nfl95p09) + +struct BurnDriver BurnDrvmd_nfl95p09 = { + "md_nfl95p09", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940904)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p09RomInfo, md_nfl95p09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940905-B) +static struct BurnRomInfo md_nfl95p08RomDesc[] = { + { "nfl '95 (prototype - sep 05, 1994 - b).bin", 0x200000, 0x123985a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p08) +STD_ROM_FN(md_nfl95p08) + +struct BurnDriver BurnDrvmd_nfl95p08 = { + "md_nfl95p08", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940905-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p08RomInfo, md_nfl95p08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940905) +static struct BurnRomInfo md_nfl95p07RomDesc[] = { + { "nfl '95 (prototype - sep 05, 1994).bin", 0x200000, 0xdbdf61ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p07) +STD_ROM_FN(md_nfl95p07) + +struct BurnDriver BurnDrvmd_nfl95p07 = { + "md_nfl95p07", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940905)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p07RomInfo, md_nfl95p07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940906) +static struct BurnRomInfo md_nfl95p06RomDesc[] = { + { "nfl '95 (prototype - sep 06, 1994).bin", 0x200000, 0x624b8699, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p06) +STD_ROM_FN(md_nfl95p06) + +struct BurnDriver BurnDrvmd_nfl95p06 = { + "md_nfl95p06", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940906)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p06RomInfo, md_nfl95p06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940907) +static struct BurnRomInfo md_nfl95p05RomDesc[] = { + { "nfl '95 (prototype - sep 07, 1994).bin", 0x200000, 0xae8aa4be, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p05) +STD_ROM_FN(md_nfl95p05) + +struct BurnDriver BurnDrvmd_nfl95p05 = { + "md_nfl95p05", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940907)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p05RomInfo, md_nfl95p05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940908) +static struct BurnRomInfo md_nfl95p04RomDesc[] = { + { "nfl '95 (prototype - sep 08, 1994).bin", 0x200000, 0x22c5e289, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p04) +STD_ROM_FN(md_nfl95p04) + +struct BurnDriver BurnDrvmd_nfl95p04 = { + "md_nfl95p04", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940908)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p04RomInfo, md_nfl95p04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940909) +static struct BurnRomInfo md_nfl95p03RomDesc[] = { + { "nfl '95 (prototype - sep 09, 1994).bin", 0x200000, 0x55df1066, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p03) +STD_ROM_FN(md_nfl95p03) + +struct BurnDriver BurnDrvmd_nfl95p03 = { + "md_nfl95p03", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940909)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p03RomInfo, md_nfl95p03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940911-B) +static struct BurnRomInfo md_nfl95p02RomDesc[] = { + { "nfl '95 (prototype - sep 11, 1994 - b).bin", 0x200000, 0x111ac6a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p02) +STD_ROM_FN(md_nfl95p02) + +struct BurnDriver BurnDrvmd_nfl95p02 = { + "md_nfl95p02", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940911-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p02RomInfo, md_nfl95p02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL '95 (Prototype, 19940911) +static struct BurnRomInfo md_nfl95p01RomDesc[] = { + { "nfl '95 (prototype - sep 11, 1994).bin", 0x200000, 0x21614c4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl95p01) +STD_ROM_FN(md_nfl95p01) + +struct BurnDriver BurnDrvmd_nfl95p01 = { + "md_nfl95p01", "md_nfl95", NULL, NULL, "1994", + "NFL '95 (Prototype, 19940911)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl95p01RomInfo, md_nfl95p01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL 98 (USA) +static struct BurnRomInfo md_nfl98RomDesc[] = { + { "nfl 98 (usa).bin", 0x200000, 0xf73ec54c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl98) +STD_ROM_FN(md_nfl98) + +struct BurnDriver BurnDrvmd_nfl98 = { + "md_nfl98", NULL, NULL, NULL, "1997", + "NFL 98 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl98RomInfo, md_nfl98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL Football '94 Starring Joe Montana (USA) +static struct BurnRomInfo md_nfl94RomDesc[] = { + { "nfl football '94 starring joe montana (usa).bin", 0x200000, 0x0d486ed5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl94) +STD_ROM_FN(md_nfl94) + +struct BurnDriver BurnDrvmd_nfl94 = { + "md_nfl94", NULL, NULL, NULL, "1993", + "NFL Football '94 Starring Joe Montana (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfl94RomInfo, md_nfl94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL Football '94 (Jpn) +static struct BurnRomInfo md_nfl94jRomDesc[] = { + { "nfl football '94 (jpn).bin", 0x200000, 0xe490dc4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfl94j) +STD_ROM_FN(md_nfl94j) + +struct BurnDriver BurnDrvmd_nfl94j = { + "md_nfl94j", "md_nfl94", NULL, NULL, "1994", + "NFL Football '94 (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nfl94jRomInfo, md_nfl94jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL Quarterback Club (World) +static struct BurnRomInfo md_nflqbRomDesc[] = { + { "nfl quarterback club (world).bin", 0x300000, 0x94542eaf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nflqb) +STD_ROM_FN(md_nflqb) + +struct BurnDriver BurnDrvmd_nflqb = { + "md_nflqb", NULL, NULL, NULL, "1994", + "NFL Quarterback Club (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE, GBF_MISC, 0, + MegadriveGetZipName, md_nflqbRomInfo, md_nflqbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL Quarterback Club 96 (Euro, USA) +static struct BurnRomInfo md_nflqb96RomDesc[] = { + { "nfl quarterback club 96 (euro, usa).bin", 0x400000, 0xd5a37cab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nflqb96) +STD_ROM_FN(md_nflqb96) + +struct BurnDriver BurnDrvmd_nflqb96 = { + "md_nflqb96", NULL, NULL, NULL, "1996", + "NFL Quarterback Club 96 (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_NFL_QB_96, GBF_MISC, 0, + MegadriveGetZipName, md_nflqb96RomInfo, md_nflqb96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NFL Sports Talk Football '93 Starring Joe Montana (Euro, USA) +static struct BurnRomInfo md_nflsportRomDesc[] = { + { "mpr-15005+mpr-15006.bin", 0x180000, 0xce0b1fe1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nflsport) +STD_ROM_FN(md_nflsport) + +struct BurnDriver BurnDrvmd_nflsport = { + "md_nflsport", NULL, NULL, NULL, "1992", + "NFL Sports Talk Football '93 Starring Joe Montana (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nflsportRomInfo, md_nflsportRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHK Taiga Drama - Taiheiki (Jpn) +static struct BurnRomInfo md_nhktaigaRomDesc[] = { + { "nhk taiga drama - taiheiki (jpn).bin", 0x100000, 0x09fbb30e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhktaiga) +STD_ROM_FN(md_nhktaiga) + +struct BurnDriver BurnDrvmd_nhktaiga = { + "md_nhktaiga", NULL, NULL, NULL, "1991", + "NHK Taiga Drama - Taiheiki (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhktaigaRomInfo, md_nhktaigaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL 95 (Euro, USA) +static struct BurnRomInfo md_nhl95RomDesc[] = { + { "nhl 95 (euro, usa).bin", 0x200000, 0xe8ee917e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhl95) +STD_ROM_FN(md_nhl95) + +struct BurnDriver BurnDrvmd_nhl95 = { + "md_nhl95", NULL, NULL, NULL, "1995", + "NHL 95 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhl95RomInfo, md_nhl95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL 96 (Euro, USA) +static struct BurnRomInfo md_nhl96RomDesc[] = { + { "nhl 96 (euro, usa).bin", 0x200000, 0x8135702c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhl96) +STD_ROM_FN(md_nhl96) + +struct BurnDriver BurnDrvmd_nhl96 = { + "md_nhl96", NULL, NULL, NULL, "1995", + "NHL 96 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhl96RomInfo, md_nhl96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL 97 (Euro, USA) +static struct BurnRomInfo md_nhl97RomDesc[] = { + { "nhl 97 (euro, usa).bin", 0x200000, 0xf067c103, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhl97) +STD_ROM_FN(md_nhl97) + +struct BurnDriver BurnDrvmd_nhl97 = { + "md_nhl97", NULL, NULL, NULL, "1996", + "NHL 97 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhl97RomInfo, md_nhl97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL 98 (USA) +static struct BurnRomInfo md_nhl98RomDesc[] = { + { "nhl 98 (usa).bin", 0x200000, 0x7b64cd98, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhl98) +STD_ROM_FN(md_nhl98) + +struct BurnDriver BurnDrvmd_nhl98 = { + "md_nhl98", NULL, NULL, NULL, "1997", + "NHL 98 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhl98RomInfo, md_nhl98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (USA) +static struct BurnRomInfo md_nhlasRomDesc[] = { + { "nhl all-star hockey '95 (usa).bin", 0x200000, 0xe6c0218b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlas) +STD_ROM_FN(md_nhlas) + +struct BurnDriver BurnDrvmd_nhlas = { + "md_nhlas", NULL, NULL, NULL, "1995", + "NHL All-Star Hockey '95 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasRomInfo, md_nhlasRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941201-B) +static struct BurnRomInfo md_nhlasp03RomDesc[] = { + { "nhl all-star hockey '95 (prototype - dec 01, 1994 - b).bin", 0x1ffffa, 0xc209d720, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp03) +STD_ROM_FN(md_nhlasp03) + +struct BurnDriver BurnDrvmd_nhlasp03 = { + "md_nhlasp03", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941201-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp03RomInfo, md_nhlasp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941201) +static struct BurnRomInfo md_nhlasp02RomDesc[] = { + { "nhl all-star hockey '95 (prototype - dec 01, 1994).bin", 0x1ffffa, 0x112e4cb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp02) +STD_ROM_FN(md_nhlasp02) + +struct BurnDriver BurnDrvmd_nhlasp02 = { + "md_nhlasp02", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941201)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp02RomInfo, md_nhlasp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941202) +static struct BurnRomInfo md_nhlasp01RomDesc[] = { + { "nhl all-star hockey '95 (prototype - dec 02, 1994).bin", 0x1ffffa, 0x01d6a6c7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp01) +STD_ROM_FN(md_nhlasp01) + +struct BurnDriver BurnDrvmd_nhlasp01 = { + "md_nhlasp01", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp01RomInfo, md_nhlasp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941107) +static struct BurnRomInfo md_nhlasp12RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 07, 1994).bin", 0x200000, 0xe8f2c88f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp12) +STD_ROM_FN(md_nhlasp12) + +struct BurnDriver BurnDrvmd_nhlasp12 = { + "md_nhlasp12", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941107)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp12RomInfo, md_nhlasp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941109) +static struct BurnRomInfo md_nhlasp11RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 09, 1994).bin", 0x1ffff9, 0x82624073, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp11) +STD_ROM_FN(md_nhlasp11) + +struct BurnDriver BurnDrvmd_nhlasp11 = { + "md_nhlasp11", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941109)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp11RomInfo, md_nhlasp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941119) +static struct BurnRomInfo md_nhlasp10RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 19, 1994).bin", 0x200000, 0xcd0f588a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp10) +STD_ROM_FN(md_nhlasp10) + +struct BurnDriver BurnDrvmd_nhlasp10 = { + "md_nhlasp10", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941119)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp10RomInfo, md_nhlasp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941121) +static struct BurnRomInfo md_nhlasp09RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 21, 1994).bin", 0x200000, 0xcfe4059d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp09) +STD_ROM_FN(md_nhlasp09) + +struct BurnDriver BurnDrvmd_nhlasp09 = { + "md_nhlasp09", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941121)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp09RomInfo, md_nhlasp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941122) +static struct BurnRomInfo md_nhlasp08RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 22, 1994).bin", 0x1ffffa, 0x81d30fe6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp08) +STD_ROM_FN(md_nhlasp08) + +struct BurnDriver BurnDrvmd_nhlasp08 = { + "md_nhlasp08", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941122)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp08RomInfo, md_nhlasp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941123) +static struct BurnRomInfo md_nhlasp07RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 23, 1994).bin", 0x1ffffa, 0x88d4fc38, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp07) +STD_ROM_FN(md_nhlasp07) + +struct BurnDriver BurnDrvmd_nhlasp07 = { + "md_nhlasp07", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941123)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp07RomInfo, md_nhlasp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941127) +static struct BurnRomInfo md_nhlasp06RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 27, 1994).bin", 0x1ffffa, 0x658ffe52, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp06) +STD_ROM_FN(md_nhlasp06) + +struct BurnDriver BurnDrvmd_nhlasp06 = { + "md_nhlasp06", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941127)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp06RomInfo, md_nhlasp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941128) +static struct BurnRomInfo md_nhlasp05RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 28, 1994).bin", 0x1ffffa, 0x51ad0056, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp05) +STD_ROM_FN(md_nhlasp05) + +struct BurnDriver BurnDrvmd_nhlasp05 = { + "md_nhlasp05", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941128)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp05RomInfo, md_nhlasp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941129) +static struct BurnRomInfo md_nhlasp04RomDesc[] = { + { "nhl all-star hockey '95 (prototype - nov 29, 1994).bin", 0x1ffffa, 0xa060a60b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp04) +STD_ROM_FN(md_nhlasp04) + +struct BurnDriver BurnDrvmd_nhlasp04 = { + "md_nhlasp04", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941129)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp04RomInfo, md_nhlasp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941001) +static struct BurnRomInfo md_nhlasp14RomDesc[] = { + { "nhl all-star hockey '95 (prototype - oct 01, 1994).bin", 0x1ffff9, 0xb1c0fbb2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp14) +STD_ROM_FN(md_nhlasp14) + +struct BurnDriver BurnDrvmd_nhlasp14 = { + "md_nhlasp14", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941001)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp14RomInfo, md_nhlasp14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19941021) +static struct BurnRomInfo md_nhlasp13RomDesc[] = { + { "nhl all-star hockey '95 (prototype - oct 21, 1994).bin", 0x200000, 0x17eb2238, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp13) +STD_ROM_FN(md_nhlasp13) + +struct BurnDriver BurnDrvmd_nhlasp13 = { + "md_nhlasp13", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19941021)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp13RomInfo, md_nhlasp13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19940914) +static struct BurnRomInfo md_nhlasp16RomDesc[] = { + { "nhl all-star hockey '95 (prototype - sep 14, 1994).bin", 0x200000, 0x5d4bc48d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp16) +STD_ROM_FN(md_nhlasp16) + +struct BurnDriver BurnDrvmd_nhlasp16 = { + "md_nhlasp16", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19940914)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp16RomInfo, md_nhlasp16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHL All-Star Hockey '95 (Prototype, 19940929) +static struct BurnRomInfo md_nhlasp15RomDesc[] = { + { "nhl all-star hockey '95 (prototype - sep 29, 1994).bin", 0x1ffff9, 0x96bae44f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlasp15) +STD_ROM_FN(md_nhlasp15) + +struct BurnDriver BurnDrvmd_nhlasp15 = { + "md_nhlasp15", "md_nhlas", NULL, NULL, "1994", + "NHL All-Star Hockey '95 (Prototype, 19940929)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlasp15RomInfo, md_nhlasp15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHLPA Hockey 93 (Euro, USA, v1.1) +static struct BurnRomInfo md_nhlpahRomDesc[] = { + { "h9306.bin", 0x080000, 0xf361d0bf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlpah) +STD_ROM_FN(md_nhlpah) + +struct BurnDriver BurnDrvmd_nhlpah = { + "md_nhlpah", NULL, NULL, NULL, "1992", + "NHLPA Hockey 93 (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA, GBF_MISC, 0, + MegadriveGetZipName, md_nhlpahRomInfo, md_nhlpahRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHLPA Hockey 93 (Euro, USA) +static struct BurnRomInfo md_nhlpah1RomDesc[] = { + { "nhlpa hockey 93 (euro, usa).bin", 0x080000, 0xcbbf4262, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlpah1) +STD_ROM_FN(md_nhlpah1) + +struct BurnDriver BurnDrvmd_nhlpah1 = { + "md_nhlpah1", "md_nhlpah", NULL, NULL, "1992", + "NHLPA Hockey 93 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA, GBF_MISC, 0, + MegadriveGetZipName, md_nhlpah1RomInfo, md_nhlpah1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nigel Mansell's World Championship Racing (Euro) +static struct BurnRomInfo md_nigelmRomDesc[] = { + { "nigel mansell's world championship racing (euro).bin", 0x100000, 0x3fe3d63b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nigelm) +STD_ROM_FN(md_nigelm) + +struct BurnDriver BurnDrvmd_nigelm = { + "md_nigelm", NULL, NULL, NULL, "1993", + "Nigel Mansell's World Championship Racing (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nigelmRomInfo, md_nigelmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nigel Mansell's World Championship Racing (USA) +static struct BurnRomInfo md_nigelmuRomDesc[] = { + { "nigel mansell's world championship racing (usa).bin", 0x100000, 0x6bc57b2c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nigelmu) +STD_ROM_FN(md_nigelmu) + +struct BurnDriver BurnDrvmd_nigelmu = { + "md_nigelmu", "md_nigelm", NULL, NULL, "1993", + "Nigel Mansell's World Championship Racing (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nigelmuRomInfo, md_nigelmuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nightmare Circus (Bra) +static struct BurnRomInfo md_ncircRomDesc[] = { + { "nightmare circus (bra).bin", 0x200000, 0x06da3217, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ncirc) +STD_ROM_FN(md_ncirc) + +struct BurnDriver BurnDrvmd_ncirc = { + "md_ncirc", NULL, NULL, NULL, "1995", + "Nightmare Circus (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ncircRomInfo, md_ncircRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nightmare Circus (Bra, Alt) +static struct BurnRomInfo md_ncirc1RomDesc[] = { + { "nightmare circus (bra) (alt).bin", 0x200000, 0x31de5a94, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ncirc1) +STD_ROM_FN(md_ncirc1) + +struct BurnDriver BurnDrvmd_ncirc1 = { + "md_ncirc1", "md_ncirc", NULL, NULL, "1995", + "Nightmare Circus (Bra, Alt)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ncirc1RomInfo, md_ncirc1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nightmare Circus (Prototype) +static struct BurnRomInfo md_ncircpRomDesc[] = { + { "nightmare circus (prototype).bin", 0x400000, 0xee96f1b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ncircp) +STD_ROM_FN(md_ncircp) + +struct BurnDriver BurnDrvmd_ncircp = { + "md_ncircp", "md_ncirc", NULL, NULL, "199?", + "Nightmare Circus (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ncircpRomInfo, md_ncircpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nikkan Sports Pro Yakyuu Van (Jpn) +static struct BurnRomInfo md_nikkanRomDesc[] = { + { "nikkan sports pro yakyuu van (jpn).bin", 0x080000, 0xc3655a59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nikkan) +STD_ROM_FN(md_nikkan) + +struct BurnDriver BurnDrvmd_nikkan = { + "md_nikkan", NULL, NULL, NULL, "1991", + "Nikkan Sports Pro Yakyuu Van (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nikkanRomInfo, md_nikkanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ninja Burai Densetsu (Jpn) +static struct BurnRomInfo md_ninjabRomDesc[] = { + { "ninja burai densetsu (jpn).bin", 0x100000, 0xa8d828a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ninjab) +STD_ROM_FN(md_ninjab) + +struct BurnDriver BurnDrvmd_ninjab = { + "md_ninjab", NULL, NULL, NULL, "1991", + "Ninja Burai Densetsu (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ninjabRomInfo, md_ninjabRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ninja Gaiden (Jpn, Prototype) +static struct BurnRomInfo md_ngaidenRomDesc[] = { + { "ninja gaiden (jpn) (prototype) (bad dump).bin", 0x100000, 0x0d7f74ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ngaiden) +STD_ROM_FN(md_ngaiden) + +struct BurnDriver BurnDrvmd_ngaiden = { + "md_ngaiden", NULL, NULL, NULL, "1992", + "Ninja Gaiden (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ngaidenRomInfo, md_ngaidenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// No Escape (USA) +static struct BurnRomInfo md_noescapeRomDesc[] = { + { "no escape (usa).bin", 0x200000, 0x44ee5f20, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_noescape) +STD_ROM_FN(md_noescape) + +struct BurnDriver BurnDrvmd_noescape = { + "md_noescape", NULL, NULL, NULL, "1994", + "No Escape (USA)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_noescapeRomInfo, md_noescapeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nobunaga no Yabou - Bushou Fuuunroku (Jpn) +static struct BurnRomInfo md_nobubusRomDesc[] = { + { "mpr-14456.bin", 0x100000, 0x30bf8637, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nobubus) +STD_ROM_FN(md_nobubus) + +struct BurnDriver BurnDrvmd_nobubus = { + "md_nobubus", NULL, NULL, NULL, "1991", + "Nobunaga no Yabou - Bushou Fuuunroku (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nobubusRomInfo, md_nobubusRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nobunaga no Yabou - Haouden (Jpn) +static struct BurnRomInfo md_nobuhaoRomDesc[] = { + { "nobunaga no yabou - haouden (jpn).bin", 0x200000, 0x96c01fc6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nobuhao) +STD_ROM_FN(md_nobuhao) + +struct BurnDriver BurnDrvmd_nobuhao = { + "md_nobuhao", NULL, NULL, NULL, "1994", + "Nobunaga no Yabou - Haouden (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nobuhaoRomInfo, md_nobuhaoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nobunaga's Ambition (USA) +static struct BurnRomInfo md_nobuambRomDesc[] = { + { "nobunaga's ambition (usa).bin", 0x080000, 0xb9bc07bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nobuamb) +STD_ROM_FN(md_nobuamb) + +struct BurnDriver BurnDrvmd_nobuamb = { + "md_nobuamb", NULL, NULL, NULL, "1993", + "Nobunaga's Ambition (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nobuambRomInfo, md_nobuambRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Nobunaga no Yabou - Zenkoku Ban (Jpn) +static struct BurnRomInfo md_nobuzenRomDesc[] = { + { "nobunaga no yabou - zenkoku ban (jpn).bin", 0x080000, 0x1381b313, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nobuzen) +STD_ROM_FN(md_nobuzen) + +struct BurnDriver BurnDrvmd_nobuzen = { + "md_nobuzen", "md_nobuamb", NULL, NULL, "1993", + "Nobunaga no Yabou - Zenkoku Ban (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_nobuzenRomInfo, md_nobuzenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Normy's Beach Babe-O-Rama (Euro, USA) +static struct BurnRomInfo md_normysRomDesc[] = { + { "normy's beach babe-o-rama (euro, usa).bin", 0x100000, 0xb56a8220, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_normys) +STD_ROM_FN(md_normys) + +struct BurnDriver BurnDrvmd_normys = { + "md_normys", NULL, NULL, NULL, "1994", + "Normy's Beach Babe-O-Rama (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_normysRomInfo, md_normysRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Olympic Gold (Euro) +static struct BurnRomInfo md_olympgRomDesc[] = { + { "mpr-14753.bin", 0x080000, 0x924e57d3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_olympg) +STD_ROM_FN(md_olympg) + +struct BurnDriver BurnDrvmd_olympg = { + "md_olympg", NULL, NULL, NULL, "1992", + "Olympic Gold (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_olympgRomInfo, md_olympgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Olympic Gold (Jpn, Kor) +static struct BurnRomInfo md_olympgjRomDesc[] = { + { "olympic gold (jpn, kor).bin", 0x080000, 0xe9c925b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_olympgj) +STD_ROM_FN(md_olympgj) + +struct BurnDriver BurnDrvmd_olympgj = { + "md_olympgj", "md_olympg", NULL, NULL, "1992", + "Olympic Gold (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_olympgjRomInfo, md_olympgjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Olympic Gold (USA) +static struct BurnRomInfo md_olympguRomDesc[] = { + { "olympic gold (usa).bin", 0x080000, 0x339594b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_olympgu) +STD_ROM_FN(md_olympgu) + +struct BurnDriver BurnDrvmd_olympgu = { + "md_olympgu", "md_olympg", NULL, NULL, "1992", + "Olympic Gold (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_olympguRomInfo, md_olympguRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Olympic Gold (USA, Alt) +static struct BurnRomInfo md_olympgu1RomDesc[] = { + { "olympic gold (usa) (alt).bin", 0x080000, 0xaf639376, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_olympgu1) +STD_ROM_FN(md_olympgu1) + +struct BurnDriver BurnDrvmd_olympgu1 = { + "md_olympgu1", "md_olympg", NULL, NULL, "1992", + "Olympic Gold (USA, Alt)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_olympgu1RomInfo, md_olympgu1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Olympic Summer Games (Euro, USA) +static struct BurnRomInfo md_olympsumRomDesc[] = { + { "olympic summer games (euro, usa).bin", 0x200000, 0x9e470fb9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_olympsum) +STD_ROM_FN(md_olympsum) + +struct BurnDriver BurnDrvmd_olympsum = { + "md_olympsum", NULL, NULL, NULL, "1996", + "Olympic Summer Games (Euro, USA)\0", NULL, "Black Pearl", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_olympsumRomInfo, md_olympsumRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Onslaught (Euro, USA) +static struct BurnRomInfo md_onslauRomDesc[] = { + { "onslaught (euro, usa).bin", 0x080000, 0x9f19d6df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_onslau) +STD_ROM_FN(md_onslau) + +struct BurnDriver BurnDrvmd_onslau = { + "md_onslau", NULL, NULL, NULL, "1991", + "Onslaught (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_onslauRomInfo, md_onslauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Euro) +static struct BurnRomInfo md_oozeRomDesc[] = { + { "ooze, the (euro).bin", 0x100000, 0xe16b102c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ooze) +STD_ROM_FN(md_ooze) + +struct BurnDriver BurnDrvmd_ooze = { + "md_ooze", NULL, NULL, NULL, "1995", + "The Ooze (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozeRomInfo, md_oozeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Jpn, USA) +static struct BurnRomInfo md_oozejuRomDesc[] = { + { "ooze, the (usa, jpn).bin", 0x100000, 0x1c0dd42f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozeju) +STD_ROM_FN(md_oozeju) + +struct BurnDriver BurnDrvmd_oozeju = { + "md_oozeju", "md_ooze", NULL, NULL, "1995", + "The Ooze (Jpn, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozejuRomInfo, md_oozejuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Euro, Prototype, 19950728) +static struct BurnRomInfo md_oozep01RomDesc[] = { + { "ooze, the (euro) (prototype - jul 28, 1995).bin", 0x100000, 0x7cf868e7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep01) +STD_ROM_FN(md_oozep01) + +struct BurnDriver BurnDrvmd_oozep01 = { + "md_oozep01", "md_ooze", NULL, NULL, "1995", + "The Ooze (Euro, Prototype, 19950728)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep01RomInfo, md_oozep01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype, 19950615) +static struct BurnRomInfo md_oozep07RomDesc[] = { + { "ooze, the (prototype - jun 15, 1995).bin", 0x0e35ce, 0x921106fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep07) +STD_ROM_FN(md_oozep07) + +struct BurnDriver BurnDrvmd_oozep07 = { + "md_oozep07", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype, 19950615)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep07RomInfo, md_oozep07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype, 19950619) +static struct BurnRomInfo md_oozep06RomDesc[] = { + { "ooze, the (prototype - jun 19, 1995).bin", 0x100000, 0xfa39281d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep06) +STD_ROM_FN(md_oozep06) + +struct BurnDriver BurnDrvmd_oozep06 = { + "md_oozep06", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype, 19950619)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep06RomInfo, md_oozep06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype, 19950629-B) +static struct BurnRomInfo md_oozep03RomDesc[] = { + { "ooze, the (prototype - jun 29, 1995 - b).bin", 0x0ee456, 0xca93e93b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep03) +STD_ROM_FN(md_oozep03) + +struct BurnDriver BurnDrvmd_oozep03 = { + "md_oozep03", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype, 19950629-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep03RomInfo, md_oozep03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype, 19950629) +static struct BurnRomInfo md_oozep02RomDesc[] = { + { "ooze, the (prototype - jun 29, 1995).bin", 0x100000, 0x1776763b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep02) +STD_ROM_FN(md_oozep02) + +struct BurnDriver BurnDrvmd_oozep02 = { + "md_oozep02", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype, 19950629)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep02RomInfo, md_oozep02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype 104, 19950622) +static struct BurnRomInfo md_oozep05RomDesc[] = { + { "ooze, the (prototype 104 - jun 22, 1995).bin", 0x0ebea8, 0xce1f139f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep05) +STD_ROM_FN(md_oozep05) + +struct BurnDriver BurnDrvmd_oozep05 = { + "md_oozep05", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype 104, 19950622)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep05RomInfo, md_oozep05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ooze (Prototype 112, 19950626) +static struct BurnRomInfo md_oozep04RomDesc[] = { + { "ooze, the (prototype 112 - jun 26, 1995).bin", 0x0ec570, 0x70419442, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_oozep04) +STD_ROM_FN(md_oozep04) + +struct BurnDriver BurnDrvmd_oozep04 = { + "md_oozep04", "md_ooze", NULL, NULL, "1995", + "The Ooze (Prototype 112, 19950626)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_oozep04RomInfo, md_oozep04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Operation Europe - Path to Victory 1939-45 (USA) +static struct BurnRomInfo md_opeuropeRomDesc[] = { + { "operation europe - path to victory 1939-45 (usa).bin", 0x100000, 0xe7cba1d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_opeurope) +STD_ROM_FN(md_opeurope) + +struct BurnDriver BurnDrvmd_opeurope = { + "md_opeurope", NULL, NULL, NULL, "1994", + "Operation Europe - Path to Victory 1939-45 (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_opeuropeRomInfo, md_opeuropeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Europa Sensen (Jpn) +static struct BurnRomInfo md_europaRomDesc[] = { + { "europa sensen (jpn).bin", 0x100000, 0xb0416c60, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_europa) +STD_ROM_FN(md_europa) + +struct BurnDriver BurnDrvmd_europa = { + "md_europa", "md_opeurope", NULL, NULL, "1993", + "Europa Sensen (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_europaRomInfo, md_europaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Osomatsu-kun Hachamecha Gekijou (Jpn) +static struct BurnRomInfo md_osomatsuRomDesc[] = { + { "osomatsu-kun hachamecha gekijou (jpn).bin", 0x040000, 0x2453350c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_osomatsu) +STD_ROM_FN(md_osomatsu) + +struct BurnDriver BurnDrvmd_osomatsu = { + "md_osomatsu", NULL, NULL, NULL, "1988", + "Osomatsu-kun Hachamecha Gekijou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_osomatsuRomInfo, md_osomatsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ottifants (Euro) +static struct BurnRomInfo md_ottifaRomDesc[] = { + { "ottifants, the (euro).bin", 0x100000, 0x41ac8003, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ottifa) +STD_ROM_FN(md_ottifa) + +struct BurnDriver BurnDrvmd_ottifa = { + "md_ottifa", NULL, NULL, NULL, "1993", + "The Ottifants (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ottifaRomInfo, md_ottifaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ottifants (Ger, Prototype) +static struct BurnRomInfo md_ottifagRomDesc[] = { + { "ottifants, the (germany) (beta).bin", 0x100000, 0xc6e3dd23, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ottifag) +STD_ROM_FN(md_ottifag) + +struct BurnDriver BurnDrvmd_ottifag = { + "md_ottifag", "md_ottifa", NULL, NULL, "1993", + "The Ottifants (Ger, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ottifagRomInfo, md_ottifagRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Outlander (Euro) +static struct BurnRomInfo md_outlandrRomDesc[] = { + { "outlander (euro).bin", 0x100000, 0xfe6f2350, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outlandr) +STD_ROM_FN(md_outlandr) + +struct BurnDriver BurnDrvmd_outlandr = { + "md_outlandr", NULL, NULL, NULL, "1992", + "Outlander (Euro)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outlandrRomInfo, md_outlandrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Outlander (USA) +static struct BurnRomInfo md_outlandruRomDesc[] = { + { "outlander (usa).bin", 0x100000, 0xc5ba7bbf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outlandru) +STD_ROM_FN(md_outlandru) + +struct BurnDriver BurnDrvmd_outlandru = { + "md_outlandru", "md_outlandr", NULL, NULL, "1992", + "Outlander (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outlandruRomInfo, md_outlandruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun (Euro, USA) +static struct BurnRomInfo md_outrunRomDesc[] = { + { "outrun (euro, usa).bin", 0x100000, 0xfdd9a8d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outrun) +STD_ROM_FN(md_outrun) + +struct BurnDriver BurnDrvmd_outrun = { + "md_outrun", NULL, NULL, NULL, "1991", + "OutRun (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outrunRomInfo, md_outrunRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun (Jpn) +static struct BurnRomInfo md_outrunjRomDesc[] = { + { "outrun (jpn).bin", 0x100000, 0xee7d9f4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outrunj) +STD_ROM_FN(md_outrunj) + +struct BurnDriver BurnDrvmd_outrunj = { + "md_outrunj", "md_outrun", NULL, NULL, "1991", + "OutRun (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outrunjRomInfo, md_outrunjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun 2019 (Euro) +static struct BurnRomInfo md_outr2019RomDesc[] = { + { "mpr-15482.bin", 0x100000, 0x5cb3536a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outr2019) +STD_ROM_FN(md_outr2019) + +struct BurnDriver BurnDrvmd_outr2019 = { + "md_outr2019", NULL, NULL, NULL, "1993", + "OutRun 2019 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outr2019RomInfo, md_outr2019RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun 2019 (Jpn) +static struct BurnRomInfo md_outr2019jRomDesc[] = { + { "outrun 2019 (jpn).bin", 0x100000, 0x0eac7440, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outr2019j) +STD_ROM_FN(md_outr2019j) + +struct BurnDriver BurnDrvmd_outr2019j = { + "md_outr2019j", "md_outr2019", NULL, NULL, "1993", + "OutRun 2019 (Jpn)\0", NULL, "Sims", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outr2019jRomInfo, md_outr2019jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun 2019 (USA) +static struct BurnRomInfo md_outr2019uRomDesc[] = { + { "outrun 2019 (usa).bin", 0x100000, 0xe32e17e2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outr2019u) +STD_ROM_FN(md_outr2019u) + +struct BurnDriver BurnDrvmd_outr2019u = { + "md_outr2019u", "md_outr2019", NULL, NULL, "1993", + "OutRun 2019 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outr2019uRomInfo, md_outr2019uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRun 2019 (USA, Prototype) +static struct BurnRomInfo md_outr2019upRomDesc[] = { + { "outrun 2019 (usa) (beta).bin", 0x100000, 0xd2ecddfa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_outr2019up) +STD_ROM_FN(md_outr2019up) + +struct BurnDriver BurnDrvmd_outr2019up = { + "md_outr2019up", "md_outr2019", NULL, NULL, "1993", + "OutRun 2019 (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_outr2019upRomInfo, md_outr2019upRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Junker's High (Jpn, Prototype) +static struct BurnRomInfo md_junkerRomDesc[] = { + { "junker's high (jpn) (beta) (bad dump).bin", 0x100000, 0x23534949, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_junker) +STD_ROM_FN(md_junker) + +struct BurnDriver BurnDrvmd_junker = { + "md_junker", "md_outr2019", NULL, NULL, "199?", + "Junker's High (Jpn, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_junkerRomInfo, md_junkerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRunners (USA) +static struct BurnRomInfo md_orunnersRomDesc[] = { + { "outrunners (usa).bin", 0x200000, 0xede636b9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_orunners) +STD_ROM_FN(md_orunners) + +struct BurnDriver BurnDrvmd_orunners = { + "md_orunners", NULL, NULL, NULL, "1994", + "OutRunners (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_orunnersRomInfo, md_orunnersRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// OutRunners (Jpn) +static struct BurnRomInfo md_orunnersjRomDesc[] = { + { "outrunners (jpn).bin", 0x200000, 0xe164a09f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_orunnersj) +STD_ROM_FN(md_orunnersj) + +struct BurnDriver BurnDrvmd_orunnersj = { + "md_orunnersj", "md_orunners", NULL, NULL, "1994", + "OutRunners (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_orunnersjRomInfo, md_orunnersjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pac-Attack (USA) +static struct BurnRomInfo md_pacattckRomDesc[] = { + { "pac-attack (usa).bin", 0x040000, 0x5df382f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pacattck) +STD_ROM_FN(md_pacattck) + +struct BurnDriver BurnDrvmd_pacattck = { + "md_pacattck", NULL, NULL, NULL, "1993", + "Pac-Attack (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pacattckRomInfo, md_pacattckRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pac-Man 2 - The New Adventures (USA) +static struct BurnRomInfo md_pacmanRomDesc[] = { + { "pac-man 2 - the new adventures (usa).bin", 0x200000, 0xfe7a7ed1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pacman) +STD_ROM_FN(md_pacman) + +struct BurnDriver BurnDrvmd_pacman = { + "md_pacman", NULL, NULL, NULL, "1994", + "Pac-Man 2 - The New Adventures (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pacmanRomInfo, md_pacmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pac-Mania (Euro, USA) +static struct BurnRomInfo md_pacmaniaRomDesc[] = { + { "mpr-14392.bin", 0x040000, 0x74bba09b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pacmania) +STD_ROM_FN(md_pacmania) + +struct BurnDriver BurnDrvmd_pacmania = { + "md_pacmania", NULL, NULL, NULL, "1991", + "Pac-Mania (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pacmaniaRomInfo, md_pacmaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pachinko Kuunyan (Jpn) +static struct BurnRomInfo md_pachinkoRomDesc[] = { + { "pachinko kuunyan (jpn).bin", 0x100000, 0x9d137e7f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pachinko) +STD_ROM_FN(md_pachinko) + +struct BurnDriver BurnDrvmd_pachinko = { + "md_pachinko", NULL, NULL, NULL, "1992", + "Pachinko Kuunyan (Jpn)\0", NULL, "Soft Vision International", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pachinkoRomInfo, md_pachinkoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pacific Theater of Operations (USA) +static struct BurnRomInfo md_pacificRomDesc[] = { + { "pacific theater of operations (usa).bin", 0x100000, 0xd9d4c6e2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pacific) +STD_ROM_FN(md_pacific) + +struct BurnDriver BurnDrvmd_pacific = { + "md_pacific", NULL, NULL, NULL, "1993", + "Pacific Theater of Operations (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pacificRomInfo, md_pacificRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teitoku no Ketsudan (Jpn) +static struct BurnRomInfo md_teitokuRomDesc[] = { + { "teitoku no ketsudan (jpn).bin", 0x100000, 0x9b08e4e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_teitoku) +STD_ROM_FN(md_teitoku) + +struct BurnDriver BurnDrvmd_teitoku = { + "md_teitoku", "md_pacific", NULL, NULL, "1992", + "Teitoku no Ketsudan (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_teitokuRomInfo, md_teitokuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Paddle Fighter (Jpn, SegaNet) +static struct BurnRomInfo md_paddleRomDesc[] = { + { "paddle fighter (jpn) (sn).bin", 0x040000, 0x3d8147e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_paddle) +STD_ROM_FN(md_paddle) + +struct BurnDriver BurnDrvmd_paddle = { + "md_paddle", NULL, NULL, NULL, "1991", + "Paddle Fighter (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_paddleRomInfo, md_paddleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Paddle Fighter (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_paddlegnkRomDesc[] = { + { "paddle fighter (jpn) (gnk).bin", 0x040000, 0xebef05a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_paddlegnk) +STD_ROM_FN(md_paddlegnk) + +struct BurnDriver BurnDrvmd_paddlegnk = { + "md_paddlegnk", "md_paddle", NULL, NULL, "1991", + "Paddle Fighter (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_paddlegnkRomInfo, md_paddlegnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Pagemaster (Euro) +static struct BurnRomInfo md_pagemastRomDesc[] = { + { "pagemaster, the (euro).bin", 0x200000, 0x79a180e2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pagemast) +STD_ROM_FN(md_pagemast) + +struct BurnDriver BurnDrvmd_pagemast = { + "md_pagemast", NULL, NULL, NULL, "1994", + "The Pagemaster (Euro)\0", NULL, "Fox Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pagemastRomInfo, md_pagemastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Pagemaster (USA) +static struct BurnRomInfo md_pagemastuRomDesc[] = { + { "pagemaster, the (usa).bin", 0x200000, 0x75a96d4e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pagemastu) +STD_ROM_FN(md_pagemastu) + +struct BurnDriver BurnDrvmd_pagemastu = { + "md_pagemastu", "md_pagemast", NULL, NULL, "1994", + "The Pagemaster (USA)\0", NULL, "Fox Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pagemastuRomInfo, md_pagemastuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Pagemaster (USA, Prototype) +static struct BurnRomInfo md_pagemastupRomDesc[] = { + { "pagemaster, the (usa) (beta).bin", 0x200000, 0x29895e3d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pagemastup) +STD_ROM_FN(md_pagemastup) + +struct BurnDriver BurnDrvmd_pagemastup = { + "md_pagemastup", "md_pagemast", NULL, NULL, "1994", + "The Pagemaster (USA, Prototype)\0", NULL, "Fox Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pagemastupRomInfo, md_pagemastupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Panorama Cotton (Jpn) +static struct BurnRomInfo md_pcottonRomDesc[] = { + { "panorama cotton (jpn).bin", 0x280000, 0x9e57d92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pcotton) +STD_ROM_FN(md_pcotton) + +struct BurnDriver BurnDrvmd_pcotton = { + "md_pcotton", NULL, NULL, NULL, "1994", + "Panorama Cotton (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pcottonRomInfo, md_pcottonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Paperboy (Euro, USA) +static struct BurnRomInfo md_paperboyRomDesc[] = { + { "paperboy (euro, usa).bin", 0x080000, 0x0a44819b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_paperboy) +STD_ROM_FN(md_paperboy) + +struct BurnDriver BurnDrvmd_paperboy = { + "md_paperboy", NULL, NULL, NULL, "1991", + "Paperboy (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_paperboyRomInfo, md_paperboyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Paperboy (Jpn) +static struct BurnRomInfo md_paperboyjRomDesc[] = { + { "mpr-14774.bin", 0x080000, 0xe14250ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_paperboyj) +STD_ROM_FN(md_paperboyj) + +struct BurnDriver BurnDrvmd_paperboyj = { + "md_paperboyj", "md_paperboy", NULL, NULL, "1992", + "Paperboy (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_paperboyjRomInfo, md_paperboyjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Paperboy 2 (Euro, USA) +static struct BurnRomInfo md_paperby2RomDesc[] = { + { "paperboy 2 (euro, usa).bin", 0x100000, 0x1de28bb1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_paperby2) +STD_ROM_FN(md_paperby2) + +struct BurnDriver BurnDrvmd_paperby2 = { + "md_paperby2", NULL, NULL, NULL, "1992", + "Paperboy 2 (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_paperby2RomInfo, md_paperby2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Party Quiz Mega Q (Jpn) +static struct BurnRomInfo md_partyqRomDesc[] = { + { "party quiz mega q (jpn).bin", 0x100000, 0x9d4b447a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_partyq) +STD_ROM_FN(md_partyq) + +struct BurnDriver BurnDrvmd_partyq = { + "md_partyq", NULL, NULL, NULL, "1993", + "Party Quiz Mega Q (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_partyqRomInfo, md_partyqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pebble Beach Golf Links (Euro) +static struct BurnRomInfo md_pebbleRomDesc[] = { + { "pebble beach golf links (euro).bin", 0x200000, 0x6cfc7297, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pebble) +STD_ROM_FN(md_pebble) + +struct BurnDriver BurnDrvmd_pebble = { + "md_pebble", NULL, NULL, NULL, "1993", + "Pebble Beach Golf Links (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pebbleRomInfo, md_pebbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pebble Beach Golf Links (USA) +static struct BurnRomInfo md_pebbleuRomDesc[] = { + { "pebble beach golf links (usa).bin", 0x200000, 0x95823c43, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pebbleu) +STD_ROM_FN(md_pebbleu) + +struct BurnDriver BurnDrvmd_pebbleu = { + "md_pebbleu", "md_pebble", NULL, NULL, "1993", + "Pebble Beach Golf Links (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pebbleuRomInfo, md_pebbleuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// New 3D Golf Simulation Pebble Beach no Hatou (Jpn) +static struct BurnRomInfo md_n3dgpebbRomDesc[] = { + { "new 3d golf simulation pebble beach no hatou (jpn).bin", 0x180000, 0x96ed2e5d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_n3dgpebb) +STD_ROM_FN(md_n3dgpebb) + +struct BurnDriver BurnDrvmd_n3dgpebb = { + "md_n3dgpebb", "md_pebble", NULL, NULL, "1993", + "New 3D Golf Simulation Pebble Beach no Hatou (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_n3dgpebbRomInfo, md_n3dgpebbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pelé's World Tournament Soccer (Euro, USA) +static struct BurnRomInfo md_pele2RomDesc[] = { + { "pele ii - world tournament soccer (euro, usa).bin", 0x200000, 0x05a486e9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pele2) +STD_ROM_FN(md_pele2) + +struct BurnDriver BurnDrvmd_pele2 = { + "md_pele2", NULL, NULL, NULL, "1994", + "Pele's World Tournament Soccer (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + L"Pel\u00e9's World Tournament Soccer (Euro, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pele2RomInfo, md_pele2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pelé! (Euro, USA) +static struct BurnRomInfo md_peleRomDesc[] = { + { "pele! (euro, usa).bin", 0x100000, 0x5a8abe51, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pele) +STD_ROM_FN(md_pele) + +struct BurnDriver BurnDrvmd_pele = { + "md_pele", NULL, NULL, NULL, "1993", + "Pele! (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + L"Pel\u00e9! (Euro, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_peleRomInfo, md_peleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pepenga Pengo (Jpn) +static struct BurnRomInfo md_ppengoRomDesc[] = { + { "pepenga pengo (jpn).bin", 0x100000, 0xd1e2324b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppengo) +STD_ROM_FN(md_ppengo) + +struct BurnDriver BurnDrvmd_ppengo = { + "md_ppengo", NULL, NULL, NULL, "1995", + "Pepenga Pengo (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppengoRomInfo, md_ppengoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pete Sampras Tennis (Euro, USA, J-Cart, Alt) +static struct BurnRomInfo md_psampras1RomDesc[] = { + { "mdstee_13.bin", 0x100000, 0xaa8b19bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psampras1) +STD_ROM_FN(md_psampras1) + +struct BurnDriver BurnDrvmd_psampras1 = { + "md_psampras1", "md_psampras", NULL, NULL, "1994", + "Pete Sampras Tennis (Euro, USA, J-Cart, Alt)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_psampras1RomInfo, md_psampras1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pete Sampras Tennis (Euro, USA, J-Cart, Alt 2) +static struct BurnRomInfo md_psampras2RomDesc[] = { + { "pete sampras tennis (euro, usa) (j-cart).bin", 0x100000, 0x9ef5bbd1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psampras2) +STD_ROM_FN(md_psampras2) + +struct BurnDriver BurnDrvmd_psampras2 = { + "md_psampras2", "md_psampras", NULL, NULL, "1994", + "Pete Sampras Tennis (Euro, USA, J-Cart, Alt 2)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_psampras2RomInfo, md_psampras2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA European Tour (Euro, USA) +static struct BurnRomInfo md_pgaeuroRomDesc[] = { + { "euro03.bin", 0x100000, 0x8ca45acd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pgaeuro) +STD_ROM_FN(md_pgaeuro) + +struct BurnDriver BurnDrvmd_pgaeuro = { + "md_pgaeuro", NULL, NULL, NULL, "1994", + "PGA European Tour (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pgaeuroRomInfo, md_pgaeuroRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour 96 (Euro, USA) +static struct BurnRomInfo md_pga96RomDesc[] = { + { "pga9601.bin", 0x200000, 0x9698bbde, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga96) +STD_ROM_FN(md_pga96) + +struct BurnDriver BurnDrvmd_pga96 = { + "md_pga96", NULL, NULL, NULL, "1995", + "PGA Tour 96 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pga96RomInfo, md_pga96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf (Euro, USA, v1.2) +static struct BurnRomInfo md_pgaRomDesc[] = { + { "pga09.bin", 0x080000, 0xc1f0b4e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga) +STD_ROM_FN(md_pga) + +struct BurnDriver BurnDrvmd_pga = { + "md_pga", NULL, NULL, NULL, "1991", + "PGA Tour Golf (Euro, USA, v1.2)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pgaRomInfo, md_pgaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf (Euro, USA, v1.1) +static struct BurnRomInfo md_pgaaRomDesc[] = { + { "pga tour golf (euro, usa) (v1.1).bin", 0x080000, 0x0489ff8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pgaa) +STD_ROM_FN(md_pgaa) + +struct BurnDriver BurnDrvmd_pgaa = { + "md_pgaa", "md_pga", NULL, NULL, "1991", + "PGA Tour Golf (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pgaaRomInfo, md_pgaaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf II (Euro, USA, v1.1) +static struct BurnRomInfo md_pga2RomDesc[] = { + { "pga tour golf ii (euro, usa) (v1.1).bin", 0x100000, 0xe82b8606, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga2) +STD_ROM_FN(md_pga2) + +struct BurnDriver BurnDrvmd_pga2 = { + "md_pga2", NULL, NULL, NULL, "1992", + "PGA Tour Golf II (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pga2RomInfo, md_pga2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf II (Jpn) +static struct BurnRomInfo md_pga2jRomDesc[] = { + { "pga tour golf ii (jpn).bin", 0x100000, 0xc05b7a4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga2j) +STD_ROM_FN(md_pga2j) + +struct BurnDriver BurnDrvmd_pga2j = { + "md_pga2j", "md_pga2", NULL, NULL, "1993", + "PGA Tour Golf II (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pga2jRomInfo, md_pga2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// PGA Tour Golf III (Euro, USA) +static struct BurnRomInfo md_pga3RomDesc[] = { + { "pga tour golf iii (euro, usa).bin", 0x200000, 0xaeb3f65f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pga3) +STD_ROM_FN(md_pga3) + +struct BurnDriver BurnDrvmd_pga3 = { + "md_pga3", NULL, NULL, NULL, "1994", + "PGA Tour Golf III (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pga3RomInfo, md_pga3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II (Euro, USA) +static struct BurnRomInfo md_pstar2aRomDesc[] = { + { "phantasy star ii (euro, usa).bin", 0x0c0000, 0x0d07d0ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar2a) +STD_ROM_FN(md_pstar2a) + +struct BurnDriver BurnDrvmd_pstar2a = { + "md_pstar2a", "md_pstar2", NULL, NULL, "1989", + "Phantasy Star II (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar2aRomInfo, md_pstar2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II (Bra) +static struct BurnRomInfo md_pstar2brRomDesc[] = { + { "phantasy star ii (bra).bin", 0x0c0000, 0xe6688b66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar2br) +STD_ROM_FN(md_pstar2br) + +struct BurnDriver BurnDrvmd_pstar2br = { + "md_pstar2br", "md_pstar2", NULL, NULL, "199?", + "Phantasy Star II (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar2brRomInfo, md_pstar2brRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Kaerazaru Toki no Owari ni (Jpn) +static struct BurnRomInfo md_pstar2jRomDesc[] = { + { "mpr-12140+mpr-12181+mpr-12182.bin", 0x0c0000, 0xbec8eb5a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar2j) +STD_ROM_FN(md_pstar2j) + +struct BurnDriver BurnDrvmd_pstar2j = { + "md_pstar2j", "md_pstar2", NULL, NULL, "1989", + "Phantasy Star II - Kaerazaru Toki no Owari ni (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar2jRomInfo, md_pstar2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Amia's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2aaRomDesc[] = { + { "phantasy star ii - amia's adventure (jpn) (sn).bin", 0x040000, 0xa3a724aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2aa) +STD_ROM_FN(md_ps2aa) + +struct BurnDriver BurnDrvmd_ps2aa = { + "md_ps2aa", NULL, NULL, NULL, "1991", + "Phantasy Star II - Amia's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2aaRomInfo, md_ps2aaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Anne's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2abRomDesc[] = { + { "phantasy star ii - anne's adventure (jpn) (sn).bin", 0x040000, 0xfafa5b6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ab) +STD_ROM_FN(md_ps2ab) + +struct BurnDriver BurnDrvmd_ps2ab = { + "md_ps2ab", NULL, NULL, NULL, "1991", + "Phantasy Star II - Anne's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2abRomInfo, md_ps2abRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Huey's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2acRomDesc[] = { + { "phantasy star ii - huey's adventure (jpn) (sn).bin", 0x040000, 0x1a076f83, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ac) +STD_ROM_FN(md_ps2ac) + +struct BurnDriver BurnDrvmd_ps2ac = { + "md_ps2ac", NULL, NULL, NULL, "1991", + "Phantasy Star II - Huey's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2acRomInfo, md_ps2acRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Kinds's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2adRomDesc[] = { + { "phantasy star ii - kinds's adventure (jpn) (sn).bin", 0x040000, 0xc334f308, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ad) +STD_ROM_FN(md_ps2ad) + +struct BurnDriver BurnDrvmd_ps2ad = { + "md_ps2ad", NULL, NULL, NULL, "1991", + "Phantasy Star II - Kinds's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2adRomInfo, md_ps2adRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Nei's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2aeRomDesc[] = { + { "phantasy star ii - nei's adventure (jpn) (sn).bin", 0x040000, 0x3d9ad465, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ae) +STD_ROM_FN(md_ps2ae) + +struct BurnDriver BurnDrvmd_ps2ae = { + "md_ps2ae", NULL, NULL, NULL, "1991", + "Phantasy Star II - Nei's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2aeRomInfo, md_ps2aeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Rudger's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2afRomDesc[] = { + { "phantasy star ii - rudger's adventure (jpn) (sn).bin", 0x040000, 0x6b5916d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2af) +STD_ROM_FN(md_ps2af) + +struct BurnDriver BurnDrvmd_ps2af = { + "md_ps2af", NULL, NULL, NULL, "1991", + "Phantasy Star II - Rudger's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2afRomInfo, md_ps2afRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Shilka's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2agRomDesc[] = { + { "phantasy star ii - shilka's adventure (jpn) (sn).bin", 0x040000, 0x1f83beb2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ag) +STD_ROM_FN(md_ps2ag) + +struct BurnDriver BurnDrvmd_ps2ag = { + "md_ps2ag", NULL, NULL, NULL, "1991", + "Phantasy Star II - Shilka's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2agRomInfo, md_ps2agRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star II - Yushis's Adventure (Jpn, SegaNet) +static struct BurnRomInfo md_ps2ahRomDesc[] = { + { "phantasy star ii - yushis's adventure (jpn) (sn).bin", 0x040000, 0xd40c76d6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ps2ah) +STD_ROM_FN(md_ps2ah) + +struct BurnDriver BurnDrvmd_ps2ah = { + "md_ps2ah", NULL, NULL, NULL, "1991", + "Phantasy Star II - Yushis's Adventure (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ps2ahRomInfo, md_ps2ahRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star III - Generations of Doom (Euro, USA, Kor) +static struct BurnRomInfo md_pstar3RomDesc[] = { + { "phantasy star iii - generations of doom (euro, usa, kor).bin", 0x0c0000, 0xc6b42b0f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar3) +STD_ROM_FN(md_pstar3) + +struct BurnDriver BurnDrvmd_pstar3 = { + "md_pstar3", NULL, NULL, NULL, "1990", + "Phantasy Star III - Generations of Doom (Euro, USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar3RomInfo, md_pstar3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star III - Generations of Doom (Bra) +static struct BurnRomInfo md_pstar3brRomDesc[] = { + { "phantasy star iii - generations of doom (bra).bin", 0x0c0000, 0x2e9b4c23, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar3br) +STD_ROM_FN(md_pstar3br) + +struct BurnDriver BurnDrvmd_pstar3br = { + "md_pstar3br", "md_pstar3", NULL, NULL, "1998", + "Phantasy Star III - Generations of Doom (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar3brRomInfo, md_pstar3brRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star III - Toki no Keishousha (Jpn) +static struct BurnRomInfo md_pstar3jRomDesc[] = { + { "phantasy star iii - toki no keishousha (jpn).bin", 0x0c0000, 0x6c48c06f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar3j) +STD_ROM_FN(md_pstar3j) + +struct BurnDriver BurnDrvmd_pstar3j = { + "md_pstar3j", "md_pstar3", NULL, NULL, "1990", + "Phantasy Star III - Toki no Keishousha (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar3jRomInfo, md_pstar3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (USA) +static struct BurnRomInfo md_pstar4RomDesc[] = { + { "phantasy star iv (usa).bin", 0x300000, 0xfe236442, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4) +STD_ROM_FN(md_pstar4) + +struct BurnDriver BurnDrvmd_pstar4 = { + "md_pstar4", NULL, NULL, NULL, "1994", + "Phantasy Star IV (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4RomInfo, md_pstar4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star - Sennenki no Owari ni (Jpn) +static struct BurnRomInfo md_pstar4jRomDesc[] = { + { "phantasy star - sennenki no owari ni (jpn).bin", 0x300000, 0xf0bfad42, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4j) +STD_ROM_FN(md_pstar4j) + +struct BurnDriver BurnDrvmd_pstar4j = { + "md_pstar4j", "md_pstar4", NULL, NULL, "1993", + "Phantasy Star - Sennenki no Owari ni (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4jRomInfo, md_pstar4jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (Prototype, 19940815) +static struct BurnRomInfo md_pstar4p3RomDesc[] = { + { "phantasy star iv (prototype - aug 15, 1994).bin", 0x300000, 0x60137f25, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4p3) +STD_ROM_FN(md_pstar4p3) + +struct BurnDriver BurnDrvmd_pstar4p3 = { + "md_pstar4p3", "md_pstar4", NULL, NULL, "1994", + "Phantasy Star IV (Prototype, 19940815)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4p3RomInfo, md_pstar4p3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (Prototype, 19940608) +static struct BurnRomInfo md_pstar4p4RomDesc[] = { + { "phantasy star iv (prototype - jun 08, 1994).bin", 0x300000, 0xdc2e1c0a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4p4) +STD_ROM_FN(md_pstar4p4) + +struct BurnDriver BurnDrvmd_pstar4p4 = { + "md_pstar4p4", "md_pstar4", NULL, NULL, "1994", + "Phantasy Star IV (Prototype, 19940608)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4p4RomInfo, md_pstar4p4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (Prototype, 19940530) +static struct BurnRomInfo md_pstar4p5RomDesc[] = { + { "phantasy star iv (prototype - may 30, 1994).bin", 0x300000, 0xb32b17e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4p5) +STD_ROM_FN(md_pstar4p5) + +struct BurnDriver BurnDrvmd_pstar4p5 = { + "md_pstar4p5", "md_pstar4", NULL, NULL, "1994", + "Phantasy Star IV (Prototype, 19940530)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4p5RomInfo, md_pstar4p5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (Prototype, 19941107) +static struct BurnRomInfo md_pstar4p1RomDesc[] = { + { "phantasy star iv (prototype - nov 07, 1994).bin", 0x300000, 0xbda29cdf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4p1) +STD_ROM_FN(md_pstar4p1) + +struct BurnDriver BurnDrvmd_pstar4p1 = { + "md_pstar4p1", "md_pstar4", NULL, NULL, "1994", + "Phantasy Star IV (Prototype, 19941107)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4p1RomInfo, md_pstar4p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantasy Star IV (Prototype, 19941027) +static struct BurnRomInfo md_pstar4p2RomDesc[] = { + { "phantasy star iv (prototype - oct 27, 1994).bin", 0x300000, 0x12a2590a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pstar4p2) +STD_ROM_FN(md_pstar4p2) + +struct BurnDriver BurnDrvmd_pstar4p2 = { + "md_pstar4p2", "md_pstar4", NULL, NULL, "1994", + "Phantasy Star IV (Prototype, 19941027)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pstar4p2RomInfo, md_pstar4p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantom 2040 (Euro) +static struct BurnRomInfo md_phantomRomDesc[] = { + { "phantom 2040 (euro).bin", 0x200000, 0xb024882e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_phantom) +STD_ROM_FN(md_phantom) + +struct BurnDriver BurnDrvmd_phantom = { + "md_phantom", NULL, NULL, NULL, "1995", + "Phantom 2040 (Euro)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_phantomRomInfo, md_phantomRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phantom 2040 (USA) +static struct BurnRomInfo md_phantomuRomDesc[] = { + { "phantom 2040 (usa).bin", 0x200000, 0xfb36e1f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_phantomu) +STD_ROM_FN(md_phantomu) + +struct BurnDriver BurnDrvmd_phantomu = { + "md_phantomu", "md_phantom", NULL, NULL, "1995", + "Phantom 2040 (USA)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_phantomuRomInfo, md_phantomuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phelios (Euro) +static struct BurnRomInfo md_pheliosRomDesc[] = { + { "phelios (euro).bin", 0x080000, 0x13abc2b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_phelios) +STD_ROM_FN(md_phelios) + +struct BurnDriver BurnDrvmd_phelios = { + "md_phelios", NULL, NULL, NULL, "1990", + "Phelios (Euro)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pheliosRomInfo, md_pheliosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phelios (Jpn) +static struct BurnRomInfo md_pheliosjRomDesc[] = { + { "phelios (jpn).bin", 0x080000, 0x94596174, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pheliosj) +STD_ROM_FN(md_pheliosj) + +struct BurnDriver BurnDrvmd_pheliosj = { + "md_pheliosj", "md_phelios", NULL, NULL, "1990", + "Phelios (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pheliosjRomInfo, md_pheliosjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Phelios (USA) +static struct BurnRomInfo md_pheliosuRomDesc[] = { + { "phelios (usa).bin", 0x080000, 0x11c79320, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pheliosu) +STD_ROM_FN(md_pheliosu) + +struct BurnDriver BurnDrvmd_pheliosu = { + "md_pheliosu", "md_phelios", NULL, NULL, "1990", + "Phelios (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pheliosuRomInfo, md_pheliosuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pink Goes to Hollywood (USA, Prototype) +static struct BurnRomInfo md_pinkpRomDesc[] = { + { "pink goes to hollywood (usa) (beta).bin", 0x100000, 0x56087cff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pinkp) +STD_ROM_FN(md_pinkp) + +struct BurnDriver BurnDrvmd_pinkp = { + "md_pinkp", "md_pink", NULL, NULL, "1993", + "Pink Goes to Hollywood (USA, Prototype)\0", NULL, "TecMagik", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pinkpRomInfo, md_pinkpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pinocchio (Euro) +static struct BurnRomInfo md_pinoccRomDesc[] = { + { "pinocchio (euro).bin", 0x300000, 0x28014bdc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pinocc) +STD_ROM_FN(md_pinocc) + +struct BurnDriver BurnDrvmd_pinocc = { + "md_pinocc", NULL, NULL, NULL, "1995", + "Pinocchio (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pinoccRomInfo, md_pinoccRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pinocchio (USA) +static struct BurnRomInfo md_pinoccuRomDesc[] = { + { "pinocchio (usa).bin", 0x300000, 0xcd4128d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pinoccu) +STD_ROM_FN(md_pinoccu) + +struct BurnDriver BurnDrvmd_pinoccu = { + "md_pinoccu", "md_pinocc", NULL, NULL, "1996", + "Pinocchio (USA)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pinoccuRomInfo, md_pinoccuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Pirates of Dark Water (USA, January 1994) +static struct BurnRomInfo md_pirateRomDesc[] = { + { "pirates of dark water, the (usa) (january 1994).bin", 0x200000, 0x0c45b9f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pirate) +STD_ROM_FN(md_pirate) + +struct BurnDriver BurnDrvmd_pirate = { + "md_pirate", NULL, NULL, NULL, "1994", + "The Pirates of Dark Water (USA, January 1994)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pirateRomInfo, md_pirateRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Pirates of Dark Water (Euro, USA, May 1994) +static struct BurnRomInfo md_pirate1RomDesc[] = { + { "pirates of dark water, the (euro, usa) (may 1994).bin", 0x200000, 0x0a62de34, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pirate1) +STD_ROM_FN(md_pirate1) + +struct BurnDriver BurnDrvmd_pirate1 = { + "md_pirate1", "md_pirate", NULL, NULL, "1994", + "The Pirates of Dark Water (Euro, USA, May 1994)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pirate1RomInfo, md_pirate1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pirates! Gold (USA) +static struct BurnRomInfo md_pgoldRomDesc[] = { + { "pirates! gold (usa).bin", 0x100000, 0xed50e75c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pgold) +STD_ROM_FN(md_pgold) + +struct BurnDriver BurnDrvmd_pgold = { + "md_pgold", NULL, NULL, NULL, "1993", + "Pirates! Gold (USA)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pgoldRomInfo, md_pgoldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pirates! Gold (USA, Prototype) +static struct BurnRomInfo md_pgoldpRomDesc[] = { + { "pirates! gold (usa) (beta).bin", 0x100000, 0x0a525641, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pgoldp) +STD_ROM_FN(md_pgoldp) + +struct BurnDriver BurnDrvmd_pgoldp = { + "md_pgoldp", "md_pgold", NULL, NULL, "1993", + "Pirates! Gold (USA, Prototype)\0", NULL, "Microprose", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pgoldpRomInfo, md_pgoldpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pit-Fighter (World, Rev. A) +static struct BurnRomInfo md_pitfightRomDesc[] = { + { "mpr-14320a.bin", 0x100000, 0xd48a8b02, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pitfight) +STD_ROM_FN(md_pitfight) + +struct BurnDriver BurnDrvmd_pitfight = { + "md_pitfight", NULL, NULL, NULL, "1991", + "Pit-Fighter (World, Rev. A)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pitfightRomInfo, md_pitfightRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pit-Fighter (World) +static struct BurnRomInfo md_pitfight1RomDesc[] = { + { "pit-fighter (world).bin", 0x100000, 0x1e0e0831, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pitfight1) +STD_ROM_FN(md_pitfight1) + +struct BurnDriver BurnDrvmd_pitfight1 = { + "md_pitfight1", "md_pitfight", NULL, NULL, "1991", + "Pit-Fighter (World)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pitfight1RomInfo, md_pitfight1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pitfall - The Mayan Adventure (Euro) +static struct BurnRomInfo md_pitfallRomDesc[] = { + { "pitfall - the mayan adventure (euro).bin", 0x200000, 0xc9198e19, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pitfall) +STD_ROM_FN(md_pitfall) + +struct BurnDriver BurnDrvmd_pitfall = { + "md_pitfall", NULL, NULL, NULL, "1994", + "Pitfall - The Mayan Adventure (Euro)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pitfallRomInfo, md_pitfallRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pitfall - The Mayan Adventure (USA) +static struct BurnRomInfo md_pitfalluRomDesc[] = { + { "pitfall - the mayan adventure (usa).bin", 0x200000, 0xf917e34f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pitfallu) +STD_ROM_FN(md_pitfallu) + +struct BurnDriver BurnDrvmd_pitfallu = { + "md_pitfallu", "md_pitfall", NULL, NULL, "1994", + "Pitfall - The Mayan Adventure (USA)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pitfalluRomInfo, md_pitfalluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pocahontas (Euro) +static struct BurnRomInfo md_pocahontRomDesc[] = { + { "mpr-18875.bin", 0x400000, 0x165e7987, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pocahont) +STD_ROM_FN(md_pocahont) + +struct BurnDriver BurnDrvmd_pocahont = { + "md_pocahont", NULL, NULL, NULL, "1996", + "Pocahontas (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pocahontRomInfo, md_pocahontRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pocahontas (USA) +static struct BurnRomInfo md_pocahontuRomDesc[] = { + { "pocahontas (usa).bin", 0x400000, 0x6ddd1c6d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pocahontu) +STD_ROM_FN(md_pocahontu) + +struct BurnDriver BurnDrvmd_pocahontu = { + "md_pocahontu", "md_pocahont", NULL, NULL, "1996", + "Pocahontas (USA)\0", NULL, "Disney Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pocahontuRomInfo, md_pocahontuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pokemon Crazy Drummer +static struct BurnRomInfo md_pokecdRomDesc[] = { + { "pokemon crazy drummer (unl).bin", 0x200000, 0x8838a25d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pokecd) +STD_ROM_FN(md_pokecd) + +struct BurnDriver BurnDrvmd_pokecd = { + "md_pokecd", NULL, NULL, NULL, "199?", + "Pokemon Crazy Drummer\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pokecdRomInfo, md_pokecdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Populous (Euro) +static struct BurnRomInfo md_populousRomDesc[] = { + { "populous (euro).bin", 0x080000, 0x83d56f64, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_populous) +STD_ROM_FN(md_populous) + +struct BurnDriver BurnDrvmd_populous = { + "md_populous", NULL, NULL, NULL, "1991", + "Populous (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_populousRomInfo, md_populousRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Populous (Jpn) +static struct BurnRomInfo md_populousjRomDesc[] = { + { "populous (jpn).bin", 0x080000, 0x97c26818, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_populousj) +STD_ROM_FN(md_populousj) + +struct BurnDriver BurnDrvmd_populousj = { + "md_populousj", "md_populous", NULL, NULL, "1991", + "Populous (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_populousjRomInfo, md_populousjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Populous (USA) +static struct BurnRomInfo md_populousuRomDesc[] = { + { "populous (usa).bin", 0x080000, 0xbd74b31e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_populousu) +STD_ROM_FN(md_populousu) + +struct BurnDriver BurnDrvmd_populousu = { + "md_populousu", "md_populous", NULL, NULL, "1991", + "Populous (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_populousuRomInfo, md_populousuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Power Drive (Euro) +static struct BurnRomInfo md_powerdrvRomDesc[] = { + { "power drive (euro).bin", 0x100000, 0x8c00ad61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_powerdrv) +STD_ROM_FN(md_powerdrv) + +struct BurnDriver BurnDrvmd_powerdrv = { + "md_powerdrv", NULL, NULL, NULL, "1994", + "Power Drive (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_powerdrvRomInfo, md_powerdrvRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Power Monger (Euro, USA) +static struct BurnRomInfo md_pmongerRomDesc[] = { + { "pm14.bin", 0x100000, 0xfb599b86, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pmonger) +STD_ROM_FN(md_pmonger) + +struct BurnDriver BurnDrvmd_pmonger = { + "md_pmonger", NULL, NULL, NULL, "1993", + "Power Monger (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pmongerRomInfo, md_pmongerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Power Monger (Jpn, Kor) +static struct BurnRomInfo md_pmongerjRomDesc[] = { + { "power monger (jpn, kor).bin", 0x100000, 0x553289b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pmongerj) +STD_ROM_FN(md_pmongerj) + +struct BurnDriver BurnDrvmd_pmongerj = { + "md_pmongerj", "md_pmonger", NULL, NULL, "1993", + "Power Monger (Jpn, Kor)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_pmongerjRomInfo, md_pmongerjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Powerball (USA) +static struct BurnRomInfo md_powrballRomDesc[] = { + { "powerball (usa).bin", 0x080000, 0x7adf232f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_powrball) +STD_ROM_FN(md_powrball) + +struct BurnDriver BurnDrvmd_powrball = { + "md_powrball", NULL, NULL, NULL, "1991", + "Powerball (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_powrballRomInfo, md_powrballRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wrestleball (Jpn) +static struct BurnRomInfo md_wrstballRomDesc[] = { + { "wrestleball (jpn).bin", 0x080000, 0xd563e07f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wrstball) +STD_ROM_FN(md_wrstball) + +struct BurnDriver BurnDrvmd_wrstball = { + "md_wrstball", "md_powrball", NULL, NULL, "1991", + "Wrestleball (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wrstballRomInfo, md_wrstballRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Predator 2 (Euro, USA) +static struct BurnRomInfo md_predatr2RomDesc[] = { + { "predator 2 (euro, usa).bin", 0x100000, 0xbdba113e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_predatr2) +STD_ROM_FN(md_predatr2) + +struct BurnDriver BurnDrvmd_predatr2 = { + "md_predatr2", NULL, NULL, NULL, "1992", + "Predator 2 (Euro, USA)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_predatr2RomInfo, md_predatr2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Premier Manager (Euro) +static struct BurnRomInfo md_premiermRomDesc[] = { + { "mpr-18473.bin", 0x100000, 0x303b889f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_premierm) +STD_ROM_FN(md_premierm) + +struct BurnDriver BurnDrvmd_premierm = { + "md_premierm", NULL, NULL, NULL, "1995", + "Premier Manager (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_premiermRomInfo, md_premiermRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Premier Manager 97 (Euro) +static struct BurnRomInfo md_premrm97RomDesc[] = { + { "premier manager 97 (euro).bin", 0x100000, 0xfccbf69b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_premrm97) +STD_ROM_FN(md_premrm97) + +struct BurnDriver BurnDrvmd_premrm97 = { + "md_premrm97", NULL, NULL, NULL, "1996", + "Premier Manager 97 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_premrm97RomInfo, md_premrm97RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Primal Rage (Euro, USA) +static struct BurnRomInfo md_primalRomDesc[] = { + { "primal rage (euro, usa).bin", 0x300000, 0x2884c6d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_primal) +STD_ROM_FN(md_primal) + +struct BurnDriver BurnDrvmd_primal = { + "md_primal", NULL, NULL, NULL, "1995", + "Primal Rage (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_primalRomInfo, md_primalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prime Time NFL Starring Deion Sanders (USA) +static struct BurnRomInfo md_primetimRomDesc[] = { + { "prime time nfl starring deion sanders (usa).bin", 0x200000, 0x5aa53cbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_primetim) +STD_ROM_FN(md_primetim) + +struct BurnDriver BurnDrvmd_primetim = { + "md_primetim", NULL, NULL, NULL, "1995", + "Prime Time NFL Starring Deion Sanders (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_primetimRomInfo, md_primetimRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prince of Persia (Euro) +static struct BurnRomInfo md_ppersiaRomDesc[] = { + { "prince of persia (euro).bin", 0x100000, 0x61de6fe0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppersia) +STD_ROM_FN(md_ppersia) + +struct BurnDriver BurnDrvmd_ppersia = { + "md_ppersia", NULL, NULL, NULL, "1993", + "Prince of Persia (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppersiaRomInfo, md_ppersiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prince of Persia (Prototype) +static struct BurnRomInfo md_ppersiapRomDesc[] = { + { "prince of persia (beta).bin", 0x100000, 0x505314b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppersiap) +STD_ROM_FN(md_ppersiap) + +struct BurnDriver BurnDrvmd_ppersiap = { + "md_ppersiap", "md_ppersia", NULL, NULL, "1993", + "Prince of Persia (Prototype)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppersiapRomInfo, md_ppersiapRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prince of Persia (Prototype, Earlier) +static struct BurnRomInfo md_ppersiap1RomDesc[] = { + { "prince of persia (beta) (earlier).bin", 0x040000, 0x425e6a87, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppersiap1) +STD_ROM_FN(md_ppersiap1) + +struct BurnDriver BurnDrvmd_ppersiap1 = { + "md_ppersiap1", "md_ppersia", NULL, NULL, "1993", + "Prince of Persia (Prototype, Earlier)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppersiap1RomInfo, md_ppersiap1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prince of Persia (USA) +static struct BurnRomInfo md_ppersiauRomDesc[] = { + { "prince of persia (usa).bin", 0x100000, 0x13c181a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppersiau) +STD_ROM_FN(md_ppersiau) + +struct BurnDriver BurnDrvmd_ppersiau = { + "md_ppersiau", "md_ppersia", NULL, NULL, "1993", + "Prince of Persia (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppersiauRomInfo, md_ppersiauRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Prince of Persia 2 - The Shadow and the Flame (Euro, Prototype) +static struct BurnRomInfo md_ppersia2RomDesc[] = { + { "prince of persia 2 - the shadow and the flame (euro) (prototype).bin", 0x200000, 0x3ab44d46, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ppersia2) +STD_ROM_FN(md_ppersia2) + +struct BurnDriver BurnDrvmd_ppersia2 = { + "md_ppersia2", NULL, NULL, NULL, "199?", + "Prince of Persia 2 - The Shadow and the Flame (Euro, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ppersia2RomInfo, md_ppersia2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Quarterback (USA) +static struct BurnRomInfo md_proquartRomDesc[] = { + { "pro quarterback (usa).bin", 0x100000, 0xcc8b2b69, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_proquart) +STD_ROM_FN(md_proquart) + +struct BurnDriver BurnDrvmd_proquart = { + "md_proquart", NULL, NULL, NULL, "1992", + "Pro Quarterback (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_proquartRomInfo, md_proquartRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Yakyuu Super League '91 (Jpn) +static struct BurnRomInfo md_proyakyuRomDesc[] = { + { "pro yakyuu super league '91 (jpn).bin", 0x080000, 0xa948ab7e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_proyakyu) +STD_ROM_FN(md_proyakyu) + +struct BurnDriver BurnDrvmd_proyakyu = { + "md_proyakyu", NULL, NULL, NULL, "1991", + "Pro Yakyuu Super League '91 (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_proyakyuRomInfo, md_proyakyuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Probotector (Euro) +static struct BurnRomInfo md_probotRomDesc[] = { + { "probotector (euro).bin", 0x200000, 0xbc597d48, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_probot) +STD_ROM_FN(md_probot) + +struct BurnDriver BurnDrvmd_probot = { + "md_probot", NULL, NULL, NULL, "1994", + "Probotector (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_probotRomInfo, md_probotRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Contra - Hard Corps (USA, Kor) +static struct BurnRomInfo md_contraRomDesc[] = { + { "contra - hard corps (usa, kor).bin", 0x200000, 0xc579f45e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_contra) +STD_ROM_FN(md_contra) + +struct BurnDriver BurnDrvmd_contra = { + "md_contra", "md_probot", NULL, NULL, "1994", + "Contra - Hard Corps (USA, Kor)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_contraRomInfo, md_contraRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Contra - The Hard Corps (Jpn) +static struct BurnRomInfo md_contrajRomDesc[] = { + { "contra - the hard corps (jpn).bin", 0x200000, 0x2ab26380, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_contraj) +STD_ROM_FN(md_contraj) + +struct BurnDriver BurnDrvmd_contraj = { + "md_contraj", "md_probot", NULL, NULL, "1994", + "Contra - The Hard Corps (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_contrajRomInfo, md_contrajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Psy-O-Blade (Jpn) +static struct BurnRomInfo md_psyobladRomDesc[] = { + { "psy-o-blade (jpn).bin", 0x0a0000, 0x8ba7e6c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psyoblad) +STD_ROM_FN(md_psyoblad) + +struct BurnDriver BurnDrvmd_psyoblad = { + "md_psyoblad", NULL, NULL, NULL, "1990", + "Psy-O-Blade (Jpn)\0", NULL, "Sigma", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_psyobladRomInfo, md_psyobladRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Psycho Pinball (Euro, 199410) +static struct BurnRomInfo md_psychoRomDesc[] = { + { "psycho pinball (euro) (october 1994).bin", 0x180000, 0xd704784b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psycho) +STD_ROM_FN(md_psycho) + +struct BurnDriver BurnDrvmd_psycho = { + "md_psycho", NULL, NULL, NULL, "1994", + "Psycho Pinball (Euro, 199410)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_psychoRomInfo, md_psychoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Psycho Pinball (Euro, 199409) +static struct BurnRomInfo md_psycho1RomDesc[] = { + { "psycho pinball (euro) (september 1994).bin", 0x180000, 0x11e9c3f2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_psycho1) +STD_ROM_FN(md_psycho1) + +struct BurnDriver BurnDrvmd_psycho1 = { + "md_psycho1", "md_psycho", NULL, NULL, "1994", + "Psycho Pinball (Euro, 199409)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_psycho1RomInfo, md_psycho1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puggsy (Euro) +static struct BurnRomInfo md_puggsyRomDesc[] = { + { "puggsy (euro).bin", 0x100000, 0x5d5c9ade, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puggsy) +STD_ROM_FN(md_puggsy) + +struct BurnDriver BurnDrvmd_puggsy = { + "md_puggsy", NULL, NULL, NULL, "1993", + "Puggsy (Euro)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puggsyRomInfo, md_puggsyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puggsy (Prototype) +static struct BurnRomInfo md_puggsypRomDesc[] = { + { "puggsy (beta).bin", 0x100000, 0x37fa4877, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puggsyp) +STD_ROM_FN(md_puggsyp) + +struct BurnDriver BurnDrvmd_puggsyp = { + "md_puggsyp", "md_puggsy", NULL, NULL, "1993", + "Puggsy (Prototype)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puggsypRomInfo, md_puggsypRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puggsy (USA) +static struct BurnRomInfo md_puggsyuRomDesc[] = { + { "puggsy (usa).bin", 0x100000, 0x70132168, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puggsyu) +STD_ROM_FN(md_puggsyu) + +struct BurnDriver BurnDrvmd_puggsyu = { + "md_puggsyu", "md_puggsy", NULL, NULL, "1993", + "Puggsy (USA)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puggsyuRomInfo, md_puggsyuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pulseman (Jpn) +static struct BurnRomInfo md_pulsemanRomDesc[] = { + { "pulseman (jpn).bin", 0x200000, 0x138a104e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pulseman) +STD_ROM_FN(md_pulseman) + +struct BurnDriver BurnDrvmd_pulseman = { + "md_pulseman", NULL, NULL, NULL, "1994", + "Pulseman (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pulsemanRomInfo, md_pulsemanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Punisher (Euro) +static struct BurnRomInfo md_punisherRomDesc[] = { + { "punisher, the (euro).bin", 0x200000, 0x729edd17, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_punisher) +STD_ROM_FN(md_punisher) + +struct BurnDriver BurnDrvmd_punisher = { + "md_punisher", NULL, NULL, NULL, "1994", + "The Punisher (Euro)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_punisherRomInfo, md_punisherRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Punisher (USA) +static struct BurnRomInfo md_punisheruRomDesc[] = { + { "punisher, the (usa).bin", 0x200000, 0x695cd8b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_punisheru) +STD_ROM_FN(md_punisheru) + +struct BurnDriver BurnDrvmd_punisheru = { + "md_punisheru", "md_punisher", NULL, NULL, "1994", + "The Punisher (USA)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_punisheruRomInfo, md_punisheruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Putter Golf (Jpn, SegaNet) +static struct BurnRomInfo md_putterRomDesc[] = { + { "putter golf (jpn) (sn).bin", 0x040000, 0x20f168a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_putter) +STD_ROM_FN(md_putter) + +struct BurnDriver BurnDrvmd_putter = { + "md_putter", NULL, NULL, NULL, "1991", + "Putter Golf (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_putterRomInfo, md_putterRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Putter Golf (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_puttergnkRomDesc[] = { + { "putter golf (jpn) (gnk).bin", 0x040000, 0xa6557faa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puttergnk) +STD_ROM_FN(md_puttergnk) + +struct BurnDriver BurnDrvmd_puttergnk = { + "md_puttergnk", "md_putter", NULL, NULL, "1991", + "Putter Golf (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puttergnkRomInfo, md_puttergnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puyo Puyo (Jpn) +static struct BurnRomInfo md_puyoRomDesc[] = { + { "puyo puyo (jpn).bin", 0x080000, 0x7f26614e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puyo) +STD_ROM_FN(md_puyo) + +struct BurnDriver BurnDrvmd_puyo = { + "md_puyo", NULL, NULL, NULL, "1992", + "Puyo Puyo (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puyoRomInfo, md_puyoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puyo Puyo 2 (Jpn, v1.1) +static struct BurnRomInfo md_puyo2RomDesc[] = { + { "puyo puyo 2 (jpn) (v1.1).bin", 0x200000, 0x25b7b2aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puyo2) +STD_ROM_FN(md_puyo2) + +struct BurnDriver BurnDrvmd_puyo2 = { + "md_puyo2", NULL, NULL, NULL, "1994", + "Puyo Puyo 2 (Jpn, v1.1)\0", NULL, "Compile", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puyo2RomInfo, md_puyo2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puyo Puyo 2 (Jpn) +static struct BurnRomInfo md_puyo2aRomDesc[] = { + { "puyo puyo 2 (jpn).bin", 0x200000, 0x51ad7797, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_puyo2a) +STD_ROM_FN(md_puyo2a) + +struct BurnDriver BurnDrvmd_puyo2a = { + "md_puyo2a", "md_puyo2", NULL, NULL, "1994", + "Puyo Puyo 2 (Jpn)\0", NULL, "Compile", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_puyo2aRomInfo, md_puyo2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puzzle & Action - Ichidant-R (Jpn) +static struct BurnRomInfo md_ichirRomDesc[] = { + { "puzzle & action - ichidanto-r (jpn).bin", 0x200000, 0x7bdec762, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ichir) +STD_ROM_FN(md_ichir) + +struct BurnDriver BurnDrvmd_ichir = { + "md_ichir", NULL, NULL, NULL, "1995", + "Puzzle & Action - Ichidant-R (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ichirRomInfo, md_ichirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Puzzle & Action - Tant-R (Jpn) +static struct BurnRomInfo md_tantrRomDesc[] = { + { "puzzle & action - tanto-r (jpn).bin", 0x200000, 0xd2d2d437, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tantr) +STD_ROM_FN(md_tantr) + +struct BurnDriver BurnDrvmd_tantr = { + "md_tantr", NULL, NULL, NULL, "1994", + "Puzzle & Action - Tant-R (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tantrRomInfo, md_tantrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pyramid Magic (Jpn, SegaNet) +static struct BurnRomInfo md_pyramidRomDesc[] = { + { "pyramid magic (jpn) (sn).bin", 0x040000, 0x306d839e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pyramid) +STD_ROM_FN(md_pyramid) + +struct BurnDriver BurnDrvmd_pyramid = { + "md_pyramid", NULL, NULL, NULL, "1991", + "Pyramid Magic (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pyramidRomInfo, md_pyramidRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pyramid Magic (Jpn, Game no Kandume MegaCD Rip) +static struct BurnRomInfo md_pyramidgnkRomDesc[] = { + { "pyramid magic (jpn) (gnk).bin", 0x040000, 0xb20272ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pyramidgnk) +STD_ROM_FN(md_pyramidgnk) + +struct BurnDriver BurnDrvmd_pyramidgnk = { + "md_pyramidgnk", "md_pyramid", NULL, NULL, "1991", + "Pyramid Magic (Jpn, Game no Kandume MegaCD Rip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pyramidgnkRomInfo, md_pyramidgnkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pyramid Magic II (Jpn, SegaNet) +static struct BurnRomInfo md_pyramid2RomDesc[] = { + { "pyramid magic ii (jpn) (sn).bin", 0x040000, 0xc9ddac72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pyramid2) +STD_ROM_FN(md_pyramid2) + +struct BurnDriver BurnDrvmd_pyramid2 = { + "md_pyramid2", NULL, NULL, NULL, "1991", + "Pyramid Magic II (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pyramid2RomInfo, md_pyramid2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pyramid Magic III (Jpn, SegaNet) +static struct BurnRomInfo md_pyramid3RomDesc[] = { + { "pyramid magic iii (jpn) (sn).bin", 0x040000, 0x8329820a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pyramid3) +STD_ROM_FN(md_pyramid3) + +struct BurnDriver BurnDrvmd_pyramid3 = { + "md_pyramid3", NULL, NULL, NULL, "1991", + "Pyramid Magic III (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pyramid3RomInfo, md_pyramid3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pyramid Magic Special (Jpn, SegaNet) +static struct BurnRomInfo md_pyramidsRomDesc[] = { + { "pyramid magic special (jpn) (sn).bin", 0x040000, 0x153a3afa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pyramids) +STD_ROM_FN(md_pyramids) + +struct BurnDriver BurnDrvmd_pyramids = { + "md_pyramids", NULL, NULL, NULL, "1991", + "Pyramid Magic Special (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pyramidsRomInfo, md_pyramidsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// QuackShot Starring Donald Duck ~ QuackShot - Guruzia Ou no Hihou (World) +static struct BurnRomInfo md_quackshtRomDesc[] = { + { "mpr-14371.bin", 0x080000, 0x5dd28dd7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP_CONTINUE_040000_100000 | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_quacksht) +STD_ROM_FN(md_quacksht) + +struct BurnDriver BurnDrvmd_quacksht = { + "md_quacksht", NULL, NULL, NULL, "1991", + "QuackShot Starring Donald Duck ~ QuackShot - Guruzia Ou no Hihou (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_quackshtRomInfo, md_quackshtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// QuackShot Starring Donald Duck ~ QuackShot - Guruzia Ou no Hihou (World, Alt) +static struct BurnRomInfo md_quacksht1RomDesc[] = { + { "quackshot starring donald duck -- quackshot - guruzia ou no hihou (world) (alt).bin", 0x080000, 0x88c8dd94, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_quacksht1) +STD_ROM_FN(md_quacksht1) + +struct BurnDriver BurnDrvmd_quacksht1 = { + "md_quacksht1", "md_quacksht", NULL, NULL, "1991", + "QuackShot Starring Donald Duck ~ QuackShot - Guruzia Ou no Hihou (World, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_quacksht1RomInfo, md_quacksht1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Quad Challenge (USA) +static struct BurnRomInfo md_quadchalRomDesc[] = { + { "quad challenge (usa).bin", 0x080000, 0x74736a80, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_quadchal) +STD_ROM_FN(md_quadchal) + +struct BurnDriver BurnDrvmd_quadchal = { + "md_quadchal", NULL, NULL, NULL, "1991", + "Quad Challenge (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_quadchalRomInfo, md_quadchalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MegaTrax (Jpn) +static struct BurnRomInfo md_megatraxRomDesc[] = { + { "megatrax (jpn).bin", 0x080000, 0xa0837741, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megatrax) +STD_ROM_FN(md_megatrax) + +struct BurnDriver BurnDrvmd_megatrax = { + "md_megatrax", "md_quadchal", NULL, NULL, "1991", + "MegaTrax (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megatraxRomInfo, md_megatraxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Queen of Poker Club (Tw) +static struct BurnRomInfo md_qpokerRomDesc[] = { + { "poker club (sachen).bin", 0x100000, 0xae28d9eb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_qpoker) +STD_ROM_FN(md_qpoker) + +struct BurnDriver BurnDrvmd_qpoker = { + "md_qpoker", NULL, NULL, NULL, "199?", + "Queen of Poker Club (Tw)\0", NULL, "Sachen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_qpokerRomInfo, md_qpokerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball '93 (USA) +static struct BurnRomInfo md_rbi93RomDesc[] = { + { "r.b.i. baseball '93 (usa).bin", 0x100000, 0xbeafce84, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi93) +STD_ROM_FN(md_rbi93) + +struct BurnDriver BurnDrvmd_rbi93 = { + "md_rbi93", NULL, NULL, NULL, "1993", + "R.B.I. Baseball '93 (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi93RomInfo, md_rbi93RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball '94 (Euro, USA) +static struct BurnRomInfo md_rbi94RomDesc[] = { + { "r.b.i. baseball '94 (euro, usa).bin", 0x200000, 0x4eb4d5e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi94) +STD_ROM_FN(md_rbi94) + +struct BurnDriver BurnDrvmd_rbi94 = { + "md_rbi94", NULL, NULL, NULL, "1994", + "R.B.I. Baseball '94 (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi94RomInfo, md_rbi94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball 3 (USA) +static struct BurnRomInfo md_rbi3RomDesc[] = { + { "r.b.i. baseball 3 (usa).bin", 0x080000, 0x4840348c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi3) +STD_ROM_FN(md_rbi3) + +struct BurnDriver BurnDrvmd_rbi3 = { + "md_rbi3", NULL, NULL, NULL, "1991", + "R.B.I. Baseball 3 (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi3RomInfo, md_rbi3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball 4 (USA) +static struct BurnRomInfo md_rbi4RomDesc[] = { + { "r.b.i. baseball 4 (usa).bin", 0x100000, 0xfecf9b94, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi4) +STD_ROM_FN(md_rbi4) + +struct BurnDriver BurnDrvmd_rbi4 = { + "md_rbi4", NULL, NULL, NULL, "1992", + "R.B.I. Baseball 4 (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi4RomInfo, md_rbi4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball 4 (Prototype) +static struct BurnRomInfo md_rbi4pRomDesc[] = { + { "r.b.i. baseball 4 (beta).bin", 0x100000, 0xf7420278, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi4p) +STD_ROM_FN(md_rbi4p) + +struct BurnDriver BurnDrvmd_rbi4p = { + "md_rbi4p", "md_rbi4", NULL, NULL, "1992", + "R.B.I. Baseball 4 (Prototype)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi4pRomInfo, md_rbi4pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// R.B.I. Baseball 4 (Jpn) +static struct BurnRomInfo md_rbi4jRomDesc[] = { + { "r.b.i. baseball 4 (jpn).bin", 0x100000, 0x8f4e1005, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rbi4j) +STD_ROM_FN(md_rbi4j) + +struct BurnDriver BurnDrvmd_rbi4j = { + "md_rbi4j", "md_rbi4", NULL, NULL, "1992", + "R.B.I. Baseball 4 (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rbi4jRomInfo, md_rbi4jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Race Drivin' (USA) +static struct BurnRomInfo md_racedrivRomDesc[] = { + { "race drivin' (usa).bin", 0x080000, 0xd737cf3d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_racedriv) +STD_ROM_FN(md_racedriv) + +struct BurnDriver BurnDrvmd_racedriv = { + "md_racedriv", NULL, NULL, NULL, "1993", + "Race Drivin' (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_racedrivRomInfo, md_racedrivRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Radical Rex (Euro) +static struct BurnRomInfo md_radrexRomDesc[] = { + { "radical rex (euro).bin", 0x100000, 0xd02d3282, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_radrex) +STD_ROM_FN(md_radrex) + +struct BurnDriver BurnDrvmd_radrex = { + "md_radrex", NULL, NULL, NULL, "1994", + "Radical Rex (Euro)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_radrexRomInfo, md_radrexRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Radical Rex (USA) +static struct BurnRomInfo md_radrexuRomDesc[] = { + { "radical rex (usa).bin", 0x100000, 0x2e6eec7e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_radrexu) +STD_ROM_FN(md_radrexu) + +struct BurnDriver BurnDrvmd_radrexu = { + "md_radrexu", "md_radrex", NULL, NULL, "1994", + "Radical Rex (USA)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_radrexuRomInfo, md_radrexuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Raiden Trad (USA) ~ Raiden Densetsu (Jpn) +static struct BurnRomInfo md_raidenRomDesc[] = { + { "raiden trad -- raiden densetsu (usa, jpn).bin", 0x100000, 0xf839a811, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_raiden) +STD_ROM_FN(md_raiden) + +struct BurnDriver BurnDrvmd_raiden = { + "md_raiden", NULL, NULL, NULL, "1991", + "Raiden Trad (USA) ~ Raiden Densetsu (Jpn)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_raidenRomInfo, md_raidenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rainbow Islands Extra (Jpn) +static struct BurnRomInfo md_rainbowRomDesc[] = { + { "rainbow islands extra (jpn).bin", 0x080000, 0xc74dcb35, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rainbow) +STD_ROM_FN(md_rainbow) + +struct BurnDriver BurnDrvmd_rainbow = { + "md_rainbow", NULL, NULL, NULL, "1990", + "Rainbow Islands Extra (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rainbowRomInfo, md_rainbowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rambo III (World, v1.1) +static struct BurnRomInfo md_rambo3RomDesc[] = { + { "rambo iii (world) (v1.1).bin", 0x040000, 0x4d47a647, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rambo3) +STD_ROM_FN(md_rambo3) + +struct BurnDriver BurnDrvmd_rambo3 = { + "md_rambo3", NULL, NULL, NULL, "1989", + "Rambo III (World, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rambo3RomInfo, md_rambo3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rambo III (World) +static struct BurnRomInfo md_rambo3aRomDesc[] = { + { "mpr-12651.bin", 0x040000, 0x2232f03d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rambo3a) +STD_ROM_FN(md_rambo3a) + +struct BurnDriver BurnDrvmd_rambo3a = { + "md_rambo3a", "md_rambo3", NULL, NULL, "1989", + "Rambo III (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rambo3aRomInfo, md_rambo3aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rampart (USA) +static struct BurnRomInfo md_rampartRomDesc[] = { + { "rampart (usa).bin", 0x080000, 0x9c4dd057, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rampart) +STD_ROM_FN(md_rampart) + +struct BurnDriver BurnDrvmd_rampart = { + "md_rampart", NULL, NULL, NULL, "1991", + "Rampart (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rampartRomInfo, md_rampartRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rampart (Jpn, Kor) +static struct BurnRomInfo md_rampartjRomDesc[] = { + { "rampart (jpn, kor).bin", 0x080000, 0x16ead64c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rampartj) +STD_ROM_FN(md_rampartj) + +struct BurnDriver BurnDrvmd_rampartj = { + "md_rampartj", "md_rampart", NULL, NULL, "1992", + "Rampart (Jpn, Kor)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rampartjRomInfo, md_rampartjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ranger-X (Euro) +static struct BurnRomInfo md_rangerxRomDesc[] = { + { "ranger-x (euro).bin", 0x100000, 0xb8c04804, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rangerx) +STD_ROM_FN(md_rangerx) + +struct BurnDriver BurnDrvmd_rangerx = { + "md_rangerx", NULL, NULL, NULL, "1993", + "Ranger-X (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rangerxRomInfo, md_rangerxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ranger-X (USA) +static struct BurnRomInfo md_rangerxuRomDesc[] = { + { "ranger-x (usa).bin", 0x100000, 0x55915915, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rangerxu) +STD_ROM_FN(md_rangerxu) + +struct BurnDriver BurnDrvmd_rangerxu = { + "md_rangerxu", "md_rangerx", NULL, NULL, "1993", + "Ranger-X (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rangerxuRomInfo, md_rangerxuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ex-Ranza (Jpn) +static struct BurnRomInfo md_exranzaRomDesc[] = { + { "mpr-15585.bin", 0x100000, 0x349bb68d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exranza) +STD_ROM_FN(md_exranza) + +struct BurnDriver BurnDrvmd_exranza = { + "md_exranza", "md_rangerx", NULL, NULL, "1993", + "Ex-Ranza (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exranzaRomInfo, md_exranzaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ex-Ranza (Jpn, Prototype) +static struct BurnRomInfo md_exranzapRomDesc[] = { + { "ex-ranza (jpn) (beta).bin", 0x100000, 0xc642fdf4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_exranzap) +STD_ROM_FN(md_exranzap) + +struct BurnDriver BurnDrvmd_exranzap = { + "md_exranzap", "md_rangerx", NULL, NULL, "1993", + "Ex-Ranza (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_exranzapRomInfo, md_exranzapRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ransei no Hasha (Jpn) +static struct BurnRomInfo md_ranseiRomDesc[] = { + { "ransei no hasha (jpn).bin", 0x100000, 0xa9a0083d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ransei) +STD_ROM_FN(md_ransei) + +struct BurnDriver BurnDrvmd_ransei = { + "md_ransei", NULL, NULL, NULL, "1991", + "Ransei no Hasha (Jpn)\0", NULL, "Asmik Ace", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ranseiRomInfo, md_ranseiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rastan Saga II (USA) +static struct BurnRomInfo md_rastans2RomDesc[] = { + { "rastan saga ii (usa).bin", 0x080000, 0xc7ee8965, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rastans2) +STD_ROM_FN(md_rastans2) + +struct BurnDriver BurnDrvmd_rastans2 = { + "md_rastans2", NULL, NULL, NULL, "1990", + "Rastan Saga II (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rastans2RomInfo, md_rastans2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rastan Saga II (Jpn) +static struct BurnRomInfo md_rastans2jRomDesc[] = { + { "rastan saga ii (jpn).bin", 0x080000, 0xebacfb5a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rastans2j) +STD_ROM_FN(md_rastans2j) + +struct BurnDriver BurnDrvmd_rastans2j = { + "md_rastans2j", "md_rastans2", NULL, NULL, "1990", + "Rastan Saga II (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rastans2jRomInfo, md_rastans2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Red Zone (Euro, USA) +static struct BurnRomInfo md_redzoneRomDesc[] = { + { "red zone (euro, usa).bin", 0x200000, 0x56512ee5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_redzone) +STD_ROM_FN(md_redzone) + +struct BurnDriver BurnDrvmd_redzone = { + "md_redzone", NULL, NULL, NULL, "1994", + "Red Zone (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_redzoneRomInfo, md_redzoneRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ren & Stimpy Show Presents Stimpy's Invention (Euro) +static struct BurnRomInfo md_renstimRomDesc[] = { + { "ren & stimpy show presents stimpy's invention, the (euro).bin", 0x100000, 0xc276c220, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_renstim) +STD_ROM_FN(md_renstim) + +struct BurnDriver BurnDrvmd_renstim = { + "md_renstim", NULL, NULL, NULL, "1993", + "The Ren & Stimpy Show Presents Stimpy's Invention (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_renstimRomInfo, md_renstimRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ren & Stimpy Show Presents Stimpy's Invention (USA) +static struct BurnRomInfo md_renstimuRomDesc[] = { + { "ren & stimpy show presents stimpy's invention, the (usa).bin", 0x100000, 0xd9503ba5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_renstimu) +STD_ROM_FN(md_renstimu) + +struct BurnDriver BurnDrvmd_renstimu = { + "md_renstimu", "md_renstim", NULL, NULL, "1993", + "The Ren & Stimpy Show Presents Stimpy's Invention (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_renstimuRomInfo, md_renstimuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Ren & Stimpy Show Presents Stimpy's Invention (USA, Prototype) +static struct BurnRomInfo md_renstimupRomDesc[] = { + { "ren & stimpy show presents stimpy's invention, the (usa) (beta).bin", 0x100000, 0xfcb86336, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_renstimup) +STD_ROM_FN(md_renstimup) + +struct BurnDriver BurnDrvmd_renstimup = { + "md_renstimup", "md_renstim", NULL, NULL, "1993", + "The Ren & Stimpy Show Presents Stimpy's Invention (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_renstimupRomInfo, md_renstimupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rent a Hero (Jpn) +static struct BurnRomInfo md_rentheroRomDesc[] = { + { "mpr-14187.bin", 0x100000, 0x2e515f82, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_renthero) +STD_ROM_FN(md_renthero) + +struct BurnDriver BurnDrvmd_renthero = { + "md_renthero", NULL, NULL, NULL, "1991", + "Rent a Hero (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_rentheroRomInfo, md_rentheroRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Resq (Euro, Prototype) +static struct BurnRomInfo md_resqRomDesc[] = { + { "resq (euro) (prototype).bin", 0x100000, 0x558e35e0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_resq) +STD_ROM_FN(md_resq) + +struct BurnDriver BurnDrvmd_resq = { + "md_resq", NULL, NULL, NULL, "199?", + "Resq (Euro, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_resqRomInfo, md_resqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Revenge of Shinobi (Euro, USA, Rev. B) +static struct BurnRomInfo md_revshinRomDesc[] = { + { "mpr-12930b.bin", 0x080000, 0x4d35ebe4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_revshin) +STD_ROM_FN(md_revshin) + +struct BurnDriver BurnDrvmd_revshin = { + "md_revshin", NULL, NULL, NULL, "1989", + "The Revenge of Shinobi (Euro, USA, Rev. B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_revshinRomInfo, md_revshinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Revenge of Shinobi (Euro, USA, Rev. A) +static struct BurnRomInfo md_revshin1RomDesc[] = { + { "revenge of shinobi, the (euro, usa) (rev a).bin", 0x080000, 0xfe91ab7e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_revshin1) +STD_ROM_FN(md_revshin1) + +struct BurnDriver BurnDrvmd_revshin1 = { + "md_revshin1", "md_revshin", NULL, NULL, "1989", + "The Revenge of Shinobi (Euro, USA, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_revshin1RomInfo, md_revshin1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Revenge of Shinobi (Euro, USA) +static struct BurnRomInfo md_revshin2RomDesc[] = { + { "revenge of shinobi, the (euro, usa).bin", 0x080000, 0x05f27994, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_revshin2) +STD_ROM_FN(md_revshin2) + +struct BurnDriver BurnDrvmd_revshin2 = { + "md_revshin2", "md_revshin", NULL, NULL, "1989", + "The Revenge of Shinobi (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_revshin2RomInfo, md_revshin2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Super Shinobi (Jpn) +static struct BurnRomInfo md_supshinRomDesc[] = { + { "mpr-12675.bin", 0x080000, 0x5c7e5ea6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supshin) +STD_ROM_FN(md_supshin) + +struct BurnDriver BurnDrvmd_supshin = { + "md_supshin", "md_revshin", NULL, NULL, "1989", + "The Super Shinobi (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supshinRomInfo, md_supshinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Revolution X (Euro, USA) +static struct BurnRomInfo md_revxRomDesc[] = { + { "revolution x (euro, usa).bin", 0x400000, 0x5fb0c5d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_revx) +STD_ROM_FN(md_revx) + +struct BurnDriver BurnDrvmd_revx = { + "md_revx", NULL, NULL, NULL, "1995", + "Revolution X (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_revxRomInfo, md_revxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's BusyTown (USA) +static struct BurnRomInfo md_rsbtRomDesc[] = { + { "richard scarry's busytown (usa).bin", 0x200000, 0x7bb60c3f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbt) +STD_ROM_FN(md_rsbt) + +struct BurnDriver BurnDrvmd_rsbt = { + "md_rsbt", NULL, NULL, NULL, "1994", + "Richard Scarry's BusyTown (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtRomInfo, md_rsbtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940809) +static struct BurnRomInfo md_rsbtp6RomDesc[] = { + { "richard scarry's busytown (prototype - aug 09, 1994).bin", 0x1fecec, 0xc48cbc30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp6) +STD_ROM_FN(md_rsbtp6) + +struct BurnDriver BurnDrvmd_rsbtp6 = { + "md_rsbtp6", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940809)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp6RomInfo, md_rsbtp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940815) +static struct BurnRomInfo md_rsbtp5RomDesc[] = { + { "richard scarry's busytown (prototype - aug 15, 1994).bin", 0x200000, 0x650ed917, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp5) +STD_ROM_FN(md_rsbtp5) + +struct BurnDriver BurnDrvmd_rsbtp5 = { + "md_rsbtp5", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940815)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp5RomInfo, md_rsbtp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940816-B) +static struct BurnRomInfo md_rsbtp4RomDesc[] = { + { "richard scarry's busytown (prototype - aug 16, 1994 - b).bin", 0x200000, 0x760cff62, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp4) +STD_ROM_FN(md_rsbtp4) + +struct BurnDriver BurnDrvmd_rsbtp4 = { + "md_rsbtp4", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940816-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp4RomInfo, md_rsbtp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940817) +static struct BurnRomInfo md_rsbtp3RomDesc[] = { + { "richard scarry's busytown (prototype - aug 17, 1994).bin", 0x1ffaa4, 0x3b9c3f4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp3) +STD_ROM_FN(md_rsbtp3) + +struct BurnDriver BurnDrvmd_rsbtp3 = { + "md_rsbtp3", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940817)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp3RomInfo, md_rsbtp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940825) +static struct BurnRomInfo md_rsbtp2RomDesc[] = { + { "richard scarry's busytown (prototype - aug 25, 1994).bin", 0x200000, 0xa0c013ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp2) +STD_ROM_FN(md_rsbtp2) + +struct BurnDriver BurnDrvmd_rsbtp2 = { + "md_rsbtp2", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940825)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp2RomInfo, md_rsbtp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940826) +static struct BurnRomInfo md_rsbtp1RomDesc[] = { + { "richard scarry's busytown (prototype - aug 26, 1994).bin", 0x200000, 0x1ad270f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp1) +STD_ROM_FN(md_rsbtp1) + +struct BurnDriver BurnDrvmd_rsbtp1 = { + "md_rsbtp1", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940826)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp1RomInfo, md_rsbtp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Richard Scarry's Busytown (Prototype, 19940721) +static struct BurnRomInfo md_rsbtp7RomDesc[] = { + { "richard scarry's busytown (prototype - jul 21, 1994).bin", 0x1f3008, 0x1e92d6ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rsbtp7) +STD_ROM_FN(md_rsbtp7) + +struct BurnDriver BurnDrvmd_rsbtp7 = { + "md_rsbtp7", "md_rsbt", NULL, NULL, "1994", + "Richard Scarry's Busytown (Prototype, 19940721)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rsbtp7RomInfo, md_rsbtp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Riddle Wired (Jpn, SegaNet) +static struct BurnRomInfo md_riddleRomDesc[] = { + { "riddle wired (jpn) (sn).bin", 0x040000, 0xfae3d720, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_riddle) +STD_ROM_FN(md_riddle) + +struct BurnDriver BurnDrvmd_riddle = { + "md_riddle", NULL, NULL, NULL, "1991", + "Riddle Wired (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_riddleRomInfo, md_riddleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rings of Power (Euro, USA) +static struct BurnRomInfo md_ringspowRomDesc[] = { + { "rin09.bin", 0x100000, 0x41fcc497, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ringspow) +STD_ROM_FN(md_ringspow) + +struct BurnDriver BurnDrvmd_ringspow = { + "md_ringspow", NULL, NULL, NULL, "1991", + "Rings of Power (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA, GBF_MISC, 0, + MegadriveGetZipName, md_ringspowRomInfo, md_ringspowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Risk (USA) +static struct BurnRomInfo md_riskRomDesc[] = { + { "risk (usa).bin", 0x080000, 0x80416d0d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_risk) +STD_ROM_FN(md_risk) + +struct BurnDriver BurnDrvmd_risk = { + "md_risk", NULL, NULL, NULL, "1994", + "Risk (USA)\0", NULL, "Parker Brothers", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_riskRomInfo, md_riskRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Risky Woods (Euro, USA) +static struct BurnRomInfo md_riskywRomDesc[] = { + { "risky woods (euro, usa).bin", 0x100000, 0xd975e93c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_riskyw) +STD_ROM_FN(md_riskyw) + +struct BurnDriver BurnDrvmd_riskyw = { + "md_riskyw", NULL, NULL, NULL, "1992", + "Risky Woods (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_riskywRomInfo, md_riskywRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Jashin Draxos (Jpn, Kor) +static struct BurnRomInfo md_draxosRomDesc[] = { + { "jashin draxos (jpn, kor).bin", 0x100000, 0x1ea07af2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_draxos) +STD_ROM_FN(md_draxos) + +struct BurnDriver BurnDrvmd_draxos = { + "md_draxos", "md_riskyw", NULL, NULL, "1993", + "Jashin Draxos (Jpn, Kor)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_draxosRomInfo, md_draxosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Euro, USA, 199409) +static struct BurnRomInfo md_ristarRomDesc[] = { + { "ristar (euro, usa) (september 1994).bin", 0x200000, 0x6511aa61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristar) +STD_ROM_FN(md_ristar) + +struct BurnDriver BurnDrvmd_ristar = { + "md_ristar", NULL, NULL, NULL, "1994", + "Ristar (Euro, USA, 199409)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarRomInfo, md_ristarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Euro, USA, 199408) +static struct BurnRomInfo md_ristar1RomDesc[] = { + { "ristar (euro, usa) (august 1994).bin", 0x200000, 0x9700139b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristar1) +STD_ROM_FN(md_ristar1) + +struct BurnDriver BurnDrvmd_ristar1 = { + "md_ristar1", "md_ristar", NULL, NULL, "1994", + "Ristar (Euro, USA, 199408)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristar1RomInfo, md_ristar1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar - The Shooting Star (Jpn, Kor) +static struct BurnRomInfo md_ristarjRomDesc[] = { + { "ristar - the shooting star (jpn, kor).bin", 0x200000, 0xce464f0e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristarj) +STD_ROM_FN(md_ristarj) + +struct BurnDriver BurnDrvmd_ristarj = { + "md_ristarj", "md_ristar", NULL, NULL, "1995", + "Ristar - The Shooting Star (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarjRomInfo, md_ristarjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Prototype, 19940812) +static struct BurnRomInfo md_ristarp2RomDesc[] = { + { "ristar (prototype - aug 12, 1994).bin", 0x200000, 0x4371f046, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristarp2) +STD_ROM_FN(md_ristarp2) + +struct BurnDriver BurnDrvmd_ristarp2 = { + "md_ristarp2", "md_ristar", NULL, NULL, "1994", + "Ristar (Prototype, 19940812)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarp2RomInfo, md_ristarp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Prototype, 19940826) +static struct BurnRomInfo md_ristarp1RomDesc[] = { + { "ristar (prototype - aug 26, 1994).bin", 0x200000, 0xd0c74fdd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristarp1) +STD_ROM_FN(md_ristarp1) + +struct BurnDriver BurnDrvmd_ristarp1 = { + "md_ristarp1", "md_ristar", NULL, NULL, "1994", + "Ristar (Prototype, 19940826)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarp1RomInfo, md_ristarp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Prototype, 19940701) +static struct BurnRomInfo md_ristarp4RomDesc[] = { + { "ristar (prototype - jul 01, 1994).bin", 0x200000, 0x7c5c7a0a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristarp4) +STD_ROM_FN(md_ristarp4) + +struct BurnDriver BurnDrvmd_ristarp4 = { + "md_ristarp4", "md_ristar", NULL, NULL, "1994", + "Ristar (Prototype, 19940701)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarp4RomInfo, md_ristarp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ristar (Prototype, 19940718) +static struct BurnRomInfo md_ristarp3RomDesc[] = { + { "ristar (prototype - jul 18, 1994).bin", 0x200000, 0x6becccc9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ristarp3) +STD_ROM_FN(md_ristarp3) + +struct BurnDriver BurnDrvmd_ristarp3 = { + "md_ristarp3", "md_ristar", NULL, NULL, "1994", + "Ristar (Prototype, 19940718)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ristarp3RomInfo, md_ristarp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road Rash (Euro, USA) +static struct BurnRomInfo md_roadrashRomDesc[] = { + { "road rash (euro, usa).bin", 0x0c0000, 0xdea53d19, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_roadrash) +STD_ROM_FN(md_roadrash) + +struct BurnDriver BurnDrvmd_roadrash = { + "md_roadrash", NULL, NULL, NULL, "1991", + "Road Rash (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_roadrashRomInfo, md_roadrashRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road Rash II (Euro, USA, v1.2) +static struct BurnRomInfo md_rrash2RomDesc[] = { + { "road rash ii (euro, usa) (v1.2).bin", 0x100000, 0x0876e992, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rrash2) +STD_ROM_FN(md_rrash2) + +struct BurnDriver BurnDrvmd_rrash2 = { + "md_rrash2", NULL, NULL, NULL, "1992", + "Road Rash II (Euro, USA, v1.2)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rrash2RomInfo, md_rrash2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road Rash II (Euro, USA) +static struct BurnRomInfo md_rrash2aRomDesc[] = { + { "rr205.bin", 0x100000, 0x7b29c209, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rrash2a) +STD_ROM_FN(md_rrash2a) + +struct BurnDriver BurnDrvmd_rrash2a = { + "md_rrash2a", "md_rrash2", NULL, NULL, "1992", + "Road Rash II (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rrash2aRomInfo, md_rrash2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road Rash II (Jpn) +static struct BurnRomInfo md_rrash2jRomDesc[] = { + { "road rash ii (jpn).bin", 0x100000, 0x9a5723b6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rrash2j) +STD_ROM_FN(md_rrash2j) + +struct BurnDriver BurnDrvmd_rrash2j = { + "md_rrash2j", "md_rrash2", NULL, NULL, "1993", + "Road Rash II (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rrash2jRomInfo, md_rrash2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road 3 Rash (Euro, USA) +static struct BurnRomInfo md_rrash3RomDesc[] = { + { "rr3b3.bin", 0x200000, 0x15785956, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rrash3) +STD_ROM_FN(md_rrash3) + +struct BurnDriver BurnDrvmd_rrash3 = { + "md_rrash3", NULL, NULL, NULL, "1995", + "Road 3 Rash (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rrash3RomInfo, md_rrash3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Road 3 Rash (USA, Prototype) +static struct BurnRomInfo md_rrash3pRomDesc[] = { + { "road rash 3 (usa) (alpha).bin", 0x200000, 0xb6626083, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rrash3p) +STD_ROM_FN(md_rrash3p) + +struct BurnDriver BurnDrvmd_rrash3p = { + "md_rrash3p", "md_rrash3", NULL, NULL, "1995", + "Road 3 Rash (USA, Prototype)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rrash3pRomInfo, md_rrash3pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoadBlasters (USA) +static struct BurnRomInfo md_roadbRomDesc[] = { + { "roadblasters (usa).bin", 0x080000, 0xec6cd5f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_roadb) +STD_ROM_FN(md_roadb) + +struct BurnDriver BurnDrvmd_roadb = { + "md_roadb", NULL, NULL, NULL, "1991", + "RoadBlasters (USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_roadbRomInfo, md_roadbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoadBlasters (Jpn) +static struct BurnRomInfo md_roadbjRomDesc[] = { + { "roadblasters (jpn).bin", 0x080000, 0xa0015440, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_roadbj) +STD_ROM_FN(md_roadbj) + +struct BurnDriver BurnDrvmd_roadbj = { + "md_roadbj", "md_roadb", NULL, NULL, "1992", + "RoadBlasters (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_roadbjRomInfo, md_roadbjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoboCop 3 (Euro, USA) +static struct BurnRomInfo md_robocop3RomDesc[] = { + { "robocop 3 (euro, usa).bin", 0x080000, 0x34fb7b27, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robocop3) +STD_ROM_FN(md_robocop3) + +struct BurnDriver BurnDrvmd_robocop3 = { + "md_robocop3", NULL, NULL, NULL, "1993", + "RoboCop 3 (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robocop3RomInfo, md_robocop3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoboCop versus The Terminator (Euro) +static struct BurnRomInfo md_robotermRomDesc[] = { + { "robocop versus the terminator (euro).bin", 0x200000, 0x85a93f8d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_roboterm) +STD_ROM_FN(md_roboterm) + +struct BurnDriver BurnDrvmd_roboterm = { + "md_roboterm", NULL, NULL, NULL, "1994", + "RoboCop versus The Terminator (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotermRomInfo, md_robotermRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoboCop versus The Terminator (Jpn, Kor) +static struct BurnRomInfo md_robotermjRomDesc[] = { + { "robocop versus the terminator (jpn, kor).bin", 0x200000, 0xd444e1f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotermj) +STD_ROM_FN(md_robotermj) + +struct BurnDriver BurnDrvmd_robotermj = { + "md_robotermj", "md_roboterm", NULL, NULL, "1994", + "RoboCop versus The Terminator (Jpn, Kor)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotermjRomInfo, md_robotermjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoboCop versus The Terminator (Prototype) +static struct BurnRomInfo md_robotermpRomDesc[] = { + { "robocop versus the terminator (beta).bin", 0x200000, 0x2487049f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotermp) +STD_ROM_FN(md_robotermp) + +struct BurnDriver BurnDrvmd_robotermp = { + "md_robotermp", "md_roboterm", NULL, NULL, "1994", + "RoboCop versus The Terminator (Prototype)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotermpRomInfo, md_robotermpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Robocop Versus The Terminator (Prototype, Alt) +static struct BurnRomInfo md_robotermp1RomDesc[] = { + { "robocop versus the terminator (beta) (alt).bin", 0x200000, 0xecebff29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotermp1) +STD_ROM_FN(md_robotermp1) + +struct BurnDriver BurnDrvmd_robotermp1 = { + "md_robotermp1", "md_roboterm", NULL, NULL, "1994", + "Robocop Versus The Terminator (Prototype, Alt)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotermp1RomInfo, md_robotermp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RoboCop versus The Terminator (USA) +static struct BurnRomInfo md_robotermuRomDesc[] = { + { "robocop versus the terminator (usa).bin", 0x200000, 0xbbad77a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotermu) +STD_ROM_FN(md_robotermu) + +struct BurnDriver BurnDrvmd_robotermu = { + "md_robotermu", "md_roboterm", NULL, NULL, "1994", + "RoboCop versus The Terminator (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotermuRomInfo, md_robotermuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Robot Battler (Jpn, SegaNet) +static struct BurnRomInfo md_robotbRomDesc[] = { + { "robot battler (jpn) (sn).bin", 0x040000, 0xfdf23eff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotb) +STD_ROM_FN(md_robotb) + +struct BurnDriver BurnDrvmd_robotb = { + "md_robotb", NULL, NULL, NULL, "1991", + "Robot Battler (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotbRomInfo, md_robotbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Robot Wreckage (USA, Prototype) +static struct BurnRomInfo md_robotwRomDesc[] = { + { "robot wreckage (usa) (prototype).bin", 0x100000, 0xc67ddb14, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_robotw) +STD_ROM_FN(md_robotw) + +struct BurnDriver BurnDrvmd_robotw = { + "md_robotw", NULL, NULL, NULL, "199?", + "Robot Wreckage (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_robotwRomInfo, md_robotwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rock n' Roll Racing (Euro) +static struct BurnRomInfo md_rocknrRomDesc[] = { + { "rock n' roll racing (euro).bin", 0x100000, 0xbc5a0562, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rocknr) +STD_ROM_FN(md_rocknr) + +struct BurnDriver BurnDrvmd_rocknr = { + "md_rocknr", NULL, NULL, NULL, "1994", + "Rock n' Roll Racing (Euro)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rocknrRomInfo, md_rocknrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rock n' Roll Racing (USA) +static struct BurnRomInfo md_rocknruRomDesc[] = { + { "rock n' roll racing (usa).bin", 0x100000, 0x6abab577, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rocknru) +STD_ROM_FN(md_rocknru) + +struct BurnDriver BurnDrvmd_rocknru = { + "md_rocknru", "md_rocknr", NULL, NULL, "1994", + "Rock n' Roll Racing (USA)\0", NULL, "Interplay", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rocknruRomInfo, md_rocknruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rocket Knight Adventures (Euro) +static struct BurnRomInfo md_rocketRomDesc[] = { + { "fx004.bin", 0x100000, 0x8eedfd51, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rocket) +STD_ROM_FN(md_rocket) + +struct BurnDriver BurnDrvmd_rocket = { + "md_rocket", NULL, NULL, NULL, "1993", + "Rocket Knight Adventures (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rocketRomInfo, md_rocketRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rocket Knight Adventures (Jpn) +static struct BurnRomInfo md_rocketjRomDesc[] = { + { "rocket knight adventures (jpn).bin", 0x100000, 0xd1c8c1c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rocketj) +STD_ROM_FN(md_rocketj) + +struct BurnDriver BurnDrvmd_rocketj = { + "md_rocketj", "md_rocket", NULL, NULL, "1993", + "Rocket Knight Adventures (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rocketjRomInfo, md_rocketjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rocket Knight Adventures (USA) +static struct BurnRomInfo md_rocketuRomDesc[] = { + { "rocket knight adventures (usa).bin", 0x100000, 0xa6efec47, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rocketu) +STD_ROM_FN(md_rocketu) + +struct BurnDriver BurnDrvmd_rocketu = { + "md_rocketu", "md_rocket", NULL, NULL, "1993", + "Rocket Knight Adventures (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rocketuRomInfo, md_rocketuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Roger Clements MVP Baseball (USA) +static struct BurnRomInfo md_rogercRomDesc[] = { + { "roger clements mvp baseball (usa).bin", 0x100000, 0x83699e34, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rogerc) +STD_ROM_FN(md_rogerc) + +struct BurnDriver BurnDrvmd_rogerc = { + "md_rogerc", NULL, NULL, NULL, "1992", + "Roger Clements MVP Baseball (USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rogercRomInfo, md_rogercRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rolling Thunder 2 (Euro) +static struct BurnRomInfo md_rthun2RomDesc[] = { + { "rolling thunder 2 (euro).bin", 0x100000, 0xc440f292, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rthun2) +STD_ROM_FN(md_rthun2) + +struct BurnDriver BurnDrvmd_rthun2 = { + "md_rthun2", NULL, NULL, NULL, "1991", + "Rolling Thunder 2 (Euro)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rthun2RomInfo, md_rthun2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rolling Thunder 2 (Jpn) +static struct BurnRomInfo md_rthun2jRomDesc[] = { + { "rolling thunder 2 (jpn).bin", 0x100000, 0x965b2628, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rthun2j) +STD_ROM_FN(md_rthun2j) + +struct BurnDriver BurnDrvmd_rthun2j = { + "md_rthun2j", "md_rthun2", NULL, NULL, "1991", + "Rolling Thunder 2 (Jpn)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rthun2jRomInfo, md_rthun2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rolling Thunder 2 (USA) +static struct BurnRomInfo md_rthun2uRomDesc[] = { + { "rolling thunder 2 (usa).bin", 0x100000, 0x3ace429b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rthun2u) +STD_ROM_FN(md_rthun2u) + +struct BurnDriver BurnDrvmd_rthun2u = { + "md_rthun2u", "md_rthun2", NULL, NULL, "1991", + "Rolling Thunder 2 (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rthun2uRomInfo, md_rthun2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rolling Thunder 3 (USA) +static struct BurnRomInfo md_rthun3RomDesc[] = { + { "rolling thunder 3 (usa).bin", 0x180000, 0x64fb13aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rthun3) +STD_ROM_FN(md_rthun3) + +struct BurnDriver BurnDrvmd_rthun3 = { + "md_rthun3", NULL, NULL, NULL, "1993", + "Rolling Thunder 3 (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rthun3RomInfo, md_rthun3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rolo to the Rescue (Euro, USA) +static struct BurnRomInfo md_roloRomDesc[] = { + { "rolo to the rescue (euro, usa).bin", 0x080000, 0x306861a2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rolo) +STD_ROM_FN(md_rolo) + +struct BurnDriver BurnDrvmd_rolo = { + "md_rolo", NULL, NULL, NULL, "1992", + "Rolo to the Rescue (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_roloRomInfo, md_roloRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zou! Zou! Zou! Rescue Daisakusen (Jpn) +static struct BurnRomInfo md_zouzouRomDesc[] = { + { "zou! zou! zou! rescue daisakusen (jpn).bin", 0x080000, 0x1a761e67, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zouzou) +STD_ROM_FN(md_zouzou) + +struct BurnDriver BurnDrvmd_zouzou = { + "md_zouzou", "md_rolo", NULL, NULL, "1993", + "Zou! Zou! Zou! Rescue Daisakusen (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zouzouRomInfo, md_zouzouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Romance of the Three Kingdoms II (USA) +static struct BurnRomInfo md_r3k2RomDesc[] = { + { "romance of the three kingdoms ii (usa).bin", 0x100000, 0x3d842478, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_r3k2) +STD_ROM_FN(md_r3k2) + +struct BurnDriver BurnDrvmd_r3k2 = { + "md_r3k2", NULL, NULL, NULL, "1991", + "Romance of the Three Kingdoms II (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_r3k2RomInfo, md_r3k2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sangokushi II (Jpn) +static struct BurnRomInfo md_sangok2RomDesc[] = { + { "mpr-14455.bin", 0x100000, 0x437ba326, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sangok2) +STD_ROM_FN(md_sangok2) + +struct BurnDriver BurnDrvmd_sangok2 = { + "md_sangok2", "md_r3k2", NULL, NULL, "1991", + "Sangokushi II (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sangok2RomInfo, md_sangok2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Romance of the Three Kingdoms III - Dragon of Destiny (USA) +static struct BurnRomInfo md_r3k3RomDesc[] = { + { "romance of the three kingdoms iii - dragon of destiny (usa).bin", 0x140000, 0x7e41c8fe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_r3k3) +STD_ROM_FN(md_r3k3) + +struct BurnDriver BurnDrvmd_r3k3 = { + "md_r3k3", NULL, NULL, NULL, "1993", + "Romance of the Three Kingdoms III - Dragon of Destiny (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_r3k3RomInfo, md_r3k3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sangokushi III (Jpn) +static struct BurnRomInfo md_sangok3RomDesc[] = { + { "sangokushi iii (jpn).bin", 0x180000, 0xa8de6aea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sangok3) +STD_ROM_FN(md_sangok3) + +struct BurnDriver BurnDrvmd_sangok3 = { + "md_sangok3", "md_r3k3", NULL, NULL, "1992", + "Sangokushi III (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sangok3RomInfo, md_sangok3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rugby World Cup 1995 (Euro, USA) +static struct BurnRomInfo md_rugbywRomDesc[] = { + { "rugby world cup 1995 (euro, usa).bin", 0x200000, 0x61f90a8a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rugbyw) +STD_ROM_FN(md_rugbyw) + +struct BurnDriver BurnDrvmd_rugbyw = { + "md_rugbyw", NULL, NULL, NULL, "1994", + "Rugby World Cup 1995 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rugbywRomInfo, md_rugbywRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sagaia (USA) +static struct BurnRomInfo md_sagaiaRomDesc[] = { + { "sagaia (usa).bin", 0x100000, 0xf1e22f43, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sagaia) +STD_ROM_FN(md_sagaia) + +struct BurnDriver BurnDrvmd_sagaia = { + "md_sagaia", NULL, NULL, NULL, "1991", + "Sagaia (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sagaiaRomInfo, md_sagaiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Darius II (Jpn) +static struct BurnRomInfo md_darius2RomDesc[] = { + { "darius ii (jpn).bin", 0x100000, 0x25dfe62a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_darius2) +STD_ROM_FN(md_darius2) + +struct BurnDriver BurnDrvmd_darius2 = { + "md_darius2", "md_sagaia", NULL, NULL, "1990", + "Darius II (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_darius2RomInfo, md_darius2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bishoujo Senshi Sailor Moon (Jpn) +static struct BurnRomInfo md_sailormRomDesc[] = { + { "bishoujo senshi sailor moon (jpn).bin", 0x200000, 0x5e246938, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sailorm) +STD_ROM_FN(md_sailorm) + +struct BurnDriver BurnDrvmd_sailorm = { + "md_sailorm", NULL, NULL, NULL, "1994", + "Bishoujo Senshi Sailor Moon (Jpn)\0", NULL, "Ma-Ba", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sailormRomInfo, md_sailormRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Saint Sword (USA) +static struct BurnRomInfo md_sswordRomDesc[] = { + { "saint sword (usa).bin", 0x080000, 0x44f66bff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssword) +STD_ROM_FN(md_ssword) + +struct BurnDriver BurnDrvmd_ssword = { + "md_ssword", NULL, NULL, NULL, "1991", + "Saint Sword (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sswordRomInfo, md_sswordRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Saint Sword (Jpn) +static struct BurnRomInfo md_sswordjRomDesc[] = { + { "saint sword (jpn).bin", 0x080000, 0x3960a00f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sswordj) +STD_ROM_FN(md_sswordj) + +struct BurnDriver BurnDrvmd_sswordj = { + "md_sswordj", "md_ssword", NULL, NULL, "1991", + "Saint Sword (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sswordjRomInfo, md_sswordjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sampras Tennis 96 (Euro, J-Cart) +static struct BurnRomInfo md_sampra96RomDesc[] = { + { "sampras tennis 96 (euro) (j-cart).bin", 0x200000, 0x14e3fb7b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sampra96) +STD_ROM_FN(md_sampra96) + +struct BurnDriver BurnDrvmd_sampra96 = { + "md_sampra96", NULL, NULL, NULL, "1995", + "Sampras Tennis 96 (Euro, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sampra96RomInfo, md_sampra96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Samurai Shodown (Euro) +static struct BurnRomInfo md_samshoRomDesc[] = { + { "samurai shodown (euro).bin", 0x300000, 0xc972014f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_samsho) +STD_ROM_FN(md_samsho) + +struct BurnDriver BurnDrvmd_samsho = { + "md_samsho", NULL, NULL, NULL, "1994", + "Samurai Shodown (Euro)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_samshoRomInfo, md_samshoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Samurai Shodown (USA) +static struct BurnRomInfo md_samshouRomDesc[] = { + { "samurai shodown (usa).bin", 0x300000, 0x5bb8b2d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_samshou) +STD_ROM_FN(md_samshou) + +struct BurnDriver BurnDrvmd_samshou = { + "md_samshou", "md_samsho", NULL, NULL, "1994", + "Samurai Shodown (USA)\0", NULL, "Takara", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_samshouRomInfo, md_samshouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Samurai Spirits (Jpn) +static struct BurnRomInfo md_samspirRomDesc[] = { + { "samurai spirits (jpn).bin", 0x300000, 0x0ea2ae36, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_samspir) +STD_ROM_FN(md_samspir) + +struct BurnDriver BurnDrvmd_samspir = { + "md_samspir", "md_samsho", NULL, NULL, "1994", + "Samurai Spirits (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_samspirRomInfo, md_samspirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// San Guo Zhi Lie Zhuan - Luan Shi Qun Ying (Chi) +static struct BurnRomInfo md_sanguoRomDesc[] = { + { "san guo zhi lie zhuan - luan shi qun ying (chi).bin", 0x100000, 0x3b5cc398, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sanguo) +STD_ROM_FN(md_sanguo) + +struct BurnDriver BurnDrvmd_sanguo = { + "md_sanguo", NULL, NULL, NULL, "199?", + "San Guo Zhi Lie Zhuan - Luan Shi Qun Ying (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sanguoRomInfo, md_sanguoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// San Guo Zhi V (Chi) +static struct BurnRomInfo md_sanguo5RomDesc[] = { + { "san guo zhi v (chi) (unl).bin", 0x200000, 0xcd7e53d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sanguo5) +STD_ROM_FN(md_sanguo5) + +struct BurnDriver BurnDrvmd_sanguo5 = { + "md_sanguo5", NULL, NULL, NULL, "199?", + "San Guo Zhi V (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sanguo5RomInfo, md_sanguo5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// San San (Jpn) +static struct BurnRomInfo md_sansanRomDesc[] = { + { "san san (japan).bin", 0x100000, 0x5b85deed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sansan) +STD_ROM_FN(md_sansan) + +struct BurnDriver BurnDrvmd_sansan = { + "md_sansan", NULL, NULL, NULL, "1994", + "San San (Jpn)\0", NULL, "San San Co.", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sansanRomInfo, md_sansanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sangokushi Retsuden - Ransei no Eiyuutachi (Jpn) +static struct BurnRomInfo md_sangokrRomDesc[] = { + { "sangokushi retsuden - ransei no eiyuutachi (jpn).bin", 0x100000, 0x0f56785a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sangokr) +STD_ROM_FN(md_sangokr) + +struct BurnDriver BurnDrvmd_sangokr = { + "md_sangokr", NULL, NULL, NULL, "1991", + "Sangokushi Retsuden - Ransei no Eiyuutachi (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sangokrRomInfo, md_sangokrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Saturday Night Slammasters (Euro) +static struct BurnRomInfo md_slammastRomDesc[] = { + { "saturday night slammasters (euro).bin", 0x400000, 0x08fa5a3f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slammast) +STD_ROM_FN(md_slammast) + +struct BurnDriver BurnDrvmd_slammast = { + "md_slammast", NULL, NULL, NULL, "1994", + "Saturday Night Slammasters (Euro)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slammastRomInfo, md_slammastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Saturday Night Slammasters (USA) +static struct BurnRomInfo md_slammastuRomDesc[] = { + { "saturday night slammasters (usa).bin", 0x400000, 0x2fb4eaba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slammastu) +STD_ROM_FN(md_slammastu) + +struct BurnDriver BurnDrvmd_slammastu = { + "md_slammastu", "md_slammast", NULL, NULL, "1994", + "Saturday Night Slammasters (USA)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slammastuRomInfo, md_slammastuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scooby Doo Mystery (USA) +static struct BurnRomInfo md_scoobyRomDesc[] = { + { "scooby doo mystery (usa).bin", 0x200000, 0x7bb9dd9b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_scooby) +STD_ROM_FN(md_scooby) + +struct BurnDriver BurnDrvmd_scooby = { + "md_scooby", NULL, NULL, NULL, "1995", + "Scooby Doo Mystery (USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_scoobyRomInfo, md_scoobyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Scrabble (Euro, Prototype) +static struct BurnRomInfo md_scrabbleRomDesc[] = { + { "scrabble (euro) (prototype).bin", 0x100000, 0x360b2610, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_scrabble) +STD_ROM_FN(md_scrabble) + +struct BurnDriver BurnDrvmd_scrabble = { + "md_scrabble", NULL, NULL, NULL, "199?", + "Scrabble (Euro, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_scrabbleRomInfo, md_scrabbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SeaQuest DSV (Euro) +static struct BurnRomInfo md_seaquestRomDesc[] = { + { "seaquest dsv (euro).bin", 0x200000, 0x0bb511bd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_seaquest) +STD_ROM_FN(md_seaquest) + +struct BurnDriver BurnDrvmd_seaquest = { + "md_seaquest", NULL, NULL, NULL, "1994", + "SeaQuest DSV (Euro)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_seaquestRomInfo, md_seaquestRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SeaQuest DSV (USA) +static struct BurnRomInfo md_seaquestuRomDesc[] = { + { "seaquest dsv (usa).bin", 0x200000, 0x25b05480, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_seaquestu) +STD_ROM_FN(md_seaquestu) + +struct BurnDriver BurnDrvmd_seaquestu = { + "md_seaquestu", "md_seaquest", NULL, NULL, "1994", + "SeaQuest DSV (USA)\0", NULL, "Black Pearl", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_seaquestuRomInfo, md_seaquestuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Second Samurai (Euro) +static struct BurnRomInfo md_secondRomDesc[] = { + { "second samurai (euro).bin", 0x100000, 0x78e92143, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_second) +STD_ROM_FN(md_second) + +struct BurnDriver BurnDrvmd_second = { + "md_second", NULL, NULL, NULL, "1994", + "Second Samurai (Euro)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_secondRomInfo, md_secondRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sega Sports 1 (Euro) +static struct BurnRomInfo md_segaspRomDesc[] = { + { "sega sports 1 (euro).bin", 0x280000, 0x07fedaf1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_segasp) +STD_ROM_FN(md_segasp) + +struct BurnDriver BurnDrvmd_segasp = { + "md_segasp", NULL, NULL, NULL, "1995", + "Sega Sports 1 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_segaspRomInfo, md_segaspRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sega Top Five (Bra) +static struct BurnRomInfo md_segatopRomDesc[] = { + { "sega top five (bra).bin", 0x200000, 0x61069069, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_segatop) +STD_ROM_FN(md_segatop) + +struct BurnDriver BurnDrvmd_segatop = { + "md_segatop", NULL, NULL, NULL, "199?", + "Sega Top Five (Bra)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_segatopRomInfo, md_segatopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sensible Soccer (Euro) +static struct BurnRomInfo md_sensibleRomDesc[] = { + { "mpr-16014.bin", 0x080000, 0xf9b396b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sensible) +STD_ROM_FN(md_sensible) + +struct BurnDriver BurnDrvmd_sensible = { + "md_sensible", NULL, NULL, NULL, "1993", + "Sensible Soccer (Euro)\0", NULL, "Renegade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sensibleRomInfo, md_sensibleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sensible Soccer (Prototype) +static struct BurnRomInfo md_sensiblepRomDesc[] = { + { "sensible soccer (beta).bin", 0x080000, 0xef52664d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sensiblep) +STD_ROM_FN(md_sensiblep) + +struct BurnDriver BurnDrvmd_sensiblep = { + "md_sensiblep", "md_sensible", NULL, NULL, "1993", + "Sensible Soccer (Prototype)\0", NULL, "Renegade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sensiblepRomInfo, md_sensiblepRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sensible Soccer - International Edition (Euro) +static struct BurnRomInfo md_sensibieRomDesc[] = { + { "sensible soccer - international edition (euro).bin", 0x080000, 0x04e3bcca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sensibie) +STD_ROM_FN(md_sensibie) + +struct BurnDriver BurnDrvmd_sensibie = { + "md_sensibie", NULL, NULL, NULL, "1993", + "Sensible Soccer - International Edition (Euro)\0", NULL, "Sony Imagesoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sensibieRomInfo, md_sensibieRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sesame Street Counting Cafe (USA) +static struct BurnRomInfo md_sesameRomDesc[] = { + { "sesame street counting cafe (usa).bin", 0x100000, 0x0a4f48c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sesame) +STD_ROM_FN(md_sesame) + +struct BurnDriver BurnDrvmd_sesame = { + "md_sesame", NULL, NULL, NULL, "1994", + "Sesame Street Counting Cafe (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sesameRomInfo, md_sesameRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadow Blasters (USA) +static struct BurnRomInfo md_shadowRomDesc[] = { + { "shadow blasters (usa).bin", 0x080000, 0x713d377b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadow) +STD_ROM_FN(md_shadow) + +struct BurnDriver BurnDrvmd_shadow = { + "md_shadow", NULL, NULL, NULL, "1990", + "Shadow Blasters (USA)\0", NULL, "Sage's Creation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shadowRomInfo, md_shadowRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shiten Myouou (Jpn) +static struct BurnRomInfo md_shitenRomDesc[] = { + { "shiten myouou (jpn).bin", 0x080000, 0x7e729693, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shiten) +STD_ROM_FN(md_shiten) + +struct BurnDriver BurnDrvmd_shiten = { + "md_shiten", "md_shadow", NULL, NULL, "1990", + "Shiten Myouou (Jpn)\0", NULL, "Sigma", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shitenRomInfo, md_shitenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadow Dancer - The Secret of Shinobi (World) +static struct BurnRomInfo md_shdancRomDesc[] = { + { "mpr-13571.bin", 0x080000, 0xebe9ad10, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shdanc) +STD_ROM_FN(md_shdanc) + +struct BurnDriver BurnDrvmd_shdanc = { + "md_shdanc", NULL, NULL, NULL, "1990", + "Shadow Dancer - The Secret of Shinobi (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shdancRomInfo, md_shdancRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadow of the Beast (Euro, USA) +static struct BurnRomInfo md_beastRomDesc[] = { + { "sha01.bin", 0x100000, 0xbd385c27, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beast) +STD_ROM_FN(md_beast) + +struct BurnDriver BurnDrvmd_beast = { + "md_beast", NULL, NULL, NULL, "1991", + "Shadow of the Beast (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beastRomInfo, md_beastRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadow of the Beast - Mashou no Okite (Jpn) +static struct BurnRomInfo md_beastjRomDesc[] = { + { "shadow of the beast - mashou no okite (jpn).bin", 0x100000, 0x0cd09d31, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beastj) +STD_ROM_FN(md_beastj) + +struct BurnDriver BurnDrvmd_beastj = { + "md_beastj", "md_beast", NULL, NULL, "1992", + "Shadow of the Beast - Mashou no Okite (Jpn)\0", NULL, "Victor Interactive Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beastjRomInfo, md_beastjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadow of the Beast II (Euro, USA) +static struct BurnRomInfo md_beast2RomDesc[] = { + { "shadow of the beast ii (euro, usa).bin", 0x100000, 0x2dede3db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beast2) +STD_ROM_FN(md_beast2) + +struct BurnDriver BurnDrvmd_beast2 = { + "md_beast2", NULL, NULL, NULL, "1992", + "Shadow of the Beast II (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_beast2RomInfo, md_beast2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (USA) +static struct BurnRomInfo md_shadowrnRomDesc[] = { + { "shadowrun (usa).bin", 0x200000, 0xfbb92909, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrn) +STD_ROM_FN(md_shadowrn) + +struct BurnDriver BurnDrvmd_shadowrn = { + "md_shadowrn", NULL, NULL, NULL, "1994", + "Shadowrun (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnRomInfo, md_shadowrnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (Jpn) +static struct BurnRomInfo md_shadowrnjRomDesc[] = { + { "shadowrun (jpn).bin", 0x200000, 0xd32199f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrnj) +STD_ROM_FN(md_shadowrnj) + +struct BurnDriver BurnDrvmd_shadowrnj = { + "md_shadowrnj", "md_shadowrn", NULL, NULL, "199?", + "Shadowrun (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnjRomInfo, md_shadowrnjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (Prototype, 19931228) +static struct BurnRomInfo md_shadowrnp4RomDesc[] = { + { "shadowrun (prototype - dec 28, 1993).bin", 0x200000, 0x2455add2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrnp4) +STD_ROM_FN(md_shadowrnp4) + +struct BurnDriver BurnDrvmd_shadowrnp4 = { + "md_shadowrnp4", "md_shadowrn", NULL, NULL, "1993", + "Shadowrun (Prototype, 19931228)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnp4RomInfo, md_shadowrnp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (Prototype, 19931231) +static struct BurnRomInfo md_shadowrnp3RomDesc[] = { + { "shadowrun (prototype - dec 31, 1993).bin", 0x200000, 0xbbb5e2fa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrnp3) +STD_ROM_FN(md_shadowrnp3) + +struct BurnDriver BurnDrvmd_shadowrnp3 = { + "md_shadowrnp3", "md_shadowrn", NULL, NULL, "1993", + "Shadowrun (Prototype, 19931231)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnp3RomInfo, md_shadowrnp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (Prototype, 19940125-C) +static struct BurnRomInfo md_shadowrnp2RomDesc[] = { + { "shadowrun (prototype - jan 25, 1994 - c).bin", 0x200000, 0x6e2bbca8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrnp2) +STD_ROM_FN(md_shadowrnp2) + +struct BurnDriver BurnDrvmd_shadowrnp2 = { + "md_shadowrnp2", "md_shadowrn", NULL, NULL, "1994", + "Shadowrun (Prototype, 19940125-C)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnp2RomInfo, md_shadowrnp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shadowrun (Prototype, 19940125) +static struct BurnRomInfo md_shadowrnp1RomDesc[] = { + { "shadowrun (prototype - jan 25, 1994).bin", 0x200000, 0x2a964bcd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shadowrnp1) +STD_ROM_FN(md_shadowrnp1) + +struct BurnDriver BurnDrvmd_shadowrnp1 = { + "md_shadowrnp1", "md_shadowrn", NULL, NULL, "1994", + "Shadowrun (Prototype, 19940125)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shadowrnp1RomInfo, md_shadowrnp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shane Warne Cricket (Aus) +static struct BurnRomInfo md_shanewarRomDesc[] = { + { "shane warne cricket (aus).bin", 0x100000, 0x68865f6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shanewar) +STD_ROM_FN(md_shanewar) + +struct BurnDriver BurnDrvmd_shanewar = { + "md_shanewar", NULL, NULL, NULL, "1997", + "Shane Warne Cricket (Aus)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shanewarRomInfo, md_shanewarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shanghai II - Dragon's Eye (USA) +static struct BurnRomInfo md_shangha2RomDesc[] = { + { "shanghai ii - dragon's eye (usa).bin", 0x100000, 0xebe9e840, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangha2) +STD_ROM_FN(md_shangha2) + +struct BurnDriver BurnDrvmd_shangha2 = { + "md_shangha2", NULL, NULL, NULL, "1994", + "Shanghai II - Dragon's Eye (USA)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangha2RomInfo, md_shangha2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shanghai II - Dragon's Eye (USA, Prototype) +static struct BurnRomInfo md_shangha2pRomDesc[] = { + { "shanghai ii - dragon's eye (beta).bin", 0x100000, 0x154aca2d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangha2p) +STD_ROM_FN(md_shangha2p) + +struct BurnDriver BurnDrvmd_shangha2p = { + "md_shangha2p", "md_shangha2", NULL, NULL, "1994", + "Shanghai II - Dragon's Eye (USA, Prototype)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangha2pRomInfo, md_shangha2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shanghai II - Dragon's Eye (USA, Prototype, Alt) +static struct BurnRomInfo md_shangha2p1RomDesc[] = { + { "shanghai ii - dragon's eye (beta) (alt).bin", 0x100000, 0x5e33867b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangha2p1) +STD_ROM_FN(md_shangha2p1) + +struct BurnDriver BurnDrvmd_shangha2p1 = { + "md_shangha2p1", "md_shangha2", NULL, NULL, "1994", + "Shanghai II - Dragon's Eye (USA, Prototype, Alt)\0", NULL, "Activision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangha2p1RomInfo, md_shangha2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shaq Fu (Euro, USA) +static struct BurnRomInfo md_shaqfuRomDesc[] = { + { "sfb2_u1+sfb2_u2.bin", 0x300000, 0x499955f2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shaqfu) +STD_ROM_FN(md_shaqfu) + +struct BurnDriver BurnDrvmd_shaqfu = { + "md_shaqfu", NULL, NULL, NULL, "1994", + "Shaq Fu (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shaqfuRomInfo, md_shaqfuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi Jie Zhi Bang Zheng Ba Zhan - World Pro Baseball 94 (Chi) +static struct BurnRomInfo md_shijieRomDesc[] = { + { "shi jie zhi bang zheng ba zhan - world pro baseball 94 (chi) (unl).bin", 0x200000, 0x72dd884f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shijie) +STD_ROM_FN(md_shijie) + +struct BurnDriver BurnDrvmd_shijie = { + "md_shijie", NULL, NULL, NULL, "1994", + "Shi Jie Zhi Bang Zheng Ba Zhan - World Pro Baseball 94 (Chi)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shijieRomInfo, md_shijieRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shikinjoh (Jpn) +static struct BurnRomInfo md_shikinjoRomDesc[] = { + { "shikinjoh (jpn).bin", 0x080000, 0x5ea0c97d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shikinjo) +STD_ROM_FN(md_shikinjo) + +struct BurnDriver BurnDrvmd_shikinjo = { + "md_shikinjo", NULL, NULL, NULL, "1991", + "Shikinjoh (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shikinjoRomInfo, md_shikinjoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force (USA) +static struct BurnRomInfo md_shinfrceRomDesc[] = { + { "shining force (usa).bin", 0x180000, 0xe0594abe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrce) +STD_ROM_FN(md_shinfrce) + +struct BurnDriver BurnDrvmd_shinfrce = { + "md_shinfrce", NULL, NULL, NULL, "1992", + "Shining Force (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrceRomInfo, md_shinfrceRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force (USA, Prototype) +static struct BurnRomInfo md_shinfrcepRomDesc[] = { + { "shining force (usa) (beta).bin", 0x180000, 0xce67143a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrcep) +STD_ROM_FN(md_shinfrcep) + +struct BurnDriver BurnDrvmd_shinfrcep = { + "md_shinfrcep", "md_shinfrce", NULL, NULL, "1992", + "Shining Force (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrcepRomInfo, md_shinfrcepRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force - Kamigami no Isan (Jpn) +static struct BurnRomInfo md_shinfrcejRomDesc[] = { + { "shining force - kamigami no isan (jpn).bin", 0x180000, 0x9378fbcd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrcej) +STD_ROM_FN(md_shinfrcej) + +struct BurnDriver BurnDrvmd_shinfrcej = { + "md_shinfrcej", "md_shinfrce", NULL, NULL, "1992", + "Shining Force - Kamigami no Isan (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrcejRomInfo, md_shinfrcejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force II - Koe no Fuuin (Jpn) +static struct BurnRomInfo md_shinfrc2jRomDesc[] = { + { "shining force ii - koe no fuuin (jpn).bin", 0x200000, 0x0288f3e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrc2j) +STD_ROM_FN(md_shinfrc2j) + +struct BurnDriver BurnDrvmd_shinfrc2j = { + "md_shinfrc2j", "md_shinfrc2", NULL, NULL, "1993", + "Shining Force II - Koe no Fuuin (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrc2jRomInfo, md_shinfrc2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force II (Prototype, 19940404) +static struct BurnRomInfo md_shinfrc2p2RomDesc[] = { + { "shining force ii (prototype - apr 04, 1994).bin", 0x200000, 0x5843670c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrc2p2) +STD_ROM_FN(md_shinfrc2p2) + +struct BurnDriver BurnDrvmd_shinfrc2p2 = { + "md_shinfrc2p2", "md_shinfrc2", NULL, NULL, "1994", + "Shining Force II (Prototype, 19940404)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrc2p2RomInfo, md_shinfrc2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force II (Prototype, 19940607) +static struct BurnRomInfo md_shinfrc2p1RomDesc[] = { + { "shining force ii (prototype - jun 07, 1994).bin", 0x200000, 0x03b68bba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrc2p1) +STD_ROM_FN(md_shinfrc2p1) + +struct BurnDriver BurnDrvmd_shinfrc2p1 = { + "md_shinfrc2p1", "md_shinfrc2", NULL, NULL, "1994", + "Shining Force II (Prototype, 19940607)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrc2p1RomInfo, md_shinfrc2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining Force II (USA) +static struct BurnRomInfo md_shinfrc2uRomDesc[] = { + { "shining force ii (usa).bin", 0x200000, 0x4815e075, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinfrc2u) +STD_ROM_FN(md_shinfrc2u) + +struct BurnDriver BurnDrvmd_shinfrc2u = { + "md_shinfrc2u", "md_shinfrc2", NULL, NULL, "1994", + "Shining Force II (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shinfrc2uRomInfo, md_shinfrc2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining in the Darkness (Euro, USA) +static struct BurnRomInfo md_shindarkRomDesc[] = { + { "shining in the darkness (euro, usa).bin", 0x100000, 0x4d2785bc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shindark) +STD_ROM_FN(md_shindark) + +struct BurnDriver BurnDrvmd_shindark = { + "md_shindark", NULL, NULL, NULL, "1991", + "Shining in the Darkness (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shindarkRomInfo, md_shindarkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining in the Darkness (Bra) +static struct BurnRomInfo md_shindarkbrRomDesc[] = { + { "shining in the darkness (bra).bin", 0x100000, 0x3ee2bbc4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shindarkbr) +STD_ROM_FN(md_shindarkbr) + +struct BurnDriver BurnDrvmd_shindarkbr = { + "md_shindarkbr", "md_shindark", NULL, NULL, "1994", + "Shining in the Darkness (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shindarkbrRomInfo, md_shindarkbrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shining and the Darkness (Jpn) +static struct BurnRomInfo md_shindarkjRomDesc[] = { + { "mpr-13807.bin", 0x100000, 0x496af51c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shindarkj) +STD_ROM_FN(md_shindarkj) + +struct BurnDriver BurnDrvmd_shindarkj = { + "md_shindarkj", "md_shindark", NULL, NULL, "1991", + "Shining and the Darkness (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_shindarkjRomInfo, md_shindarkjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shinobi III - Return of the Ninja Master (Euro) +static struct BurnRomInfo md_shinobi3RomDesc[] = { + { "shinobi iii - return of the ninja master (euro).bin", 0x100000, 0x0b6d3eb5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinobi3) +STD_ROM_FN(md_shinobi3) + +struct BurnDriver BurnDrvmd_shinobi3 = { + "md_shinobi3", NULL, NULL, NULL, "1993", + "Shinobi III - Return of the Ninja Master (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shinobi3RomInfo, md_shinobi3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shinobi III - Return of the Ninja Master (USA) +static struct BurnRomInfo md_shinobi3uRomDesc[] = { + { "shinobi iii - return of the ninja master (usa).bin", 0x100000, 0x5381506f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shinobi3u) +STD_ROM_FN(md_shinobi3u) + +struct BurnDriver BurnDrvmd_shinobi3u = { + "md_shinobi3u", "md_shinobi3", NULL, NULL, "1993", + "Shinobi III - Return of the Ninja Master (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shinobi3uRomInfo, md_shinobi3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Super Shinobi II (Jpn, Kor) +static struct BurnRomInfo md_supshin2RomDesc[] = { + { "super shinobi ii, the (jpn, kor).bin", 0x100000, 0x5b412816, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supshin2) +STD_ROM_FN(md_supshin2) + +struct BurnDriver BurnDrvmd_supshin2 = { + "md_supshin2", "md_shinobi3", NULL, NULL, "1993", + "The Super Shinobi II (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supshin2RomInfo, md_supshin2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Super Shinobi II (Jpn, Prototype) +static struct BurnRomInfo md_supshin2p1RomDesc[] = { + { "super shinobi ii, the (jpn) (beta).bin", 0x100000, 0xc47e8aea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supshin2p1) +STD_ROM_FN(md_supshin2p1) + +struct BurnDriver BurnDrvmd_supshin2p1 = { + "md_supshin2p1", "md_shinobi3", NULL, NULL, "1993", + "The Super Shinobi II (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supshin2p1RomInfo, md_supshin2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Super Shinobi II (Jpn, Prototype, Earlier) +static struct BurnRomInfo md_supshin2p2RomDesc[] = { + { "super shinobi ii, the (jpn) (beta) (earlier).bin", 0x100000, 0x1ee5bce3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supshin2p2) +STD_ROM_FN(md_supshin2p2) + +struct BurnDriver BurnDrvmd_supshin2p2 = { + "md_supshin2p2", "md_shinobi3", NULL, NULL, "1993", + "The Super Shinobi II (Jpn, Prototype, Earlier)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supshin2p2RomInfo, md_supshin2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ship (Prototype) +static struct BurnRomInfo md_shipRomDesc[] = { + { "ship (prototype).bin", 0x020000, 0x4cdc9f16, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ship) +STD_ROM_FN(md_ship) + +struct BurnDriver BurnDrvmd_ship = { + "md_ship", NULL, NULL, NULL, "199?", + "Ship (Prototype)\0", NULL, "Technopop", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shipRomInfo, md_shipRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shougi no Hoshi (Jpn) +static struct BurnRomInfo md_shougiRomDesc[] = { + { "shougi no hoshi (jpn).bin", 0x040000, 0x4148f816, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shougi) +STD_ROM_FN(md_shougi) + +struct BurnDriver BurnDrvmd_shougi = { + "md_shougi", NULL, NULL, NULL, "1991", + "Shougi no Hoshi (Jpn)\0", NULL, "Home Data", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shougiRomInfo, md_shougiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shove It! ...The Warehouse Game (USA) +static struct BurnRomInfo md_shoveitRomDesc[] = { + { "shove it! ...the warehouse game (usa).bin", 0x020000, 0xc51f40cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shoveit) +STD_ROM_FN(md_shoveit) + +struct BurnDriver BurnDrvmd_shoveit = { + "md_shoveit", NULL, NULL, NULL, "1990", + "Shove It! ...The Warehouse Game (USA)\0", NULL, "Dreamworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shoveitRomInfo, md_shoveitRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shijou Saidai no Soukoban (Jpn) +static struct BurnRomInfo md_soukobanRomDesc[] = { + { "shijou saidai no soukoban (jpn).bin", 0x040000, 0x40f4aacc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soukoban) +STD_ROM_FN(md_soukoban) + +struct BurnDriver BurnDrvmd_soukoban = { + "md_soukoban", "md_shoveit", NULL, NULL, "1990", + "Shijou Saidai no Soukoban (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soukobanRomInfo, md_soukobanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Show do Milhão (Bra) +static struct BurnRomInfo md_sdmilhaoRomDesc[] = { + { "show do milhao (bra).bin", 0x200000, 0x0a22df04, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdmilhao) +STD_ROM_FN(md_sdmilhao) + +struct BurnDriver BurnDrvmd_sdmilhao = { + "md_sdmilhao", NULL, NULL, NULL, "2001", + "Show do Milhao (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + L"Show do Milh\u00e3o (Bra)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sdmilhaoRomInfo, md_sdmilhaoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Show do Milhão Volume 2 (Bra) +static struct BurnRomInfo md_sdmilha2RomDesc[] = { + { "show do milhao volume 2 (bra).bin", 0x200000, 0x48ee66cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdmilha2) +STD_ROM_FN(md_sdmilha2) + +struct BurnDriver BurnDrvmd_sdmilha2 = { + "md_sdmilha2", NULL, NULL, NULL, "2002", + "Show do Milhao Volume 2 (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + L"Show do Milh\u00e3o Volume 2 (Bra)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sdmilha2RomInfo, md_sdmilha2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Show do Milhão Volume 2 (Bra, Alt) +static struct BurnRomInfo md_sdmilha2aRomDesc[] = { + { "show do milhao volume 2 (bra) (alt).bin", 0x200000, 0xd8c9ac6d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdmilha2a) +STD_ROM_FN(md_sdmilha2a) + +struct BurnDriver BurnDrvmd_sdmilha2a = { + "md_sdmilha2a", "md_sdmilha2", NULL, NULL, "2002", + "Show do Milhao Volume 2 (Bra, Alt)\0", NULL, "Tec Toy", "Sega Megadrive", + L"Show do Milh\u00e3o Volume 2 (Bra, Alt)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sdmilha2aRomInfo, md_sdmilha2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shui Hu - Feng Yun Zhuan (Chi) +static struct BurnRomInfo md_shuihuRomDesc[] = { + { "shui hu - feng yun zhuan (chi) (unl).bin", 0x200000, 0x3e9e010c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shuihu) +STD_ROM_FN(md_shuihu) + +struct BurnDriver BurnDrvmd_shuihu = { + "md_shuihu", NULL, NULL, NULL, "1999", + "Shui Hu - Feng Yun Zhuan (Chi)\0", NULL, "Never Ending Soft Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shuihuRomInfo, md_shuihuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shui Hu Zhuan (Chi) +static struct BurnRomInfo md_shuihuzhRomDesc[] = { + { "shui hu zhuan (chi) (unl).bin", 0x200000, 0x61e458c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shuihuzh) +STD_ROM_FN(md_shuihuzh) + +struct BurnDriver BurnDrvmd_shuihuzh = { + "md_shuihuzh", NULL, NULL, NULL, "1996", + "Shui Hu Zhuan (Chi)\0", NULL, "Chuanpu Technologies", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shuihuzhRomInfo, md_shuihuzhRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shura no Mon (Jpn) +static struct BurnRomInfo md_shuramonRomDesc[] = { + { "shura no mon (jpn).bin", 0x100000, 0xe19da6e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shuramon) +STD_ROM_FN(md_shuramon) + +struct BurnDriver BurnDrvmd_shuramon = { + "md_shuramon", NULL, NULL, NULL, "1992", + "Shura no Mon (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shuramonRomInfo, md_shuramonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Side Pocket (Euro) +static struct BurnRomInfo md_sidepockRomDesc[] = { + { "side pocket (euro).bin", 0x100000, 0x36e08145, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sidepock) +STD_ROM_FN(md_sidepock) + +struct BurnDriver BurnDrvmd_sidepock = { + "md_sidepock", NULL, NULL, NULL, "1992", + "Side Pocket (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sidepockRomInfo, md_sidepockRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Side Pocket (Jpn) +static struct BurnRomInfo md_sidepockjRomDesc[] = { + { "side pocket (jpn).bin", 0x100000, 0x336bbf3e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sidepockj) +STD_ROM_FN(md_sidepockj) + +struct BurnDriver BurnDrvmd_sidepockj = { + "md_sidepockj", "md_sidepock", NULL, NULL, "1992", + "Side Pocket (Jpn)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sidepockjRomInfo, md_sidepockjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Side Pocket (USA) +static struct BurnRomInfo md_sidepockuRomDesc[] = { + { "side pocket (usa).bin", 0x100000, 0xaf9f275d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sidepocku) +STD_ROM_FN(md_sidepocku) + +struct BurnDriver BurnDrvmd_sidepocku = { + "md_sidepocku", "md_sidepock", NULL, NULL, "1992", + "Side Pocket (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sidepockuRomInfo, md_sidepockuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Simpsons - Bart Vs The Space Mutants (Euro, USA, Rev. A) +static struct BurnRomInfo md_bartvssmRomDesc[] = { + { "mpr-14759a.bin", 0x080000, 0xdb70e8ca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bartvssm) +STD_ROM_FN(md_bartvssm) + +struct BurnDriver BurnDrvmd_bartvssm = { + "md_bartvssm", NULL, NULL, NULL, "1992", + "The Simpsons - Bart Vs The Space Mutants (Euro, USA, Rev. A)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bartvssmRomInfo, md_bartvssmRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Simpsons - Bart Vs The Space Mutants (Euro, USA) +static struct BurnRomInfo md_bartvssm1RomDesc[] = { + { "simpsons, the - bart vs the space mutants (euro, usa).bin", 0x080000, 0xc8620574, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bartvssm1) +STD_ROM_FN(md_bartvssm1) + +struct BurnDriver BurnDrvmd_bartvssm1 = { + "md_bartvssm1", "md_bartvssm", NULL, NULL, "1992", + "The Simpsons - Bart Vs The Space Mutants (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bartvssm1RomInfo, md_bartvssm1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Simpsons - Bart's Nightmare (Euro, USA) +static struct BurnRomInfo md_bartnigtRomDesc[] = { + { "simpsons, the - bart's nightmare (euro, usa).bin", 0x100000, 0x24d7507c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bartnigt) +STD_ROM_FN(md_bartnigt) + +struct BurnDriver BurnDrvmd_bartnigt = { + "md_bartnigt", NULL, NULL, NULL, "1993", + "The Simpsons - Bart's Nightmare (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bartnigtRomInfo, md_bartnigtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Skeleton Krew (Euro) +static struct BurnRomInfo md_skelkrewRomDesc[] = { + { "skeleton krew (euro).bin", 0x200000, 0x5f872737, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skelkrew) +STD_ROM_FN(md_skelkrew) + +struct BurnDriver BurnDrvmd_skelkrew = { + "md_skelkrew", NULL, NULL, NULL, "1995", + "Skeleton Krew (Euro)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skelkrewRomInfo, md_skelkrewRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Skeleton Krew (USA) +static struct BurnRomInfo md_skelkrewuRomDesc[] = { + { "skeleton krew (usa).bin", 0x200000, 0xc2e05acb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skelkrewu) +STD_ROM_FN(md_skelkrewu) + +struct BurnDriver BurnDrvmd_skelkrewu = { + "md_skelkrewu", "md_skelkrew", NULL, NULL, "1995", + "Skeleton Krew (USA)\0", NULL, "Core Design", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skelkrewuRomInfo, md_skelkrewuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Skitchin (Euro, USA) +static struct BurnRomInfo md_skitchinRomDesc[] = { + { "skitchin (euro, usa).bin", 0x200000, 0xf785f9d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skitchin) +STD_ROM_FN(md_skitchin) + +struct BurnDriver BurnDrvmd_skitchin = { + "md_skitchin", NULL, NULL, NULL, "1993", + "Skitchin (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skitchinRomInfo, md_skitchinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// From TV Animation Slam Dunk - Kyougou Makkou Taiketsu! (Jpn) +static struct BurnRomInfo md_slamdunkRomDesc[] = { + { "from tv animation slam dunk - kyougou makkou taiketsu! (jpn).bin", 0x200000, 0xcdf5678f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slamdunk) +STD_ROM_FN(md_slamdunk) + +struct BurnDriver BurnDrvmd_slamdunk = { + "md_slamdunk", NULL, NULL, NULL, "1995", + "From TV Animation Slam Dunk - Kyougou Makkou Taiketsu! (Jpn)\0", NULL, "Bandai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slamdunkRomInfo, md_slamdunkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Slam - Shaq vs. the Legends (Prototype) +static struct BurnRomInfo md_slamshaqRomDesc[] = { + { "slam - shaq vs. the legends (prototype).bin", 0x1f485a, 0xc19c200e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slamshaq) +STD_ROM_FN(md_slamshaq) + +struct BurnDriver BurnDrvmd_slamshaq = { + "md_slamshaq", NULL, NULL, NULL, "199?", + "Slam - Shaq vs. the Legends (Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slamshaqRomInfo, md_slamshaqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Slap Fight MD (Jpn) +static struct BurnRomInfo md_slapfighRomDesc[] = { + { "slap fight md (jpn).bin", 0x100000, 0xd6695695, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slapfigh) +STD_ROM_FN(md_slapfigh) + +struct BurnDriver BurnDrvmd_slapfigh = { + "md_slapfigh", NULL, NULL, NULL, "1993", + "Slap Fight MD (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slapfighRomInfo, md_slapfighRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Slaughter Sport (USA) +static struct BurnRomInfo md_slaughtrRomDesc[] = { + { "slaughter sport (usa).bin", 0x0a0000, 0xaf9f9d9c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slaughtr) +STD_ROM_FN(md_slaughtr) + +struct BurnDriver BurnDrvmd_slaughtr = { + "md_slaughtr", NULL, NULL, NULL, "1991", + "Slaughter Sport (USA)\0", NULL, "Razorsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slaughtrRomInfo, md_slaughtrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Fatman (Jpn) +static struct BurnRomInfo md_fatmanRomDesc[] = { + { "fatman (jpn).bin", 0x0a0000, 0x7867da3a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fatman) +STD_ROM_FN(md_fatman) + +struct BurnDriver BurnDrvmd_fatman = { + "md_fatman", "md_slaughtr", NULL, NULL, "1990", + "Fatman (Jpn)\0", NULL, "Sanritsu Denki", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fatmanRomInfo, md_fatmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Smurfs Travel the World (Euro) +static struct BurnRomInfo md_smurfs2RomDesc[] = { + { "smurfs travel the world, the (euro).bin", 0x100000, 0xb28bdd69, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smurfs2) +STD_ROM_FN(md_smurfs2) + +struct BurnDriver BurnDrvmd_smurfs2 = { + "md_smurfs2", NULL, NULL, NULL, "1996", + "The Smurfs Travel the World (Euro)\0", NULL, "Infogrames", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smurfs2RomInfo, md_smurfs2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Snake Rattle n' Roll (Euro) +static struct BurnRomInfo md_snakernrRomDesc[] = { + { "snake rattle n' roll (euro).bin", 0x080000, 0x543bed30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_snakernr) +STD_ROM_FN(md_snakernr) + +struct BurnDriver BurnDrvmd_snakernr = { + "md_snakernr", NULL, NULL, NULL, "1993", + "Snake Rattle n' Roll (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_snakernrRomInfo, md_snakernrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Snow Bros. - Nick & Tom (Jpn) +static struct BurnRomInfo md_snowbrosRomDesc[] = { + { "snow bros. - nick & tom (jpn).bin", 0x100000, 0x11b56228, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_snowbros) +STD_ROM_FN(md_snowbros) + +struct BurnDriver BurnDrvmd_snowbros = { + "md_snowbros", NULL, NULL, NULL, "1993", + "Snow Bros. - Nick & Tom (Jpn)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_snowbrosRomInfo, md_snowbrosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Socket (USA) +static struct BurnRomInfo md_socketRomDesc[] = { + { "socket (usa).bin", 0x100000, 0x3c14e15a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_socket) +STD_ROM_FN(md_socket) + +struct BurnDriver BurnDrvmd_socket = { + "md_socket", NULL, NULL, NULL, "1994", + "Socket (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_socketRomInfo, md_socketRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Time Dominator 1st (Jpn, Kor) +static struct BurnRomInfo md_timedomRomDesc[] = { + { "time dominator 1st (jpn, kor).bin", 0x100000, 0x7eba7a5c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_timedom) +STD_ROM_FN(md_timedom) + +struct BurnDriver BurnDrvmd_timedom = { + "md_timedom", "md_socket", NULL, NULL, "1994", + "Time Dominator 1st (Jpn, Kor)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_timedomRomInfo, md_timedomRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sol-Deace (USA) +static struct BurnRomInfo md_soldeaceRomDesc[] = { + { "sol-deace (usa).bin", 0x100000, 0xa77e4e9f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soldeace) +STD_ROM_FN(md_soldeace) + +struct BurnDriver BurnDrvmd_soldeace = { + "md_soldeace", NULL, NULL, NULL, "1992", + "Sol-Deace (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soldeaceRomInfo, md_soldeaceRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soleil (Euro) +static struct BurnRomInfo md_soleilRomDesc[] = { + { "mpr-17499.bin", 0x200000, 0xa30ebdb1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soleil) +STD_ROM_FN(md_soleil) + +struct BurnDriver BurnDrvmd_soleil = { + "md_soleil", NULL, NULL, NULL, "1994", + "Soleil (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_soleilRomInfo, md_soleilRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crusader of Centy (USA) +static struct BurnRomInfo md_crusaderRomDesc[] = { + { "crusader of centy (usa).bin", 0x200000, 0x41858f6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crusader) +STD_ROM_FN(md_crusader) + +struct BurnDriver BurnDrvmd_crusader = { + "md_crusader", "md_soleil", NULL, NULL, "1994", + "Crusader of Centy (USA)\0", NULL, "Atlus", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_crusaderRomInfo, md_crusaderRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shin Souseiki Ragnacenty (Jpn) +static struct BurnRomInfo md_ragnacenRomDesc[] = { + { "shin souseiki ragnacenty (jpn).bin", 0x200000, 0x6a3f5ae2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ragnacen) +STD_ROM_FN(md_ragnacen) + +struct BurnDriver BurnDrvmd_ragnacen = { + "md_ragnacen", "md_soleil", NULL, NULL, "1994", + "Shin Souseiki Ragnacenty (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ragnacenRomInfo, md_ragnacenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shin Souseiki Ragnacenty (Jpn, Prototype) +static struct BurnRomInfo md_ragnacenpRomDesc[] = { + { "shin souseiki ragnacenty (jpn) (beta).bin", 0x100000, 0x43797455, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ragnacenp) +STD_ROM_FN(md_ragnacenp) + +struct BurnDriver BurnDrvmd_ragnacenp = { + "md_ragnacenp", "md_soleil", NULL, NULL, "1994", + "Shin Souseiki Ragnacenty (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ragnacenpRomInfo, md_ragnacenpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ragnacenty (Kor) +static struct BurnRomInfo md_ragnacenkRomDesc[] = { + { "ragnacenty (kor).bin", 0x200000, 0x77b5b10b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ragnacenk) +STD_ROM_FN(md_ragnacenk) + +struct BurnDriver BurnDrvmd_ragnacenk = { + "md_ragnacenk", "md_soleil", NULL, NULL, "1994", + "Ragnacenty (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ragnacenkRomInfo, md_ragnacenkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (World) +static struct BurnRomInfo md_skRomDesc[] = { + { "sonic & knuckles (world).bin", 0x200000, 0x0658f691, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sk) +STD_ROM_FN(md_sk) + +struct BurnDriver BurnDrvmd_sk = { + "md_sk", NULL, NULL, NULL, "1994", + "Sonic & Knuckles (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skRomInfo, md_skRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0525, 19940525, 15.28) +static struct BurnRomInfo md_skp12RomDesc[] = { + { "sonic & knuckles (prototype 0525 - may 25, 1994, 15.28).bin", 0x400000, 0x8e8dadd0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp12) +STD_ROM_FN(md_skp12) + +struct BurnDriver BurnDrvmd_skp12 = { + "md_skp12", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0525, 19940525, 15.28)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp12RomInfo, md_skp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0606, 19940606, 10.02) +static struct BurnRomInfo md_skp10RomDesc[] = { + { "sonic & knuckles (prototype 0606 - jun 06, 1994, 10.02).bin", 0x200000, 0x03a52f63, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp10) +STD_ROM_FN(md_skp10) + +struct BurnDriver BurnDrvmd_skp10 = { + "md_skp10", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0606, 19940606, 10.02)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp10RomInfo, md_skp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0608, 19940608, 05.03) +static struct BurnRomInfo md_skp08RomDesc[] = { + { "sonic & knuckles (prototype 0608 - jun 08, 1994, 05.03).bin", 0x200000, 0x7a6c1317, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp08) +STD_ROM_FN(md_skp08) + +struct BurnDriver BurnDrvmd_skp08 = { + "md_skp08", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0608, 19940608, 05.03)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp08RomInfo, md_skp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0610, 19940610, 07.49) +static struct BurnRomInfo md_skp06RomDesc[] = { + { "sonic & knuckles (prototype 0610 - jun 10, 1994, 07.49).bin", 0x200000, 0x7092f368, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp06) +STD_ROM_FN(md_skp06) + +struct BurnDriver BurnDrvmd_skp06 = { + "md_skp06", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0610, 19940610, 07.49)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp06RomInfo, md_skp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0612, 19940612, 18.27) +static struct BurnRomInfo md_skp04RomDesc[] = { + { "sonic & knuckles (prototype 0612 - jun 12, 1994, 18.27).bin", 0x200000, 0xb0a253e8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp04) +STD_ROM_FN(md_skp04) + +struct BurnDriver BurnDrvmd_skp04 = { + "md_skp04", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0612, 19940612, 18.27)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp04RomInfo, md_skp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0618, 19940618, 09.15) +static struct BurnRomInfo md_skp02RomDesc[] = { + { "sonic & knuckles (prototype 0618 - jun 18, 1994, 09.15).bin", 0x200000, 0x2615f5dc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp02) +STD_ROM_FN(md_skp02) + +struct BurnDriver BurnDrvmd_skp02 = { + "md_skp02", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0618, 19940618, 09.15)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp02RomInfo, md_skp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0619, 19940619, 08.18) +static struct BurnRomInfo md_skp01RomDesc[] = { + { "sonic & knuckles (prototype 0619 - jun 19, 1994, 08.18).bin", 0x200000, 0x1ea5b9d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp01) +STD_ROM_FN(md_skp01) + +struct BurnDriver BurnDrvmd_skp01 = { + "md_skp01", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0619, 19940619, 08.18)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp01RomInfo, md_skp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0606, 19940605, 22.25, S2K chip) +static struct BurnRomInfo md_skp11RomDesc[] = { + { "sonic & knuckles (s2k chip) (prototype 0606 - jun 05, 1994, 22.25).bin", 0x040000, 0xbd619ea9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp11) +STD_ROM_FN(md_skp11) + +struct BurnDriver BurnDrvmd_skp11 = { + "md_skp11", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0606, 19940605, 22.25, S2K chip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp11RomInfo, md_skp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0608, 19940608, 03.35, S2K chip) +static struct BurnRomInfo md_skp09RomDesc[] = { + { "sonic & knuckles (s2k chip) (prototype 0608 - jun 08, 1994, 03.35).bin", 0x040000, 0x6a5dcbe6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp09) +STD_ROM_FN(md_skp09) + +struct BurnDriver BurnDrvmd_skp09 = { + "md_skp09", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0608, 19940608, 03.35, S2K chip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp09RomInfo, md_skp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0610, 19940610, 03.11, S2K chip) +static struct BurnRomInfo md_skp07RomDesc[] = { + { "sonic & knuckles (s2k chip) (prototype 0610 - jun 10, 1994, 03.11).bin", 0x040000, 0x0f6ff22b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp07) +STD_ROM_FN(md_skp07) + +struct BurnDriver BurnDrvmd_skp07 = { + "md_skp07", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0610, 19940610, 03.11, S2K chip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp07RomInfo, md_skp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0612, 19940612, 18.18, S2K chip) +static struct BurnRomInfo md_skp05RomDesc[] = { + { "sonic & knuckles (s2k chip) (prototype 0612 - jun 12, 1994, 18.18).bin", 0x040000, 0x9a5f8183, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp05) +STD_ROM_FN(md_skp05) + +struct BurnDriver BurnDrvmd_skp05 = { + "md_skp05", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0612, 19940612, 18.18, S2K chip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp05RomInfo, md_skp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles (Prototype 0618, 19940618, 9.07, S2K chip) +static struct BurnRomInfo md_skp03RomDesc[] = { + { "sonic & knuckles (s2k chip) (prototype 0618 - jun 18, 1994, 9.07).bin", 0x040000, 0x4dcfd55c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skp03) +STD_ROM_FN(md_skp03) + +struct BurnDriver BurnDrvmd_skp03 = { + "md_skp03", "md_sk", NULL, NULL, "1994", + "Sonic & Knuckles (Prototype 0618, 19940618, 9.07, S2K chip)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_skp03RomInfo, md_skp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles + Sonic the Hedgehog (World) +static struct BurnRomInfo md_sks1RomDesc[] = { + { "sonic & knuckles + sonic the hedgehog (world).bin", 0x280000, 0xe01f6ed5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sks1) +STD_ROM_FN(md_sks1) + +struct BurnDriver BurnDrvmd_sks1 = { + "md_sks1", NULL, NULL, NULL, "199?", + "Sonic & Knuckles + Sonic the Hedgehog (World)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sks1RomInfo, md_sks1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles + Sonic the Hedgehog 2 (World) +static struct BurnRomInfo md_sks2RomDesc[] = { + { "sonic & knuckles + sonic the hedgehog 2 (world).bin", 0x340000, 0x2ac1e7c6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sks2) +STD_ROM_FN(md_sks2) + +struct BurnDriver BurnDrvmd_sks2 = { + "md_sks2", NULL, NULL, NULL, "199?", + "Sonic & Knuckles + Sonic the Hedgehog 2 (World)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sks2RomInfo, md_sks2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Knuckles in Sonic 2 (Prototype 0524, 19940527, 10.46) +static struct BurnRomInfo md_knucklpRomDesc[] = { + { "knuckles in sonic 2 (prototype 0524 - may 27, 1994, 10.46).bin", 0x400000, 0x8878c1a8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_knucklp) +STD_ROM_FN(md_knucklp) + +struct BurnDriver BurnDrvmd_knucklp = { + "md_knucklp", "md_sks2", NULL, NULL, "199?", + "Knuckles in Sonic 2 (Prototype 0524, 19940527, 10.46)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_knucklpRomInfo, md_knucklpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic & Knuckles + Sonic the Hedgehog 3 (World) +static struct BurnRomInfo md_sks3RomDesc[] = { + { "sonic & knuckles + sonic the hedgehog 3 (world).bin", 0x400000, 0x63522553, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sks3) +STD_ROM_FN(md_sks3) + +struct BurnDriver BurnDrvmd_sks3 = { + "md_sks3", NULL, NULL, NULL, "199?", + "Sonic & Knuckles + Sonic the Hedgehog 3 (World)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sks3RomInfo, md_sks3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3C (Prototype 0408, 19940408, 17.29) +static struct BurnRomInfo md_sonic3cRomDesc[] = { + { "sonic 3c (prototype 0408 - apr 08, 1994, 17.29).bin", 0x400000, 0x59d23df5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3c) +STD_ROM_FN(md_sonic3c) + +struct BurnDriver BurnDrvmd_sonic3c = { + "md_sonic3c", "md_sks3", NULL, NULL, "199?", + "Sonic 3C (Prototype 0408, 19940408, 17.29)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3cRomInfo, md_sonic3cRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3C (Prototype 0517, 19940517, 17.08) +static struct BurnRomInfo md_sonic3caRomDesc[] = { + { "sonic 3c (prototype 0517 - may 17, 1994, 17.08).bin", 0x400000, 0x766c4b81, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3ca) +STD_ROM_FN(md_sonic3ca) + +struct BurnDriver BurnDrvmd_sonic3ca = { + "md_sonic3ca", "md_sks3", NULL, NULL, "199?", + "Sonic 3C (Prototype 0517, 19940517, 17.08)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3caRomInfo, md_sonic3caRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D - Flickies' Island (Euro) ~ Sonic 3D Blast (USA, Kor) +static struct BurnRomInfo md_s3dRomDesc[] = { + { "sonic 3d blast -- sonic 3d - flickies' island (euro, usa, kor).bin", 0x400000, 0x44a2ca44, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3d) +STD_ROM_FN(md_s3d) + +struct BurnDriver BurnDrvmd_s3d = { + "md_s3d", NULL, NULL, NULL, "1996", + "Sonic 3D - Flickies' Island (Euro) ~ Sonic 3D Blast (USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dRomInfo, md_s3dRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 73, 19960703, 13.58) +static struct BurnRomInfo md_s3dp8RomDesc[] = { + { "sonic 3d blast (prototype 73 - jul 03, 1996, 13.58).bin", 0x200000, 0x93b75e99, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp8) +STD_ROM_FN(md_s3dp8) + +struct BurnDriver BurnDrvmd_s3dp8 = { + "md_s3dp8", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 73, 19960703, 13.58)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp8RomInfo, md_s3dp8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 814, 19960815, 07.55) +static struct BurnRomInfo md_s3dp7RomDesc[] = { + { "sonic 3d blast (prototype 814 - aug 15, 1996, 07.55).bin", 0x400000, 0xd64e7675, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp7) +STD_ROM_FN(md_s3dp7) + +struct BurnDriver BurnDrvmd_s3dp7 = { + "md_s3dp7", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 814, 19960815, 07.55)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp7RomInfo, md_s3dp7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 819, 19960819, 19.49) +static struct BurnRomInfo md_s3dp6RomDesc[] = { + { "sonic 3d blast (prototype 819 - aug 19, 1996, 19.49).bin", 0x400000, 0x2c43f43a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp6) +STD_ROM_FN(md_s3dp6) + +struct BurnDriver BurnDrvmd_s3dp6 = { + "md_s3dp6", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 819, 19960819, 19.49)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp6RomInfo, md_s3dp6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 825, 19960826, 15.46) +static struct BurnRomInfo md_s3dp5RomDesc[] = { + { "sonic 3d blast (prototype 825 - aug 26, 1996, 15.46).bin", 0x400000, 0x465bcfbd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp5) +STD_ROM_FN(md_s3dp5) + +struct BurnDriver BurnDrvmd_s3dp5 = { + "md_s3dp5", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 825, 19960826, 15.46)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp5RomInfo, md_s3dp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 830, 19960831, 08.19) +static struct BurnRomInfo md_s3dp4RomDesc[] = { + { "sonic 3d blast (prototype 830 - aug 31, 1996, 08.19).bin", 0x3fff06, 0x57640422, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp4) +STD_ROM_FN(md_s3dp4) + +struct BurnDriver BurnDrvmd_s3dp4 = { + "md_s3dp4", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 830, 19960831, 08.19)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp4RomInfo, md_s3dp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 831, 19960903, 10.07) +static struct BurnRomInfo md_s3dp3RomDesc[] = { + { "sonic 3d blast (prototype 831 - sep 03, 1996, 10.07).bin", 0x400000, 0x5933e453, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp3) +STD_ROM_FN(md_s3dp3) + +struct BurnDriver BurnDrvmd_s3dp3 = { + "md_s3dp3", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 831, 19960903, 10.07)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp3RomInfo, md_s3dp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (Prototype 94, 19960904, 12.01) +static struct BurnRomInfo md_s3dp2RomDesc[] = { + { "sonic 3d blast (prototype 94 - sep 04, 1996, 12.01).bin", 0x400000, 0x2f2a4271, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp2) +STD_ROM_FN(md_s3dp2) + +struct BurnDriver BurnDrvmd_s3dp2 = { + "md_s3dp2", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (Prototype 94, 19960904, 12.01)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp2RomInfo, md_s3dp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic 3D Blast (USA, Prototype) +static struct BurnRomInfo md_s3dp1RomDesc[] = { + { "sonic 3d blast (usa) (beta).bin", 0x400000, 0xd20f385b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s3dp1) +STD_ROM_FN(md_s3dp1) + +struct BurnDriver BurnDrvmd_s3dp1 = { + "md_s3dp1", "md_s3d", NULL, NULL, "1996", + "Sonic 3D Blast (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_s3dp1RomInfo, md_s3dp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Compilation (Euro) ~ Sonic Classics (USA, Kor) +static struct BurnRomInfo md_soniccmpRomDesc[] = { + { "mpr-19693.bin", 0x400000, 0xc696aee3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soniccmp) +STD_ROM_FN(md_soniccmp) + +struct BurnDriver BurnDrvmd_soniccmp = { + "md_soniccmp", NULL, NULL, NULL, "1995", + "Sonic Compilation (Euro) ~ Sonic Classics (USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_soniccmpRomInfo, md_soniccmpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Crackers (Jpn, Prototype) +static struct BurnRomInfo md_scrackRomDesc[] = { + { "sonic crackers (jpn) (prototype).bin", 0x100000, 0x7fada88d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_scrack) +STD_ROM_FN(md_scrack) + +struct BurnDriver BurnDrvmd_scrack = { + "md_scrack", NULL, NULL, NULL, "199?", + "Sonic Crackers (Jpn, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_scrackRomInfo, md_scrackRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Eraser (Jpn, SegaNet) +static struct BurnRomInfo md_sonicerRomDesc[] = { + { "sonic eraser (jpn) (sn).bin", 0x040000, 0x62d8a0e7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicer) +STD_ROM_FN(md_sonicer) + +struct BurnDriver BurnDrvmd_sonicer = { + "md_sonicer", NULL, NULL, NULL, "1991", + "Sonic Eraser (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicerRomInfo, md_sonicerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Jam 6 +static struct BurnRomInfo md_sonicjamRomDesc[] = { + { "sonic jam 6 (unl).bin", 0x200000, 0xbf39d897, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicjam) +STD_ROM_FN(md_sonicjam) + +struct BurnDriver BurnDrvmd_sonicjam = { + "md_sonicjam", NULL, NULL, NULL, "199?", + "Sonic Jam 6\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicjamRomInfo, md_sonicjamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Jam 6 (Alt) +static struct BurnRomInfo md_sonicjam1RomDesc[] = { + { "sonic jam 6 (unl) (pirate).bin", 0x200000, 0x04f0c93e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicjam1) +STD_ROM_FN(md_sonicjam1) + +struct BurnDriver BurnDrvmd_sonicjam1 = { + "md_sonicjam1", "md_sonicjam", NULL, NULL, "199?", + "Sonic Jam 6 (Alt)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicjam1RomInfo, md_sonicjam1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Spinball (Prototype) +static struct BurnRomInfo md_sspinpRomDesc[] = { + { "sonic spinball (beta).bin", 0x140000, 0xb1524979, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sspinp) +STD_ROM_FN(md_sspinp) + +struct BurnDriver BurnDrvmd_sspinp = { + "md_sspinp", "md_sspin", NULL, NULL, "1993", + "Sonic Spinball (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sspinpRomInfo, md_sspinpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Spinball (Jpn) +static struct BurnRomInfo md_sspinjRomDesc[] = { + { "sonic spinball (jpn).bin", 0x100000, 0xacd08ce8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sspinj) +STD_ROM_FN(md_sspinj) + +struct BurnDriver BurnDrvmd_sspinj = { + "md_sspinj", "md_sspin", NULL, NULL, "1993", + "Sonic Spinball (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sspinjRomInfo, md_sspinjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Spinball (USA) +static struct BurnRomInfo md_sspinuRomDesc[] = { + { "sonic spinball (usa).bin", 0x100000, 0x677206cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sspinu) +STD_ROM_FN(md_sspinu) + +struct BurnDriver BurnDrvmd_sspinu = { + "md_sspinu", "md_sspin", NULL, NULL, "1993", + "Sonic Spinball (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sspinuRomInfo, md_sspinuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Spinball (USA, Alt) +static struct BurnRomInfo md_sspinuaRomDesc[] = { + { "sonic spinball (usa) (alt).bin", 0x100000, 0xe9960371, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sspinua) +STD_ROM_FN(md_sspinua) + +struct BurnDriver BurnDrvmd_sspinua = { + "md_sspinua", "md_sspin", NULL, NULL, "1993", + "Sonic Spinball (USA, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sspinuaRomInfo, md_sspinuaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog (Euro, USA) +static struct BurnRomInfo md_sonicRomDesc[] = { + { "mpr-13913.bin", 0x080000, 0xf9394e97, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic) +STD_ROM_FN(md_sonic) + +struct BurnDriver BurnDrvmd_sonic = { + "md_sonic", NULL, NULL, NULL, "1991", + "Sonic the Hedgehog (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicRomInfo, md_sonicRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog (Jpn, Kor) +static struct BurnRomInfo md_sonicjRomDesc[] = { + { "mpr-13933.bin", 0x080000, 0xafe05eee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicj) +STD_ROM_FN(md_sonicj) + +struct BurnDriver BurnDrvmd_sonicj = { + "md_sonicj", "md_sonic", NULL, NULL, "1991", + "Sonic the Hedgehog (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicjRomInfo, md_sonicjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog (Pirate, Ripped from Golden 10 in 1) +static struct BurnRomInfo md_sonicpirRomDesc[] = { + { "sonic the hedgehog (euro, usa) (pirate).bin", 0x080000, 0x7a093f0b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicpir) +STD_ROM_FN(md_sonicpir) + +struct BurnDriver BurnDrvmd_sonicpir = { + "md_sonicpir", "md_sonic", NULL, NULL, "1991?", + "Sonic the Hedgehog (Pirate, Ripped from Golden 10 in 1)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicpirRomInfo, md_sonicpirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (World, Rev. A) +static struct BurnRomInfo md_sonic2RomDesc[] = { + { "mpr-15000a.bin", 0x100000, 0x7b905383, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2) +STD_ROM_FN(md_sonic2) + +struct BurnDriver BurnDrvmd_sonic2 = { + "md_sonic2", NULL, NULL, NULL, "1992", + "Sonic the Hedgehog 2 (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2RomInfo, md_sonic2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (World) +static struct BurnRomInfo md_sonic2aRomDesc[] = { + { "sonic the hedgehog 2 (world).bin", 0x100000, 0x24ab4c3a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2a) +STD_ROM_FN(md_sonic2a) + +struct BurnDriver BurnDrvmd_sonic2a = { + "md_sonic2a", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2aRomInfo, md_sonic2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 4, 19920918, 16.26) +static struct BurnRomInfo md_sonic2p8RomDesc[] = { + { "sonic the hedgehog 2 (beta 4 - sep 18, 1992, 16.26).bin", 0x100000, 0x8fda5cc5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p8) +STD_ROM_FN(md_sonic2p8) + +struct BurnDriver BurnDrvmd_sonic2p8 = { + "md_sonic2p8", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 4, 19920918, 16.26)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p8RomInfo, md_sonic2p8RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 5, 19920921, 12.06) +static struct BurnRomInfo md_sonic2p7RomDesc[] = { + { "sonic the hedgehog 2 (beta 5 - sep 21, 1992, 12.06).bin", 0x100000, 0x066b9a89, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p7) +STD_ROM_FN(md_sonic2p7) + +struct BurnDriver BurnDrvmd_sonic2p7 = { + "md_sonic2p7", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 5, 19920921, 12.06)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p7RomInfo, md_sonic2p7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 6, 19920922, 18.47) +static struct BurnRomInfo md_sonic2p6RomDesc[] = { + { "sonic the hedgehog 2 (beta 6 - sep 22, 1992, 18.47).bin", 0x100000, 0xcebc64e0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p6) +STD_ROM_FN(md_sonic2p6) + +struct BurnDriver BurnDrvmd_sonic2p6 = { + "md_sonic2p6", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 6, 19920922, 18.47)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p6RomInfo, md_sonic2p6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 6, 19920922, 19.42) +static struct BurnRomInfo md_sonic2p5RomDesc[] = { + { "sonic the hedgehog 2 (beta 6 - sep 22, 1992, 19.42).bin", 0x100000, 0xcb036e6c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p5) +STD_ROM_FN(md_sonic2p5) + +struct BurnDriver BurnDrvmd_sonic2p5 = { + "md_sonic2p5", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 6, 19920922, 19.42)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p5RomInfo, md_sonic2p5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 7, 19920924, 09.26) +static struct BurnRomInfo md_sonic2p4RomDesc[] = { + { "sonic the hedgehog 2 (beta 7 - sep 24, 1992, 09.26).bin", 0x100000, 0xdc7be12c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p4) +STD_ROM_FN(md_sonic2p4) + +struct BurnDriver BurnDrvmd_sonic2p4 = { + "md_sonic2p4", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 7, 19920924, 09.26)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p4RomInfo, md_sonic2p4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Beta 8, 19920924, 19.27) +static struct BurnRomInfo md_sonic2p3RomDesc[] = { + { "sonic the hedgehog 2 (beta 8 - sep 24, 1992, 19.27).bin", 0x100000, 0x6089fadd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p3) +STD_ROM_FN(md_sonic2p3) + +struct BurnDriver BurnDrvmd_sonic2p3 = { + "md_sonic2p3", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Beta 8, 19920924, 19.27)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p3RomInfo, md_sonic2p3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (Prototype) +static struct BurnRomInfo md_sonic2p2RomDesc[] = { + { "sonic the hedgehog 2 (prototype).bin", 0x100000, 0xeea21b5c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p2) +STD_ROM_FN(md_sonic2p2) + +struct BurnDriver BurnDrvmd_sonic2p2 = { + "md_sonic2p2", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p2RomInfo, md_sonic2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (World, Rev. 01a) +static struct BurnRomInfo md_sonic2bRomDesc[] = { + { "sonic the hedgehog 2 (world) (rev 01a).bin", 0x100000, 0x92d8817d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2b) +STD_ROM_FN(md_sonic2b) + +struct BurnDriver BurnDrvmd_sonic2b = { + "md_sonic2b", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (World, Rev. 01a)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2bRomInfo, md_sonic2bRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (World, Rev. SC02) +static struct BurnRomInfo md_sonic2cRomDesc[] = { + { "sonic the hedgehog 2 (world) (rev sc02).bin", 0x100000, 0xf23ad4b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2c) +STD_ROM_FN(md_sonic2c) + +struct BurnDriver BurnDrvmd_sonic2c = { + "md_sonic2c", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (World, Rev. SC02)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2cRomInfo, md_sonic2cRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 2 (World, Prototype) +static struct BurnRomInfo md_sonic2p1RomDesc[] = { + { "sonic the hedgehog 2 (world) (beta).bin", 0x100000, 0x39faaa70, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic2p1) +STD_ROM_FN(md_sonic2p1) + +struct BurnDriver BurnDrvmd_sonic2p1 = { + "md_sonic2p1", "md_sonic2", NULL, NULL, "1992", + "Sonic the Hedgehog 2 (World, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonic2p1RomInfo, md_sonic2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 3 (Pirate) +static struct BurnRomInfo md_sonic3pirRomDesc[] = { + { "sonic the hedgehog 3 (pirate).bin", 0x200000, 0xc818f6fd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3pir) +STD_ROM_FN(md_sonic3pir) + +struct BurnDriver BurnDrvmd_sonic3pir = { + "md_sonic3pir", "md_sonic3", NULL, NULL, "1994?", + "Sonic the Hedgehog 3 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3pirRomInfo, md_sonic3pirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic the Hedgehog 3 (USA) +static struct BurnRomInfo md_sonic3uRomDesc[] = { + { "sonic the hedgehog 3 (usa).bin", 0x200000, 0x9bc192ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonic3u) +STD_ROM_FN(md_sonic3u) + +struct BurnDriver BurnDrvmd_sonic3u = { + "md_sonic3u", "md_sonic3", NULL, NULL, "1994", + "Sonic the Hedgehog 3 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sonic3uRomInfo, md_sonic3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sorcerer's Kingdom (USA, v1.1) +static struct BurnRomInfo md_sorcerkRomDesc[] = { + { "sorcerer's kingdom (usa) (v1.1).bin", 0x100000, 0xbb1fc9ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sorcerk) +STD_ROM_FN(md_sorcerk) + +struct BurnDriver BurnDrvmd_sorcerk = { + "md_sorcerk", NULL, NULL, NULL, "1992", + "Sorcerer's Kingdom (USA, v1.1)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sorcerkRomInfo, md_sorcerkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sorcerer's Kingdom (USA) +static struct BurnRomInfo md_sorcerk1RomDesc[] = { + { "sorcerer's kingdom (usa).bin", 0x100000, 0xcbe6c1ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sorcerk1) +STD_ROM_FN(md_sorcerk1) + +struct BurnDriver BurnDrvmd_sorcerk1 = { + "md_sorcerk1", "md_sorcerk", NULL, NULL, "1992", + "Sorcerer's Kingdom (USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sorcerk1RomInfo, md_sorcerk1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sorcer Kingdom (Jpn) +static struct BurnRomInfo md_sorcerkjRomDesc[] = { + { "sorcer kingdom (jpn).bin", 0x100000, 0x944135ca, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sorcerkj) +STD_ROM_FN(md_sorcerkj) + +struct BurnDriver BurnDrvmd_sorcerkj = { + "md_sorcerkj", "md_sorcerk", NULL, NULL, "1992", + "Sorcer Kingdom (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sorcerkjRomInfo, md_sorcerkjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sorcerian (Jpn) +static struct BurnRomInfo md_sorcernRomDesc[] = { + { "mpr-12906.bin", 0x080000, 0xa143a8c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sorcern) +STD_ROM_FN(md_sorcern) + +struct BurnDriver BurnDrvmd_sorcern = { + "md_sorcern", NULL, NULL, NULL, "1990", + "Sorcerian (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sorcernRomInfo, md_sorcernRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Space Harrier II (Jpn, Launch Cart) +static struct BurnRomInfo md_sharrjRomDesc[] = { + { "mpr-11934.bin", 0x080000, 0xedc0fb28, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sharrj) +STD_ROM_FN(md_sharrj) + +struct BurnDriver BurnDrvmd_sharrj = { + "md_sharrj", "md_sharr", NULL, NULL, "1988", + "Space Harrier II (Jpn, Launch Cart)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sharrjRomInfo, md_sharrjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Space Invaders 91 (USA) +static struct BurnRomInfo md_sinv91RomDesc[] = { + { "space invaders 91 (usa).bin", 0x040000, 0xbb83b528, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sinv91) +STD_ROM_FN(md_sinv91) + +struct BurnDriver BurnDrvmd_sinv91 = { + "md_sinv91", NULL, NULL, NULL, "1991", + "Space Invaders 91 (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sinv91RomInfo, md_sinv91RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Space Invaders 90 (Jpn) +static struct BurnRomInfo md_sinv90RomDesc[] = { + { "space invaders 90 (jpn).bin", 0x040000, 0x22adbd66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sinv90) +STD_ROM_FN(md_sinv90) + +struct BurnDriver BurnDrvmd_sinv90 = { + "md_sinv90", "md_sinv91", NULL, NULL, "1990", + "Space Invaders 90 (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sinv90RomInfo, md_sinv90RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sparkster (Euro) +static struct BurnRomInfo md_sparksRomDesc[] = { + { "sparkster (euro).bin", 0x100000, 0xd63e9f2d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sparks) +STD_ROM_FN(md_sparks) + +struct BurnDriver BurnDrvmd_sparks = { + "md_sparks", NULL, NULL, NULL, "1994", + "Sparkster (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sparksRomInfo, md_sparksRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sparkster (USA) +static struct BurnRomInfo md_sparksuRomDesc[] = { + { "sparkster (usa).bin", 0x100000, 0x6bdb14ed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sparksu) +STD_ROM_FN(md_sparksu) + +struct BurnDriver BurnDrvmd_sparksu = { + "md_sparksu", "md_sparks", NULL, NULL, "1994", + "Sparkster (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sparksuRomInfo, md_sparksuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sparkster - Rocket Knight Adventures 2 (Jpn) +static struct BurnRomInfo md_sparksjRomDesc[] = { + { "sparkster - rocket knight adventures 2 (jpn).bin", 0x100000, 0x914ec662, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sparksj) +STD_ROM_FN(md_sparksj) + +struct BurnDriver BurnDrvmd_sparksj = { + "md_sparksj", "md_sparks", NULL, NULL, "1994", + "Sparkster - Rocket Knight Adventures 2 (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sparksjRomInfo, md_sparksjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Speedball 2 (Euro) +static struct BurnRomInfo md_speedbl2RomDesc[] = { + { "mpr-14990.bin", 0x080000, 0x056a6e03, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_speedbl2) +STD_ROM_FN(md_speedbl2) + +struct BurnDriver BurnDrvmd_speedbl2 = { + "md_speedbl2", NULL, NULL, NULL, "1992", + "Speedball 2 (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_speedbl2RomInfo, md_speedbl2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Speedball 2 (Jpn) +static struct BurnRomInfo md_speedbl2jRomDesc[] = { + { "speedball 2 (jpn).bin", 0x080000, 0xf5442334, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_speedbl2j) +STD_ROM_FN(md_speedbl2j) + +struct BurnDriver BurnDrvmd_speedbl2j = { + "md_speedbl2j", "md_speedbl2", NULL, NULL, "1992", + "Speedball 2 (Jpn)\0", NULL, "CRI", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_speedbl2jRomInfo, md_speedbl2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Speedball 2 - Brutal Deluxe (USA) +static struct BurnRomInfo md_speedbl2uRomDesc[] = { + { "speedball 2 - brutal deluxe (usa).bin", 0x080000, 0x9fc340a7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_speedbl2u) +STD_ROM_FN(md_speedbl2u) + +struct BurnDriver BurnDrvmd_speedbl2u = { + "md_speedbl2u", "md_speedbl2", NULL, NULL, "1991", + "Speedball 2 - Brutal Deluxe (USA)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_speedbl2uRomInfo, md_speedbl2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man (Euro, USA) +static struct BurnRomInfo md_spidermnRomDesc[] = { + { "spider-man (euro, usa) (acclaim).bin", 0x200000, 0x11b5b590, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidermn) +STD_ROM_FN(md_spidermn) + +struct BurnDriver BurnDrvmd_spidermn = { + "md_spidermn", NULL, NULL, NULL, "1995", + "Spider-Man (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidermnRomInfo, md_spidermnRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man (USA, Prototype) +static struct BurnRomInfo md_spidermnp1RomDesc[] = { + { "spider-man (usa) (acclaim) (beta).bin", 0x200000, 0xb88a710d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidermnp1) +STD_ROM_FN(md_spidermnp1) + +struct BurnDriver BurnDrvmd_spidermnp1 = { + "md_spidermnp1", "md_spidermn", NULL, NULL, "1995", + "Spider-Man (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidermnp1RomInfo, md_spidermnp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man (USA, Prototype, Earlier) +static struct BurnRomInfo md_spidermnp2RomDesc[] = { + { "spider-man (usa) (acclaim) (beta) (earlier).bin", 0x200000, 0x83e1fe76, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidermnp2) +STD_ROM_FN(md_spidermnp2) + +struct BurnDriver BurnDrvmd_spidermnp2 = { + "md_spidermnp2", "md_spidermn", NULL, NULL, "1995", + "Spider-Man (USA, Prototype, Earlier)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidermnp2RomInfo, md_spidermnp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man vs. the Kingpin (World) +static struct BurnRomInfo md_spidvskpRomDesc[] = { + { "mpr-14027.bin", 0x080000, 0x70ab775f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidvskp) +STD_ROM_FN(md_spidvskp) + +struct BurnDriver BurnDrvmd_spidvskp = { + "md_spidvskp", NULL, NULL, NULL, "1991", + "Spider-Man vs. the Kingpin (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidvskpRomInfo, md_spidvskpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spider-Man & Venom - Maximum Carnage (World) +static struct BurnRomInfo md_spidmaxcRomDesc[] = { + { "spider-man and venom - maximum carnage (world).bin", 0x200000, 0x8fa0b6e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spidmaxc) +STD_ROM_FN(md_spidmaxc) + +struct BurnDriver BurnDrvmd_spidmaxc = { + "md_spidmaxc", NULL, NULL, NULL, "1994", + "Spider-Man & Venom - Maximum Carnage (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spidmaxcRomInfo, md_spidmaxcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Venom & Spider-Man - Separation Anxiety (Euro, USA) +static struct BurnRomInfo md_venomRomDesc[] = { + { "spider-man and venom - separation anxiety (euro, usa).bin", 0x300000, 0x512ade32, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_venom) +STD_ROM_FN(md_venom) + +struct BurnDriver BurnDrvmd_venom = { + "md_venom", NULL, NULL, NULL, "1995", + "Venom & Spider-Man - Separation Anxiety (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_venomRomInfo, md_venomRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spiritual Warfare (USA) +static struct BurnRomInfo md_spiritRomDesc[] = { + { "spiritual warfare (usa) (unl).bin", 0x080000, 0xd9a364ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spirit) +STD_ROM_FN(md_spirit) + +struct BurnDriver BurnDrvmd_spirit = { + "md_spirit", NULL, NULL, NULL, "1994", + "Spiritual Warfare (USA)\0", NULL, "Wisdom Tree", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spiritRomInfo, md_spiritRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spirou (Euro) +static struct BurnRomInfo md_spirouRomDesc[] = { + { "spirou (euro).bin", 0x100000, 0x6634b130, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spirou) +STD_ROM_FN(md_spirou) + +struct BurnDriver BurnDrvmd_spirou = { + "md_spirou", NULL, NULL, NULL, "1996", + "Spirou (Euro)\0", NULL, "Infogrames", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spirouRomInfo, md_spirouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Splatterhouse 2 (Euro) +static struct BurnRomInfo md_splatt2RomDesc[] = { + { "splatterhouse 2 (euro).bin", 0x100000, 0x2559e03c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_splatt2) +STD_ROM_FN(md_splatt2) + +struct BurnDriver BurnDrvmd_splatt2 = { + "md_splatt2", NULL, NULL, NULL, "1992", + "Splatterhouse 2 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_splatt2RomInfo, md_splatt2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Splatterhouse 2 (USA) +static struct BurnRomInfo md_splatt2uRomDesc[] = { + { "splatterhouse 2 (usa).bin", 0x100000, 0x2d1766e9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_splatt2u) +STD_ROM_FN(md_splatt2u) + +struct BurnDriver BurnDrvmd_splatt2u = { + "md_splatt2u", "md_splatt2", NULL, NULL, "1992", + "Splatterhouse 2 (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_splatt2uRomInfo, md_splatt2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Splatterhouse 3 (USA) +static struct BurnRomInfo md_splatt3RomDesc[] = { + { "splatterhouse 3 (usa).bin", 0x200000, 0x00f05d07, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_splatt3) +STD_ROM_FN(md_splatt3) + +struct BurnDriver BurnDrvmd_splatt3 = { + "md_splatt3", NULL, NULL, NULL, "1993", + "Splatterhouse 3 (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_splatt3RomInfo, md_splatt3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Splatterhouse Part 3 (Jpn, Kor) +static struct BurnRomInfo md_splatt3jRomDesc[] = { + { "splatterhouse part 3 (jpn, kor).bin", 0x200000, 0x31b83d22, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_splatt3j) +STD_ROM_FN(md_splatt3j) + +struct BurnDriver BurnDrvmd_splatt3j = { + "md_splatt3j", "md_splatt3", NULL, NULL, "1993", + "Splatterhouse Part 3 (Jpn, Kor)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_splatt3jRomInfo, md_splatt3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sport Games (Bra) +static struct BurnRomInfo md_sportgRomDesc[] = { + { "sport games (bra).bin", 0x200000, 0x7e3ecabf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sportg) +STD_ROM_FN(md_sportg) + +struct BurnDriver BurnDrvmd_sportg = { + "md_sportg", NULL, NULL, NULL, "199?", + "Sport Games (Bra)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sportgRomInfo, md_sportgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sports Talk Baseball (USA) +static struct BurnRomInfo md_sporttbbRomDesc[] = { + { "sports talk baseball (usa).bin", 0x100000, 0x0deb79c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sporttbb) +STD_ROM_FN(md_sporttbb) + +struct BurnDriver BurnDrvmd_sporttbb = { + "md_sporttbb", NULL, NULL, NULL, "1992", + "Sports Talk Baseball (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_sporttbbRomInfo, md_sporttbbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spot Goes to Hollywood (Euro) +static struct BurnRomInfo md_spotgoRomDesc[] = { + { "mpr-18680+mpr-18681.bin", 0x300000, 0xfbe254ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spotgo) +STD_ROM_FN(md_spotgo) + +struct BurnDriver BurnDrvmd_spotgo = { + "md_spotgo", NULL, NULL, NULL, "1996", + "Spot Goes to Hollywood (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spotgoRomInfo, md_spotgoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Spot Goes to Hollywood (USA) +static struct BurnRomInfo md_spotgouRomDesc[] = { + { "spot goes to hollywood (usa).bin", 0x300000, 0xbdad1cbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_spotgou) +STD_ROM_FN(md_spotgou) + +struct BurnDriver BurnDrvmd_spotgou = { + "md_spotgou", "md_spotgo", NULL, NULL, "1995", + "Spot Goes to Hollywood (USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_spotgouRomInfo, md_spotgouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Control (USA) +static struct BurnRomInfo md_starctrlRomDesc[] = { + { "star control (usa).bin", 0x180000, 0x8e2bceaf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starctrl) +STD_ROM_FN(md_starctrl) + +struct BurnDriver BurnDrvmd_starctrl = { + "md_starctrl", NULL, NULL, NULL, "1991", + "Star Control (USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_starctrlRomInfo, md_starctrlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Cruiser (Jpn) +static struct BurnRomInfo md_starcrRomDesc[] = { + { "star cruiser (jpn).bin", 0x080000, 0x2b75b52f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starcr) +STD_ROM_FN(md_starcr) + +struct BurnDriver BurnDrvmd_starcr = { + "md_starcr", NULL, NULL, NULL, "1990", + "Star Cruiser (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_starcrRomInfo, md_starcrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - Deep Space Nine - Crossroads of Time (Euro) +static struct BurnRomInfo md_stds9RomDesc[] = { + { "star trek - deep space nine - crossroads of time (euro).bin", 0x100000, 0xd4b122f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stds9) +STD_ROM_FN(md_stds9) + +struct BurnDriver BurnDrvmd_stds9 = { + "md_stds9", NULL, NULL, NULL, "1995", + "Star Trek - Deep Space Nine - Crossroads of Time (Euro)\0", NULL, "Virgin Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stds9RomInfo, md_stds9RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - Deep Space Nine - Crossroads of Time (USA) +static struct BurnRomInfo md_stds9uRomDesc[] = { + { "star trek - deep space nine - crossroads of time (usa).bin", 0x100000, 0xa771e1a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stds9u) +STD_ROM_FN(md_stds9u) + +struct BurnDriver BurnDrvmd_stds9u = { + "md_stds9u", "md_stds9", NULL, NULL, "1995", + "Star Trek - Deep Space Nine - Crossroads of Time (USA)\0", NULL, "Playmates", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stds9uRomInfo, md_stds9uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (USA, v1.1) +static struct BurnRomInfo md_sttngRomDesc[] = { + { "star trek - the next generation - echoes from the past (usa) (v1.1).bin", 0x200000, 0xef840ef2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttng) +STD_ROM_FN(md_sttng) + +struct BurnDriver BurnDrvmd_sttng = { + "md_sttng", NULL, NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (USA, v1.1)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngRomInfo, md_sttngRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (USA) +static struct BurnRomInfo md_sttngaRomDesc[] = { + { "star trek - the next generation - echoes from the past (usa).bin", 0x200000, 0x272153fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttnga) +STD_ROM_FN(md_sttnga) + +struct BurnDriver BurnDrvmd_sttnga = { + "md_sttnga", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngaRomInfo, md_sttngaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19941228) +static struct BurnRomInfo md_sttngbRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - dec 28, 1994).bin", 0x200000, 0x3ba670f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttngb) +STD_ROM_FN(md_sttngb) + +struct BurnDriver BurnDrvmd_sttngb = { + "md_sttngb", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19941228)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngbRomInfo, md_sttngbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19941229) +static struct BurnRomInfo md_sttngcRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - dec 29, 1994).bin", 0x200000, 0x316bbc43, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttngc) +STD_ROM_FN(md_sttngc) + +struct BurnDriver BurnDrvmd_sttngc = { + "md_sttngc", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19941229)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngcRomInfo, md_sttngcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940103) +static struct BurnRomInfo md_sttngdRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - jan 03, 1994).bin", 0x200000, 0xcac86b68, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttngd) +STD_ROM_FN(md_sttngd) + +struct BurnDriver BurnDrvmd_sttngd = { + "md_sttngd", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940103)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngdRomInfo, md_sttngdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940110) +static struct BurnRomInfo md_sttngeRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - jan 10, 1994).bin", 0x200000, 0xd138ca3e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttnge) +STD_ROM_FN(md_sttnge) + +struct BurnDriver BurnDrvmd_sttnge = { + "md_sttnge", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940110)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngeRomInfo, md_sttngeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940118) +static struct BurnRomInfo md_sttngfRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - jan 18, 1994).bin", 0x200000, 0xd8dab97a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttngf) +STD_ROM_FN(md_sttngf) + +struct BurnDriver BurnDrvmd_sttngf = { + "md_sttngf", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940118)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttngfRomInfo, md_sttngfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940125) +static struct BurnRomInfo md_sttnggRomDesc[] = { + { "star trek - the next generation - echoes from the past (prototype - jan 25, 1994).bin", 0x200000, 0x63f29e6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sttngg) +STD_ROM_FN(md_sttngg) + +struct BurnDriver BurnDrvmd_sttngg = { + "md_sttngg", "md_sttng", NULL, NULL, "1994", + "Star Trek - The Next Generation - Echoes from the Past (Prototype, 19940125)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_sttnggRomInfo, md_sttnggRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Starflight (Euro, USA, v1.1) +static struct BurnRomInfo md_starflRomDesc[] = { + { "starflight (euro, usa) (v1.1).bin", 0x100000, 0x1217dbea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starfl) +STD_ROM_FN(md_starfl) + +struct BurnDriver BurnDrvmd_starfl = { + "md_starfl", NULL, NULL, NULL, "1991", + "Starflight (Euro, USA, v1.1)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_starflRomInfo, md_starflRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Starflight (Euro, USA) +static struct BurnRomInfo md_starfl1RomDesc[] = { + { "starflight (euro, usa).bin", 0x100000, 0xd550c928, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starfl1) +STD_ROM_FN(md_starfl1) + +struct BurnDriver BurnDrvmd_starfl1 = { + "md_starfl1", "md_starfl", NULL, NULL, "1991", + "Starflight (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_starfl1RomInfo, md_starfl1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Stargate (Euro, USA) +static struct BurnRomInfo md_stargateRomDesc[] = { + { "stargate (euro, usa).bin", 0x200000, 0xe587069e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stargate) +STD_ROM_FN(md_stargate) + +struct BurnDriver BurnDrvmd_stargate = { + "md_stargate", NULL, NULL, NULL, "1994", + "Stargate (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stargateRomInfo, md_stargateRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Stargate (Euro, Prototype) +static struct BurnRomInfo md_stargatepRomDesc[] = { + { "stargate (euro) (beta).bin", 0x200000, 0x8dc8ab23, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stargatep) +STD_ROM_FN(md_stargatep) + +struct BurnDriver BurnDrvmd_stargatep = { + "md_stargatep", "md_stargate", NULL, NULL, "1994", + "Stargate (Euro, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stargatepRomInfo, md_stargatepRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Steel Talons (Euro, USA) +static struct BurnRomInfo md_steeltalRomDesc[] = { + { "steel talons (euro, usa).bin", 0x080000, 0x10e4ec63, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_steeltal) +STD_ROM_FN(md_steeltal) + +struct BurnDriver BurnDrvmd_steeltal = { + "md_steeltal", NULL, NULL, NULL, "1992", + "Steel Talons (Euro, USA)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_steeltalRomInfo, md_steeltalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Steel Talons (Jpn, Kor) +static struct BurnRomInfo md_steeltaljRomDesc[] = { + { "steel talons (jpn, kor).bin", 0x080000, 0x04f388e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_steeltalj) +STD_ROM_FN(md_steeltalj) + +struct BurnDriver BurnDrvmd_steeltalj = { + "md_steeltalj", "md_steeltal", NULL, NULL, "1993", + "Steel Talons (Jpn, Kor)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_steeltaljRomInfo, md_steeltaljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Steel Talons (USA, Prototype) +static struct BurnRomInfo md_steeltalpRomDesc[] = { + { "steel talons (usa) (beta).bin", 0x080000, 0xc4052f18, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_steeltalp) +STD_ROM_FN(md_steeltalp) + +struct BurnDriver BurnDrvmd_steeltalp = { + "md_steeltalp", "md_steeltal", NULL, NULL, "1992", + "Steel Talons (USA, Prototype)\0", NULL, "Tengen", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_steeltalpRomInfo, md_steeltalpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Stone Protectors (USA, Prototype) +static struct BurnRomInfo md_stoneproRomDesc[] = { + { "stone protectors.bin", 0x200000, 0xfbf0d54f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stonepro) +STD_ROM_FN(md_stonepro) + +struct BurnDriver BurnDrvmd_stonepro = { + "md_stonepro", NULL, NULL, NULL, "1994", + "Stone Protectors (USA, Prototype)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stoneproRomInfo, md_stoneproRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Stormlord (USA) +static struct BurnRomInfo md_strmlordRomDesc[] = { + { "stormlord (usa).bin", 0x080000, 0x39ab50a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strmlord) +STD_ROM_FN(md_strmlord) + +struct BurnDriver BurnDrvmd_strmlord = { + "md_strmlord", NULL, NULL, NULL, "1990", + "Stormlord (USA)\0", NULL, "RazorSoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_strmlordRomInfo, md_strmlordRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Stormlord (Jpn) +static struct BurnRomInfo md_strmlordjRomDesc[] = { + { "stormlord (jpn).bin", 0x080000, 0x0b440fed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strmlordj) +STD_ROM_FN(md_strmlordj) + +struct BurnDriver BurnDrvmd_strmlordj = { + "md_strmlordj", "md_strmlord", NULL, NULL, "1990", + "Stormlord (Jpn)\0", NULL, "Micro World", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_strmlordjRomInfo, md_strmlordjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Euro) +static struct BurnRomInfo md_thorRomDesc[] = { + { "mpr-17588+mpr-17606.bin", 0x300000, 0x1110b0db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thor) +STD_ROM_FN(md_thor) + +struct BurnDriver BurnDrvmd_thor = { + "md_thor", NULL, NULL, NULL, "1995", + "The Story of Thor (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorRomInfo, md_thorRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Ger) +static struct BurnRomInfo md_thorgRomDesc[] = { + { "story of thor, the (germany).bin", 0x300000, 0xfa20d011, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorg) +STD_ROM_FN(md_thorg) + +struct BurnDriver BurnDrvmd_thorg = { + "md_thorg", "md_thor", NULL, NULL, "1995", + "The Story of Thor (Ger)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorgRomInfo, md_thorgRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor - Hikari o Tsugumono (Jpn) +static struct BurnRomInfo md_thorjRomDesc[] = { + { "story of thor, the - hikari o tsugumono (jpn).bin", 0x300000, 0x4f39783c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorj) +STD_ROM_FN(md_thorj) + +struct BurnDriver BurnDrvmd_thorj = { + "md_thorj", "md_thor", NULL, NULL, "1995", + "The Story of Thor - Hikari o Tsugumono (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorjRomInfo, md_thorjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Jpn, Prototype) +static struct BurnRomInfo md_thorjpRomDesc[] = { + { "story of thor, the (jpn) (beta) (bad dump).bin", 0x1b0000, 0xbfc11649, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorjp) +STD_ROM_FN(md_thorjp) + +struct BurnDriver BurnDrvmd_thorjp = { + "md_thorjp", "md_thor", NULL, NULL, "1994", + "The Story of Thor (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_thorjpRomInfo, md_thorjpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Kor) +static struct BurnRomInfo md_thorkRomDesc[] = { + { "story of thor, the (kor).bin", 0x300000, 0xee1603c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thork) +STD_ROM_FN(md_thork) + +struct BurnDriver BurnDrvmd_thork = { + "md_thork", "md_thor", NULL, NULL, "1995", + "The Story of Thor (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorkRomInfo, md_thorkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Prototype, 19941004) +static struct BurnRomInfo md_thorp3RomDesc[] = { + { "story of thor, the (prototype - oct 04, 1994).bin", 0x300000, 0x9e486f91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorp3) +STD_ROM_FN(md_thorp3) + +struct BurnDriver BurnDrvmd_thorp3 = { + "md_thorp3", "md_thor", NULL, NULL, "1994", + "The Story of Thor (Prototype, 19941004)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorp3RomInfo, md_thorp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Prototype, 19941017) +static struct BurnRomInfo md_thorp2RomDesc[] = { + { "story of thor, the (prototype - oct 17, 1994).bin", 0x300000, 0xaa43d34a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorp2) +STD_ROM_FN(md_thorp2) + +struct BurnDriver BurnDrvmd_thorp2 = { + "md_thorp2", "md_thor", NULL, NULL, "1994", + "The Story of Thor (Prototype, 19941017)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorp2RomInfo, md_thorp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Prototype, 19941101) +static struct BurnRomInfo md_thorp1RomDesc[] = { + { "story of thor, the (prototype - nov 01, 1994).bin", 0x300000, 0xfa59f847, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thorp1) +STD_ROM_FN(md_thorp1) + +struct BurnDriver BurnDrvmd_thorp1 = { + "md_thorp1", "md_thor", NULL, NULL, "1994", + "The Story of Thor (Prototype, 19941101)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorp1RomInfo, md_thorp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Story of Thor (Spa) +static struct BurnRomInfo md_thorsRomDesc[] = { + { "story of thor, the (spain).bin", 0x300000, 0x4631f941, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thors) +STD_ROM_FN(md_thors) + +struct BurnDriver BurnDrvmd_thors = { + "md_thors", "md_thor", NULL, NULL, "1995", + "The Story of Thor (Spa)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_thorsRomInfo, md_thorsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Beyond Oasis (USA) +static struct BurnRomInfo md_beyoasisRomDesc[] = { + { "beyond oasis (usa).bin", 0x300000, 0xc4728225, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_beyoasis) +STD_ROM_FN(md_beyoasis) + +struct BurnDriver BurnDrvmd_beyoasis = { + "md_beyoasis", "md_thor", NULL, NULL, "1995", + "Beyond Oasis (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_beyoasisRomInfo, md_beyoasisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Fighter II' - Special Champion Edition (Euro) +static struct BurnRomInfo md_sf2RomDesc[] = { + { "mpr-15910+mpr-15911.bin", 0x300000, 0x56d41136, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sf2) +STD_ROM_FN(md_sf2) + +struct BurnDriver BurnDrvmd_sf2 = { + "md_sf2", NULL, NULL, NULL, "1993", + "Street Fighter II' - Special Champion Edition (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sf2RomInfo, md_sf2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Fighter II' Plus (Jpn, Asia, Kor) +static struct BurnRomInfo md_sf2jRomDesc[] = { + { "street fighter ii' plus (jpn, asia, kor).bin", 0x300000, 0x2e487ee3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sf2j) +STD_ROM_FN(md_sf2j) + +struct BurnDriver BurnDrvmd_sf2j = { + "md_sf2j", "md_sf2", NULL, NULL, "1993", + "Street Fighter II' Plus (Jpn, Asia, Kor)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sf2jRomInfo, md_sf2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Fighter II' Turbo (Pirate) +static struct BurnRomInfo md_sf2pirRomDesc[] = { + { "street fighter ii' turbo (pirate).bin", 0x200000, 0xa85491ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sf2pir) +STD_ROM_FN(md_sf2pir) + +struct BurnDriver BurnDrvmd_sf2pir = { + "md_sf2pir", "md_sf2", NULL, NULL, "1993?", + "Street Fighter II' Turbo (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sf2pirRomInfo, md_sf2pirRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Fighter II' - Special Champion Edition (USA) +static struct BurnRomInfo md_sf2uRomDesc[] = { + { "street fighter ii' - special champion edition (usa).bin", 0x300000, 0x13fe08a1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sf2u) +STD_ROM_FN(md_sf2u) + +struct BurnDriver BurnDrvmd_sf2u = { + "md_sf2u", "md_sf2", NULL, NULL, "1993", + "Street Fighter II' - Special Champion Edition (USA)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sf2uRomInfo, md_sf2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Racer (Euro) +static struct BurnRomInfo md_sracerRomDesc[] = { + { "mpr-17987.bin", 0x100000, 0x1a58d5fe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sracer) +STD_ROM_FN(md_sracer) + +struct BurnDriver BurnDrvmd_sracer = { + "md_sracer", NULL, NULL, NULL, "1995", + "Street Racer (Euro)\0", NULL, "Ubi Soft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sracerRomInfo, md_sracerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Street Smart (Jpn, USA) +static struct BurnRomInfo md_ssmartRomDesc[] = { + { "street smart (usa, jpn).bin", 0x080000, 0xb1dedfad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssmart) +STD_ROM_FN(md_ssmart) + +struct BurnDriver BurnDrvmd_ssmart = { + "md_ssmart", NULL, NULL, NULL, "1991", + "Street Smart (Jpn, USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ssmartRomInfo, md_ssmartRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage II (Euro) ~ Bare Knuckle II - Shitou e no Chingonka (Jpn) +static struct BurnRomInfo md_sor2RomDesc[] = { + { "mpr-15309.bin", 0x200000, 0x42e3efdc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor2) +STD_ROM_FN(md_sor2) + +struct BurnDriver BurnDrvmd_sor2 = { + "md_sor2", NULL, NULL, NULL, "1993", + "Streets of Rage II (Euro) ~ Bare Knuckle II - Shitou e no Chingonka (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor2RomInfo, md_sor2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 2 (USA) +static struct BurnRomInfo md_sor2uRomDesc[] = { + { "streets of rage 2 (usa).bin", 0x200000, 0xe01fa526, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor2u) +STD_ROM_FN(md_sor2u) + +struct BurnDriver BurnDrvmd_sor2u = { + "md_sor2u", "md_sor2", NULL, NULL, "1992", + "Streets of Rage 2 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor2uRomInfo, md_sor2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bare Knuckle II (Jpn, Prototype) +static struct BurnRomInfo md_bk2pRomDesc[] = { + { "bare knuckle ii (jpn) (beta).bin", 0x130000, 0x0cf2acbe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bk2p) +STD_ROM_FN(md_bk2p) + +struct BurnDriver BurnDrvmd_bk2p = { + "md_bk2p", "md_sor2", NULL, NULL, "1992", + "Bare Knuckle II (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bk2pRomInfo, md_bk2pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro) +static struct BurnRomInfo md_sor3RomDesc[] = { + { "mpr-16834+mpr-16835.bin", 0x300000, 0x3b78135f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3) +STD_ROM_FN(md_sor3) + +struct BurnDriver BurnDrvmd_sor3 = { + "md_sor3", NULL, NULL, NULL, "1994", + "Streets of Rage 3 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3RomInfo, md_sor3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Kor) +static struct BurnRomInfo md_sor3kRomDesc[] = { + { "streets of rage 3 (kor).bin", 0x300000, 0x90ef991e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3k) +STD_ROM_FN(md_sor3k) + +struct BurnDriver BurnDrvmd_sor3k = { + "md_sor3k", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3kRomInfo, md_sor3kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro, Prototype, 19940412) +static struct BurnRomInfo md_sor3p5RomDesc[] = { + { "streets of rage 3 (euro) (prototype - apr 12, 1994).bin", 0x300000, 0xa17ce5ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3p5) +STD_ROM_FN(md_sor3p5) + +struct BurnDriver BurnDrvmd_sor3p5 = { + "md_sor3p5", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Euro, Prototype, 19940412)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3p5RomInfo, md_sor3p5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro, Prototype, 19940413) +static struct BurnRomInfo md_sor3p4RomDesc[] = { + { "streets of rage 3 (euro) (prototype - apr 13, 1994).bin", 0x300000, 0x164e42ae, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3p4) +STD_ROM_FN(md_sor3p4) + +struct BurnDriver BurnDrvmd_sor3p4 = { + "md_sor3p4", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Euro, Prototype, 19940413)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3p4RomInfo, md_sor3p4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro, Prototype, 19940415) +static struct BurnRomInfo md_sor3p3RomDesc[] = { + { "streets of rage 3 (euro) (prototype - apr 15, 1994).bin", 0x300000, 0xc64f1e6b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3p3) +STD_ROM_FN(md_sor3p3) + +struct BurnDriver BurnDrvmd_sor3p3 = { + "md_sor3p3", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Euro, Prototype, 19940415)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3p3RomInfo, md_sor3p3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro, Prototype, 19940420) +static struct BurnRomInfo md_sor3p2RomDesc[] = { + { "streets of rage 3 (euro) (prototype - apr 20, 1994).bin", 0x300000, 0x6ae4bd8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3p2) +STD_ROM_FN(md_sor3p2) + +struct BurnDriver BurnDrvmd_sor3p2 = { + "md_sor3p2", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Euro, Prototype, 19940420)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3p2RomInfo, md_sor3p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Euro, Prototype, 19940425) +static struct BurnRomInfo md_sor3p1RomDesc[] = { + { "streets of rage 3 (euro) (prototype - apr 25, 1994).bin", 0x300000, 0x7033878a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3p1) +STD_ROM_FN(md_sor3p1) + +struct BurnDriver BurnDrvmd_sor3p1 = { + "md_sor3p1", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Euro, Prototype, 19940425)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3p1RomInfo, md_sor3p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940401) +static struct BurnRomInfo md_sor3up06RomDesc[] = { + { "streets of rage 3 (prototype - apr 01, 1994).bin", 0x300000, 0x797e75b7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up06) +STD_ROM_FN(md_sor3up06) + +struct BurnDriver BurnDrvmd_sor3up06 = { + "md_sor3up06", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940401)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up06RomInfo, md_sor3up06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940404) +static struct BurnRomInfo md_sor3up05RomDesc[] = { + { "streets of rage 3 (prototype - apr 04, 1994).bin", 0x300000, 0x6b968f13, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up05) +STD_ROM_FN(md_sor3up05) + +struct BurnDriver BurnDrvmd_sor3up05 = { + "md_sor3up05", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940404)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up05RomInfo, md_sor3up05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940408) +static struct BurnRomInfo md_sor3up04RomDesc[] = { + { "streets of rage 3 (prototype - apr 08, 1994).bin", 0x300000, 0xd4ba76c2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up04) +STD_ROM_FN(md_sor3up04) + +struct BurnDriver BurnDrvmd_sor3up04 = { + "md_sor3up04", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940408)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up04RomInfo, md_sor3up04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940411) +static struct BurnRomInfo md_sor3up03RomDesc[] = { + { "streets of rage 3 (prototype - apr 11, 1994).bin", 0x300000, 0xfa5e5a82, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up03) +STD_ROM_FN(md_sor3up03) + +struct BurnDriver BurnDrvmd_sor3up03 = { + "md_sor3up03", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940411)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up03RomInfo, md_sor3up03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940412) +static struct BurnRomInfo md_sor3up02RomDesc[] = { + { "streets of rage 3 (prototype - apr 12, 1994).bin", 0x300000, 0x3f52cb72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up02) +STD_ROM_FN(md_sor3up02) + +struct BurnDriver BurnDrvmd_sor3up02 = { + "md_sor3up02", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940412)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up02RomInfo, md_sor3up02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940413) +static struct BurnRomInfo md_sor3up01RomDesc[] = { + { "streets of rage 3 (prototype - apr 13, 1994).bin", 0x300000, 0x6b675807, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up01) +STD_ROM_FN(md_sor3up01) + +struct BurnDriver BurnDrvmd_sor3up01 = { + "md_sor3up01", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940413)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up01RomInfo, md_sor3up01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940308) +static struct BurnRomInfo md_sor3up10RomDesc[] = { + { "streets of rage 3 (prototype - mar 08, 1994).bin", 0x300000, 0xea50b551, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up10) +STD_ROM_FN(md_sor3up10) + +struct BurnDriver BurnDrvmd_sor3up10 = { + "md_sor3up10", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940308)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up10RomInfo, md_sor3up10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940317) +static struct BurnRomInfo md_sor3up09RomDesc[] = { + { "streets of rage 3 (prototype - mar 17, 1994).bin", 0x300000, 0x39ad962b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up09) +STD_ROM_FN(md_sor3up09) + +struct BurnDriver BurnDrvmd_sor3up09 = { + "md_sor3up09", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940317)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up09RomInfo, md_sor3up09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940318) +static struct BurnRomInfo md_sor3up08RomDesc[] = { + { "streets of rage 3 (prototype - mar 18, 1994).bin", 0x300000, 0x60142484, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up08) +STD_ROM_FN(md_sor3up08) + +struct BurnDriver BurnDrvmd_sor3up08 = { + "md_sor3up08", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940318)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up08RomInfo, md_sor3up08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (Prototype, 19940328) +static struct BurnRomInfo md_sor3up07RomDesc[] = { + { "streets of rage 3 (prototype - mar 28, 1994).bin", 0x300000, 0x8757f797, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3up07) +STD_ROM_FN(md_sor3up07) + +struct BurnDriver BurnDrvmd_sor3up07 = { + "md_sor3up07", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (Prototype, 19940328)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3up07RomInfo, md_sor3up07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Streets of Rage 3 (USA) +static struct BurnRomInfo md_sor3uRomDesc[] = { + { "streets of rage 3 (usa).bin", 0x300000, 0xd5bb15d9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sor3u) +STD_ROM_FN(md_sor3u) + +struct BurnDriver BurnDrvmd_sor3u = { + "md_sor3u", "md_sor3", NULL, NULL, "1994", + "Streets of Rage 3 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sor3uRomInfo, md_sor3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bare Knuckle III (Jpn) +static struct BurnRomInfo md_bk3RomDesc[] = { + { "bare knuckle iii (jpn).bin", 0x300000, 0x5d09236f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bk3) +STD_ROM_FN(md_bk3) + +struct BurnDriver BurnDrvmd_bk3 = { + "md_bk3", "md_sor3", NULL, NULL, "1994", + "Bare Knuckle III (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bk3RomInfo, md_bk3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Bare Knuckle III (Jpn, Prototype) +static struct BurnRomInfo md_bk3pRomDesc[] = { + { "bare knuckle iii (jpn) (beta).bin", 0x300000, 0xe7ff99db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bk3p) +STD_ROM_FN(md_bk3p) + +struct BurnDriver BurnDrvmd_bk3p = { + "md_bk3p", "md_sor3", NULL, NULL, "1994", + "Bare Knuckle III (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bk3pRomInfo, md_bk3pRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Strider (Euro, USA) +static struct BurnRomInfo md_striderRomDesc[] = { + { "mpr-13487.bin", 0x100000, 0xb9d099a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strider) +STD_ROM_FN(md_strider) + +struct BurnDriver BurnDrvmd_strider = { + "md_strider", NULL, NULL, NULL, "1990", + "Strider (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_striderRomInfo, md_striderRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Strider Hiryuu (Jpn, Kor) +static struct BurnRomInfo md_striderjRomDesc[] = { + { "strider hiryuu (jpn, kor).bin", 0x100000, 0x859173f2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_striderj) +STD_ROM_FN(md_striderj) + +struct BurnDriver BurnDrvmd_striderj = { + "md_striderj", "md_strider", NULL, NULL, "1990", + "Strider Hiryuu (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_striderjRomInfo, md_striderjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Strider II (Euro) +static struct BurnRomInfo md_strider2RomDesc[] = { + { "strider ii (euro).bin", 0x100000, 0xe85e5270, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strider2) +STD_ROM_FN(md_strider2) + +struct BurnDriver BurnDrvmd_strider2 = { + "md_strider2", NULL, NULL, NULL, "1990", + "Strider II (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_strider2RomInfo, md_strider2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Strider Returns - Journey from Darkness (USA) +static struct BurnRomInfo md_strider2uRomDesc[] = { + { "strider returns - journey from darkness (usa).bin", 0x100000, 0x42589b79, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strider2u) +STD_ROM_FN(md_strider2u) + +struct BurnDriver BurnDrvmd_strider2u = { + "md_strider2u", "md_strider2", NULL, NULL, "1990", + "Strider Returns - Journey from Darkness (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_strider2uRomInfo, md_strider2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Striker (Euro) +static struct BurnRomInfo md_strikerRomDesc[] = { + { "striker (euro).bin", 0x200000, 0xcc5d7ab2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_striker) +STD_ROM_FN(md_striker) + +struct BurnDriver BurnDrvmd_striker = { + "md_striker", NULL, NULL, NULL, "1994", + "Striker (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_strikerRomInfo, md_strikerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Striker (Euro, Prototype) +static struct BurnRomInfo md_strikerpRomDesc[] = { + { "striker (euro) (beta).bin", 0x200000, 0xc10b270e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_strikerp) +STD_ROM_FN(md_strikerp) + +struct BurnDriver BurnDrvmd_strikerp = { + "md_strikerp", "md_striker", NULL, NULL, "1994", + "Striker (Euro, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_strikerpRomInfo, md_strikerpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (Euro) +static struct BurnRomInfo md_subterrRomDesc[] = { + { "mpr-16627.bin", 0x200000, 0xe8ced28d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterr) +STD_ROM_FN(md_subterr) + +struct BurnDriver BurnDrvmd_subterr = { + "md_subterr", NULL, NULL, NULL, "1994", + "SubTerrania (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterrRomInfo, md_subterrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (Prototype) +static struct BurnRomInfo md_subterrp1RomDesc[] = { + { "subterrania (beta).bin", 0x200000, 0x3a1022d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterrp1) +STD_ROM_FN(md_subterrp1) + +struct BurnDriver BurnDrvmd_subterrp1 = { + "md_subterrp1", "md_subterr", NULL, NULL, "1994", + "SubTerrania (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterrp1RomInfo, md_subterrp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (Prototype, Earlier) +static struct BurnRomInfo md_subterrp2RomDesc[] = { + { "subterrania (beta) (earlier).bin", 0x140000, 0x9c13d25c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterrp2) +STD_ROM_FN(md_subterrp2) + +struct BurnDriver BurnDrvmd_subterrp2 = { + "md_subterrp2", "md_subterr", NULL, NULL, "1994", + "SubTerrania (Prototype, Earlier)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterrp2RomInfo, md_subterrp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (Jpn) +static struct BurnRomInfo md_subterrjRomDesc[] = { + { "subterrania (jpn).bin", 0x200000, 0x7638ea91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterrj) +STD_ROM_FN(md_subterrj) + +struct BurnDriver BurnDrvmd_subterrj = { + "md_subterrj", "md_subterr", NULL, NULL, "1994?", + "SubTerrania (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterrjRomInfo, md_subterrjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (Prototype, 19940202) +static struct BurnRomInfo md_subterrp3RomDesc[] = { + { "subterrania (prototype - feb 02, 1994).bin", 0x200000, 0xb368e394, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterrp3) +STD_ROM_FN(md_subterrp3) + +struct BurnDriver BurnDrvmd_subterrp3 = { + "md_subterrp3", "md_subterr", NULL, NULL, "1994", + "SubTerrania (Prototype, 19940202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterrp3RomInfo, md_subterrp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SubTerrania (USA) +static struct BurnRomInfo md_subterruRomDesc[] = { + { "subterrania (usa).bin", 0x200000, 0xdc3c6c45, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_subterru) +STD_ROM_FN(md_subterru) + +struct BurnDriver BurnDrvmd_subterru = { + "md_subterru", "md_subterr", NULL, NULL, "1993", + "SubTerrania (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_subterruRomInfo, md_subterruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Summer Challenge (Euro, USA) +static struct BurnRomInfo md_summerRomDesc[] = { + { "summer challenge (euro, usa).bin", 0x200000, 0xd7d53dc1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_summer) +STD_ROM_FN(md_summer) + +struct BurnDriver BurnDrvmd_summer = { + "md_summer", NULL, NULL, NULL, "1993", + "Summer Challenge (Euro, USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_summerRomInfo, md_summerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sunset Riders (Euro) +static struct BurnRomInfo md_ssridersRomDesc[] = { + { "mpr-15305.bin", 0x080000, 0x0ff33054, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssriders) +STD_ROM_FN(md_ssriders) + +struct BurnDriver BurnDrvmd_ssriders = { + "md_ssriders", NULL, NULL, NULL, "1992", + "Sunset Riders (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ssridersRomInfo, md_ssridersRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sunset Riders (USA) +static struct BurnRomInfo md_ssridersuRomDesc[] = { + { "sunset riders (usa).bin", 0x080000, 0xac30c297, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssridersu) +STD_ROM_FN(md_ssridersu) + +struct BurnDriver BurnDrvmd_ssridersu = { + "md_ssridersu", "md_ssriders", NULL, NULL, "1992", + "Sunset Riders (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ssridersuRomInfo, md_ssridersuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Baseball 2020 (Euro, USA) +static struct BurnRomInfo md_sb2020RomDesc[] = { + { "super02.bin", 0x200000, 0xc17acee5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sb2020) +STD_ROM_FN(md_sb2020) + +struct BurnDriver BurnDrvmd_sb2020 = { + "md_sb2020", NULL, NULL, NULL, "1994", + "Super Baseball 2020 (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sb2020RomInfo, md_sb2020RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 2020 Toshi Super Baseball (Jpn) +static struct BurnRomInfo md_sb2020jRomDesc[] = { + { "2020 toshi super baseball (jpn).bin", 0x200000, 0x2bbee127, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sb2020j) +STD_ROM_FN(md_sb2020j) + +struct BurnDriver BurnDrvmd_sb2020j = { + "md_sb2020j", "md_sb2020", NULL, NULL, "1994", + "2020 Toshi Super Baseball (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sb2020jRomInfo, md_sb2020jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Battleship (USA) +static struct BurnRomInfo md_sbshipRomDesc[] = { + { "super battleship (usa).bin", 0x080000, 0x99ca1bfb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sbship) +STD_ROM_FN(md_sbship) + +struct BurnDriver BurnDrvmd_sbship = { + "md_sbship", NULL, NULL, NULL, "1993", + "Super Battleship (USA)\0", NULL, "Mindscape", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sbshipRomInfo, md_sbshipRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Garry Kitchen's Super Battletank - War in the Gulf (USA) +static struct BurnRomInfo md_sbtankRomDesc[] = { + { "super battletank - war in the gulf (usa).bin", 0x080000, 0xb0b5e3c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sbtank) +STD_ROM_FN(md_sbtank) + +struct BurnDriver BurnDrvmd_sbtank = { + "md_sbtank", NULL, NULL, NULL, "1992", + "Garry Kitchen's Super Battletank - War in the Gulf (USA)\0", NULL, "Absolute Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sbtankRomInfo, md_sbtankRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Daisenryaku (Jpn) +static struct BurnRomInfo md_suprdaisRomDesc[] = { + { "mpr-12477.bin", 0x080000, 0xd50a166f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suprdais) +STD_ROM_FN(md_suprdais) + +struct BurnDriver BurnDrvmd_suprdais = { + "md_suprdais", NULL, NULL, NULL, "1989", + "Super Daisenryaku (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_suprdaisRomInfo, md_suprdaisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Fantasy Zone (Euro) +static struct BurnRomInfo md_sfzoneRomDesc[] = { + { "mpr-15124.bin", 0x100000, 0x927975be, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sfzone) +STD_ROM_FN(md_sfzone) + +struct BurnDriver BurnDrvmd_sfzone = { + "md_sfzone", NULL, NULL, NULL, "1993", + "Super Fantasy Zone (Euro)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sfzoneRomInfo, md_sfzoneRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Fantasy Zone (Jpn) +static struct BurnRomInfo md_sfzonejRomDesc[] = { + { "super fantasy zone (jpn).bin", 0x100000, 0x767780d7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sfzonej) +STD_ROM_FN(md_sfzonej) + +struct BurnDriver BurnDrvmd_sfzonej = { + "md_sfzonej", "md_sfzone", NULL, NULL, "1992", + "Super Fantasy Zone (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sfzonejRomInfo, md_sfzonejRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Hang-On (World, Rev. A) +static struct BurnRomInfo md_shangonRomDesc[] = { + { "mpr-12640a.bin", 0x080000, 0x3877d107, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangon) +STD_ROM_FN(md_shangon) + +struct BurnDriver BurnDrvmd_shangon = { + "md_shangon", NULL, NULL, NULL, "1989", + "Super Hang-On (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangonRomInfo, md_shangonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Hang-On (World) +static struct BurnRomInfo md_shangon1RomDesc[] = { + { "mpr-12640.bin", 0x080000, 0xcb2201a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shangon1) +STD_ROM_FN(md_shangon1) + +struct BurnDriver BurnDrvmd_shangon1 = { + "md_shangon1", "md_shangon", NULL, NULL, "1989", + "Super Hang-On (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shangon1RomInfo, md_shangon1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super High Impact (USA) +static struct BurnRomInfo md_shiRomDesc[] = { + { "super high impact (usa).bin", 0x100000, 0xb870c2f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shi) +STD_ROM_FN(md_shi) + +struct BurnDriver BurnDrvmd_shi = { + "md_shi", NULL, NULL, NULL, "1992", + "Super High Impact (USA)\0", NULL, "Arena", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shiRomInfo, md_shiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Hydlide (Euro) +static struct BurnRomInfo md_suphydlRomDesc[] = { + { "super hydlide (euro).bin", 0x080000, 0x1fe2d90b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suphydl) +STD_ROM_FN(md_suphydl) + +struct BurnDriver BurnDrvmd_suphydl = { + "md_suphydl", NULL, NULL, NULL, "1991", + "Super Hydlide (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_suphydlRomInfo, md_suphydlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Hydlide (Jpn) +static struct BurnRomInfo md_suphydljRomDesc[] = { + { "mpr-12632.bin", 0x080000, 0x599be386, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suphydlj) +STD_ROM_FN(md_suphydlj) + +struct BurnDriver BurnDrvmd_suphydlj = { + "md_suphydlj", "md_suphydl", NULL, NULL, "1989", + "Super Hydlide (Jpn)\0", NULL, "Asmik Ace", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_suphydljRomInfo, md_suphydljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Hydlide (USA) +static struct BurnRomInfo md_suphydluRomDesc[] = { + { "super hydlide (usa).bin", 0x080000, 0x1335ddaa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suphydlu) +STD_ROM_FN(md_suphydlu) + +struct BurnDriver BurnDrvmd_suphydlu = { + "md_suphydlu", "md_suphydl", NULL, NULL, "1989", + "Super Hydlide (USA)\0", NULL, "Seismic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_suphydluRomInfo, md_suphydluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Kick Off (Euro) +static struct BurnRomInfo md_suprkickRomDesc[] = { + { "mpr-15420.bin", 0x080000, 0xf43793ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suprkick) +STD_ROM_FN(md_suprkick) + +struct BurnDriver BurnDrvmd_suprkick = { + "md_suprkick", NULL, NULL, NULL, "1992", + "Super Kick Off (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_suprkickRomInfo, md_suprkickRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super League (Euro) +static struct BurnRomInfo md_suprleagRomDesc[] = { + { "super league (euro).bin", 0x080000, 0x55baec6e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suprleag) +STD_ROM_FN(md_suprleag) + +struct BurnDriver BurnDrvmd_suprleag = { + "md_suprleag", NULL, NULL, NULL, "1990", + "Super League (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_suprleagRomInfo, md_suprleagRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super League (Jpn) +static struct BurnRomInfo md_suprleagjRomDesc[] = { + { "super league (jpn).bin", 0x080000, 0xea13cb1d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_suprleagj) +STD_ROM_FN(md_suprleagj) + +struct BurnDriver BurnDrvmd_suprleagj = { + "md_suprleagj", "md_suprleag", NULL, NULL, "1989", + "Super League (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_suprleagjRomInfo, md_suprleagjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tommy Lasorda Baseball (USA) +static struct BurnRomInfo md_tommylbRomDesc[] = { + { "mpr-12706.bin", 0x080000, 0x4fb50304, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tommylb) +STD_ROM_FN(md_tommylb) + +struct BurnDriver BurnDrvmd_tommylb = { + "md_tommylb", "md_suprleag", NULL, NULL, "1989", + "Tommy Lasorda Baseball (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tommylbRomInfo, md_tommylbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario World +static struct BurnRomInfo md_smwRomDesc[] = { + { "super mario world (unl).bin", 0x200000, 0xcf540ba6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smw) +STD_ROM_FN(md_smw) + +struct BurnDriver BurnDrvmd_smw = { + "md_smw", "md_smb", NULL, NULL, "199?", + "Super Mario World\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smwRomInfo, md_smwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario World (Pirate) +static struct BurnRomInfo md_smwaRomDesc[] = { + { "super mario world (unl) (pirate).bin", 0x200000, 0x97c2695e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smwa) +STD_ROM_FN(md_smwa) + +struct BurnDriver BurnDrvmd_smwa = { + "md_smwa", "md_smb", NULL, NULL, "199?", + "Super Mario World (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smwaRomInfo, md_smwaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Monaco GP (Euro, Jpn) +static struct BurnRomInfo md_smgpaRomDesc[] = { + { "super monaco gp (euro, jpn).bin", 0x080000, 0xb1823595, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgpa) +STD_ROM_FN(md_smgpa) + +struct BurnDriver BurnDrvmd_smgpa = { + "md_smgpa", "md_smgp", NULL, NULL, "1990", + "Super Monaco GP (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smgpaRomInfo, md_smgpaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Monaco GP (Jpn) +static struct BurnRomInfo md_smgpjRomDesc[] = { + { "mpr-13215.bin", 0x080000, 0x90f9bab3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgpj) +STD_ROM_FN(md_smgpj) + +struct BurnDriver BurnDrvmd_smgpj = { + "md_smgpj", "md_smgp", NULL, NULL, "1990", + "Super Monaco GP (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smgpjRomInfo, md_smgpjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Monaco GP (USA) +static struct BurnRomInfo md_smgpuRomDesc[] = { + { "super monaco gp (usa).bin", 0x080000, 0x725018ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smgpu) +STD_ROM_FN(md_smgpu) + +struct BurnDriver BurnDrvmd_smgpu = { + "md_smgpu", "md_smgp", NULL, NULL, "1990", + "Super Monaco GP (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smgpuRomInfo, md_smgpuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Off Road (Euro, USA) +static struct BurnRomInfo md_superoffRomDesc[] = { + { "super off road (euro, usa).bin", 0x080000, 0x8f2fdada, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_superoff) +STD_ROM_FN(md_superoff) + +struct BurnDriver BurnDrvmd_superoff = { + "md_superoff", NULL, NULL, NULL, "1994", + "Super Off Road (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_superoffRomInfo, md_superoffRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Real Basketball (Euro) +static struct BurnRomInfo md_srealbasRomDesc[] = { + { "mpr-13432.bin", 0x080000, 0xf04765ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_srealbas) +STD_ROM_FN(md_srealbas) + +struct BurnDriver BurnDrvmd_srealbas = { + "md_srealbas", NULL, NULL, NULL, "1990", + "Super Real Basketball (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_srealbasRomInfo, md_srealbasRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Real Basketball (Jpn, Kor) +static struct BurnRomInfo md_srealbasjRomDesc[] = { + { "mpr-12904.bin", 0x080000, 0x4346e11a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_srealbasj) +STD_ROM_FN(md_srealbasj) + +struct BurnDriver BurnDrvmd_srealbasj = { + "md_srealbasj", "md_srealbas", NULL, NULL, "1990", + "Super Real Basketball (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_srealbasjRomInfo, md_srealbasjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pat Riley Basketball (USA) +static struct BurnRomInfo md_patrileyRomDesc[] = { + { "pat riley basketball (usa).bin", 0x080000, 0x3d9318a7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_patriley) +STD_ROM_FN(md_patriley) + +struct BurnDriver BurnDrvmd_patriley = { + "md_patriley", "md_srealbas", NULL, NULL, "1990", + "Pat Riley Basketball (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_patrileyRomInfo, md_patrileyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Skidmarks (Euro, J-Cart) +static struct BurnRomInfo md_sskidRomDesc[] = { + { "super skidmarks (euro) (j-cart).bin", 0x200000, 0x4a9c62f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sskid) +STD_ROM_FN(md_sskid) + +struct BurnDriver BurnDrvmd_sskid = { + "md_sskid", NULL, NULL, NULL, "1995", + "Super Skidmarks (Euro, J-Cart)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sskidRomInfo, md_sskidRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Skidmarks (USA, Prototype) +static struct BurnRomInfo md_sskidpRomDesc[] = { + { "super skidmarks (euro) (beta).bin", 0x200000, 0xa61a0f0c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sskidp) +STD_ROM_FN(md_sskidp) + +struct BurnDriver BurnDrvmd_sskidp = { + "md_sskidp", "md_sskid", NULL, NULL, "1995", + "Super Skidmarks (USA, Prototype)\0", NULL, "Codemasters", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sskidpRomInfo, md_sskidpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Street Fighter II - The New Challengers (Euro) +static struct BurnRomInfo md_ssf2RomDesc[] = { + { "super street fighter ii - the new challengers (euro).bin", 0x500000, 0x682c192f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssf2) +STD_ROM_FN(md_ssf2) + +struct BurnDriver BurnDrvmd_ssf2 = { + "md_ssf2", NULL, NULL, NULL, "1994", + "Super Street Fighter II - The New Challengers (Euro)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SSF2, GBF_MISC, 0, + MegadriveGetZipName, md_ssf2RomInfo, md_ssf2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Street Fighter II - The New Challengers (Jpn) +static struct BurnRomInfo md_ssf2jRomDesc[] = { + { "super street fighter ii - the new challengers (jpn).bin", 0x500000, 0xd8eeb2bd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssf2j) +STD_ROM_FN(md_ssf2j) + +struct BurnDriver BurnDrvmd_ssf2j = { + "md_ssf2j", "md_ssf2", NULL, NULL, "1994", + "Super Street Fighter II - The New Challengers (Jpn)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SSF2, GBF_MISC, 0, + MegadriveGetZipName, md_ssf2jRomInfo, md_ssf2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Street Fighter II - The New Challengers (USA) +static struct BurnRomInfo md_ssf2uRomDesc[] = { + { "super street fighter ii - the new challengers (usa).bin", 0x500000, 0x165defbf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ssf2u) +STD_ROM_FN(md_ssf2u) + +struct BurnDriver BurnDrvmd_ssf2u = { + "md_ssf2u", "md_ssf2", NULL, NULL, "1994", + "Super Street Fighter II - The New Challengers (USA)\0", NULL, "Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SSF2, GBF_MISC, 0, + MegadriveGetZipName, md_ssf2uRomInfo, md_ssf2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Thunder Blade (World) +static struct BurnRomInfo md_stbladRomDesc[] = { + { "mpr-12354.bin", 0x080000, 0xb13087ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stblad) +STD_ROM_FN(md_stblad) + +struct BurnDriver BurnDrvmd_stblad = { + "md_stblad", NULL, NULL, NULL, "1989", + "Super Thunder Blade (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stbladRomInfo, md_stbladRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Thunder Blade (Jpn, Launch Cart) +static struct BurnRomInfo md_stbladjRomDesc[] = { + { "mpr-11996.bin", 0x080000, 0x8bd77836, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_stbladj) +STD_ROM_FN(md_stbladj) + +struct BurnDriver BurnDrvmd_stbladj = { + "md_stbladj", "md_stblad", NULL, NULL, "1988", + "Super Thunder Blade (Jpn, Launch Cart)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_stbladjRomInfo, md_stbladjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Volley Ball (USA) +static struct BurnRomInfo md_svolleyRomDesc[] = { + { "super volley ball (usa).bin", 0x040000, 0xa88fee44, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_svolley) +STD_ROM_FN(md_svolley) + +struct BurnDriver BurnDrvmd_svolley = { + "md_svolley", NULL, NULL, NULL, "1991", + "Super Volley Ball (USA)\0", NULL, "Video System", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_svolleyRomInfo, md_svolleyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Volley Ball (USA, Alt) +static struct BurnRomInfo md_svolley1RomDesc[] = { + { "super volley ball (usa) (alt).bin", 0x040000, 0x85102799, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_svolley1) +STD_ROM_FN(md_svolley1) + +struct BurnDriver BurnDrvmd_svolley1 = { + "md_svolley1", "md_svolley", NULL, NULL, "1991", + "Super Volley Ball (USA, Alt)\0", NULL, "Video System", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_svolley1RomInfo, md_svolley1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Volley Ball (Jpn) +static struct BurnRomInfo md_svolleyjRomDesc[] = { + { "super volley ball (jpn).bin", 0x040000, 0x9b5c28ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_svolleyj) +STD_ROM_FN(md_svolleyj) + +struct BurnDriver BurnDrvmd_svolleyj = { + "md_svolleyj", "md_svolley", NULL, NULL, "1991", + "Super Volley Ball (Jpn)\0", NULL, "Video System", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_svolleyjRomInfo, md_svolleyjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Superman - The Man of Steel (Euro) +static struct BurnRomInfo md_supmanRomDesc[] = { + { "mpr-15327.bin", 0x100000, 0x7db434ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supman) +STD_ROM_FN(md_supman) + +struct BurnDriver BurnDrvmd_supman = { + "md_supman", NULL, NULL, NULL, "1993", + "Superman - The Man of Steel (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supmanRomInfo, md_supmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Superman (USA, Prototype) +static struct BurnRomInfo md_supmanpRomDesc[] = { + { "superman (usa) (beta).bin", 0x100000, 0x5cd0e1d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supmanp) +STD_ROM_FN(md_supmanp) + +struct BurnDriver BurnDrvmd_supmanp = { + "md_supmanp", "md_supman", NULL, NULL, "1992", + "Superman (USA, Prototype)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supmanpRomInfo, md_supmanpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Superman (USA) +static struct BurnRomInfo md_supmanuRomDesc[] = { + { "superman (usa).bin", 0x100000, 0x543a5869, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supmanu) +STD_ROM_FN(md_supmanu) + +struct BurnDriver BurnDrvmd_supmanu = { + "md_supmanu", "md_supman", NULL, NULL, "1992", + "Superman (USA)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_supmanuRomInfo, md_supmanuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Surging Aura (Jpn) +static struct BurnRomInfo md_surgingRomDesc[] = { + { "surging aura (jpn).bin", 0x200000, 0x65ac1d2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_surging) +STD_ROM_FN(md_surging) + +struct BurnDriver BurnDrvmd_surging = { + "md_surging", NULL, NULL, NULL, "1995", + "Surging Aura (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_surgingRomInfo, md_surgingRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Swamp Thing (USA, Prototype) +static struct BurnRomInfo md_swamptngRomDesc[] = { + { "swamp thing proto.bin", 0x400000, 0xe6ebe9d5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_swamptng) +STD_ROM_FN(md_swamptng) + +struct BurnDriver BurnDrvmd_swamptng = { + "md_swamptng", NULL, NULL, NULL, "1991", + "Swamp Thing (USA, Prototype)\0", NULL, "NuVision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_swamptngRomInfo, md_swamptngRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sword of Sodan (Euro, USA) +static struct BurnRomInfo md_swordsodRomDesc[] = { + { "sword of sodan (euro, usa).bin", 0x080000, 0x9cb8468f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_swordsod) +STD_ROM_FN(md_swordsod) + +struct BurnDriver BurnDrvmd_swordsod = { + "md_swordsod", NULL, NULL, NULL, "1990", + "Sword of Sodan (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_swordsodRomInfo, md_swordsodRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sword of Sodan (Jpn) +static struct BurnRomInfo md_swordsodjRomDesc[] = { + { "sword of sodan (jpn).bin", 0x080000, 0x58edb3f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_swordsodj) +STD_ROM_FN(md_swordsodj) + +struct BurnDriver BurnDrvmd_swordsodj = { + "md_swordsodj", "md_swordsod", NULL, NULL, "1990", + "Sword of Sodan (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_swordsodjRomInfo, md_swordsodjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Syd of Valis (USA) +static struct BurnRomInfo md_sydvalisRomDesc[] = { + { "syd of valis (usa).bin", 0x080000, 0x37dc0108, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sydvalis) +STD_ROM_FN(md_sydvalis) + +struct BurnDriver BurnDrvmd_sydvalis = { + "md_sydvalis", NULL, NULL, NULL, "1992", + "Syd of Valis (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sydvalisRomInfo, md_sydvalisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// SD Valis (Jpn) +static struct BurnRomInfo md_sdvalisRomDesc[] = { + { "sd valis (jpn).bin", 0x080000, 0x1aef72ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdvalis) +STD_ROM_FN(md_sdvalis) + +struct BurnDriver BurnDrvmd_sdvalis = { + "md_sdvalis", "md_sydvalis", NULL, NULL, "1992", + "SD Valis (Jpn)\0", NULL, "Laser Soft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sdvalisRomInfo, md_sdvalisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sword of Vermilion (Euro, USA) +static struct BurnRomInfo md_vermilRomDesc[] = { + { "mpr-13430+mpr-13431.bin", 0x0a0000, 0xea1bc9ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vermil) +STD_ROM_FN(md_vermil) + +struct BurnDriver BurnDrvmd_vermil = { + "md_vermil", NULL, NULL, NULL, "1990", + "Sword of Vermilion (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_vermilRomInfo, md_vermilRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vermilion (Jpn) +static struct BurnRomInfo md_vermiljRomDesc[] = { + { "vermilion (jpn).bin", 0x0a0000, 0xe400dfc3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vermilj) +STD_ROM_FN(md_vermilj) + +struct BurnDriver BurnDrvmd_vermilj = { + "md_vermilj", "md_vermil", NULL, NULL, "1989", + "Vermilion (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_vermiljRomInfo, md_vermiljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sylvester & Tweety in Cagey Capers (Euro) +static struct BurnRomInfo md_sylvestrRomDesc[] = { + { "sylvester & tweety in cagey capers (euro).bin", 0x200000, 0x89fc54ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sylvestr) +STD_ROM_FN(md_sylvestr) + +struct BurnDriver BurnDrvmd_sylvestr = { + "md_sylvestr", NULL, NULL, NULL, "1994", + "Sylvester & Tweety in Cagey Capers (Euro)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sylvestrRomInfo, md_sylvestrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sylvester and Tweety in Cagey Capers (USA) +static struct BurnRomInfo md_sylvestruRomDesc[] = { + { "sylvester and tweety in cagey capers (usa).bin", 0x200000, 0x9d9c786b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sylvestru) +STD_ROM_FN(md_sylvestru) + +struct BurnDriver BurnDrvmd_sylvestru = { + "md_sylvestru", "md_sylvestr", NULL, NULL, "1993", + "Sylvester and Tweety in Cagey Capers (USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sylvestruRomInfo, md_sylvestruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Syndicate (Euro, USA) +static struct BurnRomInfo md_syndicRomDesc[] = { + { "syndicate (euro, usa).bin", 0x200000, 0x95bbf87b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_syndic) +STD_ROM_FN(md_syndic) + +struct BurnDriver BurnDrvmd_syndic = { + "md_syndic", NULL, NULL, NULL, "1994", + "Syndicate (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_syndicRomInfo, md_syndicRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// T2 - Terminator 2 - Judgment Day (Euro, USA) +static struct BurnRomInfo md_t2termRomDesc[] = { + { "t2 - terminator 2 - judgment day (euro, usa).bin", 0x100000, 0x2f75e896, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_t2term) +STD_ROM_FN(md_t2term) + +struct BurnDriver BurnDrvmd_t2term = { + "md_t2term", NULL, NULL, NULL, "1991", + "T2 - Terminator 2 - Judgment Day (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_t2termRomInfo, md_t2termRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// T2 - The Arcade Game (Euro, USA) +static struct BurnRomInfo md_t2agRomDesc[] = { + { "mpr-15238.bin", 0x100000, 0xa1264f17, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_t2ag) +STD_ROM_FN(md_t2ag) + +struct BurnDriver BurnDrvmd_t2ag = { + "md_t2ag", NULL, NULL, NULL, "1992", + "T2 - The Arcade Game (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_t2agRomInfo, md_t2agRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// T2 - The Arcade Game (USA, Prototype) +static struct BurnRomInfo md_t2agpRomDesc[] = { + { "t2 - the arcade game (usa) (beta).bin", 0x100000, 0x94255703, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_t2agp) +STD_ROM_FN(md_t2agp) + +struct BurnDriver BurnDrvmd_t2agp = { + "md_t2agp", "md_t2ag", NULL, NULL, "1992", + "T2 - The Arcade Game (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_t2agpRomInfo, md_t2agpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// T2 - The Arcade Game (Jpn) +static struct BurnRomInfo md_t2agjRomDesc[] = { + { "t2 - the arcade game (jpn).bin", 0x100000, 0x5e6fe52c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_t2agj) +STD_ROM_FN(md_t2agj) + +struct BurnDriver BurnDrvmd_t2agj = { + "md_t2agj", "md_t2ag", NULL, NULL, "1994", + "T2 - The Arcade Game (Jpn)\0", NULL, "Acclaim Japan", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_t2agjRomInfo, md_t2agjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taikou Risshiden (Jpn) +static struct BurnRomInfo md_taikouRomDesc[] = { + { "taikou risshiden (jpn).bin", 0x140000, 0xf96fe15b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_taikou) +STD_ROM_FN(md_taikou) + +struct BurnDriver BurnDrvmd_taikou = { + "md_taikou", NULL, NULL, NULL, "1993", + "Taikou Risshiden (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_taikouRomInfo, md_taikouRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taiwan Daheng (Chi) +static struct BurnRomInfo md_taiwanRomDesc[] = { + { "taiwan daheng (chi) (unl).bin", 0x100000, 0xbaf20f81, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_taiwan) +STD_ROM_FN(md_taiwan) + +struct BurnDriver BurnDrvmd_taiwan = { + "md_taiwan", NULL, NULL, NULL, "1994", + "Taiwan Daheng (Chi)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_taiwanRomInfo, md_taiwanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// TaleSpin (Euro, USA) +static struct BurnRomInfo md_talespinRomDesc[] = { + { "mpr-15058.bin", 0x080000, 0xf5c0c8d0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_talespin) +STD_ROM_FN(md_talespin) + +struct BurnDriver BurnDrvmd_talespin = { + "md_talespin", NULL, NULL, NULL, "1992", + "TaleSpin (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_talespinRomInfo, md_talespinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Marvel Land (USA) +static struct BurnRomInfo md_mvlndRomDesc[] = { + { "marvel land (usa).bin", 0x100000, 0xcd7eeeb7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mvlnd) +STD_ROM_FN(md_mvlnd) + +struct BurnDriver BurnDrvmd_mvlnd = { + "md_mvlnd", "md_talmit", NULL, NULL, "1991", + "Marvel Land (USA)\0", NULL, "Namcot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mvlndRomInfo, md_mvlndRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Target Earth (USA) +static struct BurnRomInfo md_trgearthRomDesc[] = { + { "target earth (usa).bin", 0x080000, 0xcddf62d3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_trgearth) +STD_ROM_FN(md_trgearth) + +struct BurnDriver BurnDrvmd_trgearth = { + "md_trgearth", NULL, NULL, NULL, "1990", + "Target Earth (USA)\0", NULL, "Dreamworks Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_trgearthRomInfo, md_trgearthRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Assault Suit Leynos (Jpn) +static struct BurnRomInfo md_leynosRomDesc[] = { + { "assault suit leynos (jpn).bin", 0x080000, 0x81a2c800, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_leynos) +STD_ROM_FN(md_leynos) + +struct BurnDriver BurnDrvmd_leynos = { + "md_leynos", "md_trgearth", NULL, NULL, "1990", + "Assault Suit Leynos (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_leynosRomInfo, md_leynosRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Task Force Harrier EX (USA) +static struct BurnRomInfo md_taskfhexRomDesc[] = { + { "task force harrier ex (usa).bin", 0x100000, 0xc8bb0257, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_taskfhex) +STD_ROM_FN(md_taskfhex) + +struct BurnDriver BurnDrvmd_taskfhex = { + "md_taskfhex", NULL, NULL, NULL, "1991", + "Task Force Harrier EX (USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_taskfhexRomInfo, md_taskfhexRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Task Force Harrier EX (Jpn) +static struct BurnRomInfo md_taskfhexjRomDesc[] = { + { "task force harrier ex (jpn).bin", 0x100000, 0xe9a54eed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_taskfhexj) +STD_ROM_FN(md_taskfhexj) + +struct BurnDriver BurnDrvmd_taskfhexj = { + "md_taskfhexj", "md_taskfhex", NULL, NULL, "1991", + "Task Force Harrier EX (Jpn)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_taskfhexjRomInfo, md_taskfhexjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Truxton (Euro, USA) ~ Tatsujin (Jpn) +static struct BurnRomInfo md_truxtonRomDesc[] = { + { "truxton -- tatsujin (world).bin", 0x080000, 0x5bd0882d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_truxton) +STD_ROM_FN(md_truxton) + +struct BurnDriver BurnDrvmd_truxton = { + "md_truxton", NULL, NULL, NULL, "1989", + "Truxton (Euro, USA) ~ Tatsujin (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_truxtonRomInfo, md_truxtonRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Taz-Mania (World) +static struct BurnRomInfo md_tazmaniaRomDesc[] = { + { "mpr-14838.bin", 0x080000, 0x0e901f45, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tazmania) +STD_ROM_FN(md_tazmania) + +struct BurnDriver BurnDrvmd_tazmania = { + "md_tazmania", NULL, NULL, NULL, "1992", + "Taz-Mania (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tazmaniaRomInfo, md_tazmaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// USA Basketball World Challenge (Euro, USA) +static struct BurnRomInfo md_teamusaRomDesc[] = { + { "team usa basketball (euro, usa).bin", 0x100000, 0xa0caf97e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_teamusa) +STD_ROM_FN(md_teamusa) + +struct BurnDriver BurnDrvmd_teamusa = { + "md_teamusa", NULL, NULL, NULL, "1992", + "USA Basketball World Challenge (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_teamusaRomInfo, md_teamusaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// USA Basketball World Challenge (Jpn) +static struct BurnRomInfo md_dreamteamRomDesc[] = { + { "dream team usa (jpn).bin", 0x100000, 0xe2e21b72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dreamteam) +STD_ROM_FN(md_dreamteam) + +struct BurnDriver BurnDrvmd_dreamteam = { + "md_dreamteam", "md_teamusa", NULL, NULL, "1992", + "USA Basketball World Challenge (Jpn)\0", NULL, "Electronic Arts Victor", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dreamteamRomInfo, md_dreamteamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Techno Clash (Euro, USA) +static struct BurnRomInfo md_technoclRomDesc[] = { + { "techno clash (euro, usa).bin", 0x100000, 0x4e65e483, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_technocl) +STD_ROM_FN(md_technocl) + +struct BurnDriver BurnDrvmd_technocl = { + "md_technocl", NULL, NULL, NULL, "1993", + "Techno Clash (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_technoclRomInfo, md_technoclRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Technocop (USA) +static struct BurnRomInfo md_tcopRomDesc[] = { + { "technocop (usa).bin", 0x080000, 0x7459ad06, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tcop) +STD_ROM_FN(md_tcop) + +struct BurnDriver BurnDrvmd_tcop = { + "md_tcop", NULL, NULL, NULL, "1990", + "Technocop (USA)\0", NULL, "Razorsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tcopRomInfo, md_tcopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Boy Soccer Team III (Jpn, Pirate) +static struct BurnRomInfo md_bsteam3RomDesc[] = { + { "tecmo cup (jpn) (pirate).bin", 0x080000, 0xe889e218, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bsteam3) +STD_ROM_FN(md_bsteam3) + +struct BurnDriver BurnDrvmd_bsteam3 = { + "md_bsteam3", "md_tecmocup", NULL, NULL, "199?", + "Boy Soccer Team III (Jpn, Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bsteam3RomInfo, md_bsteam3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Cup (Jpn, Prototype?) +static struct BurnRomInfo md_tecmocupRomDesc[] = { + { "tecmo cup (jpn) (prototype?) (bad dump).bin", 0x080000, 0x88fdd060, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmocup) +STD_ROM_FN(md_tecmocup) + +struct BurnDriver BurnDrvmd_tecmocup = { + "md_tecmocup", NULL, NULL, NULL, "199?", + "Tecmo Cup (Jpn, Prototype?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tecmocupRomInfo, md_tecmocupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Baseball (USA) +static struct BurnRomInfo md_tecmobbRomDesc[] = { + { "tecmo super baseball (usa).bin", 0x100000, 0x227a1178, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobb) +STD_ROM_FN(md_tecmobb) + +struct BurnDriver BurnDrvmd_tecmobb = { + "md_tecmobb", NULL, NULL, NULL, "1994", + "Tecmo Super Baseball (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobbRomInfo, md_tecmobbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl (USA, 199310) +static struct BurnRomInfo md_tecmobwlRomDesc[] = { + { "tecmo super bowl (usa) (october 1993).bin", 0x100000, 0x21f27d34, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobwl) +STD_ROM_FN(md_tecmobwl) + +struct BurnDriver BurnDrvmd_tecmobwl = { + "md_tecmobwl", NULL, NULL, NULL, "1993", + "Tecmo Super Bowl (USA, 199310)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobwlRomInfo, md_tecmobwlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl (USA, 199309) +static struct BurnRomInfo md_tecmobwlaRomDesc[] = { + { "tecmo super bowl (usa) (september 1993).bin", 0x100000, 0xbd5933ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobwla) +STD_ROM_FN(md_tecmobwla) + +struct BurnDriver BurnDrvmd_tecmobwla = { + "md_tecmobwla", "md_tecmobwl", NULL, NULL, "1993", + "Tecmo Super Bowl (USA, 199309)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobwlaRomInfo, md_tecmobwlaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl (Jpn) +static struct BurnRomInfo md_tecmobwljRomDesc[] = { + { "tecmo super bowl (jpn).bin", 0x100000, 0x90c6e20c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobwlj) +STD_ROM_FN(md_tecmobwlj) + +struct BurnDriver BurnDrvmd_tecmobwlj = { + "md_tecmobwlj", "md_tecmobwl", NULL, NULL, "1993", + "Tecmo Super Bowl (Jpn)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobwljRomInfo, md_tecmobwljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl II (USA) +static struct BurnRomInfo md_tecmobw2RomDesc[] = { + { "tecmo super bowl ii - special edition (usa).bin", 0x200000, 0x0a0e67d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobw2) +STD_ROM_FN(md_tecmobw2) + +struct BurnDriver BurnDrvmd_tecmobw2 = { + "md_tecmobw2", NULL, NULL, NULL, "1994", + "Tecmo Super Bowl II (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobw2RomInfo, md_tecmobw2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl II - Special Edition (Jpn) +static struct BurnRomInfo md_tecmobw2jRomDesc[] = { + { "tecmo super bowl ii - special edition (jpn).bin", 0x200000, 0x32fb633d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobw2j) +STD_ROM_FN(md_tecmobw2j) + +struct BurnDriver BurnDrvmd_tecmobw2j = { + "md_tecmobw2j", "md_tecmobw2", NULL, NULL, "1994", + "Tecmo Super Bowl II - Special Edition (Jpn)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobw2jRomInfo, md_tecmobw2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Bowl III - Final Edition (USA) +static struct BurnRomInfo md_tecmobw3RomDesc[] = { + { "tecmo super bowl iii - final edition (usa).bin", 0x200000, 0xaae4089f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmobw3) +STD_ROM_FN(md_tecmobw3) + +struct BurnDriver BurnDrvmd_tecmobw3 = { + "md_tecmobw3", NULL, NULL, NULL, "1995", + "Tecmo Super Bowl III - Final Edition (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmobw3RomInfo, md_tecmobw3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super Hockey (USA) +static struct BurnRomInfo md_tecmohckRomDesc[] = { + { "tecmo super hockey (usa).bin", 0x100000, 0x5f86ddc9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmohck) +STD_ROM_FN(md_tecmohck) + +struct BurnDriver BurnDrvmd_tecmohck = { + "md_tecmohck", NULL, NULL, NULL, "1994", + "Tecmo Super Hockey (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmohckRomInfo, md_tecmohckRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super NBA Basketball (USA) +static struct BurnRomInfo md_tecmonbaRomDesc[] = { + { "tecmo super nba basketball (usa).bin", 0x100000, 0x53913991, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmonba) +STD_ROM_FN(md_tecmonba) + +struct BurnDriver BurnDrvmd_tecmonba = { + "md_tecmonba", NULL, NULL, NULL, "1993", + "Tecmo Super NBA Basketball (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmonbaRomInfo, md_tecmonbaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo Super NBA Basketball (Jpn) +static struct BurnRomInfo md_tecmonbajRomDesc[] = { + { "tecmo super nba basketball (jpn).bin", 0x100000, 0x79f33eb6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmonbaj) +STD_ROM_FN(md_tecmonbaj) + +struct BurnDriver BurnDrvmd_tecmonbaj = { + "md_tecmonbaj", "md_tecmonba", NULL, NULL, "1994", + "Tecmo Super NBA Basketball (Jpn)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tecmonbajRomInfo, md_tecmonbajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo World Cup '92 (Jpn) +static struct BurnRomInfo md_tecmow92RomDesc[] = { + { "tecmo world cup '92 (jpn).bin", 0x040000, 0x5e93c8b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmow92) +STD_ROM_FN(md_tecmow92) + +struct BurnDriver BurnDrvmd_tecmow92 = { + "md_tecmow92", NULL, NULL, NULL, "1992", + "Tecmo World Cup '92 (Jpn)\0", NULL, "Sims", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tecmow92RomInfo, md_tecmow92RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tecmo World Cup (USA) +static struct BurnRomInfo md_tecmowcRomDesc[] = { + { "tecmo world cup (usa).bin", 0x040000, 0xcaf8eb2c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tecmowc) +STD_ROM_FN(md_tecmowc) + +struct BurnDriver BurnDrvmd_tecmowc = { + "md_tecmowc", NULL, NULL, NULL, "1990", + "Tecmo World Cup (USA)\0", NULL, "Tecmo", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tecmowcRomInfo, md_tecmowcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teddy Boy Blues (Jpn, SegaNet) +static struct BurnRomInfo md_teddyboyRomDesc[] = { + { "teddy boy blues (jpn) (sn).bin", 0x040000, 0x733d2eb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_teddyboy) +STD_ROM_FN(md_teddyboy) + +struct BurnDriver BurnDrvmd_teddyboy = { + "md_teddyboy", NULL, NULL, NULL, "1991", + "Teddy Boy Blues (Jpn, SegaNet)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_teddyboyRomInfo, md_teddyboyRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Hero Turtles - The Hyperstone Heist (Euro) +static struct BurnRomInfo md_tmhtshRomDesc[] = { + { "teenage mutant hero turtles - the hyperstone heist (euro).bin", 0x100000, 0x966d5286, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmhtsh) +STD_ROM_FN(md_tmhtsh) + +struct BurnDriver BurnDrvmd_tmhtsh = { + "md_tmhtsh", NULL, NULL, NULL, "1992", + "Teenage Mutant Hero Turtles - The Hyperstone Heist (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmhtshRomInfo, md_tmhtshRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Ninja Turtles - Return of the Shredder (Jpn) +static struct BurnRomInfo md_tmntshjRomDesc[] = { + { "teenage mutant ninja turtles - return of the shredder (jpn).bin", 0x100000, 0x1b003498, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmntshj) +STD_ROM_FN(md_tmntshj) + +struct BurnDriver BurnDrvmd_tmntshj = { + "md_tmntshj", "md_tmhtsh", NULL, NULL, "1992", + "Teenage Mutant Ninja Turtles - Return of the Shredder (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmntshjRomInfo, md_tmntshjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Ninja Turtles - The Hyperstone Heist (USA) +static struct BurnRomInfo md_tmnthhRomDesc[] = { + { "teenage mutant ninja turtles - the hyperstone heist (usa).bin", 0x100000, 0x679c41de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmnthh) +STD_ROM_FN(md_tmnthh) + +struct BurnDriver BurnDrvmd_tmnthh = { + "md_tmnthh", "md_tmhtsh", NULL, NULL, "1992", + "Teenage Mutant Ninja Turtles - The Hyperstone Heist (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmnthhRomInfo, md_tmnthhRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Hero Turtles - Tournament Fighters (Euro) +static struct BurnRomInfo md_tmhttfRomDesc[] = { + { "teenage mutant hero turtles - tournament fighters (euro).bin", 0x200000, 0x3cd2b7e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmhttf) +STD_ROM_FN(md_tmhttf) + +struct BurnDriver BurnDrvmd_tmhttf = { + "md_tmhttf", NULL, NULL, NULL, "1993", + "Teenage Mutant Hero Turtles - Tournament Fighters (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmhttfRomInfo, md_tmhttfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Ninja Turtles - Tournament Fighters (Jpn) +static struct BurnRomInfo md_tmnttfjRomDesc[] = { + { "teenage mutant ninja turtles - tournament fighters (jpn).bin", 0x200000, 0x8843f2c9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmnttfj) +STD_ROM_FN(md_tmnttfj) + +struct BurnDriver BurnDrvmd_tmnttfj = { + "md_tmnttfj", "md_tmhttf", NULL, NULL, "1993", + "Teenage Mutant Ninja Turtles - Tournament Fighters (Jpn)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmnttfjRomInfo, md_tmnttfjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Teenage Mutant Ninja Turtles - Tournament Fighters (USA) +static struct BurnRomInfo md_tmnttfuRomDesc[] = { + { "teenage mutant ninja turtles - tournament fighters (usa).bin", 0x200000, 0x95b5484d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tmnttfu) +STD_ROM_FN(md_tmnttfu) + +struct BurnDriver BurnDrvmd_tmnttfu = { + "md_tmnttfu", "md_tmhttf", NULL, NULL, "1993", + "Teenage Mutant Ninja Turtles - Tournament Fighters (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tmnttfuRomInfo, md_tmnttfuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tekken 3 Special +static struct BurnRomInfo md_tekkn3spRomDesc[] = { + { "tekken 3 special (unl).bin", 0x200000, 0x7fcae658, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tekkn3sp) +STD_ROM_FN(md_tekkn3sp) + +struct BurnDriver BurnDrvmd_tekkn3sp = { + "md_tekkn3sp", NULL, NULL, NULL, "199?", + "Tekken 3 Special\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tekkn3spRomInfo, md_tekkn3spRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tel-Tel Mahjong (Jpn) +static struct BurnRomInfo md_telmahRomDesc[] = { + { "tel-tel mahjong (jpn).bin", 0x040000, 0x44817e92, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_telmah) +STD_ROM_FN(md_telmah) + +struct BurnDriver BurnDrvmd_telmah = { + "md_telmah", NULL, NULL, NULL, "1990", + "Tel-Tel Mahjong (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_telmahRomInfo, md_telmahRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tel-Tel Stadium (Jpn) +static struct BurnRomInfo md_telstaRomDesc[] = { + { "md-tsd.bin", 0x080000, 0x54cf8c29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_telsta) +STD_ROM_FN(md_telsta) + +struct BurnDriver BurnDrvmd_telsta = { + "md_telsta", NULL, NULL, NULL, "1990", + "Tel-Tel Stadium (Jpn)\0", NULL, "Sunsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_telstaRomInfo, md_telstaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Telebradesco Residencia (Bra) +static struct BurnRomInfo md_telebrRomDesc[] = { + { "telebradesco residencia (bra).bin", 0x040000, 0x1db99045, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_telebr) +STD_ROM_FN(md_telebr) + +struct BurnDriver BurnDrvmd_telebr = { + "md_telebr", NULL, NULL, NULL, "199?", + "Telebradesco Residencia (Bra)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_telebrRomInfo, md_telebrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Terminator (Euro) +static struct BurnRomInfo md_termintrRomDesc[] = { + { "mpr-14925.bin", 0x100000, 0x15f4d302, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_termintr) +STD_ROM_FN(md_termintr) + +struct BurnDriver BurnDrvmd_termintr = { + "md_termintr", NULL, NULL, NULL, "1991", + "The Terminator (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_termintrRomInfo, md_termintrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Terminator (USA) +static struct BurnRomInfo md_termintruRomDesc[] = { + { "terminator, the (usa).bin", 0x100000, 0x31a629be, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_termintru) +STD_ROM_FN(md_termintru) + +struct BurnDriver BurnDrvmd_termintru = { + "md_termintru", "md_termintr", NULL, NULL, "1991", + "The Terminator (USA)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_termintruRomInfo, md_termintruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Test Drive II - The Duel (Euro, USA) +static struct BurnRomInfo md_testdrv2RomDesc[] = { + { "test drive ii - the duel (euro, usa).bin", 0x100000, 0xf9bdf8c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_testdrv2) +STD_ROM_FN(md_testdrv2) + +struct BurnDriver BurnDrvmd_testdrv2 = { + "md_testdrv2", NULL, NULL, NULL, "1992", + "Test Drive II - The Duel (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_testdrv2RomInfo, md_testdrv2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tetris (Jpn) +static struct BurnRomInfo md_tetrisRomDesc[] = { + { "mpr-12356+mpr-12357.bin", 0x040000, 0x4ce90db0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tetris) +STD_ROM_FN(md_tetris) + +struct BurnDriver BurnDrvmd_tetris = { + "md_tetris", NULL, NULL, NULL, "1989", + "Tetris (Jpn)\0", NULL, "Tetris", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tetrisRomInfo, md_tetrisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Theme Park (Euro, USA) +static struct BurnRomInfo md_themeprkRomDesc[] = { + { "tpb10.bin", 0x200000, 0x289da2c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_themeprk) +STD_ROM_FN(md_themeprk) + +struct BurnDriver BurnDrvmd_themeprk = { + "md_themeprk", NULL, NULL, NULL, "1995", + "Theme Park (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_themeprkRomInfo, md_themeprkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The New Zealand Story (Jpn) +static struct BurnRomInfo md_tnzsRomDesc[] = { + { "new zealand story, the (jpn).bin", 0x080000, 0x1c77ad21, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tnzs) +STD_ROM_FN(md_tnzs) + +struct BurnDriver BurnDrvmd_tnzs = { + "md_tnzs", NULL, NULL, NULL, "1990", + "The New Zealand Story (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tnzsRomInfo, md_tnzsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thomas the Tank Engine & Friends (USA) +static struct BurnRomInfo md_thomasRomDesc[] = { + { "thomas the tank engine & friends (usa).bin", 0x100000, 0x1a406299, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_thomas) +STD_ROM_FN(md_thomas) + +struct BurnDriver BurnDrvmd_thomas = { + "md_thomas", NULL, NULL, NULL, "1993", + "Thomas the Tank Engine & Friends (USA)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_thomasRomInfo, md_thomasRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Force II (Euro, USA) +static struct BurnRomInfo md_tf2RomDesc[] = { + { "mpr-12559.bin", 0x080000, 0x9b1561b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tf2) +STD_ROM_FN(md_tf2) + +struct BurnDriver BurnDrvmd_tf2 = { + "md_tf2", NULL, NULL, NULL, "1989", + "Thunder Force II (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tf2RomInfo, md_tf2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Force II MD (Jpn) +static struct BurnRomInfo md_tf2jRomDesc[] = { + { "thunder force ii md (jpn).bin", 0x080000, 0xe75ec3e0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tf2j) +STD_ROM_FN(md_tf2j) + +struct BurnDriver BurnDrvmd_tf2j = { + "md_tf2j", "md_tf2", NULL, NULL, "1989", + "Thunder Force II MD (Jpn)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tf2jRomInfo, md_tf2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Force III (Jpn, USA) +static struct BurnRomInfo md_tf3RomDesc[] = { + { "thunder force iii (usa, jpn).bin", 0x080000, 0x1b3f399a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tf3) +STD_ROM_FN(md_tf3) + +struct BurnDriver BurnDrvmd_tf3 = { + "md_tf3", NULL, NULL, NULL, "1990", + "Thunder Force III (Jpn, USA)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tf3RomInfo, md_tf3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Force IV (Euro) +static struct BurnRomInfo md_tf4RomDesc[] = { + { "mpr-15209.bin", 0x100000, 0xe7e3c05b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tf4) +STD_ROM_FN(md_tf4) + +struct BurnDriver BurnDrvmd_tf4 = { + "md_tf4", NULL, NULL, NULL, "1993", + "Thunder Force IV (Euro)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tf4RomInfo, md_tf4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Force IV (Jpn) +static struct BurnRomInfo md_tf4jRomDesc[] = { + { "thunder force iv (jpn).bin", 0x100000, 0x8d606480, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tf4j) +STD_ROM_FN(md_tf4j) + +struct BurnDriver BurnDrvmd_tf4j = { + "md_tf4j", "md_tf4", NULL, NULL, "1992", + "Thunder Force IV (Jpn)\0", NULL, "Technosoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tf4jRomInfo, md_tf4jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lightening Force - Quest for the Darkstar (USA) +static struct BurnRomInfo md_lightforRomDesc[] = { + { "lightening force - quest for the darkstar (usa).bin", 0x100000, 0xc8f8c0e0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lightfor) +STD_ROM_FN(md_lightfor) + +struct BurnDriver BurnDrvmd_lightfor = { + "md_lightfor", "md_tf4", NULL, NULL, "1992", + "Lightening Force - Quest for the Darkstar (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lightforRomInfo, md_lightforRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Fox (USA) +static struct BurnRomInfo md_tfoxRomDesc[] = { + { "thunder fox (usa).bin", 0x100000, 0x5463f50f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tfox) +STD_ROM_FN(md_tfox) + +struct BurnDriver BurnDrvmd_tfox = { + "md_tfox", NULL, NULL, NULL, "1991", + "Thunder Fox (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tfoxRomInfo, md_tfoxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Fox (Jpn) +static struct BurnRomInfo md_tfoxjRomDesc[] = { + { "thunder fox (jpn).bin", 0x100000, 0xeca6cffa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tfoxj) +STD_ROM_FN(md_tfoxj) + +struct BurnDriver BurnDrvmd_tfoxj = { + "md_tfoxj", "md_tfox", NULL, NULL, "1991", + "Thunder Fox (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tfoxjRomInfo, md_tfoxjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Thunder Pro Wrestling Retsuden (Jpn) +static struct BurnRomInfo md_tpwresRomDesc[] = { + { "mpr-14675.bin", 0x080000, 0x24408c73, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tpwres) +STD_ROM_FN(md_tpwres) + +struct BurnDriver BurnDrvmd_tpwres = { + "md_tpwres", NULL, NULL, NULL, "1992", + "Thunder Pro Wrestling Retsuden (Jpn)\0", NULL, "Human", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tpwresRomInfo, md_tpwresRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Tick (USA) +static struct BurnRomInfo md_tickRomDesc[] = { + { "tick, the (usa).bin", 0x200000, 0x425132f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tick) +STD_ROM_FN(md_tick) + +struct BurnDriver BurnDrvmd_tick = { + "md_tick", NULL, NULL, NULL, "1994", + "The Tick (USA)\0", NULL, "Fox Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tickRomInfo, md_tickRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Time Killers (Euro) +static struct BurnRomInfo md_timekillRomDesc[] = { + { "time killers (euro).bin", 0x200000, 0xa4f48a1a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_timekill) +STD_ROM_FN(md_timekill) + +struct BurnDriver BurnDrvmd_timekill = { + "md_timekill", NULL, NULL, NULL, "1996", + "Time Killers (Euro)\0", NULL, "Black Pearl", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_timekillRomInfo, md_timekillRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Time Killers (USA) +static struct BurnRomInfo md_timekilluRomDesc[] = { + { "time killers (usa).bin", 0x200000, 0x4b5f52ac, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_timekillu) +STD_ROM_FN(md_timekillu) + +struct BurnDriver BurnDrvmd_timekillu = { + "md_timekillu", "md_timekill", NULL, NULL, "1996", + "Time Killers (USA)\0", NULL, "Black Pearl", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_timekilluRomInfo, md_timekilluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// TinHead (USA) +static struct BurnRomInfo md_tinheadRomDesc[] = { + { "tinhead (usa).bin", 0x100000, 0xd6724b84, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tinhead) +STD_ROM_FN(md_tinhead) + +struct BurnDriver BurnDrvmd_tinhead = { + "md_tinhead", NULL, NULL, NULL, "1993", + "TinHead (USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tinheadRomInfo, md_tinheadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tintin au Tibet (Euro) +static struct BurnRomInfo md_tintinRomDesc[] = { + { "tintin au tibet (euro).bin", 0x200000, 0x4243caf3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tintin) +STD_ROM_FN(md_tintin) + +struct BurnDriver BurnDrvmd_tintin = { + "md_tintin", NULL, NULL, NULL, "1995", + "Tintin au Tibet (Euro)\0", NULL, "Infogrames", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tintinRomInfo, md_tintinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures - Acme All-Stars (Euro) +static struct BurnRomInfo md_ttacmeRomDesc[] = { + { "mpr-17066.bin", 0x100000, 0x1227b2b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttacme) +STD_ROM_FN(md_ttacme) + +struct BurnDriver BurnDrvmd_ttacme = { + "md_ttacme", NULL, NULL, NULL, "1994", + "Tiny Toon Adventures - Acme All-Stars (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttacmeRomInfo, md_ttacmeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures - Acme All-Stars (USA, Kor) +static struct BurnRomInfo md_ttacmeuRomDesc[] = { + { "tiny toon adventures - acme all-stars (usa, kor).bin", 0x100000, 0x2f9faa1d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttacmeu) +STD_ROM_FN(md_ttacmeu) + +struct BurnDriver BurnDrvmd_ttacmeu = { + "md_ttacmeu", "md_ttacme", NULL, NULL, "1994", + "Tiny Toon Adventures - Acme All-Stars (USA, Kor)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttacmeuRomInfo, md_ttacmeuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures - Buster's Hidden Treasure (Euro) +static struct BurnRomInfo md_ttoonbblRomDesc[] = { + { "mpr-15406.bin", 0x080000, 0xd10fba51, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttoonbbl) +STD_ROM_FN(md_ttoonbbl) + +struct BurnDriver BurnDrvmd_ttoonbbl = { + "md_ttoonbbl", NULL, NULL, NULL, "1993", + "Tiny Toon Adventures - Buster's Hidden Treasure (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttoonbblRomInfo, md_ttoonbblRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures (Kor) +static struct BurnRomInfo md_ttoonbblkRomDesc[] = { + { "tiny toon adventures (kor).bin", 0x080000, 0x4ca3a8fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttoonbblk) +STD_ROM_FN(md_ttoonbblk) + +struct BurnDriver BurnDrvmd_ttoonbblk = { + "md_ttoonbblk", "md_ttoonbbl", NULL, NULL, "1993", + "Tiny Toon Adventures (Kor)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttoonbblkRomInfo, md_ttoonbblkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures - Buster's Hidden Treasure (USA) +static struct BurnRomInfo md_ttoonbbluRomDesc[] = { + { "tiny toon adventures - buster's hidden treasure (usa).bin", 0x080000, 0xa26d3ae0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttoonbblu) +STD_ROM_FN(md_ttoonbblu) + +struct BurnDriver BurnDrvmd_ttoonbblu = { + "md_ttoonbblu", "md_ttoonbbl", NULL, NULL, "1993", + "Tiny Toon Adventures - Buster's Hidden Treasure (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttoonbbluRomInfo, md_ttoonbbluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// TNN Bass Tournament of Champions (USA) +static struct BurnRomInfo md_tnnbassRomDesc[] = { + { "tnn bass tournament of champions (usa).bin", 0x100000, 0xc83ffa1b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tnnbass) +STD_ROM_FN(md_tnnbass) + +struct BurnDriver BurnDrvmd_tnnbass = { + "md_tnnbass", NULL, NULL, NULL, "1993", + "TNN Bass Tournament of Champions (USA)\0", NULL, "American Softworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tnnbassRomInfo, md_tnnbassRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// TNN Outdoors Bass Tournament '96 (USA) +static struct BurnRomInfo md_tnnoutRomDesc[] = { + { "tnn outdoors bass tournament '96 (usa).bin", 0x200000, 0x5c523c0b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tnnout) +STD_ROM_FN(md_tnnout) + +struct BurnDriver BurnDrvmd_tnnout = { + "md_tnnout", NULL, NULL, NULL, "1996", + "TNN Outdoors Bass Tournament '96 (USA)\0", NULL, "American Softworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tnnoutRomInfo, md_tnnoutRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Todd's Adventures in Slime World (USA) +static struct BurnRomInfo md_slimewRomDesc[] = { + { "todd's adventures in slime world (usa).bin", 0x080000, 0x652e8b7d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slimew) +STD_ROM_FN(md_slimew) + +struct BurnDriver BurnDrvmd_slimew = { + "md_slimew", NULL, NULL, NULL, "1991", + "Todd's Adventures in Slime World (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slimewRomInfo, md_slimewRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Slime World (Jpn) +static struct BurnRomInfo md_slimewjRomDesc[] = { + { "slime world (jpn).bin", 0x080000, 0x7ff5529f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_slimewj) +STD_ROM_FN(md_slimewj) + +struct BurnDriver BurnDrvmd_slimewj = { + "md_slimewj", "md_slimew", NULL, NULL, "1992", + "Slime World (Jpn)\0", NULL, "Micro World", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_slimewjRomInfo, md_slimewjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl (World, Rev. A) +static struct BurnRomInfo md_toejamRomDesc[] = { + { "mpr-14236a.bin", 0x100000, 0x7a588f4b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toejam) +STD_ROM_FN(md_toejam) + +struct BurnDriver BurnDrvmd_toejam = { + "md_toejam", NULL, NULL, NULL, "1992", + "Toe Jam & Earl (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toejamRomInfo, md_toejamRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl (World) +static struct BurnRomInfo md_toejam1RomDesc[] = { + { "toe jam & earl (world).bin", 0x100000, 0xd1b36786, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toejam1) +STD_ROM_FN(md_toejam1) + +struct BurnDriver BurnDrvmd_toejam1 = { + "md_toejam1", "md_toejam", NULL, NULL, "1992", + "Toe Jam & Earl (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toejam1RomInfo, md_toejam1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl in Panic on Funkotron (Euro) +static struct BurnRomInfo md_tje2RomDesc[] = { + { "mpr-16179.bin", 0x200000, 0x47b0a871, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tje2) +STD_ROM_FN(md_tje2) + +struct BurnDriver BurnDrvmd_tje2 = { + "md_tje2", NULL, NULL, NULL, "1993", + "Toe Jam & Earl in Panic on Funkotron (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tje2RomInfo, md_tje2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl in Panic auf Funkotron (Ger) +static struct BurnRomInfo md_tje2gRomDesc[] = { + { "toe jam & earl in panic auf funkotron (germany).bin", 0x200000, 0x4081b9f2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tje2g) +STD_ROM_FN(md_tje2g) + +struct BurnDriver BurnDrvmd_tje2g = { + "md_tje2g", "md_tje2", NULL, NULL, "1993", + "Toe Jam & Earl in Panic auf Funkotron (Ger)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tje2gRomInfo, md_tje2gRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl in Panic on Funkotron (Jpn) +static struct BurnRomInfo md_tje2jRomDesc[] = { + { "toe jam & earl in panic on funkotron (jpn).bin", 0x200000, 0xe1b36850, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tje2j) +STD_ROM_FN(md_tje2j) + +struct BurnDriver BurnDrvmd_tje2j = { + "md_tje2j", "md_tje2", NULL, NULL, "1993", + "Toe Jam & Earl in Panic on Funkotron (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tje2jRomInfo, md_tje2jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toe Jam & Earl in Panic on Funkotron (USA) +static struct BurnRomInfo md_tje2uRomDesc[] = { + { "toe jam & earl in panic on funkotron (usa).bin", 0x200000, 0xaa021bdd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tje2u) +STD_ROM_FN(md_tje2u) + +struct BurnDriver BurnDrvmd_tje2u = { + "md_tje2u", "md_tje2", NULL, NULL, "1993", + "Toe Jam & Earl in Panic on Funkotron (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tje2uRomInfo, md_tje2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toki - Going Ape Spit ~ JuJu Densetsu (World, Rev. A) +static struct BurnRomInfo md_tokiRomDesc[] = { + { "mpr-14464a.bin", 0x080000, 0x7362c3f4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toki) +STD_ROM_FN(md_toki) + +struct BurnDriver BurnDrvmd_toki = { + "md_toki", NULL, NULL, NULL, "1991", + "Toki - Going Ape Spit ~ JuJu Densetsu (World, Rev. A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tokiRomInfo, md_tokiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toki - Going Ape Spit ~ JuJu Densetsu (World) +static struct BurnRomInfo md_toki1RomDesc[] = { + { "toki - going ape spit -- juju densetsu (world).bin", 0x080000, 0xd09b1ef1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toki1) +STD_ROM_FN(md_toki1) + +struct BurnDriver BurnDrvmd_toki1 = { + "md_toki1", "md_toki", NULL, NULL, "1991", + "Toki - Going Ape Spit ~ JuJu Densetsu (World)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toki1RomInfo, md_toki1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tom and Jerry - Frantic Antics (USA, 1993) +static struct BurnRomInfo md_tomjerryRomDesc[] = { + { "tom and jerry - frantic antics (usa) (1993).bin", 0x100000, 0xb9992e1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tomjerry) +STD_ROM_FN(md_tomjerry) + +struct BurnDriver BurnDrvmd_tomjerry = { + "md_tomjerry", NULL, NULL, NULL, "1993", + "Tom and Jerry - Frantic Antics (USA, 1993)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tomjerryRomInfo, md_tomjerryRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tom and Jerry - Frantic Antics (USA, 1994) +static struct BurnRomInfo md_tomjerry1RomDesc[] = { + { "tom and jerry - frantic antics (usa) (1994).bin", 0x100000, 0x3044460c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tomjerry1) +STD_ROM_FN(md_tomjerry1) + +struct BurnDriver BurnDrvmd_tomjerry1 = { + "md_tomjerry1", "md_tomjerry", NULL, NULL, "1994", + "Tom and Jerry - Frantic Antics (USA, 1994)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tomjerry1RomInfo, md_tomjerry1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tony La Russa Baseball (USA, Oceania) +static struct BurnRomInfo md_tonylrbRomDesc[] = { + { "tony la russa baseball (usa, aus).bin", 0x100000, 0x24629c78, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tonylrb) +STD_ROM_FN(md_tonylrb) + +struct BurnDriver BurnDrvmd_tonylrb = { + "md_tonylrb", NULL, NULL, NULL, "1993", + "Tony La Russa Baseball (USA, Oceania)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tonylrbRomInfo, md_tonylrbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Top Gear 2 (USA) +static struct BurnRomInfo md_topgear2RomDesc[] = { + { "top gear 2 (usa).bin", 0x100000, 0xbd3074d2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_topgear2) +STD_ROM_FN(md_topgear2) + +struct BurnDriver BurnDrvmd_topgear2 = { + "md_topgear2", NULL, NULL, NULL, "1994", + "Top Gear 2 (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_topgear2RomInfo, md_topgear2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Top Pro Golf (Jpn) +static struct BurnRomInfo md_topgolfRomDesc[] = { + { "mpr-14853.bin", 0x100000, 0x62bad606, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_topgolf) +STD_ROM_FN(md_topgolf) + +struct BurnDriver BurnDrvmd_topgolf = { + "md_topgolf", NULL, NULL, NULL, "1992", + "Top Pro Golf (Jpn)\0", NULL, "Soft Vision", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_topgolfRomInfo, md_topgolfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Top Pro Golf 2 (Jpn) +static struct BurnRomInfo md_topgolf2RomDesc[] = { + { "top pro golf 2 (jpn).bin", 0x100000, 0xb8ce98b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_topgolf2) +STD_ROM_FN(md_topgolf2) + +struct BurnDriver BurnDrvmd_topgolf2 = { + "md_topgolf2", "md_chichi", NULL, NULL, "1993", + "Top Pro Golf 2 (Jpn)\0", NULL, "Soft Vision International", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_topgolf2RomInfo, md_topgolf2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Total Football (Euro) +static struct BurnRomInfo md_totlfootRomDesc[] = { + { "total football (euro).bin", 0x200000, 0x8360b66a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_totlfoot) +STD_ROM_FN(md_totlfoot) + +struct BurnDriver BurnDrvmd_totlfoot = { + "md_totlfoot", NULL, NULL, NULL, "1995", + "Total Football (Euro)\0", NULL, "Domark", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_totlfootRomInfo, md_totlfootRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toughman Contest (Euro, USA) +static struct BurnRomInfo md_toughmanRomDesc[] = { + { "toughman contest (euro, usa).bin", 0x400000, 0xe19fbc93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toughman) +STD_ROM_FN(md_toughman) + +struct BurnDriver BurnDrvmd_toughman = { + "md_toughman", NULL, NULL, NULL, "1995", + "Toughman Contest (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toughmanRomInfo, md_toughmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toxic Crusaders (USA) +static struct BurnRomInfo md_toxiccRomDesc[] = { + { "toxic crusaders (usa).bin", 0x080000, 0x11fd46ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toxicc) +STD_ROM_FN(md_toxicc) + +struct BurnDriver BurnDrvmd_toxicc = { + "md_toxicc", NULL, NULL, NULL, "1992", + "Toxic Crusaders (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toxiccRomInfo, md_toxiccRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toy Story (Euro) +static struct BurnRomInfo md_toystoryRomDesc[] = { + { "mpr-18848.bin", 0x400000, 0x8e89a9f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toystory) +STD_ROM_FN(md_toystory) + +struct BurnDriver BurnDrvmd_toystory = { + "md_toystory", NULL, NULL, NULL, "1996", + "Toy Story (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toystoryRomInfo, md_toystoryRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toy Story (USA) +static struct BurnRomInfo md_toystoryuRomDesc[] = { + { "toy story (usa).bin", 0x400000, 0x829fe313, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toystoryu) +STD_ROM_FN(md_toystoryu) + +struct BurnDriver BurnDrvmd_toystoryu = { + "md_toystoryu", "md_toystory", NULL, NULL, "1996", + "Toy Story (USA)\0", NULL, "Disney Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toystoryuRomInfo, md_toystoryuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Toys (USA) +static struct BurnRomInfo md_toysRomDesc[] = { + { "mpr-15574.bin", 0x100000, 0xcbc9951b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_toys) +STD_ROM_FN(md_toys) + +struct BurnDriver BurnDrvmd_toys = { + "md_toys", NULL, NULL, NULL, "1993", + "Toys (USA)\0", NULL, "Absolute Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_toysRomInfo, md_toysRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Trampoline Terror! (USA) +static struct BurnRomInfo md_trampoliRomDesc[] = { + { "trampoline terror! (usa).bin", 0x040000, 0xaabb349f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_trampoli) +STD_ROM_FN(md_trampoli) + +struct BurnDriver BurnDrvmd_trampoli = { + "md_trampoli", NULL, NULL, NULL, "1990", + "Trampoline Terror! (USA)\0", NULL, "Dreamworks", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_trampoliRomInfo, md_trampoliRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Traysia (USA) +static struct BurnRomInfo md_traysiaRomDesc[] = { + { "traysia (usa).bin", 0x100000, 0x96184f4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_traysia) +STD_ROM_FN(md_traysia) + +struct BurnDriver BurnDrvmd_traysia = { + "md_traysia", NULL, NULL, NULL, "1992", + "Traysia (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_traysiaRomInfo, md_traysiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Minato no Traysia (Jpn) +static struct BurnRomInfo md_traysiajRomDesc[] = { + { "minato no traysia (jpn).bin", 0x100000, 0xbd89fd09, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_traysiaj) +STD_ROM_FN(md_traysiaj) + +struct BurnDriver BurnDrvmd_traysiaj = { + "md_traysiaj", "md_traysia", NULL, NULL, "1992", + "Minato no Traysia (Jpn)\0", NULL, "Riot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_traysiajRomInfo, md_traysiajRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Triple Play '96 (USA) +static struct BurnRomInfo md_triple96RomDesc[] = { + { "triple play '96 (usa).bin", 0x400000, 0xf1748e91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_triple96) +STD_ROM_FN(md_triple96) + +struct BurnDriver BurnDrvmd_triple96 = { + "md_triple96", NULL, NULL, NULL, "1995", + "Triple Play '96 (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_triple96RomInfo, md_triple96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Triple Play Gold (USA) +static struct BurnRomInfo md_tpgoldRomDesc[] = { + { "triple play gold (usa).bin", 0x400000, 0xbbe69017, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tpgold) +STD_ROM_FN(md_tpgold) + +struct BurnDriver BurnDrvmd_tpgold = { + "md_tpgold", NULL, NULL, NULL, "1996", + "Triple Play Gold (USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tpgoldRomInfo, md_tpgoldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Triple Play Gold (USA, Alt) +static struct BurnRomInfo md_tpgoldaRomDesc[] = { + { "triple play gold (usa) (alt).bin", 0x400000, 0xa89638a0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tpgolda) +STD_ROM_FN(md_tpgolda) + +struct BurnDriver BurnDrvmd_tpgolda = { + "md_tpgolda", "md_tpgold", NULL, NULL, "1995", + "Triple Play Gold (USA, Alt)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_tpgoldaRomInfo, md_tpgoldaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Trouble Shooter (USA) +static struct BurnRomInfo md_troubshtRomDesc[] = { + { "trouble shooter (usa).bin", 0x080000, 0xbecfc39b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_troubsht) +STD_ROM_FN(md_troubsht) + +struct BurnDriver BurnDrvmd_troubsht = { + "md_troubsht", NULL, NULL, NULL, "1991", + "Trouble Shooter (USA)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_troubshtRomInfo, md_troubshtRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Battle Mania (Jpn) +static struct BurnRomInfo md_btlmaniaRomDesc[] = { + { "battle mania (jpn).bin", 0x080000, 0xa76c4a29, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_btlmania) +STD_ROM_FN(md_btlmania) + +struct BurnDriver BurnDrvmd_btlmania = { + "md_btlmania", "md_troubsht", NULL, NULL, "1992", + "Battle Mania (Jpn)\0", NULL, "Vic Tokai", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_btlmaniaRomInfo, md_btlmaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Troy Aikman NFL Football (USA) +static struct BurnRomInfo md_troyaikRomDesc[] = { + { "troy aikman nfl football (usa).bin", 0x200000, 0x015f2713, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_troyaik) +STD_ROM_FN(md_troyaik) + +struct BurnDriver BurnDrvmd_troyaik = { + "md_troyaik", NULL, NULL, NULL, "1994", + "Troy Aikman NFL Football (USA)\0", NULL, "Tradewest", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_troyaikRomInfo, md_troyaikRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// True Lies (World) +static struct BurnRomInfo md_trueliesRomDesc[] = { + { "true lies (world).bin", 0x200000, 0x18c09468, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_truelies) +STD_ROM_FN(md_truelies) + +struct BurnDriver BurnDrvmd_truelies = { + "md_truelies", NULL, NULL, NULL, "1995", + "True Lies (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_trueliesRomInfo, md_trueliesRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tun Shi Tian Di III (China, Simple Chinese) +static struct BurnRomInfo md_tunshiRomDesc[] = { + { "tun shi tian di iii (chi) (simple chinese) (unl).bin", 0x200000, 0xea57b668, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tunshi) +STD_ROM_FN(md_tunshi) + +struct BurnDriver BurnDrvmd_tunshi = { + "md_tunshi", NULL, NULL, NULL, "199?", + "Tun Shi Tian Di III (China, Simple Chinese)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tunshiRomInfo, md_tunshiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tun Shi Tian Di III (Chi) +static struct BurnRomInfo md_tunshi1RomDesc[] = { + { "tun shi tian di iii (chi) (unl).bin", 0x200000, 0xb23c4166, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tunshi1) +STD_ROM_FN(md_tunshi1) + +struct BurnDriver BurnDrvmd_tunshi1 = { + "md_tunshi1", "md_tunshi", NULL, NULL, "199?", + "Tun Shi Tian Di III (Chi)\0", NULL, "SKOB", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tunshi1RomInfo, md_tunshi1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Turbo OutRun (Euro, Jpn) +static struct BurnRomInfo md_turbooutRomDesc[] = { + { "turbo outrun (euro, jpn).bin", 0x080000, 0x0c661369, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_turboout) +STD_ROM_FN(md_turboout) + +struct BurnDriver BurnDrvmd_turboout = { + "md_turboout", NULL, NULL, NULL, "1992", + "Turbo OutRun (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_turbooutRomInfo, md_turbooutRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Turrican (Euro, USA) +static struct BurnRomInfo md_turricanRomDesc[] = { + { "turrican (euro, usa).bin", 0x080000, 0x634d67a6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_turrican) +STD_ROM_FN(md_turrican) + +struct BurnDriver BurnDrvmd_turrican = { + "md_turrican", NULL, NULL, NULL, "1991", + "Turrican (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_turricanRomInfo, md_turricanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Twin Cobra (USA) +static struct BurnRomInfo md_twincobrRomDesc[] = { + { "twin cobra (usa).bin", 0x0a0000, 0x2c708248, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twincobr) +STD_ROM_FN(md_twincobr) + +struct BurnDriver BurnDrvmd_twincobr = { + "md_twincobr", NULL, NULL, NULL, "1991", + "Twin Cobra (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twincobrRomInfo, md_twincobrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kyuukyoku Tiger (Jpn) +static struct BurnRomInfo md_kyuukyokRomDesc[] = { + { "kyuukyoku tiger (jpn).bin", 0x0a0000, 0x61276d21, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kyuukyok) +STD_ROM_FN(md_kyuukyok) + +struct BurnDriver BurnDrvmd_kyuukyok = { + "md_kyuukyok", "md_twincobr", NULL, NULL, "1991", + "Kyuukyoku Tiger (Jpn)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kyuukyokRomInfo, md_kyuukyokRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Twinkle Tale (Jpn) +static struct BurnRomInfo md_twinkletRomDesc[] = { + { "twinkle tale (jpn).bin", 0x100000, 0xd757f924, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twinklet) +STD_ROM_FN(md_twinklet) + +struct BurnDriver BurnDrvmd_twinklet = { + "md_twinklet", NULL, NULL, NULL, "1992", + "Twinkle Tale (Jpn)\0", NULL, "Toyo Records", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twinkletRomInfo, md_twinkletRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Twin Hawk (Euro) ~ Daisenpuu (Jpn) +static struct BurnRomInfo md_twinhawkRomDesc[] = { + { "twin hawk -- daisenpuu (euro, jpn).bin", 0x080000, 0xa2ec8c67, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twinhawk) +STD_ROM_FN(md_twinhawk) + +struct BurnDriver BurnDrvmd_twinhawk = { + "md_twinhawk", NULL, NULL, NULL, "1990", + "Twin Hawk (Euro) ~ Daisenpuu (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twinhawkRomInfo, md_twinhawkRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Two Crude Dudes (Euro) +static struct BurnRomInfo md_twocrudeRomDesc[] = { + { "two crude dudes (euro).bin", 0x100000, 0xb6d90a10, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twocrude) +STD_ROM_FN(md_twocrude) + +struct BurnDriver BurnDrvmd_twocrude = { + "md_twocrude", NULL, NULL, NULL, "1992", + "Two Crude Dudes (Euro)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twocrudeRomInfo, md_twocrudeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Two Crude Dudes (USA) +static struct BurnRomInfo md_twocrudeuRomDesc[] = { + { "two crude dudes (usa).bin", 0x100000, 0x721b5744, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twocrudeu) +STD_ROM_FN(md_twocrudeu) + +struct BurnDriver BurnDrvmd_twocrudeu = { + "md_twocrudeu", "md_twocrude", NULL, NULL, "1992", + "Two Crude Dudes (USA)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twocrudeuRomInfo, md_twocrudeuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crude Buster (Jpn) +static struct BurnRomInfo md_crudebRomDesc[] = { + { "crude buster (jpn).bin", 0x100000, 0xaffb4b00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crudeb) +STD_ROM_FN(md_crudeb) + +struct BurnDriver BurnDrvmd_crudeb = { + "md_crudeb", "md_twocrude", NULL, NULL, "1992", + "Crude Buster (Jpn)\0", NULL, "Data East", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crudebRomInfo, md_crudebRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Two Tribes - Populous II (Euro) +static struct BurnRomInfo md_twotribeRomDesc[] = { + { "mpr-15652.bin", 0x100000, 0xee988bd9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_twotribe) +STD_ROM_FN(md_twotribe) + +struct BurnDriver BurnDrvmd_twotribe = { + "md_twotribe", NULL, NULL, NULL, "1993", + "Two Tribes - Populous II (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_twotribeRomInfo, md_twotribeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultimate Mortal Kombat 3 (Euro) +static struct BurnRomInfo md_umk3RomDesc[] = { + { "pal_ultimate_mk3.bin", 0x400000, 0xecfb5cb4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_umk3) +STD_ROM_FN(md_umk3) + +struct BurnDriver BurnDrvmd_umk3 = { + "md_umk3", NULL, NULL, NULL, "1996", + "Ultimate Mortal Kombat 3 (Euro)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_umk3RomInfo, md_umk3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultimate Mortal Kombat 3 (USA) +static struct BurnRomInfo md_umk3uRomDesc[] = { + { "ultimate mortal kombat 3 (usa).bin", 0x400000, 0x7290770d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_umk3u) +STD_ROM_FN(md_umk3u) + +struct BurnDriver BurnDrvmd_umk3u = { + "md_umk3u", "md_umk3", NULL, NULL, "1996", + "Ultimate Mortal Kombat 3 (USA)\0", NULL, "Williams", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_umk3uRomInfo, md_umk3uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultimate Qix (USA) +static struct BurnRomInfo md_ultqixRomDesc[] = { + { "ultimate qix (usa).bin", 0x040000, 0xd83369d9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ultqix) +STD_ROM_FN(md_ultqix) + +struct BurnDriver BurnDrvmd_ultqix = { + "md_ultqix", NULL, NULL, NULL, "1991", + "Ultimate Qix (USA)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ultqixRomInfo, md_ultqixRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Volfied (Jpn) +static struct BurnRomInfo md_volfiedRomDesc[] = { + { "volfied (jpn).bin", 0x040000, 0xb0c5e3f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_volfied) +STD_ROM_FN(md_volfied) + +struct BurnDriver BurnDrvmd_volfied = { + "md_volfied", "md_ultqix", NULL, NULL, "1991", + "Volfied (Jpn)\0", NULL, "Taito", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_volfiedRomInfo, md_volfiedRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultimate Soccer (Euro) +static struct BurnRomInfo md_ultsoccrRomDesc[] = { + { "mpr-15819.bin", 0x100000, 0x83db6e58, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ultsoccr) +STD_ROM_FN(md_ultsoccr) + +struct BurnDriver BurnDrvmd_ultsoccr = { + "md_ultsoccr", NULL, NULL, NULL, "1993", + "Ultimate Soccer (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ultsoccrRomInfo, md_ultsoccrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultraman (Jpn) +static struct BurnRomInfo md_ultramanRomDesc[] = { + { "ultraman (jpn).bin", 0x080000, 0x83b4d5fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ultraman) +STD_ROM_FN(md_ultraman) + +struct BurnDriver BurnDrvmd_ultraman = { + "md_ultraman", NULL, NULL, NULL, "1993", + "Ultraman (Jpn)\0", NULL, "Ma-Ba", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ultramanRomInfo, md_ultramanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Uncharted Waters (USA) +static struct BurnRomInfo md_unchartdRomDesc[] = { + { "uncharted waters (usa).bin", 0x100000, 0x4edaec59, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_unchartd) +STD_ROM_FN(md_unchartd) + +struct BurnDriver BurnDrvmd_unchartd = { + "md_unchartd", NULL, NULL, NULL, "1992", + "Uncharted Waters (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_unchartdRomInfo, md_unchartdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daikoukai Jidai (Jpn) +static struct BurnRomInfo md_daikoukaRomDesc[] = { + { "daikoukai jidai (jpn).bin", 0x100000, 0x5a652458, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daikouka) +STD_ROM_FN(md_daikouka) + +struct BurnDriver BurnDrvmd_daikouka = { + "md_daikouka", "md_unchartd", NULL, NULL, "1992", + "Daikoukai Jidai (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_daikoukaRomInfo, md_daikoukaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// New Horizons (USA) +static struct BurnRomInfo md_newhorizRomDesc[] = { + { "uncharted waters - new horizons (usa).bin", 0x200000, 0xead69824, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_newhoriz) +STD_ROM_FN(md_newhoriz) + +struct BurnDriver BurnDrvmd_newhoriz = { + "md_newhoriz", NULL, NULL, NULL, "1994", + "New Horizons (USA)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_newhorizRomInfo, md_newhorizRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Daikoukai Jidai II (Jpn) +static struct BurnRomInfo md_daikouk2RomDesc[] = { + { "daikoukai jidai ii (jpn).bin", 0x200000, 0xe040f0da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_daikouk2) +STD_ROM_FN(md_daikouk2) + +struct BurnDriver BurnDrvmd_daikouk2 = { + "md_daikouk2", "md_newhoriz", NULL, NULL, "1994", + "Daikoukai Jidai II (Jpn)\0", NULL, "Koei", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_daikouk2RomInfo, md_daikouk2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Undead Line (Jpn) +static struct BurnRomInfo md_undeadRomDesc[] = { + { "undead line (jpn).bin", 0x100000, 0xfb3ca1e6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_undead) +STD_ROM_FN(md_undead) + +struct BurnDriver BurnDrvmd_undead = { + "md_undead", NULL, NULL, NULL, "1991", + "Undead Line (Jpn)\0", NULL, "Palsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_undeadRomInfo, md_undeadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Universal Soldier (Euro, USA) +static struct BurnRomInfo md_universsRomDesc[] = { + { "universal soldier (euro, usa).bin", 0x100000, 0x352ebd49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_universs) +STD_ROM_FN(md_universs) + +struct BurnDriver BurnDrvmd_universs = { + "md_universs", NULL, NULL, NULL, "1992", + "Universal Soldier (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_universsRomInfo, md_universsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Unnecessary Roughness 95 (USA) +static struct BurnRomInfo md_unnecessRomDesc[] = { + { "unnecessary roughness 95 (usa).bin", 0x200000, 0x9920e7b7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_unnecess) +STD_ROM_FN(md_unnecess) + +struct BurnDriver BurnDrvmd_unnecess = { + "md_unnecess", NULL, NULL, NULL, "1994", + "Unnecessary Roughness 95 (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_unnecessRomInfo, md_unnecessRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Urban Strike (Euro, USA) +static struct BurnRomInfo md_urbanstrRomDesc[] = { + { "urban strike (euro, usa).bin", 0x200000, 0xcf690a75, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_urbanstr) +STD_ROM_FN(md_urbanstr) + +struct BurnDriver BurnDrvmd_urbanstr = { + "md_urbanstr", NULL, NULL, NULL, "1994", + "Urban Strike (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_urbanstrRomInfo, md_urbanstrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Uzu Keobukseon (Kor) +static struct BurnRomInfo md_uzukeoRomDesc[] = { + { "uzu keobukseon (kor).bin", 0x080000, 0xa7255ba8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_uzukeo) +STD_ROM_FN(md_uzukeo) + +struct BurnDriver BurnDrvmd_uzukeo = { + "md_uzukeo", NULL, NULL, NULL, "199?", + "Uzu Keobukseon (Kor)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_uzukeoRomInfo, md_uzukeoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Valis (USA) +static struct BurnRomInfo md_valisRomDesc[] = { + { "valis (usa).bin", 0x100000, 0x13bc5b72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_valis) +STD_ROM_FN(md_valis) + +struct BurnDriver BurnDrvmd_valis = { + "md_valis", NULL, NULL, NULL, "1991", + "Valis (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_valisRomInfo, md_valisRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mugen Senshi Valis (Jpn) +static struct BurnRomInfo md_valisjRomDesc[] = { + { "mugen senshi valis (jpn).bin", 0x100000, 0x24431625, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_valisj) +STD_ROM_FN(md_valisj) + +struct BurnDriver BurnDrvmd_valisj = { + "md_valisj", "md_valis", NULL, NULL, "1991", + "Mugen Senshi Valis (Jpn)\0", NULL, "Riot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_valisjRomInfo, md_valisjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Valis III (USA) +static struct BurnRomInfo md_valis3RomDesc[] = { + { "valis iii (usa).bin", 0x100000, 0x59a2a368, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_valis3) +STD_ROM_FN(md_valis3) + +struct BurnDriver BurnDrvmd_valis3 = { + "md_valis3", NULL, NULL, NULL, "1991", + "Valis III (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_valis3RomInfo, md_valis3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Valis III (Jpn, Rev. A) +static struct BurnRomInfo md_valis3jRomDesc[] = { + { "valis iii (jpn) (rev a).bin", 0x100000, 0x4d49a166, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_valis3j) +STD_ROM_FN(md_valis3j) + +struct BurnDriver BurnDrvmd_valis3j = { + "md_valis3j", "md_valis3", NULL, NULL, "1991", + "Valis III (Jpn, Rev. A)\0", NULL, "Reno", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_valis3jRomInfo, md_valis3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vapor Trail (USA) +static struct BurnRomInfo md_vaportrRomDesc[] = { + { "vapor trail (usa).bin", 0x100000, 0xc49e3a0a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vaportr) +STD_ROM_FN(md_vaportr) + +struct BurnDriver BurnDrvmd_vaportr = { + "md_vaportr", NULL, NULL, NULL, "1991", + "Vapor Trail (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vaportrRomInfo, md_vaportrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kuuga - Operation Code 'Vapor Trail' (Jpn) +static struct BurnRomInfo md_kuugaRomDesc[] = { + { "kuuga - operation code 'vapor trail' (jpn).bin", 0x100000, 0x83b6b6ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kuuga) +STD_ROM_FN(md_kuuga) + +struct BurnDriver BurnDrvmd_kuuga = { + "md_kuuga", "md_vaportr", NULL, NULL, "1991", + "Kuuga - Operation Code 'Vapor Trail' (Jpn)\0", NULL, "Riot", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kuugaRomInfo, md_kuugaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman (Euro, USA) +static struct BurnRomInfo md_vecmanRomDesc[] = { + { "vectorman (euro, usa).bin", 0x200000, 0xd38b3354, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman) +STD_ROM_FN(md_vecman) + +struct BurnDriver BurnDrvmd_vecman = { + "md_vecman", NULL, NULL, NULL, "1995", + "Vectorman (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecmanRomInfo, md_vecmanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman (Prototype) +static struct BurnRomInfo md_vecmanp1RomDesc[] = { + { "vectorman (beta).bin", 0x200000, 0xa315c8aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecmanp1) +STD_ROM_FN(md_vecmanp1) + +struct BurnDriver BurnDrvmd_vecmanp1 = { + "md_vecmanp1", "md_vecman", NULL, NULL, "1995", + "Vectorman (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecmanp1RomInfo, md_vecmanp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman (Prototype, Alt) +static struct BurnRomInfo md_vecmanp2RomDesc[] = { + { "vectorman (beta) (alt).bin", 0x200000, 0x2084d3da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecmanp2) +STD_ROM_FN(md_vecmanp2) + +struct BurnDriver BurnDrvmd_vecmanp2 = { + "md_vecmanp2", "md_vecman", NULL, NULL, "1995", + "Vectorman (Prototype, Alt)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecmanp2RomInfo, md_vecmanp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman (Prototype, 19950724) +static struct BurnRomInfo md_vecmanp3RomDesc[] = { + { "vectorman (prototype - jul 24, 1995).bin", 0x200000, 0x0145738b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecmanp3) +STD_ROM_FN(md_vecmanp3) + +struct BurnDriver BurnDrvmd_vecmanp3 = { + "md_vecmanp3", "md_vecman", NULL, NULL, "1995", + "Vectorman (Prototype, 19950724)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecmanp3RomInfo, md_vecmanp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (USA) +static struct BurnRomInfo md_vecman2RomDesc[] = { + { "vectorman 2 (usa).bin", 0x300000, 0xc1a24088, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2) +STD_ROM_FN(md_vecman2) + +struct BurnDriver BurnDrvmd_vecman2 = { + "md_vecman2", NULL, NULL, NULL, "1996", + "Vectorman 2 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2RomInfo, md_vecman2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype) +static struct BurnRomInfo md_vecman2p1RomDesc[] = { + { "vectorman 2 (beta).bin", 0x200000, 0xada2b0ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p1) +STD_ROM_FN(md_vecman2p1) + +struct BurnDriver BurnDrvmd_vecman2p1 = { + "md_vecman2p1", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p1RomInfo, md_vecman2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype, 19960815) +static struct BurnRomInfo md_vecman2p6RomDesc[] = { + { "vectorman 2 (prototype - aug 15, 1996).bin", 0x300000, 0x998b087c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p6) +STD_ROM_FN(md_vecman2p6) + +struct BurnDriver BurnDrvmd_vecman2p6 = { + "md_vecman2p6", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype, 19960815)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p6RomInfo, md_vecman2p6RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype, 19960816) +static struct BurnRomInfo md_vecman2p5RomDesc[] = { + { "vectorman 2 (prototype - aug 16, 1996).bin", 0x300000, 0x2986e5ce, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p5) +STD_ROM_FN(md_vecman2p5) + +struct BurnDriver BurnDrvmd_vecman2p5 = { + "md_vecman2p5", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype, 19960816)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p5RomInfo, md_vecman2p5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype, 19960819) +static struct BurnRomInfo md_vecman2p4RomDesc[] = { + { "vectorman 2 (prototype - aug 19, 1996).bin", 0x300000, 0x49efab7e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p4) +STD_ROM_FN(md_vecman2p4) + +struct BurnDriver BurnDrvmd_vecman2p4 = { + "md_vecman2p4", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype, 19960819)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p4RomInfo, md_vecman2p4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype, 19960826) +static struct BurnRomInfo md_vecman2p3RomDesc[] = { + { "vectorman 2 (prototype - aug 26, 1996).bin", 0x2a8e46, 0xeb8124c8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p3) +STD_ROM_FN(md_vecman2p3) + +struct BurnDriver BurnDrvmd_vecman2p3 = { + "md_vecman2p3", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype, 19960826)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p3RomInfo, md_vecman2p3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vectorman 2 (Prototype, 19960827) +static struct BurnRomInfo md_vecman2p2RomDesc[] = { + { "vectorman 2 (prototype - aug 27, 1996).bin", 0x300000, 0x6333d89a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vecman2p2) +STD_ROM_FN(md_vecman2p2) + +struct BurnDriver BurnDrvmd_vecman2p2 = { + "md_vecman2p2", "md_vecman2", NULL, NULL, "1996", + "Vectorman 2 (Prototype, 19960827)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vecman2p2RomInfo, md_vecman2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Verytex (Jpn) +static struct BurnRomInfo md_verytexRomDesc[] = { + { "verytex (jpn).bin", 0x080000, 0xbafc375f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_verytex) +STD_ROM_FN(md_verytex) + +struct BurnDriver BurnDrvmd_verytex = { + "md_verytex", NULL, NULL, NULL, "1991", + "Verytex (Jpn)\0", NULL, "Asmik Ace", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_verytexRomInfo, md_verytexRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Viewpoint (USA) +static struct BurnRomInfo md_viewpRomDesc[] = { + { "viewpoint (usa).bin", 0x200000, 0x59c71866, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_viewp) +STD_ROM_FN(md_viewp) + +struct BurnDriver BurnDrvmd_viewp = { + "md_viewp", NULL, NULL, NULL, "1994", + "Viewpoint (USA)\0", NULL, "American Sammy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_viewpRomInfo, md_viewpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Viewpoint (USA, Prototype) +static struct BurnRomInfo md_viewppRomDesc[] = { + { "viewpoint (usa) (beta).bin", 0x180000, 0xf2e69ce7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_viewpp) +STD_ROM_FN(md_viewpp) + +struct BurnDriver BurnDrvmd_viewpp = { + "md_viewpp", "md_viewp", NULL, NULL, "1994", + "Viewpoint (USA, Prototype)\0", NULL, "American Sammy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_viewppRomInfo, md_viewppRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Euro, USA) +static struct BurnRomInfo md_vf2RomDesc[] = { + { "mpr-19107+mpr-19108.bin", 0x400000, 0x937380f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2) +STD_ROM_FN(md_vf2) + +struct BurnDriver BurnDrvmd_vf2 = { + "md_vf2", NULL, NULL, NULL, "1997", + "Virtua Fighter 2 (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2RomInfo, md_vf2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Kor) +static struct BurnRomInfo md_vf2kRomDesc[] = { + { "mpr-19369.bin", 0x400000, 0xa95d0949, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2k) +STD_ROM_FN(md_vf2k) + +struct BurnDriver BurnDrvmd_vf2k = { + "md_vf2k", "md_vf2", NULL, NULL, "1997", + "Virtua Fighter 2 (Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2kRomInfo, md_vf2kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Prototype, 19960819) +static struct BurnRomInfo md_vf2p5RomDesc[] = { + { "virtua fighter 2 (prototype - aug 19, 1996).bin", 0x400000, 0xc5ee3974, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2p5) +STD_ROM_FN(md_vf2p5) + +struct BurnDriver BurnDrvmd_vf2p5 = { + "md_vf2p5", "md_vf2", NULL, NULL, "1996", + "Virtua Fighter 2 (Prototype, 19960819)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2p5RomInfo, md_vf2p5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Prototype, 19960830) +static struct BurnRomInfo md_vf2p4RomDesc[] = { + { "virtua fighter 2 (prototype - aug 30, 1996).bin", 0x400000, 0x6a0f3a7b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2p4) +STD_ROM_FN(md_vf2p4) + +struct BurnDriver BurnDrvmd_vf2p4 = { + "md_vf2p4", "md_vf2", NULL, NULL, "1996", + "Virtua Fighter 2 (Prototype, 19960830)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2p4RomInfo, md_vf2p4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Prototype, 19960913) +static struct BurnRomInfo md_vf2p3RomDesc[] = { + { "virtua fighter 2 (prototype - sep 13, 1996).bin", 0x400000, 0xfa5bad91, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2p3) +STD_ROM_FN(md_vf2p3) + +struct BurnDriver BurnDrvmd_vf2p3 = { + "md_vf2p3", "md_vf2", NULL, NULL, "1996", + "Virtua Fighter 2 (Prototype, 19960913)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2p3RomInfo, md_vf2p3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Prototype, 19960920) +static struct BurnRomInfo md_vf2p2RomDesc[] = { + { "virtua fighter 2 (prototype - sep 20, 1996).bin", 0x400000, 0xaf516dad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2p2) +STD_ROM_FN(md_vf2p2) + +struct BurnDriver BurnDrvmd_vf2p2 = { + "md_vf2p2", "md_vf2", NULL, NULL, "1996", + "Virtua Fighter 2 (Prototype, 19960920)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2p2RomInfo, md_vf2p2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 (Prototype, 19960927) +static struct BurnRomInfo md_vf2p1RomDesc[] = { + { "virtua fighter 2 (prototype - sep 27, 1996).bin", 0x400000, 0x95ab6ab6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2p1) +STD_ROM_FN(md_vf2p1) + +struct BurnDriver BurnDrvmd_vf2p1 = { + "md_vf2p1", "md_vf2", NULL, NULL, "1996", + "Virtua Fighter 2 (Prototype, 19960927)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2p1RomInfo, md_vf2p1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Fighter 2 vs Tekken 2 +static struct BurnRomInfo md_vf2tekRomDesc[] = { + { "virtua fighter 2 vs tekken 2 (unl).bin", 0x200000, 0x2cdb499d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vf2tek) +STD_ROM_FN(md_vf2tek) + +struct BurnDriver BurnDrvmd_vf2tek = { + "md_vf2tek", NULL, NULL, NULL, "199?", + "Virtua Fighter 2 vs Tekken 2\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vf2tekRomInfo, md_vf2tekRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtual Bart (World) +static struct BurnRomInfo md_vbartRomDesc[] = { + { "virtual bart (world).bin", 0x200000, 0x8db9f378, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vbart) +STD_ROM_FN(md_vbart) + +struct BurnDriver BurnDrvmd_vbart = { + "md_vbart", NULL, NULL, NULL, "1994", + "Virtual Bart (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vbartRomInfo, md_vbartRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtual Pinball (Euro, USA) +static struct BurnRomInfo md_virtpbRomDesc[] = { + { "virtual pinball (euro, usa).bin", 0x100000, 0xd63473aa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_virtpb) +STD_ROM_FN(md_virtpb) + +struct BurnDriver BurnDrvmd_virtpb = { + "md_virtpb", NULL, NULL, NULL, "1993", + "Virtual Pinball (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_virtpbRomInfo, md_virtpbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Vixen 357 (Jpn) +static struct BurnRomInfo md_vixen357RomDesc[] = { + { "vixen 357 (jpn).bin", 0x100000, 0x3afa2d7b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vixen357) +STD_ROM_FN(md_vixen357) + +struct BurnDriver BurnDrvmd_vixen357 = { + "md_vixen357", NULL, NULL, NULL, "1992", + "Vixen 357 (Jpn)\0", NULL, "NCS", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_vixen357RomInfo, md_vixen357RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// VR Troopers (Euro, USA) +static struct BurnRomInfo md_vrtroopRomDesc[] = { + { "vr troopers (euro, usa).bin", 0x200000, 0x2f35516e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vrtroop) +STD_ROM_FN(md_vrtroop) + +struct BurnDriver BurnDrvmd_vrtroop = { + "md_vrtroop", NULL, NULL, NULL, "1994", + "VR Troopers (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vrtroopRomInfo, md_vrtroopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wacky Races (USA, Prototype) +static struct BurnRomInfo md_wackyrRomDesc[] = { + { "wacky races (usa) (prototype).bin", 0x200000, 0x1b173f09, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wackyr) +STD_ROM_FN(md_wackyr) + +struct BurnDriver BurnDrvmd_wackyr = { + "md_wackyr", NULL, NULL, NULL, "199?", + "Wacky Races (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wackyrRomInfo, md_wackyrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wacky Worlds (USA) +static struct BurnRomInfo md_wworldsRomDesc[] = { + { "wacky worlds (usa).bin", 0x100000, 0x8af4552d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworlds) +STD_ROM_FN(md_wworlds) + +struct BurnDriver BurnDrvmd_wworlds = { + "md_wworlds", NULL, NULL, NULL, "1994", + "Wacky Worlds (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wworldsRomInfo, md_wworldsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wacky Worlds (Prototype, 19940808) +static struct BurnRomInfo md_wworldsp3RomDesc[] = { + { "wacky worlds (prototype - aug 08, 1994).bin", 0x100000, 0x48d33ea0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworldsp3) +STD_ROM_FN(md_wworldsp3) + +struct BurnDriver BurnDrvmd_wworldsp3 = { + "md_wworldsp3", "md_wworlds", NULL, NULL, "1994", + "Wacky Worlds (Prototype, 19940808)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wworldsp3RomInfo, md_wworldsp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wacky Worlds (Prototype, 19940817) +static struct BurnRomInfo md_wworldsp2RomDesc[] = { + { "wacky worlds (prototype - aug 17, 1994).bin", 0x0fcbb0, 0x4615970b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworldsp2) +STD_ROM_FN(md_wworldsp2) + +struct BurnDriver BurnDrvmd_wworldsp2 = { + "md_wworldsp2", "md_wworlds", NULL, NULL, "1994", + "Wacky Worlds (Prototype, 19940817)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wworldsp2RomInfo, md_wworldsp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wacky Worlds (Prototype, 19940819) +static struct BurnRomInfo md_wworldsp1RomDesc[] = { + { "wacky worlds (prototype - aug 19, 1994).bin", 0x0fcb96, 0x7f286925, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworldsp1) +STD_ROM_FN(md_wworldsp1) + +struct BurnDriver BurnDrvmd_wworldsp1 = { + "md_wworldsp1", "md_wworlds", NULL, NULL, "1994", + "Wacky Worlds (Prototype, 19940819)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wworldsp1RomInfo, md_wworldsp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wani Wani World (Jpn) +static struct BurnRomInfo md_waniwaniRomDesc[] = { + { "wani wani world (jpn).bin", 0x080000, 0x56f0dbb2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_waniwani) +STD_ROM_FN(md_waniwani) + +struct BurnDriver BurnDrvmd_waniwani = { + "md_waniwani", NULL, NULL, NULL, "1992", + "Wani Wani World (Jpn)\0", NULL, "Kaneko", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_waniwaniRomInfo, md_waniwaniRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wardner (USA) +static struct BurnRomInfo md_wardnerRomDesc[] = { + { "wardner (usa).bin", 0x080000, 0x1e369ae2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wardner) +STD_ROM_FN(md_wardner) + +struct BurnDriver BurnDrvmd_wardner = { + "md_wardner", NULL, NULL, NULL, "1991", + "Wardner (USA)\0", NULL, "Mentrix Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wardnerRomInfo, md_wardnerRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wardner no Mori Special (Jpn) +static struct BurnRomInfo md_wardnerjRomDesc[] = { + { "wardner no mori special (jpn).bin", 0x080000, 0x80f1035c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wardnerj) +STD_ROM_FN(md_wardnerj) + +struct BurnDriver BurnDrvmd_wardnerj = { + "md_wardnerj", "md_wardner", NULL, NULL, "1991", + "Wardner no Mori Special (Jpn)\0", NULL, "Visco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wardnerjRomInfo, md_wardnerjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warlock (Euro, USA) +static struct BurnRomInfo md_warlockRomDesc[] = { + { "warlock (euro, usa).bin", 0x200000, 0x0a46539b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warlock) +STD_ROM_FN(md_warlock) + +struct BurnDriver BurnDrvmd_warlock = { + "md_warlock", NULL, NULL, NULL, "1994", + "Warlock (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_warlockRomInfo, md_warlockRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warlock (USA, Prototype) +static struct BurnRomInfo md_warlockpRomDesc[] = { + { "warlock (usa) (beta).bin", 0x200000, 0xc9b6edb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warlockp) +STD_ROM_FN(md_warlockp) + +struct BurnDriver BurnDrvmd_warlockp = { + "md_warlockp", "md_warlock", NULL, NULL, "1994", + "Warlock (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_warlockpRomInfo, md_warlockpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warpspeed (USA) +static struct BurnRomInfo md_warpspedRomDesc[] = { + { "warpspeed (usa).bin", 0x200000, 0x143697ed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warpsped) +STD_ROM_FN(md_warpsped) + +struct BurnDriver BurnDrvmd_warpsped = { + "md_warpsped", NULL, NULL, NULL, "1993", + "Warpspeed (USA)\0", NULL, "Accolade", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_warpspedRomInfo, md_warpspedRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warrior of Rome (USA) +static struct BurnRomInfo md_warriorRomDesc[] = { + { "warrior of rome (usa).bin", 0x100000, 0x5be10c6a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warrior) +STD_ROM_FN(md_warrior) + +struct BurnDriver BurnDrvmd_warrior = { + "md_warrior", NULL, NULL, NULL, "1991", + "Warrior of Rome (USA)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_warriorRomInfo, md_warriorRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Caesar no Yabou (Jpn) +static struct BurnRomInfo md_caesarRomDesc[] = { + { "caesar no yabou (jpn).bin", 0x100000, 0x69796e93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_caesar) +STD_ROM_FN(md_caesar) + +struct BurnDriver BurnDrvmd_caesar = { + "md_caesar", "md_warrior", NULL, NULL, "1991", + "Caesar no Yabou (Jpn)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_caesarRomInfo, md_caesarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warrior of Rome II (USA) +static struct BurnRomInfo md_warrior2RomDesc[] = { + { "warrior of rome ii (usa).bin", 0x100000, 0xcd8c472a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warrior2) +STD_ROM_FN(md_warrior2) + +struct BurnDriver BurnDrvmd_warrior2 = { + "md_warrior2", NULL, NULL, NULL, "1992", + "Warrior of Rome II (USA)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_warrior2RomInfo, md_warrior2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Caesar no Yabou II (Jpn) +static struct BurnRomInfo md_caesar2RomDesc[] = { + { "caesar no yabou ii (jpn).bin", 0x100000, 0x4f327b3a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_caesar2) +STD_ROM_FN(md_caesar2) + +struct BurnDriver BurnDrvmd_caesar2 = { + "md_caesar2", "md_warrior2", NULL, NULL, "1992", + "Caesar no Yabou II (Jpn)\0", NULL, "Micronet", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_caesar2RomInfo, md_caesar2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Warsong (USA) +static struct BurnRomInfo md_warsongRomDesc[] = { + { "warsong (usa).bin", 0x080000, 0x4b680285, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_warsong) +STD_ROM_FN(md_warsong) + +struct BurnDriver BurnDrvmd_warsong = { + "md_warsong", NULL, NULL, NULL, "1991", + "Warsong (USA)\0", NULL, "Treco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_warsongRomInfo, md_warsongRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Waterworld (Euro, Prototype) +static struct BurnRomInfo md_waterwldRomDesc[] = { + { "waterworld (euro) (prototype).bin", 0x200000, 0x51c80498, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_waterwld) +STD_ROM_FN(md_waterwld) + +struct BurnDriver BurnDrvmd_waterwld = { + "md_waterwld", NULL, NULL, NULL, "1995?", + "Waterworld (Euro, Prototype)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_waterwldRomInfo, md_waterwldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wayne Gretzky and the NHLPA All-Stars (Euro, USA) +static struct BurnRomInfo md_waynegRomDesc[] = { + { "wayne gretzky and the nhlpa all-stars (euro, usa).bin", 0x200000, 0xc2c13b81, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wayneg) +STD_ROM_FN(md_wayneg) + +struct BurnDriver BurnDrvmd_wayneg = { + "md_wayneg", NULL, NULL, NULL, "1995", + "Wayne Gretzky and the NHLPA All-Stars (Euro, USA)\0", NULL, "Time Warner Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_waynegRomInfo, md_waynegRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wayne's World (USA) +static struct BurnRomInfo md_waynewldRomDesc[] = { + { "wayne's world (usa).bin", 0x100000, 0xd2cf6ebe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_waynewld) +STD_ROM_FN(md_waynewld) + +struct BurnDriver BurnDrvmd_waynewld = { + "md_waynewld", NULL, NULL, NULL, "1993", + "Wayne's World (USA)\0", NULL, "THQ", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_waynewldRomInfo, md_waynewldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Weaponlord (USA) +static struct BurnRomInfo md_weapnlrdRomDesc[] = { + { "weaponlord (usa).bin", 0x300000, 0xb9895365, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_weapnlrd) +STD_ROM_FN(md_weapnlrd) + +struct BurnDriver BurnDrvmd_weapnlrd = { + "md_weapnlrd", NULL, NULL, NULL, "1995", + "Weaponlord (USA)\0", NULL, "Namco", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_weapnlrdRomInfo, md_weapnlrdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wheel of Fortune (USA) +static struct BurnRomInfo md_wheelforRomDesc[] = { + { "wheel of fortune (usa).bin", 0x080000, 0xc8d8efc3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wheelfor) +STD_ROM_FN(md_wheelfor) + +struct BurnDriver BurnDrvmd_wheelfor = { + "md_wheelfor", NULL, NULL, NULL, "1992", + "Wheel of Fortune (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wheelforRomInfo, md_wheelforRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Where in the World Is Carmen Sandiego? (Euro, USA) +static struct BurnRomInfo md_wworldRomDesc[] = { + { "where in the world is carmen sandiego (euro, usa).bin", 0x100000, 0xeef372e8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworld) +STD_ROM_FN(md_wworld) + +struct BurnDriver BurnDrvmd_wworld = { + "md_wworld", NULL, NULL, NULL, "1992", + "Where in the World Is Carmen Sandiego? (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wworldRomInfo, md_wworldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Where in the World Is Carmen Sandiego? (Bra) +static struct BurnRomInfo md_wworldbrRomDesc[] = { + { "where in the world is carmen sandiego (bra).bin", 0x100000, 0x7d4450ad, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wworldbr) +STD_ROM_FN(md_wworldbr) + +struct BurnDriver BurnDrvmd_wworldbr = { + "md_wworldbr", "md_wworld", NULL, NULL, "199?", + "Where in the World Is Carmen Sandiego? (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wworldbrRomInfo, md_wworldbrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Where in Time Is Carmen Sandiego? (Euro, USA) +static struct BurnRomInfo md_wtimeRomDesc[] = { + { "where in time is carmen sandiego (euro, usa).bin", 0x100000, 0xea19d4a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wtime) +STD_ROM_FN(md_wtime) + +struct BurnDriver BurnDrvmd_wtime = { + "md_wtime", NULL, NULL, NULL, "1992", + "Where in Time Is Carmen Sandiego? (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wtimeRomInfo, md_wtimeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Where in Time Is Carmen Sandiego? (Bra) +static struct BurnRomInfo md_wtimebrRomDesc[] = { + { "where in time is carmen sandiego (bra).bin", 0x100000, 0xd523b552, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wtimebr) +STD_ROM_FN(md_wtimebr) + +struct BurnDriver BurnDrvmd_wtimebr = { + "md_wtimebr", "md_wtime", NULL, NULL, "199?", + "Where in Time Is Carmen Sandiego? (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wtimebrRomInfo, md_wtimebrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Whip Rush (USA) +static struct BurnRomInfo md_whiprushRomDesc[] = { + { "whip rush (usa).bin", 0x080000, 0x7eb6b86b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whiprush) +STD_ROM_FN(md_whiprush) + +struct BurnDriver BurnDrvmd_whiprush = { + "md_whiprush", NULL, NULL, NULL, "1990", + "Whip Rush (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whiprushRomInfo, md_whiprushRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Whip Rush - Wakusei Voltegas no Nazo (Jpn) +static struct BurnRomInfo md_whiprushjRomDesc[] = { + { "whip rush - wakusei voltegas no nazo (jpn).bin", 0x080000, 0x8084b4d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whiprushj) +STD_ROM_FN(md_whiprushj) + +struct BurnDriver BurnDrvmd_whiprushj = { + "md_whiprushj", "md_whiprush", NULL, NULL, "1990", + "Whip Rush - Wakusei Voltegas no Nazo (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whiprushjRomInfo, md_whiprushjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wild Snake (USA, Prototype) +static struct BurnRomInfo md_wildsnakRomDesc[] = { + { "wild snake (usa) (prototype).bin", 0x080000, 0x0c1a49e5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wildsnak) +STD_ROM_FN(md_wildsnak) + +struct BurnDriver BurnDrvmd_wildsnak = { + "md_wildsnak", NULL, NULL, NULL, "1994", + "Wild Snake (USA, Prototype)\0", NULL, "Bullet-Proof Software", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wildsnakRomInfo, md_wildsnakRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Williams Arcade's Greatest Hits (USA) +static struct BurnRomInfo md_williamsRomDesc[] = { + { "williams arcade's greatest hits (usa).bin", 0x080000, 0xd68e9c00, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_williams) +STD_ROM_FN(md_williams) + +struct BurnDriver BurnDrvmd_williams = { + "md_williams", NULL, NULL, NULL, "1996", + "Williams Arcade's Greatest Hits (USA)\0", NULL, "Williams", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_williamsRomInfo, md_williamsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wimbledon Championship Tennis (Euro) +static struct BurnRomInfo md_wimbledRomDesc[] = { + { "wimbledon championship tennis (euro).bin", 0x100000, 0xb791a435, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wimbled) +STD_ROM_FN(md_wimbled) + +struct BurnDriver BurnDrvmd_wimbled = { + "md_wimbled", NULL, NULL, NULL, "1994", + "Wimbledon Championship Tennis (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wimbledRomInfo, md_wimbledRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wimbledon Championship Tennis (Jpn) +static struct BurnRomInfo md_wimbledjRomDesc[] = { + { "wimbledon championship tennis (jpn).bin", 0x100000, 0x3e0c9daf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wimbledj) +STD_ROM_FN(md_wimbledj) + +struct BurnDriver BurnDrvmd_wimbledj = { + "md_wimbledj", "md_wimbled", NULL, NULL, "1994", + "Wimbledon Championship Tennis (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wimbledjRomInfo, md_wimbledjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wimbledon Championship Tennis (USA) +static struct BurnRomInfo md_wimbleduRomDesc[] = { + { "wimbledon championship tennis (usa).bin", 0x100000, 0xf9142aee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wimbledu) +STD_ROM_FN(md_wimbledu) + +struct BurnDriver BurnDrvmd_wimbledu = { + "md_wimbledu", "md_wimbled", NULL, NULL, "1993", + "Wimbledon Championship Tennis (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wimbleduRomInfo, md_wimbleduRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wimbledon Championship Tennis (USA, Prototype) +static struct BurnRomInfo md_wimbledupRomDesc[] = { + { "wimbledon championship tennis (usa) (beta).bin", 0x100000, 0x9febc760, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wimbledup) +STD_ROM_FN(md_wimbledup) + +struct BurnDriver BurnDrvmd_wimbledup = { + "md_wimbledup", "md_wimbled", NULL, NULL, "1993", + "Wimbledon Championship Tennis (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wimbledupRomInfo, md_wimbledupRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Challenge (Euro, USA, Rev. 1) +static struct BurnRomInfo md_wintcRomDesc[] = { + { "acwcsg-1_(1-92).bin", 0x100000, 0xf57c7068, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintc) +STD_ROM_FN(md_wintc) + +struct BurnDriver BurnDrvmd_wintc = { + "md_wintc", NULL, NULL, NULL, "1992", + "Winter Challenge (Euro, USA, Rev. 1)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintcRomInfo, md_wintcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Challenge (Euro, USA) +static struct BurnRomInfo md_wintc1RomDesc[] = { + { "acwcsg_(12-91).bin", 0x100000, 0xdbc3ed1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintc1) +STD_ROM_FN(md_wintc1) + +struct BurnDriver BurnDrvmd_wintc1 = { + "md_wintc1", "md_wintc", NULL, NULL, "1992", + "Winter Challenge (Euro, USA)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintc1RomInfo, md_wintc1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Challenge (Prototype) +static struct BurnRomInfo md_wintcpRomDesc[] = { + { "winter challenge (beta).bin", 0x100000, 0x60d2a8c4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintcp) +STD_ROM_FN(md_wintcp) + +struct BurnDriver BurnDrvmd_wintcp = { + "md_wintcp", "md_wintc", NULL, NULL, "1992", + "Winter Challenge (Prototype)\0", NULL, "Ballistic", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintcpRomInfo, md_wintcpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Olympics (Euro) +static struct BurnRomInfo md_wintolRomDesc[] = { + { "winter olympics (euro).bin", 0x200000, 0xfa537a45, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintol) +STD_ROM_FN(md_wintol) + +struct BurnDriver BurnDrvmd_wintol = { + "md_wintol", NULL, NULL, NULL, "1994", + "Winter Olympics (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintolRomInfo, md_wintolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Olympics (Jpn) +static struct BurnRomInfo md_wintoljRomDesc[] = { + { "winter olympics (jpn).bin", 0x200000, 0x654a4684, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintolj) +STD_ROM_FN(md_wintolj) + +struct BurnDriver BurnDrvmd_wintolj = { + "md_wintolj", "md_wintol", NULL, NULL, "1994", + "Winter Olympics (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintoljRomInfo, md_wintoljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winter Olympic Games (USA) +static struct BurnRomInfo md_wintoluRomDesc[] = { + { "winter olympic games (usa).bin", 0x200000, 0xc5834437, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wintolu) +STD_ROM_FN(md_wintolu) + +struct BurnDriver BurnDrvmd_wintolu = { + "md_wintolu", "md_wintol", NULL, NULL, "1993", + "Winter Olympic Games (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wintoluRomInfo, md_wintoluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wiz'n'Liz - The Frantic Wabbit Wescue (Euro) +static struct BurnRomInfo md_wiznlizRomDesc[] = { + { "wiz'n'liz - the frantic wabbit wescue (euro).bin", 0x100000, 0xf09353b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wiznliz) +STD_ROM_FN(md_wiznliz) + +struct BurnDriver BurnDrvmd_wiznliz = { + "md_wiznliz", NULL, NULL, NULL, "1993", + "Wiz'n'Liz - The Frantic Wabbit Wescue (Euro)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wiznlizRomInfo, md_wiznlizRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wiz'n'Liz (USA) +static struct BurnRomInfo md_wiznlizuRomDesc[] = { + { "wiz'n'liz (usa).bin", 0x100000, 0xdf036b62, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wiznlizu) +STD_ROM_FN(md_wiznlizu) + +struct BurnDriver BurnDrvmd_wiznlizu = { + "md_wiznlizu", "md_wiznliz", NULL, NULL, "1993", + "Wiz'n'Liz (USA)\0", NULL, "Psygnosis", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wiznlizuRomInfo, md_wiznlizuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wolfchild (USA) +static struct BurnRomInfo md_wolfchldRomDesc[] = { + { "wolfchild (usa).bin", 0x100000, 0xeb5b1cbf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wolfchld) +STD_ROM_FN(md_wolfchld) + +struct BurnDriver BurnDrvmd_wolfchld = { + "md_wolfchld", NULL, NULL, NULL, "1993", + "Wolfchild (USA)\0", NULL, "JVC Musical Industries", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wolfchldRomInfo, md_wolfchldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wolverine - Adamantium Rage (Euro, USA) +static struct BurnRomInfo md_wolverinRomDesc[] = { + { "wolverine - adamantium rage (euro, usa).bin", 0x200000, 0xd2437bb7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wolverin) +STD_ROM_FN(md_wolverin) + +struct BurnDriver BurnDrvmd_wolverin = { + "md_wolverin", NULL, NULL, NULL, "1994", + "Wolverine - Adamantium Rage (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wolverinRomInfo, md_wolverinRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wonder Boy III - Monster Lair (Euro) ~ Monster Lair (Jpn) +static struct BurnRomInfo md_wboy3RomDesc[] = { + { "mpr-13619.bin", 0x080000, 0xc24bc5e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wboy3) +STD_ROM_FN(md_wboy3) + +struct BurnDriver BurnDrvmd_wboy3 = { + "md_wboy3", NULL, NULL, NULL, "1991", + "Wonder Boy III - Monster Lair (Euro) ~ Monster Lair (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wboy3RomInfo, md_wboy3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wonder Boy in Monster World (Euro, USA) +static struct BurnRomInfo md_wbmwRomDesc[] = { + { "mpr-14556.bin", 0x0c0000, 0x1592f5b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wbmw) +STD_ROM_FN(md_wbmw) + +struct BurnDriver BurnDrvmd_wbmw = { + "md_wbmw", NULL, NULL, NULL, "1992", + "Wonder Boy in Monster World (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_wbmwRomInfo, md_wbmwRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wonder Boy V - Monster World III (Jpn, Kor) +static struct BurnRomInfo md_wboy5RomDesc[] = { + { "wonder boy v - monster world iii (jpn, kor).bin", 0x0a0000, 0x45a50f96, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wboy5) +STD_ROM_FN(md_wboy5) + +struct BurnDriver BurnDrvmd_wboy5 = { + "md_wboy5", "md_wbmw", NULL, NULL, "1991", + "Wonder Boy V - Monster World III (Jpn, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_wboy5RomInfo, md_wboy5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Turma da Mônica na Terra dos Monstros (Bra) +static struct BurnRomInfo md_turmadRomDesc[] = { + { "turma da monica na terra dos monstros (bra).bin", 0x100000, 0xf8288de1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_turmad) +STD_ROM_FN(md_turmad) + +struct BurnDriver BurnDrvmd_turmad = { + "md_turmad", "md_wbmw", NULL, NULL, "1996", + "Turma da Mônica na Terra dos Monstros (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM, GBF_MISC, 0, + MegadriveGetZipName, md_turmadRomInfo, md_turmadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wonder Library (Jpn) +static struct BurnRomInfo md_wondlibRomDesc[] = { + { "wonder library (jpn).bin", 0x080000, 0x9350e754, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wondlib) +STD_ROM_FN(md_wondlib) + +struct BurnDriver BurnDrvmd_wondlib = { + "md_wondlib", NULL, NULL, NULL, "199?", + "Wonder Library (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wondlibRomInfo, md_wondlibRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Euro) +static struct BurnRomInfo md_wcs2RomDesc[] = { + { "world championship soccer ii (europe).bin", 0x100000, 0x6065774d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2) +STD_ROM_FN(md_wcs2) + +struct BurnDriver BurnDrvmd_wcs2 = { + "md_wcs2", NULL, NULL, NULL, "1994", + "World Championship Soccer II (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2RomInfo, md_wcs2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (USA) +static struct BurnRomInfo md_wcs2uRomDesc[] = { + { "world championship soccer ii (usa).bin", 0x100000, 0xc1dd1c8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2u) +STD_ROM_FN(md_wcs2u) + +struct BurnDriver BurnDrvmd_wcs2u = { + "md_wcs2u", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2uRomInfo, md_wcs2uRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940223) +static struct BurnRomInfo md_wcs2p18RomDesc[] = { + { "world championship soccer ii (prototype - feb 23, 1994).bin", 0x100000, 0xaab9e240, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p18) +STD_ROM_FN(md_wcs2p18) + +struct BurnDriver BurnDrvmd_wcs2p18 = { + "md_wcs2p18", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940223)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p18RomInfo, md_wcs2p18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940309) +static struct BurnRomInfo md_wcs2p13RomDesc[] = { + { "world championship soccer ii (prototype - mar 09, 1994).bin", 0x100000, 0x71fa89cc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p13) +STD_ROM_FN(md_wcs2p13) + +struct BurnDriver BurnDrvmd_wcs2p13 = { + "md_wcs2p13", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940309)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p13RomInfo, md_wcs2p13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940323) +static struct BurnRomInfo md_wcs2p09RomDesc[] = { + { "world championship soccer ii (prototype - mar 23, 1994).bin", 0x100000, 0x3852e514, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p09) +STD_ROM_FN(md_wcs2p09) + +struct BurnDriver BurnDrvmd_wcs2p09 = { + "md_wcs2p09", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940323)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p09RomInfo, md_wcs2p09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940324) +static struct BurnRomInfo md_wcs2p08RomDesc[] = { + { "world championship soccer ii (prototype - mar 24, 1994).bin", 0x100000, 0xa6d43b4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p08) +STD_ROM_FN(md_wcs2p08) + +struct BurnDriver BurnDrvmd_wcs2p08 = { + "md_wcs2p08", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940324)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p08RomInfo, md_wcs2p08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940325) +static struct BurnRomInfo md_wcs2p07RomDesc[] = { + { "world championship soccer ii (prototype - mar 25, 1994).bin", 0x100000, 0x6b3624fb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p07) +STD_ROM_FN(md_wcs2p07) + +struct BurnDriver BurnDrvmd_wcs2p07 = { + "md_wcs2p07", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940325)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p07RomInfo, md_wcs2p07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940326) +static struct BurnRomInfo md_wcs2p06RomDesc[] = { + { "world championship soccer ii (prototype - mar 26, 1994).bin", 0x100000, 0x1ad7ed9c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p06) +STD_ROM_FN(md_wcs2p06) + +struct BurnDriver BurnDrvmd_wcs2p06 = { + "md_wcs2p06", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940326)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p06RomInfo, md_wcs2p06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940327) +static struct BurnRomInfo md_wcs2p05RomDesc[] = { + { "world championship soccer ii (prototype - mar 27, 1994).bin", 0x100000, 0x4e141509, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p05) +STD_ROM_FN(md_wcs2p05) + +struct BurnDriver BurnDrvmd_wcs2p05 = { + "md_wcs2p05", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940327)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p05RomInfo, md_wcs2p05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940329-B) +static struct BurnRomInfo md_wcs2p04RomDesc[] = { + { "world championship soccer ii (prototype - mar 29, 1994 - b).bin", 0x100000, 0xa6759340, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p04) +STD_ROM_FN(md_wcs2p04) + +struct BurnDriver BurnDrvmd_wcs2p04 = { + "md_wcs2p04", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940329-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p04RomInfo, md_wcs2p04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940329) +static struct BurnRomInfo md_wcs2p03RomDesc[] = { + { "world championship soccer ii (prototype - mar 29, 1994).bin", 0x100000, 0x5f9c51f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p03) +STD_ROM_FN(md_wcs2p03) + +struct BurnDriver BurnDrvmd_wcs2p03 = { + "md_wcs2p03", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940329)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p03RomInfo, md_wcs2p03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940330) +static struct BurnRomInfo md_wcs2p02RomDesc[] = { + { "world championship soccer ii (prototype - mar 30, 1994).bin", 0x100000, 0x8dd49c92, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p02) +STD_ROM_FN(md_wcs2p02) + +struct BurnDriver BurnDrvmd_wcs2p02 = { + "md_wcs2p02", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940330)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p02RomInfo, md_wcs2p02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype, 19940523) +static struct BurnRomInfo md_wcs2p01RomDesc[] = { + { "world championship soccer ii (prototype - may 23, 1994).bin", 0x100000, 0x6065774d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p01) +STD_ROM_FN(md_wcs2p01) + +struct BurnDriver BurnDrvmd_wcs2p01 = { + "md_wcs2p01", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype, 19940523)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p01RomInfo, md_wcs2p01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype G, 19940222) +static struct BurnRomInfo md_wcs2p19RomDesc[] = { + { "world championship soccer ii (prototype g - feb 22, 1994).bin", 0x100000, 0x6fbfa14e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p19) +STD_ROM_FN(md_wcs2p19) + +struct BurnDriver BurnDrvmd_wcs2p19 = { + "md_wcs2p19", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype G, 19940222)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p19RomInfo, md_wcs2p19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype J, 19940228) +static struct BurnRomInfo md_wcs2p17RomDesc[] = { + { "world championship soccer ii (prototype j - feb 28, 1994).bin", 0x100000, 0xe210a74c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p17) +STD_ROM_FN(md_wcs2p17) + +struct BurnDriver BurnDrvmd_wcs2p17 = { + "md_wcs2p17", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype J, 19940228)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p17RomInfo, md_wcs2p17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype N, 19940303) +static struct BurnRomInfo md_wcs2p16RomDesc[] = { + { "world championship soccer ii (prototype n - mar 03, 1994).bin", 0x100000, 0x07b387a4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p16) +STD_ROM_FN(md_wcs2p16) + +struct BurnDriver BurnDrvmd_wcs2p16 = { + "md_wcs2p16", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype N, 19940303)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p16RomInfo, md_wcs2p16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype O, 19940303) +static struct BurnRomInfo md_wcs2p15RomDesc[] = { + { "world championship soccer ii (prototype o - mar 03, 1994).bin", 0x100000, 0x5a458d42, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p15) +STD_ROM_FN(md_wcs2p15) + +struct BurnDriver BurnDrvmd_wcs2p15 = { + "md_wcs2p15", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype O, 19940303)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p15RomInfo, md_wcs2p15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype P, 19940304) +static struct BurnRomInfo md_wcs2p14RomDesc[] = { + { "world championship soccer ii (prototype p - mar 04, 1994).bin", 0x100000, 0x8fe9f6ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p14) +STD_ROM_FN(md_wcs2p14) + +struct BurnDriver BurnDrvmd_wcs2p14 = { + "md_wcs2p14", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype P, 19940304)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p14RomInfo, md_wcs2p14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype R, 19940309) +static struct BurnRomInfo md_wcs2p12RomDesc[] = { + { "world championship soccer ii (prototype r - mar 09, 1994).bin", 0x100000, 0x94625572, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p12) +STD_ROM_FN(md_wcs2p12) + +struct BurnDriver BurnDrvmd_wcs2p12 = { + "md_wcs2p12", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype R, 19940309)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p12RomInfo, md_wcs2p12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype U, 19940314) +static struct BurnRomInfo md_wcs2p11RomDesc[] = { + { "world championship soccer ii (prototype u - mar 14, 1994).bin", 0x100000, 0x43ec107c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p11) +STD_ROM_FN(md_wcs2p11) + +struct BurnDriver BurnDrvmd_wcs2p11 = { + "md_wcs2p11", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype U, 19940314)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p11RomInfo, md_wcs2p11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (Prototype Y, 19940318) +static struct BurnRomInfo md_wcs2p10RomDesc[] = { + { "world championship soccer ii (prototype y - mar 18, 1994).bin", 0x100000, 0xf6735b61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2p10) +STD_ROM_FN(md_wcs2p10) + +struct BurnDriver BurnDrvmd_wcs2p10 = { + "md_wcs2p10", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (Prototype Y, 19940318)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2p10RomInfo, md_wcs2p10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer II (USA, Prototype) +static struct BurnRomInfo md_wcs2upRomDesc[] = { + { "world championship soccer ii (usa) (beta).bin", 0x100000, 0xc1e21c1a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs2up) +STD_ROM_FN(md_wcs2up) + +struct BurnDriver BurnDrvmd_wcs2up = { + "md_wcs2up", "md_wcs2", NULL, NULL, "1994", + "World Championship Soccer II (USA, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcs2upRomInfo, md_wcs2upRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Class Leaderboard Golf (Euro) +static struct BurnRomInfo md_wcleadRomDesc[] = { + { "mpr-15278.bin", 0x080000, 0xdaca01c3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wclead) +STD_ROM_FN(md_wclead) + +struct BurnDriver BurnDrvmd_wclead = { + "md_wclead", NULL, NULL, NULL, "1992", + "World Class Leaderboard Golf (Euro)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcleadRomInfo, md_wcleadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Class Leaderboard Golf (USA) +static struct BurnRomInfo md_wcleaduRomDesc[] = { + { "world class leaderboard golf (usa).bin", 0x080000, 0x53434bab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcleadu) +STD_ROM_FN(md_wcleadu) + +struct BurnDriver BurnDrvmd_wcleadu = { + "md_wcleadu", "md_wclead", NULL, NULL, "1992", + "World Class Leaderboard Golf (USA)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcleaduRomInfo, md_wcleaduRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Cup Italia '90 (Euro) +static struct BurnRomInfo md_wc90RomDesc[] = { + { "mpr-13239.bin", 0x040000, 0xdd95f829, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wc90) +STD_ROM_FN(md_wc90) + +struct BurnDriver BurnDrvmd_wc90 = { + "md_wc90", NULL, NULL, NULL, "1990", + "World Cup Italia '90 (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wc90RomInfo, md_wc90RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer (USA, Rev. B) ~ World Cup Soccer (Jpn, Rev. B) +static struct BurnRomInfo md_wcsRomDesc[] = { + { "mpr-12607b.bin", 0x040000, 0xbf272bcb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcs) +STD_ROM_FN(md_wcs) + +struct BurnDriver BurnDrvmd_wcs = { + "md_wcs", "md_wc90", NULL, NULL, "1989", + "World Championship Soccer (USA, Rev. B) ~ World Cup Soccer (Jpn, Rev. B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcsRomInfo, md_wcsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer (USA, v1.2) ~ World Cup Soccer (Jpn, v1.2) +static struct BurnRomInfo md_wcsaRomDesc[] = { + { "world cup soccer -- world championship soccer (usa, jpn) (v1.2).bin", 0x040000, 0xbf84ede6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcsa) +STD_ROM_FN(md_wcsa) + +struct BurnDriver BurnDrvmd_wcsa = { + "md_wcsa", "md_wc90", NULL, NULL, "1989", + "World Championship Soccer (USA, v1.2) ~ World Cup Soccer (Jpn, v1.2)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcsaRomInfo, md_wcsaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Championship Soccer (USA) ~ World Cup Soccer (Jpn) +static struct BurnRomInfo md_wcsbRomDesc[] = { + { "world cup soccer -- world championship soccer (usa, jpn).bin", 0x040000, 0xb01c3d70, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcsb) +STD_ROM_FN(md_wcsb) + +struct BurnDriver BurnDrvmd_wcsb = { + "md_wcsb", "md_wc90", NULL, NULL, "1989", + "World Championship Soccer (USA) ~ World Cup Soccer (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wcsbRomInfo, md_wcsbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Cup USA 94 (Euro, USA, Kor) +static struct BurnRomInfo md_wcup94RomDesc[] = { + { "world cup usa 94 (euro, usa, kor).bin", 0x100000, 0x0171b47f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wcup94) +STD_ROM_FN(md_wcup94) + +struct BurnDriver BurnDrvmd_wcup94 = { + "md_wcup94", NULL, NULL, NULL, "1994", + "World Cup USA 94 (Euro, USA, Kor)\0", NULL, "U.S. Gold", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wcup94RomInfo, md_wcup94RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA) +static struct BurnRomInfo md_whRomDesc[] = { + { "world heroes (usa).bin", 0x200000, 0x0f4d22ec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wh) +STD_ROM_FN(md_wh) + +struct BurnDriver BurnDrvmd_wh = { + "md_wh", NULL, NULL, NULL, "1994", + "World Heroes (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whRomInfo, md_whRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn) +static struct BurnRomInfo md_whjRomDesc[] = { + { "world heroes (jpn).bin", 0x200000, 0x56e3ceff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whj) +STD_ROM_FN(md_whj) + +struct BurnDriver BurnDrvmd_whj = { + "md_whj", "md_wh", NULL, NULL, "199?", + "World Heroes (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjRomInfo, md_whjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Euro, Prototype, 19940331-B) +static struct BurnRomInfo md_whp02RomDesc[] = { + { "world heroes (euro) (prototype - mar 31, 1994 - b).bin", 0x200000, 0xd210aa6e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp02) +STD_ROM_FN(md_whp02) + +struct BurnDriver BurnDrvmd_whp02 = { + "md_whp02", "md_wh", NULL, NULL, "1994", + "World Heroes (Euro, Prototype, 19940331-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp02RomInfo, md_whp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Euro, Prototype, 19940331) +static struct BurnRomInfo md_whp01RomDesc[] = { + { "world heroes (euro) (prototype - mar 31, 1994).bin", 0x200000, 0x92e1bf14, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp01) +STD_ROM_FN(md_whp01) + +struct BurnDriver BurnDrvmd_whp01 = { + "md_whp01", "md_wh", NULL, NULL, "1994", + "World Heroes (Euro, Prototype, 19940331)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp01RomInfo, md_whp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn, Prototype, 19940408) +static struct BurnRomInfo md_whjp4RomDesc[] = { + { "world heroes (jpn) (prototype - apr 08, 1994).bin", 0x200000, 0x2bea7215, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whjp4) +STD_ROM_FN(md_whjp4) + +struct BurnDriver BurnDrvmd_whjp4 = { + "md_whjp4", "md_wh", NULL, NULL, "1994", + "World Heroes (Jpn, Prototype, 19940408)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjp4RomInfo, md_whjp4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn, Prototype, 19940415) +static struct BurnRomInfo md_whjp3RomDesc[] = { + { "world heroes (jpn) (prototype - apr 15, 1994).bin", 0x200000, 0x6dec07b3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whjp3) +STD_ROM_FN(md_whjp3) + +struct BurnDriver BurnDrvmd_whjp3 = { + "md_whjp3", "md_wh", NULL, NULL, "1994", + "World Heroes (Jpn, Prototype, 19940415)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjp3RomInfo, md_whjp3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn, Prototype, 19940420-B) +static struct BurnRomInfo md_whjp2RomDesc[] = { + { "world heroes (jpn) (prototype - apr 20, 1994 - b).bin", 0x200000, 0xf5ffb191, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whjp2) +STD_ROM_FN(md_whjp2) + +struct BurnDriver BurnDrvmd_whjp2 = { + "md_whjp2", "md_wh", NULL, NULL, "1994", + "World Heroes (Jpn, Prototype, 19940420-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjp2RomInfo, md_whjp2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn, Prototype, 19940420, broken - C05 missing) +static struct BurnRomInfo md_whjp1RomDesc[] = { + { "world heroes (jpn) (prototype - apr 20, 1994) (broken - c05 missing).bin", 0x200000, 0xb43b518c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whjp1) +STD_ROM_FN(md_whjp1) + +struct BurnDriver BurnDrvmd_whjp1 = { + "md_whjp1", "md_wh", NULL, NULL, "1994", + "World Heroes (Jpn, Prototype, 19940420, broken - C05 missing)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjp1RomInfo, md_whjp1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (Jpn, Prototype, 19940330) +static struct BurnRomInfo md_whjp5RomDesc[] = { + { "world heroes (jpn) (prototype - mar 30, 1994).bin", 0x200000, 0x3f93181a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whjp5) +STD_ROM_FN(md_whjp5) + +struct BurnDriver BurnDrvmd_whjp5 = { + "md_whjp5", "md_wh", NULL, NULL, "1994", + "World Heroes (Jpn, Prototype, 19940330)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whjp5RomInfo, md_whjp5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940223) +static struct BurnRomInfo md_whp13RomDesc[] = { + { "world heroes (usa) (prototype - feb 23, 1994).bin", 0x200000, 0xf5db477e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp13) +STD_ROM_FN(md_whp13) + +struct BurnDriver BurnDrvmd_whp13 = { + "md_whp13", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940223)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp13RomInfo, md_whp13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940303) +static struct BurnRomInfo md_whp12RomDesc[] = { + { "world heroes (usa) (prototype - mar 03, 1994).bin", 0x200000, 0x24a63aef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp12) +STD_ROM_FN(md_whp12) + +struct BurnDriver BurnDrvmd_whp12 = { + "md_whp12", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940303)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp12RomInfo, md_whp12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940307) +static struct BurnRomInfo md_whp11RomDesc[] = { + { "world heroes (usa) (prototype - mar 07, 1994).bin", 0x200000, 0x45c29350, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp11) +STD_ROM_FN(md_whp11) + +struct BurnDriver BurnDrvmd_whp11 = { + "md_whp11", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940307)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp11RomInfo, md_whp11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940309) +static struct BurnRomInfo md_whp10RomDesc[] = { + { "world heroes (usa) (prototype - mar 09, 1994).bin", 0x200000, 0x2c7f9e64, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp10) +STD_ROM_FN(md_whp10) + +struct BurnDriver BurnDrvmd_whp10 = { + "md_whp10", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940309)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp10RomInfo, md_whp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940315) +static struct BurnRomInfo md_whp09RomDesc[] = { + { "world heroes (usa) (prototype - mar 15, 1994).bin", 0x200000, 0x2c0b2f4f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp09) +STD_ROM_FN(md_whp09) + +struct BurnDriver BurnDrvmd_whp09 = { + "md_whp09", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940315)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp09RomInfo, md_whp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940316) +static struct BurnRomInfo md_whp08RomDesc[] = { + { "world heroes (usa) (prototype - mar 16, 1994).bin", 0x200000, 0x19c74e2a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp08) +STD_ROM_FN(md_whp08) + +struct BurnDriver BurnDrvmd_whp08 = { + "md_whp08", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940316)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp08RomInfo, md_whp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940318) +static struct BurnRomInfo md_whp07RomDesc[] = { + { "world heroes (usa) (prototype - mar 18, 1994).bin", 0x200000, 0x2bc2a6bb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp07) +STD_ROM_FN(md_whp07) + +struct BurnDriver BurnDrvmd_whp07 = { + "md_whp07", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940318)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp07RomInfo, md_whp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940322, broken - C07 missing) +static struct BurnRomInfo md_whp06RomDesc[] = { + { "world heroes (usa) (prototype - mar 22, 1994) (broken - c07 missing).bin", 0x200000, 0x5c3c0931, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp06) +STD_ROM_FN(md_whp06) + +struct BurnDriver BurnDrvmd_whp06 = { + "md_whp06", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940322, broken - C07 missing)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp06RomInfo, md_whp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940323) +static struct BurnRomInfo md_whp05RomDesc[] = { + { "world heroes (usa) (prototype - mar 23, 1994).bin", 0x200000, 0x587e6739, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp05) +STD_ROM_FN(md_whp05) + +struct BurnDriver BurnDrvmd_whp05 = { + "md_whp05", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940323)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp05RomInfo, md_whp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940324) +static struct BurnRomInfo md_whp04RomDesc[] = { + { "world heroes (usa) (prototype - mar 24, 1994).bin", 0x200000, 0x8a656942, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp04) +STD_ROM_FN(md_whp04) + +struct BurnDriver BurnDrvmd_whp04 = { + "md_whp04", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940324)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp04RomInfo, md_whp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Heroes (USA, Prototype, 19940330) +static struct BurnRomInfo md_whp03RomDesc[] = { + { "world heroes (usa) (prototype - mar 30, 1994).bin", 0x200000, 0x50c797cb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whp03) +STD_ROM_FN(md_whp03) + +struct BurnDriver BurnDrvmd_whp03 = { + "md_whp03", "md_wh", NULL, NULL, "1994", + "World Heroes (USA, Prototype, 19940330)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_whp03RomInfo, md_whp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World of Illusion Starring Mickey Mouse and Donald Duck (Euro) +static struct BurnRomInfo md_worldillRomDesc[] = { + { "mpr-15271.bin", 0x100000, 0x121c6a49, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worldill) +STD_ROM_FN(md_worldill) + +struct BurnDriver BurnDrvmd_worldill = { + "md_worldill", NULL, NULL, NULL, "1992", + "World of Illusion Starring Mickey Mouse and Donald Duck (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_worldillRomInfo, md_worldillRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World of Illusion - Fushigi na Magic Box (Jpn) +static struct BurnRomInfo md_worldilljRomDesc[] = { + { "world of illusion - fushigi na magic box (jpn).bin", 0x100000, 0xcb9ee238, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worldillj) +STD_ROM_FN(md_worldillj) + +struct BurnDriver BurnDrvmd_worldillj = { + "md_worldillj", "md_worldill", NULL, NULL, "1992", + "World of Illusion - Fushigi na Magic Box (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_worldilljRomInfo, md_worldilljRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World of Illusion - Fushigi na Magic Box(Jpn, Prototype) +static struct BurnRomInfo md_worldilljpRomDesc[] = { + { "world of illusion - fushigi na magic box (jpn) (beta).bin", 0x100000, 0x577f680f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worldilljp) +STD_ROM_FN(md_worldilljp) + +struct BurnDriver BurnDrvmd_worldilljp = { + "md_worldilljp", "md_worldill", NULL, NULL, "1992", + "World of Illusion - Fushigi na Magic Box(Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_worldilljpRomInfo, md_worldilljpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World of Illusion Starring Mickey Mouse and Donald Duck (USA, Kor) +static struct BurnRomInfo md_worldilluRomDesc[] = { + { "world of illusion starring mickey mouse and donald duck (usa, kor).bin", 0x100000, 0x921ebd1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worldillu) +STD_ROM_FN(md_worldillu) + +struct BurnDriver BurnDrvmd_worldillu = { + "md_worldillu", "md_worldill", NULL, NULL, "1992", + "World of Illusion Starring Mickey Mouse and Donald Duck (USA, Kor)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_worldilluRomInfo, md_worldilluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (USA) +static struct BurnRomInfo md_wsb95RomDesc[] = { + { "world series baseball '95 (usa).bin", 0x300000, 0x25130077, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95) +STD_ROM_FN(md_wsb95) + +struct BurnDriver BurnDrvmd_wsb95 = { + "md_wsb95", NULL, NULL, NULL, "1995", + "World Series Baseball '95 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95RomInfo, md_wsb95RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19941208) +static struct BurnRomInfo md_wsb95p23RomDesc[] = { + { "world series baseball '95 (prototype - dec 08, 1994).bin", 0x300000, 0x8846b050, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p23) +STD_ROM_FN(md_wsb95p23) + +struct BurnDriver BurnDrvmd_wsb95p23 = { + "md_wsb95p23", "md_wsb95", NULL, NULL, "1994", + "World Series Baseball '95 (Prototype, 19941208)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p23RomInfo, md_wsb95p23RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19941214) +static struct BurnRomInfo md_wsb95p22RomDesc[] = { + { "world series baseball '95 (prototype - dec 14, 1994).bin", 0x300000, 0x385be354, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p22) +STD_ROM_FN(md_wsb95p22) + +struct BurnDriver BurnDrvmd_wsb95p22 = { + "md_wsb95p22", "md_wsb95", NULL, NULL, "1994", + "World Series Baseball '95 (Prototype, 19941214)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p22RomInfo, md_wsb95p22RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19941228-SB) +static struct BurnRomInfo md_wsb95p21RomDesc[] = { + { "world series baseball '95 (prototype - dec 28, 1994 - sb).bin", 0x300000, 0x9e6dbc7c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p21) +STD_ROM_FN(md_wsb95p21) + +struct BurnDriver BurnDrvmd_wsb95p21 = { + "md_wsb95p21", "md_wsb95", NULL, NULL, "1994", + "World Series Baseball '95 (Prototype, 19941228-SB)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p21RomInfo, md_wsb95p21RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950202) +static struct BurnRomInfo md_wsb95p09RomDesc[] = { + { "world series baseball '95 (prototype - feb 02, 1995).bin", 0x300000, 0xa947fe5c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p09) +STD_ROM_FN(md_wsb95p09) + +struct BurnDriver BurnDrvmd_wsb95p09 = { + "md_wsb95p09", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p09RomInfo, md_wsb95p09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950203) +static struct BurnRomInfo md_wsb95p08RomDesc[] = { + { "world series baseball '95 (prototype - feb 03, 1995).bin", 0x300000, 0x1f3754fc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p08) +STD_ROM_FN(md_wsb95p08) + +struct BurnDriver BurnDrvmd_wsb95p08 = { + "md_wsb95p08", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950203)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p08RomInfo, md_wsb95p08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950207) +static struct BurnRomInfo md_wsb95p07RomDesc[] = { + { "world series baseball '95 (prototype - feb 07, 1995).bin", 0x300000, 0xe4056559, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p07) +STD_ROM_FN(md_wsb95p07) + +struct BurnDriver BurnDrvmd_wsb95p07 = { + "md_wsb95p07", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950207)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p07RomInfo, md_wsb95p07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950209-B) +static struct BurnRomInfo md_wsb95p06RomDesc[] = { + { "world series baseball '95 (prototype - feb 09, 1995 - b).bin", 0x300000, 0x33bb9eda, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p06) +STD_ROM_FN(md_wsb95p06) + +struct BurnDriver BurnDrvmd_wsb95p06 = { + "md_wsb95p06", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950209-B)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p06RomInfo, md_wsb95p06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950209) +static struct BurnRomInfo md_wsb95p05RomDesc[] = { + { "world series baseball '95 (prototype - feb 09, 1995).bin", 0x300000, 0x83be98cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p05) +STD_ROM_FN(md_wsb95p05) + +struct BurnDriver BurnDrvmd_wsb95p05 = { + "md_wsb95p05", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950209)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p05RomInfo, md_wsb95p05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950211) +static struct BurnRomInfo md_wsb95p04RomDesc[] = { + { "world series baseball '95 (prototype - feb 11, 1995).bin", 0x300000, 0xa0664fe9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p04) +STD_ROM_FN(md_wsb95p04) + +struct BurnDriver BurnDrvmd_wsb95p04 = { + "md_wsb95p04", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950211)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p04RomInfo, md_wsb95p04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950212) +static struct BurnRomInfo md_wsb95p03RomDesc[] = { + { "world series baseball '95 (prototype - feb 12, 1995).bin", 0x300000, 0x45da8f18, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p03) +STD_ROM_FN(md_wsb95p03) + +struct BurnDriver BurnDrvmd_wsb95p03 = { + "md_wsb95p03", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950212)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p03RomInfo, md_wsb95p03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950213) +static struct BurnRomInfo md_wsb95p02RomDesc[] = { + { "world series baseball '95 (prototype - feb 13, 1995).bin", 0x300000, 0x9f30ae30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p02) +STD_ROM_FN(md_wsb95p02) + +struct BurnDriver BurnDrvmd_wsb95p02 = { + "md_wsb95p02", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950213)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p02RomInfo, md_wsb95p02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950214) +static struct BurnRomInfo md_wsb95p01RomDesc[] = { + { "world series baseball '95 (prototype - feb 14, 1995).bin", 0x300000, 0xf300a857, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p01) +STD_ROM_FN(md_wsb95p01) + +struct BurnDriver BurnDrvmd_wsb95p01 = { + "md_wsb95p01", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950214)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p01RomInfo, md_wsb95p01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950101-TST) +static struct BurnRomInfo md_wsb95p20RomDesc[] = { + { "world series baseball '95 (prototype - jan 01, 1995 - tst).bin", 0x300000, 0xc7574372, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p20) +STD_ROM_FN(md_wsb95p20) + +struct BurnDriver BurnDrvmd_wsb95p20 = { + "md_wsb95p20", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950101-TST)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p20RomInfo, md_wsb95p20RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950103-TST) +static struct BurnRomInfo md_wsb95p19RomDesc[] = { + { "world series baseball '95 (prototype - jan 03, 1995 - tst).bin", 0x300000, 0x498363f7, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p19) +STD_ROM_FN(md_wsb95p19) + +struct BurnDriver BurnDrvmd_wsb95p19 = { + "md_wsb95p19", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950103-TST)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p19RomInfo, md_wsb95p19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950105) +static struct BurnRomInfo md_wsb95p18RomDesc[] = { + { "world series baseball '95 (prototype - jan 05, 1995).bin", 0x300000, 0x1820abfb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p18) +STD_ROM_FN(md_wsb95p18) + +struct BurnDriver BurnDrvmd_wsb95p18 = { + "md_wsb95p18", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950105)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p18RomInfo, md_wsb95p18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950109-TST) +static struct BurnRomInfo md_wsb95p17RomDesc[] = { + { "world series baseball '95 (prototype - jan 09, 1995 - tst).bin", 0x300000, 0x3de7cdbc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p17) +STD_ROM_FN(md_wsb95p17) + +struct BurnDriver BurnDrvmd_wsb95p17 = { + "md_wsb95p17", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950109-TST)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p17RomInfo, md_wsb95p17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950110) +static struct BurnRomInfo md_wsb95p16RomDesc[] = { + { "world series baseball '95 (prototype - jan 10, 1995).bin", 0x300000, 0xac2772b0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p16) +STD_ROM_FN(md_wsb95p16) + +struct BurnDriver BurnDrvmd_wsb95p16 = { + "md_wsb95p16", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950110)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p16RomInfo, md_wsb95p16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950114-RM) +static struct BurnRomInfo md_wsb95p15RomDesc[] = { + { "world series baseball '95 (prototype - jan 14, 1995 - rm).bin", 0x301655, 0xf70b07cf, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p15) +STD_ROM_FN(md_wsb95p15) + +struct BurnDriver BurnDrvmd_wsb95p15 = { + "md_wsb95p15", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950114-RM)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p15RomInfo, md_wsb95p15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950116) +static struct BurnRomInfo md_wsb95p14RomDesc[] = { + { "world series baseball '95 (prototype - jan 16, 1995).bin", 0x300000, 0xf0e22b21, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p14) +STD_ROM_FN(md_wsb95p14) + +struct BurnDriver BurnDrvmd_wsb95p14 = { + "md_wsb95p14", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950116)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p14RomInfo, md_wsb95p14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950118-RM) +static struct BurnRomInfo md_wsb95p13RomDesc[] = { + { "world series baseball '95 (prototype - jan 18, 1995 - rm).bin", 0x3023d3, 0x5ce70f8f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p13) +STD_ROM_FN(md_wsb95p13) + +struct BurnDriver BurnDrvmd_wsb95p13 = { + "md_wsb95p13", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950118-RM)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p13RomInfo, md_wsb95p13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950120) +static struct BurnRomInfo md_wsb95p12RomDesc[] = { + { "world series baseball '95 (prototype - jan 20, 1995).bin", 0x300000, 0x16c15e46, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p12) +STD_ROM_FN(md_wsb95p12) + +struct BurnDriver BurnDrvmd_wsb95p12 = { + "md_wsb95p12", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950120)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p12RomInfo, md_wsb95p12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950125) +static struct BurnRomInfo md_wsb95p11RomDesc[] = { + { "world series baseball '95 (prototype - jan 25, 1995).bin", 0x300000, 0xb45d9e33, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p11) +STD_ROM_FN(md_wsb95p11) + +struct BurnDriver BurnDrvmd_wsb95p11 = { + "md_wsb95p11", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950125)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p11RomInfo, md_wsb95p11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '95 (Prototype, 19950130) +static struct BurnRomInfo md_wsb95p10RomDesc[] = { + { "world series baseball '95 (prototype - jan 30, 1995).bin", 0x300000, 0x6aa76a9d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb95p10) +STD_ROM_FN(md_wsb95p10) + +struct BurnDriver BurnDrvmd_wsb95p10 = { + "md_wsb95p10", "md_wsb95", NULL, NULL, "1995", + "World Series Baseball '95 (Prototype, 19950130)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb95p10RomInfo, md_wsb95p10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '96 (USA) +static struct BurnRomInfo md_wsb96RomDesc[] = { + { "world series baseball '96 (usa).bin", 0x300000, 0x04ee8272, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb96) +STD_ROM_FN(md_wsb96) + +struct BurnDriver BurnDrvmd_wsb96 = { + "md_wsb96", NULL, NULL, NULL, "1996", + "World Series Baseball '96 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb96RomInfo, md_wsb96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball '98 (USA) +static struct BurnRomInfo md_wsb98RomDesc[] = { + { "world series baseball '98 (usa).bin", 0x300000, 0x05b1ab53, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb98) +STD_ROM_FN(md_wsb98) + +struct BurnDriver BurnDrvmd_wsb98 = { + "md_wsb98", NULL, NULL, NULL, "1997", + "World Series Baseball '98 (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsb98RomInfo, md_wsb98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (USA) +static struct BurnRomInfo md_wsbRomDesc[] = { + { "world series baseball (usa).bin", 0x200000, 0x57c1d5ec, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsb) +STD_ROM_FN(md_wsb) + +struct BurnDriver BurnDrvmd_wsb = { + "md_wsb", NULL, NULL, NULL, "1994", + "World Series Baseball (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbRomInfo, md_wsbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19931222) +static struct BurnRomInfo md_wsbp09RomDesc[] = { + { "world series baseball (prototype - dec 22, 1993).bin", 0x1fc05d, 0x0dc0558d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp09) +STD_ROM_FN(md_wsbp09) + +struct BurnDriver BurnDrvmd_wsbp09 = { + "md_wsbp09", "md_wsb", NULL, NULL, "1993", + "World Series Baseball (Prototype, 19931222)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp09RomInfo, md_wsbp09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19931226) +static struct BurnRomInfo md_wsbp08RomDesc[] = { + { "world series baseball (prototype - dec 26, 1993).bin", 0x200000, 0x472e6a58, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp08) +STD_ROM_FN(md_wsbp08) + +struct BurnDriver BurnDrvmd_wsbp08 = { + "md_wsbp08", "md_wsb", NULL, NULL, "1993", + "World Series Baseball (Prototype, 19931226)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp08RomInfo, md_wsbp08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19931229) +static struct BurnRomInfo md_wsbp07RomDesc[] = { + { "world series baseball (prototype - dec 29, 1993).bin", 0x200000, 0xed949936, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp07) +STD_ROM_FN(md_wsbp07) + +struct BurnDriver BurnDrvmd_wsbp07 = { + "md_wsbp07", "md_wsb", NULL, NULL, "1993", + "World Series Baseball (Prototype, 19931229)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp07RomInfo, md_wsbp07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940218) +static struct BurnRomInfo md_wsbp03RomDesc[] = { + { "world series baseball (prototype - feb 18, 1994).bin", 0x200000, 0x3cadfc50, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp03) +STD_ROM_FN(md_wsbp03) + +struct BurnDriver BurnDrvmd_wsbp03 = { + "md_wsbp03", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940218)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp03RomInfo, md_wsbp03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940103) +static struct BurnRomInfo md_wsbp06RomDesc[] = { + { "world series baseball (prototype - jan 03, 1994).bin", 0x200000, 0x4b53f035, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp06) +STD_ROM_FN(md_wsbp06) + +struct BurnDriver BurnDrvmd_wsbp06 = { + "md_wsbp06", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940103)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp06RomInfo, md_wsbp06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940106) +static struct BurnRomInfo md_wsbp05RomDesc[] = { + { "world series baseball (prototype - jan 06, 1994).bin", 0x200000, 0xb07de2d3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp05) +STD_ROM_FN(md_wsbp05) + +struct BurnDriver BurnDrvmd_wsbp05 = { + "md_wsbp05", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940106)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp05RomInfo, md_wsbp05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940116) +static struct BurnRomInfo md_wsbp04RomDesc[] = { + { "world series baseball (prototype - jan 16, 1994).bin", 0x200000, 0x5322133e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp04) +STD_ROM_FN(md_wsbp04) + +struct BurnDriver BurnDrvmd_wsbp04 = { + "md_wsbp04", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940116)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp04RomInfo, md_wsbp04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940304) +static struct BurnRomInfo md_wsbp02RomDesc[] = { + { "world series baseball (prototype - mar 04, 1994).bin", 0x1feaa2, 0xedda44a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp02) +STD_ROM_FN(md_wsbp02) + +struct BurnDriver BurnDrvmd_wsbp02 = { + "md_wsbp02", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940304)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp02RomInfo, md_wsbp02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19940527) +static struct BurnRomInfo md_wsbp01RomDesc[] = { + { "world series baseball (prototype - may 27, 1994).bin", 0x200000, 0xe473728a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp01) +STD_ROM_FN(md_wsbp01) + +struct BurnDriver BurnDrvmd_wsbp01 = { + "md_wsbp01", "md_wsb", NULL, NULL, "1994", + "World Series Baseball (Prototype, 19940527)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp01RomInfo, md_wsbp01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// World Series Baseball (Prototype, 19931001) +static struct BurnRomInfo md_wsbp10RomDesc[] = { + { "world series baseball (prototype - oct 01, 1993).bin", 0x200000, 0x4f7ab92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wsbp10) +STD_ROM_FN(md_wsbp10) + +struct BurnDriver BurnDrvmd_wsbp10 = { + "md_wsbp10", "md_wsb", NULL, NULL, "1993", + "World Series Baseball (Prototype, 19931001)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wsbp10RomInfo, md_wsbp10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Worms (Euro) +static struct BurnRomInfo md_wormsRomDesc[] = { + { "worms (euro).bin", 0x200000, 0xb9a8b299, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_worms) +STD_ROM_FN(md_worms) + +struct BurnDriver BurnDrvmd_worms = { + "md_worms", NULL, NULL, NULL, "1995", + "Worms (Euro)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wormsRomInfo, md_wormsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Worms (Euro, Prototype) +static struct BurnRomInfo md_wormspRomDesc[] = { + { "worms (euro) (beta).bin", 0x200000, 0x1d191694, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wormsp) +STD_ROM_FN(md_wormsp) + +struct BurnDriver BurnDrvmd_wormsp = { + "md_wormsp", "md_worms", NULL, NULL, "1995", + "Worms (Euro, Prototype)\0", NULL, "Ocean", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wormspRomInfo, md_wormspRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wrestle War (Euro, Jpn) +static struct BurnRomInfo md_wrestwarRomDesc[] = { + { "mpr-14025.bin", 0x080000, 0x2d162a85, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wrestwar) +STD_ROM_FN(md_wrestwar) + +struct BurnDriver BurnDrvmd_wrestwar = { + "md_wrestwar", NULL, NULL, NULL, "1991", + "Wrestle War (Euro, Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wrestwarRomInfo, md_wrestwarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wrestle War (Jpn, Prototype) +static struct BurnRomInfo md_wrestwarpRomDesc[] = { + { "wrestle war (jpn) (beta).bin", 0x080000, 0x1cdee87b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wrestwarp) +STD_ROM_FN(md_wrestwarp) + +struct BurnDriver BurnDrvmd_wrestwarp = { + "md_wrestwarp", "md_wrestwar", NULL, NULL, "1991", + "Wrestle War (Jpn, Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wrestwarpRomInfo, md_wrestwarpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wu Kong Wai Zhuan (Chi) +static struct BurnRomInfo md_wukongRomDesc[] = { + { "wu kong wai zhuan (chi) (unl).bin", 0x200000, 0x880a916e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wukong) +STD_ROM_FN(md_wukong) + +struct BurnDriver BurnDrvmd_wukong = { + "md_wukong", NULL, NULL, NULL, "1996", + "Wu Kong Wai Zhuan (Chi)\0", NULL, "Ming", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_wukongRomInfo, md_wukongRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// WWF Raw (World) +static struct BurnRomInfo md_wwfrawRomDesc[] = { + { "wwf raw (world).bin", 0x300000, 0x4ef5d411, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wwfraw) +STD_ROM_FN(md_wwfraw) + +struct BurnDriver BurnDrvmd_wwfraw = { + "md_wwfraw", NULL, NULL, NULL, "1994", + "WWF Raw (World)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wwfrawRomInfo, md_wwfrawRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// WWF Royal Rumble (World) +static struct BurnRomInfo md_wwfroyalRomDesc[] = { + { "wwf royal rumble (world).bin", 0x200000, 0xb69dc53e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wwfroyal) +STD_ROM_FN(md_wwfroyal) + +struct BurnDriver BurnDrvmd_wwfroyal = { + "md_wwfroyal", NULL, NULL, NULL, "1994", + "WWF Royal Rumble (World)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wwfroyalRomInfo, md_wwfroyalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// WWF Super WrestleMania (Euro, USA) +static struct BurnRomInfo md_swmaniaRomDesc[] = { + { "mpr-15215.bin", 0x100000, 0xb929d6c5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_swmania) +STD_ROM_FN(md_swmania) + +struct BurnDriver BurnDrvmd_swmania = { + "md_swmania", NULL, NULL, NULL, "1992", + "WWF Super WrestleMania (Euro, USA)\0", NULL, "Flying Edge", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_swmaniaRomInfo, md_swmaniaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// WWF WrestleMania - The Arcade Game (Euro, USA) +static struct BurnRomInfo md_wwfagRomDesc[] = { + { "9539d+9540d.bin", 0x400000, 0xa5d023f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wwfag) +STD_ROM_FN(md_wwfag) + +struct BurnDriver BurnDrvmd_wwfag = { + "md_wwfag", NULL, NULL, NULL, "1995", + "WWF WrestleMania - The Arcade Game (Euro, USA)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wwfagRomInfo, md_wwfagRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// WWF WrestleMania - The Arcade Game (USA, Prototype) +static struct BurnRomInfo md_wwfagaRomDesc[] = { + { "wwf wrestlemania - the arcade game (usa) (alpha).bin", 0x040000, 0x719d6155, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wwfaga) +STD_ROM_FN(md_wwfaga) + +struct BurnDriver BurnDrvmd_wwfaga = { + "md_wwfaga", "md_wwfag", NULL, NULL, "1995", + "WWF WrestleMania - The Arcade Game (USA, Prototype)\0", NULL, "Acclaim Entertainment", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wwfagaRomInfo, md_wwfagaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men (Euro) +static struct BurnRomInfo md_xmenRomDesc[] = { + { "mpr-15505.bin", 0x100000, 0x0b78ca97, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen) +STD_ROM_FN(md_xmen) + +struct BurnDriver BurnDrvmd_xmen = { + "md_xmen", NULL, NULL, NULL, "1993", + "X-Men (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmenRomInfo, md_xmenRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men (USA) +static struct BurnRomInfo md_xmenuRomDesc[] = { + { "x-men (usa).bin", 0x100000, 0xf71b21b4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmenu) +STD_ROM_FN(md_xmenu) + +struct BurnDriver BurnDrvmd_xmenu = { + "md_xmenu", "md_xmen", NULL, NULL, "1993", + "X-Men (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmenuRomInfo, md_xmenuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Euro, USA) +static struct BurnRomInfo md_xmen2RomDesc[] = { + { "x-men 2 - clone wars (euro, usa).bin", 0x200000, 0x710bc628, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2) +STD_ROM_FN(md_xmen2) + +struct BurnDriver BurnDrvmd_xmen2 = { + "md_xmen2", NULL, NULL, NULL, "1995", + "X-Men 2 - Clone Wars (Euro, USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2RomInfo, md_xmen2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941202) +static struct BurnRomInfo md_xmen2p12RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 02, 1994).bin", 0x1fbe22, 0x7ad7a4e9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p12) +STD_ROM_FN(md_xmen2p12) + +struct BurnDriver BurnDrvmd_xmen2p12 = { + "md_xmen2p12", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941202)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p12RomInfo, md_xmen2p12RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941203) +static struct BurnRomInfo md_xmen2p11RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 03, 1994).bin", 0x200000, 0x669b939c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p11) +STD_ROM_FN(md_xmen2p11) + +struct BurnDriver BurnDrvmd_xmen2p11 = { + "md_xmen2p11", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941203)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p11RomInfo, md_xmen2p11RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941206) +static struct BurnRomInfo md_xmen2p10RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 06, 1994).bin", 0x200000, 0x5b1d0cf5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p10) +STD_ROM_FN(md_xmen2p10) + +struct BurnDriver BurnDrvmd_xmen2p10 = { + "md_xmen2p10", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941206)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p10RomInfo, md_xmen2p10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941207) +static struct BurnRomInfo md_xmen2p09RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 07, 1994).bin", 0x200000, 0x246a30da, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p09) +STD_ROM_FN(md_xmen2p09) + +struct BurnDriver BurnDrvmd_xmen2p09 = { + "md_xmen2p09", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941207)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p09RomInfo, md_xmen2p09RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941208) +static struct BurnRomInfo md_xmen2p08RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 08, 1994).bin", 0x1feedc, 0xc6d90b1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p08) +STD_ROM_FN(md_xmen2p08) + +struct BurnDriver BurnDrvmd_xmen2p08 = { + "md_xmen2p08", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941208)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p08RomInfo, md_xmen2p08RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941209) +static struct BurnRomInfo md_xmen2p07RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 09, 1994).bin", 0x200000, 0x28307b58, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p07) +STD_ROM_FN(md_xmen2p07) + +struct BurnDriver BurnDrvmd_xmen2p07 = { + "md_xmen2p07", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941209)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p07RomInfo, md_xmen2p07RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941210) +static struct BurnRomInfo md_xmen2p06RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 10, 1994).bin", 0x1ffaf0, 0x73e2effe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p06) +STD_ROM_FN(md_xmen2p06) + +struct BurnDriver BurnDrvmd_xmen2p06 = { + "md_xmen2p06", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941210)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p06RomInfo, md_xmen2p06RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941211-A) +static struct BurnRomInfo md_xmen2p05RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 11, 1994 - a).bin", 0x200000, 0x11415b86, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p05) +STD_ROM_FN(md_xmen2p05) + +struct BurnDriver BurnDrvmd_xmen2p05 = { + "md_xmen2p05", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941211-A)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p05RomInfo, md_xmen2p05RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941211) +static struct BurnRomInfo md_xmen2p04RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 11, 1994).bin", 0x200000, 0x51876259, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p04) +STD_ROM_FN(md_xmen2p04) + +struct BurnDriver BurnDrvmd_xmen2p04 = { + "md_xmen2p04", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941211)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p04RomInfo, md_xmen2p04RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941214) +static struct BurnRomInfo md_xmen2p03RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 14, 1994).bin", 0x200000, 0xcd662de6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p03) +STD_ROM_FN(md_xmen2p03) + +struct BurnDriver BurnDrvmd_xmen2p03 = { + "md_xmen2p03", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941214)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p03RomInfo, md_xmen2p03RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941215) +static struct BurnRomInfo md_xmen2p02RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 15, 1994).bin", 0x1ffe54, 0xa5188e30, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p02) +STD_ROM_FN(md_xmen2p02) + +struct BurnDriver BurnDrvmd_xmen2p02 = { + "md_xmen2p02", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941215)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p02RomInfo, md_xmen2p02RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941216) +static struct BurnRomInfo md_xmen2p01RomDesc[] = { + { "x-men 2 - clone wars (prototype - dec 16, 1994).bin", 0x200000, 0xe8c40972, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p01) +STD_ROM_FN(md_xmen2p01) + +struct BurnDriver BurnDrvmd_xmen2p01 = { + "md_xmen2p01", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941216)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p01RomInfo, md_xmen2p01RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19940506) +static struct BurnRomInfo md_xmen2p19RomDesc[] = { + { "x-men 2 - clone wars (prototype - may 06, 1994).bin", 0x200000, 0xa720ebb4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p19) +STD_ROM_FN(md_xmen2p19) + +struct BurnDriver BurnDrvmd_xmen2p19 = { + "md_xmen2p19", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19940506)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p19RomInfo, md_xmen2p19RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19940510) +static struct BurnRomInfo md_xmen2p18RomDesc[] = { + { "x-men 2 - clone wars (prototype - may 10, 1994).bin", 0x200000, 0x9b5dd185, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p18) +STD_ROM_FN(md_xmen2p18) + +struct BurnDriver BurnDrvmd_xmen2p18 = { + "md_xmen2p18", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19940510)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p18RomInfo, md_xmen2p18RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941117) +static struct BurnRomInfo md_xmen2p16RomDesc[] = { + { "x-men 2 - clone wars (prototype - nov 17, 1994).bin", 0x200000, 0xd90cd0de, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p16) +STD_ROM_FN(md_xmen2p16) + +struct BurnDriver BurnDrvmd_xmen2p16 = { + "md_xmen2p16", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941117)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p16RomInfo, md_xmen2p16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941123) +static struct BurnRomInfo md_xmen2p15RomDesc[] = { + { "x-men 2 - clone wars (prototype - nov 23, 1994).bin", 0x200000, 0x4386a381, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p15) +STD_ROM_FN(md_xmen2p15) + +struct BurnDriver BurnDrvmd_xmen2p15 = { + "md_xmen2p15", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941123)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p15RomInfo, md_xmen2p15RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941128) +static struct BurnRomInfo md_xmen2p14RomDesc[] = { + { "x-men 2 - clone wars (prototype - nov 28, 1994).bin", 0x200000, 0x70383a4d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p14) +STD_ROM_FN(md_xmen2p14) + +struct BurnDriver BurnDrvmd_xmen2p14 = { + "md_xmen2p14", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941128)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p14RomInfo, md_xmen2p14RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941130) +static struct BurnRomInfo md_xmen2p13RomDesc[] = { + { "x-men 2 - clone wars (prototype - nov 30, 1994).bin", 0x200000, 0x331dae0a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p13) +STD_ROM_FN(md_xmen2p13) + +struct BurnDriver BurnDrvmd_xmen2p13 = { + "md_xmen2p13", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941130)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p13RomInfo, md_xmen2p13RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-Men 2 - Clone Wars (Prototype, 19941018) +static struct BurnRomInfo md_xmen2p17RomDesc[] = { + { "x-men 2 - clone wars (prototype - oct 18, 1994).bin", 0x200000, 0x52cff37d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xmen2p17) +STD_ROM_FN(md_xmen2p17) + +struct BurnDriver BurnDrvmd_xmen2p17 = { + "md_xmen2p17", "md_xmen2", NULL, NULL, "1994", + "X-Men 2 - Clone Wars (Prototype, 19941018)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xmen2p17RomInfo, md_xmen2p17RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-perts (USA) +static struct BurnRomInfo md_xpertRomDesc[] = { + { "x-perts (usa).bin", 0x400000, 0x57e8abfd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xpert) +STD_ROM_FN(md_xpert) + +struct BurnDriver BurnDrvmd_xpert = { + "md_xpert", NULL, NULL, NULL, "1996", + "X-perts (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xpertRomInfo, md_xpertRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// X-perts (Prototype) +static struct BurnRomInfo md_xpertpRomDesc[] = { + { "x-perts (prototype).bin", 0x400000, 0x9d067249, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xpertp) +STD_ROM_FN(md_xpertp) + +struct BurnDriver BurnDrvmd_xpertp = { + "md_xpertp", "md_xpert", NULL, NULL, "1996", + "X-perts (Prototype)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xpertpRomInfo, md_xpertpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// XDR - X Dazedly Ray (Jpn) +static struct BurnRomInfo md_xdrxdaRomDesc[] = { + { "xdr - x dazedly ray (jpn).bin", 0x080000, 0xab22d002, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xdrxda) +STD_ROM_FN(md_xdrxda) + +struct BurnDriver BurnDrvmd_xdrxda = { + "md_xdrxda", NULL, NULL, NULL, "1990", + "XDR - X Dazedly Ray (Jpn)\0", NULL, "Unipac", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xdrxdaRomInfo, md_xdrxdaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Xenon 2 Megablast (Euro) +static struct BurnRomInfo md_xenon2mRomDesc[] = { + { "mpr-15064.bin", 0x080000, 0x59abe7f9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xenon2m) +STD_ROM_FN(md_xenon2m) + +struct BurnDriver BurnDrvmd_xenon2m = { + "md_xenon2m", NULL, NULL, NULL, "1992", + "Xenon 2 Megablast (Euro)\0", NULL, "Virgin Games", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xenon2mRomInfo, md_xenon2mRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Xiao Monv - Magic Girl (Chi) +static struct BurnRomInfo md_xiaomoRomDesc[] = { + { "xiao monv - magic girl (chi) (unl).bin", 0x080000, 0x8e49a92e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xiaomo) +STD_ROM_FN(md_xiaomo) + +struct BurnDriver BurnDrvmd_xiaomo = { + "md_xiaomo", NULL, NULL, NULL, "199?", + "Xiao Monv - Magic Girl (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_xiaomoRomInfo, md_xiaomoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Xin Qi Gai Wang Zi (Chi, Alt) +static struct BurnRomInfo md_xinqig1RomDesc[] = { + { "xin qi gai wang zi (chi) (alt) (unl).bin", 0x400000, 0xda5a4bfe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xinqig1) +STD_ROM_FN(md_xinqig1) + +struct BurnDriver BurnDrvmd_xinqig1 = { + "md_xinqig1", "md_xinqig", NULL, NULL, "1996", + "Xin Qi Gai Wang Zi (Chi, Alt)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_BEGGAR, GBF_MISC, 0, + MegadriveGetZipName, md_xinqig1RomInfo, md_xinqig1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Xin Qi Gai Wang Zi (Chi) +static struct BurnRomInfo md_xinqigRomDesc[] = { + { "xin qi gai wang zi (chi) (unl).bin", 0x400000, 0xdd2f38b5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_xinqig) +STD_ROM_FN(md_xinqig) + +struct BurnDriver BurnDrvmd_xinqig = { + "md_xinqig", NULL, NULL, NULL, "1996", + "Xin Qi Gai Wang Zi (Chi)\0", NULL, "C&E", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_BEGGAR, GBF_MISC, 0, + MegadriveGetZipName, md_xinqigRomInfo, md_xinqigRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ya Se Chuan Shuo (Chi) +static struct BurnRomInfo md_yasechRomDesc[] = { + { "ya se chuan shuo (chi) (unl).bin", 0x200000, 0x095b9a15, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yasech) +STD_ROM_FN(md_yasech) + +struct BurnDriver BurnDrvmd_yasech = { + "md_yasech", NULL, NULL, NULL, "1995", + "Ya Se Chuan Shuo (Chi)\0", NULL, "Chuanpu Technologies", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_yasechRomInfo, md_yasechRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Yang Jia Jiang - Yang Warrior Family (Chi) +static struct BurnRomInfo md_yangjiRomDesc[] = { + { "yang jia jiang - yang warrior family (chi) (unl).bin", 0x200000, 0x6604a79e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yangji) +STD_ROM_FN(md_yangji) + +struct BurnDriver BurnDrvmd_yangji = { + "md_yangji", NULL, NULL, NULL, "199?", + "Yang Jia Jiang - Yang Warrior Family (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_yangjiRomInfo, md_yangjiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Yogi Bear's Cartoon Capers (Euro) +static struct BurnRomInfo md_yogibearRomDesc[] = { + { "yogi bear's cartoon capers (euro).bin", 0x100000, 0x204f97d8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yogibear) +STD_ROM_FN(md_yogibear) + +struct BurnDriver BurnDrvmd_yogibear = { + "md_yogibear", NULL, NULL, NULL, "1994", + "Yogi Bear's Cartoon Capers (Euro)\0", NULL, "Empire Interactive", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_yogibearRomInfo, md_yogibearRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Young Indiana Jones Chronicles (USA, Prototype) +static struct BurnRomInfo md_youngindRomDesc[] = { + { "young indiana jones chronicles, the (usa) (prototype).bin", 0x080000, 0x44f6be35, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_youngind) +STD_ROM_FN(md_youngind) + +struct BurnDriver BurnDrvmd_youngind = { + "md_youngind", NULL, NULL, NULL, "199?", + "The Young Indiana Jones Chronicles (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_youngindRomInfo, md_youngindRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ys III (USA) +static struct BurnRomInfo md_ys3RomDesc[] = { + { "ys iii (usa).bin", 0x100000, 0xea27976e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ys3) +STD_ROM_FN(md_ys3) + +struct BurnDriver BurnDrvmd_ys3 = { + "md_ys3", NULL, NULL, NULL, "1991", + "Ys III (USA)\0", NULL, "Renovation", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ys3RomInfo, md_ys3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ys - Wanderers from Ys (Jpn) +static struct BurnRomInfo md_ys3jRomDesc[] = { + { "ys - wanderers from ys (jpn).bin", 0x100000, 0x52da4e76, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ys3j) +STD_ROM_FN(md_ys3j) + +struct BurnDriver BurnDrvmd_ys3j = { + "md_ys3j", "md_ys3", NULL, NULL, "1991", + "Ys - Wanderers from Ys (Jpn)\0", NULL, "Reno", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_ys3jRomInfo, md_ys3jRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Yuu Yuu Hakusho - Makyou Toitsusen (Jpn) +static struct BurnRomInfo md_yuusfRomDesc[] = { + { "yuu yuu hakusho - makyou toitsusen (jpn).bin", 0x300000, 0x71ceac6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yuusf) +STD_ROM_FN(md_yuusf) + +struct BurnDriver BurnDrvmd_yuusf = { + "md_yuusf", NULL, NULL, NULL, "1994", + "Yuu Yuu Hakusho - Makyou Toitsusen (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_yuusfRomInfo, md_yuusfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Yuu Yuu Hakusho - Sunset Fighters (Bra) +static struct BurnRomInfo md_yuusfbrRomDesc[] = { + { "yuu yuu hakusho - sunset fighters (bra).bin", 0x300000, 0xfe3fb8ee, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yuusfbr) +STD_ROM_FN(md_yuusfbr) + +struct BurnDriver BurnDrvmd_yuusfbr = { + "md_yuusfbr", "md_yuusf", NULL, NULL, "199?", + "Yuu Yuu Hakusho - Sunset Fighters (Bra)\0", NULL, "Tec Toy", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_yuusfbrRomInfo, md_yuusfbrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Yuu Yuu Hakusho Gaiden (Jpn) +static struct BurnRomInfo md_yuugaiRomDesc[] = { + { "yuu yuu hakusho gaiden (jpn).bin", 0x200000, 0x7dc98176, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_yuugai) +STD_ROM_FN(md_yuugai) + +struct BurnDriver BurnDrvmd_yuugai = { + "md_yuugai", NULL, NULL, NULL, "1994", + "Yuu Yuu Hakusho Gaiden (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_yuugaiRomInfo, md_yuugaiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zan Yasha Enbukyoku (Jpn) +static struct BurnRomInfo md_zanyashaRomDesc[] = { + { "zan yasha enbukyoku (jpn).bin", 0x080000, 0x637fe8f3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zanyasha) +STD_ROM_FN(md_zanyasha) + +struct BurnDriver BurnDrvmd_zanyasha = { + "md_zanyasha", NULL, NULL, NULL, "1991", + "Zan Yasha Enbukyoku (Jpn)\0", NULL, "Wolf Team", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_zanyashaRomInfo, md_zanyashaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zany Golf (Euro, USA) +static struct BurnRomInfo md_zanygolf1RomDesc[] = { + { "zany golf (euro, usa).bin", 0x080000, 0xed5d12ea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zanygolf1) +STD_ROM_FN(md_zanygolf1) + +struct BurnDriver BurnDrvmd_zanygolf1 = { + "md_zanygolf1", "md_zanygolf", NULL, NULL, "1990", + "Zany Golf (Euro, USA)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zanygolf1RomInfo, md_zanygolf1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zero the Kamikaze Squirrel (Euro) +static struct BurnRomInfo md_zerokamiRomDesc[] = { + { "zero the kamikaze squirrel (euro).bin", 0x200000, 0x45ff0b4b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zerokami) +STD_ROM_FN(md_zerokami) + +struct BurnDriver BurnDrvmd_zerokami = { + "md_zerokami", NULL, NULL, NULL, "1994", + "Zero the Kamikaze Squirrel (Euro)\0", NULL, "SunSoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zerokamiRomInfo, md_zerokamiRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zero the Kamikaze Squirrel (USA) +static struct BurnRomInfo md_zerokamiuRomDesc[] = { + { "zero the kamikaze squirrel (usa).bin", 0x200000, 0x423968df, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zerokamiu) +STD_ROM_FN(md_zerokamiu) + +struct BurnDriver BurnDrvmd_zerokamiu = { + "md_zerokamiu", "md_zerokami", NULL, NULL, "1994", + "Zero the Kamikaze Squirrel (USA)\0", NULL, "SunSoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zerokamiuRomInfo, md_zerokamiuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zero Wing (Euro) +static struct BurnRomInfo md_zerowingRomDesc[] = { + { "mpr-14463.bin", 0x100000, 0x89b744a3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zerowing) +STD_ROM_FN(md_zerowing) + +struct BurnDriver BurnDrvmd_zerowing = { + "md_zerowing", NULL, NULL, NULL, "1991", + "Zero Wing (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zerowingRomInfo, md_zerowingRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zero Wing (Jpn) +static struct BurnRomInfo md_zerowingjRomDesc[] = { + { "zero wing (jpn).bin", 0x100000, 0x7e203d2b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zerowingj) +STD_ROM_FN(md_zerowingj) + +struct BurnDriver BurnDrvmd_zerowingj = { + "md_zerowingj", "md_zerowing", NULL, NULL, "1991", + "Zero Wing (Jpn)\0", NULL, "Toaplan", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zerowingjRomInfo, md_zerowingjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zhuo Gui Da Shi - Ghost Hunter (Chi) +static struct BurnRomInfo md_zhuoguRomDesc[] = { + { "zhuo gui da shi - ghost hunter (chi) (unl).bin", 0x080000, 0x76c62a8b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zhuogu) +STD_ROM_FN(md_zhuogu) + +struct BurnDriver BurnDrvmd_zhuogu = { + "md_zhuogu", NULL, NULL, NULL, "1994", + "Zhuo Gui Da Shi - Ghost Hunter (Chi)\0", NULL, "Shenchi Technology", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zhuoguRomInfo, md_zhuoguRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zombie High (USA, Prototype) +static struct BurnRomInfo md_zombhighRomDesc[] = { + { "zombie high (usa) (prototype).bin", 0x0fa0ef, 0x7bea6194, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zombhigh) +STD_ROM_FN(md_zombhigh) + +struct BurnDriver BurnDrvmd_zombhigh = { + "md_zombhigh", NULL, NULL, NULL, "199?", + "Zombie High (USA, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zombhighRomInfo, md_zombhighRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zombies (Euro) +static struct BurnRomInfo md_zombiesRomDesc[] = { + { "zombies (euro).bin", 0x100000, 0x179a1aa2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zombies) +STD_ROM_FN(md_zombies) + +struct BurnDriver BurnDrvmd_zombies = { + "md_zombies", NULL, NULL, NULL, "1993", + "Zombies (Euro)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zombiesRomInfo, md_zombiesRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zombies Ate My Neighbors (USA) +static struct BurnRomInfo md_zombiesuRomDesc[] = { + { "zombies ate my neighbors (usa).bin", 0x100000, 0x2bf3626f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zombiesu) +STD_ROM_FN(md_zombiesu) + +struct BurnDriver BurnDrvmd_zombiesu = { + "md_zombiesu", "md_zombies", NULL, NULL, "1994", + "Zombies Ate My Neighbors (USA)\0", NULL, "Konami", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zombiesuRomInfo, md_zombiesuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zool - Ninja of the 'Nth' Dimension (Euro) +static struct BurnRomInfo md_zoolRomDesc[] = { + { "zool04.bin", 0x100000, 0x1ee58b03, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zool) +STD_ROM_FN(md_zool) + +struct BurnDriver BurnDrvmd_zool = { + "md_zool", NULL, NULL, NULL, "1993", + "Zool - Ninja of the 'Nth' Dimension (Euro)\0", NULL, "Electronic Arts", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zoolRomInfo, md_zoolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zool - Ninja of the 'Nth' Dimension (USA) +static struct BurnRomInfo md_zooluRomDesc[] = { + { "zool - ninja of the 'nth' dimension (usa).bin", 0x100000, 0xcb2939f1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zoolu) +STD_ROM_FN(md_zoolu) + +struct BurnDriver BurnDrvmd_zoolu = { + "md_zoolu", "md_zool", NULL, NULL, "1993", + "Zool - Ninja of the 'Nth' Dimension (USA)\0", NULL, "GameTek", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zooluRomInfo, md_zooluRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zoop (Euro) +static struct BurnRomInfo md_zoopRomDesc[] = { + { "mpr-18564.bin", 0x080000, 0x2fdac6ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zoop) +STD_ROM_FN(md_zoop) + +struct BurnDriver BurnDrvmd_zoop = { + "md_zoop", NULL, NULL, NULL, "1995", + "Zoop (Euro)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zoopRomInfo, md_zoopRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Zoop (USA) +static struct BurnRomInfo md_zoopuRomDesc[] = { + { "zoop (usa).bin", 0x080000, 0xa899befa, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_zoopu) +STD_ROM_FN(md_zoopu) + +struct BurnDriver BurnDrvmd_zoopu = { + "md_zoopu", "md_zoop", NULL, NULL, "1995", + "Zoop (USA)\0", NULL, "Viacom New Media", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_zoopuRomInfo, md_zoopuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Flux (Euro) +static struct BurnRomInfo md_fluxRomDesc[] = { + { "flux (euro).bin", 0x040000, 0x2a1da08c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_flux) +STD_ROM_FN(md_flux) + +struct BurnDriver BurnDrvmd_flux = { + "md_flux", NULL, NULL, NULL, "199?", + "Flux (Euro)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fluxRomInfo, md_fluxRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mega Anser (Jpn) +static struct BurnRomInfo md_megaanRomDesc[] = { + { "mega anser (jpn).bin", 0x080000, 0x08ece367, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_megaan) +STD_ROM_FN(md_megaan) + +struct BurnDriver BurnDrvmd_megaan = { + "md_megaan", NULL, NULL, NULL, "199?", + "Mega Anser (Jpn)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_megaanRomInfo, md_megaanRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// MegaNet (Bra) +static struct BurnRomInfo md_meganetRomDesc[] = { + { "meganet (bra).bin", 0x040000, 0xfab33cc2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_meganet) +STD_ROM_FN(md_meganet) + +struct BurnDriver BurnDrvmd_meganet = { + "md_meganet", NULL, NULL, NULL, "199?", + "MegaNet (Bra)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_meganetRomInfo, md_meganetRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sega Channel (Scientific Atlanta) (USA) +static struct BurnRomInfo md_segachnlRomDesc[] = { + { "sega channel (usa).bin", 0x040000, 0xbc79b6ed, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_segachnl) +STD_ROM_FN(md_segachnl) + +struct BurnDriver BurnDrvmd_segachnl = { + "md_segachnl", NULL, NULL, NULL, "199?", + "Sega Channel (Scientific Atlanta) (USA)\0", NULL, "Scientific Atlanta", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_segachnlRomInfo, md_segachnlRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sega Channel (General Instrument) (USA) +static struct BurnRomInfo md_segachnlaRomDesc[] = { + { "sega channel (general instruments) (usa).bin", 0x080000, 0x5df93f11, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_segachnla) +STD_ROM_FN(md_segachnla) + +struct BurnDriver BurnDrvmd_segachnla = { + "md_segachnla", "md_segachnl", NULL, NULL, "199?", + "Sega Channel (General Instrument) (USA)\0", NULL, "Scientific Atlanta", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_segachnlaRomInfo, md_segachnlaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sega Channel Demo (USA) +static struct BurnRomInfo md_segachdRomDesc[] = { + { "sega channel demo (usa).bin", 0x080000, 0x2abae889, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_segachd) +STD_ROM_FN(md_segachd) + +struct BurnDriver BurnDrvmd_segachd = { + "md_segachd", NULL, NULL, NULL, "199?", + "Sega Channel Demo (USA)\0", NULL, "Scientific Atlanta", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_segachdRomInfo, md_segachdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 12 in 1 +static struct BurnRomInfo md_12in1RomDesc[] = { + { "12-in-1 (unl).bin", 0x200000, 0xa98bf454, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_12in1) +STD_ROM_FN(md_12in1) + +struct BurnDriver BurnDrvmd_12in1 = { + "md_12in1", NULL, NULL, NULL, "199?", + "12 in 1\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_12IN1, GBF_MISC, 0, + MegadriveGetZipName, md_12in1RomInfo, md_12in1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// 4 in 1 (Pirate) +static struct BurnRomInfo md_4in1pbRomDesc[] = { + { "4-in-1 (pirate).bin", 0x200000, 0xbe72857b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_4in1pb) +STD_ROM_FN(md_4in1pb) + +struct BurnDriver BurnDrvmd_4in1pb = { + "md_4in1pb", NULL, NULL, NULL, "199?", + "4 in 1 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_12IN1, GBF_MISC, 0, + MegadriveGetZipName, md_4in1pbRomInfo, md_4in1pbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// A Bug's Life +static struct BurnRomInfo md_bugslifeRomDesc[] = { + { "bug's life, a (unl).bin", 0x100000, 0x10458e09, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bugslife) +STD_ROM_FN(md_bugslife) + +struct BurnDriver BurnDrvmd_bugslife = { + "md_bugslife", NULL, NULL, NULL, "199?", + "A Bug's Life\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_BUGSLIFE, GBF_MISC, 0, + MegadriveGetZipName, md_bugslifeRomInfo, md_bugslifeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// A Bug's Life (Alt?) +static struct BurnRomInfo md_bugslifeaRomDesc[] = { + { "bug's life (unl).bin", 0x100000, 0xed1c1a67, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_bugslifea) +STD_ROM_FN(md_bugslifea) + +struct BurnDriver BurnDrvmd_bugslifea = { + "md_bugslifea", "md_bugslife", NULL, NULL, "199?", + "A Bug's Life (Alt?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_bugslifeaRomInfo, md_bugslifeaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chinese Fighter III (Chi) +static struct BurnRomInfo md_chinf3RomDesc[] = { + { "chinese fighter iii (unl).bin", 0x200000, 0xe833bc6e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chinf3) +STD_ROM_FN(md_chinf3) + +struct BurnDriver BurnDrvmd_chinf3 = { + "md_chinf3", NULL, NULL, NULL, "199?", + "Chinese Fighter III (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_CHINFIGHT3, GBF_MISC, 0, + MegadriveGetZipName, md_chinf3RomInfo, md_chinf3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Earth Defense (USA) +static struct BurnRomInfo md_earthdefRomDesc[] = { + { "earth defense (usa) (unl).bin", 0x080000, 0x3519c422, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_earthdef) +STD_ROM_FN(md_earthdef) + +struct BurnDriver BurnDrvmd_earthdef = { + "md_earthdef", NULL, NULL, NULL, "1995", + "Earth Defense (USA)\0", NULL, "Realtec", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC, GBF_MISC, 0, + MegadriveGetZipName, md_earthdefRomInfo, md_earthdefRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Funny World & Balloon Boy (USA) +static struct BurnRomInfo md_funnywldRomDesc[] = { + { "funny world & balloon boy (usa) (unl).bin", 0x080000, 0xa82f05f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_funnywld) +STD_ROM_FN(md_funnywld) + +struct BurnDriver BurnDrvmd_funnywld = { + "md_funnywld", NULL, NULL, NULL, "1993", + "Funny World & Balloon Boy (USA)\0", NULL, "Realtec", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC, GBF_MISC, 0, + MegadriveGetZipName, md_funnywldRomInfo, md_funnywldRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Golden 10 in 1 +static struct BurnRomInfo md_golden10RomDesc[] = { + { "golden 10-in-1 (bad dump).bin", 0x100000, 0x4fa3f82b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_golden10) +STD_ROM_FN(md_golden10) + +struct BurnDriver BurnDrvmd_golden10 = { + "md_golden10", NULL, NULL, NULL, "199?", + "Golden 10 in 1\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_12IN1, GBF_MISC, 0, + MegadriveGetZipName, md_golden10RomInfo, md_golden10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hua Mu Lan - Mulan (Chi) +static struct BurnRomInfo md_huamulRomDesc[] = { + { "hua mu lan - mulan (chi) (unl).bin", 0x200000, 0x796882b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_huamul) +STD_ROM_FN(md_huamul) + +struct BurnDriver BurnDrvmd_huamul = { + "md_huamul", NULL, NULL, NULL, "199?", + "Hua Mu Lan - Mulan (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_MULAN, GBF_MISC, 0, + MegadriveGetZipName, md_huamulRomInfo, md_huamulRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Huan Le Tao Qi Shu - Smart Mouse (Chi) +static struct BurnRomInfo md_huanleRomDesc[] = { + { "huan le tao qi shu - smart mouse (chi) (unl).bin", 0x080000, 0xdecdf740, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_huanle) +STD_ROM_FN(md_huanle) + +struct BurnDriver BurnDrvmd_huanle = { + "md_huanle", NULL, NULL, NULL, "199?", + "Huan Le Tao Qi Shu - Smart Mouse (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SMOUSE, GBF_MISC, 0, + MegadriveGetZipName, md_huanleRomInfo, md_huanleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The King of Fighters '98 +static struct BurnRomInfo md_kof98RomDesc[] = { + { "king of fighters '98, the (unl).bin", 0x200000, 0xcbc38eea, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kof98) +STD_ROM_FN(md_kof98) + +struct BurnDriver BurnDrvmd_kof98 = { + "md_kof98", NULL, NULL, NULL, "199?", + "The King of Fighters '98\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_KOF98, GBF_MISC, 0, + MegadriveGetZipName, md_kof98RomInfo, md_kof98RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The King of Fighters 99 +static struct BurnRomInfo md_kof99RomDesc[] = { + { "the king of fighters 99 (unl).bin", 0x300000, 0x54638c11, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kof99) +STD_ROM_FN(md_kof99) + +struct BurnDriver BurnDrvmd_kof99 = { + "md_kof99", NULL, NULL, NULL, "199?", + "The King of Fighters 99\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_KOF99, GBF_MISC, 0, + MegadriveGetZipName, md_kof99RomInfo, md_kof99RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The King of Fighters '99 +static struct BurnRomInfo md_kof99aRomDesc[] = { + { "king of fighters 99 (unl).bin", 0x300000, 0xab82afbe, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kof99a) +STD_ROM_FN(md_kof99a) + +struct BurnDriver BurnDrvmd_kof99a = { + "md_kof99a", "md_kof99", NULL, NULL, "199?", + "The King of Fighters '99\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kof99aRomInfo, md_kof99aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Linghuan Daoshi Super Magician (Chi) +static struct BurnRomInfo md_supmagicRomDesc[] = { + { "elf wor (chi) (unl).bin", 0x100000, 0xe24ac6b2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supmagic) +STD_ROM_FN(md_supmagic) + +struct BurnDriver BurnDrvmd_supmagic = { + "md_supmagic", NULL, NULL, NULL, "199?", + "Linghuan Daoshi Super Magician (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_ELFWOR, GBF_MISC, 0, + MegadriveGetZipName, md_supmagicRomInfo, md_supmagicRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi Zi Wang II - The Lion King II +static struct BurnRomInfo md_lionkin2RomDesc[] = { + { "shi zi wang ii - the lion king ii, the (chi) (unl).bin", 0x200000, 0xaff46765, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionkin2) +STD_ROM_FN(md_lionkin2) + +struct BurnDriver BurnDrvmd_lionkin2 = { + "md_lionkin2", NULL, NULL, NULL, "199?", + "Shi Zi Wang II - The Lion King II\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_LIONK2, GBF_MISC, 0, + MegadriveGetZipName, md_lionkin2RomInfo, md_lionkin2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi Zi Wang 3 - The Lion King 3 +static struct BurnRomInfo md_lionkin3RomDesc[] = { + { "shi zi wang 3 - the lion king 3 (chi) (unl).bin", 0x200000, 0xc004219d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionkin3) +STD_ROM_FN(md_lionkin3) + +struct BurnDriver BurnDrvmd_lionkin3 = { + "md_lionkin3", NULL, NULL, NULL, "199?", + "Shi Zi Wang 3 - The Lion King 3\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_LIONK3, GBF_MISC, 0, + MegadriveGetZipName, md_lionkin3RomInfo, md_lionkin3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ma Jiang Qing Ren - Ji Ma Jiang Zhi (Chi) +static struct BurnRomInfo md_majianRomDesc[] = { + { "ma jiang qing ren - ji ma jiang zhi (chi) (unl).bin", 0x100000, 0xddd02ba4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_majian) +STD_ROM_FN(md_majian) + +struct BurnDriver BurnDrvmd_majian = { + "md_majian", NULL, NULL, NULL, "199?", + "Ma Jiang Qing Ren - Ji Ma Jiang Zhi (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_MJLOVER, GBF_MISC, 0, + MegadriveGetZipName, md_majianRomInfo, md_majianRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ma Jiang Qing Ren - Ji Ma Jiang Zhi (Chi, Alt) +static struct BurnRomInfo md_majianaRomDesc[] = { + { "mahjong lover (unl).bin", 0x100000, 0xf6c2cff2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_majiana) +STD_ROM_FN(md_majiana) + +struct BurnDriver BurnDrvmd_majiana = { + "md_majiana", "md_majian", NULL, NULL, "199?", + "Ma Jiang Qing Ren - Ji Ma Jiang Zhi (Chi, Alt)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_MJLOVER, GBF_MISC, 0, + MegadriveGetZipName, md_majianaRomInfo, md_majianaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pokemon Stadium +static struct BurnRomInfo md_pokestadRomDesc[] = { + { "pokemon stadium (unl).bin", 0x200000, 0xfe187c5d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pokestad) +STD_ROM_FN(md_pokestad) + +struct BurnDriver BurnDrvmd_pokestad = { + "md_pokestad", NULL, NULL, NULL, "199?", + "Pokemon Stadium\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_KAIJU, GBF_MISC, 0, + MegadriveGetZipName, md_pokestadRomInfo, md_pokestadRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Rockman X3 +static struct BurnRomInfo md_rockmnx3RomDesc[] = { + { "rockman x3 (unl).bin", 0x200000, 0x3ee639f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rockmnx3) +STD_ROM_FN(md_rockmnx3) + +struct BurnDriver BurnDrvmd_rockmnx3 = { + "md_rockmnx3", NULL, NULL, NULL, "199?", + "Rockman X3\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_ROCKMANX3, GBF_MISC, 0, + MegadriveGetZipName, md_rockmnx3RomInfo, md_rockmnx3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soul Blade +static struct BurnRomInfo md_soulbladRomDesc[] = { + { "soul blade (unl).bin", 0x400000, 0xf26f88d1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soulblad) +STD_ROM_FN(md_soulblad) + +struct BurnDriver BurnDrvmd_soulblad = { + "md_soulblad", NULL, NULL, NULL, "199?", + "Soul Blade\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SOULBLAD, GBF_MISC, 0, + MegadriveGetZipName, md_soulbladRomInfo, md_soulbladRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Soul Blade (Alt) +static struct BurnRomInfo md_soulbladaRomDesc[] = { + { "soul blade (unl)[p].bin", 0x300000, 0xdd1c7a79, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_soulblada) +STD_ROM_FN(md_soulblada) + +struct BurnDriver BurnDrvmd_soulblada = { + "md_soulblada", "md_soulblad", NULL, NULL, "199?", + "Soul Blade (Alt)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SOULBLAD, GBF_MISC, 0, + MegadriveGetZipName, md_soulbladaRomInfo, md_soulbladaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Squirrel King (Chi) +static struct BurnRomInfo md_squirrelRomDesc[] = { + { "squirrel king (chi) (unl).bin", 0x100000, 0xb8261ff5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_squirrel) +STD_ROM_FN(md_squirrel) + +struct BurnDriver BurnDrvmd_squirrel = { + "md_squirrel", NULL, NULL, NULL, "199?", + "Squirrel King (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SQUIRRELK, GBF_MISC, 0, + MegadriveGetZipName, md_squirrelRomInfo, md_squirrelRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super 15 in 1 (Pirate) +static struct BurnRomInfo md_s15in1RomDesc[] = { + { "super 15-in-1 (pirate).bin", 0x200000, 0x6d17dfff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s15in1) +STD_ROM_FN(md_s15in1) + +struct BurnDriver BurnDrvmd_s15in1 = { + "md_s15in1", NULL, NULL, NULL, "199?", + "Super 15 in 1 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP15IN1, GBF_MISC, 0, + MegadriveGetZipName, md_s15in1RomInfo, md_s15in1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super 19 in 1 (Pirate) +static struct BurnRomInfo md_s19in1RomDesc[] = { + { "super 19-in-1 (pirate).bin", 0x400000, 0x0ad2b342, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_s19in1) +STD_ROM_FN(md_s19in1) + +struct BurnDriver BurnDrvmd_s19in1 = { + "md_s19in1", NULL, NULL, NULL, "199?", + "Super 19 in 1 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP19IN1, GBF_MISC, 0, + MegadriveGetZipName, md_s19in1RomInfo, md_s19in1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Bubble Bobble (Chi) +static struct BurnRomInfo md_supbubRomDesc[] = { + { "super bubble bobble (chi) (unl).bin", 0x100000, 0x4820a161, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_supbub) +STD_ROM_FN(md_supbub) + +struct BurnDriver BurnDrvmd_supbub = { + "md_supbub", NULL, NULL, NULL, "199?", + "Super Bubble Bobble (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SBUBBOB, GBF_MISC, 0, + MegadriveGetZipName, md_supbubRomInfo, md_supbubRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Donkey Kong 99 (Protected) +static struct BurnRomInfo md_sdkong99RomDesc[] = { + { "super donkey kong 99 (unl) (protected).bin", 0x300000, 0x43be4dd5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdkong99) +STD_ROM_FN(md_sdkong99) + +struct BurnDriver BurnDrvmd_sdkong99 = { + "md_sdkong99", NULL, NULL, NULL, "199?", + "Super Donkey Kong 99 (Protected)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SDK99, GBF_MISC, 0, + MegadriveGetZipName, md_sdkong99RomInfo, md_sdkong99RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super King Kong 99 +static struct BurnRomInfo md_skkong99RomDesc[] = { + { "super king kong 99 (unl).bin", 0x200000, 0x413dfee2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_skkong99) +STD_ROM_FN(md_skkong99) + +struct BurnDriver BurnDrvmd_skkong99 = { + "md_skkong99", "md_sdkong99", NULL, NULL, "199?", + "Super King Kong 99\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SKINGKONG, GBF_MISC, 0, + MegadriveGetZipName, md_skkong99RomInfo, md_skkong99RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario 2 1998 +static struct BurnRomInfo md_smario2RomDesc[] = { + { "super mario 2 1998 (unl).bin", 0x200000, 0xf7e1b3e1, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smario2) +STD_ROM_FN(md_smario2) + +struct BurnDriver BurnDrvmd_smario2 = { + "md_smario2", NULL, NULL, NULL, "199?", + "Super Mario 2 1998\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SMB2, GBF_MISC, 0, + MegadriveGetZipName, md_smario2RomInfo, md_smario2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario Bros. +static struct BurnRomInfo md_smbRomDesc[] = { + { "super mario bros. (unl).bin", 0x200000, 0x9cfa2bd8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smb) +STD_ROM_FN(md_smb) + +struct BurnDriver BurnDrvmd_smb = { + "md_smb", NULL, NULL, NULL, "199?", + "Super Mario Bros.\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SMB, GBF_MISC, 0, + MegadriveGetZipName, md_smbRomInfo, md_smbRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Battle of Red Cliffs - Romance of the Three Kingdoms +static struct BurnRomInfo md_redcliffRomDesc[] = { + { "the battle of red cliffs - romance of the three kingdoms (unl).bin", 0x200005, 0x44463492, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_redcliff) +STD_ROM_FN(md_redcliff) + +struct BurnDriver BurnDrvmd_redcliff = { + "md_redcliff", NULL, NULL, NULL, "199?", + "The Battle of Red Cliffs - Romance of the Three Kingdoms\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_REDCL_EN, GBF_MISC, 0, + MegadriveGetZipName, md_redcliffRomInfo, md_redcliffRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Battle of Red Cliffs - Romance of the Three Kingdoms (Fixed?) +static struct BurnRomInfo md_redcliffaRomDesc[] = { + { "the battle of red cliffs (unl).bin", 0x200000, 0x63eca090, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_redcliffa) +STD_ROM_FN(md_redcliffa) + +struct BurnDriver BurnDrvmd_redcliffa = { + "md_redcliffa", "md_redcliff", NULL, NULL, "199?", + "The Battle of Red Cliffs - Romance of the Three Kingdoms (Fixed?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_REDCL_EN, GBF_MISC, 0, + MegadriveGetZipName, md_redcliffaRomInfo, md_redcliffaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Top Fighter 2000 MK VIII +static struct BurnRomInfo md_topfightRomDesc[] = { + { "top fighter 2000 mk viii (unl).bin", 0x200000, 0xf75519dc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_topfight) +STD_ROM_FN(md_topfight) + +struct BurnDriver BurnDrvmd_topfight = { + "md_topfight", NULL, NULL, NULL, "199?", + "Top Fighter 2000 MK VIII\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_TOPFIGHTER, GBF_MISC, 0, + MegadriveGetZipName, md_topfightRomInfo, md_topfightRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Top Fighter 2005 +static struct BurnRomInfo md_topf2k5RomDesc[] = { + { "top fighter 2005 (unl).bin", 0x200000, 0x174defe6, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_topf2k5) +STD_ROM_FN(md_topf2k5) + +struct BurnDriver BurnDrvmd_topf2k5 = { + "md_topf2k5", NULL, NULL, NULL, "199?", + "Top Fighter 2005\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_TOPFIGHTER, GBF_MISC, 0, + MegadriveGetZipName, md_topf2k5RomInfo, md_topf2k5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Whac-a-Critter (USA) +static struct BurnRomInfo md_whacacriRomDesc[] = { + { "whac-a-critter (usa) (unl).bin", 0x080000, 0x1bdd02b8, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_whacacri) +STD_ROM_FN(md_whacacri) + +struct BurnDriver BurnDrvmd_whacacri = { + "md_whacacri", NULL, NULL, NULL, "1993", + "Whac-a-Critter (USA)\0", NULL, "Realtec", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC, GBF_MISC, 0, + MegadriveGetZipName, md_whacacriRomInfo, md_whacacriRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Radica: Volume 1 (USA) +static struct BurnRomInfo md_radicav1RomDesc[] = { + { "radicav1.bin", 0x400000, 0x3b4c8438, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_radicav1) +STD_ROM_FN(md_radicav1) + +struct BurnDriver BurnDrvmd_radicav1 = { + "md_radicav1", NULL, NULL, NULL, "2004", + "Radica: Volume 1 (USA)\0", NULL, "Radica Games ~ Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_RADICA, GBF_MISC, 0, + MegadriveGetZipName, md_radicav1RomInfo, md_radicav1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Radica: Street Fighter Pack (Euro) +static struct BurnRomInfo md_radicasfRomDesc[] = { + { "radicasf.bin", 0x400000, 0x868afb44, BRF_PRG | SEGA_MD_ROM_LOAD_NORMAL | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_radicasf) +STD_ROM_FN(md_radicasf) + +struct BurnDriver BurnDrvmd_radicasf = { + "md_radicasf", NULL, NULL, NULL, "2004", + "Radica: Street Fighter Pack (Euro)\0", NULL, "Radica Games ~ Capcom", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_RADICA, GBF_MISC, 0, + MegadriveGetZipName, md_radicasfRomInfo, md_radicasfRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chinese Fighter III (Chi, Alt) +static struct BurnRomInfo md_chinf3aRomDesc[] = { + { "chinese fighter iii (unl, alt).bin", 0x200000, 0x6f98247d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chinf3a) +STD_ROM_FN(md_chinf3a) + +struct BurnDriver BurnDrvmd_chinf3a = { + "md_chinf3a", "md_chinf3", NULL, NULL, "199?", + "Chinese Fighter III (Chi, Alt)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chinf3aRomInfo, md_chinf3aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The King of Fighters '98 (Pirate) +static struct BurnRomInfo md_kof98aRomDesc[] = { + { "king of fighters '98, the (unl) (pirate).bin", 0x200000, 0xc79e1074, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kof98a) +STD_ROM_FN(md_kof98a) + +struct BurnDriver BurnDrvmd_kof98a = { + "md_kof98a", "md_kof98", NULL, NULL, "199?", + "The King of Fighters '98 (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kof98aRomInfo, md_kof98aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shi Zi Wang II - The Lion King II (Pirate) +static struct BurnRomInfo md_lionkin2aRomDesc[] = { + { "shi zi wang ii - the lion king ii, the (chi) (unl) (pirate).bin", 0x200000, 0x721b4981, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionkin2a) +STD_ROM_FN(md_lionkin2a) + +struct BurnDriver BurnDrvmd_lionkin2a = { + "md_lionkin2a", "md_lionkin2", NULL, NULL, "199?", + "Shi Zi Wang II - The Lion King II (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lionkin2aRomInfo, md_lionkin2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Donkey Kong 99 (Unprotected) +static struct BurnRomInfo md_sdkong99aRomDesc[] = { + { "super donkey kong 99 (unl).bin", 0x200000, 0x8e7d9177, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sdkong99a) +STD_ROM_FN(md_sdkong99a) + +struct BurnDriver BurnDrvmd_sdkong99a = { + "md_sdkong99a", "md_sdkong99", NULL, NULL, "199?", + "Super Donkey Kong 99 (Unprotected)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sdkong99aRomInfo, md_sdkong99aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Truco '96 (Arg) +static struct BurnRomInfo md_truco96RomDesc[] = { + { "truco96.bin", 0x100000, 0xcddbecfc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_truco96) +STD_ROM_FN(md_truco96) + +struct BurnDriver BurnDrvmd_truco96 = { + "md_truco96", NULL, NULL, NULL, "1996", + "Truco '96 (Arg)\0", NULL, "Miky", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_truco96RomInfo, md_truco96RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// TC 2000 (Arg) +static struct BurnRomInfo md_tc2000RomDesc[] = { + { "tc2000.bin", 0x100000, 0xcef91bdb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tc2000) +STD_ROM_FN(md_tc2000) + +struct BurnDriver BurnDrvmd_tc2000 = { + "md_tc2000", NULL, NULL, NULL, "199?", + "TC 2000 (Arg)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tc2000RomInfo, md_tc2000RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Unknown Chinese Game 1 (Chi) +static struct BurnRomInfo md_unknownRomDesc[] = { + { "unknown chinese game 1 (chi).bin", 0x200000, 0xdfacb9ff, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_unknown) +STD_ROM_FN(md_unknown) + +struct BurnDriver BurnDrvmd_unknown = { + "md_unknown", NULL, NULL, NULL, "199?", + "Unknown Chinese Game 1 (Chi)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_unknownRomInfo, md_unknownRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Unknown Game 2 (Rockman-related?) +static struct BurnRomInfo md_unknown2RomDesc[] = { + { "xxx3.bin", 0x200000, 0x188da9f0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_unknown2) +STD_ROM_FN(md_unknown2) + +struct BurnDriver BurnDrvmd_unknown2 = { + "md_unknown2", NULL, NULL, NULL, "199?", + "Unknown Game 2 (Rockman-related?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_unknown2RomInfo, md_unknown2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ultimate Soccer (Euro, Prototype) +static struct BurnRomInfo md_ultsoccrpRomDesc[] = { + { "world soccer (prototype).bin", 0x100000, 0x9d451f72, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ultsoccrp) +STD_ROM_FN(md_ultsoccrp) + +struct BurnDriver BurnDrvmd_ultsoccrp = { + "md_ultsoccrp", "md_ultsoccr", NULL, NULL, "199?", + "Ultimate Soccer (Euro, Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ultsoccrpRomInfo, md_ultsoccrpRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Duke Nukem 3D (Pirate) +static struct BurnRomInfo md_dukenk3daRomDesc[] = { + { "duke_nukem_3d.bin", 0x200000, 0x13e93c0d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dukenk3da) +STD_ROM_FN(md_dukenk3da) + +struct BurnDriver BurnDrvmd_dukenk3da = { + "md_dukenk3da", "md_dukenk3d", NULL, NULL, "199?", + "Duke Nukem 3D (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM, GBF_MISC, 0, + MegadriveGetZipName, md_dukenk3daRomInfo, md_dukenk3daRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// K. O. F. 2000 +static struct BurnRomInfo md_kof2kRomDesc[] = { + { "king of fighters 2000 (unl).bin", 0x200000, 0x34cbac5d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kof2k) +STD_ROM_FN(md_kof2k) + +struct BurnDriver BurnDrvmd_kof2k = { + "md_kof2k", NULL, NULL, NULL, "199?", + "K. O. F. 2000\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kof2kRomInfo, md_kof2kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lion King 3 (Alt?) +static struct BurnRomInfo md_lionkin3aRomDesc[] = { + { "lion_king_3.bin", 0x200000, 0x87e86943, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionkin3a) +STD_ROM_FN(md_lionkin3a) + +struct BurnDriver BurnDrvmd_lionkin3a = { + "md_lionkin3a", "md_lionkin3", NULL, NULL, "199?", + "Lion King 3 (Alt?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE | HARDWARE_SEGA_MEGADRIVE_PCB_LIONK3, GBF_MISC, 0, + MegadriveGetZipName, md_lionkin3aRomInfo, md_lionkin3aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Lion King 3 (Alt 2?) +static struct BurnRomInfo md_lionkin3bRomDesc[] = { + { "lion king 3 (unl).bin", 0x200000, 0x8e0555e4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lionkin3b) +STD_ROM_FN(md_lionkin3b) + +struct BurnDriver BurnDrvmd_lionkin3b = { + "md_lionkin3b", "md_lionkin3", NULL, NULL, "199?", + "The Lion King 3 (Alt 2?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lionkin3bRomInfo, md_lionkin3bRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Magic Bubble (Pirate) +static struct BurnRomInfo md_mbubbleRomDesc[] = { + { "magic_bubble.bin", 0x080000, 0xce4a0c46, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mbubble) +STD_ROM_FN(md_mbubble) + +struct BurnDriver BurnDrvmd_mbubble = { + "md_mbubble", NULL, NULL, NULL, "199?", + "Magic Bubble (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mbubbleRomInfo, md_mbubbleRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Magistr 16 (Rus) +static struct BurnRomInfo md_magist16RomDesc[] = { + { "magistr 16.bin", 0x400000, 0x2488e685, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_magist16) +STD_ROM_FN(md_magist16) + +struct BurnDriver BurnDrvmd_magist16 = { + "md_magist16", NULL, NULL, NULL, "199?", + "Magistr 16 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_magist16RomInfo, md_magist16RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sonic Jam 6 (Alt 2) +static struct BurnRomInfo md_sonicjam2RomDesc[] = { + { "sonic_6.bin", 0x200000, 0x87d86501, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sonicjam2) +STD_ROM_FN(md_sonicjam2) + +struct BurnDriver BurnDrvmd_sonicjam2 = { + "md_sonicjam2", "md_sonicjam", NULL, NULL, "199?", + "Sonic Jam 6 (Alt 2)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sonicjam2RomInfo, md_sonicjam2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario 2 (Alt?) +static struct BurnRomInfo md_smario2aRomDesc[] = { + { "super_mario_2.bin", 0x200000, 0x0da6dc4b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smario2a) +STD_ROM_FN(md_smario2a) + +struct BurnDriver BurnDrvmd_smario2a = { + "md_smario2a", "md_smario2", NULL, NULL, "199?", + "Super Mario 2 (Alt?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smario2aRomInfo, md_smario2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tetris (Pirate?) +static struct BurnRomInfo md_tetris1RomDesc[] = { + { "tetris.bin", 0x080000, 0xeb024ab2, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tetris1) +STD_ROM_FN(md_tetris1) + +struct BurnDriver BurnDrvmd_tetris1 = { + "md_tetris1", NULL, NULL, NULL, "199?", + "Tetris (Pirate?)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tetris1RomInfo, md_tetris1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Voina Irak (Pirate) +static struct BurnRomInfo md_virakRomDesc[] = { + { "voina_irak.bin", 0x200000, 0xc7177e93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_virak) +STD_ROM_FN(md_virak) + +struct BurnDriver BurnDrvmd_virak = { + "md_virak", NULL, NULL, NULL, "199?", + "Voina Irak (Pirate)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_virakRomInfo, md_virakRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Dyno Blaze (Early Prototype) +static struct BurnRomInfo md_dynoblazRomDesc[] = { + { "dyno blaze (proto).bin", 0x1711c6, 0xd625e584, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_dynoblaz) +STD_ROM_FN(md_dynoblaz) + +struct BurnDriver BurnDrvmd_dynoblaz = { + "md_dynoblaz", NULL, NULL, NULL, "199?", + "Dyno Blaze (Early Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dynoblazRomInfo, md_dynoblazRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Avatar (Rus) +static struct BurnRomInfo md_avatarRomDesc[] = { + { "avatar.bin", 0x110000, 0xd33e0ada, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_avatar) +STD_ROM_FN(md_avatar) + +struct BurnDriver BurnDrvmd_avatar = { + "md_avatar", "md_jimpow", NULL, NULL, "199?", + "Avatar (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_avatarRomInfo, md_avatarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Chess +static struct BurnRomInfo md_chessRomDesc[] = { + { "chess (unl).bin", 0x080000, 0x47380edd, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_chess) +STD_ROM_FN(md_chess) + +struct BurnDriver BurnDrvmd_chess = { + "md_chess", NULL, NULL, NULL, "1998", + "Chess\0", NULL, "BSComp", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_chessRomInfo, md_chessRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Command & Conquer (Prototype) +static struct BurnRomInfo md_comnconqRomDesc[] = { + { "command & conquer (beta).bin", 0x186286, 0x747fcc62, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_comnconq) +STD_ROM_FN(md_comnconq) + +struct BurnDriver BurnDrvmd_comnconq = { + "md_comnconq", NULL, NULL, NULL, "199?", + "Command & Conquer (Prototype)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_comnconqRomInfo, md_comnconqRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Commandos (Rus) +static struct BurnRomInfo md_commandsRomDesc[] = { + { "commandos.bin", 0x200000, 0x28a88d6f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_commands) +STD_ROM_FN(md_commands) + +struct BurnDriver BurnDrvmd_commands = { + "md_commands", NULL, NULL, NULL, "199?", + "Commandos (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_commandsRomInfo, md_commandsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Counter Strike (Rus) +static struct BurnRomInfo md_cstrikeRomDesc[] = { + { "counter strike.bin", 0x200000, 0x9e7b83ba, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cstrike) +STD_ROM_FN(md_cstrike) + +struct BurnDriver BurnDrvmd_cstrike = { + "md_cstrike", "md_lethalen", NULL, NULL, "199?", + "Counter Strike (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cstrikeRomInfo, md_cstrikeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Crash Bandicoot (Rus) +static struct BurnRomInfo md_crashRomDesc[] = { + { "crash bandicoot.bin", 0x400000, 0xe06bd944, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_crash) +STD_ROM_FN(md_crash) + +struct BurnDriver BurnDrvmd_crash = { + "md_crash", "md_zerokami", NULL, NULL, "199?", + "Crash Bandicoot (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_crashRomInfo, md_crashRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Death Caliber (Rus) +static struct BurnRomInfo md_deathcalRomDesc[] = { + { "death caliber.bin", 0x400000, 0x3cd2c797, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_deathcal) +STD_ROM_FN(md_deathcal) + +struct BurnDriver BurnDrvmd_deathcal = { + "md_deathcal", NULL, NULL, NULL, "199?", + "Death Caliber (Rus)\0", NULL, "Tomsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_deathcalRomInfo, md_deathcalRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Deer Hunter (Rus) +static struct BurnRomInfo md_deerhuntRomDesc[] = { + { "deer hunter.bin", 0x100000, 0xda11978b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_deerhunt) +STD_ROM_FN(md_deerhunt) + +struct BurnDriver BurnDrvmd_deerhunt = { + "md_deerhunt", NULL, NULL, NULL, "199?", + "Deer Hunter (Rus)\0", NULL, "Tomsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_deerhuntRomInfo, md_deerhuntRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Diablo (Rus) +static struct BurnRomInfo md_diabloRomDesc[] = { + { "diablo.bin", 0x100000, 0xbd642da0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_diablo) +STD_ROM_FN(md_diablo) + +struct BurnDriver BurnDrvmd_diablo = { + "md_diablo", "md_fatallab", NULL, NULL, "199?", + "Diablo (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_diabloRomInfo, md_diabloRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Domino +static struct BurnRomInfo md_dominoRomDesc[] = { + { "domino (unl).bin", 0x100000, 0xa64409be, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_domino) +STD_ROM_FN(md_domino) + +struct BurnDriver BurnDrvmd_domino = { + "md_domino", NULL, NULL, NULL, "199?", + "Domino\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_dominoRomInfo, md_dominoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA World Cup 2002 (Rus) +static struct BurnRomInfo md_fifa2k2RomDesc[] = { + { "fifa world cup 2002 (unl).bin", 0x100000, 0x852bff8e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa2k2) +STD_ROM_FN(md_fifa2k2) + +struct BurnDriver BurnDrvmd_fifa2k2 = { + "md_fifa2k2", "md_wcs2", NULL, NULL, "199?", + "FIFA World Cup 2002 (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa2k2RomInfo, md_fifa2k2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA 2003 (Rus) +static struct BurnRomInfo md_fifa2k3RomDesc[] = { + { "fifa 2003 (unl).bin", 0x200000, 0x419bcb02, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa2k3) +STD_ROM_FN(md_fifa2k3) + +struct BurnDriver BurnDrvmd_fifa2k3 = { + "md_fifa2k3", "md_fifa95", NULL, NULL, "199?", + "FIFA 2003 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa2k3RomInfo, md_fifa2k3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// FIFA World Cup - South Africa 2010 (Rus) +static struct BurnRomInfo md_fifa2k10RomDesc[] = { + { "fifa 2010 (unl).bin", 0x400000, 0x851e8411, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fifa2k10) +STD_ROM_FN(md_fifa2k10) + +struct BurnDriver BurnDrvmd_fifa2k10 = { + "md_fifa2k10", "md_fifa", NULL, NULL, "199?", + "FIFA World Cup - South Africa 2010 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fifa2k10RomInfo, md_fifa2k10RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Finding Nemo (Rus) +static struct BurnRomInfo md_nemoRomDesc[] = { + { "finding nemo.bin", 0x0a0000, 0x89b92f66, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nemo) +STD_ROM_FN(md_nemo) + +struct BurnDriver BurnDrvmd_nemo = { + "md_nemo", "md_jpond", NULL, NULL, "199?", + "Finding Nemo (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nemoRomInfo, md_nemoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Forsazh 5 Bystraya ~ Fast and the Furious 5 Quick (Rus) +static struct BurnRomInfo md_fastfur5RomDesc[] = { + { "fast and the furious 5 (unl).bin", 0x10b000, 0x29f4d87a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_fastfur5) +STD_ROM_FN(md_fastfur5) + +struct BurnDriver BurnDrvmd_fastfur5 = { + "md_fastfur5", "md_combatca", NULL, NULL, "199?", + "Forsazh 5 Bystraya ~ Fast and the Furious 5 Quick (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_fastfur5RomInfo, md_fastfur5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Gran Turismo 5 (Rus) +static struct BurnRomInfo md_gt5RomDesc[] = { + { "gran turismo 5 (unl).bin", 0x12a0d0, 0xd4392181, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gt5) +STD_ROM_FN(md_gt5) + +struct BurnDriver BurnDrvmd_gt5 = { + "md_gt5", "md_funcar", NULL, NULL, "199?", + "Gran Turismo 5 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gt5RomInfo, md_gt5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Harry Potter (Rus) +static struct BurnRomInfo md_hpotterRomDesc[] = { + { "harry potter.bin", 0x200000, 0xa184fc76, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hpotter) +STD_ROM_FN(md_hpotter) + +struct BurnDriver BurnDrvmd_hpotter = { + "md_hpotter", NULL, NULL, NULL, "199?", + "Harry Potter (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hpotterRomInfo, md_hpotterRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Harry Potter and the Chamber of Secrets (Rus) +static struct BurnRomInfo md_hpotter2RomDesc[] = { + { "harry potter 2.bin", 0x100000, 0x1684479f, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_hpotter2) +STD_ROM_FN(md_hpotter2) + +struct BurnDriver BurnDrvmd_hpotter2 = { + "md_hpotter2", "md_globglad", NULL, NULL, "199?", + "Harry Potter and the Chamber of Secrets (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_hpotter2RomInfo, md_hpotter2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Hercules 2 +static struct BurnRomInfo md_herc2RomDesc[] = { + { "hercules 2 (unl).bin", 0x200000, 0x292623db, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_herc2) +STD_ROM_FN(md_herc2) + +struct BurnDriver BurnDrvmd_herc2 = { + "md_herc2", NULL, NULL, NULL, "199?", + "Hercules 2\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_herc2RomInfo, md_herc2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ice Age (Rus) +static struct BurnRomInfo md_iceageRomDesc[] = { + { "ice age.bin", 0x400000, 0x3a585408, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_iceage) +STD_ROM_FN(md_iceage) + +struct BurnDriver BurnDrvmd_iceage = { + "md_iceage", "md_awepossm", NULL, NULL, "199?", + "Ice Age (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_iceageRomInfo, md_iceageRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ice Age 3 (Rus) +static struct BurnRomInfo md_iceage3RomDesc[] = { + { "ice age 3 (unl).bin", 0x107120, 0x58fcffb3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_iceage3) +STD_ROM_FN(md_iceage3) + +struct BurnDriver BurnDrvmd_iceage3 = { + "md_iceage3", "md_chuckrck", NULL, NULL, "199?", + "Ice Age 3 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_iceage3RomInfo, md_iceage3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Ice Age 4 (Rus) +static struct BurnRomInfo md_iceage4RomDesc[] = { + { "ice age 4 (unl).bin", 0x10e620, 0x92e86cfc, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_iceage4) +STD_ROM_FN(md_iceage4) + +struct BurnDriver BurnDrvmd_iceage4 = { + "md_iceage4", "md_chuckrck", NULL, NULL, "199?", + "Ice Age 4 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_iceage4RomInfo, md_iceage4RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// The Incredibles (Rus) +static struct BurnRomInfo md_incredibRomDesc[] = { + { "the incredibles (unl).bin", 0x200000, 0x31f7af7c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_incredib) +STD_ROM_FN(md_incredib) + +struct BurnDriver BurnDrvmd_incredib = { + "md_incredib", "md_tick", NULL, NULL, "199?", + "The Incredibles (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_incredibRomInfo, md_incredibRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Iraq War 2003 +static struct BurnRomInfo md_iraqwarRomDesc[] = { + { "iraq war 2003 (unl).bin", 0x100000, 0x49dd6f52, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_iraqwar) +STD_ROM_FN(md_iraqwar) + +struct BurnDriver BurnDrvmd_iraqwar = { + "md_iraqwar", NULL, NULL, NULL, "199?", + "Iraq War 2003\0", NULL, "Tomsoft", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_iraqwarRomInfo, md_iraqwarRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kolobok ~ Pyramid (Rus) +static struct BurnRomInfo md_kolobokRomDesc[] = { + { "kolobok.bin", 0x020000, 0xc4c55bab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kolobok) +STD_ROM_FN(md_kolobok) + +struct BurnDriver BurnDrvmd_kolobok = { + "md_kolobok", NULL, NULL, NULL, "199?", + "Kolobok ~ Pyramid (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kolobokRomInfo, md_kolobokRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kung Fu Panda 2 (Rus) +static struct BurnRomInfo md_kfpanda2RomDesc[] = { + { "kung fu panda 2 (unl).bin", 0x400000, 0xa08c3b25, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kfpanda2) +STD_ROM_FN(md_kfpanda2) + +struct BurnDriver BurnDrvmd_kfpanda2 = { + "md_kfpanda2", "md_brutal", NULL, NULL, "199?", + "Kung Fu Panda 2 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kfpanda2RomInfo, md_kfpanda2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kuzya - V Mire Dinozavrov (Rus) +static struct BurnRomInfo md_kuzyamdRomDesc[] = { + { "agent hugo - in the world of dinosaurs (unl).bin", 0x200000, 0xbd0ebe1c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kuzyamd) +STD_ROM_FN(md_kuzyamd) + +struct BurnDriver BurnDrvmd_kuzyamd = { + "md_kuzyamd", "md_chukrck2", NULL, NULL, "199?", + "Kuzya - V Mire Dinozavrov (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kuzyamdRomInfo, md_kuzyamdRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Kuzya - Ekologiya V Opasnosti (Rus) +static struct BurnRomInfo md_kuzyaeoRomDesc[] = { + { "agent hugo - environment at risk (unl).bin", 0x200000, 0xbe32d65b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_kuzyaeo) +STD_ROM_FN(md_kuzyaeo) + +struct BurnDriver BurnDrvmd_kuzyaeo = { + "md_kuzyaeo", "md_chukrck2", NULL, NULL, "199?", + "Kuzya - Ekologiya V Opasnosti (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_kuzyaeoRomInfo, md_kuzyaeoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lord of the Rings (Rus, Hack of Stormlord) +static struct BurnRomInfo md_lotrRomDesc[] = { + { "lord of the rings (unl).bin", 0x080000, 0xe2a2342a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lotr) +STD_ROM_FN(md_lotr) + +struct BurnDriver BurnDrvmd_lotr = { + "md_lotr", "md_strmlord", NULL, NULL, "199?", + "Lord of the Rings (Rus, Hack of Stormlord)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lotrRomInfo, md_lotrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Lord of the Rings (Rus) +static struct BurnRomInfo md_lotrgsRomDesc[] = { + { "lord of the rings (unl).bin", 0x200000, 0x513ea675, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_lotrgs) +STD_ROM_FN(md_lotrgs) + +struct BurnDriver BurnDrvmd_lotrgs = { + "md_lotrgs", NULL, NULL, NULL, "199?", + "Lord of the Rings (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_lotrgsRomInfo, md_lotrgsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madagascar - Operatsiya Pingvin (Rus) +static struct BurnRomInfo md_madagoppRomDesc[] = { + { "madagascar.bin", 0x100000, 0x6d28ace5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madagopp) +STD_ROM_FN(md_madagopp) + +struct BurnDriver BurnDrvmd_madagopp = { + "md_madagopp", "md_magichat", NULL, NULL, "199?", + "Madagascar - Operatsiya Pingvin (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madagoppRomInfo, md_madagoppRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Madagascar 3 (Rus) +static struct BurnRomInfo md_madagsc3RomDesc[] = { + { "madagascar 3 (unl).bin", 0x100000, 0x0bd6d0a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_madagsc3) +STD_ROM_FN(md_madagsc3) + +struct BurnDriver BurnDrvmd_madagsc3 = { + "md_madagsc3", "md_dinotale", NULL, NULL, "199?", + "Madagascar 3 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_madagsc3RomInfo, md_madagsc3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mafia (Rus) +static struct BurnRomInfo md_mafiaRomDesc[] = { + { "mafia (unl).bin", 0x100000, 0xede60834, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mafia) +STD_ROM_FN(md_mafia) + +struct BurnDriver BurnDrvmd_mafia = { + "md_mafia", "md_dicktr", NULL, NULL, "199?", + "Mafia (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mafiaRomInfo, md_mafiaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Metal Gear Solid (Rus) +static struct BurnRomInfo md_mgsRomDesc[] = { + { "metal gear solid (unl).bin", 0x080000, 0xb38191eb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mgs) +STD_ROM_FN(md_mgs) + +struct BurnDriver BurnDrvmd_mgs = { + "md_mgs", "md_crkdown", NULL, NULL, "199?", + "Metal Gear Solid (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mgsRomInfo, md_mgsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Mighty Morphin Power Rangers - The Fighting Edition (Rus) +static struct BurnRomInfo md_mmprfeRomDesc[] = { + { "mighty morphin power ranger - the fighting edition (unl).bin", 0x200000, 0xb53ff16c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_mmprfe) +STD_ROM_FN(md_mmprfe) + +struct BurnDriver BurnDrvmd_mmprfe = { + "md_mmprfe", NULL, NULL, NULL, "199?", + "Mighty Morphin Power Rangers - The Fighting Edition (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_mmprfeRomInfo, md_mmprfeRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Monsters, Inc. (Rus) +static struct BurnRomInfo md_monstincRomDesc[] = { + { "monsters inc. (unl).bin", 0x080000, 0x3f4657d5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_monstinc) +STD_ROM_FN(md_monstinc) + +struct BurnDriver BurnDrvmd_monstinc = { + "md_monstinc", "md_decapatt", NULL, NULL, "199?", + "Monsters, Inc. (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_monstincRomInfo, md_monstincRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Narnia 3 (Rus) +static struct BurnRomInfo md_narnia3RomDesc[] = { + { "narnia 3 (unl).bin", 0x129dc0, 0xab69bcd3, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_narnia3) +STD_ROM_FN(md_narnia3) + +struct BurnDriver BurnDrvmd_narnia3 = { + "md_narnia3", "md_galahad", NULL, NULL, "199?", + "Narnia 3 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_narnia3RomInfo, md_narnia3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Naruto (Rus) +static struct BurnRomInfo md_narutoRomDesc[] = { + { "naruto (unl).bin", 0x400000, 0xb29b3503, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_naruto) +STD_ROM_FN(md_naruto) + +struct BurnDriver BurnDrvmd_naruto = { + "md_naruto", "md_3ninja", NULL, NULL, "199?", + "Naruto (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_narutoRomInfo, md_narutoRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA 2000 (Rus) +static struct BurnRomInfo md_nba2kRomDesc[] = { + { "nba 2000 (unl).bin", 0x200000, 0x2cef6950, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nba2k) +STD_ROM_FN(md_nba2k) + +struct BurnDriver BurnDrvmd_nba2k = { + "md_nba2k", "md_nbaact95", NULL, NULL, "199?", + "NBA 2000 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nba2kRomInfo, md_nba2kRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NBA 2005 (Rus) +static struct BurnRomInfo md_nba2k5RomDesc[] = { + { "nba 2005 (unl).bin", 0x200000, 0xe8610238, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nba2k5) +STD_ROM_FN(md_nba2k5) + +struct BurnDriver BurnDrvmd_nba2k5 = { + "md_nba2k5", "md_nbaact95", NULL, NULL, "199?", + "NBA 2005 (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nba2k5RomInfo, md_nba2k5RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Need for Speed Undercover (Rus) +static struct BurnRomInfo md_nfsuRomDesc[] = { + { "need for speed undercover (unl).bin", 0x100000, 0xbe1b8e93, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nfsu) +STD_ROM_FN(md_nfsu) + +struct BurnDriver BurnDrvmd_nfsu = { + "md_nfsu", "md_turboout", NULL, NULL, "199?", + "Need for Speed Undercover (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nfsuRomInfo, md_nfsuRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// NHLPA 2003 (Rus) +static struct BurnRomInfo md_nhlpa2k3RomDesc[] = { + { "nhlpa 2003 (unl).bin", 0x200000, 0x4591571b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_nhlpa2k3) +STD_ROM_FN(md_nhlpa2k3) + +struct BurnDriver BurnDrvmd_nhlpa2k3 = { + "md_nhlpa2k3", "md_nhl98", NULL, NULL, "199?", + "NHLPA 2003 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_nhlpa2k3RomInfo, md_nhlpa2k3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pirates of the Caribbean (Rus) +static struct BurnRomInfo md_pircaribRomDesc[] = { + { "pirates of the caribbean (unl).bin", 0x200000, 0x48da0bf4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pircarib) +STD_ROM_FN(md_pircarib) + +struct BurnDriver BurnDrvmd_pircarib = { + "md_pircarib", "md_unchartd", NULL, NULL, "199?", + "Pirates of the Caribbean (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pircaribRomInfo, md_pircaribRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Piraty Karibskogo Morya - Na Strannyh Beregah ~ Pirates of the Caribbean - On Stranger Tides (Rus) +static struct BurnRomInfo md_pircari2RomDesc[] = { + { "pirates of the caribbean - on stranger tides (unl).bin", 0x100000, 0x63c90c7c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_pircari2) +STD_ROM_FN(md_pircari2) + +struct BurnDriver BurnDrvmd_pircari2 = { + "md_pircari2", NULL, NULL, NULL, "199?", + "Piraty Karibskogo Morya - Na Strannyh Beregah ~ Pirates of the Caribbean - On Stranger Tides (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_pircari2RomInfo, md_pircari2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// RHL 2007 (Rus) +static struct BurnRomInfo md_rhl2k7RomDesc[] = { + { "rhl 2000 (unl).bin", 0x0a0000, 0xbb7a978b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_rhl2k7) +STD_ROM_FN(md_rhl2k7) + +struct BurnDriver BurnDrvmd_rhl2k7 = { + "md_rhl2k7", "md_nhlpah", NULL, NULL, "199?", + "RHL 2007 (Rus)\0", NULL, "NewGame", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_rhl2k7RomInfo, md_rhl2k7RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shrek (Rus) +static struct BurnRomInfo md_shrekRomDesc[] = { + { "shrek (unl).bin", 0x100000, 0x561e84b9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shrek) +STD_ROM_FN(md_shrek) + +struct BurnDriver BurnDrvmd_shrek = { + "md_shrek", "md_yogibear", NULL, NULL, "199?", + "Shrek (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shrekRomInfo, md_shrekRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Shrek 2 (Rus) +static struct BurnRomInfo md_shrek2RomDesc[] = { + { "shrek 2 (unl).bin", 0x100000, 0x0ccd3651, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_shrek2) +STD_ROM_FN(md_shrek2) + +struct BurnDriver BurnDrvmd_shrek2 = { + "md_shrek2", "md_ottifa", NULL, NULL, "199?", + "Shrek 2 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_shrek2RomInfo, md_shrek2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sezon Ohoty (Rus) +static struct BurnRomInfo md_openseaRomDesc[] = { + { "open season (unl).bin", 0x100000, 0x06eb2472, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_opensea) +STD_ROM_FN(md_opensea) + +struct BurnDriver BurnDrvmd_opensea = { + "md_opensea", "md_rolo", NULL, NULL, "199?", + "Sezon Ohoty (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_openseaRomInfo, md_openseaRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sezon Ohoty 3 (Rus) +static struct BurnRomInfo md_opensea3RomDesc[] = { + { "hunting season 3 (unl).bin", 0x090d20, 0xb433878c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_opensea3) +STD_ROM_FN(md_opensea3) + +struct BurnDriver BurnDrvmd_opensea3 = { + "md_opensea3", "md_rolo", NULL, NULL, "199?", + "Sezon Ohoty 3 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_opensea3RomInfo, md_opensea3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Snezhnaya Koroleva (Rus) +static struct BurnRomInfo md_snezkoroRomDesc[] = { + { "snow queen (unl).bin", 0x200000, 0xe6c07946, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_snezkoro) +STD_ROM_FN(md_snezkoro) + +struct BurnDriver BurnDrvmd_snezkoro = { + "md_snezkoro", "md_globglad", NULL, NULL, "199?", + "Snezhnaya Koroleva (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_snezkoroRomInfo, md_snezkoroRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Wars (Rus) +static struct BurnRomInfo md_starwarsRomDesc[] = { + { "star wars (unl).bin", 0x100000, 0x94af8d44, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starwars) +STD_ROM_FN(md_starwars) + +struct BurnDriver BurnDrvmd_starwars = { + "md_starwars", "md_elimdown", NULL, NULL, "199?", + "Star Wars (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_starwarsRomInfo, md_starwarsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Star Wars Jedi (Rus) +static struct BurnRomInfo md_starjediRomDesc[] = { + { "star wars jedi (unl).bin", 0x12a0d0, 0x48c5bf60, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_starjedi) +STD_ROM_FN(md_starjedi) + +struct BurnDriver BurnDrvmd_starjedi = { + "md_starjedi", "md_wolfchld", NULL, NULL, "199?", + "Star Wars Jedi (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_starjediRomInfo, md_starjediRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Mario Bros. + Battle City (Rus) +static struct BurnRomInfo md_smbbcRomDesc[] = { + { "mario & battle city (unl).bin", 0x080000, 0x568f7994, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_smbbc) +STD_ROM_FN(md_smbbc) + +struct BurnDriver BurnDrvmd_smbbc = { + "md_smbbc", NULL, NULL, NULL, "199?", + "Super Mario Bros. + Battle City (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_smbbcRomInfo, md_smbbcRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Super Robot Wars (Rus) +static struct BurnRomInfo md_srobowrsRomDesc[] = { + { "super robot wars (unl).bin", 0x080000, 0xcfae2614, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_srobowrs) +STD_ROM_FN(md_srobowrs) + +struct BurnDriver BurnDrvmd_srobowrs = { + "md_srobowrs", "md_trgearth", NULL, NULL, "199?", + "Super Robot Wars (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_srobowrsRomInfo, md_srobowrsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// T3 - The Arcade Game (Rus) +static struct BurnRomInfo md_t3agRomDesc[] = { + { "t3 - the arcade game (unl).bin", 0x100000, 0xd2b5ef77, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_t3ag) +STD_ROM_FN(md_t3ag) + +struct BurnDriver BurnDrvmd_t3ag = { + "md_t3ag", "md_t2ag", NULL, NULL, "199?", + "T3 - The Arcade Game (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_t3agRomInfo, md_t3agRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tachki (Rus) +static struct BurnRomInfo md_carsRomDesc[] = { + { "disney's cars (r).bin", 0x200000, 0x6c5f2530, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cars) +STD_ROM_FN(md_cars) + +struct BurnDriver BurnDrvmd_cars = { + "md_cars", "md_sskid", NULL, NULL, "199?", + "Tachki (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_carsRomInfo, md_carsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tachki 2 (Rus) +static struct BurnRomInfo md_cars2RomDesc[] = { + { "cars 2 (unl).bin", 0x200000, 0x4fd4d967, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_cars2) +STD_ROM_FN(md_cars2) + +struct BurnDriver BurnDrvmd_cars2 = { + "md_cars2", "md_cproam", NULL, NULL, "199?", + "Tachki 2 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_cars2RomInfo, md_cars2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tanki 2011 (Rus) +static struct BurnRomInfo md_tank2011RomDesc[] = { + { "tank 2011 (unl).bin", 0x080000, 0x03739820, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_tank2011) +STD_ROM_FN(md_tank2011) + +struct BurnDriver BurnDrvmd_tank2011 = { + "md_tank2011", NULL, NULL, NULL, "199?", + "Tanki 2011 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_tank2011RomInfo, md_tank2011RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Tiny Toon Adventures 3 (Tw) +static struct BurnRomInfo md_ttoon3RomDesc[] = { + { "tiny toon adventures 3 (unl).bin", 0x100000, 0xd65d83d4, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ttoon3) +STD_ROM_FN(md_ttoon3) + +struct BurnDriver BurnDrvmd_ttoon3 = { + "md_ttoon3", NULL, NULL, NULL, "199?", + "Tiny Toon Adventures 3 (Tw)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ttoon3RomInfo, md_ttoon3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Transformers 3 (Rus) +static struct BurnRomInfo md_transf3RomDesc[] = { + { "transformers 3 (unl).bin", 0x110d20, 0x8632246d, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_transf3) +STD_ROM_FN(md_transf3) + +struct BurnDriver BurnDrvmd_transf3 = { + "md_transf3", "md_mazinwar", NULL, NULL, "199?", + "Transformers 3 (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_transf3RomInfo, md_transf3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Wario Land 3 (Rus) +static struct BurnRomInfo md_wario3RomDesc[] = { + { "wario land 3 (unl).bin", 0x100000, 0xcd5c93a5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_wario3) +STD_ROM_FN(md_wario3) + +struct BurnDriver BurnDrvmd_wario3 = { + "md_wario3", "md_puggsy", NULL, NULL, "199?", + "Wario Land 3 (Rus)\0", NULL, "Glorysun", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_wario3RomInfo, md_wario3RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Winx 3D Volshebnoe Priklyuchenie (Rus) +static struct BurnRomInfo md_winx3dRomDesc[] = { + { "winx 3d (unl).bin", 0x12a3d0, 0x933cecc9, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_winx3d) +STD_ROM_FN(md_winx3d) + +struct BurnDriver BurnDrvmd_winx3d = { + "md_winx3d", "md_valis3", NULL, NULL, "199?", + "Winx 3D Volshebnoe Priklyuchenie (Rus)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_winx3dRomInfo, md_winx3dRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Action Replay (Euro) +static struct BurnRomInfo md_arRomDesc[] = { + { "action replay (euro).bin", 0x008000, 0x95ff7c3e, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ar) +STD_ROM_FN(md_ar) + +struct BurnDriver BurnDrvmd_ar = { + "md_ar", NULL, NULL, NULL, "199?", + "Action Replay (Euro)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arRomInfo, md_arRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Game Genie (Euro, USA, Rev. A) +static struct BurnRomInfo md_ggenieRomDesc[] = { + { "sgr001-a+sgr002-a.bin", 0x008000, 0x14dbce4a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ggenie) +STD_ROM_FN(md_ggenie) + +struct BurnDriver BurnDrvmd_ggenie = { + "md_ggenie", NULL, NULL, NULL, "199?", + "Game Genie (Euro, USA, Rev. A)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ggenieRomInfo, md_ggenieRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Game Genie (Euro, USA) +static struct BurnRomInfo md_ggenie1RomDesc[] = { + { "sgr001+sgr002.bin", 0x008000, 0x5f293e4c, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_ggenie1) +STD_ROM_FN(md_ggenie1) + +struct BurnDriver BurnDrvmd_ggenie1 = { + "md_ggenie1", "md_ggenie", NULL, NULL, "199?", + "Game Genie (Euro, USA)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_ggenie1RomInfo, md_ggenie1RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Action Replay (Euro) +static struct BurnRomInfo md_parRomDesc[] = { + { "pro action replay (euro).bin", 0x020000, 0x17255224, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_par) +STD_ROM_FN(md_par) + +struct BurnDriver BurnDrvmd_par = { + "md_par", NULL, NULL, NULL, "199?", + "Pro Action Replay (Euro)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_parRomInfo, md_parRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Action Replay 2 (Euro) +static struct BurnRomInfo md_par2RomDesc[] = { + { "pro action replay 2 (euro).bin", 0x010000, 0xa73abd27, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_par2) +STD_ROM_FN(md_par2) + +struct BurnDriver BurnDrvmd_par2 = { + "md_par2", NULL, NULL, NULL, "199?", + "Pro Action Replay 2 (Euro)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_par2RomInfo, md_par2RomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Pro Action Replay 2 (Euro, Alt) +static struct BurnRomInfo md_par2aRomDesc[] = { + { "pro action replay 2 (euro) (alt).bin", 0x010000, 0xe6669a61, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_par2a) +STD_ROM_FN(md_par2a) + +struct BurnDriver BurnDrvmd_par2a = { + "md_par2a", "md_par2", NULL, NULL, "199?", + "Pro Action Replay 2 (Euro, Alt)\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_par2aRomInfo, md_par2aRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Racing (Euro) +static struct BurnRomInfo md_vrRomDesc[] = { + { "mpr-16420.bin", 0x200000, 0x9624d4ef, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vr) +STD_ROM_FN(md_vr) + +struct BurnDriverD BurnDrvmd_vr = { + "md_vr", NULL, NULL, NULL, "1994", + "Virtua Racing (Euro)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vrRomInfo, md_vrRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Racing (Jpn) +static struct BurnRomInfo md_vrjRomDesc[] = { + { "mpr-16389.bin", 0x200000, 0x53a293b5, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vrj) +STD_ROM_FN(md_vrj) + +struct BurnDriverD BurnDrvmd_vrj = { + "md_vrj", "md_vr", NULL, NULL, "1994", + "Virtua Racing (Jpn)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vrjRomInfo, md_vrjRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Virtua Racing (USA) +static struct BurnRomInfo md_vruRomDesc[] = { + { "virtua racing (usa).bin", 0x200000, 0x7e1a324a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_vru) +STD_ROM_FN(md_vru) + +struct BurnDriverD BurnDrvmd_vru = { + "md_vru", "md_vr", NULL, NULL, "1994", + "Virtua Racing (USA)\0", NULL, "Sega", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_vruRomInfo, md_vruRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// GEMS v2.8 +static struct BurnRomInfo md_gemsRomDesc[] = { + { "gems.bin", 0x040000, 0x98ebb058, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_gems) +STD_ROM_FN(md_gems) + +struct BurnDriver BurnDrvmd_gems = { + "md_gems", NULL, NULL, NULL, "199?", + "GEMS v2.8\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_gemsRomInfo, md_gemsRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Sound Tool v2.2? +static struct BurnRomInfo md_sndtoolRomDesc[] = { + { "sndtool.bin", 0x040000, 0xee41b452, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_sndtool) +STD_ROM_FN(md_sndtool) + +struct BurnDriver BurnDrvmd_sndtool = { + "md_sndtool", NULL, NULL, NULL, "1991", + "Sound Tool v2.2?\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_sndtoolRomInfo, md_sndtoolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + +// Art Tool +static struct BurnRomInfo md_arttoolRomDesc[] = { + { "arttool.bin", 0x040000, 0x5353f532, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 }, +}; + +STD_ROM_PICK(md_arttool) +STD_ROM_FN(md_arttool) + +struct BurnDriver BurnDrvmd_arttool = { + "md_arttool", NULL, NULL, NULL, "199?", + "Art Tool\0", NULL, "", "Sega Megadrive", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_SEGA_MEGADRIVE, GBF_MISC, 0, + MegadriveGetZipName, md_arttoolRomInfo, md_arttoolRomName, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo, + MegadriveInit, MegadriveExit, MegadriveFrame, NULL, MegadriveScan, + &bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3 +}; + diff --git a/src/burn/drivers/megadrive/megadrive.cpp b/src/burn/drivers/megadrive/megadrive.cpp new file mode 100644 index 00000000..e5e00bb5 --- /dev/null +++ b/src/burn/drivers/megadrive/megadrive.cpp @@ -0,0 +1,4225 @@ +/******************************************************************************** + SEGA Genesis / Mega Drive Driver for FBA + ******************************************************************************** + This is part of Pico Library v0936 + + (c) Copyright 2004 Dave, All rights reserved. + (c) Copyright 2006 notaz, All rights reserved. + Free for non-commercial use. + + For commercial use, separate licencing terms must be obtained. + ******************************************************************************** + + PicoOpt bits LSb->MSb: + enable_ym2612&dac, enable_sn76496, enable_z80, stereo_sound, + alt_renderer, 6button_gamepad, accurate_timing, accurate_sprites, + draw_no_32col_border, external_ym2612 + + ******************************************************************************** + Port by OopsWare + ********************************************************************************/ + +#include "burnint.h" +#include "burn_ym2612.h" +#include "sn76496.h" +#include "megadrive.h" +#include "bitswap.h" +#include "sekdebug.h" + +#define OSC_NTSC 53693175 +#define OSC_PAL 53203424 + +#define MAX_CARTRIDGE_SIZE 0xc00000 +#define MAX_SRAM_SIZE 0x010000 + +static INT32 cycles_68k, cycles_z80; + +typedef void (*MegadriveCb)(); +static MegadriveCb MegadriveCallback; + +struct PicoVideo { + UINT8 reg[0x20]; + UINT32 command; // 32-bit Command + UINT8 pending; // 1 if waiting for second half of 32-bit command + UINT8 type; // Command type (v/c/vsram read/write) + UINT16 addr; // Read/Write address + INT32 status; // Status bits + UINT8 pending_ints; // pending interrupts: ??VH???? + UINT8 pad[0x13]; // +}; + +struct PicoMisc { + UINT32 Z80Run; + UINT32 Bank68k; + UINT8 Rotate; + +// UINT8 Pad[3]; + +// UINT32 SRamReg; + UINT32 SRamStart; + UINT32 SRamEnd; + UINT32 SRamDetected; + UINT32 SRamActive; + UINT32 SRamHandlersInstalled; + UINT32 SRamReadOnly; + UINT32 SRamHasSerialEEPROM; + + UINT8 I2CMem; + UINT8 I2CClk; + + UINT16 JCartIOData[2]; + + UINT8 L3AltPDat; + UINT8 L3AltPCmd; + + UINT16 SquirrelkingExtra; + + UINT16 Lionk2ProtData; + UINT16 Lionk2ProtData2; + + UINT32 RealtecBankAddr; + UINT32 RealtecBankSize; +}; + +struct TileStrip +{ + INT32 nametab; // Position in VRAM of name table (for this tile line) + INT32 line; // Line number in pixels 0x000-0x3ff within the virtual tilemap + INT32 hscroll; // Horizontal scroll value in pixels for the line + INT32 xmask; // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap + INT32 *hc; // cache for high tile codes and their positions + INT32 cells; // cells (tiles) to draw (32 col mode doesn't need to update whole 320) +}; + +struct MegadriveJoyPad { + UINT16 pad[4]; + UINT8 padTHPhase[4]; + UINT8 padDelay[4]; +}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *RomMain; +static UINT8 *OriginalRom; + +static UINT8 *Ram68K; +static UINT8 *RamZ80; + +static UINT8 *SRam; +static UINT8 *RamIO; + +static UINT16 *RamPal; +static UINT16 *RamVid; +static UINT16 *RamSVid; +static struct PicoVideo *RamVReg; +static struct PicoMisc *RamMisc; +static struct MegadriveJoyPad *JoyPad; + +UINT16 *MegadriveCurPal; + +static UINT16 *MegadriveBackupRam; + +static UINT8 *HighCol; +static UINT8 *HighColFull; + +static INT32 *HighCacheA; +static INT32 *HighCacheB; +static INT32 *HighCacheS; +static INT32 *HighPreSpr; +static INT8 *HighSprZ; + +UINT8 MegadriveReset = 0; +UINT8 bMegadriveRecalcPalette = 0; + +UINT8 MegadriveJoy1[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 MegadriveJoy2[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 MegadriveJoy3[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 MegadriveJoy4[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 MegadriveDIP[2] = {0, 0}; + +static UINT32 RomNum = 0; +static UINT32 RomSize = 0; +static UINT32 SRamSize = 0; + +static INT32 SpriteBlocks; + +static INT32 Scanline = 0; + +static INT32 Z80HasBus = 0; +static INT32 MegadriveZ80Reset = 0; +static INT32 RomNoByteswap; + +static UINT8 Hardware; +static UINT8 DrvSECAM = 0; // NTSC + +void MegadriveCheckHardware() +{ + Hardware = MegadriveDIP[0] & 0xe0; + if (MegadriveDIP[0] & 0x01) { + // Auto Detect Region and SECAM + UINT32 support = 0; + for (INT32 i = 0; i < 4; i++) { + UINT32 v = RomMain[0x1f0 + i]; + if (v <= 0x20) continue; + + switch (v) { + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: { + support |= v - 0x30; + break; + } + + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x46: { + support |= v - 0x41; + break; + } + + case 0x45: { + // Japan + support |= 0x08; + break; + } + + case 0x4a: { + // Europe + support |= 0x01; + break; + } + + case 0x55: { + // USA + support |= 0x04; + break; + } + + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: { + support |= v - 0x61; + break; + } + } + } + + bprintf(PRINT_IMPORTANT, _T("Autodetecting Cartridge (Hardware Code: %02x%02x%02x%02x):\n"), RomMain[0x1f0], RomMain[0x1f1], RomMain[0x1f2], RomMain[0x1f3]); + Hardware = 0x80; + + if (support & 0x02) { + Hardware = 0x40; // Japan PAL + bprintf(PRINT_IMPORTANT, _T("Japan PAL supported ???\n")); + } + + if (support & 0x01) { + Hardware = 0x00; // Japan NTSC + bprintf(PRINT_IMPORTANT, _T("Japan NTSC supported\n")); + } + + if (support & 0x08) { + Hardware = 0xc0; // Europe PAL + bprintf(PRINT_IMPORTANT, _T("Europe PAL supported\n")); + } + + if (support & 0x04) { + Hardware = 0x80; // USA NTSC + bprintf(PRINT_IMPORTANT, _T("USA NTSC supported\n")); + } + + if ((Hardware & 0xc0) == 0xc0) { + bprintf(PRINT_IMPORTANT, _T("Emulating Europe PAL Machine\n")); + } else { + if ((Hardware & 0x80) == 0x80) { + bprintf(PRINT_IMPORTANT, _T("Emulating USA NTSC Machine\n")); + } else { + if ((Hardware & 0x40) == 0x40) { + bprintf(PRINT_IMPORTANT, _T("Emulating Japan PAL Machine ???\n")); + } else { + if ((Hardware & 0x00) == 0x00) { + bprintf(PRINT_IMPORTANT, _T("Emulating Japan NTSC Machine\n")); + } + } + } + } + + // CD-ROM + Hardware |= MegadriveDIP[0] & 0x20; + } + + if ((Hardware & 0x20) != 0x20) bprintf(PRINT_IMPORTANT, _T("Emulating Mega-CD Add-on\n")); +} + +//----------------------------------------------------------------- + +inline static void CalcCol(INT32 index, UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x000f) << 4; // Red + g = (nColour & 0x00f0) << 0; // Green + b = (nColour & 0x0f00) >> 4; // Blue + + r |= r >> 4; + g |= g >> 4; + b |= b >> 4; + + RamPal[index] = nColour; + + // Normal Color + MegadriveCurPal[index + 0x00] = BurnHighCol(r, g, b, 0); + + // Shadow Color + MegadriveCurPal[index + 0x40] = MegadriveCurPal[index + 0xc0] = BurnHighCol(r>>1, g>>1, b>>1, 0); + + // Highlight Color + r += 0x80; if (r > 0xFF) r = 0xFF; + g += 0x80; if (g > 0xFF) g = 0xFF; + b += 0x80; if (b > 0xFF) b = 0xFF; + MegadriveCurPal[index + 0x80] = BurnHighCol(r, g, b, 0); +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + RomMain = Next; Next += MAX_CARTRIDGE_SIZE + sizeof(long); // 68000 ROM, Max enough + + RamStart = Next; + + Ram68K = Next; Next += 0x010000; + RamZ80 = Next; Next += 0x002000; + SRam = Next; Next += MAX_SRAM_SIZE; // SRam + RamIO = Next; Next += 0x000010; // I/O + + RamPal = (UINT16 *) Next; Next += 0x000040 * sizeof(UINT16); + RamSVid = (UINT16 *) Next; Next += 0x000080; // VSRam + RamVid = (UINT16 *) Next; Next += 0x010000; // Video Ram + + RamVReg = (struct PicoVideo *)Next; Next += sizeof(struct PicoVideo); + RamMisc = (struct PicoMisc *)Next; Next += sizeof(struct PicoMisc); + + RamEnd = Next; + + MegadriveCurPal = (UINT16 *) Next; Next += 0x000040 * sizeof(UINT16) * 4; + + HighColFull = Next; Next += (8 + 320 + 8) * 240; + + HighCacheA = (INT32 *) Next; Next += (41+1) * sizeof(INT32); // caches for high layers + HighCacheB = (INT32 *) Next; Next += (41+1) * sizeof(INT32); + HighCacheS = (INT32 *) Next; Next += (80+1) * sizeof(INT32); // and sprites + HighPreSpr = (INT32 *) Next; Next += (80*2+1) * sizeof(INT32); // slightly preprocessed sprites + HighSprZ = (INT8*) Next; Next += (320+8+8); // Z-buffer for accurate sprites and shadow/hilight mode + + JoyPad = (struct MegadriveJoyPad *) Next; Next += sizeof(struct MegadriveJoyPad); + + MemEnd = Next; + return 0; +} + +UINT16 __fastcall MegadriveReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xa11100: { + UINT16 retVal = rand() & 0xffff; + if (Z80HasBus || MegadriveZ80Reset) { + retVal |= 0x100; + } else { + retVal &= 0xfeff; + } + return retVal; + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + } + return 0; +} + +UINT8 __fastcall MegadriveReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xa04000: + case 0xa04001: + case 0xa04002: + case 0xa04003: { + if (!Z80HasBus && !MegadriveZ80Reset) { + return BurnYM2612Read(0, 0); + } else { + return 0; + } + } + + case 0xa11100: { + UINT8 retVal = rand() & 0xff; + if (Z80HasBus || MegadriveZ80Reset) { + retVal |= 0x01; + } else { + retVal &= 0xfe; + } + return retVal; + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + } + return 0; +} + +void __fastcall MegadriveWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if(sekAddress >= 0xA13004 && sekAddress < 0xA13040) { + // dumb 12-in-1 or 4-in-1 banking support + sekAddress &= 0x3f; + sekAddress <<= 16; + INT32 len = RomSize - sekAddress; + if (len <= 0) return; // invalid/missing bank + if (len > 0x200000) len = 0x200000; // 2 megs + // code which does this is in RAM so this is safe. + memcpy(RomMain, RomMain + sekAddress, len); + return; + } + + switch (sekAddress) { + case 0xa04000: { + if (!Z80HasBus && !MegadriveZ80Reset) BurnYM2612Write(0, 0, byteValue); + return; + } + + case 0xa04001: { + if (!Z80HasBus && !MegadriveZ80Reset) BurnYM2612Write(0, 1, byteValue); + return; + } + + case 0xa04002: { + if (!Z80HasBus && !MegadriveZ80Reset) BurnYM2612Write(0, 2, byteValue); + return; + } + + case 0xa04003: { + if (!Z80HasBus && !MegadriveZ80Reset) BurnYM2612Write(0, 3, byteValue); + return; + } + + case 0xA11100: { + if (byteValue & 1) { + RamMisc->Z80Run = 0; + Z80HasBus = 0; + } else { + RamMisc->Z80Run = 1; + Z80HasBus = 1; + } + return; + } + + case 0xA11200: { + if (!(byteValue & 1)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2612Reset(); + MegadriveZ80Reset = 1; + } else { + MegadriveZ80Reset = 0; + } + return; + } + +// case 0xA130F1: { + // sram access register +// RamMisc->SRamReg = byteValue & 0x03; +// return; +// } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } + } +} + +void __fastcall MegadriveWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0xa11100: { + if (wordValue & 0x100) { + RamMisc->Z80Run = 0; + Z80HasBus = 0; + } else { + RamMisc->Z80Run = 1; + Z80HasBus = 1; + } + return; + } + + case 0xa11200: { + if (!(wordValue & 0x100)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2612Reset(); + MegadriveZ80Reset = 1; + } else { + MegadriveZ80Reset = 0; + } + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } + } +} + +//--------------------------------------------------------------- +// Megadrive Video Port Read Write +//--------------------------------------------------------------- + +static INT32 rendstatus = 0; + +// calculate the number of cycles 68k->VDP dma operation would take +static INT32 DmaSlowBurn(INT32 len) +{ + // test: Legend of Galahad, Time Killers + INT32 burn,maxlen,line=Scanline; + //if(line == -1) line=vcounts[SekCyclesDone()>>8]; + maxlen = (224-line) * 18; + if(len <= maxlen) + burn = len*(((cycles_68k<<8)/18))>>8; + else { + burn = maxlen*(((cycles_68k<<8)/18))>>8; + burn += (len-maxlen)*(((cycles_68k<<8)/180))>>8; + } + return burn; +} + +static INT32 GetDmaLength() +{ + INT32 len = 0; + // 16-bit words to transfer: + len = RamVReg->reg[0x13]; + len |= RamVReg->reg[0x14]<<8; + // Charles MacDonald: + if(!len) len = 0xffff; + return len; +} + +static void DmaSlow(INT32 len) +{ + UINT16 *pd=0, *pdend, *r; + UINT32 a = RamVReg->addr, a2, d; + UINT8 inc = RamVReg->reg[0xf]; + UINT32 source, burn; + + source = RamVReg->reg[0x15] << 1; + source |= RamVReg->reg[0x16] << 9; + source |= RamVReg->reg[0x17] << 17; + + //dprintf("DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i|%i]", Pico.video.type, source, a, len, inc, + // (Pico.video.status&8)||!(Pico.video.reg[1]&0x40), Pico.m.scanline, SekCyclesDone()); + + if ((source & 0xe00000) == 0xe00000) { // RAM + pd = (UINT16 *)(Ram68K + (source & 0xfffe)); + pdend = (UINT16 *)(Ram68K + 0x10000); + } else if( source < RomSize) { // ROM + pd = (UINT16 *)(RomMain + (source & ~1)); + pdend = (UINT16 *)(RomMain + RomSize); + } else return; // Invalid source address + + // CPU is stopped during DMA, so we burn some cycles to compensate that + if((RamVReg->status & 8) || !(RamVReg->reg[1] & 0x40)) { // vblank? + burn = (len*(((cycles_68k<<8)/167))>>8); // very approximate + if(!(RamVReg->status & 8)) burn += burn>>1; // a hack for Legend of Galahad + } else burn = DmaSlowBurn(len); + + //SekCyclesBurn(burn); + SekRunAdjust( 0 - burn ); + + if(!(RamVReg->status & 8)) + SekRunEnd(); + //dprintf("DmaSlow burn: %i @ %06x", burn, SekPc); + + switch ( RamVReg->type ) { + case 1: // vram + r = RamVid; + for(; len; len--) { + d = *pd++; + if(a&1) d=(d<<8)|(d>>8); + r[a>>1] = (UINT16)d; // will drop the upper bits + // AutoIncrement + a = (UINT16)(a+inc); + // didn't src overlap? + if(pd >= pdend) pd -= 0x8000; // should be good for RAM, bad for ROM + } + rendstatus |= 0x10; + break; + + case 3: // cram + //dprintf("DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i|%i]", Pico.video.type, source, a, len, inc, + // (Pico.video.status&8)||!(Pico.video.reg[1]&0x40), Pico.m.scanline, SekCyclesDone()); + for(a2 = a&0x7f; len; len--) { + CalcCol( a2>>1, *pd ); + pd++; + // AutoIncrement + a2+=inc; + // didn't src overlap? + if(pd >= pdend) pd-=0x8000; + // good dest? + if(a2 >= 0x80) break; // Todds Adventures in Slime World / Andre Agassi tennis + } + a = (a&0xff00) | a2; + break; + + case 5: // vsram[a&0x003f]=d; + r = RamSVid; + for(a2=a&0x7f; len; len--) { + r[a2>>1] = (UINT16)*pd++; + // AutoIncrement + a2+=inc; + // didn't src overlap? + if(pd >= pdend) pd-=0x8000; + // good dest? + if(a2 >= 0x80) break; + } + a=(a&0xff00)|a2; + break; + } + // remember addr + RamVReg->addr = (UINT16)a; +} + +static void DmaCopy(INT32 len) +{ + UINT8 * vr = (UINT8 *) RamVid; + UINT8 * vrs; + //UINT16 a = Pico.video.addr; + //UINT8 inc = RamVReg->reg[0xf]; + INT32 source; + + //dprintf("DmaCopy len %i [%i|%i]", len, Pico.m.scanline, SekCyclesDone()); + + source = RamVReg->reg[0x15]; + source |= RamVReg->reg[0x16]<<8; + vrs = vr + source; + + if (source+len > 0x10000) + len = 0x10000 - source; // clip?? + + for(;len;len--) { + vr[RamVReg->addr] = *vrs++; + // AutoIncrement + //a = (u16)(a + inc); + RamVReg->addr += RamVReg->reg[0xf]; + } + rendstatus |= 0x10; +} + +static void DmaFill(INT32 data) +{ + INT32 len = GetDmaLength(); + UINT8 *vr = (UINT8 *) RamVid; + UINT8 high = (UINT8) (data >> 8); + UINT16 a = RamVReg->addr; + UINT8 inc = RamVReg->reg[0xf]; + + //dprintf("DmaFill len %i inc %i [%i|%i]", len, inc, Pico.m.scanline, SekCyclesDone()); + + // from Charles MacDonald's genvdp.txt: + // Write lower byte to address specified + vr[a] = (UINT8) data; + a = (UINT16)(a+inc); + + if(!inc) len=1; + + for(;len;len--) { + // Write upper byte to adjacent address + // (here we are byteswapped, so address is already 'adjacent') + vr[a] = high; + // Increment address register + a = (UINT16)(a+inc); + } + // remember addr + RamVReg->addr = a; + // update length + RamVReg->reg[0x13] = RamVReg->reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze) + + rendstatus |= 0x10; +} + +static void CommandChange() +{ + //struct PicoVideo *pvid=&Pico.video; + UINT32 cmd = RamVReg->command; + UINT32 addr = 0; + + // Get type of transfer 0xc0000030 (v/c/vsram read/write) + RamVReg->type = (UINT8)(((cmd >> 2) & 0xc) | (cmd >> 30)); + + // Get address 0x3fff0003 + addr = (cmd >> 16) & 0x3fff; + addr |= (cmd << 14) & 0xc000; + RamVReg->addr = (UINT16)addr; + //dprintf("addr set: %04x", addr); + + // Check for dma: + if (cmd & 0x80) { + // Command DMA + if ((RamVReg->reg[1] & 0x10) == 0) return; // DMA not enabled + INT32 len = GetDmaLength(); + switch ( RamVReg->reg[0x17]>>6 ) { + case 0x00: + case 0x01: + DmaSlow(len); // 68000 to VDP + break; + case 0x03: + DmaCopy(len); // VRAM Copy + break; + case 0x02: // DMA Fill Flag ??? + default: + ;//bprintf(PRINT_NORMAL, _T("Video Command DMA Unknown %02x len %d\n"), RamVReg->reg[0x17]>>6, len); + } + } +} + +// H-counter table for hvcounter reads in 40col mode +// based on Gens code +const UINT8 hcounts_40[] = { + 0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, + 0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x13,0x14, + 0x14,0x15,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b, + 0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21, + 0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28, + 0x28,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2f, + 0x2f,0x30,0x30,0x30,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x34,0x34,0x35,0x35,0x35, + 0x36,0x36,0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3c,0x3c, + 0x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43, + 0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x4a, + 0x4a,0x4a,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50, + 0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57, + 0x57,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5e, + 0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64, + 0x65,0x65,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b, + 0x6c,0x6c,0x6c,0x6d,0x6d,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x71,0x71,0x71,0x72, + 0x72,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x79, + 0x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f, + 0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x84,0x84,0x84,0x85,0x85,0x86,0x86, + 0x86,0x87,0x87,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d, + 0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x92,0x93,0x93,0x94, + 0x94,0x94,0x95,0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,0x99,0x99,0x99,0x9a,0x9a, + 0x9b,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1, + 0xa1,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,0xa8, + 0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,0xab,0xab,0xab,0xac,0xac,0xad,0xad,0xae,0xae,0xae, + 0xaf,0xaf,0xb0,0xb0,0xe4,0xe4,0xe4,0xe5,0xe5,0xe6,0xe6,0xe6,0xe7,0xe7,0xe8,0xe8, + 0xe9,0xe9,0xe9,0xea,0xea,0xeb,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xee,0xef, + 0xef,0xf0,0xf0,0xf1,0xf1,0xf1,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf6, + 0xf6,0xf6,0xf7,0xf7,0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc, + 0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, + 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a, + 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10, +}; + +// H-counter table for hvcounter reads in 32col mode +const UINT8 hcounts_32[] = { + 0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a, + 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0f,0x10, + 0x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15, + 0x15,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b, + 0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20, + 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x26,0x26, + 0x26,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b, + 0x2c,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x31,0x31, + 0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37, + 0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c, + 0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,0x41,0x41,0x41,0x42, + 0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47, + 0x48,0x48,0x48,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d, + 0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,0x51,0x51,0x51,0x52,0x52,0x52, + 0x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58, + 0x58,0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e, + 0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63, + 0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69, + 0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e, + 0x6f,0x6f,0x6f,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x74,0x74, + 0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x79, + 0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f, + 0x7f,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x83,0x84,0x84,0x84,0x85, + 0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a, + 0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x90, + 0x90,0x90,0x91,0x91,0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,0xea,0xea,0xeb,0xeb,0xeb, + 0xec,0xec,0xec,0xed,0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf0,0xf1,0xf1, + 0xf1,0xf2,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6, + 0xf7,0xf7,0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc, + 0xfc,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x01,0x02, + 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07, + 0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d, +}; + +UINT16 __fastcall MegadriveVideoReadWord(UINT32 sekAddress) +{ + //bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %x\n"), sekAddress); + //return MegadriveVDPRead((sekAddress - 0xc00000) >> 1); + + if (sekAddress > 0xC0001F) + bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %x\n"), sekAddress); + + UINT16 res = 0; + + switch (sekAddress & 0x1c) { + case 0x00: // data + switch (RamVReg->type) { + case 0: res = RamVid [(RamVReg->addr >> 1) & 0x7fff]; break; + case 4: res = RamSVid[(RamVReg->addr >> 1) & 0x003f]; break; + case 8: res = RamPal [(RamVReg->addr >> 1) & 0x003f]; break; + } + RamVReg->addr += RamVReg->reg[0xf]; + break; + + case 0x04: // command + res = RamVReg->status; + //if(PicoOpt&0x10) d|=0x0020; // sprite collision (Shadow of the Beast) + if(RamMisc->Rotate++&8) res |= 0x0100; else res |= 0x0200; // Toggle fifo full empty (who uses that stuff?) + if(!(RamVReg->reg[1] & 0x40)) res |= 0x0008; // set V-Blank if display is disabled + if(m68k_ICount < 84+4) res |= 0x0004; // H-Blank (Sonic3 vs) + RamVReg->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald) + break; + + case 0x08: // H-counter info + { + UINT32 hc = 50; + + INT32 lineCycles = (cycles_68k - m68k_ICount) & 0x1ff; + res = Scanline; // V-Counter + + if(RamVReg->reg[12]&1) + hc = hcounts_40[lineCycles]; + else hc = hcounts_32[lineCycles]; + + if(lineCycles > cycles_68k-12) res++; // Wheel of Fortune + + if( Hardware & 0x40 ) { + if(res >= 0x103) res -= 56; // based on Gens + } else { + if(res >= 0x0EB) res -= 6; + } + + if((RamVReg->reg[12]&6) == 6) { + // interlace mode 2 (Combat Cars (UE) [!]) + res <<= 1; + if (res & 0xf00) res |= 1; + } + + //dprintf("hv: %02x %02x (%i) @ %06x", hc, d, SekCyclesDone(), SekPc); + res &= 0xff; + res <<= 8; + res |= hc; + } + break; + + default: + bprintf(PRINT_NORMAL, _T("Video Attempt to read word value of location %x, %x\n"), sekAddress, sekAddress & 0x1c); + break; + } + + return res; +} + +UINT8 __fastcall MegadriveVideoReadByte(UINT32 sekAddress) +{ + //bprintf(PRINT_NORMAL, _T("Video Attempt to read byte value of location %x\n"), sekAddress); + UINT16 res = MegadriveVideoReadWord(sekAddress & ~1); + if ((sekAddress&1)==0) res >>= 8; + return res & 0xff; +} + +void __fastcall MegadriveVideoWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress > 0xC0001F) + bprintf(PRINT_NORMAL, _T("Video Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + switch (sekAddress & 0x1c) { + case 0x00: // data + if (RamVReg->pending) + CommandChange(); + RamVReg->pending = 0; + if ((RamVReg->command & 0x80) && (RamVReg->reg[1]&0x10) && (RamVReg->reg[0x17]>>6)==2) { + + DmaFill(wordValue); + + } else { + //UINT32 a=Pico.video.addr; + switch (RamVReg->type) { + case 1: + // If address is odd, bytes are swapped (which game needs this?) + if (RamVReg->addr & 1) { + bprintf(PRINT_NORMAL, _T("Video address is odd, bytes are swapped!!!\n")); + wordValue = (wordValue<<8)|(wordValue>>8); + } + RamVid[(RamVReg->addr >> 1) & 0x7fff] = wordValue; + rendstatus |= 0x10; + break; + case 3: + //Pico.m.dirtyPal = 1; + //dprintf("w[%i] @ %04x, inc=%i [%i|%i]", Pico.video.type, a, Pico.video.reg[0xf], Pico.m.scanline, SekCyclesDone()); + CalcCol((RamVReg->addr >> 1) & 0x003f, wordValue); + break; + case 5: + RamSVid[(RamVReg->addr >> 1) & 0x003f] = wordValue; + break; + } + //dprintf("w[%i] @ %04x, inc=%i [%i|%i]", Pico.video.type, a, Pico.video.reg[0xf], Pico.m.scanline, SekCyclesDone()); + //AutoIncrement(); + RamVReg->addr += RamVReg->reg[0xf]; + } + return; + + case 0x04: // command + if(RamVReg->pending) { + // Low word of command: + RamVReg->command &= 0xffff0000; + RamVReg->command |= wordValue; + RamVReg->pending = 0; + CommandChange(); + } else { + if((wordValue & 0xc000) == 0x8000) { + INT32 num = (wordValue >> 8) & 0x1f; + RamVReg->reg[num] = wordValue & 0xff; + + // update IRQ level (Lemmings, Wiz 'n' Liz intro, ... ) + // may break if done improperly: + // International Superstar Soccer Deluxe (crash), Street Racer (logos), Burning Force (gfx), Fatal Rewind (hang), Sesame Street Counting Cafe + if(num < 2) { + + INT32 lines = (RamVReg->reg[1] & 0x20) | (RamVReg->reg[0] & 0x10); + INT32 pints = (RamVReg->pending_ints & lines); + if(pints & 0x20) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + else if(pints & 0x10) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + else SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + + } + + if (num == 5) rendstatus |= 1; +// else if(num == 0xc) Pico.m.dirtyPal = 2; // renderers should update their palettes if sh/hi mode is changed + RamVReg->type = 0; // register writes clear command (else no Sega logo in Golden Axe II) + } else { + // High word of command: + RamVReg->command &= 0x0000ffff; + RamVReg->command |= wordValue << 16; + RamVReg->pending = 1; + } + } + return; + + case 0x10: + case 0x14: + // PSG Sound + //bprintf(PRINT_NORMAL, _T("PSG Attempt to write word value %04x to location %08x\n"), wordValue, sekAddress); + SN76496Write(0, wordValue & 0xFF); + return; + + } +} + +void __fastcall MegadriveVideoWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + //bprintf(PRINT_NORMAL, _T("Video Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + MegadriveVideoWriteWord(sekAddress, (byteValue << 8) | byteValue); +} + +// -- Z80 Ram Read Write ------------------------------------------ + +UINT8 __fastcall MegadriveZ80RamReadByte(UINT32 sekAddress) +{ + if (!Z80HasBus && !MegadriveZ80Reset) { + return RamZ80[sekAddress & 0x1fff]; + } + + return 0; +} + +UINT16 __fastcall MegadriveZ80RamReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Z80Ram Attempt to read word value of location %x\n"), sekAddress); + return 0; +} + +void __fastcall MegadriveZ80RamWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (!Z80HasBus && !MegadriveZ80Reset) { + RamZ80[sekAddress & 0x1fff] = byteValue; + return; + } + bprintf(PRINT_NORMAL, _T("Z80Ram Attempt to write byte value %x to location %x and didn't have the Bus!\n"), byteValue, sekAddress); +} + +void __fastcall MegadriveZ80RamWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (!Z80HasBus && !MegadriveZ80Reset) { + RamZ80[sekAddress & 0x1fff] = wordValue >> 8; + return; + } + + bprintf(PRINT_NORMAL, _T("Z80Ram Attempt to write word value %x to location %x and didn't have the Bus!\n"), wordValue, sekAddress); +// MegadriveZ80RamWriteByte(sekAddress, wordValue >> 0x08); +} + +// -- I/O Read Write ------------------------------------------ + +static INT32 PadRead(INT32 i) +{ + INT32 pad=0,value=0,TH; + pad = ~(JoyPad->pad[i]); // Get inverse of pad MXYZ SACB RLDU + TH = RamIO[i+1] & 0x40; + + /*if(PicoOpt & 0x20)*/ { // 6 button gamepad enabled + INT32 phase = JoyPad->padTHPhase[i]; + + if(phase == 2 && !TH) { + value = (pad&0xc0)>>2; // ?0SA 0000 + goto end; + } else if(phase == 3 && TH) { + value=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ + goto end; + } else if(phase == 3 && !TH) { + value=((pad&0xc0)>>2)|0x0f; // ?0SA 1111 + goto end; + } + } + + if(TH) value=(pad&0x3f); // ?1CB RLDU + else value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU + +end: + + // orr the bits, which are set as output + value |= RamIO[i+1] & RamIO[i+4]; + + return value; // will mirror later +} + +UINT8 __fastcall MegadriveIOReadByte(UINT32 sekAddress) +{ + if (sekAddress > 0xA1001F) + bprintf(PRINT_NORMAL, _T("IO Attempt to read byte value of location %x\n"), sekAddress); + + INT32 offset = (sekAddress >> 1) & 0xf; + switch (offset) { + case 0: // Get Hardware + return Hardware; + case 1: // Pad 1 + return (RamIO[1] & 0x80) | PadRead(0); + case 2: // Pad 2 + return (RamIO[2] & 0x80) | PadRead(1); + default: + //bprintf(PRINT_NORMAL, _T("IO Attempt to read byte value of location %x\n"), sekAddress); + return RamIO[offset]; + } + return 0; +} + +UINT16 __fastcall MegadriveIOReadWord(UINT32 sekAddress) +{ + //if (sekAddress > 0xA1001F) + // bprintf(PRINT_NORMAL, _T("IO Attempt to read word value of location %x\n"), sekAddress); + + UINT8 res = MegadriveIOReadByte(sekAddress); + return res | (res << 8); +} + +void __fastcall MegadriveIOWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress > 0xA1001F) + bprintf(PRINT_NORMAL, _T("IO Attempt to byte byte value %x to location %x\n"), byteValue, sekAddress); + + INT32 offset = (sekAddress >> 1) & 0xf; + // 6-Button Support + switch( offset ) { + case 1: + JoyPad->padDelay[0] = 0; + if(!(RamIO[1] & 0x40) && (byteValue&0x40)) + JoyPad->padTHPhase[0] ++; + break; + case 2: + JoyPad->padDelay[1] = 0; + if(!(RamIO[2] & 0x40) && (byteValue&0x40)) + JoyPad->padTHPhase[1] ++; + break; + } + RamIO[offset] = byteValue; +} + +void __fastcall MegadriveIOWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + //if (sekAddress > 0xA1001F) + // bprintf(PRINT_NORMAL, _T("IO Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + MegadriveIOWriteByte(sekAddress, wordValue & 0xff); +} + +// -- YM2612/YM2612 FM Chip ---------------------------------------------------------- + +inline static INT32 MegadriveSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / (OSC_NTSC / 7); +} + +inline static double MegadriveGetTime() +{ + return (double)SekTotalCycles() / (OSC_NTSC / 7); +} + +inline static INT32 MegadriveSynchroniseStreamPAL(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / (OSC_PAL / 7); +} + +inline static double MegadriveGetTimePAL() +{ + return (double)SekTotalCycles() / (OSC_PAL / 7); +} + +// --------------------------------------------------------------- + +static INT32 MegadriveResetDo() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2612Reset(); + + MegadriveZ80Reset = 1; + Z80HasBus = 1; + +#if 0 + FILE * f = fopen("Megadrive.bin", "wb+"); + fwrite(RomMain, 1, 0x200000, f); + fclose(f); +#endif + + MegadriveCheckHardware(); + + if (Hardware & 0x40) { + BurnSetRefreshRate(50.0); + Reinitialise(); + + BurnYM2612Exit(); + BurnYM2612Init(1, OSC_PAL / 7, NULL, MegadriveSynchroniseStreamPAL, MegadriveGetTimePAL, 0); + BurnTimerAttachSek(OSC_PAL / 7); + + BurnYM2612Reset(); + + SN76496Exit(); + SN76496Init(0, OSC_PAL / 15, 1); + } else { + BurnSetRefreshRate(60.0); + Reinitialise(); + + BurnYM2612Exit(); + BurnYM2612Init(1, OSC_NTSC / 7, NULL, MegadriveSynchroniseStream, MegadriveGetTime, 0); + BurnTimerAttachSek(OSC_NTSC / 7); + + BurnYM2612Reset(); + + SN76496Exit(); + SN76496Init(0, OSC_NTSC / 15, 1); + } + + // other reset +// memset(RamMisc, 0, sizeof(struct PicoMisc)); + memset(JoyPad, 0, sizeof(struct MegadriveJoyPad)); + + // default VDP register values (based on Fusion) + memset(RamVReg, 0, sizeof(struct PicoVideo)); + RamVReg->reg[0x00] = 0x04; + RamVReg->reg[0x01] = 0x04; + RamVReg->reg[0x0c] = 0x81; + RamVReg->reg[0x0f] = 0x02; + + RamVReg->status = 0x3408 | ((MegadriveDIP[0] & 0x40) >> 6); + + return 0; +} + +INT32 __fastcall MegadriveIrqCallback(INT32 irq) +{ + switch ( irq ) { + case 4: RamVReg->pending_ints = 0x00; break; + case 6: RamVReg->pending_ints &= ~0x20; break; + } + return -1; +} + +// ---------------------------------------------------------------- +// Z80 Read/Write +// ---------------------------------------------------------------- + +UINT8 __fastcall MegadriveZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read 02%x\n"), a); + } + } + + return 0; +} + +void __fastcall MegadriveZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write %02x, %02%x\n"), a, d); + } + } +} + +UINT8 __fastcall MegadriveZ80ProgRead(UINT16 a) +{ + if (a >= 0x6100 && a <= 0x7eff) { + return 0xff; + } + + if (a >= 0x8000) { + UINT32 addr68k = RamMisc->Bank68k; + addr68k += a & 0x7fff; + if (addr68k <= 0x3fffff) return RomMain[addr68k ^ 1]; + + bprintf(PRINT_NORMAL, _T("%Z80 trying to read 68k address %06X\n"), addr68k); + return 0; + } + + switch (a) { + case 0x4000: + case 0x4001: + case 0x4002: { + return BurnYM2612Read(0, 0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04x\n"), a); + } + } + + return 0; +} + +UINT32 Z80BankPartial = 0; +UINT32 Z80BankPos = 0; + +void __fastcall MegadriveZ80ProgWrite(UINT16 a, UINT8 d) +{ + if (a == 0x6000 || a == 0x6001) { + Z80BankPartial |= (d & 0x01) << 23; + Z80BankPos++; + + if (Z80BankPos < 9) { + Z80BankPartial >>= 1; + } else { + Z80BankPos = 0; + RamMisc->Bank68k = Z80BankPartial; + Z80BankPartial = 0; + } + return; + } + + if (a >= 0x8000) { + UINT32 addr68k = RamMisc->Bank68k; + addr68k += a & 0x7fff; + + if (addr68k <= 0x3fffff) return; + + if (addr68k == 0xc00011) { + SN76496Write(0, d); + return; + } + + if ((addr68k >= 0xe00000) && (addr68k <= 0xffffff)) { + addr68k &=0xffff; + UINT16 *Ram = (UINT16*)Ram68K; + if (addr68k & 0x01) { + Ram[addr68k >> 1] = (Ram[addr68k >> 1] & 0xff00) | d; + } else { + Ram[addr68k >> 1] = (Ram[addr68k >> 1] & 0x00ff) | (d << 8); + } + return; + } + + bprintf(PRINT_NORMAL, _T("Z80-Bank68K Attempt to write byte value %02x to location %06x\n"), d, addr68k); + return; + } + + switch (a) { + case 0x4000: { + BurnYM2612Write(0, 0, d); + return; + } + + case 0x4001: { + BurnYM2612Write(0, 1, d); + return; + } + + case 0x4002: { + BurnYM2612Write(0, 2, d); + return; + } + + case 0x4003: { + BurnYM2612Write(0, 3, d); + return; + } + + case 0x7f11: + case 0x7f13: + case 0x7f15: + case 0x7f17: { + SN76496Write(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04x, %02x\n"), a, d); + } + } +} + +static INT32 MegadriveLoadRoms(bool bLoad) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + INT32 nOffset = -1; + UINT32 i; + INT32 nRet = 0; + + if (!bLoad) { + do { + ri.nLen = 0; + ri.nType = 0; + BurnDrvGetRomInfo(&ri, ++nOffset); + if(ri.nLen) RomNum++; + RomSize += ri.nLen; + } while (ri.nLen); + + bprintf(PRINT_NORMAL, _T("68K Rom, Num %i, Size %x\n"), RomNum, RomSize); + } + + if (bLoad) { + INT32 Offset = 0; + + for (i = 0; i < RomNum; i++) { + BurnDrvGetRomInfo(&ri, i); + + switch (ri.nType & 0x0f) { + case SEGA_MD_ROM_OFFS_000000: Offset = 0x000000; break; + case SEGA_MD_ROM_OFFS_000001: Offset = 0x000001; break; + case SEGA_MD_ROM_OFFS_020000: Offset = 0x020000; break; + case SEGA_MD_ROM_OFFS_080000: Offset = 0x080000; break; + case SEGA_MD_ROM_OFFS_100000: Offset = 0x100000; break; + case SEGA_MD_ROM_OFFS_100001: Offset = 0x100001; break; + case SEGA_MD_ROM_OFFS_200000: Offset = 0x200000; break; + } + + switch (ri.nType & 0xf0) { + case SEGA_MD_ROM_LOAD_NORMAL: { + nRet = BurnLoadRom(RomMain + Offset, i, 1); if (nRet) return 1; + break; + } + + case SEGA_MD_ROM_LOAD16_WORD_SWAP: { + nRet = BurnLoadRom(RomMain + Offset, i, 1); if (nRet) return 1; + BurnByteswap(RomMain + Offset, ri.nLen); + break; + } + + case SEGA_MD_ROM_LOAD16_BYTE: { + nRet = BurnLoadRom(RomMain + Offset, i, 2); if (nRet) return 1; + break; + } + + case SEGA_MD_ROM_LOAD16_WORD_SWAP_CONTINUE_040000_100000: { + nRet = BurnLoadRom(RomMain + Offset, i, 1); if (nRet) return 1; + memcpy(RomMain + 0x100000, RomMain + 0x040000, 0x40000); + BurnByteswap(RomMain + Offset, 0x140000); + break; + } + } + } + } + + return 0; +} + +// Custom Cartridge Mapping + +UINT8 __fastcall JCartCtrlReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("JCartCtrlRead Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall JCartCtrlReadWord(UINT32 /*sekAddress*/) +{ + UINT16 retData = 0; + + UINT8 JPad3 = ~(JoyPad->pad[2] & 0xff); + UINT8 JPad4 = ~(JoyPad->pad[3] & 0xff); + + if (RamMisc->JCartIOData[0] & 0x40) { + retData = (RamMisc->JCartIOData[0] & 0x40) | JPad3 | (JPad4 << 8); + } else { + retData = ((JPad3 & 0xc0) >> 2) | (JPad3 & 0x03); + retData += (((JPad4 & 0xc0) >> 2) | (JPad4 & 0x03)) << 8; + } + + return retData; +} + +void __fastcall JCartCtrlWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + bprintf(PRINT_NORMAL, _T("JCartCtrlWrite byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall JCartCtrlWriteWord(UINT32 /*sekAddress*/, UINT16 wordValue) +{ + RamMisc->JCartIOData[0] = (wordValue & 1) << 6; + RamMisc->JCartIOData[1] = (wordValue & 1) << 6; +} + +void __fastcall Ssf2BankWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0xa130f1: { + if (byteValue == 2) memcpy(RomMain + 0x000000, RomMain + 0x400000 + (((byteValue & 0x0f) - 2) * 0x080000), 0x080000); + return; + } + + case 0xa130f3: { + memcpy(RomMain + 0x080000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130f5: { + memcpy(RomMain + 0x100000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130f7: { + memcpy(RomMain + 0x180000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130f9: { + memcpy(RomMain + 0x200000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130fb: { + memcpy(RomMain + 0x280000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130fd: { + memcpy(RomMain + 0x300000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + + case 0xa130ff: { + memcpy(RomMain + 0x380000, RomMain + 0x400000 + ((byteValue & 0xf) * 0x080000), 0x080000); + return; + } + } +} + +UINT8 __fastcall LK3AltProtReadByte(UINT32 sekAddress) +{ + INT32 Offset = (sekAddress - 0x600000) >> 1; + Offset &= 0x07; + + UINT8 retData = 0; + + switch (Offset) { + case 0x02: { + switch (RamMisc->L3AltPCmd) { + case 1: + retData = RamMisc->L3AltPDat >> 1; + break; + + case 2: + retData = RamMisc->L3AltPDat >> 4; + retData |= (RamMisc->L3AltPDat & 0x0f) << 4; + break; + + default: + retData = (BIT(RamMisc->L3AltPDat, 7) << 0); + retData |= (BIT(RamMisc->L3AltPDat, 6) << 1); + retData |= (BIT(RamMisc->L3AltPDat, 5) << 2); + retData |= (BIT(RamMisc->L3AltPDat, 4) << 3); + retData |= (BIT(RamMisc->L3AltPDat, 3) << 4); + retData |= (BIT(RamMisc->L3AltPDat, 2) << 5); + retData |= (BIT(RamMisc->L3AltPDat, 1) << 6); + retData |= (BIT(RamMisc->L3AltPDat, 0) << 7); + break; + } + break; + } + } + +// bprintf(PRINT_NORMAL, _T("LK3AltProt Read Byte %x\n"), sekAddress); + + return retData; +} + +UINT16 __fastcall LK3AltProtReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("LK3AltProt Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall LK3AltProtWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + INT32 Offset = (sekAddress - 0x600000) >> 1; + Offset &= 0x07; + + switch (Offset) { + case 0x00: + RamMisc->L3AltPDat = byteValue; + return; + + case 0x01: + RamMisc->L3AltPCmd = byteValue; + return; + } + +// bprintf(PRINT_NORMAL, _T("LK3AltProt write byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall LK3AltProtWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("LK3AltProt write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +void __fastcall LK3AltBankWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + INT32 Offset = (sekAddress - 0x700000) >> 1; + Offset &= 0x07; + + if (Offset == 0) { + memcpy(RomMain, OriginalRom + ((byteValue & 0xff) * 0x8000), 0x8000); + return; + } + + bprintf(PRINT_NORMAL, _T("LK3AltBank write byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall LK3AltBankWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("LK3AltBank write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall RedclifProtReadByte(UINT32 /*sekAddress*/) +{ + return (UINT8)-0x56; +} + +UINT16 __fastcall RedclifProtReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("RedclifeProt Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall RedclifProt2ReadByte(UINT32 /*sekAddress*/) +{ + return 0x55; +} + +UINT16 __fastcall RedclifProt2ReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("RedclifeProt2 Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall RadicaBankSelectReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("RadicaBankSelect Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall RadicaBankSelectReadWord(UINT32 sekAddress) +{ + INT32 Bank = ((sekAddress - 0xa13000) >> 1) & 0x3f; + memcpy(RomMain, RomMain + 0x400000 + (Bank * 0x10000), 0x400000); + + return 0; +} + +UINT8 __fastcall Kof99A13000ReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Kof99A13000 Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Kof99A13000ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xa13000: return 0x00; + case 0xa13002: return 0x01; + case 0xa1303e: return 0x1f; + + } + + bprintf(PRINT_NORMAL, _T("Kof99A13000 Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall SoulbladReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400002: return 0x98; + case 0x400004: return 0xc0; + case 0x400006: return 0xf0; + + } + + bprintf(PRINT_NORMAL, _T("Soulblad Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall SoulbladReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Soulblad Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall MjloverProt1ReadByte(UINT32 /*sekAddress*/) +{ + return 0x90; +} + +UINT16 __fastcall MjloverProt1ReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("MjloverProt1 Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall MjloverProt2ReadByte(UINT32 /*sekAddress*/) +{ + return 0xd3; +} + +UINT16 __fastcall MjloverProt2ReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("MjloverProt2 Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall SquirrelKingExtraReadByte(UINT32 /*sekAddress*/) +{ + return RamMisc->SquirrelkingExtra; +} + +UINT16 __fastcall SquirrelKingExtraReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("SquirrelKingExtra Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall SquirrelKingExtraWriteByte(UINT32 /*sekAddress*/, UINT8 byteValue) +{ + RamMisc->SquirrelkingExtra = byteValue; +} + +void __fastcall SquirrelKingExtraWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("SquirrelKingExtra write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall SmouseProtReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400000: return 0x55; + case 0x400002: return 0x0f; + case 0x400004: return 0xaa; + case 0x400005: return 0xf0; + } + + return 0; +} + +UINT16 __fastcall SmouseProtReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("SmouseProt Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall SmbProtReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Smbprot Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall SmbProtReadWord(UINT32 /*sekAddress*/) +{ + return 0x0c; +} + +UINT8 __fastcall Smb2ProtReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Smb2Prot Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Smb2ProtReadWord(UINT32 /*sekAddress*/) +{ + return 0x0a; +} + +void __fastcall KaijuBankWriteByte(UINT32 /*sekAddress*/, UINT8 byteValue) +{ + memcpy(RomMain + 0x000000, RomMain + 0x400000 + (byteValue & 0x7f) * 0x8000, 0x8000); +} + +void __fastcall KaijuBankWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("KaijuBank write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall Chinfi3ProtReadByte(UINT32 /*sekAddress*/) +{ + UINT8 retDat = 0; + + if (SekGetPC(0) == 0x01782) // makes 'VS' screen appear + { + retDat = SekDbgGetRegister(SEK_REG_D3) & 0xff; +// retDat <<= 8; + return retDat; + } + else if (SekGetPC(0) == 0x1c24) // background gfx etc. + { + retDat = SekDbgGetRegister(SEK_REG_D3) & 0xff; +// retDat <<= 8; + return retDat; + } + else if (SekGetPC(0) == 0x10c4a) // unknown + { + return rand() & 0xff;//space->machine().rand(); + } + else if (SekGetPC(0) == 0x10c50) // unknown + { + return rand() & 0xff;//space->machine().rand(); + } + else if (SekGetPC(0) == 0x10c52) // relates to the game speed.. + { + retDat = SekDbgGetRegister(SEK_REG_D4) & 0xff; +// retDat <<= 8; + return retDat; + } + else if (SekGetPC(0) == 0x061ae) + { + retDat = SekDbgGetRegister(SEK_REG_D3) & 0xff; +// retDat <<= 8; + return retDat; + } + else if (SekGetPC(0) == 0x061b0) + { + retDat = SekDbgGetRegister(SEK_REG_D3) & 0xff; +// retDat <<= 8; + return retDat; + } + + return 0; +} + +UINT16 __fastcall Chinfi3ProtReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Chinfi3Prot Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall Chinfi3BankWriteByte(UINT32 /*sekAddress*/, UINT8 byteValue) +{ + if (byteValue == 0xf1) // *hit player + { + INT32 x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(RomMain + x, RomMain + 0x410000, 0x10000); + } + } + else if (byteValue == 0xd7) // title screen.. + { + INT32 x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(RomMain + x, RomMain + 0x470000, 0x10000); + } + } + else if (byteValue == 0xd3) // character hits floor + { + INT32 x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(RomMain + x, RomMain + 0x430000, 0x10000); + } + } + else if (byteValue == 0x00) + { + INT32 x; + for (x = 0; x < 0x100000; x += 0x10000) + { + memcpy(RomMain + x, RomMain + 0x400000 + x, 0x10000); + } + } +} + +void __fastcall Chinfi3BankWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Chinfi3Bank write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall Lionk2ProtReadByte(UINT32 sekAddress) +{ + switch(sekAddress) { + case 0x400002: { + return RamMisc->Lionk2ProtData; + } + + case 0x400006: { + return RamMisc->Lionk2ProtData2; + } + } + + bprintf(PRINT_NORMAL, _T("Lion2Prot Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Lionk2ProtReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Lion2Prot Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall Lionk2ProtWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x400000: { + RamMisc->Lionk2ProtData = byteValue; + return; + } + + case 0x400004: { + RamMisc->Lionk2ProtData2 = byteValue; + return; + } + } + + bprintf(PRINT_NORMAL, _T("Lion2Prot write byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall Lionk2ProtWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Lion2Prot write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall BuglExtraReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("BuglExtra Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall BuglExtraReadWord(UINT32 /*sekAddress*/) +{ + return 0x28; +} + +UINT8 __fastcall Elfwor400000ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400000: return 0x55; + case 0x400002: return 0x0f; + case 0x400004: return 0xc9; + case 0x400006: return 0x18; + } + + bprintf(PRINT_NORMAL, _T("Elfwor400000 Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Elfwor400000ReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Elfwor400000 Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall RockmanX3ExtraReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("RockmanX3Extra Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall RockmanX3ExtraReadWord(UINT32 /*sekAddress*/) +{ + return 0x0c; +} + +UINT8 __fastcall SbubExtraReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400000: return 0x55; + case 0x400002: return 0x0f; + } + + bprintf(PRINT_NORMAL, _T("SbubExtra Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall SbubExtraReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("SbubExtra Read Word %x\n"), sekAddress); + + return 0; +} + +UINT8 __fastcall Kof98ReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Kof98 Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Kof98ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x480000: return 0xaa00; + case 0x4800e0: return 0xaa00; + case 0x4824a0: return 0xaa00; + case 0x488880: return 0xaa00; + case 0x4a8820: return 0x0a00; + case 0x4f8820: return 0x0000; + } + + bprintf(PRINT_NORMAL, _T("Kof98 Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall RealtecWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x400000: { + INT32 BankData = (byteValue >> 9) & 0x7; + + RamMisc->RealtecBankAddr = (RamMisc->RealtecBankAddr & 0x7) | BankData << 3; + + memcpy(RomMain, RomMain + (RamMisc->RealtecBankAddr * 0x20000) + 0x400000, RamMisc->RealtecBankSize * 0x20000); + memcpy(RomMain + RamMisc->RealtecBankSize * 0x20000, RomMain + (RamMisc->RealtecBankAddr * 0x20000) + 0x400000, RamMisc->RealtecBankSize * 0x20000); + return; + } + + case 0x402000:{ + RamMisc->RealtecBankAddr = 0; + RamMisc->RealtecBankSize = (byteValue >> 8) & 0x1f; + return; + } + + case 0x404000: { + INT32 BankData = (byteValue >> 8) & 0x3; + + RamMisc->RealtecBankAddr = (RamMisc->RealtecBankAddr & 0xf8) | BankData; + + memcpy(RomMain, RomMain + (RamMisc->RealtecBankAddr * 0x20000)+ 0x400000, RamMisc->RealtecBankSize * 0x20000); + memcpy(RomMain + RamMisc->RealtecBankSize * 0x20000, RomMain + (RamMisc->RealtecBankAddr * 0x20000) + 0x400000, RamMisc->RealtecBankSize * 0x20000); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Realtec write byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall RealtecWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Realtec write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +void __fastcall Sup19in1BankWriteByte(UINT32 sekAddress, UINT8 /*byteValue*/) +{ + INT32 Offset = (sekAddress - 0xa13000) >> 1; + + memcpy(RomMain + 0x000000, RomMain + 0x400000 + ((Offset << 1) * 0x10000), 0x80000); +} + +void __fastcall Sup19in1BankWriteWord(UINT32 sekAddress, UINT16 /*wordValue*/) +{ + INT32 Offset = (sekAddress - 0xa13000) >> 1; + + memcpy(RomMain + 0x000000, RomMain + 0x400000 + ((Offset << 1) * 0x10000), 0x80000); +} + +void __fastcall Mc12in1BankWriteByte(UINT32 sekAddress, UINT8 /*byteValue*/) +{ + INT32 Offset = (sekAddress - 0xa13000) >> 1; + memcpy(RomMain + 0x000000, OriginalRom + ((Offset & 0x3f) << 17), 0x100000); +} + +void __fastcall Mc12in1BankWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Mc12in1Bank write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall TopfigReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x645b45: return 0x9f; + + case 0x6bd295: { + static INT32 x = -1; + + if (SekGetPC(0) == 0x1771a2) { + return 0x50; + } else { + x++; + return (UINT8)x; + } + } + + case 0x6f5345: { + static INT32 x = -1; + + if (SekGetPC(0) == 0x4C94E) { + return SekDbgGetRegister(SEK_REG_D0) & 0xff; + } else { + x++; + return (UINT8)x; + } + } + } + + bprintf(PRINT_NORMAL, _T("Topfig Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall TopfigReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Topfig Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall TopfigWriteByte(UINT32 /*sekAddress*/, UINT8 byteValue) +{ + if (byteValue == 0x002a) + { + memcpy(RomMain + 0x060000, RomMain + 0x570000, 0x8000); // == 0x2e*0x8000?! + + } + else if (byteValue==0x0035) // characters ingame + { + memcpy(RomMain + 0x020000, RomMain + 0x5a8000, 0x8000); // == 0x35*0x8000 + } + else if (byteValue==0x000f) // special moves + { + memcpy(RomMain + 0x058000, RomMain + 0x478000, 0x8000); // == 0xf*0x8000 + } + else if (byteValue==0x0000) + { + memcpy(RomMain + 0x060000, RomMain + 0x460000, 0x8000); + memcpy(RomMain + 0x020000, RomMain + 0x420000, 0x8000); + memcpy(RomMain + 0x058000, RomMain + 0x458000, 0x8000); + } +} + +void __fastcall TopfigWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Topfig write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +static void SetupCustomCartridgeMappers() +{ + if (((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART) || ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM)) { + SekOpen(0); + SekMapHandler(7, 0x38fffe, 0x38ffff, SM_READ | SM_WRITE); + SekSetReadByteHandler(7, JCartCtrlReadByte); + SekSetReadWordHandler(7, JCartCtrlReadWord); + SekSetWriteByteHandler(7, JCartCtrlWriteByte); + SekSetWriteWordHandler(7, JCartCtrlWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SSF2) { + OriginalRom = (UINT8*)malloc(0x500000); + memcpy(OriginalRom, RomMain, 0x500000); + + memcpy(RomMain + 0x800000, OriginalRom + 0x400000, 0x100000); + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x400000); + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x400000); + + SekOpen(0); + SekMapHandler(7, 0xa130f0, 0xa130ff, SM_WRITE); + SekSetWriteByteHandler(7, Ssf2BankWriteByte); + SekClose(); + } + + if (((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_LIONK3) || ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SKINGKONG)) { + RamMisc->L3AltPDat = 0; + RamMisc->L3AltPCmd = 0; + + OriginalRom = (UINT8*)malloc(0x200000); + memcpy(OriginalRom, RomMain, 0x200000); + + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x200000, OriginalRom + 0x000000, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0x600000, 0x6fffff, SM_READ | SM_WRITE); + SekSetReadByteHandler(7, LK3AltProtReadByte); + SekSetReadWordHandler(7, LK3AltProtReadWord); + SekSetWriteByteHandler(7, LK3AltProtWriteByte); + SekSetWriteWordHandler(7, LK3AltProtWriteWord); + SekMapHandler(8, 0x700000, 0x7fffff, SM_WRITE); + SekSetWriteByteHandler(8, LK3AltBankWriteByte); + SekSetWriteWordHandler(8, LK3AltBankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SDK99) { + RamMisc->L3AltPDat = 0; + RamMisc->L3AltPCmd = 0; + + OriginalRom = (UINT8*)malloc(0x300000); + memcpy(OriginalRom, RomMain, 0x300000); + + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x300000); + memcpy(RomMain + 0x300000, OriginalRom + 0x000000, 0x100000); + + SekOpen(0); + SekMapHandler(7, 0x600000, 0x6fffff, SM_READ | SM_WRITE); + SekSetReadByteHandler(7, LK3AltProtReadByte); + SekSetReadWordHandler(7, LK3AltProtReadWord); + SekSetWriteByteHandler(7, LK3AltProtWriteByte); + SekSetWriteWordHandler(7, LK3AltProtWriteWord); + SekMapHandler(8, 0x700000, 0x7fffff, SM_WRITE); + SekSetWriteByteHandler(8, LK3AltBankWriteByte); + SekSetWriteWordHandler(8, LK3AltBankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_REDCL_EN) { + OriginalRom = (UINT8*)malloc(0x200005); + memcpy(OriginalRom, RomMain, 0x200005); + for (UINT32 i = 0; i < RomSize; i++) { + OriginalRom[i] ^= 0x40; + } + + memcpy(RomMain + 0x000000, OriginalRom + 0x000004, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400001, SM_READ); + SekSetReadByteHandler(7, RedclifProt2ReadByte); + SekSetReadWordHandler(7, RedclifProt2ReadWord); + SekMapHandler(8, 0x400004, 0x400005, SM_READ); + SekSetReadByteHandler(8, RedclifProtReadByte); + SekSetReadWordHandler(8, RedclifProtReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_RADICA) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x400000); + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x400000); + memcpy(RomMain + 0x800000, OriginalRom + 0x000000, 0x400000); + + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa1307f, SM_READ); + SekSetReadByteHandler(7, RadicaBankSelectReadByte); + SekSetReadWordHandler(7, RadicaBankSelectReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_KOF99) { + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa1303f, SM_READ); + SekSetReadByteHandler(7, Kof99A13000ReadByte); + SekSetReadWordHandler(7, Kof99A13000ReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SOULBLAD) { + SekOpen(0); + SekMapHandler(7, 0x400002, 0x400007, SM_READ); + SekSetReadByteHandler(7, SoulbladReadByte); + SekSetReadWordHandler(7, SoulbladReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_MJLOVER) { + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400001, SM_READ); + SekSetReadByteHandler(7, MjloverProt1ReadByte); + SekSetReadWordHandler(7, MjloverProt1ReadWord); + SekMapHandler(8, 0x401000, 0x401001, SM_READ); + SekSetReadByteHandler(8, MjloverProt2ReadByte); + SekSetReadWordHandler(8, MjloverProt2ReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SQUIRRELK) { + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400007, SM_READ | SM_WRITE); + SekSetReadByteHandler(7, SquirrelKingExtraReadByte); + SekSetReadWordHandler(7, SquirrelKingExtraReadWord); + SekSetWriteByteHandler(7, SquirrelKingExtraWriteByte); + SekSetWriteWordHandler(7, SquirrelKingExtraWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SMOUSE) { + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400007, SM_READ); + SekSetReadByteHandler(7, SmouseProtReadByte); + SekSetReadWordHandler(7, SmouseProtReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SMB) { + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13001, SM_READ); + SekSetReadByteHandler(7, SmbProtReadByte); + SekSetReadWordHandler(7, SmbProtReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SMB2) { + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13001, SM_READ); + SekSetReadByteHandler(7, Smb2ProtReadByte); + SekSetReadWordHandler(7, Smb2ProtReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_KAIJU) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x400000, OriginalRom, 0x200000); + memcpy(RomMain + 0x600000, OriginalRom, 0x200000); + memcpy(RomMain + 0x000000, OriginalRom, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0x700000, 0x7fffff, SM_WRITE); + SekSetWriteByteHandler(7, KaijuBankWriteByte); + SekSetWriteWordHandler(7, KaijuBankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_CHINFIGHT3) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x600000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0x400000, 0x4fffff, SM_READ); + SekSetReadByteHandler(7, Chinfi3ProtReadByte); + SekSetReadWordHandler(7, Chinfi3ProtReadWord); + SekMapHandler(8, 0x600000, 0x6fffff, SM_WRITE); + SekSetWriteByteHandler(8, Chinfi3BankWriteByte); + SekSetWriteWordHandler(8, Chinfi3BankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_LIONK2) { + RamMisc->Lionk2ProtData = 0; + RamMisc->Lionk2ProtData2 = 0; + + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400007, SM_READ | SM_WRITE); + SekSetReadByteHandler(7, Lionk2ProtReadByte); + SekSetReadWordHandler(7, Lionk2ProtReadWord); + SekSetWriteByteHandler(7, Lionk2ProtWriteByte); + SekSetWriteWordHandler(7, Lionk2ProtWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_BUGSLIFE) { + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13001, SM_READ); + SekSetReadByteHandler(7, BuglExtraReadByte); + SekSetReadWordHandler(7, BuglExtraReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_ELFWOR) { + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400007, SM_READ); + SekSetReadByteHandler(7, Elfwor400000ReadByte); + SekSetReadWordHandler(7, Elfwor400000ReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_ROCKMANX3) { + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13001, SM_READ); + SekSetReadByteHandler(7, RockmanX3ExtraReadByte); + SekSetReadWordHandler(7, RockmanX3ExtraReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SBUBBOB) { + SekOpen(0); + SekMapHandler(7, 0x400000, 0x400003, SM_READ); + SekSetReadByteHandler(7, SbubExtraReadByte); + SekSetReadWordHandler(7, SbubExtraReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_KOF98) { + SekOpen(0); + SekMapHandler(7, 0x480000, 0x4fffff, SM_READ); + SekSetReadByteHandler(7, Kof98ReadByte); + SekSetReadWordHandler(7, Kof98ReadWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC) { + RamMisc->RealtecBankAddr = 0; + RamMisc->RealtecBankSize = 0; + + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x080000); + + for (INT32 i = 0; i < 0x400000; i += 0x2000) { + memcpy(RomMain + i, OriginalRom + 0x7e000, 0x2000); + } + + SekOpen(0); + SekMapHandler(7, 0x400000, 0x40400f, SM_WRITE); + SekSetWriteByteHandler(7, RealtecWriteByte); + SekSetWriteWordHandler(7, RealtecWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP19IN1) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x400000); + + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13039, SM_WRITE); + SekSetWriteByteHandler(7, Sup19in1BankWriteByte); + SekSetWriteWordHandler(7, Sup19in1BankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP15IN1) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa13039, SM_WRITE); + SekSetWriteByteHandler(7, Sup19in1BankWriteByte); + SekSetWriteWordHandler(7, Sup19in1BankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_12IN1) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0xa13000, 0xa1303f, SM_WRITE); + SekSetWriteByteHandler(7, Mc12in1BankWriteByte); + SekSetWriteWordHandler(7, Mc12in1BankWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_TOPFIGHTER) { + OriginalRom = (UINT8*)malloc(RomSize); + memcpy(OriginalRom, RomMain, RomSize); + + memcpy(RomMain + 0x000000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x200000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x400000, OriginalRom + 0x000000, 0x200000); + memcpy(RomMain + 0x600000, OriginalRom + 0x000000, 0x200000); + + SekOpen(0); + SekMapHandler(7, 0x600000, 0x6fffff, SM_READ); + SekSetReadByteHandler(7, TopfigReadByte); + SekSetReadWordHandler(7, TopfigReadWord); + SekMapHandler(8, 0x700000, 0x7fffff, SM_WRITE); + SekSetWriteByteHandler(8, TopfigWriteByte); + SekSetWriteWordHandler(8, TopfigWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_POKEMON) { + UINT16 *ROM16 = (UINT16 *)RomMain; + + ROM16[0x0dd19e/2] = 0x47F8; + ROM16[0x0dd1a0/2] = 0xFFF0; + ROM16[0x0dd1a2/2] = 0x4E63; + ROM16[0x0dd46e/2] = 0x4EF8; + ROM16[0x0dd470/2] = 0x0300; + ROM16[0x0dd49c/2] = 0x6002; + } + +/* if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_POKEMON2) { + UINT16 *ROM16 = (UINT16 *)RomMain; + + ROM16[0x06036/2] = 0xE000; + ROM16[0x02540/2] = 0x6026; + ROM16[0x01ED0/2] = 0x6026; + ROM16[0x02476/2] = 0x6022; + + ROM16[0x7E300/2] = 0x60FE; + }*/ + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_MULAN) { + UINT16 *ROM16 = (UINT16 *)RomMain; + + ROM16[0x06036/2] = 0xE000; + } +} + +// SRAM and EEPROM Handling + +UINT8 __fastcall MegadriveSRAMReadByte(UINT32 sekAddress) +{ + if (RamMisc->SRamActive) { + return SRam[(sekAddress - RamMisc->SRamStart) ^ 1]; + } else { + return RomMain[sekAddress ^ 1]; + } +} + +UINT16 __fastcall MegadriveSRAMReadWord(UINT32 sekAddress) +{ + if (RamMisc->SRamActive) { + UINT16 *Ram = (UINT16*)SRam; + return Ram[(sekAddress - RamMisc->SRamStart) >> 1]; + } else { + UINT16 *Rom = (UINT16*)RomMain; + return Rom[sekAddress >> 1]; + } +} + +void __fastcall MegadriveSRAMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (RamMisc->SRamActive) { + if (!RamMisc->SRamReadOnly) { + SRam[(sekAddress - RamMisc->SRamStart) ^ 1] = byteValue; + return; + } + } +} + +void __fastcall MegadriveSRAMWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (RamMisc->SRamActive) { + if (!RamMisc->SRamReadOnly) { + UINT16 *Ram = (UINT16*)SRam; + Ram[(sekAddress - RamMisc->SRamStart) >> 1] = wordValue; + return; + } + } +} + +static void InstallSRAMHandlers(bool MaskAddr) +{ + UINT32 Mask = MaskAddr ? 0x3fffff : 0xffffff; + + memset(SRam, 0xff, MAX_SRAM_SIZE); + memcpy((UINT8*)MegadriveBackupRam, SRam, RamMisc->SRamEnd - RamMisc->SRamStart + 1); + + SekOpen(0); + SekMapHandler(6, RamMisc->SRamStart & Mask, RamMisc->SRamEnd & Mask, SM_READ | SM_WRITE); + SekSetReadByteHandler(6, MegadriveSRAMReadByte); + SekSetReadWordHandler(6, MegadriveSRAMReadWord); + SekSetWriteByteHandler(6, MegadriveSRAMWriteByte); + SekSetWriteWordHandler(6, MegadriveSRAMWriteWord); + SekClose(); + + RamMisc->SRamHandlersInstalled = 1; +} + +UINT8 __fastcall Megadrive6658ARegReadByte(UINT32 sekAddress) +{ + if (sekAddress & 1) return RamMisc->SRamActive; + + bprintf(PRINT_NORMAL, _T("Megadrive6658AReg Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall Megadrive6658ARegReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Megadrive6658AReg Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall Megadrive6658ARegWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress & 1) { + if (byteValue == 1) { + RamMisc->SRamActive = 1; + return; + } + + if (byteValue == 0) { + RamMisc->SRamActive = 0; + return; + } + } + + bprintf(PRINT_NORMAL, _T("6658A Reg write byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall Megadrive6658ARegWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("6658A Reg write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall WboyVEEPROMReadByte(UINT32 sekAddress) +{ + if (sekAddress & 1) return ~RamMisc->I2CMem & 1; + + bprintf(PRINT_NORMAL, _T("WboyVEEPROM Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall WboyVEEPROMReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("WboyVEEPROM Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall WboyVEEPROMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress & 1) { + RamMisc->I2CClk = (byteValue & 0x0002) >> 1; + RamMisc->I2CMem = (byteValue & 0x0001); + return; + } + + bprintf(PRINT_NORMAL, _T("WboyVEEPROM write byte value %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall WboyVEEPROMWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("WboyVEEPROM write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall NbajamEEPROMReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Nbajam Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall NbajamEEPROMReadWord(UINT32 /*sekAddress*/) +{ + return RamMisc->I2CMem & 1; +} + +void __fastcall NbajamEEPROMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + bprintf(PRINT_NORMAL, _T("Nbajam write byte value %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall NbajamEEPROMWriteWord(UINT32 /*sekAddress*/, UINT16 wordValue) +{ + RamMisc->I2CClk = (wordValue & 0x0002) >> 1; + RamMisc->I2CMem = (wordValue & 0x0001); +} + +UINT8 __fastcall NbajamteEEPROMReadByte(UINT32 sekAddress) +{ + if (sekAddress & 1) return RamMisc->I2CMem & 1; + + bprintf(PRINT_NORMAL, _T("Nbajamte Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall NbajamteEEPROMReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Nbajamte Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall NbajamteEEPROMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress & 1) { +// RamMisc->I2CClk = (wordValue & 0x0002) >> 1; + RamMisc->I2CMem = (byteValue & 0x0001); + return; + } + + bprintf(PRINT_NORMAL, _T("Nbajamte write byte value %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall NbajamteEEPROMWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Nbajamte write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +UINT8 __fastcall EANhlpaEEPROMReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("EANhlpa Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall EANhlpaEEPROMReadWord(UINT32 /*sekAddress*/) +{ + return (RamMisc->I2CMem & 1) << 7; +} + +void __fastcall EANhlpaEEPROMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + bprintf(PRINT_NORMAL, _T("EANhlpa write byte value %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall EANhlpaEEPROMWriteWord(UINT32 /*sekAddress*/, UINT16 wordValue) +{ + RamMisc->I2CClk = ((wordValue & 0x0040) >> 6); + RamMisc->I2CMem = ((wordValue & 0x0080) >> 7); +} + +UINT8 __fastcall CodemastersEEPROMReadByte(UINT32 sekAddress) +{ + if (sekAddress & 1) return RamMisc->I2CMem & 1; + + bprintf(PRINT_NORMAL, _T("Codemasters Read Byte %x\n"), sekAddress); + + return 0; +} + +UINT16 __fastcall CodemastersEEPROMReadWord(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("Codemasters Read Word %x\n"), sekAddress); + + return 0; +} + +void __fastcall CodemastersEEPROMWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress & 1) { + RamMisc->I2CClk = (byteValue & 0x0002) >> 1; + RamMisc->I2CMem = (byteValue & 0x0001); + return; + } else { + RamMisc->I2CClk = (byteValue & 0x0002) >> 1; + RamMisc->I2CMem = (byteValue & 0x0001); + return; + } + + bprintf(PRINT_NORMAL, _T("Codemasters write byte value %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall CodemastersEEPROMWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("Codemasters write word value %04x to location %08x\n"), wordValue, sekAddress); +} + +void __fastcall MegadriveSRAMToggleWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + bprintf(PRINT_NORMAL, _T("SRam Toggle byte %02x to location %08x\n"), byteValue, sekAddress); +} + +void __fastcall MegadriveSRAMToggleWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + bprintf(PRINT_NORMAL, _T("SRam Toggle word value %04x to location %08x\n"), wordValue, sekAddress); +} + +static void MegadriveSetupSRAM() +{ + SRamSize = 0; + RamMisc->SRamStart = 0; + RamMisc->SRamEnd = 0; + RamMisc->SRamDetected = 0; + RamMisc->SRamHandlersInstalled = 0; + RamMisc->SRamActive = 0; + RamMisc->SRamReadOnly = 0; + RamMisc->SRamHasSerialEEPROM = 0; + MegadriveBackupRam = NULL; + + if ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_00400) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_00800) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_01000) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_04000) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_10000)) { + RamMisc->SRamStart = 0x200000; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_00400) RamMisc->SRamEnd = 0x2003ff; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_00800) RamMisc->SRamEnd = 0x2007ff; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_01000) RamMisc->SRamEnd = 0x200fff; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_04000) RamMisc->SRamEnd = 0x203fff; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_SRAM_10000) RamMisc->SRamEnd = 0x20ffff; + + RamMisc->SRamDetected = 1; + MegadriveBackupRam = (UINT16*)RomMain + RamMisc->SRamStart; + + SekOpen(0); + SekMapHandler(5, 0xa130f0, 0xa130f1, SM_WRITE); + SekSetWriteByteHandler(5, MegadriveSRAMToggleWriteByte); + SekSetWriteWordHandler(5, MegadriveSRAMToggleWriteWord); + SekClose(); + + if (RomSize <= RamMisc->SRamStart) { + RamMisc->SRamActive = 1; + InstallSRAMHandlers(false); + } + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_BEGGAR) { + RamMisc->SRamStart = 0x400000; + RamMisc->SRamEnd = 0x40ffff; + + RamMisc->SRamDetected = 1; + MegadriveBackupRam = (UINT16*)RomMain + RamMisc->SRamStart; + + RamMisc->SRamActive = 1; + InstallSRAMHandlers(false); + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MEGADRIVE_FRAM_00400) { + RamMisc->SRamStart = 0x200000; + RamMisc->SRamEnd = 0x2003ff; + + RamMisc->SRamDetected = 1; + MegadriveBackupRam = (UINT16*)RomMain + RamMisc->SRamStart; + + SekOpen(0); + SekMapHandler(5, 0xa130f0, 0xa130f1, SM_READ | SM_WRITE); + SekSetReadByteHandler(5, Megadrive6658ARegReadByte); + SekSetReadWordHandler(5, Megadrive6658ARegReadWord); + SekSetWriteByteHandler(5, Megadrive6658ARegWriteByte); + SekSetWriteWordHandler(5, Megadrive6658ARegWriteWord); + SekClose(); + + InstallSRAMHandlers(false); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM) { + RamMisc->SRamHasSerialEEPROM = 1; + SekOpen(0); + SekMapHandler(5, 0x200000, 0x200001, SM_READ | SM_WRITE); + SekSetReadByteHandler(5, WboyVEEPROMReadByte); + SekSetReadWordHandler(5, WboyVEEPROMReadWord); + SekSetWriteByteHandler(5, WboyVEEPROMWriteByte); + SekSetWriteWordHandler(5, WboyVEEPROMWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM) { + RamMisc->SRamHasSerialEEPROM = 1; + SekOpen(0); + SekMapHandler(5, 0x200000, 0x200001, SM_READ | SM_WRITE); + SekSetReadByteHandler(5, NbajamEEPROMReadByte); + SekSetReadWordHandler(5, NbajamEEPROMReadWord); + SekSetWriteByteHandler(5, NbajamEEPROMWriteByte); + SekSetWriteWordHandler(5, NbajamEEPROMWriteWord); + SekClose(); + } + + if (((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE) || ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_NFL_QB_96) || ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_C_SLAM)) { + RamMisc->SRamHasSerialEEPROM = 1; + SekOpen(0); + SekMapHandler(5, 0x200000, 0x200001, SM_READ | SM_WRITE); + SekSetReadByteHandler(5, NbajamteEEPROMReadByte); + SekSetReadWordHandler(5, NbajamteEEPROMReadWord); + SekSetWriteByteHandler(5, NbajamteEEPROMWriteByte); + SekSetWriteWordHandler(5, NbajamteEEPROMWriteWord); + SekClose(); + } + + if ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA) { + RamMisc->SRamHasSerialEEPROM = 1; + SekOpen(0); + SekMapHandler(5, 0x200000, 0x200001, SM_READ | SM_WRITE); + SekSetReadByteHandler(5, EANhlpaEEPROMReadByte); + SekSetReadWordHandler(5, EANhlpaEEPROMReadWord); + SekSetWriteByteHandler(5, EANhlpaEEPROMWriteByte); + SekSetWriteWordHandler(5, EANhlpaEEPROMWriteWord); + SekClose(); + } + + if (((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_CODE_MASTERS) || ((BurnDrvGetHardwareCode() & 0xff) == HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM)) { + RamMisc->SRamHasSerialEEPROM = 1; + SekOpen(0); + SekMapHandler(5, 0x300000, 0x300001, SM_WRITE); + SekSetWriteByteHandler(5, CodemastersEEPROMWriteByte); + SekSetWriteWordHandler(5, CodemastersEEPROMWriteWord); + SekMapHandler(6, 0x380000, 0x380001, SM_READ); + SekSetReadByteHandler(6, CodemastersEEPROMReadByte); + SekSetReadWordHandler(6, CodemastersEEPROMReadWord); + SekClose(); + } + + if (!RamMisc->SRamDetected && !RamMisc->SRamHasSerialEEPROM) { + // check if cart has battery save + if (RomMain[0x1b1] == 'R' && RomMain[0x1b0] == 'A') { + // SRAM info found in header + RamMisc->SRamStart = (RomMain[0x1b5] << 24 | RomMain[0x1b4] << 16 | RomMain[0x1b7] << 8 | RomMain[0x1b6]); + RamMisc->SRamEnd = (RomMain[0x1b9] << 24 | RomMain[0x1b8] << 16 | RomMain[0x1bb] << 8 | RomMain[0x1ba]); + + if ((RamMisc->SRamStart > RamMisc->SRamEnd) || ((RamMisc->SRamEnd - RamMisc->SRamStart) >= 0x10000)) { + RamMisc->SRamEnd = RamMisc->SRamStart + 0x0FFFF; + } + + // for some games using serial EEPROM, difference between SRAM end to start is 0 or 1. Currently EEPROM is not emulated. + if ((RamMisc->SRamEnd - RamMisc->SRamStart) < 2) { + RamMisc->SRamHasSerialEEPROM = 1; + } else { + RamMisc->SRamDetected = 1; + } + } else { + // set default SRAM positions, with size = 64k + RamMisc->SRamStart = 0x200000; + RamMisc->SRamEnd = RamMisc->SRamStart + 0xffff; + } + + if (RamMisc->SRamStart & 1) RamMisc->SRamStart -= 1; + + if (!(RamMisc->SRamEnd & 1)) RamMisc->SRamEnd += 1; + + // calculate backup RAM location + MegadriveBackupRam = (UINT16*) (RomMain + (RamMisc->SRamStart & 0x3fffff)); + + if (RamMisc->SRamDetected) { + bprintf(PRINT_IMPORTANT, _T("SRAM detected in header: start %06x - end %06x\n"), RamMisc->SRamStart, RamMisc->SRamEnd); + } + + // Enable SRAM handlers only if the game does not use EEPROM. + if (!RamMisc->SRamHasSerialEEPROM) { + // Info from DGen: If SRAM does not overlap main ROM, set it active by default since a few games can't manage to properly switch it on/off. + if (RomSize <= RamMisc->SRamStart) { + RamMisc->SRamActive = 1; + } + + SekOpen(0); + SekMapHandler(5, 0xa130f0, 0xa130f1, SM_WRITE); + SekSetWriteByteHandler(5, MegadriveSRAMToggleWriteByte); + SekSetWriteWordHandler(5, MegadriveSRAMToggleWriteWord); + SekClose(); + + // Sonic 1 included in Sonic Classics doesn't have SRAM and does lots of ROM access at this range, then only install read write handlers if SRAM is active to not slow down emulation. + if (RamMisc->SRamActive) InstallSRAMHandlers(true); + } + } +} + +INT32 MegadriveInit() +{ + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + MegadriveLoadRoms(0); + MegadriveLoadRoms(1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(RomMain, 0x000000, 0x3FFFFF, SM_ROM); // 68000 ROM + SekMapMemory(Ram68K, 0xFF0000, 0xFFFFFF, SM_RAM); // 68000 RAM + + SekMapHandler(1, 0xC00000, 0xC0001F, SM_RAM); // Video Port + SekMapHandler(2, 0xA00000, 0xA01FFF, SM_RAM); // Z80 Ram + SekMapHandler(3, 0xA02000, 0xA03FFF, SM_RAM); // Z80 Ram + SekMapHandler(4, 0xA10000, 0xA1001F, SM_RAM); // I/O + + SekSetReadByteHandler (0, MegadriveReadByte); + SekSetReadWordHandler (0, MegadriveReadWord); + SekSetWriteByteHandler(0, MegadriveWriteByte); + SekSetWriteWordHandler(0, MegadriveWriteWord); + + SekSetReadByteHandler (1, MegadriveVideoReadByte); + SekSetReadWordHandler (1, MegadriveVideoReadWord); + SekSetWriteByteHandler(1, MegadriveVideoWriteByte); + SekSetWriteWordHandler(1, MegadriveVideoWriteWord); + + SekSetReadByteHandler (2, MegadriveZ80RamReadByte); + SekSetReadWordHandler (2, MegadriveZ80RamReadWord); + SekSetWriteByteHandler(2, MegadriveZ80RamWriteByte); + SekSetWriteWordHandler(2, MegadriveZ80RamWriteWord); + + SekSetReadByteHandler (3, MegadriveZ80RamReadByte); + SekSetReadWordHandler (3, MegadriveZ80RamReadWord); + SekSetWriteByteHandler(3, MegadriveZ80RamWriteByte); + SekSetWriteWordHandler(3, MegadriveZ80RamWriteWord); + + SekSetReadByteHandler (4, MegadriveIOReadByte); + SekSetReadWordHandler (4, MegadriveIOReadWord); + SekSetWriteByteHandler(4, MegadriveIOWriteByte); + SekSetWriteWordHandler(4, MegadriveIOWriteWord); + + SekSetIrqCallback( MegadriveIrqCallback ); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x1FFF, 0, RamZ80); + ZetMapArea(0x0000, 0x1FFF, 1, RamZ80); + ZetMapArea(0x0000, 0x1FFF, 2, RamZ80); + + ZetMapArea(0x2000, 0x3FFF, 0, RamZ80); + ZetMapArea(0x2000, 0x3FFF, 1, RamZ80); + ZetMapArea(0x2000, 0x3FFF, 2, RamZ80); + + ZetMemEnd(); + + ZetSetReadHandler(MegadriveZ80ProgRead); + ZetSetWriteHandler(MegadriveZ80ProgWrite); + ZetSetInHandler(MegadriveZ80PortRead); + ZetSetOutHandler(MegadriveZ80PortWrite); + ZetClose(); + } + + // OSC_NTSC / 7 + BurnSetRefreshRate(60.0); + + DrvSECAM = 0; + BurnYM2612Init(1, OSC_NTSC / 7, NULL, MegadriveSynchroniseStream, MegadriveGetTime, 0); + BurnTimerAttachSek(OSC_NTSC / 7); + + SN76496Init(0, OSC_NTSC / 15, 1); + + MegadriveSetupSRAM(); + SetupCustomCartridgeMappers(); + + if (MegadriveCallback) MegadriveCallback(); + + pBurnDrvPalette = (UINT32*)MegadriveCurPal; + + MegadriveResetDo(); + + return 0; +} + +INT32 MegadriveExit() +{ + SekExit(); + ZetExit(); + + BurnYM2612Exit(); + SN76496Exit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + if (OriginalRom) { + free(OriginalRom); + OriginalRom = NULL; + } + + MegadriveCallback = NULL; + cycles_68k = 0; + cycles_z80 = 0; + RomNoByteswap = 0; + MegadriveReset = 0; + RomSize = 0; + RomNum = 0; + SRamSize = 0; + Scanline = 0; + Z80HasBus = 0; + MegadriveZ80Reset = 0; + Hardware = 0; + DrvSECAM = 0; + HighCol = NULL; + + return 0; +} + +//--------------------------------------------------------------- +// Megadrive Draw +//--------------------------------------------------------------- + +static INT32 TileNorm(INT32 sx,INT32 addr,INT32 pal) +{ + UINT8 *pd = HighCol+sx; + UINT32 pack=0; + UINT32 t=0; + + pack = *(UINT32 *)(RamVid + addr); // Get 8 pixels + if (pack) { + t=pack&0x0000f000; if (t) pd[0]=(UINT8)(pal|(t>>12)); + t=pack&0x00000f00; if (t) pd[1]=(UINT8)(pal|(t>> 8)); + t=pack&0x000000f0; if (t) pd[2]=(UINT8)(pal|(t>> 4)); + t=pack&0x0000000f; if (t) pd[3]=(UINT8)(pal|(t )); + t=pack&0xf0000000; if (t) pd[4]=(UINT8)(pal|(t>>28)); + t=pack&0x0f000000; if (t) pd[5]=(UINT8)(pal|(t>>24)); + t=pack&0x00f00000; if (t) pd[6]=(UINT8)(pal|(t>>20)); + t=pack&0x000f0000; if (t) pd[7]=(UINT8)(pal|(t>>16)); + return 0; + } + return 1; // Tile blank +} + +static INT32 TileFlip(INT32 sx,INT32 addr,INT32 pal) +{ + UINT8 *pd = HighCol+sx; + UINT32 pack=0; + UINT32 t=0; + + pack = *(UINT32 *)(RamVid + addr); // Get 8 pixels + if (pack) { + t=pack&0x000f0000; if (t) pd[0]=(UINT8)(pal|(t>>16)); + t=pack&0x00f00000; if (t) pd[1]=(UINT8)(pal|(t>>20)); + t=pack&0x0f000000; if (t) pd[2]=(UINT8)(pal|(t>>24)); + t=pack&0xf0000000; if (t) pd[3]=(UINT8)(pal|(t>>28)); + t=pack&0x0000000f; if (t) pd[4]=(UINT8)(pal|(t )); + t=pack&0x000000f0; if (t) pd[5]=(UINT8)(pal|(t>> 4)); + t=pack&0x00000f00; if (t) pd[6]=(UINT8)(pal|(t>> 8)); + t=pack&0x0000f000; if (t) pd[7]=(UINT8)(pal|(t>>12)); + return 0; + } + return 1; // Tile blank +} + +// tile renderers for hacky operator sprite support +#define sh_pix(x) \ + if(!t); \ + else if(t==0xe) pd[x]=(UINT8)((pd[x]&0x3f)|0x80); /* hilight */ \ + else if(t==0xf) pd[x]=(UINT8)((pd[x]&0x3f)|0xc0); /* shadow */ \ + else pd[x]=(UINT8)(pal|t); + +static INT32 TileNormSH(INT32 sx,INT32 addr,INT32 pal) +{ + UINT32 pack=0; UINT32 t=0; + UINT8 *pd = HighCol+sx; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=(pack&0x0000f000)>>12; sh_pix(0); + t=(pack&0x00000f00)>> 8; sh_pix(1); + t=(pack&0x000000f0)>> 4; sh_pix(2); + t=(pack&0x0000000f) ; sh_pix(3); + t=(pack&0xf0000000)>>28; sh_pix(4); + t=(pack&0x0f000000)>>24; sh_pix(5); + t=(pack&0x00f00000)>>20; sh_pix(6); + t=(pack&0x000f0000)>>16; sh_pix(7); + return 0; + } + return 1; // Tile blank +} + +static INT32 TileFlipSH(INT32 sx,INT32 addr,INT32 pal) +{ + UINT32 pack=0; UINT32 t=0; + UINT8 *pd = HighCol+sx; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=(pack&0x000f0000)>>16; sh_pix(0); + t=(pack&0x00f00000)>>20; sh_pix(1); + t=(pack&0x0f000000)>>24; sh_pix(2); + t=(pack&0xf0000000)>>28; sh_pix(3); + t=(pack&0x0000000f) ; sh_pix(4); + t=(pack&0x000000f0)>> 4; sh_pix(5); + t=(pack&0x00000f00)>> 8; sh_pix(6); + t=(pack&0x0000f000)>>12; sh_pix(7); + return 0; + } + return 1; // Tile blank +} + +static INT32 TileNormZ(INT32 sx,INT32 addr,INT32 pal,INT32 zval) +{ + UINT32 pack=0; + UINT32 t=0; + UINT8 *pd = HighCol+sx; + INT8 *zb = HighSprZ+sx; + INT32 collision = 0, zb_s; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=pack&0x0000f000; if(t) { zb_s=zb[0]; if(zb_s) collision=1; if(zval>zb_s) { pd[0]=(UINT8)(pal|(t>>12)); zb[0]=(INT8)zval; } } + t=pack&0x00000f00; if(t) { zb_s=zb[1]; if(zb_s) collision=1; if(zval>zb_s) { pd[1]=(UINT8)(pal|(t>> 8)); zb[1]=(INT8)zval; } } + t=pack&0x000000f0; if(t) { zb_s=zb[2]; if(zb_s) collision=1; if(zval>zb_s) { pd[2]=(UINT8)(pal|(t>> 4)); zb[2]=(INT8)zval; } } + t=pack&0x0000000f; if(t) { zb_s=zb[3]; if(zb_s) collision=1; if(zval>zb_s) { pd[3]=(UINT8)(pal|(t )); zb[3]=(INT8)zval; } } + t=pack&0xf0000000; if(t) { zb_s=zb[4]; if(zb_s) collision=1; if(zval>zb_s) { pd[4]=(UINT8)(pal|(t>>28)); zb[4]=(INT8)zval; } } + t=pack&0x0f000000; if(t) { zb_s=zb[5]; if(zb_s) collision=1; if(zval>zb_s) { pd[5]=(UINT8)(pal|(t>>24)); zb[5]=(INT8)zval; } } + t=pack&0x00f00000; if(t) { zb_s=zb[6]; if(zb_s) collision=1; if(zval>zb_s) { pd[6]=(UINT8)(pal|(t>>20)); zb[6]=(INT8)zval; } } + t=pack&0x000f0000; if(t) { zb_s=zb[7]; if(zb_s) collision=1; if(zval>zb_s) { pd[7]=(UINT8)(pal|(t>>16)); zb[7]=(INT8)zval; } } + if(collision) RamVReg->status |= 0x20; + return 0; + } + return 1; // Tile blank +} + +static INT32 TileFlipZ(INT32 sx,INT32 addr,INT32 pal,INT32 zval) +{ + UINT32 pack=0; + UINT32 t=0; + UINT8 *pd = HighCol+sx; + INT8 *zb = HighSprZ+sx; + INT32 collision = 0, zb_s; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=pack&0x000f0000; if(t) { zb_s=zb[0]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[0]=(UINT8)(pal|(t>>16)); zb[0]=(INT8)zval; } } + t=pack&0x00f00000; if(t) { zb_s=zb[1]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[1]=(UINT8)(pal|(t>>20)); zb[1]=(INT8)zval; } } + t=pack&0x0f000000; if(t) { zb_s=zb[2]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[2]=(UINT8)(pal|(t>>24)); zb[2]=(INT8)zval; } } + t=pack&0xf0000000; if(t) { zb_s=zb[3]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[3]=(UINT8)(pal|(t>>28)); zb[3]=(INT8)zval; } } + t=pack&0x0000000f; if(t) { zb_s=zb[4]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[4]=(UINT8)(pal|(t )); zb[4]=(INT8)zval; } } + t=pack&0x000000f0; if(t) { zb_s=zb[5]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[5]=(UINT8)(pal|(t>> 4)); zb[5]=(INT8)zval; } } + t=pack&0x00000f00; if(t) { zb_s=zb[6]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[6]=(UINT8)(pal|(t>> 8)); zb[6]=(INT8)zval; } } + t=pack&0x0000f000; if(t) { zb_s=zb[7]&0x1f; if(zb_s) collision=1; if(zval>zb_s) { pd[7]=(UINT8)(pal|(t>>12)); zb[7]=(INT8)zval; } } + if(collision) RamVReg->status |= 0x20; + return 0; + } + return 1; // Tile blank +} + + +#define sh_pixZ(x) \ + if(t) { \ + if(zb[x]) collision=1; \ + if(zval>zb[x]) { \ + if (t==0xe) { pd[x]=(UINT8)((pd[x]&0x3f)|0x80); /* hilight */ } \ + else if(t==0xf) { pd[x]=(UINT8)((pd[x]&0x3f)|0xc0); /* shadow */ } \ + else { zb[x]=(INT8)zval; pd[x]=(UINT8)(pal|t); } \ + } \ + } + +static INT32 TileNormZSH(INT32 sx,INT32 addr,INT32 pal,INT32 zval) +{ + UINT32 pack=0; + UINT32 t=0; + UINT8 *pd = HighCol+sx; + INT8 *zb = HighSprZ+sx; + INT32 collision = 0; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=(pack&0x0000f000)>>12; sh_pixZ(0); + t=(pack&0x00000f00)>> 8; sh_pixZ(1); + t=(pack&0x000000f0)>> 4; sh_pixZ(2); + t=(pack&0x0000000f) ; sh_pixZ(3); + t=(pack&0xf0000000)>>28; sh_pixZ(4); + t=(pack&0x0f000000)>>24; sh_pixZ(5); + t=(pack&0x00f00000)>>20; sh_pixZ(6); + t=(pack&0x000f0000)>>16; sh_pixZ(7); + if(collision) RamVReg->status |= 0x20; + return 0; + } + return 1; // Tile blank +} + +static INT32 TileFlipZSH(INT32 sx,INT32 addr,INT32 pal,INT32 zval) +{ + UINT32 pack=0; + UINT32 t=0; + UINT8 *pd = HighCol+sx; + INT8 *zb = HighSprZ+sx; + INT32 collision = 0; + + pack=*(UINT32 *)(RamVid+addr); // Get 8 pixels + if (pack) { + t=(pack&0x000f0000)>>16; sh_pixZ(0); + t=(pack&0x00f00000)>>20; sh_pixZ(1); + t=(pack&0x0f000000)>>24; sh_pixZ(2); + t=(pack&0xf0000000)>>28; sh_pixZ(3); + t=(pack&0x0000000f) ; sh_pixZ(4); + t=(pack&0x000000f0)>> 4; sh_pixZ(5); + t=(pack&0x00000f00)>> 8; sh_pixZ(6); + t=(pack&0x0000f000)>>12; sh_pixZ(7); + if(collision) RamVReg->status |= 0x20; + return 0; + } + return 1; // Tile blank +} + +static void DrawStrip(struct TileStrip *ts, INT32 sh) +{ + INT32 tilex=0,dx=0,ty=0,code=0,addr=0,cells; + INT32 oldcode=-1,blank=-1; // The tile we know is blank + INT32 pal=0; + + // Draw tiles across screen: + tilex = (-ts->hscroll)>>3; + ty = (ts->line&7)<<1; // Y-Offset into tile + dx = ((ts->hscroll-1)&7)+1; + cells = ts->cells; + if(dx != 8) cells++; // have hscroll, need to draw 1 cell more + + for (; cells; dx+=8,tilex++,cells--) { + INT32 zero=0; + + code=RamVid[ts->nametab + (tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + INT32 cval = code | (dx<<16) | (ty<<25); + if(code&0x1000) cval^=7<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<4; + addr+=ty; + if (code&0x1000) addr^=0xe; // Y-flip + pal=((code>>9)&0x30)|(sh<<6); + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; +} + +static void DrawStripVSRam(struct TileStrip *ts, INT32 plane) +{ + INT32 tilex=0,dx=0,ty=0,code=0,addr=0,cell=0,nametabadd=0; + INT32 oldcode=-1,blank=-1; // The tile we know is blank + INT32 pal=0,scan=Scanline; + + // Draw tiles across screen: + tilex=(-ts->hscroll)>>3; + dx=((ts->hscroll-1)&7)+1; + if(dx != 8) { + INT32 vscroll, line; + cell--; // have hscroll, start with negative cell + // also calculate intial VS stuff + vscroll = RamSVid[plane]; + + // Find the line in the name table + line = (vscroll+scan)&ts->line&0xffff; // ts->line is really ymask .. + nametabadd = (line>>3)<<(ts->line>>24); // .. and shift[width] + ty = (line&7)<<1; // Y-Offset into tile + } + + for (; cell < ts->cells; dx+=8,tilex++,cell++) { + INT32 zero=0; + + if((cell&1)==0) { + INT32 line,vscroll; + vscroll = RamSVid[plane+(cell&~1)]; + + // Find the line in the name table + line = (vscroll+scan)&ts->line&0xffff; // ts->line is really ymask .. + nametabadd = (line>>3)<<(ts->line>>24); // .. and shift[width] + ty = (line&7)<<1; // Y-Offset into tile + } + + code = RamVid[ts->nametab + nametabadd + (tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + INT32 cval = code | (dx<<16) | (ty<<25); + if(code&0x1000) cval^=7<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<4; + if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip + pal=((code>>9)&0x30); + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; +} + +static void DrawStripInterlace(struct TileStrip *ts) +{ + INT32 tilex=0,dx=0,ty=0,code=0,addr=0,cells; + INT32 oldcode=-1,blank=-1; // The tile we know is blank + INT32 pal=0; + + // Draw tiles across screen: + tilex=(-ts->hscroll)>>3; + ty=(ts->line&15)<<1; // Y-Offset into tile + dx=((ts->hscroll-1)&7)+1; + cells = ts->cells; + if(dx != 8) cells++; // have hscroll, need to draw 1 cell more + + for (; cells; dx+=8,tilex++,cells--) { + INT32 zero=0; + + code=RamVid[ts->nametab+(tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + INT32 cval = (code&0xfc00) | (dx<<16) | (ty<<25); + cval |= (code&0x3ff)<<1; + if(code&0x1000) cval^=0xf<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<5; + if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip + pal=((code>>9)&0x30); + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; +} + +static void DrawLayer(INT32 plane, INT32 *hcache, INT32 maxcells, INT32 sh) +{ + const INT8 shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps (2 is invalid) + struct TileStrip ts; + INT32 width, height, ymask; + INT32 vscroll, htab; + + ts.hc = hcache; + ts.cells = maxcells; + + // Work out the TileStrip to draw + + // Work out the name table size: 32 64 or 128 tiles (0-3) + width = RamVReg->reg[16]; + height = (width>>4)&3; + width &= 3; + + ts.xmask=(1<1) ymask =0x0ff; + + // Find name table: + if (plane==0) ts.nametab=(RamVReg->reg[2] & 0x38)<< 9; // A + else ts.nametab=(RamVReg->reg[4] & 0x07)<<12; // B + + htab = RamVReg->reg[13] << 9; // Horizontal scroll table address + if ( RamVReg->reg[11] & 2) htab += Scanline<<1; // Offset by line + if ((RamVReg->reg[11] & 1)==0) htab &= ~0xf; // Offset by tile + htab += plane; // A or B + + // Get horizontal scroll value, will be masked later + ts.hscroll = RamVid[htab & 0x7fff]; + + if((RamVReg->reg[12]&6) == 6) { + // interlace mode 2 + vscroll = RamSVid[plane]; // Get vertical scroll value + + // Find the line in the name table + ts.line=(vscroll+(Scanline<<1))&((ymask<<1)|1); + ts.nametab+=(ts.line>>4)<reg[11]&4) { + // shit, we have 2-cell column based vscroll + // luckily this doesn't happen too often + ts.line = ymask | (shift[width]<<24); // save some stuff instead of line + DrawStripVSRam(&ts, plane); + } else { + vscroll = RamSVid[plane]; // Get vertical scroll value + + // Find the line in the name table + ts.line = (vscroll+Scanline)&ymask; + ts.nametab += (ts.line>>3)<reg[3] & 0x3c)<<9; + if (RamVReg->reg[12] & 1) nametab += (Scanline>>3)<<6; // 40-cell mode + else nametab += (Scanline>>3)<<5; // 32-cell mode + + tilex = tstart<<1; + tend <<= 1; + + ty = (Scanline & 7)<<1; // Y-Offset into tile + + if(!(rendstatus & 2)) { + // check the first tile code + code = RamVid[nametab + tilex]; + // if the whole window uses same priority (what is often the case), we may be able to skip this field + if((code>>15) != prio) return; + } + + // Draw tiles across screen: + for (; tilex < tend; tilex++) { + INT32 addr=0, zero=0, pal; + + code = RamVid[nametab + tilex]; + if(code==blank) continue; + if((code>>15) != prio) { + rendstatus |= 2; + continue; + } + + pal=((code>>9)&0x30); + + if(sh) { + INT32 tmp, *zb = (INT32 *)(HighCol+8+(tilex<<3)); + if(prio) { + tmp = *zb; + if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000; + if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000; + *zb++=tmp; tmp = *zb; + if(!(tmp&0x00000080)) tmp&=~0x000000c0; if(!(tmp&0x00008000)) tmp&=~0x0000c000; + if(!(tmp&0x00800000)) tmp&=~0x00c00000; if(!(tmp&0x80000000)) tmp&=~0xc0000000; + *zb++=tmp; + } else { + pal |= 0x40; + } + } + + // Get tile address/2: + addr = (code&0x7ff)<<4; + if (code&0x1000) addr += 14-ty; else addr += ty; // Y-flip + + if (code&0x0800) zero = TileFlip(8+(tilex<<3),addr,pal); + else zero = TileNorm(8+(tilex<<3),addr,pal); + + if (zero) blank = code; // We know this tile is blank now + } + // terminate the cache list + //*hcache = 0; +} + +static void DrawTilesFromCache(INT32 *hc, INT32 sh) +{ + INT32 code, addr, zero, dx; + INT32 pal; + INT16 blank=-1; // The tile we know is blank + + // *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it + + while((code = *hc++)) { + if(!sh && (INT16)code == blank) continue; + + // Get tile address/2: + addr=(code&0x7ff)<<4; + addr+=(UINT32)code>>25; // y offset into tile + dx=(code>>16)&0x1ff; + if(sh) { + UINT8 *zb = HighCol+dx; + if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++; + if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++; + if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++; + if(!(*zb&0x80)) *zb&=0x3f; zb++; if(!(*zb&0x80)) *zb&=0x3f; zb++; + } + + pal=((code>>9)&0x30); + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if(zero) blank=(INT16)code; + } +} + +// Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size +// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + +static void DrawSprite(INT32 *sprite, INT32 **hc, INT32 sh) +{ + INT32 width=0,height=0; + INT32 row=0,code=0; + INT32 pal; + INT32 tile=0,delta=0; + INT32 sx, sy; + INT32 (*fTileFunc)(INT32 sx,INT32 addr,INT32 pal); + + // parse the sprite data + sy=sprite[0]; + code=sprite[1]; + sx=code>>16; // X + width=sy>>28; + height=(sy>>24)&7; // Width and height in tiles + sy=(sy<<16)>>16; // Y + + row=Scanline-sy; // Row of the sprite we are on + + if (code&0x1000) row=(height<<3)-1-row; // Flip Y + + tile=code&0x7ff; // Tile number + tile+=row>>3; // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile<<=4; tile+=(row&7)<<1; // Tile address + + if(code&0x8000) { // high priority - cache it + *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>16)&0xf); + } else { + delta<<=4; // Delta of address + pal=((code>>9)&0x30)|(sh<<6); + + if(sh && (code&0x6000) == 0x6000) { + if(code&0x0800) fTileFunc=TileFlipSH; + else fTileFunc=TileNormSH; + } else { + if(code&0x0800) fTileFunc=TileFlip; + else fTileFunc=TileNorm; + } + + for (; width; width--,sx+=8,tile+=delta) { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal); + } + } +} + +// Index + 0 : hhhhvvvv s---hhvv yyyyyyyy yyyyyyyy // s: skip flag, h: horiz. size +// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + +static void DrawSpriteZ(INT32 pack, INT32 pack2, INT32 shpri, INT32 sprio) +{ + INT32 width=0,height=0; + INT32 row=0; + INT32 pal; + INT32 tile=0,delta=0; + INT32 sx, sy; + INT32 (*fTileFunc)(INT32 sx,INT32 addr,INT32 pal,INT32 zval); + + // parse the sprite data + sx = pack2>>16; // X + sy = (pack <<16)>>16; // Y + width = pack >>28; + height= (pack >>24)&7; // Width and height in tiles + + row = Scanline-sy; // Row of the sprite we are on + + if (pack2&0x1000) row=(height<<3)-1-row; // Flip Y + + tile = pack2&0x7ff; // Tile number + tile+= row>>3; // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (pack2&0x0800) { // Flip X + tile += delta*(width-1); + delta = -delta; + } + + tile<<=4; + tile+=(row&7)<<1; // Tile address + delta<<=4; // Delta of address + pal=((pack2>>9)&0x30); + if((shpri&1)&&!(shpri&2)) pal|=0x40; + + shpri&=1; + if((pack2&0x6000) != 0x6000) shpri = 0; + shpri |= (pack2&0x0800)>>10; + switch(shpri) { + default: + case 0: fTileFunc=TileNormZ; break; + case 1: fTileFunc=TileNormZSH; break; + case 2: fTileFunc=TileFlipZ; break; + case 3: fTileFunc=TileFlipZSH; break; + } + + for (; width; width--,sx+=8,tile+=delta) { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal,sprio); + } +} + + +static void DrawSpriteInterlace(UINT32 *sprite) +{ + INT32 width=0,height=0; + INT32 row=0,code=0; + INT32 pal; + INT32 tile=0,delta=0; + INT32 sx, sy; + + // parse the sprite data + sy=sprite[0]; + height=sy>>24; + sy=(sy&0x3ff)-0x100; // Y + width=(height>>2)&3; height&=3; + width++; height++; // Width and height in tiles + + row=(Scanline<<1)-sy; // Row of the sprite we are on + + code=sprite[1]; + sx=((code>>16)&0x1ff)-0x78; // X + + if (code&0x1000) row^=(16<>4; // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile<<=5; tile+=(row&15)<<1; // Tile address + + delta<<=5; // Delta of address + pal=((code>>9)&0x30); // Get palette pointer + + for (; width; width--,sx+=8,tile+=delta) { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + if (code&0x0800) TileFlip(sx,tile,pal); + else TileNorm(sx,tile,pal); + } +} + + +static void DrawAllSpritesInterlace(INT32 pri, INT32 maxwidth) +{ + INT32 i,u,table,link=0,sline=Scanline<<1; + UINT32 *sprites[80]; // Sprite index + + table = RamVReg->reg[5]&0x7f; + if (RamVReg->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + table<<=8; // Get sprite table address/2 + + for (i=u=0; u < 80 && i < 21; u++) { + UINT32 *sprite; + INT32 code, sx, sy, height; + + sprite=(UINT32 *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite + + // get sprite info + code = sprite[0]; + sx = sprite[1]; + if(((sx>>15)&1) != pri) goto nextsprite; // wrong priority sprite + + // check if it is on this line + sy = (code&0x3ff)-0x100; + height = (((code>>24)&3)+1)<<4; + if(sline < sy || sline >= sy+height) goto nextsprite; // no + + // check if sprite is not hidden offscreen + sx = (sx>>16)&0x1ff; + sx -= 0x78; // Get X coordinate + 8 + if(sx <= -8*3 || sx >= maxwidth) goto nextsprite; + + // sprite is good, save it's pointer + sprites[i++]=sprite; + + nextsprite: + // Find next sprite + link=(code>>16)&0x7f; + if(!link) break; // End of sprites + } + + // Go through sprites backwards: + for (i-- ;i>=0; i--) + DrawSpriteInterlace(sprites[i]); +} + +static void DrawSpritesFromCache(INT32 *hc, INT32 sh) +{ + INT32 code, tile, sx, delta, width; + INT32 pal; + INT32 (*fTileFunc)(INT32 sx,INT32 addr,INT32 pal); + + // *(*hc)++ = (tile<<16)|((code&0x0800)<<5)|((sx<<6)&0x0000ffc0)|((code>>9)&0x30)|((sprite[0]>>24)&0xf); + + while((code=*hc++)) { + pal=(code&0x30); + delta=code&0xf; + width=delta>>2; delta&=3; + width++; delta++; // Width and height in tiles + if (code&0x10000) delta=-delta; // Flip X + delta<<=4; + tile=((UINT32)code>>17)<<1; + sx=(code<<16)>>22; // sx can be negative (start offscreen), so sign extend + + if(sh && pal == 0x30) { // + if(code&0x10000) fTileFunc=TileFlipSH; + else fTileFunc=TileNormSH; + } else { + if(code&0x10000) fTileFunc=TileFlip; + else fTileFunc=TileNorm; + } + + for (; width; width--,sx+=8,tile+=delta) { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal); + } + } +} + +// Index + 0 : ----hhvv -lllllll -------y yyyyyyyy +// Index + 4 : -------x xxxxxxxx pccvhnnn nnnnnnnn +// v +// Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size +// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + +static void PrepareSprites(INT32 full) +{ + INT32 u=0,link=0,sblocks=0; + INT32 table=0; + INT32 *pd = HighPreSpr; + + table=RamVReg->reg[5]&0x7f; + if (RamVReg->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + table<<=8; // Get sprite table address/2 + + if (!full) { + INT32 pack; + // updates: tilecode, sx + for (u=0; u < 80 && (pack = *pd); u++, pd+=2) { + UINT32 *sprite; + INT32 code, code2, sx, sy, skip=0; + + sprite=(UINT32 *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite + + // parse sprite info + code = sprite[0]; + code2 = sprite[1]; + code2 &= ~0xfe000000; + code2 -= 0x00780000; // Get X coordinate + 8 in upper 16 bits + sx = code2>>16; + + if((sx <= 8-((pack>>28)<<3) && sx >= -0x76) || sx >= 328) skip=1<<23; + else if ((sy = (pack<<16)>>16) < 240 && sy > -32) { + INT32 sbl = (2<<(pack>>28))-1; + sblocks |= sbl<<(sy>>3); + } + + *pd = (pack&~(1<<23))|skip; + *(pd+1) = code2; + + // Find next sprite + link=(code>>16)&0x7f; + if(!link) break; // End of sprites + } + SpriteBlocks |= sblocks; + } else { + for (; u < 80; u++) { + UINT32 *sprite; + INT32 code, code2, sx, sy, hv, height, width, skip=0, sx_min; + + sprite=(UINT32 *)(RamVid+((table+(link<<2))&0x7ffc)); // Find sprite + + // parse sprite info + code = sprite[0]; + sy = (code&0x1ff)-0x80; + hv = (code>>24)&0xf; + height = (hv&3)+1; + + if(sy > 240 || sy + (height<<3) <= 0) skip|=1<<22; + + width = (hv>>2)+1; + code2 = sprite[1]; + sx = (code2>>16)&0x1ff; + sx -= 0x78; // Get X coordinate + 8 + sx_min = 8-(width<<3); + + if((sx <= sx_min && sx >= -0x76) || sx >= 328) skip|=1<<23; + else if (sx > sx_min && !skip) { + INT32 sbl = (2<>3; + if(shi < 0) shi=0; // negative sy + sblocks |= sbl<>16)&0x7f; + if(!link) break; // End of sprites + } + SpriteBlocks = sblocks; + *pd = 0; // terminate + } +} + +static void DrawAllSprites(INT32 *hcache, INT32 maxwidth, INT32 prio, INT32 sh) +{ + INT32 i,u,n; + INT32 sx1seen=0; // sprite with x coord 1 or 0 seen + INT32 ntiles = 0; // tile counter for sprite limit emulation + INT32 *sprites[40]; // Sprites to draw in fast mode + INT32 *ps, pack, rs = rendstatus, scan=Scanline; + + if(rs&8) { + DrawAllSpritesInterlace(prio, maxwidth); + return; + } + if(rs&0x11) { + //dprintf("PrepareSprites(%i) [%i]", (rs>>4)&1, scan); + PrepareSprites(rs&0x10); + rendstatus=rs&~0x11; + } + if (!(SpriteBlocks & (1<<(scan>>3)))) return; + + if(((rs&4)||sh)&&prio==0) + memset(HighSprZ, 0, 328); + if(!(rs&4)&&prio) { + if(hcache[0]) DrawSpritesFromCache(hcache, sh); + return; + } + + ps = HighPreSpr; + + // Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size + // Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + + for(i=u=n=0; (pack = *ps) && n < 20; ps+=2, u++) { + INT32 sx, sy, row, pack2; + + if(pack & 0x00400000) continue; + + // get sprite info + pack2 = *(ps+1); + sx = pack2>>16; + sy = (pack <<16)>>16; + row = scan-sy; + + //dprintf("x: %i y: %i %ix%i", sx, sy, (pack>>28)<<3, (pack>>21)&0x38); + + if(sx == -0x77) sx1seen |= 1; // for masking mode 2 + + // check if it is on this line + if(row < 0 || row >= ((pack>>21)&0x38)) continue; // no + n++; // number of sprites on this line (both visible and hidden, max is 20) [broken] + + // sprite limit + ntiles += pack>>28; + if(ntiles > 40) break; + + if(pack & 0x00800000) continue; + + // masking sprite? + if(sx == -0x78) { + if(!(sx1seen&1) || sx1seen==3) { + break; // this sprite is not drawn and remaining sprites are masked + } + if((sx1seen>>8) == 0) sx1seen=(i+1)<<8; + continue; + } + else if(sx == -0x77) { + // masking mode2 (Outrun, Galaxy Force II, Shadow of the beast) + if(sx1seen>>8) { + i=(sx1seen>>8)-1; + break; + } // seen both 0 and 1 + sx1seen |= 2; + continue; + } + + // accurate sprites + //dprintf("P:%i",((sx>>15)&1)); + if(rs&4) { + // might need to skip this sprite + if((pack2&0x8000) ^ (prio<<15)) continue; + DrawSpriteZ(pack,pack2,sh|(prio<<1),(INT8)(0x1f-n)); + continue; + } + + // sprite is good, save it's pointer + sprites[i++]=ps; + } + + // Go through sprites backwards: + if(!(rs&4)) { + for (i--; i>=0; i--) + DrawSprite(sprites[i],&hcache,sh); + + // terminate cache list + *hcache = 0; + } +} + + +static void BackFill(INT32 reg7, INT32 sh) +{ + // Start with a blank scanline (background colour): + UINT32 *pd = (UINT32 *)(HighCol+8); + UINT32 *end= (UINT32 *)(HighCol+8+320); + UINT32 back = reg7 & 0x3f; + back |= sh<<6; + back |= back<<8; + back |= back<<16; + do { pd[0]=pd[1]=pd[2]=pd[3]=back; pd+=4; } while (pd < end); +} + + +static INT32 DrawDisplay(INT32 sh) +{ + INT32 maxw, maxcells; + INT32 win=0, edge=0, hvwind=0; + + if(RamVReg->reg[12] & 1) { + maxw = 328; maxcells = 40; + } else { + maxw = 264; maxcells = 32; + } + + // Find out if the window is on this line: + win = RamVReg->reg[0x12]; + edge = (win & 0x1f)<<3; + + if (win&0x80) { if (Scanline>=edge) hvwind=1; } + else { if (Scanline< edge) hvwind=1; } + + if(!hvwind) { // we might have a vertical window here + win = RamVReg->reg[0x11]; + edge = win&0x1f; + if(win&0x80) { + if(!edge) hvwind=1; + else if(edge < (maxcells>>1)) hvwind=2; + } else { + if(!edge); + else if(edge < (maxcells>>1)) hvwind=2; + else hvwind=1; + } + } + + DrawLayer(1, HighCacheB, maxcells, sh); + if(hvwind == 1) + DrawWindow(0, maxcells>>1, 0, sh); // HighCacheAW + else if(hvwind == 2) { + // ahh, we have vertical window + DrawLayer(0, HighCacheA, (win&0x80) ? edge<<1 : maxcells, sh); + DrawWindow((win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh); // HighCacheW + } else + DrawLayer(0, HighCacheA, maxcells, sh); + DrawAllSprites(HighCacheS, maxw, 0, sh); + + if(HighCacheB[0]) + DrawTilesFromCache(HighCacheB, sh); + if(hvwind == 1) + DrawWindow(0, maxcells>>1, 1, sh); + else if(hvwind == 2) { + if(HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh); + DrawWindow((win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 1, sh); + } else + if(HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh); + DrawAllSprites(HighCacheS, maxw, 1, sh); + + return 0; +} + +static void PicoFrameStart() +{ + // prepare to do this frame + rendstatus = 0x80 >> 5; // accurate sprites + RamVReg->status &= ~0x0020; + if((RamVReg->reg[12]&6) == 6) rendstatus |= 8; // interlace mode + //if(Pico.m.dirtyPal) Pico.m.dirtyPal = 2; // reset dirty if needed + PrepareSprites(1); +} + +static INT32 PicoLine(INT32 /*scan*/) +{ + INT32 sh = (RamVReg->reg[0xC] & 8)>>3; // shadow/hilight? + + BackFill(RamVReg->reg[7], sh); + if (RamVReg->reg[1] & 0x40) + DrawDisplay(sh); + + { + INT32 num = Scanline + 1; + if (!(RamVReg->reg[1] & 8)) num += 8; + HighCol = HighColFull + ( num * (8 + 320 + 8) ); + }; + + return 0; +} + +static void MegadriveDraw() +{ + UINT16 * pDest = (UINT16 *)pBurnDraw; + + if ((RamVReg->reg[12]&1) || !(MegadriveDIP[1] & 0x03)) { + + for (INT32 j=0; j<224; j++) { + UINT8 * pSrc = HighColFull + (j+9)*(8+320+8) + 8; + for (INT32 i=0;i<320;i++) + pDest[i] = MegadriveCurPal[ pSrc[i] ]; + pDest += 320; + } + + } else { + + if (( MegadriveDIP[1] & 0x03 ) == 0x01 ) { + // Center + pDest += 32; + for (INT32 j=0; j<224; j++) { + UINT8 * pSrc = HighColFull + (j+9)*(8+320+8) + 8; + + memset((UINT8 *)pDest - 32*2, 0, 64); + + for (INT32 i=0;i<256;i++) + pDest[i] = MegadriveCurPal[ pSrc[i] ]; + + memset((UINT8 *)pDest + 256*2, 0, 64); + + pDest += 320; + } + } else { + // Zoom + for (INT32 j=0; j<224; j++) { + UINT8 * pSrc = HighColFull + (j+9)*(8+320+8) + 8; + UINT32 delta = 0; + for (INT32 i=0;i<320;i++) { + pDest[i] = MegadriveCurPal[ pSrc[ delta >> 16 ] ]; + delta += 0xCCCC; + } + pDest += 320; + } + } + + } +} + +#define TOTAL_68K_CYCLES ((double)OSC_NTSC / 7) / 60 +#define TOTAL_Z80_CYCLES ((double)OSC_NTSC / 15) / 60 +#define TOTAL_68K_CYCLES_PAL ((double)OSC_PAL / 7) / 50 +#define TOTAL_Z80_CYCLES_PAL ((double)OSC_PAL / 15) / 50 + +INT32 MegadriveFrame() +{ + INT32 nSoundBufferPos = 0; + + if (MegadriveReset) { + MegadriveResetDo(); + MegadriveReset = 0; + } + + if (bMegadriveRecalcPalette) { + for (INT32 i=0;i<0x40;i++) + CalcCol(i, RamPal[i]); + bMegadriveRecalcPalette = 0; + } + + JoyPad->pad[0] = JoyPad->pad[1] = JoyPad->pad[2] = JoyPad->pad[3] = 0; + for (INT32 i = 0; i < 12; i++) { + JoyPad->pad[0] |= (MegadriveJoy1[i] & 1) << i; + JoyPad->pad[1] |= (MegadriveJoy2[i] & 1) << i; + JoyPad->pad[2] |= (MegadriveJoy3[i] & 1) << i; + JoyPad->pad[3] |= (MegadriveJoy4[i] & 1) << i; + } + + + SekNewFrame(); + ZetNewFrame(); + + HighCol = HighColFull; + PicoFrameStart(); + + INT32 lines,lines_vis = 224,line_sample; + INT32 done_z80 = 0; + INT32 hint = RamVReg->reg[10]; // Hint counter + INT32 total_68k_cycles, total_z80_cycles; + + if( Hardware & 0x40 ) { + lines = 313; + line_sample = 68; + if( RamVReg->reg[1]&8 ) lines_vis = 240; + total_68k_cycles = (INT32)(INT64)(TOTAL_68K_CYCLES_PAL * nBurnCPUSpeedAdjust / 0x100); + total_z80_cycles = (INT32)TOTAL_Z80_CYCLES_PAL; + } else { + lines = 262; + line_sample = 93; + total_68k_cycles = (INT32)(INT64)(TOTAL_68K_CYCLES * nBurnCPUSpeedAdjust / 0x100); + total_z80_cycles = (INT32)TOTAL_Z80_CYCLES; + } + + cycles_68k = total_68k_cycles / lines; + cycles_z80 = total_z80_cycles / lines; + + RamVReg->status &= ~0x88; // clear V-Int, come out of vblank + + for (INT32 y=0; ypadDelay[0]++ > 25) JoyPad->padTHPhase[0] = 0; + if(JoyPad->padDelay[1]++ > 25) JoyPad->padTHPhase[1] = 0; + } + + // H-Interrupts: + if((y <= lines_vis) && (--hint < 0)) { // y <= lines_vis: Comix Zone, Golden Axe + //dprintf("rhint:old @ %06x", SekPc); + hint = RamVReg->reg[10]; // Reload H-Int counter + RamVReg->pending_ints |= 0x10; + if (RamVReg->reg[0] & 0x10) { + SekOpen(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + } + } + + // V-Interrupt: + if (y == lines_vis) { + //dprintf("vint: @ %06x [%i|%i]", SekPc, y, SekCycleCnt); + RamVReg->status |= 0x88; // V-Int happened, go into vblank + + // there must be a gap between H and V ints, also after vblank bit set (Mazin Saga, Bram Stoker's Dracula) + SekOpen(0); +// done_68k+=SekRun(128); + BurnTimerUpdate((y * cycles_68k) + 128 - cycles_68k); + SekClose(); + + RamVReg->pending_ints |= 0x20; + if(RamVReg->reg[1] & 0x20) { + SekOpen(0); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + } + } + + // decide if we draw this line + if ((!(RamVReg->reg[1]&8) && y<=224) || ((RamVReg->reg[1]&8) && y<240)) + PicoLine(y); + + // Run scanline + SekOpen(0); + BurnTimerUpdate(y * cycles_68k); + SekClose(); + + if (Z80HasBus && !MegadriveZ80Reset) { + ZetOpen(0); + done_z80 += ZetRun(cycles_z80); + if (y == line_sample) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (y == line_sample + 1) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + SekOpen(0); + BurnYM2612Update(pSoundBuf, nSegmentLength); + SekClose(); + SN76496Update(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnDraw) MegadriveDraw(); + + SekOpen(0); + BurnTimerEndFrame(total_68k_cycles); + SekClose(); + + if (Z80HasBus && !MegadriveZ80Reset) { + if (done_z80 < total_z80_cycles) { + ZetOpen(0); + ZetRun(total_z80_cycles - done_z80); + ZetClose(); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + SekOpen(0); + BurnYM2612Update(pSoundBuf, nSegmentLength); + SekClose(); + SN76496Update(0, pSoundBuf, nSegmentLength); + } + } + + return 0; +} + +INT32 MegadriveScan(INT32 /*nAction*/, INT32 * /*pnMin*/) +{ + //BurnYM2612Scan(nAction, pnMin); + + return 1; +} diff --git a/src/burn/drivers/megadrive/megadrive.h b/src/burn/drivers/megadrive/megadrive.h new file mode 100644 index 00000000..f4311e5f --- /dev/null +++ b/src/burn/drivers/megadrive/megadrive.h @@ -0,0 +1,25 @@ +#define SEGA_MD_ROM_LOAD_NORMAL 0x10 +#define SEGA_MD_ROM_LOAD16_WORD_SWAP 0x20 +#define SEGA_MD_ROM_LOAD16_BYTE 0x30 +#define SEGA_MD_ROM_LOAD16_WORD_SWAP_CONTINUE_040000_100000 0x40 +#define SEGA_MD_ROM_OFFS_000000 0x01 +#define SEGA_MD_ROM_OFFS_000001 0x02 +#define SEGA_MD_ROM_OFFS_020000 0x03 +#define SEGA_MD_ROM_OFFS_080000 0x04 +#define SEGA_MD_ROM_OFFS_100000 0x05 +#define SEGA_MD_ROM_OFFS_100001 0x06 +#define SEGA_MD_ROM_OFFS_200000 0x07 + +extern UINT8 MegadriveReset; +extern UINT8 bMegadriveRecalcPalette; +extern UINT8 MegadriveJoy1[12]; +extern UINT8 MegadriveJoy2[12]; +extern UINT8 MegadriveJoy3[12]; +extern UINT8 MegadriveJoy4[12]; +extern UINT8 MegadriveDIP[2]; +extern UINT16 *MegadriveCurPal; + +INT32 MegadriveInit(); +INT32 MegadriveExit(); +INT32 MegadriveFrame(); +INT32 MegadriveScan(INT32 nAction, INT32 *pnMin); diff --git a/src/burn/drivers/misc_post90s/d_1945kiii.cpp b/src/burn/drivers/misc_post90s/d_1945kiii.cpp new file mode 100644 index 00000000..b8bf47a2 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_1945kiii.cpp @@ -0,0 +1,483 @@ +// FB Alpha 1945K-III driver module +// Port to Finalburn Alpha by OopsWare. 2007 + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart; +static UINT8 *RamEnd; +static UINT8 *Rom68K; +static UINT8 *RomBg; +static UINT8 *RomSpr; +static UINT8 *Ram68K; +static UINT16 *RamPal; +static UINT16 *RamSpr0; +static UINT16 *RamSpr1; +static UINT16 *RamBg; + +static UINT32 *RamCurPal; +static UINT8 bRecalcPalette; + +static UINT16 *scrollx; +static UINT16 *scrolly; +static UINT8 *m6295bank; + +static UINT8 DrvReset; +static UINT8 DrvButton[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvJoy1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvJoy2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvInput[6] = { 0, 0, 0, 0, 0, 0 }; + +static struct BurnInputInfo _1945kiiiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 2, "p1 start" }, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 4" }, + + {"P2 Start", BIT_DIGITAL, DrvButton + 3, "p2 start" }, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 4, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvInput + 5, "dip" }, +}; + +STDINPUTINFO(_1945kiii) + +static struct BurnDIPInfo _1945kiiiDIPList[] = { + {0x14, 0xFF, 0xFF, 0xef, NULL }, + {0x15, 0xFF, 0xFF, 0xff, NULL }, + + {0, 0xFE, 0, 8, "Coin 1" }, + {0x14, 0x01, 0x07, 0x07, "1 coin 1 credit" }, + {0x14, 0x01, 0x07, 0x06, "2 coins 1 credit" }, + {0x14, 0x01, 0x07, 0x05, "3 coins 1 credit" }, + {0x14, 0x01, 0x07, 0x04, "1 coin 2 credits" }, + {0x14, 0x01, 0x07, 0x03, "Free Play" }, + {0x14, 0x01, 0x07, 0x02, "5 coins 1 credit" }, + {0x14, 0x01, 0x07, 0x01, "4 coins 1 credit" }, + {0x14, 0x01, 0x07, 0x00, "1 coin 3 credits" }, + {0, 0xFE, 0, 4, "Difficulty" }, + {0x14, 0x01, 0x18, 0x18, "Hardest" }, + {0x14, 0x01, 0x18, 0x10, "Hard" }, + {0x14, 0x01, 0x18, 0x08, "Normal" }, + {0x14, 0x01, 0x18, 0x00, "Easy" }, + {0, 0xFE, 0, 4, "Lives" }, + {0x14, 0x01, 0x60, 0x60, "3" }, + {0x14, 0x01, 0x60, 0x40, "2" }, + {0x14, 0x01, 0x60, 0x20, "4" }, + {0x14, 0x01, 0x60, 0x00, "5" }, + {0, 0xFE, 0, 2, "Service" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0, 0xFE, 0, 2, "Demo sound" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + {0, 0xFE, 0, 2, "Allow Continue" }, + {0x15, 0x01, 0x02, 0x02, "Yes" }, + {0x15, 0x01, 0x02, 0x00, "No" }, +}; + +STDDIPINFO(_1945kiii) + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x001F) << 3; + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; + g |= g >> 5; + b = (nColour & 0x7C00) >> 7; + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +static void sndSetBank(UINT8 bank0, UINT8 bank1) +{ + if (bank0 != m6295bank[0]) { + m6295bank[0] = bank0; + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[0][nChannel] = MSM6295ROM + 0x000000 + 0x040000 * bank0 + (nChannel << 8); + MSM6295SampleData[0][nChannel] = MSM6295ROM + 0x000000 + 0x040000 * bank0 + (nChannel << 16); + } + } + + if (bank1 != m6295bank[1]) { + m6295bank[1] = bank1; + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[1][nChannel] = MSM6295ROM + 0x080000 + 0x040000 * bank1 + (nChannel << 8); + MSM6295SampleData[1][nChannel] = MSM6295ROM + 0x080000 + 0x040000 * bank1 + (nChannel << 16); + } + } +} + +UINT16 __fastcall k1945iiiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0x400000: + return DrvInput[0] | (DrvInput[1] << 8); + + case 0x440000: + return DrvInput[2] | (DrvInput[3] << 8); + + case 0x480000: + return DrvInput[4] | (DrvInput[5] << 8); + + case 0x4C0000: + return MSM6295ReadStatus(0); + + case 0x500000: + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall k1945iiiWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) + { + case 0x4C0000: + MSM6295Command(0, byteValue); + return; + + case 0x500000: + MSM6295Command(1, byteValue); + return; + } +} + +void __fastcall k1945iiiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) + { + case 0x340000: + scrollx[0] = wordValue; + return; + + case 0x380000: + scrolly[0] = wordValue; + return; + + case 0x3C0000: + sndSetBank((wordValue & 2) >> 1, (wordValue & 4) >> 2); + return; + } +} + +void __fastcall k1945iiiWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress = (sekAddress & 0xffe) / 2; + RamPal[sekAddress] = wordValue; + if (sekAddress < 0x200) RamCurPal[sekAddress] = CalcCol(wordValue); +} + +static INT32 MemIndex() +{ + UINT8 *Next; + + Next = Mem; + + Rom68K = Next; Next += 0x0100000; + RomBg = Next; Next += 0x0200000; + RomSpr = Next; Next += 0x0400000; + MSM6295ROM = Next; Next += 0x0100000; + + RamCurPal = (UINT32 *) Next; Next += 0x00200 * sizeof(UINT32); + + RamStart = Next; + + Ram68K = Next; Next += 0x020000; + RamPal = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + RamSpr0 = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + RamSpr1 = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + RamBg = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + + m6295bank = Next; Next += 0x000002; + scrollx = (UINT16 *) Next; Next += 0x000001 * sizeof(UINT16); + scrolly = (UINT16 *) Next; Next += 0x000001 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + + m6295bank[0] = 1; + m6295bank[1] = 1; + sndSetBank(0, 0); + + return 0; +} + +static void decode_sprites() // Pixel order - 0,2,1,3 -> 0,1,2,3 +{ + for (INT32 i = 0; i < 0x400000; i+=4) { + UINT8 c = RomSpr[i+2]; + RomSpr[i+2] = RomSpr[i+1]; + RomSpr[i+1] = c; + } +} + +static INT32 DrvInit() +{ + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Rom68K + 0x00000, 0, 2)) return 1; + if (BurnLoadRom(Rom68K + 0x00001, 1, 2)) return 1; + + if (BurnLoadRom(RomSpr + 0x00000, 2, 2)) return 1; + if (BurnLoadRom(RomSpr + 0x00001, 3, 2)) return 1; + + if (BurnLoadRom(RomBg + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(MSM6295ROM + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(MSM6295ROM + 0x80000, 6, 1)) return 1; + + decode_sprites(); + } + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); + SekMapMemory(Ram68K, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory((UINT8 *)RamPal, 0x200000, 0x200FFF, SM_ROM); + SekMapHandler(1, 0x200000, 0x200FFF, SM_WRITE); // palette write + SekMapMemory((UINT8 *)RamSpr0, 0x240000, 0x240FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr1, 0x280000, 0x280FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg, 0x2C0000, 0x2C0FFF, SM_RAM); + SekMapMemory(Ram68K + 0x10000, 0x8C0000, 0x8CFFFF, SM_RAM); + + SekSetReadWordHandler(0, k1945iiiReadWord); +// SekSetReadByteHandler(0, k1945iiiReadByte); + SekSetWriteWordHandler(0, k1945iiiWriteWord); + SekSetWriteByteHandler(0, k1945iiiWriteByte); + +// SekSetWriteByteHandler(1, k1945iiiWriteBytePalette); + SekSetWriteWordHandler(1, k1945iiiWriteWordPalette); + SekClose(); + } + + MSM6295Init(0, 7500, 80, 1); + MSM6295Init(1, 7500, 80, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + + MSM6295Exit(0); + MSM6295Exit(1); + + BurnFree(Mem); + + return 0; +} + +static void DrawBackground() +{ + for (INT32 offs = 0; offs < 64*32; offs++) + { + INT32 sx = ((offs & 0x1f) * 16) - scrollx[0]; + if (sx <= -192) sx += 512; + + INT32 sy = ((offs / 0x20) * 16) - scrolly[0]; +// if (sy <= -288) sy += 512; + + if (sx <= -16 || sx >= 320 || sy <= -16 || sy >= 224) + continue; + + INT32 code = RamBg[offs] & 0x1fff; + + if (sx >= 0 && sx <= 304 && sy >= 0 && sy <= 208) { + Render16x16Tile(pTransDraw, code, sx, sy, 0, 8, 0, RomBg); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, 0, 8, 0, RomBg); + } + } +} + +static void DrawSprites() +{ + for (INT32 i = 0; i < 0x1000/2; i++) + { + INT32 sx = RamSpr0[i] >> 8; + INT32 sy = RamSpr0[i] & 0xff; + INT32 code = (RamSpr1[i] & 0x7ffe) >> 1; + sx |= (RamSpr1[i] & 0x0001) << 8; + + if (sx >= 336) sx -= 512; + if (sy >= 240) sy -= 256; + + if (sx >= 0 && sx <= 304 && sy > 0 && sy <= 208) { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, 0, 8, 0, 0x100, RomSpr); + } else if (sx >= -16 && sx < 320 && sy >= -16 && sy < 224) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 8, 0, 0x100, RomSpr); + } + } +} + +static INT32 DrvDraw() +{ + if (bRecalcPalette) { + for (INT32 i = 0; i < 0x200; i++) { + RamCurPal[i] = CalcCol(RamPal[i]); + } + + bRecalcPalette = 0; + } + + DrawBackground(); + DrawSprites(); + + BurnTransferCopy(RamCurPal); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInput, 0xff, 4); + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] ^= (DrvJoy1[i] & 1) << i; + DrvInput[1] ^= (DrvJoy2[i] & 1) << i; + DrvInput[2] ^= (DrvButton[i] & 1) << i; + } + } + + INT32 nTotalCycles = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + + SekOpen(0); + SekRun(nTotalCycles); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + memset(pBurnSoundOut, 0, nBurnSoundLen * 2 * sizeof(INT16)); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + if (pnMin) *pnMin = 0x029671; + + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + if (nAction & ACB_WRITE) { + INT32 bank0 = m6295bank[0]; + INT32 bank1 = m6295bank[1]; + m6295bank[0] = ~0; + m6295bank[1] = ~0; + + sndSetBank(bank0, bank1); + + bRecalcPalette = 1; + } + } + + return 0; +} + + +// 1945k III + +static struct BurnRomInfo _1945kiiiRomDesc[] = { + { "prg-1.u51", 0x080000, 0x6b345f27, 1 | BRF_ESS | BRF_PRG }, // 0 68000 code + { "prg-2.u52", 0x080000, 0xce09b98c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "m16m-1.u62", 0x200000, 0x0b9a6474, BRF_GRA }, // 2 Sprites + { "m16m-2.u63", 0x200000, 0x368a8c2e, BRF_GRA }, // 3 + + { "m16m-3.u61", 0x200000, 0x32fc80dd, BRF_GRA }, // 4 Background Layer + + { "snd-1.su7", 0x080000, 0xbbb7f0ff, BRF_SND }, // 5 MSM #0 Samples + + { "snd-2.su4", 0x080000, 0x47e3952e, BRF_SND }, // 6 MSM #1 Samples +}; + +STD_ROM_PICK(_1945kiii) +STD_ROM_FN(_1945kiii) + +struct BurnDriver BurnDrv1945kiii = { + "1945kiii", NULL, NULL, NULL, "2000", + "1945k III\0", NULL, "Oriental", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, _1945kiiiRomInfo, _1945kiiiRomName, NULL, NULL, _1945kiiiInputInfo, _1945kiiiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &bRecalcPalette, 0x200, + 224, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_aerofgt.cpp b/src/burn/drivers/misc_post90s/d_aerofgt.cpp new file mode 100644 index 00000000..bffbdc9a --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_aerofgt.cpp @@ -0,0 +1,4416 @@ +/* + * Aero Fighters driver for FB Alpha 0.2.96.71 + * Port by OopsWare. 2007 + * http://oopsware.googlepages.com + * http://oopsware.ys168.com + * + * 6.13.2007 + * Add driver Spinal Breakers (spinlbrk) + * + * 6.12.2007 + * Add driver Karate Blazers (karatblz) + * + * 6.11.2007 + * Add driver Turbo Force (turbofrc) + * + * 6.10.2007 + * Add BurnHighCol support, and add BDF_16BIT_ONLY into driver. thanks to KEV + * + */ + +#include "burnint.h" +#include "burn_ym2610.h" + +#define USE_BURN_HIGHCOL 1 + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +static UINT8 DrvInput[10] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *RomZ80; +static UINT8 *RomBg; +static UINT8 *RomSpr1; +static UINT8 *RomSpr2; +static UINT8 *RomSnd1; +static UINT8 *RomSnd2; + +static UINT8 *RamPal; +static UINT16 *RamRaster; +static UINT16 *RamBg1V, *RamBg2V; +static UINT16 *RamSpr1; +static UINT16 *RamSpr2; +static UINT16 *RamSpr3; +static UINT8 *Ram01; +static UINT8 *RamZ80; + +//static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +//static INT32 nCyclesSegment; + +static UINT8 RamGfxBank[8]; + +static UINT16 *RamCurPal; +static UINT8 *DeRomBg; +static UINT8 *DeRomSpr1; +static UINT8 *DeRomSpr2; + +static UINT32 RamSpr1SizeMask; +static UINT32 RamSpr2SizeMask; +static UINT32 RomSpr1SizeMask; +static UINT32 RomSpr2SizeMask; + +static INT32 pending_command = 0; +static INT32 RomSndSize1, RomSndSize2; + +static UINT16 bg1scrollx, bg2scrollx; +static UINT16 bg1scrolly, bg2scrolly; + +static INT32 nAerofgtZ80Bank; +static UINT8 nSoundlatch; + +#if USE_BURN_HIGHCOL + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x001F) << 3; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x7C00) >> 7; // Blue + b |= b >> 5; + + return BurnHighCol(b, g, r, 0); +} + +#else + +inline static UINT32 CalcCol(UINT16 nColour) +{ + return (nColour & 0x001F) | ((nColour & 0x7FE0) << 1); +} + +#endif + +static struct BurnInputInfo aerofgtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 2, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 3, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"P3 Coin", BIT_DIGITAL, DrvButton + 6, "p3 coin"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(aerofgt) + +static struct BurnDIPInfo aerofgtDIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x00, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin Slot"}, + {0x12, 0x01, 0x01, 0x00, "Same"}, + {0x12, 0x01, 0x01, 0x01, "Individual"}, + {0, 0xFE, 0, 8, "Coin 1"}, + {0x12, 0x01, 0x0E, 0x00, "1 coin 1 credits"}, + {0x12, 0x01, 0x0E, 0x02, "2 coin 1 credits"}, + {0x12, 0x01, 0x0E, 0x04, "3 coin 1 credit"}, + {0x12, 0x01, 0x0E, 0x06, "1 coin 2 credits"}, + {0x12, 0x01, 0x0E, 0x08, "1 coins 3 credit"}, + {0x12, 0x01, 0x0E, 0x0A, "1 coins 4 credit"}, + {0x12, 0x01, 0x0E, 0x0C, "1 coins 5 credit"}, + {0x12, 0x01, 0x0E, 0x0E, "1 coins 6 credit"}, + {0, 0xFE, 0, 8, "Coin 2"}, + {0x12, 0x01, 0x70, 0x00, "1 coin 1 credits"}, + {0x12, 0x01, 0x70, 0x10, "2 coin 1 credits"}, + {0x12, 0x01, 0x70, 0x20, "3 coin 1 credit"}, + {0x12, 0x01, 0x70, 0x30, "1 coin 2 credits"}, + {0x12, 0x01, 0x70, 0x40, "1 coins 3 credit"}, + {0x12, 0x01, 0x70, 0x50, "1 coins 4 credit"}, + {0x12, 0x01, 0x70, 0x60, "1 coins 5 credit"}, + {0x12, 0x01, 0x70, 0x70, "1 coins 6 credit"}, + {0, 0xFE, 0, 2, "2 Coins to Start, 1 to Continue"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 2, "Screen flip"}, + {0x13, 0x01, 0x01, 0x00, "Off"}, + {0x13, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x13, 0x01, 0x02, 0x00, "Off"}, + {0x13, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x13, 0x01, 0x0C, 0x00, "Normal"}, + {0x13, 0x01, 0x0C, 0x04, "Easy"}, + {0x13, 0x01, 0x0C, 0x08, "Hard"}, + {0x13, 0x01, 0x0C, 0x0C, "Hardest"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x10, "1"}, + {0x13, 0x01, 0x30, 0x20, "2"}, + {0x13, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Bonus Life"}, + {0x13, 0x01, 0x40, 0x00, "200000"}, + {0x13, 0x01, 0x40, 0x40, "300000"}, + {0, 0xFE, 0, 2, "Service"}, + {0x13, 0x01, 0x80, 0x00, "Off"}, + {0x13, 0x01, 0x80, 0x80, "On"}, + +}; + +static struct BurnDIPInfo aerofgt_DIPList[] = { + {0x14, 0xFF, 0xFF, 0x0F, NULL}, + + // DIP 3 + {0, 0xFE, 0, 5, "Region"}, + {0x14, 0x01, 0x0F, 0x00, "USA"}, + {0x14, 0x01, 0x0F, 0x01, "Korea"}, + {0x14, 0x01, 0x0F, 0x02, "Hong Kong"}, + {0x14, 0x01, 0x0F, 0x04, "Taiwan"}, + {0x14, 0x01, 0x0F, 0x0F, "Any"}, +}; + +STDDIPINFOEXT(aerofgt, aerofgt, aerofgt_) + +// Rom information +static struct BurnRomInfo aerofgtRomDesc[] = { + { "1.u4", 0x080000, 0x6fdff0a2, BRF_ESS | BRF_PRG }, // 68000 code swapped + + { "538a54.124", 0x080000, 0x4d2c4df2, BRF_GRA }, // graphics + { "1538a54.124", 0x080000, 0x286d109e, BRF_GRA }, + + { "538a53.u9", 0x100000, 0x630d8e0b, BRF_GRA }, // + { "534g8f.u18", 0x080000, 0x76ce0926, BRF_GRA }, + + { "2.153", 0x020000, 0xa1ef64ec, BRF_ESS | BRF_PRG }, // Sound CPU + + { "it-19-01", 0x040000, 0x6d42723d, BRF_SND }, // samples + { "it-19-06", 0x100000, 0xcdbbdb1d, BRF_SND }, +}; + +STD_ROM_PICK(aerofgt) +STD_ROM_FN(aerofgt) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68000 ROM + RomZ80 = Next; Next += 0x030000; // Z80 ROM + RomBg = Next; Next += 0x200040; // Background, 1M 8x8x4bit decode to 2M + 64Byte safe + DeRomBg = RomBg + 0x000040; + RomSpr1 = Next; Next += 0x200000; // Sprite 1 , 1M 16x16x4bit decode to 2M + 256Byte safe + RomSpr2 = Next; Next += 0x100100; // Sprite 2 + + DeRomSpr1 = RomSpr1 + 0x000100; + DeRomSpr2 = RomSpr2 += 0x000100; + + RomSnd1 = Next; Next += 0x040000; // ADPCM data + RomSndSize1 = 0x040000; + RomSnd2 = Next; Next += 0x100000; // ADPCM data + RomSndSize2 = 0x100000; + RamStart = Next; + + RamPal = Next; Next += 0x000800; // 1024 of X1R5G5B5 Palette + RamRaster = (UINT16 *)Next; Next += 0x000800 * sizeof(UINT16); // 0x1b0000~0x1b07ff, Raster + // 0x1b0800~0x1b0801, NOP + // 0x1b0ff0~0x1b0fff, stack area during boot + RamBg1V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG1 Video Ram + RamBg2V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG2 Video Ram + RamSpr1 = (UINT16 *)Next; Next += 0x004000 * sizeof(UINT16); // Sprite 1 Ram + RamSpr2 = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // Sprite 2 Ram + Ram01 = Next; Next += 0x010000; // Work Ram + RamZ80 = Next; Next += 0x000800; // Z80 Ram 2K + + RamEnd = Next; + + RamCurPal = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // 1024 colors + + MemEnd = Next; + return 0; +} + +static void DecodeBg() +{ + for (INT32 c=0x8000-1; c>=0; c--) { + for (INT32 y=7; y>=0; y--) { + DeRomBg[(c * 64) + (y * 8) + 7] = RomBg[0x00002 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 6] = RomBg[0x00002 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 5] = RomBg[0x00003 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 4] = RomBg[0x00003 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 3] = RomBg[0x00000 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 2] = RomBg[0x00000 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 1] = RomBg[0x00001 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 0] = RomBg[0x00001 + (y * 4) + (c * 32)] >> 4; + } + } +} + +static void DecodeSpr(UINT8 *d, UINT8 *s, INT32 cnt) +{ + for (INT32 c=cnt-1; c>=0; c--) + for (INT32 y=15; y>=0; y--) { + d[(c * 256) + (y * 16) + 15] = s[0x00006 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 14] = s[0x00006 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 13] = s[0x00007 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 12] = s[0x00007 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 11] = s[0x00004 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 10] = s[0x00004 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 9] = s[0x00005 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 8] = s[0x00005 + (y * 8) + (c * 128)] >> 4; + + d[(c * 256) + (y * 16) + 7] = s[0x00002 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 6] = s[0x00002 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 5] = s[0x00003 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 4] = s[0x00003 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 3] = s[0x00000 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 2] = s[0x00000 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 1] = s[0x00001 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 0] = s[0x00001 + (y * 8) + (c * 128)] >> 4; + } +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + if (BurnLoadRom(Rom01, 0, 1)) { + return 1; + } + + // Load Graphic + BurnLoadRom(RomBg, 1, 1); + BurnLoadRom(RomBg+0x80000, 2, 1); + DecodeBg(); + + BurnLoadRom(RomSpr1+0x000000, 3, 1); + BurnLoadRom(RomSpr1+0x100000, 4, 1); + DecodeSpr(DeRomSpr1, RomSpr1, 8192+4096); + + // Load Z80 ROM + if (BurnLoadRom(RomZ80+0x10000, 5, 1)) return 1; + memcpy(RomZ80, RomZ80+0x10000, 0x10000); + + BurnLoadRom(RomSnd1, 6, 1); + BurnLoadRom(RomSnd2, 7, 1); + + return 0; +} + +UINT8 __fastcall aerofgtReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xFFFFA1: + return ~DrvInput[0]; + case 0xFFFFA3: + return ~DrvInput[1]; + case 0xFFFFA5: + return ~DrvInput[2]; + case 0xFFFFA7: + return ~DrvInput[3]; + case 0xFFFFA9: + return ~DrvInput[4]; + case 0xFFFFAD: + //printf("read pending_command %d addr %08x\n", pending_command, sekAddress); + return pending_command; + case 0xFFFFAF: + return ~DrvInput[5]; +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +/* +UINT16 __fastcall aerofgtReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + + default: + printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} +*/ + +static void SoundCommand(UINT8 nCommand) +{ +// bprintf(PRINT_NORMAL, _T(" - Sound command sent (0x%02X).\n"), nCommand); + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]); + if (nCycles <= ZetTotalCycles()) return; + + BurnTimerUpdate(nCycles); + + nSoundlatch = nCommand; + ZetNmi(); +} + +void __fastcall aerofgtWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (( sekAddress & 0xFF0000 ) == 0x1A0000) { + sekAddress &= 0xFFFF; + if (sekAddress < 0x800) { + RamPal[sekAddress^1] = byteValue; + // palette byte write at boot self-test only ?! + // if (sekAddress & 1) + // RamCurPal[sekAddress>>1] = CalcCol( *((UINT16 *)&RamPal[sekAddress]) ); + } + return; + } + + switch (sekAddress) { + case 0xFFFFC1: + pending_command = 1; + SoundCommand(byteValue); + break; +/* + case 0xFFFFB9: + case 0xFFFFBB: + case 0xFFFFBD: + case 0xFFFFBF: + break; + case 0xFFFFAD: + // NOP + break; + default: + printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); +*/ + } +} + +void __fastcall aerofgtWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (( sekAddress & 0xFF0000 ) == 0x1A0000) { + sekAddress &= 0xFFFF; + if (sekAddress < 0x800) + *((UINT16 *)&RamPal[sekAddress]) = wordValue; + RamCurPal[sekAddress>>1] = CalcCol( wordValue ); + return; + } + + switch (sekAddress) { + case 0xFFFF80: + RamGfxBank[0] = wordValue >> 0x08; + RamGfxBank[1] = wordValue & 0xFF; + break; + case 0xFFFF82: + RamGfxBank[2] = wordValue >> 0x08; + RamGfxBank[3] = wordValue & 0xFF; + break; + case 0xFFFF84: + RamGfxBank[4] = wordValue >> 0x08; + RamGfxBank[5] = wordValue & 0xFF; + break; + case 0xFFFF86: + RamGfxBank[6] = wordValue >> 0x08; + RamGfxBank[7] = wordValue & 0xFF; + break; + case 0xFFFF88: + bg1scrolly = wordValue; + break; + case 0xFFFF90: + bg2scrolly = wordValue; + break; +/* + case 0xFFFF40: + case 0xFFFF42: + case 0xFFFF44: + case 0xFFFF48: + case 0xFFFF4A: + case 0xFFFF4C: + case 0xFFFF50: + case 0xFFFF52: + case 0xFFFF60: + break; + default: + printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); +*/ + } +} + +static void aerofgtFMIRQHandler(INT32, INT32 nStatus) +{ +// bprintf(PRINT_NORMAL, _T(" - IRQ -> %i.\n"), nStatus); + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 aerofgtSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double aerofgtGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +/* +static UINT8 __fastcall aerofgtZ80Read(UINT16 a) +{ + switch (a) { + + default: + printf("Z80 Attempt to read word value of location %04x\n", a); + } + return 0; +} + +static void __fastcall aerofgtZ80Write(UINT16 a,UINT8 v) +{ + switch (a) { + + default: + printf("Attempt to write word value %x to location %x\n", v, a); + } +} +*/ + +static void aerofgtSndBankSwitch(UINT8 v) +{ +/* + UINT8 *rom = memory_region(REGION_CPU2) + 0x10000; + memory_set_bankptr(1,rom + (data & 0x03) * 0x8000); +*/ + v &= 0x03; + if (v != nAerofgtZ80Bank) { + UINT8* nStartAddress = RomZ80 + 0x10000 + (v << 15); + ZetMapArea(0x8000, 0xFFFF, 0, nStartAddress); + ZetMapArea(0x8000, 0xFFFF, 2, nStartAddress); + nAerofgtZ80Bank = v; + } +} + +UINT8 __fastcall aerofgtZ80PortRead(UINT16 p) +{ + switch (p & 0xFF) { + case 0x00: + return BurnYM2610Read(0); + case 0x02: + return BurnYM2610Read(2); + case 0x0C: + return nSoundlatch; +// default: +// printf("Z80 Attempt to read port %04x\n", p); + } + return 0; +} + +void __fastcall aerofgtZ80PortWrite(UINT16 p, UINT8 v) +{ + switch (p & 0x0FF) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + BurnYM2610Write(p & 3, v); + break; + case 0x04: + aerofgtSndBankSwitch(v); + break; + case 0x08: + pending_command = 0; + break; +// default: +// printf("Z80 Attempt to write %02x to port %04x\n", v, p); + } +} + + +static INT32 DrvDoReset() +{ + nAerofgtZ80Bank = -1; + + SekOpen(0); + //nIRQPending = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + aerofgtSndBankSwitch(0); + ZetClose(); + BurnYM2610Reset(); + + memset(RamGfxBank, 0 , sizeof(RamGfxBank)); + + return 0; +} + +static INT32 aerofgtInit() +{ + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); + + // Load the roms into memory + + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(RamPal, 0x1A0000, 0x1A07FF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamRaster, + 0x1B0000, 0x1B0FFF, SM_RAM); // Raster / MRA_NOP / MRA_BANK7 + SekMapMemory((UINT8 *)RamBg1V, + 0x1B2000, 0x1B3FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg2V, + 0x1B4000, 0x1B5FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr1, + 0x1C0000, 0x1C7FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr2, + 0x1D0000, 0x1D1FFF, SM_RAM); + SekMapMemory(Ram01, 0xFEF000, 0xFFEFFF, SM_RAM); // 64K Work RAM + +// SekSetReadWordHandler(0, aerofgtReadWord); + SekSetReadByteHandler(0, aerofgtReadByte); + SekSetWriteWordHandler(0, aerofgtWriteWord); + SekSetWriteByteHandler(0, aerofgtWriteByte); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x77FF, 0, RomZ80); + ZetMapArea(0x0000, 0x77FF, 2, RomZ80); + + ZetMapArea(0x7800, 0x7FFF, 0, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 1, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 2, RamZ80); + + ZetMemEnd(); + + //ZetSetReadHandler(aerofgtZ80Read); + //ZetSetWriteHandler(aerofgtZ80Write); + ZetSetInHandler(aerofgtZ80PortRead); + ZetSetOutHandler(aerofgtZ80PortWrite); + + ZetClose(); + } + + BurnYM2610Init(8000000, RomSnd2, &RomSndSize2, RomSnd1, &RomSndSize1, &aerofgtFMIRQHandler, aerofgtSynchroniseStream, aerofgtGetTime, 0); + BurnTimerAttachZet(4000000); + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2610Exit(); + + ZetExit(); + SekExit(); + + BurnFree(Mem); + + return 0; +} + + +static void drawgfxzoom(INT32 bank,UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy,INT32 scalex,INT32 scaley) +{ + if (!scalex || !scaley) return; + + UINT16 * p = (UINT16 *) pBurnDraw; + UINT8 * q; + UINT16 * pal; + + if (bank) { + q = DeRomSpr2 + (code) * 256; + pal = RamCurPal + 768; + } else { + q = DeRomSpr1 + (code) * 256; + pal = RamCurPal + 512; + } + + p += sy * 320 + sx; + + if (sx < 0 || sx >= 304 || sy < 0 || sy >= 208 ) { + + if ((sx <= -16) || (sx >= 320) || (sy <= -16) || (sy >= 224)) + return; + + if (flipy) { + + p += 320 * 15; + + if (flipx) { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[15] | color]; + } + p -= 320; + q += 16; + } + + } else { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[15] | color]; + } + p -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[15] | color]; + } + p += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[15] | color]; + } + p += 320; + q += 16; + } + + } + + } + + return; + } + + if (flipy) { + + p += 320 * 15; + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p -= 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p += 320; + q += 16; + } + + } + + } + +} + +static void aerofgt_drawsprites(INT32 priority) +{ + priority <<= 12; + INT32 offs = 0; + + while (offs < 0x0400 && (RamSpr2[offs] & 0x8000) == 0) { + INT32 attr_start = (RamSpr2[offs] & 0x03ff) * 4; + + /* is the way I handle priority correct? Or should I just check bit 13? */ + if ((RamSpr2[attr_start + 2] & 0x3000) == priority) { + INT32 map_start; + INT32 ox,oy,x,y,xsize,ysize,zoomx,zoomy,flipx,flipy,color; + + ox = RamSpr2[attr_start + 1] & 0x01ff; + xsize = (RamSpr2[attr_start + 1] & 0x0e00) >> 9; + zoomx = (RamSpr2[attr_start + 1] & 0xf000) >> 12; + oy = RamSpr2[attr_start + 0] & 0x01ff; + ysize = (RamSpr2[attr_start + 0] & 0x0e00) >> 9; + zoomy = (RamSpr2[attr_start + 0] & 0xf000) >> 12; + flipx = RamSpr2[attr_start + 2] & 0x4000; + flipy = RamSpr2[attr_start + 2] & 0x8000; + color = (RamSpr2[attr_start + 2] & 0x0f00) >> 4; + map_start = RamSpr2[attr_start + 3] & 0x3fff; + + ox += (xsize*zoomx+2)/4; + oy += (ysize*zoomy+2)/4; + + zoomx = 32 - zoomx; + zoomy = 32 - zoomy; + + for (y = 0;y <= ysize;y++) { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y)/2 + 16) & 0x1ff) - 16; + else sy = ((oy + zoomy * y / 2 + 16) & 0x1ff) - 16; + + for (x = 0;x <= xsize;x++) { + if (flipx) sx = ((ox + zoomx * (xsize - x) / 2 + 16) & 0x1ff) - 16; + else sx = ((ox + zoomx * x / 2 + 16) & 0x1ff) - 16; + + //if (map_start < 0x2000) + INT32 code = RamSpr1[map_start] & 0x1fff; + + drawgfxzoom(map_start&0x2000,code,color,flipx,flipy,sx,sy,zoomx<<11, zoomy<<11); + + map_start++; + } + } + } + offs++; + } +} + + +/* + * aerofgt Background Tile + * 16-bit tile code in RamBg1V and RamBg2V + * 0xE000 shr 13 is Color + * 0x1800 shr 11 is Gfx Bank + * 0x07FF shr 0 or Tile element index (low part) + * + */ + +static void TileBackground_1(UINT16 *bg, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - RamRaster[0x0000] + 18; + if (x <= -192) x += 512; + + y = my * 8 - (bg1scrolly & 0x1FF); + if (y <= (224-512)) y += 512; + + if ( x<=-8 || x>=320 || y<=-8 || y>= 224 ) + continue; + else + if ( x >=0 && x < 312 && y >= 0 && y < 216) { + + UINT8 *d = DeRomBg + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + p[0] = pal[ d[0] | c ]; + p[1] = pal[ d[1] | c ]; + p[2] = pal[ d[2] | c ]; + p[3] = pal[ d[3] | c ]; + p[4] = pal[ d[4] | c ]; + p[5] = pal[ d[5] | c ]; + p[6] = pal[ d[6] | c ]; + p[7] = pal[ d[7] | c ]; + + d += 8; + p += 320; + } + } else { + + UINT8 *d = DeRomBg + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<224 ) { + if ((x + 0) >= 0 && (x + 0)<320) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<320) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<320) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<320) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<320) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<320) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<320) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<320) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 320; + } + + } + + } +} + +static void TileBackground_2(UINT16 *bg, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - RamRaster[0x0200] + 20; + if (x <= -192) x += 512; + + y = my * 8 - (bg2scrolly & 0x1FF); + if (y <= (224-512)) y += 512; + + if ( x<=-8 || x>=320 || y<=-8 || y>= 224 ) + continue; + else + if ( x >=0 && x < 312 && y >= 0 && y < 216) { + + UINT8 *d = DeRomBg + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + + if (d[0] != 15) p[0] = pal[ d[0] | c ]; + if (d[1] != 15) p[1] = pal[ d[1] | c ]; + if (d[2] != 15) p[2] = pal[ d[2] | c ]; + if (d[3] != 15) p[3] = pal[ d[3] | c ]; + if (d[4] != 15) p[4] = pal[ d[4] | c ]; + if (d[5] != 15) p[5] = pal[ d[5] | c ]; + if (d[6] != 15) p[6] = pal[ d[6] | c ]; + if (d[7] != 15) p[7] = pal[ d[7] | c ]; + + d += 8; + p += 320; + } + } else { + + UINT8 *d = DeRomBg + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<224 ) { + if (d[0] != 15 && (x + 0) >= 0 && (x + 0)<320) p[0] = pal[ d[0] | c ]; + if (d[1] != 15 && (x + 1) >= 0 && (x + 1)<320) p[1] = pal[ d[1] | c ]; + if (d[2] != 15 && (x + 2) >= 0 && (x + 2)<320) p[2] = pal[ d[2] | c ]; + if (d[3] != 15 && (x + 3) >= 0 && (x + 3)<320) p[3] = pal[ d[3] | c ]; + if (d[4] != 15 && (x + 4) >= 0 && (x + 4)<320) p[4] = pal[ d[4] | c ]; + if (d[5] != 15 && (x + 5) >= 0 && (x + 5)<320) p[5] = pal[ d[5] | c ]; + if (d[6] != 15 && (x + 6) >= 0 && (x + 6)<320) p[6] = pal[ d[6] | c ]; + if (d[7] != 15 && (x + 7) >= 0 && (x + 7)<320) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 320; + } + + } + + } +} + +static INT32 DrvDraw() +{ + // background 1 + TileBackground_1(RamBg1V, RamCurPal); + + aerofgt_drawsprites(0); + aerofgt_drawsprites(1); + + // background 2 + TileBackground_2(RamBg2V, RamCurPal + 256); + + aerofgt_drawsprites(2); + aerofgt_drawsprites(3); + + return 0; +} + +static INT32 DrvFrame() +{ + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Buttons + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + +// SekSetCyclesScanline(nCyclesTotal[0] / 262); + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) DrvDraw(); + + return 0; +} + + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029671; + } + + if (nAction & ACB_MEMORY_ROM) { // Scan all memory, devices & variables + // + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + if (nAction & ACB_WRITE) { + // update palette while loaded + UINT16* ps = (UINT16*) RamPal; + UINT16* pd = RamCurPal; + for (INT32 i=0; i<1024; i++, ps++, pd++) + *pd = CalcCol(*ps); + } + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); // Scan 68000 state + + ZetOpen(0); + ZetScan(nAction); // Scan Z80 state + ZetClose(); + + SCAN_VAR(RamGfxBank); + SCAN_VAR(DrvInput); + + BurnYM2610Scan(nAction, pnMin); + SCAN_VAR(nSoundlatch); + SCAN_VAR(nAerofgtZ80Bank); + + if (nAction & ACB_WRITE) { + INT32 nBank = nAerofgtZ80Bank; + nAerofgtZ80Bank = -1; + aerofgtSndBankSwitch(nBank); + } + } + return 0; +} + +struct BurnDriver BurnDrvAerofgt = { + "aerofgt", NULL, NULL, NULL, "1992", + "Aero Fighters\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, FBF_SONICWI, + NULL, aerofgtRomInfo, aerofgtRomName, NULL, NULL, aerofgtInputInfo, aerofgtDIPInfo, + aerofgtInit,DrvExit,DrvFrame,DrvDraw,DrvScan, + NULL, 0x800, 224,320,3,4 +}; + +// ------------------------------------------------------ + +static struct BurnInputInfo turbofrcInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 2, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 3, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"P3 Coin", BIT_DIGITAL, DrvButton + 7, "p3 start"}, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 7, "p3 start"}, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up"}, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down"}, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left"}, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right"}, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(turbofrc) + +static struct BurnDIPInfo turbofrcDIPList[] = { + + // Defaults + {0x16, 0xFF, 0xFF, 0x00, NULL}, + {0x17, 0xFF, 0xFF, 0x06, NULL}, + + // DIP 1 + {0, 0xFE, 0, 8, "Coin 1"}, + {0x16, 0x01, 0x07, 0x00, "1 coins 1 credit"}, + {0x16, 0x01, 0x07, 0x01, "2 coins 1 credit"}, + {0x16, 0x01, 0x07, 0x02, "3 coins 1 credit"}, + {0x16, 0x01, 0x07, 0x03, "4 coins 1 credit"}, + {0x16, 0x01, 0x07, 0x04, "1 coin 2 credits"}, + {0x16, 0x01, 0x07, 0x05, "1 coin 3 credits"}, + {0x16, 0x01, 0x07, 0x06, "1 coin 5 credits"}, + {0x16, 0x01, 0x07, 0x07, "1 coin 6 credits"}, + {0, 0xFE, 0, 2, "2 Coins to Start, 1 to Continue"}, + {0x16, 0x01, 0x08, 0x00, "Off"}, + {0x16, 0x01, 0x08, 0x08, "On"}, + {0, 0xFE, 0, 2, "Coin Slot"}, + {0x16, 0x01, 0x10, 0x00, "Same"}, + {0x16, 0x01, 0x10, 0x10, "Individual"}, + {0, 0xFE, 0, 2, "Play Mode"}, + {0x16, 0x01, 0x20, 0x00, "2 Players"}, + {0x16, 0x01, 0x20, 0x20, "3 Players"}, + {0, 0xFE, 0, 2, "Demo_Sounds"}, + {0x16, 0x01, 0x40, 0x00, "Off"}, + {0x16, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Service"}, + {0x16, 0x01, 0x80, 0x00, "Off"}, + {0x16, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 2, "Screen flip"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 8, "Difficulty"}, + {0x17, 0x01, 0x0E, 0x00, "1 (Easiest)"}, + {0x17, 0x01, 0x0E, 0x02, "2"}, + {0x17, 0x01, 0x0E, 0x04, "3"}, + {0x17, 0x01, 0x0E, 0x06, "4 (Normal)"}, + {0x17, 0x01, 0x0E, 0x08, "5"}, + {0x17, 0x01, 0x0E, 0x0A, "6"}, + {0x17, 0x01, 0x0E, 0x0C, "7"}, + {0x17, 0x01, 0x0E, 0x0E, "8 (Hardest)"}, + {0, 0xFE, 0, 2, "Lives"}, + {0x17, 0x01, 0x10, 0x00, "3"}, + {0x17, 0x01, 0x10, 0x10, "2"}, + {0, 0xFE, 0, 2, "Bonus Life"}, + {0x17, 0x01, 0x20, 0x00, "300000"}, + {0x17, 0x01, 0x20, 0x20, "200000"}, + +}; + +STDDIPINFO(turbofrc) + +static struct BurnRomInfo turbofrcRomDesc[] = { + { "tfrc2.bin", 0x040000, 0x721300ee, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "tfrc1.bin", 0x040000, 0x6cd5312b, BRF_ESS | BRF_PRG }, + { "tfrc3.bin", 0x040000, 0x63f50557, BRF_ESS | BRF_PRG }, + + { "tfrcu94.bin", 0x080000, 0xbaa53978, BRF_GRA }, // gfx1 + { "tfrcu95.bin", 0x020000, 0x71a6c573, BRF_GRA }, + + { "tfrcu105.bin", 0x080000, 0x4de4e59e, BRF_GRA }, // gfx2 + { "tfrcu106.bin", 0x020000, 0xc6479eb5, BRF_GRA }, + + { "tfrcu116.bin", 0x080000, 0xdf210f3b, BRF_GRA }, // gfx3 + { "tfrcu118.bin", 0x040000, 0xf61d1d79, BRF_GRA }, + { "tfrcu117.bin", 0x080000, 0xf70812fd, BRF_GRA }, + { "tfrcu119.bin", 0x040000, 0x474ea716, BRF_GRA }, + + { "tfrcu134.bin", 0x080000, 0x487330a2, BRF_GRA }, // gfx4 + { "tfrcu135.bin", 0x080000, 0x3a7e5b6d, BRF_GRA }, + + { "tfrcu166.bin", 0x020000, 0x2ca14a65, BRF_ESS | BRF_PRG }, // Sound CPU + + { "tfrcu180.bin", 0x020000, 0x39c7c7d5, BRF_SND }, // samples + { "tfrcu179.bin", 0x100000, 0x60ca0333, BRF_SND }, +}; + +STD_ROM_PICK(turbofrc) +STD_ROM_FN(turbofrc) + +UINT8 __fastcall turbofrcReadByte(UINT32 sekAddress) +{ + sekAddress &= 0x0FFFFF; + switch (sekAddress) { + case 0x0FF000: + return ~DrvInput[3]; + case 0x0FF001: + return ~DrvInput[0]; + case 0x0FF002: + return 0xFF; + case 0x0FF003: + return ~DrvInput[1]; + case 0x0FF004: + return ~DrvInput[5]; + case 0x0FF005: + return ~DrvInput[4]; + case 0x0FF007: + return pending_command; + case 0x0FF009: + return ~DrvInput[2]; +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +/* +UINT16 __fastcall turbofrcReadWord(UINT32 sekAddress) +{ +// sekAddress &= 0x0FFFFF; +// switch (sekAddress) { + + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); +// } + return 0; +} +*/ + +void __fastcall turbofrcWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (( sekAddress & 0x0FF000 ) == 0x0FE000) { + sekAddress &= 0x07FF; + RamPal[sekAddress^1] = byteValue; + // palette byte write at boot self-test only ?! + //if (sekAddress & 1) + // RamCurPal[sekAddress>>1] = CalcCol( *((UINT16 *)&RamPal[sekAddress & 0xFFE]) ); + return; + } + + sekAddress &= 0x0FFFFF; + + switch (sekAddress) { + + case 0x0FF00E: + pending_command = 1; + SoundCommand(byteValue); + break; +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall turbofrcWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (( sekAddress & 0x0FF000 ) == 0x0FE000) { + sekAddress &= 0x07FE; + *((UINT16 *)&RamPal[sekAddress]) = wordValue; + RamCurPal[sekAddress>>1] = CalcCol( wordValue ); + return; + } + + sekAddress &= 0x0FFFFF; + + switch (sekAddress) { + case 0x0FF002: + bg1scrolly = wordValue; + break; + case 0x0FF004: + bg2scrollx = wordValue; + break; + case 0x0FF006: + bg2scrolly = wordValue; + break; + + case 0x0FF008: + RamGfxBank[0] = (wordValue >> 0) & 0x0f; + RamGfxBank[1] = (wordValue >> 4) & 0x0f; + RamGfxBank[2] = (wordValue >> 8) & 0x0f; + RamGfxBank[3] = (wordValue >> 12) & 0x0f; + break; + case 0x0FF00A: + RamGfxBank[4] = (wordValue >> 0) & 0x0f; + RamGfxBank[5] = (wordValue >> 4) & 0x0f; + RamGfxBank[6] = (wordValue >> 8) & 0x0f; + RamGfxBank[7] = (wordValue >> 12) & 0x0f; + break; + case 0x0FF00C: + // NOP + break; +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +UINT8 __fastcall turbofrcZ80PortRead(UINT16 p) +{ + switch (p & 0xFF) { + case 0x14: + return nSoundlatch; + case 0x18: + return BurnYM2610Read(0); + case 0x1A: + return BurnYM2610Read(2); +// default: +// printf("Z80 Attempt to read port %04x\n", p); + } + return 0; +} + +void __fastcall turbofrcZ80PortWrite(UINT16 p, UINT8 v) +{ + switch (p & 0x0FF) { + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + BurnYM2610Write((p - 0x18) & 3, v); + break; + case 0x00: + aerofgtSndBankSwitch(v); + break; + case 0x14: + pending_command = 0; + break; +// default: +// printf("Z80 Attempt to write %02x to port %04x\n", v, p); + } +} + +static INT32 turbofrcMemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x0C0000; // 68000 ROM + RomZ80 = Next; Next += 0x030000; // Z80 ROM + + RomBg = Next; Next += 0x280040; // + DeRomBg = RomBg + 0x000040; + + RomSpr1 = Next; Next += 0x400000; // Sprite 1 + RomSpr2 = Next; Next += 0x200100; // Sprite 2 + + DeRomSpr1 = RomSpr1 + 0x000100; + DeRomSpr2 = RomSpr2 += 0x000100; + + RomSnd1 = Next; Next += 0x020000; // ADPCM data + RomSndSize1 = 0x020000; + RomSnd2 = Next; Next += 0x100000; // ADPCM data + RomSndSize2 = 0x100000; + + RamStart = Next; + + RamBg1V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG1 Video Ram + RamBg2V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG2 Video Ram + RamSpr1 = (UINT16 *)Next; Next += 0x002000 * sizeof(UINT16); // Sprite 1 Ram + RamSpr2 = (UINT16 *)Next; Next += 0x002000 * sizeof(UINT16); // Sprite 2 Ram + RamSpr3 = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // Sprite 3 Ram + RamRaster = (UINT16 *)Next; Next += 0x000800 * sizeof(UINT16); // Raster Ram + + RamSpr1SizeMask = 0x1FFF; + RamSpr2SizeMask = 0x1FFF; + RomSpr1SizeMask = 0x3FFF; + RomSpr2SizeMask = 0x1FFF; + + Ram01 = Next; Next += 0x014000; // Work Ram + + RamPal = Next; Next += 0x000800; // 1024 of X1R5G5B5 Palette + RamZ80 = Next; Next += 0x000800; // Z80 Ram 2K + + RamEnd = Next; + + RamCurPal = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + + MemEnd = Next; + return 0; +} + +static void pspikesDecodeBg(INT32 cnt) +{ + for (INT32 c=cnt-1; c>=0; c--) { + for (INT32 y=7; y>=0; y--) { + DeRomBg[(c * 64) + (y * 8) + 7] = RomBg[0x00003 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 6] = RomBg[0x00003 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 5] = RomBg[0x00002 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 4] = RomBg[0x00002 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 3] = RomBg[0x00001 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 2] = RomBg[0x00001 + (y * 4) + (c * 32)] & 0x0f; + DeRomBg[(c * 64) + (y * 8) + 1] = RomBg[0x00000 + (y * 4) + (c * 32)] >> 4; + DeRomBg[(c * 64) + (y * 8) + 0] = RomBg[0x00000 + (y * 4) + (c * 32)] & 0x0f; + } + } +} + +static void pspikesDecodeSpr(UINT8 *d, UINT8 *s, INT32 cnt) +{ + for (INT32 c=cnt-1; c>=0; c--) + for (INT32 y=15; y>=0; y--) { + d[(c * 256) + (y * 16) + 15] = s[0x00007 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 14] = s[0x00007 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 13] = s[0x00005 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 12] = s[0x00005 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 11] = s[0x00006 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 10] = s[0x00006 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 9] = s[0x00004 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 8] = s[0x00004 + (y * 8) + (c * 128)] & 0x0f; + + d[(c * 256) + (y * 16) + 7] = s[0x00003 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 6] = s[0x00003 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 5] = s[0x00001 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 4] = s[0x00001 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 3] = s[0x00002 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 2] = s[0x00002 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 1] = s[0x00000 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 0] = s[0x00000 + (y * 8) + (c * 128)] & 0x0f; + } +} + + +static INT32 turbofrcInit() +{ + Mem = NULL; + turbofrcMemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + turbofrcMemIndex(); + + // Load 68000 ROM + if (BurnLoadRom(Rom01+0x00000, 0, 1)) return 1; + if (BurnLoadRom(Rom01+0x40000, 1, 1)) return 1; + if (BurnLoadRom(Rom01+0x80000, 2, 1)) return 1; + + // Load Graphic + BurnLoadRom(RomBg+0x000000, 3, 1); + BurnLoadRom(RomBg+0x080000, 4, 1); + BurnLoadRom(RomBg+0x0A0000, 5, 1); + BurnLoadRom(RomBg+0x120000, 6, 1); + pspikesDecodeBg(0x14000); + + BurnLoadRom(RomSpr1+0x000000, 7, 2); + BurnLoadRom(RomSpr1+0x000001, 9, 2); + BurnLoadRom(RomSpr1+0x100000, 8, 2); + BurnLoadRom(RomSpr1+0x100001, 10, 2); + BurnLoadRom(RomSpr1+0x200000, 11, 2); + BurnLoadRom(RomSpr1+0x200001, 12, 2); + pspikesDecodeSpr(DeRomSpr1, RomSpr1, 0x6000); + + // Load Z80 ROM + if (BurnLoadRom(RomZ80+0x10000, 13, 1)) return 1; + memcpy(RomZ80, RomZ80+0x10000, 0x10000); + + BurnLoadRom(RomSnd1, 14, 1); + BurnLoadRom(RomSnd2, 15, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0BFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x0C0000, 0x0CFFFF, SM_RAM); // 64K Work RAM + SekMapMemory((UINT8 *)RamBg1V, + 0x0D0000, 0x0D1FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg2V, + 0x0D2000, 0x0D3FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr1, + 0x0E0000, 0x0E3FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr2, + 0x0E4000, 0x0E7FFF, SM_RAM); + SekMapMemory(Ram01+0x10000, 0x0F8000, 0x0FBFFF, SM_RAM); // Work RAM + SekMapMemory(Ram01+0x10000, 0xFF8000, 0xFFBFFF, SM_RAM); // Work RAM + SekMapMemory((UINT8 *)RamSpr3, + 0x0FC000, 0x0FC7FF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr3, + 0xFFC000, 0xFFC7FF, SM_RAM); + SekMapMemory((UINT8 *)RamRaster, + 0x0FD000, 0x0FDFFF, SM_RAM); + SekMapMemory((UINT8 *)RamRaster, + 0xFFD000, 0xFFDFFF, SM_RAM); + SekMapMemory(RamPal, 0x0FE000, 0x0FE7FF, SM_ROM); // Palette + +// SekSetReadWordHandler(0, turbofrcReadWord); + SekSetReadByteHandler(0, turbofrcReadByte); + SekSetWriteWordHandler(0, turbofrcWriteWord); + SekSetWriteByteHandler(0, turbofrcWriteByte); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x77FF, 0, RomZ80); + ZetMapArea(0x0000, 0x77FF, 2, RomZ80); + + ZetMapArea(0x7800, 0x7FFF, 0, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 1, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 2, RamZ80); + + ZetMemEnd(); + + ZetSetInHandler(turbofrcZ80PortRead); + ZetSetOutHandler(turbofrcZ80PortWrite); + + ZetClose(); + } + + BurnYM2610Init(8000000, RomSnd2, &RomSndSize2, RomSnd1, &RomSndSize1, &aerofgtFMIRQHandler, aerofgtSynchroniseStream, aerofgtGetTime, 0); + BurnTimerAttachZet(4000000); + + DrvDoReset(); + + return 0; +} + +static void turbofrcTileBackground_1(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (RamRaster[7] & 0x1FF) - 11; + if (x <= (352-512)) x += 512; + + y = my * 8 - (bg1scrolly & 0x1FF) - 2; + if (y <= (240-512)) y += 512; + + if ( x<=-8 || x>=352 || y<=-8 || y>= 240 ) + continue; + + else + if ( x >=0 && x < (352-8) && y >= 0 && y < (240-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + p[0] = pal[ d[0] | c ]; + p[1] = pal[ d[1] | c ]; + p[2] = pal[ d[2] | c ]; + p[3] = pal[ d[3] | c ]; + p[4] = pal[ d[4] | c ]; + p[5] = pal[ d[5] | c ]; + p[6] = pal[ d[6] | c ]; + p[7] = pal[ d[7] | c ]; + + d += 8; + p += 352; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<240 ) { + if ((x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 352; + } + + } + + } +} + +static void turbofrcTileBackground_2(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (bg2scrollx & 0x1FF) + 7; + if (x <= (352-512)) x += 512; + + y = my * 8 - (bg2scrolly & 0x1FF) - 2; + if (y <= (240-512)) y += 512; + + if ( x<=-8 || x>=352 || y<=-8 || y>= 240 ) + continue; + else + if ( x >=0 && x < (352-8) && y >= 0 && y < (240-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + + if (d[0] != 15) p[0] = pal[ d[0] | c ]; + if (d[1] != 15) p[1] = pal[ d[1] | c ]; + if (d[2] != 15) p[2] = pal[ d[2] | c ]; + if (d[3] != 15) p[3] = pal[ d[3] | c ]; + if (d[4] != 15) p[4] = pal[ d[4] | c ]; + if (d[5] != 15) p[5] = pal[ d[5] | c ]; + if (d[6] != 15) p[6] = pal[ d[6] | c ]; + if (d[7] != 15) p[7] = pal[ d[7] | c ]; + + d += 8; + p += 352; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<240 ) { + if (d[0] != 15 && (x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if (d[1] != 15 && (x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if (d[2] != 15 && (x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if (d[3] != 15 && (x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if (d[4] != 15 && (x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if (d[5] != 15 && (x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if (d[6] != 15 && (x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if (d[7] != 15 && (x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 352; + } + + } + + } +} + +static void pdrawgfxzoom(INT32 bank,UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy,INT32 scalex,INT32 scaley) +{ + if (!scalex || !scaley) return; + + UINT16 * p = (UINT16 *) pBurnDraw; + UINT8 * q; + UINT16 * pal; + + if (bank) { + //if (code > RomSpr2SizeMask) + code &= RomSpr2SizeMask; + q = DeRomSpr2 + (code) * 256; + pal = RamCurPal + 768; + } else { + //if (code > RomSpr1SizeMask) + code &= RomSpr1SizeMask; + q = DeRomSpr1 + (code) * 256; + pal = RamCurPal + 512; + } + + p += sy * 352 + sx; + + if (sx < 0 || sx >= (352-16) || sy < 0 || sy >= (240-16) ) { + + if ((sx <= -16) || (sx >= 352) || (sy <= -16) || (sy >= 240)) + return; + + if (flipy) { + + p += 352 * 15; + + if (flipx) { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<240)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<352)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<352)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<352)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<352)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<352)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<352)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<352)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<352)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<352)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<352)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<352)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<352)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<352)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<352)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<352)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<352)) p[ 0] = pal[ q[15] | color]; + } + p -= 352; + q += 16; + } + + } else { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<240)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<352)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<352)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<352)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<352)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<352)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<352)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<352)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<352)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<352)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<352)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<352)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<352)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<352)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<352)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<352)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<352)) p[15] = pal[ q[15] | color]; + } + p -= 352; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<240)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<352)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<352)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<352)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<352)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<352)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<352)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<352)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<352)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<352)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<352)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<352)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<352)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<352)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<352)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<352)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<352)) p[ 0] = pal[ q[15] | color]; + } + p += 352; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<240)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<352)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<352)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<352)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<352)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<352)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<352)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<352)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<352)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<352)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<352)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<352)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<352)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<352)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<352)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<352)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<352)) p[15] = pal[ q[15] | color]; + } + p += 352; + q += 16; + } + + } + + } + + return; + } + + if (flipy) { + + p += 352 * 15; + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p -= 352; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p -= 352; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p += 352; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p += 352; + q += 16; + } + + } + + } + +} + +static void turbofrc_drawsprites(INT32 chip,INT32 chip_disabled_pri) +{ + INT32 attr_start,base,first; + + base = chip * 0x0200; + first = 4 * RamSpr3[0x1fe + base]; + + //for (attr_start = base + 0x0200-8;attr_start >= first + base;attr_start -= 4) { + for (attr_start = first + base; attr_start <= base + 0x0200-8; attr_start += 4) { + INT32 map_start; + INT32 ox,oy,x,y,xsize,ysize,zoomx,zoomy,flipx,flipy,color,pri; +// some other drivers still use this wrong table, they have to be upgraded +// INT32 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; + + if (!(RamSpr3[attr_start + 2] & 0x0080)) continue; + pri = RamSpr3[attr_start + 2] & 0x0010; + if ( chip_disabled_pri & !pri) continue; + if (!chip_disabled_pri & (pri>>4)) continue; + ox = RamSpr3[attr_start + 1] & 0x01ff; + xsize = (RamSpr3[attr_start + 2] & 0x0700) >> 8; + zoomx = (RamSpr3[attr_start + 1] & 0xf000) >> 12; + oy = RamSpr3[attr_start + 0] & 0x01ff; + ysize = (RamSpr3[attr_start + 2] & 0x7000) >> 12; + zoomy = (RamSpr3[attr_start + 0] & 0xf000) >> 12; + flipx = RamSpr3[attr_start + 2] & 0x0800; + flipy = RamSpr3[attr_start + 2] & 0x8000; + color = (RamSpr3[attr_start + 2] & 0x000f) << 4; // + 16 * spritepalettebank; + + map_start = RamSpr3[attr_start + 3]; + +// aerofgt has this adjustment, but doing it here would break turbo force title screen +// ox += (xsize*zoomx+2)/4; +// oy += (ysize*zoomy+2)/4; + + zoomx = 32 - zoomx; + zoomy = 32 - zoomy; + + for (y = 0;y <= ysize;y++) { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y)/2 + 16) & 0x1ff) - 16; + else sy = ((oy + zoomy * y / 2 + 16) & 0x1ff) - 16; + + for (x = 0;x <= xsize;x++) { + INT32 code; + + if (flipx) sx = ((ox + zoomx * (xsize - x) / 2 + 16) & 0x1ff) - 16 - 8; + else sx = ((ox + zoomx * x / 2 + 16) & 0x1ff) - 16 - 8; + + if (chip == 0) code = RamSpr1[map_start & RamSpr1SizeMask]; + else code = RamSpr2[map_start & RamSpr2SizeMask]; + + pdrawgfxzoom(chip,code,color,flipx,flipy,sx,sy,zoomx << 11, zoomy << 11); + + map_start++; + } + + if (xsize == 2) map_start += 1; + if (xsize == 4) map_start += 3; + if (xsize == 5) map_start += 2; + if (xsize == 6) map_start += 1; + } + } +} + +static INT32 turbofrcDraw() +{ + turbofrcTileBackground_1(RamBg1V, DeRomBg, RamCurPal); + turbofrcTileBackground_2(RamBg2V, DeRomBg + 0x140000, RamCurPal + 256); + +/* + // we use the priority buffer so sprites are drawn front to back + turbofrc_drawsprites(0,-1); //enemy + turbofrc_drawsprites(0, 0); //enemy + turbofrc_drawsprites(1,-1); //ship + turbofrc_drawsprites(1, 0); //intro +*/ + // in MAME it use a pri-buf control render to draw sprites from front to back + // i'm not use it, is right ??? + + turbofrc_drawsprites(0, 0); + turbofrc_drawsprites(0,-1); + turbofrc_drawsprites(1, 0); + turbofrc_drawsprites(1,-1); + + return 0; +} + +static INT32 turbofrcFrame() +{ + if (DrvReset) DrvDoReset(); + + // Compile digital inputs + // Compile digital inputs + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Joy3 + DrvInput[3] = 0x00; // Buttons + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvJoy3[i] & 1) << i; + DrvInput[3] |= (DrvButton[i] & 1) << i; + } + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) turbofrcDraw(); + + return 0; +} + +struct BurnDriver BurnDrvTurbofrc = { + "turbofrc", NULL, NULL, NULL, "1991", + "Turbo Force\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 3, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, turbofrcRomInfo, turbofrcRomName, NULL, NULL, turbofrcInputInfo, turbofrcDIPInfo, + turbofrcInit,DrvExit,turbofrcFrame,turbofrcDraw,DrvScan, + NULL, 0x800,240,352,3,4 +}; + + +// ------------------------------------------------------------ + +static struct BurnInputInfo karatblzInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 2, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 3, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 4"}, + + {"P3 Coin", BIT_DIGITAL, DrvButton + 4, "p3 coin"}, + {"P3 Start", BIT_DIGITAL, DrvButton + 6, "p3 start"}, + + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up"}, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down"}, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left"}, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right"}, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1"}, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2"}, + {"P3 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p3 fire 3"}, + {"P3 Button 4", BIT_DIGITAL, DrvJoy3 + 7, "p3 fire 4"}, + + {"P4 Coin", BIT_DIGITAL, DrvButton + 5, "p4 coin"}, + {"P4 Start", BIT_DIGITAL, DrvButton + 7, "p4 start"}, + + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 0, "p4 up"}, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 1, "p4 down"}, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 2, "p4 left"}, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 3, "p4 right"}, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1"}, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2"}, + {"P4 Button 3", BIT_DIGITAL, DrvJoy4 + 6, "p4 fire 3"}, + {"P4 Button 4", BIT_DIGITAL, DrvJoy4 + 7, "p4 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 6, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 7, "dip"}, +}; + +STDINPUTINFO(karatblz) + +static struct BurnDIPInfo karatblzDIPList[] = { + + // Defaults + {0x29, 0xFF, 0xFF, 0x00, NULL}, + {0x2A, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 8, "Coinage"}, + {0x29, 0x01, 0x07, 0x00, "1 coin 1 credit"}, + {0x29, 0x01, 0x07, 0x01, "2 coins 1 credit"}, + {0x29, 0x01, 0x07, 0x02, "3 coins 1 credit"}, + {0x29, 0x01, 0x07, 0x03, "4 coins 1 credit"}, + {0x29, 0x01, 0x07, 0x04, "1 coin 2 credit"}, + {0x29, 0x01, 0x07, 0x05, "1 coin 3 credit"}, + {0x29, 0x01, 0x07, 0x06, "1 coin 5 credit"}, + {0x29, 0x01, 0x07, 0x07, "1 coin 6 credit"}, + {0, 0xFE, 0, 2, "2 Coins to Start, 1 to Continue"}, + {0x29, 0x01, 0x08, 0x00, "Off"}, + {0x29, 0x01, 0x08, 0x08, "On"}, + {0, 0xFE, 0, 2, "Lives"}, + {0x29, 0x01, 0x10, 0x00, "2"}, + {0x29, 0x01, 0x10, 0x10, "1"}, + {0, 0xFE, 0, 4, "Cabinet"}, + {0x29, 0x01, 0x60, 0x00, "2 Players"}, + {0x29, 0x01, 0x60, 0x20, "3 Players"}, + {0x29, 0x01, 0x60, 0x40, "4 Players"}, + {0x29, 0x01, 0x60, 0x60, "4 Players (Team)"}, + {0, 0xFE, 0, 2, "Coin Slot"}, + {0x29, 0x01, 0x80, 0x00, "Same"}, + {0x29, 0x01, 0x80, 0x80, "Individual"}, + + // DIP 2 + {0, 0xFE, 0, 2, "Unknown"}, + {0x2A, 0x01, 0x01, 0x00, "Off"}, + {0x2A, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 4, "Number of Enemies"}, + {0x2A, 0x01, 0x06, 0x00, "Normal"}, + {0x2A, 0x01, 0x06, 0x02, "Easy"}, + {0x2A, 0x01, 0x06, 0x04, "Hard"}, + {0x2A, 0x01, 0x06, 0x06, "Hardest"}, + {0, 0xFE, 0, 4, "Strength of Enemies"}, + {0x2A, 0x01, 0x18, 0x00, "Normal"}, + {0x2A, 0x01, 0x18, 0x08, "Easy"}, + {0x2A, 0x01, 0x18, 0x10, "Hard"}, + {0x2A, 0x01, 0x18, 0x18, "Hardest"}, + {0, 0xFE, 0, 2, "Freeze"}, + {0x2A, 0x01, 0x20, 0x00, "Off"}, + {0x2A, 0x01, 0x20, 0x20, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x2A, 0x01, 0x40, 0x00, "Off"}, + {0x2A, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x2A, 0x01, 0x80, 0x00, "Off"}, + {0x2A, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(karatblz) + +static struct BurnRomInfo karatblzRomDesc[] = { + { "rom2v3", 0x040000, 0x01f772e1, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "1.u15", 0x040000, 0xd16ee21b, BRF_ESS | BRF_PRG }, + + { "gha.u55", 0x080000, 0x3e0cea91, BRF_GRA }, // gfx1 + { "gh9.u61", 0x080000, 0x5d1676bd, BRF_GRA }, // gfx2 + + { "u42", 0x100000, 0x65f0da84, BRF_GRA }, // gfx3 + { "3.u44", 0x020000, 0x34bdead2, BRF_GRA }, + { "u43", 0x100000, 0x7b349e5d, BRF_GRA }, + { "4.u45", 0x020000, 0xbe4d487d, BRF_GRA }, + + { "u59.ghb", 0x080000, 0x158c9cde, BRF_GRA }, // gfx4 + { "ghd.u60", 0x080000, 0x73180ae3, BRF_GRA }, + + { "5.u92", 0x020000, 0x97d67510, BRF_ESS | BRF_PRG }, // Sound CPU + + { "u105.gh8", 0x080000, 0x7a68cb1b, BRF_SND }, // samples + { "u104", 0x100000, 0x5795e884, BRF_SND }, +}; + +STD_ROM_PICK(karatblz) +STD_ROM_FN(karatblz) + +static struct BurnRomInfo karatbluRomDesc[] = { + { "2.u14", 0x040000, 0x202e6220, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "1.u15", 0x040000, 0xd16ee21b, BRF_ESS | BRF_PRG }, + + { "gha.u55", 0x080000, 0x3e0cea91, BRF_GRA }, // gfx1 + { "gh9.u61", 0x080000, 0x5d1676bd, BRF_GRA }, // gfx2 + + { "u42", 0x100000, 0x65f0da84, BRF_GRA }, // gfx3 + { "3.u44", 0x020000, 0x34bdead2, BRF_GRA }, + { "u43", 0x100000, 0x7b349e5d, BRF_GRA }, + { "4.u45", 0x020000, 0xbe4d487d, BRF_GRA }, + + { "u59.ghb", 0x080000, 0x158c9cde, BRF_GRA }, // gfx4 + { "ghd.u60", 0x080000, 0x73180ae3, BRF_GRA }, + + { "5.u92", 0x020000, 0x97d67510, BRF_ESS | BRF_PRG }, // Sound CPU + + { "u105.gh8", 0x080000, 0x7a68cb1b, BRF_SND }, // samples + { "u104", 0x100000, 0x5795e884, BRF_SND }, +}; + +STD_ROM_PICK(karatblu) +STD_ROM_FN(karatblu) + +static struct BurnRomInfo karatbljRomDesc[] = { + { "2tecmo.u14", 0x040000, 0x57e52654, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "1.u15", 0x040000, 0xd16ee21b, BRF_ESS | BRF_PRG }, + + { "gha.u55", 0x080000, 0x3e0cea91, BRF_GRA }, // gfx1 + { "gh9.u61", 0x080000, 0x5d1676bd, BRF_GRA }, // gfx2 + + { "u42", 0x100000, 0x65f0da84, BRF_GRA }, // gfx3 + { "3.u44", 0x020000, 0x34bdead2, BRF_GRA }, + { "u43", 0x100000, 0x7b349e5d, BRF_GRA }, + { "4.u45", 0x020000, 0xbe4d487d, BRF_GRA }, + + { "u59.ghb", 0x080000, 0x158c9cde, BRF_GRA }, // gfx4 + { "ghd.u60", 0x080000, 0x73180ae3, BRF_GRA }, + + { "5.u92", 0x020000, 0x97d67510, BRF_ESS | BRF_PRG }, // Sound CPU + + { "u105.gh8", 0x080000, 0x7a68cb1b, BRF_SND }, // samples + { "u104", 0x100000, 0x5795e884, BRF_SND }, +}; + +STD_ROM_PICK(karatblj) +STD_ROM_FN(karatblj) + +UINT8 __fastcall karatblzReadByte(UINT32 sekAddress) +{ + sekAddress &= 0x0FFFFF; + + switch (sekAddress) { + case 0x0FF000: + return ~DrvInput[4]; + case 0x0FF001: + return ~DrvInput[0]; + case 0x0FF002: + return 0xFF; + case 0x0FF003: + return ~DrvInput[1]; + case 0x0FF004: + return ~DrvInput[5]; + case 0x0FF005: + return ~DrvInput[2]; + case 0x0FF006: + return 0xFF; + case 0x0FF007: + return ~DrvInput[3]; + case 0x0FF008: + return ~DrvInput[7]; + case 0x0FF009: + return ~DrvInput[6]; + case 0x0FF00B: + return pending_command; + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +/* +UINT16 __fastcall karatblzReadWord(UINT32 sekAddress) +{ + sekAddress &= 0x0FFFFF; + + switch (sekAddress) { + + + default: + printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} +*/ + +void __fastcall karatblzWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress &= 0x0FFFFF; + + switch (sekAddress) { + case 0x0FF000: + case 0x0FF401: + case 0x0FF403: + + break; + + case 0x0FF002: + //if (ACCESSING_MSB) { + // setbank(bg1_tilemap,0,(data & 0x0100) >> 8); + // setbank(bg2_tilemap,1,(data & 0x0800) >> 11); + //} + RamGfxBank[0] = (byteValue & 0x1); + RamGfxBank[1] = (byteValue & 0x8) >> 3; + break; + case 0x0FF007: + pending_command = 1; + SoundCommand(byteValue); + break; +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall karatblzWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (( sekAddress & 0x0FF000 ) == 0x0FE000) { + sekAddress &= 0x07FF; + *((UINT16 *)&RamPal[sekAddress]) = wordValue; + RamCurPal[sekAddress>>1] = CalcCol( wordValue ); + return; + } + + sekAddress &= 0x0FFFFF; + + + switch (sekAddress) { + case 0x0ff008: + bg1scrollx = wordValue; + break; + case 0x0ff00A: + bg1scrolly = wordValue; + break; + case 0x0ff00C: + bg2scrollx = wordValue; + break; + case 0x0ff00E: + bg2scrolly = wordValue; + break; +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 karatblzMemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68000 ROM + RomZ80 = Next; Next += 0x030000; // Z80 ROM + + RomBg = Next; Next += 0x200040; // Background, 1M 8x8x4bit decode to 2M + 64Byte safe + DeRomBg = RomBg + 0x000040; + + RomSpr1 = Next; Next += 0x800000; // Sprite 1 , 1M 16x16x4bit decode to 2M + 256Byte safe + RomSpr2 = Next; Next += 0x200100; // Sprite 2 + + DeRomSpr1 = RomSpr1 + 0x000100; + DeRomSpr2 = RomSpr2 += 0x000100; + + RomSnd1 = Next; Next += 0x080000; // ADPCM data + RomSndSize1 = 0x080000; + RomSnd2 = Next; Next += 0x100000; // ADPCM data + RomSndSize2 = 0x100000; + + RamStart = Next; + + RamBg1V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG1 Video Ram + RamBg2V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG2 Video Ram + RamSpr1 = (UINT16 *)Next; Next += 0x008000 * sizeof(UINT16); // Sprite 1 Ram + RamSpr2 = (UINT16 *)Next; Next += 0x008000 * sizeof(UINT16); // Sprite 2 Ram + RamSpr3 = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // Sprite 3 Ram + Ram01 = Next; Next += 0x014000; // Work Ram 1 + Work Ram 1 + RamPal = Next; Next += 0x000800; // 1024 of X1R5G5B5 Palette + RamZ80 = Next; Next += 0x000800; // Z80 Ram 2K + + RamSpr1SizeMask = 0x7FFF; + RamSpr2SizeMask = 0x7FFF; + RomSpr1SizeMask = 0x7FFF; + RomSpr2SizeMask = 0x1FFF; + + RamEnd = Next; + + RamCurPal = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + + MemEnd = Next; + return 0; +} + +static INT32 karatblzInit() +{ + Mem = NULL; + karatblzMemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + karatblzMemIndex(); + + // Load 68000 ROM + if (BurnLoadRom(Rom01+0x00000, 0, 1)) return 1; + if (BurnLoadRom(Rom01+0x40000, 1, 1)) return 1; + + // Load Graphic + BurnLoadRom(RomBg+0x00000, 2, 1); + BurnLoadRom(RomBg+0x80000, 3, 1); + pspikesDecodeBg(0x10000); + + BurnLoadRom(RomSpr1+0x000000, 4, 2); + BurnLoadRom(RomSpr1+0x000001, 6, 2); + BurnLoadRom(RomSpr1+0x200000, 5, 2); + BurnLoadRom(RomSpr1+0x200001, 7, 2); + BurnLoadRom(RomSpr1+0x400000, 8, 2); + BurnLoadRom(RomSpr1+0x400001, 9, 2); + pspikesDecodeSpr(DeRomSpr1, RomSpr1, 0xA000); + + // Load Z80 ROM + if (BurnLoadRom(RomZ80+0x10000, 10, 1)) return 1; + memcpy(RomZ80, RomZ80+0x10000, 0x10000); + + BurnLoadRom(RomSnd1, 11, 1); + BurnLoadRom(RomSnd2, 12, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamBg1V, + 0x080000, 0x081FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg2V, + 0x082000, 0x083FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr1, + 0x0A0000, 0x0AFFFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr2, + 0x0B0000, 0x0BFFFF, SM_RAM); + SekMapMemory(Ram01, 0x0C0000, 0x0CFFFF, SM_RAM); // 64K Work RAM + SekMapMemory(Ram01+0x10000, 0x0F8000, 0x0FBFFF, SM_RAM); // Work RAM + SekMapMemory(Ram01+0x10000, 0xFF8000, 0xFFBFFF, SM_RAM); // Work RAM + SekMapMemory((UINT8 *)RamSpr3, + 0x0FC000, 0x0FC7FF, SM_RAM); + SekMapMemory(RamPal, 0x0FE000, 0x0FE7FF, SM_ROM); // Palette + +// SekSetReadWordHandler(0, karatblzReadWord); + SekSetReadByteHandler(0, karatblzReadByte); + SekSetWriteWordHandler(0, karatblzWriteWord); + SekSetWriteByteHandler(0, karatblzWriteByte); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x77FF, 0, RomZ80); + ZetMapArea(0x0000, 0x77FF, 2, RomZ80); + + ZetMapArea(0x7800, 0x7FFF, 0, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 1, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 2, RamZ80); + + ZetMemEnd(); + + ZetSetInHandler(turbofrcZ80PortRead); + ZetSetOutHandler(turbofrcZ80PortWrite); + + ZetClose(); + } + + BurnYM2610Init(8000000, RomSnd2, &RomSndSize2, RomSnd1, &RomSndSize1, &aerofgtFMIRQHandler, aerofgtSynchroniseStream, aerofgtGetTime, 0); + BurnTimerAttachZet(4000000); + + DrvDoReset(); + + return 0; +} + +static void karatblzTileBackground_1(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (((INT16)bg1scrollx + 8)& 0x1FF); + if (x <= (352-512)) x += 512; + + y = my * 8 - (bg1scrolly & 0x1FF); + if (y <= (240-512)) y += 512; + + if ( x<=-8 || x>=352 || y<=-8 || y>= 240 ) + continue; + + else + if ( x >=0 && x < (352-8) && y >= 0 && y < (240-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x1FFF) + ( RamGfxBank[0] << 13 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + p[0] = pal[ d[0] | c ]; + p[1] = pal[ d[1] | c ]; + p[2] = pal[ d[2] | c ]; + p[3] = pal[ d[3] | c ]; + p[4] = pal[ d[4] | c ]; + p[5] = pal[ d[5] | c ]; + p[6] = pal[ d[6] | c ]; + p[7] = pal[ d[7] | c ]; + + d += 8; + p += 352; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x1FFF) + ( RamGfxBank[0] << 13 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<240 ) { + if ((x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 352; + } + + } + + } +} + +static void karatblzTileBackground_2(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - ( ((INT16)bg2scrollx + 4) & 0x1FF); + if (x <= (352-512)) x += 512; + + y = my * 8 - (bg2scrolly & 0x1FF); + if (y <= (240-512)) y += 512; + + if ( x<=-8 || x>=352 || y<=-8 || y>= 240 ) + continue; + else + if ( x >=0 && x < (352-8) && y >= 0 && y < (240-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x1FFF) + ( RamGfxBank[1] << 13 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + + if (d[0] != 15) p[0] = pal[ d[0] | c ]; + if (d[1] != 15) p[1] = pal[ d[1] | c ]; + if (d[2] != 15) p[2] = pal[ d[2] | c ]; + if (d[3] != 15) p[3] = pal[ d[3] | c ]; + if (d[4] != 15) p[4] = pal[ d[4] | c ]; + if (d[5] != 15) p[5] = pal[ d[5] | c ]; + if (d[6] != 15) p[6] = pal[ d[6] | c ]; + if (d[7] != 15) p[7] = pal[ d[7] | c ]; + + d += 8; + p += 352; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x1FFF) + ( RamGfxBank[1] << 13 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<240 ) { + if (d[0] != 15 && (x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if (d[1] != 15 && (x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if (d[2] != 15 && (x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if (d[3] != 15 && (x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if (d[4] != 15 && (x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if (d[5] != 15 && (x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if (d[6] != 15 && (x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if (d[7] != 15 && (x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 352; + } + + } + + } +} + +static INT32 karatblzDraw() +{ + karatblzTileBackground_1(RamBg1V, DeRomBg, RamCurPal); + karatblzTileBackground_2(RamBg2V, DeRomBg + 0x100000, RamCurPal + 256); + +/* + turbofrc_drawsprites(1,-1); + turbofrc_drawsprites(1, 0); + turbofrc_drawsprites(0,-1); + turbofrc_drawsprites(0, 0); +*/ + + turbofrc_drawsprites(0, 0); + turbofrc_drawsprites(0,-1); + turbofrc_drawsprites(1, 0); + turbofrc_drawsprites(1,-1); + + return 0; +} + +static INT32 karatblzFrame() +{ + if (DrvReset) DrvDoReset(); + + // Compile digital inputs + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Joy3 + DrvInput[3] = 0x00; // Joy4 + DrvInput[4] = 0x00; // Buttons1 + DrvInput[5] = 0x00; // Buttons2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvJoy3[i] & 1) << i; + DrvInput[3] |= (DrvJoy4[i] & 1) << i; + } + for (INT32 i = 0; i < 4; i++) { + DrvInput[4] |= (DrvButton[i] & 1) << i; + DrvInput[5] |= (DrvButton[i+4] & 1) << i; + } + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) karatblzDraw(); + + return 0; +} + +struct BurnDriver BurnDrvKaratblz = { + "karatblz", NULL, NULL, NULL, "1991", + "Karate Blazers (World?)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 4, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, karatblzRomInfo, karatblzRomName, NULL, NULL, karatblzInputInfo, karatblzDIPInfo, + karatblzInit,DrvExit,karatblzFrame,karatblzDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +struct BurnDriver BurnDrvKaratblu = { + "karatblzu", "karatblz", NULL, NULL, "1991", + "Karate Blazers (US)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 4, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, karatbluRomInfo, karatbluRomName, NULL, NULL, karatblzInputInfo, karatblzDIPInfo, + karatblzInit,DrvExit,karatblzFrame,karatblzDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +struct BurnDriver BurnDrvKaratblj = { + "karatblzj", "karatblz", NULL, NULL, "1991", + "Karate Blazers (Japan)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 4, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, karatbljRomInfo, karatbljRomName, NULL, NULL, karatblzInputInfo, karatblzDIPInfo, + karatblzInit,DrvExit,karatblzFrame,karatblzDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +// ----------------------------------------------------------- + +static struct BurnInputInfo spinlbrkInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 2, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 3, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(spinlbrk) + +static struct BurnDIPInfo spinlbrkDIPList[] = { + + // Defaults + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 16, "Coin A"}, + {0x13, 0x01, 0x0F, 0x00, "1-1C 1-2 HPs"}, + {0x13, 0x01, 0x0F, 0x01, "1-1-1-1C 1-1-1-2 HPs"}, + {0x13, 0x01, 0x0F, 0x02, "1-1-1-1-1C 1-1-1-1-2 HPs"}, + {0x13, 0x01, 0x0F, 0x03, "2-2C 1-2 HPs"}, + {0x13, 0x01, 0x0F, 0x04, "2-1-1C 1-1-1 HPs"}, + {0x13, 0x01, 0x0F, 0x05, "2 Credits 2 Health Packs"}, + {0x13, 0x01, 0x0F, 0x06, "5 Credits 1 Health Pack"}, + {0x13, 0x01, 0x0F, 0x07, "4 Credits 1 Health Pack"}, + {0x13, 0x01, 0x0F, 0x08, "3 Credits 1 Health Pack"}, + {0x13, 0x01, 0x0F, 0x09, "2 Credits 1 Health Pack"}, + {0x13, 0x01, 0x0F, 0x0A, "1 Credit 6 Health Packs"}, + {0x13, 0x01, 0x0F, 0x0B, "1 Credit 5 Health Packs"}, + {0x13, 0x01, 0x0F, 0x0C, "1 Credit 4 Health Packs"}, + {0x13, 0x01, 0x0F, 0x0D, "1 Credit 3 Health Packs"}, + {0x13, 0x01, 0x0F, 0x0E, "1 Credit 2 Health Packs"}, + {0x13, 0x01, 0x0F, 0x0F, "1 Credit 1 Health Pack"}, + {0, 0xFE, 0, 16, "Coin A"}, + {0x13, 0x01, 0xF0, 0x00, "1-1C 1-2 HPs"}, + {0x13, 0x01, 0xF0, 0x10, "1-1-1-1C 1-1-1-2 HPs"}, + {0x13, 0x01, 0xF0, 0x20, "1-1-1-1-1C 1-1-1-1-2 HPs"}, + {0x13, 0x01, 0xF0, 0x30, "2-2C 1-2 HPs"}, + {0x13, 0x01, 0xF0, 0x40, "2-1-1C 1-1-1 HPs"}, + {0x13, 0x01, 0xF0, 0x50, "2 Credits 2 Health Packs"}, + {0x13, 0x01, 0xF0, 0x60, "5 Credits 1 Health Pack"}, + {0x13, 0x01, 0xF0, 0x70, "4 Credits 1 Health Pack"}, + {0x13, 0x01, 0xF0, 0x80, "3 Credits 1 Health Pack"}, + {0x13, 0x01, 0xF0, 0x90, "2 Credits 1 Health Pack"}, + {0x13, 0x01, 0xF0, 0xA0, "1 Credit 6 Health Packs"}, + {0x13, 0x01, 0xF0, 0xB0, "1 Credit 5 Health Packs"}, + {0x13, 0x01, 0xF0, 0xC0, "1 Credit 4 Health Packs"}, + {0x13, 0x01, 0xF0, 0xD0, "1 Credit 3 Health Packs"}, + {0x13, 0x01, 0xF0, 0xE0, "1 Credit 2 Health Packs"}, + {0x13, 0x01, 0xF0, 0xF0, "1 Credit 1 Health Pack"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x14, 0x01, 0x03, 0x00, "Normal"}, + {0x14, 0x01, 0x03, 0x01, "Easy"}, + {0x14, 0x01, 0x03, 0x02, "Hard"}, + {0x14, 0x01, 0x03, 0x03, "Hardest"}, +}; + +static struct BurnDIPInfo spinlbrk_DIPList[] = { + + {0, 0xFE, 0, 2, "Coin Slot"}, + {0x14, 0x01, 0x04, 0x00, "Individuala"}, + {0x14, 0x01, 0x04, 0x04, "Same"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x14, 0x01, 0x08, 0x00, "Off"}, + {0x14, 0x01, 0x08, 0x08, "On"}, + + {0, 0xFE, 0, 2, "Lever Type"}, + {0x14, 0x01, 0x10, 0x00, "Digital"}, + {0x14, 0x01, 0x10, 0x10, "Analog"}, + {0, 0xFE, 0, 2, "Service"}, + {0x14, 0x01, 0x20, 0x00, "Off"}, + {0x14, 0x01, 0x20, 0x20, "On"}, + {0, 0xFE, 0, 2, "Health Pack"}, + {0x14, 0x01, 0x40, 0x00, "32 Hitpoints"}, + {0x14, 0x01, 0x40, 0x40, "40 Hitpoints"}, + {0, 0xFE, 0, 2, "Life Restoration"}, + {0x14, 0x01, 0x80, 0x00, "10 Points"}, + {0x14, 0x01, 0x80, 0x80, "5 Points"}, + +}; + +STDDIPINFOEXT(spinlbrk, spinlbrk, spinlbrk_) + +static struct BurnDIPInfo spinlbru_DIPList[] = { + + {0, 0xFE, 0, 2, "Coin Slot"}, + {0x14, 0x01, 0x04, 0x00, "Individuala"}, + {0x14, 0x01, 0x04, 0x04, "Same"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x14, 0x01, 0x08, 0x00, "Off"}, + {0x14, 0x01, 0x08, 0x08, "On"}, + + {0, 0xFE, 0, 2, "Lever Type"}, + {0x14, 0x01, 0x10, 0x00, "Digital"}, + {0x14, 0x01, 0x10, 0x10, "Analog"}, + {0, 0xFE, 0, 2, "Service"}, + {0x14, 0x01, 0x20, 0x00, "Off"}, + {0x14, 0x01, 0x20, 0x20, "On"}, + {0, 0xFE, 0, 2, "Health Pack"}, + {0x14, 0x01, 0x40, 0x00, "20 Hitpoints"}, + {0x14, 0x01, 0x40, 0x40, "32 Hitpoints"}, + {0, 0xFE, 0, 2, "Life Restoration"}, + {0x14, 0x01, 0x80, 0x00, "10 Points"}, + {0x14, 0x01, 0x80, 0x80, "5 Points"}, + +}; + +STDDIPINFOEXT(spinlbru, spinlbrk, spinlbru_) + +static struct BurnDIPInfo spinlbrj_DIPList[] = { + + {0, 0xFE, 0, 2, "Continue"}, + {0x14, 0x01, 0x04, 0x00, "Unlimited"}, + {0x14, 0x01, 0x04, 0x04, "6 Times"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x14, 0x01, 0x08, 0x00, "Off"}, + {0x14, 0x01, 0x08, 0x08, "On"}, + + {0, 0xFE, 0, 2, "Lever Type"}, + {0x14, 0x01, 0x10, 0x00, "Digital"}, + {0x14, 0x01, 0x10, 0x10, "Analog"}, + {0, 0xFE, 0, 2, "Service"}, + {0x14, 0x01, 0x20, 0x00, "Off"}, + {0x14, 0x01, 0x20, 0x20, "On"}, + {0, 0xFE, 0, 2, "Health Pack"}, + {0x14, 0x01, 0x40, 0x00, "32 Hitpoints"}, + {0x14, 0x01, 0x40, 0x40, "40 Hitpoints"}, + {0, 0xFE, 0, 2, "Life Restoration"}, + {0x14, 0x01, 0x80, 0x00, "10 Points"}, + {0x14, 0x01, 0x80, 0x80, "5 Points"}, + +}; + +STDDIPINFOEXT(spinlbrj, spinlbrk, spinlbrj_) + +static struct BurnRomInfo spinlbrkRomDesc[] = { + { "ic98", 0x010000, 0x36c2bf70, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "ic104", 0x010000, 0x34a7e158, BRF_ESS | BRF_PRG }, + { "ic93", 0x010000, 0x726f4683, BRF_ESS | BRF_PRG }, + { "ic94", 0x010000, 0xc4385e03, BRF_ESS | BRF_PRG }, + + { "ic15", 0x080000, 0xe318cf3a, BRF_GRA }, // gfx 1 + { "ic9", 0x080000, 0xe071f674, BRF_GRA }, + + { "ic17", 0x080000, 0xa63d5a55, BRF_GRA }, // gfx 2 + { "ic11", 0x080000, 0x7dcc913d, BRF_GRA }, + { "ic16", 0x080000, 0x0d84af7f, BRF_GRA }, + + { "ic12", 0x080000, 0xd63fac4e, BRF_GRA }, // gfx 3 + { "ic18", 0x080000, 0x5a60444b, BRF_GRA }, + + { "ic14", 0x080000, 0x1befd0f3, BRF_GRA }, // gfx 4 + { "ic20", 0x080000, 0xc2f84a61, BRF_GRA }, + { "ic35", 0x080000, 0xeba8e1a3, BRF_GRA }, + { "ic40", 0x080000, 0x5ef5aa7e, BRF_GRA }, + + { "ic19", 0x010000, 0xdb24eeaa, BRF_GRA }, // gfx 5, hardcoded sprite maps + { "ic13", 0x010000, 0x97025bf4, BRF_GRA }, + + { "ic117", 0x008000, 0x625ada41, BRF_ESS | BRF_PRG }, // Sound CPU + { "ic118", 0x010000, 0x1025f024, BRF_ESS | BRF_PRG }, + + { "ic166", 0x080000, 0x6e0d063a, BRF_SND }, // samples + { "ic163", 0x080000, 0xe6621dfb, BRF_SND }, + + { "epl16p8bp.ic100", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic127", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic133", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic99", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic114", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic95", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(spinlbrk) +STD_ROM_FN(spinlbrk) + +static struct BurnRomInfo spinlbruRomDesc[] = { + { "ic98.u5", 0x010000, 0x3a0f7667, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "ic104.u6", 0x010000, 0xa0e0af31, BRF_ESS | BRF_PRG }, + { "ic93.u4", 0x010000, 0x0cf73029, BRF_ESS | BRF_PRG }, + { "ic94.u3", 0x010000, 0x5cf7c426, BRF_ESS | BRF_PRG }, + + { "ic15", 0x080000, 0xe318cf3a, BRF_GRA }, // gfx 1 + { "ic9", 0x080000, 0xe071f674, BRF_GRA }, + + { "ic17", 0x080000, 0xa63d5a55, BRF_GRA }, // gfx 2 + { "ic11", 0x080000, 0x7dcc913d, BRF_GRA }, + { "ic16", 0x080000, 0x0d84af7f, BRF_GRA }, + + { "ic12", 0x080000, 0xd63fac4e, BRF_GRA }, // gfx 3 + { "ic18", 0x080000, 0x5a60444b, BRF_GRA }, + + { "ic14", 0x080000, 0x1befd0f3, BRF_GRA }, // gfx 4 + { "ic20", 0x080000, 0xc2f84a61, BRF_GRA }, + { "ic35", 0x080000, 0xeba8e1a3, BRF_GRA }, + { "ic40", 0x080000, 0x5ef5aa7e, BRF_GRA }, + + { "ic19", 0x010000, 0xdb24eeaa, BRF_GRA }, // gfx 5, hardcoded sprite maps + { "ic13", 0x010000, 0x97025bf4, BRF_GRA }, + + { "ic117", 0x008000, 0x625ada41, BRF_ESS | BRF_PRG }, // Sound CPU + { "ic118", 0x010000, 0x1025f024, BRF_ESS | BRF_PRG }, + + { "ic166", 0x080000, 0x6e0d063a, BRF_SND }, // samples + { "ic163", 0x080000, 0xe6621dfb, BRF_SND }, + + { "epl16p8bp.ic100", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic127", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic133", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic99", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic114", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic95", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(spinlbru) +STD_ROM_FN(spinlbru) + +static struct BurnRomInfo spinlbrjRomDesc[] = { + { "j5", 0x010000, 0x6a3d690e, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "j6", 0x010000, 0x869593fa, BRF_ESS | BRF_PRG }, + { "j4", 0x010000, 0x33e33912, BRF_ESS | BRF_PRG }, + { "j3", 0x010000, 0x16ca61d0, BRF_ESS | BRF_PRG }, + + { "ic15", 0x080000, 0xe318cf3a, BRF_GRA }, // gfx 1 + { "ic9", 0x080000, 0xe071f674, BRF_GRA }, + + { "ic17", 0x080000, 0xa63d5a55, BRF_GRA }, // gfx 2 + { "ic11", 0x080000, 0x7dcc913d, BRF_GRA }, + { "ic16", 0x080000, 0x0d84af7f, BRF_GRA }, + + { "ic12", 0x080000, 0xd63fac4e, BRF_GRA }, // gfx 3 + { "ic18", 0x080000, 0x5a60444b, BRF_GRA }, + + { "ic14", 0x080000, 0x1befd0f3, BRF_GRA }, // gfx 4 + { "ic20", 0x080000, 0xc2f84a61, BRF_GRA }, + { "ic35", 0x080000, 0xeba8e1a3, BRF_GRA }, + { "ic40", 0x080000, 0x5ef5aa7e, BRF_GRA }, + + { "ic19", 0x010000, 0xdb24eeaa, BRF_GRA }, // gfx 5, hardcoded sprite maps + { "ic13", 0x010000, 0x97025bf4, BRF_GRA }, + + { "ic117", 0x008000, 0x625ada41, BRF_ESS | BRF_PRG }, // Sound CPU + { "ic118", 0x010000, 0x1025f024, BRF_ESS | BRF_PRG }, + + { "ic166", 0x080000, 0x6e0d063a, BRF_SND }, // samples + { "ic163", 0x080000, 0xe6621dfb, BRF_SND }, + + { "epl16p8bp.ic100", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic127", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic133", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "epl16p8bp.ic99", 263, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic114", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "gal16v8a.ic95", 279, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(spinlbrj) +STD_ROM_FN(spinlbrj) + +/* +UINT8 __fastcall spinlbrkReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} +*/ + +UINT16 __fastcall spinlbrkReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xFFF000: + return ~(DrvInput[0] | (DrvInput[2] << 8)); + case 0xFFF002: + return ~(DrvInput[1]); + case 0xFFF004: + return ~(DrvInput[3] | (DrvInput[4] << 8)); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} + + +void __fastcall spinlbrkWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0xFFF401: + case 0xFFF403: + // NOP + break; + + case 0xFFF007: + pending_command = 1; + SoundCommand(byteValue); + break; + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall spinlbrkWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + + if (( sekAddress & 0xFFF000 ) == 0xFFE000) { + sekAddress &= 0x07FF; + *((UINT16 *)&RamPal[sekAddress]) = wordValue; + RamCurPal[sekAddress>>1] = CalcCol( wordValue ); + return; + } + + switch (sekAddress) { + case 0xFFF000: + RamGfxBank[0] = (wordValue & 0x07); + RamGfxBank[1] = (wordValue & 0x38) >> 3; + break; + case 0xFFF002: + bg2scrollx = wordValue; + break; + case 0xFFF008: + // NOP + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 spinlbrkMemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // 68000 ROM + RomZ80 = Next; Next += 0x030000; // Z80 ROM + + RomBg = Next; Next += 0x500040; // Background, 2.5M 8x8x4bit + DeRomBg = RomBg + 0x000040; + + RomSpr1 = Next; Next += 0x200000; // Sprite 1 + RomSpr2 = Next; Next += 0x400100; // Sprite 2 + + DeRomSpr1 = RomSpr1 + 0x000100; + DeRomSpr2 = RomSpr2 += 0x000100; + + RomSnd2 = Next; Next += 0x100000; // ADPCM data + RomSnd1 = RomSnd2; + + RomSndSize1 = 0x100000; + RomSndSize2 = 0x100000; + + RamSpr2 = (UINT16 *)Next; Next += 0x010000 * sizeof(UINT16); // Sprite 2 Ram + RamSpr1 = (UINT16 *)Next; Next += 0x002000 * sizeof(UINT16); // Sprite 1 Ram + + RamStart = Next; + + RamBg1V = (UINT16 *)Next; Next += 0x000800 * sizeof(UINT16); // BG1 Video Ram + RamBg2V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG2 Video Ram + Ram01 = Next; Next += 0x004000; // Work Ram + RamSpr3 = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // Sprite 3 Ram + RamRaster = (UINT16 *)Next; Next += 0x000100 * sizeof(UINT16); // Raster + RamPal = Next; Next += 0x000800; // 1024 of X1R5G5B5 Palette + RamZ80 = Next; Next += 0x000800; // Z80 Ram 2K + + RamSpr1SizeMask = 0x1FFF; + RamSpr2SizeMask = 0xFFFF; + + RomSpr1SizeMask = 0x1FFF; + RomSpr2SizeMask = 0x3FFF; + + RamEnd = Next; + + RamCurPal = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + + MemEnd = Next; + return 0; +} + +static INT32 spinlbrkInit() +{ + Mem = NULL; + spinlbrkMemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + spinlbrkMemIndex(); + + // Load 68000 ROM + if (BurnLoadRom(Rom01+0x00001, 0, 2)) return 1; + if (BurnLoadRom(Rom01+0x00000, 1, 2)) return 1; + if (BurnLoadRom(Rom01+0x20001, 2, 2)) return 1; + if (BurnLoadRom(Rom01+0x20000, 3, 2)) return 1; + + // Load Graphic + BurnLoadRom(RomBg+0x000000, 4, 1); + BurnLoadRom(RomBg+0x080000, 5, 1); + BurnLoadRom(RomBg+0x100000, 6, 1); + BurnLoadRom(RomBg+0x180000, 7, 1); + BurnLoadRom(RomBg+0x200000, 8, 1); + pspikesDecodeBg(0x14000); + + BurnLoadRom(RomSpr1+0x000000, 9, 2); + BurnLoadRom(RomSpr1+0x000001, 10, 2); + BurnLoadRom(RomSpr1+0x100000, 11, 2); + BurnLoadRom(RomSpr1+0x100001, 13, 2); + BurnLoadRom(RomSpr1+0x200000, 12, 2); + BurnLoadRom(RomSpr1+0x200001, 14, 2); + pspikesDecodeSpr(DeRomSpr1, RomSpr1, 0x6000); + + BurnLoadRom((UINT8 *)RamSpr2+0x000001, 15, 2); + BurnLoadRom((UINT8 *)RamSpr2+0x000000, 16, 2); + + // Load Z80 ROM + if (BurnLoadRom(RomZ80+0x00000, 17, 1)) return 1; + if (BurnLoadRom(RomZ80+0x08000, 18, 1)) return 1; + + BurnLoadRom(RomSnd2+0x00000, 19, 1); + BurnLoadRom(RomSnd2+0x80000, 20, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x04FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamBg1V, + 0x080000, 0x080FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg2V, + 0x082000, 0x083FFF, SM_RAM); + SekMapMemory(Ram01, 0xFF8000, 0xFFBFFF, SM_RAM); // Work RAM + SekMapMemory((UINT8 *)RamSpr3, + 0xFFC000, 0xFFC7FF, SM_RAM); + SekMapMemory((UINT8 *)RamRaster, + 0xFFD000, 0xFFD1FF, SM_RAM); + SekMapMemory(RamPal, 0xFFE000, 0xFFE7FF, SM_ROM); // Palette + + SekSetReadWordHandler(0, spinlbrkReadWord); +// SekSetReadByteHandler(0, spinlbrkReadByte); + SekSetWriteWordHandler(0, spinlbrkWriteWord); + SekSetWriteByteHandler(0, spinlbrkWriteByte); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x77FF, 0, RomZ80); + ZetMapArea(0x0000, 0x77FF, 2, RomZ80); + + ZetMapArea(0x7800, 0x7FFF, 0, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 1, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 2, RamZ80); + + ZetMemEnd(); + + ZetSetInHandler(turbofrcZ80PortRead); + ZetSetOutHandler(turbofrcZ80PortWrite); + + ZetClose(); + } + + BurnYM2610Init(8000000, RomSnd2, &RomSndSize2, RomSnd1, &RomSndSize1, &aerofgtFMIRQHandler, aerofgtSynchroniseStream, aerofgtGetTime, 0); + BurnTimerAttachZet(4000000); + + bg2scrollx = 0; // + + for (UINT16 i=0; i<0x2000;i++) + RamSpr1[i] = i; + + DrvDoReset(); + + return 0; +} + +static void spinlbrkTileBackground_1(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (RamRaster[my*8] & 0x1FF); // + 8 + if (x <= (352-512)) x += 512; + + y = my * 8; + + if ( x<=-8 || x>=352 || y<=-8 || y>= 240 ) + continue; + + else + if ( x >=0 && x < (352-8) && y >= 0 && y < (240-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x0FFF) + ( RamGfxBank[0] << 12 ) ) * 64; + UINT16 c = (bg[offs] & 0xF000) >> 8; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + p[0] = pal[ d[0] | c ]; + p[1] = pal[ d[1] | c ]; + p[2] = pal[ d[2] | c ]; + p[3] = pal[ d[3] | c ]; + p[4] = pal[ d[4] | c ]; + p[5] = pal[ d[5] | c ]; + p[6] = pal[ d[6] | c ]; + p[7] = pal[ d[7] | c ]; + + d += 8; + p += 352; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x0FFF) + ( RamGfxBank[0] << 12 ) ) * 64; + UINT16 c = (bg[offs] & 0xF000) >> 8; + UINT16 * p = (UINT16 *) pBurnDraw + y * 352 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<240 ) { + if ((x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 352; + } + + } + + } +} + +static INT32 spinlbrkDraw() +{ + spinlbrkTileBackground_1(RamBg1V, DeRomBg, RamCurPal); + karatblzTileBackground_2(RamBg2V, DeRomBg + 0x200000, RamCurPal + 256); + + turbofrc_drawsprites(1,-1); // enemy(near far) + turbofrc_drawsprites(1, 0); // enemy(near) fense + turbofrc_drawsprites(0, 0); // avatar , post , bullet + turbofrc_drawsprites(0,-1); + +/* + UINT16 *ps = RamCurPal; + UINT16 *pd = (UINT16 *)pBurnDraw; + for (INT32 j=0;j<32;j++) { + for (INT32 i=0;i<32;i++) { + *pd = *ps; + pd ++; + ps ++; + } + pd += 352 - 32; + } +*/ + return 0; +} + +static INT32 spinlbrkFrame() +{ + if (DrvReset) DrvDoReset(); + + // Compile digital inputs + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Buttons + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) spinlbrkDraw(); + + return 0; +} + +struct BurnDriver BurnDrvSpinlbrk = { + "spinlbrk", NULL, NULL, NULL, "1990", + "Spinal Breakers (World)\0", NULL, "V-System Co.", "V-System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, spinlbrkRomInfo, spinlbrkRomName, NULL, NULL, spinlbrkInputInfo, spinlbrkDIPInfo, + spinlbrkInit,DrvExit,spinlbrkFrame,spinlbrkDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +struct BurnDriver BurnDrvSpinlbru = { + "spinlbrku", "spinlbrk", NULL, NULL, "1990", + "Spinal Breakers (US)\0", NULL, "V-System Co.", "V-System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, spinlbruRomInfo, spinlbruRomName, NULL, NULL, spinlbrkInputInfo, spinlbruDIPInfo, + spinlbrkInit,DrvExit,spinlbrkFrame,spinlbrkDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +struct BurnDriver BurnDrvSpinlbrj = { + "spinlbrkj", "spinlbrk", NULL, NULL, "1990", + "Spinal Breakers (Japan)\0", NULL, "V-System Co.", "V-System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, spinlbrjRomInfo, spinlbrjRomName, NULL, NULL, spinlbrkInputInfo, spinlbrjDIPInfo, + spinlbrkInit,DrvExit,spinlbrkFrame,spinlbrkDraw,DrvScan, + NULL, 0x800,352,240,4,3 +}; + +// ------------------------------------------------------- + +static struct BurnDIPInfo aerofgtb_DIPList[] = { + + {0x14, 0xFF, 0xFF, 0x01, NULL}, + + // DIP 3 + {0, 0xFE, 0, 2, "Region"}, + {0x14, 0x01, 0x01, 0x00, "Taiwan"}, + {0x14, 0x01, 0x01, 0x01, "Japan"}, +}; + +STDDIPINFOEXT(aerofgtb, aerofgt, aerofgtb_) + +static struct BurnRomInfo aerofgtbRomDesc[] = { + { "v2", 0x040000, 0x5c9de9f0, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "v1", 0x040000, 0x89c1dcf4, BRF_ESS | BRF_PRG }, // 68000 code swapped + + { "it-19-03", 0x080000, 0x85eba1a4, BRF_GRA }, // graphics + { "it-19-02", 0x080000, 0x4f57f8ba, BRF_GRA }, + + { "it-19-04", 0x080000, 0x3b329c1f, BRF_GRA }, // + { "it-19-05", 0x080000, 0x02b525af, BRF_GRA }, // + + { "g27", 0x040000, 0x4d89cbc8, BRF_GRA }, + { "g26", 0x040000, 0x8072c1d2, BRF_GRA }, + + { "v3", 0x020000, 0xcbb18cf4, BRF_ESS | BRF_PRG }, // Sound CPU + + { "it-19-01", 0x040000, 0x6d42723d, BRF_SND }, // samples + { "it-19-06", 0x100000, 0xcdbbdb1d, BRF_SND }, +}; + +STD_ROM_PICK(aerofgtb) +STD_ROM_FN(aerofgtb) + +static struct BurnRomInfo aerofgtcRomDesc[] = { + { "v2.149", 0x040000, 0xf187aec6, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "v1.111", 0x040000, 0x9e684b19, BRF_ESS | BRF_PRG }, // 68000 code swapped + + { "it-19-03", 0x080000, 0x85eba1a4, BRF_GRA }, // graphics + { "it-19-02", 0x080000, 0x4f57f8ba, BRF_GRA }, + + { "it-19-04", 0x080000, 0x3b329c1f, BRF_GRA }, // + { "it-19-05", 0x080000, 0x02b525af, BRF_GRA }, // + + { "g27", 0x040000, 0x4d89cbc8, BRF_GRA }, + { "g26", 0x040000, 0x8072c1d2, BRF_GRA }, + + { "2.153", 0x020000, 0xa1ef64ec, BRF_ESS | BRF_PRG }, // Sound CPU + + { "it-19-01", 0x040000, 0x6d42723d, BRF_SND }, // samples + { "it-19-06", 0x100000, 0xcdbbdb1d, BRF_SND }, +}; + +STD_ROM_PICK(aerofgtc) +STD_ROM_FN(aerofgtc) + +static struct BurnRomInfo sonicwiRomDesc[] = { + { "2.149", 0x040000, 0x3d1b96ba, BRF_ESS | BRF_PRG }, // 68000 code swapped + { "1.111", 0x040000, 0xa3d09f94, BRF_ESS | BRF_PRG }, // 68000 code swapped + + { "it-19-03", 0x080000, 0x85eba1a4, BRF_GRA }, // graphics + { "it-19-02", 0x080000, 0x4f57f8ba, BRF_GRA }, + + { "it-19-04", 0x080000, 0x3b329c1f, BRF_GRA }, // + { "it-19-05", 0x080000, 0x02b525af, BRF_GRA }, // + + { "g27", 0x040000, 0x4d89cbc8, BRF_GRA }, + { "g26", 0x040000, 0x8072c1d2, BRF_GRA }, + + { "2.153", 0x020000, 0xa1ef64ec, BRF_ESS | BRF_PRG }, // Sound CPU + + { "it-19-01", 0x040000, 0x6d42723d, BRF_SND }, // samples + { "it-19-06", 0x100000, 0xcdbbdb1d, BRF_SND }, +}; + +STD_ROM_PICK(sonicwi) +STD_ROM_FN(sonicwi) + +UINT8 __fastcall aerofgtbReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x0FE000: + return ~DrvInput[2]; + case 0x0FE001: + return ~DrvInput[0]; + case 0x0FE002: + return 0xFF; + case 0x0FE003: + return ~DrvInput[1]; + case 0x0FE004: + return ~DrvInput[4]; + case 0x0FE005: + return ~DrvInput[3]; + case 0x0FE007: + return pending_command; + case 0x0FE009: + return ~DrvInput[5]; + + default: + printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +UINT16 __fastcall aerofgtbReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + + default: + printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} + +void __fastcall aerofgtbWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if (( sekAddress & 0x0FF000 ) == 0x0FD000) { + sekAddress &= 0x07FF; + RamPal[sekAddress^1] = byteValue; + // palette byte write at boot self-test only ?! + //if (sekAddress & 1) + // RamCurPal[sekAddress>>1] = CalcCol( *((UINT16 *)&RamPal[sekAddress & 0xFFE]) ); + return; + } + + switch (sekAddress) { + case 0x0FE001: + case 0x0FE401: + case 0x0FE403: + // NOP + break; + + case 0x0FE00E: + pending_command = 1; + SoundCommand(byteValue); + break; + + default: + printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall aerofgtbWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if (( sekAddress & 0x0FF000 ) == 0x0FD000) { + sekAddress &= 0x07FE; + *((UINT16 *)&RamPal[sekAddress]) = wordValue; + RamCurPal[sekAddress>>1] = CalcCol( wordValue ); + return; + } + + switch (sekAddress) { + case 0x0FE002: + bg1scrolly = wordValue; + break; + case 0x0FE004: + bg2scrollx = wordValue; + break; + case 0x0FE006: + bg2scrolly = wordValue; + break; + case 0x0FE008: + RamGfxBank[0] = (wordValue >> 0) & 0x0f; + RamGfxBank[1] = (wordValue >> 4) & 0x0f; + RamGfxBank[2] = (wordValue >> 8) & 0x0f; + RamGfxBank[3] = (wordValue >> 12) & 0x0f; + break; + case 0x0FE00A: + RamGfxBank[4] = (wordValue >> 0) & 0x0f; + RamGfxBank[5] = (wordValue >> 4) & 0x0f; + RamGfxBank[6] = (wordValue >> 8) & 0x0f; + RamGfxBank[7] = (wordValue >> 12) & 0x0f; + break; + case 0x0FE00C: + // NOP + break; + + default: + printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 aerofgtbMemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68000 ROM + RomZ80 = Next; Next += 0x030000; // Z80 ROM + RomBg = Next; Next += 0x200040; // Background, 1M 8x8x4bit decode to 2M + 64Byte safe + DeRomBg = RomBg + 0x000040; + RomSpr1 = Next; Next += 0x200000; // Sprite 1 , 1M 16x16x4bit decode to 2M + 256Byte safe + RomSpr2 = Next; Next += 0x100100; // Sprite 2 + + DeRomSpr1 = RomSpr1 + 0x000100; + DeRomSpr2 = RomSpr2 += 0x000100; + + RomSnd1 = Next; Next += 0x040000; // ADPCM data + RomSndSize1 = 0x040000; + RomSnd2 = Next; Next += 0x100000; // ADPCM data + RomSndSize2 = 0x100000; + + RamStart = Next; + + Ram01 = Next; Next += 0x014000; // Work Ram + RamBg1V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG1 Video Ram + RamBg2V = (UINT16 *)Next; Next += 0x001000 * sizeof(UINT16); // BG2 Video Ram + RamSpr1 = (UINT16 *)Next; Next += 0x002000 * sizeof(UINT16); // Sprite 1 Ram + RamSpr2 = (UINT16 *)Next; Next += 0x002000 * sizeof(UINT16); // Sprite 2 Ram + RamSpr3 = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // Sprite 3 Ram + RamPal = Next; Next += 0x000800; // 1024 of X1R5G5B5 Palette + RamRaster = (UINT16 *)Next; Next += 0x000800 * sizeof(UINT16); // Raster + + RamSpr1SizeMask = 0x1FFF; + RamSpr2SizeMask = 0x1FFF; + RomSpr1SizeMask = 0x1FFF; + RomSpr2SizeMask = 0x0FFF; + + RamZ80 = Next; Next += 0x000800; // Z80 Ram 2K + + RamEnd = Next; + + RamCurPal = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); // 1024 colors + + MemEnd = Next; + return 0; +} + +static void aerofgtbDecodeSpr(UINT8 *d, UINT8 *s, INT32 cnt) +{ + for (INT32 c=cnt-1; c>=0; c--) + for (INT32 y=15; y>=0; y--) { + d[(c * 256) + (y * 16) + 15] = s[0x00005 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 14] = s[0x00005 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 13] = s[0x00007 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 12] = s[0x00007 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 11] = s[0x00004 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 10] = s[0x00004 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 9] = s[0x00006 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 8] = s[0x00006 + (y * 8) + (c * 128)] & 0x0f; + + d[(c * 256) + (y * 16) + 7] = s[0x00001 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 6] = s[0x00001 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 5] = s[0x00003 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 4] = s[0x00003 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 3] = s[0x00000 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 2] = s[0x00000 + (y * 8) + (c * 128)] & 0x0f; + d[(c * 256) + (y * 16) + 1] = s[0x00002 + (y * 8) + (c * 128)] >> 4; + d[(c * 256) + (y * 16) + 0] = s[0x00002 + (y * 8) + (c * 128)] & 0x0f; + } +} + +static INT32 aerofgtbInit() +{ + Mem = NULL; + aerofgtbMemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + aerofgtbMemIndex(); + + // Load the roms into memory + // Load 68000 ROM + if (BurnLoadRom(Rom01 + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Rom01 + 0x00000, 1, 2)) return 1; + + // Load Graphic + BurnLoadRom(RomBg+0x00000, 2, 1); + BurnLoadRom(RomBg+0x80000, 3, 1); + pspikesDecodeBg(0x8000); + + BurnLoadRom(RomSpr1+0x000000, 4, 2); + BurnLoadRom(RomSpr1+0x000001, 5, 2); + BurnLoadRom(RomSpr1+0x100000, 6, 2); + BurnLoadRom(RomSpr1+0x100001, 7, 2); + aerofgtbDecodeSpr(DeRomSpr1, RomSpr1, 0x3000); + + // Load Z80 ROM + if (BurnLoadRom(RomZ80+0x10000, 8, 1)) return 1; + memcpy(RomZ80, RomZ80+0x10000, 0x10000); + + BurnLoadRom(RomSnd1, 9, 1); + BurnLoadRom(RomSnd2, 10, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x0C0000, 0x0CFFFF, SM_RAM); // 64K Work RAM + SekMapMemory((UINT8 *)RamBg1V, + 0x0D0000, 0x0D1FFF, SM_RAM); + SekMapMemory((UINT8 *)RamBg2V, + 0x0D2000, 0x0D3FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr1, + 0x0E0000, 0x0E3FFF, SM_RAM); + SekMapMemory((UINT8 *)RamSpr2, + 0x0E4000, 0x0E7FFF, SM_RAM); + SekMapMemory(Ram01+0x10000, 0x0F8000, 0x0FBFFF, SM_RAM); // Work RAM + SekMapMemory((UINT8 *)RamSpr3, + 0x0FC000, 0x0FC7FF, SM_RAM); + SekMapMemory(RamPal, 0x0FD000, 0x0FD7FF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamRaster, + 0x0FF000, 0x0FFFFF, SM_RAM); // Raster + + SekSetReadWordHandler(0, aerofgtbReadWord); + SekSetReadByteHandler(0, aerofgtbReadByte); + SekSetWriteWordHandler(0, aerofgtbWriteWord); + SekSetWriteByteHandler(0, aerofgtbWriteByte); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x77FF, 0, RomZ80); + ZetMapArea(0x0000, 0x77FF, 2, RomZ80); + + ZetMapArea(0x7800, 0x7FFF, 0, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 1, RamZ80); + ZetMapArea(0x7800, 0x7FFF, 2, RamZ80); + + ZetMemEnd(); + + //ZetSetReadHandler(aerofgtZ80Read); + //ZetSetWriteHandler(aerofgtZ80Write); + ZetSetInHandler(aerofgtZ80PortRead); + ZetSetOutHandler(aerofgtZ80PortWrite); + + ZetClose(); + } + + BurnYM2610Init(8000000, RomSnd2, &RomSndSize2, RomSnd1, &RomSndSize1, &aerofgtFMIRQHandler, aerofgtSynchroniseStream, aerofgtGetTime, 0); + BurnTimerAttachZet(4000000); + + DrvDoReset(); // Reset machine + return 0; +} + +static void aerofgtbTileBackground_1(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (RamRaster[7] & 0x1FF); + if (x <= (320-512)) x += 512; + + y = my * 8 - (((INT16)bg1scrolly + 2) & 0x1FF); + if (y <= (224-512)) y += 512; + + if ( x<=-8 || x>=320 || y<=-8 || y>= 224 ) + continue; + + else + if ( x >=0 && x < (320-8) && y >= 0 && y < (224-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + p[0] = pal[ d[0] | c ]; + p[1] = pal[ d[1] | c ]; + p[2] = pal[ d[2] | c ]; + p[3] = pal[ d[3] | c ]; + p[4] = pal[ d[4] | c ]; + p[5] = pal[ d[5] | c ]; + p[6] = pal[ d[6] | c ]; + p[7] = pal[ d[7] | c ]; + + d += 8; + p += 320; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11)] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<224 ) { + if ((x + 0) >= 0 && (x + 0)<320) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<320) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<320) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<320) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<320) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<320) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<320) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<320) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 320; + } + + } + + } +} + +static void aerofgtbTileBackground_2(UINT16 *bg, UINT8 *BgGfx, UINT16 *pal) +{ + INT32 offs, mx, my, x, y; + //printf(" %5d%5d%5d%5d\n", (signed short)RamRaster[7],(signed short)bg1scrolly, (signed short)bg2scrollx,(signed short)bg2scrolly); + mx = -1; + my = 0; + for (offs = 0; offs < 64*64; offs++) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8 - (((INT16)bg2scrollx + 5) & 0x1FF); + if (x <= (320-512)) x += 512; + + y = my * 8 - (((INT16)bg2scrolly + 2) & 0x1FF); + if (y <= (224-512)) y += 512; + + if ( x<=-8 || x>=320 || y<=-8 || y>= 224 ) + continue; + else + if ( x >=0 && x < (320-8) && y >= 0 && y < (224-8)) { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + + if (d[0] != 15) p[0] = pal[ d[0] | c ]; + if (d[1] != 15) p[1] = pal[ d[1] | c ]; + if (d[2] != 15) p[2] = pal[ d[2] | c ]; + if (d[3] != 15) p[3] = pal[ d[3] | c ]; + if (d[4] != 15) p[4] = pal[ d[4] | c ]; + if (d[5] != 15) p[5] = pal[ d[5] | c ]; + if (d[6] != 15) p[6] = pal[ d[6] | c ]; + if (d[7] != 15) p[7] = pal[ d[7] | c ]; + + d += 8; + p += 320; + } + } else { + + UINT8 *d = BgGfx + ( (bg[offs] & 0x07FF) + ( RamGfxBank[((bg[offs] & 0x1800) >> 11) + 4] << 11 ) ) * 64; + UINT16 c = (bg[offs] & 0xE000) >> 9; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<224 ) { + if (d[0] != 15 && (x + 0) >= 0 && (x + 0)<352) p[0] = pal[ d[0] | c ]; + if (d[1] != 15 && (x + 1) >= 0 && (x + 1)<352) p[1] = pal[ d[1] | c ]; + if (d[2] != 15 && (x + 2) >= 0 && (x + 2)<352) p[2] = pal[ d[2] | c ]; + if (d[3] != 15 && (x + 3) >= 0 && (x + 3)<352) p[3] = pal[ d[3] | c ]; + if (d[4] != 15 && (x + 4) >= 0 && (x + 4)<352) p[4] = pal[ d[4] | c ]; + if (d[5] != 15 && (x + 5) >= 0 && (x + 5)<352) p[5] = pal[ d[5] | c ]; + if (d[6] != 15 && (x + 6) >= 0 && (x + 6)<352) p[6] = pal[ d[6] | c ]; + if (d[7] != 15 && (x + 7) >= 0 && (x + 7)<352) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 320; + } + + } + + } +} + +static void aerofgtb_pdrawgfxzoom(INT32 bank,UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy,INT32 scalex,INT32 scaley) +{ + if (!scalex || !scaley) return; + + UINT16 * p = (UINT16 *) pBurnDraw; + UINT8 * q; + UINT16 * pal; + + if (bank) { + //if (code > RomSpr2SizeMask) + code &= RomSpr2SizeMask; + q = DeRomSpr2 + (code) * 256; + pal = RamCurPal + 768; + } else { + //if (code > RomSpr1SizeMask) + code &= RomSpr1SizeMask; + q = DeRomSpr1 + (code) * 256; + pal = RamCurPal + 512; + } + + p += sy * 320 + sx; + + if (sx < 0 || sx >= (320-16) || sy < 0 || sy >= (224-16) ) { + + if ((sx <= -16) || (sx >= 320) || (sy <= -16) || (sy >= 224)) + return; + + if (flipy) { + + p += 320 * 15; + + if (flipx) { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[15] | color]; + } + p -= 320; + q += 16; + } + + } else { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[15] | color]; + } + p -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[15] | color]; + } + p += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] != 15 && ((sx + 0) >= 0) && ((sx + 0)<320)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15 && ((sx + 1) >= 0) && ((sx + 1)<320)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15 && ((sx + 2) >= 0) && ((sx + 2)<320)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15 && ((sx + 3) >= 0) && ((sx + 3)<320)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15 && ((sx + 4) >= 0) && ((sx + 4)<320)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15 && ((sx + 5) >= 0) && ((sx + 5)<320)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15 && ((sx + 6) >= 0) && ((sx + 6)<320)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15 && ((sx + 7) >= 0) && ((sx + 7)<320)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15 && ((sx + 8) >= 0) && ((sx + 8)<320)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15 && ((sx + 9) >= 0) && ((sx + 9)<320)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15 && ((sx + 10) >= 0) && ((sx + 10)<320)) p[10] = pal[ q[10] | color]; + if (q[11] != 15 && ((sx + 11) >= 0) && ((sx + 11)<320)) p[11] = pal[ q[11] | color]; + if (q[12] != 15 && ((sx + 12) >= 0) && ((sx + 12)<320)) p[12] = pal[ q[12] | color]; + if (q[13] != 15 && ((sx + 13) >= 0) && ((sx + 13)<320)) p[13] = pal[ q[13] | color]; + if (q[14] != 15 && ((sx + 14) >= 0) && ((sx + 14)<320)) p[14] = pal[ q[14] | color]; + if (q[15] != 15 && ((sx + 15) >= 0) && ((sx + 15)<320)) p[15] = pal[ q[15] | color]; + } + p += 320; + q += 16; + } + + } + + } + + return; + } + + if (flipy) { + + p += 320 * 15; + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p -= 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[15] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[14] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[13] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[12] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[11] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[10] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 6] = pal[ q[ 9] | color]; + if (q[10] != 15) p[ 5] = pal[ q[10] | color]; + if (q[11] != 15) p[ 4] = pal[ q[11] | color]; + if (q[12] != 15) p[ 3] = pal[ q[12] | color]; + if (q[13] != 15) p[ 2] = pal[ q[13] | color]; + if (q[14] != 15) p[ 1] = pal[ q[14] | color]; + if (q[15] != 15) p[ 0] = pal[ q[15] | color]; + + p += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0] != 15) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] != 15) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] != 15) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] != 15) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] != 15) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] != 15) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] != 15) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] != 15) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] != 15) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] != 15) p[ 9] = pal[ q[ 9] | color]; + if (q[10] != 15) p[10] = pal[ q[10] | color]; + if (q[11] != 15) p[11] = pal[ q[11] | color]; + if (q[12] != 15) p[12] = pal[ q[12] | color]; + if (q[13] != 15) p[13] = pal[ q[13] | color]; + if (q[14] != 15) p[14] = pal[ q[14] | color]; + if (q[15] != 15) p[15] = pal[ q[15] | color]; + + p += 320; + q += 16; + } + + } + + } + +} + +static void aerofgtb_drawsprites(INT32 chip,INT32 chip_disabled_pri) +{ + INT32 attr_start,base,first; + + base = chip * 0x0200; + first = 4 * RamSpr3[0x1fe + base]; + + //for (attr_start = base + 0x0200-8;attr_start >= first + base;attr_start -= 4) { + for (attr_start = first + base; attr_start <= base + 0x0200-8; attr_start += 4) { + INT32 map_start; + INT32 ox,oy,x,y,xsize,ysize,zoomx,zoomy,flipx,flipy,color,pri; +// some other drivers still use this wrong table, they have to be upgraded +// INT32 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; + + if (!(RamSpr3[attr_start + 2] & 0x0080)) continue; + pri = RamSpr3[attr_start + 2] & 0x0010; + if ( chip_disabled_pri & !pri) continue; + if (!chip_disabled_pri & (pri>>4)) continue; + ox = RamSpr3[attr_start + 1] & 0x01ff; + xsize = (RamSpr3[attr_start + 2] & 0x0700) >> 8; + zoomx = (RamSpr3[attr_start + 1] & 0xf000) >> 12; + oy = RamSpr3[attr_start + 0] & 0x01ff; + ysize = (RamSpr3[attr_start + 2] & 0x7000) >> 12; + zoomy = (RamSpr3[attr_start + 0] & 0xf000) >> 12; + flipx = RamSpr3[attr_start + 2] & 0x0800; + flipy = RamSpr3[attr_start + 2] & 0x8000; + color = (RamSpr3[attr_start + 2] & 0x000f) << 4; // + 16 * spritepalettebank; + + map_start = RamSpr3[attr_start + 3]; + +// aerofgt has this adjustment, but doing it here would break turbo force title screen +// ox += (xsize*zoomx+2)/4; +// oy += (ysize*zoomy+2)/4; + + zoomx = 32 - zoomx; + zoomy = 32 - zoomy; + + for (y = 0;y <= ysize;y++) { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y)/2 + 16) & 0x1ff) - 16 - 1; + else sy = ((oy + zoomy * y / 2 + 16) & 0x1ff) - 16 - 1; + + for (x = 0;x <= xsize;x++) { + INT32 code; + + if (flipx) sx = ((ox + zoomx * (xsize - x) / 2 + 16) & 0x1ff) - 16 - 8; + else sx = ((ox + zoomx * x / 2 + 16) & 0x1ff) - 16 - 8; + + if (chip == 0) code = RamSpr1[map_start & RamSpr1SizeMask]; + else code = RamSpr2[map_start & RamSpr2SizeMask]; + + aerofgtb_pdrawgfxzoom(chip,code,color,flipx,flipy,sx,sy,zoomx << 11, zoomy << 11); + + map_start++; + } + + if (xsize == 2) map_start += 1; + if (xsize == 4) map_start += 3; + if (xsize == 5) map_start += 2; + if (xsize == 6) map_start += 1; + } + } +} + +static INT32 aerofgtbDraw() +{ + aerofgtbTileBackground_1(RamBg1V, DeRomBg, RamCurPal); + aerofgtbTileBackground_2(RamBg2V, DeRomBg + 0x100000, RamCurPal + 256); + + aerofgtb_drawsprites(0, 0); + aerofgtb_drawsprites(0,-1); + aerofgtb_drawsprites(1, 0); + aerofgtb_drawsprites(1,-1); + + return 0; +} + +static INT32 aerofgtbFrame() +{ + if (DrvReset) DrvDoReset(); + + // Compile digital inputs + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Buttons + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) aerofgtbDraw(); + + return 0; +} + +struct BurnDriver BurnDrvAerofgtb = { + "aerofgtb", "aerofgt", NULL, NULL, "1992", + "Aero Fighters (Turbo Force hardware set 1)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, FBF_SONICWI, + NULL, aerofgtbRomInfo, aerofgtbRomName, NULL, NULL, aerofgtInputInfo, aerofgtbDIPInfo, + aerofgtbInit,DrvExit,aerofgtbFrame,aerofgtbDraw,DrvScan, + NULL, 0x800, 224,320,3,4 +}; + +struct BurnDriver BurnDrvAerofgtc = { + "aerofgtc", "aerofgt", NULL, NULL, "1992", + "Aero Fighters (Turbo Force hardware set 2)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, FBF_SONICWI, + NULL, aerofgtcRomInfo, aerofgtcRomName, NULL, NULL, aerofgtInputInfo, aerofgtDIPInfo, + aerofgtbInit,DrvExit,aerofgtbFrame,aerofgtbDraw,DrvScan, + NULL, 0x800, 224,320,3,4 +}; + +struct BurnDriver BurnDrvSonicwi = { + "sonicwi", "aerofgt", NULL, NULL, "1992", + "Sonic Wings (Japan)\0", NULL, "Video System Co.", "Video System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, FBF_SONICWI, + NULL, sonicwiRomInfo, sonicwiRomName, NULL, NULL, aerofgtInputInfo, aerofgtDIPInfo, + aerofgtbInit,DrvExit,aerofgtbFrame,aerofgtbDraw,DrvScan, + NULL, 0x800, 224,320,3,4 +}; + diff --git a/src/burn/drivers/misc_post90s/d_airbustr.cpp b/src/burn/drivers/misc_post90s/d_airbustr.cpp new file mode 100644 index 00000000..390e46a4 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_airbustr.cpp @@ -0,0 +1,920 @@ +// FB Alpha Air Buster: Trouble Specialty Raid Unit driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym2203.h" +#include "pandora.h" + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvZ80RAM2; +static UINT8 *DrvShareRAM; +static UINT8 *DrvDevRAM; +static UINT8 *DrvPandoraRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; + +static UINT32 *DrvPalette; + +static UINT8 *DrvScrollRegs; +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *sound_status; +static UINT8 *sound_status2; +static UINT8 *coin_lockout; +static UINT8 *flipscreen; + +static INT32 interrupt_vectors[2]; +static INT32 watchdog; +static INT32 is_bootleg; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo AirbustrInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 6, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Airbustr) + +static struct BurnDIPInfo AirbustrDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x02, 0x02, "Off" }, +// {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x12, 0x01, 0x08, 0x08, "Mode 1" }, + {0x12, 0x01, 0x08, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x30, 0x00, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x30, 0x10, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x30, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xc0, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Difficult" }, + {0x13, 0x01, 0x03, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x20, "4" }, + {0x13, 0x01, 0x30, 0x10, "5" }, + {0x13, 0x01, 0x30, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Airbustr) + +static struct BurnDIPInfo AirbustjDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x02, 0x02, "Off" }, +// {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x12, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x12, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Difficult" }, + {0x13, 0x01, 0x03, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x20, "4" }, + {0x13, 0x01, 0x30, 0x10, "5" }, + {0x13, 0x01, 0x30, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Airbustj) + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + + for (INT32 i = 0; i < 0x600; i+=2) { + INT32 d = DrvPalRAM[i + 1] * 256 + DrvPalRAM[i + 0]; + + r = (d >> 5) & 0x1f; + g = (d >> 10) & 0x1f; + b = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i / 2] = BurnHighCol(r, g, b, 0); + } +} + +static void airbustr_bankswitch(UINT8 *rom, INT32 data) +{ + ZetMapArea(0x8000, 0xbfff, 0, rom + 0x4000 * (data & 0x07)); + ZetMapArea(0x8000, 0xbfff, 2, rom + 0x4000 * (data & 0x07)); +} + +void __fastcall airbustr_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf000) == 0xc000) { // pandora + + DrvSprRAM[address & 0xfff] = data; + + address = (address & 0x800) | ((address & 0xff) << 3) | ((address & 0x700) >> 8); + + DrvPandoraRAM[address] = data; + + return; + } +} + +UINT8 __fastcall airbustr_main_read(UINT16 address) +{ + if ((address & 0xf000) == 0xe000) { + + INT32 offset = address & 0xfff; + switch (offset) + { + case 0xfe0: + watchdog = 180; + return 0; + + case 0xff2: + case 0xff3: + { + INT32 r = (DrvDevRAM[0xff0] + DrvDevRAM[0xff1] * 256) * (DrvDevRAM[0xff2] + DrvDevRAM[0xff3] * 256); + + if (offset & 1) return r >> 8; + return r; + } + + case 0xff4: + return rand(); + } + + return DrvDevRAM[offset]; + } + + return 0; +} + +void __fastcall airbustr_main_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + airbustr_bankswitch(DrvZ80ROM0, data); + return; + + case 0x01: + return; // nop + + case 0x02: + { + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + } + return; + } +} + +void __fastcall airbustr_sub_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + { + airbustr_bankswitch(DrvZ80ROM1, data); + + *flipscreen = data & 0x10; + + pandora_set_clear(data & 0x20); + } + return; + + case 0x02: // soundcommand_w + { + *soundlatch = data; + *sound_status = 1; + ZetClose(); + ZetOpen(2); + ZetNmi(); + ZetClose(); + ZetOpen(1); + } + return; + + case 0x04: + case 0x06: + case 0x08: + case 0x0a: + case 0x0c: + DrvScrollRegs[((port & 0x0f) - 0x04) / 2] = data; + return; + + case 0x28: + *coin_lockout = ~data & 0x0c; + // coINT32 counter also (0x03) + return; + + case 0x38: + return; // nop + } +} + +UINT8 __fastcall airbustr_sub_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x02: + *sound_status2 = 0; + return *soundlatch2; + + case 0x0e: + return (4 + *sound_status * 2 + (1 - *sound_status2)); + + case 0x20: + return DrvInputs[0]; + + case 0x22: + return DrvInputs[1]; + + case 0x24: + return DrvInputs[2] | *coin_lockout; + } + + return 0; +} + +void __fastcall airbustr_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + airbustr_bankswitch(DrvZ80ROM2, data); + return; + + case 0x02: + BurnYM2203Write(0, 0, data); + return; + + case 0x03: + BurnYM2203Write(0, 1, data); + return; + + case 0x04: + MSM6295Command(0, data); + return; + + case 0x06: + *soundlatch2 = data; + *sound_status2 = 1; + return; + } +} + +UINT8 __fastcall airbustr_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x02: + return BurnYM2203Read(0, 0); + + case 0x03: + return BurnYM2203Read(0, 1); + + case 0x04: + return MSM6295ReadStatus(0); + + case 0x06: + *sound_status = 0; + return *soundlatch; + } + + return 0; +} + +UINT8 DrvYM2203PortA(UINT32) +{ + return DrvDips[0]; +} + +UINT8 DrvYM2203PortB(UINT32) +{ + return DrvDips[1]; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 6000000; +} + +static INT32 DrvDoReset(INT32 full_reset) +{ + if (full_reset) { + memset (AllRam, 0, RamEnd - AllRam); + } + +// UINT8 *rom[3] = { DrvZ80ROM0, DrvZ80ROM1, DrvZ80ROM2 }; + + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); +// if (full_reset) airbustr_bankswitch(rom[i], 2); + ZetClose(); + } + + MSM6295Reset(0); + BurnYM2203Reset(); + + interrupt_vectors[0] = 0xff; + interrupt_vectors[1] = 0xfd; + + watchdog = 180; + + srand(time(NULL)); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x020000; + DrvZ80ROM1 = Next; Next += 0x020000; + DrvZ80ROM2 = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvVidRAM0 = Next; Next += 0x000800; + DrvVidRAM1 = Next; Next += 0x000800; + + DrvZ80RAM0 = Next; Next += 0x001000; + DrvZ80RAM1 = Next; Next += 0x001000; + DrvZ80RAM2 = Next; Next += 0x002000; + + DrvShareRAM = Next; Next += 0x001000; + DrvDevRAM = Next; Next += 0x001000; + + DrvPandoraRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x001000; + DrvPalRAM = Next; Next += 0x001000; + + DrvScrollRegs = Next; Next += 0x000006; + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + sound_status = Next; Next += 0x000001; + sound_status2 = Next; Next += 0x000001; + + coin_lockout = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + static INT32 Plane[4] = { 0, 1, 2, 3 }; + static INT32 XOffs[16] = { 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, + 0*4+32*8, 1*4+32*8, 2*4+32*8, 3*4+32*8, 4*4+32*8, 5*4+32*8, 6*4+32*8, 7*4+32*8 }; + static INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, + 0*32+64*8, 1*32+64*8, 2*32+64*8, 3*32+64*8, 4*32+64*8, 5*32+64*8, 6*32+64*8, 7*32+64*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x080000; i++) { + tmp[i] = (DrvGfxROM0[i] << 4) | (DrvGfxROM0[i] >> 4); + } + + GfxDecode(0x1000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + is_bootleg = BurnDrvGetFlags() & BDF_BOOTLEG; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM2 + 0x000000, 2, 1)) return 1; + + if (is_bootleg) + { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 6, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x020000, 13, 1)) return 1; + } + else + { + // mcu... + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 7, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(3); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xcfff, 0, DrvSprRAM); +// ZetMapArea(0xc000, 0xcfff, 1, DrvSprRAM); // handler + ZetMapArea(0xc000, 0xcfff, 2, DrvSprRAM); + ZetMapArea(0xd000, 0xdfff, 0, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 1, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 2, DrvZ80RAM0); + if (is_bootleg) ZetMapArea(0xe000, 0xefff, 0, DrvDevRAM); + ZetMapArea(0xe000, 0xefff, 1, DrvDevRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvDevRAM); + ZetMapArea(0xf000, 0xffff, 0, DrvShareRAM); + ZetMapArea(0xf000, 0xffff, 1, DrvShareRAM); + ZetMapArea(0xf000, 0xffff, 2, DrvShareRAM); + ZetSetWriteHandler(airbustr_main_write); + ZetSetReadHandler(airbustr_main_read); + ZetSetOutHandler(airbustr_main_out); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0xc000, 0xc7ff, 0, DrvVidRAM1); + ZetMapArea(0xc000, 0xc7ff, 1, DrvVidRAM1); + ZetMapArea(0xc000, 0xc7ff, 2, DrvVidRAM1); + ZetMapArea(0xc800, 0xcfff, 0, DrvVidRAM0); + ZetMapArea(0xc800, 0xcfff, 1, DrvVidRAM0); + ZetMapArea(0xc800, 0xcfff, 2, DrvVidRAM0); + ZetMapArea(0xd000, 0xdfff, 0, DrvPalRAM); + ZetMapArea(0xd000, 0xdfff, 1, DrvPalRAM); + ZetMapArea(0xd000, 0xdfff, 2, DrvPalRAM); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80RAM1); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80RAM1); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80RAM1); + ZetMapArea(0xf000, 0xffff, 0, DrvShareRAM); + ZetMapArea(0xf000, 0xffff, 1, DrvShareRAM); + ZetMapArea(0xf000, 0xffff, 2, DrvShareRAM); + ZetSetOutHandler(airbustr_sub_out); + ZetSetInHandler(airbustr_sub_in); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM2); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM2); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM2); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM2); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM2); + ZetSetOutHandler(airbustr_sound_out); + ZetSetInHandler(airbustr_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 3000000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetPorts(0, &DrvYM2203PortA, &DrvYM2203PortB, NULL, NULL); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(6000000); + + MSM6295Init(0, 3000000 / 132, 80, 1); + + GenericTilesInit(); + + pandora_init(DrvPandoraRAM, DrvGfxROM1, 0x200, 0, -16); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + pandora_exit(); + + GenericTilesExit(); + + ZetExit(); + MSM6295Exit(0); + + BurnYM2203Exit(); + + BurnFree(AllMem); + + return 0; +} + +static void draw_layer(UINT8 *ram, INT32 r0, INT32 r1, INT32 r2, INT32 r3, INT32 t) +{ + INT32 scrollx = DrvScrollRegs[r0] + ((~DrvScrollRegs[4] << r1) & 0x100); + INT32 scrolly = DrvScrollRegs[r2] + ((~DrvScrollRegs[4] << r3) & 0x100) + 16; + + if (*flipscreen) { + scrollx = (scrollx + 0x06a) & 0x1ff; + scrolly = (scrolly + 0x1ff) & 0x1ff; + } else { + scrollx = (scrollx - 0x094) & 0x1ff; + scrolly = (scrolly - 0x100) & 0x1ff; + } + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 512; + sy -= scrolly; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth) continue; + if (sy >= nScreenHeight) continue; + + INT32 attr = ram[offs + 0x400]; + INT32 code = ram[offs + 0x000] | ((attr & 0x0f) << 8); + + if (t) { + if (*flipscreen) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, 240 - sx, 240 - sy, attr >> 4, 4, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, attr >> 4, 4, 0, 0, DrvGfxROM0); + } + } else { + if (*flipscreen) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, 240 - sx, 240 - sy, attr >> 4, 4, 0x100, DrvGfxROM0); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, attr >> 4, 4, 0x100, DrvGfxROM0); + } + } + } +} + +static INT32 DrvDraw() +{ + DrvRecalcPalette(); + + draw_layer(DrvVidRAM0, 3, 6, 2, 5, 0); + + draw_layer(DrvVidRAM1, 1, 8, 0, 7, 1); + + pandora_flipscreen = *flipscreen; + pandora_update(pTransDraw); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(1); + } + + if (watchdog == 0 && is_bootleg == 0) { + DrvDoReset(0); + } + watchdog--; + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[3] = { 6000000 / 60, 6000000 / 60, 6000000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment - nCyclesDone[0]); + if (i == 49 || i == 99) { + interrupt_vectors[0] ^= 2; + ZetSetVector(interrupt_vectors[0]); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]); + if (i == 49 || i == 99) { + interrupt_vectors[1] ^= 2; + ZetSetVector(interrupt_vectors[1]); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + + ZetOpen(2); + BurnTimerUpdate(nCyclesDone[1] /*sync with sub cpu*/); + if (i == 99) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + } + + ZetOpen(2); + + BurnTimerEndFrame(nCyclesTotal[2]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + pandora_buffer_sprites(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Air Buster: Trouble Specialty Raid Unit (World) + +static struct BurnRomInfo airbustrRomDesc[] = { + { "pr12.h19", 0x20000, 0x91362eb2, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "pr13.l15", 0x20000, 0x13b2257b, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "pr-21.bin", 0x20000, 0x6e0a5df0, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "i80c51", 0x01000, 0x00000000, 4 | BRF_NODUMP }, // 3 80c51 MCU + + { "pr-000.bin", 0x80000, 0x8ca68f0d, 5 | BRF_GRA }, // 4 Tiles + + { "pr-001.bin", 0x80000, 0x7e6cb377, 6 | BRF_GRA }, // 5 Sprites + { "pr-02.bin", 0x10000, 0x6bbd5e46, 6 | BRF_GRA }, // 6 + + { "pr-200.bin", 0x40000, 0xa4dd3390, 7 | BRF_SND }, // 7 OKI M6295 +}; + +STD_ROM_PICK(airbustr) +STD_ROM_FN(airbustr) + +struct BurnDriver BurnDrvAirbustr = { + "airbustr", NULL, NULL, NULL, "1990", + "Air Buster: Trouble Specialty Raid Unit (World)\0", NULL, "Kaneko (Namco license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, airbustrRomInfo, airbustrRomName, NULL, NULL, AirbustrInputInfo, AirbustrDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x0300, + 256, 224, 4, 3 +}; + + +// Air Buster: Trouble Specialty Raid Unit (Japan) + +static struct BurnRomInfo airbustrjRomDesc[] = { + { "pr-14j.bin", 0x20000, 0x6b9805bd, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "pr-11j.bin", 0x20000, 0x85464124, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "pr-21.bin", 0x20000, 0x6e0a5df0, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "i80c51", 0x01000, 0x00000000, 4 | BRF_NODUMP }, // 3 80c51 MCU + + { "pr-000.bin", 0x80000, 0x8ca68f0d, 5 | BRF_GRA }, // 4 Tiles + + { "pr-001.bin", 0x80000, 0x7e6cb377, 6 | BRF_GRA }, // 5 Sprites + { "pr-02.bin", 0x10000, 0x6bbd5e46, 6 | BRF_GRA }, // 6 + + { "pr-200.bin", 0x40000, 0xa4dd3390, 7 | BRF_SND }, // 7 OKI M6295 +}; + +STD_ROM_PICK(airbustrj) +STD_ROM_FN(airbustrj) + +struct BurnDriver BurnDrvAirbustrj = { + "airbustrj", "airbustr", NULL, NULL, "1990", + "Air Buster: Trouble Specialty Raid Unit (Japan)\0", NULL, "Kaneko (Namco license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, airbustrjRomInfo, airbustrjRomName, NULL, NULL, AirbustrInputInfo, AirbustjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x0300, + 256, 224, 4, 3 +}; + + +// Air Buster: Trouble Specialty Raid Unit (bootleg) + +static struct BurnRomInfo airbustrbRomDesc[] = { + { "5.bin", 0x20000, 0x9e4216a2, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "1.bin", 0x20000, 0x85464124, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "2.bin", 0x20000, 0x6e0a5df0, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "7.bin", 0x20000, 0x2e3bf0a2, 4 | BRF_GRA }, // 3 Tiles + { "9.bin", 0x20000, 0x2c23c646, 4 | BRF_GRA }, // 4 + { "6.bin", 0x20000, 0x0d6cd470, 4 | BRF_GRA }, // 5 + { "8.bin", 0x20000, 0xb3372e51, 4 | BRF_GRA }, // 6 + + { "13.bin", 0x20000, 0x75dee86d, 5 | BRF_GRA }, // 7 Sprites + { "12.bin", 0x20000, 0xc98a8333, 5 | BRF_GRA }, // 8 + { "11.bin", 0x20000, 0x4e9baebd, 5 | BRF_GRA }, // 9 + { "10.bin", 0x20000, 0x63dc8cd8, 5 | BRF_GRA }, // 10 + { "14.bin", 0x10000, 0x6bbd5e46, 5 | BRF_GRA }, // 11 + + { "4.bin", 0x20000, 0x21d9bfe3, 6 | BRF_SND }, // 12 OKI M6295 + { "3.bin", 0x20000, 0x58cd19e2, 6 | BRF_SND }, // 13 +}; + +STD_ROM_PICK(airbustrb) +STD_ROM_FN(airbustrb) + +struct BurnDriver BurnDrvAirbustrb = { + "airbustrb", "airbustr", NULL, NULL, "1990", + "Air Buster: Trouble Specialty Raid Unit (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, airbustrbRomInfo, airbustrbRomName, NULL, NULL, AirbustrInputInfo, AirbustjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x0300, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_aquarium.cpp b/src/burn/drivers/misc_post90s/d_aquarium.cpp new file mode 100644 index 00000000..00c64a53 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_aquarium.cpp @@ -0,0 +1,764 @@ +// FB Alpha Aquarium driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80Bank; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvPalRAM; +static UINT8 *DrvMidRAM; +static UINT8 *DrvBakRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; +static UINT16 *DrvScroll; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 *soundlatch; +static UINT8 *soundack; +static UINT8 *flipscreen; + +static struct BurnInputInfo AquariumInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 15, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 8, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 9, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 10, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 11, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 3, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Aquarium) + +static struct BurnDIPInfo AquariumDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3, "Winning Rounds (Player VS CPU)" }, + {0x12, 0x01, 0x0c, 0x0c, "1/1" }, + {0x12, 0x01, 0x0c, 0x08, "2/3" }, + {0x12, 0x01, 0x0c, 0x04, "3/5" }, + + {0 , 0xfe, 0 , 3, "Winning Rounds (Player VS Player)" }, + {0x12, 0x01, 0x30, 0x30, "1/1" }, + {0x12, 0x01, 0x30, 0x20, "2/3" }, + {0x12, 0x01, 0x30, 0x10, "3/5" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0x07, 0x00, "5 Coins 1 Credits " }, + {0x13, 0x01, 0x07, 0x01, "4 Coins 1 Credits " }, + {0x13, 0x01, 0x07, 0x02, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x07, 0x03, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Credits " }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x14, 0x01, 0xff, 0x00, "Japanese" }, + {0x14, 0x01, 0xff, 0xff, "English" }, +}; + +STDDIPINFO(Aquarium) + +UINT8 __fastcall aquarium_read_byte(UINT32 address) +{ + switch (address) + { + case 0xd80080: + return DrvDips[1]; + + case 0xd80081: + return DrvDips[0]; + + case 0xd80086: + { + INT32 data = DrvInputs[1] | *soundack; + *soundack = 0; + return data; + } + } + + return 0; +} + +UINT16 __fastcall aquarium_read_word(UINT32 address) +{ + switch (address) + { + case 0xd80084: + return DrvInputs[0]; + } + + return 0; +} + +void __fastcall aquarium_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xd8008b: + *soundlatch = data; + ZetNmi(); + return; + } +} + +void __fastcall aquarium_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0xd80014: + case 0xd80016: + case 0xd80018: + case 0xd8001a: + case 0xd8001c: + case 0xd8001e: + DrvScroll[(address - 0xd80014)/2] = data; + return; + + case 0xd80056: + *flipscreen = ~data & 1; // seems right? + return; + } +} + +static void sound_bankswitch(INT32 nBank) +{ + *DrvZ80Bank = nBank & 7; + + nBank = ((nBank & 7) + 1) * 0x8000; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + nBank); +} + +void __fastcall aquarium_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM2151SelectRegister(data); + return; + + case 0x01: + BurnYM2151WriteRegister(data); + return; + + case 0x02: + MSM6295Command(0, BITSWAP08(data, 0, 1, 2, 3, 4, 5, 6, 7)); + return; + + case 0x06: + *soundack = 0x80; + return; + + case 0x08: + sound_bankswitch(data); + return; + } +} + +UINT8 __fastcall aquarium_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x01: + return BurnYM2151ReadStatus(); + + case 0x02: + return BITSWAP08(MSM6295ReadStatus(0), 0, 1, 2, 3, 4, 5, 6, 7); + + case 0x04: + return *soundlatch; + } + + return 0; +} + +void aquariumYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + Drv68KROM[0x000a5c] = DrvDips[2]; // set region (hack) + Drv68KROM[0x000a5d] = DrvDips[2]; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[5] = { 0x400000, 0, 1, 2, 3 }; + INT32 Plane2[4] = { 48, 16, 32, 0 }; + INT32 XOffs0[16] = { 8, 12, 0, 4, 24, 28, 16, 20, 40, 44, 32, 36, 56, 60, 48, 52 }; + INT32 XOffs2[16] = { 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs0[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + INT32 YOffs1[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x100000); + + GfxDecode(0x1000, 5, 16, 16, Plane0 , XOffs0, YOffs0, 0x400, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x020000); + + GfxDecode(0x1000, 4, 8, 8, Plane0 + 1, XOffs0, YOffs1, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane2 , XOffs2, YOffs0, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x100000); + + GfxDecode(0x1000, 5, 16, 16, Plane0 , XOffs0, YOffs0, 0x400, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x040000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x040000; + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM3 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x001000; + DrvMidRAM = Next; Next += 0x001000; + DrvBakRAM = Next; Next += 0x001000; + DrvTxtRAM = Next; Next += 0x002000; + DrvSprRAM = Next; Next += 0x002000; + + DrvZ80RAM = Next; Next += 0x000800; + + soundack = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + DrvZ80Bank = Next; Next += 0x000001; + + DrvScroll = (UINT16*)Next; Next += 0x000008 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvLoad5bpp(UINT8 *gfx, INT32 num) +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x20000); + if (tmp == NULL) { + return 1; + } + + if (BurnLoadRom(tmp, num, 1)) return 1; + + for (INT32 len = 0; len < 0x020000; len++) + { + gfx[len*4+0] = ((tmp[len] & 0x20) << 2) | ((tmp[len] & 0x10) >> 1); + gfx[len*4+1] = ((tmp[len] & 0x80) << 0) | ((tmp[len] & 0x40) >> 3); + gfx[len*4+2] = ((tmp[len] & 0x02) << 6) | ((tmp[len] & 0x01) << 3); + gfx[len*4+3] = ((tmp[len] & 0x08) << 4) | ((tmp[len] & 0x04) << 1); + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 2, 1)) return 1; + if (DrvLoad5bpp(DrvGfxROM0 + 0x80000, 3 )) return 1; + + if (BurnLoadRom(DrvGfxROM1, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3, 6, 1)) return 1; + if (DrvLoad5bpp(DrvGfxROM3 + 0x80000, 7 )) return 1; + + if (BurnLoadRom(DrvSndROM, 8, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvMidRAM, 0xc00000, 0xc00fff, SM_RAM); + SekMapMemory(DrvBakRAM, 0xc01000, 0xc01fff, SM_RAM); + SekMapMemory(DrvTxtRAM, 0xc02000, 0xc03fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0xc80000, 0xc81fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xd00000, 0xd00fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, aquarium_write_byte); + SekSetWriteWordHandler(0, aquarium_write_word); + SekSetReadByteHandler(0, aquarium_read_byte); + SekSetReadWordHandler(0, aquarium_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetSetOutHandler(aquarium_sound_out); + ZetSetInHandler(aquarium_sound_in); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1122000 / 132, 100.0, 1); + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetIrqHandler(&aquariumYM2151IrqHandler); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static inline void palette_write(INT32 offset) +{ + UINT8 r,g,b; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = ((data >> 11) & 0x1e) | ((data >> 3) & 0x01); + g = ((data >> 7) & 0x1e) | ((data >> 2) & 0x01); + b = ((data >> 3) & 0x1e) | ((data >> 1) & 0x01); + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +static void draw_bg_layer(UINT8 *src, UINT8 *gfx_base, INT32 scrollx, INT32 scrolly, INT32 transp, INT32 priority) +{ + UINT16 *vram = (UINT16*)src; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 color = vram[(offs * 2) + 1]; + INT32 prior = (color & 0x0020) >> 5; + if (prior != priority) continue; + + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx + 16; + if (sx < -15) sx += 0x200; + sy -= scrolly + 16; + if (sy < -15) sy += 0x200; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 flipx = color & 0x0100; + INT32 flipy = color & 0x0200; + INT32 code = vram[offs * 2] & 0x0fff; + + if (transp) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0, 0x400, gfx_base); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0, 0x400, gfx_base); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0, 0x400, gfx_base); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0, 0x400, gfx_base); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0x400, gfx_base); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0x400, gfx_base); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0x400, gfx_base); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color & 0x001f, 5, 0x400, gfx_base); + } + } + } + } +} + +static void draw_tx_layer(INT32 scrollx, INT32 scrolly) +{ + UINT16 *vram = (UINT16*)DrvTxtRAM; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx + 16; + if (sx < -7) sx += 0x200; + sy -= scrolly + 16; + if (sy < -7) sy += 0x200; + + INT32 code = vram[offs] & 0xfff; + INT32 color = vram[offs] >> 12; + + if (sx >= nScreenWidth || sy >= nScreenHeight || code == 0) continue; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, DrvGfxROM1); + } +} + +static void draw_sprites() +{ + UINT16 *sram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x0800; offs += 8) + { + INT32 code = (sram[offs+5] & 0xff) | ((sram[offs+6] & 0x3f) << 8); + + if (~sram[offs+4] & 0x80) + { + INT32 x = (((sram[offs+0] & 0xff) | ((sram[offs+1] & 0x7f) << 8)) - ((sram[offs+1] & 0x80) << 9)) - 16; + INT32 y = (((sram[offs+2] & 0xff) | ((sram[offs+3] & 0x7f) << 8)) - ((sram[offs+3] & 0x80) << 9)) - 16; + + INT32 col = sram[offs+7] & 0x0f; + INT32 chain = sram[offs+4] & 0x07; + INT32 flipy = sram[offs+4] & 0x10; + INT32 flipx = sram[offs+4] & 0x20; + + if (~sram[offs+4] & 0x08) { + if (flipy) y += chain << 4; + if (flipx) x += chain << 4; + } + + for (INT32 pos = chain; pos >= 0; pos--) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x, y, col, 4, 0, 0x300, DrvGfxROM2); + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x, y + 256, col, 4, 0, 0x300, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x, y, col, 4, 0, 0x300, DrvGfxROM2); + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x, y + 256, col, 4, 0, 0x300, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y, col, 4, 0, 0x300, DrvGfxROM2); + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y + 256, col, 4, 0, 0x300, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y, col, 4, 0, 0x300, DrvGfxROM2); + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y + 256, col, 4, 0, 0x300, DrvGfxROM2); + } + } + + code++; + + if (sram[offs+4] & 0x08) + { + if (flipy) y -= 16; + else y += 16; + } + else + { + if (flipx) x -= 16; + else x += 16; + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i+=2) { + palette_write(i); + } + } + + draw_bg_layer(DrvBakRAM, DrvGfxROM3, DrvScroll[2] & 0x1ff, DrvScroll[3] & 0x1ff, 0, 0); + draw_bg_layer(DrvMidRAM, DrvGfxROM0, DrvScroll[0] & 0x1ff, DrvScroll[1] & 0x1ff, 1, 0); + + draw_sprites(); + + draw_bg_layer(DrvBakRAM, DrvGfxROM3, DrvScroll[2] & 0x1ff, DrvScroll[3] & 0x1ff, 1, 1); + draw_bg_layer(DrvMidRAM, DrvGfxROM0, DrvScroll[0] & 0x1ff, DrvScroll[1] & 0x1ff, 1, 1); + + draw_tx_layer(DrvScroll[4] & 0x1ff, DrvScroll[5] & 0x1ff); + + if (*flipscreen) { + INT32 len = nScreenWidth * nScreenHeight; + for (INT32 i = 0; i < len / 2; i++) { + INT32 t = pTransDraw[i + 0]; + pTransDraw[i + 0] = pTransDraw[len-(1+i)]; + pTransDraw[len-(1+i)] = t; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 4); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[1] &= 0x7f; + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 16000000 / 60, 6000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nSegment); + + nSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + nCyclesDone[1] += ZetRun(nSegment); + + if (pBurnSoundOut) { + nSegment = nBurnSoundLen / nInterleave; + + BurnYM2151Render(pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + MSM6295Render(0, pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + + nSoundBufferPos += nSegment; + } + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + nSegment = nBurnSoundLen - nSoundBufferPos; + if (nSegment > 0) { + BurnYM2151Render(pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + MSM6295Render(0, pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + sound_bankswitch(*DrvZ80Bank); + ZetClose(); + } + + return 0; +} + + +// Aquarium (Japan) + +static struct BurnRomInfo aquariumRomDesc[] = { + { "aquar3", 0x080000, 0x344509a1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "aquar5", 0x040000, 0xfa555be1, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 Code + + { "aquar1", 0x080000, 0x575df6ac, 3 | BRF_GRA }, // 2 Midground Tiles + { "aquar6", 0x020000, 0x9065b146, 3 | BRF_GRA }, // 3 + + { "aquar2", 0x020000, 0xaa071b05, 4 | BRF_GRA }, // 6 Foreground Tiles + + { "aquarf1", 0x100000, 0x14758b3c, 5 | BRF_GRA }, // 7 Sprites + + { "aquar8", 0x080000, 0x915520c4, 6 | BRF_GRA }, // 4 Background Tiles + { "aquar7", 0x020000, 0xb96b2b82, 6 | BRF_GRA }, // 5 + + { "aquar4", 0x080000, 0x9a4af531, 7 | BRF_SND }, // 8 MSM6295 Samples +}; + +STD_ROM_PICK(aquarium) +STD_ROM_FN(aquarium) + +struct BurnDriver BurnDrvAquarium = { + "aquarium", NULL, NULL, NULL, "1996", + "Aquarium (Japan)\0", NULL, "Excellent System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, aquariumRomInfo, aquariumRomName, NULL, NULL, AquariumInputInfo, AquariumDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 256, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_ashnojoe.cpp b/src/burn/drivers/misc_post90s/d_ashnojoe.cpp new file mode 100644 index 00000000..f2fac789 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_ashnojoe.cpp @@ -0,0 +1,714 @@ +// FB Alpha Ashita No Joe / Success Joe driver module +// Based on MAME driver by driver by David Haywood and Pierpaolo Prazzoli + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm5205.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvZ80Banks; +static UINT8 *DrvPfRAM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; + +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; +static UINT8 *soundstatus; +static UINT8 *tilemap_reg; + +static UINT16 *scrollx; +static UINT16 *scrolly; + +static INT32 flipscreen; + +static UINT8 adpcm_byte = 0; +static UINT8 MSM5205_vclk_toggle = 0; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo AshnojoeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 11, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 13, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 12, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 14, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 8, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ashnojoe) + +static struct BurnDIPInfo AshnojoeDIPList[]= +{ + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x01, 0x00, "Upright" }, + {0x12, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x12, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x01, "Easy" }, + {0x13, 0x01, 0x03, 0x00, "Normal" }, + {0x13, 0x01, 0x03, 0x02, "Medium" }, + {0x13, 0x01, 0x03, 0x03, "Hard" }, + + {0 , 0xfe, 0 , 2, "Number of controller" }, + {0x13, 0x01, 0x04, 0x00, "2" }, + {0x13, 0x01, 0x04, 0x04, "1" }, +}; + +STDDIPINFO(Ashnojoe) + +void __fastcall ashnojoe_write_byte(UINT32 a, UINT8 d) +{ + bprintf (0, _T("%5.5x, %2.2x wb\n"), a, d); +} + +void __fastcall ashnojoe_write_word(UINT32 a, UINT16 d) +{ + switch (a) + { + case 0x4a006: + *tilemap_reg = d & 0xff; + return; + + case 0x4a008: + *soundlatch = d & 0xff; + *soundstatus = 1; + return; + + case 0x4a010: + case 0x4a012: + case 0x4a014: + case 0x4a016: + case 0x4a018: + scrollx[(a & 0x0f) / 2] = d; + return; + + case 0x4a020: + case 0x4a022: + case 0x4a024: + case 0x4a026: + case 0x4a028: + scrolly[(a & 0x0f) / 2] = d; + return; + } +} + +UINT8 __fastcall ashnojoe_read_byte(UINT32 a) +{ + bprintf (0, _T("%5.5x, rb\n"), a); + + return 0; +} + +UINT16 __fastcall ashnojoe_read_word(UINT32 a) +{ + switch (a) + { + case 0x4a000: + return DrvInputs[0]; + + case 0x4a002: + return DrvInputs[1]; + + case 0x4a004: + return ((DrvDips[1] << 8) | (DrvDips[0])); + + case 0x4a00a: + return 0; // debug? 1 kills sound + } + + return 0; +} + +void __fastcall ashnojoe_sound_write_port(UINT16 p, UINT8 d) +{ + switch (p & 0xff) + { + case 0x00: + BurnYM2203Write(0, 0, d); + return; + + case 0x01: + BurnYM2203Write(0, 1, d); + return; + + case 0x02: + adpcm_byte = d; + return; + } +} + +UINT8 __fastcall ashnojoe_sound_read_port(UINT16 p) +{ + switch (p & 0xff) + { + case 0x00: + return BurnYM2203Read(0, 0); + + case 0x01: + return BurnYM2203Read(0, 1); + + case 0x04: + *soundstatus = 0; + return *soundlatch; + + case 0x06: + return *soundstatus; + } + + return 0; +} + +void DrvYM2203WritePortA(UINT32, UINT32 d) +{ + MSM5205ResetWrite(0, !(d & 0x01)); +} + +void DrvYM2203WritePortB(UINT32, UINT32 d) +{ + INT32 bank = (d & 0x0f) * 0x8000; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80Banks + bank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80Banks + bank); +} + +inline static void DrvIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static void ashnojoe_vclk_cb() +{ + if (MSM5205_vclk_toggle == 0) + { + MSM5205DataWrite(0, adpcm_byte >> 4); + } + else + { + MSM5205DataWrite(0, adpcm_byte & 0xf); + ZetNmi(); + } + + MSM5205_vclk_toggle ^= 1; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + + BurnYM2203Reset(); + MSM5205Reset(); + + ZetClose(); + + adpcm_byte = 0; + MSM5205_vclk_toggle = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x010000; + DrvZ80Banks = Next; Next += 0x080000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x040000; + DrvGfxROM2 = Next; Next += 0x040000; + DrvGfxROM3 = Next; Next += 0x200000; + DrvGfxROM4 = Next; Next += 0x600000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + DrvPfRAM = Next; Next += 0x009000; + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x001000; + + DrvZ80RAM = Next; Next += 0x002000; + + soundlatch = Next; Next += 0x000001; + soundstatus = Next; Next += 0x000001; + + tilemap_reg = Next; Next += 0x000001; + + scrollx = (UINT16*)Next; Next += 0x000008 * sizeof(UINT16); + scrolly = (UINT16*)Next; Next += 0x000008 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvGfxExpand(UINT8 *gfx, INT32 len, INT32 bs) //0,1,2 -8x8, 3,4 16x16 +{ + if (bs) BurnByteswap(gfx, len); + + for (INT32 i = len-1; i >= 0; i--) { + gfx[i * 2 + 1] = gfx[i] & 0x0f; + gfx[i * 2 + 0] = gfx[i] >> 4; + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x080000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x100000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x180000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x200000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x280000, 17, 1)) return 1; + + if (BurnLoadRom(DrvZ80Banks + 0x000000, 18, 1)) return 1; + + DrvGfxExpand(DrvGfxROM0, 0x020000, 0); + DrvGfxExpand(DrvGfxROM1, 0x020000, 0); + DrvGfxExpand(DrvGfxROM2, 0x020000, 0); + DrvGfxExpand(DrvGfxROM3, 0x100000, 1); + DrvGfxExpand(DrvGfxROM4, 0x300000, 1); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPfRAM, 0x040000, 0x048fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x049000, 0x049fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x04c000, 0x04ffff, SM_RAM); + SekMapMemory(Drv68KROM + 0x080000, 0x080000, 0x0bffff, SM_ROM); + SekSetWriteWordHandler(0, ashnojoe_write_word); + SekSetWriteByteHandler(0, ashnojoe_write_byte); + SekSetReadWordHandler(0, ashnojoe_read_word); + SekSetReadByteHandler(0, ashnojoe_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM); + ZetMapArea(0x6000, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x6000, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x6000, 0x7fff, 2, DrvZ80RAM); + ZetSetOutHandler(ashnojoe_sound_write_port); + ZetSetInHandler(ashnojoe_sound_read_port); + ZetMemEnd(); + + MSM5205Init(0, DrvSynchroniseStream, 384000, ashnojoe_vclk_cb, MSM5205_S48_4B, 100, 1); + + BurnYM2203Init(1, 4000000, &DrvIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetPorts(0, NULL, NULL, &DrvYM2203WritePortA, &DrvYM2203WritePortB); + BurnYM2203SetVolumeShift(4); + BurnTimerAttachZet(4000000); + + ZetClose(); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + + BurnYM2203Exit(); + MSM5205Exit(); + + BurnFree(AllMem); + + return 0; +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x1000/2; i++) { + INT32 d = p[i]; + + r = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_16x16_layer(UINT8 *ram, UINT8 *gfx, INT32 color_off, INT32 scroll_off, INT32 mask, INT32 transparent) +{ + INT32 xscroll = (scrollx[scroll_off] + 112) & 0x1ff; + INT32 yscroll = (scrolly[scroll_off] + 24) & 0x1ff; + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= xscroll; + if (sx < -15) sx += 512; + sy -= yscroll; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs * 2 + 0] & mask; + INT32 color = ((vram[offs * 2 + 1] >> 8) & 0x1f) + color_off; + + if (flipscreen) { + if (transparent) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, 272 - sx, 192 - sy, color, 4, 15, 0, gfx); + } else { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, 272 - sx, 192 - sy, color, 4, 0, gfx); + } + } else { + if (transparent) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, gfx); + } + } + } +} + +static void draw_8x8_layer(UINT8 *ram, UINT8 *gfx, INT32 color_off, INT32 scroll_off, INT32 high) +{ + INT32 xscroll = (scrollx[scroll_off] + 112) & 0x1ff; + INT32 yscroll = (scrolly[scroll_off] + 24) & (high ? 0x1ff : 0x0ff); + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * (32 << high); offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= xscroll; + if (sx < -7) sx += 512; + sy -= yscroll; + if (sy < -7) sy += 256 << high; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs] & 0x0fff; + INT32 color = (vram[offs] >> 12) + color_off; + + if (flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, 280 - sx, 200 - sy, color, 4, 15, 0, gfx); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } + } +} + +static INT32 DrvDraw() +{ + DrvRecalcPalette(); + + flipscreen = *tilemap_reg & 0x01; + + INT32 backlayer = (*tilemap_reg & 0x02) ? 0x7000 : 0x6000; + + if (nSpriteEnable & 0x01) draw_16x16_layer(DrvPfRAM + backlayer, DrvGfxROM3, 0x70, 4, 0x1fff, 0); + + if (nSpriteEnable & 0x02) draw_8x8_layer(DrvPfRAM + 0x2000, DrvGfxROM1, 0x60, 3, 1); + + if (nSpriteEnable & 0x04) draw_16x16_layer(DrvPfRAM + 0x5000, DrvGfxROM4, 0x40, 2, 0x7fff, 1); + + if (nSpriteEnable & 0x08) draw_16x16_layer(DrvPfRAM + 0x4000, DrvGfxROM4, 0x20, 1, 0x7fff, 1); + + if (nSpriteEnable & 0x10) draw_8x8_layer(DrvPfRAM + 0x0000, DrvGfxROM0, 0x10, 0, 1); + + if (nSpriteEnable & 0x20) draw_8x8_layer(DrvPfRAM + 0x8000, DrvGfxROM2, 0x00, 5, 1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0, 2 * sizeof(INT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + } + + INT32 nInterleave = MSM5205CalcInterleave(0, 4000000); + INT32 nCyclesTotal[2] = { 8000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + INT32 nNext[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + nNext[0] += nCyclesTotal[0] / nInterleave; + + nCyclesDone[0] += SekRun(nNext[0] - nCyclesDone[0]); + if (i == (nInterleave - 1)) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + nNext[1] += nCyclesTotal[1] / nInterleave; + BurnTimerUpdate(nNext[1]); + MSM5205Update(); + nCyclesDone[1] += nNext[1]; + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM5205Scan(nAction, pnMin); + } + + return 0; +} + + +// Success Joe (World) + +static struct BurnRomInfo scessjoeRomDesc[] = { + { "5.4q", 0x10000, 0xc805f9e7, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "6.4s", 0x10000, 0xeda7a537, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sj201-nw.6m", 0x40000, 0x5a64ca42, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "9.8q", 0x08000, 0x8767e212, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 Code + + { "8.5e", 0x10000, 0x9bcb160e, 3 | BRF_GRA }, // 4 Character Tiles + { "7.5c", 0x10000, 0xb250c69d, 3 | BRF_GRA }, // 5 + + { "4.4e", 0x10000, 0xaa6336d3, 4 | BRF_GRA }, // 6 Character Tiles + { "3.4c", 0x10000, 0x7e2d86b5, 4 | BRF_GRA }, // 7 + + { "2.3m", 0x10000, 0xc3254938, 5 | BRF_GRA }, // 8 Character Tiles + { "1.1m", 0x10000, 0x5d16a6fa, 5 | BRF_GRA }, // 9 + + { "sj402-nw.8e", 0x80000, 0xb6d33d06, 6 | BRF_GRA }, // 10 Background Tiles + { "sj403-nw.7e", 0x80000, 0x07143f56, 6 | BRF_GRA }, // 11 + + { "sj404-nw.7a", 0x80000, 0x8f134128, 7 | BRF_GRA }, // 12 Foreground Tiles + { "sj405-nw.7c", 0x80000, 0x6fd81699, 7 | BRF_GRA }, // 13 + { "sj406-nw.7d", 0x80000, 0x634e33e6, 7 | BRF_GRA }, // 14 + { "sj407-nw.7f", 0x80000, 0x5c66ff06, 7 | BRF_GRA }, // 15 + { "sj408-nw.7g", 0x80000, 0x6a3b1ea1, 7 | BRF_GRA }, // 16 + { "sj409-nw.7j", 0x80000, 0xd8764213, 7 | BRF_GRA }, // 17 + + { "sj401-nw.10r", 0x80000, 0x25dfab59, 8 | BRF_PRG | BRF_ESS }, // 18 Z80 Banks +}; + +STD_ROM_PICK(scessjoe) +STD_ROM_FN(scessjoe) + +struct BurnDriver BurnDrvScessjoe = { + "scessjoe", NULL, NULL, NULL, "1990", + "Success Joe (World)\0", "Incomplete sound", "WAVE / Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, scessjoeRomInfo, scessjoeRomName, NULL, NULL, AshnojoeInputInfo, AshnojoeDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x800, + 288, 208, 4, 3 +}; + + +// Ashita no Joe (Japan) + +static struct BurnRomInfo ashnojoeRomDesc[] = { + { "5.bin", 0x10000, 0xc61e1569, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "6.bin", 0x10000, 0xc0a16338, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sj201-nw.6m", 0x40000, 0x5a64ca42, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "9.8q", 0x08000, 0x8767e212, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 Code + + { "8.5e", 0x10000, 0x9bcb160e, 3 | BRF_GRA }, // 4 Character Tiles + { "7.bin", 0x10000, 0x7e1efc42, 3 | BRF_GRA }, // 5 + + { "4.4e", 0x10000, 0xaa6336d3, 4 | BRF_GRA }, // 6 Character Tiles + { "3.4c", 0x10000, 0x7e2d86b5, 4 | BRF_GRA }, // 7 + + { "2.3m", 0x10000, 0xc3254938, 5 | BRF_GRA }, // 8 Character Tiles + { "1.bin", 0x10000, 0x1bf585f0, 5 | BRF_GRA }, // 9 + + { "sj402-nw.8e", 0x80000, 0xb6d33d06, 6 | BRF_GRA }, // 10 Background Tiles + { "sj403-nw.7e", 0x80000, 0x07143f56, 6 | BRF_GRA }, // 11 + + { "sj404-nw.7a", 0x80000, 0x8f134128, 7 | BRF_GRA }, // 12 Foreground Tiles + { "sj405-nw.7c", 0x80000, 0x6fd81699, 7 | BRF_GRA }, // 13 + { "sj406-nw.7d", 0x80000, 0x634e33e6, 7 | BRF_GRA }, // 14 + { "sj407-nw.7f", 0x80000, 0x5c66ff06, 7 | BRF_GRA }, // 15 + { "sj408-nw.7g", 0x80000, 0x6a3b1ea1, 7 | BRF_GRA }, // 16 + { "sj409-nw.7j", 0x80000, 0xd8764213, 7 | BRF_GRA }, // 17 + + { "sj401-nw.10r", 0x80000, 0x25dfab59, 8 | BRF_PRG | BRF_ESS }, // 18 Z80 Banks +}; + +STD_ROM_PICK(ashnojoe) +STD_ROM_FN(ashnojoe) + +struct BurnDriver BurnDrvAshnojoe = { + "ashnojoe", "scessjoe", NULL, NULL, "1990", + "Ashita no Joe (Japan)\0", "Incomplete sound", "WAVE / Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, ashnojoeRomInfo, ashnojoeRomName, NULL, NULL, AshnojoeInputInfo, AshnojoeDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x800, + 288, 208, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_backfire.cpp b/src/burn/drivers/misc_post90s/d_backfire.cpp new file mode 100644 index 00000000..3dbf18da --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_backfire.cpp @@ -0,0 +1,757 @@ +// FB Alpha Backfire! driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "arm_intf.h" +#include "ymz280b.h" +#include "eeprom.h" +#include "deco16ic.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvArmROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +//static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM; +static UINT8 *DrvArmRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM0; +static UINT8 *DrvSprRAM1; + +static UINT16 *DrvTmpBitmap0; +static UINT16 *DrvTmpBitmap_p; +static UINT16 *DrvTmpBitmap1; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[1]; +static UINT16 DrvInputs[3]; +static UINT8 DrvReset; + +static UINT32 *priority; +static INT32 nPreviousDip; + +static struct BurnInputInfo BackfireInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy3 + 8, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy3 + 9, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy3 + 10, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy3 + 12, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy3 + 13, "p2 fire 5" }, + {"P2 Button 6", BIT_DIGITAL, DrvJoy3 + 14, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Backfire) + +static struct BurnDIPInfo BackfireDIPList[]= +{ + {0x1a, 0xff, 0xff, 0x08, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1a, 0x01, 0x08, 0x08, "Off" }, + {0x1a, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Single Screen (Hack)" }, + {0x1a, 0x01, 0x80, 0x00, "Off" }, + {0x1a, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Backfire) + +void backfire_write_byte(UINT32 address, UINT8 data) +{ + Write16Byte(((UINT8*)deco16_pf_control[0]), 0x100000, 0x10001f) // 16-bit + Write16Byte(deco16_pf_ram[0], 0x110000, 0x111fff) // 16-bit + Write16Byte(deco16_pf_ram[1], 0x114000, 0x115fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[0], 0x120000, 0x120fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[1], 0x124000, 0x124fff) // 16-bit + Write16Byte(((UINT8*)deco16_pf_control[1]), 0x130000, 0x13001f) // 16-bit + Write16Byte(deco16_pf_ram[2], 0x140000, 0x141fff) // 16-bit + Write16Byte(deco16_pf_ram[3], 0x144000, 0x145fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[2], 0x150000, 0x150fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[3], 0x154000, 0x154fff) // 16-bit + + switch (address) + { + case 0x1c0000: + YMZ280BWrite(0, data); + return; + + case 0x1c0004: + YMZ280BWrite(1, data); + return; + } +} + +void backfire_write_long(UINT32 address, UINT32 data) +{ + Write16Long(((UINT8*)deco16_pf_control[0]), 0x100000, 0x10001f) // 16-bit + Write16Long(deco16_pf_ram[0], 0x110000, 0x111fff) // 16-bit + Write16Long(deco16_pf_ram[1], 0x114000, 0x115fff) // 16-bit + Write16Long(deco16_pf_rowscroll[0], 0x120000, 0x120fff) // 16-bit + Write16Long(deco16_pf_rowscroll[1], 0x124000, 0x124fff) // 16-bit + Write16Long(((UINT8*)deco16_pf_control[1]), 0x130000, 0x13001f) // 16-bit + Write16Long(deco16_pf_ram[2], 0x140000, 0x141fff) // 16-bit + Write16Long(deco16_pf_ram[3], 0x144000, 0x145fff) // 16-bit + Write16Long(deco16_pf_rowscroll[2], 0x150000, 0x150fff) // 16-bit + Write16Long(deco16_pf_rowscroll[3], 0x154000, 0x154fff) // 16-bit + + switch (address) + { + case 0x1a4000: + EEPROMWrite(data & 0x02, data & 0x04, data & 0x01); + return; + + case 0x1a8000: + priority[0] = data; // left + return; + + case 0x1ac000: + priority[1] = data; // right + return; + + case 0x1c0000: + YMZ280BWrite(0, data); + return; + + case 0x1c0004: + YMZ280BWrite(1, data); + return; + } +} + +UINT8 backfire_read_byte(UINT32 address) +{ + Read16Byte(((UINT8*)deco16_pf_control[0]), 0x100000, 0x10001f) // 16-bit + Read16Byte(deco16_pf_ram[0], 0x110000, 0x111fff) // 16-bit + Read16Byte(deco16_pf_ram[1], 0x114000, 0x115fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[0], 0x120000, 0x120fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[1], 0x124000, 0x124fff) // 16-bit + Read16Byte(((UINT8*)deco16_pf_control[1]), 0x130000, 0x13001f) // 16-bit + Read16Byte(deco16_pf_ram[2], 0x140000, 0x141fff) // 16-bit + Read16Byte(deco16_pf_ram[3], 0x144000, 0x145fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[2], 0x150000, 0x150fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[3], 0x154000, 0x154fff) // 16-bit + + switch (address) + { + case 0x190000: return DrvInputs[0]; + case 0x190002: return DrvInputs[2]; + case 0x194002: return DrvInputs[1]; + + case 0x1c0000: return YMZ280BRead(0); + case 0x1c0004: return YMZ280BRead(1); + } + + return 0; +} + +UINT32 backfire_read_long(UINT32 address) +{ + Read16Long(((UINT8*)deco16_pf_control[0]), 0x100000, 0x10001f) // 16-bit + Read16Long(deco16_pf_ram[0], 0x110000, 0x111fff) // 16-bit + Read16Long(deco16_pf_ram[1], 0x114000, 0x115fff) // 16-bit + Read16Long(deco16_pf_rowscroll[0], 0x120000, 0x120fff) // 16-bit + Read16Long(deco16_pf_rowscroll[1], 0x124000, 0x124fff) // 16-bit + Read16Long(((UINT8*)deco16_pf_control[1]), 0x130000, 0x13001f) // 16-bit + Read16Long(deco16_pf_ram[2], 0x140000, 0x141fff) // 16-bit + Read16Long(deco16_pf_ram[3], 0x144000, 0x145fff) // 16-bit + Read16Long(deco16_pf_rowscroll[2], 0x150000, 0x150fff) // 16-bit + Read16Long(deco16_pf_rowscroll[3], 0x154000, 0x154fff) // 16-bit + + switch (address) + { + case 0x190000: { + UINT32 vblnk=0; + vblnk ^= 1 << 16; + + UINT32 ret = 0; + ret |= EEPROMRead() << 24; + ret |= (DrvInputs[2] & 0xbf) << 16; + ret |= deco16_vblank; + ret |= DrvInputs[0]; + ret |= vblnk; + return ret; + } + + case 0x194000: { + UINT32 ret = 0; + ret |= EEPROMRead() << 24; + ret |= DrvInputs[1] << 16; + ret |= DrvInputs[1] << 0; + return ret; + } + + case 0x1c0000: + return YMZ280BRead(0); + + case 0x1c0004: + return YMZ280BRead(1); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvArmROM = Next; Next += 0x0100000; + + DrvGfxROM0 = Next; Next += 0x0800000; + DrvGfxROM1 = Next; Next += 0x0800000; + DrvGfxROM2 = Next; Next += 0x0200000; + DrvGfxROM3 = Next; Next += 0x0800000; +// DrvGfxROM4 = Next; Next += 0x0800000; + + YMZ280BROM = Next; + DrvSndROM = Next; Next += 0x0400000; + + DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32); + + DrvTmpBitmap_p = (UINT16*)Next; + DrvTmpBitmap0 = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + DrvTmpBitmap1 = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + + AllRam = Next; + + DrvArmRAM = Next; Next += 0x0008000; + DrvPalRAM = Next; Next += 0x0002000; + DrvSprRAM0 = Next; Next += 0x0002000; + DrvSprRAM1 = Next; Next += 0x0002000; + + priority = (UINT32*)Next; Next += 2 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ArmOpen(0); + ArmReset(); + ArmClose(); + + YMZ280BReset(); + + EEPROMReset(); + + deco16Reset(); + + return 0; +} + +static INT32 backfire_bank_callback( INT32 bank ) +{ + bank = bank >> 4; + bank = (bank & 1) | ((bank & 4) >> 1) | ((bank & 2) << 1); + + return bank * 0x1000; +} + +static void sprite_decode(UINT8 *gfx, INT32 len) +{ + INT32 Plane[4] = { 16, 0, 24, 8 }; + INT32 XOffs[16] = { 512,513,514,515,516,517,518,519, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32,10*32,11*32,12*32,13*32,14*32,15*32}; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, gfx, len); + + GfxDecode((len * 2) / 0x100, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, gfx); + + BurnFree (tmp); +} + +static void decode_samples() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + + for (INT32 i = 0; i < 0x200000; i++) { + tmp[((i & 1) << 20) | (i >> 1) ] = DrvSndROM[i]; + } + + memcpy (DrvSndROM, tmp, 0x200000); + + BurnFree (tmp); +} + +static void pCommonSpeedhackCallback() +{ + ArmIdleCycles(1120); + //bprintf (0, _T("idle skip triggered!\n")); +} + +static INT32 DrvInit(UINT32 speedhack) +{ + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvArmROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(DrvArmROM + 0x000000, 1, 2)) return 1; + + for (INT32 i = 0; i < 0x100000; i+=4) { + BurnByteswap(DrvArmROM + i + 1, 2); + } + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 3, 1)) return 1; + + for (INT32 i = 0; i < 0x400000; i++) { + INT32 j = (i & 0x17ffff) | ((i & 0x80000) << 2) | ((i & 0x200000) >> 2); + DrvGfxROM0[j] = DrvGfxROM1[i]; + } + memset (DrvGfxROM1, 0, 0x400000); + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 6, 2)) return 1; + + // if (BurnLoadRom(DrvGfxROM4 + 0x000001, 7, 2)) return 1; + // if (BurnLoadRom(DrvGfxROM4 + 0x000000, 8, 2)) return 1; + + memset (DrvSndROM, 0xff, 0x400000); + if (BurnLoadRom(DrvSndROM + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x200000, 10, 1)) return 1; + + deco156_decrypt(DrvArmROM, 0x100000); + + deco56_decrypt_gfx(DrvGfxROM0, 0x400000); + deco56_decrypt_gfx(DrvGfxROM2, 0x100000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM1, 0x400000, 0); + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x400000, 1); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + + sprite_decode(DrvGfxROM3, 0x400000); + // sprite_decode(DrvGfxROM4, 0x400000); + + decode_samples(); + } + + ArmInit(1); + ArmOpen(0); + ArmMapMemory(DrvArmROM, 0x000000, 0x0fffff, ARM_ROM); + ArmMapMemory(DrvPalRAM, 0x160000, 0x161fff, ARM_RAM); + ArmMapMemory(DrvArmRAM, 0x170000, 0x177fff, ARM_RAM); + ArmMapMemory(DrvSprRAM0, 0x184000, 0x185fff, ARM_RAM); + ArmMapMemory(DrvSprRAM1, 0x18c000, 0x18dfff, ARM_RAM); + ArmSetWriteByteHandler(backfire_write_byte); + ArmSetWriteLongHandler(backfire_write_long); + ArmSetReadByteHandler(backfire_read_byte); + ArmSetReadLongHandler(backfire_read_long); + ArmClose(); + + ArmSetSpeedHack(speedhack ? speedhack : ~0, pCommonSpeedhackCallback); + + EEPROMInit(&eeprom_interface_93C46); + + YMZ280BInit(14000000, NULL, 3); + + deco16Init(0, 0, 1); + deco16_set_bank_callback(0, backfire_bank_callback); + deco16_set_bank_callback(1, backfire_bank_callback); + deco16_set_bank_callback(2, backfire_bank_callback); + deco16_set_bank_callback(3, backfire_bank_callback); + deco16_set_color_base(1, 0x400); + deco16_set_color_base(2, 0x100); + deco16_set_color_base(3, 0x500); + deco16_set_graphics(DrvGfxROM0, 0x800000, DrvGfxROM1, 0x800000, DrvGfxROM2, 0x200000); + deco16_set_global_offsets(0, 8); + + GenericTilesInit(); + + nPreviousDip = DrvDips[0] & 0x80; + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + ArmExit(); + + YMZ280BExit(); + YMZ280BROM = NULL; + + GenericTilesExit(); + + deco16Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void simpl156_palette_recalc() +{ + UINT32 *p = (UINT32*)DrvPalRAM; + + for (INT32 i = 0; i < 0x2000 / 4; i++) + { + INT32 r = (p[i] >> 0) & 0x1f; + INT32 g = (p[i] >> 5) & 0x1f; + INT32 b = (p[i] >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites(UINT16 *dest, UINT8 *ram, UINT8 *gfx, INT32 coloff) +{ + UINT32 *spriteram = (UINT32*)ram; + + for (INT32 offs = (0x1400 / 4) - 4; offs >= 0; offs -= 4) + { + INT32 x, y, sprite, colour, multi, fx, fy, inc, flash, mult, pri; + + sprite = spriteram[offs + 1] & 0xffff; + + y = spriteram[offs] & 0xffff; + flash = y & 0x1000; + if (flash && (nCurrentFrame & 1)) + continue; + + x = spriteram[offs + 2] & 0xffff; + colour = (x >> 9) & 0x1f; + + pri = x & 0xc000; + + switch (pri & 0xc000) + { + case 0x0000: pri = 0; break; + case 0x4000: pri = 0xf0;break; + case 0x8000: pri = 0; break; + case 0xc000: pri = 0xf0;break; + } + + fx = y & 0x2000; + fy = y & 0x4000; + multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + y = 240 - y; + x = 304 - x; + + if (x > 320) continue; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (1) + { + y = 240 - y; + x = 304 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else mult = -16; + + while (multi >= 0) + { + deco16_draw_prio_sprite(dest, gfx, sprite - multi * inc, (colour<<4)+coloff, x, y + mult * multi, fx, fy, pri); + + multi--; + } + } +} + +static INT32 DrvDraw() +{ + if ((DrvDips[0] & 0x80) && nPreviousDip == 0) { // single screen + DrvTmpBitmap0 = pTransDraw; + BurnDrvSetVisibleSize(320, 240); + BurnDrvSetAspect(4, 3); + Reinitialise(); + } else if (!(DrvDips[0] & 0x80) && nPreviousDip == 0x80) { // two screens + DrvTmpBitmap0 = DrvTmpBitmap_p; + BurnDrvSetVisibleSize(640, 240); + BurnDrvSetAspect(8, 3); + Reinitialise(); + } + nPreviousDip = DrvDips[0] & 0x80; + + simpl156_palette_recalc(); + + deco16_pf12_update(); + deco16_pf34_update(); + + if (nPreviousDip == 0) nScreenWidth = 320; + + // left + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + DrvTmpBitmap0[i] = 0x100; + } + + deco16_clear_prio_map(); + + if (priority[0] == 0) { + deco16_draw_layer(2, DrvTmpBitmap0, 1); + deco16_draw_layer(0, DrvTmpBitmap0, 2); + } else if (priority[0] == 2) { + deco16_draw_layer(0, DrvTmpBitmap0, 2); + deco16_draw_layer(2, DrvTmpBitmap0, 4); + } + + draw_sprites(DrvTmpBitmap0, DrvSprRAM0, DrvGfxROM3, 0x200); + } + + // right + if (nPreviousDip == 0) { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + DrvTmpBitmap1[i] = 0x500; + } + + deco16_clear_prio_map(); + + if (priority[1] == 0) { + deco16_draw_layer(3, DrvTmpBitmap1, 1); + deco16_draw_layer(1, DrvTmpBitmap1, 2); + } else if (priority[1] == 2) { + deco16_draw_layer(1, DrvTmpBitmap1, 2); + deco16_draw_layer(3, DrvTmpBitmap1, 4); + } + + draw_sprites(DrvTmpBitmap1, DrvSprRAM1, DrvGfxROM3 /*DrvGfxROM4*/, 0x600); + + // combine + + UINT16 *dst0 = pTransDraw; + UINT16 *dst1 = pTransDraw + 320; + UINT16 *src0 = DrvTmpBitmap0; + UINT16 *src1 = DrvTmpBitmap1; + + for (INT32 y = 0; y < nScreenHeight; y++) { + memcpy (dst0, src0, 320 * sizeof(UINT16)); + memcpy (dst1, src1, 320 * sizeof(UINT16)); + + dst0 += 640; + dst1 += 640; + src0 += 320; + src1 += 320; + } + + nScreenWidth = 320 * 2; + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0x00ff; + DrvInputs[1] = 0x00ff; + DrvInputs[2] = 0xffe7; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[2] |= DrvDips[0] & 0x0008; + + if (DrvDips[0] & 0x80) DrvInputs[1] |= 0x80; + } + + INT32 nTotalCycles = 28000000 / 60; + + ArmOpen(0); + deco16_vblank = 0x10; + ArmRun(nTotalCycles - 2240); + ArmSetIRQLine(ARM_IRQ_LINE, ARM_HOLD_LINE); + deco16_vblank = 0x00; + ArmRun(2240); + ArmClose(); + + if (pBurnSoundOut) { + YMZ280BRender(pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ArmScan(nAction, pnMin); + + YMZ280BScan(); + + deco16Scan(); + } + + return 0; +} + + +// Backfire! (set 1) + +static struct BurnRomInfo backfireRomDesc[] = { + { "ra00-0.2j", 0x080000, 0x790da069, 1 | BRF_PRG | BRF_ESS }, // 0 Arm code (Encrypted) + { "ra01-0.3j", 0x080000, 0x447cb57b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "mbz-00.9a", 0x200000, 0x1098d504, 2 | BRF_GRA }, // 2 Characters & tiles + { "mbz-01.10a", 0x200000, 0x19b81e5c, 2 | BRF_GRA }, // 3 + + { "mbz-02.12a", 0x100000, 0x2bd2b0a1, 3 | BRF_GRA }, // 4 Tiles + + { "mbz-03.15a", 0x200000, 0x2e818569, 4 | BRF_GRA }, // 5 Left screen sprites + { "mbz-04.16a", 0x200000, 0x67bdafb1, 4 | BRF_GRA }, // 6 + + { "mbz-03.18a", 0x200000, 0x2e818569, 5 | BRF_GRA }, // 7 Right screen sprites + { "mbz-04.19a", 0x200000, 0x67bdafb1, 5 | BRF_GRA }, // 8 + + { "mbz-05.17l", 0x200000, 0x947c1da6, 6 | BRF_SND }, // 9 YMZ280b Samples + { "mbz-06.19l", 0x080000, 0x4a38c635, 6 | BRF_SND }, // 10 + + { "gal16v8b.6b", 0x000117, 0x00000000, 7 | BRF_NODUMP }, // 11 PLDs + { "gal16v8b.6d", 0x000117, 0x00000000, 7 | BRF_NODUMP }, // 12 + { "gal16v8b.12n", 0x000117, 0x00000000, 7 | BRF_NODUMP }, // 13 +}; + +STD_ROM_PICK(backfire) +STD_ROM_FN(backfire) + +static INT32 backfireInit() +{ + return DrvInit(0xce44); +} + +struct BurnDriver BurnDrvBackfire = { + "backfire", NULL, NULL, NULL, "1995", + "Backfire! (set 1)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, backfireRomInfo, backfireRomName, NULL, NULL, BackfireInputInfo, BackfireDIPInfo, + backfireInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 640, 240, 8, 3 +}; + + +// Backfire! (set 2) + +static struct BurnRomInfo backfireaRomDesc[] = { + { "rb-00h.h2", 0x080000, 0x60973046, 1 | BRF_PRG | BRF_ESS }, // 0 Arm code (Encrypted) + { "rb-01l.h3", 0x080000, 0x27472f60, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "mbz-00.9a", 0x200000, 0x1098d504, 2 | BRF_GRA }, // 2 Characters & tiles + { "mbz-01.10a", 0x200000, 0x19b81e5c, 2 | BRF_GRA }, // 3 + + { "mbz-02.12a", 0x100000, 0x2bd2b0a1, 3 | BRF_GRA }, // 4 Tiles + + { "mbz-03.15a", 0x200000, 0x2e818569, 4 | BRF_GRA }, // 5 Left screen sprites + { "mbz-04.16a", 0x200000, 0x67bdafb1, 4 | BRF_GRA }, // 6 + + { "mbz-03.18a", 0x200000, 0x2e818569, 5 | BRF_GRA }, // 7 Right screen sprites + { "mbz-04.19a", 0x200000, 0x67bdafb1, 5 | BRF_GRA }, // 8 + + { "mbz-05.17l", 0x200000, 0x947c1da6, 6 | BRF_SND }, // 9 YMZ280b Samples + { "mbz-06.19l", 0x080000, 0x4a38c635, 6 | BRF_SND }, // 10 +}; + +STD_ROM_PICK(backfirea) +STD_ROM_FN(backfirea) + +static INT32 backfireaInit() +{ + return DrvInit(0xcee4); +} + +struct BurnDriverD BurnDrvBackfirea = { + "backfirea", "backfire", NULL, NULL, "1995", + "Backfire! (set 2)\0", "Set inputs to \"Joystick\" in test mode", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, backfireaRomInfo, backfireaRomName, NULL, NULL, BackfireInputInfo, BackfireDIPInfo, + backfireaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 640, 240, 8, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_bloodbro.cpp b/src/burn/drivers/misc_post90s/d_bloodbro.cpp new file mode 100644 index 00000000..94efdec0 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_bloodbro.cpp @@ -0,0 +1,1108 @@ +// FB Alpha Blood Bros. driver module +// FB Alpha Blood Bros. driver module +// Based on MAME driver by Carlos A. Lozano Baides and Richard Bush + +#include "tiles_generic.h" +#include "seibusnd.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvTxRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvScrollRAM; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[2]; +static UINT8 DrvJoy2[15]; +static UINT8 DrvJoy3[13]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static INT32 nGameSelect = 0; + +static struct BurnInputInfo BloodbroInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 12, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Bloodbro) + +static struct BurnInputInfo WeststryInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Weststry) + +static struct BurnInputInfo SkysmashInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 12, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Skysmash) + +static struct BurnDIPInfo BloodbroDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x14, 0x01, 0x01, 0x01, "1" }, + {0x14, 0x01, 0x01, 0x00, "2" }, + + // Coinage condition: Coin Mode 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x14, 0x02, 0x1e, 0x14, "6 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x16, "5 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x18, "4 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x1a, "3 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x02, "8 Coins 3 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x1c, "2 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x04, "5 Coins 3 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x06, "3 Coins 2 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x1e, "1 Coin 1 Credit" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x08, "2 Coins 3 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x12, "1 Coin 2 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x10, "1 Coin 3 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x0e, "1 Coin 4 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x0c, "1 Coin 5 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + {0x14, 0x02, 0x1e, 0x00, "Free Play" }, + {0x14, 0x00, 0x01, 0x01, NULL}, + + // Coin A condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x02, 0x06, 0x00, "5 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x06, 0x02, "3 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x06, 0x04, "2 Coins 1 Credit" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x06, 0x06, "1 Coin 1 Credit" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + + // Coin B condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x02, 0x18, 0x18, "1 Coin 2 Credits" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x18, 0x10, "1 Coin 3 Credits" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x18, 0x08, "1 Coin 5 Credits" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + {0x14, 0x02, 0x18, 0x00, "1 Coin 6 Credits" }, + {0x14, 0x00, 0x01, 0x00, NULL}, + + {0 , 0xfe, 0 , 2, "Starting Coin" }, + {0x14, 0x01, 0x20, 0x20, "Normal" }, + {0x14, 0x01, 0x20, 0x00, "x2" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x00, "1" }, + {0x15, 0x01, 0x03, 0x02, "2" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "300K, 500K Every" }, + {0x15, 0x01, 0x0c, 0x08, "500K, 500K Every" }, + {0x15, 0x01, 0x0c, 0x04, "500K Only" }, + {0x15, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x20, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x40, 0x00, "No" }, + {0x15, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Bloodbro) + +static struct BurnDIPInfo WeststryDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x01, 0x01, "1" }, + {0x13, 0x01, 0x01, 0x00, "2" }, + + // Coinage condition: Coin Mode 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x13, 0x02, 0x1e, 0x14, "6 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x16, "5 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x18, "4 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x1a, "3 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x02, "8 Coins 3 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x1c, "2 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x04, "5 Coins 3 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x06, "3 Coins 2 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x1e, "1 Coin 1 Credit" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x08, "2 Coins 3 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x12, "1 Coin 2 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x0e, "1 Coin 4 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x0c, "1 Coin 5 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x0a, "1 Coin 6 Credits" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + {0x13, 0x02, 0x1e, 0x00, "Free Play" }, + {0x13, 0x00, 0x01, 0x01, NULL}, + + // Coin A condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x02, 0x06, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x06, 0x02, "3 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x06, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x06, 0x06, "1 Coin 1 Credit" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + + // Coin B condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x02, 0x18, 0x18, "1 Coin 2 Credits" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x18, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x18, 0x08, "1 Coin 5 Credits" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + {0x13, 0x02, 0x18, 0x00, "1 Coin 6 Credits" }, + {0x13, 0x00, 0x01, 0x00, NULL}, + + {0 , 0xfe, 0 , 2, "Starting Coin" }, + {0x13, 0x01, 0x20, 0x20, "Normal" }, + {0x13, 0x01, 0x20, 0x00, "x2" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x00, "1" }, + {0x14, 0x01, 0x03, 0x02, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "300K, 500K Every" }, + {0x14, 0x01, 0x0c, 0x08, "500K, 500K Every" }, + {0x14, 0x01, 0x0c, 0x04, "500K Only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x10, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "No" }, + {0x14, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Weststry) + +static struct BurnDIPInfo SkysmashDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x12, 0x01, 0x01, 0x01, "1" }, + {0x12, 0x01, 0x01, 0x00, "2" }, + + // Coinage condition: Coin Mode 1 + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x12, 0x02, 0x1e, 0x14, "6 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x16, "5 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x18, "4 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x1a, "3 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x02, "8 Coins 3 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x1c, "2 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x04, "5 Coins 3 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x06, "3 Coins 2 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x1e, "1 Coin 1 Credit" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x08, "2 Coins 3 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x12, "1 Coin 2 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x10, "1 Coin 3 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x0e, "1 Coin 4 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x0c, "1 Coin 5 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + {0x12, 0x02, 0x1e, 0x00, "Free Play" }, + {0x12, 0x00, 0x01, 0x01, NULL}, + + // Coin A condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x12, 0x02, 0x06, 0x00, "5 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x06, 0x02, "3 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x06, 0x04, "2 Coins 1 Credit" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x06, 0x06, "1 Coin 1 Credit" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + + // Coin B condition: Coin Mode 2 + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x12, 0x02, 0x18, 0x18, "1 Coin 2 Credits" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x18, 0x10, "1 Coin 3 Credits" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x18, 0x08, "1 Coin 5 Credits" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + {0x12, 0x02, 0x18, 0x00, "1 Coin 6 Credits" }, + {0x12, 0x00, 0x01, 0x00, NULL}, + + {0 , 0xfe, 0 , 2, "Starting Coin" }, + {0x12, 0x01, 0x20, 0x20, "Normal" }, + {0x12, 0x01, 0x20, 0x00, "x2" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x0c, 0x0c, "120K, 200K Every" }, + {0x13, 0x01, 0x0c, 0x08, "200K, 200K Every" }, + {0x13, 0x01, 0x0c, 0x04, "250K, 250K Every" }, + {0x13, 0x01, 0x0c, 0x00, "200K Only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x30, 0x00, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + {0x13, 0x01, 0x30, 0x20, "Hard" }, + {0x13, 0x01, 0x30, 0x10, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Skysmash) + +void __fastcall bloodbro_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffffff0) == 0xa0000) { + seibu_main_word_write(address, data); + return; + } +} + +void __fastcall bloodbro_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffffff0) == 0xa0000) { + seibu_main_word_write(address, data); + return; + } + + if ((address & 0xfffff80) == 0xc0000) { + *((UINT16*)(DrvScrollRAM + (address & 0x7e))) = data; + return; + } +} + +UINT8 __fastcall bloodbro_read_byte(UINT32 address) +{ + if ((address & 0xffffff0) == 0xa0000) { + return seibu_main_word_read(address); + } + + return 0; +} + +UINT16 __fastcall bloodbro_read_word(UINT32 address) +{ + if ((address & 0xffffff0) == 0xa0000) { + return seibu_main_word_read(address); + } + + switch (address) + { + case 0xe0000: + return ((DrvDips[1] << 8) | DrvDips[0]); + + case 0xe0002: + return DrvInputs[1]; + + case 0xe0004: + return DrvInputs[2]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + seibu_sound_reset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x00000, 0x00004, 0x80000, 0x80004 }; + INT32 XOffs0[8] = { 0x003, 0x002, 0x001, 0x000, 0x00b, 0x00a, 0x009, 0x008 }; + INT32 YOffs0[8] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 }; + + INT32 Plane1[4] = { 0x008, 0x00c, 0x000, 0x004 }; + INT32 XOffs1[16] = { 0x003, 0x002, 0x001, 0x000, 0x013, 0x012, 0x011, 0x010, + 0x203, 0x202, 0x201, 0x200, 0x213, 0x212, 0x211, 0x210 }; + INT32 YOffs1[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(0x1000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + SeibuZ80ROM = Next; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x00b800; + Drv68KRAM1 = Next; Next += 0x009000; + + DrvPalRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x001000; + DrvBgRAM = Next; Next += 0x001000; + DrvTxRAM = Next; Next += 0x002800; + DrvFgRAM = Next; Next += 0x001000; + + DrvScrollRAM = Next; Next += 0x000080; + + SeibuZ80RAM = Next; + DrvZ80RAM = Next; Next += 0x000800; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "weststry")) + { + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x8000, 0x8000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x8000, 0x8000); + + UINT8 *pTemp = (UINT8*)BurnMalloc(0x10000); + if (BurnLoadRom(pTemp + 0x00000, 5, 1)) return 1; + memcpy(DrvGfxROM0 + 0x00000, pTemp + 0x8000, 0x8000); + if (BurnLoadRom(pTemp + 0x00000, 6, 1)) return 1; + memcpy(DrvGfxROM0 + 0x08000, pTemp + 0x8000, 0x8000); + if (BurnLoadRom(pTemp + 0x00000, 7, 1)) return 1; + memcpy(DrvGfxROM0 + 0x10000, pTemp + 0x8000, 0x8000); + if (BurnLoadRom(pTemp + 0x00000, 8, 1)) return 1; + memcpy(DrvGfxROM0 + 0x18000, pTemp + 0x8000, 0x8000); + BurnFree(pTemp); + + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000,10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0xa0000,11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0xe0000,12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x00000,13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000,14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000,15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0xc0000,16, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000,17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000,18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000,19, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000,20, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000,21, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0xa0000,22, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0xc0000,23, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0xe0000,24, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000,25, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x08afff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x08b000, 0x08bfff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x08c000, 0x08cfff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x08d000, 0x08d7ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x08d800, 0x08ffff, SM_RAM); + SekMapMemory(Drv68KRAM + 0xb000, 0x0c1000, 0x0c17ff, SM_RAM); + SekMapMemory(Drv68KRAM1 + 0x0000, 0x120000, 0x127fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x128000, 0x1287ff, SM_RAM); + SekMapMemory(Drv68KRAM1 + 0x8800, 0x128800, 0x128fff, SM_RAM); + SekClose(); + + nGameSelect = 2; + } + else + { + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x8000, 0x8000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x8000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 9, 1)) return 1; + + DrvGfxDecode(); + } + + nGameSelect = 0; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "skysmash")) nGameSelect = 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x08afff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x08b000, 0x08bfff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x08c000, 0x08cfff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x08d000, 0x08d7ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x08d800, 0x08e7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x08e800, 0x08f7ff, SM_RAM); + SekMapMemory(Drv68KRAM + 0xb000, 0x08f800, 0x08ffff, SM_RAM); + SekSetWriteByteHandler(0, bloodbro_write_byte); + SekSetWriteWordHandler(0, bloodbro_write_word); + SekSetReadByteHandler(0, bloodbro_read_byte); + SekSetReadWordHandler(0, bloodbro_read_word); + SekClose(); + } + + seibu_sound_init(0, 0, 3579545, 3579545, 1000000/132); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + SekExit(); + + seibu_sound_exit(); + + BurnFree (AllMem); + + nGameSelect = 0; + + return 0; +} + +static void draw_layer(UINT8 *src, INT32 palette_offset, INT32 transp, INT32 scrollx, INT32 scrolly) +{ + UINT16 *vram = (UINT16*)src; + + for (INT32 offs = 0; offs < 32 * 16; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x200; + sy -= scrolly + 16; + if (sy < -15) sy += 0x100; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = (vram[offs] & 0xfff) | (transp << 12); + INT32 color = vram[offs] >> 12; + + if (transp) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, palette_offset, DrvGfxROM1); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, palette_offset, DrvGfxROM1); + } + } +} + +static void draw_text_layer() +{ + UINT16 *vram = (UINT16*)DrvTxRAM; + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 code = vram[offs] & 0xfff; + if (!code) continue; + + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + INT32 color = vram[offs] >> 12; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy-16, color, 4, 15, 0x700, DrvGfxROM0); + } +} + +static void draw_sprites(INT32 priority) +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0x800-4; offs >= 0; offs -= 4) + { + INT32 attr = ram[offs]; + INT32 prio = (attr & 0x0800) >> 11; + if (attr & 0x8000 || prio != priority) continue; + + INT32 width = (attr >> 7) & 7; + INT32 height = (attr >> 4) & 7; + INT32 code = ram[offs+1] & 0x1fff; + INT32 sx = ram[offs+2] & 0x01ff; + INT32 sy = ram[offs+3] & 0x01ff; + if (sx > 255) sx -= 512; + if (sy > 255) sy -= 512; + sy -= 16; + + INT32 flipx = attr & 0x2000; + INT32 flipy = attr & 0x4000; + INT32 color = attr & 0x000f; + + for (INT32 x = 0; x <= width; x++) + { + for (INT32 y = 0; y <= height; y++) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx + 16*(width-x), sy + 16*(height-y), color, 4, 15, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx + 16*x, sy + 16*(height-y), color, 4, 15, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx + 16*(width-x), sy + 16*y, color, 4, 15, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx + 16*x, sy + 16*y, color, 4, 15, 0, DrvGfxROM2); + } + } + + code++; + code &= 0x1fff; + } + } + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x1000/2; i++) + { + INT32 data = p[i]; + + r = (data >> 0) & 0x0f; + g = (data >> 4) & 0x0f; + b = (data >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + UINT16 *scroll = (UINT16*)DrvScrollRAM; + scroll += 0x10 >> (nGameSelect & 1); // skysmash + + draw_layer(DrvBgRAM, 0x400, 0, scroll[0] & 0x1ff, scroll[1] & 0x0ff); + + draw_sprites(1); + + draw_layer(DrvFgRAM, 0x500, 1, scroll[2] & 0x1ff, scroll[3] & 0x0ff); + + draw_sprites(0); + + draw_text_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + if (nGameSelect == 2) { + UINT16 *ram = (UINT16*)(Drv68KRAM + 0xb000); + ram[0] = (DrvDips[1] << 8) | (DrvDips[0]); + ram[1] = DrvInputs[1]; + ram[2] = DrvInputs[2]; + } + + seibu_coin_input = (DrvJoy1[1] << 1) | DrvJoy1[0]; + } + + INT32 nSegment; + INT32 nInterleave = 1000; + INT32 nTotalCycles[2] = { 10000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nTotalCycles[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + + BurnTimerUpdateYM3812((nTotalCycles[1] / nInterleave) * (i+1)); + } + + if (nGameSelect == 0) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); // bloodbro + if (nGameSelect == 1) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // skysmash + if (nGameSelect == 2) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); // weststry + + BurnTimerEndFrameYM3812(nTotalCycles[1]); + + if (pBurnSoundOut) { + seibu_sound_update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029706; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + seibu_sound_scan(pnMin, nAction); + } + + return 0; +} + + +// Blood Bros. (set 1) + +static struct BurnRomInfo bloodbroRomDesc[] = { + { "bb_02.bin", 0x020000, 0xc0fdc3e4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bb_01.bin", 0x020000, 0x2d7e0fdf, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bb_04.bin", 0x020000, 0xfd951c2c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bb_03.bin", 0x020000, 0x18d3c460, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "bb_07.bin", 0x010000, 0x411b94e8, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "bb_05.bin", 0x010000, 0x04ba6d19, 3 | BRF_GRA }, // 5 Characters + { "bb_06.bin", 0x010000, 0x7092e35b, 3 | BRF_GRA }, // 6 + + { "bloodb.bk", 0x100000, 0x1aa87ee6, 4 | BRF_GRA }, // 7 Tiles + + { "bloodb.obj", 0x100000, 0xd27c3952, 5 | BRF_GRA }, // 8 Sprites + + { "bb_08.bin", 0x020000, 0xdeb1b975, 6 | BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(bloodbro) +STD_ROM_FN(bloodbro) + +struct BurnDriver BurnDrvBloodbro = { + "bloodbro", NULL, NULL, NULL, "1990", + "Blood Bros. (set 1)\0", NULL, "Tad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, bloodbroRomInfo, bloodbroRomName, NULL, NULL, BloodbroInputInfo, BloodbroDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// Blood Bros. (set 2) + +static struct BurnRomInfo bloodbroaRomDesc[] = { + { "2j.21", 0x020000, 0xe8ca21b8, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "1j.22", 0x020000, 0x6b28cfc7, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bb_04.bin", 0x020000, 0xfd951c2c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bb_03.bin", 0x020000, 0x18d3c460, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "bb_07.bin", 0x010000, 0x411b94e8, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "bb_05.bin", 0x010000, 0x04ba6d19, 3 | BRF_GRA }, // 5 Characters + { "bb_06.bin", 0x010000, 0x7092e35b, 3 | BRF_GRA }, // 6 + + { "bloodb.bk", 0x100000, 0x1aa87ee6, 4 | BRF_GRA }, // 7 Tiles + + { "bloodb.obj", 0x100000, 0xd27c3952, 5 | BRF_GRA }, // 8 Sprites + + { "bb_08.bin", 0x020000, 0xdeb1b975, 6 | BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(bloodbroa) +STD_ROM_FN(bloodbroa) + +struct BurnDriver BurnDrvBloodbroa = { + "bloodbroa", "bloodbro", NULL, NULL, "1990", + "Blood Bros. (set 2)\0", NULL, "Tad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, bloodbroaRomInfo, bloodbroaRomName, NULL, NULL, BloodbroInputInfo, BloodbroDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// Blood Bros. (set 3) + +static struct BurnRomInfo bloodbrobRomDesc[] = { + { "bloodbros02.bin", 0x020000, 0x204dca6e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bloodbros01.bin", 0x020000, 0xac6719e7, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bb_04.bin", 0x020000, 0xfd951c2c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bb_03.bin", 0x020000, 0x18d3c460, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "bb_07.bin", 0x010000, 0x411b94e8, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "bb_05.bin", 0x010000, 0x04ba6d19, 3 | BRF_GRA }, // 5 Characters + { "bb_06.bin", 0x010000, 0x7092e35b, 3 | BRF_GRA }, // 6 + + { "bloodb.bk", 0x100000, 0x1aa87ee6, 4 | BRF_GRA }, // 7 Tiles + + { "bloodb.obj", 0x100000, 0xd27c3952, 5 | BRF_GRA }, // 8 Sprites + + { "bb_08.bin", 0x020000, 0xdeb1b975, 6 | BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(bloodbrob) +STD_ROM_FN(bloodbrob) + +struct BurnDriver BurnDrvBloodbrob = { + "bloodbrob", "bloodbro", NULL, NULL, "1990", + "Blood Bros. (set 3)\0", NULL, "Tad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, bloodbrobRomInfo, bloodbrobRomName, NULL, NULL, BloodbroInputInfo, BloodbroDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// West Story + +static struct BurnRomInfo weststryRomDesc[] = { + { "ws13.bin", 0x20000, 0x158e302a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ws15.bin", 0x20000, 0x672e9027, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bb_04.bin", 0x20000, 0xfd951c2c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bb_03.bin", 0x20000, 0x18d3c460, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ws17.bin", 0x10000, 0xe00a8f09, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ws09.bin", 0x10000, 0xf05b2b3e, 3 | BRF_GRA }, // 5 Characters + { "ws11.bin", 0x10000, 0x2b10e3d2, 3 | BRF_GRA }, // 6 + { "ws10.bin", 0x10000, 0xefdf7c82, 3 | BRF_GRA }, // 7 + { "ws12.bin", 0x10000, 0xaf993578, 3 | BRF_GRA }, // 8 + + { "ws05.bin", 0x20000, 0x007c8dc0, 4 | BRF_GRA }, // 9 Tiles + { "ws07.bin", 0x20000, 0x0f0c8d9a, 4 | BRF_GRA }, // 10 + { "ws06.bin", 0x20000, 0x459d075e, 4 | BRF_GRA }, // 11 + { "ws08.bin", 0x20000, 0x4d6783b3, 4 | BRF_GRA }, // 12 + { "ws01.bin", 0x20000, 0x32bda4bc, 4 | BRF_GRA }, // 13 + { "ws03.bin", 0x20000, 0x046b51f8, 4 | BRF_GRA }, // 14 + { "ws02.bin", 0x20000, 0xed9d682e, 4 | BRF_GRA }, // 15 + { "ws04.bin", 0x20000, 0x75f082e5, 4 | BRF_GRA }, // 16 + + { "ws25.bin", 0x20000, 0x8092e8e9, 5 | BRF_GRA }, // 17 Sprites + { "ws26.bin", 0x20000, 0xf6a1f42c, 5 | BRF_GRA }, // 18 + { "ws23.bin", 0x20000, 0x43d58e24, 5 | BRF_GRA }, // 19 + { "ws24.bin", 0x20000, 0x20a867ea, 5 | BRF_GRA }, // 20 + { "ws21.bin", 0x20000, 0xe23d7296, 5 | BRF_GRA }, // 21 + { "ws22.bin", 0x20000, 0x7150a060, 5 | BRF_GRA }, // 22 + { "ws19.bin", 0x20000, 0xc5dd0a96, 5 | BRF_GRA }, // 23 + { "ws20.bin", 0x20000, 0xf1245c16, 5 | BRF_GRA }, // 24 + + { "bb_08.bin", 0x20000, 0xdeb1b975, 6 | BRF_SND }, // 25 Samples +}; + +STD_ROM_PICK(weststry) +STD_ROM_FN(weststry) + +struct BurnDriverD BurnDrvWeststry = { + "weststry", "bloodbro", NULL, NULL, "1991", + "West Story (bootleg of Blood Bros.)\0", NULL, "Datsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, weststryRomInfo, weststryRomName, NULL, NULL, WeststryInputInfo, WeststryDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// Sky Smasher + +static struct BurnRomInfo skysmashRomDesc[] = { + { "rom6", 0x020000, 0xe9c1d308, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "rom5", 0x020000, 0x867f9897, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rom8", 0x020000, 0xd3646728, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rom7", 0x020000, 0xd209db4d, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "rom2", 0x010000, 0x75b194cf, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "rom3", 0x010000, 0xfbb241be, 3 | BRF_GRA }, // 5 Characters + { "rom4", 0x010000, 0xad3cde81, 3 | BRF_GRA }, // 6 + + { "rom9", 0x100000, 0xb0a5eecf, 4 | BRF_GRA }, // 7 Tiles + + { "rom10", 0x080000, 0x1bbcda5d, 5 | BRF_GRA }, // 8 Sprites + + { "rom1", 0x020000, 0xe69986f6, 6 | BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(skysmash) +STD_ROM_FN(skysmash) + +struct BurnDriver BurnDrvSkysmash = { + "skysmash", NULL, NULL, NULL, "1990", + "Sky Smasher\0", NULL, "Nihon System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, skysmashRomInfo, skysmashRomName, NULL, NULL, SkysmashInputInfo, SkysmashDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_boogwing.cpp b/src/burn/drivers/misc_post90s/d_boogwing.cpp new file mode 100644 index 00000000..34cd19e1 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_boogwing.cpp @@ -0,0 +1,986 @@ +// FB Alpha Boogie Wing / Great Ragtime Show driver module +// Based on MAME driver by Bryan McPhail and David Haywood + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KCode; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvGfxROM5; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvPalBuf; +static UINT8 *DrvSprBuf; +static UINT8 *DrvSprBuf1; +static UINT8 *DrvProtRAM; +static UINT8 *DrvUnkRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT16 *tempdraw[2]; + +static INT32 DrvOkiBank; + +static struct BurnInputInfo BoogwingInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Boogwing) + +static struct BurnDIPInfo BoogwingDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Continue Coin" }, + {0x14, 0x01, 0x80, 0x80, "Normal Coin Credit" }, + {0x14, 0x01, 0x80, 0x00, "2 Start/1 Continue" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x03, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x08, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x04, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x15, 0x01, 0x10, 0x10, "Common" }, + {0x15, 0x01, 0x10, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 2, "Stage Reset" }, + {0x15, 0x01, 0x20, 0x20, "PoINT32 of Termination" }, + {0x15, 0x01, 0x20, 0x00, "Beginning of Stage" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Boogwing) + +void __fastcall boogwing_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x220000: + case 0x220001: + deco16_priority = data; + return; + + case 0x240000: + case 0x240001: + memcpy (DrvSprBuf , DrvSprRAM , 0x800); + return; + + case 0x244000: + case 0x244001: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x800); + return; + + case 0x24e150: + case 0x24e151: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + + case 0x282008: + case 0x282009: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + } + + if ((address & 0xffff800) == 0x24e000) { + DrvProtRAM[(address & 0x7ff) ^ 1] = data; + return; + } +} + +void __fastcall boogwing_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x260000, data) + deco16_write_control_word(1, address, 0x270000, data) + + switch (address) + { + case 0x220000: + deco16_priority = data; + return; + + case 0x240000: + memcpy (DrvSprBuf , DrvSprRAM , 0x800); + return; + + case 0x244000: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x800); + return; + + case 0x24e150: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + + case 0x282008: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + } + + if ((address & 0xffff800) == 0x24e000) { + *((UINT16*)(DrvProtRAM + (address & 0x7fe))) = data; + return; + } +} + +UINT8 __fastcall boogwing_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x24e6c0: + return DrvDips[1]; + + case 0x24e6c1: + return DrvDips[0]; + + case 0x24e138: + case 0x24e139: + return (DrvInputs[0] & 0x07) | (deco16_vblank & 0x08); + + case 0x24e344: + return DrvInputs[1] >> 8; + + case 0x24e345: + return DrvInputs[1] >> 0; + } + + return 0; +} + +UINT16 __fastcall boogwing_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x24e6c0: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x24e138: + return (DrvInputs[0] & 0x07) | (deco16_vblank & 0x08); + + case 0x24e344: + return DrvInputs[1]; + } + + return 0; +} + +static INT32 boogwing_bank_callback( const INT32 bank ) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static INT32 boogwing_bank_callback2( const INT32 bank ) +{ + INT32 offset = ((bank >> 4) & 0x7) * 0x1000; + if ((bank & 0xf) == 0xa) offset += 0x800; + + return offset; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + if ((data & 0x02) != (UINT32)(DrvOkiBank & 0x02)) + memcpy (DrvSndROM1, DrvSndROM1 + 0x40000 + ((data & 0x02) >> 1) * 0x40000, 0x40000); + + if ((data & 0x01) != (UINT32)(DrvOkiBank & 0x01)) + memcpy (DrvSndROM0, DrvSndROM0 + 0x40000 + ((data & 0x01) >> 0) * 0x40000, 0x40000); + + DrvOkiBank = data; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + deco16Reset(); + + DrvOkiBank = -1; + DrvYM2151WritePort(0, 0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + Drv68KCode = Next; Next += 0x100000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROM5 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x400000; + DrvGfxROM3 = Next; Next += 0x800000; + DrvGfxROM4 = Next; Next += 0x800000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x0c0000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + tempdraw[0] = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + tempdraw[1] = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvSprRAM = Next; Next += 0x000800; + DrvSprRAM1 = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvSprBuf1 = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x002000; + DrvPalBuf = Next; Next += 0x002000; + + DrvProtRAM = Next; Next += 0x000800; + DrvUnkRAM = Next; Next += 0x000400; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + + +static INT32 DrvGfxDecode5bpp() +{ + // actually 5 bits / pixel, but fba doesn't seem to like that... + INT32 Plane[6] = { 0x1800000, 0x1000000, 0x800008, 0x800000, 0x000008, 0x000000 }; + INT32 XOffs[16] = { 32*8+0, 32*8+1, 32*8+2, 32*8+3, 32*8+4, 32*8+5, 32*8+6, 32*8+7, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp + 0x000000, DrvGfxROM1, 0x200000); + memset (tmp + 0x200000, 0, 0x200000); + memcpy (tmp + 0x200000, DrvGfxROM5, 0x100000); + + GfxDecode(0x4000, 6, 16, 16, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + for (INT32 i = 0; i < 0x400000; i++) DrvGfxROM1[i] &= 0x1f; + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 3, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM5 + 0x000000, 9, 2)) return 1; // skip a byte! + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 15, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 16, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 17, 1)) return 1; + + deco56_decrypt_gfx(DrvGfxROM0, 0x020000); + deco56_decrypt_gfx(DrvGfxROM1, 0x300000); + deco56_decrypt_gfx(DrvGfxROM2, 0x200000); + deco56_remap_gfx(DrvGfxROM5, 0x100000); + deco102_decrypt_cpu(Drv68KROM, Drv68KCode, 0x100000, 0x42ba, 0x00, 0x18); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x200000, 0); + deco16_sprite_decode(DrvGfxROM3, 0x400000); + deco16_sprite_decode(DrvGfxROM4, 0x400000); + + DrvGfxDecode5bpp(); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x200000 * 2, DrvGfxROM2, 0x200000 * 2); + deco16_set_color_base(1, 0x100); + deco16_set_color_base(2, 0x300); + deco16_set_color_base(3, 0x400); + deco16_set_global_offsets(0, 8); + deco16_set_transparency_mask(1, 0x1f); + deco16_set_color_mask(2, 0x1f); + deco16_set_color_mask(3, 0x1f); + deco16_set_bank_callback(1, boogwing_bank_callback); + deco16_set_bank_callback(2, boogwing_bank_callback2); + deco16_set_bank_callback(3, boogwing_bank_callback2); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_READ); + SekMapMemory(Drv68KCode, 0x000000, 0x0fffff, SM_FETCH); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x242000, 0x2427ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x246000, 0x2467ff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x264000, 0x265fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x266000, 0x267fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x268000, 0x268fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x26a000, 0x26afff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x274000, 0x275fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x276000, 0x277fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x278000, 0x278fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x27a000, 0x27afff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x284000, 0x285fff, SM_RAM); + SekSetWriteWordHandler(0, boogwing_main_write_word); + SekSetWriteByteHandler(0, boogwing_main_write_byte); + SekSetReadWordHandler(0, boogwing_main_read_word); + SekSetReadByteHandler(0, boogwing_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 80.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + MSM6295Init(0, 1006875 / 132, 140.0, 1); + MSM6295Init(1, 2013750 / 132, 30.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + MSM6295Exit(0); + MSM6295Exit(1); + BurnYM2151Exit(); + + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 coloff, INT32 gfx_region, INT32 bpp) +{ + if (bpp != (nBurnBpp & 4)) return; + + UINT16 *spriteram_base = (UINT16*)ram; + + INT32 colmask = (gfx_region == 4) ? 0x0f : 0x1f; + + INT32 sflipscreen = !*flipscreen; + INT32 priority = deco16_priority; + + for (INT32 offs = 0x400 - 4; offs >= 0; offs -= 4) + { + INT32 inc, mult, pri = 0, spri = 0, alpha = 0xff; + + INT32 sprite = spriteram_base[offs + 1]; + + if (!sprite) continue; + + INT32 y = spriteram_base[offs]; + + if ((y & 0x1000) && (nCurrentFrame & 1)) + continue; + + INT32 x = spriteram_base[offs + 2]; + INT32 colour = (x >> 9) & colmask; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + if (gfx_region == 4) + { + if ((spriteram_base[offs + 2] & 0xc000) == 0xc000) + spri = 4; + else if ((spriteram_base[offs + 2] & 0xc000)) + spri = 16; + else + spri = 64; + + if (spriteram_base[offs + 2] & 0x2000) alpha = 0x80; + + if (priority == 0x2) + { + if (spriteram_base[offs + 2] & 0x8000) alpha = 0x80; + + if ((spriteram_base[offs + 2] & 0xc000) == 0xc000) + pri = 4; + else if ((spriteram_base[offs + 2] & 0xc000) == 0x8000) + pri = 16; + else + pri = 64; + } + else + { + if ((spriteram_base[offs + 2] & 0x8000) == 0x8000) + pri = 16; + else + pri = 64; + } + } + else + { + if (spriteram_base[offs + 2] & 0x8000) + spri = 8; + else + spri = 32; + + if (priority == 0x1) + { + if ((spriteram_base[offs + 2] & 0xc000)) + pri = 16; + else + pri = 64; + } + else + { + if ((spriteram_base[offs + 2] & 0xc000) == 0xc000) + pri = 4; + else if ((spriteram_base[offs + 2] & 0xc000) == 0x8000) + pri = 16; + else + pri = 64; + } + } + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + y = 240 - y; + x = 304 - x; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (sflipscreen) + { + y = 240 - y; + x = 304 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else + mult = -16; + + while (multi >= 0) + { + if (!bpp) { + deco16_draw_prio_sprite(pTransDraw, gfx, sprite - multi * inc, (colour << 4) + coloff, x, y + mult * multi, fx, fy, pri, spri); + } else { + deco16_draw_alphaprio_sprite(DrvPalette, gfx, sprite - multi * inc, (colour << 4) + coloff, x, y + mult * multi, fx, fy, pri, spri, alpha); + } + + multi--; + } + } +} + +static void draw_combined_playfield(INT32 color, INT32 priority) // opaque +{ + UINT16 *src0 = tempdraw[0]; + UINT16 *src1 = tempdraw[1]; + UINT16 *dest = pTransDraw; + UINT8 *prio = deco16_prio_map; + + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < nScreenWidth; x++) { + dest[x] = color | (src0[x] & 0x0f) | ((src1[x] & 0x0f) << 4); + prio[x] = priority; + } + src0 += nScreenWidth; + src1 += nScreenWidth; + dest += nScreenWidth; + prio += 512; + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalBuf); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x400; + } + + if ((deco16_priority & 0x07) == 0x05) { + UINT8 *tptr = deco16_pf_rowscroll[3]; + deco16_pf_rowscroll[3] = deco16_pf_rowscroll[2]; + + deco16_draw_layer(2, tempdraw[0], 0x10000); + deco16_draw_layer(3, tempdraw[1], 0x10000); + + deco16_pf_rowscroll[3] = tptr; + } + + deco16_clear_prio_map(); + + INT32 bpp0 = (deco16_get_tilemap_size(0) == 1) ? DECO16_LAYER_5BITSPERPIXEL : DECO16_LAYER_4BITSPERPIXEL; + INT32 bpp1 = (deco16_get_tilemap_size(1) == 1) ? DECO16_LAYER_5BITSPERPIXEL : DECO16_LAYER_4BITSPERPIXEL; + + switch (deco16_priority & 0x07) + { + case 0x01: + case 0x02: + if (nSpriteEnable & 4) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x00) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x08) | bpp1); + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x20)); + break; + + case 0x03: + if (nSpriteEnable & 4) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x00) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x08) | bpp1); + // should use pf2 to add shadows... + break; + + case 0x05: + if (nSpriteEnable & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x00) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable &16) draw_combined_playfield(0x300, DECO16_LAYER_PRIORITY(0x20)); + break; + + case 0x00: + case 0x04: + case 0x06: + case 0x07: + if (nSpriteEnable & 4) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x00) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x08)); + if (nSpriteEnable & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x20) | bpp1); + break; + } + + draw_sprites(DrvSprBuf , DrvGfxROM3, 0x500, 3, 0); + draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4, 0); + + if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, DECO16_LAYER_PRIORITY(0xff) | bpp0); + + BurnTransferCopy(DrvPalette); + + draw_sprites(DrvSprBuf , DrvGfxROM3, 0x500, 3, 4); + draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4, 4); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 248) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(DrvOkiBank); + + INT32 bank = DrvOkiBank; + DrvOkiBank = -1; + DrvYM2151WritePort(0, bank); + } + + return 0; +} + + +// Boogie Wings (Euro v1.5, 92.12.07) + +static struct BurnRomInfo boogwingRomDesc[] = { + { "kn_00-2.2b", 0x040000, 0xe38892b9, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "kn_02-2.2e", 0x040000, 0x8426efef, 1 | BRF_PRG | BRF_ESS }, // 1 + { "kn_01-2.4b", 0x040000, 0x3ad4b54c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "kn_03-2.4e", 0x040000, 0x10b61f4a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "km06.18p", 0x010000, 0x3e8bc4e1, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "km05.9e", 0x010000, 0xd10aef95, 3 | BRF_GRA }, // 5 Characters + { "km04.8e", 0x010000, 0x329323a8, 3 | BRF_GRA }, // 6 + + { "mbd-01.9b", 0x100000, 0xd7de4f4b, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mbd-00.8b", 0x100000, 0xadb20ba9, 4 | BRF_GRA }, // 8 + { "mbd-02.10e", 0x080000, 0xb25aa721, 8 | BRF_GRA }, // 9 + + { "mbd-03.13b", 0x100000, 0xcf798f2c, 5 | BRF_GRA }, // 10 Background Tiles + { "mbd-04.14b", 0x100000, 0xd9764d0b, 5 | BRF_GRA }, // 11 + + { "mbd-05.16b", 0x200000, 0x1768c66a, 6 | BRF_GRA }, // 12 Sprite Bank A + { "mbd-06.17b", 0x200000, 0x7750847a, 6 | BRF_GRA }, // 13 + + { "mbd-07.18b", 0x200000, 0x241faac1, 7 | BRF_GRA }, // 14 Sprite Bank B + { "mbd-08.19b", 0x200000, 0xf13b1e56, 7 | BRF_GRA }, // 15 + + { "mbd-10.17p", 0x080000, 0xf159f76a, 9 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mbd-09.16p", 0x080000, 0xf44f2f87, 10 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "kj-00.15n", 0x000400, 0xadd4d50b, 11 | BRF_OPT }, // 18 Unknown PROMs +}; + +STD_ROM_PICK(boogwing) +STD_ROM_FN(boogwing) + +struct BurnDriver BurnDrvBoogwing = { + "boogwing", NULL, NULL, NULL, "1992", + "Boogie Wings (Euro v1.5, 92.12.07)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, boogwingRomInfo, boogwingRomName, NULL, NULL, BoogwingInputInfo, BoogwingDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Boogie Wings (Asia v1.5, 92.12.07) + +static struct BurnRomInfo boogwingaRomDesc[] = { + { "km_00-2.2b", 0x040000, 0x71ab71c6, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "km_02-2.2e", 0x040000, 0xe90f07f9, 1 | BRF_PRG | BRF_ESS }, // 1 + { "km_01-2.4b", 0x040000, 0x7fdce2d3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "km_03-2.4e", 0x040000, 0x0b582de3, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "km06.18p", 0x010000, 0x3e8bc4e1, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "km05.9e", 0x010000, 0xd10aef95, 3 | BRF_GRA }, // 5 Characters + { "km04.8e", 0x010000, 0x329323a8, 3 | BRF_GRA }, // 6 + + { "mbd-01.9b", 0x100000, 0xd7de4f4b, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mbd-00.8b", 0x100000, 0xadb20ba9, 4 | BRF_GRA }, // 8 + { "mbd-02.10e", 0x080000, 0xb25aa721, 4 | BRF_GRA }, // 9 + + { "mbd-03.13b", 0x100000, 0xcf798f2c, 5 | BRF_GRA }, // 10 Background Tiles + { "mbd-04.14b", 0x100000, 0xd9764d0b, 5 | BRF_GRA }, // 11 + + { "mbd-05.16b", 0x200000, 0x1768c66a, 6 | BRF_GRA }, // 12 Sprite Bank A + { "mbd-06.17b", 0x200000, 0x7750847a, 6 | BRF_GRA }, // 13 + + { "mbd-07.18b", 0x200000, 0x241faac1, 7 | BRF_GRA }, // 14 Sprite Bank B + { "mbd-08.19b", 0x200000, 0xf13b1e56, 7 | BRF_GRA }, // 15 + + { "mbd-10.17p", 0x080000, 0xf159f76a, 8 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mbd-09.16p", 0x080000, 0xf44f2f87, 9 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "kj-00.15n", 0x000400, 0xadd4d50b, 10 | BRF_OPT }, // 18 Unknown PROMs +}; + +STD_ROM_PICK(boogwinga) +STD_ROM_FN(boogwinga) + +struct BurnDriver BurnDrvBoogwinga = { + "boogwinga", "boogwing", NULL, NULL, "1992", + "Boogie Wings (Asia v1.5, 92.12.07)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, boogwingaRomInfo, boogwingaRomName, NULL, NULL, BoogwingInputInfo, BoogwingDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// The Great Ragtime Show (Japan v1.5, 92.12.07) + +static struct BurnRomInfo ragtimeRomDesc[] = { + { "kh_00-2.2b", 0x040000, 0x553e179f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "kh_02-2.2e", 0x040000, 0x6c759ec0, 1 | BRF_PRG | BRF_ESS }, // 1 + { "kh_01-2.4b", 0x040000, 0x12dfee70, 1 | BRF_PRG | BRF_ESS }, // 2 + { "kh_03-2.4e", 0x040000, 0x076fea18, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "km06.18p", 0x010000, 0x3e8bc4e1, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "km05.9e", 0x010000, 0xd10aef95, 3 | BRF_GRA }, // 5 Characters + { "km04.8e", 0x010000, 0x329323a8, 3 | BRF_GRA }, // 6 + + { "mbd-01.9b", 0x100000, 0xd7de4f4b, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mbd-00.8b", 0x100000, 0xadb20ba9, 4 | BRF_GRA }, // 8 + { "mbd-02.10e", 0x080000, 0xb25aa721, 8 | BRF_GRA }, // 9 + + { "mbd-03.13b", 0x100000, 0xcf798f2c, 5 | BRF_GRA }, // 10 Background Tiles + { "mbd-04.14b", 0x100000, 0xd9764d0b, 5 | BRF_GRA }, // 11 + + { "mbd-05.16b", 0x200000, 0x1768c66a, 6 | BRF_GRA }, // 12 Sprite Bank A + { "mbd-06.17b", 0x200000, 0x7750847a, 6 | BRF_GRA }, // 13 + + { "mbd-07.18b", 0x200000, 0x241faac1, 7 | BRF_GRA }, // 14 Sprite Bank B + { "mbd-08.19b", 0x200000, 0xf13b1e56, 7 | BRF_GRA }, // 15 + + { "mbd-10.17p", 0x080000, 0xf159f76a, 9 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mbd-09.16p", 0x080000, 0xf44f2f87, 10 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "kj-00.15n", 0x000400, 0xadd4d50b, 11 | BRF_OPT }, // 18 Unknown PROMs +}; + +STD_ROM_PICK(ragtime) +STD_ROM_FN(ragtime) + +struct BurnDriver BurnDrvRagtime = { + "ragtime", "boogwing", NULL, NULL, "1992", + "The Great Ragtime Show (Japan v1.5, 92.12.07)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, ragtimeRomInfo, ragtimeRomName, NULL, NULL, BoogwingInputInfo, BoogwingDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// The Great Ragtime Show (Japan v1.3, 92.11.26) + +static struct BurnRomInfo ragtimeaRomDesc[] = { + { "kh_00-1.2b", 0x040000, 0x88f0155a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "kh_02-1.2e", 0x040000, 0x8811b41b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "kh_01-1.4b", 0x040000, 0x4dab63ad, 1 | BRF_PRG | BRF_ESS }, // 2 + { "kh_03-1.4e", 0x040000, 0x8a4cbb18, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "km06.18p", 0x010000, 0x3e8bc4e1, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "km05.9e", 0x010000, 0xd10aef95, 3 | BRF_GRA }, // 5 Characters + { "km04.8e", 0x010000, 0x329323a8, 3 | BRF_GRA }, // 6 + + { "mbd-01.9b", 0x100000, 0xd7de4f4b, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mbd-00.8b", 0x100000, 0xadb20ba9, 4 | BRF_GRA }, // 8 + { "mbd-02.10e", 0x080000, 0xb25aa721, 8 | BRF_GRA }, // 9 + + { "mbd-03.13b", 0x100000, 0xcf798f2c, 5 | BRF_GRA }, // 10 Background Tiles + { "mbd-04.14b", 0x100000, 0xd9764d0b, 5 | BRF_GRA }, // 11 + + { "mbd-05.16b", 0x200000, 0x1768c66a, 6 | BRF_GRA }, // 12 Sprite Bank A + { "mbd-06.17b", 0x200000, 0x7750847a, 6 | BRF_GRA }, // 13 + + { "mbd-07.18b", 0x200000, 0x241faac1, 7 | BRF_GRA }, // 14 Sprite Bank B + { "mbd-08.19b", 0x200000, 0xf13b1e56, 7 | BRF_GRA }, // 15 + + { "mbd-10.17p", 0x080000, 0xf159f76a, 9 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mbd-09.16p", 0x080000, 0xf44f2f87, 10 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "kj-00.15n", 0x000400, 0xadd4d50b, 11 | BRF_OPT }, // 18 Unknown PROMs +}; + +STD_ROM_PICK(ragtimea) +STD_ROM_FN(ragtimea) + +struct BurnDriver BurnDrvRagtimea = { + "ragtimea", "boogwing", NULL, NULL, "1992", + "The Great Ragtime Show (Japan v1.3, 92.11.26)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, ragtimeaRomInfo, ragtimeaRomName, NULL, NULL, BoogwingInputInfo, BoogwingDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_cbuster.cpp b/src/burn/drivers/misc_post90s/d_cbuster.cpp new file mode 100644 index 00000000..71195bdb --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_cbuster.cpp @@ -0,0 +1,880 @@ +// FB Alpha Crude Buster / Two Crude drive module +// Based on MAME driver by by Bryan McPhail + +#include "tiles_generic.h" +#include "bitswap.h" +#include "deco16ic.h" +#include "burn_ym2203.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM0; +static UINT8 *DrvPalRAM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static INT32 prot_data = 0; + +static struct BurnInputInfo CbusterInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Cbuster) + +static struct BurnDIPInfo CbusterDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x14, 0x01, 0x03, 0x01, "1" }, + {0x14, 0x01, 0x03, 0x00, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + {0x14, 0x01, 0x0c, 0x04, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "No" }, + {0x14, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Cbuster) + +void __fastcall cbuster_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0xb5000, data) + deco16_write_control_word(1, address, 0xb6000, data) + + switch (address) + { + case 0xbc000: + case 0xbc001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0xbc002: + case 0xbc003: + *soundlatch = data; + //cpu_set_input_line(state->audiocpu, 0, HOLD_LINE); + return; + } +} + +void __fastcall cbuster_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xbc000: + case 0xbc001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0xbc002: + case 0xbc003: + *soundlatch = data; + //cpu_set_input_line(state->audiocpu, 0, HOLD_LINE); + return; + + case 0xbc004: + if (data == 0x9a) prot_data = 0; + if (data == 0x02) prot_data = 0x63 << 8; + if (data == 0x00) { prot_data = 0x0e; deco16_priority = 0; } + return; + + case 0xbc005: + if (data == 0xaa) prot_data = 0x74; + if (data == 0x9a) prot_data = 0x0e; + if (data == 0x55) prot_data = 0x1e; + if (data == 0x0e) { prot_data = 0x0e; deco16_priority = 0; } + if (data == 0x00) { prot_data = 0x0e; deco16_priority = 0; } + if (data == 0xf1) { prot_data = 0x36; deco16_priority = 1; } + if (data == 0x80) { prot_data = 0x2e; deco16_priority = 1; } + if (data == 0x40) { prot_data = 0x1e; deco16_priority = 1; } + if (data == 0xc0) { prot_data = 0x3e; deco16_priority = 0; } + if (data == 0xff) { prot_data = 0x76; deco16_priority = 1; } + return; + } +} + +UINT16 __fastcall cbuster_main_read_word(UINT32 address) +{ + switch (address) + { + case 0xbc000: + case 0xbc001: + return DrvInputs[0]; + + case 0xbc002: + case 0xbc003: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0xbc004: + bprintf (0, _T("%5.5x, rw\n"), address); + return prot_data; + + case 0xbc006: + case 0xbc007: + return (DrvInputs[1] & 0xf7) | (deco16_vblank & 0x08); + } + + return 0; +} + +UINT8 __fastcall cbuster_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0xbc000: + return DrvInputs[0] >> 8; + + case 0xbc001: + return DrvInputs[0]; + + case 0xbc002: + return DrvDips[1]; + + case 0xbc003: + return DrvDips[0]; + + case 0xbc004: + bprintf (0, _T("%5.5x, rb\n"), address); + return prot_data >> 8; + case 0xbc005: + bprintf (0, _T("%5.5x, rb\n"), address); + return prot_data; + + case 0xbc006: + case 0xbc007: + return (DrvInputs[1] & 0xf7) | (deco16_vblank & 0x08); + } + + return 0; +} + +static INT32 cbuster_bank_callback(const INT32 bank) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return 0 * nSoundRate; //(INT64)HucTotalCycles() * nSoundRate / 8055000; +} + +static double DrvGetTime() +{ + return 0; //(double)HucTotalCycles() / 8055000.0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + BurnYM2151Reset(); + BurnYM2203Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + deco16Reset(); + + return 0; +} + +static INT32 DrvGfxDecode(UINT8 *gfx, INT32 len, INT32 type) +{ + INT32 Plane[4] = { 24,16,8,0 }; + INT32 XOffs[16] = { 512,513,514,515,516,517,518,519, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32,10*32,11*32,12*32,13*32,14*32,15*32}; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, gfx, len); + + if (type == 1) { + GfxDecode((len * 2) / 0x040, 4, 8, 8, Plane, XOffs + 8, YOffs, 0x100, tmp, gfx); + } else { + GfxDecode((len * 2) / 0x100, 4, 16, 16, Plane, XOffs + 0, YOffs, 0x400, tmp, gfx); + } + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x040000; + DrvSndROM1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvPalRAM0 = Next; Next += 0x001000; + DrvPalRAM1 = Next; Next += 0x001000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvROMRearrange() +{ + UINT8 *RAM = Drv68KROM; + UINT8 *PTR; + + for (INT32 i = 0; i < 0x80000; i += 2) + { + INT32 h = i + 1, l = i + 0; + RAM[h] = BITSWAP08(RAM[h], 4, 6, 7, 5, 3, 2, 1, 0); + RAM[l] = BITSWAP08(RAM[l], 7, 1, 5, 4, 6, 2, 3, 0); + +#if 0 + RAM[h] = (RAM[h] & 0xcf) | ((RAM[h] & 0x10) << 1) | ((RAM[h] & 0x20) >> 1); + RAM[h] = (RAM[h] & 0x5f) | ((RAM[h] & 0x20) << 2) | ((RAM[h] & 0x80) >> 2); + + RAM[l] = (RAM[l] & 0xbd) | ((RAM[l] & 0x2) << 5) | ((RAM[l] & 0x40) >> 5); + RAM[l] = (RAM[l] & 0xf5) | ((RAM[l] & 0x2) << 2) | ((RAM[l] & 0x8) >> 2); +#endif + } + + RAM = DrvGfxROM3 + 0x080000; + PTR = DrvGfxROM3 + 0x140000; + for (INT32 i = 0; i < 0x20000; i += 64) + { + for (INT32 j = 0; j < 16; j++) + { + RAM[i + 0x00000 + j * 2] = PTR[i / 2 + 0x00000 + j]; + RAM[i + 0x00020 + j * 2] = PTR[i / 2 + 0x00010 + j]; + RAM[i + 0x00001 + j * 2] = PTR[i / 2 + 0x10000 + j]; + RAM[i + 0x00021 + j * 2] = PTR[i / 2 + 0x10010 + j]; + RAM[i + 0xa0000 + j * 2] = PTR[i / 2 + 0x20000 + j]; + RAM[i + 0xa0020 + j * 2] = PTR[i / 2 + 0x20010 + j]; + RAM[i + 0xa0001 + j * 2] = PTR[i / 2 + 0x30000 + j]; + RAM[i + 0xa0021 + j * 2] = PTR[i / 2 + 0x30010 + j]; + } + } +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 7, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x0a0000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x140000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x150000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x160000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x170000, 14, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 15, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 16, 1)) return 1; + + DrvROMRearrange(); + + memcpy (DrvGfxROM0, DrvGfxROM1, 0x100000); + + DrvGfxDecode(DrvGfxROM0, 0x100000, 1); + DrvGfxDecode(DrvGfxROM1, 0x100000, 0); + DrvGfxDecode(DrvGfxROM2, 0x080000, 0); + + deco16_tile_decode(DrvGfxROM3, DrvGfxROM3, 0x0a0000 * 2, 0); + } + + deco16Init(0, 0, 1); + deco16_set_global_offsets(0, 8); + deco16_set_graphics(DrvGfxROM0, 0x200000, DrvGfxROM1, 0x200000, DrvGfxROM2, 0x100000); + deco16_set_bank_callback(0, cbuster_bank_callback); + deco16_set_bank_callback(1, cbuster_bank_callback); + deco16_set_bank_callback(2, cbuster_bank_callback); + deco16_set_bank_callback(3, cbuster_bank_callback); + deco16_set_color_base(0, 0x000); + deco16_set_color_base(1, 0x200); + deco16_set_color_base(2, 0x300); + deco16_set_color_base(3, 0x400); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x083fff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x0a0000, 0x0a1fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x0a2000, 0x0a2fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x0a4000, 0x0a47ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x0a6000, 0x0a67ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x0a8000, 0x0a8fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x0aa000, 0x0abfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x0ac000, 0x0ac7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x0ae000, 0x0ae7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x0b0000, 0x0b07ff, SM_RAM); + SekMapMemory(DrvPalRAM0, 0x0b8000, 0x0b8fff, SM_RAM); + SekMapMemory(DrvPalRAM1, 0x0b9000, 0x0b9fff, SM_RAM); + SekSetWriteWordHandler(0, cbuster_main_write_word); + SekSetWriteByteHandler(0, cbuster_main_write_byte); + SekSetReadWordHandler(0, cbuster_main_read_word); + SekSetReadByteHandler(0, cbuster_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(8055000); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1023924 / 132, 75.0, 1); + MSM6295Init(1, 2047848 / 132, 60.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + BurnYM2151Exit(); + BurnYM2203Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + SekExit(); +// huc6280 + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT16 *p0 = (UINT16*)DrvPalRAM0; + UINT16 *p1 = (UINT16*)DrvPalRAM1; + + for (INT32 i = 0; i < BurnDrvGetPaletteEntries(); i++) { + INT32 r = ((p0[i] & 0xff) * 175) / 100; + INT32 g = ((p0[i] >> 8 ) * 175) / 100; + INT32 b = ((p1[i] & 0xff) * 175) / 100; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites(INT32 pri) +{ + UINT16 *buffered_spriteram = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 x, y, sprite, colour, multi, fx, fy, inc, flash, mult; + + sprite = buffered_spriteram[offs + 1] & 0x7fff; + if (!sprite) + continue; + + y = buffered_spriteram[offs]; + x = buffered_spriteram[offs + 2]; + + if ((y & 0x8000) && pri == 1) + continue; + if (!(y & 0x8000) && pri == 0) + continue; + + colour = (x >> 9) & 0xf; + if (x & 0x2000) + colour += 64; + colour += 0x10; + + flash = y & 0x1000; + if (flash && (nCurrentFrame & 1)) + continue; + + fx = y & 0x2000; + fy = y & 0x4000; + multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 256) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + if (x > 256) continue; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y = 240 - y; + x = 240 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else mult = -16; + + while (multi >= 0) + { + INT32 sy = (y + mult * multi) - 8; + INT32 c = sprite - multi * inc; + + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, x, sy, colour, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, x, sy, colour, 4, 0, 0, DrvGfxROM3); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, x, sy, colour, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, x, sy, colour, 4, 0, 0, DrvGfxROM3); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + DrvPaletteRecalc(); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + if (nBurnLayer & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE); + + draw_sprites(0); + + if (deco16_priority) { + if (nBurnLayer & 2) deco16_draw_layer(1, pTransDraw, 0); + if (nBurnLayer & 4) deco16_draw_layer(2, pTransDraw, 0); + } else { + if (nBurnLayer & 2) deco16_draw_layer(2, pTransDraw, 0); + if (nBurnLayer & 4) deco16_draw_layer(1, pTransDraw, 0); + } + + draw_sprites(1); + + if (nBurnLayer & 8) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 12000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); +// HucOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); +// nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + +// HucClose(); + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2151Scan(nAction); + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + } + + return 0; +} + + +// Crude Buster (World FX version) + +static struct BurnRomInfo cbusterRomDesc[] = { + { "fx01.rom", 0x20000, 0xddae6d83, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fx00.rom", 0x20000, 0x5bc2c0de, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fx03.rom", 0x20000, 0xc3d65bf9, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fx02.rom", 0x20000, 0xb875266b, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fu11-.rom", 0x10000, 0x65f20f10, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "mab-00", 0x80000, 0x660eaabd, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + { "fu05-.rom", 0x10000, 0x8134d412, 3 | BRF_GRA }, // 6 + { "fu06-.rom", 0x10000, 0x2f914a45, 3 | BRF_GRA }, // 7 + + { "mab-01", 0x80000, 0x1080d619, 4 | BRF_GRA }, // 8 Background Tiles + + { "mab-02", 0x80000, 0x58b7231d, 5 | BRF_GRA }, // 9 Sprites + { "mab-03", 0x80000, 0x76053b9d, 5 | BRF_GRA }, // 10 + { "fu07-.rom", 0x10000, 0xca8d0bb3, 5 | BRF_GRA }, // 11 + { "fu08-.rom", 0x10000, 0xc6afc5c8, 5 | BRF_GRA }, // 12 + { "fu09-.rom", 0x10000, 0x526809ca, 5 | BRF_GRA }, // 13 + { "fu10-.rom", 0x10000, 0x6be6d50e, 5 | BRF_GRA }, // 14 + + { "fu12-.rom", 0x20000, 0x2d1d65f2, 6 | BRF_SND }, // 15 OKI M6295 Samples 0 + + { "fu13-.rom", 0x20000, 0xb8525622, 7 | BRF_SND }, // 16 OKI M6295 Samples 1 + + { "mb7114h.18e", 0x00100, 0x3645b70f, 8 | BRF_OPT }, // 17 Unused PROMs +}; + +STD_ROM_PICK(cbuster) +STD_ROM_FN(cbuster) + +struct BurnDriver BurnDrvCbuster = { + "cbuster", NULL, NULL, NULL, "1990", + "Crude Buster (World FX version)\0","No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, cbusterRomInfo, cbusterRomName, NULL, NULL, CbusterInputInfo, CbusterDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Crude Buster (World FU version) + +static struct BurnRomInfo cbusterwRomDesc[] = { + { "fu01-.rom", 0x20000, 0x0203e0f8, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fu00-.rom", 0x20000, 0x9c58626d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fu03-.rom", 0x20000, 0xdef46956, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fu02-.rom", 0x20000, 0x649c3338, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fu11-.rom", 0x10000, 0x65f20f10, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "mab-00", 0x80000, 0x660eaabd, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + { "fu05-.rom", 0x10000, 0x8134d412, 3 | BRF_GRA }, // 6 + { "fu06-.rom", 0x10000, 0x2f914a45, 3 | BRF_GRA }, // 7 + + { "mab-01", 0x80000, 0x1080d619, 4 | BRF_GRA }, // 8 Background Tiles + + { "mab-02", 0x80000, 0x58b7231d, 5 | BRF_GRA }, // 9 Sprites + { "mab-03", 0x80000, 0x76053b9d, 5 | BRF_GRA }, // 10 + { "fu07-.rom", 0x10000, 0xca8d0bb3, 5 | BRF_GRA }, // 11 + { "fu08-.rom", 0x10000, 0xc6afc5c8, 5 | BRF_GRA }, // 12 + { "fu09-.rom", 0x10000, 0x526809ca, 5 | BRF_GRA }, // 13 + { "fu10-.rom", 0x10000, 0x6be6d50e, 5 | BRF_GRA }, // 14 + + { "fu12-.rom", 0x20000, 0x2d1d65f2, 6 | BRF_SND }, // 15 OKI M6295 Samples 0 + + { "fu13-.rom", 0x20000, 0xb8525622, 7 | BRF_SND }, // 16 OKI M6295 Samples 1 + + { "mb7114h.18e", 0x00100, 0x3645b70f, 8 | BRF_OPT }, // 17 Unused PROMs +}; + +STD_ROM_PICK(cbusterw) +STD_ROM_FN(cbusterw) + +struct BurnDriver BurnDrvCbusterw = { + "cbusterw", "cbuster", NULL, NULL, "1990", + "Crude Buster (World FU version)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, cbusterwRomInfo, cbusterwRomName, NULL, NULL, CbusterInputInfo, CbusterDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Crude Buster (Japan) + +static struct BurnRomInfo cbusterjRomDesc[] = { + { "fr01-1", 0x20000, 0xaf3c014f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fr00-1", 0x20000, 0xf666ad52, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fr03", 0x20000, 0x02c06118, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fr02", 0x20000, 0xb6c34332, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fu11-.rom", 0x10000, 0x65f20f10, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "mab-00", 0x80000, 0x660eaabd, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + { "fu05-.rom", 0x10000, 0x8134d412, 3 | BRF_GRA }, // 6 + { "fu06-.rom", 0x10000, 0x2f914a45, 3 | BRF_GRA }, // 7 + + { "mab-01", 0x80000, 0x1080d619, 4 | BRF_GRA }, // 8 Background Tiles + + { "mab-02", 0x80000, 0x58b7231d, 5 | BRF_GRA }, // 9 Sprites + { "mab-03", 0x80000, 0x76053b9d, 5 | BRF_GRA }, // 10 + { "fr07", 0x10000, 0x52c85318, 5 | BRF_GRA }, // 11 + { "fr08", 0x10000, 0xea25fbac, 5 | BRF_GRA }, // 12 + { "fr09", 0x10000, 0xf8363424, 5 | BRF_GRA }, // 13 + { "fr10", 0x10000, 0x241d5760, 5 | BRF_GRA }, // 14 + + { "fu12-.rom", 0x20000, 0x2d1d65f2, 6 | BRF_SND }, // 15 OKI M6295 Samples 0 + + { "fu13-.rom", 0x20000, 0xb8525622, 7 | BRF_SND }, // 16 OKI M6295 Samples 1 + + { "mb7114h.18e", 0x00100, 0x3645b70f, 8 | BRF_OPT }, // 17 Unused PROMs +}; + +STD_ROM_PICK(cbusterj) +STD_ROM_FN(cbusterj) + +struct BurnDriver BurnDrvCbusterj = { + "cbusterj", "cbuster", NULL, NULL, "1990", + "Crude Buster (Japan)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, cbusterjRomInfo, cbusterjRomName, NULL, NULL, CbusterInputInfo, CbusterDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Two Crude (US) + +static struct BurnRomInfo twocrudeRomDesc[] = { + { "ft01", 0x20000, 0x08e96489, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ft00", 0x20000, 0x6765c445, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ft03", 0x20000, 0x28002c99, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ft02", 0x20000, 0x37ea0626, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fu11-.rom", 0x10000, 0x65f20f10, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "mab-00", 0x80000, 0x660eaabd, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + { "fu05-.rom", 0x10000, 0x8134d412, 3 | BRF_GRA }, // 6 + { "fu06-.rom", 0x10000, 0x2f914a45, 3 | BRF_GRA }, // 7 + + { "mab-01", 0x80000, 0x1080d619, 4 | BRF_GRA }, // 8 Background Tiles + + { "mab-02", 0x80000, 0x58b7231d, 5 | BRF_GRA }, // 9 Sprites + { "mab-03", 0x80000, 0x76053b9d, 5 | BRF_GRA }, // 10 + { "ft07", 0x10000, 0xe3465c25, 5 | BRF_GRA }, // 11 + { "ft08", 0x10000, 0xc7f1d565, 5 | BRF_GRA }, // 12 + { "ft09", 0x10000, 0x6e3657b9, 5 | BRF_GRA }, // 13 + { "ft10", 0x10000, 0xcdb83560, 5 | BRF_GRA }, // 14 + + { "fu12-.rom", 0x20000, 0x2d1d65f2, 6 | BRF_SND }, // 15 OKI M6295 Samples 0 + + { "fu13-.rom", 0x20000, 0xb8525622, 7 | BRF_SND }, // 16 OKI M6295 Samples 1 + + { "mb7114h.18e", 0x00100, 0x3645b70f, 8 | BRF_OPT }, // 17 Unused PROMs +}; + +STD_ROM_PICK(twocrude) +STD_ROM_FN(twocrude) + +struct BurnDriver BurnDrvTwocrude = { + "twocrude", "cbuster", NULL, NULL, "1990", + "Two Crude (US)\0", "No sound", "Data East USA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, twocrudeRomInfo, twocrudeRomName, NULL, NULL, CbusterInputInfo, CbusterDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_cninja.cpp b/src/burn/drivers/misc_post90s/d_cninja.cpp new file mode 100644 index 00000000..6e0b35ea --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_cninja.cpp @@ -0,0 +1,3255 @@ +// FB Alpha Caveman Ninja driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "bitswap.h" +#include "deco16ic.h" +#include "burn_ym2203.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSprBuf; +static UINT8 *DrvSprBuf1; +static UINT8 *DrvPrtRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static INT32 scanline; +static INT32 irq_mask; +static INT32 irq_timer; + +static INT32 DrvOkiBank; + +static INT32 has_z80 = 0; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo Robocop2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Robocop2) + +static struct BurnDIPInfo CninjaDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x01, "1" }, + {0x13, 0x01, 0x03, 0x00, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Restore Life Meter" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Cninja) + +static struct BurnDIPInfo CninjauDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Credit(s) to Start" }, + {0x12, 0x01, 0x80, 0x80, "1" }, + {0x12, 0x01, 0x80, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x01, "1" }, + {0x13, 0x01, 0x03, 0x00, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Restore Life Meter" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Cninjau) + +static struct BurnDIPInfo MutantfDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Credit(s) to Start" }, + {0x12, 0x01, 0x80, 0x80, "1" }, + {0x12, 0x01, 0x80, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Timer Decrement" }, + {0x13, 0x01, 0x03, 0x01, "Slow" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x02, "Fast" }, + {0x13, 0x01, 0x03, 0x00, "Very Fast" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Life Per Stage" }, + {0x13, 0x01, 0x30, 0x00, "Least" }, + {0x13, 0x01, 0x30, 0x10, "Little" }, + {0x13, 0x01, 0x30, 0x20, "Less" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Mutantf) + +static struct BurnDIPInfo EdrandyDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Credit(s) to Start" }, + {0x12, 0x01, 0x80, 0x80, "1" }, + {0x12, 0x01, 0x80, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Player's Power" }, + {0x13, 0x01, 0x03, 0x01, "Very Low" }, + {0x13, 0x01, 0x03, 0x00, "Low" }, + {0x13, 0x01, 0x03, 0x03, "Medium" }, + {0x13, 0x01, 0x03, 0x02, "High" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Edrandy) + +static struct BurnDIPInfo EdrandcDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Unknown" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Player's Power" }, + {0x13, 0x01, 0x03, 0x01, "Very Low" }, + {0x13, 0x01, 0x03, 0x00, "Low" }, + {0x13, 0x01, 0x03, 0x03, "Medium" }, + {0x13, 0x01, 0x03, 0x02, "High" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Edrandc) + +static struct BurnDIPInfo Robocop2DIPList[]= +{ + {0x14, 0xff, 0xff, 0xbf, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x00, "2" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x15, 0x01, 0x0c, 0x08, "400 Seconds" }, + {0x15, 0x01, 0x0c, 0x0c, "300 Seconds" }, + {0x15, 0x01, 0x0c, 0x04, "200 Seconds" }, + {0x15, 0x01, 0x0c, 0x00, "100 Seconds" }, + + {0 , 0xfe, 0 , 4, "Health" }, + {0x15, 0x01, 0x30, 0x00, "17" }, + {0x15, 0x01, 0x30, 0x10, "24" }, + {0x15, 0x01, 0x30, 0x30, "33" }, + {0x15, 0x01, 0x30, 0x20, "40" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Bullets" }, + {0x16, 0x01, 0x03, 0x00, "Least" }, + {0x16, 0x01, 0x03, 0x01, "Less" }, + {0x16, 0x01, 0x03, 0x03, "Normal" }, + {0x16, 0x01, 0x03, 0x02, "More" }, + + {0 , 0xfe, 0 , 4, "Enemy Movement" }, + {0x16, 0x01, 0x0c, 0x08, "Slow" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Fast" }, + {0x16, 0x01, 0x0c, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4, "Enemy Strength" }, + {0x16, 0x01, 0x30, 0x20, "Less" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x10, "More" }, + {0x16, 0x01, 0x30, 0x00, "Most" }, + + {0 , 0xfe, 0 , 2, "Enemy Weapon Speed" }, + {0x16, 0x01, 0x40, 0x40, "Normal" }, + {0x16, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2, "Game Over Message" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Robocop2) + +void __fastcall cninja_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x140000, data) + deco16_write_control_word(1, address, 0x150000, data) + + switch (address) + { + case 0x190000: + //case 0x1a4000: + irq_mask = data & 0xff; + return; + + case 0x190002: + //case 0x1a4002: + { + scanline = data & 0xff; + + if ((!BIT(scanline,1)) && (scanline > 0) && (scanline < 240)) { + irq_timer = scanline; + } else { + irq_timer = -1; + } + } + return; + + // case 0x1ac000: + case 0x1b4000: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x17ff2a: + // case 0x1bc0a8: + *soundlatch = data; + if (has_z80) { + ZetNmi(); + } else { + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + } + break; + } + + ////if ((address & 0xfffff800) == 0x198000) { + // deco16_66_prot_w(address, data, 0xffff); + // return; + //} + + //if ((address & 0xffffff00) == 0x1bc000) { + // deco16_prot_ram[(address & 0xff) / 2] = data; + + // return; + //} +} + +void __fastcall cninja_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + // case 0x190000: + case 0x190001: + // case 0x1a4000: + // case 0x1a4001: + irq_mask = data & 0xff; + return; + + // case 0x190002: + case 0x190003: + // case 0x1a4002: + // case 0x1a4003: + { + scanline = data & 0xff; + if ((~irq_mask & 0x02) && (scanline > 0) && (scanline < 240)) { + irq_timer = scanline; + } else { + irq_timer = -1; + } + } + return; + + // case 0x1ac000: + // case 0x1ac001: + // case 0x1b4000: + case 0x1b4001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x1bc0a8: + case 0x1bc0a9: + *soundlatch = data; + if (has_z80) { + ZetNmi(); + } else { + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + } + break; + } + + //if ((address & 0xfffff800) == 0x198000) { + // deco16_66_prot_w(address, data, 0x00ff << ((address & 1) << 3)); + // return; + //} + + //if ((address & 0xffffff00) == 0x1bc000) { + // DrvPrtRAM[(address & 0xff)^1] = data; +// + // return; + //} +} + +UINT16 __fastcall cninja_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x17ff22: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x17ff28: + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x17ff2c: + return DrvInputs[0]; + + // case 0x1a4002: + case 0x190002: + return scanline; + + // case 0x1a4004: + case 0x190004: + SekSetIRQLine(3, SEK_IRQSTATUS_NONE); + SekSetIRQLine(4, SEK_IRQSTATUS_NONE); + return 0; + } + + //if ((address & 0xfffffc00) == 0x1bc000) { + // return deco16_104_cninja_prot_r(address); + //} + + //if ((address & 0xfffff800) == 0x198000) { + // return deco16_60_prot_r(address); + //} + + return 0; +} + +UINT8 __fastcall cninja_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x17ff22: + return DrvDips[1]; + + case 0x17ff23: + return DrvDips[0]; + + // case 0x17ff28: + case 0x17ff29: + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x17ff2c: + return DrvInputs[0] >> 8; + + case 0x17ff2d: + return DrvInputs[0]; + + // case 0x1a4002: + // case 0x1a4003: + // case 0x190002: + case 0x190003: + return scanline; + + // case 0x1a4004: + case 0x1a4005: + // case 0x190004: + case 0x190005: + SekSetIRQLine(3, SEK_IRQSTATUS_NONE); + SekSetIRQLine(4, SEK_IRQSTATUS_NONE); + return 0; + } + + //if ((address & 0xfffff800) == 0x198000) { + // return deco16_60_prot_r(address) >> ((~address & 1) << 3); + //} + + //if ((address & 0xfffffc00) == 0x1bc000) { + // return deco16_104_cninja_prot_r(address) >> ((~address & 1) << 3); + //} + + return 0; +} + +void __fastcall mutantf_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x300000, data) + deco16_write_control_word(1, address, 0x310000, data) + + switch (address) + { + case 0x180000: + deco16_priority = data; + return; + + case 0x1a0064: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + + case 0x1c0000: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x1e0000: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x800); + return; + } + + if ((address & 0xfffff800) == 0x1a0000) { + deco16_66_prot_w(address, data, 0xffff); + return; + } +} + +void __fastcall mutantf_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x180000: + case 0x180001: + deco16_priority = data; + return; + + case 0x1c0000: + case 0x1c0001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x1e0000: + case 0x1e0001: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x800); + return; + + case 0x1a0064: + case 0x1a0065: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + } + + if ((address & 0xfffff800) == 0x1a0000) { + deco16_66_prot_w(address, data, 0x00ff << ((address & 1) << 3)); + return; + } +} + +UINT16 __fastcall mutantf_main_read_word(UINT32 address) +{ + if ((address & 0xfffff800) == 0x1a0000) { + return deco16_66_prot_r(address); + } + + return 0; +} + +UINT8 __fastcall mutantf_main_read_byte(UINT32 address) +{ + if (address == 0x1c0001) return deco16ic_71_read() & 0xff; + + if ((address & 0xfffff800) == 0x1a0000) { + return deco16_66_prot_r(address) >> ((~address & 1) << 3); + } + + return 0; +} + +void __fastcall robocop2_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x140000, data) + deco16_write_control_word(1, address, 0x150000, data) + + switch (address) + { + case 0x1b0000: + irq_mask = data & 0xff; + return; + + case 0x1b0002: { + scanline = data & 0xff; + + if ((!BIT(scanline,1)) && (scanline > 0) && (scanline < 240)) { + irq_timer = scanline; + } else { + irq_timer = -1; + } + } + return; + + case 0x198000: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x18c064: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return;; + + case 0x1f0000: + deco16_priority = data; + return; + } +} + +void __fastcall robocop2_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x1b0000: + case 0x1b0001: + + irq_mask = data & 0xff; + return; + + case 0x1b0002: + case 0x1b0003: { + scanline = data & 0xff; + if ((~irq_mask & 0x02) && (scanline > 0) && (scanline < 240)) { + irq_timer = scanline; + } else { + irq_timer = -1; + } + } + return; + + case 0x198000: + case 0x198001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x18c064: + case 0x18c065: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + + case 0x1f0000: + case 0x1f0001: + deco16_priority = data; + return; + } +} + +UINT16 __fastcall robocop2_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x18c41a: + return DrvInputs[0]; + + case 0x18c320: + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x18c4e6: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x18c504: + return 0x0084; + + case 0x1b0002: + return scanline; + + case 0x1b0004: + SekSetIRQLine(3, SEK_IRQSTATUS_NONE); + SekSetIRQLine(4, SEK_IRQSTATUS_NONE); + return 0; + + case 0x1f8000: + return DrvDips[2]; + } + + return 0; +} + +UINT8 __fastcall robocop2_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x18c41a: + return DrvInputs[0] >> 8; + + case 0x18c41b: + return DrvInputs[0] >> 0; + + case 0x18c320: + case 0x18c321: + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x18c4e6: + return DrvDips[0]; + + case 0x18c4e7: + return DrvDips[1]; + + case 0x18c504: + case 0x18c505: + return 0x0084; + + case 0x1b0002: + case 0x1b0003: + return scanline; + + case 0x1b0004: + case 0x1b0005: + SekSetIRQLine(3, SEK_IRQSTATUS_NONE); + SekSetIRQLine(4, SEK_IRQSTATUS_NONE); + return 0; + + case 0x1f8000: + case 0x1f8001: + return DrvDips[2]; + } + + return 0; +} + +void __fastcall stoneage_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8800: + BurnYM2151SelectRegister(data); + return; + + case 0x8801: + BurnYM2151WriteRegister(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall stoneage_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8800: + case 0x8801: + return BurnYM2151ReadStatus(); + + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + ZetSetIRQLine(0x20, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + if (has_z80) { + ZetSetIRQLine(0, state ? ZET_IRQSTATUS_ACK : ZET_IRQSTATUS_NONE); + } else { +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); + } +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + DrvOkiBank = data & 1; + + memcpy (DrvSndROM1, DrvSndROM1 + 0x40000 + (data & 1) * 0x40000, 0x40000); +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return 0 * nSoundRate; //(INT64)HucTotalCycles() * nSoundRate / 4027500; +} + +static double DrvGetTime() +{ + return 0; //(double)HucTotalCycles() / 4027500.0; +} + +static INT32 cninja_bank_callback(const INT32 bank) +{ + if ((bank >> 4) & 0xf) return 0x0000; + return 0x1000; +} + +static INT32 mutantf_1_bank_callback(const INT32 bank) +{ + return ((bank >> 4) & 0x3) << 12; +} + +static INT32 mutantf_2_bank_callback(const INT32 bank) +{ + return ((bank >> 5) & 0x1) << 14; +} + +static INT32 robocop2_bank_callback(const INT32 bank) +{ + return (bank & 0x30) << 8; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + if (has_z80) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } else { + // Huc6280 + } + + MSM6295Reset(0); + MSM6295Reset(1); + BurnYM2151Reset(); + BurnYM2203Reset(); + + DrvYM2151WritePort(0, 0); // set initial oki bank + + deco16Reset(); + + scanline = 0; + irq_mask = 0; + irq_timer = -1; + + return 0; +} + +static void DrvBootlegCharDecode(UINT8 *gfx, INT32 len) +{ + UINT8 *dst = (UINT8*)BurnMalloc(len); + + memcpy (dst, gfx, len); + + for (INT32 r = 0; r < len; r+=4) { + for (INT32 i = 0; i < 8; i++) { + INT32 t0 = (dst[r + 3] >> (7 - (i & 7))) & 1; + INT32 t1 = (dst[r + 1] >> (7 - (i & 7))) & 1; + INT32 t2 = (dst[r + 2] >> (7 - (i & 7))) & 1; + INT32 t3 = (dst[r + 0] >> (7 - (i & 7))) & 1; + + gfx[(r * 2) + i] = (t0 << 3) | (t1 << 2) | (t2 << 1) | (t3 << 0); + } + } + + BurnFree (dst); +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x300000; + DrvGfxROM3 = Next; Next += 0xa00000; + DrvGfxROM4 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x0c0000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x008000; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvSprRAM1 = Next; Next += 0x000800; + DrvSprBuf1 = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x002000; + + deco16_prot_ram = (UINT16*)Next; + DrvPrtRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void cninja_patch() +{ + UINT16 *rom = (UINT16 *)Drv68KROM; + + for (INT32 i = 0; i < 0x80000 / 2; i++) + { + if (rom[i] == 0x66ff || rom[i] == 0x67ff) + { + if (rom[i - 4] == 0x0c39 || rom[i - 4] == 0x0839) + { + rom[i - 0] = 0x4e71; + rom[i - 1] = 0x4e71; + rom[i - 2] = 0x4e71; + rom[i - 3] = 0x4e71; + rom[i - 4] = 0x4e71; + } + } + } +} + +static INT32 CninjaInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80000, 5, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 8, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 11, 1)) return 1; + + for (INT32 i = 0; i < 0x40000; i++) { + INT32 n = DrvGfxROM2[i + 0x40000]; + DrvGfxROM2[i + 0x40000] = DrvGfxROM2[i + 0x80000]; + DrvGfxROM2[i + 0x80000] = n; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100001, 15, 2)) return 1; + + BurnByteswap(DrvGfxROM3, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 16, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x40000, 17, 1)) return 1; + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + + deco16_sprite_decode(DrvGfxROM3, 0x200000); // 16x16 + + cninja_patch(); + } + + deco16Init(0, 1, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x080000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_global_offsets(0, 8); + + deco16_set_color_base(2, 0x200 + 0x000); + deco16_set_color_base(3, 0x200 + 0x300); + deco16_set_bank_callback(2, cninja_bank_callback); + deco16_set_bank_callback(3, cninja_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x144000, 0x144fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x146000, 0x146fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x14c000, 0x14c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x14e000, 0x14e7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x154000, 0x154fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x156000, 0x156fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x15c000, 0x15c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x15e000, 0x15e7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x184000, 0x187fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x19c000, 0x19dfff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x1a4000, 0x1a47ff, SM_RAM); + SekSetWriteWordHandler(0, cninja_main_write_word); + SekSetWriteByteHandler(0, cninja_main_write_byte); + SekSetReadWordHandler(0, cninja_main_read_word); + SekSetReadByteHandler(0, cninja_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 EdrandyInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0xc0001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0xc0000, 7, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 13, 1)) return 1; + + for (INT32 i = 0; i < 0x40000; i++) { + INT32 n = DrvGfxROM2[i + 0x40000]; + DrvGfxROM2[i + 0x40000] = DrvGfxROM2[i + 0x80000]; + DrvGfxROM2[i + 0x80000] = n; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100001, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200001, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300000, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300001, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400001, 23, 2)) return 1; + + BurnByteswap(DrvGfxROM3, 0x500000); + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 24, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x40000, 25, 1)) return 1; + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + + deco16_sprite_decode(DrvGfxROM3, 0x500000); // 16x16 + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x080000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_global_offsets(0, 8); + + deco16_set_color_base(2, 0x200 + 0x000); + deco16_set_color_base(3, 0x200 + 0x300); + deco16_set_bank_callback(2, cninja_bank_callback); + deco16_set_bank_callback(3, cninja_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x144000, 0x144fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x146000, 0x146fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x14c000, 0x14c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x14e000, 0x14e7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x154000, 0x154fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x156000, 0x156fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x15c000, 0x15c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x15e000, 0x15e7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x188000, 0x189fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x194000, 0x197fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x1bc000, 0x1bc7ff, SM_RAM); + SekSetWriteWordHandler(0, cninja_main_write_word); + SekSetWriteByteHandler(0, cninja_main_write_byte); + SekSetReadWordHandler(0, cninja_main_read_word); + SekSetReadByteHandler(0, cninja_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 MutantfInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x00001, 6, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + + memcpy (DrvGfxROM0 + 0x50000, DrvGfxROM0 + 0x10000, 0x10000); + memcpy (DrvGfxROM0 + 0x10000, DrvGfxROM1 + 0x00000, 0x40000); + memcpy (DrvGfxROM0 + 0x60000, DrvGfxROM1 + 0x40000, 0x40000); + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 9, 1)) return 1; + + for (INT32 i = 0; i < 0x40000; i++) { + INT32 n = DrvGfxROM2[i + 0x40000]; + DrvGfxROM2[i + 0x40000] = DrvGfxROM2[i + 0x80000]; + DrvGfxROM2[i + 0x80000] = n; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400001, 15, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000001, 16, 4)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000003, 17, 4)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 18, 4)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000002, 19, 4)) return 1; + + BurnByteswap(DrvGfxROM3, 0x500000); + BurnByteswap(DrvGfxROM4, 0x040000); + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 20, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x40000, 21, 1)) return 1; + + deco56_decrypt_gfx(DrvGfxROM0, 0xa0000); + deco56_decrypt_gfx(DrvGfxROM1, 0x80000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x0a0000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + + deco16_sprite_decode(DrvGfxROM3, 0x500000); // 16x16 + deco16_sprite_decode(DrvGfxROM4, 0x040000); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0xa0000 * 2, DrvGfxROM1, 0x080000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_global_offsets(0, 8); + + deco16_set_color_base(0, 0x000); + deco16_set_color_base(1, 0x300); + deco16_set_color_base(2, 0x200); + deco16_set_color_base(3, 0x400); + deco16_set_bank_callback(0, mutantf_1_bank_callback); + deco16_set_bank_callback(1, mutantf_2_bank_callback); + deco16_set_bank_callback(2, mutantf_1_bank_callback); + deco16_set_bank_callback(3, mutantf_1_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x160000, 0x161fff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x304000, 0x305fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x306000, 0x307fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x308000, 0x3087ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x30a000, 0x30a7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x314000, 0x315fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x316000, 0x317fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x318000, 0x3187ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x31a000, 0x31a7ff, SM_RAM); + SekSetWriteWordHandler(0, mutantf_main_write_word); + SekSetWriteByteHandler(0, mutantf_main_write_byte); + SekSetReadWordHandler(0, mutantf_main_read_word); + SekSetReadByteHandler(0, mutantf_main_read_byte); + SekClose(); + + // Huc6280... + + // not really... + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 CninjablInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + UINT8 *tmp = (UINT8*)malloc(0x400000); + + if (BurnLoadRom(tmp + 0x00000, 3, 2)) return 1; + if (BurnLoadRom(tmp + 0x00001, 4, 2)) return 1; + BurnByteswap(tmp, 0x400000); + + for (INT32 i = 0; i < 0x200000; i++) tmp[i] ^= 0xff; + + memcpy (DrvGfxROM0 + 0x000000, tmp + 0x000000, 0x020000); + memcpy (DrvGfxROM1 + 0x000000, tmp + 0x080000, 0x080000); + memcpy (DrvGfxROM2 + 0x000000, tmp + 0x180000, 0x080000); + memcpy (DrvGfxROM2 + 0x080000, tmp + 0x100000, 0x080000); + memcpy (DrvGfxROM3 + 0x000000, tmp + 0x200000, 0x200000); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 5, 1)) return 1; + + DrvBootlegCharDecode(DrvGfxROM0, 0x020000); + deco16_sprite_decode(DrvGfxROM1, 0x080000); + deco16_sprite_decode(DrvGfxROM2, 0x100000); + deco16_sprite_decode(DrvGfxROM3, 0x200000); + } + + deco16Init(0, 1, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x080000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_global_offsets(0, 8); + deco16_set_scroll_offs(3, 1, 2, 0); + deco16_set_scroll_offs(2, 1, 2, 0); + deco16_set_color_base(2, 0x200 + 0x000); + deco16_set_color_base(3, 0x200 + 0x300); + deco16_set_bank_callback(2, cninja_bank_callback); + deco16_set_bank_callback(3, cninja_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x138000, 0x1387ff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x144000, 0x144fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x146000, 0x146fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x14c000, 0x14c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x14e000, 0x14e7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x154000, 0x154fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x156000, 0x156fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x15c000, 0x15c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x15e000, 0x15e7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x180000, 0x187fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x19c000, 0x19dfff, SM_RAM); + SekSetWriteWordHandler(0, cninja_main_write_word); + SekSetWriteByteHandler(0, cninja_main_write_byte); + SekSetReadWordHandler(0, cninja_main_read_word); + SekSetReadByteHandler(0, cninja_main_read_byte); + SekClose(); + + has_z80 = 1; + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(stoneage_sound_write); + ZetSetReadHandler(stoneage_sound_read); + ZetMemEnd(); + ZetClose(); + + // not really... + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 StoneageInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 8, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 11, 1)) return 1; + + for (INT32 i = 0; i < 0x40000; i++) { + INT32 n = DrvGfxROM2[i + 0x40000]; + DrvGfxROM2[i + 0x40000] = DrvGfxROM2[i + 0x80000]; + DrvGfxROM2[i + 0x80000] = n; + } + + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100001, 15, 2)) return 1; + + BurnByteswap(DrvGfxROM3, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 16, 1)) return 1; + + memset (DrvSndROM1, 0xff, 0x80000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + + deco16_sprite_decode(DrvGfxROM3, 0x200000); // 16x16 + } + + deco16Init(0, 1, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x080000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_global_offsets(0, 8); + deco16_set_scroll_offs(3, 1, 10, 0); + deco16_set_scroll_offs(1, 1, 10, 0); + deco16_set_scroll_offs(0, 1, -2, 0); + deco16_set_color_base(2, 0x200 + 0x000); + deco16_set_color_base(3, 0x200 + 0x300); + deco16_set_bank_callback(2, cninja_bank_callback); + deco16_set_bank_callback(3, cninja_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x144000, 0x144fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x146000, 0x146fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x14c000, 0x14c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x14e000, 0x14e7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x154000, 0x154fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x156000, 0x156fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x15c000, 0x15c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x15e000, 0x15e7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x184000, 0x187fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x19c000, 0x19dfff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x1a4000, 0x1a47ff, SM_RAM); + SekSetWriteWordHandler(0, cninja_main_write_word); + SekSetWriteByteHandler(0, cninja_main_write_byte); + SekSetReadWordHandler(0, cninja_main_read_word); + SekSetReadByteHandler(0, cninja_main_read_byte); + SekClose(); + + has_z80 = 1; + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(stoneage_sound_write); + ZetSetReadHandler(stoneage_sound_read); + ZetMemEnd(); + ZetClose(); + + // not really... + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 Robocop2Init() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x80000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0xc0001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0xc0000, 7, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000, 12, 1)) return 1; + + for (INT32 i = 0; i < 0x40000; i++) { + INT32 n = DrvGfxROM1[i + 0x40000]; + DrvGfxROM1[i + 0x40000] = DrvGfxROM1[i + 0x80000]; + DrvGfxROM1[i + 0x80000] = n; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 1)) return 1; + memcpy (DrvGfxROM2 + 0x000000, DrvGfxROM3 + 0x000000, 0x040000); + memcpy (DrvGfxROM2 + 0x0c0000, DrvGfxROM3 + 0x040000, 0x040000); + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 14, 1)) return 1; + memcpy (DrvGfxROM2 + 0x040000, DrvGfxROM3 + 0x000000, 0x040000); + memcpy (DrvGfxROM2 + 0x100000, DrvGfxROM3 + 0x040000, 0x040000); + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 15, 1)) return 1; + memcpy (DrvGfxROM2 + 0x080000, DrvGfxROM3 + 0x000000, 0x040000); + memcpy (DrvGfxROM2 + 0x140000, DrvGfxROM3 + 0x040000, 0x040000); + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100001, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200001, 21, 2)) return 1; + + BurnByteswap(DrvGfxROM3, 0x300000); + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 22, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x40000, 23, 1)) return 1; + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM4, 0x180000, 2); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x180000, 0); + + deco16_sprite_decode(DrvGfxROM3, 0x300000); // 16x16 + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x100000 * 2, DrvGfxROM2, 0x180000 * 2); + deco16_set_global_offsets(0, 8); + + deco16_set_color_base(2, 0x200 + 0x000); + deco16_set_color_base(3, 0x200 + 0x300); + deco16_set_bank_callback(1, robocop2_bank_callback); + deco16_set_bank_callback(2, robocop2_bank_callback); + deco16_set_bank_callback(3, robocop2_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x144000, 0x144fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x146000, 0x146fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x14c000, 0x14c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x14e000, 0x14e7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x154000, 0x154fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x156000, 0x156fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x15c000, 0x15c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x15e000, 0x15e7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x180000, 0x1807ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x1a8000, 0x1a9fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x1b8000, 0x1bbfff, SM_RAM); + SekSetWriteWordHandler(0, robocop2_main_write_word); + SekSetWriteByteHandler(0, robocop2_main_write_byte); + SekSetReadWordHandler(0, robocop2_main_read_word); + SekSetReadByteHandler(0, robocop2_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + BurnYM2151Init(3580000, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + MSM6295Exit(0); + MSM6295Exit(1); + BurnYM2151Exit(); + BurnYM2203Exit(); + + SekExit(); + + if (has_z80) { + ZetExit(); + has_z80 = 0; + } else { + // huc6280 + } + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void cninja_draw_sprites() +{ + UINT16 *buffered_spriteram = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0x400 - 4; offs >=0 ; offs -= 4) + { + INT32 x, y, sprite, color, multi, flipx, flipy, inc, flash, mult, pri = 0; + sprite = buffered_spriteram[offs + 1]; + if (!sprite) + continue; + + x = buffered_spriteram[offs + 2]; + + switch (x & 0xc000) + { + case 0x0000: pri = 0; break; + case 0x4000: pri = 0xf0; break; + case 0x8000: pri = 0xf0 | 0xcc; break; + case 0xc000: pri = 0xf0 | 0xcc; break; + } + + y = buffered_spriteram[offs]; + flash = y & 0x1000; + if (flash && (nCurrentFrame & 1)) + continue; + + color = (x >> 9) & 0x1f; + + flipx = y & 0x2000; + flipy = y & 0x4000; + multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= nScreenWidth) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + sprite &= ~multi; + if (flipy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y = 240 - y; + x = (nScreenWidth - 16) - x; + if (flipx) flipx = 0; else flipx = 1; + if (flipy) flipy = 0; else flipy = 1; + mult = 16; + } + else + mult = -16; + + while (multi >= 0) + { + deco16_draw_prio_sprite(pTransDraw, DrvGfxROM3, sprite - multi * inc, (color << 4) + 0x300, x, y + mult * multi, flipx, flipy, pri); + + multi--; + } + } +} + +static void cninjabl_draw_sprites() +{ + UINT16 *buffered_spriteram = (UINT16*)DrvSprBuf; + INT32 offs; + INT32 endoffs; + + endoffs = 0x400 - 4; + for (offs = 0; offs < 0x400 - 4 ; offs += 4) + { + INT32 y = buffered_spriteram[offs + 1]; + + if (y == 0x180) + { + endoffs = offs; + offs = 0x400 - 4; + } + } + + for (offs = endoffs; offs >=0 ; offs -= 4) + { + INT32 x, y, sprite, colour, multi, fx, fy, inc, flash, mult, pri = 0; + + sprite = buffered_spriteram[offs + 0]; + y = buffered_spriteram[offs + 1]; + + if (!sprite) + continue; + + x = buffered_spriteram[offs + 2]; + + switch (x & 0xc000) + { + case 0x0000: pri = 0; break; + case 0x4000: pri = 0xf0; break; + case 0x8000: pri = 0xf0 | 0xcc; break; + case 0xc000: pri = 0xf0 | 0xcc; break; + } + + flash = y & 0x1000; + if (flash && (nCurrentFrame & 1)) + continue; + + colour = (x >> 9) & 0x1f; + + fx = y & 0x2000; + fy = y & 0x4000; + + multi = (1 << ((y & 0x0600) >> 9)) - 1; + + y -= multi * 16; + y += 4; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 256) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y = 240 - y; + x = 240 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else + mult = -16; + + while (multi >= 0) + { + deco16_draw_prio_sprite(pTransDraw, DrvGfxROM3, sprite - multi * inc, (colour << 4) + 0x300, x, y + mult * multi, fx, fy, pri); + + multi--; + } + } +} + +static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gfxbank) +{ + UINT16 *spriteptr = (UINT16*)ram; + + INT32 offs, end, inc; + + if (gfxbank == 4) + { + offs = 0; + end = 0x400; + inc = 4; + } + else + { + offs = 0x3fc; + end = -4; + inc = -4; + } + + while (offs != end) + { + INT32 x, y, sprite, colour, fx, fy, w, h, sx, sy, x_mult, y_mult; + INT32 alpha = 0xff; + + sprite = spriteptr[offs + 3]; + if (!sprite) + { + offs += inc; + continue; + } + + sx = spriteptr[offs + 1]; + + h = (spriteptr[offs + 2] & 0xf000) >> 12; + w = (spriteptr[offs + 2] & 0x0f00) >> 8; + + sy = spriteptr[offs]; + if ((sy & 0x2000) && (nCurrentFrame & 1)) + { + offs += inc; + continue; + } + + colour = (spriteptr[offs + 2] >> 0) & 0x1f; + + if (gfxbank == 4) + { + alpha = 0x80; + colour &= 0xf; + } + + fx = (spriteptr[offs + 0] & 0x4000); + fy = (spriteptr[offs + 0] & 0x8000); + + if (*flipscreen) + { + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + + sx = sx & 0x01ff; + sy = sy & 0x01ff; + if (sx > 0x180) sx = -(0x200 - sx); + if (sy > 0x180) sy = -(0x200 - sy); + + if (fx) { x_mult = -16; sx += 16 * w; } else { x_mult = 16; sx -= 16; } + if (fy) { y_mult = -16; sy += 16 * h; } else { y_mult = 16; sy -= 16; } + } + else + { + sx = sx & 0x01ff; + sy = sy & 0x01ff; + if (sx & 0x100) sx = -(0x100 - (sx & 0xff)); + if (sy & 0x100) sy = -(0x100 - (sy & 0xff)); + sx = 304 - sx; + sy = 240 - sy; + if (sx >= 432) sx -= 512; + if (sy >= 384) sy -= 512; + if (fx) { x_mult = -16; sx += 16; } else { x_mult = 16; sx -= 16*w; } + if (fy) { y_mult = -16; sy += 16; } else { y_mult = 16; sy -= 16*h; } + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + // needs alpha blending... + deco16_draw_prio_sprite(pTransDraw, gfx, sprite + y + h * x, (colour << 4) + colbank, sx + x_mult * (w-x), sy + y_mult * (h-y), fx, fy, 0); + } + } + offs += inc; + } +} + +static INT32 CninjaDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x200; + } + + deco16_clear_prio_map(); + + if (nSpriteEnable & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x01) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nSpriteEnable & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x02) | DECO16_LAYER_TRANSMASK1); + if (nSpriteEnable & 8) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x04) | DECO16_LAYER_TRANSMASK0); + + cninja_draw_sprites(); + + if (nSpriteEnable & 16) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 CninjablDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x200; + } + + deco16_clear_prio_map(); + + if (nSpriteEnable & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x01) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nSpriteEnable & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x02) | DECO16_LAYER_TRANSMASK1); + if (nSpriteEnable & 8) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x04) | DECO16_LAYER_TRANSMASK0); + + cninjabl_draw_sprites(); + + if (nSpriteEnable & 16) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 EdrandyDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0; + } + + deco16_clear_prio_map(); + + if (nSpriteEnable & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x01) | DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nSpriteEnable & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x04)); + + cninja_draw_sprites(); + + if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 Robocop2Draw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x200; + } + + deco16_clear_prio_map(); + + INT32 layer_8bpp = 0; + + if (deco16_priority & 4) + { + deco16_set_color_mask(2, 0); + deco16_set_color_mask(3, 0); + deco16_set_graphics(2, DrvGfxROM4, 0x100000, 16); + layer_8bpp = DECO16_LAYER_8BITSPERPIXEL; + } + else + { + deco16_set_color_mask(2, 0xf); + deco16_set_color_mask(3, 0xf); + deco16_set_graphics(2, DrvGfxROM2, 0x300000, 16); + + if (nSpriteEnable & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE | DECO16_LAYER_PRIORITY(0x01)); + } + + if (deco16_priority & 8) { + if (nSpriteEnable & 2) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nSpriteEnable & 4) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x04) | layer_8bpp); + } else { + if (nSpriteEnable & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02) | layer_8bpp); + if (nSpriteEnable & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x04)); + } + + cninja_draw_sprites(); + + if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 MutantfDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x400; + } + + if (nSpriteEnable & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE); + if (nSpriteEnable & 2) deco16_draw_layer(1, pTransDraw, 0); + if (nSpriteEnable & 4) deco16_draw_layer(2, pTransDraw, 0); + + if (deco16_priority & 1) + { + deco16_clear_prio_map(); + mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3); + deco16_clear_prio_map(); + mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4); + } + else + { + deco16_clear_prio_map(); + mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4); + deco16_clear_prio_map(); + mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3); + } + + if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 CninjaFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + deco16_prot_inputs = DrvInputs; + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[2] = (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 12000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (irq_timer == i) { + SekSetIRQLine((irq_mask & 0x10) ? 3 : 4, SEK_IRQSTATUS_ACK); + irq_timer = -1; + } + if (i == 248) deco16_vblank = 0x08; + } + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +static INT32 MutantfFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + deco16_prot_inputs = DrvInputs; + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[2] = (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + MutantfDraw(); + } + + return 0; +} + +static INT32 StoneageFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + deco16_prot_inputs = DrvInputs; + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[2] = (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + INT32 nInterleave = 256; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 12000000 / 58, 3579545 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave); + + if (irq_timer == i) { + SekSetIRQLine((irq_mask & 0x10) ? 3 : 4, SEK_IRQSTATUS_ACK); + irq_timer = -1; + } + if (i == 248) deco16_vblank = 0x08; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2203Scan(nAction, pnMin); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(scanline); + SCAN_VAR(irq_mask); + SCAN_VAR(irq_timer); + + SCAN_VAR(DrvOkiBank); + DrvYM2151WritePort(0, DrvOkiBank); + } + + return 0; +} + + +// Caveman Ninja (World ver 4) + +static struct BurnRomInfo cninjaRomDesc[] = { + { "gn-02-3.1k", 0x020000, 0x39aea12a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gn-05-2.3k", 0x020000, 0x0f4360ef, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gn-01-2.1j", 0x020000, 0xf740ef7e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gn-04-2.3j", 0x020000, 0xc98fcb62, 1 | BRF_PRG | BRF_ESS }, // 3 + { "gn-00.rom", 0x020000, 0x0b110b16, 1 | BRF_PRG | BRF_ESS }, // 4 + { "gn-03.rom", 0x020000, 0x1e28e697, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "gl-07.rom", 0x010000, 0xca8bef96, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "gl-08.rom", 0x010000, 0x33a2b400, 3 | BRF_GRA }, // 7 Characters + { "gl-09.rom", 0x010000, 0x5a2d4752, 3 | BRF_GRA }, // 8 + + { "mag-02.rom", 0x080000, 0xde89c69a, 4 | BRF_GRA }, // 9 Foreground Tiles + + { "mag-00.rom", 0x080000, 0xa8f05d33, 5 | BRF_GRA }, // 10 Background Tiles + { "mag-01.rom", 0x080000, 0x5b399eed, 5 | BRF_GRA }, // 11 + + { "mag-03.rom", 0x080000, 0x2220eb9f, 6 | BRF_GRA }, // 12 Sprites + { "mag-05.rom", 0x080000, 0x56a53254, 6 | BRF_GRA }, // 13 + { "mag-04.rom", 0x080000, 0x144b94cc, 6 | BRF_GRA }, // 14 + { "mag-06.rom", 0x080000, 0x82d44749, 6 | BRF_GRA }, // 15 + + { "gl-06.rom", 0x020000, 0xd92e519d, 7 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mag-07.rom", 0x080000, 0x08eb5264, 8 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "mb7122h.7v", 0x000400, 0xa1267336, 0 | BRF_OPT }, // 18 Unused PROMs +}; + +STD_ROM_PICK(cninja) +STD_ROM_FN(cninja) + +struct BurnDriver BurnDrvCninja = { + "cninja", NULL, NULL, NULL, "1991", + "Caveman Ninja (World ver 4)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cninjaRomInfo, cninjaRomName, NULL, NULL, DrvInputInfo, CninjaDIPInfo, + CninjaInit, DrvExit, CninjaFrame, CninjaDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Caveman Ninja (World ver 1) + +static struct BurnRomInfo cninja1RomDesc[] = { + { "gn-02.1k", 0x020000, 0xccc59524, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gn-05.3k", 0x020000, 0xa002cbe4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gn-01.1j", 0x020000, 0x18f0527c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gn-04.3j", 0x020000, 0xea4b6d53, 1 | BRF_PRG | BRF_ESS }, // 3 + { "gn-00.rom", 0x020000, 0x0b110b16, 1 | BRF_PRG | BRF_ESS }, // 4 + { "gn-03.rom", 0x020000, 0x1e28e697, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "gl-07.rom", 0x010000, 0xca8bef96, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "gl-08.rom", 0x010000, 0x33a2b400, 3 | BRF_GRA }, // 7 Characters + { "gl-09.rom", 0x010000, 0x5a2d4752, 3 | BRF_GRA }, // 8 + + { "mag-02.rom", 0x080000, 0xde89c69a, 4 | BRF_GRA }, // 9 Foreground Tiles + + { "mag-00.rom", 0x080000, 0xa8f05d33, 5 | BRF_GRA }, // 10 Background Tiles + { "mag-01.rom", 0x080000, 0x5b399eed, 5 | BRF_GRA }, // 11 + + { "mag-03.rom", 0x080000, 0x2220eb9f, 6 | BRF_GRA }, // 12 Sprites + { "mag-05.rom", 0x080000, 0x56a53254, 6 | BRF_GRA }, // 13 + { "mag-04.rom", 0x080000, 0x144b94cc, 6 | BRF_GRA }, // 14 + { "mag-06.rom", 0x080000, 0x82d44749, 6 | BRF_GRA }, // 15 + + { "gl-06.rom", 0x020000, 0xd92e519d, 7 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mag-07.rom", 0x080000, 0x08eb5264, 8 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "mb7122h.7v", 0x000400, 0xa1267336, 0 | BRF_OPT }, // 18 Unused PROMs +}; + +STD_ROM_PICK(cninja1) +STD_ROM_FN(cninja1) + +struct BurnDriverD BurnDrvCninja1 = { + "cninja1", "cninja", NULL, NULL, "1991", + "Caveman Ninja (World ver 1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cninja1RomInfo, cninja1RomName, NULL, NULL, DrvInputInfo, CninjaDIPInfo, + CninjaInit, DrvExit, CninjaFrame, CninjaDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Caveman Ninja (US ver 4) + +static struct BurnRomInfo cninjauRomDesc[] = { + { "gm-02-3.1k", 0x020000, 0xd931c3b1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gm-05-2.3k", 0x020000, 0x7417d3fb, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gm-01-2.1j", 0x020000, 0x72041f7e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gm-04-2.3j", 0x020000, 0x2104d005, 1 | BRF_PRG | BRF_ESS }, // 3 + { "gn-00.rom", 0x020000, 0x0b110b16, 1 | BRF_PRG | BRF_ESS }, // 4 + { "gn-03.rom", 0x020000, 0x1e28e697, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "gl-07.rom", 0x010000, 0xca8bef96, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "gl-08.rom", 0x010000, 0x33a2b400, 3 | BRF_GRA }, // 7 Characters + { "gl-09.rom", 0x010000, 0x5a2d4752, 3 | BRF_GRA }, // 8 + + { "mag-02.rom", 0x080000, 0xde89c69a, 4 | BRF_GRA }, // 9 Foreground Tiles + + { "mag-00.rom", 0x080000, 0xa8f05d33, 5 | BRF_GRA }, // 10 Background Tiles + { "mag-01.rom", 0x080000, 0x5b399eed, 5 | BRF_GRA }, // 11 + + { "mag-03.rom", 0x080000, 0x2220eb9f, 6 | BRF_GRA }, // 12 Sprites + { "mag-05.rom", 0x080000, 0x56a53254, 6 | BRF_GRA }, // 13 + { "mag-04.rom", 0x080000, 0x144b94cc, 6 | BRF_GRA }, // 14 + { "mag-06.rom", 0x080000, 0x82d44749, 6 | BRF_GRA }, // 15 + + { "gl-06.rom", 0x020000, 0xd92e519d, 7 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mag-07.rom", 0x080000, 0x08eb5264, 8 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "mb7122h.7v", 0x000400, 0xa1267336, 0 | BRF_OPT }, // 18 Unused PROMs +}; + +STD_ROM_PICK(cninjau) +STD_ROM_FN(cninjau) + +struct BurnDriverD BurnDrvCninjau = { + "cninjau", "cninja", NULL, NULL, "1991", + "Caveman Ninja (US ver 4)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cninjauRomInfo, cninjauRomName, NULL, NULL, DrvInputInfo, CninjauDIPInfo, + CninjaInit, DrvExit, CninjaFrame, CninjaDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Tatakae Genshizin Joe & Mac (Japan ver 1) + +static struct BurnRomInfo joemacRomDesc[] = { + { "gl-02-2.1k", 0x020000, 0x80da12e2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gl-05-2.3k", 0x020000, 0xfe4dbbbb, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gl-01-2.1j", 0x020000, 0x0b245307, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gl-04-2.3j", 0x020000, 0x1b331f61, 1 | BRF_PRG | BRF_ESS }, // 3 + { "gn-00.rom", 0x020000, 0x0b110b16, 1 | BRF_PRG | BRF_ESS }, // 4 + { "gn-03.rom", 0x020000, 0x1e28e697, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "gl-07.rom", 0x010000, 0xca8bef96, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "gl-08.rom", 0x010000, 0x33a2b400, 3 | BRF_GRA }, // 7 Characters + { "gl-09.rom", 0x010000, 0x5a2d4752, 3 | BRF_GRA }, // 8 + + { "mag-02.rom", 0x080000, 0xde89c69a, 4 | BRF_GRA }, // 9 Foreground Tiles + + { "mag-00.rom", 0x080000, 0xa8f05d33, 5 | BRF_GRA }, // 10 Background Tiles + { "mag-01.rom", 0x080000, 0x5b399eed, 5 | BRF_GRA }, // 11 + + { "mag-03.rom", 0x080000, 0x2220eb9f, 6 | BRF_GRA }, // 12 Sprites + { "mag-05.rom", 0x080000, 0x56a53254, 6 | BRF_GRA }, // 13 + { "mag-04.rom", 0x080000, 0x144b94cc, 6 | BRF_GRA }, // 14 + { "mag-06.rom", 0x080000, 0x82d44749, 6 | BRF_GRA }, // 15 + + { "gl-06.rom", 0x020000, 0xd92e519d, 7 | BRF_SND }, // 16 OKI M6295 Samples 0 + + { "mag-07.rom", 0x080000, 0x08eb5264, 8 | BRF_SND }, // 17 OKI M6295 Samples 1 + + { "mb7122h.7v", 0x000400, 0xa1267336, 0 | BRF_OPT }, // 18 Unused PROMs +}; + +STD_ROM_PICK(joemac) +STD_ROM_FN(joemac) + +struct BurnDriverD BurnDrvJoemac = { + "joemac", "cninja", NULL, NULL, "1991", + "Tatakae Genshizin Joe & Mac (Japan ver 1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, joemacRomInfo, joemacRomName, NULL, NULL, DrvInputInfo, CninjaDIPInfo, + CninjaInit, DrvExit, CninjaFrame, CninjaDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Stoneage (bootleg of Caveman Ninja) + +static struct BurnRomInfo stoneageRomDesc[] = { + { "sa_1_019.bin", 0x020000, 0x7fb8c44f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sa_1_033.bin", 0x020000, 0x961c752b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sa_1_018.bin", 0x020000, 0xa4043022, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sa_1_032.bin", 0x020000, 0xf52a3286, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sa_1_017.bin", 0x020000, 0x08d6397a, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sa_1_031.bin", 0x020000, 0x103079f5, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sa_1_012.bin", 0x010000, 0x56058934, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "gl-08.rom", 0x010000, 0x33a2b400, 3 | BRF_GRA }, // 7 Characters + { "gl-09.rom", 0x010000, 0x5a2d4752, 3 | BRF_GRA }, // 8 + + { "mag-02.rom", 0x080000, 0xde89c69a, 4 | BRF_GRA }, // 9 Foreground Tiles + + { "mag-00.rom", 0x080000, 0xa8f05d33, 5 | BRF_GRA }, // 10 Background Tiles + { "mag-01.rom", 0x080000, 0x5b399eed, 5 | BRF_GRA }, // 11 + + { "mag-03.rom", 0x080000, 0x2220eb9f, 6 | BRF_GRA }, // 12 Sprites + { "mag-05.rom", 0x080000, 0x56a53254, 6 | BRF_GRA }, // 13 + { "mag-04.rom", 0x080000, 0x144b94cc, 6 | BRF_GRA }, // 14 + { "mag-06.rom", 0x080000, 0x82d44749, 6 | BRF_GRA }, // 15 + + { "sa_1_069.bin", 0x040000, 0x2188f3ca, 7 | BRF_SND }, // 16 OKI M6295 Samples +}; + +STD_ROM_PICK(stoneage) +STD_ROM_FN(stoneage) + +struct BurnDriverD BurnDrvStoneage = { + "stoneage", "cninja", NULL, NULL, "1991", + "Stoneage (bootleg of Caveman Ninja)\0", "No sound", "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, stoneageRomInfo, stoneageRomName, NULL, NULL, DrvInputInfo, CninjaDIPInfo, + StoneageInit, DrvExit, StoneageFrame, CninjaDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Caveman Ninja (bootleg) + +static struct BurnRomInfo cninjablRomDesc[] = { + { "joe mac 3.68k", 0x080000, 0xdc931d80, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "joe mac 4.68k", 0x080000, 0xe8dfe0b5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "joe mac 5.z80", 0x010000, 0xd791b9d7, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "joe mac 1.gfx", 0x200000, 0x17ea5931, 3 | BRF_GRA }, // 3 Graphics (Expanded on init) + { "joe mac 2.gfx", 0x200000, 0xcc95317b, 3 | BRF_GRA }, // 4 + + { "joe mac 6.samples", 0x080000, 0xdbecad83, 4 | BRF_SND }, // 5 OKI M6295 Samples +}; + +STD_ROM_PICK(cninjabl) +STD_ROM_FN(cninjabl) + +struct BurnDriver BurnDrvCninjabl = { + "cninjabl", "cninja", NULL, NULL, "1991", + "Caveman Ninja (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cninjablRomInfo, cninjablRomName, NULL, NULL, DrvInputInfo, CninjaDIPInfo, + CninjablInit, DrvExit, StoneageFrame, CninjablDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Mutant Fighter (World ver EM-5) + +static struct BurnRomInfo mutantfRomDesc[] = { + { "hd-03-4.2c", 0x020000, 0x94859545, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hd-00-4.2a", 0x020000, 0x3cdb648f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hd-04-1.4c", 0x020000, 0xfd2ea8d7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "hd-01-1.4a", 0x020000, 0x48a247ac, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hd-12.21j", 0x010000, 0x13d55f11, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "hd-06-1.8d", 0x010000, 0x8b7a558b, 3 | BRF_GRA }, // 5 Characters + { "hd-07-1.9d", 0x010000, 0xd2a3d449, 3 | BRF_GRA }, // 6 + + { "maf-00.8a", 0x080000, 0xe56f528d, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "maf-01.9a", 0x080000, 0xc3d5173d, 5 | BRF_GRA }, // 8 Background Tiles + { "maf-02.11a", 0x080000, 0x0b37d849, 5 | BRF_GRA }, // 9 + + { "maf-03.18a", 0x100000, 0xf4366d2c, 6 | BRF_GRA }, // 10 Sprite Bank A + { "maf-04.20a", 0x100000, 0x0c8f654e, 6 | BRF_GRA }, // 11 + { "maf-05.21a", 0x080000, 0xb0cfeb80, 6 | BRF_GRA }, // 12 + { "maf-06.18d", 0x100000, 0xf5c7a9b5, 6 | BRF_GRA }, // 13 + { "maf-07.20d", 0x100000, 0xfd6008a3, 6 | BRF_GRA }, // 14 + { "maf-08.21d", 0x080000, 0xe41cf1e7, 6 | BRF_GRA }, // 15 + + { "hf-08.15a", 0x010000, 0x93b7279f, 7 | BRF_GRA }, // 16 Sprite Bank B + { "hf-09.17a", 0x010000, 0x05e2c074, 7 | BRF_GRA }, // 17 + { "hf-10.15c", 0x010000, 0x9b06f418, 7 | BRF_GRA }, // 18 + { "hf-11.17c", 0x010000, 0x3859a531, 7 | BRF_GRA }, // 19 + + { "maf-10.20l", 0x040000, 0x7c57f48b, 8 | BRF_SND }, // 20 OKI M6295 Samples 0 + + { "maf-09.18l", 0x080000, 0x28e7ed81, 9 | BRF_SND }, // 21 OKI M6295 Samples 1 +}; + +STD_ROM_PICK(mutantf) +STD_ROM_FN(mutantf) + +struct BurnDriver BurnDrvMutantf = { + "mutantf", NULL, NULL, NULL, "1992", + "Mutant Fighter (World ver EM-5)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, mutantfRomInfo, mutantfRomName, NULL, NULL, DrvInputInfo, MutantfDIPInfo, + MutantfInit, DrvExit, MutantfFrame, MutantfDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Mutant Fighter (World ver EM-4) + +static struct BurnRomInfo mutantf4RomDesc[] = { + { "hd-03-3.2c", 0x020000, 0xe6f53574, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hd-00-3.2a", 0x020000, 0xd3055454, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hd-04-1.4c", 0x020000, 0xfd2ea8d7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "hd-01-1.4a", 0x020000, 0x48a247ac, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hd-12.21j", 0x010000, 0x13d55f11, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "hd-06-1.8d", 0x010000, 0x8b7a558b, 3 | BRF_GRA }, // 5 Characters + { "hd-07-1.9d", 0x010000, 0xd2a3d449, 3 | BRF_GRA }, // 6 + + { "maf-00.8a", 0x080000, 0xe56f528d, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "maf-01.9a", 0x080000, 0xc3d5173d, 5 | BRF_GRA }, // 8 Background Tiles + { "maf-02.11a", 0x080000, 0x0b37d849, 5 | BRF_GRA }, // 9 + + { "maf-03.18a", 0x100000, 0xf4366d2c, 6 | BRF_GRA }, // 10 Sprite Bank A + { "maf-04.20a", 0x100000, 0x0c8f654e, 6 | BRF_GRA }, // 11 + { "maf-05.21a", 0x080000, 0xb0cfeb80, 6 | BRF_GRA }, // 12 + { "maf-06.18d", 0x100000, 0xf5c7a9b5, 6 | BRF_GRA }, // 13 + { "maf-07.20d", 0x100000, 0xfd6008a3, 6 | BRF_GRA }, // 14 + { "maf-08.21d", 0x080000, 0xe41cf1e7, 6 | BRF_GRA }, // 15 + + { "hf-08.15a", 0x010000, 0x93b7279f, 7 | BRF_GRA }, // 16 Sprite Bank B + { "hf-09.17a", 0x010000, 0x05e2c074, 7 | BRF_GRA }, // 17 + { "hf-10.15c", 0x010000, 0x9b06f418, 7 | BRF_GRA }, // 18 + { "hf-11.17c", 0x010000, 0x3859a531, 7 | BRF_GRA }, // 19 + + { "maf-10.20l", 0x040000, 0x7c57f48b, 8 | BRF_SND }, // 20 OKI M6295 Samples 0 + + { "maf-09.18l", 0x080000, 0x28e7ed81, 9 | BRF_SND }, // 21 OKI M6295 Samples 1 +}; + +STD_ROM_PICK(mutantf4) +STD_ROM_FN(mutantf4) + +struct BurnDriver BurnDrvMutantf4 = { + "mutantf4", "mutantf", NULL, NULL, "1992", + "Mutant Fighter (World ver EM-4)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, mutantf4RomInfo, mutantf4RomName, NULL, NULL, DrvInputInfo, MutantfDIPInfo, + MutantfInit, DrvExit, MutantfFrame, MutantfDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Mutant Fighter (World ver EM-3) + +static struct BurnRomInfo mutantf3RomDesc[] = { + { "hd-03-2.2c", 0x020000, 0x0586c4fa, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hd-00-2.2a", 0x020000, 0x6f8ec48e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hd-04-1.4c", 0x020000, 0xfd2ea8d7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "hd-01-1.4a", 0x020000, 0x48a247ac, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hd-12.21j", 0x010000, 0x13d55f11, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "hd-06-1.8d", 0x010000, 0x8b7a558b, 3 | BRF_GRA }, // 5 Characters + { "hd-07-1.9d", 0x010000, 0xd2a3d449, 3 | BRF_GRA }, // 6 + + { "maf-00.8a", 0x080000, 0xe56f528d, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "maf-01.9a", 0x080000, 0xc3d5173d, 5 | BRF_GRA }, // 8 Background Tiles + { "maf-02.11a", 0x080000, 0x0b37d849, 5 | BRF_GRA }, // 9 + + { "maf-03.18a", 0x100000, 0xf4366d2c, 6 | BRF_GRA }, // 10 Sprite Bank A + { "maf-04.20a", 0x100000, 0x0c8f654e, 6 | BRF_GRA }, // 11 + { "maf-05.21a", 0x080000, 0xb0cfeb80, 6 | BRF_GRA }, // 12 + { "maf-06.18d", 0x100000, 0xf5c7a9b5, 6 | BRF_GRA }, // 13 + { "maf-07.20d", 0x100000, 0xfd6008a3, 6 | BRF_GRA }, // 14 + { "maf-08.21d", 0x080000, 0xe41cf1e7, 6 | BRF_GRA }, // 15 + + { "hf-08.15a", 0x010000, 0x93b7279f, 7 | BRF_GRA }, // 16 Sprite Bank B + { "hf-09.17a", 0x010000, 0x05e2c074, 7 | BRF_GRA }, // 17 + { "hf-10.15c", 0x010000, 0x9b06f418, 7 | BRF_GRA }, // 18 + { "hf-11.17c", 0x010000, 0x3859a531, 7 | BRF_GRA }, // 19 + + { "maf-10.20l", 0x040000, 0x7c57f48b, 8 | BRF_SND }, // 20 OKI M6295 Samples 0 + + { "maf-09.18l", 0x080000, 0x28e7ed81, 9 | BRF_SND }, // 21 OKI M6295 Samples 1 +}; + +STD_ROM_PICK(mutantf3) +STD_ROM_FN(mutantf3) + +struct BurnDriver BurnDrvMutantf3 = { + "mutantf3", "mutantf", NULL, NULL, "1992", + "Mutant Fighter (World ver EM-3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, mutantf3RomInfo, mutantf3RomName, NULL, NULL, DrvInputInfo, MutantfDIPInfo, + MutantfInit, DrvExit, MutantfFrame, MutantfDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Death Brade (Japan ver JM-3) + +static struct BurnRomInfo deathbrdRomDesc[] = { + { "hf-03-2.2c", 0x020000, 0xfb86fff3, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hf-00-2.2a", 0x020000, 0x099aa422, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hd-04-1.4c", 0x020000, 0xfd2ea8d7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "hd-01-1.4a", 0x020000, 0x48a247ac, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hd-12.21j", 0x010000, 0x13d55f11, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "hd-06-1.8d", 0x010000, 0x8b7a558b, 3 | BRF_GRA }, // 5 Characters + { "hd-07-1.9d", 0x010000, 0xd2a3d449, 3 | BRF_GRA }, // 6 + + { "maf-00.8a", 0x080000, 0xe56f528d, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "maf-01.9a", 0x080000, 0xc3d5173d, 5 | BRF_GRA }, // 8 Background Tiles + { "maf-02.11a", 0x080000, 0x0b37d849, 5 | BRF_GRA }, // 9 + + { "maf-03.18a", 0x100000, 0xf4366d2c, 6 | BRF_GRA }, // 10 Sprite Bank A + { "maf-04.20a", 0x100000, 0x0c8f654e, 6 | BRF_GRA }, // 11 + { "maf-05.21a", 0x080000, 0xb0cfeb80, 6 | BRF_GRA }, // 12 + { "maf-06.18d", 0x100000, 0xf5c7a9b5, 6 | BRF_GRA }, // 13 + { "maf-07.20d", 0x100000, 0xfd6008a3, 6 | BRF_GRA }, // 14 + { "maf-08.21d", 0x080000, 0xe41cf1e7, 6 | BRF_GRA }, // 15 + + { "hf-08.15a", 0x010000, 0x93b7279f, 7 | BRF_GRA }, // 16 Sprite Bank B + { "hf-09.17a", 0x010000, 0x05e2c074, 7 | BRF_GRA }, // 17 + { "hf-10.15c", 0x010000, 0x9b06f418, 7 | BRF_GRA }, // 18 + { "hf-11.17c", 0x010000, 0x3859a531, 7 | BRF_GRA }, // 19 + + { "maf-10.20l", 0x040000, 0x7c57f48b, 8 | BRF_SND }, // 20 OKI M6295 Samples 0 + + { "maf-09.18l", 0x080000, 0x28e7ed81, 9 | BRF_SND }, // 21 OKI M6295 Samples 1 +}; + +STD_ROM_PICK(deathbrd) +STD_ROM_FN(deathbrd) + +struct BurnDriver BurnDrvDeathbrd = { + "deathbrd", "mutantf", NULL, NULL, "1992", + "Death Brade (Japan ver JM-3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, deathbrdRomInfo, deathbrdRomName, NULL, NULL, DrvInputInfo, MutantfDIPInfo, + MutantfInit, DrvExit, MutantfFrame, MutantfDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// The Cliffhanger - Edward Randy (World ver 3) + +static struct BurnRomInfo edrandyRomDesc[] = { + { "gg-00-2.k1", 0x020000, 0xce1ba964, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gg-04-2.k3", 0x020000, 0x24caed19, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gg-01-2.j1", 0x020000, 0x33677b80, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gg-05-2.j3", 0x020000, 0x79a68ca6, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ge-02.h1", 0x020000, 0xc2969fbb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ge-06.h3", 0x020000, 0x5c2e6418, 1 | BRF_PRG | BRF_ESS }, // 5 + { "ge-03.f1", 0x020000, 0x5e7b19a8, 1 | BRF_PRG | BRF_ESS }, // 6 + { "ge-07.f3", 0x020000, 0x5eb819a1, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "ge-09.k13", 0x010000, 0x9f94c60b, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gg-10.y6", 0x010000, 0xb96c6cbe, 3 | BRF_GRA }, // 9 Characters + { "gg-11.z6", 0x010000, 0xee567448, 3 | BRF_GRA }, // 10 + + { "mad-02", 0x080000, 0x6c76face, 4 | BRF_GRA }, // 11 Foreground Tiles + + { "mad-00", 0x080000, 0x3735b22d, 5 | BRF_GRA }, // 12 Background Tiles + { "mad-01", 0x080000, 0x7bb13e1c, 5 | BRF_GRA }, // 13 + + { "mad-03", 0x080000, 0xc0bff892, 6 | BRF_GRA }, // 14 Sprites + { "mad-05", 0x080000, 0x3f2ccf95, 6 | BRF_GRA }, // 15 + { "mad-04", 0x080000, 0x464f3eb9, 6 | BRF_GRA }, // 16 + { "mad-06", 0x080000, 0x60871f77, 6 | BRF_GRA }, // 17 + { "mad-07", 0x080000, 0xac03466e, 6 | BRF_GRA }, // 18 + { "mad-08", 0x080000, 0x1b420ec8, 6 | BRF_GRA }, // 19 + { "mad-10", 0x080000, 0x42da8ef0, 6 | BRF_GRA }, // 20 + { "mad-11", 0x080000, 0x03c1f982, 6 | BRF_GRA }, // 21 + { "mad-09", 0x080000, 0x930f4900, 6 | BRF_GRA }, // 22 + { "mad-12", 0x080000, 0xa0bd62b6, 6 | BRF_GRA }, // 23 + + { "ge-08.j13", 0x020000, 0xdfe28c7b, 7 | BRF_SND }, // 24 OKI M6295 Samples 0 + + { "mad-13", 0x080000, 0x6ab28eba, 8 | BRF_SND }, // 25 OKI M6295 Samples 1 + + { "ge-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 26 Unused PROMs +}; + +STD_ROM_PICK(edrandy) +STD_ROM_FN(edrandy) + +struct BurnDriverD BurnDrvEdrandy = { + "edrandy", NULL, NULL, NULL, "1990", + "The Cliffhanger - Edward Randy (World ver 3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, edrandyRomInfo, edrandyRomName, NULL, NULL, DrvInputInfo, EdrandyDIPInfo, + EdrandyInit, DrvExit, CninjaFrame, EdrandyDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// The Cliffhanger - Edward Randy (World ver 2) + +static struct BurnRomInfo edrandy2RomDesc[] = { + { "gg00-1.k1", 0x020000, 0xa029cc4a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gg04-1.k3", 0x020000, 0x8b7928a4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gg01-1.j1", 0x020000, 0x84360123, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gg05-1.j3", 0x020000, 0x0bf85d9d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ge-02.h1", 0x020000, 0xc2969fbb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ge-06.h3", 0x020000, 0x5c2e6418, 1 | BRF_PRG | BRF_ESS }, // 5 + { "ge-03.f1", 0x020000, 0x5e7b19a8, 1 | BRF_PRG | BRF_ESS }, // 6 + { "ge-07.f3", 0x020000, 0x5eb819a1, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "ge-09.k13", 0x010000, 0x9f94c60b, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gg-10.y6", 0x010000, 0xb96c6cbe, 3 | BRF_GRA }, // 9 Characters + { "gg-11.z6", 0x010000, 0xee567448, 3 | BRF_GRA }, // 10 + + { "mad-02", 0x080000, 0x6c76face, 4 | BRF_GRA }, // 11 Foreground Tiles + + { "mad-00", 0x080000, 0x3735b22d, 5 | BRF_GRA }, // 12 Background Tiles + { "mad-01", 0x080000, 0x7bb13e1c, 5 | BRF_GRA }, // 13 + + { "mad-03", 0x080000, 0xc0bff892, 6 | BRF_GRA }, // 14 Sprites + { "mad-05", 0x080000, 0x3f2ccf95, 6 | BRF_GRA }, // 15 + { "mad-04", 0x080000, 0x464f3eb9, 6 | BRF_GRA }, // 16 + { "mad-06", 0x080000, 0x60871f77, 6 | BRF_GRA }, // 17 + { "mad-07", 0x080000, 0xac03466e, 6 | BRF_GRA }, // 18 + { "mad-08", 0x080000, 0x1b420ec8, 6 | BRF_GRA }, // 19 + { "mad-10", 0x080000, 0x42da8ef0, 6 | BRF_GRA }, // 20 + { "mad-11", 0x080000, 0x03c1f982, 6 | BRF_GRA }, // 21 + { "mad-09", 0x080000, 0x930f4900, 6 | BRF_GRA }, // 22 + { "mad-12", 0x080000, 0xa0bd62b6, 6 | BRF_GRA }, // 23 + + { "ge-08.j13", 0x020000, 0xdfe28c7b, 7 | BRF_SND }, // 24 OKI M6295 Samples 0 + + { "mad-13", 0x080000, 0x6ab28eba, 8 | BRF_SND }, // 25 OKI M6295 Samples 1 + + { "ge-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 26 Unused PROMs +}; + +STD_ROM_PICK(edrandy2) +STD_ROM_FN(edrandy2) + +struct BurnDriverD BurnDrvEdrandy2 = { + "edrandy2", "edrandy", NULL, NULL, "1990", + "The Cliffhanger - Edward Randy (World ver 2)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, edrandy2RomInfo, edrandy2RomName, NULL, NULL, DrvInputInfo, EdrandcDIPInfo, + EdrandyInit, DrvExit, CninjaFrame, EdrandyDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// The Cliffhanger - Edward Randy (World ver 1) + +static struct BurnRomInfo edrandy1RomDesc[] = { + { "1.k1", 0x020000, 0xf184cdaa, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "5.k3", 0x020000, 0x7e3a4b81, 1 | BRF_PRG | BRF_ESS }, // 1 + { "2.j1", 0x020000, 0x212cd593, 1 | BRF_PRG | BRF_ESS }, // 2 + { "6.j3", 0x020000, 0x4a96fb07, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ge-02.h1", 0x020000, 0xc2969fbb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ge-06.h3", 0x020000, 0x5c2e6418, 1 | BRF_PRG | BRF_ESS }, // 5 + { "ge-03.f1", 0x020000, 0x5e7b19a8, 1 | BRF_PRG | BRF_ESS }, // 6 + { "ge-07.f3", 0x020000, 0x5eb819a1, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "ge-09.k13", 0x010000, 0x9f94c60b, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "ge-10.y6", 0x010000, 0x2528d795, 3 | BRF_GRA }, // 9 Characters + { "ge-11.z6", 0x010000, 0xe34a931e, 3 | BRF_GRA }, // 10 + + { "mad-02", 0x080000, 0x6c76face, 4 | BRF_GRA }, // 11 Foreground Tiles + + { "mad-00", 0x080000, 0x3735b22d, 5 | BRF_GRA }, // 12 Background Tiles + { "mad-01", 0x080000, 0x7bb13e1c, 5 | BRF_GRA }, // 13 + + { "mad-03", 0x080000, 0xc0bff892, 6 | BRF_GRA }, // 14 Sprites + { "mad-05", 0x080000, 0x3f2ccf95, 6 | BRF_GRA }, // 15 + { "mad-04", 0x080000, 0x464f3eb9, 6 | BRF_GRA }, // 16 + { "mad-06", 0x080000, 0x60871f77, 6 | BRF_GRA }, // 17 + { "mad-07", 0x080000, 0xac03466e, 6 | BRF_GRA }, // 18 + { "mad-08", 0x080000, 0x1b420ec8, 6 | BRF_GRA }, // 19 + { "mad-10", 0x080000, 0x42da8ef0, 6 | BRF_GRA }, // 20 + { "mad-11", 0x080000, 0x03c1f982, 6 | BRF_GRA }, // 21 + { "mad-09", 0x080000, 0x930f4900, 6 | BRF_GRA }, // 22 + { "mad-12", 0x080000, 0xa0bd62b6, 6 | BRF_GRA }, // 23 + + { "ge-08.j13", 0x020000, 0xdfe28c7b, 7 | BRF_SND }, // 24 OKI M6295 Samples 0 + + { "mad-13", 0x080000, 0x6ab28eba, 8 | BRF_SND }, // 25 OKI M6295 Samples 1 + + { "ge-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 26 Unused PROMs +}; + +STD_ROM_PICK(edrandy1) +STD_ROM_FN(edrandy1) + +struct BurnDriverD BurnDrvEdrandy1 = { + "edrandy1", "edrandy", NULL, NULL, "1990", + "The Cliffhanger - Edward Randy (World ver 1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, edrandy1RomInfo, edrandy1RomName, NULL, NULL, DrvInputInfo, EdrandcDIPInfo, + EdrandyInit, DrvExit, CninjaFrame, EdrandyDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// The Cliffhanger - Edward Randy (Japan ver 3) + +static struct BurnRomInfo edrandyjRomDesc[] = { + { "ge-00-2.k1", 0x020000, 0xb3d2403c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ge-04-2.k3", 0x020000, 0x8a9624d6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ge-01-2.j1", 0x020000, 0x84360123, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ge-05-2.j3", 0x020000, 0x0bf85d9d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ge-02.h1", 0x020000, 0xc2969fbb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ge-06.h3", 0x020000, 0x5c2e6418, 1 | BRF_PRG | BRF_ESS }, // 5 + { "ge-03.f1", 0x020000, 0x5e7b19a8, 1 | BRF_PRG | BRF_ESS }, // 6 + { "ge-07.f3", 0x020000, 0x5eb819a1, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "ge-09.k13", 0x010000, 0x9f94c60b, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "ge-10.y6", 0x010000, 0x2528d795, 3 | BRF_GRA }, // 9 Characters + { "ge-11.z6", 0x010000, 0xe34a931e, 3 | BRF_GRA }, // 10 + + { "mad-02", 0x080000, 0x6c76face, 4 | BRF_GRA }, // 11 Foreground Tiles + + { "mad-00", 0x080000, 0x3735b22d, 5 | BRF_GRA }, // 12 Background Tiles + { "mad-01", 0x080000, 0x7bb13e1c, 5 | BRF_GRA }, // 13 + + { "mad-03", 0x080000, 0xc0bff892, 6 | BRF_GRA }, // 14 Sprites + { "mad-05", 0x080000, 0x3f2ccf95, 6 | BRF_GRA }, // 15 + { "mad-04", 0x080000, 0x464f3eb9, 6 | BRF_GRA }, // 16 + { "mad-06", 0x080000, 0x60871f77, 6 | BRF_GRA }, // 17 + { "mad-07", 0x080000, 0xac03466e, 6 | BRF_GRA }, // 18 + { "mad-08", 0x080000, 0x1b420ec8, 6 | BRF_GRA }, // 19 + { "mad-10", 0x080000, 0x42da8ef0, 6 | BRF_GRA }, // 20 + { "mad-11", 0x080000, 0x03c1f982, 6 | BRF_GRA }, // 21 + { "mad-09", 0x080000, 0x930f4900, 6 | BRF_GRA }, // 22 + { "mad-12", 0x080000, 0xa0bd62b6, 6 | BRF_GRA }, // 23 + + { "ge-08.j13", 0x020000, 0xdfe28c7b, 7 | BRF_SND }, // 24 OKI M6295 Samples 0 + + { "mad-13", 0x080000, 0x6ab28eba, 8 | BRF_SND }, // 25 OKI M6295 Samples 1 + + { "ge-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 26 Unused PROMs +}; + +STD_ROM_PICK(edrandyj) +STD_ROM_FN(edrandyj) + +struct BurnDriverD BurnDrvEdrandyj = { + "edrandyj", "edrandy", NULL, NULL, "1990", + "The Cliffhanger - Edward Randy (Japan ver 3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, edrandyjRomInfo, edrandyjRomName, NULL, NULL, DrvInputInfo, EdrandcDIPInfo, + EdrandyInit, DrvExit, CninjaFrame, EdrandyDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Robocop 2 (Euro/Asia v0.10) + +static struct BurnRomInfo robocop2RomDesc[] = { + { "gq-03.k1", 0x020000, 0xa7e90c28, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gq-07.k3", 0x020000, 0xd2287ec1, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gq-02.j1", 0x020000, 0x6777b8a0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gq-06.j3", 0x020000, 0xe11e27b5, 1 | BRF_PRG | BRF_ESS }, // 3 + { "go-01-1.h1", 0x020000, 0xab5356c0, 1 | BRF_PRG | BRF_ESS }, // 4 + { "go-05-1.h3", 0x020000, 0xce21bda5, 1 | BRF_PRG | BRF_ESS }, // 5 + { "go-00.f1", 0x020000, 0xa93369ea, 1 | BRF_PRG | BRF_ESS }, // 6 + { "go-04.f3", 0x020000, 0xee2f6ad9, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "gp-09.k13", 0x010000, 0x4a4e0f8d, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gp10-1.y6", 0x010000, 0xd25d719c, 3 | BRF_GRA }, // 9 Characters + { "gp11-1.z6", 0x010000, 0x030ded47, 3 | BRF_GRA }, // 10 + + { "mah-04.z4", 0x080000, 0x9b6ca18c, 4 | BRF_GRA }, // 11 Foreground Tiles + { "mah-03.y4", 0x080000, 0x37894ddc, 4 | BRF_GRA }, // 12 + + { "mah-01.z1", 0x080000, 0x26e0dfff, 5 | BRF_GRA }, // 13 Background Tiles + { "mah-00.y1", 0x080000, 0x7bd69e41, 5 | BRF_GRA }, // 14 + { "mah-02.a1", 0x080000, 0x328a247d, 5 | BRF_GRA }, // 15 + + { "mah-05.y9", 0x080000, 0x6773e613, 6 | BRF_GRA }, // 16 Sprites + { "mah-08.y12", 0x080000, 0x88d310a5, 6 | BRF_GRA }, // 17 + { "mah-06.z9", 0x080000, 0x27a8808a, 6 | BRF_GRA }, // 18 + { "mah-09.z12", 0x080000, 0xa58c43a7, 6 | BRF_GRA }, // 19 + { "mah-07.a9", 0x080000, 0x526f4190, 6 | BRF_GRA }, // 20 + { "mah-10.a12", 0x080000, 0x14b770da, 6 | BRF_GRA }, // 21 + + { "gp-08.j13", 0x020000, 0x365183b1, 7 | BRF_SND }, // 22 OKI M6295 Samples 0 + + { "mah-11.f13", 0x080000, 0x642bc692, 8 | BRF_SND }, // 23 OKI M6295 Samples 1 + + { "go-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 24 Unused PROMs +}; + +STD_ROM_PICK(robocop2) +STD_ROM_FN(robocop2) + +struct BurnDriver BurnDrvRobocop2 = { + "robocop2", NULL, NULL, NULL, "1991", + "Robocop 2 (Euro/Asia v0.10)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, robocop2RomInfo, robocop2RomName, NULL, NULL, Robocop2InputInfo, Robocop2DIPInfo, + Robocop2Init, DrvExit, CninjaFrame, Robocop2Draw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Robocop 2 (US v0.05) + +static struct BurnRomInfo robocop2uRomDesc[] = { + { "robo03.k1", 0x020000, 0xf4c96cc9, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "robo07.k3", 0x020000, 0x11e53a7c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "robo02.j1", 0x020000, 0xfa086a0d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "robo06.j3", 0x020000, 0x703b49d0, 1 | BRF_PRG | BRF_ESS }, // 3 + { "go-01-1.h1", 0x020000, 0xab5356c0, 1 | BRF_PRG | BRF_ESS }, // 4 + { "go-05-1.h3", 0x020000, 0xce21bda5, 1 | BRF_PRG | BRF_ESS }, // 5 + { "go-00.f1", 0x020000, 0xa93369ea, 1 | BRF_PRG | BRF_ESS }, // 6 + { "go-04.f3", 0x020000, 0xee2f6ad9, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "gp-09.k13", 0x010000, 0x4a4e0f8d, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gp10-1.y6", 0x010000, 0xd25d719c, 3 | BRF_GRA }, // 9 Characters + { "gp11-1.z6", 0x010000, 0x030ded47, 3 | BRF_GRA }, // 10 + + { "mah-04.z4", 0x080000, 0x9b6ca18c, 4 | BRF_GRA }, // 11 Foreground Tiles + { "mah-03.y4", 0x080000, 0x37894ddc, 4 | BRF_GRA }, // 12 + + { "mah-01.z1", 0x080000, 0x26e0dfff, 5 | BRF_GRA }, // 13 Background Tiles + { "mah-00.y1", 0x080000, 0x7bd69e41, 5 | BRF_GRA }, // 14 + { "mah-02.a1", 0x080000, 0x328a247d, 5 | BRF_GRA }, // 15 + + { "mah-05.y9", 0x080000, 0x6773e613, 6 | BRF_GRA }, // 16 Sprites + { "mah-08.y12", 0x080000, 0x88d310a5, 6 | BRF_GRA }, // 17 + { "mah-06.z9", 0x080000, 0x27a8808a, 6 | BRF_GRA }, // 18 + { "mah-09.z12", 0x080000, 0xa58c43a7, 6 | BRF_GRA }, // 19 + { "mah-07.a9", 0x080000, 0x526f4190, 6 | BRF_GRA }, // 20 + { "mah-10.a12", 0x080000, 0x14b770da, 6 | BRF_GRA }, // 21 + + { "gp-08.j13", 0x020000, 0x365183b1, 7 | BRF_SND }, // 22 OKI M6295 Samples 0 + + { "mah-11.f13", 0x080000, 0x642bc692, 8 | BRF_SND }, // 23 OKI M6295 Samples 1 + + { "go-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 24 Unused PROMs +}; + +STD_ROM_PICK(robocop2u) +STD_ROM_FN(robocop2u) + +struct BurnDriver BurnDrvRobocop2u = { + "robocop2u", "robocop2", NULL, NULL, "1991", + "Robocop 2 (US v0.05)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, robocop2uRomInfo, robocop2uRomName, NULL, NULL, Robocop2InputInfo, Robocop2DIPInfo, + Robocop2Init, DrvExit, CninjaFrame, Robocop2Draw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Robocop 2 (Japan v0.11) + +static struct BurnRomInfo robocop2jRomDesc[] = { + { "go-03-1.k1", 0x020000, 0x52506608, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "go-07-1.k3", 0x020000, 0x739cda17, 1 | BRF_PRG | BRF_ESS }, // 1 + { "go-02-1.j1", 0x020000, 0x48c0ace9, 1 | BRF_PRG | BRF_ESS }, // 2 + { "go-06-1.j3", 0x020000, 0x41abec87, 1 | BRF_PRG | BRF_ESS }, // 3 + { "go-01-1.h1", 0x020000, 0xab5356c0, 1 | BRF_PRG | BRF_ESS }, // 4 + { "go-05-1.h3", 0x020000, 0xce21bda5, 1 | BRF_PRG | BRF_ESS }, // 5 + { "go-00.f1", 0x020000, 0xa93369ea, 1 | BRF_PRG | BRF_ESS }, // 6 + { "go-04.f3", 0x020000, 0xee2f6ad9, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "gp-09.k13", 0x010000, 0x4a4e0f8d, 2 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gp10-1.y6", 0x010000, 0xd25d719c, 3 | BRF_GRA }, // 9 Characters + { "gp11-1.z6", 0x010000, 0x030ded47, 3 | BRF_GRA }, // 10 + + { "mah-04.z4", 0x080000, 0x9b6ca18c, 4 | BRF_GRA }, // 11 Foreground Tiles + { "mah-03.y4", 0x080000, 0x37894ddc, 4 | BRF_GRA }, // 12 + + { "mah-01.z1", 0x080000, 0x26e0dfff, 5 | BRF_GRA }, // 13 Background Tiles + { "mah-00.y1", 0x080000, 0x7bd69e41, 5 | BRF_GRA }, // 14 + { "mah-02.a1", 0x080000, 0x328a247d, 5 | BRF_GRA }, // 15 + + { "mah-05.y9", 0x080000, 0x6773e613, 6 | BRF_GRA }, // 16 Sprites + { "mah-08.y12", 0x080000, 0x88d310a5, 6 | BRF_GRA }, // 17 + { "mah-06.z9", 0x080000, 0x27a8808a, 6 | BRF_GRA }, // 18 + { "mah-09.z12", 0x080000, 0xa58c43a7, 6 | BRF_GRA }, // 19 + { "mah-07.a9", 0x080000, 0x526f4190, 6 | BRF_GRA }, // 20 + { "mah-10.a12", 0x080000, 0x14b770da, 6 | BRF_GRA }, // 21 + + { "gp-08.j13", 0x020000, 0x365183b1, 7 | BRF_SND }, // 22 OKI M6295 Samples 0 + + { "mah-11.f13", 0x080000, 0x642bc692, 8 | BRF_SND }, // 23 OKI M6295 Samples 1 + + { "go-12.v7", 0x000400, 0x278f674f, 0 | BRF_OPT }, // 24 Unused PROMs +}; + +STD_ROM_PICK(robocop2j) +STD_ROM_FN(robocop2j) + +struct BurnDriver BurnDrvRobocop2j = { + "robocop2j", "robocop2", NULL, NULL, "1991", + "Robocop 2 (Japan v0.11)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, robocop2jRomInfo, robocop2jRomName, NULL, NULL, Robocop2InputInfo, Robocop2DIPInfo, + Robocop2Init, DrvExit, CninjaFrame, Robocop2Draw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_crospang.cpp b/src/burn/drivers/misc_post90s/d_crospang.cpp new file mode 100644 index 00000000..dd3205a3 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_crospang.cpp @@ -0,0 +1,787 @@ +// FB Alpha Cross Pang driver module +// Based on MAME driver by Pierpaolo Prazzoli and David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym3812.h" + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvSprRAM; +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; +static UINT8 *tile_bank; +static UINT16 *fg_scroll_x; +static UINT16 *fg_scroll_y; +static UINT16 *bg_scroll_x; +static UINT16 *bg_scroll_y; + +static UINT8 DrvRecalc; + +static INT32 bestri = 0; + +static struct BurnInputInfo CrospangInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 9, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Crospang) + +static struct BurnDIPInfo CrospangDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x7e, NULL }, + {0x12, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x11, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Number of Powers" }, + {0x11, 0x01, 0x20, 0x00, "1" }, + {0x11, 0x01, 0x20, 0x20, "2" }, + + {0 , 0xfe, 0 , 4, "Extra Balls" }, + {0x11, 0x01, 0xc0, 0xc0, "1" }, + {0x11, 0x01, 0xc0, 0x80, "2" }, + {0x11, 0x01, 0xc0, 0x40, "3" }, + {0x11, 0x01, 0xc0, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Minimum Balls per Row"}, + {0x12, 0x01, 0x18, 0x18, "3" }, + {0x12, 0x01, 0x18, 0x10, "4" }, + {0x12, 0x01, 0x18, 0x08, "5" }, + {0x12, 0x01, 0x18, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Crospang) + +static struct BurnDIPInfo HeuksunDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x11, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Heuksun) + +static struct BurnDIPInfo BestriDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfb, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x11, 0x01, 0x06, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x06, 0x04, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x06, 0x02, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x06, 0x06, "1 Coin 2 Credits" }, +}; + +STDDIPINFO(Bestri) + +void __fastcall crospang_write_byte(UINT32 address, UINT8 data) +{ + if (bestri == 0) return; + + switch (address) + { + case 0x10000e: + *tile_bank = (data >> 2) & 0x0f; + return; + } +} + +void __fastcall crospang_write_word(UINT32 address, UINT16 data) +{ + if (bestri == 0) { + switch (address) + { + case 0x100002: + *fg_scroll_y = (data + 8) & 0x1ff; + return; + + case 0x100004: + *bg_scroll_x = (data + 4) & 0x1ff; + return; + + case 0x100006: + *bg_scroll_y = (data + 8) & 0x1ff; + return; + + case 0x100008: + *fg_scroll_x = (data + 0) & 0x1ff; + return; + + case 0x270000: + *soundlatch = data & 0xff; + return; + } + } else { + switch (address) + { + case 0x100004: + *fg_scroll_x = ((data ^ 0x0000) + 32) & 0x1ff; + return; + + case 0x100006: + *fg_scroll_y = ((data ^ 0xff54) + 7) & 0x1ff; + return; + + case 0x10000a: + *bg_scroll_y = ((data ^ 0xfeaa) + 7) & 0x1ff; + return; + + case 0x10000c: + *bg_scroll_x = ((data ^ 0x0000) - 60) & 0x1ff; + return; + + case 0x270000: + *soundlatch = data & 0xff; + return; + } + } +} + +UINT8 __fastcall crospang_read_byte(UINT32 address) +{ + switch (address) + { + case 0x280002: + return DrvInputs[1] >> 8; + } + + return 0; +} + +UINT16 __fastcall crospang_read_word(UINT32 address) +{ + switch (address) + { + case 0x280000: + case 0x280002: + case 0x280004: + return DrvInputs[(address >> 1) & 3]; + } + + return 0; +} + +void __fastcall crospang_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM3812Write(0, data); + return; + + case 0x01: + BurnYM3812Write(1, data); + return; + + case 0x02: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall crospang_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return BurnYM3812Read(0); + + case 0x02: + return MSM6295ReadStatus(0); + + case 0x06: + return *soundlatch; + } + + return 0; +} + +inline static INT32 crospangSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3579545); +} + +void crospangYM3812IrqHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + MSM6295Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x000800; + DrvBgRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + tile_bank = Next; Next += 0x000001; + + fg_scroll_x = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + bg_scroll_x = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + fg_scroll_y = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + bg_scroll_y = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode(INT32 gfx0len, INT32 gfx1len, INT32 type) +{ + INT32 Plane0[4] = { ((gfx0len / 2) * 8) + 8, ((gfx0len / 2) * 8) + 0, 8, 0 }; + INT32 Plane1[4] = { ((gfx1len / 2) * 8) + 8, ((gfx1len / 2) * 8) + 0, 8, 0 }; + INT32 XOffs[16] = { 32*8+0, 32*8+1, 32*8+2, 32*8+3, 32*8+4, 32*8+5, 32*8+6, 32*8+7, + 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, + 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(((gfx0len - 1) | (gfx1len - 1)) + 1); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < gfx0len; i++) { // rearrange tiles a bit + INT32 k = (type) ? (((i & 0x40000) << 2) | ((i & 0x180000) >> 1) | (i & 0x3ffff)) : i; + tmp[k ^ (gfx0len/2) ^ 0x20] = DrvGfxROM0[i]; + } + + GfxDecode((gfx0len * 2) / (16 * 16), 4, 16, 16, Plane0, XOffs, YOffs, 0x200, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, gfx1len); + + GfxDecode((gfx1len * 2) / (16 * 16), 4, 16, 16, Plane1, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 crospangLoadRoms() +{ + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100001, 9, 2)) return 1; + + DrvGfxDecode(0x80000, 0x200000, 0); + + return 0; +} + +static INT32 heuksunLoadRoms() +{ + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080001, 9, 2)) return 1; + + DrvGfxDecode(0x200000, 0x100000, 1); + + return 0; +} + +static INT32 bestriLoadRoms() +{ + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100001, 7, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100001, 11, 2)) return 1; + + DrvGfxDecode(0x200000, 0x200000, 1); + + return 0; +} + +static INT32 DrvInit(INT32 (*pRomLoadCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 5, 2)) return 1; + + if (pRomLoadCallback) { + if (pRomLoadCallback()) return 1; + } + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvFgRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x122000, 0x1227ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x200000, 0x2005ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x210000, 0x2107ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x320000, 0x32ffff, SM_RAM); // crospang, heuksun + SekMapMemory(Drv68KRAM, 0x3a0000, 0x3affff, SM_RAM); // bestri + SekSetWriteByteHandler(0, crospang_write_byte); + SekSetWriteWordHandler(0, crospang_write_word); + SekSetReadByteHandler(0, crospang_read_byte); + SekSetReadWordHandler(0, crospang_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetSetOutHandler(crospang_sound_out); + ZetSetInHandler(crospang_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(3579545, &crospangYM3812IrqHandler, crospangSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + MSM6295Init(0, 1056000 / 132, 80.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + bestri = 0; + + return 0; +} + +static void draw_layer(UINT8 *src, INT32 coloffs, INT32 scrollx, INT32 scrolly, INT32 transp) +{ + UINT16 *vram = (UINT16*)src; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x200; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 data = vram[offs]; + INT32 code = (data & 0xfff) + (*tile_bank << 12); + INT32 color = (data >> 12) + coloffs; + + if (transp) { + if (!(code&0xfff)) continue; + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0;offs < 0x400;offs += 4) + { + INT32 sprite = ram[offs + 1] & 0x7fff; + if (!sprite) continue; + + INT32 y = ram[offs]; + if ((y & 0x1000) && (GetCurrentFrame() & 1)) continue; // flash + + INT32 x = ram[offs + 2]; + INT32 color = (x >>9) & 0xf; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x &= 0x01ff; + y &= 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + y = (240 - y) - 7; + x = (304 - x) - 5; + + INT32 inc = -1; + + if (!fy) + { + sprite += multi; + inc = 1; + } + + while (multi >= 0) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite - multi * inc, x, y - 16 * multi, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite - multi * inc, x, y - 16 * multi, color, 4, 0, 0, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite - multi * inc, x, y - 16 * multi, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite - multi * inc, x, y - 16 * multi, color, 4, 0, 0, DrvGfxROM1); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x300; i++) { + r = (pal[i] >> 10) & 0x1f; + g = (pal[i] >> 5) & 0x1f; + b = (pal[i] >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + draw_layer(DrvBgRAM, 0x20, *bg_scroll_x, *bg_scroll_y, 0); + draw_layer(DrvFgRAM, 0x10, *fg_scroll_x, *fg_scroll_y, 1); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = 0xffff; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[2] = (DrvDips[1] << 8) | DrvDips[0]; + } + + INT32 nTotalCycles[2] = { 7159090 / 60, 3579545 / 60 }; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + SekRun(nTotalCycles[0]); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnTimerEndFrameYM3812(nTotalCycles[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Cross Pang + +static struct BurnRomInfo crospangRomDesc[] = { + { "p1.bin", 0x20000, 0x0bcbbaad, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "p2.bin", 0x20000, 0x0947d204, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "s1.bin", 0x10000, 0xd61a224c, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "s2.bin", 0x20000, 0x9f9ecd22, 3 | BRF_SND }, // 3 Oki Samples + + { "rom1.bin", 0x40000, 0x905042bb, 4 | BRF_GRA }, // 4 Background Tiles + { "rom2.bin", 0x40000, 0xbc4381e9, 4 | BRF_GRA }, // 5 + + { "rom3.bin", 0x80000, 0xcc6e1fce, 5 | BRF_GRA }, // 6 Sprites + { "rom4.bin", 0x80000, 0x9a91d494, 5 | BRF_GRA }, // 7 + { "rom5.bin", 0x80000, 0x53a34dc5, 5 | BRF_GRA }, // 8 + { "rom6.bin", 0x80000, 0x9c633082, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(crospang) +STD_ROM_FN(crospang) + +static INT32 crospangInit() +{ + return DrvInit(crospangLoadRoms); +} + +struct BurnDriver BurnDrvCrospang = { + "crospang", NULL, NULL, NULL, "1998", + "Cross Pang\0", NULL, "F2 System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, crospangRomInfo, crospangRomName, NULL, NULL, CrospangInputInfo, CrospangDIPInfo, + crospangInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Heuk Sun Baek Sa (Korea) + +static struct BurnRomInfo heuksunRomDesc[] = { + { "ua02.j3", 0x80000, 0xdb2b9c8e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ua03.j5", 0x80000, 0xde9f01e8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "us02.r4", 0x10000, 0xc7cc05fa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "us08.u7", 0x40000, 0xae177589, 3 | BRF_SND }, // 3 Oki Samples + + { "uc07.t11", 0x80000, 0x4d1ed885, 4 | BRF_GRA }, // 4 Background Tiles + { "uc08.r11", 0x80000, 0x242cee69, 4 | BRF_GRA }, // 5 + + { "ud14.p11", 0x40000, 0x4fc2b574, 5 | BRF_GRA }, // 6 Sprites + { "ud15.m11", 0x40000, 0x1d6187a6, 5 | BRF_GRA }, // 7 + { "ud16.l11", 0x40000, 0xeabec43e, 5 | BRF_GRA }, // 8 + { "ud17.j11", 0x40000, 0xc6b04171, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(heuksun) +STD_ROM_FN(heuksun) + +static INT32 heuksunInit() +{ + return DrvInit(heuksunLoadRoms); +} + +struct BurnDriver BurnDrvHeuksun = { + "heuksun", NULL, NULL, NULL, "199?", + "Heuk Sun Baek Sa (Korea)\0", NULL, "Oksan / F2 System", "Miscellaneous", + L"\uD751\uC120\uBC31\uC0AC (Korea)\0Heuk Sun Baek Sa\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, heuksunRomInfo, heuksunRomName, NULL, NULL, CrospangInputInfo, HeuksunDIPInfo, + heuksunInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Bestri (Korea) + +static struct BurnRomInfo bestriRomDesc[] = { + { "ua02.i3", 0x80000, 0x9e94023d, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ua03.i5", 0x80000, 0x08cfa8d8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "us02.p3", 0x10000, 0xc7cc05fa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "us08.q7", 0x40000, 0x85d8f3de, 3 | BRF_SND }, // 3 Oki Samples + + { "uc07 p12", 0x80000, 0x3d299954, 4 | BRF_GRA }, // 4 Background Tiles + { "uc08.m12", 0x80000, 0x2fc0c30e, 4 | BRF_GRA }, // 5 + { "uc29.k12", 0x80000, 0x0260c321, 4 | BRF_GRA }, // 6 + { "uc28.n12", 0x80000, 0x9938be27, 4 | BRF_GRA }, // 7 + + { "ud14.j12", 0x80000, 0x141c696e, 5 | BRF_GRA }, // 8 Sprites + { "ud15.h12", 0x80000, 0x7c04adc0, 5 | BRF_GRA }, // 9 + { "ud16.g12", 0x80000, 0x3282ea76, 5 | BRF_GRA }, // 10 + { "ud17.e12", 0x80000, 0x3a3a3f1a, 5 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(bestri) +STD_ROM_FN(bestri) + +static INT32 bestriInit() +{ + bestri = 1; + + return DrvInit(bestriLoadRoms); +} + +struct BurnDriver BurnDrvBestri = { + "bestri", NULL, NULL, NULL, "1998", + "Bestri (Korea)\0", NULL, "F2 System", "Miscellaneous", + L"Bestri\0\uBCA0\uC2A4\uD2B8\uB77C\uC774 (Korea)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, bestriRomInfo, bestriRomName, NULL, NULL, CrospangInputInfo, BestriDIPInfo, + bestriInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_crshrace.cpp b/src/burn/drivers/misc_post90s/d_crshrace.cpp new file mode 100644 index 00000000..45ba5880 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_crshrace.cpp @@ -0,0 +1,887 @@ +// FB Alpha Lethal Crash Race driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2610.h" + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[4]; +static UINT16 DrvInputs[6]; +static UINT8 DrvReset; + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvVidRAM2; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSprRAM2; +static UINT8 *DrvSprBuf1a; +static UINT8 *DrvSprBuf2a; +static UINT8 *DrvSprBuf1b; +static UINT8 *DrvSprBuf2b; +static UINT8 *DrvZ80RAM; +static UINT16 *DrvGfxCtrl; +static UINT16 *DrvBgTmp; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 *nSoundBank; +static UINT8 *pending_command; +static UINT8 *roz_bank; +static UINT8 *gfx_priority; +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static struct BurnInputInfo CrshraceInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 11, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 9, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 12, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy1 + 10, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p3 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 15, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 14, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Region", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(Crshrace) + +static struct BurnDIPInfo CrshraceDIPList[]= +{ + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xff, NULL }, + {0x20, 0xff, 0xff, 0xff, NULL }, + {0x21, 0xff, 0xff, 0x01, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x1e, 0x01, 0x01, 0x01, "Off" }, +// {0x1e, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1e, 0x01, 0x02, 0x00, "Off" }, + {0x1e, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x1e, 0x01, 0x04, 0x04, "Off" }, + {0x1e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1e, 0x01, 0x08, 0x08, "Off" }, + {0x1e, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1e, 0x01, 0xc0, 0x80, "Easy" }, + {0x1e, 0x01, 0xc0, 0xc0, "Normal" }, + {0x1e, 0x01, 0xc0, 0x40, "Hard" }, + {0x1e, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coin Slot" }, + {0x1f, 0x01, 0x01, 0x01, "Same" }, + {0x1f, 0x01, 0x01, 0x00, "Individual" }, + + // Coinage condition: Coin Slot Individual + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x1f, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + {0x1f, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x1f, 0x00, 0x01, 0x00, NULL}, + + // Coin A condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x1f, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + + // Coin B condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x1f, 0x02, 0x70, 0x50, "3 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x40, "1 Coin 2 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x30, "1 Coin 3 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x20, "1 Coin 4 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x10, "1 Coin 5 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + {0x1f, 0x02, 0x70, 0x00, "1 Coin 6 Credits" }, + {0x1f, 0x00, 0x01, 0x01, NULL}, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x1f, 0x01, 0x80, 0x80, "Off" }, + {0x1f, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Reset on P.O.S.T. Error" }, + {0x20, 0x01, 0x80, 0x00, "No" }, + {0x20, 0x01, 0x80, 0x80, "Yes" }, + + {0 , 0xfe, 0 , 5, "Country" }, + {0x21, 0x01, 0x0f, 0x01, "World" }, + {0x21, 0x01, 0x0f, 0x08, "USA & Canada" }, + {0x21, 0x01, 0x0f, 0x00, "Japan" }, + {0x21, 0x01, 0x0f, 0x02, "Korea" }, + {0x21, 0x01, 0x0f, 0x04, "Hong Kong & Taiwan" }, +}; + +STDDIPINFO(Crshrace) + +static void crshrace_drawtile(INT32 offset) +{ + INT32 sx = (offset & 0x3f) << 4; + INT32 sy = (offset >> 6) << 4; + + INT32 code = *((UINT16*)(DrvVidRAM1 + (offset << 1))); + INT32 color = code >> 12; + code = (code & 0xfff) | (*roz_bank << 12); + color = (color << 4) | 0x100; + + UINT8 *src = DrvGfxROM1 + (code << 8); + UINT16 *dst = DrvBgTmp + (sy << 10) + sx; + + for (INT32 y = 0; y < 16; y++) { + for (INT32 x = 0; x < 16; x++) { + INT32 pxl = *src++; + if (pxl == 0x0f) pxl = ~0; + + dst[x] = pxl | color; + } + dst += 1024; + } +} + +void __fastcall crshrace_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0xfff020 && address <= 0xfff03f) { // K053936_0_ctrl + DrvGfxCtrl[(address & 0x1f)/2] = data; + return; + } + + if ((address & 0xfffe000) == 0xd00000) { + *((UINT16*)(DrvVidRAM1 + (address & 0x1ffe))) = data; + crshrace_drawtile((address & 0x1ffe)/2); + return; + } +} + +void __fastcall crshrace_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffe000) == 0xd00000) { + DrvVidRAM1[(address & 0x1fff) ^ 1] = data; + crshrace_drawtile((address & 0x1ffe)/2); + return; + } + + switch (address) + { + case 0xffc001: + *roz_bank = data; + return; + + case 0xfff001: + *gfx_priority = data & 0xdf; + *flipscreen = data & 0x20; + return; + + case 0xfff009: + *pending_command = 1; + *soundlatch = data; + ZetNmi(); + return; + } +} + +UINT16 __fastcall crshrace_read_word(UINT32) +{ + return 0; +} + +UINT8 __fastcall crshrace_read_byte(UINT32 address) +{ + switch (address) + { + case 0xfff000: + return DrvInputs[0] >> 8; + + case 0xfff001: + return DrvInputs[0]; + + case 0xfff002: + return DrvInputs[1] >> 8; + + case 0xfff003: + return DrvInputs[1]; + + case 0xfff004: + return DrvDips[1]; + + case 0xfff005: + return DrvDips[0]; + + case 0xfff00b: + return DrvDips[2]; + + case 0xfff00f: + return DrvInputs[2]; + + case 0xfff006: + return DrvDips[3] | (*pending_command << 7); + } + + return 0; +} + +static void sound_bankswitch(INT32 bank) +{ + *nSoundBank = bank & 0x03; + INT32 nBank = (*nSoundBank & 0x03) << 15; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + nBank); +} + +void __fastcall crshrace_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + sound_bankswitch(data); + return; + + case 0x04: + *pending_command = 0; + return; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + BurnYM2610Write(port & 3, data); + return; + } +} + +UINT8 __fastcall crshrace_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x04: + return *soundlatch; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + return BurnYM2610Read(port & 3); + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x300000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x800000; + DrvGfxROM2 = Next; Next += 0x800000; + + DrvSndROM = Next; Next += 0x200000; + + DrvPalette = (UINT32 *)Next; Next += 0x000401 * sizeof(UINT32); + DrvBgTmp = (UINT16*)Next; Next += 0x100000 * sizeof(UINT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x001000; + DrvVidRAM1 = Next; Next += 0x002000; + DrvVidRAM2 = Next; Next += 0x001000; + + DrvSprRAM1 = Next; Next += 0x002000; + DrvSprRAM2 = Next; Next += 0x010000; + + DrvSprBuf1a = Next; Next += 0x002000; + DrvSprBuf2a = Next; Next += 0x010000; + DrvSprBuf1b = Next; Next += 0x002000; + DrvSprBuf2b = Next; Next += 0x010000; + + DrvZ80RAM = Next; Next += 0x000800; + + nSoundBank = Next; Next += 0x000001; + roz_bank = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + gfx_priority = Next; Next += 0x000001; + pending_command = Next; Next += 0x000001; + + DrvGfxCtrl = (UINT16*)Next; Next += 0x000010 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + memset (DrvBgTmp, 0xff, 0x200000); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2610Reset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[8] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x004, 0x000, 0x00c, 0x008, 0x014, 0x010, 0x01c, 0x018, + 0x024, 0x020, 0x02c, 0x028, 0x034, 0x030, 0x03c, 0x038 }; + INT32 YOffs[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x300000; i++) { + tmp[i^1] = (DrvGfxROM1[i] << 4) | (DrvGfxROM1[i] >> 4); + } + + GfxDecode(0x6000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x400000); + + GfxDecode(0x8000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x0000000, 0, 1)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0100000, 1, 1)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0200000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 9, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 10, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x0100000, 11, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KROM + 0x100000, 0x300000, 0x3fffff, SM_ROM); + SekMapMemory(Drv68KROM + 0x200000, 0x400000, 0x4fffff, SM_ROM); + SekMapMemory(Drv68KROM + 0x200000, 0x500000, 0x5fffff, SM_ROM); + SekMapMemory(DrvSprRAM2, 0xa00000, 0xa0ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xd00000, 0xd01fff, SM_ROM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe01fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xfe0000, 0xfeffff, SM_RAM); + SekMapMemory(DrvVidRAM2, 0xffd000, 0xffdfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xffe000, 0xffefff, SM_RAM); + SekSetWriteWordHandler(0, crshrace_write_word); + SekSetWriteByteHandler(0, crshrace_write_byte); + SekSetReadWordHandler(0, crshrace_read_word); + SekSetReadByteHandler(0, crshrace_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x77ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x77ff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + 0x10000); + ZetMapArea(0x8000, 0xffff, 1, DrvZ80ROM + 0x10000); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + 0x10000); + ZetSetOutHandler(crshrace_sound_out); + ZetSetInHandler(crshrace_sound_in); + ZetMemEnd(); + ZetClose(); + + INT32 DrvSndROMLen = 0x100000; + BurnYM2610Init(8000000, DrvSndROM + 0x100000, &DrvSndROMLen, DrvSndROM, &DrvSndROMLen, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2610Exit(); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + INT32 offs = 0; + UINT16 *sprbuf1 = (UINT16*)DrvSprBuf1a; + UINT16 *sprbuf2 = (UINT16*)DrvSprBuf2a; + + static const INT32 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; + + while (offs < 0x0400 && (sprbuf1[offs] & 0x4000) == 0) + { + INT32 attr_start = 4 * (sprbuf1[offs++] & 0x03ff); + + INT32 ox = sprbuf1[attr_start + 1] & 0x01ff; + INT32 xsize = (sprbuf1[attr_start + 1] & 0x0e00) >> 9; + INT32 zoomx = (sprbuf1[attr_start + 1] & 0xf000) >> 12; + INT32 oy = sprbuf1[attr_start + 0] & 0x01ff; + INT32 ysize = (sprbuf1[attr_start + 0] & 0x0e00) >> 9; + INT32 zoomy = (sprbuf1[attr_start + 0] & 0xf000) >> 12; + INT32 flipx = sprbuf1[attr_start + 2] & 0x4000; + INT32 flipy = sprbuf1[attr_start + 2] & 0x8000; + INT32 color = (sprbuf1[attr_start + 2] & 0x1f00) >> 8; + INT32 map_start = sprbuf1[attr_start + 3] & 0x7fff; + + zoomx = 16 - zoomtable[zoomx]/8; + zoomy = 16 - zoomtable[zoomy]/8; + + if (sprbuf1[attr_start + 2] & 0x20ff) color = 1; // what?? mame_rand? why? + + for (INT32 y = 0;y <= ysize;y++) + { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y) + 16) & 0x1ff) - 16; + else sy = ((oy + zoomy * y + 16) & 0x1ff) - 16; + + for (INT32 x = 0;x <= xsize;x++) + { + if (flipx) + sx = ((ox + zoomx * (xsize - x) + 16) & 0x1ff) - 16; + else + sx = ((ox + zoomx * x + 16) & 0x1ff) - 16; + + INT32 code = sprbuf2[map_start & 0x7fff] & 0x7fff; + map_start++; + + RenderZoomedTile(pTransDraw, DrvGfxROM2, code, (color << 4) | 0x200, 0x0f, sx, sy, flipx, flipy, 16, 16, zoomx << 12, zoomy << 12); + } + } + } +} + +static void draw_background() +{ + UINT16 *vram = (UINT16*)DrvVidRAM2; + + for (INT32 offs = 0; offs < 64*28; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + if (sx >= 320) continue; + + INT32 sy = (offs >> 6) << 3; + + INT32 code = vram[offs] & 0x3fff; + if (code == 0) continue; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, 0, 4, 0xff, 0, DrvGfxROM0); + } +} + +static inline void copy_roz(UINT32 startx, UINT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy) +{ + UINT16 *dst = pTransDraw; + UINT16 *src = DrvBgTmp; + + for (INT32 sy = 0; sy < nScreenHeight; sy++, startx+=incyx, starty+=incyy) + { + UINT32 cx = startx; + UINT32 cy = starty; + + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) + { + INT32 p = src[(((cy >> 16) & 0x3ff) * 1024) + ((cx >> 16) & 0x3ff)]; + + if (p != 0xffff) { + *dst = p; + } + } + } +} + +static void draw_foreground() +{ + UINT16 *ctrl = DrvGfxCtrl; + + UINT32 startx,starty; + INT32 incxx,incxy,incyx,incyy; + + startx = 256 * (INT16)(ctrl[0x00]); + starty = 256 * (INT16)(ctrl[0x01]); + incyx = (INT16)(ctrl[0x02]); + incyy = (INT16)(ctrl[0x03]); + incxx = (INT16)(ctrl[0x04]); + incxy = (INT16)(ctrl[0x05]); + + if (ctrl[0x06] & 0x4000) { incyx *= 256; incyy *= 256; } + if (ctrl[0x06] & 0x0040) { incxx *= 256; incxy *= 256; } + + startx -= -21 * incyx; + starty -= -21 * incyy; + + startx -= -48 * incxx; + starty -= -48 * incxy; + + copy_roz(startx << 5, starty << 5, incxx << 5, incxy << 5, incyx << 5, incyy << 5); +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x400; i++) { + r = (p[i] >> 0) & 0x1f; + g = (p[i] >> 10) & 0x1f; + b = (p[i] >> 5) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + DrvPalette[0x400] = 0; + } + + if (*gfx_priority & 0x04) + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x400; + } + + BurnTransferCopy(DrvPalette); + + return 0; + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x01ff; + } + + switch (*gfx_priority & 0xfb) + { + case 0x00: + draw_sprites(); + draw_background(); + draw_foreground(); + break; + + case 0x01: + case 0x02: + draw_background(); + draw_foreground(); + draw_sprites(); + break; + + default: + break; + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 6 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[3] = (DrvDips[0]) | (DrvDips[1] << 8); + DrvInputs[4] = DrvDips[2]; + DrvInputs[5] = (DrvDips[3] << 8); + } + + INT32 nCyclesTotal[2] = { 16000000 / 60, 4000000 / 60 }; + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + // double buffer sprites + memcpy (DrvSprBuf1b, DrvSprBuf1a, 0x002000); + memcpy (DrvSprBuf1a, DrvSprRAM1, 0x002000); + memcpy (DrvSprBuf2b, DrvSprBuf2a, 0x010000); + memcpy (DrvSprBuf2a, DrvSprRAM2, 0x010000); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + for (INT32 i = 0; i < 0x1000; i++) { + crshrace_drawtile(i); + } + + ZetOpen(0); + sound_bankswitch(*nSoundBank); + ZetClose(); + } + + return 0; +} + + +// Lethal Crash Race (set 1) + +static struct BurnRomInfo crshraceRomDesc[] = { + { "1", 0x080000, 0x21e34fb7, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "w21", 0x100000, 0xa5df7325, 1 | BRF_PRG | BRF_ESS }, // 1 + { "w22", 0x100000, 0xfc9d666d, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "2", 0x020000, 0xe70a900f, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 Code + + { "h895", 0x100000, 0x36ad93c3, 3 | BRF_GRA }, // 4 Background Tiles + + { "w18", 0x100000, 0xb15df90d, 4 | BRF_GRA }, // 5 Foreground Tiles + { "w19", 0x100000, 0x28326b93, 4 | BRF_GRA }, // 6 + { "w20", 0x100000, 0xd4056ad1, 4 | BRF_GRA }, // 7 + + { "h897", 0x200000, 0xe3230128, 5 | BRF_GRA }, // 8 Sprites + { "h896", 0x200000, 0xfff60233, 5 | BRF_GRA }, // 9 + + { "h894", 0x100000, 0xd53300c1, 6 | BRF_SND }, // 10 YM2610 Samples + { "h893", 0x100000, 0x32513b63, 6 | BRF_SND }, // 11 +}; + +STD_ROM_PICK(crshrace) +STD_ROM_FN(crshrace) + +struct BurnDriver BurnDrvCrshrace = { + "crshrace", NULL, NULL, NULL, "1993", + "Lethal Crash Race (set 1)\0", NULL, "Video System Co.", "Miscellaneous", + L"Lethal Crash Race\0\u7206\u70C8 \u30AF\u30E9\u30C3\u30B7\u30E5 \u30EC\u30FC\u30B9 (set 1)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, crshraceRomInfo, crshraceRomName, NULL, NULL, CrshraceInputInfo, CrshraceDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x401, + 224, 320, 3, 4 +}; + + +// Lethal Crash Race (set 2) + +static struct BurnRomInfo crshrace2RomDesc[] = { + { "01-ic10.bin", 0x080000, 0xb284aacd, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "w21", 0x100000, 0xa5df7325, 1 | BRF_PRG | BRF_ESS }, // 1 + { "w22", 0x100000, 0xfc9d666d, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "2", 0x020000, 0xe70a900f, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 Code + + { "h895", 0x100000, 0x36ad93c3, 3 | BRF_GRA }, // 4 Background Tiles + + { "w18", 0x100000, 0xb15df90d, 4 | BRF_GRA }, // 5 Foreground Tiles + { "w19", 0x100000, 0x28326b93, 4 | BRF_GRA }, // 6 + { "w20", 0x100000, 0xd4056ad1, 4 | BRF_GRA }, // 7 + + { "h897", 0x200000, 0xe3230128, 5 | BRF_GRA }, // 8 Sprites + { "h896", 0x200000, 0xfff60233, 5 | BRF_GRA }, // 9 + + { "h894", 0x100000, 0xd53300c1, 6 | BRF_SND }, // 10 YM2610 Samples + { "h893", 0x100000, 0x32513b63, 6 | BRF_SND }, // 11 +}; + +STD_ROM_PICK(crshrace2) +STD_ROM_FN(crshrace2) + +struct BurnDriver BurnDrvCrshrace2 = { + "crshrace2", "crshrace", NULL, NULL, "1993", + "Lethal Crash Race (set 2)\0", NULL, "Video System Co.", "Miscellaneous", + L"Lethal Crash Race\0\u7206\u70C8 \u30AF\u30E9\u30C3\u30B7\u30E5 \u30EC\u30FC\u30B9 (set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, crshrace2RomInfo, crshrace2RomName, NULL, NULL, CrshraceInputInfo, CrshraceDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x401, + 224, 320, 3, 4 +}; + diff --git a/src/burn/drivers/misc_post90s/d_darkseal.cpp b/src/burn/drivers/misc_post90s/d_darkseal.cpp new file mode 100644 index 00000000..1d842616 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_darkseal.cpp @@ -0,0 +1,872 @@ +// FB Alpha Dark Seal driver module +// Based on MAME driver by Bryan McPhail + +// To do: +// Add support for the Huc6280 & set up the sound hardware + +#include "tiles_generic.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvH6280ROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *Drv68KRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPf3RAM; +static UINT8 *DrvPf2RAM; +static UINT8 *DrvPf1RAM; +static UINT8 *DrvPf12RowRAM; +static UINT8 *DrvPf34RowRAM; +static UINT8 *DrvPfCtrlRAM0; +static UINT8 *DrvPfCtrlRAM1; +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDip[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 DrvRecalc = 0; +static INT32 vblank = 0; + +static struct BurnInputInfo DarksealInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Darkseal) + +static struct BurnDIPInfo DarksealDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x07, 0x01, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x38, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x38, 0x08, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "1" }, + {0x12, 0x01, 0x03, 0x01, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x12, 0x01, 0x30, 0x00, "2" }, + {0x12, 0x01, 0x30, 0x10, "2.5" }, + {0x12, 0x01, 0x30, 0x30, "3" }, + {0x12, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x12, 0x01, 0x40, 0x00, "No" }, + {0x12, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Darkseal) + +static inline void palette_write(INT32 offset) +{ + UINT16 *data = (UINT16*)(DrvPalRAM + offset); + UINT8 r,g,b; + + r = (data[0x0000/2] >> 0) & 0xff; + g = (data[0x0000/2] >> 8) & 0xff; + b = (data[0x1000/2] >> 0) & 0xff; + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall darkseal_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffff0) == 0x180000) { + switch (address & 0x0e) + { + case 0x06: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x08: + *soundlatch = data; + return; + } + + return; + } +} + +void __fastcall darkseal_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff0) == 0x180000) { + switch (address & 0x0f) + { + case 0x06: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x08: + *soundlatch = data & 0xff; + return; + } + + return; + } + + if ((address & 0xfffff0) == 0x240000) { + *((UINT16*)(DrvPfCtrlRAM0 + (address & 0x0e))) = data; + return; + } + + if ((address & 0xfffff0) == 0x2a0000) { + *((UINT16*)(DrvPfCtrlRAM1 + (address & 0x0e))) = data; + return; + } +} + +UINT8 __fastcall darkseal_read_byte(UINT32 address) +{ + if ((address & 0xfffff0) == 0x180000) { + switch (address & 0xf) + { + case 0: + return DrvDip[1]; + + case 1: + return DrvDip[0]; + + case 2: + return DrvInputs[0] >> 8; + + case 3: + return DrvInputs[0] & 0xff; + + case 4: + return 0xff; + + case 5: + return (DrvInputs[1] ^ vblank) & 0xff; + } + + return 0xff; + } + + return 0; +} + +UINT16 __fastcall darkseal_read_word(UINT32 address) +{ + if ((address & 0xfffff0) == 0x180000) { + switch (address & 0xe) + { + case 0: + return (DrvDip[0] | (DrvDip[1]<<8)); + + case 2: + return DrvInputs[0]; + + case 4: + return DrvInputs[1] ^ vblank; + } + + return 0xffff; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + + DrvH6280ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x200000; + + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x002000; + DrvPf3RAM = Next; Next += 0x002000; + DrvPf12RowRAM = Next; Next += 0x001000; + DrvPf34RowRAM = Next; Next += 0x001000; + DrvPf2RAM = Next; Next += 0x002000; + DrvPf1RAM = Next; Next += 0x002000; + DrvPfCtrlRAM0 = Next; Next += 0x000010; + DrvPfCtrlRAM1 = Next; Next += 0x000010; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x00000*8, 0x10000*8, 0x8000*8, 0x18000*8 }; + INT32 Plane1[4] = { 8, 0, 0x40000*8+8, 0x40000*8 }; + INT32 Plane2[4] = { 8, 0, 0x80000*8+8, 0x80000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs0[8] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }; + INT32 XOffs1[16] = { 32*8+0, 32*8+1, 32*8+2, 32*8+3, 32*8+4, 32*8+5, 32*8+6, 32*8+7, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs1[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(0x1000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane2, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static void DrvPrgDecode() +{ + for (INT32 i = 0; i < 0x80000; i++) + Drv68KROM[i] = BITSWAP08(Drv68KROM[i], 7, 1, 5, 4, 3, 2, 6, 0); +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + + if (BurnLoadRom(DrvH6280ROM, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x80000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 11, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x20000, 12, 1)) return 1; + + DrvPrgDecode(); + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x141fff, SM_RAM); // split ram + SekMapMemory(DrvPf3RAM + 0x001000, 0x200000, 0x200fff, SM_RAM); // mirror + SekMapMemory(DrvPf3RAM, 0x202000, 0x203fff, SM_RAM); + SekMapMemory(DrvPf12RowRAM, 0x220000, 0x220fff, SM_RAM); + SekMapMemory(DrvPf34RowRAM, 0x222000, 0x222fff, SM_RAM); + SekMapMemory(DrvPf2RAM, 0x260000, 0x261fff, SM_RAM); + SekMapMemory(DrvPf1RAM, 0x262000, 0x263fff, SM_RAM); + SekSetWriteWordHandler(0, darkseal_write_word); + SekSetWriteByteHandler(0, darkseal_write_byte); + SekSetReadWordHandler(0, darkseal_read_word); + SekSetReadByteHandler(0, darkseal_read_byte); + SekClose(); + + // sound hardware... + + BurnSetRefreshRate(58.00); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + UINT16 *SprRAM = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 sprite = SprRAM[offs+1] & 0x1fff; + if (!sprite) continue; + + INT32 y = SprRAM[offs]; + INT32 x = SprRAM[offs+2]; + + INT32 flash = ((y >> 12) & 1) & GetCurrentFrame(); + if (flash) continue; + + INT32 color = ((x >> 9) & 0x1f) + 0x10; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x &= 0x01ff; + y &= 0x01ff; + if (x > 255) x -= 512; + if (y > 255) y -= 512; + x = 240 - x; + y = (240 - y) - 8; + + if (x > 256) continue; + + sprite &= ~multi; + + INT32 inc = -1; + + if (!fy) { + sprite += multi; + inc = 1; + } + + while (multi >= 0) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite - multi * inc, x, y+-16*multi, color, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite - multi * inc, x, y+-16*multi, color, 4, 0, 0, DrvGfxROM3); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite - multi * inc, x, y+-16*multi, color, 4, 0, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite - multi * inc, x, y+-16*multi, color, 4, 0, 0, DrvGfxROM3); + } + } + + multi--; + } + } +} + +static void draw_pf1_layer(INT32 scroll_x, INT32 scroll_y) +{ + UINT16 *vram = (UINT16*)DrvPf1RAM; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scroll_x; + if (sx < -7) sx += 0x200; + sy -= scroll_y + 8; + if (sy < -7) sy += 0x200; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + + code &= 0xfff; + if (!code) continue; + + if (sy >= 0 && sx >= 0 && sy <= nScreenHeight-8 && sx <= nScreenWidth-8) { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_pf23_layer_no_rowscroll(UINT8 *ram, UINT8 *gfx_base, INT32 coloffs, INT32 transp, INT32 scroll_x, INT32 scroll_y) +{ + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f); + INT32 sy = (offs >> 6); + + INT32 ofst = (sx & 0x1f) + ((sy & 0x1f) << 5) + ((sx & 0x20) << 5) + ((sy & 0x20) << 6); + + sx <<= 4, sy <<= 4; + + sx -= scroll_x; + if (sx < -15) sx += 0x400; + sy -= scroll_y + 8; + if (sy < -15) sy += 0x400; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[ofst]; + INT32 color = code >> 12; + + code &= 0xfff; + if (!code && transp) continue; + + if (transp) { + if (sy >= 0 && sx >= 0 && sy <= nScreenHeight-16 && sx <= nScreenWidth-16) { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, coloffs, gfx_base); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, coloffs, gfx_base); + } + } else { + if (sy >= 0 && sx >= 0 && sy <= nScreenHeight-16 && sx <= nScreenWidth-16) { + Render16x16Tile(pTransDraw, code, sx, sy, color, 4, coloffs, gfx_base); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, coloffs, gfx_base); + } + } + } +} + +static void draw_pf23_layer_rowscroll(INT32 scroll_x, INT32 scroll_y) +{ + UINT16 *vram = (UINT16*)DrvPf3RAM; + UINT16 *rows = (UINT16*)DrvPf34RowRAM; + UINT16 *dest; + + for (INT32 y = 8; y < 248; y++) + { + INT32 row = (scroll_y + y) >> 4; + INT32 xscr = scroll_x + (rows[0x40+y] & 0x3ff); + dest = pTransDraw + ((y-8) * nScreenWidth); + + for (INT32 x = 0; x < 256+16; x+=16) + { + INT32 col = ((xscr + x) & 0x3ff) >> 4; + INT32 sx = x - (xscr & 0x0f); + if (sx < -15) sx += 0x400; + if (sx < 0) sx += 16; + + INT32 ofst = (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 5) + ((row & 0x20) << 6); + + INT32 code = vram[ofst] & 0xfff; + INT32 color = ((vram[ofst] >> 12) << 4) | 0x400; + + UINT8 *src = DrvGfxROM2 + (code << 8) + (((scroll_y + y) & 0x0f) << 4); + for (INT32 xx = sx; xx < ((sx+16) < nScreenWidth) ? (sx+16) : nScreenWidth; xx++) { + if (xx >= nScreenWidth) break; + dest[xx] = src[xx-sx] | color; + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i+=2) { + palette_write(i); + } + } + + UINT16 *ctrl0 = (UINT16*)DrvPfCtrlRAM0; + UINT16 *ctrl1 = (UINT16*)DrvPfCtrlRAM1; + + INT32 flipscreen = ~ctrl0[0] & 0x80; + + if (ctrl0[6] & 0x4000) { + draw_pf23_layer_rowscroll(ctrl0[3] & 0x3ff, ctrl0[4] & 0x3ff); + } else { + draw_pf23_layer_no_rowscroll(DrvPf3RAM, DrvGfxROM2, 0x400, 0, ctrl0[3] & 0x3ff, ctrl0[4] & 0x3ff); + } + + draw_pf23_layer_no_rowscroll(DrvPf2RAM, DrvGfxROM1, 0x300, 1, ctrl1[1] & 0x3ff, ctrl1[2] & 0x3ff); + + draw_sprites(); + + draw_pf1_layer(ctrl1[3] & 0x1ff, ctrl1[4] & 0x1ff); + + if (flipscreen) { + INT32 full = nScreenWidth * nScreenHeight; + for (INT32 i = 0; i < full / 2; i++) { + INT32 t = pTransDraw[i + 0]; + pTransDraw[i + 0] = pTransDraw[(full-1)-i]; + pTransDraw[(full-1)-i] = t; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 256; + INT32 nTotalCycles[2] = { 12000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + vblank = 8; + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + + nCyclesDone[0] += SekRun(nSegment); + + if (i == 7) vblank = 0; + if (i == 247) vblank = 8; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + } + + return 0; +} + + +// Dark Seal (World revision 3) + +static struct BurnRomInfo darksealRomDesc[] = { + { "ga04-3.rom", 0x20000, 0xbafad556, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ga01-3.rom", 0x20000, 0xf409050e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ga-00.rom", 0x20000, 0xfbf3ac63, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ga-05.rom", 0x20000, 0xd5e3ae3f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fz-06.rom", 0x10000, 0xc4828a6d, 2 | BRF_PRG | BRF_ESS }, // 4 H6280 Code + + { "fz-02.rom", 0x10000, 0x3c9c3012, 3 | BRF_GRA }, // 5 Text Tiles + { "fz-03.rom", 0x10000, 0x264b90ed, 3 | BRF_GRA }, // 6 + + { "mac-03.rom", 0x80000, 0x9996f3dc, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "mac-02.rom", 0x80000, 0x49504e89, 5 | BRF_GRA }, // 8 Background Tiles + + { "mac-00.rom", 0x80000, 0x52acf1d6, 6 | BRF_GRA }, // 9 Sprite Tiles + { "mac-01.rom", 0x80000, 0xb28f7584, 6 | BRF_GRA }, // 10 + + { "fz-08.rom", 0x20000, 0xc9bf68e1, 7 | BRF_SND }, // 11 Oki6295 #0 Samples + + { "fz-07.rom", 0x20000, 0x588dd3cb, 8 | BRF_SND }, // 12 Oki6295 #1 Samples +}; + +STD_ROM_PICK(darkseal) +STD_ROM_FN(darkseal) + +struct BurnDriver BurnDrvDarkseal = { + "darkseal", NULL, NULL, NULL, "1990", + "Dark Seal (World revision 3)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, darksealRomInfo, darksealRomName, NULL, NULL, DarksealInputInfo, DarksealDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Dark Seal (World revision 1) + +static struct BurnRomInfo darksea1RomDesc[] = { + { "ga-04.rom", 0x20000, 0xa1a985a9, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ga-01.rom", 0x20000, 0x98bd2940, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ga-00.rom", 0x20000, 0xfbf3ac63, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ga-05.rom", 0x20000, 0xd5e3ae3f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fz-06.rom", 0x10000, 0xc4828a6d, 2 | BRF_PRG | BRF_ESS }, // 4 H6280 Code + + { "fz-02.rom", 0x10000, 0x3c9c3012, 3 | BRF_GRA }, // 5 Text Tiles + { "fz-03.rom", 0x10000, 0x264b90ed, 3 | BRF_GRA }, // 6 + + { "mac-03.rom", 0x80000, 0x9996f3dc, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "mac-02.rom", 0x80000, 0x49504e89, 5 | BRF_GRA }, // 8 Background Tiles + + { "mac-00.rom", 0x80000, 0x52acf1d6, 6 | BRF_GRA }, // 9 Sprite Tiles + { "mac-01.rom", 0x80000, 0xb28f7584, 6 | BRF_GRA }, // 10 + + { "fz-08.rom", 0x20000, 0xc9bf68e1, 7 | BRF_SND }, // 11 Oki6295 #0 Samples + + { "fz-07.rom", 0x20000, 0x588dd3cb, 8 | BRF_SND }, // 12 Oki6295 #1 Samples +}; + +STD_ROM_PICK(darksea1) +STD_ROM_FN(darksea1) + +struct BurnDriver BurnDrvDarksea1 = { + "darkseal1", "darkseal", NULL, NULL, "1990", + "Dark Seal (World revision 1)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, darksea1RomInfo, darksea1RomName, NULL, NULL, DarksealInputInfo, DarksealDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Dark Seal (Japan) + +static struct BurnRomInfo darkseajRomDesc[] = { + { "fz-04.bin", 0x20000, 0x817faa2c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fz-01.bin", 0x20000, 0x373caeee, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fz-00.bin", 0x20000, 0x1ab99aa7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fz-05.bin", 0x20000, 0x3374ef8c, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fz-06.rom", 0x10000, 0xc4828a6d, 2 | BRF_PRG | BRF_ESS }, // 4 H6280 Code + + { "fz-02.rom", 0x10000, 0x3c9c3012, 3 | BRF_GRA }, // 5 Text Tiles + { "fz-03.rom", 0x10000, 0x264b90ed, 3 | BRF_GRA }, // 6 + + { "mac-03.rom", 0x80000, 0x9996f3dc, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "mac-02.rom", 0x80000, 0x49504e89, 5 | BRF_GRA }, // 8 Background Tiles + + { "mac-00.rom", 0x80000, 0x52acf1d6, 6 | BRF_GRA }, // 9 Sprite Tiles + { "mac-01.rom", 0x80000, 0xb28f7584, 6 | BRF_GRA }, // 10 + + { "fz-08.rom", 0x20000, 0xc9bf68e1, 7 | BRF_SND }, // 11 Oki6295 #0 Samples + + { "fz-07.rom", 0x20000, 0x588dd3cb, 8 | BRF_SND }, // 12 Oki6295 #1 Samples +}; + +STD_ROM_PICK(darkseaj) +STD_ROM_FN(darkseaj) + +struct BurnDriver BurnDrvDarkseaj = { + "darksealj", "darkseal", NULL, NULL, "1990", + "Dark Seal (Japan)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, darkseajRomInfo, darkseajRomName, NULL, NULL, DarksealInputInfo, DarksealDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Gate of Doom (US revision 4) + +static struct BurnRomInfo gatedoomRomDesc[] = { + { "gb04-4", 0x20000, 0x8e3a0bfd, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gb01-4", 0x20000, 0x8d0fd383, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ga-00.rom", 0x20000, 0xfbf3ac63, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ga-05.rom", 0x20000, 0xd5e3ae3f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fz-06.rom", 0x10000, 0xc4828a6d, 2 | BRF_PRG | BRF_ESS }, // 4 H6280 Code + + { "fz-02.rom", 0x10000, 0x3c9c3012, 3 | BRF_GRA }, // 5 Text Tiles + { "fz-03.rom", 0x10000, 0x264b90ed, 3 | BRF_GRA }, // 6 + + { "mac-03.rom", 0x80000, 0x9996f3dc, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "mac-02.rom", 0x80000, 0x49504e89, 5 | BRF_GRA }, // 8 Background Tiles + + { "mac-00.rom", 0x80000, 0x52acf1d6, 6 | BRF_GRA }, // 9 Sprite Tiles + { "mac-01.rom", 0x80000, 0xb28f7584, 6 | BRF_GRA }, // 10 + + { "fz-08.rom", 0x20000, 0xc9bf68e1, 7 | BRF_SND }, // 11 Oki6295 #0 Samples + + { "fz-07.rom", 0x20000, 0x588dd3cb, 8 | BRF_SND }, // 12 Oki6295 #1 Samples +}; + +STD_ROM_PICK(gatedoom) +STD_ROM_FN(gatedoom) + +struct BurnDriver BurnDrvGatedoom = { + "gatedoom", "darkseal", NULL, NULL, "1990", + "Gate of Doom (US revision 4)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, gatedoomRomInfo, gatedoomRomName, NULL, NULL, DarksealInputInfo, DarksealDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; + + +// Gate of Doom (US revision 1) + +static struct BurnRomInfo gatedom1RomDesc[] = { + { "gb04.bin", 0x20000, 0x4c3bbd2b, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gb01.bin", 0x20000, 0x59e367f4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gb00.bin", 0x20000, 0xa88c16a1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gb05.bin", 0x20000, 0x252d7e14, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fz-06.rom", 0x10000, 0xc4828a6d, 2 | BRF_PRG | BRF_ESS }, // 4 H6280 Code + + { "fz-02.rom", 0x10000, 0x3c9c3012, 3 | BRF_GRA }, // 5 Text Tiles + { "fz-03.rom", 0x10000, 0x264b90ed, 3 | BRF_GRA }, // 6 + + { "mac-03.rom", 0x80000, 0x9996f3dc, 4 | BRF_GRA }, // 7 Foreground Tiles + + { "mac-02.rom", 0x80000, 0x49504e89, 5 | BRF_GRA }, // 8 Background Tiles + + { "mac-00.rom", 0x80000, 0x52acf1d6, 6 | BRF_GRA }, // 9 Sprite Tiles + { "mac-01.rom", 0x80000, 0xb28f7584, 6 | BRF_GRA }, // 10 + + { "fz-08.rom", 0x20000, 0xc9bf68e1, 7 | BRF_SND }, // 11 Oki6295 #0 Samples + + { "fz-07.rom", 0x20000, 0x588dd3cb, 8 | BRF_SND }, // 12 Oki6295 #1 Samples +}; + +STD_ROM_PICK(gatedom1) +STD_ROM_FN(gatedom1) + +struct BurnDriver BurnDrvGatedom1 = { + "gatedoom1", "darkseal", NULL, NULL, "1990", + "Gate of Doom (US revision 1)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, gatedom1RomInfo, gatedom1RomName, NULL, NULL, DarksealInputInfo, DarksealDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_dassault.cpp b/src/burn/drivers/misc_post90s/d_dassault.cpp new file mode 100644 index 00000000..74ca0e1c --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_dassault.cpp @@ -0,0 +1,1170 @@ +// FB Alpha Thunder Zone / Desert Assault driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM0; +static UINT8 *Drv68KROM1; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvHucRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM0; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSprBuf0; +static UINT8 *DrvSprBuf1; +static UINT8 *DrvShareRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static INT32 DrvOkiBank; + +static struct BurnInputInfo ThndzoneInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy2 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy2 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy2 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy2 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p4 coin" }, + {"P4 Up", BIT_DIGITAL, DrvJoy2 + 8, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy2 + 9, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy2 + 10, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy2 + 11, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Thndzone) + +static struct BurnDIPInfo ThndzoneDIPList[]= +{ + {0x20, 0xff, 0xff, 0xff, NULL }, + {0x21, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x20, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x20, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x20, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x20, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x20, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x20, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x20, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x20, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x20, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x20, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x20, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x20, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x20, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x20, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x20, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x20, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x20, 0x01, 0x40, 0x40, "Off" }, + {0x20, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x20, 0x01, 0x80, 0x80, "Off" }, + {0x20, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x21, 0x01, 0x0c, 0x08, "Easy" }, + {0x21, 0x01, 0x0c, 0x0c, "Normal" }, + {0x21, 0x01, 0x0c, 0x04, "Hard" }, + {0x21, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Max Players" }, + {0x21, 0x01, 0x20, 0x20, "2" }, + {0x21, 0x01, 0x20, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x21, 0x01, 0x80, 0x80, "Off" }, + {0x21, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Thndzone) + +static struct BurnDIPInfo DassaultDIPList[]= +{ + {0x20, 0xff, 0xff, 0xff, NULL }, + {0x21, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x20, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x20, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x20, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x20, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x20, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x20, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x20, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x20, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x20, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x20, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x20, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x20, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x20, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x20, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x20, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x20, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x20, 0x01, 0x40, 0x40, "Off" }, + {0x20, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x20, 0x01, 0x80, 0x80, "Off" }, + {0x20, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x21, 0x01, 0x0c, 0x08, "Easy" }, + {0x21, 0x01, 0x0c, 0x0c, "Normal" }, + {0x21, 0x01, 0x0c, 0x04, "Hard" }, + {0x21, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3, "Max Players" }, + {0x21, 0x01, 0x30, 0x30, "2" }, + {0x21, 0x01, 0x30, 0x20, "3" }, + {0x21, 0x01, 0x30, 0x10, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x21, 0x01, 0x80, 0x80, "Off" }, + {0x21, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Dassault) + +static struct BurnDIPInfo Dassault4DIPList[]= +{ + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x1e, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x1e, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x1e, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x1e, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x1e, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x1e, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x1e, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x1e, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1e, 0x01, 0x40, 0x40, "Off" }, + {0x1e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x1e, 0x01, 0x80, 0x80, "Off" }, + {0x1e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1f, 0x01, 0x0c, 0x08, "Easy" }, + {0x1f, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1f, 0x01, 0x0c, 0x04, "Hard" }, + {0x1f, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1f, 0x01, 0x80, 0x80, "Off" }, + {0x1f, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Dassault4) + +void __fastcall dassault_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x220000, data) + deco16_write_control_word(1, address, 0x260000, data) + + switch (address) + { + case 0x180000: + case 0x180001: + *soundlatch = data; + // cpu_set_input_line(state->audiocpu, 0, HOLD_LINE); + return; + + case 0x1c000c: + case 0x1c000d: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x1000); + return; + + case 0x1c000e: + case 0x1c000f: + // coin counter + return; + } +} + +void __fastcall dassault_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x180000: + case 0x180001: + *soundlatch = data; + // cpu_set_input_line(state->audiocpu, 0, HOLD_LINE); + return; + + case 0x1c000b: + deco16_priority = data; + return; + + case 0x1c000c: + case 0x1c000d: + memcpy (DrvSprBuf1, DrvSprRAM1, 0x1000); + return; + + case 0x1c000e: + case 0x1c000f: + // coin counter + return; + } +} + +UINT16 __fastcall dassault_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x1c0000: + return DrvInputs[0]; // p1,p2 + + case 0x1c0002: + return DrvInputs[1]; // p3,p4 + + case 0x1c0004: + return DrvDips[0]; + + case 0x1c0006: + return DrvDips[1]; + + case 0x1c0008: + return (DrvInputs[2] & 0xf7) | (deco16_vblank & 0x08); + + case 0x1c000a: + case 0x1c000c: + case 0x1c000e: + return 0xffff; + } + + return 0; +} + +UINT8 __fastcall dassault_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x1c0000: + return DrvInputs[0] >> 8; + + case 0x1c0001: + return DrvInputs[0]; // p1,p2 + + case 0x1c0002: + return DrvInputs[1] >> 8; + + case 0x1c0003: + return DrvInputs[1]; // p3,p4 + + case 0x1c0004: + case 0x1c0005: + return DrvDips[0]; + + case 0x1c0006: + case 0x1c0007: + return DrvDips[1]; + + case 0x1c0008: + case 0x1c0009: + return (DrvInputs[2] & 0xf7) | (deco16_vblank & 0x08); + + case 0x1c000a: + case 0x1c000b: + case 0x1c000c: + case 0x1c000d: + case 0x1c000e: + case 0x1c000f: + return 0xff; + } + + return 0; +} + +UINT16 __fastcall dassault_sub_read_word(UINT32 address) +{ + switch (address) + { + case 0x100004: + case 0x100005: + return (deco16_vblank ? 0xffff : 0); + } + + return 0; +} + +UINT8 __fastcall dassault_sub_read_byte(UINT32 address) +{ + switch (address) + { + case 0x100004: + case 0x100005: + return (deco16_vblank ? 0xff : 0); + } + + return 0; +} + +void __fastcall dassault_sub_write_word(UINT32 address, UINT16 ) +{ + switch (address) + { + case 0x100000: + case 0x100001: + memcpy (DrvSprBuf0, DrvSprRAM0, 0x1000); + return; + } +} + +void __fastcall dassault_sub_write_byte(UINT32 address, UINT8 ) +{ + switch (address) + { + case 0x100000: + case 0x100001: + memcpy (DrvSprBuf0, DrvSprRAM0, 0x1000); + return; + } +} + +static void set_cpuA_irq(INT32 state) +{ + if (SekGetActive() == 0) { // main + SekSetIRQLine(5, state ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); + } else { + SekClose(); + SekOpen(0); + SekSetIRQLine(5, state ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); + SekClose(); + SekOpen(1); + } +} + +static void set_cpuB_irq(INT32 state) +{ + if (SekGetActive() == 1) { // sub + SekSetIRQLine(6, state ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); + } else { + SekClose(); + SekOpen(1); + SekSetIRQLine(6, state ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE); + SekClose(); + SekOpen(0); + } +} + +void __fastcall dassault_irq_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffffffc) == 0x3feffc) { + if (address & 2) { + set_cpuB_irq(1); + } else { + set_cpuA_irq(1); + } + } + + *((UINT16*)(DrvShareRAM + (address & 0xffe))) = data; +} + +void __fastcall dassault_irq_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffffffc) == 0x3feffc) { + if (address & 2) { + set_cpuB_irq(1); + } else { + set_cpuA_irq(1); + } + } + + DrvShareRAM[(address & 0xfff)^1] = data; +} + +UINT16 __fastcall dassault_irq_read_word(UINT32 address) +{ + if ((address & 0xffffffc) == 0x3feffc) { + if (address & 2) { + set_cpuB_irq(0); + } else { + set_cpuA_irq(0); + } + } + + return *((UINT16*)(DrvShareRAM + (address & 0xffe))); +} + +UINT8 __fastcall dassault_irq_read_byte(UINT32 address) +{ + if (SekGetPC(0) == 0x114c && (DrvShareRAM[0] & 0x80) && (address & ~1) == 0x3fe000) SekRunEnd(); + + if ((address & 0xffffffc) == 0x3feffc) { + if (address & 2) { + set_cpuB_irq(0); + } else { + set_cpuA_irq(0); + } + } + + return DrvShareRAM[(address & 0xfff)^1]; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + DrvOkiBank = data & 1; + + memcpy (DrvSndROM1, DrvSndROM1 + 0x40000 + (data & 1) * 0x40000, 0x40000); +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return 0 * nSoundRate; //(INT64)HucTotalCycles() * nSoundRate / 4027500; +} + +static double DrvGetTime() +{ + return 0; //(double)HucTotalCycles() / 4027500.0; +} + +static INT32 dassault_bank_callback( const INT32 bank ) +{ + return ((bank >> 4) & 0xf) << 12; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + SekOpen(1); + SekReset(); + SekClose(); + + // huc6280 + + BurnYM2151Reset(); + BurnYM2203Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + DrvYM2151WritePort(0, 0); // Set OKI1 Bank + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM0 = Next; Next += 0x080000; + Drv68KROM1 = Next; Next += 0x080000; + + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x300000; + DrvGfxROM1 = Next; Next += 0x300000; + DrvGfxROM2 = Next; Next += 0x400000; + DrvGfxROM3 = Next; Next += 0x800000; + DrvGfxROM4 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x0c0000; + + DrvPalette = (UINT32*)Next; Next += 0x1000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM0 = Next; Next += 0x004000; + Drv68KRAM1 = Next; Next += 0x004000; + DrvHucRAM = Next; Next += 0x002000; + + DrvSprRAM0 = Next; Next += 0x001000; + DrvSprRAM1 = Next; Next += 0x001000; + + DrvSprBuf0 = Next; Next += 0x001000; + DrvSprBuf1 = Next; Next += 0x001000; + + DrvShareRAM = Next; Next += 0x001000; + + DrvPalRAM = Next; Next += 0x004000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM0 + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x040000, 3, 2)) return 1; + + if (BurnLoadRom(Drv68KROM1 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x040001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM1 + 0x040000, 7, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 10, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 1)) return 1; + + memcpy (DrvGfxROM3 + 0x000000, DrvGfxROM1 + 0x080000, 0x080000); + memcpy (DrvGfxROM1 + 0x090000, DrvGfxROM3 + 0x000000, 0x080000); + memcpy (DrvGfxROM1 + 0x080000, DrvGfxROM0 + 0x000000, 0x010000); + memcpy (DrvGfxROM1 + 0x110000, DrvGfxROM0 + 0x010000, 0x010000); + memset (DrvGfxROM3, 0, 0x200000); + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 13, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x180000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x280000, 19, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300000, 20, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x380000, 21, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000001, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x040000, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x040001, 25, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 26, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 27, 1)) return 1; + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x120000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x120000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x200000, 0); + deco16_tile_decode(DrvGfxROM3, DrvGfxROM3, 0x400000, 0); + deco16_tile_decode(DrvGfxROM4, DrvGfxROM4, 0x080000, 0); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x120000 * 2, DrvGfxROM1, 0x120000 * 2, DrvGfxROM2, 0x200000 * 2); + deco16_set_global_offsets(0, 8); + deco16_set_color_base(2, 0x200); + deco16_set_color_base(3, 0x300); + deco16_set_bank_callback(0, dassault_bank_callback); + deco16_set_bank_callback(1, dassault_bank_callback); + deco16_set_bank_callback(2, dassault_bank_callback); + deco16_set_bank_callback(3, dassault_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM0, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x200000, 0x201fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x202000, 0x203fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x212000, 0x212fff, SM_WRITE); + SekMapMemory(deco16_pf_ram[2], 0x240000, 0x240fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x242000, 0x242fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x252000, 0x252fff, SM_WRITE); + SekMapMemory(Drv68KRAM0, 0x3f8000, 0x3fbfff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x3fc000, 0x3fcfff, SM_RAM); + SekMapMemory(DrvShareRAM, 0x3fe000, 0x3fefff, SM_FETCH); + + SekSetWriteWordHandler(0, dassault_main_write_word); + SekSetWriteByteHandler(0, dassault_main_write_byte); + SekSetReadWordHandler(0, dassault_main_read_word); + SekSetReadByteHandler(0, dassault_main_read_byte); + + SekMapHandler(1, 0x3fe000, 0x3fefff, SM_WRITE | SM_READ); + SekSetWriteWordHandler(1, dassault_irq_write_word); + SekSetWriteByteHandler(1, dassault_irq_write_byte); + SekSetReadWordHandler(1, dassault_irq_read_word); + SekSetReadByteHandler(1, dassault_irq_read_byte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Drv68KROM1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM1, 0x3f8000, 0x3fbfff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x3fc000, 0x3fcfff, SM_RAM); + SekMapMemory(DrvShareRAM, 0x3fe000, 0x3fefff, SM_FETCH); + + SekSetWriteWordHandler(0, dassault_sub_write_word); + SekSetWriteByteHandler(0, dassault_sub_write_byte); + SekSetReadWordHandler(0, dassault_sub_read_word); + SekSetReadByteHandler(0, dassault_sub_read_byte); + + SekMapHandler(1, 0x3fe000, 0x3fefff, SM_WRITE | SM_READ); + + SekSetWriteWordHandler(1, dassault_irq_write_word); + SekSetWriteByteHandler(1, dassault_irq_write_byte); + SekSetReadWordHandler(1, dassault_irq_read_word); + SekSetReadByteHandler(1, dassault_irq_read_byte); + SekClose(); + + // h6280 + + BurnYM2151Init(3580000, 40.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(4027500); + + MSM6295Init(0, 1023924 / 132, 50.0, 1); + MSM6295Init(1, 2047848 / 132, 25.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + BurnYM2203Exit(); + BurnYM2151Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + SekExit(); +// huc6280 + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_sprites(INT32 bpp) +{ + if ((nBurnBpp & 4) != bpp) return; + + UINT16 *spritebase; + UINT8 *gfx; + + for (INT32 bank = 0; bank < 2; bank++) + { + for (INT32 offs = 0x800 - 4; offs >= 0; offs -= 4) + { + INT32 alpha = 0xff, pmask = 0, coloff = 0; + + if (bank == 0) + { + spritebase = (UINT16*)DrvSprBuf0; + gfx = DrvGfxROM3; + coloff = 0x400; + } + else + { + spritebase = (UINT16*)DrvSprBuf1; + gfx = DrvGfxROM4; + coloff = 0x800; + } + + INT32 sprite = spritebase[offs + 1] & 0x7fff; + if (!sprite) continue; + + INT32 x = spritebase[offs + 2]; + INT32 y = spritebase[offs + 0]; + + if ((y & 0x1000) && (nCurrentFrame & 1)) continue; // flash + + INT32 color = ((x >> 9) & 0x1f) | ((y >> 10) & 0x20); + + INT32 flipx = y & 0x2000; + INT32 flipy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + if (bank == 0) { + switch (spritebase[offs+2] & 0xc000) + { + case 0xc000: pmask = 0x01; break; + case 0x8000: pmask = 0x08; break; + case 0x4000: pmask = 0x20; break; + case 0x0000: pmask = 0x80; break; + } + } else { + switch (deco16_priority & 0x03) + { + case 0x0001: pmask = 0x10; break; + case 0x0002: + case 0x0003: + case 0x0000: pmask = 0x40; break; + } + + if (x & 0xc000) alpha = 0x80; + } + + x &= 0x01ff; + y &= 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + x = 304 - x; + y = 240 - y; + if (x > 320) continue; + + INT32 inc, mult; + sprite &= ~multi; + if (flipy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y = 240 - y; + x = 304 - x; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else mult = -16; + + while (multi >= 0) + { + if (!bpp) { + deco16_draw_prio_sprite(pTransDraw, gfx, sprite - multi * inc, (color << 4) + coloff, x, y + mult * multi, flipx, flipy, pmask, 1 << bank); + } else { + deco16_draw_alphaprio_sprite(DrvPalette, gfx, sprite - multi * inc, (color << 4) + coloff, x, y + mult * multi, flipx, flipy, pmask, 1 << bank, alpha); + } + + multi--; + } + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0xc00; + } + + deco16_clear_prio_map(); + + if (nBurnLayer & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE | DECO16_LAYER_PRIORITY(0)); + + switch (deco16_priority & 3) + { + case 0: + if (nBurnLayer & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nBurnLayer & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x10)); + break; + + case 1: + if (nBurnLayer & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nBurnLayer & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x40)); + break; + + case 2: break; + + case 3: + if (nBurnLayer & 2) deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + if (nBurnLayer & 4) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x10)); + break; + } + + if (nSpriteEnable & 1) draw_sprites(0); + + if (nBurnLayer & 8) deco16_draw_layer(0, pTransDraw, DECO16_LAYER_PRIORITY(0xff)); + + BurnTransferCopy(DrvPalette); + + if (nSpriteEnable & 2) draw_sprites(4); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[3] = { 14000000 / 60, 14000000 / 60, 4027500 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + SekOpen(0); + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + SekOpen(1); + nCyclesDone[1] += SekRun(nCyclesDone[0] - nCyclesDone[1]); + if (i == (nInterleave - 1)) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // nCyclesDone[2] += HucRun(nCyclesTotal[2] / nInterleave); + + if (i == 248) deco16_vblank = 0x08; + } + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2203Scan(nAction, pnMin); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(DrvOkiBank); + DrvYM2151WritePort(0, DrvOkiBank); + } + + return 0; +} + + +// Thunder Zone (World) + +static struct BurnRomInfo thndzoneRomDesc[] = { + { "gz_01.bin", 0x020000, 0x15e8c328, 1 | BRF_PRG | BRF_ESS }, // 0 68k 'A' Code + { "gz_03.bin", 0x020000, 0xaab5c86e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gs00", 0x020000, 0xb7277175, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gs02", 0x020000, 0xcde31e35, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "gz_10.bin", 0x020000, 0x79f919e9, 2 | BRF_PRG | BRF_ESS }, // 4 68k 'B' Code + { "gz_08.bin", 0x020000, 0xd47d7836, 2 | BRF_PRG | BRF_ESS }, // 5 + { "gs11", 0x020000, 0x80cb23de, 2 | BRF_PRG | BRF_ESS }, // 6 + { "gs09", 0x020000, 0x0a8fa7e1, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "gs04", 0x010000, 0x81c29ebf, 3 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gs05", 0x010000, 0x0aae996a, 4 | BRF_GRA }, // 9 Characters + { "gs06", 0x010000, 0x4efdf03d, 4 | BRF_GRA }, // 10 + + { "maj-02", 0x100000, 0x383bbc37, 5 | BRF_GRA }, // 11 Foreground Tiles + + { "maj-01", 0x100000, 0x9840a204, 6 | BRF_GRA }, // 12 Background Tiles + { "maj-00", 0x100000, 0x87ea8d16, 6 | BRF_GRA }, // 13 + + { "maj-04", 0x080000, 0x36e49b19, 7 | BRF_GRA }, // 14 Sprite Bank A + { "maj-05", 0x080000, 0x80fc71cc, 7 | BRF_GRA }, // 15 + { "maj-06", 0x080000, 0x2e7a684b, 7 | BRF_GRA }, // 16 + { "maj-07", 0x080000, 0x3acc1f78, 7 | BRF_GRA }, // 17 + { "maj-08", 0x080000, 0x1958a36d, 7 | BRF_GRA }, // 18 + { "maj-09", 0x080000, 0xc21087a1, 7 | BRF_GRA }, // 19 + { "maj-10", 0x080000, 0xa02fa641, 7 | BRF_GRA }, // 20 + { "maj-11", 0x080000, 0xdabe9305, 7 | BRF_GRA }, // 21 + + { "gs12", 0x020000, 0x9a86a015, 8 | BRF_GRA }, // 22 Sprite Bank B + { "gs13", 0x020000, 0xf4709905, 8 | BRF_GRA }, // 23 + { "gs14", 0x020000, 0x750fc523, 8 | BRF_GRA }, // 24 + { "gs15", 0x020000, 0xf14edd3d, 8 | BRF_GRA }, // 25 + + { "gs07", 0x020000, 0x750b7e5d, 9 | BRF_SND }, // 26 MSM6295 Samples 0 + + { "maj-03", 0x080000, 0x31dcfac3, 10 | BRF_SND }, // 27 MSM6295 Samples 1 + + { "mb7128y.10m", 0x000800, 0xbde780a2, 11 | BRF_OPT }, // 28 Unknown Proms + { "mb7128y.16p", 0x000800, 0xc44d2751, 11 | BRF_OPT }, // 29 + + { "pal16r8a 1h", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 30 PLDs + { "pal16l8b.7c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 31 + { "pal16l8b.7d", 0x000104, 0x199e83fd, 12 | BRF_OPT }, // 32 + { "pal16l8b.7e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 33 + { "pal16l8b.7l", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 34 + { "pal16l8b.8e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 35 + { "pal16l8b.9d", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 36 + { "pal16l8b.10c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 37 +}; + +STD_ROM_PICK(thndzone) +STD_ROM_FN(thndzone) + +struct BurnDriver BurnDrvThndzone = { + "thndzone", NULL, NULL, NULL, "1991", + "Thunder Zone (World)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, thndzoneRomInfo, thndzoneRomName, NULL, NULL, ThndzoneInputInfo, ThndzoneDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 320, 240, 4, 3 +}; + + +// Desert Assault (US) + +static struct BurnRomInfo dassaultRomDesc[] = { + { "01.bin", 0x020000, 0x14f17ea7, 1 | BRF_PRG | BRF_ESS }, // 0 68k 'A' Code + { "03.bin", 0x020000, 0xbed1b90c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gs00", 0x020000, 0xb7277175, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gs02", 0x020000, 0xcde31e35, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hc10-1.bin", 0x020000, 0xac5ac770, 2 | BRF_PRG | BRF_ESS }, // 4 68k 'B' Code + { "hc08-1.bin", 0x020000, 0x864dca56, 2 | BRF_PRG | BRF_ESS }, // 5 + { "gs11", 0x020000, 0x80cb23de, 2 | BRF_PRG | BRF_ESS }, // 6 + { "gs09", 0x020000, 0x0a8fa7e1, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "gs04", 0x010000, 0x81c29ebf, 3 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gs05", 0x010000, 0x0aae996a, 4 | BRF_GRA }, // 9 Characters + { "gs06", 0x010000, 0x4efdf03d, 4 | BRF_GRA }, // 10 + + { "maj-02", 0x100000, 0x383bbc37, 5 | BRF_GRA }, // 11 Foreground Tiles + + { "maj-01", 0x100000, 0x9840a204, 6 | BRF_GRA }, // 12 Background Tiles + { "maj-00", 0x100000, 0x87ea8d16, 6 | BRF_GRA }, // 13 + + { "maj-04", 0x080000, 0x36e49b19, 7 | BRF_GRA }, // 14 Sprite Bank A + { "maj-05", 0x080000, 0x80fc71cc, 7 | BRF_GRA }, // 15 + { "maj-06", 0x080000, 0x2e7a684b, 7 | BRF_GRA }, // 16 + { "maj-07", 0x080000, 0x3acc1f78, 7 | BRF_GRA }, // 17 + { "maj-08", 0x080000, 0x1958a36d, 7 | BRF_GRA }, // 18 + { "maj-09", 0x080000, 0xc21087a1, 7 | BRF_GRA }, // 19 + { "maj-10", 0x080000, 0xa02fa641, 7 | BRF_GRA }, // 20 + { "maj-11", 0x080000, 0xdabe9305, 7 | BRF_GRA }, // 21 + + { "gs12", 0x020000, 0x9a86a015, 8 | BRF_GRA }, // 22 Sprite Bank B + { "gs13", 0x020000, 0xf4709905, 8 | BRF_GRA }, // 23 + { "gs14", 0x020000, 0x750fc523, 8 | BRF_GRA }, // 24 + { "gs15", 0x020000, 0xf14edd3d, 8 | BRF_GRA }, // 25 + + { "gs07", 0x020000, 0x750b7e5d, 9 | BRF_SND }, // 26 MSM6295 Samples 0 + + { "maj-03", 0x080000, 0x31dcfac3, 10 | BRF_SND }, // 27 MSM6295 Samples 1 + + { "mb7128y.10m", 0x000800, 0xbde780a2, 11 | BRF_OPT }, // 28 Unknown Proms + { "mb7128y.16p", 0x000800, 0xc44d2751, 11 | BRF_OPT }, // 29 + + { "pal16r8a 1h", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 30 PLDs + { "pal16l8b.7c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 31 + { "pal16l8b.7d", 0x000104, 0x199e83fd, 12 | BRF_OPT }, // 32 + { "pal16l8b.7e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 33 + { "pal16l8b.7l", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 34 + { "pal16l8b.8e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 35 + { "pal16l8b.9d", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 36 + { "pal16l8b.10c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 37 +}; + +STD_ROM_PICK(dassault) +STD_ROM_FN(dassault) + +struct BurnDriver BurnDrvDassault = { + "dassault", "thndzone", NULL, NULL, "1991", + "Desert Assault (US)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, dassaultRomInfo, dassaultRomName, NULL, NULL, ThndzoneInputInfo, DassaultDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 320, 240, 4, 3 +}; + + +// Desert Assault (US 4 Players) + +static struct BurnRomInfo dassault4RomDesc[] = { + { "gs01", 0x020000, 0x8613634d, 1 | BRF_PRG | BRF_ESS }, // 0 68k 'A' Code + { "gs03", 0x020000, 0xea860bd4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gs00", 0x020000, 0xb7277175, 1 | BRF_PRG | BRF_ESS }, // 2 + { "gs02", 0x020000, 0xcde31e35, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "gs10", 0x020000, 0x285f72a3, 2 | BRF_PRG | BRF_ESS }, // 4 68k 'B' Code + { "gs08", 0x020000, 0x16691ede, 2 | BRF_PRG | BRF_ESS }, // 5 + { "gs11", 0x020000, 0x80cb23de, 2 | BRF_PRG | BRF_ESS }, // 6 + { "gs09", 0x020000, 0x0a8fa7e1, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "gs04", 0x010000, 0x81c29ebf, 3 | BRF_PRG | BRF_ESS }, // 8 Huc6280 Code + + { "gs05", 0x010000, 0x0aae996a, 4 | BRF_GRA }, // 9 Characters + { "gs06", 0x010000, 0x4efdf03d, 4 | BRF_GRA }, // 10 + + { "maj-02", 0x100000, 0x383bbc37, 5 | BRF_GRA }, // 11 Foreground Tiles + + { "maj-01", 0x100000, 0x9840a204, 6 | BRF_GRA }, // 12 Background Tiles + { "maj-00", 0x100000, 0x87ea8d16, 6 | BRF_GRA }, // 13 + + { "maj-04", 0x080000, 0x36e49b19, 7 | BRF_GRA }, // 14 Sprite Bank A + { "maj-05", 0x080000, 0x80fc71cc, 7 | BRF_GRA }, // 15 + { "maj-06", 0x080000, 0x2e7a684b, 7 | BRF_GRA }, // 16 + { "maj-07", 0x080000, 0x3acc1f78, 7 | BRF_GRA }, // 17 + { "maj-08", 0x080000, 0x1958a36d, 7 | BRF_GRA }, // 18 + { "maj-09", 0x080000, 0xc21087a1, 7 | BRF_GRA }, // 19 + { "maj-10", 0x080000, 0xa02fa641, 7 | BRF_GRA }, // 20 + { "maj-11", 0x080000, 0xdabe9305, 7 | BRF_GRA }, // 21 + + { "gs12", 0x020000, 0x9a86a015, 8 | BRF_GRA }, // 22 Sprite Bank B + { "gs13", 0x020000, 0xf4709905, 8 | BRF_GRA }, // 23 + { "gs14", 0x020000, 0x750fc523, 8 | BRF_GRA }, // 24 + { "gs15", 0x020000, 0xf14edd3d, 8 | BRF_GRA }, // 25 + + { "gs07", 0x020000, 0x750b7e5d, 9 | BRF_SND }, // 26 MSM6295 Samples 0 + + { "maj-03", 0x080000, 0x31dcfac3, 10 | BRF_SND }, // 27 MSM6295 Samples 1 + + { "mb7128y.10m", 0x000800, 0xbde780a2, 11 | BRF_OPT }, // 28 Unknown Proms + { "mb7128y.16p", 0x000800, 0xc44d2751, 11 | BRF_OPT }, // 29 + + { "pal16r8a 1h", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 30 PLDs + { "pal16l8b.7c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 31 + { "pal16l8b.7d", 0x000104, 0x199e83fd, 12 | BRF_OPT }, // 32 + { "pal16l8b.7e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 33 + { "pal16l8b.7l", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 34 + { "pal16l8b.8e", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 35 + { "pal16l8b.9d", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 36 + { "pal16l8b.10c", 0x000104, 0x00000000, 12 | BRF_NODUMP }, // 37 +}; + +STD_ROM_PICK(dassault4) +STD_ROM_FN(dassault4) + +struct BurnDriver BurnDrvDassault4 = { + "dassault4", "thndzone", NULL, NULL, "1991", + "Desert Assault (US 4 Players)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, dassault4RomInfo, dassault4RomName, NULL, NULL, ThndzoneInputInfo, Dassault4DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_dcon.cpp b/src/burn/drivers/misc_post90s/d_dcon.cpp new file mode 100644 index 00000000..7e92e53b --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_dcon.cpp @@ -0,0 +1,798 @@ +// FB Alpha D-Con / SD Gundam Psycho Salamander no Kyoui driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "seibusnd.h" + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvMgRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvTxRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 *scroll; + +static INT32 gfx_bank; +static INT32 gfx_enable; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT16 DrvInputs[3]; +static UINT8 DrvReset; + +static INT32 is_sdgndmps = 0; + +static struct BurnInputInfo DconInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 12, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Dcon) + +static struct BurnDIPInfo DconDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x18, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Dcon) + +static struct BurnDIPInfo SdgndmpsDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xdf, NULL }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0x0f, 0x04, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "5 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x02, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x08, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0xf0, 0x40, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x20, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x80, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x20, 0x20, "No" }, + {0x13, 0x01, 0x20, 0x00, "Yes" }, + +}; + +STDDIPINFO(Sdgndmps) + +void __fastcall dcon_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff0) == 0x0a0000) { + seibu_main_word_write(address, data); + return; + } + + if ((address & 0xfff800) == 0x09d000) { + gfx_bank = (data & 1) << 12; + return; + } + + if ((address & 0xfffff0) == 0x0c0020) { + scroll[(address & 0x0f) >> 1] = data; + return; + } + + if (address == 0x0c001c) { + gfx_enable = data; + return; + } +} + +UINT16 __fastcall dcon_main_read_word(UINT32 address) +{ + if ((address & 0xfffff0) == 0x0a0000) { + return seibu_main_word_read(address); + } + + switch (address) + { + case 0x0e0000: + return (DrvDips[1] << 8) | DrvDips[0]; + + case 0x0e0002: + return DrvInputs[1]; + + case 0x0e0004: + return DrvInputs[2]; + } + + if (address == 0x0c001c) { + return gfx_enable; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x00000, 0x00004, 0x80000, 0x80004 }; + INT32 XOffs0[8] = { 0x003, 0x002, 0x001, 0x000, 0x00b, 0x00a, 0x009, 0x008 }; + INT32 YOffs0[8] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 }; + + INT32 Plane1[4] = { 0x008, 0x00c, 0x000, 0x004 }; + INT32 XOffs1[16] = { 0x003, 0x002, 0x001, 0x000, 0x013, 0x012, 0x011, 0x010, + 0x203, 0x202, 0x201, 0x200, 0x213, 0x212, 0x211, 0x210 }; + INT32 YOffs1[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(0x1000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM3); + + memcpy (tmp, DrvGfxROM4, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM4); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + seibu_sound_reset(); + + gfx_bank = 0; + gfx_enable = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + SeibuZ80ROM = Next; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x200000; + DrvGfxROM4 = Next; Next += 0x400000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x000800; + DrvBgRAM = Next; Next += 0x000800; + DrvMgRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x000800; + DrvTxRAM = Next; Next += 0x001000; + Drv68KRAM = Next; Next += 0x00c000; + DrvPalRAM = Next; Next += 0x001000; + + scroll = (UINT16*)Next; Next += 0x000010; + + SeibuZ80RAM = Next; + DrvZ80RAM = Next; Next += 0x000800; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x08000, 0x08000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x08000, 0x08000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 9, 1)) return 1; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "sdgndmps")) { + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x100000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 12, 1)) return 1; + + is_sdgndmps = 1; + } else { + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x100000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x180000, 13, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 14, 1)) return 1; + } + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x08bfff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x08c000, 0x08c7ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x08c800, 0x08cfff, SM_RAM); + SekMapMemory(DrvMgRAM, 0x08d000, 0x08d7ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x08d800, 0x08e7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x08e800, 0x08f7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x08f800, 0x08ffff, SM_RAM); + SekSetWriteWordHandler(0, dcon_main_write_word); + SekSetReadWordHandler(0, dcon_main_read_word); + SekClose(); + + seibu_sound_init(is_sdgndmps, 0, 3579545, 3579545, 1320000/132); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + SekExit(); + + seibu_sound_exit(); + + BurnFree (AllMem); + + is_sdgndmps = 0; + + return 0; +} + +static void draw_txt_layer(INT32 scrollx, INT32 scrolly) +{ + UINT16 *vram = (UINT16*)DrvTxRAM; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + code &= 0xfff; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x700, DrvGfxROM0); + } +} + +static void draw_layer(UINT8 *ram, UINT8 *gfx, INT32 col, INT32 scrollx, INT32 scrolly, INT32 trans, INT32 bank) +{ + scrollx &= 0x1ff; + scrolly &= 0x1ff; + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 512; + sy -= scrolly; + if (sy < -15) sy += 512; + + INT32 code = vram[offs]; + INT32 color = (code >> 12) & 0x0f; + code &= 0xfff; + code |= bank; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + if (trans) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, col, gfx); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, col, gfx); + } + } +} + +static inline void draw_sprite(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 fx, INT32 fy) +{ + if (sx < -15 || sy < -15 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0xf, 0, DrvGfxROM4); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0xf, 0, DrvGfxROM4); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0xf, 0, DrvGfxROM4); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0xf, 0, DrvGfxROM4); + } + } +} + +static void draw_sprites(INT32 priority, INT32 yoffset) +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0x400; offs >= 0; offs -= 4) + { + INT32 attr = ram[offs]; + if (~attr & 0x8000) continue; + + INT32 sprite = ram[offs+1]; + + INT32 prio = (sprite >> 14) & 3; + if (prio != priority) continue; + + sprite &= 0x3fff; + + INT32 y = ram[offs+3]; + INT32 x = ram[offs+2]; + + if (x & 0x8000) x = 0 - (0x200 - (x & 0x1ff)); + else x &= 0x1ff; + if (y & 0x8000) y = 0 - (0x200 - (y & 0x1ff)); + else y &= 0x1ff; + + INT32 color = attr & 0x003f; + INT32 fx = attr & 0x4000; + INT32 fy = attr & 0x2000; + INT32 dy = ((attr & 0x0380) >> 7) + 1; + INT32 dx = ((attr & 0x1c00) >> 10) + 1; + + y -= yoffset; + + for (INT32 ax = 0; ax < dx; ax++) + { + for (INT32 ay = 0; ay < dy; ay++) + { + if (!fx && !fy) + { + draw_sprite(sprite, color, x+ax*16, y+ay*16, fx, fy); + draw_sprite(sprite, color, x+ax*16, y+ay*16 + 512, fx, fy); + draw_sprite(sprite, color, x+ax*16, y+ay*16 - 512, fx, fy); + } + else if (fx && !fy) + { + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+ay*16, fx, fy); + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+ay*16 + 512, fx, fy); + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+ay*16 - 512, fx, fy); + } + else if (!fx && fy) + { + draw_sprite(sprite, color, x+ax*16, y+(dy-1-ay)*16, fx, fy); + draw_sprite(sprite, color, x+ax*16, y+(dy-1-ay)*16 + 512, fx, fy); + draw_sprite(sprite, color, x+ax*16, y+(dy-1-ay)*16 - 512, fx, fy); + } + else + { + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+(dy-1-ay)*16, fx, fy); + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+(dy-1-ay)*16 + 512, fx, fy); + draw_sprite(sprite, color, x+(dx-1-ax)*16, y+(dy-1-ay)*16 - 512, fx, fy); + } + + sprite++; + sprite &= 0x3fff; + } + } + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000/2; i++) { + INT32 d = p[i]; + + b = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + r = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void DrvDraw(INT32 xoffset, INT32 yoffset) +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + if (~gfx_enable & 1) { + draw_layer(DrvBgRAM, DrvGfxROM1, 0x400, scroll[0] + xoffset, scroll[1] + yoffset, 0, 0); + } else { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) + pTransDraw[i] = 0x0f; + } + + draw_sprites(2, yoffset); + + if (~gfx_enable & 2) draw_layer(DrvMgRAM, DrvGfxROM3, 0x500, scroll[2] + xoffset, scroll[3] + yoffset, 1, gfx_bank); + + draw_sprites(1, yoffset); + + if (~gfx_enable & 4) draw_layer(DrvFgRAM, DrvGfxROM2, 0x600, scroll[4] + xoffset, scroll[5] + yoffset, 1, 0); + + draw_sprites(0, yoffset); + + draw_txt_layer(xoffset, yoffset); + + draw_sprites(3, yoffset); + + BurnTransferCopy(DrvPalette); +} + +static INT32 DconDraw() +{ + DrvDraw(0, 0); + + return 0; +} + +static INT32 SdgndmpsDraw() +{ + DrvDraw(128, 16); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + seibu_coin_input = (DrvJoy1[1] << 1) | DrvJoy1[0]; + } + + INT32 nSegment; + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + INT32 nTotalCycles[2] = { 10000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + if (is_sdgndmps) + { + for (INT32 i = 0; i < nInterleave; i++) + { + SekRun(nTotalCycles[0] / nInterleave); + ZetRun(nTotalCycles[1] / nInterleave); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + seibu_sound_update(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + else + { + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nTotalCycles[0] / nInterleave; + + nCyclesDone[0] += SekRun(nSegment); + + BurnTimerUpdateYM3812(i * (nTotalCycles[1] / nInterleave)); + } + + BurnTimerEndFrameYM3812(nTotalCycles[1]); + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut && !is_sdgndmps) { + seibu_sound_update(pBurnSoundOut, nBurnSoundLen); + } else { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + seibu_sound_update(pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029706; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + seibu_sound_scan(pnMin, nAction); + + SCAN_VAR(gfx_bank); + SCAN_VAR(gfx_enable); + } + + return 0; +} + + +// D-Con + +static struct BurnRomInfo dconRomDesc[] = { + { "p0-0", 0x020000, 0xa767ec15, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "p0-1", 0x020000, 0xa7efa091, 1 | BRF_PRG | BRF_ESS }, // 1 + { "p1-0", 0x020000, 0x3ec1ef7d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "p1-1", 0x020000, 0x4b8de320, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fmsnd", 0x010000, 0x50450faa, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "fix0", 0x010000, 0xab30061f, 3 | BRF_GRA }, // 5 Characters + { "fix1", 0x010000, 0xa0582115, 3 | BRF_GRA }, // 6 + + { "bg1", 0x080000, 0xeac43283, 4 | BRF_GRA }, // 7 Background Tiles + + { "bg3", 0x080000, 0x1408a1e0, 5 | BRF_GRA }, // 8 Foreground Tiles + + { "bg2", 0x080000, 0x01864eb6, 6 | BRF_GRA }, // 9 Midground Tiles + + { "obj0", 0x080000, 0xc3af37db, 7 | BRF_GRA }, // 10 Sprites + { "obj1", 0x080000, 0xbe1f53ba, 7 | BRF_GRA }, // 11 + { "obj2", 0x080000, 0x24e0b51c, 7 | BRF_GRA }, // 12 + { "obj3", 0x080000, 0x5274f02d, 7 | BRF_GRA }, // 13 + + { "pcm", 0x020000, 0xd2133b85, 8 | BRF_SND }, // 14 OKIM6295 Samples +}; + +STD_ROM_PICK(dcon) +STD_ROM_FN(dcon) + +struct BurnDriver BurnDrvDcon = { + "dcon", NULL, NULL, NULL, "1992", + "D-Con\0", NULL, "Success", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, dconRomInfo, dconRomName, NULL, NULL, DconInputInfo, DconDIPInfo, + DrvInit, DrvExit, DrvFrame, DconDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// SD Gundam Psycho Salamander no Kyoui + +static struct BurnRomInfo sdgndmpsRomDesc[] = { + { "911-a01.25", 0x020000, 0x3362915d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "911-a02.29", 0x020000, 0xfbc78285, 1 | BRF_PRG | BRF_ESS }, // 1 + { "911-a03.27", 0x020000, 0x6c24b4f2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "911-a04.28", 0x020000, 0x6ff9d716, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "911-a05.010", 0x010000, 0x90455406, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "911-a08.66", 0x010000, 0xe7e04823, 3 | BRF_GRA }, // 5 Characters + { "911-a07.73", 0x010000, 0x6f40d4a9, 3 | BRF_GRA }, // 6 + + { "911-a12.63", 0x080000, 0x8976bbb6, 4 | BRF_GRA }, // 7 Background Tiles + + { "911-a11.65", 0x080000, 0x3f3b7810, 5 | BRF_GRA }, // 8 Foreground Tiles + + { "911-a13.64", 0x100000, 0xf38a584a, 6 | BRF_GRA }, // 9 Midground Tiles + + { "911-a10.73", 0x100000, 0x80e341fb, 7 | BRF_GRA }, // 10 Sprites + { "911-a09.74", 0x100000, 0x98f34519, 7 | BRF_GRA }, // 11 + + { "911-a06.97", 0x040000, 0x12c79440, 8 | BRF_SND }, // 12 OKIM6295 Samples + + { "bnd-007.88", 0x000200, 0x96f7646e, 0 | BRF_OPT }, // 13 Priority Prom (not used) +}; + +STD_ROM_PICK(sdgndmps) +STD_ROM_FN(sdgndmps) + +static INT32 SdgndmpsInit() +{ + INT32 nRet = DrvInit(); + + if (nRet == 0) + { + // Patch out protection? + *((UINT16 *)(Drv68KROM + 0x04de)) = 0x4245; + *((UINT16 *)(Drv68KROM + 0x04e0)) = 0x4e71; + *((UINT16 *)(Drv68KROM + 0x04e2)) = 0x4e71; + *((UINT16 *)(Drv68KROM + 0x1356)) = 0x4e71; + *((UINT16 *)(Drv68KROM + 0x1358)) = 0x4e71; + } + + return nRet; +} + +struct BurnDriver BurnDrvSdgndmps = { + "sdgndmps", NULL, NULL, NULL, "1991", + "SD Gundam Psycho Salamander no Kyoui\0", NULL, "Banpresto / Bandai", "Miscellaneous", + L"\u30AC\u30F3\u30C0\u30E0 \u30B5\u30A4\u30B3\u30B5\u30E9\u30DE\uF303\u30C0\u30FC\u306E\u8105\u5A01\0SD Gundam Psycho Salamander no Kyoui\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, sdgndmpsRomInfo, sdgndmpsRomName, NULL, NULL, DconInputInfo, SdgndmpsDIPInfo, + SdgndmpsInit, DrvExit, DrvFrame, SdgndmpsDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_ddragon3.cpp b/src/burn/drivers/misc_post90s/d_ddragon3.cpp new file mode 100644 index 00000000..d6bed5d2 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_ddragon3.cpp @@ -0,0 +1,2104 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[4] = {0, 0, 0, 0}; +static UINT8 DrvInput[4] = {0x00, 0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvMSM6295ROMSrc = NULL; +static UINT8 *DrvFgVideoRam = NULL; +static UINT8 *DrvBgVideoRam = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT16 DrvBgTileBase; +static UINT16 DrvBgScrollX; +static UINT16 DrvBgScrollY; +static UINT16 DrvFgScrollX; +static UINT16 DrvFgScrollY; +static UINT16 DrvVReg; +static UINT8 DrvSoundLatch; +static UINT8 DrvOkiBank; +static UINT8 DrvVBlank; + +typedef void (*Render)(); +static Render DrawFunction; +static void DrvDraw(); +static void CtribeDraw(); + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 start" }, + {"Start 3" , BIT_DIGITAL , DrvInputPort3 + 7, "p3 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 fire 3" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort3 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort3 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort3 + 1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort3 + 0, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 5, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , DrvInputPort3 + 6, "p3 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort1 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, + {"Dip 4" , BIT_DIPSWITCH, DrvDip + 3 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = DrvInput[3] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + DrvInput[3] |= (DrvInputPort3[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[2]); + DrvClearOpposites(&DrvInput[3]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x1c, 0xff, 0xff, 0xff, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x1c, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x1c, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x1c, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x1c, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Continue Discount" }, + {0x1c, 0x01, 0x10, 0x10, "Off" }, + {0x1c, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1c, 0x01, 0x20, 0x00, "Off" }, + {0x1c, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1c, 0x01, 0x40, 0x40, "Off" }, + {0x1c, 0x01, 0x40, 0x00, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1d, 0x01, 0x03, 0x02, "Easy" }, + {0x1d, 0x01, 0x03, 0x03, "Normal" }, + {0x1d, 0x01, 0x03, 0x01, "Hard" }, + {0x1d, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Player vs Player Damage"}, + {0x1d, 0x01, 0x04, 0x04, "Off" }, + {0x1d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x1d, 0x01, 0x10, 0x10, "Off" }, + {0x1d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Stage Clear Energy" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "50" }, + + {0 , 0xfe, 0 , 2 , "Starting Energy" }, + {0x1d, 0x01, 0x40, 0x00, "200" }, + {0x1d, 0x01, 0x40, 0x40, "230" }, + + {0 , 0xfe, 0 , 2 , "Number of Players" }, + {0x1d, 0x01, 0x80, 0x80, "2" }, + {0x1d, 0x01, 0x80, 0x00, "3" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo DrvbDIPList[]= +{ + // Default Values + {0x1c, 0xff, 0xff, 0x10, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1c, 0x01, 0x10, 0x10, "Off" }, + {0x1c, 0x01, 0x10, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x1d, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x1d, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x1d, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x1d, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Continue Discount" }, + {0x1d, 0x01, 0x10, 0x10, "Off" }, + {0x1d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1e, 0x01, 0x03, 0x02, "Easy" }, + {0x1e, 0x01, 0x03, 0x03, "Normal" }, + {0x1e, 0x01, 0x03, 0x01, "Hard" }, + {0x1e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Player vs Player Damage"}, + {0x1e, 0x01, 0x04, 0x04, "Off" }, + {0x1e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x1e, 0x01, 0x10, 0x10, "Off" }, + {0x1e, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Stage Clear Energy" }, + {0x1e, 0x01, 0x20, 0x00, "Off" }, + {0x1e, 0x01, 0x20, 0x20, "50" }, + + // Dip 4 + {0 , 0xfe, 0 , 2 , "Starting Energy" }, + {0x1f, 0x01, 0x01, 0x00, "200" }, + {0x1f, 0x01, 0x01, 0x01, "230" }, + + {0 , 0xfe, 0 , 2 , "Number of Players" }, + {0x1f, 0x01, 0x02, 0x02, "2" }, + {0x1f, 0x01, 0x02, 0x00, "3" }, +}; + +STDDIPINFO(Drvb) + +static struct BurnDIPInfo CtribeDIPList[]= +{ + // Default Values + {0x1c, 0xff, 0xff, 0x10, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1c, 0x01, 0x10, 0x10, "Off" }, + {0x1c, 0x01, 0x10, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x1d, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x1d, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x1d, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x1d, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Continue Discount" }, + {0x1d, 0x01, 0x10, 0x10, "Off" }, + {0x1d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1e, 0x01, 0x03, 0x02, "Easy" }, + {0x1e, 0x01, 0x03, 0x03, "Normal" }, + {0x1e, 0x01, 0x03, 0x01, "Hard" }, + {0x1e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Timer Speed" }, + {0x1e, 0x01, 0x04, 0x04, "Normal" }, + {0x1e, 0x01, 0x04, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "FBI Logo" }, + {0x1e, 0x01, 0x08, 0x00, "Off" }, + {0x1e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x1e, 0x01, 0x10, 0x10, "Off" }, + {0x1e, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Stage Clear Energy" }, + {0x1e, 0x01, 0x20, 0x20, "0" }, + {0x1e, 0x01, 0x20, 0x00, "50" }, + + // Dip 4 + {0 , 0xfe, 0 , 2 , "More Stage Clear Energy"}, + {0x1f, 0x01, 0x01, 0x01, "Off" }, + {0x1f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Number of Players" }, + {0x1f, 0x01, 0x02, 0x02, "2" }, + {0x1f, 0x01, 0x02, 0x00, "3" }, +}; + +STDDIPINFO(Ctribe) + +static struct BurnRomInfo DrvRomDesc[] = { + { "30a14-0.ic78", 0x40000, 0xf42fe016, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "30a15-0.ic79", 0x20000, 0xad50e92c, BRF_ESS | BRF_PRG }, // 1 + + { "30a13-0.ic43", 0x10000, 0x1e974d9b, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "30j-7.ic4", 0x40000, 0x89d58d32, BRF_GRA }, // 3 Tiles + { "30j-6.ic5", 0x40000, 0x9bf1538e, BRF_GRA }, // 4 + { "30j-5.ic6", 0x40000, 0x8f671a62, BRF_GRA }, // 5 + { "30j-4.ic7", 0x40000, 0x0f74ea1c, BRF_GRA }, // 6 + + { "30j-3.ic9", 0x80000, 0xb3151871, BRF_GRA }, // 7 Sprites + { "30a12-0.ic8", 0x10000, 0x20d64bea, BRF_GRA }, // 8 + { "30j-2.ic11", 0x80000, 0x41c6fb08, BRF_GRA }, // 9 + { "30a11-0.ic10", 0x10000, 0x785d71b0, BRF_GRA }, // 10 + { "30j-1.ic13", 0x80000, 0x67a6f114, BRF_GRA }, // 11 + { "30a10-0.ic12", 0x10000, 0x15e43d12, BRF_GRA }, // 12 + { "30j-0.ic15", 0x80000, 0xf15dafbe, BRF_GRA }, // 13 + { "30a9-0.ic14", 0x10000, 0x5a47e7a4, BRF_GRA }, // 14 + + { "30j-8.ic73", 0x80000, 0xc3ad40f3, BRF_SND }, // 15 Samples + + { "mb7114h.ic38", 0x00100, 0x113c7443, BRF_GRA }, // 16 PROM +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "30j15.ic78", 0x40000, 0x40618cbc, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "30j14.ic79", 0x20000, 0x96827e80, BRF_ESS | BRF_PRG }, // 1 + + { "30j13.ic43", 0x10000, 0x1e974d9b, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "30j-7.ic4", 0x40000, 0x89d58d32, BRF_GRA }, // 3 Tiles + { "30j-6.ic5", 0x40000, 0x9bf1538e, BRF_GRA }, // 4 + { "30j-5.ic6", 0x40000, 0x8f671a62, BRF_GRA }, // 5 + { "30j-4.ic7", 0x40000, 0x0f74ea1c, BRF_GRA }, // 6 + + { "30j-3.ic9", 0x80000, 0xb3151871, BRF_GRA }, // 7 Sprites + { "30j12-0.ic8", 0x10000, 0x1e9290d7, BRF_GRA }, // 8 + { "30j-2.ic11", 0x80000, 0x41c6fb08, BRF_GRA }, // 9 + { "30j11-0.ic10", 0x10000, 0x99195b2a, BRF_GRA }, // 10 + { "30j-1.ic13", 0x80000, 0x67a6f114, BRF_GRA }, // 11 + { "30j10-0.ic12", 0x10000, 0xe3879b5d, BRF_GRA }, // 12 + { "30j-0.ic15", 0x80000, 0xf15dafbe, BRF_GRA }, // 13 + { "30j9-0.ic14", 0x10000, 0x2759ae84, BRF_GRA }, // 14 + + { "30j-8.ic73", 0x80000, 0xc3ad40f3, BRF_SND }, // 15 Samples + + { "mb7114h.ic38", 0x00100, 0x113c7443, BRF_GRA }, // 16 PROM +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo DrvpRomDesc[] = { + { "30a14-0.ic80", 0x40000, 0xf42fe016, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "30a15-0.ic79", 0x20000, 0xad50e92c, BRF_ESS | BRF_PRG }, // 1 + + { "30a13-0.ic43", 0x10000, 0x1e974d9b, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "14.ic45", 0x20000, 0xb036a27b, BRF_GRA }, // 3 Tiles + { "15.ic46", 0x20000, 0x24d0bf41, BRF_GRA }, // 4 + { "30.ic13", 0x20000, 0x72fe2b16, BRF_GRA }, // 5 + { "31.ic14", 0x20000, 0xab48a0c8, BRF_GRA }, // 6 + { "23.ic29", 0x20000, 0x0768fedd, BRF_GRA }, // 7 + { "24.ic30", 0x20000, 0xec9db18a, BRF_GRA }, // 8 + { "21.ic25", 0x20000, 0x902744b9, BRF_GRA }, // 9 + { "22.ic26", 0x20000, 0x5b142d4d, BRF_GRA }, // 10 + + { "9.ic39", 0x20000, 0x726c49b7, BRF_GRA }, // 11 Sprites + { "10.ic40", 0x20000, 0x37a1c335, BRF_GRA }, // 12 + { "11.ic41", 0x20000, 0x2bcfe63c, BRF_GRA }, // 13 + { "12.ic42", 0x20000, 0xb864cf17, BRF_GRA }, // 14 + { "4.ic33", 0x20000, 0x8c71eb06, BRF_GRA }, // 15 + { "5.ic34", 0x20000, 0x3e134be9, BRF_GRA }, // 16 + { "6.ic35", 0x20000, 0xb4115ef0, BRF_GRA }, // 17 + { "7.ic36", 0x20000, 0x4639333d, BRF_GRA }, // 18 + { "16.ic19", 0x20000, 0x04420cc8, BRF_GRA }, // 19 + { "17.ic20", 0x20000, 0x33f97b2f, BRF_GRA }, // 20 + { "18.ic21", 0x20000, 0x0f9a8f2a, BRF_GRA }, // 21 + { "19.ic22", 0x20000, 0x15c91772, BRF_GRA }, // 22 + { "25.ic3", 0x20000, 0x894734b3, BRF_GRA }, // 23 + { "26.ic4", 0x20000, 0xcd504584, BRF_GRA }, // 24 + { "27.ic5", 0x20000, 0x38e8a9ad, BRF_GRA }, // 25 + { "28.ic6", 0x20000, 0x80c1cb74, BRF_GRA }, // 26 + { "30a12-0.ic43", 0x20000, 0x91da004c, BRF_GRA }, // 27 + { "30a11-0.ic37", 0x20000, 0x5f419232, BRF_GRA }, // 28 + { "30a10-0.ic23", 0x20000, 0x12f641ba, BRF_GRA }, // 29 + { "30a9-0.ic7", 0x20000, 0x9199a77b, BRF_GRA }, // 30 + + { "2.ic73", 0x40000, 0x3af21dbe, BRF_SND }, // 31 Samples + { "3.ic74", 0x40000, 0xc28b53cd, BRF_SND }, // 32 + + { "30.ic38", 0x00100, 0x113c7443, BRF_GRA }, // 33 PROM +}; + +STD_ROM_PICK(Drvp) +STD_ROM_FN(Drvp) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "dd3.01", 0x20000, 0x68321d8b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "dd3.03", 0x20000, 0xbc05763b, BRF_ESS | BRF_PRG }, // 1 + { "dd3.02", 0x20000, 0x38d9ae75, BRF_ESS | BRF_PRG }, // 2 + + { "dd3.06", 0x10000, 0x1e974d9b, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "dd3.f", 0x40000, 0x89d58d32, BRF_GRA }, // 4 Tiles + { "dd3.e", 0x40000, 0x9bf1538e, BRF_GRA }, // 5 + { "dd3.b", 0x40000, 0x8f671a62, BRF_GRA }, // 6 + { "dd3.a", 0x40000, 0x0f74ea1c, BRF_GRA }, // 7 + + { "dd3.3e", 0x20000, 0x726c49b7, BRF_GRA }, // 8 Sprites + { "dd3.3d", 0x20000, 0x37a1c335, BRF_GRA }, // 9 + { "dd3.3c", 0x20000, 0x2bcfe63c, BRF_GRA }, // 10 + { "dd3.3b", 0x20000, 0xb864cf17, BRF_GRA }, // 11 + { "dd3.3a", 0x10000, 0x20d64bea, BRF_GRA }, // 12 + { "dd3.2e", 0x20000, 0x8c71eb06, BRF_GRA }, // 13 + { "dd3.2d", 0x20000, 0x3e134be9, BRF_GRA }, // 14 + { "dd3.2c", 0x20000, 0xb4115ef0, BRF_GRA }, // 15 + { "dd3.2b", 0x20000, 0x4639333d, BRF_GRA }, // 16 + { "dd3.2a", 0x10000, 0x785d71b0, BRF_GRA }, // 17 + { "dd3.1e", 0x20000, 0x04420cc8, BRF_GRA }, // 18 + { "dd3.1d", 0x20000, 0x33f97b2f, BRF_GRA }, // 19 + { "dd3.1c", 0x20000, 0x0f9a8f2a, BRF_GRA }, // 20 + { "dd3.1b", 0x20000, 0x15c91772, BRF_GRA }, // 21 + { "dd3.1a", 0x10000, 0x15e43d12, BRF_GRA }, // 22 + { "dd3.0e", 0x20000, 0x894734b3, BRF_GRA }, // 23 + { "dd3.0d", 0x20000, 0xcd504584, BRF_GRA }, // 24 + { "dd3.0c", 0x20000, 0x38e8a9ad, BRF_GRA }, // 25 + { "dd3.0b", 0x20000, 0x80c1cb74, BRF_GRA }, // 26 + { "dd3.0a", 0x10000, 0x5a47e7a4, BRF_GRA }, // 27 + + { "dd3.j7", 0x40000, 0x3af21dbe, BRF_SND }, // 28 Samples + { "dd3.j8", 0x40000, 0xc28b53cd, BRF_SND }, // 29 + + { "mb7114h.38", 0x00100, 0x113c7443, BRF_GRA }, // 30 PROM +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo CtribeRomDesc[] = { + { "28a16-2.ic26", 0x20000, 0xc46b2e63, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "28a15-2.ic25", 0x20000, 0x3221c755, BRF_ESS | BRF_PRG }, // 1 + { "28j17-0.104", 0x10000, 0x8c2c6dbd, BRF_ESS | BRF_PRG }, // 2 + + { "28a10-0.ic89", 0x08000, 0x4346de13, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "28j7-0.ic11", 0x40000, 0xa8b773f1, BRF_GRA }, // 4 Tiles + { "28j6-0.ic13", 0x40000, 0x617530fc, BRF_GRA }, // 5 + { "28j5-0.ic12", 0x40000, 0xcef0a821, BRF_GRA }, // 6 + { "28j4-0.ic14", 0x40000, 0xb84fda09, BRF_GRA }, // 7 + + { "28j3-0.ic77", 0x80000, 0x1ac2a461, BRF_GRA }, // 8 Sprites + { "28a14-0.ic60", 0x10000, 0x972faddb, BRF_GRA }, // 9 + { "28j2-0.ic78", 0x80000, 0x8c796707, BRF_GRA }, // 10 + { "28a13-0.ic61", 0x10000, 0xeb3ab374, BRF_GRA }, // 11 + { "28j1-0.ic97", 0x80000, 0x1c9badbd, BRF_GRA }, // 12 + { "28a12-0.ic85", 0x10000, 0xc602ac97, BRF_GRA }, // 13 + { "28j0-0.ic98", 0x80000, 0xba73c49e, BRF_GRA }, // 14 + { "28a11-0.ic86", 0x10000, 0x4da1d8e5, BRF_GRA }, // 15 + + { "28j9-0.ic83", 0x20000, 0xf92a7f4a, BRF_SND }, // 16 Samples + { "28j8-0.ic82", 0x20000, 0x1a3a0b39, BRF_SND }, // 17 + + { "28.ic44", 0x00100, 0x964329ef, BRF_GRA }, // 18 PROM +}; + +STD_ROM_PICK(Ctribe) +STD_ROM_FN(Ctribe) + +static struct BurnRomInfo Ctribe1RomDesc[] = { + { "1_28a16-2.ic26",0x20000, 0xf00f8443, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "1_28a15-2.ic25",0x20000, 0xdd70079f, BRF_ESS | BRF_PRG }, // 1 + { "28j17-0.104", 0x10000, 0x8c2c6dbd, BRF_ESS | BRF_PRG }, // 2 + + { "28a10-0.ic89", 0x08000, 0x4346de13, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "28j7-0.ic11", 0x40000, 0xa8b773f1, BRF_GRA }, // 4 Tiles + { "28j6-0.ic13", 0x40000, 0x617530fc, BRF_GRA }, // 5 + { "28j5-0.ic12", 0x40000, 0xcef0a821, BRF_GRA }, // 6 + { "28j4-0.ic14", 0x40000, 0xb84fda09, BRF_GRA }, // 7 + + { "28j3-0.ic77", 0x80000, 0x1ac2a461, BRF_GRA }, // 8 Sprites + { "28a14-0.ic60", 0x10000, 0x972faddb, BRF_GRA }, // 9 + { "28j2-0.ic78", 0x80000, 0x8c796707, BRF_GRA }, // 10 + { "28a13-0.ic61", 0x10000, 0xeb3ab374, BRF_GRA }, // 11 + { "28j1-0.ic97", 0x80000, 0x1c9badbd, BRF_GRA }, // 12 + { "28a12-0.ic85", 0x10000, 0xc602ac97, BRF_GRA }, // 13 + { "28j0-0.ic98", 0x80000, 0xba73c49e, BRF_GRA }, // 14 + { "28a11-0.ic86", 0x10000, 0x4da1d8e5, BRF_GRA }, // 15 + + { "28j9-0.ic83", 0x20000, 0xf92a7f4a, BRF_SND }, // 16 Samples + { "28j8-0.ic82", 0x20000, 0x1a3a0b39, BRF_SND }, // 17 + + { "28.ic44", 0x00100, 0x964329ef, BRF_GRA }, // 18 PROM +}; + +STD_ROM_PICK(Ctribe1) +STD_ROM_FN(Ctribe1) + +static struct BurnRomInfo CtribejRomDesc[] = { + { "28j16-02.26", 0x20000, 0x658b8568, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "28j15-12.25", 0x20000, 0x50aac7e7, BRF_ESS | BRF_PRG }, // 1 + { "28j17-0.104", 0x10000, 0x8c2c6dbd, BRF_ESS | BRF_PRG }, // 2 + + { "28j10-0.89", 0x08000, 0x4346de13, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "28j7-0.ic11", 0x40000, 0xa8b773f1, BRF_GRA }, // 4 Tiles + { "28j6-0.ic13", 0x40000, 0x617530fc, BRF_GRA }, // 5 + { "28j5-0.ic12", 0x40000, 0xcef0a821, BRF_GRA }, // 6 + { "28j4-0.ic14", 0x40000, 0xb84fda09, BRF_GRA }, // 7 + + { "28j3-0.ic77", 0x80000, 0x1ac2a461, BRF_GRA }, // 8 Sprites + { "28j14-0.60", 0x10000, 0x6869050a, BRF_GRA }, // 9 + { "28j2-0.ic78", 0x80000, 0x8c796707, BRF_GRA }, // 10 + { "28j13-0.61", 0x10000, 0x8b8addea, BRF_GRA }, // 11 + { "28j1-0.ic97", 0x80000, 0x1c9badbd, BRF_GRA }, // 12 + { "28j12-0.85", 0x10000, 0x422b041c, BRF_GRA }, // 13 + { "28j0-0.ic98", 0x80000, 0xba73c49e, BRF_GRA }, // 14 + { "28j11-0.86", 0x10000, 0x4a391c5b, BRF_GRA }, // 15 + + { "28j9-0.ic83", 0x20000, 0xf92a7f4a, BRF_SND }, // 16 Samples + { "28j8-0.ic82", 0x20000, 0x1a3a0b39, BRF_SND }, // 17 + + { "28.ic44", 0x00100, 0x964329ef, BRF_GRA }, // 18 PROM +}; + +STD_ROM_PICK(Ctribej) +STD_ROM_FN(Ctribej) + +static struct BurnRomInfo CtribebRomDesc[] = { + { "ct_ep1.rom", 0x20000, 0x9cfa997f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ct_ep3.rom", 0x20000, 0x2ece8681, BRF_ESS | BRF_PRG }, // 1 + { "ct_ep2.rom", 0x10000, 0x8c2c6dbd, BRF_ESS | BRF_PRG }, // 2 + + { "ct_ep4.rom", 0x08000, 0x4346de13, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "ct_mr7.rom", 0x40000, 0xa8b773f1, BRF_GRA }, // 4 Tiles + { "ct_mr6.rom", 0x40000, 0x617530fc, BRF_GRA }, // 5 + { "ct_mr5.rom", 0x40000, 0xcef0a821, BRF_GRA }, // 6 + { "ct_mr4.rom", 0x40000, 0xb84fda09, BRF_GRA }, // 7 + + { "ct_mr3.rom", 0x80000, 0x1ac2a461, BRF_GRA }, // 8 Sprites + { "ct_ep5.rom", 0x10000, 0x972faddb, BRF_GRA }, // 9 + { "ct_mr2.rom", 0x80000, 0x8c796707, BRF_GRA }, // 10 + { "ct_ep6.rom", 0x10000, 0xeb3ab374, BRF_GRA }, // 11 + { "ct_mr1.rom", 0x80000, 0x1c9badbd, BRF_GRA }, // 12 + { "ct_ep7.rom", 0x10000, 0xc602ac97, BRF_GRA }, // 13 + { "ct_mr0.rom", 0x80000, 0xba73c49e, BRF_GRA }, // 14 + { "ct_ep8.rom", 0x10000, 0x4da1d8e5, BRF_GRA }, // 15 + + { "ct_mr8.rom", 0x40000, 0x9963a6be, BRF_SND }, // 16 Samples +}; + +STD_ROM_PICK(Ctribeb) +STD_ROM_FN(Ctribeb) + +static struct BurnRomInfo Ctribeb2RomDesc[] = { + { "1.bin", 0x20000, 0x9cfa997f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "3.bin", 0x20000, 0x2ece8681, BRF_ESS | BRF_PRG }, // 1 + { "2.bin", 0x10000, 0x8c2c6dbd, BRF_ESS | BRF_PRG }, // 2 + + { "6.bin", 0x10000, 0x0101df2d, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "7.bin", 0x40000, 0xa8b773f1, BRF_GRA }, // 4 Tiles + { "8.bin", 0x40000, 0x617530fc, BRF_GRA }, // 5 + { "11.bin", 0x40000, 0xcef0a821, BRF_GRA }, // 6 + { "12.bin", 0x40000, 0xb84fda09, BRF_GRA }, // 7 + { "9.bin", 0x20000, 0x2719d7ce, BRF_GRA }, // 8 + { "10.bin", 0x20000, 0x753a4f53, BRF_GRA }, // 9 + { "13.bin", 0x20000, 0x59e01fe1, BRF_GRA }, // 10 + { "14.bin", 0x20000, 0xa69ab4f3, BRF_GRA }, // 11 + + { "34.bin", 0x20000, 0x5b498f0e, BRF_GRA }, // 12 Sprites + { "33.bin", 0x20000, 0x14d79049, BRF_GRA }, // 13 + { "32.bin", 0x20000, 0x9631ea23, BRF_GRA }, // 14 + { "31.bin", 0x20000, 0x0ca8d3b9, BRF_GRA }, // 15 + { "30.bin", 0x10000, 0x972faddb, BRF_GRA }, // 16 + { "29.bin", 0x20000, 0x479ae8ea, BRF_GRA }, // 17 + { "28.bin", 0x20000, 0x95598bbf, BRF_GRA }, // 18 + { "27.bin", 0x20000, 0x4a3d006d, BRF_GRA }, // 19 + { "26.bin", 0x20000, 0xaa34a3cb, BRF_GRA }, // 20 + { "25.bin", 0x10000, 0xeb3ab374, BRF_GRA }, // 21 + { "24.bin", 0x20000, 0xd60bbff0, BRF_GRA }, // 22 + { "23.bin", 0x20000, 0xd9595c47, BRF_GRA }, // 23 + { "22.bin", 0x20000, 0x5a19a911, BRF_GRA }, // 24 + { "21.bin", 0x20000, 0x071360f9, BRF_GRA }, // 25 + { "20.bin", 0x10000, 0xc602ac97, BRF_GRA }, // 26 + { "19.bin", 0x20000, 0x8d22736a, BRF_GRA }, // 27 + { "18.bin", 0x20000, 0x0f157822, BRF_GRA }, // 28 + { "17.bin", 0x20000, 0x7f48c824, BRF_GRA }, // 29 + { "16.bin", 0x20000, 0xcd1e9bd5, BRF_GRA }, // 30 + { "15.bin", 0x10000, 0x4da1d8e5, BRF_GRA }, // 31 + + { "5.bin", 0x20000, 0xf92a7f4a, BRF_SND }, // 32 Samples + { "4.bin", 0x20000, 0x1a3a0b39, BRF_SND }, // 33 +}; + +STD_ROM_PICK(Ctribeb2) +STD_ROM_FN(Ctribeb2) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x80000; + DrvZ80Rom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x40000; + DrvMSM6295ROMSrc = Next; Next += 0x80000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x04800; + DrvZ80Ram = Next; Next += 0x00800; + DrvFgVideoRam = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x01000; + DrvBgVideoRam = Next; Next += 0x00800; + DrvPaletteRam = Next; Next += 0x00600; + + RamEnd = Next; + + DrvTiles = Next; Next += 8192 * 16 * 16; + DrvSprites = Next; Next += 0x4800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00600 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + DrvBgTileBase = 0; + DrvBgScrollX = 0; + DrvBgScrollY = 0; + DrvFgScrollX = 0; + DrvFgScrollY = 0; + DrvVReg = 0; + DrvSoundLatch = 0; + DrvOkiBank = 0; + DrvVBlank = 0; + + return 0; +} + +UINT8 __fastcall Ddragon368KReadByte(UINT32 a) +{ + switch (a) { + case 0x100000: { + return 0xff - DrvInput[2]; + } + + case 0x100001: { + return 0xff - DrvInput[0]; + } + + case 0x100003: { + return 0xff - DrvInput[1]; + } + + case 0x100007: { + return 0xff - DrvInput[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ddragon368KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x100003: { + DrvSoundLatch = d; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ddragon368KReadWord(UINT32 a) +{ + switch (a) { + case 0x100002: { + return (0xff << 8) | (0xff - DrvInput[1]); + } + + case 0x100004: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ddragon368KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x000004: + case 0x000006: { + // ??? + return; + } + + case 0x0c0000: { + DrvFgScrollX = d & 0x1ff; + return; + } + + case 0x0c0002: { + DrvFgScrollY = d & 0x1ff; + return; + } + + case 0x0c0004: { + DrvBgScrollX = d & 0x1ff; + return; + } + + case 0x0c0006: { + DrvBgScrollY = d & 0x1ff; + return; + } + + case 0x0c0008: { + return; + } + + case 0x0c000c: { + DrvBgTileBase = d & 0x1ff; + return; + } + + case 0x100000: { + DrvVReg = d; + return; + } + + case 0x100002: { + DrvSoundLatch = d; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + case 0x100004: + case 0x100006: + case 0x100008: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Ddragon3b68KReadByte(UINT32 a) +{ + switch (a) { + case 0x180000: { + return 0xef - DrvInput[1] + (DrvDip[0] & 0x10); + } + + case 0x180001: { + return 0xff - DrvInput[0]; + } + + case 0x180002: { + return DrvDip[1]; + } + + case 0x180003: { + return 0xff - DrvInput[2]; + } + + case 0x180005: { + return 0xff - DrvInput[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ddragon3b68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x140003: { + DrvSoundLatch = d; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ddragon3b68KReadWord(UINT32 a) +{ + switch (a) { + case 0x180000: { + return (((0xef - DrvInput[1]) + (DrvDip[0] & 0x10)) << 8) | (0xff - DrvInput[0]); + } + + case 0x180004: { + return (DrvDip[2] << 8) | (0xff - DrvInput[3]); + } + + case 0x180006: { + return (DrvDip[3] << 8) | 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ddragon3b68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x000004: + case 0x000006: { + // ??? + return; + } + + case 0x0c0000: { + DrvFgScrollX = d & 0x1ff; + return; + } + + case 0x0c0002: { + DrvFgScrollY = d & 0x1ff; + return; + } + + case 0x0c0004: { + DrvBgScrollX = d & 0x1ff; + return; + } + + case 0x0c0006: { + DrvBgScrollY = d & 0x1ff; + return; + } + + case 0x0c0008: { + return; + } + + case 0x0c000c: { + DrvBgTileBase = d & 0x1ff; + return; + } + + case 0x140000: { + DrvVReg = d; + return; + } + + case 0x140002: { + DrvSoundLatch = d; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + case 0x140004: + case 0x140006: + case 0x140008: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Ddragon3Z80Read(UINT16 a) +{ + switch (a) { + case 0xc801: { + return BurnYM2151ReadStatus(); + } + + case 0xd800: { + return MSM6295ReadStatus(0); + } + + case 0xe000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Ddragon3Z80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xc801: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xd800: { + MSM6295Command(0, d); + return; + } + + case 0xe800: { + DrvOkiBank = d & 1; + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Ctribeb68KReadByte(UINT32 a) +{ + switch (a) { + case 0x180000: { + if (DrvVBlank) return 0xe7 - DrvInput[1] + (DrvDip[0] & 0x10); + return 0xef - DrvInput[1] + (DrvDip[0] & 0x10); + } + + case 0x180001: { + return 0xff - DrvInput[0]; + } + + case 0x180003: { + return 0xff - DrvInput[2]; + } + + case 0x180004: { + return DrvDip[2]; + } + + case 0x180005: { + return 0xff - DrvInput[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ctribeb68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x0c000d: { + DrvBgTileBase = d; + return; + } + + case 0x140001: { + DrvVReg = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ctribeb68KReadWord(UINT32 a) +{ + switch (a) { + case 0x180000: { + if (DrvVBlank) return ((0xe7 - DrvInput[1] + (DrvDip[0] & 0x10)) << 8) | (0xff - DrvInput[0]); + return ((0xef - DrvInput[1] + (DrvDip[0] & 0x10)) << 8) | (0xff - DrvInput[0]); + } + + case 0x180002: { + return (DrvDip[1] << 8) | (0xff - DrvInput[2]); + } + + case 0x180004: { + return (DrvDip[2] << 8) | (0xff - DrvInput[3]); + } + + case 0x180006: { + return (DrvDip[3] << 8) | 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ctribeb68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x0c0000: { + DrvFgScrollX = d & 0x1ff; + return; + } + + case 0x0c0002: { + DrvFgScrollY = d & 0x1ff; + return; + } + + case 0x0c0004: { + DrvBgScrollX = d & 0x1ff; + return; + } + + case 0x0c0006: { + DrvBgScrollY = d & 0x1ff; + return; + } + + case 0x0c0008: { + return; + } + + case 0x0c000c: { + DrvBgTileBase = d & 0x1ff; + return; + } + + case 0x140000: { + DrvVReg = d; + return; + } + + case 0x140002: { + DrvSoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + case 0x140004: + case 0x140006: + case 0x140008: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall CtribeZ80Read(UINT16 a) +{ + switch (a) { + case 0x8801: { + return BurnYM2151ReadStatus(); + } + + case 0x9800: { + return MSM6295ReadStatus(0); + } + + case 0xa000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall CtribeZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x8800: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x8801: { + BurnYM2151WriteRegister(d); + return; + } + + case 0x9800: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 TilePlaneOffsets[4] = { 0, 0x200000, 0x400000, 0x600000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 SpritePlaneOffsets[4] = { 0, 0x800000, 0x1000000, 0x1800000 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + BurnSetRefreshRate(57.0); + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(8192, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x280000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x380000, 14, 1); if (nRet != 0) return 1; + GfxDecode(0x4800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 15, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvFgVideoRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvBgVideoRam , 0x082000, 0x0827ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1405ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x180000, 0x180fff, SM_RAM); + SekMapMemory(Drv68KRam , 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, Ddragon368KReadWord); + SekSetWriteWordHandler(0, Ddragon368KWriteWord); + SekSetReadByteHandler(0, Ddragon368KReadByte); + SekSetWriteByteHandler(0, Ddragon368KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Ddragon3Z80Read); + ZetSetWriteHandler(Ddragon3Z80Write); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1000000 / 132, 100.0, 1); + + DrawFunction = DrvDraw; + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvpInit() +{ + INT32 nRet = 0, nLen; + + BurnSetRefreshRate(57.0); + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x060000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0a0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c0000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0e0000, 10, 1); if (nRet != 0) return 1; + GfxDecode(8192, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x060000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x120000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x140000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x160000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x220000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x240000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x260000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x320000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x340000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x360000, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x280000, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x380000, 30, 1); if (nRet != 0) return 1; + GfxDecode(0x4800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 31, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x40000, 32, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvFgVideoRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvBgVideoRam , 0x082000, 0x0827ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1405ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x180000, 0x180fff, SM_RAM); + SekMapMemory(Drv68KRam , 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, Ddragon368KReadWord); + SekSetWriteWordHandler(0, Ddragon368KWriteWord); + SekSetReadByteHandler(0, Ddragon368KReadByte); + SekSetWriteByteHandler(0, Ddragon368KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Ddragon3Z80Read); + ZetSetWriteHandler(Ddragon3Z80Write); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1000000 / 132, 100.0, 1); + + DrawFunction = DrvDraw; + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvbInit() +{ + INT32 nRet = 0, nLen; + + BurnSetRefreshRate(57.0); + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00001, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 2, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 3, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c0000, 7, 1); if (nRet != 0) return 1; + GfxDecode(8192, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x060000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x120000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x140000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x160000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x220000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x240000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x260000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x280000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x320000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x340000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x360000, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x380000, 27, 1); if (nRet != 0) return 1; + GfxDecode(0x4800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x40000, 29, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvFgVideoRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x081000, 0x081fff, SM_RAM); + SekMapMemory(DrvBgVideoRam , 0x082000, 0x0827ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x100000, 0x1005ff, SM_RAM); + SekMapMemory(Drv68KRam , 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, Ddragon3b68KReadWord); + SekSetWriteWordHandler(0, Ddragon3b68KWriteWord); + SekSetReadByteHandler(0, Ddragon3b68KReadByte); + SekSetWriteByteHandler(0, Ddragon3b68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Ddragon3Z80Read); + ZetSetWriteHandler(Ddragon3Z80Write); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1000000 / 132, 100.0, 1); + + DrawFunction = DrvDraw; + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 CtribeInit() +{ + INT32 nRet = 0, nLen; + + BurnSetRefreshRate(57.0); + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00001, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 2, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 3, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c0000, 7, 1); if (nRet != 0) return 1; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ctribeb2")) { + nRet = BurnLoadRom(DrvTempRom + 0x100000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x140000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x1c0000, 11, 1); if (nRet != 0) return 1; + } + GfxDecode(8192, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x400000); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ctribeb2")) { + nRet = BurnLoadRom(DrvTempRom + 0x000000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x060000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x120000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x140000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x160000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x220000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x240000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x260000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x280000, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x320000, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x340000, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x360000, 30, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x380000, 31, 1); if (nRet != 0) return 1; + } else { + nRet = BurnLoadRom(DrvTempRom + 0x000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x280000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x380000, 15, 1); if (nRet != 0) return 1; + } + GfxDecode(0x4800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load Sample Roms + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ctribeb")) { + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom, 16, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM + 0x20000, DrvTempRom + 0x00000, 0x20000); + memcpy(MSM6295ROM + 0x00000, DrvTempRom + 0x20000, 0x20000); + } else { + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ctribeb2")) { + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 32, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x20000, 33, 1); if (nRet != 0) return 1; + } else { + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x20000, 17, 1); if (nRet != 0) return 1; + } + } + memcpy(DrvMSM6295ROMSrc, MSM6295ROM, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvFgVideoRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x081000, 0x081fff, SM_RAM); + SekMapMemory(DrvBgVideoRam , 0x082000, 0x0827ff, SM_RAM); + SekMapMemory(Drv68KRam , 0x082800, 0x082fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x100000, 0x1005ff, SM_RAM); + SekMapMemory(Drv68KRam + 0x800 , 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, Ctribeb68KReadWord); + SekSetWriteWordHandler(0, Ctribeb68KWriteWord); + SekSetReadByteHandler(0, Ctribeb68KReadByte); + SekSetWriteByteHandler(0, Ctribeb68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(CtribeZ80Read); + ZetSetWriteHandler(CtribeZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1000000 / 132, 10.0, 1); + + DrawFunction = CtribeDraw; + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + ZetExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + + DrawFunction = NULL; + + DrvBgTileBase = 0; + DrvBgScrollX = 0; + DrvBgScrollY = 0; + DrvFgScrollX = 0; + DrvFgScrollY = 0; + DrvVReg = 0; + DrvSoundLatch = 0; + DrvOkiBank = 0; + DrvVBlank = 0; + + BurnFree(Mem); + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 0); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 10); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 CtribeCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x600; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void CtribeCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x600; i++, ps++, pd++) { + *pd = CtribeCalcCol(*ps); + } +} + +static void DrvRenderBgLayer(INT32 Opaque) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvBgVideoRam; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = VideoRam[TileIndex]; + Code = (Attr & 0xfff) | ((DrvBgTileBase & 0x01) << 12); + Colour = ((Attr & 0xf000) >> 12); + + x = 16 * mx; + y = 16 * my; + + x -= DrvBgScrollX; + y -= DrvBgScrollY; + if (x < -16) x += 512; + if (y < -16) y += 512; + + y -= 8; + + if (Opaque) { + if (x > 16 && x < 304 && y > 16 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } + } else { + if (x > 16 && x < 304 && y > 16 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512, DrvTiles); + } + } + + TileIndex++; + } + } +} + +static void DrvRenderFgLayer(INT32 Opaque) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, Offset, xFlip; + + UINT16 *VideoRam = (UINT16*)DrvFgVideoRam; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Offset = TileIndex * 2; + Attr = VideoRam[Offset]; + Code = VideoRam[Offset + 1] & 0x1fff; + Colour = Attr & 0x0f; + xFlip = Attr & 0x40; + + x = 16 * mx; + y = 16 * my; + + x -= DrvFgScrollX; + y -= DrvFgScrollY; + if (x < -16) x += 512; + if (y < -16) y += 512; + + y -= 8; + + if (Opaque) { + if (x > 16 && x < 304 && y > 16 && y < 224) { + if (xFlip) { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } else { + if (xFlip) { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } + } else { + if (x > 16 && x < 304 && y > 16 && y < 224) { + if (xFlip) { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } + } else { + if (xFlip) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } + } + } + + TileIndex++; + } + } +} + +static void DrvRenderSprites() +{ + UINT16 *Source = (UINT16*)DrvSpriteRam; + UINT16 *Finish = Source + 0x800; + + while (Source < Finish) { + UINT16 Attr = Source[1]; + + if (Attr & 0x01) { + INT32 i; + INT32 Bank = Source[3] & 0xff; + INT32 Code = (Source[2] & 0xff) + (Bank * 256); + INT32 Colour = Source[4] & 0xf; + INT32 xFlip = Attr & 0x10; + INT32 yFlip = Attr & 0x08; + INT32 sx = Source[5] & 0xff; + INT32 sy = Source[0] & 0xff; + INT32 Height = (Attr >> 5) & 0x07; + + if (Attr & 0x04) sx |= 0x100; + if (Attr & 0x02) { + sy = 239 + (0x100 - sy); + } else { + sy = 240 - sy; + } + if (sx > 0x17f) sx = 0 - (0x200 - sx); + + sy -= 8; + + for (i = 0; i <= Height; i++) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code + i, sx, sy - (i * 16), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code + i, sx, sy - (i * 16), Colour, 4, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code + i, sx, sy - (i * 16), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code + i, sx, sy - (i * 16), Colour, 4, 0, 0, DrvSprites); + } + } + } + } + + Source += 8; + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + + if ((DrvVReg & 0x60) == 0x40) { + DrvRenderBgLayer(1); + DrvRenderFgLayer(0); + DrvRenderSprites(); + } else if ((DrvVReg & 0x60) == 0x60) { + DrvRenderFgLayer(1); + DrvRenderBgLayer(0); + DrvRenderSprites(); + } else { + DrvRenderBgLayer(1); + DrvRenderSprites(); + DrvRenderFgLayer(0); + } + + BurnTransferCopy(DrvPalette); +} + +static void CtribeDraw() +{ + BurnTransferClear(); + CtribeCalcPalette(); + + if (DrvVReg & 0x08) { + DrvRenderFgLayer(1); + DrvRenderSprites(); + DrvRenderBgLayer(0); + } else { + DrvRenderBgLayer(1); + DrvRenderFgLayer(0); + DrvRenderSprites(); + } + + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + DrvVBlank = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 5) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + if (i == 5) DrvVBlank = 1; + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekOpen(0); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrawFunction(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029674; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); // Scan Z80 + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(DrvBgTileBase); + SCAN_VAR(DrvBgScrollX); + SCAN_VAR(DrvBgScrollY); + SCAN_VAR(DrvFgScrollX); + SCAN_VAR(DrvFgScrollY); + SCAN_VAR(DrvVReg); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvOkiBank); + SCAN_VAR(DrvVBlank); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + } + + return 0; +} + +struct BurnDriver BurnDrvDdragon3 = { + "ddragon3", NULL, NULL, NULL, "1990", + "Double Dragon 3 - The Rosetta Stone (US)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdrago3j = { + "ddragon3j", "ddragon3", NULL, NULL, "1990", + "Double Dragon 3 - The Rosetta Stone (Japan)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdrago3p = { + "ddragon3p", "ddragon3", NULL, NULL, "1990", + "Double Dragon 3 - The Rosetta Stone (prototype)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, DrvpRomInfo, DrvpRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvpInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdrago3b = { + "ddragon3b", "ddragon3", NULL, NULL, "1990", + "Double Dragon 3 - The Rosetta Stone (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvbDIPInfo, + DrvbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCtribe = { + "ctribe", NULL, NULL, NULL, "1990", + "The Combatribes (US)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, CtribeRomInfo, CtribeRomName, NULL, NULL, DrvInputInfo, CtribeDIPInfo, + CtribeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCtribe1 = { + "ctribe1", "ctribe", NULL, NULL, "1990", + "The Combatribes (US) - Set 1?\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, Ctribe1RomInfo, Ctribe1RomName, NULL, NULL, DrvInputInfo, CtribeDIPInfo, + CtribeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCtribej = { + "ctribej", "ctribe", NULL, NULL, "1990", + "The Combatribes (Japan)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, CtribejRomInfo, CtribejRomName, NULL, NULL, DrvInputInfo, CtribeDIPInfo, + CtribeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCtribeb = { + "ctribeb", "ctribe", NULL, NULL, "1990", + "The Combatribes (bootleg set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, CtribebRomInfo, CtribebRomName, NULL, NULL, DrvInputInfo, CtribeDIPInfo, + CtribeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCtribeb2 = { + "ctribeb2", "ctribe", NULL, NULL, "1990", + "The Combatribes (bootleg set 2)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, Ctribeb2RomInfo, Ctribeb2RomName, NULL, NULL, DrvInputInfo, CtribeDIPInfo, + CtribeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_deniam.cpp b/src/burn/drivers/misc_post90s/d_deniam.cpp new file mode 100644 index 00000000..3ccd637b --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_deniam.cpp @@ -0,0 +1,995 @@ +// FB Alpha Deniam-16 Hardware driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvTxtRAM; +static UINT32 *DrvPalette; +static INT16 *DrvTxtTable; +static INT16 *DrvLayerTable; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT8 DrvInputs[3]; + +static INT32 nCyclesDone[2]; + +static UINT8 *soundlatch; +static UINT8 *coin_control; +static UINT8 *okibank; + +static INT32 bg_scrollx_offs; +static INT32 bg_scrolly_offs; +static INT32 fg_scrollx_offs; +static INT32 fg_scrolly_offs; +static INT32 bg_scrollx_reg; +static INT32 bg_scrolly_reg; +static INT32 bg_page_reg; +static INT32 fg_scrollx_reg; +static INT32 fg_scrolly_reg; +static INT32 fg_page_reg; + +static INT32 nGame = 0; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 5, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 4, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 7, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 6, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 5, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 4, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 7, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 6, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 2, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 3, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo KarianxDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x14, 0x01, 0x07, 0x02, "3 Coins 1 Credits " }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits " }, + {0x14, 0x01, 0x07, 0x04, "3 Coins 2 Credits " }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x14, 0x01, 0x07, 0x06, "2 Coins 3 Credits " }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 2 Credits " }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x14, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x18, 0x08, "Very Easy" }, + {0x14, 0x01, 0x18, 0x10, "Easy" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Music" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 1, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Karianx) + +static struct BurnDIPInfo Logicpr2DIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x14, 0x01, 0x07, 0x02, "3 Coins 1 Credits " }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits " }, + {0x14, 0x01, 0x07, 0x04, "3 Coins 2 Credits " }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x14, 0x01, 0x07, 0x06, "2 Coins 3 Credits " }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 2 Credits " }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x14, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Play Time" }, + {0x14, 0x01, 0x18, 0x08, "Slow" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x10, "Fast" }, + {0x14, 0x01, 0x18, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x60, 0x20, "Easy" }, + {0x14, 0x01, 0x60, 0x60, "Normal" }, + {0x14, 0x01, 0x60, 0x40, "Hard" }, + {0x14, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Logicpr2) + +static void deniam16_set_okibank(INT32 bank) +{ + *okibank = bank; + + MSM6295ROM = DrvSndROM + (*okibank ? 0x40000 : 0x00000); +} + +UINT8 __fastcall deniam16_read_byte(UINT32 address) +{ + switch (address) + { + case 0xc40001: + return MSM6295ReadStatus(0); // logicpr2 + + case 0xc40003: + return *coin_control; + + case 0xc44001: + return DrvInputs[0] & 0xff; + + case 0xc44003: + return DrvInputs[1] & 0xff; + + case 0xc44005: + return DrvInputs[2] & 0xff; + + case 0xc4400b: + return DrvDips[0]; + } + + return 0; +} + +void __fastcall deniam16_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xc40000: + if (nGame != 2) { + *soundlatch = data; + ZetNmi(); + } + return; + + case 0xc40001: + if (nGame == 2) { + MSM6295Command(0, data); + } + return; + + case 0xc40003: + *coin_control = data; + return; + + case 0xc40007: + deniam16_set_okibank(data & 0x01); // logicpr2 + return; + + case 0xc40008: + BurnYM3812Write(0, data); // logicpr2 + return; + + case 0xc4000a: + BurnYM3812Write(1, data); // logicpr2 + return; + } +} + +void __fastcall deniam16_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x02: + BurnYM3812Write(0, data); + return; + + case 0x03: + BurnYM3812Write(1, data); + return; + + case 0x05: + MSM6295Command(0, data); + return; + + case 0x07: + deniam16_set_okibank(data & 0x40); + return; + } +} + +UINT8 __fastcall deniam16_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x01: + return *soundlatch; + + case 0x05: + return MSM6295ReadStatus(0); + } + + return 0; +} + +inline static INT32 deniam16ZetSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 6250000); +} + +inline static INT32 deniam16SekSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(SekTotalCycles() * nSoundRate / 12500000); +} + +void deniam16YM3812IrqHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM3812Reset(); + + deniam16_set_okibank(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + DrvTxtTable = (INT16*)Next; Next += 0x0800 * sizeof(INT16); + DrvLayerTable = (INT16*)Next; Next += 0x2000 * sizeof(INT16); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x000800; + DrvTxtRAM = Next; Next += 0x001000; + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x001000; + DrvVidRAM = Next; Next += 0x010000; + + DrvZ80RAM = Next; Next += 0x000800; + + coin_control = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + okibank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void create_offset_tables() +{ + for (INT32 offs = 0; offs < 128 * 64; offs++) + { + INT32 sx = (offs & 0x7f); + INT32 sy = (offs >> 7); + + DrvLayerTable[offs] = (sx & 0x3f) + ((sy & 0x1f) << 6) + ((sx & 0x40) << 5) + ((sy & 0x20) << 7); + } + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f); + INT32 sy = (offs >> 6); + + DrvTxtTable[offs] = (sx & 0x3f) + ((sy & 0x1f) << 6) + ((sx & 0x40) << 5) + ((sy & 0x20) << 7); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { (0x80000 * 8) * 2, (0x80000 * 8) * 1, 0 }; + INT32 XOffs[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x180000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x180000); + + GfxDecode(0x10000, 3, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + switch (nGame) + { + case 0: + { + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 8, 1)) return 1; + } + break; + + case 1: + { + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200001, 11, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 12, 1)) return 1; + } + break; + + case 2: + { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM1, 0x400000); + + if (BurnLoadRom(DrvSndROM + 0x000000, 6, 1)) return 1; + } + break; + } + + DrvGfxDecode(); + create_offset_tables(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvVidRAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(DrvTxtRAM, 0x410000, 0x410fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x440000, 0x4407ff, SM_WRITE); + SekMapMemory(DrvPalRAM, 0x840000, 0x840fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, deniam16_write_byte); + SekSetReadByteHandler(0, deniam16_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xf7ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xf7ff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(deniam16_sound_out); + ZetSetInHandler(deniam16_sound_in); + ZetMemEnd(); + ZetClose(); + + if (nGame != 2) { + BurnYM3812Init(3125000, &deniam16YM3812IrqHandler, deniam16ZetSynchroniseStream, 0); + BurnTimerAttachZetYM3812(6250000); + } else { + BurnYM3812Init(3125000, NULL, deniam16SekSynchroniseStream, 0); + BurnTimerAttachSekYM3812(12500000); + } + + MSM6295Init(0, 1056000 / 132, 100.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM3812Exit(); + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + nGame = 0; + + return 0; +} + +static void palette_write(INT32 offset) +{ + UINT8 r,g,b; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = ((data << 1) & 0x1e) | ((data >> 12) & 1); + g = ((data >> 3) & 0x1e) | ((data >> 13) & 1); + b = ((data >> 7) & 0x1e) | ((data >> 14) & 1); + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +static void draw_sprites(INT32 priority) +{ + UINT16 *source = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0;offs < 0x800/2;offs += 8) + { + if (priority != ((source[offs+4]&0xc0) >> 6)) continue; + + INT32 sx = (source[offs+1] & 0x01ff) + 16*8 - 1; + if (sx >= 512) sx -= 512; + sx -= 192; + INT32 starty = source[offs+0] & 0xff; + if (starty >= nScreenHeight) continue; + INT32 endy = source[offs+0] >> 8; + if (endy >= nScreenHeight) endy = nScreenHeight-1; + + INT32 width = source[offs+2] & 0x007f; + INT32 flipx = source[offs+2] & 0x0100; + if (flipx) sx++; + + INT32 color = (0x40 + (source[offs+4] & 0x3f)) << 4; + + INT32 start = source[offs+3] + ((source[offs+4] & 0x1f00) << 8); + UINT8 *rom = DrvGfxROM1 + start * 2; + + for (INT32 y = starty+1;y <= endy;y++) + { + INT32 drawing = 0; + INT32 i=0; + + rom += 2 * width; + INT32 x = 0; + + UINT16 *dest = pTransDraw + (y * nScreenWidth); + + while (i < 512) + { + if (flipx) + { + if ((rom[i] & 0x0f) == 0x0f) + { + if (!drawing) drawing = 1; + else break; + } + else + { + if (rom[i] & 0x0f) + { + if (sx+x >= 0 && sx+x < nScreenWidth) { + dest[(sx+x)] = color | (rom[i] & 0x0f); + } + } + x++; + } + + if ((rom[i] & 0xf0) == 0xf0) + { + if (!drawing) drawing = 1; + else break; + } + else + { + if (rom[i] & 0xf0) + { + if (sx+x >= 0 && sx+x < nScreenWidth) { + dest[(sx+x)] = color | (rom[i]>>4); + } + } + x++; + } + + i--; + } + else + { + if ((rom[i] & 0xf0) == 0xf0) + { + if (!drawing) drawing = 1; + else break; + } + else + { + if (rom[i] & 0xf0) + { + if (sx+x >= 0 && sx+x < nScreenWidth) { + dest[(sx+x)] = color | (rom[i]>>4); + } + } + x++; + } + + if ((rom[i] & 0x0f) == 0x0f) + { + if (!drawing) drawing = 1; + else break; + } + else + { + if (rom[i] & 0x0f) + { + if (sx+x >= 0 && sx+x < nScreenWidth) { + dest[(sx+x)] = color | (rom[i] & 0x0f); + } + } + x++; + } + + i++; + } + } + } + } +} + +static void draw_layer(INT32 *in_page, INT32 scrollx, INT32 scrolly, INT32 transp) +{ + UINT16 *vram = (UINT16*)DrvVidRAM; + + for (INT32 offs = 0; offs < 128 * 64; offs++) + { + INT32 sx = ((offs & 0x7f) << 3) - scrollx; + INT32 sy = ((offs >> 7) << 3) - scrolly; + + INT32 ofst = DrvLayerTable[offs]; + + INT32 attr = vram[in_page[ofst>>11] * 0x0800 + (ofst & 0x7ff)]; + INT32 code = attr; + if (transp && !code) continue; + INT32 color = (attr & 0x1fc0) >> 6; + + if (sx >= nScreenWidth || sy >= nScreenHeight || sy < -7 || sx < -7) continue; + + if (sx >= 0 && sx < (nScreenWidth - 7) && sy >= 0 && sy < (nScreenHeight - 7)) { + if (transp) { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM0); + } + } else { + if (transp) { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM0); + } + } + } +} + +static void draw_text() +{ + UINT16 *vram = (UINT16*)DrvTxtRAM; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = ((offs & 0x3f) << 3) - 192; + INT32 sy = (offs >> 6) << 3; + + INT32 attr = vram[DrvTxtTable[offs]]; + INT32 code = attr & 0xf1ff; + INT32 color = (attr & 0x0e00) >> 9; + + if (sx < 0 || sy >= nScreenHeight || sx >= nScreenWidth || !code) continue; + + if (sx >= 0 && sx < (nScreenWidth - 7) && sy >= 0 && sy < (nScreenHeight - 7)) { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i+=2) { + palette_write(i); + } + } + + if (~*coin_control & 0x20) return 0; + + { + INT32 pages[4]; + UINT16 *txtram = (UINT16*)DrvTxtRAM; + + // draw_sprites(0); + + INT32 bg_scrollx = (txtram[bg_scrollx_reg] - bg_scrollx_offs) & 0x1ff; + INT32 bg_scrolly = ((txtram[bg_scrolly_reg] & 0xff) - bg_scrolly_offs) & 0xff; + INT32 page = txtram[bg_page_reg]; + + pages[3] = (page >> 12) & 0x0f; + pages[2] = (page >> 8) & 0x0f; + pages[1] = (page >> 4) & 0x0f; + pages[0] = (page >> 0) & 0x0f; + + draw_layer(pages, bg_scrollx+192, bg_scrolly, 0); + + draw_sprites(1); + + INT32 fg_scrollx = (txtram[fg_scrollx_reg] - fg_scrollx_offs) & 0x1ff; + INT32 fg_scrolly = ((txtram[fg_scrolly_reg] & 0xff) - fg_scrolly_offs) & 0xff; + page = txtram[fg_page_reg]; + + pages[3] = (page >> 12) & 0x0f; + pages[2] = (page >> 8) & 0x0f; + pages[1] = (page >> 4) & 0x0f; + pages[0] = (page >> 0) & 0x0f; + + draw_layer(pages, fg_scrollx+192, fg_scrolly, 1); + + draw_sprites(2); + draw_text(); + draw_sprites(3); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + SekNewFrame(); + ZetNewFrame(); + + INT32 nInterleave = 10; + INT32 nCyclesSegment; + INT32 nCyclesTotal[2] = { 12500000 / 60, 6250000 / 60 }; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesSegment = nCyclesTotal[0] / nInterleave; + + nCyclesDone[0] = SekRun(nCyclesSegment); + + if (nGame == 2) continue; + + nCyclesSegment = nCyclesTotal[1] / nInterleave; + + BurnTimerUpdateYM3812(i * nCyclesSegment); + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + if (nGame != 2) BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + SCAN_VAR(nCyclesDone[0]); + SCAN_VAR(nCyclesDone[1]); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + deniam16_set_okibank(*okibank); + } + + return 0; +} + + +// Logic Pro (Japan) + +static struct BurnRomInfo logicproRomDesc[] = { + { "logicpro.r4", 0x40000, 0xc506d484, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "logicpro.r3", 0x40000, 0xd5a4cf62, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "logicpro.r2", 0x10000, 0x000d624b, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "logicpro.r5", 0x80000, 0xdedf18c9, 3 | BRF_GRA }, // 3 Graphics Tiles + { "logicpro.r6", 0x80000, 0x3ecbd1c2, 3 | BRF_GRA }, // 4 + { "logicpro.r7", 0x80000, 0x47135521, 3 | BRF_GRA }, // 5 + + { "logicpro.r9", 0x80000, 0xa98bc1d2, 4 | BRF_GRA }, // 6 Sprites + { "logicpro.r8", 0x80000, 0x1de46298, 4 | BRF_GRA }, // 7 + + { "logicpro.r1", 0x80000, 0xa1fec4d4, 5 | BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(logicpro) +STD_ROM_FN(logicpro) + +static INT32 logicproInit() +{ + bg_scrollx_reg = 0x00a4/2; + bg_scrolly_reg = 0x00a8/2; + bg_page_reg = 0x00ac/2; + fg_scrollx_reg = 0x00a2/2; + fg_scrolly_reg = 0x00a6/2; + fg_page_reg = 0x00aa/2; + + bg_scrollx_offs = 0x00d; + bg_scrolly_offs = 0x000; + fg_scrollx_offs = 0x009; + fg_scrolly_offs = 0x000; + + return DrvInit(); +} + +struct BurnDriver BurnDrvLogicpro = { + "logicpro", NULL, NULL, NULL, "1996", + "Logic Pro (Japan)\0", NULL, "Deniam", "Deniam-16b Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, logicproRomInfo, logicproRomName, NULL, NULL, DrvInputInfo, Logicpr2DIPInfo, + logicproInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Croquis (Germany) + +static struct BurnRomInfo croquisRomDesc[] = { + { "r4.bin", 0x40000, 0x03c9055e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "r3.bin", 0x40000, 0xa98ae4f6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "logicpro.r2", 0x10000, 0x000d624b, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "logicpro.r5", 0x80000, 0xdedf18c9, 3 | BRF_GRA }, // 3 Graphics Tiles + { "logicpro.r6", 0x80000, 0x3ecbd1c2, 3 | BRF_GRA }, // 4 + { "logicpro.r7", 0x80000, 0x47135521, 3 | BRF_GRA }, // 5 + + { "logicpro.r9", 0x80000, 0xa98bc1d2, 4 | BRF_GRA }, // 6 Sprites + { "logicpro.r8", 0x80000, 0x1de46298, 4 | BRF_GRA }, // 7 + + { "logicpro.r1", 0x80000, 0xa1fec4d4, 5 | BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(croquis) +STD_ROM_FN(croquis) + +struct BurnDriver BurnDrvCroquis = { + "croquis", "logicpro", NULL, NULL, "1996", + "Croquis (Germany)\0", NULL, "Deniam", "Deniam-16b Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, croquisRomInfo, croquisRomName, NULL, NULL, DrvInputInfo, Logicpr2DIPInfo, + logicproInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Karian Cross (Rev. 1.0) + +static struct BurnRomInfo karianxRomDesc[] = { + { "even", 0x80000, 0xfd0ce238, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "odd", 0x80000, 0xbe173cdc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "snd", 0x10000, 0xfedd3375, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bkg1", 0x80000, 0x5cb8558a, 3 | BRF_GRA }, // 3 Graphics Tiles + { "bkg2", 0x80000, 0x95ff297c, 3 | BRF_GRA }, // 4 + { "bkg3", 0x80000, 0x6c81f1b2, 3 | BRF_GRA }, // 5 + + { "obj4", 0x80000, 0x5f8d75a9, 4 | BRF_GRA }, // 6 Sprites + { "obj1", 0x80000, 0x967ee97d, 4 | BRF_GRA }, // 7 + { "obj5", 0x80000, 0xe9fc22f9, 4 | BRF_GRA }, // 8 + { "obj2", 0x80000, 0xd39eb04e, 4 | BRF_GRA }, // 9 + { "obj6", 0x80000, 0xc1ec35a5, 4 | BRF_GRA }, // 10 + { "obj3", 0x80000, 0x6ac1ac87, 4 | BRF_GRA }, // 11 + + { "voi", 0x80000, 0xc6506a80, 5 | BRF_SND }, // 12 Samples +}; + +STD_ROM_PICK(karianx) +STD_ROM_FN(karianx) + +static INT32 karianxInit() +{ + nGame = 1; + + bg_scrollx_reg = 0x00a4/2; + bg_scrolly_reg = 0x00a8/2; + bg_page_reg = 0x00ac/2; + fg_scrollx_reg = 0x00a2/2; + fg_scrolly_reg = 0x00a6/2; + fg_page_reg = 0x00aa/2; + + bg_scrollx_offs = 0x10d; + bg_scrolly_offs = 0x080; + fg_scrollx_offs = 0x109; + fg_scrolly_offs = 0x080; + + return DrvInit(); +} + +struct BurnDriver BurnDrvKarianx = { + "karianx", NULL, NULL, NULL, "1996", + "Karian Cross (Rev. 1.0)\0", NULL, "Deniam", "Deniam-16b Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, karianxRomInfo, karianxRomName, NULL, NULL, DrvInputInfo, KarianxDIPInfo, + karianxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Logic Pro 2 (Japan) + +static struct BurnRomInfo logicpr2RomDesc[] = { + { "lp2-2", 0x080000, 0xcc1880bf, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "lp2-1", 0x080000, 0x46d5e954, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "log2-b01", 0x080000, 0xfe789e07, 3 | BRF_GRA }, // 2 Graphics Tiles + { "log2-b02", 0x080000, 0x1e0c51cd, 3 | BRF_GRA }, // 3 + { "log2-b03", 0x080000, 0x916f2928, 3 | BRF_GRA }, // 4 + + { "obj", 0x400000, 0xf221f305, 4 | BRF_GRA }, // 5 Sprites + + { "log2-s01", 0x100000, 0x2875c435, 5 | BRF_SND }, // 6 Samples +}; + +STD_ROM_PICK(logicpr2) +STD_ROM_FN(logicpr2) + +static INT32 logicpr2Init() +{ + nGame = 2; + + return logicproInit(); +} + +struct BurnDriver BurnDrvLogicpr2 = { + "logicpr2", NULL, NULL, NULL, "1997", + "Logic Pro 2 (Japan)\0", NULL, "Deniam", "Deniam-16c Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, logicpr2RomInfo, logicpr2RomName, NULL, NULL, DrvInputInfo, Logicpr2DIPInfo, + logicpr2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_dietgogo.cpp b/src/burn/drivers/misc_post90s/d_dietgogo.cpp new file mode 100644 index 00000000..1d0b412a --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_dietgogo.cpp @@ -0,0 +1,618 @@ +// FB Alpha Diet Go Go driver module +// Based on MAME driver by Bryan McPhail and David Haywood + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "timer.h" +#include "msm6295.h" +#include "h6280_intf.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KCode; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvHucRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo DietgoInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Dietgo) + +static struct BurnDIPInfo DietgoDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Continue Coin" }, + {0x14, 0x01, 0x80, 0x80, "1 Start/1 Continue" }, + {0x14, 0x01, 0x80, 0x00, "2 Start/1 Continue" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x00, "2" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x08, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x04, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x15, 0x01, 0x10, 0x10, "Off" }, + {0x15, 0x01, 0x10, 0x00, "On" }, +}; + +STDDIPINFO(Dietgo) + +void __fastcall dietgogo_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x200000, data) + + switch (address) + { + case 0x340380: + deco16_soundlatch = data; + h6280SetIRQLine(0, H6280_IRQSTATUS_ACK); + return; + } +} + +void __fastcall dietgogo_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x340380: + case 0x340381: + deco16_soundlatch = data; + h6280SetIRQLine(0, H6280_IRQSTATUS_ACK); + return; + } +} + +UINT16 __fastcall dietgogo_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x340298: + return (DrvInputs[0] & 0x07) | (deco16_vblank & 0x0008); + + case 0x340342: + return DrvInputs[1]; + + case 0x340506: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + return 0; +} + +UINT8 __fastcall dietgogo_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x340298: + case 0x340299: + return (DrvInputs[0] & 0x07) | (deco16_vblank & 0x0008); + + case 0x340342: + case 0x340343: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x340506: + return DrvDips[1]; + + case 0x340507: + return DrvDips[9]; + } + + return 0; +} + +static INT32 dietgo_bank_callback(const INT32 bank) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + deco16SoundReset(); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + Drv68KCode = Next; Next += 0x080000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvSprRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000c00; + DrvHucRAM = Next; Next += 0x002000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00001, 1, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 5, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 6, 1)) return 1; + + deco102_decrypt_cpu(Drv68KROM, Drv68KCode, 0x80000, 0xe9ba, 0x01, 0x19); + + deco56_decrypt_gfx(DrvGfxROM1, 0x100000); + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x100000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_sprite_decode(DrvGfxROM2, 0x200000); + } + + deco16Init(1, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x100000 * 2, DrvGfxROM1, 0x100000 * 2, NULL, 0); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(0, dietgo_bank_callback); + deco16_set_bank_callback(1, dietgo_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_READ); + SekMapMemory(Drv68KCode, 0x000000, 0x07ffff, SM_FETCH); + SekMapMemory(deco16_pf_ram[0], 0x210000, 0x211fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x212000, 0x213fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x220000, 0x2207ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x222000, 0x2227ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x280000, 0x2807ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x300000, 0x300bff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x380000, 0x38ffff, SM_RAM); + SekSetWriteWordHandler(0, dietgogo_main_write_word); + SekSetWriteByteHandler(0, dietgogo_main_write_byte); + SekSetReadWordHandler(0, dietgogo_main_read_word); + SekSetReadByteHandler(0, dietgogo_main_read_byte); + SekClose(); + + deco16SoundInit(DrvHucROM, DrvHucRAM, 2685000, 0, NULL, 0.45, 1006875, 0.60, 0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + deco16Exit(); + deco16SoundExit(); + + SekExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + if (ram[offs + 1] == 0) continue; + + INT32 inc, mult; + + INT32 sy = ram[offs + 0]; + INT32 code = ram[offs + 1] & 0x3fff; + INT32 sx = ram[offs + 2]; + + if ((sy & 0x1000) && (nCurrentFrame & 1)) continue; + + INT32 color = (sx >> 9) & 0x1f; + + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + INT32 multi = (1 << ((sy & 0x0600) >> 9)) - 1; + + sx &= 0x01ff; + sy &= 0x01ff; + if (sx >= 320) sx -= 512; + if (sy >= 256) sy -= 512; + sy = 240 - sy; + sx = 304 - sx; + + code &= ~multi; + + if (flipy) { + inc = -1; + } else { + code += multi; + inc = 1; + } + + if (*flipscreen) + { + sy = 240 - sy; + sx = 304 - sx; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else + mult = -16; + + if (sx >= 320 || sx < -15) continue; + + while (multi >= 0) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code - multi * inc, sx, (sy + mult * multi) - 8, color, 4, 0, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code - multi * inc, sx, (sy + mult * multi) - 8, color, 4, 0, 0x200, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code - multi * inc, sx, (sy + mult * multi) - 8, color, 4, 0, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code - multi * inc, sx, (sy + mult * multi) - 8, color, 4, 0, 0x200, DrvGfxROM2); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + if (nBurnLayer & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_OPAQUE); + + if (nBurnLayer & 2) deco16_draw_layer(0, pTransDraw, 0); + + if (nBurnLayer & 4) draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + h6280NewFrame(); + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 2685000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + h6280Open(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + nCyclesDone[1] += h6280Run(nCyclesTotal[1] / nInterleave); + // BurnTimerUpdate(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + deco16SoundUpdate(pBurnSoundOut, nBurnSoundLen); + } + + h6280Close(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + } + + return 0; +} + + +// Diet Go Go (USA v1.1 1992.09.26) + +static struct BurnRomInfo dietgouRomDesc[] = { + { "jx.00", 0x040000, 0x1a9de04f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jx.01", 0x040000, 0x79c097c8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jx.02", 0x010000, 0x4e3492a5, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "may00", 0x100000, 0x234d1f8d, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "may01", 0x100000, 0x2da57d04, 4 | BRF_GRA }, // 4 Sprites + { "may02", 0x100000, 0x3a66a713, 4 | BRF_GRA }, // 5 + + { "may03", 0x080000, 0xb6e42bae, 5 | BRF_SND }, // 6 OKI M6295 Samples + + { "pal16l8b.6h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 7 PLDs + { "pal16l8b.7h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 8 + { "pal16r6a.11h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 9 +}; + +STD_ROM_PICK(dietgou) +STD_ROM_FN(dietgou) + +struct BurnDriver BurnDrvDietgou = { + "dietgou", "dietgo", NULL, NULL, "1992", + "Diet Go Go (USA v1.1 1992.09.26)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, dietgouRomInfo, dietgouRomName, NULL, NULL, DietgoInputInfo, DietgoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Diet Go Go (Euro v1.1 1992.08.04) + +static struct BurnRomInfo dietgoeRomDesc[] = { + { "jy00-1.4h", 0x040000, 0x8bce137d, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jy01-1.5h", 0x040000, 0xeca50450, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jy02.m14", 0x010000, 0x4e3492a5, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "may00", 0x100000, 0x234d1f8d, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "may01", 0x100000, 0x2da57d04, 4 | BRF_GRA }, // 4 Sprites + { "may02", 0x100000, 0x3a66a713, 4 | BRF_GRA }, // 5 + + { "may03", 0x080000, 0xb6e42bae, 5 | BRF_SND }, // 6 OKI M6295 Samples + + { "pal16l8b.6h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 7 PLDs + { "pal16l8b.7h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 8 + { "pal16r6a.11h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 9 +}; + +STD_ROM_PICK(dietgoe) +STD_ROM_FN(dietgoe) + +struct BurnDriver BurnDrvDietgoe = { + "dietgoe", "dietgo", NULL, NULL, "1992", + "Diet Go Go (Euro v1.1 1992.08.04)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, dietgoeRomInfo, dietgoeRomName, NULL, NULL, DietgoInputInfo, DietgoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Diet Go Go (Euro v1.1 1992.09.26) + +static struct BurnRomInfo dietgoRomDesc[] = { + { "jy00-2.h4", 0x040000, 0x014dcf62, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jy01-2.h5", 0x040000, 0x793ebd83, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jy02.m14", 0x010000, 0x4e3492a5, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "may00", 0x100000, 0x234d1f8d, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "may01", 0x100000, 0x2da57d04, 4 | BRF_GRA }, // 4 Sprites + { "may02", 0x100000, 0x3a66a713, 4 | BRF_GRA }, // 5 + + { "may03", 0x080000, 0xb6e42bae, 5 | BRF_SND }, // 6 OKI M6295 Samples + + { "pal16l8b.6h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 7 PLDs + { "pal16l8b.7h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 8 + { "pal16r6a.11h", 0x000104, 0x00000000, 6 | BRF_NODUMP }, // 9 +}; + +STD_ROM_PICK(dietgo) +STD_ROM_FN(dietgo) + +struct BurnDriver BurnDrvDietgo = { + "dietgo", NULL, NULL, NULL, "1992", + "Diet Go Go (Euro v1.1 1992.09.26)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, dietgoRomInfo, dietgoRomName, NULL, NULL, DietgoInputInfo, DietgoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Diet Go Go (Japan v1.1 1992.09.26) + +static struct BurnRomInfo dietgojRomDesc[] = { + { "jw-00-2.4h", 0x040000, 0xe6ba6c49, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jw-01-2.5h", 0x040000, 0x684a3d57, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jx.02", 0x010000, 0x4e3492a5, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "may00", 0x100000, 0x234d1f8d, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "may01", 0x100000, 0x2da57d04, 4 | BRF_GRA }, // 4 Sprites + { "may02", 0x100000, 0x3a66a713, 4 | BRF_GRA }, // 5 + + { "may03", 0x080000, 0xb6e42bae, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(dietgoj) +STD_ROM_FN(dietgoj) + +struct BurnDriver BurnDrvDietgoj = { + "dietgoj", "dietgo", NULL, NULL, "1992", + "Diet Go Go (Japan v1.1 1992.09.26)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, dietgojRomInfo, dietgojRomName, NULL, NULL, DietgoInputInfo, DietgoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_diverboy.cpp b/src/burn/drivers/misc_post90s/d_diverboy.cpp new file mode 100644 index 00000000..fe893e82 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_diverboy.cpp @@ -0,0 +1,496 @@ +// FB Alpha Diverboy driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 *soundlatch; +static UINT8 *samplebank; + +static struct BurnInputInfo DiverboyInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy2 + 2, "p3 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Diverboy) + +static struct BurnDIPInfo DiverboyDIPList[]= +{ + {0x12, 0xff, 0xff, 0xb8, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x12, 0x01, 0x07, 0x07, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x05, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x00, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x08, 0x00, "2" }, + {0x12, 0x01, 0x08, 0x08, "3" }, + + {0 , 0xfe, 0 , 2, "Display Copyright" }, + {0x12, 0x01, 0x10, 0x00, "No" }, + {0x12, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x60, 0x00, "Easy" }, + {0x12, 0x01, 0x60, 0x20, "Normal" }, + {0x12, 0x01, 0x60, 0x40, "Hard" }, + {0x12, 0x01, 0x60, 0x60, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x80, 0x80, "No" }, + {0x12, 0x01, 0x80, 0x00, "Yes" }, +}; + +STDDIPINFO(Diverboy) + +void __fastcall diverboy_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ +} + +void __fastcall diverboy_write_word(UINT32 address, UINT16 data) +{ + if (address == 0x100000) { + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + return; + } +} + +UINT8 __fastcall diverboy_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180000: + return DrvInputs[0] >> 8; + + case 0x180001: + return DrvInputs[0] & 0xff; + + case 0x180009: + return DrvInputs[1] & 0xf7; + } + + return 0; +} + +UINT16 __fastcall diverboy_read_word(UINT32 address) +{ + switch (address) + { + case 0x180002: + return DrvDips[0]; + + case 0x180008: + return DrvInputs[1]; + } + + return 0; +} + +static inline void sample_bank(INT32 data) +{ + *samplebank = data & 3; + + MSM6295ROM = DrvSndROM + ((data & 3) << 18); +} + +void __fastcall diverboy_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + sample_bank(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall diverboy_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + sample_bank(0); + MSM6295Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + samplebank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0, 1, 2, 3 }; + INT32 XOffs[16] = { 56, 60, 48, 52, 40, 44, 32, 36, 24, 28, 16, 20, 8, 12, 0, 4 }; + INT32 YOffs[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + memcpy (DrvZ80ROM, DrvZ80ROM + 0x8000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 8, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 9, 1)) return 1; + memcpy (DrvSndROM + 0xc0000, DrvSndROM + 0x60000, 0x20000); + memcpy (DrvSndROM + 0x80000, DrvSndROM + 0x40000, 0x20000); + memcpy (DrvSndROM + 0x40000, DrvSndROM + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM + 0x020000, 10, 1)) return 1; + memcpy (DrvSndROM + 0xe0000, DrvSndROM + 0x20000, 0x20000); + memcpy (DrvSndROM + 0xa0000, DrvSndROM + 0x20000, 0x20000); + memcpy (DrvSndROM + 0x60000, DrvSndROM + 0x20000, 0x20000); + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x040000, 0x04ffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x080000, 0x083fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x1407ff, SM_RAM); + SekSetWriteByteHandler(0, diverboy_write_byte); + SekSetWriteWordHandler(0, diverboy_write_word); + SekSetReadByteHandler(0, diverboy_read_byte); + SekSetReadWordHandler(0, diverboy_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(diverboy_sound_write); + ZetSetReadHandler(diverboy_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1320000 / 132, 100.0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_sprites() +{ + UINT16 *vram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x4000 / 2; offs+=8) + { + INT32 sy = ( 256 - vram[offs + 4]) - 16; + INT32 sx = ((480 - vram[offs + 0]) & 0x1ff) - 173; + INT32 attr = vram[offs + 1]; + INT32 code = vram[offs + 3]; + INT32 color = ((attr & 0x00f0) >> 4) | ((attr & 0x000c) << 2); + INT32 flash = (attr & 0x1000); + INT32 bank = (attr & 0x0002) >> 1; + + if (flash && (GetCurrentFrame() & 1)) continue; + if (sx >= nScreenWidth || sy >= nScreenHeight || sx < -15 || sy < -15) continue; + + if (attr & 0x0008) { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, bank ? DrvGfxROM1 : DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, bank ? DrvGfxROM1 : DrvGfxROM0); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x800 / 2; i++, pal++) { + r = ((*pal << 4) & 0xf0) | ((*pal << 0) & 0x0f); + g = ((*pal >> 0) & 0xf0) | ((*pal >> 4) & 0x0f); + b = ((*pal >> 4) & 0xf0) | ((*pal >> 8) & 0x0f); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = ~0; + DrvInputs[1] = ~8; + + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nTotalCycles[2] = { 12000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + + nCyclesDone[0] += SekRun(nSegment); + + nSegment = (nTotalCycles[1] - nCyclesDone[1]) / (nInterleave - i); + + nCyclesDone[1] += ZetRun(nSegment); + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + MSM6295Scan(0, nAction); + + if (nAction & ACB_WRITE) { + sample_bank(*samplebank); + } + } + + return 0; +} + + +// Diver Boy + +static struct BurnRomInfo diverboyRomDesc[] = { + { "db_01.bin", 0x20000, 0x6aa11366, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "db_02.bin", 0x20000, 0x45f8a673, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "db_05.bin", 0x10000, 0xffeb49ec, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "db_08.bin", 0x80000, 0x7bb96220, 3 | BRF_GRA }, // 3 Bank 0 Graphics + { "db_09.bin", 0x80000, 0x12b15476, 3 | BRF_GRA }, // 4 + + { "db_07.bin", 0x20000, 0x18485741, 4 | BRF_GRA }, // 5 Bank 1 Graphics + { "db_10.bin", 0x20000, 0xc381d1cc, 4 | BRF_GRA }, // 6 + { "db_06.bin", 0x20000, 0x21b4e352, 4 | BRF_GRA }, // 7 + { "db_11.bin", 0x20000, 0x41d29c81, 4 | BRF_GRA }, // 8 + + { "db_03.bin", 0x80000, 0x50457505, 5 | BRF_SND }, // 9 Oki6295 Samples + { "db_04.bin", 0x20000, 0x01b81da0, 5 | BRF_SND }, // 10 +}; + +STD_ROM_PICK(diverboy) +STD_ROM_FN(diverboy) + +struct BurnDriver BurnDrvDiverboy = { + "diverboy", NULL, NULL, NULL, "1992", + "Diver Boy\0", NULL, "Electronic Devices Italy", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, diverboyRomInfo, diverboyRomName, NULL, NULL, DiverboyInputInfo, DiverboyDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_drtomy.cpp b/src/burn/drivers/misc_post90s/d_drtomy.cpp new file mode 100644 index 00000000..495125f9 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_drtomy.cpp @@ -0,0 +1,508 @@ +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *Mem, *MemEnd, *RamStart, *RamEnd; +static UINT8 *Rom, *Gfx0, *Gfx1, *Snd; +static UINT8 *VidRam, *PalRam, *SprRam, *WorkRam; +static UINT32 *Palette, *DrvPalette; +static UINT8 DrvRecalc; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvDips[2], DrvInputs[2], DrvReset; + +static INT32 m6295bank; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 6, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xaf, NULL }, + + {0 , 0xfe, 0 , 11 , "Coin A" }, + {0x11, 0x01, 0x0f, 0x0a, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x07, "3 Coins 2 Credits" }, + {0x11, 0x01, 0x0f, 0x00, "5 Coins 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x0f, 0x06, "3 Coins 4 Credits" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x08, "2 Coins 5 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 11 , "Coin B" }, + {0x11, 0x01, 0xf0, 0xa0, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xf0, 0x70, "3 Coins 2 Credits" }, + {0x11, 0x01, 0xf0, 0x00, "5 Coins 4 Credits" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xf0, 0x60, "3 Coins 4 Credits" }, + {0x11, 0x01, 0xf0, 0x90, "2 Coins 3 Credits" }, + {0x11, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xf0, 0x80, "2 Coins 5 Credits" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x12, 0x01, 0x01, 0x00, "Less" }, + {0x12, 0x01, 0x01, 0x01, "More" }, + + {0 , 0xfe, 0 , 2 , "Number of Virus" }, + {0x12, 0x01, 0x02, 0x02, "Less" }, + {0x12, 0x01, 0x02, 0x00, "More" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x20, 0x20, "English" }, + {0x12, 0x01, 0x20, 0x00, "Italian" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x40, 0x40, "No" }, + {0x12, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Drv) + +static inline void drtomy_okibank_w(UINT8 data) +{ + m6295bank = data & 3; + memcpy (Snd + 0x20000, Snd + 0x40000 + m6295bank * 0x20000, 0x20000); +} + +static inline void set_palette(UINT16 pal, INT32 offset) +{ + INT32 r = (pal >> 10) & 0x1f; + INT32 g = (pal >> 5) & 0x1f; + INT32 b = (pal >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[offset] = (r << 16) | (g << 8) | b; + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +UINT8 __fastcall drtomy_read_byte(UINT32 address) +{ + switch (address) + { + case 0x700001: + return DrvDips[0]; + + case 0x700003: + return DrvDips[1]; + + case 0x700005: + return DrvInputs[0]; + + case 0x700007: + return DrvInputs[1]; + + case 0x70000f: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT16 __fastcall drtomy_read_word(UINT32) +{ + return 0; +} + +void __fastcall drtomy_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x70000d: + if (m6295bank != (data & 3)) { + drtomy_okibank_w(data); + } + return; + + case 0x70000f: + MSM6295Command(0, data); + return; + } +} + +void __fastcall drtomy_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff800) == 0x200000) { + UINT16 *pal = (UINT16*)(PalRam + (address & 0x7fe)); + + *pal = data; + + set_palette(*pal, (address >> 1) & 0x3ff); + + return; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (VidRam, 0, 0x2000); + memset (PalRam, 0, 0x0800); + memset (SprRam, 0, 0x1000); + memset (WorkRam, 0, 0x4000); + memset (Palette, 0, 0x1000); + + DrvRecalc = 1; + + SekOpen(0); + SekReset(); + SekClose(); + + m6295bank = 0; + MSM6295Reset(0); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + static INT32 Planes[4] = { 0x000000, 0x200000, 0x400000, 0x600000 }; + static INT32 XOffs[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 }; + static INT32 YOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x100000); + + GfxDecode(0x8000, 4, 8, 8, Planes, XOffs, YOffs, 0x040, tmp, Gfx0); + GfxDecode(0x2000, 4, 16, 16, Planes, XOffs, YOffs, 0x100, tmp, Gfx1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom = Next; Next += 0x040000; + Gfx0 = Next; Next += 0x200000; + Gfx1 = Next; Next += 0x200000; + Snd = Next; Next += 0x0c0000; + + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamStart = Next; + + VidRam = Next; Next += 0x002000; + PalRam = Next; Next += 0x000800; + SprRam = Next; Next += 0x001000; + WorkRam = Next; Next += 0x004000; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Rom + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Rom + 0x000001, 1, 2)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx0 + i * 0x40000, i + 2, 1)) return 1; + } + + if (BurnLoadRom(Snd + 0x000000, 6, 1)) return 1; + memcpy (Snd + 0x40000, Snd + 0x00000, 0x80000); + memcpy (Snd + 0x20000, Snd + 0x00000, 0x20000); + + MSM6295ROM = Snd; + + if (DrvGfxDecode()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Rom, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(VidRam, 0x100000, 0x101fff, SM_RAM); + SekMapMemory(PalRam, 0x200000, 0x1007ff, SM_ROM); + SekMapMemory(SprRam, 0x440000, 0x440fff, SM_RAM); + SekMapMemory(WorkRam, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, drtomy_write_byte); + SekSetWriteWordHandler(0, drtomy_write_word); + SekSetReadByteHandler(0, drtomy_read_byte); + SekSetReadWordHandler(0, drtomy_read_word); + SekClose(); + + MSM6295Init(0, 1625000 / 132 /*?*/, 80, 0); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + GenericTilesExit(); + MSM6295Exit(0); + + BurnFree (Mem); + + MSM6295ROM = NULL; + + return 0; +} + + +static void draw_sprites() +{ + INT32 i, x, y, ex, ey; + + static const INT32 x_offset[2] = {0x0,0x2}; + static const INT32 y_offset[2] = {0x0,0x1}; + + UINT16 *spriteram = (UINT16*)SprRam; + + for (i = 3; i < 0x1000/2; i+=4){ + INT32 sx = spriteram[i+2] & 0x01ff; + INT32 sy = (240 - (spriteram[i] & 0x00ff)) & 0x00ff; + INT32 number = spriteram[i+3]; + INT32 color = (spriteram[i+2] & 0x1e00) >> 9; + INT32 attr = (spriteram[i] & 0xfe00) >> 9; + + INT32 xflip = attr & 0x20; + INT32 yflip = attr & 0x40; + INT32 spr_size; + + if (attr & 0x04){ + spr_size = 1; + } else { + spr_size = 2; + number &= (~3); + } + + for (y = 0; y < spr_size; y++){ + for (x = 0; x < spr_size; x++){ + + ex = xflip ? (spr_size-1-x) : x; + ey = yflip ? (spr_size-1-y) : y; + + INT32 sxx = sx-0x09+x*8; + INT32 syy = sy+y*8; + + syy -= 0x10; + + INT32 code = number + x_offset[ex] + y_offset[ey]; + + if (yflip) { + if (xflip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sxx, syy, color, 4, 0, 0x100, Gfx0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sxx, syy, color, 4, 0, 0x100, Gfx0); + } + } else { + if (xflip) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sxx, syy, color, 4, 0, 0x100, Gfx0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sxx, syy, color, 4, 0, 0x100, Gfx0); + } + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x300; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + { + UINT16 *bg_ram = (UINT16*)(VidRam + 0x1000); + UINT16 *fg_ram = (UINT16*)(VidRam + 0x0000); + + for (INT32 offs = 0; offs < 0x400 >> 1; offs++) { + INT32 code, color, sx, sy; + + sx = (offs << 4) & 0x1f0; + sy = (offs >> 1) & 0x1f0; + + if (sx > 0x140 || sy < 0x10) continue; + sy -= 0x10; + + // background + code = bg_ram[offs] & 0xfff; + color = bg_ram[offs] >> 12; + + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx1); + + // foreground + code = fg_ram[offs] & 0xfff; + color = fg_ram[offs] >> 12; + + if (!code) continue; + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, Gfx1); + } + } + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static inline void makeInputs() +{ + DrvInputs[0] = DrvInputs[1] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + makeInputs(); + + SekOpen(0); + SekRun(12000000 / 60); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + if (nAction & ACB_WRITE) + DrvRecalc = 1; + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + MSM6295Scan(0, nAction); + + SCAN_VAR(m6295bank); + + if (nAction & ACB_WRITE) + drtomy_okibank_w(m6295bank); + } + + return 0; +} + +// Dr. Tomy + +static struct BurnRomInfo drtomyRomDesc[] = { + { "15.u21", 0x20000, 0x0b8d763b, 1 | BRF_PRG | BRF_ESS }, + { "16.u22", 0x20000, 0x206f4d65, 1 | BRF_PRG | BRF_ESS }, + + { "20.u80", 0x40000, 0x4d4d86ff, 2 | BRF_GRA }, + { "19.u81", 0x40000, 0x49ecbfe2, 2 | BRF_GRA }, + { "18.u82", 0x40000, 0x8ee5c921, 2 | BRF_GRA }, + { "17.u83", 0x40000, 0x42044b1c, 2 | BRF_GRA }, + + { "14.u23", 0x80000, 0x479614ec, 3 | BRF_SND }, +}; + +STD_ROM_PICK(drtomy) +STD_ROM_FN(drtomy) + +struct BurnDriver BurnDrvDrtomy = { + "drtomy", NULL, NULL, NULL, "1993", + "Dr. Tomy\0", NULL, "Playmark", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, drtomyRomInfo, drtomyRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_egghunt.cpp b/src/burn/drivers/misc_post90s/d_egghunt.cpp new file mode 100644 index 00000000..13d41ff1 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_egghunt.cpp @@ -0,0 +1,558 @@ +// FB Alpha Egg Hunt driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM1; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; + +static UINT8 ram_bank; +static UINT8 gfx_bank; +static UINT8 oki_bank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo EgghuntInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 7, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 6, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 5, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 2" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 7, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 6, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 5, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 2, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Egghunt) + +static struct BurnDIPInfo EgghuntDIPList[]= +{ + {0x10, 0xff, 0xff, 0x61, NULL }, + {0x11, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2, "Debug Mode" }, + {0x10, 0x01, 0x01, 0x01, "Off" }, + {0x10, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 3, "Credits per Player" }, + {0x10, 0x01, 0x60, 0x60, "1" }, + {0x10, 0x01, 0x60, 0x40, "2" }, + {0x10, 0x01, 0x60, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Censor Pictures" }, + {0x11, 0x01, 0x80, 0x00, "No" }, + {0x11, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Egghunt) + +static inline void palette_write(INT32 offset) +{ + INT32 d = (DrvPalRAM[offset + 1] << 8) | (DrvPalRAM[offset + 0]); + + INT32 r = (d >> 10) & 0x1f; + INT32 g = (d >> 5) & 0x1f; + INT32 b = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall egghunt_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0xc000) { + DrvPalRAM[address & 0x7ff] = data; + palette_write(address & 0x7fe); + return; + } +} + +static void set_ram_bank(INT32 data) +{ + ram_bank = data & 1; + + if (ram_bank) { + ZetMapArea(0xd000, 0xdfff, 0, DrvSprRAM); + ZetMapArea(0xd000, 0xdfff, 1, DrvSprRAM); + ZetMapArea(0xd000, 0xdfff, 2, DrvSprRAM); + } else { + ZetMapArea(0xd000, 0xdfff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xdfff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xdfff, 2, DrvVidRAM); + } +} + +void __fastcall egghunt_main_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + set_ram_bank(data); + return; + + case 0x01: + gfx_bank = data & 0x33; + return; + + case 0x03: + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + *soundlatch = data; + return; + } +} + +UINT8 __fastcall egghunt_main_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return DrvDips[0]; + + case 0x01: + return DrvInputs[0]; + + case 0x02: + return DrvInputs[1]; + + case 0x03: + return DrvInputs[2]; + + case 0x04: + return DrvDips[1]; + + case 0x06: + return 0xff; + } + + return 0; +} + +static void set_oki_bank(INT32 data) +{ + MSM6295ROM = DrvSndROM0 + ((data & 0x10) >> 4) * 0x40000; + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[0][nChannel] = MSM6295ROM + (nChannel << 8); + MSM6295SampleData[0][nChannel] = MSM6295ROM + (nChannel << 16); + } +} + +void __fastcall egghunt_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe001: + oki_bank = data; + set_oki_bank(data); + return; + + case 0xe004: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall egghunt_sound_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xe001: + return oki_bank; + + case 0xe004: + return MSM6295ReadStatus(0); + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + set_oki_bank(0); + MSM6295Reset(0); + + oki_bank = 0; + ram_bank = 0; + gfx_bank = 0; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x400000, 0x600000, 0x000000, 0x200000 }; + INT32 XOffs0[8] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + INT32 XOffs1[16]= { 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x84, 0x85, 0x86, 0x87, 0x80, 0x81, 0x82, 0x83 }; + INT32 YOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x100000; i++) tmp[i] = DrvGfxROM0[i] ^ 0xff; + + GfxDecode(0x08000, 4, 8, 8, Plane, XOffs0, YOffs, 0x040, tmp, DrvGfxROM0); + + for (INT32 i = 0; i < 0x100000; i++) tmp[i] = DrvGfxROM1[i] ^ 0xff; + + GfxDecode(0x01000, 4, 16, 16, Plane, XOffs1, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x020000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x100000; + + DrvSndROM0 = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x002000; + DrvVidRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x001000; + DrvColRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM1 = Next; Next += 0x001000; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.0); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c0000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 9, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 10, 1)) return 1; + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xc7ff, 0, DrvPalRAM); +// ZetMapArea(0xc000, 0xc7ff, 1, DrvPalRAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvPalRAM); + ZetMapArea(0xc800, 0xcfff, 0, DrvColRAM); + ZetMapArea(0xc800, 0xcfff, 1, DrvColRAM); + ZetMapArea(0xc800, 0xcfff, 2, DrvColRAM); + ZetMapArea(0xd000, 0xdfff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xdfff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xdfff, 2, DrvVidRAM); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80RAM0); + ZetSetWriteHandler(egghunt_main_write); + ZetSetOutHandler(egghunt_main_write_port); + ZetSetInHandler(egghunt_main_read_port); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80RAM1); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80RAM1); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80RAM1); + ZetSetWriteHandler(egghunt_sound_write); + ZetSetReadHandler(egghunt_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132, 100.0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + MSM6295ROM = NULL; + + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + for (INT32 offs = 0x1000 - 0x40; offs >= 0; offs -= 0x20) + { + INT32 attr = DrvSprRAM[offs + 1]; + INT32 code = DrvSprRAM[offs + 0] | ((attr & 0xe0) << 3); + INT32 sx = DrvSprRAM[offs + 3] | ((attr & 0x10) << 4); + INT32 sy = ((DrvSprRAM[offs + 2] + 8) & 0xff) - 8; + + if (attr & 0xe0) { + if (gfx_bank & 0x20) { + code += 0x400 << (gfx_bank & 1); + } + } + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx - 64, sy - 8, attr & 0x0f, 4, 15, 0, DrvGfxROM1); + } +} + +static void draw_background_layer() +{ + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = ((offs & 0x3f) << 3) - 64; + INT32 sy = ((offs >> 6) << 3) - 8; + + if (sy < 0 || sy >= nScreenHeight || sx < 0 || sx >= nScreenWidth) continue; + + INT32 code = ((DrvVidRAM[offs * 2 + 1] & 0x3f) << 8) | (DrvVidRAM[offs * 2 + 0]); + INT32 color = DrvColRAM[offs] & 0x3f; + + if (code & 0x2000) { + if (gfx_bank & 0x02) { + code += 0x2000 << (gfx_bank & 1); + } + } + + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + draw_background_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 6000000 / 60, 6000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nSegment); + ZetClose(); + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + MSM6295Scan(0, nAction); + + SCAN_VAR(oki_bank); + SCAN_VAR(gfx_bank); + SCAN_VAR(ram_bank); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + set_ram_bank(ram_bank); + ZetClose(); + + set_oki_bank(oki_bank); + } + + return 0; +} + + +// Egg Hunt + +static struct BurnRomInfo egghuntRomDesc[] = { + { "prg.bin", 0x20000, 0xeb647145, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + + { "rom2.bin", 0x10000, 0x88a71bc3, 2 | BRF_ESS | BRF_PRG }, // 1 Z80 #1 Code + + { "rom3.bin", 0x40000, 0x9d51ac49, 3 | BRF_GRA }, // 2 Tiles + { "rom4.bin", 0x40000, 0x41c63041, 3 | BRF_GRA }, // 3 + { "rom5.bin", 0x40000, 0x6f96cb97, 3 | BRF_GRA }, // 4 + { "rom6.bin", 0x40000, 0xb5a41d4b, 3 | BRF_GRA }, // 5 + + { "rom7.bin", 0x20000, 0x1b43fb57, 4 | BRF_GRA }, // 6 Sprites + { "rom8.bin", 0x20000, 0xf8122d0d, 4 | BRF_GRA }, // 7 + { "rom9.bin", 0x20000, 0xdbfa0ffe, 4 | BRF_GRA }, // 8 + { "rom10.bin", 0x20000, 0x14f5fc74, 4 | BRF_GRA }, // 9 + + { "rom1.bin", 0x80000, 0xf03589bc, 5 | BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(egghunt) +STD_ROM_FN(egghunt) + +struct BurnDriver BurnDrvEgghunt = { + "egghunt", NULL, NULL, NULL, "1995", + "Egg Hunt\0", NULL, "Invi Image", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, egghuntRomInfo, egghuntRomName, NULL, NULL, EgghuntInputInfo, EgghuntDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 384, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_esd16.cpp b/src/burn/drivers/misc_post90s/d_esd16.cpp new file mode 100644 index 00000000..8a073576 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_esd16.cpp @@ -0,0 +1,1716 @@ +// FB Alpha ESD 16-bit hardware driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "eeprom.h" +#include "burn_ym3812.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfx0Trans; +static UINT8 *DrvGfx1Trans; +static UINT8 *DrvGfx2Trans; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvSprRAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; +static UINT16 *esd16_scroll_0; +static UINT16 *esd16_scroll_1; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT16 DrvInputs[3]; + +static UINT8 flipscreen; +static UINT8 soundlatch; +static UINT8 esd16_tilemap0_color; +static UINT16 head_layersize; +static UINT16 headpanic_platform_x; +static UINT16 headpanic_platform_y; +static UINT8 esd16_z80_bank; + +static INT32 game_select; + +static struct BurnInputInfo MultchmpInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 2, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 3, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy1 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy1 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy1 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy1 + 13, "p2 fire 2"}, + + {"Service" , BIT_DIGITAL , DrvJoy3 + 0, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Multchmp) + +static struct BurnInputInfo HedpanicInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 2, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 3, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy1 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy1 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy1 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy1 + 13, "p2 fire 2"}, + + {"Service" , BIT_DIGITAL , DrvJoy2 + 4, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, +}; + +STDINPUTINFO(Hedpanic) + +static struct BurnInputInfo SwatpolcInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 2, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 3, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy1 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy1 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy1 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy1 + 13, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy1 + 14, "p2 fire 3"}, + + {"Service" , BIT_DIGITAL , DrvJoy2 + 4, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, +}; + +STDINPUTINFO(Swatpolc) + +static struct BurnDIPInfo MultchmpDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL}, + {0x13, 0xff, 0xff, 0xff, NULL}, + + {0x12, 0xfe, 0, 2, "Coinage Type" }, + {0x12, 0x01, 0x02, 0x02, "1" }, + {0x12, 0x01, 0x02, 0x00, "2" }, + + {0x12, 0xfe, 0, 2, "Demo Sounds" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0x12, 0xfe, 0, 2, "Flip Screen" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0x12, 0xfe, 0, 4, "Coin A" }, + {0x12, 0x01, 0x30, 0x10, "2C 1C" }, + {0x12, 0x01, 0x30, 0x30, "1C 1C" }, + {0x12, 0x01, 0x30, 0x00, "2C 3C" }, + {0x12, 0x01, 0x30, 0x20, "1C 2C" }, + + {0x12, 0xfe, 0, 4, "Coin B" }, + {0x12, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x12, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x12, 0x01, 0xc0, 0x00, "2C 3C" }, + {0x12, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x13, 0xfe, 0, 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Hard" }, + {0x13, 0x01, 0x03, 0x00, "Hardest" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x0c, 0x00, "2" }, + {0x13, 0x01, 0x0c, 0x0c, "3" }, + {0x13, 0x01, 0x0c, 0x08, "4" }, + {0x13, 0x01, 0x0c, 0x04, "5" }, + + {0x13, 0xfe, 0, 2, "Selectable Games" }, + {0x13, 0x01, 0x10, 0x10, "3" }, + {0x13, 0x01, 0x10, 0x00, "4" }, + + {0x13, 0xfe, 0, 2, "Free Play" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Multchmp) + +//---------------------------------------------------------------------------------------------------------- + +static void palette_write(INT32 offset, UINT16 data) +{ + *((UINT16*)(DrvPalRAM + offset)) = data; + + INT32 r = (data >> 10) & 0x1f; + INT32 g = (data >> 5) & 0x1f; + INT32 b = (data >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[offset>>1] = (r << 16) | (g << 8) | b; + DrvPalette[offset>>1] = BurnHighCol(r, g, b, 0); +} + +static inline void esd_sound_command_w(UINT8 data) +{ + soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); +} + +//---------------------------------------------------------------------------------------------------------- + +void __fastcall multchmp_write_byte(UINT32, UINT8) +{ + return; +} + +void __fastcall multchmp_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff800) == 0x200000) { + palette_write(address & 0x7ff, data); + return; + } + + switch (address) + { + case 0x500000: + case 0x500002: + esd16_scroll_0[(address>>1)&1] = data; + return; + + case 0x500004: + case 0x500006: + esd16_scroll_1[(address>>1)&1] = data; + return; + + case 0x600008: + esd16_tilemap0_color = data & 3; + flipscreen = data & 0x80; + return; + + case 0x60000c: + esd_sound_command_w(data); + return; + } + return; +} + +UINT8 __fastcall multchmp_read_byte(UINT32 address) +{ + switch (address) + { + case 0x600002: + case 0x600003: + case 0x600004: + case 0x600005: + case 0x600006: + case 0x600007: + return DrvInputs[(address - 0x600002) >> 1] >> ((~address & 1) << 3); + } + + return 0; +} + +UINT16 __fastcall multchmp_read_word(UINT32 address) +{ + switch (address) + { + case 0x600002: + case 0x600004: + case 0x600006: + return DrvInputs[(address - 0x600002) >> 1]; + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +void __fastcall hedpanic_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xc0000e: + EEPROMWrite(data & 0x02, data & 0x01, (data & 0x04) >> 6); + return; + } + + return; +} + +void __fastcall hedpanic_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff000) == 0x800000) { + palette_write(address & 0xfff, data); + return; + } + + switch (address) + { + case 0xb00000: + case 0xb00002: + esd16_scroll_0[(address>>1)&1] = data; + return; + + case 0xb00004: + case 0xb00006: + esd16_scroll_1[(address>>1)&1] = data; + return; + + case 0xb00008: + headpanic_platform_x = data; + return; + + case 0xb0000a: + headpanic_platform_y = data; + return; + + case 0xb0000e: + head_layersize = data; + return; + + case 0xc00008: + esd16_tilemap0_color = data & 3; + flipscreen = data & 0x80; + return; + + case 0xc0000c: + esd_sound_command_w(data); + return; + + case 0xd00008: + INT32 ofst = (headpanic_platform_x + 0x40 * headpanic_platform_y) << 1; + + *((UINT16*)(DrvVidRAM1 + ofst)) = data; + return; + } + return; +} + +UINT8 __fastcall hedpanic_read_byte(UINT32 address) +{ + switch (address) + { + case 0xc00002: + case 0xc00003: + case 0xc00004: + case 0xc00005: + return DrvInputs[(address - 0xc00002) >> 1] >> ((~address & 1) << 3); + + case 0xc00006: + return (EEPROMRead() & 1) << 7; + } + + return 0; +} + +UINT16 __fastcall hedpanic_read_word(UINT32) +{ + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +void __fastcall mchampdx_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x50000e: + EEPROMWrite(data & 0x02, data & 0x01, (data & 0x04) >> 6); + return; + } + + return; +} + +void __fastcall mchampdx_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff000) == 0x400000) { + palette_write(address & 0xfff, data); + return; + } + + switch (address) + { + case 0x500008: + esd16_tilemap0_color = data & 3; + flipscreen = data & 0x80; + return; + + case 0x50000c: + esd_sound_command_w(data); + return; + + case 0x700000: + case 0x700002: + esd16_scroll_0[(address>>1)&1] = data; + return; + + case 0x700004: + case 0x700006: + esd16_scroll_1[(address>>1)&1] = data; + return; + + case 0x700008: + headpanic_platform_x = data; + return; + + case 0x70000a: + headpanic_platform_y = data; + return; + + case 0x70000e: + head_layersize = data; + return; + + case 0xd00008: + INT32 ofst = (headpanic_platform_x + 0x40 * headpanic_platform_y) << 1; + + *((UINT16*)(DrvVidRAM1 + ofst)) = data; + return; + } + return; +} + +UINT8 __fastcall mchampdx_read_byte(UINT32 address) +{ + switch (address) + { + case 0x500002: + case 0x500003: + case 0x500004: + case 0x500005: + return DrvInputs[(address - 0x500002) >> 1] >> ((~address & 1) << 3); + + case 0x500006: + return (EEPROMRead() & 1) << 7; + + } + + return 0; +} + +UINT16 __fastcall mchampdx_read_word(UINT32 address) +{ + switch (address) + { + case 0x500002: + case 0x500004: + return DrvInputs[(address - 0x500002) >> 1]; + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +void __fastcall tangtang_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x50000e: + EEPROMWrite(data & 0x02, data & 0x01, (data & 0x04) >> 6); + return; + } + return; +} + +void __fastcall tangtang_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff000) == 0x100000) { + palette_write(address & 0xfff, data); + return; + } + + switch (address) + { + case 0x400000: + case 0x400002: + esd16_scroll_0[(address>>1)&1] = data; + return; + + case 0x400004: + case 0x400006: + esd16_scroll_1[(address>>1)&1] = data; + return; + + case 0x400008: + headpanic_platform_x = data; + return; + + case 0x40000a: + headpanic_platform_y = data; + return; + + case 0x40000e: + head_layersize = data; + return; + + case 0x500008: + esd16_tilemap0_color = data & 3; + flipscreen = data & 0x80; + return; + + case 0x50000c: + esd_sound_command_w(data); + return; + + case 0x600008: + INT32 ofst = (headpanic_platform_x + 0x40 * headpanic_platform_y) << 1; + + *((UINT16*)(DrvVidRAM1 + ofst)) = data; + return; + } + return; +} + +UINT8 __fastcall tangtang_read_byte(UINT32 address) +{ + switch (address) + { + case 0x500002: + case 0x500003: + case 0x500004: + case 0x500005: + return DrvInputs[(address - 0x500002) >> 1] >> ((~address & 1) << 3); + + case 0x500006: + return (EEPROMRead() & 1) << 7; + } + + return 0; +} + +UINT16 __fastcall tangtang_read_word(UINT32 address) +{ + switch (address) + { + case 0x500002: + case 0x500004: + return DrvInputs[(address - 0x500002) >> 1]; + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +static void esd16_sound_rombank_w(INT32 data) +{ + esd16_z80_bank = data & 0xf; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x4000 * esd16_z80_bank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x4000 * esd16_z80_bank); +} + +void __fastcall esd16_sound_write(UINT16, UINT8) +{ +} + +UINT8 __fastcall esd16_sound_read(UINT16) +{ + return 0; +} + +void __fastcall esd16_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM3812Write(0, data); + return; + + case 0x01: + BurnYM3812Write(1, data); + return; + + case 0x02: + MSM6295Command(0, data); + return; + + case 0x05: + esd16_sound_rombank_w(data); + return; + } +} + +UINT8 __fastcall esd16_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x02: + return MSM6295ReadStatus(0); + + case 0x03: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return soundlatch; + + case 0x06: + return 0; + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + EEPROMReset(); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + esd16_sound_rombank_w(0); + ZetClose(); + + MSM6295Reset(0); + BurnYM3812Reset(); + + soundlatch = 0; + flipscreen = 0; + esd16_tilemap0_color = 0; + esd16_z80_bank = 0; + head_layersize = 0; + headpanic_platform_x = 0; + headpanic_platform_y = 0; + + return 0; +} + +static void calculate_transparency_tables() +{ + memset (DrvGfx0Trans, 1, 0x08000); + memset (DrvGfx1Trans, 1, 0x10000); + memset (DrvGfx2Trans, 1, 0x06000); + + for (INT32 i = 0; i < 0x800000; i++) { + if (DrvGfxROM0[i]) DrvGfx0Trans[i>>8] = 0; + } + + for (INT32 i = 0; i < 0x400000; i++) { + if (DrvGfxROM1[i]) DrvGfx1Trans[i>>6] = 0; + } + + for (INT32 i = 0; i < 0x600000; i++) { + if (DrvGfxROM2[i]) DrvGfx2Trans[i>>8] = 0; + } +} + +static INT32 DrvGfxDecode() +{ + static INT32 Planes0[5] = { + 0x800000, 0x600000, 0x400000, 0x200000, 0x000000 + }; + + static INT32 XOffs0[16] = { + 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000, + 0x087, 0x086, 0x085, 0x084, 0x083, 0x082, 0x081, 0x080 + }; + + static INT32 YOffs0[16] = { + 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 + }; + + static INT32 Planes1[8] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 + }; + + static INT32 XOffs1[8] = { + 0x1800000, 0x1000000, 0x0800000, 0x0000000, + 0x1800008, 0x1000008, 0x0800008, 0x0000008 + }; + + static INT32 YOffs1[8] = { + 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 + }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x140000); + + GfxDecode(0x02000, 5, 16, 16, Planes0, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x400000); + + GfxDecode(0x10000, 8, 8, 8, Planes1, XOffs1, YOffs1, 0x080, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 HedpanicGfxDecode() +{ + static INT32 Planes0[5] = { 0x2000000, 0x0000000, 0x0000008, 0x1000000, 0x1000008 }; + + static INT32 XOffs0[16] = { + 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000, + 0x107, 0x106, 0x105, 0x104, 0x103, 0x102, 0x101, 0x100 + }; + + static INT32 YOffs0[16] = { + 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 + }; + + static INT32 Planes1[8] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 + }; + + static INT32 XOffs1[16] = { + 0x000, 0x010, 0x008, 0x018, 0x020, 0x030, 0x028, 0x038, + 0x200, 0x210, 0x208, 0x218, 0x220, 0x230, 0x228, 0x238 + }; + + static INT32 YOffs1[16] = { + 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x400, 0x440, 0x480, 0x4c0, 0x500, 0x540, 0x580, 0x5c0 + }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x600000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x500000); + + GfxDecode(0x08000, 5, 16, 16, Planes0, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x400000); + + GfxDecode(0x10000, 8, 8, 8, Planes1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM1); + GfxDecode(0x04000, 8, 16, 16, Planes1, XOffs1, YOffs1, 0x800, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 TangtangGfxDecode() +{ + static INT32 Planes0[5] = { + 0x1000000, 0x0c00000, 0x0800000, 0x0400000, 0x0000000 + }; + + static INT32 XOffs0[16] = { + 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000, + 0x087, 0x086, 0x085, 0x084, 0x083, 0x082, 0x081, 0x080 + }; + + static INT32 YOffs0[16] = { + 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 + }; + + static INT32 Planes1[8] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 + }; + + static INT32 XOffs1[16] = { + 0x000, 0x010, 0x008, 0x018, 0x020, 0x030, 0x028, 0x038, + 0x200, 0x210, 0x208, 0x218, 0x220, 0x230, 0x228, 0x238 + }; + + static INT32 YOffs1[16] = { + 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x400, 0x440, 0x480, 0x4c0, 0x500, 0x540, 0x580, 0x5c0 + }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x600000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x280000); + + GfxDecode(0x04000, 5, 16, 16, Planes0, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x400000); + + GfxDecode(0x10000, 8, 8, 8, Planes1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM1); + GfxDecode(0x04000, 8, 16, 16, Planes1, XOffs1, YOffs1, 0x800, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x0080000; + DrvZ80ROM = Next; Next += 0x0040000; + + DrvGfxROM0 = Next; Next += 0x0800000; + DrvGfxROM1 = Next; Next += 0x0400000; + DrvGfxROM2 = Next; Next += 0x0600000; + + DrvGfx0Trans = Next; Next += 0x0008000; + DrvGfx1Trans = Next; Next += 0x0010000; + DrvGfx2Trans = Next; Next += 0x0006000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x0040000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x0010000; + DrvZ80RAM = Next; Next += 0x0000800; + + DrvPalRAM = Next; Next += 0x0001000; + + DrvSprRAM = Next; Next += 0x0000800; + + DrvVidRAM0 = Next; Next += 0x0004000; + DrvVidRAM1 = Next; Next += 0x0004000; + + esd16_scroll_0 = (UINT16*)Next; Next += 0x0000004; + esd16_scroll_1 = (UINT16*)Next; Next += 0x0000004; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static INT32 DrvInit(INT32 (*pInitCallback)()) +{ + INT32 nLen; + + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pInitCallback()) return 1; + + calculate_transparency_tables(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + ZetSetWriteHandler(esd16_sound_write); + ZetSetReadHandler(esd16_sound_read); + ZetSetInHandler(esd16_sound_in); + ZetSetOutHandler(esd16_sound_out); + ZetClose(); + + BurnYM3812Init(4000000, NULL, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + MSM6295Init(0, 1056000 / 132, 60.0, 1); + + EEPROMInit(&eeprom_interface_93C46); // not used in multchmp + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + EEPROMExit(); + MSM6295Exit(0); + BurnYM3812Exit(); + SekExit(); + GenericTilesExit(); + + BurnFree (AllMem); + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +static void esd16_draw_sprites(INT32 priority) +{ + UINT16 *spriteram16 = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x800/2 - 8/2 ; offs += 8/2 ) + { + INT32 y, starty, endy; + + INT32 sx = spriteram16[ offs + 2 ]; + + if ((sx >> 15) != priority) continue; + + int sy = spriteram16[ offs ]; + int code = spriteram16[ offs + 1 ]; + + INT32 dimy = 0x10 << ((sy >> 9) & 3); + + INT32 flipx = 0; + + if (game_select) { + flipx = sy & 0x2000; + } + + INT32 color = (sx >> 9) & 0xf; + + sx = sx & 0x1ff; + if (sx >= 0x180) sx -= 0x200; + + if (game_select) { + sx -= 24; + sy = 0x1ff - (sy & 0x1ff); + starty = sy - dimy; + endy = sy; + } else { + sy = 0x100 - ((sy & 0xff) - (sy & 0x100)); + sy -= dimy; + starty = sy; + endy = sy + dimy; + } + + if (sx >= nScreenWidth || sx < -15) continue; + + for (y = starty - 8; y != endy - 8; y += 16, code++) + { + if (y >= nScreenHeight || y < -15 || DrvGfx0Trans[code]) continue; + + if (sx >= 0 && y >= 0 && sx <= 303 && y <= 223) { + + if (flipx) { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, y, color, 5, 0, 0x200, DrvGfxROM0); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, y, color, 5, 0, 0x200, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, y, color, 5, 0, 0x200, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, y, color, 5, 0, 0x200, DrvGfxROM0); + } + } + } + } +} + +static void draw_background_8x8(UINT8 *vidram, INT32 color, INT32 transp, INT32 scrollx, INT32 scrolly) +{ + INT32 offs; + UINT16 *vram = (UINT16*)vidram; + + scrollx &= 0x3ff; + scrolly &= 0x1ff; + + for (offs = 0; offs < 0x4000 / 2; offs++) { + INT32 code = vram[offs]; + + if (DrvGfx1Trans[code] && transp) continue; + + INT32 sx = (offs & 0x7f) << 3; + INT32 sy = (offs >> 7) << 3; + + sx -= scrollx; + sy -= scrolly; + if (sx > 0x3ff) sx -= 0x400; + if (sy > 0x1ff) sy -= 0x200; + if (sx < -0x07) sx += 0x400; + if (sy < -0x07) sy += 0x200; + + if (sx < -7 || sy < -7 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + if (sx >= 0 && sy >= 0 && sx <= 311 && sy <= 231) { + if (transp) { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvGfxROM1); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 8, 0, DrvGfxROM1); + } + } else { + if (transp) { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 8, 0, DrvGfxROM1); + } + } + } + + return; +} + +static void draw_background_16x16(UINT8 *vidram, INT32 color, INT32 transp, INT32 scrollx, INT32 scrolly) +{ + INT32 offs; + UINT16 *vram = (UINT16*)vidram; + + scrollx &= 0x3ff; + scrolly &= 0x3ff; + + for (offs = 0; offs < 0x1000 / 2; offs++) { + INT32 code = vram[offs] & 0x3fff; + + if (DrvGfx2Trans[code] && transp) continue; + + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= scrollx; + sy -= scrolly; + + if (sx > 0x3ff) sx -= 0x400; + if (sy > 0x3ff) sy -= 0x400; + if (sx < -0x0f) sx += 0x400; + if (sy < -0x0f) sy += 0x400; + + if (sx < -15 || sy < -15 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + if (sx >= 0 && sy >= 0 && sx <= 303 && sy <= 223) { + if (transp) { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile(pTransDraw, code, sx, sy, color, 8, 0, DrvGfxROM2); + } + } else { + if (transp) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 8, 0, DrvGfxROM2); + } + } + } + + return; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + if (head_layersize & 0x0001) { + draw_background_16x16(DrvVidRAM0, esd16_tilemap0_color, 0, esd16_scroll_0[0] + 0x62, esd16_scroll_0[1]+8); + } else { + draw_background_8x8(DrvVidRAM0, esd16_tilemap0_color, 0, esd16_scroll_0[0] + 0x62, esd16_scroll_0[1]+8); + } + + esd16_draw_sprites(1); + + if (head_layersize & 0x0002) { + draw_background_16x16(DrvVidRAM1, 0, 1, esd16_scroll_1[0] + 0x60, esd16_scroll_1[1]+8); + } else { + draw_background_8x8(DrvVidRAM1, 0, 1, esd16_scroll_1[0] + 0x60, esd16_scroll_1[1]+8); + } + + esd16_draw_sprites(0); + + if (flipscreen) { + INT32 screensize = nScreenWidth * nScreenHeight; + for (INT32 i = 0; i < screensize>>1; i++) { + INT32 t = pTransDraw[i]; + pTransDraw[i] = pTransDraw[screensize-(i+1)]; + pTransDraw[screensize-(i+1)] = t; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesSegment; + INT32 nInterleave = 64; + INT32 nCyclesTotal[2]; + INT32 nCyclesDone[2]; + + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = ~0; + + if (game_select == 0) { + DrvInputs[2] = (DrvDips[1] << 8) | DrvDips[0]; + } + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + } + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + + nCyclesDone[0] += SekRun(nCyclesSegment); + + nCyclesSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + if (i & 1) ZetNmi(); + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029692; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + EEPROMScan(nAction, pnMin); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(flipscreen); + SCAN_VAR(soundlatch); + SCAN_VAR(esd16_tilemap0_color); + SCAN_VAR(head_layersize); + SCAN_VAR(headpanic_platform_x); + SCAN_VAR(headpanic_platform_y); + SCAN_VAR(game_select); + SCAN_VAR(esd16_z80_bank); + + ZetOpen(0); + esd16_sound_rombank_w(esd16_z80_bank); + ZetClose(); + } + + return 0; +} + +//---------------------------------------------------------------------------------------------------------- + +// Multi Champ (World) + +static struct BurnRomInfo multchmpRomDesc[] = { + { "esd2.cu02", 0x040000, 0x2d1b098a, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd1.cu03", 0x040000, 0x10974063, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x020000, 0x7c178bd7, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "esd14.ju03", 0x040000, 0xa6122225, 3 | BRF_GRA }, // 3 - Sprites + { "esd15.ju04", 0x040000, 0x88b7a97c, 3 | BRF_GRA }, // 4 + { "esd16.ju05", 0x040000, 0xe670a6da, 3 | BRF_GRA }, // 5 + { "esd17.ju06", 0x040000, 0xa69d4399, 3 | BRF_GRA }, // 6 + { "esd13.ju07", 0x040000, 0x22071594, 3 | BRF_GRA }, // 7 + + { "esd5.fu27", 0x080000, 0x299f32c2, 4 | BRF_GRA }, // 8 - Tiles + { "esd6.fu32", 0x080000, 0xe2689bb2, 4 | BRF_GRA }, // 9 + { "esd11.fu29", 0x080000, 0x9bafd8ee, 4 | BRF_GRA }, // 10 + { "esd12.fu33", 0x080000, 0xc6b86001, 4 | BRF_GRA }, // 11 + { "esd7.fu26", 0x080000, 0xa783a003, 4 | BRF_GRA }, // 12 + { "esd8.fu30", 0x080000, 0x22861af2, 4 | BRF_GRA }, // 13 + { "esd9.fu28", 0x080000, 0x6652c04a, 4 | BRF_GRA }, // 14 + { "esd10.fu31", 0x080000, 0xd815974b, 4 | BRF_GRA }, // 15 + + { "esd4.su10", 0x020000, 0x6e741fcd, 5 | BRF_SND }, // 16 - OKI Samples +}; + +STD_ROM_PICK(multchmp) +STD_ROM_FN(multchmp) + +static INT32 multchmpCallback() +{ + game_select = 0; + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x40000, i + 3, 1)) return 1; + } + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x80000, i + 8, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 16, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x200000, 0x2005ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x300000, 0x3007ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x300800, 0x300fff, SM_RAM); // mirror + SekMapMemory(DrvVidRAM0, 0x400000, 0x403fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x420000, 0x423fff, SM_RAM); + SekSetWriteByteHandler(0, multchmp_write_byte); + SekSetWriteWordHandler(0, multchmp_write_word); + SekSetReadByteHandler(0, multchmp_read_byte); + SekSetReadWordHandler(0, multchmp_read_word); + SekClose(); + + return 0; +} + +static INT32 MultchmpInit() +{ + return DrvInit(multchmpCallback); +} + +struct BurnDriver BurnDrvMultchmp = { + "multchmp", NULL, NULL, NULL, "1999", + "Multi Champ (World)\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, multchmpRomInfo, multchmpRomName, NULL, NULL, MultchmpInputInfo, MultchmpDIPInfo, + MultchmpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Multi Champ (Korea) + +static struct BurnRomInfo multchmkRomDesc[] = { + { "multchmp.u02", 0x040000, 0x7da8c0df, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "multchmp.u03", 0x040000, 0x5dc62799, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x020000, 0x7c178bd7, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "multchmp.u36", 0x040000, 0xd8f06fa8, 3 | BRF_GRA }, // 3 - Sprites + { "multchmp.u37", 0x040000, 0xb1ae7f08, 3 | BRF_GRA }, // 4 + { "multchmp.u38", 0x040000, 0x88e252e8, 3 | BRF_GRA }, // 5 + { "multchmp.u39", 0x040000, 0x51f01067, 3 | BRF_GRA }, // 6 + { "multchmp.u35", 0x040000, 0x9d1590a6, 3 | BRF_GRA }, // 7 + + { "multchmp.u27", 0x080000, 0xdc42704e, 4 | BRF_GRA }, // 8 - Tiles + { "multchmp.u28", 0x080000, 0x449991fa, 4 | BRF_GRA }, // 9 + { "multchmp.u33", 0x080000, 0xe4c0ec96, 4 | BRF_GRA }, // 10 + { "multchmp.u34", 0x080000, 0xbffaaccc, 4 | BRF_GRA }, // 11 + { "multchmp.u29", 0x080000, 0x01bd1399, 4 | BRF_GRA }, // 12 + { "multchmp.u30", 0x080000, 0xc6b4cc18, 4 | BRF_GRA }, // 13 + { "multchmp.u31", 0x080000, 0xb1e4e9e3, 4 | BRF_GRA }, // 14 + { "multchmp.u32", 0x080000, 0xf05cb5b4, 4 | BRF_GRA }, // 15 + + { "esd4.su10", 0x020000, 0x6e741fcd, 5 | BRF_SND }, // 16 - OKI Samples +}; + +STD_ROM_PICK(multchmk) +STD_ROM_FN(multchmk) + +struct BurnDriver BurnDrvMultchmk = { + "multchmpk", "multchmp", NULL, NULL, "1999", + "Multi Champ (Korea)\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, multchmkRomInfo, multchmkRomName, NULL, NULL, MultchmpInputInfo, MultchmpDIPInfo, + MultchmpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Head Panic (ver. 0117, 17/01/2000) + +static struct BurnRomInfo hedpanicRomDesc[] = { + { "esd2.cu03", 0x040000, 0x7c7be3bb, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd1.cu02", 0x040000, 0x42405e9d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0xa88d4424, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "esd7.ju02", 0x200000, 0x055d525f, 3 | BRF_GRA }, // 3 - Sprites + { "esd6.ju01", 0x200000, 0x5858372c, 3 | BRF_GRA }, // 4 + { "esd5.ju07", 0x080000, 0xbd785921, 3 | BRF_GRA }, // 5 + + { "esd8.fu35", 0x200000, 0x23aceb4f, 4 | BRF_GRA }, // 6 - Tiles + { "esd9.fu34", 0x200000, 0x76b46cd2, 4 | BRF_GRA }, // 7 + + { "esd4.su10", 0x020000, 0x3c11c590, 5 | BRF_SND }, // 8 - OKI Samples + + { "hedpanic.nv",0x000080, 0xe91f4038, 0 | BRF_OPT }, // 9 - Default EEPROM +}; + +STD_ROM_PICK(hedpanic) +STD_ROM_FN(hedpanic) + +static INT32 hedpanicCallback() +{ + game_select = 1; + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x400000, 5, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 8, 1)) return 1; + + HedpanicGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x800000, 0x8007ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x900000, 0x9007ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x900800, 0x900fff, SM_RAM); // mirror + SekMapMemory(DrvVidRAM0, 0xa00000, 0xa03fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xa20000, 0xa23fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xa24000, 0xa27fff, SM_RAM); // mirror + SekSetWriteByteHandler(0, hedpanic_write_byte); + SekSetWriteWordHandler(0, hedpanic_write_word); + SekSetReadByteHandler(0, hedpanic_read_byte); + SekSetReadWordHandler(0, hedpanic_read_word); + SekClose(); + + return 0; +} + +static INT32 HedpanicInit() +{ + return DrvInit(hedpanicCallback); +} + +struct BurnDriver BurnDrvHedpanic = { + "hedpanic", NULL, NULL, NULL, "2000", + "Head Panic (ver. 0117, 17/01/2000)\0", "Story line & game instructions in English", "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, hedpanicRomInfo, hedpanicRomName, NULL, NULL, HedpanicInputInfo, NULL, + HedpanicInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Head Panic (ver. 0315, 15/03/2000) + +static struct BurnRomInfo hedpanifRomDesc[] = { + { "esd2", 0x040000, 0x8cccc691, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd1", 0x040000, 0xd8574925, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0xa88d4424, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "esd7.ju02", 0x200000, 0x055d525f, 3 | BRF_GRA }, // 3 - Sprites + { "esd6.ju01", 0x200000, 0x5858372c, 3 | BRF_GRA }, // 4 + { "esd5.ju07", 0x080000, 0xbd785921, 3 | BRF_GRA }, // 5 + + { "esd8.fu35", 0x200000, 0x23aceb4f, 4 | BRF_GRA }, // 6 - Tiles + { "esd9.fu34", 0x200000, 0x76b46cd2, 4 | BRF_GRA }, // 7 + + { "esd4.su10", 0x020000, 0x3c11c590, 5 | BRF_SND }, // 8 - OKI Samples + + { "hedpanic.nv",0x000080, 0xe91f4038, 0 | BRF_OPT }, // 9 - Default EEPROM +}; + +STD_ROM_PICK(hedpanif) +STD_ROM_FN(hedpanif) + +struct BurnDriver BurnDrvHedpanif = { + "hedpanicf", "hedpanic", NULL, NULL, "2000", + "Head Panic (ver. 0315, 15/03/2000)\0", "Story line in Japanese, game instructions in English", "ESD / Fuuki", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, hedpanifRomInfo, hedpanifRomName, NULL, NULL, HedpanicInputInfo, NULL, + HedpanicInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Multi Champ Deluxe (ver. 0106, 06/01/2000) + +static struct BurnRomInfo mchampdxRomDesc[] = { + { "ver0106_esd2.cu02", 0x040000, 0xea98b3fd, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "ver0106_esd1.cu03", 0x040000, 0xc6e4546b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0x1b22568c, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "ver0106_ju02.bin", 0x200000, 0xb27a4977, 3 | BRF_GRA }, // 3 - Sprites + { "ver0106_ju01.bin", 0x200000, 0x55841d90, 3 | BRF_GRA }, // 4 + { "ver0106_esd5.ju07", 0x040000, 0x7a3ac887, 3 | BRF_GRA }, // 5 + + { "rom.fu35", 0x200000, 0xba46f3dc, 4 | BRF_GRA }, // 6 - Tiles + { "rom.fu34", 0x200000, 0x2895cf09, 4 | BRF_GRA }, // 7 + + { "ver0106_esd4.su10", 0x040000, 0xac8ae009, 5 | BRF_SND }, // 8 - OKI Samples +}; + +STD_ROM_PICK(mchampdx) +STD_ROM_FN(mchampdx) + +static INT32 mchampdxCallback() +{ + game_select = 3; + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x400000, 5, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 8, 1)) return 1; + + HedpanicGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x300000, 0x303fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x320000, 0x323fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x324000, 0x327fff, SM_RAM); // mirror + SekMapMemory(DrvPalRAM, 0x400000, 0x400fff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x600000, 0x6007ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x600800, 0x6007ff, SM_RAM); // mirror + SekSetWriteByteHandler(0, mchampdx_write_byte); + SekSetWriteWordHandler(0, mchampdx_write_word); + SekSetReadByteHandler(0, mchampdx_read_byte); + SekSetReadWordHandler(0, mchampdx_read_word); + SekClose(); + + return 0; +} + +static INT32 MchampdxInit() +{ + return DrvInit(mchampdxCallback); +} + +struct BurnDriver BurnDrvMchampdx = { + "mchampdx", NULL, NULL, NULL, "2000", + "Multi Champ Deluxe (ver. 0106, 06/01/2000)\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, mchampdxRomInfo, mchampdxRomName, NULL, NULL, HedpanicInputInfo, NULL, + MchampdxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Multi Champ Deluxe (ver. 1126, 26/11/1999) + +static struct BurnRomInfo mchampdaRomDesc[] = { + { "esd2.cu02", 0x040000, 0x4cca802c, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd1.cu03", 0x040000, 0x0af1cd0a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0x1b22568c, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "rom.ju01", 0x200000, 0x1a749fc2, 3 | BRF_GRA }, // 3 - Sprites + { "rom.ju02", 0x200000, 0x7e87e332, 3 | BRF_GRA }, // 4 + { "esd5.ju07", 0x080000, 0x6cc871cc, 3 | BRF_GRA }, // 5 + + { "rom.fu35", 0x200000, 0xba46f3dc, 4 | BRF_GRA }, // 6 - Tiles + { "rom.fu34", 0x200000, 0x2895cf09, 4 | BRF_GRA }, // 7 + + { "esd4.su10", 0x040000, 0x2fbe94ab, 5 | BRF_SND }, // 8 - OKI Samples +}; + +STD_ROM_PICK(mchampda) +STD_ROM_FN(mchampda) + +struct BurnDriver BurnDrvMchampda = { + "mchampdxa", "mchampdx", NULL, NULL, "1999", + "Multi Champ Deluxe (ver. 1126, 26/11/1999)\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, mchampdaRomInfo, mchampdaRomName, NULL, NULL, HedpanicInputInfo, NULL, + MchampdxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// Tang Tang (ver. 0526, 26/05/2000) + +static struct BurnRomInfo tangtangRomDesc[] = { + { "esd2.cu02", 0x040000, 0xb6dd6e3d, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd1.cu03", 0x040000, 0xb6c0f2f4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0xd48ecc5c, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "xju04.bin", 0x040000, 0xf999b9d7, 3 | BRF_GRA }, // 3 - Sprites + { "xju05.bin", 0x040000, 0x679302cf, 3 | BRF_GRA }, // 4 + { "xju06.bin", 0x040000, 0x01f59ff7, 3 | BRF_GRA }, // 5 + { "xju07.bin", 0x040000, 0x556acac3, 3 | BRF_GRA }, // 6 + { "xju08.bin", 0x040000, 0xecc2d8c7, 3 | BRF_GRA }, // 7 + + { "fu35.bin", 0x200000, 0x84f3f833, 4 | BRF_GRA }, // 8 - Tiles + { "fu34.bin", 0x200000, 0xbf91f543, 4 | BRF_GRA }, // 9 + + { "esd4.su10", 0x020000, 0xf2dfb02d, 5 | BRF_SND }, // 10 - OKI Samples +}; + +STD_ROM_PICK(tangtang) +STD_ROM_FN(tangtang) + +static INT32 tangtangCallback() +{ + game_select = 4; + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000, 3 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 10, 1)) return 1; + + TangtangGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x100000, 0x100fff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x200000, 0x2007ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x200800, 0x200fff, SM_RAM); // mirror + SekMapMemory(DrvVidRAM0, 0x300000, 0x303fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x320000, 0x323fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x324000, 0x327fff, SM_RAM); // mirror + SekMapMemory(Drv68KRAM, 0x700000, 0x70ffff, SM_RAM); + SekSetWriteByteHandler(0, tangtang_write_byte); + SekSetWriteWordHandler(0, tangtang_write_word); + SekSetReadByteHandler(0, tangtang_read_byte); + SekSetReadWordHandler(0, tangtang_read_word); + SekClose(); + + return 0; +} + +static INT32 TangtangInit() +{ + return DrvInit(tangtangCallback); +} + +struct BurnDriver BurnDrvTangtang = { + "tangtang", NULL, NULL, NULL, "2000", + "Tang Tang (ver. 0526, 26/05/2000)\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, tangtangRomInfo, tangtangRomName, NULL, NULL, HedpanicInputInfo, NULL, + TangtangInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; + + +// SWAT Police + +static struct BurnRomInfo swatpolcRomDesc[] = { + { "esd.cu02", 0x040000, 0x29e0c126, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "esd.cu03", 0x040000, 0x1070208b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "esd3.su06", 0x040000, 0x80e97dbe, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "esd1.ju03", 0x080000, 0x17fcc5e7, 3 | BRF_GRA }, // 3 - Sprites + { "esd2.ju04", 0x080000, 0x9c1752f2, 3 | BRF_GRA }, // 4 + { "esd3.ju05", 0x080000, 0xe8d9c092, 3 | BRF_GRA }, // 5 + { "esd4.ju06", 0x080000, 0xbde1b130, 3 | BRF_GRA }, // 6 + { "esd5.ju07", 0x080000, 0xd2c27f03, 3 | BRF_GRA }, // 7 + + { "fu35", 0x200000, 0xc55897c5, 4 | BRF_GRA }, // 8 - Tiles + { "fu34", 0x200000, 0x7117a6a2, 4 | BRF_GRA }, // 9 + + { "at27c020.su10", 0x040000, 0xc43efec2, 5 | BRF_SND }, // 10 - OKI Samples +}; + +STD_ROM_PICK(swatpolc) +STD_ROM_FN(swatpolc) + +static INT32 swatpolcCallback() +{ + game_select = 5; + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000, 3 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 10, 1)) return 1; + + TangtangGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x800000, 0x8007ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x900000, 0x9007ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x900800, 0x900fff, SM_RAM); // mirror + SekMapMemory(DrvVidRAM0, 0xa00000, 0xa03fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xa20000, 0xa23fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xa24000, 0xa27fff, SM_RAM); // mirror + SekSetWriteByteHandler(0, hedpanic_write_byte); + SekSetWriteWordHandler(0, hedpanic_write_word); + SekSetReadByteHandler(0, hedpanic_read_byte); + SekSetReadWordHandler(0, hedpanic_read_word); + SekClose(); + + return 0; +} + +static INT32 SwatpolcInit() +{ + return DrvInit(swatpolcCallback); +} + +struct BurnDriver BurnDrvSwatpolc = { + "swatpolc", NULL, NULL, NULL, "2001", + "SWAT Police\0", NULL, "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, swatpolcRomInfo, swatpolcRomName, NULL, NULL, SwatpolcInputInfo, NULL, + SwatpolcInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_f1gp.cpp b/src/burn/drivers/misc_post90s/d_f1gp.cpp new file mode 100644 index 00000000..0a52636e --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_f1gp.cpp @@ -0,0 +1,1387 @@ +// FB Alpha F-1 Grand Prix driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2610.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM0; +static UINT8 *Drv68KROM1; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZoomRAM; +static UINT8 *DrvRozVidRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvShareRAM; +static UINT8 *DrvSprVRAM1; +static UINT8 *DrvSprVRAM2; +static UINT8 *DrvSprCGRAM1; +static UINT8 *DrvSprCGRAM2; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvBgDirty; +static UINT8 *DrvBgTileDirty; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 *DrvBgTmp; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT8 *gfxctrl; +static UINT8 *pending_command; +static UINT8 *roz_bank; +static UINT8 *DrvZ80Bank; +static UINT16 *DrvFgScrollX; +static UINT16 *DrvFgScrollY; +static UINT16 *DrvBgCtrl; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvDips[4]; +static UINT16 DrvInputs[3]; +static UINT8 DrvReset; + +static INT16 zoom_table[32][33]; + +static INT32 nScreenStartY = 8; + +static struct BurnInputInfo F1gpInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 9, "p2 coin" }, + {"Start", BIT_DIGITAL, DrvJoy1 + 10, "p1 start" }, + {"Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 14, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Region", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(F1gp) + +static struct BurnInputInfo F1gp2InputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 9, "p2 coin" }, + {"Start", BIT_DIGITAL, DrvJoy1 + 10, "p1 start" }, + {"Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + {"Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 14, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Region", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(F1gp2) + +static struct BurnDIPInfo F1gpDIPList[]= +{ + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xfb, NULL }, + {0x0c, 0xff, 0xff, 0x10, NULL }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0a, 0x01, 0x01, 0x01, "Off" }, + {0x0a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0a, 0x01, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x0a, 0x01, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x0a, 0x01, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x0a, 0x01, 0x0e, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x0a, 0x01, 0x70, 0x50, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x0a, 0x01, 0x70, 0x40, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0x70, 0x30, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0x70, 0x20, "1 Coin 4 Credits" }, + {0x0a, 0x01, 0x70, 0x10, "1 Coin 5 Credits" }, + {0x0a, 0x01, 0x70, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x0a, 0x01, 0x80, 0x80, "Off" }, + {0x0a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x09, 0x01, 0x03, 0x02, "Easy" }, + {0x09, 0x01, 0x03, 0x03, "Normal" }, + {0x09, 0x01, 0x03, 0x01, "Hard" }, + {0x09, 0x01, 0x03, 0x00, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Game Mode" }, +// {0x09, 0x01, 0x04, 0x04, "Single" }, +// {0x09, 0x01, 0x04, 0x00, "Multiple" }, // ID CHECK ERROR + + {0 , 0xfe, 0 , 2, "Mode Select" }, + {0x09, 0x01, 0x08, 0x00, "Off" }, + {0x09, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x0b, 0x01, 0x02, 0x02, "Off" }, +// {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 6, "Country" }, + {0x0c, 0x01, 0x1f, 0x10, "World" }, + {0x0c, 0x01, 0x1f, 0x01, "USA & Canada"}, + {0x0c, 0x01, 0x1f, 0x00, "Japan" }, + {0x0c, 0x01, 0x1f, 0x02, "Korea" }, + {0x0c, 0x01, 0x1f, 0x04, "Hong Kong" }, + {0x0c, 0x01, 0x1f, 0x08, "Taiwan" }, +}; + +STDDIPINFO(F1gp) + +static struct BurnDIPInfo F1gp2DIPList[]= +{ + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xfb, NULL }, + {0x0d, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0b, 0x01, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x0b, 0x01, 0x0e, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x0b, 0x01, 0x70, 0x50, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x70, 0x40, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0x70, 0x30, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0x70, 0x20, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0x70, 0x10, "1 Coin 5 Credits" }, + {0x0b, 0x01, 0x70, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x0b, 0x01, 0x80, 0x80, "Off" }, + {0x0b, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0a, 0x01, 0x03, 0x02, "Easy" }, + {0x0a, 0x01, 0x03, 0x03, "Normal" }, + {0x0a, 0x01, 0x03, 0x01, "Hard" }, + {0x0a, 0x01, 0x03, 0x00, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Game Mode" }, +// {0x0a, 0x01, 0x04, 0x04, "Single" }, +// {0x0a, 0x01, 0x04, 0x00, "Multiple" }, // ID CHECK ERROR + + {0 , 0xfe, 0 , 2, "Mode Select" }, + {0x0a, 0x01, 0x08, 0x00, "Off" }, + {0x0a, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0c, 0x01, 0x01, 0x01, "Off" }, + {0x0c, 0x01, 0x01, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x0c, 0x01, 0x02, 0x02, "Off" }, +// {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Country" }, + {0x0d, 0x01, 0x01, 0x01, "World" }, + {0x0d, 0x01, 0x01, 0x00, "Japan" }, +}; + +STDDIPINFO(F1gp2) + +static inline void expand_dynamic_tiles(INT32 offset) +{ + UINT16 data = *((UINT16*)(DrvZoomRAM + offset)); + + offset <<= 1; + + DrvGfxROM3[offset + 0] = (data >> 12) & 0x0f; + DrvGfxROM3[offset + 1] = (data >> 8) & 0x0f; + DrvGfxROM3[offset + 2] = (data >> 4) & 0x0f; + DrvGfxROM3[offset + 3] = (data >> 0) & 0x0f; + + DrvBgTileDirty[offset >> 8] = 1; +} + +void __fastcall f1gp_main_write_word(UINT32 address, UINT16 data) +{ + if (((address & 0xfffffe0) == 0xfff040 && nScreenStartY == 8) || // f1gp + ((address & 0xffffff0) == 0xfff020 && nScreenStartY == 0)) { // f1gp2 + DrvBgCtrl[(address >> 1) & 0x0f] = data; + return; + } + + if ((address & 0xfc0000) == 0xc00000) { + UINT16 *p = (UINT16*)(DrvZoomRAM + (address & 0x3fffe)); + + if (p[0] == data) return; + + p[0] = data; + + expand_dynamic_tiles(address & 0x3fffe); + + return; + } + + if ((address & 0xff8000) == 0xd00000) { + UINT16 *p = (UINT16*)(DrvRozVidRAM + (address & 0x1ffe)); + + if (p[0] == data) return; + + p[0] = data; + + DrvBgDirty[(address >> 1) & 0xfff] = 1; + + return; + } + + switch (address) + { + case 0xfff002: // f1gp + case 0xfff003: + *DrvFgScrollX = data & 0x1ff; + return; + + case 0xfff004: + case 0xfff005: + *DrvFgScrollY = data & 0x0ff; + return; + + case 0xfff044: // f1gp2 + case 0xfff045: + *DrvFgScrollX = (data+80) & 0x1ff; + return; + + case 0xfff046: + case 0xfff047: + *DrvFgScrollY = (data+26) & 0x0ff; + return; + } +} + +void __fastcall f1gp_main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xff8000) == 0xd00000) { + address = (address & 0x1fff) ^ 1; + + INT32 d = DrvRozVidRAM[address]; + + if (d == data) return; + + DrvRozVidRAM[address] = data; + DrvBgDirty[(address >> 1) & 0xfff] = 1; + + return; + } + + switch (address) + { + case 0xfff000: + if (*roz_bank != data) { + *roz_bank = data; + memset (DrvBgDirty, 1, 0x1000); + } + return; + + case 0xfff001: + *flipscreen = data & 0x20; + *gfxctrl = data & 0xdf; + return; + + case 0xfff009: + { + INT32 t = (SekTotalCycles() / 2) - ZetTotalCycles(); + if (t > 0) ZetRun(t); + *pending_command = 0xff; + *soundlatch = data; + ZetNmi(); + } + return; + } +} + +UINT16 __fastcall f1gp_main_read_word(UINT32 address) +{ + switch (address) + { + case 0xfff004: + return (DrvDips[1] << 8) | DrvDips[0]; + + case 0xfff006: + return (DrvDips[2] << 8); + } + + return 0; +} + +UINT8 __fastcall f1gp_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0xfff000: + case 0xfff001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0xfff004: + return DrvDips[0]; + + case 0xfff005: + return DrvDips[1]; + + case 0xfff006: + return DrvDips[2]; + + case 0xfff009: + return *pending_command; + + case 0xfff00b: + case 0xfff051: + return DrvDips[3]; + } + + return 0; +} + +static void sound_bankswitch(INT32 data) +{ + INT32 nBank = ((data & 1) << 15) + 0x8000; + + *DrvZ80Bank = data & 1; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + nBank); +} + +void __fastcall f1gp_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x0c: + sound_bankswitch(data); + return; + + case 0x14: + *pending_command = 0; + return; + + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + BurnYM2610Write(port & 3, data); + return; + } +} + +UINT8 __fastcall f1gp_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x14: + return *soundlatch; + + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + return BurnYM2610Read(port & 3); + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 5000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 5000000.0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + memset (DrvBgDirty, 1, 0x1000); + memset (DrvBgTileDirty, 1, 0x0800); + + SekOpen(0); + SekReset(); + SekClose(); + + SekOpen(1); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2610Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM0 = Next; Next += 0x500000; + Drv68KROM1 = Next; Next += 0x020000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM3 = Next; Next += 0x800000; + + DrvSndROM = Next; Next += 0x200000; + + DrvPalette = (UINT32 *)Next; Next += 0x000401 * sizeof(UINT32); + + DrvBgDirty = Next; Next += 0x001000; + DrvBgTileDirty = Next; Next += 0x000800; + DrvBgTmp = (UINT16*)Next; Next += 0x100000 * sizeof(UINT16); + + AllRam = Next; + + Drv68KRAM0 = Next; Next += 0x004000; + Drv68KRAM1 = Next; Next += 0x004000; + DrvShareRAM = Next; Next += 0x001000; + DrvZoomRAM = Next; Next += 0x040000; + DrvPalRAM = Next; Next += 0x001000; + DrvRozVidRAM = Next; Next += 0x002000; + DrvVidRAM = Next; Next += 0x001000; + + DrvSprVRAM1 = Next; Next += 0x001000; + DrvSprVRAM2 = Next; Next += 0x000400; + + DrvSprCGRAM1 = Next; Next += 0x008000; + DrvSprCGRAM2 = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x000800; + + pending_command = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + gfxctrl = Next; Next += 0x000001; + roz_bank = Next; Next += 0x000001; + + DrvZ80Bank = Next; Next += 0x000001; + + DrvFgScrollX = (UINT16*)Next; Next += 0x000001 * sizeof(UINT16); + DrvFgScrollY = (UINT16*)Next; Next += 0x000001 * sizeof(UINT16); + DrvBgCtrl = (UINT16*)Next; Next += 0x000010 * sizeof(UINT16); + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void DrvInitZoomTable() +{ + zoom_table[0][0] = -1; + + for (INT32 x = 1; x < 32; x++) { + for (INT32 y = 0; y < 16; y++) { + float t = ((16.0000-1.0000) / x) * y; + zoom_table[x][y] = (t >= 16) ? -1 : (INT32)t; + } + } +} + +static void WordSwap(UINT8 *src, INT32 len) +{ + for (INT32 i = 0; i < len; i+=4) { + INT32 d = src[i+1]; + src[i+1] = src[i+2]; + src[i+2] = d; + } +} + +static INT32 F1gpGfxDecode() +{ + INT32 Plane[8] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x004, 0x000, 0x00c, 0x008, 0x014, 0x010, 0x01c, 0x018, + 0x024, 0x020, 0x02c, 0x028, 0x034, 0x030, 0x03c, 0x038 }; + INT32 YOffs[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 F1gp2GfxDecode() +{ + INT32 Plane[8] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x008, 0x00c, 0x000, 0x004, 0x018, 0x01c, 0x010, 0x014, + 0x028, 0x02c, 0x020, 0x024, 0x038, 0x03c, 0x030, 0x034 }; + INT32 YOffs[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x200000; i++) { + tmp[i^1] = (DrvGfxROM1[i] << 4) | (DrvGfxROM1[i] >> 4); + } + + GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM3, 0x400000); + + GfxDecode(0x8000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 nGame) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (nGame) { + nScreenStartY = 0; + + if (BurnLoadRom(Drv68KROM0 + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0300000, 2, 1)) return 1; + memcpy (Drv68KROM0 + 0x100000, Drv68KROM0 + 0x400000, 0x100000); + memcpy (Drv68KROM0 + 0x200000, Drv68KROM0 + 0x300000, 0x100000); + + if (BurnLoadRom(Drv68KROM1, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 11, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x0100000, 12, 1)) return 1; + + F1gp2GfxDecode(); + } else { + if (BurnLoadRom(Drv68KROM0 + 0x0000000, 0, 1)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0100000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0100001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0180000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0180001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0200000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0200001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0280000, 7, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0280001, 8, 2)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0300000, 9, 1)) return 1; + if (BurnLoadRom(Drv68KROM0 + 0x0400000, 10, 1)) return 1; + + if (BurnLoadRom(Drv68KROM1, 11, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 14, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 16, 2)) return 1; + WordSwap(DrvGfxROM1, 0x100000); + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 18, 2)) return 1; + WordSwap(DrvGfxROM2, 0x080000); + + if (BurnLoadRom(DrvSndROM + 0x0000000, 19, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x0100000, 20, 1)) return 1; + + F1gpGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM0, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KROM0 + 0x100000, 0x100000, 0x2fffff, SM_ROM); + SekMapMemory(DrvRozVidRAM, 0xd00000, 0xd01fff, SM_ROM); + SekMapMemory(DrvRozVidRAM, 0xd02000, 0xd03fff, SM_ROM); + SekMapMemory(DrvRozVidRAM, 0xd04000, 0xd05fff, SM_ROM); + SekMapMemory(DrvRozVidRAM, 0xd06000, 0xd07fff, SM_ROM); + + if (nGame) { + SekMapMemory(DrvSprCGRAM1, 0xa00000, 0xa07fff, SM_RAM); + SekMapMemory(DrvSprVRAM1, 0xe00000, 0xe00fff, SM_RAM); + } else { + SekMapMemory(Drv68KROM0 + 0x300000, 0xa00000, 0xbfffff, SM_ROM); + SekMapMemory(DrvZoomRAM, 0xc00000, 0xc3ffff, SM_ROM); + SekMapMemory(DrvSprCGRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(DrvSprCGRAM2, 0xe04000, 0xe07fff, SM_RAM); + SekMapMemory(DrvSprVRAM1, 0xf00000, 0xf003ff, SM_RAM); + SekMapMemory(DrvSprVRAM2, 0xf10000, 0xf103ff, SM_RAM); + } + + SekMapMemory(Drv68KRAM0, 0xff8000, 0xffbfff, SM_RAM); + SekMapMemory(DrvShareRAM, 0xffc000, 0xffcfff, SM_RAM); + SekMapMemory(DrvVidRAM, 0xffd000, 0xffdfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xffe000, 0xffefff, SM_RAM); + SekSetWriteWordHandler(0, f1gp_main_write_word); + SekSetWriteByteHandler(0, f1gp_main_write_byte); + SekSetReadWordHandler(0, f1gp_main_read_word); + SekSetReadByteHandler(0, f1gp_main_read_byte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Drv68KROM1, 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Drv68KRAM1, 0xff8000, 0xffbfff, SM_RAM); + SekMapMemory(DrvShareRAM, 0xffc000, 0xffcfff, SM_RAM); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x77ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x77ff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + 0x8000); + ZetSetOutHandler(f1gp_sound_out); + ZetSetInHandler(f1gp_sound_in); + ZetMemEnd(); + ZetClose(); + + INT32 DrvSndROMLen = 0x100000; + BurnYM2610Init(8000000, DrvSndROM + 0x100000, &DrvSndROMLen, DrvSndROM, &DrvSndROMLen, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(5000000); + + DrvInitZoomTable(); + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2610Exit(); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + nScreenStartY = 8; + + return 0; +} + +static void draw_foreground(INT32 transp) +{ + transp *= 0xff; + + UINT16 *vram = (UINT16*)DrvVidRAM; + + for (INT32 offs = nScreenStartY; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = ((offs >> 6) << 3) - nScreenStartY; + + sx -= *DrvFgScrollX; + if (sx < -7) sx += 512; + sy -= *DrvFgScrollY; + if (sy < -7) sy += 256; + + INT32 code = vram[offs] & 0x7fff; + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 flipy = vram[offs] & 0x8000; + + if (transp) { + if (flipy) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, 0, 8, transp, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 8, transp, 0, DrvGfxROM0); + } + } else { + if (flipy) { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0); + } + } + } +} + +static void draw_16x16_zoom(UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 xz, INT32 yz, INT32 fx, INT32 fy) +{ + if (yz <= 1 || xz <= 1) return; + + if (yz == 16 && xz == 16) { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, gfx); + } + } + + return; + } + + fx = (fx * 0x0f); + fy = (fy >> 1) * 0x0f; + + color = (color << 4); + UINT8 *src = gfx + (code << 8); + + INT16 *xm = zoom_table[xz-1]; + INT16 *ym = zoom_table[yz-1]; + + for (INT32 y = 0; y < 16; y++) + { + INT32 yy = sy + y; + + if (ym[y ^ fy] == -1 || yy < 0 || yy >= nScreenHeight) continue; + + INT32 yyz = (ym[y ^ fy] << 4); + + for (INT32 x = 0; x < 16; x++) + { + INT16 xxz = xm[x ^ fx]; + if (xxz == -1) continue; + + INT32 xx = sx + x; + + INT32 pxl = src[yyz|xxz]; + + if (pxl == 15 || xx < 0 || xx >= nScreenWidth || yy < 0 || yy >= nScreenHeight) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = pxl | color; + } + } +} + +static void f1gp_draw_sprites(UINT8 *ram0, UINT8 *ram1, UINT8 *gfx, INT32 colo) +{ + INT32 attr_start,first; + UINT16 *spram = (UINT16*)ram0; + UINT16 *spram2 = (UINT16*)ram1; + + static const INT32 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; + + first = 4 * spram[0x1fe]; + + for (attr_start = first; attr_start < 0x0200; attr_start += 4) + { + INT32 map_start; + INT32 ox,oy,x,y,xsize,ysize,zoomx,zoomy,flipx,flipy,color; + + if (!(spram[attr_start + 2] & 0x0080)) continue; + + oy = spram[attr_start + 0] & 0x01ff; + zoomy = (spram[attr_start + 0] & 0xf000) >> 12; + ox = spram[attr_start + 1] & 0x01ff; + zoomx = (spram[attr_start + 1] & 0xf000) >> 12; + xsize = (spram[attr_start + 2] & 0x0700) >> 8; + flipx = spram[attr_start + 2] & 0x0800; + ysize = (spram[attr_start + 2] & 0x7000) >> 12; + flipy = spram[attr_start + 2] & 0x8000; + color = (spram[attr_start + 2] & 0x000f) | colo; + map_start = spram[attr_start + 3]; + + zoomx = 16 - zoomtable[zoomx]/8; + zoomy = 16 - zoomtable[zoomy]/8; + + for (y = 0;y <= ysize;y++) + { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y) + 16) & 0x1ff) - 16; + else sy = ((oy + zoomy * y + 16) & 0x1ff) - 16; + + for (x = 0;x <= xsize;x++) + { + INT32 code; + + if (flipx) sx = ((ox + zoomx * (xsize - x) + 16) & 0x1ff) - 16; + else sx = ((ox + zoomx * x + 16) & 0x1ff) - 16; + + code = spram2[map_start & 0x1fff] & 0x1fff; + map_start++; + + draw_16x16_zoom(gfx, code, color, sx, sy-8, zoomx, zoomy, flipx, flipy); + } + + if (xsize == 2) map_start += 1; + if (xsize == 4) map_start += 3; + if (xsize == 5) map_start += 2; + if (xsize == 6) map_start += 1; + } + } +} + +static void f1gp2_draw_sprites() +{ + INT32 offs = 0; + UINT16 *spram = (UINT16*)DrvSprVRAM1; + UINT16 *spram2 = (UINT16*)DrvSprCGRAM1; + + while (offs < 0x0400 && (spram[offs] & 0x4000) == 0) + { + INT32 attr_start; + INT32 map_start; + INT32 ox,oy,x,y,xsize,ysize,zoomx,zoomy,flipx,flipy,color; + + attr_start = 4 * (spram[offs++] & 0x01ff); + + oy = spram[attr_start + 0] & 0x01ff; + ysize = (spram[attr_start + 0] & 0x0e00) >> 9; + zoomy = (spram[attr_start + 0] & 0xf000) >> 12; + ox = spram[attr_start + 1] & 0x01ff; + xsize = (spram[attr_start + 1] & 0x0e00) >> 9; + zoomx = (spram[attr_start + 1] & 0xf000) >> 12; + flipx = spram[attr_start + 2] & 0x4000; + flipy = spram[attr_start + 2] & 0x8000; + color = (spram[attr_start + 2] & 0x1f00) >> 8; + map_start = spram[attr_start + 3] & 0x7fff; + + zoomx = 32 - zoomx; + zoomy = 32 - zoomy; + + if (spram[attr_start + 2] & 0x20ff) color = GetCurrentFrame() & 0x0f; // good enough? + + for (y = 0;y <= ysize;y++) + { + INT32 sx,sy; + + if (flipy) sy = ((oy + zoomy * (ysize - y)/2 + 16) & 0x1ff) - 16; + else sy = ((oy + zoomy * y / 2 + 16) & 0x1ff) - 16; + + for (x = 0;x <= xsize;x++) + { + INT32 code; + + if (flipx) sx = ((ox + zoomx * (xsize - x) / 2 + 16) & 0x1ff) - 16; + else sx = ((ox + zoomx * x / 2 + 16) & 0x1ff) - 16; + + code = spram2[map_start & 0x3fff] & 0x3fff; + map_start++; + + if (*flipscreen) { + flipx = !flipx; + flipy = !flipy; + sx = 304-sx; + sy = 208-sy; + } + + draw_16x16_zoom(DrvGfxROM1, code, color | 0x20, sx, sy, 16, 16, flipx, flipy); + } + } + } +} + +static void predraw_roz_tile(INT32 offset) +{ + UINT16 data = *((UINT16*)(DrvRozVidRAM + offset)); + + offset >>= 1; + + INT32 sx = (offset & 0x3f) << 4; + INT32 sy = (offset >> 6) << 4; + + UINT16 *dst = DrvBgTmp + (sy * 1024) + sx; + + INT32 code = (data & 0x7ff) | (*roz_bank << 11); + INT32 color = ((data >> 12) << 4) | ((nScreenStartY) ? 0x300 : 0x100); + UINT8 *src = DrvGfxROM3 + (code << 8); + + for (INT32 y = 0; y < 16; y++) { + for (INT32 x = 0; x < 16; x++) { + dst[x] = src[x] | color; + if (src[x] == 0x0f) dst[x] |= 0x8000; + } + dst += 1024; + src += 16; + } +} + +static void predraw_background() +{ + UINT16 *ptr = (UINT16*)DrvRozVidRAM; + for (INT32 i = 0; i < 0x2000; i+=2, ptr++) { + if (DrvBgDirty[i/2] || DrvBgTileDirty[*ptr & 0x7ff]) { + predraw_roz_tile(i); + DrvBgDirty[i/2] = 0; + } + } + + memset (DrvBgTileDirty, 0, 0x800); +} + +static inline void copy_roz(UINT32 startx, UINT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, INT32 transp) +{ + UINT16 *dst = pTransDraw; + UINT16 *src = DrvBgTmp; + + for (INT32 sy = 0; sy < nScreenHeight; sy++, startx+=incyx, starty+=incyy) + { + UINT32 cx = startx; + UINT32 cy = starty; + + if (transp) { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) + { + INT32 pxl = src[(((cy >> 16) & 0x3ff) << 10) + ((cx >> 16) & 0x3ff)]; + + if (!(pxl & 0x8000)) { + *dst = pxl; + } + } + } else { + for (INT32 x = 0; x < nScreenWidth; x++, cx+=incxx, cy+=incxy, dst++) { + *dst = src[(((cy >> 16) & 0x3ff) << 10) + ((cx >> 16) & 0x3ff)] & 0x3ff; + } + } + } +} + +static void draw_background(INT32 transp) +{ + UINT16 *ctrl = DrvBgCtrl; + + UINT32 startx,starty; + INT32 incxx,incxy,incyx,incyy; + + startx = 256 * (INT16)(ctrl[0x00]); + starty = 256 * (INT16)(ctrl[0x01]); + incyx = (INT16)(ctrl[0x02]); + incyy = (INT16)(ctrl[0x03]); + incxx = (INT16)(ctrl[0x04]); + incxy = (INT16)(ctrl[0x05]); + + if (ctrl[0x06] & 0x4000) { incyx *= 256; incyy *= 256; } + if (ctrl[0x06] & 0x0040) { incxx *= 256; incxy *= 256; } + + if (nScreenStartY) { + startx -= -10 * incyx; + starty -= -10 * incyy; + startx -= -58 * incxx; + starty -= -58 * incxy; + } else { + startx -= -21 * incyx; + starty -= -21 * incyy; + startx -= -48 * incxx; + starty -= -48 * incxy; + } + + copy_roz(startx << 5, starty << 5, incxx << 5, incxy << 5, incyx << 5, incyy << 5, transp); +} + +static void recalculate_palette() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x400; i++) { + r = (p[i] >> 10) & 0x1f; + g = (p[i] >> 5) & 0x1f; + b = (p[i] >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + DrvPalette[0x400] = 0; + } +} + +static INT32 F1gpDraw() +{ + recalculate_palette(); + predraw_background(); + draw_background(0); + + if (*gfxctrl == 0x00) { + if (nBurnLayer & 2) f1gp_draw_sprites(DrvSprVRAM2, DrvSprCGRAM2, DrvGfxROM2, 0x20); + if (nBurnLayer & 1) f1gp_draw_sprites(DrvSprVRAM1, DrvSprCGRAM1, DrvGfxROM1, 0x10); + if (nBurnLayer & 4) draw_foreground(1); + } else { + if (nBurnLayer & 2) f1gp_draw_sprites(DrvSprVRAM2, DrvSprCGRAM2, DrvGfxROM2, 0x20); + if (nBurnLayer & 4) draw_foreground(1); + if (nBurnLayer & 1) f1gp_draw_sprites(DrvSprVRAM1, DrvSprCGRAM1, DrvGfxROM1, 0x10); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 F1gp2Draw() +{ + recalculate_palette(); + predraw_background(); + + if (!(*gfxctrl & 4)) { + switch (*gfxctrl & 3) + { + case 0: + if (nBurnLayer & 1) draw_background(0); + if (nBurnLayer & 4) f1gp2_draw_sprites(); + if (nBurnLayer & 2) draw_foreground(1); + break; + + case 1: + if (nBurnLayer & 1) draw_background(0); + if (nBurnLayer & 2) draw_foreground(1); + if (nBurnLayer & 4) f1gp2_draw_sprites(); + break; + + case 2: + if (nBurnLayer & 2) draw_foreground(0); + if (nBurnLayer & 1) draw_background(1); + if (nBurnLayer & 4) f1gp2_draw_sprites(); + break; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 F1gpbDraw() +{ + recalculate_palette(); + BurnTransferClear(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + DrvInputs[0] = 0xffff; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[3] = { 10000000 / 60, 10000000 / 60, 5000000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCycleSegment = ((nCyclesTotal[0] / nInterleave) * (i+1)) - nCyclesDone[0]; + + SekOpen(0); + nCyclesDone[0] += SekRun(nCycleSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + + SekOpen(1); + nCyclesDone[1] += SekRun(nCycleSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + BurnTimerEndFrame(nCyclesTotal[2]); + + if (pBurnSoundOut) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + if (nScreenStartY) { + for (INT32 i = 0; i < 0x40000; i+=2) { + expand_dynamic_tiles(i); + } + } + + ZetOpen(0); + sound_bankswitch(*DrvZ80Bank); + ZetClose(); + } + + return 0; +} + + +// F-1 Grand Prix + +static struct BurnRomInfo f1gpRomDesc[] = { + { "rom1-a.3", 0x020000, 0x2d8f785b, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "rom11-a.2", 0x040000, 0x53df8ea1, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rom10-a.1", 0x040000, 0x46a289fb, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rom13-a.4", 0x040000, 0x7d92e1fa, 1 | BRF_PRG | BRF_ESS }, // 3 + { "rom12-a.3", 0x040000, 0xd8c1bcf4, 1 | BRF_PRG | BRF_ESS }, // 4 + { "rom6-a.6", 0x040000, 0x6d947a3f, 1 | BRF_PRG | BRF_ESS }, // 5 + { "rom7-a.5", 0x040000, 0x7a014ba6, 1 | BRF_PRG | BRF_ESS }, // 6 + { "rom9-a.8", 0x040000, 0x49286572, 1 | BRF_PRG | BRF_ESS }, // 7 + { "rom8-a.7", 0x040000, 0x0ed783c7, 1 | BRF_PRG | BRF_ESS }, // 8 + { "rom2-a.06", 0x100000, 0x747dd112, 1 | BRF_PRG | BRF_ESS }, // 9 + { "rom3-a.05", 0x100000, 0x264aed13, 1 | BRF_PRG | BRF_ESS }, // 10 + + { "rom4-a.4", 0x020000, 0x8e811d36, 2 | BRF_PRG | BRF_ESS }, // 11 68K #1 Code + + { "rom5-a.8", 0x020000, 0x9ea36e35, 3 | BRF_PRG | BRF_ESS }, // 12 Z80 Code + + { "rom3-b.07", 0x100000, 0xffb1d489, 4 | BRF_GRA }, // 13 Character Tiles + { "rom2-b.04", 0x100000, 0xd1b3471f, 4 | BRF_GRA }, // 14 + + { "rom5-b.2", 0x080000, 0x17572b36, 5 | BRF_GRA }, // 15 Sprite Bank 0 + { "rom4-b.3", 0x080000, 0x72d12129, 5 | BRF_GRA }, // 16 + + { "rom7-b.17", 0x040000, 0x2aed9003, 6 | BRF_GRA }, // 17 Sprite Bank 1 + { "rom6-b.16", 0x040000, 0x6789ef12, 6 | BRF_GRA }, // 18 + + { "rom14-a.09", 0x100000, 0xb4c1ac31, 7 | BRF_SND }, // 19 YM2610 Samples + { "rom17-a.08", 0x100000, 0xea70303d, 7 | BRF_SND }, // 20 +}; + +STD_ROM_PICK(f1gp) +STD_ROM_FN(f1gp) + +static INT32 F1gpInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvF1gp = { + "f1gp", NULL, NULL, NULL, "1991", + "F-1 Grand Prix\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, f1gpRomInfo, f1gpRomName, NULL, NULL, F1gpInputInfo, F1gpDIPInfo, + F1gpInit, DrvExit, DrvFrame, F1gpDraw, DrvScan, &DrvRecalc, 0x401, + 240, 320, 3, 4 +}; + + +// F-1 Grand Prix (Playmark bootleg) + +static struct BurnRomInfo f1gpbRomDesc[] = { + { "1.ic38", 0x020000, 0x046dd83a, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 code + { "7.ic39", 0x020000, 0x960f5db4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "2.ic48", 0x080000, 0xb3b315c3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "8.ic41", 0x080000, 0x39af8180, 1 | BRF_PRG | BRF_ESS }, // 3 + { "3.ic165", 0x080000, 0xb7295a30, 1 | BRF_PRG | BRF_ESS }, // 4 + { "9.ic166", 0x080000, 0xbb596d5b, 1 | BRF_PRG | BRF_ESS }, // 5 + { "4.ic42", 0x080000, 0x5dbde98a, 1 | BRF_PRG | BRF_ESS }, // 6 + { "10.ic43", 0x080000, 0xd60e7706, 1 | BRF_PRG | BRF_ESS }, // 7 + { "5.ic167", 0x080000, 0x48c36293, 1 | BRF_PRG | BRF_ESS }, // 8 + { "11.ic168", 0x080000, 0x92a28e52, 1 | BRF_PRG | BRF_ESS }, // 9 + + { "16.u7", 0x010000, 0x7609d818, 2 | BRF_PRG | BRF_ESS }, // 10 68K #1 Code + { "17.u6", 0x010000, 0x951befde, 2 | BRF_PRG | BRF_ESS }, // 11 + + { "13.ic151", 0x080000, 0x4238074b, 3 | BRF_GRA }, // 12 Character Tiles + { "12.ic152", 0x080000, 0xe97c2b6e, 3 | BRF_GRA }, // 13 + { "15.ic153", 0x080000, 0xc2867d7f, 3 | BRF_GRA }, // 14 + { "14.ic154", 0x080000, 0x0cd20423, 3 | BRF_GRA }, // 15 + + { "rom21", 0x080000, 0x7a08c3b7, 4 | BRF_GRA }, // 16 Sprite Banks + { "rom20", 0x080000, 0xbd1273d0, 4 | BRF_GRA }, // 17 + { "19.ic141", 0x080000, 0xaa4ebdfe, 4 | BRF_GRA }, // 18 + { "18.ic140", 0x080000, 0x9b2a4325, 4 | BRF_GRA }, // 19 + + { "6.ic13", 0x080000, 0x6e83ffd8, 5 | BRF_SND }, // 20 OKI MSM6295 Samples +}; + +STD_ROM_PICK(f1gpb) +STD_ROM_FN(f1gpb) + +static INT32 F1gpbInit() +{ + return 1; +} + +struct BurnDriverD BurnDrvF1gpb = { + "f1gpb", "f1gp", NULL, NULL, "1991", + "F-1 Grand Prix (Playmark bootleg)\0", NULL, "[Video System Co.] (Playmark bootleg)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 1, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, f1gpbRomInfo, f1gpbRomName, NULL, NULL, F1gpInputInfo, F1gpDIPInfo, + F1gpbInit, DrvExit, DrvFrame, F1gpbDraw, DrvScan, &DrvRecalc, 0x401, + 240, 320, 3, 4 +}; + + +// F-1 Grand Prix Part II + +static struct BurnRomInfo f1gp2RomDesc[] = { + { "rom12.v1", 0x020000, 0xc5c5f199, 1 | BRF_PRG | BRF_ESS }, // 0 68K #0 Code + { "rom14.v2", 0x020000, 0xdd5388e2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rom2", 0x200000, 0x3b0cfa82, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "rom13.v3", 0x020000, 0xc37aa303, 2 | BRF_PRG | BRF_ESS }, // 3 68K #1 Code + + { "rom5.v4", 0x020000, 0x6a9398a1, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "rom1", 0x200000, 0xf2d55ad7, 4 | BRF_GRA }, // 5 Character Tiles + + { "rom15", 0x200000, 0x1ac03e2e, 5 | BRF_GRA }, // 6 Sprites + + { "rom11", 0x100000, 0xb22a2c1f, 6 | BRF_GRA }, // 7 Background Tiles + { "rom10", 0x100000, 0x43fcbe23, 6 | BRF_GRA }, // 8 + { "rom9", 0x100000, 0x1bede8a1, 6 | BRF_GRA }, // 9 + { "rom8", 0x100000, 0x98baf2a1, 6 | BRF_GRA }, // 10 + + { "rom4", 0x080000, 0xc2d3d7ad, 7 | BRF_SND }, // 11 YM2610 Samples + { "rom3", 0x100000, 0x7f8f066f, 7 | BRF_SND }, // 12 +}; + +STD_ROM_PICK(f1gp2) +STD_ROM_FN(f1gp2) + +static INT32 F1gp2Init() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvF1gp2 = { + "f1gp2", NULL, NULL, NULL, "1992", + "F-1 Grand Prix Part II\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, f1gp2RomInfo, f1gp2RomName, NULL, NULL, F1gp2InputInfo, F1gp2DIPInfo, + F1gp2Init, DrvExit, DrvFrame, F1gp2Draw, DrvScan, &DrvRecalc, 0x401, + 224, 320, 3, 4 +}; + diff --git a/src/burn/drivers/misc_post90s/d_fstarfrc.cpp b/src/burn/drivers/misc_post90s/d_fstarfrc.cpp new file mode 100644 index 00000000..4eb5eec6 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_fstarfrc.cpp @@ -0,0 +1,1286 @@ +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym2151.h" + +static UINT8 FstarfrcInputPort0[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 FstarfrcInputPort1[6] = {0, 0, 0, 0, 0, 0}; +static UINT8 FstarfrcDip[2] = {0, 0}; +static UINT16 FstarfrcInput[2] = {0x00, 0x00}; +static UINT8 FstarfrcReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *FstarfrcRom = NULL; +static UINT8 *FstarfrcZ80Rom = NULL; +static UINT8 *FstarfrcRam = NULL; +static UINT8 *FstarfrcCharRam = NULL; +static UINT8 *FstarfrcVideoRam = NULL; +static UINT8 *FstarfrcColourRam = NULL; +static UINT8 *FstarfrcVideo2Ram = NULL; +static UINT8 *FstarfrcColour2Ram = NULL; +static UINT8 *FstarfrcSpriteRam = NULL; +static UINT8 *FstarfrcPaletteRam = NULL; +static UINT8 *FstarfrcZ80Ram = NULL; +static UINT32 *FstarfrcPalette = NULL; +static UINT8 *FstarfrcCharTiles = NULL; +static UINT8 *FstarfrcLayerTiles = NULL; +static UINT8 *FstarfrcSpriteTiles = NULL; +static UINT8 *FstarfrcTempGfx = NULL; + +static INT32 CharScrollX; +static INT32 CharScrollY; +static INT32 Scroll1X; +static INT32 Scroll1Y; +static INT32 Scroll2X; +static INT32 Scroll2Y; + +static INT32 Ginkun = 0; +static INT32 Riot = 0; + +static INT32 FstarfrcSoundLatch; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo FstarfrcInputList[] = { + {"Coin 1" , BIT_DIGITAL , FstarfrcInputPort0 + 14, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , FstarfrcInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , FstarfrcInputPort0 + 15, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , FstarfrcInputPort0 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , FstarfrcInputPort0 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , FstarfrcInputPort0 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , FstarfrcInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , FstarfrcInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , FstarfrcInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , FstarfrcInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , FstarfrcInputPort0 + 11, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , FstarfrcInputPort0 + 10, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , FstarfrcInputPort0 + 9, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , FstarfrcInputPort0 + 8, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , FstarfrcInputPort0 + 12, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , FstarfrcInputPort0 + 13, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &FstarfrcReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, FstarfrcDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, FstarfrcDip + 1 , "dip" }, +}; + +STDINPUTINFO(Fstarfrc) + +static struct BurnInputInfo RiotInputList[] = { + {"Coin 1" , BIT_DIGITAL , FstarfrcInputPort0 + 14, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , FstarfrcInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , FstarfrcInputPort0 + 15, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , FstarfrcInputPort0 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , FstarfrcInputPort0 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , FstarfrcInputPort0 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , FstarfrcInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , FstarfrcInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , FstarfrcInputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , FstarfrcInputPort0 + 4, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , FstarfrcInputPort0 + 5, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , FstarfrcInputPort0 + 11, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , FstarfrcInputPort0 + 10, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , FstarfrcInputPort0 + 9, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , FstarfrcInputPort0 + 8, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , FstarfrcInputPort1 + 5, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , FstarfrcInputPort0 + 12, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , FstarfrcInputPort0 + 13, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &FstarfrcReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, FstarfrcDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, FstarfrcDip + 1 , "dip" }, +}; + +STDINPUTINFO(Riot) + +inline void FstarfrcMakeInputs() +{ + // Reset Inputs + FstarfrcInput[0] = FstarfrcInput[1] = 0x3fff; + + // Compile Digital Inputs + for (INT32 i = 0; i < 14; i++) { + FstarfrcInput[0] -= (FstarfrcInputPort0[i] & 1) << i; + } + + for (INT32 i = 14; i < 16; i++) { + FstarfrcInput[0] |= (FstarfrcInputPort0[i] & 1) << i; + } + + for (INT32 i = 0; i < 6; i++) { + FstarfrcInput[1] -= (FstarfrcInputPort1[i] & 1) << i; + } +} + +static struct BurnDIPInfo FstarfrcDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin SW 1" }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x03, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin SW 2" }, + {0x11, 0x01, 0x0c, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x04, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Screen Reverse" }, + {0x11, 0x01, 0x10, 0x10, "Off" }, + {0x11, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demonstration Sound" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Continue Play" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "The Number of Player" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Level Up Speed" }, + {0x12, 0x01, 0x30, 0x00, "Slowest" }, + {0x12, 0x01, 0x30, 0x10, "Slow" }, + {0x12, 0x01, 0x30, 0x30, "Fast" }, + {0x12, 0x01, 0x30, 0x20, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0xc0, 0xc0, "200,000, 1,000,000" }, + {0x12, 0x01, 0xc0, 0x80, "220,000, 1,200,000" }, + {0x12, 0x01, 0xc0, 0x40, "240,000, 1,400,000" }, + {0x12, 0x01, 0xc0, 0x00, "Every 500,000, Once at Highest Score"}, +}; + +STDDIPINFO(Fstarfrc) + +static struct BurnDIPInfo GinkunDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin SW 1" }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x03, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin SW 2" }, + {0x11, 0x01, 0x0c, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x04, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Continue Plus 1up" }, + {0x11, 0x01, 0x10, 0x10, "Off" }, + {0x11, 0x01, 0x10, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, +}; + +STDDIPINFO(Ginkun) + +static struct BurnDIPInfo RiotDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x07, 0x01, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x07, 0x02, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x07, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x38, 0x30, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x28, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x38, 0x18, "4 Coins 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Starting Coins" }, + {0x13, 0x01, 0x40, 0x40, "1" }, + {0x13, 0x01, 0x40, 0x00, "2" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x03, "1" }, + {0x14, 0x01, 0x03, 0x02, "2" }, + {0x14, 0x01, 0x03, 0x01, "3" }, + {0x14, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, +}; + +STDDIPINFO(Riot) + +static struct BurnRomInfo FstarfrcRomDesc[] = { + { "fstarf01.rom", 0x40000, 0x94c71de6, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "fstarf02.rom", 0x40000, 0xb1a07761, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "fstarf03.rom", 0x20000, 0x54375335, BRF_GRA }, // 2 + { "fstarf05.rom", 0x80000, 0x77a281e7, BRF_GRA }, // 3 + { "fstarf04.rom", 0x80000, 0x398a920d, BRF_GRA }, // 4 + { "fstarf09.rom", 0x80000, 0xd51341d2, BRF_GRA }, // 5 + { "fstarf06.rom", 0x80000, 0x07e40e87, BRF_GRA }, // 6 + + { "fstarf07.rom", 0x10000, 0xe0ad5de1, BRF_PRG | BRF_SND }, // 7 Z80 Program Code + + { "fstarf08.rom", 0x20000, 0xf0ad5693, BRF_SND }, // 8 Samples +}; + + +STD_ROM_PICK(Fstarfrc) +STD_ROM_FN(Fstarfrc) + + +static struct BurnRomInfo FstarfrcjRomDesc[] = { + { "1.bin", 0x40000, 0x1905d85d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "2.bin", 0x40000, 0xde9cfc39, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "fstarf03.rom", 0x20000, 0x54375335, BRF_GRA }, // 2 + { "fstarf05.rom", 0x80000, 0x77a281e7, BRF_GRA }, // 3 + { "fstarf04.rom", 0x80000, 0x398a920d, BRF_GRA }, // 4 + { "fstarf09.rom", 0x80000, 0xd51341d2, BRF_GRA }, // 5 + { "fstarf06.rom", 0x80000, 0x07e40e87, BRF_GRA }, // 6 + + { "fstarf07.rom", 0x10000, 0xe0ad5de1, BRF_PRG | BRF_SND }, // 7 Z80 Program Code + + { "fstarf08.rom", 0x20000, 0xf0ad5693, BRF_SND }, // 8 Samples +}; + + +STD_ROM_PICK(Fstarfrcj) +STD_ROM_FN(Fstarfrcj) + +static struct BurnRomInfo GinkunRomDesc[] = { + { "ginkun01.i01", 0x40000, 0x98946fd5, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ginkun02.i02", 0x40000, 0xe98757f6, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ginkun03.i03", 0x20000, 0x4456e0df, BRF_GRA }, // 2 + { "ginkun05.i09", 0x80000, 0x1263bd42, BRF_GRA }, // 3 + { "ginkun04.i05", 0x80000, 0x9e4cf611, BRF_GRA }, // 4 + { "ginkun09.i22", 0x80000, 0x233384b9, BRF_GRA }, // 5 + { "ginkun06.i16", 0x80000, 0xf8589184, BRF_GRA }, // 6 + + { "ginkun07.i17", 0x10000, 0x8836b1aa, BRF_PRG | BRF_SND }, // 7 Z80 Program Code + + { "ginkun08.i18", 0x20000, 0x8b7583c7, BRF_SND }, // 8 Samples +}; + + +STD_ROM_PICK(Ginkun) +STD_ROM_FN(Ginkun) + +static struct BurnRomInfo RiotRomDesc[] = { + { "1.ic1", 0x40000, 0x9ef4232e, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "2.ic2", 0x40000, 0xf2c6fbbf, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "3.ic3", 0x20000, 0xf60f5c96, BRF_GRA }, // 2 + { "5.ic9", 0x80000, 0x056fce78, BRF_GRA }, // 3 + { "4.ic5", 0x80000, 0x0894e7b4, BRF_GRA }, // 4 + { "9.ic22", 0x80000, 0x0ead54f3, BRF_GRA }, // 5 + { "6.ic16", 0x80000, 0x96ef61da, BRF_GRA }, // 6 + + { "7.ic17", 0x10000, 0x0a95b8f3, BRF_PRG | BRF_SND }, // 7 Z80 Program Code + + { "8.ic18", 0x20000, 0x4b70e266, BRF_SND }, // 8 Samples +}; + + +STD_ROM_PICK(Riot) +STD_ROM_FN(Riot) + +INT32 FstarfrcDoReset() +{ + CharScrollX = CharScrollY = Scroll1X = Scroll1Y = Scroll2X = Scroll2Y = 0; + + FstarfrcSoundLatch = 0; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +void FstarfrcYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0 , ZET_IRQSTATUS_NONE); + } +} + +UINT16 __fastcall FstarfrcReadWord(UINT32 a) +{ + switch (a) { + case 0x150030: { + SEK_DEF_READ_WORD(0, a); + } + + case 0x150040: { + SEK_DEF_READ_WORD(0, a); + } + + case 0x150050: { + return FstarfrcInput[0]; + } + } + + return 0; +} + +UINT8 __fastcall FstarfrcReadByte(UINT32 a) +{ + switch (a) { + case 0x150030: + case 0x150031: { + return FstarfrcDip[1]; + } + case 0x150040: + case 0x150041: { + return FstarfrcDip[0]; + } + } + + return 0; +} + +void __fastcall FstarfrcWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x150010: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0x160000: { + CharScrollX = d; + return; + } + + case 0x16000c: { + Scroll1X = d; + return; + } + + case 0x160012: { + Scroll1Y = d; + return; + } + + case 0x160018: { + Scroll2X = d; + return; + } + + case 0x16001e: { + Scroll2Y = d; + return; + } + } +} + +void __fastcall FstarfrcWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x150011: { + FstarfrcSoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + } +} + +UINT16 __fastcall GinkunReadWord(UINT32 a) +{ + switch (a) { + case 0x150020: { + return FstarfrcInput[1]; + } + + case 0x150030: { + SEK_DEF_READ_WORD(0, a); + } + + case 0x150040: { + SEK_DEF_READ_WORD(0, a); + } + + case 0x150050: { + return FstarfrcInput[0]; + } + } + +// bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); + + return 0; +} + +UINT8 __fastcall GinkunReadByte(UINT32 a) +{ + switch (a) { + case 0x150030: + case 0x150031: { + return FstarfrcDip[1]; + } + case 0x150040: + case 0x150041: { + return FstarfrcDip[0]; + } + } + + +// bprintf(PRINT_NORMAL, _T("Read Byte -> %06X\n"), a); + + return 0; +} + +void __fastcall GinkunWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { +// case 0x150010: { +// SEK_DEF_WRITE_WORD(0, a, d); +// return; +// } + + case 0x150066: { + return; + } + + case 0x16002e: { + return; + } + + case 0x160000: { + CharScrollX = d; + return; + } + + case 0x160006: { + CharScrollY = d; + return; + } + + case 0x16000c: { + Scroll1X = d; + return; + } + + case 0x160012: { + Scroll1Y = d; + return; + } + + case 0x160018: { + Scroll2X = d; + return; + } + + case 0x16001e: { + Scroll2Y = d; + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Write Word -> %06X, %04X\n"), a, d); +} + +void __fastcall GinkunWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x150001: { + return; // Flipscreen + } + + case 0x150021: { + return; // NOP + } + + case 0x150031: { + return; // NOP + } + + case 0x150011: { + FstarfrcSoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Write Byte -> %06X, %02X\n"), a, d); +} + +UINT8 __fastcall FstarfrcZ80Read(UINT16 a) +{ + switch (a) { + case 0xfc00: { + return MSM6295ReadStatus(0); + } + + case 0xfc05: { + return BurnYM2151ReadStatus(); + } + + case 0xfc08: { + return FstarfrcSoundLatch; + } + } + + return 0; +} + +void __fastcall FstarfrcZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfc00: { + MSM6295Command(0, d); + return; + } + + case 0xfc04: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xfc05: { + BurnYM2151WriteRegister(d); + return; + } + } +} + +static INT32 FstarfrcMemIndex() +{ + UINT8 *Next; Next = Mem; + + FstarfrcRom = Next; Next += 0x80000; + FstarfrcZ80Rom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x20000; + + RamStart = Next; + + if (Ginkun || Riot) { + FstarfrcRam = Next; Next += 0x05000; + FstarfrcCharRam = Next; Next += 0x01000; + FstarfrcVideoRam = Next; Next += 0x01000; + FstarfrcColourRam = Next; Next += 0x01000; + FstarfrcVideo2Ram = Next; Next += 0x01000; + FstarfrcColour2Ram = Next; Next += 0x01000; + } else { + FstarfrcRam = Next; Next += 0x0a000; + FstarfrcCharRam = Next; Next += 0x01000; + FstarfrcVideoRam = Next; Next += 0x00800; + FstarfrcColourRam = Next; Next += 0x00800; + FstarfrcVideo2Ram = Next; Next += 0x00800; + FstarfrcColour2Ram = Next; Next += 0x00800; + } + FstarfrcSpriteRam = Next; Next += 0x01000; + FstarfrcPaletteRam = Next; Next += 0x02000; + FstarfrcZ80Ram = Next; Next += 0x0c002; + + RamEnd = Next; + + FstarfrcCharTiles = Next; Next += (4096 * 8 * 8); + FstarfrcLayerTiles = Next; Next += (8192 * 16 * 16); + FstarfrcSpriteTiles = Next; Next += (32768 * 8 * 8); + FstarfrcPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; +static INT32 TileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + + +INT32 FstarfrcInit() +{ + INT32 nRet = 0, nLen; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ginkun")) Ginkun = 1; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "riot")) Riot = 1; + + // Allocate and Blank all required memory + Mem = NULL; + FstarfrcMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + FstarfrcMemIndex(); + + FstarfrcTempGfx = (UINT8*)BurnMalloc(0x100000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(FstarfrcRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(FstarfrcRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and decode Char Tiles rom + memset(FstarfrcTempGfx, 0, 0x100000); + nRet = BurnLoadRom(FstarfrcTempGfx, 2, 1); if (nRet != 0) return 1; + GfxDecode(4096, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, FstarfrcTempGfx, FstarfrcCharTiles); + + // Load, byteswap and decode Bg and Fg Layer roms + memset(FstarfrcTempGfx, 0, 0x100000); + nRet = BurnLoadRom(FstarfrcTempGfx + 0x000000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(FstarfrcTempGfx + 0x000001, 4, 2); if (nRet != 0) return 1; + GfxDecode(8192, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, FstarfrcTempGfx, FstarfrcLayerTiles); + + // Load, byteswap and decode Sprite Tile roms + memset(FstarfrcTempGfx, 0, 0x100000); + nRet = BurnLoadRom(FstarfrcTempGfx + 0x000000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(FstarfrcTempGfx + 0x000001, 6, 2); if (nRet != 0) return 1; + GfxDecode(32768, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, FstarfrcTempGfx, FstarfrcSpriteTiles); + + BurnFree(FstarfrcTempGfx); + + // Load Z80 Program rom + nRet = BurnLoadRom(FstarfrcZ80Rom, 7, 1); if (nRet != 0) return 1; + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 8, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + if (!strncmp(BurnDrvGetTextA(DRV_NAME), "fstarfrc", 8)) { + SekMapMemory(FstarfrcRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(FstarfrcRam , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(FstarfrcCharRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(FstarfrcVideoRam , 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(FstarfrcColourRam , 0x120800, 0x120fff, SM_RAM); + SekMapMemory(FstarfrcVideo2Ram , 0x121000, 0x1217ff, SM_RAM); + SekMapMemory(FstarfrcColour2Ram , 0x121800, 0x121fff, SM_RAM); + SekMapMemory(FstarfrcRam + 0x4000, 0x122000, 0x127fff, SM_RAM); + SekMapMemory(FstarfrcSpriteRam , 0x130000, 0x130fff, SM_RAM); + SekMapMemory(FstarfrcPaletteRam , 0x140000, 0x141fff, SM_RAM); + SekSetReadWordHandler(0, FstarfrcReadWord); + SekSetWriteWordHandler(0, FstarfrcWriteWord); + SekSetReadByteHandler(0, FstarfrcReadByte); + SekSetWriteByteHandler(0, FstarfrcWriteByte); + } else { + SekMapMemory(FstarfrcRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(FstarfrcRam , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(FstarfrcCharRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(FstarfrcVideoRam , 0x120000, 0x120fff, SM_RAM); + SekMapMemory(FstarfrcColourRam , 0x121000, 0x121fff, SM_RAM); + SekMapMemory(FstarfrcVideo2Ram , 0x122000, 0x122fff, SM_RAM); + SekMapMemory(FstarfrcColour2Ram , 0x123000, 0x123fff, SM_RAM); + SekMapMemory(FstarfrcRam + 0x4000, 0x124000, 0x124fff, SM_RAM); + SekMapMemory(FstarfrcSpriteRam , 0x130000, 0x130fff, SM_RAM); + SekMapMemory(FstarfrcPaletteRam , 0x140000, 0x141fff, SM_RAM); + SekSetReadWordHandler(0, GinkunReadWord); + SekSetWriteWordHandler(0, GinkunWriteWord); + SekSetReadByteHandler(0, GinkunReadByte); + SekSetWriteByteHandler(0, GinkunWriteByte); + } + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, FstarfrcZ80Rom ); + ZetMapArea(0x0000, 0xefff, 2, FstarfrcZ80Rom ); + ZetMapArea(0xf000, 0xfbff, 0, FstarfrcZ80Ram ); + ZetMapArea(0xf000, 0xfbff, 1, FstarfrcZ80Ram ); + ZetMapArea(0xf000, 0xfbff, 2, FstarfrcZ80Ram ); + ZetMapArea(0xfffe, 0xffff, 0, FstarfrcZ80Ram + 0xc000); + ZetMapArea(0xfffe, 0xffff, 1, FstarfrcZ80Ram + 0xc000); + ZetMapArea(0xfffe, 0xffff, 2, FstarfrcZ80Ram + 0xc000); + ZetMemEnd(); + ZetSetReadHandler(FstarfrcZ80Read); + ZetSetWriteHandler(FstarfrcZ80Write); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(8000000 / 2, 50.0); + BurnYM2151SetIrqHandler(&FstarfrcYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 7575, 40, 1); + + GenericTilesInit(); + + // Reset the driver + FstarfrcDoReset(); + + return 0; +} + +INT32 FstarfrcExit() +{ + BurnYM2151Exit(); + MSM6295Exit(0); + + SekExit(); + ZetExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + Ginkun = 0; + Riot = 0; + + return 0; +} + +void GinkunRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = ((FstarfrcVideo2Ram[TileIndex + 1] << 8) | FstarfrcVideo2Ram[TileIndex + 0]) & 0x1fff; + Colour = (((FstarfrcColour2Ram[TileIndex + 1] << 8) | FstarfrcColour2Ram[TileIndex + 0]) & 0x0f); + + x = 16 * mx; + y = 16 * my; + + x -= Scroll2X; + y -= Scroll2Y; + + x &= 0x1ff; + y &= 0x1ff; + + if (x >= 496) x -= 512; + if (y >= 496) y -= 512; + + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512 + (0x10 << 4), FstarfrcLayerTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512 + (0x10 << 4), FstarfrcLayerTiles); + } + + TileIndex += 2; + } + } +} + +void FstarfrcRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = ((FstarfrcVideo2Ram[TileIndex + 1] << 8) | FstarfrcVideo2Ram[TileIndex + 0]) & 0x1fff; + Colour = (((FstarfrcColour2Ram[TileIndex + 1] << 8) | FstarfrcColour2Ram[TileIndex + 0]) & 0x0f); + + x = 16 * mx; + y = 16 * my; + + x -= Scroll2X; + y -= Scroll2Y; + + x &= 0x1ff; + y &= 0x1ff; + + if (x >= 496) x -= 512; + if (y >= 496) y -= 512; + + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512 + (0x10 << 4), FstarfrcLayerTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512 + (0x10 << 4), FstarfrcLayerTiles); + } + + TileIndex += 2; + } + } +} + +void GinkunRenderFgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = ((FstarfrcVideoRam[TileIndex + 1] << 8) | FstarfrcVideoRam[TileIndex + 0]) & 0x1fff; + Colour = ((FstarfrcColourRam[TileIndex + 1] << 8) | FstarfrcColourRam[TileIndex + 0]) & 0x0f; + + x = 16 * mx; + y = 16 * my; + + x -= Scroll1X; + y -= Scroll1Y; + + x &= 0x1ff; + y &= 0x1ff; + + if (x >= 496) x -= 512; + if (y >= 496) y -= 512; + + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512, FstarfrcLayerTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512, FstarfrcLayerTiles); + } + + TileIndex += 2 ; + } + } +} + +void FstarfrcRenderFgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = ((FstarfrcVideoRam[TileIndex + 1] << 8) | FstarfrcVideoRam[TileIndex + 0]) & 0x1fff; + Colour = ((FstarfrcColourRam[TileIndex + 1] << 8) | FstarfrcColourRam[TileIndex + 0]) & 0x0f; + + x = 16 * mx; + y = 16 * my; + + x -= Scroll1X; + y -= Scroll1Y; + + x &= 0x1ff; + y &= 0x1ff; + + if (x >= 496) x -= 512; + if (y >= 496) y -= 512; + + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512, FstarfrcLayerTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512, FstarfrcLayerTiles); + } + + TileIndex += 2 ; + } + } +} + +void FstarfrcRenderTextLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = (FstarfrcCharRam[TileIndex + 1] << 8) | FstarfrcCharRam[TileIndex + 0]; + Colour = Code >> 12; + Code &= 0x0fff; + + x = 8 * mx; + y = 8 * my; + + x -= CharScrollX; + y -= CharScrollY; + + x &= 0x1ff; + y &= 0x0ff; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, FstarfrcCharTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, FstarfrcCharTiles); + } + + TileIndex += 2 ; + } + } +} + +static void draw_sprites(INT32 layerpriority) +{ + UINT16* pFstarfrcSpriteRam = ((UINT16*)FstarfrcSpriteRam); + + + INT32 offs; + const UINT8 layout[8][8] = + { + {0,1,4,5,16,17,20,21}, + {2,3,6,7,18,19,22,23}, + {8,9,12,13,24,25,28,29}, + {10,11,14,15,26,27,30,31}, + {32,33,36,37,48,49,52,53}, + {34,35,38,39,50,51,54,55}, + {40,41,44,45,56,57,60,61}, + {42,43,46,47,58,59,62,63} + }; + + for (offs = 0; offs < 0x1000 / 2; offs += 8) + { + if (pFstarfrcSpriteRam[offs] & 0x04) /* enable */ + { + INT32 code,color,sizex,sizey,flipx,flipy,xpos,ypos; + INT32 x,y,priority; + + code = pFstarfrcSpriteRam[offs+1]; + color = (pFstarfrcSpriteRam[offs+2] & 0xf0) >> 4; + sizex = 1 << ((pFstarfrcSpriteRam[offs+2] & 0x03) >> 0); + if(Riot) + sizey = sizex; + else + sizey = 1 << ((pFstarfrcSpriteRam[offs+2] & 0x0c) >> 2); + if (sizex >= 2) code &= ~0x01; + if (sizey >= 2) code &= ~0x02; + if (sizex >= 4) code &= ~0x04; + if (sizey >= 4) code &= ~0x08; + if (sizex >= 8) code &= ~0x10; + if (sizey >= 8) code &= ~0x20; + flipx = pFstarfrcSpriteRam[offs] & 0x01; + flipy = pFstarfrcSpriteRam[offs] & 0x02; + xpos = pFstarfrcSpriteRam[offs+4]; + if (xpos >= 0x8000) xpos -= 0x10000; + ypos = pFstarfrcSpriteRam[offs+3]; + if (ypos >= 0x8000) ypos -= 0x10000; + priority = (pFstarfrcSpriteRam[offs] & 0xc0) >> 6; + + if (priority != layerpriority) continue; + + for (y = 0;y < sizey;y++) + { + for (x = 0;x < sizex;x++) + { + INT32 sx = xpos + 8*(flipx?(sizex-1-x):x); + INT32 sy = ypos + 8*(flipy?(sizey-1-y):y); + + if ((code + layout[y][x]) > 32767) break; + + sy -= 16; + + if (sx > 7 && sx < 248 && sy > 7 && sy < 216) { + if (!flipx) { + if (!flipy) { + Render8x8Tile_Mask(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } + } else { + if (!flipy) { + Render8x8Tile_Mask_FlipX(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } else { + Render8x8Tile_Mask_FlipXY(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } + } + } else { + if (!flipx) { + if (!flipy) { + Render8x8Tile_Mask_Clip(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } + } else { + if (!flipy) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + layout[y][x], sx, sy, color, 4, 0, 0, FstarfrcSpriteTiles); + } + } + } + } + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 0) & 0x0f; + g = (nColour >> 4) & 0x0f; + b = (nColour >> 8) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +INT32 FstarfrcCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)FstarfrcPaletteRam, pd = FstarfrcPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +void GinkunRender() +{ + FstarfrcCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x300; + } + + draw_sprites(3); + GinkunRenderBgLayer(); + draw_sprites(2); + GinkunRenderFgLayer(); + draw_sprites(1); + FstarfrcRenderTextLayer(); + draw_sprites(0); + BurnTransferCopy(FstarfrcPalette); +} + +void FstarfrcRender() +{ + FstarfrcCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x300; + } + + draw_sprites(3); + FstarfrcRenderBgLayer(); + draw_sprites(2); + FstarfrcRenderFgLayer(); + draw_sprites(1); + FstarfrcRenderTextLayer(); + draw_sprites(0); + BurnTransferCopy(FstarfrcPalette); +} + +INT32 FstarfrcFrame() +{ + INT32 nInterleave = 10; + + if (FstarfrcReset) FstarfrcDoReset(); + + FstarfrcMakeInputs(); + + nCyclesTotal[0] = (24000000 / 2) / 60; + nCyclesTotal[1] = (8000000 / 2) / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + + SekOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) { + if (Ginkun || Riot) { + GinkunRender(); + } else { + FstarfrcRender(); + } + } + + return 0; +} + +static INT32 FstarfrcScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x02944; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + BurnYM2151Scan(nAction); + + // Scan critical driver variables + SCAN_VAR(FstarfrcSoundLatch); + SCAN_VAR(FstarfrcInput); + SCAN_VAR(FstarfrcDip); + SCAN_VAR(CharScrollX); + SCAN_VAR(CharScrollY); + SCAN_VAR(Scroll1X); + SCAN_VAR(Scroll1Y); + SCAN_VAR(Scroll2X); + SCAN_VAR(Scroll2Y); + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + } + + return 0; +} + +struct BurnDriver BurnDrvFstarfrc = { + "fstarfrc", NULL, NULL, NULL, "1992", + "Final Star Force (US)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, FstarfrcRomInfo, FstarfrcRomName, NULL, NULL, FstarfrcInputInfo, FstarfrcDIPInfo, + FstarfrcInit, FstarfrcExit, FstarfrcFrame, NULL, FstarfrcScan, + NULL, 0x2000, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFstarfrcj = { + "fstarfrcj", "fstarfrc", NULL, NULL, "1992", + "Final Star Force (Japan)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, FstarfrcjRomInfo, FstarfrcjRomName, NULL, NULL, FstarfrcInputInfo, FstarfrcDIPInfo, + FstarfrcInit, FstarfrcExit, FstarfrcFrame, NULL, FstarfrcScan, + NULL, 0x2000, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGinkun = { + "ginkun", NULL, NULL, NULL, "1995", + "Ganbare Ginkun\0", "Imperfect GFX", "Tecmo", "Miscellaneous", + L"\u304C\u3093\u3070\u308C \u30AE\u30F3\u304F\u3093\0Ganbare Ginkun\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, GinkunRomInfo, GinkunRomName, NULL, NULL, FstarfrcInputInfo, GinkunDIPInfo, + FstarfrcInit, FstarfrcExit, FstarfrcFrame, NULL, FstarfrcScan, + NULL, 0x2000, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRiot = { + "riot", NULL, NULL, NULL, "1992", + "Riot\0", NULL, "NMK", "Miscellaneous", + L"\u96F7\u8ECB\u6597 Riot\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, RiotRomInfo, RiotRomName, NULL, NULL, RiotInputInfo, RiotDIPInfo, + FstarfrcInit, FstarfrcExit, FstarfrcFrame, NULL, FstarfrcScan, + NULL, 0x2000, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_funkyjet.cpp b/src/burn/drivers/misc_post90s/d_funkyjet.cpp new file mode 100644 index 00000000..781ed94e --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_funkyjet.cpp @@ -0,0 +1,727 @@ +// FB Alpha Funky Jet driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPrtRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static struct BurnInputInfo FunkyjetInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Funkyjet) + +static struct BurnDIPInfo FunkyjetDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x02, 0x00, "No" }, + {0x15, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x10, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x20, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0xc0, 0x80, "1" }, + {0x15, 0x01, 0xc0, 0xc0, "2" }, + {0x15, 0x01, 0xc0, 0x40, "3" }, + {0x15, 0x01, 0xc0, 0x00, "4" }, +}; + +STDDIPINFO(Funkyjet) + +static struct BurnDIPInfo FunkyjetjDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x02, 0x00, "No" }, + {0x15, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x10, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x20, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0xc0, 0x80, "1" }, + {0x15, 0x01, 0xc0, 0xc0, "2" }, + {0x15, 0x01, 0xc0, 0x40, "3" }, + {0x15, 0x01, 0xc0, 0x00, "4" }, +}; + +STDDIPINFO(Funkyjetj) + +static struct BurnDIPInfo SotsugyoDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xed, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x15, 0x01, 0x0c, 0x04, "1" }, + {0x15, 0x01, 0x0c, 0x08, "2" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x30, "Easy" }, + {0x15, 0x01, 0x30, 0x20, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Free Play" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Sotsugyo) + +void __fastcall funkyjet_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x300000, data) + + switch (address) + { + case 0x18010a: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + } + + if ((address & 0xfff800) == 0x180000) { + *((UINT16*)(DrvPrtRAM + (address & 0x7fe))) = data; + return; + } +} + +void __fastcall funkyjet_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x18010a: + case 0x18010b: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + break; + } + + if ((address & 0xfff800) == 0x180000) { + DrvPrtRAM[(address & 0x7ff)^1] = data; + return; + } +} + +UINT16 __fastcall funkyjet_main_read_word(UINT32 address) +{ + if ((address & 0xfff800) == 0x180000) { + return deco16_146_funkyjet_prot_r(address); + } + + return 0; +} + +UINT8 __fastcall funkyjet_main_read_byte(UINT32 address) +{ + if ((address & 0xfff800) == 0x180000) { + return deco16_146_funkyjet_prot_r(address) >> ((~address & 1) << 3); + } + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + MSM6295Reset(0); + BurnYM2151Reset(); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + deco16_prot_ram = (UINT16*)Next; + DrvPrtRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 6, 1)) return 1; + + deco74_decrypt_gfx(DrvGfxROM1, 0x080000); + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x080000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + } + + deco16Init(1, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x80000 * 2, DrvGfxROM1, 0x80000 * 2, NULL, 0); + deco16_set_color_base(0, 256); + deco16_set_color_base(1, 512); + deco16_set_global_offsets(0, 8); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x140000, 0x143fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x320000, 0x321fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x322000, 0x323fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x340000, 0x340bff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x342000, 0x342bff, SM_RAM); + SekSetWriteWordHandler(0, funkyjet_main_write_word); + SekSetWriteByteHandler(0, funkyjet_main_write_byte); + SekSetReadWordHandler(0, funkyjet_main_read_word); + SekSetReadByteHandler(0, funkyjet_main_read_byte); + SekClose(); + + // Huc6280... + + MSM6295Init(0, 1000000 / 132, 50.0, 1); + + BurnYM2151Init(3580000, 40.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + MSM6295Exit(0); + BurnYM2151Exit(); + + SekExit(); + // huc6280 + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x800 / 2; i++) { + INT32 b = (p[i] >> 8) & 0x0f; + INT32 g = (p[i] >> 4) & 0x0f; + INT32 r = (p[i] >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult; + + INT32 sy = ram[offs + 0]; + INT32 code = ram[offs + 1] & 0x3fff; + INT32 sx = ram[offs + 2]; + + if ((sy & 0x1000) && (nCurrentFrame & 1)) continue; + + INT32 color = (sx >> 9) & 0x1f; + + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + INT32 multi = (1 << ((sy & 0x0600) >> 9)) - 1; + + sx &= 0x01ff; + sy &= 0x01ff; + if (sx >= 320) sx -= 512; + if (sy >= 256) sy -= 512; + sy = 240 - sy; + sx = 304 - sx; + + code &= ~multi; + + if (flipy) { + inc = -1; + } else { + code += multi; + inc = 1; + } + + if (*flipscreen) + { + sy = 240 - sy; + sx = 304 - sx; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else + mult = -16; + + if (sx >= 320 || sx < -15 || sy >= nScreenHeight) continue; + + while (multi >= 0) + { + INT32 y = ((sy + mult * multi) & 0x1ff) - 8; + INT32 c = (code - multi * inc) & 0x3fff; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + DrvPaletteRecalc(); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x300; + } + + if (nBurnLayer & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_OPAQUE); + if (nBurnLayer & 2) deco16_draw_layer(0, pTransDraw, 0); + + if (nBurnLayer & 4) draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + deco16_prot_inputs = DrvInputs; + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[2] = (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 248) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Funky Jet (World) + +static struct BurnRomInfo funkyjetRomDesc[] = { + { "jk00.12f", 0x40000, 0x712089c1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jk01.13f", 0x40000, 0xbe3920d7, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jk02.16f", 0x10000, 0x748c0bd8, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "mat02", 0x80000, 0xe4b94c7e, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "mat01", 0x80000, 0x24093a8d, 4 | BRF_GRA }, // 4 Sprites + { "mat00", 0x80000, 0xfbda0228, 4 | BRF_GRA }, // 5 + + { "jk03.15h", 0x20000, 0x69a0eaf7, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(funkyjet) +STD_ROM_FN(funkyjet) + +struct BurnDriver BurnDrvFunkyjet = { + "funkyjet", NULL, NULL, NULL, "1992", + "Funky Jet (World)\0", "No sound", "[Data East] (Mitchell license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, funkyjetRomInfo, funkyjetRomName, NULL, NULL, FunkyjetInputInfo, FunkyjetDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Funky Jet (Japan) + +static struct BurnRomInfo funkyjetjRomDesc[] = { + { "jh00-2.11f", 0x40000, 0x5b98b700, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jh01-2.13f", 0x40000, 0x21280220, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "jk02.16f", 0x10000, 0x748c0bd8, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "mat02", 0x80000, 0xe4b94c7e, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "mat01", 0x80000, 0x24093a8d, 4 | BRF_GRA }, // 4 Sprites + { "mat00", 0x80000, 0xfbda0228, 4 | BRF_GRA }, // 5 + + { "jk03.15h", 0x20000, 0x69a0eaf7, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(funkyjetj) +STD_ROM_FN(funkyjetj) + +struct BurnDriver BurnDrvFunkyjetj = { + "funkyjetj", "funkyjet", NULL, NULL, "1992", + "Funky Jet (Japan)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, funkyjetjRomInfo, funkyjetjRomName, NULL, NULL, FunkyjetInputInfo, FunkyjetjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Sotsugyo Shousho + +static struct BurnRomInfo sotsugyoRomDesc[] = { + { "03.12f", 0x40000, 0xd175dfd1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "04.13f", 0x40000, 0x2072477c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sb020.16f", 0x10000, 0xbaf5ec93, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "02.2f", 0x80000, 0x337b1451, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "01.4a", 0x80000, 0xfa10dd54, 4 | BRF_GRA }, // 4 Sprites + { "00.2a", 0x80000, 0xd35a14ef, 4 | BRF_GRA }, // 5 + + { "sb030.15h", 0x20000, 0x1ea43f48, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(sotsugyo) +STD_ROM_FN(sotsugyo) + +struct BurnDriver BurnDrvSotsugyo = { + "sotsugyo", NULL, NULL, NULL, "1995", + "Sotsugyo Shousho\0", "No sound", "Mitchell (Atlus license)", "Miscellaneous", + L"\u5352\u696D\u8A3C\u66F8\0Sotsugyo Shousho\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, sotsugyoRomInfo, sotsugyoRomName, NULL, NULL, FunkyjetInputInfo, SotsugyoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_funybubl.cpp b/src/burn/drivers/misc_post90s/d_funybubl.cpp new file mode 100644 index 00000000..f815d92a --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_funybubl.cpp @@ -0,0 +1,623 @@ +// FB Alpha Funny Bubble driver module +// Based on MAME driver by Pierpaolo Prazzoli and David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" + +// To do: +// Fix sound after save state + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[1]; +static UINT8 DrvInps[3]; + +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static UINT8 soundlatch; +static INT32 nDrvRomBank; +static INT32 nDrvVidRAMBank; +static INT32 nDrvOkiBank; + +static struct BurnInputInfo FunybublInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Funybubl) + + +static struct BurnDIPInfo FunybublDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin_A" }, + {0x0f, 0x01, 0x07, 0x01, "3 Coins 1 Credits " }, + {0x0f, 0x01, 0x07, 0x02, "2 Coins 1 Credits " }, + {0x0f, 0x01, 0x07, 0x03, "3 Coins 2 Credits " }, + {0x0f, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x0f, 0x01, 0x07, 0x04, "2 Coins 3 Credits " }, + {0x0f, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x0f, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x0f, 0x01, 0x07, 0x00, "Free_Play" }, + + {0 , 0xfe, 0 , 7, "Difficulty" }, + {0x0f, 0x01, 0x38, 0x30, "Very_Easy" }, + {0x0f, 0x01, 0x38, 0x28, "Easy" }, + {0x0f, 0x01, 0x38, 0x38, "Normal" }, + {0x0f, 0x01, 0x38, 0x20, "Hard 1" }, + {0x0f, 0x01, 0x38, 0x18, "Hard 2" }, + {0x0f, 0x01, 0x38, 0x10, "Hard 3" }, + {0x0f, 0x01, 0x38, 0x08, "Hard 4" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Nudity" }, + {0x0f, 0x01, 0x80, 0x80, "Semi" }, + {0x0f, 0x01, 0x80, 0x00, "Full" }, +}; + +STDDIPINFO(Funybubl) + + +UINT8 __fastcall funybubl_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + return DrvInps[port & 3]; + + case 0x03: + return DrvDips[0]; + + case 0x06: + return 0; + } + + return 0; +} + +void __fastcall funybubl_write(UINT16 address, UINT8 data) +{ + if (address >= 0xc400 && address <= 0xcfff) { + + INT32 offset = address - 0xc400; + + DrvPalRAM[offset] = data; + + UINT32 coldat; + + offset &= 0xfffc; + + coldat = DrvPalRAM[offset] | (DrvPalRAM[offset+1] << 8) | (DrvPalRAM[offset+2] << 16) | (DrvPalRAM[offset+3] << 24); + + UINT8 r, g, b; + + r = (coldat >> 12) << 2; + r |= r >> 6; + + g = (coldat >> 0) << 2; + g |= g >> 6; + + b = (coldat >> 6) << 2; + b |= b >> 6; + + Palette[offset >> 2] = (r << 16) | (g << 8) | b; + DrvPalette[offset >> 2] = BurnHighCol(r, g, b, 0); + + return; + } +} + +static void funybubl_set_vidram_bank(INT32 data) +{ + nDrvVidRAMBank = data & 1; + + ZetMapArea(0xd000, 0xdfff, 0, DrvVidRAM + nDrvVidRAMBank * 0x1000); + ZetMapArea(0xd000, 0xdfff, 1, DrvVidRAM + nDrvVidRAMBank * 0x1000); + ZetMapArea(0xd000, 0xdfff, 2, DrvVidRAM + nDrvVidRAMBank * 0x1000); +} + +static void funybubl_set_rom_bank(INT32 data) +{ + nDrvRomBank = data & 0x3f; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + nDrvRomBank * 0x4000); + ZetMapArea(0x8000, 0xbfff, 1, DrvZ80ROM0 + nDrvRomBank * 0x4000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + nDrvRomBank * 0x4000); +} + +static void funybubl_set_oki_bank(INT32 data) +{ + nDrvOkiBank = data & 1; + + MSM6295ROM = DrvSndROM + nDrvOkiBank * 0x40000; +} + +void __fastcall funybubl_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + funybubl_set_vidram_bank(data); + return; + + case 0x01: + funybubl_set_rom_bank(data); + return; + + case 0x03: + soundlatch = data; + + ZetClose(); + ZetOpen(1); + ZetRaiseIrq(0); + ZetClose(); + ZetOpen(0); + return; + + case 0x06: + case 0x07: + return; + } +} + +void __fastcall funybubl_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + funybubl_set_oki_bank(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall funybubl_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return soundlatch; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[8] = { 0x200000 * 3, 0x200000 * 2, 0x200000 * 1, 0x200000 * 0, + 0x200000 * 7, 0x200000 * 6, 0x200000 * 5, 0x200000 * 4 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs0[8] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }; + + INT32 Plane1[8] = { 0x400000 * 3 + 4, 0x400000 * 3 + 0, 0x400000 * 2 + 4, 0x400000 * 2 + 0, + 0x400000 * 1 + 4, 0x400000 * 1 + 0, 0x400000 * 0 + 4, 0x400000 * 0 + 0 }; + INT32 XOffs1[16] = { 0, 1,2,3, 8,9,10,11, 256,257,258,259, 264,265,266,267 }; + INT32 YOffs1[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, + 8*16, 9*16,10*16,11*16,12*16,13*16,14*16,15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x200000; i++) { // invert + DrvGfxROM0[i] ^= 0xff; + DrvGfxROM1[i] ^= 0xff; + } + + memcpy (tmp, DrvGfxROM0, 0x200000); + + GfxDecode(0x8000, 8, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x2000, 8, 16, 16, Plane1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x040000; + DrvZ80ROM1 = Next; Next += 0x008000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x080000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x000c00; + DrvVidRAM = Next; Next += 0x002000; + + DrvZ80RAM1 = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + funybubl_set_vidram_bank(0); + funybubl_set_rom_bank(0); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + funybubl_set_oki_bank(0); + MSM6295Reset(0); + + soundlatch = 0; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0, 0, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) + if (BurnLoadRom(DrvGfxROM0 + i * 0x40000, i + 1, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) + if (BurnLoadRom(DrvGfxROM1 + i * 0x80000, i + 9, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1, 13, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 14, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x20000, 15, 1)) return 1; + + memcpy (DrvSndROM + 0x60000, DrvSndROM + 0x40000, 0x20000); + memcpy (DrvSndROM + 0x40000, DrvSndROM + 0x00000, 0x20000); + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0xc400, 0xcfff, 0, DrvPalRAM); + ZetMapArea(0xc400, 0xcfff, 2, DrvPalRAM); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80RAM0); + ZetSetWriteHandler(funybubl_write); + ZetSetOutHandler(funybubl_out); + ZetSetInHandler(funybubl_in); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(funybubl_sound_write); + ZetSetReadHandler(funybubl_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132, 100.0, 0); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_sprites() +{ + UINT8 *source = &DrvVidRAM[0x2000-0x20]; + UINT8 *finish = source - 0x1000; + + while (source > finish) + { + INT32 sx, sy, code; + + sy = source[2]; + sx = source[3]; + code = source[0] | ( (source[1] & 0x0f) <<8); + if (source[1] & 0x80) code += 0x1000; + if (source[1] & 0x20) { if (sx < 0xe0) sx += 0x100; } + + sx -= 96; + sy -= 16; + + if ((sx >= 0 && sx < 305) || (sy >= 0 && sy < 208)) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 8, 0xff, 0, DrvGfxROM1); + } + + source -= 0x20; + } +} + +static void draw_background() +{ + for (INT32 offs = 0; offs < 0x1000; offs+=2) + { + INT32 sx = ((offs >> 1) & 0x3f) << 3; + INT32 sy = (offs >> 7) << 3; + + sx -= 96; + sy -= 16; + if (sx < 0 || sx > 312 || sy < 0 || sy > 216) continue; + + INT32 code = DrvVidRAM[offs] | (DrvVidRAM[offs + 1] << 8); + + Render8x8Tile_Mask_Clip(pTransDraw, code & 0x7fff, sx, sy, 1+(code>>15), 8, 0, 0, DrvGfxROM0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x300; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + draw_background(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInps, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + DrvInps[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 6000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment; + + ZetOpen(0); + nSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + ZetOpen(1); + nSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + nCyclesDone[1] += ZetRun(nSegment); + ZetClose(); + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029697; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + MSM6295Scan(0, nAction); + + SCAN_VAR(soundlatch); + SCAN_VAR(nDrvOkiBank); + SCAN_VAR(nDrvRomBank); + SCAN_VAR(nDrvVidRAMBank); + } + + if (nAction & ACB_WRITE) { + funybubl_set_oki_bank(nDrvOkiBank); + funybubl_set_rom_bank(nDrvRomBank); + funybubl_set_vidram_bank(nDrvVidRAMBank); + } + + return 0; +} + +// Funny Bubble + +static struct BurnRomInfo funybublRomDesc[] = { + { "a.ub16", 0x40000, 0x4e799cdd, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "f.ug13", 0x40000, 0x64d7163d, 2 | BRF_GRA }, // 1 Background Tiles + { "g.uh13", 0x40000, 0x6891e2b8, 2 | BRF_GRA }, // 2 + { "h.ug15", 0x40000, 0xca7f7528, 2 | BRF_GRA }, // 3 + { "i.uh15", 0x40000, 0x23608ec6, 2 | BRF_GRA }, // 4 + { "l.ug16", 0x40000, 0x0acf8143, 2 | BRF_GRA }, // 5 + { "m.uh16", 0x40000, 0x55ed8d9c, 2 | BRF_GRA }, // 6 + { "n.ug17", 0x40000, 0x52398b68, 2 | BRF_GRA }, // 7 + { "o.uh17", 0x40000, 0x446e31b2, 2 | BRF_GRA }, // 8 + + { "d.ug1", 0x80000, 0xb7ebbc00, 3 | BRF_GRA }, // 9 Sprites + { "e.ug2", 0x80000, 0x28afc396, 3 | BRF_GRA }, // 10 + { "j.ug3", 0x80000, 0x9e8687cd, 3 | BRF_GRA }, // 11 + { "k.ug4", 0x80000, 0x63f0e810, 3 | BRF_GRA }, // 12 + + { "p.su6", 0x08000, 0x33169d4d, 4 | BRF_PRG | BRF_ESS }, // 13 Z80 #1 Code + + { "b.su12", 0x20000, 0xa2d780f4, 5 | BRF_SND }, // 14 Samples + { "c.su13", 0x40000, 0x1f7e9269, 5 | BRF_SND }, // 15 +}; + +STD_ROM_PICK(funybubl) +STD_ROM_FN(funybubl) + +struct BurnDriver BurnDrvFunybubl = { + "funybubl", NULL, NULL, NULL, "1999", + "Funny Bubble\0", NULL, "In Chang Electronic Co", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, funybublRomInfo, funybublRomName, NULL, NULL, FunybublInputInfo, FunybublDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 224, 4, 3 +}; + + +// Funny Bubble (Comad version) + +static struct BurnRomInfo funybubcRomDesc[] = { + { "2.ub16", 0x40000, 0xd684c13f, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "7.ug12", 0x40000, 0x87603d7b, 2 | BRF_GRA }, // 1 Background Tiles + { "8.uh13", 0x40000, 0xab6031bd, 2 | BRF_GRA }, // 2 + { "9.ug15", 0x40000, 0x0e8352ff, 2 | BRF_GRA }, // 3 + { "10.uh15", 0x40000, 0xdf7dd356, 2 | BRF_GRA }, // 4 + { "13.ug16", 0x40000, 0x9f57bdd5, 2 | BRF_GRA }, // 5 + { "14.uh16", 0x40000, 0x2ac15ea3, 2 | BRF_GRA }, // 6 + { "15.ug17", 0x40000, 0x9a5e66a6, 2 | BRF_GRA }, // 7 + { "16.uh17", 0x40000, 0x218060b3, 2 | BRF_GRA }, // 8 + + { "5.ug1", 0x80000, 0xb7ebbc00, 3 | BRF_GRA }, // 9 Sprites + { "6.ug2", 0x80000, 0x28afc396, 3 | BRF_GRA }, // 10 + { "11.ug3", 0x80000, 0x9e8687cd, 3 | BRF_GRA }, // 11 + { "12.ug4", 0x80000, 0x63f0e810, 3 | BRF_GRA }, // 12 + + { "1.su6", 0x08000, 0x33169d4d, 4 | BRF_PRG | BRF_ESS }, // 13 Z80 #1 Code + + { "3.su12", 0x20000, 0xa2d780f4, 5 | BRF_SND }, // 14 Samples + { "4.su13", 0x40000, 0x1f7e9269, 5 | BRF_SND }, // 15 +}; + +STD_ROM_PICK(funybubc) +STD_ROM_FN(funybubc) + +struct BurnDriver BurnDrvFunybubc = { + "funybublc", "funybubl", NULL, NULL, "1999", + "Funny Bubble (Comad version)\0", NULL, "Comad Industry Co Ltd", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, funybubcRomInfo, funybubcRomName, NULL, NULL, FunybublInputInfo, FunybublDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_fuukifg3.cpp b/src/burn/drivers/misc_post90s/d_fuukifg3.cpp new file mode 100644 index 00000000..a9da42d7 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_fuukifg3.cpp @@ -0,0 +1,1302 @@ +// FB Alpha Fuuki FG-3 driver module +// Based on MAME driver by Paul Priest and David Haywood + +#include "tiles_generic.h" +#include "burn_ymf278b.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf0; +static UINT8 *DrvSprBuf1; +static UINT8 *DrvFgRAM1; +static UINT8 *DrvFgRAM2; +static UINT8 *DrvBgRAM1; +static UINT8 *DrvBgRAM2; +static UINT8 *DrvVidRegs; +static UINT8 *DrvShareRAM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvScrollBuf; +static UINT8 *DrvTransTab1; +static UINT8 *DrvTransTab2; +static UINT8 *DrvTransTab3; + +static UINT16 *DrvRasterPos; +static UINT8 *nDrvZ80Bank; +static UINT16 *tilebank; +static UINT16 *tilebank_buf; +static UINT8 *priority; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 DrvInputs[4]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[4]; +static UINT8 DrvReset; + +static INT32 nEnableRaster[3]; + +static struct BurnInputInfo AsurabldInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 8, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Asurabld) + +static struct BurnDIPInfo AsurabldDIPList[]= +{ + {0x14, 0xff, 0xff, 0x3f, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Blood Colour" }, + {0x14, 0x01, 0x02, 0x02, "Red" }, + {0x14, 0x01, 0x02, 0x00, "Green" }, + + {0 , 0xfe, 0 , 4, "Timer" }, + {0x14, 0x01, 0x30, 0x00, "Slow" }, + {0x14, 0x01, 0x30, 0x30, "Medium" }, + {0x14, 0x01, 0x30, 0x10, "Fast" }, + {0x14, 0x01, 0x30, 0x20, "Very Fast" }, + + {0 , 0xfe, 0 , 2, "Coinage Mode" }, + {0x14, 0x01, 0xc0, 0xc0, "Split" }, + {0x14, 0x01, 0xc0, 0x00, "Joint" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x15, 0x01, 0x01, 0x01, "Off" }, +// {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Computer Level" }, + {0x15, 0x01, 0x0e, 0x00, "0" }, + {0x15, 0x01, 0x0e, 0x08, "1" }, + {0x15, 0x01, 0x0e, 0x04, "2" }, + {0x15, 0x01, 0x0e, 0x0c, "3" }, + {0x15, 0x01, 0x0e, 0x0e, "4" }, + {0x15, 0x01, 0x0e, 0x02, "5" }, + {0x15, 0x01, 0x0e, 0x0a, "6" }, + {0x15, 0x01, 0x0e, 0x06, "7" }, + + {0 , 0xfe, 0 , 4, "Damage" }, + {0x15, 0x01, 0x30, 0x20, "Lowest" }, + {0x15, 0x01, 0x30, 0x30, "Low" }, + {0x15, 0x01, 0x30, 0x10, "Medium" }, + {0x15, 0x01, 0x30, 0x00, "High" }, + + {0 , 0xfe, 0 , 3, "Max Rounds" }, + {0x15, 0x01, 0xc0, 0x00, "1" }, + {0x15, 0x01, 0xc0, 0x40, "3" }, + {0x15, 0x01, 0xc0, 0x80, "5" }, + + {0 , 0xfe, 0 , 9, "Coin B" }, + {0x16, 0x01, 0x0f, 0x08, "8 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x09, "7 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0a, "6 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0c, "4 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0d, "3 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0e, "2 Coins 1 Credits " }, + {0x16, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits " }, + {0x16, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 9, "Coin A" }, + {0x16, 0x01, 0xf0, 0x80, "8 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0x90, "7 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits " }, + {0x16, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits " }, + {0x16, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Asurabld) + +static inline void cpu_sync() // sync z80 & 68k +{ + INT32 t = ((SekTotalCycles() * 3) / 10) - ZetTotalCycles(); + + if (t > 0) { + BurnTimerUpdate(t); + } +} + +void __fastcall fuuki32_write_long(UINT32 , UINT32 ) +{ + +} + +void __fastcall fuuki32_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffffe0) == 0x8c0000) { + + if (address == 0x8c001c) { + DrvRasterPos[0] = data & 0xff; + } + + *((UINT16*)(DrvVidRegs + (address & 0x1e))) = data; + + return; + } + + if ((address & 0xffffe0) == 0x903fe0) { + cpu_sync(); + + DrvShareRAM[(address & 0x1f) >> 1] = data & 0xff; + return; + } + + switch (address) + { + case 0x8e0000: + priority[0] = data & 0x000f; + return; + + case 0xa00000: + tilebank[0] = data; + return; + } +} + +void __fastcall fuuki32_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffffe0) == 0x903fe0) { + cpu_sync(); + + DrvShareRAM[(address & 0x1f) >> 1] = data; + return; + } +} + +UINT32 __fastcall fuuki32_read_long(UINT32) +{ + return 0; +} + +UINT16 __fastcall fuuki32_read_word(UINT32 address) +{ + switch (address) + { + case 0x800000: + return DrvInputs[0]; + + case 0x810000: + return DrvInputs[1]; + + case 0x880000: + return DrvInputs[2]; + + case 0x890000: + return DrvInputs[3]; + + case 0x8c001e: + return *((UINT16*)(DrvVidRegs + 0x1e)); + } + + return 0; +} + +UINT8 __fastcall fuuki32_read_byte(UINT32 address) +{ + if ((address & 0xffffe0) == 0x903fe0) { + cpu_sync(); + return DrvShareRAM[(address & 0x1f) >> 1]; + } + + return 0; +} + +static void bankswitch(INT32 data) +{ + nDrvZ80Bank[0] = data; + + INT32 nBank = (data & 0x0f) * 0x8000; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + nBank); +} + +void __fastcall fuuki32_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xfff0) == 0x7ff0) { + DrvShareRAM[address & 0x0f] = data; + return; + } +} + +UINT8 __fastcall fuuki32_sound_read(UINT16 address) +{ + if ((address & 0xfff0) == 0x7ff0) { + return DrvShareRAM[address & 0x0f]; + } + + return 0; +} + +void __fastcall fuuki32_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + bankswitch(data); + return; + + case 0x40: + case 0x42: + case 0x44: + BurnYMF278BSelectRegister((port >> 1) & 3, data); + return; + + case 0x41: + case 0x43: + case 0x45: + BurnYMF278BWriteRegister((port >> 1) & 3, data); + return; + } +} + +UINT8 __fastcall fuuki32_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x40: + return BurnYMF278BReadStatus(); + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYMF278BReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x200000; + DrvZ80ROM = Next; Next += 0x080000; + + DrvTransTab1 = Next; Next += 0x008000; + DrvTransTab2 = Next; Next += 0x008000; + DrvTransTab3 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x4000000; + DrvGfxROM1 = Next; Next += 0x800000; + DrvGfxROM2 = Next; Next += 0x800000; + DrvGfxROM3 = Next; Next += 0x400000; + + DrvSndROM = Next; Next += 0x400000; + + DrvPalette = (UINT32 *)Next; Next += 0x2000 * sizeof(UINT32); + DrvScrollBuf = (UINT32 *)Next; Next += 256 * 4 * sizeof(UINT32); + DrvRasterPos = (UINT16*)Next; Next += 0x0001 * sizeof(UINT16); + + AllRam = Next; + + DrvVidRegs = Next; Next += 0x000400; + DrvShareRAM = Next; Next += 0x000010; + DrvZ80RAM = Next; Next += 0x001000; + + Drv68KRAM = Next; Next += 0x020000; + DrvPalRAM = Next; Next += 0x004000; + DrvFgRAM1 = Next; Next += 0x002000; + DrvFgRAM2 = Next; Next += 0x020000; + DrvBgRAM1 = Next; Next += 0x002000; + DrvBgRAM2 = Next; Next += 0x002000; + DrvSprRAM = Next; Next += 0x002000; + DrvSprBuf0 = Next; Next += 0x002000; + DrvSprBuf1 = Next; Next += 0x002000; + + priority = Next; Next += 0x000001; + + tilebank = (UINT16*)Next; Next += 0x0001 * sizeof(UINT16); + tilebank_buf = (UINT16*)Next; Next += 0x0002 * sizeof(UINT16); + + nDrvZ80Bank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[ 8] = { 0x0000000, 0x0000001, 0x0000002, 0x0000003, + 0x2000000, 0x2000001, 0x2000002, 0x2000003 }; + INT32 XOffs[16] = { 0x008, 0x00c, 0x000, 0x004, 0x018, 0x01c, 0x010, 0x014, + 0x028, 0x02c, 0x020, 0x024, 0x038, 0x03c, 0x030, 0x034 }; + INT32 YOffs0[ 8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + INT32 YOffs1[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + UINT8 *tmp = DrvGfxROM0 + 0x2000000; + + memcpy (tmp, DrvGfxROM1, 0x800000); + + GfxDecode(0x08000, 8, 16, 16, Plane, XOffs, YOffs1, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x800000); + + GfxDecode(0x08000, 8, 16, 16, Plane, XOffs, YOffs1, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x200000); + + GfxDecode(0x10000, 4, 8, 8, Plane, XOffs, YOffs0, 0x100, tmp, DrvGfxROM3); + + return 0; +} + +static void DrvSpriteExpand() +{ + BurnByteswap(DrvGfxROM0, 0x4000000); + UINT8 *tmp; + + for (INT32 i = 0x2000000 - 0x80; i >= 0; i -= 0x80) + { + tmp = DrvGfxROM0 + i; + + for (INT32 j = 0x7f; j >= 0; j--) { + INT32 t = tmp[j]; + DrvGfxROM0[((i + j) << 1) + 0] = t >> 4; + DrvGfxROM0[((i + j) << 1) + 1] = t & 0x0f; + } + } +} + +static void DrvCalculateTransTab(UINT8 *src, UINT8 *dst, INT32 t, INT32 w, INT32 len) +{ + UINT8 *dptr = dst; + for (INT32 i = 0; i < len; i+= w) + { + INT32 a = 0, b = 0; + for (INT32 j = 0; j < w; j++) { + a|=src[i+j]^t; + + if (src[i+j] != t) { + b++; + } + } + + dptr[0] = a ? 0 : 2; + if (b == w) dptr[0] |= 1; + + dptr++; + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x0000001, 0, 4)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000000, 1, 4)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000003, 2, 4)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000002, 3, 4)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x0000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0400000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x0000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0400000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x0000000, 10, 1)) return 1; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "asurabld") == 0) { + if (BurnLoadRom(DrvGfxROM0 + 0x0400000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0800000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c00000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1000000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1400000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1800000, 16, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM0 + 0x0000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0400000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0800000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c00000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1000000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1400000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1800000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1c00000, 18, 1)) return 1; + } + + DrvGfxDecode(); + DrvSpriteExpand(); + + DrvCalculateTransTab(DrvGfxROM1, DrvTransTab1, 0xff, 0x100, 0x800000); + DrvCalculateTransTab(DrvGfxROM2, DrvTransTab2, 0xff, 0x100, 0x800000); + DrvCalculateTransTab(DrvGfxROM3, DrvTransTab3, 0x0f, 0x040, 0x400000); + } + + SekInit(0, 0x68ec020); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x410000, 0x41ffff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x500000, 0x501fff, SM_RAM); + SekMapMemory(DrvBgRAM2, 0x502000, 0x503fff, SM_RAM); + SekMapMemory(DrvFgRAM1, 0x504000, 0x505fff, SM_RAM); + SekMapMemory(DrvFgRAM2, 0x506000, 0x507fff, SM_RAM); + SekMapMemory(DrvFgRAM2 + 0x2000,0x508000, 0x517fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x600000, 0x601fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700000, 0x703fff, SM_RAM); + SekSetWriteLongHandler(0, fuuki32_write_long); + SekSetWriteWordHandler(0, fuuki32_write_word); + SekSetWriteByteHandler(0, fuuki32_write_byte); + SekSetReadLongHandler(0, fuuki32_read_long); + SekSetReadWordHandler(0, fuuki32_read_word); + SekSetReadByteHandler(0, fuuki32_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM); + ZetMapArea(0x6000, 0x6fff, 0, DrvZ80RAM); + ZetMapArea(0x6000, 0x6fff, 1, DrvZ80RAM); + ZetMapArea(0x6000, 0x6fff, 2, DrvZ80RAM); + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + 0x8000); + ZetSetWriteHandler(fuuki32_sound_write); + ZetSetReadHandler(fuuki32_sound_read); + ZetSetOutHandler(fuuki32_sound_out); + ZetSetInHandler(fuuki32_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnYMF278BInit(0, DrvSndROM, &DrvFMIRQHandler, DrvSynchroniseStream); + BurnTimerAttachZet(6000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYMF278BExit(); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites(INT32 prio) +{ + UINT16 *src = (UINT16*)DrvSprBuf1; + + for (INT32 offs = 0; offs < 0x2000 / 2; offs += 4) + { + INT32 sx = src[offs + 0]; + INT32 sy = src[offs + 1]; + INT32 attr = src[offs + 2]; + INT32 code = src[offs + 3]; + + if (prio != ((attr >> 6) & 0x0003) || sx & 0x0400) continue; + + INT32 bank = (tilebank_buf[1] >> ((code >> 12) & 0x0c)) & 0xf; + + code = (code & 0x3fff) | (bank << 14); + + INT32 flipx = sx & 0x0800; + INT32 flipy = sy & 0x0800; + INT32 xnum = ((sx >> 12) & 0xf) + 1; + INT32 ynum = ((sy >> 12) & 0xf) + 1; + INT32 xzoom = 128 - ((attr >> 10) & 0x3c); + INT32 yzoom = 128 - ((attr >> 6) & 0x3c); + + sx = (sx & 0x1ff) - (sx & 0x200); + sy = (sy & 0x1ff) - (sy & 0x200); + + INT32 xstart, ystart, xend, yend, xinc, yinc; + if (flipx) { xstart = (xnum-1) * 16; xend = -16; xinc = -16; } + else { xstart = 0; xend = xnum * 16; xinc = +16; } + + if (flipy) { ystart = (ynum-1) * 16; yend = -16; yinc = -16; } + else { ystart = 0; yend = ynum * 16; yinc = +16; } + + for (INT32 y = ystart; y != yend; y += yinc) + { + for (INT32 x = xstart; x != xend; x += xinc) + { + if (xzoom == 128 && yzoom == 128) { + if (sx + x >= 0 && sx + x < nScreenWidth - 15 && sy + y >= 0 && sy + y < nScreenHeight - 15) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } else { + Render16x16Tile_Mask(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code++, sx + x, sy + y, attr & 0x3f, 4, 0x0f, 0x800, DrvGfxROM0); + } + } + } + } else { + RenderZoomedTile(pTransDraw, DrvGfxROM0, code++, ((attr & 0x3f) << 4) | 0x800, 15, sx + (x * xzoom) / 128, sy + (y * yzoom) / 128, flipx, flipy, 16, 16, (xzoom + 8) << 9, (yzoom + 8) << 9); + } + } + } + } +} + +static void draw_background_layer(UINT8 *ram, UINT8 *gfx, UINT8 *tab, INT32 coloff, INT32 soff) +{ + INT32 yoff = (DrvScrollBuf[0x300] & 0xffff) - 0x1f3; + INT32 xoff = (DrvScrollBuf[0x300] >> 16) - 0x3f6; + INT32 scrolly = ((DrvScrollBuf[soff*256] & 0xffff) + yoff) & 0x1ff; + INT32 scrollx = ((DrvScrollBuf[soff*256] >> 16) + xoff) & 0x3ff; + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= scrollx; + if (sx < -15) sx += 1024; + sy -= scrolly; + if (sy < -15) sy += 512; + + INT32 code = vram[offs*2] & 0x7fff; + if (tab[code] == 2) continue; + INT32 attr = vram[offs*2 + 1]; + + INT32 color = (attr & 0x30) >> 4; + INT32 flipx = (attr >> 6) & 1; + INT32 flipy = (attr >> 7) & 1; + + if (sx >= 0 && sx < nScreenWidth - 15 && sy >= 0 && sy < nScreenHeight - 15) { + if (tab[code]) { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } else { + Render16x16Tile_FlipY(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } + } else { + if (flipx) { + Render16x16Tile_FlipX(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } else { + Render16x16Tile(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } + } + } + } else { + if (sx >= nScreenWidth || sy >= nScreenWidth) continue; + + if (tab[code]) { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 8, coloff, gfx); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 8, 0xff, coloff, gfx); + } + } + } + } + } +} + +static void draw_background_layer_byline(UINT8 *ram, UINT8 *gfx, UINT8 *tab, INT32 coloff, INT32 soff) +{ + UINT16 *vram = (UINT16*)ram; + UINT16 *dst = pTransDraw; + + for (INT32 y = 0; y < nScreenHeight; y++) + { + INT32 yoff = (DrvScrollBuf[0x300 + y] & 0xffff) - 0x1f3; + INT32 xoff = (DrvScrollBuf[0x300 + y] >> 16) - 0x3f6; + INT32 scrolly = ((DrvScrollBuf[(soff*256) + y] & 0xffff) + yoff + y) & 0x1ff; + INT32 scrollx = ((DrvScrollBuf[(soff*256) + y] >> 16) + xoff) & 0x3ff; + + INT32 yy = scrolly & 0x1f0; + INT32 yo = (scrolly & 0x0f) << 4; + INT32 xo = scrollx & 0x0f; + + for (INT32 x = 0; x < nScreenWidth + 16; x+=16) + { + INT32 xx = ((scrollx + x) >> 3) & 0x7e; + + INT32 ofst = (yy << 3) | xx; + + INT32 code = vram[ofst] & 0x7fff; + if (tab[code] == 2) continue; + INT32 attr = vram[ofst + 1]; + + INT32 color = (attr & 0x30) << 4; + INT32 flipx = ((attr >> 6) & 1) * 0x0f; + INT32 flipy = ((attr >> 7) & 1) * 0xf0; + + color |= coloff; + + UINT8 *src = gfx + (code << 8) + (yo ^ flipy); + + INT32 xxx = x - xo; + + if (tab[code]) { + if (xxx >= 0 && xxx < (nScreenWidth - 15)) { + dst[xxx++] = src[ 0 ^ flipx] | color; + dst[xxx++] = src[ 1 ^ flipx] | color; + dst[xxx++] = src[ 2 ^ flipx] | color; + dst[xxx++] = src[ 3 ^ flipx] | color; + dst[xxx++] = src[ 4 ^ flipx] | color; + dst[xxx++] = src[ 5 ^ flipx] | color; + dst[xxx++] = src[ 6 ^ flipx] | color; + dst[xxx++] = src[ 7 ^ flipx] | color; + dst[xxx++] = src[ 8 ^ flipx] | color; + dst[xxx++] = src[ 9 ^ flipx] | color; + dst[xxx++] = src[10 ^ flipx] | color; + dst[xxx++] = src[11 ^ flipx] | color; + dst[xxx++] = src[12 ^ flipx] | color; + dst[xxx++] = src[13 ^ flipx] | color; + dst[xxx++] = src[14 ^ flipx] | color; + dst[xxx ] = src[15 ^ flipx] | color; + } else { + for (INT32 sx = 0; sx < 16; sx++, xxx++) + { + if (xxx >= 0 && xxx < nScreenWidth) { + dst[xxx] = src[sx ^ flipx] | color; + } + } + } + } else { + if (xxx >= 0 && xxx < (nScreenWidth - 15)) { + for (INT32 sx = 0; sx < 16; sx++, xxx++) { + INT32 pxl = src[sx ^ flipx]; + + if (pxl != 0xff) { + dst[xxx] = pxl | color; + } + } + } else { + for (INT32 sx = 0; sx < 16; sx++, xxx++) { + INT32 pxl = src[sx ^ flipx]; + + if (xxx >= 0 && xxx < nScreenWidth && pxl != 0xff) { + dst[xxx] = pxl | color; + } + } + } + } + } + + dst += nScreenWidth; + } +} + +static void draw_foreground_layer(UINT8 *ram) +{ + UINT16 *vram = (UINT16*)ram; + + INT32 scrolly = DrvScrollBuf[0x200] & 0xff; + INT32 scrollx = (DrvScrollBuf[0x200] >> 16) & 0x1ff; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs*2]; + if (DrvTransTab3[code] == 2) continue; + INT32 attr = vram[offs*2+1]; + + INT32 color = attr & 0x3f; + INT32 flipx = (attr >> 6) & 1; + INT32 flipy = (attr >> 7) & 1; + + if (sx >= 0 && sx < nScreenWidth - 15 && sy >= 0 && sy < nScreenHeight - 15) { + if (DrvTransTab3[code]) { + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } + } + } + } else { + if (DrvTransTab3[code]) { + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0xc00, DrvGfxROM3); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xc00, DrvGfxROM3); + } + } + } + } + } +} + +static void draw_foreground_layer_byline(UINT8 *ram) +{ + UINT16 *vram = (UINT16*)ram; + UINT16 *dst = pTransDraw; + + for (INT32 y = 0; y < nScreenHeight; y++) + { + INT32 scrolly = ((DrvScrollBuf[512 + y] & 0xffff) + y) & 0x0ff; + INT32 scrollx = (DrvScrollBuf[512 + y] >> 16) & 0x1ff; + + INT32 yy = scrolly & 0xf8; + INT32 yo = (scrolly & 0x07) << 3; + INT32 xo = scrollx & 0x07; + + for (INT32 x = 0; x < nScreenWidth + 8; x+=8) + { + INT32 xx = ((scrollx + x) >> 2) & 0x7e; + + INT32 ofst = (yy << 4) | xx; + + INT32 code = vram[ofst]; + if (DrvTransTab3[code] == 2) continue; + INT32 attr = vram[ofst + 1]; + + INT32 color = attr & 0x3f; + INT32 flipx = ((attr >> 6) & 1) * 0x07; + INT32 flipy = ((attr >> 7) & 1) * 0x38; + + color <<= 4; + color |= 0xc00; + + UINT8 *src = DrvGfxROM3 + (code << 6) + (yo ^ flipy); + + INT32 xxx = x - xo; + + if (DrvTransTab3[code]) { + if (xxx >= 0 && xxx < (nScreenWidth - 7)) { + dst[xxx++] = src[0 ^ flipx] | color; + dst[xxx++] = src[1 ^ flipx] | color; + dst[xxx++] = src[2 ^ flipx] | color; + dst[xxx++] = src[3 ^ flipx] | color; + dst[xxx++] = src[4 ^ flipx] | color; + dst[xxx++] = src[5 ^ flipx] | color; + dst[xxx++] = src[6 ^ flipx] | color; + dst[xxx++] = src[7 ^ flipx] | color; + } else { + for (INT32 sx = 0; sx < 8; sx++, xxx++) + { + if (xxx >= 0 && xxx < nScreenWidth) { + dst[xxx] = src[sx ^ flipx] | color; + } + } + } + } else { + if (xxx >= 0 && xxx < (nScreenWidth - 7)) { + for (INT32 sx = 0; sx < 8; sx++, xxx++) { + INT32 pxl = src[sx ^ flipx]; + if (pxl != 0x0f) { + dst[xxx] = pxl | color; + } + } + } else { + for (INT32 sx = 0; sx < 8; sx++, xxx++) { + INT32 pxl = src[sx ^ flipx]; + if (xxx >= 0 && xxx < nScreenWidth && pxl != 0x0f) { + dst[xxx] = pxl | color; + } + } + } + } + } + + dst += nScreenWidth; + } +} + +static void fuuki32_draw_layer(INT32 layer, INT32 buffer) +{ + switch (layer) + { + case 0: + if (nEnableRaster[0]) { + draw_background_layer_byline(DrvBgRAM1, DrvGfxROM1, DrvTransTab1, 0x000, 0); + } else { + draw_background_layer(DrvBgRAM1, DrvGfxROM1, DrvTransTab1, 0x000, 0); + } + return; + + case 1: + if (nEnableRaster[1]) { + draw_background_layer_byline(DrvBgRAM2, DrvGfxROM2, DrvTransTab2, 0x400, 1); + } else { + draw_background_layer(DrvBgRAM2, DrvGfxROM2, DrvTransTab2, 0x400, 1); + } + return; + + case 2: + if (buffer) { + if (nEnableRaster[2]) { + draw_foreground_layer_byline(DrvFgRAM2); + } else { + draw_foreground_layer(DrvFgRAM2); + } + } else { + if (nEnableRaster[2]) { + draw_foreground_layer_byline(DrvFgRAM1); + } else { + draw_foreground_layer(DrvFgRAM1); + } + } + return; + } +} + +static void enable_rasters() +{ + nEnableRaster[0] = nEnableRaster[1] = nEnableRaster[2] = 0; + + for (INT32 i = 0; i < nScreenHeight; i++) { + if (DrvScrollBuf[0x000] != DrvScrollBuf[0x000 + i]) { + nEnableRaster[0] |= 1; + } + + if (DrvScrollBuf[0x100] != DrvScrollBuf[0x100 + i]) { + nEnableRaster[1] |= 1; + } + + if (DrvScrollBuf[0x200] != DrvScrollBuf[0x200 + i]) { + nEnableRaster[2] |= 1; + } + + if (DrvScrollBuf[0x300] != DrvScrollBuf[0x300 + i]) { + nEnableRaster[0] |= 1; + nEnableRaster[1] |= 1; + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x2000 / 2; i++) { + r = (p[i] >> 10) & 0x1f; + g = (p[i] >> 5) & 0x1f; + b = (p[i] >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + UINT32 *vregs = (UINT32*)DrvVidRegs; + + static const INT32 pri_table[6][3] = { + { 0, 1, 2 }, + { 0, 2, 1 }, + { 1, 0, 2 }, + { 1, 2, 0 }, // ? + { 2, 0, 1 }, + { 2, 1, 0 } + }; + + INT32 tm_front = pri_table[ priority[0] ][0]; + INT32 tm_middle = pri_table[ priority[0] ][1]; + INT32 tm_back = pri_table[ priority[0] ][2]; + INT32 buffer = vregs[0x1e/4] & 0x40; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x1fff; + } + + enable_rasters(); + + if (nSpriteEnable & 1) draw_sprites(3); + + fuuki32_draw_layer(tm_back, buffer); + + if (nSpriteEnable & 2) draw_sprites(2); + + fuuki32_draw_layer(tm_middle, buffer); + + if (nSpriteEnable & 4) draw_sprites(1); + + fuuki32_draw_layer(tm_front, buffer); + + if (nSpriteEnable & 8) draw_sprites(0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 0x04); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[2] = 0xff00 | DrvDips[0]; + DrvInputs[3] = (DrvDips[2] << 8) | DrvDips[1]; + } + + SekNewFrame(); + ZetNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 248; // ? + INT32 nCyclesTotal[2] = { 20000000 / 60, 6000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + UINT32 *vregs = (UINT32*)DrvVidRegs; + + SekOpen(0); + ZetOpen(0); + + // 68ec020 timing probably not right... + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + nCyclesDone[0] += SekRun(nSegment - nCyclesDone[0]); + // if (i == 16) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); // raster line -- 0 not 16? + + if (i == DrvRasterPos[0]) { + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + DrvRasterPos[0] = 0x1000; + } + + if (i == 247) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); // level 1 or 8 ? + if (i == 239) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); // vblank + + // hack -- save scroll/offset registers so the + // lines can be drawn in one pass -- should save + // quite a few cycles... + DrvScrollBuf[i + 0x000] = vregs[0]; + DrvScrollBuf[i + 0x100] = vregs[1]; + DrvScrollBuf[i + 0x200] = vregs[2]; + DrvScrollBuf[i + 0x300] = vregs[3]; + } + + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYMF278BUpdate(nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf1, DrvSprBuf0, 0x2000); + memcpy (DrvSprBuf0, DrvSprRAM, 0x2000); + tilebank_buf[1] = tilebank_buf[0]; + tilebank_buf[0] = tilebank[0]; + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029704; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYMF278BScan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(nDrvZ80Bank[0]); + ZetClose(); + } + + return 0; +} + + +// Asura Blade - Sword of Dynasty (Japan) + +static struct BurnRomInfo asurabldRomDesc[] = { + { "pgm3.u1", 0x080000, 0x053e9758, 1 | BRF_PRG | BRF_ESS }, // 0 68ec020 Code + { "pgm2.u2", 0x080000, 0x16b656ca, 1 | BRF_PRG | BRF_ESS }, // 1 + { "pgm1.u3", 0x080000, 0x35104452, 1 | BRF_PRG | BRF_ESS }, // 2 + { "pgm0.u4", 0x080000, 0x68615497, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "srom.u7", 0x080000, 0xbb1deb89, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "pcm.u6", 0x400000, 0xac72225a, 3 | BRF_SND }, // 5 Samples + + { "bg1113.u23", 0x400000, 0x94338267, 4 | BRF_GRA }, // 6 Background Tiles 0 + { "bg1012.u22", 0x400000, 0xd717a0a1, 4 | BRF_GRA }, // 7 + + { "bg2123.u24", 0x400000, 0x4acfc469, 5 | BRF_GRA }, // 8 Background Tiles 1 + { "bg2022.u25", 0x400000, 0xee312cd3, 5 | BRF_GRA }, // 9 + + { "map.u5", 0x200000, 0xe681155e, 6 | BRF_GRA }, // 10 Character Tiles + + { "sp23.u14", 0x400000, 0x7df492eb, 7 | BRF_GRA }, // 11 Sprite Tiles + { "sp45.u15", 0x400000, 0x1890f42a, 7 | BRF_GRA }, // 12 + { "sp67.u16", 0x400000, 0xa48f1ef0, 7 | BRF_GRA }, // 13 + { "sp89.u17", 0x400000, 0x6b024362, 7 | BRF_GRA }, // 14 + { "spab.u18", 0x400000, 0x803d2d8c, 7 | BRF_GRA }, // 15 + { "spcd.u19", 0x400000, 0x42e5c26e, 7 | BRF_GRA }, // 16 +}; + +STD_ROM_PICK(asurabld) +STD_ROM_FN(asurabld) + +struct BurnDriver BurnDrvAsurabld = { + "asurabld", NULL, NULL, NULL, "1998", + "Asura Blade - Sword of Dynasty (Japan)\0", "Imperfect GFX", "Fuuki", "FG-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, asurabldRomInfo, asurabldRomName, NULL, NULL, AsurabldInputInfo, AsurabldDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 320, 240, 4, 3 +}; + + +// Asura Buster - Eternal Warriors (Japan) + +static struct BurnRomInfo asurabusRomDesc[] = { + { "pgm3.u1", 0x080000, 0x2c6b5271, 1 | BRF_PRG | BRF_ESS }, // 0 68ec020 Code + { "pgm2.u2", 0x080000, 0x8f8694ec, 1 | BRF_PRG | BRF_ESS }, // 1 + { "pgm1.u3", 0x080000, 0x0a040f0f, 1 | BRF_PRG | BRF_ESS }, // 2 + { "pgm0.u4", 0x080000, 0x9b71e9d8, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "srom.u7", 0x080000, 0x368da389, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "opm.u6", 0x400000, 0x31b05be4, 3 | BRF_SND }, // 5 Samples + + { "bg1113.u23", 0x400000, 0x5f8657e6, 4 | BRF_GRA }, // 6 Background Tiles 0 + { "bg1012.u22", 0x400000, 0xe3fb9af0, 4 | BRF_GRA }, // 7 + + { "bg2123.u24", 0x400000, 0xc4ebb86b, 5 | BRF_GRA }, // 8 Background Tiles 1 + { "bg2022.u25", 0x400000, 0xf46eda52, 5 | BRF_GRA }, // 9 + + { "map.u5", 0x200000, 0xbd179dc5, 6 | BRF_GRA }, // 10 Character Tiles + + { "sp01.u13", 0x400000, 0x5edea463, 7 | BRF_GRA }, // 11 Sprite Tiles + { "sp23.u14", 0x400000, 0x91b1b0de, 7 | BRF_GRA }, // 12 + { "sp45.u15", 0x400000, 0x96c69aac, 7 | BRF_GRA }, // 13 + { "sp67.u16", 0x400000, 0x7c3d83bf, 7 | BRF_GRA }, // 14 + { "sp89.u17", 0x400000, 0xcb1e14f8, 7 | BRF_GRA }, // 15 + { "spab.u18", 0x400000, 0xe5a4608d, 7 | BRF_GRA }, // 16 + { "spcd.u19", 0x400000, 0x99bfbe32, 7 | BRF_GRA }, // 17 + { "spef.u20", 0x400000, 0xc9c799cc, 7 | BRF_GRA }, // 18 +}; + +STD_ROM_PICK(asurabus) +STD_ROM_FN(asurabus) + +struct BurnDriver BurnDrvAsurabus = { + "asurabus", NULL, NULL, NULL, "2000", + "Asura Buster - Eternal Warriors (Japan)\0", "Imperfect SND, freezes on first boss", "Fuuki", "FG-3", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, asurabusRomInfo, asurabusRomName, NULL, NULL, AsurabldInputInfo, AsurabldDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_gaelco.cpp b/src/burn/drivers/misc_post90s/d_gaelco.cpp new file mode 100644 index 00000000..fc259010 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_gaelco.cpp @@ -0,0 +1,1480 @@ +// FB Alpha Gaelco hardware driver module +// Based on MAME driver by Manuel Abadia with various bits by Nicola Salmoria and Andreas Naive + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "msm6295.h" +#include "burn_ym3812.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv6809ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRegs; +static UINT8 *Drv6809RAM; + +static UINT8 *DrvPrioBitmap; + +static UINT8 *soundlatch; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static INT32 nOkiBank; + +static INT32 gaelco_encryption_param1; +static INT32 has_sound_cpu = 0; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo BigkarnkInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Bigkarnk) + +static struct BurnDIPInfo BigkarnkDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xce, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x12, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play (if Coin B too)" }, + + {0 , 0xfe, 0 , 11, "Coin B" }, + {0x12, 0x01, 0xf0, 0x70, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "Free Play (if Coin A too)" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x13, 0x01, 0x07, 0x07, "0" }, + {0x13, 0x01, 0x07, 0x06, "1" }, + {0x13, 0x01, 0x07, 0x05, "2" }, + {0x13, 0x01, 0x07, 0x04, "3" }, + {0x13, 0x01, 0x07, 0x03, "4" }, + {0x13, 0x01, 0x07, 0x02, "5" }, + {0x13, 0x01, 0x07, 0x01, "6" }, + {0x13, 0x01, 0x07, 0x00, "7" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x18, 0x18, "1" }, + {0x13, 0x01, 0x18, 0x10, "2" }, + {0x13, 0x01, 0x18, 0x08, "3" }, + {0x13, 0x01, 0x18, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Impact" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Go to test mode now" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Bigkarnk) + +static struct BurnDIPInfo ManiacsqDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xf5, NULL }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x11, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play (if Coin B too)" }, + + {0 , 0xfe, 0 , 11, "Coin B" }, + {0x11, 0x01, 0xf0, 0x70, "4 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0x90, "2 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x11, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, + {0x11, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x11, 0x01, 0xf0, 0x00, "Free Play (if Coin A too)" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Sound Type" }, + {0x12, 0x01, 0x08, 0x00, "Stereo" }, + {0x12, 0x01, 0x08, 0x08, "Mono" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0xc0, 0x40, "Easy" }, + {0x12, 0x01, 0xc0, 0xc0, "Normal" }, + {0x12, 0x01, 0xc0, 0x80, "Hard" }, + {0x12, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Maniacsq) + +static struct BurnDIPInfo BiomtoyDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x11, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play (if Coin B too)" }, + + {0 , 0xfe, 0 , 11, "Coin B" }, + {0x11, 0x01, 0xf0, 0x70, "4 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0x90, "2 Coins 1 Credits" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x11, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, + {0x11, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x11, 0x01, 0xf0, 0x00, "Free Play (if Coin A too)" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x30, 0x20, "0" }, + {0x12, 0x01, 0x30, 0x10, "1" }, + {0x12, 0x01, 0x30, 0x30, "2" }, + {0x12, 0x01, 0x30, 0x00, "3" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0xc0, 0x40, "Easy" }, + {0x12, 0x01, 0xc0, 0xc0, "Normal" }, + {0x12, 0x01, 0xc0, 0x80, "Hard" }, + {0x12, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Biomtoy) + +static struct BurnDIPInfo SquashDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xdf, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x02, "6 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x03, "5 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 2 Credits" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 3 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x38, 0x00, "3 Coins 4 Credits" }, + {0x11, 0x01, 0x38, 0x08, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "2 Player Continue" }, + {0x11, 0x01, 0x40, 0x40, "2 Credits / 5 Games" }, + {0x11, 0x01, 0x40, 0x00, "1 Credit / 3 Games" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Number of Faults" }, + {0x12, 0x01, 0x0c, 0x08, "4" }, + {0x12, 0x01, 0x0c, 0x0c, "5" }, + {0x12, 0x01, 0x0c, 0x04, "6" }, + {0x12, 0x01, 0x0c, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Squash) + +static struct BurnDIPInfo ThoopDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xcf, NULL }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x11, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play (if Coin B too)" }, + + {0 , 0xfe, 0 , 2, "2 Cr. Start, 1 Continue" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x03, "Easy" }, + {0x12, 0x01, 0x03, 0x02, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Player Controls" }, + {0x12, 0x01, 0x04, 0x04, "2 Joysticks" }, + {0x12, 0x01, 0x04, 0x00, "1 Joystick" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x18, 0x00, "4" }, + {0x12, 0x01, 0x18, 0x08, "3" }, + {0x12, 0x01, 0x18, 0x10, "2" }, + {0x12, 0x01, 0x18, 0x18, "1" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x40, 0x40, "Upright" }, + {0x12, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Thoop) + +static INT32 decrypt(INT32 const param1, INT32 const param2, INT32 const enc_prev_word, INT32 const dec_prev_word, INT32 const enc_word) +{ + INT32 const swap = (BIT(dec_prev_word, 8) << 1) | BIT(dec_prev_word, 7); + INT32 const type = (BIT(dec_prev_word,12) << 1) | BIT(dec_prev_word, 2); + INT32 res=0; + INT32 k=0; + + switch (swap) + { + case 0: res = BITSWAP16(enc_word, 1, 2, 0,14,12,15, 4, 8,13, 7, 3, 6,11, 5,10, 9); break; + case 1: res = BITSWAP16(enc_word, 14,10, 4,15, 1, 6,12,11, 8, 0, 9,13, 7, 3, 5, 2); break; + case 2: res = BITSWAP16(enc_word, 2,13,15, 1,12, 8,14, 4, 6, 0, 9, 5,10, 7, 3,11); break; + case 3: res = BITSWAP16(enc_word, 3, 8, 1,13,14, 4,15, 0,10, 2, 7,12, 6,11, 9, 5); break; + } + + res ^= param2; + + switch (type) + { + case 0: + k = 0x003a; + break; + + case 1: + k = (BIT(dec_prev_word, 0) << 0) | + (BIT(dec_prev_word, 1) << 1) | + (BIT(dec_prev_word, 1) << 2) | + (BIT(enc_prev_word, 3) << 3) | + (BIT(enc_prev_word, 8) << 4) | + (BIT(enc_prev_word,15) << 5); + break; + + case 2: + k = (BIT(enc_prev_word, 5) << 0) | + (BIT(dec_prev_word, 5) << 1) | + (BIT(enc_prev_word, 7) << 2) | + (BIT(enc_prev_word, 3) << 3) | + (BIT(enc_prev_word,13) << 4) | + (BIT(enc_prev_word,14) << 5); + break; + + case 3: + k = (BIT(enc_prev_word, 0) << 0) | + (BIT(enc_prev_word, 9) << 1) | + (BIT(enc_prev_word, 6) << 2) | + (BIT(dec_prev_word, 4) << 3) | + (BIT(enc_prev_word, 2) << 4) | + (BIT(dec_prev_word,11) << 5); + break; + } + + k ^= param1; + + res = ((res & 0xffc0) | ((res + k) & 0x003f)) ^ param1; + + switch (type) + { + case 0: + k = (BIT(enc_word, 9) << 0) | + (BIT(res,2) << 1) | + (BIT(enc_word, 5) << 2) | + (BIT(res,5) << 3) | + (BIT(res,4) << 4); + break; + + case 1: + k = (BIT(dec_prev_word, 2) << 0) | + (BIT(enc_prev_word, 4) << 1) | + (BIT(dec_prev_word,14) << 2) | + (BIT(res, 1) << 3) | + (BIT(dec_prev_word,12) << 4); + break; + + case 2: + k = (BIT(enc_prev_word, 6) << 0) | + (BIT(dec_prev_word, 6) << 1) | + (BIT(dec_prev_word,15) << 2) | + (BIT(res,0) << 3) | + (BIT(dec_prev_word, 7) << 4); + break; + + case 3: + k = (BIT(dec_prev_word, 2) << 0) | + (BIT(dec_prev_word, 9) << 1) | + (BIT(enc_prev_word, 5) << 2) | + (BIT(dec_prev_word, 1) << 3) | + (BIT(enc_prev_word,10) << 4); + + break; + } + + k ^= param1; + + res = ((res & 0x003f) | ((res + (k << 6)) & 0x07c0) | ((res + (k << 11)) & 0xf800)) ^ ((param1 << 6) | (param1 << 11)); + + return BITSWAP16(res, 2,6,0,11,14,12,7,10,5,4,8,3,9,1,13,15); +} + +UINT16 __fastcall gaelco_decrypt(INT32 offset, INT32 data, INT32 param1, INT32 param2) +{ + static INT32 lastpc, lastoffset, lastencword, lastdecword; + + INT32 thispc = SekGetPC(-1); + + if (lastpc == thispc && offset == lastoffset + 1) + { + lastpc = 0; + data = decrypt(param1, param2, lastencword, lastdecword, data); + } + else + { + lastpc = thispc; + lastoffset = offset; + lastencword = data; + + data = decrypt(param1, param2, 0, 0, data); + + lastdecword = data; + } + + return data; +} + +static void oki_bankswitch(INT32 data) +{ + if (nOkiBank != (data & 0x0f)) { + nOkiBank = data & 0x0f; + memcpy (DrvSndROM + 0x30000, DrvSndROM + 0x40000 + (data & 0x0f) * 0x10000, 0x10000); + } +} + +static void palette_write(INT32 offset) +{ + offset = offset & 0x7fe; + + UINT16 p = *((UINT16*)(DrvPalRAM + offset)); + + INT32 r = (p >> 0) & 0x1f; + INT32 g = (p >> 5) & 0x1f; + INT32 b = (p >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffc000) == 0x100000) { + *((UINT16*)(DrvVidRAM + (address & 0x3ffe))) = gaelco_decrypt((address & 0x3ffe)/2, data, gaelco_encryption_param1, 0x4228); + return; + } + + switch (address) + { + case 0x108000: + case 0x108001: + case 0x108002: + case 0x108003: + case 0x108004: + case 0x108005: + case 0x108006: + case 0x108007: + *((UINT16*)(DrvVidRegs + (address & 0x06))) = data; + return; + + case 0x10800c: + case 0x10800d: + // watchdog + return; + + case 0x70000c: + case 0x70000d: + oki_bankswitch(data); + return; + + case 0x70000e: + case 0x70000f: + MSM6295Command(0, data); + return; + } +} + +void __fastcall main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffc000) == 0x100000) { + return; // encrypted ram write + } + + switch (address) + { + case 0x108000: + case 0x108001: + case 0x108002: + case 0x108003: + case 0x108004: + case 0x108005: + case 0x108006: + case 0x108007: + //DrvVidRegs[(address & 0x07)^1] = data; + return; + + case 0x10800c: + case 0x10800d: + // watchdog + return; + + case 0x70000c: + case 0x70000d: + oki_bankswitch(data); + return; + + case 0x70000e: + case 0x70000f: + if (has_sound_cpu) { + *soundlatch = data; + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); + } else { + MSM6295Command(0, data); + } + return; + } +} + +UINT16 __fastcall main_read_word(UINT32 address) +{ + switch (address) + { + case 0x700000: + case 0x700001: + return DrvDips[1]; + + case 0x700002: + case 0x700003: + return DrvDips[0]; + + case 0x700004: + case 0x700005: + return DrvInputs[0]; + + case 0x700006: + case 0x700007: + return DrvInputs[1]; + + case 0x700008: + case 0x700009: + return DrvInputs[2]; + + case 0x70000e: + case 0x70000f: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT8 __fastcall main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x700000: + case 0x700001: + return DrvDips[1]; + + case 0x700002: + case 0x700003: + return DrvDips[0]; + + case 0x700004: + case 0x700005: + return DrvInputs[0]; + + case 0x700006: + case 0x700007: + return DrvInputs[1]; + + case 0x700008: + case 0x700009: + return DrvInputs[2]; + + case 0x70000e: + case 0x70000f: + return MSM6295ReadStatus(0); + } + + return 0; +} + +void __fastcall palette_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff800) == 0x200000) { + *((UINT16 *)(DrvPalRAM + (address & 0x7fe))) = data; + palette_write(address); + return; + } +} + +void __fastcall palette_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff800) == 0x200000) { + DrvPalRAM[(address & 0x7ff) ^ 1] = data; + palette_write(address); + return; + } +} + +static void sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0800: + case 0x0801: + MSM6295Command(0, data); + return; + + case 0x0a00: + case 0x0a01: + BurnYM3812Write(address & 1, data); + return; + } +} + +static UINT8 sound_read(UINT16 address) +{ + switch (address) + { + case 0x0800: + case 0x0801: + return MSM6295ReadStatus(0); + + case 0x0a00: + case 0x0a01: + return BurnYM3812Read(address & 1); + + case 0x0b00: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)nM6809CyclesTotal * nSoundRate / 2216750; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + BurnYM3812Reset(); + MSM6295Reset(0); + + memcpy (DrvSndROM, DrvSndROM + 0x040000, 0x030000); + + nOkiBank = -1; + oki_bankswitch(3); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + Drv6809ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x140000; + + AllRam = Next; + + DrvPalRAM = Next; Next += 0x000800; + Drv68KRAM = Next; Next += 0x010000; + DrvVidRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x001000; + + DrvVidRegs = Next; Next += 0x000008; + + Drv6809RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + DrvPrioBitmap = Next; Next += 320 * 240; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x0000000, 0x0800000, 0x1000000, 0x1800000 }; + INT32 Plane1[4] = { 0x0400000, 0x0c00000, 0x1400000, 0x1c00000 }; + INT32 XOffs[16] = { 0,1,2,3,4,5,6,7, 16*8+0,16*8+1,16*8+2,16*8+3,16*8+4,16*8+5,16*8+6,16*8+7 }; + INT32 YOffs[16] = { 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8, 8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x400000); + + GfxDecode(0x10000, 4, 8, 8, Plane0, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + GfxDecode(0x04000, 4, 16, 16, Plane1, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 (*pRomLoadCallback)(), INT32 encrypted_ram, INT32 sound_cpu) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pRomLoadCallback) { + if (pRomLoadCallback()) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvVidRAM, 0x100000, 0x103fff, encrypted_ram ? SM_ROM : SM_RAM); + SekMapMemory(DrvPalRAM, 0x200000, 0x2007ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x440000, 0x440fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, main_write_word); + SekSetWriteByteHandler(0, main_write_byte); + SekSetReadWordHandler(0, main_read_word); + SekSetReadByteHandler(0, main_read_byte); + + SekMapHandler(1, 0x200000, 0x2007FF, SM_WRITE); + SekSetWriteWordHandler(1, palette_write_word); + SekSetWriteByteHandler(1, palette_write_byte); + SekClose(); + + has_sound_cpu = sound_cpu ? 1 : 0; + + // big karnak + { + M6809Init(1); + M6809Open(0); + M6809MapMemory(Drv6809RAM, 0x0000, 0x07ff, M6809_RAM); + M6809MapMemory(Drv6809ROM + 0x0c00, 0x0c00, 0xffff, M6809_ROM); + M6809SetReadByteHandler(sound_read); + M6809SetWriteByteHandler(sound_write); + M6809Close(); + + BurnYM3812Init(3580000, NULL, &DrvSynchroniseStream, 0); + BurnTimerAttachM6809YM3812(2216750); + } + + MSM6295Init(0, 1056000 / 132, 100.0, has_sound_cpu ? 1 : 0); + + gaelco_encryption_param1 = encrypted_ram; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static void DrvGfxReorder() +{ + for (INT32 i = 0; i < 0x400000; i++) { + DrvGfxROM0[(i & 0xf3ffff) | ((i & 0x80000) >> 1) | ((i & 0x40000) << 1)] = DrvGfxROM1[i]; + } +} + +static INT32 ThoopRomLoad() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + + DrvGfxReorder(); + + if (BurnLoadRom(DrvSndROM + 0x040000, 6, 1)) return 1; + + return 0; +} + +static INT32 SquashRomLoad() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x180000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x280000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x300000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x380000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x040000, 6, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x0c0000, 6, 1)) return 1; + + return 0; +} + +static INT32 BiomtoyRomLoad() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x280000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x380000, 8, 1)) return 1; + + DrvGfxReorder(); + + if (BurnLoadRom(DrvSndROM + 0x040000, 10, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x0c0000, 11, 1)) return 1; + + return 0; +} + +static INT32 BigkarnkRomLoad() +{ + if (BurnLoadRom(Drv6809ROM + 0x000000, 7, 1)) return 1; + + return SquashRomLoad(); +} + +static INT32 ThoopInit() +{ + return DrvInit(ThoopRomLoad, 0x0e, 0); +} + +static INT32 SquashInit() +{ + return DrvInit(SquashRomLoad, 0x0f, 0); +} + +static INT32 BiomtoyInit() +{ + return DrvInit(BiomtoyRomLoad, 0 /* Ram is not encrypted! */, 0); +} + +static INT32 ManiacspInit() +{ + return DrvInit(SquashRomLoad, 0 /* Ram is not encrypted! */, 0); +} + +static INT32 BigkarnkInit() +{ + return DrvInit(BigkarnkRomLoad, 0 /* Ram is not encrypted! */, 1 /* M6809 Sound CPU */); +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM3812Exit(); + MSM6295Exit(0); + MSM6295ROM = NULL; + + SekExit(); + M6809Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_priority_sprite(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 priority) +{ + if (sx < -7 || sy < -7 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + INT32 flip = (flipy ? 0x38 : 0) | (flipx ? 0x07 : 0); + + UINT8 *gfx = DrvGfxROM0 + (code * 0x40); + + UINT16 *dst; + UINT8 *pri; + + for (INT32 y = 0; y < 8; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + pri = DrvPrioBitmap + sy * nScreenWidth; + + for (INT32 x = 0; x < 8; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((y*8)+x)^flip]; + + if (pxl) { + if (priority & (1 << pri[sx])) continue; + + dst[sx] = pxl | color; + pri[sx] = 15; + } + } + + sx -= 8; + } +} + +static void draw_sprites() +{ + UINT16 *spriteram = (UINT16*)DrvSprRAM; + + for (INT32 i = 0x800 - 4 - 1; i >= 3; i -= 4) + { + INT32 sx = spriteram[i + 2] & 0x01ff; + INT32 sy = (240 - (spriteram[i] & 0x00ff)) & 0x00ff; + INT32 number = spriteram[i + 3]; + INT32 color = (spriteram[i + 2] & 0x7e00) >> 9; + INT32 attr = (spriteram[i] & 0xfe00) >> 9; + INT32 priority = (spriteram[i] & 0x3000) >> 12; + + INT32 xflip = attr & 0x20; + INT32 yflip = attr & 0x40; + INT32 spr_size, pri_mask; + + if (color >= 0x38) priority = 4; + + switch (priority) + { + case 0: pri_mask = 0xff00; break; + case 1: pri_mask = 0xfff0; break; + case 2: pri_mask = 0xfffc; break; + case 3: pri_mask = 0xfffe; break; + default: + case 4: pri_mask = 0; break; + } + + if (attr & 0x04) + spr_size = 1; + else + { + spr_size = 2; + number &= ~3; + } + + for (INT32 y = 0; y < spr_size; y++) + { + for (INT32 x = 0; x < spr_size; x++) + { + INT32 ex = xflip ? (spr_size - 1 - x) : x; + INT32 ey = yflip ? (spr_size - 1 - y) : y; + + draw_priority_sprite(number + (ex * 2) + ey, color << 4, sx-0x0f+x*8, sy+y*8-16, xflip, yflip, pri_mask); + } + } + } +} + +static void draw_layer(INT32 offset, INT32 mask, INT32 category, INT32 priority) +{ + UINT16 *reg = (UINT16*)(DrvVidRegs + (offset / 0x1000) * 4); + UINT16 *ram = (UINT16*)(DrvVidRAM + offset); + + INT32 scrolly = (reg[0] + 16) & 0x1ff; + INT32 scrollx = (reg[1] + (offset ? 0 : 4)) & 0x1ff; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 attr0 = ram[offs * 2 + 0]; + INT32 attr1 = ram[offs * 2 + 1]; + + INT32 code = (attr0 & 0xfffc) >> 2; + INT32 flipy = (attr0 & 0x0002); + INT32 flipx = (attr0 & 0x0001); + INT32 categ = (attr1 & 0x00c0) >> 6; + INT32 color = (attr1 & 0x003f) << 4; + + if (categ != category) continue; + + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x200; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + { + INT32 flip = 0; + if (flipy) flip |= 0xf0; + if (flipx) flip |= 0x0f; + UINT8 *gfx = DrvGfxROM1 + (code * 0x100); + + UINT16 *dest; + UINT8 *prio; + + for (INT32 y = 0; y < 16; y++, sy++) { + if (sy < 0) continue; + if (sy >= nScreenHeight) break; + + dest = pTransDraw + sy * nScreenWidth; + prio = DrvPrioBitmap + sy * nScreenWidth; + + for (INT32 x = 0, xx = sx; x < 16; x++, xx++) { + if (xx < 0) continue; + if (xx >= nScreenWidth) break; + + INT32 pxl = gfx[((y << 4)|x)^flip]; + + if ((mask & (1 << pxl)) == 0) { + dest[xx] = pxl | color; + prio[xx] = priority; + } + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + memset (DrvPrioBitmap, 0, 320 * 240); + BurnTransferClear(); + + draw_layer(0x1000, 0x0001, 3, 0); + draw_layer(0x0000, 0x0001, 3, 0); + draw_layer(0x1000, 0x0001, 2, 1); + draw_layer(0x0000, 0x0001, 2, 1); + draw_layer(0x1000, 0x0001, 1, 2); + draw_layer(0x0000, 0x0001, 1, 2); + draw_layer(0x1000, 0x0001, 0, 4); + draw_layer(0x0000, 0x0001, 0, 4); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 BigkarnkDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + memset (DrvPrioBitmap, 0, 320 * 240); + BurnTransferClear(); + + draw_layer(0x1000, 0x00ff, 3, 0); + draw_layer(0x0000, 0x00ff, 3, 0); + draw_layer(0x1000, 0xff01, 3, 1); + draw_layer(0x0000, 0xff01, 3, 1); + draw_layer(0x1000, 0x00ff, 2, 1); + draw_layer(0x0000, 0x00ff, 2, 1); + draw_layer(0x1000, 0xff01, 2, 2); + draw_layer(0x0000, 0xff01, 2, 2); + draw_layer(0x1000, 0x00ff, 1, 2); + draw_layer(0x0000, 0x00ff, 1, 2); + draw_layer(0x1000, 0xff01, 1, 4); + draw_layer(0x0000, 0xff01, 1, 4); + draw_layer(0x1000, 0x00ff, 0, 4); + draw_layer(0x0000, 0x00ff, 0, 4); + draw_layer(0x1000, 0xff01, 0, 8); + draw_layer(0x0000, 0xff01, 0, 8); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + SekOpen(0); + SekRun(12000000 / 60); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 BigkarnkFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + M6809NewFrame(); + + { + memset (DrvInputs, 0xff, 3 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[2] = (DrvInputs[2] & ~0x02) | (DrvDips[2] & 0x02); + } + + SekOpen(0); + M6809Open(0); + + SekRun(10000000 / 60); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnTimerEndFrameYM3812(2216750 / 60); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + M6809Close(); + + if (pBurnDraw) { + BigkarnkDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + M6809Scan(nAction); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(nOkiBank); + } + + if (nAction & ACB_WRITE) { + INT32 bank = nOkiBank; + nOkiBank = -1; + oki_bankswitch(bank); + } + + return 0; +} + + +// Big Karnak + +static struct BurnRomInfo bigkarnkRomDesc[] = { + { "d16", 0x40000, 0x44fb9c73, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "d19", 0x40000, 0xff79dfdd, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "h5", 0x80000, 0x20e239ff, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "h10", 0x80000, 0xab442855, 2 | BRF_GRA }, // 3 + { "h8", 0x80000, 0x83dce5a3, 2 | BRF_GRA }, // 4 + { "h6", 0x80000, 0x24e84b24, 2 | BRF_GRA }, // 5 + + { "d1", 0x40000, 0x26444ad1, 3 | BRF_SND }, // 6 M6295 Samples + + { "d5", 0x10000, 0x3b73b9c5, 4 | BRF_PRG | BRF_ESS }, // 7 M6809 Code +}; + +STD_ROM_PICK(bigkarnk) +STD_ROM_FN(bigkarnk) + +struct BurnDriver BurnDrvBigkarnk = { + "bigkarnk", NULL, NULL, NULL, "1991", + "Big Karnak\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, bigkarnkRomInfo, bigkarnkRomName, NULL, NULL, BigkarnkInputInfo, BigkarnkDIPInfo, + BigkarnkInit, DrvExit, BigkarnkFrame, BigkarnkDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Maniac Square (prototype) + +static struct BurnRomInfo maniacspRomDesc[] = { + { "d18", 0x20000, 0x740ecab2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "d16", 0x20000, 0xc6c42729, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "f3", 0x40000, 0xe7f6582b, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "f2", 0x40000, 0xca43a5ae, 2 | BRF_GRA }, // 3 + { "f1", 0x40000, 0xfca112e8, 2 | BRF_GRA }, // 4 + { "f0", 0x40000, 0x6e829ee8, 2 | BRF_GRA }, // 5 + + { "c1", 0x80000, 0x2557f2d6, 3 | BRF_SND }, // 6 M6295 Samples +}; + +STD_ROM_PICK(maniacsp) +STD_ROM_FN(maniacsp) + +struct BurnDriver BurnDrvManiacsp = { + "maniacsp", "maniacsq", NULL, NULL, "1996", + "Maniac Square (prototype)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, maniacspRomInfo, maniacspRomName, NULL, NULL, DrvInputInfo, ManiacsqDIPInfo, + ManiacspInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Biomechanical Toy (Ver. 1.0.1885) + +static struct BurnRomInfo biomtoyRomDesc[] = { + { "d18", 0x80000, 0x4569ce64, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "d16", 0x80000, 0x739449bd, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "h6", 0x80000, 0x9416a729, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "j6", 0x80000, 0xe923728b, 2 | BRF_GRA }, // 3 + { "h7", 0x80000, 0x9c984d7b, 2 | BRF_GRA }, // 4 + { "j7", 0x80000, 0x0e18fac2, 2 | BRF_GRA }, // 5 + { "h9", 0x80000, 0x8c1f6718, 2 | BRF_GRA }, // 6 + { "j9", 0x80000, 0x1c93f050, 2 | BRF_GRA }, // 7 + { "h10", 0x80000, 0xaca1702b, 2 | BRF_GRA }, // 8 + { "j10", 0x80000, 0x8e3e96cc, 2 | BRF_GRA }, // 9 + + { "c1", 0x80000, 0x0f02de7e, 3 | BRF_SND }, // 10 M6295 Samples + { "c3", 0x80000, 0x914e4bbc, 3 | BRF_SND }, // 11 +}; + +STD_ROM_PICK(biomtoy) +STD_ROM_FN(biomtoy) + +struct BurnDriver BurnDrvBiomtoy = { + "biomtoy", NULL, NULL, NULL, "1995", + "Biomechanical Toy (Ver. 1.0.1885)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, biomtoyRomInfo, biomtoyRomName, NULL, NULL, DrvInputInfo, BiomtoyDIPInfo, + BiomtoyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Biomechanical Toy (Ver. 1.0.1884) + +static struct BurnRomInfo biomtoyaRomDesc[] = { + { "biomtoya.d18", 0x80000, 0x39b6cdbd, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "biomtoya.d16", 0x80000, 0xab340671, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "h6", 0x80000, 0x9416a729, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "j6", 0x80000, 0xe923728b, 2 | BRF_GRA }, // 3 + { "h7", 0x80000, 0x9c984d7b, 2 | BRF_GRA }, // 4 + { "j7", 0x80000, 0x0e18fac2, 2 | BRF_GRA }, // 5 + { "h9", 0x80000, 0x8c1f6718, 2 | BRF_GRA }, // 6 + { "j9", 0x80000, 0x1c93f050, 2 | BRF_GRA }, // 7 + { "h10", 0x80000, 0xaca1702b, 2 | BRF_GRA }, // 8 + { "j10", 0x80000, 0x8e3e96cc, 2 | BRF_GRA }, // 9 + + { "c1", 0x80000, 0x0f02de7e, 3 | BRF_SND }, // 10 M6295 Samples + { "c3", 0x80000, 0x914e4bbc, 3 | BRF_SND }, // 11 +}; + +STD_ROM_PICK(biomtoya) +STD_ROM_FN(biomtoya) + +struct BurnDriver BurnDrvBiomtoya = { + "biomtoya", "biomtoy", NULL, NULL, "1995", + "Biomechanical Toy (Ver. 1.0.1884)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, biomtoyaRomInfo, biomtoyaRomName, NULL, NULL, DrvInputInfo, BiomtoyDIPInfo, + BiomtoyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Squash (Ver. 1.0) + +static struct BurnRomInfo squashRomDesc[] = { + { "squash.d18", 0x20000, 0xce7aae96, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "squash.d16", 0x20000, 0x8ffaedd7, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "squash.c12", 0x80000, 0x5c440645, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "squash.c11", 0x80000, 0x9e19694d, 2 | BRF_GRA }, // 3 + { "squash.c10", 0x80000, 0x892a035c, 2 | BRF_GRA }, // 4 + { "squash.c09", 0x80000, 0x0bb91c69, 2 | BRF_GRA }, // 5 + + { "squash.d01", 0x80000, 0xa1b9651b, 3 | BRF_SND }, // 6 M6295 Samples +}; + +STD_ROM_PICK(squash) +STD_ROM_FN(squash) + +struct BurnDriver BurnDrvSquash = { + "squash", NULL, NULL, NULL, "1992", + "Squash (Ver. 1.0)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, squashRomInfo, squashRomName, NULL, NULL, DrvInputInfo, SquashDIPInfo, + SquashInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Thunder Hoop (Ver. 1) + +static struct BurnRomInfo thoopRomDesc[] = { + { "th18dea1.040", 0x080000, 0x59bad625, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "th161eb4.020", 0x040000, 0x6add61ed, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "c09", 0x100000, 0x06f0edbf, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "c10", 0x100000, 0x2d227085, 2 | BRF_GRA }, // 3 + { "c11", 0x100000, 0x7403ef7e, 2 | BRF_GRA }, // 4 + { "c12", 0x100000, 0x29a5ca36, 2 | BRF_GRA }, // 5 + + { "sound", 0x100000, 0x99f80961, 3 | BRF_SND }, // 6 M6295 Samples +}; + +STD_ROM_PICK(thoop) +STD_ROM_FN(thoop) + +struct BurnDriver BurnDrvThoop = { + "thoop", NULL, NULL, NULL, "1992", + "Thunder Hoop (Ver. 1)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, thoopRomInfo, thoopRomName, NULL, NULL, DrvInputInfo, ThoopDIPInfo, + ThoopInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_gaiden.cpp b/src/burn/drivers/misc_post90s/d_gaiden.cpp new file mode 100644 index 00000000..7b25556f --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_gaiden.cpp @@ -0,0 +1,2008 @@ +// FB Alpha Ninja Gaiden driver module +// Based on MAME driver by Alex Pasadyn, Phil Stroffolino, Nicola Salmoria, and various others + +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "bitswap.h" + + +static INT32 game = 0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static UINT8 *Mem, *MemEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; + +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfx0Transp; +static UINT8 *DrvGfx1Transp; +static UINT8 *DrvGfx2Transp; + +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvVidRAM2; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static INT32 flipscreen; +static UINT8 soundlatch; + +static INT32 prot; +static INT32 jumpcode; +static INT32 jumppointer; + +static INT32 tx_scroll_x; +static INT32 tx_scroll_y; +static INT32 fg_scroll_x; +static INT32 fg_scroll_y; +static INT32 bg_scroll_x; +static INT32 bg_scroll_y; + + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p1 right" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 6, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 6, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 3"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo RaigaInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p1 right" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Raiga) + +static struct BurnDIPInfo GaidenDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Energy" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0xc0, 0x00, "1" }, + {0x14, 0x01, 0xc0, 0xc0, "2" }, + {0x14, 0x01, 0xc0, 0x40, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, +}; + +STDDIPINFO(Gaiden) + +static struct BurnDIPInfo WildfangDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2 , "Title" }, + {0x14, 0x01, 0x01, 0x01, "Wild Fang" }, + {0x14, 0x01, 0x01, 0x00, "Tecmo Knight" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, // Wild Fang + {0x14, 0x02, 0x0c, 0x0c, "Easy" }, + {0x14, 0x00, 0x01, 0x01, NULL }, + {0x14, 0x02, 0x0c, 0x04, "Normal" }, + {0x14, 0x00, 0x01, 0x01, NULL }, + {0x14, 0x02, 0x0c, 0x08, "Hard" }, + {0x14, 0x00, 0x01, 0x01, NULL }, + {0x14, 0x02, 0x0c, 0x00, "Hardest" }, + {0x14, 0x00, 0x01, 0x01, NULL }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, // Tecmo Knight + {0x14, 0x02, 0x30, 0x30, "Easy" }, + {0x14, 0x00, 0x01, 0x00, NULL }, + {0x14, 0x02, 0x30, 0x10, "Normal" }, + {0x14, 0x00, 0x01, 0x00, NULL }, + {0x14, 0x02, 0x30, 0x20, "Hard" }, + {0x14, 0x00, 0x01, 0x00, NULL }, + {0x14, 0x02, 0x30, 0x00, "Hardest" }, + {0x14, 0x00, 0x01, 0x00, NULL }, + + {0 , 0xfe, 0 , 3 , "Lives" }, + {0x14, 0x01, 0xc0, 0x80, "1" }, + {0x14, 0x01, 0xc0, 0xc0, "2" }, + {0x14, 0x01, 0xc0, 0x40, "3" }, +// {0x14, 0x01, 0xc0, 0x00, "2" }, +}; + +STDDIPINFO(Wildfang) + +static struct BurnDIPInfo TknightDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x30, 0x30, "Easy" }, + {0x14, 0x01, 0x30, 0x10, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3 , "Lives" }, + {0x14, 0x01, 0xc0, 0x80, "1" }, + {0x14, 0x01, 0xc0, 0xc0, "2" }, + {0x14, 0x01, 0xc0, 0x40, "3" }, +// {0x14, 0x01, 0xc0, 0x00, "2" }, +}; + +STDDIPINFO(Tknight) + +static struct BurnDIPInfo DrgnbowlDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x04, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Energy" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0xc0, 0x00, "1" }, + {0x14, 0x01, 0xc0, 0xc0, "2" }, + {0x14, 0x01, 0xc0, 0x40, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, +}; + +STDDIPINFO(Drgnbowl) + +static struct BurnDIPInfo RaigaDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x5f, NULL }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x11, 0x01, 0xf0, 0x00, "5 Coins 1 Credit" }, + {0x11, 0x01, 0xf0, 0x40, "4 Coins 1 Credit" }, + {0x11, 0x01, 0xf0, 0xa0, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xf0, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xf0, 0x20, "3 Coins 2 Credits" }, + {0x11, 0x01, 0xf0, 0x80, "4 Coins 3 Credits" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xf0, 0xc0, "3 Coins 4 Credits" }, + {0x11, 0x01, 0xf0, 0xe0, "2 Coins 3 Credits" }, + {0x11, 0x01, 0xf0, 0x70, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x11, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x11, 0x01, 0x0f, 0x00, "5 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x04, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0a, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x01, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x02, "3 Coins 2 Credits" }, + {0x11, 0x01, 0x0f, 0x08, "4 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0c, "3 Coins 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0e, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x07, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x11, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x03, 0x03, "50k 200k" }, + {0x12, 0x01, 0x03, 0x01, "100k 300k" }, + {0x12, 0x01, 0x03, 0x02, "50k only" }, + {0x12, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x00, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x08, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x30, 0x30, "Easy" }, + {0x12, 0x01, 0x30, 0x10, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Raiga) + +static const INT32 jumppoints_00[0x100] = +{ + 0x6669, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1,0x4a46, -1, + -1,0x6704, -2, -1, -1, -1, -1, -1, + -1, -2, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -2, -1, -1, -1, -1,0x4e75, -1, -1, + -1, -2, -1,0x4e71,0x60fc, -1,0x7288, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const INT32 jumppoints_other[0x100] = +{ + 0x5457,0x494e,0x5f4b,0x4149,0x5345,0x525f,0x4d49,0x5941, + 0x5241,0x5349,0x4d4f,0x4a49, -1, -1, -1, -1, + -1, -1, -2,0x594f, -1,0x4e75, -1, -1, + -1, -2, -1, -1,0x4e75, -1,0x5349, -1, + -1, -1, -1,0x4e75, -1,0x4849, -1, -1, + -2, -1, -1,0x524f, -1, -1, -1, -1, + -1, -2, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const INT32 wildfang_jumppoints[0x100] = +{ + 0x0c0c,0x0cac,0x0d42,0x0da2,0x0eea,0x112e,0x1300,0x13fa, + 0x159a,0x1630,0x109a,0x1700,0x1750,0x1806,0x18d6,0x1a44, + 0x1b52, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const INT32 *jumppoints; + +static void protection_w(UINT8 data) +{ + switch (data & 0xf0) + { + case 0x00: // init + prot = 0x00; + break; + + case 0x10: // high 4 bits of jump code + jumpcode = (data & 0x0f) << 4; + prot = 0x10; + break; + + case 0x20: // low 4 bits of jump code + jumpcode |= data & 0x0f; + if (jumppoints[jumpcode] == -2) { + jumppoints = jumppoints_other; + jumppointer = 1; + } + + if (jumppoints[jumpcode] == -1) { + jumpcode = 0; + } + prot = 0x20; + break; + + case 0x30: // bits 12-15 of function address + prot = 0x40 | ((jumppoints[jumpcode] >> 12) & 0x0f); + break; + + case 0x40: // bits 8-11 of function address + prot = 0x50 | ((jumppoints[jumpcode] >> 8) & 0x0f); + break; + + case 0x50: // bits 4-7 of function address + prot = 0x60 | ((jumppoints[jumpcode] >> 4) & 0x0f); + break; + + case 0x60: // bits 0-3 of function address + prot = 0x70 | ((jumppoints[jumpcode] >> 0) & 0x0f); + break; + } +} + +static UINT8 protection_r() +{ + return prot; +} + + +static void palette_write(INT32 offset, UINT16 pal) +{ + UINT8 b = (pal >> 8) & 0x0f; + UINT8 g = (pal >> 4) & 0x0f; + UINT8 r = (pal >> 0) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + Palette[offset] = (r << 16) | (g << 8) | b; + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +UINT8 __fastcall gaiden_read_byte(UINT32 address) +{ + switch (address) + { + case 0x07a001: + return DrvInputs[0]; + + case 0x07a002: + return DrvInputs[2]; + + case 0x07a003: + return DrvInputs[1]; + + case 0x07a004: + return DrvDips[1]; + + case 0x07a005: + return DrvDips[0]; + + case 0x07a007: // Raiga, Wild Fang + return protection_r(); + } + + return 0; +} + +UINT16 __fastcall gaiden_read_word(UINT32 address) +{ + switch (address) + { + case 0x07a000: + return DrvInputs[0]; + + case 0x07a002: + return (DrvInputs[2] << 8) | DrvInputs[1]; + + case 0x07a004: + return (DrvDips[1] << 8) | DrvDips[0]; + } + + return 0; +} + +void __fastcall gaiden_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffffe000) == 0x78000) { + address &= 0x1fff; + + DrvPalRAM[address ^ 1] = data; + + palette_write(address>>1, *((UINT16*)(DrvPalRAM + (address & ~1)))); + + return; + } + + switch (address) + { + case 0x7a00e: // Dragon Bowl + soundlatch = data; + ZetRaiseIrq(0); + return; + + case 0x7a802: // Tecmo Knight + case 0x7a803: // Ninja Gaiden + soundlatch = data; + ZetNmi(); + return; + + case 0x7a804: // Raiga, Wild Fang + protection_w(data); + return; + + } +} + +void __fastcall gaiden_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffffe000) == 0x78000) { + address &= 0x1ffe; + + *((UINT16*)(DrvPalRAM + address)) = data; + + palette_write(address>>1, *((UINT16*)(DrvPalRAM + address))); + + return; + } + + switch (address & 0xfffffffe) + { + case 0x7a104: + tx_scroll_y = data & 0x1ff; + return; + + case 0x7a10c: + tx_scroll_x = data & 0x3ff; + return; + + case 0x7a204: + fg_scroll_y = data & 0x1ff; + return; + + case 0x7a20c: + fg_scroll_x = data & 0x3ff; + return; + + case 0x7a304: + bg_scroll_y = data & 0x1ff; + return; + + case 0x7a30c: + bg_scroll_x = data & 0x3ff; + return; + + + case 0x7a808: + flipscreen = data & 1; + return; + + // Dragon Bowl + case 0x7f000: + bg_scroll_y = data & 0x1ff; + return; + + case 0x7f002: + bg_scroll_x = (data + 248) & 0x3ff; + return; + + case 0x7f004: + fg_scroll_y = data & 0x1ff; + return; + + case 0x7f006: + fg_scroll_x = (data + 252) & 0x3ff; + return; + } +} + + +void __fastcall gaiden_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + MSM6295Command(0, data); + return; + + case 0xf810: + BurnYM2203Write(0, 0, data); + return; + + case 0xf811: + BurnYM2203Write(0, 1, data); + return; + + case 0xf820: + BurnYM2203Write(1, 0, data); + return; + + case 0xf821: + BurnYM2203Write(1, 1, data); + return; + } +} + +UINT8 __fastcall gaiden_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + return MSM6295ReadStatus(0); + + case 0xfc00: + return 0; + + case 0xfc20: + return soundlatch; + } + + return 0; +} + + +void __fastcall drgnbowl_sound_write(UINT16 address, UINT8 data) +{ + switch (address & 0xff) + { + case 0x00: + BurnYM2151SelectRegister(data); + return; + + case 0x01: + BurnYM2151WriteRegister(data); + return; + + case 0x80: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall drgnbowl_sound_read(UINT16 address) +{ + switch (address & 0xff) + { + case 0x01: + return BurnYM2151ReadStatus(); + + case 0x80: + return MSM6295ReadStatus(0); + + case 0xc0: + return soundlatch; + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KROM = Next; Next += 0x0040000; + DrvZ80ROM = Next; Next += 0x0010000; + + DrvGfxROM0 = Next; Next += 0x0020000; + DrvGfxROM1 = Next; Next += 0x0100000; + DrvGfxROM2 = Next; Next += 0x0100000; + DrvGfxROM3 = Next; Next += 0x0200000; + + DrvGfx0Transp = Next; Next += 0x0000800; + DrvGfx1Transp = Next; Next += 0x0001000; + DrvGfx2Transp = Next; Next += 0x0001000; + + MSM6295ROM = Next; Next += 0x0040000; + + DrvPalette = (UINT32*)Next; Next += 0x1000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x0004000; + DrvVidRAM0 = Next; Next += 0x0001000; + DrvVidRAM1 = Next; Next += 0x0002000; + DrvVidRAM2 = Next; Next += 0x0002000; + DrvSprRAM = Next; Next += 0x0002000; + DrvPalRAM = Next; Next += 0x0002000; + + DrvZ80RAM = Next; Next += 0x0000800; + + Palette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + soundlatch = 0; + tx_scroll_x = 0; + tx_scroll_y = 0; + fg_scroll_x = 0; + fg_scroll_y = 0; + bg_scroll_x = 0; + bg_scroll_y = 0; + + flipscreen = 0; + + prot = 0; + jumpcode = 0; + jumppointer = 0; + + if (game == 2) { + jumppoints = jumppoints_00; + } else { + jumppoints = wildfang_jumppoints; + } + + prot = 0; + jumpcode = 0; + + DrvReset = 0; + + DrvRecalc = 1; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + if (game == 1) { + BurnYM2151Reset(); + } else { + BurnYM2203Reset(); + } + + SetCurrentFrame(0); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + static INT32 Planes[4] = { 0x000, 0x001, 0x002, 0x003 }; + static INT32 TileXOffsets[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x100, 0x104, 0x108, 0x10c, 0x110, 0x114, 0x118, 0x11c }; + static INT32 TileYOffsets[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + static INT32 SpriteXOffsets[8] = { 0x000000, 0x000004, 0x400000, 0x400004, + 0x000008, 0x00000c, 0x400008, 0x40000c }; + static INT32 SpriteYOffsets[8] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x010000); + + GfxDecode(0x00800, 4, 8, 8, Planes, TileXOffsets, TileYOffsets, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x080000); + + GfxDecode(0x01000, 4, 16, 16, Planes, TileXOffsets, TileYOffsets, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(0x01000, 4, 16, 16, Planes, TileXOffsets, TileYOffsets, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x100000); + + GfxDecode(0x08000, 4, 8, 8, Planes, SpriteXOffsets, SpriteYOffsets, 0x080, tmp, DrvGfxROM3); + + BurnFree (tmp); + + // Make transparency tables + { + memset(DrvGfx0Transp, 2, 0x0800); + for (INT32 i = 0; i < 0x20000; i++) { + if (DrvGfxROM0[i] != 0) DrvGfx0Transp[i>>6] |= 1; + if (DrvGfxROM0[i] == 0) DrvGfx0Transp[i>>6] &= ~2; + } + + memset(DrvGfx1Transp, 2, 0x1000); + memset(DrvGfx2Transp, 2, 0x1000); + for (INT32 i = 0; i < 0x100000; i++) { + if (DrvGfxROM1[i] != 0) DrvGfx1Transp[i>>8] |= 1; + if (DrvGfxROM1[i] == 0) DrvGfx1Transp[i>>8] &= ~2; + if (DrvGfxROM2[i] != 0) DrvGfx2Transp[i>>8] |= 1; + if (DrvGfxROM2[i] == 0) DrvGfx2Transp[i>>8] &= ~2; + } + } + + return 0; +} + +static INT32 drgnbowlDecode() +{ + UINT8 *buf = (UINT8*)BurnMalloc(0x100000); + if (buf == NULL) { + return 1; + } + + memcpy (buf, Drv68KROM, 0x40000); + + for (INT32 i = 0; i < 0x40000; i++) { + Drv68KROM[i] = buf[BITSWAP24(i,23,22,21,20,19,18,17,15,16,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)]; + } + + for (INT32 i = 0; i < 0x100000; i++) { + buf[i] = DrvGfxROM1[BITSWAP24(i,23,22,21,20,19,18,16,17,15,14,13,4,3,12,11,10,9,8,7,6,5,2,1,0)]; + } + + static INT32 CharPlanes[4] = { 0, 1, 2, 3 }; + static INT32 CharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; + static INT32 CharYOffsets[8] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0 }; + + static INT32 Planes[4] = { 0x600000, 0x400000, 0x200000, 0x000000 }; + static INT32 XOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; + static INT32 YOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + GfxDecode(0x02000, 4, 16, 16, Planes, XOffsets, YOffsets, 0x100, buf, DrvGfxROM1); + + memcpy (buf, DrvGfxROM3, 0x100000); + + for (INT32 i = 0; i < 0x100000; i++) buf[i] ^= 0xff; + + GfxDecode(0x02000, 4, 16, 16, Planes, XOffsets, YOffsets, 0x100, buf, DrvGfxROM3); + + memcpy (buf, DrvGfxROM0, 0x010000); + + GfxDecode(0x00800, 4, 8, 8, CharPlanes, CharXOffsets, CharYOffsets, 0x100, buf, DrvGfxROM0); + + BurnFree (buf); + + // Make transparency tables + { + memset(DrvGfx0Transp, 2, 0x0800); + for (INT32 i = 0; i < 0x20000; i++) { + if (DrvGfxROM0[i] != 0xf) DrvGfx0Transp[i>>6] |= 1; + if (DrvGfxROM0[i] == 0xf) DrvGfx0Transp[i>>6] &= ~2; + } + + memset(DrvGfx1Transp, 3, 0x1000); + memset(DrvGfx2Transp, 2, 0x1000); + for (INT32 i = 0; i < 0x100000; i++) { + if (DrvGfxROM2[i] != 0xf) DrvGfx2Transp[i>>8] |= 1; + if (DrvGfxROM2[i] == 0xf) DrvGfx2Transp[i>>8] &= ~2; + + } + } + + return 0; +} + +static INT32 DrvGetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *Load68K = Drv68KROM; + UINT8 *LoadZ80 = DrvZ80ROM; + UINT8 *LoadG0 = DrvGfxROM0; + UINT8 *LoadG1 = DrvGfxROM1; + UINT8 *LoadG2 = DrvGfxROM2; + UINT8 *LoadG3 = DrvGfxROM3; + UINT8 *LoadSND = MSM6295ROM; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(Load68K + 1, i + 0, 2)) return 1; + if (BurnLoadRom(Load68K + 0, i + 1, 2)) return 1; + Load68K += ri.nLen * 2; + i++; + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(LoadZ80, i, 1)) return 1; + LoadZ80 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(LoadG0, i, 1)) return 1; + LoadG0 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(LoadG1, i, 1)) return 1; + LoadG1 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 5) { + if (BurnLoadRom(LoadG2, i, 1)) return 1; + LoadG2 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 6) { + if (BurnLoadRom(LoadG3, i, 1)) return 1; + LoadG3 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 7) { + if (BurnLoadRom(LoadSND, i, 1)) return 1; + LoadSND += ri.nLen; + continue; + } + } + + return 0; +} + +inline static void DrvYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + if (DrvGetRoms()) return 1; + if (game == 1) { + if (drgnbowlDecode()) return 1; + } else { + if (DrvGfxDecode()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x070000, 0x070fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x072000, 0x073fff, SM_RAM); + SekMapMemory(DrvVidRAM2, 0x074000, 0x075fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x076000, 0x077fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x078000, 0x079fff, SM_ROM); + SekSetWriteByteHandler(0, gaiden_write_byte); + SekSetWriteWordHandler(0, gaiden_write_word); + SekSetReadByteHandler(0, gaiden_read_byte); + SekSetReadWordHandler(0, gaiden_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + if (game == 1) { + ZetMapArea(0x0000, 0xf7ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xf7ff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(drgnbowl_sound_write); + ZetSetInHandler(drgnbowl_sound_read); + } else { + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(gaiden_sound_write); + ZetSetReadHandler(gaiden_sound_read); + } + ZetMemEnd(); + ZetClose(); + + if (game == 1) { + BurnYM2151Init(4000000, 100.0); + } else { + BurnYM2203Init(2, 4000000, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + } + + MSM6295Init(0, 1000000 / 132, 80, 1); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + ZetExit(); + + MSM6295Exit(0); + if (game == 1) { + BurnYM2151Exit(); + } else { + BurnYM2203Exit(); + } + + GenericTilesExit(); + + BurnFree (Mem); + + game = 0; + + return 0; +} + +static void gaiden_draw_sprites(INT32 prior) +{ + static const UINT8 layout[8][8] = + { + { 0, 1, 4, 5,16,17,20,21}, + { 2, 3, 6, 7,18,19,22,23}, + { 8, 9,12,13,24,25,28,29}, + {10,11,14,15,26,27,30,31}, + {32,33,36,37,48,49,52,53}, + {34,35,38,39,50,51,54,55}, + {40,41,44,45,56,57,60,61}, + {42,43,46,47,58,59,62,63} + }; + + INT32 count = 0; + const UINT16 *source = (UINT16*)DrvSprRAM; + + while (count < 256) + { + INT32 attributes = source[0]; + INT32 col,row; + + if (attributes & 0x04) + { + INT32 priority = (attributes >> 6) & 3; + + if (priority != prior) goto skip_sprite; + + INT32 flipx = (attributes & 1); + INT32 flipy = (attributes & 2); + + INT32 color = source[2]; + INT32 sizex = 1 << (color & 3); + INT32 sizey = 1 << ((color >> (game & 2)) & 3); + + INT32 number = (source[1] & (sizex > 2 ? 0x7ff8 : 0x7ffc)); // raiga + + INT32 ypos = source[3] & 0x01ff; + INT32 xpos = source[4] & 0x01ff; + + if ((attributes & 0x20) && (GetCurrentFrame() & 1)) + goto skip_sprite; + + color = (color >> 4) & 0x0f; + + if (xpos >= 256) + xpos -= 512; + + if (ypos >= 256) + ypos -= 512; + + if (flipscreen) + { + flipx = !flipx; + flipy = !flipy; + + xpos = 256 - (sizex << 3) - xpos; + ypos = 256 - (sizey << 3) - ypos; + + if (xpos <= -256) + xpos += 512; + + if (ypos <= -256) + ypos += 512; + } + + for (row = 0; row < sizey; row++) + { + for (col = 0; col < sizex; col++) + { + INT32 sx = xpos + ((flipx ? (sizex - 1 - col) : col) << 3); + INT32 sy = ypos + ((flipy ? (sizey - 1 - row) : row) << 3); + + sy -= 16; + + if (sx < -15 || sx > 255 || sy < - 15 || sy > 223) continue; + + if (sx >= 0 && sx <= 240 && sy >= 0 && sy <= 208) { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render8x8Tile_Mask(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, number + layout[row][col], sx, sy, color, 4, 0, 0, DrvGfxROM3); + } + } + } + } + } + } +skip_sprite: + source += 8; + count++; + } +} + +static void drgnbowl_draw_sprites(INT32 priority) +{ + UINT16 *spriteram16 = (UINT16*)DrvSprRAM; + + INT32 i, code, color, x, y, flipx, flipy; + + for (i = 0x400 - 4; i >= 0; i -= 4) + { + if ((spriteram16[i + 3] & 0x20) != priority) + continue; + + code = (spriteram16[i] & 0xff) | ((spriteram16[i + 3] & 0x1f) << 8); + y = 256 - (spriteram16[i + 1] & 0xff) - 12; + x = spriteram16[i + 2] & 0xff; + color = spriteram16[0x400 + i] & 0x0f; + flipx = spriteram16[i + 3] & 0x40; + flipy = spriteram16[i + 3] & 0x80; + + if(spriteram16[0x400 + i] & 0x80) + x -= 256; + + x += 256; + + y -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x, y, color, 4, 0xf, 0x100, DrvGfxROM3); + if (x >= 497) Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x - 512, y, color, 4, 0xf, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x, y, color, 4, 0xf, 0x100, DrvGfxROM3); + if (x >= 497) Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x - 512, y, color, 4, 0xf, 0x100, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y, color, 4, 0xf, 0x100, DrvGfxROM3); + if (x >= 497) Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x - 512, y, color, 4, 0xf, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y, color, 4, 0xf, 0x100, DrvGfxROM3); + if (x >= 497) Render16x16Tile_Mask_Clip(pTransDraw, code, x - 512, y, color, 4, 0xf, 0x100, DrvGfxROM3); + } + } + } +} + +static void draw_layer(UINT16 *vidram, UINT8 *gfxbase, INT32 palette_offset, UINT16 scrollx, UINT16 scrolly, UINT8 *transptab, INT32 transp) +{ + for (INT32 offs = 0; offs < 0x800; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + sx -= scrollx; + sy -= scrolly; + + if (sx < -15) sx += 1024; + if (sy < -15) sy += 512; + if (sy >= 0x100 || sx >= 0x100) continue; + + if (flipscreen) { + sy = 0x1ff - sy; + sx = 0x3ff - sx; + sy -= 0x110; + sx -= 0x310; + } + + sy -= 16; + + INT32 code = vidram[0x0800 + offs] & 0x0fff; + INT32 color = (vidram[offs] >> 4) & 0x0f; + + if (game == 2) { //raiga + if (palette_offset == 0x300) { + color |= (vidram[offs] & 0x08) << 4; + } + } + + if (sy >= 0 && sy <= 208 && sx >= 0 && sx <= 240) { + if (transptab[code] & 1) { + if (transptab[code] & 2) { + if (flipscreen) { + Render16x16Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, palette_offset, gfxbase); + } else { + Render16x16Tile(pTransDraw, code, sx, sy, color, 4, palette_offset, gfxbase); + } + } else { + if (flipscreen) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, transp, palette_offset, gfxbase); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, transp, palette_offset, gfxbase); + } + } + } + } else { + if (transptab[code] & 1) { + if (transptab[code] & 2) { + if (flipscreen) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, palette_offset, gfxbase); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, palette_offset, gfxbase); + } + } else { + if (flipscreen) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, transp, palette_offset, gfxbase); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, transp, palette_offset, gfxbase); + } + } + } + } + } +} + +static void draw_text(INT32 paloffset, INT32 transp) +{ + UINT16 *vidram = (UINT16*)DrvVidRAM0; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 2) & 0xf8; + + if (flipscreen) { + sy = 0xf8 - sy; + sx = 0xf8 - sx; + } + + sx -= tx_scroll_x; + sy -= tx_scroll_y + 16; + + // tx_scroll is used? + + INT32 code = vidram[0x400 + offs] & 0x07ff; + INT32 color = (vidram[0x000 + offs] >> 4) & 0x0f; + + if (!code) continue; + + if (sy >= 0 && sy <= 216 && sx >= 0 && sx <= 248) { + if (DrvGfx0Transp[code] & 1) { + if (DrvGfx0Transp[code] & 2) { + if (flipscreen) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, paloffset, DrvGfxROM0); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, paloffset, DrvGfxROM0); + } + } else { + if (flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, transp, paloffset, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, transp, paloffset, DrvGfxROM0); + } + } + } + } else { + if (DrvGfx0Transp[code] & 1) { + if (DrvGfx0Transp[code] & 2) { + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, paloffset, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, paloffset, DrvGfxROM0); + } + } else { + if (flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, transp, paloffset, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, transp, paloffset, DrvGfxROM0); + } + } + } + } + } +} + +static INT32 DrgnbowlDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + { + for (INT32 offs = 0; offs < nScreenWidth * nScreenHeight; offs++) { + pTransDraw[offs] = 0; + } + } + + draw_layer((UINT16*)DrvVidRAM2, DrvGfxROM1, 0x300, bg_scroll_x, bg_scroll_y, DrvGfx1Transp, -1); // no transp + drgnbowl_draw_sprites(0x20); + draw_layer((UINT16*)DrvVidRAM1, DrvGfxROM2, 0x200, fg_scroll_x, fg_scroll_y, DrvGfx2Transp, 0xf); + drgnbowl_draw_sprites(0x00); + draw_text(0, 0x0f); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + { + for (INT32 offs = 0; offs < nScreenWidth * nScreenHeight; offs++) { + pTransDraw[offs] = 0x200; + } + } + + gaiden_draw_sprites(3); + draw_layer((UINT16*)DrvVidRAM2, DrvGfxROM1, 0x300, bg_scroll_x, bg_scroll_y, DrvGfx1Transp, 0); + gaiden_draw_sprites(2); + draw_layer((UINT16*)DrvVidRAM1, DrvGfxROM2, 0x200, fg_scroll_x, fg_scroll_y, DrvGfx2Transp, 0); + gaiden_draw_sprites(1); + draw_text(0x100,0); + gaiden_draw_sprites(0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nCyclesTotal[2] = { (game == 1 ? 10000000 : 9216000) / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + nCurrentCPU = 1; + if (game == 1) { + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } else { + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + } + + if (pBurnSoundOut && game == 1) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (game != 1) BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + if (game == 1) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } else { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + if (game == 1) { + DrgnbowlDraw(); + } else { + DrvDraw(); + } + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029523; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + MSM6295Scan(0, nAction); + + if (game == 1) { + BurnYM2151Scan(nAction); + } else { + BurnYM2203Scan(nAction, pnMin); + } + + SCAN_VAR(prot); + SCAN_VAR(jumpcode); + SCAN_VAR(jumppointer); + + SCAN_VAR(tx_scroll_x); + SCAN_VAR(tx_scroll_y); + SCAN_VAR(fg_scroll_x); + SCAN_VAR(fg_scroll_y); + SCAN_VAR(bg_scroll_x); + SCAN_VAR(bg_scroll_y); + + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen); + + if (jumppointer) { + jumppoints = jumppoints_other; + } + } + + return 0; +} + + +// Shadow Warriors (World, set 1) + +static struct BurnRomInfo shadowwRomDesc[] = { + { "shadowa_1.3s", 0x20000, 0x8290d567, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "shadowa_2.4s", 0x20000, 0xf3f08921, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gaiden_3.4b", 0x10000, 0x75fd3e6a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "gaiden_5.7a", 0x10000, 0x8d4035f7, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x1ecfddaa, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x1291a696, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x140b47ca, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0x7638cccb, 4 | BRF_GRA }, // 7 + + { "18.6a", 0x20000, 0x3fadafd6, 5 | BRF_GRA }, // 8 Background Tiles + { "19.6b", 0x20000, 0xddae9d5b, 5 | BRF_GRA }, // 9 + { "20.4b", 0x20000, 0x08cf7a93, 5 | BRF_GRA }, // 10 + { "21.4b", 0x20000, 0x1ac892f5, 5 | BRF_GRA }, // 11 + + { "6.3m", 0x20000, 0xe7ccdf9f, 6 | BRF_GRA }, // 12 Sprites + { "8.3n", 0x20000, 0x7ef7f880, 6 | BRF_GRA }, // 13 + { "10.3r", 0x20000, 0xa6451dec, 6 | BRF_GRA }, // 14 + { "shadoww_12a.xx", 0x10000, 0x9bb07731, 6 | BRF_GRA }, // 15 + { "shadoww_12b.xx", 0x10000, 0xa4a950a2, 6 | BRF_GRA }, // 16 + { "7.1m", 0x20000, 0x016bec95, 6 | BRF_GRA }, // 17 + { "9.1n", 0x20000, 0x6e9b7fd3, 6 | BRF_GRA }, // 18 + { "11.1r", 0x20000, 0x7fbfdf5e, 6 | BRF_GRA }, // 19 + { "shadoww_13a.xx", 0x10000, 0x996d2fa5, 6 | BRF_GRA }, // 20 + { "shadoww_13b.xx", 0x10000, 0xb8df8a34, 6 | BRF_GRA }, // 21 + + { "4.4a", 0x20000, 0xb0e0faf9, 7 | BRF_SND }, // 22 MSM6295 Samples +}; + +STD_ROM_PICK(shadoww) +STD_ROM_FN(shadoww) + +struct BurnDriver BurnDrvShadoww = { + "shadoww", NULL, NULL, NULL, "1988", + "Shadow Warriors (World, set 1)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, shadowwRomInfo, shadowwRomName, NULL, NULL, DrvInputInfo, GaidenDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Shadow Warriors (World, set 2) + +static struct BurnRomInfo shadowwaRomDesc[] = { + { "shadoww_1.3s", 0x20000, 0xfefba387, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "shadoww_2.4s", 0x20000, 0x9b9d6b18, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gaiden_3.4b", 0x10000, 0x75fd3e6a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "gaiden_5.7a", 0x10000, 0x8d4035f7, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x1ecfddaa, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x1291a696, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x140b47ca, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0x7638cccb, 4 | BRF_GRA }, // 7 + + { "18.6a", 0x20000, 0x3fadafd6, 5 | BRF_GRA }, // 8 Background Tiles + { "19.6b", 0x20000, 0xddae9d5b, 5 | BRF_GRA }, // 9 + { "20.4b", 0x20000, 0x08cf7a93, 5 | BRF_GRA }, // 10 + { "21.4b", 0x20000, 0x1ac892f5, 5 | BRF_GRA }, // 11 + + { "6.3m", 0x20000, 0xe7ccdf9f, 6 | BRF_GRA }, // 12 Sprites + { "8.3n", 0x20000, 0x7ef7f880, 6 | BRF_GRA }, // 13 + { "10.3r", 0x20000, 0xa6451dec, 6 | BRF_GRA }, // 14 + { "shadoww_12a.xx", 0x10000, 0x9bb07731, 6 | BRF_GRA }, // 15 + { "shadoww_12b.xx", 0x10000, 0xa4a950a2, 6 | BRF_GRA }, // 16 + { "7.1m", 0x20000, 0x016bec95, 6 | BRF_GRA }, // 17 + { "9.1n", 0x20000, 0x6e9b7fd3, 6 | BRF_GRA }, // 18 + { "11.1r", 0x20000, 0x7fbfdf5e, 6 | BRF_GRA }, // 19 + { "shadoww_13a.xx", 0x10000, 0x996d2fa5, 6 | BRF_GRA }, // 20 + { "shadoww_13b.xx", 0x10000, 0xb8df8a34, 6 | BRF_GRA }, // 21 + + { "4.4a", 0x20000, 0xb0e0faf9, 7 | BRF_SND }, // 22 MSM6295 Samples +}; + +STD_ROM_PICK(shadowwa) +STD_ROM_FN(shadowwa) + +struct BurnDriver BurnDrvShadowwa = { + "shadowwa", "shadoww", NULL, NULL, "1988", + "Shadow Warriors (World, set 2)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, shadowwaRomInfo, shadowwaRomName, NULL, NULL, DrvInputInfo, GaidenDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Ninja Gaiden (US) + +static struct BurnRomInfo gaidenRomDesc[] = { + { "gaiden_1.3s", 0x20000, 0xe037ff7c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gaiden_2.4s", 0x20000, 0x454f7314, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gaiden_3.4b", 0x10000, 0x75fd3e6a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "gaiden_5.7a", 0x10000, 0x8d4035f7, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x1ecfddaa, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x1291a696, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x140b47ca, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0x7638cccb, 4 | BRF_GRA }, // 7 + + { "18.6a", 0x20000, 0x3fadafd6, 5 | BRF_GRA }, // 8 Background Tiles + { "19.6b", 0x20000, 0xddae9d5b, 5 | BRF_GRA }, // 9 + { "20.4b", 0x20000, 0x08cf7a93, 5 | BRF_GRA }, // 10 + { "21.4b", 0x20000, 0x1ac892f5, 5 | BRF_GRA }, // 11 + + { "6.3m", 0x20000, 0xe7ccdf9f, 6 | BRF_GRA }, // 12 Sprites + { "8.3n", 0x20000, 0x7ef7f880, 6 | BRF_GRA }, // 13 + { "10.3r", 0x20000, 0xa6451dec, 6 | BRF_GRA }, // 14 + { "gaiden_12.3s", 0x20000, 0x90f1e13a, 6 | BRF_GRA }, // 15 + { "7.1m", 0x20000, 0x016bec95, 6 | BRF_GRA }, // 16 + { "9.1n", 0x20000, 0x6e9b7fd3, 6 | BRF_GRA }, // 17 + { "11.1r", 0x20000, 0x7fbfdf5e, 6 | BRF_GRA }, // 18 + { "gaiden_13.1s", 0x20000, 0x7d9f5c5e, 6 | BRF_GRA }, // 19 + + { "4.4a", 0x20000, 0xb0e0faf9, 7 | BRF_SND }, // 20 MSM6295 Samples +}; + +STD_ROM_PICK(gaiden) +STD_ROM_FN(gaiden) + +struct BurnDriver BurnDrvGaiden = { + "gaiden", "shadoww", NULL, NULL, "1988", + "Ninja Gaiden (US)\0", NULL, "Tecmo", "Miscellaneous", + L"Ninja \u5916\u4F1D Gaiden (US)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, gaidenRomInfo, gaidenRomName, NULL, NULL, DrvInputInfo, GaidenDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Ninja Ryukenden (Japan, set 1) + +static struct BurnRomInfo ryukendnRomDesc[] = { + { "ryukendn_1.3s", 0x20000, 0x6203a5e2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ryukendn_2.4s", 0x20000, 0x9e99f522, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3.4b", 0x10000, 0x6b686b69, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "hn27512p.7a", 0x10000, 0x765e7baa, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x1ecfddaa, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x1291a696, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x140b47ca, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0x7638cccb, 4 | BRF_GRA }, // 7 + + { "18.6a", 0x20000, 0x3fadafd6, 5 | BRF_GRA }, // 8 Background Tiles + { "19.6b", 0x20000, 0xddae9d5b, 5 | BRF_GRA }, // 9 + { "20.4b", 0x20000, 0x08cf7a93, 5 | BRF_GRA }, // 10 + { "21.4b", 0x20000, 0x1ac892f5, 5 | BRF_GRA }, // 11 + + { "6.3m", 0x20000, 0xe7ccdf9f, 6 | BRF_GRA }, // 12 Sprites + { "8.3n", 0x20000, 0x7ef7f880, 6 | BRF_GRA }, // 13 + { "10.3r", 0x20000, 0xa6451dec, 6 | BRF_GRA }, // 14 + { "shadoww_12a.xx", 0x10000, 0x9bb07731, 6 | BRF_GRA }, // 15 + { "ryukendn_12b.xx",0x10000, 0x1773628a, 6 | BRF_GRA }, // 16 + { "7.1m", 0x20000, 0x016bec95, 6 | BRF_GRA }, // 17 + { "9.1n", 0x20000, 0x6e9b7fd3, 6 | BRF_GRA }, // 18 + { "11.1r", 0x20000, 0x7fbfdf5e, 6 | BRF_GRA }, // 19 + { "shadoww_13a.xx", 0x10000, 0x996d2fa5, 6 | BRF_GRA }, // 20 + { "ryukendn_13b.xx",0x10000, 0x1f43c507, 6 | BRF_GRA }, // 21 + + { "4.4a", 0x20000, 0xb0e0faf9, 7 | BRF_SND }, // 22 MSM6295 Samples +}; + +STD_ROM_PICK(ryukendn) +STD_ROM_FN(ryukendn) + +struct BurnDriver BurnDrvRyukendn = { + "ryukendn", "shadoww", NULL, NULL, "1989", + "Ninja Ryukenden (Japan, set 1)\0", NULL, "Tecmo", "Miscellaneous", + L"\u5FCD\u8005 \u9F8D\u5263\u4F1D (Japan, set 1)\0Ninja Ryukenden\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, ryukendnRomInfo, ryukendnRomName, NULL, NULL, DrvInputInfo, GaidenDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Ninja Ryukenden (Japan, set 2) + +static struct BurnRomInfo ryukendaRomDesc[] = { + { "1.3s", 0x20000, 0x0ed5464c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2.4s", 0x20000, 0xa93a8256, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3.4b", 0x10000, 0x6b686b69, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "hn27512p.7a", 0x10000, 0x765e7baa, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x1ecfddaa, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x1291a696, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x140b47ca, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0x7638cccb, 4 | BRF_GRA }, // 7 + + { "18.6a", 0x20000, 0x3fadafd6, 5 | BRF_GRA }, // 8 Background Tiles + { "19.6b", 0x20000, 0xddae9d5b, 5 | BRF_GRA }, // 9 + { "20.4b", 0x20000, 0x08cf7a93, 5 | BRF_GRA }, // 10 + { "21.4b", 0x20000, 0x1ac892f5, 5 | BRF_GRA }, // 11 + + { "6.3m", 0x20000, 0xe7ccdf9f, 6 | BRF_GRA }, // 12 Sprites + { "8.3n", 0x20000, 0x7ef7f880, 6 | BRF_GRA }, // 13 + { "10.3r", 0x20000, 0xa6451dec, 6 | BRF_GRA }, // 14 + { "12.3s", 0x20000, 0x277204f0, 6 | BRF_GRA }, // 15 + { "7.1m", 0x20000, 0x016bec95, 6 | BRF_GRA }, // 16 + { "9.1n", 0x20000, 0x6e9b7fd3, 6 | BRF_GRA }, // 17 + { "11.1r", 0x20000, 0x7fbfdf5e, 6 | BRF_GRA }, // 18 + { "13.1s", 0x20000, 0x4e56a508, 6 | BRF_GRA }, // 19 + + { "4.4a", 0x20000, 0xb0e0faf9, 7 | BRF_SND }, // 20 MSM6295 Samples +}; + +STD_ROM_PICK(ryukenda) +STD_ROM_FN(ryukenda) + +struct BurnDriver BurnDrvRyukenda = { + "ryukendna", "shadoww", NULL, NULL, "1989", + "Ninja Ryukenden (Japan, set 2)\0", NULL, "Tecmo", "Miscellaneous", + L"\u5FCD\u8005 \u9F8D\u5263\u4F1D (Japan, set 2)\0Ninja Ryukenden\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, ryukendaRomInfo, ryukendaRomName, NULL, NULL, DrvInputInfo, GaidenDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Wild Fang / Tecmo Knight + +static struct BurnRomInfo wildfangRomDesc[] = { + { "1.3st", 0x20000, 0xab876c9b, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2.5st", 0x20000, 0x1dc74b3b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "tkni3.bin", 0x10000, 0x15623ec7, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "tkni5.bin", 0x10000, 0x5ed15896, 3 | BRF_GRA }, // 3 Characters + + { "14.3a", 0x20000, 0x0d20c10c, 4 | BRF_GRA }, // 4 Foreground Tiles + { "15.3b", 0x20000, 0x3f40a6b4, 4 | BRF_GRA }, // 5 + { "16.1a", 0x20000, 0x0f31639e, 4 | BRF_GRA }, // 6 + { "17.1b", 0x20000, 0xf32c158e, 4 | BRF_GRA }, // 7 + + { "tkni6.bin", 0x80000, 0xf68fafb1, 5 | BRF_GRA }, // 8 + + { "tkni9.bin", 0x80000, 0xd22f4239, 6 | BRF_GRA }, // 9 Sprites + { "tkni8.bin", 0x80000, 0x4931b184, 6 | BRF_GRA }, // 10 + + { "tkni4.bin", 0x20000, 0xa7a1dbcf, 7 | BRF_SND }, // 11 MSM6295 Samples + + { "a-6v.mcu", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(wildfang) +STD_ROM_FN(wildfang) + +struct BurnDriver BurnDrvWildfang = { + "wildfang", NULL, NULL, NULL, "1989", + "Wild Fang / Tecmo Knight\0", NULL, "Tecmo", "Miscellaneous", + L"Wild Fang\0Tecmo Knight\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, wildfangRomInfo, wildfangRomName, NULL, NULL, DrvInputInfo, WildfangDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Tecmo Knight + +static struct BurnRomInfo tknightRomDesc[] = { + { "tkni1.bin", 0x20000, 0x9121daa8, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tkni2.bin", 0x20000, 0x6669cd87, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "tkni3.bin", 0x10000, 0x15623ec7, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "tkni5.bin", 0x10000, 0x5ed15896, 3 | BRF_GRA }, // 3 Characters + + { "tkni7.bin", 0x80000, 0x4b4d4286, 4 | BRF_GRA }, // 4 Foreground Tiles + + { "tkni6.bin", 0x80000, 0xf68fafb1, 5 | BRF_GRA }, // 5 + + { "tkni9.bin", 0x80000, 0xd22f4239, 6 | BRF_GRA }, // 6 Sprites + { "tkni8.bin", 0x80000, 0x4931b184, 6 | BRF_GRA }, // 7 + + { "tkni4.bin", 0x20000, 0xa7a1dbcf, 7 | BRF_SND }, // 8 MSM6295 Samples + + { "a-6v.mcu", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(tknight) +STD_ROM_FN(tknight) + +struct BurnDriver BurnDrvTknight = { + "tknight", "wildfang", NULL, NULL, "1989", + "Tecmo Knight\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, tknightRomInfo, tknightRomName, NULL, NULL, DrvInputInfo, TknightDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Raiga - Strato Fighter (US) + +static struct BurnRomInfo stratofRomDesc[] = { + { "1.3s", 0x20000, 0x060822a4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2.4s", 0x20000, 0x339358fa, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a-4b.3", 0x10000, 0x18655c95, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "b-7a.5", 0x10000, 0x6d2e4bf1, 3 | BRF_GRA }, // 3 Characters + + { "b-1b", 0x80000, 0x781d1bd2, 4 | BRF_GRA }, // 4 Foreground Tiles + + { "b-4b", 0x80000, 0x89468b84, 5 | BRF_GRA }, // 5 + + { "b-2m", 0x80000, 0x5794ec32, 6 | BRF_GRA }, // 6 Sprites + { "b-1m", 0x80000, 0xb0de0ded, 6 | BRF_GRA }, // 7 + + { "a-4a.4", 0x20000, 0xef9acdcf, 7 | BRF_SND }, // 8 MSM6295 Samples + + { "a-6v.mcu", 0x01000, 0x00000000, 0 | BRF_NODUMP }, // 9 MCU +}; + +STD_ROM_PICK(stratof) +STD_ROM_FN(stratof) + +static INT32 stratofInit() +{ + game = 2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvStratof = { + "stratof", NULL, NULL, NULL, "1991", + "Raiga - Strato Fighter (US)\0", NULL, "Tecmo", "Miscellaneous", + L"\u96F7\u7259 Strato Fighter (US)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, stratofRomInfo, stratofRomName, NULL, NULL, RaigaInputInfo, RaigaDIPInfo, + stratofInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Raiga - Strato Fighter (Japan) + +static struct BurnRomInfo raigaRomDesc[] = { + { "a-3s.1", 0x20000, 0x303c2a6c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "a-4s.2", 0x20000, 0x5f31fecb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a-4b.3", 0x10000, 0x18655c95, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "b-7a.5", 0x10000, 0x6d2e4bf1, 3 | BRF_GRA }, // 3 Characters + + { "b-1b", 0x80000, 0x781d1bd2, 4 | BRF_GRA }, // 4 Foreground Tiles + + { "b-4b", 0x80000, 0x89468b84, 5 | BRF_GRA }, // 5 + + { "b-2m", 0x80000, 0x5794ec32, 6 | BRF_GRA }, // 6 Sprites + { "b-1m", 0x80000, 0xb0de0ded, 6 | BRF_GRA }, // 7 + + { "a-4a.4", 0x20000, 0xef9acdcf, 7 | BRF_SND }, // 8 MSM6295 Samples + + { "a-6v.mcu", 0x01000, 0x00000000, 0 | BRF_NODUMP }, // 9 MCU +}; + +STD_ROM_PICK(raiga) +STD_ROM_FN(raiga) + +struct BurnDriver BurnDrvRaiga = { + "raiga", "stratof", NULL, NULL, "1991", + "Raiga - Strato Fighter (Japan)\0", NULL, "Tecmo", "Miscellaneous", + L"\u96F7\u7259 Strato Fighter (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, raigaRomInfo, raigaRomName, NULL, NULL, RaigaInputInfo, RaigaDIPInfo, + stratofInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Dragon Bowl + +static struct BurnRomInfo drgnbowlRomDesc[] = { + { "4.3h", 0x20000, 0x90730008, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "5.4h", 0x20000, 0x193cc915, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.2r", 0x10000, 0xd9cbf84a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "22.6m", 0x10000, 0x86e41198, 3 | BRF_GRA }, // 3 Characters + + { "6.5a", 0x20000, 0xb15759f7, 4 | BRF_GRA }, // 4 Foreground & Background Tiles + { "7.5b", 0x20000, 0x2541d445, 4 | BRF_GRA }, // 5 + { "8.6a", 0x20000, 0x51a2f5c4, 4 | BRF_GRA }, // 6 + { "9.6b", 0x20000, 0xf4c8850f, 4 | BRF_GRA }, // 7 + { "10.7a", 0x20000, 0x9e4b3c61, 4 | BRF_GRA }, // 8 + { "11.7b", 0x20000, 0x0d33d083, 4 | BRF_GRA }, // 9 + { "12.8a", 0x20000, 0x6c497ad3, 4 | BRF_GRA }, // 10 + { "13.8b", 0x20000, 0x7a84adff, 4 | BRF_GRA }, // 11 + + { "21.8r", 0x20000, 0x0cee8711, 6 | BRF_GRA }, // 18 Sprites + { "20.8q", 0x20000, 0x9647e02a, 6 | BRF_GRA }, // 19 + { "19.7r", 0x20000, 0x5082ceff, 6 | BRF_GRA }, // 16 + { "18.7q", 0x20000, 0xd18a7ffb, 6 | BRF_GRA }, // 17 + { "17.6r", 0x20000, 0x9088af09, 6 | BRF_GRA }, // 14 + { "16.6q", 0x20000, 0x8ade4e01, 6 | BRF_GRA }, // 15 + { "15.5r", 0x20000, 0x7429371c, 6 | BRF_GRA }, // 12 + { "14.5q", 0x20000, 0x4301b97f, 6 | BRF_GRA }, // 13 + + { "3.3q", 0x20000, 0x489c6d0e, 7 | BRF_SND }, // 20 MSM6295 Samples + { "2.3r", 0x20000, 0x7710ce39, 7 | BRF_SND }, // 21 +}; + +STD_ROM_PICK(drgnbowl) +STD_ROM_FN(drgnbowl) + +static INT32 drgnbowlInit() +{ + game = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvDrgnbowl = { + "drgnbowl", NULL, NULL, NULL, "1992", + "Dragon Bowl\0", NULL, "Nics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, drgnbowlRomInfo, drgnbowlRomName, NULL, NULL, DrvInputInfo, DrgnbowlDIPInfo, + drgnbowlInit, DrvExit, DrvFrame, DrgnbowlDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_post90s/d_galpanic.cpp b/src/burn/drivers/misc_post90s/d_galpanic.cpp new file mode 100644 index 00000000..402e4b30 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_galpanic.cpp @@ -0,0 +1,2022 @@ +/* + * Gals Panic (set 1) driver for FB Alpha 0.2.96.71 + * + * Port by OopsWare. 2007 + */ + +#include "burnint.h" +#include "driver.h" + +#include "msm6295.h" + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *Rom68K; +static UINT8 *RomGfx; +static UINT8 *DeRomGfx; +static UINT8 *RomSnd; + +static UINT16 *Ram68K; +static UINT16 *RamPal; +static UINT16 *RamFg; +static UINT16 *RamBg; +static UINT16 *RamSpr; +static UINT16 *RamBgM; + +static UINT32 *RamCurPal; +static UINT32 *RamCTB64k; + +static UINT8 DrvButton[7] = {0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[7] = {0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[7] = {0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0, 0, 0, 0, 0, 0}; +static UINT8 DrvReset = 0; +//static UINT16 GalPanicCoin = 0; + +UINT8 RecalcBgPalette; + +static INT32 nCyclesDone[1], nCyclesTotal[1]; +static INT32 nCyclesSegment; +static INT32 SndBank; + +static struct BurnInputInfo GalpanicInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 6, "service"}, + {"Tilt", BIT_DIGITAL, DrvButton + 5, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 2, "dip"}, +}; + +STDINPUTINFO(Galpanic) + +static struct BurnInputInfo GalhustlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 2, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 3, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 1, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 2, "dip"}, +}; + +STDINPUTINFO(Galhustl) + +inline void ComadClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static struct BurnDIPInfo GalpanicDIPList[] = { + + // Defaults + {0x11, 0xFF, 0xFF, 0x00, NULL}, + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Service mode"}, + {0x11, 0x01, 0x04, 0x00, "Off"}, + {0x11, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 4, "Coin 1"}, + {0x11, 0x01, 0x30, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x30, 0x10, "2 coins 1 credit"}, + {0x11, 0x01, 0x30, 0x20, "3 coins 1 credit"}, + {0x11, 0x01, 0x30, 0x30, "4 coins 1 credit"}, + {0, 0xFE, 0, 4, "Coin 2"}, + {0x11, 0x01, 0xC0, 0x00, "1 coin 2 credits"}, + {0x11, 0x01, 0xC0, 0x40, "1 coin 3 credits"}, + {0x11, 0x01, 0xC0, 0x80, "1 coin 4 credits"}, + {0x11, 0x01, 0xC0, 0xC0, "1 coin 6 credits"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x12, 0x01, 0x03, 0x00, "Normal"}, + {0x12, 0x01, 0x03, 0x01, "Easy"}, + {0x12, 0x01, 0x03, 0x02, "Hard"}, + {0x12, 0x01, 0x03, 0x03, "Hardest"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x12, 0x01, 0x30, 0x00, "3"}, + {0x12, 0x01, 0x30, 0x10, "4"}, + {0x12, 0x01, 0x30, 0x20, "2"}, + {0x12, 0x01, 0x30, 0x30, "5"}, +// {0, 0xFE, 0, 2, "Unknown"}, // demo sounds? +// {0x12, 0x01, 0x40, 0x00, "Off"}, +// {0x12, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Character test"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(Galpanic) + +static struct BurnDIPInfo ComadDIPList[] = { + + // Defaults + {0x11, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x11, 0x01, 0x03, 0x01, "Easy"}, + {0x11, 0x01, 0x03, 0x00, "Normal"}, + {0x11, 0x01, 0x03, 0x02, "Hard"}, + {0x11, 0x01, 0x03, 0x03, "Hardest"}, +// {0, 0xFE, 0, 2, "Unknown"}, // freeze/vblank? +// {0x11, 0x01, 0x08, 0x00, "Off"}, +// {0x11, 0x01, 0x08, 0x08, "On"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x11, 0x01, 0x30, 0x20, "2"}, + {0x11, 0x01, 0x30, 0x00, "3"}, + {0x11, 0x01, 0x30, 0x10, "4"}, + {0x11, 0x01, 0x30, 0x30, "5"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x11, 0x01, 0x40, 0x40, "Off"}, + {0x11, 0x01, 0x40, 0x00, "On"}, +}; + +static struct BurnDIPInfo FantasiaDIPList[] = { + + // Defaults + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 2 + {0, 0xFE, 0, 2, "Service mode"}, + {0x12, 0x01, 0x04, 0x00, "Off"}, + {0x12, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 2, "Coin mode"}, + {0x12, 0x01, 0x08, 0x00, "Mode 1"}, + {0x12, 0x01, 0x08, 0x08, "Mode 2"}, + // Coin mode 1 condition + {0, 0xFE, 0, 4, "Coin 1"}, + {0x12, 0x02, 0x30, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x10, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x20, "1 coin 2 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x30, "1 coin 6 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0, 0xFE, 0, 4, "Coin 2"}, + {0x12, 0x02, 0xC0, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0x40, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0x80, "1 coin 2 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0xC0, "1 coin 6 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + // Coin mode 2 condition + {0, 0xFE, 0, 4, "Coin 1"}, + {0x12, 0x02, 0x30, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x10, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x20, "1 coin 3 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x30, "1 coin 4 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin 2"}, + {0x12, 0x02, 0xC0, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0x40, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0x80, "1 coin 3 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0xC0, "1 coin 4 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, +}; + +static struct BurnDIPInfo Missw96DIPList[] = { + + // Defaults + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 2 + {0, 0xFE, 0, 2, "Coin mode"}, + {0x12, 0x01, 0x08, 0x00, "Mode 1"}, + {0x12, 0x01, 0x08, 0x08, "Mode 2"}, + // Coin mode 1 condition + {0, 0xFE, 0, 4, "Coin 1"}, + {0x12, 0x02, 0x30, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x10, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x20, "1 coin 2 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0x30, 0x30, "1 coin 6 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0, 0xFE, 0, 4, "Coin 2"}, + {0x12, 0x02, 0xC0, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0x40, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0x80, "1 coin 2 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + {0x12, 0x02, 0xC0, 0xC0, "1 coin 6 credits"}, + {0x12, 0x00, 0x08, 0x00, NULL}, + // Coin mode 2 condition + {0, 0xFE, 0, 4, "Coin 1"}, + {0x12, 0x02, 0x30, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x10, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x20, "1 coin 3 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0x30, 0x30, "1 coin 4 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin 2"}, + {0x12, 0x02, 0xC0, 0x00, "1 coin 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0x40, "2 coins 1 credit"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0x80, "1 coin 3 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, + {0x12, 0x02, 0xC0, 0xC0, "1 coin 4 credits"}, + {0x12, 0x00, 0x08, 0x08, NULL}, +}; + +STDDIPINFOEXT(Fantasia, Comad, Fantasia) +STDDIPINFOEXT(Missw96, Comad, Missw96) + +static struct BurnDIPInfo GalhustlDIPList[] = { + + // Defaults + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 4, "Lives"}, + {0x13, 0x01, 0x03, 0x03, "6"}, + {0x13, 0x01, 0x03, 0x02, "7"}, + {0x13, 0x01, 0x03, 0x00, "8"}, + {0x13, 0x01, 0x03, 0x01, "10"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x13, 0x01, 0x40, 0x40, "Off"}, + {0x13, 0x01, 0x40, 0x00, "On"}, + {0, 0xFE, 0, 2, "Service mode"}, + {0x13, 0x01, 0x80, 0x00, "Off"}, + {0x13, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 8, "Coinage"}, + {0x14, 0x01, 0x07, 0x00, "1 coin 1 credit"}, + {0x14, 0x01, 0x07, 0x01, "1 coin 2 credits"}, + {0x14, 0x01, 0x07, 0x02, "1 coin 3 credits"}, + {0x14, 0x01, 0x07, 0x03, "3 coins 2 credits"}, + {0x14, 0x01, 0x07, 0x04, "2 coins 3 credits"}, + {0x14, 0x01, 0x07, 0x05, "2 coins 1 credit"}, + {0x14, 0x01, 0x07, 0x06, "3 coins 1 credit"}, + {0x14, 0x01, 0x07, 0x07, "4 coins 1 credit"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x14, 0x01, 0x18, 0x08, "Easy"}, + {0x14, 0x01, 0x18, 0x00, "Normal"}, + {0x14, 0x01, 0x18, 0x10, "Hard"}, + {0x14, 0x01, 0x18, 0x18, "Hardest"}, + {0, 0xFE, 0, 4, "Play time"}, + {0x14, 0x01, 0x60, 0x60, "70 Sec"}, + {0x14, 0x01, 0x60, 0x40, "80 Sec"}, + {0x14, 0x01, 0x60, 0x00, "100 Sec"}, + {0x14, 0x01, 0x60, 0x20, "120 Sec"}, +}; + +STDDIPINFO(Galhustl) + +static struct BurnDIPInfo ZipzapDIPList[] = { + + // Defaults + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x10, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Additional obsticals"}, + {0x13, 0x01, 0x02, 0x00, "Off"}, + {0x13, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x13, 0x01, 0x0C, 0x0C, "1"}, + {0x13, 0x01, 0x0C, 0x04, "2"}, + {0x13, 0x01, 0x0C, 0x00, "3"}, + {0x13, 0x01, 0x0C, 0x08, "4"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Coinage"}, + {0x14, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x14, 0x01, 0x03, 0x01, "1 coin 2 credits"}, + {0x14, 0x01, 0x03, 0x02, "2 coins 1 credit"}, + {0x14, 0x01, 0x03, 0x03, "3 coins 1 credit"}, + {0, 0xFE, 0, 2, "Select player mode"}, + {0x14, 0x01, 0x04, 0x04, "Off"}, + {0x14, 0x01, 0x04, 0x00, "On"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0x14, 0x01, 0x08, 0x00, "On"}, +}; + +STDDIPINFO(Zipzap) + +// Rom information +static struct BurnRomInfo GalpanicRomDesc[] = { + { "pm110.4m2", 0x080000, 0xae6b17a8, BRF_ESS | BRF_PRG }, // 68000 code + { "pm109.4m1", 0x080000, 0xb85d792d, BRF_ESS | BRF_PRG }, + { "pm112.subic6", 0x020000, 0x7b972b58, BRF_ESS | BRF_PRG }, + { "pm111.subic5", 0x020000, 0x4eb7298d, BRF_ESS | BRF_PRG }, + { "pm004e.8", 0x080000, 0xd3af52bc, BRF_ESS | BRF_PRG }, + { "pm005e.7", 0x080000, 0xd7ec650c, BRF_ESS | BRF_PRG }, + { "pm000e.15", 0x080000, 0x5d220f3f, BRF_ESS | BRF_PRG }, + { "pm001e.14", 0x080000, 0x90433eb1, BRF_ESS | BRF_PRG }, + { "pm002e.17", 0x080000, 0x713ee898, BRF_ESS | BRF_PRG }, + { "pm003e.16", 0x080000, 0x6bb060fd, BRF_ESS | BRF_PRG }, + + { "pm006e.67", 0x100000, 0x57aec037, BRF_GRA }, // graphics + + { "pm008e.l", 0x080000, 0xd9379ba8, BRF_SND }, // PCM + { "pm007e.u", 0x080000, 0xc7ed7950, BRF_SND }, +}; + +STD_ROM_PICK(Galpanic) +STD_ROM_FN(Galpanic) + +// Rom information +static struct BurnRomInfo FantasiaRomDesc[] = { + { "prog2_16.rom", 0x080000, 0xe27c6c57, BRF_ESS | BRF_PRG }, // 68000 code + { "prog1_13.rom", 0x080000, 0x68d27413, BRF_ESS | BRF_PRG }, + { "iscr6_09.rom", 0x080000, 0x2a588393, BRF_ESS | BRF_PRG }, + { "iscr5_05.rom", 0x080000, 0x6160e0f0, BRF_ESS | BRF_PRG }, + { "iscr4_08.rom", 0x080000, 0xf776b743, BRF_ESS | BRF_PRG }, + { "iscr3_04.rom", 0x080000, 0x5df0dff2, BRF_ESS | BRF_PRG }, + { "iscr2_07.rom", 0x080000, 0x5707d861, BRF_ESS | BRF_PRG }, + { "iscr1_03.rom", 0x080000, 0x36cb811a, BRF_ESS | BRF_PRG }, + { "imag2_10.rom", 0x080000, 0x1f14a395, BRF_ESS | BRF_PRG }, + { "imag1_06.rom", 0x080000, 0xfaf870e4, BRF_ESS | BRF_PRG }, + + { "obj1_17.rom", 0x080000, 0xaadb6eb7, BRF_GRA }, // graphics + + { "mus-1_01.rom", 0x080000, 0x22955efb, BRF_SND }, // PCM + { "mus-2_02.rom", 0x080000, 0x4cd4d6c3, BRF_SND }, + + { "gscr2_15.rom", 0x080000, 0x46666768, BRF_OPT }, // unknown + { "gscr1_12.rom", 0x080000, 0x4bd25be6, BRF_OPT }, + { "gscr4_14.rom", 0x080000, 0x4e7e6ed4, BRF_OPT }, + { "gscr3_11.rom", 0x080000, 0x6d00a4c5, BRF_OPT }, +}; + +STD_ROM_PICK(Fantasia) +STD_ROM_FN(Fantasia) + +// Rom information +static struct BurnRomInfo SupmodelRomDesc[] = { + { "prog2.12", 0x080000, 0x714b7e74, BRF_ESS | BRF_PRG }, // 68000 code + { "prog1.7", 0x080000, 0x0bb858de, BRF_ESS | BRF_PRG }, + { "i-scr2.10", 0x080000, 0xd07ec0ce, BRF_ESS | BRF_PRG }, + { "i-scr1.5", 0x080000, 0xa96a8bde, BRF_ESS | BRF_PRG }, + { "i-scr4.9", 0x080000, 0xe959cab5, BRF_ESS | BRF_PRG }, + { "i-scr3.4", 0x080000, 0x4bf5e082, BRF_ESS | BRF_PRG }, + { "i-scr6.8", 0x080000, 0xe71337c2, BRF_ESS | BRF_PRG }, + { "i-scr5.3", 0x080000, 0x641ccdfb, BRF_ESS | BRF_PRG }, + { "i-scr8.11", 0x080000, 0x7c1813c8, BRF_ESS | BRF_PRG }, + { "i-scr7.6", 0x080000, 0x19c73268, BRF_ESS | BRF_PRG }, + + { "obj1.13", 0x080000, 0x832cd451, BRF_GRA }, // graphics + + { "music1.1", 0x080000, 0x2b1f6655, BRF_SND }, // PCM + { "music2.2", 0x080000, 0xcccae65a, BRF_SND }, +}; + +STD_ROM_PICK(Supmodel) +STD_ROM_FN(Supmodel) + +// Rom information +static struct BurnRomInfo NewfantRomDesc[] = { + { "prog2_12.rom", 0x080000, 0xde43a457, BRF_ESS | BRF_PRG }, // 68000 code + { "prog1_07.rom", 0x080000, 0x370b45be, BRF_ESS | BRF_PRG }, + { "iscr2_10.rom", 0x080000, 0x4f2da2eb, BRF_ESS | BRF_PRG }, + { "iscr1_05.rom", 0x080000, 0x63c6894f, BRF_ESS | BRF_PRG }, + { "iscr4_09.rom", 0x080000, 0x725741ec, BRF_ESS | BRF_PRG }, + { "iscr3_04.rom", 0x080000, 0x51d6b362, BRF_ESS | BRF_PRG }, + { "iscr6_08.rom", 0x080000, 0x178b2ef3, BRF_ESS | BRF_PRG }, + { "iscr5_03.rom", 0x080000, 0xd2b5c5fa, BRF_ESS | BRF_PRG }, + { "iscr8_11.rom", 0x080000, 0xf4148528, BRF_ESS | BRF_PRG }, + { "iscr7_06.rom", 0x080000, 0x2dee0c31, BRF_ESS | BRF_PRG }, + + { "obj1_13.rom", 0x080000, 0xe6d1bc71, BRF_GRA }, // graphics + + { "musc1_01.rom", 0x080000, 0x10347fce, BRF_SND }, // PCM + { "musc2_02.rom", 0x080000, 0xb9646a8c, BRF_SND }, +}; + +STD_ROM_PICK(Newfant) +STD_ROM_FN(Newfant) + +// Rom information +static struct BurnRomInfo Fantsy95RomDesc[] = { + { "prog2.12", 0x080000, 0x1e684da7, BRF_ESS | BRF_PRG }, // 68000 code + { "prog1.7", 0x080000, 0xdc4e4f6b, BRF_ESS | BRF_PRG }, + { "i-scr2.10", 0x080000, 0xab8756ff, BRF_ESS | BRF_PRG }, + { "i-scr1.5", 0x080000, 0xd8e2ef77, BRF_ESS | BRF_PRG }, + { "i-scr4.9", 0x080000, 0x4e52eb23, BRF_ESS | BRF_PRG }, + { "i-scr3.4", 0x080000, 0x797731f8, BRF_ESS | BRF_PRG }, + { "i-scr6.8", 0x080000, 0x6f8e5239, BRF_ESS | BRF_PRG }, + { "i-scr5.3", 0x080000, 0x85420e3f, BRF_ESS | BRF_PRG }, + { "i-scr8.11", 0x080000, 0x33db8177, BRF_ESS | BRF_PRG }, + { "i-scr7.6", 0x080000, 0x8662dd01, BRF_ESS | BRF_PRG }, + + { "obj1.13", 0x080000, 0x832cd451, BRF_GRA }, // graphics + + { "music1.1", 0x080000, 0x3117e2ef, BRF_SND }, // PCM + { "music2.2", 0x080000, 0x0c1109f9, BRF_SND }, +}; + +STD_ROM_PICK(Fantsy95) +STD_ROM_FN(Fantsy95) + +// Rom information +static struct BurnRomInfo Missw96RomDesc[] = { + { "mw96_10.bin", 0x080000, 0xb1309bb1, BRF_ESS | BRF_PRG }, // 68000 code + { "mw96_06.bin", 0x080000, 0xa5892bb3, BRF_ESS | BRF_PRG }, + { "mw96_09.bin", 0x080000, 0x7032dfdf, BRF_ESS | BRF_PRG }, + { "mw96_05.bin", 0x080000, 0x91de5ab5, BRF_ESS | BRF_PRG }, + { "mw96_08.bin", 0x080000, 0xb8e66fb5, BRF_ESS | BRF_PRG }, + { "mw96_04.bin", 0x080000, 0xe77a04f8, BRF_ESS | BRF_PRG }, + { "mw96_07.bin", 0x080000, 0x26112ed3, BRF_ESS | BRF_PRG }, + { "mw96_03.bin", 0x080000, 0xe9374a46, BRF_ESS | BRF_PRG }, + + { "mw96_11.bin", 0x080000, 0x3983152f, BRF_GRA }, // graphics + + { "mw96_01.bin", 0x080000, 0xe78a659e, BRF_SND }, // PCM + { "mw96_02.bin", 0x080000, 0x60fa0c00, BRF_SND }, +}; + +STD_ROM_PICK(Missw96) +STD_ROM_FN(Missw96) + +// Rom information +static struct BurnRomInfo Missmw96RomDesc[] = { + { "mmw96_10.bin", 0x080000, 0x45ed1cd9, BRF_ESS | BRF_PRG }, // 68000 code + { "mmw96_06.bin", 0x080000, 0x52ec9e5d, BRF_ESS | BRF_PRG }, + { "mmw96_09.bin", 0x080000, 0x6c458b05, BRF_ESS | BRF_PRG }, + { "mmw96_05.bin", 0x080000, 0x48159555, BRF_ESS | BRF_PRG }, + { "mmw96_08.bin", 0x080000, 0x1dc72b07, BRF_ESS | BRF_PRG }, + { "mmw96_04.bin", 0x080000, 0xfc3e18fa, BRF_ESS | BRF_PRG }, + { "mmw96_07.bin", 0x080000, 0x001572bf, BRF_ESS | BRF_PRG }, + { "mmw96_03.bin", 0x080000, 0x22204025, BRF_ESS | BRF_PRG }, + + { "mmw96_11.bin", 0x080000, 0x7d491f8c, BRF_GRA }, // graphics + + { "mw96_01.bin", 0x080000, 0xe78a659e, BRF_SND }, // PCM + { "mw96_02.bin", 0x080000, 0x60fa0c00, BRF_SND }, +}; + +STD_ROM_PICK(Missmw96) +STD_ROM_FN(Missmw96) + +// Rom information +static struct BurnRomInfo Fantsia2RomDesc[] = { + { "prog2.g17", 0x080000, 0x57c59972, BRF_ESS | BRF_PRG }, // 68000 code + { "prog1.f17", 0x080000, 0xbf2d9a26, BRF_ESS | BRF_PRG }, + { "scr2.g16", 0x080000, 0x887b1bc5, BRF_ESS | BRF_PRG }, + { "scr1.f16", 0x080000, 0xcbba3182, BRF_ESS | BRF_PRG }, + { "scr4.g15", 0x080000, 0xce97e411, BRF_ESS | BRF_PRG }, + { "scr3.f15", 0x080000, 0x480cc2e8, BRF_ESS | BRF_PRG }, + { "scr6.g14", 0x080000, 0xb29d49de, BRF_ESS | BRF_PRG }, + { "scr5.f14", 0x080000, 0xd5f88b83, BRF_ESS | BRF_PRG }, + { "scr8.g20", 0x080000, 0x694ae2b3, BRF_ESS | BRF_PRG }, + { "scr7.f20", 0x080000, 0x6068712c, BRF_ESS | BRF_PRG }, + + { "obj1.1i", 0x080000, 0x52e6872a, BRF_GRA }, // graphics + { "obj2.2i", 0x080000, 0xea6e3861, BRF_GRA }, + + { "music2.1b", 0x080000, 0x23cc4f9c, BRF_SND }, // PCM + { "music1.1a", 0x080000, 0x864167c2, BRF_SND }, +}; + +STD_ROM_PICK(Fantsia2) +STD_ROM_FN(Fantsia2) + +// Rom information +static struct BurnRomInfo Fantsia2aRomDesc[] = { + { "fnt2-22.bin", 0x080000, 0xa3a92c4b, BRF_ESS | BRF_PRG }, // 68000 code + { "fnt2-17.bin", 0x080000, 0xd0ce4493, BRF_ESS | BRF_PRG }, + { "fnt2-21.bin", 0x080000, 0xe989c2e7, BRF_ESS | BRF_PRG }, + { "fnt2-16.bin", 0x080000, 0x8c06d372, BRF_ESS | BRF_PRG }, + { "fnt2-20.bin", 0x080000, 0x6e9f1e65, BRF_ESS | BRF_PRG }, + { "fnt2-15.bin", 0x080000, 0x85cbeb2b, BRF_ESS | BRF_PRG }, + { "fnt2-19.bin", 0x080000, 0x7953226a, BRF_ESS | BRF_PRG }, + { "fnt2-14.bin", 0x080000, 0x10d8ccff, BRF_ESS | BRF_PRG }, + { "fnt2-18.bin", 0x080000, 0x4cdaeda3, BRF_ESS | BRF_PRG }, + { "fnt2-13.bin", 0x080000, 0x68c7f042, BRF_ESS | BRF_PRG }, + + { "obj1.1i", 0x080000, 0x52e6872a, BRF_GRA }, // graphics + { "obj2.2i", 0x080000, 0xea6e3861, BRF_GRA }, + + { "music2.1b", 0x080000, 0x23cc4f9c, BRF_SND }, // PCM + { "music1.1a", 0x080000, 0x864167c2, BRF_SND }, +}; + +STD_ROM_PICK(Fantsia2a) +STD_ROM_FN(Fantsia2a) + +// Rom information +static struct BurnRomInfo WownfantRomDesc[] = { + { "ep-4001 42750001 u81.bin", 0x080000, 0x9942d200, BRF_ESS | BRF_PRG }, // 68000 code + { "ep-4001 42750001 u80.bin", 0x080000, 0x17359eeb, BRF_ESS | BRF_PRG }, + { "ep-061 43750002 - 1.bin", 0x200000, 0xc318e841, BRF_ESS | BRF_PRG }, + { "ep-061 43750002 - 2.bin", 0x200000, 0x8871dc3a, BRF_ESS | BRF_PRG }, + + { "ep-4001 42750001 u113.bin", 0x080000, 0x3e77ca1f, BRF_GRA }, // graphics + { "ep-4001 42750001 u112.bin", 0x080000, 0x51f4b604, BRF_GRA }, + + { "ep-4001 42750001 u4.bin", 0x080000, 0x06dc889e, BRF_SND }, // PCM + { "ep-4001 42750001 u1.bin", 0x080000, 0x864167c2, BRF_SND }, +}; + +STD_ROM_PICK(Wownfant) +STD_ROM_FN(Wownfant) + +// Rom information +static struct BurnRomInfo GalhustlRomDesc[] = { + { "ue17.3", 0x080000, 0xb2583dbb, BRF_ESS | BRF_PRG }, // 68000 code + { "ud17.4", 0x080000, 0x470a3668, BRF_ESS | BRF_PRG }, + + { "galhstl5.u5", 0x080000, 0x44a18f15, BRF_GRA }, // graphics + + { "galhstl1.ub6", 0x080000, 0x23848790, BRF_SND }, // PCM + { "galhstl2.uc6", 0x080000, 0x2168e54a, BRF_SND }, +}; + +STD_ROM_PICK(Galhustl) +STD_ROM_FN(Galhustl) + +// Rom information +static struct BurnRomInfo ZipzapRomDesc[] = { + { "ue17.bin", 0x040000, 0xda6c3fc8, BRF_ESS | BRF_PRG }, // 68000 code + { "ud17.bin", 0x040000, 0x2901fae1, BRF_ESS | BRF_PRG }, + { "937.bin", 0x080000, 0x61dd653f, BRF_ESS | BRF_PRG }, + { "941.bin", 0x080000, 0x320321ed, BRF_ESS | BRF_PRG }, + { "936.bin", 0x080000, 0x596543cc, BRF_ESS | BRF_PRG }, + { "940.bin", 0x080000, 0x0c9dfb53, BRF_ESS | BRF_PRG }, + { "934.bin", 0x080000, 0x1e65988a, BRF_ESS | BRF_PRG }, + { "939.bin", 0x080000, 0x8790a6a3, BRF_ESS | BRF_PRG }, + { "938.bin", 0x080000, 0x61c06b60, BRF_ESS | BRF_PRG }, + { "942.bin", 0x080000, 0x282413b8, BRF_ESS | BRF_PRG }, + + { "u5.bin", 0x080000, 0xc274d8b5, BRF_GRA }, // graphics + + { "snd.bin", 0x080000, 0xbc20423e, BRF_SND }, // PCM +}; + +STD_ROM_PICK(Zipzap) +STD_ROM_FN(Zipzap) + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom68K = Next; Next += 0x400000; // 68000 ROM + RomGfx = Next; Next += 0x200100; // Graphics, 1M 16x16x4bit decode to 2M + 64byte safe + DeRomGfx = RomGfx + 0x000100; + RomSnd = Next; Next += 0x140000; // ADPCM - OKI6295 + + RamStart = Next; + + RamFg = (UINT16 *) Next; Next += 0x010000 * sizeof(UINT16); + RamBg = (UINT16 *) Next; Next += 0x010000 * sizeof(UINT16); + RamPal = (UINT16 *) Next; Next += 0x000400 * sizeof(UINT16); + RamSpr = (UINT16 *) Next; Next += 0x002400 * sizeof(UINT16); + + RamEnd = Next; + + RamCurPal = (UINT32 *) Next; Next += 0x000400 * sizeof(UINT32); + RamCTB64k = (UINT32 *) Next; Next += 0x008000 * sizeof(UINT32); + + MemEnd = Next; + return 0; +} + +static INT32 MemIndex2() +{ + UINT8 *Next; Next = Mem; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "galhustl")) { + Rom68K = Next; Next += 0x100000; // 68000 ROM + } else { + Rom68K = Next; Next += 0x500000; // 68000 ROM + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "fantsia2") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fantsia2a") || !strcmp(BurnDrvGetTextA(DRV_NAME), "wownfant")) { + RomGfx = Next; Next += 0x200100; // Graphics, 1M 16x16x4bit decode to 2M + 64byte safe + } else { + RomGfx = Next; Next += 0x100100; // Graphics, 1/2M 16x16x4bit decode to 1M + 64byte safe + } + DeRomGfx = RomGfx + 0x000100; + RomSnd = Next; Next += 0x140000; // ADPCM - OKI6295 + + RamStart = Next; + + Ram68K = (UINT16 *) Next; Next += 0x008020 * sizeof(UINT16); + RamFg = (UINT16 *) Next; Next += 0x010000 * sizeof(UINT16); + RamBg = (UINT16 *) Next; Next += 0x010000 * sizeof(UINT16); + RamPal = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + RamSpr = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + RamBgM = (UINT16 *) Next; Next += 0x002000 * sizeof(UINT16); + + RamEnd = Next; + + RamCurPal = (UINT32 *) Next; Next += 0x000400 * sizeof(UINT32); + RamCTB64k = (UINT32 *) Next; Next += 0x008000 * sizeof(UINT32); + + MemEnd = Next; + return 0; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +UINT8 __fastcall GalpanicReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400001: + return MSM6295ReadStatus(0); + //default: + // printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +UINT16 __fastcall GalpanicReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x800000: + return ~(DrvInput[0] | (DrvInput[1] << 8)); + case 0x800002: + return ~(DrvInput[2] | (DrvInput[3] << 8)); + case 0x800004: + return ~(DrvInput[4] | (DrvInput[5] << 8)); + //default: + // printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} + +void __fastcall GalpanicWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x900000: + SndBank = (byteValue & 0x0f); + memcpy(&RomSnd[0x30000], &RomSnd[0x40000 + SndBank * 0x10000], 0x10000); + break; + case 0x400001: + MSM6295Command(0, byteValue); + break; + //case 0xB00000: + //case 0xC00000: + //case 0xD00000: + // /* NOP */ + // break; + //default: + // printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +UINT8 __fastcall ComadReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC80000: + case 0xD00000: + case 0xF00000: + case 0xF80000: + return MSM6295ReadStatus(0); + + case 0x80000a: + case 0x80000c: + return rand() & 0xffff; + + case 0x800006: + case 0x800008: + return rand() & 0xffff; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall ComadWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x900000: + case 0x900001: + SndBank = (byteValue & 0x0f); + memcpy(&RomSnd[0x30000], &RomSnd[0x40000 + SndBank * 0x10000], 0x10000); + break; + case 0xC00000: + case 0xC80000: + case 0xD00000: + case 0xF00000: + case 0xF80000: + MSM6295Command(0, byteValue & 0xff); + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall GalhustlWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + +if (sekAddress >= 0x580000 && sekAddress <= 0x583fff) { + for (INT32 i = 0; i < 8; i++) { + INT32 Offs = (sekAddress - 0x580000) >> 1; + RamBgM = (UINT16*)RamBg; + RamBgM[Offs * 8 + i] = wordValue; + } + + return; + } + + switch (sekAddress) { + case 0xA00000: +// GalPanicCoin = wordValue; + break; + + case 0xE00012: + return; // NOP? + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +UINT16 __fastcall GalhustlReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x800000: + SEK_DEF_READ_WORD(0, sekAddress); + return 0; + case 0x800002: + SEK_DEF_READ_WORD(0, sekAddress); + return 0; + case 0x800004: + SEK_DEF_READ_WORD(0, sekAddress); + return 0; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +UINT8 __fastcall GalhustlReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: + case 0xD00000: + return MSM6295ReadStatus(0); + + case 0x800000: + return ~(DrvInput[1]); + case 0x800001: + return ~(DrvInput[0]); + case 0x800002: + return ~(DrvInput[3]); + case 0x800003: + return ~(DrvInput[2]); + case 0x800004: + case 0x800005: + return 0xff - DrvInput[5]; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + SndBank = 0; + MSM6295Reset(0); + + return 0; +} + +void DeCodeGfx() +{ + for (INT32 c=8192-1; c>=0; c--) { + INT32 fx = 8; + for (INT32 y=15; y>=0; y--) { + if (y == 7) fx = 0; + DeRomGfx[(c * 256) + (y * 16) + 15] = RomGfx[0x00023 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 14] = RomGfx[0x00023 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 13] = RomGfx[0x00022 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 12] = RomGfx[0x00022 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 11] = RomGfx[0x00021 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 10] = RomGfx[0x00021 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 9] = RomGfx[0x00020 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 8] = RomGfx[0x00020 + ((y + fx) * 4) + (c * 128)] >> 4; + + DeRomGfx[(c * 256) + (y * 16) + 7] = RomGfx[0x00003 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 6] = RomGfx[0x00003 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 5] = RomGfx[0x00002 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 4] = RomGfx[0x00002 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 3] = RomGfx[0x00001 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 2] = RomGfx[0x00001 + ((y + fx) * 4) + (c * 128)] >> 4; + DeRomGfx[(c * 256) + (y * 16) + 1] = RomGfx[0x00000 + ((y + fx) * 4) + (c * 128)] & 0x0f; + DeRomGfx[(c * 256) + (y * 16) + 0] = RomGfx[0x00000 + ((y + fx) * 4) + (c * 128)] >> 4; + } + } +} + +static INT32 GalpanicInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 3, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(Rom68K + 0x100000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300001, 9, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 10, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 11, 1); + BurnLoadRom(RomSnd + 0x0C0000, 12, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x3FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x6007FF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x7047FF, SM_RAM); // sprites + + SekSetReadWordHandler(0, GalpanicReadWord); + SekSetReadByteHandler(0, GalpanicReadByte); + SekSetWriteByteHandler(0, GalpanicWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 FantasiaInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400001, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400000, 9, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 10, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 11, 1); + BurnLoadRom(RomSnd + 0x0C0000, 12, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x4FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamBgM, + 0x580000, 0x583FFF, SM_RAM); // another tilemap? + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)Ram68K, + 0x680000, 0x68001F, SM_WRITE); // regs? + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K+0x000020, + 0x780000, 0x78001F, SM_WRITE); // regs? + SekMapMemory((UINT8 *)Ram68K+0x000040, + 0xC80000, 0xC8FFFF, SM_RAM); // work ram? + + + SekSetReadWordHandler(0, GalpanicReadWord); + SekSetReadByteHandler(0, ComadReadByte); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 Missw96Init() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 7, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 8, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 9, 1); + BurnLoadRom(RomSnd + 0x0C0000, 10, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x4FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamBgM, + 0x580000, 0x583FFF, SM_RAM); // another tilemap? + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K, + 0xC00000, 0xC0FFFF, SM_RAM); // work ram? + SekMapMemory((UINT8 *)Ram68K+0x010000, + 0x680000, 0x68001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x010020, + 0x780000, 0x78001F, SM_RAM); // regs? + + SekSetReadWordHandler(0, GalpanicReadWord); + SekSetReadByteHandler(0, ComadReadByte); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 Fantsia2Init() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400001, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400000, 9, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomGfx + 0x080000, 11, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 12, 1); + BurnLoadRom(RomSnd + 0x0C0000, 13, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x4FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamBgM, + 0x580000, 0x583FFF, SM_RAM); // another tilemap? + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K, + 0xF80000, 0xF8FFFF, SM_RAM); // work ram? + SekMapMemory((UINT8 *)Ram68K+0x010000, + 0x680000, 0x68001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x010020, + 0x780000, 0x78001F, SM_RAM); // regs? + + SekSetReadWordHandler(0, GalpanicReadWord); + SekSetReadByteHandler(0, ComadReadByte); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 WownfantInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 3, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomGfx + 0x080000, 5, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 6, 1); + BurnLoadRom(RomSnd + 0x0C0000, 7, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x4FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamBgM, + 0x580000, 0x583FFF, SM_RAM); // another tilemap? + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K, + 0xF80000, 0xF8FFFF, SM_RAM); // work ram? + SekMapMemory((UINT8 *)Ram68K+0x010000, + 0x680000, 0x68001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x010020, + 0x780000, 0x78001F, SM_RAM); // regs? + + SekSetReadWordHandler(0, GalpanicReadWord); + SekSetReadByteHandler(0, ComadReadByte); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 GalhustlInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + DeCodeGfx(); + + BurnLoadRom(RomSnd + 0x040000, 3, 1); + BurnLoadRom(RomSnd + 0x0C0000, 4, 1); + memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground +// SekMapMemory((UINT8 *)RamBgM, +// 0x580000, 0x583FFF, SM_RAM); // another tilemap? +// SekMapHandler(1, 0x580000, 0x583FFF, SM_WRITE); + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K, + 0x680000, 0x68001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x000020, + 0x780000, 0x78001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x000040, + 0xE80000, 0xE8FFFF, SM_RAM); // work ram? + + SekSetReadWordHandler(0, GalhustlReadWord); + SekSetReadByteHandler(0, GalhustlReadByte); + SekSetWriteWordHandler(0, GalhustlWriteWord); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 12000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 ZipzapInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex2(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex2(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x300000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400001, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x400000, 9, 2); if (nRet != 0) return 1; + +// Rom68K[0x0bc4] = 0x71; +// Rom68K[0x0bc5] = 0x4e; + + nRet = BurnLoadRom(RomGfx + 0x000000, 10, 1); if (nRet != 0) return 1; + DeCodeGfx(); + +// BurnLoadRom(RomSnd + 0x040000, 11, 1); +// BurnLoadRom(RomSnd + 0x0C0000, 11, 1); +// memcpy(RomSnd, RomSnd + 0x040000, 0x040000); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x4FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamFg, + 0x500000, 0x51FFFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamBg, + 0x520000, 0x53FFFF, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamBgM, + 0x580000, 0x583FFF, SM_RAM); // another tilemap? +// SekMapHandler(1, 0x580000, 0x583FFF, SM_WRITE); + SekMapMemory((UINT8 *)RamPal, + 0x600000, 0x600FFF, SM_RAM); // palette + SekMapMemory((UINT8 *)RamSpr, + 0x700000, 0x700FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)Ram68K, + 0xC80000, 0xC8FFFF, SM_RAM); // work ram? + SekMapMemory((UINT8 *)Ram68K+0x010000, + 0x680000, 0x68001F, SM_RAM); // regs? + SekMapMemory((UINT8 *)Ram68K+0x010020, + 0x780000, 0x78001F, SM_RAM); // regs? +// SekMapMemory((UINT8 *)Ram68K+0x010040, +// 0x701000, 0x71FFFF, SM_RAM); // work ram? + + SekSetReadWordHandler(0, GalhustlReadWord); + SekSetReadByteHandler(0, GalhustlReadByte); + SekSetWriteByteHandler(0, ComadWriteByte); + + SekClose(); + } + + MSM6295ROM = RomSnd; + MSM6295Init(0, 8000, 80, 0); + + RecalcBgPalette = 1; + + DrvDoReset(); + return 0; +} + +static INT32 GalpanicExit() +{ + SekExit(); + MSM6295Exit(0); + + BurnFree(Mem); + + RecalcBgPalette = 0; + return 0; +} + +static void drawgfx(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + UINT16 * p = (UINT16 *) pBurnDraw; + UINT8 * q = DeRomGfx + (code) * 256; + UINT32 * pal = RamCurPal + 256; + + p += sy * 256 + sx; + + if ((sx < 0) || (sx >= 240) || (sy < 0) || (sy >= 208)) { + + if ((sx <= -16) || (sx >= 256) || (sy <= -16) || (sy >= 224)) + return ; + + // clip + if (!flipy) { + p += 256 * 15; + + if (!flipx) { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] && ((sx + 15) >= 0) && ((sx + 15)<256)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] && ((sx + 14) >= 0) && ((sx + 14)<256)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] && ((sx + 13) >= 0) && ((sx + 13)<256)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] && ((sx + 12) >= 0) && ((sx + 12)<256)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] && ((sx + 11) >= 0) && ((sx + 11)<256)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] && ((sx + 10) >= 0) && ((sx + 10)<256)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] && ((sx + 9) >= 0) && ((sx + 9)<256)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] && ((sx + 8) >= 0) && ((sx + 8)<256)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] && ((sx + 7) >= 0) && ((sx + 7)<256)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] && ((sx + 6) >= 0) && ((sx + 6)<256)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] && ((sx + 5) >= 0) && ((sx + 5)<256)) p[ 5] = pal[ q[10] | color]; + if (q[11] && ((sx + 4) >= 0) && ((sx + 4)<256)) p[ 4] = pal[ q[11] | color]; + if (q[12] && ((sx + 3) >= 0) && ((sx + 3)<256)) p[ 3] = pal[ q[12] | color]; + if (q[13] && ((sx + 2) >= 0) && ((sx + 2)<256)) p[ 2] = pal[ q[13] | color]; + if (q[14] && ((sx + 1) >= 0) && ((sx + 1)<256)) p[ 1] = pal[ q[14] | color]; + if (q[15] && ((sx + 0) >= 0) && ((sx + 0)<256)) p[ 0] = pal[ q[15] | color]; + } + p -= 256; + q += 16; + } + + } else { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] && ((sx + 0) >= 0) && ((sx + 0)<256)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] && ((sx + 1) >= 0) && ((sx + 1)<256)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] && ((sx + 2) >= 0) && ((sx + 2)<256)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] && ((sx + 3) >= 0) && ((sx + 3)<256)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] && ((sx + 4) >= 0) && ((sx + 4)<256)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] && ((sx + 5) >= 0) && ((sx + 5)<256)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] && ((sx + 6) >= 0) && ((sx + 6)<256)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] && ((sx + 7) >= 0) && ((sx + 7)<256)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] && ((sx + 8) >= 0) && ((sx + 8)<256)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] && ((sx + 9) >= 0) && ((sx + 9)<256)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] && ((sx + 10) >= 0) && ((sx + 10)<256)) p[10] = pal[ q[10] | color]; + if (q[11] && ((sx + 11) >= 0) && ((sx + 11)<256)) p[11] = pal[ q[11] | color]; + if (q[12] && ((sx + 12) >= 0) && ((sx + 12)<256)) p[12] = pal[ q[12] | color]; + if (q[13] && ((sx + 13) >= 0) && ((sx + 13)<256)) p[13] = pal[ q[13] | color]; + if (q[14] && ((sx + 14) >= 0) && ((sx + 14)<256)) p[14] = pal[ q[14] | color]; + if (q[15] && ((sx + 15) >= 0) && ((sx + 15)<256)) p[15] = pal[ q[15] | color]; + } + p -= 256; + q += 16; + } + } + + } else { + + if (!flipx) { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] && ((sx + 15) >= 0) && ((sx + 15)<256)) p[15] = pal[ q[ 0] | color]; + if (q[ 1] && ((sx + 14) >= 0) && ((sx + 14)<256)) p[14] = pal[ q[ 1] | color]; + if (q[ 2] && ((sx + 13) >= 0) && ((sx + 13)<256)) p[13] = pal[ q[ 2] | color]; + if (q[ 3] && ((sx + 12) >= 0) && ((sx + 12)<256)) p[12] = pal[ q[ 3] | color]; + if (q[ 4] && ((sx + 11) >= 0) && ((sx + 11)<256)) p[11] = pal[ q[ 4] | color]; + if (q[ 5] && ((sx + 10) >= 0) && ((sx + 10)<256)) p[10] = pal[ q[ 5] | color]; + if (q[ 6] && ((sx + 9) >= 0) && ((sx + 9)<256)) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7] && ((sx + 8) >= 0) && ((sx + 8)<256)) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8] && ((sx + 7) >= 0) && ((sx + 7)<256)) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9] && ((sx + 6) >= 0) && ((sx + 6)<256)) p[ 6] = pal[ q[ 9] | color]; + if (q[10] && ((sx + 5) >= 0) && ((sx + 5)<256)) p[ 5] = pal[ q[10] | color]; + if (q[11] && ((sx + 4) >= 0) && ((sx + 4)<256)) p[ 4] = pal[ q[11] | color]; + if (q[12] && ((sx + 3) >= 0) && ((sx + 3)<256)) p[ 3] = pal[ q[12] | color]; + if (q[13] && ((sx + 2) >= 0) && ((sx + 2)<256)) p[ 2] = pal[ q[13] | color]; + if (q[14] && ((sx + 1) >= 0) && ((sx + 1)<256)) p[ 1] = pal[ q[14] | color]; + if (q[15] && ((sx + 0) >= 0) && ((sx + 0)<256)) p[ 0] = pal[ q[15] | color]; + } + p += 256; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<224)) { + if (q[ 0] && ((sx + 0) >= 0) && ((sx + 0)<256)) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1] && ((sx + 1) >= 0) && ((sx + 1)<256)) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2] && ((sx + 2) >= 0) && ((sx + 2)<256)) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3] && ((sx + 3) >= 0) && ((sx + 3)<256)) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4] && ((sx + 4) >= 0) && ((sx + 4)<256)) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5] && ((sx + 5) >= 0) && ((sx + 5)<256)) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6] && ((sx + 6) >= 0) && ((sx + 6)<256)) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7] && ((sx + 7) >= 0) && ((sx + 7)<256)) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8] && ((sx + 8) >= 0) && ((sx + 8)<256)) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9] && ((sx + 9) >= 0) && ((sx + 9)<256)) p[ 9] = pal[ q[ 9] | color]; + if (q[10] && ((sx + 10) >= 0) && ((sx + 10)<256)) p[10] = pal[ q[10] | color]; + if (q[11] && ((sx + 11) >= 0) && ((sx + 11)<256)) p[11] = pal[ q[11] | color]; + if (q[12] && ((sx + 12) >= 0) && ((sx + 12)<256)) p[12] = pal[ q[12] | color]; + if (q[13] && ((sx + 13) >= 0) && ((sx + 13)<256)) p[13] = pal[ q[13] | color]; + if (q[14] && ((sx + 14) >= 0) && ((sx + 14)<256)) p[14] = pal[ q[14] | color]; + if (q[15] && ((sx + 15) >= 0) && ((sx + 15)<256)) p[15] = pal[ q[15] | color]; + } + p += 256; + q += 16; + } + } + } + + return; + } + + if (!flipy) { + + p += 256 * 15; + + if (!flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0]) p[15] = pal[ q[ 0] | color]; + if (q[ 1]) p[14] = pal[ q[ 1] | color]; + if (q[ 2]) p[13] = pal[ q[ 2] | color]; + if (q[ 3]) p[12] = pal[ q[ 3] | color]; + if (q[ 4]) p[11] = pal[ q[ 4] | color]; + if (q[ 5]) p[10] = pal[ q[ 5] | color]; + if (q[ 6]) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7]) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8]) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9]) p[ 6] = pal[ q[ 9] | color]; + if (q[10]) p[ 5] = pal[ q[10] | color]; + if (q[11]) p[ 4] = pal[ q[11] | color]; + if (q[12]) p[ 3] = pal[ q[12] | color]; + if (q[13]) p[ 2] = pal[ q[13] | color]; + if (q[14]) p[ 1] = pal[ q[14] | color]; + if (q[15]) p[ 0] = pal[ q[15] | color]; + + p -= 256; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0]) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1]) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2]) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3]) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4]) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5]) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6]) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7]) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8]) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9]) p[ 9] = pal[ q[ 9] | color]; + if (q[10]) p[10] = pal[ q[10] | color]; + if (q[11]) p[11] = pal[ q[11] | color]; + if (q[12]) p[12] = pal[ q[12] | color]; + if (q[13]) p[13] = pal[ q[13] | color]; + if (q[14]) p[14] = pal[ q[14] | color]; + if (q[15]) p[15] = pal[ q[15] | color]; + + p -= 256; + q += 16; + } + } + + } else { + + if (!flipx) { + + for (INT32 i=0;i<16;i++) { + if (q[ 0]) p[15] = pal[ q[ 0] | color]; + if (q[ 1]) p[14] = pal[ q[ 1] | color]; + if (q[ 2]) p[13] = pal[ q[ 2] | color]; + if (q[ 3]) p[12] = pal[ q[ 3] | color]; + if (q[ 4]) p[11] = pal[ q[ 4] | color]; + if (q[ 5]) p[10] = pal[ q[ 5] | color]; + if (q[ 6]) p[ 9] = pal[ q[ 6] | color]; + if (q[ 7]) p[ 8] = pal[ q[ 7] | color]; + + if (q[ 8]) p[ 7] = pal[ q[ 8] | color]; + if (q[ 9]) p[ 6] = pal[ q[ 9] | color]; + if (q[10]) p[ 5] = pal[ q[10] | color]; + if (q[11]) p[ 4] = pal[ q[11] | color]; + if (q[12]) p[ 3] = pal[ q[12] | color]; + if (q[13]) p[ 2] = pal[ q[13] | color]; + if (q[14]) p[ 1] = pal[ q[14] | color]; + if (q[15]) p[ 0] = pal[ q[15] | color]; + + p += 256; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (q[ 0]) p[ 0] = pal[ q[ 0] | color]; + if (q[ 1]) p[ 1] = pal[ q[ 1] | color]; + if (q[ 2]) p[ 2] = pal[ q[ 2] | color]; + if (q[ 3]) p[ 3] = pal[ q[ 3] | color]; + if (q[ 4]) p[ 4] = pal[ q[ 4] | color]; + if (q[ 5]) p[ 5] = pal[ q[ 5] | color]; + if (q[ 6]) p[ 6] = pal[ q[ 6] | color]; + if (q[ 7]) p[ 7] = pal[ q[ 7] | color]; + + if (q[ 8]) p[ 8] = pal[ q[ 8] | color]; + if (q[ 9]) p[ 9] = pal[ q[ 9] | color]; + if (q[10]) p[10] = pal[ q[10] | color]; + if (q[11]) p[11] = pal[ q[11] | color]; + if (q[12]) p[12] = pal[ q[12] | color]; + if (q[13]) p[13] = pal[ q[13] | color]; + if (q[14]) p[14] = pal[ q[14] | color]; + if (q[15]) p[15] = pal[ q[15] | color]; + + p += 256; + q += 16; + } + + } + + } + +} + +static INT32 GalpanicDraw() +{ + if (RecalcBgPalette) { + for (INT32 i = 0; i < 32768; i++) { + INT32 r = pal5bit(i >> 5); + INT32 g = pal5bit(i >> 10); + INT32 b = pal5bit(i >> 0); + RamCTB64k[i] = BurnHighCol(r, g, b, 0); + } + + RecalcBgPalette = 0; + } + + for (INT32 i = 0; i < 1024; i++) { + UINT16 nColour = RamPal[i]; + INT32 r = pal5bit(nColour >> 6); + INT32 g = pal5bit(nColour >> 11); + INT32 b = pal5bit(nColour >> 1); + RamCurPal[i] = BurnHighCol(r, g, b, 0); + } + + UINT16 * d = (UINT16 *)pBurnDraw + ( 224 * 256 ) - 1; + UINT16 * s = (UINT16 *)RamBg; + UINT16 * f = (UINT16 *)RamFg; + for (INT32 j=0;j<224;j++) { + for (INT32 i=0;i<256;i++) { + if (*f) *d = RamCurPal[*f]; + else *d = RamCTB64k[*s >> 1]; + d--; + s++; + f++; + } + } + + INT32 sx, sy; + sx = sy = 0; + for (INT32 offs=0; offs<0x002400; offs+=0x08) { + INT32 x,y,code,color,flipx,flipy,attr1,attr2; + + attr1 = RamSpr[offs + 3]; + x = RamSpr[offs + 4] - ((attr1 & 0x01) << 8); + y = RamSpr[offs + 5] + ((attr1 & 0x02) << 7); + if (attr1 & 0x04) /* multi sprite */ + { + sx += x; + sy += y; + } + else + { + sx = x; + sy = y; + } + + color = (attr1 & 0xf0); + + /* bit 0 [offs + 0] is used but I don't know what for */ + + attr2 = RamSpr[offs + 7]; + code = RamSpr[offs + 6] + ((attr2 & 0x1f) << 8); + flipx = attr2 & 0x80; + flipy = attr2 & 0x40; + + drawgfx(code, color, flipx, flipy, 256-sx-16, 224-(sy - 16)-16); + //drawgfx(code, color, flipx, flipy, sx, (sy - 16)); + } + + return 0; +} + +static INT32 ComadDraw() +{ + if (RecalcBgPalette) { + for (INT32 i = 0; i < 32768; i++) { + INT32 r = pal5bit(i >> 5); + INT32 g = pal5bit(i >> 10); + INT32 b = pal5bit(i >> 0); + RamCTB64k[i] = BurnHighCol(r, g, b, 0); + } + + RecalcBgPalette = 0; + } + + for (INT32 i = 0; i < 1024; i++) { + UINT16 nColour = RamPal[i]; + INT32 r = pal5bit(nColour >> 6); + INT32 g = pal5bit(nColour >> 11); + INT32 b = pal5bit(nColour >> 1); + RamCurPal[i] = BurnHighCol(r, g, b, 0); + } + + UINT16 * d = (UINT16 *)pBurnDraw + ( 224 * 256 ) - 1; + UINT16 * s = (UINT16 *)RamBg; + UINT16 * f = (UINT16 *)RamFg; + for (INT32 j=0;j<224;j++) { + for (INT32 i=0;i<256;i++) { + if (*f) *d = RamCurPal[*f]; + else *d = RamCTB64k[*s >> 1]; + d--; + s++; + f++; + } + } + + INT32 sx, sy; + sx = sy = 0; + for (INT32 offs=0; offs<0x000800; offs+=4) { + INT32 code,color,flipx,flipy; + + code = RamSpr[offs + 1] & 0x1fff; + color = (RamSpr[offs] & 0x003c) << 2; + flipx = RamSpr[offs] & 0x0002; + flipy = RamSpr[offs] & 0x0001; + + if((RamSpr[offs] & 0x6000) == 0x6000) /* Link bits */ + { + sx += RamSpr[offs + 2] >> 6; + sy += RamSpr[offs + 3] >> 6; + } + else + { + sx = RamSpr[offs + 2] >> 6; + sy = RamSpr[offs + 3] >> 6; + } + + sx = (sx&0x1ff) - (sx&0x200); + sy = (sy&0x1ff) - (sy&0x200); + + drawgfx(code, color, flipx, flipy, 256-sx-16, 224-sy-16); + } + + return 0; +} + +static INT32 GalpanicFrame() +{ + if (DrvReset) // Reset machine + DrvDoReset(); + + DrvInput[1] = 0x0000; // Joy1 + DrvInput[3] = 0x0000; // Joy2 + DrvInput[5] = 0x0000; // Buttons + for (INT32 i = 0; i < 5; i++) { + DrvInput[1] |= (DrvJoy1[i] & 1) << i; + DrvInput[3] |= (DrvJoy2[i] & 1) << i; + } + for (INT32 i = 0; i < 7; i++) { + DrvInput[5] |= (DrvButton[i] & 1) << i; + } + + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + + SekNewFrame(); + + SekOpen(0); + + SekRun(nCyclesTotal[0] / 2); + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); // let game run ??? + SekRun(nCyclesTotal[0] / 2); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); // update palette + + SekClose(); + + if (pBurnDraw) + GalpanicDraw(); // Draw screen if needed + if (pBurnSoundOut) + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + return 0; +} + +static INT32 ComadFrame() +{ + if (DrvReset) // Reset machine + DrvDoReset(); + + DrvInput[1] = 0x0000; // Joy1 + DrvInput[3] = 0x0000; // Joy2 + DrvInput[5] = 0x0000; // Buttons + for (INT32 i = 0; i < 5; i++) { + DrvInput[1] |= (DrvJoy1[i] & 1) << i; + DrvInput[3] |= (DrvJoy2[i] & 1) << i; + } + for (INT32 i = 0; i < 7; i++) { + DrvInput[5] |= (DrvButton[i] & 1) << i; + } + + // Clear Opposites + ComadClearOpposites(&DrvInput[1]); + ComadClearOpposites(&DrvInput[3]); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "supmodel") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fantsia2") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fantsia2a") || !strcmp(BurnDrvGetTextA(DRV_NAME), "wownfant")) { + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + } else { + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + } + + SekOpen(0); + SekNewFrame(); + + SekRun(nCyclesTotal[0] / 4); + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); // let game run + SekRun(nCyclesTotal[0] / 4); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); // enable icons + SekRun(nCyclesTotal[0] / 4); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); // update palette + SekRun(nCyclesTotal[0] / 4); + + SekClose(); + + if (pBurnSoundOut) + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) + ComadDraw(); // Draw screen if needed + + return 0; +} + +static INT32 GalhustlFrame() +{ + if (DrvReset) // Reset machine + DrvDoReset(); + + DrvInput[1] = 0x0000; // Joy1 + DrvInput[3] = 0x0000; // Joy2 + DrvInput[5] = 0x0000; // Buttons + for (INT32 i = 0; i < 8; i++) { + DrvInput[1] |= (DrvJoy1[i] & 1) << i; + DrvInput[3] |= (DrvJoy2[i] & 1) << i; + } + for (INT32 i = 0; i < 7; i++) { + DrvInput[5] |= (DrvButton[i] & 1) << i; + } + + INT32 nInterleave = 4; + + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 1) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + if (pBurnSoundOut) + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) + ComadDraw(); // Draw screen if needed + + return 0; +} + +static INT32 GalpanicScan(INT32 nAction,INT32 *pnMin) +{ +struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029671; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // Scan 68000 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + + // Scan critical driver variables + SCAN_VAR(SndBank); + SCAN_VAR(DrvInput); + SCAN_VAR(RamCurPal); + SCAN_VAR(RamCTB64k); + + if (nAction & ACB_WRITE) { + memcpy(&RomSnd[0x30000], &RomSnd[0x40000 + SndBank * 0x10000], 0x10000); + } + } + + return 0; +} + +struct BurnDriver BurnDrvGalpanic = { + "galpanic", NULL, NULL, NULL, "1990", + "Gals Panic (Unprotected)\0", NULL, "Kaneko", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, GalpanicRomInfo, GalpanicRomName, NULL, NULL, GalpanicInputInfo, GalpanicDIPInfo, + GalpanicInit, GalpanicExit, GalpanicFrame, GalpanicDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFantasia = { + "fantasia", NULL, NULL, NULL, "1994", + "Fantasia\0", NULL, "Comad / New Japan System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, FantasiaRomInfo, FantasiaRomName, NULL, NULL, GalpanicInputInfo, FantasiaDIPInfo, + FantasiaInit, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSupmodel = { + "supmodel", NULL, NULL, NULL, "1994", + "Super Model\0", NULL, "Comad / New Japan System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, SupmodelRomInfo, SupmodelRomName, NULL, NULL, GalpanicInputInfo, FantasiaDIPInfo, + FantasiaInit, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNewfant = { + "newfant", NULL, NULL, NULL, "1995", + "New Fantasia\0", NULL, "Comad / New Japan System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, NewfantRomInfo, NewfantRomName, NULL, NULL, GalpanicInputInfo, FantasiaDIPInfo, + FantasiaInit, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvFantsy95 = { + "fantsy95", NULL, NULL, NULL, "1995", + "Fantasy '95\0", NULL, "Hi-max Technology Inc.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Fantsy95RomInfo, Fantsy95RomName, NULL, NULL, GalpanicInputInfo, FantasiaDIPInfo, + FantasiaInit, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvMissw96 = { + "missw96", NULL, NULL, NULL, "1996", + "Miss World '96 (Nude)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Missw96RomInfo, Missw96RomName, NULL, NULL, GalpanicInputInfo, Missw96DIPInfo, + Missw96Init, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMissmw96 = { + "missmw96", "missw96", NULL, NULL, "1996", + "Miss Mister World '96 (Nude)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Missmw96RomInfo, Missmw96RomName, NULL, NULL, GalpanicInputInfo, Missw96DIPInfo, + Missw96Init, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantsia2 = { + "fantsia2", NULL, NULL, NULL, "1997", + "Fantasia II (Explicit)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Fantsia2RomInfo, Fantsia2RomName, NULL, NULL, GalpanicInputInfo, Missw96DIPInfo, + Fantsia2Init, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantsia2a = { + "fantsia2a", "fantsia2", NULL, NULL, "1997", + "Fantasia II (Less Explicit)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Fantsia2aRomInfo, Fantsia2aRomName, NULL, NULL, GalpanicInputInfo, Missw96DIPInfo, + Fantsia2Init, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWownfant = { + "wownfant", NULL, NULL, NULL, "2002", + "WOW New Fantasia\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, WownfantRomInfo, WownfantRomName, NULL, NULL, GalpanicInputInfo, Missw96DIPInfo, + WownfantInit, GalpanicExit, ComadFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGalhustl = { + "galhustl", NULL, NULL, NULL, "1997", + "Gals Hustler\0", NULL, "ACE International", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, GalhustlRomInfo, GalhustlRomName, NULL, NULL, GalhustlInputInfo, GalhustlDIPInfo, + GalhustlInit, GalpanicExit, GalhustlFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvZipzap = { + "zipzap", NULL, NULL, NULL, "1995", + "Zip & Zap\0", "Imperfect GFXs, No Sound", "Barko Corp", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_BREAKOUT, 0, + NULL, ZipzapRomInfo, ZipzapRomName, NULL, NULL, GalhustlInputInfo, ZipzapDIPInfo, + ZipzapInit, GalpanicExit, GalhustlFrame, ComadDraw, GalpanicScan, &RecalcBgPalette, 0x400, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_gotcha.cpp b/src/burn/drivers/misc_post90s/d_gotcha.cpp new file mode 100644 index 00000000..53543f95 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_gotcha.cpp @@ -0,0 +1,663 @@ +// FB Alpha "Got-ya" driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvSndBank; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvGfxBank; +static UINT16 *DrvScrollx; +static UINT16 *DrvScrolly; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static UINT8 *bankselect; +static UINT8 *soundlatch; + +static struct BurnInputInfo GotchaInputList[] = { + {"Coin A", BIT_DIGITAL, DrvJoy2 + 8, "p1 coin" }, + {"Coin B", BIT_DIGITAL, DrvJoy2 + 9, "p2 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p2 fire 3" }, + + {"P3 Start", BIT_DIGITAL, DrvJoy1 + 11, "p3 start" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy1 + 8, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy1 + 9, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy1 + 10, "p3 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Gotcha) + +static struct BurnDIPInfo GotchaDIPList[]= +{ + {0x0f, 0xff, 0xff, 0x97, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x0f, 0x01, 0x07, 0x07, "1" }, + {0x0f, 0x01, 0x07, 0x06, "2" }, + {0x0f, 0x01, 0x07, 0x05, "3" }, + {0x0f, 0x01, 0x07, 0x04, "4" }, + {0x0f, 0x01, 0x07, 0x03, "5" }, + {0x0f, 0x01, 0x07, 0x02, "6" }, + {0x0f, 0x01, 0x07, 0x01, "7" }, + {0x0f, 0x01, 0x07, 0x00, "8" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x08, "Off" }, + {0x0f, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0x30, 0x30, "1" }, + {0x0f, 0x01, 0x30, 0x20, "2" }, + {0x0f, 0x01, 0x30, 0x10, "3" }, + {0x0f, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x0f, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin/99 Credits" }, + + {0 , 0xfe, 0 , 2, "Info" }, + {0x10, 0x01, 0x01, 0x01, "Off" }, + {0x10, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Explane Type" }, + {0x10, 0x01, 0x02, 0x02, "Off" }, + {0x10, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Game Selection" }, + {0x10, 0x01, 0x04, 0x00, "Off" }, + {0x10, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Gotcha) + +static void set_okibank(INT32 data) +{ + *DrvSndBank = data & 1; + + INT32 nBank = (~data & 1) << 18; + + memcpy(MSM6295ROM + 0x00000, DrvSndROM + nBank, 0x40000); +} + +void __fastcall gotcha_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x100004: + set_okibank(data); + return; + + case 0x300000: + *bankselect = data & 3; + return; + + case 0x30000e: + DrvGfxBank[*bankselect] = data & 0x0f; + return; + } +} + +void __fastcall gotcha_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x100000: + *soundlatch = data & 0xff; + return; + + case 0x300002: + case 0x300006: + DrvScrollx[(address >> 2) & 1] = data & 0x3ff; + return; + + case 0x300004: + case 0x300008: + DrvScrolly[(address >> 3) & 1] = (data + 8) & 0x1ff; + return; + } +} + +UINT8 __fastcall gotcha_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180002: + return DrvInputs[1] >> 8; + } + + return 0; +} + +UINT16 __fastcall gotcha_read_word(UINT32 address) +{ + switch (address) + { + case 0x180000: + return DrvInputs[0]; + + case 0x180004: + return DrvInputs[2]; + } + + return 0; +} + +void __fastcall gotcha_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: + BurnYM2151SelectRegister(data); + return; + + case 0xc001: + BurnYM2151WriteRegister(data); + return; + + case 0xc002: + case 0xc003: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall gotcha_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc001: + return BurnYM2151ReadStatus(); + + case 0xc006: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + set_okibank(1); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + +// MSM6295ROM = Next; + MSM6295ROM = Next; Next += 0x040000; + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x001000; + DrvBgRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + DrvScrollx = (UINT16*)Next; Next += 0x000002 * sizeof(UINT16); + DrvScrolly = (UINT16*)Next; Next += 0x000002 * sizeof(UINT16); + + DrvGfxBank = Next; Next += 0x000004; + + DrvSndBank = Next; Next += 0x000001; + + bankselect = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000000, 0x400000, 0x800000, 0xc00000 }; + INT32 XOffs[16] = { 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 4, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 5, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 6, 1)) return 1; // gfx0 + for (INT32 i = 0; i < 0x200000; i++) { + INT32 j = ((i & 0x20000) << 3) | ((i & 0x1c0000) >> 1) | ((i & 0x1ffff)^0x10); + DrvGfxROM0[j] = DrvGfxROM1[i]; + } + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 9, 1)) return 1; // gfx0 + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 10, 1)) return 1; // gfx0 + + if (BurnLoadRom(DrvSndROM, 11, 1)) return 1; + memcpy(MSM6295ROM, DrvSndROM, 0x40000); + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x120000, 0x12ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x320000, 0x320fff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x322000, 0x322fff, SM_RAM); + SekSetWriteWordHandler(0, gotcha_write_word); + SekSetWriteByteHandler(0, gotcha_write_byte); + SekSetReadWordHandler(0, gotcha_read_word); + SekSetReadByteHandler(0, gotcha_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xd000, 0xd7ff, 0, DrvZ80RAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvZ80RAM); + ZetMapArea(0xd000, 0xd7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(gotcha_sound_write); + ZetSetReadHandler(gotcha_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1000000 / 132, 100.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_layer(UINT8 *ram, INT32 col, INT32 scrollx, INT32 scrolly, INT32 transp) +{ + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x400; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + INT32 ofst = (offs & 0x1f) | ((offs & 0x7c0)>>1) | ((offs & 0x20) << 5); + + INT32 attr = vram[ofst]; + INT32 code = (attr & 0x3ff) | (DrvGfxBank[(attr >> 10) & 3] << 10); + INT32 color = (attr >> 12) | col; + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, transp, 0, DrvGfxROM0); + } +} + +static void draw_sprites() +{ + UINT16 *vram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x800/2; offs += 4) + { + INT32 sx = 0x13b - ((vram[offs + 2] + 0x10) & 0x1ff); + INT32 sy = vram[offs + 0] + 8; + INT32 code = vram[offs + 1] & 0x3fff; + INT32 color = vram[offs + 2] >> 9; + INT32 height = 1 << ((vram[offs + 0] & 0x0600) >> 9); + INT32 flipx = vram[offs + 0] & 0x2000; + INT32 flipy = vram[offs + 0] & 0x4000; + + for (INT32 y = 0; y < height; y++) + { + INT32 yy = 0x101 - ((sy + 0x10 * (height - y)) & 0x1ff); + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code + height-1 - y, sx, yy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code + height-1 - y, sx, yy, color, 4, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code + y, sx, yy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code + y, sx, yy, color, 4, 0, 0, DrvGfxROM1); + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x600/2; i++) { + INT32 d = pal[i]; + + r = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + draw_layer(DrvBgRAM, 32, DrvScrollx[1]+5, DrvScrolly[1], ~0); + draw_layer(DrvFgRAM, 16, DrvScrollx[0]+1, DrvScrolly[0], 0); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[2] = (DrvDips[0]) | (DrvDips[1] << 8); + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 14318180 / 60, 6000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nSegment); + + nSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + nCyclesDone[1] += ZetRun(nSegment); + + if (pBurnSoundOut) { + nSegment = nBurnSoundLen / nInterleave; + + BurnYM2151Render(pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + MSM6295Render(0, pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + + nSoundBufferPos += nSegment; + } + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + nSegment = nBurnSoundLen - nSoundBufferPos; + if (nSegment > 0) { + BurnYM2151Render(pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + MSM6295Render(0, pBurnSoundOut + (nSoundBufferPos << 1), nSegment); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + set_okibank(*DrvSndBank); + } + + return 0; +} + + +// Got-cha Mini Game Festival + +static struct BurnRomInfo gotchaRomDesc[] = { + { "gotcha.u3", 0x40000, 0x5e5d52e0, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gotcha.u2", 0x40000, 0x3aa8eaff, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gotcha_u.z02", 0x10000, 0xf4f6e16b, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "gotcha-u.42a", 0x80000, 0x4ea822f0, 3 | BRF_GRA }, // 3 Tiles + { "gotcha-u.42b", 0x80000, 0x6bb529ac, 3 | BRF_GRA }, // 4 + { "gotcha-u.41a", 0x80000, 0x49299b7b, 3 | BRF_GRA }, // 5 + { "gotcha-u.41b", 0x80000, 0xc093f04e, 3 | BRF_GRA }, // 6 + + { "gotcha.u56", 0x80000, 0x85f6a062, 4 | BRF_GRA }, // 7 Sprites + { "gotcha.u55", 0x80000, 0x426b4e48, 4 | BRF_GRA }, // 8 + { "gotcha.u54", 0x80000, 0x903e05a4, 4 | BRF_GRA }, // 9 + { "gotcha.u53", 0x80000, 0x3c24d51e, 4 | BRF_GRA }, // 10 + + { "gotcha-u.z11", 0x80000, 0x6111c6ae, 5 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(gotcha) +STD_ROM_FN(gotcha) + +struct BurnDriver BurnDrvGotcha = { + "gotcha", NULL, NULL, NULL, "1997", + "Got-cha Mini Game Festival\0", NULL, "Dongsung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, gotchaRomInfo, gotchaRomName, NULL, NULL, GotchaInputInfo, GotchaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; + + +// Pasha Pasha Champ Mini Game Festival + +static struct BurnRomInfo ppchampRomDesc[] = { + { "u3", 0x40000, 0xf56c0fc2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2", 0x40000, 0xa941ffdc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "uz02", 0x10000, 0xf4f6e16b, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "u42a", 0x80000, 0xf0b521d1, 3 | BRF_GRA }, // 3 Tiles + { "u42b", 0x80000, 0x1107918e, 3 | BRF_GRA }, // 4 + { "u41a", 0x80000, 0x3f567d33, 3 | BRF_GRA }, // 5 + { "u41b", 0x80000, 0x18a3497e, 3 | BRF_GRA }, // 6 + + { "u56", 0x80000, 0x160e46b3, 4 | BRF_GRA }, // 7 Sprites + { "u55", 0x80000, 0x7351b61c, 4 | BRF_GRA }, // 8 + { "u54", 0x80000, 0xa3d8c5ef, 4 | BRF_GRA }, // 9 + { "u53", 0x80000, 0x10ca65c4, 4 | BRF_GRA }, // 10 + + { "uz11", 0x80000, 0x3d96274c, 5 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(ppchamp) +STD_ROM_FN(ppchamp) + +struct BurnDriver BurnDrvPpchamp = { + "ppchamp", "gotcha", NULL, NULL, "1997", + "Pasha Pasha Champ Mini Game Festival\0", NULL, "Dongsung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, ppchampRomInfo, ppchampRomName, NULL, NULL, GotchaInputInfo, GotchaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_gumbo.cpp b/src/burn/drivers/misc_post90s/d_gumbo.cpp new file mode 100644 index 00000000..e68bb534 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_gumbo.cpp @@ -0,0 +1,773 @@ +// FB Alpha Gumbo driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvBgRAM; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo GumboInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 6, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 7, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 12, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 13, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 14, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 15, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Gumbo) + +static struct BurnInputInfo DblpointInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 6, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 7, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 3" }, + + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 12, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 13, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 14, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 15, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 9, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Dblpoint) + +static struct BurnDIPInfo GumboDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x0e, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Helps" }, + {0x0e, 0x01, 0x04, 0x00, "0" }, + {0x0e, 0x01, 0x04, 0x04, "1" }, + + {0 , 0xfe, 0 , 2, "Bonus Bar Level" }, + {0x0e, 0x01, 0x08, 0x08, "Normal" }, + {0x0e, 0x01, 0x08, 0x00, "High" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0e, 0x01, 0x30, 0x20, "Easy" }, + {0x0e, 0x01, 0x30, 0x30, "Normal" }, + {0x0e, 0x01, 0x30, 0x10, "Hard" }, + {0x0e, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Picture View" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Gumbo) + +static struct BurnDIPInfo MsbingoDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x0e, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Chance Count" }, + {0x0e, 0x01, 0x0c, 0x0c, "0" }, + {0x0e, 0x01, 0x0c, 0x08, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Play Level" }, + {0x0e, 0x01, 0x10, 0x10, "Normal" }, + {0x0e, 0x01, 0x10, 0x00, "Easy" }, + + {0 , 0xfe, 0 , 2, "Play Speed" }, + {0x0e, 0x01, 0x20, 0x20, "Normal" }, + {0x0e, 0x01, 0x20, 0x00, "High" }, + + {0 , 0xfe, 0 , 2, "Left Count" }, + {0x0e, 0x01, 0x40, 0x40, "Normal" }, + {0x0e, 0x01, 0x40, 0x00, "Low" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Msbingo) + +static struct BurnDIPInfo MspuzzleDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 4, "Time Mode" }, + {0x0e, 0x01, 0x03, 0x03, "0" }, + {0x0e, 0x01, 0x03, 0x02, "1" }, + {0x0e, 0x01, 0x03, 0x01, "2" }, + {0x0e, 0x01, 0x03, 0x00, "3" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x0e, 0x01, 0x0c, 0x00, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x0c, 0x04, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2, "Sound Test" }, + {0x0e, 0x01, 0x10, 0x10, "Off" }, + {0x0e, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "View Staff Credits" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Picture View" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Mspuzzle) + +static struct BurnDIPInfo DblpointDIPList[]= +{ + {0x10, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x10, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x0c, 0x0c, "Easy" }, + {0x10, 0x01, 0x0c, 0x08, "Normal" }, + {0x10, 0x01, 0x0c, 0x04, "Hard" }, + {0x10, 0x01, 0x0c, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Sound Test" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Picture View" }, + {0x10, 0x01, 0x20, 0x20, "Off" }, + {0x10, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Dblpoint) + +void __fastcall gumbo_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x1b0300: + case 0x1c0300: + MSM6295Command(0, data); + return; + } +} + +UINT16 __fastcall gumbo_read_word(UINT32 address) +{ + switch (address) + { + case 0x1b0100: + case 0x1c0100: + return DrvInputs[0]; + + case 0x1b0200: + case 0x1c0200: + return DrvInputs[1]; + + case 0x1b0300: + case 0x1c0300: + return MSM6295ReadStatus(0); + } + + return 0; +} + +void __fastcall gumbo_write_byte(UINT32, UINT8) +{ +} + +UINT8 __fastcall gumbo_read_byte(UINT32) +{ + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs0[8] = { 0, 0x800000, 8, 0x800008, 16, 0x800010, 24, 0x800018 }; + INT32 XOffs1[4] = { 0, 0x200000, 8, 0x200008 }; + INT32 YOffs0[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + INT32 YOffs1[4] = { 0, 16, 32, 48 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x200000); + + GfxDecode(0x8000, 8, 8, 8, Plane, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x080000); + + GfxDecode(0x8000, 8, 4, 4, Plane, XOffs1, YOffs1, 0x040, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x080000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000400; + DrvBgRAM = Next; Next += 0x002000; + DrvFgRAM = Next; Next += 0x008000; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 GumboInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + INT32 dblpoin = strncmp(BurnDrvGetTextA(DRV_NAME), "dblpoin", 7) ? 0 : 0x10000; + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 6, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x083fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x1b0000, 0x1b03ff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x1e0000^dblpoin, 0x1e0fff^dblpoin, SM_RAM); + SekMapMemory(DrvFgRAM, 0x1f0000^dblpoin, 0x1f3fff^dblpoin, SM_RAM); + SekSetWriteByteHandler(0, gumbo_write_byte); + SekSetReadByteHandler(0, gumbo_read_byte); + SekSetWriteWordHandler(0, gumbo_write_word); + SekSetReadWordHandler(0, gumbo_read_word); + SekClose(); + + MSM6295Init(0, 1122000 / 132, 100.0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 MspuzzleInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvSndROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 4, 1)) return 1; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "msbingo")) { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 6, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x180000, 8, 1)) return 1; + } + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x1a0000, 0x1a03ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x190000, 0x197fff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x1c0000, 0x1c1fff, SM_RAM); + SekSetWriteByteHandler(0, gumbo_write_byte); + SekSetReadByteHandler(0, gumbo_read_byte); + SekSetWriteWordHandler(0, gumbo_write_word); + SekSetReadWordHandler(0, gumbo_read_word); + SekClose(); + + MSM6295Init(0, 1122000 / 132, 100.0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_background() +{ + UINT16 *vram = (UINT16*)DrvBgRAM; + + for (INT32 offs = 0x80; offs < 0x780; offs++) + { + INT32 sx = ((offs & 0x3f) << 3) - 64; + INT32 sy = ((offs >> 6) << 3) - 16; + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 code = vram[offs] & 0x7fff; + + Render8x8Tile(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0); + } +} + +static void draw_foreground() +{ + UINT16 *vram = (UINT16*)DrvFgRAM; + + for (INT32 offs = 0x200; offs < 0x1e00; offs++) + { + INT32 sx = ((offs & 0x7f) << 2) - 64; + INT32 sy = ((offs >> 7) << 2) - 16; + INT32 code = vram[offs] & 0x7fff; + + if (sx < 0 || sx >= nScreenWidth) continue; + + UINT16 *pDest = pTransDraw + (sy * nScreenWidth) + sx; + UINT8 *pSrc = DrvGfxROM1 + (code << 4); + + for (INT32 y = 0; y < 4; y++) + { + if (pSrc[0] != 0xff) pDest[0] = pSrc[0] | 0x100; + if (pSrc[1] != 0xff) pDest[1] = pSrc[1] | 0x100; + if (pSrc[2] != 0xff) pDest[2] = pSrc[2] | 0x100; + if (pSrc[3] != 0xff) pDest[3] = pSrc[3] | 0x100; + + pDest += nScreenWidth; + pSrc += 4; + } + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x200; i++) { + INT32 d = pal[i]; + + r = (d >> 7) & 0xf8; + g = (d >> 2) & 0xf8; + b = (d << 3) & 0xf8; + + r |= (r >> 5); + g |= (g >> 5); + b |= (b >> 5); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + draw_background(); + draw_foreground(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = ~0; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + DrvInputs[1] = (DrvDips[0] << 8) | 0x00ff; + } + + SekOpen(0); + SekRun(7159090 / 60); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Gumbo + +static struct BurnRomInfo gumboRomDesc[] = { + { "u1.bin", 0x20000, 0xe09899e4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2.bin", 0x20000, 0x60e59acb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.bin", 0x40000, 0x16fbe06b, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x20000, 0x97741798, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x20000, 0x1411451b, 3 | BRF_GRA }, // 4 + + { "u421.bin", 0x80000, 0x42445132, 4 | BRF_GRA }, // 5 Background Tiles + { "u420.bin", 0x80000, 0xde1f0e2f, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(gumbo) +STD_ROM_FN(gumbo) + +struct BurnDriver BurnDrvGumbo = { + "gumbo", NULL, NULL, NULL, "1994", + "Gumbo\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, gumboRomInfo, gumboRomName, NULL, NULL, GumboInputInfo, GumboDIPInfo, + GumboInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Miss Puzzle (Clone of Gumbo) + +static struct BurnRomInfo mspuzzlgRomDesc[] = { + { "u1", 0x20000, 0x95218ff1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2", 0x20000, 0x7ea7d96c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.bin", 0x40000, 0x16fbe06b, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x20000, 0x97741798, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x20000, 0x1411451b, 3 | BRF_GRA }, // 4 + + { "u420", 0x80000, 0x2b387153, 4 | BRF_GRA }, // 5 Background Tiles + { "u421", 0x80000, 0xafa06a93, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(mspuzzlg) +STD_ROM_FN(mspuzzlg) + +struct BurnDriver BurnDrvMspuzzlg = { + "mspuzzleg", "gumbo", NULL, NULL, "1994", + "Miss Puzzle (Clone of Gumbo)\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, mspuzzlgRomInfo, mspuzzlgRomName, NULL, NULL, GumboInputInfo, GumboDIPInfo, + GumboInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Miss Bingo + +static struct BurnRomInfo msbingoRomDesc[] = { + { "u1.bin", 0x20000, 0x6eeb6d89, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2.bin", 0x20000, 0xf15dd4b5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.bin", 0x40000, 0x55011f69, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x40000, 0x8a46d467, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x40000, 0xd5fd3e2e, 3 | BRF_GRA }, // 4 + + { "u421.bin", 0x80000, 0xb73f21ab, 4 | BRF_GRA }, // 5 Background Tiles + { "u420.bin", 0x80000, 0xc2fe9175, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(msbingo) +STD_ROM_FN(msbingo) + +struct BurnDriver BurnDrvMsbingo = { + "msbingo", NULL, NULL, NULL, "1994", + "Miss Bingo\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, msbingoRomInfo, msbingoRomName, NULL, NULL, GumboInputInfo, MsbingoDIPInfo, + MspuzzleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Miss Puzzle + +static struct BurnRomInfo mspuzzleRomDesc[] = { + { "u1.bin", 0x40000, 0xd9e63f12, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2.bin", 0x40000, 0x9c3fc677, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.bin", 0x40000, 0x0a223a38, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x40000, 0x505ee3c2, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x40000, 0x3d6b6c78, 3 | BRF_GRA }, // 4 + + { "u421.bin", 0x80000, 0x5387ab3a, 4 | BRF_GRA }, // 5 Background Tiles + { "u425.bin", 0x80000, 0xf53a9042, 4 | BRF_GRA }, // 6 + { "u420.bin", 0x80000, 0xc3f892e6, 4 | BRF_GRA }, // 7 + { "u426.bin", 0x80000, 0xc927e8da, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(mspuzzle) +STD_ROM_FN(mspuzzle) + +struct BurnDriver BurnDrvMspuzzle = { + "mspuzzle", NULL, NULL, NULL, "1994", + "Miss Puzzle\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, mspuzzleRomInfo, mspuzzleRomName, NULL, NULL, GumboInputInfo, MspuzzleDIPInfo, + MspuzzleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 320, 3, 4 +}; + + +// Miss Puzzle (Nudes) + +static struct BurnRomInfo mspuzzlenRomDesc[] = { + { "u1.rom", 0x20000, 0xec940df4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2.rom", 0x20000, 0x7b9cac82, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.rom", 0x40000, 0x8826b018, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x40000, 0x505ee3c2, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x40000, 0x3d6b6c78, 3 | BRF_GRA }, // 4 + + { "u421.rom", 0x80000, 0x3c567c55, 4 | BRF_GRA }, // 5 Background Tiles + { "u425.rom", 0x80000, 0x1c4c8fc1, 4 | BRF_GRA }, // 6 + { "u420.rom", 0x80000, 0xf52ab7fd, 4 | BRF_GRA }, // 7 + { "u426.rom", 0x80000, 0xc28b2743, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(mspuzzlen) +STD_ROM_FN(mspuzzlen) + +struct BurnDriverD BurnDrvMspuzzlen = { + "mspuzzlen", "mspuzzle", NULL, NULL, "1994", + "Miss Puzzle (Nudes)\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, mspuzzlenRomInfo, mspuzzlenRomName, NULL, NULL, GumboInputInfo, MspuzzleDIPInfo, + MspuzzleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 320, 3, 4 +}; + + +// Double Point + +static struct BurnRomInfo dblpointRomDesc[] = { + { "u1.bin", 0x20000, 0xb05c9e02, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u2.bin", 0x20000, 0xcab35cbe, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u210.rom", 0x40000, 0xd35f975c, 2 | BRF_SND }, // 2 Samples + + { "u512.bin", 0x40000, 0xb57b8534, 3 | BRF_GRA }, // 3 Foreground Tiles + { "u511.bin", 0x40000, 0x74ed13ff, 3 | BRF_GRA }, // 4 + + { "u421.bin", 0x80000, 0xb0e9271f, 4 | BRF_GRA }, // 5 Background Tiles + { "u420.bin", 0x80000, 0x252789e8, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(dblpoint) +STD_ROM_FN(dblpoint) + +struct BurnDriver BurnDrvDblpoint = { + "dblpoint", NULL, NULL, NULL, "1995", + "Double Point\0", NULL, "Min Corp.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, dblpointRomInfo, dblpointRomName, NULL, NULL, DblpointInputInfo, DblpointDIPInfo, + GumboInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + + +// Double Point (Dong Bang Electron, bootleg?) + +static struct BurnRomInfo dblpoindRomDesc[] = { + { "d12.bin", 0x20000, 0x44bc1bd9, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "d13.bin", 0x20000, 0x625a311b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "d11.bin", 0x40000, 0xd35f975c, 2 | BRF_SND }, // 2 Samples + + { "d14.bin", 0x40000, 0x41943db5, 3 | BRF_GRA }, // 3 Foreground Tiles + { "d15.bin", 0x40000, 0x6b899a51, 3 | BRF_GRA }, // 4 + + { "d16.bin", 0x80000, 0xafea0158, 4 | BRF_GRA }, // 5 Background Tiles + { "d17.bin", 0x80000, 0xc971dcb5, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(dblpoind) +STD_ROM_FN(dblpoind) + +struct BurnDriver BurnDrvDblpoind = { + "dblpointd", "dblpoint", NULL, NULL, "1995", + "Double Point (Dong Bang Electron, bootleg?)\0", NULL, "Dong Bang Electron", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, dblpoindRomInfo, dblpoindRomName, NULL, NULL, DblpointInputInfo, DblpointDIPInfo, + GumboInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_post90s/d_hyperpac.cpp b/src/burn/drivers/misc_post90s/d_hyperpac.cpp new file mode 100644 index 00000000..e83fbb63 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_hyperpac.cpp @@ -0,0 +1,4103 @@ +#include "tiles_generic.h" +#include "timer.h" +#include "msm6295.h" +#include "burn_ym2151.h" +#include "burn_ym3812.h" +#include "bitswap.h" + +static UINT8 HyperpacInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 HyperpacInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 HyperpacInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 HyperpacDip[2] = {0, 0}; +static UINT8 HyperpacInput[3] = {0x00, 0x00, 0x00}; +static UINT8 HyperpacReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *HyperpacRom = NULL; +static UINT8 *HyperpacZ80Rom = NULL; +static UINT8 *HyperpacRam = NULL; +static UINT8 *HyperpacPaletteRam = NULL; +static UINT8 *HyperpacSpriteRam = NULL; +static UINT8 *HyperpacZ80Ram = NULL; +static UINT32 *HyperpacPalette = NULL; +static UINT8 *HyperpacSprites = NULL; +static UINT8 *HyperpacSprites8bpp = NULL; +static UINT8 *HyperpacTempGfx = NULL; +static UINT8 *HyperpacProtData = NULL; + +static INT32 HyperpacSoundLatch; +static INT32 Moremore = 0; +static INT32 Threein1semi = 0; +static INT32 Cookbib3 = 0; +static INT32 Fourin1boot = 0; +static INT32 Finalttr = 0; +static INT32 Twinadv = 0; +static INT32 Honeydol = 0; +static INT32 Wintbob = 0; + +static INT32 HyperpacNumTiles = 0; +static INT32 HyperpacNumTiles8bpp = 0; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static INT32 Snowbro3MusicPlaying; +static INT32 Snowbro3Music; + +static struct BurnInputInfo HyperpacInputList[] = { + {"Coin 1" , BIT_DIGITAL , HyperpacInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , HyperpacInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , HyperpacInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , HyperpacInputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , HyperpacInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , HyperpacInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , HyperpacInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , HyperpacInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , HyperpacInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , HyperpacInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , HyperpacInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , HyperpacInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , HyperpacInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , HyperpacInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , HyperpacInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , HyperpacInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , HyperpacInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , HyperpacInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &HyperpacReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, HyperpacDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, HyperpacDip + 1 , "dip" }, +}; + +STDINPUTINFO(Hyperpac) + +static struct BurnInputInfo SnowbrosInputList[] = { + {"Coin 1" , BIT_DIGITAL , HyperpacInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , HyperpacInputPort2 + 0, "p1 start" }, + + {"P1 Up" , BIT_DIGITAL , HyperpacInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , HyperpacInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , HyperpacInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , HyperpacInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , HyperpacInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , HyperpacInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , HyperpacInputPort0 + 6, "p1 fire 3" }, + + {"Coin 2" , BIT_DIGITAL , HyperpacInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , HyperpacInputPort2 + 1, "p2 start" }, + + {"P2 Up" , BIT_DIGITAL , HyperpacInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , HyperpacInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , HyperpacInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , HyperpacInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , HyperpacInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , HyperpacInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , HyperpacInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &HyperpacReset , "reset" }, + {"Service" , BIT_DIGITAL , HyperpacInputPort2 + 6, "service" }, + {"Tilt" , BIT_DIGITAL , HyperpacInputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, HyperpacDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, HyperpacDip + 1 , "dip" }, +}; + +STDINPUTINFO(Snowbros) + +inline void HyperpacClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void HyperpacMakeInputs() +{ + // Reset Inputs + HyperpacInput[0] = HyperpacInput[1] = HyperpacInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + HyperpacInput[0] |= (HyperpacInputPort0[i] & 1) << i; + HyperpacInput[1] |= (HyperpacInputPort1[i] & 1) << i; + HyperpacInput[2] |= (HyperpacInputPort2[i] & 1) << i; + } + + // Clear Opposites + HyperpacClearOpposites(&HyperpacInput[0]); + HyperpacClearOpposites(&HyperpacInput[1]); +} + +static struct BurnDIPInfo HyperpacDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfc, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x13, 0x01, 0x02, 0x02, "3" }, + {0x13, 0x01, 0x02, 0x00, "5" }, + + {0 , 0xfe, 0 , 8 , "Coin : Credit" }, + {0x13, 0x01, 0x1c, 0x00, "5 : 1" }, + {0x13, 0x01, 0x1c, 0x04, "4 : 1" }, + {0x13, 0x01, 0x1c, 0x08, "3 : 1" }, + {0x13, 0x01, 0x1c, 0x0c, "2 : 1" }, + {0x13, 0x01, 0x1c, 0x1c, "1 : 1" }, + {0x13, 0x01, 0x1c, 0x14, "2 : 3" }, + {0x13, 0x01, 0x1c, 0x18, "1 : 2" }, + {0x13, 0x01, 0x1c, 0x10, "1 : 3" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x00, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x40, "Hard" }, + {0x13, 0x01, 0x60, 0x20, "Very Hard" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x13, 0x01, 0x80, 0x80, "Game" }, + {0x13, 0x01, 0x80, 0x00, "Test" }, +}; + +STDDIPINFO(Hyperpac) + +static struct BurnDIPInfo Cookbib2DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfc, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Max Vs Round" }, + {0x13, 0x01, 0x02, 0x02, "3" }, + {0x13, 0x01, 0x02, 0x00, "1" }, + + {0 , 0xfe, 0 , 8 , "Coin : Credit" }, + {0x13, 0x01, 0x1c, 0x00, "5 : 1" }, + {0x13, 0x01, 0x1c, 0x04, "4 : 1" }, + {0x13, 0x01, 0x1c, 0x08, "3 : 1" }, + {0x13, 0x01, 0x1c, 0x0c, "2 : 1" }, + {0x13, 0x01, 0x1c, 0x1c, "1 : 1" }, + {0x13, 0x01, 0x1c, 0x14, "2 : 3" }, + {0x13, 0x01, 0x1c, 0x18, "1 : 2" }, + {0x13, 0x01, 0x1c, 0x10, "1 : 3" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x00, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x40, "Hard" }, + {0x13, 0x01, 0x60, 0x20, "Very Hard" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x13, 0x01, 0x80, 0x80, "Game" }, + {0x13, 0x01, 0x80, 0x00, "Test" }, +}; + +STDDIPINFO(Cookbib2) + +static struct BurnDIPInfo Cookbib3DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xee, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin : Credit" }, + {0x13, 0x01, 0x0e, 0x00, "5 : 1" }, + {0x13, 0x01, 0x0e, 0x02, "4 : 1" }, + {0x13, 0x01, 0x0e, 0x04, "3 : 1" }, + {0x13, 0x01, 0x0e, 0x06, "2 : 1" }, + {0x13, 0x01, 0x0e, 0x0e, "1 : 1" }, + {0x13, 0x01, 0x0e, 0x0a, "2 : 3" }, + {0x13, 0x01, 0x0e, 0x0c, "1 : 2" }, + {0x13, 0x01, 0x0e, 0x08, "1 : 3" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x70, 0x20, "Level 1" }, + {0x13, 0x01, 0x70, 0x10, "Level 2" }, + {0x13, 0x01, 0x70, 0x00, "Level 3" }, + {0x13, 0x01, 0x70, 0x70, "Level 4" }, + {0x13, 0x01, 0x70, 0x60, "Level 5" }, + {0x13, 0x01, 0x70, 0x50, "Level 6" }, + {0x13, 0x01, 0x70, 0x40, "Level 7" }, + {0x13, 0x01, 0x70, 0x30, "Level 8" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x13, 0x01, 0x80, 0x80, "Game" }, + {0x13, 0x01, 0x80, 0x00, "Test" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Cookbib3) + +static struct BurnDIPInfo MoremoreDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xee, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin : Credit" }, + {0x13, 0x01, 0x0e, 0x00, "5 : 1" }, + {0x13, 0x01, 0x0e, 0x02, "4 : 1" }, + {0x13, 0x01, 0x0e, 0x04, "3 : 1" }, + {0x13, 0x01, 0x0e, 0x06, "2 : 1" }, + {0x13, 0x01, 0x0e, 0x0e, "1 : 1" }, + {0x13, 0x01, 0x0e, 0x0a, "2 : 3" }, + {0x13, 0x01, 0x0e, 0x0c, "1 : 2" }, + {0x13, 0x01, 0x0e, 0x08, "1 : 3" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x70, 0x20, "Level 1" }, + {0x13, 0x01, 0x70, 0x10, "Level 2" }, + {0x13, 0x01, 0x70, 0x00, "Level 3" }, + {0x13, 0x01, 0x70, 0x70, "Level 4" }, + {0x13, 0x01, 0x70, 0x60, "Level 5" }, + {0x13, 0x01, 0x70, 0x50, "Level 6" }, + {0x13, 0x01, 0x70, 0x40, "Level 7" }, + {0x13, 0x01, 0x70, 0x30, "Level 8" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x13, 0x01, 0x80, 0x80, "Game" }, + {0x13, 0x01, 0x80, 0x00, "Test" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Moremore) + +static struct BurnDIPInfo ToppyrapDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin : Credit" }, + {0x13, 0x01, 0x1c, 0x00, "5 : 1" }, + {0x13, 0x01, 0x1c, 0x04, "4 : 1" }, + {0x13, 0x01, 0x1c, 0x08, "3 : 1" }, + {0x13, 0x01, 0x1c, 0x0c, "2 : 1" }, + {0x13, 0x01, 0x1c, 0x1c, "1 : 1" }, + {0x13, 0x01, 0x1c, 0x14, "2 : 3" }, + {0x13, 0x01, 0x1c, 0x18, "1 : 2" }, + {0x13, 0x01, 0x1c, 0x10, "1 : 3" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x00, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x40, "Hard" }, + {0x13, 0x01, 0x60, 0x20, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x13, 0x01, 0x80, 0x80, "Game" }, + {0x13, 0x01, 0x80, 0x00, "Test" }, + + {0 , 0xfe, 0 , 4 , "Player Count" }, + {0x14, 0x01, 0x03, 0x00, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x02, "4" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4 , "Game Time" }, + {0x14, 0x01, 0x0c, 0x04, "40 seconds" }, + {0x14, 0x01, 0x0c, 0x08, "50 seconds" }, + {0x14, 0x01, 0x0c, 0x0c, "60 seconds" }, + {0x14, 0x01, 0x0c, 0x00, "70 seconds" }, + + {0 , 0xfe, 0 , 2 , "God Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Internal Test" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Toppyrap) + +static struct BurnDIPInfo Fourin1bootDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x06, 0x04, "1" }, + {0x13, 0x01, 0x06, 0x06, "2" }, + {0x13, 0x01, 0x06, 0x02, "3" }, + {0x13, 0x01, 0x06, 0x00, "4" }, + + {0 , 0xfe, 0 , 16 , "Coin : Credit" }, + {0x13, 0x01, 0x78, 0x18, "4 : 1" }, + {0x13, 0x01, 0x78, 0x38, "3 : 1" }, + {0x13, 0x01, 0x78, 0x10, "4 : 2" }, + {0x13, 0x01, 0x78, 0x58, "2 : 1" }, + {0x13, 0x01, 0x78, 0x30, "3 : 2" }, + {0x13, 0x01, 0x78, 0x08, "4 : 3" }, + {0x13, 0x01, 0x78, 0x00, "4 : 4" }, + {0x13, 0x01, 0x78, 0x28, "3 : 3" }, + {0x13, 0x01, 0x78, 0x50, "2 : 2" }, + {0x13, 0x01, 0x78, 0x78, "1 : 1" }, + {0x13, 0x01, 0x78, 0x20, "3 : 4" }, + {0x13, 0x01, 0x78, 0x48, "2 : 3" }, + {0x13, 0x01, 0x78, 0x40, "2 : 4" }, + {0x13, 0x01, 0x78, 0x70, "1 : 2" }, + {0x13, 0x01, 0x78, 0x68, "1 : 3" }, + {0x13, 0x01, 0x78, 0x60, "1 : 4" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x02, "1" }, + {0x14, 0x01, 0x03, 0x00, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x14, 0x01, 0x80, 0x80, "Game" }, + {0x14, 0x01, 0x80, 0x00, "Test" }, +}; + +STDDIPINFO(Fourin1boot) + +static struct BurnDIPInfo FinalttrDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 7 , "Coin : Credit" }, + {0x13, 0x01, 0x38, 0x00, "4 : 1" }, + {0x13, 0x01, 0x38, 0x10, "3 : 1" }, + {0x13, 0x01, 0x38, 0x30, "2 : 1" }, + {0x13, 0x01, 0x38, 0x38, "1 : 1" }, + {0x13, 0x01, 0x38, 0x20, "2 : 3" }, + {0x13, 0x01, 0x38, 0x28, "1 : 2" }, + {0x13, 0x01, 0x38, 0x08, "1 : 4" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Time" }, + {0x14, 0x01, 0x0c, 0x00, "60 seconds" }, + {0x14, 0x01, 0x0c, 0x0c, "90 seconds" }, + {0x14, 0x01, 0x0c, 0x08, "120 seconds" }, + {0x14, 0x01, 0x0c, 0x04, "150 seconds" }, +}; + +STDDIPINFO(Finalttr) + +static struct BurnDIPInfo TwinadvDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin : Credit" }, + {0x13, 0x01, 0x03, 0x00, "3 : 1" }, + {0x13, 0x01, 0x03, 0x01, "2 : 1" }, + {0x13, 0x01, 0x03, 0x03, "1 : 1" }, + {0x13, 0x01, 0x03, 0x02, "1 : 2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Select" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x01, "Harder" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x04, 0x04, "3" }, + {0x14, 0x01, 0x04, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Ticket Mode 1" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Ticket Mode 2" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Twinadv) + +static struct BurnDIPInfo HoneydolDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xef, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Show Girls" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Select" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Slide show on boot" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x01, "Harder" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer speed" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Fast" }, + {0x14, 0x01, 0x0c, 0x04, "Faster" }, + {0x14, 0x01, 0x0c, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x20, "3" }, + {0x14, 0x01, 0x30, 0x30, "5" }, + + {0 , 0xfe, 0 , 2 , "Max vs Round" }, + {0x14, 0x01, 0x80, 0x80, "3" }, + {0x14, 0x01, 0x80, 0x00, "1" }, +}; + +STDDIPINFO(Honeydol) + +static struct BurnDIPInfo SnowbrosDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0x01, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Country" }, + {0x15, 0x01, 0x01, 0x01, "Europ Type" }, + {0x15, 0x01, 0x01, 0x00, "America Type" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Invert Screen" }, + {0x15, 0x01, 0x02, 0x00, "Normal Screen" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x15, 0x01, 0x04, 0x00, "Off" }, + {0x15, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Advertise Sound Off" }, + {0x15, 0x01, 0x08, 0x00, "Advertise Sound On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "4 Coin 1 Play" }, + {0x15, 0x01, 0x30, 0x20, "3 Coin 1 Play" }, + {0x15, 0x01, 0x30, 0x10, "2 Coin 1 Play" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 2 Play" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 3 Play" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 4 Play" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 6 Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Game Difficulty A" }, + {0x16, 0x01, 0x03, 0x00, "Game Difficulty B" }, + {0x16, 0x01, 0x03, 0x02, "Game Difficulty C" }, + {0x16, 0x01, 0x03, 0x03, "Game Difficulty D" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "Extend No Extend" }, + {0x16, 0x01, 0x0c, 0x00, "Extend 100000 Only" }, + {0x16, 0x01, 0x0c, 0x08, "Extend 100000, 200000" }, + {0x16, 0x01, 0x0c, 0x04, "Extend 200000 Only" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x10, "Hero Counts 1" }, + {0x16, 0x01, 0x30, 0x30, "Hero Counts 2" }, + {0x16, 0x01, 0x30, 0x00, "Hero Counts 3" }, + {0x16, 0x01, 0x30, 0x20, "Hero Counts 4" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x16, 0x01, 0x40, 0x40, "No Death, Stop Mode" }, + {0x16, 0x01, 0x40, 0x00, "Normal Game" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x80, 0x00, "Continue Play On" }, + {0x16, 0x01, 0x80, 0x80, "Continue Play Off" }, +}; + +STDDIPINFO(Snowbros) + +static struct BurnDIPInfo SnowbrojDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet Type" }, + {0x15, 0x01, 0x01, 0x01, "Up-Right Type" }, + {0x15, 0x01, 0x01, 0x00, "Table Type" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Invert Screen" }, + {0x15, 0x01, 0x02, 0x00, "Normal Screen" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x15, 0x01, 0x04, 0x00, "Off" }, + {0x15, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Advertise Sound Off" }, + {0x15, 0x01, 0x08, 0x00, "Advertise Sound On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "2 Coin 3 Play" }, + {0x15, 0x01, 0x30, 0x20, "2 Coin 1 Play" }, + {0x15, 0x01, 0x30, 0x10, "1 Coin 2 Play" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "2 Coin 3 Play" }, + {0x15, 0x01, 0xc0, 0x80, "2 Coin 1 Play" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 2 Play" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Game Difficulty A" }, + {0x16, 0x01, 0x03, 0x00, "Game Difficulty B" }, + {0x16, 0x01, 0x03, 0x02, "Game Difficulty C" }, + {0x16, 0x01, 0x03, 0x03, "Game Difficulty D" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "Extend No Extend" }, + {0x16, 0x01, 0x0c, 0x00, "Extend 100000 Only" }, + {0x16, 0x01, 0x0c, 0x08, "Extend 100000, 200000" }, + {0x16, 0x01, 0x0c, 0x04, "Extend 200000 Only" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x10, "Hero Counts 1" }, + {0x16, 0x01, 0x30, 0x30, "Hero Counts 2" }, + {0x16, 0x01, 0x30, 0x00, "Hero Counts 3" }, + {0x16, 0x01, 0x30, 0x20, "Hero Counts 4" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x16, 0x01, 0x40, 0x40, "No Death, Stop Mode" }, + {0x16, 0x01, 0x40, 0x00, "Normal Game" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x80, 0x00, "Continue Play On" }, + {0x16, 0x01, 0x80, 0x80, "Continue Play Off" }, +}; + +STDDIPINFO(Snowbroj) + +static struct BurnRomInfo HyperpacRomDesc[] = { + { "hyperpac.h12", 0x20000, 0x2cf0531a, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "hyperpac.i12", 0x20000, 0x9c7d85b8, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "hyperpac.a4", 0x40000, 0xbd8673da, BRF_GRA }, // 2 Sprites + { "hyperpac.a5", 0x40000, 0x5d90cd82, BRF_GRA }, // 3 Sprites + { "hyperpac.a6", 0x40000, 0x61d86e63, BRF_GRA }, // 4 Sprites + + { "hyperpac.u1", 0x10000, 0x03faf88e, BRF_SND }, // 5 Z80 Program Code + + { "hyperpac.j15", 0x40000, 0xfb9f468d, BRF_SND }, // 6 Samples + + { "at89c52.bin", 0x02000, 0x291f9326, BRF_PRG | BRF_OPT }, +}; + + +STD_ROM_PICK(Hyperpac) +STD_ROM_FN(Hyperpac) + +static struct BurnRomInfo HyperpacbRomDesc[] = { + { "hpacuh12.bin", 0x20000, 0x633ab2c6, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "hpacui12.bin", 0x20000, 0x23dc00d1, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "hyperpac.a4", 0x40000, 0xbd8673da, BRF_GRA }, // 2 Sprites + { "hyperpac.a5", 0x40000, 0x5d90cd82, BRF_GRA }, // 3 Sprites + { "hyperpac.a6", 0x40000, 0x61d86e63, BRF_GRA }, // 4 Sprites + + { "hyperpac.u1", 0x10000, 0x03faf88e, BRF_SND }, // 5 Z80 Program Code + + { "hyperpac.j15", 0x40000, 0xfb9f468d, BRF_SND }, // 6 Samples +}; + + +STD_ROM_PICK(Hyperpacb) +STD_ROM_FN(Hyperpacb) + +static struct BurnRomInfo Cookbib2RomDesc[] = { + { "cookbib2.02", 0x40000, 0xb2909460, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "cookbib2.01", 0x40000, 0x65aafde2, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "cookbib2.05", 0x80000, 0x89fb38ce, BRF_GRA }, // 2 Sprites + { "cookbib2.04", 0x80000, 0xf240111f, BRF_GRA }, // 3 Sprites + { "cookbib2.03", 0x40000, 0xe1604821, BRF_GRA }, // 4 Sprites + + { "cookbib2.07", 0x10000, 0xf59f1c9a, BRF_SND }, // 5 Z80 Program Code + + { "cookbib2.06", 0x20000, 0x5e6f76b8, BRF_SND }, // 6 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0xae6d8ed5, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Cookbib2) +STD_ROM_FN(Cookbib2) + +static struct BurnRomInfo Cookbib3RomDesc[] = { + { "u52.bin", 0x40000, 0x65134893, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u74.bin", 0x40000, 0xc4ab8435, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "u75.bin", 0x80000, 0xcbe4d9c8, BRF_GRA }, // 2 Sprites + { "u76.bin", 0x80000, 0x1be17b57, BRF_GRA }, // 3 Sprites + { "u77.bin", 0x80000, 0x7823600d, BRF_GRA }, // 4 Sprites + + { "u35.bin", 0x10000, 0x5dfd2a98, BRF_SND }, // 5 Z80 Program Code + + { "u14.bin", 0x20000, 0xe5bf9288, BRF_SND }, // 6 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0xc819b9a8, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Cookbib3) +STD_ROM_FN(Cookbib3) + +static struct BurnRomInfo MoremoreRomDesc[] = { + { "u52.bin", 0x40000, 0xcea4b246, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u74.bin", 0x40000, 0x2acdcb88, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "u75.bin", 0x80000, 0xd671815c, BRF_GRA }, // 2 Sprites + { "u76.bin", 0x80000, 0xe0d479e8, BRF_GRA }, // 3 Sprites + { "u77.bin", 0x80000, 0x60a281da, BRF_GRA }, // 4 Sprites + { "u78.bin", 0x80000, 0xe2723b4e, BRF_GRA }, // 5 Sprites + + { "u35.bin", 0x10000, 0x92dc95fc, BRF_SND }, // 6 Z80 Program Code + + { "u14.bin", 0x40000, 0x90580088, BRF_SND }, // 7 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x782dd2aa, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Moremore) +STD_ROM_FN(Moremore) + +static struct BurnRomInfo MoremorpRomDesc[] = { + { "mmp_u52.bin", 0x40000, 0x66baf9b2, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mmp_u74.bin", 0x40000, 0x7c6fede5, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mmp_u75.bin", 0x80000, 0xaf9e824e, BRF_GRA }, // 2 Sprites + { "mmp_u76.bin", 0x80000, 0xc42af064, BRF_GRA }, // 3 Sprites + { "mmp_u77.bin", 0x80000, 0x1d7396e1, BRF_GRA }, // 4 Sprites + { "mmp_u78.bin", 0x80000, 0x5508d80b, BRF_GRA }, // 5 Sprites + + { "mmp_u35.bin", 0x10000, 0x4d098cad, BRF_SND }, // 6 Z80 Program Code + + { "mmp_u14.bin", 0x40000, 0x211a2566, BRF_SND }, // 7 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x782dd2aa, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Moremorp) +STD_ROM_FN(Moremorp) + +static struct BurnRomInfo ToppyrapRomDesc[] = { + { "uh12.bin", 0x40000, 0x6f5ad699, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ui12.bin", 0x40000, 0xcaf5a7e1, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ua4.bin", 0x80000, 0xa9577bcf, BRF_GRA }, // 2 Sprites + { "ua5.bin", 0x80000, 0x7179d32d, BRF_GRA }, // 3 Sprites + { "ua6.bin", 0x80000, 0x4834e5b1, BRF_GRA }, // 4 Sprites + { "ua7.bin", 0x80000, 0x663dd099, BRF_GRA }, // 5 Sprites + + { "u1.bin", 0x10000, 0x07f50947, BRF_SND }, // 6 Z80 Program Code + + { "uj15.bin", 0x20000, 0xa3bacfd7, BRF_SND }, // 7 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x0704e6c7, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Toppyrap) +STD_ROM_FN(Toppyrap) + +static struct BurnRomInfo Threein1semiRomDesc[] = { + { "u52", 0x40000, 0xb0e4a0f7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u74", 0x40000, 0x266862c4, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "u75", 0x80000, 0xb66a0db6, BRF_GRA }, // 2 Sprites + { "u76", 0x80000, 0x5f4b48ea, BRF_GRA }, // 3 Sprites + { "u77", 0x80000, 0xd44211e3, BRF_GRA }, // 4 Sprites + { "u78", 0x80000, 0xaf596afc, BRF_GRA }, // 5 Sprites + + { "u35", 0x10000, 0xe40481da, BRF_SND }, // 6 Z80 Program Code + + { "u14", 0x40000, 0xc83c11be, BRF_SND }, // 7 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x85deba7c, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Threein1semi) +STD_ROM_FN(Threein1semi) + +static struct BurnRomInfo TwinkleRomDesc[] = { + { "uh12.bin", 0x20000, 0xa99626fe, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ui12.bin", 0x20000, 0x5af73684, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ua4.bin", 0x80000, 0x6b64bb09, BRF_GRA }, // 2 Sprites + + { "u1.bin", 0x10000, 0xe40481da, BRF_SND }, // 3 Z80 Program Code + + { "uj15.bin", 0x40000, 0x0a534b37, BRF_SND }, // 4 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x00d3e4b4, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Twinkle) +STD_ROM_FN(Twinkle) + +static struct BurnRomInfo PzlbreakRomDesc[] = { + { "4.uh12", 0x20000, 0xb3f04f80, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "5.ui12", 0x20000, 0x13c298a0, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "2.ua4", 0x80000, 0xd211705a, BRF_GRA }, // 2 Sprites + { "3.ua5", 0x80000, 0x6cdb73e9, BRF_GRA }, // 3 + + { "0.u1", 0x10000, 0x1ad646b7, BRF_SND }, // 4 Z80 Program Code + + { "1.uj15", 0x40000, 0xdbfae77c, BRF_SND }, // 5 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0x092cb794, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Pzlbreak) +STD_ROM_FN(Pzlbreak) + +static struct BurnRomInfo Fourin1bootRomDesc[] = { + { "u52", 0x80000, 0x71815878, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u74", 0x80000, 0xe22d3fa2, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "u78", 0x200000,0x6c1fbc9c, BRF_GRA }, // 2 Sprites + + { "u35", 0x10000, 0xc894ac80, BRF_SND }, // 3 Z80 Program Code + + { "u14", 0x40000, 0x94b09b0e, BRF_SND }, // 4 Samples +}; + + +STD_ROM_PICK(Fourin1boot) +STD_ROM_FN(Fourin1boot) + +static struct BurnRomInfo FinalttrRomDesc[] = { + { "10.7o", 0x20000, 0xeecc83e5, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "9.5o", 0x20000, 0x58d3640e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "5.1d", 0x40000, 0x64a450f3, BRF_GRA }, // 2 Sprites + { "6.1f", 0x40000, 0x7281a3cc, BRF_GRA }, // 3 Sprites + { "7.1g", 0x40000, 0xec80f442, BRF_GRA }, // 4 Sprites + { "9.1h", 0x40000, 0x2ebd316d, BRF_GRA }, // 5 Sprites + + { "12.5r", 0x10000, 0x4bc21361, BRF_SND }, // 6 Z80 Program Code + + { "11.7p", 0x20000, 0x2e331022, BRF_SND }, // 7 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, + + { "protdata.bin", 0x00200, 0xd5bbb006, BRF_ESS | BRF_PRG }, // Data from shared RAM +}; + + +STD_ROM_PICK(Finalttr) +STD_ROM_FN(Finalttr) + +static struct BurnRomInfo TwinadvRomDesc[] = { + { "13.uh12", 0x20000, 0x9f70a39b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "12.ui12", 0x20000, 0xd8776495, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "16.ua4", 0x80000, 0xf491e171, BRF_GRA }, // 2 Sprites + { "15.ua5", 0x80000, 0x79a08b8d, BRF_GRA }, // 3 Sprites + { "14.ua6", 0x80000, 0x79faee0b, BRF_GRA }, // 4 Sprites + + { "uh15.bin", 0x08000, 0x3d5acd08, BRF_SND }, // 5 Z80 Program Code + + { "sra.bin", 0x40000, 0x82f452c4, BRF_SND }, // 6 Samples + { "srb.bin", 0x40000, 0x109e51e6, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Twinadv) +STD_ROM_FN(Twinadv) + +static struct BurnRomInfo TwinadvkRomDesc[] = { + { "uh12", 0x20000, 0xe0bcc738, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ui12", 0x20000, 0xa3ee6451, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ua4", 0x80000, 0xa5aff49b, BRF_GRA }, // 2 Sprites + { "ua5", 0x80000, 0xf83b3b97, BRF_GRA }, // 3 Sprites + { "ua6", 0x80000, 0x4dfcffb9, BRF_GRA }, // 4 Sprites + + { "uh15.bin", 0x08000, 0x3d5acd08, BRF_SND }, // 5 Z80 Program Code + + { "sra.bin", 0x40000, 0x82f452c4, BRF_SND }, // 6 Samples + { "srb.bin", 0x40000, 0x109e51e6, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Twinadvk) +STD_ROM_FN(Twinadvk) + +static struct BurnRomInfo HoneydolRomDesc[] = { + { "d-16.uh12", 0x20000, 0xcee1a2e3, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "d-17.ui12", 0x20000, 0xcac44154, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "d-13.1", 0x80000, 0xff6a57fb, BRF_GRA }, // 2 4bpp Sprites + + { "d-14.5", 0x80000, 0x2178996f, BRF_GRA }, // 3 8bpp Sprites + { "d-15.6", 0x80000, 0x6629239e, BRF_GRA }, // 4 8bpp Sprites + { "d-18.9", 0x80000, 0x0210507a, BRF_GRA }, // 5 8bpp Sprites + { "d-19.10", 0x80000, 0xd27375d5, BRF_GRA }, // 6 8bpp Sprites + + { "d-12.uh15", 0x08000, 0x386f1b63, BRF_SND }, // 7 Z80 Program Code + + { "d-11.u14", 0x40000, 0xf3ee4861, BRF_SND }, // 8 Samples +}; + + +STD_ROM_PICK(Honeydol) +STD_ROM_FN(Honeydol) + +static struct BurnRomInfo SnowbrosRomDesc[] = { + { "sn6.bin", 0x20000, 0x4899ddcf, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "sn5.bin", 0x20000, 0xad310d3f, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbros) +STD_ROM_FN(Snowbros) + +static struct BurnRomInfo SnowbroaRomDesc[] = { + { "sbros-3a.5", 0x20000, 0x10cb37e1, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "sbros-2a.6", 0x20000, 0xab91cc1e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbroa) +STD_ROM_FN(Snowbroa) + +static struct BurnRomInfo SnowbrobRomDesc[] = { + { "sbros3-a", 0x20000, 0x301627d6, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "sbros2-a", 0x20000, 0xf6689f41, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbrob) +STD_ROM_FN(Snowbrob) + +static struct BurnRomInfo SnowbrocRomDesc[] = { + { "3-a.ic5", 0x20000, 0xe1bc346b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "2-a.ic6", 0x20000, 0x1be27f9d, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbroc) +STD_ROM_FN(Snowbroc) + +static struct BurnRomInfo SnowbrojRomDesc[] = { + { "snowbros.3", 0x20000, 0x3f504f9e, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "snowbros.2", 0x20000, 0x854b02bc, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbroj) +STD_ROM_FN(Snowbroj) + +static struct BurnRomInfo SnowbrodRomDesc[] = { + { "sbk_3-a.bin", 0x20000, 0x97174d40, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "sbk_2-a.bin", 0x20000, 0x80cc80e5, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "sbros-1.41", 0x80000, 0x16f06b3a, BRF_GRA }, // 2 Sprites + + { "sbros-4.29", 0x08000, 0xe6eab4e4, BRF_SND }, // 3 Z80 Program Code +}; + + +STD_ROM_PICK(Snowbrod) +STD_ROM_FN(Snowbrod) + +static struct BurnRomInfo WintbobRomDesc[] = { + { "wb3", 0x10000, 0xb9719767, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "wb1", 0x10000, 0xa4488998, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + { "wb04.bin", 0x10000, 0x53be758d, BRF_ESS | BRF_PRG }, // 2 68000 Program Code + { "wb02.bin", 0x10000, 0xfc8e292e, BRF_ESS | BRF_PRG }, // 3 68000 Program Code + + { "wb13.bin", 0x10000, 0x426921de, BRF_GRA }, // 4 Sprites + { "wb06.bin", 0x10000, 0x68204937, BRF_GRA }, // 5 Sprites + { "wb12.bin", 0x10000, 0xef4e04c7, BRF_GRA }, // 6 Sprites + { "wb07.bin", 0x10000, 0x53f40978, BRF_GRA }, // 7 Sprites + { "wb11.bin", 0x10000, 0x41cb4563, BRF_GRA }, // 8 Sprites + { "wb08.bin", 0x10000, 0x9497b88c, BRF_GRA }, // 9 Sprites + { "wb10.bin", 0x10000, 0x5fa22b1e, BRF_GRA }, // 10 Sprites + { "wb09.bin", 0x10000, 0x9be718ca, BRF_GRA }, // 11 Sprites + + { "wb05.bin", 0x10000, 0x53fe59df, BRF_SND }, // 12 Z80 Program Code +}; + + +STD_ROM_PICK(Wintbob) +STD_ROM_FN(Wintbob) + +static struct BurnRomInfo Snowbro3RomDesc[] = { + { "ur4", 0x020000, 0x19c13ffd, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ur3", 0x020000, 0x3f32fa15, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ua5", 0x080000, 0x0604e385, BRF_GRA }, // 2 4bpp Sprites + + { "un7", 0x200000, 0x4a79da4c, BRF_GRA }, // 3 8bpp Sprites + { "un8", 0x200000, 0x7a4561a4, BRF_GRA }, // 4 8bpp Sprites + + { "us5", 0x080000, 0x7c6368ef, BRF_SND }, // 5 Samples + + { "sound.mcu", 0x010000, 0x00000000, BRF_PRG | BRF_NODUMP }, // 6 Sound MCU +}; + + +STD_ROM_PICK(Snowbro3) +STD_ROM_FN(Snowbro3) + +INT32 HyperpacDoReset() +{ + HyperpacSoundLatch = 0; + + if(HyperpacProtData && !Finalttr) memcpy(HyperpacRam + 0xf000, HyperpacProtData, 0x200); + if(HyperpacProtData && Finalttr) memcpy(HyperpacRam + 0x2000, HyperpacProtData, 0x200); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + if (Honeydol) BurnYM3812Reset(); + if (!Twinadv && !Honeydol) BurnYM2151Reset(); + + return 0; +} + +INT32 SnowbrosDoReset() +{ + HyperpacSoundLatch = 0; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + return 0; +} + +INT32 Snowbro3DoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + + Snowbro3Music = 0; + Snowbro3MusicPlaying = 0; + + return 0; +} + +void HyperpacYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +// ---------------------------------------------------------------------------- +// CPU synchronisation + +static INT32 nCycles68KSync; + +static inline void snowbrosSynchroniseZ80(INT32 nExtraCycles) +{ + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; + + if (nCycles <= ZetTotalCycles()) { + return; + } + + nCycles68KSync = nCycles - nExtraCycles; + + BurnTimerUpdateYM3812(nCycles); +} + +// Callbacks for the FM chip + +static void snowbrosFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 snowbrosSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +static INT32 HoneydolSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static void Snowbro3PlayMusic(INT32 data) +{ + Snowbro3Music = data; + + bprintf(PRINT_NORMAL, _T("%x\n"), data); + + switch (data) { + case 0x23: { + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0x80000, 0x20000); + Snowbro3MusicPlaying = 1; + break; + } + + case 0x24: { + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0xa0000, 0x20000); + Snowbro3MusicPlaying = 1; + break; + } + + case 0x25: { + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0xc0000, 0x20000); + Snowbro3MusicPlaying = 1; + break; + } + + case 0x26: { + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0x80000, 0x20000); + Snowbro3MusicPlaying = 1; + break; + } + + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: { + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0xc0000, 0x20000); + Snowbro3MusicPlaying = 1; + break; + } + + case 0x2e: { + Snowbro3MusicPlaying = 0; + break; + } + } +} + +static void Snowbro3PlaySound(INT32 data) +{ + INT32 Status = MSM6295ReadStatus(0); + + if ((Status & 0x01) == 0x00) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x12); + } else { + if ((Status & 0x02) == 0x00) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x12); + } else { + if ((Status & 0x04) == 0x00) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x42); + } + } + } +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall HyperpacReadByte(UINT32 a) +{ + switch (a) { + case 0x200000: { + if (Threein1semi) return 0x0a; + } + + case 0x200001: { + if (Moremore || Threein1semi) return 0x0a; + } + + case 0x500000: { + return HyperpacInput[0]; + } + + case 0x500001: { + return HyperpacDip[0]; + } + + case 0x500002: { + return HyperpacInput[1]; + } + + case 0x500003: { + return HyperpacDip[1]; + } + + case 0x500004: { + return HyperpacInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall HyperpacReadByteLow(UINT32 a) +{ + switch (a) { + case 0x200001: { + if (Fourin1boot) return 0x02; + } + + case 0x500000: { + return 0x7f - HyperpacInput[0]; + } + + case 0x500001: { + return HyperpacDip[0]; + } + + case 0x500002: { + return 0x7f - HyperpacInput[1]; + } + + case 0x500003: { + return HyperpacDip[1]; + } + + case 0x500004: { + return 0xff - HyperpacInput[2]; + } + + case 0x500005: { + return 0xff - HyperpacInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); + } + } + + return 0xff; +} + +void __fastcall HyperpacWriteByte(UINT32 a, UINT8 d) +{ + if (a < 0x100000) return; + + switch (a) { + case 0x300001: { + HyperpacSoundLatch = d & 0xff; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); + } + } +} + +void __fastcall TwinadvWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x200000: + case 0x200001: { + return; + } + + case 0x300001: { + HyperpacSoundLatch = d & 0xff; + ZetNmi(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall HyperpacReadWord(UINT32 a) +{ + switch (a) { + case 0x200000: { + if (Cookbib3) return 0x2a2a; + } + + default: { + bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); + } + } + + return 0; +} + +UINT16 __fastcall HyperpacReadWordLow(UINT32 a) +{ + switch (a) { + case 0x500000: + case 0x500002: + case 0x500004: { + SEK_DEF_READ_WORD(0, a); + } + + default: { + bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); + } + + } + + return 0xffff; +} + +void __fastcall HyperpacWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x00b7d6: + case 0x00b7d8: { + if (Finalttr) return; + } + + case 0x200000: { + if (Fourin1boot) return; // Watchdog in original Snow Bros. + } + + case 0x300000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0x400000: { + return; + } + + case 0x800000: + case 0x900000: + case 0xa00000: { + // IRQ ACK + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall HoneydolReadByte(UINT32 a) +{ + switch (a) { + case 0x900000: { + return 0x7f - HyperpacInput[0]; + } + + case 0x900001: { + return HyperpacDip[0]; + } + + case 0x900002: { + return 0x7f - HyperpacInput[1]; + } + + case 0x900003: { + return HyperpacDip[1]; + } + + case 0x900004: { + return 0xff - HyperpacInput[2]; + } + + case 0x900005: { + return 0xff; + } + } + + bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); + + return 0; +} + +UINT16 __fastcall HoneydolReadWord(UINT32 a) +{ + switch (a) { + case 0x900000: + case 0x900002: + case 0x900004: { + SEK_DEF_READ_WORD(0, a); + return 0; + } + } + + bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); + + return 0; +} + +void __fastcall HoneydolWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x300000: { + return; + } + + case 0x300001: { + HyperpacSoundLatch = d; + snowbrosSynchroniseZ80(0); + ZetNmi(); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); +} + +void __fastcall HoneydolWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x200000: { + return; // Watchdog? + } + + case 0x300000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0x400000: + case 0x500000: + case 0x600000: { + // IRQ Ack + return; + } + + case 0x800000: { + // ? + return; + } + } + + bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); +} + +UINT8 __fastcall HyperpacZ80Read(UINT16 a) +{ + switch (a) { + case 0xf001: { + return BurnYM2151ReadStatus(); + } + + case 0xf008: { + if (Fourin1boot) { + if (HyperpacSoundLatch != 0xff) return HyperpacSoundLatch; + } else { + return HyperpacSoundLatch; + } + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); + } + } + + return 0; +} + +void __fastcall HyperpacZ80Write(UINT16 a, UINT8 d) +{ + d &= 0xff; + + switch (a) { + case 0xf000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xf001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xf002: { + MSM6295Command(0, d); + return; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02x\n"), a, d); + } + } +} + +UINT8 __fastcall TwinadvZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + return HyperpacSoundLatch; + } + + case 0x06: { + return MSM6295ReadStatus(0); + } + } + + bprintf(PRINT_NORMAL, _T("Z80 Port Read -> %02X\n"), a); + + return 0; +} + +void __fastcall TwinadvZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + HyperpacSoundLatch = d; + return; + } + + case 0x04: { + INT32 bank = (d &0x02) >> 1; + memcpy(MSM6295ROM + 0x00000, MSM6295ROM + (0x40000 * bank), 0x40000); + return; + } + + case 0x06: { + MSM6295Command(0, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Z80 Port Write -> %02X, %02x\n"), a, d); +} + +UINT8 __fastcall HoneydolZ80Read(UINT16 a) +{ + switch (a) { + case 0xe010: { + return MSM6295ReadStatus(0); + } + } + + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); + + return 0; +} + +void __fastcall HoneydolZ80Write(UINT16 a, UINT8 d) +{ + d &= 0xff; + + switch (a) { + case 0xe010: { + MSM6295Command(0, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02x\n"), a, d); +} + +UINT16 __fastcall SnowbrosReadWord(UINT32 a) +{ + switch (a) { + case 0x300000: + case 0x500000: + case 0x500002: + case 0x500004: { + SEK_DEF_READ_WORD(0, a); + } + } + + return 0; +} + +UINT8 __fastcall SnowbrosReadByte(UINT32 a) +{ + switch (a) { + case 0x300001: { + snowbrosSynchroniseZ80(0x0100); + return HyperpacSoundLatch; + } + + case 0x500000: { + return 0x7f - HyperpacInput[0]; + } + + case 0x500001: { + return 0xff - HyperpacDip[0]; + } + + case 0x500002: { + return 0xff - HyperpacInput[1]; + } + + case 0x500003: { + return 0xff - HyperpacDip[1]; + } + + case 0x500004: { + return 0xff - HyperpacInput[2]; + } + } + + return 0; +} + +void __fastcall SnowbrosWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x300000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + } +} + +void __fastcall SnowbrosWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x300001: { + HyperpacSoundLatch = d; + snowbrosSynchroniseZ80(0); + ZetNmi(); + return; + } + } +} + +UINT16 __fastcall Snowbro3ReadWord(UINT32 a) +{ + switch (a) { + case 0x300000: { + return 3; + } + + case 0x500000: + case 0x500002: + case 0x500004: { + SEK_DEF_READ_WORD(0, a); + } + } + + bprintf(PRINT_NORMAL, _T("68000 Read Word %06X\n"), a); + + return 0; +} + +UINT8 __fastcall Snowbro3ReadByte(UINT32 a) +{ + switch (a) { +/* case 0x300001: { + snowbrosSynchroniseZ80(0x0100); + return HyperpacSoundLatch; + }*/ + + case 0x500000: { + return 0x7f - HyperpacInput[0]; + } + + case 0x500001: { + return 0xff - HyperpacDip[0]; + } + + case 0x500002: { + return 0xff - HyperpacInput[1]; + } + + case 0x500003: { + return 0xff - HyperpacDip[1]; + } + + case 0x500004: { + return 0xff - HyperpacInput[2]; + } + + case 0x500005: { + return 0xff; + } + } + + bprintf(PRINT_NORMAL, _T("68000 Read Byte %06X\n"), a); + + return 0; +} + +void __fastcall Snowbro3WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x300000: { + if (d == 0xfe) { + Snowbro3MusicPlaying = 0; + MSM6295Command(0, 0x78); + } else { + d = d >> 8; + + if (d <= 0x21) Snowbro3PlaySound(d); + if (d >= 0x22 && d <= 0x31) Snowbro3PlayMusic(d); + if (d >= 0x30 && d <= 0x51) Snowbro3PlaySound(d - 0x30); + if (d >= 0x52 && d <= 0x5f) Snowbro3PlayMusic(d - 0x30); + } + return; + } + + case 0x200000: + case 0x800000: + case 0x900000: + case 0xa00000: { + return; + } + } + + bprintf(PRINT_NORMAL, _T("68000 Write Word %06X -> %04X\n"), a, d); +} + +void __fastcall Snowbro3WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x300000: { + if (d == 0xfe) { + Snowbro3MusicPlaying = 0; + MSM6295Command(0, 0x78); + } else { + //d = d >> 8; + + if (d <= 0x21) Snowbro3PlaySound(d); + if (d >= 0x22 && d <= 0x31) Snowbro3PlayMusic(d); + if (d >= 0x30 && d <= 0x51) Snowbro3PlaySound(d - 0x30); + if (d >= 0x52 && d <= 0x5f) Snowbro3PlayMusic(d - 0x30); + } + return; + } + } + + bprintf(PRINT_NORMAL, _T("68000 Write Byte %06X -> %02X\n"), a, d); +} + +UINT8 __fastcall SnowbrosZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x02: + return BurnYM3812Read(0); + case 0x04: { + if (ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEndYM3812(); + } + return HyperpacSoundLatch; + } + } + + return 0; +} + +void __fastcall SnowbrosZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + BurnYM3812Write(0, d); + return; + } + + case 0x03: { + BurnYM3812Write(1, d); + return; + } + + case 0x04: { + HyperpacSoundLatch = d; + return; + } + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + HyperpacRom = Next; Next += 0x100000; + HyperpacZ80Rom = Next; Next += 0x10000; + if (Twinadv) { + MSM6295ROM = Next; Next += 0x80000; + } else { + MSM6295ROM = Next; Next += 0x40000; + } + + RamStart = Next; + + HyperpacRam = Next; Next += 0x10000; + if (Honeydol) { + HyperpacPaletteRam = Next; Next += 0x00800; + } else { + HyperpacPaletteRam = Next; Next += 0x00200; + } + HyperpacSpriteRam = Next; Next += 0x02000; + HyperpacZ80Ram = Next; Next += 0x00800; + + RamEnd = Next; + + HyperpacSprites = Next; Next += (HyperpacNumTiles * 16 * 16); + HyperpacSprites8bpp = Next; Next += (HyperpacNumTiles8bpp * 16 * 16); + HyperpacProtData = Next; Next += 0x00200; + if (Honeydol) { + HyperpacPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + } else { + HyperpacPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + } + MemEnd = Next; + + return 0; +} + + +static INT32 SnowbrosMemIndex() +{ + UINT8 *Next; Next = Mem; + + HyperpacRom = Next; Next += 0x40000; + HyperpacZ80Rom = Next; Next += (Wintbob) ? 0x10000 : 0x08000; + + RamStart = Next; + + HyperpacRam = Next; Next += 0x04000; + HyperpacPaletteRam = Next; Next += 0x00200; + HyperpacSpriteRam = Next; Next += 0x02000; + HyperpacZ80Ram = Next; Next += 0x00800; + + RamEnd = Next; + + HyperpacSprites = Next; Next += (HyperpacNumTiles * 16 * 16); + HyperpacPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 Snowbro3MemIndex() +{ + UINT8 *Next; Next = Mem; + + HyperpacRom = Next; Next += 0x40000; + MSM6295ROM = Next; Next += 0xe0000; + + RamStart = Next; + + HyperpacRam = Next; Next += 0x04000; + HyperpacPaletteRam = Next; Next += 0x00400; + HyperpacSpriteRam = Next; Next += 0x02200; + + RamEnd = Next; + + HyperpacSprites = Next; Next += (HyperpacNumTiles * 16 * 16); + HyperpacSprites8bpp = Next; Next += (HyperpacNumTiles8bpp * 16 * 16); + HyperpacPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +INT32 HyperpacMachineInit() +{ + BurnSetRefreshRate(57.5); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(HyperpacRom , 0x000000, 0x0fffff, SM_ROM); + if (Finalttr) { + SekMapMemory(HyperpacRam , 0x100000, 0x103fff, SM_RAM); + } else { + SekMapMemory(HyperpacRam , 0x100000, 0x10ffff, SM_RAM); + } + SekMapMemory(HyperpacPaletteRam, 0x600000, 0x6001ff, SM_RAM); + SekMapMemory(HyperpacSpriteRam , 0x700000, 0x701fff, SM_RAM); + if (Fourin1boot || Finalttr) { + SekSetReadByteHandler(0, HyperpacReadByteLow); + SekSetReadWordHandler(0, HyperpacReadWordLow); + } else { + SekSetReadByteHandler(0, HyperpacReadByte); + SekSetReadWordHandler(0, HyperpacReadWord); + } + SekSetWriteByteHandler(0, HyperpacWriteByte); + SekSetWriteWordHandler(0, HyperpacWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xcfff, 0, HyperpacZ80Rom); + ZetMapArea(0x0000, 0xcfff, 2, HyperpacZ80Rom); + ZetMapArea(0xd000, 0xd7ff, 0, HyperpacZ80Ram); + ZetMapArea(0xd000, 0xd7ff, 1, HyperpacZ80Ram); + ZetMapArea(0xd000, 0xd7ff, 2, HyperpacZ80Ram); + ZetMemEnd(); + ZetSetReadHandler(HyperpacZ80Read); + ZetSetWriteHandler(HyperpacZ80Write); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(4000000, 25.0); + BurnYM2151SetIrqHandler(&HyperpacYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 999900 / 132, 100.0, 1); + + GenericTilesInit(); + + // Reset the driver + HyperpacDoReset(); + + return 0; +} + +static INT32 HyperpacSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 HyperpacSpriteXOffsets[16] = { 4, 0, 260, 256, 20, 16, 276, 272, 12, 8, 268, 264, 28, 24, 284, 280 }; +static INT32 HyperpacSpriteYOffsets[16] = { 0, 64, 32, 96, 512, 576, 544, 608, 128, 192, 160, 224, 640, 704, 672, 736 }; +static INT32 SnowbrosSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 SnowbrosSpriteXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; +static INT32 SnowbrosSpriteYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 WintbobSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 WintbobSpriteXOffsets[16] = { 12, 8, 4, 0, 28, 24, 20, 16, 44, 40, 36, 32, 60, 56, 52, 48 }; +static INT32 WintbobSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 Honeydol8BppPlaneOffsets[8] = { 0, 1, 2, 3, 0x800000, 0x800001, 0x800002, 0x800003 }; +static INT32 Honeydol8BppXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; +static INT32 Honeydol8BppYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 Snowbro38BppPlaneOffsets[8] = { 8, 9, 10, 11, 0, 1, 2, 3 }; +static INT32 Snowbro38BppXOffsets[16] = { 0, 4, 16, 20, 32, 36, 48, 52, 512, 516, 528, 532, 544, 548, 560, 564 }; +static INT32 Snowbro38BppYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472 }; + +INT32 HyperpacInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 6144; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x0c0000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 5, 1); if (nRet != 0) return 1; + + // Simulate RAM initialisation done by the protection MCU (not needed for bootleg) + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "hyperpac")) { + HyperpacRam[0xe000 + 0] = 0xf9; + HyperpacRam[0xe000 + 1] = 0x4e; + HyperpacRam[0xe002 + 0] = 0x00; + HyperpacRam[0xe002 + 1] = 0x00; + HyperpacRam[0xe004 + 0] = 0x2c; + HyperpacRam[0xe004 + 1] = 0x06; + HyperpacRam[0xe080 + 0] = 0xdc; + HyperpacRam[0xe080 + 1] = 0xfe; + HyperpacRam[0xe082 + 0] = 0x98; + HyperpacRam[0xe082 + 1] = 0xba; + HyperpacRam[0xe084 + 0] = 0x54; + HyperpacRam[0xe084 + 1] = 0x76; + HyperpacRam[0xe086 + 0] = 0x10; + HyperpacRam[0xe086 + 1] = 0x32; + } + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x00000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x40000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x80000, 4, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 6, 1); if (nRet != 0) return 1; + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 Cookbib2Init() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 10240; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x140000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 5, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x100000, 4, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 6, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 8, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 Cookbib3Init() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 16384; + + Cookbib3 = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x200000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load and descramble Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 5, 1); if (nRet != 0) return 1; + UINT8 *pTemp = (UINT8*)BurnMalloc(0x10000); + memcpy(pTemp, HyperpacZ80Rom, 0x10000); + memcpy(HyperpacZ80Rom + 0xc000, pTemp + 0x0000, 0x4000); + memcpy(HyperpacZ80Rom + 0x8000, pTemp + 0x4000, 0x4000); + memcpy(HyperpacZ80Rom + 0x4000, pTemp + 0x8000, 0x4000); + memcpy(HyperpacZ80Rom + 0x0000, pTemp + 0xc000, 0x4000); + BurnFree(pTemp); + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x100000, 4, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 6, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 8, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 MoremoreInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 16384; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "moremore") || !strcmp(BurnDrvGetTextA(DRV_NAME), "moremorp")) Moremore = 1; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "3in1semi")) Threein1semi = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x200000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 6, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x100000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x180000, 5, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 7, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 9, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 TwinkleInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 4096; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x080000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 3, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 4, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 6, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 PzlbreakInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 8192; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x100000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 3, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 5, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 7, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +void Fourin1bootDescrambleRom() +{ + UINT8 *buffer; + UINT8 *src = HyperpacRom; + INT32 len = 0x100000; + + /* strange order */ + if ((buffer = (UINT8*)BurnMalloc(len))) + { + INT32 i; + for (i = 0;i < len; i++) + if (i&1) buffer[i] = BITSWAP08(src[i],6,7,5,4,3,2,1,0); + else buffer[i] = src[i]; + + memcpy(src,buffer,len); + BurnFree(buffer); + } + + src = HyperpacZ80Rom; + len = 0x10000; + + /* strange order */ + if ((buffer = (UINT8*)BurnMalloc(len))) + { + INT32 i; + for (i = 0;i < len; i++) { + buffer[i] = src[i ^ 0x4000]; + } + memcpy(src,buffer,len); + BurnFree(buffer); + } +} + +INT32 Fourin1bootInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 16384; + + Fourin1boot = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x200000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load and Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 3, 1); if (nRet != 0) return 1; + + Fourin1bootDescrambleRom(); + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, SnowbrosSpritePlaneOffsets, SnowbrosSpriteXOffsets, SnowbrosSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 4, 1); if (nRet != 0) return 1; + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 FinalttrInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 8192; + + Finalttr = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x100000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 6, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x040000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x0c0000, 5, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, HyperpacSpritePlaneOffsets, HyperpacSpriteXOffsets, HyperpacSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 7, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(HyperpacProtData, 9, 1); if (nRet) return 1; + BurnByteswap(HyperpacProtData, 0x200); + + nRet = HyperpacMachineInit(); if (nRet) return 1; + + return 0; +} + +INT32 TwinadvInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 12288; + + Twinadv = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x180000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 5, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x100000, 4, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, SnowbrosSpritePlaneOffsets, SnowbrosSpriteXOffsets, SnowbrosSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x40000, 7, 1); if (nRet != 0) return 1; + + BurnSetRefreshRate(57.5); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(HyperpacRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(HyperpacRam , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(HyperpacPaletteRam, 0x600000, 0x6001ff, SM_RAM); + SekMapMemory(HyperpacSpriteRam , 0x700000, 0x701fff, SM_RAM); + SekSetReadByteHandler(0, HyperpacReadByteLow); + SekSetReadWordHandler(0, HyperpacReadWordLow); + SekSetWriteByteHandler(0, TwinadvWriteByte); + SekSetWriteWordHandler(0, HyperpacWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetMapArea(0x0000, 0x7fff, 0, HyperpacZ80Rom); + ZetMapArea(0x0000, 0x7fff, 2, HyperpacZ80Rom); + ZetMapArea(0x8000, 0x87ff, 0, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 1, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 2, HyperpacZ80Ram); + ZetMemEnd(); + ZetSetInHandler(TwinadvZ80PortRead); + ZetSetOutHandler(TwinadvZ80PortWrite); + ZetClose(); + + // Setup the OKIM6295 emulation + MSM6295Init(0, (12000000/12) / 132 , 100.0, 0); + + GenericTilesInit(); + + // Reset the driver + HyperpacDoReset(); + + return 0; +} + +INT32 HoneydolInit() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 4096; + HyperpacNumTiles8bpp = 8192; + + Honeydol = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x200000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 7, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 2, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, SnowbrosSpritePlaneOffsets, SnowbrosSpriteXOffsets, SnowbrosSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + + // Load and Decode 8bpp Sprite Roms + memset(HyperpacTempGfx, 0, 0x200000); + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x080000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x100000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x180000, 6, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles8bpp, 8, 16, 16, Honeydol8BppPlaneOffsets, Honeydol8BppXOffsets, Honeydol8BppYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites8bpp); + BurnFree(HyperpacTempGfx); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 8, 1); if (nRet != 0) return 1; + + BurnSetRefreshRate(57.5); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(HyperpacRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(HyperpacRam , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(HyperpacPaletteRam, 0xa00000, 0xa007ff, SM_RAM); + SekMapMemory(HyperpacSpriteRam , 0xb00000, 0xb01fff, SM_RAM); + SekSetReadByteHandler(0, HoneydolReadByte); + SekSetReadWordHandler(0, HoneydolReadWord); + SekSetWriteByteHandler(0, HoneydolWriteByte); + SekSetWriteWordHandler(0, HoneydolWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, HyperpacZ80Rom); + ZetMapArea(0x0000, 0x7fff, 2, HyperpacZ80Rom); + ZetMapArea(0x8000, 0x87ff, 0, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 1, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 2, HyperpacZ80Ram); + ZetMemEnd(); + ZetSetInHandler(SnowbrosZ80PortRead); + ZetSetOutHandler(SnowbrosZ80PortWrite); + ZetSetReadHandler(HoneydolZ80Read); + ZetSetWriteHandler(HoneydolZ80Write); + ZetClose(); + + BurnYM3812Init(3000000, &snowbrosFMIRQHandler, &HoneydolSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 999900 / 132, 100.0, 1); + + GenericTilesInit(); + + // Reset the driver + HyperpacDoReset(); + + return 0; +} + +INT32 SnowbrosInit() +{ + INT32 nRet = 0, nLen; + + BurnSetRefreshRate(57.5); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "wintbob")) Wintbob = 1; + + HyperpacNumTiles = 4096; + + // Allocate and Blank all required memory + Mem = NULL; + SnowbrosMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + SnowbrosMemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x80000); + + if (Wintbob) { + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x20000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 12, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x00000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x00001, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x20000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x20001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x40000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x40001, 9, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x60000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x60001, 11, 2); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, WintbobSpritePlaneOffsets, WintbobSpriteXOffsets, WintbobSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + } else { + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(HyperpacZ80Rom, 3, 1); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x00000, 2, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, SnowbrosSpritePlaneOffsets, SnowbrosSpriteXOffsets, SnowbrosSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + BurnFree(HyperpacTempGfx); + } + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(HyperpacRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(HyperpacRam , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(HyperpacPaletteRam, 0x600000, 0x6001ff, SM_RAM); + SekMapMemory(HyperpacSpriteRam , 0x700000, 0x701fff, SM_RAM); + SekSetReadWordHandler(0, SnowbrosReadWord); + SekSetWriteWordHandler(0, SnowbrosWriteWord); + SekSetReadByteHandler(0, SnowbrosReadByte); + SekSetWriteByteHandler(0, SnowbrosWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, HyperpacZ80Rom); + ZetMapArea(0x0000, 0x7fff, 2, HyperpacZ80Rom); + ZetMapArea(0x8000, 0x87ff, 0, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 1, HyperpacZ80Ram); + ZetMapArea(0x8000, 0x87ff, 2, HyperpacZ80Ram); + ZetMemEnd(); + ZetSetInHandler(SnowbrosZ80PortRead); + ZetSetOutHandler(SnowbrosZ80PortWrite); + ZetClose(); + + BurnYM3812Init(3000000, &snowbrosFMIRQHandler, &snowbrosSynchroniseStream, 0); + BurnTimerAttachZetYM3812(6000000); + + GenericTilesInit(); + + // Reset the driver + SnowbrosDoReset(); + + return 0; +} + +INT32 Snowbro3Init() +{ + INT32 nRet = 0, nLen; + + HyperpacNumTiles = 0x1000; + HyperpacNumTiles8bpp = 0x4000; + + // Allocate and Blank all required memory + Mem = NULL; + Snowbro3MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Snowbro3MemIndex(); + + HyperpacTempGfx = (UINT8*)BurnMalloc(0x400000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(HyperpacRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Decode 68000 Program Rom + UINT8 *buffer; + buffer = (UINT8*)BurnMalloc(0x40000); + for (INT32 i = 0; i < 0x40000; i++) { + buffer[i] = HyperpacRom[BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,3,4,1,2,0)]; + } + memcpy(HyperpacRom, buffer, 0x40000); + BurnFree(buffer); + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(HyperpacTempGfx + 0x00000, 2, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles, 4, 16, 16, SnowbrosSpritePlaneOffsets, SnowbrosSpriteXOffsets, SnowbrosSpriteYOffsets, 0x400, HyperpacTempGfx, HyperpacSprites); + + // Load and Decode 8bpp Sprite Roms + memset(HyperpacTempGfx, 0, 0x400000); + nRet = BurnLoadRom(HyperpacTempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(HyperpacTempGfx + 0x200000, 4, 1); if (nRet != 0) return 1; + GfxDecode(HyperpacNumTiles8bpp, 8, 16, 16, Snowbro38BppPlaneOffsets, Snowbro38BppXOffsets, Snowbro38BppYOffsets, 0x800, HyperpacTempGfx, HyperpacSprites8bpp); + + // Load Sample Roms + memset(HyperpacTempGfx, 0, 0x400000); + nRet = BurnLoadRom(HyperpacTempGfx, 5, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM + 0x00000, HyperpacTempGfx + 0x00000, 0x20000); + memcpy(MSM6295ROM + 0x80000, HyperpacTempGfx + 0x20000, 0x60000); + BurnFree(HyperpacTempGfx); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(HyperpacRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(HyperpacRam , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(HyperpacPaletteRam, 0x600000, 0x6003ff, SM_RAM); + SekMapMemory(HyperpacSpriteRam , 0x700000, 0x7021ff, SM_RAM); + SekSetReadWordHandler(0, Snowbro3ReadWord); + SekSetWriteWordHandler(0, Snowbro3WriteWord); + SekSetReadByteHandler(0, Snowbro3ReadByte); + SekSetWriteByteHandler(0, Snowbro3WriteByte); + SekClose(); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 999900 / 132, 100.0, 0); + + GenericTilesInit(); + + // Reset the driver + Snowbro3DoReset(); + + return 0; +} + +INT32 HyperpacExit() +{ + BurnYM3812Exit(); + BurnYM2151Exit(); + MSM6295Exit(0); + + SekExit(); + ZetExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + HyperpacNumTiles = 0; + HyperpacNumTiles8bpp = 0; + + Moremore = 0; + Threein1semi = 0; + Cookbib3 = 0; + Fourin1boot = 0; + Finalttr = 0; + Twinadv = 0; + Honeydol = 0; + + return 0; +} + +INT32 SnowbrosExit() +{ + BurnYM3812Exit(); + MSM6295Exit(0); + + SekExit(); + ZetExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + HyperpacNumTiles = 0; + HyperpacNumTiles8bpp = 0; + Wintbob = 0; + + Snowbro3Music = 0; + Snowbro3MusicPlaying = 0; + + return 0; +} + +void HyperpacRenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + for (Offs = 0; Offs < 0x2000; Offs += 16) { + INT32 dx = ((HyperpacSpriteRam[Offs + 9] << 8) + HyperpacSpriteRam[Offs + 8]) & 0xff; + INT32 dy = ((HyperpacSpriteRam[Offs + 11] << 8) + HyperpacSpriteRam[Offs + 10]) & 0xff; + INT32 TileColour = (HyperpacSpriteRam[Offs + 7] << 8) + HyperpacSpriteRam[Offs + 6]; + INT32 Attr = (HyperpacSpriteRam[Offs + 15] << 8) + HyperpacSpriteRam[Offs + 14]; + INT32 Attr2 = (HyperpacSpriteRam[Offs + 13] << 8) + HyperpacSpriteRam[Offs + 12]; + INT32 FlipX = Attr & 0x80; + INT32 FlipY = (Attr & 0x40) << 1; + INT32 Tile = ((Attr & 0x3f) << 8) + (Attr2 & 0xff); + INT32 Colour = (TileColour & 0xf0) >> 4; + + if (TileColour & 1) dx = -1 - (dx ^ 0xff); + if (TileColour & 2) dy = -1 - (dy ^ 0xff); + if (TileColour & 4) { + x += dx; + y += dy; + } else { + x = dx; + y = dy; + } + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } + } +} + +void TwinadvRenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + for (Offs = 0; Offs < 0x2000; Offs += 16) { + INT32 dx = ((HyperpacSpriteRam[Offs + 9] << 8) + HyperpacSpriteRam[Offs + 8]) & 0xff; + INT32 dy = ((HyperpacSpriteRam[Offs + 11] << 8) + HyperpacSpriteRam[Offs + 10]) & 0xff; + INT32 TileColour = (HyperpacSpriteRam[Offs + 7] << 8) + HyperpacSpriteRam[Offs + 6]; + INT32 Attr = (HyperpacSpriteRam[Offs + 15] << 8) + HyperpacSpriteRam[Offs + 14]; + INT32 Attr2 = (HyperpacSpriteRam[Offs + 13] << 8) + HyperpacSpriteRam[Offs + 12]; + INT32 FlipX = Attr & 0x80; + INT32 FlipY = (Attr & 0x40) << 1; + INT32 Tile = ((Attr & 0x3f) << 8) + (Attr2 & 0xff); + INT32 Colour = (TileColour & 0xf0) >> 4; + Colour ^= 0xf; + + x = dx; + y = dy; + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } + } +} + +void HoneydolRenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + for (Offs = 0; Offs < 0x2000; Offs += 16) { + INT32 dx = (((HyperpacSpriteRam[Offs + 9] << 8) + HyperpacSpriteRam[Offs + 8]) >> 8) & 0xff; + INT32 dy = (((HyperpacSpriteRam[Offs + 11] << 8) + HyperpacSpriteRam[Offs + 10]) >> 8) & 0xff; + INT32 TileColour = (((HyperpacSpriteRam[Offs + 7] << 8) + HyperpacSpriteRam[Offs + 6]) >> 8) & 3; + INT32 Attr = ((HyperpacSpriteRam[Offs + 15] << 8) + HyperpacSpriteRam[Offs + 14]) >> 8; + INT32 Attr2 = (((HyperpacSpriteRam[Offs + 13] << 8) + HyperpacSpriteRam[Offs + 12]) >> 8) & 0xff; + INT32 FlipX = Attr & 0x80; + INT32 FlipY = (Attr & 0x40) << 1; + INT32 Tile = ((Attr & 0x3f) << 8) + (Attr2 & 0xff); + INT32 Colour = TileColour; + + x = dx; + y = dy; + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 8, 0, 0, HyperpacSprites8bpp); + } + } + } + + + + + dx = ((HyperpacSpriteRam[Offs + 9] << 8) + HyperpacSpriteRam[Offs + 8]) & 0xff; + dy = ((HyperpacSpriteRam[Offs + 11] << 8) + HyperpacSpriteRam[Offs + 10]) & 0xff; + TileColour = (HyperpacSpriteRam[Offs + 7] << 8) + HyperpacSpriteRam[Offs + 6]; + Attr = (HyperpacSpriteRam[Offs + 15] << 8) + HyperpacSpriteRam[Offs + 14]; + Attr2 = (HyperpacSpriteRam[Offs + 13] << 8) + HyperpacSpriteRam[Offs + 12]; + FlipX = Attr & 0x80; + FlipY = (Attr & 0x40) << 1; + Tile = ((Attr & 0x3f) << 8) + (Attr2 & 0xff); + Colour = (TileColour & 0x3f0) >> 4; + Colour ^= 0x3f; + + x = dx; + y = dy; + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } + } +} + +void SnowbrosRenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + for (Offs = 0; Offs < 0x2000; Offs += 16) { + INT32 dx = ((HyperpacSpriteRam[Offs + 9] << 8) + HyperpacSpriteRam[Offs + 8]) & 0xff; + INT32 dy = ((HyperpacSpriteRam[Offs + 11] << 8) + HyperpacSpriteRam[Offs + 10]) & 0xff; + INT32 TileColour = (HyperpacSpriteRam[Offs + 7] << 8) + HyperpacSpriteRam[Offs + 6]; + INT32 Attr = (HyperpacSpriteRam[Offs + 15] << 8) + HyperpacSpriteRam[Offs + 14]; + INT32 Attr2 = (HyperpacSpriteRam[Offs + 13] << 8) + HyperpacSpriteRam[Offs + 12]; + INT32 FlipX = Attr & 0x80; + INT32 FlipY = (Attr & 0x40) << 1; + INT32 Tile = ((Attr & 0x1f) << 8) + (Attr2 & 0xff); + INT32 Colour = (TileColour & 0xf0) >> 4; + + if (TileColour & 1) dx = -1 - (dx ^ 0xff); + if (TileColour & 2) dy = -1 - (dy ^ 0xff); + if (TileColour & 4) { + x += dx; + y += dy; + } else { + x = dx; + y = dy; + } + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } + } +} + +void WintbobRenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + UINT16 *SpriteRam = (UINT16*)HyperpacSpriteRam; + + for (Offs = 0; Offs < 0x2000 >> 1; Offs += 8) { + x = SpriteRam[Offs + 0] & 0xff; + y = SpriteRam[Offs + 4] & 0xff; + INT32 Attr = SpriteRam[Offs + 1]; + INT32 Disbl = Attr & 0x02; + INT32 Wrapr = Attr & 0x08; + INT32 Colour = (Attr & 0xf0) >> 4; + INT32 Attr2 = SpriteRam[Offs + 2]; + INT32 Tile = (Attr2 << 8) | (SpriteRam[Offs + 3] & 0xff); + INT32 FlipX = Attr2 & 0x80; + INT32 FlipY = (Attr2 & 0x40) << 1; + + if (Wrapr == 8) x -= 256; + + Tile &= 0xfff; + + if (Disbl == 2) continue; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, 4, 0, 0, HyperpacSprites); + } + } + } + } +} + +void Snowbro3RenderSpriteLayer() +{ + INT32 x = 0, y = 0, Offs; + + UINT16 *SpriteRam = (UINT16*)HyperpacSpriteRam; + UINT8 *pTile = NULL; + INT32 ColourDepth = 0; + + for (Offs = 0; Offs < 0x2200 >> 1; Offs += 8) { + INT32 dx = SpriteRam[Offs + 4] & 0xff; + INT32 dy = SpriteRam[Offs + 5] & 0xff; + INT32 TileColour = SpriteRam[Offs + 3]; + INT32 Attr = SpriteRam[Offs + 7]; + INT32 Attr2 = SpriteRam[Offs + 6]; + INT32 FlipX = Attr & 0x80; + INT32 FlipY = (Attr & 0x40) << 1; + INT32 Tile = ((Attr & 0xff) << 8) + (Attr2 & 0xff); + + if (TileColour & 1) dx = -1 - (dx ^ 0xff); + if (TileColour & 2) dy = -1 - (dy ^ 0xff); + if (TileColour & 4) { + x += dx; + y += dy; + } else { + x = dx; + y = dy; + } + + if (x > 511) x &= 0x1ff; + if (y > 511) y &= 0x1ff; + + if (Offs < 0x800) { + TileColour = 0x10; + Tile &= 0x3fff; + ColourDepth = 8; + pTile = HyperpacSprites8bpp; + } else { + Tile &= 0xfff; + ColourDepth = 4; + pTile = HyperpacSprites; + } + + INT32 Colour = (TileColour & 0xf0) >> 4; + + if (x > 15 && x < 240 && (y - 16) > 15 && (y - 16) <= 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, x, y - 16, Colour, ColourDepth, 0, 0, pTile); + } + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 0) & 0x1f; + g = (nColour >> 5) & 0x1f; + b = (nColour >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + return BurnHighCol(r, g, b, 0); +} + +INT32 HyperpacCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)HyperpacPaletteRam, pd = HyperpacPalette; i < 0x200; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +INT32 HoneydolCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)HyperpacPaletteRam, pd = HyperpacPalette; i < 0x800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +INT32 Snowbro3CalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)HyperpacPaletteRam, pd = HyperpacPalette; i < 0x400; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +void HyperpacRender() +{ + HyperpacCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xf0; + } + + HyperpacRenderSpriteLayer(); + BurnTransferCopy(HyperpacPalette); +} + +void PzlbreakRender() +{ + HyperpacCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xc0; + } + + HyperpacRenderSpriteLayer(); + BurnTransferCopy(HyperpacPalette); +} + +void TwinadvRender() +{ + HyperpacCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xf0; + } + + TwinadvRenderSpriteLayer(); + BurnTransferCopy(HyperpacPalette); +} + +void HoneydolRender() +{ + HoneydolCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xf0; + } + + HoneydolRenderSpriteLayer(); + BurnTransferCopy(HyperpacPalette); +} + +void SnowbrosRender() +{ + HyperpacCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xf0; + } + + if (Wintbob) { + WintbobRenderSpriteLayer(); + } else { + SnowbrosRenderSpriteLayer(); + } + BurnTransferCopy(HyperpacPalette); +} + +void Snowbro3Render() +{ + Snowbro3CalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0xf0; + + } + + Snowbro3RenderSpriteLayer(); + BurnTransferCopy(HyperpacPalette); +} + +INT32 HyperpacFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) HyperpacDoReset(); + + HyperpacMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + if (pBurnDraw) HyperpacRender(); + + return 0; +} + +INT32 PzlbreakFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) HyperpacDoReset(); + + HyperpacMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + if (pBurnDraw) PzlbreakRender(); + + return 0; +} + +INT32 FinalttrFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) HyperpacDoReset(); + + HyperpacMakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 3578545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + + if (pBurnDraw) HyperpacRender(); + + return 0; +} + +INT32 TwinadvFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) HyperpacDoReset(); + + HyperpacMakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 2) ZetRaiseIrq(0); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + ZetClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) TwinadvRender(); + + return 0; +} + +INT32 HoneydolFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) HyperpacDoReset(); + + HyperpacMakeInputs(); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - SekTotalCycles(); + SekRun(nCyclesSegment); + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T("%i\ %i\n"), nCyclesDone[0], nCyclesDone[1]); + + ZetClose(); + SekClose(); + + if (pBurnDraw) HoneydolRender(); + + return 0; +} + +INT32 SnowbrosFrame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) SnowbrosDoReset(); + + HyperpacMakeInputs(); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (Wintbob) ? 12000000 / 60 : 8000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - SekTotalCycles(); + SekRun(nCyclesSegment); + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T("%i\ %i\n"), nCyclesDone[0], nCyclesDone[1]); + + ZetClose(); + SekClose(); + + if (pBurnDraw) SnowbrosRender(); + + return 0; +} + +INT32 Snowbro3Frame() +{ + INT32 nInterleave = 4; + + if (HyperpacReset) Snowbro3DoReset(); + + HyperpacMakeInputs(); + + SekOpen(0); + + SekNewFrame(); + + SekIdle(nCyclesDone[0]); + + nCyclesTotal[0] = 16000000 / 60; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - SekTotalCycles(); + SekRun(nCyclesSegment); + + if (i == 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 2) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + INT32 Status = MSM6295ReadStatus(0); + if (Snowbro3MusicPlaying) { + if ((Status & 0x08) == 0x00) { + MSM6295Command(0, 0x80 | Snowbro3Music); + MSM6295Command(0, 0x82); + } + } else { + if ((Status & 0x08) == 0x00) { + MSM6295Command(0, 0x40); + } + } + } + + SekClose(); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + + SekClose(); + + if (pBurnSoundOut) MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) Snowbro3Render(); + + return 0; +} + +static INT32 HyperpacScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x02944; + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + BurnYM2151Scan(nAction); + + // Scan critical driver variables + SCAN_VAR(HyperpacSoundLatch); + SCAN_VAR(HyperpacInput); + SCAN_VAR(HyperpacDip); + } + + return 0; +} + +static INT32 SnowbrosScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029519; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + SCAN_VAR(nCyclesDone); + + BurnYM3812Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(HyperpacSoundLatch); + SCAN_VAR(HyperpacInput); + SCAN_VAR(HyperpacDip); + } + + return 0; +} + +static INT32 Snowbro3Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + + // Scan critical driver variables + SCAN_VAR(HyperpacSoundLatch); + SCAN_VAR(HyperpacInput); + SCAN_VAR(HyperpacDip); + SCAN_VAR(Snowbro3Music); + SCAN_VAR(Snowbro3MusicPlaying); + } + + return 0; +} + +struct BurnDriver BurnDrvHyperpac = { + "hyperpac", NULL, NULL, NULL, "1995", + "Hyper Pacman\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, HyperpacRomInfo, HyperpacRomName, NULL, NULL, HyperpacInputInfo, HyperpacDIPInfo, + HyperpacInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHyperpacb = { + "hyperpacb", "hyperpac", NULL, NULL, "1995", + "Hyper Pacman (bootleg)\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, HyperpacbRomInfo, HyperpacbRomName, NULL, NULL, HyperpacInputInfo, HyperpacDIPInfo, + HyperpacInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCookbib2 = { + "cookbib2", NULL, NULL, NULL, "1996", + "Cookie & Bibi 2\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Cookbib2RomInfo, Cookbib2RomName, NULL, NULL, HyperpacInputInfo, Cookbib2DIPInfo, + Cookbib2Init, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCookbib3 = { + "cookbib3", NULL, NULL, NULL, "1997", + "Cookie & Bibi 3\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, Cookbib3RomInfo, Cookbib3RomName, NULL, NULL, HyperpacInputInfo, Cookbib3DIPInfo, + Cookbib3Init, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMoremore = { + "moremore", NULL, NULL, NULL, "1999", + "More More\0", NULL, "SemiCom / Exit", "Kaneko Pandora based", + L"More More\0\uBAA8\uC544\uBAA8\uC544 More More\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, MoremoreRomInfo, MoremoreRomName, NULL, NULL, HyperpacInputInfo, MoremoreDIPInfo, + MoremoreInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMoremorp = { + "moremorp", NULL, NULL, NULL, "1999", + "More More Plus\0", NULL, "SemiCom / Exit", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, MoremorpRomInfo, MoremorpRomName, NULL, NULL, HyperpacInputInfo, MoremoreDIPInfo, + MoremoreInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThreein1semi = { + "3in1semi", NULL, NULL, NULL, "1997", + "XESS - The New Revolution (SemiCom 3-in-1)\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, Threein1semiRomInfo, Threein1semiRomName, NULL, NULL, HyperpacInputInfo, MoremoreDIPInfo, + MoremoreInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvToppyrap = { + "toppyrap", NULL, NULL, NULL, "1996", + "Toppy & Rappy\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, ToppyrapRomInfo, ToppyrapRomName, NULL, NULL, HyperpacInputInfo, ToppyrapDIPInfo, + MoremoreInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTwinkle = { + "twinkle", NULL, NULL, NULL, "1997", + "Twinkle\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, TwinkleRomInfo, TwinkleRomName, NULL, NULL, HyperpacInputInfo, MoremoreDIPInfo, + TwinkleInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPzlbreak = { + "pzlbreak", NULL, NULL, NULL, "1997", + "Puzzle Break\0", NULL, "SemiCom", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, PzlbreakRomInfo, PzlbreakRomName, NULL, NULL, HyperpacInputInfo, MoremoreDIPInfo, + PzlbreakInit, HyperpacExit, PzlbreakFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFourin1boot = { + "4in1boot", NULL, NULL, NULL, "2002", + "Puzzle King\0", NULL, "K1 Soft", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, Fourin1bootRomInfo, Fourin1bootRomName, NULL, NULL, HyperpacInputInfo, Fourin1bootDIPInfo, + Fourin1bootInit, HyperpacExit, HyperpacFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFinalttr = { + "finalttr", NULL, NULL, NULL, "1993", + "Final Tetris\0", NULL, "Jeil Computer System", "Kaneko Pandora based", + L"Final Tetris\0\uD30C\uC774\uB110 \uD14C\uD2B8\uB9AC\uC2A4\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, FinalttrRomInfo, FinalttrRomName, NULL, NULL, HyperpacInputInfo, FinalttrDIPInfo, + FinalttrInit, HyperpacExit, FinalttrFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTwinadv = { + "twinadv", NULL, NULL, NULL, "1995", + "Twin Adventure (World)\0", NULL, "Barko Corp", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, TwinadvRomInfo, TwinadvRomName, NULL, NULL, HyperpacInputInfo, TwinadvDIPInfo, + TwinadvInit, HyperpacExit, TwinadvFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTwinadvk = { + "twinadvk", "twinadv", NULL, NULL, "1995", + "Twin Adventure (Korea)\0", NULL, "Barko Corp", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, TwinadvkRomInfo, TwinadvkRomName, NULL, NULL, HyperpacInputInfo, TwinadvDIPInfo, + TwinadvInit, HyperpacExit, TwinadvFrame, NULL, HyperpacScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHoneydol = { + "honeydol", NULL, NULL, NULL, "1995", + "Honey Dolls\0", NULL, "Barko Corp", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, HoneydolRomInfo, HoneydolRomName, NULL, NULL, HyperpacInputInfo, HoneydolDIPInfo, + HoneydolInit, HyperpacExit, HoneydolFrame, NULL, HyperpacScan, + NULL, 0x800, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbros = { + "snowbros", NULL, NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (set 1)\0", NULL, "Toaplan", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbrosRomInfo, SnowbrosRomName, NULL, NULL, SnowbrosInputInfo, SnowbrosDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbroa = { + "snowbrosa", "snowbros", NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (set 2)\0", NULL, "Toaplan", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbroaRomInfo, SnowbroaRomName, NULL, NULL, SnowbrosInputInfo, SnowbrosDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbrob = { + "snowbrosb", "snowbros", NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (set 3)\0", NULL, "Toaplan", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbrobRomInfo, SnowbrobRomName, NULL, NULL, SnowbrosInputInfo, SnowbrosDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbroc = { + "snowbrosc", "snowbros", NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (set 4)\0", NULL, "Toaplan", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbrocRomInfo, SnowbrocRomName, NULL, NULL, SnowbrosInputInfo, SnowbrosDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbroj = { + "snowbrosj", "snowbros", NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (Japan)\0", NULL, "Toaplan", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbrojRomInfo, SnowbrojRomName, NULL, NULL, SnowbrosInputInfo, SnowbrojDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbrod = { + "snowbrosd", "snowbros", NULL, NULL, "1990", + "Snow Bros. - Nick & Tom (Dooyong license)\0", NULL, "Toaplan (Dooyong license)", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SnowbrodRomInfo, SnowbrodRomName, NULL, NULL, SnowbrosInputInfo, SnowbrojDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWintbob = { + "wintbob", "snowbros", NULL, NULL, "1990", + "The Winter Bobble (bootleg)\0", NULL, "bootleg", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, WintbobRomInfo, WintbobRomName, NULL, NULL, SnowbrosInputInfo, SnowbrosDIPInfo, + SnowbrosInit, SnowbrosExit, SnowbrosFrame, NULL, SnowbrosScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnowbro3 = { + "snowbros3", "snowbros", NULL, NULL, "2002", + "Snow Brothers 3 - Magical Adventure\0", NULL, "bootleg", "Kaneko Pandora based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, Snowbro3RomInfo, Snowbro3RomName, NULL, NULL, SnowbrosInputInfo, SnowbrojDIPInfo, + Snowbro3Init, SnowbrosExit, Snowbro3Frame, NULL, Snowbro3Scan, + NULL, 0x400, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_kaneko16.cpp b/src/burn/drivers/misc_post90s/d_kaneko16.cpp new file mode 100644 index 00000000..1df83fce --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_kaneko16.cpp @@ -0,0 +1,5029 @@ +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym2151.h" +#include "eeprom.h" +#include "kanekotb.h" + +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +/*============================================================================================== +Driver Variables +===============================================================================================*/ + +static UINT8 Kaneko16InputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Kaneko16InputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Kaneko16InputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Kaneko16InputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Kaneko16Dip[2] = {0, 0}; +static UINT8 Kaneko16Input[4] = {0x00, 0x00, 0x00, 0x00}; +static UINT8 Kaneko16Reset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Kaneko16Rom = NULL; +static UINT8 *Kaneko16Z80Rom = NULL; +static UINT8 *MSM6295ROMData = NULL; +static UINT8 *MSM6295ROMData2 = NULL; +static UINT8 *Kaneko16Ram = NULL; +static UINT8 *Kaneko16Z80Ram = NULL; +static UINT8 *Kaneko16MCURam = NULL; +static UINT8 *Kaneko16NVRam = NULL; +static UINT8 *Kaneko16PaletteRam = NULL; +static UINT8 *Kaneko16SpriteRam = NULL; +static UINT8 *Kaneko16Video0Ram = NULL; +static UINT8 *Kaneko16Video1Ram = NULL; +static UINT8 *Kaneko16Video2Ram = NULL; +static UINT8 *Kaneko16Video3Ram = NULL; +static UINT8 *Kaneko16VScrl0Ram = NULL; +static UINT8 *Kaneko16VScrl1Ram = NULL; +static UINT8 *Kaneko16VScrl2Ram = NULL; +static UINT8 *Kaneko16VScrl3Ram = NULL; +static UINT32 *Kaneko16Palette = NULL; +static UINT8 *Kaneko16Tiles = NULL; +static UINT8 *Kaneko16Tiles2 = NULL; +static UINT8 *Kaneko16Sprites = NULL; +static UINT8 *Kaneko16TempGfx = NULL; + +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[6]; + +static UINT32 Kaneko16SoundLatch; +static INT32 MSM6295Bank0; +static INT32 MSM6295Bank1; + +static UINT16 ToyboxMCUCom[4]; + +static UINT16 Kaneko16Bg15Reg; +static UINT16 Kaneko16Bg15Select; +static UINT16 *Kaneko16Bg15Data = NULL; +static UINT8 Kaneko16RecalcBg15Palette; + +static UINT16 Kaneko16SpriteFlipX; +static UINT16 Kaneko16SpriteFlipY; +static UINT16 Kaneko16SpriteRegs[0x20]; +static UINT16 Kaneko16Layer0Regs[0x10]; +static UINT16 Kaneko16Layer1Regs[0x10]; +static UINT32 Kaneko16SpritesColourOffset; +static UINT32 Kaneko16LayersColourOffset; +static UINT32 Kaneko16SpritesColourMask; +static UINT16 Kaneko16DisplayEnable; +static INT32 Kaneko16TilesXOffset; +static INT32 Kaneko16TilesYOffset; +static INT32 Kaneko16SpriteXOffset; + +static UINT32 *LayerQueueXY[4]; +static UINT32 *LayerQueueColour[4]; +static UINT8 *LayerQueuePriority[4]; +static INT32 LayerQueueSize[4]; + +static INT32 Kaneko16NumTiles; +static INT32 Kaneko16NumTiles2; +static INT32 Kaneko16NumSprites; +static INT32 Kaneko16SpriteRamSize; + +// Flags +static INT32 Kaneko168BppSprites; +static INT32 Kaneko16Eeprom; +static INT32 Kaneko16Bg15; +static INT32 Gtmr; +static INT32 Bloodwar; +static INT32 Bonkadv; +static INT32 Mgcrystl; + +typedef void (*MCURun)(); +MCURun ToyboxMCURun; + +typedef void (*FrameRender)(); +FrameRender Kaneko16FrameRender; +void BerlwallFrameRender(); +void BlazeonFrameRender(); +void BloodwarFrameRender(); +void ExplbrkrFrameRender(); +void GtmrFrameRender(); +void MgcrystlFrameRender(); + +typedef INT32 (*ParseSprite)(INT32, struct tempsprite*); +ParseSprite Kaneko16ParseSprite; +static INT32 Kaneko16ParseSpriteType0(INT32 i, struct tempsprite *s); +static INT32 Kaneko16ParseSpriteType1(INT32 i, struct tempsprite *s); +static INT32 Kaneko16ParseSpriteType2(INT32 i, struct tempsprite *s); + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; +static INT32 nSoundBufferPos; + +struct tempsprite +{ + INT32 code,color; + INT32 x,y; + INT32 xoffs,yoffs; + INT32 flipx,flipy; + INT32 priority; +}; + +static struct +{ + struct tempsprite *first_sprite; +} spritelist; + +/*============================================================================================== +Input Definitions +===============================================================================================*/ + +static struct BurnInputInfo BerlwallInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , Kaneko16InputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , Kaneko16InputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 4, "diag" }, + {"Tilt" , BIT_DIGITAL , Kaneko16InputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, Kaneko16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Berlwall) + +static struct BurnInputInfo BlazeonInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort1 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort1 + 6, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 7, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 5, "diag" }, + {"Tilt" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, Kaneko16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Blazeon) + +static struct BurnInputInfo BloodwarInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , Kaneko16InputPort0 + 6, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , Kaneko16InputPort0 + 7, "p1 fire 4" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , Kaneko16InputPort1 + 6, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , Kaneko16InputPort3 + 2, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 4, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, +}; + +STDINPUTINFO(Bloodwar) + +static struct BurnInputInfo BonkadvInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 4, "diag" }, + {"Tilt" , BIT_DIGITAL , Kaneko16InputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, +}; + +STDINPUTINFO(Bonkadv) + +static struct BurnInputInfo ExplbrkrInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, +}; + +STDINPUTINFO(Explbrkr) + +static struct BurnInputInfo GtmrInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 4, "diag" }, + {"Tilt" , BIT_DIGITAL , Kaneko16InputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, +}; + +STDINPUTINFO(Gtmr) + +static struct BurnInputInfo MgcrystlInputList[] = { + {"Coin 1" , BIT_DIGITAL , Kaneko16InputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Kaneko16InputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Kaneko16InputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Kaneko16InputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Kaneko16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Kaneko16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Kaneko16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Kaneko16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Kaneko16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Kaneko16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Kaneko16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Kaneko16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Kaneko16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Kaneko16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Kaneko16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Kaneko16InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Kaneko16Reset , "reset" }, + {"Service" , BIT_DIGITAL , Kaneko16InputPort2 + 6, "service" }, + {"Test" , BIT_DIGITAL , Kaneko16InputPort2 + 4, "diag" }, + {"Tilt" , BIT_DIGITAL , Kaneko16InputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, Kaneko16Dip + 0 , "dip" }, +}; + +STDINPUTINFO(Mgcrystl) + +inline void Kaneko16ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void Kaneko16MakeInputs() +{ + // Reset Inputs + Kaneko16Input[0] = Kaneko16Input[1] = Kaneko16Input[2] = Kaneko16Input[3] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + Kaneko16Input[0] |= (Kaneko16InputPort0[i] & 1) << i; + Kaneko16Input[1] |= (Kaneko16InputPort1[i] & 1) << i; + Kaneko16Input[2] |= (Kaneko16InputPort2[i] & 1) << i; + Kaneko16Input[3] |= (Kaneko16InputPort3[i] & 1) << i; + } + + // Clear Opposites + Kaneko16ClearOpposites(&Kaneko16Input[0]); + Kaneko16ClearOpposites(&Kaneko16Input[1]); +} + +/*============================================================================================== +Dip Switch Definitions +===============================================================================================*/ + +static struct BurnDIPInfo BerlwallDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Screen Direction" }, + {0x16, 0x01, 0x01, 0x01, "Normal" }, + {0x16, 0x01, 0x01, 0x00, "Reverse" }, + + {0 , 0xfe, 0 , 8 , "Coin Slot A" }, + {0x16, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x16, 0x01, 0x1c, 0x18, "1 Coins 2 Credits" }, + {0x16, 0x01, 0x1c, 0x14, "1 Coins 3 Credits" }, + {0x16, 0x01, 0x1c, 0x10, "1 Coins 4 Credits" }, + {0x16, 0x01, 0x1c, 0x0c, "2 Coins 1 Credit" }, + {0x16, 0x01, 0x1c, 0x08, "2 Coin 3 Credits" }, + {0x16, 0x01, 0x1c, 0x04, "3 Coins 1 Credit" }, + {0x16, 0x01, 0x1c, 0x00, "4 Coins 1 Credit" }, + + {0 , 0xfe, 0 , 8 , "Coin Slot B" }, + {0x16, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x16, 0x01, 0xe0, 0xc0, "1 Coins 2 Credits" }, + {0x16, 0x01, 0xe0, 0xa0, "1 Coins 3 Credits" }, + {0x16, 0x01, 0xe0, 0x80, "1 Coins 4 Credits" }, + {0x16, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0x40, "2 Coin 3 Credits" }, + {0x16, 0x01, 0xe0, 0x20, "1 Coin 5 Credits" }, + {0x16, 0x01, 0xe0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Game Level" }, + {0x17, 0x01, 0x03, 0x03, "Standard" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x01, "Difficult" }, + {0x17, 0x01, 0x03, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 4 , "Number of Players" }, + {0x17, 0x01, 0x0c, 0x0c, "3" }, + {0x17, 0x01, 0x0c, 0x08, "2" }, + {0x17, 0x01, 0x0c, 0x04, "5" }, + {0x17, 0x01, 0x0c, 0x00, "7" }, + + {0 , 0xfe, 0 , 4 , "Language Type" }, + {0x17, 0x01, 0x30, 0x30, "English" }, + {0x17, 0x01, 0x30, 0x20, "Italy" }, + {0x17, 0x01, 0x30, 0x10, "Germany" }, + {0x17, 0x01, 0x30, 0x00, "Pause Mode" }, + + {0 , 0xfe, 0 , 2 , "Demonstration Sound" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Testmode Switch" }, + {0x17, 0x01, 0x80, 0x80, "Normal Game" }, + {0x17, 0x01, 0x80, 0x00, "Testmode" }, +}; + +STDDIPINFO(Berlwall) + +static struct BurnDIPInfo BerlwalltDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Screen Direction" }, + {0x16, 0x01, 0x01, 0x01, "Normal" }, + {0x16, 0x01, 0x01, 0x00, "Reverse" }, + + {0 , 0xfe, 0 , 8 , "Coin Slot A" }, + {0x16, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x16, 0x01, 0x1c, 0x18, "1 Coins 2 Credits" }, + {0x16, 0x01, 0x1c, 0x14, "1 Coins 3 Credits" }, + {0x16, 0x01, 0x1c, 0x10, "1 Coins 4 Credits" }, + {0x16, 0x01, 0x1c, 0x0c, "2 Coins 1 Credit" }, + {0x16, 0x01, 0x1c, 0x08, "2 Coin 3 Credits" }, + {0x16, 0x01, 0x1c, 0x04, "3 Coins 1 Credit" }, + {0x16, 0x01, 0x1c, 0x00, "4 Coins 1 Credit" }, + + {0 , 0xfe, 0 , 8 , "Coin Slot B" }, + {0x16, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x16, 0x01, 0xe0, 0xc0, "1 Coins 2 Credits" }, + {0x16, 0x01, 0xe0, 0xa0, "1 Coins 3 Credits" }, + {0x16, 0x01, 0xe0, 0x80, "1 Coins 4 Credits" }, + {0x16, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0x40, "2 Coin 3 Credits" }, + {0x16, 0x01, 0xe0, 0x20, "1 Coin 5 Credits" }, + {0x16, 0x01, 0xe0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Game Level" }, + {0x17, 0x01, 0x03, 0x03, "Standard" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x01, "Difficult" }, + {0x17, 0x01, 0x03, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 4 , "Number of Players" }, + {0x17, 0x01, 0x0c, 0x0c, "2" }, + {0x17, 0x01, 0x0c, 0x08, "3" }, + {0x17, 0x01, 0x0c, 0x04, "5" }, + {0x17, 0x01, 0x0c, 0x00, "1" }, + + {0 , 0xfe, 0 , 4 , "Language Type" }, + {0x17, 0x01, 0x30, 0x30, "English" }, + {0x17, 0x01, 0x30, 0x20, "Italy" }, + {0x17, 0x01, 0x30, 0x10, "Germany" }, + {0x17, 0x01, 0x30, 0x00, "Pause Mode" }, + + {0 , 0xfe, 0 , 2 , "Demonstration Sound" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Testmode Switch" }, + {0x17, 0x01, 0x80, 0x80, "Normal Game" }, + {0x17, 0x01, 0x80, 0x00, "Testmode" }, +}; + +STDDIPINFO(Berlwallt) + +static struct BurnDIPInfo BlazeonDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Standard" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Strong" }, + + {0 , 0xfe, 0 , 4 , "Number of Players" }, + {0x14, 0x01, 0x0c, 0x00, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Demonstration Sound" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 16 , "Coin Rate Slot A" }, + {0x15, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x15, 0x01, 0x0f, 0x01, "2 Coin 3 Play" }, + {0x15, 0x01, 0x0f, 0x02, "4 Coin 5 Play" }, + {0x15, 0x01, 0x0f, 0x03, "5 Coin 6 Play" }, + {0x15, 0x01, 0x0f, 0x04, "4 Coin 3 Play" }, + {0x15, 0x01, 0x0f, 0x05, "6 Coin 3 Play" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coin 3 Play" }, + {0x15, 0x01, 0x0f, 0x07, "4 Coin 1 Play" }, + {0x15, 0x01, 0x0f, 0x08, "3 Coin 1 Play" }, + {0x15, 0x01, 0x0f, 0x09, "2 Coin 1 Play" }, + {0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Play" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Play" }, + {0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Play" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Play" }, + {0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Play" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 16 , "Coin Rate Slot B" }, + {0x15, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x15, 0x01, 0xf0, 0x10, "2 Coin 3 Play" }, + {0x15, 0x01, 0xf0, 0x20, "4 Coin 5 Play" }, + {0x15, 0x01, 0xf0, 0x30, "5 Coin 6 Play" }, + {0x15, 0x01, 0xf0, 0x40, "4 Coin 3 Play" }, + {0x15, 0x01, 0xf0, 0x50, "6 Coin 3 Play" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coin 3 Play" }, + {0x15, 0x01, 0xf0, 0x70, "4 Coin 1 Play" }, + {0x15, 0x01, 0xf0, 0x80, "3 Coin 1 Play" }, + {0x15, 0x01, 0xf0, 0x90, "2 Coin 1 Play" }, + {0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Play" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Play" }, + {0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Play" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Play" }, + {0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Play" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, +}; + +STDDIPINFO(Blazeon) + +static struct BurnDIPInfo BloodwarDIPList[]= +{ + // Default Values + {0x17, 0xff, 0xff, 0x01, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x17, 0x01, 0x02, 0x00, "Off" }, + {0x17, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Screen Flip" }, + {0x17, 0x01, 0x04, 0x00, "Normal" }, + {0x17, 0x01, 0x04, 0x04, "Reverse" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x17, 0x01, 0x38, 0x00, "1 Easy" }, + {0x17, 0x01, 0x38, 0x08, "2" }, + {0x17, 0x01, 0x38, 0x10, "3" }, + {0x17, 0x01, 0x38, 0x18, "4" }, + {0x17, 0x01, 0x38, 0x20, "5" }, + {0x17, 0x01, 0x38, 0x28, "6" }, + {0x17, 0x01, 0x38, 0x30, "7" }, + {0x17, 0x01, 0x38, 0x38, "8 Hard" }, + + {0 , 0xfe, 0 , 2 , "Join During Game" }, + {0x17, 0x01, 0x40, 0x40, "Impossible" }, + {0x17, 0x01, 0x40, 0x00, "Possible" }, + + {0 , 0xfe, 0 , 2 , "Continue Coin" }, + {0x17, 0x01, 0x80, 0x00, "Normal" }, + {0x17, 0x01, 0x80, 0x80, "Continue coin" }, +}; + +STDDIPINFO(Bloodwar) + +static struct BurnDIPInfo BonkadvDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0x10, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Screen Direction" }, + {0x14, 0x01, 0x01, 0x00, "Standard" }, + {0x14, 0x01, 0x01, 0x01, "Reverse" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sound" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Title Level Display" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Bonkadv) + +static struct BurnDIPInfo ExplbrkrDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Explbrkr) + +static struct BurnDIPInfo GtmrDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x04, 0x00, "Upright" }, + {0x14, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Controls" }, + {0x14, 0x01, 0x18, 0x00, "1 Joystick" }, + {0x14, 0x01, 0x18, 0x10, "2 Joysticks" }, + {0x14, 0x01, 0x18, 0x08, "Wheel (360)" }, + {0x14, 0x01, 0x18, 0x18, "Wheel (270)" }, + + {0 , 0xfe, 0 , 2 , "Use Brake" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "National Anthem & Flag" }, + {0x14, 0x01, 0xc0, 0x00, "Use Memory" }, + {0x14, 0x01, 0xc0, 0x40, "Anthem Only" }, + {0x14, 0x01, 0xc0, 0x80, "Flag Only" }, + {0x14, 0x01, 0xc0, 0xc0, "None" }, +}; + +STDDIPINFO(Gtmr) + +static struct BurnDIPInfo Gtmr2DIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 5 , "Communication" }, + {0x14, 0x01, 0x07, 0x00, "None" }, + {0x14, 0x01, 0x07, 0x01, "Machine 1" }, + {0x14, 0x01, 0x07, 0x02, "Machine 2" }, + {0x14, 0x01, 0x07, 0x03, "Machine 3" }, + {0x14, 0x01, 0x07, 0x04, "Machine 4" }, + + {0 , 0xfe, 0 , 4 , "Controls" }, + {0x14, 0x01, 0x18, 0x00, "Joystick" }, + {0x14, 0x01, 0x18, 0x10, "Wheel (360)" }, + {0x14, 0x01, 0x18, 0x08, "Wheel (270D)" }, + {0x14, 0x01, 0x18, 0x18, "Wheel (270A)" }, + + {0 , 0xfe, 0 , 2 , "Pedal Function" }, + {0x14, 0x01, 0x20, 0x00, "Microswitch" }, + {0x14, 0x01, 0x20, 0x20, "Potentiometer" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Gtmr2) + +static struct BurnDIPInfo MgcrystlDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Mgcrystl) + +/*============================================================================================== +ROM Descriptions +===============================================================================================*/ + +static struct BurnRomInfo BerlwallRomDesc[] = { + { "u23_01.bin", 0x020000, 0x76b526ce, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u39_01.bin", 0x020000, 0x78fa7ef2, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "bw001", 0x080000, 0xbc927260, BRF_GRA }, // 2 Sprites + { "bw002", 0x080000, 0x223f5465, BRF_GRA }, // 3 Sprites + { "bw300", 0x020000, 0xb258737a, BRF_GRA }, // 4 Sprites + + { "bw003", 0x080000, 0xfbb4b72d, BRF_GRA }, // 5 Tiles + + { "bw004", 0x080000, 0x5300c34d, BRF_GRA }, // 6 High colour background + { "bw008", 0x080000, 0x9aaf2f2f, BRF_GRA }, // 7 High colour background + { "bw005", 0x080000, 0x16db6d43, BRF_GRA }, // 8 High colour background + { "bw009", 0x080000, 0x1151a0b0, BRF_GRA }, // 9 High colour background + { "bw006", 0x080000, 0x73a35d1f, BRF_GRA }, // 10 High colour background + { "bw00a", 0x080000, 0xf447dfc2, BRF_GRA }, // 11 High colour background + { "bw007", 0x080000, 0x97f85c87, BRF_GRA }, // 12 High colour background + { "bw00b", 0x080000, 0xb0a48225, BRF_GRA }, // 13 High colour background + + { "bw000", 0x040000, 0xd8fe869d, BRF_SND }, // 14 Samples +}; + + +STD_ROM_PICK(Berlwall) +STD_ROM_FN(Berlwall) + +static struct BurnRomInfo BerlwalltRomDesc[] = { + { "bw100a", 0x020000, 0xe6bcb4eb, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "bw101a", 0x020000, 0x38056fb2, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "bw001", 0x080000, 0xbc927260, BRF_GRA }, // 2 Sprites + { "bw002", 0x080000, 0x223f5465, BRF_GRA }, // 3 Sprites + { "bw300", 0x020000, 0xb258737a, BRF_GRA }, // 4 Sprites + + { "bw003", 0x080000, 0xfbb4b72d, BRF_GRA }, // 5 Tiles + + { "bw004", 0x080000, 0x5300c34d, BRF_GRA }, // 6 High colour background + { "bw008", 0x080000, 0x9aaf2f2f, BRF_GRA }, // 7 High colour background + { "bw005", 0x080000, 0x16db6d43, BRF_GRA }, // 8 High colour background + { "bw009", 0x080000, 0x1151a0b0, BRF_GRA }, // 9 High colour background + { "bw006", 0x080000, 0x73a35d1f, BRF_GRA }, // 10 High colour background + { "bw00a", 0x080000, 0xf447dfc2, BRF_GRA }, // 11 High colour background + { "bw007", 0x080000, 0x97f85c87, BRF_GRA }, // 12 High colour background + { "bw00b", 0x080000, 0xb0a48225, BRF_GRA }, // 13 High colour background + + { "bw000", 0x040000, 0xd8fe869d, BRF_SND }, // 14 Samples +}; + + +STD_ROM_PICK(Berlwallt) +STD_ROM_FN(Berlwallt) + +static struct BurnRomInfo BlazeonRomDesc[] = { + { "bz_prg1.u80", 0x040000, 0x8409e31d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "bz_prg2.u81", 0x040000, 0xb8a0a08b, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "bz_sp1.u20", 0x100000, 0x0d5809a1, BRF_GRA }, // 2 Sprites + { "bz_sp2.u21", 0x100000, 0x56ead2bd, BRF_GRA }, // 3 Sprites + + { "bz_bg.u2", 0x100000, 0xfc67f19f, BRF_GRA }, // 4 Tiles + + { "3.u45", 0x020000, 0x52fe4c94, BRF_ESS | BRF_PRG }, // 5 Z80 Program Code +}; + + +STD_ROM_PICK(Blazeon) +STD_ROM_FN(Blazeon) + +static struct BurnRomInfo BloodwarRomDesc[] = { + { "ofp0f3.514", 0x080000, 0x0c93da15, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ofp1f3.513", 0x080000, 0x894ecbe5, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ofd0x3.124", 0x020000, 0x399f2005, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "of-200-0201.8", 0x200000, 0xbba63025, BRF_GRA }, // 3 Sprites + { "of-201-0202.9", 0x200000, 0x4ffd9ddc, BRF_GRA }, // 4 Sprites + { "of-202-0203.10", 0x200000, 0xfbcc5363, BRF_GRA }, // 5 Sprites + { "of-203-0204.11", 0x200000, 0x8e818ce9, BRF_GRA }, // 6 Sprites + { "of-204-0205.12", 0x200000, 0x70c4a76b, BRF_GRA }, // 7 Sprites + { "of-205-0206.13", 0x200000, 0x80c667bb, BRF_GRA }, // 8 Sprites + { "of-206-0207.14", 0x200000, 0xc2028c97, BRF_GRA }, // 9 Sprites + { "of-207-0208.15", 0x200000, 0xb1f30c61, BRF_GRA }, // 10 Sprites + { "of-208-0209.28", 0x200000, 0xa8f29545, BRF_GRA }, // 11 Sprites + { "of-209e-0210.16", 0x100000, 0x93018468, BRF_GRA }, // 12 Sprites + { "of-2090-2011.17", 0x100000, 0x3fb226a1, BRF_GRA }, // 13 Sprites + { "of-210e-0212.18", 0x100000, 0x80f3fa1b, BRF_GRA }, // 14 Sprites + { "of-2100-0213.19", 0x100000, 0x8ca3a3d6, BRF_GRA }, // 15 Sprites + { "of-211e-0214.20", 0x100000, 0x8d3d96f7, BRF_GRA }, // 16 Sprites + { "of-2110-0215.21", 0x100000, 0x78268230, BRF_GRA }, // 17 Sprites + { "of-212e-0216.22", 0x100000, 0x5a013d99, BRF_GRA }, // 18 Sprites + { "of-2120-0217.23", 0x100000, 0x84ed25bd, BRF_GRA }, // 19 Sprites + { "of-213e-0218.24", 0x100000, 0x861bc5b1, BRF_GRA }, // 20 Sprites + { "of-2130-0219.25", 0x100000, 0xa79b8119, BRF_GRA }, // 21 Sprites + { "of-214e-0220.26", 0x100000, 0x43c622de, BRF_GRA }, // 22 Sprites + { "of-2140-0221.27", 0x100000, 0xd10bf03c, BRF_GRA }, // 23 Sprites + + { "of-300-0225.51", 0x100000, 0xfbc3c08a, BRF_GRA }, // 24 Tiles + { "of-301-0226.55", 0x100000, 0xfcf215de, BRF_GRA }, // 25 Tiles (Layers 2 & 3) + + { "of-101-f-0223.101", 0x100000, 0x295f3c93, BRF_SND }, // 26 Samples + { "of-100-0222.99", 0x100000, 0x42b12269, BRF_SND }, // 27 Samples +}; + + +STD_ROM_PICK(Bloodwar) +STD_ROM_FN(Bloodwar) + +static struct BurnRomInfo BonkadvRomDesc[] = { + { "prg.8", 0x080000, 0xaf2e60f8, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "prg.7", 0x080000, 0xa1cc6a78, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mcu.124", 0x020000, 0x9d4e2724, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "pc100101.37", 0x200000, 0xc96e7c10, BRF_GRA }, // 3 Sprites + { "pc200102.40", 0x100000, 0xc2b7a26a, BRF_GRA }, // 4 Sprites + { "pc300103.38", 0x100000, 0x51ee162c, BRF_GRA }, // 5 Sprites + { "pc600106.42", 0x080000, 0x25877026, BRF_GRA }, // 6 Sprites + { "pc700107.43", 0x080000, 0xbfe21c44, BRF_GRA }, // 7 Sprites + + { "pc400104.51", 0x100000, 0x3b176f84, BRF_GRA }, // 8 Tiles + { "pc500105.55", 0x100000, 0xbebb3edc, BRF_GRA }, // 9 Tiles (Layers 2 & 3) + + { "pc604109.101", 0x100000, 0x76025530, BRF_SND }, // 10 Samples + { "pc601106.99", 0x100000, 0xa893651c, BRF_SND }, // 11 Samples + { "pc602107.100", 0x100000, 0x0fbb23aa, BRF_SND }, // 12 Samples + { "pc603108.102", 0x100000, 0x58458985, BRF_SND }, // 13 Samples +}; + + +STD_ROM_PICK(Bonkadv) +STD_ROM_FN(Bonkadv) + +static struct BurnRomInfo ExplbrkrRomDesc[] = { + { "ts100e.u18", 0x040000, 0xcc84a985, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ts101e.u19", 0x040000, 0x88f4afb7, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ts001e.u37", 0x080000, 0x70b66e7e, BRF_GRA }, // 2 Sprites + { "ts000e.u38", 0x080000, 0xa7a94143, BRF_GRA }, // 3 Sprites + { "ts002e.u36", 0x040000, 0x611271e6, BRF_GRA }, // 4 Sprites + + { "ts010.u4", 0x100000, 0xdf935324, BRF_GRA }, // 5 Tiles + { "ts020.u33", 0x100000, 0xeb58c35d, BRF_GRA }, // 6 Tiles (Layers 2 & 3) + + { "ts030.u5", 0x100000, 0x1d68e9d1, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Explbrkr) +STD_ROM_FN(Explbrkr) + +static struct BurnRomInfo BakubrkrRomDesc[] = { + { "ts100j.u18", 0x040000, 0x8cc0a4fd, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ts101j.u19", 0x040000, 0xaea92195, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "ts001j.u37", 0x080000, 0x70b66e7e, BRF_GRA }, // 2 Sprites + { "ts000j.u38", 0x080000, 0xa7a94143, BRF_GRA }, // 3 Sprites + { "ts002j.u36", 0x040000, 0x611271e6, BRF_GRA }, // 4 Sprites + + { "ts010.u4", 0x100000, 0xdf935324, BRF_GRA }, // 5 Tiles + { "ts020.u33", 0x100000, 0xeb58c35d, BRF_GRA }, // 6 Tiles (Layers 2 & 3) + + { "ts030.u5", 0x100000, 0x1d68e9d1, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Bakubrkr) +STD_ROM_FN(Bakubrkr) + +static struct BurnRomInfo GtmrRomDesc[] = { + { "u2.bin", 0x080000, 0x031799f7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u1.bin", 0x080000, 0x6238790a, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mmd0x2.u124.bin", 0x020000, 0x3d7cb329, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "mm-200-402-s0.bin", 0x200000, 0xc0ab3efc, BRF_GRA }, // 3 Sprites + { "mm-201-403-s1.bin", 0x200000, 0xcf6b23dc, BRF_GRA }, // 4 Sprites + { "mm-202-404-s2.bin", 0x200000, 0x8f27f5d3, BRF_GRA }, // 5 Sprites + { "mm-203-405-s3.bin", 0x080000, 0xe9747c8c, BRF_GRA }, // 6 Sprites + { "mms1x2.u30.bin", 0x020000, 0xb42b426f, BRF_GRA }, // 7 Sprites + { "mms0x2.u29.bin", 0x020000, 0xbd22b7d2, BRF_GRA }, // 8 Sprites + + { "mm-300-406-a0.bin", 0x200000, 0xb15f6b7f, BRF_GRA }, // 9 Tiles + + { "mm-100-401-e0.bin", 0x100000, 0xb9cbfbee, BRF_SND }, // 10 Samples +}; + + +STD_ROM_PICK(Gtmr) +STD_ROM_FN(Gtmr) + +static struct BurnRomInfo GtmraRomDesc[] = { + { "mmp0x2.u514.bin", 0x080000, 0xba4a77c8, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mmp1x2.u513.bin", 0x080000, 0xa2b9034e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mmd0x2.u124.bin", 0x020000, 0x3d7cb329, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "mm-200-402-s0.bin", 0x200000, 0xc0ab3efc, BRF_GRA }, // 3 Sprites + { "mm-201-403-s1.bin", 0x200000, 0xcf6b23dc, BRF_GRA }, // 4 Sprites + { "mm-202-404-s2.bin", 0x200000, 0x8f27f5d3, BRF_GRA }, // 5 Sprites + { "mm-203-405-s3.bin", 0x080000, 0xe9747c8c, BRF_GRA }, // 6 Sprites + { "mms1x2.u30.bin", 0x020000, 0xb42b426f, BRF_GRA }, // 7 Sprites + { "mms0x2.u29.bin", 0x020000, 0xbd22b7d2, BRF_GRA }, // 8 Sprites + + { "mm-300-406-a0.bin", 0x200000, 0xb15f6b7f, BRF_GRA }, // 9 Tiles + + { "mm-100-401-e0.bin", 0x100000, 0xb9cbfbee, BRF_SND }, // 10 Samples +}; + + +STD_ROM_PICK(Gtmra) +STD_ROM_FN(Gtmra) + +static struct BurnRomInfo GtmreRomDesc[] = { + { "gmmu2.bin", 0x080000, 0x36dc4aa9, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gmmu1.bin", 0x080000, 0x8653c144, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gtmrusa.u12", 0x020000, 0x2e1a06ff, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "gmmu27.bin", 0x200000, 0xc0ab3efc, BRF_GRA }, // 3 Sprites + { "gmmu28.bin", 0x200000, 0xcf6b23dc, BRF_GRA }, // 4 Sprites + { "gmmu29.bin", 0x200000, 0x8f27f5d3, BRF_GRA }, // 5 Sprites + { "gmmu30.bin", 0x080000, 0xe9747c8c, BRF_GRA }, // 6 Sprites + { "gmmu64.bin", 0x100000, 0x57d77b33, BRF_GRA }, // 7 Sprites + { "gmmu65.bin", 0x100000, 0x05b8bdca, BRF_GRA }, // 8 Sprites + + { "gmmu52.bin", 0x200000, 0xb15f6b7f, BRF_GRA }, // 9 Tiles + + { "gmmu23.bin", 0x100000, 0xb9cbfbee, BRF_SND }, // 10 Samples + { "gmmu24.bin", 0x100000, 0x380cdc7c, BRF_SND }, // 11 Samples +}; + + +STD_ROM_PICK(Gtmre) +STD_ROM_FN(Gtmre) + +static struct BurnRomInfo GtmrusaRomDesc[] = { + { "gtmrusa.u2", 0x080000, 0x5be615c4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gtmrusa.u1", 0x080000, 0xae853e4e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gtmrusa.u12", 0x020000, 0x2e1a06ff, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "gmmu27.bin", 0x200000, 0xc0ab3efc, BRF_GRA }, // 3 Sprites + { "gmmu28.bin", 0x200000, 0xcf6b23dc, BRF_GRA }, // 4 Sprites + { "gmmu29.bin", 0x200000, 0x8f27f5d3, BRF_GRA }, // 5 Sprites + { "gmmu30.bin", 0x080000, 0xe9747c8c, BRF_GRA }, // 6 Sprites + { "gmmu64.bin", 0x100000, 0x57d77b33, BRF_GRA }, // 7 Sprites + { "gmmu65.bin", 0x100000, 0x05b8bdca, BRF_GRA }, // 8 Sprites + + { "gmmu52.bin", 0x200000, 0xb15f6b7f, BRF_GRA }, // 9 Tiles + + { "gmmu23.bin", 0x100000, 0xb9cbfbee, BRF_SND }, // 10 Samples + { "gmmu24.bin", 0x100000, 0x380cdc7c, BRF_SND }, // 11 Samples +}; + + +STD_ROM_PICK(Gtmrusa) +STD_ROM_FN(Gtmrusa) + +static struct BurnRomInfo Gtmr2RomDesc[] = { + { "m2p0x1a.u8", 0x080000, 0xc29039fb, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "m2p1x1a.u7", 0x080000, 0x8ef392c4, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "m2d0x0.u31", 0x020000, 0x2e1a06ff, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "m2-200-0.u49", 0x400000, 0x93aafc53, BRF_GRA }, // 3 Sprites + { "m2-201-0.u50", 0x200000, 0x39b60a83, BRF_GRA }, // 4 Sprites + { "m2-202-0.u51", 0x200000, 0xfd06b339, BRF_GRA }, // 5 Sprites + { "m2s0x1a.u32", 0x080000, 0xa485eec6, BRF_GRA }, // 6 Sprites + { "m2s1x1a.u33", 0x080000, 0xc5b71bb2, BRF_GRA }, // 7 Sprites + + { "m2-300-0.u89", 0x200000, 0x4dc42fbb, BRF_GRA }, // 8 Tiles + { "m2-301-0.u90", 0x200000, 0xf4e894f2, BRF_GRA }, // 9 Tiles + { "m2b0x0.u93", 0x020000, 0xe023d51b, BRF_GRA }, // 10 Tiles + { "m2b1x0.u94", 0x020000, 0x03c48bdb, BRF_GRA }, // 11 Tiles + + { "m2-100-0.u48", 0x100000, 0x5250fa45, BRF_SND }, // 12 Samples + { "m2w1x0.u47", 0x040000, 0x1b0513c5, BRF_SND }, // 13 Samples +}; + + +STD_ROM_PICK(Gtmr2) +STD_ROM_FN(Gtmr2) + +static struct BurnRomInfo Gtmr2aRomDesc[] = { + { "m2p0x1.u8", 0x080000, 0x525f6618, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "m2p1x1.u7", 0x080000, 0x914683e5, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "m2d0x0.u31", 0x020000, 0x2e1a06ff, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "m2-200-0.u49", 0x400000, 0x93aafc53, BRF_GRA }, // 3 Sprites + { "m2-201-0.u50", 0x200000, 0x39b60a83, BRF_GRA }, // 4 Sprites + { "m2-202-0.u51", 0x200000, 0xfd06b339, BRF_GRA }, // 5 Sprites + { "m2s0x1.u32", 0x080000, 0x4069d6c7, BRF_GRA }, // 6 Sprites + { "m2s1x1.u33", 0x080000, 0xc53fe269, BRF_GRA }, // 7 Sprites + + { "m2-300-0.u89", 0x200000, 0x4dc42fbb, BRF_GRA }, // 8 Tiles + { "m2-301-0.u90", 0x200000, 0xf4e894f2, BRF_GRA }, // 9 Tiles + { "m2b0x0.u93", 0x020000, 0xe023d51b, BRF_GRA }, // 10 Tiles + { "m2b1x0.u94", 0x020000, 0x03c48bdb, BRF_GRA }, // 11 Tiles + + { "m2-100-0.u48", 0x100000, 0x5250fa45, BRF_SND }, // 12 Samples + { "m2w1x0.u47", 0x040000, 0x1b0513c5, BRF_SND }, // 13 Samples +}; + + +STD_ROM_PICK(Gtmr2a) +STD_ROM_FN(Gtmr2a) + +static struct BurnRomInfo Gtmr2uRomDesc[] = { + { "m2p0a1.u8", 0x080000, 0x813e1d5e, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "m2p1a1.u7", 0x080000, 0xbee63666, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "m2d0x0.u31", 0x020000, 0x2e1a06ff, BRF_PRG | BRF_OPT }, // 2 MCU Code + + { "m2-200-0.u49", 0x400000, 0x93aafc53, BRF_GRA }, // 3 Sprites + { "m2-201-0.u50", 0x200000, 0x39b60a83, BRF_GRA }, // 4 Sprites + { "m2-202-0.u51", 0x200000, 0xfd06b339, BRF_GRA }, // 5 Sprites + { "m2s0a1.u32", 0x080000, 0x98977171, BRF_GRA }, // 6 Sprites + { "m2s1a1.u33", 0x080000, 0xc69a732e, BRF_GRA }, // 7 Sprites + + { "m2-300-0.u89", 0x200000, 0x4dc42fbb, BRF_GRA }, // 8 Tiles + { "m2-301-0.u90", 0x200000, 0xf4e894f2, BRF_GRA }, // 9 Tiles + { "m2b0x0.u93", 0x020000, 0xe023d51b, BRF_GRA }, // 10 Tiles + { "m2b1x0.u94", 0x020000, 0x03c48bdb, BRF_GRA }, // 11 Tiles + + { "m2-100-0.u48", 0x100000, 0x5250fa45, BRF_SND }, // 12 Samples + { "m2w1a1.u47", 0x080000, 0x15f25342, BRF_SND }, // 13 Samples +}; + + +STD_ROM_PICK(Gtmr2u) +STD_ROM_FN(Gtmr2u) + +static struct BurnRomInfo MgcrystlRomDesc[] = { + { "mc100e02.u18", 0x020000, 0x246a1335, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mc101e02.u19", 0x040000, 0x708ea1dc, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mc000.u38", 0x100000, 0x28acf6f4, BRF_GRA }, // 2 Sprites + { "mc001.u37", 0x080000, 0x005bc43d, BRF_GRA }, // 3 Sprites + { "mc002e02.u36", 0x020000, 0x27ac1056, BRF_GRA }, // 4 Sprites + + { "mc010.u04", 0x100000, 0x85072772, BRF_GRA }, // 5 Tiles + { "mc020.u34", 0x100000, 0x1ea92ff1, BRF_GRA }, // 6 Tiles (Layers 2 & 3) + + { "mc030.u32", 0x040000, 0xc165962e, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Mgcrystl) +STD_ROM_FN(Mgcrystl) + +static struct BurnRomInfo MgcrystloRomDesc[] = { + { "mc100h00.u18", 0x020000, 0xc7456ba7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mc101h00.u19", 0x040000, 0xea8f9300, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mc000.u38", 0x100000, 0x28acf6f4, BRF_GRA }, // 2 Sprites + { "mc001.u37", 0x080000, 0x005bc43d, BRF_GRA }, // 3 Sprites + { "mc002h00.u36", 0x020000, 0x22729037, BRF_GRA }, // 4 Sprites + + { "mc010.u04", 0x100000, 0x85072772, BRF_GRA }, // 5 Tiles + { "mc020.u34", 0x100000, 0x1ea92ff1, BRF_GRA }, // 6 Tiles (Layers 2 & 3) + + { "mc030.u32", 0x040000, 0xc165962e, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Mgcrystlo) +STD_ROM_FN(Mgcrystlo) + +static struct BurnRomInfo MgcrystljRomDesc[] = { + { "mc100j02.u18", 0x020000, 0xafe5882d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mc101j02.u19", 0x040000, 0x60da5492, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "mc000.u38", 0x100000, 0x28acf6f4, BRF_GRA }, // 2 Sprites + { "mc001.u37", 0x080000, 0x005bc43d, BRF_GRA }, // 3 Sprites + { "mc002e02.u36", 0x020000, 0x27ac1056, BRF_GRA }, // 4 Sprites + + { "mc010.u04", 0x100000, 0x85072772, BRF_GRA }, // 5 Tiles + { "mc020.u34", 0x100000, 0x1ea92ff1, BRF_GRA }, // 6 Tiles (Layers 2 & 3) + + { "mc030.u32", 0x040000, 0xc165962e, BRF_SND }, // 7 Samples +}; + + +STD_ROM_PICK(Mgcrystlj) +STD_ROM_FN(Mgcrystlj) + +/*============================================================================================== +Graphics Decoding +===============================================================================================*/ + +static void Kaneko16DecodeBg15Bitmaps() +{ + INT32 sx, x, y; + + for (sx = 0; sx < 32; sx++) { + for (x = 0; x < 256; x++) { + for (y = 0; y < 256; y++) { + INT32 addr = (sx * 256 * 256) + (y * 256) + x; + INT32 data = (Kaneko16TempGfx[addr * 2 + 0] * 256) + Kaneko16TempGfx[addr * 2 + 1]; + INT32 r, g, b; + + r = (data & 0x07c0) >> 6; + g = (data & 0xf800) >> 11; + b = (data & 0x003e) >> 1; + + r ^= 0x09; + + if (~g & 0x08) g ^= 0x010; + g = (g - 1) & 0x1f; + + b ^= 0x03; + if (~b & 0x08) b ^= 0x10; + b = (b + 2) & 0x1f; + + if ((r & 0x10) && (b & 0x10)) g = (g - 1) & 0x1f; + + Kaneko16Bg15Data[addr] = 2048 + ((g << 10) | (r << 5) | b); + } + } + } +} + +/*============================================================================================== +Unscramble Tile/Sound ROM Functions +===============================================================================================*/ + +static void UnscrambleTiles(INT32 length) +{ + UINT8 *RAM = Kaneko16TempGfx; + INT32 i; + + if (RAM == NULL) return; + + for (i = 0; i < length; i ++) + { + RAM[i] = ((RAM[i] & 0xF0)>>4) + ((RAM[i] & 0x0F)<<4); + } +} + +static void ExpandSampleBanks() +{ + INT32 bank; + + for (bank = 15; bank > 0; bank--) + { + UINT8 *src0 = MSM6295ROMData; + UINT8 *srcn = src0 + 0x10000 * (bank < 3 ? 3 : bank); + UINT8 *dst = src0 + 0x40000 * bank; + + memcpy(dst + 0x30000, srcn + 0x00000, 0x10000); + memcpy(dst + 0x00000, src0 + 0x00000, 0x30000); + } +} + +/*============================================================================================== +Allocate Memory +===============================================================================================*/ + +static INT32 GtmrMemIndex() +{ + UINT8 *Next; Next = Mem; + + Kaneko16Rom = Next; Next += 0x100000; + MSM6295ROM = Next; Next += 0x140000; + MSM6295ROMData = Next; Next += 0x400000; + MSM6295ROMData2 = Next; Next += 0x300000; + + RamStart = Next; + + Kaneko16Ram = Next; Next += 0x028000; + Kaneko16MCURam = Next; Next += 0x010000; + Kaneko16NVRam = Next; Next += 0x000100; + Kaneko16PaletteRam = Next; Next += 0x010000; + Kaneko16SpriteRam = Next; Next += Kaneko16SpriteRamSize; + Kaneko16Video0Ram = Next; Next += 0x001000; + Kaneko16Video1Ram = Next; Next += 0x001000; + Kaneko16Video2Ram = Next; Next += 0x001000; + Kaneko16Video3Ram = Next; Next += 0x001000; + Kaneko16VScrl0Ram = Next; Next += 0x001000; + Kaneko16VScrl1Ram = Next; Next += 0x001000; + Kaneko16VScrl2Ram = Next; Next += 0x001000; + Kaneko16VScrl3Ram = Next; Next += 0x001000; + + RamEnd = Next; + + Kaneko16Sprites = Next; Next += (Kaneko16NumSprites * 16 * 16); + Kaneko16Tiles = Next; Next += (Kaneko16NumTiles * 16 * 16); + LayerQueueXY[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueXY[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueuePriority[0] = Next; Next += nScreenWidth * nScreenHeight; + LayerQueuePriority[1] = Next; Next += nScreenWidth * nScreenHeight; + if (Kaneko16NumTiles2) { + Kaneko16Tiles2 = Next; Next += (Kaneko16NumTiles2 * 16 * 16); + LayerQueueXY[2] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueXY[3] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[2] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[3] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueuePriority[2] = Next; Next += nScreenWidth * nScreenHeight; + LayerQueuePriority[3] = Next; Next += nScreenWidth * nScreenHeight; + } + Kaneko16Palette = (UINT32*)Next; Next += 0x010000 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 ExplbrkrMemIndex() +{ + UINT8 *Next; Next = Mem; + + Kaneko16Rom = Next; Next += 0x080000; + MSM6295ROM = Next; Next += 0x040000; + MSM6295ROMData = Next; Next += 0x200000; + + RamStart = Next; + + Kaneko16Ram = Next; Next += 0x010000; + Kaneko16PaletteRam = Next; Next += 0x001000; + Kaneko16SpriteRam = Next; Next += Kaneko16SpriteRamSize; + Kaneko16Video0Ram = Next; Next += 0x001000; + Kaneko16Video1Ram = Next; Next += 0x001000; + Kaneko16Video2Ram = Next; Next += 0x001000; + Kaneko16Video3Ram = Next; Next += 0x001000; + Kaneko16VScrl0Ram = Next; Next += 0x001000; + Kaneko16VScrl1Ram = Next; Next += 0x001000; + Kaneko16VScrl2Ram = Next; Next += 0x001000; + Kaneko16VScrl3Ram = Next; Next += 0x001000; + + RamEnd = Next; + + Kaneko16Sprites = Next; Next += (Kaneko16NumSprites * 16 * 16); + Kaneko16Tiles = Next; Next += (Kaneko16NumTiles * 16 * 16); + LayerQueueXY[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueXY[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueuePriority[0] = Next; Next += nScreenWidth * nScreenHeight; + LayerQueuePriority[1] = Next; Next += nScreenWidth * nScreenHeight; + if (Kaneko16NumTiles2) { + Kaneko16Tiles2 = Next; Next += (Kaneko16NumTiles2 * 16 * 16); + LayerQueueXY[2] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueXY[3] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[2] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[3] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueuePriority[2] = Next; Next += nScreenWidth * nScreenHeight; + LayerQueuePriority[3] = Next; Next += nScreenWidth * nScreenHeight; + } + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + if (Kaneko16Bg15) { + Kaneko16Bg15Data = (UINT16*)Next; Next += (32 * 256 * 256) * sizeof(UINT16); // 32 bitmaps - 256 x 256 + Kaneko16Palette = (UINT32*)Next; Next += (0x001000 + 32768) * sizeof(UINT32); + } else { + Kaneko16Palette = (UINT32*)Next; Next += 0x001000 * sizeof(UINT32); + } + MemEnd = Next; + + return 0; +} + +static INT32 BlazeonMemIndex() +{ + UINT8 *Next; Next = Mem; + + Kaneko16Rom = Next; Next += 0x080000; + Kaneko16Z80Rom = Next; Next += 0x020000; + + RamStart = Next; + + Kaneko16Ram = Next; Next += 0x010000; + Kaneko16Z80Ram = Next; Next += 0x002000; + Kaneko16PaletteRam = Next; Next += 0x001000; + Kaneko16SpriteRam = Next; Next += Kaneko16SpriteRamSize; + Kaneko16Video0Ram = Next; Next += 0x001000; + Kaneko16Video1Ram = Next; Next += 0x001000; + Kaneko16VScrl0Ram = Next; Next += 0x001000; + Kaneko16VScrl1Ram = Next; Next += 0x001000; + + RamEnd = Next; + + Kaneko16Sprites = Next; Next += (Kaneko16NumSprites * 16 * 16); + Kaneko16Tiles = Next; Next += (Kaneko16NumTiles * 16 * 16); + LayerQueueXY[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueXY[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[0] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueueColour[1] = (UINT32*)Next; Next += nScreenWidth * nScreenHeight * sizeof(UINT32); + LayerQueuePriority[0] = Next; Next += nScreenWidth * nScreenHeight; + LayerQueuePriority[1] = Next; Next += nScreenWidth * nScreenHeight; + Kaneko16Palette = (UINT32*)Next; Next += 0x001000 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +/*============================================================================================== +Protection Calculator +===============================================================================================*/ + +static struct { + UINT16 x1p, y1p, x1s, y1s; + UINT16 x2p, y2p, x2s, y2s; + + INT16 x12, y12, x21, y21; + + UINT16 mult_a, mult_b; +} hit; + +INT16 calc_compute_x(void) +{ + INT16 x_coll; + + // X distance + if ((hit.x2p >= hit.x1p) && (hit.x2p < (hit.x1p + hit.x1s))) // x2p inside x1 + x_coll = (hit.x1s - (hit.x2p - hit.x1p)); + else if ((hit.x1p >= hit.x2p) && (hit.x1p < (hit.x2p + hit.x2s))) // x1p inside x2 + x_coll = (hit.x2s - (hit.x1p - hit.x2p)); + else // normal/no overlap + x_coll = ((hit.x1s + hit.x2s)/2) - abs((hit.x1p + hit.x1s/2) - (hit.x2p + hit.x2s/2)); + + return x_coll; +} +INT16 calc_compute_y(void) +{ + INT16 y_coll; + + // Y distance + if ((hit.y2p >= hit.y1p) && (hit.y2p < (hit.y1p + hit.y1s))) // y2p inside y1 + y_coll = (hit.y1s - (hit.y2p - hit.y1p)); + else if ((hit.y1p >= hit.y2p) && (hit.y1p < (hit.y2p + hit.y2s))) // y1p inside y2 + y_coll = (hit.y2s - (hit.y1p - hit.y2p)); + else // normal/no overlap + y_coll = ((hit.y1s + hit.y2s)/2) - abs((hit.y1p + hit.y1s/2) - (hit.y2p + hit.y2s/2)); + + return y_coll; +} + +static UINT16 BloodwarCalcRead(INT32 offset) +{ + UINT16 data = 0; + INT16 x_coll, y_coll; + + x_coll = calc_compute_x(); + y_coll = calc_compute_y(); + + switch (offset) + { + case 0x00/2: // X distance + return x_coll; + + case 0x02/2: // Y distance + return y_coll; + + case 0x04/2: // similar to the hit detection from SuperNova, but much simpler + + // 4th nibble: Y Absolute Collision -> possible values = 9,8,4,3,2 + if (hit.y1p > hit.y2p) data |= 0x2000; + else if (hit.y1p == hit.y2p) data |= 0x4000; + else if (hit.y1p < hit.y2p) data |= 0x8000; + if (y_coll<0) data |= 0x1000; + + // 3rd nibble: X Absolute Collision -> possible values = 9,8,4,3,2 + if (hit.x1p > hit.x2p) data |= 0x0200; + else if (hit.x1p == hit.x2p) data |= 0x0400; + else if (hit.x1p < hit.x2p) data |= 0x0800; + if (x_coll<0) data |= 0x0100; + + // 2nd nibble: always set to 4 + data |= 0x0040; + + // 1st nibble: XY Overlap Collision -> possible values = 0,2,4,f + if (x_coll>=0) data |= 0x0004; + if (y_coll>=0) data |= 0x0002; + if ((x_coll>=0)&&(y_coll>=0)) data |= 0x000F; + + return data; + + case 0x14/2: + return rand() & 0xffff; + + case 0x20/2: return hit.x1p; + case 0x22/2: return hit.x1s; + case 0x24/2: return hit.y1p; + case 0x26/2: return hit.y1s; + + case 0x2c/2: return hit.x2p; + case 0x2e/2: return hit.x2s; + case 0x30/2: return hit.y2p; + case 0x32/2: return hit.y2s; + } + + return 0; +} + +static UINT16 BonkadvCalcRead(INT32 offset) +{ + UINT16 data = 0; + + switch (offset) + { + case 0x00/2: // watchdog + return 0; + + case 0x02/2: // unknown (yet!), used by *MANY* games !!! + break; + + case 0x04/2: // similar to the hit detection from SuperNova, but much simpler + + // X Absolute Collision + if (hit.x1p > hit.x2p) data |= 0x0200; + else if (hit.x1p == hit.x2p) data |= 0x0400; + else if (hit.x1p < hit.x2p) data |= 0x0800; + + // Y Absolute Collision + if (hit.y1p > hit.y2p) data |= 0x2000; + else if (hit.y1p == hit.y2p) data |= 0x4000; + else if (hit.y1p < hit.y2p) data |= 0x8000; + + // XY Overlap Collision + hit.x12 = (hit.x1p) - (hit.x2p + hit.x2s); + hit.y12 = (hit.y1p) - (hit.y2p + hit.y2s); + hit.x21 = (hit.x1p + hit.x1s) - (hit.x2p); + hit.y21 = (hit.y1p + hit.y1s) - (hit.y2p); + + if ((hit.x12 < 0) && (hit.y12 < 0) && + (hit.x21 >= 0) && (hit.y21 >= 0)) + data |= 0x0001; + + return data; + + case 0x10/2: + return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) >> 16); + case 0x12/2: + return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) & 0xffff); + + case 0x14/2: + return rand() & 0xffff; + } + + return 0; +} + +static void BloodwarCalcWrite(INT32 offset, UINT16 data) +{ + switch (offset) { + case 0x20 >> 1: hit.x1p = data; return; + case 0x22 >> 1: hit.x1s = data; return; + case 0x24 >> 1: hit.y1p = data; return; + case 0x26 >> 1: hit.y1s = data; return; + + case 0x2c >> 1: hit.x2p = data; return; + case 0x2e >> 1: hit.x2s = data; return; + case 0x30 >> 1: hit.y2p = data; return; + case 0x32 >> 1: hit.y2s = data; return; + } +} + +static void BonkadvCalcWrite(INT32 offset, UINT16 data) +{ + switch (offset) { + case 0x00 >> 1: hit.x1p = data; return; + case 0x02 >> 1: hit.x1s = data; return; + case 0x04 >> 1: hit.y1p = data; return; + case 0x06 >> 1: hit.y1s = data; return; + case 0x08 >> 1: hit.x2p = data; return; + case 0x0a >> 1: hit.x2s = data; return; + case 0x0c >> 1: hit.y2p = data; return; + case 0x0e >> 1: hit.y2s = data; return; + case 0x10 >> 1: hit.mult_a = data; return; + case 0x12 >> 1: hit.mult_b = data; return; + } +} + +/*============================================================================================== +Toybox MCU +===============================================================================================*/ + +static void ToyboxMCUInit() +{ + memset(ToyboxMCUCom, 0, 4 * sizeof(UINT16)); +} + +static UINT16 ToyboxMCUStatusRead() +{ + return 0; +} + +#define MCU_RESPONSE(d) memcpy(&MCURam[MCUOffset], d, sizeof(d)) + +static void BloodwarMCURun() +{ + UINT16 *MCURam = (UINT16*)Kaneko16MCURam; + UINT16 *NVRam = (UINT16*)Kaneko16NVRam; + + UINT16 MCUCommand = MCURam[0x10/2]; + UINT16 MCUOffset = MCURam[0x12/2] >> 1; + UINT16 MCUData = MCURam[0x14/2]; + + switch (MCUCommand >> 8) { + case 0x02: { + memcpy(MCURam + MCUOffset, NVRam, 128); + return; + } + + case 0x03: { + MCURam[MCUOffset + 0] = 0xff00 - (Kaneko16Dip[0] << 8); + return; + } + + case 0x04: { + switch (MCUData) { + // unknown purpose data + case 0x01: MCU_RESPONSE(bloodwar_mcu_4_01); break; // Warrior 1 + case 0x02: MCU_RESPONSE(bloodwar_mcu_4_02); break; // Warrior 2 + case 0x03: MCU_RESPONSE(bloodwar_mcu_4_03); break; // Warrior 3 + case 0x04: MCU_RESPONSE(bloodwar_mcu_4_04); break; // Warrior 4 + case 0x05: MCU_RESPONSE(bloodwar_mcu_4_05); break; // Warrior 5 + case 0x06: MCU_RESPONSE(bloodwar_mcu_4_06); break; // Warrior 6 + case 0x07: MCU_RESPONSE(bloodwar_mcu_4_07); break; // Warrior 7 + case 0x08: MCU_RESPONSE(bloodwar_mcu_4_08); break; // Warrior 8 + case 0x09: MCU_RESPONSE(bloodwar_mcu_4_09); break; // Warrior 9 + + // palette data + case 0x0a: MCU_RESPONSE(bloodwar_mcu_4_0a); break; // Warrior 1 Player 1 + case 0x0b: MCU_RESPONSE(bloodwar_mcu_4_0b); break; // Warrior 1 Player 2 + case 0x0c: MCU_RESPONSE(bloodwar_mcu_4_0c); break; // Warrior 5 Player 1 + case 0x0d: MCU_RESPONSE(bloodwar_mcu_4_0d); break; // Warrior 5 Player 2 + case 0x0e: MCU_RESPONSE(bloodwar_mcu_4_0e); break; // Warrior 4 Player 2 + case 0x0f: MCU_RESPONSE(bloodwar_mcu_4_0f); break; // Warrior 4 Player 1 + case 0x10: MCU_RESPONSE(bloodwar_mcu_4_10); break; // Warrior 6 Player 1 + case 0x11: MCU_RESPONSE(bloodwar_mcu_4_11); break; // Warrior 6 Player 2 + case 0x12: MCU_RESPONSE(bloodwar_mcu_4_12); break; // Warrior 9 Player 1 + case 0x13: MCU_RESPONSE(bloodwar_mcu_4_13); break; // Warrior 9 Player 2 + case 0x14: MCU_RESPONSE(bloodwar_mcu_4_14); break; // Warrior 7 Player 1 + case 0x15: MCU_RESPONSE(bloodwar_mcu_4_15); break; // Warrior 7 Player 2 + case 0x16: MCU_RESPONSE(bloodwar_mcu_4_16); break; // Warrior 8 Player 1 + case 0x17: MCU_RESPONSE(bloodwar_mcu_4_17); break; // Warrior 8 Player 2 + case 0x18: MCU_RESPONSE(bloodwar_mcu_4_18); break; // Warrior 2 Player 2 + case 0x19: MCU_RESPONSE(bloodwar_mcu_4_19); break; // Warrior 2 Player 1 + case 0x1a: MCU_RESPONSE(bloodwar_mcu_4_1a); break; // Warrior 3 Player 1 + case 0x1b: MCU_RESPONSE(bloodwar_mcu_4_1b); break; // Warrior 3 Player 2 + + // tilemap data + case 0x1c: MCU_RESPONSE(bloodwar_mcu_4_1c); break; // Warrior 8 + case 0x1d: MCU_RESPONSE(bloodwar_mcu_4_1d); break; // Warrior 2 + case 0x1e: MCU_RESPONSE(bloodwar_mcu_4_1e); break; // Warrior 3 + case 0x1f: MCU_RESPONSE(bloodwar_mcu_4_1f); break; // Warrior 5 + case 0x20: MCU_RESPONSE(bloodwar_mcu_4_20); break; // Warrior 4 + case 0x21: MCU_RESPONSE(bloodwar_mcu_4_21); break; // Warrior 6 + case 0x22: MCU_RESPONSE(bloodwar_mcu_4_22); break; // Warrior 1 + case 0x23: MCU_RESPONSE(bloodwar_mcu_4_23); break; // Warrior 9 + case 0x24: MCU_RESPONSE(bloodwar_mcu_4_24); break; // Warrior 7 + + // fighter data: pointers to ROM data + case 0x25: MCU_RESPONSE(bloodwar_mcu_4_25); break; // Warrior 1 + case 0x26: MCU_RESPONSE(bloodwar_mcu_4_26); break; // Warrior 2 + case 0x27: MCU_RESPONSE(bloodwar_mcu_4_27); break; // Warrior 3 + case 0x28: MCU_RESPONSE(bloodwar_mcu_4_28); break; // Warrior 4 + case 0x29: MCU_RESPONSE(bloodwar_mcu_4_29); break; // Warrior 5 + case 0x2a: MCU_RESPONSE(bloodwar_mcu_4_2a); break; // Warrior 6 + case 0x2b: MCU_RESPONSE(bloodwar_mcu_4_2b); break; // Warrior 7 + case 0x2c: MCU_RESPONSE(bloodwar_mcu_4_2c); break; // Warrior 8 + case 0x2d: MCU_RESPONSE(bloodwar_mcu_4_2d); break; // Warrior 9 + } + return; + } + + case 0x42: { + memcpy(NVRam, MCURam + MCUOffset, 128); + return; + } + } +} + +static void BonkadvMCURun() +{ + UINT16 *MCURam = (UINT16*)Kaneko16MCURam; + UINT16 *NVRam = (UINT16*)Kaneko16NVRam; + + UINT16 MCUCommand = MCURam[0x10/2]; + UINT16 MCUOffset = MCURam[0x12/2] >> 1; + UINT16 MCUData = MCURam[0x14/2]; + + switch (MCUCommand >> 8) { + case 0x02: { + memcpy(MCURam + MCUOffset, NVRam, 128); + return; + } + + case 0x03: { + MCURam[MCUOffset + 0] = 0xff00 - (Kaneko16Dip[0] << 8); + return; + } + + case 0x04: { + switch (MCUData) { + // static, in this order, at boot/reset + case 0x34: MCU_RESPONSE(bonkadv_mcu_4_34); break; + case 0x30: MCU_RESPONSE(bonkadv_mcu_4_30); break; + case 0x31: MCU_RESPONSE(bonkadv_mcu_4_31); break; + case 0x32: MCU_RESPONSE(bonkadv_mcu_4_32); break; + case 0x33: MCU_RESPONSE(bonkadv_mcu_4_33); break; + + // dynamic, per-level (29), in level order + case 0x00: MCU_RESPONSE(bonkadv_mcu_4_00); break; + case 0x02: MCU_RESPONSE(bonkadv_mcu_4_02); break; + case 0x01: MCU_RESPONSE(bonkadv_mcu_4_01); break; + case 0x05: MCU_RESPONSE(bonkadv_mcu_4_05); break; + case 0x07: MCU_RESPONSE(bonkadv_mcu_4_07); break; + case 0x06: MCU_RESPONSE(bonkadv_mcu_4_06); break; + case 0x09: MCU_RESPONSE(bonkadv_mcu_4_09); break; + case 0x0D: MCU_RESPONSE(bonkadv_mcu_4_0D); break; + case 0x03: MCU_RESPONSE(bonkadv_mcu_4_03); break; + case 0x08: MCU_RESPONSE(bonkadv_mcu_4_08); break; + case 0x04: MCU_RESPONSE(bonkadv_mcu_4_04); break; + case 0x0C: MCU_RESPONSE(bonkadv_mcu_4_0C); break; + case 0x0A: MCU_RESPONSE(bonkadv_mcu_4_0A); break; + case 0x0B: MCU_RESPONSE(bonkadv_mcu_4_0B); break; + case 0x10: MCU_RESPONSE(bonkadv_mcu_4_10); break; + case 0x0E: MCU_RESPONSE(bonkadv_mcu_4_0E); break; + case 0x13: MCU_RESPONSE(bonkadv_mcu_4_13); break; + case 0x0F: MCU_RESPONSE(bonkadv_mcu_4_0F); break; + case 0x11: MCU_RESPONSE(bonkadv_mcu_4_11); break; + case 0x14: MCU_RESPONSE(bonkadv_mcu_4_14); break; + case 0x12: MCU_RESPONSE(bonkadv_mcu_4_12); break; + case 0x17: MCU_RESPONSE(bonkadv_mcu_4_17); break; + case 0x1A: MCU_RESPONSE(bonkadv_mcu_4_1A); break; + case 0x15: MCU_RESPONSE(bonkadv_mcu_4_15); break; + case 0x18: MCU_RESPONSE(bonkadv_mcu_4_18); break; + case 0x16: MCU_RESPONSE(bonkadv_mcu_4_16); break; + case 0x19: MCU_RESPONSE(bonkadv_mcu_4_19); break; + case 0x1B: MCU_RESPONSE(bonkadv_mcu_4_1B); break; + case 0x1C: MCU_RESPONSE(bonkadv_mcu_4_1C); break; + } + return; + } + + case 0x42: { + memcpy(NVRam, MCURam + MCUOffset, 128); + return; + } + + case 0x43: { + // Reset defaults + memcpy(NVRam, bonkadv_mcu_43, sizeof(bonkadv_mcu_43)); + return; + } + } +} + +#undef MCU_RESPONSE + +static void GtmrMCURun() +{ + UINT16 *MCURam = (UINT16*)Kaneko16MCURam; + UINT16 *NVRam = (UINT16*)Kaneko16NVRam; + + UINT16 MCUCommand = MCURam[0x10/2]; + UINT16 MCUOffset = MCURam[0x12/2] >> 1; + + switch (MCUCommand >> 8) { + case 0x02: { + memcpy(MCURam + MCUOffset, NVRam, 128); + return; + } + + case 0x03: { + MCURam[MCUOffset + 0] = 0xff00 - (Kaneko16Dip[0] << 8); + return; + } + + case 0x04: { + /* MCU writes the string "MM0525-TOYBOX199" to shared ram */ + MCURam[MCUOffset + 0] = 0x4d4d; + MCURam[MCUOffset + 1] = 0x3035; + MCURam[MCUOffset + 2] = 0x3235; + MCURam[MCUOffset + 3] = 0x2d54; + MCURam[MCUOffset + 4] = 0x4f59; + MCURam[MCUOffset + 5] = 0x424f; + MCURam[MCUOffset + 6] = 0x5831; + MCURam[MCUOffset + 7] = 0x3939; + return; + } + + case 0x42: { + memcpy(NVRam, MCURam + MCUOffset, 128); + return; + } + } +} + +static void GtmrevoMCURun() +{ + UINT16 *MCURam = (UINT16*)Kaneko16MCURam; + UINT16 *NVRam = (UINT16*)Kaneko16NVRam; + + UINT16 MCUCommand = MCURam[0x10/2]; + UINT16 MCUOffset = MCURam[0x12/2] >> 1; + + switch (MCUCommand >> 8) { + case 0x02: { + memcpy(MCURam + MCUOffset, NVRam, 128); + return; + } + + case 0x03: { + MCURam[MCUOffset + 0] = 0xff00 - (Kaneko16Dip[0] << 8); + return; + } + + case 0x04: { + /* MCU writes the string "USMM0713-TB1994 " to shared ram */ + MCURam[MCUOffset + 0] = 0x5553; + MCURam[MCUOffset + 1] = 0x4d4d; + MCURam[MCUOffset + 2] = 0x3037; + MCURam[MCUOffset + 3] = 0x3133; + MCURam[MCUOffset + 4] = 0x2d54; + MCURam[MCUOffset + 5] = 0x4231; + MCURam[MCUOffset + 6] = 0x3939; + MCURam[MCUOffset + 7] = 0x3420; + return; + } + + case 0x42: { + memcpy(NVRam, MCURam + MCUOffset, 128); + return; + } + } +} + +static void ToyboxMCUComWrite(INT32 which, UINT16 data) +{ + ToyboxMCUCom[which] = data; + if (ToyboxMCUCom[0] != 0xffff) return; + if (ToyboxMCUCom[1] != 0xffff) return; + if (ToyboxMCUCom[2] != 0xffff) return; + if (ToyboxMCUCom[3] != 0xffff) return; + + memset(ToyboxMCUCom, 0, 4 * sizeof(UINT16)); + ToyboxMCURun(); +} + +/*============================================================================================== +Reset Functions +===============================================================================================*/ + +static INT32 Kaneko16DoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + Kaneko16SpriteFlipX = 0; + Kaneko16SpriteFlipY = 0; + Kaneko16DisplayEnable = 0; + memset(Kaneko16SpriteRegs, 0, 0x20 * sizeof(UINT16)); + memset(Kaneko16Layer0Regs, 0, 0x10 * sizeof(UINT16)); + memset(Kaneko16Layer1Regs, 0, 0x10 * sizeof(UINT16)); + + return 0; +} + +static INT32 BerlwallDoReset() +{ + INT32 nRet = Kaneko16DoReset(); + + for (INT32 i = 0; i < 2; i++) { + AY8910Reset(i); + } + + MSM6295Reset(0); + MSM6295Bank0 = 0; + + Kaneko16Bg15Reg = 0; + Kaneko16Bg15Select = 0; + + return nRet; +} + +static INT32 BlazeonDoReset() +{ + INT32 nRet = Kaneko16DoReset(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + Kaneko16SoundLatch = 0; + + return nRet; +} + +static INT32 ExplbrkrDoReset() +{ + INT32 nRet = Kaneko16DoReset(); + + for (INT32 i = 0; i < 2; i++) { + AY8910Reset(i); + } + + EEPROMReset(); + + MSM6295Reset(0); + MSM6295Bank0 = 0; + + return nRet; +} + +static INT32 GtmrDoReset() +{ + INT32 nRet = Kaneko16DoReset(); + + MSM6295Reset(0); + MSM6295Reset(1); + MSM6295Bank0 = 0; + MSM6295Bank1 = 0; + + ToyboxMCUInit(); + + return nRet; +} + +/*============================================================================================== +Memory Handlers +===============================================================================================*/ + +UINT8 __fastcall BerlwallReadByte(UINT32 a) +{ + switch (a) { + case 0x680000: { + return 0xff - Kaneko16Input[0]; + } + + case 0x680002: { + return 0xff - Kaneko16Input[1]; + } + + case 0x680004: { + return 0xff - Kaneko16Input[2]; + } + + case 0x800001: { + AY8910Write(0, 0, (a - 0x800000) >> 1); + return AY8910Read(0); + } + + case 0x800401: { + return MSM6295ReadStatus(0); + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall BerlwallWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x700000: { + // Coin lockout + return; + } + + case 0x800010: + case 0x800012: + case 0x800014: { + AY8910Write(0, 0, (a - 0x800000) >> 1); + AY8910Write(0, 1, d & 0xff); + return; + } + + case 0x800210: + case 0x800212: + case 0x800214: { + AY8910Write(1, 0, (a - 0x800200) >> 1); + AY8910Write(1, 1, d & 0xff); + return; + } + + + case 0x800401: { + MSM6295Command(0, d & 0xff); + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); +// } + } +} + +UINT16 __fastcall BerlwallReadWord(UINT32 a) +{ + switch (a) { + case 0x780000: { + // watchdog reset + return 0; + } + + case 0x80000e: + case 0x80001c: + case 0x80001e: { + AY8910Write(0, 0, (a - 0x800000) >> 1); + return AY8910Read(0); + } + + case 0x80020e: { + AY8910Write(1, 0, (a - 0x800200) >> 1); + return AY8910Read(1); + } + + case 0x8003fe: { + // NOP + return 0; + } + + case 0x800400: { + return MSM6295ReadStatus(0); + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall BerlwallWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x480000: { + // ?? + return; + } + + case 0x500000: { + Kaneko16Bg15Reg = d; + return; + } + + case 0x580000: { + Kaneko16Bg15Select = d; + return; + } + + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: + case 0x800008: + case 0x80000a: + case 0x80000c: + case 0x80000e: + case 0x800010: + case 0x800012: + case 0x800014: + case 0x800016: + case 0x800018: + case 0x80001a: { + AY8910Write(0, 0, (a - 0x800000) >> 1); + AY8910Write(0, 1, d & 0xff); + return; + } + + case 0x800200: + case 0x800202: + case 0x800204: + case 0x800206: + case 0x800208: + case 0x80020a: + case 0x80020c: + case 0x80020e: + case 0x800210: + case 0x800212: + case 0x800214: + case 0x800216: + case 0x800218: + case 0x80021a: { + AY8910Write(1, 0, (a - 0x800200) >> 1); + AY8910Write(1, 1, d & 0xff); + return; + } + + case 0x8003fe: { + // NOP + return; + } + + case 0x800400: { + MSM6295Command(0, d & 0xff); + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); +// } + } +} + +UINT8 __fastcall BlazeonReadByte(UINT32 a) +{ + switch (a) { + case 0xc00000: { + return 0xff - Kaneko16Input[0]; + } + + case 0xc00001: { + return Kaneko16Dip[0]; + } + + case 0xc00002: { + return 0xff - Kaneko16Input[1]; + } + + case 0xc00003: { + return Kaneko16Dip[1]; + } + + case 0xc00006: { + return 0xff - Kaneko16Input[2]; + } + + case 0xc00007: { + return 0xff; + } + + case 0xec0000: { + // NOP + return 0; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall BlazeonWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xd00000: { + // Coin lockout + return; + } + + case 0xe00000: { + Kaneko16SoundLatch = d; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); +// } + } +} + +UINT16 __fastcall BlazeonReadWord(UINT32 a) +{ + switch (a) { + case 0xc00000: { + SEK_DEF_READ_WORD(0, a); + return 0; + } + + case 0xc00002: { + SEK_DEF_READ_WORD(0, a); + return 0; + } + + case 0xc00004: { + return 0xffff; + } + + case 0xc00006: { + SEK_DEF_READ_WORD(0, a); + return 0; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall BlazeonWriteWord(UINT32 a, UINT16 /*d*/) +{ + switch (a) { + case 0xd00000: { + // Coin lockout + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); +// } + } +} + +UINT8 __fastcall ExplbrkrReadByte(UINT32 a) +{ + switch (a) { + case 0x400001: { + AY8910Write(0, 0, (a - 0x400000) >> 1); + return AY8910Read(0); + } + + case 0x40021d: { + AY8910Write(1, 0, (a - 0x400200) >> 1); + return AY8910Read(1); + } + + case 0x400401: { + return MSM6295ReadStatus(0); + } + + case 0xe00000: { + return 0xff - Kaneko16Input[0]; + } + + case 0xe00001: { + return Kaneko16Dip[0]; + } + + case 0xe00002: { + return 0xff - Kaneko16Input[1]; + } + + case 0xe00004: { + return 0xff - Kaneko16Input[2]; + } + + case 0xe00006: { + return 0xff; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall ExplbrkrWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x40000f: + case 0x400010: + case 0x400012: + case 0x400014: { + AY8910Write(0, 0, (a - 0x400000) >> 1); + AY8910Write(0, 1, d & 0xff); + return; + } + + case 0x40020f: + case 0x400210: + case 0x400212: + case 0x400214: + case 0x40021f: { + AY8910Write(1, 0, (a - 0x400200) >> 1); + AY8910Write(1, 1, d & 0xff); + return; + } + + case 0x400401: { + MSM6295Command(0, d & 0xff); + return; + } + + case 0xd00000: return; + + case 0xd00001: { + EEPROMWriteBit(d & 0x02); + EEPROMSetClockLine((d & 0x01) ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE ); + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); +// } + } +} + +UINT16 __fastcall ExplbrkrReadWord(UINT32 a) +{ + switch (a) { + case 0xa00000: { + // Magical crystals Watchdog reset + return 0; + } + + case 0xa80000: { + // Watchdog reset + return 0; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall ExplbrkrWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x400000: + case 0x400002: + case 0x400004: + case 0x400006: + case 0x400008: + case 0x40000a: + case 0x40000c: + case 0x40000e: + case 0x400010: + case 0x400012: + case 0x400014: + case 0x400016: + case 0x400018: + case 0x40001a: + case 0x40001c: { + AY8910Write(0, 0, (a - 0x400000) >> 1); + AY8910Write(0, 1, d & 0xff); + return; + } + + case 0x40001e: { + if (Mgcrystl) { + AY8910Write(0, 0, (a - 0x400000) >> 1); + AY8910Write(0, 1, d & 0xff); + } else { + MSM6295Bank0 = d & 7; + memcpy(MSM6295ROM + 0x0000000, MSM6295ROMData + (0x40000 * (d & 7)), 0x40000); + } + return; + } + + case 0x400200: + case 0x400202: + case 0x400204: + case 0x400206: + case 0x400208: + case 0x40020a: + case 0x40020c: + case 0x40020e: + case 0x400210: + case 0x400212: + case 0x400214: + case 0x400216: + case 0x400218: + case 0x40021a: + case 0x40021c: + case 0x40021e: { + AY8910Write(1, 0, (a - 0x400200) >> 1); + AY8910Write(1, 1, d & 0xff); + return; + } + + case 0x900000: { + Kaneko16SpriteRegs[0] = d; + if (d & 0xff) { + Kaneko16SpriteFlipX = d & 2; + Kaneko16SpriteFlipY = d & 1; + } + return; + } + + case 0xd00000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); +// } + } +} + +UINT8 __fastcall MgcrystlReadByte(UINT32 a) +{ + switch (a) { + case 0x400001: { + AY8910Write(0, 0, (a - 0x400000) >> 1); + return AY8910Read(0); + } + + case 0x40021d: { + AY8910Write(1, 0, (a - 0x400200) >> 1); + return AY8910Read(1); + } + + case 0x400401: { + return MSM6295ReadStatus(0); + } + + case 0xc00000: { + return 0xff - Kaneko16Input[0]; + } + + case 0xc00001: { + return Kaneko16Dip[0]; + } + + case 0xc00002: { + return 0x3f - Kaneko16Input[1]; + } + + case 0xc00004: { + return 0xff - Kaneko16Input[2]; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); +// } + } + + return 0; +} + +UINT8 __fastcall GtmrReadByte(UINT32 a) +{ + switch (a) { + case 0x900014: { + if (Gtmr) return rand() & 0xff; + return 0; + } + + case 0x900015: { + if (Bonkadv) return BonkadvCalcRead((a - 0x900000) >> 1); + return 0; + } + + case 0xb00000: { + return 0xff - Kaneko16Input[0]; + } + + case 0xb00002: { + return 0xff - Kaneko16Input[1]; + } + + case 0xb00004: { + return 0xff - Kaneko16Input[2]; + } + + case 0xb00006: { + return 0xff - Kaneko16Input[3]; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read byte -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall GtmrWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x600000: + case 0x600002: + case 0x600004: + case 0x600006: + case 0x600008: + case 0x600009: + case 0x60000a: + case 0x60000b: + case 0x60000c: + case 0x60000e: + case 0x600010: + case 0x600012: + case 0x600014: + case 0x600016: + case 0x600018: + case 0x60001a: + case 0x60001c: + case 0x60001e: { + Kaneko16Layer0Regs[(a - 0x600000) >> 1] = d; + return; + } + + case 0x680000: + case 0x680002: + case 0x680004: + case 0x680006: + case 0x680008: + case 0x680009: + case 0x68000a: + case 0x68000b: + case 0x68000c: + case 0x68000e: + case 0x680010: + case 0x680012: + case 0x680014: + case 0x680016: + case 0x680018: + case 0x68001a: + case 0x68001c: + case 0x68001e: { + Kaneko16Layer1Regs[(a - 0x680000) >> 1] = d; + return; + } + + case 0x700000: + case 0x700002: + case 0x700004: + case 0x700006: + case 0x700008: + case 0x70000a: + case 0x70000c: + case 0x70000e: + case 0x700010: + case 0x700012: + case 0x700014: + case 0x700016: + case 0x700018: + case 0x70001a: + case 0x70001c: + case 0x70001e: { + UINT32 offset = (a - 0x700000) >> 1; + Kaneko16SpriteRegs[offset] = d; + if (offset == 0 && (d & 0xff)) { + Kaneko16SpriteFlipX = d & 2; + Kaneko16SpriteFlipY = d & 1; + } + return; + } + + case 0x800001: { + MSM6295Command(0, d); + return; + } + + case 0x880001: { + MSM6295Command(1, d); + return; + } + + case 0xb80000: { + // Coin lockout + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write byte -> %06X, %02X\n"), a, d); +// } + } +} + +UINT16 __fastcall GtmrReadWord(UINT32 a) +{ + switch (a) { + case 0x800000: { + return MSM6295ReadStatus(0); + } + + case 0x880000: { + return MSM6295ReadStatus(1); + } + + case 0x900000: + case 0x900002: + case 0x900004: + case 0x900006: + case 0x900008: + case 0x90000a: + case 0x90000c: + case 0x90000e: + case 0x900010: + case 0x900012: + case 0x900014: + case 0x900016: + case 0x900018: + case 0x90001a: + case 0x90001c: + case 0x90001e: + case 0x900020: + case 0x900022: + case 0x900024: + case 0x900026: + case 0x900028: + case 0x90002a: + case 0x90002c: + case 0x90002e: + case 0x900030: + case 0x900032: + case 0x900034: + case 0x900036: + case 0x900038: { + if (Bloodwar) return BloodwarCalcRead((a - 0x900000) >> 1); + if (Bonkadv) return BonkadvCalcRead((a - 0x900000) >> 1); + if (Gtmr) return rand() & 0xffff; + return 0; + } + + case 0xa00000: { + // Watchdog read + return 0; + } + + case 0xb00000: { + return 0xff00 - (Kaneko16Input[0] << 8); + } + + case 0xb00002: { + return 0xff00 - (Kaneko16Input[1] << 8); + } + + case 0xb00004: { + return 0xff00 - (Kaneko16Input[2] << 8); + } + + case 0xb00006: { + return 0xffff; + } + + case 0xd00000: { + return ToyboxMCUStatusRead(); + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Read Word -> %06X\n"), a); +// } + } + + return 0; +} + +void __fastcall GtmrWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x2a0000: { + ToyboxMCUComWrite(0, d); + return; + } + + case 0x2b0000: { + ToyboxMCUComWrite(1, d); + return; + } + + case 0x2c0000: { + ToyboxMCUComWrite(2, d); + return; + } + + case 0x2d0000: { + ToyboxMCUComWrite(3, d); + return; + } + + case 0x700000: { + Kaneko16SpriteRegs[0] = d; + if (d & 0xff) { + Kaneko16SpriteFlipX = d & 2; + Kaneko16SpriteFlipY = d & 1; + } + return; + } + + case 0x800000: { + MSM6295Command(0, d); + return; + } + + case 0x880000: { + MSM6295Command(1, d); + return; + } + + case 0x900000: + case 0x900002: + case 0x900004: + case 0x900006: + case 0x900008: + case 0x90000a: + case 0x90000c: + case 0x90000e: + case 0x900010: + case 0x900012: + case 0x900014: + case 0x900016: + case 0x900018: + case 0x90001a: + case 0x90001c: + case 0x90001e: + case 0x900020: + case 0x900022: + case 0x900024: + case 0x900026: + case 0x900028: + case 0x90002a: + case 0x90002c: + case 0x90002e: + case 0x900030: + case 0x900032: + case 0x900034: + case 0x900036: + case 0x900038: { + if (Bonkadv) BonkadvCalcWrite((a - 0x900000) >> 1, d); + if (Bloodwar) BloodwarCalcWrite((a - 0x900000) >> 1, d); + return; + } + + case 0xa00000: { + // Watchdog write + return; + } + + case 0xb80000: { + // Coin lockout + return; + } + + case 0xc00000: { + Kaneko16DisplayEnable = d; + return; + } + + case 0xe00000: { + MSM6295Bank0 = d & 0xf; + memcpy(MSM6295ROM + 0x0000000, MSM6295ROMData + (0x40000 * (d & 0x0f)),0x40000); + return; + } + + case 0xe80000: { + if (Gtmr) { + MSM6295Bank1 = d & 1; + memcpy(MSM6295ROM + 0x0100000, MSM6295ROMData2 + (0x40000 * (d & 0x01)),0x40000); + } else { + MSM6295Bank1 = d; + memcpy(MSM6295ROM + 0x0100000, MSM6295ROMData2 + (0x40000 * d),0x40000); + } + return; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Write word -> %06X, %04X\n"), a, d); +// } + } +} + +UINT8 __fastcall Kaneko16Z80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x03: { + return BurnYM2151ReadStatus(); + } + + case 0x06: { + return Kaneko16SoundLatch; + } + } + + return 0; +} + +void __fastcall Kaneko16Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x03: { + BurnYM2151WriteRegister(d); + return; + } + } +} + +/*============================================================================================== +Sound Chip Handlers +===============================================================================================*/ + +static UINT8 Kaneko16EepromRead(UINT32 /*a*/) +{ + return EEPROMRead() & 0x01; +} + +static void Kaneko16EepromReset(UINT32 /*a*/, UINT32 d) +{ + EEPROMSetCSLine((d & 0x01) ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE ); +} + +static UINT8 Kaneko16Dip0Read(UINT32 /*a*/) +{ + return Kaneko16Dip[0]; +} + +static UINT8 Kaneko16Dip1Read(UINT32 /*a*/) +{ + return Kaneko16Dip[1]; +} + +/*============================================================================================== +Driver Inits +===============================================================================================*/ + +static void Kaneko16VideoInit() +{ + GenericTilesInit(); + + spritelist.first_sprite = (struct tempsprite *)BurnMalloc(0x400 * sizeof(spritelist.first_sprite[0])); + + Kaneko16ParseSprite = Kaneko16ParseSpriteType0; + + Kaneko16SpritesColourOffset = 0; + Kaneko16SpritesColourMask = 0x0fff; + Kaneko168BppSprites = 0; + if (Gtmr || Bloodwar || Bonkadv) { + Kaneko16SpritesColourOffset = 0x4000; + Kaneko16SpritesColourMask = 0xffff; + Kaneko168BppSprites = 1; + } + + Kaneko16SpriteXOffset = 0; + Kaneko16SpriteRamSize = 0x2000; + + Kaneko16LayersColourOffset = 0x40 * 16; + if (Gtmr || Bloodwar || Bonkadv) Kaneko16LayersColourOffset = 0; + Kaneko16TilesXOffset = 0; + if (nScreenWidth == 256) Kaneko16TilesXOffset = 0x5b; + if (nScreenWidth == 320) Kaneko16TilesXOffset = 0x33; + Kaneko16TilesYOffset = 0; + if (nScreenHeight == 224 || nScreenHeight == 232) Kaneko16TilesYOffset = -0x08; + + Kaneko16Bg15 = 0; + Kaneko16Bg15Reg = 0; + Kaneko16Bg15Select = 0; + Kaneko16RecalcBg15Palette = 0; +} + +static INT32 GtmrMachineInit() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Kaneko16Rom , 0x000000, 0x0ffffd, SM_ROM); + SekMapMemory(Kaneko16Ram , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(Kaneko16MCURam , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(Kaneko16PaletteRam , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Kaneko16Ram + 0x10000, 0x310000, 0x327fff, SM_RAM); + SekMapMemory(Kaneko16SpriteRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(Kaneko16Video1Ram , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(Kaneko16Video0Ram , 0x501000, 0x501fff, SM_RAM); + SekMapMemory(Kaneko16VScrl1Ram , 0x502000, 0x502fff, SM_RAM); + SekMapMemory(Kaneko16VScrl0Ram , 0x503000, 0x503fff, SM_RAM); + SekMapMemory(Kaneko16Video3Ram , 0x580000, 0x580fff, SM_RAM); + SekMapMemory(Kaneko16Video2Ram , 0x581000, 0x581fff, SM_RAM); + SekMapMemory(Kaneko16VScrl3Ram , 0x582000, 0x582fff, SM_RAM); + SekMapMemory(Kaneko16VScrl2Ram , 0x583000, 0x583fff, SM_RAM); + SekMapMemory((UINT8*)Kaneko16Layer0Regs , 0x600000, 0x60001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16Layer1Regs , 0x680000, 0x68001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16SpriteRegs + 2, 0x700002, 0x70001f, SM_WRITE); + SekSetReadByteHandler(0, GtmrReadByte); + SekSetReadWordHandler(0, GtmrReadWord); + SekSetWriteByteHandler(0, GtmrWriteByte); + SekSetWriteWordHandler(0, GtmrWriteWord); + SekClose(); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1980000 / 165, 100.0, 0); + MSM6295Init(1, 1980000 / 165, 100.0, 0); + + return 0; +} + +static INT32 FourBppPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 FourBppXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; +static INT32 FourBppYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 EightBppPlaneOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 EightBppXOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 512, 520, 528, 536, 544, 552, 560, 568 }; +static INT32 EightBppYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472 }; + +static INT32 BerlwallInit() +{ + INT32 nRet = 0, nLen; + + Kaneko16NumSprites = 0x2400; + Kaneko16NumTiles = 0x1000; + Kaneko16NumTiles2 = 0; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType2; + Kaneko16Bg15 = 1; + Kaneko16RecalcBg15Palette = 1; + + // Allocate and Blank all required memory + Mem = NULL; + ExplbrkrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + ExplbrkrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x400000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0100000, 4, 1); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x400000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 5, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x080000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + + // Load bitmap roms + memset(Kaneko16TempGfx, 0, 0x400000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x100000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x100001, 9, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200001, 11, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x300000, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x300001, 13, 2); if (nRet != 0) return 1; + Kaneko16DecodeBg15Bitmaps(); + BurnFree(Kaneko16TempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 14, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROMData, MSM6295ROM, 0x40000); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Kaneko16Rom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Kaneko16Ram , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(Kaneko16SpriteRam , 0x30e000, 0x30ffff, SM_RAM); + SekMapMemory(Kaneko16PaletteRam , 0x400000, 0x400fff, SM_RAM); + SekMapMemory(Kaneko16Video1Ram , 0xc00000, 0xc00fff, SM_RAM); + SekMapMemory(Kaneko16Video0Ram , 0xc01000, 0xc01fff, SM_RAM); + SekMapMemory(Kaneko16VScrl1Ram , 0xc02000, 0xc02fff, SM_RAM); + SekMapMemory(Kaneko16VScrl0Ram , 0xc03000, 0xc03fff, SM_RAM); + SekMapMemory((UINT8*)Kaneko16Layer0Regs , 0xd00000, 0xd0001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16SpriteRegs + 2, 0x600002, 0x60003f, SM_WRITE); + SekSetReadByteHandler(0, BerlwallReadByte); + SekSetReadWordHandler(0, BerlwallReadWord); + SekSetWriteByteHandler(0, BerlwallWriteByte); + SekSetWriteWordHandler(0, BerlwallWriteWord); + SekClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 2000000, nBurnSoundRate, &Kaneko16Dip0Read, &Kaneko16Dip1Read, NULL, NULL); + AY8910Init(1, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + // Setup the OKIM6295 emulation + MSM6295Init(0, (12000000 / 6) / 132, 100.0, 1); + + Kaneko16FrameRender = BerlwallFrameRender; + + // Reset the driver + BerlwallDoReset(); + + return 0; +} + +static INT32 BlazeonInit() +{ + INT32 nRet = 0, nLen; + + Kaneko16NumSprites = 0x4000; + Kaneko16NumTiles = 0x2000; + Kaneko16NumTiles2 = 0; + + Kaneko16VideoInit(); + Kaneko16SpriteRamSize = 0x1000; + Kaneko16SpriteXOffset = 0x10000 - 0x680; + + // Allocate and Blank all required memory + Mem = NULL; + BlazeonMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + BlazeonMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x200000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0100000, 3, 1); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x200000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 4, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + + BurnFree(Kaneko16TempGfx); + + // Load Z80 Rom + nRet = BurnLoadRom(Kaneko16Z80Rom, 5, 1); if (nRet != 0) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Kaneko16Rom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Kaneko16Ram , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Kaneko16PaletteRam , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(Kaneko16Video1Ram , 0x600000, 0x600fff, SM_RAM); + SekMapMemory(Kaneko16Video0Ram , 0x601000, 0x601fff, SM_RAM); + SekMapMemory(Kaneko16VScrl1Ram , 0x602000, 0x602fff, SM_RAM); + SekMapMemory(Kaneko16VScrl0Ram , 0x603000, 0x603fff, SM_RAM); + SekMapMemory(Kaneko16SpriteRam , 0x700000, 0x700fff, SM_RAM); + SekMapMemory((UINT8*)Kaneko16Layer0Regs , 0x800000, 0x80000f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16SpriteRegs + 2, 0x900002, 0x90001f, SM_WRITE); + SekSetReadByteHandler(0, BlazeonReadByte); + SekSetReadWordHandler(0, BlazeonReadWord); + SekSetWriteByteHandler(0, BlazeonWriteByte); + SekSetWriteWordHandler(0, BlazeonWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, Kaneko16Z80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, Kaneko16Z80Rom ); + ZetMapArea(0xc000, 0xdfff, 0, Kaneko16Z80Ram ); + ZetMapArea(0xc000, 0xdfff, 1, Kaneko16Z80Ram ); + ZetMapArea(0xc000, 0xdfff, 2, Kaneko16Z80Ram ); + ZetMemEnd(); + ZetSetInHandler(Kaneko16Z80PortRead); + ZetSetOutHandler(Kaneko16Z80PortWrite); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(4000000, 25.0); + + Kaneko16FrameRender = BlazeonFrameRender; + + // Reset the driver + BlazeonDoReset(); + + return 0; +} + +static INT32 BloodwarInit() +{ + INT32 nRet = 0, nLen; + + Bloodwar = 1; + + Kaneko16NumSprites = 0x1e000; + Kaneko16NumTiles = 0x2000; + Kaneko16NumTiles2 = 0x2000; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x1e00000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0200000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0400000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0600000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0800000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0a00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0c00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0e00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1000000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1200000, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1200001, 13, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1400000, 14, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1400001, 15, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1600000, 16, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1600001, 17, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1800000, 18, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1800001, 19, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1a00000, 20, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1a00001, 21, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1c00000, 22, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x1c00001, 23, 2); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x1e00000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 24, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + memset(Kaneko16TempGfx, 0, 0x1e00000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 25, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles2, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles2); + BurnFree(Kaneko16TempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2, 27, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + ToyboxMCURun = BloodwarMCURun; + Kaneko16FrameRender = BloodwarFrameRender; + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +static INT32 BonkadvInit() +{ + INT32 nRet = 0, nLen; + + Bonkadv = 1; + + Kaneko16NumSprites = 0x5000; + Kaneko16NumTiles = 0x4000; + Kaneko16NumTiles2 = 0x4000; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x500000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0200000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0300000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0400000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0400001, 7, 2); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x500000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 8, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + memset(Kaneko16TempGfx, 0, 0x500000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 9, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles2, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles2); + BurnFree(Kaneko16TempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2 + 0x100000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2 + 0x200000, 13, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + ToyboxMCURun = BonkadvMCURun; + Kaneko16FrameRender = BloodwarFrameRender; + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +static INT32 ExplbrkrInit() +{ + INT32 nRet = 0, nLen; + + Kaneko16NumSprites = 0x4800; + Kaneko16NumTiles = 0x2000; + Kaneko16NumTiles2 = 0x2000; + + Kaneko16VideoInit(); + + // Allocate and Blank all required memory + Mem = NULL; + ExplbrkrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + ExplbrkrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x240000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0100000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0180000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0200000, 4, 1); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x240000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 5, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + memset(Kaneko16TempGfx, 0, 0x240000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 6, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles2, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles2); + + // Load Sample Rom + memset(Kaneko16TempGfx, 0, 0x240000); + nRet = BurnLoadRom(Kaneko16TempGfx, 7, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROMData + 0x000000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x020000, Kaneko16TempGfx + 0x020000, 0x20000); + memcpy(MSM6295ROMData + 0x040000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x060000, Kaneko16TempGfx + 0x040000, 0x20000); + memcpy(MSM6295ROMData + 0x080000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x0a0000, Kaneko16TempGfx + 0x060000, 0x20000); + memcpy(MSM6295ROMData + 0x0c0000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x0e0000, Kaneko16TempGfx + 0x080000, 0x20000); + memcpy(MSM6295ROMData + 0x100000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x120000, Kaneko16TempGfx + 0x0a0000, 0x20000); + memcpy(MSM6295ROMData + 0x140000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x160000, Kaneko16TempGfx + 0x0c0000, 0x20000); + memcpy(MSM6295ROMData + 0x180000, Kaneko16TempGfx + 0x000000, 0x20000); + memcpy(MSM6295ROMData + 0x1a0000, Kaneko16TempGfx + 0x0e0000, 0x20000); + BurnFree(Kaneko16TempGfx); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Kaneko16Rom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Kaneko16Ram , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(Kaneko16Video1Ram , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(Kaneko16Video0Ram , 0x501000, 0x501fff, SM_RAM); + SekMapMemory(Kaneko16VScrl1Ram , 0x502000, 0x502fff, SM_RAM); + SekMapMemory(Kaneko16VScrl0Ram , 0x503000, 0x503fff, SM_RAM); + SekMapMemory(Kaneko16Video3Ram , 0x580000, 0x580fff, SM_RAM); + SekMapMemory(Kaneko16Video2Ram , 0x581000, 0x581fff, SM_RAM); + SekMapMemory(Kaneko16VScrl3Ram , 0x582000, 0x582fff, SM_RAM); + SekMapMemory(Kaneko16VScrl2Ram , 0x583000, 0x583fff, SM_RAM); + SekMapMemory(Kaneko16SpriteRam , 0x600000, 0x601fff, SM_RAM); + SekMapMemory(Kaneko16PaletteRam , 0x700000, 0x700fff, SM_RAM); + SekMapMemory((UINT8*)Kaneko16Layer0Regs , 0x800000, 0x80001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16SpriteRegs + 2, 0x900002, 0x90001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16Layer1Regs , 0xb00000, 0xb0001f, SM_WRITE); + SekSetReadByteHandler(0, ExplbrkrReadByte); + SekSetReadWordHandler(0, ExplbrkrReadWord); + SekSetWriteByteHandler(0, ExplbrkrWriteByte); + SekSetWriteWordHandler(0, ExplbrkrWriteWord); + SekClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 2000000, nBurnSoundRate, &Kaneko16EepromRead, NULL, NULL, &Kaneko16EepromReset); + + // Setup the OKIM6295 emulation + MSM6295Init(0, (12000000 / 6) / 132, 100.0, 1); + + Kaneko16Eeprom = 1; + EEPROMInit(&eeprom_interface_93C46); + + Kaneko16FrameRender = ExplbrkrFrameRender; + + // Reset the driver + ExplbrkrDoReset(); + + return 0; +} + +static INT32 GtmrInit() +{ + INT32 nRet = 0, nLen; + + Gtmr = 1; + + Kaneko16NumSprites = 0x8400; + Kaneko16NumTiles = 0x4000; + Kaneko16NumTiles2 = 0x4000; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x840000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x800001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x800000, 8, 2); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x840000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 9, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x200000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + BurnFree(Kaneko16TempGfx); + memcpy(Kaneko16Tiles2, Kaneko16Tiles, Kaneko16NumTiles * 16 * 16); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 10, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + ToyboxMCURun = GtmrMCURun; + Kaneko16FrameRender = GtmrFrameRender; + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +static INT32 GtmrevoInit() +{ + INT32 nRet = 0, nLen; + + Gtmr = 1; + + Kaneko16NumSprites = 0x8000; + Kaneko16NumTiles = 0x4000; + Kaneko16NumTiles2 = 0x4000; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x800000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600001, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600000, 6, 1); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x800000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 9, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x200000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + BurnFree(Kaneko16TempGfx); + memcpy(Kaneko16Tiles2, Kaneko16Tiles, Kaneko16NumTiles * 16 * 16); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2, 11, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + ToyboxMCURun = GtmrevoMCURun; + Kaneko16FrameRender = GtmrFrameRender; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +INT32 Gtmr2Init() +{ + INT32 nRet = 0, nLen; + + Gtmr = 1; + + Kaneko16NumSprites = 0x8000; + Kaneko16NumTiles = 0x8800; + Kaneko16NumTiles2 = 0x8800; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x800000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x700000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x700001, 7, 2); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x800000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400001, 11, 2); if (nRet != 0) return 1; + UnscrambleTiles(0x440000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + BurnFree(Kaneko16TempGfx); + memcpy(Kaneko16Tiles2, Kaneko16Tiles, Kaneko16NumTiles * 16 * 16); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2 + 0x40000, 13, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + ToyboxMCURun = GtmrevoMCURun; + Kaneko16FrameRender = GtmrFrameRender; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +INT32 Gtmr2uInit() +{ + INT32 nRet = 0, nLen; + + Gtmr = 1; + + Kaneko16NumSprites = 0x8000; + Kaneko16NumTiles = 0x8800; + Kaneko16NumTiles2 = 0x8800; + + Kaneko16VideoInit(); + Kaneko16ParseSprite = Kaneko16ParseSpriteType1; + + // Allocate and Blank all required memory + Mem = NULL; + GtmrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + GtmrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x800000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x600000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x700000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x700001, 7, 2); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 8, 16, 16, EightBppPlaneOffsets, EightBppXOffsets, EightBppYOffsets, 0x800, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x800000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x200000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x400001, 11, 2); if (nRet != 0) return 1; + UnscrambleTiles(0x440000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + BurnFree(Kaneko16TempGfx); + memcpy(Kaneko16Tiles2, Kaneko16Tiles, Kaneko16NumTiles * 16 * 16); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROMData, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROMData2, 13, 1); if (nRet != 0) return 1; + ExpandSampleBanks(); + + nRet = GtmrMachineInit(); if (nRet != 0) return 1; + + ToyboxMCURun = GtmrevoMCURun; + Kaneko16FrameRender = GtmrFrameRender; + + // Reset the driver + GtmrDoReset(); + + return 0; +} + +static INT32 MgcrystlInit() +{ + INT32 nRet = 0, nLen; + + Mgcrystl = 1; + + Kaneko16NumSprites = 0x5000; + Kaneko16NumTiles = 0x2000; + Kaneko16NumTiles2 = 0x2000; + + Kaneko16VideoInit(); + + // Allocate and Blank all required memory + Mem = NULL; + ExplbrkrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + ExplbrkrMemIndex(); + + Kaneko16TempGfx = (UINT8*)BurnMalloc(0x280000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Kaneko16Rom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16Rom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and Decode Sprite Roms + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0100000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0180000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0200000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0220000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0240000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Kaneko16TempGfx + 0x0260000, 4, 1); if (nRet != 0) return 1; + GfxDecode(Kaneko16NumSprites, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Sprites); + + // Load and Decode Tile Roms + memset(Kaneko16TempGfx, 0, 0x280000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 5, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles); + memset(Kaneko16TempGfx, 0, 0x280000); + nRet = BurnLoadRom(Kaneko16TempGfx + 0x000000, 6, 1); if (nRet != 0) return 1; + UnscrambleTiles(0x100000); + GfxDecode(Kaneko16NumTiles2, 4, 16, 16, FourBppPlaneOffsets, FourBppXOffsets, FourBppYOffsets, 0x400, Kaneko16TempGfx, Kaneko16Tiles2); + BurnFree(Kaneko16TempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 7, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROMData, MSM6295ROM, 0x40000); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Kaneko16Rom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Kaneko16Ram , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Kaneko16PaletteRam , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(Kaneko16Video1Ram , 0x600000, 0x600fff, SM_RAM); + SekMapMemory(Kaneko16Video0Ram , 0x601000, 0x601fff, SM_RAM); + SekMapMemory(Kaneko16VScrl1Ram , 0x602000, 0x602fff, SM_RAM); + SekMapMemory(Kaneko16VScrl0Ram , 0x603000, 0x603fff, SM_RAM); + SekMapMemory(Kaneko16Video3Ram , 0x680000, 0x680fff, SM_RAM); + SekMapMemory(Kaneko16Video2Ram , 0x681000, 0x681fff, SM_RAM); + SekMapMemory(Kaneko16VScrl3Ram , 0x682000, 0x682fff, SM_RAM); + SekMapMemory(Kaneko16VScrl2Ram , 0x683000, 0x683fff, SM_RAM); + SekMapMemory(Kaneko16SpriteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory((UINT8*)Kaneko16Layer0Regs , 0x800000, 0x80001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16SpriteRegs + 2, 0x900002, 0x90001f, SM_WRITE); + SekMapMemory((UINT8*)Kaneko16Layer1Regs , 0xb00000, 0xb0001f, SM_WRITE); + SekSetReadByteHandler(0, MgcrystlReadByte); + SekSetReadWordHandler(0, ExplbrkrReadWord); + SekSetWriteByteHandler(0, ExplbrkrWriteByte); + SekSetWriteWordHandler(0, ExplbrkrWriteWord); + SekClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 2000000, nBurnSoundRate, &Kaneko16EepromRead, NULL, NULL, &Kaneko16EepromReset); + + // Setup the OKIM6295 emulation + MSM6295Init(0, (12000000 / 4) / 165, 100.0, 1); + + Kaneko16Eeprom = 1; + EEPROMInit(&eeprom_interface_93C46); + + Kaneko16FrameRender = MgcrystlFrameRender; + + // Reset the driver + ExplbrkrDoReset(); + + return 0; +} + +INT32 Kaneko16Exit() +{ + SekExit(); + MSM6295Exit(0); + MSM6295Exit(1); + if (Kaneko16Eeprom) EEPROMExit(); + ZetExit(); + BurnYM2151Exit(); + + for (INT32 i = 0; i < 2; i++) { + AY8910Exit(i); + } + + GenericTilesExit(); + + BurnFree(Mem); + + Kaneko16NumTiles = 0; + Kaneko16NumTiles2 = 0; + Kaneko16NumSprites = 0; + Kaneko16SpriteFlipX = 0; + Kaneko16SpriteFlipY = 0; + Kaneko16SpritesColourOffset = 0; + Kaneko16SpritesColourMask = 0; + Kaneko16LayersColourOffset = 0; + Kaneko16DisplayEnable = 0; + Kaneko168BppSprites = 0; + Kaneko16Eeprom = 0; + Kaneko16TilesXOffset = 0; + Kaneko16TilesYOffset = 0; + Kaneko16Bg15 = 0; + Kaneko16Bg15Reg = 0; + Kaneko16Bg15Select = 0; + Kaneko16RecalcBg15Palette = 0; + Kaneko16SpriteRamSize = 0; + Kaneko16SpriteXOffset = 0; + Kaneko16SoundLatch = 0; + MSM6295Bank0 = 0; + MSM6295Bank1 = 0; + memset(Kaneko16SpriteRegs, 0, 0x20 * sizeof(UINT16)); + memset(Kaneko16Layer0Regs, 0, 0x10 * sizeof(UINT16)); + memset(Kaneko16Layer1Regs, 0, 0x10 * sizeof(UINT16)); + memset(ToyboxMCUCom, 0, 0x04 * sizeof(UINT16)); + + ToyboxMCURun = NULL; + Kaneko16FrameRender = NULL; + Kaneko16ParseSprite = NULL; + + Gtmr = 0; + Bloodwar = 0; + Bonkadv = 0; + Mgcrystl = 0; + + return 0; +} + +/*============================================================================================== +Sprite Rendering +===============================================================================================*/ + +#define USE_LATCHED_XY 1 +#define USE_LATCHED_CODE 2 +#define USE_LATCHED_COLOUR 4 + +static INT32 Kaneko16ParseSpriteType0(INT32 i, struct tempsprite *s) +{ + INT32 Attr, xOffs, Offset; + UINT16 *SpriteRam = (UINT16*)Kaneko16SpriteRam; + + Offset = (i * 8) >> 1; + + if (Offset >= (Kaneko16SpriteRamSize >> 1)) return -1; + + Attr = SpriteRam[Offset + 0]; + s->code = SpriteRam[Offset + 1]; + s->x = SpriteRam[Offset + 2]; + s->y = SpriteRam[Offset + 3]; + + s->color = (Attr & 0xfc) >> 2; + s->priority = (Attr & 0x300) >> 8; + s->flipy = Attr & 0x001; + s->flipx = Attr & 0x002; + + xOffs = (Attr & 0x1800) >> 11; + s->yoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 1]; + s->xoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 0]; + + s->yoffs -= Kaneko16SpriteRegs[0x01]; + + return ((Attr & 0x2000) ? USE_LATCHED_XY : 0) | ((Attr & 0x4000) ? USE_LATCHED_COLOUR: 0) | ((Attr & 0x8000) ? USE_LATCHED_CODE : 0); +} + +static INT32 Kaneko16ParseSpriteType1(INT32 i, struct tempsprite *s) +{ + INT32 Attr, xOffs, Offset; + UINT16 *SpriteRam = (UINT16*)Kaneko16SpriteRam; + + Offset = (i * 8) >> 1; + + if (Offset >= (Kaneko16SpriteRamSize >> 1)) return -1; + + Attr = SpriteRam[Offset + 0]; + s->code = SpriteRam[Offset + 1]; + s->x = SpriteRam[Offset + 2]; + s->y = SpriteRam[Offset + 3]; + + s->color = Attr & 0x3f; + s->priority = (Attr & 0xc0) >> 6; + s->flipy = Attr & 0x100; + s->flipx = Attr & 0x200; + s->code += (s->y & 1) << 16; + + xOffs = (Attr & 0x1800) >> 11; + s->yoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 1]; + s->xoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 0]; + + s->yoffs -= Kaneko16SpriteRegs[0x01]; + + return ((Attr & 0x2000) ? USE_LATCHED_XY : 0) | ((Attr & 0x4000) ? USE_LATCHED_COLOUR: 0) | ((Attr & 0x8000) ? USE_LATCHED_CODE : 0); +} + +static INT32 Kaneko16ParseSpriteType2(INT32 i, struct tempsprite *s) +{ + INT32 Attr, xOffs, Offset; + UINT16 *SpriteRam = (UINT16*)Kaneko16SpriteRam; + + Offset = (i * (16 >> 1)) + (8 >> 1); + + if (Offset >= (Kaneko16SpriteRamSize >> 1)) return -1; + + Attr = SpriteRam[Offset + 0]; + s->code = SpriteRam[Offset + 1]; + s->x = SpriteRam[Offset + 2]; + s->y = SpriteRam[Offset + 3]; + + s->color = (Attr & 0xfc) >> 2; + s->priority = (Attr & 0x300) >> 8; + s->flipy = Attr & 0x001; + s->flipx = Attr & 0x002; + + xOffs = (Attr & 0x1800) >> 11; + s->yoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 1]; + s->xoffs = Kaneko16SpriteRegs[0x08 + (xOffs * 2) + 0]; + + s->yoffs -= Kaneko16SpriteRegs[0x01]; + + return ((Attr & 0x2000) ? USE_LATCHED_XY : 0) | ((Attr & 0x4000) ? USE_LATCHED_COLOUR: 0) | ((Attr & 0x8000) ? USE_LATCHED_CODE : 0); +} + +static void Kaneko16RenderSprite(UINT32 Code, UINT32 Colour, INT32 FlipX, INT32 FlipY, INT32 sx, INT32 sy) +{ + UINT8 *SourceBase = Kaneko16Sprites + ((Code % Kaneko16NumSprites) * 256); + + INT32 SpriteScreenHeight = ((1 << 16) * 16 + 0x8000) >> 16; + INT32 SpriteScreenWidth = ((1 << 16) * 16 + 0x8000) >> 16; + + if (Kaneko168BppSprites) { + Colour = 0x100 * (Colour % 0x40); + } else { + Colour = 0x10 * (Colour % 0x40); + } + + if (SpriteScreenHeight && SpriteScreenWidth) { + INT32 dx = (16 << 16) / SpriteScreenWidth; + INT32 dy = (16 << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (FlipX) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (FlipY) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth + 1) { + INT32 Pixels = ex - nScreenWidth - 1; + ex -= Pixels; + } + + if (ey > nScreenHeight + 1) { + INT32 Pixels = ey - nScreenHeight - 1; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * 16); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + if (y < 0 || y > (nScreenHeight - 1)) continue; + + INT32 x, xIndex = xIndexBase; + for (x = sx; x > 16]; + if (c != 0) { + if (x >= 0 && x < nScreenWidth) pPixel[x] = (c | Colour | Kaneko16SpritesColourOffset) & Kaneko16SpritesColourMask; + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +static void Kaneko16RenderSprites(INT32 PriorityDraw) +{ + struct tempsprite *s = spritelist.first_sprite; + + INT32 i = 0; + INT32 x = 0; + INT32 y = 0; + INT32 Colour = 0; + INT32 Code = 0; + INT32 Priority = 0; + INT32 xOffs = 0; + INT32 yOffs = 0; + INT32 FlipX = 0; + INT32 FlipY = 0; + + while (1) { + INT32 Flags; + + Flags = Kaneko16ParseSprite(i, s); + + if (Flags == -1) break; + + if (Flags & USE_LATCHED_CODE) { + s->code = ++Code; + } else { + Code = s->code; + } + + if (Flags & USE_LATCHED_COLOUR) { + s->color = Colour; + s->priority = Priority; + s->xoffs = xOffs; + s->yoffs = yOffs; + s->flipx = FlipX; + s->flipy = FlipY; + } else { + Colour = s->color; + Priority = s->priority; + xOffs = s->xoffs; + yOffs = s->yoffs; + FlipX = s->flipx; + FlipY = s->flipy; + } + + if (Flags & USE_LATCHED_XY) + { + s->x += x; + s->y += y; + } + + x = s->x; + y = s->y; + + s->x = s->xoffs + s->x; + s->y = s->yoffs + s->y; + + s->x += Kaneko16SpriteXOffset; + + s->x = ((s->x & 0x7fc0) - (s->x & 0x8000)) / 0x40; + s->y = ((s->y & 0x7fc0) - (s->y & 0x8000)) / 0x40; + + i++; + s++; + } + + for (s = spritelist.first_sprite; s < spritelist.first_sprite + 0x400; s++) { + if (s->priority == PriorityDraw) Kaneko16RenderSprite(s->code, s->color, s->flipx, s->flipy, s->x, s->y); + } +} + +#undef USE_LATCHED_XY +#undef USE_LATCHED_CODE +#undef USE_LATCHED_COLOUR + +/*============================================================================================== +Tile Rendering +===============================================================================================*/ + +static INT32 Kaneko16GetLayerFlipOffset(INT32 curroffs) +{ + if (curroffs == 0) return 15; + if (curroffs == 1) return 14; + if (curroffs == 2) return 13; + if (curroffs == 3) return 12; + if (curroffs == 4) return 11; + if (curroffs == 5) return 10; + if (curroffs == 6) return 9; + if (curroffs == 7) return 8; + if (curroffs == 8) return 7; + if (curroffs == 9) return 6; + if (curroffs == 10) return 5; + if (curroffs == 11) return 4; + if (curroffs == 12) return 3; + if (curroffs == 13) return 2; + if (curroffs == 14) return 1; + if (curroffs == 15) return 0; + + return 0; +} + +static void Kaneko16QueueTilesLayer(INT32 Layer) +{ + INT32 x, y, mx, my, px, py, Code, Attr, Colour, Flip, Priority, LineScroll, TileIndex, pSrcXOffs, pSrcYOffs, xScroll, yScroll; + UINT8 pTileSrc; + + LayerQueueSize[Layer] = 0; + TileIndex = 0; + + UINT16 *VRAM = NULL; + UINT16 *VSCROLLRAM = NULL; + UINT16 *LAYERREGS = NULL; + UINT8 *TILEDATA = NULL; + INT32 xScrollReg = 0; + INT32 yScrollReg = 0; + INT32 xOffs = 0; + INT32 numTiles = 0; + + switch (Layer) { + case 0: { + VRAM = (UINT16*)Kaneko16Video0Ram; + VSCROLLRAM = (UINT16*)Kaneko16VScrl0Ram; + LAYERREGS = Kaneko16Layer0Regs; + TILEDATA = Kaneko16Tiles; + xScrollReg = 2; + yScrollReg = 3; + xOffs = 0; + numTiles = Kaneko16NumTiles; + break; + } + + case 1: { + VRAM = (UINT16*)Kaneko16Video1Ram; + VSCROLLRAM = (UINT16*)Kaneko16VScrl1Ram; + LAYERREGS = Kaneko16Layer0Regs; + TILEDATA = Kaneko16Tiles; + xScrollReg = 0; + yScrollReg = 1; + xOffs = 2; + numTiles = Kaneko16NumTiles; + break; + } + + case 2: { + VRAM = (UINT16*)Kaneko16Video2Ram; + VSCROLLRAM = (UINT16*)Kaneko16VScrl2Ram; + LAYERREGS = Kaneko16Layer1Regs; + TILEDATA = Kaneko16Tiles2; + xScrollReg = 2; + yScrollReg = 3; + xOffs = 0; + numTiles = Kaneko16NumTiles2; + break; + } + + case 3: { + VRAM = (UINT16*)Kaneko16Video3Ram; + VSCROLLRAM = (UINT16*)Kaneko16VScrl3Ram; + LAYERREGS = Kaneko16Layer1Regs; + TILEDATA = Kaneko16Tiles2; + xScrollReg = 0; + yScrollReg = 1; + xOffs = 2; + numTiles = Kaneko16NumTiles2; + break; + } + } + + xScroll = LAYERREGS[xScrollReg]; + xOffs = Kaneko16TilesXOffset + xOffs; + yScroll = ((LAYERREGS[yScrollReg] >> 6) & 0x1ff) - Kaneko16TilesYOffset; + + mx = my = -1; + for (y = 0; y < 512; y++) { + if (!(y % 16)) my++; + + LineScroll = VSCROLLRAM[y]; + py = y - yScroll; + + if (py < -30) py += 512; + + for (x = 0; x < 512; x++) { + if (!(x % 16)) mx++; + + if (py < 0 || py >= nScreenHeight) continue; + + px = x - (((xScroll + LineScroll) >> 6) & 0x1ff) - xOffs; + if (px < -7) px += 512; + + if (px < 0 || px >= nScreenWidth) continue; + + TileIndex = ((my * 32) + mx) * 2; + + Code = VRAM[TileIndex + 1]; + if (Code >= numTiles) continue; + Attr = VRAM[TileIndex + 0]; + Priority = (Attr >> 8) & 7; + Colour = (Attr >> 2) & 0x3f; + Flip = Attr & 3; + + pSrcXOffs = x % 16; + pSrcYOffs = y % 16; + if (Flip & 1) pSrcYOffs = Kaneko16GetLayerFlipOffset(pSrcYOffs); + if (Flip & 2) pSrcXOffs = Kaneko16GetLayerFlipOffset(pSrcXOffs); + + pTileSrc = TILEDATA[(Code << 8) + (pSrcYOffs * 16) + pSrcXOffs]; + + if (pTileSrc != 0) { + LayerQueueXY[Layer][LayerQueueSize[Layer]] = (py << 9) | px; + LayerQueueColour[Layer][LayerQueueSize[Layer]] = (Colour << 4) | pTileSrc; + LayerQueuePriority[Layer][LayerQueueSize[Layer]] = Priority; + LayerQueueSize[Layer]++; + } + } + mx = -1; + } +} + +static void Kaneko16RenderLayerQueue(INT32 Layer, INT32 Priority) +{ + for (INT32 i = 0; i < LayerQueueSize[Layer]; i++) { + if (LayerQueuePriority[Layer][i] == Priority) { + UINT16* pPixel = pTransDraw + ((LayerQueueXY[Layer][i] >> 9) * nScreenWidth) + (LayerQueueXY[Layer][i] & 0x1ff); + pPixel[0] = LayerQueueColour[Layer][i] | Kaneko16LayersColourOffset; + } + } +} + +void Kaneko16RenderTileLayer(INT32 Layer, INT32 PriorityDraw, INT32 xScroll) +{ + INT32 mx, my, Code, Attr, Colour, Flip, Priority, x, y, TileIndex = 0; + + UINT16 *VRAM = NULL; + UINT16 *LAYERREGS = NULL; + UINT8 *TILEDATA = NULL; + INT32 yScrollReg = 0; + INT32 xOffs = 0; + INT32 numTiles = 0; + + switch (Layer) { + case 0: { + VRAM = (UINT16*)Kaneko16Video0Ram; + LAYERREGS = Kaneko16Layer0Regs; + TILEDATA = Kaneko16Tiles; + yScrollReg = 3; + xOffs = 0; + numTiles = Kaneko16NumTiles; + break; + } + + case 1: { + VRAM = (UINT16*)Kaneko16Video1Ram; + LAYERREGS = Kaneko16Layer0Regs; + TILEDATA = Kaneko16Tiles; + yScrollReg = 1; + xOffs = 2; + numTiles = Kaneko16NumTiles; + break; + } + + case 2: { + VRAM = (UINT16*)Kaneko16Video2Ram; + LAYERREGS = Kaneko16Layer1Regs; + TILEDATA = Kaneko16Tiles2; + yScrollReg = 3; + xOffs = 0; + numTiles = Kaneko16NumTiles2; + break; + } + + case 3: { + VRAM = (UINT16*)Kaneko16Video3Ram; + LAYERREGS = Kaneko16Layer1Regs; + TILEDATA = Kaneko16Tiles2; + yScrollReg = 1; + xOffs = 2; + numTiles = Kaneko16NumTiles2; + break; + } + } + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = VRAM[TileIndex + 1]; + + if (Code >= numTiles) continue; + + Attr = VRAM[TileIndex + 0]; + Colour = (Attr >> 2) & 0x3f; + Flip = Attr & 3; + Priority = (Attr >> 8) & 7; + + if (Priority == PriorityDraw) { + x = 16 * mx; + y = 16 * my; + + x -= (xScroll >> 6) & 0x1ff; + y -= (LAYERREGS[yScrollReg] >> 6) & 0x1ff; + + if (x < -7) x += 512; + if (y < -30) y += 512; + + x -= Kaneko16TilesXOffset + xOffs; + y += Kaneko16TilesYOffset; + + if (x > 0 && x < (nScreenWidth - 16) && y > 0 && y < (nScreenHeight - 16)) { + if (Flip == 0) Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 1) Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 2) Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 3) Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + } else { + if (Flip == 0) Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 1) Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 2) Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + if (Flip == 3) Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, Kaneko16LayersColourOffset, TILEDATA); + } + } + + TileIndex += 2; + } + } +} + +/*============================================================================================== +Background Bitmap Rendering +===============================================================================================*/ + +static void Kaneko16RenderBg15Bitmap() +{ + INT32 Select = Kaneko16Bg15Select; + INT32 Flip = Select & 0x20; + INT32 x, y; + + if (Flip) Select ^= 0x1f; + Select &= 0x1f; + + for (y = 0; y < nScreenHeight; y++) { + UINT16 *pPixel = pTransDraw + (y * nScreenWidth); + UINT16 *data = Kaneko16Bg15Data + (Select * 256 * 256) + ((y + 16) * 256); + + for (x = 0; x < nScreenWidth; x++) { + pPixel[x] = data[x]; + } + } +} + +/*============================================================================================== +Palette Handling +===============================================================================================*/ + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 5); + g = pal5bit(nColour >> 10); + b = pal5bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +INT32 Kaneko16CalcPalette(INT32 num) +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)Kaneko16PaletteRam, pd = Kaneko16Palette; i < num; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +/*============================================================================================== +Graphics Rendering +===============================================================================================*/ + +// If the VScroll RAM is the same all the way through then just apply it as an xScroll value - much faster then doing line scroll on every line +#define HANDLE_VSCROLL(_N_) \ + if (Layer##_N_##Enabled) { \ + INT32 vScrollFast = 1; \ + UINT16 *VSCROLLRAM = (UINT16*)Kaneko16VScrl##_N_##Ram; \ + INT32 LineScroll = VSCROLLRAM[0]; \ + for (i = 0; i < 0x200; i++) { \ + if (VSCROLLRAM[i] != LineScroll) { \ + vScrollFast = 0; \ + break; \ + } \ + } \ + if (!vScrollFast) { \ + vScroll##_N_##Enabled = 1; \ + Kaneko16QueueTilesLayer(_N_); \ + } else { \ + vScroll##_N_##Enabled = 0; \ + xScroll##_N_ += LineScroll; \ + } \ + } \ +\ + +void BerlwallFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x0800); + + if (Kaneko16RecalcBg15Palette) { + for (i = 0; i < 32768; i++) { + INT32 r = pal5bit(i >> 5); + INT32 g = pal5bit(i >> 10); + INT32 b = pal5bit(i >> 0); + Kaneko16Palette[i + 2048] = BurnHighCol(r, g, b, 0); + } + + Kaneko16RecalcBg15Palette = 0; + } + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + Kaneko16RenderBg15Bitmap(); + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + + if (i == 0) Kaneko16RenderSprites(0); + if (i == 1) Kaneko16RenderSprites(1); + if (i == 2) Kaneko16RenderSprites(2); + if (i == 7) Kaneko16RenderSprites(3); + } + + BurnTransferCopy(Kaneko16Palette); +} + +void BlazeonFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x0800); + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + + if (i == 0) Kaneko16RenderSprites(0); + if (i == 1) Kaneko16RenderSprites(1); + if (i == 7) Kaneko16RenderSprites(2); + if (i == 7) Kaneko16RenderSprites(3); + } + + BurnTransferCopy(Kaneko16Palette); +} + +void BloodwarFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + INT32 Layer2Enabled = 0; + INT32 Layer3Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + INT32 vScroll2Enabled = 0; + INT32 vScroll3Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + INT32 xScroll2 = Kaneko16Layer1Regs[2]; + INT32 xScroll3 = Kaneko16Layer1Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x1000) Layer2Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x0010) Layer3Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x10000); + + if (!Kaneko16DisplayEnable) return; + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + if (Kaneko16Layer1Regs[4] & 0x800) { + HANDLE_VSCROLL(2) + } + + if (Kaneko16Layer1Regs[4] & 0x008) { + HANDLE_VSCROLL(3) + } + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + if (Layer2Enabled) { if (vScroll2Enabled) { Kaneko16RenderLayerQueue(2, i); } else { Kaneko16RenderTileLayer(2, i, xScroll2); }} + if (Layer3Enabled) { if (vScroll3Enabled) { Kaneko16RenderLayerQueue(3, i); } else { Kaneko16RenderTileLayer(3, i, xScroll3); }} + + if (i == 1) Kaneko16RenderSprites(0); + if (i == 2) Kaneko16RenderSprites(1); + if (i == 4) Kaneko16RenderSprites(2); + if (i == 6) Kaneko16RenderSprites(3); + } + + BurnTransferCopy(Kaneko16Palette); +} + +void ExplbrkrFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + INT32 Layer2Enabled = 0; + INT32 Layer3Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + INT32 vScroll2Enabled = 0; + INT32 vScroll3Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + INT32 xScroll2 = Kaneko16Layer1Regs[2]; + INT32 xScroll3 = Kaneko16Layer1Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x1000) Layer2Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x0010) Layer3Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x1000); + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + if (Kaneko16Layer1Regs[4] & 0x800) { + HANDLE_VSCROLL(2) + } + + if (Kaneko16Layer1Regs[4] & 0x008) { + HANDLE_VSCROLL(3) + } + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + if (Layer2Enabled) { if (vScroll2Enabled) { Kaneko16RenderLayerQueue(2, i); } else { Kaneko16RenderTileLayer(2, i, xScroll2); }} + if (Layer3Enabled) { if (vScroll3Enabled) { Kaneko16RenderLayerQueue(3, i); } else { Kaneko16RenderTileLayer(3, i, xScroll3); }} + } + + Kaneko16RenderSprites(0); + Kaneko16RenderSprites(1); + Kaneko16RenderSprites(2); + Kaneko16RenderSprites(3); + + BurnTransferCopy(Kaneko16Palette); +} + +void GtmrFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + INT32 Layer2Enabled = 0; + INT32 Layer3Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + INT32 vScroll2Enabled = 0; + INT32 vScroll3Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + INT32 xScroll2 = Kaneko16Layer1Regs[2]; + INT32 xScroll3 = Kaneko16Layer1Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x1000) Layer2Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x0010) Layer3Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x10000); + + if (!Kaneko16DisplayEnable) return; + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + if (Kaneko16Layer1Regs[4] & 0x800) { + HANDLE_VSCROLL(2) + } + + if (Kaneko16Layer1Regs[4] & 0x008) { + HANDLE_VSCROLL(3) + } + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + if (Layer2Enabled) { if (vScroll2Enabled) { Kaneko16RenderLayerQueue(2, i); } else { Kaneko16RenderTileLayer(2, i, xScroll2); }} + if (Layer3Enabled) { if (vScroll3Enabled) { Kaneko16RenderLayerQueue(3, i); } else { Kaneko16RenderTileLayer(3, i, xScroll3); }} + + if (i == 0) Kaneko16RenderSprites(0); + if (i == 1) Kaneko16RenderSprites(1); + if (i == 2) Kaneko16RenderSprites(2); + if (i == 7) Kaneko16RenderSprites(3); + } + + BurnTransferCopy(Kaneko16Palette); +} + +void MgcrystlFrameRender() +{ + INT32 i; + INT32 Layer0Enabled = 0; + INT32 Layer1Enabled = 0; + INT32 Layer2Enabled = 0; + INT32 Layer3Enabled = 0; + + INT32 vScroll0Enabled = 0; + INT32 vScroll1Enabled = 0; + INT32 vScroll2Enabled = 0; + INT32 vScroll3Enabled = 0; + + INT32 xScroll0 = Kaneko16Layer0Regs[2]; + INT32 xScroll1 = Kaneko16Layer0Regs[0]; + INT32 xScroll2 = Kaneko16Layer1Regs[2]; + INT32 xScroll3 = Kaneko16Layer1Regs[0]; + + if (~Kaneko16Layer0Regs[4] & 0x1000) Layer0Enabled = 1; + if (~Kaneko16Layer0Regs[4] & 0x0010) Layer1Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x1000) Layer2Enabled = 1; + if (~Kaneko16Layer1Regs[4] & 0x0010) Layer3Enabled = 1; + + BurnTransferClear(); + Kaneko16CalcPalette(0x1000); + + if (Kaneko16Layer0Regs[4] & 0x800) { + HANDLE_VSCROLL(0) + } + + if (Kaneko16Layer0Regs[4] & 0x008) { + HANDLE_VSCROLL(1) + } + + if (Kaneko16Layer1Regs[4] & 0x800) { + HANDLE_VSCROLL(2) + } + + if (Kaneko16Layer1Regs[4] & 0x008) { + HANDLE_VSCROLL(3) + } + + for (i = 0; i < 8; i++) { + if (Layer0Enabled) { if (vScroll0Enabled) { Kaneko16RenderLayerQueue(0, i); } else { Kaneko16RenderTileLayer(0, i, xScroll0); }} + if (Layer1Enabled) { if (vScroll1Enabled) { Kaneko16RenderLayerQueue(1, i); } else { Kaneko16RenderTileLayer(1, i, xScroll1); }} + if (Layer2Enabled) { if (vScroll2Enabled) { Kaneko16RenderLayerQueue(2, i); } else { Kaneko16RenderTileLayer(2, i, xScroll2); }} + if (Layer3Enabled) { if (vScroll3Enabled) { Kaneko16RenderLayerQueue(3, i); } else { Kaneko16RenderTileLayer(3, i, xScroll3); }} + + if (i == 1) Kaneko16RenderSprites(0); + if (i == 2) Kaneko16RenderSprites(1); + if (i == 4) Kaneko16RenderSprites(2); + if (i == 6) Kaneko16RenderSprites(3); + } + + BurnTransferCopy(Kaneko16Palette); +} + +/*============================================================================================== +Frame functions +===============================================================================================*/ + +INT32 ExplbrkrFrame() +{ + INT32 nInterleave = 10; + nSoundBufferPos = 0; + + if (Kaneko16Reset) ExplbrkrDoReset(); + + Kaneko16MakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesDone[0] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 3) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 6) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 9) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) Kaneko16FrameRender(); + + return 0; +} + +INT32 BlazeonFrame() +{ + INT32 nInterleave = 10; + nSoundBufferPos = 0; + + if (Kaneko16Reset) BlazeonDoReset(); + + Kaneko16MakeInputs(); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 3) SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + if (i == 6) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + if (i == 9) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + } + + } + + if (pBurnDraw) Kaneko16FrameRender(); + + return 0; +} + +INT32 GtmrFrame() +{ + if (Kaneko16Reset) GtmrDoReset(); + + Kaneko16MakeInputs(); + + SekOpen(0); + SekNewFrame(); + + SekRun((16000000 / 60) / 4); + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + SekRun((16000000 / 60) / 4); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekRun((16000000 / 60) / 4); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekRun((16000000 / 60) / 4); + + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) Kaneko16FrameRender(); + + return 0; +} + +/*============================================================================================== +Scan Driver +===============================================================================================*/ + +static INT32 Kaneko16Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if (Kaneko16Eeprom) EEPROMScan(nAction, pnMin); + + if (nAction & ACB_NVRAM && Kaneko16NVRam) { + memset(&ba, 0, sizeof(ba)); + ba.Data = Kaneko16NVRam; + ba.nLen = 0x100; + ba.szName = "NVRam"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(Kaneko16Dip); + SCAN_VAR(Kaneko16Input); + SCAN_VAR(Kaneko16SoundLatch); + SCAN_VAR(Kaneko16SpriteFlipX); + SCAN_VAR(Kaneko16SpriteFlipY); + SCAN_VAR(Kaneko16DisplayEnable); + SCAN_VAR(Kaneko16SpriteRegs); + SCAN_VAR(Kaneko16Layer0Regs); + SCAN_VAR(Kaneko16Layer1Regs); + + if (Kaneko16Bg15) { + SCAN_VAR(Kaneko16Bg15Reg); + SCAN_VAR(Kaneko16Bg15Select); + } + } + + return 0; +} + +static INT32 BlazeonScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + BurnYM2151Scan(nAction); + + SCAN_VAR(nSoundBufferPos); + } + + return Kaneko16Scan(nAction, pnMin);; +} + +static INT32 ExplbrkrScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if (nAction & ACB_DRIVER_DATA) { + AY8910Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + SCAN_VAR(MSM6295Bank0); + SCAN_VAR(nSoundBufferPos); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x0000000, MSM6295ROMData + (0x40000 * MSM6295Bank0),0x40000); + } + + return Kaneko16Scan(nAction, pnMin);; +} + +static INT32 GtmrScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if (nAction & ACB_DRIVER_DATA) { + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + SCAN_VAR(ToyboxMCUCom); + SCAN_VAR(MSM6295Bank0); + SCAN_VAR(MSM6295Bank1); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x0000000, MSM6295ROMData + (0x40000 * MSM6295Bank0),0x40000); + memcpy(MSM6295ROM + 0x0100000, MSM6295ROMData2 + (0x40000 * MSM6295Bank1),0x40000); + } + + return Kaneko16Scan(nAction, pnMin);; +} + +/*============================================================================================== +Driver defs +===============================================================================================*/ + +struct BurnDriver BurnDrvBerlwall = { + "berlwall", NULL, NULL, NULL, "1991", + "The Berlin Wall\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, BerlwallRomInfo, BerlwallRomName, NULL, NULL, BerlwallInputInfo, BerlwallDIPInfo, + BerlwallInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + &Kaneko16RecalcBg15Palette, 0x9000, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBerlwallt = { + "berlwallt", "berlwall", NULL, NULL, "1991", + "The Berlin Wall (bootleg ?)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, BerlwalltRomInfo, BerlwalltRomName, NULL, NULL, BerlwallInputInfo, BerlwalltDIPInfo, + BerlwallInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + &Kaneko16RecalcBg15Palette, 0x9000, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBlazeon = { + "blazeon", NULL, NULL, NULL, "1991", + "Blaze On (Japan)\0", NULL, "Atlus", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, BlazeonRomInfo, BlazeonRomName, NULL, NULL, BlazeonInputInfo, BlazeonDIPInfo, + BlazeonInit, Kaneko16Exit, BlazeonFrame, NULL, BlazeonScan, + NULL, 0x1000, 320, 232, 4, 3 +}; + +struct BurnDriver BurnDrvBloodwar = { + "bloodwar", NULL, NULL, NULL, "1994", + "Blood Warrior\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, BloodwarRomInfo, BloodwarRomName, NULL, NULL, BloodwarInputInfo, BloodwarDIPInfo, + BloodwarInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBonkadv = { + "bonkadv", NULL, NULL, NULL, "1994", + "B.C. Kid / Bonk's Adventure / Kyukyoku!! PC Genjin\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, BonkadvRomInfo, BonkadvRomName, NULL, NULL, BonkadvInputInfo, BonkadvDIPInfo, + BonkadvInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvExplbrkr = { + "explbrkr", NULL, NULL, NULL, "1992", + "Explosive Breaker\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, ExplbrkrRomInfo, ExplbrkrRomName, NULL, NULL, ExplbrkrInputInfo, ExplbrkrDIPInfo, + ExplbrkrInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + NULL, 0x1000, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvBakubrkr = { + "bakubrkr", "explbrkr", NULL, NULL, "1992", + "Bakuretsu Breaker\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, BakubrkrRomInfo, BakubrkrRomName, NULL, NULL, ExplbrkrInputInfo, ExplbrkrDIPInfo, + ExplbrkrInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + NULL, 0x1000, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvGtmr = { + "gtmr", NULL, NULL, NULL, "1994", + "1000 Miglia: Great 1000 Miles Rally (94/07/18)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, GtmrRomInfo, GtmrRomName, NULL, NULL, GtmrInputInfo, GtmrDIPInfo, + GtmrInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmra = { + "gtmra", "gtmr", NULL, NULL, "1994", + "1000 Miglia: Great 1000 Miles Rally (94/06/13)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, GtmraRomInfo, GtmraRomName, NULL, NULL, GtmrInputInfo, GtmrDIPInfo, + GtmrInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmre = { + "gtmre", "gtmr", NULL, NULL, "1994", + "Great 1000 Miles Rally: Evolution Model!!! (94/09/06)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, GtmreRomInfo, GtmreRomName, NULL, NULL, GtmrInputInfo, GtmrDIPInfo, + GtmrevoInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmrusa = { + "gtmrusa", "gtmr", NULL, NULL, "1994", + "Great 1000 Miles Rally: U.S.A Version! (94/09/06)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, GtmrusaRomInfo, GtmrusaRomName, NULL, NULL, GtmrInputInfo, GtmrDIPInfo, + GtmrevoInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmr2 = { + "gtmr2", NULL, NULL, NULL, "1995", + "Mille Miglia 2: Great 1000 Miles Rally (95/05/24)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, Gtmr2RomInfo, Gtmr2RomName, NULL, NULL, GtmrInputInfo, Gtmr2DIPInfo, + Gtmr2Init, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmr2a = { + "gtmr2a", "gtmr2", NULL, NULL, "1995", + "Mille Miglia 2: Great 1000 Miles Rally (95/04/04)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, Gtmr2aRomInfo, Gtmr2aRomName, NULL, NULL, GtmrInputInfo, Gtmr2DIPInfo, + Gtmr2Init, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGtmr2u = { + "gtmr2u", "gtmr2", NULL, NULL, "1995", + "Great 1000 Miles Rally 2 USA (95/05/18)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0, + NULL, Gtmr2uRomInfo, Gtmr2uRomName, NULL, NULL, GtmrInputInfo, Gtmr2DIPInfo, + Gtmr2uInit, Kaneko16Exit, GtmrFrame, NULL, GtmrScan, + NULL, 0x10000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMgcrsytl = { + "mgcrystl", NULL, NULL, NULL, "1991", + "Magical Crystals (World, 92/01/10)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, MgcrystlRomInfo, MgcrystlRomName, NULL, NULL, MgcrystlInputInfo, MgcrystlDIPInfo, + MgcrystlInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + NULL, 0x1000, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMgcrsytlo = { + "mgcrystlo", "mgcrystl", NULL, NULL, "1991", + "Magical Crystals (World, 91/12/10)\0", NULL, "Kaneko", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, MgcrystloRomInfo, MgcrystloRomName, NULL, NULL, MgcrystlInputInfo, MgcrystlDIPInfo, + MgcrystlInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + NULL, 0x1000, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMgcrsytlj = { + "mgcrystlj", "mgcrystl", NULL, NULL, "1991", + "Magical Crystals (Japan, 92/01/13)\0", NULL, "Kaneko (Atlus license)", "Kaneko 16-bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, MgcrystljRomInfo, MgcrystljRomName, NULL, NULL, MgcrystlInputInfo, MgcrystlDIPInfo, + MgcrystlInit, Kaneko16Exit, ExplbrkrFrame, NULL, ExplbrkrScan, + NULL, 0x1000, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_lordgun.cpp b/src/burn/drivers/misc_post90s/d_lordgun.cpp new file mode 100644 index 00000000..67249a0f --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_lordgun.cpp @@ -0,0 +1,1513 @@ +// FB Alpha Lord of Gun driver module +// Based on MAME driver by Luca Elia, XingXing, and David Haywood + +#include "tiles_generic.h" +#include "burn_ymf278b.h" +#include "burn_ym3812.h" +#include "msm6295.h" +#include "8255ppi.h" +#include "eeprom.h" +#include "burn_gun.h" + +static UINT8 *AllMem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *AllRam = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KROM = NULL; +static UINT8 *DrvZ80ROM = NULL; +static UINT8 *DrvGfxROM0 = NULL; +static UINT8 *DrvGfxROM1 = NULL; +static UINT8 *DrvGfxROM2 = NULL; +static UINT8 *DrvGfxROM3 = NULL; +static UINT8 *DrvSndROM0 = NULL; +static UINT8 *DrvSndROM1 = NULL; +static UINT8 *DrvSndROM2 = NULL; +static UINT8 *Drv68KRAM = NULL; +static UINT8 *DrvPriRAM = NULL; +static UINT8 *DrvPalRAM = NULL; +static UINT8 *DrvVidRAM0 = NULL; +static UINT8 *DrvVidRAM1 = NULL; +static UINT8 *DrvVidRAM2 = NULL; +static UINT8 *DrvVidRAM3 = NULL; +static UINT8 *DrvScrRAM = NULL; +static UINT8 *DrvSprRAM = NULL; +static UINT8 *DrvProtRAM = NULL; +static UINT8 *DrvZ80RAM = NULL; + +static UINT32 *DrvPalette = NULL; +static UINT8 DrvRecalc; + +static UINT16 *scrollx = NULL; +static UINT16 *scrolly = NULL; +static UINT16 *priority = NULL; +static UINT8 *soundlatch = NULL; +static INT8 *okibank = NULL; + +static UINT8 *DrvTransTable[5] = { NULL, NULL, NULL, NULL, NULL }; +static UINT16 *draw_bitmap[5] = { NULL, NULL, NULL, NULL, NULL }; + +static UINT8 aliencha_dip_sel; +static UINT8 lordgun_whitescreen; + +static INT32 DrvAxis[4]; +static UINT16 DrvAnalogInput[4]; +static UINT16 DrvInputs[5]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvDips[4]; +static UINT8 DrvReset; + +static INT32 lordgun_gun_hw_x[2]; +static INT32 lordgun_gun_hw_y[2]; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo LordgunInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy4 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "mouse x-axis"), + A("P1 Up / Down", BIT_ANALOG_REL, DrvAxis + 1, "mouse y-axis"), + {"P1 Button 1", BIT_DIGITAL, DrvJoy5 + 4, "mouse button" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy4 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 2, "mouse x-axis"), + A("P2 Up / Down", BIT_ANALOG_REL, DrvAxis + 3, "mouse y-axis"), + {"P2 Button 1", BIT_DIGITAL, DrvJoy5 + 5, "mouse button" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Lordgun) + +#undef A + +static struct BurnInputInfo AlienchaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy4 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy4 + 2, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy4 + 3, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy4 + 4, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy4 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy4 + 5, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy4 + 6, "p2 fire 5" }, + {"P2 Button 6", BIT_DIGITAL, DrvJoy4 + 7, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 1, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Fake Dip", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(Aliencha) + +static struct BurnDIPInfo LordgunDIPList[]= +{ + {0x0d, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2, "Stage Select" }, + {0x0d, 0x01, 0x01, 0x01, "Off" }, + {0x0d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Guns" }, + {0x0d, 0x01, 0x02, 0x02, "IGS" }, + {0x0d, 0x01, 0x02, 0x00, "Konami" }, + + {0 , 0xfe, 0 , 2, "Ranking Music" }, + {0x0d, 0x01, 0x04, 0x04, "Exciting" }, + {0x0d, 0x01, 0x04, 0x00, "Tender" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x0d, 0x01, 0x08, 0x00, "1" }, + {0x0d, 0x01, 0x08, 0x08, "2" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0d, 0x01, 0x40, 0x40, "Off" }, + {0x0d, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Lordgun) + +static struct BurnDIPInfo AlienchaDIPList[]= +{ + {0x1a, 0xff, 0xff, 0xff, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xff, NULL }, + {0x1d, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Credits To Start" }, + {0x1a, 0x01, 0x01, 0x01, "1" }, + {0x1a, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x1a, 0x01, 0x0e, 0x00, "5 Coins 1 Credits" }, + {0x1a, 0x01, 0x0e, 0x02, "4 Coins 1 Credits" }, + {0x1a, 0x01, 0x0e, 0x04, "3 Coins 1 Credits" }, + {0x1a, 0x01, 0x0e, 0x06, "2 Coins 1 Credits" }, + {0x1a, 0x01, 0x0e, 0x0e, "1 Coin 1 Credits" }, + {0x1a, 0x01, 0x0e, 0x0c, "1 Coin 2 Credits" }, + {0x1a, 0x01, 0x0e, 0x0a, "1 Coin 3 Credits" }, + {0x1a, 0x01, 0x0e, 0x08, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x1a, 0x01, 0x70, 0x00, "5 Coins 1 Credits" }, + {0x1a, 0x01, 0x70, 0x10, "4 Coins 1 Credits" }, + {0x1a, 0x01, 0x70, 0x20, "3 Coins 1 Credits" }, + {0x1a, 0x01, 0x70, 0x30, "2 Coins 1 Credits" }, + {0x1a, 0x01, 0x70, 0x70, "1 Coin 1 Credits" }, + {0x1a, 0x01, 0x70, 0x60, "1 Coin 2 Credits" }, + {0x1a, 0x01, 0x70, 0x50, "1 Coin 3 Credits" }, + {0x1a, 0x01, 0x70, 0x40, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x1a, 0x01, 0x80, 0x80, "1" }, + {0x1a, 0x01, 0x80, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1b, 0x01, 0x03, 0x03, "0" }, + {0x1b, 0x01, 0x03, 0x02, "1" }, + {0x1b, 0x01, 0x03, 0x01, "2" }, + {0x1b, 0x01, 0x03, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1b, 0x01, 0x04, 0x04, "Off" }, + {0x1b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Time" }, + {0x1b, 0x01, 0x08, 0x00, "32 s" }, + {0x1b, 0x01, 0x08, 0x08, "40 s" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1b, 0x01, 0x10, 0x00, "Off" }, + {0x1b, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x1b, 0x01, 0x20, 0x20, "Off" }, + {0x1b, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Join" }, + {0x1b, 0x01, 0x40, 0x00, "No" }, + {0x1b, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x1b, 0x01, 0x80, 0x00, "No" }, + {0x1b, 0x01, 0x80, 0x80, "Yes" }, + + {0 , 0xfe, 0 , 3, "Buttons" }, + {0x1c, 0x01, 0x03, 0x01, "3" }, + {0x1c, 0x01, 0x03, 0x02, "4" }, + {0x1c, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 2, "Vs. Rounds" }, + {0x1c, 0x01, 0x04, 0x00, "3" }, + {0x1c, 0x01, 0x04, 0x04, "5" }, + + {0 , 0xfe, 0 , 2, "Language (text)" }, + {0x1d, 0x01, 0x01, 0x00, "English" }, + {0x1d, 0x01, 0x01, 0x01, "Chinese" }, + + {0 , 0xfe, 0 , 2, "Language (char names)"}, + {0x1d, 0x01, 0x02, 0x00, "English" }, + {0x1d, 0x01, 0x02, 0x02, "Chinese" }, + + {0 , 0xfe, 0 , 2, "Title" }, + {0x1d, 0x01, 0x04, 0x00, "Alien Challenge" }, + {0x1d, 0x01, 0x04, 0x04, "Round House Rumble" }, +}; + +STDDIPINFO(Aliencha) + +static struct BurnDIPInfo AlienchacDIPList[] = { + {0x1d, 0xff, 0xff, 0x03, NULL }, +}; + +STDDIPINFOEXT(Alienchac, Aliencha, Alienchac) + +static const short lordgun_gun_x_table[] = +{ + -100, 0x001,0x001,0x002,0x002,0x003,0x003,0x004,0x005,0x006,0x007,0x008,0x009,0x00A,0x00B,0x00C, + 0x00D,0x00E,0x00F,0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,0x018,0x019,0x01A,0x01B,0x01C, + 0x01D,0x01E,0x01F,0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,0x028,0x029,0x02A,0x02B,0x02C, + 0x02D,0x02E,0x02F,0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x038,0x039,0x03A,0x03B,0x03C, + 0x03D,0x03E,0x03F,0x040,0x041,0x043,0x044,0x045,0x046,0x047,0x048,0x049,0x04A,0x04B,0x04C,0x04E, + 0x04F,0x050,0x051,0x052,0x053,0x054,0x055,0x056,0x057,0x059,0x05A,0x05B,0x05C,0x05D,0x05E,0x05F, + 0x060,0x061,0x05A,0x063,0x065,0x066,0x067,0x068,0x069,0x06A,0x06B,0x06C,0x06D,0x06E,0x06F,0x071, + 0x072,0x074,0x075,0x077,0x078,0x07A,0x07B,0x07D,0x07E,0x080,0x081,0x083,0x085,0x087,0x089,0x08B, + 0x08D,0x08E,0x08F,0x090,0x092,0x093,0x095,0x097,0x098,0x099,0x09A,0x09B,0x09C,0x09D,0x09E,0x0A0, + 0x0A1,0x0A2,0x0A3,0x0A4,0x0A5,0x0A6,0x0A7,0x0A8,0x0A9,0x0AA,0x0AC,0x0AD,0x0AE,0x0AF,0x0B0,0x0B1, + 0x0B2,0x0B3,0x0B4,0x0B5,0x0B6,0x0B8,0x0B9,0x0BA,0x0BB,0x0BC,0x0BD,0x0BE,0x0BF,0x0C0,0x0C1,0x0C2, + 0x0C4,0x0C5,0x0C6,0x0C7,0x0C8,0x0C9,0x0CA,0x0CB,0x0CC,0x0CD,0x0CF,0x0D0,0x0D1,0x0D2,0x0D3,0x0D4, + 0x0D5,0x0D6,0x0D7,0x0D8,0x0D9,0x0DB,0x0DC,0x0DD,0x0DE,0x0DF,0x0E0,0x0E1,0x0E2,0x0E3,0x0E4,0x0E5, + 0x0E7,0x0E8,0x0E9,0x0EA,0x0EB,0x0EC,0x0ED,0x0EE,0x0EF,0x0F0,0x0F1,0x0F3,0x0F4,0x0F5,0x0F6,0x0F7, + 0x0F8,0x0F9,0x0FA,0x0FB,0x0FC,0x0FE,0x0FF,0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x108, + 0x10A,0x10B,0x10C,0x10D,0x10E,0x10F,0x110,0x111,0x112,0x113,0x114,0x116,0x117,0x118,0x119,0x11A, + 0x11B,0x11C,0x11D,0x11E,0x11F,0x120,0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x129,0x12A,0x12B, + 0x12C,0x12E,0x12F,0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x139,0x13A,0x13B,0x13C,0x13D, + 0x13E,0x13F,0x140,0x141,0x142,0x143,0x145,0x146,0x147,0x148,0x149,0x14A,0x14B,0x14C,0x14D,0x14E, + 0x14F,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,0x15A,0x15B,0x15D,0x15E,0x15F,0x160, + 0x161,0x162,0x163,0x164,0x165,0x166,0x167,0x169,0x16A,0x16B,0x16C,0x16D,0x16E,0x16F,0x170,0x171, + 0x172,0x174,0x175,0x176,0x177,0x178,0x179,0x17A,0x17B,0x17C,0x17D,0x17E,0x17F,0x180,0x181,0x182, + 0x183,0x184,0x185,0x186,0x187,0x188,0x189,0x18A,0x18B,0x18C,0x18D,0x18E,0x18F,0x190,0x191,0x192, + 0x193,0x194,0x195,0x196,0x197,0x198,0x199,0x19A,0x19B,0x19C,0x19D,0x19E,0x19F,0x1A0,0x1A1,0x1A2, + 0x1A3,0x1A4,0x1A5,0x1A6,0x1A7,0x1A8,0x1A9,0x1AA,0x1AB,0x1AC,0x1AD,0x1AE,0x1AF,0x1B0,0x1B1,0x1B2, + 0x1B3,0x1B4,0x1B5,0x1B6,0x1B7,0x1B8,0x1B9,0x1BA,0x1BB,0x1BC,0x1BD,0x1BE,0x1BF,0x1BF +}; + +static void lordgun_update_gun(INT32 i) +{ + INT32 x = DrvAnalogInput[i] - 0x3c; + + lordgun_gun_hw_x[i] = DrvAnalogInput[i]; + lordgun_gun_hw_y[i] = DrvAnalogInput[i+2]; + + if ((x < 0) || (x > (INT32)(sizeof(lordgun_gun_x_table)/sizeof(lordgun_gun_x_table[0]))) ) + x = 0; + + INT32 scrx = lordgun_gun_x_table[x]; + INT32 scry = DrvAnalogInput[i+2]; + + if ((scrx < 0) || (scrx >= nScreenWidth) || (scry < 0) || (scry > nScreenHeight)) { + lordgun_gun_hw_x[i] = lordgun_gun_hw_y[i] = 0; + } +} + +void __fastcall lordgun_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x502000: + scrollx[0] = data; + return; + + case 0x502200: + scrollx[1] = data; + return; + + case 0x502400: + scrollx[2] = data; + return; + + case 0x502600: + scrollx[3] = data; + return; + + case 0x502800: + scrolly[0] = data; + return; + + case 0x502a00: + scrolly[1] = data; + return; + + case 0x502c00: + scrolly[2] = data; + return; + + case 0x502e00: + scrolly[3] = data; + return; + + case 0x503000: + priority[0] = data; + return; + + case 0x504000: + soundlatch[0] = data >> 8; + soundlatch[1] = data; + ZetNmi(); + return; + + case 0x506000: + case 0x506002: + case 0x506004: + case 0x506006: + ppi8255_w(0, (address >> 1) & 3, data); + return; + + case 0x508000: + case 0x508002: + case 0x508004: + case 0x508006: + ppi8255_w(1, (address >> 1) & 3, data); + return; + } +} + +void __fastcall lordgun_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ +// address = data; // kill warnings... +} + +UINT16 __fastcall lordgun_read_word(UINT32 address) +{ + switch (address) + { + case 0x503800: + return lordgun_gun_hw_x[0]; + + case 0x503a00: + return lordgun_gun_hw_x[1]; + + case 0x503c00: + return lordgun_gun_hw_y[0]; + + case 0x503e00: + return lordgun_gun_hw_y[1]; + + case 0x506000: + case 0x506002: + case 0x506004: + case 0x506006: + return ppi8255_r(0, (address >> 1) & 3); + + case 0x508000: + case 0x508002: + case 0x508004: + case 0x508006: + return ppi8255_r(1, (address >> 1) & 3); + } + + return 0; +} + +UINT8 __fastcall lordgun_read_byte(UINT32 address) +{ + switch (address) + { + case 0x506001: + case 0x506003: + case 0x506005: + case 0x506007: + return ppi8255_r(0, (address >> 1) & 3); + + case 0x508001: + case 0x508003: + case 0x508005: + case 0x508007: + return ppi8255_r(1, (address >> 1) & 3); + } + + return 0; +} + +static void set_oki_bank(INT32 bank) +{ + if (*okibank != (bank & 0x02)) { + *okibank = bank & 0x02; + + memcpy (DrvSndROM0, DrvSndROM0 + 0x40000 + *okibank * 0x40000, 0x40000); + } +} + +void __fastcall lordgun_sound_write_port(UINT16 port, UINT8 data) +{ + switch (port) + { + case 0x1000: // lordgun + case 0x1001: + BurnYM3812Write(port & 1, data); + return; + + case 0x2000: // lordgun + MSM6295Command(0, data); + return; + + case 0x6000: // lordgun + set_oki_bank(data); + return; + + case 0x7000: // aliencha + case 0x7001: + case 0x7002: + BurnYMF278BSelectRegister(port & 3, data); + return; + + case 0x7003: + case 0x7004: + case 0x7005: + BurnYMF278BWriteRegister(port & 3, data); + return; + + case 0x7400: // aliencha + MSM6295Command(0, data); + return; + + case 0x7800: // aliencha + MSM6295Command(1, data); + return; + } +} + +UINT8 __fastcall lordgun_sound_read_port(UINT16 port) +{ + switch (port) + { + case 0x2000: // lordgun + return MSM6295ReadStatus(0); + + case 0x3000: + return soundlatch[0]; + + case 0x4000: + return soundlatch[1]; + + case 0x7000: // aliencha + return BurnYMF278BReadStatus(); + + case 0x7400: // aliencha + return MSM6295ReadStatus(0); + + case 0x7800: // aliencha + return MSM6295ReadStatus(1); + } + + return 0; +} + +// ppi8255 handlers + +static void aliencha_dip_select(UINT8 data) +{ + aliencha_dip_sel = data; +} + +static UINT8 lordgun_dip_read() +{ + return (DrvDips[0] & 0x4f) | (EEPROMRead() ? 0x80 : 0) | (DrvInputs[4] & 0x30); +} + +static void lordgun_eeprom_write(UINT8 data) +{ + static INT32 old; + + for (INT32 i = 0; i < 2; i++) + if ((data & (0x04 << i)) && !(old & (0x04 << i))) + lordgun_update_gun(i); + + // coin counter 0x01 (0) + + EEPROMWrite((data & 0x20), (data & 0x10), (data & 0x40)); + + lordgun_whitescreen = data & 0x80; + + old = data; +} + +static void aliencha_eeprom_write(UINT8 data) +{ + lordgun_whitescreen = !(data & 0x02); + + // coin counters 0x08 (0) and 0x10 (1) + + EEPROMWrite((data & 0x40), (data & 0x20), (data & 0x80)); +} + +static UINT8 lordgun_start1_read() { return DrvInputs[0]; } +static UINT8 lordgun_start2_read() { return DrvInputs[1]; } +static UINT8 lordgun_service_read(){ return DrvInputs[2]; } +static UINT8 lordgun_coin_read() { return DrvInputs[3]; } + +static UINT8 aliencha_service_read(){ return (DrvInputs[2] & 0xfe) | (EEPROMRead() ? 0x01 : 0); } // aliencha eeprom read... + +static UINT8 aliencha_dip_read() +{ + switch (aliencha_dip_sel & 0x70) { + case 0x30: return DrvDips[0]; + case 0x60: return DrvDips[1]; + case 0x50: return DrvDips[2]; + } + return 0xff; +} + +// sound irq / timing handlers + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + ZetSetIRQLine(0, nStatus ? ZET_IRQSTATUS_ACK : ZET_IRQSTATUS_NONE); +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 5000000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYMF278BReset(); // aliencha + BurnYM3812Reset(); + MSM6295Reset(0); + MSM6295Reset(1); // aliencha + + *okibank = -1; + set_oki_bank(0); // lordgun + + EEPROMReset(); + + aliencha_dip_sel = 0; + lordgun_whitescreen = 0; + + // rom hacks + if (!strncmp(BurnDrvGetTextA(DRV_NAME), "aliencha", 8)) { + *((UINT16*)(Drv68KROM + 0x00a34)) = 0x7000 | ((DrvDips[3] >> 0) & 1); // text language + *((UINT16*)(Drv68KROM + 0x00a38)) = 0x7000 | ((DrvDips[3] >> 1) & 1); // character name language + *((UINT16*)(Drv68KROM + 0x00a3c)) = 0x7000 | ((DrvDips[3] >> 2) & 1); // title + } else { + + UINT8 lordgun_eepromdata[48] = { + 0xFF, 0x83, 0x5F, 0xFF, 0xFF, 0xBF, 0x14, 0xB7, 0xA3, 0xA4, 0x80, 0x29, 0x37, 0xA6, 0x32, 0x39, + 0x37, 0x90, 0x10, 0x33, 0xBA, 0xA3, 0x00, 0x37, 0x01, 0x00, 0xFF, 0xFF, 0x03, 0x42, 0xFF, 0xFF, + 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + if (EEPROMAvailable() == 0) { + EEPROMFill(lordgun_eepromdata, 0, 48); + } + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x200000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x800000; + DrvGfxROM2 = Next; Next += 0x800000; + DrvGfxROM3 = Next; Next += 0x1000000; + + DrvTransTable[0]= Next; Next += (0x0400000 / ( 8 * 8)); + DrvTransTable[1]= Next; Next += (0x0800000 / (16 * 16)); + DrvTransTable[2]= Next; Next += (0x0800000 / (32 * 32)); + DrvTransTable[3]= Next; Next += (0x1000000 / (16 * 16)); + DrvTransTable[4]= Next; Next += (0x0800000 / (16 * 16)) * 16; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x040000; + DrvSndROM2 = Next; Next += 0x200000; + + DrvPalette = (UINT32*)Next; Next += (0x0800 + 1) * sizeof(UINT32); + + draw_bitmap[0] = (UINT16*)Next; Next += 448 * 240 * 2; + draw_bitmap[1] = (UINT16*)Next; Next += 448 * 240 * 2; + draw_bitmap[2] = (UINT16*)Next; Next += 448 * 240 * 2; + draw_bitmap[3] = (UINT16*)Next; Next += 448 * 240 * 2; + draw_bitmap[4] = (UINT16*)Next; Next += 448 * 240 * 2; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPriRAM = Next; Next += 0x010000; + DrvVidRAM0 = Next; Next += 0x010000; + DrvVidRAM1 = Next; Next += 0x004000; + DrvVidRAM2 = Next; Next += 0x004000; + DrvVidRAM3 = Next; Next += 0x002000; + DrvScrRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + DrvProtRAM = Next; Next += 0x000400; + DrvPalRAM = Next; Next += 0x001000; + + DrvZ80RAM = Next; Next += 0x001000; + + scrollx = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + scrolly = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + priority = (UINT16*)Next; Next += 0x000001 * sizeof(UINT16); + + soundlatch = Next; Next += 0x000002; + + okibank = (INT8*)Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvSetTransTab(UINT8 *gfx, INT32 tab, INT32 len, INT32 size) +{ + for (INT32 i = 0; i < len; i+= (size * size)) + { + DrvTransTable[tab][i/(size*size)] = 1; // transparent + + for (INT32 j = 0; j < (size * size); j++) { + if (gfx[i + j] != 0x3f) { + DrvTransTable[tab][i/(size*size)] = 0; + break; + } + } + } +} + +static void DrvGfxDecode(UINT8 *gfxsrc, UINT8 *gfxdest, INT32 len, INT32 size) +{ + INT32 Planes[6] = { + (((len * 8) / 3) * 2) + 8, (((len * 8) / 3) * 2) + 0, + (((len * 8) / 3) * 1) + 8, (((len * 8) / 3) * 1) + 0, + (((len * 8) / 3) * 0) + 8, (((len * 8) / 3) * 0) + 0 + }; + + INT32 XOffs1[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 }; + INT32 XOffs2[32] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, + 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, + 0x600, 0x601, 0x602, 0x603, 0x604, 0x605, 0x606, 0x607 }; + INT32 YOffs[32] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0, + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, + 0x180, 0x190, 0x1a0, 0x1b0, 0x1c0, 0x1d0, 0x1e0, 0x1f0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, gfxsrc, len); + + GfxDecode(((len * 8) / 6) / (size*size), 6, size, size, Planes, (size == 32) ? XOffs2 : XOffs1, YOffs, (size*size*2), tmp, gfxdest); + + BurnFree (tmp); +} + +static INT32 DrvInit(INT32 (*pInitCallback)(), INT32 lordgun) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pInitCallback) { + if (pInitCallback()) return 1; + } + + DrvGfxDecode(DrvGfxROM0, DrvGfxROM0, 0x300000, 8); + DrvGfxDecode(DrvGfxROM2, DrvGfxROM1, 0x600000, 16); + DrvGfxDecode(DrvGfxROM2, DrvGfxROM2, 0x600000, 32); + DrvGfxDecode(DrvGfxROM3, DrvGfxROM3, 0xc00000, 16); + DrvSetTransTab(DrvGfxROM0, 0, 0x0400000, 8); + DrvSetTransTab(DrvGfxROM1, 1, 0x0800000, 16); + DrvSetTransTab(DrvGfxROM2, 2, 0x0800000, 32); + DrvSetTransTab(DrvGfxROM3, 3, 0x1000000, 16); + DrvSetTransTab(DrvGfxROM1, 4, 0x0800000, 16/4); // for line scroll + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvPriRAM, 0x210000, 0x21ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x310000, 0x313fff, SM_RAM); + SekMapMemory(DrvVidRAM2 , 0x314000, 0x317fff, SM_RAM); + SekMapMemory(DrvVidRAM3, 0x318000, 0x319fff, SM_RAM); + SekMapMemory(DrvScrRAM, 0x31c000, 0x31c7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x400000, 0x4007ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x500000, 0x500fff, SM_RAM); + SekMapMemory(DrvProtRAM, 0x50a800, 0x50abff, SM_RAM); // 900-9ff (lordgun) + SekMapMemory(DrvProtRAM, 0x50b800, 0x50bbff, SM_RAM); // 900-9ff (aliencha) + SekSetWriteWordHandler(0, lordgun_write_word); + SekSetWriteByteHandler(0, lordgun_write_byte); + SekSetReadWordHandler(0, lordgun_read_word); + SekSetReadByteHandler(0, lordgun_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(lordgun_sound_write_port); + ZetSetInHandler(lordgun_sound_read_port); + ZetMemEnd(); + ZetClose(); + + // aliencha + BurnYMF278BInit(0, DrvSndROM2, &DrvFMIRQHandler, DrvSynchroniseStream); + BurnTimerAttachZet(5000000); + + // lordgun + BurnYM3812Init(3579545, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(5000000); + + MSM6295Init(0, 1000000 / 132, 100, 1); + MSM6295Init(1, 1000000 / 132, 100, 1); // aliencha + + ppi8255_init(2); + if (lordgun) { + PPI0PortReadA = lordgun_dip_read; + PPI0PortWriteB = lordgun_eeprom_write; + PPI0PortReadC = lordgun_service_read; + } else { + PPI0PortReadA = aliencha_dip_read; + PPI0PortReadC = aliencha_service_read; + PPI0PortWriteB = aliencha_eeprom_write; + PPI0PortWriteC = aliencha_dip_select; + } + + PPI1PortReadA = lordgun_start1_read; + PPI1PortReadB = lordgun_start2_read; + PPI1PortReadC = lordgun_coin_read; + + EEPROMInit(&eeprom_interface_93C46); + + GenericTilesInit(); + + BurnGunInit(2, true); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYMF278BExit(); // aliencha + BurnYM3812Exit(); + MSM6295Exit(0); + MSM6295Exit(1); // aliencha + + ppi8255_exit(); + BurnGunExit(); + + SekExit(); + ZetExit(); + + EEPROMExit(); + + BurnFree (AllMem); + + return 0; +} + +static INT32 lordgunLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x600000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x800000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0xa00000, 14, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 15, 1)) return 1; + + UINT16 *rom = (UINT16*)Drv68KROM; + + for (INT32 i = 0; i < 0x100000/2; i++) { + if ((i & 0x0120) == 0x0100 || (i & 0x0a00) == 0x0800) + rom[i] ^= 0x0010; + } + + rom[0x14832/2] = 0x6000; // 014832: 6700 0006 beq $1483a (protection) + rom[0x1587e/2] = 0x6010; // 01587E: 6710 beq $15890 (rom check) + + return 0; +} + +static INT32 alienchaLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + BurnByteswap(Drv68KROM, 0x200000); + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x800000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 12, 1)) return 1; + + if (BurnLoadRom(DrvSndROM2 + 0x000000, 13, 1)) return 1; + + UINT16 *rom = (UINT16*)Drv68KROM; + + rom[0x0A558/2] = 0x6012; // 0A558 beq.s $A56C + rom[0x0A8DC/2] = 0x6012; // 0A8DC beq.s $A8F0 + rom[0x0AC92/2] = 0x6012; // 0AC92 beq.s $ACA6 + rom[0x124CC/2] = 0x6012; // 124CC beq.s $124E0 + rom[0x12850/2] = 0x6012; // 12850 beq.s $12864 + rom[0x12C06/2] = 0x6012; // 12C06 beq.s $12C1A + rom[0x1862A/2] = 0x6012; // 1862A beq.s $1863E + rom[0x189AE/2] = 0x6012; // 189AE beq.s $189C2 + rom[0x18D64/2] = 0x6012; // 18D64 beq.s $18D78 + rom[0x230FC/2] = 0x6012; // 230FC beq.s $23110 + rom[0x23480/2] = 0x6012; // 23480 beq.s $23494 + rom[0x23836/2] = 0x6012; // 23836 beq.s $2384A + rom[0x2BD0E/2] = 0x6012; // 2BD0E beq.s $2BD22 + rom[0x2C092/2] = 0x6012; // 2C092 beq.s $2C0A6 + rom[0x2C448/2] = 0x6012; // 2C448 beq.s $2C45C + + return 0; +} + +static INT32 alienchacLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + BurnByteswap(Drv68KROM, 0x200000); + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 2, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x800000, 12, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 13, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 14, 1)) return 1; + + if (BurnLoadRom(DrvSndROM2 + 0x000000, 15, 1)) return 1; + + UINT16 *rom = (UINT16*)Drv68KROM; + + rom[0x0A550/2] = 0x6012; // 0A558 beq.s $A564 + rom[0x0A8D4/2] = 0x6012; // 0A8D4 beq.s $A8E8 + rom[0x0AC8A/2] = 0x6012; // 0AC8A beq.s $AC9E + rom[0x124B8/2] = 0x6012; // 124B8 beq.s $124CC + rom[0x1283C/2] = 0x6012; // 1283C beq.s $12850 + rom[0x12BF2/2] = 0x6012; // 12BF2 beq.s $12C06 + rom[0x18616/2] = 0x6012; // 18616 beq.s $1862A + rom[0x1899A/2] = 0x6012; // 1899A beq.s $189AE + rom[0x18D50/2] = 0x6012; // 18D50 beq.s $18D64 + rom[0x230E8/2] = 0x6012; // 230E8 beq.s $230FC + rom[0x2346C/2] = 0x6012; // 2346C beq.s $23480 + rom[0x23822/2] = 0x6012; // 23822 beq.s $23822 + rom[0x2BCFA/2] = 0x6012; // 2BCFA beq.s $2BD0E + rom[0x2C07E/2] = 0x6012; // 2C07E beq.s $2C092 + rom[0x2C434/2] = 0x6012; // 2C434 beq.s $2C448 + + return 0; +} + +static void draw_layer_linescroll() +{ + UINT16 *vram = (UINT16*)DrvVidRAM1; + UINT16 *sram = (UINT16*)DrvScrRAM; + UINT16 *dest = draw_bitmap[1]; + + for (INT32 y = 0; y < nScreenHeight; y++, dest += nScreenWidth) + { + INT32 yscroll = (scrolly[1] + y) & 0x1ff; + + for (INT32 x = 0; x < nScreenWidth + 16; x+=16) { + + INT32 xscroll = (scrollx[1] + sram[y * 2 + 1] + x) & 0x7ff; + + INT32 ofst = (((yscroll >> 4) << 7) | (xscroll >> 4)) << 1; + + INT32 attr = vram[ofst]; + INT32 code = vram[ofst + 1] & 0x7fff; + INT32 pri = (attr & 0x0e00) >> 9; + + INT32 flipx = attr & 0x8000; + INT32 flipy = attr & 0x4000; + + INT32 color = ((attr & 0x0070) << 2)+0x600+pri*0x800; + + { + UINT8 *gfx = DrvGfxROM1 + (code << 8); + + if (flipy) gfx += ((yscroll & 0x0f)^0xf) << 4; + else gfx += ((yscroll & 0x0f) ) << 4; + + if (DrvTransTable[4][(gfx-DrvGfxROM1)/16]) continue; + + if (flipx) flipx = 0x0f; + + for (INT32 xx = 0, sx = x - (xscroll & 0x0f); xx < 16; xx++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[xx^flipx]; + + if (pxl == 0x3f) continue; + + dest[sx] = pxl | color; + } + } + } + } +} + +static void draw_layer(UINT8 *ram, UINT8 *gfx, INT32 size, INT32 wide, INT32 high, INT32 color_offset, INT32 color_and, INT32 layer) +{ + INT32 twidth = wide * size; + INT32 theight = high * size; + + INT32 code_and = (size == 32) ? 0x1fff : ((size == 16) ? 0x7fff : 0xffff); + + UINT16 *vram = (UINT16*)ram; + + for (INT32 sy = 0, offs = 0; sy < high * size; sy+=size) + { + for (INT32 sx = 0; sx < wide * size; sx+=size, offs++) + { + INT32 code = vram[offs * 2 + 1] & code_and; + if (DrvTransTable[layer][code]) continue; // transparent + + INT32 attr = vram[offs * 2 + 0]; + + INT32 prio = (attr >> 9) & 0x07; + INT32 color= ((attr >> 4) & color_and) + color_offset / 0x40 + prio * 0x800 / 0x40; + + INT32 flipx= attr & 0x8000; + INT32 flipy= attr & 0x4000; + + INT32 xx = sx - (scrollx[layer] % twidth); + if (xx < (0 - (size - 1))) xx += twidth; + + INT32 yy = sy - (scrolly[layer] % theight); + if (yy < (0 - (size - 1))) yy += theight; + + if (xx >= nScreenWidth || yy >= nScreenHeight) continue; + + if (flipy) { + if (flipx) { + RenderCustomTile_Mask_FlipXY_Clip(draw_bitmap[layer], size, size, code, xx, yy, color, 6, 0x3f, 0, gfx); + } else { + RenderCustomTile_Mask_FlipY_Clip(draw_bitmap[layer], size, size, code, xx, yy, color, 6, 0x3f, 0, gfx); + } + } else { + if (flipx) { + RenderCustomTile_Mask_FlipX_Clip(draw_bitmap[layer], size, size, code, xx, yy, color, 6, 0x3f, 0, gfx); + } else { + RenderCustomTile_Mask_Clip(draw_bitmap[layer], size, size, code, xx, yy, color, 6, 0x3f, 0, gfx); + } + } + } + } +} + +static void draw_sprites() +{ + UINT16 *sprite = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x800 / 2; offs += 4) + { + INT32 x0, x1, dx, y0, y1, dy; + + INT32 attr = sprite[offs + 1]; + if (attr & 0x0100) break; + + INT32 sy = sprite[offs + 0]; + INT32 code = sprite[offs + 2]; + INT32 sx = sprite[offs + 3]; + INT32 flipx = (attr & 0x8000); + INT32 flipy = (attr & 0x4000); + INT32 pri = (attr & 0x0e00) >> 9; + INT32 color = (attr & 0x00f0) >> 4; + INT32 nx = (attr & 0x000f) + 1; + INT32 ny = ((sy & 0xf000) >> 12) + 1; + + if (flipx) { x0 = nx - 1; x1 = -1; dx = -1; } + else { x0 = 0; x1 = nx; dx = +1; } + + if (flipy) { y0 = ny - 1; y1 = -1; dy = -1; } + else { y0 = 0; y1 = ny; dy = +1; } + + sx -= 0x18; + sy = (sy & 0x7ff) - (sy & 0x800); + + for (INT32 y = y0; y != y1; y += dy, code += 1 - 0x10 * nx) + { + for (INT32 x = x0; x != x1; x += dx, code += 0x10) + { + if (DrvTransTable[3][code]) continue; + + if (flipy) { + if (flipx) { + RenderCustomTile_Mask_FlipXY_Clip(draw_bitmap[4], 16, 16, code, sx + x * 0x10, sy + y * 0x10, color + pri * 0x800/0x40, 6, 0x3f, 0, DrvGfxROM3); + } else { + RenderCustomTile_Mask_FlipY_Clip(draw_bitmap[4], 16, 16, code, sx + x * 0x10, sy + y * 0x10, color + pri * 0x800/0x40, 6, 0x3f, 0, DrvGfxROM3); + } + } else { + if (flipx) { + RenderCustomTile_Mask_FlipX_Clip(draw_bitmap[4], 16, 16, code, sx + x * 0x10, sy + y * 0x10, color + pri * 0x800/0x40, 6, 0x3f, 0, DrvGfxROM3); + } else { + RenderCustomTile_Mask_Clip(draw_bitmap[4], 16, 16, code, sx + x * 0x10, sy + y * 0x10, color + pri * 0x800/0x40, 6, 0x3f, 0, DrvGfxROM3); + } + } + } + } + } +} + +static void copy_layers() +{ + const UINT8 pri2layer[8] = { 0, 0, 0, 4, 3, 0, 1, 2 }; + const UINT8 layerpri[5] = { 0, 1, 2, 4, 3 }; + + UINT16 *dest = pTransDraw; + UINT16 *source[5] = { draw_bitmap[0], draw_bitmap[1], draw_bitmap[2], draw_bitmap[3], draw_bitmap[4] }; + UINT16 *pri_ram = (UINT16*)DrvPriRAM; + + for (INT32 y = 0; y < nScreenHeight; y++) + { + for (INT32 x = 0; x < nScreenWidth; x++) + { + UINT16 pens[5]; + INT32 pri_addr = 0; + + for (INT32 l = 0; l < 5; l++) { + pens[l] = *source[l]++; + if (pens[l] == 0x3f) pri_addr |= 1 << layerpri[l]; + } + + pri_addr |= (pens[1] >> 11) << 5; + pri_addr |= (pens[4] >> 11) << 8; + pri_addr |= (pens[0] >> 11) << 11; + pri_addr |= (pens[3] >> 11) << 14; + + *dest++ = pens[pri2layer[pri_ram[pri_addr & 0x7fff] & 7]] & 0x7ff; + } + } +} + +static void DrvPaletteRecalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x1000 / 2; i++) { + INT32 r = (p[i] >> 0) & 0x0f; + INT32 g = (p[i] >> 4) & 0x0f; + INT32 b = (p[i] >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + + DrvPalette[0x0800] = BurnHighCol(0xff, 0xff, 0xff, 0); // white +} + +static INT32 DrvDraw() +{ + DrvPaletteRecalc(); + + if (lordgun_whitescreen) { + for (INT32 o = 0; o < nScreenWidth * nScreenHeight; o++) { + pTransDraw[o] = 0x800; // white!! + } + + BurnTransferCopy(DrvPalette); + return 0; + } + + for (INT32 o = 0; o < nScreenWidth * nScreenHeight; o++) { + draw_bitmap[0][o] = draw_bitmap[1][o] = draw_bitmap[2][o] = draw_bitmap[3][o] = draw_bitmap[4][o] = 0x003f; + } + + INT32 line_enable = 0; + { + UINT16 *rs = (UINT16*)DrvScrRAM; + for (INT32 i = 0; i < nScreenHeight * 2; i+=2) { + if ((rs[i + 1] & 0x7ff) != (rs[1] & 0x7ff)) { + line_enable = 1; + break; + } + } + } + + draw_layer(DrvVidRAM0, DrvGfxROM0, 8, 0x100, 0x040, 0x500, 0x03, 0); + if (line_enable == 0) { + draw_layer(DrvVidRAM1, DrvGfxROM1, 16, 0x080, 0x020, 0x600, 0x07, 1); + } else { + draw_layer_linescroll(); + } + draw_layer(DrvVidRAM2, DrvGfxROM2, 32, 0x040, 0x010, 0x700, 0x03, 2); + draw_layer(DrvVidRAM3, DrvGfxROM0, 8, 0x040, 0x020, 0x400, 0x0f, 3); + draw_sprites(); + + copy_layers(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 lordgunDraw() +{ + DrvDraw(); + + for (INT32 i = 0; i < BurnDrvGetMaxPlayers(); i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } + + return 0; +} + +static inline void compile_inputs() +{ + memset (DrvInputs, 0xff, 5 * sizeof(INT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + + BurnGunMakeInputs(0, (INT16)DrvAxis[0], (INT16)DrvAxis[1]); + BurnGunMakeInputs(1, (INT16)DrvAxis[2], (INT16)DrvAxis[3]); + + float x0 = ((float)((BurnGunX[0] >> 8) + 8)) / 448 * 412; + float y0 = ((float)((BurnGunY[0] >> 8) + 8)) / 224 * 224; + float x1 = ((float)((BurnGunX[1] >> 8) + 8)) / 448 * 412; + float y1 = ((float)((BurnGunY[1] >> 8) + 8)) / 224 * 224; + DrvAnalogInput[0] = (UINT16)x0 + 0x3c; + DrvAnalogInput[2] = (UINT8)y0 + 0; + DrvAnalogInput[1] = (UINT16)x1 + 0x3c; + DrvAnalogInput[3] = (UINT8)y1 + 0; +} + +static INT32 lordgunFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + compile_inputs(); + + SekNewFrame(); + ZetNewFrame(); + + INT32 nTotalCycles[2] = { 10000000 / 60, 5000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + INT32 nInterleave = 50; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + nNext = (i + 1) * nTotalCycles[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + BurnTimerUpdateYM3812(i * (nTotalCycles[1] / nInterleave)); + } + + BurnTimerEndFrameYM3812(nTotalCycles[1]); + + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + lordgunDraw(); + } + + return 0; +} + +static INT32 alienchaFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + compile_inputs(); + + SekNewFrame(); + ZetNewFrame(); + + INT32 nInterleave = 1000; + + INT32 nCyclesTotal[2] = { 10000000 / 60, 5000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYMF278BUpdate(nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029708; + } + + if (nAction & ACB_VOLATILE) { + + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYMF278BScan(nAction, pnMin); + + BurnGunScan(); + EEPROMScan(nAction, pnMin); + + SCAN_VAR(aliencha_dip_sel); + SCAN_VAR(lordgun_whitescreen); + + SCAN_VAR(lordgun_gun_hw_x[0]); + SCAN_VAR(lordgun_gun_hw_y[0]); + SCAN_VAR(lordgun_gun_hw_x[1]); + SCAN_VAR(lordgun_gun_hw_y[1]); + } + + if (nAction & ACB_WRITE) { + INT32 bank = *okibank; + *okibank = -1; + set_oki_bank(bank); + } + + return 0; +} + + +// Lord of Gun (USA) + +static struct BurnRomInfo lordgunRomDesc[] = { + { "lordgun.10", 0x080000, 0xacda77ef, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "lordgun.4", 0x080000, 0xa1a61254, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "lordgun.90", 0x010000, 0xd59b5e28, 2 | BRF_PRG | BRF_ESS }, // 2 z80 code + + { "igst001.108", 0x100000, 0x36dd96f3, 3 | BRF_GRA }, // 3 8x8 tiles + { "igst002.114", 0x100000, 0x816a7665, 3 | BRF_GRA }, // 4 + { "igst003.119", 0x100000, 0xcbfee543, 3 | BRF_GRA }, // 5 + + { "igsb001.82", 0x200000, 0x3096de1c, 4 | BRF_GRA }, // 6 16x16 and 32x32 tiles + { "igsb002.91", 0x200000, 0x2234531e, 4 | BRF_GRA }, // 7 + { "igsb003.97", 0x200000, 0x6cbf21ac, 4 | BRF_GRA }, // 8 + + { "igsa001.14", 0x200000, 0x400abe33, 5 | BRF_GRA }, // 9 Sprites + { "igsa004.13", 0x200000, 0x52687264, 5 | BRF_GRA }, // 10 + { "igsa002.9", 0x200000, 0xa4810e38, 5 | BRF_GRA }, // 11 + { "igsa005.8", 0x200000, 0xe32e79e3, 5 | BRF_GRA }, // 12 + { "igsa003.3", 0x200000, 0x649e48d9, 5 | BRF_GRA }, // 13 + { "igsa006.2", 0x200000, 0x39288eb6, 5 | BRF_GRA }, // 14 + + { "lordgun.100", 0x080000, 0xb4e0fa07, 6 | BRF_SND }, // 15 OKI #0 Samples +}; + +STD_ROM_PICK(lordgun) +STD_ROM_FN(lordgun) + +static INT32 lordgunInit() +{ + return DrvInit(lordgunLoadRoms, 1); +} + +struct BurnDriver BurnDrvLordgun = { + "lordgun", NULL, NULL, NULL, "1994", + "Lord of Gun (USA)\0", "Imperfect graphics and sound", "IGS", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, lordgunRomInfo, lordgunRomName, NULL, NULL, LordgunInputInfo, LordgunDIPInfo, + lordgunInit, DrvExit, lordgunFrame, lordgunDraw, DrvScan, &DrvRecalc, 0x800, + 448, 224, 4, 3 +}; + +// Alien Challenge (World) + +static struct BurnRomInfo alienchaRomDesc[] = { + { "igsc0102.u81", 0x200000, 0xe3432be3, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "hfh_s.u86", 0x010000, 0x5728a9ed, 2 | BRF_PRG | BRF_ESS }, // 1 z80 code + + { "igst0101.u9", 0x100000, 0x2ce12d7b, 3 | BRF_GRA }, // 2 8x8 tiles + { "igst0102.u10", 0x100000, 0x542a76a0, 3 | BRF_GRA }, // 3 + { "igst0103.u11", 0x100000, 0xadf5698a, 3 | BRF_GRA }, // 4 + + { "igsb0101.u8", 0x200000, 0x5c995f7e, 4 | BRF_GRA }, // 5 16x16 and 32x32 tiles + { "igsb0102.u7", 0x200000, 0xa2ae9baf, 4 | BRF_GRA }, // 6 + { "igsb0103.u6", 0x200000, 0x11b927af, 4 | BRF_GRA }, // 7 + + { "igsa0101.u3", 0x400000, 0x374d07c4, 5 | BRF_GRA }, // 8 Sprites + { "igsa0102.u2", 0x400000, 0xdbeee7ac, 5 | BRF_GRA }, // 9 + { "igsa0103.u1", 0x400000, 0xe5f19041, 5 | BRF_GRA }, // 10 + + { "hfh_g.u65", 0x040000, 0xec469b57, 6 | BRF_SND }, // 11 OKI #0 Samples + + { "hfh_g.u66", 0x040000, 0x7cfcd98e, 7 | BRF_SND }, // 12 OKI #1 Samples + + { "yrw801-m", 0x200000, 0x2a9d8d43, 8 | BRF_SND }, // 13 YMF278b Samples +}; + +STD_ROM_PICK(aliencha) +STD_ROM_FN(aliencha) + +static INT32 alienchaInit() +{ + return DrvInit(alienchaLoadRoms, 0); +} + +struct BurnDriver BurnDrvAliencha = { + "aliencha", NULL, NULL, NULL, "1994", + "Alien Challenge (World)\0", "Imperfect sound", "IGS", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, alienchaRomInfo, alienchaRomName, NULL, NULL, AlienchaInputInfo, AlienchaDIPInfo, + alienchaInit, DrvExit, alienchaFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 448, 224, 4, 3 +}; + + +// Alien Challenge (China) + +static struct BurnRomInfo alienchacRomDesc[] = { + { "igsc0102.u81", 0x200000, 0xe3432be3, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "hfh_p.u80", 0x080000, 0x5175ebdc, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hfh_p.u79", 0x080000, 0x42ad978c, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "hfh_s.u86", 0x010000, 0x5728a9ed, 2 | BRF_PRG | BRF_ESS }, // 3 z80 code + + { "igst0101.u9", 0x100000, 0x2ce12d7b, 3 | BRF_GRA }, // 4 8x8 tiles + { "igst0102.u10", 0x100000, 0x542a76a0, 3 | BRF_GRA }, // 5 + { "igst0103.u11", 0x100000, 0xadf5698a, 3 | BRF_GRA }, // 6 + + { "igsb0101.u8", 0x200000, 0x5c995f7e, 4 | BRF_GRA }, // 7 16x16 and 32x32 tiles + { "igsb0102.u7", 0x200000, 0xa2ae9baf, 4 | BRF_GRA }, // 8 + { "igsb0103.u6", 0x200000, 0x11b927af, 4 | BRF_GRA }, // 9 + + { "igsa0101.u3", 0x400000, 0x374d07c4, 5 | BRF_GRA }, // 10 Sprites + { "igsa0102.u2", 0x400000, 0xdbeee7ac, 5 | BRF_GRA }, // 11 + { "igsa0103.u1", 0x400000, 0xe5f19041, 5 | BRF_GRA }, // 12 + + { "hfh_g.u65", 0x040000, 0xec469b57, 6 | BRF_SND }, // 11 OKI #0 Samples + + { "hfh_g.u66", 0x040000, 0x7cfcd98e, 7 | BRF_SND }, // 12 OKI #1 Samples + + { "yrw801-m", 0x200000, 0x2a9d8d43, 8 | BRF_SND }, // 13 YMF278b Samples +}; + +STD_ROM_PICK(alienchac) +STD_ROM_FN(alienchac) + +static INT32 alienchacInit() +{ + return DrvInit(alienchacLoadRoms, 0); +} + +struct BurnDriver BurnDrvAlienchac = { + "alienchac", "aliencha", NULL, NULL, "1994", + "Alien Challenge (China)\0", "Imperfect sound", "IGS", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, alienchacRomInfo, alienchacRomName, NULL, NULL, AlienchaInputInfo, AlienchacDIPInfo, + alienchacInit, DrvExit, alienchaFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 448, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_mcatadv.cpp b/src/burn/drivers/misc_post90s/d_mcatadv.cpp new file mode 100644 index 00000000..a51fe098 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_mcatadv.cpp @@ -0,0 +1,1181 @@ +// FB Alpha Face "LINDA" hardware driver module +// Based on MAME driver by Paul Priest and David Haywood + +#include "tiles_generic.h" +#include "burn_ym2610.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT32 *DrvPalette; + +static UINT8 *DrvPrioBitmap; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[ 2]; +static UINT16 DrvInputs[2]; +static UINT8 DrvReset; + +static UINT16 *DrvScrollRAM0; +static UINT16 *DrvScrollRAM1; +static UINT16 *DrvVidRegs; +static UINT16 *DrvVidRegBuf; + +static UINT8 *nDrvZ80Bank; +static UINT8 *soundlatch; +static UINT8 *soundlatch2; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesDone[2]; +static INT32 watchdog; + +static INT32 nGame; + +static struct BurnInputInfo McatadvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Mcatadv) + +static struct BurnDIPInfo McatadvDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x02, 0x02, "Off" }, +// {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x08, 0x08, "Mode 1" }, + {0x13, 0x01, 0x08, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits " }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits " }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits " }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 4 Credits " }, + + {0 , 0xfe, 0 , 7, "Coin B" }, + {0x13, 0x01, 0xc0, 0x00, "4 Coins 1 Credits " }, + {0x13, 0x01, 0xc0, 0x40, "3 Coins 1 Credits " }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits " }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits " }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits " }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits " }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 4 Credits " }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x0c, 0x04, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "8" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x14, 0x01, 0xc0, 0x40, "Upright 1 Player" }, + {0x14, 0x01, 0xc0, 0xc0, "Upright 2 Players" }, + {0x14, 0x01, 0xc0, 0x80, "Cocktail" }, +}; + +STDDIPINFO(Mcatadv) + +static struct BurnInputInfo NostInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 9, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Nost) + +static struct BurnDIPInfo NostDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x10, 0x01, 0x03, 0x02, "2" }, + {0x10, 0x01, 0x03, 0x03, "3" }, + {0x10, 0x01, 0x03, 0x01, "4" }, + {0x10, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x0c, 0x08, "Easy" }, + {0x10, 0x01, 0x0c, 0x0c, "Normal" }, + {0x10, 0x01, 0x0c, 0x04, "Hard" }, + {0x10, 0x01, 0x0c, 0x00, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x10, 0x01, 0x10, 0x10, "Off" }, +// {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x10, 0x01, 0x20, 0x00, "Off" }, + {0x10, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x10, 0x01, 0xc0, 0x80, "500k 1000k" }, + {0x10, 0x01, 0xc0, 0xc0, "800k 1500k" }, + {0x10, 0x01, 0xc0, 0x40, "1000k 2000k" }, + {0x10, 0x01, 0xc0, 0x00, "None" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x02, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x04, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 2 Credits " }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x07, 0x03, "2 Coins 3 Credits " }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin_B" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x10, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x20, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 2 Credits " }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x38, 0x18, "2 Coins 3 Credits " }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits " }, +}; + +STDDIPINFO(Nost) + +static inline void mcatadv_z80_sync() +{ +#if 0 + float nCycles = SekTotalCycles() * 1.0000; + nCycles /= nCyclesTotal[0]; + nCycles *= nCyclesTotal[1]; + nCycles -= nCyclesDone[1]; + if (nCycles > 0) { + nCyclesDone[1] += ZetRun((INT32)nCycles); + } +#endif +} + +static inline void palette_write(INT32 offset) +{ + UINT8 r,g,b; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = (data >> 5) & 0x1f; + r = (r << 3) | (r >> 2); + + g = (data >> 10) & 0x1f; + g = (g << 3) | (g >> 2); + + b = (data >> 0) & 0x1f; + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall mcatadv_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ + +} + +void __fastcall mcatadv_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x200000: + case 0x200002: + case 0x200004: + DrvScrollRAM0[(address & 6) >> 1] = data; + return; + + case 0x300000: + case 0x300002: + case 0x300004: + DrvScrollRAM1[(address & 6) >> 1] = data; + return; + + case 0xb00000: + case 0xb00002: + case 0xb00004: + case 0xb00006: + case 0xb00008: + case 0xb0000a: + case 0xb0000c: + case 0xb0000e: + DrvVidRegs[(address & 0x0e) >> 1] = data; + return; + + case 0xb00018: + watchdog = 0; + return; + + case 0xc00000: + { + mcatadv_z80_sync(); + + *soundlatch = data; + ZetNmi(); + } + return; + } +} + +UINT8 __fastcall mcatadv_read_byte(UINT32 address) +{ + switch (address) + { + case 0x800000: + return DrvInputs[0] >> 8; + + case 0x800001: + return DrvInputs[0] & 0xff; + + case 0x800002: + return DrvInputs[1] >> 8; + + case 0x800003: + return DrvInputs[1] & 0xff; + } + + return 0; +} + +UINT16 __fastcall mcatadv_read_word(UINT32 address) +{ + switch (address) + { + case 0x800000: + return DrvInputs[0]; + + case 0x800002: + return DrvInputs[1]; + + case 0xa00000: + return (DrvDips[0] << 8) | 0x00ff; + + case 0xa00002: + return (DrvDips[1] << 8) | 0x00ff; + + case 0xb0001e: + watchdog = 0; + return 0x0c00; + + case 0xc00000: + mcatadv_z80_sync(); + return *soundlatch2; + } + + return 0; +} + +static void sound_bankswitch(INT32 data) +{ + *nDrvZ80Bank = data; + + ZetMapArea(0x4000 << nGame, 0xbfff, 0, DrvZ80ROM + (data * 0x4000)); + ZetMapArea(0x4000 << nGame, 0xbfff, 2, DrvZ80ROM + (data * 0x4000)); +} + +void __fastcall mcatadv_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + BurnYM2610Write(address & 3, data); + return; + + case 0xf000: + sound_bankswitch(data); + return; + } +} + +UINT8 __fastcall mcatadv_sound_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + case 0xe002: + return BurnYM2610Read(address & 2); + } + + return 0; +} + +void __fastcall mcatadv_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + BurnYM2610Write(port & 3, data); + return; + + case 0x40: + sound_bankswitch(data); + return; + + case 0x80: + *soundlatch2 = data; + return; + } +} + +UINT8 __fastcall mcatadv_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x04: + case 0x05: + case 0x06: + case 0x07: + return BurnYM2610Read(port & 3); + + case 0x80: + return *soundlatch; + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 DrvGfxDecode() +{ + static INT32 Planes[4] = { 0, 1, 2, 3 }; + static INT32 XOffs[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; + static INT32 YOffs[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x280000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM1, 0x180000); + + GfxDecode(0x3000, 4, 16, 16, Planes, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x280000); + + GfxDecode(0x5000, 4, 16, 16, Planes, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x040000; + + DrvGfxROM0 = Next; Next += 0x600000; + DrvGfxROM1 = Next; Next += 0x300000; + DrvGfxROM2 = Next; Next += 0x500000; + + DrvSndROM = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x1001 * sizeof(UINT32); + + DrvPrioBitmap = Next; Next += 320 * 224; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvZ80RAM = Next; Next += 0x002000; + + DrvVidRAM0 = Next; Next += 0x002000; + DrvVidRAM1 = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x003000; + DrvSprRAM = Next; Next += 0x010000; + DrvSprBuf = Next; Next += 0x008000; + + DrvScrollRAM0 = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + DrvScrollRAM1 = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + DrvVidRegs = (UINT16*)Next; Next += 0x000008 * sizeof(UINT16); + DrvVidRegBuf = (UINT16*)Next; Next += 0x000008 * sizeof(UINT16); + + nDrvZ80Bank = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + sound_bankswitch(1); + ZetClose(); + + BurnYM2610Reset(); + + watchdog = 0; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x400000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x400001, 8, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 13, 1)) return 1; + + if (DrvZ80ROM[0x20000]) // Nostradamus + { + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 12, 1)) return 1; + + nGame = 1; + } + else + { + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 12, 1)) return 1; + + nGame = 0; + } + } + + DrvGfxDecode(); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x400000, 0x401fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x500000, 0x501fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x600000, 0x602fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x700000, 0x70ffff, SM_RAM); + SekSetWriteByteHandler(0, mcatadv_write_byte); + SekSetWriteWordHandler(0, mcatadv_write_word); + SekSetReadByteHandler(0, mcatadv_read_byte); + SekSetReadWordHandler(0, mcatadv_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM); + ZetSetWriteHandler(mcatadv_sound_write); + ZetSetReadHandler(mcatadv_sound_read); + ZetSetInHandler(mcatadv_sound_in); + ZetSetOutHandler(mcatadv_sound_out); + ZetMemEnd(); + ZetClose(); + + INT32 DrvSndROMLen = nGame ? 0x100000 : 0x80000; + BurnYM2610Init(8000000, DrvSndROM, &DrvSndROMLen, DrvSndROM, &DrvSndROMLen, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + BurnYM2610Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + UINT16 *source = (UINT16*)DrvSprBuf; + UINT16 *vidregram = DrvVidRegs; + UINT16 *vidregbuf = DrvVidRegBuf; + UINT16 *finish = source + 0x2000-4; + UINT8 *prio = DrvPrioBitmap; + INT32 global_x = vidregram[0]-0x184; + INT32 global_y = vidregram[1]-0x1f1; + + UINT16 *destline; + + INT32 xstart, xend, xinc; + INT32 ystart, yend, yinc; + + if (vidregbuf[2] == 0x0001) + { + source += 0x2000; + finish += 0x2000; + } + + while (source < finish) + { + INT32 attr = source[0]; + INT32 pri = attr >> 14; + INT32 pen = (attr & 0x3f00) >> 4; + INT32 tileno = source[1]; + INT32 x = source[2] & 0x03ff; + INT32 y = source[3] & 0x03ff; + INT32 flipy = attr & 0x0040; + INT32 flipx = attr & 0x0080; + + INT32 height = (source[3] & 0xf000) >> 8; + INT32 width = (source[2] & 0xf000) >> 8; + INT32 offset = tileno << 8; + + UINT8 *sprdata = DrvGfxROM0; + + INT32 drawxpos, drawypos; + INT32 xcnt,ycnt; + INT32 pix; + + if (x & 0x200) x-=0x400; + if (y & 0x200) y-=0x400; + + if (source[3] != source[0]) + { + if(!flipx) { xstart = 0; xend = width; xinc = 1; } + else { xstart = width-1; xend = -1; xinc = -1; } + if(!flipy) { ystart = 0; yend = height; yinc = 1; } + else { ystart = height-1; yend = -1; yinc = -1; } + + for (ycnt = ystart; ycnt != yend; ycnt += yinc) { + drawypos = y+ycnt-global_y; + + if ((drawypos >= 0) && (drawypos < 224)) { + destline = pTransDraw + drawypos * 320; + prio = DrvPrioBitmap + drawypos * 320; + + for (xcnt = xstart; xcnt != xend; xcnt += xinc) { + drawxpos = x+xcnt-global_x; + + if (drawxpos >= 0 && drawxpos < 320) { + if (prio[drawxpos] < pri) { + if (offset >= 0xa00000) offset = 0; + pix = sprdata[offset >> 1]; + + if (offset & 1) pix >>= 4; + pix &= 0x0f; + + if (pix && drawxpos >= 0 && drawxpos < 320) destline[drawxpos] = pix | pen; + } + } + + offset++; + } + } else { + offset += width; + } + } + } + source+=4; + } + + return; +} + +static void draw_background(UINT8 *vidramsrc, UINT8 *gfxbase, UINT16 *scroll, INT32 priority, INT32 max_tile) +{ + UINT16 *vidram = (UINT16*)vidramsrc; + UINT16 *dest = pTransDraw; + UINT8 *prio = DrvPrioBitmap; + + INT32 yscroll = ((scroll[1] & 0x1ff) - 0x1df) & 0x1ff; + INT32 xscroll = ((scroll[0] & 0x1ff) - 0x194) & 0x1ff; + + if (~scroll[1] & 0x4000 && ~scroll[0] & 0x4000) { // row by row + yscroll &= 0x1ff; + xscroll &= 0x1ff; + + for (INT32 y = 0; y < 239; y+=16) + { + for (INT32 x = 0; x < 335; x+=16) + { + INT32 sy = y - (yscroll & 0x0f); + INT32 sx = x - (xscroll & 0x0f); + if (sy < -15 || sx < -15 || sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 offs = (((yscroll+y)&0x1f0) << 2) | (((xscroll+x)&0x1f0)>>3); + + if ((vidram[offs] >> 14) != priority) continue; + + INT32 code = vidram[offs | 1]; + if (!code || code >= max_tile) continue; + INT32 color = ((vidram[offs] >> 8) & 0x3f) | ((scroll[2] & 3) << 6); + + { + color <<= 4; + + UINT8 *gfx = gfxbase + code * 0x100; + + for (INT32 vy = 0; vy < 16; vy++, sy++, gfx+=16) { + if (sy < 0) continue; + if (sy >= nScreenHeight) break; + + dest = pTransDraw + nScreenWidth * sy; + prio = DrvPrioBitmap + nScreenWidth * sy; + + for (INT32 vx = 0; vx < 16; vx++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[vx]; + + if (pxl) { + dest[sx] = pxl | color; + prio[sx] = priority; + } + } + + sx -= 16; + } + } + + //Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, gfxbase); + } + } + + return; + } + + for (INT32 y = 0; y < 224; y++, dest += 320, prio += 320) // line by line + { + INT32 scrollx = xscroll; + INT32 scrolly = (yscroll + y) & 0x1ff; + + if (scroll[1] & 0x4000) scrolly = vidram[0x0800 + (scrolly * 2) + 1] & 0x1ff; + if (scroll[0] & 0x4000) scrollx += vidram[0x0800 + (scrolly * 2) + 0]; + + INT32 srcy = (scrolly & 0x1ff) >> 4; + INT32 srcx = (scrollx & 0x1ff) >> 4; + + for (INT32 x = 0; x < 336; x+=16) + { + INT32 offs = ((srcy << 5) | ((srcx + (x >> 4)) & 0x1f)) << 1; + + if ((vidram[offs] >> 14) != priority) continue; + + INT32 code = vidram[offs | 1]; + if (!code || code >= max_tile) continue; + + INT32 color = ((vidram[offs] >> 4) & 0x3f0) | ((scroll[2] & 3) << 10); + + UINT8 *gfxsrc = gfxbase + (code << 8) + ((scrolly & 0x0f) << 4); + + for (INT32 dx = 0; dx < 16; dx++) + { + INT32 dst = (x + dx) - (scrollx & 0x0f); + if (dst < 0 || dst >= nScreenWidth) continue; + + if (gfxsrc[dx]) { + dest[dst] = color | gfxsrc[dx]; + prio[dst] = priority; + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x2000; i+=2) { + palette_write(i); + } + DrvPalette[0x1000] = 0; + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x1000; + DrvPrioBitmap[i] = 0; + } + + for (INT32 i = 0; i < 4; i++) + { + draw_background(DrvVidRAM0, DrvGfxROM1, DrvScrollRAM0, i, 0x3000); + draw_background(DrvVidRAM1, DrvGfxROM2, DrvScrollRAM1, i, 0x5000); + } + + draw_sprites(); + + memcpy (DrvSprBuf, DrvSprRAM, 0x08000); + memcpy (DrvVidRegBuf, DrvVidRegs, 0x08 * sizeof(UINT16)); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = 0xffff; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[0] ^= (nGame << 11); // nostradamus wants bit 11 off + } + + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[1 ] = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + watchdog++; + if (watchdog == 180) { + SekReset(); + ZetReset(); + watchdog = 0; + } + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + + SCAN_VAR(nCyclesDone[1]); + SCAN_VAR(watchdog); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + sound_bankswitch(*nDrvZ80Bank); + ZetClose(); + } + + return 0; +} + + +// Magical Cat Adventure + +static struct BurnRomInfo mcatadvRomDesc[] = { + { "mca-u30e", 0x080000, 0xc62fbb65, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "mca-u29e", 0x080000, 0xcf21227c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u9.bin", 0x020000, 0xfda05171, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "mca-u82.bin", 0x100000, 0x5f01d746, 3 | BRF_GRA }, // 3 Sprites + { "mca-u83.bin", 0x100000, 0x4e1be5a6, 3 | BRF_GRA }, // 4 + { "mca-u84.bin", 0x080000, 0xdf202790, 3 | BRF_GRA }, // 5 + { "mca-u85.bin", 0x080000, 0xa85771d2, 3 | BRF_GRA }, // 6 + { "mca-u86e", 0x080000, 0x017bf1da, 3 | BRF_GRA }, // 7 + { "mca-u87e", 0x080000, 0xbc9dc9b9, 3 | BRF_GRA }, // 8 + + { "mca-u58.bin", 0x080000, 0x3a8186e2, 4 | BRF_GRA }, // 9 Background Tiles + + { "mca-u60.bin", 0x100000, 0xc8942614, 5 | BRF_GRA }, // 10 Foreground Tiles + { "mca-u61.bin", 0x100000, 0x51af66c9, 5 | BRF_GRA }, // 11 + { "mca-u100", 0x080000, 0xb273f1b0, 5 | BRF_GRA }, // 12 + + { "mca-u53.bin", 0x080000, 0x64c76e05, 6 | BRF_SND }, // 13 YM2610 Samples +}; + +STD_ROM_PICK(mcatadv) +STD_ROM_FN(mcatadv) + +struct BurnDriver BurnDrvMcatadv = { + "mcatadv", NULL, NULL, NULL, "1993", + "Magical Cat Adventure\0", NULL, "Wintechno", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, mcatadvRomInfo, mcatadvRomName, NULL, NULL, McatadvInputInfo, McatadvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 320, 224, 4, 3 +}; + + +// Magical Cat Adventure (Japan) + +static struct BurnRomInfo mcatadvjRomDesc[] = { + { "u30.bin", 0x080000, 0x05762f42, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "u29.bin", 0x080000, 0x4c59d648, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u9.bin", 0x020000, 0xfda05171, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "mca-u82.bin", 0x100000, 0x5f01d746, 3 | BRF_GRA }, // 3 Sprites + { "mca-u83.bin", 0x100000, 0x4e1be5a6, 3 | BRF_GRA }, // 4 + { "mca-u84.bin", 0x080000, 0xdf202790, 3 | BRF_GRA }, // 5 + { "mca-u85.bin", 0x080000, 0xa85771d2, 3 | BRF_GRA }, // 6 + { "u86.bin", 0x080000, 0x2d3725ed, 3 | BRF_GRA }, // 7 + { "u87.bin", 0x080000, 0x4ddefe08, 3 | BRF_GRA }, // 8 + + { "mca-u58.bin", 0x080000, 0x3a8186e2, 4 | BRF_GRA }, // 9 Background Tiles + + { "mca-u60.bin", 0x100000, 0xc8942614, 5 | BRF_GRA }, // 10 Foreground Tiles + { "mca-u61.bin", 0x100000, 0x51af66c9, 5 | BRF_GRA }, // 11 + { "u100.bin", 0x080000, 0xe2c311da, 5 | BRF_GRA }, // 12 + + { "mca-u53.bin", 0x080000, 0x64c76e05, 6 | BRF_SND }, // 13 YM2610 Samples +}; + +STD_ROM_PICK(mcatadvj) +STD_ROM_FN(mcatadvj) + +struct BurnDriver BurnDrvMcatadvj = { + "mcatadvj", "mcatadv", NULL, NULL, "1993", + "Magical Cat Adventure (Japan)\0", NULL, "Wintechno", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, mcatadvjRomInfo, mcatadvjRomName, NULL, NULL, McatadvInputInfo, McatadvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 320, 224, 4, 3 +}; + + +// Catt (Japan) + +static struct BurnRomInfo cattRomDesc[] = { + { "catt-u30.bin", 0x080000, 0x8c921e1e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "catt-u29.bin", 0x080000, 0xe725af6d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u9.bin", 0x020000, 0xfda05171, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "mca-u82.bin", 0x100000, 0x5f01d746, 3 | BRF_GRA }, // 3 Sprites + { "mca-u83.bin", 0x100000, 0x4e1be5a6, 3 | BRF_GRA }, // 4 + { "u84.bin", 0x100000, 0x843fd624, 3 | BRF_GRA }, // 5 + { "u85.bin", 0x100000, 0x5ee7b628, 3 | BRF_GRA }, // 6 + { "mca-u86e", 0x080000, 0x017bf1da, 3 | BRF_GRA }, // 7 + { "mca-u87e", 0x080000, 0xbc9dc9b9, 3 | BRF_GRA }, // 8 + + { "u58.bin", 0x100000, 0x73c9343a, 4 | BRF_GRA }, // 9 Background Tiles + + { "mca-u60.bin", 0x100000, 0xc8942614, 5 | BRF_GRA }, // 10 Foreground Tiles + { "mca-u61.bin", 0x100000, 0x51af66c9, 5 | BRF_GRA }, // 11 + { "mca-u100", 0x080000, 0xb273f1b0, 5 | BRF_GRA }, // 12 + + { "u53.bin", 0x100000, 0x99f2a624, 6 | BRF_SND }, // 13 YM2610 Samples + + { "peel18cv8.u1", 0x000155, 0x00000000, 7 | BRF_NODUMP | BRF_OPT }, // 14 plds + { "gal16v8a.u10", 0x000117, 0x00000000, 7 | BRF_NODUMP | BRF_OPT }, // 15 +}; + +STD_ROM_PICK(catt) +STD_ROM_FN(catt) + +struct BurnDriver BurnDrvCatt = { + "catt", "mcatadv", NULL, NULL, "1993", + "Catt (Japan)\0", NULL, "Wintechno", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cattRomInfo, cattRomName, NULL, NULL, McatadvInputInfo, McatadvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 320, 224, 4, 3 +}; + + +// Nostradamus + +static struct BurnRomInfo nostRomDesc[] = { + { "nos-pe-u.bin", 0x080000, 0x4b080149, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "nos-po-u.bin", 0x080000, 0x9e3cd6d9, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "nos-ps.u9", 0x040000, 0x832551e9, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "nos-se-0.u82", 0x100000, 0x9d99108d, 3 | BRF_GRA }, // 3 Sprites + { "nos-so-0.u83", 0x100000, 0x7df0fc7e, 3 | BRF_GRA }, // 4 + { "nos-se-1.u84", 0x100000, 0xaad07607, 3 | BRF_GRA }, // 5 + { "nos-so-1.u85", 0x100000, 0x83d0012c, 3 | BRF_GRA }, // 6 + { "nos-se-2.u86", 0x080000, 0xd99e6005, 3 | BRF_GRA }, // 7 + { "nos-so-2.u87", 0x080000, 0xf60e8ef3, 3 | BRF_GRA }, // 8 + + { "nos-b0-0.u58", 0x100000, 0x0214b0f2, 4 | BRF_GRA }, // 9 Background Tiles + { "nos-b0-1.u59", 0x080000, 0x3f8b6b34, 4 | BRF_GRA }, // 10 + + { "nos-b1-0.u60", 0x100000, 0xba6fd0c7, 5 | BRF_GRA }, // 11 Foreground Tiles + { "nos-b1-1.u61", 0x080000, 0xdabd8009, 5 | BRF_GRA }, // 12 + + { "nossn-00.u53", 0x100000, 0x3bd1bcbc, 6 | BRF_SND }, // 13 YM2610 Samples +}; + +STD_ROM_PICK(nost) +STD_ROM_FN(nost) + +static void NostPatch() +{ + // Can also be fixed overclocking the z80 to 4250000 and enabling + // z80 sync, but is slow and breaks sound in Mcatadv. + *((UINT16*)(Drv68KROM + 0x000122)) = 0x0146; // Skip ROM Check +} + +static INT32 NostInit() +{ + INT32 nRet = DrvInit(); + + if (nRet == 0) { + NostPatch(); + } + + return nRet; +} + +struct BurnDriver BurnDrvNost = { + "nost", NULL, NULL, NULL, "1993", + "Nostradamus\0", NULL, "Face", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, nostRomInfo, nostRomName, NULL, NULL, NostInputInfo, NostDIPInfo, + NostInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 224, 320, 3, 4 +}; + + +// Nostradamus (Japan) + +static struct BurnRomInfo nostjRomDesc[] = { + { "nos-pe-j.u30", 0x080000, 0x4b080149, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "nos-po-j.u29", 0x080000, 0x7fe241de, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "nos-ps.u9", 0x040000, 0x832551e9, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "nos-se-0.u82", 0x100000, 0x9d99108d, 3 | BRF_GRA }, // 3 Sprites + { "nos-so-0.u83", 0x100000, 0x7df0fc7e, 3 | BRF_GRA }, // 4 + { "nos-se-1.u84", 0x100000, 0xaad07607, 3 | BRF_GRA }, // 5 + { "nos-so-1.u85", 0x100000, 0x83d0012c, 3 | BRF_GRA }, // 6 + { "nos-se-2.u86", 0x080000, 0xd99e6005, 3 | BRF_GRA }, // 7 + { "nos-so-2.u87", 0x080000, 0xf60e8ef3, 3 | BRF_GRA }, // 8 + + { "nos-b0-0.u58", 0x100000, 0x0214b0f2, 4 | BRF_GRA }, // 9 Background Tiles + { "nos-b0-1.u59", 0x080000, 0x3f8b6b34, 4 | BRF_GRA }, // 10 + + { "nos-b1-0.u60", 0x100000, 0xba6fd0c7, 5 | BRF_GRA }, // 11 Foreground Tiles + { "nos-b1-1.u61", 0x080000, 0xdabd8009, 5 | BRF_GRA }, // 12 + + { "nossn-00.u53", 0x100000, 0x3bd1bcbc, 6 | BRF_SND }, // 13 YM2610 Samples +}; + +STD_ROM_PICK(nostj) +STD_ROM_FN(nostj) + +struct BurnDriver BurnDrvNostj = { + "nostj", "nost", NULL, NULL, "1993", + "Nostradamus (Japan)\0", NULL, "Face", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, nostjRomInfo, nostjRomName, NULL, NULL, NostInputInfo, NostDIPInfo, + NostInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 224, 320, 3, 4 +}; + + +// Nostradamus (Korea) + +static struct BurnRomInfo nostkRomDesc[] = { + { "nos-pe-t.u30", 0x080000, 0xbee5fbc8, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "nos-po-t.u29", 0x080000, 0xf4736331, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "nos-ps.u9", 0x040000, 0x832551e9, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "nos-se-0.u82", 0x100000, 0x9d99108d, 3 | BRF_GRA }, // 3 Sprites + { "nos-so-0.u83", 0x100000, 0x7df0fc7e, 3 | BRF_GRA }, // 4 + { "nos-se-1.u84", 0x100000, 0xaad07607, 3 | BRF_GRA }, // 5 + { "nos-so-1.u85", 0x100000, 0x83d0012c, 3 | BRF_GRA }, // 6 + { "nos-se-2.u86", 0x080000, 0xd99e6005, 3 | BRF_GRA }, // 7 + { "nos-so-2.u87", 0x080000, 0xf60e8ef3, 3 | BRF_GRA }, // 8 + + { "nos-b0-0.u58", 0x100000, 0x0214b0f2, 4 | BRF_GRA }, // 9 Background Tiles + { "nos-b0-1.u59", 0x080000, 0x3f8b6b34, 4 | BRF_GRA }, // 10 + + { "nos-b1-0.u60", 0x100000, 0xba6fd0c7, 5 | BRF_GRA }, // 11 Foreground Tiles + { "nos-b1-1.u61", 0x080000, 0xdabd8009, 5 | BRF_GRA }, // 12 + + { "nossn-00.u53", 0x100000, 0x3bd1bcbc, 6 | BRF_SND }, // 13 YM2610 Samples +}; + +STD_ROM_PICK(nostk) +STD_ROM_FN(nostk) + +struct BurnDriver BurnDrvNostk = { + "nostk", "nost", NULL, NULL, "1993", + "Nostradamus (Korea)\0", NULL, "Face", "LINDA", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, nostkRomInfo, nostkRomName, NULL, NULL, NostInputInfo, NostDIPInfo, + NostInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1001, + 224, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_midas.cpp b/src/burn/drivers/misc_post90s/d_midas.cpp new file mode 100644 index 00000000..acdf41d6 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_midas.cpp @@ -0,0 +1,668 @@ +// FB Alpha Andamiro "Midas" hardware driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "eeprom.h" +#include "ymz280b.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvSprROM; +static UINT8 *DrvTxtROM; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvGfxRAM; +static UINT32 *DrvPalette; +static UINT8 *DrvSprTransTab; +static UINT8 *DrvTxtTransTab; +static UINT16 *DrvGfxRegs; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvJoy6[16]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT16 DrvInputs[6]; + +static INT32 DrvRecalc0 = 0; + +static short zoom_table[16][16]; + +static struct BurnInputInfo LivequizInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 8, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy6 + 10, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy6 + 11, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy6 + 8, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy6 + 9, "p1 fire 4" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 10, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 8, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy1 + 9, "p2 fire 4" }, + + {"P3 Start", BIT_DIGITAL, DrvJoy5 + 0, "p3 start" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 0, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 1, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy4 + 2, "p3 fire 3" }, + {"P3 Button 4", BIT_DIGITAL, DrvJoy4 + 3, "p3 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Livequiz) + +static struct BurnDIPInfo LivequizDIPList[] = +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Livequiz) + +inline static void palette_write(INT32 offs) +{ + DrvPalette[offs/4] = BurnHighCol(DrvPalRAM[offs + 0], DrvPalRAM[offs + 3], DrvPalRAM[offs + 2], 0); +} + +void __fastcall midas_write_byte(UINT32 address, UINT8 data) +{ + if (address >= 0xa00000 && address <= 0xa3ffff) { + DrvPalRAM[(address & 0x3ffff) ^ 1] = data; + palette_write(address & 0x3fffc); + return; + } + + switch (address) + { + case 0x9a0001: + EEPROMWrite(data & 0x02, data & 0x01, data & 0x04); + return; + + case 0xb80009: + YMZ280BSelectRegister(data); + return; + + case 0xb8000b: + YMZ280BWriteRegister(data); + return; + } +} + +void __fastcall midas_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0xa00000 && address <= 0xa3ffff) { + *((UINT16*)(DrvPalRAM + (address & 0x3fffe))) = data; + palette_write(address & 0x3fffc); + return; + } + + switch (address) + { + case 0x9c0000: + DrvGfxRegs[0] = data; + return; + + case 0x9c0002: + { + DrvGfxRegs[1] = data; + *((UINT16*)(DrvGfxRAM + (DrvGfxRegs[0] << 1))) = data; + DrvGfxRegs[0] += DrvGfxRegs[2]; + } + return; + + case 0x9c0004: + DrvGfxRegs[2] = data; + return; + } +} + +UINT8 __fastcall midas_read_byte(UINT32 address) +{ + switch (address) + { + case 0x900001: + return DrvInputs[5]; + + case 0x920001: + return DrvInputs[2] | (EEPROMRead() ? 8 : 0); + + case 0x940000: + return (DrvInputs[0] >> 8); + + case 0x980000: + return (DrvInputs[1] >> 8); + + case 0xb8000b: + return YMZ280BReadStatus(); + + case 0xba0001: + return DrvInputs[4]; + + case 0xbc0001: + return DrvInputs[3]; + } + + return 0; +} + +UINT16 __fastcall midas_read_word(UINT32 address) +{ + switch (address) + { + case 0x900000: + return DrvInputs[5]; + + case 0x980000: + return DrvInputs[1]; + + case 0xb00000: + case 0xb20000: + case 0xb40000: + case 0xb60000: + return 0xffff; + + case 0xbc0000: + return DrvInputs[3]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + YMZ280BReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x200000; + + DrvTxtROM = Next; Next += 0x040000; + DrvSprROM = Next; Next += 0x800000; + + DrvTxtTransTab = Next; Next += 0x040000 / 0x040; + DrvSprTransTab = Next; Next += 0x800000 / 0x100; + + YMZ280BROM = Next; Next += 0x200000; + + DrvPalette = (UINT32*)Next; Next += 0x10000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM0 = Next; Next += 0x020000; + Drv68KRAM1 = Next; Next += 0x040000; + DrvPalRAM = Next; Next += 0x080000; + DrvGfxRAM = Next; Next += 0x020000; + + DrvGfxRegs = (UINT16*)Next; Next += 3 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvInitZoomTable() +{ + zoom_table[0][0] = -1; + + for (INT32 x = 1; x < 16; x++) { + for (INT32 y = 0; y < 16; y++) { + float t = ((16.0000-1.0000) / x) * y; + zoom_table[x][y] = (t >= 16) ? -1 : (INT32)t; + } + } +} + +static void DrvFillTransTabs(UINT8 *tab, UINT8 *gfx, INT32 gfxlen, INT32 tilesize) +{ + for (INT32 i = 0; i < gfxlen; i+=tilesize) + { + tab[i/tilesize] = 0; + + INT32 count = 0; + + for (INT32 j = 0; j < tilesize; j++) { + if (gfx[i + j]) { + tab[i/tilesize] = 1; + count++; + } + } + + if (count >= (tilesize-1)) { + tab[i/tilesize] |= 2; + } + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[8] = { 0x3000008, 0x3000000, 0x1000008, 0x1000000, 0x2000008, 0x2000000, 0x0000008, 0x0000000 }; + INT32 XOffs0[16] = { 0x107, 0x106, 0x105, 0x104, 0x103, 0x102, 0x101, 0x100, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000 }; + INT32 YOffs0[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + + INT32 Plane1[8] = { 0x008, 0x009, 0x00a, 0x00b, 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs1[8] = { 0x104, 0x100, 0x184, 0x180, 0x004, 0x000, 0x084, 0x080 }; + INT32 YOffs1[8] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x800000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvSprROM, 0x800000); + + GfxDecode(0x8000, 8, 16, 16, Plane0, XOffs0, YOffs0, 0x200, tmp, DrvSprROM); + + memcpy (tmp, DrvTxtROM, 0x040000); + + GfxDecode(0x1000, 8, 8, 8, Plane1, XOffs1, YOffs1, 0x200, tmp, DrvTxtROM); + + DrvFillTransTabs(DrvSprTransTab, DrvSprROM, 0x800000, 0x100); + DrvFillTransTabs(DrvTxtTransTab, DrvTxtROM, 0x040000, 0x040); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM, 0, 1)) return 1; + + if (BurnLoadRom(DrvTxtROM, 7, 1)) return 1; + + if (BurnLoadRom(DrvSprROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvSprROM + 0x200000, 4, 1)) return 1; + if (BurnLoadRom(DrvSprROM + 0x400000, 5, 1)) return 1; + if (BurnLoadRom(DrvSprROM + 0x600000, 6, 1)) return 1; + + if (BurnLoadRom(YMZ280BROM, 8, 1)) return 1; + + DrvGfxDecode(); + } + + *((UINT16*)(Drv68KROM + 0x13345a)) = 0x4e75; // patch out protection + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0xa00000, 0xa3ffff, SM_ROM); + SekMapMemory(DrvPalRAM + 0x3ffff, 0xa40000, 0xa7ffff, SM_RAM); + SekMapMemory(Drv68KRAM0, 0xd00000, 0xd1ffff, SM_RAM); + SekMapMemory(Drv68KRAM1, 0xe00000, 0xe3ffff, SM_RAM); + SekMapMemory(DrvGfxRAM, 0xf90000, 0xfaffff, SM_RAM); + SekSetWriteByteHandler(0, midas_write_byte); + SekSetWriteWordHandler(0, midas_write_word); + SekSetReadByteHandler(0, midas_read_byte); + SekSetReadWordHandler(0, midas_read_word); + SekClose(); + + YMZ280BInit(16934400, NULL, 3); + + EEPROMInit(&eeprom_interface_93C46); + + DrvInitZoomTable(); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + YMZ280BExit(); + YMZ280BROM = NULL; + + EEPROMExit(); + + SekExit(); + + BurnFree (AllMem); + + DrvRecalc0 = 0; + + return 0; +} + +static void draw_16x16_zoom(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 xz, INT32 yz, INT32 fx, INT32 fy) +{ + if (yz == 1 || xz == 1) return; + + fx = (fx * 0x0f); + fy = (fy >> 1) * 0x0f; + + UINT8 *src = DrvSprROM + (code << 8); + + INT16 *xm = zoom_table[xz-1]; + INT16 *ym = zoom_table[yz-1]; + + for (INT32 y = 0; y < 16; y++) + { + INT32 yy = sy + y; + + if (ym[y ^ fy] == -1 || yy < 0 || yy >= nScreenHeight) continue; + + INT32 yyz = (ym[y ^ fy] << 4); + + for (INT32 x = 0; x < 16; x++) + { + INT16 xxz = xm[x ^ fx]; + if (xxz == -1) continue; + + INT32 xx = sx + x; + + INT32 pxl = src[yyz|xxz]; + + if (!pxl || xx < 0 || xx >= nScreenWidth || yy < 0 || yy >= nScreenHeight) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = pxl | color; + } + } +} + +static void draw_sprites() +{ + UINT16 *codes = (UINT16*)DrvGfxRAM; + UINT16 *s = codes + 0x8000; + + INT32 sx_old = 0, sy_old = 0, ynum_old = 0, xzoom_old = 0; + INT32 xdim, ydim, xscale, yscale, ynum; + + for (INT32 i = 0; i < 0x180; i++, s++, codes+=0x40) + { + INT32 zoom = s[0x000]; + INT32 sy = s[0x200]; + INT32 sx = s[0x400]; + + INT32 xzoom = ((zoom >> 8) & 0x0f) + 1; + INT32 yzoom = (zoom & 0x7f) + 1; + + if (sy & 0x40) { + ynum = ynum_old; + sx = sx_old + xzoom_old; + sy = sy_old; + } else { + ynum = sy & 0x3f; + sx = (sx >> 7); + sy = 0x200 - (sy >> 7); + + if (ynum > 0x20) ynum = 0x20; + } + + if (sx >= 0x1f0) sx -= 0x200; + + ynum_old = ynum; + sx_old = sx; + sy_old = sy; + xzoom_old = xzoom; + + sy <<= 16; + + xdim = xzoom << 16; + ydim = yzoom << 13; + + xscale = xzoom; + yscale = yzoom >> 3; + + for (INT32 y = 0; y < ynum; y++) + { + INT32 code = codes[y * 2]; + if (code & 0x8000) continue; // only 8mb of sprites... + + INT32 attr = codes[y * 2 + 1]; + + INT32 yy = (((sy + y * ydim) >> 16) & 0x1ff) - 16; + + if (sx >= nScreenWidth || yy >= nScreenHeight || !DrvSprTransTab[code]) continue; + + if (yscale != 16 || xscale != 16) { + draw_16x16_zoom(code, attr & 0xff00, sx, yy, xscale, yscale, attr & 1, attr & 2); + continue; + } + + if (DrvSprTransTab[code] & 2) { + if (sx < 0 || sx > (nScreenWidth-16) || yy < 0 || yy > (nScreenHeight-16)) { + if (attr & 2) { + if (attr & 1) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } + } else { + if (attr & 1) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } + } + } else { + if (attr & 2) { + if (attr & 1) { + Render16x16Tile_FlipXY(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } else { + Render16x16Tile_FlipY(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } + } else { + if (attr & 1) { + Render16x16Tile_FlipX(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } else { + Render16x16Tile(pTransDraw, code, sx, yy, attr >> 8, 8, 0, DrvSprROM); + } + } + } + } else { + if (sx < 0 || sx > (nScreenWidth-16) || yy < 0 || yy > (nScreenHeight-16)) { + if (attr & 2) { + if (attr & 1) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } + } else { + if (attr & 1) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } + } + } else { + if (attr & 2) { + if (attr & 1) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } + } else { + if (attr & 1) { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, yy, attr >> 8, 8, 0, 0, DrvSprROM); + } + } + } + } + } + } +} + +static void draw_layer() +{ + UINT16 *vram = (UINT16*)(DrvGfxRAM + 0xe000); + + for (INT32 offs = 0; offs < 0x28 * 0x20; offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = ((offs & 0x1f) << 3) - 16; + + INT32 code = vram[offs] & 0xfff; + INT32 color = vram[offs] >> 12; + + if (sy < 0 || sy >= nScreenHeight || !DrvTxtTransTab[code]) continue; + + if (DrvTxtTransTab[code] & 2) { + Render8x8Tile(pTransDraw, code, sx, sy, color, 8, 0, DrvTxtROM); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvTxtROM); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc0 != nBurnBpp) { + for (INT32 i = 0; i < 0x40000; i+=4) { + palette_write(i); + } + + DrvRecalc0 = nBurnBpp; + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) + pTransDraw[i] = 0xfff; + + draw_sprites(); + + draw_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 6 * sizeof(UINT16)); + + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy6[i] & 1) << i; + } + + DrvInputs[2] &= ~0x0008; + DrvInputs[5] = (DrvInputs[5] & 0xff00) | DrvDips[0]; + } + + SekOpen(0); + SekRun(12000000 / 60); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + YMZ280BRender(pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + EEPROMScan(nAction, pnMin); + + if (nAction & ACB_VOLATILE) { + + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + + SekScan(nAction); + + YMZ280BScan(); + } + + return 0; +} + + +// Live Quiz Show + +static struct BurnRomInfo livequizRomDesc[] = { + { "flash.u1", 0x200000, 0x8ec44493, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "main_pic12c508a.u27",0x000400, 0xa84f0a7e, 2 | BRF_PRG | BRF_OPT }, // 1 Mcu Code (not used) + { "sub_pic12c508a.u4", 0x000400, 0xe52ebdc4, 2 | BRF_PRG | BRF_OPT }, // 2 + + { "flash.u15", 0x200000, 0xd6eb56f1, 3 | BRF_GRA }, // 3 Sprites + { "flash.u16", 0x200000, 0x4c9fd873, 3 | BRF_GRA }, // 4 + { "flash.u19", 0x200000, 0xdaa81532, 3 | BRF_GRA }, // 5 + { "flash.u20", 0x200000, 0xb540a8c7, 3 | BRF_GRA }, // 6 + + { "27c4096.u23", 0x080000, 0x25121de8, 4 | BRF_GRA }, // 7 Characters + + { "flash.u5", 0x200000, 0xdc062792, 5 | BRF_SND }, // 8 YMZ280b Samples +}; + +STD_ROM_PICK(livequiz) +STD_ROM_FN(livequiz) + +struct BurnDriver BurnDrvLivequiz = { + "livequiz", NULL, NULL, NULL, "1999", + "Live Quiz Show\0", NULL, "Andamiro Entertainment Co. Ltd.", "Andamiro Midas", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, livequizRomInfo, livequizRomName, NULL, NULL, LivequizInputInfo, LivequizDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x10000, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_mogura.cpp b/src/burn/drivers/misc_post90s/d_mogura.cpp new file mode 100644 index 00000000..ad9282f4 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_mogura.cpp @@ -0,0 +1,410 @@ +// FB Alpha Mogura Desse driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "dac.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvGfxRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvGfxROM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8] = {0, }; +static UINT8 DrvJoy2[8] = {0, }; +static UINT8 DrvJoy3[8] = {0, }; +static UINT8 DrvJoy4[8] = {0, }; +static UINT8 DrvJoy5[8] = {0, }; +static UINT8 DrvDiag[2] = {0, }; +static UINT8 DrvReset; +static UINT8 DrvInputs[6] = {0, }; + +static struct BurnInputInfo MoguraInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy4 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, DrvJoy4 + 6, "p3 fire 3" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy1 + 3, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy5 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy5 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy5 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy5 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy5 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy5 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy5 + 5, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, DrvJoy5 + 6, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Diagnostics", BIT_DIGITAL, DrvDiag + 0, "diag" }, + {"Service 1", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy1 + 5, "service2" }, + {"Service 3", BIT_DIGITAL, DrvJoy1 + 6, "service3" }, + {"Service 4", BIT_DIGITAL, DrvJoy1 + 7, "service4" }, +}; + +STDINPUTINFO(Mogura) + +inline void MoguraClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvTileDecode(INT32 offset, INT32 data) +{ + UINT8 *tile = DrvGfxROM + (offset << 2); + + tile[0] = (data >> 6) & 3; + tile[1] = (data >> 4) & 3; + tile[2] = (data >> 2) & 3; + tile[3] = (data >> 0) & 3; +} + +void __fastcall mogura_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf000) == 0xe000) { + DrvGfxRAM[address & 0xfff] = data; + DrvTileDecode(address & 0xfff, data); + return; + } +} + +void __fastcall mogura_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x14: + DACWrite(0, (data & 0xf0)); + DACWrite(1, (data & 0x0f) << 4); + return; + } +} + +UINT8 __fastcall mogura_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x08: + return DrvInputs[0]; + + case 0x0c: + return ~DrvInputs[1]; + + case 0x0d: + return ~DrvInputs[2]; + + case 0x0e: + return ~DrvInputs[3]; + + case 0x0f: + return ~DrvInputs[4]; + + case 0x10: + return ~DrvInputs[5]; + } + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (DrvColPROM[i] >> 3) & 0x01; + bit1 = (DrvColPROM[i] >> 4) & 0x01; + bit2 = (DrvColPROM[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (DrvColPROM[i] >> 6) & 0x01; + bit2 = (DrvColPROM[i] >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + DrvPalette[((i & 7) << 2) | ((i >> 3) & 3)] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + DACReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x008000; + DrvColPROM = Next; Next += 0x000020; + + DrvPalette = (UINT32*)Next; Next += 0x0020 * sizeof(UINT32); + + AllRam = Next; + + DrvGfxROM = Next; Next += 0x004000; + DrvGfxRAM = Next; Next += 0x001000; + + DrvVidRAM = Next; Next += 0x001000; + + DrvZ80RAM = Next; Next += 0x002000; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM, 0, 1)) return 1; + + if (BurnLoadRom(DrvColPROM, 1, 1)) return 1; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM); + ZetMapArea(0xe000, 0xefff, 0, DrvGfxRAM); +// ZetMapArea(0xe000, 0xefff, 1, DrvGfxRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvGfxRAM); + ZetMapArea(0xf000, 0xffff, 0, DrvVidRAM); + ZetMapArea(0xf000, 0xffff, 1, DrvVidRAM); + ZetMapArea(0xf000, 0xffff, 2, DrvVidRAM); + ZetSetWriteHandler(mogura_write); + ZetSetOutHandler(mogura_write_port); + ZetSetInHandler(mogura_read_port); + ZetMemEnd(); + ZetClose(); + + DACInit(0, 0, 0); + DACInit(1, 0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + DACExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background() +{ + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = ((offs ^ 0x20) & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + if (sx >= 256) sx ^= 128; + if (sx >= 320) continue; + + INT32 code = DrvVidRAM[offs]; + INT32 color = (DrvVidRAM[offs + 0x800] >> 1) & 7; + + Render8x8Tile(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_background(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xff; + DrvInputs[1] = 0x00; + DrvInputs[2] = 0x00; + DrvInputs[3] = 0x00; + DrvInputs[4] = 0x00; + DrvInputs[5] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + DrvInputs[3] |= (DrvJoy4[i] & 1) << i; + DrvInputs[4] |= (DrvJoy5[i] & 1) << i; + DrvInputs[5] |= (DrvDiag[i] & 1) << i; + } + } + + // Clear Opposites + MoguraClearOpposites(&DrvInputs[1]); + MoguraClearOpposites(&DrvInputs[2]); + MoguraClearOpposites(&DrvInputs[3]); + MoguraClearOpposites(&DrvInputs[4]); + + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 1; + INT32 nSoundBufferPos = 0; + INT32 nTotalCycles = 3000000 / 60; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + ZetRun(nTotalCycles / nInterleave); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + DACUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + ZetRaiseIrq(0); + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + DACScan(nAction, pnMin); + } + + return 0; +} + + +// Mogura Desse + +static struct BurnRomInfo moguraRomDesc[] = { + { "gx141.5n", 0x8000, 0x98e6120d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + + { "gx141.7j", 0x0020, 0xb21c5d5f, 2 | BRF_GRA }, // 1 Color Prom +}; + +STD_ROM_PICK(mogura) +STD_ROM_FN(mogura) + +struct BurnDriver BurnDrvMogura = { + "mogura", NULL, NULL, NULL, "1991", + "Mogura Desse\0", "Konami test board", "Konami", "Miscellaneous", + L"\u30E2\u30B0\u30E9\u30C7\u30C3\u30BB\0Mogura Desse\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, moguraRomInfo, moguraRomName, NULL, NULL, MoguraInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 320, 256, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_mugsmash.cpp b/src/burn/drivers/misc_post90s/d_mugsmash.cpp new file mode 100644 index 00000000..e79b8884 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_mugsmash.cpp @@ -0,0 +1,686 @@ +// FB Alpha Mug Smashers driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvVidRegs; +static UINT8 *DrvSndRegs; + +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static INT32 *DrvScrollX; +static INT32 *DrvScrollY; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[4]; +static UINT16 DrvInps[4]; + +static UINT8 *soundlatch; + +static struct BurnInputInfo MugsmashInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 9, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip D", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(Mugsmash) + +static struct BurnDIPInfo MugsmashDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xe1, NULL }, + {0x15, 0xff, 0xff, 0xda, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Color Test" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Draw SF." }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x14, 0x01, 0x0e, 0x0c, "4 Coins 1 Credits " }, + {0x14, 0x01, 0x0e, 0x0a, "3 Coins 1 Credits " }, + {0x14, 0x01, 0x0e, 0x08, "2 Coins 1 Credits " }, + {0x14, 0x01, 0x0e, 0x00, "1 Coin 1 Credits " }, + {0x14, 0x01, 0x0e, 0x02, "1 Coin 2 Credits " }, + {0x14, 0x01, 0x0e, 0x04, "1 Coin 3 Credits " }, + {0x14, 0x01, 0x0e, 0x06, "1 Coin 4 Credits " }, + {0x14, 0x01, 0x0e, 0x0e, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x14, 0x01, 0x10, 0x10, "No" }, + {0x14, 0x01, 0x10, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Sound Test" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x06, 0x00, "1" }, + {0x15, 0x01, 0x06, 0x02, "2" }, + {0x15, 0x01, 0x06, 0x04, "3" }, + {0x15, 0x01, 0x06, 0x06, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x00, "Very_Easy" }, + {0x15, 0x01, 0x30, 0x10, "Easy" }, + {0x15, 0x01, 0x30, 0x20, "Hard" }, + {0x15, 0x01, 0x30, 0x30, "Very_Hard" }, + + {0 , 0xfe, 0 , 2, "Draw Objects" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Mugsmash) + +UINT8 __fastcall mugsmash_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180000: + case 0x180001: + case 0x180002: + case 0x180003: + case 0x180004: + case 0x180005: + case 0x180006: + case 0x180007: + return DrvInps[(address >> 1) & 3] >> ((~address & 1) << 3); + } + + return 0; +} + +UINT16 __fastcall mugsmash_read_word(UINT32 address) +{ + switch (address) + { + case 0x180000: + case 0x180002: + case 0x180004: + case 0x180006: + return DrvInps[(address >> 1) & 3]; + } + + return 0; +} + +static void palette_write(INT32 offset) +{ + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + UINT8 r,g,b; + + r = (data >> 10); + r = (r << 3) | (r >> 2); + + g = (data >> 5); + g = (g << 3) | (r >> 2); + + b = (data >> 0); + b = (b << 3) | (b >> 2); + + Palette[offset >> 1] = (r << 16) | (g << 8) | (b); + DrvPalette[offset >> 1] = BurnHighCol(r, g, b, 0); +} + +void __fastcall mugsmash_write_byte(UINT32 address, UINT8 data) +{ + if (address >= 0x100000 && address <= 0x1005ff) { + DrvPalRAM[address & 0x7ff] = data; + + palette_write(address & 0x7ff); + + return; + } + + switch (address) + { + case 0x0c0000: + case 0x0c0001: + case 0x0c0002: + case 0x0c0003: + case 0x0c0004: + case 0x0c0005: + case 0x0c0006: + case 0x0c0007: + DrvVidRegs[address & 7] = data; + return; + + case 0x140002: + case 0x140003: + ZetNmi(); + case 0x140000: + case 0x140001: + case 0x140004: + case 0x140005: + case 0x140006: + case 0x140007: + DrvSndRegs[address & 7] = data; + return; + } +} + +void __fastcall mugsmash_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0x100000 && address <= 0x1005ff) { + *((UINT16*)(DrvPalRAM + (address & 0x7fe))) = data; + + palette_write(address & 0x7fe); + + return; + } + + switch (address) + { + case 0x0c0000: + *((UINT16*)(DrvVidRegs + (address & 7))) = data; + DrvScrollX[1] = *((UINT16*)(DrvVidRegs + 4)) + 7; + return; + + case 0x0c0002: + *((UINT16*)(DrvVidRegs + (address & 7))) = data; + DrvScrollY[1] = *((UINT16*)(DrvVidRegs + 6)) + 12; + return; + + case 0x0c0004: + *((UINT16*)(DrvVidRegs + (address & 7))) = data; + DrvScrollX[0] = *((UINT16*)(DrvVidRegs + 0)) + 3; + return; + + case 0x0c0006: + *((UINT16*)(DrvVidRegs + (address & 7))) = data; + DrvScrollY[0] = *((UINT16*)(DrvVidRegs + 2)) + 12; + return; + + case 0x140002: + ZetNmi(); + case 0x140000: + case 0x140004: + case 0x140006: + *((UINT16*)(DrvSndRegs + (address & 7))) = data; + return; + } +} + +void __fastcall mugsmash_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8800: + BurnYM2151SelectRegister(data); + return; + + case 0x8801: + BurnYM2151WriteRegister(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall mugsmash_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8801: + return BurnYM2151ReadStatus(); + + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0, 1, 2, 3 }; + INT32 XOffs0[16] = { 16, 20, 24, 28, 0, 4, 8, 12, 48, 52, 56, 60, 32, 36, 40, 44 }; + INT32 YOffs0[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + + INT32 Plane1[4] = { 0xc00000, 0x800000, 0x400000, 0x000000 }; + INT32 XOffs1[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; + INT32 YOffs1[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x300000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x300000); + + GfxDecode(0x6000, 4, 16, 16, Plane0, XOffs0, YOffs0, 0x400, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x010000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvGfxROM0 = Next; Next += 0x600000; + DrvGfxROM1 = Next; Next += 0x400000; + + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x004000; + DrvVidRAM0 = Next; Next += 0x001000; + DrvVidRAM1 = Next; Next += 0x001000; + + DrvVidRegs = Next; Next += 0x000008; + DrvSndRegs = Next; Next += 0x000008; + + DrvScrollX = (INT32*)Next; Next += 0x000002 * sizeof(INT32); + DrvScrollY = (INT32*)Next; Next += 0x000002 * sizeof(INT32); + + DrvZ80RAM = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +void MugsmashYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + for (INT32 i = 0; i < 6; i+=2) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000 + 0, i + 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000 + 1, i + 4, 2)) return 1; + } + + for (INT32 i = 0; i < 4; i++) + if (BurnLoadRom(DrvGfxROM1 + i * 0x80000, i + 9, 1)) return 1; + + for (INT32 i = 0; i < 2; i++) + if (BurnLoadRom(DrvSndROM + i * 0x20000, i + 13, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvVidRAM0, 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x082000, 0x082fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x100000, 0x1005ff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x1c0000, 0x1cffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x200000, 0x203fff, SM_RAM); + SekSetWriteByteHandler(0, mugsmash_write_byte); + SekSetWriteWordHandler(0, mugsmash_write_word); + SekSetReadByteHandler(0, mugsmash_read_byte); + SekSetReadWordHandler(0, mugsmash_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(mugsmash_sound_write); + ZetSetReadHandler(mugsmash_sound_read); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + soundlatch = DrvSndRegs + 2; + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetIrqHandler(&MugsmashYM2151IrqHandler); + + MSM6295Init(0, 1122000 / 132, 50.0, 1); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + + MSM6295Exit(0); + BurnYM2151Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + const UINT16 *source = (const UINT16*)DrvSprRAM; + const UINT16 *finish = source + 0x2000; + + while (source < finish) + { + INT32 xpos = source[0] & 0x00ff; + INT32 ypos = source[4] & 0x00ff; + INT32 num = (source[3] & 0x00ff) | ((source[2] & 0x00ff) << 8); + INT32 attr = source[1]; + INT32 flipx = (attr & 0x0080)>>7; + INT32 color = attr & 0x000f; + + xpos += (attr & 0x0020) << 3; + ypos += (attr & 0x0010) << 4; + + xpos -= 28; + ypos -= 24; + + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, num, xpos, ypos, color, 4, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, num, xpos, ypos, color, 4, 0, 0, DrvGfxROM0); + } + + source += 8; + } +} + +static void draw_layer(UINT8 *source, INT32 colofst, INT32 scroll) +{ + UINT16 *vram = (UINT16*)source; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + INT32 code = vram[(offs << 1) | 1]; + INT32 color = vram[(offs << 1)]; + INT32 flipx = color & 0x40; + INT32 flipy = color & 0x80; + color &= 0x000f; + + sx -= DrvScrollX[scroll] & 0x1ff; + sy -= DrvScrollY[scroll] & 0x1ff; + if (sx < -15) sx += 0x200; + if (sy < -15) sy += 0x200; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, colofst, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, colofst, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, colofst, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, colofst, DrvGfxROM1); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x300; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + draw_layer(DrvVidRAM1, 0x200, 1); + draw_layer(DrvVidRAM0, 0x100, 0); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + for (INT32 i = 0; i < 4; i++) { + DrvInps[i] = (DrvDips[i] << 8) | 0xff; + } + + for (INT32 i = 0; i < 16; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 12000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment; + + nSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + nSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + nCyclesDone[1] += ZetRun(nSegment); + + nSegment = nBurnSoundLen / nInterleave; + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut + ((nSegment * i) << 1), nSegment); + MSM6295Render(0, pBurnSoundOut + ((nSegment * i) << 1), nSegment); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029697; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Mug Smashers + +static struct BurnRomInfo mugsmashRomDesc[] = { + { "mugs_04.bin", 0x40000, 0x2498fd27, 1 | BRF_PRG | BRF_ESS }, // 0 68000 Code + { "mugs_05.bin", 0x40000, 0x95efb40b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "mugs_03.bin", 0x10000, 0x0101df2d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "mugs_11.bin", 0x80000, 0x1c9f5acf, 3 | BRF_GRA }, // 3 Sprites + { "mugs_10.bin", 0x80000, 0x6b3c22d9, 3 | BRF_GRA }, // 4 + { "mugs_09.bin", 0x80000, 0x4e9490f3, 3 | BRF_GRA }, // 5 + { "mugs_08.bin", 0x80000, 0x716328d5, 3 | BRF_GRA }, // 6 + { "mugs_07.bin", 0x80000, 0x9e3167fd, 3 | BRF_GRA }, // 7 + { "mugs_06.bin", 0x80000, 0x8df75d29, 3 | BRF_GRA }, // 8 + + { "mugs_12.bin", 0x80000, 0xc0a6ed98, 4 | BRF_GRA }, // 9 Bg Tiles + { "mugs_13.bin", 0x80000, 0xe2be8595, 4 | BRF_GRA }, // 10 + { "mugs_14.bin", 0x80000, 0x24e81068, 4 | BRF_GRA }, // 11 + { "mugs_15.bin", 0x80000, 0x82e8187c, 4 | BRF_GRA }, // 12 + + { "mugs_02.bin", 0x20000, 0xf92a7f4a, 5 | BRF_GRA }, // 13 Samples + { "mugs_01.bin", 0x20000, 0x1a3a0b39, 5 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(mugsmash) +STD_ROM_FN(mugsmash) + +struct BurnDriver BurnDrvMugsmash = { + "mugsmash", NULL, NULL, NULL, "1990?", + "Mug Smashers\0", NULL, "Electronic Devices Italy / 3D Games England", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, mugsmashRomInfo, mugsmashRomName, NULL, NULL, MugsmashInputInfo, MugsmashDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_news.cpp b/src/burn/drivers/misc_post90s/d_news.cpp new file mode 100644 index 00000000..aaddfe64 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_news.cpp @@ -0,0 +1,450 @@ +#include "tiles_generic.h" +#include "msm6295.h" + +// FB Alpha - "News" Driver + +// Input Related Variables +static UINT8 NewsInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 NewsDip[1] = {0}; +static UINT8 NewsInput[1] = {0x00}; +static UINT8 NewsReset = 0; + +// Memory Holders +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *NewsRom = NULL; +static UINT8 *NewsRam = NULL; +static UINT8 *NewsFgVideoRam = NULL; +static UINT8 *NewsBgVideoRam = NULL; +static UINT8 *NewsPaletteRam = NULL; +static UINT32 *NewsPalette = NULL; +static UINT8 *NewsTiles = NULL; +static UINT8 *NewsTempGfx = NULL; + +// Misc Variables, system control values, etc. +static INT32 BgPic; + +// Dip Switch and Input Definitions +static struct BurnInputInfo NewsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , NewsInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , NewsInputPort0 + 1, "p1 start" }, + + {"Up" , BIT_DIGITAL , NewsInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , NewsInputPort0 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , NewsInputPort0 + 4, "p1 left" }, + {"Right" , BIT_DIGITAL , NewsInputPort0 + 5, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , NewsInputPort0 + 6, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , NewsInputPort0 + 7, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &NewsReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, NewsDip + 0 , "dip" }, +}; + +STDINPUTINFO(News) + +inline void NewsClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } + if ((*nJoystickInputs & 0x30) == 0x30) { + *nJoystickInputs &= ~0x30; + } +} + +inline void NewsMakeInputs() +{ + // Reset Inputs + NewsInput[0] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + NewsInput[0] |= (NewsInputPort0[i] & 1) << i; + } + + // Clear Opposites + NewsClearOpposites(&NewsInput[0]); +} + +static struct BurnDIPInfo NewsDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x09, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x09, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x09, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x09, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x09, 0x01, 0x0c, 0x0c, "Easy" }, + {0x09, 0x01, 0x0c, 0x08, "Medium" }, + {0x09, 0x01, 0x0c, 0x04, "Hard" }, + {0x09, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Helps" }, + {0x09, 0x01, 0x10, 0x10, "1" }, + {0x09, 0x01, 0x10, 0x00, "2" }, + + {0 , 0xfe, 0 , 2 , "Copyright" }, + {0x09, 0x01, 0x20, 0x00, "Poby" }, + {0x09, 0x01, 0x20, 0x20, "Virus" }, +}; + +STDDIPINFO(News) + +static struct BurnDIPInfo NewsaDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x09, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x09, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x09, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x09, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x09, 0x01, 0x0c, 0x0c, "Easy" }, + {0x09, 0x01, 0x0c, 0x08, "Medium" }, + {0x09, 0x01, 0x0c, 0x04, "Hard" }, + {0x09, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Helps" }, + {0x09, 0x01, 0x10, 0x10, "1" }, + {0x09, 0x01, 0x10, 0x00, "2" }, +}; + +STDDIPINFO(Newsa) + +// Rom Definitions +static struct BurnRomInfo NewsRomDesc[] = { + { "virus.4", 0x08000, 0xaa005dfb, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + + { "virus.2", 0x40000, 0xb5af58d8, BRF_GRA }, // 1 Tiles + { "virus.3", 0x40000, 0xa4b1c175, BRF_GRA }, // 2 Tiles + + { "virus.1", 0x40000, 0x41f5935a, BRF_SND }, // 3 Samples +}; + + +STD_ROM_PICK(News) +STD_ROM_FN(News) + +static struct BurnRomInfo NewsaRomDesc[] = { + { "newsa_virus.4", 0x10000, 0x74a257da, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + + { "virus.2", 0x40000, 0xb5af58d8, BRF_GRA }, // 1 Tiles + { "virus.3", 0x40000, 0xa4b1c175, BRF_GRA }, // 2 Tiles + + { "virus.1", 0x40000, 0x41f5935a, BRF_SND }, // 3 Samples +}; + + +STD_ROM_PICK(Newsa) +STD_ROM_FN(Newsa) + +// Misc Driver Functions and Memory Handlers +INT32 NewsDoReset() +{ + BgPic = 0; + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 8) & 0x0f; + g = (nColour >> 4) & 0x0f; + b = (nColour >> 0) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +UINT8 __fastcall NewsRead(UINT16 a) +{ + switch (a) { + case 0xc000: { + return NewsDip[0]; + } + + case 0xc001: { + return 0xff - NewsInput[0]; + } + + case 0xc002: { + return MSM6295ReadStatus(0); + } + } + + return 0; +} + +void __fastcall NewsWrite(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc002: { + MSM6295Command(0, d); + return; + } + + case 0xc003: { + BgPic = d; + return; + } + } + + if (a >= 0x9000 && a <= 0x91ff) { + INT32 Offset = a - 0x9000; + + NewsPaletteRam[Offset] = d; + NewsPalette[Offset / 2] = CalcCol(NewsPaletteRam[Offset | 1] | (NewsPaletteRam[Offset & ~1] << 8)); + return; + } +} + + + +// Function to Allocate and Index required memory +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + NewsRom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x40000; + + RamStart = Next; + + NewsRam = Next; Next += 0x02000; + NewsFgVideoRam = Next; Next += 0x00800; + NewsBgVideoRam = Next; Next += 0x00800; + NewsPaletteRam = Next; Next += 0x00200; + + RamEnd = Next; + + NewsTiles = Next; Next += (16384 * 8 * 8); + NewsPalette = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 TileYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + +// Driver Init and Exit Functions +INT32 NewsInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + NewsTempGfx = (UINT8*)BurnMalloc(0x80000); + + // Load Z80 Program Rom + nRet = BurnLoadRom(NewsRom, 0, 1); if (nRet != 0) return 1; + + // Load, byte-swap and decode Tile Roms + nRet = BurnLoadRom(NewsTempGfx + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(NewsTempGfx + 0x00001, 2, 2); if (nRet != 0) return 1; + GfxDecode(16384, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, NewsTempGfx, NewsTiles); + BurnFree(NewsTempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM, 3, 1); if (nRet != 0) return 1; + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, NewsRom ); + ZetMapArea(0x0000, 0x7fff, 2, NewsRom ); + ZetMapArea(0x8000, 0x87ff, 0, NewsFgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 1, NewsFgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 2, NewsFgVideoRam ); + ZetMapArea(0x8800, 0x8fff, 0, NewsBgVideoRam ); + ZetMapArea(0x8800, 0x8fff, 1, NewsBgVideoRam ); + ZetMapArea(0x8800, 0x8fff, 2, NewsBgVideoRam ); + ZetMapArea(0xe000, 0xffff, 0, NewsRam ); + ZetMapArea(0xe000, 0xffff, 1, NewsRam ); + ZetMapArea(0xe000, 0xffff, 2, NewsRam ); + ZetMemEnd(); + ZetSetReadHandler(NewsRead); + ZetSetWriteHandler(NewsWrite); + ZetClose(); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 8000, 100, 0); + + GenericTilesInit(); + + // Reset the driver + NewsDoReset(); + + return 0; +} + +INT32 NewsExit() +{ + MSM6295Exit(0); + ZetExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + BgPic = 0; + + return 0; +} + +// Graphics Emulation +void NewsRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = (NewsBgVideoRam[TileIndex * 2] << 8) | NewsBgVideoRam[TileIndex * 2 + 1]; + Colour = (Code & 0xf000) >> 12; + Code &= 0x0fff; + if ((Code & 0x0e00) == 0xe00) Code = (Code & 0x1ff) | (BgPic << 9); + x = 8 * mx; + y = 8 * my; + y -= 16; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 4, 0, NewsTiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, NewsTiles); + } + + TileIndex++; + } + } +} + +void NewsRenderFgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = (NewsFgVideoRam[TileIndex * 2] << 8) | NewsFgVideoRam[TileIndex * 2 + 1]; + Colour = (Code & 0xf000) >> 12; + Code &= 0x0fff; + x = 8 * mx; + y = 8 * my; + y -= 16; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, NewsTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, NewsTiles); + } + + TileIndex++; + } + } +} + +void NewsDraw() +{ + NewsRenderBgLayer(); + NewsRenderFgLayer(); + BurnTransferCopy(NewsPalette); +} + +// Frame Function +INT32 NewsFrame() +{ + if (NewsReset) NewsDoReset(); + + NewsMakeInputs(); + + ZetOpen(0); + ZetRun(8000000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnDraw) NewsDraw(); + if (pBurnSoundOut) MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + return 0; +} + +// Scan RAM +static INT32 NewsScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x02942; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + + // Scan critical driver variables + SCAN_VAR(NewsInput); + SCAN_VAR(NewsDip); + SCAN_VAR(BgPic); + } + + return 0; +} + +// Driver Declaration +struct BurnDriver BurnDrvNews = { + "news", NULL, NULL, NULL, "1993", + "News (set 1)\0", NULL, "Poby / Virus", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, NewsRomInfo, NewsRomName, NULL, NULL, NewsInputInfo, NewsDIPInfo, + NewsInit, NewsExit, NewsFrame, NULL, NewsScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNewsa = { + "newsa", "news", NULL, NULL, "1993", + "News (set 2)\0", NULL, "Poby / Jeansole", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, NewsaRomInfo, NewsaRomName, NULL, NULL, NewsInputInfo, NewsaDIPInfo, + NewsInit, NewsExit, NewsFrame, NULL, NewsScan, + NULL, 0x100, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_nmg5.cpp b/src/burn/drivers/misc_post90s/d_nmg5.cpp new file mode 100644 index 00000000..628c0d39 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_nmg5.cpp @@ -0,0 +1,1761 @@ +// FB Alpha NMG5 driver module +// Based on MAME driver by Pierpaolo Prazzoli + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "msm6295.h" + +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvBmpRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT16 *DrvScrRAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[ 2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static UINT8 DrvOkiBank; +static UINT8 soundlatch; +static UINT8 prot_val; +static UINT8 input_data; +static UINT8 priority_reg; +static UINT8 gfx_bank; + +static struct BurnInputInfo Nmg5InputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy3 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy3 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 15, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 13, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 14, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Nmg5) + +static struct BurnInputInfo SearcheyInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy3 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy3 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 15, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 13, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Searchey) + +static struct BurnInputInfo PclubysInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy3 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy3 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 15, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 8, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 9, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 10, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 11, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 13, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 14, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Pclubys) + +static struct BurnInputInfo GarogunInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy3 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy3 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p1 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Garogun) + +static struct BurnInputInfo Ordi7InputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p1 start" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 2, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 3, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy3 + 1, "p1 fire 4"}, + {"P1 Button 5" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 5"}, + {"P1 Button 6" , BIT_DIGITAL , DrvJoy3 + 10, "p1 fire 6"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ordi7) + +static struct BurnDIPInfo Nmg5DIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xdf, NULL }, + + {0x13, 0xfe, 0, 2, "Game Title" }, + {0x13, 0x01, 0x01, 0x01, "Multi 5" }, + {0x13, 0x01, 0x01, 0x00, "New Multi Game 5" }, + + {0x13, 0xfe, 0, 4, "Crocodiles (Tong Boy)" }, + {0x13, 0x01, 0x06, 0x06, "Pattern 1" }, + {0x13, 0x01, 0x06, 0x02, "Pattern 2" }, + {0x13, 0x01, 0x06, 0x04, "Pattern 3" }, + {0x13, 0x01, 0x06, 0x00, "Pattern 4" }, + + {0x13, 0xfe, 0, 4, "License" }, + {0x13, 0x01, 0x18, 0x00, "New Impeuropex Corp. S.R.L." }, + {0x13, 0x01, 0x18, 0x08, "BNS Enterprises" }, + {0x13, 0x01, 0x18, 0x10, "Nova Games" }, + {0x13, 0x01, 0x18, 0x18, "None" }, + + {0x13, 0xfe, 0, 2, "1P Vs 2P Rounds (Bubble Gum)" }, + {0x13, 0x01, 0x20, 0x20, "Best of 1" }, + {0x13, 0x01, 0x20, 0x00, "Best of 3" }, + + {0x13, 0xfe, 0, 4, "Difficulty" }, + {0x13, 0x01, 0xc0, 0x40, "Easy" }, + {0x13, 0x01, 0xc0, 0xc0, "Normal" }, + {0x13, 0x01, 0xc0, 0x80, "Hard" }, + {0x13, 0x01, 0xc0, 0x00, "Hardest" }, + + {0x14, 0xfe, 0, 4, "Coin B" }, + {0x14, 0x01, 0x03, 0x02, "2C 1C" }, + {0x14, 0x01, 0x03, 0x03, "1C 1C" }, + {0x14, 0x01, 0x03, 0x00, "2C 3C" }, + {0x14, 0x01, 0x03, 0x01, "1C 2C" }, +// {0x14, 0x01, 0x03, 0x03, "1C 1C" }, +// {0x14, 0x01, 0x03, 0x01, "1C 3C" }, +// {0x14, 0x01, 0x03, 0x02, "1C 4C" }, +// {0x14, 0x01, 0x03, 0x00, "1C 6C" }, + + {0x14, 0xfe, 0, 4, "Coin A" }, + {0x14, 0x01, 0x0c, 0x08, "2C 1C" }, + {0x14, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x14, 0x01, 0x0c, 0x00, "2C 3C" }, + {0x14, 0x01, 0x0c, 0x04, "1C 2C" }, +// {0x14, 0x01, 0x0c, 0x00, "4C 1C" }, +// {0x14, 0x01, 0x0c, 0x08, "3C 1C" }, +// {0x14, 0x01, 0x0c, 0x04, "2C 1C" }, +// {0x14, 0x01, 0x0c, 0x0c, "1C 1C" }, + + {0x14, 0xfe, 0, 2, "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0x14, 0xfe, 0, 2, "Coin Type" }, + {0x14, 0x01, 0x40, 0x40, "1" }, + {0x14, 0x01, 0x40, 0x00, "2" }, + + {0x14, 0xfe, 0, 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Nmg5) + +static struct BurnDIPInfo SearcheyDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xdd, NULL }, + + {0 , 0xfe, 0, 4, "Timer Speed" }, + {0x10, 0x01, 0x03, 0x03, "Slowest" }, + {0x10, 0x01, 0x03, 0x02, "Slow" }, + {0x10, 0x01, 0x03, 0x01, "Fast" }, + {0x10, 0x01, 0x03, 0x00, "Fastest" }, + + {0x10, 0xfe, 0, 4, "Helps" }, + {0x10, 0x01, 0x0c, 0x0c, "1" }, + {0x10, 0x01, 0x0c, 0x08, "2" }, + {0x10, 0x01, 0x0c, 0x04, "3" }, + {0x10, 0x01, 0x0c, 0x00, "4" }, + + {0x10, 0xfe, 0, 4, "Lives" }, + {0x10, 0x01, 0x30, 0x20, "3" }, + {0x10, 0x01, 0x30, 0x10, "4" }, + {0x10, 0x01, 0x30, 0x30, "5" }, + {0x10, 0x01, 0x30, 0x00, "6" }, + + {0x10, 0xfe, 0, 4, "Coinage" }, + {0x10, 0x01, 0xc0, 0x00, "3C 1C" }, + {0x10, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x10, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x10, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x11, 0xfe, 0, 2, "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0x11, 0xfe, 0, 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0x11, 0xfe, 0, 2, "Language" }, + {0x11, 0x01, 0x20, 0x00, "English" }, + {0x11, 0x01, 0x20, 0x20, "Korean" }, + + {0x11, 0xfe, 0, 2, "Items to find" }, + {0x11, 0x01, 0x80, 0x00, "Less" }, + {0x11, 0x01, 0x80, 0x80, "More" }, +}; + +STDDIPINFO(Searchey) + +static struct BurnDIPInfo Searchp2DIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xf7, NULL }, + + {0x10, 0xfe, 0, 4, "Timer Speed" }, + {0x10, 0x01, 0x03, 0x03, "Slowest" }, + {0x10, 0x01, 0x03, 0x02, "Slow" }, + {0x10, 0x01, 0x03, 0x01, "Fast" }, + {0x10, 0x01, 0x03, 0x00, "Fastest" }, + + {0x10, 0xfe, 0, 4, "Helps" }, + {0x10, 0x01, 0x0c, 0x0c, "1" }, + {0x10, 0x01, 0x0c, 0x08, "2" }, + {0x10, 0x01, 0x0c, 0x04, "3" }, + {0x10, 0x01, 0x0c, 0x00, "4" }, + + {0x10, 0xfe, 0, 4, "Lives" }, + {0x10, 0x01, 0x30, 0x20, "3" }, + {0x10, 0x01, 0x30, 0x10, "4" }, + {0x10, 0x01, 0x30, 0x30, "5" }, + {0x10, 0x01, 0x30, 0x00, "6" }, + + {0x10, 0xfe, 0, 4, "Coinage" }, + {0x10, 0x01, 0xc0, 0x00, "3C 1C" }, + {0x10, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x10, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x10, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x11, 0xfe, 0, 2, "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0x11, 0xfe, 0, 4, "Lucky Chance" }, + {0x11, 0x01, 0x06, 0x06, "Table 1" }, + {0x11, 0x01, 0x06, 0x04, "Table 2" }, + {0x11, 0x01, 0x06, 0x02, "Table 3" }, + {0x11, 0x01, 0x06, 0x00, "Table 4" }, + + {0x11, 0xfe, 0, 8, "Language" }, + {0x11, 0x01, 0x38, 0x38, "Korean" }, + {0x11, 0x01, 0x38, 0x30, "English" }, + {0x11, 0x01, 0x38, 0x28, "Japanese" }, + {0x11, 0x01, 0x38, 0x20, "Chinese" }, + {0x11, 0x01, 0x38, 0x18, "Italian" }, + {0x11, 0x01, 0x38, 0x10, "Korean" }, + {0x11, 0x01, 0x38, 0x08, "Korean" }, + {0x11, 0x01, 0x38, 0x00, "Korean" }, + + {0x11, 0xfe, 0, 2, "Lucky Timer" }, + {0x11, 0x01, 0x40, 0x00, "Less" }, + {0x11, 0x01, 0x40, 0x40, "More" }, + + {0x11, 0xfe, 0, 2, "Items to find" }, + {0x11, 0x01, 0x80, 0x00, "Less" }, + {0x11, 0x01, 0x80, 0x80, "More" }, +}; + +STDDIPINFO(Searchp2) + +static struct BurnDIPInfo PclubysDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0x12, 0xfe, 0, 2, "Lives (Mad Ball)" }, + {0x12, 0x01, 0x01, 0x00, "3" }, + {0x12, 0x01, 0x01, 0x01, "4" }, + + {0x12, 0xfe, 0, 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0x12, 0xfe, 0, 2, "1P Vs 2P Rounds" }, + {0x12, 0x01, 0x04, 0x00, "Best of 1" }, + {0x12, 0x01, 0x04, 0x04, "Best of 3" }, + + {0x12, 0xfe, 0, 2, "Nudity" }, + {0x12, 0x01, 0x08, 0x08, "Soft only" }, + {0x12, 0x01, 0x08, 0x00, "Soft and Hard" }, + + {0x12, 0xfe, 0, 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x30, "Easy" }, + {0x12, 0x01, 0x30, 0x20, "Normal" }, + {0x12, 0x01, 0x30, 0x10, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0x12, 0xfe, 0, 4, "Coinage" }, + {0x12, 0x01, 0xc0, 0x00, "3C 1C" }, + {0x12, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x12, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x12, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x13, 0xfe, 0, 2, "Service Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0x13, 0xfe, 0, 4, "Timer Speed (Magic Eye)" }, + {0x13, 0x01, 0x30, 0x30, "Slowest" }, + {0x13, 0x01, 0x30, 0x20, "Slow" }, + {0x13, 0x01, 0x30, 0x10, "Fast" }, + {0x13, 0x01, 0x30, 0x00, "Fastest" }, + + {0x13, 0xfe, 0, 2, "Lives (Magic Eye)" }, + {0x13, 0x01, 0x40, 0x00, "3" }, + {0x13, 0x01, 0x40, 0x40, "4" }, + + {0x13, 0xfe, 0, 2, "Timer Speed (Box Logic)" }, + {0x13, 0x01, 0x80, 0x80, "Slow" }, + {0x13, 0x01, 0x80, 0x00, "Fast" }, +}; + +STDDIPINFO(Pclubys) + +static struct BurnDIPInfo GarogunDIPList[]= +{ + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0xfd, NULL }, + + {0x09, 0xfe, 0, 4, "Helps" }, + {0x09, 0x01, 0x03, 0x00, "1" }, + {0x09, 0x01, 0x03, 0x01, "2" }, + {0x09, 0x01, 0x03, 0x02, "3" }, + {0x09, 0x01, 0x03, 0x03, "4" }, + + {0x09, 0xfe, 0, 4, "Timer Speed (Bonus Levels)" }, + {0x09, 0x01, 0x0c, 0x0c, "Slowest" }, + {0x09, 0x01, 0x0c, 0x08, "Slow" }, + {0x09, 0x01, 0x0c, 0x04, "Fast" }, + {0x09, 0x01, 0x0c, 0x00, "Fastest" }, + + {0x09, 0xfe, 0, 4, "Timer Speed (Main Levels)" }, + {0x09, 0x01, 0x30, 0x30, "Slowest" }, + {0x09, 0x01, 0x30, 0x20, "Slow" }, + {0x09, 0x01, 0x30, 0x10, "Fast" }, + {0x09, 0x01, 0x30, 0x00, "Fastest" }, + + {0x09, 0xfe, 0, 4, "Coinage" }, + {0x09, 0x01, 0xc0, 0x00, "3C 1C" }, + {0x09, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x09, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x09, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x0a, 0xfe, 0, 2, "Service Mode" }, + {0x0a, 0x01, 0x01, 0x01, "Off" }, + {0x0a, 0x01, 0x01, 0x00, "On" }, + + {0x0a, 0xfe, 0, 2, "Demo Sounds" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Garogun) + +static struct BurnDIPInfo Ordi7DIPList[]= +{ + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0xff, NULL }, + + {0x09, 0xfe, 0, 2, "High-Low Error" }, + {0x09, 0x01, 0x01, 0x01, "-500" }, + {0x09, 0x01, 0x01, 0x00, "Lose All" }, + + {0x09, 0xfe, 0, 2, "Minimum Credits" }, + {0x09, 0x01, 0x02, 0x02, "300" }, + {0x09, 0x01, 0x02, 0x00, "500" }, + + {0x09, 0xfe, 0, 4, "Credit Limit" }, + {0x09, 0x01, 0x0c, 0x0c, "10000" }, + {0x09, 0x01, 0x0c, 0x08, "30000" }, + {0x09, 0x01, 0x0c, 0x04, "50000" }, + {0x09, 0x01, 0x0c, 0x00, "100000" }, + + {0x09, 0xfe, 0, 4, "Bet" }, + {0x09, 0x01, 0x30, 0x30, "50 Credits" }, + {0x09, 0x01, 0x30, 0x20, "100 Credits" }, + {0x09, 0x01, 0x30, 0x10, "150 Credits" }, + {0x09, 0x01, 0x30, 0x00, "200 Credits" }, + + {0x09, 0xfe, 0, 4, "Coinage" }, + {0x09, 0x01, 0xc0, 0xc0, "1 Coin 50 Credits" }, + {0x09, 0x01, 0xc0, 0x80, "1 Coin 100 Credits" }, + {0x09, 0x01, 0xc0, 0x40, "1 Coin 500 Credits" }, + {0x09, 0x01, 0xc0, 0x00, "1 Coin 1000 Credits" }, + + {0x0a, 0xfe, 0, 2, "Service Mode" }, + {0x0a, 0x01, 0x01, 0x01, "Off" }, + {0x0a, 0x01, 0x01, 0x00, "On" }, + + {0x0a, 0xfe, 0, 2, "Winnings" }, + {0x0a, 0x01, 0x04, 0x04, "Medals and Credits" }, + {0x0a, 0x01, 0x04, 0x00, "Credits only" }, + + {0x0a, 0xfe, 0, 4, "Medals Table" }, + {0x0a, 0x01, 0x18, 0x18, "x1.0" }, + {0x0a, 0x01, 0x18, 0x10, "x1.4" }, + {0x0a, 0x01, 0x18, 0x08, "x2.0" }, + {0x0a, 0x01, 0x18, 0x00, "x3.0" }, + + {0x0a, 0xfe, 0, 8, "Payout %" }, + {0x0a, 0x01, 0xe0, 0xe0, "90%" }, + {0x0a, 0x01, 0xe0, 0xc0, "85%" }, + {0x0a, 0x01, 0xe0, 0xa0, "80%" }, + {0x0a, 0x01, 0xe0, 0x80, "75%" }, + {0x0a, 0x01, 0xe0, 0x60, "70%" }, + {0x0a, 0x01, 0xe0, 0x40, "65%" }, + {0x0a, 0x01, 0xe0, 0x20, "60%" }, + {0x0a, 0x01, 0xe0, 0x00, "55%" }, +}; + +STDDIPINFO(Ordi7) + +static struct BurnDIPInfo WondstckDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xfd, NULL }, + + {0x10, 0xfe, 0, 2, "Helps" }, + {0x10, 0x01, 0x10, 0x10, "3" }, + {0x10, 0x01, 0x10, 0x00, "5" }, + + {0x10, 0xfe, 0, 2, "Lives" }, + {0x10, 0x01, 0x20, 0x20, "3" }, + {0x10, 0x01, 0x20, 0x00, "5" }, + + {0x10, 0xfe, 0, 4, "Coinage" }, + {0x10, 0x01, 0xc0, 0x00, "3C 1C" }, + {0x10, 0x01, 0xc0, 0x40, "2C 1C" }, + {0x10, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x10, 0x01, 0xc0, 0x80, "1C 2C" }, + + {0x11, 0xfe, 0, 2, "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0x11, 0xfe, 0, 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0x11, 0xfe, 0, 4, "Difficulty" }, + {0x11, 0x01, 0xc0, 0x80, "Easy" }, + {0x11, 0x01, 0xc0, 0xc0, "Normal" }, + {0x11, 0x01, 0xc0, 0x40, "Hard" }, + {0x11, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Wondstck) + +//----------------------------------------------------------------------------------------------- + +static void palette_write(INT32 offset) +{ + INT32 data = *((UINT16*)(DrvPalRAM + offset)); + + INT32 r = (data >> 0) & 0x1f; + INT32 g = (data >> 5) & 0x1f; + INT32 b = (data >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[offset>>1] = (r << 16) | (g << 8) | b; + DrvPalette[offset>>1] = BurnHighCol(r, g, b, 0); +} + +void __fastcall nmg5_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffff800) == 0x140000) { + DrvPalRAM[address & 0x7ff] = data; + palette_write(address & 0x7ff); + return; + } + + switch (address) + { + case 0x180000: + case 0x180001: + soundlatch = data; + ZetNmi(); + return; + + case 0x180004: + case 0x180005: + input_data = data & 0xf; + return; + + case 0x180006: + case 0x180007: + gfx_bank = data & 3; + return; + + case 0x18000e: + case 0x18000f: + priority_reg = data & 7; + return; + + case 0x300002: + case 0x300003: + case 0x300004: + case 0x300005: + case 0x300006: + case 0x300007: + case 0x300008: + case 0x300009: + *((UINT8*)(DrvScrRAM + ((address - 2) & 7))) = data; + return; + } + + return; +} + +void __fastcall nmg5_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff800) == 0x140000) { + *((UINT16*)(DrvPalRAM + (address & 0x7ff))) = data; + palette_write(address & 0x7ff); + return; + } + + switch (address) + { + case 0x180000: + soundlatch = data; + ZetNmi(); + return; + + case 0x180004: + input_data = data & 0xf; + return; + + case 0x180006: + gfx_bank = data & 3; + return; + + case 0x18000e: + priority_reg = data & 7; + return; + + case 0x300002: + case 0x300004: + case 0x300006: + case 0x300008: + DrvScrRAM[(address - 0x300002) >> 1] = data & 0x1ff; + return; + } + + return; +} + +UINT8 __fastcall nmg5_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180004: + case 0x180005: + return prot_val | input_data; + + case 0x180008: + return DrvInputs[0] >> 8; + + case 0x180009: + return DrvInputs[0]; + + case 0x18000a: + return DrvInputs[1] >> 8; + + case 0x18000b: + return DrvInputs[1] & ~0x50; + + case 0x18000c: + return DrvInputs[2] >> 8; + + case 0x18000d: + return DrvInputs[2]; + } + + return 0; +} + +UINT16 __fastcall nmg5_read_word(UINT32 address) +{ + switch (address) + { + case 0x180004: + return prot_val | input_data; + + case 0x180008: + return DrvInputs[0]; + + case 0x18000a: + return DrvInputs[1] & ~0x50; + + case 0x18000c: + return DrvInputs[2]; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +void __fastcall pclubys_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffff800) == 0x440000) { + DrvPalRAM[address & 0x7ff] = data; + palette_write(address & 0x7ff); + return; + } + + switch (address) + { + case 0x480000: + case 0x480001: + soundlatch = data; + ZetNmi(); + return; + + case 0x480004: + case 0x480005: + input_data = data & 0xf; + return; + + case 0x480006: + case 0x480007: + gfx_bank = data & 3; + return; + + case 0x48000e: + case 0x48000f: + priority_reg = data & 7; + return; + + case 0x500002: + case 0x500003: + case 0x500004: + case 0x500005: + case 0x500006: + case 0x500007: + case 0x500008: + case 0x500009: + *((UINT8*)(DrvScrRAM + ((address - 0x500002) & 7))) = data; + return; + } + + return; +} + +void __fastcall pclubys_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff800) == 0x440000) { + *((UINT16*)(DrvPalRAM + (address & 0x7ff))) = data; + palette_write(address & 0x7ff); + return; + } + + switch (address) + { + case 0x480000: + soundlatch = data; + ZetNmi(); + return; + + case 0x480004: + input_data = data & 0xf; + return; + + case 0x480006: + gfx_bank = data & 3; + return; + + case 0x48000e: + priority_reg = data & 7; + return; + + case 0x500002: + case 0x500004: + case 0x500006: + case 0x500008: + DrvScrRAM[(address - 0x500002) >> 1] = data; + return; + } + + return; +} + +UINT8 __fastcall pclubys_read_byte(UINT32 address) +{ + switch (address) + { + case 0x480004: + case 0x480005: + return prot_val | input_data; + + case 0x480008: + return DrvInputs[0] >> 8; + + case 0x480009: + return DrvInputs[0]; + + case 0x48000a: + return DrvInputs[1] >> 8; + + case 0x48000b: + return DrvInputs[1]; + + case 0x48000c: + return DrvInputs[2] >> 8; + + case 0x48000d: + return DrvInputs[2]; + } + + return 0; +} + +UINT16 __fastcall pclubys_read_word(UINT32 address) +{ + switch (address) + { + case 0x480004: + return prot_val | input_data; + + case 0x480008: + return DrvInputs[0]; + + case 0x48000a: + return DrvInputs[1]; + + case 0x48000c: + return DrvInputs[2]; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +void __fastcall nmg5_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + DrvOkiBank = data & 1; + MSM6295ROM = DrvSndROM + (DrvOkiBank ? 0x40000 : 0); + return; + + case 0x10: + BurnYM3812Write(0, data); + return; + + case 0x11: + BurnYM3812Write(1, data); + return; + + case 0x1c: + MSM6295Command(0, data); + return; + } + + return; +} + +UINT8 __fastcall nmg5_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x10: + return BurnYM3812Read(0); + + case 0x18: + return soundlatch; + + case 0x1c: + return MSM6295ReadStatus(0); + } + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x0100000; + DrvZ80ROM = Next; Next += 0x0010000; + + DrvGfxROM0 = Next; Next += 0x1000000; + DrvGfxROM1 = Next; Next += 0x0400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x0080000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x0010000; + DrvZ80RAM = Next; Next += 0x0000800; + + DrvPalRAM = Next; Next += 0x0000800; + + DrvSprRAM = Next; Next += 0x0000800; + + DrvVidRAM0 = Next; Next += 0x0002000; + DrvVidRAM1 = Next; Next += 0x0002000; + + DrvBmpRAM = Next; Next += 0x0010000; + + DrvScrRAM = (UINT16*)Next; Next += 0x0000004 * sizeof(UINT16); + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + priority_reg = 7; + + soundlatch = 0; + input_data = 0; + gfx_bank = 0; + DrvOkiBank = 0; + MSM6295ROM = DrvSndROM; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM3812Reset(); + + return 0; +} + +static INT32 DrvGfxDecode(INT32 type) +{ + static INT32 Planes0[8] = { + 0x1C00000, 0x1800000, 0x1400000, 0x1000000, + 0x0c00000, 0x0800000, 0x0400000, 0x0000000 + }; + + static INT32 XOffs0[8] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 + }; + + static INT32 YOffs0[8] = { + 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038 + }; + + static INT32 Planes0a[8] = { + 0x2000008, 0x4000000, 0x0000008, 0x0000000, + 0x6000008, 0x6000000, 0x4000008, 0x2000000 + }; + + static INT32 XOffs0a[8] = { + 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 + }; + + static INT32 YOffs0a[8] = { + 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 + }; + + static INT32 Planes1[5] = { + 0x0800000, 0x0c00000, 0x0400000, 0x1000000, 0x0000000 + }; + + static INT32 XOffs1[16] = { + 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000, + 0x087, 0x086, 0x085, 0x084, 0x083, 0x082, 0x081, 0x080 + }; + + static INT32 YOffs1[16] = { + 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 + }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x1000000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x1000000); + + if (type) { + GfxDecode(0x40000, 8, 8, 8, Planes0a, XOffs0a, YOffs0a, 0x080, tmp, DrvGfxROM0); + } else { + GfxDecode(0x10000, 8, 8, 8, Planes0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + } + + memcpy (tmp, DrvGfxROM1, 0x400000); + + GfxDecode(0x04000, 5, 16, 16, Planes1, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit(INT32 loadtype, INT32 sektype, INT32 zettype) // 0 nmg, 1 pclubys +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (loadtype) { + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x400000, i + 3, 1)) return 1; + } + + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x080000, i + 7, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 12, 1)) return 1; + } else { + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000, i + 3, 1)) return 1; + } + + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x80000, i + 11, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 16, 1)) return 1; + } + + DrvGfxDecode(loadtype); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvBmpRAM, 0x800000, 0x80ffff, SM_RAM); + if (sektype) { + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x440000, 0x4407ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x460000, 0x4607ff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x520000, 0x521fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x522000, 0x523fff, SM_RAM); + SekSetWriteByteHandler(0, pclubys_write_byte); + SekSetWriteWordHandler(0, pclubys_write_word); + SekSetReadByteHandler(0, pclubys_read_byte); + SekSetReadWordHandler(0, pclubys_read_word); + } else { + SekMapMemory(Drv68KRAM, 0x120000, 0x12ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x1407ff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x320000, 0x321fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x322000, 0x323fff, SM_RAM); + SekSetWriteByteHandler(0, nmg5_write_byte); + SekSetWriteWordHandler(0, nmg5_write_word); + SekSetReadByteHandler(0, nmg5_read_byte); + SekSetReadWordHandler(0, nmg5_read_word); + } + SekClose(); + + ZetInit(1); + ZetOpen(0); + if (zettype) { + ZetMapArea(0x0000, 0xf7ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xf7ff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + } else { + ZetMapArea(0x0000, 0xdfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xdfff, 2, DrvZ80ROM); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80RAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80RAM); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80RAM); + } + ZetSetInHandler(nmg5_read_port); + ZetSetOutHandler(nmg5_write_port); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(4000000, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + MSM6295Init(0, 1000000 / 132, 100.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM3812Exit(); + + GenericTilesExit(); + ZetExit(); + SekExit(); + + BurnFree (AllMem); + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +static void draw_bitmap() +{ + UINT16 x,y,count; + INT32 pix; + + UINT16 *bitmap = (UINT16*)DrvBmpRAM; + + for (y = 0, count = 0; y < 256; y++) + { + for(x = 0; x < 128; x++, count++) + { + if (!bitmap[count]) continue; + + INT32 ofst = ((y - 9) * nScreenWidth) + ((x << 2) - 12); + + pix = bitmap[count] >> 12; + if (pix) pTransDraw[ofst ] = pix | 0x300; + + pix = (bitmap[count]&0x0f00)>>8; + if (pix) pTransDraw[ofst | 1] = pix | 0x300; + + pix = (bitmap[count]&0x00f0)>>4; + if (pix) pTransDraw[ofst | 2] = pix | 0x300; + + pix = bitmap[count] & 0x000f; + if (pix) pTransDraw[ofst | 3] = pix | 0x300; + } + } +} + +static void DrawTiles(UINT8 *vidram, INT32 color, INT32 transp, INT32 scrollx, INT32 scrolly) +{ + UINT16 *vram = (UINT16*)vidram; + + for (INT32 offs = 0; offs < 0x2000 / 2; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + INT32 code = vram[offs] | (gfx_bank << 16); + + sx -= scrollx; + sy -= scrolly; + if (sx < -7) sx += 0x200; + if (sy < -7) sy += 0x200; + + if (transp) { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 8, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 8, 0, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + UINT16 *spriteram16 = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0;offs < 0x800/2;offs += 4) + { + INT32 sx = spriteram16[offs + 2] & 0x1ff; + INT32 sy = spriteram16[offs]; + INT32 code = spriteram16[offs + 1]; + INT32 color = (spriteram16[offs + 2] >> 9) & 0xf; + INT32 height = 1 << ((sy & 0x0600) >> 9); + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + + for (INT32 y = 0;y < height;y++) + { + INT32 yy = 248 - ((sy + ((height - y) << 4)) & 0x1ff); + + INT32 tile = code + (flipy ? height-1-y : y); + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, tile, sx, yy, color, 5, 0, 0x200, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, tile, sx, yy, color, 5, 0, 0x200, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, tile, sx, yy, color, 5, 0, 0x200, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, tile, sx, yy, color, 5, 0, 0x200, DrvGfxROM1); + } + } + + if (sx < 0x1f1) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, tile, sx - 512, yy, color, 5, 0, 0x200, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, tile, sx - 512, yy, color, 5, 0, 0x200, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, tile, sx - 512, yy, color, 5, 0, 0x200, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, tile, sx - 512, yy, color, 5, 0, 0x200, DrvGfxROM1); + } + } + } + } +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + DrawTiles(DrvVidRAM0, 1, 0, DrvScrRAM[2]+3, DrvScrRAM[3]+9); + + if(priority_reg == 0) + { + draw_sprites(); + DrawTiles(DrvVidRAM1, 0, 1, DrvScrRAM[0]-1, DrvScrRAM[1]+9); + draw_bitmap(); + } + else if(priority_reg == 1) + { + draw_bitmap(); + draw_sprites(); + DrawTiles(DrvVidRAM1, 0, 1, DrvScrRAM[0]-1, DrvScrRAM[1]+9); + } + else if(priority_reg == 2) + { + draw_sprites(); + draw_bitmap(); + DrawTiles(DrvVidRAM1, 0, 1, DrvScrRAM[0]-1, DrvScrRAM[1]+9); + } + else if(priority_reg == 3) + { + DrawTiles(DrvVidRAM1, 0, 1, DrvScrRAM[0]-1, DrvScrRAM[1]+9); + draw_sprites(); + draw_bitmap(); + } + else if(priority_reg == 7) + { + DrawTiles(DrvVidRAM1, 0, 1, DrvScrRAM[0]-1, DrvScrRAM[1]+9); + draw_bitmap(); + draw_sprites(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + + +static INT32 DrvFrame() +{ + INT32 nTotalCycles[2] = { 16000000 / 60, 4000000 / 60 }; + + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 6); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + + DrvInputs[0] = (DrvDips[1] << 8) | DrvDips[0]; + } + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + SekRun(nTotalCycles[0]); + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnTimerEndFrameYM3812(nTotalCycles[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029692; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); +// BurnTimerScan(nAction, pnMin); + + SCAN_VAR(soundlatch); + SCAN_VAR(prot_val); + SCAN_VAR(input_data); + SCAN_VAR(priority_reg); + SCAN_VAR(gfx_bank); + SCAN_VAR(DrvOkiBank); + } + + if (nAction & ACB_WRITE) { + nmg5_write_port(0, DrvOkiBank); + } + + return 0; +} + +//----------------------------------------------------------------------------------------------- + +// Multi 5 / New Multi Game 5 + +static struct BurnRomInfo nmg5RomDesc[] = { + { "ub15.bin", 0x80000, 0x36af3e2f, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "ub16.bin", 0x80000, 0x2d9923d4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "xh15.bin", 0x10000, 0x12d047c4, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "srom1.bin", 0x80000, 0x6771b694, 3 | BRF_GRA }, // 3 - Tiles + { "srom2.bin", 0x80000, 0x362d33af, 3 | BRF_GRA }, // 4 + { "srom3.bin", 0x80000, 0x8bad69d1, 3 | BRF_GRA }, // 5 + { "srom4.bin", 0x80000, 0xe73a7fcb, 3 | BRF_GRA }, // 6 + { "srom5.bin", 0x80000, 0x7300494e, 3 | BRF_GRA }, // 7 + { "srom6.bin", 0x80000, 0x74b5fdf9, 3 | BRF_GRA }, // 8 + { "srom7.bin", 0x80000, 0xbd2b9036, 3 | BRF_GRA }, // 9 + { "srom8.bin", 0x80000, 0xdd38360e, 3 | BRF_GRA }, // 10 + + { "uf1.bin", 0x40000, 0x9a9fb6f4, 4 | BRF_GRA }, // 11 - Sprites + { "uf2.bin", 0x40000, 0x66954d63, 4 | BRF_GRA }, // 12 + { "ufa1.bin", 0x40000, 0xba73ed2d, 4 | BRF_GRA }, // 13 + { "uh1.bin", 0x40000, 0xf7726e8e, 4 | BRF_GRA }, // 14 + { "uj1.bin", 0x40000, 0x54f7486e, 4 | BRF_GRA }, // 15 + + { "xra1.bin", 0x20000, 0xc74a4f3e, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(nmg5) +STD_ROM_FN(nmg5) + +static INT32 Nmg5Init() +{ + prot_val = 0x10; + + return DrvInit(0,0,0); +} + +struct BurnDriver BurnDrvNmg5 = { + "nmg5", NULL, NULL, NULL, "1998", + "Multi 5 / New Multi Game 5\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, nmg5RomInfo, nmg5RomName, NULL, NULL, Nmg5InputInfo, Nmg5DIPInfo, + Nmg5Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Multi 5 / New Multi Game 5 (earlier) + +static struct BurnRomInfo nmg5eRomDesc[] = { + { "ub15.rom", 0x80000, 0x578516e2, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "ub16.rom", 0x80000, 0x12fab483, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "xh15.bin", 0x10000, 0x12d047c4, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "srom1.rom", 0x80000, 0x6df3e0c2, 3 | BRF_GRA }, // 3 - Tiles + { "srom2.rom", 0x80000, 0x3caf65f9, 3 | BRF_GRA }, // 4 + { "srom3.rom", 0x80000, 0x812f3f87, 3 | BRF_GRA }, // 5 + { "srom4.rom", 0x80000, 0xedb8299d, 3 | BRF_GRA }, // 6 + { "srom5.rom", 0x80000, 0x79821f18, 3 | BRF_GRA }, // 7 + { "srom6.rom", 0x80000, 0x7e37abaf, 3 | BRF_GRA }, // 8 + { "srom7.rom", 0x80000, 0xb7a9c660, 3 | BRF_GRA }, // 9 + { "srom8.rom", 0x80000, 0xd7ba6058, 3 | BRF_GRA }, // 10 + + { "uf1.rom", 0x40000, 0x502dbd65, 4 | BRF_GRA }, // 11 - Sprites + { "uf2.rom", 0x40000, 0x6744cca0, 4 | BRF_GRA }, // 12 + { "ufa1.rom", 0x40000, 0x7110677f, 4 | BRF_GRA }, // 13 + { "uh1.rom", 0x40000, 0xf6a3ef4d, 4 | BRF_GRA }, // 14 + { "uj1.rom", 0x40000, 0x0595d8ef, 4 | BRF_GRA }, // 15 + + { "xra1.bin", 0x20000, 0xc74a4f3e, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(nmg5e) +STD_ROM_FN(nmg5e) + +struct BurnDriver BurnDrvNmg5e = { + "nmg5e", "nmg5", NULL, NULL, "1997", + "Multi 5 / New Multi Game 5 (earlier)\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, nmg5eRomInfo, nmg5eRomName, NULL, NULL, Nmg5InputInfo, Nmg5DIPInfo, + Nmg5Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Search Eye + +static struct BurnRomInfo searcheyRomDesc[] = { + { "u7.bin", 0x40000, 0x287ce3dd, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "u2.bin", 0x40000, 0xb574f033, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u128.bin", 0x10000, 0x85bae10c, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "u63.bin", 0x80000, 0x1b0b7b7d, 3 | BRF_GRA }, // 3 - Tiles + { "u68.bin", 0x80000, 0xae18b2aa, 3 | BRF_GRA }, // 4 + { "u73.bin", 0x80000, 0xab7f8716, 3 | BRF_GRA }, // 5 + { "u79.bin", 0x80000, 0x7f2c8b83, 3 | BRF_GRA }, // 6 + { "u64.bin", 0x80000, 0x322a903c, 3 | BRF_GRA }, // 7 + { "u69.bin", 0x80000, 0xd546eaf8, 3 | BRF_GRA }, // 8 + { "u74.bin", 0x80000, 0xe6134d84, 3 | BRF_GRA }, // 9 + { "u80.bin", 0x80000, 0x9a160918, 3 | BRF_GRA }, // 10 + + { "u83.bin", 0x20000, 0xc5a1c647, 4 | BRF_GRA }, // 11 - Sprites + { "u82.bin", 0x20000, 0x25b2ae62, 4 | BRF_GRA }, // 12 + { "u105.bin", 0x20000, 0xb4207ef0, 4 | BRF_GRA }, // 13 + { "u96.bin", 0x20000, 0x8c40818a, 4 | BRF_GRA }, // 14 + { "u97.bin", 0x20000, 0x5dc7f231, 4 | BRF_GRA }, // 15 + + { "u137.bin", 0x40000, 0x49105e23, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(searchey) +STD_ROM_FN(searchey) + +struct BurnDriver BurnDrvSearchey = { + "searchey", NULL, NULL, NULL, "1999", + "Search Eye\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, searcheyRomInfo, searcheyRomName, NULL, NULL, SearcheyInputInfo, SearcheyDIPInfo, + Nmg5Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Search Eye Plus V2.0 + +static struct BurnRomInfo searchp2RomDesc[] = { + { "u7", 0x080000, 0x37fe9e18, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "u2", 0x080000, 0x8278513b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u128", 0x010000, 0x85bae10c, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "0.u1", 0x400000, 0x28a50dcf, 3 | BRF_GRA }, // 3 - Tiles + { "2.u3", 0x400000, 0x30d46e19, 3 | BRF_GRA }, // 4 + { "1.u2", 0x400000, 0xf9c4e824, 3 | BRF_GRA }, // 5 + { "3.u4", 0x400000, 0x619f142f, 3 | BRF_GRA }, // 6 + + { "u83", 0x040000, 0x2bae34cb, 4 | BRF_GRA }, // 7 - Sprites + { "u82", 0x040000, 0x5cb773f0, 4 | BRF_GRA }, // 8 + { "u105", 0x040000, 0xe8adb15e, 4 | BRF_GRA }, // 9 + { "u96", 0x040000, 0x67efb536, 4 | BRF_GRA }, // 10 + { "u97", 0x040000, 0xf7b63826, 4 | BRF_GRA }, // 11 + + { "u137", 0x040000, 0xcd037524, 5 | BRF_SND }, // 12 - Samples +}; + +STD_ROM_PICK(searchp2) +STD_ROM_FN(searchp2) + +static INT32 Searchp2Init() +{ + prot_val = 0x10; + + BurnSetRefreshRate(55); + + return DrvInit(1,0,0); +} + +struct BurnDriver BurnDrvSearchp2 = { + "searchp2", NULL, NULL, NULL, "1999", + "Search Eye Plus V2.0\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, searchp2RomInfo, searchp2RomName, NULL, NULL, SearcheyInputInfo, Searchp2DIPInfo, + Searchp2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Puzzle Club (Yun Sung, set 1) + +static struct BurnRomInfo pclubysRomDesc[] = { + { "rom3.7", 0x080000, 0x62e28e6d, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "rom4.2", 0x080000, 0xb51dab41, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "rom1.128", 0x010000, 0x25cd27f8, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "rom10.167", 0x400000, 0xd67e8e84, 3 | BRF_GRA }, // 3 - Tiles + { "rom12.165", 0x400000, 0x6be8b733, 3 | BRF_GRA }, // 4 + { "rom11.166", 0x400000, 0x672501a4, 3 | BRF_GRA }, // 5 + { "rom13.164", 0x400000, 0xfc725ce7, 3 | BRF_GRA }, // 6 + + { "rom8.83", 0x080000, 0x651af101, 4 | BRF_GRA }, // 7 - Sprites + { "rom9.82", 0x080000, 0x2535b4d6, 4 | BRF_GRA }, // 8 + { "rom7.105", 0x080000, 0xf7536c52, 4 | BRF_GRA }, // 9 + { "rom6.95", 0x080000, 0x3c078a52, 4 | BRF_GRA }, // 10 + { "rom5.97", 0x080000, 0x20eae2f8, 4 | BRF_GRA }, // 11 + + { "rom2.137", 0x080000, 0x4ff97ad1, 4 | BRF_SND }, // 12 - Samples +}; + +STD_ROM_PICK(pclubys) +STD_ROM_FN(pclubys) + +static INT32 PclubysInit() +{ + prot_val = 0x10; + + return DrvInit(1,1,1); +} + +struct BurnDriver BurnDrvPclubys = { + "pclubys", NULL, NULL, NULL, "2000", + "Puzzle Club (Yun Sung, set 1)\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, pclubysRomInfo, pclubysRomName, NULL, NULL, PclubysInputInfo, PclubysDIPInfo, + PclubysInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Puzzle Club (Yun Sung, set 2) + +static struct BurnRomInfo pclubysaRomDesc[] = { + { "rom3a.7", 0x080000, 0x885aa07a, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "rom4a.2", 0x080000, 0x9bfbdeac, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "rom1.128", 0x010000, 0x25cd27f8, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "rom10.167", 0x400000, 0xd67e8e84, 3 | BRF_GRA }, // 3 - Tiles + { "rom12.165", 0x400000, 0x6be8b733, 3 | BRF_GRA }, // 4 + { "rom11.166", 0x400000, 0x672501a4, 3 | BRF_GRA }, // 5 + { "rom13.164", 0x400000, 0xfc725ce7, 3 | BRF_GRA }, // 6 + + { "rom8.83", 0x080000, 0x651af101, 4 | BRF_GRA }, // 7 - Sprites + { "rom9.82", 0x080000, 0x2535b4d6, 4 | BRF_GRA }, // 8 + { "rom7.105", 0x080000, 0xf7536c52, 4 | BRF_GRA }, // 9 + { "rom6.95", 0x080000, 0x3c078a52, 4 | BRF_GRA }, // 10 + { "rom5.97", 0x080000, 0x20eae2f8, 4 | BRF_GRA }, // 11 + + { "rom2.137", 0x080000, 0x4ff97ad1, 4 | BRF_SND }, // 12 - Samples +}; + +STD_ROM_PICK(pclubysa) +STD_ROM_FN(pclubysa) + +struct BurnDriver BurnDrvPclubysa = { + "pclubysa", "pclubys", NULL, NULL, "2000", + "Puzzle Club (Yun Sung, set 2)\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MINIGAMES, 0, + NULL, pclubysaRomInfo, pclubysaRomName, NULL, NULL, PclubysInputInfo, PclubysDIPInfo, + PclubysInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Garogun Seroyang (Korea) + +static struct BurnRomInfo garogunRomDesc[] = { + { "p1.u7", 0x80000, 0x9b5627f8, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "p2.u2", 0x80000, 0x1d2ff271, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "rom.u128", 0x10000, 0x117b31ce, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "8.u63", 0x80000, 0x2d152d32, 3 | BRF_GRA }, // 3 - Tiles + { "11.u68", 0x80000, 0x60ec7f67, 3 | BRF_GRA }, // 4 + { "9.u73", 0x80000, 0xa4b16319, 3 | BRF_GRA }, // 5 + { "13.u79", 0x80000, 0x2dc14fb6, 3 | BRF_GRA }, // 6 + { "6.u64", 0x80000, 0xa0fc7547, 3 | BRF_GRA }, // 7 + { "10.u69", 0x80000, 0xe5dc36c3, 3 | BRF_GRA }, // 8 + { "7.u74", 0x80000, 0xa0574f8d, 3 | BRF_GRA }, // 9 + { "12.u80", 0x80000, 0x94d66169, 3 | BRF_GRA }, // 10 + + { "4.u83", 0x40000, 0x3d1d46ff, 4 | BRF_GRA }, // 11 - Sprites + { "5.u82", 0x40000, 0x2a7b2fb5, 4 | BRF_GRA }, // 12 + { "3.u105", 0x40000, 0xcd20e39c, 4 | BRF_GRA }, // 13 + { "2.u96", 0x40000, 0x4df3b502, 4 | BRF_GRA }, // 14 + { "1.u97", 0x40000, 0x591b3efe, 4 | BRF_GRA }, // 15 + + { "s.u137", 0x80000, 0x3eadc21a, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(garogun) +STD_ROM_FN(garogun) + +static INT32 GarogunInit() +{ + prot_val = 0x40; + + return DrvInit(0,1,1); +} + +struct BurnDriver BurnDrvGarogun = { + "garogun", NULL, NULL, NULL, "2000", + "Garogun Seroyang (Korea)\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, garogunRomInfo, garogunRomName, NULL, NULL, GarogunInputInfo, GarogunDIPInfo, + GarogunInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// 7 Ordi (Korea) + +static struct BurnRomInfo ordi7RomDesc[] = { + { "p1.u7", 0x20000, 0xebf21862, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "p2.u2", 0x20000, 0xf7943a6a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "4.u128", 0x10000, 0xed73b565, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "8.u63", 0x80000, 0xed8dfe5d, 3 | BRF_GRA }, // 3 - Tiles + { "11.u68", 0x80000, 0x742764a7, 3 | BRF_GRA }, // 4 + { "9.u73", 0x80000, 0x2b76efd0, 3 | BRF_GRA }, // 5 + { "13.u79", 0x80000, 0x3892b356, 3 | BRF_GRA }, // 6 + { "6.u64", 0x80000, 0x5c0b0838, 3 | BRF_GRA }, // 7 + { "10.u69", 0x80000, 0xc15db1a4, 3 | BRF_GRA }, // 8 + { "7.u74", 0x80000, 0x6910f754, 3 | BRF_GRA }, // 9 + { "12.u80", 0x80000, 0x4c5dd9ef, 3 | BRF_GRA }, // 10 + + { "4.u83", 0x80000, 0xa2569cf4, 4 | BRF_GRA }, // 11 - Sprites + { "5.u82", 0x80000, 0x045e548e, 4 | BRF_GRA }, // 12 + { "3.u105", 0x80000, 0x04c1dbf9, 4 | BRF_GRA }, // 13 + { "2.u96", 0x80000, 0x11fa7de8, 4 | BRF_GRA }, // 14 + { "1.u97", 0x80000, 0xcd1ffe88, 4 | BRF_GRA }, // 15 + + { "3.u137", 0x20000, 0x669ed310, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(ordi7) +STD_ROM_FN(ordi7) + +static INT32 Ordi7Init() +{ + INT32 nRet; + + prot_val = 0x20; + + nRet = DrvInit(0,0,1); + + if (nRet == 0) { + memcpy (DrvSndROM + 0x20000, DrvSndROM, 0x20000); + memcpy (DrvSndROM + 0x40000, DrvSndROM, 0x20000); + memcpy (DrvSndROM + 0x50000, DrvSndROM, 0x20000); + } + + return nRet; +} + +struct BurnDriver BurnDrvOrdi7 = { + "7ordi", NULL, NULL, NULL, "2002", + "7 Ordi (Korea)\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_CASINO, 0, + NULL, ordi7RomInfo, ordi7RomName, NULL, NULL, Ordi7InputInfo, Ordi7DIPInfo, + Ordi7Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; + + +// Wonder Stick + +static struct BurnRomInfo wondstckRomDesc[] = { + { "u4.bin", 0x20000, 0x46a3e9f6, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "u2.bin", 0x20000, 0x9995b743, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u128.bin", 0x10000, 0x86dba085, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "u63.bin", 0x80000, 0xc6cf09b4, 3 | BRF_GRA }, // 3 - Tiles + { "u68.bin", 0x80000, 0x2e9e9a5e, 3 | BRF_GRA }, // 4 + { "u73.bin", 0x80000, 0x3a828604, 3 | BRF_GRA }, // 5 + { "u79.bin", 0x80000, 0x0cca46af, 3 | BRF_GRA }, // 6 + { "u64.bin", 0x80000, 0xdcec9ac5, 3 | BRF_GRA }, // 7 + { "u69.bin", 0x80000, 0x27b9d708, 3 | BRF_GRA }, // 8 + { "u74.bin", 0x80000, 0x7eff8e2f, 3 | BRF_GRA }, // 9 + { "u80.bin", 0x80000, 0x1160a0c2, 3 | BRF_GRA }, // 10 + + { "u83.bin", 0x80000, 0xf51cf9c6, 4 | BRF_GRA }, // 11 - Sprites + { "u82.bin", 0x80000, 0xddd3c60c, 4 | BRF_GRA }, // 12 + { "u105.bin", 0x80000, 0xa7fc624d, 4 | BRF_GRA }, // 13 + { "u96.bin", 0x80000, 0x2369d8a3, 4 | BRF_GRA }, // 14 + { "u97.bin", 0x80000, 0xaba1bd94, 4 | BRF_GRA }, // 15 + + { "u137.bin", 0x40000, 0x294b6cbd, 5 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(wondstck) +STD_ROM_FN(wondstck) + +static INT32 WondstckInit() +{ + prot_val = 0x00; + + return DrvInit(0,0,0); +} + +struct BurnDriver BurnDrvWondstck = { + "wondstck", NULL, NULL, NULL, "????", + "Wonder Stick\0", NULL, "Yun Sung", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, wondstckRomInfo, wondstckRomName, NULL, NULL, SearcheyInputInfo, WondstckDIPInfo, + WondstckInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x400, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_nmk16.cpp b/src/burn/drivers/misc_post90s/d_nmk16.cpp new file mode 100644 index 00000000..b7534c03 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_nmk16.cpp @@ -0,0 +1,8834 @@ +// FB Alpha NMK16 driver module +// Based on MAME driver by Mirko Buffoni, Richard Bush, Nicola Salmoria, Bryan McPhail, David Haywood, and R. Belmont +// Also, a huge "thank you!" to JackC for helping bug test + +#include "tiles_generic.h" +#include "seibusnd.h" +#include "bitswap.h" +#include "nmk004.h" + +#if 0 + blkheart -- good + mustang -- good + acrobatm -- good + manybloc -- good + stagger1 -- good + tharrier -- good + airattck -- good + macross -- good + redhawkb -- good + popspops -- good + spec2k -- good + firehawk -- good + mangchi -- good + bubble2000 -- good + hachamf -- good -- small gfx issues, need to compare to MAME + redhawki -- good + strahl -- good + bioship -- good + nouryoku -- good + tdragon -- good + tdragon2 -- good (input issues?, I can not confirm) + macross2 -- good (input issues?, I can not confirm) + ssmissin -- good + twinactn -- good + gunnail -- good + raphero -- good -- no sound, cpu NOT emulated (input issues?, I can not confirm) + vandyke -- good + vandykeb -- good -- no sound. cpu NOT emulated :) + grdnstrm -- good + grdnstrmk -- good + bjtwin -- good + sabotenb -- good + + tdragonb -- bad sound. Seibu sound needs hooked up properly + mustangb -- bad sound. Seibu sound needs hooked up properly +#endif + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvTileROM; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgRAM0; +static UINT8 *DrvBgRAM1; +static UINT8 *DrvBgRAM2; +static UINT8 *DrvBgRAM3; +static UINT8 *DrvTxRAM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvSprBuf2; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvScrollRAM; + +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *flipscreen; +static UINT8 *tilebank; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT16 DrvInputs[3]; +static UINT8 DrvReset; + +static INT32 nGraphicsMask[3]; +static INT32 videoshift = 0; +static INT32 input_high[2] = { 0, 0 }; +static INT32 is_8bpp = 0; +static INT32 global_y_offset = 16; +static INT32 screen_flip_y = 0; +static UINT32 nNMK004CpuSpeed; +static INT32 nNMK004EnableIrq2; +static INT32 macross2_sound_enable; + +static struct BurnInputInfo CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common) + +static struct BurnInputInfo TharrierInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy3 + 6, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy3 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy3 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy3 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 1, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy3 + 2, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy3 + 7, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 14, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 13, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 12, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 9, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 10, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Tharrier) + +static struct BurnInputInfo ManyblocInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 6, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 8, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 14, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 13, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 12, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 9, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 10, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Manybloc) + +static struct BurnInputInfo SsmissinInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ssmissin) + +static struct BurnInputInfo Tdragon2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Tdragon2) + +static struct BurnInputInfo AcrobatmInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Acrobatm) + +static struct BurnDIPInfo RedhawkbDIPList[]= +{ + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0xc0, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0x00, "3" }, + {0x12, 0x01, 0xc0, 0x80, "5" }, + +// {0 , 0xfe, 0 , 4, "Flip Screen" }, +// {0x13, 0x01, 0x03, 0x00, "Off" }, +// {0x13, 0x01, 0x03, 0x03, "On" }, +// {0x13, 0x01, 0x03, 0x01, "Horizontally" }, +// {0x13, 0x01, 0x03, 0x02, "Vertically" }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x18, 0x10, "Easy" }, + {0x13, 0x01, 0x18, 0x00, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Hard" }, + {0x13, 0x01, 0x18, 0x18, "Hardest" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0xe0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Redhawkb) + +static struct BurnDIPInfo RapheroDIPList[]= +{ + {0x14, 0xff, 0xff, 0xfd, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x14, 0x01, 0x02, 0x02, "Japanese" }, + {0x14, 0x01, 0x02, 0x00, "English" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x10, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0xc0, 0x00, "1" }, + {0x14, 0x01, 0xc0, 0x40, "2" }, + {0x14, 0x01, 0xc0, 0xc0, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x15, 0x01, 0x01, 0x01, "Off" }, +// {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x15, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x15, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x15, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Raphero) + +static struct BurnDIPInfo BioshipDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x06, 0x00, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Normal" }, + {0x12, 0x01, 0x06, 0x02, "Hard" }, + {0x12, 0x01, 0x06, 0x04, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Bioship) + +static struct BurnDIPInfo StrahlDIPList[]= +{ + {0x12, 0xff, 0xff, 0x7f, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x18, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x40, 0x40, "Off" }, +// {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x60, 0x40, "100k and every 200k" }, + {0x13, 0x01, 0x60, 0x60, "200k and every 200k" }, + {0x13, 0x01, 0x60, 0x20, "300k and every 300k" }, + {0x13, 0x01, 0x60, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Strahl) + +static struct BurnDIPInfo HachamfDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x18, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x13, 0x01, 0x02, 0x00, "English" }, + {0x13, 0x01, 0x02, 0x02, "Japanese" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x04, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x08, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x00, "1" }, + {0x13, 0x01, 0xc0, 0x40, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x80, "4" }, +}; + +STDDIPINFO(Hachamf) + +static struct BurnDIPInfo VandykeDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x01, 0x00, "2" }, + {0x12, 0x01, 0x01, 0x01, "3" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0xc0, 0x00, "Easy" }, + {0x12, 0x01, 0xc0, 0xc0, "Normal" }, + {0x12, 0x01, 0xc0, 0x40, "Hard" }, + {0x12, 0x01, 0xc0, 0x80, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Vandyke) + + +static struct BurnDIPInfo BlkheartDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x0c, "Easy" }, + {0x12, 0x01, 0x0c, 0x08, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + {0x12, 0x01, 0xc0, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Blkheart) + +static struct BurnDIPInfo MacrossDIPList[]= +{ + {0x12, 0xff, 0xff, 0xf7, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x04, 0x04, "Off" }, +// {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x12, 0x01, 0x08, 0x00, "English" }, + {0x12, 0x01, 0x08, 0x08, "Japanese" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x10, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0x0f, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "5 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0xf0, 0x40, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Macross) + +static struct BurnDIPInfo TharrierDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "Free Play" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x14, 0x01, 0x01, 0x01, "Upright" }, +// {0x14, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x04, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "200k" }, + {0x14, 0x01, 0x30, 0x20, "200k and 1 Mil" }, + {0x14, 0x01, 0x30, 0x00, "200k, 500k & 1,2,3,5 Mil" }, + {0x14, 0x01, 0x30, 0x10, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0xc0, 0x40, "2" }, + {0x14, 0x01, 0xc0, 0xc0, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, + {0x14, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Tharrier) + +static struct BurnDIPInfo ManyblocDIPList[]= +{ + {0x11, 0xff, 0xff, 0x18, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Slot System" }, + {0x11, 0x01, 0x01, 0x00, "Off" }, + {0x11, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Explanation" }, + {0x11, 0x01, 0x02, 0x00, "English" }, + {0x11, 0x01, 0x02, 0x02, "Japanese" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x08, 0x08, "Upright" }, + {0x11, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x10, 0x10, "Off" }, + {0x11, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x60, 0x60, "Easy" }, + {0x11, 0x01, 0x60, 0x00, "Normal" }, + {0x11, 0x01, 0x60, 0x20, "Hard" }, + {0x11, 0x01, 0x60, 0x40, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x11, 0x01, 0x80, 0x00, "Off" }, +// {0x11, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x07, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x00, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x38, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x00, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4, "Plate Probability" }, + {0x12, 0x01, 0xc0, 0xc0, "Bad" }, + {0x12, 0x01, 0xc0, 0x00, "Normal" }, + {0x12, 0x01, 0xc0, 0x40, "Better" }, + {0x12, 0x01, 0xc0, 0x80, "Best" }, +}; + +STDDIPINFO(Manybloc) + +static struct BurnDIPInfo SsmissinDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x11, 0x01, 0x01, 0x01, "Off" }, +// {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x0c, 0x04, "Easy" }, + {0x11, 0x01, 0x0c, 0x0c, "Normal" }, + {0x11, 0x01, 0x0c, 0x08, "Hard" }, + {0x11, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0xc0, 0x00, "1" }, + {0x11, 0x01, 0xc0, 0x40, "2" }, + {0x11, 0x01, 0xc0, 0xc0, "3" }, + {0x11, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x12, 0x01, 0xe0, 0x20, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Ssmissin) + +static struct BurnDIPInfo Macross2DIPList[]= +{ + {0x12, 0xff, 0xff, 0xf7, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x04, 0x04, "Off" }, +// {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x12, 0x01, 0x08, 0x00, "English" }, + {0x12, 0x01, 0x08, 0x08, "Japanese" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x10, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0x0f, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "5 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0xf0, 0x40, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Macross2) + +static struct BurnDIPInfo Tdragon2DIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x04, 0x04, "Off" }, +// {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x10, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0xc0, 0x00, "1" }, + {0x14, 0x01, 0xc0, 0x40, "2" }, + {0x14, 0x01, 0xc0, 0xc0, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x15, 0x01, 0x0f, 0x04, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x0f, 0x0a, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x0f, 0x01, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x0f, 0x00, "5 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x02, "3 Coins 2 Credits" }, + {0x15, 0x01, 0x0f, 0x08, "4 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x0f, 0x0c, "3 Coins 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0e, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0f, 0x07, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x0f, 0x0b, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x0f, 0x0d, "1 Coin 5 Credits" }, + {0x15, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x15, 0x01, 0xf0, 0x40, "4 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xa0, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x20, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0x80, "4 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "3 Coins 4 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Tdragon2) + +static struct BurnDIPInfo Stagger1DIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + +// {0 , 0xfe, 0 , 4, "Flip Screen" }, +// {0x13, 0x01, 0x03, 0x03, "Off" }, +// {0x13, 0x01, 0x03, 0x00, "On" }, +// {0x13, 0x01, 0x03, 0x02, "Horizontally" }, +// {0x13, 0x01, 0x03, 0x01, "Vertically" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x18, 0x08, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Stagger1) + +static struct BurnDIPInfo GrdnstrmDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Bombs" }, + {0x12, 0x01, 0x08, 0x08, "2" }, + {0x12, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + +// {0 , 0xfe, 0 , 0, "Mirror Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + +// {0 , 0xfe, 0 , 4, "Flip Screen" }, +// {0x13, 0x01, 0x02, 0x02, "Off" }, +// {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x13, 0x01, 0x18, 0x08, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Grdnstrm) + +static struct BurnDIPInfo GrdnstrkDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Bombs" }, + {0x12, 0x01, 0x08, 0x08, "2" }, + {0x12, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + +// {0 , 0xfe, 0 , 0, "Flip Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + +// {0 , 0xfe, 0 , 4, "Mirror Screen" }, +// {0x13, 0x01, 0x02, 0x02, "Off" }, +// {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x13, 0x01, 0x18, 0x08, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Grdnstrk) + +static struct BurnDIPInfo PopspopsDIPList[]= +{ + {0x12, 0xff, 0xff, 0xfa, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x18, 0x10, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Popspops) + +static struct BurnDIPInfo Bubl2000DIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Free Credit" }, + {0x12, 0x01, 0xc0, 0x80, "500k" }, + {0x12, 0x01, 0xc0, 0xc0, "800k" }, + {0x12, 0x01, 0xc0, 0x40, "1000k" }, + {0x12, 0x01, 0xc0, 0x00, "1500k" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 7, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Bubl2000) + +static struct BurnDIPInfo MangchiDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "DSWS" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Vs Rounds" }, + {0x12, 0x01, 0x18, 0x18, "2" }, + {0x12, 0x01, 0x18, 0x10, "3" }, + {0x12, 0x01, 0x18, 0x08, "4" }, + {0x12, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x18, 0x08, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Mangchi) + +static struct BurnDIPInfo FirehawkDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 6, "Difficulty" }, + {0x12, 0x01, 0x0e, 0x06, "Very Easy" }, + {0x12, 0x01, 0x0e, 0x08, "Easy" }, + {0x12, 0x01, 0x0e, 0x0e, "Normal" }, + {0x12, 0x01, 0x0e, 0x02, "Hard" }, + {0x12, 0x01, 0x0e, 0x04, "Hardest" }, + {0x12, 0x01, 0x0e, 0x0c, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Number of Bombs" }, + {0x12, 0x01, 0x20, 0x20, "2" }, + {0x12, 0x01, 0x20, 0x00, "3" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "4" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x13, 0x01, 0x02, 0x02, "English" }, + {0x13, 0x01, 0x02, 0x00, "China" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Continue Coins" }, + {0x13, 0x01, 0x18, 0x18, "1 Coin" }, + {0x13, 0x01, 0x18, 0x08, "2 Coins" }, + {0x13, 0x01, 0x18, 0x10, "3 Coins" }, + {0x13, 0x01, 0x18, 0x00, "4 Coins" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Firehawk) + +static struct BurnDIPInfo Spec2kDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Number of Bombs" }, + {0x12, 0x01, 0x08, 0x08, "2" }, + {0x12, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Copyright Notice" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x18, 0x08, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x13, 0x01, 0xe0, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Spec2k) + +static struct BurnDIPInfo TwinactnDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xe0, 0x00, "Free Play" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x0c, "Easy" }, + {0x13, 0x01, 0x0c, 0x04, "Normal" }, + {0x13, 0x01, 0x0c, 0x08, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x40, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x80, "4" }, + {0x13, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Twinactn) + +static struct BurnDIPInfo BjtwinDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Starting level" }, + {0x12, 0x01, 0x0e, 0x08, "Germany" }, + {0x12, 0x01, 0x0e, 0x04, "Thailand" }, + {0x12, 0x01, 0x0e, 0x0c, "Nevada" }, + {0x12, 0x01, 0x0e, 0x0e, "Japan" }, + {0x12, 0x01, 0x0e, 0x06, "Korea" }, + {0x12, 0x01, 0x0e, 0x0a, "England" }, + {0x12, 0x01, 0x0e, 0x02, "Hong Kong" }, + {0x12, 0x01, 0x0e, 0x00, "China" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x20, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x10, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Bjtwin) + +static struct BurnDIPInfo SabotenbDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x12, 0x01, 0x02, 0x02, "Japanese" }, + {0x12, 0x01, 0x02, 0x00, "English" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Sabotenb) + +static struct BurnDIPInfo NouryokuDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Life Decrease Speed" }, + {0x12, 0x01, 0x03, 0x02, "Slow" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Fast" }, + {0x12, 0x01, 0x03, 0x00, "Very Fast" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x12, 0x01, 0xe0, 0x20, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0x00, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x20, 0x20, "Off" }, +// {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Nouryoku) + +static struct BurnDIPInfo MustangDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xe0, 0x00, "Free Play" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x01, 0x01, "Off" }, +// {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x04, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x08, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x40, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x80, "4" }, + {0x13, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Mustang) + +static struct BurnDIPInfo TdragonbDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "1" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x20, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x10, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x80, 0x80, "Off" }, +// {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x20, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x08, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Tdragonb) + +static struct BurnDIPInfo TdragonDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x20, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x08, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Tdragon) + +static struct BurnDIPInfo AcrobatmDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x13, 0x01, 0x02, 0x02, "Off" }, +// {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x06, 0x02, "50k and 100k" }, + {0x14, 0x01, 0x06, 0x06, "100k and 100k" }, + {0x14, 0x01, 0x06, 0x04, "100k and 200k" }, + {0x14, 0x01, 0x06, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x14, 0x01, 0x08, 0x00, "English" }, + {0x14, 0x01, 0x08, 0x08, "Japanese" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + {0x14, 0x01, 0x30, 0x10, "Easy" }, + {0x14, 0x01, 0x30, 0x20, "Hard" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0xc0, 0x40, "2" }, + {0x14, 0x01, 0xc0, 0xc0, "3" }, + {0x14, 0x01, 0xc0, 0x80, "4" }, + {0x14, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Acrobatm) + +static struct BurnDIPInfo GunnailDIPList[]= +{ + {0x12, 0xff, 0xff, 0xfd, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x12, 0x01, 0x01, 0x01, "Off" }, +// {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x12, 0x01, 0x02, 0x02, "Japanese" }, + {0x12, 0x01, 0x02, 0x00, "English" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x1c, 0x10, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0xe0, 0x80, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xe0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Gunnail) + +//------------------------------------------------------------------------------------------------------------ +// NMK112 chip emulation -- probably should be in an external file + +#define MAXCHIPS 2 +#define TABLESIZE 0x100 +#define BANKSIZE 0x10000 + +static UINT8 page_mask; +static UINT8 current_bank[8]; +static UINT8 *region[2]; +static UINT32 regionlen[2]; + +void NMK112_okibank_write(INT32 offset, UINT8 data) +{ + INT32 chip = (offset & 4) >> 2; + INT32 banknum = offset & 3; + INT32 paged = (page_mask & (1 << chip)); + + UINT8 *rom = region[chip]; + INT32 size = regionlen[chip] - 0x40000; + INT32 bankaddr = (data * BANKSIZE) % size; + + if (current_bank[offset] == data) return; + current_bank[offset] = data; + + if ((paged) && (banknum == 0)) + memcpy (rom + 0x400, rom + 0x40000 + bankaddr+0x400, BANKSIZE-0x400); + else + memcpy (rom + banknum * BANKSIZE, rom + 0x40000 + bankaddr, BANKSIZE); + + if (paged) + { + rom += banknum * TABLESIZE; + memcpy(rom, rom + 0x40000 + bankaddr, TABLESIZE); + } +} + +void NMK112Reset() +{ + memset (current_bank, ~0, sizeof(current_bank)); + NMK112_okibank_write(0, 0); + NMK112_okibank_write(4, 0); +} + +void NMK112_init(UINT8 disable_page_mask, UINT8 *rgn0, UINT8 *rgn1, INT32 len0, INT32 len1) +{ + region[0] = rgn0; + region[1] = rgn1; + regionlen[0] = len0; + regionlen[1] = len1; + page_mask = ~disable_page_mask; + NMK112Reset(); +} + +//------------------------------------------------------------------------------------------------------------ + +#define STRANGE_RAM_WRITE_BYTE(value) \ + if ((address & 0xffff0000) == value) { \ + Drv68KRAM[(address & 0xfffe) | 0] = data; \ + Drv68KRAM[(address & 0xfffe) | 1] = data; \ + return; \ + } \ + +// MAKE SHORT ^^ + +#define STRANGE_RAM_WRITE_WORD(value) \ + if ((address & 0xffff0000) == value) { \ + *((UINT16*)(Drv68KRAM + (address & 0xfffe))) = data; \ + return; \ + } \ + +#define PROT_JSR(_offs_,_protvalue_,_pc_) \ + if(nmk16_mainram[(_offs_)/2] == _protvalue_) \ + { \ + nmk16_mainram[(_offs_)/2] = 0xffff; /*(MCU job done)*/ \ + nmk16_mainram[(_offs_+2-0x10)/2] = 0x4ef9;/*JMP*/\ + nmk16_mainram[(_offs_+4-0x10)/2] = 0x0000;/*HI-DWORD*/\ + nmk16_mainram[(_offs_+6-0x10)/2] = _pc_; /*LO-DWORD*/\ + } \ + +#define PROT_INPUT(_offs_,_protvalue_,_protinput_,_input_) \ + if(nmk16_mainram[_offs_] == _protvalue_) \ + {\ + nmk16_mainram[_protinput_] = ((_input_ & 0xffff0000)>>16);\ + nmk16_mainram[_protinput_+1] = (_input_ & 0x0000ffff);\ + } + +//------------------------------------------------------------------------------------------------------------ +// MCU simulation stuff + +static INT32 prot_count = 0; + +static UINT8 tharrier_mcu_r() +{ + UINT16 *nmk16_mainram = (UINT16*)Drv68KRAM; + + static const UINT8 to_main[15] = + { + 0x82,0xc7,0x00,0x2c,0x6c,0x00,0x9f,0xc7,0x00,0x29,0x69,0x00,0x8b,0xc7,0x00 + }; + + INT32 res; + + if (SekGetPC(-1)==0x08aa) res = (nmk16_mainram[0x9064/2])|0x20; + else if (SekGetPC(-1)==0x08ce) res = (nmk16_mainram[0x9064/2])|0x60; + else if (SekGetPC(-1)==0x0332) res = (nmk16_mainram[0x90f6/2])|0x00; + else if (SekGetPC(-1)==0x64f4) res = (nmk16_mainram[0x90f6/2])|0x00; + else + { + res = to_main[prot_count++]; + if (prot_count > 14) + prot_count = 0; + } + return res; +} + +static void HachaRAMProt(INT32 offset) +{ + UINT16 *nmk16_mainram = (UINT16*)Drv68KRAM; + + switch(offset) + { + case 0xe058/2: PROT_INPUT(0xe058/2,0xc71f,0xe000/2,0x00080000); break; + case 0xe182/2: PROT_INPUT(0xe182/2,0x865d,0xe004/2,0x00080002); break; + case 0xe51e/2: PROT_INPUT(0xe51e/2,0x0f82,0xe008/2,0x00080008); break; + case 0xe6b4/2: PROT_INPUT(0xe6b4/2,0x79be,0xe00c/2,0x0008000a); break; + case 0xe10e/2: PROT_JSR(0xe10e,0x8007,0x870a); //870a not 9d66 + PROT_JSR(0xe10e,0x8000,0xd9c6); break; + case 0xe11e/2: PROT_JSR(0xe11e,0x8038,0x972a); // 972a + PROT_JSR(0xe11e,0x8031,0xd1f8); break; + case 0xe12e/2: PROT_JSR(0xe12e,0x8019,0x9642); // OK-9642 + PROT_JSR(0xe12e,0x8022,0xda06); break; + case 0xe13e/2: PROT_JSR(0xe13e,0x802a,0x9d66); // 9d66 not 9400 - OK + PROT_JSR(0xe13e,0x8013,0x81aa); break; + case 0xe14e/2: PROT_JSR(0xe14e,0x800b,0xb3f2); // b3f2 - OK + PROT_JSR(0xe14e,0x8004,0x8994); break; + case 0xe15e/2: PROT_JSR(0xe15e,0x803c,0xb59e); // b59e - OK + PROT_JSR(0xe15e,0x8035,0x8d0c); break; + case 0xe16e/2: PROT_JSR(0xe16e,0x801d,0x9ac2); // 9ac2 - OK + PROT_JSR(0xe16e,0x8026,0x8c36); break; + case 0xe17e/2: PROT_JSR(0xe17e,0x802e,0xc366); // c366 - OK + PROT_JSR(0xe17e,0x8017,0x870a); break; + case 0xe18e/2: PROT_JSR(0xe18e,0x8004,0xd620); // unused + PROT_JSR(0xe18e,0x8008,0x972a); break; // unused + case 0xe19e/2: PROT_JSR(0xe19e,0x8030,0xd9c6); // OK-d9c6 + PROT_JSR(0xe19e,0x8039,0x9642); break; + case 0xe1ae/2: PROT_JSR(0xe1ae,0x8011,0xd1f8); // d1f8 not c67e + PROT_JSR(0xe1ae,0x802a,0x9d66); break; + case 0xe1be/2: PROT_JSR(0xe1be,0x8022,0xda06); // da06 + PROT_JSR(0xe1be,0x801b,0xb3f2); break; + case 0xe1ce/2: PROT_JSR(0xe1ce,0x8003,0x81aa); // 81aa + PROT_JSR(0xe1ce,0x800c,0xb59e); break; + case 0xe1de/2: PROT_JSR(0xe1de,0x8034,0x8994); // 8994 - OK + PROT_JSR(0xe1de,0x803d,0x9ac2); break; + case 0xe1ee/2: PROT_JSR(0xe1ee,0x8015,0x8d0c); // 8d0c not 82f6 + PROT_JSR(0xe1ee,0x802e,0xc366); break; + case 0xe1fe/2: PROT_JSR(0xe1fe,0x8026,0x8c36); // 8c36 + PROT_JSR(0xe1fe,0x8016,0xd620); break; // unused + case 0xef00/2: + if(nmk16_mainram[0xef00/2] == 0x60fe) + { + nmk16_mainram[0xef00/2] = 0x0000; // this is the coin counter + nmk16_mainram[0xef02/2] = 0x0000; + nmk16_mainram[0xef04/2] = 0x4ef9; + nmk16_mainram[0xef06/2] = 0x0000; + nmk16_mainram[0xef08/2] = 0x7dc2; + } + break; + } +} + +static void tdragon_mainram_w(INT32 offset) +{ + UINT16 *nmk16_mainram = (UINT16*)Drv68KRAM; + + switch(offset) + { + case 0xe066/2: PROT_INPUT(0xe066/2,0xe23e,0xe000/2,0x000c0000); break; + case 0xe144/2: PROT_INPUT(0xe144/2,0xf54d,0xe004/2,0x000c0002); break; + case 0xe60e/2: PROT_INPUT(0xe60e/2,0x067c,0xe008/2,0x000c0008); break; + case 0xe714/2: PROT_INPUT(0xe714/2,0x198b,0xe00c/2,0x000c000a); break; + case 0xe70e/2: PROT_JSR(0xe70e,0x8007,0x9e22); + PROT_JSR(0xe70e,0x8000,0xd518); break; + case 0xe71e/2: PROT_JSR(0xe71e,0x8038,0xaa0a); + PROT_JSR(0xe71e,0x8031,0x8e7c); break; + case 0xe72e/2: PROT_JSR(0xe72e,0x8019,0xac48); + PROT_JSR(0xe72e,0x8022,0xd558); break; + case 0xe73e/2: PROT_JSR(0xe73e,0x802a,0xb110); + PROT_JSR(0xe73e,0x8013,0x96da); break; + case 0xe74e/2: PROT_JSR(0xe74e,0x800b,0xb9b2); + PROT_JSR(0xe74e,0x8004,0xa062); break; + case 0xe75e/2: PROT_JSR(0xe75e,0x803c,0xbb4c); + PROT_JSR(0xe75e,0x8035,0xa154); break; + case 0xe76e/2: PROT_JSR(0xe76e,0x801d,0xafa6); + PROT_JSR(0xe76e,0x8026,0xa57a); break; + case 0xe77e/2: PROT_JSR(0xe77e,0x802e,0xc6a4); + PROT_JSR(0xe77e,0x8017,0x9e22); break; + case 0xe78e/2: PROT_JSR(0xe78e,0x8004,0xaa0a); + PROT_JSR(0xe78e,0x8008,0xaa0a); break; + case 0xe79e/2: PROT_JSR(0xe79e,0x8030,0xd518); + PROT_JSR(0xe79e,0x8039,0xac48); break; + case 0xe7ae/2: PROT_JSR(0xe7ae,0x8011,0x8e7c); + PROT_JSR(0xe7ae,0x802a,0xb110); break; + case 0xe7be/2: PROT_JSR(0xe7be,0x8022,0xd558); + PROT_JSR(0xe7be,0x801b,0xb9b2); break; + case 0xe7ce/2: PROT_JSR(0xe7ce,0x8003,0x96da); + PROT_JSR(0xe7ce,0x800c,0xbb4c); break; + case 0xe7de/2: PROT_JSR(0xe7de,0x8034,0xa062); + PROT_JSR(0xe7de,0x803d,0xafa6); break; + case 0xe7ee/2: PROT_JSR(0xe7ee,0x8015,0xa154); + PROT_JSR(0xe7ee,0x802e,0xc6a4); break; + case 0xe7fe/2: PROT_JSR(0xe7fe,0x8026,0xa57a); + PROT_JSR(0xe7fe,0x8016,0xa57a); break; + case 0xef00/2: + if(nmk16_mainram[0xef00/2] == 0x60fe) + { + nmk16_mainram[0xef00/2] = 0x0000; // this is the coin counter + nmk16_mainram[0xef02/2] = 0x0000; + nmk16_mainram[0xef04/2] = 0x4ef9; + nmk16_mainram[0xef06/2] = 0x0000; + nmk16_mainram[0xef08/2] = 0x92f4; + } + break; + } +} + +static void mcu_run(UINT8 dsw_setting) +{ + static UINT8 input_pressed; + static UINT16 coin_input; + UINT8 dsw[2]; + static UINT8 start_helper = 0; + static UINT8 coin_count[2],coin_count_frac[2]; + static UINT8 i; + + UINT16 *nmk16_mainram = (UINT16*)Drv68KRAM; + + if(start_helper & 1 && nmk16_mainram[0x9000/2] & 0x0200) // start 1 + { + nmk16_mainram[0xef00/2]--; + start_helper = start_helper & 2; + } + if(start_helper & 2 && nmk16_mainram[0x9000/2] & 0x0100) // start 2 + { + nmk16_mainram[0xef00/2]--; + start_helper = start_helper & 1; + } + + if(dsw_setting) // Thunder Dragon + { + dsw[0] = (DrvDips[1] & 0x7); + dsw[1] = (DrvDips[1] & 0x38) >> 3; + for(i=0;i<2;i++) + { + switch(dsw[i] & 7) + { + case 0: nmk16_mainram[0x9000/2]|=0x4000; break; // free play + case 1: coin_count_frac[i] = 1; coin_count[i] = 4; break; + case 2: coin_count_frac[i] = 1; coin_count[i] = 3; break; + case 3: coin_count_frac[i] = 1; coin_count[i] = 2; break; + case 4: coin_count_frac[i] = 4; coin_count[i] = 1; break; + case 5: coin_count_frac[i] = 3; coin_count[i] = 1; break; + case 6: coin_count_frac[i] = 2; coin_count[i] = 1; break; + case 7: coin_count_frac[i] = 1; coin_count[i] = 1; break; + } + } + } + else // Hacha Mecha Fighter + { + dsw[0] = (DrvDips[1] & 0x07) >> 0; + dsw[1] = (DrvDips[1] & 0x38) >> 3; + for(i=0;i<2;i++) + { + switch(dsw[i] & 7) + { + case 0: nmk16_mainram[0x9000/2]|=0x4000; break; // free play + case 1: coin_count_frac[i] = 4; coin_count[i] = 1; break; + case 2: coin_count_frac[i] = 3; coin_count[i] = 1; break; + case 3: coin_count_frac[i] = 2; coin_count[i] = 1; break; + case 4: coin_count_frac[i] = 1; coin_count[i] = 4; break; + case 5: coin_count_frac[i] = 1; coin_count[i] = 3; break; + case 6: coin_count_frac[i] = 1; coin_count[i] = 2; break; + case 7: coin_count_frac[i] = 1; coin_count[i] = 1; break; + } + } + } + + // read the coin port + coin_input = (~(DrvInputs[0])); + + if(coin_input & 0x01) // coin 1 + { + if((input_pressed & 0x01) == 0) + { + if(coin_count_frac[0] != 1) + { + nmk16_mainram[0xef02/2]+=coin_count[0]; + if(coin_count_frac[0] == nmk16_mainram[0xef02/2]) + { + nmk16_mainram[0xef00/2]+=coin_count[0]; + nmk16_mainram[0xef02/2] = 0; + } + } + else + nmk16_mainram[0xef00/2]+=coin_count[0]; + } + input_pressed = (input_pressed & 0xfe) | 1; + } + else + input_pressed = (input_pressed & 0xfe); + + if(coin_input & 0x02) // coin 2 + { + if((input_pressed & 0x02) == 0) + { + if(coin_count_frac[1] != 1) + { + nmk16_mainram[0xef02/2]+=coin_count[1]; + if(coin_count_frac[1] == nmk16_mainram[0xef02/2]) + { + nmk16_mainram[0xef00/2]+=coin_count[1]; + nmk16_mainram[0xef02/2] = 0; + } + } + else + nmk16_mainram[0xef00/2]+=coin_count[1]; + } + input_pressed = (input_pressed & 0xfd) | 2; + } + else + input_pressed = (input_pressed & 0xfd); + + if(coin_input & 0x04) // service 1 + { + if((input_pressed & 0x04) == 0) + nmk16_mainram[0xef00/2]++; + input_pressed = (input_pressed & 0xfb) | 4; + } + else + input_pressed = (input_pressed & 0xfb); + + if(nmk16_mainram[0xef00/2] > 0 && nmk16_mainram[0x9000/2] & 0x8000) //enable start button + { + if(coin_input & 0x08) // start 1 + { + if((input_pressed & 0x08) == 0 && (!(nmk16_mainram[0x9000/2] & 0x0200))) // start 1 + start_helper = 1; + + input_pressed = (input_pressed & 0xf7) | 8; + } + else + input_pressed = (input_pressed & 0xf7); + + if(coin_input & 0x10) // start 2 + { + if((input_pressed & 0x10) == 0 && (!(nmk16_mainram[0x9000/2] & 0x0100))) // start 2 + start_helper = (nmk16_mainram[0x9000/2] == 0x8000) ? (3) : (2); + + input_pressed = (input_pressed & 0xef) | 0x10; + } + else + input_pressed = (input_pressed & 0xef); + } +} + +//------------------------------------------------------------------------------------------------- + +void __fastcall tharrier_main_write_byte(UINT32 address, UINT8 data) +{ + STRANGE_RAM_WRITE_BYTE(0xf0000) +} + +void __fastcall tharrier_main_write_word(UINT32 address, UINT16 data) +{ + STRANGE_RAM_WRITE_WORD(0xf0000) + + switch (address) + { + case 0x080010: // mcu write.. unused... + return; + + case 0x08001e: + *soundlatch = data; + return; + } +} + +UINT8 __fastcall tharrier_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0] >> 8; + + case 0x080001: + return DrvInputs[0]; + + case 0x080002: + return tharrier_mcu_r(); + + case 0x080003: + return DrvInputs[1]; + + case 0x080004: + return DrvDips[1]; + + case 0x080005: + return DrvDips[0]; + + case 0x08000e: + case 0x08000f: + return *soundlatch2; + + case 0x080202: + return DrvInputs[2] >> 8; + + case 0x080203: + return DrvInputs[2]; + } + + return 0; +} + +UINT16 __fastcall tharrier_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080004: + return (DrvDips[0] << 8) | DrvDips[1]; + + case 0x08000e: + return *soundlatch2; + + case 0x080202: + return DrvInputs[2]; + } + + return 0; +} + +void __fastcall manybloc_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x08001e: + case 0x08001f: + *soundlatch = data; + return; + } +} + +void __fastcall manybloc_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x08001e: + *soundlatch = data; + return; + } +} + +UINT8 __fastcall manybloc_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0] >> 8; + + case 0x080001: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1] >> 8; + + case 0x080003: + return DrvInputs[1]; + + case 0x080004: + return DrvDips[0]; + + case 0x080005: + return DrvDips[1]; + + case 0x08001e: + case 0x08001f: + return *soundlatch2; + } + + return 0; +} + +UINT16 __fastcall manybloc_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080004: + return (DrvDips[0] << 8) | DrvDips[1]; + + case 0x08001e: + return *soundlatch2; + } + + return 0; +} + +void __fastcall ssmissin_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x0c0014: + case 0x0c0015: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + case 0x0c0019: + if (data != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + case 0x0c001f: + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } +} + +void __fastcall ssmissin_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x0c0014: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } +} + +UINT8 __fastcall ssmissin_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + return DrvInputs[0] >> 8; + + case 0x0c0001: + return DrvInputs[0]; + + case 0x0c0004: + return DrvInputs[1] >> 8; + + case 0x0c0005: + return DrvInputs[1]; + + case 0x0c0006: + return DrvDips[0]; + + case 0x0c0007: + return DrvDips[1]; + } + + return 0; +} + +UINT16 __fastcall ssmissin_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + return DrvInputs[0]; + + case 0x0c0004: + return DrvInputs[1]; + + case 0x0c0006: + return (DrvDips[0] << 8) | DrvDips[1]; + } + + return 0; +} + +static void macross2_sound_sync() +{ +/* INT32 cycles = (SekTotalCycles() * 4) / 10; + + if (cycles > ZetTotalCycles() && cycles < 71429) { + BurnTimerUpdate(cycles); + }*/ +} + +UINT8 __fastcall macross2_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0] >> 8; + + case 0x100001: + return DrvInputs[0]; + + case 0x100002: + return DrvInputs[1] >> 8; + + case 0x100003: + return DrvInputs[1]; + + case 0x100008: + case 0x100009: + return DrvDips[0]; + + case 0x10000a: + case 0x10000b: + return DrvDips[1]; + + case 0x10000e: + case 0x10000f: + if (macross2_sound_enable) { + macross2_sound_sync(); + } + return *soundlatch2; + } + + return 0; +} + +UINT16 __fastcall macross2_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0]; + + case 0x100002: + return DrvInputs[1]; + + case 0x100008: + return (DrvDips[0] << 8) | DrvDips[0]; + + case 0x10000a: + return (DrvDips[1] << 8) | DrvDips[1]; + + case 0x10000e: + if (macross2_sound_enable) { + macross2_sound_sync(); + } + return *soundlatch2; + } + + return 0; +} + +void __fastcall macross2_main_write_byte(UINT32 address, UINT8 data) +{ + bprintf (0, _T("%x, %x wb\n"), address, data); + + switch (address) + { + case 0x100014: + case 0x100015: + // *flipscreen = data & 1; + return; + } +} + +void __fastcall macross2_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x100014: + // *flipscreen = data & 1; + return; + + case 0x100016: + bprintf (0, _T("%x, %x ww\n"), address, data); + if (data == 0) { + if (macross2_sound_enable != 0) { + macross2_sound_sync(); + ZetReset(); + } + } else { +// INT32 cycles = ((SekTotalCycles() * 4) / 10) - ZetTotalCycles(); +// if (cycles > 0 && cycles < 71429) { +// ZetIdle(cycles); +// } + } + + macross2_sound_enable = data; + return; + + case 0x100018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x10001e: + if (macross2_sound_enable) { + macross2_sound_sync(); + } + + *soundlatch = data; + return; + } +} + +void __fastcall afega_main_write_word(UINT32 address, UINT16 data) +{ + if (address & 0xfff00000) { + SekWriteWord(address & 0xfffff, data); + return; + } + + STRANGE_RAM_WRITE_WORD(0xc0000) + STRANGE_RAM_WRITE_WORD(0xf0000) + + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + + case 0x08001e: + *soundlatch = data & 0xff; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } +} + +void __fastcall afega_main_write_byte(UINT32 address, UINT8 data) +{ + if (address & 0xfff00000) { + SekWriteByte(address & 0xfffff, data); + return; + } + + STRANGE_RAM_WRITE_BYTE(0xc0000) + STRANGE_RAM_WRITE_BYTE(0xf0000) + + switch (address) + { + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x08001e: + case 0x08001f: + *soundlatch = data & 0xff; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + } +} + +UINT8 __fastcall afega_main_read_byte(UINT32 address) +{ + if (address & 0xfff00000) { + return SekReadByte(address & 0xfffff); + } + + switch (address) + { + case 0x080000: + return DrvInputs[0] >> 8; + + case 0x080001: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1] >> 8; + + case 0x080003: + return DrvInputs[1]; + + case 0x080004: + return DrvDips[0]; + + case 0x080005: + return DrvDips[1]; + + case 0x080012: + case 0x080013: + return 0x01; + } + + return 0; +} + +UINT16 __fastcall afega_main_read_word(UINT32 address) +{ + if (address & 0xfff00000) { + return SekReadWord(address & 0xfffff); + } + + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080004: + return ((DrvDips[0] << 8) | DrvDips[1]); + + case 0x080012: + return 0x0100; + } + + return 0; +} + +void __fastcall bjtwin_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x094000: + case 0x094001: + if (data != 0xff) { + *tilebank = data; + } + return; + } +} + +void __fastcall bjtwin_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x084000: + MSM6295Command(0, data & 0xff); + return; + + case 0x084010: + MSM6295Command(1, data & 0xff); + return; + + case 0x084020: + case 0x084022: + case 0x084024: + case 0x084026: + case 0x084028: + case 0x08402a: + case 0x08402c: + case 0x08402e: + NMK112_okibank_write((address >> 1) & 7, data); + return; + + case 0x094000: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + } +} + +UINT8 __fastcall bjtwin_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0] >> 8; + + case 0x080001: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1] >> 8; + + case 0x080003: + return DrvInputs[1]; + + case 0x080008: + case 0x080009: + return DrvDips[0]; + + case 0x08000a: + case 0x08000b: + return DrvDips[1]; + + case 0x084000: + case 0x084001: + return MSM6295ReadStatus(0); + + case 0x084010: + case 0x084011: + return MSM6295ReadStatus(1); + } + + return 0; +} + +UINT16 __fastcall bjtwin_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080008: + return 0xff00 | DrvDips[0]; + + case 0x08000a: + return 0xff00 | DrvDips[1]; + + case 0x084000: + return MSM6295ReadStatus(0); + + case 0x084010: + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall mustangb_main_write_word(UINT32 address, UINT16 data) +{ + STRANGE_RAM_WRITE_WORD(0xf0000) + + switch (address) + { + case 0x080014: + case 0x0c0014: + // *flipscreen = data & 1; + return; + + case 0x08001e: + case 0x0c001e: + // bprintf (0, _T("%6.6x, %x,\n"), SekGetPC(-1), data); + seibu_sound_mustb_write_word(0, data); + return; + } +} + +void __fastcall mustangb_main_write_byte(UINT32 address, UINT8 data) +{ + STRANGE_RAM_WRITE_BYTE(0xf0000) + + switch (address) + { + case 0x080014: + case 0x080015: + case 0x0c0014: + case 0x0c0015: + // *flipscreen = data & 1; + return; + + case 0x08001e: + case 0x08001f: + case 0x0c001e: + case 0x0c001f: + // bprintf (0, _T("%6.6x, %x,\n"), SekGetPC(-1), data); + seibu_sound_mustb_write_word(0, data); + return; + } +} + +UINT16 __fastcall mustangb_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x0c0000: + return DrvInputs[0]; + + case 0x080002: + case 0x0c0002: + return DrvInputs[1]; + + case 0x080004: + case 0x0c0008: + return (DrvDips[0] << 8) | DrvDips[1]; + + case 0x0c000a: + return 0xff00 | DrvDips[1]; + } + + return 0; +} + +UINT8 __fastcall mustangb_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x0c0000: + return DrvInputs[0] >> 8; + + case 0x080001: + case 0x0c0001: + return DrvInputs[0]; + + case 0x080002: + case 0x0c0002: + return DrvInputs[1] >> 8; + + case 0x080003: + case 0x0c0003: + return DrvInputs[1]; + + case 0x080004: + case 0x0c0008: + return DrvDips[1]; + + case 0x080005: + case 0x0c0009: + return DrvDips[0]; + + case 0x0c000a: + case 0x0c000b: + return DrvDips[1]; + } + + return 0; +} + +UINT8 __fastcall mustang_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x080001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x080002: + case 0x080003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x080004: + case 0x080005: + return DrvDips[address & 1]; + + case 0x08000e: + case 0x08000f: + return NMK004Read(); + } + + return 0; +} + +UINT16 __fastcall mustang_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080004: + return (DrvDips[0] << 8) | DrvDips[1]; + + case 0x08000e: + return NMK004Read(); + } + + return 0; +} + +void __fastcall mustang_main_write_word(UINT32 address, UINT16 data) +{ + STRANGE_RAM_WRITE_WORD(0xf0000) + + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x08001e: + NMK004Write(0, data); + return; + } +} + +void __fastcall mustang_main_write_byte(UINT32 address, UINT8 data) +{ + STRANGE_RAM_WRITE_BYTE(0xf0000) +} + +UINT8 __fastcall acrobatm_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + case 0x0c0001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x0c0002: + case 0x0c0003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x0c0008: + case 0x0c0009: + return DrvDips[0]; + + case 0x0c000a: + case 0x0c000b: + return DrvDips[1]; + } + + return 0; +} + +UINT16 __fastcall acrobatm_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + return DrvInputs[0]; + + case 0x0c0002: + return DrvInputs[1]; + + case 0x0c0008: + return DrvDips[0]; + + case 0x0c000a: + return DrvDips[1]; + + case 0x0c000e: + return NMK004Read(); + } + + return 0; +} + +void __fastcall acrobatm_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x0c0014: + case 0x0c0015: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + case 0x0c0019: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + case 0x0c001f: + NMK004Write(0, data); + return; + } +} + +void __fastcall acrobatm_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x0c0014: + case 0x0c0015: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + case 0x0c0019: + if (data != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + case 0x0c001f: + NMK004Write(0, data); + return; + } +} + +UINT8 __fastcall tdragon_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + case 0x0c0001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x0c0002: + case 0x0c0003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x0c0008: + case 0x0c0009: + return DrvDips[0]; + + case 0x0c000a: + case 0x0c000b: + return DrvDips[1]; + } + + return 0; +} + +UINT16 __fastcall tdragon_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x0c0000: + return DrvInputs[0]; + + case 0x0c0002: + return DrvInputs[1]; + + case 0x0c0008: + return DrvDips[0]; + + case 0x0c000a: + return DrvDips[1]; + + case 0x0c000e: + return NMK004Read(); + } + + return 0; +} + +void __fastcall tdragon_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffff0000) == 0x0b0000) { + *((UINT16*)(Drv68KRAM + (address & 0xfffe))) = data; + tdragon_mainram_w((address >> 1) & 0x7fff); + return; + } + + switch (address) + { + case 0x0c0014: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + NMK004Write(0, data); + return; + } +} + +void __fastcall tdragon_main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffff0000) == 0x0b0000) { + Drv68KRAM [(address & 0xffff) ^ 1] = data; + tdragon_mainram_w((address >> 1) & 0x7fff); + return; + } + + switch (address) + { + case 0x0c0014: + case 0x0c0015: + // *flipscreen = data & 1; + return; + + case 0x0c0018: + case 0x0c0019: + if (data != 0xff) { + *tilebank = data; + } + return; + + case 0x0c001e: + case 0x0c001f: + NMK004Write(0, data); + return; + } +} + + +UINT8 __fastcall macross_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x080001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x080002: + case 0x080003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x080008: + case 0x080009: + return DrvDips[0]; + + case 0x08000a: + case 0x08000b: + return DrvDips[1]; + + case 0x08000e: + case 0x08000f: + return NMK004Read(); + } + + return 0; +} + +UINT16 __fastcall macross_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080008: + return (DrvDips[0] << 8) | DrvDips[0]; + + case 0x08000a: + return (DrvDips[1] << 8) | DrvDips[1]; + + case 0x08000e: + return NMK004Read(); + } + + return 0; +} + +void __fastcall macross_main_write_word(UINT32 address, UINT16 data) +{ + STRANGE_RAM_WRITE_WORD(0xf0000) + + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x080018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x08001e: + NMK004Write(0, data); + return; + + case 0x084000: + if ((data & 0xff) != 0xff) + *tilebank = data; // bioship + return; + } +} + +void __fastcall macross_main_write_byte(UINT32 address, UINT8 data) +{ + STRANGE_RAM_WRITE_BYTE(0xf0000) + + switch (address) + { + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x080018: + case 0x080019: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x08001e: + case 0x08001f: + NMK004Write(0, data); + return; + + case 0x084000: + case 0x084001: + if ((data & 0xff) != 0xff) { + *tilebank = data; // bioship + } + return; + } +} + +void __fastcall vandykeb_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x080010: + *((UINT16 *)(DrvScrollRAM + 0x06)) = data; + return; + + case 0x080012: + *((UINT16 *)(DrvScrollRAM + 0x04)) = data; + return; + + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x080018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x08001a: + *((UINT16 *)(DrvScrollRAM + 0x02)) = data; + return; + + case 0x08001c: + *((UINT16 *)(DrvScrollRAM + 0x00)) = data; + return; + + case 0x08001e: + // write to PIC + return; + } +} + +void __fastcall vandykeb_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x080010: + DrvScrollRAM[7] = data; + return; + + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x080018: + case 0x080019: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x08001a: + DrvScrollRAM[3] = data; + return; + + case 0x08001e: + case 0x08001f: + // write to PIC + return; + } +} + +UINT8 __fastcall hachamf_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x080001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x080002: + case 0x080003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x08000a: + case 0x08000b: + return 0; // ?? + + case 0x08000e: + case 0x08000f: + return NMK004Read(); + } + + return 0; +} + +UINT16 __fastcall hachamf_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080008: + return (DrvDips[0] << 8) | DrvDips[1]; + + case 0x08000a: + return 0; // ?? + + case 0x08000e: + return NMK004Read(); + } + + return 0; +} + +void __fastcall hachamf_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffff0000) == 0xf0000) { + *((UINT16*)(Drv68KRAM + (address & 0xfffe))) = data; + HachaRAMProt((address & 0xffff) >> 1); + return; + } + + switch (address) + { + case 0x080014: + // *flipscreen = data & 1; + return; + + case 0x080018: + if ((data & 0xff) != 0xff) { + *tilebank = data & 0xff; + } + return; + + case 0x08001e: + NMK004Write(0, data); + return; + } +} + +void __fastcall hachamf_main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffff0000) == 0xf0000) { + Drv68KRAM[(address & 0xffff) ^ 1] = data; + HachaRAMProt((address & 0xffff) >> 1); + return; + } + + switch (address) + { + case 0x080014: + case 0x080015: + // *flipscreen = data & 1; + return; + + case 0x080018: + case 0x080019: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x08001e: + case 0x08001f: + NMK004Write(0, data); + return; + } +} + +void __fastcall raphero_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x100014: + case 0x100015: + // *flipscreen = data & 1; + return; + + case 0x100018: + case 0x100019: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x10001e: + case 0x10001f: + *soundlatch = data; + return; + } +} + +void __fastcall raphero_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x100014: + // *flipscreen = data & 1; + return; + + case 0x100018: + if ((data & 0xff) != 0xff) { + *tilebank = data; + } + return; + + case 0x10001e: + *soundlatch = data & 0xff; + return; + } +} + +UINT8 __fastcall raphero_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x100000: + case 0x100001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x100002: + case 0x100003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x100008: + case 0x100009: + return DrvDips[0]; + + case 0x10000a: + case 0x10000b: + return DrvDips[1]; + + case 0x10000e: + case 0x10000f: + return *soundlatch2; + } + + return 0; +} + +UINT16 __fastcall raphero_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0]; + + case 0x100002: + return DrvInputs[1]; + + case 0x100008: + return DrvDips[0]; + + case 0x10000a: + return DrvDips[1]; + + case 0x10000e: + return *soundlatch2; + } + + return 0; +} + + +//----------------------------------------------------------------------------------------------------- + + +static void tharrier_sound_bankswitch(UINT8 *rom, INT32 bank) +{ + if (bank < 3) { + memcpy (rom + 0x20000, rom + 0x40000 + (bank * 0x20000), 0x20000); + } +} + +void __fastcall tharrier_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf000: + *soundlatch2 = data; + return; + + case 0xf400: + MSM6295Command(0, data); + return; + + case 0xf500: + MSM6295Command(0, data); + return; + + case 0xf600: + tharrier_sound_bankswitch(DrvSndROM0, data & 3); + return; + + case 0xf700: + tharrier_sound_bankswitch(DrvSndROM1, data & 3); + return; + } +} + +UINT8 __fastcall tharrier_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf000: + return *soundlatch; + + case 0xf400: + return MSM6295ReadStatus(0); + + case 0xf500: + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall tharrier_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM2203Write(0, 0, data); + return; + + case 0x01: + BurnYM2203Write(0, 1, data); + return; + } +} + +UINT8 __fastcall tharrier_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + return BurnYM2203Read(0, 0); + } + + return 0; +} + +static void ssmissin_okibank(INT32 bank) +{ + memcpy(DrvSndROM0 + 0x20000, DrvSndROM0 + 0x40000 + (bank & 3) * 0x20000, 0x20000); +} + +void __fastcall ssmissin_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + ssmissin_okibank(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall ssmissin_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +void __fastcall afega_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf808: + BurnYM2151SelectRegister(data); + return; + + case 0xf809: + BurnYM2151WriteRegister(data); + return; + + case 0xf80a: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall afega_sound_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xf808: + case 0xf809: + return BurnYM2151ReadStatus(); + + case 0xf80a: + return MSM6295ReadStatus(0); + } + + return 0; +} + +void __fastcall firehawk_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xfff2: + if (data == 0xfe) + memcpy (DrvSndROM1, DrvSndROM1 + 0x40000, 0x40000); + else if(data == 0xff) + memcpy (DrvSndROM1, DrvSndROM1 + 0x80000, 0x40000); + return; + + case 0xfff8: + MSM6295Command(1, data); + return; + + case 0xfffa: + MSM6295Command(0, data); + return; + } + + if (address >= 0xfe00) { + DrvZ80RAM[address & 0xfff] = data; + return; + } +} + +UINT8 __fastcall firehawk_sound_read(UINT16 address) +{ + switch (address) + { + case 0xfff0: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + + case 0xfff8: + return MSM6295ReadStatus(1); + + case 0xfffa: + return MSM6295ReadStatus(0); + } + + if (address >= 0xfe00) { + return DrvZ80RAM[address & 0xfff]; + } + + return 0; +} + +static void macross2_sound_bank(INT32 bank) +{ + bank = (bank & 7) * 0x4000; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x10000 + bank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x10000 + bank); +} + +void __fastcall macross2_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe001: + macross2_sound_bank(data); + return; + + case 0xf000: + *soundlatch2 = data; + return; + } +} + +UINT8 __fastcall macross2_sound_read(UINT16 address) +{ + if (address == 0xf000) return *soundlatch; + + return 0; +} + +void __fastcall macross2_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM2203Write(0, 0, data); + return; + + case 0x01: + BurnYM2203Write(0, 1, data); + return; + + case 0x80: + MSM6295Command(0, data); + return; + + case 0x88: + MSM6295Command(1, data); + return; + + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + NMK112_okibank_write(port & 7, data); + return; + } +} + +UINT8 __fastcall macross2_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + return BurnYM2203Read(0, 0); + + case 0x80: + return MSM6295ReadStatus(0); + + case 0x88: + return MSM6295ReadStatus(1); + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------- + +static void DrvYM2203IrqHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static void DrvYM2151IrqHandler(INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +inline static INT32 Macross2SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 4000000); +} + +inline static double Macross2GetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static void NMK004YM2203IrqHandler(INT32, INT32 nStatus) +{ + NMK004_irq(nStatus); +} + +inline static double NMK004GetTime() +{ + return (double)SekTotalCycles() / nNMK004CpuSpeed; +} + +inline static INT32 NMK004SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(SekTotalCycles() * nSoundRate / nNMK004CpuSpeed); +} + +static void MSM6295SetInitialBanks(INT32 chips) +{ + INT32 len = DrvSndROM1 - DrvSndROM0; + + for (INT32 i = 0; i < chips; i++) { + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[i][nChannel] = MSM6295ROM + (i * len) + (nChannel << 8); + MSM6295SampleData[i][nChannel] = MSM6295ROM + (i * len) + (nChannel << 16); + } + } +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + MSM6295SetInitialBanks(2); + + macross2_sound_enable = -1; + prot_count = 0; + + return 0; +} + +static INT32 SmissinDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + + return 0; +} + +static INT32 AfegaDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + MSM6295SetInitialBanks(2); + + return 0; +} + +static INT32 BjtwinDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + + NMK112Reset(); + MSM6295SetInitialBanks(2); + + return 0; +} + +static INT32 SeibuSoundDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + seibu_sound_reset(); + MSM6295SetInitialBanks(2); + + return 0; +} + +static INT32 NMK004DoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + MSM6295SetInitialBanks(2); + + NMK004_init(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x030000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x800000; + DrvGfxROM2 = Next; Next += 0x800000; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "raphero") == 0) { + Next += 0x800000; + } + + DrvTileROM = Next; Next += 0x020000; + + MSM6295ROM = Next; + + DrvSndROM0 = Next; Next += 0x300000; + DrvSndROM1 = Next; Next += 0x300000; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "raphero") == 0) { + Next += 0x600000; + } + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvPalRAM = Next; Next += 0x000800; + Drv68KRAM = Next; Next += 0x010000; + DrvBgRAM0 = Next; Next += 0x004000; + DrvBgRAM1 = Next; Next += 0x004000; + DrvBgRAM2 = Next; Next += 0x004000; + DrvBgRAM3 = Next; Next += 0x004000; + DrvTxRAM = Next; Next += 0x001000; + DrvScrollRAM = Next; Next += 0x001000; + + DrvSprBuf = Next; Next += 0x001000; + DrvSprBuf2 = Next; Next += 0x001000; + + DrvZ80RAM = Next; Next += 0x002000; + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + tilebank = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode(INT32 len0, INT32 len1, INT32 len2) +{ + INT32 Plane[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x200, 0x204, 0x208, 0x20c, 0x210, 0x214, 0x218, 0x21c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc((len2 >= len1) ? len2 : len1); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, len0); + + GfxDecode((len0 * 2) / ( 8 * 8), 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, len1); + + GfxDecode((len1 * 2) / (16 * 16), 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, len2); + + GfxDecode((len2 * 2) / (16 * 16), 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + nGraphicsMask[0] = ((len0 * 2) / ( 8 * 8)) - 1; + nGraphicsMask[1] = ((len1 * 2) / (16 * 16)) - 1; + nGraphicsMask[2] = ((len2 * 2) / (16 * 16)) - 1; + + BurnFree (tmp); + + return 0; +} + +static INT32 BjtwinGfxDecode(INT32 len0, INT32 len1, INT32 len2) +{ + INT32 Plane[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x200, 0x204, 0x208, 0x20c, 0x210, 0x214, 0x218, 0x21c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc((len2 >= len1) ? len2 : len1); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, len0); + + GfxDecode((len0 * 2) / ( 8 * 8), 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, len1); + + GfxDecode((len1 * 2) / ( 8 * 8), 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, len2); + + GfxDecode((len2 * 2) / (16 * 16), 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + nGraphicsMask[0] = ((len0 * 2) / ( 8 * 8)) - 1; + nGraphicsMask[1] = ((len1 * 2) / ( 8 * 8)) - 1; + nGraphicsMask[2] = ((len2 * 2) / (16 * 16)) - 1; + + BurnFree (tmp); + + return 0; +} + +static INT32 GrdnstrmGfxDecode(INT32 len0, INT32 len1, INT32 len2) +{ + INT32 Plane[8] = { 0x000, 0x001, 0x002, 0x003, (len1*4), (len1*4)+1, (len1*4)+2, (len1*4)+3 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x200, 0x204, 0x208, 0x20c, 0x210, 0x214, 0x218, 0x21c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc((len2 >= len1) ? len2 : len1); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, len0); + + GfxDecode((len0 * 2) / ( 8 * 8), 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, len1); + + GfxDecode((len1 * 1) / (16 * 16), 8, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, len2); + + GfxDecode((len2 * 2) / (16 * 16), 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + nGraphicsMask[0] = ((len0 * 2) / ( 8 * 8)) - 1; + nGraphicsMask[1] = ((len1 * 1) / (16 * 16)) - 1; + nGraphicsMask[2] = ((len2 * 2) / (16 * 16)) - 1; + is_8bpp = 1; + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 (*pLoadCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(tharrier_sound_write); + ZetSetReadHandler(tharrier_sound_read); + ZetSetOutHandler(tharrier_sound_out); + ZetSetInHandler(tharrier_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(56.00); + + BurnYM2203Init(1, 1500000, &DrvYM2203IrqHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + + MSM6295Init(0, 4000000 / 165, 20.0, 1); + MSM6295Init(1, 4000000 / 165, 20.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 BjtwinInit(INT32 (*pLoadCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x09c000, 0x09cfff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x09d000, 0x09dfff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, bjtwin_main_write_word); + SekSetWriteByteHandler(0, bjtwin_main_write_byte); + SekSetReadWordHandler(0, bjtwin_main_read_word); + SekSetReadByteHandler(0, bjtwin_main_read_byte); + SekClose(); + + BurnSetRefreshRate(56.00); + + MSM6295Init(0, 4000000 / 165, 20.0, 1); + MSM6295Init(1, 4000000 / 165, 20.0, 1); + + NMK112_init(0, DrvSndROM0, DrvSndROM1, 0x140000, 0x140000); + + GenericTilesInit(); + + BjtwinDoReset(); + + return 0; +} + +static INT32 Macross2Init() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM, 0x20000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x400000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 6, 1)) return 1; + memcpy (DrvSndROM0, DrvSndROM0 + 0x40000, 0x40000); + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 7, 1)) return 1; + memcpy (DrvSndROM1, DrvSndROM1 + 0x40000, 0x40000); + + DrvGfxDecode(0x20000, 0x200000, 0x400000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x130000, 0x1307ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x140000, 0x143fff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x144000, 0x147fff, SM_RAM); + SekMapMemory(DrvBgRAM2, 0x148000, 0x14bfff, SM_RAM); + SekMapMemory(DrvBgRAM3, 0x14c000, 0x14ffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x170000, 0x170fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x171000, 0x171fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x1f0000, 0x1fffff, SM_RAM); + SekSetWriteWordHandler(0, macross2_main_write_word); + SekSetWriteByteHandler(0, macross2_main_write_byte); + SekSetReadWordHandler(0, macross2_main_read_word); + SekSetReadByteHandler(0, macross2_main_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x8000); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM); + ZetSetWriteHandler(macross2_sound_write); + ZetSetReadHandler(macross2_sound_read); + ZetSetOutHandler(macross2_sound_out); + ZetSetInHandler(macross2_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(56.00); + + BurnYM2203Init(1, 1500000, &DrvYM2203IrqHandler, Macross2SynchroniseStream, Macross2GetTime, 0); + BurnTimerAttachZet(4000000); + + MSM6295Init(0, 4000000 / 165, 20.0, 1); + MSM6295Init(1, 4000000 / 165, 20.0, 1); + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "macross2") == 0) { + NMK112_init(0, DrvSndROM0, DrvSndROM1, 0x240000, 0x140000); + } else { + NMK112_init(0, DrvSndROM0, DrvSndROM1, 0x240000, 0x240000); + } + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 MSM6295x1Init(INT32 (*pLoadCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(ssmissin_sound_write); + ZetSetReadHandler(ssmissin_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(56.00); + + MSM6295Init(0, 1000000 / 165, 100.0, 0); + + GenericTilesInit(); + + SmissinDoReset(); + + return 0; +} + +static INT32 SeibuSoundInit(INT32 (*pLoadCallback)(), INT32 type) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + + if (type) { // mustangb + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + } else { // tdragonb + SekMapMemory(Drv68KRAM, 0x0b0000, 0x0bffff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x0c4000, 0x0c43ff, SM_WRITE); + SekMapMemory(DrvPalRAM, 0x0c8000, 0x0c87ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x0cc000, 0x0cffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d0000, 0x0d07ff, SM_RAM); + } + SekSetWriteWordHandler(0, mustangb_main_write_word); + SekSetWriteByteHandler(0, mustangb_main_write_byte); + SekSetReadWordHandler(0, mustangb_main_read_word); + SekSetReadByteHandler(0, mustangb_main_read_byte); + SekClose(); + + BurnSetRefreshRate(56.00); + + SeibuZ80ROM = DrvZ80ROM; + SeibuZ80RAM = DrvZ80RAM; + seibu_sound_init(0, 0, 3579545, 3579545, 1320000 / 132); + + GenericTilesInit(); + + SeibuSoundDoReset(); + + return 0; +} + +static INT32 AfegaInit(INT32 (*pLoadCallback)(), void (*pZ80Callback)(), INT32 pin7high) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadCallback) { + if (pLoadCallback()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x084000, 0x0843ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0c0000, 0x0cffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, afega_main_write_word); + SekSetWriteByteHandler(0, afega_main_write_byte); + SekSetReadWordHandler(0, afega_main_read_word); + SekSetReadByteHandler(0, afega_main_read_byte); + SekClose(); + + if (pZ80Callback) { + pZ80Callback(); + } + + BurnSetRefreshRate(56.00); + + BurnYM2151Init(4000000, 70.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1000000 / (pin7high ? 132 : 165), 60.0, 1); + MSM6295Init(1, 1000000 / (pin7high ? 132 : 165), 60.0, 1); + + GenericTilesInit(); + + AfegaDoReset(); + + return 0; +} + +static INT32 NMK004Init(INT32 (*pLoadCallback)(), INT32 nCpuSpeed, INT32 pin7high, INT32 irq2) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + nNMK004CpuSpeed = nCpuSpeed; + nNMK004EnableIrq2 = irq2; + + if (pLoadCallback) { + pLoadCallback(); + } + + BurnSetRefreshRate(56.00); + + BurnYM2203Init(1, 1500000, &NMK004YM2203IrqHandler, NMK004SynchroniseStream, NMK004GetTime, 0); + BurnTimerAttachSek(nNMK004CpuSpeed); + + MSM6295Init(0, 4000000 / (pin7high ? 132 : 165), 20.0, 1); + MSM6295Init(1, 4000000 / (pin7high ? 132 : 165), 20.0, 1); + + NMK004OKIROM0 = DrvSndROM0; + NMK004OKIROM1 = DrvSndROM1; + NMK004PROGROM = DrvZ80ROM; + + GenericTilesInit(); + + NMK004DoReset(); + + return 0; +} + +static INT32 CommonExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + MSM6295ROM = NULL; + + SekExit(); + + BurnFree (AllMem); + + input_high[0] = input_high[1] = 0; + is_8bpp = 0; + global_y_offset = 16; + videoshift = 0; + screen_flip_y = 0; + + return 0; +} + +static INT32 SeibuSoundExit() +{ + GenericTilesExit(); + + seibu_sound_exit(); + SekExit(); + + BurnFree (AllMem); + + input_high[0] = input_high[1] = 0; + is_8bpp = 0; + global_y_offset = 16; + videoshift = 0; + + return 0; +} + +static INT32 AfegaExit() +{ + BurnYM2151Exit(); + MSM6295Exit(1); + ZetExit(); + + return CommonExit(); +} + +static INT32 BjtwinExit() +{ + BurnYM2151Exit(); + MSM6295Exit(1); + + return CommonExit(); +} + +static INT32 DrvExit() +{ + BurnYM2203Exit(); + MSM6295Exit(1); + ZetExit(); + + return CommonExit(); +} + +static INT32 NMK004Exit() +{ + BurnYM2203Exit(); + MSM6295Exit(1); + + return CommonExit(); +} + +//------------------------------------------------------------------------------------------------------------------ + +static void DrvPaletteRecalc() +{ + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x400; i++) { + INT32 data = pal[i]; + + r = ((data >> 11) & 0x1e) | ((data >> 3) & 0x01); + g = ((data >> 7) & 0x1e) | ((data >> 2) & 0x01); + b = ((data >> 3) & 0x1e) | ((data >> 1) & 0x01); + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites(INT32 flip, INT32 coloff, INT32 coland, INT32 priority) +{ + UINT16 *sprram = (UINT16*)DrvSprBuf2; + + for (INT32 offs = 0; offs < 0x1000/2; offs += 8) + { + if (sprram[offs] & 0x0001) + { + INT32 sx = (sprram[offs+4] & 0x01ff) + videoshift; + INT32 sy = (sprram[offs+6] & 0x01ff); + INT32 code = sprram[offs+3] & nGraphicsMask[2]; + INT32 color = sprram[offs+7] & coland; + INT32 w = (sprram[offs+1] & 0x000f); + INT32 h = ((sprram[offs+1] & 0x00f0) >> 4); + INT32 pri = ((sprram[offs+0] & 0x00c0) >> 6); + INT32 flipy = ((sprram[offs+1] & 0x0200) >> 9); + INT32 flipx = ((sprram[offs+1] & 0x0100) >> 8); + + if (!flip) flipy = flipx = 0; + + color = (color << 4) + coloff; + + INT32 delta = 16; + + if (pri != priority) + continue; + + if (*flipscreen) + { + sx = 368 - sx; + sy = 240 - sy; + delta = -16; + + flipx ^= *flipscreen; + flipy ^= *flipscreen; + } + + INT32 yy = h; + sy += flipy ? (delta * h) : 0; + + do + { + INT32 x = sx + (flipx ? (delta * w) : 0); + INT32 xx = w; + + do + { + INT32 xxx = ((x + 16) & 0x1ff) - 16; + INT32 yyy = (sy & 0x1ff) - global_y_offset; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, xxx, yyy, color, 0, 15, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, xxx, yyy, color, 0, 15, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, xxx, yyy, color, 0, 15, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, xxx, yyy, color, 0, 15, 0, DrvGfxROM2); + } + } + code = (code + 1) & nGraphicsMask[2]; + x += delta * (flipx ? -1 : 1); + + } while (--xx >= 0); + sy += delta * (flipx ? -1 : 1); + + } while (--yy >= 0); + } + } +} + +static void draw_macross_background(UINT8 *ram, INT32 scrollx, INT32 scrolly, INT32 coloff, INT32 t) +{ + scrolly = (scrolly + global_y_offset) & 0x1ff; + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 0x100 * 0x20; offs++) + { + INT32 sx = (offs & 0xff) << 4; + INT32 sy = (offs >> 8) << 4; + + INT32 row = sy >> 4; + INT32 col = sx >> 4; + + sx = (((sx - scrollx) + 16) & 0xfff) - 16; + sy = (((sy - scrolly) + 16) & 0x1ff) - 16; + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 ofst = ((row >> 4) << 12) | (row & 0x0f) | (col << 4); + + if (is_8bpp) { + INT32 code = vram[ofst] & nGraphicsMask[1]; + + Render16x16Tile_Clip(pTransDraw, code, sx, sy, 0, 8, coloff, DrvGfxROM1); + } else { + INT32 code = ((vram[ofst] & 0xfff) | (*tilebank << 12)) & nGraphicsMask[1]; + INT32 color = vram[ofst] >> 12; + + if (t) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, coloff, DrvGfxROM1); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, coloff, DrvGfxROM1); + } + } + } +} + +static void draw_gunnail_background(UINT8 *ram) +{ + INT32 bank = (*tilebank << 12) & nGraphicsMask[1]; // good enough?? + UINT16 *vram = (UINT16*)ram; + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + for (INT32 y = 16; y < nScreenHeight + 16; y++) + { + INT32 yscroll = (scroll[0x100] + scroll[0x100 | y] + y) & 0x1ff; + + INT32 row = yscroll >> 4; + INT32 yl = (yscroll & 0x0f) << 4; + + INT32 ofst0 = ((row >> 4) << 12) | (row & 0x0f); + INT32 xscroll0 = scroll[0] + scroll[y] - videoshift; + + UINT16 *dest = pTransDraw + (y - 16) * nScreenWidth; + + for (INT32 x = 0; x < nScreenWidth + 16; x+=16) + { + INT32 xscroll = (x + xscroll0) & 0xfff; + INT32 sx = x - (xscroll & 0x0f); + + INT32 ofst = ofst0 | (xscroll & 0xff0); + + INT32 code = (vram[ofst] & 0xfff) | bank; + INT32 color = (vram[ofst] >> 12) << 4; + + UINT8 *src = DrvGfxROM1 + (code << 8) + yl; + + for (INT32 xx = 0; xx < 16; xx++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + dest[sx] = src[xx] | color; + } + } + } +} + +static void draw_bjtwin_background(INT32 scrollx) +{ + UINT16 *vram = (UINT16*)DrvBgRAM0; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = (offs & 0x1f) << 3; + + sy -= global_y_offset; + sx = (((sx - scrollx) + 8) & 0x1ff) - 8; + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + INT32 bank = code & 0x800; + code &= 0x7ff; + if (bank) code |= (*tilebank << 11); + code &= nGraphicsMask[1]; + + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, bank ? DrvGfxROM1 : DrvGfxROM0); + } +} + +static void bioship_draw_background(INT32 scrollx, INT32 scrolly) +{ + scrolly = (scrolly + global_y_offset) & 0x1ff; + INT32 bank = *tilebank * 0x2000; + UINT16 *tilerom = (UINT16*)DrvTileROM; + + for (INT32 offs = 0; offs < 0x1000; offs++) + { + INT32 sx = (offs >> 4) << 4; + INT32 sy = (offs & 0x0f) << 4; + + sx = (((sx + 16) - scrollx) & 0xfff) - 16; + + if (sx >= nScreenWidth) continue; + + INT32 code = tilerom[offs | bank]; + sy = (((sy + 16) - scrolly) & 0x1ff) - 16; + + if (sy < nScreenHeight) { + Render16x16Tile_Clip(pTransDraw, code & 0xfff, sx, sy, code >> 12, 4, 0, DrvGfxROM1 + 0x100000); + } + + code = tilerom[offs | bank | 0x1000]; + sy = (((sy + 16) + 256) & 0x1ff) - 16; + + if (sy < nScreenHeight) { + Render16x16Tile_Clip(pTransDraw, code & 0xfff, sx, sy, code >> 12, 4, 0, DrvGfxROM1 + 0x100000); + } + } +} + +static void draw_macross_text_layer(INT32 scrollx, INT32 scrolly, INT32 wide, INT32 coloff) +{ + if (nGraphicsMask[0] == 0) return; + + scrolly = (scrolly + global_y_offset) & 0x1ff; + INT32 wmask = (0x100 << wide) - 1; + UINT16 *vram = (UINT16*)DrvTxRAM; + + for (INT32 offs = 0; offs < 32 * (32 << wide); offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = (offs & 0x1f) << 3; + + sx = (((sx - scrollx) + 8) & wmask) - 8; + sy = (((sy - scrolly) + 8) & 0xff) - 8; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs]; + + Render8x8Tile_Mask_Clip(pTransDraw, code & 0xfff, sx, sy, code >> 12, 4, 15, coloff, DrvGfxROM0); + } +} + +static void draw_screen_yflip() +{ + if (!screen_flip_y) return; + + UINT16 *tmp = (UINT16*)pBurnDraw; // :D + UINT16 *src1 = pTransDraw; + UINT16 *src2 = pTransDraw + (nScreenHeight-1) * nScreenWidth; + + for (INT32 y = 0; y < nScreenHeight / 2; y++) { + memcpy (tmp, src1, nScreenWidth * 2); + memcpy (src1, src2, nScreenWidth * 2); + memcpy (src2, tmp, nScreenWidth * 2); + src1 += nScreenWidth; + src2 -= nScreenWidth; + } +} + +static inline void common_draw(INT32 spriteflip, INT32 bgscrollx, INT32 bgscrolly, INT32 txscrollx, INT32 txscrolly, INT32 tx_coloff) +{ + DrvPaletteRecalc(); + + draw_macross_background(DrvBgRAM0, bgscrollx, bgscrolly, 0, 0); + + draw_sprites(spriteflip, 0x100, 0x0f, 3); + draw_sprites(spriteflip, 0x100, 0x0f, 2); + draw_sprites(spriteflip, 0x100, 0x0f, 1); + draw_sprites(spriteflip, 0x100, 0x0f, 0); + + draw_macross_text_layer(txscrollx, txscrolly, 0, tx_coloff); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); +} + +static INT32 TharrierDraw() +{ + INT32 scrollx = *((UINT16*)(Drv68KRAM + 0x9f00)) & 0xfff; + + common_draw(1, scrollx, 0, 0, 0, 0); + + return 0; +} + +static INT32 ManyblocDraw() +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrollx = scroll[0x82 / 2] & 0xfff; + INT32 scrolly = scroll[0xc2 / 2] & 0x1ff; + + common_draw(1, scrollx, scrolly, 0, 0, 0); + + return 0; +} + +static INT32 MacrossDraw() +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrollx = ((scroll[0] & 0x0f) << 8) | (scroll[1] & 0xff); + INT32 scrolly = ((scroll[2] & 0x01) << 8) | (scroll[3] & 0xff); + + common_draw(0, scrollx, scrolly, 0, 0, 0x200); + + return 0; +} + +static INT32 VandykeDraw() +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrollx = ((scroll[0] & 0x0f) << 8) | (scroll[1] >> 8); + INT32 scrolly = ((scroll[2] & 0x01) << 8) | (scroll[3] >> 8); + + common_draw(0, scrollx, scrolly, 0, 0, 0x200); + + return 0; +} + +static INT32 RedhawkiDraw() +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrollx = scroll[2] & 0xff; + INT32 scrolly = scroll[3] & 0xff; + + common_draw(0, scrollx, scrolly, 0, 0, 0x300); + + return 0; +} + +static INT32 FirehawkDraw() +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrolly = (scroll[3] + 0x100) & 0x1ff; + INT32 scrollx = (scroll[2] + 0x000) & 0xfff; + + common_draw(1, scrollx, scrolly, 0, 0, 0x200); + + return 0; +} + +static INT32 HachamfDraw() +{ + if (nNMK004CpuSpeed == 10000000) { // hachamf + mcu_run(0); + } else { // tdragon + mcu_run(1); + } + + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 scrollx = ((scroll[0] & 0x0f) << 8) | (scroll[1] & 0xff); + INT32 scrolly = ((scroll[2] & 0x01) << 8) | (scroll[3] & 0xff); + + common_draw(0, scrollx, scrolly, 0, 0, 0x200); + + return 0; +} + +static INT32 StrahlDraw() +{ + DrvPaletteRecalc(); + + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + INT32 bgscrollx = ((scroll[0x000] & 0x0f) << 8) | (scroll[0x001] & 0xff); + INT32 bgscrolly = ((scroll[0x002] & 0x01) << 8) | (scroll[0x003] & 0xff); + INT32 fgscrollx = ((scroll[0x200] & 0x0f) << 8) | (scroll[0x201] & 0xff); + INT32 fgscrolly = ((scroll[0x202] & 0x01) << 8) | (scroll[0x203] & 0xff); + + draw_macross_background(DrvBgRAM0, bgscrollx, bgscrolly, 0x300, 0); + + INT32 bgbank_bak = *tilebank; *tilebank = 0x01; + draw_macross_background(DrvBgRAM1, fgscrollx, fgscrolly, 0x200, 1); + *tilebank = bgbank_bak; + + draw_sprites(0, 0x100, 0x0f, 3); + draw_sprites(0, 0x100, 0x0f, 2); + draw_sprites(0, 0x100, 0x0f, 1); + draw_sprites(0, 0x100, 0x0f, 0); + + draw_macross_text_layer(0, 0, 0, 0x200); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 Macross2Draw() +{ + videoshift = 64; + DrvPaletteRecalc(); + + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + INT32 scrollx = ((scroll[0] & 0x0f) << 8) | (scroll[1] & 0xff); + INT32 scrolly = ((scroll[2] & 0x01) << 8) | (scroll[3] & 0xff); + + switch (scroll[0] & 0x30) + { + case 0x00: draw_macross_background(DrvBgRAM0, (scrollx - 64) & 0xfff, scrolly, 0, 0); break; + case 0x10: draw_macross_background(DrvBgRAM1, (scrollx - 64) & 0xfff, scrolly, 0, 0); break; + case 0x20: draw_macross_background(DrvBgRAM2, (scrollx - 64) & 0xfff, scrolly, 0, 0); break; + case 0x30: draw_macross_background(DrvBgRAM3, (scrollx - 64) & 0xfff, scrolly, 0, 0); break; + } + + draw_sprites(0, 0x100, 0x1f, 3); + draw_sprites(0, 0x100, 0x1f, 2); + draw_sprites(0, 0x100, 0x1f, 1); + draw_sprites(0, 0x100, 0x1f, 0); + + draw_macross_text_layer(-64, 0, 1, 0x300); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 GunnailDraw() +{ + DrvPaletteRecalc(); + + videoshift = 64; + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + switch ((scroll[0] >> 8) & 0x30) + { + case 0x00: draw_gunnail_background(DrvBgRAM0); break; + //case 0x10: draw_gunnail_background(DrvBgRAM1); break; + //case 0x20: draw_gunnail_background(DrvBgRAM2); break; + //case 0x30: draw_gunnail_background(DrvBgRAM3); break; + + // GunNail only has a single ram bank. If it tries to + // use another, just clear everything. + + case 0x10: + case 0x20: + case 0x30: + BurnTransferClear(); + break; + } + + draw_sprites(0, 0x100, 0x0f, 3); + draw_sprites(0, 0x100, 0x0f, 2); + draw_sprites(0, 0x100, 0x0f, 1); + draw_sprites(0, 0x100, 0x0f, 0); + + draw_macross_text_layer(-64, 0, 1, 0x200); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 RapheroDraw() +{ + DrvPaletteRecalc(); + + videoshift = 64; + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + switch ((scroll[0] >> 8) & 0x30) + { + case 0x00: draw_gunnail_background(DrvBgRAM0); break; + case 0x10: draw_gunnail_background(DrvBgRAM1); break; + case 0x20: draw_gunnail_background(DrvBgRAM2); break; + case 0x30: draw_gunnail_background(DrvBgRAM3); break; + } + + draw_sprites(0, 0x100, 0x1f, 3); + draw_sprites(0, 0x100, 0x1f, 2); + draw_sprites(0, 0x100, 0x1f, 1); + draw_sprites(0, 0x100, 0x1f, 0); + + draw_macross_text_layer(-64, 0, 1, 0x300); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 BioshipDraw() +{ + DrvPaletteRecalc(); + + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 bgscrolly = (scroll[0x02] & 0x100) | (scroll[0x03] >> 8); + INT32 bgscrollx = (scroll[0x00] & 0xf00) | (scroll[0x01] >> 8); + INT32 fgscrolly = (scroll[0x02] & 0x100) | (scroll[0x03] >> 8); + INT32 fgscrollx = (scroll[0x00] & 0xf00) | (scroll[0x01] >> 8); + + bioship_draw_background(bgscrollx, bgscrolly); + + INT32 bgbank_bak = *tilebank; *tilebank = 0; + draw_macross_background(DrvBgRAM0, fgscrollx, fgscrolly, 0x100, 1); + *tilebank = bgbank_bak; + + draw_sprites(0, 0x200, 0x0f, 3); + draw_sprites(0, 0x200, 0x0f, 2); + draw_sprites(0, 0x200, 0x0f, 1); + draw_sprites(0, 0x200, 0x0f, 0); + + draw_macross_text_layer(0, 0, 0, 0x300); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 BjtwinDraw() +{ + videoshift = 64; + + DrvPaletteRecalc(); + + draw_bjtwin_background(-64); + + draw_sprites(0, 0x100, 0x0f, 3); + draw_sprites(0, 0x100, 0x0f, 2); + draw_sprites(0, 0x100, 0x0f, 1); + draw_sprites(0, 0x100, 0x0f, 0); + + draw_screen_yflip(); + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void AfegaCommonDraw(INT32 , INT32 xoffset, INT32 yoffset) +{ + UINT16 *scroll = (UINT16*)DrvScrollRAM; + INT32 bgscrollx = (scroll[1] + xoffset) & 0xfff; + INT32 bgscrolly = (scroll[0] + yoffset) & 0x1ff; + INT32 txscrollx = (scroll[3] & 0xff); + INT32 txscrolly = (scroll[2] & 0xff); + + common_draw(1, bgscrollx, bgscrolly, txscrollx, txscrolly, 0x200); +} + +static INT32 AfegaDraw() +{ + AfegaCommonDraw(1, -0x100, 0); + return 0; +} + +static INT32 RedhawkbDraw() +{ + AfegaCommonDraw(1, 0, 0x100); + return 0; +} + +static INT32 Bubl2000Draw() +{ + AfegaCommonDraw(0, -0x100, 0); + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + if (strncmp(BurnDrvGetTextA(DRV_NAME), "tharrier", 8) == 0) + { + DrvInputs[0] = 0x8000; + DrvInputs[1] = 0x0000; + DrvInputs[2] = 0x0000; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + if (DrvInputs[0] & 0x0001) DrvInputs[1] ^= 0x0080; + if (DrvInputs[0] & 0x0002) DrvInputs[1] ^= 0x0020; + if (DrvInputs[0] & 0x0008) DrvInputs[1] ^= 0x0001; + if (DrvInputs[0] & 0x0010) DrvInputs[1] ^= 0x0102; + } + else + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nTotalCycles[2] = { 10000000 / 56, 3000000 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nTotalCycles[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekRun(0); + } + if (i == ((nInterleave/2)-1)) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave-1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + BurnTimerUpdate(i * (nTotalCycles[1] / nInterleave)); + } + + BurnTimerEndFrame(nTotalCycles[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 SsmissinFrame() +{ + if (DrvReset) { + SmissinDoReset(); + } + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nTotalCycles[2] = { 8000000 / 56, 4000000 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nTotalCycles[0] / nInterleave; + + nCyclesDone[0] += SekRun(nSegment); + + if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekRun(0); + } + if (i == ((nInterleave/2)-1) && nNMK004EnableIrq2) + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave-1)) + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + ZetRun(nTotalCycles[1] / nInterleave); + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 Macross2Frame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 200; + INT32 nTotalCycles[2] = { 10000000 / 56, 4000000 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nTotalCycles[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == 1 || i == (nInterleave / 2)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + } + if (i == (nInterleave-1)) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + if (macross2_sound_enable) { + //BurnTimerUpdate((nSegment * 4) / 10); + BurnTimerUpdate(i * (nTotalCycles[1] / nInterleave)); + } + } + + if (macross2_sound_enable) { + BurnTimerEndFrame(nTotalCycles[1]); + } + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 AfegaFrame() +{ + if (DrvReset) { + AfegaDoReset(); + } + + ZetNewFrame(); + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 12000000 / 56, 4000000 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment; + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave / 2) - 1) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave) - 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + nSegment = nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += ZetRun(nSegment); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 BjtwinFrame() +{ + if (DrvReset) { + BjtwinDoReset(); + } + + ZetNewFrame(); + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[1] = { 10000000 / 56 }; + INT32 nCyclesDone[1] = { 0 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment; + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + } + if (i == (nInterleave-1)) { + SekRun(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + if (pBurnSoundOut) { + memset (pBurnSoundOut, 0, nBurnSoundLen * 2 * sizeof(INT16)); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 SeibuSoundFrame() +{ + if (DrvReset) { + SeibuSoundDoReset(); + } + + ZetNewFrame(); + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { 10000000 / 56, 3579545 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment; + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + } + + if (i == ((nInterleave/2)-1)) { + SekRun(0); + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + if (i == (nInterleave-1)) { + SekRun(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + if (pBurnSoundOut) { + seibu_sound_update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + + return 0; +} + +static INT32 NMK004Frame() +{ + if (DrvReset) { + NMK004DoReset(); + } + + { + DrvInputs[0] = ~input_high[0]; + DrvInputs[1] = ~input_high[1]; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + SekNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 200; + INT32 nTotalCycles[1] = { nNMK004CpuSpeed / 56 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] / nInterleave) * (i + 1); + BurnTimerUpdate(nSegment); + + if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + } + if (i == ((nInterleave/2)-1) && nNMK004EnableIrq2) { + SekRun(0); + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + if (i == (nInterleave-1)) { + SekRun(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + BurnTimerEndFrame(nTotalCycles[0]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + if (strncmp(BurnDrvGetTextA(DRV_NAME), "strahl", 6) == 0) { + memcpy (DrvSprBuf2, Drv68KRAM + 0xf000, 0x1000); + } else { + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------------------------------------------- + +static void decryptcode(INT32 len, INT32 a17, INT32 a16, INT32 a15, INT32 a14, INT32 a13) +{ + UINT8 *buf = (UINT8*)malloc(len); + + memcpy (buf, Drv68KROM, len); + + for (INT32 i = 0; i < len; i++) { + Drv68KROM[i] = buf[BITSWAP24(i, 23,22,21,20,19,18,a17,a16,a15,a14,a13,12,11,10,9,8,7,6,5,4,3,2,1,0)]; + } + + if (buf) { + free (buf); + buf = NULL; + } +} + +static UINT32 bjtwin_address_map_bg0(UINT32 addr) +{ + return ((addr & 0x00004) >> 2) | ((addr & 0x00800) >> 10) | ((addr & 0x40000) >> 16); +} + +static UINT8 decode_byte(UINT8 src, const UINT8 *bitp) +{ + UINT8 ret = 0; + for (INT32 i=0; i<8; i++) + ret |= (((src >> bitp[i]) & 1) << (7-i)); + + return ret; +} + +static UINT16 decode_word(UINT16 src, const UINT8 *bitp) +{ + UINT16 ret=0; + for (INT32 i = 0; i < 16; i++) + ret |= (((src >> bitp[i]) & 1) << (15-i)); + + return ret; +} + +static UINT32 bjtwin_address_map_sprites(UINT32 addr) +{ + return ((addr & 0x00010) >> 4) | ((addr & 0x20000) >> 16) | ((addr & 0x100000) >> 18); +} + +static void decode_gfx(INT32 gfxlen0, INT32 gfxlen1) +{ + static const UINT8 decode_data_bg[8][8] = + { + {0x3,0x0,0x7,0x2,0x5,0x1,0x4,0x6}, + {0x1,0x2,0x6,0x5,0x4,0x0,0x3,0x7}, + {0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0}, + {0x7,0x6,0x5,0x0,0x1,0x4,0x3,0x2}, + {0x2,0x0,0x1,0x4,0x3,0x5,0x7,0x6}, + {0x5,0x3,0x7,0x0,0x4,0x6,0x2,0x1}, + {0x2,0x7,0x0,0x6,0x5,0x3,0x1,0x4}, + {0x3,0x4,0x7,0x6,0x2,0x0,0x5,0x1}, + }; + + static const UINT8 decode_data_sprite[8][16] = + { + {0x9,0x3,0x4,0x5,0x7,0x1,0xb,0x8,0x0,0xd,0x2,0xc,0xe,0x6,0xf,0xa}, + {0x1,0x3,0xc,0x4,0x0,0xf,0xb,0xa,0x8,0x5,0xe,0x6,0xd,0x2,0x7,0x9}, + {0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0}, + {0xf,0xe,0xc,0x6,0xa,0xb,0x7,0x8,0x9,0x2,0x3,0x4,0x5,0xd,0x1,0x0}, + {0x1,0x6,0x2,0x5,0xf,0x7,0xb,0x9,0xa,0x3,0xd,0xe,0xc,0x4,0x0,0x8}, + {0x7,0x5,0xd,0xe,0xb,0xa,0x0,0x1,0x9,0x6,0xc,0x2,0x3,0x4,0x8,0xf}, + {0x0,0x5,0x6,0x3,0x9,0xb,0xa,0x7,0x1,0xd,0x2,0xe,0x4,0xc,0x8,0xf}, + {0x9,0xc,0x4,0x2,0xf,0x0,0xb,0x8,0xa,0xd,0x3,0x6,0x5,0xe,0x1,0x7}, + }; + + for (INT32 A = 0; A < gfxlen0; A++) { + DrvGfxROM1[A] = decode_byte(DrvGfxROM1[A], decode_data_bg[bjtwin_address_map_bg0(A)]); + } + + for (INT32 A = 0; A < gfxlen1; A += 2) + { + UINT16 tmp = decode_word((DrvGfxROM2[A+1] << 8) | DrvGfxROM2[A], decode_data_sprite[bjtwin_address_map_sprites(A)]); + DrvGfxROM2[A+1] = tmp >> 8; + DrvGfxROM2[A] = tmp & 0xff; + } +} + +static void ssmissin_decode() +{ + for (INT32 A = 0; A < 0x100000; A++) + { + DrvGfxROM1[A] = BITSWAP08(DrvGfxROM1[A], 7, 6, 5, 3, 4, 2, 1, 0); + DrvGfxROM2[A] = BITSWAP08(DrvGfxROM2[A], 7, 6, 5, 3, 4, 2, 1, 0); + } +} + +static void decode_tdragonb() +{ + static const UINT8 decode_data_tdragonb[16] = { + 0xe,0xc,0xa,0x8,0x7,0x5,0x3,0x1,0xf,0xd,0xb,0x9,0x6,0x4,0x2,0x0 + }; + + for (INT32 A = 0; A < 0x40000; A += 2) + { + UINT16 tmp = decode_word((Drv68KROM[A+1] << 8) | Drv68KROM[A], decode_data_tdragonb); + Drv68KROM[A+1] = tmp >> 8; + Drv68KROM[A] = tmp & 0xff; + } + + ssmissin_decode(); +} + +//------------------------------------------------------------------------------------------------------------- + + +// Task Force Harrier + +static struct BurnRomInfo tharrierRomDesc[] = { + { "2", 0x020000, 0x78923aaa, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3", 0x020000, 0x99cea259, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "12", 0x010000, 0xb959f837, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "1", 0x010000, 0xc7402e4a, 3 | BRF_GRA }, // 3 Characters + + { "89050-4", 0x080000, 0x64d7d687, 4 | BRF_GRA }, // 4 Tiles + + { "89050-13", 0x080000, 0x24db3fa4, 5 | BRF_GRA }, // 5 Sprites + { "89050-17", 0x080000, 0x7f715421, 5 | BRF_GRA }, // 6 + + { "89050-8", 0x080000, 0x11ee4c39, 6 | BRF_SND }, // 7 OKI1 Samples + + { "89050-10", 0x080000, 0x893552ab, 7 | BRF_SND }, // 8 OKI2 Samples + + { "21.bpr", 0x000100, 0xfcd5efea, 0 | BRF_OPT }, // 9 Unused proms + { "22.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 + { "23.bpr", 0x000020, 0xfc3569f4, 0 | BRF_OPT }, // 11 + { "24.bpr", 0x000100, 0xe0a009fe, 0 | BRF_OPT }, // 12 + { "25.bpr", 0x000100, 0xe0a009fe, 0 | BRF_OPT }, // 13 + { "26.bpr", 0x000020, 0x0cbfb33e, 0 | BRF_OPT }, // 14 +}; + +STD_ROM_PICK(tharrier) +STD_ROM_FN(tharrier) + +static INT32 TharrierLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 7, 1)) return 1; + memmove (DrvSndROM0 + 0x40000, DrvSndROM0 + 0x20000, 0x60000); + + if (BurnLoadRom(DrvSndROM1 + 0x00000, 8, 1)) return 1; + memmove (DrvSndROM1 + 0x40000, DrvSndROM1 + 0x20000, 0x60000); + + DrvGfxDecode(0x10000, 0x80000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0883ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09d000, 0x09d7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, tharrier_main_write_word); + SekSetWriteByteHandler(0, tharrier_main_write_byte); + SekSetReadWordHandler(0, tharrier_main_read_word); + SekSetReadByteHandler(0, tharrier_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 TharrierInit() +{ + input_high[0] = 0x7fff; + input_high[1] = 0xffff; + + return DrvInit(TharrierLoadCallback); +} + +struct BurnDriver BurnDrvTharrier = { + "tharrier", NULL, NULL, NULL, "1989", + "Task Force Harrier\0", NULL, "UPL (American Sammy license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tharrierRomInfo, tharrierRomName, NULL, NULL, TharrierInputInfo, TharrierDIPInfo, + TharrierInit, DrvExit, DrvFrame, TharrierDraw, NULL, NULL, 0x200, + 224, 256, 3, 4 +}; + + +// Task Force Harrier (Japan) + +static struct BurnRomInfo tharrierjRomDesc[] = { + { "2.bin", 0x020000, 0xf3887a44, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3.bin", 0x020000, 0x65c247f6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "12", 0x010000, 0xb959f837, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "1.bin", 0x010000, 0x005c26c3, 3 | BRF_GRA }, // 3 Characters + + { "89050-4", 0x080000, 0x64d7d687, 4 | BRF_GRA }, // 4 Tiles + + { "89050-13", 0x080000, 0x24db3fa4, 5 | BRF_GRA }, // 5 Sprites + { "89050-17", 0x080000, 0x7f715421, 5 | BRF_GRA }, // 6 + + { "89050-8", 0x080000, 0x11ee4c39, 6 | BRF_SND }, // 7 OKI1 Samples + + { "89050-10", 0x080000, 0x893552ab, 7 | BRF_SND }, // 8 OKI2 Samples + + { "21.bpr", 0x000100, 0xfcd5efea, 0 | BRF_OPT }, // 9 Unused proms + { "22.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 + { "23.bpr", 0x000020, 0xfc3569f4, 0 | BRF_OPT }, // 11 + { "24.bpr", 0x000100, 0xe0a009fe, 0 | BRF_OPT }, // 12 + { "25.bpr", 0x000100, 0xe0a009fe, 0 | BRF_OPT }, // 13 + { "26.bpr", 0x000020, 0x0cbfb33e, 0 | BRF_OPT }, // 14 +}; + +STD_ROM_PICK(tharrierj) +STD_ROM_FN(tharrierj) + +struct BurnDriver BurnDrvTharrierj = { + "tharrierj", "tharrier", NULL, NULL, "1989", + "Task Force Harrier (Japan)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tharrierjRomInfo, tharrierjRomName, NULL, NULL, TharrierInputInfo, TharrierDIPInfo, + TharrierInit, DrvExit, DrvFrame, TharrierDraw, NULL, NULL, 0x200, + 224, 256, 3, 4 +}; + + +// Many Block + +static struct BurnRomInfo manyblocRomDesc[] = { + { "1-u33.bin", 0x020000, 0x07473154, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "2-u35.bin", 0x020000, 0x04acd8c1, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3-u146.bin", 0x010000, 0x7bf5fafa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "12-u39.bin", 0x010000, 0x413b5438, 3 | BRF_GRA }, // 3 Characters + + { "5-u97.bin", 0x040000, 0x536699e6, 4 | BRF_GRA }, // 4 Ciles + { "4-u96.bin", 0x040000, 0x28af2640, 4 | BRF_GRA }, // 5 + + { "8-u54b.bin", 0x020000, 0x03eede77, 5 | BRF_GRA }, // 6 Sprites + { "10-u86b.bin", 0x020000, 0x9eab216f, 5 | BRF_GRA }, // 7 + { "9-u53b.bin", 0x020000, 0xdfcfa040, 5 | BRF_GRA }, // 8 + { "11-u85b.bin", 0x020000, 0xfe747dd5, 5 | BRF_GRA }, // 9 + + { "6-u131.bin", 0x040000, 0x79a4ae75, 6 | BRF_SND }, // 10 OKI1 Samples + { "7-u132.bin", 0x040000, 0x21db875e, 6 | BRF_SND }, // 11 + + { "u200.bpr", 0x000020, 0x1823600b, 0 | BRF_OPT }, // 12 Unused proms + { "u7.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 13 + { "u10.bpr", 0x000200, 0x8e9b569a, 0 | BRF_OPT }, // 14 + { "u120.bpr", 0x000100, 0x576c5984, 0 | BRF_OPT }, // 15 +}; + +STD_ROM_PICK(manybloc) +STD_ROM_FN(manybloc) + +static INT32 ManyblocLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x00000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00001, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40001, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x60000, 11, 1)) return 1; + memmove (DrvSndROM0 + 0x40000, DrvSndROM0 + 0x20000, 0x20000); + + DrvGfxDecode(0x10000, 0x80000, 0x80000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0883ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x09c000, 0x09cfff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09d000, 0x09d7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, manybloc_main_write_word); + SekSetWriteByteHandler(0, manybloc_main_write_byte); + SekSetReadWordHandler(0, manybloc_main_read_word); + SekSetReadByteHandler(0, manybloc_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 ManyblocInit() +{ + global_y_offset = 8; + input_high[0] = 0x7fff; + input_high[1] = 0xffff; + + return DrvInit(ManyblocLoadCallback); +} + +struct BurnDriver BurnDrvManybloc = { + "manybloc", NULL, NULL, NULL, "1991", + "Many Block\0", NULL, "Bee-Oh", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, manyblocRomInfo, manyblocRomName, NULL, NULL, ManyblocInputInfo, ManyblocDIPInfo, + ManyblocInit, DrvExit, DrvFrame, ManyblocDraw, NULL, NULL, 0x200, + 240, 256, 3, 4 +}; + + +// S.S. Mission + +static struct BurnRomInfo ssmissinRomDesc[] = { + { "ssm14.165", 0x020000, 0xeda61b74, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "ssm15.166", 0x020000, 0xaff15927, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "ssm11.188", 0x008000, 0x8be6dce3, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "ssm16.172", 0x020000, 0x5cf6eb1f, 3 | BRF_GRA }, // 3 Characters + + { "ssm17.147", 0x080000, 0xc9c28455, 4 | BRF_GRA }, // 4 Tiles + { "ssm18.148", 0x080000, 0xebfdaad6, 4 | BRF_GRA }, // 5 + + { "ssm20.34", 0x080000, 0xa0c16c4d, 5 | BRF_GRA }, // 6 Sprites + { "ssm19.33", 0x080000, 0xb1943657, 5 | BRF_GRA }, // 7 + + { "ssm13.190", 0x020000, 0x618f66f0, 6 | BRF_SND }, // 8 OKI1 Samples + { "ssm12.189", 0x080000, 0xe8219c83, 6 | BRF_SND }, // 9 + + { "ssm-pr2.113", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 Unused proms + { "ssm-pr1.114", 0x000200, 0xed0bd072, 0 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(ssmissin) +STD_ROM_FN(ssmissin) + +static INT32 SsmissinLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x00000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00001, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x40000, 9, 1)) return 1; + + ssmissin_decode(); + DrvGfxDecode(0x20000, 0x100000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x0b0000, 0x0bffff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x0c4000, 0x0c43ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x0c8000, 0x0c87ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x0cc000, 0x0cffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d0000, 0x0d07ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d0800, 0x0d0fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d1000, 0x0d17ff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d1800, 0x0d1fff, SM_RAM); + SekSetWriteWordHandler(0, ssmissin_main_write_word); + SekSetWriteByteHandler(0, ssmissin_main_write_byte); + SekSetReadWordHandler(0, ssmissin_main_read_word); + SekSetReadByteHandler(0, ssmissin_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 SsmissinInit() +{ + return MSM6295x1Init(SsmissinLoadCallback); +} + +struct BurnDriver BurnDrvSsmissin = { + "ssmissin", NULL, NULL, NULL, "1992", + "S.S. Mission\0", NULL, "Comad", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, ssmissinRomInfo, ssmissinRomName, NULL, NULL, SsmissinInputInfo, SsmissinDIPInfo, + SsmissinInit, CommonExit, SsmissinFrame, MacrossDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Air Attack (set 1) + +static struct BurnRomInfo airattckRomDesc[] = { + { "uc10.bin", 0x020000, 0x1837d4ba, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "ue10.bin", 0x020000, 0x71deb9d8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3.su6", 0x008000, 0x3e352370, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "4.ul10", 0x020000, 0xe9362ab4, 3 | BRF_GRA }, // 3 Characters + + { "9.uw9", 0x080000, 0x86e59966, 4 | BRF_GRA }, // 4 Tiles + { "10.ux9", 0x080000, 0x122c8d04, 4 | BRF_GRA }, // 5 + + { "8.uo82", 0x080000, 0x9a83e3d8, 5 | BRF_GRA }, // 6 Sprites + { "7.uo81", 0x080000, 0x3c38d671, 5 | BRF_GRA }, // 7 + + { "2.su12", 0x020000, 0x93ab615b, 6 | BRF_SND }, // 8 OKI1 Samples + { "1.su13", 0x080000, 0x09a836bb, 6 | BRF_SND }, // 9 + + { "82s129.ug6", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 Unused proms + { "82s147.uh6", 0x000200, 0xed0bd072, 0 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(airattck) +STD_ROM_FN(airattck) + +struct BurnDriver BurnDrvAirattck = { + "airattck", NULL, NULL, NULL, "1996", + "Air Attack (set 1)\0", NULL, "Comad", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, airattckRomInfo, airattckRomName, NULL, NULL, SsmissinInputInfo, SsmissinDIPInfo, + SsmissinInit, CommonExit, SsmissinFrame, MacrossDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Air Attack (set 2) + +static struct BurnRomInfo airattckaRomDesc[] = { + { "5.ue10", 0x020000, 0x6589c005, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "6.uc10", 0x020000, 0x3572baf0, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3.su6", 0x008000, 0x3e352370, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "4.ul10", 0x020000, 0xe9362ab4, 3 | BRF_GRA }, // 3 Characters + + { "9.uw9", 0x080000, 0x86e59966, 4 | BRF_GRA }, // 4 Tiles + { "10.ux9", 0x080000, 0x122c8d04, 4 | BRF_GRA }, // 5 + + { "8.uo82", 0x080000, 0x9a83e3d8, 5 | BRF_GRA }, // 6 Sprites + { "7.uo81", 0x080000, 0x3c38d671, 5 | BRF_GRA }, // 7 + + { "2.su12", 0x020000, 0x93ab615b, 6 | BRF_SND }, // 8 OKI1 Samples + { "1.su13", 0x080000, 0x09a836bb, 6 | BRF_SND }, // 9 + + { "82s129.ug6", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 Unused proms + { "82s147.uh6", 0x000200, 0xed0bd072, 0 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(airattcka) +STD_ROM_FN(airattcka) + +struct BurnDriver BurnDrvAirattcka = { + "airattcka", "airattck", NULL, NULL, "1996", + "Air Attack (set 2)\0", NULL, "Comad", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, airattckaRomInfo, airattckaRomName, NULL, NULL, SsmissinInputInfo, SsmissinDIPInfo, + SsmissinInit, CommonExit, SsmissinFrame, MacrossDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Super Spacefortress Macross II / Chou-Jikuu Yousai Macross II + +static struct BurnRomInfo macross2RomDesc[] = { + { "mcrs2j.3", 0x080000, 0x36a618fe, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "mcrs2j.2", 0x020000, 0xb4aa8ac7, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 code + + { "mcrs2j.1", 0x020000, 0xc7417410, 3 | BRF_GRA }, // 2 Characters + + { "bp932an.a04", 0x200000, 0xc4d77ff0, 4 | BRF_GRA }, // 3 Tiles + + { "bp932an.a07", 0x200000, 0xaa1b21b9, 5 | BRF_GRA }, // 4 Sprites + { "bp932an.a08", 0x200000, 0x67eb2901, 5 | BRF_GRA }, // 5 + + { "bp932an.a06", 0x200000, 0xef0ffec0, 6 | BRF_SND }, // 6 OKI1 Samples + + { "bp932an.a05", 0x100000, 0xb5335abb, 7 | BRF_SND }, // 7 OKI2 Samples + + { "mcrs2bpr.9", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 Unused proms + { "mcrs2bpr.10", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(macross2) +STD_ROM_FN(macross2) + +struct BurnDriver BurnDrvMacross2 = { + "macross2", NULL, NULL, NULL, "1993", + "Super Spacefortress Macross II / Chou-Jikuu Yousai Macross II\0", NULL, "Banpresto", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, macross2RomInfo, macross2RomName, NULL, NULL, CommonInputInfo, Macross2DIPInfo, + Macross2Init, DrvExit, Macross2Frame, Macross2Draw, NULL, NULL, 0x400, + 384, 224, 4, 3 +}; + + +// Thunder Dragon 2 (9th Nov. 1993) + +static struct BurnRomInfo tdragon2RomDesc[] = { + { "6.rom", 0x080000, 0xca348caf, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "5.bin", 0x020000, 0xb870be61, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 code + + { "1.bin", 0x020000, 0xd488aafa, 3 | BRF_GRA }, // 2 Characters + + { "ww930914.2", 0x200000, 0xf968c65d, 4 | BRF_GRA }, // 3 Tiles + + { "ww930917.7", 0x200000, 0xb98873cb, 5 | BRF_GRA }, // 4 Sprites + { "ww930918.8", 0x200000, 0xbaee84b2, 5 | BRF_GRA }, // 5 + + { "ww930916.4", 0x200000, 0x07c35fe6, 6 | BRF_SND }, // 6 OKI1 Samples + + { "ww930915.3", 0x200000, 0x82025bab, 7 | BRF_SND }, // 7 OKI2 Samples + + { "9.bpr", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 Unused proms + { "10.bpr", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(tdragon2) +STD_ROM_FN(tdragon2) + +struct BurnDriver BurnDrvTdragon2 = { + "tdragon2", NULL, NULL, NULL, "1993", + "Thunder Dragon 2 (9th Nov. 1993)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, tdragon2RomInfo, tdragon2RomName, NULL, NULL, Tdragon2InputInfo, Tdragon2DIPInfo, + Macross2Init, DrvExit, Macross2Frame, Macross2Draw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Thunder Dragon 2 (1st Oct. 1993) + +static struct BurnRomInfo tdragon2aRomDesc[] = { + { "6.bin", 0x080000, 0x310d6bca, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "5.bin", 0x020000, 0xb870be61, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 code + + { "1.bin", 0x020000, 0xd488aafa, 3 | BRF_GRA }, // 2 Characters + + { "ww930914.2", 0x200000, 0xf968c65d, 4 | BRF_GRA }, // 3 Tiles + + { "ww930917.7", 0x200000, 0xb98873cb, 5 | BRF_GRA }, // 4 Sprites + { "ww930918.8", 0x200000, 0xbaee84b2, 5 | BRF_GRA }, // 5 + + { "ww930916.4", 0x200000, 0x07c35fe6, 6 | BRF_SND }, // 6 OKI1 Samples + + { "ww930915.3", 0x200000, 0x82025bab, 7 | BRF_SND }, // 7 OKI2 Samples + + { "9.bpr", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 Unused proms + { "10.bpr", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(tdragon2a) +STD_ROM_FN(tdragon2a) + +struct BurnDriver BurnDrvTdragon2a = { + "tdragon2a", "tdragon2", NULL, NULL, "1993", + "Thunder Dragon 2 (1st Oct. 1993)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, tdragon2aRomInfo, tdragon2aRomName, NULL, NULL, Tdragon2InputInfo, Tdragon2DIPInfo, + Macross2Init, DrvExit, Macross2Frame, Macross2Draw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Big Bang (9th Nov. 1993) + +static struct BurnRomInfo bigbangRomDesc[] = { + { "eprom.3", 0x080000, 0x28e5957a, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "5.bin", 0x020000, 0xb870be61, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 code + + { "1.bin", 0x020000, 0xd488aafa, 3 | BRF_GRA }, // 2 Characters + + { "ww930914.2", 0x200000, 0xf968c65d, 4 | BRF_GRA }, // 3 Tiles + + { "ww930917.7", 0x200000, 0xb98873cb, 5 | BRF_GRA }, // 4 Sprites + { "ww930918.8", 0x200000, 0xbaee84b2, 5 | BRF_GRA }, // 5 + + { "ww930916.4", 0x200000, 0x07c35fe6, 6 | BRF_SND }, // 6 OKI1 Samples + + { "ww930915.3", 0x200000, 0x82025bab, 7 | BRF_SND }, // 7 OKI2 Samples + + { "9.bpr", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 Unused proms + { "10.bpr", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(bigbang) +STD_ROM_FN(bigbang) + +struct BurnDriver BurnDrvBigbang = { + "bigbang", "tdragon2", NULL, NULL, "1993", + "Big Bang (9th Nov. 1993)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, bigbangRomInfo, bigbangRomName, NULL, NULL, Tdragon2InputInfo, Tdragon2DIPInfo, + Macross2Init, DrvExit, Macross2Frame, Macross2Draw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Stagger I (Japan) + +static struct BurnRomInfo stagger1RomDesc[] = { + { "2.bin", 0x020000, 0x8555929b, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3.bin", 0x020000, 0x5b0b63ac, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.bin", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "4.bin", 0x080000, 0x46463d36, 4 | BRF_GRA }, // 3 Tiles + + { "7.bin", 0x080000, 0x048f7683, 5 | BRF_GRA }, // 4 Characters + { "6.bin", 0x080000, 0x051d4a77, 5 | BRF_GRA }, // 5 + + { "5", 0x040000, 0xe911ce33, 6 | BRF_SND }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(stagger1) +STD_ROM_FN(stagger1) + +static void pAfegaZ80Callback() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(afega_sound_write); + ZetSetReadHandler(afega_sound_read); + ZetMemEnd(); + ZetClose(); +} + +static INT32 Stagger1LoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + memset (DrvGfxROM0, 0xff, 0x20); + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 5, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 6, 1)) return 1; + + DrvGfxDecode(0x20, 0x80000, 0x100000); + + return 0; +} + +static INT32 Stagger1Init() +{ + return AfegaInit(Stagger1LoadCallback, pAfegaZ80Callback, 1); +} + +struct BurnDriver BurnDrvStagger1 = { + "stagger1", NULL, NULL, NULL, "1998", + "Stagger I (Japan)\0", NULL, "Afega", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, stagger1RomInfo, stagger1RomName, NULL, NULL, CommonInputInfo, Stagger1DIPInfo, + Stagger1Init, AfegaExit, AfegaFrame, AfegaDraw, NULL, NULL, 0x300, + 224, 256, 3, 4 +}; + + +// Red Hawk (US) + +static struct BurnRomInfo redhawkRomDesc[] = { + { "2", 0x020000, 0x3ef5f326, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3", 0x020000, 0x9b3a10ef, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.bin", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "4", 0x080000, 0xd6427b8a, 4 | BRF_GRA }, // 5 Tiles + + { "7", 0x080000, 0x66a8976d, 5 | BRF_GRA }, // 3 Characters + { "6", 0x080000, 0x61560164, 5 | BRF_GRA }, // 4 + + { "5", 0x040000, 0xe911ce33, 6 | BRF_GRA }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(redhawk) +STD_ROM_FN(redhawk) + +static INT32 RedhawkInit() +{ + INT32 nRet = AfegaInit(Stagger1LoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x40000, 16,15,14,17,13); + } + + return nRet; +} + +struct BurnDriver BurnDrvRedhawk = { + "redhawk", "stagger1", NULL, NULL, "1997", + "Red Hawk (US)\0", NULL, "Afega (New Vision Ent. license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, redhawkRomInfo, redhawkRomName, NULL, NULL, CommonInputInfo, Stagger1DIPInfo, + RedhawkInit, AfegaExit, AfegaFrame, AfegaDraw, NULL, NULL, 0x300, + 224, 256, 3, 4 +}; + + +// Red Hawk (Excellent Co., Ltd) + +static struct BurnRomInfo redhawkeRomDesc[] = { + { "rhawk2.bin", 0x020000, 0x6d2e23b4, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "rhawk3.bin", 0x020000, 0x5e0d6188, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.bin", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "rhawk4.bin", 0x080000, 0xd79aa288, 4 | BRF_GRA }, // 3 Tiles + + { "rhawk7.bin", 0x080000, 0x0264ef54, 5 | BRF_GRA }, // 4 Characters + { "rhawk6.bin", 0x080000, 0x3f980ab6, 5 | BRF_GRA }, // 5 + + { "5", 0x040000, 0xe911ce33, 6 | BRF_GRA }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(redhawke) +STD_ROM_FN(redhawke) + +struct BurnDriver BurnDrvRedhawke = { + "redhawke", "stagger1", NULL, NULL, "1997", + "Red Hawk (Excellent Co., Ltd)\0", NULL, "Afega (Excellent Co. license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, redhawkeRomInfo, redhawkeRomName, NULL, NULL, CommonInputInfo, Stagger1DIPInfo, + Stagger1Init, AfegaExit, AfegaFrame, AfegaDraw, NULL, NULL, 0x300, + 224, 256, 3, 4 +}; + + +// Red Hawk (Italy) + +static struct BurnRomInfo redhawkiRomDesc[] = { + { "rhit-2.bin", 0x020000, 0x30cade0e, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "rhit-3.bin", 0x020000, 0x37dbb3c2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.bin", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "rhit-4.bin", 0x080000, 0xaafb3cc4, 4 | BRF_GRA }, // 3 Tiles + + { "rhit-7.bin", 0x080000, 0xbcb367c7, 5 | BRF_GRA }, // 4 Characters + { "rhit-6.bin", 0x080000, 0x7cbd5c60, 5 | BRF_GRA }, // 5 + + { "5", 0x040000, 0xe911ce33, 6 | BRF_SND }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(redhawki) +STD_ROM_FN(redhawki) + +static INT32 RedhawkiInit() +{ + INT32 nRet = AfegaInit(Stagger1LoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x40000, 15, 16, 17, 14, 13); + } + + return nRet; +} + +struct BurnDriver BurnDrvRedhawki = { + "redhawki", "stagger1", NULL, NULL, "1997", + "Red Hawk (Italy)\0", NULL, "Afega (Hea Dong Corp license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, redhawkiRomInfo, redhawkiRomName, NULL, NULL, CommonInputInfo, Stagger1DIPInfo, + RedhawkiInit, AfegaExit, AfegaFrame, RedhawkiDraw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Vince (Redhawk bootleg + +static struct BurnRomInfo redhawkbRomDesc[] = { + { "rhb-1.bin", 0x020000, 0xe733ea07, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "rhb-2.bin", 0x020000, 0xf9fa5684, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.bin", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "rhb-5.bin", 0x080000, 0xd0eaf6f2, 4 | BRF_GRA }, // 3 Tiles + + { "rhb-3.bin", 0x080000, 0x0318d68b, 5 | BRF_GRA }, // 4 Characters + { "rhb-4.bin", 0x080000, 0xba21c1ef, 5 | BRF_GRA }, // 5 + + { "5", 0x040000, 0xe911ce33, 6 | BRF_SND }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(redhawkb) +STD_ROM_FN(redhawkb) + +static INT32 RedhawkbLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + memset (DrvGfxROM0, 0xff, 0x20); + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x80000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x00000, 6, 1)) return 1; + + DrvGfxDecode(0x20, 0x80000, 0x100000); + + BurnByteswap(DrvGfxROM1, 0x100000); + BurnByteswap(DrvGfxROM2, 0x200000); + + return 0; +} + +static INT32 RedhawkbInit() +{ + input_high[0] = input_high[1] = 0xffff; + + return AfegaInit(RedhawkbLoadCallback, pAfegaZ80Callback, 1); +} + +struct BurnDriver BurnDrvRedhawkb = { + "redhawkb", "stagger1", NULL, NULL, "1997", + "Vince (Redhawk bootleg)\0", NULL, "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, redhawkbRomInfo, redhawkbRomName, NULL, NULL, CommonInputInfo, RedhawkbDIPInfo, + RedhawkbInit, AfegaExit, AfegaFrame, RedhawkbDraw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Guardian Storm + +static struct BurnRomInfo grdnstrmRomDesc[] = { + { "afega4.u112", 0x040000, 0x2244713a, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "afega5.u107", 0x040000, 0x5815c806, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "afega7.u92", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "afega1.u4", 0x010000, 0x9e7ef086, 3 | BRF_GRA }, // 3 Characters + + { "afega_af1-b2.uc8", 0x200000, 0xd68588c2, 4 | BRF_GRA }, // 4 Tiles + { "afega_af1-b1.uc3", 0x200000, 0xf8b200a8, 4 | BRF_GRA }, // 5 + + { "afega3.uc13", 0x200000, 0x0218017c, 5 | BRF_GRA }, // 6 Sprites + + { "afega1.u95", 0x040000, 0xe911ce33, 6 | BRF_SND }, // 7 OKI1 Samples +}; + +STD_ROM_PICK(grdnstrm) +STD_ROM_FN(grdnstrm) + +static INT32 GrdnstrmLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + + GrdnstrmGfxDecode(0x10000, 0x400000, 0x200000); + + return 0; +} + +static INT32 GrdnstrmInit() +{ + screen_flip_y = 1; + + return AfegaInit(GrdnstrmLoadCallback, pAfegaZ80Callback, 1); +} + +struct BurnDriver BurnDrvGrdnstrm = { + "grdnstrm", NULL, NULL, NULL, "1998", + "Guardian Storm\0", NULL, "Afega (Apples Industries license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, grdnstrmRomInfo, grdnstrmRomName, NULL, NULL, CommonInputInfo, GrdnstrmDIPInfo, + GrdnstrmInit, AfegaExit, AfegaFrame, FirehawkDraw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Sen Jin - Guardian Storm (Korea) + +static struct BurnRomInfo grdnstrmkRomDesc[] = { + { "gst-04.u112", 0x040000, 0x922c931a, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "gst-05.u107", 0x040000, 0xd22ca2dc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "afega7.u92", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "gst-03.u4", 0x010000, 0xa1347297, 3 | BRF_GRA }, // 3 Characters + + { "afega_af1-b2.uc8", 0x200000, 0xd68588c2, 4 | BRF_GRA }, // 4 Tiles + { "afega_af1-b1.uc3", 0x200000, 0xf8b200a8, 4 | BRF_GRA }, // 5 + + { "afega_af1-sp.uc13", 0x200000, 0x7d4d4985, 5 | BRF_GRA }, // 6 Sprites + + { "afega1.u95", 0x040000, 0xe911ce33, 6 | BRF_SND }, // 7 OKI1 Samples +}; + +STD_ROM_PICK(grdnstrmk) +STD_ROM_FN(grdnstrmk) + +static INT32 GrdnstrmkInit() +{ + INT32 nRet = AfegaInit(GrdnstrmLoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x80000, 16,17,14,15,13); + } + + return nRet; +} + +struct BurnDriver BurnDrvGrdnstrmk = { + "grdnstrmk", "grdnstrm", NULL, NULL, "1998", + "Sen Jin - Guardian Storm (Korea)\0", NULL, "Afega", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, grdnstrmkRomInfo, grdnstrmkRomName, NULL, NULL, CommonInputInfo, GrdnstrkDIPInfo, + GrdnstrmkInit, AfegaExit, AfegaFrame, AfegaDraw, NULL, NULL, 0x300, + 224, 256, 3, 4 +}; + + +// Pop's Pop's + +static struct BurnRomInfo popspopsRomDesc[] = { + { "afega4.u112", 0x040000, 0xdb191762, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "afega5.u107", 0x040000, 0x17e0c48b, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "afega1.u92", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "afega3.u4", 0x010000, 0xf39dd5d2, 3 | BRF_GRA }, // 3 Characters + + { "afega6.uc8", 0x200000, 0x6d506c97, 4 | BRF_GRA }, // 4 Tiles + { "afega7.uc3", 0x200000, 0x02d7f9de, 4 | BRF_GRA }, // 5 + + { "afega2.u95", 0x040000, 0xecd8eeac, 6 | BRF_SND }, // 6 OKI1 Samples +}; + +STD_ROM_PICK(popspops) +STD_ROM_FN(popspops) + +static INT32 PopspopsLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 5, 1)) return 1; + + memset (DrvGfxROM2, 0xff, 0x80); + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 6, 1)) return 1; + + GrdnstrmGfxDecode(0x10000, 0x400000, 0x80); + + return 0; +} + +static INT32 PopspopsInit() +{ + INT32 nRet = AfegaInit(PopspopsLoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x80000, 16,17,14,15,13); + } + + return nRet; +} + +struct BurnDriver BurnDrvPopspops = { + "popspops", NULL, NULL, NULL, "1999", + "Pop's Pop's\0", NULL, "Afega", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, popspopsRomInfo, popspopsRomName, NULL, NULL, CommonInputInfo, PopspopsDIPInfo, + PopspopsInit, AfegaExit, AfegaFrame, Bubl2000Draw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Bubble 2000 + +static struct BurnRomInfo bubl2000RomDesc[] = { + { "rom10.112", 0x020000, 0x87f960d7, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "rom11.107", 0x020000, 0xb386041a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "rom01.92", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "rom03.4", 0x010000, 0xf4c15588, 3 | BRF_GRA }, // 3 Characters + + { "rom06.6", 0x080000, 0xac1aabf5, 4 | BRF_GRA }, // 4 Tiles + { "rom07.9", 0x080000, 0x69aff769, 4 | BRF_GRA }, // 5 + { "rom13.7", 0x080000, 0x3a5b7226, 4 | BRF_GRA }, // 6 + { "rom04.1", 0x080000, 0x46acd054, 4 | BRF_GRA }, // 7 + { "rom05.3", 0x080000, 0x37deb6a1, 4 | BRF_GRA }, // 8 + { "rom12.2", 0x080000, 0x1fdc59dd, 4 | BRF_GRA }, // 9 + + { "rom08.11", 0x040000, 0x519dfd82, 5 | BRF_GRA }, // 10 Sprites + { "rom09.14", 0x040000, 0x04fcb5c6, 5 | BRF_GRA }, // 11 + + { "rom02.95", 0x040000, 0x859a86e5, 6 | BRF_SND }, // 12 OKI1 Samples +}; + +STD_ROM_PICK(bubl2000) +STD_ROM_FN(bubl2000) + +static INT32 Bubl2000LoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x280000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x300000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 11, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 12, 1)) return 1; + + GrdnstrmGfxDecode(0x10000, 0x400000, 0x80000); + + return 0; +} + +static INT32 Bubl2000Init() +{ + INT32 nRet = AfegaInit(Bubl2000LoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x40000, 13,14,15,16,17); + } + + return nRet; +} + +struct BurnDriver BurnDrvBubl2000 = { + "bubl2000", NULL, NULL, NULL, "1998", + "Bubble 2000\0", NULL, "Tuning", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, bubl2000RomInfo, bubl2000RomName, NULL, NULL, CommonInputInfo, Bubl2000DIPInfo, + Bubl2000Init, AfegaExit, AfegaFrame, Bubl2000Draw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Hot Bubble + +static struct BurnRomInfo hotbublRomDesc[] = { + { "c2.uc9", 0x040000, 0x7917b95d, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "c1.uc1", 0x040000, 0x7bb240e9, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "s1.uc14", 0x010000, 0x5d8cf28e, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "t1.uc2", 0x010000, 0xce683a93, 3 | BRF_GRA }, // 3 Characters + + { "cr5.uc15", 0x080000, 0x65bd5159, 4 | BRF_GRA }, // 4 Tiles + { "cr7.uc19", 0x080000, 0xa89d9ce4, 4 | BRF_GRA }, // 5 + { "cr6.uc16", 0x080000, 0x99d6523c, 4 | BRF_GRA }, // 6 + { "cr1.uc6", 0x080000, 0xfc9101d2, 4 | BRF_GRA }, // 7 + { "cr3.uc12", 0x080000, 0xc841a4f6, 4 | BRF_GRA }, // 8 + { "cr2.uc7", 0x080000, 0x27ad6fc8, 4 | BRF_GRA }, // 9 + + { "br1.uc3", 0x080000, 0x6fc18de4, 5 | BRF_GRA }, // 10 Sprites + { "br3.uc10", 0x080000, 0xbb677240, 5 | BRF_GRA }, // 11 + + { "s2.uc18", 0x040000, 0x401c980f, 6 | BRF_SND }, // 12 OKI1 Samples +}; + +STD_ROM_PICK(hotbubl) +STD_ROM_FN(hotbubl) + +struct BurnDriver BurnDrvHotbubl = { + "hotbubl", "bubl2000", NULL, NULL, "1998", + "Hot Bubble\0", NULL, "Pandora", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, hotbublRomInfo, hotbublRomName, NULL, NULL, CommonInputInfo, Bubl2000DIPInfo, + Bubl2000Init, AfegaExit, AfegaFrame, Bubl2000Draw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Mang-Chi + +static struct BurnRomInfo mangchiRomDesc[] = { + { "afega9.u112", 0x040000, 0x0b1517a5, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "afega10.u107", 0x040000, 0xb1d0f33d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sound.u92", 0x010000, 0xbec4f9aa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "afega5.uc6", 0x080000, 0xc73261e0, 4 | BRF_GRA }, // 3 Tiles + { "afega4.uc1", 0x080000, 0x73940917, 4 | BRF_GRA }, // 4 + + { "afega6.uc11", 0x040000, 0x979efc30, 5 | BRF_GRA }, // 5 Sprites + { "afega7.uc14", 0x040000, 0xc5cbcc38, 5 | BRF_GRA }, // 6 + + { "afega2.u95", 0x040000, 0x78c8c1f9, 6 | BRF_SND }, // 7 OKI1 Samples +}; + +STD_ROM_PICK(mangchi) +STD_ROM_FN(mangchi) + +static INT32 MangchiLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + memset (DrvGfxROM0, 0xff, 0x20); + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + + GrdnstrmGfxDecode(0x20, 0x100000, 0x80000); + + return 0; +} + +static INT32 MangchiInit() +{ + INT32 nRet = AfegaInit(MangchiLoadCallback, pAfegaZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x80000, 13,14,15,16,17); + } + + return nRet; +} + +struct BurnDriver BurnDrvMangchi = { + "mangchi", NULL, NULL, NULL, "2000", + "Mang-Chi\0", NULL, "Afega", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, mangchiRomInfo, mangchiRomName, NULL, NULL, CommonInputInfo, MangchiDIPInfo, + MangchiInit, AfegaExit, AfegaFrame, Bubl2000Draw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Fire Hawk + +static struct BurnRomInfo firehawkRomDesc[] = { + { "fhawk_p1.u59", 0x080000, 0xd6d71a50, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "fhawk_p2.u60", 0x080000, 0x9f35d245, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "fhawk_s1.u40", 0x020000, 0xc6609c39, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "fhawk_g1.uc6", 0x200000, 0x2ab0b06b, 4 | BRF_GRA }, // 3 Tiles + { "fhawk_g2.uc5", 0x200000, 0xd11bfa20, 4 | BRF_GRA }, // 4 + + { "fhawk_g3.uc2", 0x200000, 0xcae72ff4, 5 | BRF_GRA }, // 5 Sprites + + { "fhawk_s2.u36", 0x040000, 0xd16aaaad, 6 | BRF_SND }, // 6 OKI1 Samples + + { "fhawk_s3.u41", 0x040000, 0x3fdcfac2, 7 | BRF_SND }, // 7 OKI2 Samples +}; + +STD_ROM_PICK(firehawk) +STD_ROM_FN(firehawk) + +static void pFirehawkZ80Callback() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM); + ZetMapArea(0xf000, 0xfeff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xfeff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xfeff, 2, DrvZ80RAM); + + ZetSetWriteHandler(firehawk_sound_write); + ZetSetReadHandler(firehawk_sound_read); + ZetMemEnd(); + ZetClose(); +} + +static INT32 FirehawkLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + memset (DrvGfxROM0, 0xff, 0x20); + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 7, 1)) return 1; + + GrdnstrmGfxDecode(0x20, 0x400000, 0x200000); + + return 0; +} + +static INT32 FirehawkInit() +{ + screen_flip_y = 1; + + return AfegaInit(FirehawkLoadCallback, pFirehawkZ80Callback, 1); +} + +struct BurnDriver BurnDrvFirehawk = { + "firehawk", NULL, NULL, NULL, "2001", + "Fire Hawk\0", NULL, "ESD", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, firehawkRomInfo, firehawkRomName, NULL, NULL, CommonInputInfo, FirehawkDIPInfo, + FirehawkInit, AfegaExit, AfegaFrame, FirehawkDraw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Spectrum 2000 (Euro) + +static struct BurnRomInfo spec2kRomDesc[] = { + { "yonatech5.u124", 0x040000, 0x72ab5c05, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "yonatech6.u120", 0x040000, 0x7e44bd9c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "yonatech1.u103", 0x010000, 0xef5acda7, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "yonatech4.u3", 0x020000, 0x5626b08e, 3 | BRF_GRA }, // 3 Characters + + { "u153.bin", 0x200000, 0xa00bbf8f, 4 | BRF_GRA }, // 4 Tiles + { "u152.bin", 0x200000, 0xf6423fab, 4 | BRF_GRA }, // 5 + + { "u154.bin", 0x200000, 0xf77b764e, 5 | BRF_GRA }, // 6 Sprites + + { "yonatech2.u101", 0x020000, 0x4160f172, 6 | BRF_SND }, // 7 OKI1 Samples + + { "yonatech3.u106", 0x080000, 0x6644c404, 7 | BRF_SND }, // 8 OKI2 Samples +}; + +STD_ROM_PICK(spec2k) +STD_ROM_FN(spec2k) + +static INT32 Spec2kLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x200000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 8, 1)) return 1; + + GrdnstrmGfxDecode(0x20000, 0x400000, 0x200000); + + return 0; +} + +static INT32 Spec2kInit() +{ + screen_flip_y = 1; + + INT32 nRet = AfegaInit(Spec2kLoadCallback, pFirehawkZ80Callback, 1); + + if (nRet == 0) { + decryptcode(0x80000, 17,13,14,15,16); + } + + return nRet; +} + +struct BurnDriver BurnDrvSpec2k = { + "spec2k", NULL, NULL, NULL, "2000", + "Spectrum 2000 (Euro)\0", NULL, "YONA Tech", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, spec2kRomInfo, spec2kRomName, NULL, NULL, CommonInputInfo, Spec2kDIPInfo, + Spec2kInit, AfegaExit, AfegaFrame, FirehawkDraw, NULL, NULL, 0x300, + 256, 224, 4, 3 +}; + + +// Twin Action + +static struct BurnRomInfo twinactnRomDesc[] = { + { "afega.uj13", 0x020000, 0x9187701d, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "afega.uj12", 0x020000, 0xfe8cff9c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "afega.su6", 0x008000, 0x3a52dc88, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "afega.uj11", 0x020000, 0x3f439e92, 3 | BRF_GRA }, // 3 Characters + + { "afega.ui20", 0x080000, 0x237c8f92, 4 | BRF_GRA }, // 4 Tiles + + { "afega.ub11", 0x080000, 0x287f20d8, 5 | BRF_GRA }, // 5 Sprites + { "afega.ub13", 0x080000, 0xf525f819, 5 | BRF_GRA }, // 6 + + { "afega.su12", 0x020000, 0x91d665f3, 6 | BRF_SND }, // 7 OKI1 Samples + { "afega.su13", 0x040000, 0x30e1c306, 6 | BRF_SND }, // 8 +}; + +STD_ROM_PICK(twinactn) +STD_ROM_FN(twinactn) + +static INT32 TwinactnLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + memcpy (DrvSndROM0 + 0x40000, DrvSndROM0 + 0x00000, 0x20000); + memcpy (DrvSndROM0 + 0x60000, DrvSndROM0 + 0x00000, 0x20000); + if (BurnLoadRom(DrvSndROM0 + 0x080000, 8, 1)) return 1; + + DrvGfxDecode(0x20000, 0x80000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, afega_main_write_word); + SekSetWriteByteHandler(0, afega_main_write_byte); + SekSetReadWordHandler(0, afega_main_read_word); + SekSetReadByteHandler(0, afega_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 TwinactnInit() +{ + input_high[0] = 0x0000; + input_high[1] = 0x8080; + nNMK004EnableIrq2 = 1; + + return MSM6295x1Init(TwinactnLoadCallback); +} + +struct BurnDriver BurnDrvTwinactn = { + "twinactn", NULL, NULL, NULL, "1995", + "Twin Action\0", NULL, "Afega", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, twinactnRomInfo, twinactnRomName, NULL, NULL, CommonInputInfo, TwinactnDIPInfo, + TwinactnInit, CommonExit, SsmissinFrame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Saboten Bombers (set 1) + +static struct BurnRomInfo sabotenbRomDesc[] = { + { "ic76.sb1", 0x040000, 0xb2b0b2cf, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "ic75.sb2", 0x040000, 0x367e87b7, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "ic35.sb3", 0x010000, 0xeb7bc99d, 3 | BRF_GRA }, // 2 Characters + + { "ic32.sb4", 0x200000, 0x24c62205, 4 | BRF_GRA }, // 3 Tiles + + { "ic100.sb5", 0x200000, 0xb20f166e, 5 | BRF_GRA }, // 4 Sprites + + { "ic30.sb6", 0x100000, 0x288407af, 6 | BRF_SND }, // 5 OKI1 Samples + + { "ic27.sb7", 0x100000, 0x43e33a7e, 7 | BRF_SND }, // 6 OKI2 Samples +}; + +STD_ROM_PICK(sabotenb) +STD_ROM_FN(sabotenb) + +static INT32 SabotenbLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 6, 1)) return 1; + + decode_gfx(0x200000, 0x200000); + + BjtwinGfxDecode(0x10000, 0x200000, 0x200000); + + return 0; +} + +static INT32 SabotenbInit() +{ + return BjtwinInit(SabotenbLoadCallback); +} + +struct BurnDriver BurnDrvSabotenb = { + "sabotenb", NULL, NULL, NULL, "1992", + "Saboten Bombers (set 1)\0", NULL, "NMK / Tecmo", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, sabotenbRomInfo, sabotenbRomName, NULL, NULL, CommonInputInfo, SabotenbDIPInfo, + SabotenbInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 384, 224, 4, 3 +}; + + +// Saboten Bombers (set 2) + +static struct BurnRomInfo sabotenbaRomDesc[] = { + { "sb1.76", 0x040000, 0xdf6f65e2, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "sb2.75", 0x040000, 0x0d2c1ab8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "ic35.sb3", 0x010000, 0xeb7bc99d, 3 | BRF_GRA }, // 2 Characters + + { "ic32.sb4", 0x200000, 0x24c62205, 4 | BRF_GRA }, // 3 Tiles + + { "ic100.sb5", 0x200000, 0xb20f166e, 5 | BRF_GRA }, // 4 Sprites + + { "ic30.sb6", 0x100000, 0x288407af, 6 | BRF_SND }, // 5 OKI1 Samples + + { "ic27.sb7", 0x100000, 0x43e33a7e, 7 | BRF_SND }, // 6 OKI2 Samples +}; + +STD_ROM_PICK(sabotenba) +STD_ROM_FN(sabotenba) + +struct BurnDriver BurnDrvSabotenba = { + "sabotenba", "sabotenb", NULL, NULL, "1992", + "Saboten Bombers (set 2)\0", NULL, "NMK / Tecmo", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, sabotenbaRomInfo, sabotenbaRomName, NULL, NULL, CommonInputInfo, SabotenbDIPInfo, + SabotenbInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 384, 224, 4, 3 +}; + + +// Cactus (bootleg of Saboten Bombers) + +static struct BurnRomInfo cactusRomDesc[] = { + { "02.bin", 0x040000, 0x15b2ff2f, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "01.bin", 0x040000, 0x5b8ba46a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "i03.bin", 0x010000, 0xeb7bc99d, 3 | BRF_GRA }, // 2 Characters + + { "s-05.bin", 0x100000, 0xfce962b9, 4 | BRF_GRA }, // 3 Tiles + { "s-06.bin", 0x100000, 0x16768fbc, 4 | BRF_GRA }, // 4 + + { "s-03.bin", 0x100000, 0xbc1781b8, 5 | BRF_GRA }, // 5 Sprites + { "s-04.bin", 0x100000, 0xf823885e, 5 | BRF_GRA }, // 6 + + { "s-01.bin", 0x100000, 0x288407af, 6 | BRF_SND }, // 7 OKI1 Samples + + { "s-02.bin", 0x100000, 0x43e33a7e, 7 | BRF_SND }, // 8 OKI2 Samples +}; + +STD_ROM_PICK(cactus) +STD_ROM_FN(cactus) + +static INT32 CactusLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 7, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 8, 1)) return 1; + + decode_gfx(0x200000, 0x200000); + + BjtwinGfxDecode(0x10000, 0x200000, 0x200000); + + return 0; +} + +static INT32 CactusInit() +{ + return BjtwinInit(CactusLoadCallback); +} + +struct BurnDriver BurnDrvCactus = { + "cactus", "sabotenb", NULL, NULL, "1992", + "Cactus (bootleg of Saboten Bombers)\0", NULL, "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, cactusRomInfo, cactusRomName, NULL, NULL, CommonInputInfo, SabotenbDIPInfo, + CactusInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 384, 224, 4, 3 +}; + + +// Bombjack Twin (set 1) + +static struct BurnRomInfo bjtwinRomDesc[] = { + { "93087-1.bin", 0x020000, 0x93c84e2d, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "93087-2.bin", 0x020000, 0x30ff678a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "93087-3.bin", 0x010000, 0xaa13df7c, 3 | BRF_GRA }, // 2 Characters + + { "93087-4.bin", 0x100000, 0x8a4f26d0, 4 | BRF_GRA }, // 3 Tiles + + { "93087-5.bin", 0x100000, 0xbb06245d, 5 | BRF_GRA }, // 4 Sprites + + { "93087-6.bin", 0x100000, 0x372d46dd, 6 | BRF_SND }, // 5 OKI1 Samples + + { "93087-7.bin", 0x100000, 0x8da67808, 7 | BRF_SND }, // 6 OKI2 Samples + + { "8.bpr", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 7 Unused proms + { "9.bpr", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 +}; + +STD_ROM_PICK(bjtwin) +STD_ROM_FN(bjtwin) + +static INT32 BjtwinLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x100000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 6, 1)) return 1; + + decode_gfx(0x100000, 0x100000); + + BjtwinGfxDecode(0x10000, 0x100000, 0x100000); + + return 0; +} + +static INT32 BjtwinGameInit() +{ + return BjtwinInit(BjtwinLoadCallback); +} + +struct BurnDriver BurnDrvBjtwin = { + "bjtwin", NULL, NULL, NULL, "1993", + "Bombjack Twin (set 1)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, bjtwinRomInfo, bjtwinRomName, NULL, NULL, CommonInputInfo, BjtwinDIPInfo, + BjtwinGameInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Bombjack Twin (set 2) + +static struct BurnRomInfo bjtwinaRomDesc[] = { + { "93087.1", 0x020000, 0xc82b3d8e, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "93087.2", 0x020000, 0x9be1ec47, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "93087-3.bin", 0x010000, 0xaa13df7c, 3 | BRF_GRA }, // 2 Characters + + { "93087-4.bin", 0x100000, 0x8a4f26d0, 4 | BRF_GRA }, // 3 Tiles + + { "93087-5.bin", 0x100000, 0xbb06245d, 5 | BRF_GRA }, // 4 Sprites + + { "93087-6.bin", 0x100000, 0x372d46dd, 6 | BRF_SND }, // 5 OKI1 Samples + + { "93087-7.bin", 0x100000, 0x8da67808, 7 | BRF_SND }, // 6 OKI2 Samples + + { "8.bpr", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 7 Unused proms + { "9.bpr", 0x000100, 0x435653a2, 0 | BRF_OPT }, // 8 +}; + +STD_ROM_PICK(bjtwina) +STD_ROM_FN(bjtwina) + +struct BurnDriver BurnDrvBjtwina = { + "bjtwina", "bjtwin", NULL, NULL, "1993", + "Bombjack Twin (set 2)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, bjtwinaRomInfo, bjtwinaRomName, NULL, NULL, CommonInputInfo, BjtwinDIPInfo, + BjtwinGameInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Nouryoku Koujou Iinkai + +static struct BurnRomInfo nouryokuRomDesc[] = { + { "ic76.1", 0x040000, 0x26075988, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "ic75.2", 0x040000, 0x75ab82cd, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "ic35.3", 0x010000, 0x03d0c3b1, 3 | BRF_GRA }, // 2 Characters + + { "ic32.4", 0x200000, 0x88d454fd, 4 | BRF_GRA }, // 3 Tiles + + { "ic100.5", 0x200000, 0x24d3e24e, 5 | BRF_GRA }, // 4 Sprites + + { "ic30.6", 0x100000, 0xfeea34f4, 6 | BRF_SND }, // 5 OKI1 Samples + + { "ic27.7", 0x100000, 0x8a69fded, 7 | BRF_SND }, // 6 OKI2 Samples +}; + +STD_ROM_PICK(nouryoku) +STD_ROM_FN(nouryoku) + +static INT32 NouryokuLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 6, 1)) return 1; + + decode_gfx(0x200000, 0x200000); + + BjtwinGfxDecode(0x10000, 0x200000, 0x200000); + + return 0; +} + +static INT32 NouryokuGameInit() +{ + return BjtwinInit(NouryokuLoadCallback); +} + +struct BurnDriver BurnDrvNouryoku = { + "nouryoku", NULL, NULL, NULL, "1995", + "Nouryoku Koujou Iinkai\0", NULL, "Tecmo", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, nouryokuRomInfo, nouryokuRomName, NULL, NULL, CommonInputInfo, NouryokuDIPInfo, + NouryokuGameInit, BjtwinExit, BjtwinFrame, BjtwinDraw, NULL, NULL, 0x400, + 384, 224, 4, 3 +}; + + +// US AAF Mustang (25th May. 1990) + +static struct BurnRomInfo mustangRomDesc[] = { + { "2.bin", 0x020000, 0xbd9f7c89, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3.bin", 0x020000, 0x0eec36a5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "90058-7", 0x010000, 0x920a93c8, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "90058-1", 0x020000, 0x81ccfcad, 3 | BRF_GRA }, // 3 Characters + + { "90058-4", 0x080000, 0xa07a2002, 4 | BRF_GRA }, // 4 Tiles + + { "90058-8", 0x080000, 0x560bff04, 5 | BRF_GRA }, // 5 Sprites + { "90058-9", 0x080000, 0xb9d72a03, 5 | BRF_GRA }, // 6 + + { "90058-5", 0x080000, 0xc60c883e, 6 | BRF_SND }, // 7 OKI1 Samples + + { "90058-6", 0x080000, 0x233c1776, 7 | BRF_SND }, // 8 OKI2 Samples + + { "10.bpr", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 9 Unused proms + { "90058-11", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 +}; + +STD_ROM_PICK(mustang) +STD_ROM_FN(mustang) + +static INT32 MustangLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x20000, 7, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x20000, 8, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x20000, 0x80000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, mustang_main_write_word); + SekSetWriteByteHandler(0, mustang_main_write_byte); + SekSetReadWordHandler(0, mustang_main_read_word); + SekSetReadByteHandler(0, mustang_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 MustangInit() +{ + return NMK004Init(MustangLoadCallback, 10000000, 0, 1); +} + +struct BurnDriver BurnDrvMustang = { + "mustang", NULL, NULL, NULL, "1990", + "US AAF Mustang (25th May. 1990)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, mustangRomInfo, mustangRomName, NULL, NULL, CommonInputInfo, MustangDIPInfo, + MustangInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// US AAF Mustang (25th May. 1990 / Seoul Trading) + +static struct BurnRomInfo mustangsRomDesc[] = { + { "90058-2", 0x020000, 0x833aa458, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "90058-3", 0x020000, 0xe4b80f06, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "90058-7", 0x010000, 0x920a93c8, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "90058-1", 0x020000, 0x81ccfcad, 3 | BRF_GRA }, // 3 Characters + + { "90058-4", 0x080000, 0xa07a2002, 4 | BRF_GRA }, // 4 Tiles + + { "90058-8", 0x080000, 0x560bff04, 5 | BRF_GRA }, // 5 Sprites + { "90058-9", 0x080000, 0xb9d72a03, 5 | BRF_GRA }, // 6 + + { "90058-5", 0x080000, 0xc60c883e, 6 | BRF_SND }, // 7 OKI1 Samples + + { "90058-6", 0x080000, 0x233c1776, 7 | BRF_SND }, // 8 OKI2 Samples + + { "90058-10", 0x000100, 0xde156d99, 0 | BRF_OPT }, // 9 Unused proms + { "90058-11", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 +}; + +STD_ROM_PICK(mustangs) +STD_ROM_FN(mustangs) + +struct BurnDriver BurnDrvMustangs = { + "mustangs", "mustang", NULL, NULL, "1990", + "US AAF Mustang (25th May. 1990 / Seoul Trading)\0", NULL, "UPL (Seoul Trading license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, mustangsRomInfo, mustangsRomName, NULL, NULL, CommonInputInfo, MustangDIPInfo, + MustangInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// US AAF Mustang (bootleg) + +static struct BurnRomInfo mustangbRomDesc[] = { + { "mustang.14", 0x020000, 0x13c6363b, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "mustang.13", 0x020000, 0xd8ccce31, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "mustang.16", 0x010000, 0x99ee7505, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "90058-1", 0x020000, 0x81ccfcad, 3 | BRF_GRA }, // 3 Characters + + { "90058-4", 0x080000, 0xa07a2002, 4 | BRF_GRA }, // 4 Tiles + + { "90058-8", 0x080000, 0x560bff04, 5 | BRF_GRA }, // 5 Sprites + { "90058-9", 0x080000, 0xb9d72a03, 5 | BRF_GRA }, // 6 + + { "mustang.17", 0x010000, 0xf6f6c4bf, 6 | BRF_SND }, // 7 oki +}; + +STD_ROM_PICK(mustangb) +STD_ROM_FN(mustangb) + +static INT32 MustangbLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x8000, 0x8000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x0000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + + DrvGfxDecode(0x20000, 0x80000, 0x100000); + + return 0; +} + +static INT32 MustangbInit() +{ + return SeibuSoundInit(MustangbLoadCallback, 1); +} + +struct BurnDriver BurnDrvMustangb = { + "mustangb", "mustang", NULL, NULL, "1990", + "US AAF Mustang (bootleg)\0", "No sound", "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, mustangbRomInfo, mustangbRomName, NULL, NULL, CommonInputInfo, MustangDIPInfo, + MustangbInit, SeibuSoundExit, SeibuSoundFrame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// US AAF Mustang (TAB Austria bootleg) + +static struct BurnRomInfo mustangb2RomDesc[] = { + { "05.bin", 0x020000, 0x13c6363b, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "04.bin", 0x020000, 0x0d06f723, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "01.bin", 0x010000, 0x90820499, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "06.bin", 0x020000, 0x81ccfcad, 3 | BRF_GRA }, // 3 Characters + + { "07.bin", 0x020000, 0x5f8fdfb1, 4 | BRF_GRA }, // 4 Tiles + { "10.bin", 0x020000, 0x39757d6a, 4 | BRF_GRA }, // 5 + { "08.bin", 0x020000, 0xb3dd5243, 4 | BRF_GRA }, // 6 + { "09.bin", 0x020000, 0xc6c9752f, 4 | BRF_GRA }, // 7 + + { "18.bin", 0x020000, 0xd13f0722, 5 | BRF_GRA }, // 8 Sprites + { "13.bin", 0x020000, 0x54773f95, 5 | BRF_GRA }, // 9 + { "17.bin", 0x020000, 0x87c1fb43, 5 | BRF_GRA }, // 10 + { "14.bin", 0x020000, 0x932d3e33, 5 | BRF_GRA }, // 11 + { "16.bin", 0x020000, 0x23d03ad5, 5 | BRF_GRA }, // 12 + { "15.bin", 0x020000, 0xa62b2f87, 5 | BRF_GRA }, // 13 + { "12.bin", 0x020000, 0x42a6cfc2, 5 | BRF_GRA }, // 14 + { "11.bin", 0x020000, 0x9d3bee66, 5 | BRF_GRA }, // 15 + + { "02.bin", 0x010000, 0xf6f6c4bf, 6 | BRF_SND }, // 16 oki +}; + +STD_ROM_PICK(mustangb2) +STD_ROM_FN(mustangb2) + +static INT32 Mustangb2LoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x8000, 0x8000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x8000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040001, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0c0000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0c0001, 15, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 16, 1)) return 1; + + DrvGfxDecode(0x20000, 0x80000, 0x100000); + + return 0; +} + +static INT32 Mustangb2Init() +{ + return SeibuSoundInit(Mustangb2LoadCallback, 1); +} + +struct BurnDriver BurnDrvMustangb2 = { + "mustangb2", "mustang", NULL, NULL, "1990", + "US AAF Mustang (TAB Austria bootleg)\0", "No sound", "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, mustangb2RomInfo, mustangb2RomName, NULL, NULL, CommonInputInfo, MustangDIPInfo, + Mustangb2Init, SeibuSoundExit, SeibuSoundFrame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Thunder Dragon (9th Jan. 1992) + +static struct BurnRomInfo tdragonRomDesc[] = { + { "91070_68k.8", 0x020000, 0x121c3ae7, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "91070_68k.7", 0x020000, 0x6e154d8e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "91070.1", 0x010000, 0xbf493d74, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "91070.6", 0x020000, 0xfe365920, 3 | BRF_GRA }, // 3 Characters + + { "91070.5", 0x100000, 0xd0bde826, 4 | BRF_GRA }, // 4 Tiles + + { "91070.4", 0x100000, 0x3eedc2fe, 5 | BRF_GRA }, // 5 Sprites + + { "91070.3", 0x080000, 0xae6875a8, 6 | BRF_SND }, // 6 OKI1 Samples + + { "91070.2", 0x080000, 0xecfea43e, 7 | BRF_SND }, // 7 OKI2 Samples + + { "91070.9", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 8 Unused proms + { "91070.10", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(tdragon) +STD_ROM_FN(tdragon) + +static INT32 TdragonLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x100000); + + if (BurnLoadRom(DrvSndROM0 + 0x20000, 6, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x20000, 7, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x20000, 0x100000, 0x100000); + } + + { + *((UINT16*)(Drv68KROM + 0x048a)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x04aa)) = 0x4e71; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x0b0000, 0x0bffff, SM_ROM); + SekMapMemory(DrvScrollRAM, 0x0c4000, 0x0c43ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x0c8000, 0x0c87ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x0cc000, 0x0cffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d0000, 0x0d07ff, SM_RAM); + SekSetWriteWordHandler(0, tdragon_main_write_word); + SekSetWriteByteHandler(0, tdragon_main_write_byte); + SekSetReadWordHandler(0, tdragon_main_read_word); + SekSetReadByteHandler(0, tdragon_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 TdragonInit() +{ + return NMK004Init(TdragonLoadCallback, 8000000, 0, 1); +} + +struct BurnDriver BurnDrvTdragon = { + "tdragon", NULL, NULL, NULL, "1991", + "Thunder Dragon (9th Jan. 1992)\0", "No sound", "NMK (Tecmo license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, tdragonRomInfo, tdragonRomName, NULL, NULL, CommonInputInfo, TdragonDIPInfo, + TdragonInit, NMK004Exit, NMK004Frame, HachamfDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Thunder Dragon (4th Jun. 1991) + +static struct BurnRomInfo tdragon1RomDesc[] = { + { "thund.8", 0x020000, 0xedd02831, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "thund.7", 0x020000, 0x52192fe5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "91070.1", 0x010000, 0xbf493d74, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "91070.6", 0x020000, 0xfe365920, 3 | BRF_GRA }, // 3 Characters + + { "91070.5", 0x100000, 0xd0bde826, 4 | BRF_GRA }, // 4 Tiles + + { "91070.4", 0x100000, 0x3eedc2fe, 5 | BRF_GRA }, // 5 Sprites + + { "91070.3", 0x080000, 0xae6875a8, 6 | BRF_SND }, // 6 OKI1 Samples + + { "91070.2", 0x080000, 0xecfea43e, 7 | BRF_SND }, // 7 OKI2 Samples + + { "91070.9", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 8 Unused proms + { "91070.10", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(tdragon1) +STD_ROM_FN(tdragon1) + +struct BurnDriver BurnDrvTdragon1 = { + "tdragon1", "tdragon", NULL, NULL, "1991", + "Thunder Dragon (4th Jun. 1991)\0", NULL, "NMK (Tecmo license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, tdragon1RomInfo, tdragon1RomName, NULL, NULL, CommonInputInfo, TdragonDIPInfo, + TdragonInit, NMK004Exit, NMK004Frame, HachamfDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Thunder Dragon (bootleg) + +static struct BurnRomInfo tdragonbRomDesc[] = { + { "td_04.bin", 0x020000, 0xe8a62d3e, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "td_03.bin", 0x020000, 0x2fa1aa04, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "td_02.bin", 0x010000, 0x99ee7505, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 code + + { "td_08.bin", 0x020000, 0x5144dc69, 3 | BRF_GRA }, // 3 Characters + + { "td_06.bin", 0x080000, 0xc1be8a4d, 4 | BRF_GRA }, // 4 Tiles + { "td_07.bin", 0x080000, 0x2c3e371f, 4 | BRF_GRA }, // 5 + + { "td_10.bin", 0x080000, 0xbfd0ec5d, 5 | BRF_GRA }, // 6 Sprites + { "td_09.bin", 0x080000, 0xb6e074eb, 5 | BRF_GRA }, // 7 + + { "td_01.bin", 0x010000, 0xf6f6c4bf, 6 | BRF_SND }, // 8 OKI1 Samples +}; + +STD_ROM_PICK(tdragonb) +STD_ROM_FN(tdragonb) + +static INT32 TdragonbLoadCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x8000, 0x8000); + memcpy (DrvZ80ROM + 0x18000, DrvZ80ROM + 0x0000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 8, 1)) return 1; + + decode_tdragonb(); + DrvGfxDecode(0x20000, 0x100000, 0x100000); + + *((UINT16 *)(Drv68KROM + 0x00308)) = 0x4e71; // fix intro sprites + + return 0; +} + +static INT32 TdragonbInit() +{ + return SeibuSoundInit(TdragonbLoadCallback, 0); +} + +struct BurnDriver BurnDrvTdragonb = { + "tdragonb", "tdragon", NULL, NULL, "1991", + "Thunder Dragon (bootleg)\0", "No sound", "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, tdragonbRomInfo, tdragonbRomName, NULL, NULL, CommonInputInfo, TdragonbDIPInfo, + TdragonbInit, SeibuSoundExit, SeibuSoundFrame, MacrossDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + + +// Acrobat Mission + +static struct BurnRomInfo acrobatmRomDesc[] = { + { "02_ic100.bin", 0x020000, 0x3fe487f4, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "01_ic101.bin", 0x020000, 0x17175753, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "04_ic74.bin", 0x010000, 0x176905fb, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "03_ic79.bin", 0x010000, 0xd86c186e, 3 | BRF_GRA }, // 3 Characters + + { "09_ic8.bin", 0x100000, 0x7c12afed, 4 | BRF_GRA }, // 4 Tiles + + { "07_ic42.bin", 0x100000, 0x5672bdaa, 5 | BRF_GRA }, // 5 Sprites + { "08_ic29.bin", 0x080000, 0xb4c0ace3, 5 | BRF_GRA }, // 6 + + { "05_ic54.bin", 0x080000, 0x3b8c2b0e, 6 | BRF_SND }, // 7 OKI1 Samples + + { "06_ic53.bin", 0x080000, 0xc1517cd4, 7 | BRF_SND }, // 8 OKI2 Samples + + { "10_ic81.bin", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 9 Unused proms + { "11_ic80.bin", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 10 +}; + +STD_ROM_PICK(acrobatm) +STD_ROM_FN(acrobatm) + +static INT32 AcrobatmLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 7, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 8, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x10000, 0x100000, 0x200000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x08ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x0c4000, 0x0c47ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x0c8000, 0x0c83ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x0cc000, 0x0cffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x0d4000, 0x0d47ff, SM_RAM); + SekSetWriteWordHandler(0, acrobatm_main_write_word); + SekSetWriteByteHandler(0, acrobatm_main_write_byte); + SekSetReadWordHandler(0, acrobatm_main_read_word); + SekSetReadByteHandler(0, acrobatm_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 AcrobatmInit() +{ + return NMK004Init(AcrobatmLoadCallback, 10000000, 0, 1); +} + +struct BurnDriver BurnDrvAcrobatm = { + "acrobatm", NULL, NULL, NULL, "1991", + "Acrobat Mission\0", NULL, "UPL (Taito license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, acrobatmRomInfo, acrobatmRomName, NULL, NULL, AcrobatmInputInfo, AcrobatmDIPInfo, + AcrobatmInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x300, + 224, 256, 3, 4 +}; + + +// Super Spacefortress Macross / Chou-Jikuu Yousai Macross + +static struct BurnRomInfo macrossRomDesc[] = { + { "921a03", 0x080000, 0x33318d55, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "921a02", 0x010000, 0x77c082c7, 2 | BRF_PRG | BRF_ESS }, // 1 NMK004 data + + { "921a01", 0x020000, 0xbbd8242d, 3 | BRF_GRA }, // 2 Characters + + { "921a04", 0x200000, 0x4002e4bb, 4 | BRF_GRA }, // 3 Tiles + + { "921a07", 0x200000, 0x7d2bf112, 5 | BRF_GRA }, // 4 Sprites + + { "921a05", 0x080000, 0xd5a1eddd, 6 | BRF_SND }, // 5 OKI1 Samples + + { "921a06", 0x080000, 0x89461d0f, 7 | BRF_SND }, // 6 OKI2 Samples + + { "921a08", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 7 Unused proms + { "921a09", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 8 + { "921a10", 0x000020, 0x8371e42d, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(macross) +STD_ROM_FN(macross) + +static INT32 MacrossLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 5, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 6, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + decode_gfx(0x200000, 0x200000); + DrvGfxDecode(0x20000, 0x200000, 0x200000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 MacrossInit() +{ + return NMK004Init(MacrossLoadCallback, 10000000, 0, 0); +} + +struct BurnDriver BurnDrvMacross = { + "macross", NULL, NULL, NULL, "1992", + "Super Spacefortress Macross / Chou-Jikuu Yousai Macross\0", NULL, "Banpresto", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, macrossRomInfo, macrossRomName, NULL, NULL, CommonInputInfo, MacrossDIPInfo, + MacrossInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// GunNail (28th May. 1992) + +static struct BurnRomInfo gunnailRomDesc[] = { + { "3e.bin", 0x040000, 0x61d985b2, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "3o.bin", 0x040000, 0xf114e89c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "92077_2.bin", 0x010000, 0xcd4e55f8, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "1.bin", 0x020000, 0x3d00a9f4, 3 | BRF_GRA }, // 3 Characters + + { "92077-4.bin", 0x100000, 0xa9ea2804, 4 | BRF_GRA }, // 4 Tiles + + { "92077-7.bin", 0x200000, 0xd49169b3, 5 | BRF_GRA }, // 5 Sprites + + { "92077-5.bin", 0x080000, 0xfeb83c73, 6 | BRF_SND }, // 6 OKI1 Samples + + { "92077-6.bin", 0x080000, 0x6d133f0d, 7 | BRF_SND }, // 7 OKI2 Samples + + { "8.bpr", 0x000100, 0x4299776e, 0 | BRF_OPT }, // 8 Unused proms + { "9.bpr", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 9 + { "10.bpr", 0x000020, 0xc60103c8, 0 | BRF_OPT }, // 10 +}; + +STD_ROM_PICK(gunnail) +STD_ROM_FN(gunnail) + +static INT32 GunnailLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x200000); + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 5, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 6, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + decode_gfx(0x100000, 0x200000); + DrvGfxDecode(0x20000, 0x100000, 0x200000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c7ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09cfff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09d000, 0x09dfff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 GunnailInit() +{ + return NMK004Init(GunnailLoadCallback, 12000000, 0, 0); +} + +struct BurnDriver BurnDrvGunnail = { + "gunnail", NULL, NULL, NULL, "1993", + "GunNail (28th May. 1992)\0", NULL, "NMK / Tecmo", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, gunnailRomInfo, gunnailRomName, NULL, NULL, CommonInputInfo, GunnailDIPInfo, + GunnailInit, NMK004Exit, NMK004Frame, GunnailDraw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; + + +// Black Heart + +static struct BurnRomInfo blkheartRomDesc[] = { + { "blkhrt.7", 0x020000, 0x5bd248c0, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "blkhrt.6", 0x020000, 0x6449e50d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "4.bin", 0x010000, 0x7cefa295, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "3.bin", 0x020000, 0xa1ab3a16, 3 | BRF_GRA }, // 3 Characters + + { "90068-5.bin", 0x100000, 0xa1ab4f24, 4 | BRF_GRA }, // 4 Tiles + + { "90068-8.bin", 0x100000, 0x9d3204b2, 5 | BRF_GRA }, // 5 Sprites + + { "90068-2.bin", 0x080000, 0x3a583184, 6 | BRF_SND }, // 6 OKI1 Samples + + { "90068-1.bin", 0x080000, 0xe7af69d2, 7 | BRF_SND }, // 7 OKI2 Samples + + { "9.bpr", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 8 Unused proms + { "10.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(blkheart) +STD_ROM_FN(blkheart) + +static INT32 BlkheartLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x100000); + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x20000, 0x100000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 BlkheartInit() +{ + return NMK004Init(BlkheartLoadCallback, 8000000, 0, 0); +} + +struct BurnDriver BurnDrvBlkheart = { + "blkheart", NULL, NULL, NULL, "1991", + "Black Heart\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, blkheartRomInfo, blkheartRomName, NULL, NULL, CommonInputInfo, BlkheartDIPInfo, + BlkheartInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Black Heart (Japan) + +static struct BurnRomInfo blkheartjRomDesc[] = { + { "7.bin", 0x020000, 0xe0a5c667, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "6.bin", 0x020000, 0x7cce45e8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "4.bin", 0x010000, 0x7cefa295, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "3.bin", 0x020000, 0xa1ab3a16, 3 | BRF_GRA }, // 3 Characters + + { "90068-5.bin", 0x100000, 0xa1ab4f24, 4 | BRF_GRA }, // 4 Tiles + + { "90068-8.bin", 0x100000, 0x9d3204b2, 5 | BRF_GRA }, // 5 Sprites + + { "90068-2.bin", 0x080000, 0x3a583184, 6 | BRF_SND }, // 6 OKI1 Samples + + { "90068-1.bin", 0x080000, 0xe7af69d2, 7 | BRF_SND }, // 7 OKI2 Samples + + { "9.bpr", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 8 Unused proms + { "10.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 9 +}; + +STD_ROM_PICK(blkheartj) +STD_ROM_FN(blkheartj) + +struct BurnDriver BurnDrvBlkheartj = { + "blkheartj", "blkheart", NULL, NULL, "1991", + "Black Heart (Japan)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, blkheartjRomInfo, blkheartjRomName, NULL, NULL, CommonInputInfo, BlkheartDIPInfo, + BlkheartInit, NMK004Exit, NMK004Frame, MacrossDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Vandyke (Japan) + +static struct BurnRomInfo vandykeRomDesc[] = { + { "vdk-1.16", 0x020000, 0xc1d01c59, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "vdk-2.15", 0x020000, 0x9d741cc2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "vdk-4.127", 0x010000, 0xeba544f0, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "vdk-3.222", 0x010000, 0x5a547c1b, 3 | BRF_GRA }, // 3 Characters + + { "vdk-01.13", 0x080000, 0x195a24be, 4 | BRF_GRA }, // 4 Tiles + + { "vdk-07.202", 0x080000, 0x42d41f06, 5 | BRF_GRA }, // 5 Sprites + { "vdk-06.203", 0x080000, 0xd54722a8, 5 | BRF_GRA }, // 6 + { "vdk-04.2-1", 0x080000, 0x0a730547, 5 | BRF_GRA }, // 7 + { "vdk-05.3-1", 0x080000, 0xba456d27, 5 | BRF_GRA }, // 8 + + { "vdk-02.126", 0x080000, 0xb2103274, 6 | BRF_SND }, // 9 OKI1 Samples + + { "vdk-03.165", 0x080000, 0x631776d3, 7 | BRF_SND }, // 10 OKI2 Samples + + { "ic100.bpr", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 11 Unused proms + { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(vandyke) +STD_ROM_FN(vandyke) + +static INT32 VandykeLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100001, 8, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x10000, 0x80000, 0x200000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09d000, 0x09d7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 VandykeInit() +{ + return NMK004Init(VandykeLoadCallback, 10000000, 0, 1); +} + +struct BurnDriver BurnDrvVandyke = { + "vandyke", NULL, NULL, NULL, "1990", + "Vandyke (Japan)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, vandykeRomInfo, vandykeRomName, NULL, NULL, CommonInputInfo, VandykeDIPInfo, + VandykeInit, NMK004Exit, NMK004Frame, VandykeDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Vandyke (Jaleco, Set 1) + +static struct BurnRomInfo vandykejalRomDesc[] = { + { "vdk-1.16", 0x020000, 0xc1d01c59, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "jaleco2.15", 0x020000, 0x170e4d2e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "vdk-4.127", 0x010000, 0xeba544f0, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "vdk-3.222", 0x010000, 0x5a547c1b, 3 | BRF_GRA }, // 3 Characters + + { "vdk-01.13", 0x080000, 0x195a24be, 4 | BRF_GRA }, // 4 Tiles + + { "vdk-07.202", 0x080000, 0x42d41f06, 5 | BRF_GRA }, // 5 Sprites + { "vdk-06.203", 0x080000, 0xd54722a8, 5 | BRF_GRA }, // 6 + { "vdk-04.2-1", 0x080000, 0x0a730547, 5 | BRF_GRA }, // 7 + { "vdk-05.3-1", 0x080000, 0xba456d27, 5 | BRF_GRA }, // 8 + + { "vdk-02.126", 0x080000, 0xb2103274, 6 | BRF_SND }, // 9 OKI1 Samples + + { "vdk-03.165", 0x080000, 0x631776d3, 7 | BRF_SND }, // 10 OKI2 Samples + + { "ic100.bpr", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 11 Unused proms + { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(vandykejal) +STD_ROM_FN(vandykejal) + +struct BurnDriver BurnDrvVandykejal = { + "vandykejal", "vandyke", NULL, NULL, "1990", + "Vandyke (Jaleco, Set 1)\0", NULL, "UPL (Jaleco license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, vandykejalRomInfo, vandykejalRomName, NULL, NULL, CommonInputInfo, VandykeDIPInfo, + VandykeInit, NMK004Exit, NMK004Frame, VandykeDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Vandyke (Jaleco, Set 2) + +static struct BurnRomInfo vandykejal2RomDesc[] = { + { "vdk-even.16", 0x020000, 0xcde05a84, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "vdk-odd.15", 0x020000, 0x0f6fea40, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "vdk-4.127", 0x010000, 0xeba544f0, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "vdk-3.222", 0x010000, 0x5a547c1b, 3 | BRF_GRA }, // 3 Characters + + { "vdk-01.13", 0x080000, 0x195a24be, 4 | BRF_GRA }, // 4 Tiles + + { "vdk-07.202", 0x080000, 0x42d41f06, 5 | BRF_GRA }, // 5 Sprites + { "vdk-06.203", 0x080000, 0xd54722a8, 5 | BRF_GRA }, // 6 + { "vdk-04.2-1", 0x080000, 0x0a730547, 5 | BRF_GRA }, // 7 + { "vdk-05.3-1", 0x080000, 0xba456d27, 5 | BRF_GRA }, // 8 + + { "vdk-02.126", 0x080000, 0xb2103274, 6 | BRF_SND }, // 9 OKI1 Samples + + { "vdk-03.165", 0x080000, 0x631776d3, 7 | BRF_SND }, // 10 OKI2 Samples + + { "ic100.bpr", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 11 Unused proms + { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(vandykejal2) +STD_ROM_FN(vandykejal2) + +struct BurnDriver BurnDrvVandykejal2 = { + "vandykejal2", "vandyke", NULL, NULL, "1990", + "Vandyke (Jaleco, Set 2)\0", NULL, "UPL (Jaleco license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, vandykejal2RomInfo, vandykejal2RomName, NULL, NULL, CommonInputInfo, VandykeDIPInfo, + VandykeInit, NMK004Exit, NMK004Frame, VandykeDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Vandyke (bootleg with PIC16c57) + +static struct BurnRomInfo vandykebRomDesc[] = { + { "2.bin", 0x020000, 0x9c269702, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "1.bin", 0x020000, 0xdd6303a1, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "pic16c57", 0x002d4c, 0xbdb3920d, 2 | BRF_PRG | BRF_ESS }, // 2 PIC16c57 code + + { "3.bin", 0x010000, 0x5a547c1b, 3 | BRF_GRA }, // 3 Characters + + { "4.bin", 0x040000, 0x4ba4138d, 4 | BRF_GRA }, // 4 Tiles + { "5.bin", 0x040000, 0x9a1ac697, 4 | BRF_GRA }, // 5 + + { "13.bin", 0x040000, 0xbb561871, 5 | BRF_GRA }, // 6 Sprites + { "17.bin", 0x040000, 0x346e3b66, 5 | BRF_GRA }, // 7 + { "12.bin", 0x040000, 0xcdef9b17, 5 | BRF_GRA }, // 8 + { "16.bin", 0x040000, 0xbeda678c, 5 | BRF_GRA }, // 9 + { "11.bin", 0x020000, 0x823185d9, 5 | BRF_GRA }, // 10 + { "15.bin", 0x020000, 0x149f3247, 5 | BRF_GRA }, // 11 + { "10.bin", 0x020000, 0x388b1abc, 5 | BRF_GRA }, // 12 + { "14.bin", 0x020000, 0x32eeba37, 5 | BRF_GRA }, // 13 + + { "9.bin", 0x020000, 0x56bf774f, 6 | BRF_SND }, // 14 OKI1 Samples + { "8.bin", 0x020000, 0x89851fcf, 6 | BRF_SND }, // 15 + { "7.bin", 0x020000, 0xd7bf0f6a, 6 | BRF_SND }, // 16 + { "6.bin", 0x020000, 0xa7fcf709, 6 | BRF_SND }, // 17 +}; + +STD_ROM_PICK(vandykeb) +STD_ROM_FN(vandykeb) + +static INT32 VandykebLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + // if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080001, 9, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100001, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x140000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x140001, 13, 2)) return 1; + + // if (BurnLoadRom(DrvSndROM0 + 0x000000, 14, 1)) return 1; + // if (BurnLoadRom(DrvSndROM0 + 0x020000, 15, 1)) return 1; + // if (BurnLoadRom(DrvSndROM0 + 0x040000, 16, 1)) return 1; + // if (BurnLoadRom(DrvSndROM0 + 0x060000, 17, 1)) return 1; + + DrvGfxDecode(0x10000, 0x80000, 0x200000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); +// SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09d000, 0x09d7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, vandykeb_main_write_word); // different scroll regs + SekSetWriteByteHandler(0, vandykeb_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 VandykebInit() +{ + input_high[0] = 0x0040; // or it locks up + + return NMK004Init(VandykebLoadCallback, 10000000, 0, 1); +} + +struct BurnDriver BurnDrvVandykeb = { + "vandykeb", "vandyke", NULL, NULL, "1990", + "Vandyke (bootleg with PIC16c57)\0", "No sound", "[UPL] (bootleg)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, vandykebRomInfo, vandykebRomName, NULL, NULL, CommonInputInfo, VandykeDIPInfo, + VandykebInit, NMK004Exit, NMK004Frame, VandykeDraw, NULL, NULL, 0x400, + 224, 256, 3, 4 +}; + + +// Hacha Mecha Fighter (19th Sep. 1991) + +static struct BurnRomInfo hachamfRomDesc[] = { + { "7.93", 0x020000, 0x9d847c31, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "6.94", 0x020000, 0xde6408a0, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.70", 0x010000, 0x9e6f48fc, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "5.95", 0x020000, 0x29fb04a2, 3 | BRF_GRA }, // 3 Characters + + { "91076-4.101", 0x100000, 0xdf9653a4, 4 | BRF_GRA }, // 4 Tiles + + { "91076-8.57", 0x100000, 0x7fd0f556, 5 | BRF_GRA }, // 5 Sprites + + { "91076-2.46", 0x080000, 0x3f1e67f2, 6 | BRF_SND }, // 6 OKI1 Samples + + { "91076-3.45", 0x080000, 0xb25ed93b, 7 | BRF_SND }, // 7 OKI2 Samples +}; + +STD_ROM_PICK(hachamf) +STD_ROM_FN(hachamf) + +static INT32 HachamfLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x100000); + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x20000, 0x100000, 0x100000); + } + + { + *((UINT16*)(Drv68KROM + 0x048a)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x04aa)) = 0x4e71; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_ROM); + SekSetWriteWordHandler(0, hachamf_main_write_word); + SekSetWriteByteHandler(0, hachamf_main_write_byte); + SekSetReadWordHandler(0, hachamf_main_read_word); + SekSetReadByteHandler(0, hachamf_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 HachamfInit() +{ + return NMK004Init(HachamfLoadCallback, 10000000, 0, 0); +} + +struct BurnDriver BurnDrvHachamf = { + "hachamf", NULL, NULL, NULL, "1991", + "Hacha Mecha Fighter (19th Sep. 1991)\0", NULL, "NMK", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, hachamfRomInfo, hachamfRomName, NULL, NULL, CommonInputInfo, HachamfDIPInfo, + HachamfInit, NMK004Exit, NMK004Frame, HachamfDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Koutetsu Yousai Strahl (Japan set 1) + +static struct BurnRomInfo strahlRomDesc[] = { + { "strahl-2.82", 0x020000, 0xc9d008ae, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "strahl-1.83", 0x020000, 0xafc3c4d6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "strahl-4.66", 0x010000, 0x60a799c4, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "strahl-3.73", 0x010000, 0x2273b33e, 3 | BRF_GRA }, // 3 Characters + + { "str7b2r0.275", 0x040000, 0x5769e3e1, 4 | BRF_GRA }, // 4 Tiles + + { "strl3-01.32", 0x080000, 0xd8337f15, 5 | BRF_GRA }, // 5 Sprites + { "strl4-02.57", 0x080000, 0x2a38552b, 5 | BRF_GRA }, // 6 + { "strl5-03.58", 0x080000, 0xa0e7d210, 5 | BRF_GRA }, // 7 + + { "str6b1w1.776", 0x080000, 0xbb1bb155, 9 | BRF_SND }, // 8 Foreground Tiles + + { "str8pmw1.540", 0x080000, 0x01d6bb6a, 6 | BRF_SND }, // 9 OKI1 Samples + + { "str9pew1.639", 0x080000, 0x6bb3eb9f, 7 | BRF_SND }, // 10 OKI2 Samples +}; + +STD_ROM_PICK(strahl) +STD_ROM_FN(strahl) + +static INT32 StrahlLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x10000, 0x100000, 0x200000); + } + + { + *((UINT16*)(Drv68KROM + 0x79e)) = 0x4e71; // remove protection + *((UINT16*)(Drv68KROM + 0x7a0)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x7a2)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x8e0)) = 0x4e71; // force pass rom check + *((UINT16*)(Drv68KROM + 0x8e2)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x968)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x96a)) = 0x4e71; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvScrollRAM, 0x084000, 0x0843ff, SM_RAM); + SekMapMemory(DrvScrollRAM + 0x400, 0x088000, 0x0883ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x08c000, 0x08c7ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x094000, 0x097fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 StrahlInit() +{ + return NMK004Init(StrahlLoadCallback, 12000000, 0, 1); +} + +struct BurnDriver BurnDrvStrahl = { + "strahl", NULL, NULL, NULL, "1992", + "Koutetsu Yousai Strahl (Japan set 1)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, strahlRomInfo, strahlRomName, NULL, NULL, CommonInputInfo, StrahlDIPInfo, + StrahlInit, NMK004Exit, NMK004Frame, StrahlDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Koutetsu Yousai Strahl (Japan set 2) + +static struct BurnRomInfo strahlaRomDesc[] = { + { "rom2", 0x020000, 0xf80a22ef, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "rom1", 0x020000, 0x802ecbfc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "strahl-4.66", 0x010000, 0x60a799c4, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "strahl-3.73", 0x010000, 0x2273b33e, 3 | BRF_GRA }, // 3 Characters + + { "str7b2r0.275", 0x040000, 0x5769e3e1, 4 | BRF_GRA }, // 4 Tiles + + { "strl3-01.32", 0x080000, 0xd8337f15, 5 | BRF_GRA }, // 5 Sprites + { "strl4-02.57", 0x080000, 0x2a38552b, 5 | BRF_GRA }, // 6 + { "strl5-03.58", 0x080000, 0xa0e7d210, 5 | BRF_GRA }, // 7 + + { "str6b1w1.776", 0x080000, 0xbb1bb155, 9 | BRF_GRA }, // 8 Foreground tiles + + { "str8pmw1.540", 0x080000, 0x01d6bb6a, 6 | BRF_SND }, // 9 OKI1 Samples + + { "str9pew1.639", 0x080000, 0x6bb3eb9f, 7 | BRF_SND }, // 10 OKI2 Samples +}; + +STD_ROM_PICK(strahla) +STD_ROM_FN(strahla) + +struct BurnDriver BurnDrvStrahla = { + "strahla", "strahl", NULL, NULL, "1992", + "Koutetsu Yousai Strahl (Japan set 2)\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, strahlaRomInfo, strahlaRomName, NULL, NULL, CommonInputInfo, StrahlDIPInfo, + StrahlInit, NMK004Exit, NMK004Frame, StrahlDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Bio-ship Paladin + +static struct BurnRomInfo bioshipRomDesc[] = { + { "2.ic14", 0x020000, 0xacf56afb, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "1.ic15", 0x020000, 0x820ef303, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "6.ic120", 0x010000, 0x5f39a980, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "7", 0x010000, 0x2f3f5a10, 3 | BRF_GRA }, // 3 Characters + + { "sbs-g_01.ic9", 0x080000, 0x21302e78, 4 | BRF_GRA }, // 4 Tiles + + { "sbs-g_03.ic194", 0x080000, 0x60e00d7b, 5 | BRF_GRA }, // 5 Sprites + + { "sbs-g_02.ic4", 0x080000, 0xf31eb668, 9 | BRF_GRA }, // 6 Foreground tiles + + { "8.ic27", 0x010000, 0x75a46fea, 10 | BRF_GRA }, // 7 Tilemap roms + { "9.ic26", 0x010000, 0xd91448ee, 10 | BRF_GRA }, // 8 + + { "sbs-g_04.ic139", 0x080000, 0x7c74cc4e, 6 | BRF_SND }, // 9 OKI1 Samples + + { "sbs-g_05.ic160", 0x080000, 0xf0a782e3, 7 | BRF_SND }, // 10 OKI2 Samples + + { "82s135.ic94", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 11 Unused proms + { "82s129.ic69", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 + { "82s123.ic154", 0x000020, 0x0f789fc7, 0 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(bioship) +STD_ROM_FN(bioship) + +static INT32 BioshipLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 6, 1)) return 1; + + if (BurnLoadRom(DrvTileROM + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvTileROM + 0x000000, 8, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; + memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x10000, 0x100000, 0x80000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 BioshipInit() +{ + return NMK004Init(BioshipLoadCallback, 10000000, 1, 1); +} + +struct BurnDriver BurnDrvBioship = { + "bioship", NULL, NULL, NULL, "1990", + "Bio-ship Paladin\0", NULL, "UPL (American Sammy license)", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, bioshipRomInfo, bioshipRomName, NULL, NULL, CommonInputInfo, BioshipDIPInfo, + BioshipInit, NMK004Exit, NMK004Frame, BioshipDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Space Battle Ship Gomorrah + +static struct BurnRomInfo sbsgomoRomDesc[] = { + { "11.ic14", 0x020000, 0x7916150b, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "10.ic15", 0x020000, 0x1d7accb8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "6.ic120", 0x010000, 0x5f39a980, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "7.ic46", 0x010000, 0xf2b77f80, 3 | BRF_GRA }, // 3 Characters + + { "sbs-g_01.ic9", 0x080000, 0x21302e78, 4 | BRF_GRA }, // 4 Tiles + + { "sbs-g_03.ic194", 0x080000, 0x60e00d7b, 5 | BRF_GRA }, // 5 Sprites + + { "sbs-g_02.ic4", 0x080000, 0xf31eb668, 9 | BRF_GRA }, // 6 Foreground tiles + + { "8.ic27", 0x010000, 0x75a46fea, 10 | BRF_GRA }, // 7 Tilemap roms + { "9.ic26", 0x010000, 0xd91448ee, 10 | BRF_GRA }, // 8 + + { "sbs-g_04.ic139", 0x080000, 0x7c74cc4e, 6 | BRF_SND }, // 9 OKI1 Samples + + { "sbs-g_05.ic160", 0x080000, 0xf0a782e3, 7 | BRF_SND }, // 10 OKI2 Samples + + { "82s135.ic94", 0x000100, 0x98ed1c97, 0 | BRF_OPT }, // 11 Unused proms + { "82s129.ic69", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 + { "82s123.ic154", 0x000020, 0x0f789fc7, 0 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(sbsgomo) +STD_ROM_FN(sbsgomo) + +struct BurnDriver BurnDrvSbsgomo = { + "sbsgomo", "bioship", NULL, NULL, "1990", + "Space Battle Ship Gomorrah\0", NULL, "UPL", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, sbsgomoRomInfo, sbsgomoRomName, NULL, NULL, CommonInputInfo, BioshipDIPInfo, + BioshipInit, NMK004Exit, NMK004Frame, BioshipDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Rapid Hero + +static struct BurnRomInfo rapheroRomDesc[] = { + { "rhp94099.3", 0x080000, 0xec9b4f05, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + + { "rhp94099.2", 0x020000, 0xfe01ece1, 2 | BRF_PRG | BRF_ESS }, // 1 Tmp90c841 Code + + { "rhp94099.1", 0x020000, 0x55a7a011, 3 | BRF_GRA }, // 2 Characters + + { "rhp94099.4", 0x200000, 0x076eee7b, 4 | BRF_GRA }, // 3 Tiles + + { "rhp94099.8", 0x200000, 0x49892f07, 5 | BRF_GRA }, // 4 Sprites + { "rhp94099.9", 0x200000, 0xea2e47f0, 5 | BRF_GRA }, // 5 + { "rhp94099.10", 0x200000, 0x512cb839, 5 | BRF_GRA }, // 6 + + { "rhp94099.7", 0x200000, 0x0d99547e, 6 | BRF_SND }, // 7 OKI1 Samples + + { "rhp94099.5", 0x200000, 0x515eba93, 7 | BRF_SND }, // 8 OKI2 Samples + { "rhp94099.6", 0x200000, 0xf1a80e5a, 7 | BRF_SND }, // 9 + { "rhp94099.7", 0x200000, 0x0d99547e, 7 | BRF_SND }, // 10 + { "rhp94099.7", 0x200000, 0x0d99547e, 7 | BRF_SND }, // 11 + + { "prom1.u19", 0x000100, 0x4299776e, 0 | BRF_OPT }, // 12 Unused proms + { "prom2.u53", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 13 + { "prom3.u60", 0x000100, 0x304f98c6, 0 | BRF_OPT }, // 14 +}; + +STD_ROM_PICK(raphero) +STD_ROM_FN(raphero) + +static INT32 RapheroLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 1, 1)) return 1; + memmove (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x00000, 0x20000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x200000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400000, 6, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x600000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 7, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x40000, 0x20000); + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 8, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x240000, 9, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x440000, 10, 1)) return 1; + if (BurnLoadRom(DrvSndROM0 + 0x640000, 11, 1)) return 1; + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x40000, 0x20000); + + DrvGfxDecode(0x20000, 0x200000, 0x600000); + memset (DrvGfxROM2 + 0xc00000, 0x0f, 0x400000); + nGraphicsMask[2] = 0xffff; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x130000, 0x1307ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x140000, 0x143fff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x144000, 0x147fff, SM_RAM); + SekMapMemory(DrvBgRAM2, 0x148000, 0x14bfff, SM_RAM); + SekMapMemory(DrvBgRAM3, 0x14c000, 0x14ffff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x170000, 0x170fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x171000, 0x171fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x1f0000, 0x1fffff, SM_RAM); + SekSetWriteWordHandler(0, raphero_main_write_word); + SekSetWriteByteHandler(0, raphero_main_write_byte); + SekSetReadWordHandler(0, raphero_main_read_word); + SekSetReadByteHandler(0, raphero_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 RapheroInit() +{ + return NMK004Init(RapheroLoadCallback, 14000000, 0, 0); // NOT REALLY NMK004!!! +} + +struct BurnDriver BurnDrvRaphero = { + "raphero", NULL, NULL, NULL, "1994", + "Rapid Hero\0", "Incomplete sound", "Media Trading Corp", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, rapheroRomInfo, rapheroRomName, NULL, NULL, Tdragon2InputInfo, RapheroDIPInfo, + RapheroInit, NMK004Exit, NMK004Frame, RapheroDraw, NULL, NULL, 0x400, + 224, 384, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_ohmygod.cpp b/src/burn/drivers/misc_post90s/d_ohmygod.cpp new file mode 100644 index 00000000..a88563d7 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_ohmygod.cpp @@ -0,0 +1,691 @@ +#include "tiles_generic.h" +#include "msm6295.h" + +// define this to enable basic unmapped memory reads and writes +#define OHMYGODLOG 1 + +static UINT8 OhmygodInputPort0[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 OhmygodInputPort1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 OhmygodDip[2] = {0, 0}; +static UINT16 OhmygodInput[2] = {0x00, 0x00}; +static UINT8 OhmygodReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *OhmygodRom = NULL; +static UINT8 *OhmygodRam = NULL; +static UINT8 *OhmygodVideoRam = NULL; +static UINT8 *OhmygodPaletteRam = NULL; +static UINT8 *OhmygodSpriteRam = NULL; +static UINT32 *OhmygodPalette = NULL; + +UINT8 *OhmygodChars; +UINT8 *OhmygodSprites; + +static INT32 AdpcmBankShift; +static INT32 SndBank; +static INT32 watch_tick=0; +static INT32 OhmygodSpriteBank; +static UINT32 OhmygodScrollx; +static UINT32 OhmygodScrolly; + +static struct BurnInputInfo OhmygodInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , OhmygodInputPort0 + 8, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , OhmygodInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , OhmygodInputPort1 + 8, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , OhmygodInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , OhmygodInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , OhmygodInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , OhmygodInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , OhmygodInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , OhmygodInputPort0 + 4, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , OhmygodInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , OhmygodInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , OhmygodInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , OhmygodInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , OhmygodInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &OhmygodReset , "reset" }, + {"Service" , BIT_DIGITAL , OhmygodInputPort1 + 9, "service" }, + {"Diagnostic" , BIT_DIGITAL , OhmygodInputPort0 + 9, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, OhmygodDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, OhmygodDip + 1 , "dip" }, +}; + +STDINPUTINFO(Ohmygod) + +inline void OhmygodClearOpposites(UINT16* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void OhmygodMakeInputs() +{ + // Reset Inputs + OhmygodInput[0] = OhmygodInput[1] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 10; i++) { + OhmygodInput[0] |= (OhmygodInputPort0[i] & 1) << i; + OhmygodInput[1] |= (OhmygodInputPort1[i] & 1) << i; + } + + // Clear Opposites + OhmygodClearOpposites(&OhmygodInput[0]); + OhmygodClearOpposites(&OhmygodInput[1]); +} + +static struct BurnDIPInfo OhmygodDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 15 , "Coin A" }, + {0x11, 0x01, 0x0f, 0x05, "6 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x03, "5 Coin-6 Play" }, + {0x11, 0x01, 0x0f, 0x07, "4 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x04, "4 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x02, "4 Coin-5 Play" }, + {0x11, 0x01, 0x0f, 0x08, "3 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x01, "2 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin-2 Play" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin-4 Play" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin-5 Play" }, + {0x11, 0x01, 0x0f, 0x0a, "1 Coin-6 Play" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x11, 0x01, 0xf0, 0x50, "6 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0x30, "5 Coin-6 Play" }, + {0x11, 0x01, 0xf0, 0x70, "4 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x40, "4 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0x20, "4 Coin-5 Play" }, + {0x11, 0x01, 0xf0, 0x80, "3 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x90, "2 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x10, "2 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0xe0, "1 Coin-2 Play" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0xc0, "1 Coin-4 Play" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin-5 Play" }, + {0x11, 0x01, 0xf0, 0xa0, "1 Coin-6 Play" }, + {0x11, 0x01, 0xf0, 0x00, "Free Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "1P Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "VS Difficulty" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal Jake" }, + {0x12, 0x01, 0x0c, 0x08, "Hard Jake" }, + {0x12, 0x01, 0x0c, 0x04, "Normal" }, + {0x12, 0x01, 0x0c, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "VS Matches/Credit" }, + {0x12, 0x01, 0x10, 0x00, "1 Game Match" }, + {0x12, 0x01, 0x10, 0x10, "3 Game Match" }, + + {0 , 0xfe, 0 , 2 , "Attract Sound" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Balls Have Eyes" }, + {0x12, 0x01, 0x40, 0x00, "No" }, + {0x12, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ohmygod) + +static struct BurnDIPInfo NanameDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 15 , "Coin A" }, + {0x11, 0x01, 0x0f, 0x05, "6 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x03, "5 Coin-6 Play" }, + {0x11, 0x01, 0x0f, 0x07, "4 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x04, "4 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x02, "4 Coin-5 Play" }, + {0x11, 0x01, 0x0f, 0x08, "3 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x09, "2 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x01, "2 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x0f, "1 Coin-1 Play" }, + {0x11, 0x01, 0x0f, 0x0e, "1 Coin-2 Play" }, + {0x11, 0x01, 0x0f, 0x0d, "1 Coin-3 Play" }, + {0x11, 0x01, 0x0f, 0x0c, "1 Coin-4 Play" }, + {0x11, 0x01, 0x0f, 0x0b, "1 Coin-5 Play" }, + {0x11, 0x01, 0x0f, 0x0a, "1 Coin-6 Play" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x11, 0x01, 0xf0, 0x50, "6 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0x30, "5 Coin-6 Play" }, + {0x11, 0x01, 0xf0, 0x70, "4 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x40, "4 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0x20, "4 Coin-5 Play" }, + {0x11, 0x01, 0xf0, 0x80, "3 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x90, "2 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0x10, "2 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin-1 Play" }, + {0x11, 0x01, 0xf0, 0xe0, "1 Coin-2 Play" }, + {0x11, 0x01, 0xf0, 0xd0, "1 Coin-3 Play" }, + {0x11, 0x01, 0xf0, 0xc0, "1 Coin-4 Play" }, + {0x11, 0x01, 0xf0, 0xb0, "1 Coin-5 Play" }, + {0x11, 0x01, 0xf0, 0xa0, "1 Coin-6 Play" }, + {0x11, 0x01, 0xf0, 0x00, "Free Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "1P Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "VS Difficulty" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal Jake" }, + {0x12, 0x01, 0x0c, 0x08, "Hard Jake" }, + {0x12, 0x01, 0x0c, 0x04, "Normal" }, + {0x12, 0x01, 0x0c, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "VS Matches/Credit" }, + {0x12, 0x01, 0x10, 0x00, "1 Game Match" }, + {0x12, 0x01, 0x10, 0x10, "3 Game Match" }, + + {0 , 0xfe, 0 , 2 , "Attract Sound" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Balls Have Eyes" }, + {0x12, 0x01, 0x40, 0x00, "No" }, + {0x12, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Naname) + +static struct BurnRomInfo OhmygodRomDesc[] = { + { "omg-p.114", 0x080000, 0x48fa40ca, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + + { "omg-b.117", 0x080000, 0x73621fa6, BRF_GRA }, // 1 Characters + { "omg-s.120", 0x080000, 0x6413bd36, BRF_GRA }, // 2 Sprites + + { "omg-g.107", 0x200000, 0x7405573c, BRF_SND }, // 3 Samples +}; + + +STD_ROM_PICK(Ohmygod) +STD_ROM_FN(Ohmygod) + +static struct BurnRomInfo NanameRomDesc[] = { + { "036-prg.114", 0x080000, 0x3b7362f7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + + { "036-bg.117", 0x080000, 0xf53e8da5, BRF_GRA }, // 1 Characters + { "036-spr.120", 0x080000, 0xe36d8731, BRF_GRA }, // 2 Sprites + + { "036-snd.107", 0x200000, 0xa3e0caf4, BRF_SND }, // 3 Samples +}; + + +STD_ROM_PICK(Naname) +STD_ROM_FN(Naname) + +INT32 OhmygodDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + watch_tick=3*60; + + // Set the initial MSM6295 Bank + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ohmygod")) { + AdpcmBankShift = 4; + } else { + AdpcmBankShift = 0; + } + + OhmygodSpriteBank = 0; + + SndBank = 0; + memcpy(MSM6295ROM + 0x20000, MSM6295ROM + 0x40000 + 0x20000 * SndBank, 0x20000); + + MSM6295Reset(0); + + return 0; +} + + +void do_watchtick() +{ + if (watch_tick > 0) + if (--watch_tick == 0) { + SekOpen(0); + SekReset(); + SekClose(); + watch_tick=3*60; + } +} + +UINT16 __fastcall OhmygodReadWord(UINT32 a) +{ + switch (a) { + case 0x800000: { + return 0xffff - OhmygodInput[0]; + } + + case 0x800002: { + return 0xffff - OhmygodInput[1]; + } + + case 0xb00000: { + return 0xff00 | MSM6295ReadStatus(0); + } + + case 0xc00000: { + watch_tick= 3 * 60; + return 0xffff; + } + } + +#ifdef OHMYGODLOG + bprintf(PRINT_NORMAL, _T("68000 Read Word: %06X\n"), a); +#endif + SEK_DEF_READ_WORD(0, a); +} + +UINT8 __fastcall OhmygodReadByte(UINT32 a) +{ + switch (a) { + case 0xa00000: { + return OhmygodDip[0]; + } + + case 0xa00001: { + return 0xff; + } + + case 0xa00002: { + return OhmygodDip[1]; + } + + case 0xa00003: { + return 0xff; + } + } + +#ifdef OHMYGODLOG + bprintf(PRINT_NORMAL, _T("68000 Read Byte: %06X\n"), a); +#endif + + return 0; +} + +void __fastcall OhmygodWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x400000: { + OhmygodScrollx = d - 0x81ec; + return; + } + + case 0x400002: { + OhmygodScrolly = d - 0x81ef; + return; + } + + case 0x900000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0xb00000: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0xd00000: { + OhmygodSpriteBank = d & 0x8000; + return; + } + } + +#ifdef OHMYGODLOG + bprintf(PRINT_NORMAL, _T("68000 Write Word: %06X, %04X\n"), a, d); +#endif +} + +void __fastcall OhmygodWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x710000 && a <= 0x713fff) { + return; + } + + switch (a) { + case 0x900000: { + return; + } + + case 0x900001: { + if (SndBank != ((d >> AdpcmBankShift) & 0x0f)) { + SndBank = (d >> AdpcmBankShift) & 0x0f; + memcpy(MSM6295ROM + 0x20000,MSM6295ROM + 0x40000 + 0x20000 * SndBank,0x20000); + } + return; + } + + case 0xb00000: { + return; + } + + case 0xb00001: { + MSM6295Command(0, d); + return; + } + } + +#ifdef OHMYGODLOG + bprintf(PRINT_NORMAL, _T("68000 Write Byte: %06X, %02X\n"), a, d); +#endif +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + OhmygodRom = Next; Next += 0x080000; + MSM6295ROM = Next; Next += 0x240000; + + RamStart = Next; + + OhmygodRam = Next; Next += 0x018000; + OhmygodVideoRam = Next; Next += 0x004000; + OhmygodPaletteRam = Next; Next += 0x000800; + OhmygodSpriteRam = Next; Next += 0x004000; + + RamEnd = Next; + + OhmygodChars = Next; Next += (16384 * 8 * 8); + OhmygodSprites = Next; Next += (4096 * 16 * 16); + OhmygodPalette = (UINT32*)Next; Next += 0x000800 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 TileYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 SpriteXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 }; +static INT32 SpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + +INT32 OhmygodInit() +{ + INT32 nRet = 0, nLen; + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + // Load 68000 Program Rom + nRet = BurnLoadRom(OhmygodRom, 0x00, 1); if (nRet != 0) return 1; + + // malloc stuff + UINT8 *TempGfx=(UINT8*)BurnMalloc(0x80000); + + // Load and decode Character Rom + nRet = BurnLoadRom(TempGfx, 1, 1); if (nRet != 0) return 1; + GfxDecode(16384, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, TempGfx, OhmygodChars); + + // Load and decode Sprite Rom + memset(TempGfx, 0, 0x80000); + nRet = BurnLoadRom(TempGfx, 2, 1); if (nRet != 0) return 1; + GfxDecode(4096, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x400, TempGfx, OhmygodSprites); + BurnFree(TempGfx); + + // Load Sample Rom + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x40000, 3, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(OhmygodRom , 0x000000, 0x07ffff, SM_ROM ); + SekMapMemory(OhmygodRam + 0x000000, 0x300000, 0x303fff, SM_RAM ); + SekMapMemory(OhmygodVideoRam , 0x304000, 0x307fff, SM_RAM ); + SekMapMemory(OhmygodRam + 0x004000, 0x308000, 0x30ffff, SM_RAM ); + SekMapMemory(OhmygodPaletteRam , 0x600000, 0x607fff, SM_WRITE); + SekMapMemory(OhmygodSpriteRam , 0x700000, 0x703fff, SM_RAM ); + SekMapMemory(OhmygodRam + 0x00c000, 0x704000, 0x707fff, SM_RAM ); + SekMapMemory(OhmygodRam + 0x010000, 0x708000, 0x70ffff, SM_RAM ); + SekSetReadWordHandler(0, OhmygodReadWord); + SekSetWriteWordHandler(0, OhmygodWriteWord); + SekSetReadByteHandler(0, OhmygodReadByte); + SekSetWriteByteHandler(0, OhmygodWriteByte); + SekClose(); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 14000000/8/132, 100, 0); + + GenericTilesInit(); + + // Reset the driver + OhmygodDoReset(); + + return 0; +} + +INT32 OhmygodExit() +{ + MSM6295Exit(0); + SekExit(); + GenericTilesExit(); + + BurnFree(Mem); + + return 0; +} + +void OhmygodRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = (OhmygodVideoRam[2 * TileIndex + 3] << 8) | OhmygodVideoRam[2 * TileIndex + 2]; + Colour = (OhmygodVideoRam[2 * TileIndex + 1] << 8) | OhmygodVideoRam[2 * TileIndex + 0]; + Colour = (Colour & 0x0f00) >> 8; + x = 8 * mx; + y = 8 * my; + + x -= OhmygodScrollx + 97; + y -= OhmygodScrolly; + + if (x > 7 && x < 312 && y > 7 && y < 232) { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 4, 0, OhmygodChars); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, OhmygodChars); + } + + TileIndex +=2 ; + } + } +} + +void OhmygodRenderSpriteLayer() +{ + INT32 MemOffset = OhmygodSpriteBank ? 0x2000 : 0x0000; + + for (INT32 Offs = MemOffset; Offs < MemOffset + 0x2000; Offs += 8) { + INT32 sx, sy, Code, Colour, Flipx; + + Code = ((OhmygodSpriteRam[Offs + 7] << 8) + OhmygodSpriteRam[Offs + 6]) & 0x0fff; + Colour = ((OhmygodSpriteRam[Offs + 5] << 8) + OhmygodSpriteRam[Offs + 4]) & 0x000f; + sx = ((OhmygodSpriteRam[Offs + 1] << 8) + OhmygodSpriteRam[Offs + 0]) - 29; + sy = (OhmygodSpriteRam[Offs + 3] << 8) + OhmygodSpriteRam[Offs + 2]; + if (sy >= 32768) sy -= 65536; + + sx -= 96; + + Flipx = ((OhmygodSpriteRam[Offs + 7] << 8) + OhmygodSpriteRam[Offs + 6]) & 0x8000; + + if (sx > 15 && sx < 304 && sy > 15 && sy < 224) { + if (!Flipx) { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 512, OhmygodSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0, 512, OhmygodSprites); + } + } else { + if (!Flipx) { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 512, OhmygodSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 512, OhmygodSprites); + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 5) & 0x1f; + g = (nColour >> 10) & 0x1f; + b = (nColour >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + return BurnHighCol(r, g, b, 0); +} + +INT32 OhmygodCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)OhmygodPaletteRam, pd = OhmygodPalette; i < 0x800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +void OhmygodDraw() +{ + OhmygodCalcPalette(); + OhmygodRenderCharLayer(); + OhmygodRenderSpriteLayer(); + BurnTransferCopy(OhmygodPalette); +} + +INT32 OhmygodFrame() +{ + if (OhmygodReset) OhmygodDoReset(); + + OhmygodMakeInputs(); + + SekNewFrame(); + + SekOpen(0); + SekRun(12000000 / 60); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + do_watchtick(); + if (pBurnDraw) OhmygodDraw(); + if (pBurnSoundOut) MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + return 0; +} + +static INT32 OhmygodScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x02944; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + + MSM6295Scan(0, nAction); // Scan OKIM6295 + + // Scan critical driver variables + SCAN_VAR(OhmygodInput); + SCAN_VAR(OhmygodDip); + SCAN_VAR(AdpcmBankShift); + SCAN_VAR(SndBank); + SCAN_VAR(watch_tick); + SCAN_VAR(OhmygodSpriteBank); + SCAN_VAR(OhmygodScrollx); + SCAN_VAR(OhmygodScrolly); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x20000,MSM6295ROM + 0x40000 + 0x20000 * SndBank,0x20000); + } + + return 0; +} + +struct BurnDriver BurnDrvOhmygod = { + "ohmygod", NULL, NULL, NULL, "1993", + "Oh My God!\0", NULL, "Atlus", "Miscellaneous", + L"Oh my God! (Japan)\0Oh my god! \u30AA\u30FC\u30DE\u30A4\u30AC\u30A1\u30FC\uFF01\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, OhmygodRomInfo, OhmygodRomName, NULL, NULL, OhmygodInputInfo, OhmygodDIPInfo, + OhmygodInit, OhmygodExit, OhmygodFrame, NULL, OhmygodScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriverD BurnDrvNaname = { + "naname", NULL, NULL, NULL, "1994", + "Naname de Magic!\0", NULL, "Atlus", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, NanameRomInfo, NanameRomName, NULL, NULL, OhmygodInputInfo, NanameDIPInfo, + OhmygodInit, OhmygodExit, OhmygodFrame, NULL, OhmygodScan, + NULL, 0x800, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_pass.cpp b/src/burn/drivers/misc_post90s/d_pass.cpp new file mode 100644 index 00000000..e2b52baf --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_pass.cpp @@ -0,0 +1,512 @@ +// FB Alpha Pass driver module +// Based on MAME driver by David Haywood and Stephh + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgVRAM; +static UINT8 *DrvFgVRAM; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 *soundlatch; + +static struct BurnInputInfo PassInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 1, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 6, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 7, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 12, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 13, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 14, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 15, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Pass) + +static struct BurnDIPInfo PassDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xe7, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x18, 0x00, "Easy" }, + {0x12, 0x01, 0x18, 0x18, "Normal" }, + {0x12, 0x01, 0x18, 0x08, "Hard" }, + {0x12, 0x01, 0x18, 0x10, "Hardest" }, + + {0 , 0xfe, 0 , 7, "Coinage" }, + {0x12, 0x01, 0xe0, 0x80, "4 Coins 1 Credits " }, + {0x12, 0x01, 0xe0, 0x40, "3 Coins 1 Credits " }, + {0x12, 0x01, 0xe0, 0xc0, "2 Coins 1 Credits " }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Pass) + +void __fastcall pass_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x230000: + *soundlatch = data & 0xff; + return; + } +} + +void __fastcall pass_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ + +} + +UINT16 __fastcall pass_read_word(UINT32 address) +{ + switch (address) + { + case 0x230100: + return DrvInputs[1]; + + case 0x230200: + return DrvInputs[0]; + } + + return 0; +} + +UINT8 __fastcall pass_read_byte(UINT32 /*address*/) +{ + return 0; +} + +void __fastcall pass_sound_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x70: + BurnYM2203Write(0, 0, data); + return; + + case 0x71: + BurnYM2203Write(0, 1, data); + return; + + case 0x80: + MSM6295Command(0, data); + return; + + case 0xc0: + *soundlatch = 0; + return; + } +} + +UINT8 __fastcall pass_sound_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return *soundlatch; + + case 0x70: + return BurnYM2203Read(0, 0); + + case 0x71: + return BurnYM2203Read(0, 1); + } + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3579545.0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + MSM6295Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x080000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000400; + DrvBgVRAM = Next; Next += 0x001000; + DrvFgVRAM = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x0000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 5, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x000001, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040001, 9, 2)) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x083fff, SM_RAM); + SekMapMemory(DrvBgVRAM, 0x200000, 0x200fff, SM_RAM); + SekMapMemory(DrvFgVRAM, 0x210000, 0x213fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x220000, 0x2203ff, SM_RAM); + SekSetWriteWordHandler(0, pass_write_word); + SekSetWriteByteHandler(0, pass_write_byte); + SekSetReadWordHandler(0, pass_read_word); + SekSetReadByteHandler(0, pass_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80RAM); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(pass_sound_write_port); + ZetSetInHandler(pass_sound_read_port); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 3579545, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3579545); + + MSM6295Init(0, 792000 / 132, 100.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2203Exit(); + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_foreground_layer() +{ + UINT16 *vram = (UINT16*)DrvFgVRAM; + + for (INT32 offs = 0; offs < 128 * 64; offs++) + { + INT32 sx = ((offs & 0x7f) << 2) - 64; + INT32 sy = ((offs >> 7) << 2) - 16; + + if (sx >= nScreenWidth || sx < -3 || sy >= nScreenHeight || sy < -3) continue; + + INT32 attr = vram[offs]; + INT32 code = attr & 0x3fff; + INT32 flipy = (attr & 0x8000) >> 15; + INT32 flipx = (attr & 0x4000) >> 14; + + if (code < 0x10) continue; + + INT32 flip = (flipy * 0x0c) | (flipx * 3); + UINT8 *src = DrvGfxROM0 + (code << 4); + + for (INT32 y = 0; y < 4; y++, sy++) + { + for (INT32 x = 0; x < 4; x++) + { + INT32 pxl = src[((y << 2) | x) ^ flip]; + if (pxl == 0xff) continue; + + pTransDraw[(sy * nScreenWidth) + (sx + x)] = pxl | 0x100; + } + } + } +} + +static void draw_background_layer() +{ + UINT16 *vram = (UINT16*)DrvBgVRAM; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = ((offs & 0x3f) << 3) - 64; + INT32 sy = ((offs >> 6) << 3) - 16; + + if (sx >= nScreenWidth || sx < -7 || sy >= nScreenHeight || sy < -7) continue; + + INT32 attr = vram[offs]; + INT32 code = attr & 0x1fff; + INT32 flipy = attr & 0x8000; + INT32 flipx = attr & 0x4000; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM1); + } else { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM1); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM1); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x200; i++) { + INT32 d = pal[i]; + + r = ((d >> 10) & 0x1f); + g = ((d >> 5) & 0x1f); + b = ((d >> 0) & 0x1f); + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + draw_background_layer(); + draw_foreground_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + DrvInputs[0] = ~0; + DrvInputs[1] = DrvDips[0] | (DrvDips[1] << 8); + + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nTotalCycles[2] = { 7159090 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nSegment); + + nSegment = nTotalCycles[1] / nInterleave; + BurnTimerUpdate(i * nSegment); + } + + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + BurnTimerEndFrame(nTotalCycles[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029703; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Pass + +static struct BurnRomInfo passRomDesc[] = { + { "33", 0x20000, 0x0c5f18f6, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "34", 0x20000, 0x7b54573d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "23", 0x10000, 0xb9a0ccde, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "31", 0x20000, 0xc7315bbd, 3 | BRF_SND }, // 3 Samples + + { "35", 0x20000, 0x2ab33f07, 4 | BRF_GRA }, // 4 Foreground Tiles + { "36", 0x20000, 0x6677709d, 4 | BRF_GRA }, // 5 + + { "38", 0x20000, 0x7f11b81a, 5 | BRF_GRA }, // 6 Background Tiles + { "40", 0x20000, 0x80e0a71d, 5 | BRF_GRA }, // 7 + { "37", 0x20000, 0x296499e7, 5 | BRF_GRA }, // 8 + { "39", 0x20000, 0x35c0ad5c, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(pass) +STD_ROM_FN(pass) + +struct BurnDriver BurnDrvPass = { + "pass", NULL, NULL, NULL, "1992", + "Pass\0", NULL, "Oksan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, passRomInfo, passRomName, NULL, NULL, PassInputInfo, PassDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_pirates.cpp b/src/burn/drivers/misc_post90s/d_pirates.cpp new file mode 100644 index 00000000..66f39a88 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_pirates.cpp @@ -0,0 +1,691 @@ +// FB Alpha Pirates driver +// Based on MAME driver by David Haywood and Nicola Salmoria + +#include "tiles_generic.h" +#include "bitswap.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvMiscRAM; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 *DrvOkiBank; +static UINT16 *DrvScrollX; + +static INT32 is_genix = 0; + +static struct BurnInputInfo PiratesInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, &DrvDips, "dip" }, +}; + +STDINPUTINFO(Pirates) + +static struct BurnDIPInfo PiratesDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x0c, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x0c, 0x0c, "Off" }, + {0x13, 0x01, 0x0c, 0x00, "On" }, +}; + +STDDIPINFO(Pirates) + +inline static void genix_hack() +{ + if (is_genix) { + Drv68KRAM[0x9e98] = 0x04; + Drv68KRAM[0x9e99] = 0x00; + Drv68KRAM[0x9e9a] = 0x00; + Drv68KRAM[0x9e9b] = 0x00; + } +} + +static void palette_write(INT32 offset) +{ + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + UINT8 r,g,b; + + r = (data >> 10) & 0x1f; + g = (data >> 5) & 0x1f; + b = (data >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset >> 1] = BurnHighCol(r, g, b, 0); +} + +static void set_oki_bank(INT32 data) +{ + *DrvOkiBank = data; + memcpy (MSM6295ROM, DrvSndROM + (data << 12), 0x40000); + +bprintf (PRINT_NORMAL, _T("%2.2x\n"), data); +} + +void __fastcall pirates_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffc00) == 0x109c00) { + Drv68KRAM[(address & 0xffff) ^ 1] = data; + genix_hack(); + + return; + } + + if ((address & 0xffc000) == 0x800000) { + DrvPalRAM[address & 0x3fff] = data; + palette_write(address & 0x3ffe); + return; + } + +//bprintf (PRINT_NORMAL, _T("%5.5x, %2.2x\n"), address, data); + + switch (address) + { + case 0x600000: + case 0x600001: + if (*DrvOkiBank != (data & 0x40)) + set_oki_bank(data & 0x40); + return; + + case 0xa00000: + case 0xa00001: + MSM6295Command(0, data); + return; + } +} + +void __fastcall pirates_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffc00) == 0x109c00) { + *((UINT16 *)(Drv68KRAM + (address & 0xfffe))) = data; + genix_hack(); + + return; + } + + if ((address & 0xffc000) == 0x800000) { + *((UINT16 *)(DrvPalRAM + (address & 0x3ffe))) = data; + palette_write(address & 0x3ffe); + return; + } + +//bprintf (PRINT_NORMAL, _T("%5.5x, %4.4x\n"), address, data); + + switch (address) + { + case 0x600000: + if (*DrvOkiBank != (data & 0x40)) + set_oki_bank(data & 0x40); + return; + + case 0x700000: + *DrvScrollX = data & 0x1ff; + return; + + case 0xa00000: + MSM6295Command(0, data & 0xff); + return; + } +} + +UINT8 __fastcall pirates_read_byte(UINT32 address) +{ + genix_hack(); +//bprintf (PRINT_NORMAL, _T("%5.5x, b\n"), address); + + + switch (address) + { + case 0x300000: + case 0x300001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x400000: + case 0x400001: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0xa00001: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT16 __fastcall pirates_read_word(UINT32 address) +{ + genix_hack(); +//bprintf (PRINT_NORMAL, _T("%5.5x, w\n"), address); + + switch (address) + { + case 0x300000: + return DrvInputs[0]; + + case 0x400000: + return DrvInputs[1]; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x400000 * 3, 0x400000 * 2, 0x400000 * 1, 0x400000 * 0 }; + INT32 XOffs[16] = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }; + INT32 YOffs0[8] = { 8*0, 8*1, 8*2, 8*3, 8*4, 8*5, 8*6, 8*7 }; + INT32 YOffs1[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, + 8*16, 9*16,10*16,11*16,12*16,13*16,14*16,15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x200000); + + GfxDecode(0x10000, 4, 8, 8, Plane, XOffs, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x04000, 4, 16, 16, Plane, XOffs, YOffs1, 0x100, tmp, DrvGfxROM1); + + BurnFree(tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x400000; + + MSM6295ROM = Next; Next += 0x040000; + DrvSndROM = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x2000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + DrvMiscRAM = Next; Next += 0x005000; + + DrvScrollX = (UINT16*)Next; Next += 0x000002; + + DrvOkiBank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + + set_oki_bank(0); + + return 0; +} + +static void pirates_decrypt_68k() +{ + UINT16 *buf = (UINT16 *)BurnMalloc(0x100000); + UINT16 *rom = (UINT16 *)Drv68KROM; + + memcpy (buf, rom, 0x100000); + + for (INT32 i=0; i< 0x100000/2; i++) + { + INT32 adrl, adrr; + UINT8 vl, vr; + + adrl = BITSWAP24(i,23,22,21,20,19,18,4,8,3,14,2,15,17,0,9,13,10,5,16,7,12,6,1,11); + vl = BITSWAP08(buf[adrl], 4,2,7,1,6,5,0,3); + + adrr = BITSWAP24(i,23,22,21,20,19,18,4,10,1,11,12,5,9,17,14,0,13,6,15,8,3,16,7,2); + vr = BITSWAP08(buf[adrr]>>8, 1,4,7,0,3,5,6,2); + + rom[i] = (vr<<8) | vl; + } + + BurnFree (buf); +} + +static void pirates_decrypt_p() +{ + UINT8 *buf = (UINT8*)BurnMalloc(0x200000); + UINT8 *rom = DrvGfxROM0; + memcpy (buf, rom, 0x200000); + + for (INT32 i=0; i<0x200000/4; i++) + { + INT32 adr = BITSWAP24(i,23,22,21,20,19,18,10,2,5,9,7,13,16,14,11,4,1,6,12,17,3,0,15,8); + rom[adr+0*(0x200000/4)] = BITSWAP08(buf[i+0*(0x200000/4)], 2,3,4,0,7,5,1,6); + rom[adr+1*(0x200000/4)] = BITSWAP08(buf[i+1*(0x200000/4)], 4,2,7,1,6,5,0,3); + rom[adr+2*(0x200000/4)] = BITSWAP08(buf[i+2*(0x200000/4)], 1,4,7,0,3,5,6,2); + rom[adr+3*(0x200000/4)] = BITSWAP08(buf[i+3*(0x200000/4)], 2,3,4,0,7,5,1,6); + } + + BurnFree (buf); +} + +static void pirates_decrypt_s() +{ + UINT8 *buf = (UINT8*)BurnMalloc(0x200000); + UINT8 *rom = DrvGfxROM1; + memcpy (buf, rom, 0x200000); + + for (INT32 i=0; i<0x200000/4; i++) + { + INT32 adr = BITSWAP24(i,23,22,21,20,19,18,17,5,12,14,8,3,0,7,9,16,4,2,6,11,13,1,10,15); + rom[adr+0*(0x200000/4)] = BITSWAP08(buf[i+0*(0x200000/4)], 4,2,7,1,6,5,0,3); + rom[adr+1*(0x200000/4)] = BITSWAP08(buf[i+1*(0x200000/4)], 1,4,7,0,3,5,6,2); + rom[adr+2*(0x200000/4)] = BITSWAP08(buf[i+2*(0x200000/4)], 2,3,4,0,7,5,1,6); + rom[adr+3*(0x200000/4)] = BITSWAP08(buf[i+3*(0x200000/4)], 4,2,7,1,6,5,0,3); + } + + BurnFree (buf); +} + +static void pirates_decrypt_oki() +{ + UINT8 *buf = (UINT8*)BurnMalloc(0x80000); + UINT8 *rom = DrvSndROM; + memcpy (buf, rom, 0x80000); + + for (INT32 i=0; i<0x80000; i++) + { + INT32 adr = BITSWAP24(i,23,22,21,20,19,10,16,13,8,4,7,11,14,17,12,6,2,0,5,18,15,3,1,9); + rom[adr] = BITSWAP08(buf[i], 2,3,4,0,7,5,1,6); + } + + BurnFree (buf); +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM0 + i * 0x80000, 2 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + i * 0x80000, 6 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 10, 1)) return 1; + + pirates_decrypt_68k(); + pirates_decrypt_p(); + pirates_decrypt_s(); + pirates_decrypt_oki(); + + DrvGfxDecode(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "pirates")) { + *((UINT16*)(Drv68KROM + 0x62c0)) = 0x6006; // bypass protection + } else { + is_genix = 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM + 0x0000, 0x100000, 0x109bff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x9c00, 0x109c00, 0x109fff, (is_genix) ? SM_ROM : SM_RAM); + SekMapMemory(Drv68KRAM + 0xa000, 0x10a000, 0x10ffff, SM_RAM); +// SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x500000, 0x5007ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x800000, 0x803fff, SM_ROM); + SekMapMemory(DrvMiscRAM, 0x900000, 0x904fff, SM_RAM); + SekSetWriteByteHandler(0, pirates_write_byte); + SekSetWriteWordHandler(0, pirates_write_word); + SekSetReadByteHandler(0, pirates_read_byte); + SekSetReadWordHandler(0, pirates_read_word); + SekClose(); + + MSM6295Init(0, 1333333 / (132 + 39), 100.0, 0); // otherwise too fast! + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + + MSM6295Exit(0); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + is_genix = 0; + + return 0; +} + +static void draw_layer(INT32 offset, INT32 coloffs, INT32 transp) +{ + UINT16 *vram = (UINT16*)(DrvMiscRAM + offset); + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = (offs & 0x1f) << 3; + + sx -= *DrvScrollX; + if (sx < -15) sx += 0x200; + + if (sy < 16 || sy > 239 || sx > 287 || sx < -15) continue; + + INT32 code = vram[offs*2]; + INT32 color = vram[offs*2+1]; + + if (transp) { + if (!code && !color) continue; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color + coloffs, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy - 16, color + coloffs, 4, 0, DrvGfxROM0); + } + } +} + +static void draw_text_layer() +{ + UINT16 *vram = (UINT16*)(DrvMiscRAM + 0x0180); + + for (INT32 offs = 0; offs < 36 * 32; offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = (offs & 0x1f) << 3; + + if (sy < 16 || sy > 239 || sx >= 288) continue; + + INT32 code = vram[offs*2]; + INT32 color = vram[offs*2+1]; + + if (!code && !color) continue; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0, 0, DrvGfxROM0); + } +} + +static void draw_sprites() +{ + UINT16 *source = ((UINT16*)DrvSprRAM) + 4; + UINT16 *finish = source + 0x800/2-4; + + while (source < finish) + { + INT32 sx, sy, flipx, flipy, code, color; + + sx = source[1] - 32; + sy = source[-1]; + + if (sy & 0x8000) break; + + code = source[2] >> 2; + color = source[0] & 0xff; + flipx = source[2] & 2; + flipy = source[2] & 1; + + sy = (0xf2 - sy) - 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x1800, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x1800, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x1800, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x1800, DrvGfxROM1); + } + } + + source+=4; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x4000; i+=2) { + palette_write(i); + } + } + + if (nBurnLayer & 1) + draw_layer(0x2a80, 0x100, 0); + else + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + if (nBurnLayer & 2) draw_layer(0x1380, 0x080, 1); + + if (nBurnLayer & 8) draw_sprites(); + + if (nBurnLayer & 4) draw_text_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xffff; + DrvInputs[1] = 0x0003 | DrvDips; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 10; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + SekRun((16000000 / 60) / nInterleave); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + MSM6295Render(0, pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + MSM6295Scan(0, nAction); + } + + set_oki_bank(*DrvOkiBank); + + return 0; +} + + +// Pirates + +static struct BurnRomInfo piratesRomDesc[] = { + { "r_449b.bin", 0x80000, 0x224aeeda, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "l_5c1e.bin", 0x80000, 0x46740204, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "p4_4d48.bin", 0x80000, 0x89fda216, 2 | BRF_GRA }, // 2 Tiles + { "p2_5d74.bin", 0x80000, 0x40e069b4, 2 | BRF_GRA }, // 3 + { "p1_7b30.bin", 0x80000, 0x26d78518, 2 | BRF_GRA }, // 4 + { "p8_9f4f.bin", 0x80000, 0xf31696ea, 2 | BRF_GRA }, // 5 + + { "s1_6e89.bin", 0x80000, 0xc78a276f, 3 | BRF_GRA }, // 6 Sprites + { "s2_6df3.bin", 0x80000, 0x9f0bad96, 3 | BRF_GRA }, // 7 + { "s4_fdcc.bin", 0x80000, 0x8916ddb5, 3 | BRF_GRA }, // 8 + { "s8_4b7c.bin", 0x80000, 0x1c41bd2c, 3 | BRF_GRA }, // 9 + + { "s89_49d4.bin", 0x80000, 0x63a739ec, 4 | BRF_SND }, // 10 Oki Samples +}; + +STD_ROM_PICK(pirates) +STD_ROM_FN(pirates) + +struct BurnDriver BurnDrvPirates = { + "pirates", NULL, NULL, NULL, "1994", + "Pirates\0", NULL, "NIX", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, piratesRomInfo, piratesRomName, NULL, NULL, PiratesInputInfo, PiratesDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 288, 224, 4, 3 +}; + + +// Genix Family + +static struct BurnRomInfo genixRomDesc[] = { + { "1.15", 0x80000, 0xd26abfb0, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2.16", 0x80000, 0xa14a25b4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "7.34", 0x40000, 0x58da8aac, 2 | BRF_GRA }, // 2 Tiles + { "9.35", 0x40000, 0x96bad9a8, 2 | BRF_GRA }, // 3 + { "8.48", 0x40000, 0x0ddc58b6, 2 | BRF_GRA }, // 4 + { "10.49", 0x40000, 0x2be308c5, 2 | BRF_GRA }, // 5 + + { "6.69", 0x40000, 0xb8422af7, 3 | BRF_GRA }, // 6 Sprites + { "5.70", 0x40000, 0xe46125c5, 3 | BRF_GRA }, // 7 + { "4.71", 0x40000, 0x7a8ed21b, 3 | BRF_GRA }, // 8 + { "3.72", 0x40000, 0xf78bd6ca, 3 | BRF_GRA }, // 9 + + { "0.31", 0x80000, 0x80d087bc, 4 | BRF_SND }, // 10 Oki Samples +}; + +STD_ROM_PICK(genix) +STD_ROM_FN(genix) + +struct BurnDriver BurnDrvGenix = { + "genix", NULL, NULL, NULL, "1994", + "Genix Family\0", NULL, "NIX", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, genixRomInfo, genixRomName, NULL, NULL, PiratesInputInfo, PiratesDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_pktgaldx.cpp b/src/burn/drivers/misc_post90s/d_pktgaldx.cpp new file mode 100644 index 00000000..0d5ded26 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_pktgaldx.cpp @@ -0,0 +1,630 @@ +// FB Alpha Pocket Gal deluxe driver module +// Based on MAME driver by David Haywood and Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KCode; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvProtRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo PktgaldxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3"} , + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Pktgaldx) + +static struct BurnDIPInfo PktgaldxDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x00, "2" }, + {0x15, 0x01, 0x03, 0x01, "3" }, + {0x15, 0x01, 0x03, 0x03, "4" }, + {0x15, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x15, 0x01, 0x0c, 0x00, "60" }, + {0x15, 0x01, 0x0c, 0x04, "80" }, + {0x15, 0x01, 0x0c, 0x0c, "100" }, + {0x15, 0x01, 0x0c, 0x08, "120" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x15, 0x01, 0x20, 0x20, "Off" }, + {0x15, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Pktgaldx) + +void __fastcall pktgaldx_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff0) == 0x140000) { + MSM6295Command(0, data); + return; + } + + if ((address & 0xfffff0) == 0x160000) { + MSM6295Command(1, data); + return; + } + + deco16_write_control_word(0, address, 0x161800, data) + + if ((address & 0xfffff0) == 0x164800) { + memcpy (DrvSndROM0 + 0x100000, DrvSndROM1 + (data & 3) * 0x40000, 0x40000); + return; + } +} + +void __fastcall pktgaldx_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffff0) == 0x140000) { + MSM6295Command(0, data); + return; + } + + if ((address & 0xfffff0) == 0x160000) { + MSM6295Command(1, data); + return; + } + + deco16_write_control_word(0, address, 0x161800, data) + + if ((address & 0xfffff0) == 0x164800) { + memcpy (DrvSndROM0 + 0x100000, DrvSndROM1 + (data & 3) * 0x40000, 0x40000); + return; + } +} + +UINT16 __fastcall pktgaldx_read_word(UINT32 address) +{ + switch (address) + { + case 0x140006: + return MSM6295ReadStatus(0); + + case 0x150006: + return MSM6295ReadStatus(1); + + case 0x167db2: + return (DrvInputs[0] & 0xfff7) | (deco16_vblank & 0x08); + + case 0x167c4c: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x167842: + return DrvInputs[1]; + + case 0x167d10: + return *((UINT16*)(DrvProtRAM + 0)); + + case 0x167d1a: + return *((UINT16*)(DrvProtRAM + 2)); + } + + return 0; +} + +UINT8 __fastcall pktgaldx_read_byte(UINT32 address) +{ + switch (address) + { + case 0x140006: + case 0x140007: + return MSM6295ReadStatus(0); + + case 0x150006: + case 0x150007: + return MSM6295ReadStatus(1); + + case 0x167db2: + case 0x167db3: + return (DrvInputs[0] & 0xf7) | (deco16_vblank & 0x08); + + case 0x167c4c: + return DrvDips[1]; + + case 0x167c4d: + return DrvDips[0]; + + case 0x167842: + return DrvInputs[1] >> 8; + + case 0x167843: + return DrvInputs[1] >> 0; + + case 0x167d10: + case 0x167d11: + return DrvProtRAM[((address & 1) ^ 1) + 0]; + + case 0x167d1a: + case 0x167d1b: + return DrvProtRAM[((address & 1) ^ 1) + 2]; + + } + + return 0; +} + +static INT32 pktgaldx_bank_callback( const INT32 bank ) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + Drv68KCode = Next; Next += 0x080000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x140000; + DrvSndROM1 = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvSprRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x001000; + DrvProtRAM = Next; Next += 0x000800; + + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 3, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 5, 1)) return 1; + + deco102_decrypt_cpu(Drv68KROM, Drv68KCode, 0x80000, 0x42ba, 0x00, 0x00); + + deco56_decrypt_gfx(DrvGfxROM1, 0x100000); + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x100000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_sprite_decode(DrvGfxROM2, 0x100000); + } + + deco16Init(1, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x100000 * 2, DrvGfxROM1, 0x100000 * 2, NULL, 0); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(1, pktgaldx_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_READ); + SekMapMemory(Drv68KCode, 0x000000, 0x07ffff, SM_FETCH); + SekMapMemory(deco16_pf_ram[0], 0x100000, 0x100fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x102000, 0x102fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x110000, 0x1107ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x112000, 0x1127ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x130000, 0x130fff, SM_RAM); + SekMapMemory(DrvProtRAM, 0x167800, 0x167fff, SM_WRITE); + SekMapMemory(Drv68KRAM, 0x170000, 0x17ffff, SM_RAM); + SekSetWriteWordHandler(0, pktgaldx_write_word); + SekSetWriteByteHandler(0, pktgaldx_write_byte); + SekSetReadWordHandler(0, pktgaldx_read_word); + SekSetReadByteHandler(0, pktgaldx_read_byte); + SekClose(); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + MSM6295Exit(0); + MSM6295Exit(1); + + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_sprites() +{ + UINT16 *spriteram = (UINT16 *)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult; + + INT32 sprite = spriteram[offs+1]; + if (!sprite) continue; + + INT32 y = spriteram[offs]; + + if ((y & 0x1000) && (nCurrentFrame & 1)) continue; // flash + + INT32 x = spriteram[offs + 2]; + INT32 colour = (x >> 9) & 0x1f; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + y = 240 - y; + x = 304 - x; + + if (x > 320) continue; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (!*flipscreen) + { + y = 240 - y; + x = 304 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else mult = -16; + + while (multi >= 0) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x200, DrvGfxROM2); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x200, DrvGfxROM2); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 00; + } + + if (nBurnLayer & 1) deco16_draw_layer(1, pTransDraw, 0); + + if (nBurnLayer & 2) draw_sprites(); + + if (nBurnLayer & 4) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[1] = { 14000000 / 58 }; + INT32 nCyclesDone[1] = { 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + memset (pBurnSoundOut, 0, nBurnSoundLen * 2 * sizeof(INT16)); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + deco16Scan(); + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + } + + return 0; +} + + +// Pocket Gal Deluxe (Euro v3.00) + +static struct BurnRomInfo pktgaldxRomDesc[] = { + { "ke00-2.12a", 0x080000, 0xb04baf3a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "maz-02.2h", 0x100000, 0xc9d35a59, 2 | BRF_GRA }, // 1 Character and Background Tiles + + { "maz-00.1b", 0x080000, 0xfa3071f4, 3 | BRF_GRA }, // 2 Sprites + { "maz-01.3b", 0x080000, 0x4934fe21, 3 | BRF_GRA }, // 3 + + { "ke01.14f", 0x020000, 0x8a106263, 4 | BRF_SND }, // 4 OKI M6295 Sample 0 + + { "maz-03.13f", 0x100000, 0xa313c964, 5 | BRF_SND }, // 5 OKI M6295 Sample 1 +}; + +STD_ROM_PICK(pktgaldx) +STD_ROM_FN(pktgaldx) + +struct BurnDriver BurnDrvPktgaldx = { + "pktgaldx", NULL, NULL, NULL, "1992", + "Pocket Gal Deluxe (Euro v3.00)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, pktgaldxRomInfo, pktgaldxRomName, NULL, NULL, PktgaldxInputInfo, PktgaldxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Pocket Gal Deluxe (Japan v3.00) + +static struct BurnRomInfo pktgaldxjRomDesc[] = { + { "kg00-2.12a", 0x080000, 0x62dc4137, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "maz-02.2h", 0x100000, 0xc9d35a59, 2 | BRF_GRA }, // 1 Character and Background Tiles + + { "maz-00.1b", 0x080000, 0xfa3071f4, 3 | BRF_GRA }, // 2 Sprites + { "maz-01.3b", 0x080000, 0x4934fe21, 3 | BRF_GRA }, // 3 + + { "ke01.14f", 0x020000, 0x8a106263, 4 | BRF_SND }, // 4 OKI M6295 Sample 0 + + { "maz-03.13f", 0x100000, 0xa313c964, 5 | BRF_SND }, // 5 OKI M6295 Sample 1 +}; + +STD_ROM_PICK(pktgaldxj) +STD_ROM_FN(pktgaldxj) + +struct BurnDriver BurnDrvPktgaldxj = { + "pktgaldxj", "pktgaldx", NULL, NULL, "1993", + "Pocket Gal Deluxe (Japan v3.00)\0", NULL, "Nihon System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, pktgaldxjRomInfo, pktgaldxjRomName, NULL, NULL, PktgaldxInputInfo, PktgaldxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Pocket Gal Deluxe (Euro v3.00, bootleg) + +static struct BurnRomInfo pktgaldxbRomDesc[] = { + { "4.bin", 0x80000, 0x67ce30aa, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu + { "5.bin", 0x80000, 0x64cb4c33, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "11.bin", 0x80000, 0xa8c8f1fd, 2 | BRF_GRA }, // 2 Sprites + { "6.bin", 0x80000, 0x0e3335a1, 2 | BRF_GRA }, // 3 + { "10.bin", 0x80000, 0x9dd743a9, 2 | BRF_GRA }, // 4 + { "7.bin", 0x80000, 0x0ebf12b5, 2 | BRF_GRA }, // 5 + { "9.bin", 0x80000, 0x078f371c, 2 | BRF_GRA }, // 6 + { "8.bin", 0x80000, 0x40f5a032, 2 | BRF_GRA }, // 7 + + { "kg01.14f", 0x20000, 0x8a106263, 3 | BRF_SND }, // 8 OKI M6295 Sample 0 + + { "3.bin", 0x80000, 0x4638747b, 4 | BRF_SND }, // 9 OKI M6295 Sample 1 + { "2.bin", 0x80000, 0xf841d995, 4 | BRF_SND }, // 10 +}; + +STD_ROM_PICK(pktgaldxb) +STD_ROM_FN(pktgaldxb) + +static INT32 pkgaldxbInit() +{ + return 1; +} + +struct BurnDriverD BurnDrvPktgaldxb = { + "pktgaldxb", "pktgaldx", NULL, NULL, "1992", + "Pocket Gal Deluxe (Euro v3.00, bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, pktgaldxbRomInfo, pktgaldxbRomName, NULL, NULL, PktgaldxInputInfo, PktgaldxDIPInfo, + pkgaldxbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_powerins.cpp b/src/burn/drivers/misc_post90s/d_powerins.cpp new file mode 100644 index 00000000..1eff1625 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_powerins.cpp @@ -0,0 +1,1196 @@ +/*************************************************************** + Power Instinct + (C) 1993 Atlus + driver by Luca Elia (l.elia@tin.it) + *************************************************************** + port to Finalburn Alpha by OopsWare. 2007 + ***************************************************************/ + +#include "tiles_generic.h" +#include "msm6295.h" +#include "burn_ym2203.h" + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *Rom68K; +static UINT8 *RomZ80; +static UINT8 *RomBg; +static UINT8 *RomFg; +static UINT8 *RomSpr; + +static UINT8 *RamZ80; +static UINT16 *RamPal; +static UINT16 *RamBg; +static UINT16 *RamFg; +static UINT16 *RamSpr; +static UINT16 *RamVReg; + +static UINT32 *RamCurPal; + +static UINT8 DrvButton[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvJoy1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvJoy2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static UINT8 DrvInput[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +static UINT8 bRecalcPalette = 0; +static UINT8 DrvReset = 0; + +static UINT32 tile_bank; +static INT32 m6295size; +static UINT16 soundlatch = 0; +static INT32 oki_bank = -1; + +#define GAME_POWERINS 1 +#define GAME_POWERINA 2 +#define GAME_POWERINB 3 + +static INT32 game_drv = 0; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +inline static void CalcCol(INT32 idx) +{ + /* RRRR GGGG BBBB RGBx */ + UINT16 wordValue = RamPal[idx]; + INT32 r = ((wordValue >> 8) & 0xF0 ) | ((wordValue << 0) & 0x08) | ((wordValue >> 13) & 0x07 ); + INT32 g = ((wordValue >> 4) & 0xF0 ) | ((wordValue << 1) & 0x08) | ((wordValue >> 9) & 0x07 ); + INT32 b = ((wordValue >> 0) & 0xF0 ) | ((wordValue << 2) & 0x08) | ((wordValue >> 5) & 0x07 ); + RamCurPal[idx] = BurnHighCol(r, g, b, 0); +} + +static struct BurnInputInfo powerinsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 3, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 4, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 5, "diag"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 6, "dip"}, +}; + +STDINPUTINFO(powerins) + +static struct BurnDIPInfo powerinsDIPList[] = { + + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Free play"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 8, "Coin 1"}, + {0x17, 0x01, 0x70, 0x30, "4 coins 1 credit"}, + {0x17, 0x01, 0x70, 0x50, "3 coins 1 credit"}, + {0x17, 0x01, 0x70, 0x10, "2 coins 1 credit"}, + {0x17, 0x01, 0x70, 0x00, "1 coin 1 credit"}, + {0x17, 0x01, 0x70, 0x40, "1 coin 2 credits"}, + {0x17, 0x01, 0x70, 0x20, "1 coin 3 credits"}, + {0x17, 0x01, 0x70, 0x60, "1 coin 4 credits"}, + {0x17, 0x01, 0x70, 0x70, "2 coins to start, 1 to continue"}, + {0, 0xFE, 0, 8, "Coin 2"}, + {0x17, 0x01, 0x0E, 0x06, "4 coins 1 credit"}, + {0x17, 0x01, 0x0E, 0x0A, "3 coins 1 credit"}, + {0x17, 0x01, 0x0E, 0x02, "2 coins 1 credit"}, + {0x17, 0x01, 0x0E, 0x00, "1 coin 1 credit"}, + {0x17, 0x01, 0x0E, 0x08, "1 coin 2 credits"}, + {0x17, 0x01, 0x0E, 0x04, "1 coin 3 credits"}, + {0x17, 0x01, 0x0E, 0x0C, "1 coin 4 credits"}, + {0x17, 0x01, 0x0E, 0x0E, "2 coins to start, 1 to continue"}, + {0, 0xFE, 0, 2, "Flip screen"}, + {0x17, 0x01, 0x80, 0x00, "Off"}, + {0x17, 0x01, 0x80, 0x80, "On"}, + +}; + +static struct BurnDIPInfo powerinaDIPList[] = { + + // Defaults + {0x18, 0xFF, 0xFF, 0x04, NULL}, + + // DIP 2 + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x18, 0x01, 0x01, 0x00, "1 chute"}, + {0x18, 0x01, 0x01, 0x01, "2 chutes"}, + {0, 0xFE, 0, 2, "Join In mode"}, + {0x18, 0x01, 0x02, 0x00, "Off"}, + {0x18, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x18, 0x01, 0x04, 0x00, "Off"}, + {0x18, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 2, "Allow continue"}, + {0x18, 0x01, 0x08, 0x08, "Off"}, + {0x18, 0x01, 0x08, 0x00, "On"}, + {0, 0xFE, 0, 2, "Blood color"}, + {0x18, 0x01, 0x10, 0x00, "Red"}, + {0x18, 0x01, 0x10, 0x10, "Blue"}, + {0, 0xFE, 0, 2, "Game time"}, + {0x18, 0x01, 0x20, 0x00, "Normal"}, + {0x18, 0x01, 0x20, 0x20, "Short"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x18, 0x01, 0xC0, 0x80, "Easy"}, + {0x18, 0x01, 0xC0, 0x00, "Normal"}, + {0x18, 0x01, 0xC0, 0x40, "Hard"}, + {0x18, 0x01, 0xC0, 0xC0, "Hardest"}, + +}; + +static struct BurnDIPInfo powerinjDIPList[] = { + + // Defaults + {0x18, 0xFF, 0xFF, 0x04, NULL}, + + // DIP 2 +// {0, 0xFE, 0, 2, "Unknown"}, +// {0x18, 0x01, 0x01, 0x00, "Off"}, +// {0x18, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Join In mode"}, + {0x18, 0x01, 0x02, 0x00, "Off"}, + {0x18, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x18, 0x01, 0x04, 0x00, "Off"}, + {0x18, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 2, "Allow continue"}, + {0x18, 0x01, 0x08, 0x08, "Off"}, + {0x18, 0x01, 0x08, 0x00, "On"}, + {0, 0xFE, 0, 2, "Blood color"}, + {0x18, 0x01, 0x10, 0x00, "Red"}, + {0x18, 0x01, 0x10, 0x10, "Blue"}, + {0, 0xFE, 0, 2, "Game time"}, + {0x18, 0x01, 0x20, 0x00, "Normal"}, + {0x18, 0x01, 0x20, 0x20, "Short"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x18, 0x01, 0xC0, 0x80, "Easy"}, + {0x18, 0x01, 0xC0, 0x00, "Normal"}, + {0x18, 0x01, 0xC0, 0x40, "Hard"}, + {0x18, 0x01, 0xC0, 0xC0, "Hardest"}, + +}; + +STDDIPINFOEXT(powerins, powerins, powerina) +STDDIPINFOEXT(powerinj, powerins, powerinj) + +// Rom information + +static struct BurnRomInfo powerinsRomDesc[] = { + { "93095-3a.u108", 0x080000, 0x9825ea3d, BRF_ESS | BRF_PRG }, // 68000 code + { "93095-4.u109", 0x080000, 0xd3d7a782, BRF_ESS | BRF_PRG }, + + { "93095-2.u90", 0x020000, 0x4b123cc6, BRF_ESS | BRF_PRG }, // Z80 code + + { "93095-5.u16", 0x100000, 0xb1371808, BRF_GRA }, // layer 0 + { "93095-6.u17", 0x100000, 0x29c85d80, BRF_GRA }, + { "93095-7.u18", 0x080000, 0x2dd76149, BRF_GRA }, + + { "93095-1.u15", 0x020000, 0x6a579ee0, BRF_GRA }, // layer 1 + + { "93095-12.u116", 0x100000, 0x35f3c2a3, BRF_GRA }, + { "93095-13.u117", 0x100000, 0x1ebd45da, BRF_GRA }, + { "93095-14.u118", 0x100000, 0x760d871b, BRF_GRA }, + { "93095-15.u119", 0x100000, 0xd011be88, BRF_GRA }, + { "93095-16.u120", 0x100000, 0xa9c16c9c, BRF_GRA }, + { "93095-17.u121", 0x100000, 0x51b57288, BRF_GRA }, + { "93095-18.u122", 0x100000, 0xb135e3f2, BRF_GRA }, + { "93095-19.u123", 0x100000, 0x67695537, BRF_GRA }, + + { "93095-10.u48", 0x100000, 0x329ac6c5, BRF_SND }, // sound 1 + { "93095-11.u49", 0x100000, 0x75d6097c, BRF_SND }, + + { "93095-8.u46", 0x100000, 0xf019bedb, BRF_SND }, // sound 2 + { "93095-9.u47", 0x100000, 0xadc83765, BRF_SND }, + + { "22.u81", 0x000020, 0x67d5ec4b, BRF_OPT }, // unknown + { "21.u71", 0x000100, 0x182cd81f, BRF_OPT }, + { "20.u54", 0x000100, 0x38bd0e2f, BRF_OPT }, + +}; + +STD_ROM_PICK(powerins) +STD_ROM_FN(powerins) + +static struct BurnRomInfo powerinjRomDesc[] = { + { "93095-3j.u108", 0x080000, 0x3050a3fb, BRF_ESS | BRF_PRG }, // 68000 code + { "93095-4.u109", 0x080000, 0xd3d7a782, BRF_ESS | BRF_PRG }, + + { "93095-2.u90", 0x020000, 0x4b123cc6, BRF_ESS | BRF_PRG }, // Z80 code + + { "93095-5.u16", 0x100000, 0xb1371808, BRF_GRA }, // layer 0 + { "93095-6.u17", 0x100000, 0x29c85d80, BRF_GRA }, + { "93095-7.u18", 0x080000, 0x2dd76149, BRF_GRA }, + + { "93095-1.u15", 0x020000, 0x6a579ee0, BRF_GRA }, // layer 1 + + { "93095-12.u116", 0x100000, 0x35f3c2a3, BRF_GRA }, + { "93095-13.u117", 0x100000, 0x1ebd45da, BRF_GRA }, + { "93095-14.u118", 0x100000, 0x760d871b, BRF_GRA }, + { "93095-15.u119", 0x100000, 0xd011be88, BRF_GRA }, + { "93095-16.u120", 0x100000, 0xa9c16c9c, BRF_GRA }, + { "93095-17.u121", 0x100000, 0x51b57288, BRF_GRA }, + { "93095-18.u122", 0x100000, 0xb135e3f2, BRF_GRA }, + { "93095-19.u123", 0x100000, 0x67695537, BRF_GRA }, + + { "93095-10.u48", 0x100000, 0x329ac6c5, BRF_SND }, // sound 1 + { "93095-11.u49", 0x100000, 0x75d6097c, BRF_SND }, + + { "93095-8.u46", 0x100000, 0xf019bedb, BRF_SND }, // sound 2 + { "93095-9.u47", 0x100000, 0xadc83765, BRF_SND }, + + { "22.u81", 0x000020, 0x67d5ec4b, BRF_OPT }, // unknown + { "21.u71", 0x000100, 0x182cd81f, BRF_OPT }, + { "20.u54", 0x000100, 0x38bd0e2f, BRF_OPT }, + +}; + +STD_ROM_PICK(powerinj) +STD_ROM_FN(powerinj) + +static struct BurnRomInfo powerinaRomDesc[] = { + { "rom1", 0x080000, 0xb86c84d6, BRF_ESS | BRF_PRG }, // 68000 code + { "rom2", 0x080000, 0xd3d7a782, BRF_ESS | BRF_PRG }, + + { "rom6", 0x200000, 0xb6c10f80, BRF_GRA }, // layer 0 + { "rom4", 0x080000, 0x2dd76149, BRF_GRA }, + + { "rom3", 0x020000, 0x6a579ee0, BRF_GRA }, // layer 1 + + { "rom10", 0x200000, 0xefad50e8, BRF_GRA }, // sprites + { "rom9", 0x200000, 0x08229592, BRF_GRA }, + { "rom8", 0x200000, 0xb02fdd6d, BRF_GRA }, + { "rom7", 0x200000, 0x92ab9996, BRF_GRA }, + + { "rom5", 0x080000, 0x88579c8f, BRF_SND }, // sound 1 +}; + +STD_ROM_PICK(powerina) +STD_ROM_FN(powerina) + +static struct BurnRomInfo powerinbRomDesc[] = { + { "2q.bin", 0x080000, 0x11bf3f2a, BRF_ESS | BRF_PRG }, // 68000 code + { "2r.bin", 0x080000, 0xd8d621be, BRF_ESS | BRF_PRG }, + + { "1f.bin", 0x020000, 0x4b123cc6, BRF_ESS | BRF_PRG }, // Z80 code + + { "13k.bin", 0x080000, 0x1975b4b8, BRF_GRA }, // layer 0 + { "13l.bin", 0x080000, 0x376e4919, BRF_GRA }, + { "13o.bin", 0x080000, 0x0d5ff532, BRF_GRA }, + { "13q.bin", 0x080000, 0x99b25791, BRF_GRA }, + { "13r.bin", 0x080000, 0x2dd76149, BRF_GRA }, + + { "6n.bin", 0x020000, 0x6a579ee0, BRF_GRA }, // layer 1 + + { "14g.bin", 0x080000, 0x8b9b89c9, BRF_GRA }, + { "11g.bin", 0x080000, 0x4d127bdf, BRF_GRA }, + { "13g.bin", 0x080000, 0x298eb50e, BRF_GRA }, + { "11i.bin", 0x080000, 0x57e6d283, BRF_GRA }, + { "12g.bin", 0x080000, 0xfb184167, BRF_GRA }, + { "11j.bin", 0x080000, 0x1b752a4d, BRF_GRA }, + { "14m.bin", 0x080000, 0x2f26ba7b, BRF_GRA }, + { "11k.bin", 0x080000, 0x0263d89b, BRF_GRA }, + { "14n.bin", 0x080000, 0xc4633294, BRF_GRA }, + { "11l.bin", 0x080000, 0x5e4b5655, BRF_GRA }, + { "14p.bin", 0x080000, 0x4d4b0e4e, BRF_GRA }, + { "11o.bin", 0x080000, 0x7e9f2d2b, BRF_GRA }, + { "13p.bin", 0x080000, 0x0e7671f2, BRF_GRA }, + { "11p.bin", 0x080000, 0xee59b1ec, BRF_GRA }, + { "12p.bin", 0x080000, 0x9ab1998c, BRF_GRA }, + { "11q.bin", 0x080000, 0x1ab0c88a, BRF_GRA }, + + { "4a.bin", 0x080000, 0x8cd6824e, BRF_SND }, // sound 1 + { "4b.bin", 0x080000, 0xe31ae04d, BRF_SND }, + { "4c.bin", 0x080000, 0xc4c9f599, BRF_SND }, + { "4d.bin", 0x080000, 0xf0a9f0e1, BRF_SND }, + + { "5a.bin", 0x080000, 0x62557502, BRF_SND }, // sound 2 + { "5b.bin", 0x080000, 0xdbc86bd7, BRF_SND }, + { "5c.bin", 0x080000, 0x5839a2bd, BRF_SND }, + { "5d.bin", 0x080000, 0x446f9dc3, BRF_SND }, + + { "82s123.bin", 0x000020, 0x67d5ec4b, BRF_OPT }, // unknown + { "82s147.bin", 0x000200, 0xd7818542, BRF_OPT }, + +}; + +STD_ROM_PICK(powerinb) +STD_ROM_FN(powerinb) + +static void sndSetBank(UINT8 offset, UINT8 data) +{ + INT32 chip = (offset & 4) >> 2; + INT32 bank = offset & 3; + + MSM6295SampleInfo[chip][bank] = MSM6295ROM + 0x200000 * chip + 0x010000 * data + (bank << 8); + MSM6295SampleData[chip][bank] = MSM6295ROM + 0x200000 * chip + 0x010000 * data; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom68K = Next; Next += 0x0100000; // 68000 ROM + RomZ80 = Next; Next += 0x0020000; // Z80 ROM + RomBg = Next; Next += 0x0500000; + RomFg = Next; Next += 0x0100000; + RomSpr = Next; Next += 0x1000000; + MSM6295ROM = Next; Next += m6295size; + + RamStart = Next; + + RamZ80 = Next; Next += 0x002000; + + RamPal = (UINT16 *) Next; Next += 0x001000; + RamBg = (UINT16 *) Next; Next += 0x004000; + RamFg = (UINT16 *) Next; Next += 0x001000; + RamSpr = (UINT16 *) Next; Next += 0x010000; + RamVReg = (UINT16 *) Next; Next += 0x000008; + + RamEnd = Next; + + RamCurPal = (UINT32 *) Next; Next += 0x000800 * sizeof(UINT32); + + MemEnd = Next; + return 0; +} + +UINT8 __fastcall powerinsReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x10003f: + return MSM6295ReadStatus(0); + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall powerinsReadWord(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0x100000: + return ~DrvInput[0]; + + case 0x100002: + return ~(DrvInput[2] + (DrvInput[3]<<8)); + + case 0x100008: + return ~DrvInput[4]; + + case 0x10000A: + return ~DrvInput[6]; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall powerinsWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) + { + case 0x100031: + // powerins_okibank + if (oki_bank != (byteValue & 7)) { + oki_bank = byteValue & 7; + memcpy(&MSM6295ROM[0x30000],&MSM6295ROM[0x40000 + 0x10000*oki_bank],0x10000); + } + break; + + case 0x10003e: + // powerina only! + break; + + case 0x10003f: + // powerina only! + MSM6295Command(0, byteValue); + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall powerinsWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) + { + case 0x100014: + // powerins_flipscreen_w + break; + + case 0x100018: + // powerins_tilebank_w + tile_bank = wordValue * 0x800; + break; + + case 0x10001e: + //powerins_soundlatch_w + soundlatch = wordValue & 0xff; + break; + + case 0x10003e: + // powerina only! + MSM6295Command(0, wordValue & 0xff); + break; + + case 0x130000: RamVReg[0] = wordValue; break; + case 0x130002: RamVReg[1] = wordValue; break; + case 0x130004: RamVReg[2] = wordValue; break; + case 0x130006: RamVReg[3] = wordValue; break; + + case 0x100016: // NOP + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +void __fastcall powerinsWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress -= 0x120000; + sekAddress >>= 1; + RamPal[sekAddress] = wordValue; + CalcCol( sekAddress ); +} + +UINT8 __fastcall powerinsZ80Read(UINT16 a) +{ + switch (a) + { + case 0xE000: + return soundlatch; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to read value of location %04x\n"), a); + } + + return 0; +} + +#if 1 && defined FBA_DEBUG +void __fastcall powerinsZ80Write(UINT16 a,UINT8 v) +{ + switch (a) { + case 0xE000: + case 0xE001: + break; + + default: + bprintf(PRINT_NORMAL, _T("Z80 Attempt to write value %x to location %x\n"), v, a); + } +} +#endif + +UINT8 __fastcall powerinsZ80In(UINT16 p) +{ + switch (p & 0xFF) + { + case 0x00: + if ( game_drv == GAME_POWERINS ) + return BurnYM2203Read(0, 0); + else + return 0x01; + + case 0x01: + if ( game_drv == GAME_POWERINS ) + return BurnYM2203Read(0, 1); + else + return 0; + + case 0x80: + return MSM6295ReadStatus(0); + + case 0x88: + return MSM6295ReadStatus(1); + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to read port %04x\n"), p); + } + + return 0; +} + +void __fastcall powerinsZ80Out(UINT16 p, UINT8 v) +{ + switch (p & 0x0FF) { + case 0x00: + if ( game_drv == GAME_POWERINS ) + BurnYM2203Write(0, 0, v); + break; + + case 0x01: + if ( game_drv == GAME_POWERINS ) + BurnYM2203Write(0, 1, v); + break; + + case 0x80: + MSM6295Command(0, v); + break; + + case 0x88: + MSM6295Command(1, v); + break; + + case 0x90: sndSetBank(0, v); break; + case 0x91: sndSetBank(1, v); break; + case 0x92: sndSetBank(2, v); break; + case 0x93: sndSetBank(3, v); break; + case 0x94: sndSetBank(4, v); break; + case 0x95: sndSetBank(5, v); break; + case 0x96: sndSetBank(6, v); break; + case 0x97: sndSetBank(7, v); break; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to write %02x to port %04x\n"), v, p); + } +} + +static void powerinsIRQHandler(INT32, INT32 nStatus) +{ +// bprintf(PRINT_NORMAL, _T("powerinsIRQHandler %i\n"), nStatus); + + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 powerinsSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +static double powerinsGetTime() +{ + return (double)ZetTotalCycles() / 6000000; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + MSM6295Reset(0); + + if (game_drv != GAME_POWERINA) { + ZetOpen(0); + ZetReset(); + ZetClose(); + + if (game_drv == GAME_POWERINS) BurnYM2203Reset(); + + MSM6295Reset(1); + + } + + return 0; +} + +static void LoadDecodeBgRom(UINT8 *tmp, UINT8 * dest, INT32 id, INT32 size) +{ + BurnLoadRom(tmp, id, 1); + + for (INT32 z=0;z<(size/128);z++) { + for (INT32 y=0;y<16;y++) { + dest[ 0] = tmp[ 0] >> 4; + dest[ 1] = tmp[ 0] & 15; + dest[ 2] = tmp[ 1] >> 4; + dest[ 3] = tmp[ 1] & 15; + + dest[ 4] = tmp[ 2] >> 4; + dest[ 5] = tmp[ 2] & 15; + dest[ 6] = tmp[ 3] >> 4; + dest[ 7] = tmp[ 3] & 15; + + dest[ 8] = tmp[64] >> 4; + dest[ 9] = tmp[64] & 15; + dest[10] = tmp[65] >> 4; + dest[11] = tmp[65] & 15; + + dest[12] = tmp[66] >> 4; + dest[13] = tmp[66] & 15; + dest[14] = tmp[67] >> 4; + dest[15] = tmp[67] & 15; + + dest += 16; + tmp += 4; + } + tmp += 64; + } +} + +static void LoadDecodeSprRom(UINT8 *tmp, UINT8 * dest, INT32 id, INT32 size) +{ + if ( game_drv == GAME_POWERINB ) { + BurnLoadRom(tmp + 0, 9 + id*2, 2); + BurnLoadRom(tmp + 1, 10 + id*2, 2); + } else + BurnLoadRom(tmp, id, 1); + + for (INT32 z=0;z<(size/128);z++) { + for (INT32 y=0;y<16;y++) { + dest[ 0] = tmp[ 1] >> 4; + dest[ 1] = tmp[ 1] & 15; + dest[ 2] = tmp[ 0] >> 4; + dest[ 3] = tmp[ 0] & 15; + + dest[ 4] = tmp[ 3] >> 4; + dest[ 5] = tmp[ 3] & 15; + dest[ 6] = tmp[ 2] >> 4; + dest[ 7] = tmp[ 2] & 15; + + dest[ 8] = tmp[65] >> 4; + dest[ 9] = tmp[65] & 15; + dest[10] = tmp[64] >> 4; + dest[11] = tmp[64] & 15; + + dest[12] = tmp[67] >> 4; + dest[13] = tmp[67] & 15; + dest[14] = tmp[66] >> 4; + dest[15] = tmp[66] & 15; + + dest += 16; + tmp += 4; + } + tmp += 64; + } +} + +static INT32 powerinsInit() +{ + INT32 nRet; + UINT8 * tmp; + + m6295size = 0x80000 * 4 * 2; + + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "powerins") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "powerinsj") == 0) { + game_drv = GAME_POWERINS; + } else + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "powerinsa") == 0 ) { + game_drv = GAME_POWERINA; + m6295size = 0x90000; + } else + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "powerinsb") == 0 ) { + game_drv = GAME_POWERINB; + } else + return 1; + + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(); + + // load roms + + tmp = (UINT8 *)BurnMalloc(0x200000); + if (tmp==0) return 1; + + if ( game_drv == GAME_POWERINS ) { + nRet = BurnLoadRom(Rom68K + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x080000, 1, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomZ80 + 0x000000, 2, 1); if (nRet != 0) return 1; + + // load background tile roms + LoadDecodeBgRom(tmp, RomBg+0x000000, 3, 0x100000); + LoadDecodeBgRom(tmp, RomBg+0x200000, 4, 0x100000); + LoadDecodeBgRom(tmp, RomBg+0x400000, 5, 0x080000); + + BurnLoadRom(RomFg + 0x000000, 6, 1); + + // load sprite roms + for (INT32 i=0;i<8;i++) + LoadDecodeSprRom(tmp, RomSpr+0x200000*i, i+7, 0x100000); + + BurnLoadRom(MSM6295ROM + 0x000000, 15, 1); + BurnLoadRom(MSM6295ROM + 0x100000, 16, 1); + BurnLoadRom(MSM6295ROM + 0x200000, 17, 1); + BurnLoadRom(MSM6295ROM + 0x300000, 18, 1); + + + } else + if ( game_drv == GAME_POWERINA ) { + nRet = BurnLoadRom(Rom68K + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x080000, 1, 1); if (nRet != 0) return 1; + + // load background tile roms + LoadDecodeBgRom(tmp, RomBg+0x000000, 2, 0x200000); + LoadDecodeBgRom(tmp, RomBg+0x400000, 3, 0x080000); + + // load foreground tile roms + BurnLoadRom(RomFg + 0x000000, 4, 1); + + // load sprite roms + for (INT32 i=0;i<4;i++) + LoadDecodeSprRom(tmp, RomSpr+0x400000*i, i+5, 0x200000); + + BurnLoadRom(MSM6295ROM + 0x10000, 9, 1); + memcpy(MSM6295ROM, MSM6295ROM + 0x10000, 0x30000); + + } else + if ( game_drv == GAME_POWERINB ) { + + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomZ80 + 0x000000, 2, 1); if (nRet != 0) return 1; + + // load background tile roms + for (INT32 i=0;i<5;i++) + LoadDecodeBgRom(tmp, RomBg+0x100000*i, i+3, 0x80000); + + // load foreground tile roms + BurnLoadRom(RomFg + 0x000000, 8, 1); + + // load sprite roms + for (INT32 i=0;i<8;i++) + LoadDecodeSprRom(tmp, RomSpr+0x200000*i, i, 0x100000); + + BurnLoadRom(MSM6295ROM + 0x000000, 25, 1); + BurnLoadRom(MSM6295ROM + 0x080000, 26, 1); + BurnLoadRom(MSM6295ROM + 0x100000, 27, 1); + BurnLoadRom(MSM6295ROM + 0x180000, 28, 1); + BurnLoadRom(MSM6295ROM + 0x200000, 29, 1); + BurnLoadRom(MSM6295ROM + 0x280000, 30, 1); + BurnLoadRom(MSM6295ROM + 0x300000, 31, 1); + BurnLoadRom(MSM6295ROM + 0x380000, 32, 1); + + } + + BurnFree(tmp); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory((UINT8 *)RamPal, + 0x120000, 0x120FFF, SM_ROM); // palette + SekMapMemory((UINT8 *)RamBg, + 0x140000, 0x143fff, SM_RAM); // b ground + SekMapMemory((UINT8 *)RamFg, + 0x170000, 0x170fff, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamFg, + 0x171000, 0x171fff, SM_RAM); // f ground Mirror + SekMapMemory((UINT8 *)RamSpr, + 0x180000, 0x18ffff, SM_RAM); // sprites + + SekMapHandler(1, 0x120000, 0x120FFF, SM_WRITE); + + + SekSetReadWordHandler(0, powerinsReadWord); + SekSetReadByteHandler(0, powerinsReadByte); + SekSetWriteWordHandler(0, powerinsWriteWord); + SekSetWriteByteHandler(0, powerinsWriteByte); + + //SekSetWriteByteHandler(1, powerinsWriteBytePalette); + SekSetWriteWordHandler(1, powerinsWriteWordPalette); + + SekClose(); + } + + if ( game_drv != GAME_POWERINA ) { + + ZetInit(1); + ZetOpen(0); + + ZetSetReadHandler(powerinsZ80Read); +#if 1 && defined FBA_DEBUG + ZetSetWriteHandler(powerinsZ80Write); +#endif + ZetSetInHandler(powerinsZ80In); + ZetSetOutHandler(powerinsZ80Out); + + // ROM bank 1 + ZetMapArea(0x0000, 0xBFFF, 0, RomZ80); + ZetMapArea(0x0000, 0xBFFF, 2, RomZ80); + // RAM + ZetMapArea(0xC000, 0xDFFF, 0, RamZ80); + ZetMapArea(0xC000, 0xDFFF, 1, RamZ80); + ZetMapArea(0xC000, 0xDFFF, 2, RamZ80); + + ZetMemEnd(); + ZetClose(); + } + + if ( game_drv == GAME_POWERINA ) { + MSM6295Init(0, 990000 / 165, 80, 0); + } + + if (game_drv == GAME_POWERINS ) { + BurnYM2203Init(1, 12000000 / 8, &powerinsIRQHandler, powerinsSynchroniseStream, powerinsGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(6000000); + BurnSetRefreshRate(56.0); + + MSM6295Init(0, 4000000 / 165, 40, 1); + MSM6295Init(1, 4000000 / 165, 40, 1); + } + + if (game_drv == GAME_POWERINB ) { + MSM6295Init(0, 4000000 / 165, 40, 1); + MSM6295Init(1, 4000000 / 165, 40, 1); + } + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 powerinsExit() +{ + GenericTilesExit(); + + SekExit(); + MSM6295Exit(0); + + if (game_drv != GAME_POWERINA) { + MSM6295Exit(1); + + if (game_drv == GAME_POWERINS) + BurnYM2203Exit(); + + ZetExit(); + } + + BurnFree(Mem); + return 0; +} + +static void TileBackground() +{ + for (INT32 offs = 256*32-1; offs >=0; offs--) { + + INT32 page = offs >> 8; + INT32 x = (offs >> 4) & 0xF; + INT32 y = (offs >> 0) & 0xF; + + x = x * 16 + (page & 7) * 256 + 32 - ((RamVReg[1]&0xff) + (RamVReg[0]&0xff)*256); + y = y * 16 + (page >> 4) * 256 - 16 - ((RamVReg[3]&0xff) + (RamVReg[2]&0xff)*256); + + if ( x<=-16 || x>=320 || y <=-16 || y>=224 ) continue; + else { + INT32 attr = RamBg[offs]; + INT32 code = ((attr & 0x7ff) + tile_bank); + INT32 color = (attr >> 12) | ((attr >> 7) & 0x10); + + if ( x >=0 && x <= (320-16) && y>=0 && y <=(224-16) ) { + Render16x16Tile(pTransDraw, code, x, y, color, 4, 0, RomBg); + } else { + Render16x16Tile_Clip(pTransDraw, code, x, y, color, 4, 0, RomBg); + } + } + } +} + +static void TileForeground() +{ + for (INT32 offs = 0; offs < 64*32; offs++) { + INT32 x = ((offs & 0xFFE0) >> 2 ) + 32; + INT32 y = ((offs & 0x001F) << 3 ) - 16; + if (x > 320) x -= 512; + if ( x<0 || x>(320-8) || y<0 || y>(224-8)) continue; + else { + if ((RamFg[offs] & 0x0FFF) == 0) continue; + UINT8 *d = RomFg + (RamFg[offs] & 0x0FFF) * 32; + UINT16 c = ((RamFg[offs] & 0xF000) >> 8) | 0x200; + UINT16 *p = pTransDraw + y * 320 + x; + for (INT32 k=0;k<8;k++) { + if ((d[0] >> 4) != 15) p[0] = (d[0] >> 4) | c; + if ((d[0] & 0xF) != 15) p[1] = (d[0] & 0xF) | c; + if ((d[1] >> 4) != 15) p[2] = (d[1] >> 4) | c; + if ((d[1] & 0xF) != 15) p[3] = (d[1] & 0xF) | c; + if ((d[2] >> 4) != 15) p[4] = (d[2] >> 4) | c; + if ((d[2] & 0xF) != 15) p[5] = (d[2] & 0xF) | c; + if ((d[3] >> 4) != 15) p[6] = (d[3] >> 4) | c; + if ((d[3] & 0xF) != 15) p[7] = (d[3] & 0xF) | c; + d += 4; + p += 320; + } + } + } +} + +static inline void drawgfx(UINT32 code,UINT32 color,INT32 flipx,/*INT32 flipy,*/INT32 sx,INT32 sy) +{ + if (sx >= 0 && sx <= (320-16) && sy >= 0 && sy <= (224-16) ) { + if ( flipx ) + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 15, 0x400, RomSpr); + else + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, 15, 0x400, RomSpr); + } else { + if ( flipx ) + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x400, RomSpr); + else + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x400, RomSpr); + } +} + +static void DrawSprites() +{ + UINT16 *source = RamSpr + 0x8000/2; + UINT16 *finish = RamSpr + 0x9000/2; + + for ( ; source < finish; source += 8 ) { + + if (!(source[0]&1)) continue; + + INT32 size = source[1]; + INT32 code = (source[3] & 0x7fff) + ( (size & 0x0100) << 7 ); + INT32 sx = source[4]; + INT32 sy = source[6]; + INT32 color = source[7] & 0x3F; + INT32 flipx = size & 0x1000; + INT32 dimx = ((size >> 0) & 0xf ) + 1; + INT32 dimy = ((size >> 4) & 0xf ) + 1; + + sx &= 0x3ff; if (sx > 0x1ff) sx -= 0x400; sx += 32; + sy &= 0x3ff; if (sy > 0x1ff) sy -= 0x400; sy -= 16; + + for (INT32 x = 0 ; x < dimx ; x++) + for (INT32 y = 0 ; y < dimy ; y++) { + drawgfx(code, color, flipx, /*flipy, */sx + x*16, sy + y*16); + code ++; + } + } +} + +static void DrvDraw() +{ + if (bRecalcPalette) { + for (INT32 i=0; i<0x800; i++) CalcCol(i); + bRecalcPalette = 0; + } + + BurnTransferClear(); + + TileBackground(); + DrawSprites(); + TileForeground(); + + BurnTransferCopy(RamCurPal); +} + +static INT32 powerinsFrame() +{ + INT32 nInterleave = 200; + + if (DrvReset) DrvDoReset(); + + DrvInput[0] = 0x00; + DrvInput[2] = 0x00; + DrvInput[3] = 0x00; + for (INT32 i = 0; i < 8; i++) { + DrvInput[2] |= (DrvJoy1[i] & 1) << i; + DrvInput[3] |= (DrvJoy2[i] & 1) << i; + DrvInput[0] |= (DrvButton[i] & 1) << i; + } + + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 56)); + if (game_drv == GAME_POWERINB) nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = 6000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + SekOpen(0); + if (game_drv != GAME_POWERINA) { + ZetNewFrame(); + ZetOpen(0); + } + + if ( game_drv == GAME_POWERINA ) { + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + SekRun(nCyclesTotal[0]); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (game_drv == GAME_POWERINS) { + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + if (game_drv == GAME_POWERINB) { + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if ((i & 180) == 0) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + if (game_drv == GAME_POWERINS) { + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + } + + if (game_drv == GAME_POWERINB) { + ZetRun(nCyclesTotal[1] - nCyclesDone[1]); + + if (pBurnSoundOut) { + memset(pBurnSoundOut, 0, nBurnSoundLen * 2 * sizeof(INT16)); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 powerinsScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029671; + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); // Scan 68000 state + + if ( game_drv != GAME_POWERINA ) + ZetScan(nAction); // Scan Z80 state + + if ( game_drv == GAME_POWERINS ) + BurnYM2203Scan(nAction, pnMin); + + MSM6295Scan(0, nAction); + if ( game_drv != GAME_POWERINA ) + MSM6295Scan(1, nAction); + + SCAN_VAR(m6295size); + SCAN_VAR(soundlatch); + if ( game_drv == GAME_POWERINA ) + SCAN_VAR(oki_bank); + + SCAN_VAR(tile_bank); + SCAN_VAR(RamCurPal); + + if (nAction & ACB_WRITE) { + bRecalcPalette = 1; + if ( game_drv == GAME_POWERINA ) + memcpy(&MSM6295ROM[0x30000],&MSM6295ROM[0x40000 + 0x10000*oki_bank],0x10000); + } + } + + return 0; +} + +struct BurnDriver BurnDrvPowerins = { + "powerins", NULL, NULL, NULL, "1993", + "Power Instinct (USA)\0", NULL, "Atlus", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, FBF_PWRINST, + NULL, powerinsRomInfo, powerinsRomName, NULL, NULL, powerinsInputInfo, powerinsDIPInfo, + powerinsInit, powerinsExit, powerinsFrame, NULL, powerinsScan, &bRecalcPalette, 0x800, + 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPowerinj = { + "powerinsj", "powerins", NULL, NULL, "1993", + "Gouketsuji Ichizoku (Japan)\0", NULL, "Atlus", "Miscellaneous", + L"\u8C6A\u8840\u5BFA\u4E00\u65CF (Japan)\0Gouketsuji Ichizoku\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, FBF_PWRINST, + NULL, powerinjRomInfo, powerinjRomName, NULL, NULL, powerinsInputInfo, powerinjDIPInfo, + powerinsInit, powerinsExit, powerinsFrame, NULL, powerinsScan, &bRecalcPalette, 0x800, + 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPowerina = { + "powerinsa", "powerins", NULL, NULL, "1993", + "Power Instinct (USA, bootleg set 1)\0", NULL, "Atlus", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, FBF_PWRINST, + NULL, powerinaRomInfo, powerinaRomName, NULL, NULL, powerinsInputInfo, powerinsDIPInfo, + powerinsInit, powerinsExit, powerinsFrame, NULL, powerinsScan, &bRecalcPalette, 0x800, + 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPowerinb = { + "powerinsb", "powerins", NULL, NULL, "1993", + "Power Instinct (USA, bootleg set 2)\0", NULL, "Atlus", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, FBF_PWRINST, + NULL, powerinbRomInfo, powerinbRomName, NULL, NULL, powerinsInputInfo, powerinsDIPInfo, + powerinsInit, powerinsExit, powerinsFrame, NULL, powerinsScan, &bRecalcPalette, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_pushman.cpp b/src/burn/drivers/misc_post90s/d_pushman.cpp new file mode 100644 index 00000000..e0baca2e --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_pushman.cpp @@ -0,0 +1,975 @@ +// FB Alpha Pushman driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "m6805_intf.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvMcuROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvMcuRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16*DrvScroll; +static UINT8 *DrvShareRAM; +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static INT32 latch; +static INT32 new_latch; + +static UINT16 DrvInputs[2]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static INT32 vblank; +static INT32 no_mcu = 0; + +static struct BurnInputInfo PushmanInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 14, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 13, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Pushman) + +static struct BurnInputInfo BballsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 14, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 13, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Bballs) + +static struct BurnDIPInfo PushmanDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Debug Mode (Cheat)" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Pull Option" }, + {0x14, 0x01, 0x02, 0x02, "5" }, + {0x14, 0x01, 0x02, 0x00, "9" }, + + {0 , 0xfe, 0 , 2, "Level Select" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x08, 0x08, "Upright" }, + {0x14, 0x01, 0x08, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x15, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x15, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x15, 0x01, 0x08, 0x08, "Easy" }, + {0x15, 0x01, 0x08, 0x00, "Hard" }, +}; + +STDDIPINFO(Pushman) + +static struct BurnDIPInfo BballsDIPList[]= +{ + {0x12, 0xff, 0xff, 0xcf, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x12, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x12, 0x01, 0x08, 0x08, "Easy" }, + {0x12, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Music (In-game)" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Music (Attract Mode)" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0xc0, "1" }, + {0x12, 0x01, 0xc0, 0x80, "2" }, + {0x12, 0x01, 0xc0, 0x40, "3" }, + {0x12, 0x01, 0xc0, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Zaps" }, + {0x13, 0x01, 0x01, 0x01, "1" }, + {0x13, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Display Next Ball" }, + {0x13, 0x01, 0x02, 0x02, "No" }, + {0x13, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 3, "Service Mode" }, + {0x13, 0x01, 0xc0, 0xc0, "Off" }, + {0x13, 0x01, 0xc0, 0x40, "Inputs/Outputs" }, + {0x13, 0x01, 0xc0, 0x00, "Graphics" }, +}; + +STDDIPINFO(Bballs) + +void __fastcall pushman_main_write_word(UINT32 address, UINT16 data) +{ + if (address & 0xf00000) { + SekWriteWord(address & 0xfffff, data); + return; + } + + switch (address) + { + case 0x060000: + case 0x060002: + case 0x060004: + case 0x060006: + { + INT32 offset = address & 0x06; + + DrvShareRAM[offset + 0] = data >> 8; + DrvShareRAM[offset + 1] = data; + + if (no_mcu) { + if(offset == 0) { + latch = 0; + if (DrvShareRAM[0] <= 0xf) latch = DrvShareRAM[0] << 2; + if (DrvShareRAM[1]) latch |= 2; + new_latch = 1; + } + } else { + if (offset == 2) { + m68705SetIrqLine(0, 1); + m6805Run(0); + m68705SetIrqLine(0, 0); + new_latch = 0; + } + } + } + return; + + case 0x0e8000: + case 0x0e8002: + DrvScroll[(address >> 1) & 1] = data; + return; + } +} + +void __fastcall pushman_main_write_byte(UINT32 address, UINT8 data) +{ + if (address & 0xf00000) { + SekWriteByte(address & 0xfffff, data); + return; + } + + switch (address) + { + case 0x0e4000: + *flipscreen = data & 0x02; + return; + + case 0x0e4002: + *soundlatch = data; + return; + } +} + +UINT16 __fastcall pushman_main_read_word(UINT32 address) +{ + if (address & 0xf00000) { + return SekReadWord(address & 0xfffff); + } + + switch (address) + { + case 0x060000: + return latch; + + case 0x060002: + case 0x060004: + return ((DrvShareRAM[(address & 0x06) + 1] << 8) | DrvShareRAM[(address & 0x06)]); + + case 0x060006: + if ( new_latch) { new_latch = 0; return 0; } + if (!new_latch) return 0xff; + + case 0x0e4000: + return DrvInputs[0]; + + case 0x0e4002: + return DrvInputs[1] ^ vblank; + + case 0x0e4004: + return (DrvDips[1] << 8) | DrvDips[0]; + } + + return 0; +} + +UINT8 __fastcall pushman_main_read_byte(UINT32 address) +{ + if (address & 0xf00000) { + return SekReadByte(address & 0xfffff); + } + + switch (address) + { + case 0x0e4002: + return (DrvInputs[1] ^ vblank) >> 8; + } + + return 0; +} + + +void __fastcall pushman_sound_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + BurnYM2203Write(0, port & 1, data); + return; + + case 0x80: + case 0x81: + BurnYM2203Write(1, port & 1, data); + return; + } +} + +UINT8 __fastcall pushman_sound_read(UINT16 address) +{ + if (address == 0xe000) return *soundlatch; + + return 0; +} + +void pushman_mcu_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0002: + { + if (~DrvShareRAM[2] & 0x02 && data & 0x02) { + latch = (DrvShareRAM[1] << 8) | DrvShareRAM[0]; + new_latch = 1; + } + DrvShareRAM[address] = data; + } + return; + + case 0x0000: + case 0x0001: + case 0x0003: + case 0x0004: + case 0x0005: + case 0x0006: + case 0x0007: + DrvShareRAM[address] = data; + return; + } +} + +UINT8 pushman_mcu_read(UINT16 address) +{ + switch (address) + { + case 0x0000: + case 0x0001: + case 0x0002: + case 0x0003: + case 0x0004: + case 0x0005: + case 0x0006: + case 0x0007: + return DrvShareRAM[address]; + } + + return 0; +} + +static void DrvIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + +// m6805Open(0); + m68705Reset(); +// m6805Close(); + + BurnYM2203Reset(); + + latch = 0x400; // bballs + new_latch = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x020000; + DrvZ80ROM = Next; Next += 0x010000; + DrvMcuROM = Next; Next += 0x001000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROM3 = Next; Next += 0x010000; + + DrvPalette = (UINT32*)Next; Next += 0x0240 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x001000; + DrvVidRAM = Next; Next += 0x000800; + DrvZ80RAM = Next; Next += 0x000800; + DrvMcuRAM = Next; Next += 0x000080; + + DrvShareRAM = Next; Next += 0x000008; + + DrvScroll = (UINT16*)Next; Next += 0x000002 * sizeof(UINT16); + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x000004, 0x000000, 0x100004, 0x100000 }; + INT32 Plane1[4] = { 0x000000, 0x080000, 0x100000, 0x180000 }; + INT32 XOffs0[32] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x200, 0x201, 0x202, 0x203, 0x208, 0x209, 0x20a, 0x20b, + 0x400, 0x401, 0x402, 0x403, 0x408, 0x409, 0x40a, 0x40b, + 0x600, 0x601, 0x602, 0x603, 0x608, 0x609, 0x60a, 0x60b }; + INT32 YOffs0[32] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0, + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, + 0x180, 0x190, 0x1a0, 0x1b0, 0x1c0, 0x1d0, 0x1e0, 0x1f0 }; + INT32 XOffs1[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087 }; + INT32 YOffs1[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0800, 2, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x0200, 4, 32, 32, Plane0, XOffs0, YOffs0, 0x800, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + BurnLoadRom(DrvMcuROM + 0x00000, 3, 1); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 13, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x0e0800, 0x0e17ff, SM_RAM); + SekMapMemory(DrvVidRAM, 0x0ec000, 0x0ec7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x0f8000, 0x0f87ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0fc000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, pushman_main_write_word); + SekSetWriteByteHandler(0, pushman_main_write_byte); + SekSetReadWordHandler(0, pushman_main_read_word); + SekSetReadByteHandler(0, pushman_main_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetSetReadHandler(pushman_sound_read); + ZetSetOutHandler(pushman_sound_out_port); + ZetMemEnd(); + ZetClose(); + + m6805Init(1, 0x1000); +// m6805Open(0); + m6805MapMemory(DrvMcuRAM + 0x0000, 0x0010, 0x007f, M6805_RAM); + m6805MapMemory(DrvMcuROM + 0x0080, 0x0080, 0x0fff, M6805_ROM); + m6805SetWriteHandler(pushman_mcu_write); + m6805SetReadHandler(pushman_mcu_read); +// m6805Close(); + + BurnYM2203Init(2, 2000000, &DrvIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(1); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + m6805Exit(); + + BurnFree (AllMem); + + no_mcu = 0; + + return 0; +} + +static void draw_background() +{ + INT32 scrollx = DrvScroll[0] & 0xfff; + INT32 scrolly = (0xf00 - DrvScroll[1] + 16) & 0x7ff; + + for (INT32 offs = 0; offs < 128 * 64; offs++) + { + INT32 col = offs & 0x7f; + INT32 row = offs >> 7; + + INT32 sy = (row << 5) - scrolly; + if (sy < -31) sy += 0x0800; + + INT32 sx = (col << 5) - scrollx; + if (sx < -31) sx += 0x1000; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 ofst = (col & 7) + ((~row & 7) << 3) + ((col & 0x78) << 3) + ((~row&0x38)<<7); + + INT32 attr = DrvGfxROM3[ofst * 2 + 0] | (DrvGfxROM3[ofst * 2 + 1] << 8); + INT32 code = (attr & 0xff) | ((attr & 0x4000) >> 6); + INT32 color = (attr >> 8) & 0x0f; + INT32 flipx = (attr & 0x2000); + + if (flipx) { + Render32x32Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM2); + } else { + Render32x32Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM2); + } + } +} + +static void draw_foreground() +{ + UINT16 *vram = (UINT16*)DrvVidRAM; + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= 16; + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs]; + INT32 code = (attr & 0xff) | ((attr & 0xc000) >> 6) | ((attr & 0x2000) >> 3); + INT32 color = (attr >> 8) & 0x0f; + INT32 flipy = (attr & 0x1000); + + if (flipy) { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 2, 3, 0x200, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 3, 0x200, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + UINT16 *vram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0x0800-4; offs >= 0; offs -= 4) + { + INT32 x = vram[offs + 3] & 0x1ff; + if (x == 0x180) continue; + + if (x > 0xff) x=0-(0x200-x); + + INT32 y = 240-vram[offs + 2]; + INT32 color = (vram[offs + 1] >> 2) & 0xf; + INT32 code = vram[offs + 0] & 0x7ff; + + INT32 flipx = vram[offs + 1] & 2; + INT32 flipy = vram[offs + 1] & 1; + + if (*flipscreen) + { + x = 240 - x; + y = 240 - y; + flipx = !flipx; + flipy = !flipy; + } + + y -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x, y, color, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x, y, color, 4, 15, 0x100, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y, color, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y, color, 4, 15, 0x100, DrvGfxROM1); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0x200 / 2; i < 0x680 / 2; i++) { + r = (p[i] >> 8) & 0x0f; + g = (p[i] >> 4) & 0x0f; + b = (p[i] >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i - 0x100] = BurnHighCol(r, g, b, 0); + } + } + + draw_background(); + draw_sprites(); + draw_foreground(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + SekOpen(0); + ZetOpen(0); +// m6805Open(0); + + INT32 nInterleave = 256; + INT32 nCyclesTotal[3] = { 8000000 / 60, 4000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 16) vblank = 0x0400; + if (i == 240) vblank = 0; + + INT32 segment = nCyclesTotal[0] / nInterleave; + + nCyclesDone[0] += SekRun(segment); + if (i == (nInterleave - 1)) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + if (no_mcu == 0) { + nCyclesDone[1] += m6805Run(segment / 2); + } + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + } + + if (pBurnSoundOut) { + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + +// m6805Close(); + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + m6805Scan(nAction, 0); + + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(new_latch); + SCAN_VAR(latch); + } + + return 0; +} + + +// Pushman (Korea, set 1) + +static struct BurnRomInfo pushmanRomDesc[] = { + { "pushman.012", 0x10000, 0x330762bc, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "pushman.011", 0x10000, 0x62636796, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "pushman.013", 0x08000, 0xadfe66c1, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "pushman68705r3p.ic23",0x01000, 0xd7916657, 3 | BRF_PRG | BRF_ESS }, // 3 M68705 MCU Code + + { "pushman.001", 0x08000, 0x626e5865, 4 | BRF_GRA }, // 4 Characters + + { "pushman.004", 0x10000, 0x87aafa70, 5 | BRF_GRA }, // 5 Sprites + { "pushman.005", 0x10000, 0x7fd1200c, 5 | BRF_GRA }, // 6 + { "pushman.002", 0x10000, 0x0a094ab0, 5 | BRF_GRA }, // 7 + { "pushman.003", 0x10000, 0x73d1f29d, 5 | BRF_GRA }, // 8 + + { "pushman.006", 0x10000, 0x48ef3da6, 6 | BRF_GRA }, // 9 Tiles + { "pushman.008", 0x10000, 0x4b6a3e88, 6 | BRF_GRA }, // 10 + { "pushman.007", 0x10000, 0xb70020bd, 6 | BRF_GRA }, // 11 + { "pushman.009", 0x10000, 0xcc555667, 6 | BRF_GRA }, // 12 + + { "pushman.010", 0x08000, 0xa500132d, 7 | BRF_GRA }, // 13 Tilemap + + { "n82s129an.ic82", 0x00100, 0xec80ae36, 0 | BRF_GRA }, // 14 Prom +}; + +STD_ROM_PICK(pushman) +STD_ROM_FN(pushman) + +struct BurnDriver BurnDrvPushman = { + "pushman", NULL, NULL, NULL, "1990", + "Pushman (Korea, set 1)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, pushmanRomInfo, pushmanRomName, NULL, NULL, PushmanInputInfo, PushmanDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// Pushman (Korea, set 2) + +static struct BurnRomInfo pushmanaRomDesc[] = { + { "pushmana.212", 0x10000, 0x871d0858, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "pushmana.011", 0x10000, 0xae57761e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "pushman.013", 0x08000, 0xadfe66c1, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "pushman68705r3p.ic23",0x01000, 0xd7916657, 3 | BRF_PRG | BRF_ESS }, // 3 M68705 MCU Code + + { "pushmana.130", 0x10000, 0xf83f92e7, 4 | BRF_GRA }, // 4 Characters + + { "pushman.004", 0x10000, 0x87aafa70, 5 | BRF_GRA }, // 5 Sprites + { "pushman.005", 0x10000, 0x7fd1200c, 5 | BRF_GRA }, // 6 + { "pushman.002", 0x10000, 0x0a094ab0, 5 | BRF_GRA }, // 7 + { "pushman.003", 0x10000, 0x73d1f29d, 5 | BRF_GRA }, // 8 + + { "pushman.006", 0x10000, 0x48ef3da6, 6 | BRF_GRA }, // 9 Tiles + { "pushman.008", 0x10000, 0x4b6a3e88, 6 | BRF_GRA }, // 10 + { "pushman.007", 0x10000, 0xb70020bd, 6 | BRF_GRA }, // 11 + { "pushman.009", 0x10000, 0xcc555667, 6 | BRF_GRA }, // 12 + + { "pushmana.189", 0x10000, 0x59f25598, 7 | BRF_GRA }, // 13 Tilemap + + { "n82s129an.ic82", 0x000100, 0xec80ae36, 0 | BRF_GRA }, // 14 Prom +}; + +STD_ROM_PICK(pushmana) +STD_ROM_FN(pushmana) + +struct BurnDriver BurnDrvPushmana = { + "pushmana", "pushman", NULL, NULL, "1990", + "Pushman (Korea, set 2)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, pushmanaRomInfo, pushmanaRomName, NULL, NULL, PushmanInputInfo, PushmanDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// Pushman (American Sammy license) + +static struct BurnRomInfo pushmansRomDesc[] = { + { "pman-12.ic212", 0x10000, 0x4251109d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "pman-11.ic197", 0x10000, 0x1167ed9f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "pman-13.ic216", 0x08000, 0xbc03827a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "pushman68705r3p.ic23",0x01000, 0xd7916657, 3 | BRF_PRG | BRF_ESS }, // 3 M68705 MCU Code + + { "pman-1.ic130", 0x08000, 0x14497754, 4 | BRF_GRA }, // 4 Characters + + { "pman-4.ic58", 0x10000, 0x16e5ce6b, 5 | BRF_GRA }, // 5 Sprites + { "pman-5.ic59", 0x10000, 0xb82140b8, 5 | BRF_GRA }, // 6 + { "pman-2.56", 0x10000, 0x2cb2ac29, 5 | BRF_GRA }, // 7 + { "pman-3.57", 0x10000, 0x8ab957c8, 5 | BRF_GRA }, // 8 + + { "pman-6.ic131", 0x10000, 0xbd0f9025, 6 | BRF_GRA }, // 9 Tiles + { "pman-8.ic148", 0x10000, 0x591bd5c0, 6 | BRF_GRA }, // 10 + { "pman-7.ic132", 0x10000, 0x208cb197, 6 | BRF_GRA }, // 11 + { "pman-9.ic149", 0x10000, 0x77ee8577, 6 | BRF_GRA }, // 12 + + { "pman-10.ic189", 0x08000, 0x5f9ae9a1, 7 | BRF_GRA }, // 13 Tilemap + + { "n82s129an.ic82", 0x00100, 0xec80ae36, 0 | BRF_GRA }, // 14 Prom +}; + +STD_ROM_PICK(pushmans) +STD_ROM_FN(pushmans) + +struct BurnDriver BurnDrvPushmans = { + "pushmans", "pushman", NULL, NULL, "1990", + "Pushman (American Sammy license)\0", NULL, "Comad (American Sammy license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, pushmansRomInfo, pushmansRomName, NULL, NULL, PushmanInputInfo, PushmanDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// Bouncing Balls + +static struct BurnRomInfo bballsRomDesc[] = { + { "bb12.m17", 0x10000, 0x4501c245, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "bb11.l17", 0x10000, 0x55e45b60, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bb13.n4", 0x08000, 0x1ef78175, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "68705.uc", 0x01000, 0x00000000, 3 | BRF_PRG | BRF_NODUMP }, // 3 M68705 MCU Code + + { "bb1.g20", 0x08000, 0xb62dbcb8, 4 | BRF_GRA }, // 4 Characters + + { "bb4.d1", 0x10000, 0xb77de5f8, 5 | BRF_GRA }, // 5 Sprites + { "bb5.d2", 0x10000, 0xffffccbf, 5 | BRF_GRA }, // 6 + { "bb2.b1", 0x10000, 0xa5b13236, 5 | BRF_GRA }, // 7 + { "bb3.b2", 0x10000, 0xe35b383d, 5 | BRF_GRA }, // 8 + + { "bb6.h1", 0x10000, 0x0cada9ce, 6 | BRF_GRA }, // 9 Tiles + { "bb8.j1", 0x10000, 0xd55fe7c1, 6 | BRF_GRA }, // 10 + { "bb7.h2", 0x10000, 0xa352d53b, 6 | BRF_GRA }, // 11 + { "bb9.j2", 0x10000, 0x78d185ac, 6 | BRF_GRA }, // 12 + + { "bb10.l6", 0x08000, 0xd06498f9, 7 | BRF_GRA }, // 13 Tilemap + + { "bb_prom.e9", 0x00100, 0xec80ae36, 8 | BRF_OPT }, // 14 Priority +}; + +STD_ROM_PICK(bballs) +STD_ROM_FN(bballs) + +static INT32 bballsInit() +{ + no_mcu = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvBballs = { + "bballs", NULL, NULL, NULL, "1991", + "Bouncing Balls\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, bballsRomInfo, bballsRomName, NULL, NULL, BballsInputInfo, BballsDIPInfo, + bballsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_raiden.cpp b/src/burn/drivers/misc_post90s/d_raiden.cpp new file mode 100644 index 00000000..8f6c02bb --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_raiden.cpp @@ -0,0 +1,1679 @@ +// Raiden (c) 1990 Seibu Kaihatsu +// driver by Oliver Bergmann, Bryan McPhail, Randy Mongenel + +// port to FB Alpha by OopsWare + + +#include "burnint.h" +#include "burn_ym3812.h" +#include "msm6295.h" +#include "vez.h" + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *RomV30A; +static UINT8 *RomV30B; +static UINT8 *RomZ80; + +static UINT8 *RomGfx1; +static UINT8 *RomGfx2; +static UINT8 *RomGfx3; +static UINT8 *RomGfx4; + +static UINT8 *RamV30A; +static UINT8 *RamV30B; +static UINT8 *RamV30S; +static UINT8 *RamZ80; + +static UINT8 *RamSpr; +static UINT16 *RamFg; +static UINT16 *RamBg; +static UINT16 *RamTxt; +static UINT8 *RamPal; +static UINT8 *RamScroll; + +static UINT16 *RamCurPal; + +static UINT8 bRecalcPalette = 0; +static UINT8 DrvReset = 0; + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +static UINT8 main2sub[2] = {0, 0}; +static UINT8 sub2main[2] = {0, 0}; +static INT32 main2sub_pending = 0; +static INT32 sub2main_pending = 0; +static UINT8 z80_irq1, z80_irq2; +static INT32 seibu_bank = 0; + +#define GAME_RAIDEN 0 +#define GAME_RAIDENA 1 +#define GAME_RAIDENK 2 +#define GAME_RAIDENT 3 +static INT32 game_drv; + +inline static UINT32 CalcCol(INT32 offs) +{ + // xxxxBBBBGGGGRRRR + INT32 nColour = RamPal[offs + 0] | (RamPal[offs + 1] << 8); + INT32 r, g, b; + + r = (nColour & 0x000F) << 4; // Red + r |= r >> 4; + g = (nColour & 0x00F0) >> 0; // Green + g |= g >> 4; + b = (nColour & 0x0F00) >> 4; // Blue + b |= b >> 4; + + return BurnHighCol(r, g, b, 0); +} + +static struct BurnInputInfo raidenInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(raiden) + + +static struct BurnDIPInfo raidenDIPList[] = { + + // Defaults + {0x11, 0xFF, 0xFF, 0x00, NULL}, + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin Mode"}, + {0x11, 0x01, 0x01, 0x00, "A"}, + {0x11, 0x01, 0x01, 0x01, "B"}, + {0, 0xFE, 0, 16, "Coinage"}, + {0x11, 0x01, 0x1E, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x1E, 0x02, "2 coins 1 credit"}, + {0x11, 0x01, 0x1E, 0x04, "3 coins 1 credit"}, + {0x11, 0x01, 0x1E, 0x06, "4 coins 1 credits"}, + {0x11, 0x01, 0x1E, 0x08, "5 coins 1 credit"}, + {0x11, 0x01, 0x1E, 0x0A, "6 coins 1 credit"}, + {0x11, 0x01, 0x1E, 0x0C, "1 coin 2 credits"}, + {0x11, 0x01, 0x1E, 0x0E, "1 coin 3 credits"}, + {0x11, 0x01, 0x1E, 0x10, "1 coin 4 credits"}, + {0x11, 0x01, 0x1E, 0x12, "1 coin 5 credits"}, + {0x11, 0x01, 0x1E, 0x14, "1 coin 6 credits"}, + {0x11, 0x01, 0x1E, 0x16, "2 coins 3 credits"}, + {0x11, 0x01, 0x1E, 0x18, "3 coins 2 credits"}, + {0x11, 0x01, 0x1E, 0x1A, "5 coins 3 credits"}, + {0x11, 0x01, 0x1E, 0x1C, "8 coins 3 credits"}, + {0x11, 0x01, 0x1E, 0x1E, "Free Play"}, + {0, 0xFE, 0, 2, "Credits to Start"}, + {0x11, 0x01, 0x20, 0x00, "1"}, + {0x11, 0x01, 0x20, 0x20, "2"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x11, 0x01, 0x80, 0x00, "Off"}, + {0x11, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Lives"}, + {0x12, 0x01, 0x03, 0x00, "3"}, + {0x12, 0x01, 0x03, 0x01, "1"}, + {0x12, 0x01, 0x03, 0x02, "2"}, + {0x12, 0x01, 0x03, 0x03, "5"}, + {0, 0xFE, 0, 4, "Bonus Life"}, + {0x12, 0x01, 0x0c, 0x00, "150000 400000"}, + {0x12, 0x01, 0x0c, 0x04, "80000 300000"}, + {0x12, 0x01, 0x0c, 0x08, "300000 1000000"}, + {0x12, 0x01, 0x0c, 0x0c, "1000000 5000000"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x12, 0x01, 0x30, 0x00, "Normal"}, + {0x12, 0x01, 0x30, 0x10, "Easy"}, + {0x12, 0x01, 0x30, 0x20, "Hard"}, + {0x12, 0x01, 0x30, 0x30, "Very Hard"}, + {0, 0xFE, 0, 2, "Allow Continue"}, + {0x12, 0x01, 0x40, 0x00, "Yes"}, + {0x12, 0x01, 0x40, 0x40, "No"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x12, 0x01, 0x80, 0x00, "On"}, + {0x12, 0x01, 0x80, 0x80, "Off"}, +}; + +STDDIPINFO(raiden) + +static struct BurnRomInfo raidenRomDesc[] = { + { "rai1.bin", 0x010000, 0xa4b12785, BRF_ESS | BRF_PRG }, // CPU 0, V30 + { "rai2.bin", 0x010000, 0x17640bd5, BRF_ESS | BRF_PRG }, + { "rai3.bin", 0x020000, 0x9d735bf5, BRF_ESS | BRF_PRG }, + { "rai4.bin", 0x020000, 0x8d184b99, BRF_ESS | BRF_PRG }, + + { "rai5.bin", 0x020000, 0x7aca6d61, BRF_ESS | BRF_PRG }, // CPU 1, V30 + { "rai6a.bin", 0x020000, 0xe3d35cc2, BRF_ESS | BRF_PRG }, + + { "rai6.bin", 0x010000, 0x723a483b, BRF_ESS | BRF_PRG }, // CPU 2, Z80 + + { "rai9.bin", 0x008000, 0x1922b25e, BRF_GRA }, // Tiles + { "rai10.bin", 0x008000, 0x5f90786a, BRF_GRA }, + { "raiu0919.bin", 0x080000, 0xda151f0b, BRF_GRA }, + { "raiu0920.bin", 0x080000, 0xac1f57ac, BRF_GRA }, + { "raiu165.bin", 0x080000, 0x946d7bde, BRF_GRA }, + + { "rai7.bin", 0x010000, 0x8f927822, BRF_SND }, // Sound + + { "ep910pc-1.bin", 0x000884, 0x00000000, BRF_NODUMP }, + { "ep910pc-2.bin", 0x000884, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(raiden) +STD_ROM_FN(raiden) + +static struct BurnRomInfo raidenaRomDesc[] = { + { "rai1.bin", 0x010000, 0xa4b12785, BRF_ESS | BRF_PRG }, // CPU 0, V30 + { "rai2.bin", 0x010000, 0x17640bd5, BRF_ESS | BRF_PRG }, + { "raiden03.rom", 0x020000, 0xf6af09d0, BRF_ESS | BRF_PRG }, + { "raiden04.rom", 0x020000, 0x6bdfd416, BRF_ESS | BRF_PRG }, + + { "raiden05.rom", 0x020000, 0xed03562e, BRF_ESS | BRF_PRG }, // CPU 1, V30 + { "raiden06.rom", 0x020000, 0xa19d5b5d, BRF_ESS | BRF_PRG }, + + { "raiden08.rom", 0x010000, 0xcbe055c7, BRF_ESS | BRF_PRG }, // CPU 2, Z80 + + { "rai9.bin", 0x008000, 0x1922b25e, BRF_GRA }, // Tiles + { "rai10.bin", 0x008000, 0x5f90786a, BRF_GRA }, + { "raiu0919.bin", 0x080000, 0xda151f0b, BRF_GRA }, + { "raiu0920.bin", 0x080000, 0xac1f57ac, BRF_GRA }, + { "raiu165.bin", 0x080000, 0x946d7bde, BRF_GRA }, + + { "rai7.bin", 0x010000, 0x8f927822, BRF_SND }, // Sound +}; + +STD_ROM_PICK(raidena) +STD_ROM_FN(raidena) + +static struct BurnRomInfo raidenkRomDesc[] = { + { "rai1.bin", 0x010000, 0xa4b12785, BRF_ESS | BRF_PRG }, // CPU 0, V30 + { "rai2.bin", 0x010000, 0x17640bd5, BRF_ESS | BRF_PRG }, + { "raiden03.rom", 0x020000, 0xf6af09d0, BRF_ESS | BRF_PRG }, + { "1i", 0x020000, 0xfddf24da, BRF_ESS | BRF_PRG }, + + { "raiden05.rom", 0x020000, 0xed03562e, BRF_ESS | BRF_PRG }, // CPU 1, V30 + { "raiden06.rom", 0x020000, 0xa19d5b5d, BRF_ESS | BRF_PRG }, + + { "8b", 0x010000, 0x99ee7505, BRF_ESS | BRF_PRG }, // CPU 2, Z80 + + { "rai9.bin", 0x008000, 0x1922b25e, BRF_GRA }, // Tiles + { "rai10.bin", 0x008000, 0x5f90786a, BRF_GRA }, + { "raiu0919.bin", 0x080000, 0xda151f0b, BRF_GRA }, + { "raiu0920.bin", 0x080000, 0xac1f57ac, BRF_GRA }, + { "raiu165.bin", 0x080000, 0x946d7bde, BRF_GRA }, + + { "rai7.bin", 0x010000, 0x8f927822, BRF_SND }, // Sound +}; + +STD_ROM_PICK(raidenk) +STD_ROM_FN(raidenk) + +static struct BurnRomInfo raidentRomDesc[] = { + { "rai1.bin", 0x010000, 0xa4b12785, BRF_ESS | BRF_PRG }, // CPU 0, V30 + { "rai2.bin", 0x010000, 0x17640bd5, BRF_ESS | BRF_PRG }, + { "raiden03.rom", 0x020000, 0xf6af09d0, BRF_ESS | BRF_PRG }, + { "raid04t.023", 0x020000, 0x61eefab1, BRF_ESS | BRF_PRG }, + + { "raiden05.rom", 0x020000, 0xed03562e, BRF_ESS | BRF_PRG }, // CPU 1, V30 + { "raiden06.rom", 0x020000, 0xa19d5b5d, BRF_ESS | BRF_PRG }, + + { "raid08.212", 0x010000, 0xcbe055c7, BRF_ESS | BRF_PRG }, // CPU 2, Z80 + + { "rai9.bin", 0x008000, 0x1922b25e, BRF_GRA }, // Tiles + { "rai10.bin", 0x008000, 0x5f90786a, BRF_GRA }, + { "raiu0919.bin", 0x080000, 0xda151f0b, BRF_GRA }, + { "raiu0920.bin", 0x080000, 0xac1f57ac, BRF_GRA }, + { "raiu165.bin", 0x080000, 0x946d7bde, BRF_GRA }, + + { "rai7.bin", 0x010000, 0x8f927822, BRF_SND }, // Sound +}; + +STD_ROM_PICK(raident) +STD_ROM_FN(raident) + +static void update_irq_lines() +{ + if ((z80_irq1 & z80_irq2) == 0xff) + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + else + if (z80_irq2 == 0xdf) { // this shouldn't be required + ZetSetVector(z80_irq1 & z80_irq2); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } +} + +static UINT8 seibu_main_v30_r(UINT32 offset) +{ + switch (offset) { + case 0x4: return sub2main[0]; + case 0x5: return 0; + + case 0x6: return sub2main[1]; + case 0x7: return 0; + + case 0xa: return main2sub_pending ? 1 : 0; + case 0xb: return 0; + default : return 0xff; + } +} + +static void seibu_main_v30_w(UINT32 offset, UINT8 data) +{ + switch (offset) { + case 0x0: main2sub[0] = data; break; + case 0x2: main2sub[1] = data; break; + case 0x8: + z80_irq2 = 0xdf; + ZetOpen(0); + update_irq_lines(); + ZetClose(); + break; + case 0xc: + sub2main_pending = 0; + main2sub_pending = 1; + break; + } +} + +void raidenFMIRQHandler(INT32, INT32 nStatus) +{ + z80_irq1 = (nStatus) ? 0xd7 : 0xff; + update_irq_lines(); +} + +static void set_seibu_bank(INT32 bank) +{ + bank &= 1; + if (seibu_bank != bank) { + seibu_bank = bank; + ZetMapArea(0x8000, 0xFFFF, 0, RomZ80 + 0x8000 * (1-seibu_bank) ); + ZetMapArea(0x8000, 0xFFFF, 2, RomZ80 + 0x8000 * (1-seibu_bank) ); + } +} + +INT32 raidenSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +UINT8 __fastcall raidenReadByte(UINT32 vezAddress) +{ + switch (vezAddress) { + case 0x0b000: return ~DrvInput[1]; + case 0x0b001: return ~DrvInput[2]; + case 0x0b002: return ~DrvInput[3]; + case 0x0b003: return ~DrvInput[4]; + + case 0x0d000: + case 0x0d001: + case 0x0d002: + case 0x0d003: + case 0x0d004: + case 0x0d005: + case 0x0d006: + case 0x0d007: + case 0x0d008: + case 0x0d009: + case 0x0d00a: + case 0x0d00b: + case 0x0d00c: + case 0x0d00d: return seibu_main_v30_r(vezAddress - 0x0d000); + + //default: + // bprintf(PRINT_NORMAL, _T("CPU #0 Attempt to read byte value of location %x\n"), vezAddress); + } + return 0; +} + +void __fastcall raidenWriteByte(UINT32 vezAddress, UINT8 byteValue) +{ + + switch (vezAddress) { + + case 0x0b000: + case 0x0b001: + case 0x0b002: + case 0x0b003: + case 0x0b004: + case 0x0b005: + case 0x0b006: + case 0x0b007: + // raiden_control_w + // flip_screen not support + break; + + case 0x0d060: + case 0x0d061: + case 0x0d062: + case 0x0d063: + case 0x0d064: + case 0x0d065: + case 0x0d066: + case 0x0d067: + RamScroll[ vezAddress - 0x0d060 ] = byteValue; + break; + + case 0x0d000: + case 0x0d001: + case 0x0d002: + case 0x0d003: + case 0x0d004: + case 0x0d005: + case 0x0d006: + case 0x0d007: + case 0x0d008: + case 0x0d009: + case 0x0d00a: + case 0x0d00b: + case 0x0d00c: + case 0x0d00d: + seibu_main_v30_w(vezAddress - 0x0d000, byteValue); + break; + //default: + // bprintf(PRINT_NORMAL, _T("CPU #0 Attempt to write byte value %x to location %x\n"), byteValue, vezAddress); + } +} + +UINT8 __fastcall raidenAltReadByte(UINT32 vezAddress) +{ + switch (vezAddress) { + case 0x0a000: + case 0x0a001: + case 0x0a002: + case 0x0a003: + case 0x0a004: + case 0x0a005: + case 0x0a006: + case 0x0a007: + case 0x0a008: + case 0x0a009: + case 0x0a00a: + case 0x0a00b: + case 0x0a00c: + case 0x0a00d: return seibu_main_v30_r(vezAddress - 0x0a000); + + case 0x0e000: return ~DrvInput[1]; + case 0x0e001: return ~DrvInput[2]; + case 0x0e002: return ~DrvInput[3]; + case 0x0e003: return ~DrvInput[4]; + + //default: + // bprintf(PRINT_NORMAL, _T("CPU #0 Attempt to read byte value of location %x\n"), vezAddress); + } + return 0; +} + +void __fastcall raidenAltWriteByte(UINT32 vezAddress, UINT8 byteValue) +{ + + switch (vezAddress) { + + case 0x0b000: + case 0x0b001: + case 0x0b002: + case 0x0b003: + case 0x0b004: + case 0x0b005: + case 0x0b006: + case 0x0b007: + // raiden_control_w + // flip_screen not support + break; + + case 0x0f002: RamScroll[0] = byteValue; break; + case 0x0f004: RamScroll[1] = byteValue; break; + case 0x0f012: RamScroll[2] = byteValue; break; + case 0x0f014: RamScroll[3] = byteValue; break; + case 0x0f022: RamScroll[4] = byteValue; break; + case 0x0f024: RamScroll[5] = byteValue; break; + case 0x0f032: RamScroll[6] = byteValue; break; + case 0x0f034: RamScroll[7] = byteValue; break; + + case 0x0a000: + case 0x0a001: + case 0x0a002: + case 0x0a003: + case 0x0a004: + case 0x0a005: + case 0x0a006: + case 0x0a007: + case 0x0a008: + case 0x0a009: + case 0x0a00a: + case 0x0a00b: + case 0x0a00c: + case 0x0a00d: + seibu_main_v30_w(vezAddress - 0x0a000, byteValue); + break; + //default: + // bprintf(PRINT_NORMAL, _T("CPU #0 Attempt to write byte value %x to location %x\n"), byteValue, vezAddress); + } +} + +UINT8 __fastcall raidenSubReadByte(UINT32 vezAddress) +{ + switch (vezAddress) { + case 0x04008: { + UINT8 nRet = RamV30S[0x8]; + //INT32 pc = VezPC(); + //if (pc==0xfcde6 && ret!=0x40) cpu_spin(); + bprintf(PRINT_NORMAL, _T("sub_cpu_spin_r %02x%02x\n"), RamV30S[0x8], RamV30S[0x9]); + return nRet; } + case 0x04009: + bprintf(PRINT_NORMAL, _T("sub_cpu_spin_r %02x%02x\n"), RamV30S[0x8], RamV30S[0x9]); + return RamV30S[0x9]; + + //default: + // bprintf(PRINT_NORMAL, _T("CPU #1 Attempt to read byte value of location %x\n"), vezAddress); + } + return 0; +} + +void __fastcall raidenSubWriteByte(UINT32 vezAddress, UINT8 byteValue) +{ + if ((vezAddress & 0xFF000) == 0x03000 ) { + vezAddress -= 0x03000; + RamPal[ vezAddress ] = byteValue; + if (vezAddress & 1) + RamCurPal[ vezAddress >> 1 ] = CalcCol( vezAddress - 1 ); + return; + } + +// switch (vezAddress) { +// default: +// bprintf(PRINT_NORMAL, _T("CPU #1 Attempt to write byte value %x to location %x\n"), byteValue, vezAddress); +// } + +} + +UINT8 __fastcall raidenZ80Read(UINT16 a) +{ + switch (a) { + case 0x4008: return BurnYM3812Read(0); + case 0x4010: return main2sub[0]; + case 0x4011: return main2sub[1]; + case 0x4012: return sub2main_pending ? 1 : 0; + case 0x4013: return DrvInput[0]; + case 0x6000: return MSM6295ReadStatus(0); +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to read word value of location %04x\n"), a); + } + return 0; +} + + +void __fastcall raidenZ80Write(UINT16 a,UINT8 v) +{ + switch (a) { + case 0x4000: + // just a guess + main2sub_pending = 0; + sub2main_pending = 1; + break; + case 0x4001: + // seibu_irq_clear_w + z80_irq1 = 0xff; + z80_irq2 = 0xff; + update_irq_lines(); + break; + case 0x4002: + // seibu_rst10_ack_w + break; + case 0x4003: + // seibu_rst18_ack_w + z80_irq2 = 0xff; + update_irq_lines(); + break; + case 0x4007: + // seibu_bank_w + set_seibu_bank(v); + break; + case 0x4008: + // YM3812_control_port_0_w + BurnYM3812Write(0, v); + break; + case 0x4009: + // YM3812_write_port_0_w + BurnYM3812Write(1, v); + break; + case 0x4018: + sub2main[0] = v; + break; + case 0x4019: + sub2main[1] = v; + break; + case 0x401b: + // seibu_coin_w + //bprintf(PRINT_NORMAL, _T("seibu_coin_w(%02x)\n"), v); + break; + case 0x6000: + // OKIM6295_data_0_w + MSM6295Command(0, v); + break; + //default: + // bprintf(PRINT_NORMAL, _T("Z80 Attempt to write word value %x to location %x\n"), v, a); + } +} + +static INT32 DrvDoReset() +{ + + VezOpen(0); + VezReset(); + VezClose(); + + VezOpen(1); + VezReset(); + VezClose(); + + seibu_bank = -1; + + ZetOpen(0); + set_seibu_bank(0); + ZetReset(); + z80_irq1 = 0xff; + z80_irq2 = 0xff; + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + MSM6295Reset(0); + BurnYM3812Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + RomV30A = Next; Next += 0x060000; // V30 main cpu + RomV30B = Next; Next += 0x040000; // V30 sub cpu + RomZ80 = Next; Next += 0x020000; // Z80 sound cpu + + RomGfx1 = Next; Next += 0x020000; // char + RomGfx2 = Next; Next += 0x100000; // tile 1 + RomGfx3 = Next; Next += 0x100000; // tile 2 + RomGfx4 = Next; Next += 0x100000; // spr + + MSM6295ROM = Next; Next += 0x010000; + + RamStart = Next; + + RamV30A = Next; Next += 0x007000; + RamV30B = Next; Next += 0x002000; + RamV30S = Next; Next += 0x001000; + RamZ80 = Next; Next += 0x000800; + + RamSpr = Next; Next += 0x001000; + RamFg = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + RamBg = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + RamTxt = (UINT16 *)Next; Next += 0x000400 * sizeof(UINT16); + + RamPal = Next; Next += 0x001000; + RamScroll = Next; Next += 0x000008; + + RamEnd = Next; + + RamCurPal = (UINT16 *) Next; Next += 0x000800 * sizeof(UINT16); + + MemEnd = Next; + return 0; +} + +void decode_gfx_1(UINT8 * dst, UINT8 * src) +{ + for(INT32 i=0;i<0x10000/32;i++) { + for (INT32 j=0;j<8;j++) { + + dst[0] = (((src[0] >> 7) & 1) << 2) | (((src[0] >> 3) & 1) << 3) | (((src[0x8000] >> 7) & 1) << 0) | (((src[0x8000] >> 3) & 1) << 1); + dst[1] = (((src[0] >> 6) & 1) << 2) | (((src[0] >> 2) & 1) << 3) | (((src[0x8000] >> 6) & 1) << 0) | (((src[0x8000] >> 2) & 1) << 1); + dst[2] = (((src[0] >> 5) & 1) << 2) | (((src[0] >> 1) & 1) << 3) | (((src[0x8000] >> 5) & 1) << 0) | (((src[0x8000] >> 1) & 1) << 1); + dst[3] = (((src[0] >> 4) & 1) << 2) | (((src[0] >> 0) & 1) << 3) | (((src[0x8000] >> 4) & 1) << 0) | (((src[0x8000] >> 0) & 1) << 1); + dst[4] = (((src[1] >> 7) & 1) << 2) | (((src[1] >> 3) & 1) << 3) | (((src[0x8001] >> 7) & 1) << 0) | (((src[0x8001] >> 3) & 1) << 1); + dst[5] = (((src[1] >> 6) & 1) << 2) | (((src[1] >> 2) & 1) << 3) | (((src[0x8001] >> 6) & 1) << 0) | (((src[0x8001] >> 2) & 1) << 1); + dst[6] = (((src[1] >> 5) & 1) << 2) | (((src[1] >> 1) & 1) << 3) | (((src[0x8001] >> 5) & 1) << 0) | (((src[0x8001] >> 1) & 1) << 1); + dst[7] = (((src[1] >> 4) & 1) << 2) | (((src[1] >> 0) & 1) << 3) | (((src[0x8001] >> 4) & 1) << 0) | (((src[0x8001] >> 0) & 1) << 1); + + src += 2; + dst += 8; + } + } +} + +void decode_gfx_2(UINT8 * dst, UINT8 * src) +{ + for(INT32 i=0;i<0x80000/128;i++) { + for (INT32 j=0;j<16;j++) { + + dst[ 0] = (((src[ 1] >> 7) & 1) << 2) | (((src[ 1] >> 3) & 1) << 3) | (((src[ 0] >> 7) & 1) << 0) | (((src[ 0] >> 3) & 1) << 1); + dst[ 1] = (((src[ 1] >> 6) & 1) << 2) | (((src[ 1] >> 2) & 1) << 3) | (((src[ 0] >> 6) & 1) << 0) | (((src[ 0] >> 2) & 1) << 1); + dst[ 2] = (((src[ 1] >> 5) & 1) << 2) | (((src[ 1] >> 1) & 1) << 3) | (((src[ 0] >> 5) & 1) << 0) | (((src[ 0] >> 1) & 1) << 1); + dst[ 3] = (((src[ 1] >> 4) & 1) << 2) | (((src[ 1] >> 0) & 1) << 3) | (((src[ 0] >> 4) & 1) << 0) | (((src[ 0] >> 0) & 1) << 1); + dst[ 4] = (((src[ 3] >> 7) & 1) << 2) | (((src[ 3] >> 3) & 1) << 3) | (((src[ 2] >> 7) & 1) << 0) | (((src[ 2] >> 3) & 1) << 1); + dst[ 5] = (((src[ 3] >> 6) & 1) << 2) | (((src[ 3] >> 2) & 1) << 3) | (((src[ 2] >> 6) & 1) << 0) | (((src[ 2] >> 2) & 1) << 1); + dst[ 6] = (((src[ 3] >> 5) & 1) << 2) | (((src[ 3] >> 1) & 1) << 3) | (((src[ 2] >> 5) & 1) << 0) | (((src[ 2] >> 1) & 1) << 1); + dst[ 7] = (((src[ 3] >> 4) & 1) << 2) | (((src[ 3] >> 0) & 1) << 3) | (((src[ 2] >> 4) & 1) << 0) | (((src[ 2] >> 0) & 1) << 1); + + dst[ 8] = (((src[65] >> 7) & 1) << 2) | (((src[65] >> 3) & 1) << 3) | (((src[64] >> 7) & 1) << 0) | (((src[64] >> 3) & 1) << 1); + dst[ 9] = (((src[65] >> 6) & 1) << 2) | (((src[65] >> 2) & 1) << 3) | (((src[64] >> 6) & 1) << 0) | (((src[64] >> 2) & 1) << 1); + dst[10] = (((src[65] >> 5) & 1) << 2) | (((src[65] >> 1) & 1) << 3) | (((src[64] >> 5) & 1) << 0) | (((src[64] >> 1) & 1) << 1); + dst[11] = (((src[65] >> 4) & 1) << 2) | (((src[65] >> 0) & 1) << 3) | (((src[64] >> 4) & 1) << 0) | (((src[64] >> 0) & 1) << 1); + dst[12] = (((src[67] >> 7) & 1) << 2) | (((src[67] >> 3) & 1) << 3) | (((src[66] >> 7) & 1) << 0) | (((src[66] >> 3) & 1) << 1); + dst[13] = (((src[67] >> 6) & 1) << 2) | (((src[67] >> 2) & 1) << 3) | (((src[66] >> 6) & 1) << 0) | (((src[66] >> 2) & 1) << 1); + dst[14] = (((src[67] >> 5) & 1) << 2) | (((src[67] >> 1) & 1) << 3) | (((src[66] >> 5) & 1) << 0) | (((src[66] >> 1) & 1) << 1); + dst[15] = (((src[67] >> 4) & 1) << 2) | (((src[67] >> 0) & 1) << 3) | (((src[66] >> 4) & 1) << 0) | (((src[66] >> 0) & 1) << 1); + + + src += 4; + dst += 16; + } + src += 64; + } +} + +static void common_decrypt() +{ + UINT8 *RAM = RomV30A; + INT32 i; + UINT8 a; + + static const UINT8 xor_table[4][16]={ + {0xF1,0xF9,0xF5,0xFD,0xF1,0xF1,0x3D,0x3D,0x73,0xFB,0x77,0xFF,0x73,0xF3,0x3F,0x3F}, // rom 3 + {0xDF,0xFF,0xFF,0xFF,0xDB,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFB,0xFF}, // rom 4 + {0x7F,0x7F,0xBB,0x77,0x77,0x77,0xBE,0xF6,0x7F,0x7F,0xBB,0x77,0x77,0x77,0xBE,0xF6}, // rom 5 + {0xFF,0xFF,0xFD,0xFD,0xFD,0xFD,0xEF,0xEF,0xFF,0xFF,0xFD,0xFD,0xFD,0xFD,0xEF,0xEF} // rom 6 + }; + + // Rom 3 - main cpu even bytes + for (i=0x20000; i<0x60000; i+=2) { + a=RAM[i]; + a^=xor_table[0][(i/2) & 0x0f]; + a^=0xff; + a=(a & 0x31) | ((a<<1) & 0x04) | ((a>>5) & 0x02) | ((a<<4) & 0x40) | ((a<<4) & 0x80) | ((a>>4) & 0x08); + RAM[i]=a; + } + + // Rom 4 - main cpu odd bytes + for (i=0x20001; i<0x60000; i+=2) { + a=RAM[i]; + a^=xor_table[1][(i/2) & 0x0f]; + a^=0xff; + a=(a & 0xdb) | ((a>>3) & 0x04) | ((a<<3) & 0x20); + RAM[i]=a; + } + + RAM = RomV30B; + + // Rom 5 - sub cpu even bytes + for (i=0x00000; i<0x40000; i+=2) { + a=RAM[i]; + a^=xor_table[2][(i/2) & 0x0f]; + a^=0xff; + a=(a & 0x32) | ((a>>1) & 0x04) | ((a>>4) & 0x08) | ((a<<5) & 0x80) | ((a>>6) & 0x01) | ((a<<6) & 0x40); + RAM[i]=a; + } + + // Rom 6 - sub cpu odd bytes + for (i=0x00001; i<0x40000; i+=2) { + a=RAM[i]; + a^=xor_table[3][(i/2) & 0x0f]; + a^=0xff; + a=(a & 0xed) | ((a>>3) & 0x02) | ((a<<3) & 0x10); + RAM[i]=a; + } +} + +#define BIT(x,n) (((x)>>(n))&1) + +#define BITSWAP8(val,B7,B6,B5,B4,B3,B2,B1,B0) \ + ((BIT(val,B7) << 7) | \ + (BIT(val,B6) << 6) | \ + (BIT(val,B5) << 5) | \ + (BIT(val,B4) << 4) | \ + (BIT(val,B3) << 3) | \ + (BIT(val,B2) << 2) | \ + (BIT(val,B1) << 1) | \ + (BIT(val,B0) << 0)) + +static UINT8 decrypt_data(INT32 a,UINT8 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP8(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP8(src,7,6,5,4,2,3,1,0); + + return src; +} + +static UINT8 decrypt_opcode(INT32 a,UINT8 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if (~BIT(a,13) & BIT(a,12)) src ^= 0x20; + if (~BIT(a,6) & BIT(a,1)) src ^= 0x10; + if (~BIT(a,12) & BIT(a,2)) src ^= 0x08; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP8(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP8(src,7,6,5,4,2,3,1,0); + if (BIT(a,12) & BIT(a,9)) src = BITSWAP8(src,7,6,4,5,3,2,1,0); + if (BIT(a,11) & ~BIT(a,6)) src = BITSWAP8(src,6,7,5,4,3,2,1,0); + + return src; +} + +void seibu_sound_decrypt() +{ + for (INT32 i=0; i<0x10000;i++) { + UINT8 src = RomZ80[i]; + RomZ80[i+0x00000] = decrypt_data(i,src); + RomZ80[i+0x10000] = decrypt_opcode(i,src); + } +} + +static INT32 DrvInit() +{ + INT32 nRet; + + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "raiden") == 0 ) + game_drv = GAME_RAIDEN; + else + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "raidena") == 0 ) + game_drv = GAME_RAIDENA; + else + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "raidenk") == 0 ) + game_drv = GAME_RAIDENK; + else + if ( strcmp(BurnDrvGetTextA(DRV_NAME), "raident") == 0 ) + game_drv = GAME_RAIDENT; + else + return 1; + + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(); + + nRet = BurnLoadRom(RomV30A + 0x000000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomV30A + 0x000001, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomV30A + 0x020000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomV30A + 0x020001, 3, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomV30B + 0x000000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(RomV30B + 0x000001, 5, 2); if (nRet != 0) return 1; + + if (game_drv != GAME_RAIDEN) + common_decrypt(); + + nRet = BurnLoadRom(RomZ80 + 0x000000, 6, 1); if (nRet != 0) return 1; + + if (game_drv == GAME_RAIDENA || game_drv == GAME_RAIDENT) + seibu_sound_decrypt(); + + UINT8 * tmp = (UINT8 *) BurnMalloc (0x80000); + if (tmp == 0) return 1; + + BurnLoadRom(tmp + 0x00000, 7, 1); + BurnLoadRom(tmp + 0x08000, 8, 1); + decode_gfx_1(RomGfx1, tmp); + + BurnLoadRom(tmp + 0x00000, 9, 1); + decode_gfx_2(RomGfx2, tmp); + BurnLoadRom(tmp + 0x00000, 10, 1); + decode_gfx_2(RomGfx3, tmp); + BurnLoadRom(tmp + 0x00000, 11, 1); + decode_gfx_2(RomGfx4, tmp); + + BurnFree (tmp); + + BurnLoadRom(MSM6295ROM, 12, 1); + + { + VezInit(0, V30_TYPE); + VezInit(1, V30_TYPE); + + // main-cpu + VezOpen(0); + + VezMapArea(0x00000, 0x06fff, 0, RamV30A); // RAM + VezMapArea(0x00000, 0x06fff, 1, RamV30A); + + VezMapArea(0x07000, 0x07fff, 0, RamSpr); // Sprites + VezMapArea(0x07000, 0x07fff, 1, RamSpr); + + VezMapArea(0x0c000, 0x0c7ff, 1, (UINT8 *)RamTxt); + + VezMapArea(0xA0000, 0xFFFFF, 0, RomV30A); // CPU 0 ROM + VezMapArea(0xA0000, 0xFFFFF, 2, RomV30A); // CPU 0 ROM + + if (game_drv == GAME_RAIDEN) { + VezMapArea(0x0a000, 0x0afff, 0, RamV30S); // Share RAM + VezMapArea(0x0a000, 0x0afff, 1, RamV30S); + VezSetReadHandler(raidenReadByte); + VezSetWriteHandler(raidenWriteByte); + } else { + VezMapArea(0x08000, 0x08fff, 0, RamV30S); // Share RAM + VezMapArea(0x08000, 0x08fff, 1, RamV30S); + VezSetReadHandler(raidenAltReadByte); + VezSetWriteHandler(raidenAltWriteByte); + } + + VezClose(); + + // sub-cpu + VezOpen(1); + + VezMapArea(0x00000, 0x01fff, 0, RamV30B); // RAM + VezMapArea(0x00000, 0x01fff, 1, RamV30B); + + VezMapArea(0x02000, 0x027ff, 0, (UINT8 *)RamBg); // Background + VezMapArea(0x02000, 0x027ff, 1, (UINT8 *)RamBg); + + VezMapArea(0x02800, 0x02fff, 0, (UINT8 *)RamFg); // Foreground + VezMapArea(0x02800, 0x02fff, 1, (UINT8 *)RamFg); + + VezMapArea(0x03000, 0x03fff, 0, RamPal); // Palette + //VezMapArea(0x03000, 0x03fff, 1, RamPal); + + VezMapArea(0x04000, 0x04fff, 0, RamV30S); // Share RAM + VezMapArea(0x04000, 0x04fff, 1, RamV30S); + + VezMapArea(0xC0000, 0xFFFFF, 0, RomV30B); // CPU 1 ROM + VezMapArea(0xC0000, 0xFFFFF, 2, RomV30B); // CPU 1 ROM + + VezSetReadHandler(raidenSubReadByte); + VezSetWriteHandler(raidenSubWriteByte); + + VezClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetMapArea(0x0000, 0x1FFF, 0, RomZ80); + + if (game_drv == GAME_RAIDENA || game_drv == GAME_RAIDENT) + ZetMapArea(0x0000, 0x1FFF, 2, RomZ80 + 0x10000, RomZ80); + else + ZetMapArea(0x0000, 0x1FFF, 2, RomZ80); + + ZetMapArea(0x2000, 0x27FF, 0, RamZ80); + ZetMapArea(0x2000, 0x27FF, 1, RamZ80); + ZetMapArea(0x2000, 0x27FF, 2, RamZ80); + + //ZetMapArea(0x8000, 0xFFFF, 0, RomZ80 + 0x8000); + //ZetMapArea(0x8000, 0xFFFF, 2, RomZ80 + 0x8000); + //use set_seibu_bank(0); in DrvDoReset(); + + ZetMemEnd(); + + ZetSetReadHandler(raidenZ80Read); + ZetSetWriteHandler(raidenZ80Write); + ZetClose(); + + } + + BurnYM3812Init(3579545, &raidenFMIRQHandler, &raidenSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + MSM6295Init(0, 8000, 80.0, 1); // 1320000 + DrvDoReset(); + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM3812Exit(); + + VezExit(); + ZetExit(); + + BurnFree(Mem); + + return 0; +} + +static void drawBackground() +{ + /* cccc tttt tttt tttt */ + UINT16 * pal = RamCurPal + 0; + INT32 offs, mx, my, x, y, sx, sy; + + if (game_drv == GAME_RAIDEN) { + sx = (RamScroll[0] | (RamScroll[1] << 8)) & 0x1ff; + sy = (RamScroll[2] | (RamScroll[3] << 8)) & 0x1ff; + } else { + sx = ((RamScroll[2]&0x10)<<4) | ((RamScroll[3]&0x7f) << 1) | ((RamScroll[3]&0x80) >> 7); + sy = ((RamScroll[0]&0x10)<<4) | ((RamScroll[1]&0x7f) << 1) | ((RamScroll[1]&0x80) >> 7); + } + + mx = 0; + my = -1; + for (offs = 0; offs < 32*32; offs++) { + my++; + if (my == 32) { + my = 0; + mx++; + } + + x = mx * 16 - 0 - sx; + if (x < -16) x += 512; + + y = my * 16 - 16 - sy; + if (y < -16) y += 512; + + if (x<=-16 || x>=256 || y<=-16 || y>=224) continue; + else { + UINT32 tileno = RamBg[offs] & 0x0FFF; + //if (tileno == 0) continue; + UINT32 c = (RamBg[offs] & 0xF000) >> 8; + UINT16 * p = (UINT16 *) pBurnDraw + y * 256 + x; + UINT8 *d = RomGfx2 + (tileno << 8); + + if (x<0 || x>(256-16) || y<0 || y>(224-16)) + for (INT32 k=0;k<16;k++) { + if ((y+k)>=0 && (y+k)<224) { + if ((x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[ 0]|c]; + if ((x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[ 1]|c]; + if ((x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[ 2]|c]; + if ((x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[ 3]|c]; + if ((x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[ 4]|c]; + if ((x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[ 5]|c]; + if ((x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 6]|c]; + if ((x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 7]|c]; + if ((x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 8]|c]; + if ((x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 9]|c]; + if ((x+10)>=0 && (x+10)<256) p[10] = pal[d[10]|c]; + if ((x+11)>=0 && (x+11)<256) p[11] = pal[d[11]|c]; + if ((x+12)>=0 && (x+12)<256) p[12] = pal[d[12]|c]; + if ((x+13)>=0 && (x+13)<256) p[13] = pal[d[13]|c]; + if ((x+14)>=0 && (x+14)<256) p[14] = pal[d[14]|c]; + if ((x+15)>=0 && (x+15)<256) p[15] = pal[d[15]|c]; + } + d += 16; + p += 256; + } + else + for (INT32 k=0;k<16;k++) { + p[ 0] = pal[d[ 0]|c]; + p[ 1] = pal[d[ 1]|c]; + p[ 2] = pal[d[ 2]|c]; + p[ 3] = pal[d[ 3]|c]; + p[ 4] = pal[d[ 4]|c]; + p[ 5] = pal[d[ 5]|c]; + p[ 6] = pal[d[ 6]|c]; + p[ 7] = pal[d[ 7]|c]; + p[ 8] = pal[d[ 8]|c]; + p[ 9] = pal[d[ 9]|c]; + p[10] = pal[d[10]|c]; + p[11] = pal[d[11]|c]; + p[12] = pal[d[12]|c]; + p[13] = pal[d[13]|c]; + p[14] = pal[d[14]|c]; + p[15] = pal[d[15]|c]; + + d += 16; + p += 256; + } + } + } +} + +static void drawForeground() +{ + /* cccc tttt tttt tttt */ + UINT16 * pal = RamCurPal + 256; + INT32 offs, mx, my, x, y, sx, sy; + + if (game_drv == GAME_RAIDEN) { + sx = (RamScroll[4] | (RamScroll[5] << 8)) & 0x1ff; + sy = (RamScroll[6] | (RamScroll[7] << 8)) & 0x1ff; + } else { + sx = ((RamScroll[6]&0x10)<<4) | ((RamScroll[7]&0x7f) << 1) | ((RamScroll[7]&0x80) >> 7); + sy = ((RamScroll[4]&0x10)<<4) | ((RamScroll[5]&0x7f) << 1) | ((RamScroll[5]&0x80) >> 7); + } + + mx = 0; + my = -1; + for (offs = 0; offs < 32*32; offs++) { + my++; + if (my == 32) { + my = 0; + mx++; + } + + x = mx * 16 - 0 - sx; + if (x < -16) x += 512; + + y = my * 16 - 16 - sy; + if (y < -16) y += 512; + + if (x<=-16 || x>=256 || y<=-16 || y>=224) continue; + else { + UINT32 tileno = RamFg[offs] & 0x0FFF; + if (tileno == 0) continue; + UINT32 c = (RamFg[offs] & 0xF000) >> 8; + UINT16 * p = (UINT16 *) pBurnDraw + y * 256 + x; + UINT8 *d = RomGfx3 + (tileno << 8); + + if (x<0 || x>(256-16) || y<0 || y>(224-16)) + for (INT32 k=0;k<16;k++) { + if ((y+k)>=0 && (y+k)<224) { + if (d[ 0]!=15 && (x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[ 0]|c]; + if (d[ 1]!=15 && (x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[ 1]|c]; + if (d[ 2]!=15 && (x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[ 2]|c]; + if (d[ 3]!=15 && (x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[ 3]|c]; + if (d[ 4]!=15 && (x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[ 4]|c]; + if (d[ 5]!=15 && (x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[ 5]|c]; + if (d[ 6]!=15 && (x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 6]|c]; + if (d[ 7]!=15 && (x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 7]|c]; + if (d[ 8]!=15 && (x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 8]|c]; + if (d[ 9]!=15 && (x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 9]|c]; + if (d[10]!=15 && (x+10)>=0 && (x+10)<256) p[10] = pal[d[10]|c]; + if (d[11]!=15 && (x+11)>=0 && (x+11)<256) p[11] = pal[d[11]|c]; + if (d[12]!=15 && (x+12)>=0 && (x+12)<256) p[12] = pal[d[12]|c]; + if (d[13]!=15 && (x+13)>=0 && (x+13)<256) p[13] = pal[d[13]|c]; + if (d[14]!=15 && (x+14)>=0 && (x+14)<256) p[14] = pal[d[14]|c]; + if (d[15]!=15 && (x+15)>=0 && (x+15)<256) p[15] = pal[d[15]|c]; + } + d += 16; + p += 256; + } + else + for (INT32 k=0;k<16;k++) { + if (d[ 0] != 15) p[ 0] = pal[d[ 0]|c]; + if (d[ 1] != 15) p[ 1] = pal[d[ 1]|c]; + if (d[ 2] != 15) p[ 2] = pal[d[ 2]|c]; + if (d[ 3] != 15) p[ 3] = pal[d[ 3]|c]; + if (d[ 4] != 15) p[ 4] = pal[d[ 4]|c]; + if (d[ 5] != 15) p[ 5] = pal[d[ 5]|c]; + if (d[ 6] != 15) p[ 6] = pal[d[ 6]|c]; + if (d[ 7] != 15) p[ 7] = pal[d[ 7]|c]; + if (d[ 8] != 15) p[ 8] = pal[d[ 8]|c]; + if (d[ 9] != 15) p[ 9] = pal[d[ 9]|c]; + if (d[10] != 15) p[10] = pal[d[10]|c]; + if (d[11] != 15) p[11] = pal[d[11]|c]; + if (d[12] != 15) p[12] = pal[d[12]|c]; + if (d[13] != 15) p[13] = pal[d[13]|c]; + if (d[14] != 15) p[14] = pal[d[14]|c]; + if (d[15] != 15) p[15] = pal[d[15]|c]; + + d += 16; + p += 256; + } + } + } +} + +static void drawSprites(INT32 pri) +{ + /* yyyyyyyy -ff-CCCC tttttttt ----TTTT xxxxxxxx PP-----X -------- EEEEEEEE */ + UINT16 * pal = RamCurPal + 512; + + for(UINT8 * pSpr = RamSpr + 0x1000 - 8; pSpr>=RamSpr; pSpr-=8 ) { + + if (pSpr[7]!=0xf) continue; + if (!(pri & pSpr[5])) continue; + + INT32 fx= pSpr[1] & 0x20; + INT32 fy= pSpr[1] & 0x40; + INT32 y = pSpr[0] - 16; + INT32 x = pSpr[4]; + + if (pSpr[5]&1) x = 0 - (0x100-x); + + INT32 c = (pSpr[1] & 0xf) << 4; + INT32 sprite = (pSpr[2] | (pSpr[3] << 8)) & 0x0fff; + + if (x<=-16 || x>=256 || y<=-16 || y>=224) continue; + else { + + UINT8 *d = RomGfx4 + (sprite << 8); + UINT16 * p = (UINT16 *) pBurnDraw ; + p += y * 256 + x; + + if (x<0 || x>(256-16) || y<0 || y>(224-16)) { + + + if ( fy ) { + p += 256 * 15; + + if ( fx ) + for (INT32 k=15;k>=0;k--) { + if ((y+k)>=0 && (y+k)<224) { + if (d[15]!=15 && (x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[15]|c]; + if (d[14]!=15 && (x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[14]|c]; + if (d[13]!=15 && (x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[13]|c]; + if (d[12]!=15 && (x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[12]|c]; + if (d[11]!=15 && (x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[11]|c]; + if (d[10]!=15 && (x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[10]|c]; + if (d[ 9]!=15 && (x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 9]|c]; + if (d[ 8]!=15 && (x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 8]|c]; + if (d[ 7]!=15 && (x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 7]|c]; + if (d[ 6]!=15 && (x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 6]|c]; + if (d[ 5]!=15 && (x+10)>=0 && (x+10)<256) p[10] = pal[d[ 5]|c]; + if (d[ 4]!=15 && (x+11)>=0 && (x+11)<256) p[11] = pal[d[ 4]|c]; + if (d[ 3]!=15 && (x+12)>=0 && (x+12)<256) p[12] = pal[d[ 3]|c]; + if (d[ 2]!=15 && (x+13)>=0 && (x+13)<256) p[13] = pal[d[ 2]|c]; + if (d[ 1]!=15 && (x+14)>=0 && (x+14)<256) p[14] = pal[d[ 1]|c]; + if (d[ 0]!=15 && (x+15)>=0 && (x+15)<256) p[15] = pal[d[ 0]|c]; + } + d += 16; + p -= 256; + } + else + for (INT32 k=15;k>=0;k--) { + if ((y+k)>=0 && (y+k)<224) { + if (d[ 0]!=15 && (x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[ 0]|c]; + if (d[ 1]!=15 && (x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[ 1]|c]; + if (d[ 2]!=15 && (x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[ 2]|c]; + if (d[ 3]!=15 && (x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[ 3]|c]; + if (d[ 4]!=15 && (x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[ 4]|c]; + if (d[ 5]!=15 && (x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[ 5]|c]; + if (d[ 6]!=15 && (x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 6]|c]; + if (d[ 7]!=15 && (x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 7]|c]; + if (d[ 8]!=15 && (x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 8]|c]; + if (d[ 9]!=15 && (x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 9]|c]; + if (d[10]!=15 && (x+10)>=0 && (x+10)<256) p[10] = pal[d[10]|c]; + if (d[11]!=15 && (x+11)>=0 && (x+11)<256) p[11] = pal[d[11]|c]; + if (d[12]!=15 && (x+12)>=0 && (x+12)<256) p[12] = pal[d[12]|c]; + if (d[13]!=15 && (x+13)>=0 && (x+13)<256) p[13] = pal[d[13]|c]; + if (d[14]!=15 && (x+14)>=0 && (x+14)<256) p[14] = pal[d[14]|c]; + if (d[15]!=15 && (x+15)>=0 && (x+15)<256) p[15] = pal[d[15]|c]; + } + d += 16; + p -= 256; + } + + } else { + + if ( fx ) + for (INT32 k=0;k<16;k++) { + if ((y+k)>=0 && (y+k)<224) { + if (d[15]!=15 && (x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[15]|c]; + if (d[14]!=15 && (x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[14]|c]; + if (d[13]!=15 && (x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[13]|c]; + if (d[12]!=15 && (x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[12]|c]; + if (d[11]!=15 && (x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[11]|c]; + if (d[10]!=15 && (x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[10]|c]; + if (d[ 9]!=15 && (x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 9]|c]; + if (d[ 8]!=15 && (x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 8]|c]; + if (d[ 7]!=15 && (x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 7]|c]; + if (d[ 6]!=15 && (x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 6]|c]; + if (d[ 5]!=15 && (x+10)>=0 && (x+10)<256) p[10] = pal[d[ 5]|c]; + if (d[ 4]!=15 && (x+11)>=0 && (x+11)<256) p[11] = pal[d[ 4]|c]; + if (d[ 3]!=15 && (x+12)>=0 && (x+12)<256) p[12] = pal[d[ 3]|c]; + if (d[ 2]!=15 && (x+13)>=0 && (x+13)<256) p[13] = pal[d[ 2]|c]; + if (d[ 1]!=15 && (x+14)>=0 && (x+14)<256) p[14] = pal[d[ 1]|c]; + if (d[ 0]!=15 && (x+15)>=0 && (x+15)<256) p[15] = pal[d[ 0]|c]; + } + d += 16; + p += 256; + } + else + for (INT32 k=0;k<16;k++) { + if ((y+k)>=0 && (y+k)<224) { + if (d[ 0]!=15 && (x+ 0)>=0 && (x+ 0)<256) p[ 0] = pal[d[ 0]|c]; + if (d[ 1]!=15 && (x+ 1)>=0 && (x+ 1)<256) p[ 1] = pal[d[ 1]|c]; + if (d[ 2]!=15 && (x+ 2)>=0 && (x+ 2)<256) p[ 2] = pal[d[ 2]|c]; + if (d[ 3]!=15 && (x+ 3)>=0 && (x+ 3)<256) p[ 3] = pal[d[ 3]|c]; + if (d[ 4]!=15 && (x+ 4)>=0 && (x+ 4)<256) p[ 4] = pal[d[ 4]|c]; + if (d[ 5]!=15 && (x+ 5)>=0 && (x+ 5)<256) p[ 5] = pal[d[ 5]|c]; + if (d[ 6]!=15 && (x+ 6)>=0 && (x+ 6)<256) p[ 6] = pal[d[ 6]|c]; + if (d[ 7]!=15 && (x+ 7)>=0 && (x+ 7)<256) p[ 7] = pal[d[ 7]|c]; + if (d[ 8]!=15 && (x+ 8)>=0 && (x+ 8)<256) p[ 8] = pal[d[ 8]|c]; + if (d[ 9]!=15 && (x+ 9)>=0 && (x+ 9)<256) p[ 9] = pal[d[ 9]|c]; + if (d[10]!=15 && (x+10)>=0 && (x+10)<256) p[10] = pal[d[10]|c]; + if (d[11]!=15 && (x+11)>=0 && (x+11)<256) p[11] = pal[d[11]|c]; + if (d[12]!=15 && (x+12)>=0 && (x+12)<256) p[12] = pal[d[12]|c]; + if (d[13]!=15 && (x+13)>=0 && (x+13)<256) p[13] = pal[d[13]|c]; + if (d[14]!=15 && (x+14)>=0 && (x+14)<256) p[14] = pal[d[14]|c]; + if (d[15]!=15 && (x+15)>=0 && (x+15)<256) p[15] = pal[d[15]|c]; + } + d += 16; + p += 256; + } + } + + } else { + + if ( fy ) { + + p += 256 * 15; + + if ( fx ) { + + for (INT32 k=15;k>=0;k--) { + if (d[15] != 15) p[ 0] = pal[d[15]|c]; + if (d[14] != 15) p[ 1] = pal[d[14]|c]; + if (d[13] != 15) p[ 2] = pal[d[13]|c]; + if (d[12] != 15) p[ 3] = pal[d[12]|c]; + if (d[11] != 15) p[ 4] = pal[d[11]|c]; + if (d[10] != 15) p[ 5] = pal[d[10]|c]; + if (d[ 9] != 15) p[ 6] = pal[d[ 9]|c]; + if (d[ 8] != 15) p[ 7] = pal[d[ 8]|c]; + if (d[ 7] != 15) p[ 8] = pal[d[ 7]|c]; + if (d[ 6] != 15) p[ 9] = pal[d[ 6]|c]; + if (d[ 5] != 15) p[10] = pal[d[ 5]|c]; + if (d[ 4] != 15) p[11] = pal[d[ 4]|c]; + if (d[ 3] != 15) p[12] = pal[d[ 3]|c]; + if (d[ 2] != 15) p[13] = pal[d[ 2]|c]; + if (d[ 1] != 15) p[14] = pal[d[ 1]|c]; + if (d[ 0] != 15) p[15] = pal[d[ 0]|c]; + + d += 16; + p -= 256; + } + + } else { + + for (INT32 k=15;k>=0;k--) { + if (d[ 0] != 15) p[ 0] = pal[d[ 0]|c]; + if (d[ 1] != 15) p[ 1] = pal[d[ 1]|c]; + if (d[ 2] != 15) p[ 2] = pal[d[ 2]|c]; + if (d[ 3] != 15) p[ 3] = pal[d[ 3]|c]; + if (d[ 4] != 15) p[ 4] = pal[d[ 4]|c]; + if (d[ 5] != 15) p[ 5] = pal[d[ 5]|c]; + if (d[ 6] != 15) p[ 6] = pal[d[ 6]|c]; + if (d[ 7] != 15) p[ 7] = pal[d[ 7]|c]; + if (d[ 8] != 15) p[ 8] = pal[d[ 8]|c]; + if (d[ 9] != 15) p[ 9] = pal[d[ 9]|c]; + if (d[10] != 15) p[10] = pal[d[10]|c]; + if (d[11] != 15) p[11] = pal[d[11]|c]; + if (d[12] != 15) p[12] = pal[d[12]|c]; + if (d[13] != 15) p[13] = pal[d[13]|c]; + if (d[14] != 15) p[14] = pal[d[14]|c]; + if (d[15] != 15) p[15] = pal[d[15]|c]; + + d += 16; + p -= 256; + } + + } + + } else { + + if ( fx ) { + + for (INT32 k=0;k<16;k++) { + if (d[15] != 15) p[ 0] = pal[d[15]|c]; + if (d[14] != 15) p[ 1] = pal[d[14]|c]; + if (d[13] != 15) p[ 2] = pal[d[13]|c]; + if (d[12] != 15) p[ 3] = pal[d[12]|c]; + if (d[11] != 15) p[ 4] = pal[d[11]|c]; + if (d[10] != 15) p[ 5] = pal[d[10]|c]; + if (d[ 9] != 15) p[ 6] = pal[d[ 9]|c]; + if (d[ 8] != 15) p[ 7] = pal[d[ 8]|c]; + if (d[ 7] != 15) p[ 8] = pal[d[ 7]|c]; + if (d[ 6] != 15) p[ 9] = pal[d[ 6]|c]; + if (d[ 5] != 15) p[10] = pal[d[ 5]|c]; + if (d[ 4] != 15) p[11] = pal[d[ 4]|c]; + if (d[ 3] != 15) p[12] = pal[d[ 3]|c]; + if (d[ 2] != 15) p[13] = pal[d[ 2]|c]; + if (d[ 1] != 15) p[14] = pal[d[ 1]|c]; + if (d[ 0] != 15) p[15] = pal[d[ 0]|c]; + + d += 16; + p += 256; + } + + } else { + + for (INT32 k=0;k<16;k++) { + if (d[ 0] != 15) p[ 0] = pal[d[ 0]|c]; + if (d[ 1] != 15) p[ 1] = pal[d[ 1]|c]; + if (d[ 2] != 15) p[ 2] = pal[d[ 2]|c]; + if (d[ 3] != 15) p[ 3] = pal[d[ 3]|c]; + if (d[ 4] != 15) p[ 4] = pal[d[ 4]|c]; + if (d[ 5] != 15) p[ 5] = pal[d[ 5]|c]; + if (d[ 6] != 15) p[ 6] = pal[d[ 6]|c]; + if (d[ 7] != 15) p[ 7] = pal[d[ 7]|c]; + if (d[ 8] != 15) p[ 8] = pal[d[ 8]|c]; + if (d[ 9] != 15) p[ 9] = pal[d[ 9]|c]; + if (d[10] != 15) p[10] = pal[d[10]|c]; + if (d[11] != 15) p[11] = pal[d[11]|c]; + if (d[12] != 15) p[12] = pal[d[12]|c]; + if (d[13] != 15) p[13] = pal[d[13]|c]; + if (d[14] != 15) p[14] = pal[d[14]|c]; + if (d[15] != 15) p[15] = pal[d[15]|c]; + + d += 16; + p += 256; + } + + } + + } + } + } + + } + +} + +static void drawText() +{ + /* TT-- cccc tttt tttt */ + UINT16 * pal = RamCurPal + 768; + INT32 offs, mx, my, x, y; + + mx = 0; + my = -1; + for (offs = 0; offs < 32*32; offs++) { + my++; + if (my == 32) { + my = 0; + mx++; + } + x = mx * 8; + y = my * 8 - 16; + + if ( y<0 || y>=224) continue; + else { + UINT32 tileno = (RamTxt[offs] & 0x00FF) | ((RamTxt[offs] & 0xC000) >> 6); + if (tileno == 0) continue; + UINT32 c = (RamTxt[offs] & 0x0F00) >> 4; + UINT16 * p = (UINT16 *) pBurnDraw + y * 256 + x; + UINT8 *d = RomGfx1 + (tileno << 6); + + for (INT32 k=0;k<8;k++) { + if (d[0] != 15) p[0] = pal[d[0]|c]; + if (d[1] != 15) p[1] = pal[d[1]|c]; + if (d[2] != 15) p[2] = pal[d[2]|c]; + if (d[3] != 15) p[3] = pal[d[3]|c]; + if (d[4] != 15) p[4] = pal[d[4]|c]; + if (d[5] != 15) p[5] = pal[d[5]|c]; + if (d[6] != 15) p[6] = pal[d[6]|c]; + if (d[7] != 15) p[7] = pal[d[7]|c]; + d += 8; + p += 256; + } + } + } +} + +static void drawTextAlt() +{ + /* TT-- cccc tttt tttt */ + UINT16 * pal = RamCurPal + 768; + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 32*32; offs++) { + mx++; + if (mx == 32) { + mx = 0; + my++; + } + x = mx * 8; + y = my * 8 - 16; + + if ( y<0 || y>=224) continue; + else { + UINT32 tileno = (RamTxt[offs] & 0x00FF) | ((RamTxt[offs] & 0xC000) >> 6); + if (tileno == 0) continue; + UINT32 c = (RamTxt[offs] & 0x0F00) >> 4; + UINT16 * p = (UINT16 *) pBurnDraw + y * 256 + x; + UINT8 *d = RomGfx1 + (tileno << 6); + + for (INT32 k=0;k<8;k++) { + if (d[0] != 15) p[0] = pal[d[0]|c]; + if (d[1] != 15) p[1] = pal[d[1]|c]; + if (d[2] != 15) p[2] = pal[d[2]|c]; + if (d[3] != 15) p[3] = pal[d[3]|c]; + if (d[4] != 15) p[4] = pal[d[4]|c]; + if (d[5] != 15) p[5] = pal[d[5]|c]; + if (d[6] != 15) p[6] = pal[d[6]|c]; + if (d[7] != 15) p[7] = pal[d[7]|c]; + d += 8; + p += 256; + } + } + } +} + +static void DrvDraw() +{ + drawBackground(); + drawSprites(0x40); + drawForeground(); + drawSprites(0x80); + drawText(); +} + +static INT32 DrvFrame() +{ + if (DrvReset) DrvDoReset(); + + if (bRecalcPalette) { + for (INT32 i=0;i<(0x1000/2);i++) + RamCurPal[i] = CalcCol(i << 1); + bRecalcPalette = 0; + } + + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Joy1 + DrvInput[2] = 0x00; // Joy2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvButton[i] & 1) << i; + DrvInput[1] |= (DrvJoy1[i] & 1) << i; + DrvInput[2] |= (DrvJoy2[i] & 1) << i; + } + + VezNewFrame(); + ZetNewFrame(); + + for (INT32 i=0; i<200; i++) { + VezOpen(0); + VezRun(10000000 / 60 / 200); + VezOpen(1); + VezRun(10000000 / 60 / 200); + ZetOpen(0); + BurnTimerUpdateYM3812(i * ((3579545 / 60) / 200)); + ZetClose(); + } + + VezOpen(0); + VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + + VezOpen(1); + VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + +// ZetOpen(0); +// ZetRun( 3579545 / 60 ); +// ZetClose(); + + if (pBurnDraw) DrvDraw(); + + ZetOpen(0); + BurnTimerEndFrameYM3812(3579545 / 60); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + return 0; +} + +static void DrvDrawAlt() +{ + drawBackground(); + drawSprites(0x40); + drawForeground(); + drawSprites(0x80); + drawTextAlt(); +} + +static INT32 DrvFrameAlt() +{ + if (DrvReset) DrvDoReset(); + + if (bRecalcPalette) { + for (INT32 i=0;i<(0x1000/2);i++) + RamCurPal[i] = CalcCol(i << 1); + bRecalcPalette = 0; + } + + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Joy1 + DrvInput[2] = 0x00; // Joy2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvButton[i] & 1) << i; + DrvInput[1] |= (DrvJoy1[i] & 1) << i; + DrvInput[2] |= (DrvJoy2[i] & 1) << i; + } + + VezNewFrame(); + ZetNewFrame(); + + for (INT32 i=0; i<120; i++) { + VezOpen(0); + VezRun(10000000 / 60 / 120); + VezOpen(1); + VezRun(10000000 / 60 / 120); + } + + VezOpen(0); + VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + + VezOpen(1); + VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + +// ZetOpen(0); +// ZetRun( 3579545 / 60 ); +// ZetClose(); + + if (pBurnDraw) DrvDrawAlt(); + + ZetOpen(0); + BurnTimerEndFrameYM3812(3579545 / 60); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + if ( pnMin ) *pnMin = 0x029671; + + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + if (nAction & ACB_WRITE) + bRecalcPalette = 1; + } + + if (nAction & ACB_DRIVER_DATA) { + + VezScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + INT32 cbank; + if (nAction & ACB_WRITE) { + SCAN_VAR(cbank); + set_seibu_bank(cbank); + } else { + cbank = seibu_bank; + SCAN_VAR(cbank); + } + + SCAN_VAR(DrvInput); + + SCAN_VAR(main2sub); + SCAN_VAR(sub2main); + SCAN_VAR(main2sub_pending); + SCAN_VAR(sub2main_pending); + SCAN_VAR(z80_irq1); + SCAN_VAR(z80_irq2); + } + + return 0; +} + +struct BurnDriver BurnDrvRaiden = { + "raiden", NULL, NULL, NULL, "1990", + "Raiden\0", NULL, "Seibu Kaihatsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, raidenRomInfo, raidenRomName, NULL, NULL, raidenInputInfo, raidenDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, &bRecalcPalette, 0x1000, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRaidena = { + "raidena", "raiden", NULL, NULL, "1990", + "Raiden (Alternate Hardware)\0", NULL, "Seibu Kaihatsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, raidenaRomInfo, raidenaRomName, NULL, NULL, raidenInputInfo, raidenDIPInfo, + DrvInit, DrvExit, DrvFrameAlt, NULL, DrvScan, &bRecalcPalette, 0x1000, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRaidenk = { + "raidenk", "raiden", NULL, NULL, "1990", + "Raiden (Korea)\0", NULL, "Seibu Kaihatsu (IBL Corporation license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, raidenkRomInfo, raidenkRomName, NULL, NULL, raidenInputInfo, raidenDIPInfo, + DrvInit, DrvExit, DrvFrameAlt, NULL, DrvScan, &bRecalcPalette, 0x1000, + 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRaident = { + "raident", "raiden", NULL, NULL, "1990", + "Raiden (Taiwan)\0", NULL, "Seibu Kaihatsu (Liang HWA Electronics license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, raidentRomInfo, raidentRomName, NULL, NULL, raidenInputInfo, raidenDIPInfo, + DrvInit, DrvExit, DrvFrameAlt, NULL, DrvScan, &bRecalcPalette, 0x1000, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_rohga.cpp b/src/burn/drivers/misc_post90s/d_rohga.cpp new file mode 100644 index 00000000..c0d80964 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_rohga.cpp @@ -0,0 +1,2286 @@ +// FB Alpha Rohga Armor Force / Wizard Fire / Nitro Ball / Schmeiser Robo driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalBuf; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprRAM2; +static UINT8 *DrvSprBuf; +static UINT8 *DrvSprBuf2; +static UINT8 *DrvPrtRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT16 DrvInputs[4]; + +static UINT16 *tempdraw[2]; + +static INT32 DrvOkiBank; + +static struct BurnInputInfo RohgaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Rohga) + +static struct BurnInputInfo WizdfireInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Wizdfire) + +static struct BurnInputInfo NitrobalInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p3 coin" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Nitrobal) + +static struct BurnDIPInfo RohgaDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Credits to Start, 1 to Continue" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Player's Vitality" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x20, "Low" }, + {0x15, 0x01, 0x30, 0x10, "Lowest" }, + {0x15, 0x01, 0x30, 0x00, "High" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Stage Clear Bonus" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Enemy's Vitality" }, + {0x16, 0x01, 0x0c, 0x08, "Low" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "High" }, + {0x16, 0x01, 0x0c, 0x00, "Highest" }, + + {0 , 0xfe, 0 , 4, "Enemy Encounter Rate" }, + {0x16, 0x01, 0x30, 0x20, "Low" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x10, "High" }, + {0x16, 0x01, 0x30, 0x00, "Highest" }, + + {0 , 0xfe, 0 , 4, "Enemy's Weapon Speed" }, + {0x16, 0x01, 0xc0, 0x80, "Slow" }, + {0x16, 0x01, 0xc0, 0xc0, "Normal" }, + {0x16, 0x01, 0xc0, 0x40, "Fast" }, + {0x16, 0x01, 0xc0, 0x00, "Fastest" }, +}; + +STDDIPINFO(Rohga) + +static struct BurnDIPInfo SchmeisrDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x04, 0x00, "Off" }, + {0x15, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze Screen" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Schmeisr) + +static struct BurnDIPInfo WizdfireDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Credits to Start, 1 to Continue" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x00, "2" }, + {0x13, 0x01, 0x03, 0x01, "3" }, + {0x13, 0x01, 0x03, 0x03, "4" }, + {0x13, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Magic Gauge Speed" }, + {0x13, 0x01, 0x30, 0x00, "Very Slow" }, + {0x13, 0x01, 0x30, 0x10, "Slow" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + {0x13, 0x01, 0x30, 0x20, "Fast" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Wizdfire) + +static struct BurnDIPInfo NitrobalDIPList[]= +{ + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x19, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x19, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x19, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x19, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x19, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x19, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x19, 0x01, 0x40, 0x40, "Off" }, + {0x19, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "2 Credits to Start, 1 to Continue" }, + {0x19, 0x01, 0x80, 0x80, "Off" }, + {0x19, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x1a, 0x01, 0x03, 0x01, "1" }, + {0x1a, 0x01, 0x03, 0x00, "2" }, + {0x1a, 0x01, 0x03, 0x03, "3" }, + {0x1a, 0x01, 0x03, 0x02, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty?" }, + {0x1a, 0x01, 0x0c, 0x08, "Easy" }, + {0x1a, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1a, 0x01, 0x0c, 0x04, "Hard" }, + {0x1a, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Split Coin Chutes" }, + {0x1a, 0x01, 0x10, 0x10, "Off" }, + {0x1a, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Players" }, + {0x1a, 0x01, 0x20, 0x20, "2" }, + {0x1a, 0x01, 0x20, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Shot Button to Start" }, + {0x1a, 0x01, 0x40, 0x40, "Off" }, + {0x1a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1a, 0x01, 0x80, 0x80, "Off" }, + {0x1a, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Nitrobal) + +void __fastcall rohga_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x200000, data) + deco16_write_control_word(1, address, 0x240000, data) + + switch (address) + { + case 0x2800a8: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + + case 0x300000: + memcpy (DrvSprBuf2, DrvSprBuf, 0x800); + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x31000a: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + + case 0x321100: // schmeisr + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + + case 0x322000: + deco16_priority = data; + return; + } + + if ((address & 0xffff000) == 0x280000) { + deco16_104_rohga_prot_w(address, data, 0xffff); + + return; + } +} + +void __fastcall rohga_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x2800a8: + case 0x2800a9: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + + case 0x300000: + case 0x300001: + memcpy (DrvSprBuf2, DrvSprBuf, 0x800); + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x31000a: + case 0x31000b: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + + case 0x321100: // schmeisr + case 0x321101: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + + case 0x322000: + case 0x322001: + deco16_priority = data; + return; + } + + if ((address & 0xffff000) == 0x280000) { + deco16_104_rohga_prot_w(address, data, 0x00ff << ((address & 1) << 3)); + return; + } +} + +UINT16 __fastcall rohga_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x2c0000: + case 0x300000: // schmeisr + return DrvDips[2]; + + case 0x310002: // schmeisr + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x321100: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return 0; + } + + if ((address & 0xffff000) == 0x280000) { + return deco16_104_rohga_prot_r(address); + } + + return 0; +} + +UINT8 __fastcall rohga_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x2c0000: + case 0x2c0001: + case 0x300000: // schmeisr + case 0x300001: + return DrvDips[2]; + + case 0x310002: // schmeisr + case 0x310003: + return (DrvInputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x321100: + case 0x321101: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return 0; + } + + if ((address & 0xffff000) == 0x280000) { + return deco16_104_rohga_prot_r(address) >> ((~address & 1) << 3); + } + + return 0; +} + +void __fastcall wizdfire_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x300000, data) + deco16_write_control_word(1, address, 0x310000, data) + + switch (address) + { + case 0x350000: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x370000: + memcpy (DrvSprBuf2, DrvSprRAM2, 0x800); + return; + + case 0x380008: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + + case 0x320000: + deco16_priority = data; + return; + + case 0x320004: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + + case 0xfe4150: + case 0xff4260: // nitrobal + case 0xff4a60: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + } + + if ((address & 0xffff000) == 0xfe4000) { + deco16_prot_ram[(address & 0x7ff)/2] = data; + return; + } + + if ((address & 0xffff000) == 0xff4000) { + deco16_146_nitroball_prot_w(address, data, 0xffff); + return; + } +} + +void __fastcall wizdfire_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x350000: + case 0x350001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x370000: + case 0x370001: + memcpy (DrvSprBuf2, DrvSprRAM2, 0x800); + return; + + case 0x380008: + case 0x380009: + memcpy (DrvPalBuf, DrvPalRAM, 0x2000); + return; + + case 0x320000: + case 0x320001: + deco16_priority = data; + return; + + + case 0x320004: + case 0x320005: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + + case 0xfe4150: + case 0xfe4151: + case 0xff4260: // nitrobal + case 0xff4261: + case 0xff4a61: + case 0xff4a60: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + } + + if ((address & 0xffff000) == 0xfe4000) { + DrvPrtRAM[(address & 0x7ff)^1] = data; + return; + } + + if ((address & 0xffff000) == 0xff4000) { + deco16_146_nitroball_prot_w(address, data, 0x00ff << ((address & 1) << 3)); + return; + } +} + +UINT16 __fastcall wizdfire_main_read_word(UINT32 address) +{ + if (address == 0x320000) return DrvInputs[2]; + + if ((address & 0xffff800) == 0xfe4000) { + return deco16_104_prot_r(address); + } + + if ((address & 0xffff000) == 0xff4000) { + return deco16_146_nitroball_prot_r(address); + } + + return 0; +} + +UINT8 __fastcall wizdfire_main_read_byte(UINT32 address) +{ + if (address == 0x320000 || address == 0x320001) return DrvInputs[2] >> ((~address & 1) << 3); + + if ((address & 0xffff800) == 0xfe4000) { + return deco16_104_prot_r(address) >> ((~address & 1) << 3); + } + + if ((address & 0xffff000) == 0xff4000) { + return deco16_146_nitroball_prot_r(address) >> ((~address & 1) << 3); + } + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static void DrvYM2151WritePort(UINT32, UINT32 data) +{ + if ((data & 0x01) != (UINT32)(DrvOkiBank & 0x01)) + memcpy (DrvSndROM0, DrvSndROM0 + ((data & 0x01) >> 0) * 0x40000, 0x40000); + + if ((data & 0x02) != (UINT32)(DrvOkiBank & 0x02)) + memcpy (DrvSndROM1, DrvSndROM1 + ((data & 0x02) >> 1) * 0x40000, 0x40000); + + DrvOkiBank = data; +} + +static INT32 rohga_bank_callback( const INT32 bank ) +{ + return ((bank >> 4) & 0x3) << 12; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + deco16Reset(); + + DrvOkiBank = -1; + DrvYM2151WritePort(0, 0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x200000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x080000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROM2 = Next; Next += 0x400000; + DrvGfxROM3 = Next; Next += 0x800000; + DrvGfxROM4 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x0c0000; + + tempdraw[0] = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + tempdraw[1] = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x024000; + DrvSprRAM2 = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf2 = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + + deco16_prot_ram = (UINT16*)Next; + DrvPrtRAM = Next; Next += 0x000800; + deco16_buffer_ram = (UINT16*)Next; Next += 0x000800; + + DrvPalRAM = Next; Next += 0x002000; + DrvPalBuf = Next; Next += 0x002000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvSpriteDecode() +{ + INT32 Plane[6] = { 0x400000*8+8, 0x400000*8, 0x200000*8+8, 0x200000*8, 8, 0 }; + INT32 XOffs[16] = { 7,6,5,4,3,2,1,0, 32*8+7, 32*8+6, 32*8+5, 32*8+4, 32*8+3, 32*8+2, 32*8+1, 32*8+0 }; + INT32 YOffs[16] = { 15*16, 14*16, 13*16, 12*16, 11*16, 10*16, 9*16, 8*16, 7*16, 6*16, 5*16, 4*16, 3*16, 2*16, 1*16, 0*16}; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x600000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM3, 0x600000); + + GfxDecode(0x8000, 6, 16, 16, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 RohgaInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x100001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x100000, 3, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x400000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x500000, 16, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x040000, 17, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x040000, 18, 1)) return 1; + + deco56_decrypt_gfx(DrvGfxROM0, 0x020000); + deco56_decrypt_gfx(DrvGfxROM1, 0x100000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x200000, 0); + DrvSpriteDecode(); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x100000 * 2, DrvGfxROM2, 0x200000 * 2); + deco16_set_color_base(2, 512); + deco16_set_color_base(3, 768); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(0, rohga_bank_callback); + deco16_set_bank_callback(1, rohga_bank_callback); + deco16_set_bank_callback(2, rohga_bank_callback); + deco16_set_bank_callback(3, rohga_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x3c0000, 0x3c1fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x3c2000, 0x3c2fff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x3c4000, 0x3c4fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x3c6000, 0x3c6fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x3c8000, 0x3c8fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x3c9000, 0x3c9fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x3ca000, 0x3cafff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x3cb000, 0x3cbfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x3cc000, 0x3ccfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x3cd000, 0x3cdfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x3ce000, 0x3cefff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x3cf000, 0x3cffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x3d0000, 0x3d07ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x3e0000, 0x3e1fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x3f0000, 0x3f3fff, SM_RAM); + SekSetWriteWordHandler(0, rohga_main_write_word); + SekSetWriteByteHandler(0, rohga_main_write_byte); + SekSetReadWordHandler(0, rohga_main_read_word); + SekSetReadByteHandler(0, rohga_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 80.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + MSM6295Init(0, 1006875 / 132, 100.0, 1); + MSM6295Init(1, 2013750 / 132, 40.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 WizdfireInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 5, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 8, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200001, 16, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000001, 18, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 19, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 20, 1)) return 1; + + deco74_decrypt_gfx(DrvGfxROM0, 0x020000); + deco74_decrypt_gfx(DrvGfxROM1, 0x200000); + deco74_decrypt_gfx(DrvGfxROM2, 0x100000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x200000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + deco16_sprite_decode(DrvGfxROM3, 0x400000); + deco16_sprite_decode(DrvGfxROM4, 0x100000); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x200000 * 2, DrvGfxROM2, 0x100000 * 2); + deco16_set_color_base(2, 512); + deco16_set_color_base(3, 768); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(0, rohga_bank_callback); + deco16_set_bank_callback(1, rohga_bank_callback); + deco16_set_bank_callback(2, rohga_bank_callback); + deco16_set_bank_callback(3, rohga_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x200000, 0x200fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x202000, 0x202fff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x208000, 0x208fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x20a000, 0x20afff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x20c000, 0x20c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x20e000, 0x20e7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x340000, 0x3407ff, SM_RAM); + SekMapMemory(DrvSprRAM2, 0x360000, 0x3607ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x380000, 0x381fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xfdc000, 0xfe3fff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x8000, 0xfe4800, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, wizdfire_main_write_word); + SekSetWriteByteHandler(0, wizdfire_main_write_byte); + SekSetReadWordHandler(0, wizdfire_main_read_word); + SekSetReadByteHandler(0, wizdfire_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 80.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + MSM6295Init(0, 1006875 / 132, 100.0, 1); + MSM6295Init(1, 2013750 / 132, 40.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 SchmeisrInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x300000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 12, 1)) return 1; + + deco74_decrypt_gfx(DrvGfxROM1, 0x100000); + + memcpy (DrvGfxROM0 + 0x000000, DrvGfxROM1 + 0x000000, 0x020000); + memcpy (DrvGfxROM0 + 0x020000, DrvGfxROM1 + 0x080000, 0x020000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x040000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x200000, 0); + DrvSpriteDecode(); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x40000 * 2, DrvGfxROM1, 0x100000 * 2, DrvGfxROM2, 0x200000 * 2); + deco16_set_color_base(2, 512); + deco16_set_color_base(3, 768); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(0, rohga_bank_callback); + deco16_set_bank_callback(1, rohga_bank_callback); + deco16_set_bank_callback(2, rohga_bank_callback); + deco16_set_bank_callback(3, rohga_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x3c0000, 0x3c1fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x3c2000, 0x3c2fff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x3c4000, 0x3c4fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x3c6000, 0x3c6fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x3c8000, 0x3c8fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x3c9000, 0x3c9fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x3ca000, 0x3cafff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x3cb000, 0x3cbfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x3cc000, 0x3ccfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x3cd000, 0x3cdfff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x3ce000, 0x3cefff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x3cf000, 0x3cffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x3d0000, 0x3d07ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x3e0000, 0x3e1fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x3e2000, 0x3e3fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xff7fff, SM_RAM); + SekSetWriteWordHandler(0, rohga_main_write_word); + SekSetWriteByteHandler(0, rohga_main_write_byte); + SekSetReadWordHandler(0, rohga_main_read_word); + SekSetReadByteHandler(0, rohga_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 80.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + MSM6295Init(0, 1006875 / 132, 100.0, 1); + MSM6295Init(1, 2013750 / 132, 40.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 NitrobalInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 5, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 8, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x100000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200000, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x200001, 16, 2)) return 1; + BurnByteswap(DrvGfxROM3, 0x400000); + + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 17, 2)) return 1; + if (BurnLoadRom(DrvGfxROM4 + 0x000001, 18, 2)) return 1; + BurnByteswap(DrvGfxROM4, 0x080000); + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 19, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 20, 1)) return 1; + + deco56_decrypt_gfx(DrvGfxROM0, 0x020000); + deco56_decrypt_gfx(DrvGfxROM1, 0x100000); + deco74_decrypt_gfx(DrvGfxROM2, 0x200000); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, 0x020000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x100000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x200000, 0); + deco16_sprite_decode(DrvGfxROM3, 0x400000); + deco16_sprite_decode(DrvGfxROM4, 0x080000); + } + + deco16Init(0, 0, 0); + deco16_set_graphics(DrvGfxROM0, 0x20000 * 2, DrvGfxROM1, 0x100000 * 2, DrvGfxROM2, 0x200000 * 2); + deco16_set_color_base(2, 512); + deco16_set_color_mask(2, 0); + deco16_set_color_base(3, 512); + deco16_set_color_mask(3, 0); + deco16_set_global_offsets(0, 8); + deco16_set_bank_callback(0, rohga_bank_callback); + deco16_set_bank_callback(1, rohga_bank_callback); + deco16_set_bank_callback(2, rohga_bank_callback); + deco16_set_bank_callback(3, rohga_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(deco16_pf_ram[0], 0x200000, 0x200fff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x201000, 0x201fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x202000, 0x2027ff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x202800, 0x202fff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x208000, 0x2087ff, SM_RAM); + SekMapMemory(deco16_pf_ram[2], 0x208800, 0x208fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x20a000, 0x20a7ff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x20a800, 0x20afff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x204000, 0x2047ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x206000, 0x2067ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[2], 0x20c000, 0x20c7ff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[3], 0x20e000, 0x20e7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x340000, 0x3407ff, SM_RAM); + SekMapMemory(DrvSprRAM2, 0x360000, 0x3607ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x380000, 0x381fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xfec000, 0xff3fff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x8000, 0xff8000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, wizdfire_main_write_word); + SekSetWriteByteHandler(0, wizdfire_main_write_byte); + SekSetReadWordHandler(0, wizdfire_main_read_word); + SekSetReadByteHandler(0, wizdfire_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 80.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + BurnYM2151SetPortHandler(&DrvYM2151WritePort); + + MSM6295Init(0, 1006875 / 132, 100.0, 1); + MSM6295Init(1, 2013750 / 132, 40.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void rohga_draw_sprites(UINT8 *ram, INT32 is_schmeisr) +{ + UINT16 *spriteptr = (UINT16*)ram; + + for (INT32 offs = 0x400 - 4; offs >= 0; offs -= 4) + { + INT32 inc, mult, pri = 0; + INT32 sprite = spriteptr[offs + 1]; + + if (!sprite) continue; + + INT32 x = spriteptr[offs + 2]; + + switch (x & 0x6000) + { + case 0x0000: pri = 0; break; + case 0x4000: pri = 0xf0; break; + case 0x6000: pri = 0xf0 | 0xcc; break; + case 0x2000: pri = 0; break; + } + + INT32 y = spriteptr[offs]; + + if ((y & 0x1000) && (nCurrentFrame & 1)) continue; // flash + + INT32 colour = (((x >> 9) & 0xf) << 6); + if (is_schmeisr) colour += ((x & 0x8000) >> 15) << 4; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + x = 304 - x; + y = 240 - y; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = -16; + } + else + mult = +16; + + while (multi >= 0) + { + deco16_draw_prio_sprite(pTransDraw, DrvGfxROM3, (sprite - multi * inc) & 0x7fff, colour + 0x400, x, y + mult * multi, fx, fy, pri); + + multi--; + } + } +} + +static void wizdfire_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 coloff, INT32 mode, INT32 bank) +{ + UINT16 *spriteptr = (UINT16*)ram; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult, prio = 0, alpha = 0xff; + + INT32 sprite = spriteptr[offs + 1]; + if (!sprite) continue; + + INT32 x = spriteptr[offs + 2]; + + switch (mode) + { + case 4: + if ((x & 0xc000) != 0xc000) + continue; + prio = 0x08; + break; + case 3: + if ((x & 0xc000) != 0x8000) + continue; + prio = 0x10; + break; + case 2: + if ((x & 0x8000) != 0x8000) + continue; + prio = 0x20; + break; + case 1: + case 0: + default: + if ((x & 0x8000) != 0) + continue; + prio = 0x40; + break; + } + + INT32 y = spriteptr[offs]; + + if ((y & 0x1000) && (nCurrentFrame & 1)) continue; // flash + + INT32 colour = (x >> 9) & 0x1f; + + if (bank == 4 && colour & 0x10) + { + alpha = 0x80; + colour &= 0xf; + } + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x0600) >> 9)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + x = 304 - x; + y = 240 - y; + mult = -16; + } else { + mult = +16; + fx = !fx; + fy = !fy; + } + + if (bank == 3) { + sprite &= 0x7fff; + } else { + sprite &= 0x0fff; + } + + while (multi >= 0) + { + deco16_draw_prio_sprite(pTransDraw, gfx, sprite - multi * inc, (colour << 4) + coloff, x, y + mult * multi, fx, fy, -1); +#if 0 + drawgfx_alpha(bitmap,cliprect,machine->gfx[bank], + sprite - multi * inc, + colour, + fx,fy, + x,y + mult * multi, + 0,alpha); +#endif + multi--; + } + } +} + +static void nitrobal_draw_sprites(UINT8 *ram, INT32 gfxbank, INT32 /*bpp*/) +{ +// if (bpp != (nBurnBpp & 0x04)) return; + + UINT16 *spriteptr = (UINT16*)ram; + + INT32 offs = 0x3fc; + INT32 end = -4; + INT32 inc = -4; + UINT8 *gfx; + + while (offs != end) + { + INT32 x, y, sprite, colour, fx, fy, w, h, sx, sy, x_mult, y_mult, tilemap_pri, sprite_pri, coloff; + INT32 alpha = 0xff; + + sprite = spriteptr[offs + 3]; + if (!sprite) + { + offs += inc; + continue; + } + + sx = spriteptr[offs + 1]; + + h = (spriteptr[offs + 2] & 0xf000) >> 12; + w = (spriteptr[offs + 2] & 0x0f00) >> 8; + + sy = spriteptr[offs]; + if ((sy & 0x2000) && (nCurrentFrame & 1)) + { + offs += inc; + continue; + } + + colour = (spriteptr[offs + 2] >> 0) & 0x1f; + + if (gfxbank == 3) + { + switch (spriteptr[offs + 2] & 0xe0) + { + case 0xc0: tilemap_pri = 8; break; + case 0x80: tilemap_pri = 32; break; + case 0x20: tilemap_pri = 32; break; + case 0x40: tilemap_pri = 8; break; + case 0xa0: tilemap_pri = 32; break; + case 0x00: tilemap_pri = 128; break; + default: tilemap_pri = 128; break; + } + + sprite_pri = 1; + + gfx = DrvGfxROM3; + coloff = 0x400; + } + else + { + if (deco16_priority) + tilemap_pri = 8; + else + tilemap_pri = 64; + + sprite_pri = 2; + + gfx = DrvGfxROM4; + coloff = 0x600; + + if (colour & 0x10) { + alpha = 0x80; + colour &= 0x0f; + } + } + + fx = (spriteptr[offs + 0] & 0x4000); + fy = (spriteptr[offs + 0] & 0x8000); + + if (!*flipscreen) + { + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + + sx = sx & 0x01ff; + sy = sy & 0x01ff; + if (sx > 0x180) sx = -(0x200 - sx); + if (sy > 0x180) sy = -(0x200 - sy); + + if (fx) { x_mult = -16; sx += 16 * w; } else { x_mult = 16; sx -= 16; } + if (fy) { y_mult = -16; sy += 16 * h; } else { y_mult = 16; sy -= 16; } + } + else + { + sx = sx & 0x01ff; + sy = sy & 0x01ff; + if (sx & 0x100) sx = -(0x100 - (sx & 0xff)); + if (sy & 0x100) sy = -(0x100 - (sy & 0xff)); + sx = 304 - sx; + sy = 240 - sy; + if (sx >= 432) sx -= 512; + if (sy >= 384) sy -= 512; + if (fx) { x_mult = -16; sx += 16; } else { x_mult = 16; sx -= 16 * w; } + if (fy) { y_mult = -16; sy += 16; } else { y_mult = 16; sy -= 16 * h; } + } + + if (gfxbank == 3) { + sprite &= 0x7fff; + } else { + sprite &= 0x0fff; + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + //if (!bpp) { + deco16_draw_prio_sprite(pTransDraw, gfx, sprite + y + h * x, (colour << 4) + coloff, sx + x_mult * (w-x), sy + y_mult * (h-y), fx, fy, tilemap_pri, sprite_pri); + //} else { + // deco16_draw_alphaprio_sprite(DrvPalette, gfx, sprite + y + h * x, (colour << 4) + coloff, sx + x_mult * (w-x), sy + y_mult * (h-y), fx, fy, tilemap_pri, sprite_pri, alpha); + //} + } + } + + offs += inc; + } +} + +static void draw_combined_playfield_step1() +{ + UINT8 *tptr = deco16_pf_rowscroll[3]; + deco16_pf_rowscroll[3] = deco16_pf_rowscroll[2]; + + deco16_draw_layer(2, tempdraw[0], 0x10000); + deco16_draw_layer(3, tempdraw[1], 0x10000); + + deco16_pf_rowscroll[3] = tptr; +} + +static void draw_combined_playfield(INT32 color, INT32 priority) // opaque +{ + UINT16 *src0 = tempdraw[0]; + UINT16 *src1 = tempdraw[1]; + UINT16 *dest = pTransDraw; + UINT8 *prio = deco16_prio_map; + + for (INT32 y = 0; y < nScreenHeight; y++) { + for (INT32 x = 0; x < nScreenWidth; x++) { + dest[x] = color | (src0[x] & 0x0f) | ((src1[x] & 0x0f) << 4); + prio[x] = priority; + } + src0 += nScreenWidth; + src1 += nScreenWidth; + dest += nScreenWidth; + prio += 512; + } +} + +static void update_rohga(INT32 is_schmeisr) +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x300; + } + + if ((deco16_priority & 0x03) == 0) { + draw_combined_playfield_step1(); + } + + deco16_clear_prio_map(); + + switch (deco16_priority & 3) + { + case 0: + if (deco16_priority & 4) + { + draw_combined_playfield(0x300, DECO16_LAYER_PRIORITY(3)); + } + else + { + deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE | DECO16_LAYER_PRIORITY(0x01)); + deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + } + deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x04)); + break; + + case 1: + deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE | DECO16_LAYER_PRIORITY(0x01)); + deco16_draw_layer(1, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x04)); + break; + + case 2: + deco16_draw_layer(1, pTransDraw, DECO16_LAYER_OPAQUE | DECO16_LAYER_PRIORITY(0x01)); + deco16_draw_layer(3, pTransDraw, DECO16_LAYER_PRIORITY(0x02)); + deco16_draw_layer(2, pTransDraw, DECO16_LAYER_PRIORITY(0x04)); + break; + } + + if (nSpriteEnable & 1) rohga_draw_sprites(DrvSprBuf2, is_schmeisr); + + deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); +} + +static INT32 RohgaDraw() +{ + update_rohga(0); + + return 0; +} + +static INT32 SchmeisrDraw() +{ + update_rohga(1); + + return 0; +} + +static INT32 WizdfireDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x200; + } + + if (nBurnLayer & 1) deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE); + + if (nSpriteEnable & 1) wizdfire_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x400, 4, 3); + + if (nBurnLayer & 2) deco16_draw_layer(1, pTransDraw, 0); + + if (nSpriteEnable & 2) wizdfire_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x400, 3, 3); + + if ((deco16_priority & 0x1f) == 0x1f) { + if (nBurnLayer & 4) deco16_draw_layer(2, pTransDraw, 0); // tilemap draw alpha 0x80... + } else { + if (nBurnLayer & 4) deco16_draw_layer(2, pTransDraw, 0); + } + + if (nSpriteEnable & 4) wizdfire_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x400, 0, 3); + if (nSpriteEnable & 8) wizdfire_draw_sprites(DrvSprBuf2, DrvGfxROM4, 0x600, 2, 4); + if (nSpriteEnable & 16) wizdfire_draw_sprites(DrvSprBuf2, DrvGfxROM4, 0x600, 1, 4); + + if (nBurnLayer & 8) deco16_draw_layer(0, pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 NitrobalDraw() +{ +// if (DrvRecalc) { + deco16_palette_recalculate(DrvPalette, DrvPalRAM); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x200; + } + + draw_combined_playfield_step1(); + + deco16_clear_prio_map(); + + draw_combined_playfield(0x200, 0); + + if (nBurnLayer & 1)deco16_draw_layer(3, pTransDraw, DECO16_LAYER_OPAQUE); + + deco16_draw_layer(1, pTransDraw, 16); + + nitrobal_draw_sprites(DrvSprBuf , 3, 0); + nitrobal_draw_sprites(DrvSprBuf2, 4, 0); + + deco16_draw_layer(0, pTransDraw, DECO16_LAYER_PRIORITY(0xff)); + + BurnTransferCopy(DrvPalette); + +// nitrobal_draw_sprites(DrvSprBuf , 3, 4); +// nitrobal_draw_sprites(DrvSprBuf2, 4, 4); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + deco16_prot_inputs = DrvInputs; + memset (DrvInputs, 0xff, 4 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy3[i] & 1) << i; + } + DrvInputs[2] = (DrvDips[1] << 8) | (DrvDips[0] << 0); + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 2685000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_ACK); + + SekClose(); + + if (pBurnSoundOut && 0) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(DrvOkiBank); + + INT32 bank = DrvOkiBank; + DrvOkiBank = -1; + DrvYM2151WritePort(0, bank); + } + + return 0; +} + + +// Rohga Armor Force (Asia/Europe v5.0) + +static struct BurnRomInfo rohgaRomDesc[] = { + { "ht-00-1.2a", 0x040000, 0x1ed84a67, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ht-03-1.2d", 0x040000, 0x84e7ebf6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ha04.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "ha01.13a", 0x010000, 0xfb8f8519, 3 | BRF_GRA }, // 5 Characters + { "ha02.14a", 0x010000, 0xaa47c17f, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(rohga) +STD_ROM_FN(rohga) + +struct BurnDriver BurnDrvRohga = { + "rohga", NULL, NULL, NULL, "1991", + "Rohga Armor Force (Asia/Europe v5.0)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, rohgaRomInfo, rohgaRomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Rohga Armor Force (Asia/Europe v3.0 Set 1) + +static struct BurnRomInfo rohga1RomDesc[] = { + { "jd00.bin", 0x040000, 0xe046c77a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jd03.bin", 0x040000, 0x2c5120b8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ha04.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "ha01.13a", 0x010000, 0xfb8f8519, 3 | BRF_GRA }, // 5 Characters + { "ha02.14a", 0x010000, 0xaa47c17f, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(rohga1) +STD_ROM_FN(rohga1) + +struct BurnDriver BurnDrvRohga1 = { + "rohga1", "rohga", NULL, NULL, "1991", + "Rohga Armor Force (Asia/Europe v3.0 Set 1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, rohga1RomInfo, rohga1RomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Rohga Armor Force (Asia/Europe v3.0 Set 2) + +static struct BurnRomInfo rohga2RomDesc[] = { + { "hts-00-3.2a", 0x040000, 0x154f02ec, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hts-03-3.2d", 0x040000, 0x5e69d3d8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ha04.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "ha01.13a", 0x010000, 0xfb8f8519, 3 | BRF_GRA }, // 5 Characters + { "ha02.14a", 0x010000, 0xaa47c17f, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(rohga2) +STD_ROM_FN(rohga2) + +struct BurnDriver BurnDrvRohga2 = { + "rohga2", "rohga", NULL, NULL, "1991", + "Rohga Armor Force (Asia/Europe v3.0 Set 2)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, rohga2RomInfo, rohga2RomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Rohga Armor Force (Hong Kong v3.0) + +static struct BurnRomInfo rohgahRomDesc[] = { + { "jd00-2.2a", 0x040000, 0xec70646a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jd03-2.2d", 0x040000, 0x11d4c9a2, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ha04.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "ha01.13a", 0x010000, 0xfb8f8519, 3 | BRF_GRA }, // 5 Characters + { "ha02.14a", 0x010000, 0xaa47c17f, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(rohgah) +STD_ROM_FN(rohgah) + +struct BurnDriver BurnDrvRohgah = { + "rohgah", "rohga", NULL, NULL, "1991", + "Rohga Armor Force (Hong Kong v3.0)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, rohgahRomInfo, rohgahRomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Rohga Armor Force (US v1.0) + +static struct BurnRomInfo rohgauRomDesc[] = { + { "ha00.2a", 0x040000, 0xd8d13052, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ha03.2d", 0x040000, 0x5f683bbf, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ha04.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "ha01.13a", 0x010000, 0xfb8f8519, 3 | BRF_GRA }, // 5 Characters + { "ha02.14a", 0x010000, 0xaa47c17f, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(rohgau) +STD_ROM_FN(rohgau) + +struct BurnDriver BurnDrvRohgau = { + "rohgau", "rohga", NULL, NULL, "1991", + "Rohga Armor Force (US v1.0)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, rohgauRomInfo, rohgauRomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Wolf Fang -Kuhga 2001- (Japan) + +static struct BurnRomInfo wolffangRomDesc[] = { + { "hw_00-1.2a", 0x040000, 0x69dc611e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hw_03-1.2d", 0x040000, 0xb66d9680, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mam00.8a", 0x080000, 0x0fa440a6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "mam07.8d", 0x080000, 0xf8bc7f20, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hw_04-.18p", 0x010000, 0xeb6608eb, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "hw_01-.13a", 0x010000, 0xd9810ca4, 3 | BRF_GRA }, // 5 Characters + { "hw_02-.14a", 0x010000, 0x2a27ac8e, 3 | BRF_GRA }, // 6 + + { "mam01.10a", 0x080000, 0xdbf4fbcc, 4 | BRF_GRA }, // 7 Foreground Tiles + { "mam02.11a", 0x080000, 0xb1fac481, 4 | BRF_GRA }, // 8 + + { "mam08.17d", 0x100000, 0xca97a83f, 5 | BRF_GRA }, // 9 Background Tiles + { "mam09.18d", 0x100000, 0x3f57d56f, 5 | BRF_GRA }, // 10 + + { "mam05.19a", 0x100000, 0x307a2cd1, 6 | BRF_GRA }, // 11 Sprites + { "mam06.20a", 0x100000, 0xa1119a2d, 6 | BRF_GRA }, // 12 + { "mam10.19d", 0x100000, 0x99f48f9f, 6 | BRF_GRA }, // 13 + { "mam11.20d", 0x100000, 0xc3f12859, 6 | BRF_GRA }, // 14 + { "mam03.17a", 0x100000, 0xfc4dfd48, 6 | BRF_GRA }, // 15 + { "mam04.18a", 0x100000, 0x7d3b38bf, 6 | BRF_GRA }, // 16 + + { "mam13.15p", 0x080000, 0x525b9461, 8 | BRF_SND }, // 17 OKI M6295 Samples 0 + + { "mam12.14p", 0x080000, 0x6f00b791, 7 | BRF_SND }, // 18 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 19 Unused PROMs +}; + +STD_ROM_PICK(wolffang) +STD_ROM_FN(wolffang) + +struct BurnDriver BurnDrvWolffang = { + "wolffang", "rohga", NULL, NULL, "1991", + "Wolf Fang -Kuhga 2001- (Japan)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, wolffangRomInfo, wolffangRomName, NULL, NULL, RohgaInputInfo, RohgaDIPInfo, + RohgaInit, DrvExit, DrvFrame, RohgaDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Wizard Fire (Over Sea v2.1) + +static struct BurnRomInfo wizdfireRomDesc[] = { + { "je-01.3d", 0x020000, 0xb6d62367, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "je-00.3a", 0x020000, 0xf33de278, 1 | BRF_PRG | BRF_ESS }, // 1 + { "je-03.5d", 0x020000, 0x5217d404, 1 | BRF_PRG | BRF_ESS }, // 2 + { "je-02.5a", 0x020000, 0x36a1ce28, 1 | BRF_PRG | BRF_ESS }, // 3 + { "mas13", 0x080000, 0x7e5256ce, 1 | BRF_PRG | BRF_ESS }, // 4 + { "mas12", 0x080000, 0x005bd499, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "je-06.20r", 0x010000, 0x79042546, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "je-04.10d", 0x010000, 0x73cba800, 3 | BRF_GRA }, // 7 Characters + { "je-05.12d", 0x010000, 0x22e2c49d, 3 | BRF_GRA }, // 8 + + { "mas00", 0x100000, 0x3d011034, 4 | BRF_GRA }, // 9 Foreground Tiles + { "mas01", 0x100000, 0x6d0c9d0b, 4 | BRF_GRA }, // 10 + + { "mas02", 0x080000, 0xaf00e620, 5 | BRF_GRA }, // 11 Background Tiles + { "mas03", 0x080000, 0x2fe61ea2, 5 | BRF_GRA }, // 12 + + { "mas04", 0x100000, 0x1e56953b, 6 | BRF_GRA }, // 13 Sprite Bank A + { "mas05", 0x100000, 0x3826b8f8, 6 | BRF_GRA }, // 14 + { "mas06", 0x100000, 0x3b8bbd45, 6 | BRF_GRA }, // 15 + { "mas07", 0x100000, 0x31303769, 6 | BRF_GRA }, // 16 + + { "mas08", 0x080000, 0xe224fb7a, 7 | BRF_GRA }, // 17 Sprite Bank B + { "mas09", 0x080000, 0x5f6deb41, 7 | BRF_GRA }, // 18 + + { "mas10", 0x080000, 0x6edc06a7, 8 | BRF_SND }, // 19 OKI M6295 Samples 0 + + { "mas11", 0x080000, 0xc2f0a4f2, 9 | BRF_SND }, // 20 OKI M6295 Samples 1 + + { "mb7122h.16l", 0x000400, 0x2bee57cc, 0 | BRF_OPT }, // 21 Unused PROMs +}; + +STD_ROM_PICK(wizdfire) +STD_ROM_FN(wizdfire) + +struct BurnDriver BurnDrvWizdfire = { + "wizdfire", NULL, NULL, NULL, "1992", + "Wizard Fire (Over Sea v2.1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, wizdfireRomInfo, wizdfireRomName, NULL, NULL, WizdfireInputInfo, WizdfireDIPInfo, + WizdfireInit, DrvExit, DrvFrame, WizdfireDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Wizard Fire (US v1.1) + +static struct BurnRomInfo wizdfireuRomDesc[] = { + { "jf-01.3d", 0x020000, 0xbde42a41, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jf-00.3a", 0x020000, 0xbca3c995, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jf-03.5d", 0x020000, 0x5217d404, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jf-02.5a", 0x020000, 0x36a1ce28, 1 | BRF_PRG | BRF_ESS }, // 3 + { "mas13", 0x080000, 0x7e5256ce, 1 | BRF_PRG | BRF_ESS }, // 4 + { "mas12", 0x080000, 0x005bd499, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "jf-06.20r", 0x010000, 0x79042546, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "jf-04.10d", 0x010000, 0x73cba800, 3 | BRF_GRA }, // 7 Characters + { "jf-05.12d", 0x010000, 0x22e2c49d, 3 | BRF_GRA }, // 8 + + { "mas00", 0x100000, 0x3d011034, 4 | BRF_GRA }, // 9 Foreground Tiles + { "mas01", 0x100000, 0x6d0c9d0b, 4 | BRF_GRA }, // 10 + + { "mas02", 0x080000, 0xaf00e620, 5 | BRF_GRA }, // 11 Background Tiles + { "mas03", 0x080000, 0x2fe61ea2, 5 | BRF_GRA }, // 12 + + { "mas04", 0x100000, 0x1e56953b, 6 | BRF_GRA }, // 13 Sprite Bank A + { "mas05", 0x100000, 0x3826b8f8, 6 | BRF_GRA }, // 14 + { "mas06", 0x100000, 0x3b8bbd45, 6 | BRF_GRA }, // 15 + { "mas07", 0x100000, 0x31303769, 6 | BRF_GRA }, // 16 + + { "mas08", 0x080000, 0xe224fb7a, 7 | BRF_GRA }, // 17 Sprite Bank B + { "mas09", 0x080000, 0x5f6deb41, 7 | BRF_GRA }, // 18 + + { "mas10", 0x080000, 0x6edc06a7, 8 | BRF_SND }, // 19 OKI M6295 Samples 0 + + { "mas11", 0x080000, 0xc2f0a4f2, 9 | BRF_SND }, // 20 OKI M6295 Samples 1 + + { "mb7122h.16l", 0x000400, 0x2bee57cc, 0 | BRF_OPT }, // 21 Unused PROMs +}; + +STD_ROM_PICK(wizdfireu) +STD_ROM_FN(wizdfireu) + +struct BurnDriver BurnDrvWizdfireu = { + "wizdfireu", "wizdfire", NULL, NULL, "1992", + "Wizard Fire (US v1.1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, wizdfireuRomInfo, wizdfireuRomName, NULL, NULL, WizdfireInputInfo, WizdfireDIPInfo, + WizdfireInit, DrvExit, DrvFrame, WizdfireDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Dark Seal 2 (Japan v2.1) + +static struct BurnRomInfo darkseal2RomDesc[] = { + { "jb-01-3.3d", 0x020000, 0x82308c01, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jb-00-3.3a", 0x020000, 0x1d38113a, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jb-03.5d", 0x020000, 0x5217d404, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jb-02.5a", 0x020000, 0x36a1ce28, 1 | BRF_PRG | BRF_ESS }, // 3 + { "mas13", 0x080000, 0x7e5256ce, 1 | BRF_PRG | BRF_ESS }, // 4 + { "mas12", 0x080000, 0x005bd499, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "jb-06.20r", 0x010000, 0x2066a1dd, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "jb-04.10d", 0x010000, 0x73cba800, 3 | BRF_GRA }, // 7 Characters + { "jb-05.12d", 0x010000, 0x22e2c49d, 3 | BRF_GRA }, // 8 + + { "mas00", 0x100000, 0x3d011034, 4 | BRF_GRA }, // 9 Foreground Tiles + { "mas01", 0x100000, 0x6d0c9d0b, 4 | BRF_GRA }, // 10 + + { "mas02", 0x080000, 0xaf00e620, 5 | BRF_GRA }, // 11 Background Tiles + { "mas03", 0x080000, 0x2fe61ea2, 5 | BRF_GRA }, // 12 + + { "mas04", 0x100000, 0x1e56953b, 6 | BRF_GRA }, // 13 Sprite Bank A + { "mas05", 0x100000, 0x3826b8f8, 6 | BRF_GRA }, // 14 + { "mas06", 0x100000, 0x3b8bbd45, 6 | BRF_GRA }, // 15 + { "mas07", 0x100000, 0x31303769, 6 | BRF_GRA }, // 16 + + { "mas08", 0x080000, 0xe224fb7a, 7 | BRF_GRA }, // 17 Sprite Bank B + { "mas09", 0x080000, 0x5f6deb41, 7 | BRF_GRA }, // 18 + + { "mas10", 0x080000, 0x6edc06a7, 8 | BRF_SND }, // 19 OKI M6295 Samples 0 + + { "mas11", 0x080000, 0xc2f0a4f2, 9 | BRF_SND }, // 20 OKI M6295 Samples 1 + + { "mb7122h.16l", 0x000400, 0x2bee57cc, 0 | BRF_OPT }, // 21 Unused PROMs +}; + +STD_ROM_PICK(darkseal2) +STD_ROM_FN(darkseal2) + +struct BurnDriver BurnDrvDarkseal2 = { + "darkseal2", "wizdfire", NULL, NULL, "1992", + "Dark Seal 2 (Japan v2.1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, darkseal2RomInfo, darkseal2RomName, NULL, NULL, WizdfireInputInfo, WizdfireDIPInfo, + WizdfireInit, DrvExit, DrvFrame, WizdfireDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Schmeiser Robo (Japan) + +static struct BurnRomInfo schmeisrRomDesc[] = { + { "sr001j.8a", 0x080000, 0xed31f3ff, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sr006j.8d", 0x080000, 0x9e9cfa5d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sr013.18p", 0x010000, 0x4ac00cbb, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "sr002-74.9a", 0x080000, 0x97e15c7b, 3 | BRF_GRA }, // 3 Foreground Tiles + { "sr003-74.11a", 0x080000, 0xea367971, 3 | BRF_GRA }, // 4 + + { "sr007.17d", 0x100000, 0x886f80c7, 4 | BRF_GRA }, // 5 Background Tiles + { "sr008.18d", 0x100000, 0xa74cbc90, 4 | BRF_GRA }, // 6 + + { "sr004.19a", 0x100000, 0xe25434a1, 5 | BRF_GRA }, // 7 Sprites + { "sr005.20a", 0x100000, 0x1630033b, 5 | BRF_GRA }, // 8 + { "sr009.19d", 0x100000, 0x7b9d982f, 5 | BRF_GRA }, // 9 + { "sr010.20d", 0x100000, 0x6e9e5352, 5 | BRF_GRA }, // 10 + + { "sr012.15p", 0x080000, 0x38843d4d, 7 | BRF_SND }, // 12 OKI M6295 Samples 0 + + { "sr011.14p", 0x080000, 0x81805616, 6 | BRF_SND }, // 11 OKI M6295 Samples 1 + + { "hb-00.11p", 0x000200, 0xb7a7baad, 0 | BRF_OPT }, // 13 Unused PROMs +}; + +STD_ROM_PICK(schmeisr) +STD_ROM_FN(schmeisr) + +struct BurnDriver BurnDrvSchmeisr = { + "schmeisr", NULL, NULL, NULL, "1993", + "Schmeiser Robo (Japan)\0","No sound", "Hot B", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, schmeisrRomInfo, schmeisrRomName, NULL, NULL, RohgaInputInfo, SchmeisrDIPInfo, + SchmeisrInit, DrvExit, DrvFrame, SchmeisrDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Nitro Ball (US) + +static struct BurnRomInfo nitrobalRomDesc[] = { + { "jl01-4.d3", 0x020000, 0x0414e409, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jl00-4.b3", 0x020000, 0xdd9e2bcc, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jl03-4.d5", 0x020000, 0xea264ac5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jl02-4.b5", 0x020000, 0x74047997, 1 | BRF_PRG | BRF_ESS }, // 3 + { "jl05-2.d6", 0x040000, 0xb820fa20, 1 | BRF_PRG | BRF_ESS }, // 4 + { "jl04-2.b6", 0x040000, 0x1fd8995b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "jl08.r20", 0x010000, 0x93d93fe1, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "jl06.d10", 0x010000, 0x91cf668e, 3 | BRF_GRA }, // 7 Characters + { "jl07.d12", 0x010000, 0xe61d0e42, 3 | BRF_GRA }, // 8 + + { "mav00.b10", 0x080000, 0x34785d97, 4 | BRF_GRA }, // 9 Foreground Tiles + { "mav01.b12", 0x080000, 0x8b531b16, 4 | BRF_GRA }, // 10 + + { "mav02.b16", 0x100000, 0x20723bf7, 5 | BRF_GRA }, // 11 Background Tiles + { "mav03.e16", 0x100000, 0xef6195f0, 5 | BRF_GRA }, // 12 + + { "mav05.e19", 0x100000, 0xd92d769c, 6 | BRF_GRA }, // 13 Sprite Bank A + { "mav04.b19", 0x100000, 0x8ba48385, 6 | BRF_GRA }, // 14 + { "mav07.e20", 0x080000, 0x5fc10ccd, 6 | BRF_GRA }, // 15 + { "mav06.b20", 0x080000, 0xae6201a5, 6 | BRF_GRA }, // 16 + + { "mav09.e23", 0x040000, 0x1ce7b51a, 7 | BRF_GRA }, // 17 Sprite Bank B + { "mav08.b23", 0x040000, 0x64966576, 7 | BRF_GRA }, // 18 + + { "mav10.r17", 0x080000, 0x8ad734b0, 8 | BRF_SND }, // 19 OKI M6295 Samples 0 + + { "mav11.r19", 0x080000, 0xef513908, 9 | BRF_SND }, // 20 OKI M6295 Samples 1 + + { "jn-00.17l", 0x000400, 0x6ac77b84, 0 | BRF_OPT }, // 21 Unused PROMs +}; + +STD_ROM_PICK(nitrobal) +STD_ROM_FN(nitrobal) + +struct BurnDriver BurnDrvNitrobal = { + "nitrobal", NULL, NULL, NULL, "1992", + "Nitro Ball (US)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, nitrobalRomInfo, nitrobalRomName, NULL, NULL, NitrobalInputInfo, NitrobalDIPInfo, + NitrobalInit, DrvExit, DrvFrame, NitrobalDraw, DrvScan, &DrvRecalc, 0x800, + 240, 320, 3, 4 +}; + + +// Gun Ball (Japan) + +static struct BurnRomInfo gunballRomDesc[] = { + { "jc01.3d", 0x020000, 0x61bfa998, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jc00.3b", 0x020000, 0x73ba8f74, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jc03.5d", 0x020000, 0x19231612, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jc02.5b", 0x020000, 0xa254f34c, 1 | BRF_PRG | BRF_ESS }, // 3 + { "jc05-3.6d", 0x040000, 0xf750a709, 1 | BRF_PRG | BRF_ESS }, // 4 + { "jc04-3.6b", 0x040000, 0xad711767, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "jl08.r20", 0x010000, 0x93d93fe1, 2 | BRF_PRG | BRF_ESS }, // 6 Huc6280 Code + + { "jl06.d10", 0x010000, 0x91cf668e, 3 | BRF_GRA }, // 7 Characters + { "jl07.d12", 0x010000, 0xe61d0e42, 3 | BRF_GRA }, // 8 + + { "mav00.b10", 0x080000, 0x34785d97, 4 | BRF_GRA }, // 9 Foreground Tiles + { "mav01.b12", 0x080000, 0x8b531b16, 4 | BRF_GRA }, // 10 + + { "mav02.b16", 0x100000, 0x20723bf7, 5 | BRF_GRA }, // 11 Background Tiles + { "mav03.e16", 0x100000, 0xef6195f0, 5 | BRF_GRA }, // 12 + + { "mav05.e19", 0x100000, 0xd92d769c, 6 | BRF_GRA }, // 13 Sprite Bank A + { "mav04.b19", 0x100000, 0x8ba48385, 6 | BRF_GRA }, // 14 + { "mav07.e20", 0x080000, 0x5fc10ccd, 6 | BRF_GRA }, // 15 + { "mav06.b20", 0x080000, 0xae6201a5, 6 | BRF_GRA }, // 16 + + { "mav09.e23", 0x040000, 0x1ce7b51a, 7 | BRF_GRA }, // 17 Sprite Bank B + { "mav08.b23", 0x040000, 0x64966576, 7 | BRF_GRA }, // 18 + + { "mav10.r17", 0x080000, 0x8ad734b0, 8 | BRF_SND }, // 19 OKI M6295 Samples 0 + + { "mav11.r19", 0x080000, 0xef513908, 9 | BRF_SND }, // 20 OKI M6295 Samples 1 + + { "jn-00.17l", 0x000400, 0x6ac77b84, 0 | BRF_OPT }, // 21 Unused PROMs +}; + +STD_ROM_PICK(gunball) +STD_ROM_FN(gunball) + +struct BurnDriver BurnDrvGunball = { + "gunball", "nitrobal", NULL, NULL, "1992", + "Gun Ball (Japan)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, gunballRomInfo, gunballRomName, NULL, NULL, NitrobalInputInfo, NitrobalDIPInfo, + NitrobalInit, DrvExit, DrvFrame, NitrobalDraw, DrvScan, &DrvRecalc, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_seta.cpp b/src/burn/drivers/misc_post90s/d_seta.cpp new file mode 100644 index 00000000..986a30c7 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_seta.cpp @@ -0,0 +1,10165 @@ +// FB Alpha Seta driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "burn_ym2612.h" +#include "burn_ym3812.h" +#include "burn_gun.h" +#include "msm6295.h" +#include "x1010.h" + +/* + To do: + further simulate m65c02 games + calibr50, usclassc, krazybowl, downtown need analog inputs hooked up... + flipscreen support + jockeyc needs work... +*/ + +#define NOIRQ2 0x80 +#define SET_IRQLINES(vblank, irq2) (((vblank) << 8) | (irq2)) +#define SPRITE_BUFFER 1 +#define NO_SPRITE_BUFFER 0 +#define SET_GFX_DECODE(n0, n1, n2) n0, n1, n2 + +static UINT8 *AllMem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *AllRam = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KROM = NULL; +static UINT8 *DrvSubROM = NULL; +static UINT8 *DrvGfxROM0 = NULL; +static UINT8 *DrvGfxROM1 = NULL; +static UINT8 *DrvGfxROM2 = NULL; +static UINT8 *DrvColPROM = NULL; +static UINT8 *DrvSndROM = NULL; +static UINT8 *Drv68KRAM = NULL; +static UINT8 *Drv68KRAM2 = NULL; +static UINT8 *DrvSubRAM = NULL; +static UINT8 *DrvShareRAM = NULL; +static UINT8 *DrvNVRAM = NULL; +static UINT8 *DrvPalRAM = NULL; +static UINT8 *DrvSprRAM0 = NULL; +static UINT8 *DrvSprRAM1 = NULL; +static UINT8 *DrvVidRAM0 = NULL; +static UINT8 *DrvVidRAM1 = NULL; +static UINT8 *DrvVIDCTRLRAM0 = NULL; +static UINT8 *DrvVIDCTRLRAM1 = NULL; +static UINT8 *DrvVideoRegs = NULL; + +static UINT32 *Palette = NULL; +static UINT32 *DrvPalette = NULL; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch = NULL; +static UINT8 *tilebank = NULL; +static UINT32 *tile_offset = NULL; + +static INT32 cpuspeed = 0; +static INT32 irqtype = 0; +static INT32 buffer_sprites = 0; +static INT32 DrvROMLen[5] = { 0, 0, 0, 0, 0 }; +static INT32 DrvGfxMask[3] = { 0, 0, 0 }; +static UINT8 *DrvGfxTransMask[3] = { NULL, NULL, NULL }; +static INT32 VideoOffsets[3][2] = { { 0, 0 }, { 0, 0 }, { 0, 0 } }; +static INT32 ColorOffsets[3] = { 0, 0, 0 }; +static INT32 ColorDepths[3]; +static INT32 twineagle = 0; +static INT32 oisipuzl_hack = 0; +static INT32 refresh_rate = 6000; + +static INT32 seta_samples_bank = 0; +static INT32 usclssic_port_select = 0; +static INT32 tndrcade_init_sim = 0; +static INT32 gun_input_bit = 0; +static INT32 gun_input_src = 0; + +static INT32 watchdog_enable = 0; +static INT32 watchdog = 0; +static INT32 flipscreen; + +static INT32 DrvAxis[4]; +static UINT16 DrvAnalogInput[4]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvJoy6[16]; +static UINT8 DrvJoy7[16]; +static UINT8 DrvDips[7]; +static UINT16 DrvInputs[6]; +static UINT8 DrvReset; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo QzkklogyInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 5" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Qzkklogy) + +static struct BurnInputInfo DrgnunitInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Drgnunit) + +static struct BurnInputInfo StgInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Stg) + +static struct BurnInputInfo Qzkklgy2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Qzkklgy2) + +static struct BurnInputInfo DaiohInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy4 + 0, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy4 + 1, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy4 + 2, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy4 + 3, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy4 + 4, "p2 fire 5" }, + {"P2 Button 6", BIT_DIGITAL, DrvJoy4 + 5, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Daioh) + +static struct BurnInputInfo RezonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Rezon) + +static struct BurnInputInfo EightfrcInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Eightfrc) + +static struct BurnInputInfo WrofaeroInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Wrofaero) + +static struct BurnInputInfo ZingzipInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Zingzip) + +static struct BurnInputInfo MsgundamInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Msgundam) + +static struct BurnInputInfo KamenridInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Kamenrid) + +static struct BurnInputInfo MadsharkInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Madshark) + +static struct BurnInputInfo WitsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Start", BIT_DIGITAL, DrvJoy4 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 2, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 3, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 0, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 1, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p3 fire 2" }, + + {"P4 Start", BIT_DIGITAL, DrvJoy5 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy5 + 2, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy5 + 3, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy5 + 0, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy5 + 1, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy5 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy5 + 5, "p4 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Wits) + +static struct BurnInputInfo ThunderlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Thunderl) + +static struct BurnInputInfo AtehateInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Atehate) + +static struct BurnInputInfo BlockcarInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Blockcar) + +static struct BurnInputInfo GundharaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Gundhara) + +static struct BurnInputInfo BlandiaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Blandia) + +static struct BurnInputInfo OisipuzlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Oisipuzl) + +static struct BurnInputInfo PairloveInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Pairlove) + +static struct BurnInputInfo OrbsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Orbs) + +static struct BurnInputInfo KeroppiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Keroppi) + +static struct BurnInputInfo JjsquawkInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Jjsquawk) + +static struct BurnInputInfo ExtdwnhlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Extdwnhl) + +static struct BurnInputInfo KrzybowlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + // space holders for analog inputs + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 8, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy1 + 9, "p1 fire 5" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + // space holders for analog inputs + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 8, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy2 + 9, "p2 fire 5" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Krzybowl) + +static struct BurnInputInfo UtoukondInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Utoukond) + +static struct BurnInputInfo TndrcadeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 5, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Tndrcade) + +static struct BurnInputInfo DowntownInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, +// fake to make space for analog + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 9, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, +// fake to make space for analog + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 9, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 5, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 4, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Downtown) + +static struct BurnInputInfo MetafoxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 5, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 4, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Metafox) + +static struct BurnInputInfo ZombraidInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "mouse button 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "mouse button 2" }, + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "mouse x-axis"), + A("P1 Up / Down", BIT_ANALOG_REL, DrvAxis + 1, "mouse y-axis"), + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 2, "p2 x-axis"), + A("P2 Up / Down", BIT_ANALOG_REL, DrvAxis + 3, "p2 y-axis"), + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Zombraid) + +static struct BurnInputInfo KiwameInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"Start", BIT_DIGITAL, DrvJoy4 + 5, "p1 start" }, + {"A", BIT_DIGITAL, DrvJoy4 + 0, "mah a" }, + {"B", BIT_DIGITAL, DrvJoy3 + 0, "mah b" }, + {"C", BIT_DIGITAL, DrvJoy5 + 0, "mah c" }, + {"D", BIT_DIGITAL, DrvJoy6 + 0, "mah d" }, + {"E", BIT_DIGITAL, DrvJoy4 + 1, "mah e" }, + {"F", BIT_DIGITAL, DrvJoy2 + 3, "mah f" }, + {"G", BIT_DIGITAL, DrvJoy5 + 1, "mah g" }, + {"H", BIT_DIGITAL, DrvJoy6 + 1, "mah h" }, + {"I", BIT_DIGITAL, DrvJoy4 + 2, "mah i" }, + {"J", BIT_DIGITAL, DrvJoy3 + 2, "mah j" }, + {"K", BIT_DIGITAL, DrvJoy4 + 4, "mah k" }, + {"L", BIT_DIGITAL, DrvJoy2 + 0, "mah l" }, + {"M", BIT_DIGITAL, DrvJoy4 + 3, "mah m" }, + {"N", BIT_DIGITAL, DrvJoy3 + 3, "mah n" }, + {"Pon", BIT_DIGITAL, DrvJoy6 + 3, "mah pon" }, + {"Chi", BIT_DIGITAL, DrvJoy5 + 3, "mah chi" }, + {"Kan", BIT_DIGITAL, DrvJoy4 + 4, "mah kan" }, + {"Ron", BIT_DIGITAL, DrvJoy5 + 4, "mah ron" }, + {"Reach", BIT_DIGITAL, DrvJoy3 + 4, "mah reach" }, + {"Flip Flip", BIT_DIGITAL, DrvJoy2 + 3, "mah ff" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Kiwame) + +static struct BurnInputInfo SokonukeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Sokonuke) + +static struct BurnInputInfo NeobattlInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Neobattl) + +static struct BurnInputInfo UmanclubInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 3, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Umanclub) + +static struct BurnInputInfo TwineaglInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 4, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 5, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Twineagl) + +static struct BurnInputInfo CrazyfgtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 top-center", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 bottom-center", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + {"P1 top-left", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 3" }, + {"P1 bottom-left", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 4" }, + {"P1 top-right", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 5" }, + {"P1 bottom-right", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Crazyfgt) + +static struct BurnInputInfo Calibr50InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, +// fake to make space for analog inputs... + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, +// fake to make space for analog inputs... + + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 5, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 4, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Calibr50) + +static struct BurnInputInfo UsclssicInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 14, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 13, "p1 fire 1" }, +// space holder for analog inputs + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy3 + 0, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy5 + 14, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy5 + 13, "p2 fire 1" }, +// space holder for analog inputs + {"P2 Button 2", BIT_DIGITAL, DrvJoy4 + 0, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy5 + 0, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 7, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Usclssic) + +static struct BurnInputInfo JockeycInputList[] = { + {"P1 A Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin" }, + {"P1 B Coin", BIT_DIGITAL, DrvJoy1 + 4, "p3 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy4 + 3, "p1 start" }, + {"P1 Bet 1", BIT_DIGITAL, DrvJoy3 + 0, "p1 bet 1" }, + {"P1 Bet 2", BIT_DIGITAL, DrvJoy3 + 1, "p1 bet 2" }, + {"P1 Bet 3", BIT_DIGITAL, DrvJoy3 + 2, "p1 bet 3" }, + {"P1 Bet 4", BIT_DIGITAL, DrvJoy3 + 3, "p1 bet 4" }, + {"P1 Bet 5", BIT_DIGITAL, DrvJoy3 + 4, "p1 bet 5" }, + {"P1 Bet 6", BIT_DIGITAL, DrvJoy4 + 0, "p1 bet 6" }, + {"P1 Bet 1-2", BIT_DIGITAL, DrvJoy5 + 0, "p1 bet 1-2" }, + {"P1 Bet 1-3", BIT_DIGITAL, DrvJoy5 + 1, "p1 bet 1-3" }, + {"P1 Bet 1-4", BIT_DIGITAL, DrvJoy5 + 2, "p1 bet 1-4" }, + {"P1 Bet 1-5", BIT_DIGITAL, DrvJoy5 + 3, "p1 bet 1-5" }, + {"P1 Bet 1-6", BIT_DIGITAL, DrvJoy5 + 4, "p1 bet 1-6" }, + {"P1 Bet 2-3", BIT_DIGITAL, DrvJoy6 + 0, "p1 bet 2-3" }, + {"P1 Bet 2-4", BIT_DIGITAL, DrvJoy6 + 1, "p1 bet 2-4" }, + {"P1 Bet 2-5", BIT_DIGITAL, DrvJoy6 + 2, "p1 bet 2-5" }, + {"P1 Bet 2-6", BIT_DIGITAL, DrvJoy6 + 3, "p1 bet 2-6" }, + {"P1 Bet 3-4", BIT_DIGITAL, DrvJoy6 + 4, "p1 bet 3-4" }, + {"P1 Bet 3-5", BIT_DIGITAL, DrvJoy7 + 0, "p1 bet 3-5" }, + {"P1 Bet 3-6", BIT_DIGITAL, DrvJoy7 + 1, "p1 bet 3-6" }, + {"P1 Bet 4-5", BIT_DIGITAL, DrvJoy7 + 2, "p1 bet 4-5" }, + {"P1 Bet 4-6", BIT_DIGITAL, DrvJoy7 + 3, "p1 bet 4-6" }, + {"P1 Bet 5-6", BIT_DIGITAL, DrvJoy7 + 4, "p1 bet 5-6" }, + {"P1 Collect", BIT_DIGITAL, DrvJoy4 + 1, "p1 collect" }, + {"P1 Credit", BIT_DIGITAL, DrvJoy4 + 2, "p1 credit" }, + {"P1 Cancel", BIT_DIGITAL, DrvJoy4 + 4, "p1 cancel" }, + + {"P2 A Coin", BIT_DIGITAL, DrvJoy1 + 13, "p2 coin" }, + {"P2 B Coin", BIT_DIGITAL, DrvJoy1 + 12, "p4 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy4 + 11, "p2 start" }, + {"P2 Bet 1", BIT_DIGITAL, DrvJoy3 + 8, "p2 bet 1" }, + {"P2 Bet 2", BIT_DIGITAL, DrvJoy3 + 9, "p2 bet 2" }, + {"P2 Bet 3", BIT_DIGITAL, DrvJoy3 + 10, "p2 bet 3" }, + {"P2 Bet 4", BIT_DIGITAL, DrvJoy3 + 11, "p2 bet 4" }, + {"P2 Bet 5", BIT_DIGITAL, DrvJoy3 + 12, "p2 bet 5" }, + {"P2 Bet 6", BIT_DIGITAL, DrvJoy4 + 8, "p2 bet 6" }, + {"P2 Bet 1-2", BIT_DIGITAL, DrvJoy5 + 8, "p2 bet 1-2" }, + {"P2 Bet 1-3", BIT_DIGITAL, DrvJoy5 + 9, "p2 bet 1-3" }, + {"P2 Bet 1-4", BIT_DIGITAL, DrvJoy5 + 10, "p2 bet 1-4" }, + {"P2 Bet 1-5", BIT_DIGITAL, DrvJoy5 + 11, "p2 bet 1-5" }, + {"P2 Bet 1-6", BIT_DIGITAL, DrvJoy5 + 12, "p2 bet 1-6" }, + {"P2 Bet 2-3", BIT_DIGITAL, DrvJoy6 + 8, "p2 bet 2-3" }, + {"P2 Bet 2-4", BIT_DIGITAL, DrvJoy6 + 9, "p2 bet 2-4" }, + {"P2 Bet 2-5", BIT_DIGITAL, DrvJoy6 + 10, "p2 bet 2-5" }, + {"P2 Bet 2-6", BIT_DIGITAL, DrvJoy6 + 11, "p2 bet 2-6" }, + {"P2 Bet 3-4", BIT_DIGITAL, DrvJoy6 + 12, "p2 bet 3-4" }, + {"P2 Bet 3-5", BIT_DIGITAL, DrvJoy7 + 8, "p2 bet 3-5" }, + {"P2 Bet 3-6", BIT_DIGITAL, DrvJoy7 + 9, "p2 bet 3-6" }, + {"P2 Bet 4-5", BIT_DIGITAL, DrvJoy7 + 10, "p2 bet 4-5" }, + {"P2 Bet 4-6", BIT_DIGITAL, DrvJoy7 + 11, "p2 bet 4-6" }, + {"P2 Bet 5-6", BIT_DIGITAL, DrvJoy7 + 12, "p2 bet 5-6" }, + {"P2 Collect", BIT_DIGITAL, DrvJoy4 + 9, "p2 collect" }, + {"P2 Credit", BIT_DIGITAL, DrvJoy4 + 10, "p2 credit" }, + {"P2 Cancel", BIT_DIGITAL, DrvJoy4 + 12, "p2 cancel" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 14, "service" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Dip D", BIT_DIPSWITCH, DrvDips + 3, "dip" }, + {"Dip E", BIT_DIPSWITCH, DrvDips + 4, "dip" }, + {"Dip F", BIT_DIPSWITCH, DrvDips + 5, "dip" }, + {"Dip 10", BIT_DIPSWITCH, DrvDips + 6, "dip" }, +}; + +STDINPUTINFO(Jockeyc) + +#undef A + +static struct BurnDIPInfo CrazyfgtDIPList[]= +{ + {0x09, 0xff, 0xff, 0x3f, NULL }, + {0x0a, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x09, 0x01, 0x07, 0x00, "4 Coins 1 Credits" }, + {0x09, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x09, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x09, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x09, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x09, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x09, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x09, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x09, 0x01, 0x38, 0x00, "4 Coins 1 Credits" }, + {0x09, 0x01, 0x38, 0x08, "3 Coins 1 Credits" }, + {0x09, 0x01, 0x38, 0x10, "2 Coins 1 Credits" }, + {0x09, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x09, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x09, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x09, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x09, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 4, "Unknown" }, + {0x09, 0x01, 0xc0, 0xc0, "5" }, + {0x09, 0x01, 0xc0, 0x80, "10" }, + {0x09, 0x01, 0xc0, 0x40, "15" }, + {0x09, 0x01, 0xc0, 0x00, "20" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0a, 0x01, 0x01, 0x01, "Off" }, + {0x0a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty?" }, + {0x0a, 0x01, 0x0c, 0x0c, "0" }, + {0x0a, 0x01, 0x0c, 0x08, "1" }, + {0x0a, 0x01, 0x0c, 0x04, "2" }, + {0x0a, 0x01, 0x0c, 0x00, "3" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x0a, 0x01, 0x30, 0x10, "24" }, + {0x0a, 0x01, 0x30, 0x20, "32" }, + {0x0a, 0x01, 0x30, 0x30, "48" }, + {0x0a, 0x01, 0x30, 0x00, "100" }, + + {0 , 0xfe, 0 , 4, "Bonus?" }, + {0x0a, 0x01, 0xc0, 0xc0, "0" }, + {0x0a, 0x01, 0xc0, 0x80, "1" }, + {0x0a, 0x01, 0xc0, 0x40, "2" }, + {0x0a, 0x01, 0xc0, 0x00, "3" }, +}; + +STDDIPINFO(Crazyfgt) + + +static struct BurnDIPInfo UsclssicDIPList[]= +{ + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Credits For 9-Hole" }, + {0x0d, 0x01, 0x01, 0x01, "2" }, + {0x0d, 0x01, 0x01, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Game Type" }, + {0x0d, 0x01, 0x02, 0x02, "Domestic" }, + {0x0d, 0x01, 0x02, 0x00, "Foreign" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0d, 0x01, 0x0c, 0x04, "1" }, + {0x0d, 0x01, 0x0c, 0x08, "2" }, + {0x0d, 0x01, 0x0c, 0x0c, "3" }, + {0x0d, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x0d, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0e, 0x01, 0x01, 0x00, "Upright" }, + {0x0e, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0e, 0x01, 0x02, 0x02, "Off" }, + {0x0e, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Flight Distance" }, + {0x0e, 0x01, 0x38, 0x38, "Normal" }, + {0x0e, 0x01, 0x38, 0x30, "-30 Yards" }, + {0x0e, 0x01, 0x38, 0x28, "+10 Yards" }, + {0x0e, 0x01, 0x38, 0x20, "+20 Yards" }, + {0x0e, 0x01, 0x38, 0x18, "+30 Yards" }, + {0x0e, 0x01, 0x38, 0x10, "+40 Yards" }, + {0x0e, 0x01, 0x38, 0x08, "+50 Yards" }, + {0x0e, 0x01, 0x38, 0x00, "+60 Yards" }, + + {0 , 0xfe, 0 , 4, "Licensed To" }, + {0x0e, 0x01, 0xc0, 0xc0, "Romstar" }, + {0x0e, 0x01, 0xc0, 0x80, "None (Japan)" }, + {0x0e, 0x01, 0xc0, 0x40, "Taito" }, + {0x0e, 0x01, 0xc0, 0x00, "Taito America" }, +}; + +STDDIPINFO(Usclssic) + + +static struct BurnDIPInfo Calibr50DIPList[]= +{ + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x15, 0x01, 0x01, 0x01, "Romstar" }, + {0x15, 0x01, 0x01, 0x00, "None (Japan)" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x03, "Easiest" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x01, "Normal" }, + {0x16, 0x01, 0x03, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Score Digits" }, + {0x16, 0x01, 0x04, 0x04, "7" }, + {0x16, 0x01, 0x04, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x16, 0x01, 0x08, 0x08, "3" }, + {0x16, 0x01, 0x08, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Display Score" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Erase Backup Ram" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x16, 0x01, 0x40, 0x40, "Taito America" }, + {0x16, 0x01, 0x40, 0x40, "Taito" }, +}; + +STDDIPINFO(Calibr50) + +static struct BurnDIPInfo TwineaglDIPList[]= +{ + {0x13, 0xff, 0xff, 0xf7, NULL }, + {0x14, 0xff, 0xff, 0xf3, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Copyright" }, + {0x13, 0x01, 0x01, 0x01, "Taito" }, + {0x13, 0x01, 0x01, 0x00, "Taito America (Romstar license)" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x08, 0x00, "Upright" }, + {0x13, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "Never" }, + {0x14, 0x01, 0x0c, 0x08, "500K Only" }, + {0x14, 0x01, 0x0c, 0x04, "1000K Only" }, + {0x14, 0x01, 0x0c, 0x00, "500K, Every 1500K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Copyright" }, + {0x14, 0x01, 0x40, 0x40, "Seta (Taito license)" }, + {0x14, 0x01, 0x40, 0x40, "Taito America" }, + + {0 , 0xfe, 0 , 2, "Coinage Type" }, + {0x14, 0x01, 0x80, 0x80, "1" }, + {0x14, 0x01, 0x80, 0x00, "2" }, +}; + +STDDIPINFO(Twineagl) + +static struct BurnDIPInfo KiwameDIPList[]= +{ + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xff, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x19, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x19, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x19, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x20, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x38, 0x18, "2 Coins 3 Credits" }, + {0x19, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x19, 0x01, 0x40, 0x00, "Off" }, + {0x19, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Player's TSUMO" }, + {0x19, 0x01, 0x80, 0x80, "Manual" }, + {0x19, 0x01, 0x80, 0x00, "Auto" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1a, 0x01, 0x01, 0x01, "Off" }, + {0x1a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1a, 0x01, 0x02, 0x02, "Off" }, + {0x1a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x1a, 0x01, 0x1c, 0x1c, "None" }, + {0x1a, 0x01, 0x1c, 0x18, "Prelim 1" }, + {0x1a, 0x01, 0x1c, 0x14, "Prelim 2" }, + {0x1a, 0x01, 0x1c, 0x10, "Final 1" }, + {0x1a, 0x01, 0x1c, 0x0c, "Final 2" }, + {0x1a, 0x01, 0x1c, 0x08, "Final 3" }, + {0x1a, 0x01, 0x1c, 0x04, "Qrt Final" }, + {0x1a, 0x01, 0x1c, 0x00, "SemiFinal" }, + + {0 , 0xfe, 0 , 8, "Points Gap" }, + {0x1a, 0x01, 0xe0, 0xe0, "None" }, + {0x1a, 0x01, 0xe0, 0xc0, "+6000" }, + {0x1a, 0x01, 0xe0, 0xa0, "+4000" }, + {0x1a, 0x01, 0xe0, 0x80, "+2000" }, + {0x1a, 0x01, 0xe0, 0x60, "-2000" }, + {0x1a, 0x01, 0xe0, 0x40, "-4000" }, + {0x1a, 0x01, 0xe0, 0x20, "-6000" }, + {0x1a, 0x01, 0xe0, 0x00, "-8000" }, +}; + +STDDIPINFO(Kiwame) + +static struct BurnDIPInfo MetafoxDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xb1, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x13, 0x01, 0x01, 0x01, "Jordan" }, + {0x13, 0x01, 0x01, 0x00, "Taito America" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + {0x14, 0x01, 0x0c, 0x08, "60K Only" }, + {0x14, 0x01, 0x0c, 0x00, "60k & 90k" }, + {0x14, 0x01, 0x0c, 0x04, "90K Only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x14, 0x01, 0x40, 0x40, "Romstar" }, + {0x14, 0x01, 0x40, 0x00, "Taito" }, + + {0 , 0xfe, 0 , 2, "Coinage Type" }, + {0x14, 0x01, 0x80, 0x80, "1" }, + {0x14, 0x01, 0x80, 0x00, "2" }, +}; + +STDDIPINFO(Metafox) + +static struct BurnDIPInfo ArbalestDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xbf, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x13, 0x01, 0x01, 0x00, "Taito" }, + {0x13, 0x01, 0x01, 0x01, "Jordan" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Easy" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x01, "Harder" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "Never" }, + {0x14, 0x01, 0x0c, 0x08, "300k Only" }, + {0x14, 0x01, 0x0c, 0x04, "600k Only" }, + {0x14, 0x01, 0x0c, 0x00, "300k & 600k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 1, "Licensed To" }, + {0x14, 0x01, 0x40, 0x40, "Romstar" }, + + {0 , 0xfe, 0 , 2, "Coinage Type" }, + {0x14, 0x01, 0x80, 0x80, "1" }, + {0x14, 0x01, 0x80, 0x00, "2" }, +}; + +STDDIPINFO(Arbalest) + +static struct BurnDIPInfo DowntownDIPList[]= +{ + {0x15, 0xff, 0xff, 0xf6, NULL }, + {0x16, 0xff, 0xff, 0xbd, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Sales" }, + {0x15, 0x01, 0x01, 0x01, "Japan Only" }, + {0x15, 0x01, 0x01, 0x00, "World" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Normal" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "Never" }, + {0x16, 0x01, 0x0c, 0x08, "50K Only" }, + {0x16, 0x01, 0x0c, 0x04, "100K Only" }, + {0x16, 0x01, 0x0c, 0x00, "50K, Every 150K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x10, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x00, "4" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "World License" }, + {0x16, 0x01, 0x40, 0x40, "Romstar" }, + {0x16, 0x01, 0x40, 0x00, "Taito" }, + + {0 , 0xfe, 0 , 2, "Coinage Type" }, + {0x16, 0x01, 0x80, 0x80, "1" }, + {0x16, 0x01, 0x80, 0x00, "2" }, +}; + +STDDIPINFO(Downtown) + +static struct BurnDIPInfo TndrcadeDIPList[]= +{ + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Hard" }, + {0x13, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x0c, 0x0c, "50K Only" }, + {0x13, 0x01, 0x0c, 0x04, "50K, Every 150K" }, + {0x13, 0x01, 0x0c, 0x00, "70K, Every 200K" }, + {0x13, 0x01, 0x0c, 0x08, "100K Only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x10, "1" }, + {0x13, 0x01, 0x30, 0x00, "2" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Licensed To" }, + {0x13, 0x01, 0x80, 0x80, "Taito America Corp." }, + {0x13, 0x01, 0x80, 0x00, "Taito Corp. Japan" }, + + {0 , 0xfe, 0 , 2, "Title" }, + {0x14, 0x01, 0x01, 0x01, "Thundercade" }, + {0x14, 0x01, 0x01, 0x00, "Twin Formation" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, +}; + +STDDIPINFO(Tndrcade) + +static struct BurnDIPInfo TndrcadjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Hard" }, + {0x13, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x0c, 0x0c, "50K Only" }, + {0x13, 0x01, 0x0c, 0x04, "50K, Every 150K" }, + {0x13, 0x01, 0x0c, 0x00, "70K, Every 200K" }, + {0x13, 0x01, 0x0c, 0x08, "100K Only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x10, "1" }, + {0x13, 0x01, 0x30, 0x00, "2" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, +}; + +STDDIPINFO(Tndrcadj) + +static struct BurnDIPInfo UtoukondDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x00, "5 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x00, "1" }, + {0x15, 0x01, 0x03, 0x02, "2" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x01, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x08, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x04, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x10, 0x10, "Off" }, + {0x15, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x15, 0x01, 0x40, 0x40, "100k" }, + {0x15, 0x01, 0x40, 0x00, "150k" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Utoukond) + +static struct BurnDIPInfo KrzybowlDIPList[]= +{ + {0x18, 0xff, 0xff, 0xff, NULL }, + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x18, 0x01, 0x01, 0x01, "Off" }, + {0x18, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x18, 0x01, 0x02, 0x00, "Off" }, + {0x18, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x18, 0x01, 0x0c, 0x08, "Easy" }, + {0x18, 0x01, 0x0c, 0x0c, "Normal" }, + {0x18, 0x01, 0x0c, 0x04, "Hard" }, + {0x18, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Frames" }, + {0x18, 0x01, 0x10, 0x10, "10" }, + {0x18, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x18, 0x01, 0x20, 0x20, "Upright" }, + {0x18, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Controls" }, + {0x18, 0x01, 0x40, 0x40, "Trackball" }, + {0x18, 0x01, 0x40, 0x00, "Joystick" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x18, 0x01, 0x80, 0x80, "Off" }, + {0x18, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x19, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x19, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x19, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x19, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x19, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x19, 0x01, 0x38, 0x20, "1 Coin 2 Credits" }, + {0x19, 0x01, 0x38, 0x18, "1 Coin 3 Credits" }, + {0x19, 0x01, 0x38, 0x10, "1 Coin 4 Credits" }, + {0x19, 0x01, 0x38, 0x08, "1 Coin 5 Credits" }, + {0x19, 0x01, 0x38, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Force Coinage" }, + {0x19, 0x01, 0x40, 0x40, "No" }, + {0x19, 0x01, 0x40, 0x00, "2 Coins 1 Credits" }, +}; + +STDDIPINFO(Krzybowl) + +static struct BurnDIPInfo ExtdwnhlDIPList[]= +{ + {0x0c, 0xff, 0xff, 0xff, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0c, 0x01, 0x01, 0x01, "Off" }, + {0x0c, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x00, "Off" }, + {0x0c, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0c, 0x01, 0x0c, 0x08, "Easy" }, + {0x0c, 0x01, 0x0c, 0x0c, "Normal" }, + {0x0c, 0x01, 0x0c, 0x04, "Hard" }, + {0x0c, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0c, 0x01, 0x10, 0x10, "Off" }, + {0x0c, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0c, 0x01, 0x20, 0x20, "Upright" }, + {0x0c, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Controls" }, + {0x0c, 0x01, 0x40, 0x40, "2" }, + {0x0c, 0x01, 0x40, 0x00, "1" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0c, 0x01, 0x80, 0x80, "Off" }, + {0x0c, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0d, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x0d, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x0d, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x0d, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x0d, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x0d, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x0d, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x0d, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0x38, 0x20, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0x38, 0x18, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0x38, 0x10, "1 Coin 4 Credits" }, + {0x0d, 0x01, 0x38, 0x08, "1 Coin 5 Credits" }, + {0x0d, 0x01, 0x38, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Continue Coin" }, + {0x0d, 0x01, 0x40, 0x40, "Normal: Start 1C / Continue 1C" }, + {0x0d, 0x01, 0x40, 0x00, "Half Continue: Start 2C / Continue 1C" }, + + {0 , 0xfe, 0 , 2, "Game Mode" }, + {0x0d, 0x01, 0x80, 0x80, "Finals Only" }, + {0x0d, 0x01, 0x80, 0x00, "Semi-Finals & Finals" }, + + {0 , 0xfe, 0 , 2, "Service Mode (No Toggle)" }, + {0x0e, 0x01, 0x08, 0x08, "Off" }, + {0x0e, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 3, "Country" }, + {0x0e, 0x01, 0x30, 0x30, "World" }, + {0x0e, 0x01, 0x30, 0x10, "USA" }, + {0x0e, 0x01, 0x30, 0x00, "Japan" }, +}; + +STDDIPINFO(Extdwnhl) + +static struct BurnDIPInfo SokonukeDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x01, 0x01, "Off" }, + {0x10, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x00, "Off" }, + {0x10, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x0c, 0x08, "Easy" }, + {0x10, 0x01, 0x0c, 0x0c, "Normal" }, + {0x10, 0x01, 0x0c, 0x04, "Hard" }, + {0x10, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x10, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x08, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x38, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Cheap Continue" }, + {0x11, 0x01, 0x40, 0x40, "No" }, + {0x11, 0x01, 0x40, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Sokonuke) + +static struct BurnDIPInfo JjsquawkDIPList[]= +{ + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xef, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x18, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Energy" }, + {0x13, 0x01, 0x30, 0x20, "2" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x10, "4" }, + {0x13, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0xc0, 0x80, "20K, Every 100K" }, + {0x13, 0x01, 0xc0, 0xc0, "50K, Every 200K" }, + {0x13, 0x01, 0xc0, 0x40, "70K, 200K Only" }, + {0x13, 0x01, 0xc0, 0x00, "100K Only" }, +}; + +STDDIPINFO(Jjsquawk) + +static struct BurnDIPInfo KeroppiDIPList[]= +{ + {0x04, 0xff, 0xff, 0xff, NULL }, + {0x05, 0xff, 0xff, 0xbf, NULL }, + {0x06, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x04, 0x01, 0x07, 0x03, "1" }, + {0x04, 0x01, 0x07, 0x05, "2" }, + {0x04, 0x01, 0x07, 0x01, "3" }, + {0x04, 0x01, 0x07, 0x07, "4" }, + {0x04, 0x01, 0x07, 0x06, "5" }, + {0x04, 0x01, 0x07, 0x02, "6" }, + {0x04, 0x01, 0x07, 0x04, "7" }, + {0x04, 0x01, 0x07, 0x00, "8" }, + + {0 , 0xfe, 0 , 8, "Game Select" }, + {0x04, 0x01, 0x38, 0x38, "No. 1,2,3" }, + {0x04, 0x01, 0x38, 0x30, "No. 1" }, + {0x04, 0x01, 0x38, 0x28, "No. 2,3" }, + {0x04, 0x01, 0x38, 0x20, "No. 3" }, + {0x04, 0x01, 0x38, 0x18, "No. 1,2" }, + {0x04, 0x01, 0x38, 0x10, "No. 2" }, + {0x04, 0x01, 0x38, 0x08, "No. 1,3" }, + {0x04, 0x01, 0x38, 0x00, "No. 1,2,3" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x05, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x05, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x05, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x05, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x05, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x05, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x05, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x05, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x05, 0x01, 0x20, 0x20, "Off" }, + {0x05, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x05, 0x01, 0x40, 0x40, "Off" }, + {0x05, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x05, 0x01, 0x80, 0x80, "Off" }, + {0x05, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Keroppi) + +static struct BurnDIPInfo OrbsDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x01, 0x01, "Off" }, + {0x10, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x00, "Off" }, + {0x10, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x0c, 0x08, "Easy" }, + {0x10, 0x01, 0x0c, 0x0c, "Normal" }, + {0x10, 0x01, 0x0c, 0x04, "Hard" }, + {0x10, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Stock" }, + {0x10, 0x01, 0x10, 0x10, "1" }, + {0x10, 0x01, 0x10, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Level Select" }, + {0x10, 0x01, 0x20, 0x20, "Off" }, + {0x10, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Timer speed" }, + {0x10, 0x01, 0x40, 0x40, "Normal" }, + {0x10, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x10, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x08, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x38, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Force Coinage (Half)" }, + {0x11, 0x01, 0x40, 0x40, "No" }, + {0x11, 0x01, 0x40, 0x00, "2 Coins 1 Credits" }, +}; + +STDDIPINFO(Orbs) + +static struct BurnDIPInfo PairloveDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x04, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x14, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Pairlove) + +static struct BurnDIPInfo OisipuzlDIPList[]= +{ + {0x12, 0xff, 0xff, 0xfb, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x03, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Oisipuzl) + +static struct BurnDIPInfo BlandiaDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage Type" }, + {0x15, 0x01, 0x02, 0x02, "1" }, + {0x15, 0x01, 0x02, 0x00, "2" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x15, 0x01, 0x1c, 0x10, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x1c, 0x0c, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x1c, 0x04, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x1c, 0x18, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x1c, 0x08, "2 Coins 5 Credits" }, + {0x15, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x1c, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x15, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xe0, 0x60, "2 Coins 4 Credits" }, + {0x15, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xe0, 0x80, "3 Coins/7 Credits" }, + {0x15, 0x01, 0xe0, 0x20, "2 Coins 5 Credits" }, + {0x15, 0x01, 0xe0, 0x40, "2 Coins 6 Credits" }, + {0x15, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xe0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "1" }, + {0x16, 0x01, 0x03, 0x03, "2" }, + {0x16, 0x01, 0x03, 0x01, "3" }, + {0x16, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + {0x16, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "2 Player Game" }, + {0x16, 0x01, 0x10, 0x10, "2 Credits" }, + {0x16, 0x01, 0x10, 0x00, "1 Credit" }, + + {0 , 0xfe, 0 , 2, "Continue" }, + {0x16, 0x01, 0x20, 0x20, "1 Credit" }, + {0x16, 0x01, 0x20, 0x00, "1 Coin" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Blandia) + +static struct BurnDIPInfo GundharaDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0x30, 0x00, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x14, 0x01, 0xc0, 0xc0, "Japanese" }, + {0x14, 0x01, 0xc0, 0x00, "English" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Normal" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x0c, 0x08, "1" }, + {0x15, 0x01, 0x0c, 0x0c, "2" }, + {0x15, 0x01, 0x0c, 0x04, "3" }, + {0x15, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x30, 0x30, "200K" }, + {0x15, 0x01, 0x30, 0x20, "200K, Every 200K" }, + {0x15, 0x01, 0x30, 0x10, "400K" }, + {0x15, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x08, 0x08, "Off" }, + {0x16, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Gundhara) + +static struct BurnDIPInfo AtehateDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0e, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x0e, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x0e, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x38, 0x20, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x38, 0x18, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x0f, 0x01, 0x01, 0x01, "Off" }, + {0x0f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x0f, 0x01, 0x0c, 0x08, "Easy" }, + {0x0f, 0x01, 0x0c, 0x0c, "Normal" }, + {0x0f, 0x01, 0x0c, 0x04, "Hard" }, + {0x0f, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0x30, 0x00, "2" }, + {0x0f, 0x01, 0x30, 0x30, "3" }, + {0x0f, 0x01, 0x30, 0x10, "4" }, + {0x0f, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0f, 0x01, 0xc0, 0xc0, "None" }, + {0x0f, 0x01, 0xc0, 0x00, "20K Only" }, + {0x0f, 0x01, 0xc0, 0x80, "20K, Every 30K" }, + {0x0f, 0x01, 0xc0, 0x40, "30K, Every 40K" }, +}; + +STDDIPINFO(Atehate) + +static struct BurnDIPInfo ThunderlDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xe9, NULL }, + {0x15, 0xff, 0xff, 0xef, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x0c, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "4 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x04, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "4 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "3 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "2 Coins 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "4 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "4 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "3 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "2 Coins 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x04, 0x00, "Upright" }, + {0x14, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Controls" }, + {0x14, 0x01, 0x08, 0x08, "2" }, + {0x14, 0x01, 0x08, 0x00, "1" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x14, 0x01, 0x20, 0x20, "3" }, + {0x14, 0x01, 0x20, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0xc0, 0x80, "Easy" }, + {0x14, 0x01, 0xc0, 0xc0, "Normal" }, + {0x14, 0x01, 0xc0, 0x40, "Hard" }, + {0x14, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Force 1 Life" }, + {0x15, 0x01, 0x10, 0x00, "Off" }, + {0x15, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 5, "Copyright" }, + {0x15, 0x01, 0xe0, 0x80, "Romstar" }, + {0x15, 0x01, 0xe0, 0xc0, "Seta (Romstar License)"}, + {0x15, 0x01, 0xe0, 0xe0, "Seta (Visco License)" }, + {0x15, 0x01, 0xe0, 0xa0, "Visco" }, + {0x15, 0x01, 0xe0, 0x60, "None" }, +}; + +STDDIPINFO(Thunderl) + +static struct BurnDIPInfo WitsDIPList[]= +{ + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0xff, NULL }, + {0x23, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x21, 0x01, 0x03, 0x02, "Easy" }, + {0x21, 0x01, 0x03, 0x03, "Normal" }, + {0x21, 0x01, 0x03, 0x01, "Hard" }, + {0x21, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x21, 0x01, 0x0c, 0x08, "150k, 350k" }, + {0x21, 0x01, 0x0c, 0x0c, "200k, 500k" }, + {0x21, 0x01, 0x0c, 0x04, "300k, 600k" }, + {0x21, 0x01, 0x0c, 0x00, "400k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x21, 0x01, 0x30, 0x00, "1" }, + {0x21, 0x01, 0x30, 0x10, "2" }, + {0x21, 0x01, 0x30, 0x30, "3" }, + {0x21, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Play Mode" }, + {0x21, 0x01, 0x40, 0x40, "2 Players" }, + {0x21, 0x01, 0x40, 0x00, "4 Players" }, + + {0 , 0xfe, 0 , 2, "CPU Player During Multi-Player Game" }, + {0x21, 0x01, 0x80, 0x00, "No" }, + {0x21, 0x01, 0x80, 0x80, "Yes" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x22, 0x01, 0x01, 0x01, "Upright" }, + {0x22, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x22, 0x01, 0x02, 0x02, "Off" }, + {0x22, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x22, 0x01, 0x04, 0x04, "Every 3rd Loop" }, + {0x22, 0x01, 0x04, 0x00, "Every 7th Loop" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x22, 0x01, 0x08, 0x08, "Off" }, + {0x22, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x22, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x22, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x22, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x22, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x22, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x22, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x22, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x22, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "License" }, + {0x23, 0x01, 0xc0, 0xc0, "Romstar" }, + {0x23, 0x01, 0xc0, 0x80, "Seta U.S.A" }, + {0x23, 0x01, 0xc0, 0x40, "Visco (Japan Only)" }, + {0x23, 0x01, 0xc0, 0x00, "Athena (Japan Only)" }, +}; + +STDDIPINFO(Wits) + +static struct BurnDIPInfo MadsharkDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 0, "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "1000k" }, + {0x13, 0x01, 0x18, 0x08, "1000k 2000k" }, + {0x13, 0x01, 0x18, 0x10, "1500k 3000k" }, + {0x13, 0x01, 0x18, 0x00, "No" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x40, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x14, 0x01, 0x03, 0x02, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x01, "4" }, + {0x14, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x1c, 0x04, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x08, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x1c, 0x0c, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x1c, 0x18, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x1c, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x14, 0x01, 0xe0, 0x20, "4 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0x40, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xe0, 0x60, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xe0, 0x00, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Country" }, + {0x15, 0x01, 0x80, 0x80, "Japan" }, + {0x15, 0x01, 0x80, 0x00, "World" }, +}; + +STDDIPINFO(Madshark) + +static struct BurnDIPInfo MsgundamDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x06, 0x04, "Easy" }, + {0x14, 0x01, 0x06, 0x06, "Normal" }, + {0x14, 0x01, 0x06, 0x02, "Hard" }, + {0x14, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Memory Check" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x15, 0x01, 0x80, 0x80, "English" }, + {0x15, 0x01, 0x80, 0x00, "Japanese" }, +}; + +STDDIPINFO(Msgundam) + +static struct BurnDIPInfo Msgunda1DIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x06, 0x04, "Easy" }, + {0x14, 0x01, 0x06, 0x06, "Normal" }, + {0x14, 0x01, 0x06, 0x02, "Hard" }, + {0x14, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Memory Check" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 1, "Language" }, + {0x15, 0x01, 0x80, 0x00, "Japanese" }, +}; + +STDDIPINFO(Msgunda1) + +static struct BurnDIPInfo ZingzipDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x08, "Easy" }, + {0x13, 0x01, 0x0c, 0x0c, "Normal" }, + {0x13, 0x01, 0x0c, 0x04, "Hard" }, + {0x13, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 0, "Coinage" }, + {0x13, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Zingzip) + +static struct BurnDIPInfo WrofaeroDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Stage & Weapon Select"}, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x03, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x16, 0x01, 0x0c, 0x08, "Easy" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Hard" }, + {0x16, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x16, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x16, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x16, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x16, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x16, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x16, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x16, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x16, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x16, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Wrofaero) + +static struct BurnDIPInfo EightfrcDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7b, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x20, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x08, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Shared Credits" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Credits To Start" }, + {0x13, 0x01, 0x80, 0x80, "1" }, + {0x13, 0x01, 0x80, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x18, 0x10, "Easy" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x08, "Hard" }, + {0x14, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x60, 0x40, "2" }, + {0x14, 0x01, 0x60, 0x60, "3" }, + {0x14, 0x01, 0x60, 0x20, "4" }, + {0x14, 0x01, 0x60, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x14, 0x01, 0x80, 0x00, "English" }, + {0x14, 0x01, 0x80, 0x80, "Japanese" }, +}; + +STDDIPINFO(Eightfrc) + +static struct BurnDIPInfo RezonDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x14, 0x01, 0x18, 0x00, "Upright 1 Controller" }, + {0x14, 0x01, 0x18, 0x18, "Upright 2 Controllers"}, + {0x14, 0x01, 0x18, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x02, "2" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x01, "4" }, + {0x15, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x08, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x04, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x15, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x15, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x15, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x08, 0x08, "Off" }, + {0x16, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Taito Logo" }, + {0x16, 0x01, 0x10, 0x00, "Off" }, + {0x16, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(Rezon) + +static struct BurnDIPInfo Qzkklgy2DIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Highlight Right Answer" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Skip Real DAT Rom Check?" }, + {0x0e, 0x01, 0x08, 0x08, "Off" }, + {0x0e, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x0f, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x0f, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0x07, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x0f, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0f, 0x01, 0x08, 0x08, "Off" }, + {0x0f, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0f, 0x01, 0x30, 0x30, "Easy" }, + {0x0f, 0x01, 0x30, 0x20, "Normal" }, + {0x0f, 0x01, 0x30, 0x10, "Hard" }, + {0x0f, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0xc0, 0x80, "2" }, + {0x0f, 0x01, 0xc0, 0xc0, "3" }, + {0x0f, 0x01, 0xc0, 0x40, "4" }, + {0x0f, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Qzkklgy2) + +static struct BurnDIPInfo QzkklogyDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Highlight Right Answer" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0f, 0x01, 0x80, 0x80, "Off" }, + {0x0f, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x10, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x10, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x07, 0x01, "2 Coins 3 Credits" }, + {0x10, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x10, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x10, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x30, 0x20, "Easy" }, + {0x10, 0x01, 0x30, 0x30, "Normal" }, + {0x10, 0x01, 0x30, 0x10, "Hard" }, + {0x10, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x10, 0x01, 0xc0, 0x80, "2" }, + {0x10, 0x01, 0xc0, 0xc0, "3" }, + {0x10, 0x01, 0xc0, 0x40, "4" }, + {0x10, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Qzkklogy) + +static struct BurnDIPInfo StgDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Hard" }, + {0x13, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x10, "1" }, + {0x13, 0x01, 0x30, 0x00, "2" }, + {0x13, 0x01, 0x30, 0x30, "3" }, + {0x13, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Stg) + +static struct BurnDIPInfo DrgnunitDIPList[]= +{ + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x03, 0x03, "Easy" }, + {0x15, 0x01, 0x03, 0x02, "Normal" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x08, "150K, Every 300K" }, + {0x15, 0x01, 0x0c, 0x0c, "200K, Every 400K" }, + {0x15, 0x01, 0x0c, 0x04, "300K, Every 500K" }, + {0x15, 0x01, 0x0c, 0x00, "400K Only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x30, 0x00, "1" }, + {0x15, 0x01, 0x30, 0x10, "2" }, + {0x15, 0x01, 0x30, 0x30, "3" }, + {0x15, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x16, 0x01, 0x04, 0x04, "1 of 4 Scenes" }, + {0x16, 0x01, 0x04, 0x00, "1 of 8 Scenes" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x08, 0x08, "Off" }, + {0x16, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x16, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x16, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Coin B" }, + {0x16, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x16, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x16, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x16, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coinage Type" }, + {0x17, 0x01, 0x10, 0x10, "1" }, + {0x17, 0x01, 0x10, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Title" }, + {0x17, 0x01, 0x20, 0x20, "Dragon Unit" }, + {0x17, 0x01, 0x20, 0x00, "Castle of Dragon" }, + + {0 , 0xfe, 0 , 2, "(C) / License" }, + {0x17, 0x01, 0xc0, 0xc0, "Athena (Japan)" }, + {0x17, 0x01, 0xc0, 0x80, "Athena / Taito (Japan)" }, + {0x17, 0x01, 0xc0, 0x40, "Seta USA / Taito America" }, + {0x17, 0x01, 0xc0, 0x00, "Seta USA / Romstar" }, +}; + +STDDIPINFO(Drgnunit) + +static struct BurnDIPInfo DaiohDIPList[]= +{ + {0x1a, 0xff, 0xff, 0x7f, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x1a, 0x01, 0x07, 0x01, "4 Coins 1 Credits" }, + {0x1a, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x1a, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x1a, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x1a, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x1a, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x1a, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x1a, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x1a, 0x01, 0x38, 0x08, "4 Coins 1 Credits" }, + {0x1a, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x1a, 0x01, 0x38, 0x20, "2 Coins 1 Credits" }, + {0x1a, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x1a, 0x01, 0x38, 0x18, "2 Coins 3 Credits" }, + {0x1a, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x1a, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x1a, 0x01, 0x38, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1a, 0x01, 0x40, 0x00, "Off" }, + {0x1a, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Auto Shot" }, + {0x1a, 0x01, 0x80, 0x80, "Off" }, + {0x1a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1b, 0x01, 0x01, 0x01, "Off" }, + {0x1b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1b, 0x01, 0x02, 0x02, "Off" }, + {0x1b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1b, 0x01, 0x0c, 0x08, "Easy" }, + {0x1b, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1b, 0x01, 0x0c, 0x04, "Hard" }, + {0x1b, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x1b, 0x01, 0x30, 0x00, "1" }, + {0x1b, 0x01, 0x30, 0x10, "2" }, + {0x1b, 0x01, 0x30, 0x30, "3" }, + {0x1b, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x1b, 0x01, 0xc0, 0x80, "300k and every 800k" }, + {0x1b, 0x01, 0xc0, 0xc0, "500k and every 1000k" }, + {0x1b, 0x01, 0xc0, 0x40, "800k and 2000k only" }, + {0x1b, 0x01, 0xc0, 0x00, "1000k Only" }, + + {0 , 0xfe, 0 , 2, "Country" }, + {0x1c, 0x01, 0x80, 0x80, "USA (6 buttons)" }, + {0x1c, 0x01, 0x80, 0x00, "Japan (2 buttons)" }, +}; + +STDDIPINFO(Daioh) + +static struct BurnDIPInfo NeobattlDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x00, "Off" }, + {0x11, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Stage Select" }, + {0x11, 0x01, 0x08, 0x08, "Off" }, + {0x11, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x02, "1" }, + {0x12, 0x01, 0x03, 0x03, "2" }, + {0x12, 0x01, 0x03, 0x01, "3" }, + {0x12, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x12, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Neobattl) + +static struct BurnDIPInfo UmanclubDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Stage Select" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x02, "1" }, + {0x14, 0x01, 0x03, 0x03, "2" }, + {0x14, 0x01, 0x03, 0x01, "3" }, + {0x14, 0x01, 0x03, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x04, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x14, 0x01, 0xf0, 0xa0, "6 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "4 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "8 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x20, "5 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0x30, "3 Coins 2 Credits" }, + {0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xf0, 0x40, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x80, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Umanclub) + +static struct BurnDIPInfo KamenridDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Intro Music" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x14, 0x01, 0x0f, 0x05, "6 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "5 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x03, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x08, "8 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x04, "5 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "3 Coins 2 Credits" }, + {0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0f, 0x02, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x10, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Country" }, + {0x15, 0x01, 0x80, 0x80, "USA" }, + {0x15, 0x01, 0x80, 0x00, "Japan" }, +}; + +STDDIPINFO(Kamenrid) + +static struct BurnDIPInfo BlockcarDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x03, 0x02, "Easy" }, + {0x13, 0x01, 0x03, 0x03, "Normal" }, + {0x13, 0x01, 0x03, 0x01, "Hard" }, + {0x13, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x0c, 0x0c, "20K, Every 50K" }, + {0x13, 0x01, 0x0c, 0x04, "20K, Every 70K" }, + {0x13, 0x01, 0x0c, 0x08, "30K, Every 60K" }, + {0x13, 0x01, 0x0c, 0x00, "30K, Every 90K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x30, 0x00, "1" }, + {0x13, 0x01, 0x30, 0x30, "2" }, + {0x13, 0x01, 0x30, 0x20, "3" }, + {0x13, 0x01, 0x30, 0x10, "4" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x04, 0x00, "Off" }, + {0x14, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Title" }, + {0x15, 0x01, 0x10, 0x10, "Thunder & Lightning 2" }, + {0x15, 0x01, 0x10, 0x00, "Block Carnival" }, +}; + +STDDIPINFO(Blockcar) + +static struct BurnDIPInfo ZombraidDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xfd, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Vertical Screen Flip" }, + {0x0e, 0x01, 0x01, 0x01, "Off" }, + {0x0e, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Horizontal Screen Flip" }, + {0x0e, 0x01, 0x02, 0x00, "Off" }, + {0x0e, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0e, 0x01, 0x04, 0x00, "Off" }, + {0x0e, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0e, 0x01, 0x18, 0x10, "Easy" }, + {0x0e, 0x01, 0x18, 0x18, "Normal" }, + {0x0e, 0x01, 0x18, 0x08, "Hard" }, + {0x0e, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x0e, 0x01, 0x20, 0x00, "Off" }, + {0x0e, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0f, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x0f, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x0f, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x0f, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x0f, 0x01, 0x38, 0x28, "3 Coins 1 Credits" }, + {0x0f, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x0f, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x0f, 0x01, 0x38, 0x20, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0x38, 0x18, "1 Coin 3 Credits" }, + {0x0f, 0x01, 0x38, 0x10, "1 Coin 4 Credits" }, + {0x0f, 0x01, 0x38, 0x08, "1 Coin 5 Credits" }, + {0x0f, 0x01, 0x38, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x0f, 0x01, 0x40, 0x40, "No" }, + {0x0f, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Zombraid) + +static struct BurnDIPInfo JockeycDIPList[]= +{ + {0x39, 0xff, 0xff, 0xff, NULL }, + {0x3a, 0xff, 0xff, 0xff, NULL }, + {0x3b, 0xff, 0xff, 0xff, NULL }, + + {0x3c, 0xff, 0xff, 0xff, NULL }, + {0x3d, 0xff, 0xff, 0xff, NULL }, + {0x3e, 0xff, 0xff, 0xff, NULL }, + {0x3f, 0xff, 0xff, 0xff, NULL }, + +// dip1 + {0 , 0xfe, 0 , 3, "Max Bet" }, + {0x39, 0x01, 0x03, 0x03, "10" }, + {0x39, 0x01, 0x03, 0x02, "20" }, + {0x39, 0x01, 0x03, 0x01, "99" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x39, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x39, 0x01, 0x1c, 0x18, "1 Coin 2 Credits" }, + {0x39, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x39, 0x01, 0x1c, 0x10, "1 Coin 4 Credits" }, + {0x39, 0x01, 0x1c, 0x0c, "1 Coin 5 Credits" }, + {0x39, 0x01, 0x1c, 0x08, "1 Coin/10 Credits" }, + {0x39, 0x01, 0x1c, 0x04, "1 Coin/20 Credits" }, + {0x39, 0x01, 0x1c, 0x00, "1 Coin/50 Credits" }, + +// dip2-3 + {0 , 0xfe, 0 , 4, "Betting Clock Speed" }, + {0x3a, 0x01, 0x18, 0x18, "Slowest" }, + {0x3a, 0x01, 0x18, 0x10, "Slower" }, + {0x3a, 0x01, 0x18, 0x08, "Faster" }, + {0x3a, 0x01, 0x18, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 16, "Payout Rate" }, + {0x3b, 0x01, 0x01, 0x01, "80%" }, + {0x3b, 0x01, 0x01, 0x01, "81%" }, + {0x3b, 0x01, 0x01, 0x01, "82%" }, + {0x3b, 0x01, 0x01, 0x01, "83%" }, + {0x3b, 0x01, 0x01, 0x01, "84%" }, + {0x3b, 0x01, 0x01, 0x01, "85%" }, + {0x3b, 0x01, 0x01, 0x01, "86%" }, + {0x3b, 0x01, 0x01, 0x01, "87%" }, + {0x3b, 0x01, 0x01, 0xe0, "88%" }, + {0x3b, 0x01, 0x01, 0xc0, "89%" }, + {0x3b, 0x01, 0x01, 0xa0, "90%" }, + {0x3b, 0x01, 0x01, 0x80, "91%" }, + {0x3b, 0x01, 0x01, 0x60, "92%" }, + {0x3b, 0x01, 0x01, 0x40, "93%" }, + {0x3b, 0x01, 0x01, 0x20, "94%" }, + {0x3b, 0x01, 0x01, 0x00, "95%" }, + + {0 , 0xfe, 0 , 2, "Payout" }, + {0x3b, 0x01, 0x04, 0x00, "Off" }, + {0x3b, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Horses" }, + {0x3b, 0x01, 0x08, 0x08, "Random" }, + {0x3b, 0x01, 0x08, 0x00, "Cyclic" }, + + {0 , 0xfe, 0 , 2, "Higher Odds" }, + {0x3b, 0x01, 0x10, 0x10, "Off" }, + {0x3b, 0x01, 0x10, 0x00, "On" }, + +// overlay on p1/p2 + {0 , 0xfe, 0 , 2, "Coin Drop - 1P" }, + {0x3c, 0x01, 0x01, 0x01, "Off" }, + {0x3c, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Hopper Overflow - 1P" }, + {0x3c, 0x01, 0x02, 0x02, "Off" }, + {0x3c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Out" }, + {0x3c, 0x01, 0x04, 0x00, "Off" }, + {0x3c, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Att Pay - 1P" }, + {0x3c, 0x01, 0x08, 0x08, "Off" }, + {0x3c, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Sense 2 - 1P" }, + {0x3c, 0x01, 0x40, 0x40, "Off" }, + {0x3c, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Sense 1 - 1P" }, + {0x3c, 0x01, 0x80, 0x80, "Off" }, + {0x3c, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Drop - 2P" }, + {0x3d, 0x01, 0x01, 0x01, "Off" }, + {0x3d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Sel Sense" }, + {0x3d, 0x01, 0x02, 0x02, "Off" }, + {0x3d, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Att Pay - 2P" }, + {0x3d, 0x01, 0x08, 0x08, "Off" }, + {0x3d, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Sense 2 - 2P" }, + {0x3d, 0x01, 0x40, 0x40, "Off" }, + {0x3d, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Sense 1 - 2P" }, + {0x3d, 0x01, 0x80, 0x80, "Off" }, + {0x3d, 0x01, 0x80, 0x00, "On" }, + +// p2 + {0 , 0xfe, 0 , 2, "SYSTEM" }, + {0x3e, 0x01, 0x02, 0x02, "Off" }, + {0x3e, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Tilt" }, + {0x3e, 0x01, 0x08, 0x08, "Off" }, + {0x3e, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Special Test Mode Item?" }, + {0x3f, 0x01, 0x04, 0x04, "Off" }, + {0x3f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Call SW" }, + {0x3f, 0x01, 0x08, 0x08, "Off" }, + {0x3f, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x3f, 0x01, 0x10, 0x10, "Off" }, + {0x3f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Analyzer" }, + {0x3f, 0x01, 0x20, 0x20, "Off" }, + {0x3f, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Jockeyc) + +// d_seta2.cpp +//void __fastcall setaSoundRegWriteByte(UINT32 sekAddress, UINT8 byteValue); +void __fastcall setaSoundRegWriteWord(UINT32 sekAddress, UINT16 wordValue); +//UINT8 __fastcall setaSoundRegReadByte(UINT32 sekAddress); +UINT16 __fastcall setaSoundRegReadWord(UINT32 sekAddress); + +// these should probably be moved to x1010.cpp +static UINT8 __fastcall setaSoundRegReadByte(UINT32 sekAddress) +{ + if (~sekAddress & 1) { + return x1_010_chip->HI_WORD_BUF[(sekAddress & 0x3fff) >> 1]; + } else { + return x1010_sound_read_word((sekAddress & 0x3fff) >> 1); + } +} + +static void __fastcall setaSoundRegWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + UINT32 offset = (sekAddress & 0x00003fff) >> 1; + INT32 channel, reg; + + if (~sekAddress & 1) { + x1_010_chip->HI_WORD_BUF[ offset ] = byteValue; + } else { + offset ^= x1_010_chip->address; + channel = offset / sizeof(X1_010_CHANNEL); + reg = offset % sizeof(X1_010_CHANNEL); + + if (channel < SETA_NUM_CHANNELS && reg == 0 && (x1_010_chip->reg[offset] & 1) == 0 && (byteValue&1) != 0) { + x1_010_chip->smp_offset[channel] = 0; + x1_010_chip->env_offset[channel] = 0; + } + x1_010_chip->reg[offset] = byteValue; + } +} + +void x1010Reset() +{ + x1_010_chip->sound_enable = 1; // enabled by default? + memset (x1_010_chip->reg, 0, 0x2000); + memset (x1_010_chip->HI_WORD_BUF, 0, 0x2000); + memset (x1_010_chip->smp_offset, 0, SETA_NUM_CHANNELS * sizeof(INT32)); + memset (x1_010_chip->env_offset, 0, SETA_NUM_CHANNELS * sizeof(INT32)); + memset (x1_010_chip->sound_banks, 0, SETA_NUM_BANKS * sizeof(INT32)); +} + +void x1010Enable(INT32 data) +{ + x1_010_chip->sound_enable = data; +} + +static void set_pcm_bank(INT32 data) +{ + INT32 new_bank = (data >> 3) & 0x07; + + if (new_bank != seta_samples_bank) + { + INT32 samples_len = DrvROMLen[3]; + + seta_samples_bank = new_bank; + + if (samples_len == 0x200000 || samples_len == 0x180000) // eightfrc, blandia + { + INT32 addr = 0x40000 * new_bank; + if (new_bank >= 3) addr += 0x40000; + + if ((samples_len > 0x100000) && ((addr + 0x40000) <= samples_len)) + memcpy(DrvSndROM + 0xc0000, DrvSndROM + addr, 0x40000); + } + else if (samples_len == 0x400000) // zombraid + { + if (new_bank == 0) new_bank = 1; + INT32 addr = 0x80000 * new_bank; + if (new_bank > 0) addr += 0x80000; + + memcpy (DrvSndROM + 0x80000, DrvSndROM + addr, 0x80000); + } + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// macros + +#define SetaVidRAMCtrlWriteWord(num, base) \ + if ((address >= (base + 0)) && address <= (base + 5)) { \ + *((UINT16*)(DrvVIDCTRLRAM##num + (address & 0x06))) = data; \ + return; \ + } + +#define SetaVidRAMCtrlWriteByte(num, base) \ + if ((address >= (base + 0)) && (address <= (base + 5))) { \ + DrvVIDCTRLRAM##num[(address & 0x07)^1] = data; \ + return; \ + } + +#define SetVidRAMRegsWriteWord(base) \ + if ((address >= (base + 0)) && (address <= (base + 5))) { \ + *((UINT16*)(DrvVideoRegs + (address & 0x06))) = data; \ + if ((address - base) == 0) x1010Enable(data & 0x20); \ + if ((address - base) == 2) set_pcm_bank(data); \ + return; \ + } + +#define SetVidRAMRegsWriteByte(base) \ + if ((address >= (base + 0)) && (address <= (base + 5))) { \ + DrvVideoRegs[(address & 0x07)^1] = data; \ + return; \ + } + +#define SetaReadDips(base) \ + if (address >= (base + 0) && address <= (base + 3)) { \ + return DrvDips[((address - base)/2)^1]; \ + } + +//----------------------------------------------------------------------------------------------------------------------------------- +// drgnunit + +UINT16 __fastcall drgnunit_read_word(UINT32 address) +{ + SetaReadDips(0x600000) + + switch (address) + { + case 0xb00000: + return DrvInputs[0]; + + case 0xb00002: + return DrvInputs[1]; + + case 0xb00004: + return DrvInputs[2]^0xff^DrvDips[2]; + } + + return 0; +} + +UINT8 __fastcall drgnunit_read_byte(UINT32 address) +{ + SetaReadDips(0x600000) + + switch (address) + { + case 0xb00000: + case 0xb00001: + return DrvInputs[0]; + + case 0xb00002: + case 0xb00003: + return DrvInputs[1]; + + case 0xb00004: + case 0xb00005: + return DrvInputs[2]^0xff^DrvDips[2]; + } + + return 0; +} + +void __fastcall drgnunit_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0x800000) + + SetVidRAMRegsWriteWord(0x500000) +} + +void __fastcall drgnunit_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0x800000) + + SetVidRAMRegsWriteByte(0x500000) +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// thunderl, wits + +UINT16 __fastcall thunderl_read_word(UINT32 address) +{ + SetaReadDips(0x600000) + + switch (address) + { + case 0xb00000: + case 0xb00001: + return DrvInputs[0]; + + case 0xb00002: + case 0xb00003: + return DrvInputs[1]; + + case 0xb00004: + case 0xb00005: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0xb00008: + case 0xb00009: + return DrvInputs[3]; + + case 0xb0000a: + case 0xb0000b: + return DrvInputs[4]; + + case 0xb0000c: + case 0xb0000d: + return 0x00dd;// thunderl_prot + } + + return 0; +} + +UINT8 __fastcall thunderl_read_byte(UINT32 address) +{ + SetaReadDips(0x600000) + + switch (address) + { + case 0xb00000: + case 0xb00001: + return DrvInputs[0]; + + case 0xb00002: + case 0xb00003: + return DrvInputs[1]; + + case 0xb00004: + case 0xb00005: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0xb00008: + case 0xb00009: + return DrvInputs[3]; + + case 0xb0000a: + case 0xb0000b: + return DrvInputs[4]; + + case 0xb0000c: + case 0xb0000d: + return 0xdd;// thunderl_prot + } + + return 0; +} + +void __fastcall thunderl_write_word(UINT32 address, UINT16 data) +{ + SetVidRAMRegsWriteWord(0x500000) +} + +void __fastcall thunderl_write_byte(UINT32 address, UINT8 data) +{ + SetVidRAMRegsWriteByte(0x500000) +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// daioh + +UINT16 __fastcall daioh_read_word(UINT32 address) +{ + SetaReadDips(0x300000) + SetaReadDips(0x400008) + SetaReadDips(0x600000) + + switch (address) + { + case 0x400000: + return DrvInputs[0]; + + case 0x400002: + return DrvInputs[1]; + + case 0x400004: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x40000c: + watchdog = 0; + return 0xff; + + case 0x500006: + return DrvInputs[3]; + } + + return 0; +} + +UINT8 __fastcall daioh_read_byte(UINT32 address) +{ + SetaReadDips(0x300000) + SetaReadDips(0x400008) + SetaReadDips(0x600000) + + switch (address) + { + case 0x400000: + case 0x400001: + return DrvInputs[0]; + + case 0x400002: + case 0x400003: + return DrvInputs[1]; + + case 0x400004: + case 0x400005: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x40000c: + case 0x40000d: + watchdog = 0; + return 0xff; + + case 0x500006: + case 0x500007: + return DrvInputs[3]; + } + + return 0; +} + +void __fastcall daioh_write_word(UINT32 address, UINT16 data) +{ + SetVidRAMRegsWriteWord(0x500000) + + SetaVidRAMCtrlWriteWord(0, 0x900000) // blandiap + SetaVidRAMCtrlWriteWord(0, 0x908000) // jjsquawkb + SetaVidRAMCtrlWriteWord(0, 0xa00000) // blandia + + SetaVidRAMCtrlWriteWord(1, 0x980000) // blandiap + SetaVidRAMCtrlWriteWord(1, 0x909000) // jjsquawkb + SetaVidRAMCtrlWriteWord(1, 0xa80000) // blandia + + switch (address) + { + case 0x400000: + case 0x40000c: + watchdog = 0; + return; + } +} + +void __fastcall daioh_write_byte(UINT32 address, UINT8 data) +{ + SetVidRAMRegsWriteByte(0x500000) + + SetaVidRAMCtrlWriteByte(0, 0x900000) // blandiap + SetaVidRAMCtrlWriteByte(0, 0x908000) // jjsquawkb + SetaVidRAMCtrlWriteByte(0, 0xa00000) // blandia + + SetaVidRAMCtrlWriteByte(1, 0x980000) // blandiap + SetaVidRAMCtrlWriteByte(1, 0x909000) // jjsquawkb + SetaVidRAMCtrlWriteByte(1, 0xa80000) // blandia + + switch (address) + { + case 0x400000: + case 0x400001: + case 0x40000c: + case 0x40000d: + watchdog = 0; + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// msgundam + +void __fastcall msgundam_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0xb00000) + SetaVidRAMCtrlWriteWord(1, 0xb80000) + + switch (address) + { + case 0x500000: + case 0x500001: + *((UINT16*)(DrvVideoRegs + 0)) = data; + return; + case 0x500002: + case 0x500003: + *((UINT16*)(DrvVideoRegs + 4)) = data; + return; + + case 0x500004: + case 0x500005: + *((UINT16*)(DrvVideoRegs + 2)) = data; + return; + } +} + +void __fastcall msgundam_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0xb00000) + SetaVidRAMCtrlWriteByte(1, 0xb80000) + + switch (address) + { + case 0x500000: + case 0x500001: + DrvVideoRegs[(~address & 0x01) | 0] = data; + return; + + case 0x500002: + case 0x500003: + DrvVideoRegs[(~address & 0x01) | 4] = data; + return; + + case 0x500004: + case 0x500005: + DrvVideoRegs[(~address & 0x01) | 2] = data; + // seta_vregs_w + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// kamenrid + +UINT16 __fastcall kamenrid_read_word(UINT32 address) +{ + SetaReadDips(0x500004) + + switch (address) + { + case 0x500000: + return DrvInputs[0]; + + case 0x500002: + return DrvInputs[1]; + + case 0x500009: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x50000c: + return 0xffff; // watchdog + } + + return 0; +} + +UINT8 __fastcall kamenrid_read_byte(UINT32 address) +{ + SetaReadDips(0x500004) + + switch (address) + { + case 0x500000: + case 0x500001: + return DrvInputs[0]; + + case 0x500002: + case 0x500003: + return DrvInputs[1]; + + case 0x500009: + case 0x50000a: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x50000c: + case 0x50000d: + return 0xff; // watchdog + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// krzybowl, madshark + +static UINT16 krzybowl_input_read(INT32 offset) +{ + INT32 dir1x = 0x800; //input_port_read(space->machine, "TRACK1_X") & 0xfff; + INT32 dir1y = 0x800; //input_port_read(space->machine, "TRACK1_Y") & 0xfff; + INT32 dir2x = 0x800; //input_port_read(space->machine, "TRACK2_X") & 0xfff; + INT32 dir2y = 0x800; //input_port_read(space->machine, "TRACK2_Y") & 0xfff; + + switch ((offset & 0x0e) / 2) + { + case 0x0/2: return dir1x & 0xff; + case 0x2/2: return dir1x >> 8; + case 0x4/2: return dir1y & 0xff; + case 0x6/2: return dir1y >> 8; + case 0x8/2: return dir2x & 0xff; + case 0xa/2: return dir2x >> 8; + case 0xc/2: return dir2y & 0xff; + case 0xe/2: return dir2y >> 8; + } + + return 0; +} + +UINT16 __fastcall madshark_read_word(UINT32 address) +{ + SetaReadDips(0x300000) + SetaReadDips(0x500008) + + switch (address) + { + case 0x500000: + return DrvInputs[0]; + + case 0x500002: + return DrvInputs[1]; + + case 0x500004: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x50000c: + watchdog = 0; + return 0xffff; + } + + if ((address & ~0x00000f) == 0x600000) { + return krzybowl_input_read(address); + } + + return 0; +} + +UINT8 __fastcall madshark_read_byte(UINT32 address) +{ + SetaReadDips(0x300000) + SetaReadDips(0x500008) + + switch (address) + { + case 0x500000: + case 0x500001: + return DrvInputs[0]; + + case 0x500002: + case 0x500003: + return DrvInputs[1]; + + case 0x500004: + case 0x500005: + return DrvInputs[2]^0xff^DrvDips[2]; + + case 0x50000c: + case 0x50000d: + watchdog = 0; + return 0xff; + } + + if ((address & ~0x00000f) == 0x600000) { + return krzybowl_input_read(address); + } + + return 0; +} + +void __fastcall madshark_write_word(UINT32 address, UINT16 data) +{ + SetVidRAMRegsWriteWord(0x600000) + SetaVidRAMCtrlWriteWord(0, 0x900000) + SetaVidRAMCtrlWriteWord(1, 0x980000) + + switch (address) + { + case 0x50000c: + watchdog = 0; + return; + } +} + +void __fastcall madshark_write_byte(UINT32 address, UINT8 data) +{ + SetVidRAMRegsWriteByte(0x600000) + SetaVidRAMCtrlWriteByte(0, 0x900000) + SetaVidRAMCtrlWriteByte(1, 0x980000) + + switch (address) + { + case 0x50000c: + case 0x50000d: + watchdog = 0; + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// keroppi, pairlove + +static INT32 keroppi_prize_hop = 0; +static INT32 keroppi_protection_count = 0; +static INT32 keroppi_timer_frame = -1; +static const UINT16 keroppi_protection_word[] = { + 0x0000, + 0x0000, 0x0000, 0x0000, + 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, + 0x0400, 0x0400, 0x0400, + 0x0000, 0x0000, 0x0000 +}; + +static UINT16 pairslove_protram[0x100]; +static UINT16 pairslove_protram_old[0x100]; + +UINT16 __fastcall pairlove_read_word(UINT32 address) +{ + SetaReadDips(0x300000) + + switch (address) + { + case 0x100000: { // keroppi + INT32 res = keroppi_protection_word[keroppi_protection_count]; + keroppi_protection_count++; + if (keroppi_protection_count > 15) keroppi_protection_count = 15; + return res; + } + + case 0x200000: // keroppi + keroppi_protection_count = 0; + return 0x00; + + case 0x500000: + return DrvInputs[0]; + + case 0x500002: + return DrvInputs[1]; + + case 0x500004: { + INT32 res = DrvInputs[2]^0xff^DrvDips[2]; + + if (keroppi_prize_hop == 1 && keroppi_timer_frame != -1) { + if ((GetCurrentFrame() - keroppi_timer_frame) >= 3) { + keroppi_prize_hop = 2; + keroppi_timer_frame = - 1; + } + } + + if (keroppi_prize_hop == 2) { + res &= ~0x0002; + keroppi_prize_hop = 0; + } + return res; + } + } + + if ((address & 0xfffffe00) == 0x900000) { + INT32 offset = (address & 0x1ff) / 2; + + INT32 retdata = pairslove_protram[offset]; + pairslove_protram[offset]=pairslove_protram_old[offset]; + return retdata; + } + + return 0; +} + +UINT8 __fastcall pairlove_read_byte(UINT32 address) +{ + SetaReadDips(0x300000) + + switch (address) + { + case 0x100000: // keroppi + case 0x100001: { + INT32 res = keroppi_protection_word[keroppi_protection_count]; + keroppi_protection_count++; + if (keroppi_protection_count > 15) keroppi_protection_count = 15; + return res; + } + + case 0x200000: + case 0x200001: // keroppi + keroppi_protection_count = 0; + return 0x00; + + case 0x500000: + case 0x500001: + return DrvInputs[0]; + + case 0x500002: + case 0x500003: + return DrvInputs[1]; + + case 0x500004: + case 0x500005: { + INT32 res = DrvInputs[2]^0xff^DrvDips[2]; + + if (keroppi_prize_hop == 1 && keroppi_timer_frame != -1) { + if ((GetCurrentFrame() - keroppi_timer_frame) >= 3) { + keroppi_prize_hop = 2; + keroppi_timer_frame = -1; + } + } + + if (keroppi_prize_hop == 2) { + res &= ~0x0002; + keroppi_prize_hop = 0; + } + return res; + } + } + + if ((address & 0xfffffe00) == 0x900000) { + INT32 offset = (address & 0x1ff) / 2; + INT32 retdata = pairslove_protram[offset]; + pairslove_protram[offset]=pairslove_protram_old[offset]; + return retdata; + } + + return 0; +} + +void __fastcall pairlove_write_word(UINT32 address, UINT16 data) +{ + SetVidRAMRegsWriteWord(0x400000) + + switch (address) + { + case 0x900002: // keroppi + if ((data & 0x0010) && !keroppi_prize_hop) { + keroppi_prize_hop = 1; + keroppi_timer_frame = GetCurrentFrame(); + } + break; // for pairslove prot + } + + if ((address & 0xfffffe00) == 0x900000) { + INT32 offset = (address & 0x1ff) / 2; + pairslove_protram_old[offset]=pairslove_protram[offset]; + pairslove_protram[offset]=data; + return; + } +} + +void __fastcall pairlove_write_byte(UINT32 address, UINT8 data) +{ + SetVidRAMRegsWriteByte(0x400000) + + switch (address) + { + case 0x900002: + case 0x900003: // keroppi + if ((data & 0x0010) && !keroppi_prize_hop) { + keroppi_prize_hop = 1; + keroppi_timer_frame = GetCurrentFrame(); + } + break; // for pairslove prot + } + + if ((address & 0xfffffe00) == 0x900000) { + INT32 offset = (address & 0x1ff) / 2; + pairslove_protram_old[offset]=pairslove_protram[offset]; + pairslove_protram[offset]=data; + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// downtown, metafox, twineagl, arbelester + +void __fastcall downtown_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0x800000) + + switch (address) + { + case 0x400000: + case 0x400002: + case 0x400004: + case 0x400006: + // tilebank[(address & 6) / 2] = data; + return; + + case 0xa00000: + case 0xa00002: + case 0xa00004: + case 0xa00006: + // sub_ctrl_w + return; + } +} + +void __fastcall downtown_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0x800000) + + switch (address) + { + case 0x400000: + case 0x400001: + case 0x400002: + case 0x400003: + case 0x400004: + case 0x400005: + case 0x400006: + case 0x400007: + tilebank[(address & 6) / 2] = data; + return; + + case 0xa00000: + case 0xa00001: + case 0xa00002: + case 0xa00003: + case 0xa00004: + case 0xa00005: + case 0xa00006: + case 0xa00007: + // sub_ctrl_w + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// kiwame + +static INT32 kiwame_inputs_read(INT32 offset) +{ + INT32 i; + INT32 row_select = DrvNVRAM[0x10b]; + + for (i = 0; i < 5; i++) + if (row_select & (1 << i)) break; + + switch (offset) + { + case 0: return DrvInputs[i+1]; + case 4: return DrvInputs[0]^0xff^DrvDips[2]; + case 2: + case 8: return 0xffff; + } + + return 0; +} + +UINT16 __fastcall kiwame_read_word(UINT32 address) +{ + switch (address) + { + case 0xe00000: + return DrvDips[1]; + + case 0xe00002: + return DrvDips[0]; + } + + if ((address & 0xfffff0) == 0xd00000) { + return kiwame_inputs_read(address & 0x0e); + } + if ((address & 0xfffc00) == 0xfffc00) { + // bprintf (0, _T("%5.5x, rw\n"), address); + return DrvNVRAM[(address & 0x3fe)]; + } + + return 0; +} + +UINT8 __fastcall kiwame_read_byte(UINT32 address) +{ + switch (address) + { + case 0xe00000: + case 0xe00001: + return DrvDips[1]; + + case 0xe00002: + case 0xe00003: + return DrvDips[0]; + } + + if ((address & 0xfffff0) == 0xd00000) { + return kiwame_inputs_read(address & 0x0e); + } + + if ((address & 0xfffc01) == 0xfffc01) { + return DrvNVRAM[(address & 0x3fe)]; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// zombraid gun handler + +static INT32 zombraid_gun_read() +{ + return (DrvAnalogInput[gun_input_src] >> gun_input_bit) & 1; +} + +static void zombraid_gun_write(INT32 data) +{ + static INT32 bit_count = 0, old_clock = 0; + + if(data&4) { bit_count = 0; return; } // Reset + + if((data&1) == old_clock) return; // No change + + if (old_clock == 0) // Rising edge + { + switch (bit_count) + { + case 0: + case 1: // Starting sequence 2,3,2,3. Other inputs? + break; + + case 2: // First bit of source + gun_input_src = (gun_input_src&2) | (data>>1); + break; + + case 3: // Second bit of source + gun_input_src = (gun_input_src&1) | (data&2); + break; + + default: + // "Player1_Gun_Recoil", (data & 0x10)>>4 + // "Player2_Gun_Recoil", (data & 0x08)>>3 + gun_input_bit = bit_count - 4; + gun_input_bit = 8 - gun_input_bit; // Reverse order + break; + } + bit_count++; + } + + old_clock = data & 1; +} + +void __fastcall zombraid_gun_write_word(UINT32 address, UINT16 data) +{ + if ((address & ~1) == 0xf00000) zombraid_gun_write(data); +} + +void __fastcall zombraid_gun_write_byte(UINT32 address, UINT8 data) +{ + if ((address & ~1) == 0xf00000) zombraid_gun_write(data); +} + +UINT16 __fastcall zombraid_gun_read_word(UINT32 ) +{ + return zombraid_gun_read(); +} + +UINT8 __fastcall zombraid_gun_read_byte(UINT32 ) +{ + return zombraid_gun_read(); +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// utoukond sound handler + +void __fastcall utoukond_sound_write(UINT16 address, UINT8 data) +{ + if (address >= 0xf000) { + setaSoundRegWriteByte((address & 0xfff) * 2 + 1, data); + } +} + +UINT8 __fastcall utoukond_sound_read(UINT16 address) +{ + if (address >= 0xf000) { + return x1010_sound_read(address & 0xfff); + } + return 0; +} + +void __fastcall utoukond_sound_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + BurnYM3438Write(0, port & 3, data); + return; + } +} + +UINT8 __fastcall utoukond_sound_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + return BurnYM3438Read(0, port & 3);// right? + + case 0xc0: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// wiggie / superbar sound handler + +void __fastcall wiggie_sound_write_word(UINT32 , UINT16 ) +{ + +} + +void __fastcall wiggie_sound_write_byte(UINT32 address, UINT8 data) +{ + if (address != 0xb00008 && address != 0xc00000) return; // wiggie + + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); +} + +void __fastcall wiggie_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall wiggie_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// usclssic + +void __fastcall usclssic_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0xa00000) + + switch (address) + { + case 0xb40000: + usclssic_port_select = (data & 0x40) >> 6; + tile_offset[0] = (data & 0x10) << 10; + // coin lockout too... + return; + + case 0xb40010: + *soundlatch = data; + return; + + case 0xb40018: + watchdog = 0; + return; + } +} + +void __fastcall usclssic_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0xa00000) + + switch (address) + { + case 0xb40000: + case 0xb40001: + usclssic_port_select = (data & 0x40) >> 6; + tile_offset[0] = (data & 0x10) << 10; + // coin lockout too... + return; + + case 0xb40010: + case 0xb40011: + *soundlatch = data; + return; + + case 0xb40018: + case 0xb40019: + watchdog = 0; + return; + } +} + +static UINT8 uclssic_trackball_read(INT32 offset) +{ + const UINT16 start_vals[2] = { 0xf000, 0x9000 }; + + UINT16 ret = DrvInputs[1 + ((offset & 4)/4) + (usclssic_port_select * 2)] ^ start_vals[(offset / 4) & 1]; + + if (offset & 2) ret >>= 8; + + return ret ^ 0xff; +} + +UINT16 __fastcall usclssic_read_word(UINT32 address) +{ + switch (address) + { + case 0xb40000: + case 0xb40002: + case 0xb40004: + case 0xb40006: + return uclssic_trackball_read(address); + + case 0xb40010: + return DrvInputs[0] ^ 0xf0; + + case 0xb40018: + return DrvDips[1] & 0x0f; + + case 0xb4001a: + return DrvDips[1] >> 4; + + case 0xb4001c: + return DrvDips[0] & 0x0f; + + case 0xb4001e: + return DrvDips[0] >> 4; + } + + return 0; +} + +UINT8 __fastcall usclssic_read_byte(UINT32 address) +{ + switch (address) + { + case 0xb40000: + case 0xb40001: + case 0xb40002: + case 0xb40003: + case 0xb40004: + case 0xb40005: + case 0xb40006: + case 0xb40007: + return uclssic_trackball_read(address); + + case 0xb40010: + case 0xb40011: + return DrvInputs[0] ^ 0xf0; + + case 0xb40018: + case 0xb40019: + return DrvDips[1] & 0x0f; + + case 0xb4001a: + case 0xb4001b: + return DrvDips[1] >> 4; + + case 0xb4001c: + case 0xb4001d: + return DrvDips[0] & 0x0f; + + case 0xb4001e: + case 0xb4001f: + return DrvDips[0] >> 4; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// calibr50 + +static UINT16 calibr50_input_read(INT32 offset) +{ + INT32 dir1 = 0; // analog port + INT32 dir2 = 0; // analog port + + switch (offset & 0x1e) + { + case 0x00: return DrvInputs[0]; // p1 + case 0x02: return DrvInputs[1]; // p2 + case 0x08: return DrvInputs[2]^0xff^DrvDips[2]; // Coins + case 0x10: return (dir1 & 0xff); // lower 8 bits of p1 rotation + case 0x12: return (dir1 >> 8); // upper 4 bits of p1 rotation + case 0x14: return (dir2 & 0xff); // lower 8 bits of p2 rotation + case 0x16: return (dir2 >> 8); // upper 4 bits of p2 rotation + case 0x18: return 0xffff; // ? (value's read but not used) + } + + return 0; +} + +UINT16 __fastcall calibr50_read_word(UINT32 address) +{ + switch (address) + { + case 0x400000: + case 0x400001: + watchdog = 0; + return 0xffff; + } + + if ((address & 0xfffffe0) == 0xa00000) { + return calibr50_input_read(address); + } + + SetaReadDips(0x600000) + + return 0; +} + +UINT8 __fastcall calibr50_read_byte(UINT32 address) +{ + switch (address) + { + case 0x400000: + case 0x400001: + watchdog = 0; + return 0xff; + + case 0xb00000: + case 0xb00001: + static INT32 ret; // fake read from sound cpu + ret ^= 0x80; + return ret; + } + + if ((address & 0xfffffe0) == 0xa00000) { + return calibr50_input_read(address) >> ((~address & 1) << 3); + } + + SetaReadDips(0x600000) + + return 0; +} + +void __fastcall calibr50_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0x800000) + + if ((address & ~1) == 0xb00000) { + *soundlatch = data; + return; + } +} + +void __fastcall calibr50_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0x800000) + + if ((address & ~1) == 0xb00000) { + *soundlatch = data; + return; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------- +// downtown protection handler, m65c02 simulation (metafox, arbelester) + +static UINT8 *downtown_protram; + +UINT8 __fastcall downtown_prot_read(UINT32 address) +{ + if (downtown_protram[0xf8] == 0xa3) { + if (address >= 0x200100 && address <= 0x20010b) { + char *waltz = "WALTZ0"; + return waltz[(address & 0x0f) / 2]; + } else { + return 0; + } + } + + return downtown_protram[(address & 0x1ff)^1]; +} + +static inline UINT8 simulation_input_return(UINT8 inputs, INT32 a0, INT32 a1, INT32 a2, INT32 a3) +{ + UINT8 ret = 0; + if (inputs & a0 ) ret |= 0x01; // right + if (inputs & a1 ) ret |= 0x02; // left + if (inputs & a2 ) ret |= 0x04; // up + if (inputs & a3 ) ret |= 0x08; // down + if (inputs & 0x10) ret |= 0x10; // button 1 + if (inputs & 0x20) ret |= 0x20; // button 2 + if (inputs & 0x20) ret |= 0x40; // button 3 + if (inputs & 0x80) ret |= 0x80; // start + + if ((ret & 0x0c) == 0x0c) ret &= ~0x0c; // clear opposites + if ((ret & 0x03) == 0x03) ret &= ~0x03; + + return ret; +} + +UINT8 __fastcall metafox_sharedram_read_byte(UINT32 address)// metafox input simulation +{ + static INT32 coin_read = 0; + INT32 inputs0 = DrvInputs[0]^0xffff; + INT32 inputs1 = DrvInputs[1]^0xffff; + INT32 inputs2 = (DrvInputs[2]^0xff^DrvDips[2])^0xffff; + + INT32 offset = address & 0xffe; + + if (offset == 0x014) { // handle start input... + DrvShareRAM[offset] = 0; + if (inputs0 & 0x80) DrvShareRAM[0x14] |= 0x04; // start 1 pressed + if (inputs1 & 0x80) DrvShareRAM[0x14] |= 0x08; // start 2 pressed + if (inputs2 & 0x20) DrvShareRAM[0x14] |= 0x10; // service + if (inputs2 & 0x10) DrvShareRAM[0x14] |= 0x20; // tilt + + static INT32 nPreviousStart0, nPreviousStart1; + INT32 nCurrentStart0 = inputs0 & 0x80; + INT32 nCurrentStart1 = inputs1 & 0x80; + if ((nCurrentStart0 != nPreviousStart0) && !nCurrentStart0) { + if (DrvShareRAM[0x68] && coin_read) { + DrvShareRAM[0x68]--; + coin_read = 0; + } + } + if ((nCurrentStart1 != nPreviousStart1) && !nCurrentStart1) { + if (DrvShareRAM[0x68] && coin_read) { + DrvShareRAM[0x68]--; + coin_read = 0; + } + } + nPreviousStart0 = nCurrentStart0; + nPreviousStart1 = nCurrentStart1; + } + + if (offset == 0x00a) { // player 1 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs0, 8, 4, 1, 2); + } + + if (offset == 0x010) { // player 2 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs1, 8, 4, 1, 2); + } + + if (offset == 0x068) { // coin1 & coin2 (needs coinage dips added) + static INT32 nPreviousCoin0, nPreviousCoin1; + INT32 nCurrentCoin0 = inputs2 & 0x80; + INT32 nCurrentCoin1 = inputs2 & 0x40; + if (nPreviousCoin0 != nCurrentCoin0) DrvShareRAM[0x068] += ((nCurrentCoin0 >> 7) & 1); + if (nPreviousCoin1 != nCurrentCoin1) DrvShareRAM[0x068] += ((nCurrentCoin1 >> 6) & 1); + if (DrvShareRAM[0x68] > 9) DrvShareRAM[0x68] = 9; + nPreviousCoin0 = nCurrentCoin0; + nPreviousCoin1 = nCurrentCoin1; + coin_read = 1; + } + + return DrvShareRAM[offset]; +} + +UINT16 __fastcall metafox_sharedram_read_word(UINT32 address) +{ + return metafox_sharedram_read_byte(address); +} + +UINT8 __fastcall tndrcade_sharedram_read_byte(UINT32 address) // tndrcade input simulation +{ + static INT32 coin_read = 0; + INT32 inputs0 = DrvInputs[0]^0xffff; + INT32 inputs1 = DrvInputs[1]^0xffff; + INT32 inputs2 = (DrvInputs[2]^0xff^DrvDips[2])^0xffff; + + INT32 offset = address & 0xffe; + + if (offset >= 0x1c0 && offset <= 0x1de) { // these are read often, the game refuses to boot without the proper sequence + if (tndrcade_init_sim > 0 && tndrcade_init_sim <= 4) { + DrvShareRAM[offset] = ((((offset - 0x1c0) / 2) * 0x0f) + 3) - (tndrcade_init_sim-1); + if (offset == 0x1de) tndrcade_init_sim++; + } else { + DrvShareRAM[offset] = ((offset & 0x1f) / 2) | (((offset & 0x1f) / 2) << 4); + if (offset == 0x1dc) tndrcade_init_sim++; + } + } + + if (offset == 0x002) return 0x31; // or error + if (offset == 0x09a) return DrvDips[1] ^ 0xff; // ? + if (offset == 0x09c) return DrvDips[0] ^ 0xff; + + if (offset == 0x014) { // handle start input... + DrvShareRAM[0x14] = 0; + if (inputs0 & 0x80) DrvShareRAM[0x14] |= 0x04; // start 1 pressed + if (inputs1 & 0x80) DrvShareRAM[0x14] |= 0x08; // start 2 pressed + if (inputs2 & 0x20) DrvShareRAM[0x14] |= 0x10; // service + if (inputs2 & 0x10) DrvShareRAM[0x14] |= 0x20; // tilt + + static INT32 nPreviousStart0, nPreviousStart1; + INT32 nCurrentStart0 = inputs0 & 0x80; + INT32 nCurrentStart1 = inputs1 & 0x80; + if ((nCurrentStart0 != nPreviousStart0) && !nCurrentStart0) { + if (DrvShareRAM[0x68] && coin_read) { + DrvShareRAM[0x68]--; + coin_read = 0; + } + } + if ((nCurrentStart1 != nPreviousStart1) && !nCurrentStart1) { + if (DrvShareRAM[0x68] && coin_read) { + DrvShareRAM[0x68]--; + coin_read = 0; + } + } + nPreviousStart0 = nCurrentStart0; + nPreviousStart1 = nCurrentStart1; + } + + if (offset == 0x00a) { // player 1 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs0, 2, 1, 4, 8); + } + + if (offset == 0x010) { // player 2 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs1, 2, 1, 4, 8); + } + + if (offset == 0x068) { // coin1 & coin2 (needs coinage dips added) + static INT32 nPreviousCoin0, nPreviousCoin1; + INT32 nCurrentCoin0 = inputs2 & 0x01; + INT32 nCurrentCoin1 = inputs2 & 0x02; + if (nPreviousCoin0 != nCurrentCoin0) DrvShareRAM[offset] += ((nCurrentCoin0 >> 0) & 1); + if (nPreviousCoin1 != nCurrentCoin1) DrvShareRAM[offset] += ((nCurrentCoin1 >> 1) & 1); + if (DrvShareRAM[offset] > 9) DrvShareRAM[offset] = 9; + nPreviousCoin0 = nCurrentCoin0; + nPreviousCoin1 = nCurrentCoin1; + coin_read = 1; + } + + return DrvShareRAM[(address & 0xffe)]; +} + +UINT16 __fastcall tndrcade_sharedram_read_word(UINT32 address) +{ + return tndrcade_sharedram_read_byte(address); +} + +UINT8 __fastcall downtown_sharedram_read_byte(UINT32 address) // downtown input simulation +{ +//bprintf (0, _T("%5.5x\n"), address); + static INT32 coin_read = 0; + INT32 inputs0 = DrvInputs[0]^0xffff; + INT32 inputs1 = DrvInputs[1]^0xffff; + INT32 inputs2 = (DrvInputs[2]^0xff^DrvDips[2])^0xffff; + INT32 offset = address & 0xffe; + + if (offset == 0x002) DrvShareRAM[offset] = 0x31; // or ERROR COM RAM + + if (offset == 0x070) { // coin1 & coin2 + static INT32 nPreviousCoin0, nPreviousCoin1; + INT32 nCurrentCoin0 = inputs2 & 0x80; + INT32 nCurrentCoin1 = inputs2 & 0x40; + if (nPreviousCoin0 != nCurrentCoin0) DrvShareRAM[offset] += ((nCurrentCoin0 >> 7) & 1); + if (nPreviousCoin1 != nCurrentCoin1) DrvShareRAM[offset] += ((nCurrentCoin1 >> 6) & 1); + if (DrvShareRAM[offset] > 9) DrvShareRAM[offset] = 9; + nPreviousCoin0 = nCurrentCoin0; + nPreviousCoin1 = nCurrentCoin1; + coin_read = 1; + } + + if (offset == 0x0d4) { // service button & tilt + DrvShareRAM[offset] = 0xf7; // player 1 rotation high + if (inputs2 & 0x10) DrvShareRAM[offset] ^= 0x10; + if (inputs2 & 0x20) DrvShareRAM[offset] ^= 0x20; + } + + if (offset == 0x0d6) DrvShareRAM[offset] = 0xff; // player 1 rotation low + if (offset == 0x0d8) DrvShareRAM[offset] = ~simulation_input_return(inputs0, 1, 2, 4, 8); // player 1 inputs... + if (offset == 0x0dc) DrvShareRAM[offset] = 0x0f; // player 2 rotation high + if (offset == 0x0de) DrvShareRAM[offset] = 0xbf; // player 2 rotation low + if (offset == 0x0e0) DrvShareRAM[offset] = ~simulation_input_return(inputs1, 1, 2, 4, 8); // player 2 inputs... + + if (offset >= 0x1c0 && offset <= 0x1de) { // these are read often, the game refuses to boot without the proper sequence + if (tndrcade_init_sim <= 1) { + DrvShareRAM[offset] = ((((offset - 0x1c0) / 2) * 0x0f) + 1) - tndrcade_init_sim; + if (offset == 0x1de) tndrcade_init_sim++; + } else { + DrvShareRAM[offset] = ((offset & 0x1f) / 2) | (((offset & 0x1f) / 2) << 4); + if (offset == 0x1dc) tndrcade_init_sim++; + } + } + + return DrvShareRAM[offset]; +} + +UINT16 __fastcall downtown_sharedram_read_word(UINT32 address) +{ + downtown_sharedram_read_byte(address & 0xffe); + return DrvShareRAM[address & 0xffe]; // +} + +UINT8 __fastcall twineagl_sharedram_read_byte(UINT32 address) // twineagl input simulation +{ + static INT32 coin_read = 0; + INT32 inputs0 = DrvInputs[0]^0xffff; + INT32 inputs1 = DrvInputs[1]^0xffff; + INT32 inputs2 = (DrvInputs[2]^0xff^DrvDips[2])^0xffff; + INT32 offset = address & 0xffe; + + if (offset == 0x000) DrvShareRAM[offset] = 0x00; + if (offset == 0x002) DrvShareRAM[offset] = 0x31; // or ERROR COM RAM + + if (offset == 0x00a) { // player 1 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs0, 2, 1, 4, 8); + } + + if (offset == 0x010) { // player 2 inputs... + DrvShareRAM[offset] = simulation_input_return(inputs1, 2, 1, 4, 8); + } + + if (offset == 0x014) { // handle start input... + DrvShareRAM[offset] = 0; + if (inputs0 & 0x80) DrvShareRAM[offset] |= 0x04; // start 1 pressed + if (inputs1 & 0x80) DrvShareRAM[offset] |= 0x08; // start 2 pressed + if (inputs2 & 0x20) DrvShareRAM[offset] |= 0x10; // service + if (inputs2 & 0x10) DrvShareRAM[offset] |= 0x20; // tilt + + static INT32 nPreviousStart0, nPreviousStart1; + INT32 nCurrentStart0 = inputs0 & 0x80; + INT32 nCurrentStart1 = inputs1 & 0x80; + if ((nCurrentStart0 != nPreviousStart0) && !nCurrentStart0) { + if (DrvShareRAM[0x68] && coin_read) { + DrvShareRAM[0x68]--; + coin_read = 0; + } + } + if ((nCurrentStart1 != nPreviousStart1) && !nCurrentStart1) { + if (DrvShareRAM[0x68] > 1 && coin_read) { + DrvShareRAM[0x68]-=2; + coin_read = 0; + } + } + nPreviousStart0 = nCurrentStart0; + nPreviousStart1 = nCurrentStart1; + } + + if (offset == 0x068) { // coin1 & coin2 + static INT32 nPreviousCoin0, nPreviousCoin1; + INT32 nCurrentCoin0 = inputs2 & 0x01; + INT32 nCurrentCoin1 = inputs2 & 0x02; + if (nPreviousCoin0 != nCurrentCoin0) DrvShareRAM[offset] += ((nCurrentCoin0 >> 0) & 1); + if (nPreviousCoin1 != nCurrentCoin1) DrvShareRAM[offset] += ((nCurrentCoin1 >> 1) & 1); + if (DrvShareRAM[offset] > 9) DrvShareRAM[offset] = 9; + nPreviousCoin0 = nCurrentCoin0; + nPreviousCoin1 = nCurrentCoin1; + coin_read = 1; + } + + if (offset == 0x0a8) { // more start inputs... + if (coin_read && ((inputs0 & 0x80) || (inputs1 & 0x80))) { + DrvShareRAM[offset] = 0; + if (inputs0 & 0x80) DrvShareRAM[offset] |= 0x04; // start 1 pressed + if (inputs1 & 0x80) DrvShareRAM[offset] |= 0x08; // start 2 pressed + } + } + + if (offset >= 0x1c0 && offset <= 0x1de) { // these are read often, the game refuses to boot without the proper sequence + if (tndrcade_init_sim <= 1) { + DrvShareRAM[offset] = ((((offset - 0x1c0) / 2) * 0x0f) + 1) - tndrcade_init_sim; + if (offset == 0x1de) tndrcade_init_sim++; + } else { + DrvShareRAM[offset] = ((offset & 0x1f) / 2) | (((offset & 0x1f) / 2) << 4); + if (offset == 0x1dc) tndrcade_init_sim++; + } + } + + return DrvShareRAM[offset]; +} + +UINT16 __fastcall twineagl_sharedram_read_word(UINT32 address) +{ + INT32 offset = address & 0xffe; + twineagl_sharedram_read_byte(offset); + return DrvShareRAM[offset]; +} + +void __fastcall twineagl_sharedram_write_word(UINT32 address, UINT16 data) +{ + INT32 offset = address & 0xffe; + + data &= 0xff; + + DrvShareRAM[offset] = data; + + if (offset == 0x400 && data) { + INT32 ofst = 0; + + for (INT32 i = 0; i < 0x100; i+=16) { + if (DrvShareRAM[i + 0x200] == 0) { + ofst = i + 0x200; + break; + } + } + if (ofst == 0) return; + + // add to playlist + { + INT32 ofst2 = (DrvShareRAM[offset] * 0x0b) + 0x204; // find song data in m65c02 rom (correct?) + + DrvShareRAM[ofst + 0] = 0x81; + DrvShareRAM[ofst + 2] = DrvSubROM[ofst2 + 0]; + DrvShareRAM[ofst + 4] = DrvSubROM[ofst2 + 1]; + DrvShareRAM[ofst + 8] = DrvSubROM[ofst2 + 2]; + } + } +} + +void __fastcall twineagl_sharedram_write_byte(UINT32 address, UINT8 data) +{ + twineagl_sharedram_write_word(address, data); +} + + +//----------------------------------------------------------------------------------------------------------------------------------- +// crazy fight + +UINT16 __fastcall crazyfgt_read_word(UINT32 address) +{ + switch (address) + { + case 0x610000: + case 0x610001: + return DrvInputs[0]; + + case 0x610002: + case 0x610003: + return 0xffff; + + case 0x610004: + case 0x610005: + return DrvInputs[1]; + } + + SetaReadDips(0x630000) + + return 0; +} + +UINT8 __fastcall crazyfgt_read_byte(UINT32 address) +{ + switch (address) + { + case 0x610000: + case 0x610001: + return DrvInputs[0]; + + case 0x610002: + case 0x610003: + return 0xff; + + case 0x610004: + case 0x610005: + return DrvInputs[1]; + } + + SetaReadDips(0x630000) + + return 0; +} + +void __fastcall crazyfgt_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(1, 0x900000) + SetaVidRAMCtrlWriteByte(0, 0x980000) + + switch (address) + { + case 0x650000: + case 0x650001: + BurnYM3812Write(0, data); + return; + + case 0x658000: + case 0x658001: + MSM6295Command(0, data); + return; + } +} + +void __fastcall crazyfgt_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(1, 0x900000) + SetaVidRAMCtrlWriteWord(0, 0x980000) + + switch (address) + { + case 0x650000: + case 0x650001: + BurnYM3812Write(0, data); + return; + + case 0x658000: + case 0x658001: + MSM6295Command(0, data); + return; + } +} + + +//----------------------------------------------------------------------------------------------------------------------------------- +// 68k initializers + +static void drgnunit68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x900000, 0x903fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xf00000, 0xf0ffff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x0010000, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, drgnunit_write_word); + SekSetWriteByteHandler(0, drgnunit_write_byte); + SekSetReadWordHandler(0, drgnunit_read_word); + SekSetReadByteHandler(0, drgnunit_read_byte); + + SekMapHandler(1, 0x100000, 0x103fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void daioh68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x701000, 0x70ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x88ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x0020000, 0xa80000, 0xa803ff, SM_WRITE); // nop out + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb13fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void wrofaero68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x21ffff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0011000, 0x701000, 0x70ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x88ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb13fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void msgundam68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + + for (INT32 i = 0; i < 0x80000; i+=0x10000) // mirrored + SekMapMemory(Drv68KRAM, 0x200000+i, 0x20ffff+i, SM_RAM); + + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x800000, 0x800607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x900000, 0x903fff, SM_RAM); + + SekMapMemory(DrvVidRAM0, 0xa00000, 0xa0ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xa80000, 0xa8ffff, SM_RAM); + SekSetWriteWordHandler(0, msgundam_write_word); + SekSetWriteByteHandler(0, msgundam_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void umanclub68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x300000, 0x300fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb03fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void kamenrid68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0011000, 0x701000, 0x703fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x807fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x887fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb07fff, SM_RAM); + SekSetWriteWordHandler(0, madshark_write_word); + SekSetWriteByteHandler(0, madshark_write_byte); + SekSetReadWordHandler(0, kamenrid_read_word); + SekSetReadByteHandler(0, kamenrid_read_byte); + + SekMapHandler(1, 0xd00000, 0xd03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + { + DrvGfxROM2 = DrvGfxROM1 + 0x80000; + DrvROMLen[2] = DrvROMLen[1] = DrvROMLen[1] / 2; + memcpy (DrvGfxROM2, DrvGfxROM1 + 0x40000, 0x40000); + } +} + +static void madshark68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0011000, 0x701000, 0x703fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x807fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x887fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb07fff, SM_RAM); + SekSetWriteWordHandler(0, madshark_write_word); + SekSetWriteByteHandler(0, madshark_write_byte); + SekSetReadWordHandler(0, madshark_read_word); + SekSetReadByteHandler(0, madshark_read_byte); + + SekMapHandler(1, 0xd00000, 0xd03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + { + DrvGfxROM2 = (UINT8*)BurnMalloc(0x200000); + DrvROMLen[1] = DrvROMLen[2] = 0x200000; + + memcpy (DrvGfxROM0 + 0x200000, DrvGfxROM0 + 0x000000, 0x100000); + memcpy (DrvGfxROM0 + 0x000000, DrvGfxROM0 + 0x100000, 0x200000); + + memcpy (DrvGfxROM2 + 0x000000, DrvGfxROM1 + 0x100000, 0x100000); + memcpy (DrvGfxROM2 + 0x100000, DrvGfxROM1 + 0x300000, 0x100000); + memcpy (DrvGfxROM1 + 0x100000, DrvGfxROM1 + 0x200000, 0x100000); + } +} + +static void thunderl68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x00ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x700000, 0x700fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe07fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, thunderl_write_word); + SekSetWriteByteHandler(0, thunderl_write_byte); + SekSetReadWordHandler(0, thunderl_read_word); + SekSetReadByteHandler(0, thunderl_read_byte); + + SekMapHandler(1, 0x100000, 0x103fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void atehate68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x700000, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x900000, 0x9fffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekSetWriteWordHandler(0, thunderl_write_word); + SekSetWriteByteHandler(0, thunderl_write_byte); + SekSetReadWordHandler(0, thunderl_read_word); + SekSetReadByteHandler(0, thunderl_read_byte); + + SekMapHandler(1, 0x100000, 0x103fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void blockcar68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0xb00000, 0xb00fff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xe00000, 0xe00607 | 0x7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xf00000, 0xf05fff, SM_RAM); + SekSetWriteWordHandler(0, thunderl_write_word); + SekSetWriteByteHandler(0, thunderl_write_byte); + SekSetReadWordHandler(0, madshark_read_word); + SekSetReadByteHandler(0, madshark_read_byte); + + SekMapHandler(1, 0xa00000, 0xa03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + memcpy (DrvSndROM + 0x80000, DrvSndROM, 0x80000); +} + +static void zombraid68kInit() +{ + wrofaero68kInit(); + + SekOpen(0); + SekMapHandler(2, 0xf00000, 0xf00003, SM_READ | SM_WRITE); + SekSetReadWordHandler (2, zombraid_gun_read_word); + SekSetReadByteHandler (2, zombraid_gun_read_byte); + SekSetWriteWordHandler(2, zombraid_gun_write_word); + SekSetWriteByteHandler(2, zombraid_gun_write_byte); + SekClose(); + + memcpy (DrvSndROM + 0x100000, DrvSndROM + 0x080000, 0x280000); +} + +static void BlandiaGfxRearrange() +{ + INT32 rom_size = DrvROMLen[1]; + UINT8 *buf = (UINT8*)BurnMalloc(rom_size); + + UINT8 *rom = DrvGfxROM1 + 0x40000; + + if (rom_size == 0x100000) memcpy (rom, rom + 0x40000, 0x80000); // blandia + + for (INT32 rpos = 0; rpos < 0x80000/2; rpos++) { + buf[rpos+0x40000] = rom[rpos*2]; + buf[rpos] = rom[rpos*2+1]; + } + + memcpy (rom, buf, 0x80000); + + rom = DrvGfxROM2 + 0x40000; + + if (rom_size == 0x100000) memcpy (rom, rom + 0x40000, 0x80000); // blandia + + for (INT32 rpos = 0; rpos < 0x80000/2; rpos++) { + buf[rpos+0x40000] = rom[rpos*2]; + buf[rpos] = rom[rpos*2+1]; + } + + memcpy (rom, buf, 0x80000); + + DrvROMLen[1] = DrvROMLen[2] = 0xc0000; + + BurnFree (buf); +} + +static void blandia68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x21ffff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0011000, 0x701000, 0x70ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x800000, 0x800607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x900000, 0x903fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0xb00000, 0xb0ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xb80000, 0xb8ffff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + memmove (Drv68KROM + 0x100000, Drv68KROM + 0x080000, 0x100000); + memmove (DrvSndROM + 0x100000, DrvSndROM + 0x0c0000, 0x0c0000); + + BlandiaGfxRearrange(); +} + +static void blandiap68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x21ffff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0011000, 0x701000, 0x70ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x88ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(Drv68KRAM + 0x0020000, 0xa80000, 0xa803ff, SM_WRITE); //nop + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb03fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + memmove (Drv68KROM + 0x100000, Drv68KROM + 0x080000, 0x100000); + + // set up sound banks... + { + UINT8 *tmp = (UINT8*)BurnMalloc(0x240000); + + INT32 offsets[16] = { + 0x000000, 0x140000, 0x020000, 0x160000, + 0x040000, 0x180000, 0x060000, 0x1a0000, + 0x080000, 0x1c0000, 0x0a0000, 0x1e0000, + 0x100000, 0x200000, 0x120000, 0x220000 + }; + + for (INT32 i = 0; i < 16; i++) { + memcpy (tmp + offsets[i], DrvSndROM + (i * 0x020000), 0x020000); + } + + memcpy (DrvSndROM, tmp, 0x240000); + + BurnFree (tmp); + } +} + +static void oisipuzl68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x883fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb03fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xc00400, 0xc00fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0x700000, 0x703fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void pairlove68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvNVRAM, 0x800000, 0x8001ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xb00000, 0xb00fff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xe00000, 0xe00607 | 0x7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xf00000, 0xf0ffff, SM_RAM); + SekSetWriteWordHandler(0, pairlove_write_word); + SekSetWriteByteHandler(0, pairlove_write_byte); + SekSetReadWordHandler(0, pairlove_read_word); + SekSetReadByteHandler(0, pairlove_read_byte); + + SekMapHandler(1, 0xa00000, 0xa03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +static void jjsquawkb68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x21ffff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x0010000, 0x700000, 0x70b3ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x70b400, 0x70bfff, SM_RAM); + SekMapMemory(Drv68KRAM2 + 0x001c000, 0x70c000, 0x70ffff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x804000, 0x807fff, SM_RAM); + SekMapMemory(DrvVidRAM1 + 0x4000, 0x884000, 0x88ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa0a000, 0xa0a607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb0c000, 0xb0ffff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + BurnLoadRom(Drv68KROM + 0x0000000, 0, 1); + BurnLoadRom(Drv68KROM + 0x0100000, 1, 1); + + DrvGfxROM2 = DrvGfxROM1 + 0x400000; + DrvROMLen[1] = DrvROMLen[2] = 0x200000; + + memcpy (DrvGfxROM2 + 0x000000, DrvGfxROM1 + 0x100000, 0x100000); + memcpy (DrvGfxROM2 + 0x100000, DrvGfxROM1 + 0x300000, 0x100000); + memcpy (DrvGfxROM1 + 0x100000, DrvGfxROM1 + 0x200000, 0x100000); +} + +static void extdwnhl68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x23ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x600400, 0x600fff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x601000, 0x610bff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x88ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb13fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xe00000, 0xe03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + // swap halves of sound rom + memcpy (DrvSndROM + 0x100000, DrvSndROM + 0x000000, 0x080000); + memcpy (DrvSndROM + 0x000000, DrvSndROM + 0x080000, 0x100000); +} + +static void krzybowl68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvNVRAM, 0x800000, 0x8001ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xb00000, 0xb003ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xe00000, 0xe00607 | 0x7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xf00000, 0xf0ffff, SM_RAM); + SekSetWriteWordHandler(0, thunderl_write_word); + SekSetWriteByteHandler(0, thunderl_write_byte); + SekSetReadWordHandler(0, madshark_read_word); + SekSetReadByteHandler(0, madshark_read_byte); + + SekMapHandler(1, 0xa00000, 0xa03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); +} + +void __fastcall triplfun_sound_write_byte(UINT32 address, UINT8 data) +{ + if ((address & ~1) == 0x500006) { + MSM6295Command(0, data); + } +} + +UINT8 __fastcall triplfun_sound_read_byte(UINT32) +{ + return MSM6295ReadStatus(0); +} + +static void triplfun68kInit() +{ + oisipuzl68kInit(); + + SekOpen(0); + SekMapHandler(2, 0x500006, 0x500007, SM_READ | SM_WRITE); +// SekSetReadWordHandler (2, triplfun_sound_read_word); + SekSetReadByteHandler (2, triplfun_sound_read_byte); +// SekSetWriteWordHandler(2, triplfun_sound_write_word); + SekSetWriteByteHandler(2, triplfun_sound_write_byte); + SekClose(); + + MSM6295Exit(0); + MSM6295Init(0, 792000 / 132, 100.0, 0); + + memcpy (Drv68KROM + 0x100000, Drv68KROM + 0x080000, 0x080000); + memset (Drv68KROM + 0x080000, 0, 0x080000); +} + +static void utoukond68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700400, 0x700fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x880000, 0x883fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb03fff, SM_RAM); + SekSetWriteWordHandler(0, daioh_write_word); + SekSetWriteByteHandler(0, daioh_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0xc00000, 0xc00001, SM_WRITE); + SekSetWriteWordHandler(1, wiggie_sound_write_word); + SekSetWriteByteHandler(1, wiggie_sound_write_byte); + SekClose(); + + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, DrvSubROM); + ZetMapArea(0x0000, 0xdfff, 2, DrvSubROM); + ZetMapArea(0xe000, 0xefff, 0, DrvSubRAM); + ZetMapArea(0xe000, 0xefff, 1, DrvSubRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvSubRAM); + ZetSetWriteHandler(utoukond_sound_write); + ZetSetReadHandler(utoukond_sound_read); + ZetSetOutHandler(utoukond_sound_write_port); + ZetSetInHandler(utoukond_sound_read_port); + ZetMemEnd(); + ZetClose(); + + for (INT32 i = 0; i < 0x400000; i++) DrvGfxROM0[i] ^= 0xff; +} + +static void Wiggie68kDecode() +{ + UINT8 *tmp = Drv68KRAM; + + for (INT32 i = 0; i < 0x20000; i+=16) { + for (INT32 j = 0; j < 16; j++) { + tmp[j] = Drv68KROM[i+((j & 1) | ((j & 2) << 2) | ((j & 0x0c) >> 1))]; + } + memcpy (Drv68KROM + i, tmp, 0x10); + } +} + +static void wiggie68kInit() +{ + thunderl68kInit(); + + SekOpen(0); + SekMapMemory(Drv68KRAM + 0x80000, 0x100000, 0x103fff, SM_READ); // nop + + SekMapHandler(1, 0xb00008, 0xb00009, SM_WRITE); + SekSetWriteWordHandler(1, wiggie_sound_write_word); + SekSetWriteByteHandler(1, wiggie_sound_write_byte); + SekClose(); + + Wiggie68kDecode(); + + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvSubROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvSubROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvSubRAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvSubRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvSubRAM); + ZetSetWriteHandler(wiggie_sound_write); + ZetSetReadHandler(wiggie_sound_read); + ZetMemEnd(); + ZetClose(); +} + +static void downtown68kInit() +{ + downtown_protram = DrvNVRAM; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x09ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x900000, 0x903fff, SM_RAM); + SekMapMemory(DrvShareRAM, 0xb00000, 0xb00fff, SM_WRITE); // m65c02 not emulated, simulate instead + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xf00000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, downtown_write_word); + SekSetWriteByteHandler(0, downtown_write_byte); + SekSetReadWordHandler(0, daioh_read_word); + SekSetReadByteHandler(0, daioh_read_byte); + + SekMapHandler(1, 0x100000, 0x103fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekMapMemory(downtown_protram, 0x200000, 0x2003ff, SM_WRITE); + SekMapHandler(2, 0x200000, 0x2003ff, SM_READ); + SekSetReadByteHandler (2, downtown_prot_read); + + SekMapHandler(3, 0xb00000, 0xb00fff, SM_READ); + SekSetReadByteHandler (3, downtown_sharedram_read_byte); + SekSetReadWordHandler (3, downtown_sharedram_read_word); + SekClose(); +} + +static void metafox68kInit() +{ + downtown68kInit(); + + SekOpen(0); + SekSetReadByteHandler (3, metafox_sharedram_read_byte); + SekSetReadWordHandler (3, metafox_sharedram_read_word); + SekClose(); +} + +static void tndrcade68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x380000, 0x3803ff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x600000, 0x600607 | 0x7ff, SM_RAM); + SekMapMemory(DrvShareRAM, 0xa00000, 0xa00fff, SM_WRITE); // m65c02 not emulated, simulate instead + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + + // install simulation to make game playable + SekMapHandler(3, 0xa00000, 0xa00fff, SM_READ); + SekSetReadByteHandler (3, tndrcade_sharedram_read_byte); + SekSetReadWordHandler (3, tndrcade_sharedram_read_word); + SekClose(); +} + +static void kiwame68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xb00000, 0xb003ff, SM_RAM); + SekMapMemory(DrvNVRAM, 0xfffc00, 0xffffff, SM_WRITE); + + SekSetReadWordHandler(0, kiwame_read_word); + SekSetReadByteHandler(0, kiwame_read_byte); + + SekMapHandler(1, 0xc00000, 0xc03fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + { + // give the game proper vectors + *((UINT16 *)(Drv68KROM + 0x00064)) = 0x0000; + *((UINT16 *)(Drv68KROM + 0x00066)) = 0x0dca; + + // get past backup ram error + // the game never actually tests it before failing?? + *((UINT16 *)(Drv68KROM + 0x136d2)) = 0x6052; + } +} + +UINT8 __fastcall twineagle_extram_read_byte(UINT32 address) +{ + return DrvNVRAM[address & 0x3fe]; +} + +static void twineagle68kInit() +{ + downtown68kInit(); + + SekOpen(0); + SekMapMemory(DrvNVRAM, 0x200000, 0x2003ff, SM_WRITE); + SekMapHandler(2, 0x200000, 0x2003ff, SM_READ); + SekSetReadByteHandler (2, twineagle_extram_read_byte); + + SekMapHandler(3, 0xb00000, 0xb00fff, SM_READ | SM_WRITE); + SekSetReadByteHandler (3, twineagl_sharedram_read_byte); + SekSetReadWordHandler (3, twineagl_sharedram_read_word); + SekSetWriteWordHandler(3, twineagl_sharedram_write_word); + SekSetWriteByteHandler(3, twineagl_sharedram_write_byte); + SekClose(); + + BurnByteswap(Drv68KROM, 0x80000); +} + +static void crazyfgt68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x640400, 0x640fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x880000, 0x883fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xb00000, 0xb03fff, SM_RAM); + SekSetWriteWordHandler(0, crazyfgt_write_word); + SekSetWriteByteHandler(0, crazyfgt_write_byte); + SekSetReadWordHandler(0, crazyfgt_read_word); + SekSetReadByteHandler(0, crazyfgt_read_byte); + SekClose(); + + // Patch protection + *((UINT16*)(Drv68KROM + 0x1078)) = 0x4e71; + + BlandiaGfxRearrange(); // fix bg tiles +} + +static void usclssic68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvSprRAM0, 0x800000, 0x800607 | 0x7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xb00000, 0xb003ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0xd00000, 0xd04fff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0xe00000, 0xe00fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, usclssic_write_word); + SekSetWriteByteHandler(0, usclssic_write_byte); + SekSetReadWordHandler(0, usclssic_read_word); + SekSetReadByteHandler(0, usclssic_read_byte); + SekClose(); + + // m65c02 sound... +} + +static void calibr5068kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x09ffff, SM_ROM); + SekMapMemory(Drv68KRAM2, 0x200000, 0x200fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x700000, 0x7003ff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x900000, 0x904fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, calibr50_write_word); + SekSetWriteByteHandler(0, calibr50_write_byte); + SekSetReadWordHandler(0, calibr50_read_word); + SekSetReadByteHandler(0, calibr50_read_byte); + SekClose(); + + // m65c02 sound... +} + +//----------------------------------------------------------------------------------------------------------------------------------- + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0x20, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0x20, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static INT32 DrvYM3812SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / 16000000; +} + + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 DrvGfxDecode(INT32 type, UINT8 *gfx, INT32 num) +{ + DrvGfxTransMask[num] = NULL; + + INT32 len = DrvROMLen[num]; + if (DrvROMLen[num] == 0) DrvGfxMask[num] = 1; // no divide by 0 + if (len == 0 || type == -1) return 0; + + INT32 Plane0[4] = { ((len * 8) / 2) + 8, ((len * 8) / 2) + 0, 8, 0 }; + INT32 XOffs0[16] = { 0,1,2,3,4,5,6,7, 128,129,130,131,132,133,134,135 }; + INT32 YOffs0[16] = { 0*16,1*16,2*16,3*16,4*16,5*16,6*16,7*16, 16*16,17*16,18*16,19*16,20*16,21*16,22*16,23*16 }; + + INT32 Plane1[4] = { 0, 4, ((len * 8) / 2) + 0, ((len * 8) / 2) + 4 }; + INT32 Plane1a[6] = { (((len * 8) / 3) * 0) + 0, (((len * 8) / 3) * 0) + 4, (((len * 8) / 3) * 1) + 0, (((len * 8) / 3) * 1) + 4, (((len * 8) / 3) * 2) + 0, (((len * 8) / 3) * 2) + 4 }; + INT32 XOffs1[16] = { 128+64,128+65,128+66,128+67, 128+0,128+1,128+2,128+3, 8*8+0,8*8+1,8*8+2,8*8+3, 0,1,2,3 }; + INT32 YOffs1[16] = { 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8, 32*8,33*8,34*8,35*8,36*8,37*8,38*8,39*8 }; + + INT32 Plane2[6] = { ((len * 8) / 2)+0*4, ((len * 8) / 2)+1*4, 2*4,3*4,0*4,1*4 }; + INT32 XOffs2[16] = { 256+128,256+129,256+130,256+131, 256+0,256+1,256+2,256+3, 128,129,130,131, 0,1,2,3 }; + INT32 YOffs2[16] = { 0*16,1*16,2*16,3*16,4*16,5*16,6*16,7*16, 32*16,33*16,34*16,35*16,36*16,37*16,38*16,39*16 }; + + INT32 Plane3[4] = { ((len * 8) / 4) * 0, ((len * 8) / 4) * 1, ((len * 8) / 4) * 2, ((len * 8) / 4) * 3 }; + INT32 XOffs3[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; + INT32 YOffs3[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128+0, 128+8, 128+16, 128+24, 128+32, 128+40, 128+48, 128+56 }; + INT32 YOffs3a[16]= { 0*8, 16*8, 4*8, 20*8, 2*8, 18*8, 6*8, 22*8, 1*8, 17*8, 5*8, 21*8, 3*8, 19*8, 7*8, 23*8 }; // wiggie + INT32 YOffs3b[16]= { 0*8, 2*8, 16*8, 18*8, 1*8, 3*8, 17*8, 19*8, 4*8, 6*8, 20*8, 22*8, 5*8, 7*8,21*8, 23*8 }; // superbar + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, gfx, len); + + switch (type) + { + case 0: // layout_planes_2roms + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane0, XOffs0, YOffs0, 0x200, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + + case 1: // layout_planes_2roms_split + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane1, XOffs1, YOffs1, 0x200, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + + case 2: // layout_packed + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane2 + 2, XOffs2, YOffs2, 0x400, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + + case 3: // layout_packed_6bits_2roms + GfxDecode((len * 1) / (16 * 16), 6, 16, 16, Plane2 + 0, XOffs2, YOffs2, 0x400, tmp, gfx); + DrvGfxMask[num] = (len * 1) / (16 * 16); + ColorDepths[num] = 6; //handled like 4 + break; + + case 4: // layout_packed_6bits_3roms + GfxDecode(((len * 8)/6) / (16 * 16), 6, 16, 16, Plane1a, XOffs1, YOffs1, 0x200, tmp, gfx); + DrvGfxMask[num] = ((len * 8)/6) / (16 * 16); + ColorDepths[num] = 6; //handled like 4 + break; + + case 5: // layout_planes + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane3, XOffs3, YOffs3 , 0x100, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + + case 6: // wiggie_layout + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane3, XOffs3, YOffs3a, 0x100, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + + case 7: // superbar_layout + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Plane3, XOffs3, YOffs3b, 0x100, tmp, gfx); + DrvGfxMask[num] = (len * 2) / (16 * 16); + ColorDepths[num] = 4; + break; + } + + BurnFree (tmp); + + { + INT32 size = DrvGfxMask[num]; + + DrvGfxTransMask[num] = (UINT8*)BurnMalloc(size); + + for (INT32 i = 0; i < size << 8; i += (1 << 8)) { + DrvGfxTransMask[num][i >> 8] = 1; // transparent + for (INT32 j = 0; j < (1 << 8); j++) { + if (gfx[i + j]) { + DrvGfxTransMask[num][i >> 8] = 0; + break; + } + } + } + } + + return 0; +} + +static INT32 DrvLoadRoms(INT32 bload) +{ + char* pRomName; + struct BurnRomInfo ri, rh; + + UINT8 *LoadPrg[2] = { Drv68KROM, DrvSubROM }; + UINT8 *LoadGfx[5] = { DrvGfxROM0, DrvGfxROM1, DrvGfxROM2, DrvSndROM, DrvColPROM }; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i + 0); + BurnDrvGetRomInfo(&rh, i + 1); + + if ((ri.nType & 7) < 3 && (ri.nType & 7)) { + INT32 type = (ri.nType - 1) & 1; + + if ((rh.nType & 7) == 1 && (rh.nLen == ri.nLen)) { + if (bload) if (BurnLoadRom(LoadPrg[type] + 0, i + 1, 2)) return 1; + if (bload) if (BurnLoadRom(LoadPrg[type] + 1, i + 0, 2)) return 1; + LoadPrg[type] += ri.nLen * 2; + i++; // loading two roms + } else { + if (bload) if (BurnLoadRom(LoadPrg[type], i, 1)) return 1; + LoadPrg[type] += ri.nLen; + } + continue; + } + + if ((ri.nType & 7) == 3 || (ri.nType & 7) == 4 || (ri.nType & 7) == 5 || (ri.nType & 7) == 6 || (ri.nType & 7) == 7) { // gfx, snd, colprom + INT32 type = (ri.nType & 7) - 3; + + if (ri.nType & 8) { // interleaved... + if (bload) if (BurnLoadRom(LoadGfx[type] + 0, i + 0, 2)) return 1; + + if ((ri.nType & 16) == 0) { // zingzap + if (bload) if (BurnLoadRom(LoadGfx[type] + 1, i + 1, 2)) return 1; + i++; + } + + LoadGfx[type] += ri.nLen * 2; + } else { + if (bload) if (BurnLoadRom(LoadGfx[type], i, 1)) return 1; + LoadGfx[type] += ri.nLen; + } + + continue; + } + } + + if (bload == 0) { + DrvROMLen[0] = LoadGfx[0] - DrvGfxROM0; + DrvROMLen[1] = LoadGfx[1] - DrvGfxROM1; + DrvROMLen[2] = LoadGfx[2] - DrvGfxROM2; + DrvROMLen[3] = LoadGfx[3] - DrvSndROM; + DrvROMLen[4] = LoadGfx[4] - DrvColPROM; + + // bprintf (0, _T("%x, %x, %x, %x %x\n"), DrvROMLen[0], DrvROMLen[1], DrvROMLen[2], DrvROMLen[3], DrvROMLen[4]); + } + + return 0; +} + +static INT32 DrvDoReset(INT32 ram) +{ + if (ram) memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); // wiggie, utoukond, superbar + ZetReset(); + ZetClose(); + + x1010Reset(); + MSM6295Reset(0); + BurnYM3438Reset(); + BurnYM3812Reset(); + + watchdog = 0; + + tndrcade_init_sim = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x200000; + DrvSubROM = Next; Next += 0x050000; + + DrvGfxROM2 = Next; Next += DrvROMLen[2] * 2; + DrvGfxROM1 = Next; Next += DrvROMLen[1] * 2; + DrvGfxROM0 = Next; Next += DrvROMLen[0] * 2; + + DrvColPROM = Next; Next += 0x000800; + + MSM6295ROM = Next; + X1010SNDROM = Next; + DrvSndROM = Next; Next += DrvROMLen[3] + 0x100000; // for banking + + Palette = (UINT32*)Next; Next += BurnDrvGetPaletteEntries() * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += BurnDrvGetPaletteEntries() * sizeof(UINT32); + + DrvNVRAM = Next; Next += 0x000400; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x100000; + Drv68KRAM2 = Next; Next += 0x020000; + DrvSubRAM = Next; Next += 0x001000; + DrvPalRAM = Next; Next += 0x001000; + DrvSprRAM0 = Next; Next += 0x000800; + DrvSprRAM1 = Next; Next += 0x014000; + + DrvVidRAM0 = Next; Next += 0x010000; + DrvVIDCTRLRAM0 = Next; Next += 0x000008; + + DrvVidRAM1 = Next; Next += 0x010000; + DrvVIDCTRLRAM1 = Next; Next += 0x000008; + + DrvVideoRegs = Next; Next += 0x000008; + + soundlatch = Next; Next += 0x000001; + tilebank = Next; Next += 0x000004; + tile_offset = (UINT32*)Next; Next += 0x000001 * sizeof(UINT32); + + DrvShareRAM = Next; Next += 0x001000; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void DrvSetVideoOffsets(INT32 spritex, INT32 spritex_flipped, INT32 tilesx, INT32 tilesx_flipped) +{ + VideoOffsets[0][0] = spritex; + VideoOffsets[0][1] = spritex_flipped; + VideoOffsets[1][0] = tilesx; + VideoOffsets[1][1] = tilesx_flipped; +} + +static void DrvSetColorOffsets(INT32 gfx0, INT32 gfx1, INT32 gfx2) +{ + ColorOffsets[0] = gfx0; + ColorOffsets[1] = gfx1; + ColorOffsets[2] = gfx2; +} + +static void DrvSetDefaultColorTable() +{ + for (INT32 i = 0; i < BurnDrvGetPaletteEntries(); i++) { + Palette[i] = i; + } +} + +static void zingzapSetColorTable() +{ + for (INT32 color = 0; color < 0x20; color++) { + for (INT32 pen = 0; pen < 0x40; pen++) { + Palette[0x400 + ((color << 6) | pen)] = 0x400 + (((color << 4) + pen) & 0x1ff); + } + } +} + +static void jjsquawkSetColorTable() +{ + for (INT32 color = 0; color < 0x20; color++) { + for (INT32 pen = 0; pen < 0x40; pen++) { + Palette[0x200 + ((color << 6) | pen)] = 0x400 + (((color << 4) + pen) & 0x1ff); + Palette[0xa00 + ((color << 6) | pen)] = 0x200 + (((color << 4) + pen) & 0x1ff); + } + } +} + +static void gundharaSetColorTable() +{ + for (INT32 color = 0; color < 0x20; color++) { + for (INT32 pen = 0; pen < 0x40; pen++) { + Palette[0x200 + ((color << 6) | pen)] = 0x400 + ((((color & ~3) << 4) + pen) & 0x1ff); + Palette[0xa00 + ((color << 6) | pen)] = 0x200 + ((((color & ~3) << 4) + pen) & 0x1ff); + } + } +} + +static void blandiaSetColorTable() +{ + for (INT32 color = 0; color < 0x20; color++) { + for (INT32 pen = 0; pen < 0x40; pen++) { + Palette[0x200 + ((color << 6) | pen)] = 0x200 + ((color << 4) | (pen & 0x0f)); + Palette[0xa00 + ((color << 6) | pen)] = 0x400 + pen; + } + } +} + +static void usclssicSetColorTable() +{ + memcpy (DrvColPROM + 0x600, DrvColPROM + 0x000, 0x200); +// memcpy (DrvColPROM + 0x200, DrvColPROM + 0x200, 0x200); + + for (INT32 color = 0; color < 0x200; color++) { + Palette[color] = color; + } + + for (INT32 color = 0; color < 0x20; color++) { + for (INT32 pen = 0; pen < 0x40; pen++) { + Palette[0x200 + ((color << 6) | pen)] = 0x200 + (((color << 4) + pen) & 0x1ff); + } + } +} + +static INT32 DrvInit(void (*p68kInit)(), INT32 cpu_speed, INT32 irq_type, INT32 spr_buffer, INT32 gfxtype0, INT32 gfxtype1, INT32 gfxtype2) +{ + BurnSetRefreshRate((1.00 * refresh_rate)/100); + + DrvLoadRoms(0); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (DrvLoadRoms(1)) return 1; + + // make sure these are initialized so that we can use common routines + ZetInit(1); + MSM6295Init(0, 1000000 / 132, 100.0, 0); + + if (p68kInit) { + p68kInit(); + } + + DrvGfxDecode(gfxtype0, DrvGfxROM0, 0); + DrvGfxDecode(gfxtype1, DrvGfxROM1, 1); + DrvGfxDecode(gfxtype2, DrvGfxROM2, 2); + + cpuspeed = cpu_speed; + irqtype = irq_type; + buffer_sprites = spr_buffer; + + x1010_sound_init(16000000, 0x0000); + + BurnYM3812Init(4000000, NULL, DrvYM3812SynchroniseStream, 0); + BurnTimerAttachSekYM3812(16000000); + + BurnYM3438Init(1, 16000000/4, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 1); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + DrvSetDefaultColorTable(); + + bprintf (0, _T("%d\n"), nScreenHeight); + + VideoOffsets[2][0] = ((256 - nScreenHeight) / 2); // adjust for screen height + VideoOffsets[2][1] = VideoOffsets[2][0]; + + BurnGunInit(2, true); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ +// FILE *fa = fopen("nvram", "wb"); +// fwrite (DrvNVRAM, 0x400, 1, fa); +// fclose (fa); + + GenericTilesExit(); + + DrvGfxROM0 = NULL; + DrvGfxROM1 = NULL; + DrvGfxROM2 = NULL; + + memset (ColorOffsets, 0, 3 * sizeof(INT32)); + + SekExit(); + ZetExit(); + + BurnGunExit(); + + x1010_exit(); + BurnYM3438Exit(); + BurnYM3812Exit(); + + MSM6295Exit(0); + MSM6295ROM = NULL; + + BurnFree (AllMem); + + oisipuzl_hack = 0; + twineagle = 0; + watchdog_enable = 0; + refresh_rate = 6000; + + BurnFree (DrvGfxTransMask[0]); + BurnFree (DrvGfxTransMask[2]); + BurnFree (DrvGfxTransMask[1]); + + return 0; +} + +// usclssic needs color set up... + +static inline void DrvColors(INT32 i, INT32 pal) +{ + INT32 r = (pal >> 10) & 0x1f; + INT32 g = (pal >> 5) & 0x1f; + INT32 b = (pal >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); +} + +static void DrvPaletteRecalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + if (DrvROMLen[4]) { // color prom + if (DrvROMLen[4] > 1) { // usclassic + memcpy (DrvColPROM + 0x400, DrvPalRAM, 0x200); + memcpy (DrvColPROM + 0x000, DrvPalRAM, 0x200); + } + p = (UINT16*)DrvColPROM; + } + + for (INT32 i = 0; i < BurnDrvGetPaletteEntries(); i++) { + DrvColors(i, p[Palette[i]]); + } +} + +static void draw_sprites_map() +{ + UINT16 *spriteram16 = (UINT16*)DrvSprRAM0; + + INT32 ctrl = spriteram16[0x600/2]; + INT32 ctrl2 = spriteram16[0x602/2]; + + INT32 flip = ctrl & 0x40; + INT32 numcol = ctrl2 & 0x0f; + + UINT16 *src = ((UINT16*)DrvSprRAM1) + ( ((ctrl2 ^ (~ctrl2<<1)) & 0x40) ? 0x2000/2 : 0 ); + + INT32 upper = ( spriteram16[ 0x604/2 ] & 0xFF ) +( spriteram16[ 0x606/2 ] & 0xFF ) * 256; + + INT32 col0 = 0; + switch (ctrl & 0x0f) + { + case 0x01: col0 = 0x4; break; // krzybowl + case 0x06: col0 = 0x8; break; // kiwame + } + + INT32 xoffs = 0; + INT32 yoffs = flip ? 1 : -1; + + if (numcol == 1) numcol = 16; + + for (INT32 col = 0 ; col < numcol; col++) + { + INT32 x = spriteram16[(col * 0x20 + 0x408)/2] & 0xff; + INT32 y = spriteram16[(col * 0x20 + 0x400)/2] & 0xff; + + for (INT32 offs = 0; offs < 0x20; offs++) + { + INT32 code = src[((col+col0)&0xf) * 0x40/2 + offs + 0x800/2]; + INT32 color = src[((col+col0)&0xf) * 0x40/2 + offs + 0xc00/2]; + + INT32 flipx = code & 0x8000; + INT32 flipy = code & 0x4000; + + INT32 bank = (color & 0x0600) >> 9; + + INT32 sx = x + xoffs + (offs & 1) * 16; + INT32 sy = -(y + yoffs) + (offs / 2) * 16; + + if (upper & (1 << col)) sx += 256; + + if (flip) { + sy = 0xf0 - sy; + flipx = !flipx; + flipy = !flipy; + } + + color = (color >> 11) & 0x1f; + code = ((code & 0x3fff) + (bank * 0x4000)) % DrvGfxMask[0]; + + if (DrvGfxTransMask[0][code]) continue; + + sx = ((sx + 0x10) & 0x1ff) - 0x10; + sy = ((sy + 8) & 0x0ff) - 8; + sy = ((sy+16-VideoOffsets[2][0])&0xff)-16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, 0, DrvGfxROM0); + } + } + } + } +} + +static void draw_sprites() +{ + if (~nSpriteEnable & 1) return; + + UINT16 *spriteram16 = (UINT16*)DrvSprRAM0; + + INT32 ctrl = spriteram16[ 0x600/2 ]; + INT32 ctrl2 = spriteram16[ 0x602/2 ]; + + INT32 flip = ctrl & 0x40; + + UINT16 *src = ((UINT16*)DrvSprRAM1) + ( ((ctrl2 ^ (~ctrl2<<1)) & 0x40) ? 0x2000/2 : 0 ); + + draw_sprites_map(); + + INT32 yoffs = oisipuzl_hack ? 32 : 0; + INT32 xoffs = VideoOffsets[0][flip ? 1 : 0]; + + for (INT32 offs = (0x400-2)/2 ; offs >= 0; offs -= 1) + { + int code = src[offs + 0x000/2]; + int sx = src[offs + 0x400/2]; + + int sy = spriteram16[offs + 0x000/2] & 0xff; + + int flipx = code & 0x8000; + int flipy = code & 0x4000; + + INT32 bank = (sx & 0x0600) >> 9; + INT32 color = (sx >> 11) & 0x1f; + + if (flip) + { + sy = (0x100 - nScreenHeight) + 0xf0 - sy; + flipx = !flipx; + flipy = !flipy; + } + + code = ((code & 0x3fff) + (bank * 0x4000)) % DrvGfxMask[0]; + + if (DrvGfxTransMask[0][code]) continue; + + sx = ((sx + xoffs + 0x10) & 0x1ff) - 0x10; + sy = ((((0xf0 - sy) - (-2) + 8)) & 0x0ff) - 8; + sy = ((yoffs+sy+16-VideoOffsets[2][0])&0xff)-16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, ColorOffsets[0], DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, ColorOffsets[0], DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, ColorOffsets[0], DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, ColorDepths[0], 0, ColorOffsets[0], DrvGfxROM0); + } + } + } +} + +// this is needed because some color depths (specifically 6 bits per pixel) need colors added rather than xored. +static void RenderTile(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 trans_col, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height) +{ + INT32 flip = 0; + if (flipy) flip |= (height - 1) * width; + if (flipx) flip |= width - 1; + + gfx += code * width * height; + + for (INT32 y = 0; y < height; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 x = 0; x < width; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((y * width) + x) ^ flip]; + + if (pxl == trans_col) continue; + + dest[sy * nScreenWidth + sx] = pxl + color; + } + + sx -= width; + } +} + +static void draw_layer(UINT8 *ram, UINT8 *gfx, INT32 num, INT32 opaque, INT32 scrollx, INT32 scrolly) +{ + INT32 mask = DrvGfxMask[num]; + INT32 depth = ColorDepths[num]; + INT32 color_offset = ColorOffsets[num]; + + scrollx = (scrollx + VideoOffsets[1][flipscreen]) & 0x3ff; + scrolly = (scrolly + VideoOffsets[2][0]) & 0x1ff; + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x400; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs + 0x000]; + INT32 color = vram[offs + 0x800] & 0x001f; + + INT32 code = (attr & 0x3fff) + tile_offset[0]; + + if (twineagle) { + if ((code & 0x3e00) == 0x3e00) { + code = (code & 0x007f) | ((tilebank[(code & 0x0180) >> 7] >> 1) << 7); + } + } + + code %= mask; + + if (!opaque) { + if (DrvGfxTransMask[num][code]) continue; + } + + INT32 flipx = attr & 0x8000; + INT32 flipy = attr & 0x4000; + + if (flipscreen) { + sx = (nScreenWidth - 16) - sx; + sy = (nScreenHeight - 16) - sy; + flipx ^= 0x8000; + flipy ^= 0x4000; + } + + if (depth == 6) { + RenderTile(pTransDraw, gfx, code, (color * (1<> 6; // disabled for now... + flipscreen ^= tmap_flip; + + INT32 visible = (nScreenHeight - 1); + + UINT16 *vctrl0 = (UINT16*)DrvVIDCTRLRAM0; + UINT16 *vctrl1 = (UINT16*)DrvVIDCTRLRAM1; + + INT32 x_0 = vctrl0[0]; + INT32 y_0 = vctrl0[1]; + INT32 en0 = vctrl0[2]; + + INT32 x_1 = vctrl1[0]; + INT32 y_1 = vctrl1[1]; + INT32 en1 = vctrl1[2]; + + x_0 += 0x10 - VideoOffsets[1][flipscreen ? 1 : 0]; + y_0 -= (256 - visible)/2; + if (flipscreen) + { + x_0 = -x_0 - 512; + y_0 = y_0 - visible; + } + + if (enable_tilemap2) + { + x_1 += 0x10 - VideoOffsets[1][flipscreen ? 1 : 0]; + y_1 -= (256 - visible)/2; + if (flipscreen) + { + x_1 = -x_1 - 512; + y_1 = y_1 - visible; + } + + order = *((UINT16*)(DrvVideoRegs + 2)); + } + + if ( en0 & 0x08) layer_enable &= ~0x01; + if (~en0 & 0x08) layer_enable &= ~0x02; + if ( en1 & 0x08) layer_enable &= ~0x04; + if (~en1 & 0x08) layer_enable &= ~0x08; + if (enable_tilemap2 == 0) layer_enable &= ~0x0c; + + layer_enable &= nBurnLayer; + + BurnTransferClear(); + + if (order & 1) + { + if (layer_enable & 0x04) draw_layer(DrvVidRAM1 + 0x0000, DrvGfxROM2, 2, 1, x_1, y_1); + if (layer_enable & 0x08) draw_layer(DrvVidRAM1 + 0x2000, DrvGfxROM2, 2, 1, x_1, y_1); + + if ((order & 2) == 2) draw_sprites(); + + if (layer_enable & 0x01) draw_layer(DrvVidRAM0 + 0x0000, DrvGfxROM1, 1, 0, x_0, y_0); + if (layer_enable & 0x02) draw_layer(DrvVidRAM0 + 0x2000, DrvGfxROM1, 1, 0, x_0, y_0); + + if ((order & 2) == 0) draw_sprites(); + } + else + { + if (layer_enable & 0x01) draw_layer(DrvVidRAM0 + 0x0000, DrvGfxROM1, 1, 1, x_0, y_0); + if (layer_enable & 0x02) draw_layer(DrvVidRAM0 + 0x2000, DrvGfxROM1, 1, 1, x_0, y_0); + + if ((order & 2) == 2) draw_sprites(); + + if (layer_enable & 0x04) draw_layer(DrvVidRAM1 + 0x0000, DrvGfxROM2, 2, 0, x_1, y_1); + if (layer_enable & 0x08) draw_layer(DrvVidRAM1 + 0x2000, DrvGfxROM2, 2, 0, x_1, y_1); + + if ((order & 2) == 0) draw_sprites(); + } +} + +static INT32 setaNoLayersDraw() +{ + DrvPaletteRecalc(); + + BurnTransferClear(); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 seta1layerDraw() +{ + DrvPaletteRecalc(); + + seta_update(0, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 seta2layerDraw() +{ + DrvPaletteRecalc(); + + seta_update(1, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 zombraidDraw() +{ + seta2layerDraw(); + + for (INT32 i = 0; i < BurnDrvGetMaxPlayers(); i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } + + return 0; +} + +static INT32 seta2layerFlippedDraw() +{ + DrvPaletteRecalc(); + + seta_update(1, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void irq_generator(INT32 loop) +{ + if (loop != 4 && loop != 9) return; + + loop = (loop / 5) & 1; + + INT32 line = (irqtype >> (loop * 8)) & 0xff; + if (line & 0x80) return; + + SekSetIRQLine(line, SEK_IRQSTATUS_AUTO); +} + +static void sprite_buffer() +{ + if ((DrvSprRAM0[0x602] & 0x20) == 0) + { + if (DrvSprRAM0[0x602] & 0x40) { + memcpy (DrvSprRAM1 + 0x0000, DrvSprRAM1 + 0x2000, 0x2000); + } else { + memcpy (DrvSprRAM1 + 0x2000, DrvSprRAM1 + 0x0000, 0x2000); + } + } +} + +static INT32 DrvCommonFrame(void (*pFrameCallback)()) +{ + if (DrvReset) { + DrvDoReset(1); + } + + if (watchdog_enable) { + watchdog++; + if (watchdog >= 180) { + DrvDoReset(0); + } + } + + { + memset (DrvInputs, 0xff, 7 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy6[i] & 1) << i; + DrvInputs[6] ^= (DrvJoy7[i] & 1) << i; + } + + BurnGunMakeInputs(0, (INT16)DrvAxis[0], (INT16)DrvAxis[1]); // zombraid + BurnGunMakeInputs(1, (INT16)DrvAxis[2], (INT16)DrvAxis[3]); + + float xRatio = (float)128 / 384; + float yRatio = (float)96 / 224; + + for (INT32 i = 0; i < 2; i++) { + INT32 x = BurnGunX[i] >> 8; + INT32 y = BurnGunY[i] >> 8; + + x = (INT32)(x * xRatio); + y = (INT32)(y * yRatio); + + x -= 0xbe; + y += 0x48; + + DrvAnalogInput[0 + (i * 2)] = (UINT8)~x; + DrvAnalogInput[1 + (i * 2)] = (UINT8)y; + } + } + + pFrameCallback(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + if (buffer_sprites) { + sprite_buffer(); + } + + return 0; +} + +static void Drv68kNoSubFrameCallback() +{ + INT32 nInterleave = 10; + INT32 nCyclesTotal[1] = { (cpuspeed * 100) / refresh_rate }; + INT32 nCyclesDone[1] = { 0 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + + irq_generator(i); + } + + SekClose(); + + if (pBurnSoundOut) { + x1010_sound_update(); + } +} + +static INT32 DrvFrame() +{ + return DrvCommonFrame(Drv68kNoSubFrameCallback); +} + +static void Drv68k_5IRQ_FrameCallback() +{ + INT32 nInterleave = 10; + INT32 nCyclesTotal[1] = { (cpuspeed * 100) / refresh_rate }; + INT32 nCyclesDone[1] = { 0 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + + if (i & 1 && i == 1) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i & 1 && i != 1) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + SekClose(); + + if (pBurnSoundOut) { + x1010_sound_update(); + } +} + +static INT32 Drv5IRQFrame() +{ + return DrvCommonFrame(Drv68k_5IRQ_FrameCallback); +} + +static void Drv68kNoSubM6295FrameCallback() +{ + INT32 nInterleave = 10; + INT32 nCyclesTotal[1] = { (cpuspeed * 100) / refresh_rate }; + INT32 nCyclesDone[1] = { 0 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + + irq_generator(i); + } + + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } +} + +static INT32 DrvM6295Frame() +{ + return DrvCommonFrame(Drv68kNoSubM6295FrameCallback); +} + +static void Drv68kZ80M6295FrameCallback() +{ + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { (cpuspeed * 100) / refresh_rate, (4000000 * 100) / refresh_rate }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave); + irq_generator(i); + } + + ZetClose(); + SekClose(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } +} + +static INT32 DrvZ80M6295Frame() +{ + return DrvCommonFrame(Drv68kZ80M6295FrameCallback); +} + + +static void Drv68kZ80YM3438FrameCallback() +{ + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { (cpuspeed * 100) / refresh_rate, (4000000 * 100) / refresh_rate }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + irq_generator(i); + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + x1010_sound_update(); + BurnYM3438Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + +} + +static INT32 Drv68kZ80YM3438Frame() +{ + return DrvCommonFrame(Drv68kZ80YM3438FrameCallback); +} + +static void CrzyfghtFrameCallback() +{ + INT32 nInterleave = 6; + INT32 nCyclesTotal[1] = { (cpuspeed * 100) / refresh_rate }; + + SekOpen(0); + + INT32 irq[6] = { 2, 2, 2, 2, 2, 1 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + //BurnTimerUpdateYM3812(nCyclesTotal[0] / nInterleave); + + SekRun(nCyclesTotal[0] / nInterleave); + + SekSetIRQLine(irq[i], SEK_IRQSTATUS_AUTO); + } + + BurnTimerUpdateEndYM3812(); + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + // BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); +} + +static INT32 CrazyfgtFrame() +{ + return DrvCommonFrame(CrzyfghtFrameCallback); +} + + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029708; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = DrvNVRAM; + ba.nLen = 0x400; + ba.szName = "NV Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + x1010_scan(nAction, pnMin); + BurnYM3812Scan(nAction, pnMin); + BurnYM3438Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(seta_samples_bank); + SCAN_VAR(usclssic_port_select); + SCAN_VAR(tndrcade_init_sim); + SCAN_VAR(gun_input_bit); + SCAN_VAR(gun_input_src); + } + + if (nAction & ACB_WRITE) { + INT32 tmpbank = seta_samples_bank; + seta_samples_bank = -1; + set_pcm_bank(tmpbank); + } + + return 0; +} + + +//----------------------------------------------------------------------------------------------------------------- +// Nonworking games... + +// Seta / Visco Roulette? + +static struct BurnRomInfo setaroulRomDesc[] = { + { "uf1002.u14", 0x10000, 0xb3a622b0, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uf1003.u16", 0x10000, 0xa6afd769, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "uf0005.u3", 0x08000, 0x383c2d57, 0x03 | BRF_GRA }, // 2 Sprites + { "uf0006.u4", 0x08000, 0x90c9dae6, 0x03 | BRF_GRA }, // 3 + { "uf0007.u5", 0x08000, 0xe72c3dba, 0x03 | BRF_GRA }, // 4 + { "uf0008.u6", 0x08000, 0xe198e602, 0x03 | BRF_GRA }, // 5 + + { "uf0010.u15", 0x80000, 0x0af13a56, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "uf0009.u13", 0x80000, 0x20f2d7f5, 0x04 | BRF_GRA }, // 7 + { "uf0012.u29", 0x80000, 0xcba2a6b7, 0x04 | BRF_GRA }, // 8 + { "uf0011.u22", 0x80000, 0xaf60adf9, 0x04 | BRF_GRA }, // 9 + { "uf0014.u38", 0x80000, 0xda2bd4e4, 0x04 | BRF_GRA }, // 10 + { "uf0013.u37", 0x80000, 0x645ec3c3, 0x04 | BRF_GRA }, // 11 + { "uf0015.u40", 0x80000, 0x11dc19fa, 0x04 | BRF_GRA }, // 12 + { "uf0016.u48", 0x80000, 0x10f99fa8, 0x04 | BRF_GRA }, // 13 + + { "uf1004.u52", 0x20000, 0xd63ea334, 0x06 | BRF_SND }, // 14 x1-010 Samples + + { "ufo017.bin", 0x00200, 0xbf50c303, 0x00 | BRF_GRA }, // 15 Color Proms + { "ufo018.bin", 0x00200, 0x1c584d5f, 0x00 | BRF_GRA }, // 16 +}; + +STD_ROM_PICK(setaroul) +STD_ROM_FN(setaroul) + +static INT32 NotWorkingInit() +{ + return 1; +} + +struct BurnDriverD BurnDrvSetaroul = { + "setaroul", NULL, NULL, NULL, "198?", + "Seta / Visco Roulette?\0", NULL, "Seta / Visco", "Seta", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, setaroulRomInfo, setaroulRomName, NULL, NULL, DrgnunitInputInfo, NULL, + NotWorkingInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0, + 240, 384, 3, 4 +}; + + +// International Toote (Germany) + +static struct BurnRomInfo inttooteRomDesc[] = { + { "p523.v01_horse_prog_2.002", 0x10000, 0x6ce6f1ad, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "p523.v01_horse_prog_1.003", 0x10000, 0x921fcff5, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ya_002_001.u18", 0x80000, 0xdd108016, 0x01 | BRF_PRG | BRF_ESS }, // 2 + + { "ya_011_004.u10", 0x80000, 0xeb74d2e0, 0x03 | BRF_GRA }, // 3 Sprites + { "ya_011_005.u17", 0x80000, 0x4a6c804b, 0x03 | BRF_GRA }, // 4 + { "ya_011_006.u22", 0x80000, 0xbfae01a5, 0x03 | BRF_GRA }, // 5 + { "ya_011_007.u27", 0x80000, 0x2dc7a294, 0x03 | BRF_GRA }, // 6 + { "p523.v01_horse_fore_1.u135", 0x10000, 0x3a75df30, 0x00 | BRF_GRA }, // 7 + { "p523.v01_horse_fore_2.u134", 0x10000, 0x26fb0339, 0x00 | BRF_GRA }, // 8 + { "p523.v01_horse_fore_3.u133", 0x10000, 0xc38596af, 0x00 | BRF_GRA }, // 9 + { "p523.v01_horse_fore_4.u132", 0x10000, 0x64ef345e, 0x00 | BRF_GRA }, // 10 + + { "ya_011_008.u35", 0x40000, 0x4b890f83, 0x04 | BRF_GRA }, // 11 Layer 1 tiles + { "p523.v01_horse_back_1.u137", 0x20000, 0x39b221ea, 0x04 | BRF_GRA }, // 12 + { "ya_011_009.u41", 0x40000, 0xcaa5e3c1, 0x04 | BRF_GRA }, // 13 + { "p523.v01_horse_back_2.u136", 0x20000, 0x9c5e32a0, 0x04 | BRF_GRA }, // 14 + + { "ya_011_013.u71", 0x80000, 0x2bccaf47, 0x06 | BRF_SND }, // 17 x1-010 Samples + { "ya_011_012.u64", 0x80000, 0xa8015ce6, 0x06 | BRF_SND }, // 18 + + { "ya-010.prom", 0x00200, 0x778094b3, 0x00 | BRF_GRA }, // 15 Color Proms + { "ya-011.prom", 0x00200, 0xbd4fe2f6, 0x00 | BRF_GRA }, // 16 +}; + +STD_ROM_PICK(inttoote) +STD_ROM_FN(inttoote) + +#if 0 +static void inttoote68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(DrvVidRAM0, 0xb00000, 0xb07fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + + + SekMapHandler(1, 0x900000, 0x903fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + + BurnLoadRom(DrvGfxROM0 + 0x070000, 7, 1); + BurnLoadRom(DrvGfxROM0 + 0x0f0000, 8, 1); + BurnLoadRom(DrvGfxROM0 + 0x170000, 9, 1); + BurnLoadRom(DrvGfxROM0 + 0x1f0000, 10, 1); +} + +static INT32 inttooteInit() +{ + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(1, 1, -1, -1); + + return DrvInit(inttoote68kInit, 16000000, SET_IRQLINES(0x80, 0x80) /* Custom */, NO_SPRITE_BUFFER, SET_GFX_DECODE(5, 1, -1)); +} +#endif + +struct BurnDriverD BurnDrvInttoote = { + "inttoote", "jockeyc", NULL, NULL, "1998", + "International Toote (Germany)\0", NULL, "Coinmaster", "Seta", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, inttooteRomInfo, inttooteRomName, NULL, NULL, DrgnunitInputInfo, NULL, + NotWorkingInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0, + 384, 240, 4, 3 +}; + + +// International Toote II (World?) + +static struct BurnRomInfo inttooteaRomDesc[] = { + { "p387.v01_horse_prog_2.002", 0x10000, 0x1ced885e, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "p387.v01_horse_prog_1.003", 0x10000, 0xe24592af, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ya_002_001.u18", 0x80000, 0xdd108016, 0x01 | BRF_PRG | BRF_ESS }, // 2 + + { "ya_011_004.u10", 0x80000, 0xeb74d2e0, 0x03 | BRF_GRA }, // 3 Sprites + { "ya_011_005.u17", 0x80000, 0x4a6c804b, 0x03 | BRF_GRA }, // 4 + { "ya_011_006.u22", 0x80000, 0xbfae01a5, 0x03 | BRF_GRA }, // 5 + { "ya_011_007.u27", 0x80000, 0x2dc7a294, 0x03 | BRF_GRA }, // 6 + { "p523.v01_horse_fore_1.u135", 0x10000, 0x3a75df30, 0x00 | BRF_GRA }, // 7 + { "p523.v01_horse_fore_2.u134", 0x10000, 0x26fb0339, 0x00 | BRF_GRA }, // 8 + { "p523.v01_horse_fore_3.u133", 0x10000, 0xc38596af, 0x00 | BRF_GRA }, // 9 + { "p523.v01_horse_fore_4.u132", 0x10000, 0x64ef345e, 0x00 | BRF_GRA }, // 10 + + { "ya_011_008.u35", 0x40000, 0x4b890f83, 0x04 | BRF_GRA }, // 11 Layer 1 tiles + { "p523.v01_horse_back_1.u137", 0x20000, 0x39b221ea, 0x04 | BRF_GRA }, // 12 + { "ya_011_009.u41", 0x40000, 0xcaa5e3c1, 0x04 | BRF_GRA }, // 13 + { "p523.v01_horse_back_2.u136", 0x20000, 0x9c5e32a0, 0x04 | BRF_GRA }, // 14 + + { "ya_011_013.u71", 0x80000, 0x2bccaf47, 0x06 | BRF_SND }, // 17 x1-010 Samples + { "ya_011_012.u64", 0x80000, 0xa8015ce6, 0x06 | BRF_SND }, // 18 + + { "ya-010.prom", 0x00200, 0x778094b3, 0x00 | BRF_GRA }, // 15 Color Proms + { "ya-011.prom", 0x00200, 0xbd4fe2f6, 0x00 | BRF_GRA }, // 16 +}; + +STD_ROM_PICK(inttootea) +STD_ROM_FN(inttootea) + +struct BurnDriverD BurnDrvInttootea = { + "inttootea", "jockeyc", NULL, NULL, "1993", + "International Toote II (World?)\0", NULL, "Coinmaster", "Seta", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, inttooteaRomInfo, inttooteaRomName, NULL, NULL, DrgnunitInputInfo, NULL, + NotWorkingInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0, + 384, 240, 4, 3 +}; + + +//----------------------------------------------------------------------------------------------------------------- +// Working games + + +// Dragon Unit / Castle of Dragon + +static struct BurnRomInfo drgnunitRomDesc[] = { + { "prg-e.bin", 0x20000, 0x728447df, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "prg-o.bin", 0x20000, 0xb2f58ecf, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "obj-2.bin", 0x20000, 0xd7f6ab5a, 0x0b | BRF_GRA }, // 2 Sprites + { "obj-1.bin", 0x20000, 0x53a95b13, 0x0b | BRF_GRA }, // 3 + { "obj-6.bin", 0x20000, 0x80b801f7, 0x0b | BRF_GRA }, // 4 + { "obj-5.bin", 0x20000, 0x6b87bc20, 0x0b | BRF_GRA }, // 5 + { "obj-4.bin", 0x20000, 0x60d17771, 0x0b | BRF_GRA }, // 6 + { "obj-3.bin", 0x20000, 0x0bccd4d5, 0x0b | BRF_GRA }, // 7 + { "obj-8.bin", 0x20000, 0x826c1543, 0x0b | BRF_GRA }, // 8 + { "obj-7.bin", 0x20000, 0xcbaa7f6a, 0x0b | BRF_GRA }, // 9 + + { "scr-1o.bin", 0x20000, 0x671525db, 0x04 | BRF_GRA }, // 10 Layer 1 tiles + { "scr-2o.bin", 0x20000, 0x2a3f2ed8, 0x04 | BRF_GRA }, // 11 + { "scr-3o.bin", 0x20000, 0x4d33a92d, 0x04 | BRF_GRA }, // 12 + { "scr-4o.bin", 0x20000, 0x79a0aa61, 0x04 | BRF_GRA }, // 13 + { "scr-1e.bin", 0x20000, 0xdc9cd8c9, 0x04 | BRF_GRA }, // 14 + { "scr-2e.bin", 0x20000, 0xb6126b41, 0x04 | BRF_GRA }, // 15 + { "scr-3e.bin", 0x20000, 0x1592b8c2, 0x04 | BRF_GRA }, // 16 + { "scr-4e.bin", 0x20000, 0x8201681c, 0x04 | BRF_GRA }, // 17 + + { "snd-1.bin", 0x20000, 0x8f47bd0d, 0x06 | BRF_SND }, // 18 x1-010 Samples + { "snd-2.bin", 0x20000, 0x65c40ef5, 0x06 | BRF_SND }, // 19 + { "snd-3.bin", 0x20000, 0x71fbd54e, 0x06 | BRF_SND }, // 20 + { "snd-4.bin", 0x20000, 0xac50133f, 0x06 | BRF_SND }, // 21 + { "snd-5.bin", 0x20000, 0x70652f2c, 0x06 | BRF_SND }, // 22 + { "snd-6.bin", 0x20000, 0x10a1039d, 0x06 | BRF_SND }, // 23 + { "snd-7.bin", 0x20000, 0xdecbc8b0, 0x06 | BRF_SND }, // 24 + { "snd-8.bin", 0x20000, 0x3ac51bee, 0x06 | BRF_SND }, // 25 +}; + +STD_ROM_PICK(drgnunit) +STD_ROM_FN(drgnunit) + +static INT32 drgnunitInit() +{ + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(2, 2, -2, -2); + + return DrvInit(drgnunit68kInit, 8000000, SET_IRQLINES(1, 2), SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvDrgnunit = { + "drgnunit", NULL, NULL, NULL, "1989", + "Dragon Unit / Castle of Dragon\0", NULL, "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, drgnunitRomInfo, drgnunitRomName, NULL, NULL, DrgnunitInputInfo, DrgnunitDIPInfo, + drgnunitInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Quiz Kokology + +static struct BurnRomInfo qzkklogyRomDesc[] = { + { "3.u27", 0x20000, 0xb8c27cde, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "1.u9", 0x20000, 0xce01cd54, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "4.u33", 0x20000, 0x4f5c554c, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "2.u17", 0x20000, 0x65fa1b8d, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "t2709u32.u32", 0x80000, 0x900f196c, 0x03 | BRF_GRA }, // 4 Sprites + { "t2709u26.u26", 0x80000, 0x416ac849, 0x03 | BRF_GRA }, // 5 + + { "t2709u42.u39", 0x80000, 0x194d5704, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "t2709u39.u42", 0x80000, 0x6f95a76d, 0x04 | BRF_GRA }, // 7 + + { "t2709u47.u47", 0x80000, 0x0ebdad40, 0x06 | BRF_SND }, // 8 x1-010 Samples + { "t2709u55.u55", 0x80000, 0x43960c68, 0x06 | BRF_SND }, // 9 +}; + +STD_ROM_PICK(qzkklogy) +STD_ROM_FN(qzkklogy) + +static INT32 qzkklogyInit() +{ + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(1, 1, -1, -1); + + return DrvInit(drgnunit68kInit, 8000000, SET_IRQLINES(1, 2), SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvQzkklogy = { + "qzkklogy", NULL, NULL, NULL, "1992", + "Quiz Kokology\0", NULL, "Tecmo", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, qzkklogyRomInfo, qzkklogyRomName, NULL, NULL, QzkklogyInputInfo, QzkklogyDIPInfo, + qzkklogyInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Strike Gunner S.T.G + +static struct BurnRomInfo stgRomDesc[] = { + { "att01003.u27", 0x20000, 0x7a640a93, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "att01001.u9", 0x20000, 0x4fa88ad3, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "att01004.u33", 0x20000, 0xbbd45ca1, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "att01002.u17", 0x20000, 0x2f8fd80c, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "att01006.u32", 0x80000, 0x6ad78ea2, 0x03 | BRF_GRA }, // 4 Sprites + { "att01005.u26", 0x80000, 0xa347ff00, 0x03 | BRF_GRA }, // 5 + + { "att01008.u39", 0x80000, 0x20c47457, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "att01007.u42", 0x80000, 0xac975544, 0x04 | BRF_GRA }, // 7 + + { "att01009.u47", 0x80000, 0x4276b58d, 0x06 | BRF_SND }, // 8 x1-010 Samples + { "att01010.u55", 0x80000, 0xfffb2f53, 0x06 | BRF_SND }, // 9 +}; + +STD_ROM_PICK(stg) +STD_ROM_FN(stg) + +static INT32 stgInit() +{ + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(0, 0, -2, -2); + + return DrvInit(drgnunit68kInit, 8000000, SET_IRQLINES(2, 1), SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvStg = { + "stg", NULL, NULL, NULL, "1991", + "Strike Gunner S.T.G\0", NULL, "Athena / Tecmo", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, stgRomInfo, stgRomName, NULL, NULL, StgInputInfo, StgDIPInfo, + stgInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Quiz Kokology 2 + +static struct BurnRomInfo qzkklgy2RomDesc[] = { + { "fn001001.106", 0x080000, 0x7bf8eb17, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fn001003.107", 0x040000, 0xee6ef111, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fn001004.100", 0x100000, 0x5ba139a2, 0x03 | BRF_GRA }, // 2 Sprites + + { "fn001005.104", 0x200000, 0x95726a63, 0x04 | BRF_GRA }, // 3 Layer 1 tiles + + { "fn001006.105", 0x100000, 0x83f201e6, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(qzkklgy2) +STD_ROM_FN(qzkklgy2) + +static INT32 qzkklgy2Init() +{ + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(0, 0, -1, -3); + + return DrvInit(drgnunit68kInit, 16000000, SET_IRQLINES(1, 2), SPRITE_BUFFER, SET_GFX_DECODE(0, 2, -1)); +} + +struct BurnDriver BurnDrvQzkklgy2 = { + "qzkklgy2", NULL, NULL, NULL, "1993", + "Quiz Kokology 2\0", NULL, "Tecmo", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, qzkklgy2RomInfo, qzkklgy2RomName, NULL, NULL, Qzkklgy2InputInfo, Qzkklgy2DIPInfo, + qzkklgy2Init, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Daioh + +static struct BurnRomInfo daiohRomDesc[] = { + { "fg1-001", 0x080000, 0x104ae74a, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fg1-002", 0x080000, 0xe39a4e67, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fg1-004", 0x100000, 0x9ab0533e, 0x03 | BRF_GRA }, // 2 Sprites + { "fg1-003", 0x100000, 0x1c9d51e2, 0x03 | BRF_GRA }, // 3 + + { "fg1-005", 0x200000, 0xc25159b9, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + + { "fg1-006", 0x200000, 0x2052c39a, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "fg1-007", 0x100000, 0x4a2fe9e0, 0x06 | BRF_SND }, // 6 x1-010 Samples +}; + +STD_ROM_PICK(daioh) +STD_ROM_FN(daioh) + +static INT32 daiohInit() +{ + DrvSetVideoOffsets(1, 1, -1, -1); + DrvSetColorOffsets(0, 0x400, 0x200); + + return DrvInit(daioh68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); +} + +struct BurnDriver BurnDrvDaioh = { + "daioh", NULL, NULL, NULL, "1993", + "Daioh\0", NULL, "Athena", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, daiohRomInfo, daiohRomName, NULL, NULL, DaiohInputInfo, DaiohDIPInfo, + daiohInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 240, 384, 3, 4 +}; + + +// Rezon + +static struct BurnRomInfo rezonRomDesc[] = { + { "us001001.u3", 0x020000, 0xab923052, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "us001002.u4", 0x020000, 0x3dafa0d5, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "us001004.103", 0x020000, 0x54871c7c, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "us001003.102", 0x020000, 0x1ac3d272, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "us001006.u64", 0x080000, 0xa4916e96, 0x03 | BRF_GRA }, // 4 Sprites + { "us001005.u63", 0x080000, 0xe6251ebc, 0x03 | BRF_GRA }, // 5 + + { "us001007.u66", 0x080000, 0x3760b935, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + + { "us001008.u68", 0x080000, 0x0ab73910, 0x05 | BRF_GRA }, // 7 Layer 2 tiles + + { "us001009.u70", 0x100000, 0x0d7d2e2b, 0x06 | BRF_SND }, // 8 x1-010 Samples +}; + +STD_ROM_PICK(rezon) +STD_ROM_FN(rezon) + +static INT32 rezonInit() +{ + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(wrofaero68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); + + if (nRet == 0) { + memcpy (Drv68KROM + 0x100000, Drv68KROM + 0x040000, 0x040000); + memset (Drv68KROM + 0x040000, 0, 0x40000); + BurnByteswap(DrvSndROM, 0x100000); + } + + return nRet; +} + +struct BurnDriver BurnDrvRezon = { + "rezon", NULL, NULL, NULL, "1991", + "Rezon\0", NULL, "Allumer", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, rezonRomInfo, rezonRomName, NULL, NULL, RezonInputInfo, RezonDIPInfo, + rezonInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 240, 4, 3 +}; + + +// Rezon (Taito) + +static struct BurnRomInfo rezontRomDesc[] = { + { "us001001.u3", 0x020000, 0xab923052, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "rezon_1_p.u4", 0x020000, 0x9ed32f8c, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "us001004.103", 0x020000, 0x54871c7c, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "us001003.102", 0x020000, 0x1ac3d272, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "us001006.u64", 0x080000, 0xa4916e96, 0x03 | BRF_GRA }, // 4 Sprites + { "us001005.u63", 0x080000, 0xe6251ebc, 0x03 | BRF_GRA }, // 5 + + { "us001007.u66", 0x080000, 0x3760b935, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + + { "us001008.u68", 0x080000, 0x0ab73910, 0x05 | BRF_GRA }, // 7 Layer 2 tiles + + { "us001009.u70", 0x100000, 0x0d7d2e2b, 0x06 | BRF_SND }, // 8 x1-010 Samples +}; + +STD_ROM_PICK(rezont) +STD_ROM_FN(rezont) + +struct BurnDriver BurnDrvRezont = { + "rezont", "rezon", NULL, NULL, "1992", + "Rezon (Taito)\0", NULL, "Allumer (Taito license)", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, rezontRomInfo, rezontRomName, NULL, NULL, RezonInputInfo, RezonDIPInfo, + rezonInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 240, 4, 3 +}; + + +// Eight Forces + +static struct BurnRomInfo eightfrcRomDesc[] = { + { "uy2-u4.u3", 0x040000, 0xf1f249c5, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uy2-u3.u4", 0x040000, 0x6f2d8618, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "u64.bin", 0x080000, 0xf561ff2e, 0x03 | BRF_GRA }, // 2 Sprites + { "u63.bin", 0x080000, 0x4c3f8366, 0x03 | BRF_GRA }, // 3 + + { "u66.bin", 0x100000, 0x6fad2b7f, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + + { "u68.bin", 0x100000, 0xc17aad22, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "u70.bin", 0x100000, 0xdfdb67a3, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "u69.bin", 0x100000, 0x82ec08f1, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(eightfrc) +STD_ROM_FN(eightfrc) + +static INT32 eightfrcInit() +{ + DrvSetVideoOffsets(3, 4, 0, 0); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(wrofaero68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); + + if (nRet == 0) { + memcpy (DrvSndROM + 0x100000, DrvSndROM + 0x0c0000, 0x140000); // sound banks + } + + return nRet; +} + +struct BurnDriver BurnDrvEightfrc = { + "eightfrc", NULL, NULL, NULL, "1994", + "Eight Forces\0", NULL, "Tecmo", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, eightfrcRomInfo, eightfrcRomName, NULL, NULL, EightfrcInputInfo, EightfrcDIPInfo, + eightfrcInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 224, 384, 3, 4 +}; + + +// War of Aero - Project MEIOU + +static struct BurnRomInfo wrofaeroRomDesc[] = { + { "u3.bin", 0x40000, 0x9b896a97, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u4.bin", 0x40000, 0xdda84846, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "u64.bin", 0x80000, 0xf06ccd78, 0x03 | BRF_GRA }, // 2 Sprites + { "u63.bin", 0x80000, 0x2a602a1b, 0x03 | BRF_GRA }, // 3 + + { "u66.bin", 0x80000, 0xc9fc6a0c, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + + { "u68.bin", 0x80000, 0x25c0c483, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "u69.bin", 0x80000, 0x957ecd41, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "u70.bin", 0x80000, 0x8d756fdf, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(wrofaero) +STD_ROM_FN(wrofaero) + +static INT32 wrofaeroInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0x400, 0x200); + + return DrvInit(wrofaero68kInit, 16000000, SET_IRQLINES(2, 4), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); +} + +struct BurnDriver BurnDrvWrofaero = { + "wrofaero", NULL, NULL, NULL, "1993", + "War of Aero - Project MEIOU\0", NULL, "Yang Cheng", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, wrofaeroRomInfo, wrofaeroRomName, NULL, NULL, WrofaeroInputInfo, WrofaeroDIPInfo, + wrofaeroInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 240, 384, 3, 4 +}; + + +// Zing Zing Zip + +static struct BurnRomInfo zingzipRomDesc[] = { + { "uy001001.3", 0x040000, 0x1a1687ec, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uy001002.4", 0x040000, 0x62e3b0c4, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "uy001006.64", 0x080000, 0x46e4a7d8, 0x03 | BRF_GRA }, // 2 Sprites + { "uy001005.63", 0x080000, 0x4aac128e, 0x03 | BRF_GRA }, // 3 + + { "uy001008.66", 0x100000, 0x1dff7c4b, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + { "uy001007.65", 0x080000, 0xec5b3ab9, 0x1c | BRF_GRA }, // 5 + + { "uy001010.68", 0x100000, 0xbdbcdf03, 0x05 | BRF_GRA }, // 6 Layer 2 tiles + + { "uy001011.70", 0x100000, 0xbd845f55, 0x06 | BRF_SND }, // 7 x1-010 Samples +}; + +STD_ROM_PICK(zingzip) +STD_ROM_FN(zingzip) + +static INT32 zingzipInit() +{ + DrvSetVideoOffsets(0, 0, -1, -2); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(wrofaero68kInit, 16000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 2)); + + if (nRet == 0) { + zingzapSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvZingzip = { + "zingzip", NULL, NULL, NULL, "1992", + "Zing Zing Zip\0", NULL, "Allumer + Tecmo", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, zingzipRomInfo, zingzipRomName, NULL, NULL, ZingzipInputInfo, ZingzipDIPInfo, + zingzipInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0xc00, + 240, 384, 3, 4 +}; + + +// Mobile Suit Gundam + +static struct BurnRomInfo msgundamRomDesc[] = { + { "fa003002.u25", 0x080000, 0x1cc72d4c, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fa001001.u20", 0x100000, 0xfca139d0, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fa001008.u21", 0x200000, 0xe7accf48, 0x03 | BRF_GRA }, // 2 Sprites + { "fa001007.u22", 0x200000, 0x793198a6, 0x03 | BRF_GRA }, // 3 + + { "fa001006.u23", 0x100000, 0x3b60365c, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + + { "fa001005.u24", 0x080000, 0x8cd7ff86, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "fa001004.u26", 0x100000, 0xb965f07c, 0x06 | BRF_SND }, // 6 x1-010 Samples +}; + +STD_ROM_PICK(msgundam) +STD_ROM_FN(msgundam) + +static INT32 msgundamInit() +{ + refresh_rate = 5666; // 56.66 hz + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(msgundam68kInit, 16000000, SET_IRQLINES(4, 2), SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); + + if (nRet == 0) { + memmove (Drv68KROM + 0x100000, Drv68KROM + 0x080000, 0x100000); + memset(Drv68KROM + 0x080000, 0, 0x080000); + } + + return nRet; +} + +struct BurnDriver BurnDrvMsgundam = { + "msgundam", NULL, NULL, NULL, "1993", + "Mobile Suit Gundam\0", NULL, "Banpresto", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, msgundamRomInfo, msgundamRomName, NULL, NULL, MsgundamInputInfo, MsgundamDIPInfo, + msgundamInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 240, 4, 3 +}; + + +// Mobile Suit Gundam (Japan) + +static struct BurnRomInfo msgundam1RomDesc[] = { + { "fa002002.u25", 0x080000, 0xdee3b083, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fa001001.u20", 0x100000, 0xfca139d0, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fa001008.u21", 0x200000, 0xe7accf48, 0x03 | BRF_GRA }, // 2 Sprites + { "fa001007.u22", 0x200000, 0x793198a6, 0x03 | BRF_GRA }, // 3 + + { "fa001006.u23", 0x100000, 0x3b60365c, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + + { "fa001005.u24", 0x080000, 0x8cd7ff86, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "fa001004.u26", 0x100000, 0xb965f07c, 0x06 | BRF_SND }, // 6 x1-010 Samples +}; + +STD_ROM_PICK(msgundam1) +STD_ROM_FN(msgundam1) + +struct BurnDriver BurnDrvMsgundam1 = { + "msgundam1", "msgundam", NULL, NULL, "1993", + "Mobile Suit Gundam (Japan)\0", NULL, "Banpresto", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, msgundam1RomInfo, msgundam1RomName, NULL, NULL, MsgundamInputInfo, Msgunda1DIPInfo, + msgundamInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 240, 4, 3 +}; + + +// SD Gundam Neo Battling (Japan) + +static struct BurnRomInfo neobattlRomDesc[] = { + { "bp923001.u45", 0x020000, 0x0d0aeb73, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bp923002.u46", 0x020000, 0x9731fbbc, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "bp923-003.u15", 0x080000, 0x91ca98a1, 0x03 | BRF_GRA }, // 2 Sprites + { "bp923-004.u9", 0x080000, 0x15c678e3, 0x03 | BRF_GRA }, // 3 + + { "bp923-005.u4", 0x100000, 0x7c0e37be, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(neobattl) +STD_ROM_FN(neobattl) + +static INT32 umanclubInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(umanclub68kInit, 16000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriver BurnDrvNeobattl = { + "neobattl", NULL, NULL, NULL, "1992", + "SD Gundam Neo Battling (Japan)\0", NULL, "Banpresto / Sotsu Agency. Sunrise", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, neobattlRomInfo, neobattlRomName, NULL, NULL, NeobattlInputInfo, NeobattlDIPInfo, + umanclubInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Ultraman Club - Tatakae! Ultraman Kyoudai!! + +static struct BurnRomInfo umanclubRomDesc[] = { + { "uw001006.u48", 0x020000, 0x3dae1e9d, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uw001007.u49", 0x020000, 0x5c21e702, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "bp-u-002.u2", 0x080000, 0x936cbaaa, 0x03 | BRF_GRA }, // 2 Sprites + { "bp-u-001.u1", 0x080000, 0x87813c48, 0x03 | BRF_GRA }, // 3 + + { "uw003.u13", 0x100000, 0xe2f718eb, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(umanclub) +STD_ROM_FN(umanclub) + +struct BurnDriver BurnDrvUmanclub = { + "umanclub", NULL, NULL, NULL, "1992", + "Ultraman Club - Tatakae! Ultraman Kyoudai!!\0", NULL, "Tsuburaya Prod. / Banpresto", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, umanclubRomInfo, umanclubRomName, NULL, NULL, UmanclubInputInfo, UmanclubDIPInfo, + umanclubInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Masked Riders Club Battle Race + +static struct BurnRomInfo kamenridRomDesc[] = { + { "fj001003.25", 0x080000, 0x9b65d1b9, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "fj001005.21", 0x100000, 0x5d031333, 0x03 | BRF_GRA }, // 1 Sprites + { "fj001006.22", 0x100000, 0xcf28eb78, 0x03 | BRF_GRA }, // 2 + + { "fj001007.152", 0x080000, 0xd9ffe80b, 0x04 | BRF_GRA }, // 3 user1 + + { "fj001008.26", 0x100000, 0x45e2b329, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(kamenrid) +STD_ROM_FN(kamenrid) + +static INT32 kamenridInit() +{ + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x400, 0x200); + + return DrvInit(kamenrid68kInit, 16000000, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); +} + +struct BurnDriver BurnDrvKamenrid = { + "kamenrid", NULL, NULL, NULL, "1993", + "Masked Riders Club Battle Race\0", NULL, "Toei / Banpresto", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, kamenridRomInfo, kamenridRomName, NULL, NULL, KamenridInputInfo, KamenridDIPInfo, + kamenridInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 240, 4, 3 +}; + + +// Mad Shark + +static struct BurnRomInfo madsharkRomDesc[] = { + { "fq001002.201", 0x080000, 0x4286a811, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fq001001.200", 0x080000, 0x38bfa0ad, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fq001004.202", 0x200000, 0xe56a1b5e, 0x03 | BRF_GRA }, // 2 Sprites + + { "fq001006.152", 0x200000, 0x3bc5e8e4, 0x04 | BRF_GRA }, // 3 user1 + { "fq001005.205", 0x100000, 0x5f6c6d4a, 0x1c | BRF_GRA }, // 4 + + { "fq001007.26", 0x100000, 0xe4b33c13, 0x06 | BRF_SND }, // 5 x1-010 Samples +}; + +STD_ROM_PICK(madshark) +STD_ROM_FN(madshark) + +static INT32 madsharkInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0x200, 0xa00); + + INT32 nRet = DrvInit(madshark68kInit, 16000000, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 3)); + + if (nRet == 0) { + jjsquawkSetColorTable(); + } + + return nRet; +} + +static INT32 madsharkExit() +{ + BurnFree (DrvGfxROM2); + + return DrvExit(); +} + +struct BurnDriver BurnDrvMadshark = { + "madshark", NULL, NULL, NULL, "1993", + "Mad Shark\0", NULL, "Allumer", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, madsharkRomInfo, madsharkRomName, NULL, NULL, MadsharkInputInfo, MadsharkDIPInfo, + madsharkInit, madsharkExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 224, 384, 3, 4 +}; + + +// Wit's (Japan) + +static struct BurnRomInfo witsRomDesc[] = { + { "un001001.u1", 0x08000, 0x416c567e, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "un001002.u4", 0x08000, 0x497a3fa6, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "un001008.7l", 0x20000, 0x1d5d0b2b, 0x0b | BRF_GRA }, // 2 Sprites + { "un001007.5l", 0x20000, 0x9e1e6d51, 0x0b | BRF_GRA }, // 3 + { "un001006.4l", 0x20000, 0x98a980d4, 0x0b | BRF_GRA }, // 4 + { "un001005.2l", 0x20000, 0x6f2ce3c0, 0x0b | BRF_GRA }, // 5 + + { "un001004.12a", 0x20000, 0xa15ff938, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "un001003.10a", 0x20000, 0x3f4b9e55, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(wits) +STD_ROM_FN(wits) + +static INT32 witsInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(thunderl68kInit, 8000000, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriver BurnDrvWits = { + "wits", NULL, NULL, NULL, "1989", + "Wit's (Japan)\0", NULL, "Athena (Visco license)", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, witsRomInfo, witsRomName, NULL, NULL, WitsInputInfo, WitsDIPInfo, + witsInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Thunder & Lightning + +static struct BurnRomInfo thunderlRomDesc[] = { + { "m4", 0x08000, 0x1e6b9462, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "m5", 0x08000, 0x7e82793e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "t17", 0x20000, 0x599a632a, 0x0b | BRF_GRA }, // 2 Sprites + { "t16", 0x20000, 0x3aeef91c, 0x0b | BRF_GRA }, // 3 + { "t15", 0x20000, 0xb97a7b56, 0x0b | BRF_GRA }, // 4 + { "t14", 0x20000, 0x79c707be, 0x0b | BRF_GRA }, // 5 + + { "r28", 0x80000, 0xa043615d, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "r27", 0x80000, 0xcb8425a3, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(thunderl) +STD_ROM_FN(thunderl) + +struct BurnDriver BurnDrvThunderl = { + "thunderl", NULL, NULL, NULL, "1990", + "Thunder & Lightning\0", NULL, "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, thunderlRomInfo, thunderlRomName, NULL, NULL, ThunderlInputInfo, ThunderlDIPInfo, + witsInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Athena no Hatena ? + +static struct BurnRomInfo atehateRomDesc[] = { + { "fs001001.evn", 0x080000, 0x4af1f273, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fs001002.odd", 0x080000, 0xc7ca7a85, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fs001003.gfx", 0x200000, 0x8b17e431, 0x03 | BRF_GRA }, // 2 Sprites + + { "fs001004.pcm", 0x100000, 0xf9344ce5, 0x06 | BRF_SND }, // 3 x1-010 Samples +}; + +STD_ROM_PICK(atehate) +STD_ROM_FN(atehate) + +static INT32 atehateInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(atehate68kInit, 16000000, SET_IRQLINES(2, 1), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriver BurnDrvAtehate = { + "atehate", NULL, NULL, NULL, "1993", + "Athena no Hatena ?\0", NULL, "Athena", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, atehateRomInfo, atehateRomName, NULL, NULL, AtehateInputInfo, AtehateDIPInfo, + atehateInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; + + +// Block Carnival / Thunder & Lightning 2 + +static struct BurnRomInfo blockcarRomDesc[] = { + { "u1.a1", 0x20000, 0x4313fb00, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u4.a3", 0x20000, 0x2237196d, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "bl-chr-0.j3", 0x80000, 0xa33300ca, 0x03 | BRF_GRA }, // 2 Sprites + { "bl-chr-1.l3", 0x80000, 0x563de808, 0x03 | BRF_GRA }, // 3 + + { "bl-snd-0.a13", 0x80000, 0xa92dabaf, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(blockcar) +STD_ROM_FN(blockcar) + +static INT32 blockcarInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(blockcar68kInit, 8000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriver BurnDrvBlockcar = { + "blockcar", NULL, NULL, NULL, "1992", + "Block Carnival / Thunder & Lightning 2\0", NULL, "Visco", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, blockcarRomInfo, blockcarRomName, NULL, NULL, BlockcarInputInfo, BlockcarDIPInfo, + blockcarInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Zombie Raid (US) + +static struct BurnRomInfo zombraidRomDesc[] = { + { "fy001003.3", 0x080000, 0x0b34b8f7, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fy001004.4", 0x080000, 0x71bfeb1a, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "fy001002.103", 0x080000, 0x313fd68f, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "fy001001.102", 0x080000, 0xa0f61f13, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "fy001006.200", 0x200000, 0xe9ae99f7, 0x03 | BRF_GRA }, // 4 Sprites + + { "fy001008.66", 0x200000, 0x73d7b0e1, 0x04 | BRF_GRA }, // 5 Layer 1 tiles + { "fy001007.65", 0x100000, 0xb2fc2c81, 0x1c | BRF_GRA }, // 6 + + { "fy001010.68", 0x200000, 0x8b40ed7a, 0x05 | BRF_GRA }, // 7 Layer 2 tiles + { "fy001009.67", 0x100000, 0x6bcca641, 0x1d | BRF_GRA }, // 8 + + { "fy001012.b", 0x200000, 0xfd30e102, 0x06 | BRF_SND }, // 9 x1-010 Samples + { "fy001011.a", 0x200000, 0xe3c431de, 0x06 | BRF_SND }, // 10 +}; + +STD_ROM_PICK(zombraid) +STD_ROM_FN(zombraid) + +static INT32 zombraidInit() +{ + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x200, 0xa00); + + INT32 nRet = DrvInit(zombraid68kInit, 16000000, SET_IRQLINES(2, 4), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 3)); + + if (nRet == 0) { + gundharaSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvZombraid = { + "zombraid", NULL, NULL, NULL, "1995", + "Zombie Raid (US)\0", NULL, "American Sammy", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, zombraidRomInfo, zombraidRomName, NULL, NULL, ZombraidInputInfo, ZombraidDIPInfo, + zombraidInit, DrvExit, DrvFrame, zombraidDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// Gundhara + +static struct BurnRomInfo gundharaRomDesc[] = { + { "bpgh-003.u3", 0x080000, 0x14e9970a, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bpgh-004.u4", 0x080000, 0x96dfc658, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "bpgh-002.103", 0x080000, 0x312f58e2, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "bpgh-001.102", 0x080000, 0x8d23a23c, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "bpgh-008.u64", 0x200000, 0x7ed9d272, 0x03 | BRF_GRA }, // 4 Sprites + { "bpgh-006.201", 0x200000, 0x5a81411d, 0x03 | BRF_GRA }, // 5 + { "bpgh-007.u63", 0x200000, 0xaa49ce7b, 0x03 | BRF_GRA }, // 6 + { "bpgh-005.200", 0x200000, 0x74138266, 0x03 | BRF_GRA }, // 7 + + { "bpgh-010.u66", 0x100000, 0xb742f0b8, 0x04 | BRF_GRA }, // 8 Layer 1 tiles + { "bpgh-009.u65", 0x080000, 0xb768e666, 0x1c | BRF_GRA }, // 9 + + { "bpgh-012.u68", 0x200000, 0xedfda595, 0x05 | BRF_GRA }, // 10 Layer 2 tiles + { "bpgh-011.u67", 0x100000, 0x49aff270, 0x1d | BRF_GRA }, // 11 + + { "bpgh-013.u70", 0x100000, 0x0fa5d503, 0x06 | BRF_SND }, // 12 x1-010 Samples +}; + +STD_ROM_PICK(gundhara) +STD_ROM_FN(gundhara) + +static void gundhara68kInit() +{ + wrofaero68kInit(); + + memmove (DrvSndROM + 0x100000, DrvSndROM + 0x080000, 0x080000); + memmove (DrvSndROM + 0x000000, DrvSndROM + 0x080000, 0x100000); +} + +static INT32 gundharaInit() +{ + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x200, 0xa00); + + INT32 nRet = DrvInit(gundhara68kInit, 16000000, SET_IRQLINES(2, 4), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 3)); + + if (nRet == 0) { + gundharaSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvGundhara = { + "gundhara", NULL, NULL, NULL, "1995", + "Gundhara\0", NULL, "Banpresto", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, gundharaRomInfo, gundharaRomName, NULL, NULL, GundharaInputInfo, GundharaDIPInfo, + gundharaInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 240, 384, 3, 4 +}; + + +// Blandia + +static struct BurnRomInfo blandiaRomDesc[] = { + { "ux001001.003", 0x040000, 0x2376a1f3, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ux001002.004", 0x040000, 0xb915e172, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ux001003.202", 0x100000, 0x98052c63, 0x01 | BRF_PRG | BRF_ESS }, // 2 + + { "ux001008.064", 0x100000, 0x413647b6, 0x03 | BRF_GRA }, // 6 + { "ux001007.201", 0x100000, 0x4440fdd1, 0x03 | BRF_GRA }, // 4 + { "ux001006.063", 0x100000, 0xabc01cf7, 0x03 | BRF_GRA }, // 5 + { "ux001005.200", 0x100000, 0xbea0c4a5, 0x03 | BRF_GRA }, // 3 Sprites + + { "ux001009.065", 0x080000, 0xbc6f6aea, 0x04 | BRF_GRA }, // 7 Layer 1 tiles + { "ux001010.066", 0x080000, 0xbd7f7614, 0x04 | BRF_GRA }, // 8 + + { "ux001011.067", 0x080000, 0x5efe0397, 0x05 | BRF_GRA }, // 9 Layer 2 tiles + { "ux001012.068", 0x080000, 0xf29959f6, 0x05 | BRF_GRA }, // 10 + + { "ux001013.069", 0x100000, 0x5cd273cd, 0x06 | BRF_SND }, // 11 x1-010 Samples + { "ux001014.070", 0x080000, 0x86b49b4e, 0x06 | BRF_SND }, // 12 +}; + +STD_ROM_PICK(blandia) +STD_ROM_FN(blandia) + +static INT32 blandiaInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0xa00, 0x200); + + INT32 nRet = DrvInit(blandia68kInit, 16000000, SET_IRQLINES(2, 4), SPRITE_BUFFER, SET_GFX_DECODE(0, 4, 4)); + + if (nRet == 0) { + blandiaSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvBlandia = { + "blandia", NULL, NULL, NULL, "1992", + "Blandia\0", NULL, "Allumer", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, blandiaRomInfo, blandiaRomName, NULL, NULL, BlandiaInputInfo, BlandiaDIPInfo, + blandiaInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// Blandia (prototype) + +static struct BurnRomInfo blandiapRomDesc[] = { + { "prg-even.bin", 0x40000, 0x7ecd30e8, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "prg-odd.bin", 0x40000, 0x42b86c15, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "tbl0.bin", 0x80000, 0x69b79eb8, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "tbl1.bin", 0x80000, 0xcf2fd350, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "o-1.bin", 0x80000, 0x4c67b7f0, 0x0b | BRF_GRA }, // 4 Sprites + { "o-0.bin", 0x80000, 0x5e7b8555, 0x0b | BRF_GRA }, // 5 + { "o-5.bin", 0x80000, 0x40bee78b, 0x0b | BRF_GRA }, // 6 + { "o-4.bin", 0x80000, 0x7c634784, 0x0b | BRF_GRA }, // 7 + { "o-3.bin", 0x80000, 0x387fc7c4, 0x0b | BRF_GRA }, // 8 + { "o-2.bin", 0x80000, 0xc669bb49, 0x0b | BRF_GRA }, // 9 + { "o-7.bin", 0x80000, 0xfc77b04a, 0x0b | BRF_GRA }, // 10 + { "o-6.bin", 0x80000, 0x92882943, 0x0b | BRF_GRA }, // 11 + + { "v1-2.bin", 0x20000, 0xd524735e, 0x04 | BRF_GRA }, // 12 Layer 1 tiles + { "v1-5.bin", 0x20000, 0xeb440cdb, 0x04 | BRF_GRA }, // 13 + { "v1-1.bin", 0x20000, 0x09bdf75f, 0x04 | BRF_GRA }, // 14 + { "v1-4.bin", 0x20000, 0x803911e5, 0x04 | BRF_GRA }, // 15 + { "v1-0.bin", 0x20000, 0x73617548, 0x04 | BRF_GRA }, // 16 + { "v1-3.bin", 0x20000, 0x7f18e4fb, 0x04 | BRF_GRA }, // 17 + + { "v2-2.bin", 0x20000, 0xc4f15638, 0x05 | BRF_GRA }, // 18 Layer 2 tiles + { "v2-5.bin", 0x20000, 0xc2e57622, 0x05 | BRF_GRA }, // 19 + { "v2-1.bin", 0x20000, 0xc4f15638, 0x05 | BRF_GRA }, // 20 + { "v2-4.bin", 0x20000, 0x16ec2130, 0x05 | BRF_GRA }, // 21 + { "v2-0.bin", 0x20000, 0x5b05eba9, 0x05 | BRF_GRA }, // 22 + { "v2-3.bin", 0x20000, 0x80ad0c3b, 0x05 | BRF_GRA }, // 23 + + { "s-0.bin", 0x40000, 0xa5fde408, 0x06 | BRF_SND }, // 24 x1-010 Samples + { "s-1.bin", 0x40000, 0x3083f9c4, 0x06 | BRF_SND }, // 25 + { "s-2.bin", 0x40000, 0xa591c9ef, 0x06 | BRF_SND }, // 26 + { "s-3.bin", 0x40000, 0x68826c9d, 0x06 | BRF_SND }, // 27 + { "s-4.bin", 0x40000, 0x1c7dc8c2, 0x06 | BRF_SND }, // 28 + { "s-5.bin", 0x40000, 0x4bb0146a, 0x06 | BRF_SND }, // 29 + { "s-6.bin", 0x40000, 0x9f8f34ee, 0x06 | BRF_SND }, // 30 + { "s-7.bin", 0x40000, 0xe077dd39, 0x06 | BRF_SND }, // 31 +}; + +STD_ROM_PICK(blandiap) +STD_ROM_FN(blandiap) + +static INT32 blandiapInit() +{ + DrvSetVideoOffsets(0, 8, -2, 6); + DrvSetColorOffsets(0, 0xa00, 0x200); + + INT32 nRet = DrvInit(blandiap68kInit, 16000000, SET_IRQLINES(2, 4), SPRITE_BUFFER, SET_GFX_DECODE(0, 4, 4)); + + if (nRet == 0) { + blandiaSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvBlandiap = { + "blandiap", "blandia", NULL, NULL, "1992", + "Blandia (prototype)\0", NULL, "Allumer", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, blandiapRomInfo, blandiapRomName, NULL, NULL, BlandiaInputInfo, BlandiaDIPInfo, + blandiapInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// Oishii Puzzle Ha Irimasenka + +static struct BurnRomInfo oisipuzlRomDesc[] = { + { "ss1u200.v10", 0x80000, 0xf5e53baf, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ss1u201.v10", 0x80000, 0x7a7ff5ae, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "ss1u306.v10", 0x80000, 0xce43a754, 0x03 | BRF_GRA }, // 2 Sprites + { "ss1u307.v10", 0x80000, 0x2170b7ec, 0x03 | BRF_GRA }, // 3 + { "ss1u304.v10", 0x80000, 0x546ab541, 0x03 | BRF_GRA }, // 4 + { "ss1u305.v10", 0x80000, 0x2a33e08b, 0x03 | BRF_GRA }, // 5 + + { "ss1u23.v10", 0x80000, 0x9fa60901, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "ss1u24.v10", 0x80000, 0xc10eb4b3, 0x04 | BRF_GRA }, // 7 + + { "ss1u25.v10", 0x80000, 0x56840728, 0x05 | BRF_GRA }, // 8 Layer 2 tiles + + { "ss1u26.v10", 0x80000, 0xd452336b, 0x06 | BRF_SND }, // 9 x1-010 Samples + { "ss1u27.v10", 0x80000, 0x17fe921d, 0x06 | BRF_SND }, // 10 +}; + +STD_ROM_PICK(oisipuzl) +STD_ROM_FN(oisipuzl) + +static INT32 oisipuzlInit() +{ + oisipuzl_hack = 1; // 32 pixel offset for sprites??? + watchdog_enable = 1; // needs a reset before it will boot + + DrvSetVideoOffsets(2, 2, -1, -1); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(oisipuzl68kInit, 16000000, (2 << 8) | (1 << 0), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); + + if (nRet == 0) + { + memset (Drv68KROM, 0, 0x200000); + + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + if (BurnLoadRom(Drv68KROM + 0x100000, 1, 1)) return 1; + + for (INT32 i = 0; i < 0x400000; i++) DrvGfxROM0[i] ^= 0x0f; // invert + } + + return nRet; +} + +struct BurnDriver BurnDrvOisipuzl = { + "oisipuzl", NULL, NULL, NULL, "1993", + "Oishii Puzzle Ha Irimasenka\0", NULL, "Sunsoft + Atlus", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, oisipuzlRomInfo, oisipuzlRomName, NULL, NULL, OisipuzlInputInfo, OisipuzlDIPInfo, + oisipuzlInit, DrvExit, DrvFrame, seta2layerFlippedDraw, DrvScan, &DrvRecalc, 0x600, + 320, 224, 4, 3 +}; + + +// Triple Fun + +static struct BurnRomInfo triplfunRomDesc[] = { + { "05.bin", 0x80000, 0x06eb3821, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "04.bin", 0x80000, 0x37a5c46e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "09.bin", 0x80000, 0x98cc8ca5, 0x0b | BRF_GRA }, // 2 Sprites + { "08.bin", 0x80000, 0x63a8f10f, 0x0b | BRF_GRA }, // 3 + { "11.bin", 0x80000, 0x276ef724, 0x0b | BRF_GRA }, // 4 + { "10.bin", 0x80000, 0x20b0f282, 0x0b | BRF_GRA }, // 5 + + { "02.bin", 0x80000, 0x4c0d1068, 0x0c | BRF_GRA }, // 6 Layer 1 tiles + { "03.bin", 0x80000, 0xdba94e18, 0x0c | BRF_GRA }, // 7 + + { "06.bin", 0x40000, 0x8944bb72, 0x0d | BRF_GRA }, // 8 Layer 2 tiles + { "07.bin", 0x40000, 0x934a5d91, 0x0d | BRF_GRA }, // 9 + + { "01.bin", 0x40000, 0xc186a930, 0x06 | BRF_SND }, // 10 OKI M6295 Samples +}; + +STD_ROM_PICK(triplfun) +STD_ROM_FN(triplfun) + +static INT32 triplfunInit() +{ + oisipuzl_hack = 1; + DrvSetVideoOffsets(0, 0, -1, -1); + DrvSetColorOffsets(0, 0x400, 0x200); + + return DrvInit(triplfun68kInit, 16000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); +} + +struct BurnDriver BurnDrvTriplfun = { + "triplfun", "oisipuzl", NULL, NULL, "1993", + "Triple Fun\0", NULL, "bootleg", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, triplfunRomInfo, triplfunRomName, NULL, NULL, OisipuzlInputInfo, OisipuzlDIPInfo, + triplfunInit, DrvExit, DrvM6295Frame, seta2layerFlippedDraw, DrvScan, &DrvRecalc, 0x600, + 320, 224, 4, 3 +}; + + +// Pairs Love + +static struct BurnRomInfo pairloveRomDesc[] = { + { "ut2-001-001.1a", 0x10000, 0x083338b7, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ut2-001-002.3a", 0x10000, 0x39d88aae, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "ut2-001-004.5j", 0x80000, 0xfdc47b26, 0x03 | BRF_GRA }, // 2 Sprites + { "ut2-001-005.5l", 0x80000, 0x076f94a2, 0x03 | BRF_GRA }, // 3 + + { "ut2-001-003.12a", 0x80000, 0x900219a9, 0x06 | BRF_SND }, // 4 x1-010 Samples +}; + +STD_ROM_PICK(pairlove) +STD_ROM_FN(pairlove) + +static INT32 pairloveInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + INT32 nRet = DrvInit(pairlove68kInit, 8000000, SET_IRQLINES(2, 1), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); + + if (nRet == 0) { + memcpy (DrvSndROM + 0x80000, DrvSndROM, 0x80000); + } + + return nRet; +} + +struct BurnDriver BurnDrvPairlove = { + "pairlove", NULL, NULL, NULL, "1991", + "Pairs Love\0", NULL, "Athena", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, pairloveRomInfo, pairloveRomName, NULL, NULL, PairloveInputInfo, PairloveDIPInfo, + pairloveInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Orbs (10/7/94 prototype?) + +static struct BurnRomInfo orbsRomDesc[] = { + { "orbs.u10", 0x80000, 0x10f079c8, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "orbs.u9", 0x80000, 0xf269d16f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "orbs.u14", 0x80000, 0x1cc76541, 0x03 | BRF_GRA }, // 2 Sprites + { "orbs.u13", 0x80000, 0x784bdc1a, 0x03 | BRF_GRA }, // 3 + { "orbs.u12", 0x80000, 0xb8c352c2, 0x03 | BRF_GRA }, // 4 + { "orbs.u11", 0x80000, 0x58cb38ba, 0x03 | BRF_GRA }, // 5 + + { "orbs.u15", 0x80000, 0xbc0e9fe3, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "orbs.u16", 0x80000, 0xaecd8373, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(orbs) +STD_ROM_FN(orbs) + +static INT32 orbsInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(pairlove68kInit, 7159090, SET_IRQLINES(2, 1), NO_SPRITE_BUFFER, SET_GFX_DECODE(5, -1, -1)); +} + +struct BurnDriver BurnDrvOrbs = { + "orbs", NULL, NULL, NULL, "1994", + "Orbs (10/7/94 prototype?)\0", NULL, "American Sammy", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, orbsRomInfo, orbsRomName, NULL, NULL, OrbsInputInfo, OrbsDIPInfo, + orbsInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// Kero Kero Keroppi no Issyoni Asobou (Japan) + +static struct BurnRomInfo keroppiRomDesc[] = { + { "ft-001-001.u10", 0x80000, 0x37861e7d, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ft-001-002.u9", 0x80000, 0xf531d4ef, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "ft-001-003.u14", 0x80000, 0x62fb22fb, 0x03 | BRF_GRA }, // 2 Sprites + { "ft-001-004.u13", 0x80000, 0x69908c98, 0x03 | BRF_GRA }, // 3 + { "ft-001-005.u12", 0x80000, 0xde6432a8, 0x03 | BRF_GRA }, // 4 + { "ft-001-006.u11", 0x80000, 0x9c500eae, 0x03 | BRF_GRA }, // 5 + + { "ft-001-007.u15", 0x80000, 0xc98dacf0, 0x06 | BRF_SND }, // 6 x1-010 Samples + { "ft-001-008.u16", 0x80000, 0xb9c4b637, 0x06 | BRF_SND }, // 7 +}; + +STD_ROM_PICK(keroppi) +STD_ROM_FN(keroppi) + +struct BurnDriver BurnDrvKeroppi = { + "keroppi", NULL, NULL, NULL, "1993", + "Kero Kero Keroppi no Issyoni Asobou (Japan)\0", NULL, "Sammy Industries", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, keroppiRomInfo, keroppiRomName, NULL, NULL, KeroppiInputInfo, KeroppiDIPInfo, + orbsInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 320, 240, 4, 3 +}; + + +// J. J. Squawkers + +static struct BurnRomInfo jjsquawkRomDesc[] = { + { "jj-rom1.040", 0x80000, 0x7b9af960, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "jj-rom2.040", 0x80000, 0x47dd71a3, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "jj-rom9", 0x80000, 0x27441cd3, 0x03 | BRF_GRA }, // 2 Sprites + { "jj-rom10", 0x80000, 0xca2b42c4, 0x03 | BRF_GRA }, // 3 + { "jj-rom7", 0x80000, 0x62c45658, 0x03 | BRF_GRA }, // 4 + { "jj-rom8", 0x80000, 0x2690c57b, 0x03 | BRF_GRA }, // 5 + + { "jj-rom11", 0x80000, 0x98b9f4b4, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "jj-rom12", 0x80000, 0xd4aa916c, 0x04 | BRF_GRA }, // 7 + { "jj-rom3.040", 0x80000, 0xa5a35caf, 0x1c | BRF_GRA }, // 8 + + { "jj-rom14", 0x80000, 0x274bbb48, 0x05 | BRF_GRA }, // 9 Layer 2 tiles + { "jj-rom13", 0x80000, 0x51e29871, 0x05 | BRF_GRA }, // 10 + { "jj-rom4.040", 0x80000, 0xa235488e, 0x1d | BRF_GRA }, // 11 + + { "jj-rom5.040", 0x80000, 0xd99f2879, 0x06 | BRF_SND }, // 12 x1-010 Samples + { "jj-rom6.040", 0x80000, 0x9df1e478, 0x06 | BRF_SND }, // 13 +}; + +STD_ROM_PICK(jjsquawk) +STD_ROM_FN(jjsquawk) + +static INT32 jjsquawkInit() +{ + DrvSetVideoOffsets(1, 1, -1, -1); + DrvSetColorOffsets(0, 0x200, 0xa00); + + INT32 nRet = DrvInit(wrofaero68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 3)); + + if (nRet == 0) { + jjsquawkSetColorTable(); + + memcpy (Drv68KROM + 0x100000, Drv68KROM + 0x080000, 0x080000); + memset (Drv68KROM + 0x080000, 0, 0x080000); + } + + return nRet; +} + +struct BurnDriver BurnDrvJjsquawk = { + "jjsquawk", NULL, NULL, NULL, "1993", + "J. J. Squawkers\0", NULL, "Athena / Able", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, jjsquawkRomInfo, jjsquawkRomName, NULL, NULL, JjsquawkInputInfo, JjsquawkDIPInfo, + jjsquawkInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// J. J. Squawkers (bootleg, Blandia conversion) + +static struct BurnRomInfo jjsquawkb2RomDesc[] = { + { "u3.3a", 0x080000, 0xf94c913b, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "u4.4a", 0x080000, 0x0227a2be, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "u64.3l", 0x100000, 0x11d8713a, 0x03 | BRF_GRA }, // 2 Sprites // jj-rom9 + jj-rom10 from jjsquawk + { "u63.2l", 0x100000, 0x7a385ef0, 0x03 | BRF_GRA }, // 3 // jj-rom7 + jj-rom8 from jjsquawk + + { "u66.5l", 0x100000, 0xbbaf40c5, 0x04 | BRF_GRA }, // 4 Layer 1 tiles // jj-rom11 + jj-rom12 from jjsquawk + { "u65.4l", 0x080000, 0xa5a35caf, 0x1c | BRF_GRA }, // 5 // jj-rom3.040 from jjsquawk + + { "u68.7l", 0x100000, 0xae9ae01f, 0x05 | BRF_GRA }, // 9 Layer 2 tiles // jj-rom14 + jj-rom13 from jjsquawk + { "u67.6l", 0x080000, 0xa235488e, 0x1d | BRF_GRA }, // 10 // jj-rom4.040 from jjsquawk + + { "u70.10l", 0x100000, 0x181a55b8, 0x06 | BRF_SND }, // 11 x1-010 Samples // jj-rom5.040 + jj-rom6.040 from jjsquawk +}; + +STD_ROM_PICK(jjsquawkb2) +STD_ROM_FN(jjsquawkb2) + +struct BurnDriver BurnDrvJjsquawkb2 = { + "jjsquawkb2", "jjsquawk", NULL, NULL, "1993", + "J. J. Squawkers (bootleg, Blandia conversion)\0", NULL, "Athena / Able", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, jjsquawkb2RomInfo, jjsquawkb2RomName, NULL, NULL, JjsquawkInputInfo, JjsquawkDIPInfo, + jjsquawkInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// J. J. Squawkers (bootleg) + +static struct BurnRomInfo jjsquawkbRomDesc[] = { + { "3", 0x080000, 0xafd5bd07, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2", 0x080000, 0x740a7366, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "4.bin", 0x200000, 0x969502f7, 0x03 | BRF_GRA }, // 2 Sprites + { "2.bin", 0x200000, 0x765253d1, 0x03 | BRF_GRA }, // 3 + + { "3.bin", 0x200000, 0xb1e3a4bb, 0x04 | BRF_GRA }, // 4 Layer 1 tiles + { "1.bin", 0x200000, 0xa5d37cf7, 0x04 | BRF_GRA }, // 5 + + { "1", 0x100000, 0x181a55b8, 0x06 | BRF_SND }, // 6 x1-010 Samples +}; + +STD_ROM_PICK(jjsquawkb) +STD_ROM_FN(jjsquawkb) + +static INT32 jjsquawkbInit() +{ + DrvSetVideoOffsets(1, 1, -1, -1); + DrvSetColorOffsets(0, 0x200, 0xa00); + + INT32 nRet = DrvInit(jjsquawkb68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 3)); + + if (nRet == 0) { + jjsquawkSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvJjsquawkb = { + "jjsquawkb", "jjsquawk", NULL, NULL, "1993", + "J. J. Squawkers (bootleg)\0", NULL, "bootleg", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, jjsquawkbRomInfo, jjsquawkbRomName, NULL, NULL, JjsquawkInputInfo, JjsquawkDIPInfo, + jjsquawkbInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 240, 4, 3 +}; + + +// Extreme Downhill (v1.5) + +static struct BurnRomInfo extdwnhlRomDesc[] = { + { "fw001002.201", 0x080000, 0x24d21924, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fw001001.200", 0x080000, 0xfb12a28b, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fw001003.202", 0x200000, 0xac9b31d5, 0x03 | BRF_GRA }, // 2 Sprites + + { "fw001004.206", 0x200000, 0x0dcb1d72, 0x04 | BRF_GRA }, // 3 Layer 1 tiles + { "fw001005.205", 0x100000, 0x5c33b2f1, 0x1c | BRF_GRA }, // 4 + + { "fw001006.152", 0x200000, 0xd00e8ddd, 0x05 | BRF_GRA }, // 5 Layer 2 tiles + + { "fw001007.026", 0x100000, 0x16d84d7a, 0x06 | BRF_SND }, // 6 x1-010 Samples +}; + +STD_ROM_PICK(extdwnhl) +STD_ROM_FN(extdwnhl) + +static INT32 extdwnhlInit() +{ + watchdog_enable = 1; + + DrvSetVideoOffsets(0, 0, -2, -2); + DrvSetColorOffsets(0, 0x400, 0x200); + + INT32 nRet = DrvInit(extdwnhl68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 3, 2)); + + if (nRet == 0) { + zingzapSetColorTable(); + if (DrvGfxTransMask[2] == NULL) { + DrvGfxTransMask[2] = DrvGfxTransMask[1]; // sokonuke fix + bprintf (0, _T("null\n")); + } + } + + return nRet; +} + +struct BurnDriver BurnDrvExtdwnhl = { + "extdwnhl", NULL, NULL, NULL, "1995", + "Extreme Downhill (v1.5)\0", NULL, "Sammy Industries Japan", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, extdwnhlRomInfo, extdwnhlRomName, NULL, NULL, ExtdwnhlInputInfo, ExtdwnhlDIPInfo, + extdwnhlInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 320, 240, 4, 3 +}; + + +// Sokonuke Taisen Game (Japan) + +static struct BurnRomInfo sokonukeRomDesc[] = { + { "001-001.bin", 0x080000, 0x9d0aa3ca, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "001-002.bin", 0x080000, 0x96f2ef5f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "001-003.bin", 0x200000, 0xab9ba897, 0x03 | BRF_GRA }, // 2 Sprites + + { "001-004.bin", 0x100000, 0x34ca3540, 0x04 | BRF_GRA }, // 3 Layer 1 tiles + { "001-005.bin", 0x080000, 0x2b95d68d, 0x1c | BRF_GRA }, // 4 + + { "001-006.bin", 0x100000, 0xecfac767, 0x06 | BRF_SND }, // 5 x1-010 Samples +}; + +STD_ROM_PICK(sokonuke) +STD_ROM_FN(sokonuke) + +struct BurnDriver BurnDrvSokonuke = { + "sokonuke", NULL, NULL, NULL, "1995", + "Sokonuke Taisen Game (Japan)\0", NULL, "Sammy Industries", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, sokonukeRomInfo, sokonukeRomName, NULL, NULL, SokonukeInputInfo, SokonukeDIPInfo, + extdwnhlInit, DrvExit, DrvFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 320, 240, 4, 3 +}; + + +// Krazy Bowl + +static struct BurnRomInfo krzybowlRomDesc[] = { + { "fv001.002", 0x40000, 0x8c03c75f, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fv001.001", 0x40000, 0xf0630beb, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fv001.003", 0x80000, 0x7de22749, 0x03 | BRF_GRA }, // 2 Sprites + { "fv001.004", 0x80000, 0xc7d2fe32, 0x03 | BRF_GRA }, // 3 + + { "fv001.005", 0x80000, 0x5e206062, 0x06 | BRF_SND }, // 4 x1-010 Samples + { "fv001.006", 0x80000, 0x572a15e7, 0x06 | BRF_SND }, // 5 +}; + +STD_ROM_PICK(krzybowl) +STD_ROM_FN(krzybowl) + +static INT32 krzybowlInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(krzybowl68kInit, 16000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriverD BurnDrvKrzybowl = { + "krzybowl", NULL, NULL, NULL, "1994", + "Krazy Bowl\0", NULL, "American Sammy", "Seta", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, krzybowlRomInfo, krzybowlRomName, NULL, NULL, KrzybowlInputInfo, KrzybowlDIPInfo, + krzybowlInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 320, 3, 4 +}; + + +// Wiggie Waggie + +static struct BurnRomInfo wiggieRomDesc[] = { + { "wiggie.e19", 0x10000, 0x24b58f16, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "wiggie.e21", 0x10000, 0x83ba6edb, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "wiggie.a5", 0x10000, 0x8078d77b, 0x02 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "wiggie.j16", 0x20000, 0x4fb40b8a, 0x03 | BRF_GRA }, // 3 Sprites + { "wiggie.j18", 0x20000, 0xebc418e9, 0x03 | BRF_GRA }, // 4 + { "wiggie.j20", 0x20000, 0xc073501b, 0x03 | BRF_GRA }, // 5 + { "wiggie.j21", 0x20000, 0x22f6fa39, 0x03 | BRF_GRA }, // 6 + + { "wiggie.d1", 0x40000, 0x27fbe12a, 0x06 | BRF_SND }, // 7 OKI M6295 Samples +}; + +STD_ROM_PICK(wiggie) +STD_ROM_FN(wiggie) + +static INT32 wiggieInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(wiggie68kInit, 16000000 / 2, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(6, -1, -1)); +} + +struct BurnDriver BurnDrvWiggie = { + "wiggie", NULL, NULL, NULL, "1994", + "Wiggie Waggie\0", NULL, "Promat", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, wiggieRomInfo, wiggieRomName, NULL, NULL, ThunderlInputInfo, ThunderlDIPInfo, + wiggieInit, DrvExit, DrvZ80M6295Frame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Super Bar + +static struct BurnRomInfo superbarRomDesc[] = { + { "promat_512-1.e19", 0x10000, 0xcc7f9e87, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "promat_512-2.e21", 0x10000, 0x5e8c7231, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "promat.a5", 0x10000, 0x8078d77b, 0x02 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "promat_1m-4.j16", 0x20000, 0x43dbc99f, 0x03 | BRF_GRA }, // 3 Sprites + { "promat_1m-5.j18", 0x20000, 0xc09344b0, 0x03 | BRF_GRA }, // 4 + { "promat_1m-6.j20", 0x20000, 0x7d83f8ba, 0x03 | BRF_GRA }, // 5 + { "promat_1m-7.j21", 0x20000, 0x734df92a, 0x03 | BRF_GRA }, // 6 + + { "promat_2m-1.d1", 0x40000, 0x27fbe12a, 0x06 | BRF_SND }, // 7 OKI M6295 Samples +}; + +STD_ROM_PICK(superbar) +STD_ROM_FN(superbar) + +static INT32 superbarInit() +{ + DrvSetVideoOffsets(0, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(wiggie68kInit, 8000000, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(7, -1, -1)); +} + +struct BurnDriver BurnDrvSuperbar = { + "superbar", "wiggie", NULL, NULL, "1994", + "Super Bar\0", NULL, "Promat", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, superbarRomInfo, superbarRomName, NULL, NULL, ThunderlInputInfo, ThunderlDIPInfo, + superbarInit, DrvExit, DrvZ80M6295Frame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Ultra Toukon Densetsu (Japan) + +static struct BurnRomInfo utoukondRomDesc[] = { + { "93uta010.3", 0x080000, 0xc486ef5e, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "93uta011.4", 0x080000, 0x978978f7, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "93uta009.112", 0x010000, 0x67f18483, 0x02 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "93uta04.64", 0x100000, 0x9cba0538, 0x03 | BRF_GRA }, // 3 Sprites + { "93uta02.201", 0x100000, 0x884fedfa, 0x03 | BRF_GRA }, // 4 + { "93uta03.63", 0x100000, 0x818484a5, 0x03 | BRF_GRA }, // 5 + { "93uta01.200", 0x100000, 0x364de841, 0x03 | BRF_GRA }, // 6 + + { "93uta05.66", 0x100000, 0x5e640bfb, 0x04 | BRF_GRA }, // 7 Layer 1 tiles + + { "93uta07.68", 0x100000, 0x67bdd036, 0x05 | BRF_GRA }, // 8 Layer 2 tiles + { "93uta06.67", 0x100000, 0x294c26e4, 0x05 | BRF_GRA }, // 9 + + { "93uta08.69", 0x100000, 0x3d50bbcd, 0x06 | BRF_SND }, // 10 x1-010 Samples +}; + +STD_ROM_PICK(utoukond) +STD_ROM_FN(utoukond) + +static INT32 utoukondInit() +{ + DrvSetVideoOffsets(0, 0, -2, 0); + DrvSetColorOffsets(0, 0x400, 0x200); + + return DrvInit(utoukond68kInit, 16000000, SET_IRQLINES(2, 1), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 2, 2)); +} + +struct BurnDriver BurnDrvUtoukond = { + "utoukond", NULL, NULL, NULL, "1993", + "Ultra Toukon Densetsu (Japan)\0", "No sound", "Banpresto + Tsuburaya Prod.", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, utoukondRomInfo, utoukondRomName, NULL, NULL, UtoukondInputInfo, UtoukondDIPInfo, + utoukondInit, DrvExit, Drv68kZ80YM3438Frame, seta2layerDraw, DrvScan, &DrvRecalc, 0x600, + 384, 224, 4, 3 +}; + + +// DownTown / Mokugeki (Set 1) + +static struct BurnRomInfo downtownRomDesc[] = { + { "ud2001.000", 0x40000, 0xf1965260, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ud2001.003", 0x40000, 0xe7d5fa5f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ud2001.002", 0x10000, 0xa300e3ac, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ud2001.001", 0x10000, 0xd2918094, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ud2002.004", 0x40000, 0xbbd538b1, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ud2005.t01", 0x80000, 0x77e6d249, 0x0b | BRF_GRA }, // 5 Sprites + { "ud2006.t02", 0x80000, 0x6e381bf2, 0x0b | BRF_GRA }, // 6 + { "ud2007.t03", 0x80000, 0x737b4971, 0x0b | BRF_GRA }, // 7 + { "ud2008.t04", 0x80000, 0x99b9d757, 0x0b | BRF_GRA }, // 8 + + { "ud2009.t05", 0x80000, 0xaee6c581, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "ud2010.t06", 0x80000, 0x3d399d54, 0x04 | BRF_GRA }, // 10 + + { "ud2011.t07", 0x80000, 0x9c9ff69f, 0x06 | BRF_SND }, // 11 x1-010 Samples +}; + +STD_ROM_PICK(downtown) +STD_ROM_FN(downtown) + +static INT32 downtownInit() +{ + refresh_rate = 5742; // 57.42 hz + DrvSetVideoOffsets(0, 0, -1, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(downtown68kInit, 8000000, SET_IRQLINES(1, 2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvDowntown = { + "downtown", NULL, NULL, NULL, "1989", + "DownTown / Mokugeki (Set 1)\0", "No sound, imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, downtownRomInfo, downtownRomName, NULL, NULL, DowntownInputInfo, DowntownDIPInfo, + downtownInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// DownTown / Mokugeki (Set 2) + +static struct BurnRomInfo downtown2RomDesc[] = { + { "ud2001.000", 0x40000, 0xf1965260, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ud2001.003", 0x40000, 0xe7d5fa5f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ud2000.002", 0x10000, 0xca976b24, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ud2000.001", 0x10000, 0x1708aebd, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ud2002.004", 0x40000, 0xbbd538b1, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ud2005.t01", 0x80000, 0x77e6d249, 0x0b | BRF_GRA }, // 5 Sprites + { "ud2006.t02", 0x80000, 0x6e381bf2, 0x0b | BRF_GRA }, // 6 + { "ud2007.t03", 0x80000, 0x737b4971, 0x0b | BRF_GRA }, // 7 + { "ud2008.t04", 0x80000, 0x99b9d757, 0x0b | BRF_GRA }, // 8 + + { "ud2009.t05", 0x80000, 0xaee6c581, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "ud2010.t06", 0x80000, 0x3d399d54, 0x04 | BRF_GRA }, // 10 + + { "ud2011.t07", 0x80000, 0x9c9ff69f, 0x06 | BRF_SND }, // 11 x1-010 Samples +}; + +STD_ROM_PICK(downtown2) +STD_ROM_FN(downtown2) + +struct BurnDriverD BurnDrvDowntown2 = { + "downtown2", "downtown", NULL, NULL, "1989", + "DownTown / Mokugeki (Set 2)\0", "No sound, imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, downtown2RomInfo, downtown2RomName, NULL, NULL, DowntownInputInfo, DowntownDIPInfo, + downtownInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// DownTown / Mokugeki (Joystick Hack) + +static struct BurnRomInfo downtownjRomDesc[] = { + { "ud2001.000", 0x40000, 0xf1965260, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ud2001.003", 0x40000, 0xe7d5fa5f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "u37.9a", 0x10000, 0x73047657, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "u31.8a", 0x10000, 0x6a050240, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ud2002.004", 0x40000, 0xbbd538b1, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ud2005.t01", 0x80000, 0x77e6d249, 0x0b | BRF_GRA }, // 5 Sprites + { "ud2006.t02", 0x80000, 0x6e381bf2, 0x0b | BRF_GRA }, // 6 + { "ud2007.t03", 0x80000, 0x737b4971, 0x0b | BRF_GRA }, // 7 + { "ud2008.t04", 0x80000, 0x99b9d757, 0x0b | BRF_GRA }, // 8 + + { "ud2009.t05", 0x80000, 0xaee6c581, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "ud2010.t06", 0x80000, 0x3d399d54, 0x04 | BRF_GRA }, // 10 + + { "ud2011.t07", 0x80000, 0x9c9ff69f, 0x06 | BRF_SND }, // 11 x1-010 Samples +}; + +STD_ROM_PICK(downtownj) +STD_ROM_FN(downtownj) + +struct BurnDriver BurnDrvDowntownj = { + "downtownj", "downtown", NULL, NULL, "1989", + "DownTown / Mokugeki (Joystick Hack)\0", "No sound, imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, downtownjRomInfo, downtownjRomName, NULL, NULL, DowntownInputInfo, DowntownDIPInfo, + downtownInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// DownTown / Mokugeki (prototype) + +static struct BurnRomInfo downtownpRomDesc[] = { + { "ud2001.000", 0x40000, 0xf1965260, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ud2001.003", 0x40000, 0xe7d5fa5f, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ud2_061e.bin", 0x10000, 0x251d6552, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ud2_061o.bin", 0x10000, 0x6394a7c0, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ud2002.004", 0x40000, 0xbbd538b1, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ud2005.t01", 0x80000, 0x77e6d249, 0x0b | BRF_GRA }, // 5 Sprites + { "ud2006.t02", 0x80000, 0x6e381bf2, 0x0b | BRF_GRA }, // 6 + { "ud2007.t03", 0x80000, 0x737b4971, 0x0b | BRF_GRA }, // 7 + { "ud2008.t04", 0x80000, 0x99b9d757, 0x0b | BRF_GRA }, // 8 + + { "ud2009.t05", 0x80000, 0xaee6c581, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "ud2010.t06", 0x80000, 0x3d399d54, 0x04 | BRF_GRA }, // 10 + + { "ud2011.t07", 0x80000, 0x9c9ff69f, 0x06 | BRF_SND }, // 11 x1-010 Samples +}; + +STD_ROM_PICK(downtownp) +STD_ROM_FN(downtownp) + +struct BurnDriverD BurnDrvDowntownp = { + "downtownp", "downtown", NULL, NULL, "1989", + "DownTown / Mokugeki (prototype)\0", "No sound, imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, downtownpRomInfo, downtownpRomName, NULL, NULL, DowntownInputInfo, DowntownDIPInfo, + downtownInit, DrvExit, DrvFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// Thundercade / Twin Formation + +static struct BurnRomInfo tndrcadeRomDesc[] = { + { "ua0-4.u19", 0x20000, 0x73bd63eb, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ua0-2.u17", 0x20000, 0xe96194b1, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ua0-3.u18", 0x20000, 0x0a7b1c41, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ua0-1.u16", 0x20000, 0xfa906626, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ua10-5.u24", 0x20000, 0x8eff6122, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ua0-10.u12", 0x40000, 0xaa7b6757, 0x03 | BRF_GRA }, // 5 Sprites + { "ua0-11.u13", 0x40000, 0x11eaf931, 0x03 | BRF_GRA }, // 6 + { "ua0-12.u14", 0x40000, 0x00b5381c, 0x03 | BRF_GRA }, // 7 + { "ua0-13.u15", 0x40000, 0x8f9a0ed3, 0x03 | BRF_GRA }, // 8 + { "ua0-6.u8", 0x40000, 0x14ecc7bb, 0x03 | BRF_GRA }, // 9 + { "ua0-7.u9", 0x40000, 0xff1a4e68, 0x03 | BRF_GRA }, // 10 + { "ua0-8.u10", 0x40000, 0x936e1884, 0x03 | BRF_GRA }, // 11 + { "ua0-9.u11", 0x40000, 0xe812371c, 0x03 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(tndrcade) +STD_ROM_FN(tndrcade) + +static INT32 tndrcadeInit() +{ + DrvSetVideoOffsets(-1, 0, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(tndrcade68kInit, 8000000, SET_IRQLINES(2, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, -1, -1)); +} + +struct BurnDriverD BurnDrvTndrcade = { + "tndrcade", NULL, NULL, NULL, "1987", + "Thundercade / Twin Formation\0", "No sound, imperfect inputs", "[Seta] (Taito license)", "Seta", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tndrcadeRomInfo, tndrcadeRomName, NULL, NULL, TndrcadeInputInfo, TndrcadeDIPInfo, + tndrcadeInit, DrvExit, DrvFrame /*DrvM65c02Frame*/, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// Tokusyu Butai U.A.G. (Japan) + +static struct BurnRomInfo tndrcadejRomDesc[] = { + { "ua0-4.u19", 0x20000, 0x73bd63eb, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ua0-2.u17", 0x20000, 0xe96194b1, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ua0-3.u18", 0x20000, 0x0a7b1c41, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ua0-1.u16", 0x20000, 0xfa906626, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "thcade5.u24", 0x20000, 0x8cb9df7b, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ua0-10.u12", 0x40000, 0xaa7b6757, 0x03 | BRF_GRA }, // 5 Sprites + { "ua0-11.u13", 0x40000, 0x11eaf931, 0x03 | BRF_GRA }, // 6 + { "ua0-12.u14", 0x40000, 0x00b5381c, 0x03 | BRF_GRA }, // 7 + { "ua0-13.u15", 0x40000, 0x8f9a0ed3, 0x03 | BRF_GRA }, // 8 + { "ua0-6.u8", 0x40000, 0x14ecc7bb, 0x03 | BRF_GRA }, // 9 + { "ua0-7.u9", 0x40000, 0xff1a4e68, 0x03 | BRF_GRA }, // 10 + { "ua0-8.u10", 0x40000, 0x936e1884, 0x03 | BRF_GRA }, // 11 + { "ua0-9.u11", 0x40000, 0xe812371c, 0x03 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(tndrcadej) +STD_ROM_FN(tndrcadej) + +struct BurnDriverD BurnDrvTndrcadej = { + "tndrcadej", "tndrcade", NULL, NULL, "1987", + "Tokusyu Butai U.A.G. (Japan)\0", "No sound, imperfect inputs", "[Seta] (Taito license)", "Seta", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tndrcadejRomInfo, tndrcadejRomName, NULL, NULL, TndrcadeInputInfo, TndrcadjDIPInfo, + tndrcadeInit, DrvExit, DrvFrame /*DrvM65c02Frame*/, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// Arbalester + +static struct BurnRomInfo arbalestRomDesc[] = { + { "uk001.03", 0x40000, 0xee878a2c, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uk001.04", 0x40000, 0x902bb4e3, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "uk001.05", 0x02000, 0x0339fc53, 0x02 | BRF_PRG | BRF_ESS }, // 2 M65c02 Code + + { "uk001.06", 0x40000, 0x11c75746, 0x0b | BRF_GRA }, // 3 Sprites + { "uk001.07", 0x40000, 0x01b166c7, 0x0b | BRF_GRA }, // 4 + { "uk001.08", 0x40000, 0x78d60ba3, 0x0b | BRF_GRA }, // 5 + { "uk001.09", 0x40000, 0xb4748ae0, 0x0b | BRF_GRA }, // 6 + + { "uk001.10", 0x80000, 0xc1e2f823, 0x04 | BRF_GRA }, // 7 Layer 1 tiles + { "uk001.11", 0x80000, 0x09dfe56a, 0x04 | BRF_GRA }, // 8 + { "uk001.12", 0x80000, 0x818a4085, 0x04 | BRF_GRA }, // 9 + { "uk001.13", 0x80000, 0x771fa164, 0x04 | BRF_GRA }, // 10 + + { "uk001.15", 0x80000, 0xce9df5dd, 0x06 | BRF_SND }, // 11 x1-010 Samples + { "uk001.14", 0x80000, 0x016b844a, 0x06 | BRF_SND }, // 12 +}; + +STD_ROM_PICK(arbalest) +STD_ROM_FN(arbalest) + +static INT32 arbalestInit() +{ + DrvSetVideoOffsets(0, 1, -2, -1); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(metafox68kInit, 8000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvArbalest = { + "arbalest", NULL, NULL, NULL, "1989", + "Arbalester\0", "Imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, arbalestRomInfo, arbalestRomName, NULL, NULL, MetafoxInputInfo, ArbalestDIPInfo, + arbalestInit, DrvExit, DrvFrame /*DrvM65c02Frame*/, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// Meta Fox + +static struct BurnRomInfo metafoxRomDesc[] = { + { "p1003161", 0x40000, 0x4fd6e6a1, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "p1004162", 0x40000, 0xb6356c9a, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "up001002", 0x10000, 0xce91c987, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "up001001", 0x10000, 0x0db7a505, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "up001005", 0x02000, 0x2ac5e3e3, 0x02 | BRF_PRG | BRF_ESS }, // 4 m65c02 Code + + { "p1006163", 0x40000, 0x80f69c7c, 0x0b | BRF_GRA }, // 5 Sprites + { "p1007164", 0x40000, 0xd137e1a3, 0x0b | BRF_GRA }, // 6 + { "p1008165", 0x40000, 0x57494f2b, 0x0b | BRF_GRA }, // 7 + { "p1009166", 0x40000, 0x8344afd2, 0x0b | BRF_GRA }, // 8 + + { "up001010", 0x80000, 0xbfbab472, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "up001011", 0x80000, 0x26cea381, 0x04 | BRF_GRA }, // 10 + { "up001012", 0x80000, 0xfed2c5f9, 0x04 | BRF_GRA }, // 11 + { "up001013", 0x80000, 0xadabf9ea, 0x04 | BRF_GRA }, // 12 + + { "up001015", 0x80000, 0x2e20e39f, 0x06 | BRF_SND }, // 13 x1-010 Samples + { "up001014", 0x80000, 0xfca6315e, 0x06 | BRF_SND }, // 14 +}; + +STD_ROM_PICK(metafox) +STD_ROM_FN(metafox) + +static INT32 metafoxInit() +{ + DrvSetVideoOffsets(0, 0, 16, -19); + DrvSetColorOffsets(0, 0, 0); + + INT32 nRet = DrvInit(metafox68kInit, 8000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); + + if (nRet == 0) { + *((UINT16*)(Drv68KROM + 0x8ab1c)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x8ab1e)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x8ab20)) = 0x4e71; + } + + return nRet; +} + +struct BurnDriver BurnDrvMetafox = { + "metafox", NULL, NULL, NULL, "1989", + "Meta Fox\0", "Imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, metafoxRomInfo, metafoxRomName, NULL, NULL, MetafoxInputInfo, MetafoxDIPInfo, + metafoxInit, DrvExit, DrvFrame /*DrvM65c02Frame*/, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// Pro Mahjong Kiwame + +static struct BurnRomInfo kiwameRomDesc[] = { + { "fp001001.bin", 0x40000, 0x31b17e39, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fp001002.bin", 0x40000, 0x5a6e2efb, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "fp001003.bin", 0x80000, 0x0f904421, 0x03 | BRF_GRA }, // 2 Sprites + + { "fp001006.bin", 0x80000, 0x96cf395d, 0x06 | BRF_SND }, // 3 x1-010 Samples + { "fp001005.bin", 0x80000, 0x65b5fe9a, 0x06 | BRF_SND }, // 4 +}; + +STD_ROM_PICK(kiwame) +STD_ROM_FN(kiwame) + +static INT32 kiwameInit() +{ + DrvSetVideoOffsets(0, -16, 0, 0); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(kiwame68kInit, 16000000, SET_IRQLINES(1, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriverD BurnDrvKiwame = { + "kiwame", NULL, NULL, NULL, "1994", + "Pro Mahjong Kiwame\0", NULL, "Athena", "Seta", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, kiwameRomInfo, kiwameRomName, NULL, NULL, KiwameInputInfo, KiwameDIPInfo, + kiwameInit, DrvExit, DrvFrame, setaNoLayersDraw, DrvScan, &DrvRecalc, 0x200, + 448, 240, 4, 3 +}; + + +// Twin Eagle - Revenge Joe's Brother + +static struct BurnRomInfo twineaglRomDesc[] = { + { "ua2-1", 0x80000, 0x5c3fe531, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + + { "ua2-2", 0x02000, 0x783ca84e, 0x02 | BRF_PRG | BRF_ESS }, // 1 M65c02 Code + + { "ua2-4", 0x40000, 0x8b7532d6, 0x0b | BRF_GRA }, // 2 Sprites + { "ua2-3", 0x40000, 0x1124417a, 0x0b | BRF_GRA }, // 3 + { "ua2-6", 0x40000, 0x99d8dbba, 0x0b | BRF_GRA }, // 4 + { "ua2-5", 0x40000, 0x6e450d28, 0x0b | BRF_GRA }, // 5 + + { "ua2-8", 0x80000, 0x7d3a8d73, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "ua2-10", 0x80000, 0x5bbe1f56, 0x04 | BRF_GRA }, // 7 + { "ua2-7", 0x80000, 0xfce56907, 0x04 | BRF_GRA }, // 8 + { "ua2-9", 0x80000, 0xa451eae9, 0x04 | BRF_GRA }, // 9 + + { "ua2-11", 0x80000, 0x624e6057, 0x06 | BRF_SND }, // 10 x1-010 Samples + { "ua2-12", 0x80000, 0x3068ff64, 0x06 | BRF_SND }, // 11 +}; + +STD_ROM_PICK(twineagl) +STD_ROM_FN(twineagl) + +static INT32 twineaglInit() +{ + twineagle = 1; + + DrvSetVideoOffsets(0, 0, 0, -3); + DrvSetColorOffsets(0, 0, 0); + + return DrvInit(twineagle68kInit, 8000000, SET_IRQLINES(3, NOIRQ2), NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvTwineagl = { + "twineagl", NULL, NULL, NULL, "1988", + "Twin Eagle - Revenge Joe's Brother\0", "Imperfect inputs", "Seta (Taito license)", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, twineaglRomInfo, twineaglRomName, NULL, NULL, TwineaglInputInfo, TwineaglDIPInfo, + twineaglInit, DrvExit, DrvFrame /*DrvM65c02Frame*/, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 224, 384, 3, 4 +}; + + +// U.S. Classic + +static struct BurnRomInfo usclssicRomDesc[] = { + { "ue2001.u20", 0x20000, 0x18b41421, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ue2000.u14", 0x20000, 0x69454bc2, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ue2002.u22", 0x20000, 0xa7bbe248, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "ue2003.u30", 0x20000, 0x29601906, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "ue002u61.004", 0x40000, 0x476e9f60, 0x02 | BRF_PRG | BRF_ESS }, // 4 M65c02 Code + + { "ue001009.119", 0x80000, 0xdc065204, 0x0b | BRF_GRA }, // 5 Sprites + { "ue001008.118", 0x80000, 0x5947d9b5, 0x0b | BRF_GRA }, // 6 + { "ue001007.117", 0x80000, 0xb48a885c, 0x0b | BRF_GRA }, // 7 + { "ue001006.116", 0x80000, 0xa6ab6ef4, 0x0b | BRF_GRA }, // 8 + + { "ue001010.120", 0x80000, 0xdd683031, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "ue001011.121", 0x80000, 0x0e27bc49, 0x04 | BRF_GRA }, // 10 + { "ue001012.122", 0x80000, 0x961dfcdc, 0x04 | BRF_GRA }, // 11 + { "ue001013.123", 0x80000, 0x03e9eb79, 0x04 | BRF_GRA }, // 12 + { "ue001014.124", 0x80000, 0x9576ace7, 0x04 | BRF_GRA }, // 13 + { "ue001015.125", 0x80000, 0x631d6eb1, 0x04 | BRF_GRA }, // 14 + { "ue001016.126", 0x80000, 0xf44a8686, 0x04 | BRF_GRA }, // 15 + { "ue001017.127", 0x80000, 0x7f568258, 0x04 | BRF_GRA }, // 16 + { "ue001018.128", 0x80000, 0x4bd98f23, 0x04 | BRF_GRA }, // 17 + { "ue001019.129", 0x80000, 0x6d9f5a33, 0x04 | BRF_GRA }, // 18 + { "ue001020.130", 0x80000, 0xbc07403f, 0x04 | BRF_GRA }, // 19 + { "ue001021.131", 0x80000, 0x98c03efd, 0x04 | BRF_GRA }, // 20 + + { "ue001005.132", 0x80000, 0xc5fea37c, 0x06 | BRF_SND }, // 21 x1-010 Samples + + { "ue1-023.prm", 0x00200, 0xa13192a4, 0x0f | BRF_GRA }, // 22 Color PROMs + { "ue1-022.prm", 0x00200, 0x1a23129e, 0x0f | BRF_GRA }, // 23 +}; + +STD_ROM_PICK(usclssic) +STD_ROM_FN(usclssic) + +static INT32 usclssicInit() +{ + watchdog_enable = 1; + DrvSetColorOffsets(0, 0x200, 0); + DrvSetVideoOffsets(1, 2, 0, -1); + + INT32 nRet = DrvInit(usclssic68kInit, 8000000, SET_IRQLINES(0x80, 0x80) /*custom*/, NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 4, -1)); + + if (nRet == 0) { + usclssicSetColorTable(); + } + + return nRet; +} + +struct BurnDriverD BurnDrvUsclssic = { + "usclssic", NULL, NULL, NULL, "1989", + "U.S. Classic\0", "No sound, imperfect inputs", "Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, usclssicRomInfo, usclssicRomName, NULL, NULL, UsclssicInputInfo, UsclssicDIPInfo, + usclssicInit, DrvExit, Drv5IRQFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0xa00, + 240, 384, 3, 4 +}; + + +// Caliber 50 + +static struct BurnRomInfo calibr50RomDesc[] = { + { "uh002001.u45", 0x40000, 0xeb92e7ed, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "uh002004.u41", 0x40000, 0x5a0ed31e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "uh001003.9a", 0x10000, 0x0d30d09f, 0x01 | BRF_PRG | BRF_ESS }, // 2 + { "uh001002.7a", 0x10000, 0x7aecc3f9, 0x01 | BRF_PRG | BRF_ESS }, // 3 + + { "uh001005.u61", 0x40000, 0x4a54c085, 0x02 | BRF_PRG | BRF_ESS }, // 4 m65c02 Code + + { "uh001006.ux2", 0x80000, 0xfff52f91, 0x0b | BRF_GRA }, // 5 Sprites + { "uh001007.ux1", 0x80000, 0xb6c19f71, 0x0b | BRF_GRA }, // 6 + { "uh001008.ux6", 0x80000, 0x7aae07ef, 0x0b | BRF_GRA }, // 7 + { "uh001009.ux0", 0x80000, 0xf85da2c5, 0x0b | BRF_GRA }, // 8 + + { "uh001010.u3x", 0x80000, 0xf986577a, 0x04 | BRF_GRA }, // 9 Layer 1 tiles + { "uh001011.u50", 0x80000, 0x08620052, 0x04 | BRF_GRA }, // 10 + + { "uh001013.u60", 0x80000, 0x09ec0df6, 0x06 | BRF_SND }, // 11 x1-010 Samples + { "uh001012.u46", 0x80000, 0xbb996547, 0x06 | BRF_SND }, // 12 +}; + +STD_ROM_PICK(calibr50) +STD_ROM_FN(calibr50) + +static INT32 calibr50Init() +{ + refresh_rate = 5742; // 57.42 hz + watchdog_enable = 1; + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(-1, 2, -3, -2); + + return DrvInit(calibr5068kInit, 8000000, SET_IRQLINES(0x80, 0x80) /*custom*/, NO_SPRITE_BUFFER, SET_GFX_DECODE(0, 1, -1)); +} + +struct BurnDriver BurnDrvCalibr50 = { + "calibr50", NULL, NULL, NULL, "1989", + "Caliber 50\0", "No sound, imperfect inputs", "Athena / Seta", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, calibr50RomInfo, calibr50RomName, NULL, NULL, Calibr50InputInfo, Calibr50DIPInfo, + calibr50Init, DrvExit, Drv5IRQFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 240, 384, 3, 4 +}; + + +// Crazy Fight + +static struct BurnRomInfo crazyfgtRomDesc[] = { + { "rom.u3", 0x40000, 0xbf333e75, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "rom.u4", 0x40000, 0x505e9d47, 0x01 | BRF_PRG | BRF_ESS }, // 1 + + { "rom.u228", 0x80000, 0x7181618e, 0x03 | BRF_GRA }, // 2 Sprites + { "rom.u227", 0x80000, 0x7905b5f2, 0x03 | BRF_GRA }, // 3 + { "rom.u226", 0x80000, 0xef210e34, 0x03 | BRF_GRA }, // 4 + { "rom.u225", 0x80000, 0x451b4419, 0x03 | BRF_GRA }, // 5 + + { "rom.u67", 0x40000, 0xec8c6831, 0x04 | BRF_GRA }, // 6 Layer 1 tiles + { "rom.u68", 0x80000, 0x2124312e, 0x04 | BRF_GRA }, // 7 + + { "rom.u65", 0x40000, 0x58448231, 0x05 | BRF_GRA }, // 8 Layer 2 tiles + { "rom.u66", 0x80000, 0xc6f7735b, 0x05 | BRF_GRA }, // 9 + + { "rom.u85", 0x40000, 0x7b95d0bb, 0x06 | BRF_SND }, // 10 OKI M6295 Samples +}; + +STD_ROM_PICK(crazyfgt) +STD_ROM_FN(crazyfgt) + +static INT32 crazyfgtInit() +{ + DrvSetColorOffsets(0, 0xa00, 0x200); + DrvSetVideoOffsets(6, 0, -4, 0); + + INT32 nRet = DrvInit(crazyfgt68kInit, 16000000, SET_IRQLINES(0x80, 0x80) /*custom*/, NO_SPRITE_BUFFER, SET_GFX_DECODE(5, 4, 4)); + + if (nRet == 0) { + gundharaSetColorTable(); + } + + return nRet; +} + +struct BurnDriver BurnDrvCrazyfgt = { + "crazyfgt", NULL, NULL, NULL, "1996", + "Crazy Fight\0", NULL, "Subsino", "Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, crazyfgtRomInfo, crazyfgtRomName, NULL, NULL, CrazyfgtInputInfo, CrazyfgtDIPInfo, + crazyfgtInit, DrvExit, CrazyfgtFrame, seta2layerDraw, DrvScan, &DrvRecalc, 0x1200, + 384, 224, 4, 3 +}; + + +//---------------------------------------------------------------------------------------------------------- +// should be moved into its own file + +static UINT8 msm6242_reg[3]; +static time_t msm6242_hold_time; + +UINT8 msm6242_read(UINT32 offset) +{ + tm *systime; + + if (msm6242_reg[0] & 1) { + systime = localtime(&msm6242_hold_time); + } else { + time_t curtime = time(NULL); + systime = localtime(&curtime); + } + + switch (offset) + { + case 0x00: return systime->tm_sec % 10; + case 0x01: return systime->tm_sec / 10; + case 0x02: return systime->tm_min % 10; + case 0x03: return systime->tm_min / 10; + case 0x04: + case 0x05: + { + INT32 hour = systime->tm_hour, pm = 0; + + if ((msm6242_reg[2] & 0x04) == 0) // 12 hour mode? + { + if (hour >= 12) pm = 1; + hour %= 12; + if (hour == 0) hour = 12; + } + + if (offset == 0x04) return hour % 10; + + return (hour / 10) | (pm <<2); + } + + case 0x06: return systime->tm_mday % 10; + case 0x07: return systime->tm_mday / 10; + case 0x08: return (systime->tm_mon+1) % 10; + case 0x09: return (systime->tm_mon+1) / 10; + case 0x0a: return systime->tm_year % 10; + case 0x0b: return (systime->tm_year % 100) / 10; + case 0x0c: return systime->tm_wday; + case 0x0d: return msm6242_reg[0]; + case 0x0e: return msm6242_reg[1]; + case 0x0f: return msm6242_reg[2]; + } + + return 0; +} + +void msm6242_write(UINT32 offset, UINT8 data) +{ + if (offset == 0x0d) { + msm6242_reg[0] = data & 0x0f; + if (data & 1) msm6242_hold_time = time(NULL); + } else if (offset == 0x0e) { + msm6242_reg[1] = data & 0x0f; + } else if (offset == 0x0f) { + if ((data ^ msm6242_reg[2]) & 0x04) { + msm6242_reg[2] = (msm6242_reg[2] & 0x04) | (data & ~0x04); + + if (msm6242_reg[2] & 1) msm6242_reg[2] = (msm6242_reg[2] & ~0x04) | (data & 0x04); + } else { + msm6242_reg[2] = data & 0x0f; + } + } +} + +void msm6242_reset() +{ + memset (msm6242_reg, 0, 3); + msm6242_hold_time = time(NULL); +} + +//-------------------------------------------------------------------------------------------------------------------- + +static UINT16 jockeyc_dsw_read(INT32 offset) +{ + INT32 dip2 = DrvDips[1] | (DrvDips[2] << 8); + INT32 shift = offset << 2; + + return ((((DrvDips[0] >> shift) & 0xf)) << 0) | ((((dip2 >> shift) & 0xf)) << 4) | ((((dip2 >> (shift+8)) & 0xf)) << 8); +} + +UINT16 __fastcall jockeyc_read_word(UINT32 address) +{ + switch (address) + { + case 0x200000: + case 0x200001: { + INT32 i; + for (i = 3; i < 8; i++) { + if (usclssic_port_select & (1 << i)) return DrvInputs[(i - 3) + 2]; + } + return 0xffff; + } + + case 0x200002: + case 0x200003: + return DrvInputs[0]; + + case 0x200010: + case 0x200011: + return DrvInputs[1] & 0x7fff; + + case 0x500000: + case 0x500001: + case 0x500002: + case 0x500003: + return jockeyc_dsw_read(address & 2); + + case 0x600000: + case 0x600001: + case 0x600002: + case 0x600003: + return ~0; + } + + if ((address & 0xfffffe0) == 0x800000) { + return msm6242_read((address & 0x1e) / 2); + } + + return 0; +} + +UINT8 __fastcall jockeyc_read_byte(UINT32 address) +{ + switch (address) + { + case 0x200000: + case 0x200001: { + INT32 i; + for (i = 3; i < 8; i++) { + if (usclssic_port_select & (1 << i)) return DrvInputs[(i - 3) + 2]; + } + return 0xff; + } + + case 0x200002: + return DrvInputs[0] >> 8; + + case 0x200003: + return DrvInputs[0]; + + case 0x200010: + return (DrvInputs[1] >> 8) & 0x7f; + + case 0x200011: + return DrvInputs[1]; + + case 0x500000: + case 0x500001: + case 0x500002: + case 0x500003: + return jockeyc_dsw_read(address & 2); + + case 0x600000: + case 0x600001: + case 0x600002: + case 0x600003: + return ~0; + } + + if ((address & 0xfffffe0) == 0x800000) { + return msm6242_read((address & 0x1e) / 2); + } + + return 0; +} + +void __fastcall jockeyc_write_word(UINT32 address, UINT16 data) +{ + SetaVidRAMCtrlWriteWord(0, 0xa00000) + + switch (address) + { + case 0x200000: + case 0x200001: + usclssic_port_select = data & 0xf8; + return; + + case 0x300000: + case 0x300001: + watchdog = 0; + return; + } + + if ((address & 0xfffffe0) == 0x800000) { + msm6242_write((address & 0x1e) / 2, data); + return; + } +} + +void __fastcall jockeyc_write_byte(UINT32 address, UINT8 data) +{ + SetaVidRAMCtrlWriteByte(0, 0xa00000) + + switch (address) + { + case 0x200000: + case 0x200001: + usclssic_port_select = data & 0xf8; + return; + + case 0x300000: + case 0x300001: + watchdog = 0; + return; + } + + if ((address & 0xfffffe0) == 0x800000) { + msm6242_write((address & 0x1e) / 2, data); + return; + + } +} + +static void jockeyc68kInit() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(DrvVidRAM0, 0xb00000, 0xb07fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xd00000, 0xd00607 | 0x7ff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, jockeyc_write_word); + SekSetWriteByteHandler(0, jockeyc_write_byte); + SekSetReadWordHandler(0, jockeyc_read_word); + SekSetReadByteHandler(0, jockeyc_read_byte); + + SekMapHandler(1, 0x900000, 0x903fff, SM_READ | SM_WRITE); + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + SekClose(); + + memcpy (Drv68KROM + 0x100000, Drv68KROM + 0x020000, 0x080000); + memset (Drv68KROM + 0x020000, 0xff, 0x60000); + memset (Drv68KROM + 0x180000, 0xff, 0x80000); + + memmove (DrvGfxROM1 + 0x60000, DrvGfxROM1 + 0x40000, 0x40000); + memset (DrvGfxROM1 + 0x40000, 0, 0x20000); + memset (DrvGfxROM1 + 0xa0000, 0, 0x20000); + + DrvROMLen[4] = 1; // force use of pal ram + + msm6242_reset(); +} + +static INT32 jockeycInit() +{ + watchdog_enable = 1; + DrvSetColorOffsets(0, 0, 0); + DrvSetVideoOffsets(0, 0, 0, 0); + + return DrvInit(jockeyc68kInit, 16000000, SET_IRQLINES(0x80, 0x80) /*custom*/, NO_SPRITE_BUFFER, SET_GFX_DECODE(5, 1, -1)); +} + +static void jockeycFrameCallback() +{ + DrvInputs[0] ^= 0xffff; + DrvInputs[0] ^= DrvDips[3] | (DrvDips[4] << 8); + DrvInputs[1] ^= 0xffff; + DrvInputs[1] ^= DrvDips[5] | (DrvDips[6] << 8); + + INT32 nInterleave = 10; + INT32 nCyclesTotal[1] = { cpuspeed / 60 }; + INT32 nCyclesDone[1] = { 0 }; + + INT32 irqs[10] = { 4, 1, 2, 6, 6, 6, 6, 6, 6, 6 }; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + + SekSetIRQLine(irqs[9-i], SEK_IRQSTATUS_AUTO); // ? + } + + SekClose(); + + if (pBurnSoundOut) { + x1010_sound_update(); + } +} + +static INT32 jockeycFrame() +{ + return DrvCommonFrame(jockeycFrameCallback); +} + + +// Jockey Club + +static struct BurnRomInfo jockeycRomDesc[] = { + { "ya-007-002-u23.bin", 0x10000, 0xc499bf4d, 0x01 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ya-007-003-u33.bin", 0x10000, 0xe7b0677e, 0x01 | BRF_PRG | BRF_ESS }, // 1 + { "ya_002_001.u18", 0x80000, 0xdd108016, 0x01 | BRF_PRG | BRF_ESS }, // 2 + + { "ya_011_004.u10", 0x80000, 0xeb74d2e0, 0x03 | BRF_GRA }, // 3 Sprites + { "ya_011_005.u17", 0x80000, 0x4a6c804b, 0x03 | BRF_GRA }, // 4 + { "ya_011_006.u22", 0x80000, 0xbfae01a5, 0x03 | BRF_GRA }, // 5 + { "ya_011_007.u27", 0x80000, 0x2dc7a294, 0x03 | BRF_GRA }, // 6 + + { "ya_011_008.u35", 0x40000, 0x4b890f83, 0x04 | BRF_GRA }, // 7 Layer 1 tiles + { "ya_011_009.u41", 0x40000, 0xcaa5e3c1, 0x04 | BRF_GRA }, // 8 +// double this so that we can use the graphics decoding routines... + { "ya_011_009.u41", 0x40000, 0xcaa5e3c1, 0x04 | BRF_GRA }, // 9 + + { "ya_011_013.u71", 0x80000, 0x2bccaf47, 0x06 | BRF_SND }, // 10 x1snd + { "ya_011_012.u64", 0x80000, 0xa8015ce6, 0x06 | BRF_SND }, // 11 + + { "ya-011.prom", 0x00200, 0xbd4fe2f6, 0x0f | BRF_GRA }, // 13 + { "ya-010.prom", 0x00200, 0x778094b3, 0x0f | BRF_GRA }, // 12 Color PROMs +}; + +STD_ROM_PICK(jockeyc) +STD_ROM_FN(jockeyc) + +struct BurnDriverD BurnDrvJockeyc = { + "jockeyc", NULL, NULL, NULL, "1990", + "Jockey Club\0", NULL, "[Seta] (Visco license)", "Seta", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, jockeycRomInfo, jockeycRomName, NULL, NULL, JockeycInputInfo, JockeycDIPInfo, + jockeycInit, DrvExit, jockeycFrame, seta1layerDraw, DrvScan, &DrvRecalc, 0x200, + 384, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_seta2.cpp b/src/burn/drivers/misc_post90s/d_seta2.cpp new file mode 100644 index 00000000..9f79cc66 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_seta2.cpp @@ -0,0 +1,3412 @@ +/******************************************************************************** + Newer Seta Hardware + MAME driver by Luca Elia (l.elia@tin.it) + ******************************************************************************** + port to Finalburn Alpha by OopsWare. 2007 + ********************************************************************************/ + +#include "tiles_generic.h" +#include "burn_gun.h" +#include "eeprom.h" +#include "x1010.h" + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *Rom68K; +static UINT8 *RomGfx; + +static UINT8 *Ram68K; +static UINT8 *RamUnknown; +static UINT8 *RamNV; + +static UINT16 *RamSpr; +static UINT16 *RamSprBak; +static UINT16 *RamPal; +static UINT32 *CurPal; +static UINT16 *RamTMP68301; +static UINT16 *RamVReg; + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy5[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static INT32 DrvAxis[4]; +static UINT8 DrvAnalogInput[4]; + +static UINT8 DrvReset = 0; +static UINT8 bRecalcPalette = 0; + +static UINT32 gfx_code_mask; +//static UINT8 bMahjong = 0; +static UINT8 Mahjong_keyboard = 0; +static UINT8 HasNVRam; + +static INT32 yoffset; +static INT32 sva_x; +static INT32 sva_y; + +#define M68K_CYCS 50000000 / 3 + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo grdiansInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 3, "diag"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(grdians) + +static struct BurnDIPInfo grdiansDIPList[] = { + + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x15, 0x01, 0x03, 0x01, "Easy"}, + {0x15, 0x01, 0x03, 0x00, "Normal"}, + {0x15, 0x01, 0x03, 0x02, "Hard"}, + {0x15, 0x01, 0x03, 0x03, "Hardest"}, +// {0, 0xFE, 0, 2, "Unknown"}, +// {0x15, 0x01, 0x04, 0x00, "Off"}, +// {0x15, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 2, "Title"}, + {0x15, 0x01, 0x08, 0x00, "Guardians"}, + {0x15, 0x01, 0x08, 0x08, "Denjin Makai II"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x15, 0x01, 0x30, 0x10, "1"}, + {0x15, 0x01, 0x30, 0x00, "2"}, + {0x15, 0x01, 0x30, 0x20, "3"}, + {0x15, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + + // DIP 2 + {0, 0xFE, 0, 16, "Coin 1"}, + {0x16, 0x01, 0x0f, 0x00, "1 coin 1 credit"}, + {0x16, 0x01, 0x0f, 0x01, "1 coin 2 credits"}, + {0x16, 0x01, 0x0f, 0x02, "1 coin 3 credits"}, + {0x16, 0x01, 0x0f, 0x03, "1 coin 4 credits"}, + {0x16, 0x01, 0x0f, 0x04, "1 coin 5 credits"}, + {0x16, 0x01, 0x0f, 0x05, "1 coin 6 credits"}, + {0x16, 0x01, 0x0f, 0x06, "1 coin 7 credits"}, + {0x16, 0x01, 0x0f, 0x07, "2 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x08, "2 coins 3 credits"}, + {0x16, 0x01, 0x0f, 0x09, "2 coins 5 credits"}, + {0x16, 0x01, 0x0f, 0x0a, "3 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x0b, "3 coins 2 credits"}, + {0x16, 0x01, 0x0f, 0x0c, "3 coins 4 credits"}, + {0x16, 0x01, 0x0f, 0x0d, "4 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x0e, "4 coins 3 credits"}, + {0x16, 0x01, 0x0f, 0x0f, "Free play"}, + {0, 0xFE, 0, 16, "Coin 2"}, + {0x16, 0x01, 0xf0, 0x00, "1 coin 1 credit"}, + {0x16, 0x01, 0xf0, 0x10, "1 coin 2 credits"}, + {0x16, 0x01, 0xf0, 0x20, "1 coin 3 credits"}, + {0x16, 0x01, 0xf0, 0x30, "1 coin 4 credits"}, + {0x16, 0x01, 0xf0, 0x40, "1 coin 5 credits"}, + {0x16, 0x01, 0xf0, 0x50, "1 coin 6 credits"}, + {0x16, 0x01, 0xf0, 0x60, "1 coin 7 credits"}, + {0x16, 0x01, 0xf0, 0x70, "2 coins 1 credit"}, + {0x16, 0x01, 0xf0, 0x80, "2 coins 3 credits"}, + {0x16, 0x01, 0xf0, 0x90, "2 coins 5 credits"}, + {0x16, 0x01, 0xf0, 0xa0, "3 coins 1 credit"}, + {0x16, 0x01, 0xf0, 0xb0, "3 coins 2 credits"}, + {0x16, 0x01, 0xf0, 0xc0, "3 coins 4 credits"}, + {0x16, 0x01, 0xf0, 0xd0, "4 coins 1 credit"}, + {0x16, 0x01, 0xf0, 0xe0, "4 coins 3 credits"}, + {0x16, 0x01, 0xf0, 0xf0, "Free play"}, +}; + +STDDIPINFO(grdians) + +static struct BurnInputInfo mj4simaiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + + {"A", BIT_DIGITAL, DrvJoy1 + 0, "mah a"}, + {"E", BIT_DIGITAL, DrvJoy1 + 1, "mah e"}, + {"I", BIT_DIGITAL, DrvJoy1 + 2, "mah i"}, + {"M", BIT_DIGITAL, DrvJoy1 + 3, "mah m"}, + {"Kan", BIT_DIGITAL, DrvJoy1 + 4, "mah kan"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 5, "p1 start"}, + + {"B", BIT_DIGITAL, DrvJoy2 + 0, "mah b"}, + {"F", BIT_DIGITAL, DrvJoy2 + 1, "mah f"}, + {"J", BIT_DIGITAL, DrvJoy2 + 2, "mah j"}, + {"N", BIT_DIGITAL, DrvJoy2 + 3, "mah n"}, + {"Reach", BIT_DIGITAL, DrvJoy2 + 4, "mah reach"}, + {"Bet", BIT_DIGITAL, DrvJoy2 + 5, "mah bet"}, + + {"C", BIT_DIGITAL, DrvJoy3 + 0, "mah c"}, + {"G", BIT_DIGITAL, DrvJoy3 + 1, "mah g"}, + {"K", BIT_DIGITAL, DrvJoy3 + 2, "mah k"}, + {"Chi", BIT_DIGITAL, DrvJoy3 + 3, "mah chi"}, + {"Ron", BIT_DIGITAL, DrvJoy3 + 4, "mah ron"}, + + {"D", BIT_DIGITAL, DrvJoy4 + 0, "mah d"}, + {"H", BIT_DIGITAL, DrvJoy4 + 1, "mah h"}, + {"L", BIT_DIGITAL, DrvJoy4 + 2, "mah l"}, + {"Pon", BIT_DIGITAL, DrvJoy4 + 3, "mah pon"}, + + {"LastChange", BIT_DIGITAL, DrvJoy5 + 0, "mah lc"}, + {"Score", BIT_DIGITAL, DrvJoy5 + 1, "mah score"}, + {"DoubleUp", BIT_DIGITAL, DrvJoy5 + 2, "mah du"}, // ???? + {"FlipFlop", BIT_DIGITAL, DrvJoy5 + 3, "mah ff"}, + {"Big", BIT_DIGITAL, DrvJoy5 + 4, "mah big"}, // ???? + {"Smaill", BIT_DIGITAL, DrvJoy5 + 5, "mah small"}, // ???? + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(mj4simai) + +static struct BurnDIPInfo mj4simaiDIPList[] = { + + // Defaults + {0x1F, 0xFF, 0xFF, 0x00, NULL}, + {0x20, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 8, "Coinage"}, + {0x1F, 0x01, 0x07, 0x00, "1 coin 1 credit"}, + {0x1F, 0x01, 0x07, 0x01, "1 coin 2 credits"}, + {0x1F, 0x01, 0x07, 0x02, "1 coin 3 credits"}, + {0x1F, 0x01, 0x07, 0x03, "1 coin 4 credits"}, + {0x1F, 0x01, 0x07, 0x04, "2 coins 1 credit"}, + {0x1F, 0x01, 0x07, 0x05, "3 coins 1 credit"}, + {0x1F, 0x01, 0x07, 0x06, "4 coins 1 credit"}, + {0x1F, 0x01, 0x07, 0x07, "5 coins 1 credit"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x1F, 0x01, 0x08, 0x08, "Off"}, + {0x1F, 0x01, 0x08, 0x00, "On"}, + {0, 0xFE, 0, 2, "Tumo pin"}, + {0x1F, 0x01, 0x10, 0x10, "Off"}, + {0x1F, 0x01, 0x10, 0x00, "On"}, + {0, 0xFE, 0, 2, "Flip screen"}, + {0x1F, 0x01, 0x20, 0x00, "Off"}, + {0x1F, 0x01, 0x20, 0x20, "On"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x1F, 0x01, 0x40, 0x00, "Off"}, + {0x1F, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x1F, 0x01, 0x80, 0x00, "Off"}, + {0x1F, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 8, "Difficulty"}, + {0x20, 0x01, 0x07, 0x03, "0"}, + {0x20, 0x01, 0x07, 0x04, "1"}, + {0x20, 0x01, 0x07, 0x05, "2"}, + {0x20, 0x01, 0x07, 0x06, "3"}, + {0x20, 0x01, 0x07, 0x07, "4"}, + {0x20, 0x01, 0x07, 0x00, "5"}, + {0x20, 0x01, 0x07, 0x01, "6"}, + {0x20, 0x01, 0x07, 0x02, "7"}, + {0, 0xFE, 0, 2, "Continue"}, + {0x20, 0x01, 0x08, 0x08, "Off"}, + {0x20, 0x01, 0x08, 0x00, "On"}, + {0, 0xFE, 0, 2, "Select girl"}, + {0x20, 0x01, 0x10, 0x00, "Off"}, + {0x20, 0x01, 0x10, 0x10, "On"}, + {0, 0xFE, 0, 2, "Com put"}, + {0x20, 0x01, 0x20, 0x00, "Off"}, + {0x20, 0x01, 0x20, 0x20, "On"}, +}; + +STDDIPINFO(mj4simai) + + +static struct BurnInputInfo myangelInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 3, "diag"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(myangel) + +static struct BurnDIPInfo myangel2DIPList[] = { + + // Defaults + {0x0F, 0xFF, 0xFF, 0x00, NULL}, + {0x10, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x0F, 0x01, 0x01, 0x00, "Off"}, + {0x0F, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Increase lives while playing"}, + {0x0F, 0x01, 0x08, 0x08, "No"}, + {0x0F, 0x01, 0x08, 0x00, "Yes"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x0F, 0x01, 0x30, 0x10, "2"}, + {0x0F, 0x01, 0x30, 0x00, "3"}, + {0x0F, 0x01, 0x30, 0x20, "4"}, + {0x0F, 0x01, 0x30, 0x30, "5"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x0F, 0x01, 0x40, 0x40, "Off"}, + {0x0F, 0x01, 0x40, 0x00, "On"}, + {0, 0xFE, 0, 2, "Flip screen"}, + {0x0F, 0x01, 0x80, 0x00, "Off"}, + {0x0F, 0x01, 0x80, 0x80, "On"}, + + // DIP 2 + {0, 0xFE, 0, 16, "Coinage"}, + {0x10, 0x01, 0x0f, 0x00, "1 coin 1 credit"}, + {0x10, 0x01, 0x0f, 0x01, "1 coin 2 credits"}, + {0x10, 0x01, 0x0f, 0x02, "1 coin 3 credits"}, + {0x10, 0x01, 0x0f, 0x03, "1 coin 4 credits"}, + {0x10, 0x01, 0x0f, 0x04, "1 coin 5 credits"}, + {0x10, 0x01, 0x0f, 0x05, "1 coin 6 credits"}, + {0x10, 0x01, 0x0f, 0x06, "1 coin 7 credits"}, + {0x10, 0x01, 0x0f, 0x07, "2 coins 1 credit"}, + {0x10, 0x01, 0x0f, 0x08, "2 coins 3 credits"}, + {0x10, 0x01, 0x0f, 0x09, "2 coins 5 credits"}, + {0x10, 0x01, 0x0f, 0x0a, "3 coins 1 credit"}, + {0x10, 0x01, 0x0f, 0x0b, "3 coins 2 credits"}, + {0x10, 0x01, 0x0f, 0x0c, "3 coins 4 credits"}, + {0x10, 0x01, 0x0f, 0x0d, "4 coins 1 credit"}, + {0x10, 0x01, 0x0f, 0x0e, "4 coins 3 credits"}, + {0x10, 0x01, 0x0f, 0x0f, "Free play"}, + +}; + +static struct BurnDIPInfo myangelDIPList[] = { + + {0, 0xFE, 0, 2, "Push start to freeze (cheat)"}, + {0x10, 0x01, 0x80, 0x00, "No"}, + {0x10, 0x01, 0x80, 0x80, "Yes"}, + +}; + +STDDIPINFO(myangel2) +STDDIPINFOEXT(myangel, myangel2, myangel) + +static struct BurnDIPInfo pzlbowlDIPList[] = { + + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x80, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x15, 0x01, 0x01, 0x00, "Off"}, + {0x15, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x15, 0x01, 0x02, 0x02, "Off"}, + {0x15, 0x01, 0x02, 0x00, "On"}, + {0, 0xFE, 0, 2, "Flip screen"}, + {0x15, 0x01, 0x04, 0x00, "Off"}, + {0x15, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 8, "Difficulty"}, + {0x15, 0x01, 0x38, 0x08, "Easiest"}, + {0x15, 0x01, 0x38, 0x10, "Easier"}, + {0x15, 0x01, 0x38, 0x18, "Easy"}, + {0x15, 0x01, 0x38, 0x00, "Normal"}, + {0x15, 0x01, 0x38, 0x20, "Hard"}, + {0x15, 0x01, 0x38, 0x28, "Harder"}, + {0x15, 0x01, 0x38, 0x30, "Very hard"}, + {0x15, 0x01, 0x38, 0x38, "Hardest"}, + {0, 0xFE, 0, 4, "Winning rounds (player vs player)"}, + {0x15, 0x01, 0xc0, 0x80, "1"}, + {0x15, 0x01, 0xc0, 0x00, "2"}, + {0x15, 0x01, 0xc0, 0x40, "3"}, + {0x15, 0x01, 0xc0, 0xc0, "5"}, + + // DIP 2 + {0, 0xFE, 0, 16, "Coinage"}, + {0x16, 0x01, 0x0f, 0x00, "1 coin 1 credit"}, + {0x16, 0x01, 0x0f, 0x01, "1 coin 2 credits"}, + {0x16, 0x01, 0x0f, 0x02, "1 coin 3 credits"}, + {0x16, 0x01, 0x0f, 0x03, "1 coin 4 credits"}, + {0x16, 0x01, 0x0f, 0x04, "1 coin 5 credits"}, + {0x16, 0x01, 0x0f, 0x05, "1 coin 6 credits"}, + {0x16, 0x01, 0x0f, 0x06, "1 coin 7 credits"}, + {0x16, 0x01, 0x0f, 0x07, "2 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x08, "2 coins 3 credits"}, + {0x16, 0x01, 0x0f, 0x09, "2 coins 5 credits"}, + {0x16, 0x01, 0x0f, 0x0a, "3 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x0b, "3 coins 2 credits"}, + {0x16, 0x01, 0x0f, 0x0c, "3 coins 4 credits"}, + {0x16, 0x01, 0x0f, 0x0d, "4 coins 1 credit"}, + {0x16, 0x01, 0x0f, 0x0e, "4 coins 3 credits"}, + {0x16, 0x01, 0x0f, 0x0f, "Free play"}, + {0, 0xFE, 0, 2, "Allow continue"}, + {0x16, 0x01, 0x10, 0x10, "No"}, + {0x16, 0x01, 0x10, 0x00, "Yes"}, + {0, 0xFE, 0, 2, "Join In"}, + {0x16, 0x01, 0x20, 0x20, "No"}, + {0x16, 0x01, 0x20, 0x00, "Yes"}, +// {0, 0xFE, 0, 2, "Unused"}, +// {0x16, 0x01, 0x40, 0x00, "Off"}, +// {0x16, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Language"}, + {0x16, 0x01, 0x80, 0x00, "Japanese"}, + {0x16, 0x01, 0x80, 0x80, "English"}, + +}; + +STDDIPINFO(pzlbowl) + +static struct BurnInputInfo penbrosInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 3, "diag"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, +}; + +STDINPUTINFO(penbros) + +static struct BurnDIPInfo penbrosDIPList[] = { + + // Defaults + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x13, 0x01, 0x01, 0x00, "Off"}, + {0x13, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Screen"}, + {0x13, 0x01, 0x02, 0x00, "Normal"}, + {0x13, 0x01, 0x02, 0x02, "Reverse"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x13, 0x01, 0x08, 0x08, "Off"}, + {0x13, 0x01, 0x08, 0x00, "On"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x13, 0x01, 0x30, 0x10, "3 coins 1 play"}, + {0x13, 0x01, 0x30, 0x20, "2 coins 1 play"}, + {0x13, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x13, 0x01, 0x30, 0x30, "1 coin 2 plays"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x13, 0x01, 0xc0, 0x40, "3 coins 1 play"}, + {0x13, 0x01, 0xc0, 0x80, "2 coins 1 play"}, + {0x13, 0x01, 0xc0, 0x00, "1 coin 1 play"}, + {0x13, 0x01, 0xc0, 0xc0, "1 coin 2 plays"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x14, 0x01, 0x03, 0x01, "Easy"}, + {0x14, 0x01, 0x03, 0x00, "Normal"}, + {0x14, 0x01, 0x03, 0x02, "Hard"}, + {0x14, 0x01, 0x03, 0x03, "Very hard"}, + {0, 0xFE, 0, 4, "Player stock"}, + {0x14, 0x01, 0x0c, 0x0c, "2"}, + {0x14, 0x01, 0x0c, 0x00, "3"}, + {0x14, 0x01, 0x0c, 0x08, "4"}, + {0x14, 0x01, 0x0c, 0x04, "5"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x14, 0x01, 0x30, 0x20, "150000, 500000pts"}, + {0x14, 0x01, 0x30, 0x00, "200000, 700000pts"}, + {0x14, 0x01, 0x30, 0x30, "250000 every"}, + {0x14, 0x01, 0x30, 0x10, "None"}, + {0, 0xFE, 0, 4, "Match count"}, + {0x14, 0x01, 0xc0, 0x00, "2"}, + {0x14, 0x01, 0xc0, 0x80, "3"}, + {0x14, 0x01, 0xc0, 0x40, "4"}, + {0x14, 0x01, 0xc0, 0xc0, "5"}, +}; + +STDDIPINFO(penbros) + +static struct BurnInputInfo GundamexInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy3 + 0, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy4 + 0, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 7, "dip"}, +}; + +STDINPUTINFO(Gundamex) + +static struct BurnDIPInfo GundamexDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + {0x18, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x01, 0x00, "Off" }, + {0x16, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x06, 0x04, "Easy" }, + {0x16, 0x01, 0x06, 0x06, "Normal" }, + {0x16, 0x01, 0x06, 0x02, "Hard" }, + {0x16, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x16, 0x01, 0x10, 0x10, "Off" }, + {0x16, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Show Targets" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x17, 0x01, 0x07, 0x00, "4 Coins 1 Credits " }, + {0x17, 0x01, 0x07, 0x01, "3 Coins 1 Credits " }, + {0x17, 0x01, 0x07, 0x02, "2 Coins 1 Credits " }, + {0x17, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x17, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x17, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x17, 0x01, 0x07, 0x03, "1 Coin 4 Credits " }, + {0x17, 0x01, 0x07, 0x04, "1 Coin 5 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x17, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x17, 0x01, 0x38, 0x10, "2 Coins 3 Credits " }, + {0x17, 0x01, 0x38, 0x00, "3 Coins/5 Credits" }, + {0x17, 0x01, 0x38, 0x30, "1 Coin 2 Credits " }, + {0x17, 0x01, 0x38, 0x08, "2 Coins 5 Credits " }, + {0x17, 0x01, 0x38, 0x28, "1 Coin 3 Credits " }, + {0x17, 0x01, 0x38, 0x18, "1 Coin 4 Credits " }, + {0x17, 0x01, 0x38, 0x20, "1 Coin 5 Credits " }, + + {0 , 0xfe, 0 , 8, "Debug Mode" }, + {0x17, 0x01, 0x40, 0x40, "Off" }, + {0x17, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x17, 0x01, 0x80, 0x80, "Off" }, + {0x17, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x18, 0x01, 0x20, 0x20, "English" }, + {0x18, 0x01, 0x20, 0x00, "Japanese" }, +}; + +STDDIPINFO(Gundamex) + +static struct BurnInputInfo DeerhuntInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy4 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start"}, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "mouse x-axis"), + A("P1 Up / Down", BIT_ANALOG_REL, DrvAxis + 1, "mouse y-axis"), + + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "mouse button 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "mouse button 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy4 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 6, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 7, "dip"}, +}; + +STDINPUTINFO(Deerhunt) + +static struct BurnDIPInfo DeerhuntDIPList[]= +{ + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0a, 0x01, 0x07, 0x05, "4 Coins 1 Credits " }, + {0x0a, 0x01, 0x07, 0x06, "2 Coins 1 Credits " }, + {0x0a, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x0a, 0x01, 0x07, 0x04, "1 Coin 2 Credits " }, + {0x0a, 0x01, 0x07, 0x03, "1 Coin 3 Credits " }, + {0x0a, 0x01, 0x07, 0x02, "1 Coin 4 Credits " }, + {0x0a, 0x01, 0x07, 0x01, "1 Coin 5 Credits " }, + {0x0a, 0x01, 0x07, 0x00, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0a, 0x01, 0x38, 0x28, "4 Coins 1 Credits " }, + {0x0a, 0x01, 0x38, 0x30, "2 Coins 1 Credits " }, + {0x0a, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x0a, 0x01, 0x38, 0x20, "1 Coin 2 Credits " }, + {0x0a, 0x01, 0x38, 0x18, "1 Coin 3 Credits " }, + {0x0a, 0x01, 0x38, 0x10, "1 Coin 4 Credits " }, + {0x0a, 0x01, 0x38, 0x08, "1 Coin 5 Credits " }, + {0x0a, 0x01, 0x38, 0x00, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 2, "Discount To Continue" }, + {0x0a, 0x01, 0x40, 0x40, "Off" }, + {0x0a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0a, 0x01, 0x80, 0x80, "Off" }, + {0x0a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Vert. Flip Screen" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Horiz. Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0b, 0x01, 0x04, 0x00, "Off" }, + {0x0b, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0b, 0x01, 0x18, 0x10, "Easy" }, + {0x0b, 0x01, 0x18, 0x18, "Normal" }, + {0x0b, 0x01, 0x18, 0x08, "Hard" }, + {0x0b, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Blood Color" }, + {0x0b, 0x01, 0x20, 0x20, "Red" }, + {0x0b, 0x01, 0x20, 0x00, "Yellow" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x0b, 0x01, 0x40, 0x40, "3" }, + {0x0b, 0x01, 0x40, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Gun Type" }, + {0x0b, 0x01, 0x80, 0x80, "Pump Action" }, + {0x0b, 0x01, 0x80, 0x00, "Hand Gun" }, +}; + +STDDIPINFO(Deerhunt) + + +static struct BurnDIPInfo TurkhuntDIPList[]= +{ + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0a, 0x01, 0x07, 0x05, "4 Coins 1 Credits " }, + {0x0a, 0x01, 0x07, 0x06, "2 Coins 1 Credits " }, + {0x0a, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x0a, 0x01, 0x07, 0x04, "1 Coin 2 Credits " }, + {0x0a, 0x01, 0x07, 0x03, "1 Coin 3 Credits " }, + {0x0a, 0x01, 0x07, 0x02, "1 Coin 4 Credits " }, + {0x0a, 0x01, 0x07, 0x01, "1 Coin 5 Credits " }, + {0x0a, 0x01, 0x07, 0x00, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x0a, 0x01, 0x38, 0x28, "4 Coins 1 Credits " }, + {0x0a, 0x01, 0x38, 0x30, "2 Coins 1 Credits " }, + {0x0a, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x0a, 0x01, 0x38, 0x20, "1 Coin 2 Credits " }, + {0x0a, 0x01, 0x38, 0x18, "1 Coin 3 Credits " }, + {0x0a, 0x01, 0x38, 0x10, "1 Coin 4 Credits " }, + {0x0a, 0x01, 0x38, 0x08, "1 Coin 5 Credits " }, + {0x0a, 0x01, 0x38, 0x00, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 2, "Discount To Continue" }, + {0x0a, 0x01, 0x40, 0x40, "Off" }, + {0x0a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0a, 0x01, 0x80, 0x80, "Off" }, + {0x0a, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Vert. Flip Screen" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Horiz. Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0b, 0x01, 0x04, 0x00, "Off" }, + {0x0b, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0b, 0x01, 0x18, 0x10, "Easy" }, + {0x0b, 0x01, 0x18, 0x18, "Normal" }, + {0x0b, 0x01, 0x18, 0x08, "Hard" }, + {0x0b, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Blood Color" }, + {0x0b, 0x01, 0x20, 0x20, "Red" }, + {0x0b, 0x01, 0x20, 0x00, "Yellow" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x0b, 0x01, 0x40, 0x40, "2" }, + {0x0b, 0x01, 0x40, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Gun Type" }, + {0x0b, 0x01, 0x80, 0x80, "Pump Action" }, + {0x0b, 0x01, 0x80, 0x00, "Hand Gun" }, +}; + +STDDIPINFO(Turkhunt) + +static struct BurnInputInfo WschampInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy4 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start"}, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "mouse x-axis"), + A("P1 Up / Down", BIT_ANALOG_REL, DrvAxis + 1, "mouse y-axis"), + + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "mouse button 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "mouse button 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy4 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 7, "p2 start"}, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 2, "p2 x-axis"), + A("P2 Up / Down", BIT_ANALOG_REL, DrvAxis + 3, "p2 y-axis"), + + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy4 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 6, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 7, "dip"}, +}; + +STDINPUTINFO(Wschamp) + +static struct BurnDIPInfo WschampDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x09, "4 Coins Start, 4 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x08, "4 Coins Start, 3 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x07, "4 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x06, "4 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0c, "3 Coins Start, 3 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0b, "3 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0a, "3 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0e, "2 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0d, "2 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x05, "1 Coin 2 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x04, "1 Coin 3 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x03, "1 Coin 4 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x02, "1 Coin 5 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x01, "1 Coin 6 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Vert. Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Horiz. Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x13, 0x01, 0x18, 0x10, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x13, 0x01, 0x40, 0x40, "2" }, + {0x13, 0x01, 0x40, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Gun Type" }, + {0x13, 0x01, 0x80, 0x80, "Pump Action" }, + {0x13, 0x01, 0x80, 0x00, "Hand Gun" }, +}; + +STDDIPINFO(Wschamp) + +static struct BurnDIPInfo TrophyhDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x09, "4 Coins Start, 4 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x08, "4 Coins Start, 3 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x07, "4 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x06, "4 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0c, "3 Coins Start, 3 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0b, "3 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0a, "3 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0e, "2 Coins Start, 2 Coins Continue" }, + {0x12, 0x01, 0x0f, 0x0d, "2 Coins Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin Start, 1 Coin Continue" }, + {0x12, 0x01, 0x0f, 0x05, "1 Coin 2 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x04, "1 Coin 3 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x03, "1 Coin 4 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x02, "1 Coin 5 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x01, "1 Coin 6 Credits, 1 Credit Start & Continue" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Vert. Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Horiz. Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x13, 0x01, 0x18, 0x10, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Blood Color" }, + {0x13, 0x01, 0x20, 0x20, "Red" }, + {0x13, 0x01, 0x20, 0x00, "Yellow" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x13, 0x01, 0x40, 0x40, "2" }, + {0x13, 0x01, 0x40, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Gun Type" }, + {0x13, 0x01, 0x80, 0x80, "Pump Action" }, + {0x13, 0x01, 0x80, 0x00, "Hand Gun" }, +}; + +STDDIPINFO(Trophyh) + +// Rom information + +static struct BurnRomInfo grdiansRomDesc[] = { + { "u2.bin", 0x080000, 0x36adc6f2, BRF_ESS | BRF_PRG }, // 68000 code + { "u3.bin", 0x080000, 0x2704f416, BRF_ESS | BRF_PRG }, + { "u4.bin", 0x080000, 0xbb52447b, BRF_ESS | BRF_PRG }, + { "u5.bin", 0x080000, 0x9c164a3b, BRF_ESS | BRF_PRG }, + + { "u16.bin", 0x400000, 0x6a65f265, BRF_GRA }, // GFX + { "u20.bin", 0x400000, 0xa7226ab7, BRF_GRA }, + { "u15.bin", 0x400000, 0x01672dcd, BRF_GRA }, + { "u19.bin", 0x400000, 0xc0c998a0, BRF_GRA }, + { "u18.bin", 0x400000, 0x967babf4, BRF_GRA }, + { "u22.bin", 0x400000, 0x6239997a, BRF_GRA }, + { "u17.bin", 0x400000, 0x0fad0629, BRF_GRA }, + { "u21.bin", 0x400000, 0x6f95e466, BRF_GRA }, + + { "u32.bin", 0x100000, 0xcf0f3017, BRF_SND }, // PCM + +}; + +STD_ROM_PICK(grdians) +STD_ROM_FN(grdians) + +static struct BurnRomInfo mj4simaiRomDesc[] = { + { "ll.u2", 0x080000, 0x7be9c781, BRF_ESS | BRF_PRG }, // 68000 code + { "lh1.u3", 0x080000, 0x82aa3f72, BRF_ESS | BRF_PRG }, + { "hl.u4", 0x080000, 0x226063b7, BRF_ESS | BRF_PRG }, + { "hh.u5", 0x080000, 0x23aaf8df, BRF_ESS | BRF_PRG }, + + { "cha-03.u16", 0x400000, 0xd367429a, BRF_GRA }, // GFX + { "cha-04.u18", 0x400000, 0x7f2008c3, BRF_GRA }, + { "cha-05.u15", 0x400000, 0xe94ec40a, BRF_GRA }, + { "cha-06.u17", 0x400000, 0x5cb0b3a9, BRF_GRA }, + { "cha-01.u21", 0x400000, 0x35f47b37, BRF_GRA }, + { "cha-02.u22", 0x400000, 0xf6346860, BRF_GRA }, + + { "cha-07.u32", 0x400000, 0x817519ee, BRF_SND }, // PCM + +}; + +STD_ROM_PICK(mj4simai) +STD_ROM_FN(mj4simai) + +static struct BurnRomInfo myangelRomDesc[] = { + { "kq1-prge.u2", 0x080000, 0x6137d4c0, BRF_ESS | BRF_PRG }, // 68000 code + { "kq1-prgo.u3", 0x080000, 0x4aad10d8, BRF_ESS | BRF_PRG }, + { "kq1-tble.u4", 0x080000, 0xe332a514, BRF_ESS | BRF_PRG }, + { "kq1-tblo.u5", 0x080000, 0x760cab15, BRF_ESS | BRF_PRG }, + + { "kq1-cg2.u20", 0x200000, 0x80b4e8de, BRF_GRA }, // GFX + { "kq1-cg0.u16", 0x200000, 0xf8ae9a05, BRF_GRA }, + { "kq1-cg3.u19", 0x200000, 0x9bdc35c9, BRF_GRA }, + { "kq1-cg1.u15", 0x200000, 0x23bd7ea4, BRF_GRA }, + { "kq1-cg6.u22", 0x200000, 0xb25acf12, BRF_GRA }, + { "kq1-cg4.u18", 0x200000, 0xdca7f8f2, BRF_GRA }, + { "kq1-cg7.u21", 0x200000, 0x9f48382c, BRF_GRA }, + { "kq1-cg5.u17", 0x200000, 0xa4bc4516, BRF_GRA }, + + { "kq1-snd.u32", 0x200000, 0x8ca1b449, BRF_SND }, // PCM + +}; + +STD_ROM_PICK(myangel) +STD_ROM_FN(myangel) + +static struct BurnRomInfo myangel2RomDesc[] = { + { "kqs1ezpr.u2", 0x080000, 0x2469aac2, BRF_ESS | BRF_PRG }, // 68000 code + { "kqs1ozpr.u3", 0x080000, 0x6336375c, BRF_ESS | BRF_PRG }, + { "kqs1e-tb.u4", 0x080000, 0xe759b4cc, BRF_ESS | BRF_PRG }, + { "kqs1o-tb.u5", 0x080000, 0xb6168737, BRF_ESS | BRF_PRG }, + + { "kqs1-cg4.u20", 0x200000, 0xd1802241, BRF_GRA }, // GFX + { "kqs1-cg0.u16", 0x400000, 0xc21a33a7, BRF_GRA }, + { "kqs1-cg5.u19", 0x200000, 0xd86cf19c, BRF_GRA }, + { "kqs1-cg1.u15", 0x400000, 0xdca799ba, BRF_GRA }, + { "kqs1-cg6.u22", 0x200000, 0x3f08886b, BRF_GRA }, + { "kqs1-cg2.u18", 0x400000, 0xf7f92c7e, BRF_GRA }, + { "kqs1-cg7.u21", 0x200000, 0x2c977904, BRF_GRA }, + { "kqs1-cg3.u17", 0x400000, 0xde3b2191, BRF_GRA }, + + { "kqs1-snd.u32", 0x400000, 0x792a6b49, BRF_SND }, // PCM +}; + +STD_ROM_PICK(myangel2) +STD_ROM_FN(myangel2) + +static struct BurnRomInfo pzlbowlRomDesc[] = { + { "kup-u06.i03", 0x080000, 0x314e03ac, BRF_ESS | BRF_PRG }, // 68000 code + { "kup-u07.i03", 0x080000, 0xa0423a04, BRF_ESS | BRF_PRG }, + + { "kuc-u38.i00", 0x400000, 0x3db24172, BRF_GRA }, // GFX + { "kuc-u39.i00", 0x400000, 0x9b26619b, BRF_GRA }, + { "kuc-u40.i00", 0x400000, 0x7e49a2cf, BRF_GRA }, + { "kuc-u41.i00", 0x400000, 0x2febf19b, BRF_GRA }, + + { "kus-u18.i00", 0x400000, 0xe2b1dfcf, BRF_SND }, // PCM + +}; + +STD_ROM_PICK(pzlbowl) +STD_ROM_FN(pzlbowl) + +static struct BurnRomInfo penbrosRomDesc[] = { + { "u06.bin", 0x080000, 0x7bbdffac, BRF_ESS | BRF_PRG }, // 68000 code + { "u07.bin", 0x080000, 0xd50cda5f, BRF_ESS | BRF_PRG }, + + { "u38.bin", 0x400000, 0x4247b39e, BRF_GRA }, // GFX + { "u39.bin", 0x400000, 0xf9f07faf, BRF_GRA }, + { "u40.bin", 0x400000, 0xdc9e0a96, BRF_GRA }, + + { "u18.bin", 0x200000, 0xde4e65e2, BRF_SND }, // PCM +}; + +STD_ROM_PICK(penbros) +STD_ROM_FN(penbros) + +static struct BurnRomInfo gundamexRomDesc[] = { + { "ka002002.u2", 0x080000, 0xe850f6d8, BRF_ESS | BRF_PRG }, // 0 68000 code + { "ka002004.u3", 0x080000, 0xc0fb1208, BRF_ESS | BRF_PRG }, // 1 + { "ka002001.u4", 0x080000, 0x553ebe6b, BRF_ESS | BRF_PRG }, // 2 + { "ka002003.u5", 0x080000, 0x946185aa, BRF_ESS | BRF_PRG }, // 3 + { "ka001005.u77", 0x080000, 0xf01d3d00, BRF_ESS | BRF_PRG }, // 4 + + { "ka001009.u16", 0x200000, 0x997d8d93, BRF_GRA }, // 5 GFX + { "ka001010.u18", 0x200000, 0x811b67ca, BRF_GRA }, // 6 + { "ka001011.u20", 0x200000, 0x08a72700, BRF_GRA }, // 7 + { "ka001012.u15", 0x200000, 0xb789e4a8, BRF_GRA }, // 8 + { "ka001013.u17", 0x200000, 0xd8a0201f, BRF_GRA }, // 9 + { "ka001014.u19", 0x200000, 0x7635e026, BRF_GRA }, // 10 + { "ka001006.u21", 0x200000, 0x6aac2f2f, BRF_GRA }, // 11 + { "ka001007.u22", 0x200000, 0x588f9d63, BRF_GRA }, // 12 + { "ka001008.u23", 0x200000, 0xdb55a60a, BRF_GRA }, // 13 + + { "ka001015.u28", 0x200000, 0xada2843b, BRF_SND }, // 14 PCM + + { "eeprom.bin", 0x000080, 0x80f8e248, BRF_OPT }, +}; + +STD_ROM_PICK(gundamex) +STD_ROM_FN(gundamex) + +static struct BurnRomInfo deerhuntRomDesc[] = { + { "as0906e05.u06", 0x100000, 0x20c81f17, 1 }, // 0 68000 code + { "as0907e05.u07", 0x100000, 0x1731aa2a, 1 }, // 1 + + { "as0901m01.u38", 0x800000, 0x1d6acf8f, 2 }, // 2 GFX + { "as0902m01.u39", 0x800000, 0xc7ca2128, 2 }, // 3 + { "as0903m01.u40", 0x800000, 0xe8ef81b3, 2 }, // 4 + { "as0904m01.u41", 0x800000, 0xd0f97fdc, 2 }, // 5 + + { "as0905m01.u18", 0x400000, 0x8d8165bb, 3 }, // 6 PCM +}; + +STD_ROM_PICK(deerhunt) +STD_ROM_FN(deerhunt) + +static struct BurnRomInfo deerhunaRomDesc[] = { + { "as0906e04-v4_2.u06", 0x100000, 0xbb3af36f, 1 }, // 0 68000 code + { "as0907e04-v4_2.u07", 0x100000, 0x83f02117, 1 }, // 1 + + { "as0901m01.u38", 0x800000, 0x1d6acf8f, 2 }, // 2 GFX + { "as0902m01.u39", 0x800000, 0xc7ca2128, 2 }, // 3 + { "as0903m01.u40", 0x800000, 0xe8ef81b3, 2 }, // 4 + { "as0904m01.u41", 0x800000, 0xd0f97fdc, 2 }, // 5 + + { "as0905m01.u18", 0x400000, 0x8d8165bb, 3 }, // 6 PCM +}; + +STD_ROM_PICK(deerhuna) +STD_ROM_FN(deerhuna) + +static struct BurnRomInfo deerhunbRomDesc[] = { + { "as0906e04.u06", 0x100000, 0x07d9b64a, 1 }, // 0 68000 code + { "as0907e04.u07", 0x100000, 0x19973d08, 1 }, // 1 + + { "as0901m01.u38", 0x800000, 0x1d6acf8f, 2 }, // 2 GFX + { "as0902m01.u39", 0x800000, 0xc7ca2128, 2 }, // 3 + { "as0903m01.u40", 0x800000, 0xe8ef81b3, 2 }, // 4 + { "as0904m01.u41", 0x800000, 0xd0f97fdc, 2 }, // 5 + + { "as0905m01.u18", 0x400000, 0x8d8165bb, 3 }, // 6 PCM +}; + +STD_ROM_PICK(deerhunb) +STD_ROM_FN(deerhunb) + + +static struct BurnRomInfo deerhuncRomDesc[] = { + { "as0906e02.u06", 0x100000, 0x190cca42, 1 }, // 0 68000 code + { "as0907e02.u07", 0x100000, 0x9de2b901, 1 }, // 1 + + { "as0901m01.u38", 0x800000, 0x1d6acf8f, 2 }, // 2 GFX + { "as0902m01.u39", 0x800000, 0xc7ca2128, 2 }, // 3 + { "as0903m01.u40", 0x800000, 0xe8ef81b3, 2 }, // 4 + { "as0904m01.u41", 0x800000, 0xd0f97fdc, 2 }, // 5 + + { "as0905m01.u18", 0x400000, 0x8d8165bb, 3 }, // 6 PCM +}; + +STD_ROM_PICK(deerhunc) +STD_ROM_FN(deerhunc) + +static struct BurnRomInfo turkhuntRomDesc[] = { + { "asx906e01.u06", 0x100000, 0xc96266e1, 1 }, // 0 68000 code + { "asx907e01.u07", 0x100000, 0x7c67b502, 1 }, // 1 + + { "asx901m01.u38", 0x800000, 0xeabd3f44, 2 }, // 2 GFX + { "asx902m01.u39", 0x800000, 0xc32130c8, 2 }, // 3 + { "asx903m01.u40", 0x800000, 0x5f86c322, 2 }, // 4 + { "asx904m01.u41", 0x800000, 0xc77e0b66, 2 }, // 5 + + { "asx905m01.u18", 0x400000, 0x8d9dd9a9, 3 }, // 6 PCM +}; + +STD_ROM_PICK(turkhunt) +STD_ROM_FN(turkhunt) + +static struct BurnRomInfo wschampRomDesc[] = { + { "as1006e03.u06", 0x100000, 0x0ad01677, 1 }, // 0 68000 code + { "as1007e03.u07", 0x100000, 0x572624f0, 1 }, // 1 + + { "as1001m01.u38", 0x800000, 0x92595579, 2 }, // 2 GFX + { "as1002m01.u39", 0x800000, 0x16c2bb08, 2 }, // 3 + { "as1003m01.u40", 0x800000, 0x89618858, 2 }, // 4 + { "as1004m01.u41", 0x800000, 0x500c0909, 2 }, // 5 + + { "as1005m01.u18", 0x400000, 0xe4b137b8, 3 }, // 6 PCM +}; + +STD_ROM_PICK(wschamp) +STD_ROM_FN(wschamp) + +static struct BurnRomInfo wschampaRomDesc[] = { + { "as1006e02.u06", 0x100000, 0xd3d3b2b5, 1 }, // 0 68000 code + { "as1007e02.u07", 0x100000, 0x78ede6d9, 1 }, // 1 + + { "as1001m01.u38", 0x800000, 0x92595579, 2 }, // 2 GFX + { "as1002m01.u39", 0x800000, 0x16c2bb08, 2 }, // 3 + { "as1003m01.u40", 0x800000, 0x89618858, 2 }, // 4 + { "as1004m01.u41", 0x800000, 0x500c0909, 2 }, // 5 + + { "as1005m01.u18", 0x400000, 0xe4b137b8, 3 }, // 6 PCM +}; + +STD_ROM_PICK(wschampa) +STD_ROM_FN(wschampa) + +static struct BurnRomInfo trophyhRomDesc[] = { + { "as1106e01.u06", 0x100000, 0xb4950882, 1 }, // 0 68000 code + { "as1107e01.u07", 0x100000, 0x19ee67cb, 1 }, // 1 + + { "as1101m01.u38", 0x800000, 0x855ed675, 2 }, // 2 GFX + { "as1102m01.u39", 0x800000, 0xd186d271, 2 }, // 3 + { "as1103m01.u40", 0x800000, 0xadf8a54e, 2 }, // 4 + { "as1104m01.u41", 0x800000, 0x387882e9, 2 }, // 5 + + { "as1105m01.u18", 0x400000, 0x633d0df8, 3 }, // 6 PCM +}; + +STD_ROM_PICK(trophyh) +STD_ROM_FN(trophyh) + +static struct BurnRomInfo funcube2RomDesc[] = { + { "fc21_prg-0b.u3", 0x080000, 0xadd1c8a6, 1 }, // 0 68000 code + + { "fc21_iopr-0.u49", 0x020000, 0x314555ef, 2 }, // 1 H8/3007 code + + { "fc21a", 0x000300, 0x00000000, 3 | BRF_NODUMP }, // 2 PIC12C508 Code + + { "fc21_obj-0.u43", 0x400000, 0x08cfe6d9, 4 }, // 3 GFX + { "fc21_obj-1.u42", 0x400000, 0x4c1fbc20, 4 }, // 4 + + { "fc21_voi0.u47", 0x400000, 0x25b5fc3f, 5 }, // 5 PCM +}; + +STD_ROM_PICK(funcube2) +STD_ROM_FN(funcube2) + +static struct BurnRomInfo funcube4RomDesc[] = { + { "fc41_prg-0.u3", 0x080000, 0xef870874, 1 }, // 0 68000 code + + { "fc21_iopr-0.u49", 0x020000, 0x314555ef, 2 }, // 1 H8/3007 code + + { "fc41a", 0x000300, 0x00000000, 3 | BRF_NODUMP }, // 2 PIC12C508 Code + + { "fc41_obj-0.u43", 0x400000, 0x9ff029d5, 4 }, // 3 GFX + { "fc41_obj-1.u42", 0x400000, 0x5ab7b087, 4 }, // 4 + + { "fc41_snd0.u47", 0x400000, 0x48337257, 5 }, // 5 PCM +}; + +STD_ROM_PICK(funcube4) +STD_ROM_FN(funcube4) + + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x7c00) >> 7; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x001f) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +// ---- Toshiba TMP68301 --------------------------------------------- + +static INT32 tmp68301_timer[3] = {0, 0, 0}; +static INT32 tmp68301_timer_counter[3] = {0, 0, 0}; +static INT32 tmp68301_irq_vector[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +static void tmp68301_update_timer( INT32 i ) +{ + UINT16 TCR = RamTMP68301[(0x200 + i * 0x20)/2]; + UINT16 MAX1 = RamTMP68301[(0x204 + i * 0x20)/2]; + UINT16 MAX2 = RamTMP68301[(0x206 + i * 0x20)/2]; + + INT32 max = 0; + double duration = 0; + +// timer_adjust(tmp68301_timer[i],TIME_NEVER,i,0); + tmp68301_timer[i] = 0; + tmp68301_timer_counter[i] = 0; + //bprintf(PRINT_NORMAL, _T("Tmp68301: update timer %d. TCR: %04x MAX: %04x %04x\n"), i, TCR, MAX1, MAX2); + + // timers 1&2 only + switch( (TCR & 0x0030)>>4 ) { // MR2..1 + case 1: max = MAX1; break; + case 2: max = MAX2; break; + } + + switch ( (TCR & 0xc000)>>14 ) { // CK2..1 + case 0: // System clock (CLK) + if (max) { + INT32 scale = (TCR & 0x3c00)>>10; // P4..1 + if (scale > 8) scale = 8; + duration = M68K_CYCS; //Machine->drv->cpu[0].cpu_clock; + duration /= 1 << scale; + duration /= max; + } + break; + } + +// logerror("CPU #0 PC %06X: TMP68301 Timer %d, duration %lf, max %04X\n",activecpu_get_pc(),i,duration,max); +// bprintf(PRINT_NORMAL, _T("TMP68301 Timer %d, duration %lf, max %04X TCR %04X\n"),i,duration,max,TCR); + + if (!(TCR & 0x0002)) // CS + { + if (duration) { + // timer_adjust(tmp68301_timer[i],TIME_IN_HZ(duration),i,0); + // active tmp68301 timer i, and set duration + tmp68301_timer[i] = (INT32) (M68K_CYCS / duration); + //tmp68301_timer_counter[i] = 0; + //bprintf(PRINT_NORMAL, _T("Tmp68301: update timer #%d duration to %d (%8.3f)\n"), i, tmp68301_timer[i], duration); + } else + //logerror("CPU #0 PC %06X: TMP68301 error, timer %d duration is 0\n",activecpu_get_pc(),i); + bprintf(PRINT_ERROR, _T("Tmp68301: error timer %d duration is 0\n"), i, TCR, MAX1, MAX2); + } +} + +static void tmp68301_timer_callback(INT32 i) +{ + UINT16 TCR = RamTMP68301[(0x200 + i * 0x20)/2]; + UINT16 IMR = RamTMP68301[0x94/2]; // Interrupt Mask Register (IMR) + UINT16 ICR = RamTMP68301[0x8e/2+i]; // Interrupt Controller Register (ICR7..9) + UINT16 IVNR = RamTMP68301[0x9a/2]; // Interrupt Vector Number Register (IVNR) + +// logerror("CPU #0 PC %06X: callback timer %04X, j = %d\n",activecpu_get_pc(),i,tcount); +// bprintf(PRINT_NORMAL, _T("Tmp68301: timer[%d] TCR: %04x IMR: %04x\n"), i, TCR, IMR); + + if ( (TCR & 0x0004) && !(IMR & (0x100<> 5) & 3 ); + switch ( addr ) { + case 0x200: tmp68301_update_timer(0); break; + case 0x220: tmp68301_update_timer(1); break; + case 0x240: tmp68301_update_timer(2); break; + } +} + +void __fastcall Tmp68301WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress &= 0x0003ff; + UINT8 *p = (UINT8 *)RamTMP68301; + p[sekAddress ^ 1] = byteValue; +// bprintf(PRINT_NORMAL, _T("TMP68301 Reg %04X <- %04X & %04X %04x\n"),sekAddress&0xfffe, (sekAddress&1)?byteValue:byteValue<<8,(sekAddress&1)?0x00ff:0xff00, RamTMP68301[sekAddress>>1]); +} + +void __fastcall Tmp68301WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress &= 0x0003ff; + RamTMP68301[ sekAddress >> 1 ] = wordValue; + tmp68301_regs_w( sekAddress, wordValue ); +// bprintf(PRINT_NORMAL, _T("TMP68301 Reg %04X <- %04X & %04X %04x\n"),sekAddress,wordValue,0xffff, RamTMP68301[sekAddress>>1]); +} + + +UINT8 __fastcall grdiansReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall grdiansReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x600000: return ~DrvInput[3]; // DIP 1 + case 0x600002: return ~DrvInput[4]; // DIP 2 + case 0x700000: return ~DrvInput[0]; // Joy 1 + case 0x700002: return ~DrvInput[1]; // Joy 2 + case 0x700004: return ~DrvInput[2]; // Coin + + case 0x70000C: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xFFFF; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall grdiansWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall grdiansWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x800000: + //bprintf(PRINT_NORMAL, _T("lockout 0x%04x\n"), wordValue); + break; + + case 0xE00010: + case 0xE00012: + case 0xE00014: + case 0xE00016: + case 0xE00018: + case 0xE0001A: + case 0xE0001C: + case 0xE0001E: + x1010_sound_bank_w( (sekAddress - 0xE00010) >> 1, wordValue ); + break; + + case 0xE00000: // nop + break; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +UINT8 __fastcall setaSoundRegReadByte(UINT32 sekAddress) +{ + bprintf(PRINT_NORMAL, _T("x1-010 to read byte value of location %x\n"), sekAddress); + return 0; +} + +UINT16 __fastcall setaSoundRegReadWord(UINT32 sekAddress) +{ + return x1010_sound_read_word((sekAddress & 0x3ffff) >> 1); +} + +void __fastcall setaSoundRegWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + // bprintf(PRINT_NORMAL, _T("x1-010 to write byte value %x to location %x\n"), byteValue, sekAddress); + UINT32 offset = (sekAddress & 0x00003fff) >> 1; + INT32 channel, reg; + + if (sekAddress & 1) { + + x1_010_chip->HI_WORD_BUF[ offset ] = byteValue; + + } else { + + offset ^= x1_010_chip->address; + + channel = offset / sizeof(X1_010_CHANNEL); + reg = offset % sizeof(X1_010_CHANNEL); + + if( channel < SETA_NUM_CHANNELS && reg == 0 && (x1_010_chip->reg[offset]&1) == 0 && (byteValue&1) != 0 ) { + x1_010_chip->smp_offset[channel] = 0; + x1_010_chip->env_offset[channel] = 0; + } + x1_010_chip->reg[offset] = byteValue; + + } + +} + +void __fastcall setaSoundRegWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + //bprintf(PRINT_NORMAL, _T("x1-010 to write word value %x to location %x\n"), wordValue, sekAddress); + UINT32 offset = (sekAddress & 0x00003fff) >> 1; + INT32 channel, reg; + + x1_010_chip->HI_WORD_BUF[ offset ] = wordValue >> 8; + + offset ^= x1_010_chip->address; + + channel = offset / sizeof(X1_010_CHANNEL); + reg = offset % sizeof(X1_010_CHANNEL); + + if( channel < SETA_NUM_CHANNELS && reg == 0 && (x1_010_chip->reg[offset]&1) == 0 && (wordValue&1) != 0 ) { + x1_010_chip->smp_offset[channel] = 0; + x1_010_chip->env_offset[channel] = 0; + } + x1_010_chip->reg[offset] = wordValue & 0xff; +} + +void __fastcall grdiansPaletteWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + bprintf(PRINT_NORMAL, _T("Pal to write byte value %x to location %x\n"), byteValue, sekAddress); +} + +void __fastcall grdiansPaletteWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + //bprintf(PRINT_NORMAL, _T("Pal to write word value %x to location %x\n"), wordValue, sekAddress); + sekAddress &= 0x00FFFF; + sekAddress >>= 1; + RamPal[sekAddress] = wordValue; + CurPal[sekAddress] = CalcCol( wordValue ); +} + +void __fastcall grdiansClearWriteByte(UINT32, UINT8) {} +void __fastcall grdiansClearWriteWord(UINT32, UINT16) {} + +INT32 __fastcall grdiansSekIrqCallback(INT32 irq) +{ + //bprintf(PRINT_NORMAL, _T("Sek Irq Call back %d vector %04x\n"), irq, tmp68301_irq_vector[irq]); + return tmp68301_irq_vector[irq]; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); +// SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gundamex")) { + EEPROMReset(); // gundam + if (EEPROMAvailable() == 0) { + UINT8 EEPROMDATA[2] = { 0x08, 0x70 }; + EEPROMFill(EEPROMDATA, 0, 2); + } + } + + return 0; +} + +static INT32 MemIndex(INT32 CodeSize, INT32 GfxSize, INT32 PcmSize, INT32 ExtRamSize) +{ + UINT8 *Next; Next = Mem; + Rom68K = Next; Next += CodeSize; // 68000 ROM + RomGfx = Next; Next += GfxSize; // GFX Rom + X1010SNDROM = Next; Next += PcmSize; // PCM + + RamStart = Next; + + Ram68K = Next; Next += 0x010000; + RamUnknown = Next; Next += ExtRamSize; + if (HasNVRam) RamNV = Next; Next += 0x10000; + RamSpr = (UINT16 *) Next; Next += 0x020000 * sizeof(UINT16); + RamSprBak = (UINT16 *) Next; Next += 0x020000 * sizeof(UINT16); + RamPal = (UINT16 *) Next; Next += 0x008000 * sizeof(UINT16); + RamTMP68301 = (UINT16 *) Next; Next += 0x000200 * sizeof(UINT16); + + RamVReg = (UINT16 *) Next; Next += 0x000020 * sizeof(UINT16); + + RamEnd = Next; + + CurPal = (UINT32 *) Next; Next += 0x008000 * sizeof(UINT32); + + MemEnd = Next; + return 0; +} + +static void loadDecodeGfx(UINT8 *p, INT32 cnt, INT32 offset2x) +{ + UINT8 * d = RomGfx; + UINT8 * q = p + 1; + + for (INT32 i=0; i> 7) & 1 ) << offset2x) | (( (*q >> 7) & 1 ) << (offset2x + 1)); + *(d+1) |= (( (*p >> 6) & 1 ) << offset2x) | (( (*q >> 6) & 1 ) << (offset2x + 1)); + *(d+2) |= (( (*p >> 5) & 1 ) << offset2x) | (( (*q >> 5) & 1 ) << (offset2x + 1)); + *(d+3) |= (( (*p >> 4) & 1 ) << offset2x) | (( (*q >> 4) & 1 ) << (offset2x + 1)); + *(d+4) |= (( (*p >> 3) & 1 ) << offset2x) | (( (*q >> 3) & 1 ) << (offset2x + 1)); + *(d+5) |= (( (*p >> 2) & 1 ) << offset2x) | (( (*q >> 2) & 1 ) << (offset2x + 1)); + *(d+6) |= (( (*p >> 1) & 1 ) << offset2x) | (( (*q >> 1) & 1 ) << (offset2x + 1)); + *(d+7) |= (( (*p >> 0) & 1 ) << offset2x) | (( (*q >> 0) & 1 ) << (offset2x + 1)); + } + +} + +static INT32 grdiansInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0200000, 0x2000000, 0x0200000, 0x00C000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0200000, 0x2000000, 0x0200000, 0x00C000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0800000); + for (INT32 i=0; i<8; i+=2) { + BurnLoadRom(tmpGfx + 0x0200000, i+5, 1); + memcpy(tmpGfx + 0x0600000, tmpGfx + 0x0200000, 0x0200000); + BurnLoadRom(tmpGfx + 0x0000000, i+4, 1); + loadDecodeGfx( tmpGfx, 0x0800000 / 2, i ); + } + + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 12, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + SekMapMemory(RamUnknown, 0x304000, 0x30FFFF, SM_RAM); // ? seems tile data + + SekMapMemory((UINT8 *)RamSpr, + 0xC00000, 0xC3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0xC40000, 0xC4FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0xC60000, 0xC6003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0xB00000, 0xB03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xC40000, 0xC4FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xC50000, 0xC5FFFF, SM_WRITE); + SekMapHandler(4, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, grdiansReadWord); + SekSetReadByteHandler(0, grdiansReadByte); + SekSetWriteWordHandler(0, grdiansWriteWord); + SekSetWriteByteHandler(0, grdiansWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, grdiansClearWriteWord); + SekSetWriteByteHandler(3, grdiansClearWriteByte); + + SekSetWriteWordHandler(4, Tmp68301WriteWord); + SekSetWriteByteHandler(4, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0; + sva_x = 128; + sva_y = 128; + + gfx_code_mask = 0x0800000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + DrvDoReset(); + + return 0; +} + +// -- mj4simai ----------------------------------------------------------- + +UINT8 __fastcall mj4simaiReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall mj4simaiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x600006: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xffff; + + case 0x600000: + case 0x600002: + switch (Mahjong_keyboard) + { + case 0x01: return ~DrvInput[0]; + case 0x02: return ~DrvInput[1]; + case 0x04: return ~DrvInput[5]; + case 0x08: return ~DrvInput[6]; + case 0x10: return ~DrvInput[7]; + default: return 0xffff; + } + + case 0x600100: return ~DrvInput[2]; // Coin + + case 0x600300: return ~DrvInput[3]; // DIP 1 + case 0x600302: return ~DrvInput[4]; // DIP 2 + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall mj4simaiWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall mj4simaiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x600200: break; // NOP + + case 0x600300: + case 0x600302: + case 0x600304: + case 0x600306: + case 0x600308: + case 0x60030A: + case 0x60030C: + case 0x60030E: + x1010_sound_bank_w( (sekAddress & 0xf) >> 1, wordValue ); + break; + case 0x600004: + Mahjong_keyboard = wordValue & 0xff; + break; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +static INT32 mj4simaiInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0200000, 0x2000000, 0x0500000, 0x000000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0200000, 0x2000000, 0x0500000, 0x000000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0800000); + for (INT32 i=0; i<6; i+=2) { + BurnLoadRom(tmpGfx + 0x0000000, i+4, 1); + BurnLoadRom(tmpGfx + 0x0400000, i+5, 1); + loadDecodeGfx( tmpGfx, 0x0800000 / 2, i ); + } + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 10, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory((UINT8 *)RamSpr, + 0xC00000, 0xC3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0xC40000, 0xC4FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0xC60000, 0xC6003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0xB00000, 0xB03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xC40000, 0xC4FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, mj4simaiReadWord); + SekSetReadByteHandler(0, mj4simaiReadByte); + SekSetWriteWordHandler(0, mj4simaiWriteWord); + SekSetWriteByteHandler(0, mj4simaiWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0; + sva_x = 64; + sva_y = 128; + + gfx_code_mask = 0x0800000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + +// bMahjong = 1; + + DrvDoReset(); + + return 0; +} + +// -- myangel ----------------------------------------------------------- + +UINT8 __fastcall myangelReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall myangelReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x700000: return ~DrvInput[0]; + case 0x700002: return ~DrvInput[1]; + case 0x700004: return ~DrvInput[2]; + + case 0x700006: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xffff; + + case 0x700300: return ~DrvInput[3]; // DIP 1 + case 0x700302: return ~DrvInput[4]; // DIP 2 + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall myangelWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall myangelWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x700200: break; // NOP + + case 0x700310: + case 0x700312: + case 0x700314: + case 0x700316: + case 0x700318: + case 0x70031A: + case 0x70031C: + case 0x70031E: + x1010_sound_bank_w( (sekAddress & 0xf) >> 1, wordValue ); + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +static INT32 myangelInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0200000, 0x1000000, 0x0300000, 0x000000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0200000, 0x1000000, 0x0300000, 0x000000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0400000); + for (INT32 i=0; i<8; i+=2) { + BurnLoadRom(tmpGfx + 0x0000000, i+4, 1); + BurnLoadRom(tmpGfx + 0x0200000, i+5, 1); + loadDecodeGfx( tmpGfx, 0x0400000 / 2, i ); + } + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 12, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory((UINT8 *)RamSpr, + 0xC00000, 0xC3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0xC40000, 0xC4FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0xC60000, 0xC6003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0xB00000, 0xB03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xC40000, 0xC4FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, myangelReadWord); + SekSetReadByteHandler(0, myangelReadByte); + SekSetWriteWordHandler(0, myangelWriteWord); + SekSetWriteByteHandler(0, myangelWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0x10; + sva_x = 0; + sva_y = 0; + + gfx_code_mask = 0x0400000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + DrvDoReset(); + + return 0; +} + +// -- myangel2 ----------------------------------------------------------- + +UINT8 __fastcall myangel2ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall myangel2ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x600000: return ~DrvInput[0]; + case 0x600002: return ~DrvInput[1]; + case 0x600004: return ~DrvInput[2]; + + case 0x600006: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xffff; + + case 0x600300: return ~DrvInput[3]; // DIP 1 + case 0x600302: return ~DrvInput[4]; // DIP 2 + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall myangel2WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall myangel2WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x600200: break; // NOP + + case 0x600300: + case 0x600302: + case 0x600304: + case 0x600306: + case 0x600308: + case 0x60030A: + case 0x60030C: + case 0x60030E: + x1010_sound_bank_w( (sekAddress & 0xf) >> 1, wordValue ); + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +static INT32 myangel2Init() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0200000, 0x1800000, 0x0500000, 0x000000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0200000, 0x1800000, 0x0500000, 0x000000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0600000); + for (INT32 i = 0; i < 8; i+=2) { + BurnLoadRom(tmpGfx + 0x0000000, i + 4, 1); + BurnLoadRom(tmpGfx + 0x0200000, i + 5, 1); + loadDecodeGfx(tmpGfx, 0x0600000 / 2, i); + } + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 12, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory((UINT8 *)RamSpr, + 0xD00000, 0xD3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0xD40000, 0xD4FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0xD60000, 0xD6003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0xB00000, 0xB03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xD40000, 0xD4FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, myangel2ReadWord); + SekSetReadByteHandler(0, myangel2ReadByte); + SekSetWriteWordHandler(0, myangel2WriteWord); + SekSetWriteByteHandler(0, myangel2WriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0x10; + sva_x = 0; + sva_y = 0; + + gfx_code_mask = 0x0600000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + DrvDoReset(); + + return 0; +} + +// -- pzlbowl ----------------------------------------------------------- + +UINT8 __fastcall pzlbowlReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall pzlbowlReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400300: return ~DrvInput[3]; // DIP 1 + case 0x400302: return ~DrvInput[4]; // DIP 2 + case 0x500000: return ~DrvInput[0]; // Player 1 + case 0x500002: return ~DrvInput[1]; // Player 2 + + case 0x500004: { + //readinputport(4) | (rand() & 0x80 ) + static UINT16 prot = 0; + prot ^= 0x80; + return ~(prot | DrvInput[2]); + } + case 0x500006: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xffff; + case 0x700000: { + /* The game checks for a specific value read from the ROM region. + The offset to use is stored in RAM at address 0x20BA16 */ + UINT32 address = (*(UINT16 *)(Ram68K + 0x00ba16) << 16) | *(UINT16 *)(Ram68K + 0x00ba18); + bprintf(PRINT_NORMAL, _T("pzlbowl Protection read address %08x [%02x %02x %02x %02x]\n"), address, + Rom68K[ address - 2 ], Rom68K[ address - 1 ], Rom68K[ address - 0 ], Rom68K[ address + 1 ]); + return Rom68K[ address - 2 ]; } +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall pzlbowlWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall pzlbowlWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x400300: + case 0x400302: + case 0x400304: + case 0x400306: + case 0x400308: + case 0x40030A: + case 0x40030C: + case 0x40030E: + x1010_sound_bank_w( (sekAddress & 0xf) >> 1, wordValue ); + break; + case 0x500004: + //bprintf(PRINT_NORMAL, _T("Coin Counter %x\n"), wordValue); + break; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +static INT32 pzlbowlInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0100000, 0x1000000, 0x0500000, 0x000000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0100000, 0x1000000, 0x0500000, 0x000000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0400000); + for (INT32 i=0; i<4; i++) { + BurnLoadRom(tmpGfx, i+2, 1); + loadDecodeGfx( tmpGfx, 0x0400000 / 2, i*2 ); + } + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 6, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory((UINT8 *)RamSpr, + 0x800000, 0x83FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0x840000, 0x84FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0x860000, 0x86003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0x900000, 0x903FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0x840000, 0x84FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, pzlbowlReadWord); + SekSetReadByteHandler(0, pzlbowlReadByte); + SekSetWriteWordHandler(0, pzlbowlWriteWord); + SekSetWriteByteHandler(0, pzlbowlWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0; + sva_x = 16; + sva_y = 256; + + gfx_code_mask = 0x0400000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + DrvDoReset(); + + return 0; +} + +// -- penbros ----------------------------------------------------------- + +UINT8 __fastcall penbrosReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall penbrosReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x500300: return ~DrvInput[3]; // DIP 1 + case 0x500302: return ~DrvInput[4]; // DIP 2 + case 0x600000: return ~DrvInput[0]; // Player 1 + case 0x600002: return ~DrvInput[1]; // Player 2 + case 0x600004: return ~DrvInput[2]; // Coin + + case 0x600006: + //bprintf(PRINT_NORMAL, _T("watchdog_reset16_r\n")); + return 0xffff; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall penbrosWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall penbrosWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x500300: + case 0x500302: + case 0x500304: + case 0x500306: + case 0x500308: + case 0x50030A: + case 0x50030C: + case 0x50030E: + x1010_sound_bank_w( (sekAddress & 0xf) >> 1, wordValue ); + break; + case 0x600004: + //bprintf(PRINT_NORMAL, _T("Coin Counter %x\n"), wordValue); + break; +// default: +// bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +static INT32 penbrosInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0100000, 0x1000000, 0x0300000, 0x040000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0100000, 0x1000000, 0x0300000, 0x040000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load Gfx + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0400000); + for (INT32 i=0; i<3; i++) { + BurnLoadRom(tmpGfx, i+2, 1); + loadDecodeGfx( tmpGfx, 0x0400000 / 2, i*2 ); + } + BurnFree(tmpGfx); + + // Leave 1MB empty (addressable by the chip) + BurnLoadRom(X1010SNDROM + 0x100000, 5, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory(RamUnknown + 0x00000, + 0x210000, 0x23FFFF, SM_RAM); + SekMapMemory(RamUnknown + 0x30000, + 0x300000, 0x30FFFF, SM_RAM); + + SekMapMemory((UINT8 *)RamSpr, + 0xB00000, 0xB3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0xB40000, 0xB4FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, + 0xB60000, 0xB6003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, + 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(1, 0xA00000, 0xA03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xB40000, 0xB4FFFF, SM_WRITE); // Palette + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, penbrosReadWord); + SekSetReadByteHandler(0, penbrosReadByte); + SekSetWriteWordHandler(0, penbrosWriteWord); + SekSetWriteByteHandler(0, penbrosWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0; + sva_x = 0; + sva_y = 128; + + gfx_code_mask = 0x0400000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + DrvDoReset(); + + return 0; +} + +// -- gundamex ----------------------------------------------------------- + +void __fastcall gundamexWriteWord(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x70000c: // watchdog + case 0x800000: // coin lockout + return; + + case 0xe00010: + case 0xe00012: + case 0xe00014: + case 0xe00016: + case 0xe00018: + case 0xe0001a: + case 0xe0001c: + case 0xe0001e: + x1010_sound_bank_w( (address & 0x0f) >> 1, data ); + return; + + case 0xfffd0a: + EEPROMWrite(data & 0x02, data & 0x04, data & 0x01); + return; + } + + if ((address & 0xfffc00) == 0xfffc00) { + Tmp68301WriteWord(address, data); + return; + } +} + +void __fastcall gundamexWriteByte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffc00) == 0xfffc00) { + Tmp68301WriteByte(address, data); + return; + } +} + +UINT16 __fastcall gundamexReadWord(UINT32 address) +{ + switch (address) + { + case 0x600000: + return 0xff00 | DrvInput[3]; + + case 0x600002: + return 0xff00 | DrvInput[4]; + + case 0x700000: + return 0xffff ^ DrvInput[0]; + + case 0x700002: + return 0xffff ^ DrvInput[1]; + + case 0x700004: + return ((0xffff ^ DrvInput[2]) & ~0x20) | (DrvInput[7] & 0x20); + + case 0x700008: + return 0xffff ^ DrvInput[5]; + + case 0x70000a: + return 0xffff ^ DrvInput[6]; + + case 0xfffd0a: + return ((EEPROMRead() & 1)) << 3; + } + + if ((address & 0xfffc00) == 0xfffc00) { + return RamTMP68301[(address & 0x3ff) / 2]; + } + + return 0; +} + +static INT32 gundamexInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(0x0300000, 0x2000000, 0x0300000, 0x010000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(0x0300000, 0x2000000, 0x0300000, 0x010000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x100000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x200000, 4, 0); if (nRet != 0) return 1; + + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0600000); + nRet = BurnLoadRom(tmpGfx + 0x0000000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0200000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0400000, 7, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x600000 / 2, 0); + nRet = BurnLoadRom(tmpGfx + 0x0000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0200000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0400000, 10, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x600000 / 2, 2); + nRet = BurnLoadRom(tmpGfx + 0x0000000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0200000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(tmpGfx + 0x0400000, 13, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x600000 / 2, 4); + + BurnFree(tmpGfx); + + BurnLoadRom(X1010SNDROM + 0x100000, 14, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + SekMapMemory(Rom68K + 0x200000, 0x500000, 0x57FFFF, SM_ROM); // CPU 0 ROM + + SekMapMemory((UINT8 *)RamSpr, 0xc00000, 0xc3FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, 0xc40000, 0xc4FFFF, SM_ROM); // Palette + SekMapMemory(RamUnknown + 0x00000, 0xc50000, 0xc5FFFF, SM_RAM); + SekMapMemory((UINT8 *)RamVReg, 0xc60000, 0xc6003F, SM_RAM); // Video Registers + + SekMapHandler(1, 0xb00000, 0xb03FFF, SM_READ | SM_WRITE); + SekMapHandler(2, 0xc40000, 0xc4FFFF, SM_WRITE); + + SekSetReadWordHandler(0, gundamexReadWord); + //SekSetReadByteHandler(0, gundamexReadByte); + SekSetWriteWordHandler(0, gundamexWriteWord); + SekSetWriteByteHandler(0, gundamexWriteByte); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + // Hack to skip black screen on EEPROM failure + //*((UINT16*)(Rom68K + 0x00f98)) = 0x4e71; + + yoffset = 0; + sva_x = 0; + sva_y = 256; + + gfx_code_mask = 0x0800000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + EEPROMInit(&eeprom_interface_93C46); + + DrvDoReset(); + + return 0; +} + +// -- samshoot ----------------------------------------------------------- + +void __fastcall samshootWriteWord(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff0) == 0x400300) { + x1010_sound_bank_w( (address & 0x0f) >> 1, data ); + return; + } +} + +UINT16 __fastcall samshootReadWord(UINT32 address) +{ + switch (address) + { + case 0x400000: + return 0xff00 | DrvInput[6]; + + case 0x400002: + return 0xff00 | DrvInput[0]; + + case 0x500000: + return DrvAnalogInput[0] | (DrvAnalogInput[1] << 8); + + case 0x580000: + return DrvAnalogInput[2] | (DrvAnalogInput[3] << 8); + + case 0x700000: + return 0xff00 | DrvInput[1]; + + case 0x700002: + return 0xff00 | DrvInput[2]; + + case 0x700004: + return 0xff00 | DrvInput[3]; + + case 0x700006: + return 0; // watchdog + + case 0xfffd0a: + return 0xff00 | DrvInput[7]; + } + + return 0; +} + +static INT32 samshootInit() +{ + INT32 nRet; + + HasNVRam = 1; + + Mem = NULL; + MemIndex(0x0200000, 0x2000000, 0x0500000, 0x010000); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(0x0200000, 0x2000000, 0x0500000, 0x010000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000000, 1, 2); if (nRet != 0) return 1; + + UINT8 * tmpGfx = (UINT8 *)BurnMalloc(0x0800000); + + nRet = BurnLoadRom(tmpGfx, 2, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x800000 / 2, 0); + nRet = BurnLoadRom(tmpGfx, 3, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x800000 / 2, 2); + nRet = BurnLoadRom(tmpGfx, 4, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x800000 / 2, 4); + nRet = BurnLoadRom(tmpGfx, 5, 1); if (nRet != 0) return 1; + loadDecodeGfx(tmpGfx, 0x800000 / 2, 6); + + BurnFree(tmpGfx); + + BurnLoadRom(X1010SNDROM + 0x100000, 6, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram68K, 0x200000, 0x20FFFF, SM_RAM); // CPU 0 RAM + + SekMapMemory(RamNV + 0x00000, 0x300000, 0x30FFFF, SM_RAM); + + SekMapMemory((UINT8 *)RamSpr, 0x800000, 0x83FFFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, 0x840000, 0x84FFFF, SM_ROM); // Palette + SekMapMemory((UINT8 *)RamVReg, 0x860000, 0x86003F, SM_RAM); // Video Registers + SekMapMemory((UINT8 *)RamTMP68301, 0xFFFC00, 0xFFFFFF, SM_ROM); // TMP68301 Registers + + SekMapHandler(2, 0x840000, 0x84FFFF, SM_WRITE); // Palette + SekMapHandler(1, 0x900000, 0x903FFF, SM_READ | SM_WRITE); + SekMapHandler(3, 0xFFFC00, 0xFFFFFF, SM_WRITE); + + SekSetReadWordHandler(0, samshootReadWord); + SekSetWriteWordHandler(0, samshootWriteWord); + + SekSetReadWordHandler (1, setaSoundRegReadWord); + SekSetReadByteHandler (1, setaSoundRegReadByte); + SekSetWriteWordHandler(1, setaSoundRegWriteWord); + SekSetWriteByteHandler(1, setaSoundRegWriteByte); + + SekSetWriteWordHandler(2, grdiansPaletteWriteWord); + SekSetWriteByteHandler(2, grdiansPaletteWriteByte); + + SekSetWriteWordHandler(3, Tmp68301WriteWord); + SekSetWriteByteHandler(3, Tmp68301WriteByte); + + SekSetIrqCallback( grdiansSekIrqCallback ); + + SekClose(); + } + + GenericTilesInit(); + + yoffset = 0; + sva_x = 64; + sva_y = 64; + + gfx_code_mask = 0x0800000 * 4 / 64; + + x1010_sound_init(50000000 / 3, 0x0000); + + BurnGunInit(2, true); + + DrvDoReset(); + + return 0; +} + + +static INT32 grdiansExit() +{ + SekExit(); + x1010_exit(); + + GenericTilesExit(); + + BurnFree(Mem); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gundamex")) { + EEPROMExit(); + } + + BurnGunExit(); + + HasNVRam = 0; + +// bMahjong = 0; + + return 0; +} + + +#define DRAWGFX( op ) \ + code %= gfx_code_mask; /* I hate to use a modulo, but myangel2 needs it */ \ + if (!code) return; \ + sx -= sva_x; \ + sy -= sva_y; \ + \ + if (sx <= -8) return; \ + if (sx >= nScreenWidth) return; \ + if (sy <= -8) return; \ + if (sy >= nScreenHeight) return; \ + \ + UINT16 * pd = pTransDraw; \ + UINT8 * ps = RomGfx + (code << 6); \ + \ + if (sx < 0 || sx > nScreenWidth - 8 || sy < 0 || sy > nScreenHeight - 8) { \ + if ( flipy ) { \ + pd += (sy + 7) * nScreenWidth + sx; \ + if ( flipx ) { \ + for (INT32 i=7;i>=0;i--,pd-=nScreenWidth) \ + if ( sy+i < 0 || sy+i >= nScreenHeight ) \ + ps += 8; \ + else \ + for (INT32 j=7;j>=0;j--,ps++) { \ + UINT8 c = op; \ + if ( c && sx+j >= 0 && sx+j < nScreenWidth ) \ + *(pd + j) = c | color; \ + } \ + } else \ + for (INT32 i=7;i>=0;i--,pd-=nScreenWidth) \ + if ( sy+i < 0 || sy+i >= nScreenHeight ) \ + ps += 8; \ + else \ + for (INT32 j=0;j<8;j++,ps++) { \ + UINT8 c = op; \ + if ( c && sx+j >= 0 && sx+j < nScreenWidth ) \ + *(pd + j) = c | color; \ + } \ + } else { \ + pd += sy * nScreenWidth + sx; \ + if ( flipx ) { \ + for (INT32 i=0;i<8;i++,pd+=nScreenWidth) \ + if ( sy+i < 0 || sy+i >= nScreenHeight ) \ + ps += 8; \ + else \ + for (INT32 j=7;j>=0;j--,ps++) { \ + UINT8 c = op; \ + if ( c && sx+j >= 0 && sx+j < nScreenWidth ) \ + *(pd + j) = c | color; \ + } \ + } else \ + for (INT32 i=0;i<8;i++,pd+=nScreenWidth) \ + if ( sy+i < 0 || sy+i >= nScreenHeight ) \ + ps += 8; \ + else \ + for (INT32 j=0;j<8;j++,ps++) { \ + UINT8 c = op; \ + if ( c && sx+j >= 0 && sx+j < nScreenWidth ) \ + *(pd + j) = c | color; \ + } \ + } \ + return; \ + } \ + \ + \ + if ( flipy ) { \ + pd += (sy + 7) * nScreenWidth + sx; \ + if ( flipx ) \ + for (INT32 i=0;i<8;i++,pd-=nScreenWidth) \ + for (INT32 j=7;j>=0;j--,ps++) { \ + UINT8 c = op; \ + if ( c ) *(pd + j) = c | color; \ + } \ + else \ + for (INT32 i=0;i<8;i++,pd-=nScreenWidth) \ + for (INT32 j=0;j<8;j++,ps++) { \ + UINT8 c = op; \ + if ( c ) *(pd + j) = c | color; \ + } \ + } else { \ + pd += sy * nScreenWidth + sx; \ + if ( flipx ) \ + for (INT32 i=0;i<8;i++,pd+=nScreenWidth) \ + for (INT32 j=7;j>=0;j--,ps++) { \ + UINT8 c = op; \ + if ( c ) *(pd + j) = c | color; \ + } \ + else \ + for (INT32 i=0;i<8;i++,pd+=nScreenWidth) \ + for (INT32 j=0;j<8;j++,ps++) { \ + UINT8 c = op; \ + if ( c ) *(pd + j) = c | color; \ + } \ + } \ + + +static void drawgfx0(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 4bpp tiles (----3210) + DRAWGFX( *ps & 0x0f ); +} + +static void drawgfx1(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 4bpp tiles (3210----) + DRAWGFX( *ps >> 4 ); +} + +static void drawgfx2(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 6bpp tiles (--543210) + DRAWGFX( *ps & 0x3f ); +} + +static void drawgfx3(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 8bpp tiles (76543210) + DRAWGFX( *ps ); +} + +static void drawgfx4(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 3bpp tiles? (-----210) + DRAWGFX( *ps & 0x07 ); +} + +static void drawgfx5(UINT32 code,UINT32 color,INT32 flipx,INT32 flipy,INT32 sx,INT32 sy) +{ + // 2bpp tiles??? (--10----) + DRAWGFX( (*ps >> 4) & 0x03 ); +} + +static void drawgfxN(UINT32,UINT32,INT32,INT32,INT32,INT32) +{ + // unknown +} + +typedef void (*pDrawgfx)(UINT32,UINT32,INT32,INT32,INT32,INT32); + +static void DrvDraw() +{ + if (bRecalcPalette) { + for (INT32 i=0;i<0x08000; i++) + CurPal[i] = CalcCol( RamPal[i] ); + bRecalcPalette = 0; + } + +// memset(pBurnDraw, 0, nScreenWidth * nScreenHeight * 2); + BurnTransferClear(); + + if (RamVReg[0x30/2] & 1) { // Blank Screen + memcpy(RamSprBak, RamSpr, 0x040000); + return; + } + + UINT16 *s1 = RamSprBak + 0x3000 / 2; + UINT16 *end = RamSprBak + 0x040000 / 2; + + for ( ; s1 < end; s1+=4 ) { + INT32 num = s1[0]; + INT32 xoffs = s1[1]; + INT32 yoffs = s1[2]; + INT32 sprite = s1[3]; + pDrawgfx drawgfx = drawgfxN; + + // Single-sprite address + UINT16 *s2 = RamSprBak + (sprite & 0x7fff) * 4; + + // Single-sprite tile size + INT32 global_sizex = xoffs & 0x0c00; + INT32 global_sizey = yoffs & 0x0c00; + + INT32 use_global_size = num & 0x1000; + + xoffs &= 0x3ff; + yoffs &= 0x3ff; + + // Color depth + switch (num & 0x0700) + { + case 0x0700: // 8bpp tiles (76543210) + drawgfx = drawgfx3; break; + case 0x0600: // 6bpp tiles (--543210) (myangel sliding blocks test) + drawgfx = drawgfx2; break; + case 0x0500: // 4bpp tiles (3210----) + drawgfx = drawgfx1; break; + case 0x0400: // 4bpp tiles (----3210) + drawgfx = drawgfx0; break; + case 0x0200: // 3bpp tiles? (-----210) (myangel "Graduate Tests") + drawgfx = drawgfx4; break; + case 0x0100: // 2bpp tiles??? (--10----) (myangel2 question bubble, myangel endgame) + drawgfx = drawgfx5; break; + case 0x0000: // no idea! + drawgfx = drawgfx0; break; + //default: + //bprintf(PRINT_NORMAL, _T("unknown gfxset %x\n"), (num & 0x0700)>>8 ); + // drawgfx = drawgfxN; + } + + // Number of single-sprites + num = (num & 0x00ff) + 1; + + for( ; num > 0; num--,s2+=4 ) { + if (s2 >= end) break; + + if (sprite & 0x8000) { + // "tilemap" sprite + INT32 clip_min_y; + INT32 clip_max_y; + INT32 clip_min_x; + INT32 clip_max_x; + + INT32 dx,x,y; + INT32 flipx; + INT32 flipy; + INT32 sx = s2[0]; + INT32 sy = s2[1]; + INT32 scrollx = s2[2]; + INT32 scrolly = s2[3]; + INT32 tilesize = (scrollx & 0x8000) >> 15; + INT32 page = (scrollx & 0x7c00) >> 10; + INT32 height = ((sy & 0xfc00) >> 10) + 1; + + sx &= 0x3ff; + sy &= 0x1ff; + scrollx &= 0x3ff; + scrolly &= 0x1ff; + + clip_min_y = (sy + yoffs) & 0x1ff; + clip_max_y = clip_min_y + height * 0x10 - 1; + if (clip_min_y > (sva_y + nScreenHeight - 1)) continue; + if (clip_max_y < sva_y) continue; + + clip_min_x = sva_x; + clip_max_x = sva_x + nScreenWidth - 1; + + if (clip_min_y < sva_y) clip_min_y = sva_y; + if (clip_max_y > (sva_y + nScreenHeight - 1)) clip_max_y = sva_y + nScreenHeight - 1; + + dx = sx + (scrollx & 0x3ff) + xoffs + 0x10; + + /* Draw the rows */ + /* I don't think the following is entirely correct (when using 16x16 + tiles x should probably loop from 0 to 0x20) but it seems to work + fine in all the games we have for now. */ + for (y = 0; y < (0x40 >> tilesize); y++) + { + INT32 py = ((scrolly - (y+1) * (8 << tilesize) + 0x10) & 0x1ff) - 0x10 - yoffset; + + if (py < clip_min_y - 0x10) continue; + if (py > clip_max_y) continue; + + for (x = 0; x < 0x40;x++) + { + INT32 px = ((dx + x * (8 << tilesize) + 0x10) & 0x3ff) - 0x10; + INT32 tx, ty; + INT32 attr, code, color; + UINT16 *s3; + + if (px < clip_min_x - 0x10) continue; + if (px > clip_max_x) continue; + + s3 = RamSprBak + 2 * ((page * 0x2000/4) + ((y & 0x1f) << 6) + (x & 0x03f)); + + attr = s3[0]; + code = s3[1] + ((attr & 0x0007) << 16); + flipx = (attr & 0x0010); + flipy = (attr & 0x0008); + color = (attr & 0xffe0) >> 5; + + if (tilesize) code &= ~3; + + for (ty = 0; ty <= tilesize; ty++) + for (tx = 0; tx <= tilesize; tx++) + drawgfx(code ^ tx ^ (ty<<1), color << 4, flipx, flipy, px + (flipx ? tilesize-tx : tx) * 8, py + (flipy ? tilesize-ty : ty) * 8 ); + } + } + + } else { + // "normal" sprite + INT32 sx = s2[0]; + INT32 sy = s2[1]; + INT32 attr = s2[2]; + INT32 code = s2[3] + ((attr & 0x0007) << 16); + INT32 flipx = (attr & 0x0010); + INT32 flipy = (attr & 0x0008); + INT32 color = (attr & 0xffe0) >> 5; + + INT32 sizex = use_global_size ? global_sizex : sx; + INT32 sizey = use_global_size ? global_sizey : sy; + INT32 x,y; + sizex = (1 << ((sizex & 0x0c00)>> 10))-1; + sizey = (1 << ((sizey & 0x0c00)>> 10))-1; + + + sx += xoffs; + sy += yoffs; + + sx = (sx & 0x1ff) - (sx & 0x200); + sy &= 0x1ff; + sy -= yoffset; + + code &= ~((sizex+1) * (sizey+1) - 1); // see myangel, myangel2 and grdians + + for (y = 0; y <= sizey; y++) + for (x = 0; x <= sizex; x++) + drawgfx( code++, color << 4, flipx, flipy, sx + (flipx ? sizex-x : x) * 8, sy + (flipy ? sizey-y : y) * 8 ); + + } + + } + if (s1[0] & 0x8000) break; // end of list marker + } + + BurnTransferCopy(CurPal); + + memcpy(RamSprBak, RamSpr, 0x040000); +} + + +#define M68K_CYCS_PER_FRAME (M68K_CYCS / 60) +#define SETA2_INTER_LEAVE 32 +#define M68K_CYCS_PER_INTER (M68K_CYCS_PER_FRAME / SETA2_INTER_LEAVE) + +static INT32 grdiansFrame() +{ + if (DrvReset) // Reset machine + DrvDoReset(); + + DrvInput[0] = 0x00; // Joy1 + DrvInput[1] = 0x00; // Joy2 + DrvInput[2] = 0x00; // Buttons + DrvInput[5] = 0x00; // Joy3 + DrvInput[6] = 0x00; // Joy4 +// DrvInput[7] = 0x00; // Joy5 + + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + DrvInput[5] |= (DrvJoy3[i] & 1) << i; + DrvInput[6] |= (DrvJoy4[i] & 1) << i; + DrvInput[6] |= (DrvJoy5[i] & 1) << i; + } + + INT32 nCyclesDone = 0; + INT32 nCyclesNext = 0; + INT32 nCyclesExec = 0; + + SekNewFrame(); + + SekOpen(0); + + for(INT32 i=0; i= tmp68301_timer[j]) { + // timer[j] timeout ! + tmp68301_timer[j] = 0; + tmp68301_timer_counter[j] = 0; + tmp68301_timer_callback(j); + } + } + } + + tmp68301_update_irq_state(0); + + SekClose(); + + if (pBurnDraw) + DrvDraw(); + + if (pBurnSoundOut) + x1010_sound_update(); + + return 0; +} + +static INT32 samshootDraw() +{ + DrvDraw(); + + for (INT32 i = 0; i < BurnDrvGetMaxPlayers(); i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } + + return 0; +} + +static INT32 samshootFrame() +{ + if (DrvReset) // Reset machine + DrvDoReset(); + + { + memset (DrvInput, 0xff, 5); + + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] ^= (DrvJoy1[i] & 1) << i; + DrvInput[1] ^= (DrvJoy2[i] & 1) << i; + DrvInput[2] ^= (DrvJoy3[i] & 1) << i; + DrvInput[3] ^= (DrvJoy4[i] & 1) << i; + DrvInput[4] ^= (DrvJoy5[i] & 1) << i; + } + + BurnGunMakeInputs(0, (INT16)DrvAxis[0], (INT16)DrvAxis[1]); + BurnGunMakeInputs(1, (INT16)DrvAxis[2], (INT16)DrvAxis[3]); + + float x0 = (320 - ((float)((BurnGunX[0] >> 8) + 8))) / 320 * 160; + float y0 = (240 - ((float)((BurnGunY[0] >> 8) + 8))) / 240 * 240; + float x1 = (320 - ((float)((BurnGunX[1] >> 8) + 8))) / 320 * 160; + float y1 = (240 - ((float)((BurnGunY[1] >> 8) + 8))) / 240 * 240; + DrvAnalogInput[0] = (UINT8)x0 + 36; + DrvAnalogInput[1] = (UINT8)y0 + 22; + DrvAnalogInput[2] = (UINT8)x1 + 36; + DrvAnalogInput[3] = (UINT8)y1 + 22; + } + + INT32 nCyclesDone = 0; + INT32 nCyclesNext = 0; + INT32 nCyclesExec = 0; + + SekNewFrame(); + + SekOpen(0); + + for(INT32 i=0; i= tmp68301_timer[j]) { + // timer[j] timeout ! + tmp68301_timer[j] = 0; + tmp68301_timer_counter[j] = 0; + tmp68301_timer_callback(j); + } + } + + if (i == 15) tmp68301_update_irq_state(2); + } + + tmp68301_update_irq_state(0); + + SekClose(); + + if (pBurnDraw) + samshootDraw(); + + if (pBurnSoundOut) + x1010_sound_update(); + + return 0; +} + +static INT32 grdiansScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) // Return minimum compatible version + *pnMin = 0x029671; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM && HasNVRam) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamNV; + ba.nLen = 0x10000; + ba.szName = "Backup Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + // Scan 68000 state + SekScan(nAction); + + x1010_scan(nAction, pnMin); + + BurnGunScan(); + + // Scan Input state + SCAN_VAR(DrvInput); + + // Scan TMP 68301 Chip state + SCAN_VAR(tmp68301_timer); + SCAN_VAR(tmp68301_timer_counter); + SCAN_VAR(tmp68301_irq_vector); + + if (nAction & ACB_WRITE) { + + // palette changed + bRecalcPalette = 1; + + // x1-010 bank changed + for (INT32 i=0; isound_banks[i] * 0x20000, 0x20000); + } + } + + return 0; +} + +struct BurnDriver BurnDrvGrdians = { + "grdians", NULL, NULL, NULL, "1995", + "Guardians\0Denjin Makai II\0", NULL, "Banpresto", "Newer Seta", + L"Guardians\0\u96FB\u795E\u9B54\u584A \uFF29\uFF29\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, grdiansRomInfo, grdiansRomName, NULL, NULL, grdiansInputInfo, grdiansDIPInfo, + grdiansInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 304, 232, 4, 3 +}; + +struct BurnDriver BurnDrvMj4simai = { + "mj4simai", NULL, NULL, NULL, "1996", + "Wakakusamonogatari Mahjong Yonshimai (Japan)\0", NULL, "Maboroshi Ware", "Newer Seta", + L"\u82E5\u8349\u7269\u8A9E \u9EBB\u96C0\u56DB\u59C9\u59B9 (Japan)\0Wakakusamonogatari Mahjong Yonshimai\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_MAHJONG, 0, + NULL, mj4simaiRomInfo, mj4simaiRomName, NULL, NULL, mj4simaiInputInfo, mj4simaiDIPInfo, + mj4simaiInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMyangel = { + "myangel", NULL, NULL, NULL, "1996", + "Kosodate Quiz My Angel (Japan)\0", NULL, "Namco", "Newer Seta", + L"\u5B50\u80B2\u3066\u30AF\u30A4\u30BA \u30DE\u30A4 \u30A8\u30F3\u30B8\u30A7\u30EB (Japan)\0Kosodate Quiz My Angel\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, myangelRomInfo, myangelRomName, NULL, NULL, myangelInputInfo, myangelDIPInfo, + myangelInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 376, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMyangel2 = { + "myangel2", NULL, NULL, NULL, "1996", + "Kosodate Quiz My Angel 2 (Japan)\0", NULL, "Namco", "Newer Seta", + L"\u5B50\u80B2\u3066\u30AF\u30A4\u30BA \u30DE\u30A4 \u30A8\u30F3\u30B8\u30A7\u30EB \uFF12 (Japan)\0Kosodate Quiz My Angel 2\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, myangel2RomInfo, myangel2RomName, NULL, NULL, myangelInputInfo, myangel2DIPInfo, + myangel2Init, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 376, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPzlbowl = { + "pzlbowl", NULL, NULL, NULL, "1999", + "Puzzle De Bowling (Japan)\0", NULL, "Nihon System / Moss", "Newer Seta", + L"Puzzle De Bowling\0\u30D1\u30BA\u30EB \uFF24\uFF25 \u30DC\u30FC\u30EA\u30F3\u30B0\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, pzlbowlRomInfo, pzlbowlRomName, NULL, NULL, grdiansInputInfo, pzlbowlDIPInfo, + pzlbowlInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPenbros = { + "penbros", NULL, NULL, NULL, "2000", + "Penguin Brothers (Japan)\0", NULL, "Subsino", "Newer Seta", + L"\u30DA\u30F3\u30AE\u30F3 \u30D6\u30E9\u30B6\u30FC\u30BA (Japan)\0Penguin Brothers\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, penbrosRomInfo, penbrosRomName, NULL, NULL, penbrosInputInfo, penbrosDIPInfo, + penbrosInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGundamex = { + "gundamex", NULL, NULL, NULL, "1994", + "Mobile Suit Gundam EX Revue\0", NULL, "Banpresto", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, gundamexRomInfo, gundamexRomName, NULL, NULL, GundamexInputInfo, GundamexDIPInfo, + gundamexInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDeerhunt = { + "deerhunt", NULL, NULL, NULL, "2000", + "Deer Hunting USA V4.3\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, deerhuntRomInfo, deerhuntRomName, NULL, NULL, DeerhuntInputInfo, DeerhuntDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDeerhuna = { + "deerhunta", "deerhunt", NULL, NULL, "2000", + "Deer Hunting USA V4.2\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, deerhunaRomInfo, deerhunaRomName, NULL, NULL, DeerhuntInputInfo, DeerhuntDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDeerhunb = { + "deerhuntb", "deerhunt", NULL, NULL, "2000", + "Deer Hunting USA V4.0\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, deerhunbRomInfo, deerhunbRomName, NULL, NULL, DeerhuntInputInfo, DeerhuntDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDeerhunc = { + "deerhuntc", "deerhunt", NULL, NULL, "2000", + "Deer Hunting USA V2\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, deerhuncRomInfo, deerhuncRomName, NULL, NULL, DeerhuntInputInfo, DeerhuntDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTurkhunt = { + "turkhunt", NULL, NULL, NULL, "2001", + "Turkey Hunting USA V1.0\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, turkhuntRomInfo, turkhuntRomName, NULL, NULL, DeerhuntInputInfo, TurkhuntDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWschamp = { + "wschamp", NULL, NULL, NULL, "2001", + "Wing Shooting Championship V2.00\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, wschampRomInfo, wschampRomName, NULL, NULL, WschampInputInfo, WschampDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWschampa = { + "wschampa", "wschamp", NULL, NULL, "2001", + "Wing Shooting Championship V1.01\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, wschampaRomInfo, wschampaRomName, NULL, NULL, WschampInputInfo, WschampDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTrophyh = { + "trophyh", NULL, NULL, NULL, "2002", + "Trophy Hunting - Bear & Moose V1.0\0", NULL, "Sammy USA Corporation", "Newer Seta", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, trophyhRomInfo, trophyhRomName, NULL, NULL, WschampInputInfo, TrophyhDIPInfo, + samshootInit, grdiansExit, samshootFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +static INT32 funcubeInit() +{ + return 1; +} + +struct BurnDriverD BurnDrvFuncube2 = { + "funcube2", NULL, NULL, NULL, "2001", + "Funcube 2 (v1.1)\0", "Unemulated Sub CPU", "Namco", "Newer Seta", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, funcube2RomInfo, funcube2RomName, NULL, NULL, grdiansInputInfo, grdiansDIPInfo, + funcubeInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; + +struct BurnDriverD BurnDrvFuncube4 = { + "funcube4", NULL, NULL, NULL, "2001", + "Funcube 4 (v1.0)\0", "Unemulated Sub CPU", "Namco", "Newer Seta", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, funcube4RomInfo, funcube4RomName, NULL, NULL, grdiansInputInfo, grdiansDIPInfo, + funcubeInit, grdiansExit, grdiansFrame, NULL, grdiansScan, &bRecalcPalette, 0x8000, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_shadfrce.cpp b/src/burn/drivers/misc_post90s/d_shadfrce.cpp new file mode 100644 index 00000000..21e4e0de --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_shadfrce.cpp @@ -0,0 +1,1601 @@ +/******************************************************************************** + Shadow Force (c)1993 Technos + Preliminary Driver by David Haywood + Based on the Various Other Technos Games + ******************************************************************************** + port to Finalburn Alpha by OopsWare. 2007 + ******************************************************************************** + + 2007.07.05 + bug fix: no reset while init driver, 68k boot from pc addr 0x000000 ... + add pri-buf (RamPri) for render + + ********************************************************************************/ + +#include "burnint.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +static UINT8 *Rom68K; +static UINT8 *RomZ80; +static UINT8 *RomGfx01; +static UINT8 *RomGfx02; +static UINT8 *RomGfx03; + +static UINT8 *Ram68K; +static UINT16 *RamBg00; +static UINT16 *RamBg01; +static UINT16 *RamFg; +static UINT16 *RamSpr; +static UINT16 *RamPal; +static UINT8 *RamZ80; + +static UINT16 *RamCurPal; +static UINT8 *RamPri; + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDipBtn[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +static UINT8 DrvInput[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvReset = 0; +static UINT8 nBrightness = 0xFF; + +static UINT8 bVBlink = 0; +static UINT16 bg0scrollx, bg0scrolly, bg1scrollx, bg1scrolly; +static UINT8 nSoundlatch = 0; +static UINT8 bRecalcPalette = 0; + +static INT32 nZ80Cycles; + +inline static void CalcCol(INT32 idx) +{ + /* xBBBBBGGGGGRRRRR */ + UINT16 nColour = RamPal[idx]; + INT32 r = (nColour & 0x001F) << 3; r |= r >> 5; // Red + INT32 g = (nColour & 0x03E0) >> 2; g |= g >> 5; // Green + INT32 b = (nColour & 0x7C00) >> 7; b |= b >> 5; // Blue + r = (r * nBrightness) >> 8; + g = (g * nBrightness) >> 8; + b = (b * nBrightness) >> 8; + RamCurPal[idx] = BurnHighCol(r, g, b, 0); +} + +static struct BurnInputInfo shadfrceInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvDipBtn + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvButton + 0, "p1 fire 4"}, + {"P1 Button 5", BIT_DIGITAL, DrvButton + 1, "p1 fire 5"}, + {"P1 Button 6", BIT_DIGITAL, DrvButton + 2, "p1 fire 6"}, + + {"P2 Coin", BIT_DIGITAL, DrvDipBtn + 1, "p2 coin"}, // only available when you are in "test mode" + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvButton + 3, "p2 fire 4"}, + {"P2 Button 5", BIT_DIGITAL, DrvButton + 4, "p2 fire 5"}, + {"P2 Button 6", BIT_DIGITAL, DrvButton + 5, "p2 fire 6"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 1, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, + {"Dip D", BIT_DIPSWITCH, DrvInput + 7, "dip"}, +}; + +STDINPUTINFO(shadfrce) + +static struct BurnDIPInfo shadfrceDIPList[] = { + + // Defaults + {0x19, 0xFF, 0xFF, 0x00, NULL}, + {0x1A, 0xFF, 0xFF, 0x00, NULL}, + {0x1B, 0xFF, 0xFF, 0x00, NULL}, + {0x1C, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + // coin 1 + // coin 2 + {0, 0xFE, 0, 2, "Service1"}, // only available when you are in "test mode" + {0x19, 0x01, 0x04, 0x00, "Off"}, + {0x19, 0x01, 0x04, 0x04, "On"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x1A, 0x01, 0x03, 0x00, "Normal"}, + {0x1A, 0x01, 0x03, 0x01, "Hard"}, + {0x1A, 0x01, 0x03, 0x02, "Easy"}, + {0x1A, 0x01, 0x03, 0x03, "Hardest"}, + {0, 0xFE, 0, 4, "Stage Clear Energy Regain"}, + {0x1A, 0x01, 0x0C, 0x00, "25%"}, + {0x1A, 0x01, 0x0C, 0x04, "10%"}, + {0x1A, 0x01, 0x0C, 0x08, "50%"}, + {0x1A, 0x01, 0x0C, 0x0C, "0%"}, + + // DIP 3 + {0, 0xFE, 0, 4, "Coinage"}, + {0x1B, 0x01, 0x06, 0x00, "1C_1C"}, + {0x1B, 0x01, 0x06, 0x02, "1C_2C"}, + {0x1B, 0x01, 0x06, 0x04, "2C_1C"}, + {0x1B, 0x01, 0x06, 0x06, "3C_1C"}, + + {0, 0xFE, 0, 2, "Continue Price"}, + {0x1B, 0x01, 0x08, 0x00, "Off"}, + {0x1B, 0x01, 0x08, 0x80, "On"}, + {0, 0xFE, 0, 2, "Free Play"}, + {0x1B, 0x01, 0x10, 0x00, "Off"}, + {0x1B, 0x01, 0x10, 0x10, "On"}, + {0, 0xFE, 0, 2, "Flip Screen"}, + {0x1B, 0x01, 0x20, 0x00, "Off"}, + {0x1B, 0x01, 0x20, 0x20, "On"}, + + // DIP 4 + {0, 0xFE, 0, 2, "Demo Sounds"}, + {0x1C, 0x01, 0x01, 0x00, "Off"}, + {0x1C, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Test Mode"}, + {0x1C, 0x01, 0x02, 0x00, "Off"}, + {0x1C, 0x01, 0x02, 0x02, "On"}, +// {0, 0xFE, 0, 2, "VBlink"}, // ??? +// {0x1C, 0x01, 0x04, 0x00, "Off"}, +// {0x1C, 0x01, 0x04, 0x04, "On"}, + +}; + +STDDIPINFO(shadfrce) + +// Rom information +static struct BurnRomInfo shadfrceRomDesc[] = { + { "32a12-01.34", 0x040000, 0x04501198, BRF_ESS | BRF_PRG }, // 68000 code + { "32a13-01.26", 0x040000, 0xb8f8a05c, BRF_ESS | BRF_PRG }, + { "32a14-0.33", 0x040000, 0x08279be9, BRF_ESS | BRF_PRG }, + { "32a15-0.14", 0x040000, 0xbfcadfea, BRF_ESS | BRF_PRG }, + + { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code + + { "32a11-0.55", 0x020000, 0xcfaf5e77, BRF_GRA }, // gfx 1 chars + + { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite + { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA }, + { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA }, + { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA }, + { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA }, + + { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg + { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA }, + { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA }, + + { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM +}; + +STD_ROM_PICK(shadfrce) +STD_ROM_FN(shadfrce) + +static struct BurnRomInfo shadfrcjRomDesc[] = { + { "32a12-011.34", 0x040000, 0x0c041e08, BRF_ESS | BRF_PRG }, // 68000 code + { "32a13-010.26", 0x040000, 0x00985361, BRF_ESS | BRF_PRG }, + { "32a14-010.33", 0x040000, 0xea03ca25, BRF_ESS | BRF_PRG }, + { "32j15-01.14", 0x040000, 0x3dc3a84a, BRF_ESS | BRF_PRG }, + + { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code + + { "32j11-0.55", 0x020000, 0x7252d993, BRF_GRA }, // gfx 1 chars + + { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite + { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA }, + { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA }, + { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA }, + { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA }, + + { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg + { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA }, + { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA }, + + { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM +}; + +STD_ROM_PICK(shadfrcj) +STD_ROM_FN(shadfrcj) + +static struct BurnRomInfo shadfrcjv2RomDesc[] = { + { "32j12-01.34", 0x040000, 0x38fdbe1d, BRF_ESS | BRF_PRG }, // 68000 code + { "32j13-01.26", 0x040000, 0x6e1df6f1, BRF_ESS | BRF_PRG }, + { "32j14-01.33", 0x040000, 0x89e3fb60, BRF_ESS | BRF_PRG }, + { "32j15-01.14", 0x040000, 0x3dc3a84a, BRF_ESS | BRF_PRG }, + + { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code + + { "32j11-0.55", 0x020000, 0x7252d993, BRF_GRA }, // gfx 1 chars + + { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite + { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA }, + { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA }, + { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA }, + { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA }, + + { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg + { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA }, + { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA }, + + { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM +}; + +STD_ROM_PICK(shadfrcjv2) +STD_ROM_FN(shadfrcjv2) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom68K = Next; Next += 0x100000; // 68000 ROM + RomZ80 = Next; Next += 0x010000; // Z80 ROM + RomGfx01 = Next; Next += 0x020000 / 4 * 8; // fg 8x8x4 + RomGfx02 = Next; Next += 0xA00000 / 5 * 8; // spr 16x16x5 sprite + RomGfx03 = Next; Next += 0x300000 / 6 * 8; // bg 16x16x6 tile + MSM6295ROM = Next; Next += 0x080000; + + RamStart = Next; + RamBg00 = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16); + RamBg01 = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16); + RamFg = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16); + RamSpr = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16); + RamPal = (UINT16 *) Next; Next += 0x004000 * sizeof(UINT16); + Ram68K = Next; Next += 0x010000; + RamZ80 = Next; Next += 0x001800; + RamEnd = Next; + + RamCurPal = (UINT16 *) Next; Next += 0x004000 * sizeof(UINT16); + RamPri = Next; Next += 0x014000; // 320x256 Priority Buffer + + MemEnd = Next; + return 0; +} + +UINT8 __fastcall shadfrceReadByte(UINT32 sekAddress) +{ +/* + INP0 : --AABBBB CCCCCCCC : DIP2-8 DIP2-7, coin 1 coin 2 service 1 , player 1 + INP1 : --DDDDDD EEEEEEEE : Difficulty but DIP2-8 DIP2-7, player 2 + INP2 : --FFFFFF GGGGGGGG : Coinage ~ Flip_Screen but Demo_Sounds service, button 4~6 + INP3 : ----HHII ???????? : v-blink? , service Demo_Sounds +*/ + switch (sekAddress) { + case 0x1D0020: + return (~DrvInput[1] & 0x3F); + case 0x1D0021: + return ~DrvInput[0]; + case 0x1D0022: + return (~DrvInput[3] & 0x3F); + case 0x1D0023: + return ~DrvInput[2]; + case 0x1D0024: + return (~DrvInput[5] & 0x3F); + case 0x1D0025: + return ~DrvInput[4]; + case 0x1D0026: + return ~(DrvInput[7] | (bVBlink << 2)) /*& 0x0F*/; + case 0x1D0027: + return ~DrvInput[6]; + + case 0x1C000B: + return 0; + case 0x1D000D: + return nBrightness; + default: + bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall shadfrceReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x1D0020: + return ~(DrvInput[0] | (DrvInput[1] << 8)) & 0x3FFF; + case 0x1D0022: + return ~(DrvInput[2] | (DrvInput[3] << 8)) & 0x3FFF; + case 0x1D0024: + return ~(DrvInput[4] | (DrvInput[5] << 8)) & 0x3FFF; + case 0x1D0026: + return ~(DrvInput[6] | ( (DrvInput[7] | (bVBlink << 2))<< 8)) /*& 0x0FFF*/; + default: + bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall shadfrceWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x1C000B: + // shadfrce_flip_screen + break; + case 0x1D000C: +// bprintf(PRINT_NORMAL, _T("sound write %02x\n"), byteValue); + nSoundlatch = byteValue; + ZetNmi(); + break; + case 0x1D000D: + //bprintf(PRINT_NORMAL, _T("Brightness set to %02x\n"), byteValue); + nBrightness = byteValue; + for(INT32 i=0;i<0x4000;i++) CalcCol(i); + break; + + case 0x1C0009: + case 0x1C000D: + case 0x1D0007: + case 0x1D0009: + case 0x1D0011: + case 0x1D0013: + case 0x1D0015: + case 0x1D0017: // NOP + break; + default: + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + + } +} + +void __fastcall shadfrceWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x1C0000: bg0scrollx = wordValue & 0x1FF; break; + case 0x1C0002: bg0scrolly = wordValue & 0x1FF; break; + case 0x1C0004: bg1scrollx = wordValue & 0x1FF; break; + case 0x1C0006: bg1scrolly = wordValue & 0x1FF; break; + + case 0x1D000D: + bprintf(PRINT_NORMAL, _T("Brightness set to %04x\n"), wordValue); + //nBrightness = byteValue; + break; + case 0x1D0016: + // wait v-blink dip change call back ??? + //bprintf(PRINT_NORMAL, _T("v-blink clear at PC 0x%06x\n"), SekGetPC(0) ); + break; + + case 0x1D0000: // NOP + case 0x1D0002: + case 0x1D0006: + case 0x1D0008: + break; + default: + bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + + } +} + +/* +void __fastcall shadfrceWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + //CavePalWriteByte(sekAddress & 0xFFFF, byteValue); + bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to palette %x\n"), byteValue, sekAddress); +} +*/ + +void __fastcall shadfrceWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress &= 0x7FFF; + sekAddress >>= 1; + RamPal[sekAddress] = wordValue; + CalcCol(sekAddress); +} + +UINT8 __fastcall shadfrceZRead(UINT16 a) +{ + switch (a) { + case 0xC801: // YM2151_status_port_0_r + //bprintf(PRINT_NORMAL, _T("YM2151_status_port_0_r\n")); + return BurnYM2151ReadStatus(); + case 0xD800: // OKIM6295_status_0_r + //bprintf(PRINT_NORMAL, _T("OKIM6295_status_0_r\n")); + return MSM6295ReadStatus(0); + case 0xE000: // soundlatch_r + //bprintf(PRINT_NORMAL, _T("Soundlatch_r\n")); + return nSoundlatch; +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a); + } + return 0; +} + +void __fastcall shadfrceZWrite(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xC800: // YM2151_register_port_0_w + //bprintf(PRINT_NORMAL, _T("BurnYM2151SelectRegister(%02x)\n"), d); + BurnYM2151SelectRegister(d); + break; + case 0xC801: // YM2151_data_port_0_w + //bprintf(PRINT_NORMAL, _T("BurnYM2151WriteRegister(%02x)\n"), d); + BurnYM2151WriteRegister(d); + break; + case 0xD800: // OKIM6295_data_0_w + //bprintf(PRINT_NORMAL, _T("MSM6295Command(%02x)\n"), d); + MSM6295Command(0, d); + break; + case 0xE800: // oki_bankswitch_w + bprintf(PRINT_NORMAL, _T("oki_bankswitch_w(%02X)\n"), d); + break; +// default: +// bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d); + } +} + +static void shadfrceYM2151IRQHandler(INT32 nStatus) +{ + if (nStatus) { + //ZetRaiseIrq(255); + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + ZetRun(0x0400); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 loadDecodeGfx01() +{ +/* + 8,8, + RGN_FRAC(1,1), + 4, + { 0, 2, 4, 6 }, + { 1, 0, 8*8+1, 8*8+0, 16*8+1, 16*8+0, 24*8+1, 24*8+0 }, + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, + 32*8 +*/ + UINT8 *buf = NULL; + + if ((buf = (UINT8*)BurnMalloc(0x20000)) == NULL) { + return 1; + } + + memset(buf, 0, 0x20000); + BurnLoadRom(buf, 5, 1); + + UINT8 *tmp = buf; + UINT8 *pgfx = RomGfx01; + + for (INT32 i=0; i<(0x20000/32); i++) { + for( INT32 y=0;y<8;y++) { + + pgfx[0] = (((tmp[ 0]>>0)&1)<<0) | (((tmp[ 0]>>2)&1)<<1) | (((tmp[ 0]>>4)&1)<<2) | (((tmp[ 0]>>6)&1)<<3); + pgfx[1] = (((tmp[ 0]>>1)&1)<<0) | (((tmp[ 0]>>3)&1)<<1) | (((tmp[ 0]>>5)&1)<<2) | (((tmp[ 0]>>7)&1)<<3); + pgfx[2] = (((tmp[ 8]>>0)&1)<<0) | (((tmp[ 8]>>2)&1)<<1) | (((tmp[ 8]>>4)&1)<<2) | (((tmp[ 8]>>6)&1)<<3); + pgfx[3] = (((tmp[ 8]>>1)&1)<<0) | (((tmp[ 8]>>3)&1)<<1) | (((tmp[ 8]>>5)&1)<<2) | (((tmp[ 8]>>7)&1)<<3); + pgfx[4] = (((tmp[16]>>0)&1)<<0) | (((tmp[16]>>2)&1)<<1) | (((tmp[16]>>4)&1)<<2) | (((tmp[16]>>6)&1)<<3); + pgfx[5] = (((tmp[16]>>1)&1)<<0) | (((tmp[16]>>3)&1)<<1) | (((tmp[16]>>5)&1)<<2) | (((tmp[16]>>7)&1)<<3); + pgfx[6] = (((tmp[24]>>0)&1)<<0) | (((tmp[24]>>2)&1)<<1) | (((tmp[24]>>4)&1)<<2) | (((tmp[24]>>6)&1)<<3); + pgfx[7] = (((tmp[24]>>1)&1)<<0) | (((tmp[24]>>3)&1)<<1) | (((tmp[24]>>5)&1)<<2) | (((tmp[24]>>7)&1)<<3); + + tmp += 1; + pgfx += 8; + } + tmp += 24; + } + + BurnFree(buf); + return 0; +} + +static INT32 loadDecodeGfx02() +{ +/* + 16,16, + RGN_FRAC(1,5), + 5, + { 0x800000*8, 0x600000*8, 0x400000*8, 0x200000*8, 0x000000*8 }, + { 0,1,2,3,4,5,6,7,16*8+0,16*8+1,16*8+2,16*8+3,16*8+4,16*8+5,16*8+6,16*8+7 }, + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }, + 16*16 +*/ + UINT8 *buf = NULL; + + if ((buf = (UINT8*)BurnMalloc(0xA00000)) == NULL) { + return 1; + } + memset(buf, 0, 0xA00000); + + BurnLoadRom(buf + 0x000000, 6, 1); + BurnLoadRom(buf + 0x200000, 7, 1); + BurnLoadRom(buf + 0x400000, 8, 1); + BurnLoadRom(buf + 0x600000, 9, 1); + BurnLoadRom(buf + 0x800000, 10, 1); + + UINT8 *tmp1 = buf; + UINT8 *tmp2 = tmp1 + 0x200000; + UINT8 *tmp3 = tmp2 + 0x200000; + UINT8 *tmp4 = tmp3 + 0x200000; + UINT8 *tmp5 = tmp4 + 0x200000; + UINT8 *pgfx = RomGfx02; + +// TODO: be lazy to research how BurnProgresser work, so ... + +// BurnSetProgressRange(1.0); + + for (INT32 i=0; i<(0x200000/32); i++) { + for( INT32 y=0;y<16;y++) { + + for(INT32 x=0;x<8;x++) { + pgfx[(7-x)+0] = (((tmp1[ 0] >> x) & 0x01) << 0) | + (((tmp2[ 0] >> x) & 0x01) << 1) | + (((tmp3[ 0] >> x) & 0x01) << 2) | + (((tmp4[ 0] >> x) & 0x01) << 3) | + (((tmp5[ 0] >> x) & 0x01) << 4); + pgfx[(7-x)+8] = (((tmp1[16] >> x) & 0x01) << 0) | + (((tmp2[16] >> x) & 0x01) << 1) | + (((tmp3[16] >> x) & 0x01) << 2) | + (((tmp4[16] >> x) & 0x01) << 3) | + (((tmp5[16] >> x) & 0x01) << 4); + } + tmp1 += 1; + tmp2 += 1; + tmp3 += 1; + tmp4 += 1; + tmp5 += 1; + pgfx += 16; + } + +// if ((i & 0xFFF) == 0) +// BurnUpdateProgress( 1.0 / 16, i ? NULL : _T("Decodeing graphics..."), 1); + + tmp1 += 16; + tmp2 += 16; + tmp3 += 16; + tmp4 += 16; + tmp5 += 16; + } + + BurnFree(buf); + return 0; +} + +static INT32 loadDecodeGfx03() +{ +/* + 16,16, + RGN_FRAC(1,3), + 6, + { 0x000000*8+8, 0x000000*8+0, 0x100000*8+8, 0x100000*8+0, 0x200000*8+8, 0x200000*8+0 }, + { 0, 1, 2, 3, 4, 5, 6, 7,16*16+0,16*16+1,16*16+2,16*16+3,16*16+4,16*16+5,16*16+6,16*16+7 }, + { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16,9*16,10*16,11*16,12*16,13*16,14*16,15*16 }, + 64*8 +*/ + UINT8 *buf = NULL; + + if ((buf = (UINT8*)BurnMalloc(0x300000)) == NULL) { + return 1; + } + memset(buf, 0, 0x300000); + + BurnLoadRom(buf + 0x000000, 11, 1); + BurnLoadRom(buf + 0x100000, 12, 1); + BurnLoadRom(buf + 0x200000, 13, 1); + + UINT8 *tmp1 = buf; + UINT8 *tmp2 = tmp1 + 0x100000; + UINT8 *tmp3 = tmp2 + 0x100000; + UINT8 *pgfx = RomGfx03; + + for (INT32 i=0; i<(0x100000/64); i++) { + for( INT32 y=0;y<16;y++) { + + for(INT32 x=0;x<8;x++) { + pgfx[(7-x)+0] = (((tmp3[ 0] >> x) & 0x01) << 0) | (((tmp3[ 1] >> x) & 0x01) << 1) | + (((tmp2[ 0] >> x) & 0x01) << 2) | (((tmp2[ 1] >> x) & 0x01) << 3) | + (((tmp1[ 0] >> x) & 0x01) << 4) | (((tmp1[ 1] >> x) & 0x01) << 5); + pgfx[(7-x)+8] = (((tmp3[32] >> x) & 0x01) << 0) | (((tmp3[33] >> x) & 0x01) << 1) | + (((tmp2[32] >> x) & 0x01) << 2) | (((tmp2[33] >> x) & 0x01) << 3) | + (((tmp1[32] >> x) & 0x01) << 4) | (((tmp1[33] >> x) & 0x01) << 5); + } + tmp1 += 2; + tmp2 += 2; + tmp3 += 2; + pgfx += 16; + } + tmp1 += 32; + tmp2 += 32; + tmp3 += 32; + } + + BurnFree(buf); + + return 0; +} + +static INT32 shadfrceInit() +{ + INT32 nRet; + + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); // blank all memory + MemIndex(); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(Rom68K + 0x000000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x000001, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x080000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Rom68K + 0x080001, 3, 2); if (nRet != 0) return 1; + + nRet = BurnLoadRom(RomZ80 + 0x000000, 4, 1); if (nRet != 0) return 1; + + loadDecodeGfx01(); + loadDecodeGfx02(); + loadDecodeGfx03(); + + BurnLoadRom(MSM6295ROM, 14, 1); + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + + SekMapMemory((UINT8 *)RamBg00, + 0x100000, 0x101FFF, SM_RAM); // b ground 0 + SekMapMemory((UINT8 *)RamBg01, + 0x102000, 0x103FFF, SM_RAM); // b ground 1 + SekMapMemory((UINT8 *)RamFg, + 0x140000, 0x141FFF, SM_RAM); // f ground + SekMapMemory((UINT8 *)RamSpr, + 0x142000, 0x143FFF, SM_RAM); // sprites + SekMapMemory((UINT8 *)RamPal, + 0x180000, 0x187FFF, SM_ROM); // palette + SekMapMemory(Ram68K, 0x1F0000, 0x1FFFFF, SM_RAM); // 68K RAM + + SekMapHandler(1, 0x180000, 0x187FFF, SM_WRITE); + + + SekSetReadWordHandler(0, shadfrceReadWord); + SekSetReadByteHandler(0, shadfrceReadByte); + SekSetWriteWordHandler(0, shadfrceWriteWord); + SekSetWriteByteHandler(0, shadfrceWriteByte); + + //SekSetWriteByteHandler(1, shadfrceWriteBytePalette); + SekSetWriteWordHandler(1, shadfrceWriteWordPalette); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + + ZetSetReadHandler(shadfrceZRead); + ZetSetWriteHandler(shadfrceZWrite); + //ZetSetInHandler(shadfrceZIn); + //ZetSetOutHandler(shadfrceZOut); + + // ROM bank 1 + ZetMapArea(0x0000, 0xBFFF, 0, RomZ80); + ZetMapArea(0x0000, 0xBFFF, 2, RomZ80); + + // RAM + ZetMapArea(0xC000, 0xC7FF, 0, RamZ80); + ZetMapArea(0xC000, 0xC7FF, 1, RamZ80); + ZetMapArea(0xC000, 0xC7FF, 2, RamZ80); + + ZetMapArea(0xF000, 0xFFFF, 0, RamZ80+0x0800); + ZetMapArea(0xF000, 0xFFFF, 1, RamZ80+0x0800); + ZetMapArea(0xF000, 0xFFFF, 2, RamZ80+0x0800); + + ZetMemEnd(); + ZetClose(); + } + + BurnYM2151Init(3579545, 50.0); // 3.5795 MHz + YM2151SetIrqHandler(0, &shadfrceYM2151IRQHandler); + MSM6295Init(0, 12000, 50.0, 1); // 12.000 KHz + nZ80Cycles = 3579545 * 100 / nBurnFPS; + + DrvDoReset(); + return 0; +} + +static INT32 shadfrceExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + SekExit(); + ZetExit(); + + BurnFree(Mem); + + return 0; +} + +#define TILE_BG0(x) \ + if (d[x]) { p[x]=pal[d[x]|c]; pp[x]=2; } + +#define TILE_BG0_FLIPX(x) \ + if (d[x]) { p[15-x]=pal[d[x]|c]; pp[15-x]=2; } + +#define TILE_BG0_E(z) \ + if (d[z]&&(x+z)>=0 && (x+z)<320) { p[z]=pal[d[z]|c]; pp[z]=2; } + +#define TILE_BG0_FLIPX_E(z) \ + if (d[z]&&(x+15-z)>=0&&(x+15-z)<320) { p[15-z]=pal[d[z]|c]; pp[15-z]=2; } + +#define TILE_BG0_LINE \ + TILE_BG0( 0) \ + TILE_BG0( 1) \ + TILE_BG0( 2) \ + TILE_BG0( 3) \ + TILE_BG0( 4) \ + TILE_BG0( 5) \ + TILE_BG0( 6) \ + TILE_BG0( 7) \ + TILE_BG0( 8) \ + TILE_BG0( 9) \ + TILE_BG0(10) \ + TILE_BG0(11) \ + TILE_BG0(12) \ + TILE_BG0(13) \ + TILE_BG0(14) \ + TILE_BG0(15) + +#define TILE_BG0_FLIPX_LINE \ + TILE_BG0_FLIPX( 0) \ + TILE_BG0_FLIPX( 1) \ + TILE_BG0_FLIPX( 2) \ + TILE_BG0_FLIPX( 3) \ + TILE_BG0_FLIPX( 4) \ + TILE_BG0_FLIPX( 5) \ + TILE_BG0_FLIPX( 6) \ + TILE_BG0_FLIPX( 7) \ + TILE_BG0_FLIPX( 8) \ + TILE_BG0_FLIPX( 9) \ + TILE_BG0_FLIPX(10) \ + TILE_BG0_FLIPX(11) \ + TILE_BG0_FLIPX(12) \ + TILE_BG0_FLIPX(13) \ + TILE_BG0_FLIPX(14) \ + TILE_BG0_FLIPX(15) + +#define TILE_BG0_LINE_E \ + if (((y+k)>=0) && ((y+k)<256)) { \ + TILE_BG0_E( 0) \ + TILE_BG0_E( 1) \ + TILE_BG0_E( 2) \ + TILE_BG0_E( 3) \ + TILE_BG0_E( 4) \ + TILE_BG0_E( 5) \ + TILE_BG0_E( 6) \ + TILE_BG0_E( 7) \ + TILE_BG0_E( 8) \ + TILE_BG0_E( 9) \ + TILE_BG0_E(10) \ + TILE_BG0_E(11) \ + TILE_BG0_E(12) \ + TILE_BG0_E(13) \ + TILE_BG0_E(14) \ + TILE_BG0_E(15) \ + } + +#define TILE_BG0_FLIPX_LINE_E \ + if (((y+k)>=0) && ((y+k)<256)) { \ + TILE_BG0_FLIPX_E( 0) \ + TILE_BG0_FLIPX_E( 1) \ + TILE_BG0_FLIPX_E( 2) \ + TILE_BG0_FLIPX_E( 3) \ + TILE_BG0_FLIPX_E( 4) \ + TILE_BG0_FLIPX_E( 5) \ + TILE_BG0_FLIPX_E( 6) \ + TILE_BG0_FLIPX_E( 7) \ + TILE_BG0_FLIPX_E( 8) \ + TILE_BG0_FLIPX_E( 9) \ + TILE_BG0_FLIPX_E(10) \ + TILE_BG0_FLIPX_E(11) \ + TILE_BG0_FLIPX_E(12) \ + TILE_BG0_FLIPX_E(13) \ + TILE_BG0_FLIPX_E(14) \ + TILE_BG0_FLIPX_E(15) \ + } + +static void tileBackground_0() +{ + /* ---- ---- YXcc CCCC --TT TTTT TTTT TTTT */ + + UINT16 * pal = RamCurPal + 0x2000; + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 32*32*2; offs+=2) { + mx++; + if (mx == 32) { + mx = 0; + my++; + } + + x = mx * 16 - bg0scrollx; + if (x <= (320-512)) x += 512; + + y = my * 16 - bg0scrolly; + if (y <= (256-512)) y += 512; + + if ( x<=-16 || x>=320 || y<=-16 || y>= 256 ) + continue; + else + if ( x >=0 && x <= (320-16) && y >= 0 && y <= (256-16)) { + + UINT32 tileno = RamBg00[offs+1] & 0x3FFF; + if (tileno == 0) continue; + + UINT32 c = (RamBg00[offs] & 0x1F); + if (c & 0x10) c ^= 0x30; // skip hole + c <<= 6; + + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx03 + (tileno << 8); + + UINT8 * pp = RamPri + y * 320 + x; + + if (RamBg00[offs] & 0x0080) { + p += 320 * 15; + pp += 320 * 15; + if (RamBg00[offs] & 0x0040) { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_FLIPX_LINE + + d += 16; + p -= 320; + pp -= 320; + } + } else { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_LINE + + d += 16; + p -= 320; + pp -= 320; + } + } + } else { + if (RamBg00[offs] & 0x0040) { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_FLIPX_LINE + + d += 16; + p += 320; + pp += 320; + } + } else { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_LINE + + d += 16; + p += 320; + pp += 320; + } + } + } + + } else { + + UINT32 tileno = RamBg00[offs+1] & 0x3FFF; + if (tileno == 0) continue; + + UINT32 c = (RamBg00[offs] & 0x1F); + if (c & 0x10) c ^= 0x30; // skip hole + c <<= 6; + + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx03 + (tileno << 8); + UINT8 * pp = RamPri + y * 320 + x; + + if (RamBg00[offs] & 0x0080) { + p += 320 * 15; + pp += 320 * 15; + if (RamBg00[offs] & 0x0040) { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_FLIPX_LINE_E + + d += 16; + p -= 320; + pp -= 320; + } + } else { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_LINE_E + + d += 16; + p -= 320; + pp -= 320; + } + } + } else { + if (RamBg00[offs] & 0x0040) { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_FLIPX_LINE_E + + d += 16; + p += 320; + pp += 320; + } + } else { + for (INT32 k=0;k<16;k++) { + + TILE_BG0_LINE_E + + d += 16; + p += 320; + pp += 320; + } + } + } + + } + } + +} + +static void tileBackground_1() +{ + /* cccc TTTT TTTT TTTT */ + + UINT16 * pal = RamCurPal + 0x2000; + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 32*32; offs++) { + mx++; + if (mx == 32) { + mx = 0; + my++; + } + + x = mx * 16 - bg1scrollx; + if (x <= (320-512)) x += 512; + + y = my * 16 - bg1scrolly; + if (y <= (256-512)) y += 512; + + if ( x<=-16 || x>=320 || y<=-16 || y>= 256 ) + continue; + else + if ( x >=0 && x <= (320-16) && y >= 0 && y <= (256-16)) { + + UINT32 tileno = RamBg01[offs] & 0x0FFF; + UINT32 c = ((RamBg01[offs] & 0xF000) >> 6) + (64 << 6); + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx03 + (tileno << 8); + + for (INT32 k=0;k<16;k++) { + p[ 0] = pal[ d[ 0] | c ]; + p[ 1] = pal[ d[ 1] | c ]; + p[ 2] = pal[ d[ 2] | c ]; + p[ 3] = pal[ d[ 3] | c ]; + p[ 4] = pal[ d[ 4] | c ]; + p[ 5] = pal[ d[ 5] | c ]; + p[ 6] = pal[ d[ 6] | c ]; + p[ 7] = pal[ d[ 7] | c ]; + p[ 8] = pal[ d[ 8] | c ]; + p[ 9] = pal[ d[ 9] | c ]; + p[10] = pal[ d[10] | c ]; + p[11] = pal[ d[11] | c ]; + p[12] = pal[ d[12] | c ]; + p[13] = pal[ d[13] | c ]; + p[14] = pal[ d[14] | c ]; + p[15] = pal[ d[15] | c ]; + + d += 16; + p += 320; + } + } else { + UINT32 tileno = RamBg01[offs] & 0x0FFF; + UINT32 c = ((RamBg01[offs] & 0xF000) >> 6) + (64 << 6); + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx03 + (tileno << 8); + + for (INT32 k=0;k<16;k++) { + if ( (y+k)>=0 && (y+k)<256 ) { + if ((x + 0) >= 0 && (x + 0)<320) p[ 0] = pal[ d[ 0] | c ]; + if ((x + 1) >= 0 && (x + 1)<320) p[ 1] = pal[ d[ 1] | c ]; + if ((x + 2) >= 0 && (x + 2)<320) p[ 2] = pal[ d[ 2] | c ]; + if ((x + 3) >= 0 && (x + 3)<320) p[ 3] = pal[ d[ 3] | c ]; + if ((x + 4) >= 0 && (x + 4)<320) p[ 4] = pal[ d[ 4] | c ]; + if ((x + 5) >= 0 && (x + 5)<320) p[ 5] = pal[ d[ 5] | c ]; + if ((x + 6) >= 0 && (x + 6)<320) p[ 6] = pal[ d[ 6] | c ]; + if ((x + 7) >= 0 && (x + 7)<320) p[ 7] = pal[ d[ 7] | c ]; + if ((x + 8) >= 0 && (x + 8)<320) p[ 8] = pal[ d[ 8] | c ]; + if ((x + 9) >= 0 && (x + 9)<320) p[ 9] = pal[ d[ 9] | c ]; + if ((x + 10) >= 0 && (x + 10)<320) p[10] = pal[ d[10] | c ]; + if ((x + 11) >= 0 && (x + 11)<320) p[11] = pal[ d[11] | c ]; + if ((x + 12) >= 0 && (x + 12)<320) p[12] = pal[ d[12] | c ]; + if ((x + 13) >= 0 && (x + 13)<320) p[13] = pal[ d[13] | c ]; + if ((x + 14) >= 0 && (x + 14)<320) p[14] = pal[ d[14] | c ]; + if ((x + 15) >= 0 && (x + 15)<320) p[15] = pal[ d[15] | c ]; + } + d += 16; + p += 320; + } + } + } +} + +static void tileForeground() +{ + /* ---- ---- tttt tttt ---- ---- pppp TTTT */ + + UINT16 * pal = RamCurPal; + INT32 offs, mx, my, x, y; + + mx = -1; + my = 0; + for (offs = 0; offs < 64*32*2; offs+=2) { + mx++; + if (mx == 64) { + mx = 0; + my++; + } + + x = mx * 8; + y = my * 8; + + if ( x<=-8 || x>=320 || y<=-8 || y>= 256 ) + continue; + else + if ( x >=0 && x < (320-8) && y >= 0 && y < (256-8)) { + + UINT32 tileno = (RamFg[offs] & 0x00FF) | ((RamFg[offs+1] & 0x000F) << 8); + if (tileno == 0) continue; + + UINT32 c = (RamFg[offs+1] & 0x00F0) << 2; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx01 + (tileno << 6); + + for (INT32 k=0;k<8;k++) { + if (d[0]) p[0] = pal[d[0]|c]; + if (d[1]) p[1] = pal[d[1]|c]; + if (d[2]) p[2] = pal[d[2]|c]; + if (d[3]) p[3] = pal[d[3]|c]; + if (d[4]) p[4] = pal[d[4]|c]; + if (d[5]) p[5] = pal[d[5]|c]; + if (d[6]) p[6] = pal[d[6]|c]; + if (d[7]) p[7] = pal[d[7]|c]; + + d += 8; + p += 320; + } + } else { + + UINT32 tileno = (RamFg[offs] & 0x00FF) | ((RamFg[offs+1] & 0x000F) << 8); + if (tileno == 0) continue; + + UINT32 c = (RamFg[offs+1] & 0x00F0) << 2; + UINT16 * p = (UINT16 *) pBurnDraw + y * 320 + x; + UINT8 *d = RomGfx01 + (tileno << 6); + + for (INT32 k=0;k<8;k++) { + if ( (y+k)>=0 && (y+k)<256 ) { + if ((x + 0) >= 0 && (x + 0)<320) p[0] = pal[ d[0] | c ]; + if ((x + 1) >= 0 && (x + 1)<320) p[1] = pal[ d[1] | c ]; + if ((x + 2) >= 0 && (x + 2)<320) p[2] = pal[ d[2] | c ]; + if ((x + 3) >= 0 && (x + 3)<320) p[3] = pal[ d[3] | c ]; + if ((x + 4) >= 0 && (x + 4)<320) p[4] = pal[ d[4] | c ]; + if ((x + 5) >= 0 && (x + 5)<320) p[5] = pal[ d[5] | c ]; + if ((x + 6) >= 0 && (x + 6)<320) p[6] = pal[ d[6] | c ]; + if ((x + 7) >= 0 && (x + 7)<320) p[7] = pal[ d[7] | c ]; + } + d += 8; + p += 320; + } + } + } +} + +#define TILE_SPR_NORMAL(x) \ + if (q[x]) { if((pp[x]&(0x05|pri))==0) p[x]=pal[q[x]|color]; pp[x]|=(1<=0)&&((sx+x)<320)) { if((pp[x]&(0x05|pri))==0) p[x]=pal[q[x]|color]; pp[x]|=(1<=0)&&((sx+15-x)<320)) { if((pp[15-x]&(0x05|pri))==0) p[15-x]=pal[q[x]|color]; pp[15-x]|=(1<= (320-16) || sy < 0 || sy >= (256-16) ) { + + if ((sx <= -16) || (sx >= 320) || (sy <= -16) || (sy >= 256)) + return; + + if (flipy) { + + p += 320 * 15; + pp += 320 * 15; + + if (flipx) { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<256)) { + + TILE_SPR_FLIP_X_LINE_E + + } + p -= 320; + pp -= 320; + q += 16; + } + + } else { + + for (INT32 i=15;i>=0;i--) { + if (((sy+i)>=0) && ((sy+i)<256)) { + + TILE_SPR_NORMAL_LINE_E + + } + p -= 320; + pp -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<256)) { + + TILE_SPR_FLIP_X_LINE_E + + } + p += 320; + pp += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + if (((sy+i)>=0) && ((sy+i)<256)) { + + TILE_SPR_NORMAL_LINE_E + + } + p += 320; + pp += 320; + q += 16; + } + + } + + } + + return; + } + + if (flipy) { + + p += 320 * 15; + pp += 320 * 15; + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + + TILE_SPR_FLIP_X_LINE + + p -= 320; + pp -= 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + + TILE_SPR_NORMAL_LINE + + p -= 320; + pp -= 320; + q += 16; + } + } + + } else { + + if (flipx) { + + for (INT32 i=0;i<16;i++) { + + TILE_SPR_FLIP_X_LINE + + p += 320; + pp += 320; + q += 16; + } + + } else { + + for (INT32 i=0;i<16;i++) { + + TILE_SPR_NORMAL_LINE + + p += 320; + pp += 320; + q += 16; + } + + } + + } + +} + +static void drawSprites() +{ + /* | ---- ---- hhhf Fe-Y | ---- ---- yyyy yyyy | ---- ---- TTTT TTTT | ---- ---- tttt tttt | + | ---- ---- -pCc cccX | ---- ---- xxxx xxxx | ---- ---- ---- ---- | ---- ---- ---- ---- | */ + + UINT16 * finish = RamSpr; + UINT16 * source = finish + 0x2000/2 - 8; + INT32 hcount; + + while( source>=finish ) { + INT32 ypos = 0x100 - (((source[0] & 0x0003) << 8) | (source[1] & 0x00ff)); + INT32 xpos = (((source[4] & 0x0001) << 8) | (source[5] & 0x00ff)) + 1; + INT32 tile = ((source[2] & 0x00ff) << 8) | (source[3] & 0x00ff); + INT32 height = (source[0] & 0x00e0) >> 5; + INT32 enable = ((source[0] & 0x0004)); + INT32 flipx = ((source[0] & 0x0010) >> 4); + INT32 flipy = ((source[0] & 0x0008) >> 3); + INT32 pal = ((source[4] & 0x003e)); + INT32 pri_mask = (source[4] & 0x0040) ? 0x02 : 0x00; + +// if ( (1 << pri_mask) & nSpriteEnable) { + + if (pal & 0x20) pal ^= 0x60; // skip hole + pal <<= 5; + + height++; + if (enable) { + for (hcount=0;hcount> 2); + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * 1 / 4) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + bVBlink = 0; + SekRun(3500000 / 60); + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + ZetRun(nZ80Cycles >> 2); + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * 2 / 4) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + bVBlink = 1; + SekRun(3500000 / 60); + + ZetRun(nZ80Cycles >> 2); + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * 3 / 4) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + + bVBlink = 0; + SekRun(3500000 / 60); + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + + ZetRun(nZ80Cycles >> 2); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + +/* + ZetRun(nZ80Cycles); + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } +*/ + + ZetClose(); + SekClose(); + + if (pBurnDraw) + DrvDraw(); // Draw screen if needed + + + + return 0; +} + +static INT32 shadfrceScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) // Return minimum compatible version + *pnMin = 0x029671; + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 state + ZetScan(nAction); + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + SCAN_VAR(DrvInput); + SCAN_VAR(nBrightness); + SCAN_VAR(bg0scrollx); + SCAN_VAR(bg0scrolly); + SCAN_VAR(bg1scrollx); + SCAN_VAR(bg1scrolly); + SCAN_VAR(nSoundlatch); + } + + if (nAction & ACB_WRITE) { + // recalc palette and brightness + for(INT32 i=0;i<0x4000;i++) CalcCol(i); + } + + return 0; +} + +struct BurnDriver BurnDrvShadfrce = { + "shadfrce", NULL, NULL, NULL, "1993", + "Shadow Force (US Version 2)\0", NULL, "Technos Japan", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, shadfrceRomInfo, shadfrceRomName, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo, + shadfrceInit, shadfrceExit, shadfrceFrame, NULL, shadfrceScan, &bRecalcPalette, 0x8000, + 320, 256, 4, 3 +}; + +struct BurnDriver BurnDrvShadfrcj = { + "shadfrcej", "shadfrce", NULL, NULL, "1993", + "Shadow Force (Japan Version 3)\0", NULL, "Technos Japan", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, shadfrcjRomInfo, shadfrcjRomName, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo, + shadfrceInit, shadfrceExit, shadfrceFrame, NULL, shadfrceScan, &bRecalcPalette, 0x8000, + 320, 256, 4, 3 +}; + +struct BurnDriver BurnDrvShadfrcjv2 = { + "shadfrcejv2", "shadfrce", NULL, NULL, "1993", + "Shadow Force (Japan Version 2)\0", NULL, "Technos Japan", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, shadfrcjv2RomInfo, shadfrcjv2RomName, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo, + shadfrceInit, shadfrceExit, shadfrceFrame, NULL, shadfrceScan, &bRecalcPalette, 0x8000, + 320, 256, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_silkroad.cpp b/src/burn/drivers/misc_post90s/d_silkroad.cpp new file mode 100644 index 00000000..9e26cf04 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_silkroad.cpp @@ -0,0 +1,643 @@ +// FB Alpha Legend of Silkroad driver +// Based on MAME driver by David Haywood, R.Belmont, and Stephh + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvTransTab; +static UINT16 *DrvSysRegs; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc = 0; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 15, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 14, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 12, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 13, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 11, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 10, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 9, "p1 fire 3" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 7, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 6, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 4, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 5, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 1, "p2 fire 3" }, + + {"Test", BIT_DIGITAL, DrvJoy2 + 5, "diag" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 4, "service" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x15, 0xff, 0xff, 0x1c, NULL}, + {0x16, 0xff, 0xff, 0xf7, NULL}, + + {0, 0xfe, 0, 2, "Lives" }, + {0x15, 0x01, 0x01, 0x01, "1" }, + {0x15, 0x01, 0x01, 0x00, "2" }, + + {0, 0xfe, 0, 2, "Blood Effect" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0, 0xfe, 0, 8, "Difficulty" }, + {0x15, 0x01, 0xe0, 0x60, "Easiest" }, + {0x15, 0x01, 0xe0, 0x40, "Easier" }, + {0x15, 0x01, 0xe0, 0x20, "Easy" }, + {0x15, 0x01, 0xe0, 0x00, "Normal" }, + {0x15, 0x01, 0xe0, 0xe0, "Medium" }, + {0x15, 0x01, 0xe0, 0xc0, "Hard" }, + {0x15, 0x01, 0xe0, 0xa0, "Harder" }, + {0x15, 0x01, 0xe0, 0x80, "Hardest" }, + + {0, 0xfe, 0, 2, "Free Play" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0, 0xfe, 0, 2, "Demo Sounds" }, + {0x16, 0x01, 0x08, 0x08, "Off" }, + {0x16, 0x01, 0x08, 0x00, "On" }, + + {0, 0xfe, 0, 2, "Chute Type" }, + {0x16, 0x01, 0x10, 0x10, "Single" }, + {0x16, 0x01, 0x10, 0x00, "Multi" }, + + {0, 0xfe, 0, 8, "Coinage" }, + {0x16, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0x20, "4 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x16, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x16, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x16, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x16, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, +}; + +STDDIPINFO(Drv) + +static void palette_write(INT32 offset, UINT16 pal) +{ + UINT8 r = (pal >> 10) & 0x1f; + UINT8 g = (pal >> 5) & 0x1f; + UINT8 b = (pal >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +UINT8 __fastcall silkroad_read_byte(UINT32 address) +{ + switch (address) + { + case 0xc00000: + return DrvInputs[0] >> 8; + + case 0xc00001: + return DrvInputs[0] & 0xff; + + case 0xc00002: + return 0xff; + + case 0xc00003: + return DrvInputs[1] & 0xff; + + case 0xc00004: + return DrvDips[1]; + + case 0xc00005: + return DrvDips[0]; + + case 0xc00025: + return MSM6295ReadStatus(0); + + case 0xc0002d: + return BurnYM2151ReadStatus(); + + case 0xc00031: + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall silkroad_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xc00025: + MSM6295Command(0, data); + return; + + case 0xc00029: + BurnYM2151SelectRegister(data); + return; + + case 0xc0002d: + BurnYM2151WriteRegister(data); + return; + + case 0xc00031: + MSM6295Command(1, data); + return; + } +} + +void __fastcall silkroad_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffffc000) == 0x600000) { + *((UINT16 *)(DrvPalRAM + (address & 0x3ffe))) = data; + + palette_write((address >> 2) & 0x0fff, data); + + return; + } + + if (address >= 0xc0010c || address <= 0xc00123) { + DrvSysRegs[(address - 0xc0010c) >> 1] = data; + + return; + } +} + +void __fastcall silkroad_write_long(UINT32 address, UINT32 data) +{ + if ((address & 0xffffc000) == 0x600000) { + *((UINT32 *)(DrvPalRAM + (address & 0x3ffc))) = data; + + palette_write((address >> 2) & 0x0fff, data >> 16); + + return; + } +} + +static INT32 DrvGfxROMDecode() +{ + static INT32 Planes[6] = { 0x0000008, 0x0000000, 0x1000008, 0x1000000, 0x2000008, 0x2000000 }; + static INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017 }; + static INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x600000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 4; i++ ){ + if (BurnLoadRom(tmp + 0x000000, 2 + i * 3, 1)) return 1; + if (BurnLoadRom(tmp + 0x200000, 3 + i * 3, 1)) return 1; + if (BurnLoadRom(tmp + 0x400000, 4 + i * 3, 1)) return 1; + + if (i == 0) { // fix rom04 + for (INT32 j = 0x1b3fff; j >= 0; j--) { + tmp[0x44c000 + j] = tmp[0x44c000 + (j - 1)]; + } + } + + for (INT32 j = 0; j < 0x600000; j++) { + tmp[j] ^= 0xff; + } + + GfxDecode(0x08000, 6, 16, 16, Planes, XOffs, YOffs, 0x200, tmp, DrvGfxROM + 0x0800000 * i); + } + + BurnFree (tmp); + + DrvTransTab = (UINT8*)BurnMalloc(0x20000); + if (DrvTransTab == NULL) { + return 1; + } + + { + memset (DrvTransTab, 0, 0x20000); + for (INT32 i = 0, c = 0; i < 0x2000000; i++) { + if (DrvGfxROM[i]) { + DrvTransTab[i>>8] |= 1; + c++; + } + + if ((i & 0xff) == 0xff) { + if (c == 0x100) DrvTransTab[i>>8] |= 2; + c = 0; + } + } + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + BurnYM2151Reset(); + + MSM6295Reset(0); + MSM6295Reset(1); + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[0][nChannel] = DrvSndROM0 + (nChannel << 8); + MSM6295SampleData[0][nChannel] = DrvSndROM0 + (nChannel << 16); + + MSM6295SampleInfo[1][nChannel] = DrvSndROM1 + (nChannel << 8); + MSM6295SampleData[1][nChannel] = DrvSndROM1 + (nChannel << 16); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x0200000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x0080000; + DrvSndROM1 = Next; Next += 0x0040000; + + DrvPalette = (UINT32 *)Next; Next += 0x0001001 * sizeof (UINT32); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x0001000; + DrvPalRAM = Next; Next += 0x0004000; + DrvVidRAM = Next; Next += 0x000c000; + Drv68KRAM = Next; Next += 0x0020000; + + DrvSysRegs = (UINT16*)Next; Next += 0x0000020 * sizeof (UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + DrvGfxROM = (UINT8*)BurnMalloc(0x2000000); + if (DrvGfxROM == NULL) { + return 1; + } + + if (DrvGfxROMDecode()) return 1; + + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 1, 1, 2)) return 1; + + for (INT32 i = 0; i < 0x200000; i+= 4) { + INT32 t = Drv68KROM[i + 1]; + Drv68KROM[i + 1] = Drv68KROM[i + 2]; + Drv68KROM[i + 2] = t; + } + + if (BurnLoadRom(DrvSndROM0, 14, 1)) return 1; + if (BurnLoadRom(DrvSndROM1, 15, 1)) return 1; + } + + SekInit(0, 0x68EC020); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x40c000, 0x40cfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x600000, 0x603fff, SM_ROM); + SekMapMemory(DrvVidRAM, 0x800000, 0x80bfff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xfe0000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, silkroad_write_byte); + SekSetWriteWordHandler(0, silkroad_write_word); + SekSetWriteLongHandler(0, silkroad_write_long); + SekSetReadByteHandler(0, silkroad_read_byte); + SekClose(); + + BurnYM2151Init(3579545, 100.0); + MSM6295Init(0, 1056000 / 132, 45.0, 1); + MSM6295Init(1, 2112000 / 132, 45.0, 1); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + GenericTilesExit(); + + BurnFree (AllMem); + BurnFree (DrvGfxROM); + BurnFree (DrvTransTab); + + DrvRecalc = 0; + + return 0; +} + +static void silkroad_draw_tile(INT32 code, INT32 sx, INT32 sy, INT32 color, INT32 flipx) +{ + if (!DrvTransTab[code]) return; + + if (flipx) { + if (sx >= 0 && sx <= 352 && sy >= 0 && sy <= 208) { + if (DrvTransTab[code] & 2) { + Render16x16Tile_FlipX(pTransDraw, code, sx, sy, color, 6, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 6, 0, 0, DrvGfxROM); + } + } else { + if (DrvTransTab[code] & 2) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 6, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 6, 0, 0, DrvGfxROM); + } + } + } else { + if (sx >= 0 && sx <= 352 && sy >= 0 && sy <= 208) { + if (DrvTransTab[code] & 2) { + Render16x16Tile(pTransDraw, code, sx, sy, color, 6, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 6, 0, 0, DrvGfxROM); + } + } else { + if (DrvTransTab[code] & 2) { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 6, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 6, 0, 0, DrvGfxROM); + } + } + } +} + +static void draw_sprites(INT32 pri) +{ + UINT32 *source = (UINT32*)DrvSprRAM; + UINT32 *finish = source + 0x1000/4; + UINT32 *maxspr = source; + + while (maxspr < finish) + { + if ((maxspr[1] & 0xff000000) == 0xff000000) break; + maxspr += 2; + } + + finish = maxspr - 2; + + while (finish >= source) + { + INT32 xpos = (finish[0] & 0x01ff) - 50; + INT32 ypos = (finish[0] >> 16) - 16; + INT32 attr = finish[1] >> 16; + INT32 tileno = (finish[1] & 0xffff) | ((attr & 0x8000) << 1); + finish -= 2; + + INT32 priority = attr & 0x1000; + if (pri != priority || ypos == -16 || ypos > 223) continue; + + INT32 color = attr & 0x003f; + INT32 flipx = attr & 0x0080; + INT32 width = ((attr >> 8) & 0x0f) + 1; + + if (flipx) { + for (INT32 wcount = width; wcount > 0; wcount--) { + INT32 sx = xpos + (((wcount << 4) - 0x10) | 8); + + if (sx < -15 || sx > 379) continue; + + silkroad_draw_tile(tileno+(width-wcount), sx, ypos, color, 1); + } + } else { + for (INT32 wcount = 0; wcount < width; wcount++) { + INT32 sx = xpos + ((wcount << 4) | 8); + + if (sx < -15 || sx > 379) continue; + + silkroad_draw_tile(tileno + wcount, sx, ypos, color, 0); + } + } + } +} + +static void draw_layer(INT32 offset, INT32 scrollx, INT32 scrolly) +{ + UINT32 *vidram = (UINT32*)(DrvVidRAM + offset); + + for (INT32 offs = 0; offs < 0x4000 / 4; offs++) + { + INT32 sx = (offs << 4) & 0x3f0; + INT32 sy = (offs >> 2) & 0x3f0; + sx -= scrollx + 50; + sy -= scrolly + 16; + if (sy < -15) sy += 0x400; + if (sx < -15) sx += 0x400; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vidram[offs] & 0xffff; + INT32 color = (vidram[offs] >> 16) & 0x1f; + INT32 flipx = (vidram[offs] >> 16) & 0x80; + + silkroad_draw_tile(code + 0x18000, sx, sy, color, flipx); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc != nBurnBpp) { + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x2000; i+=2) { + palette_write(i/2, pal[i]); + } + + DrvPalette[0x1000] = BurnHighCol(0xff, 0x00, 0xff, 0); + DrvRecalc = nBurnBpp; + } + + if (nBurnLayer & 1) { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x7c0; + } + } else { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x1000; + } + } + + if (nBurnLayer & 2) draw_layer(0x0000, DrvSysRegs[ 0] & 0x3ff, DrvSysRegs[ 1] & 0x3ff); + if (nSpriteEnable & 1) draw_sprites(0x0000); + if (nBurnLayer & 4) draw_layer(0x4000, DrvSysRegs[ 5] & 0x3ff, DrvSysRegs[10] & 0x3ff); + if (nSpriteEnable & 2) draw_sprites(0x1000); + if (nBurnLayer & 8) draw_layer(0x8000, DrvSysRegs[ 4] & 0x3ff, DrvSysRegs[ 2] & 0x3ff); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = 0xffff; + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + } + + DrvInputs[1] ^= DrvJoy2[4] << 6; + + if (!(DrvInputs[0] & 0x00c0)) DrvInputs[0] |= 0x00c0; + if (!(DrvInputs[0] & 0x0030)) DrvInputs[0] |= 0x0030; + if (!(DrvInputs[0] & 0xc000)) DrvInputs[0] |= 0xc000; + if (!(DrvInputs[0] & 0x3000)) DrvInputs[0] |= 0x3000; + } + + INT32 nTotalCycles = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + + SekOpen(0); + SekRun(nTotalCycles); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(DrvInputs[0]); + SCAN_VAR(DrvInputs[1]); + } + + return 0; +} + + +// The Legend of Silkroad + +static struct BurnRomInfo silkroadRomDesc[] = { + { "rom02.bin", 0x100000, 0x4e5200fc, 1 | BRF_PRG }, // 0 Motorola '020 Code + { "rom03.bin", 0x100000, 0x73ccc78c, 1 | BRF_PRG }, // 1 + + { "rom12.bin", 0x200000, 0x96393d04, 2 | BRF_GRA }, // 2 Tiles + { "rom08.bin", 0x200000, 0x23f1d462, 2 | BRF_GRA }, // 3 + { "rom04.bin", 0x200000, 0x2cf6ed30, 2 | BRF_GRA }, // 4 + + { "rom13.bin", 0x200000, 0x4ca1698e, 2 | BRF_GRA }, // 5 + { "rom09.bin", 0x200000, 0xef0b5bf4, 2 | BRF_GRA }, // 6 + { "rom05.bin", 0x200000, 0x512d6e25, 2 | BRF_GRA }, // 7 + + { "rom14.bin", 0x200000, 0xd00b19c4, 2 | BRF_GRA }, // 8 + { "rom10.bin", 0x200000, 0x7d324280, 2 | BRF_GRA }, // 9 + { "rom06.bin", 0x200000, 0x3ac26060, 2 | BRF_GRA }, // 10 + + { "rom07.bin", 0x200000, 0x9fc6ff9d, 2 | BRF_GRA }, // 11 + { "rom11.bin", 0x200000, 0x11abaf1c, 2 | BRF_GRA }, // 12 + { "rom15.bin", 0x200000, 0x26a3b168, 2 | BRF_GRA }, // 13 + + { "rom00.bin", 0x080000, 0xb10ba7ab, 3 | BRF_SND }, // 14 OKI Samples + { "rom01.bin", 0x040000, 0xdb8cb455, 4 | BRF_SND }, // 15 +}; + +STD_ROM_PICK(silkroad) +STD_ROM_FN(silkroad) + +struct BurnDriver BurnDrvSilkroad = { + "silkroad", NULL, NULL, NULL, "1999", + "The Legend of Silkroad\0", NULL, "Unico", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, + NULL, silkroadRomInfo, silkroadRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1001, + 380, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_simpl156.cpp b/src/burn/drivers/misc_post90s/d_simpl156.cpp new file mode 100644 index 00000000..ae485a09 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_simpl156.cpp @@ -0,0 +1,1090 @@ +// FB Alpha Data East Simple 156 System driver module +// Based on MAME driver by + +#include "tiles_generic.h" +#include "arm_intf.h" +#include "msm6295.h" +#include "eeprom.h" +#include "deco16ic.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvArmROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvEEPROM; +static UINT8 *DrvArmRAM; +static UINT8 *DrvSysRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[1]; +static UINT16 DrvInputs[2]; +static UINT8 DrvReset; + +static INT32 DrvOkiBank; + +static struct BurnInputInfo Simpl156InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Simpl156) + +static struct BurnDIPInfo Simpl156DIPList[]= +{ + {0x14, 0xff, 0xff, 0x08, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Simpl156) + +//----------------------------------------------------------------------------------------------------------------------------------------------- + +static void oki_set_bank(INT32 bank) +{ + if (DrvOkiBank != (bank & 0x07)) { + DrvOkiBank = bank & 0x07; + memcpy (DrvSndROM0 + 0x100000, DrvSndROM1 + 0x40000 * DrvOkiBank, 0x40000); + } +} + +// use INT type for ADDRESS to kill mingw warnings +static void CommonWrite32(INT32 address, UINT32 data) +{ + Write16Long(DrvArmRAM, 0x000000, 0x007fff) // 16-bit + Write16Long(DrvSprRAM, 0x010000, 0x011fff) // 16-bit + Write16Long(DrvPalRAM, 0x020000, 0x020fff) // 16-bit + Write16Long(((UINT8*)deco16_pf_control[0]), 0x040000, 0x04001f) // 16-bit + Write16Long(deco16_pf_ram[0], 0x050000, 0x051fff) // 16-bit + Write16Long(deco16_pf_ram[0], 0x052000, 0x053fff) // 16-bit mirror + Write16Long(deco16_pf_ram[1], 0x054000, 0x055fff) // 16-bit + Write16Long(deco16_pf_rowscroll[0], 0x060000, 0x061fff) // 16-bit + Write16Long(deco16_pf_rowscroll[1], 0x064000, 0x065fff) // 16-bit + + if (address == 0x030000) { + oki_set_bank(data); + EEPROMWrite(data & 0x20, data & 0x40, data & 0x10); + return; + } +} + +static void CommonWrite8(INT32 address, UINT8 data) +{ + Write16Byte(DrvArmRAM, 0x000000, 0x007fff) // 16-bit + Write16Byte(DrvSprRAM, 0x010000, 0x011fff) // 16-bit + Write16Byte(DrvPalRAM, 0x020000, 0x020fff) // 16-bit + Write16Byte(((UINT8*)deco16_pf_control[0]), 0x040000, 0x04001f) // 16-bit + Write16Byte(deco16_pf_ram[0], 0x050000, 0x051fff) // 16-bit + Write16Byte(deco16_pf_ram[0], 0x052000, 0x053fff) // 16-bit mirror + Write16Byte(deco16_pf_ram[1], 0x054000, 0x055fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[0], 0x060000, 0x061fff) // 16-bit + Write16Byte(deco16_pf_rowscroll[1], 0x064000, 0x065fff) // 16-bit + + if ((address & ~3) == 0x030000) { + oki_set_bank(data); + EEPROMWrite(data & 0x20, data & 0x40, data & 0x10); + return; + } +} + +static UINT32 CommonRead32(INT32 address) +{ + Read16Long(DrvArmRAM, 0x000000, 0x007fff) // 16-bit + Read16Long(DrvSprRAM, 0x010000, 0x011fff) // 16-bit + Read16Long(DrvPalRAM, 0x020000, 0x020fff) // 16-bit + Read16Long(((UINT8*)deco16_pf_control[0]), 0x040000, 0x04001f) // 16-bit + Read16Long(deco16_pf_ram[0], 0x050000, 0x051fff) // 16-bit + Read16Long(deco16_pf_ram[0], 0x052000, 0x053fff) // 16-bit mirror + Read16Long(deco16_pf_ram[1], 0x054000, 0x055fff) // 16-bit + Read16Long(deco16_pf_rowscroll[0], 0x060000, 0x061fff) // 16-bit + Read16Long(deco16_pf_rowscroll[1], 0x064000, 0x065fff) // 16-bit + + if (address == 0x30000) { + return DrvInputs[1]; + } + + return 0; +} + +static UINT8 CommonRead8(INT32 address) +{ + Read16Byte(DrvArmRAM, 0x000000, 0x007fff) // 16-bit + Read16Byte(DrvSprRAM, 0x010000, 0x011fff) // 16-bit + Read16Byte(DrvPalRAM, 0x020000, 0x020fff) // 16-bit + Read16Byte(((UINT8*)deco16_pf_control[0]), 0x040000, 0x04001f) // 16-bit + Read16Byte(deco16_pf_ram[0], 0x050000, 0x051fff) // 16-bit + Read16Byte(deco16_pf_ram[0], 0x052000, 0x053fff) // 16-bit mirror + Read16Byte(deco16_pf_ram[1], 0x054000, 0x055fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[0], 0x060000, 0x061fff) // 16-bit + Read16Byte(deco16_pf_rowscroll[1], 0x064000, 0x065fff) // 16-bit + + switch (address) + { + case 0x030000: + case 0x030001: + case 0x030002: + case 0x030003: + return 0xff; + } + + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------------------- + +static UINT32 map_offsets[3]; // memory, msm0, msm1 + +void simpl156_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xf80000) == map_offsets[0]) { + CommonWrite8(address & 0x7ffff, data); + } + + if ((address & ~3) == map_offsets[1]) { + MSM6295Command(0, data); + return; + } + + if ((address & ~3) == map_offsets[2]) { + MSM6295Command(1, data); + return; + } +} + +void simpl156_write_long(UINT32 address, UINT32 data) +{ + if ((address & 0xf80000) == map_offsets[0]) { + CommonWrite32(address & 0x7ffff, data); + } + + if (address == map_offsets[1]) { + MSM6295Command(0, data); + return; + } + + if (address == map_offsets[2]) { + MSM6295Command(1, data); + return; + } +} + +UINT8 simpl156_read_byte(UINT32 address) +{ + if ((address & 0xf80000) == map_offsets[0]) { + return CommonRead8(address & 0x7ffff); + } + + if ((address & ~3) == 0x200000) { + return ~0; // inputs -- only read once on boot + } + + if ((address & ~3) == map_offsets[1]) { + return MSM6295ReadStatus(0); + } + + if ((address & ~3) == map_offsets[2]) { + return MSM6295ReadStatus(1); + } + + return 0; +} + +UINT32 simpl156_read_long(UINT32 address) +{ + if ((address & 0xf80000) == map_offsets[0]) { + return CommonRead32(address & 0x7ffff); + } + + if (address == 0x200000) { + return 0xffff0000 | (EEPROMRead() << 8) | DrvInputs[0] | deco16_vblank; // party time needs proper vblank + } + + if (address == map_offsets[1]) { + return MSM6295ReadStatus(0); + } + + if (address == map_offsets[2]) { + return MSM6295ReadStatus(1); + } + + return 0; +} + +static void common_map(INT32 ram, INT32 sfx, INT32 mus) +{ + map_offsets[0] = ram; // ram regions + map_offsets[1] = sfx; // oki #0 (sfx) + map_offsets[2] = mus; // oki #1 (music) + + ArmInit(1); + ArmOpen(0); + ArmMapMemory(DrvArmROM, 0x000000, 0x07ffff, ARM_ROM); + ArmMapMemory(DrvSysRAM, 0x201000, 0x201fff, ARM_RAM); // 32-bit + // ram regions and oki addresses set in map offsets + ArmSetWriteByteHandler(simpl156_write_byte); + ArmSetWriteLongHandler(simpl156_write_long); + ArmSetReadByteHandler(simpl156_read_byte); + ArmSetReadLongHandler(simpl156_read_long); + ArmClose(); +} + +static void mitchell_map() { common_map(0x180000, 0x100000, 0x140000); } +static void magdrop_map() { common_map(0x380000, 0x400000, 0x340000); } +static void joemacr_map() { common_map(0x100000, 0x180000, 0x1c0000); } +static void chainrec_map() { common_map(0x400000, 0x480000, 0x3c0000); } +static void magdropp_map() { common_map(0x680000, 0x780000, 0x4c0000); } + +static INT32 simpl156_bank_callback(const INT32 bank) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ArmOpen(0); + ArmReset(); + ArmClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + + EEPROMReset(); + + if (EEPROMAvailable() == 0) { + EEPROMFill(DrvEEPROM, 0, 0x80); + } + + deco16Reset(); + + DrvOkiBank = -1; + oki_set_bank(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvArmROM = Next; Next += 0x0080000; + + DrvGfxROM0 = Next; Next += 0x0400000; + DrvGfxROM1 = Next; Next += 0x0400000; + DrvGfxROM2 = Next; Next += 0x1000000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x0180000; + DrvSndROM1 = Next; Next += 0x0200000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + DrvEEPROM = Next; Next += 0x0000080; + + AllRam = Next; + + DrvArmRAM = Next; Next += 0x0004000; + DrvSysRAM = Next; Next += 0x0002000; + DrvPalRAM = Next; Next += 0x0001000; + DrvSprRAM = Next; Next += 0x0001000; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void decode_samples() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + + for (INT32 i = 0; i < 0x200000; i++) { + tmp[((i & 1) << 20) | (i >> 1)] = DrvSndROM1[i]; + } + + memcpy (DrvSndROM1, tmp, 0x200000); + + BurnFree (tmp); +} + +static void pCommonSpeedhackCallback() +{ + ArmIdleCycles(1120); // ok? +} + +static INT32 CommonInit(INT32 (*pRomLoad)(INT32 *, INT32 *), void (*pMap)(), INT32 msm, UINT32 speedhack) +{ + BurnSetRefreshRate(58.00); + + INT32 gfx0len, gfx1len; + + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pRomLoad) { + + if (pRomLoad(&gfx0len, &gfx1len)) return 1; + + deco156_decrypt(DrvArmROM, 0x080000); + + deco56_decrypt_gfx(DrvGfxROM0, gfx0len); + + deco16_tile_decode(DrvGfxROM0, DrvGfxROM1, gfx0len, 0); + deco16_tile_decode(DrvGfxROM0, DrvGfxROM0, gfx0len, 1); + + deco16_sprite_decode(DrvGfxROM2, gfx1len); + + decode_samples(); + } + + if (pMap) { + pMap(); + } + + ArmSetSpeedHack(speedhack ? speedhack : ~0, pCommonSpeedhackCallback); + + EEPROMInit(&eeprom_interface_93C46); + + MSM6295Init(0, 1006875 / 132, 60.0, 1); + MSM6295Init(1, 2013750 / 132 / msm, 20.0, 1); + + deco16Init(1, 0, 1); + deco16_set_bank_callback(0, simpl156_bank_callback); + deco16_set_bank_callback(1, simpl156_bank_callback); + deco16_set_graphics(DrvGfxROM0, gfx0len*2, DrvGfxROM1, gfx0len*2, NULL, 0); + deco16_set_global_offsets(0, 8); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + ArmExit(); + + MSM6295Exit(0); + MSM6295Exit(1); + MSM6295ROM = NULL; + + GenericTilesExit(); + + deco16Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void simpl156_palette_recalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x1000 / 4; i++) + { + INT32 r = (p[i] >> 0) & 0x1f; + INT32 g = (p[i] >> 5) & 0x1f; + INT32 b = (p[i] >> 10) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites() +{ + UINT16 *spriteram = (UINT16*)DrvSprRAM; + + for (INT32 offs = (0x1400 / 4) - 4; offs >= 0; offs -= 4) + { + INT32 mult, inc; + + INT32 sy = spriteram[offs + 0]; + if ((sy & 0x1000) && (nCurrentFrame & 1)) continue; + + INT32 code = spriteram[offs + 1]; + INT32 sx = spriteram[offs + 2]; + INT32 color = (sx >> 9) & 0x1f; + INT32 pri = sx & 0xc000; + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + INT32 multi = (1 << ((sy & 0x0600) >> 9)) - 1; + + switch (pri) + { + case 0x0000: pri = 0x00; break; + case 0x4000: pri = 0xf0; break; + case 0x8000: + case 0xc000: pri = 0xfc; break; + } + + sx = sx & 0x01ff; + sy = sy & 0x01ff; + if (sx >= 320) sx -= 512; + if (sy >= 256) sy -= 512; + sy = 240 - sy; + sx = 304 - sx; + + if (sx > 320) continue; + + code &= ~multi; + + if (flipy) { + inc = -1; + } else { + code += multi; + inc = 1; + } + + if (1)//flipscreen + { + sy = 240 - sy; + sx = 304 - sx; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else + mult = -16; + + while (multi >= 0) + { + deco16_draw_prio_sprite(pTransDraw, DrvGfxROM2, code - multi * inc, (color << 4)+0x200, sx, sy + mult * multi, flipx, flipy, pri); + + multi--; + } + } +} + +static INT32 DrvDraw() +{ + simpl156_palette_recalc(); + + deco16_pf12_update(); + deco16_clear_prio_map(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + deco16_draw_layer(1, pTransDraw, 2); + deco16_draw_layer(0, pTransDraw, 4); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0x0007 | (DrvDips[0] & 8); + DrvInputs[1] = 0xffff; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nTotalCycles = 28000000 / 58; + + ArmOpen(0); + deco16_vblank = 0xf0; + ArmRun(nTotalCycles - 2240); + ArmSetIRQLine(ARM_IRQ_LINE, ARM_HOLD_LINE); + deco16_vblank = 0x00; + ArmRun(2240); + ArmClose(); + + if (pBurnSoundOut) { + memset (pBurnSoundOut, 0, nBurnSoundLen * sizeof(INT16) * 2); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ArmScan(nAction, pnMin); + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + deco16Scan(); + + SCAN_VAR(DrvOkiBank); + } + + if (nAction & ACB_WRITE) { + INT32 bank = DrvOkiBank; + DrvOkiBank = -1; + oki_set_bank(bank); + } + + return 0; +} + + +// Joe & Mac Returns (World, Version 1.1, 1994.05.27) + +static struct BurnRomInfo joemacrRomDesc[] = { + { "05.u29", 0x080000, 0x74e9a158, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "01.u8l", 0x080000, 0x4da4a2c1, 2 | BRF_GRA }, // 1 Characters & Tiles + { "02.u8h", 0x080000, 0x642c08db, 2 | BRF_GRA }, // 2 + + { "mbn01", 0x080000, 0xa3a37353, 3 | BRF_GRA }, // 3 Sprites + { "mbn02", 0x080000, 0xaa2230c5, 3 | BRF_GRA }, // 4 + + { "mbn04", 0x040000, 0xdcbd4771, 4 | BRF_SND }, // 5 OKI SFX Samples + + { "mbn03", 0x200000, 0x70b71a2a, 5 | BRF_SND }, // 6 OKI Music Samples +}; + +STD_ROM_PICK(joemacr) +STD_ROM_FN(joemacr) + +static INT32 joemacrLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 4, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 6, 1)) return 1; + + *gfxlen0 = 0x100000; + *gfxlen1 = 0x200000; + + return 0; +} + +static INT32 joemacrInit() +{ + return CommonInit(joemacrLoadCallback, joemacr_map, 1, 0x0284); +} + +struct BurnDriver BurnDrvJoemacr = { + "joemacr", NULL, NULL, NULL, "1994", + "Joe & Mac Returns (World, Version 1.1, 1994.05.27)\0", NULL, "Data East", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, joemacrRomInfo, joemacrRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + joemacrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Joe & Mac Returns (World, Version 1.0, 1994.05.19) + +static struct BurnRomInfo joemacraRomDesc[] = { + { "mw00", 0x080000, 0xe1b78f40, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mbn00", 0x100000, 0x11b2dac7, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mbn01", 0x080000, 0xa3a37353, 3 | BRF_GRA }, // 2 Sprites + { "mbn02", 0x080000, 0xaa2230c5, 3 | BRF_GRA }, // 3 + + { "mbn04", 0x040000, 0xdcbd4771, 4 | BRF_SND }, // 4 OKI SFX Samples + + { "mbn03", 0x200000, 0x70b71a2a, 5 | BRF_SND }, // 5 OKI Music Samples +}; + +STD_ROM_PICK(joemacra) +STD_ROM_FN(joemacra) + +static INT32 joemacraLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 3, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 5, 1)) return 1; + + *gfxlen0 = 0x100000; + *gfxlen1 = 0x200000; + + return 0; +} + +static INT32 joemacraInit() +{ + return CommonInit(joemacraLoadCallback, joemacr_map, 1, 0x0284); +} + +struct BurnDriver BurnDrvJoemacra = { + "joemacra", "joemacr", NULL, NULL, "1994", + "Joe & Mac Returns (World, Version 1.0, 1994.05.19)\0", NULL, "Data East", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, joemacraRomInfo, joemacraRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + joemacraInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Chain Reaction (World, Version 2.2, 1995.09.25) + +static struct BurnRomInfo chainrecRomDesc[] = { + { "e1", 0x080000, 0x8a8340ef, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcc-00", 0x100000, 0x646b03ec, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "u3", 0x080000, 0x92659721, 3 | BRF_GRA }, // 2 Sprites + { "u4", 0x080000, 0xe304eb32, 3 | BRF_GRA }, // 3 + { "u5", 0x080000, 0x1b6f01ea, 3 | BRF_GRA }, // 4 + { "u6", 0x080000, 0x531a56f2, 3 | BRF_GRA }, // 5 + + { "mcc-04", 0x040000, 0x86ee6ade, 4 | BRF_SND }, // 6 OKI SFX Samples + + { "mcc-03", 0x100000, 0xda2ebba0, 5 | BRF_SND }, // 7 OKI Music Samples + + { "eeprom-chainrec.bin", 0x000080, 0xb6da3fbf, 6 | BRF_PRG | BRF_ESS }, // 8 Default EEPROM Data +}; + +STD_ROM_PICK(chainrec) +STD_ROM_FN(chainrec) + +static INT32 chainrecLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 2, 4)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000002, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000003, 5, 4)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvEEPROM + 0x000000, 8, 1)) return 1; + + *gfxlen0 = 0x100000; + *gfxlen1 = 0x200000; + + return 0; +} + +static INT32 chainrecInit() +{ + return CommonInit(chainrecLoadCallback, chainrec_map, 1, 0x02d4); +} + +struct BurnDriver BurnDrvChainrec = { + "chainrec", NULL, NULL, NULL, "1995", + "Chain Reaction (World, Version 2.2, 1995.09.25)\0", NULL, "Data East", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, chainrecRomInfo, chainrecRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + chainrecInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Magical Drop (Japan, Version 1.1, 1995.06.21) + +static struct BurnRomInfo magdropRomDesc[] = { + { "re00-2.e1", 0x080000, 0x7138f10f, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcc-00", 0x100000, 0x646b03ec, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcc-01.a13", 0x100000, 0x13d88745, 3 | BRF_GRA }, // 2 Sprites + { "mcc-02.a14", 0x100000, 0xd0f97126, 3 | BRF_GRA }, // 3 + + { "mcc-04", 0x040000, 0x86ee6ade, 4 | BRF_SND }, // 4 OKI SFX Samples + + { "mcc-03", 0x100000, 0xda2ebba0, 5 | BRF_SND }, // 5 OKI Music Samples + + { "93c45.2h", 0x000080, 0x16ce8d2d, 6 | BRF_PRG | BRF_ESS }, // 6 Default EEPROM Data +}; + +STD_ROM_PICK(magdrop) +STD_ROM_FN(magdrop) + +static INT32 magdropLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 3, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvEEPROM + 0x000000, 6, 1)) return 1; + + *gfxlen0 = 0x100000; + *gfxlen1 = 0x200000; + + return 0; +} + +static INT32 magdropInit() +{ + return CommonInit(magdropLoadCallback, magdrop_map, 1, 0x02d4); +} + +struct BurnDriver BurnDrvMagdrop = { + "magdrop", "chainrec", NULL, NULL, "1995", + "Magical Drop (Japan, Version 1.1, 1995.06.21)\0", NULL, "Data East", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, magdropRomInfo, magdropRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + magdropInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Magical Drop Plus 1 (Japan, Version 2.1, 1995.09.12) + +static struct BurnRomInfo magdroppRomDesc[] = { + { "rz00-1.e1", 0x080000, 0x28caf639, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcc-00", 0x100000, 0x646b03ec, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcc-01.a13", 0x100000, 0x13d88745, 3 | BRF_GRA }, // 2 Sprites + { "mcc-02.a14", 0x100000, 0xd0f97126, 3 | BRF_GRA }, // 3 + + { "mcc-04", 0x040000, 0x86ee6ade, 4 | BRF_SND }, // 4 OKI SFX Samples + + { "mcc-03", 0x100000, 0xda2ebba0, 5 | BRF_SND }, // 5 OKI Music Samples + + { "eeprom.2h", 0x000080, 0xd13d9edd, 6 | BRF_PRG | BRF_ESS }, // 6 Default EEPROM Data +}; + +STD_ROM_PICK(magdropp) +STD_ROM_FN(magdropp) + +static INT32 magdroppInit() +{ + return CommonInit(magdropLoadCallback, magdropp_map, 1, 0x02d4); +} + +struct BurnDriver BurnDrvMagdropp = { + "magdropp", "chainrec", NULL, NULL, "1995", + "Magical Drop Plus 1 (Japan, Version 2.1, 1995.09.12)\0", NULL, "Data East", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, magdroppRomInfo, magdroppRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + magdroppInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Charlie Ninja + +static struct BurnRomInfo charlienRomDesc[] = { + { "nd00-1.1e", 0x080000, 0xf18f4b23, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mbr-00.9a", 0x200000, 0xecf2c7f0, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mbr-01.14a", 0x100000, 0x46c90215, 3 | BRF_GRA }, // 2 Sprites + { "mbr-03.14h", 0x100000, 0xc448a68a, 3 | BRF_GRA }, // 3 + + { "nd01-0.13h", 0x040000, 0x635a100a, 4 | BRF_SND }, // 4 OKI SFX Samples + + { "mbr-02.12f", 0x100000, 0x4f67d333, 5 | BRF_SND }, // 5 OKI Music Samples +}; + +STD_ROM_PICK(charlien) +STD_ROM_FN(charlien) + +static INT32 charlienLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + for (INT32 i = 0; i < 0x80000; i++) { + INT32 t = DrvGfxROM0[0x080000 + i]; + DrvGfxROM0[0x080000 + i] = DrvGfxROM0[0x100000 + i]; + DrvGfxROM0[0x100000 + i] = t; + } + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 3, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 5, 1)) return 1; + + *gfxlen0 = 0x200000; + *gfxlen1 = 0x200000; + + return 0; +} + +static INT32 charlienInit() +{ + return CommonInit(charlienLoadCallback, mitchell_map, 2, 0xc8c8); +} + +struct BurnDriver BurnDrvCharlien = { + "charlien", NULL, NULL, NULL, "1995", + "Charlie Ninja\0", NULL, "Mitchell", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, charlienRomInfo, charlienRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + charlienInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Party Time: Gonta the Diver II / Ganbare! Gonta!! 2 (World Release) + +static struct BurnRomInfo prtytimeRomDesc[] = { + { "pz_00-0.1e", 0x080000, 0xec715c87, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcb-00.9a", 0x200000, 0xc48a4f2b, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcb-02.14a", 0x200000, 0x423cfb38, 3 | BRF_GRA }, // 2 Sprites + { "mcb-05.14h", 0x200000, 0x81540cfb, 3 | BRF_GRA }, // 3 + { "mcb-01.13a", 0x200000, 0x06f40a57, 3 | BRF_GRA }, // 4 + { "mcb-03.14d", 0x200000, 0x0aef73af, 3 | BRF_GRA }, // 5 + + { "pz_01-0.13h", 0x040000, 0x8925bce2, 4 | BRF_SND }, // 6 OKI SFX Samples + + { "mcb-04.12f", 0x200000, 0xe23d3590, 5 | BRF_SND }, // 7 OKI Music Samples + + { "eeprom-prtytime.bin", 0x000080, 0x105700da, 6 | BRF_PRG | BRF_ESS }, // 8 Default EEPROM Data +}; + +STD_ROM_PICK(prtytime) +STD_ROM_FN(prtytime) + +static INT32 prtytimeLoadCallback(INT32 *gfxlen0, INT32 *gfxlen1) +{ + if (BurnLoadRom(DrvArmROM + 0x000000, 0, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 1, 1)) return 1; + for (INT32 i = 0; i < 0x80000; i++) { + INT32 t = DrvGfxROM0[0x080000 + i]; + DrvGfxROM0[0x080000 + i] = DrvGfxROM0[0x100000 + i]; + DrvGfxROM0[0x100000 + i] = t; + } + + if (BurnLoadRom(DrvGfxROM2 + 0x000001, 2, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 3, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x400000, 5, 2)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvEEPROM + 0x000000, 8, 1)) return 1; + + *gfxlen0 = 0x200000; + *gfxlen1 = 0x800000; + + return 0; +} + +static INT32 prtytimeInit() +{ + return CommonInit(prtytimeLoadCallback, mitchell_map, 2, 0x04f0); +} + +struct BurnDriver BurnDrvPrtytime = { + "prtytime", NULL, NULL, NULL, "1995", + "Party Time: Gonta the Diver II / Ganbare! Gonta!! 2 (World Release)\0", NULL, "Mitchell", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, prtytimeRomInfo, prtytimeRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + prtytimeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 320, 3, 4 +}; + + +// Ganbare! Gonta!! 2 / Party Time: Gonta the Diver II (Japan Release) + +static struct BurnRomInfo gangontaRomDesc[] = { + { "rd_00-0.1e", 0x080000, 0xf80f43bb, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcb-00.9a", 0x200000, 0xc48a4f2b, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcb-02.14a", 0x200000, 0x423cfb38, 3 | BRF_GRA }, // 2 Sprites + { "mcb-05.14h", 0x200000, 0x81540cfb, 3 | BRF_GRA }, // 3 + { "mcb-01.13a", 0x200000, 0x06f40a57, 3 | BRF_GRA }, // 4 + { "mcb-03.14d", 0x200000, 0x0aef73af, 3 | BRF_GRA }, // 5 + + { "rd_01-0.13h", 0x040000, 0x70fd18c6, 4 | BRF_SND }, // 6 OKI SFX Samples + + { "mcb-04.12f", 0x200000, 0xe23d3590, 5 | BRF_SND }, // 7 OKI Music Samples + + { "eeprom-gangonta.bin", 0x000080, 0x27ba60a5, 6 | BRF_PRG | BRF_ESS }, // 8 Default EEPROM Data +}; + +STD_ROM_PICK(gangonta) +STD_ROM_FN(gangonta) + +struct BurnDriver BurnDrvGangonta = { + "gangonta", "prtytime", NULL, NULL, "1995", + "Ganbare! Gonta!! 2 / Party Time: Gonta the Diver II (Japan Release)\0", NULL, "Mitchell", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, gangontaRomInfo, gangontaRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + prtytimeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 320, 3, 4 +}; + + +// Osman (World) + +static struct BurnRomInfo osmanRomDesc[] = { + { "sa00-0.1e", 0x080000, 0xec6b3257, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcf-00.9a", 0x200000, 0x247712dc, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcf-02.14a", 0x200000, 0x21251b33, 3 | BRF_GRA }, // 2 Sprites + { "mcf-04.14h", 0x200000, 0x4fa55577, 3 | BRF_GRA }, // 3 + { "mcf-01.13a", 0x200000, 0x83881e25, 3 | BRF_GRA }, // 4 + { "mcf-03.14d", 0x200000, 0xfaf1d51d, 3 | BRF_GRA }, // 5 + + { "sa01-0.13h", 0x040000, 0xcea8368e, 4 | BRF_SND }, // 6 OKI SFX Samples + + { "mcf-05.12f", 0x200000, 0xf007d376, 5 | BRF_SND }, // 7 OKI Music Samples + + { "eeprom-osman.bin", 0x000080, 0x509552b2, 6 | BRF_PRG | BRF_ESS }, // 8 Default EEPROM Data +}; + +STD_ROM_PICK(osman) +STD_ROM_FN(osman) + +static INT32 osmanInit() +{ + return CommonInit(prtytimeLoadCallback, mitchell_map, 2, 0x5974); +} + +struct BurnDriver BurnDrvOsman = { + "osman", NULL, NULL, NULL, "1996", + "Osman (World)\0", NULL, "Mitchell", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, osmanRomInfo, osmanRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + osmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Cannon Dancer (Japan) + +static struct BurnRomInfo candanceRomDesc[] = { + { "sa00-0.1e", 0x080000, 0xec6b3257, 1 | BRF_PRG | BRF_ESS }, // 0 ARM Code + + { "mcf-00.9a", 0x200000, 0x247712dc, 2 | BRF_GRA }, // 1 Characters & Tiles + + { "mcf-02.14a", 0x200000, 0x21251b33, 3 | BRF_GRA }, // 2 Sprites + { "mcf-04.14h", 0x200000, 0x4fa55577, 3 | BRF_GRA }, // 3 + { "mcf-01.13a", 0x200000, 0x83881e25, 3 | BRF_GRA }, // 4 + { "mcf-03.14d", 0x200000, 0xfaf1d51d, 3 | BRF_GRA }, // 5 + + { "sa01-0.13h", 0x040000, 0xcea8368e, 4 | BRF_SND }, // 6 OKI SFX Samples + + { "mcf-05.12f", 0x200000, 0xf007d376, 5 | BRF_SND }, // 7 OKI Music Samples + + { "eeprom-candance.bin", 0x000080, 0x0a0a8f6b, 6 | BRF_PRG | BRF_ESS }, // 8 Default EEPROM Data +}; + +STD_ROM_PICK(candance) +STD_ROM_FN(candance) + +struct BurnDriver BurnDrvCandance = { + "candance", "osman", NULL, NULL, "1996", + "Cannon Dancer (Japan)\0", NULL, "Mitchell (Atlus license)", "Simple 156", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, candanceRomInfo, candanceRomName, NULL, NULL, Simpl156InputInfo, Simpl156DIPInfo, + osmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_speedspn.cpp b/src/burn/drivers/misc_post90s/d_speedspn.cpp new file mode 100644 index 00000000..b2589138 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_speedspn.cpp @@ -0,0 +1,637 @@ +// FB Alpha Speed Spin driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvVidRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvAttrRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *display_enable; +static UINT8 *banks; + +static UINT8 DrvInputs[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static INT32 black_color; + +static struct BurnInputInfo SpeedspnInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 7, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 6, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 5, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 7, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 6, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 5, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 2, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Speedspn) + +static struct BurnDIPInfo SpeedspnDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x01, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x04, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "5 Coins/2 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "4 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "4 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "3 Coins/5 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0xf0, 0x10, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "5 Coins/2 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "4 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "4 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "3 Coins/5 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 5 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2, "World Cup" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Backhand" }, + {0x14, 0x01, 0x02, 0x02, "Automatic" }, + {0x14, 0x01, 0x02, 0x00, "Manual" }, + + {0 , 0xfe, 0 , 4, "Points to Win" }, + {0x14, 0x01, 0x0c, 0x0c, "11 Points and 1 Adv." }, + {0x14, 0x01, 0x0c, 0x08, "11 Points and 2 Adv." }, + {0x14, 0x01, 0x0c, 0x04, "21 Points and 1 Adv." }, + {0x14, 0x01, 0x0c, 0x00, "21 Points and 2 Adv." }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x10, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + +}; + +STDDIPINFO(Speedspn) + +static void bankswitch(INT32 data) +{ + const INT32 offsets[10] = { + 0x30000, 0x1c000, 0x24000, 0x5c000, 0x50000, 0x44000, 0x20000, 0x54000, 0x58000, 0x08000 + }; + + banks[0] = (data > 8) ? 9 : data; + + ZetMapArea(0xc000, 0xffff, 0, DrvZ80ROM0 + offsets[banks[0]]); + ZetMapArea(0xc000, 0xffff, 2, DrvZ80ROM0 + offsets[banks[0]]); +} + +static void vidram_bankswitch(INT32 data) +{ + banks[1] = data & 1; + + ZetMapArea(0x9000, 0x9fff, 0, DrvVidRAM + banks[1] * 0x1000); + ZetMapArea(0x9000, 0x9fff, 1, DrvVidRAM + banks[1] * 0x1000); + ZetMapArea(0x9000, 0x9fff, 2, DrvVidRAM + banks[1] * 0x1000); +} + +static inline void speedspn_palette_write(INT32 offset) +{ + INT32 r = DrvPalRAM[offset + 1] & 0x0f; + INT32 g = DrvPalRAM[offset + 0] >> 4; + INT32 b = DrvPalRAM[offset + 0] & 0x0f; + + offset /= 2; + + DrvPalette[offset] = BurnHighCol((r << 4) | r, (g << 4) | g, (b << 4) | b, 0); + if (DrvPalette[offset] == 0) black_color = offset; +} + +void __fastcall speedspn_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0x8000) { + address &= 0x7ff; + + if (data != DrvPalRAM[address]) { + DrvPalRAM[address] = data; + + speedspn_palette_write(address & ~1); + } + } +} + +void __fastcall speedspn_main_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x01: + case 0x10: // ? + return; + + case 0x07: + *display_enable = ~data & 1; + return; + + case 0x12: + bankswitch(data); + return; + + case 0x13: + *soundlatch = data; + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + return; + + case 0x17: + vidram_bankswitch(data); + return; + } +} + +UINT8 __fastcall speedspn_main_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x10: + return DrvInputs[0]; + + case 0x11: + return DrvInputs[1]; + + case 0x12: + return DrvInputs[2]; + + case 0x13: + return DrvDips[0]; + + case 0x14: + return DrvDips[1]; + + case 0x16: + return 0; // irq ack? + } + + return 0; +} + +static void oki_bankswitch(INT32 data) +{ + banks[2] = data & 3; + + MSM6295ROM = DrvSndROM + (banks[2] * 0x40000); + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295SampleInfo[0][nChannel] = MSM6295ROM + (nChannel << 8); + MSM6295SampleData[0][nChannel] = MSM6295ROM + (nChannel << 16); + } +} + +void __fastcall speedspn_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + oki_bankswitch(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall speedspn_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + bankswitch(0); + vidram_bankswitch(0); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + oki_bankswitch(1); + MSM6295Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x090000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x080000; + + DrvSndROM = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x002000; + DrvZ80RAM1 = Next; Next += 0x000800; + + DrvVidRAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x000800; + DrvAttrRAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + display_enable = Next; Next += 0x000001; + banks = Next; Next += 0x000003; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x200000, 0x300000, 0x000000, 0x100000 }; + INT32 XOffs0[8] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 }; + INT32 YOffs0[8] = { 0x038, 0x030, 0x028, 0x020, 0x018, 0x010, 0x008, 0x000 }; + + INT32 Plane1[4] = { 0x000004, 0x000000, 0x100004, 0x100000 }; + INT32 XOffs1[16] = { 0x10b, 0x10a, 0x109, 0x108, 0x103, 0x102, 0x101, 0x100, + 0x00b, 0x00a, 0x009, 0x008, 0x003, 0x002, 0x001, 0x000 }; + INT32 YOffs1[16] = { 0x0f0, 0x0e0, 0x0d0, 0x0c0, 0x0b0, 0x0a0, 0x090, 0x080, + 0x070, 0x060, 0x050, 0x040, 0x030, 0x020, 0x010, 0x000 }; + + UINT8 *tmp = (UINT8*)malloc(0x80000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x80000; i++) tmp[i] = DrvGfxROM0[i] ^ 0xff; + + GfxDecode(0x4000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + for (INT32 i = 0; i < 0x40000; i++) tmp[i] = DrvGfxROM1[i] ^ 0xff; + + GfxDecode(0x0800, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x200, tmp, DrvGfxROM1); + + if (tmp) { + free (tmp); + tmp = NULL; + } + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x000000, 0, 1)) return 1; + memmove (DrvZ80ROM0 + 0x10000, DrvZ80ROM0 + 0x08000, 0x78000); + + if (BurnLoadRom(DrvZ80ROM1 + 0x000000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 1)) return 1; + memcpy (DrvSndROM + 0x000000, DrvGfxROM0 + 0x000000, 0x020000); + memcpy (DrvSndROM + 0x040000, DrvGfxROM0 + 0x000000, 0x020000); + memcpy (DrvSndROM + 0x080000, DrvGfxROM0 + 0x000000, 0x020000); + memcpy (DrvSndROM + 0x0c0000, DrvGfxROM0 + 0x000000, 0x020000); + memcpy (DrvSndROM + 0x020000, DrvGfxROM0 + 0x000000, 0x020000); + memcpy (DrvSndROM + 0x060000, DrvGfxROM0 + 0x020000, 0x020000); + memcpy (DrvSndROM + 0x0a0000, DrvGfxROM0 + 0x040000, 0x020000); + memcpy (DrvSndROM + 0x0e0000, DrvGfxROM0 + 0x060000, 0x020000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x020000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x060000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 8, 1)) return 1; + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0x87ff, 0, DrvPalRAM); +// ZetMapArea(0x8000, 0x87ff, 1, DrvPalRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvPalRAM); + ZetMapArea(0x8800, 0x8fff, 0, DrvAttrRAM); + ZetMapArea(0x8800, 0x8fff, 1, DrvAttrRAM); + ZetMapArea(0x8800, 0x8fff, 2, DrvAttrRAM); + ZetMapArea(0xa000, 0xbfff, 0, DrvZ80RAM0); + ZetMapArea(0xa000, 0xbfff, 1, DrvZ80RAM0); + ZetMapArea(0xa000, 0xbfff, 2, DrvZ80RAM0); + ZetSetWriteHandler(speedspn_main_write); + ZetSetOutHandler(speedspn_main_write_port); + ZetSetInHandler(speedspn_main_read_port); + ZetMemEnd(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(speedspn_sound_write); + ZetSetReadHandler(speedspn_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1122000 / 132, 100.0, 0); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + MSM6295Exit(0); + + if (AllMem) { + free (AllMem); + AllMem = NULL; + } + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_layer() +{ + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (((offs / 32) << 3) + 192) & 0x1ff; + INT32 sy = (((offs & 0x1f) << 3) - 8) & 0x0ff; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = DrvVidRAM[offs * 2 + 1] | ((DrvVidRAM[offs * 2 + 0] & 0x3f) << 8); + INT32 color = DrvAttrRAM[offs ^ 0x400]; + + if (color & 0x80) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color & 0x3f, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color & 0x3f, 4, 0, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x1000; offs < 0x2000; offs += 4) + { + INT32 sy = DrvVidRAM[offs + 3]; + INT32 attr = DrvVidRAM[offs + 2]; + INT32 code = DrvVidRAM[offs + 1] + ((attr & 0xe0) << 3); + INT32 sx = DrvVidRAM[offs + 0] + ((attr & 0x10) << 4); + + if (attr == 0 && sx != 0) // fix junk on char. select screen + break; + + if (attr == 0 && code == 0) // speedup + continue; + + Render16x16Tile_Mask_Clip(pTransDraw, code, (0x1f8 - sx) - 64, sy - 8, attr & 0x0f, 4, 0x0f, 0, DrvGfxROM1); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i+=2) { + speedspn_palette_write(i); + } + DrvRecalc = 0; + } + + if (*display_enable) + { + draw_layer(); + draw_sprites(); + } + else + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = black_color; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 6000000 / 60, 6000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment; + + ZetOpen(0); + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nSegment); + ZetClose(); + } + + if (pBurnSoundOut) { + MSM6295Render(0,pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + MSM6295Scan(0, nAction); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(banks[0]); + vidram_bankswitch(banks[1]); + ZetClose(); + + oki_bankswitch(banks[2]); + + DrvRecalc = 1; + } + + return 0; +} + + +// Speed Spin + +static struct BurnRomInfo speedspnRomDesc[] = { + { "tch-ss1.u78", 0x80000, 0x41b6b45b, 1 | BRF_PRG | BRF_ESS }, // 0 Main Z80 Code + + { "tch-ss2.u96", 0x10000, 0x4611fd0c, 2 | BRF_PRG | BRF_ESS }, // 1 Sound Z80 Code + + { "tch-ss3.u95", 0x80000, 0x1c9deb5e, 3 | BRF_SND }, // 2 Samples + + { "tch-ss4.u70", 0x20000, 0x41517859, 4 | BRF_GRA }, // 3 Background Tiles + { "tch-ss5.u69", 0x20000, 0x832b2f34, 4 | BRF_GRA }, // 4 + { "tch-ss6.u60", 0x20000, 0xf1fd7289, 4 | BRF_GRA }, // 5 + { "tch-ss7.u59", 0x20000, 0xc4958543, 4 | BRF_GRA }, // 6 + + { "tch-ss8.u39", 0x20000, 0x2f27b16d, 5 | BRF_GRA }, // 7 Sprites + { "tch-ss9.u34", 0x20000, 0xc372f8ec, 5 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(speedspn) +STD_ROM_FN(speedspn) + +struct BurnDriver BurnDrvSpeedspn = { + "speedspn", NULL, NULL, NULL, "1994", + "Speed Spin\0", NULL, "TCH", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, speedspnRomInfo, speedspnRomName, NULL, NULL, SpeedspnInputInfo, SpeedspnDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 384, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_suna16.cpp b/src/burn/drivers/misc_post90s/d_suna16.cpp new file mode 100644 index 00000000..1bbebd8a --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_suna16.cpp @@ -0,0 +1,2359 @@ +// FB Alpha SunA 16-bit hardware driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "burn_ym3526.h" +#include "driver.h" +#include "dac.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvGfxROM0; +static UINT32 nGfxROM0Len; +static UINT8 *DrvGfxROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvSprRAM0; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalRAM2; +static UINT32 *Palette; +static UINT32 *DrvPalette; + +static INT16 *pFMBuffer; +static INT16 *pAY8910Buffer[3]; +static INT16 *pSoundBuffer; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvJoy6[16]; + +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static UINT16 DrvInputs[6]; + +static INT32 game_select = 0; + +static UINT8 soundlatch; +static UINT8 soundlatch2; +static UINT8 soundlatch3; +static UINT8 flipscreen; +static UINT8 color_bank; + +static UINT8 bestofbest_prot = 0; + +static UINT8 z80bankdata[2]; + +static struct BurnInputInfo BestbestInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 15, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 15, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 14, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy1 + 9, "p1 fire 4"}, + {"P1 Button 5" , BIT_DIGITAL , DrvJoy1 + 10, "p1 fire 5"}, + {"P1 Button 6" , BIT_DIGITAL , DrvJoy1 + 11, "p1 fire 6"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 14, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy2 + 9, "p2 fire 4"}, + {"P2 Button 5" , BIT_DIGITAL , DrvJoy2 + 10, "p2 fire 5"}, + {"P2 Button 6" , BIT_DIGITAL , DrvJoy2 + 11, "p2 fire 6"}, + + {"Service" , BIT_DIGITAL , DrvJoy3 + 6, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Bestbest) + +static struct BurnInputInfo UballoonInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 15, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 15, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 14, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 14, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 12, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Uballoon) + +static struct BurnInputInfo BssoccerInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy6 + 4, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy6 + 5, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvJoy6 + 6, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , DrvJoy6 + 7, "p4 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 3"}, + + {"P3 Start" , BIT_DIGITAL , DrvJoy3 + 7, "p3 start" }, + {"P3 Up" , BIT_DIGITAL , DrvJoy3 + 0, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvJoy3 + 1, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvJoy3 + 2, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvJoy3 + 3, "p3 right" }, + {"P3 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p3 fire 1"}, + {"P3 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p3 fire 2"}, + {"P3 Button 3" , BIT_DIGITAL , DrvJoy3 + 6, "p3 fire 3"}, + + {"P4 Start" , BIT_DIGITAL , DrvJoy4 + 7, "p4 start" }, + {"P4 Up" , BIT_DIGITAL , DrvJoy4 + 0, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvJoy4 + 1, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvJoy4 + 2, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvJoy4 + 3, "p4 right" }, + {"P4 Button 1" , BIT_DIGITAL , DrvJoy4 + 4, "p4 fire 1"}, + {"P4 Button 2" , BIT_DIGITAL , DrvJoy4 + 5, "p4 fire 2"}, + {"P4 Button 3" , BIT_DIGITAL , DrvJoy4 + 6, "p4 fire 3"}, + + {"Service" , BIT_DIGITAL , DrvJoy3 + 6, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Bssoccer) + +static struct BurnInputInfo SunaqInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 6, "p1 start" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 1, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 2, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy1 + 3, "p1 fire 4"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 6, "p2 start" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 2, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy2 + 3, "p2 fire 4"}, + + {"Service" , BIT_DIGITAL , DrvJoy3 + 6, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Sunaq) + +static struct BurnDIPInfo bestbestDIPList[]= +{ + {0x1a, 0xff, 0xff, 0xff, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + + {0x1a, 0xfe, 0, 8, "Coinage" }, + {0x1a, 0x01, 0x07, 0x00, "5C 1C" }, + {0x1a, 0x01, 0x07, 0x01, "4C 1C" }, + {0x1a, 0x01, 0x07, 0x02, "3C 1C" }, + {0x1a, 0x01, 0x07, 0x03, "2C 1C" }, + {0x1a, 0x01, 0x07, 0x07, "1C 1C" }, + {0x1a, 0x01, 0x07, 0x06, "1C 2C" }, + {0x1a, 0x01, 0x07, 0x05, "1C 3C" }, + {0x1a, 0x01, 0x07, 0x04, "1C 4C" }, + + {0x1a, 0xfe, 0, 4, "Difficulty" }, + {0x1a, 0x01, 0x18, 0x18, "Easy" }, + {0x1a, 0x01, 0x18, 0x10, "Normal" }, + {0x1a, 0x01, 0x18, 0x08, "Hard" }, + {0x1a, 0x01, 0x18, 0x00, "Hardest" }, + + {0x1a, 0xfe, 0, 2, "Display Combos" }, + {0x1a, 0x01, 0x20, 0x00, "Off" }, + {0x1a, 0x01, 0x20, 0x20, "On" }, + + {0x1a, 0xfe, 0, 2, "Demo Sounds" }, + {0x1a, 0x01, 0x80, 0x80, "Off" }, + {0x1a, 0x01, 0x80, 0x00, "On" }, + + {0x1b, 0xfe, 0, 2, "Flip Screen" }, + {0x1b, 0x01, 0x01, 0x01, "Off" }, + {0x1b, 0x01, 0x01, 0x00, "On" }, + + {0x1b, 0xfe, 0, 4, "Play Time" }, + {0x1b, 0x01, 0x06, 0x06, "1:10" }, + {0x1b, 0x01, 0x06, 0x04, "1:20" }, + {0x1b, 0x01, 0x06, 0x02, "1:30" }, + {0x1b, 0x01, 0x06, 0x00, "1:40" }, +}; + +STDDIPINFO(bestbest) + +static struct BurnDIPInfo bssoccerDIPList[]= +{ + {0x26, 0xff, 0xff, 0xff, NULL }, + {0x27, 0xff, 0xff, 0xff, NULL }, + {0x28, 0xff, 0xff, 0xff, NULL }, + + {0x26, 0xfe, 0, 8, "Coinage" }, + {0x26, 0x01, 0x07, 0x00, "4C 1C" }, + {0x26, 0x01, 0x07, 0x01, "3C 1C" }, + {0x26, 0x01, 0x07, 0x02, "2C 1C" }, + {0x26, 0x01, 0x07, 0x07, "1C 1C" }, + {0x26, 0x01, 0x07, 0x06, "1C 2C" }, + {0x26, 0x01, 0x07, 0x05, "1C 3C" }, + {0x26, 0x01, 0x07, 0x04, "1C 4C" }, + {0x26, 0x01, 0x07, 0x03, "1C 5C" }, + + {0x26, 0xfe, 0, 4, "Difficulty" }, + {0x26, 0x01, 0x18, 0x10, "Easy" }, + {0x26, 0x01, 0x18, 0x18, "Normal" }, + {0x26, 0x01, 0x18, 0x08, "Hard" }, + {0x26, 0x01, 0x18, 0x00, "Hardest?" }, + + {0x26, 0xfe, 0, 2, "Demo Sounds" }, + {0x26, 0x01, 0x20, 0x00, "Off" }, + {0x26, 0x01, 0x20, 0x20, "On" }, + + {0x26, 0xfe, 0, 2, "Flip Screen" }, + {0x26, 0x01, 0x40, 0x40, "Off" }, + {0x26, 0x01, 0x40, 0x00, "On" }, + + {0x27, 0xfe, 0, 4, "Play Time P1" }, + {0x27, 0x01, 0x03, 0x03, "1:30" }, + {0x27, 0x01, 0x03, 0x02, "1:45" }, + {0x27, 0x01, 0x03, 0x01, "2:00" }, + {0x27, 0x01, 0x03, 0x00, "2:15" }, + + {0x27, 0xfe, 0, 4, "Play Time P2" }, + {0x27, 0x01, 0x0c, 0x0c, "1:30" }, + {0x27, 0x01, 0x0c, 0x08, "1:45" }, + {0x27, 0x01, 0x0c, 0x04, "2:00" }, + {0x27, 0x01, 0x0c, 0x00, "2:15" }, + + {0x27, 0xfe, 0, 4, "Play Time P3" }, + {0x27, 0x01, 0x30, 0x30, "1:30" }, + {0x27, 0x01, 0x30, 0x20, "1:45" }, + {0x27, 0x01, 0x30, 0x10, "2:00" }, + {0x27, 0x01, 0x30, 0x00, "2:15" }, + + {0x27, 0xfe, 0, 4, "Play Time P4" }, + {0x27, 0x01, 0xc0, 0xc0, "1:30" }, + {0x27, 0x01, 0xc0, 0x80, "1:45" }, + {0x27, 0x01, 0xc0, 0x40, "2:00" }, + {0x27, 0x01, 0xc0, 0x00, "2:15" }, + + {0x28, 0xfe, 0, 2, "Copyright" }, + {0x28, 0x01, 0x01, 0x01, "Distributer Unico" }, + {0x28, 0x01, 0x01, 0x00, "All Rights Reserved" }, +}; + +STDDIPINFO(bssoccer) + + +static struct BurnDIPInfo sunaqDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xcf, NULL }, + + {0x0e, 0xfe, 0, 8, "Coinage" }, + {0x0e, 0x01, 0x07, 0x00, "5C 1C" }, + {0x0e, 0x01, 0x07, 0x01, "4C 1C" }, + {0x0e, 0x01, 0x07, 0x02, "3C 1C" }, + {0x0e, 0x01, 0x07, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x07, 0x07, "1C 1C" }, + {0x0e, 0x01, 0x07, 0x06, "1C 2C" }, + {0x0e, 0x01, 0x07, 0x05, "1C 3C" }, + {0x0e, 0x01, 0x07, 0x04, "1C 4C" }, + + {0x0e, 0xfe, 0, 4, "Difficulty" }, + {0x0e, 0x01, 0x18, 0x00, "Easy" }, + {0x0e, 0x01, 0x18, 0x08, "Normal" }, + {0x0e, 0x01, 0x18, 0x10, "Hard" }, + {0x0e, 0x01, 0x18, 0x18, "Hardest" }, + + {0x0e, 0xfe, 0, 2, "Demo Sounds" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, + + {0x0e, 0xfe, 0, 2, "Flip Screen" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(sunaq) + + +static struct BurnDIPInfo uballoonDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0x12, 0xfe, 0, 2, "Copyright" }, + {0x12, 0x01, 0x30, 0x30, "Distributer Unico" }, + {0x12, 0x01, 0x30, 0x20, "All Rights Reserved" }, +// {0x12, 0x01, 0x30, 0x10, "Distributer Unico" }, +// {0x12, 0x01, 0x30, 0x00, "All Rights Reserved" }, + + {0x13, 0xfe, 0, 8, "Coinage" }, + {0x13, 0x01, 0x07, 0x00, "5C 1C" }, + {0x13, 0x01, 0x07, 0x01, "4C 1C" }, + {0x13, 0x01, 0x07, 0x02, "3C 1C" }, + {0x13, 0x01, 0x07, 0x03, "2C 1C" }, + {0x13, 0x01, 0x07, 0x07, "1C 1C" }, + {0x13, 0x01, 0x07, 0x06, "1C 2C" }, + {0x13, 0x01, 0x07, 0x05, "1C 3C" }, + {0x13, 0x01, 0x07, 0x04, "1C 4C" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x18, 0x10, "2" }, + {0x13, 0x01, 0x18, 0x18, "3" }, + {0x13, 0x01, 0x18, 0x08, "4" }, + {0x13, 0x01, 0x18, 0x00, "5" }, + + {0x13, 0xfe, 0, 4, "Difficulty" }, + {0x13, 0x01, 0x60, 0x40, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Hard" }, + {0x13, 0x01, 0x60, 0x00, "Hardest" }, + + {0x14, 0xfe, 0, 2, "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0x14, 0xfe, 0, 2, "Cabinet" }, + {0x14, 0x01, 0x02, 0x02, "Upright" }, + {0x14, 0x01, 0x02, 0x00, "Cocktail" }, + + {0x14, 0xfe, 0, 8, "Bonus Life" }, + {0x14, 0x01, 0x1c, 0x1c, "200K" }, + {0x14, 0x01, 0x1c, 0x10, "300K, 1000K" }, + {0x14, 0x01, 0x1c, 0x18, "400K" }, + {0x14, 0x01, 0x1c, 0x0c, "500K, 1500K" }, + {0x14, 0x01, 0x1c, 0x08, "500K, 2000K" }, + {0x14, 0x01, 0x1c, 0x04, "500K, 3000K" }, + {0x14, 0x01, 0x1c, 0x14, "600K" }, + {0x14, 0x01, 0x1c, 0x00, "None" }, + + {0x14, 0xfe, 0, 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(uballoon) + + +//------------------------------------------------------------------------------------------------- +// Generic functions + +static void suna_palette_write(INT32 offset) +{ + UINT8 r, b, g; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = (data >> 0) & 0x1f; + r = (r << 3) | (r >> 2); + + g = (data >> 5) & 0x1f; + g = (g << 3) | (g >> 2); + + b = (data >> 10) & 0x1f; + b = (b << 3) | (b >> 2); + + Palette[offset>>1] = (r << 16) | (g << 8) | b; + DrvPalette[offset>>1] = BurnHighCol(r, g, b, 0); + + return; +} + +//------------------------------------------------------------------------------------------------- +// Memory handlers + + +//---------------------------------------------------------------- +// Best of Best + + +//------------------ +// 68k + +UINT16 __fastcall bestbest_read_word(UINT32 address) +{ + switch (address & ~1) + { + case 0x500000: + return DrvInputs[0]; + + case 0x500002: + return DrvInputs[1]; + + case 0x500004: + return DrvInputs[2]; + } + + return 0; +} + +UINT8 __fastcall bestbest_read_byte(UINT32 address) +{ + switch (address) + { + case 0x500000: + case 0x500001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x500002: + case 0x500003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x500004: + case 0x500005: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0x500019: + return bestofbest_prot; + } + + return 0; +} + +void __fastcall bestbest_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0x540000) { + *((UINT16*)(DrvPalRAM + (address & 0x0fff))) = data; + suna_palette_write(address & 0xffe); + return; + } + + switch (address & ~1) + { + case 0x500000: + soundlatch = data; + return; + + case 0x500002: + flipscreen = data & 0x10; + return; + } + + return; +} + +void __fastcall bestbest_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff000) == 0x540000) { + DrvPalRAM[address & 0xfff] = data; + suna_palette_write(address & 0xffe); + return; + } + + switch (address) + { + case 0x500000: + case 0x500001: + soundlatch = data; + return; + + case 0x500002: + case 0x500003: + flipscreen = data & 0x10; + return; + + case 0x500008: + case 0x500009: + switch (data & 0xff) { + case 0x00: bestofbest_prot ^= 0x09; break; + case 0x08: bestofbest_prot ^= 0x02; break; + case 0x0c: bestofbest_prot ^= 0x03; break; + } + return; + } + + return; +} + +//------------------ +// Z80 #0 + +void __fastcall bestbest_sound0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: + case 0xc001: + BurnYM3526Write(address & 1, data); + return; + + case 0xc002: + case 0xc003: + AY8910Write(0, address & 1, data); + return; + + case 0xf000: + soundlatch2 = data; + return; + } + + return; +} + +UINT8 __fastcall bestbest_sound0_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + return soundlatch; + } + + return 0; +} + +//------------------ +// Z80 #1 + +void __fastcall bestbest_sound1_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: { DACWrite(0, (data & 0xf) * 0x11); return; } + case 0x01: { DACWrite(1, (data & 0xf) * 0x11); return; } + + case 0x02: { DACWrite(2, (data & 0xf) * 0x11); return; } + case 0x03: { DACWrite(3, (data & 0xf) * 0x11); return; } + } + + return; +} + +UINT8 __fastcall bestbest_sound1_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return soundlatch2; + } + + return 0; +} + + +//---------------------------------------------------------------- +// SunA Quiz + + +//------------------ +// 68k + +UINT16 __fastcall sunaq_read_word(UINT32 address) +{ + if ((address & 0xfff000) == 0x540000) { + if (address & 0x200) { + return *((UINT16*)(DrvPalRAM2 + (address & 0xffe))); + } else { + address += color_bank << 9; + return *((UINT16*)(DrvPalRAM + (address & 0xffe))); + } + } + + switch (address & ~1) + { + case 0x500000: + return DrvInputs[0]; + + case 0x500002: + return DrvInputs[1]; + + case 0x500004: + return DrvInputs[2]; + + case 0x500006: + return DrvInputs[3]; + } + + return 0; +} + +UINT8 __fastcall sunaq_read_byte(UINT32 address) +{ + if ((address & 0xfff000) == 0x540000) { + if (address & 0x200) { + return DrvPalRAM2[address & 0xffe]; + } else { + address += color_bank << 9; + return DrvPalRAM[address & 0xffe]; + } + } + + switch (address) + { + case 0x500000: + case 0x500001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x500002: + case 0x500003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x500004: + case 0x500005: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0x500006: + case 0x500007: + return DrvInputs[3] >> ((~address & 1) << 3); + } + + return 0; +} + +void __fastcall sunaq_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0x540000) { + if (address & 0x200) { + *((UINT16*)(DrvPalRAM2 + (address & 0xffff))) = data; + } else { + address += color_bank << 9; + *((UINT16*)(DrvPalRAM + (address & 0xffff))) = data; + suna_palette_write(address & 0xffff); + } + return; + } + + switch (address & ~1) + { + case 0x500000: + soundlatch = data; + return; + + case 0x500002: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + + case 0x500004: + // coin counter + return; + } + return; +} + +void __fastcall sunaq_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff000) == 0x540000) { + if (address & 0x200) { + DrvPalRAM2[address & 0xfff] = data; + } else { + address += color_bank << 9; + DrvPalRAM[address & 0xfff] = data; + suna_palette_write(address & 0xffe); + } + + return; + } + + switch (address) + { + case 0x500000: + case 0x500001: + soundlatch = data; + return; + + case 0x500002: + case 0x500003: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + + case 0x500004: + case 0x500005: + // coin counter + return; + } + return; +} + +//------------------ +// Z80 #0 + +void __fastcall sunaq_sound0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + BurnYM2151SelectRegister(data); + return; + + case 0xf801: + BurnYM2151WriteRegister(data); + return; + + case 0xfc00: + soundlatch2 = data; + return; + } + + return; +} + + +//---------------------------------------------------------------- +// Ultra Balloon + + +//------------------ +// 68k + +UINT16 __fastcall uballoon_read_word(UINT32 address) +{ + if ((address & 0xfff000) == 0x200000) { + if (address & 0x200) { + return *((UINT16*)(DrvPalRAM2 + (address & 0xffe))); + } else { + address += color_bank << 9; + return *((UINT16*)(DrvPalRAM + (address & 0xffe))); + } + } + + switch (address & ~1) + { + case 0x600000: + return DrvInputs[0]; + + case 0x600002: + return DrvInputs[1]; + + case 0x600004: + return DrvInputs[2]; + + case 0x600006: + return DrvInputs[3]; + } + + return 0; +} + +UINT8 __fastcall uballoon_read_byte(UINT32 address) +{ + if ((address & 0xfff000) == 0x200000) { + if (address & 0x200) { + return DrvPalRAM2[address & 0xffe]; + } else { + address += color_bank << 9; + return DrvPalRAM[address & 0xffe]; + } + } + + switch (address) + { + case 0x600000: + case 0x600001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x600002: + case 0x600003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x600004: + case 0x600005: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0x600006: + case 0x600007: + return DrvInputs[3] >> ((~address & 1) << 3); + } + + return 0; +} + +void __fastcall uballoon_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0x200000) { + if (address & 0x200) { + *((UINT16*)(DrvPalRAM2 + (address & 0xffff))) = data; + } else { + address += color_bank << 9; + *((UINT16*)(DrvPalRAM + (address & 0xffff))) = data; + suna_palette_write(address & 0xffff); + } + return; + } + + switch (address & ~1) + { + case 0x600000: + soundlatch = data; + return; + + case 0x600004: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + } + return; +} + +void __fastcall uballoon_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff000) == 0x200000) { + if (address & 0x200) { + DrvPalRAM2[address & 0xfff] = data; + } else { + address += color_bank << 9; + DrvPalRAM[address & 0xfff] = data; + suna_palette_write(address & 0xffe); + } + return; + } + + switch (address) + { + case 0x600000: + case 0x600001: + soundlatch = data; + return; + + case 0x600004: + case 0x600005: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + } + return; +} + +//------------------ +// Z80 #1 + +static void uballoon_bankswitch(INT32 data) +{ + z80bankdata[0] = data; + + INT32 bank = ((data & 1) << 16) | 0x400; + + ZetMapArea(0x0400, 0xffff, 0, DrvZ80ROM1 + bank); + ZetMapArea(0x0400, 0xffff, 2, DrvZ80ROM1 + bank); +} + +void __fastcall uballoon_sound1_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: { DACWrite(0, (data & 0xf) * 0x11); return; } + case 0x01: { DACWrite(1, (data & 0xf) * 0x11); return; } + + case 0x03: + uballoon_bankswitch(data); + return; + } + + return; +} + +UINT8 __fastcall uballoon_sound1_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return soundlatch2; + } + + return 0; +} + + +//---------------------------------------------------------------- +// Back Street Soccer + + +//------------------ +// 68k + +UINT16 __fastcall bssoccer_read_word(UINT32 address) +{ + if ((address & 0xfff000) == 0x400000) { + if (address & 0x200) { + return *((UINT16*)(DrvPalRAM2 + (address & 0xffe))); + } else { + address += color_bank << 9; + return *((UINT16*)(DrvPalRAM + (address & 0xffe))); + } + } + + switch (address & ~1) + { + case 0xa00000: + return DrvInputs[0]; + + case 0xa00002: + return DrvInputs[1]; + + case 0xa00004: + return DrvInputs[2]; + + case 0xa00006: + return DrvInputs[3]; + + case 0xa00008: + return DrvInputs[4]; + + case 0xa0000a: + return DrvInputs[5]; + + } + + return 0; +} + +UINT8 __fastcall bssoccer_read_byte(UINT32 address) +{ + if ((address & 0xfff000) == 0x400000) { + if (address & 0x200) { + return DrvPalRAM2[address & 0xffe]; + } else { + address += color_bank << 9; + return DrvPalRAM[address & 0xffe]; + } + } + + switch (address) + { + case 0xa00000: + case 0xa00001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0xa00002: + case 0xa00003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0xa00004: + case 0xa00005: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0xa00006: + case 0xa00007: + return DrvInputs[3] >> ((~address & 1) << 3); + + case 0xa00008: + case 0xa00009: + return DrvInputs[4] >> ((~address & 1) << 3); + + case 0xa0000a: + case 0xa0000b: + return DrvInputs[5] >> ((~address & 1) << 3); + } + + return 0; +} + +void __fastcall bssoccer_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0x400000) { + if (address & 0x200) { + *((UINT16*)(DrvPalRAM2 + (address & 0xffff))) = data; + } else { + address += color_bank << 9; + *((UINT16*)(DrvPalRAM + (address & 0xffff))) = data; + suna_palette_write(address & 0xffff); + } + return; + } + + switch (address & ~1) + { + case 0xa00000: + soundlatch = data; + return; + + case 0xa00002: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + } + return; +} + +void __fastcall bssoccer_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff000) == 0x400000) { + if (address & 0x200) { + DrvPalRAM[address & 0xfff] = data; + } else { + address += color_bank << 9; + DrvPalRAM[address & 0xfff] = data; + suna_palette_write(address & 0xffe); + } + return; + } + + switch (address) + { + case 0xa00000: + case 0xa00001: + soundlatch = data; + return; + + case 0xa00002: + case 0xa00003: + flipscreen = data & 0x01; + color_bank = (data >> 2) & 1; + return; + } + return; +} + +//------------------ +// Z80 #0 + +static void bssoccer_bankswitch_w(UINT8 *z80data, INT32 p, INT32 data) +{ + z80bankdata[p] = data; + + INT32 bank = ((data & 7) << 16) | 0x1000; + + ZetMapArea(0x1000, 0xffff, 0, z80data + bank); + ZetMapArea(0x1000, 0xffff, 2, z80data + bank); +} + +void __fastcall bssoccer_sound0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf800: + BurnYM2151SelectRegister(data); + return; + + case 0xf801: + BurnYM2151WriteRegister(data); + return; + + case 0xfd00: + soundlatch2 = data; + return; + + case 0xfe00: + soundlatch3 = data; + return; + } + + return; +} + +UINT8 __fastcall bssoccer_sound0_read(UINT16 address) +{ + switch (address) + { + case 0xf801: + return BurnYM2151ReadStatus(); + + case 0xfc00: + return soundlatch; + } + + return 0; +} + +//------------------ +// Z80 #1 + +void __fastcall bssoccer_sound1_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: { DACWrite(0, (data & 0xf) * 0x11); return; } + case 0x01: { DACWrite(1, (data & 0xf) * 0x11); return; } + + case 0x03: + bssoccer_bankswitch_w(DrvZ80ROM1, 0, data); + return; + } + + return; +} + +UINT8 __fastcall bssoccer_sound1_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return soundlatch2; + } + + return 0; +} + +//------------------ +// Z80 #2 + +void __fastcall bssoccer_sound2_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: { DACWrite(2, (data & 0xf) * 0x11); return; } + case 0x01: { DACWrite(3, (data & 0xf) * 0x11); return; } + return; + + case 0x03: + bssoccer_bankswitch_w(DrvZ80ROM2, 1, data); + return; + } + + return; +} + +UINT8 __fastcall bssoccer_sound2_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return soundlatch3; + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------- +// Initialization routines + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + for (INT32 j = 0; j < 2; j++) { + ZetOpen(j); + ZetReset(); + ZetClose(); + } + + if (game_select == 3) { + ZetOpen(2); + ZetReset(); + ZetClose(); + } + + soundlatch = 0; + soundlatch2 = 0; + soundlatch3 = 0; + color_bank = 0; + bestofbest_prot = 0; + flipscreen = 0; + + z80bankdata[0] = z80bankdata[1] = 0; + + if (game_select == 3) { + ZetOpen(1); + bssoccer_bankswitch_w(DrvZ80ROM1, 0, z80bankdata[0]); + ZetClose(); + ZetOpen(2); + bssoccer_bankswitch_w(DrvZ80ROM2, 1, z80bankdata[1]); + ZetClose(); + } + + if (game_select == 2) { + ZetOpen(1); + uballoon_bankswitch(z80bankdata[0]); + ZetClose(); + } + + if (game_select == 1) { + ZetOpen(1); + bssoccer_bankswitch_w(DrvZ80ROM1, 0, z80bankdata[0]); + ZetClose(); + } + + if (game_select) { + BurnYM2151Reset(); + } else { + BurnYM3526Reset(); + AY8910Reset(0); + } + + DACReset(); + + return 0; +} + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x0200000; + DrvZ80ROM0 = Next; Next += 0x0010000; + DrvZ80ROM1 = Next; Next += 0x0080000; + DrvZ80ROM2 = Next; Next += 0x0080000; + + DrvGfxROM0 = Next; Next += 0x0600000; + if (game_select == 0) { + DrvGfxROM1 = Next; Next += 0x0800000; + } + + DrvPalette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 3 * sizeof(INT16); + pSoundBuffer = (INT16*)Next; Next += nBurnSoundLen * 2 * sizeof(INT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x0010000; + +// DrvZ80RAM0 = Next; Next += 0x0000800; + DrvZ80RAM0 = Next; Next += 0x0001000; + + DrvSprRAM0 = Next; Next += 0x0020000; + DrvSprRAM1 = Next; Next += 0x0020000; + + DrvPalRAM = Next; Next += 0x0001000; + DrvPalRAM2 = Next; Next += 0x0010000; + + Palette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode(UINT8 *gfx_base, INT32 len) +{ + INT32 Plane[4] = {(len << 2) + 0, (len << 2) + 4, 0, 4 }; + INT32 XOffs[8] = { 3, 2, 1, 0, 11, 10, 9, 8 }; + INT32 YOffs[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < len; i++) tmp[i] = gfx_base[i] ^ 0xff; // copy & invert + + GfxDecode(((len * 8) / 4) / 64, 4, 8, 8, Plane, XOffs, YOffs, 0x80, tmp, gfx_base); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvLoadRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + + UINT8 *Load68K = Drv68KROM; + UINT8 *Loadz0 = DrvZ80ROM0; + UINT8 *Loadz1 = DrvZ80ROM1; + UINT8 *Loadz2 = DrvZ80ROM2; + UINT8 *Loadg0 = DrvGfxROM0; + UINT8 *Loadg1 = DrvGfxROM1; + + INT32 gfx0_len = 0; + INT32 gfx1_len = 0; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + + if (BurnLoadRom(Load68K + 1, i + 0, 2)) return 1; + if (BurnLoadRom(Load68K + 0, i + 1, 2)) return 1; + + Load68K += 0x100000; + + i++; + + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(Loadz0, i, 1)) return 1; + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(Loadz1, i, 1)) return 1; + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(Loadz2, i, 1)) return 1; + continue; + } + + if ((ri.nType & 7) == 5) { + if (BurnLoadRom(Loadg0, i, 1)) return 1; + + Loadg0 += ri.nLen; + gfx0_len += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 6) { + if (BurnLoadRom(Loadg1, i, 1)) return 1; + + Loadg1 += ri.nLen; + gfx1_len += ri.nLen; + + continue; + } + } + + nGfxROM0Len = gfx0_len >> 5; + + if (gfx0_len) DrvGfxDecode(DrvGfxROM0, gfx0_len); + if (gfx1_len) DrvGfxDecode(DrvGfxROM1, gfx1_len); + + return 0; +} + +void bestbest_ay8910_write_a(UINT32,UINT32) +{ +} + +static void bestbestFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 bestbestSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +static INT32 BestbestInit() +{ + INT32 nLen; + + game_select = 0; + + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 3; i++) { + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + } + + if (DrvLoadRoms()) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KROM, 0x040000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KROM, 0x080000, 0x0bffff, SM_ROM); + SekMapMemory(Drv68KROM, 0x0c0000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KROM + 0x100000, 0x200000, 0x2fffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x540000, 0x540fff, SM_ROM); + SekMapMemory(DrvPalRAM2, 0x541000, 0x54ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x580000, 0x58ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x5c0000, 0x5dffff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0x5e0000, 0x5fffff, SM_RAM); + SekSetWriteByteHandler(0, bestbest_write_byte); + SekSetWriteWordHandler(0, bestbest_write_word); + SekSetReadByteHandler(0, bestbest_read_byte); + SekSetReadWordHandler(0, bestbest_read_word); + SekClose(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80RAM0); + ZetSetReadHandler(bestbest_sound0_read); + ZetSetWriteHandler(bestbest_sound0_write); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0xffff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0xffff, 2, DrvZ80ROM1); + ZetSetInHandler(bestbest_sound1_in); + ZetSetOutHandler(bestbest_sound1_out); + ZetClose(); + + BurnYM3526Init(3000000, &bestbestFMIRQHandler, &bestbestSynchroniseStream, 0); + BurnTimerAttachZetYM3526(6000000); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, bestbest_ay8910_write_a, NULL); + + DACInit(0, 0, 1); + DACInit(1, 0, 1); + DACInit(2, 0, 1); + DACInit(3, 0, 1); + DACSetVolShift(0, 2); + DACSetVolShift(1, 2); + DACSetVolShift(2, 2); + DACSetVolShift(3, 2); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 SunaqInit() +{ + INT32 nLen; + + game_select = 1; + + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (DrvLoadRoms()) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvPalRAM2, 0x540400, 0x540fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x580000, 0x583fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x5c0000, 0x5dffff, SM_RAM); + SekSetWriteByteHandler(0, sunaq_write_byte); + SekSetWriteWordHandler(0, sunaq_write_word); + SekSetReadByteHandler(0, sunaq_read_byte); + SekSetReadWordHandler(0, sunaq_read_word); + SekClose(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM0); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM0); + ZetSetWriteHandler(sunaq_sound0_write); + ZetSetReadHandler(bssoccer_sound0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x0fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x0fff, 2, DrvZ80ROM1); + ZetMapArea(0x1000, 0xffff, 0, DrvZ80ROM1 + 0x1000); + ZetMapArea(0x1000, 0xffff, 2, DrvZ80ROM1 + 0x1000); + ZetSetInHandler(bssoccer_sound1_in); + ZetSetOutHandler(bssoccer_sound1_out); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 25.0); + + DACInit(0, 0, 2); + DACInit(1, 0, 2); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + + +static INT32 UballoonInit() +{ + INT32 nLen; + + game_select = 2; + + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (DrvLoadRoms()) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvPalRAM2, 0x200400, 0x200fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x400000, 0x41ffff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x5c0000, 0x5dffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x800000, 0x803fff, SM_RAM); + SekSetWriteByteHandler(0, uballoon_write_byte); + SekSetWriteWordHandler(0, uballoon_write_word); + SekSetReadByteHandler(0, uballoon_read_byte); + SekSetReadWordHandler(0, uballoon_read_word); + SekClose(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80ROM0); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM0); + ZetSetWriteHandler(sunaq_sound0_write); + ZetSetReadHandler(bssoccer_sound0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x03ff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x03ff, 2, DrvZ80ROM1); + ZetMapArea(0x0400, 0xffff, 0, DrvZ80ROM1 + 0x400); + ZetMapArea(0x0400, 0xffff, 2, DrvZ80ROM1 + 0x400); + ZetSetInHandler(uballoon_sound1_in); + ZetSetOutHandler(uballoon_sound1_out); + ZetMemEnd(); + ZetClose(); + + // Patch out the protection checks + *((UINT16*)(Drv68KROM + 0x0113c)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x0113e)) = 0x4e71; + *((UINT16*)(Drv68KROM + 0x01784)) = 0x600c; + *((UINT16*)(Drv68KROM + 0x018e2)) = 0x600c; + *((UINT16*)(Drv68KROM + 0x03c54)) = 0x600c; + *((UINT16*)(Drv68KROM + 0x126a0)) = 0x4e71; + + BurnYM2151Init(3579545, 25.0); + + DACInit(0, 0, 1); + DACInit(1, 0, 1); + DACSetVolShift(0, 2); + DACSetVolShift(1, 2); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 BssoccerInit() +{ + INT32 nLen; + + game_select = 3; + + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (DrvLoadRoms()) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x203fff, SM_RAM); + SekMapMemory(DrvPalRAM2, 0x400400, 0x400fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0x600000, 0x61ffff, SM_RAM); + SekSetWriteByteHandler(0, bssoccer_write_byte); + SekSetWriteWordHandler(0, bssoccer_write_word); + SekSetReadByteHandler(0, bssoccer_read_byte); + SekSetReadWordHandler(0, bssoccer_read_word); + SekClose(); + + ZetInit(3); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM0); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM0); + ZetSetWriteHandler(bssoccer_sound0_write); + ZetSetReadHandler(bssoccer_sound0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x0fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x0fff, 2, DrvZ80ROM1); + ZetMapArea(0x1000, 0xffff, 0, DrvZ80ROM1 + 0x1000); + ZetMapArea(0x1000, 0xffff, 2, DrvZ80ROM1 + 0x1000); + ZetSetInHandler(bssoccer_sound1_in); + ZetSetOutHandler(bssoccer_sound1_out); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetMapArea(0x0000, 0x0fff, 0, DrvZ80ROM2); + ZetMapArea(0x0000, 0x0fff, 2, DrvZ80ROM2); + ZetMapArea(0x1000, 0xffff, 0, DrvZ80ROM2 + 0x1000); + ZetMapArea(0x1000, 0xffff, 2, DrvZ80ROM2 + 0x1000); + ZetSetInHandler(bssoccer_sound2_in); + ZetSetOutHandler(bssoccer_sound2_out); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 25.0); + + DACInit(0, 0, 1); + DACInit(1, 0, 1); + DACInit(2, 0, 1); + DACInit(3, 0, 1); + DACSetVolShift(0, 2); + DACSetVolShift(1, 2); + DACSetVolShift(2, 2); + DACSetVolShift(3, 2); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnFree (AllMem); + + if (game_select) { + BurnYM2151Exit(); + } else { + AY8910Exit(0); + } + + DACExit(); + + SekExit(); + ZetExit(); + + GenericTilesExit(); + + return 0; +} + + +//------------------------------------------------------------------------------------------------- +// Drawing & CPU/sound emulation routines + + +static void draw_sprites(UINT16 *sprites, UINT8 *gfx_base, INT32 max_tile) +{ + INT32 offs; + + INT32 max_x = (256 - 0) - 8; + INT32 max_y = (256 - 0) - 8; + + for (offs = 0xfc00/2; offs < 0x10000/2 ; offs += 4/2) + { + INT32 srcpg, srcx,srcy, dimx,dimy; + INT32 tile_x, tile_xinc, tile_xstart; + INT32 tile_y, tile_yinc; + INT32 dx, dy; + INT32 flipx, y0; + + INT32 y = sprites[ offs + 0 + 0x00000 / 2 ]; + INT32 x = sprites[ offs + 1 + 0x00000 / 2 ]; + INT32 dim = sprites[ offs + 0 + 0x10000 / 2 ]; + + INT32 bank = (x >> 12) & 0xf; + + srcpg = ((y & 0xf000) >> 12) + ((x & 0x0200) >> 5); + srcx = ((y >> 8) & 0xf) * 2; + srcy = ((dim >> 0) & 0xf) * 2; + + switch ( (dim >> 4) & 0xc ) + { + case 0x0: dimx = 2; dimy = 2; y0 = 0x100; break; + case 0x4: dimx = 4; dimy = 4; y0 = 0x100; break; + case 0x8: dimx = 2; dimy = 32; y0 = 0x130; break; + default: + case 0xc: dimx = 4; dimy = 32; y0 = 0x120; break; + } + + if (dimx==4) { flipx = srcx & 2; srcx &= ~2; } + else { flipx = 0; } + + x = (x & 0xff) - (x & 0x100); + y = (y0 - (y & 0xff) - dimy*8 ) & 0xff; + + if (flipx) { tile_xstart = dimx-1; tile_xinc = -1; } + else { tile_xstart = 0; tile_xinc = +1; } + + tile_y = 0; tile_yinc = +1; + + for (dy = 0; dy < dimy * 8; dy += 8) + { + tile_x = tile_xstart; + + for (dx = 0; dx < dimx * 8; dx += 8) + { + INT32 addr = (srcpg * 0x20 * 0x20) + + ((srcx + tile_x) & 0x1f) * 0x20 + + ((srcy + tile_y) & 0x1f); + + INT32 tile = sprites[ addr + 0x00000 / 2 ]; + INT32 color = sprites[ addr + 0x10000 / 2 ]; + + INT32 sx = x + dx; + INT32 sy = (y + dy) & 0xff; + + INT32 tile_flipx = tile & 0x4000; + INT32 tile_flipy = tile & 0x8000; + + if (flipx) tile_flipx ^= 0x4000; + + if (flipscreen) + { + sx = max_x - sx; + sy = max_y - sy; + tile_flipx ^= 0x4000; + tile_flipy ^= 0x8000; + } + + tile = (tile & 0x3fff) | (bank << 14); + color += (color_bank << 4); + color &= 0x7f; + tile %= max_tile; + + sy -= 16; + + tile_x += tile_xinc; + + if (sy < -15 || sy > (nScreenHeight - 1) || sx < -15 || sx > (nScreenWidth - 1)) { + continue; + } + + if (tile_flipy) { + if (tile_flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, tile, sx, sy, color, 4, 0x0f, 0, gfx_base); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, tile, sx, sy, color, 4, 0x0f, 0, gfx_base); + } + } else { + if (tile_flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, tile, sx, sy, color, 4, 0x0f, 0, gfx_base); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, tile, sx, sy, color, 4, 0x0f, 0, gfx_base); + } + } + } + + tile_y += tile_yinc; + } + + } + +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0xff; + } + + draw_sprites((UINT16*)DrvSprRAM0, DrvGfxROM0, nGfxROM0Len); + if (!game_select) { + draw_sprites((UINT16*)DrvSprRAM1, DrvGfxROM1, 0x20000); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static inline void AssembleInputs() +{ + memset (DrvInputs, 0xff, 6 * sizeof(UINT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + DrvInputs[3] ^= DrvJoy4[i] << i; + DrvInputs[4] ^= DrvJoy5[i] << i; + DrvInputs[5] ^= DrvJoy6[i] << i; + } + + switch (game_select) + { + case 0: // bestbest + { + DrvInputs[2] = (DrvDips[1] << 8) | DrvDips[0]; + } + return; + + case 1: // sunaq + { + DrvInputs[2] = DrvDips[0]; + } + return; + + case 2: // uballoon + { + DrvInputs[1] = (DrvInputs[1] & 0xff) | (DrvDips[0] << 8); + DrvInputs[2] = DrvDips[1]; + DrvInputs[3] = DrvDips[2]; + } + return; + + case 3: // bssoccer + { + DrvInputs[4] = (DrvDips[1] << 8) | DrvDips[0]; + DrvInputs[5] = ((DrvInputs[5] & 0xfe) | (DrvDips[2] & 0x01)) | 0xff00; + } + return; + } + + return; +} + +static INT32 BestbestFrame() +{ + INT32 nCyclesTotal[3]; + + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) { + DrvDoReset(); + } + + AssembleInputs(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesTotal[2] = 6000000 / 60; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + + SekRun(nCyclesTotal[0] / 2); + if (i == (nInterleave / 2)-1) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave )-1) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + ZetOpen(0); + BurnTimerUpdateYM3526(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + + ZetOpen(1); + ZetRun(nCyclesTotal[2] / nInterleave); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pSoundBuffer + (nSoundBufferPos << 1); + INT32 nSample; + + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + DACUpdate(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + SekClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pSoundBuffer + (nSoundBufferPos << 1); + INT32 nSample; + + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + ZetOpen(0); + BurnTimerEndFrameYM3526(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + for (INT32 i = 0; i < nBurnSoundLen; i++) { + pBurnSoundOut[(i << 1) + 0] += pSoundBuffer[(i << 1) + 0]; + pBurnSoundOut[(i << 1) + 1] += pSoundBuffer[(i << 1) + 1]; + } + } + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 SunaqFrame() +{ + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[3]; + + if (DrvReset) { + DrvDoReset(); + } + + AssembleInputs(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 3579500 / 60; + nCyclesTotal[2] = 6000000 / 60; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + SekRun(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave )-1) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + for (INT32 j = 0; j < 2; j++) { + ZetOpen(j); + ZetRun(nCyclesTotal[j+1] / nInterleave); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 UballoonFrame() +{ + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[3]; + + if (DrvReset) { + DrvDoReset(); + } + + AssembleInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesTotal[1] = 3579500 / 60; + nCyclesTotal[2] = 5000000 / 60; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + SekRun(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave )-1) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + for (INT32 j = 0; j < 2; j++) { + ZetOpen(j); + ZetRun(nCyclesTotal[j+1] / nInterleave); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 BssoccerFrame() +{ + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 10; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[4]; + + if (DrvReset) { + DrvDoReset(); + } + + AssembleInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesTotal[1] = 3579500 / 60; + nCyclesTotal[2] = 5000000 / 60; + nCyclesTotal[3] = 5000000 / 60; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + SekRun(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave / 2)-1) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave )-1) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + for (INT32 j = 0; j < 3; j++) { + ZetOpen(j); + ZetRun(nCyclesTotal[j+1] / nInterleave); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029692; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + DACScan(nAction, pnMin); + + if (game_select) { + BurnYM2151Scan(nAction); + } else { + AY8910Scan(nAction, pnMin); + } + + SCAN_VAR(soundlatch); + SCAN_VAR(soundlatch2); + SCAN_VAR(soundlatch3); + SCAN_VAR(flipscreen); + SCAN_VAR(color_bank); + SCAN_VAR(bestofbest_prot); + + SCAN_VAR(z80bankdata[0]); + SCAN_VAR(z80bankdata[1]); + } + + if (game_select == 3) { + ZetOpen(1); + bssoccer_bankswitch_w(DrvZ80ROM1, 0, z80bankdata[0]); + ZetClose(); + ZetOpen(2); + bssoccer_bankswitch_w(DrvZ80ROM2, 1, z80bankdata[1]); + ZetClose(); + } + + if (game_select == 2) { + ZetOpen(1); + uballoon_bankswitch(z80bankdata[0]); + ZetClose(); + } + + return 0; +} + + + +//------------------------------------------------------------------------------------------------- +// Drivers + + +// Best Of Best + +static struct BurnRomInfo bestbestRomDesc[] = { + { "4.bin", 0x20000, 0x06741994, 1 | BRF_ESS | BRF_PRG }, // 0 - 68K Code + { "2.bin", 0x20000, 0x42843dec, 1 | BRF_ESS | BRF_PRG }, // 1 + { "3.bin", 0x80000, 0xe2bb8f26, 1 | BRF_ESS | BRF_PRG }, // 2 + { "1.bin", 0x80000, 0xd365e20a, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "5.bin", 0x10000, 0xbb9265e6, 2 | BRF_ESS | BRF_PRG }, // 4 - Z80 #0 Code + + { "6.bin", 0x10000, 0xdd445f6b, 3 | BRF_ESS | BRF_PRG }, // 5 - Z80 #1 Code + + { "9.bin", 0x80000, 0xb11994ea, 5 | BRF_GRA }, // 6 - Sprites (Chip 0) + { "10.bin", 0x80000, 0x37b41ef5, 5 | BRF_GRA }, // 7 + { "7.bin", 0x80000, 0x16188b73, 5 | BRF_GRA }, // 8 + { "8.bin", 0x80000, 0x765ce06b, 5 | BRF_GRA }, // 9 + + { "16.bin", 0x80000, 0xdc46cdea, 6 | BRF_GRA }, // 10 - Sprites (Chip 1) + { "17.bin", 0x80000, 0xc6fadd57, 6 | BRF_GRA }, // 11 + { "13.bin", 0x80000, 0x23283ac4, 6 | BRF_GRA }, // 12 + { "18.bin", 0x80000, 0x674c4609, 6 | BRF_GRA }, // 13 + { "14.bin", 0x80000, 0xc210fb53, 6 | BRF_GRA }, // 14 + { "15.bin", 0x80000, 0x3b1166c7, 6 | BRF_GRA }, // 15 + { "11.bin", 0x80000, 0x323eebc3, 6 | BRF_GRA }, // 16 + { "12.bin", 0x80000, 0xca7c8176, 6 | BRF_GRA }, // 17 + + { "82s129.5", 0x00100, 0x10bfcebb, 0 | BRF_OPT }, // 18 - PROMs (not used) + { "82s129.6", 0x00100, 0x10bfcebb, 0 | BRF_OPT }, // 19 +}; + +STD_ROM_PICK(bestbest) +STD_ROM_FN(bestbest) + +struct BurnDriver BurnDrvBestbest = { + "bestbest", NULL, NULL, NULL, "1994", + "Best Of Best\0", NULL, "SunA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, bestbestRomInfo, bestbestRomName, NULL, NULL, BestbestInputInfo, bestbestDIPInfo, + BestbestInit, DrvExit, BestbestFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// SunA Quiz 6000 Academy (940620-6) + +static struct BurnRomInfo sunaqRomDesc[] = { + { "prog2.bin", 0x80000, 0xa92bce45, 1 | BRF_ESS | BRF_PRG }, // 0 - 68K Code + { "prog1.bin", 0x80000, 0xff690e7e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "audio1.bin", 0x10000, 0x3df42f82, 2 | BRF_ESS | BRF_PRG }, // 2 - Z80 #0 Code + + { "audio2.bin", 0x80000, 0xcac85ba9, 3 | BRF_ESS | BRF_PRG }, // 3 - Z80 #1 Code + + { "gfx1.bin", 0x80000, 0x0bde5acf, 5 | BRF_GRA }, // 4 - Sprites + { "gfx2.bin", 0x80000, 0x24b74826, 5 | BRF_GRA }, // 5 +}; + +STD_ROM_PICK(sunaq) +STD_ROM_FN(sunaq) + +struct BurnDriver BurnDrvSunaq = { + "sunaq", NULL, NULL, NULL, "1994", + "SunA Quiz 6000 Academy (940620-6)\0", NULL, "SunA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, sunaqRomInfo, sunaqRomName, NULL, NULL, SunaqInputInfo, sunaqDIPInfo, + SunaqInit, DrvExit, SunaqFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Ultra Balloon + +static struct BurnRomInfo uballoonRomDesc[] = { + { "prg2.rom", 0x80000, 0x72ab80ea, 1 | BRF_ESS | BRF_PRG }, // 0 - 68K Code + { "prg1.rom", 0x80000, 0x27a04f55, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "audio1.rom", 0x10000, 0xc771f2b4, 2 | BRF_ESS | BRF_PRG }, // 2 - Z80 #0 Code + + { "audio2.rom", 0x20000, 0xc7f75347, 3 | BRF_ESS | BRF_PRG }, // 3 - Z80 #1 Code + + { "gfx1.rom", 0x80000, 0xfd2ec297, 5 | BRF_GRA }, // 4 - Sprites + { "gfx2.rom", 0x80000, 0x6307aa60, 5 | BRF_GRA }, // 5 + { "gfx3.rom", 0x80000, 0x718f3150, 5 | BRF_GRA }, // 6 + { "gfx4.rom", 0x80000, 0xaf7e057e, 5 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(uballoon) +STD_ROM_FN(uballoon) + +struct BurnDriver BurnDrvUballoon = { + "uballoon", NULL, NULL, NULL, "1996", + "Ultra Balloon\0", NULL, "SunA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, uballoonRomInfo, uballoonRomName, NULL, NULL, UballoonInputInfo, uballoonDIPInfo, + UballoonInit, DrvExit, UballoonFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; + + +// Back Street Soccer + +static struct BurnRomInfo bssoccerRomDesc[] = { + { "02", 0x080000, 0x32871005, 1 | BRF_ESS | BRF_PRG }, // 0 - 68K Code + { "01", 0x080000, 0xace00db6, 1 | BRF_ESS | BRF_PRG }, // 1 + { "04", 0x080000, 0x25ee404d, 1 | BRF_ESS | BRF_PRG }, // 2 + { "03", 0x080000, 0x1a131014, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "11", 0x010000, 0xdf7ae9bc, 2 | BRF_ESS | BRF_PRG }, // 4 - Z80 #0 Code + + { "13", 0x080000, 0x2b273dca, 3 | BRF_ESS | BRF_PRG }, // 5 - Z80 #1 Code + + { "12", 0x080000, 0x6b73b87b, 4 | BRF_ESS | BRF_PRG }, // 6 - Z80 #0 Code + + { "05", 0x080000, 0xa5245bd4, 5 | BRF_GRA }, // 7 - Sprites + { "07", 0x080000, 0xfdb765c2, 5 | BRF_GRA }, // 8 + { "09", 0x080000, 0x0e82277f, 5 | BRF_GRA }, // 9 + { "06", 0x080000, 0xd42ce84b, 5 | BRF_GRA }, // 10 + { "08", 0x080000, 0x96cd2136, 5 | BRF_GRA }, // 11 + { "10", 0x080000, 0x1ca94d21, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(bssoccer) +STD_ROM_FN(bssoccer) + +struct BurnDriver BurnDrvBssoccer = { + "bssoccer", NULL, NULL, NULL, "1996", + "Back Street Soccer\0", "graphics issues?", "SunA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_POST90S, GBF_SPORTSFOOTBALL, 0, + NULL, bssoccerRomInfo, bssoccerRomName, NULL, NULL, BssoccerInputInfo, bssoccerDIPInfo, + BssoccerInit, DrvExit, BssoccerFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_supbtime.cpp b/src/burn/drivers/misc_post90s/d_supbtime.cpp new file mode 100644 index 00000000..079feb11 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_supbtime.cpp @@ -0,0 +1,693 @@ +// FB Alpha Super Burger Time / China Town driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo SupbtimeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Supbtime) + +static struct BurnDIPInfo SupbtimeDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x11, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x11, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x11, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x02, 0x00, "No" }, + {0x12, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x10, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3, "Lives" }, + {0x12, 0x01, 0xc0, 0x80, "1" }, + {0x12, 0x01, 0xc0, 0x00, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, +}; + +STDDIPINFO(Supbtime) + +static struct BurnDIPInfo ChinatwnDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x11, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x11, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x11, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x10, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x12, 0x01, 0xc0, 0x00, "1500" }, + {0x12, 0x01, 0xc0, 0x80, "2000" }, + {0x12, 0x01, 0xc0, 0xc0, "2500" }, + {0x12, 0x01, 0xc0, 0x40, "3000" }, +}; + +STDDIPINFO(Chinatwn) + +void __fastcall supbtime_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x300000, data) + + switch (address) + { + case 0x100000: + case 0x1a0000: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + } +} + +void __fastcall supbtime_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x100000: + case 0x100001: + case 0x1a0000: + case 0x1a0001: + *soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + } +} + +UINT16 __fastcall supbtime_main_read_word(UINT32 address) +{ + deco16_read_control_word(0, address, 0x300000) + + switch (address) + { + case 0x180000: + return DrvInputs[0]; + + case 0x180002: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x180008: + return (DrvInputs[1] & ~0x0008) | (deco16_vblank & 0x0008); + + case 0x18000a: + case 0x18000c: + return 0; + } + + return 0; +} + +UINT8 __fastcall supbtime_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180000: + case 0x180001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x180002: + return DrvDips[0]; + + case 0x180003: + return DrvDips[1]; + + case 0x180008: + case 0x180009: + return (DrvInputs[1] & ~0x0008) | (deco16_vblank & 0x0008); + } + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + MSM6295Reset(0); + BurnYM2151Reset(); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit(INT32 game) +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 5, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 6, 1)) return 1; + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x080000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_sprite_decode(DrvGfxROM2, 0x100000); + } + + deco16Init(1, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x80000 * 2, DrvGfxROM1, 0x80000 * 2, NULL, 0); + deco16_set_color_base(0, 256); + deco16_set_color_base(1, 512); + deco16_set_global_offsets(0, 8); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + if (game) { + SekMapMemory(Drv68KRAM, 0x100000, 0x103fff, SM_RAM); // super burger time + } else { + SekMapMemory(Drv68KRAM, 0x1a0000, 0x1a3fff, SM_RAM); // china town + } + SekMapMemory(DrvSprRAM, 0x120000, 0x1207ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x320000, 0x321fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x322000, 0x323fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x340000, 0x340bff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x342000, 0x342bff, SM_RAM); + SekSetWriteWordHandler(0, supbtime_main_write_word); + SekSetWriteByteHandler(0, supbtime_main_write_byte); + SekSetReadWordHandler(0, supbtime_main_read_word); + SekSetReadByteHandler(0, supbtime_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 40.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1023924 / 132, 50.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + MSM6295Exit(0); + BurnYM2151Exit(); + + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x800 / 2; i++) { + INT32 b = (p[i] >> 8) & 0x0f; + INT32 g = (p[i] >> 4) & 0x0f; + INT32 r = (p[i] >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult; + + INT32 sy = ram[offs + 0]; + INT32 code = ram[offs + 1] & 0x3fff; + INT32 sx = ram[offs + 2]; + + if ((sy & 0x1000) && (nCurrentFrame & 1)) continue; + + INT32 color = (sx >> 9) & 0x1f; + + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + INT32 multi = (1 << ((sy & 0x0600) >> 9)) - 1; + + sx &= 0x01ff; + sy &= 0x01ff; + if (sx >= 320) sx -= 512; + if (sy >= 256) sy -= 512; + sy = 240 - sy; + sx = 304 - sx; + + code &= ~multi; + + if (flipy) { + inc = -1; + } else { + code += multi; + inc = 1; + } + + if (*flipscreen) + { + sy = 240 - sy; + sx = 304 - sx; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else + mult = -16; + + if (sx >= 320 || sx < -15) continue; + + while (multi >= 0) + { + INT32 y = (sy + mult * multi) - 8; + INT32 c = (code - multi * inc) & 0x3fff; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + DrvPaletteRecalc(); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x300; + } + + if (nBurnLayer & 1) deco16_draw_layer(1, pTransDraw, 0x10000 /*opaque*/); + + if (nBurnLayer & 2) draw_sprites(); + + if (nBurnLayer & 4) deco16_draw_layer(0, pTransDraw, 0x00000 /*transparent*/); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + } + + return 0; +} + + + +// Super Burger Time (World, set 1) + +static struct BurnRomInfo supbtimeRomDesc[] = { + { "gk03", 0x20000, 0xaeaeed61, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gk04", 0x20000, 0x2bc5a4eb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gc06.bin", 0x10000, 0xe0e6c0f4, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "mae02.bin", 0x80000, 0xa715cca0, 3 | BRF_GRA }, // 3 Characters and Background Tiles + + { "mae00.bin", 0x80000, 0x30043094, 4 | BRF_GRA }, // 4 Sprites + { "mae01.bin", 0x80000, 0x434af3fb, 4 | BRF_GRA }, // 5 + + { "gc05.bin", 0x20000, 0x2f2246ff, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(supbtime) +STD_ROM_FN(supbtime) + +static INT32 supbtimeInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvSupbtime = { + "supbtime", NULL, NULL, NULL, "1990", + "Super Burger Time (World, set 1)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, supbtimeRomInfo, supbtimeRomName, NULL, NULL, SupbtimeInputInfo, SupbtimeDIPInfo, + supbtimeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Super Burger Time (World, set 2) + +static struct BurnRomInfo supbtimeaRomDesc[] = { + { "3.11f", 0x20000, 0x98b5f263, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "4.12f", 0x20000, 0x937e68b9, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gc06.bin", 0x10000, 0xe0e6c0f4, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "mae02.bin", 0x80000, 0xa715cca0, 3 | BRF_GRA }, // 3 Characters and Background Tiles + + { "mae00.bin", 0x80000, 0x30043094, 4 | BRF_GRA }, // 4 Sprites + { "mae01.bin", 0x80000, 0x434af3fb, 4 | BRF_GRA }, // 5 + + { "gc05.bin", 0x20000, 0x2f2246ff, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(supbtimea) +STD_ROM_FN(supbtimea) + +struct BurnDriver BurnDrvSupbtimea = { + "supbtimea", "supbtime", NULL, NULL, "1990", + "Super Burger Time (World, set 2)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, supbtimeaRomInfo, supbtimeaRomName, NULL, NULL, SupbtimeInputInfo, SupbtimeDIPInfo, + supbtimeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// Super Burger Time (Japan) + +static struct BurnRomInfo supbtimejRomDesc[] = { + { "gc03.bin", 0x20000, 0xb5621f6a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "gc04.bin", 0x20000, 0x551b2a0c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gc06.bin", 0x10000, 0xe0e6c0f4, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "mae02.bin", 0x80000, 0xa715cca0, 3 | BRF_GRA }, // 3 Characters and Background Tiles + + { "mae00.bin", 0x80000, 0x30043094, 4 | BRF_GRA }, // 4 Sprites + { "mae01.bin", 0x80000, 0x434af3fb, 4 | BRF_GRA }, // 5 + + { "gc05.bin", 0x20000, 0x2f2246ff, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(supbtimej) +STD_ROM_FN(supbtimej) + +struct BurnDriver BurnDrvSupbtimej = { + "supbtimej", "supbtime", NULL, NULL, "1990", + "Super Burger Time (Japan)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, supbtimejRomInfo, supbtimejRomName, NULL, NULL, SupbtimeInputInfo, SupbtimeDIPInfo, + supbtimeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; + + +// China Town (Japan) + +static struct BurnRomInfo chinatwnRomDesc[] = { + { "gv_00-.f11", 0x20000, 0x2ea7ea5d, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu + { "gv_01-.f13", 0x20000, 0xbcab03c7, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gv_02-.f16", 0x10000, 0x95151d84, 2 | BRF_PRG | BRF_ESS }, // 2 audiocpu + + { "mak-02.h2", 0x80000, 0x745b2c50, 3 | BRF_GRA }, // 3 gfx1 + + { "mak-00.a2", 0x80000, 0x18e8cc1b, 4 | BRF_GRA }, // 4 gfx2 + { "mak-01.a4", 0x80000, 0xd88ebda8, 4 | BRF_GRA }, // 5 + + { "gv_03-.j14", 0x20000, 0x948faf92, 5 | BRF_SND }, // 6 oki +}; + +STD_ROM_PICK(chinatwn) +STD_ROM_FN(chinatwn) + +static INT32 chinatwnInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvChinatwn = { + "chinatwn", NULL, NULL, NULL, "1991", + "China Town (Japan)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, chinatwnRomInfo, chinatwnRomName, NULL, NULL, SupbtimeInputInfo, ChinatwnDIPInfo, + chinatwnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_suprnova.cpp b/src/burn/drivers/misc_post90s/d_suprnova.cpp new file mode 100644 index 00000000..1838485f --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_suprnova.cpp @@ -0,0 +1,774 @@ +#include "tiles_generic.h" +#include "sh2.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[1] = {0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvBiosRom = NULL; +static UINT8 *DrvPrgRom = NULL; +static UINT8 *DrvSpriteRom = NULL; +static UINT8 *DrvSampleRom = NULL; +static UINT8 *DrvPrgRam = NULL; +static UINT8 *DrvBackupRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteRegs = NULL; +static UINT8 *DrvTileARam = NULL; +static UINT8 *DrvTileBRam = NULL; +static UINT8 *DrvTileBTilesRam = NULL; +static UINT8 *DrvTileRegs = NULL; +static UINT8 *DrvTileLineRam = NULL; +static UINT8 *DrvCacheRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvPaletteRegs = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT8 *DrvTilesA8Bpp = NULL; +static UINT8 *DrvTilesB8Bpp = NULL; +static UINT8 *DrvTilesA4Bpp = NULL; +static UINT8 *DrvTilesB4Bpp = NULL; +static UINT32 *DrvPalette = NULL; + +static INT32 nCyclesDone[1], nCyclesTotal[1]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo CyvernInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 6, "service" }, + {"Tilt" , BIT_DIGITAL , DrvInputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, +}; + +STDINPUTINFO(Cyvern) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Use backup RAM" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo CyvernRomDesc[] = { + { "sknsj1.u10", 0x080000, 0x7e2b836c, BRF_ESS | BRF_PRG }, // 0 BIOS + + { "cvj-even.u10", 0x100000, 0x802fadb4, BRF_ESS | BRF_PRG }, // 1 SH-2 Program + { "cvj-odd.u8", 0x100000, 0xf8a0fbdd, BRF_ESS | BRF_PRG }, // 2 + + { "cv100-00.u24", 0x400000, 0xcd4ae88a, BRF_GRA }, // 3 Sprites + { "cv101-00.u20", 0x400000, 0xa6cb3f0b, BRF_GRA }, // 4 + + { "cv200-00.u16", 0x400000, 0xddc8c67e, BRF_GRA }, // 5 Tiles Plane A + { "cv201-00.u13", 0x400000, 0x65863321, BRF_GRA }, // 6 + + { "cv210-00.u18", 0x400000, 0x7486bf3a, BRF_GRA }, // 7 Tiles Plane B + + { "cv300-00.u4", 0x400000, 0xfbeda465, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Cyvern) +STD_ROM_FN(Cyvern) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvBiosRom = Next; Next += 0x080000; + DrvPrgRom = Next; Next += 0x200000; + DrvSpriteRom = Next; Next += 0x800000; + DrvSampleRom = Next; Next += 0x400000; + + RamStart = Next; + + DrvPrgRam = Next; Next += 0x100000; + DrvBackupRam = Next; Next += 0x002000; + DrvSpriteRam = Next; Next += 0x004000; + DrvSpriteRegs = Next; Next += 0x000040; + DrvTileARam = Next; Next += 0x004000; + DrvTileBRam = Next; Next += 0x004000; + DrvTileBTilesRam = Next; Next += 0x040000; + DrvTileRegs = Next; Next += 0x000080; + DrvTileLineRam = Next; Next += 0x008000; + DrvPaletteRam = Next; Next += 0x020000; + DrvPaletteRegs = Next; Next += 0x000020; + DrvCacheRam = Next; Next += 0x001000; + + RamEnd = Next; + + DrvTilesA8Bpp = Next; Next += 0x08000 * 16 * 16; + DrvTilesB8Bpp = Next; Next += 0x08000 * 16 * 16; + DrvTilesA4Bpp = Next; Next += 0x10000 * 16 * 16; + DrvTilesB4Bpp = Next; Next += 0x10000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x08000 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static struct { + UINT16 x1p, y1p, z1p, x1s, y1s, z1s; + UINT16 x2p, y2p, z2p, x2s, y2s, z2s; + UINT16 org; + + UINT16 x1_p1, x1_p2, y1_p1, y1_p2, z1_p1, z1_p2; + UINT16 x2_p1, x2_p2, y2_p1, y2_p2, z2_p1, z2_p2; + UINT16 x1tox2, y1toy2, z1toz2; + INT16 x_in, y_in, z_in; + UINT16 flag; + + UINT8 disconnect; +} hit; + +static void hit_calc_orig(UINT16 p, UINT16 s, UINT16 org, UINT16 *l, UINT16 *r) +{ + switch(org & 3) { + case 0: + *l = p; + *r = p+s; + break; + case 1: + *l = p-s/2; + *r = *l+s; + break; + case 2: + *l = p-s; + *r = p; + break; + case 3: + *l = p-s; + *r = p+s; + break; + } +} + +static void hit_calc_axis(UINT16 x1p, UINT16 x1s, UINT16 x2p, UINT16 x2s, UINT16 org, + UINT16 *x1_p1, UINT16 *x1_p2, UINT16 *x2_p1, UINT16 *x2_p2, + INT16 *x_in, UINT16 *x1tox2) +{ + UINT16 x1l=0, x1r=0, x2l=0, x2r=0; + hit_calc_orig(x1p, x1s, org, &x1l, &x1r); + hit_calc_orig(x2p, x2s, org >> 8, &x2l, &x2r); + + *x1tox2 = x2p-x1p; + *x1_p1 = x1p; + *x2_p1 = x2p; + *x1_p2 = x1r; + *x2_p2 = x2l; + *x_in = x1r-x2l; +} + +static void hit_recalc(void) +{ + hit_calc_axis(hit.x1p, hit.x1s, hit.x2p, hit.x2s, hit.org, + &hit.x1_p1, &hit.x1_p2, &hit.x2_p1, &hit.x2_p2, + &hit.x_in, &hit.x1tox2); + hit_calc_axis(hit.y1p, hit.y1s, hit.y2p, hit.y2s, hit.org, + &hit.y1_p1, &hit.y1_p2, &hit.y2_p1, &hit.y2_p2, + &hit.y_in, &hit.y1toy2); + hit_calc_axis(hit.z1p, hit.z1s, hit.z2p, hit.z2s, hit.org, + &hit.z1_p1, &hit.z1_p2, &hit.z2_p1, &hit.z2_p2, + &hit.z_in, &hit.z1toz2); + + hit.flag = 0; + hit.flag |= hit.y2p > hit.y1p ? 0x8000 : hit.y2p == hit.y1p ? 0x4000 : 0x2000; + hit.flag |= hit.y_in >= 0 ? 0 : 0x1000; + hit.flag |= hit.x2p > hit.x1p ? 0x0800 : hit.x2p == hit.x1p ? 0x0400 : 0x0200; + hit.flag |= hit.x_in >= 0 ? 0 : 0x0100; + hit.flag |= hit.z2p > hit.z1p ? 0x0080 : hit.z2p == hit.z1p ? 0x0040 : 0x0020; + hit.flag |= hit.z_in >= 0 ? 0 : 0x0010; + hit.flag |= hit.x_in >= 0 && hit.y_in >= 0 && hit.z_in >= 0 ? 8 : 0; + hit.flag |= hit.z_in >= 0 && hit.x_in >= 0 ? 4 : 0; + hit.flag |= hit.y_in >= 0 && hit.z_in >= 0 ? 2 : 0; + hit.flag |= hit.x_in >= 0 && hit.y_in >= 0 ? 1 : 0; +} + +static void SknsHitWrite(UINT32 offset, UINT32 data) +{ + INT32 adr = offset * 4; + + switch(adr) { + case 0x00: + case 0x28: + hit.x1p = data; + break; + case 0x08: + case 0x30: + hit.y1p = data; + break; + case 0x38: + case 0x50: + hit.z1p = data; + break; + case 0x04: + case 0x2c: + hit.x1s = data; + break; + case 0x0c: + case 0x34: + hit.y1s = data; + break; + case 0x3c: + case 0x54: + hit.z1s = data; + break; + case 0x10: + case 0x58: + hit.x2p = data; + break; + case 0x18: + case 0x60: + hit.y2p = data; + break; + case 0x20: + case 0x68: + hit.z2p = data; + break; + case 0x14: + case 0x5c: + hit.x2s = data; + break; + case 0x1c: + case 0x64: + hit.y2s = data; + break; + case 0x24: + case 0x6c: + hit.z2s = data; + break; + case 0x70: + hit.org = data; + break; + default: +// log_write("HIT", adr, data, type); + break; + } + hit_recalc(); +} + +static void SknsHit2Write(UINT32 offset, UINT32 data) +{ +// log_event("HIT", "Set disconnect to %02x", data); + hit.disconnect = data; +} + +UINT32 __fastcall SknsHitRead(UINT32 offset) +{ + INT32 adr = offset *4; + +// log_read("HIT", adr, type); + + if(hit.disconnect) + return 0x0000; + switch(adr) { + case 0x28: + case 0x2a: + return rand() & 0xffff; + case 0x00: + case 0x10: + return (UINT16)hit.x_in; + case 0x04: + case 0x14: + return (UINT16)hit.y_in; + case 0x18: + return (UINT16)hit.z_in; + case 0x08: + case 0x1c: + return hit.flag; + case 0x40: + return hit.x1p; + case 0x48: + return hit.y1p; + case 0x50: + return hit.z1p; + case 0x44: + return hit.x1s; + case 0x4c: + return hit.y1s; + case 0x54: + return hit.z1s; + case 0x58: + return hit.x2p; + case 0x60: + return hit.y2p; + case 0x68: + return hit.z2p; + case 0x5c: + return hit.x2s; + case 0x64: + return hit.y2s; + case 0x6c: + return hit.z2s; + case 0x70: + return hit.org; + case 0x80: + return hit.x1tox2; + case 0x84: + return hit.y1toy2; + case 0x88: + return hit.z1toz2; + case 0x90: + return hit.x1_p1; + case 0xa0: + return hit.y1_p1; + case 0xb0: + return hit.z1_p1; + case 0x98: + return hit.x1_p2; + case 0xa8: + return hit.y1_p2; + case 0xb8: + return hit.z1_p2; + case 0x94: + return hit.x2_p1; + case 0xa4: + return hit.y2_p1; + case 0xb4: + return hit.z2_p1; + case 0x9c: + return hit.x2_p2; + case 0xac: + return hit.y2_p2; + case 0xbc: + return hit.z2_p2; + default: +// log_read("HIT", adr, type); + return 0; + } +} + +static INT32 DrvDoReset() +{ + Sh2Open(0); + Sh2Reset(*(UINT32 *)(DrvBiosRom + 0), *(UINT32 *)(DrvBiosRom + 4)); + Sh2Close(); + + return 0; +} + +UINT8 __fastcall CyvernReadByte(UINT32 a) +{ + switch (a) { + case 0x20400007: { + //??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Read byte => %08X\n"), a); + } + } + + return 0; +} + +void __fastcall CyvernWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x0040000e: { + // unknown i/o write; + return; + } + + case 0x00c00000: + case 0x00c00001: { + //sound write + return; + } + + case 0x01800000: { + SknsHit2Write(0, d); + return; + } + + case 0x2040000e: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Write byte => %08X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall CyvernReadWord(UINT32 a) +{ + if (a >= 0x06000000 && a <= 0x06ffffff) { + if (a >= 0x06000028 && a <= 0x0600002b) bprintf(PRINT_NORMAL, _T("Read Word Bios Skip %x, %x\n"), a, Sh2GetPC(0)); + UINT32 Offset = (a - 0x06000000) / 2; + UINT16 *Ram = (UINT16*)DrvPrgRam; + + return Ram[Offset]; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Read word => %08X\n"), a); + } + } + + return 0; +} + +void __fastcall CyvernWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x05000000: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Write word => %08X, %04X\n"), a, d); + } + } +} + +UINT32 __fastcall CyvernReadLong(UINT32 a) +{ + if (a >= 0x02f00000 && a <= 0x02f000ff) { + UINT32 Offset = (a - 0x02f00000) / 4; + + return SknsHitRead(Offset); + } + + if (a >= 0x06000000 && a <= 0x06ffffff) { + if (a >= 0x06000028 && a <= 0x0600002b) bprintf(PRINT_NORMAL, _T("Read Long Bios Skip %x, %x\n"), a, Sh2GetPC(0) / 4); + UINT32 Offset = (a - 0x06000000) / 4; + UINT32 *Ram = (UINT32*)DrvPrgRam; + + return Ram[Offset]; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Read long => %08X\n"), a); + } + } + + return 0; +} + +void __fastcall CyvernWriteLong(UINT32 a, UINT32 d) +{ + if (a >= 0x02f00000 && a <= 0x02f000ff) { + UINT32 Offset = (a - 0x02f00000) / 4; + + SknsHitWrite(Offset, d); + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Write long => %08X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall BiosSkipReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Read Bios Skip byte => %08X\n"), a); + } + } + + return 0; +} + +UINT16 __fastcall BiosSkipReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Read Bios Skip word => %08X\n"), a); + } + } + + return 0; +} + +UINT32 __fastcall BiosSkipReadLong(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Read Bios Skip long => %08X\n"), a); + } + } + + return 0; +} + +static void be_to_le(UINT8 * p, INT32 size) +{ + UINT8 c; + for(INT32 i=0; i> 0) & 0x1f; + INT32 g = (PaletteRam[Offset] >> 5) & 0x1f; + INT32 b = (PaletteRam[Offset] >> 10) & 0x1f; + + r <<= 3; + g <<= 3; + b <<= 3; + + DrvPalette[Offset] = BurnHighCol(r, g, b, 0); + } +} + +static void DrvRenderTileALayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT32 *VideoRam = (UINT32*)DrvTileARam; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[TileIndex] & 0x001fffff; + Colour = (VideoRam[TileIndex] & 0x3f000000) >> 24; + + if (Code) bprintf(PRINT_NORMAL, _T("%x, %x\n"), Code, Colour); + + x = 16 * mx; + y = 16 * my; + +// x -= DrvFgScrollX; +// y -= DrvFgScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 1024; + + if (x > 16 && x < 304 && y > 16 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTilesA8Bpp); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTilesA8Bpp); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + + DrvRenderTileALayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 28638000 / 60; + nCyclesDone[0] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + Sh2Open(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += Sh2Run(nCyclesSegment); + if (i == 5) Sh2SetIRQLine(1, SH2_IRQSTATUS_AUTO); + if (i == 9) Sh2SetIRQLine(5, SH2_IRQSTATUS_AUTO); + Sh2Close(); + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029693; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +struct BurnDriver BurnDrvCyvern = { + "cyvern", NULL, NULL, NULL, "1998", + "Cyvern (Japan)\0", NULL, "Kaneko", "Super Kaneko Nova System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, CyvernRomInfo, CyvernRomName, NULL, NULL, CyvernInputInfo, DrvDIPInfo, + CyvernInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x8000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_taotaido.cpp b/src/burn/drivers/misc_post90s/d_taotaido.cpp new file mode 100644 index 00000000..ed777035 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_taotaido.cpp @@ -0,0 +1,1026 @@ +// FB Alpha "Tao Taido" driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "burn_ym2610.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvSprRAM0; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSpr0Buf0; +static UINT8 *DrvSpr1Buf0; +static UINT8 *DrvSpr0Buf1; +static UINT8 *DrvSpr1Buf1; +static UINT8 *DrvScrollRAM; +static UINT8 *taotaido_tileregs; +static UINT8 *taotaido_spritebank; +static UINT32 *DrvPalette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDip[4]; +static UINT16 DrvInps[5]; +static UINT8 DrvReset; + +static UINT8 *nDrvZ80Bank; +static UINT8 *pending_command; +static UINT8 *soundlatch; + +static INT32 nCyclesTotal[2]; + +static struct BurnInputInfo TaotaidoInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 6, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 5, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDip + 2, "dip" }, + {"Region", BIT_DIPSWITCH, DrvDip + 3, "dip" }, +}; + +STDINPUTINFO(Taotaido) + +static struct BurnInputInfo TaotaidoaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Weak Punch", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Medium Punch", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Strong Punch", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + {"P1 Weak Kick", BIT_DIGITAL, DrvJoy4 + 0, "p1 fire 4" }, + {"P1 Medium Kick", BIT_DIGITAL, DrvJoy4 + 1, "p1 fire 5" }, + {"P1 Strong Kick", BIT_DIGITAL, DrvJoy4 + 2, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Weak Punch", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Medium Punch", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Strong Punch", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + {"P2 Weak Kick", BIT_DIGITAL, DrvJoy5 + 0, "p2 fire 4" }, + {"P2 Medium Kick", BIT_DIGITAL, DrvJoy5 + 1, "p2 fire 5" }, + {"P2 Strong Kick", BIT_DIGITAL, DrvJoy5 + 2, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 6, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 5, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDip + 2, "dip" }, + {"Region", BIT_DIPSWITCH, DrvDip + 3, "dip" }, +}; + +STDINPUTINFO(Taotaidoa) + +static struct BurnDIPInfo TaotaidoDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + {0x18, 0xff, 0xff, 0x08, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Slot" }, + {0x15, 0x01, 0x01, 0x01, "Same" }, + {0x15, 0x01, 0x01, 0x00, "Individual" }, + + // Coinage condition: Coin Slot Individual + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x15, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x15, 0x00, 0x01, 0x00, NULL}, + + // Coin 1 condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin 1" }, + {0x15, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + + // Coin 2 condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin 2" }, + {0x15, 0x02, 0x70, 0x50, "3 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x40, "1 Coin 2 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x30, "1 Coin 3 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x20, "1 Coin 4 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x10, "1 Coin 5 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x70, 0x00, "1 Coin 6 Credits" }, + {0x15, 0x00, 0x01, 0x01, NULL}, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x16, 0x01, 0x01, 0x01, "Off" }, +// {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x02, 0x00, "Off" }, + {0x16, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x18, 0x10, "Easy" }, + {0x16, 0x01, 0x18, 0x18, "Normal" }, + {0x16, 0x01, 0x18, 0x08, "Hard" }, + {0x16, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Join In (1 Credit)" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Buy In" }, + {0x17, 0x01, 0x02, 0x00, "No" }, + {0x17, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 5, "Country" }, + {0x18, 0x01, 0x0f, 0x00, "US" }, + {0x18, 0x01, 0x0f, 0x01, "Japan" }, + {0x18, 0x01, 0x0f, 0x02, "Hong-Kong/Taiwan" }, + {0x18, 0x01, 0x0f, 0x04, "Korea" }, + {0x18, 0x01, 0x0f, 0x08, "World" }, +}; + +STDDIPINFO(Taotaido) + +static struct BurnDIPInfo TaotaidoaDIPList[]= +{ + // Default Values + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xff, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + {0x1e, 0xff, 0xff, 0x08, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Slot" }, + {0x1b, 0x01, 0x01, 0x01, "Same" }, + {0x1b, 0x01, 0x01, 0x00, "Individual" }, + + // Coinage condition: Coin Slot Individual + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x1b, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + {0x1b, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x1b, 0x00, 0x01, 0x00, NULL}, + + // Coin 1 condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin 1" }, + {0x1b, 0x02, 0x0e, 0x0a, "3 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x0c, "2 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x0e, "1 Coin 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x08, "1 Coin 2 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x06, "1 Coin 3 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x04, "1 Coin 4 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x02, "1 Coin 5 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x0e, 0x00, "1 Coin 6 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + + // Coin 2 condition: Coin Slot Same + {0 , 0xfe, 0 , 8, "Coin 2" }, + {0x1b, 0x02, 0x70, 0x50, "3 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x40, "1 Coin 2 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x30, "1 Coin 3 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x20, "1 Coin 4 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x10, "1 Coin 5 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + {0x1b, 0x02, 0x70, 0x00, "1 Coin 6 Credits" }, + {0x1b, 0x00, 0x01, 0x01, NULL}, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x1b, 0x01, 0x80, 0x80, "Off" }, + {0x1b, 0x01, 0x80, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x1c, 0x01, 0x01, 0x01, "Off" }, +// {0x1c, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x1c, 0x01, 0x02, 0x00, "Off" }, + {0x1c, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x1c, 0x01, 0x04, 0x04, "Off" }, + {0x1c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1c, 0x01, 0x18, 0x10, "Easy" }, + {0x1c, 0x01, 0x18, 0x18, "Normal" }, + {0x1c, 0x01, 0x18, 0x08, "Hard" }, + {0x1c, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1c, 0x01, 0x20, 0x20, "Off" }, + {0x1c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Join In (1 Credit)" }, + {0x1d, 0x01, 0x01, 0x01, "Off" }, + {0x1d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Buy In" }, + {0x1d, 0x01, 0x02, 0x00, "No" }, + {0x1d, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 5, "Country" }, + {0x1e, 0x01, 0x0f, 0x00, "US" }, + {0x1e, 0x01, 0x0f, 0x01, "Japan" }, + {0x1e, 0x01, 0x0f, 0x02, "Hong-Kong/Taiwan" }, + {0x1e, 0x01, 0x0f, 0x04, "Korea" }, + {0x1e, 0x01, 0x0f, 0x08, "World" }, +}; + +STDDIPINFO(Taotaidoa) + +static void palette_write(INT32 offset) +{ + UINT8 r, g, b; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = (data >> 10) & 0x1f; + r = (r << 3) | (r >> 2); + g = (data >> 5) & 0x1f; + g = (g << 3) | (g >> 2); + b = (data >> 0) & 0x1f; + b = (b << 3) | (b >> 2); + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +UINT8 __fastcall taotaido_read_byte(UINT32 address) +{ + if (address < 0xffff00) return 0; + + switch (address) + { + case 0xffff80: + case 0xffff81: + return DrvInps[0] >> ((~address & 1) << 3); + + case 0xffff82: + case 0xffff83: + return DrvInps[1] >> ((~address & 1) << 3); + + case 0xffff84: + case 0xffff85: + return DrvInps[2] >> ((~address & 1) << 3); + + case 0xffff87: + return DrvDip[0]; + + case 0xffff89: + return DrvDip[1]; + + case 0xffff8b: + return DrvDip[2]; + + case 0xffff8f: + return DrvDip[3]; + + case 0xffffa0: // p3 + case 0xffffa1: + return DrvInps[3] >> ((~address & 1) << 3); + + case 0xffffa2: // p4 + case 0xffffa3: + return DrvInps[4] >> ((~address & 1) << 3); + + case 0xffffe1: + return *pending_command; + } + + return 0; +} + +UINT16 __fastcall taotaido_read_word(UINT32 address) +{ + if (address < 0xffff00) return 0; + + switch (address) + { + case 0xffff80: + return DrvInps[0]; + + case 0xffff82: + return DrvInps[1]; + + case 0xffff84: + return DrvInps[2]; + + case 0xffffa0: // p3 + return DrvInps[3]; + + case 0xffffa2: // p4 + return DrvInps[4]; + } + + return 0; +} + +void __fastcall taotaido_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff000) == 0xffc000) { + DrvPalRAM[(address & 0xfff) ^ 1] = data; + palette_write(address & 0xffe); + return; + } + + if (address < 0xffff00) return; + + switch (address) + { + case 0xffff08: + case 0xffff09: + case 0xffff0a: + case 0xffff0b: + case 0xffff0c: + case 0xffff0d: + case 0xffff0e: + case 0xffff0f: + taotaido_tileregs[address & 0x07] = data; + return; + + case 0xffff40: + case 0xffff41: + case 0xffff42: + case 0xffff43: + case 0xffff44: + case 0xffff45: + case 0xffff46: + case 0xffff47: + taotaido_spritebank[address & 7] = data; + return; + + case 0xffffc1: + { + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]); + if (nCycles <= ZetTotalCycles()) return; + + BurnTimerUpdate(nCycles); + + *pending_command = 1; + *soundlatch = data; + ZetNmi(); + } + return; + } +} + +void __fastcall taotaido_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff000) == 0xffc000) { + *((UINT16*)(DrvPalRAM + (address & 0xffe))) = data; + palette_write(address & 0xffe); + return; + } + + if (address < 0xffff00) return; + + switch (address) + { + case 0xffff08: + case 0xffff0a: + case 0xffff0c: + case 0xffff0e: + *((UINT16*)(taotaido_tileregs + (address & 0x06))) = data; + return; + + case 0xffff40: + case 0xffff42: + case 0xffff44: + case 0xffff46: + *((UINT16*)(taotaido_spritebank + (address & 6))) = data; + return; + } +} + +static void taotaido_sound_bankswitch(INT32 data) +{ + *nDrvZ80Bank = data & 3; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + 0x8000 * *nDrvZ80Bank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + 0x8000 * *nDrvZ80Bank); +} + +void __fastcall taotaido_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + BurnYM2610Write(port & 3, data); + return; + + case 0x04: + if (*nDrvZ80Bank != (data & 3)) { + taotaido_sound_bankswitch(data); + } + return; + + case 0x08: + *pending_command = 0; + return; + } +} + +UINT8 __fastcall taotaido_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return BurnYM2610Read(0); + + + case 0x02: + return BurnYM2610Read(2); + + case 0x0c: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[ 4] = { + 0x000, 0x001, 0x002, 0x003 + }; + + INT32 XOffs[16] = { + 0x004, 0x000, 0x00c, 0x008, 0x014, 0x010, 0x01c, 0x018, + 0x024, 0x020, 0x02c, 0x028, 0x034, 0x030, 0x03c, 0x038 + }; + + INT32 YOffs[16] = { + 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 + }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x600000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x600000); + + GfxDecode(0xc000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + taotaido_sound_bankswitch(1); + ZetClose(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0xc00000; + DrvGfxROM1 = Next; Next += 0x400000; + + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x200000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x001000; + DrvBgRAM = Next; Next += 0x004000; + DrvSprRAM0 = Next; Next += 0x002000; + DrvSprRAM1 = Next; Next += 0x010000; + DrvScrollRAM = Next; Next += 0x000400; + DrvSpr0Buf0 = Next; Next += 0x002000; + DrvSpr1Buf0 = Next; Next += 0x010000; + DrvSpr0Buf1 = Next; Next += 0x002000; + DrvSpr1Buf1 = Next; Next += 0x010000; + + taotaido_tileregs = Next; Next += 0x000010; + taotaido_spritebank = Next; Next += 0x000010; + + pending_command = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + nDrvZ80Bank = Next; Next += 0x000001; + + DrvZ80RAM = Next; Next += 0x000800; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void taotaidoFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 taotaidoSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 5000000; +} + +static double taotaidoGetTime() +{ + return (double)ZetTotalCycles() / 5000000.0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 1)) return 1; + if (BurnLoadRom(Drv68KROM + 0x080000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x400000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x000000, 8, 1)) return 1; + + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvBgRAM, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(DrvSprRAM0, 0xa00000, 0xa01fff, SM_RAM); + SekMapMemory(DrvSprRAM1, 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xfe0000, 0xfeffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xffc000, 0xffcfff, SM_ROM); + SekMapMemory(DrvScrollRAM, 0xffe000, 0xffe3ff, SM_RAM); + SekSetWriteByteHandler(0, taotaido_write_byte); + SekSetWriteWordHandler(0, taotaido_write_word); + SekSetReadByteHandler(0, taotaido_read_byte); + SekSetReadWordHandler(0, taotaido_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x77ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x77ff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetSetInHandler(taotaido_sound_in); + ZetSetOutHandler(taotaido_sound_out); + ZetMemEnd(); + ZetClose(); + + INT32 nDrvSndROM0Size = 0x100000; + INT32 nDrvSndROM1Size = 0x200000; + BurnYM2610Init(8000000, DrvSndROM1, &nDrvSndROM1Size, DrvSndROM0, &nDrvSndROM0Size, &taotaidoFMIRQHandler, taotaidoSynchroniseStream, taotaidoGetTime, 0); + BurnTimerAttachZet(5000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2610Exit(); + + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer() +{ + UINT16 *vram = (UINT16*)DrvBgRAM; + UINT16 *scroll = (UINT16*)DrvScrollRAM; + + for (INT32 line = 0; line < 224; line++) + { + INT32 scrolly = ((scroll[(line << 1) | 1] >> 4) + 0) & 0x3ff; + INT32 scrollx = ((scroll[(line << 1) | 0] >> 4) + 30) & 0x7ff; + + INT32 sy = scrolly >> 4; + + for (INT32 col = 0; col < (320 / 16) + 1; col++) + { + INT32 sx = (scrollx >> 4) + col; + INT32 ofst = (sy << 6) + (sx & 0x3f) + ((sx & 0x40) << 6); + + INT32 code = vram[ofst]; + INT32 bank = (code >> 9) & 7; + INT32 color = ((code >> 12) << 4) | 0x300; + + code = (code & 0x1ff) | (taotaido_tileregs[bank] << 9); + + UINT8 *src = DrvGfxROM1 + (code << 8) + ((scrolly & 0x0f) << 4); + + for (INT32 x = 0; x < 16; x++) { + INT32 xx = (x + (col << 4)) - (scrollx & 0x0f); + if (xx < 0 || xx >= nScreenWidth) continue; + pTransDraw[(line * nScreenWidth) + xx] = src[x] | color; + } + } + } +} + +static void draw_sprite(INT32 spriteno) +{ + UINT16 *source = (UINT16*)DrvSpr0Buf1; + UINT16 *source1 = (UINT16*)DrvSpr1Buf1; + source += spriteno*4; + + INT32 yzoom = (source[0] & 0xf000) >> 12; + INT32 xzoom = (source[1] & 0xf000) >> 12; + + INT32 ysize = (source[0] & 0x0e00) >> 9; + INT32 xsize = (source[1] & 0x0e00) >> 9; + + INT32 ypos = source[0] & 0x01ff; + INT32 xpos = source[1] & 0x01ff; + + INT32 yflip = source[2] & 0x8000; + INT32 xflip = source[2] & 0x4000; + INT32 color = (source[2] & 0x1f00) >> 8; + + INT32 tile = source[3] & 0xffff; + + xpos += (xsize*xzoom+2)/4; + ypos += (ysize*yzoom+2)/4; + + xzoom = 32 - xzoom; + yzoom = 32 - yzoom; + + for (INT32 y = 0;y <= ysize;y++) + { + INT32 sx,sy; + + if (yflip) sy = ((ypos + yzoom * (ysize - y)/2 + 16) & 0x1ff) - 16; + else sy = ((ypos + yzoom * y / 2 + 16) & 0x1ff) - 16; + + for (INT32 x = 0;x <= xsize;x++) + { + INT32 realtile = source1[tile & 0x7fff]; + + if (realtile > 0x3fff) + { + INT32 block; + + block = (realtile & 0x3800)>>11; + + realtile &= 0x07ff; + realtile |= taotaido_spritebank[block] * 0x800; + } + + if (xflip) sx = ((xpos + xzoom * (xsize - x) / 2 + 16) & 0x1ff) - 16; + else sx = ((xpos + xzoom * x / 2 + 16) & 0x1ff) - 16; + + if (yflip) { + if (xflip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, realtile, sx, sy, color, 4, 15, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, realtile, sx, sy, color, 4, 15, 0, DrvGfxROM0); + } + } else { + if (xflip) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, realtile, sx, sy, color, 4, 15, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, realtile, sx, sy, color, 4, 15, 0, DrvGfxROM0); + } + } + + tile++; + } + } +} + +static void draw_sprites() +{ + UINT16 *source = (UINT16*)DrvSpr0Buf1; + UINT16 *finish = source + 0x2000/2; + + while (source < finish) + { + if (source[0] == 0x4000) break; + + draw_sprite(source[0] & 0x3ff); + + source++; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i+=2) { + palette_write(i); + } + } + + draw_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + memset (DrvInps, 0xff, 5 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + DrvInps[2] ^= (DrvJoy3[i] & 1) << i; + DrvInps[3] ^= (DrvJoy4[i] & 1) << i; + DrvInps[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)(5000000.0 / 60.0); + + SekOpen(0); + ZetOpen(0); + + SekRun(nCyclesTotal[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSpr0Buf1, DrvSpr0Buf0, 0x02000); + memcpy (DrvSpr1Buf1, DrvSpr1Buf0, 0x10000); + memcpy (DrvSpr0Buf0, DrvSprRAM0, 0x02000); + memcpy (DrvSpr1Buf0, DrvSprRAM1, 0x10000); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + } + + ZetOpen(0); + taotaido_sound_bankswitch(*nDrvZ80Bank); + ZetClose(); + + return 0; +} + + +// Tao Taido (set 1) + +static struct BurnRomInfo taotaidoRomDesc[] = { + { "1-u90.bin", 0x080000, 0xa3ee30da, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2-u91.bin", 0x080000, 0x30b7e4fb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3-u113.bin", 0x020000, 0xa167c4e4, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "u86.bin", 0x200000, 0x908e251e, 3 | BRF_GRA }, // 3 Sprites + { "u87.bin", 0x200000, 0xc4290ba6, 3 | BRF_GRA }, // 4 + { "u88.bin", 0x200000, 0x407d9aeb, 3 | BRF_GRA }, // 5 + + { "u15.bin", 0x200000, 0xe95823e9, 4 | BRF_GRA }, // 6 Background Tiles + + { "u104.bin", 0x100000, 0xe89387a9, 5 | BRF_SND }, // 7 Samples + { "u127.bin", 0x200000, 0x0cf0cb23, 6 | BRF_SND }, // 8 +}; + +STD_ROM_PICK(taotaido) +STD_ROM_FN(taotaido) + +struct BurnDriver BurnDrvTaotaido = { + "taotaido", NULL, NULL, NULL, "1993", + "Tao Taido (set 1)\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, taotaidoRomInfo, taotaidoRomName, NULL, NULL, TaotaidoInputInfo, TaotaidoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; + + +// Tao Taido (set 2) + +static struct BurnRomInfo taotaidoaRomDesc[] = { + { "tt0-u90.bin", 0x080000, 0x69d4cca7, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tt1-u91.bin", 0x080000, 0x41025469, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "3-u113.bin", 0x020000, 0xa167c4e4, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "u86.bin", 0x200000, 0x908e251e, 3 | BRF_GRA }, // 3 Sprites + { "u87.bin", 0x200000, 0xc4290ba6, 3 | BRF_GRA }, // 4 + { "u88.bin", 0x200000, 0x407d9aeb, 3 | BRF_GRA }, // 5 + + { "u15.bin", 0x200000, 0xe95823e9, 4 | BRF_GRA }, // 6 Background Tiles + + { "u104.bin", 0x100000, 0xe89387a9, 5 | BRF_SND }, // 7 Samples + { "u127.bin", 0x200000, 0x0cf0cb23, 6 | BRF_SND }, // 8 +}; + +STD_ROM_PICK(taotaidoa) +STD_ROM_FN(taotaidoa) + +struct BurnDriver BurnDrvTaotaidoa = { + "taotaidoa", "taotaido", NULL, NULL, "1993", + "Tao Taido (set 2)\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, taotaidoaRomInfo, taotaidoaRomName, NULL, NULL, TaotaidoaInputInfo, TaotaidoaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_tecmosys.cpp b/src/burn/drivers/misc_post90s/d_tecmosys.cpp new file mode 100644 index 00000000..e7c2381d --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_tecmosys.cpp @@ -0,0 +1,1481 @@ +// FB Alpha Tecmo System driver module +// Based on MAME driver by Farfetch, David Haywood, Tomasz Slanina, and nuapete + +#include "tiles_generic.h" +#include "msm6295.h" +#include "eeprom.h" +#include "ymz280b.h" +// ymf262 + +//#define ENABLE_SOUND_HARDWARE // no sound without ymf262 core anyway... + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvSprROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; + +static UINT8 *Drv68KRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvBgRAM0; +static UINT8 *DrvBgRAM1; +static UINT8 *DrvBgRAM2; +static UINT8 *DrvBgScrRAM0; +static UINT8 *DrvBgScrRAM1; +static UINT8 *DrvBgScrRAM2; +static UINT8 *spritelist_select; +static UINT8 *Drv88Regs; +static UINT8 *DrvA8Regs; +static UINT8 *DrvB0Regs; +static UINT8 *DrvC0Regs; +static UINT8 *DrvC8Regs; + +#ifdef ENABLE_SOUND_HARDWARE +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *DrvOkiBank; +static UINT8 *DrvZ80Bank; +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +#endif + +static UINT8 protection_read_pointer; +static UINT8 protection_status; +static UINT8 protection_value; + +static UINT16 *DrvTmpSprites; + +static UINT32 *DrvPalette; +static UINT32 *DrvPalette24; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static INT32 vblank; +static INT32 watchdog; +static INT32 deroon; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 10, "p1 fire 4" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 10, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service 1", BIT_DIGITAL, DrvJoy1 + 9, "service" }, + {"Service 2", BIT_DIGITAL, DrvJoy2 + 9, "service" }, +}; + +STDINPUTINFO(Drv) + +struct prot_data +{ + UINT8 passwd_len; + const UINT8* passwd; + const UINT8* code; + UINT8 checksums[4]; +}; + +static const struct prot_data *protection_data; + +static const UINT8 deroon_passwd[] = { 'L', 'U', 'N', 'A', 0 }; +static const UINT8 deroon_upload[] = { 0x02, 0x4e, 0x75, 0x00 }; +static const struct prot_data deroon_data = { 0x05, deroon_passwd, deroon_upload, { 0xa6, 0x29, 0x4b, 0x3f } }; + +static const UINT8 tkdensho_passwd[] = { 'A','G','E','P','R','O','T','E','C','T',' ','S','T','A','R','T', 0 }; +static const UINT8 tkdensho_upload[] = { 0x06, 0x4e, 0xf9, 0x00, 0x00, 0x22, 0xc4, 0x00 }; +static const struct prot_data tkdensho_data = { 0x11, tkdensho_passwd, tkdensho_upload, { 0xbf, 0xfa, 0xda, 0xda } }; +static const struct prot_data tkdenshoa_data = { 0x11, tkdensho_passwd, tkdensho_upload, { 0xbf, 0xfa, 0x21, 0x5d } }; + +static void protection_reset() +{ + protection_read_pointer = 0; + protection_status = 0; // idle + protection_value = 0xff; +} + +static void tecmosys_prot_data_write(INT32 data) +{ + static const UINT8 ranges[] = { + 0x10,0x11,0x12,0x13,0x24,0x25,0x26,0x27,0x38,0x39,0x3a,0x3b,0x4c,0x4d,0x4e,0x4f, 0x00 + }; + + switch (protection_status) + { + case 0: // idle + if (data == 0x13) + { + protection_status = 1; // login + protection_value = protection_data->passwd_len; + protection_read_pointer = 0; + break; + } + break; + + case 1: // login + if (protection_read_pointer >= protection_data->passwd_len) + { + protection_status = 2; // send code + protection_value = protection_data->code[0]; + protection_read_pointer = 1; + } + else + protection_value = protection_data->passwd[protection_read_pointer++] == data ? 0 : 0xff; + break; + + case 2: // send code + if (protection_read_pointer >= protection_data->code[0]+2) + { + protection_status = 3; // send address + protection_value = ranges[0]; + protection_read_pointer = 1; + } + else + protection_value = data == protection_data->code[protection_read_pointer-1] ? protection_data->code[protection_read_pointer++] : 0xff; + break; + + case 3: // send address + if (protection_read_pointer >= 17) + { + protection_status = 4; // send checksum + protection_value = 0; + protection_read_pointer = 0; + } + else + { + protection_value = data == ranges[protection_read_pointer-1] ? ranges[protection_read_pointer++] : 0xff; + } + break; + + case 4: // send checksum + if (protection_read_pointer >= 5) + { + protection_status = 5; // done + protection_value = 0; + } + else + protection_value = data == protection_data->checksums[protection_read_pointer] ? protection_data->checksums[protection_read_pointer++] : 0xff; + break; + + case 5: // done + break; + } +} + +void __fastcall tecmosys_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x880000: + case 0x880002: + *((UINT16*)(Drv88Regs + (address & 0x02))) = data; + return; + + case 0x880008: + *spritelist_select = data & 0x03; + return; + + case 0x880022: + watchdog = 0; + return; + + case 0xa00000: + EEPROMWrite((data & 0x0400), (data & 0x0200), (data & 0x0800)); + return; + + case 0xa80000: + case 0xa80002: + case 0xa80004: + *((UINT16*)(DrvA8Regs + (address & 0x06))) = data; + return; + + case 0xb00000: + case 0xb00002: + case 0xb00004: + *((UINT16*)(DrvB0Regs + (address & 0x06))) = data; + return; + + case 0xb80000: // protection status - does nothing + return; + + case 0xc00000: + case 0xc00002: + case 0xc00004: + *((UINT16*)(DrvC0Regs + (address & 0x06))) = data; + return; + + case 0xc80000: + case 0xc80002: + case 0xc80004: + *((UINT16*)(DrvC8Regs + (address & 0x06))) = data; + return; + + case 0xe00000: +#ifdef ENABLE_SOUND_HARDWARE + ZetRun((SekTotalCycles() / 2) - ZetTotalCycles()); + *soundlatch = data & 0xff; + ZetNmi(); +#endif + return; + + case 0xe80000: + tecmosys_prot_data_write(data >> 8); + return; + } +} + +void __fastcall tecmosys_main_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ + +} + +UINT16 __fastcall tecmosys_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x880000: + return vblank; + + case 0xd00000: + return DrvInputs[0]; + + case 0xd00002: + return DrvInputs[1]; + + case 0xd80000: + return (EEPROMRead() & 1) << 11; + + case 0xf00000: +#ifdef ENABLE_SOUND_HARDWARE + ZetRun((SekTotalCycles() / 2) - ZetTotalCycles()); + return *soundlatch2; +#else + return 0; +#endif + + case 0xf80000: + INT32 ret = protection_value; + protection_value = 0xff; + return ret << 8; + } + + return 0; +} + +UINT8 __fastcall tecmosys_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0xb80000: + return 0x00; // protection status + } + + return 0; +} + +static inline void palette_update(INT32 pal) +{ + UINT16 p = *((UINT16*)(DrvPalRAM + pal * 2)); + + INT32 r = (p >> 5) & 0x1f; + INT32 g = (p >> 10) & 0x1f; + INT32 b = (p >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[pal] = BurnHighCol(r, g, b, 0); + DrvPalette24[pal] = (r << 16) + (g << 8) + b; +} + +void __fastcall tecmosys_palette_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xff8000) == 0x900000) { + *((UINT16 *)(DrvPalRAM + 0x0000 + (address & 0x7ffe))) = data; + palette_update((0x0000 + (address & 0x7ffe)) / 2); + return; + } + + if ((address & 0xfff000) == 0x980000) { + *((UINT16 *)(DrvPalRAM + 0x8000 + (address & 0x0ffe))) = data; + palette_update((0x8000 + (address & 0x0ffe)) / 2); + return; + } +} + +void __fastcall tecmosys_palette_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xff8000) == 0x900000) { + DrvPalRAM[(0x0000 + (address & 0x7fff)) ^ 1] = data; + palette_update((0x0000 + (address & 0x7ffe)) / 2); + return; + } + + if ((address & 0xfff000) == 0x980000) { + DrvPalRAM[(0x8000 + (address & 0x0fff)) ^ 1] = data; + palette_update((0x8000 + (address & 0x0ffe)) / 2); + return; + } +} + +#ifdef ENABLE_SOUND_HARDWARE + +static void bankswitch(INT32 data) +{ + if ((data & 0x0f) != *DrvZ80Bank) { + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + (data & 0x0f) * 0x4000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + (data & 0x0f) * 0x4000); + } + + *DrvZ80Bank = data & 0x0f; +} + +static void oki_bankswitch(INT32 data) +{ + if ((data & 0x33) != *DrvOkiBank) { + + INT32 upperbank = (data & 0x30) >> 4; + INT32 lowerbank = (data & 0x03) >> 0; + + if (lowerbank != ((*DrvOkiBank & 0x0f) >> 0)) { + memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x80000 + lowerbank * 0x20000, 0x20000); + } + + if (upperbank != ((*DrvOkiBank & 0xf0) >> 4)) { + memcpy (DrvSndROM0 +0x20000, DrvSndROM0 + 0x80000 + upperbank * 0x20000, 0x20000); + } + } + + *DrvOkiBank = data & 0x33; +} + +void __fastcall tecmosys_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + // ymf262_w + return; + + case 0x10: + MSM6295Command(0, data); + return; + + case 0x20: + oki_bankswitch(data); + return; + + case 0x30: + bankswitch(data); + return; + + case 0x50: + *soundlatch2 = data; + return; + + case 0x60: + YMZ280BSelectRegister(data); + return; + + case 0x61: + YMZ280BWriteRegister(data); + return; + } +} + +UINT8 __fastcall tecmosys_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + return 0; // ymf262_r + + case 0x10: + return MSM6295ReadStatus(0); + + case 0x40: + return *soundlatch; + + case 0x60: + case 0x61: + return YMZ280BReadStatus(); + } + + return 0; +} + +/* +static void DrvIrqHandler(INT32 irq) // for ymf262 +{ + if (irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} +*/ + +#endif + +static INT32 DrvDoReset(INT32 full_reset) +{ + if (full_reset) { + memset (AllRam, 0, RamEnd - AllRam); + } + + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + protection_reset(); + + watchdog = 0; + +#ifdef ENABLE_SOUND_HARDWARE + ZetOpen(0); + ZetReset(); + ZetClose(); + + // ymf262 + YMZ280BReset(); + MSM6295Reset(0); + + *DrvOkiBank = *DrvZ80Bank = ~0; +#endif + + return 0; +} + +#ifdef ENABLE_SOUND_HARDWARE +static INT32 MemIndex(INT32 sndlen) +#else +static INT32 MemIndex(INT32 /*sndlen*/) +#endif +{ + + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + + DrvGfxROM0 = Next; Next += 0x200000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM3 = Next; Next += 0x200000; + +#ifdef ENABLE_SOUND_HARDWARE + DrvZ80ROM = Next; Next += 0x040000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + + YMZ280BROM = Next; + DrvSndROM1 = Next; Next += sndlen; +#endif + + DrvPalette = (UINT32*)Next; Next += 0x4800 * sizeof(UINT32); + DrvPalette24 = (UINT32*)Next; Next += 0x4800 * sizeof(UINT32); + + DrvTmpSprites = (UINT16*)Next; Next += 320 * 240 * sizeof(UINT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvSprRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x009000; + + DrvTxtRAM = Next; Next += 0x004000; + + DrvBgRAM0 = Next; Next += 0x001000; + DrvBgScrRAM0 = Next; Next += 0x000400; + DrvBgRAM1 = Next; Next += 0x001000; + DrvBgScrRAM1 = Next; Next += 0x000400; + DrvBgRAM2 = Next; Next += 0x001000; + DrvBgScrRAM2 = Next; Next += 0x000400; + + +#ifdef ENABLE_SOUND_HARDWARE + DrvOkiBank = Next; Next += 0x000001; + DrvZ80Bank = Next; Next += 0x000001; + + DrvZ80RAM = Next; Next += 0x001800; + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; +#endif + spritelist_select = Next; Next += 0x000001; + + Drv88Regs = Next; Next += 0x000004; + DrvA8Regs = Next; Next += 0x000006; + DrvB0Regs = Next; Next += 0x000006; + DrvC0Regs = Next; Next += 0x000006; + DrvC8Regs = Next; Next += 0x000006; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void descramble_sprites(INT32 len) +{ + UINT8 *src = DrvSprROM; + UINT8 tmp[4]; + + for (INT32 i=0; i < len; i+=4) + { + tmp[0] = ((src[i+2]&0xf0)>>0) | ((src[i+3]&0xf0)>>4); + tmp[1] = ((src[i+2]&0x0f)<<4) | ((src[i+3]&0x0f)>>0); + tmp[2] = ((src[i+0]&0xf0)>>0) | ((src[i+1]&0xf0)>>4); + tmp[3] = ((src[i+0]&0x0f)<<4) | ((src[i+1]&0x0f)<<0); + + memcpy (src + i, tmp, 4); + } +} + +static void expand_characters() +{ + for (INT32 i = 0x100000 - 1; i >= 0; i--) { + DrvGfxROM0[i * 2 + 0] = DrvGfxROM0[i] >> 4; + DrvGfxROM0[i * 2 + 1] = DrvGfxROM0[i] & 0x0f; + } +} + +static void expand_tiles(UINT8 *rom, INT32 len) +{ + INT32 Planes[4] = { 0, 1, 2, 3 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, 0x100, 0x104, 0x108, 0x10c, 0x110, 0x114, 0x118, 0x11c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + + memcpy (tmp, rom, len); + + GfxDecode((len * 2) / (16 * 16), 4, 16, 16, Planes, XOffs, YOffs, 128*8, tmp, rom); + + BurnFree (tmp); +} + +static INT32 CommonInit(INT32 (*pRomLoadCallback)(), INT32 spritelen, INT32 sndlen, const struct prot_data *dev_data_pointer, INT32 game) +{ + AllMem = NULL; + MemIndex(sndlen); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(sndlen); + + DrvSprROM = (UINT8*)BurnMalloc(spritelen); + if (DrvSprROM == NULL) return 1; + + if (pRomLoadCallback) { + if (pRomLoadCallback()) return 1; + } + + descramble_sprites(spritelen); + expand_characters(); + expand_tiles(DrvGfxROM1, 0x100000); + expand_tiles(DrvGfxROM2, 0x100000); + expand_tiles(DrvGfxROM3, 0x100000); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x300000, 0x300fff, SM_RAM); + SekMapMemory(DrvBgScrRAM0, 0x301000, 0x3013ff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x400000, 0x400fff, SM_RAM); + SekMapMemory(DrvBgScrRAM1, 0x401000, 0x4013ff, SM_RAM); + SekMapMemory(DrvBgRAM2, 0x500000, 0x500fff, SM_RAM); + SekMapMemory(DrvBgScrRAM2, 0x501000, 0x5013ff, SM_RAM); + SekMapMemory(DrvTxtRAM, 0x700000, 0x703fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x900000, 0x907fff, SM_ROM); + SekMapMemory(DrvPalRAM + 0x8000,0x980000, 0x980fff, SM_ROM); + SekSetWriteWordHandler(0, tecmosys_main_write_word); + SekSetWriteByteHandler(0, tecmosys_main_write_byte); + SekSetReadWordHandler(0, tecmosys_main_read_word); + SekSetReadByteHandler(0, tecmosys_main_read_byte); + + SekMapHandler(1, 0x900000, 0x980fff, SM_WRITE); + SekSetWriteWordHandler(1, tecmosys_palette_write_word); + SekSetWriteByteHandler(1, tecmosys_palette_write_byte); + SekClose(); + + deroon = game; + protection_data = dev_data_pointer; + + EEPROMInit(&eeprom_interface_93C46); + + BurnSetRefreshRate(57.4458); + +#ifdef ENABLE_SOUND_HARDWARE + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xe000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xe000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xe000, 0xf7ff, 2, DrvZ80RAM); + ZetSetOutHandler(tecmosys_sound_out); + ZetSetInHandler(tecmosys_sound_in); + ZetMemEnd(); + ZetClose(); + + // ymf262 + + YMZ280BInit(16900000, NULL, 3); + + MSM6295Init(0, 2000000 / 132, 50.0, 1); +#endif + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + EEPROMExit(); + + SekExit(); + +#ifdef ENABLE_SOUND_HARDWARE + ZetExit(); + + // ymf262 + + MSM6295Exit(0); + MSM6295ROM = NULL; + + YMZ280BExit(); + YMZ280BROM = NULL; +#endif + + BurnFree (DrvSprROM); + BurnFree (AllMem); + + return 0; +} + +static void draw_character_layer() +{ + UINT16 *vram = (UINT16*)DrvTxtRAM; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs * 2 + 0]; + INT32 code = vram[offs * 2 + 1] & 0x7fff; + INT32 color = attr & 0x003f; + INT32 flipy = attr & 0x0080; + INT32 flipx = attr & 0x0040; + + if (code == 0) continue; // Should save some cycles + + if (sx >= 0 && sx <= (nScreenWidth - 8) && sy >= 0 && sy <= (nScreenHeight - 8)) { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0xc400, DrvGfxROM0); + } + } + } + } +} + +static void draw_background_layer(UINT8 *ram, UINT8 *gfx, UINT8 *regs, INT32 yoff, INT32 xoff, INT32 priority) +{ + UINT16 *vram = (UINT16*)ram; + + INT32 scrollx = (*((UINT16*)(regs + 0)) + xoff) & 0x1ff; + INT32 scrolly = (*((UINT16*)(regs + 2)) + yoff) & 0x1ff; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 512; + sy -= scrolly; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs * 2 + 0]; + INT32 code = vram[offs * 2 + 1] & 0x1fff; + INT32 color = attr & 0x003f; + INT32 flipy = attr & 0x0080; + INT32 flipx = attr & 0x0040; + + if (!code) continue; // Should save some cycles + + if (sx >= 0 && sx <= (nScreenWidth - 16) && sy >= 0 && sy <= (nScreenHeight - 16)) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, priority, gfx); + } + } + } + } +} + +static void draw_sprite_zoomed(INT32 addr, INT32 color, INT32 x, INT32 y, INT32 flipx, INT32 flipy, INT32 xsize, INT32 ysize, INT32 zoomx, INT32 zoomy) +{ + if (y >= nScreenHeight || x >= nScreenWidth) return; + + INT32 drawx, drawy; + UINT8 *rom = DrvSprROM + addr; + + for (INT32 ycnt = 0; ycnt < ysize; ycnt++, rom += xsize) + { + if (flipy) + drawy = y + (((ysize * zoomy) / 256) - 1) - ((ycnt * zoomy) / 256); + else + drawy = y + ((ycnt * zoomy) / 256); + + if (drawy < 0 || drawy >= 240) continue; + + UINT16 *dstptr = DrvTmpSprites + drawy * nScreenWidth; + + for (INT32 xcnt = 0; xcnt < xsize; xcnt++) + { + if (flipx) + drawx = x + (((xsize * zoomx) / 256) - 1) - ((xcnt * zoomx) / 256); + else + drawx = x + ((xcnt * zoomx) / 256); + + if (drawx >= 0 && drawx < 320) + { + INT32 data = rom[xcnt]; + + if (data) dstptr[drawx] = data + color; + } + } + } +} + +static void draw_sprite_nozoom(INT32 addr, INT32 color, INT32 x, INT32 y, INT32 flipx, INT32 flipy, INT32 xsize, INT32 ysize) +{ + if (y >= nScreenHeight || x >= nScreenWidth) return; + + INT32 drawx, drawy; + UINT8 *rom = DrvSprROM + addr; + + for (INT32 ycnt = 0; ycnt < ysize; ycnt++, rom += xsize) + { + if (flipy) + drawy = y + (ysize - 1) - ycnt; + else + drawy = y + ycnt; + + if (drawy < 0 || drawy >= 240) continue; + + UINT16 *dstptr = DrvTmpSprites + drawy * nScreenWidth; + + if (x >= 0 && (x + xsize) < nScreenWidth) { + if (flipx) { + drawx = x + (xsize - 1); + + for (INT32 xcnt = 0; xcnt < xsize; xcnt++) + { + INT32 data = rom[xcnt]; + + if (data) dstptr[drawx - xcnt] = data + color; + } + } else { + dstptr += x; + + for (INT32 xcnt = 0; xcnt < xsize; xcnt++) + { + INT32 data = rom[xcnt]; + + if (data) dstptr[xcnt] = data + color; + } + } + } else { + for (INT32 xcnt = 0; xcnt < xsize; xcnt++) + { + if (flipx) + drawx = x + (xsize - 1) - xcnt; + else + drawx = x + xcnt; + + if (drawx >= 0 && drawx < 320) + { + INT32 data = rom[xcnt]; + + if (data) dstptr[drawx] = data + color; + } + } + } + } +} + +static void draw_sprites() +{ + INT32 extrax = *((UINT16*)(Drv88Regs + 0)); + INT32 extray = *((UINT16*)(Drv88Regs + 2)); + + memset (DrvTmpSprites, 0, 320 * 240 * sizeof(INT16)); + + UINT16 *spriteram = (UINT16*)(DrvSprRAM + (*spritelist_select * 0x4000)); + + for (INT32 i = 0; i < 0x4000/2; i+=8) + { + INT32 x = ((spriteram[i+0] + 386) - extrax) & 0x3ff; + INT32 y = ((spriteram[i+1] + 1) - extray) & 0x1ff; + INT32 zoomx = spriteram[i+2] & 0x0fff; + INT32 zoomy = spriteram[i+3] & 0x0fff; + INT32 prio =(spriteram[i+4] & 0x0030) << 10; + INT32 flipx = spriteram[i+4] & 0x0040; + INT32 flipy = spriteram[i+4] & 0x0080; + INT32 color = spriteram[i+4] & 0x3f00; + INT32 addr =(spriteram[i+5] | ((spriteram[i+4] & 0x000f) << 16)) << 8; + INT32 ysize =(spriteram[i+6] & 0x00ff) << 4; + INT32 xsize =(spriteram[i+6] & 0xff00) >> 4; + + if ((spriteram[i+4] & 0x8000) || !zoomx || !zoomy) continue; + + if (x & 0x200) x -= 0x400; // positions are signed + if (y & 0x100) y -= 0x200; + + if (zoomx == 0x100 && zoomy == 0x100) { + draw_sprite_nozoom(addr, color + prio, x, y, flipx, flipy, xsize, ysize); + } else { + draw_sprite_zoomed(addr, color + prio, x, y, flipx, flipy, xsize, ysize, zoomx, zoomy); + } + } +} + +static void blend_sprites_and_transfer() +{ + UINT16 *srcptr = pTransDraw; + UINT16 *srcptr2 = DrvTmpSprites; + UINT8 *dstptr = pBurnDraw; + UINT16 *palram = (UINT16*)DrvPalRAM; + + for (INT32 z = 0; z < 320 * 240; z++) + { + if (!(srcptr2[z] & 0x3fff)) // tiles only, copy + { + PutPix(dstptr + z * nBurnBpp, DrvPalette[(srcptr[z] & 0x7ff) + 0x4000]); + continue; + } + + // check for blend/priority + + INT32 pxl =(srcptr [z] & 0x07ff) + 0x4000; + INT32 pxl2 =(srcptr2[z] & 0x3fff); + + if ((palram[pxl] & 0x8000) && (palram[pxl2] & 0x8000)) // blend + { + INT32 colour = DrvPalette24[pxl]; + INT32 colour2 = DrvPalette24[pxl2]; + + INT32 b = ((colour & 0x000000ff) + (colour2 & 0x000000ff)) >> 1; + INT32 g = ((colour & 0x0000ff00) + (colour2 & 0x0000ff00)) >> 9; + INT32 r = ((colour & 0x00ff0000) + (colour2 & 0x00ff0000)) >> 17; + + PutPix(dstptr + z * nBurnBpp, BurnHighCol(r, g, b, 0)); + } + else if ((srcptr2[z] & 0xc000) >= (srcptr[z] & 0xc000)) + { + PutPix(dstptr + z * nBurnBpp, DrvPalette[pxl2]); + } + else + { + PutPix(dstptr + z * nBurnBpp, DrvPalette[pxl]); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x9000/2; i++) { + palette_update(i); + } + DrvRecalc = 0; + } + + BurnTransferClear(); + + if (!deroon) { // deroon does not have tiles for this layer, so don't bother drawing it... + draw_background_layer(DrvBgRAM0, DrvGfxROM1, DrvC8Regs, 16, 104, 0x0000); + } + draw_background_layer(DrvBgRAM1, DrvGfxROM2, DrvA8Regs, 17, 106, 0x4000); + draw_background_layer(DrvBgRAM2, DrvGfxROM3, DrvB0Regs, 17, 106, 0x8000); + draw_character_layer(); + + blend_sprites_and_transfer(); + + draw_sprites(); // draw next frame's sprites + + return 0; +} + +static INT32 DrvFrame() +{ + SekNewFrame(); +#ifdef ENABLE_SOUND_HARDWARE + ZetNewFrame(); +#endif + + watchdog++; + if (watchdog >= 400) { //? + DrvDoReset(0); + } + + if (DrvReset) { + DrvDoReset(1); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + // clear opposites + if ((DrvInputs[0] & 0x03) == 0x00) DrvInputs[0] |= 0x03; + if ((DrvInputs[0] & 0x0c) == 0x00) DrvInputs[0] |= 0x0c; + if ((DrvInputs[1] & 0x03) == 0x00) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0x00) DrvInputs[1] |= 0x0c; + } + + INT32 nSegment; + INT32 nInterleave = 256; +#ifdef ENABLE_SOUND_HARDWARE + INT32 nSoundBufferPos = 0; +#endif + INT32 nCyclesTotal[2] = { 1600000000 / 5745, 800000000 / 5745 }; // 57.4458hz + INT32 nCyclesDone[2] = { 0, 0 }; + + nCyclesTotal[0] = (INT32)((INT64)nCyclesTotal[0] * nBurnCPUSpeedAdjust / 0x0100); + nCyclesTotal[1] = (INT32)((INT64)nCyclesTotal[1] * nBurnCPUSpeedAdjust / 0x0100); + + SekOpen(0); + ZetOpen(0); + + vblank = 1; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 240) { + vblank = 0; + SekSetIRQLine(1, SEK_IRQSTATUS_ACK); + } + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + +#ifdef ENABLE_SOUND_HARDWARE + nCyclesDone[1] += ZetRun((SekTotalCycles() / 2) - ZetTotalCycles()); + + if (pBurnSoundOut) { + nSegment = nBurnSoundLen / nInterleave; + YMZ280BRender(pBurnSoundOut + nSoundBufferPos, nSegment); + MSM6295Render(0, pBurnSoundOut + nSoundBufferPos, nSegment); + + nSoundBufferPos += nSegment << 1; + } +#endif + } + + SekSetIRQLine(1, SEK_IRQSTATUS_NONE); + +#ifdef ENABLE_SOUND_HARDWARE + if (pBurnSoundOut) { + nSegment = nBurnSoundLen - nSoundBufferPos; + if (nSegment > 0) { + YMZ280BRender(pBurnSoundOut + nSoundBufferPos, nSegment); + MSM6295Render(0, pBurnSoundOut + nSoundBufferPos, nSegment); + } + } + + ZetClose(); +#endif + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + DrvRecalc = 1; + + if (nAction & ACB_MEMORY_ROM) { + ba.Data = Drv68KROM; + ba.nLen = 0x100000; + ba.nAddress = 0; + ba.szName = "68K ROM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = Drv68KRAM; + ba.nLen = 0x010000; + ba.nAddress = 0x200000; + ba.szName = "68K RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgRAM0; + ba.nLen = 0x0001000; + ba.nAddress = 0x300000; + ba.szName = "Background RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgScrRAM0; + ba.nLen = 0x000400; + ba.nAddress = 0x301000; + ba.szName = "Background Scroll RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgRAM1; + ba.nLen = 0x0001000; + ba.nAddress = 0x400000; + ba.szName = "Midground RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgScrRAM1; + ba.nLen = 0x000400; + ba.nAddress = 0x401000; + ba.szName = "Midground Scroll RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgRAM2; + ba.nLen = 0x0001000; + ba.nAddress = 0x500000; + ba.szName = "Foreground RAM"; + BurnAcb(&ba); + + ba.Data = DrvBgScrRAM2; + ba.nLen = 0x000400; + ba.nAddress = 0x501000; + ba.szName = "Foreground Scroll RAM"; + BurnAcb(&ba); + + ba.Data = DrvTxtRAM; + ba.nLen = 0x004000; + ba.nAddress = 0x700000; + ba.szName = "Text RAM"; + BurnAcb(&ba); + + ba.Data = DrvSprRAM; + ba.nLen = 0x001000; + ba.nAddress = 0x800000; + ba.szName = "Sprite RAM"; + BurnAcb(&ba); + + ba.Data = Drv88Regs; + ba.nLen = 0x000004; + ba.nAddress = 0x880000; + ba.szName = "880000 Registers"; + BurnAcb(&ba); + + ba.Data = DrvPalRAM; + ba.nLen = 0x008000; + ba.nAddress = 0x900000; + ba.szName = "Sprite Palette RAM"; + BurnAcb(&ba); + + ba.Data = DrvPalRAM; + ba.nLen = 0x001000; + ba.nAddress = 0x980000; + ba.szName = "Layer Palette RAM"; + BurnAcb(&ba); + + ba.Data = DrvA8Regs; + ba.nLen = 0x000006; + ba.nAddress = 0xa80000; + ba.szName = "A80000 Registers"; + BurnAcb(&ba); + + ba.Data = DrvB0Regs; + ba.nLen = 0x000006; + ba.nAddress = 0xb00000; + ba.szName = "B00000 Registers"; + BurnAcb(&ba); + + ba.Data = DrvC0Regs; + ba.nLen = 0x000006; + ba.nAddress = 0xc00000; + ba.szName = "C00000 Registers"; + BurnAcb(&ba); + + ba.Data = DrvC8Regs; + ba.nLen = 0x000006; + ba.nAddress = 0xc80000; + ba.szName = "C80000 Registers"; + BurnAcb(&ba); + +#ifdef ENABLE_SOUND_HARDWARE + ba.Data = DrvZ80RAM; + ba.nLen = 0x001800; + ba.nAddress = 0xff0000; + ba.szName = "Z80 RAM (Not accessible)"; + BurnAcb(&ba); +#endif + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); +#ifdef ENABLE_SOUND_HARDWARE + ZetScan(nAction); + + // ymf262 + YMZ280BScan(); + MSM6295Scan(0, nAction); +#endif + + EEPROMScan(nAction, pnMin); + + SCAN_VAR(protection_read_pointer); + SCAN_VAR(protection_status); + SCAN_VAR(protection_value); + + } + + if (nAction & ACB_WRITE) { +#ifdef ENABLE_SOUND_HARDWARE + INT32 bank; + + ZetOpen(0); + bank = *DrvZ80Bank; + *DrvZ80Bank = ~0; + bankswitch(bank); + ZetClose(); + + bank = *DrvOkiBank; + *DrvOkiBank = ~0; + oki_bankswitch(*DrvOkiBank); +#endif + } + + return 0; +} + + +// Deroon DeroDero + +static struct BurnRomInfo deroonRomDesc[] = { + { "t001.upau1", 0x080000, 0x14b92c18, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "t002.upal1", 0x080000, 0x0fb05c68, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "t003.uz1", 0x040000, 0x8bdfafa0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "t101.uah1", 0x200000, 0x74baf845, 3 | BRF_GRA }, // 3 Sprites + { "t102.ual1", 0x200000, 0x1a02c4a3, 3 | BRF_GRA }, // 4 + { "t103.ubl1", 0x400000, 0x84e7da88, 3 | BRF_GRA }, // 5 + { "t104.ucl1", 0x200000, 0x66eb611a, 3 | BRF_GRA }, // 6 + + { "t301.ubd1", 0x100000, 0x8b026177, 4 | BRF_GRA }, // 7 Character Tiles + + { "t201.ubb1", 0x100000, 0xd5a087ac, 6 | BRF_GRA }, // 8 Midground Layer + + { "t202.ubc1", 0x100000, 0xf051dae1, 7 | BRF_GRA }, // 9 Foreground Layer + + { "t401.uya1", 0x200000, 0x92111992, 8 | BRF_SND }, // 10 YMZ280B Samples + + { "t501.uad1", 0x080000, 0x2fbcfe27, 9 | BRF_SND }, // 11 OKI6295 Samples + + { "deroon_68hc11a8.rom", 0x002000, 0x00000000, 0 | BRF_NODUMP }, // 12 68HC11A8 Code + { "deroon_68hc11a8.eeprom", 0x000200, 0x00000000, 0 | BRF_NODUMP }, // 13 68HC11A8 EEPROM +}; + +STD_ROM_PICK(deroon) +STD_ROM_FN(deroon) + +static INT32 DeroonRomCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000000, 1, 2)) return 1; + +#ifdef ENABLE_SOUND_HARDWARE + if (BurnLoadRom(DrvZ80ROM + 0x0000000, 2, 1)) return 1; +#endif + + if (BurnLoadRom(DrvSprROM + 0x0000000, 3, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x0000001, 4, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x0800001, 5, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x1000001, 6, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x0000000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x0000000, 9, 1)) return 1; + +#ifdef ENABLE_SOUND_HARDWARE + if (BurnLoadRom(DrvSndROM1 + 0x0000000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x0080000, 11, 1)) return 1; +#endif + + return 0; +} + +static INT32 DeroonInit() +{ + return CommonInit(DeroonRomCallback, 0x2000000, 0x200000, &deroon_data, 1); +} + +struct BurnDriver BurnDrvDeroon = { + "deroon", NULL, NULL, NULL, "1995", + "Deroon DeroDero\0", "No sound", "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, deroonRomInfo, deroonRomName, NULL, NULL, DrvInputInfo, NULL, + DeroonInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x4800, + 320, 240, 4, 3 +}; + + +// Toukidenshou - Angel Eyes (VER. 960614) + +static struct BurnRomInfo tkdenshoRomDesc[] = { + { "aeprge-2.pal", 0x080000, 0x25e453d6, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "aeprgo-2.pau", 0x080000, 0x22d59510, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "aesprg-2.z1", 0x020000, 0x43550ab6, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "ae100h.ah1", 0x400000, 0x06be252b, 3 | BRF_GRA }, // 3 Sprites + { "ae100.al1", 0x400000, 0x009cdff4, 3 | BRF_GRA }, // 4 + { "ae101h.bh1", 0x400000, 0xf2469eff, 3 | BRF_GRA }, // 5 + { "ae101.bl1", 0x400000, 0xdb7791bb, 3 | BRF_GRA }, // 6 + { "ae102h.ch1", 0x200000, 0xf9d2a343, 3 | BRF_GRA }, // 7 + { "ae102.cl1", 0x200000, 0x681be889, 3 | BRF_GRA }, // 8 + { "ae104.el1", 0x400000, 0xe431b798, 3 | BRF_GRA }, // 9 + { "ae105.fl1", 0x400000, 0xb7f9ebc1, 3 | BRF_GRA }, // 10 + { "ae106.gl1", 0x200000, 0x7c50374b, 3 | BRF_GRA }, // 11 + + { "ae300w36.bd1", 0x080000, 0xe829f29e, 4 | BRF_GRA }, // 12 Character Tiles + + { "ae200w74.ba1", 0x100000, 0xc1645041, 5 | BRF_GRA }, // 13 Background Tiles + + { "ae201w75.bb1", 0x100000, 0x3f63bdff, 6 | BRF_GRA }, // 14 Midground Tiles + + { "ae202w76.bc1", 0x100000, 0x5cc857ca, 7 | BRF_GRA }, // 15 Foreground Tiles + + { "ae400t23.ya1", 0x200000, 0xc6ffb043, 8 | BRF_SND }, // 16 YMZ280B Samples + { "ae401t24.yb1", 0x200000, 0xd83f1a73, 8 | BRF_SND }, // 17 + + { "ae500w07.ad1", 0x080000, 0x3734f92c, 9 | BRF_SND }, // 18 OKI6295 Samples + + { "tkdensho_68hc11a8.rom", 0x002000, 0x00000000, 0 | BRF_NODUMP }, // 19 68HC11A8 Code + { "tkdensho_68hc11a8.eeprom", 0x000200, 0x00000000, 0 | BRF_NODUMP }, // 20 68HC11A8 EEPROM +}; + +STD_ROM_PICK(tkdensho) +STD_ROM_FN(tkdensho) + +static INT32 TkdenshoRomCallback() +{ + if (BurnLoadRom(Drv68KROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0000000, 1, 2)) return 1; + +#ifdef ENABLE_SOUND_HARDWARE + if (BurnLoadRom(DrvZ80ROM + 0x0000000, 2, 1)) return 1; + memcpy (DrvZ80ROM + 0x20000, DrvZ80ROM, 0x20000); +#endif + + if (BurnLoadRom(DrvSprROM + 0x0000000, 3, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x0000001, 4, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x0800000, 5, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x0800001, 6, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x1000000, 7, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x1000001, 8, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x2000001, 9, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x2800001, 10, 2)) return 1; + if (BurnLoadRom(DrvSprROM + 0x3000001, 11, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000000, 12, 1)) return 1; + memcpy (DrvGfxROM0 + 0x80000, DrvGfxROM0, 0x80000); // double here rather than mask later + + if (BurnLoadRom(DrvGfxROM1 + 0x0000000, 13, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x0000000, 14, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x0000000, 15, 1)) return 1; + +#ifdef ENABLE_SOUND_HARDWARE + if (BurnLoadRom(DrvSndROM1 + 0x0000000, 16, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x0200000, 17, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x0080000, 18, 1)) return 1; +#endif + + return 0; +} + +static INT32 TkdenshoInit() +{ + return CommonInit(TkdenshoRomCallback, 0x4000000, 0x400000, &tkdensho_data, 0); +} + +struct BurnDriver BurnDrvTkdensho = { + "tkdensho", NULL, NULL, NULL, "1996", + "Toukidenshou - Angel Eyes (VER. 960614)\0", "No sound", "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, tkdenshoRomInfo, tkdenshoRomName, NULL, NULL, DrvInputInfo, NULL, + TkdenshoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x4800, + 320, 240, 4, 3 +}; + + +// Toukidenshou - Angel Eyes (VER. 960427) + +static struct BurnRomInfo tkdenshoaRomDesc[] = { + { "aeprge.pal", 0x080000, 0x17a209ff, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "aeprgo.pau", 0x080000, 0xd265e6a1, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "aesprg-2.z1", 0x020000, 0x43550ab6, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "ae100h.ah1", 0x400000, 0x06be252b, 3 | BRF_GRA }, // 3 Sprites + { "ae100.al1", 0x400000, 0x009cdff4, 3 | BRF_GRA }, // 4 + { "ae101h.bh1", 0x400000, 0xf2469eff, 3 | BRF_GRA }, // 5 + { "ae101.bl1", 0x400000, 0xdb7791bb, 3 | BRF_GRA }, // 6 + { "ae102h.ch1", 0x200000, 0xf9d2a343, 3 | BRF_GRA }, // 7 + { "ae102.cl1", 0x200000, 0x681be889, 3 | BRF_GRA }, // 8 + { "ae104.el1", 0x400000, 0xe431b798, 3 | BRF_GRA }, // 9 + { "ae105.fl1", 0x400000, 0xb7f9ebc1, 3 | BRF_GRA }, // 10 + { "ae106.gl1", 0x200000, 0x7c50374b, 3 | BRF_GRA }, // 11 + + { "ae300w36.bd1", 0x080000, 0xe829f29e, 4 | BRF_GRA }, // 12 Character Tiles + + { "ae200w74.ba1", 0x100000, 0xc1645041, 5 | BRF_GRA }, // 13 Background Tiles + + { "ae201w75.bb1", 0x100000, 0x3f63bdff, 6 | BRF_GRA }, // 14 Midground Tiles + + { "ae202w76.bc1", 0x100000, 0x5cc857ca, 7 | BRF_GRA }, // 15 Foreground Tiles + + { "ae400t23.ya1", 0x200000, 0xc6ffb043, 8 | BRF_SND }, // 16 YMZ280B Samples + { "ae401t24.yb1", 0x200000, 0xd83f1a73, 8 | BRF_SND }, // 17 + + { "ae500w07.ad1", 0x080000, 0x3734f92c, 9 | BRF_SND }, // 18 OKI6295 Samples + + { "tkdensho_68hc11a8.rom", 0x002000, 0x00000000, 0 | BRF_NODUMP }, // 19 68HC11A8 Code + { "tkdensho_68hc11a8.eeprom", 0x000200, 0x00000000, 0 | BRF_NODUMP }, // 20 68HC11A8 EEPROM +}; + +STD_ROM_PICK(tkdenshoa) +STD_ROM_FN(tkdenshoa) + +static INT32 TkdenshoaInit() +{ + return CommonInit(TkdenshoRomCallback, 0x4000000, 0x400000, &tkdenshoa_data, 0); +} + +struct BurnDriver BurnDrvTkdenshoa = { + "tkdenshoa", "tkdensho", NULL, NULL, "1996", + "Toukidenshou - Angel Eyes (VER. 960427)\0", "No sound", "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, tkdenshoaRomInfo, tkdenshoaRomName, NULL, NULL, DrvInputInfo, NULL, + TkdenshoaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x4800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_tumbleb.cpp b/src/burn/drivers/misc_post90s/d_tumbleb.cpp new file mode 100644 index 00000000..beaea725 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_tumbleb.cpp @@ -0,0 +1,4641 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" +#include "burn_ym3812.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0, 0, 0}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvProtData = NULL; +static UINT8 *DrvMSM6295ROMSrc = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPf1Ram = NULL; +static UINT8 *DrvPf2Ram = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; +static UINT16 *DrvControl = NULL; + +static UINT8 DrvVBlank; +static UINT8 DrvOkiBank; +static UINT8 DrvZ80Bank; +static UINT16 DrvTileBank; +static INT32 DrvSoundLatch; +static INT32 Tumbleb2MusicCommand; +static INT32 Tumbleb2MusicBank; +static INT32 Tumbleb2MusicIsPlaying; + +static INT32 DrvSpriteXOffset; +static INT32 DrvSpriteYOffset; +static INT32 DrvSpriteRamSize; +static INT32 DrvSpriteMask; +static INT32 DrvSpriteColourMask; +static INT32 DrvYM2151Freq; +static INT32 DrvNumSprites; +static INT32 DrvNumChars; +static INT32 DrvNumTiles; +static INT32 DrvHasZ80; +static INT32 DrvHasYM2151; +static INT32 DrvHasYM3812; +static INT32 DrvHasProt; +static INT32 Tumbleb2; +static INT32 Jumpkids; +static INT32 Chokchok; +static INT32 Wlstar; +static INT32 Wondl96; +static INT32 Bcstry; +static INT32 Semibase; +static INT32 SemicomSoundCommand; +static INT32 Pf1XOffset; +static INT32 Pf1YOffset; +static INT32 Pf2XOffset; +static INT32 Pf2YOffset; + +typedef INT32 (*LoadRoms)(); +static LoadRoms DrvLoadRoms; +typedef void (*Map68k)(); +static Map68k DrvMap68k; +typedef void (*MapZ80)(); +static MapZ80 DrvMapZ80; +typedef void (*Render)(); +static Render DrvRender; + +static void DrvDraw(); +static void PangpangDraw(); +static void SuprtrioDraw(); +static void HtchctchDraw(); +static void FncywldDraw(); +static void SdfightDraw(); +static void JumppopDraw(); + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo TumblebInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Tumbleb) + +static struct BurnInputInfo MetlsavrInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Metlsavr) + +static struct BurnInputInfo SuprtrioInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, +}; + +STDINPUTINFO(Suprtrio) + +static struct BurnInputInfo HtchctchInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Htchctch) + +static struct BurnInputInfo FncywldInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Fncywld) + +static struct BurnInputInfo SemibaseInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , DrvInputPort2 + 2, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , DrvInputPort2 + 3, "p4 coin" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Semibase) + +static struct BurnInputInfo JumppopInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Jumppop) + +static struct BurnDIPInfo TumblebDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x12, 0x01, 0xe0, 0x00, "3 Coins 1 Credit" }, + {0x12, 0x01, 0xe0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x12, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x12, 0x01, 0x1c, 0x00, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x1c, 0x10, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "2 Coins to Start, 1 to Continue" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0xc0, 0x80, "1" }, + {0x13, 0x01, 0xc0, 0x00, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x40, "4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x30, 0x10, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + {0x13, 0x01, 0x30, 0x20, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFO(Tumbleb) + +static struct BurnDIPInfo MetlsavrDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x0c, 0x00, "2" }, + {0x13, 0x01, 0x0c, 0x0c, "3" }, + {0x13, 0x01, 0x0c, 0x08, "4" }, + {0x13, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x13, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x10, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x30, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x70, 0x60, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x70, 0x50, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x70, 0x40, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Language" }, + {0x14, 0x01, 0x08, 0x08, "English" }, + {0x14, 0x01, 0x08, 0x00, "Korean" }, + + {0 , 0xfe, 0 , 4 , "Life Meter" }, + {0x14, 0x01, 0x30, 0x00, "66%" }, + {0x14, 0x01, 0x30, 0x30, "100%" }, + {0x14, 0x01, 0x30, 0x20, "133%" }, + {0x14, 0x01, 0x30, 0x10, "166%" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x14, 0x01, 0xc0, 0x40, "30 Seconds" }, + {0x14, 0x01, 0xc0, 0x80, "40 Seconds" }, + {0x14, 0x01, 0xc0, 0xc0, "60 Seconds" }, + {0x14, 0x01, 0xc0, 0x00, "80 Seconds" }, +}; + +STDDIPINFO(Metlsavr) + +static struct BurnDIPInfo SuprtrioDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x10, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x12, 0x01, 0x07, 0x06, "5 Coins 1 Credit" }, + {0x12, 0x01, 0x07, 0x05, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x07, 0x04, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x07, 0x00, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x07, 0x01, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x07, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x18, 0x00, "1" }, + {0x12, 0x01, 0x18, 0x08, "2" }, + {0x12, 0x01, 0x18, 0x10, "3" }, + {0x12, 0x01, 0x18, 0x18, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x20, 0x00, "Normal" }, + {0x12, 0x01, 0x20, 0x20, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x40, 0x00, "50000" }, + {0x12, 0x01, 0x40, 0x40, "60000" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x80, 0x00, "Off" }, + {0x12, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Suprtrio) + +static struct BurnDIPInfo HtchctchDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x06, 0x00, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Normal" }, + {0x12, 0x01, 0x06, 0x02, "Hard" }, + {0x12, 0x01, 0x06, 0x04, "Very Hard" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x12, 0x01, 0x38, 0x00, "5 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x30, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x38, 0x28, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x08, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Stage Skip" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Htchctch) + +static struct BurnDIPInfo CookbibDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x06, 0x00, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Normal" }, + {0x12, 0x01, 0x06, 0x02, "Hard" }, + {0x12, 0x01, 0x06, 0x04, "Very Hard" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x12, 0x01, 0x38, 0x00, "5 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x30, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x38, 0x28, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x08, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Winning Rounds (vs mode)"}, + {0x12, 0x01, 0x40, 0x00, "1" }, + {0x12, 0x01, 0x40, 0x40, "2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Cookbib) + +static struct BurnDIPInfo ChokchokDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Winning Rounds (vs mode)"}, + {0x11, 0x01, 0x01, 0x00, "2" }, + {0x11, 0x01, 0x01, 0x01, "3" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x11, 0x01, 0x20, 0x20, "60 Seconds" }, + {0x11, 0x01, 0x20, 0x00, "90 Seconds" }, + + {0 , 0xfe, 0 , 4 , "Starting Balls" }, + {0x11, 0x01, 0xc0, 0x00, "3" }, + {0x11, 0x01, 0xc0, 0xc0, "4" }, + {0x11, 0x01, 0xc0, 0x40, "5" }, + {0x11, 0x01, 0xc0, 0x80, "6" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x06, 0x00, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Normal" }, + {0x12, 0x01, 0x06, 0x02, "Hard" }, + {0x12, 0x01, 0x06, 0x04, "Very Hard" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x12, 0x01, 0x38, 0x00, "5 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x10, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x30, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x38, 0x28, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x08, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Chokchok) + +static struct BurnDIPInfo WlstarDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x13, 0x01, 0x10, 0x00, "1 Credit" }, + {0x13, 0x01, 0x10, 0x10, "2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0xc0, 0x00, "Easy" }, + {0x13, 0x01, 0xc0, 0xc0, "Normal" }, + {0x13, 0x01, 0xc0, 0x40, "Hard" }, + {0x13, 0x01, 0xc0, 0x80, "Hardest" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Last Inning" }, + {0x14, 0x01, 0x01, 0x00, "9" }, + {0x14, 0x01, 0x01, 0x01, "12" }, + + {0 , 0xfe, 0 , 2 , "Versus CPU Game Ends" }, + {0x14, 0x01, 0x02, 0x02, "+10" }, + {0x14, 0x01, 0x02, 0x00, "+7" }, + + {0 , 0xfe, 0 , 2 , "Versus Game" }, + {0x14, 0x01, 0x04, 0x00, "1 Credit / 2 Innings" }, + {0x14, 0x01, 0x04, 0x04, "1 Credit / 3 Innings" }, + + {0 , 0xfe, 0 , 2 , "Full 2 Players Game" }, + {0x14, 0x01, 0x08, 0x00, "4 Credits" }, + {0x14, 0x01, 0x08, 0x08, "6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x14, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x40, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Wlstar) + +static struct BurnDIPInfo Wondl96DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Field Colour" }, + {0x13, 0x01, 0x10, 0x10, "Blue" }, + {0x13, 0x01, 0x10, 0x00, "Green" }, + + {0 , 0xfe, 0 , 2 , "Versus CPU Game Ends" }, + {0x13, 0x01, 0x20, 0x20, "+10" }, + {0x13, 0x01, 0x20, 0x00, "+7" }, + + {0 , 0xfe, 0 , 2 , "Versus Game" }, + {0x13, 0x01, 0x40, 0x00, "1 Credit / 2 Innings" }, + {0x13, 0x01, 0x40, 0x40, "1 Credit / 3 Innings" }, + + {0 , 0xfe, 0 , 2 , "Full 2 Players Game" }, + {0x13, 0x01, 0x80, 0x80, "4 Credits" }, + {0x13, 0x01, 0x80, 0x00, "6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x14, 0x01, 0x0e, 0x04, "Level 1" }, + {0x14, 0x01, 0x0e, 0x08, "Level 2" }, + {0x14, 0x01, 0x0e, 0x00, "Level 3" }, + {0x14, 0x01, 0x0e, 0x0e, "Level 4" }, + {0x14, 0x01, 0x0e, 0x06, "Level 5" }, + {0x14, 0x01, 0x0e, 0x0a, "Level 6" }, + {0x14, 0x01, 0x0e, 0x02, "Level 7" }, + {0x14, 0x01, 0x0e, 0x0c, "Level 8" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x14, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x40, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, +}; + +STDDIPINFO(Wondl96) + +static struct BurnDIPInfo FncywldDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xf7, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x14, 0x01, 0xe0, 0x20, "4 Coins 1 Credit" }, + {0x14, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x14, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xe0, 0x00, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x14, 0x01, 0x04, 0x04, "English" }, + {0x14, 0x01, 0x04, 0x00, "Korean" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "2 Coins to Start, 1 to Continue" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0xc0, 0x80, "1" }, + {0x15, 0x01, 0xc0, 0x00, "2" }, + {0x15, 0x01, 0xc0, 0xc0, "3" }, + {0x15, 0x01, 0xc0, 0x40, "4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x30, 0x30, "Easy" }, + {0x15, 0x01, 0x30, 0x20, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFO(Fncywld) + +static struct BurnDIPInfo SdfightDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x0e, 0x04, "1" }, + {0x13, 0x01, 0x0e, 0x08, "2" }, + {0x13, 0x01, 0x0e, 0x00, "3" }, + {0x13, 0x01, 0x0e, 0x0e, "4" }, + {0x13, 0x01, 0x0e, 0x06, "5" }, + {0x13, 0x01, 0x0e, 0x0a, "6" }, + {0x13, 0x01, 0x0e, 0x02, "7" }, + {0x13, 0x01, 0x0e, 0x0c, "8" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x13, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x40, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Winning Rounds" }, + {0x14, 0x01, 0x08, 0x08, "2" }, + {0x14, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x14, 0x01, 0xc0, 0x40, "30" }, + {0x14, 0x01, 0xc0, 0x80, "50" }, + {0x14, 0x01, 0xc0, 0xc0, "70" }, + {0x14, 0x01, 0xc0, 0x00, "90" }, +}; + +STDDIPINFO(Sdfight) + +static struct BurnDIPInfo BcstryDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x0e, 0x04, "1" }, + {0x13, 0x01, 0x0e, 0x08, "2" }, + {0x13, 0x01, 0x0e, 0x00, "3" }, + {0x13, 0x01, 0x0e, 0x0e, "4" }, + {0x13, 0x01, 0x0e, 0x06, "5" }, + {0x13, 0x01, 0x0e, 0x0a, "6" }, + {0x13, 0x01, 0x0e, 0x02, "7" }, + {0x13, 0x01, 0x0e, 0x0c, "8" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x13, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x40, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Event Selection" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Control Type" }, + {0x14, 0x01, 0x40, 0x40, "Joysticks & Buttons" }, + {0x14, 0x01, 0x40, 0x00, "Buttons" }, + + {0 , 0xfe, 0 , 2 , "Debug Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Bcstry) + +static struct BurnDIPInfo SemibaseDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0x7f, NULL }, + {0x16, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x15, 0x01, 0x0e, 0x04, "1" }, + {0x15, 0x01, 0x0e, 0x08, "2" }, + {0x15, 0x01, 0x0e, 0x00, "3" }, + {0x15, 0x01, 0x0e, 0x0e, "4" }, + {0x15, 0x01, 0x0e, 0x06, "5" }, + {0x15, 0x01, 0x0e, 0x0a, "6" }, + {0x15, 0x01, 0x0e, 0x02, "7" }, + {0x15, 0x01, 0x0e, 0x0c, "8" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x15, 0x01, 0x70, 0x00, "5 Coins 1 Credit" }, + {0x15, 0x01, 0x70, 0x40, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "vs CPU Game Ends" }, + {0x16, 0x01, 0x20, 0x20, "+10" }, + {0x16, 0x01, 0x20, 0x00, "+7" }, + + {0 , 0xfe, 0 , 2 , "Vs Game" }, + {0x16, 0x01, 0x40, 0x40, "1 Credit / 2 Innings" }, + {0x16, 0x01, 0x40, 0x00, "1 Credit / 3 Innings" }, + + {0 , 0xfe, 0 , 2 , "Full 2 Players Game" }, + {0x16, 0x01, 0x80, 0x00, "4 Credits" }, + {0x16, 0x01, 0x80, 0x80, "6 Credits" }, +}; + +STDDIPINFO(Semibase) + +static struct BurnDIPInfo DquizgoDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x0e, 0x04, "1" }, + {0x13, 0x01, 0x0e, 0x08, "2" }, + {0x13, 0x01, 0x0e, 0x00, "3" }, + {0x13, 0x01, 0x0e, 0x0e, "4" }, + {0x13, 0x01, 0x0e, 0x06, "5" }, + {0x13, 0x01, 0x0e, 0x0a, "6" }, + {0x13, 0x01, 0x0e, 0x02, "7" }, + {0x13, 0x01, 0x0e, 0x0c, "8" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x13, 0x01, 0x70, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x40, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x20, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x60, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x70, 0x70, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x70, 0x50, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x70, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x70, 0x10, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0xc0, 0x00, "2" }, + {0x14, 0x01, 0xc0, 0xc0, "3" }, + {0x14, 0x01, 0xc0, 0x40, "4" }, + {0x14, 0x01, 0xc0, 0x80, "5" }, +}; + +STDDIPINFO(Dquizgo) + +static struct BurnDIPInfo JumppopDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x11, 0x01, 0xe0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xe0, 0x80, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x11, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x11, 0x01, 0x1c, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x1c, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x1c, 0x1c, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x02, 0x00, "Off" }, + {0x12, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Picture Viewer" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Background Type" }, + {0x12, 0x01, 0x08, 0x08, "1" }, + {0x12, 0x01, 0x08, 0x00, "2" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x30, 0x20, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x10, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0xc0, 0x80, "1" }, + {0x12, 0x01, 0xc0, 0x00, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x40, "4" }, +}; + +STDDIPINFO(Jumppop) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); +} + +static struct BurnRomInfo TumblebRomDesc[] = { + { "thumbpop.12", 0x40000, 0x0c984703, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "thumbpop.13", 0x40000, 0x864c4053, BRF_ESS | BRF_PRG }, // 1 + + { "thumbpop.19", 0x40000, 0x0795aab4, BRF_GRA }, // 2 Tiles + { "thumbpop.18", 0x40000, 0xad58df43, BRF_GRA }, // 3 + + { "map-01.rom", 0x80000, 0xe81ffa09, BRF_GRA }, // 4 Sprites + { "map-00.rom", 0x80000, 0x8c879cfe, BRF_GRA }, // 5 + + { "thumbpop.snd", 0x80000, 0xfabbf15d, BRF_SND }, // 6 Samples +}; + +STD_ROM_PICK(Tumbleb) +STD_ROM_FN(Tumbleb) + +static struct BurnRomInfo Tumbleb2RomDesc[] = { + { "thumbpop.2", 0x40000, 0x34b016e1, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "thumbpop.3", 0x40000, 0x89501c71, BRF_ESS | BRF_PRG }, // 1 + + { "thumbpop.19", 0x40000, 0x0795aab4, BRF_GRA }, // 2 Tiles + { "thumbpop.18", 0x40000, 0xad58df43, BRF_GRA }, // 3 + + { "map-01.rom", 0x80000, 0xe81ffa09, BRF_GRA }, // 4 Sprites + { "map-00.rom", 0x80000, 0x8c879cfe, BRF_GRA }, // 5 + + { "thumbpop.snd", 0x80000, 0xfabbf15d, BRF_SND }, // 6 Samples + + { "pic_16c57", 0x02d4c, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(Tumbleb2) +STD_ROM_FN(Tumbleb2) + +static struct BurnRomInfo JumpkidsRomDesc[] = { + { "23-ic29.15c", 0x40000, 0x6ba11e91, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "24-ic30.17c", 0x40000, 0x5795d98b, BRF_ESS | BRF_PRG }, // 1 + + { "22-ic19.3c", 0x08000, 0xbd619530, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "30-ic125.15j", 0x40000, 0x44b9a089, BRF_GRA }, // 3 Tiles + { "29-ic124.13j", 0x40000, 0x3f98ec69, BRF_GRA }, // 4 + + { "25-ic69.1g", 0x40000, 0x176ae857, BRF_GRA }, // 5 Sprites + { "28-ic131.1l", 0x40000, 0xed837757, BRF_GRA }, // 6 + { "26-ic70.2g", 0x40000, 0xe8b34980, BRF_GRA }, // 7 + { "27-ic100.1j", 0x40000, 0x3918dda3, BRF_GRA }, // 8 + + { "21-ic17.1c", 0x80000, 0xe5094f75, BRF_SND }, // 9 Samples + { "ic18.2c", 0x20000, 0xa63736c3, BRF_SND }, // 10 +}; + +STD_ROM_PICK(Jumpkids) +STD_ROM_FN(Jumpkids) + +static struct BurnRomInfo MetlsavrRomDesc[] = { + { "first-4.ub17", 0x40000, 0x667a494d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "first-3.ub18", 0x40000, 0x87bf4ed2, BRF_ESS | BRF_PRG }, // 1 + + { "first-2.ua7", 0x10000, 0x49505edf, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0x17aa17a9, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "first-5.rom5", 0x40000, 0xdd4af746, BRF_GRA }, // 4 Tiles + { "first-6.rom6", 0x40000, 0x808b0e0b, BRF_GRA }, // 5 + + { "first-7.uor1", 0x80000, 0xa6816747, BRF_GRA }, // 6 Sprites + { "first-8.uor2", 0x80000, 0x377020e5, BRF_GRA }, // 7 + { "first-9.uor3", 0x80000, 0xfccf1bb7, BRF_GRA }, // 8 + { "first-10.uor4", 0x80000, 0xa22b587b, BRF_GRA }, // 9 + + { "first-1.uc1", 0x40000, 0xe943dacb, BRF_SND }, // 10 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 11 +}; + +STD_ROM_PICK(Metlsavr) +STD_ROM_FN(Metlsavr) + +static struct BurnRomInfo PangpangRomDesc[] = { + { "2.bin", 0x40000, 0x45436666, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "3.bin", 0x40000, 0x2725cbe7, BRF_ESS | BRF_PRG }, // 1 + + { "11.bin", 0x40000, 0xa2b9fec8, BRF_GRA }, // 2 Tiles + { "10.bin", 0x40000, 0x4f59d7b9, BRF_GRA }, // 3 + { "6.bin", 0x40000, 0x1ebbc4f1, BRF_GRA }, // 4 + { "7.bin", 0x40000, 0xcd544173, BRF_GRA }, // 5 + + { "8.bin", 0x40000, 0xea0fa1e0, BRF_GRA }, // 6 Sprites + { "9.bin", 0x40000, 0x1da5fe49, BRF_GRA }, // 7 + { "4.bin", 0x40000, 0x4f282eb1, BRF_GRA }, // 8 + { "5.bin", 0x40000, 0x00694df9, BRF_GRA }, // 9 + + { "1.bin", 0x80000, 0xe722bb02, BRF_SND }, // 10 Samples + + { "pic_16c57", 0x02d4c, 0x1ca515b4, BRF_OPT }, +}; + +STD_ROM_PICK(Pangpang) +STD_ROM_FN(Pangpang) + +static struct BurnRomInfo SuprtrioRomDesc[] = { + { "rom2", 0x40000, 0x4102e59d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "rom1", 0x40000, 0xcc3a83c3, BRF_ESS | BRF_PRG }, // 1 + + { "rom4l", 0x10000, 0x466aa96d, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "rom4", 0x80000, 0xcd2dfae4, BRF_GRA }, // 3 Tiles + { "rom5", 0x80000, 0x4e64da64, BRF_GRA }, // 4 + + { "rom9l", 0x40000, 0xcc45f437, BRF_GRA }, // 5 Sprites + { "rom8l", 0x40000, 0x9bc90169, BRF_GRA }, // 6 + { "rom7l", 0x40000, 0xbfc7c756, BRF_GRA }, // 7 + { "rom6l", 0x40000, 0xbb3499af, BRF_GRA }, // 8 + + { "rom3h", 0x80000, 0x34ea7ec9, BRF_SND }, // 9 Samples + { "rom3l", 0x20000, 0x1b73233b, BRF_SND }, // 10 +}; + +STD_ROM_PICK(Suprtrio) +STD_ROM_FN(Suprtrio) + +static struct BurnRomInfo HtchctchRomDesc[] = { + { "p04.b17", 0x20000, 0x6991483a, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "p03.b16", 0x20000, 0xeff14c40, BRF_ESS | BRF_PRG }, // 1 + + { "p02.b5", 0x10000, 0xc5a03186, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0x5b27adb6, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "p06srom5.bin", 0x40000, 0x3d2cbb0d, BRF_GRA }, // 4 Tiles + { "p07srom6.bin", 0x40000, 0x0207949c, BRF_GRA }, // 5 + + { "p08uor1.bin", 0x20000, 0x6811e7b6, BRF_GRA }, // 6 Sprites + { "p09uor2.bin", 0x20000, 0x1c6549cf, BRF_GRA }, // 7 + { "p10uor3.bin", 0x20000, 0x6462e6e0, BRF_GRA }, // 8 + { "p11uor4.bin", 0x20000, 0x9c511d98, BRF_GRA }, // 9 + + { "p01.c1", 0x20000, 0x18c06829, BRF_SND }, // 10 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 11 +}; + +STD_ROM_PICK(Htchctch) +STD_ROM_FN(Htchctch) + +static struct BurnRomInfo CookbibRomDesc[] = { + { "prg2.ub17", 0x20000, 0x2664a335, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "prg1.ub16", 0x20000, 0xcda6335f, BRF_ESS | BRF_PRG }, // 1 + + { "prg-s.ub5", 0x10000, 0x547d6ea3, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0xa77d13f4, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "srom5.bin", 0x40000, 0x73a46e43, BRF_GRA }, // 4 Tiles + { "srom6.bin", 0x40000, 0xade2dbec, BRF_GRA }, // 5 + + { "uor1.bin", 0x20000, 0xa7d91f23, BRF_GRA }, // 6 Sprites + { "uor2.bin", 0x20000, 0x9aacbec2, BRF_GRA }, // 7 + { "uor3.bin", 0x20000, 0x3fee0c3c, BRF_GRA }, // 8 + { "uor4.bin", 0x20000, 0xbed9ed2d, BRF_GRA }, // 9 + + { "sound.uc1", 0x20000, 0x545e19b6, BRF_SND }, // 10 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 11 +}; + +STD_ROM_PICK(Cookbib) +STD_ROM_FN(Cookbib) + +static struct BurnRomInfo ChokchokRomDesc[] = { + { "ub17.bin", 0x40000, 0xecdb45ca, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ub18.bin", 0x40000, 0xb183852a, BRF_ESS | BRF_PRG }, // 1 + + { "ub5.bin", 0x10000, 0x30c2171d, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0x0bd39834, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "srom5.bin", 0x80000, 0x836608b8, BRF_GRA }, // 4 Tiles + { "srom6.bin", 0x80000, 0x31d5715d, BRF_GRA }, // 5 + + { "uor1.bin", 0x80000, 0xded6642a, BRF_GRA }, // 6 Sprites + { "uor2.bin", 0x80000, 0x493f9516, BRF_GRA }, // 7 + { "uor3.bin", 0x80000, 0xe2dc3e12, BRF_GRA }, // 8 + { "uor4.bin", 0x80000, 0x6f377530, BRF_GRA }, // 9 + + { "uc1.bin", 0x40000, 0xf3f57abd, BRF_SND }, // 10 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 11 +}; + +STD_ROM_PICK(Chokchok) +STD_ROM_FN(Chokchok) + +static struct BurnRomInfo WlstarRomDesc[] = { + { "n-4.u817", 0x40000, 0xfc3e829b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "n-3.u818", 0x40000, 0xf01bc623, BRF_ESS | BRF_PRG }, // 1 + + { "ua7", 0x10000, 0x90cafa5f, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + +#if !defined (ROM_VERIFY) + { "protdata.bin", 0x00200, 0xb7ffde5b, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data +#else + { "87c52.mcu", 0x02000, 0xab5e2a7e, BRF_ESS | BRF_PRG }, // 3 MCU Program Code +#endif + + { "5.srom5", 0x80000, 0xf7f8c859, BRF_GRA }, // 4 Tiles + { "6.srom6", 0x80000, 0x34ace2a8, BRF_GRA }, // 5 + + { "7.udr1", 0x80000, 0x6e47c31d, BRF_GRA }, // 6 Sprites + { "8.udr2", 0x80000, 0x09c5d57c, BRF_GRA }, // 7 + { "9.udr3", 0x80000, 0x3ec064f0, BRF_GRA }, // 8 + { "10.udr4", 0x80000, 0xb4693cdd, BRF_GRA }, // 9 + + { "ua1", 0x40000, 0xde217d30, BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(Wlstar) +STD_ROM_FN(Wlstar) + +static struct BurnRomInfo Wondl96RomDesc[] = { + { "ub17.bin", 0x40000, 0x41d8e03c, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ub18.bin", 0x40000, 0x0e4963af, BRF_ESS | BRF_PRG }, // 1 + + { "ub5.bin", 0x10000, 0xd99d19c4, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + +#if !defined (ROM_VERIFY) + { "protdata.bin", 0x00200, 0xd7578b1e, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data +#else + { "87c52.mcu", 0x02000, 0x6f4c659a, BRF_ESS | BRF_PRG }, // 3 MCU Program Code +#endif + + { "srom5.bin", 0x80000, 0xdb8010c3, BRF_GRA }, // 4 Tiles + { "srom6.bin", 0x80000, 0x2f364e54, BRF_GRA }, // 5 + + { "uor1.bin", 0x80000, 0xe1e9eebb, BRF_GRA }, // 6 Sprites + { "uor2.bin", 0x80000, 0xddebfe83, BRF_GRA }, // 7 + { "uor3.bin", 0x80000, 0x7efe4d67, BRF_GRA }, // 8 + { "uor4.bin", 0x80000, 0x7b1596d1, BRF_GRA }, // 9 + + { "uc1.bin", 0x40000, 0x0e7913e6, BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(Wondl96) +STD_ROM_FN(Wondl96) + +static struct BurnRomInfo FncywldRomDesc[] = { + { "01_fw02.bin", 0x80000, 0xecb978c1, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "02_fw03.bin", 0x80000, 0x2d233b42, BRF_ESS | BRF_PRG }, // 1 + + { "08_fw09.bin", 0x40000, 0xa4a00de9, BRF_GRA }, // 2 Tiles + { "07_fw08.bin", 0x40000, 0xb48cd1d4, BRF_GRA }, // 3 + { "10_fw11.bin", 0x40000, 0xf21bab48, BRF_GRA }, // 4 + { "09_fw10.bin", 0x40000, 0x6aea8e0f, BRF_GRA }, // 5 + + { "05_fw06.bin", 0x40000, 0xe141ecdc, BRF_GRA }, // 6 Sprites + { "06_fw07.bin", 0x40000, 0x0058a812, BRF_GRA }, // 7 + { "03_fw04.bin", 0x40000, 0x6ad38c14, BRF_GRA }, // 8 + { "04_fw05.bin", 0x40000, 0xb8d079a6, BRF_GRA }, // 9 + + { "00_fw01.bin", 0x40000, 0xb395fe01, BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(Fncywld) +STD_ROM_FN(Fncywld) + +static struct BurnRomInfo SdfightRomDesc[] = { + { "u817", 0x80000, 0x9f284f4d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "u818", 0x80000, 0xa60e5b22, BRF_ESS | BRF_PRG }, // 1 + + { "ua7", 0x10000, 0xc3d36da4, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0xefb8b822, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "9.ug11", 0x80000, 0xbf809ccd, BRF_GRA }, // 4 Tiles + { "10.ug12", 0x80000, 0xa5a3bfa2, BRF_GRA }, // 5 + { "15.ui11", 0x80000, 0x3bc8aa6d, BRF_GRA }, // 6 + { "16.ui12", 0x80000, 0x71e6b78d, BRF_GRA }, // 7 + + { "11.uk2", 0x80000, 0xd006fadc, BRF_GRA }, // 8 Sprites + { "12.uk3", 0x80000, 0x2a2f4153, BRF_GRA }, // 9 + { "5.uj2", 0x80000, 0xf1246cbf, BRF_GRA }, // 10 + { "6.uj3", 0x80000, 0xd346878c, BRF_GRA }, // 11 + { "13.uk4", 0x80000, 0x9bc40774, BRF_GRA }, // 12 + { "14.uk5", 0x80000, 0xa1e61674, BRF_GRA }, // 13 + { "7.uj4", 0x80000, 0xdbdece8a, BRF_GRA }, // 14 + { "8.uj5", 0x80000, 0x60be7dd1, BRF_GRA }, // 15 + + { "uc1", 0x40000, 0x535cae2c, BRF_SND }, // 16 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 17 +}; + +STD_ROM_PICK(Sdfight) +STD_ROM_FN(Sdfight) + +static struct BurnRomInfo BcstryRomDesc[] = { + { "bcstry_u.62", 0x40000, 0x7f7aa244, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "bcstry_u.35", 0x40000, 0xd25b80a4, BRF_ESS | BRF_PRG }, // 1 + + { "bcstry_u.21", 0x10000, 0x3ba072d4, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0xe84e328c, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "bcstry_u.109", 0x80000, 0xeb04d37a, BRF_GRA }, // 4 Tiles + { "bcstry_u.113", 0x80000, 0x746ecdd7, BRF_GRA }, // 5 + { "bcstry_u.110", 0x80000, 0x1bfe65c3, BRF_GRA }, // 6 + { "bcstry_u.111", 0x80000, 0xc8bf3a3c, BRF_GRA }, // 7 + + { "bcstry_u.100", 0x80000, 0x8c11cbed, BRF_GRA }, // 8 Sprites + { "bcstry_u.106", 0x80000, 0x5219bcbf, BRF_GRA }, // 9 + { "bcstry_u.99", 0x80000, 0xcdb1af87, BRF_GRA }, // 10 + { "bcstry_u.105", 0x80000, 0x8166b596, BRF_GRA }, // 11 + { "bcstry_u.104", 0x80000, 0x377c0c71, BRF_GRA }, // 12 + { "bcstry_u.108", 0x80000, 0x442307ed, BRF_GRA }, // 13 + { "bcstry_u.102", 0x80000, 0x71b40ece, BRF_GRA }, // 14 + { "bcstry_u.107", 0x80000, 0xab3c923a, BRF_GRA }, // 15 + + { "bcstry_u.64", 0x40000, 0x23f0e0fe, BRF_SND }, // 16 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 17 +}; + +STD_ROM_PICK(Bcstry) +STD_ROM_FN(Bcstry) + +static struct BurnRomInfo BcstryaRomDesc[] = { + { "prg2.ic62", 0x40000, 0xf54c0a96, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "prg1.ic35", 0x40000, 0x2c55100a, BRF_ESS | BRF_PRG }, // 1 + + { "bcstry_u.21", 0x10000, 0x3ba072d4, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0xe84e328c, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "bcstry_u.109", 0x80000, 0xeb04d37a, BRF_GRA }, // 4 Tiles + { "bcstry_u.113", 0x80000, 0x746ecdd7, BRF_GRA }, // 5 + { "bcstry_u.110", 0x80000, 0x1bfe65c3, BRF_GRA }, // 6 + { "bcstry_u.111", 0x80000, 0xc8bf3a3c, BRF_GRA }, // 7 + + { "bcstry_u.100", 0x80000, 0x8c11cbed, BRF_GRA }, // 8 Sprites + { "bcstry_u.106", 0x80000, 0x5219bcbf, BRF_GRA }, // 9 + { "bcstry_u.99", 0x80000, 0xcdb1af87, BRF_GRA }, // 10 + { "bcstry_u.105", 0x80000, 0x8166b596, BRF_GRA }, // 11 + { "bcstry_u.104", 0x80000, 0x377c0c71, BRF_GRA }, // 12 + { "bcstry_u.108", 0x80000, 0x442307ed, BRF_GRA }, // 13 + { "bcstry_u.102", 0x80000, 0x71b40ece, BRF_GRA }, // 14 + { "bcstry_u.107", 0x80000, 0xab3c923a, BRF_GRA }, // 15 + + { "bcstry_u.64", 0x40000, 0x23f0e0fe, BRF_SND }, // 16 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 17 +}; + +STD_ROM_PICK(Bcstrya) +STD_ROM_FN(Bcstrya) + +static struct BurnRomInfo SemibaseRomDesc[] = { + { "ic62.68k", 0x40000, 0x85ea81c3, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ic35.68k", 0x40000, 0xd2249605, BRF_ESS | BRF_PRG }, // 1 + + { "ic21.z80", 0x10000, 0xd95c64d0, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0xecbf2163, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "ic109.gfx", 0x80000, 0x2b86e983, BRF_GRA }, // 4 Tiles + { "ic113.gfx", 0x80000, 0xe39b6610, BRF_GRA }, // 5 + { "ic110.gfx", 0x80000, 0xbba4a015, BRF_GRA }, // 6 + { "ic111.gfx", 0x80000, 0x61133b63, BRF_GRA }, // 7 + + { "ic100.gfx", 0x80000, 0x01c3d12a, BRF_GRA }, // 8 Sprites + { "ic106.gfx", 0x80000, 0xdb282ac2, BRF_GRA }, // 9 + { "ic99.gfx", 0x80000, 0x349df821, BRF_GRA }, // 10 + { "ic105.gfx", 0x80000, 0xf7caa81c, BRF_GRA }, // 11 + { "ic104.gfx", 0x80000, 0x51a5d38a, BRF_GRA }, // 12 + { "ic108.gfx", 0x80000, 0xb253d60e, BRF_GRA }, // 13 + { "ic102.gfx", 0x80000, 0x3caefe97, BRF_GRA }, // 14 + { "ic107.gfx", 0x80000, 0x68109898, BRF_GRA }, // 15 + + { "ic64.snd", 0x40000, 0x8a60649c, BRF_SND }, // 16 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 17 +}; + +STD_ROM_PICK(Semibase) +STD_ROM_FN(Semibase) + +static struct BurnRomInfo DquizgoRomDesc[] = { + { "ub17", 0x80000, 0x0b96ab14, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ub18", 0x80000, 0x07f869f2, BRF_ESS | BRF_PRG }, // 1 + + { "ub5", 0x10000, 0xe40481da, BRF_ESS | BRF_PRG }, // 2 Z80 Program Code + + { "protdata.bin", 0x00200, 0x6064b9e0, BRF_ESS | BRF_PRG }, // 3 Shared RAM Data + + { "srom5", 0x80000, 0xf1cdd21d, BRF_GRA }, // 4 Tiles + { "srom6", 0x80000, 0xf848939e, BRF_GRA }, // 5 + + { "uor1", 0x80000, 0xb4912bf6, BRF_GRA }, // 6 Sprites + { "uor2", 0x80000, 0xb011cf93, BRF_GRA }, // 7 + { "uor3", 0x80000, 0xd96c3582, BRF_GRA }, // 8 + { "uor4", 0x80000, 0x77ff23eb, BRF_GRA }, // 9 + + { "uc1", 0x40000, 0xd0f4c4ba, BRF_SND }, // 10 Samples + + { "87c52.mcu", 0x10000, 0x00000000, BRF_NODUMP }, // 11 +}; + +STD_ROM_PICK(Dquizgo) +STD_ROM_FN(Dquizgo) + +static struct BurnRomInfo JumppopRomDesc[] = { + { "68k_prg.bin", 0x080000, 0x123536b9, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + + { "z80_prg.bin", 0x040000, 0xa88d4424, BRF_ESS | BRF_PRG }, // 1 Z80 Program Code + + { "bg0.bin", 0x100000, 0x35a1363d, BRF_GRA }, // 2 Tiles + { "bg1.bin", 0x100000, 0x5b37f943, BRF_GRA }, // 3 + + { "sp0.bin", 0x100000, 0x7c5d0633, BRF_GRA }, // 4 Sprites + { "sp1.bin", 0x100000, 0x7eae782e, BRF_GRA }, // 5 + + { "samples.bin", 0x040000, 0x066f30a7, BRF_SND }, // 6 Samples +}; + +STD_ROM_PICK(Jumppop) +STD_ROM_FN(Jumppop) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x100000; + if (DrvHasZ80)DrvZ80Rom = Next; Next += 0x010000; + if (DrvHasProt) DrvProtData = Next; Next += 0x000200; + MSM6295ROM = Next; Next += 0x040000; + DrvMSM6295ROMSrc = Next; Next += 0x100000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x010800; + if (DrvHasZ80)DrvZ80Ram = Next; Next += 0x000800; + DrvSpriteRam = Next; Next += DrvSpriteRamSize; + DrvPf1Ram = Next; Next += 0x002000; + DrvPf2Ram = Next; Next += 0x002000; + DrvPaletteRam = Next; Next += 0x001000; + DrvControl = (UINT16*)Next; Next += 8 * sizeof(UINT16); + + RamEnd = Next; + + DrvChars = Next; Next += DrvNumChars * 8 * 8; + DrvTiles = Next; Next += DrvNumTiles * 16 * 16; + DrvSprites = Next; Next += DrvNumSprites * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 JumppopMemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x080000; + DrvZ80Rom = Next; Next += 0x040000; + MSM6295ROM = Next; Next += 0x040000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x0c0000; + DrvZ80Ram = Next; Next += 0x000800; + DrvSpriteRam = Next; Next += DrvSpriteRamSize; + DrvPf1Ram = Next; Next += 0x004000; + DrvPf2Ram = Next; Next += 0x004000; + DrvPaletteRam = Next; Next += 0x000800; + DrvControl = (UINT16*)Next; Next += 8 * sizeof(UINT16); + + RamEnd = Next; + + DrvChars = Next; Next += DrvNumChars * 8 * 8; + DrvTiles = Next; Next += DrvNumTiles * 16 * 16; + DrvSprites = Next; Next += DrvNumSprites * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + if (DrvHasProt == 1) memcpy(Drv68KRam + 0x000, DrvProtData, 0x200); + if (DrvHasProt == 2) memcpy(Drv68KRam + 0x200, DrvProtData, 0x200); + + SekOpen(0); + SekReset(); + SekClose(); + + if (DrvHasZ80) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + if (DrvHasYM2151) BurnYM2151Reset(); + if (DrvHasYM3812) BurnYM3812Reset(); + + MSM6295Reset(0); + + DrvVBlank = 0; + DrvOkiBank = 0; + DrvTileBank = 0; + DrvSoundLatch = 0; + Tumbleb2MusicCommand = 0; + Tumbleb2MusicBank = 0; + Tumbleb2MusicIsPlaying = 0; + memset(DrvControl, 0, 8); + + return 0; +} + +static const INT32 Tumbleb2SoundLookup[256] = { + /*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ + 0x00, -2, 0x00, 0x00, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0x00, -2, /* 0 */ + -2, 0x00, -2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 2 */ + 0x19, 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 3 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* f */ +}; + +static void Tumbleb2PlayMusic() +{ + INT32 Status = MSM6295ReadStatus(0); + + if (Tumbleb2MusicIsPlaying) + { + if ((Status & 0x08) == 0) { + MSM6295Command(0, 0x80 | Tumbleb2MusicCommand); + MSM6295Command(0, 0x00 | 0x82); + } + } +} + +static void Tumbleb2SetMusicBank(INT32 Bank) +{ + memcpy(MSM6295ROM + 0x38000, DrvMSM6295ROMSrc + 0x38000 + (Bank * 0x8000), 0x8000); +} + +static void Tumbleb2PlaySound(UINT16 data) +{ + INT32 Status = MSM6295ReadStatus(0); + + if ((Status & 0x01) == 0) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x00 | 0x12); + } else { + if ((Status & 0x02) == 0) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x00 | 0x22); + } else { + if ((Status & 0x04) == 0) { + MSM6295Command(0, 0x80 | data); + MSM6295Command(0, 0x00 | 0x42); + } + } + } +} + +static void Tumbleb2ProcessMusicCommand(UINT16 data) +{ + INT32 Status = MSM6295ReadStatus(0); + + if (data == 1) { + if ((Status & 0x08) == 0x08) { + MSM6295Command(0, 0x40); + Tumbleb2MusicIsPlaying = 0; + } + } else { + if (Tumbleb2MusicIsPlaying != data) { + Tumbleb2MusicIsPlaying = data; + + MSM6295Command(0, 0x40); + + switch (data) { + case 0x04: // map screen + Tumbleb2MusicBank = 1; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x05: // america + Tumbleb2MusicBank = 6; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x06: // asia + Tumbleb2MusicBank = 2; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x07: // africa/egypt -- don't seem to have a tune for this one + Tumbleb2MusicBank = 4; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x08: // antartica + Tumbleb2MusicBank = 3; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x09: // brazil / south america + Tumbleb2MusicBank = 4; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x0a: // japan -- don't seem to have a tune + Tumbleb2MusicBank = 2; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x0b: // australia + Tumbleb2MusicBank = 5; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x0c: // france/europe + Tumbleb2MusicBank = 6; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x0d: // how to play + Tumbleb2MusicBank = 7; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x0f: // stage clear + Tumbleb2MusicBank = 0; + Tumbleb2MusicCommand = 0x33; + break; + + case 0x10: // boss stage + Tumbleb2MusicBank = 8; + Tumbleb2MusicCommand = 0x38; + break; + + case 0x12: // world clear + Tumbleb2MusicBank = 0; + Tumbleb2MusicCommand = 0x34; + break; + + default: // anything else.. + Tumbleb2MusicBank = 8; + Tumbleb2MusicCommand = 0x38; + break; + } + + Tumbleb2SetMusicBank(Tumbleb2MusicBank); + Tumbleb2PlayMusic(); + } + } +} + +static void Tumbleb2SoundMCUCommand(UINT16 data) +{ + INT32 Sound = Tumbleb2SoundLookup[data & 0xff]; + + if (Sound == 0) { + + } else { + if (Sound == -2) { + Tumbleb2ProcessMusicCommand(data); + } else { + Tumbleb2PlaySound(Sound); + } + } +} + +UINT8 __fastcall Tumbleb68KReadByte(UINT32 a) +{ + switch (a) { + case 0x100001: { + return ~0; + } + + case 0x180002: { + return DrvDip[1]; + } + + case 0x180003: { + return DrvDip[0]; + } + + case 0x180009: { + if (Semibase) return 0xff - DrvInput[2]; + if (DrvVBlank) { + if (Wondl96) { + return 0xf3 - DrvInput[2]; + } else { + return 0xf7 - DrvInput[2]; + } + } + if (Wondl96) return 0xfb - DrvInput[2]; + return 0xff - DrvInput[2]; + } + + case 0x18000a: { + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Tumbleb68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x100000: { + if (Tumbleb2) { + Tumbleb2SoundMCUCommand(d); + return; + } else { + MSM6295Command(0, d); + return; + } + } + + case 0x100001: { + if (SemicomSoundCommand) DrvSoundLatch = d; + return; + } + + case 0x100002: { + if (Chokchok) DrvTileBank = (d << 8) << 1; + if (Bcstry) DrvTileBank = d << 8; + return; + } + + case 0x100003: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Tumbleb68KReadWord(UINT32 a) +{ + switch (a) { + case 0x100004: { + return rand() % 0x10000; + } + + case 0x180000: { + return ((0xff - DrvInput[1]) << 8) | (0xff - DrvInput[0]); + } + + case 0x180002: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + case 0x180004: { + return -0; + } + + case 0x180006: { + return -0; + } + + case 0x180008: { + if (Bcstry && (SekGetPC(0) == 0x560)) { + return 0x1a0; + } else { + if (Semibase) return 0xffff - DrvInput[2]; + if (DrvVBlank) { + if (Wondl96) { + return 0xfff3 - DrvInput[2]; + } else { + return 0xfff7 - DrvInput[2]; + } + } + } + if (Wondl96) return 0xfff3 - DrvInput[2]; + return 0xffff - DrvInput[2]; + } + + case 0x18000a: { + return 0; + } + + case 0x18000c: { + return 0; + } + + case 0x18000e: { + return -0; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Tumbleb68KWriteWord(UINT32 a, UINT16 d) +{ +#if 1 && defined FBA_DEBUG + if (a >= 0x160800 && a <= 0x160807) return; + if (a >= 0x198000 && a <= 0x1a8015) return; + if (a >= 0x321000 && a <= 0x321fff) return; + if (a >= 0x323000 && a <= 0x331fff) return; + if (a >= 0x340000 && a <= 0x3401ff) return; + if (a >= 0x340400 && a <= 0x34047f) return; + if (a >= 0x342000 && a <= 0x3421ff) return; + if (a >= 0x342400 && a <= 0x34247f) return; +#endif + + if (a >= 0x300000 && a <= 0x30000f) { + DrvControl[(a - 0x300000) >> 1] = d; + return; + } + + switch (a) { + case 0x100000: { + if (Tumbleb2) { + Tumbleb2SoundMCUCommand(d); + return; + } else { + if (Jumpkids) { + DrvSoundLatch = d & 0xff; + ZetOpen(0); + ZetRaiseIrq(0); + ZetClose(); + return; + } else { + if (SemicomSoundCommand) { + if (d & 0xff) DrvSoundLatch = d & 0xff; + return; + } else { + MSM6295Command(0, d & 0xff); + return; + } + } + } + } + + case 0x100002: { + if (Wlstar) DrvTileBank = d & 0x4000; + return; + } + + case 0x18000c: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT16 __fastcall Suprtrio68KReadWord(UINT32 a) +{ + switch (a) { + case 0xe00000: { + return ((0xff - DrvInput[1]) << 8) | (0xff - DrvInput[0]); + } + + case 0xe40000: { + return 0xffff - DrvInput[2]; + } + + case 0xe80002: { + return 0xff00 | DrvDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Suprtrio68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0xa00000 && a <= 0xa0000f) { + DrvControl[(a - 0xa00000) >> 1] = d; + return; + } + + switch (a) { + case 0xe00000: { + DrvTileBank = d << 14; + return; + } + + case 0xec0000: { + if (SemicomSoundCommand) { + if (d & 0xff) DrvSoundLatch = d & 0xff; + } + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Fncywld68KReadByte(UINT32 a) +{ + switch (a) { + case 0x100003: { + return 0; + } + + case 0x100005: { + return MSM6295ReadStatus(0); + } + + case 0x180002: { + return DrvDip[1]; + } + + case 0x180005: { + return -0; + } + + case 0x180009: { + if (DrvVBlank) return 0xf7 - DrvInput[2]; + return 0xff - DrvInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Fncywld68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x100001: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x100003: { + BurnYM2151WriteRegister(d); + return; + } + + case 0x100005: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Fncywld68KReadWord(UINT32 a) +{ + switch (a) { + case 0x180000: { + return ((0xff - DrvInput[1]) << 8) | (0xff - DrvInput[0]); + } + + case 0x180002: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + case 0x180004: { + return -0; + } + + case 0x180006: { + return -0; + } + + case 0x180008: { + if (DrvVBlank) return 0xfff7 - DrvInput[2]; + return 0xffff - DrvInput[2]; + } + + case 0x18000a: { + return 0; + } + + case 0x18000c: { + return 0; + } + + case 0x18000e: { + return -0; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Fncywld68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x160800 && a <= 0x160807) return; + + if (a >= 0x300000 && a <= 0x30000f) { + DrvControl[(a - 0x300000) >> 1] = d; + return; + } + + switch (a) { + case 0x100000: { + BurnYM2151SelectRegister(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT16 __fastcall Jumppop68KReadWord(UINT32 a) +{ + switch (a) { + case 0x180002: { + return ((0xff - DrvInput[1]) << 8) | (0xff - DrvInput[0]); + } + + case 0x180004: { + return 0xffff - DrvInput[2]; + } + + case 0x180006: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Jumppop68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x380000 && a <= 0x38000f) { + DrvControl[(a - 0x380000) >> 1] = d; + return; + } + + switch (a) { + case 0x180000: { + // NOP + return; + } + + case 0x18000c: { + DrvSoundLatch = d & 0xff; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0x180008: + case 0x18000a: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall JumpkidsZ80Read(UINT16 a) +{ + switch (a) { + case 0x9800: { + return MSM6295ReadStatus(0); + } + + case 0xa000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall JumpkidsZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + DrvOkiBank = d & 3; + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + (DrvOkiBank * 0x20000), 0x20000); + return; + } + + case 0x9800: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall SemicomZ80Read(UINT16 a) +{ + switch (a) { + case 0xf001: { + return BurnYM2151ReadStatus(); + } + + case 0xf002: { + return MSM6295ReadStatus(0); + } + + case 0xf008: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall SemicomZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xf000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xf001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xf002: { + MSM6295Command(0, d); + return; + } + + case 0xf006: { + return; + } + + case 0xf00e: { + DrvOkiBank = d; + memcpy(MSM6295ROM + 0x30000, DrvMSM6295ROMSrc + 0x30000 + (DrvOkiBank * 0x10000), 0x10000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall JumppopZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + return MSM6295ReadStatus(0); + } + + case 0x03: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + case 0x06: { + // NOP + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read -> %02X\n"), a); + } + } + + return 0; +} + +void __fastcall JumppopZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + BurnYM3812Write(0, d); + return; + } + + case 0x01: { + BurnYM3812Write(1, d); + return; + } + + case 0x02: { + MSM6295Command(0, d); + return; + } + + case 0x04: { + // NOP + return; + } + + case 0x05: { + DrvZ80Bank = d; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + (DrvZ80Bank * 0x4000)); + return; + } + + case 0x06: { + // NOP + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write -> %02X, %02x\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0x200008, 0x200000, 8, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 SpritePlaneOffsets[4] = { 0x400008, 0x400000, 8, 0 }; +static INT32 Sprite2PlaneOffsets[4] = { 0x800008, 0x800000, 8, 0 }; +static INT32 Sprite3PlaneOffsets[4] = { 0x1000008, 0x1000000, 8, 0 }; +static INT32 SpriteXOffsets[16] = { 256, 257, 258, 259, 260, 261, 262, 263, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; +static INT32 SuprtrioPlaneOffsets[4] = { 0x400000, 0, 0x600000, 0x200000 }; +static INT32 SuprtrioXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SuprtrioYOffsets[16] = { 8, 0, 16, 24, 40, 32, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 JpCharPlaneOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 JpCharXOffsets[8] = { 0x800000, 0x800008, 0, 8, 0x800010, 0x800018, 16, 24 }; +static INT32 JpCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 JpTilePlaneOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 JpTileXOffsets[16] = { 0x800000, 0x800008, 0, 8, 0x800010, 0x800018, 16, 24, 0x800100, 0x800108, 256, 264, 0x800110, 0x800118, 272, 280 }; +static INT32 JpTileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; + +static void TumblebTilesRearrange() +{ + UINT8 *rom = DrvTempRom; + INT32 len = DrvNumTiles * 128; + INT32 i; + + /* gfx data is in the wrong order */ + for (i = 0;i < len;i++) + { + if ((i & 0x20) == 0) + { + INT32 t = rom[i]; rom[i] = rom[i + 0x20]; rom[i + 0x20] = t; + } + } + /* low/high half are also swapped */ + for (i = 0;i < len/2;i++) + { + INT32 t = rom[i]; rom[i] = rom[i + len/2]; rom[i + len/2] = t; + } +} + +static INT32 TumblebLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 3, 2); if (nRet != 0) return 1; + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, CharPlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 5, 1); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 6, 1); if (nRet != 0) return 1; + if (Tumbleb2) nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x80000, 6, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 JumpkidsLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 4, 2); if (nRet != 0) return 1; + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, CharPlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 8, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 MetlsavrLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(DrvProtData, 3, 1); if (nRet) return 1; + BurnByteswap(DrvProtData, 0x200); + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 2); if (nRet != 0) return 1; + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, CharPlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 9, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 PangpangLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 5, 2); if (nRet != 0) return 1; + UINT8 *pTemp = (UINT8*)BurnMalloc(0x100000); + memcpy(pTemp, DrvTempRom, 0x100000); + memset(DrvTempRom, 0, 0x100000); + memcpy(DrvTempRom + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(DrvTempRom + 0x080000, pTemp + 0x040000, 0x40000); + memcpy(DrvTempRom + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(DrvTempRom + 0x0c0000, pTemp + 0x0c0000, 0x40000); + BurnFree(pTemp); + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, SpritePlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 9, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 10, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + return 0; +} + +static void SuprtrioDecrypt68KRom() +{ + UINT16 *Rom = (UINT16*)Drv68KRom; + UINT16 *pTemp = (UINT16*)BurnMalloc(0x80000); + INT32 i; + + memcpy(pTemp, Rom, 0x80000); + for (i = 0; i < 0x40000; i++) { + INT32 j = i ^ 0x06; + if ((i & 1) == 0) j ^= 0x02; + if ((i & 3) == 0) j ^= 0x08; + Rom[i] = pTemp[j]; + } + BurnFree(pTemp); +} + +static void SuprtrioDecryptTiles() +{ + UINT16 *Rom = (UINT16*)DrvTempRom; + UINT16 *pTemp = (UINT16*)BurnMalloc(0x100000); + INT32 i; + + memcpy(pTemp, Rom, 0x100000); + for (i = 0; i < 0x80000; i++) { + INT32 j = i ^ 0x02; + if (i & 1) j ^= 0x04; + Rom[i] = pTemp[j]; + } + BurnFree(pTemp); +} + +static INT32 SuprtrioLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + SuprtrioDecrypt68KRom(); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 4, 1); if (nRet != 0) return 1; + UINT8 *pTemp = (UINT8*)BurnMalloc(0x100000); + memcpy(pTemp, DrvTempRom, 0x100000); + memset(DrvTempRom, 0, 0x100000); + memcpy(DrvTempRom + 0x000000, pTemp + 0x000000, 0x20000); + memcpy(DrvTempRom + 0x040000, pTemp + 0x020000, 0x20000); + memcpy(DrvTempRom + 0x020000, pTemp + 0x040000, 0x20000); + memcpy(DrvTempRom + 0x060000, pTemp + 0x060000, 0x20000); + memcpy(DrvTempRom + 0x080000, pTemp + 0x080000, 0x20000); + memcpy(DrvTempRom + 0x0c0000, pTemp + 0x0a0000, 0x20000); + memcpy(DrvTempRom + 0x0a0000, pTemp + 0x0c0000, 0x20000); + memcpy(DrvTempRom + 0x0e0000, pTemp + 0x0e0000, 0x20000); + BurnFree(pTemp); + SuprtrioDecryptTiles(); + GfxDecode(DrvNumTiles, 4, 16, 16, SuprtrioPlaneOffsets, SuprtrioXOffsets, SuprtrioYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 8, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x80000, 10, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 HtchctchLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(DrvProtData, 3, 1); if (nRet) return 1; + BurnByteswap(DrvProtData, 0x200); + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 2); if (nRet != 0) return 1; + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, CharPlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040001, 9, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, CharPlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 ChokchokLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(DrvProtData, 3, 1); if (nRet) return 1; + BurnByteswap(DrvProtData, 0x200); + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 2); if (nRet != 0) return 1; + UINT8 *pTemp = (UINT8*)BurnMalloc(0x100000); + memcpy(pTemp, DrvTempRom, 0x100000); + memset(DrvTempRom, 0, 0x200000); + memcpy(DrvTempRom + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(DrvTempRom + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(DrvTempRom + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(DrvTempRom + 0x140000, pTemp + 0x0c0000, 0x40000); + BurnFree(pTemp); + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, Sprite2PlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 9, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 FncywldLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 5, 2); if (nRet != 0) return 1; + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, SpritePlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080001, 9, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 SdfightLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(DrvTempRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 1, 2); if (nRet != 0) return 1; + memcpy(Drv68KRom + 0xc0000, DrvTempRom + 0x00000, 0x40000); + memcpy(Drv68KRom + 0x80000, DrvTempRom + 0x40000, 0x40000); + memcpy(Drv68KRom + 0x40000, DrvTempRom + 0x80000, 0x40000); + memcpy(Drv68KRom + 0x00000, DrvTempRom + 0xc0000, 0x40000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load Shared RAM data + nRet = BurnLoadRom(DrvProtData, 3, 1); if (nRet) return 1; + BurnByteswap(DrvProtData, 0x200); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x200001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 7, 2); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x000000, DrvTempRom + 0x200000, 0x40000); + memcpy(DrvTempRom + 0x100000, DrvTempRom + 0x240000, 0x40000); + memcpy(DrvTempRom + 0x040000, DrvTempRom + 0x280000, 0x40000); + memcpy(DrvTempRom + 0x140000, DrvTempRom + 0x2c0000, 0x40000); + memcpy(DrvTempRom + 0x080000, DrvTempRom + 0x300000, 0x40000); + memcpy(DrvTempRom + 0x180000, DrvTempRom + 0x340000, 0x40000); + memcpy(DrvTempRom + 0x0c0000, DrvTempRom + 0x380000, 0x40000); + memcpy(DrvTempRom + 0x1c0000, DrvTempRom + 0x3c0000, 0x40000); + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, Sprite2PlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 9, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 11, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200001, 13, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 14, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 15, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, Sprite3PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 16, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 BcstryLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(DrvTempRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 1, 2); if (nRet != 0) return 1; + memcpy(Drv68KRom + 0x40000, DrvTempRom + 0x00000, 0x40000); + memcpy(Drv68KRom + 0x00000, DrvTempRom + 0x40000, 0x40000); + + // Load Z80 Program Roms + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom, 2, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom + 0x04000, DrvTempRom + 0x00000, 0x04000); + memcpy(DrvZ80Rom + 0x00000, DrvTempRom + 0x04000, 0x04000); + memcpy(DrvZ80Rom + 0x0c000, DrvTempRom + 0x08000, 0x04000); + memcpy(DrvZ80Rom + 0x08000, DrvTempRom + 0x0c000, 0x04000); + + // Load Shared RAM data + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvProtData, 3, 1); if (nRet) return 1; + BurnByteswap(DrvProtData, 0x200); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x200000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200001, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 7, 2); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x000000, DrvTempRom + 0x200000, 0x40000); + memcpy(DrvTempRom + 0x100000, DrvTempRom + 0x240000, 0x40000); + memcpy(DrvTempRom + 0x040000, DrvTempRom + 0x280000, 0x40000); + memcpy(DrvTempRom + 0x140000, DrvTempRom + 0x2c0000, 0x40000); + memcpy(DrvTempRom + 0x080000, DrvTempRom + 0x300000, 0x40000); + memcpy(DrvTempRom + 0x180000, DrvTempRom + 0x340000, 0x40000); + memcpy(DrvTempRom + 0x0c0000, DrvTempRom + 0x380000, 0x40000); + memcpy(DrvTempRom + 0x1c0000, DrvTempRom + 0x3c0000, 0x40000); + TumblebTilesRearrange(); + GfxDecode(DrvNumChars, 4, 8, 8, Sprite2PlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 9, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 11, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200001, 13, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 14, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 15, 2); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, Sprite3PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 16, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static void TumblebMap68k() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x1a0000, 0x1a07ff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0x320000, 0x320fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0x322000, 0x322fff, SM_RAM); + SekSetReadWordHandler(0, Tumbleb68KReadWord); + SekSetWriteWordHandler(0, Tumbleb68KWriteWord); + SekSetReadByteHandler(0, Tumbleb68KReadByte); + SekSetWriteByteHandler(0, Tumbleb68KWriteByte); + SekClose(); +} + +static void PangpangMap68k() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x1a0000, 0x1a07ff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0x320000, 0x321fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0x340000, 0x341fff, SM_RAM); + SekSetReadWordHandler(0, Tumbleb68KReadWord); + SekSetWriteWordHandler(0, Tumbleb68KWriteWord); + SekSetReadByteHandler(0, Tumbleb68KReadByte); + SekSetWriteByteHandler(0, Tumbleb68KWriteByte); + SekClose(); +} + +static void SuprtrioMap68k() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0x700000, 0x7007ff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0xa20000, 0xa20fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0xa22000, 0xa22fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0xcf0000, 0xcf05ff, SM_RAM); + SekMapMemory(Drv68KRam , 0xf00000, 0xf07fff, SM_RAM); + SekSetReadWordHandler(0, Suprtrio68KReadWord); + SekSetWriteWordHandler(0, Suprtrio68KWriteWord); + SekClose(); +} + +static void HtchctchMap68k() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x160000, 0x160fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x1a0000, 0x1a0fff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0x320000, 0x321fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0x322000, 0x322fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x5000 , 0x341000, 0x342fff, SM_RAM); + SekSetReadWordHandler(0, Tumbleb68KReadWord); + SekSetWriteWordHandler(0, Tumbleb68KWriteWord); + SekSetReadByteHandler(0, Tumbleb68KReadByte); + SekSetWriteByteHandler(0, Tumbleb68KWriteByte); + SekClose(); +} + +static void FncywldMap68k() +{ + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x140fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x160000, 0x1607ff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0x320000, 0x321fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0x322000, 0x323fff, SM_RAM); + SekMapMemory(Drv68KRam , 0xff0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, Fncywld68KReadWord); + SekSetWriteWordHandler(0, Fncywld68KWriteWord); + SekSetReadByteHandler(0, Fncywld68KReadByte); + SekSetWriteByteHandler(0, Fncywld68KWriteByte); + SekClose(); +} + +static void JumpkidsMapZ80() +{ + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(JumpkidsZ80Read); + ZetSetWriteHandler(JumpkidsZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); +} + +static void SemicomMapZ80() +{ + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(SemicomZ80Read); + ZetSetWriteHandler(SemicomZ80Write); + ZetMapArea(0x0000, 0xcfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xcfff, 2, DrvZ80Rom ); + ZetMapArea(0xd000, 0xd7ff, 0, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 1, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); +} + +void SemicomYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit(bool bReset, INT32 SpriteRamSize, INT32 SpriteMask, INT32 SpriteXOffset, INT32 SpriteYOffset, INT32 NumSprites, INT32 NumChars, INT32 NumTiles, double Refresh, INT32 OkiFreq) +{ + INT32 nRet = 0, nLen; + + DrvSpriteRamSize = SpriteRamSize; + DrvNumSprites = NumSprites, + DrvNumChars = NumChars, + DrvNumTiles = NumTiles, + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + nRet = DrvLoadRoms(); + + DrvMap68k(); + + if (DrvHasZ80) DrvMapZ80(); + + if (DrvHasYM2151) { + if (!DrvYM2151Freq) DrvYM2151Freq = 3427190; + BurnYM2151Init(DrvYM2151Freq, 25.0); + if (DrvHasZ80) BurnYM2151SetIrqHandler(&SemicomYM2151IrqHandler); + } + + // Setup the OKIM6295 emulation + if (DrvHasYM2151) { + MSM6295Init(0, OkiFreq / 132, 20.0, 1); + } else { + MSM6295Init(0, OkiFreq / 132, 20.0, 0); + } + + BurnSetRefreshRate(Refresh); + + nCyclesTotal[0] = 14000000 / 60; + + DrvSpriteXOffset = SpriteXOffset; + DrvSpriteYOffset = SpriteYOffset; + DrvSpriteMask = SpriteMask; + DrvSpriteColourMask = 0x0f; + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 0; + + GenericTilesInit(); + + // Reset the driver + if (bReset) DrvDoReset(); + + return 0; +} + +static INT32 TumblebInit() +{ + DrvLoadRoms = TumblebLoadRoms; + DrvMap68k = TumblebMap68k; + DrvRender = DrvDraw; + + return DrvInit(1, 0x800, 0x3fff, -1, 0, 0x2000, 0x4000, 0x1000, 58.0, 8000000 / 10); +} + +static INT32 Tumbleb2Init() +{ + Tumbleb2 = 1; + return TumblebInit(); +} + +static INT32 JumpkidsInit() +{ + INT32 nRet; + + Jumpkids = 1; + DrvHasZ80 = 1; + DrvLoadRoms = JumpkidsLoadRoms; + DrvMap68k = TumblebMap68k; + DrvMapZ80 = JumpkidsMapZ80; + DrvRender = DrvDraw; + + nRet = DrvInit(1, 0x800, 0x7fff, -1, 0, 0x2000, 0x4000, 0x1000, 60.0, 8000000 / 8); + + nCyclesTotal[0] = 12000000 / 60; + nCyclesTotal[1] = (8000000 / 2) / 60; + + return nRet; +} + +static INT32 MetlsavrInit() +{ + INT32 nRet; + + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = MetlsavrLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = DrvDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x4000, 0x4000, 0x1000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + return nRet; +} + +static INT32 PangpangInit() +{ + Tumbleb2 = 1; + DrvLoadRoms = PangpangLoadRoms; + DrvMap68k = PangpangMap68k; + DrvRender = PangpangDraw; + + return DrvInit(1, 0x800, 0x7fff, -1, 0, 0x2000, 0x8000, 0x2000, 58.0, 8000000 / 10); +} + +static INT32 SuprtrioInit() +{ + INT32 nRet; + + DrvHasZ80 = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = SuprtrioLoadRoms; + DrvMap68k = SuprtrioMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = SuprtrioDraw; + + nRet = DrvInit(1, 0x800, 0x7fff, 0, 0, 0x2000, 0x8000, 0x2000, 60.0, 875000); + + Pf1XOffset = -6; + Pf2XOffset = -2; + nCyclesTotal[1] = 8000000 / 60; + + return nRet; +} + +static INT32 HtchctchInit() +{ + INT32 nRet; + + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = HtchctchLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x1000, 0x4000, 0x1000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + return nRet; +} + +static INT32 CookbibInit() +{ + INT32 nRet = HtchctchInit(); + + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 2; + + return nRet; +} + +static INT32 ChokchokInit() +{ + INT32 nRet; + + Chokchok = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = ChokchokLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = DrvDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x4000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 2; + + return nRet; +} + +static INT32 WlstarInit() +{ + INT32 nRet; + + Wlstar = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = ChokchokLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x4000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 2; + + return nRet; +} + +static INT32 Wondl96Init() +{ + INT32 nRet; + + Wlstar = 1; + Wondl96 = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 2; + SemicomSoundCommand = 1; + DrvLoadRoms = ChokchokLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x4000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 2; + + return nRet; +} + +static INT32 FncywldInit() +{ + INT32 nRet; + + DrvHasYM2151 = 1; + DrvYM2151Freq = 32220000 / 9; + DrvLoadRoms = FncywldLoadRoms; + DrvMap68k = FncywldMap68k; + DrvRender = FncywldDraw; + + nRet = DrvInit(1, 0x800, 0x3fff, -1, 0, 0x2000, 0x8000, 0x2000, 60.0, 1023924); + + nCyclesTotal[0] = 12000000 / 60; + DrvSpriteColourMask = 0x3f; + + return nRet; +} + +static INT32 SdfightInit() +{ + INT32 nRet; + + Bcstry = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvYM2151Freq = 3427190; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = SdfightLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = SdfightDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, 0, 1, 0x8000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -5; + Pf1YOffset = -16; + Pf2XOffset = -1; + Pf2YOffset = 0; + + return nRet; +} + +static INT32 BcstryInit() +{ + INT32 nRet; + + Bcstry = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvYM2151Freq = 3427190; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = BcstryLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x8000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + //Pf1XOffset = 8; + Pf1XOffset = -5; + Pf1YOffset = 0; + //Pf2XOffset = 8; + Pf2XOffset = -1; + Pf2YOffset = 0; + + return nRet; +} + +static INT32 SemibaseInit() +{ + INT32 nRet; + + Semibase = 1; + Bcstry = 1; + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvYM2151Freq = 3427190; + DrvHasProt = 1; + SemicomSoundCommand = 1; + DrvLoadRoms = BcstryLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x8000, 0x10000, 0x4000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -2; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 0; + + return nRet; +} + +static INT32 DquizgoInit() +{ + INT32 nRet; + + DrvHasZ80 = 1; + DrvHasYM2151 = 1; + DrvHasProt = 2; + SemicomSoundCommand = 1; + DrvLoadRoms = MetlsavrLoadRoms; + DrvMap68k = HtchctchMap68k; + DrvMapZ80 = SemicomMapZ80; + DrvRender = HtchctchDraw; + + nRet = DrvInit(1, 0x1000, 0x7fff, -1, 0, 0x4000, 0x4000, 0x1000, 60.0, 1024000); + + nCyclesTotal[0] = 15000000 / 60; + nCyclesTotal[1] = (15000000 / 4) / 60; + + Pf1XOffset = -5; + Pf1YOffset = 0; + Pf2XOffset = -1; + Pf2YOffset = 2; + + return nRet; +} + +inline static INT32 JumppopSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3500000); +} + +static INT32 JumppopInit() +{ + INT32 nRet = 0, nLen; + + DrvSpriteRamSize = 0x1000; + DrvNumSprites = 0x4000, + DrvNumChars = 0x8000, + DrvNumTiles = 0x2000, + + DrvHasZ80 = 1; + DrvHasYM3812 = 1; + + // Allocate and Blank all required memory + Mem = NULL; + JumppopMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + JumppopMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 1); if (nRet != 0) return 1; + + // Load Z80 Program Roms + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvZ80Rom, 1, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 3, 1); if (nRet != 0) return 1; + GfxDecode(DrvNumChars, 8, 8, 8, JpCharPlaneOffsets, JpCharXOffsets, JpCharYOffsets, 0x100, DrvTempRom, DrvChars); + GfxDecode(DrvNumTiles, 8, 16, 16, JpTilePlaneOffsets, JpTileXOffsets, JpTileYOffsets, 0x400, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 5, 1); if (nRet != 0) return 1; + GfxDecode(DrvNumSprites, 4, 16, 16, Sprite2PlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(MSM6295ROM, 6, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Drv68KRam , 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x160000, 0x160fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x1a0000, 0x1a7fff, SM_RAM); + SekMapMemory(DrvPf1Ram , 0x320000, 0x323fff, SM_RAM); + SekMapMemory(DrvPf2Ram , 0x300000, 0x303fff, SM_RAM); + SekSetReadWordHandler(0, Jumppop68KReadWord); + SekSetWriteWordHandler(0, Jumppop68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetInHandler(JumppopZ80PortRead); + ZetSetOutHandler(JumppopZ80PortWrite); + ZetMapArea(0x0000, 0x2fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x2fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x8000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x8000 ); + ZetMapArea(0xf800, 0xffff, 0, DrvZ80Ram ); + ZetMapArea(0xf800, 0xffff, 1, DrvZ80Ram ); + ZetMapArea(0xf800, 0xffff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(3500000, NULL, JumppopSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3500000); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 875000 / 132, 100.0, 1); + + BurnSetRefreshRate(60.0); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesTotal[1] = 3500000 / 60; + + DrvSpriteXOffset = 1; + DrvSpriteYOffset = 0; + DrvSpriteMask = 0x7fff; + DrvSpriteColourMask = 0x0f; + Pf1XOffset = -0x3a0; + Pf1YOffset = 0; + Pf2XOffset = -0x3a2; + Pf2YOffset = 0; + + GenericTilesInit(); + DrvRender = JumppopDraw; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + if (DrvHasZ80) ZetExit(); + if (DrvHasYM2151) BurnYM2151Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + + DrvVBlank = 0; + DrvOkiBank = 0; + DrvZ80Bank = 0; + DrvTileBank = 0; + DrvSoundLatch = 0; + Tumbleb2MusicCommand = 0; + Tumbleb2MusicBank = 0; + Tumbleb2MusicIsPlaying = 0; + + DrvSpriteXOffset = 0; + DrvSpriteYOffset = 0; + DrvSpriteRamSize = 0; + DrvSpriteMask = 0; + DrvSpriteColourMask = 0; + DrvYM2151Freq = 0; + DrvNumSprites = 0; + DrvNumChars = 0; + DrvNumTiles = 0; + DrvHasZ80 = 0; + DrvHasYM2151 = 0; + DrvHasYM3812 = 0; + DrvHasProt = 0; + Tumbleb2 = 0; + Jumpkids = 0; + Chokchok = 0; + Wlstar = 0; + Wondl96 = 0; + Bcstry = 0; + Semibase = 0; + SemicomSoundCommand = 0; + Pf1XOffset = 0; + Pf1YOffset = 0; + Pf2XOffset = 0; + Pf2YOffset = 0; + + DrvLoadRoms = NULL; + DrvMap68k = NULL; + DrvMapZ80 = NULL; + DrvRender = NULL; + + BurnFree(Mem); + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 HtchctchCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 0); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 10); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 FncywldCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 8); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 JumppopCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 10); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x400; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void HtchctchCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x400; i++, ps++, pd++) { + *pd = HtchctchCalcCol(*ps); + } +} + +static void FncywldCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x800; i++, ps++, pd++) { + *pd = FncywldCalcCol(*ps); + } +} + +static void JumppopCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x400; i++, ps++, pd++) { + *pd = JumppopCalcCol(*ps); + } +} + +static void DrvRenderPf2Layer(INT32 ScrollX, INT32 ScrollY) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf2Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex]; + Code = (Attr & 0xfff) | (DrvTileBank >> 2); + Colour = Attr >> 12; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((ScrollX + Pf2XOffset) & 0x3ff); + y -= ((ScrollY + Pf2YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } + } + } +} + +static void PangpangRenderPf2Layer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf2Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex * 2 + 0]; + Code = VideoRam[TileIndex * 2 + 1] & 0xfff; + Code |= 0x1000; + Colour = (Attr >> 12) & 0x0f; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[3] + Pf2XOffset) & 0x3ff); + y -= ((DrvControl[4] + Pf2YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 512, DrvTiles); + } + } + } +} + +static void FncywldRenderPf2Layer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf2Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex * 2 + 1]; + Code = VideoRam[TileIndex * 2 + 0]; + Colour = Attr & 0x1f; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[3] + Pf2XOffset) & 0x3ff); + y -= ((DrvControl[4] + Pf2YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 0x400, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0x400, DrvTiles); + } + } + } +} + +static void JumppopRenderPf2Layer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf2Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[TileIndex]; + Code &= (DrvNumTiles - 1); + Colour = 0; + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[0] + Pf2XOffset) & 0x3ff); + y -= ((DrvControl[1] + Pf2YOffset) & 0x3ff); + if (x < -16) x += 1024; + if (y < -16) y += 1024; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 8, 512, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 8, 512, DrvTiles); + } + + TileIndex++; + } + } +} + +static void JumppopRenderPf2AltLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf2Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 128; mx++) { + Code = VideoRam[TileIndex]; + Colour = 0; + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[0] + Pf2XOffset) & 0x3ff); + y -= ((DrvControl[1] + Pf2YOffset) & 0x1ff); + if (x < -8) x += 1024; + if (y < -8) y += 512; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 512, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 512, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvRenderPf1Layer(INT32 ScrollX, INT32 ScrollY) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex]; + Code = (Attr & 0xfff) | (DrvTileBank >> 2); + Colour = Attr >> 12; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((ScrollX + Pf1XOffset) & 0x3ff); + y -= ((ScrollY + Pf1YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } + } + } +} + +static void PangpangRenderPf1Layer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex * 2 + 0]; + Code = VideoRam[TileIndex * 2 + 1]; + Colour = (Attr >> 12) & 0x0f; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x3ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvTiles); + } + } + } +} + +static void FncywldRenderPf1Layer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + Attr = VideoRam[TileIndex * 2 + 1]; + Code = VideoRam[TileIndex * 2 + 0]; + Colour = Attr & 0x1f; + + Code &= (DrvNumTiles - 1); + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x3ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0x1ff); + if (x < -16) x += 1024; + if (y < -16) y += 512; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x200, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x200, DrvTiles); + } + } + } +} + +static void JumppopRenderPf1Layer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[TileIndex] & 0x1fff; + Code &= (DrvNumTiles - 1); + Colour = 0; + + x = 16 * mx; + y = 16 * my; + + x -= ((DrvControl[2] + Pf1XOffset) & 0x3ff); + y -= ((DrvControl[3] + Pf1YOffset) & 0x3ff); + if (x < -16) x += 1024; + if (y < -16) y += 1024; + + y -= 8; + + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 256, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 256, DrvTiles); + } + + TileIndex++; + } + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex]; + Code = (Attr & 0xfff) | DrvTileBank; + Colour = Attr >> 12; + Code &= (DrvNumChars - 1); + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x1ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0xff); + if (x < -8) x += 512; + if (y < -8) y += 256; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } + + TileIndex++; + } + } +} + +static void PangpangRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex * 2 + 0]; + Code = VideoRam[TileIndex * 2 + 1] & 0x1fff; + Colour = (Attr >> 12) & 0x1f; + Code &= (DrvNumChars - 1); + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x1ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0xff); + if (x < -8) x += 512; + if (y < -8) y += 256; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } + + TileIndex++; + } + } +} + +static void FncywldRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex * 2 + 1]; + Code = VideoRam[TileIndex * 2 + 0] & 0x1fff; + if (Code) { + Colour = Attr & 0x1f; + Code &= (DrvNumChars - 1); + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x1ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0xff); + if (x < -8) x += 512; + if (y < -8) y += 256; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x400, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x400, DrvChars); + } + } + + TileIndex++; + } + } +} + +static void SdfightRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex]; + Code = (Attr & 0xfff) | DrvTileBank; + Colour = Attr >> 12; + Code &= (DrvNumChars - 1); + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[1] + Pf1XOffset) & 0x1ff); + y -= ((DrvControl[2] + Pf1YOffset) & 0x1ff); + if (x < -8) x += 512; + if (y < -8) y += 512; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, DrvChars); + } + + TileIndex++; + } + } +} + +static void JumppopRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvPf1Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 128; mx++) { + Code = VideoRam[TileIndex]; + Colour = 0; + + x = 8 * mx; + y = 8 * my; + + x -= ((DrvControl[2] + Pf1XOffset) & 0x3ff); + y -= ((DrvControl[3] + Pf1YOffset) & 0x1ff); + if (x < -8) x += 1024; + if (y < -8) y += 512; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 256, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 256, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvRenderSprites(INT32 MaskColour, INT32 xFlipped) +{ + INT32 Offset; + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + + for (Offset = 0; Offset < DrvSpriteRamSize / 2; Offset += 4) { + INT32 x, y, Code, Colour, Flash, Multi, xFlip, yFlip, Inc, Mult; + + Code = SpriteRam[Offset + 1] & DrvSpriteMask; + if (!Code) continue; + + y = SpriteRam[Offset]; + Flash = y & 0x1000; + if (Flash && (GetCurrentFrame() & 1)) continue; + + x = SpriteRam[Offset + 2]; + Colour = (x >> 9) & DrvSpriteColourMask; + xFlip = y & 0x2000; + yFlip = y & 0x4000; + + Multi = (1 << ((y & 0x600) >> 9)) - 1; + + x &= 0x1ff; + y &= 0x1ff; + if (x >= 320) x -= 512; + if (y >= 256) y -= 512; + y = 240 - y; + x = 304 - x; + + y -= 8; + + if (yFlip) { + Inc = -1; + } else { + Code += Multi; + Inc = 1; + } + + if (xFlipped) { + xFlip = !xFlip; + x = 304 - x; + } + + Mult = -16; + + while (Multi >= 0) { + INT32 RenderCode = Code - (Multi * Inc); + INT32 RenderX = DrvSpriteXOffset + x; + INT32 RenderY = DrvSpriteYOffset + y + (Mult * Multi); + RenderCode &= (DrvNumSprites - 1); + + if (RenderX > 16 && RenderX < 304 && RenderY > 16 && RenderY < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, RenderCode, RenderX, RenderY, Colour, 4, MaskColour, 0, DrvSprites); + } + } + } + + Multi--; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderPf2Layer(DrvControl[3], DrvControl[4]); + + if (DrvControl[6] & 0x80) { + DrvRenderCharLayer(); + } else { + DrvRenderPf1Layer(DrvControl[1], DrvControl[2]); + } + + DrvRenderSprites(0, 0); + BurnTransferCopy(DrvPalette); +} + +static void PangpangDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + PangpangRenderPf2Layer(); + + if (DrvControl[6] & 0x80) { + PangpangRenderCharLayer(); + } else { + PangpangRenderPf1Layer(); + } + + DrvRenderSprites(0, 0); + BurnTransferCopy(DrvPalette); +} + +static void SuprtrioDraw() +{ + BurnTransferClear(); + HtchctchCalcPalette(); + DrvRenderPf2Layer(-DrvControl[3], -DrvControl[4]); + DrvRenderPf1Layer(-DrvControl[1], -DrvControl[2]); + DrvRenderSprites(0, 0); + BurnTransferCopy(DrvPalette); +} + +static void HtchctchDraw() +{ + BurnTransferClear(); + HtchctchCalcPalette(); + DrvRenderPf2Layer(DrvControl[3], DrvControl[4]); + + if (DrvControl[6] & 0x80) { + DrvRenderCharLayer(); + } else { + DrvRenderPf1Layer(DrvControl[1], DrvControl[2]); + } + + DrvRenderSprites(0, 0); + BurnTransferCopy(DrvPalette); +} + +static void FncywldDraw() +{ + BurnTransferClear(); + FncywldCalcPalette(); + FncywldRenderPf2Layer(); + + if (DrvControl[6] & 0x80) { + FncywldRenderCharLayer(); + } else { + FncywldRenderPf1Layer(); + } + + DrvRenderSprites(0x0f, 0); + BurnTransferCopy(DrvPalette); +} + +static void SdfightDraw() +{ + BurnTransferClear(); + HtchctchCalcPalette(); + DrvRenderPf2Layer(DrvControl[3], DrvControl[4]); + + if (DrvControl[6] & 0x80) { + SdfightRenderCharLayer(); + } else { + DrvRenderPf1Layer(DrvControl[1], DrvControl[2]); + } + + DrvRenderSprites(0, 0); + BurnTransferCopy(DrvPalette); +} + +static void JumppopDraw() +{ + BurnTransferClear(); + JumppopCalcPalette(); + + if (DrvControl[7] & 0x01) { + JumppopRenderPf2Layer(); + } else { + JumppopRenderPf2AltLayer(); + } + + if (DrvControl[7] & 0x02) { + JumppopRenderPf1Layer(); + } else { + JumppopRenderCharLayer(); + } + + DrvRenderSprites(0, 1); + BurnTransferCopy(DrvPalette); +} + +#define NUM_SCANLINES 315 +#define SCANLINE_VBLANK_START 37 +#define SCANLINE_VBLANK_END SCANLINE_VBLANK_START + 240 + +static INT32 DrvFrame() +{ + INT32 nInterleave = NUM_SCANLINES; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + if (DrvHasZ80) ZetNewFrame(); + + DrvVBlank = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == SCANLINE_VBLANK_START) DrvVBlank = 1; + if (i == SCANLINE_VBLANK_END) DrvVBlank = 0; + if (i == NUM_SCANLINES - 1) { + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + if (Tumbleb2) Tumbleb2PlayMusic(); + } + SekClose(); + + if (DrvHasZ80) { + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (DrvHasYM2151) { + if (DrvHasZ80) ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + if (DrvHasZ80) ZetClose(); + } + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + if (DrvHasYM2151) { + if (DrvHasZ80) ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + if (DrvHasZ80) ZetClose(); + } + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvRender(); + + return 0; +} + +static INT32 JumppopFrame() +{ + INT32 nInterleave = 1953 / 60; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) { + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + } + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + BurnTimerUpdateYM3812(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + ZetNmi(); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) JumppopDraw(); + + return 0; +} + +#undef NUM_SCANLINES +#undef SCANLINE_VBLANK_START +#undef SCANLINE_VBLANK_END + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029676; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + if (DrvHasZ80) ZetScan(nAction); + if (DrvHasYM2151) BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(DrvVBlank); + SCAN_VAR(DrvOkiBank); + SCAN_VAR(DrvZ80Bank); + SCAN_VAR(DrvTileBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(Tumbleb2MusicCommand); + SCAN_VAR(Tumbleb2MusicBank); + SCAN_VAR(Tumbleb2MusicIsPlaying); + } + + if (nAction & ACB_WRITE) { + if (DrvOkiBank) { + if (Jumpkids) { + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + (DrvOkiBank * 0x20000), 0x20000); + } else { + memcpy(MSM6295ROM + 0x30000, DrvMSM6295ROMSrc + 0x30000 + (DrvOkiBank * 0x10000), 0x10000); + } + } + + if (DrvZ80Bank) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + (DrvZ80Bank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + (DrvZ80Bank * 0x4000)); + ZetClose(); + } + } + + return 0; +} + +struct BurnDriver BurnDrvTumbleb = { + "tumbleb", "tumblep", NULL, NULL, "1991", + "Tumble Pop (bootleg set 1)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, TumblebRomInfo, TumblebRomName, NULL, NULL, TumblebInputInfo, TumblebDIPInfo, + TumblebInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTumbleb2 = { + "tumbleb2", "tumblep", NULL, NULL, "1991", + "Tumble Pop (bootleg set 2)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, Tumbleb2RomInfo, Tumbleb2RomName, NULL, NULL, TumblebInputInfo, TumblebDIPInfo, + Tumbleb2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvJumpkids = { + "jumpkids", NULL, NULL, NULL, "1993", + "Jump Kids\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, JumpkidsRomInfo, JumpkidsRomName, NULL, NULL, TumblebInputInfo, TumblebDIPInfo, + JumpkidsInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMetlsavr = { + "metlsavr", NULL, NULL, NULL, "1994", + "Metal Saver\0", NULL, "First Amusement", "Miscellaneous", + L"Metal Saver\0\uBA54\uD0C8\uC138\uC774\uBC84\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, MetlsavrRomInfo, MetlsavrRomName, NULL, NULL, MetlsavrInputInfo, MetlsavrDIPInfo, + MetlsavrInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPangpang = { + "pangpang", NULL, NULL, NULL, "1994", + "Pang Pang\0", NULL, "Dong Gue La Mi Ltd.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, PangpangRomInfo, PangpangRomName, NULL, NULL, TumblebInputInfo, TumblebDIPInfo, + PangpangInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSuprtrio = { + "suprtrio", NULL, NULL, NULL, "1994", + "Super Trio\0", NULL, "Gameace", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, SuprtrioRomInfo, SuprtrioRomName, NULL, NULL, SuprtrioInputInfo, SuprtrioDIPInfo, + SuprtrioInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHtchctch = { + "htchctch", NULL, NULL, NULL, "1995", + "Hatch Catch\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, HtchctchRomInfo, HtchctchRomName, NULL, NULL, HtchctchInputInfo, HtchctchDIPInfo, + HtchctchInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCookbib = { + "cookbib", NULL, NULL, NULL, "1995", + "Cookie & Bibi\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, CookbibRomInfo, CookbibRomName, NULL, NULL, HtchctchInputInfo, CookbibDIPInfo, + CookbibInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvChokChok = { + "chokchok", NULL, NULL, NULL, "1995", + "Choky! Choky!\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, ChokchokRomInfo, ChokchokRomName, NULL, NULL, HtchctchInputInfo, ChokchokDIPInfo, + ChokchokInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWlstar = { + "wlstar", NULL, NULL, NULL, "1995", + "Wonder League Star - Sok-Magicball Fighting (Korea)\0", NULL, "Mijin", "Miscellaneous", + L"\uC6D0\uB354\uB9AC\uADF8\uC2A4\uD0C0 - \uC18D \uB9E4\uC9C1\uBCFC \uD30C\uC774\uD305 (Korea)\0Wonder League Star - Sok-Magicball Fighting\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, WlstarRomInfo, WlstarRomName, NULL, NULL, MetlsavrInputInfo, WlstarDIPInfo, + WlstarInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWondl96 = { + "wondl96", NULL, NULL, NULL, "1995", + "Wonder League '96 (Korea)\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, Wondl96RomInfo, Wondl96RomName, NULL, NULL, MetlsavrInputInfo, Wondl96DIPInfo, + Wondl96Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvFancywld = { + "fncywld", NULL, NULL, NULL, "1996", + "Fancy World - Earth of Crisis\0", NULL, "Unico", "Miscellaneous", + L"Fancy World - Earth of Crisis\0\uD39C\uC2DC\uC6D4\uB4DC \uD658\uC0C1\uC758 \uC138\uACC4 - Earth of Crisis\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, FncywldRomInfo, FncywldRomName, NULL, NULL, FncywldInputInfo, FncywldDIPInfo, + FncywldInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSdfight = { + "sdfight", NULL, NULL, NULL, "1996", + "SD Fighters (Korea)\0", NULL, "SemiCom", "Miscellaneous", + L"\uFF33\uFF24 \uD30C\uC774\uD130\uC988 (Korea)\0SD Fighters\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, SdfightRomInfo, SdfightRomName, NULL, NULL, MetlsavrInputInfo, SdfightDIPInfo, + SdfightInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBcstry = { + "bcstry", NULL, NULL, NULL, "1997", + "B.C. Story (set 1)\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, BcstryRomInfo, BcstryRomName, NULL, NULL, MetlsavrInputInfo, BcstryDIPInfo, + BcstryInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBcstrya = { + "bcstrya", "bcstry", NULL, NULL, "1997", + "B.C. Story (set 2)\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, BcstryaRomInfo, BcstryaRomName, NULL, NULL, MetlsavrInputInfo, BcstryDIPInfo, + BcstryInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSemibase = { + "semibase", NULL, NULL, NULL, "1997", + "MuHanSeungBu (SemiCom Baseball) (Korea)\0", NULL, "SemiCom", "Miscellaneous", + L"\u7121\u9650\u52DD\u8CA0\0\uC804\uC6D0 \uAD6D\uC81C\uB9AC\uADF8 \uC804 (SemiCom Baseball) (Korea)\0MuHanSeungBu\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SPORTSMISC, 0, + NULL, SemibaseRomInfo, SemibaseRomName, NULL, NULL, SemibaseInputInfo, SemibaseDIPInfo, + SemibaseInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDquizgo = { + "dquizgo", NULL, NULL, NULL, "1998", + "Date Quiz Go Go (Korea)\0", NULL, "SemiCom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, DquizgoRomInfo, DquizgoRomName, NULL, NULL, MetlsavrInputInfo, DquizgoDIPInfo, + DquizgoInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvJumppop = { + "jumppop", NULL, NULL, NULL, "2001", + "Jumping Pop\0", "Missing Sounds", "ESD", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, JumppopRomInfo, JumppopRomName, NULL, NULL, JumppopInputInfo, JumppopDIPInfo, + JumppopInit, DrvExit, JumppopFrame, NULL, DrvScan, + NULL, 0x400, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_tumblep.cpp b/src/burn/drivers/misc_post90s/d_tumblep.cpp new file mode 100644 index 00000000..11414986 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_tumblep.cpp @@ -0,0 +1,563 @@ +// FB Alpha Tumble Pop driver module +// Based on MAME driver by Bryan McPhail and David Haywood + +#include "tiles_generic.h" +#include "h6280_intf.h" +#include "deco16ic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvHucRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo TumblepInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Tumblep) + +static struct BurnDIPInfo TumblepDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "2 Coins to Start, 1 to Continue" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x1c, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x10, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x1c, 0x1c, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x1c, 0x0c, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x1c, 0x14, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x1c, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x1c, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x1c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0xe0, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0x80, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xe0, 0xe0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xe0, 0x60, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xe0, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xe0, 0xc0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xe0, 0x40, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x02, 0x00, "No" }, + {0x13, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x30, 0x10, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + {0x13, 0x01, 0x30, 0x20, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x80, "1" }, + {0x13, 0x01, 0xc0, 0x00, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x40, "4" }, +}; + +STDDIPINFO(Tumblep) + +void __fastcall tumblep_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(0, address, 0x300000, data) + + switch (address) + { + case 0x100000: + deco16_soundlatch = data; + h6280SetIRQLine(0, H6280_IRQSTATUS_ACK); + return; + } +} + +void __fastcall tumblep_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x100000: + case 0x100001: + deco16_soundlatch = data; + h6280SetIRQLine(0, H6280_IRQSTATUS_ACK); + return; + } +} + +UINT16 __fastcall tumblep_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x180000: + return DrvInputs[0]; + + case 0x180002: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x180008: + return (DrvInputs[1] & ~0x0008) | (deco16_vblank & 0x0008); + } + + return 0; +} + +UINT8 __fastcall tumblep_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180000: + case 0x180001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x180002: + return DrvDips[0]; + + case 0x180003: + return DrvDips[1]; + + case 0x180008: + case 0x180009: + return (DrvInputs[1] & ~0x0008) | (deco16_vblank & 0x0008); + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + deco16SoundReset(); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvHucRAM = Next; Next += 0x002000; + DrvSprRAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvHucROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 4, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 5, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 6, 1)) return 1; + + deco56_decrypt_gfx(DrvGfxROM1, 0x080000); + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x080000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_sprite_decode(DrvGfxROM2, 0x100000); + } + + deco16Init(1, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x80000 * 2, DrvGfxROM1, 0x80000 * 2, NULL, 0); + deco16_set_color_base(0, 256); + deco16_set_color_base(1, 512); + deco16_set_global_offsets(0, 8); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x120000, 0x123fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x1407ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x1a0000, 0x1a07ff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x320000, 0x321fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x322000, 0x323fff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[0], 0x340000, 0x340bff, SM_RAM); + SekMapMemory(deco16_pf_rowscroll[1], 0x342000, 0x342bff, SM_RAM); + SekSetWriteWordHandler(0, tumblep_main_write_word); + SekSetWriteByteHandler(0, tumblep_main_write_byte); + SekSetReadWordHandler(0, tumblep_main_read_word); + SekSetReadByteHandler(0, tumblep_main_read_byte); + SekClose(); + + deco16SoundInit(DrvHucROM, DrvHucRAM, 4027500, 0, NULL, 40.0, 1023924, 50.0, 0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + deco16SoundExit(); + + SekExit(); + + BurnFree(AllMem); + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT16 *p = (UINT16*)DrvPalRAM; + + for (INT32 i = 0; i < 0x800 / 2; i++) { + INT32 b = (p[i] >> 8) & 0x0f; + INT32 g = (p[i] >> 4) & 0x0f; + INT32 r = (p[i] >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult; + + INT32 sy = ram[offs + 0]; + INT32 code = ram[offs + 1] & 0x3fff; + INT32 sx = ram[offs + 2]; + + if ((sy & 0x1000) && (nCurrentFrame & 1)) continue; + + INT32 color = (sx >> 9) & 0x1f; + + INT32 flipx = sy & 0x2000; + INT32 flipy = sy & 0x4000; + INT32 multi = (1 << ((sy & 0x0600) >> 9)) - 1; + + sx &= 0x01ff; + sy &= 0x01ff; + if (sx >= 320) sx -= 512; + if (sy >= 256) sy -= 512; + sy = 240 - sy; + sx = 304 - sx; + + code &= ~multi; + + if (flipy) { + inc = -1; + } else { + code += multi; + inc = 1; + } + + if (*flipscreen) + { + sy = 240 - sy; + sx = 304 - sx; + flipx = !flipx; + flipy = !flipy; + mult = 16; + } + else + mult = -16; + + if (sx >= 320 || sx < -15) continue; + + while (multi >= 0) + { + INT32 y = (sy + mult * multi) - 8; + INT32 c = (code - multi * inc) & 0x3fff; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, y, color, 4, 0, 0, DrvGfxROM2); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + DrvPaletteRecalc(); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + if (nBurnLayer & 1) deco16_draw_layer(1, pTransDraw, DECO16_LAYER_OPAQUE); + + if (nBurnLayer & 2) deco16_draw_layer(0, pTransDraw, 0); + + if (nBurnLayer & 4) draw_sprites(); + + // hack! fix ugly line and keep proper aspect ratio. + { + UINT16 *dst = pTransDraw + (nScreenWidth - 2); + for (INT32 y = 0; y < nScreenHeight; y++) { + dst[1] = dst[0]; + dst += nScreenWidth; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 14000000 / 58, 4027500 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + h6280Open(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + nCyclesDone[1] += h6280Run(nCyclesTotal[1] / nInterleave); + + if (i == 240) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + deco16SoundUpdate(pBurnSoundOut, nBurnSoundLen); + } + + h6280Close(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + // BurnYM2151Scan(nAction); + // MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Tumble Pop (World) + +static struct BurnRomInfo tumblepRomDesc[] = { + { "hl00-1.f12", 0x40000, 0xfd697c1b, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hl01-1.f13", 0x40000, 0xd5a62a3f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "hl02-.f16", 0x10000, 0xa5cab888, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "map-02.rom", 0x80000, 0xdfceaa26, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "map-01.rom", 0x80000, 0xe81ffa09, 4 | BRF_GRA }, // 4 Sprites + { "map-00.rom", 0x80000, 0x8c879cfe, 4 | BRF_GRA }, // 5 + + { "hl03-.j15", 0x20000, 0x01b81da0, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(tumblep) +STD_ROM_FN(tumblep) + +struct BurnDriver BurnDrvTumblep = { + "tumblep", NULL, NULL, NULL, "1991", + "Tumble Pop (World)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, tumblepRomInfo, tumblepRomName, NULL, NULL, TumblepInputInfo, TumblepDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Tumble Pop (Japan) + +static struct BurnRomInfo tumblepjRomDesc[] = { + { "hk00-1.f12", 0x40000, 0x2d3e4d3d, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "hk01-1.f13", 0x40000, 0x56912a00, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "hl02-.f16", 0x10000, 0xa5cab888, 2 | BRF_PRG | BRF_ESS }, // 2 Huc6280 Code + + { "map-02.rom", 0x80000, 0xdfceaa26, 3 | BRF_GRA }, // 3 Characters & Background Tiles + + { "map-01.rom", 0x80000, 0xe81ffa09, 4 | BRF_GRA }, // 4 Sprites + { "map-00.rom", 0x80000, 0x8c879cfe, 4 | BRF_GRA }, // 5 + + { "hl03-.j15", 0x20000, 0x01b81da0, 5 | BRF_SND }, // 6 OKI M6295 Samples +}; + +STD_ROM_PICK(tumblepj) +STD_ROM_FN(tumblepj) + +struct BurnDriver BurnDrvTumblepj = { + "tumblepj", "tumblep", NULL, NULL, "1991", + "Tumble Pop (Japan)\0", "No Sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, tumblepjRomInfo, tumblepjRomName, NULL, NULL, TumblepInputInfo, TumblepDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + diff --git a/src/burn/drivers/misc_post90s/d_unico.cpp b/src/burn/drivers/misc_post90s/d_unico.cpp new file mode 100644 index 00000000..c22f0015 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_unico.cpp @@ -0,0 +1,1906 @@ +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "burn_ym2151.h" +#include "msm6295.h" +#include "eeprom.h" +#include "burn_gun.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; +static INT32 DrvAnalogPort0 = 0; +static INT32 DrvAnalogPort1 = 0; +static INT32 DrvAnalogPort2 = 0; +static INT32 DrvAnalogPort3 = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvMSM6295ROMSrc = NULL; +static UINT8 *DrvVideo0Ram = NULL; +static UINT8 *DrvVideo1Ram = NULL; +static UINT8 *DrvVideo2Ram = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvScrollRam = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static INT32 nCyclesDone[1], nCyclesTotal[1]; +static INT32 nCyclesSegment; + +static UINT16 DrvScrollX0; +static UINT16 DrvScrollY0; +static UINT16 DrvScrollX1; +static UINT16 DrvScrollY1; +static UINT16 DrvScrollX2; +static UINT16 DrvScrollY2; +static UINT8 DrvOkiBank; + +static UINT32 DrvNumTiles; +static UINT32 DrvNumSprites; + +typedef void (*UnicoMakeInputs)(); +static UnicoMakeInputs UnicoMakeInputsFunction; + +static struct BurnInputInfo BurglarxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 2, "service" }, + {"Service 2" , BIT_DIGITAL , DrvInputPort2 + 3, "service 2" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Burglarx) + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo ZeropntInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p2 start" }, + + A("P1 Gun X" , BIT_ANALOG_REL, &DrvAnalogPort0 , "mouse x-axis"), + A("P1 Gun Y" , BIT_ANALOG_REL, &DrvAnalogPort1 , "mouse y-axis"), + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 0, "mouse button 1" }, + + A("P2 Gun X" , BIT_ANALOG_REL, &DrvAnalogPort2 , "p2 x-axis"), + A("P2 Gun Y" , BIT_ANALOG_REL, &DrvAnalogPort3 , "p2 y-axis"), + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Diagnostic" , BIT_DIGITAL , DrvInputPort0 + 2, "diag" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Zeropnt) + +#undef A + +static inline void BurglarxClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void BurglarxMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + BurglarxClearOpposites(&DrvInput[0]); + BurglarxClearOpposites(&DrvInput[1]); +} + +static inline void ZeropntMakeInputs() +{ + // Reset Inputs + DrvInput[0] = 0x00; + DrvInput[1] = 0xff; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + } + + BurnGunMakeInputs(0, (INT16)DrvAnalogPort0, (INT16)DrvAnalogPort1); + BurnGunMakeInputs(1, (INT16)DrvAnalogPort2, (INT16)DrvAnalogPort3); +} + +static inline void Zeropnt2MakeInputs() +{ + // Reset Inputs + DrvInput[0] = 0x00; + DrvInput[1] = 0x7f; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + } + + BurnGunMakeInputs(0, (INT16)DrvAnalogPort0, (INT16)DrvAnalogPort1); + BurnGunMakeInputs(1, (INT16)DrvAnalogPort2, (INT16)DrvAnalogPort3); +} + +static struct BurnDIPInfo BurglarxDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xf7, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Test Mode" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x15, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x15, 0x01, 0xe0, 0x20, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x03, 0x02, "None" }, + {0x16, 0x01, 0x03, 0x03, "A" }, + {0x16, 0x01, 0x03, 0x01, "B" }, + {0x16, 0x01, 0x03, 0x00, "C" }, + + {0 , 0xfe, 0 , 2 , "Starting Energy" }, + {0x16, 0x01, 0x80, 0x00, "2" }, + {0x16, 0x01, 0x80, 0x80, "3" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x30, 0x20, "Easy" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x10, "Hard" }, + {0x16, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0xc0, 0x80, "2" }, + {0x16, 0x01, 0xc0, 0xc0, "3" }, + {0x16, 0x01, 0xc0, 0x40, "4" }, + {0x16, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Burglarx) + +static struct BurnDIPInfo ZeropntDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x08, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x0d, 0x01, 0x02, 0x00, "Off" }, + {0x0d, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x0d, 0x01, 0xe0, 0xe0, "5 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0xc0, "4 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0xa0, "3 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x80, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x00, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x20, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0xe0, 0x40, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0xe0, 0x60, "1 Coin 4 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 3 , "Difficulty" }, + {0x0e, 0x01, 0x30, 0x10, "Easy" }, + {0x0e, 0x01, 0x30, 0x00, "Normal" }, + {0x0e, 0x01, 0x30, 0x20, "Hard" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0xc0, 0x40, "2" }, + {0x0e, 0x01, 0xc0, 0x00, "3" }, + {0x0e, 0x01, 0xc0, 0x80, "4" }, + {0x0e, 0x01, 0xc0, 0xc0, "5" }, +}; + +STDDIPINFO(Zeropnt) + +static struct BurnDIPInfo Zeropnt2DIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x0d, 0x01, 0x01, 0x01, "Off" }, + {0x0d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Coins to Continue" }, + {0x0d, 0x01, 0x02, 0x00, "1" }, + {0x0d, 0x01, 0x02, 0x02, "2" }, + + {0 , 0xfe, 0 , 3 , "Gun Reloading" }, + {0x0d, 0x01, 0x0c, 0x08, "No" }, + {0x0d, 0x01, 0x0c, 0x04, "Yes" }, + {0x0d, 0x01, 0x0c, 0x0c, "Factory Setting" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0d, 0x01, 0x10, 0x10, "English" }, + {0x0d, 0x01, 0x10, 0x00, "Japanese" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x0d, 0x01, 0xe0, 0x00, "5 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x20, "4 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x40, "3 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0x60, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xe0, 0xe0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xe0, 0xc0, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0xe0, 0xa0, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0xe0, 0x80, "1 Coin 4 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Korean Language" }, + {0x0e, 0x01, 0x01, 0x01, "Off" }, + {0x0e, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x02, 0x02, "Off" }, + {0x0e, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x0e, 0x01, 0x1c, 0x10, "2" }, + {0x0e, 0x01, 0x1c, 0x0c, "3" }, + {0x0e, 0x01, 0x1c, 0x1c, "4" }, + {0x0e, 0x01, 0x1c, 0x18, "5" }, + {0x0e, 0x01, 0x1c, 0x14, "6" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0xc0, 0x80, "Easy" }, + {0x0e, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0e, 0x01, 0xc0, 0x40, "Hard" }, + {0x0e, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Zeropnt2) + +static struct BurnRomInfo BurglarxRomDesc[] = { + { "bx-rom2.pgm", 0x80000, 0xf81120c8, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "bx-rom3.pgm", 0x80000, 0x080b4e82, BRF_ESS | BRF_PRG }, // 1 + + { "bx-rom4", 0x80000, 0xf74ce31f, BRF_GRA }, // 2 Sprites + { "bx-rom10", 0x80000, 0x6f56ca23, BRF_GRA }, // 3 + { "bx-rom9", 0x80000, 0x33f29d79, BRF_GRA }, // 4 + { "bx-rom8", 0x80000, 0x24367092, BRF_GRA }, // 5 + { "bx-rom7", 0x80000, 0xaff6bdea, BRF_GRA }, // 6 + { "bx-rom6", 0x80000, 0x246afed2, BRF_GRA }, // 7 + { "bx-rom11", 0x80000, 0x898d176a, BRF_GRA }, // 8 + { "bx-rom5", 0x80000, 0xfdee1423, BRF_GRA }, // 9 + + { "bx-rom14", 0x80000, 0x30413373, BRF_GRA }, // 10 Layers + { "bx-rom18", 0x80000, 0x8e7fc99f, BRF_GRA }, // 11 + { "bx-rom19", 0x80000, 0xd40eabcd, BRF_GRA }, // 12 + { "bx-rom15", 0x80000, 0x78833c75, BRF_GRA }, // 13 + { "bx-rom17", 0x80000, 0xf169633f, BRF_GRA }, // 14 + { "bx-rom12", 0x80000, 0x71eb160f, BRF_GRA }, // 15 + { "bx-rom13", 0x80000, 0xda34bbb5, BRF_GRA }, // 16 + { "bx-rom16", 0x80000, 0x55b28ef9, BRF_GRA }, // 17 + + { "bx-rom1.snd", 0x80000, 0x8ae67138, BRF_SND }, // 18 Samples +}; + +STD_ROM_PICK(Burglarx) +STD_ROM_FN(Burglarx) + +static struct BurnRomInfo ZeropntRomDesc[] = { + { "zero_2.bin", 0x080000, 0x1e599509, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "zero_3.bin", 0x080000, 0x588aeef7, BRF_ESS | BRF_PRG }, // 1 + + { "zpobjz01.bin", 0x200000, 0x1f2768a3, BRF_GRA }, // 2 Sprites + { "zpobjz02.bin", 0x200000, 0xde34f33a, BRF_GRA }, // 3 + { "zpobjz03.bin", 0x200000, 0xd7a657f7, BRF_GRA }, // 4 + { "zpobjz04.bin", 0x200000, 0x3aec2f8d, BRF_GRA }, // 5 + + { "zpscrz06.bin", 0x200000, 0xe1e53cf0, BRF_GRA }, // 6 Layers + { "zpscrz05.bin", 0x200000, 0x0d7d4850, BRF_GRA }, // 7 + { "zpscrz07.bin", 0x200000, 0xbb178f32, BRF_GRA }, // 8 + { "zpscrz08.bin", 0x200000, 0x672f02e5, BRF_GRA }, // 9 + + { "zero_1.bin", 0x080000, 0xfd2384fa, BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(Zeropnt) +STD_ROM_FN(Zeropnt) + +static struct BurnRomInfo ZeropntaRomDesc[] = { + { "zpa2.bin", 0x080000, 0x285fbca3, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "zpa3.bin", 0x080000, 0xad7b3129, BRF_ESS | BRF_PRG }, // 1 + + { "zpobjz01.bin", 0x200000, 0x1f2768a3, BRF_GRA }, // 2 Sprites + { "zpobjz02.bin", 0x200000, 0xde34f33a, BRF_GRA }, // 3 + { "zpobjz03.bin", 0x200000, 0xd7a657f7, BRF_GRA }, // 4 + { "zpobjz04.bin", 0x200000, 0x3aec2f8d, BRF_GRA }, // 5 + + { "zpscrz06.bin", 0x200000, 0xe1e53cf0, BRF_GRA }, // 6 Layers + { "zpscrz05.bin", 0x200000, 0x0d7d4850, BRF_GRA }, // 7 + { "zpscrz07.bin", 0x200000, 0xbb178f32, BRF_GRA }, // 8 + { "zpscrz08.bin", 0x200000, 0x672f02e5, BRF_GRA }, // 9 + + { "zero_1.bin", 0x080000, 0xfd2384fa, BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(Zeropnta) +STD_ROM_FN(Zeropnta) + +static struct BurnRomInfo Zeropnt2RomDesc[] = { + { "d16-d31.4", 0x100000, 0x48314fdb, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "d0-d15.3", 0x100000, 0x5ec4151e, BRF_ESS | BRF_PRG }, // 1 + + { "db0db1zp.209", 0x400000, 0x474b460c, BRF_GRA }, // 2 Sprites + { "db2db3zp.210", 0x400000, 0x0a1d0a88, BRF_GRA }, // 3 + { "db4db5zp.211", 0x400000, 0x227169dc, BRF_GRA }, // 4 + { "db6db7zp.212", 0x400000, 0xa6306cdb, BRF_GRA }, // 5 + + { "a0-a1zp.205", 0x400000, 0xf7ca9c0e, BRF_GRA }, // 6 Layers + { "a2-a3zp.206", 0x400000, 0x0581c8fe, BRF_GRA }, // 7 + { "a4-a5zp.208", 0x400000, 0xddd091ef, BRF_GRA }, // 8 + { "a6-a7zp.207", 0x400000, 0x3fd46113, BRF_GRA }, // 9 + + { "uzp2-1.bin", 0x080000, 0xed0966ed, BRF_SND }, // 10 Samples (Oki 1) + + { "uzp2-2.bin", 0x040000, 0xdb8cb455, BRF_SND }, // 11 Samples (Oki 2) +}; + +STD_ROM_PICK(Zeropnt2) +STD_ROM_FN(Zeropnt2) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x100000; + MSM6295ROM = Next; Next += 0x040000; + DrvMSM6295ROMSrc = Next; Next += 0x080000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x014000; + DrvVideo0Ram = Next; Next += 0x004000; + DrvVideo1Ram = Next; Next += 0x004000; + DrvVideo2Ram = Next; Next += 0x004000; + DrvSpriteRam = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x008000; + + RamEnd = Next; + + DrvTiles = Next; Next += DrvNumTiles * 16 * 16; + DrvSprites = Next; Next += DrvNumSprites * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 Zeropnt2MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x200000; + MSM6295ROM = Next; Next += 0x140000; + DrvMSM6295ROMSrc = Next; Next += 0x080000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x024000; + DrvVideo0Ram = Next; Next += 0x004000; + DrvVideo1Ram = Next; Next += 0x004000; + DrvVideo2Ram = Next; Next += 0x004000; + DrvSpriteRam = Next; Next += 0x000800; + DrvPaletteRam = Next; Next += 0x008000; + DrvScrollRam = Next; Next += 0x000018; + + RamEnd = Next; + + DrvTiles = Next; Next += DrvNumTiles * 16 * 16; + DrvSprites = Next; Next += DrvNumSprites * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + BurnYM3812Reset(); + MSM6295Reset(0); + + DrvScrollX0 = 0; + DrvScrollY0 = 0; + DrvScrollX1 = 0; + DrvScrollY1 = 0; + DrvScrollX2 = 0; + DrvScrollY2 = 0; + DrvOkiBank = 0; + + return 0; +} + +static INT32 Zeropnt2DoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + DrvOkiBank = 0; + + return 0; +} + +UINT8 __fastcall Burglarx68KReadByte(UINT32 a) +{ + switch (a) { + case 0x800000: { + return 0xff - DrvInput[1]; + } + + case 0x800001: { + return 0xff - DrvInput[0]; + } + + case 0x800019: { + return 0xff - DrvInput[2]; + } + + case 0x80001a: { + return DrvDip[0]; + } + + case 0x80001c: { + return DrvDip[1]; + } + + case 0x800189: { + return MSM6295ReadStatus(0); + } + + case 0x80018c: { + return BurnYM3812Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Burglarx68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x800189: { + MSM6295Command(0, d); + return; + } + + case 0x80018a: { + BurnYM3812Write(1, d); + return; + } + + case 0x80018c: { + BurnYM3812Write(0, d); + return; + } + + case 0x80018e: { + DrvOkiBank = d & 1; + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Burglarx68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Burglarx68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x800030: { + // NOP??? + return; + } + + case 0x80010c: { + DrvScrollX0 = d & 0x3ff; + return; + } + + case 0x80010e: { + DrvScrollY0 = d & 0x3ff; + return; + } + + case 0x800110: { + DrvScrollY2 = d & 0x3ff; + return; + } + + case 0x800114: { + DrvScrollX2 = d & 0x3ff; + return; + } + + case 0x800116: { + DrvScrollX1 = d & 0x3ff; + return; + } + + case 0x800120: { + DrvScrollY1 = d & 0x3ff; + return; + } + + case 0x8001e0: { + // IRQ Ack??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Zeropnt68KReadByte(UINT32 a) +{ + switch (a) { + case 0x800018: { + return DrvInput[1]; + } + + case 0x800019: { + return DrvInput[0]; + } + + case 0x80001a: { + return DrvDip[0]; + } + + case 0x80001c: { + return DrvDip[1]; + } + + case 0x800170: { + INT32 y = BurnGunReturnY(1); + + y = 0x18 + ((y * 0xe0) / 0xff); + + return ((y & 0xff) ^ (GetCurrentFrame() & 1)); + } + + case 0x800174: { + INT32 x = BurnGunReturnX(1); + + x = x * 384 / 256; + if (x < 0x160) { + x = 0x30 + (x * 0xd0 / 0x15f); + } else { + x = ((x - 0x160) * 0x20) / 0x1f; + } + + return ((x & 0xff) ^ (GetCurrentFrame() & 1)); + } + + case 0x800178: { + INT32 y = BurnGunReturnY(0); + + y = 0x18 + ((y * 0xe0) / 0xff); + + return ((y & 0xff) ^ (GetCurrentFrame() & 1)); + } + + case 0x80017c: { + INT32 x = BurnGunReturnX(0); + + x = x * 384 / 256; + if (x < 0x160) { + x = 0x30 + (x * 0xd0 / 0x15f); + } else { + x = ((x - 0x160) * 0x20) / 0x1f; + } + + return ((x & 0xff) ^ (GetCurrentFrame() & 1)); + + } + + case 0x800189: { + return MSM6295ReadStatus(0); + } + + case 0x80018c: { + return BurnYM3812Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Zeropnt68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x800189: { + MSM6295Command(0, d); + return; + } + + case 0x80018a: { + BurnYM3812Write(1, d); + return; + } + + case 0x80018c: { + BurnYM3812Write(0, d); + return; + } + + case 0x80018e: { + DrvOkiBank = d & 1; + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + 0x20000 + (0x20000 * DrvOkiBank), 0x20000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Zeropnt68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Zeropnt68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x800030: { + // NOP??? + return; + } + + case 0x80010c: { + DrvScrollX0 = d & 0x3ff; + return; + } + + case 0x80010e: { + DrvScrollY0 = d & 0x3ff; + return; + } + + case 0x800110: { + DrvScrollY2 = d & 0x3ff; + return; + } + + case 0x800114: { + DrvScrollX2 = d & 0x3ff; + return; + } + + case 0x800116: { + DrvScrollX1 = d & 0x3ff; + return; + } + + case 0x800120: { + DrvScrollY1 = d & 0x3ff; + return; + } + + case 0x8001e0: { + // IRQ Ack??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Zeropnt268KReadByte(UINT32 a) +{ + switch (a) { + case 0x800019: { + return DrvInput[0]; + } + + case 0x800025: { + return MSM6295ReadStatus(0); + } + + case 0x80002d: { + return BurnYM2151ReadStatus(); + } + + case 0x800031: { + return MSM6295ReadStatus(1); + } + + case 0x800140: { + INT32 y = BurnGunReturnY(1); + + y = 0x18 + ((y * 0xe0) / 0xff); + + return ((y & 0xff) ^ (GetCurrentFrame() & 1)) + 0x08; + } + + case 0x800144: { + INT32 x = BurnGunReturnX(1); + + x = x * 384 / 256; + if (x < 0x160) { + x = 0x30 + (x * 0xd0 / 0x15f); + } else { + x = ((x - 0x160) * 0x20) / 0x1f; + } + + return ((x & 0xff) ^ (GetCurrentFrame() & 1)) - 0x08; + } + + case 0x800148: { + INT32 y = BurnGunReturnY(0); + + y = 0x18 + ((y * 0xe0) / 0xff); + + return ((y & 0xff) ^ (GetCurrentFrame() & 1)) + 0x08; + } + + case 0x80014c: { + INT32 x = BurnGunReturnX(0); + + x = x * 384 / 256; + if (x < 0x160) { + x = 0x30 + (x * 0xd0 / 0x15f); + } else { + x = ((x - 0x160) * 0x20) / 0x1f; + } + + return ((x & 0xff) ^ (GetCurrentFrame() & 1)) - 0x08; + } + + case 0x800150: { + return DrvDip[0]; + } + + case 0x800154: { + return DrvDip[1]; + } + + case 0x80015c: { + return DrvInput[1] | ((EEPROMRead() & 0x01) << 8); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Zeropnt268KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x800025: { + MSM6295Command(0, d); + return; + } + + case 0x800029: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x80002d: { + BurnYM2151WriteRegister(d); + return; + } + + case 0x800031: { + MSM6295Command(1, d); + return; + } + + case 0x800034: { + DrvOkiBank = (d & 3) % 4; + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + 0x20000 + (0x20000 * DrvOkiBank), 0x20000); + return; + } + + case 0x800039: { + // LEDs + return; + } + + case 0x8001f0: { + EEPROMWrite(d & 0x02, d & 0x01, d & 0x04); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Zeropnt268KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Zeropnt268KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x80010c: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[0] = d; + return; + } + + case 0x80010e: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[1] = d; + return; + } + + case 0x800110: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[2] = d; + return; + } + + case 0x800114: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[4] = d; + return; + } + + case 0x800116: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[5] = d; + return; + } + + case 0x800120: { + UINT16* ScrollRam = (UINT16*)DrvScrollRam; + ScrollRam[10] = d; + return; + } + + case 0x8001e0: { + // IRQ Ack??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT32 __fastcall Zeropnt268KReadLong(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Read long => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Zeropnt268KWriteLong(UINT32 a, UINT32 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write long => %06X, %08X\n"), a, d); + } + } +} + +static INT32 BurglarxSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / 16000000; +} + +static INT32 BurglarxTilePlaneOffsets[8] = { 0x1800008, 0x1800000, 0x1000008, 0x1000000, 0x0800008, 0x0800000, 0x0000008, 0x0000000 }; +static INT32 ZeropntTilePlaneOffsets[8] = { 0x3000008, 0x3000000, 0x2000008, 0x2000000, 0x1000008, 0x1000000, 0x0000008, 0x0000000 }; +static INT32 Zeropnt2TilePlaneOffsets[8] = { 0x6000008, 0x6000000, 0x4000008, 0x4000000, 0x2000008, 0x2000000, 0x0000008, 0x0000000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23 }; +static INT32 TileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 }; + +static INT32 BurglarxInit() +{ + INT32 nRet = 0, nLen; + + DrvNumTiles = 0x4000; + DrvNumSprites = 0x4000; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x400000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 11, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 13, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 14, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200001, 15, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 16, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 17, 2); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x400000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x4000, 8, 16, 16, BurglarxTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x400000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200001, 7, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300001, 9, 2); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x400000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x4000, 8, 16, 16, BurglarxTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 18, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvVideo1Ram , 0x904000, 0x907fff, SM_RAM); + SekMapMemory(DrvVideo2Ram , 0x908000, 0x90bfff, SM_RAM); + SekMapMemory(DrvVideo0Ram , 0x90c000, 0x90ffff, SM_RAM); + SekMapMemory(Drv68KRam + 0x10000 , 0x920000, 0x923fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x930000, 0x9307ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x940000, 0x947fff, SM_RAM); + SekMapMemory(Drv68KRam , 0xff0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, Burglarx68KReadWord); + SekSetWriteWordHandler(0, Burglarx68KWriteWord); + SekSetReadByteHandler(0, Burglarx68KReadByte); + SekSetWriteByteHandler(0, Burglarx68KWriteByte); + SekClose(); + + BurnYM3812Init(3579545, NULL, &BurglarxSynchroniseStream, 0); + BurnTimerAttachSekYM3812(16000000); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1056000 / 132, 100.0, 1); + + GenericTilesInit(); + + UnicoMakeInputsFunction = BurglarxMakeInputs; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 ZeropntInit() +{ + INT32 nRet = 0, nLen; + + DrvNumTiles = 0x8000; + DrvNumSprites = 0x8000; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x800000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x400000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x600000, 9, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x800000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x8000, 8, 16, 16, ZeropntTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x800000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x400000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x600000, 5, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x800000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x8000, 8, 16, 16, ZeropntTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 10, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvVideo1Ram , 0x904000, 0x907fff, SM_RAM); + SekMapMemory(DrvVideo2Ram , 0x908000, 0x90bfff, SM_RAM); + SekMapMemory(DrvVideo0Ram , 0x90c000, 0x90ffff, SM_RAM); + SekMapMemory(Drv68KRam + 0x10000 , 0x920000, 0x923fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x930000, 0x9307ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x940000, 0x947fff, SM_RAM); + SekMapMemory(Drv68KRam , 0xef0000, 0xefffff, SM_RAM); + SekSetReadWordHandler(0, Zeropnt68KReadWord); + SekSetWriteWordHandler(0, Zeropnt68KWriteWord); + SekSetReadByteHandler(0, Zeropnt68KReadByte); + SekSetWriteByteHandler(0, Zeropnt68KWriteByte); + SekClose(); + + BurnYM3812Init(3579545, NULL, &BurglarxSynchroniseStream, 0); + BurnTimerAttachSekYM3812(16000000); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1056000 / 132, 100.0, 1); + + GenericTilesInit(); + + BurnGunInit(2, true); + + UnicoMakeInputsFunction = ZeropntMakeInputs; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static const eeprom_interface zeropnt2_eeprom_interface = +{ + 7, // address bits 7 + 8, // data bits 8 + "*110", // read 1 10 aaaaaaa + "*101", // write 1 01 aaaaaaa dddddddd + "*111", // erase 1 11 aaaaaaa + "*10000xxxx", // lock 1 00 00xxxx + "*10011xxxx", // unlock 1 00 11xxxx + 0, + 0 +}; + +static INT32 Zeropnt2Init() +{ + INT32 nRet = 0, nLen; + + DrvNumTiles = 0x10000; + DrvNumSprites = 0x10000; + + // Allocate and Blank all required memory + Mem = NULL; + Zeropnt2MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Zeropnt2MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x1000000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x000000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x000001, 1, 2); if (nRet != 0) return 1; + + for (INT32 i = 0; i < 0x200000; i+= 4) { + INT32 t = Drv68KRom[i + 1]; + Drv68KRom[i + 1] = Drv68KRom[i + 2]; + Drv68KRom[i + 2] = t; + } + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x400000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x800000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc00000, 9, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x1000000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x10000, 8, 16, 16, Zeropnt2TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x1000000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x400000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x800000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc00000, 5, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x1000000; i++) { + DrvTempRom[i] ^= 0xff; + } + GfxDecode(0x10000, 8, 16, 16, Zeropnt2TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x100000, 11, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM + 0x000000, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68EC020); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(DrvVideo1Ram , 0x904000, 0x907fff, SM_RAM); + SekMapMemory(DrvVideo2Ram , 0x908000, 0x90bfff, SM_RAM); + SekMapMemory(DrvVideo0Ram , 0x90c000, 0x90ffff, SM_RAM); + SekMapMemory(Drv68KRam + 0x10000 , 0x920000, 0x923fff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0x930000, 0x9307ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x940000, 0x947fff, SM_RAM); + SekMapMemory(Drv68KRam , 0xfe0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, Zeropnt268KReadWord); + SekSetWriteWordHandler(0, Zeropnt268KWriteWord); + SekSetReadByteHandler(0, Zeropnt268KReadByte); + SekSetWriteByteHandler(0, Zeropnt268KWriteByte); + SekSetReadLongHandler(0, Zeropnt268KReadLong); + SekSetWriteLongHandler(0, Zeropnt268KWriteLong); + SekClose(); + + EEPROMInit(&zeropnt2_eeprom_interface); + + BurnYM2151Init(3579545, 25.0); + + MSM6295Init(0, 1056000 / 132, 100.0, 1); + MSM6295Init(1, 3960000 / 132, 100.0, 1); + + GenericTilesInit(); + + BurnGunInit(2, true); + + // Reset the driver + Zeropnt2DoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + + BurnYM3812Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + BurnGunExit(); + + DrvScrollX0 = 0; + DrvScrollY0 = 0; + DrvScrollX1 = 0; + DrvScrollY1 = 0; + DrvScrollX2 = 0; + DrvScrollY2 = 0; + DrvOkiBank = 0; + + DrvNumTiles = 0; + DrvNumSprites = 0; + + UnicoMakeInputsFunction = NULL; + + BurnFree(Mem); + + return 0; +} + +static INT32 Zeropnt2Exit() +{ + BurnYM2151Exit(); + MSM6295Exit(1); + + EEPROMExit(); + + return DrvExit(); +} + +static void DrvRenderSprites(INT32 PriorityDraw) +{ + for (INT32 Offset = 0; Offset < 0x400; Offset += 4) { + INT32 x, xStart, xEnd, xInc; + UINT16 *SpriteRam = (UINT16*)DrvSpriteRam; + + INT32 sx = SpriteRam[Offset + 0]; + INT32 sy = SpriteRam[Offset + 1]; + INT32 Code = SpriteRam[Offset + 2]; + INT32 Attr = SpriteRam[Offset + 3]; + + INT32 xFlip = Attr & 0x20; + INT32 yFlip = Attr & 0x40; + + INT32 xDim = ((Attr >> 8) & 0x0f) + 1; + INT32 Priority = ((Attr >> 12) & 0x03); + + if (Priority != PriorityDraw) continue; + + sx -= 0x3f; + sy -= 0x0e; + + sx = (sx & 0x1ff) - (sx & 0x200); + sy = (sy & 0x1ff) - (sy & 0x200); + + if (xFlip) { + xStart = sx + (xDim - 1) * 16; + xEnd = sx - 16; + xInc = -16; + } else { + xStart = sx; + xEnd = sx + (xDim * 16); + xInc = 16; + } + + for (x = xStart; x != xEnd; x += xInc) { + if (x > 16 && x < 368 && sy > 16 && sy < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } + } + } + } +} + +static void Zeropnt2RenderSprites(INT32 PriorityDraw) +{ + for (INT32 Offset = 0; Offset < 0x200; Offset += 2) { + INT32 x, xStart, xEnd, xInc; + UINT32 *SpriteRam = (UINT32*)DrvSpriteRam; + + INT32 sx = SpriteRam[Offset + 0] & 0xffff; + INT32 sy = SpriteRam[Offset + 0] >> 16; + INT32 Code = SpriteRam[Offset + 1] & 0xffff; + INT32 Attr = SpriteRam[Offset + 1] >> 16; + + INT32 xFlip = Attr & 0x20; + INT32 yFlip = Attr & 0x40; + + INT32 xDim = ((Attr >> 8) & 0x0f) + 1; + INT32 Priority = ((Attr >> 12) & 0x03); + + if (Priority != PriorityDraw) continue; + + sx -= 0x3f; + sy -= 0x0e; + + sx = (sx & 0x1ff) - (sx & 0x200); + sy = (sy & 0x1ff) - (sy & 0x200); + + if (xFlip) { + xStart = sx + (xDim - 1) * 16; + xEnd = sx - 16; + xInc = -16; + } else { + xStart = sx; + xEnd = sx + (xDim * 16); + xInc = 16; + } + + for (x = xStart; x != xEnd; x += xInc) { + if (x > 16 && x < 368 && sy > 16 && sy < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code++, x, sy, Attr & 0x1f, 8, 0, 0, DrvSprites); + } + } + } + } + } +} + +static void DrvRenderLayer(INT32 Layer) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 ScrollX = DrvScrollX0; + UINT16 ScrollY = DrvScrollY0; + UINT16 *VideoRam = (UINT16*)DrvVideo0Ram; + + if (Layer == 1) { + ScrollX = DrvScrollX1; + ScrollY = DrvScrollY1; + VideoRam = (UINT16*)DrvVideo1Ram; + } + + if (Layer == 2) { + ScrollX = DrvScrollX2; + ScrollY = DrvScrollY2; + VideoRam = (UINT16*)DrvVideo2Ram; + } + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[2 * TileIndex + 1]; + Code = VideoRam[2 * TileIndex + 0]; + Colour = Attr & 0x1f; + Flip = Attr >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 16 * mx; + y = 16 * my; + + x -= ScrollX; + y -= ScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 1024; + + y -= 15; + if (Layer == 0) x -= 0x32; + if (Layer == 1) x -= 0x30; + if (Layer == 2) x -= 0x2e; + + if (x > 16 && x < 368 && y > 16 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } + } + + TileIndex++; + } + } +} + +static void Zeropnt2RenderLayer(INT32 Layer) +{ + INT32 mx, my, Attr, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + UINT32 Code; + + UINT32 *VideoRam = (UINT32*)DrvVideo0Ram; + UINT32 *ScrollRam = (UINT32*)DrvScrollRam; + + UINT16 ScrollX = ScrollRam[0] & 0xffff; + UINT16 ScrollY = ScrollRam[0] >> 16; + + if (Layer == 1) { + ScrollX = ScrollRam[2] >> 16; + ScrollY = ScrollRam[5] & 0xffff; + VideoRam = (UINT32*)DrvVideo1Ram; + } + + if (Layer == 2) { + ScrollX = ScrollRam[2] & 0xffff; + ScrollY = ScrollRam[1] & 0xffff; + VideoRam = (UINT32*)DrvVideo2Ram; + } + + ScrollX &= 0x3ff; + ScrollY &= 0x3ff; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[TileIndex]; + Attr = Code >> 16; + Code &= 0xffff; + Colour = Attr & 0x1f; + Flip = Attr >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 16 * mx; + y = 16 * my; + + x -= ScrollX; + y -= ScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 1024; + + y -= 15; + if (Layer == 0) x -= 0x32; + if (Layer == 1) x -= 0x30; + if (Layer == 2) x -= 0x2e; + + if (Code) { + if (x > 16 && x < 368 && y > 16 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 8, 0, 0, DrvTiles); + } + } + } + } + + TileIndex++; + } + } +} + +static void DrvCalcPalette() +{ + UINT16 Data1, Data2; + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + + for (INT32 i = 0; i < 0x4000; i += 2) { + Data1 = PaletteRam[i & ~1]; + Data2 = PaletteRam[i | 1]; + + DrvPalette[i >> 1] = BurnHighCol((Data1 >> 8) & 0xfc, (Data1 >> 0) & 0xfc, (Data2 >> 8) & 0xfc, 0); + } +} + +static void Zeropnt2CalcPalette() +{ + UINT32 *PaletteRam = (UINT32*)DrvPaletteRam; + UINT32 rgb0; + + for (INT32 i = 0; i < 0x2000; i++) { + rgb0 = PaletteRam[i]; + + DrvPalette[i] = BurnHighCol((rgb0 >> 8) & 0xfc, (rgb0 >> 0) & 0xfc, (rgb0 >> 24) & 0xfc, 0); + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x1f00; + } + + DrvRenderLayer(0); + DrvRenderSprites(0); + DrvRenderLayer(1); + DrvRenderSprites(1); + DrvRenderLayer(2); + DrvRenderSprites(2); + DrvRenderSprites(3); + + BurnTransferCopy(DrvPalette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static void Zeropnt2Draw() +{ + BurnTransferClear(); + Zeropnt2CalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x1f00; + } + + Zeropnt2RenderSprites(3); + Zeropnt2RenderLayer(0); + Zeropnt2RenderSprites(2); + Zeropnt2RenderLayer(1); + Zeropnt2RenderSprites(1); + Zeropnt2RenderLayer(2); + Zeropnt2RenderSprites(0); + + BurnTransferCopy(DrvPalette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) DrvDoReset(); + + UnicoMakeInputsFunction(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesDone[0] = 0; + + SekNewFrame(); + + SekOpen(0); + BurnTimerEndFrameYM3812(nCyclesTotal[0]); + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + SekClose(); + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 Zeropnt2Frame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) Zeropnt2DoReset(); + + Zeropnt2MakeInputs(); + + nCyclesTotal[0] = 16000000 / 60; + nCyclesDone[0] = 0; + + SekNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 9) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) Zeropnt2Draw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029691; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + MSM6295Scan(0, nAction); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(DrvOkiBank); + } + + return 0; +} + +static INT32 BurglarxScan(INT32 nAction, INT32 *pnMin) +{ + DrvScan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + BurnYM3812Scan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + } + + return 0; +} + +static INT32 ZeropntScan(INT32 nAction, INT32 *pnMin) +{ + DrvScan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + BurnYM3812Scan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + 0x20000 + (0x20000 * DrvOkiBank), 0x20000); + } + + return 0; +} + +static INT32 Zeropnt2Scan(INT32 nAction, INT32 *pnMin) +{ + DrvScan(nAction, pnMin); + + EEPROMScan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + BurnYM2151Scan(nAction); + MSM6295Scan(1, nAction); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x20000, DrvMSM6295ROMSrc + 0x20000 + (0x20000 * DrvOkiBank), 0x20000); + } + + return 0; +} + +struct BurnDriver BurnDrvBurglarx = { + "burglarx", NULL, NULL, NULL, "1997", + "Burglar X\0", NULL, "Unico", "Unico", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, BurglarxRomInfo, BurglarxRomName, NULL, NULL, BurglarxInputInfo, BurglarxDIPInfo, + BurglarxInit, DrvExit, DrvFrame, NULL, BurglarxScan, + NULL, 0x2000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvZeropnt = { + "zeropnt", NULL, NULL, NULL, "1998", + "Zero Point (set 1)\0", NULL, "Unico", "Unico", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, ZeropntRomInfo, ZeropntRomName, NULL, NULL, ZeropntInputInfo, ZeropntDIPInfo, + ZeropntInit, DrvExit, DrvFrame, NULL, ZeropntScan, + NULL, 0x2000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvZeropnta = { + "zeropnta", "zeropnt", NULL, NULL, "1998", + "Zero Point (set 2)\0", NULL, "Unico", "Unico", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, ZeropntaRomInfo, ZeropntaRomName, NULL, NULL, ZeropntInputInfo, ZeropntDIPInfo, + ZeropntInit, DrvExit, DrvFrame, NULL, ZeropntScan, + NULL, 0x2000, 384, 224, 4, 3 +}; + +struct BurnDriver BurnDrvZeropnt2 = { + "zeropnt2", NULL, NULL, NULL, "1999", + "Zero Point 2\0", NULL, "Unico", "Unico", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SHOOT, 0, + NULL, Zeropnt2RomInfo, Zeropnt2RomName, NULL, NULL, ZeropntInputInfo, Zeropnt2DIPInfo, + Zeropnt2Init, Zeropnt2Exit, Zeropnt2Frame, NULL, Zeropnt2Scan, + NULL, 0x2000, 384, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_vmetal.cpp b/src/burn/drivers/misc_post90s/d_vmetal.cpp new file mode 100644 index 00000000..fe2d85cb --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_vmetal.cpp @@ -0,0 +1,706 @@ +// FB Alpha Varia Metal driver module +// Based on MAME driver by + +// There is a bug in the background scrolling of some levels +// Also a bug in sprite drawing, flipped case? (see special shot) + +#include "tiles_generic.h" +#include "msm6295.h" +#include "es8712.h" + +static UINT8 *AllMem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *AllRam = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KROM = NULL; +static UINT8 *DrvGfxROM = NULL; +static UINT8 *DrvSndROM0 = NULL; +static UINT8 *DrvSndROM1 = NULL; +static UINT8 *Drv68KRAM = NULL; +static UINT8 *DrvPalRAM = NULL; +static UINT8 *DrvSprRAM = NULL; +static UINT8 *DrvTXTRAM = NULL; +static UINT8 *DrvMD1RAM = NULL; +static UINT8 *DrvMD2RAM = NULL; +static UINT8 *DrvTLUTRAM = NULL; +static UINT8 *DrvVidRegs = NULL; + +static UINT16 *DrvPriBmp = NULL; + +static UINT32 *DrvPalette = NULL; +static UINT8 DrvRecalc; + +static INT32 blackpen = 0; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo vmetalInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 15, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 8, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 9, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 10, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 11, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 3, "service" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 4, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy2 + 2, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(vmetal) + +static struct BurnDIPInfo vmetalDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x16, 0x01, 0x07, 0x05, "3 Coins 1 Credits" }, + {0x16, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x07, 0x04, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x07, 0x03, "1 Coin 3 Credits" }, + {0x16, 0x01, 0x07, 0x02, "1 Coin 4 Credits" }, + {0x16, 0x01, 0x07, 0x01, "1 Coin 5 Credits" }, + {0x16, 0x01, 0x07, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x10, 0x10, "Off" }, + {0x16, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x03, "Normal" }, + {0x17, 0x01, 0x03, 0x01, "Hard" }, + {0x17, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x17, 0x01, 0x0c, 0x08, "1" }, + {0x17, 0x01, 0x0c, 0x04, "2" }, + {0x17, 0x01, 0x0c, 0x0c, "3" }, + {0x17, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x17, 0x01, 0x10, 0x10, "Every 30000" }, + {0x17, 0x01, 0x10, 0x00, "Every 60000" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x80, 0x80, "Off" }, + {0x17, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(vmetal) + +void __fastcall vmetal_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x400001: + case 0x400003: + MSM6295Command(0, data); + return; + } + + if ((address & 0xfffffff0) == 0x500000) { + es8712Write(0, (address/2) & 0x07, data); + return; + } +} + +void __fastcall vmetal_write_word(UINT32 address, UINT16 data) +{ + if (address == 0x200000) { + if ((data & 0x40) == 0) + es8712Reset(0); + else + es8712Play(0); + + if (data & 0x10) + es8712SetBankBase(0, 0x100000); + else + es8712SetBankBase(0, 0x000000); + } +} + +#define read_dip(dip) (((DrvDips[0] & (1 << (dip-1))) ? 0x40 : 0) | ((DrvDips[1] & (1 << (dip-1))) ? 0x80 : 0)) + +UINT8 __fastcall vmetal_read_byte(UINT32 address) +{ + switch (address) + { + case 0x400001: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT16 __fastcall vmetal_read_word(UINT32 address) +{ + switch (address) + { + case 0x200000: + return DrvInputs[0]; + + case 0x200002: + return DrvInputs[1]; + + case 0x31fefe: + return read_dip(8); + + case 0x31ff7e: + return read_dip(7); + + case 0x31ffbe: + return read_dip(6); + + case 0x31ffde: + return read_dip(5); + + case 0x31ffee: + return read_dip(4); + + case 0x31fff6: + return read_dip(3); + + case 0x31fffa: + return read_dip(2); + + case 0x31fffc: + return read_dip(1); + } + + if ((address & 0xffff0000) == 0x160000) { + UINT16 *vreg = (UINT16*)DrvVidRegs; + + INT32 offset = ((address & 0xfffe) | ((vreg[0x0ab/2] & 0x7f) << 16)) * 2; + + return (DrvGfxROM[offset + 0] << 12) | (DrvGfxROM[offset + 1] << 8) | (DrvGfxROM[offset + 2] << 4) | (DrvGfxROM[offset + 3] << 0); + } + + return 0; +} + +static inline void palette_write(INT32 offset) +{ + if (offset & 0x2000) { + INT32 rgb = *((UINT16*)(DrvPalRAM + offset)); + + if (rgb == 0) blackpen = offset/2; + + UINT8 g = (rgb >> 11); + UINT8 r = (rgb >> 6) & 0x1f; + UINT8 b = (rgb >> 1) & 0x1f; + + DrvPalette[(offset/2)&0xfff] = BurnHighCol((r << 3) | (r >> 5), (g << 3) | (g >> 5), (b << 3) | (b >> 5), 0); + } +} + +void __fastcall vmetal_palette_write_byte(UINT32 address, UINT8 data) +{ + DrvPalRAM[(address & 0x3fff)^1] = data; + + palette_write(address & 0x3ffe); +} + +void __fastcall vmetal_palette_write_word(UINT32 address, UINT16 data) +{ + *((UINT16*)(DrvPalRAM + (address & 0x3ffe))) = data; + + palette_write(address & 0x3ffe); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + es8712Reset(0); + MSM6295Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x100000; + + DrvGfxROM = Next; Next += 0x800000 * 2; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x100000; + DrvSndROM1 = Next; Next += 0x200000; + + DrvPalette = (UINT32*)Next; Next += 0x1000 * sizeof(UINT32); + + DrvPriBmp = (UINT16*)Next; Next += 320 * 224 * sizeof(UINT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + + DrvPalRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x004000; + + DrvTXTRAM = Next; Next += 0x020000; + DrvMD1RAM = Next; Next += 0x020000; + DrvMD2RAM = Next; Next += 0x020000; + + DrvTLUTRAM = Next; Next += 0x000800; + DrvVidRegs = Next; Next += 0x001000; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void expand_gfx() +{ + for (INT32 i = 0; i < 0x800000; i+=8) { // properly interleave graphics + for (INT32 j = 0; j < 8; j++) { + DrvGfxROM[0x800000+j] = DrvGfxROM[i + ((j & 1) << 2) + ((j & 6) >> 1)]; + } + + memcpy (DrvGfxROM + i, DrvGfxROM + 0x800000, 8); + } + + for (INT32 i = 0x1000000-1; i >= 0; i--) { // unpack 4bpp pixel data + DrvGfxROM[i] = (DrvGfxROM[i/2] >> ((i & 1) << 2)) & 0x0f; + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000000, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000001, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000002, 2, 4)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x000003, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x000001, 5, 4)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 7, 1)) return 1; + + expand_gfx(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(DrvTXTRAM, 0x100000, 0x11ffff, SM_RAM); + SekMapMemory(DrvMD1RAM, 0x120000, 0x13ffff, SM_RAM); + SekMapMemory(DrvMD2RAM, 0x140000, 0x15ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x170000, 0x173fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x174000, 0x177fff, SM_RAM); + SekMapMemory(DrvTLUTRAM, 0x178000, 0x1787ff, SM_RAM); + SekMapMemory(DrvVidRegs, 0x178800, 0x1797ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, vmetal_write_byte); + SekSetWriteWordHandler(0, vmetal_write_word); + SekSetReadByteHandler(0, vmetal_read_byte); + SekSetReadWordHandler(0, vmetal_read_word); + + SekMapHandler(1, 0x170000, 0x173fff, SM_WRITE); + SekSetWriteByteHandler(1, vmetal_palette_write_byte); + SekSetWriteWordHandler(1, vmetal_palette_write_word); + SekClose(); + + es8712Init(0, DrvSndROM1, 12000 / 60 /* Rate / FPS */, 50.0, 0); + + MSM6295Init(0, 1320000 / 132, 75.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + es8712Exit(0); + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void draw_layer_8x8() +{ + UINT16 *vram = (UINT16*)DrvTXTRAM; + UINT16 *vlut = (UINT16*)DrvTLUTRAM; + + for (INT32 y = 0; y < 224 / 8; y++) { + for (INT32 x = 0; x < 320 / 8; x++) { + INT32 offs = (y << 8) | x; + + INT32 sx = x << 3; + INT32 sy = y << 3; + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 data = vram[offs]; + if (data & 0x8000) continue; + + INT32 index = (data & 0x7ff0) >> 3; + UINT32 lut = (vlut[index] << 16) | (vlut[index + 1]); + + INT32 code = (data & 0x0f) | (lut & 0x3fff0); + INT32 color = (lut >> 20) & 0x1f; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0xe00, DrvGfxROM); + } + } +} + +static void draw_layer_16x16(UINT8 *ram, INT32 scrolloff) +{ + UINT16 *vram = (UINT16*)ram; + UINT16 *vlut = (UINT16*)DrvTLUTRAM; + UINT16 *scrl = (UINT16*)(DrvVidRegs + 0x6a + scrolloff); + + for (INT32 offs = 0; offs < 256 * 256; offs++) + { + INT32 sx = (offs & 0xff) << 4; + INT32 sy = (offs >> 8) << 4; + + sx -= scrl[0] & 0xfff; + if (sx < -15) sx += 0x1000; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 data = vram[offs]; + if (data & 0x8000) continue; + + INT32 index = (data & 0x7ff0) >> 3; + + UINT32 lu = (vlut[index] << 16) | (vlut[index + 1] << 0); + + INT32 code = (data & 0x0f) | ((lu >> 2) & 0xfff0); + INT32 color = (lu >> 20) & 0xff; + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM); + } +} + +static void RenderZoomedPriorityTile(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 t, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 width, INT32 height, INT32 zoomx, INT32 zoomy, INT32 prio) +{ + INT32 h = ((zoomy << 4) + 0x8000) >> 16; + INT32 w = ((zoomx << 4) + 0x8000) >> 16; + + if (!h || !w || sx + w < 0 || sy + h < 0 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + if (fy) fy = (height-1)*width; + if (fx) fy |= (width-1); + + INT32 hz = (height << 12) / h; + INT32 wz = (width << 12) / w; + + INT32 starty = 0, startx = 0, endy = h, endx = w; + if (sy < 0) starty = 0 - sy; + if (sx < 0) startx = 0 - sx; + if (sy + h >= nScreenHeight) endy -= (h + sy) - nScreenHeight; + if (sx + w >= nScreenWidth ) endx -= (w + sx) - nScreenWidth; + + UINT8 *src = gfx + (code * width * height); + UINT16 *dst = dest + (sy + starty) * nScreenWidth + sx; + UINT16 *pri = DrvPriBmp + (sy + starty) * nScreenWidth + sx; + + for (INT32 y = starty; y < endy; y++) + { + INT32 zy = ((y * hz) >> 12) * width; + + for (INT32 x = startx; x < endx; x++) + { + INT32 pxl = src[(zy + ((x * wz) >> 12)) ^ fy]; + + if (pxl != t) { + if ((pri[x] & prio) == 0) { + dst[x] = pxl | color; + pri[x] = prio; + } + } + } + + dst += nScreenWidth; + pri += nScreenWidth; + } +} + +static void draw_sprites() // metro_draw_sprites +{ + UINT16 *videoregs = (UINT16*)(DrvVidRegs + 0xf00); + UINT16 *spriteram = (UINT16*)DrvSprRAM; + UINT8 *gfx_max = DrvGfxROM + 0x1000000; + + INT32 sprites = videoregs[0x00] & 0x1ff; + if (sprites == 0) return; + + INT32 color_start = (videoregs[0x04] & 0x0f) << 4; + + static const INT32 primask[4] = { 0x0000, 0xff00, 0xfff0, 0xfffc }; + + static const INT32 zoomtable[0x40] = { + 0xAAC,0x800,0x668,0x554,0x494,0x400,0x390,0x334, + 0x2E8,0x2AC,0x278,0x248,0x224,0x200,0x1E0,0x1C8, + 0x1B0,0x198,0x188,0x174,0x164,0x154,0x148,0x13C, + 0x130,0x124,0x11C,0x110,0x108,0x100,0x0F8,0x0F0, + 0x0EC,0x0E4,0x0DC,0x0D8,0x0D4,0x0CC,0x0C8,0x0C4, + 0x0C0,0x0BC,0x0B8,0x0B4,0x0B0,0x0AC,0x0A8,0x0A4, + 0x0A0,0x09C,0x098,0x094,0x090,0x08C,0x088,0x080, + 0x078,0x070,0x068,0x060,0x058,0x050,0x048,0x040 + }; + + UINT16 *src; + INT32 inc; + + for (INT32 i = 0; i < 0x20; i++) + { + if (videoregs[0x02/2] & 0x8000) + { + src = spriteram; + inc = (8 / 2); + } else { + src = spriteram + (sprites - 1) * (8 / 2); + inc = -(8 / 2); + } + + for (INT32 j = 0; j < sprites; j++) + { + INT32 x = src[0]; + INT32 curr_pri = (x & 0xf800) >> 11; + + if ((curr_pri == 0x1f) || (curr_pri != i)) + { + src += inc; + continue; + } + + INT32 pri = (videoregs[0x01] & 0x0300) >> 8; + + if (!(videoregs[0x01] & 0x8000)) + { + if (curr_pri > (videoregs[0x01] & 0x001f)) + pri = (videoregs[0x01] & 0x0c00) >> 10; + } + + INT32 y = src[1]; + INT32 attr = src[2]; + INT32 code = src[3]; + + INT32 flipx = attr & 0x8000; + INT32 flipy = attr & 0x4000; + INT32 color = (attr & 0x00f0) >> 4; + + INT32 width = (((attr >> 11) & 0x7) + 1) * 8; + INT32 height = (((attr >> 8) & 0x7) + 1) * 8; + + INT32 zoom = zoomtable[(y & 0xfc00) >> 10] << 8; + + x = (x & 0x07ff)-64; + y = (y & 0x03ff)-64; + + UINT8 *gfxdata = DrvGfxROM + (32 * (((attr & 0x000f) << 16) + code))*2; + + if ((gfxdata + (width / 2 * height - 1)*2) >= gfx_max) + continue; + + RenderZoomedPriorityTile(pTransDraw, gfxdata, 0, (color + color_start)<<4, 15, x, y, flipx, flipy, width, height, (zoom*width) >> 4, (zoom*height)>>4, primask[pri]); + + src += inc; + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0x2000; i < 0x4000; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = blackpen; + DrvPriBmp[i] = 0; + } + + draw_layer_16x16(DrvMD1RAM, 0x10); + draw_layer_16x16(DrvMD2RAM, 0x00); + draw_sprites(); + draw_layer_8x8(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nTotalCycles = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + + SekOpen(0); + SekRun(nTotalCycles); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (pBurnSoundOut) { + es8712Update(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029708; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + es8712Scan(0, nAction); + MSM6295Scan(0, nAction); + + SCAN_VAR(blackpen); + + DrvRecalc = 1; + } + + return 0; +} + + +// Varia Metal + +static struct BurnRomInfo vmetalRomDesc[] = { + { "5b.u19", 0x080000, 0x4933ac6c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "6b.u18", 0x080000, 0x4eb939d5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.u29", 0x200000, 0xb470c168, 2 | BRF_GRA }, // 2 8x8, 16x16, and Sprite tiles + { "2.u31", 0x200000, 0xb36f8d60, 2 | BRF_GRA }, // 3 + { "3.u28", 0x200000, 0x00fca765, 2 | BRF_GRA }, // 4 + { "4.u30", 0x200000, 0x5a25a49c, 2 | BRF_GRA }, // 5 + + { "8.u9", 0x080000, 0xc14c001c, 3 | BRF_SND }, // 6 OKI MSM6295 Samples + + { "7.u12", 0x200000, 0xa88c52f1, 4 | BRF_SND }, // 7 ES8712 Samples +}; + +STD_ROM_PICK(vmetal) +STD_ROM_FN(vmetal) + +struct BurnDriver BurnDrvVmetal = { + "vmetal", NULL, NULL, NULL, "1995", + "Varia Metal\0", "Imperfect graphics", "Excellent System", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, vmetalRomInfo, vmetalRomName, NULL, NULL, vmetalInputInfo, vmetalDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 320, 3, 4 +}; + + +// Varia Metal (New Ways Trading Co.) + +static struct BurnRomInfo vmetalnRomDesc[] = { + { "vm5.bin", 0x080000, 0x43ef844e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "vm6.bin", 0x080000, 0xcb292ab1, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.u29", 0x200000, 0xb470c168, 2 | BRF_GRA }, // 2 8x8, 16x16, and Sprite tiles + { "2.u31", 0x200000, 0xb36f8d60, 2 | BRF_GRA }, // 3 + { "3.u28", 0x200000, 0x00fca765, 2 | BRF_GRA }, // 4 + { "4.u30", 0x200000, 0x5a25a49c, 2 | BRF_GRA }, // 5 + + { "8.u9", 0x080000, 0xc14c001c, 3 | BRF_SND }, // 6 OKI MSM6295 Samples + + { "7.u12", 0x200000, 0xa88c52f1, 4 | BRF_SND }, // 7 ES8712 Samples +}; + +STD_ROM_PICK(vmetaln) +STD_ROM_FN(vmetaln) + +struct BurnDriver BurnDrvVmetaln = { + "vmetaln", "vmetal", NULL, NULL, "1995", + "Varia Metal (New Ways Trading Co.)\0", "Imperfect graphics", "Excellent System (New Ways Trading Co. license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, + NULL, vmetalnRomInfo, vmetalnRomName, NULL, NULL, vmetalInputInfo, vmetalDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_post90s/d_welltris.cpp b/src/burn/drivers/misc_post90s/d_welltris.cpp new file mode 100644 index 00000000..862c7888 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_welltris.cpp @@ -0,0 +1,962 @@ +// FB Alpha Welltris driver module +// Based on MAME driver David Haywood + +#include "tiles_generic.h" +#include "burn_ym2610.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvPxlRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *pending_command; + +static UINT8 *flipscreen; +static UINT8 *sound_bank; +static UINT8 *gfx_bank; +static UINT8 *spritepalbank; +static UINT8 *pixelpalbank; +static UINT8 *charpalbank; + +static UINT16 *scroll; + +static UINT8 DrvInputs[6]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvJoy6[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static INT32 screen_y_offset; + +static struct BurnInputInfo WelltrisInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + +/* {"P3 Coin", BIT_DIGITAL, DrvJoy6 + 0, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy6 + 2, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy4 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy4 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy4 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy4 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p3 fire 2" }, + + {"P4 Coin", BIT_DIGITAL, DrvJoy6 + 1, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, DrvJoy6 + 3, "p4 start" }, + {"P4 Up", BIT_DIGITAL, DrvJoy5 + 0, "p4 up" }, + {"P4 Down", BIT_DIGITAL, DrvJoy5 + 1, "p4 down" }, + {"P4 Left", BIT_DIGITAL, DrvJoy5 + 2, "p4 left" }, + {"P4 Right", BIT_DIGITAL, DrvJoy5 + 3, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, DrvJoy5 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, DrvJoy5 + 5, "p4 fire 2" },*/ + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Test", BIT_DIGITAL, DrvJoy1 + 4, "diag" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, +// {"Tilt", BIT_DIGITAL, DrvJoy1 + 5, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Welltris) + +static struct BurnInputInfo Quiz18kInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Quiz18k) + +static struct BurnDIPInfo WelltrisDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x06, "5 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x0f, 0x04, "2-1, 4-2, 5-3, 6-4" }, + {0x13, 0x01, 0x0f, 0x03, "2-1, 4-3" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x0f, 0x01, "1-1, 2-2, 3-3, 4-5" }, + {0x13, 0x01, 0x0f, 0x02, "1-1, 2-2, 3-3, 4-4, 5-6" }, + {0x13, 0x01, 0x0f, 0x00, "1-1, 2-3" }, + {0x13, 0x01, 0x0f, 0x05, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0xf0, 0x60, "5 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xf0, 0x40, "2-1, 4-2, 5-3, 6-4" }, + {0x13, 0x01, 0xf0, 0x30, "2-1, 4-3" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xf0, 0x10, "1-1, 2-2, 3-3, 4-5" }, + {0x13, 0x01, 0xf0, 0x20, "1-1, 2-2, 3-3, 4-4, 5-6" }, + {0x13, 0x01, 0xf0, 0x00, "1-1, 2-3" }, + {0x13, 0x01, 0xf0, 0x50, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x14, 0x01, 0x04, 0x04, "Mono Player" }, + {0x14, 0x01, 0x04, 0x00, "Many Player" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + +// {0 , 0xfe, 0 , 2, "DIPSW 2-5 (see notes)" }, +// {0x14, 0x01, 0x10, 0x10, "Off" }, +// {0x14, 0x01, 0x10, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "4 Players Mode" }, +// {0x14, 0x01, 0x30, 0x30, "Off" }, +// {0x14, 0x01, 0x30, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Welltris) + +static struct BurnDIPInfo Quiz18kDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xfd, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Title Logo Type" }, + {0x15, 0x01, 0x20, 0x20, "1" }, + {0x15, 0x01, 0x20, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Quiz18k) + +inline void WelltrisClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static void cpu_sync() +{ + UINT32 cycles = (SekTotalCycles() * 2) - (ZetTotalCycles() * 5); + + if (cycles > 5) { + BurnTimerUpdate(cycles / 5); + } +} + +static inline void sprite_hack(INT32 offset) +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + if (offset == 0x3fc) { + if (ram[0x1fc] == 0 && ram[0x1fd] == 0 && ram[0x1ff] == 0) { + memset (DrvSprRAM, 0, 0x3fc); + } + } +} + +static inline void palette_write(INT32 offset) +{ + UINT16 p = *((UINT16*)(DrvPalRAM + offset)); + + INT32 r = (p >> 10) & 0x1f; + INT32 g = (p >> 5) & 0x1f; + INT32 b = (p >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[offset / 2] = BurnHighCol(r, g, b, 0); +} + +void __fastcall welltris_main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffffc00) == 0xffc000) { + DrvSprRAM[(address & 0x3ff) ^ 1] = data; + sprite_hack(address & 0x3fe); + return; + } + + if ((address & 0xfffff000) == 0xffe000) { + DrvPalRAM[(address & 0xfff) ^ 1] = data; + palette_write(address & 0xffe); + return; + } + + switch (address) + { + case 0xfff001: + *charpalbank = data & 0x03; + *pixelpalbank =(data & 0x08) >> 3; + *spritepalbank =(data & 0x20) >> 5; + *flipscreen = data & 0x80; + return; + + case 0xfff003: + gfx_bank[0] = data >> 4; + gfx_bank[1] = data & 0x0f; + return; + + case 0xfff009: + cpu_sync(); + *pending_command = 0x80; + *soundlatch = data; + ZetNmi(); + return; + } +} + +void __fastcall welltris_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffffc00) == 0xffc000) { + *((UINT16*)(DrvSprRAM + (address & 0x3fe))) = data; + sprite_hack(address & 0x3fe); + return; + } + + if ((address & 0xfffff000) == 0xffe000) { + *((UINT16*)(DrvPalRAM + (address & 0xffe))) = data; + palette_write(address & 0xffe); + return; + } + + switch (address) + { + case 0xfff004: + scroll[0] = data - 14; + return; + + case 0xfff006: + scroll[1] = data; + return; + } +} + +UINT8 __fastcall welltris_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0xfff001: + return ~DrvInputs[1]; + + case 0xfff003: + return ~DrvInputs[2]; + + case 0xfff005: + return ~DrvInputs[3]; + + case 0xfff007: + return ~DrvInputs[4]; + + case 0xfff009: + cpu_sync(); + return (DrvInputs[0] & 0x7f) | *pending_command; + + case 0xfff00b: + return ~DrvInputs[5]; + + case 0xfff00d: + return DrvDips[0]; + + case 0xfff00f: + return DrvDips[1]; + } + + return 0; +} + +UINT16 __fastcall welltris_main_read_word(UINT32 ) +{ + return 0; +} + +static void bankswitch(INT32 data) +{ + sound_bank[0] = data; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + (data & 0x03) * 0x8000); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + (data & 0x03) * 0x8000); +} + +void __fastcall welltris_sound_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + bankswitch(data); + return; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + BurnYM2610Write(port & 3, data); + return; + + case 0x18: + *pending_command = 0; + return; + } +} + +UINT8 __fastcall welltris_sound_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x08: + return BurnYM2610Read(0); + + case 0x0a: + return BurnYM2610Read(2); + + case 0x10: + return *soundlatch; + } + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2610Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x180000; + DrvZ80ROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x300000; + DrvGfxROM1 = Next; Next += 0x200000; + + DrvSndROM0 = Next; Next += 0x080000; + DrvSndROM1 = Next; Next += 0x100000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x001000; + DrvSprRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x001000; + DrvPxlRAM = Next; Next += 0x020000; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + pending_command = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + sound_bank = Next; Next += 0x000001; + + gfx_bank = Next; Next += 0x000002; + + charpalbank = Next; Next += 0x000001; + spritepalbank = Next; Next += 0x000001; + pixelpalbank = Next; Next += 0x000001; + + scroll = (UINT16*)Next; Next += 0x000002 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvGfxExpand(UINT8 *gfx, INT32 len) // gfx0 - 0, gfx1 - 600 +{ + for (INT32 i = len - 1; i >= 0; i--) { + gfx[i * 2 + 1] = gfx[i] >> 4; + gfx[i * 2 + 0] = gfx[i] & 0x0f; + } +} + +static void DrvFixSprites() +{ + for (INT32 i = 0; i < 0x100000; i+=4) { + INT32 t = DrvGfxROM1[i + 1]; + DrvGfxROM1[i + 1] = DrvGfxROM1[i + 2]; + DrvGfxROM1[i + 2] = t; + } +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + screen_y_offset = (strncmp(BurnDrvGetTextA(DRV_NAME), "welltris", 8) == 0) ? 8 : 0; + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x100001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x100000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 4, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0, 5, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvSndROM1 + 0x80000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x00001, 9, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 10, 1)) return 1; + + if (screen_y_offset == 0) { + if (BurnLoadRom(DrvGfxROM0 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x100000, 12, 1)) return 1; + } else { + // welltris 4 player hack (change ori 0030 to 0000 + *((UINT16 *)(Drv68KROM + 0xB91E)) = 0x0000; + } + + DrvFixSprites(); + DrvGfxExpand(DrvGfxROM0, 0x180000); + DrvGfxExpand(DrvGfxROM1, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM + 0x000000, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KROM + 0x100000, 0x100000, 0x17ffff, SM_ROM); + SekMapMemory(DrvPxlRAM, 0x800000, 0x81ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff8000, 0xffbfff, SM_RAM); + SekMapMemory(DrvSprRAM, 0xffc000, 0xffc3ff, SM_ROM); + SekMapMemory(DrvVidRAM, 0xffd000, 0xffdfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xffe000, 0xffefff, SM_ROM); + SekSetWriteByteHandler(0, welltris_main_write_byte); + SekSetWriteWordHandler(0, welltris_main_write_word); + SekSetReadByteHandler(0, welltris_main_read_byte); + SekSetReadWordHandler(0, welltris_main_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x77ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x77ff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetSetOutHandler(welltris_sound_write_port); + ZetSetInHandler(welltris_sound_read_port); + ZetMemEnd(); + ZetClose(); + + INT32 DrvSndROMLen1 = 0x100000; + INT32 DrvSndROMLen0 = 0x080000; + + BurnYM2610Init(8000000, DrvSndROM1, &DrvSndROMLen1, DrvSndROM0, &DrvSndROMLen0, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + BurnYM2610SetSoundMixMode(1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM2610Exit(); + BurnYM2610SetSoundMixMode(0); + + ZetExit(); + SekExit(); + + BurnFree(AllMem); + + return 0; +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + static const UINT8 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; + + for (INT32 offs = 0; offs < 0x200 - 4; offs += 4) { + INT32 data0 = ram[offs + 0]; + INT32 data1 = ram[offs + 1]; + INT32 data2 = ram[offs + 2]; + INT32 data3 = ram[offs + 3]; + + INT32 code = data3 & 0x1fff; + INT32 color = (data2 & 0x0f) + (0x10 * *spritepalbank) + 0x60; + INT32 y = (data0 & 0x1ff) + 1 - screen_y_offset; + INT32 x = (data1 & 0x1ff) + 6 - 15; + INT32 yzoom = (data0 >> 12) & 15; + INT32 xzoom = (data1 >> 12) & 15; + INT32 zoomed = (xzoom | yzoom); + INT32 ytiles = ((data2 >> 12) & 7) + 1; + INT32 xtiles = ((data2 >> 8) & 7) + 1; + INT32 yflip = (data2 >> 15) & 1; + INT32 xflip = (data2 >> 11) & 1; + INT32 xt, yt; + + if (!(ram[offs + 2] & 0x0080)) continue; + + xzoom = 16 - zoomtable[xzoom] / 8; + yzoom = 16 - zoomtable[yzoom] / 8; + + if (x >= 0x200) x -= 0x200; + if (y >= 0x200) y -= 0x200; + + if (!xflip && !yflip) { + for (yt = 0; yt < ytiles; yt++) { + for (xt = 0; xt < xtiles; xt++, code++) { + if (!zoomed) + Render16x16Tile_Mask_Clip(pTransDraw, code, x + xt * 16, y + yt * 16, color, 4, 15, 0, DrvGfxROM1); + else + RenderZoomedTile(pTransDraw, DrvGfxROM1, code, color << 4, 15, x + xt * xzoom, y + yt * yzoom, 0, 0, 16, 16, 0x1000 * xzoom, 0x1000 * yzoom); + } + if (xtiles == 3) code += 1; + if (xtiles == 5) code += 3; + if (xtiles == 6) code += 2; + if (xtiles == 7) code += 1; + } + } + else if (xflip && !yflip) { + for (yt = 0; yt < ytiles; yt++) { + for (xt = 0; xt < xtiles; xt++, code++) { + if (!zoomed) + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x + (xtiles - 1 - xt) * 16, y + yt * 16, color, 4, 15, 0, DrvGfxROM1); + else + RenderZoomedTile(pTransDraw, DrvGfxROM1, code, color << 4, 15, x + (xtiles - 1 - xt) * xzoom, y + yt * yzoom, 1, 0, 16, 16, 0x1000 * xzoom, 0x1000 * yzoom); + } + if (xtiles == 3) code += 1; + if (xtiles == 5) code += 3; + if (xtiles == 6) code += 2; + if (xtiles == 7) code += 1; + } + } + else if (!xflip && yflip) { + for (yt = 0; yt < ytiles; yt++) { + for (xt = 0; xt < xtiles; xt++, code++) { + if (!zoomed) + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x + xt * 16, y + (ytiles - 1 - yt) * 16, color, 4, 15, 0, DrvGfxROM1); + else + RenderZoomedTile(pTransDraw, DrvGfxROM1, code, color << 4, 15, x + xt * xzoom, y + (ytiles - 1 - yt) * yzoom, 0, 1, 16, 16, 0x1000 * xzoom, 0x1000 * yzoom); + } + if (xtiles == 3) code += 1; + if (xtiles == 5) code += 3; + if (xtiles == 6) code += 2; + if (xtiles == 7) code += 1; + } + } + else { + for (yt = 0; yt < ytiles; yt++) { + for (xt = 0; xt < xtiles; xt++, code++) { + if (!zoomed) + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x + (xtiles - 1 - xt) * 16, y + (ytiles - 1 - yt) * 16, color, 4, 15, 0, DrvGfxROM1); + else + RenderZoomedTile(pTransDraw, DrvGfxROM1, code, color << 4, 15, x + (xtiles - 1 - xt) * xzoom, y + (ytiles - 1 - yt) * yzoom, 1, 1, 16, 16, 0x1000 * xzoom, 0x1000 * yzoom); + } + if (xtiles == 3) code += 1; + if (xtiles == 5) code += 3; + if (xtiles == 6) code += 2; + if (xtiles == 7) code += 1; + } + } + } +} + +static void draw_foreground() +{ + INT32 color_bank = *charpalbank << 3; + INT32 scrollx = scroll[0] & 0x1ff; + INT32 scrolly = scroll[1] & 0x0ff; + + UINT16 *vram = (UINT16*)DrvVidRAM; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + INT32 attr = vram[offs]; + INT32 code = (attr & 0xfff) | (gfx_bank[(attr >> 12) & 1] << 12); + INT32 color = (attr >> 13) | color_bank; + + Render8x8Tile_Mask_Clip(pTransDraw, code, sx - 15, sy - screen_y_offset, color & 0x7f, 4, 15, 0, DrvGfxROM0); + } +} + +static void draw_background() +{ + INT32 color_bank = 0x400 + (*pixelpalbank << 8); + + UINT16 *vram = (UINT16*)DrvPxlRAM; + + for (INT32 offs = (screen_y_offset * 256); offs < 256 * 256; offs++) + { + INT32 sx = ((offs & 0xff) << 1) - 15; + INT32 sy = (offs >> 8) - screen_y_offset; + + INT32 pxl = vram[offs]; + + if (sy < nScreenHeight && sy >= 0) { + if (sx >= 0 && sx < nScreenWidth) pTransDraw[sy * nScreenWidth + sx++] = color_bank | (pxl >> 8); + if (sx >= 0 && sx < nScreenWidth) pTransDraw[sy * nScreenWidth + sx ] = color_bank | (pxl & 0xff); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + BurnTransferClear(); + + draw_background(); + draw_foreground(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + { + DrvInputs[0] = 0xff; + DrvInputs[1] = 0x00; + DrvInputs[2] = 0x00; + DrvInputs[3] = 0x00; + DrvInputs[4] = 0x00; + DrvInputs[5] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + DrvInputs[3] |= (DrvJoy4[i] & 1) << i; + DrvInputs[4] |= (DrvJoy5[i] & 1) << i; + DrvInputs[5] |= (DrvJoy6[i] & 1) << i; + } + } + + // Clear Opposites + WelltrisClearOpposites(&DrvInputs[1]); + WelltrisClearOpposites(&DrvInputs[2]); +// WelltrisClearOpposites(&DrvInputs[3]); +// WelltrisClearOpposites(&DrvInputs[4]); + + SekOpen(0); + ZetOpen(0); + + SekRun(10000000 / 60); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(4000000 / 60); + + if (pBurnSoundOut) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(sound_bank[0]); + ZetClose(); + } + + return 0; +} + + +// Welltris - Alexey Pajitnov's (World?, 2 players) + +static struct BurnRomInfo welltrisRomDesc[] = { + { "j2u.8", 0x20000, 0x7488fe94, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "j1u.7", 0x20000, 0x571413ac, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lh532j10.10", 0x40000, 0x1187c665, 1 | BRF_PRG | BRF_ESS }, // 2 + { "lh532j11.9", 0x40000, 0x18eda9e5, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "3.144", 0x20000, 0xae8f763e, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "lh534j11.126", 0x80000, 0xbf85fb0d, 3 | BRF_SND }, // 5 ADPCM-B Samples + + { "lh534j09.123", 0x80000, 0x6c2ce9a5, 4 | BRF_SND }, // 6 ADPCM-A Samples + { "lh534j10.124", 0x80000, 0xe3682221, 4 | BRF_SND }, // 7 + + { "046.93", 0x40000, 0x31d96d77, 5 | BRF_GRA }, // 8 Sprites + { "048.94", 0x40000, 0xbb4643da, 5 | BRF_GRA }, // 9 + + { "lh534j12.77", 0x80000, 0xb61a8b74, 6 | BRF_GRA }, // 10 Tiles +}; + +STD_ROM_PICK(welltris) +STD_ROM_FN(welltris) + +struct BurnDriver BurnDrvWelltris = { + "welltris", NULL, NULL, NULL, "1991", + "Welltris - Alexey Pajitnov's (World?, 2 players)\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, welltrisRomInfo, welltrisRomName, NULL, NULL, WelltrisInputInfo, WelltrisDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 352, 240, 4, 3 +}; + + +// Welltris - Alexey Pajitnov's (Japan, 2 players) + +static struct BurnRomInfo welltrisjRomDesc[] = { + { "j2.8", 0x20000, 0x68ec5691, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu + { "j1.7", 0x20000, 0x1598ea2c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lh532j10.10", 0x40000, 0x1187c665, 1 | BRF_PRG | BRF_ESS }, // 2 + { "lh532j11.9", 0x40000, 0x18eda9e5, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "3.144", 0x20000, 0xae8f763e, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "lh534j11.126", 0x80000, 0xbf85fb0d, 3 | BRF_SND }, // 5 ADPCM-B Samples + + { "lh534j09.123", 0x80000, 0x6c2ce9a5, 4 | BRF_SND }, // 6 ADPCM-A Samples + { "lh534j10.124", 0x80000, 0xe3682221, 4 | BRF_SND }, // 7 + + { "046.93", 0x40000, 0x31d96d77, 5 | BRF_GRA }, // 8 Sprites + { "048.94", 0x40000, 0xbb4643da, 5 | BRF_GRA }, // 9 + + { "lh534j12.77", 0x80000, 0xb61a8b74, 6 | BRF_GRA }, // 10 Tiles +}; + +STD_ROM_PICK(welltrisj) +STD_ROM_FN(welltrisj) + +struct BurnDriver BurnDrvWelltrisj = { + "welltrisj", "welltris", NULL, NULL, "1991", + "Welltris - Alexey Pajitnov's (Japan, 2 players)\0", NULL, "Video System Co.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, welltrisjRomInfo, welltrisjRomName, NULL, NULL, WelltrisInputInfo, WelltrisDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 352, 240, 4, 3 +}; + + +// Miyasu Nonki no Quiz 18-Kin + +static struct BurnRomInfo quiz18kRomDesc[] = { + { "1-ic8.bin", 0x20000, 0x10a64336, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "2-ic7.bin", 0x20000, 0x8b21b431, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ic10.bin", 0x40000, 0x501453a3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ic9.bin", 0x40000, 0x99b6840f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "3-ic144.bin", 0x20000, 0x72d372e3, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ic126.bin", 0x40000, 0x7a92fbc9, 3 | BRF_SND }, // 5 ADPCM-B Samples + + { "ic123.bin", 0x80000, 0xee4995cf, 4 | BRF_SND }, // 6 ADPCM-A Samples + { "ic124.bin", 0x40000, 0x076f58c3, 4 | BRF_SND }, // 7 + + { "ic93.bin", 0x80000, 0x4d387c5e, 5 | BRF_GRA }, // 8 Sprites + { "ic94.bin", 0x80000, 0x6be2f164, 5 | BRF_GRA }, // 9 + + { "ic77.bin", 0x80000, 0xaf3b6fd1, 6 | BRF_GRA }, // 10 Tiles + { "ic78.bin", 0x80000, 0x44bbdef3, 6 | BRF_GRA }, // 11 + { "ic79.bin", 0x80000, 0xd721e169, 6 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(quiz18k) +STD_ROM_FN(quiz18k) + +struct BurnDriver BurnDrvQuiz18k = { + "quiz18k", NULL, NULL, NULL, "1992", + "Miyasu Nonki no Quiz 18-Kin\0", NULL, "EIM", "Miscellaneous", + L"\u307F\u3084\u3059\u306E\u3093\u304D\u306E \u30AF\u30A4\u30BA\uFF11\uFF18\u7981 \uFF24\uFF52\uFF0E \u30A8\u30C3\u3061\u3083\u3093\u306E\u8A3A\u5BDF\u5BA4\0Miyasu Nonki no Quiz 18-Kin\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, quiz18kRomInfo, quiz18kRomName, NULL, NULL, Quiz18kInputInfo, Quiz18kDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_wwfwfest.cpp b/src/burn/drivers/misc_post90s/d_wwfwfest.cpp new file mode 100644 index 00000000..31b16da3 --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_wwfwfest.cpp @@ -0,0 +1,1203 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[5] = {0, 0, 0, 0, 0}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvMSM6295ROMSrc = NULL; +static UINT8 *DrvCharVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteRamBuff = NULL; +static UINT8 *DrvBg0VideoRam = NULL; +static UINT8 *DrvBg1VideoRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvVBlank; +static UINT8 DrvOkiBank; +static UINT8 DrvSoundLatch; +static UINT16 DrvBg0ScrollX; +static UINT16 DrvBg0ScrollY; +static UINT16 DrvBg1ScrollX; +static UINT16 DrvBg1ScrollY; +static UINT16 DrvVReg; + +static INT32 DrvSpriteXOffset; +static INT32 DrvBg0XOffset; +static INT32 DrvBg1XOffset[2]; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort4 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" }, + {"Start 3" , BIT_DIGITAL , DrvInputPort2 + 7, "p3 start" }, + {"Start 4" , BIT_DIGITAL , DrvInputPort3 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort2 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort2 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort2 + 1, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort2 + 0, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , DrvInputPort3 + 2, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvInputPort3 + 3, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvInputPort3 + 1, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvInputPort3 + 0, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort4 + 1, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = DrvInput[3] = DrvInput[4] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + DrvInput[3] |= (DrvInputPort3[i] & 1) << i; + DrvInput[4] |= (DrvInputPort4[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); + DrvClearOpposites(&DrvInput[3]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x1f, 0xff, 0xff, 0xef, NULL }, + {0x20, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x1f, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x1f, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x1f, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x1f, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Buy In Price" }, + {0x1f, 0x01, 0x04, 0x04, "1 Coin" }, + {0x1f, 0x01, 0x04, 0x00, "As Start Price" }, + + {0 , 0xfe, 0 , 2 , "Regain Power Price" }, + {0x1f, 0x01, 0x08, 0x08, "1 Coin" }, + {0x1f, 0x01, 0x08, 0x00, "As Start Price" }, + + {0 , 0xfe, 0 , 2 , "Continue Price" }, + {0x1f, 0x01, 0x10, 0x10, "1 Coin" }, + {0x1f, 0x01, 0x10, 0x00, "As Start Price" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1f, 0x01, 0x20, 0x00, "Off" }, + {0x1f, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1f, 0x01, 0x40, 0x40, "Off" }, + {0x1f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "FBI Logo" }, + {0x1f, 0x01, 0x80, 0x00, "Off" }, + {0x1f, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x20, 0x01, 0x03, 0x02, "Easy" }, + {0x20, 0x01, 0x03, 0x03, "Normal" }, + {0x20, 0x01, 0x03, 0x01, "Hard" }, + {0x20, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3 , "Number of Players" }, + {0x20, 0x01, 0x0c, 0x04, "2" }, + {0x20, 0x01, 0x0c, 0x08, "3" }, + {0x20, 0x01, 0x0c, 0x0c, "4" }, + + {0 , 0xfe, 0 , 4 , "Clear Stage Power Up" }, + {0x20, 0x01, 0x60, 0x00, "0" }, + {0x20, 0x01, 0x60, 0x20, "12" }, + {0x20, 0x01, 0x60, 0x60, "24" }, + {0x20, 0x01, 0x60, 0x40, "32" }, + + {0 , 0xfe, 0 , 2 , "Championship Game" }, + {0x20, 0x01, 0x80, 0x00, "4th" }, + {0x20, 0x01, 0x80, 0x80, "5th" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo DrvRomDesc[] = { + { "31a13-2.ic19", 0x040000, 0x7175bca7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "31a14-2.ic18", 0x040000, 0x5d06bfd1, BRF_ESS | BRF_PRG }, // 1 + + { "31a11-2.ic42", 0x010000, 0x5ddebfea, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "31a12-0.ic33", 0x020000, 0xd0803e20, BRF_GRA }, // 3 Chars + + { "31j0.ic1", 0x040000, 0x8a12b450, BRF_GRA }, // 4 Tiles + { "31j1.ic2", 0x040000, 0x82ed7155, BRF_GRA }, // 5 + + { "31j3.ic9", 0x100000, 0xe395cf1d, BRF_GRA }, // 6 Sprites + { "31j2.ic8", 0x100000, 0xb5a97465, BRF_GRA }, // 7 + { "31j5.ic11", 0x100000, 0x2ce545e8, BRF_GRA }, // 8 + { "31j4.ic10", 0x100000, 0x00edb66a, BRF_GRA }, // 9 + { "31j6.ic12", 0x100000, 0x79956cf8, BRF_GRA }, // 10 + { "31j7.ic13", 0x100000, 0x74d774c3, BRF_GRA }, // 11 + { "31j9.ic15", 0x100000, 0xdd387289, BRF_GRA }, // 12 + { "31j8.ic14", 0x100000, 0x44abe127, BRF_GRA }, // 13 + + { "31j10.ic73", 0x080000, 0x6c522edb, BRF_SND }, // 14 Samples +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvaRomDesc[] = { + { "wf_19.rom", 0x040000, 0xbd02e3c4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "wf_18.rom", 0x040000, 0x933ea1a0, BRF_ESS | BRF_PRG }, // 1 + + { "31a11-2.ic42", 0x010000, 0x5ddebfea, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "wf_33.rom", 0x020000, 0x06f22615, BRF_GRA }, // 3 Chars + + { "31j0.ic1", 0x040000, 0x8a12b450, BRF_GRA }, // 4 Tiles + { "31j1.ic2", 0x040000, 0x82ed7155, BRF_GRA }, // 5 + + { "31j3.ic9", 0x100000, 0xe395cf1d, BRF_GRA }, // 6 Sprites + { "31j2.ic8", 0x100000, 0xb5a97465, BRF_GRA }, // 7 + { "31j5.ic11", 0x100000, 0x2ce545e8, BRF_GRA }, // 8 + { "31j4.ic10", 0x100000, 0x00edb66a, BRF_GRA }, // 9 + { "31j6.ic12", 0x100000, 0x79956cf8, BRF_GRA }, // 10 + { "31j7.ic13", 0x100000, 0x74d774c3, BRF_GRA }, // 11 + { "31j9.ic15", 0x100000, 0xdd387289, BRF_GRA }, // 12 + { "31j8.ic14", 0x100000, 0x44abe127, BRF_GRA }, // 13 + + { "31j10.ic73", 0x080000, 0x6c522edb, BRF_SND }, // 14 Samples +}; + +STD_ROM_PICK(Drva) +STD_ROM_FN(Drva) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "2", 0x040000, 0x632bb3a4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "3", 0x040000, 0xea73369c, BRF_ESS | BRF_PRG }, // 1 + + { "1", 0x010000, 0xd9e8cda2, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "4", 0x020000, 0x520ef575, BRF_GRA }, // 3 Chars + + { "5", 0x020000, 0x35e4d6eb, BRF_GRA }, // 4 Tiles + { "6", 0x020000, 0xa054a5b2, BRF_GRA }, // 5 + { "7", 0x020000, 0x101f0136, BRF_GRA }, // 6 + { "8", 0x020000, 0x7b2ecba7, BRF_GRA }, // 7 + + { "wf_09.rom", 0x100000, 0xe395cf1d, BRF_GRA }, // 8 Sprites + { "wf_08.rom", 0x100000, 0xb5a97465, BRF_GRA }, // 9 + { "wf_11.rom", 0x100000, 0x2ce545e8, BRF_GRA }, // 10 + { "wf_10.rom", 0x100000, 0x00edb66a, BRF_GRA }, // 11 + { "wf_12.rom", 0x100000, 0x79956cf8, BRF_GRA }, // 12 + { "wf_13.rom", 0x100000, 0x74d774c3, BRF_GRA }, // 13 + { "wf_15.rom", 0x100000, 0xdd387289, BRF_GRA }, // 14 + { "wf_14.rom", 0x100000, 0x44abe127, BRF_GRA }, // 15 + + { "wf_73a.rom", 0x080000, 0x6c522edb, BRF_SND }, // 16 Samples +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "31j13-0.ic19", 0x040000, 0x2147780d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "31j14-0.ic18", 0x040000, 0xd76fc747, BRF_ESS | BRF_PRG }, // 1 + + { "31a11-2.ic42", 0x010000, 0x5ddebfea, BRF_ESS | BRF_PRG }, // 2 Z80 Program + + { "31j12-0.ic33", 0x020000, 0xf4821fe0, BRF_GRA }, // 3 Chars + + { "31j0.ic1", 0x040000, 0x8a12b450, BRF_GRA }, // 4 Tiles + { "31j1.ic2", 0x040000, 0x82ed7155, BRF_GRA }, // 5 + + { "31j3.ic9", 0x100000, 0xe395cf1d, BRF_GRA }, // 6 Sprites + { "31j2.ic8", 0x100000, 0xb5a97465, BRF_GRA }, // 7 + { "31j5.ic11", 0x100000, 0x2ce545e8, BRF_GRA }, // 8 + { "31j4.ic10", 0x100000, 0x00edb66a, BRF_GRA }, // 9 + { "31j6.ic12", 0x100000, 0x79956cf8, BRF_GRA }, // 10 + { "31j7.ic13", 0x100000, 0x74d774c3, BRF_GRA }, // 11 + { "31j9.ic15", 0x100000, 0xdd387289, BRF_GRA }, // 12 + { "31j8.ic14", 0x100000, 0x44abe127, BRF_GRA }, // 13 + + { "31j10.ic73", 0x080000, 0x6c522edb, BRF_SND }, // 14 Samples +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x80000; + DrvZ80Rom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x40000; + DrvMSM6295ROMSrc = Next; Next += 0x80000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x04000; + DrvZ80Ram = Next; Next += 0x00800; + DrvCharVideoRam = Next; Next += 0x02000; + DrvSpriteRam = Next; Next += 0x02000; + DrvSpriteRamBuff = Next; Next += 0x02000; + DrvBg0VideoRam = Next; Next += 0x01000; + DrvBg1VideoRam = Next; Next += 0x01000; + DrvPaletteRam = Next; Next += 0x04000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x01000 * 8 * 8; + DrvTiles = Next; Next += 0x01000 * 16 * 16; + DrvSprites = Next; Next += 0x10000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + DrvVBlank = 0; + DrvBg0ScrollX = 0; + DrvBg0ScrollY = 0; + DrvBg1ScrollX = 0; + DrvBg1ScrollY = 0; + DrvVReg = 0; + DrvOkiBank = 0; + DrvSoundLatch = 0; + + return 0; +} + +UINT8 __fastcall Wwfwfest68KReadByte(UINT32 a) +{ + switch (a) { + case 0x140020: { + return (0xcf - DrvInput[4]) | ((DrvDip[1] & 0xc0) >> 2); + } + + case 0x140021: { + return 0xff - DrvInput[0]; + } + + case 0x140023: { + return 0xff - DrvInput[1]; + } + + case 0x140025: { + return 0xff - DrvInput[2]; + } + + case 0x140026: { + UINT8 Temp = 0xfc; + if (DrvVBlank) Temp = 0xfb; + Temp |= (DrvDip[0] & 0xc0) >> 6; + return Temp; + } + + case 0x140027: { + return 0xff - DrvInput[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Wwfwfest68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x0c0000 && a <= 0x0c1fff) { + UINT16 *CharRam = (UINT16*)DrvCharVideoRam; + CharRam[(a - 0x0c0000) >> 1] = d; + return; + } + + switch (a) { + case 0x140011: { + DrvVReg = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Wwfwfest68KReadWord(UINT32 a) +{ + if (a >= 0x180000 && a <= 0x18ffff) { + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + INT32 Offset = (a - 0x180000) >> 1; + Offset = (Offset & 0x0f) | (Offset & 0x7fc0) >> 2; + return PaletteRam[Offset]; + } + + switch (a) { + case 0x140020: { + UINT16 Temp = (0xff - DrvInput[0]) | ((0xff - DrvInput[4]) << 8); + Temp &= 0xcfff; + Temp |= ((DrvDip[1] & 0xc0) << 6); + return Temp; + } + + case 0x140022: { + UINT16 Temp = 0xff - DrvInput[1]; + Temp |= ((DrvDip[1] & 0x3f) << 8); + return Temp; + } + + case 0x140024: { + UINT16 Temp = 0xff - DrvInput[2]; + Temp |= ((DrvDip[0] & 0x3f) << 8); + return Temp; + } + + case 0x140026: { + UINT16 Temp = 0xff - DrvInput[3]; + if (DrvVBlank) { + Temp |= (0xfb << 8); + } else { + Temp |= (0xff << 8); + } + Temp &= 0xfcff; + Temp |= ((DrvDip[0] & 0xc0) << 2); + return Temp; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Wwfwfest68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x0c0000 && a <= 0x0c1fff) { + UINT16 *CharRam = (UINT16*)DrvCharVideoRam; + CharRam[(a - 0x0c0000) >> 1] = d; + return; + } + + if (a >= 0x180000 && a <= 0x18ffff) { + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + INT32 Offset = (a - 0x180000) >> 1; + Offset = (Offset & 0x0f) | (Offset & 0x7fc0) >> 2; + PaletteRam[Offset] = d; + return; + } + + if (a >= 0x120000 && a <= 0x121fff) { + return; + } + + switch (a) { + case 0x100000: { + DrvBg0ScrollX = d & 0x1ff; + return; + } + + case 0x100002: { + DrvBg0ScrollY = d & 0x1ff; + return; + } + + case 0x100004: { + DrvBg1ScrollX = d & 0x1ff; + return; + } + + case 0x100006: { + DrvBg1ScrollY = d & 0x1ff; + return; + } + + case 0x140010: { + DrvVReg = d; + return; + } + + case 0x14000c: { + DrvSoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nCyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + + case 0x100008: { + // ??? + return; + } + + case 0x10000c: { + // ??? + return; + } + + case 0x140000: + case 0x140002: { + // NOP + return; + } + + case 0x140006: + case 0x140008: + case 0x140012: + case 0x140014: + case 0x140016: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall WwfwfestZ80Read(UINT16 a) +{ + switch (a) { + case 0xc801: { + return BurnYM2151ReadStatus(); + } + + case 0xd800: { + return MSM6295ReadStatus(0); + } + + case 0xe000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall WwfwfestZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xc801: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xd800: { + MSM6295Command(0, d); + return; + } + + case 0xe800: { + DrvOkiBank = d & 1; + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 2, 4, 6 }; +static INT32 CharXOffsets[8] = { 1, 0, 65, 64, 129, 128, 193, 192 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 TilePlaneOffsets[4] = { 8, 0, 0x200008, 0x200000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 256, 257, 258, 259, 260, 261, 262, 263 }; +static INT32 TileYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; +static INT32 SpritePlaneOffsets[4] = { 0, 0x1000000, 0x2000000, 0x3000000 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen, RomOffset; + + RomOffset = 0; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "wwfwfestb")) RomOffset = 2; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x800000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00000, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00001, 1, 2); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom, 2, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x800000); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "wwfwfestb")) { + nRet = BurnLoadRom(DrvTempRom + 0x040000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x040001, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 7, 2); if (nRet != 0) return 1; + } else { + nRet = BurnLoadRom(DrvTempRom + 0x040000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000000, 5, 1); if (nRet != 0) return 1; + } + GfxDecode(0x1000, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x800000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 7 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x200000, 8 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x300000, 9 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x400000, 10 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x500000, 11 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x600000, 12 + RomOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x700000, 13 + RomOffset, 1); if (nRet != 0) return 1; + GfxDecode(0x10000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load Sample Roms + nRet = BurnLoadRom(DrvMSM6295ROMSrc + 0x00000, 14 + RomOffset, 1); if (nRet != 0) return 1; + memcpy(MSM6295ROM, DrvMSM6295ROMSrc, 0x40000); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvBg0VideoRam , 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvBg1VideoRam , 0x082000, 0x082fff, SM_RAM); + SekMapMemory(DrvCharVideoRam , 0x0c0000, 0x0c1fff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0x0c2000, 0x0c3fff, SM_RAM); + SekMapMemory(Drv68KRam , 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, Wwfwfest68KReadWord); + SekSetWriteWordHandler(0, Wwfwfest68KWriteWord); + SekSetReadByteHandler(0, Wwfwfest68KReadByte); + SekSetWriteByteHandler(0, Wwfwfest68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(WwfwfestZ80Read); + ZetSetWriteHandler(WwfwfestZ80Write); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + // Setup the YM2151 emulation + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + // Setup the OKIM6295 emulation + MSM6295Init(0, 1024188 / 132, 100.0, 1); + + DrvSpriteXOffset = 0; + DrvBg0XOffset = 0; + DrvBg1XOffset[0] = 0; + DrvBg1XOffset[1] = 0; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "wwfwfestb")) { + DrvSpriteXOffset = 2; + DrvBg0XOffset = -4; + DrvBg1XOffset[0] = -4; + DrvBg1XOffset[1] = -2; + } + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + ZetExit(); + + BurnYM2151Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + + DrvVBlank = 0; + DrvBg0ScrollX = 0; + DrvBg0ScrollY = 0; + DrvBg1ScrollX = 0; + DrvBg1ScrollY = 0; + DrvVReg = 0; + DrvOkiBank = 0; + DrvSoundLatch = 0; + + DrvSpriteXOffset = 0; + DrvBg0XOffset = 0; + DrvBg1XOffset[0] = 0; + DrvBg1XOffset[1] = 0; + + BurnFree(Mem); + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void DrvRenderBg0Layer(INT32 Opaque) +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, xScroll, yScroll, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)DrvBg0VideoRam; + UINT16 *TileBase; + + if (DrvVReg == 0x78) { + xScroll = DrvBg0ScrollX + DrvBg0XOffset; + yScroll = DrvBg0ScrollY; + } else { + xScroll = DrvBg1ScrollX + DrvBg0XOffset; + yScroll = DrvBg1ScrollY; + } + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + TileBase = &VideoRam[TileIndex * 2]; + Code = TileBase[1] & 0xfff; + Colour = TileBase[0] & 0x0f; + Flip = (TileBase[0] & 0xc0) >> 6; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 16 * mx; + y = 16 * my; + + x -= xScroll; + y -= yScroll; + if (x < -16) x += 512; + if (y < -16) y += 512; + + y -= 8; + + if (Opaque) { + if (x > 16 && x < 304 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0x1000, DrvTiles); + } + } + } + } else { + if (x > 16 && x < 304 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x1000, DrvTiles); + } + } + } + } + + TileIndex++; + } + } +} + +static void DrvRenderBg1Layer(INT32 Opaque) +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, xScroll, yScroll; + + UINT16 *VideoRam = (UINT16*)DrvBg1VideoRam; + UINT16 *TileBase; + + if (DrvVReg == 0x78) { + xScroll = DrvBg1ScrollX + DrvBg1XOffset[0]; + yScroll = DrvBg1ScrollY; + } else { + xScroll = DrvBg0ScrollX + DrvBg1XOffset[1]; + yScroll = DrvBg0ScrollY; + } + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + TileBase = &VideoRam[TileIndex]; + Code = TileBase[0] & 0xfff; + Colour = (TileBase[0] & 0xf000) >> 12; + + x = 16 * mx; + y = 16 * my; + + x -= xScroll; + y -= yScroll; + if (x < -16) x += 512; + if (y < -16) y += 512; + + y -= 8; + + if (Opaque) { + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 0x0c00, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0c00, DrvTiles); + } + } else { + if (x > 0 && x < 304 && y > 0 && y < 224) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0x0c00, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x0c00, DrvTiles); + } + } + + TileIndex++; + } + } +} + +static void DrvRenderSprites() +{ + UINT16 *Source = (UINT16*)DrvSpriteRamBuff; + UINT16 *Finish = (UINT16*)DrvSpriteRamBuff + 0x1000; + + while (Source < Finish) { + INT32 x, y, Colour, xFlip, yFlip, Chain, Enable, Code, Count; + + Enable = Source[1] & 1; + + if (Enable) { + x = +(Source[5] & 0x00ff) | (Source[1] & 0x0004) << 6; + if (x > 512 - 16) x -= 512; + x += DrvSpriteXOffset; + y = (Source[0] & 0x00ff) | (Source[1] & 0x0002) << 7; + y = (256 - y) & 0x1ff; + y -= 16; + y -= 8; + xFlip = (Source[1] & 0x0010) >> 4; + yFlip = (Source[1] & 0x0008) >> 3; + Chain = (Source[1] & 0x00e0) >> 5; + Chain += 1; + Code = (Source[2] & 0x00ff) | (Source[3] & 0x00ff) << 8; + Colour = (Source[4] & 0x000f); + + for (Count = 0; Count < Chain; Count++) { + INT32 yPos; + yPos = y - 16 * Count; + if (yFlip) yPos = y - (16 * (Chain - 1)) + (16 * Count); + + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code + Count, x, yPos, Colour, 4, 0, 0x400, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code + Count, x, yPos, Colour, 4, 0, 0x400, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code + Count, x, yPos, Colour, 4, 0, 0x400, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code + Count, x, yPos, Colour, 4, 0, 0x400, DrvSprites); + } + } + } + } + + Source += 8; + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvCharVideoRam; + UINT16 *TileBase; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + TileBase = &VideoRam[TileIndex * 2]; + Code = (TileBase[0] & 0xff) | ((TileBase[1] & 0x0f) << 8); + Colour = (TileBase[1] & 0xf0) >> 4; + + x = 8 * mx; + y = 8 * my; + + y -= 8; + + if (x > 0 && x < 312 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + + if (DrvVReg == 0x7b) { + DrvRenderBg0Layer(1); + DrvRenderBg1Layer(0); + DrvRenderSprites(); + DrvRenderCharLayer(); + } + + if (DrvVReg == 0x7c) { + DrvRenderBg0Layer(1); + DrvRenderSprites(); + DrvRenderBg1Layer(0); + DrvRenderCharLayer(); + } + + if (DrvVReg == 0x78) { + DrvRenderBg1Layer(1); + DrvRenderBg0Layer(0); + DrvRenderSprites(); + DrvRenderCharLayer(); + } + + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = (24000000 / 2) / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + DrvVBlank = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 5) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == 5) DrvVBlank = 1; + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekOpen(0); + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + memcpy(DrvSpriteRamBuff, DrvSpriteRam, 0x2000); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029674; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); // Scan Z80 + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(DrvVBlank); + SCAN_VAR(DrvOkiBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvBg0ScrollX); + SCAN_VAR(DrvBg0ScrollY); + SCAN_VAR(DrvBg1ScrollX); + SCAN_VAR(DrvBg1ScrollY); + SCAN_VAR(DrvVReg); + } + + if (nAction & ACB_WRITE) { + memcpy(MSM6295ROM + 0x00000, DrvMSM6295ROMSrc + (0x40000 * DrvOkiBank), 0x40000); + } + + return 0; +} + +struct BurnDriver BurnDrvWwfwfest = { + "wwfwfest", NULL, NULL, NULL, "1991", + "WWF WrestleFest (US set 1)\0", NULL, "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWwfwfesta = { + "wwfwfesta", "wwfwfest", NULL, NULL, "1991", + "WWF WrestleFest (US Tecmo)\0", NULL, "Technos Japan (Tecmo License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, DrvaRomInfo, DrvaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWwfwfestb = { + "wwfwfestb", "wwfwfest", NULL, NULL, "1991", + "WWF WrestleFest (US bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWwfwfestj = { + "wwfwfestj", "wwfwfest", NULL, NULL, "1991", + "WWF WrestleFest (Japan)\0", NULL, "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x2000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_xorworld.cpp b/src/burn/drivers/misc_post90s/d_xorworld.cpp new file mode 100644 index 00000000..d8548ebd --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_xorworld.cpp @@ -0,0 +1,434 @@ +// FB Alpha Xor World driver module +// Based on MAME driver by Manuel Abadia + +#include "tiles_generic.h" +#include "saa1099.h" +#include "eeprom.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT8 DrvInputs[2]; + +static struct BurnInputInfo XorworldInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Xorworld) + +static struct BurnDIPInfo XorworldDIPList[]= +{ + {0x11, 0xff, 0xff, 0xc7, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x11, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x01, "2 Coins 2 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x11, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x08, 0x08, "Off" }, + {0x11, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x60, 0x40, "Easy" }, + {0x11, 0x01, 0x60, 0x60, "Normal" }, + {0x11, 0x01, 0x60, 0x20, "Hard" }, + {0x11, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Xorworld) + +void __fastcall xorworld_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x800001: + saa1099DataWrite(0, data); + return; + + case 0x800003: + saa1099ControlWrite(0, data); + return; + + case 0xa00009: + EEPROMSetCSLine((data & 0x01) ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE); + return; + + case 0xa0000b: + EEPROMSetClockLine((data & 0x01) ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE); + return; + + case 0xa0000d: + EEPROMWriteBit((data & 0x01)); + return; + } +} + +UINT8 __fastcall xorworld_read_byte(UINT32 address) +{ + switch (address) + { + case 0x200001: + return DrvInputs[0]; + + case 0x400000: + return DrvInputs[1]; + + case 0x600001: + return (DrvDips[0] & ~0x10) | (EEPROMRead() ? 0x10 : 0); + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + EEPROMReset(); + + saa1099Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x020000; + + DrvGfxROM = Next; Next += 0x040000; + + DrvColPROM = Next; Next += 0x000300; + + DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x003800; + DrvVidRAM = Next; Next += 0x000800; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) { + INT32 r,g,b; + + r = ((DrvColPROM[i + 0x000] >> 0) & 0x01) * 0x0e; + r += ((DrvColPROM[i + 0x000] >> 1) & 0x01) * 0x1e; + r += ((DrvColPROM[i + 0x000] >> 2) & 0x01) * 0x44; + r += ((DrvColPROM[i + 0x000] >> 3) & 0x01) * 0x8f; + + g = ((DrvColPROM[i + 0x100] >> 0) & 0x01) * 0x0e; + g += ((DrvColPROM[i + 0x100] >> 1) & 0x01) * 0x1e; + g += ((DrvColPROM[i + 0x100] >> 2) & 0x01) * 0x44; + g += ((DrvColPROM[i + 0x100] >> 3) & 0x01) * 0x8f; + + b = ((DrvColPROM[i + 0x200] >> 0) & 0x01) * 0x0e; + b += ((DrvColPROM[i + 0x200] >> 1) & 0x01) * 0x1e; + b += ((DrvColPROM[i + 0x200] >> 2) & 0x01) * 0x44; + b += ((DrvColPROM[i + 0x200] >> 3) & 0x01) * 0x8f; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x80000, 0x80004, 0x00000, 0x00004 }; + INT32 XOffs[8] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b }; + INT32 YOffs[8] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x20000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x20000); + + GfxDecode((0x20000 * 2) / 0x40, 4, 8, 8, Plane, XOffs, YOffs, 0x080, tmp, DrvGfxROM); + + BurnFree (tmp); + + return 0; +} + +static void xorworldPatch() // protection hack +{ + UINT16 *rom = (UINT16*)Drv68KROM; + + rom[0x1390 / 2] = 0x4239; + rom[0x1392 / 2] = 0x00ff; + rom[0x1394 / 2] = 0xe196; + rom[0x1396 / 2] = 0x4239; + rom[0x1398 / 2] = 0x00ff; + rom[0x139a / 2] = 0xe197; + rom[0x139c / 2] = 0x4239; + rom[0x139e / 2] = 0x00ff; + rom[0x13a0 / 2] = 0xe0bc; + rom[0x13a2 / 2] = 0x41f9; + rom[0x13a4 / 2] = 0x00ff; + rom[0x13a6 / 2] = 0xcfce; + rom[0x13a8 / 2] = 0x3e3c; + rom[0x13aa / 2] = 0x000f; + rom[0x13ac / 2] = 0x4218; + rom[0x13ae / 2] = 0x51cf; + rom[0x13b0 / 2] = 0xfffc; + rom[0x13b2 / 2] = 0x4e75; + rom[0x13b4 / 2] = 0x31ff; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x00000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x10000, 3, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 5, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 6, 1)) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + + xorworldPatch(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(DrvVidRAM, 0xffc000, 0xffc7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0xffc800, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, xorworld_write_byte); + SekSetReadByteHandler(0, xorworld_read_byte); + SekClose(); + + saa1099Init(0, 8000000, 1000, 0); + + EEPROMInit(&eeprom_interface_93C46); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + EEPROMExit(); + + SekExit(); + + saa1099Exit(0); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer() +{ + UINT16 *ram = (UINT16*)DrvVidRAM; + + for (INT32 offs = 32 * 2; offs < (32 * 32) - (32 * 2); offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 code = ram[offs] & 0x0fff; + INT32 color = ram[offs] >> 12; + + Render8x8Tile(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM); + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprRAM; + + for (INT32 i = 0; i < 0x40; i += 2) + { + INT32 sx = ram[i] & 0xff; + INT32 sy = (240 - (ram[i] >> 8)) - 16; + INT32 code = ram[i+1] & 0x0ffc; + INT32 color = ram[i+1] >> 12; + + Render8x8Tile_Mask_Clip(pTransDraw, code + 0, sx + 0, sy + 0, color, 4, 0, 0, DrvGfxROM); + Render8x8Tile_Mask_Clip(pTransDraw, code + 1, sx + 0, sy + 8, color, 4, 0, 0, DrvGfxROM); + Render8x8Tile_Mask_Clip(pTransDraw, code + 2, sx + 8, sy + 0, color, 4, 0, 0, DrvGfxROM); + Render8x8Tile_Mask_Clip(pTransDraw, code + 3, sx + 8, sy + 8, color, 4, 0, 0, DrvGfxROM); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2); + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + SekOpen(0); + + for (INT32 i = 0; i < 4; i++) + { + SekRun((10000000 / 60) / 4); + if (i == 0 || i == 2) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + if (/*i==1||*/i == 3) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + if (pBurnSoundOut) { + saa1099Update(0, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + + saa1099Scan(0, nAction); + + EEPROMScan(nAction, pnMin); + } + + return 0; +} + + +// Xor World (prototype) + +static struct BurnRomInfo xorworldRomDesc[] = { + { "c13.bin", 0x10000, 0x615a864d, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "b13.bin", 0x10000, 0x632e8ee5, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "d9.bin", 0x10000, 0xda8d4d65, 2 | BRF_GRA }, // 2 Tiles and Sprites + { "d10.bin", 0x10000, 0x3b1d6f24, 2 | BRF_GRA }, // 3 + + { "b4.bin", 0x00100, 0x75e468af, 3 | BRF_GRA }, // 4 Color PROMs + { "b7.bin", 0x00100, 0x7e1cd146, 3 | BRF_GRA }, // 5 + { "b5.bin", 0x00100, 0xc1b9d9f9, 3 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(xorworld) +STD_ROM_FN(xorworld) + +struct BurnDriver BurnDrvXorworld = { + "xorworld", NULL, NULL, NULL, "1990", + "Xor World (prototype)\0", NULL, "Gaelco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, xorworldRomInfo, xorworldRomName, NULL, NULL, XorworldInputInfo, XorworldDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/d_yunsun16.cpp b/src/burn/drivers/misc_post90s/d_yunsun16.cpp new file mode 100644 index 00000000..690a193f --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_yunsun16.cpp @@ -0,0 +1,1112 @@ +// FB Alpha Yun Sung 16 Bit Games driver module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT32 soundbank; +static UINT16 *scroll; +static UINT8 *soundlatch; +static UINT8 *video_priority; + +static UINT16 DrvInputs[2]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static INT32 is_magicbub = 0; + +static struct BurnInputInfo MagicbubInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Magicbub) + +static struct BurnInputInfo BombkickInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Bombkick) + +static struct BurnDIPInfo MagicbubDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xbf, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x0e, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x01, "3 Coins 2 Credits" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0e, 0x01, 0x18, 0x10, "Easy" }, + {0x0e, 0x01, 0x18, 0x18, "Normal" }, + {0x0e, 0x01, 0x18, 0x08, "Hard" }, + {0x0e, 0x01, 0x18, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "1P Vs 2P Rounds (Start)" }, + {0x0f, 0x01, 0x0c, 0x08, "Best of 1" }, + {0x0f, 0x01, 0x0c, 0x0c, "Best of 3" }, + {0x0f, 0x01, 0x0c, 0x04, "Best of 5" }, + {0x0f, 0x01, 0x0c, 0x00, "Best of 7" }, + + {0 , 0xfe, 0 , 0, "1P Vs 2P Rounds (Join-in)" }, + {0x0f, 0x01, 0x10, 0x00, "Best of 1" }, + {0x0f, 0x01, 0x10, 0x10, "Best of 3" }, +}; + +STDDIPINFO(Magicbub) + +static struct BurnDIPInfo MagicbubaDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xbf, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x0e, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x01, "3 Coins 2 Credits" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0e, 0x01, 0x18, 0x10, "Easy" }, + {0x0e, 0x01, 0x18, 0x18, "Normal" }, + {0x0e, 0x01, 0x18, 0x08, "Hard" }, + {0x0e, 0x01, 0x18, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x0e, 0x01, 0x40, 0x40, "Off" }, + {0x0e, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Nudity" }, + {0x0f, 0x01, 0x03, 0x03, "Soft only" }, + {0x0f, 0x01, 0x03, 0x00, "Hard only" }, + {0x0f, 0x01, 0x03, 0x01, "Soft and Hard" }, + {0x0f, 0x01, 0x03, 0x02, "Soft then Hard" }, + + {0 , 0xfe, 0 , 4, "1P Vs 2P Rounds (Start)" }, + {0x0f, 0x01, 0x0c, 0x08, "Best of 1" }, + {0x0f, 0x01, 0x0c, 0x0c, "Best of 3" }, + {0x0f, 0x01, 0x0c, 0x04, "Best of 5" }, + {0x0f, 0x01, 0x0c, 0x00, "Best of 7" }, + + {0 , 0xfe, 0 , 4, "1P Vs 2P Rounds (Join-in)" }, + {0x0f, 0x01, 0x10, 0x00, "Best of 1" }, + {0x0f, 0x01, 0x10, 0x10, "Best of 3" }, +}; + +STDDIPINFO(Magicbuba) + +static struct BurnDIPInfo ShockingDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x0e, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x07, 0x03, "3 Coins 2 Credits" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x07, 0x04, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x0f, 0x01, 0x07, 0x04, "Easiest" }, + {0x0f, 0x01, 0x07, 0x05, "Easier" }, + {0x0f, 0x01, 0x07, 0x06, "Easy" }, + {0x0f, 0x01, 0x07, 0x07, "Normal" }, + {0x0f, 0x01, 0x07, 0x03, "Medium" }, + {0x0f, 0x01, 0x07, 0x02, "Hard" }, + {0x0f, 0x01, 0x07, 0x01, "Harder" }, + {0x0f, 0x01, 0x07, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 0, "Lives" }, + {0x0f, 0x01, 0x30, 0x20, "2" }, + {0x0f, 0x01, 0x30, 0x30, "3" }, + {0x0f, 0x01, 0x30, 0x10, "4" }, + {0x0f, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 0, "Demo Sounds" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0f, 0x01, 0x80, 0x80, "Off" }, + {0x0f, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Shocking) + +static struct BurnDIPInfo BombkickDIPList[]= +{ + {0x12, 0xff, 0xff, 0x9f, NULL }, + {0x13, 0xff, 0xff, 0xaf, NULL }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x04, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x18, 0x10, "Easy" }, + {0x12, 0x01, 0x18, 0x18, "Normal" }, + {0x12, 0x01, 0x18, 0x08, "Hard" }, + {0x12, 0x01, 0x18, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Special Powers" }, + {0x12, 0x01, 0x20, 0x20, "2" }, + {0x12, 0x01, 0x20, 0x00, "3" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x00, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + +}; + +STDDIPINFO(Bombkick) + +static struct BurnDIPInfo PaprazziDIPList[]= +{ + {0x0e, 0xff, 0xff, 0x9b, NULL }, + {0x0f, 0xff, 0xff, 0xa7, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x0e, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x0e, 0x01, 0x08, 0x00, "Korean" }, + {0x0e, 0x01, 0x08, 0x08, "English" }, + + {0 , 0xfe, 0 , 2, "Enemies" }, + {0x0e, 0x01, 0x10, 0x00, "Type 1" }, + {0x0e, 0x01, 0x10, 0x10, "Type 2" }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x0e, 0x01, 0xc0, 0x00, "80" }, + {0x0e, 0x01, 0xc0, 0x40, "100" }, + {0x0e, 0x01, 0xc0, 0x80, "120" }, + {0x0e, 0x01, 0xc0, 0xc0, "150" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x0f, 0x01, 0x07, 0x04, "Easiest" }, + {0x0f, 0x01, 0x07, 0x05, "Easier" }, + {0x0f, 0x01, 0x07, 0x06, "Easy" }, + {0x0f, 0x01, 0x07, 0x07, "Normal" }, + {0x0f, 0x01, 0x07, 0x03, "Medium" }, + {0x0f, 0x01, 0x07, 0x02, "Hard" }, + {0x0f, 0x01, 0x07, 0x01, "Harder" }, + {0x0f, 0x01, 0x07, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0x30, 0x20, "3" }, + {0x0f, 0x01, 0x30, 0x30, "2" }, + {0x0f, 0x01, 0x30, 0x10, "4" }, + {0x0f, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Gfx Viewer" }, + {0x0f, 0x01, 0x80, 0x80, "Off" }, + {0x0f, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Paprazzi) + +static void set_sample_bank(INT32 bank) +{ + if (bank != soundbank) { + soundbank = bank; + memcpy(DrvSndROM + 0x20000, DrvSndROM + 0x40000 + (soundbank * 0x20000), 0x20000); + } +} + +void __fastcall magicbub_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x80010c: + case 0x80010e: + scroll[2 + ((address >> 1) & 1)] = data & 0x3ff; + return; + + case 0x800114: + case 0x800116: + scroll[0 + ((address >> 1) & 1)] = data & 0x3ff; + return; + + case 0x800154: + *video_priority = data & 0xff; + return; + + } +} + +void __fastcall magicbub_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x800180: + case 0x800181: + set_sample_bank(data & 3); + return; + + case 0x800188: + case 0x800189: + if (is_magicbub) { + if (data != 0x3a) { + *soundlatch = data; +// ZetNmi(); + Z80SetIrqLine(Z80_INPUT_LINE_NMI, 1); + } + } else { + MSM6295Command(0, data); + } + return; + } +} + +UINT16 __fastcall magicbub_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x800000: + return DrvInputs[0]; + + case 0x800018: + return DrvInputs[1]; + } + + return 0; +} + +UINT8 __fastcall magicbub_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x800000: + case 0x800001: + return (DrvInputs[0] >> ((~address & 1) << 3)); + + case 0x800018: + case 0x800019: + return (DrvInputs[1] >> ((~address & 1) << 3)); + + case 0x80001a: + case 0x80001b: + return DrvDips[0]; + + case 0x80001c: + case 0x80001d: + return DrvDips[1]; + + case 0x800188: + case 0x800189: + return MSM6295ReadStatus(0); + } + + return 0; +} + +void __fastcall magicbub_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x10: + BurnYM3812Write(0, data); + return; + + case 0x11: + BurnYM3812Write(1, data); + return; + + case 0x1c: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall magicbub_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x10: + return BurnYM3812Read(0); + + case 0x11: + return BurnYM3812Read(1); + + case 0x18: + Z80SetIrqLine(Z80_INPUT_LINE_NMI, 0); + return *soundlatch; + + case 0x1c: + return MSM6295ReadStatus(0); + } + + return 0; +} + + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3000000; +} + +static void DrvYM3812IrqHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM3812Reset(); + + memcpy (DrvSndROM, DrvSndROM + 0x40000, 0x40000); + soundbank = 1; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x400000; + DrvGfxROM1 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x080000 + 0x40000; + + DrvPalette = (UINT32*)Next; Next += 0x2000 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvVidRAM0 = Next; Next += 0x004000; + DrvVidRAM1 = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x001000; + DrvPalRAM = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x000800; + + scroll = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + soundlatch = Next; Next += 0x000001; + video_priority = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[8] = { 0x030, 0x020, 0x010, 0x000, 0x038, 0x028, 0x018, 0x008 }; + INT32 Plane1[4] = { 0x600000, 0x200000, 0x400000, 0x000000 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x040, 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, 0x047 }; + INT32 XOffs1[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f }; + INT32 YOffs0[16] = { 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, + 0x400, 0x480, 0x500, 0x580, 0x600, 0x680, 0x700, 0x780 }; + INT32 YOffs1[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x400000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x400000; i++) { + tmp[i] = DrvGfxROM0[(i & ~7) | ((i & 6) >> 1) | ((i & 1) << 2)]; + } + + GfxDecode(0x4000, 8, 16, 16, Plane0, XOffs0, YOffs0, 0x800, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 game_select) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + INT32 offset = 0; + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + memset (DrvGfxROM0, 0xff, 0x400000); + + switch (game_select) + { + case 0: // magicbub + { + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000002, 5, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000003, 6, 4)) return 1; + offset = 7; + + is_magicbub = 1; + } + break; + + case 1: // magicbuba + { + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000002, 5, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000003, 6, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 7, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200001, 8, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200002, 9, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200003, 10, 4)) return 1; + offset = 11; + + is_magicbub = 1; + } + break; + + case 2: // paprazzi + { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000002, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000003, 5, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200000, 6, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200001, 7, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200002, 8, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x200003, 9, 4)) return 1; + offset = 10; + } + break; + + case 3: // shocking, bombkick + { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 2, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 3, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000002, 4, 4)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000003, 5, 4)) return 1; + offset = 6; + } + break; + } + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, offset + 0, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, offset + 1, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, offset + 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, offset + 3, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x040000, offset + 4, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x900000, 0x903fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x908000, 0x90bfff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0x90c000, 0x90ffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x910000, 0x910fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, magicbub_main_write_word); + SekSetWriteByteHandler(0, magicbub_main_write_byte); + SekSetReadWordHandler(0, magicbub_main_read_word); + SekSetReadByteHandler(0, magicbub_main_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xdfff, 2, DrvZ80ROM); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80RAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80RAM); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80RAM); + ZetSetOutHandler(magicbub_sound_out); + ZetSetInHandler(magicbub_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(4000000, &DrvYM3812IrqHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3000000); + + MSM6295Init(0, (is_magicbub ? 1056000 : 1000000) / 132, 60.0, is_magicbub); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM3812Exit(); + + SekExit(); + GenericTilesExit(); + + BurnFree (AllMem); + + is_magicbub = 0; + + return 0; +} + +static inline void DrvRecalcPal() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x2000; i++) { + if (i == 0x200) i = 0x1000; + INT32 d = p[i]; + + r = (d >> 10) & 0x1f; + g = (d >> 5) & 0x1f; + b = (d >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_layer(INT32 scr, INT32 pri) +{ + INT32 scrollx = scroll[scr * 2 + 0] + ((scr) ? 0x38 : 0x34) + ((is_magicbub) ? 32 : 0); + INT32 scrolly = scroll[scr * 2 + 1] + 0x10; + + UINT16 *vram = (UINT16*)(scr ? DrvVidRAM1 : DrvVidRAM0); + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= scrollx; + if (sx < -15) sx += 1024; + sy -= scrolly; + if (sy < -15) sy += 1024; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 ofst = (offs & 0xc00) + ((offs << 4) & 0x300) + ((offs >> 6) & 0x0f) + ((offs & 0x0f) << 4); + + INT32 code = vram[ofst * 2 + 0] & 0x3fff; + INT32 attr = vram[ofst * 2 + 1]; + + if (pri) { + if (attr & 0x20) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 8, 0x1000, DrvGfxROM0); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 8, 0x1000, DrvGfxROM0); + } + } else { + if (attr & 0x20) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 8, 0xff, 0x1000, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 8, 0xff, 0x1000, DrvGfxROM0); + } + } + } +} + +static void draw_sprites(INT32 pri) +{ + if ((*video_priority & 3) != pri) return; + + INT32 x_offset = is_magicbub ? 96 : 64; + UINT16 *vram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x1000 / 2; offs += 8 / 2) + { + INT32 sx = vram[offs + 0] - x_offset; + INT32 sy = vram[offs + 1] - 0x0f; + INT32 code = vram[offs + 2] & 0x1fff; + INT32 attr = vram[offs + 3]; + INT32 flipx = attr & 0x20; + INT32 flipy = attr & 0x40; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, attr & 0x1f, 4, 15, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, attr & 0x1f, 4, 15, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, attr & 0x1f, 4, 15, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, attr & 0x1f, 4, 15, 0, DrvGfxROM1); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPal(); + } + + if ((*video_priority & 0x0c) == 0x04) { + draw_layer(0, 1); + + if (nSpriteEnable & 1) draw_sprites(1); + + if (nBurnLayer & 2) draw_layer(0, 0); + if (nSpriteEnable & 2 )draw_sprites(2); + + if (nBurnLayer & 4) draw_layer(1, 0); + + if (nSpriteEnable & 4) { + draw_sprites(3); + draw_sprites(0); + } + } else if ((*video_priority & 0x0c) == 0x08) { + draw_layer(1, 1); + + if (nSpriteEnable & 1) draw_sprites(1); + + if (nBurnLayer & 2) draw_layer(1, 0); + + if (nSpriteEnable & 2)draw_sprites(2); + + if (nBurnLayer & 4) draw_layer(0, 0); + + if (nSpriteEnable & 4) { + draw_sprites(3); + draw_sprites(0); + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 2 * sizeof(UINT16)); + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 16000000 / 60, 3000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + if (is_magicbub == 0) continue; + + nSegment = nCyclesTotal[1] / nInterleave; + BurnTimerUpdateYM3812((1 + i) * nSegment); + } + + if (is_magicbub) { + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + } + + if (pBurnSoundOut) { + if (is_magicbub) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + } + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + + SCAN_VAR(soundbank); + + INT32 bank = soundbank; + soundbank = -1; + set_sample_bank(bank); + } + + return 0; +} + + +// Magic Bubble + +static struct BurnRomInfo magicbubRomDesc[] = { + { "magbuble.u33", 0x40000, 0x18fdd582, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "magbuble.u32", 0x40000, 0xf6ea7004, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "magbuble.143", 0x10000, 0x04192753, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "magbuble.u67", 0x80000, 0x6355e57d, 3 | BRF_GRA }, // 3 Background Tiles + { "magbuble.u68", 0x80000, 0x53ae6c2b, 3 | BRF_GRA }, // 4 + { "magbuble.u69", 0x80000, 0xb892e64c, 3 | BRF_GRA }, // 5 + { "magbuble.u70", 0x80000, 0x37794837, 3 | BRF_GRA }, // 6 + + { "magbuble.u20", 0x20000, 0xf70e3b8c, 4 | BRF_GRA }, // 7 Sprites + { "magbuble.u21", 0x20000, 0xad082cf3, 4 | BRF_GRA }, // 8 + { "magbuble.u22", 0x20000, 0x7c68df7a, 4 | BRF_GRA }, // 9 + { "magbuble.u23", 0x20000, 0xc7763fc1, 4 | BRF_GRA }, // 10 + + { "magbuble.131", 0x20000, 0x03e04e89, 5 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(magicbub) +STD_ROM_FN(magicbub) + +static INT32 MagicbubInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvMagicbub = { + "magicbub", NULL, NULL, NULL, "199?", + "Magic Bubble\0", NULL, "Yun Sung", "Yun Sung 16 Bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, magicbubRomInfo, magicbubRomName, NULL, NULL, MagicbubInputInfo, MagicbubDIPInfo, + MagicbubInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 320, 224, 4, 3 +}; + + +// Magic Bubble (Adult version) + +static struct BurnRomInfo magicbubaRomDesc[] = { + { "u33.bin", 0x40000, 0xa8164a02, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "u32.bin", 0x40000, 0x58f885ad, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "magbuble.143", 0x10000, 0x04192753, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "u67.bin", 0x80000, 0x89523dcd, 3 | BRF_GRA }, // 3 Background Tiles + { "u68.bin", 0x80000, 0x30e01a70, 3 | BRF_GRA }, // 4 + { "u69.bin", 0x80000, 0xfe357f52, 3 | BRF_GRA }, // 5 + { "u70.bin", 0x80000, 0x1398a473, 3 | BRF_GRA }, // 6 + { "u71.bin", 0x80000, 0x0844e017, 3 | BRF_GRA }, // 7 + { "u72.bin", 0x80000, 0x591db1cb, 3 | BRF_GRA }, // 8 + { "u73.bin", 0x80000, 0xcb4f3c3c, 3 | BRF_GRA }, // 9 + { "u74.bin", 0x80000, 0x81ff4910, 3 | BRF_GRA }, // 10 + + { "magbuble.u20", 0x20000, 0xf70e3b8c, 4 | BRF_GRA }, // 11 Sprites + { "magbuble.u21", 0x20000, 0xad082cf3, 4 | BRF_GRA }, // 12 + { "magbuble.u22", 0x20000, 0x7c68df7a, 4 | BRF_GRA }, // 13 + { "magbuble.u23", 0x20000, 0xc7763fc1, 4 | BRF_GRA }, // 14 + + { "magbuble.131", 0x20000, 0x03e04e89, 5 | BRF_SND }, // 15 Samples +}; + +STD_ROM_PICK(magicbuba) +STD_ROM_FN(magicbuba) + +static INT32 MagicbubaInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvMagicbuba = { + "magicbuba", "magicbub", NULL, NULL, "199?", + "Magic Bubble (Adult version)\0", NULL, "Yun Sung", "Yun Sung 16 Bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, magicbubaRomInfo, magicbubaRomName, NULL, NULL, MagicbubInputInfo, MagicbubaDIPInfo, + MagicbubaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 320, 224, 4, 3 +}; + + +// Paparazzi + +static struct BurnRomInfo paprazziRomDesc[] = { + { "u33.bin", 0x20000, 0x91f33abd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "u32.bin", 0x20000, 0xad5a3fec, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "u67.bin", 0x80000, 0xea0b9e27, 3 | BRF_GRA }, // 2 Background Tiles + { "u68.bin", 0x80000, 0x6b7ff4dd, 3 | BRF_GRA }, // 3 + { "u69.bin", 0x80000, 0x06749294, 3 | BRF_GRA }, // 4 + { "u70.bin", 0x80000, 0x0adacdf8, 3 | BRF_GRA }, // 5 + { "u71.bin", 0x80000, 0x69178fc4, 3 | BRF_GRA }, // 6 + { "u72.bin", 0x80000, 0x7c3384b9, 3 | BRF_GRA }, // 7 + { "u73.bin", 0x80000, 0x73fbc13e, 3 | BRF_GRA }, // 8 + { "u74.bin", 0x80000, 0xf1afda11, 3 | BRF_GRA }, // 9 + + { "u20.bin", 0x40000, 0xccb0ad6b, 4 | BRF_GRA }, // 10 Sprites + { "u21.bin", 0x40000, 0x125badf0, 4 | BRF_GRA }, // 11 + { "u22.bin", 0x40000, 0x436499c7, 4 | BRF_GRA }, // 12 + { "u23.bin", 0x40000, 0x358280fe, 4 | BRF_GRA }, // 13 + + { "u131.bin", 0x80000, 0xbcf7aa12, 5 | BRF_SND }, // 14 Samples +}; + +STD_ROM_PICK(paprazzi) +STD_ROM_FN(paprazzi) + +static INT32 PaprazziInit() +{ + return DrvInit(2); +} + +struct BurnDriver BurnDrvPaprazzi = { + "paprazzi", NULL, NULL, NULL, "1996", + "Paparazzi\0", NULL, "Yun Sung", "Yun Sung 16 Bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, paprazziRomInfo, paprazziRomName, NULL, NULL, MagicbubInputInfo, PaprazziDIPInfo, + PaprazziInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 224, 384, 3, 4 +}; + + +// Shocking + +static struct BurnRomInfo shockingRomDesc[] = { + { "yunsun16.u33", 0x40000, 0x8a155521, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "yunsun16.u32", 0x40000, 0xc4998c10, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "yunsun16.u67", 0x80000, 0xe30fb2c4, 3 | BRF_GRA }, // 2 Background Tiles + { "yunsun16.u68", 0x80000, 0x7d702538, 3 | BRF_GRA }, // 3 + { "yunsun16.u69", 0x80000, 0x97447fec, 3 | BRF_GRA }, // 4 + { "yunsun16.u70", 0x80000, 0x1b1f7895, 3 | BRF_GRA }, // 5 + + { "yunsun16.u20", 0x40000, 0x124699d0, 4 | BRF_GRA }, // 6 Sprites + { "yunsun16.u21", 0x40000, 0x4eea29a2, 4 | BRF_GRA }, // 7 + { "yunsun16.u22", 0x40000, 0xd6db0388, 4 | BRF_GRA }, // 8 + { "yunsun16.u23", 0x40000, 0x1fa33b2e, 4 | BRF_GRA }, // 9 + + { "yunsun16.131", 0x80000, 0xd0a1bb8c, 5 | BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(shocking) +STD_ROM_FN(shocking) + +static INT32 ShockingInit() +{ + return DrvInit(3); +} + +struct BurnDriver BurnDrvShocking = { + "shocking", NULL, NULL, NULL, "1997", + "Shocking\0", NULL, "Yun Sung", "Yun Sung 16 Bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0, + NULL, shockingRomInfo, shockingRomName, NULL, NULL, MagicbubInputInfo, ShockingDIPInfo, + ShockingInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 384, 224, 4, 3 +}; + + +// Bomb Kick + +static struct BurnRomInfo bombkickRomDesc[] = { + { "bk_u33", 0x40000, 0xd6eb50bf, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "bk_u32", 0x40000, 0xd55388a2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bk_u67", 0x80000, 0x1962f536, 3 | BRF_GRA }, // 2 Background Tiles + { "bk_u68", 0x80000, 0xd80c75a4, 3 | BRF_GRA }, // 3 + { "bk_u69", 0x80000, 0x615e1e6f, 3 | BRF_GRA }, // 4 + { "bk_u70", 0x80000, 0x59817ef1, 3 | BRF_GRA }, // 5 + + { "bk_u20", 0x40000, 0xc2b83e3f, 4 | BRF_GRA }, // 6 Sprites + { "bk_u21", 0x40000, 0xd6890192, 4 | BRF_GRA }, // 7 + { "bk_u22", 0x40000, 0x9538c46c, 4 | BRF_GRA }, // 8 + { "bk_u23", 0x40000, 0xe3831f3d, 4 | BRF_GRA }, // 9 + + { "bk_u131", 0x80000, 0x22cc5732, 5 | BRF_SND }, // 10 Samples +}; + +STD_ROM_PICK(bombkick) +STD_ROM_FN(bombkick) + +struct BurnDriver BurnDrvBombkick = { + "bombkick", NULL, NULL, NULL, "1998", + "Bomb Kick\0", NULL, "Yun Sung", "Yun Sung 16 Bit", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0, + NULL, bombkickRomInfo, bombkickRomName, NULL, NULL, BombkickInputInfo, BombkickDIPInfo, + ShockingInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 384, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_post90s/d_zerozone.cpp b/src/burn/drivers/misc_post90s/d_zerozone.cpp new file mode 100644 index 00000000..0557118f --- /dev/null +++ b/src/burn/drivers/misc_post90s/d_zerozone.cpp @@ -0,0 +1,552 @@ +// FB Alpha Zero Zone driver module +// Based on MAME driver by Brad Oliver + +#include "tiles_generic.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[4]; + +static UINT8 soundlatch; +static UINT8 tilebank; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 3, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + {"P1 Score Line (cheat)" , BIT_DIGITAL , DrvJoy2 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 4, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 11, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 10, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 9, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 8, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 13, "p2 fire 2"}, + {"P2 Score Line (cheat)" , BIT_DIGITAL , DrvJoy2 + 14, "p2 fire 3"}, + + {"Service" , BIT_DIGITAL , DrvJoy4 + 7, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x14, 0xff, 0xff, 0xdf, NULL }, + {0x15, 0xff, 0xff, 0xf7, NULL }, + + {0x14, 0xfe, 0, 8, "Coinage" }, + {0x14, 0x01, 0x07, 0x00, "5C 1C" }, + {0x14, 0x01, 0x07, 0x01, "4C 1C" }, + {0x14, 0x01, 0x07, 0x02, "3C 1C" }, + {0x14, 0x01, 0x07, 0x03, "2C 1C" }, + {0x14, 0x01, 0x07, 0x07, "1C 1C" }, + {0x14, 0x01, 0x07, 0x06, "1C 2C" }, + {0x14, 0x01, 0x07, 0x05, "1C 3C" }, + {0x14, 0x01, 0x07, 0x04, "1C 4C" }, + + {0x14, 0xfe, 0, 2, "Difficulty" }, + {0x14, 0x01, 0x08, 0x08, "In Game Default" }, + {0x14, 0x01, 0x08, 0x00, "Always Hard" }, + + {0x14, 0xfe, 0, 2, "Speed" }, + {0x14, 0x01, 0x10, 0x10, "Normal" }, + {0x14, 0x01, 0x10, 0x00, "Fast" }, + + {0x14, 0xfe, 0, 2, "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0x15, 0xfe, 0, 2, "Helps" }, + {0x15, 0x01, 0x04, 0x04, "1" }, + {0x15, 0x01, 0x04, 0x00, "2" }, + + {0x15, 0xfe, 0, 2, "Bonus Help" }, + {0x15, 0x01, 0x08, 0x00, "30000" }, + {0x15, 0x01, 0x08, 0x08, "None" }, + + {0x15, 0xfe, 0, 2, "Activate 'Score Line'? (Cheat)" }, + {0x15, 0x01, 0x10, 0x10, "No" }, + {0x15, 0x01, 0x10, 0x00, "Yes" }, +}; + +STDDIPINFO(Drv) + +UINT8 __fastcall zerozone_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + case 0x080001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0x080002: + case 0x080003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0x080008: + case 0x080009: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0x08000a: + case 0x08000b: + return DrvInputs[3] >> ((~address & 1) << 3); + } + + return 0; +} + +UINT16 __fastcall zerozone_read_word(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[0]; + + case 0x080002: + return DrvInputs[1]; + + case 0x080008: + return DrvInputs[2]; + + case 0x08000a: + return DrvInputs[3]; + } + + return 0; +} + +static void palette_write(INT32 offset) +{ + UINT8 r, b, g; + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + r = (data >> 11) & 0x1e; + r |= (data >> 3) & 0x01; + r = (r << 3) | (r >> 2); + + g = (data >> 7) & 0x1e; + g |= (data >> 2) & 0x01; + g = (g << 3) | (g >> 2); + + b = (data >> 3) & 0x1e; + b |= (data >> 1) & 0x01; + b = (b << 3) | (b >> 2); + + Palette[offset>>1] = (r << 16) | (g << 8) | b; + DrvPalette[offset>>1] = BurnHighCol(r, g, b, 0); + + return; +} + +void __fastcall zerozone_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffe00) == 0x88000) { + *((UINT16*)(DrvPalRAM + (address & 0x1fe))) = data; + palette_write(address & 0x1fe); + return; + } + + switch (address) + { + case 0x84000: + soundlatch = data >> 8; + ZetRaiseIrq(0xff); + return; + + case 0xb4000: + tilebank = data & 7; + return; + } + + return; +} + +void __fastcall zerozone_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x84000: + soundlatch = data; + ZetRaiseIrq(0xff); + return; + + case 0xb4001: + tilebank = data & 7; + return; + } + + return; +} + +void __fastcall zerozone_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall zerozone_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + soundlatch = 0; + tilebank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x020000; + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x010000; + DrvPalRAM = Next; Next += 0x000200; + DrvVidRAM = Next; Next += 0x004000; + + DrvZ80RAM = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0, 1, 2, 3 }; + INT32 XOffs[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; + INT32 YOffs[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x80000); + + GfxDecode(0x4000, 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM, 3, 1)) return 1; + + if (BurnLoadRom(DrvSndROM, 4, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x20000, 5, 1)) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0881ff, SM_ROM); + SekMapMemory(DrvVidRAM, 0x09ce00, 0x09ffff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0c0000, 0x0cffff, SM_RAM); + SekSetWriteByteHandler(0, zerozone_write_byte); + SekSetWriteWordHandler(0, zerozone_write_word); + SekSetReadByteHandler(0, zerozone_read_byte); + SekSetReadWordHandler(0, zerozone_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(zerozone_sound_write); + ZetSetReadHandler(zerozone_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132, 100.0, 0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x100; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + UINT16 *vram = (UINT16*)DrvVidRAM; + + for (INT32 offs = 0; offs < 0x800; offs++) + { + INT32 sy = (offs & 0x1f) << 3; + INT32 sx = (offs >> 5) << 3; + + sy -= 16; + sx -= 8; + if (sy < 0 || sx < 0 || sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 code = vram[offs] & 0x7ff; + INT32 color = vram[offs] >> 12; + + code += tilebank * (vram[offs] & 0x800); + + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = ~0; + DrvInputs[1] = ~0; + DrvInputs[2] = 0x00ff | (DrvDips[1] << 8); + DrvInputs[3] = 0xff00 | DrvDips[0]; + + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nTotalCycles[2] = { 10000000 / 60, 1000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + + nCyclesDone[0] += SekRun(nSegment); + + nSegment = (nTotalCycles[1] - nCyclesDone[1]) / (nInterleave - i); + + nCyclesDone[1] += ZetRun(nSegment); + } + + if (pBurnSoundOut) { + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029692; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + MSM6295Scan(0, nAction); + + SCAN_VAR(soundlatch); + SCAN_VAR(tilebank); + } + + return 0; +} + + +// Zero Zone + +static struct BurnRomInfo zerozoneRomDesc[] = { + { "zz-4.rom", 0x10000, 0x83718b9b, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "zz-5.rom", 0x10000, 0x18557f41, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "zz-1.rom", 0x08000, 0x223ccce5, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "zz-6.rom", 0x80000, 0xc8b906b9, 3 | BRF_GRA }, // 3 - Tiles + + { "zz-2.rom", 0x20000, 0xc7551e81, 4 | BRF_SND }, // 4 - MSM6295 Samples + { "zz-3.rom", 0x20000, 0xe348ff5e, 4 | BRF_SND }, // 5 +}; + +STD_ROM_PICK(zerozone) +STD_ROM_FN(zerozone) + +struct BurnDriver BurnDrvZerozone = { + "zerozone", NULL, NULL, NULL, "1993", + "Zero Zone\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, zerozoneRomInfo, zerozoneRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 368, 224, 4, 3 +}; + + +// Las Vegas Girl (Girl '94) + +static struct BurnRomInfo lvgirl94RomDesc[] = { + { "rom4", 0x10000, 0xc4fb449e, 1 | BRF_PRG | BRF_ESS }, // 0 - 68k Code + { "rom5", 0x10000, 0x5d446a1a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "rom1", 0x08000, 0x223ccce5, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "rom6", 0x40000, 0xeeeb94ba, 3 | BRF_GRA }, // 3 - Tiles + + { "rom2", 0x20000, 0xc7551e81, 4 | BRF_SND }, // 4 - MSM6295 Samples + { "rom3", 0x20000, 0xe348ff5e, 4 | BRF_SND }, // 5 +}; + +STD_ROM_PICK(lvgirl94) +STD_ROM_FN(lvgirl94) + +struct BurnDriver BurnDrvLvgirl94 = { + "lvgirl94", NULL, NULL, NULL, "1994", + "Las Vegas Girl (Girl '94)\0", NULL, "Comad", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_VSFIGHT, 0, + NULL, lvgirl94RomInfo, lvgirl94RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 368, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_post90s/deco16ic.cpp b/src/burn/drivers/misc_post90s/deco16ic.cpp new file mode 100644 index 00000000..32cd428d --- /dev/null +++ b/src/burn/drivers/misc_post90s/deco16ic.cpp @@ -0,0 +1,3201 @@ +/* +TO DO! + +// column scroll needs improved does 'size' (16/8) sized columns rather than 1pxl +// this affects boogie wings +// why is mutant fight's scrolling off in title? + +1 Double Wings MBE 102 52 141 104 +*/ + + + +#include "tiles_generic.h" +#include "bitswap.h" + +static INT32 deco16_layer_size[4]; +static INT32 deco16_layer_size_select[4]; + +static INT32 (*deco16_bank_callback[4])(const INT32 bank); + +static INT32 deco16_pf_colorbank[4]; +static INT32 deco16_pf_colormask[4]; +static INT32 deco16_pf_transmask[4]; + +static INT32 deco16_pf_bank[4]; + +static INT32 deco16_pf_gfx_bank[4]; // (1/2) 8x8, 16x16, (2/3) 8x8, 16x16 + +static UINT16 deco16_scroll_x[4][ 512]; // 512 +static UINT16 deco16_scroll_y[4][1024]; // 1024 + +static INT32 deco16_enable_rowscroll[4]; +static INT32 deco16_enable_colscroll[4]; + +static INT32 deco16_global_x_offset = 0; +static INT32 deco16_global_y_offset = 0; + +static INT32 deco16_scroll_offset[4][2][2]; // tmap, size, x, y + +static UINT16 transmask[4][2]; + +INT32 deco16_graphics_mask[3]; + +UINT8 *deco16_graphics[3]; + +UINT16 *deco16_pf_control[2]; +UINT8 *deco16_pf_ram[4] = { NULL, NULL, NULL, NULL }; +UINT8 *deco16_pf_rowscroll[4];//4 or 2? + +UINT16 deco16_priority; + +UINT8 *deco16_prio_map; +UINT8 *deco16_sprite_prio_map; // boogwing + +INT32 deco16_vblank; + +void deco16ProtScan(); +void deco16ProtReset(); + +INT32 deco16_get_tilemap_size(INT32 tmap) +{ + return deco16_layer_size_select[tmap]; +} + +// painfully unfast. +void deco16_draw_prio_sprite(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri, INT32 spri) +{ + gfx += code * 0x100; + + INT32 flip = 0; + if (flipx) flip |= 0x0f; + if (flipy) flip |= 0xf0; + + sy -= deco16_global_y_offset; + sx -= deco16_global_x_offset; + + for (INT32 yy = 0; yy < 16; yy++, sy++) { + + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 xx = 0; xx < 16; xx++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((yy * 16) + xx) ^ flip]; + + if (!pxl) continue; + + if (pri != -1) { + INT32 bpriority = deco16_prio_map[(sy * 512) + sx]; + + if (spri == -1) { + if ((pri & (1 << (bpriority & 0x1f))) || (bpriority & 0x80)) continue; + deco16_prio_map[sy * 512 + sx] |= 0x80; // right? + } else { + if (pri <= bpriority || spri <= deco16_sprite_prio_map[sy * 512 + sx]) continue; + deco16_sprite_prio_map[sy * 512 + sx] = spri; + deco16_prio_map[sy * 512 + sx] = pri; // right? + } + } + + dest[sy * nScreenWidth + sx] = pxl | color; + + deco16_prio_map[sy * 512 + sx] |= 0x80; // right? + } + + sx -= 16; + } +} + +void deco16_draw_prio_sprite(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri) +{ + deco16_draw_prio_sprite(dest, gfx, code, color, sx, sy, flipx, flipy, pri, -1); +} + +static inline UINT32 alpha_blend(UINT32 d, UINT32 s, UINT32 p) +{ + INT32 a = 256 - p; + + return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) | + ((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) >> 8; +} + +void deco16_draw_alphaprio_sprite(UINT32 *palette, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri, INT32 spri, INT32 alpha) +{ + if (alpha == 0) return; + + gfx += code * 0x100; + + INT32 flip = 0; + if (flipx) flip |= 0x0f; + if (flipy) flip |= 0xf0; + + sy -= deco16_global_y_offset; + sx -= deco16_global_x_offset; + + UINT32 *dest = (UINT32*)pBurnDraw; + + for (INT32 yy = 0; yy < 16; yy++, sy++) { + + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 xx = 0; xx < 16; xx++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((yy * 16) + xx) ^ flip]; + + if (!pxl) continue; + + INT32 bpriority = deco16_prio_map[(sy * 512) + sx]; + + if (spri == -1) { + if ((pri & (1 << (bpriority & 0x1f))) || (bpriority & 0x80)) continue; + deco16_prio_map[sy * 512 + sx] |= 0x80; // right? + } else { + if (pri <= bpriority || spri <= deco16_sprite_prio_map[sy * 512 + sx]) continue; + deco16_sprite_prio_map[sy * 512 + sx] = spri; + deco16_prio_map[sy * 512 + sx] = pri; // right? + } + + if (alpha == 0xff) { + dest[sy * nScreenWidth + sx] = palette[pxl | color]; + } else { + dest[sy * nScreenWidth + sx] = alpha_blend(dest[sy * nScreenWidth + sx], palette[pxl | color], alpha); + } + } + + sx -= 16; + } +} + +void deco16_palette_recalculate(UINT32 *palette, UINT8 *pal) +{ + UINT16 *p = (UINT16*)pal; + + for (INT32 i = 0; i < BurnDrvGetPaletteEntries() * 2; i+=2) + { + INT32 b = (p[i + 0] >> 0) & 0xff; + INT32 g = (p[i + 1] >> 8) & 0xff; + INT32 r = (p[i + 1] >> 0) & 0xff; + + palette[i/2] = BurnHighCol(r, g, b, 0); + } +} + +void deco16_tile_decode(UINT8 *src, UINT8 *dst, INT32 len, INT32 type) +{ + INT32 Plane[4] = { ((len / 2) * 8) + 8, ((len / 2) * 8) + 0, 0x00008, 0x00000 }; + INT32 XOffs[16] = { 32*8+0, 32*8+1, 32*8+2, 32*8+3, 32*8+4, 32*8+5, 32*8+6, 32*8+7, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }; + + INT32 Plane1[8] = { 0x100000*8+8, 0x100000*8, 0x40000*8+8, 0x40000*8, 0xc0000*8+8, 0xc0000*8, 8, 0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, src, len); + + if (type == 2) { //16x16x8bpp + GfxDecode(4096, 8, 16, 16, Plane1, XOffs + 0, YOffs, 0x200, tmp, dst); + } else if (type == 1) { // 8x8 + GfxDecode((len * 2) / 0x040, 4, 8, 8, Plane, XOffs + 8, YOffs, 0x080, tmp, dst); + } else { + GfxDecode((len * 2) / 0x100, 4, 16, 16, Plane, XOffs + 0, YOffs, 0x200, tmp, dst); + } + + BurnFree (tmp); +} + +void deco16_sprite_decode(UINT8 *gfx, INT32 len) +{ + INT32 Plane[4] = { 24,8,16,0 }; + INT32 XOffs[16] = { 512,513,514,515,516,517,518,519, 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32,10*32,11*32,12*32,13*32,14*32,15*32}; + + UINT8 *tmp = (UINT8*)BurnMalloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, gfx, len); + + GfxDecode((len * 2) / 0x100, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, gfx); + + BurnFree (tmp); +} + +void deco16_draw_layer(INT32 tmap, UINT16 *dest, INT32 flags) +{ + INT32 size = deco16_layer_size_select[tmap]; + if (size == -1) return; + + INT32 control = deco16_pf_control[tmap / 2][6]; + if (tmap & 1) control >>= 8; + +// INT32 control0 = deco16_pf_control[tmap / 2][5]; +// if (tmap & 1) control0 >>= 8; +// if ((control0 & 0x80) == 0) return; // layer disable bit + + INT32 select = (tmap & 2) + ((tmap < 2) ? size : 0); + + size = size ? 16 : 8; + + INT32 bpp = (flags & 0x100000) ? 8 : 4; + if (flags & 0x200000) bpp = 5; + + UINT8 *gfx = deco16_graphics[select]; + INT32 gfxmask = deco16_graphics_mask[select]; + + UINT16 *vram = (UINT16 *)deco16_pf_ram[tmap]; + + INT32 tmask = transmask[tmap][(flags & 0x00100) >> 8]; + if (flags & 0x10000) tmask = 0; // opaque! + + INT32 priority = flags & 0x000ff; + + INT32 tilebank = deco16_pf_bank[tmap]; + INT32 colmask = deco16_pf_colormask[tmap]; + INT32 colbank = deco16_pf_colorbank[tmap] >> bpp; + + INT32 hmask = (32 * size) - 1; + INT32 wmask = (deco16_layer_size[tmap] * size) - 1; + INT32 shift = (wmask & 0x100) ? 6 : 5; + INT32 smask = size - 1; + + for (INT32 y = 0; y < nScreenHeight; y++) + { + INT32 xoff = deco16_scroll_x[tmap][y] & wmask; + + for (INT32 x = 0; x < nScreenWidth + size; x+=size) + { + INT32 yoff = deco16_scroll_y[tmap][x] & hmask; + + INT32 yy = (y + yoff) & hmask; + INT32 xx = (x + xoff) & wmask; + + INT32 col = xx / size; + INT32 row = yy / size; + + INT32 ofst; + if (size == 8) { + ofst = (row << shift) | (col); + } else { + ofst = (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 5) + ((row & 0x20) << 6); + } + + INT32 code = vram[ofst]; + INT32 color = code >> 12; + + INT32 flipx = 0; + INT32 flipy = 0; + + if ((color & 0x0008) && (control & 0x03)) { + flipx = control & 0x01; + flipy = control & 0x02; + color &= 0x07; + } + + code = ((code & 0xfff) | tilebank) & gfxmask; + color = (color & colmask) + colbank; + + { + color <<= bpp; + + INT32 sx = x - (xx & smask); + + INT32 sy = yy & smask; + if (flipy) sy ^= smask; + + UINT8 *src = gfx + (code * size * size) + (sy * size); + + if (flipx) flipx = smask; + + for (INT32 xxx = 0; xxx < size; xxx++) { + if ((xxx + sx) < 0 || (xxx + sx) >= nScreenWidth) continue; + + INT32 pxl = src[xxx^flipx]; + + if ((tmask & (1 << pxl))) continue; + + dest[y * nScreenWidth + xxx + sx] = pxl | color; + deco16_prio_map[y * 512 + xxx + sx] = priority; + } + } + } + } +} + +void deco16_set_bank_callback(INT32 tmap, INT32 (*callback)(const INT32 bank)) +{ + deco16_bank_callback[tmap] = callback; +} + +void deco16_set_color_base(INT32 tmap, INT32 base) +{ + deco16_pf_colorbank[tmap & 3] = base; +} + +void deco16_set_color_mask(INT32 tmap, INT32 mask) +{ + deco16_pf_colormask[tmap & 3] = mask; +} + +void deco16_set_transparency_mask(INT32 tmap, INT32 mask) +{ + deco16_pf_transmask[tmap & 3] = mask; +} + +void deco16_set_gfxbank(INT32 tmap, INT32 small, INT32 big) +{ + deco16_pf_gfx_bank[0 + (tmap & 2)] = small; + deco16_pf_gfx_bank[1 + (tmap & 2)] = big; +} + +void deco16_set_global_offsets(INT32 x, INT32 y) +{ + deco16_global_x_offset = x; + deco16_global_y_offset = y; +} + +static void set_transmask(INT32 tmap, INT32 tmask0, INT32 tmask1) +{ + transmask[tmap][0] = tmask0; + transmask[tmap][1] = tmask1; +} + +static void set_graphics_mask(INT32 gfx, INT32 len) +{ + INT32 b = 1; + + while (b < (len - 1)) { + b <<= 1; + } + + deco16_graphics_mask[gfx] = b - 1; +} + +void deco16_set_graphics(INT32 num, UINT8 *gfx, INT32 len, INT32 size /*tile size*/) +{ + deco16_graphics[num] = gfx; + + set_graphics_mask(num, len / (size * size)); +} + +void deco16_set_graphics(UINT8 *gfx0, INT32 len0, UINT8 *gfx1, INT32 len1, UINT8 *gfx2, INT32 len2) +{ + deco16_graphics[0] = gfx0; + deco16_graphics[1] = gfx1; + deco16_graphics[2] = gfx2; + + set_graphics_mask(0, len0 / (8 * 8)); + set_graphics_mask(1, len1 / (16 * 16)); + set_graphics_mask(2, len2 / (16 * 16)); +} + +void deco16_clear_prio_map() +{ + memset(deco16_prio_map, 0, 512 * 256); + memset(deco16_sprite_prio_map, 0, 512 * 256); +} + +void deco16_set_scroll_offs(INT32 tmap, INT32 size, INT32 offsetx, INT32 offsety) +{ + deco16_scroll_offset[tmap][size][0] = offsetx; + deco16_scroll_offset[tmap][size][1] = offsety; +} + +void deco16Init(INT32 no_pf34, INT32 split, INT32 full_width) +{ + set_transmask(0, 0x0001, 0xffff); + set_transmask(1, 0x0001, 0xffff); + set_transmask(2, 0x0001, 0xffff); + set_transmask(3, 0x0001, 0xffff); + + if (split) { + set_transmask(1, 0xff01, 0x00ff); + } + + memset (deco16_scroll_offset, 0, 4 * 2 * 2 * sizeof(INT32)); + + deco16_pf_ram[0] = (UINT8*)BurnMalloc(0x2000); // ok + deco16_pf_ram[1] = (UINT8*)BurnMalloc(0x2000); + + deco16_pf_rowscroll[0] = (UINT8*)BurnMalloc(0x1000);// plenty + deco16_pf_rowscroll[1] = (UINT8*)BurnMalloc(0x1000); + + deco16_pf_control[0] = (UINT16*)BurnMalloc(0x10); //1/2 + deco16_pf_control[1] = (UINT16*)BurnMalloc(0x10); //3/4 + + if (no_pf34 == 0) { + deco16_pf_ram[2] = (UINT8*)BurnMalloc(0x2000); // right? + deco16_pf_ram[3] = (UINT8*)BurnMalloc(0x2000); + + deco16_pf_rowscroll[2] = (UINT8*)BurnMalloc(0x1000); // right? + deco16_pf_rowscroll[3] = (UINT8*)BurnMalloc(0x1000); + } + + deco16_prio_map = (UINT8*)BurnMalloc(512 * 256); // priority map + deco16_sprite_prio_map = (UINT8*)BurnMalloc(512 * 256); + + deco16_bank_callback[0] = NULL; + deco16_bank_callback[1] = NULL; + deco16_bank_callback[2] = NULL; + deco16_bank_callback[3] = NULL; + + deco16_layer_size[0] = 64; + deco16_layer_size[1] = full_width ? 64 : 32; + deco16_layer_size[2] = (!no_pf34) ? (full_width ? 64 : 32) : 0; + deco16_layer_size[3] = (!no_pf34) ? (full_width ? 64 : 32) : 0; + + deco16_pf_transmask[0] = 15; + deco16_pf_transmask[1] = 15; + deco16_pf_transmask[2] = 15; + deco16_pf_transmask[3] = 15; + + deco16_pf_colormask[0] = 15; + deco16_pf_colormask[1] = 15; + deco16_pf_colormask[2] = 15; + deco16_pf_colormask[3] = 15; + + deco16_pf_bank[0] = 0; + deco16_pf_bank[1] = 0; + deco16_pf_bank[2] = 0; + deco16_pf_bank[3] = 0; + + deco16_pf_colorbank[0] = 0; + deco16_pf_colorbank[1] = 16 << 4; // 2 + deco16_pf_colorbank[2] = 0; + deco16_pf_colorbank[3] = 16 << 4; // 4 + + deco16_pf_gfx_bank[0] = 0; + deco16_pf_gfx_bank[1] = 1; + deco16_pf_gfx_bank[2] = 2; + + deco16_layer_size_select[0] = 1; //16x16 + deco16_layer_size_select[1] = 1; + deco16_layer_size_select[2] = 1; + deco16_layer_size_select[3] = 1; + + deco16_global_x_offset = 0; + deco16_global_y_offset = 0; + + deco16_priority = 0; +} + +void deco16Reset() +{ + memset (deco16_pf_rowscroll[0], 0, 0x1000); + memset (deco16_pf_rowscroll[1], 0, 0x1000); + + if (deco16_pf_rowscroll[2]) { + memset (deco16_pf_rowscroll[2], 0, 0x1000); + memset (deco16_pf_rowscroll[3], 0, 0x1000); + } + + memset (deco16_pf_control[0], 0, 16); + memset (deco16_pf_control[1], 0, 16); + memset (deco16_pf_ram[0], 0, 0x2000); + memset (deco16_pf_ram[1], 0, 0x2000); + + if (deco16_pf_ram[2]) { + memset (deco16_pf_ram[2], 0, 0x2000); + memset (deco16_pf_ram[3], 0, 0x2000); + } + + deco16_priority = 0; + + deco16ProtReset(); +} + +void deco16Exit() +{ + BurnFree(deco16_prio_map); + + BurnFree (deco16_sprite_prio_map); + + for (INT32 i = 0; i < 4; i++) { + BurnFree (deco16_pf_rowscroll[i]); + BurnFree (deco16_pf_ram[i]); + } + + BurnFree (deco16_pf_control[0]); + BurnFree (deco16_pf_control[1]); +} + +static void pf_update(INT32 tmap, INT32 scrollx, INT32 scrolly, UINT16 *rowscroll, INT32 control0, INT32 control1) +{ + if (~tmap & 2) { + if (control1 & 0x80) { + deco16_layer_size_select[tmap] = (control0 & 0x80) ? 0 : -1; // 8x8 + } else { + deco16_layer_size_select[tmap] = (control0 & 0x80) ? 1 : -1; // 16x16 + } + } + + deco16_enable_rowscroll[tmap] = 0; + deco16_enable_colscroll[tmap] = 0; + + if (rowscroll == NULL) return; + + if ((control1 & 0x40) == 0x40) // row scroll + { + INT32 size = deco16_layer_size_select[tmap] ? 16 : 8; + + INT32 rows = 1; + INT32 row_sel = (control0 >> 3) & 0x0f; + if (row_sel < 9) rows = 0x200 >> row_sel; + + INT32 rownum = 512; + + if (size == 8) { + rows /= 2; + rownum /= 2; + if (rows == 0) rows = 1; + } + + if (rows != 1) deco16_enable_rowscroll[tmap] = 1; + + INT32 rsize = rownum / rows; + + INT32 xscroll = scrollx + deco16_global_x_offset + deco16_scroll_offset[tmap][size/16][0]; + + for (INT32 r = 0; r < rows; r++) { + for (INT32 p = rsize * r; p < (rsize * r) + rsize; p++) { + deco16_scroll_x[tmap][(p - deco16_global_y_offset) & 0x1ff] = xscroll + rowscroll[r]; + } + } + + if (~control1 & 0x20) { + for (INT32 r = 0; r < 1024; r++) { + deco16_scroll_y[tmap][r] = scrolly + deco16_global_y_offset; + } + } + } + + if ((control1 & 0x20) == 0x20) // column scroll + { + INT32 size = deco16_layer_size_select[tmap] ? 16 : 8; + + INT32 mask = (0x40 >> (control0 & 0x07)) - 1; + if (mask < 0) mask = 0; + + INT32 cols = 1024 / (8 << (control0 & 0x07)); + + INT32 colnum = 1024; + + if (size == 8) { + cols /= 2; + colnum /= 2; + if (cols == 0) cols = 1; + } + + if (cols != 1) deco16_enable_rowscroll[tmap] = 1; + + INT32 rsize = colnum / cols; + + for (INT32 r = 0; r < cols; r++) { + for (INT32 p = rsize * r; p < (rsize * r) + rsize; p++) { + deco16_scroll_y[tmap][p] = scrolly + rowscroll[(r & mask) + 0x200] + deco16_global_y_offset; + } + } + + if (~control1 & 0x40) { + INT32 xscroll = scrollx + deco16_global_x_offset + deco16_scroll_offset[tmap][size/16][0]; + + for (INT32 r = 0; r < 512; r++) { + deco16_scroll_x[tmap][(r - deco16_global_y_offset) & 0x1ff] = xscroll; + } + } + } + + if ((control1 & 0x60) == 0x00) // normal scroll + { + INT32 size = deco16_layer_size_select[tmap] ? 16 : 8; + + for (INT32 r = 0; r < 1024; r++) { + deco16_scroll_y[tmap][r] = scrolly + deco16_global_y_offset; + } + + INT32 xscroll = scrollx + deco16_global_x_offset + deco16_scroll_offset[tmap][size/16][0]; + + for (INT32 r = 0; r < 512; r++) { + deco16_scroll_x[tmap][(r - deco16_global_y_offset) & 0x1ff] = xscroll; + } + } +} + +void deco16_pf12_update() +{ + if (deco16_bank_callback[0]) deco16_pf_bank[0] = deco16_bank_callback[0](deco16_pf_control[0][7] & 0xff); + if (deco16_bank_callback[1]) deco16_pf_bank[1] = deco16_bank_callback[1](deco16_pf_control[0][7] >> 8); + + pf_update(0, deco16_pf_control[0][1], deco16_pf_control[0][2], (UINT16 *)deco16_pf_rowscroll[0], deco16_pf_control[0][5] & 0xff, deco16_pf_control[0][6] & 0xff); + pf_update(1, deco16_pf_control[0][3], deco16_pf_control[0][4], (UINT16 *)deco16_pf_rowscroll[1], deco16_pf_control[0][5] >> 8 , deco16_pf_control[0][6] >> 8); +} + +void deco16_pf34_update() +{ + if (deco16_bank_callback[2]) deco16_pf_bank[2] = deco16_bank_callback[2](deco16_pf_control[1][7] & 0xff); + if (deco16_bank_callback[3]) deco16_pf_bank[3] = deco16_bank_callback[3](deco16_pf_control[1][7] >> 8); + + pf_update(2, deco16_pf_control[1][1], deco16_pf_control[1][2], (UINT16 *)deco16_pf_rowscroll[2], deco16_pf_control[1][5] & 0xff, deco16_pf_control[1][6] & 0xff); + pf_update(3, deco16_pf_control[1][3], deco16_pf_control[1][4], (UINT16 *)deco16_pf_rowscroll[3], deco16_pf_control[1][5] >> 8 , deco16_pf_control[1][6] >> 8); +} + +void deco16Scan() +{ + struct BurnArea ba; + + { + char name[128]; + + for (INT32 i = 0; i < 4; i++) { + if (deco16_pf_ram[i] == NULL) continue; + + // memset(&ba, 0, sizeof(ba)); + ba.Data = deco16_pf_ram[i]; + ba.nLen = 0x2000; + sprintf (name, "Deco16ic RAM %d", i); + ba.szName = name; + BurnAcb(&ba); + + // memset(&ba, 0, sizeof(ba)); + ba.Data = deco16_pf_rowscroll[i]; + ba.nLen = 0x1000; + sprintf (name, "Deco16ic Rowscroll %d", i); + ba.szName = name; + BurnAcb(&ba); + } + + memset(&ba, 0, sizeof(ba)); + ba.Data = (UINT8*)deco16_pf_control[0]; + ba.nLen = 16; + ba.szName = "Deco16ic Control 0"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = (UINT8*)deco16_pf_control[1]; + ba.nLen = 16; + ba.szName = "Deco16ic Control 1"; + BurnAcb(&ba); + + SCAN_VAR(deco16_priority); + SCAN_VAR(deco16_vblank); + } + + deco16ProtScan(); +} + + +//--------------------------------------------------------------------------------------------------------------------------------------------------- +// Data East common sound routines + +#define ENABLE_HUC6280 + +#ifdef ENABLE_HUC6280 +#include "h6280_intf.h" +#endif + +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +static INT32 deco16_sound_enable[4]; // ym2203, ym2151, msm6295 0, msm6295 1 +static INT32 deco16_sound_cpuclock = 0; + +INT32 deco16_soundlatch; + +static void deco16YM2151IrqHandler(INT32 state) +{ +#ifdef ENABLE_HUC6280 + h6280SetIRQLine(1, state ? H6280_IRQSTATUS_ACK : H6280_IRQSTATUS_NONE); +#else + state = state; +#endif +} + +static INT32 deco16SynchroniseStream(INT32 nSoundRate) +{ +#ifdef ENABLE_HUC6280 + return (INT64)h6280TotalCycles() * nSoundRate / deco16_sound_cpuclock; +#else + return 0 * nSoundRate; +#endif +} + +static double deco16GetTime() +{ +#ifdef ENABLE_HUC6280 + return (double)h6280TotalCycles() / (deco16_sound_cpuclock * 1.0); +#else + return 0; +#endif +} + +static void deco16_sound_write(UINT32 address, UINT8 data) +{ +//bprintf (0, _T("%5.5x, %2.2x\n"), address, data); + + switch (address) + { + case 0x100000: + case 0x100001: // ym2203 (not for these games...) + return; + + case 0x110000: + BurnYM2151SelectRegister(data); + return; + + case 0x110001: + BurnYM2151WriteRegister(data); + return; + + case 0x120000: + case 0x120001: + MSM6295Command(0, data); + return; + + case 0x130000: + case 0x130001: + MSM6295Command(1, data); + return; + + case 0x1fec00: + case 0x1fec01: +#ifdef ENABLE_HUC6280 + h6280_timer_w(address & 1, data); +#endif + return; + + case 0x1ff400: + case 0x1ff401: + case 0x1ff402: + case 0x1ff403: +#ifdef ENABLE_HUC6280 + h6280_irq_status_w(address & 3, data); +#endif + return; + } +} + +static UINT8 deco16_sound_read(UINT32 address) +{ +//bprintf (0, _T("%5.5x, rb\n"), address); + + + switch (address) + { + case 0x110000: + return 0xff; + + case 0x110001: + return BurnYM2151ReadStatus(); + + case 0x120000: + case 0x120001: + return MSM6295ReadStatus(0); + + case 0x130000: + case 0x130001: + return MSM6295ReadStatus(1); + + case 0x140000: + case 0x140001: +#ifdef ENABLE_HUC6280 + h6280SetIRQLine(0, H6280_IRQSTATUS_NONE); +#endif + return deco16_soundlatch; + } + + return 0; +} + +void deco16SoundReset() +{ +#ifdef ENABLE_HUC6280 + h6280Open(0); + h6280Reset(); + h6280Close(); +#endif + + if (deco16_sound_enable[0]) BurnYM2151Reset(); + if (deco16_sound_enable[1]) BurnYM2203Reset(); + if (deco16_sound_enable[2]) MSM6295Reset(0); + if (deco16_sound_enable[3]) MSM6295Reset(1); + + deco16_soundlatch = 0; +} + +void deco16SoundInit(UINT8 *rom, UINT8 *ram, INT32 huc_clock, INT32 ym2203, void (ym2151_port)(UINT32,UINT32), double ym2151vol, INT32 msmclk0, double msmvol0, INT32 msmclk1, double msmvol1) +{ +#ifdef ENABLE_HUC6280 + h6280Init(1); + h6280Open(0); + h6280MapMemory(rom, 0x000000, 0x00ffff, H6280_ROM); + h6280MapMemory(ram, 0x1f0000, 0x1f1fff, H6280_RAM); + h6280SetWriteHandler(deco16_sound_write); + h6280SetReadHandler(deco16_sound_read); + h6280Close(); +#else + rom = rom; + ram = ram; +#endif + + deco16_sound_cpuclock = huc_clock; + + deco16_sound_enable[0] = 1; // ym2151 always enabled + deco16_sound_enable[1] = ym2203 ? 1 : 0; + deco16_sound_enable[2] = 1; // msm6295 #0 always enabled + deco16_sound_enable[3] = msmclk1 ? 1 : 0; + + BurnYM2151Init(3580000, ym2151vol); + BurnYM2151SetIrqHandler(&deco16YM2151IrqHandler); + if (ym2151_port) BurnYM2151SetPortHandler(ym2151_port); + + if (ym2203) { + BurnYM2203Init(1, 4027500, NULL, deco16SynchroniseStream, deco16GetTime, 1); +#ifdef ENABLE_HUC6280 + BurnTimerAttachH6280(deco16_sound_cpuclock); +#endif + } + + MSM6295Init(0, msmclk0 / 132, msmvol0, 1); + + if (msmclk1) { + MSM6295Init(1, msmclk1 / 132, msmvol1, 1); + } +} + +void deco16SoundExit() +{ +#ifdef ENABLE_HUC6280 + h6280Exit(); +#endif + + if (deco16_sound_enable[0]) BurnYM2151Exit(); + if (deco16_sound_enable[1]) BurnYM2203Exit(); + if (deco16_sound_enable[2]) MSM6295Exit(0); + if (deco16_sound_enable[3]) MSM6295Exit(1); + + MSM6295ROM = NULL; + + deco16_sound_enable[0] = 0; + deco16_sound_enable[1] = 0; + deco16_sound_enable[2] = 0; + deco16_sound_enable[3] = 0; + + deco16_sound_cpuclock = 0; +} + +void deco16SoundUpdate(INT16 *buf, INT32 len) +{ + if (deco16_sound_enable[0]) BurnYM2151Render(buf, len); + if (deco16_sound_enable[1]) BurnYM2203Update(buf, len); + if (deco16_sound_enable[2]) MSM6295Render(0, buf, len); + if (deco16_sound_enable[3]) MSM6295Render(1, buf, len); +} + + + + +//--------------------------------------------------------------------------------------------------------------------------------------------------- +// Data East decryption routines + +static const UINT16 xor_masks[16] = +{ + 0xd556,0x73cb,0x2963,0x4b9a,0xb3bc,0xbc73,0xcbc9,0xaeb5, + 0x1e6d,0xd5b5,0xe676,0x5cc5,0x395a,0xdaae,0x2629,0xe59e, +}; + +static const UINT8 swap_patterns[8][16] = +{ + { 0xf,0x8,0x9,0xc,0xa,0xd,0xb,0xe, 0x2,0x7,0x4,0x3,0x1,0x5,0x6,0x0 }, + { 0xc,0xa,0xb,0x9,0x8,0xf,0xe,0xd, 0x6,0x0,0x3,0x5,0x7,0x4,0x2,0x1 }, + { 0x8,0xc,0xb,0x9,0xd,0xe,0xf,0xa, 0x4,0x6,0x5,0x0,0x3,0x1,0x7,0x2 }, + { 0x8,0x9,0xa,0xd,0xb,0xf,0xe,0xc, 0x5,0x4,0x0,0x7,0x2,0x6,0x1,0x3 }, + { 0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb, 0x1,0x5,0x0,0x3,0x2,0x7,0x6,0x4 }, + { 0xe,0xf,0xd,0x8,0xc,0xa,0xb,0x9, 0x1,0x2,0x7,0x6,0x4,0x3,0x0,0x5 }, + { 0xd,0xe,0xa,0xb,0x9,0x8,0xc,0xf, 0x3,0x1,0x7,0x4,0x5,0x0,0x2,0x6 }, + { 0x9,0x8,0xe,0xa,0xf,0xb,0xd,0xc, 0x6,0x0,0x5,0x2,0x4,0x1,0x3,0x7 }, +}; + +static const UINT8 deco56_xor_table[0x800] = +{ + 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9,10, 7,11,11, 9,11, 3, 7,10,12,13, 3,14, 0, 0, 9, 0,15, 3, 4,14, + 6, 3,14,14, 3,12, 3,13, 9, 5,13, 3, 8, 2, 7,14, 2, 5, 1, 2, 3, 4,14,11, 8, 0, 6, 7,10, 3, 4, 7, + 15, 1, 2, 7, 7,14,15, 0, 7, 9,15, 3,14,10, 9,12,11,12, 2, 8, 1,10, 9,14, 5, 6,15,10, 4,15, 5, 2, + 3, 2, 4,15, 7, 7,10,13, 1,13, 6, 6, 7, 5,10, 9, 5,15,14, 2, 7,12, 7, 4, 2,15,12,10,11,15, 4, 6, + 9, 3,11,13, 0, 3, 6, 4,15, 8, 3, 8, 0, 3,13, 8, 6, 0,11, 4, 9, 7,11, 1, 8, 1,10, 9, 2, 8,11,15, + 2, 8,10, 5, 3, 8, 0,10, 0,15, 3, 1,15, 3, 8, 6,13,11,10, 4,15, 4, 4, 3, 7, 7,15, 3,11,15,15, 2, + 3, 7,13, 4,10,12, 9, 8,11, 2, 5, 8, 7, 4,14, 0,12, 1,15,10, 3,10, 5,13, 1, 4, 0, 7, 7, 2, 8,15, + 12, 1, 9,14,12, 9,11, 5,13, 1,12,12,14, 8, 8,13, 4,13, 1,12,10, 1,10,15, 7, 5, 1,13,10,10,15, 1, + 3,14,13, 0, 0, 1, 3, 9, 5, 0, 4,13, 6,14, 2, 8, 3, 3, 5, 8, 1,10, 7, 5,13, 4, 2,12, 5, 1, 0, 4, + 4, 6,14,10, 6, 3,11,10, 0,10, 2, 3,11,11,15,13, 3,10, 3, 8, 3, 4, 7, 1, 5, 3, 9, 8,14,13,13, 4, + 1, 0, 1,12,12,12,11,11, 3, 7, 4,10,10, 3,10, 3, 1, 7, 4, 6, 2,12, 3, 3, 0, 0,10, 0, 6, 8, 0, 7, + 2,15,10,14, 1,14, 4,12, 4, 2, 3, 4, 8, 0,10,10,15, 1, 8, 4,11, 2,12, 6,12,12,12, 2, 4, 6, 3,12, + 4, 7,14,11,10, 6,13, 3, 4,14, 7, 5, 7, 5,10, 8, 5, 0, 7,12, 3, 7,14, 3, 3, 8, 0, 7, 6, 9,11,15, + 10,15, 9, 7, 0,13, 7, 3, 7, 4,10, 1, 7, 4, 3,15, 2, 6, 1,14,12,12,10,10, 1,11,15, 0,10, 7,12,15, + 8,10, 2,14,11, 0,10,12,13,15,12,15, 8,11, 5, 3, 0, 7,10, 6, 1, 9,11, 8, 4, 2, 4,12, 6, 3,15, 3, + 2, 1,10, 2, 2, 7,10, 6,11,12, 6, 2,11, 7,15, 1,13, 9,12, 3, 9,12, 2,12, 6, 5,11, 8, 0, 7,14,10, + 7, 8, 6, 5,12, 4, 1,12,12,13, 8, 4, 8,12, 8, 2, 1,15,13,14, 8, 6,11, 2,13, 5, 6,10, 9, 5, 7,11, + 5,11,13, 2, 0, 8, 2,10, 2, 1, 6, 4, 8,14, 0, 4, 8,11, 8,15,12, 0,15, 6, 1,13,15,10, 3,13,14,13, + 4, 5,12, 4, 3, 8, 9,15,13,11, 4, 8,10, 7,12, 7, 7, 9, 7,11,13, 0,15, 5,11, 5, 6, 2, 5, 1, 9, 2, + 9,15, 9, 8,14, 6,11, 7,10, 4,14,12, 3,12, 3, 0, 4, 8,11, 9, 5, 7,14, 1,10, 3, 2,12,12,10,12, 8, + 4, 5,10,13,11, 6,14, 4,13,14, 8, 3,10, 5, 6, 4, 4,10, 6, 5,12,11,10, 5, 9, 6, 7, 6, 4, 6, 3,15, + 5,14,14,13, 7, 6,12,13,15, 5,15,10, 2, 1,15, 3,10,15, 7, 4, 5, 2,10,15,14,15, 1,13,12, 9, 8,14, + 15, 3, 4, 1, 9,13,13, 3,12,15, 8,15, 7, 1,10,12,10, 9,12,10,14, 6, 5, 5, 4, 0,12,14,15, 6, 5, 5, + 2,14, 2, 6,14, 2,12, 7, 5, 1, 2, 3, 2,12,15, 4,10, 5,10,13, 0, 2, 2, 1, 5, 7, 5, 2, 0,13, 0, 4, + 13,13, 9,12, 5, 5,10,15, 6,11, 5, 2,11, 8, 0, 6, 9,13, 2, 6, 1,11, 5, 1,12, 8, 4, 7, 9,13, 4, 4, + 15, 3, 4, 5, 5, 0, 9, 4,10, 8, 1, 0,13, 8, 6,12,15,15,10, 7,10, 2, 6, 1, 4, 0, 2, 8, 3,10, 2,12, + 4, 1,12,15, 0, 1,10, 0,10,11, 6, 1, 0, 3, 2, 3, 4, 4, 9,14, 7, 3,13, 7,13, 9,14,12,10, 5, 4,14, + 0, 5,15, 8,12,12, 0, 5,11,15, 8, 7,15, 5,12, 5, 5, 3, 6,13,15,15, 7, 0, 3, 9, 1, 5, 7, 7,12, 5, + 3,12,10,11, 2,11, 5,10, 1, 3, 6, 2, 7, 1, 3, 0, 6, 8,12,15,14, 6,10,13, 9, 1,15, 4, 6,13,14, 7, + 2,13,12, 9, 4, 7, 9, 9, 6,10, 6,15,15, 2, 0, 4,12,12,10, 2, 7, 4,14,10, 2, 6, 5,12, 0,14, 1,15, + 13, 1, 4,13, 3,13, 6,15,11,15, 0,13,12, 5, 4,11,14,15, 6,13, 6, 7, 2, 2, 7,11, 6, 7,15, 0,13,10, + 6,14, 9,13,12,14, 4, 8, 5,13, 3,14, 6, 6,13, 8, 7, 7, 5, 8,12, 2, 6, 0, 6, 8, 2,13, 9,14, 3,15, + 1, 4,13, 3, 6, 8,15, 4, 8, 7, 4,10, 0, 9, 2,15, 2, 1, 3, 3, 1, 4, 0, 3, 1, 8, 5, 0,10, 0, 1, 6, + 11, 3,12, 0,14,11, 0, 5,15, 9, 1, 7,15,12,12,10, 2, 2, 3,15,13,13, 2,13,14,13,13, 8,11,10, 9, 9, + 9, 7, 7, 4, 9, 1, 9,10, 9, 9, 9,15,13,14,12,13, 6,11, 4, 6, 9,14, 6, 6, 7, 0, 8, 6,10, 7, 9,13, + 4, 8, 1, 8, 9, 9, 3,14,10,14,11, 7,15, 8,13,11, 9, 0, 5, 4, 4, 7, 6, 0,13, 9,13, 7, 9, 3, 2, 0, + 7,11, 5, 8, 8, 0,10, 3, 1, 4, 2,15,12, 5, 2, 6,15, 5,13, 6,12, 8,10, 9,12, 9, 1, 2,15,14, 5,11, + 13, 3, 6, 8,15, 5, 8, 2,10, 2, 8,14,15, 5, 4, 0,10, 2,14,14, 8, 8, 9, 9,11,11,12,11, 5, 4, 2,12, + 15,12, 1,11, 5,13, 0,12, 2, 4, 0, 0,12,12, 4,15, 7, 1, 2,13,10,10, 6, 4, 8, 6, 0,14,13, 1, 8, 3, + 10, 9,11,12, 6, 0,11,14, 1,13, 7, 4,11, 3,10, 0, 2,10,14,13, 7, 8,10, 7, 7,12,10,11, 3, 9,13, 8, + 0,10,10,13, 7,12, 8, 8, 5,15,10,15, 7, 1, 8, 2,12, 1,14,10,10, 4, 5, 7,11, 3, 7, 7, 1,12,12,12, + 1,14, 4, 0,11,15, 8,10, 1,14, 2,11, 5, 5,10,12, 2, 2, 1, 0,10, 0, 6, 2,10,13, 1,11,14, 0,12,11, + 8, 8,12, 4, 5, 5,14,14, 9, 8, 0,10, 1, 9,15,10,13, 5, 2, 7, 1, 2, 6, 5, 5,11, 0,13, 8, 0, 7, 2, + 15,11,15, 0, 5,15, 5, 6, 0, 2, 5, 3, 0,14,14, 4,11, 7, 7, 4,10,11, 1, 8,13, 9, 4,13, 3, 6, 1,10, + 1, 0,15,15,12,10, 6,11, 3, 4, 7, 8, 7,14, 8, 7,12,15, 9, 8, 7,14,14, 9,15, 8, 9, 4,12, 3,12,12, + 7, 8,11, 2, 4, 8, 4, 9, 4,11,15, 2,13, 6, 3,13, 1,13, 5, 0, 2,10, 5, 8, 1,13,14, 0,11,15, 8,12, + 10, 4, 5,10, 4,11,11, 2, 2,13, 2, 6, 0, 7, 4,11, 1,12, 6,13,14, 5, 9, 0, 5,13,14, 6,13, 3,13, 9, + 14,14, 0, 9,12,14, 9,10, 1, 2,12, 3, 3,15, 8, 4, 3, 1,13,13,13,13, 4, 3, 5,15, 8, 2,15,13,11, 7, + 4, 0,15,14, 1,13, 6, 8, 2, 8, 7,14,11, 7, 4, 1, 8,12,13,11, 0, 9, 0, 3,12,11, 2, 3, 9, 1, 3,13, + 4, 5,15,10, 5, 9, 0, 3, 9, 6,13, 7,15,13,11,13,12, 6,14,15, 3, 6,10, 3,11,10, 1, 4,13, 0,15,15, + 11, 0, 7,14, 9,15, 1,14, 2,13, 7,12,11, 7, 9, 6,11, 5,12, 4, 3, 6, 8, 3, 9, 0,15, 7, 1,11, 7,12, + 2,13,13, 3, 0,11, 1,11, 6, 1, 5, 5, 4, 5,12, 3, 3,15, 3,10, 7,12,15, 0,13,10, 0, 2, 6,12, 9, 5, + 3, 0, 0, 6, 3,13, 7,14,11,15, 7, 2, 2,11, 6,11, 9, 3,10,11, 1, 8, 1,13, 0,11, 2,10, 3,12, 4,11, + 0, 0,10,10, 2, 3,15, 0, 0, 9,14, 5,14,10,14, 0,13, 1, 1,12, 3, 3, 1,15, 8, 8,11,13, 8, 4, 8, 5, + 8, 7,13, 2, 1, 1,14,15, 1, 7, 7, 1,14, 1, 4,14, 0, 0, 7, 6, 5,11, 5, 8, 7, 1, 4, 3, 8,14, 5,11, + 13, 8, 1, 9, 6,12, 9, 6, 3, 3,11,12, 5,11, 4, 4, 3,11, 0, 0,10,10, 7,15,15,11, 1,11,13,11, 6, 8, + 2,15,10, 7, 0, 6, 3, 5, 2,14,12, 8,12,10,15, 8, 4,11, 8,13,11, 2, 5,13,10, 5, 9,10,15, 6, 3,12, + 3, 0,11,15, 5,13,12,13,12, 0, 8,12,10, 0, 5, 5, 3, 2,10, 5, 3,10, 7, 2,13,12,15,13, 1,10, 4,10, + 12,14,12, 1, 6,13, 6, 6, 0,13,11, 4, 5, 7, 1, 7, 7, 0, 4,13,13,12,14, 6, 1, 3,13,11, 1, 4, 9, 9, + 2,12, 8, 5,10,15, 2, 0,14, 9, 5, 8,11, 5, 3, 4, 7, 1, 2,13, 3, 8, 1, 3,11,12,11, 5, 1, 5,10,12, + 10, 2,10,13,12, 3, 9, 2,12,14,13, 8, 2, 1, 5, 3,15, 2, 8, 2, 1,15,10, 6,10, 3, 8, 9, 6, 9, 2,10, + 4,12,10,15,14,15, 1,15, 0,13, 6, 0, 5, 6,13,12, 2,14, 0,10, 6,15, 8, 8, 6, 8, 2,12,11, 3, 9, 5, + 9,15,11, 3,11,14,15, 6,14, 6, 7,12, 7,10, 6,14, 6, 6, 3, 5, 9,14, 7, 5, 8, 6, 2,12,15, 1, 2, 4, + 11, 6, 3, 0, 5,11,14,14,14, 4,13, 6,11, 6, 4,12,15, 2, 4, 1, 1, 5, 1,15, 7, 0, 5, 0, 0, 0,12, 1, +}; + +static const UINT16 deco56_address_table[0x800] = +{ + 0x527,0x1a1,0x2f6,0x523,0x297,0x005,0x141,0x3b4,0x539,0x794,0x6dd,0x498,0x59b,0x119,0x5db,0x631, + 0x2f1,0x565,0x409,0x158,0x2d6,0x16e,0x571,0x0b9,0x543,0x52b,0x668,0x0c0,0x5fd,0x216,0x5ea,0x24e, + 0x14b,0x09b,0x6d1,0x2f5,0x591,0x0b4,0x0a8,0x64a,0x39b,0x0d9,0x336,0x2a1,0x460,0x068,0x7b4,0x187, + 0x59a,0x2f0,0x5cd,0x181,0x7f7,0x733,0x223,0x581,0x4c5,0x1d4,0x11b,0x22a,0x688,0x738,0x130,0x202, + 0x12e,0x203,0x33e,0x4d0,0x2bd,0x0c4,0x042,0x614,0x6c2,0x385,0x3ed,0x7e2,0x2bb,0x2ef,0x3e1,0x654, + 0x73f,0x447,0x15f,0x41d,0x320,0x05a,0x2f4,0x116,0x1d6,0x0c2,0x4c1,0x0f3,0x694,0x28f,0x15c,0x125, + 0x343,0x291,0x33b,0x21e,0x031,0x4fa,0x76b,0x133,0x503,0x4e8,0x19c,0x3c6,0x24a,0x0b5,0x1df,0x71e, + 0x5ed,0x564,0x648,0x5d7,0x5c2,0x4a4,0x30e,0x750,0x474,0x11f,0x4a2,0x3bb,0x64c,0x258,0x4c7,0x586, + 0x071,0x362,0x593,0x252,0x2b0,0x5aa,0x053,0x047,0x6ef,0x669,0x6e8,0x011,0x093,0x443,0x33c,0x060, + 0x211,0x7d3,0x4c8,0x426,0x1c1,0x2e8,0x1fb,0x51a,0x402,0x49f,0x519,0x1c7,0x096,0x4e6,0x279,0x455, + 0x7ac,0x3a6,0x4af,0x736,0x1cb,0x45c,0x275,0x18c,0x776,0x6e0,0x5d4,0x59c,0x210,0x358,0x64f,0x2cf, + 0x0f4,0x307,0x577,0x7ba,0x296,0x0f6,0x1a3,0x09d,0x2c5,0x532,0x7bd,0x26c,0x171,0x727,0x5ba,0x2da, + 0x37b,0x707,0x366,0x10e,0x346,0x107,0x20a,0x4b1,0x12d,0x10b,0x603,0x788,0x2f7,0x6da,0x28b,0x08d, + 0x3ff,0x1e6,0x2a4,0x39f,0x454,0x112,0x2ec,0x441,0x0fa,0x054,0x3e5,0x3a2,0x1ec,0x322,0x53e,0x413, + 0x5b5,0x058,0x751,0x27a,0x3a7,0x2d1,0x16d,0x3f3,0x5f5,0x13e,0x122,0x1fe,0x069,0x7dd,0x213,0x424, + 0x36f,0x6f5,0x20e,0x431,0x5b2,0x25e,0x601,0x169,0x1a9,0x1cd,0x2e3,0x39e,0x338,0x7e5,0x5e5,0x7b1, + 0x3dc,0x464,0x065,0x255,0x246,0x71c,0x55c,0x3f7,0x5f6,0x0c8,0x1b4,0x148,0x284,0x69f,0x17f,0x4cd, + 0x6d4,0x63f,0x7ca,0x28a,0x75f,0x2df,0x708,0x442,0x00e,0x140,0x457,0x14f,0x63a,0x420,0x23e,0x672, + 0x440,0x716,0x3ca,0x1bb,0x622,0x367,0x018,0x109,0x3c1,0x206,0x7cb,0x42e,0x44c,0x613,0x61e,0x67c, + 0x396,0x06d,0x01b,0x0c9,0x40f,0x4b6,0x6b8,0x485,0x758,0x4d3,0x61b,0x34d,0x4fe,0x7a6,0x025,0x3eb, + 0x73a,0x79b,0x3db,0x312,0x190,0x35d,0x7b2,0x78b,0x248,0x010,0x075,0x12b,0x345,0x753,0x64b,0x163, + 0x374,0x557,0x4d8,0x25b,0x780,0x479,0x012,0x360,0x51c,0x3a1,0x0d0,0x020,0x137,0x5cf,0x7c5,0x189, + 0x679,0x352,0x7da,0x48a,0x18b,0x5fc,0x1fd,0x344,0x4dd,0x69e,0x761,0x542,0x65d,0x55b,0x755,0x4f9, + 0x427,0x501,0x329,0x6f2,0x2b4,0x1b6,0x319,0x459,0x3fb,0x6df,0x4ab,0x176,0x2fd,0x62f,0x1ca,0x1b3, + 0x1b7,0x2dc,0x674,0x56c,0x3ab,0x428,0x6c0,0x541,0x23d,0x283,0x6aa,0x5cb,0x231,0x713,0x014,0x79c, + 0x1af,0x3f2,0x32b,0x19b,0x0d2,0x25c,0x5be,0x1c5,0x383,0x50d,0x3e4,0x657,0x4bb,0x0e8,0x403,0x26b, + 0x14e,0x3b7,0x08f,0x31b,0x43f,0x375,0x2ca,0x6bc,0x678,0x13d,0x0e3,0x395,0x2ff,0x120,0x7eb,0x630, + 0x52d,0x369,0x36a,0x58c,0x538,0x04a,0x461,0x24f,0x717,0x73c,0x784,0x59f,0x0c3,0x340,0x476,0x207, + 0x6b7,0x31c,0x0da,0x729,0x2c0,0x7f0,0x3d5,0x67a,0x092,0x314,0x34f,0x2bc,0x6ee,0x32a,0x1a7,0x06b, + 0x40b,0x029,0x7fc,0x608,0x316,0x15a,0x113,0x3b8,0x22b,0x445,0x389,0x7a1,0x174,0x218,0x10d,0x29b, + 0x4a5,0x0e5,0x25f,0x250,0x75e,0x4c4,0x721,0x230,0x0d8,0x3c2,0x680,0x65f,0x25d,0x222,0x44d,0x57d, + 0x056,0x37f,0x4a9,0x30d,0x6de,0x7f5,0x423,0x2f9,0x3be,0x097,0x380,0x27c,0x5f1,0x2ba,0x1ea,0x2a5, + 0x162,0x0bd,0x4ff,0x5fa,0x3bf,0x01c,0x3ae,0x682,0x550,0x46a,0x13c,0x193,0x3cb,0x01e,0x6e9,0x03a, + 0x6d6,0x323,0x55a,0x74f,0x508,0x4f1,0x616,0x609,0x2b3,0x32c,0x0b7,0x584,0x77c,0x4c2,0x412,0x20d, + 0x21c,0x5f8,0x26f,0x69a,0x40d,0x50b,0x552,0x000,0x4e9,0x6e2,0x022,0x5d1,0x2f3,0x243,0x22d,0x706, + 0x304,0x76d,0x201,0x1e0,0x7be,0x3a9,0x074,0x1ac,0x57a,0x754,0x244,0x08a,0x425,0x561,0x6d3,0x48f, + 0x298,0x636,0x760,0x507,0x282,0x013,0x091,0x232,0x067,0x1ef,0x691,0x7e8,0x489,0x62e,0x289,0x487, + 0x3df,0x562,0x3e7,0x104,0x040,0x117,0x3d8,0x3f1,0x135,0x1b2,0x3cc,0x0e4,0x5e8,0x75c,0x595,0x2af, + 0x72f,0x361,0x0cf,0x5ca,0x3d1,0x049,0x002,0x347,0x287,0x337,0x799,0x404,0x7bc,0x0f1,0x101,0x467, + 0x1e2,0x544,0x095,0x37c,0x2fa,0x763,0x38f,0x376,0x722,0x035,0x2e1,0x28e,0x09e,0x4fb,0x26d,0x611, + 0x46c,0x5e7,0x563,0x6d2,0x724,0x2a0,0x475,0x24d,0x240,0x437,0x7c8,0x1dc,0x47a,0x356,0x72b,0x06a, + 0x765,0x499,0x1a8,0x7b0,0x73d,0x592,0x149,0x4cb,0x5a9,0x1e1,0x4ba,0x774,0x0b6,0x570,0x469,0x294, + 0x2d0,0x5df,0x5a3,0x16c,0x273,0x2b9,0x6c3,0x68a,0x5c6,0x041,0x768,0x4e3,0x0bc,0x077,0x21a,0x2db, + 0x0be,0x006,0x79a,0x17b,0x6ec,0x689,0x4b5,0x471,0x0f5,0x515,0x683,0x47d,0x576,0x5de,0x3b0,0x705, + 0x676,0x7d4,0x659,0x02c,0x49e,0x05e,0x02d,0x68c,0x3c8,0x4b9,0x5dd,0x390,0x0f0,0x42a,0x663,0x381, + 0x48b,0x06e,0x2be,0x0c7,0x42f,0x62c,0x568,0x5ee,0x212,0x559,0x3ec,0x3b9,0x180,0x4e2,0x1e9,0x303, + 0x446,0x387,0x6c9,0x52a,0x33d,0x7e4,0x325,0x5ff,0x554,0x290,0x675,0x7db,0x22f,0x578,0x5bf,0x3b6, + 0x4b7,0x7dc,0x5e2,0x18f,0x1ba,0x56a,0x78c,0x6af,0x5a2,0x749,0x4d6,0x208,0x400,0x43a,0x35f,0x286, + 0x251,0x332,0x030,0x6f6,0x0d3,0x786,0x3a5,0x214,0x087,0x667,0x378,0x29e,0x015,0x166,0x7ce,0x1f7, + 0x3e8,0x49c,0x787,0x6be,0x16f,0x0ba,0x7d6,0x458,0x488,0x783,0x7cf,0x588,0x5dc,0x6c4,0x70a,0x100, + 0x4fd,0x13a,0x078,0x715,0x1d2,0x633,0x32d,0x72a,0x6d5,0x6fd,0x78f,0x3d2,0x2c3,0x03e,0x17e,0x505, + 0x583,0x326,0x2ea,0x51b,0x44a,0x04d,0x3d7,0x1e4,0x0ab,0x3e6,0x124,0x3b1,0x368,0x2c2,0x6c6,0x68e, + 0x4ee,0x1d5,0x00c,0x430,0x71a,0x651,0x22e,0x20f,0x4ec,0x08e,0x292,0x086,0x589,0x435,0x6db,0x567, + 0x769,0x4f6,0x599,0x038,0x36d,0x448,0x4f7,0x3fa,0x082,0x3c0,0x021,0x4bf,0x5b9,0x277,0x023,0x422, + 0x0c6,0x6ab,0x4e5,0x044,0x00f,0x23a,0x664,0x36b,0x6fb,0x462,0x3d4,0x5ec,0x439,0x604,0x04c,0x546, + 0x0a2,0x14c,0x436,0x128,0x063,0x735,0x7cc,0x410,0x105,0x4d1,0x655,0x1b5,0x3a4,0x6ba,0x04b,0x634, + 0x7c6,0x1ce,0x3ef,0x11a,0x066,0x433,0x767,0x526,0x524,0x37a,0x5ad,0x0ec,0x4dc,0x38d,0x35b,0x4b2, + 0x54d,0x19d,0x172,0x495,0x692,0x545,0x6a8,0x5a0,0x164,0x407,0x742,0x145,0x1ab,0x7c4,0x285,0x299, + 0x1aa,0x66b,0x55d,0x594,0x69b,0x138,0x660,0x463,0x5b8,0x027,0x29d,0x57c,0x77a,0x481,0x797,0x7d9, + 0x732,0x7c1,0x6c1,0x416,0x701,0x78e,0x695,0x4a6,0x7ea,0x44f,0x7e6,0x106,0x5d9,0x57e,0x4f2,0x779, + 0x79f,0x509,0x2b5,0x22c,0x502,0x108,0x0b8,0x228,0x062,0x147,0x4fc,0x417,0x205,0x619,0x60b,0x308, + 0x7d7,0x1ee,0x555,0x0bf,0x398,0x04e,0x02e,0x061,0x4f3,0x699,0x182,0x48c,0x0e9,0x4b8,0x196,0x27e, + 0x1de,0x2b6,0x3d6,0x677,0x0d6,0x579,0x700,0x19a,0x3af,0x68d,0x51d,0x5d2,0x31e,0x4ae,0x617,0x1f8, + 0x47c,0x7b3,0x7e3,0x50f,0x470,0x3a3,0x6dc,0x0c1,0x46e,0x6b2,0x5ae,0x5e1,0x492,0x6b6,0x14d,0x178, + 0x1c9,0x798,0x781,0x0a5,0x23b,0x702,0x540,0x245,0x3d9,0x3b5,0x3ea,0x6ae,0x605,0x3de,0x0aa,0x179, + 0x2c9,0x2ae,0x0ee,0x6a0,0x262,0x4ac,0x0cc,0x60a,0x5b1,0x0cd,0x194,0x0ad,0x76c,0x73e,0x71d,0x5eb, + 0x7c0,0x486,0x0cb,0x200,0x551,0x1c6,0x3bc,0x686,0x696,0x12c,0x242,0x321,0x373,0x60f,0x635,0x56d, + 0x115,0x5e6,0x4da,0x704,0x48d,0x261,0x4f8,0x217,0x49a,0x6fa,0x085,0x56b,0x2ad,0x75a,0x5da,0x720, + 0x790,0x1f9,0x10f,0x55e,0x05d,0x21d,0x748,0x263,0x4d7,0x771,0x3bd,0x26e,0x07e,0x415,0x432,0x6eb, + 0x525,0x2ee,0x703,0x08b,0x274,0x310,0x533,0x1b0,0x21f,0x5f3,0x1b1,0x090,0x5a6,0x35e,0x7ad,0x6e5, + 0x330,0x4b0,0x175,0x4c6,0x70d,0x2d3,0x2b2,0x68b,0x5ef,0x650,0x003,0x081,0x1b9,0x46f,0x01f,0x026, + 0x7cd,0x2cb,0x642,0x0a6,0x764,0x7a3,0x58e,0x45a,0x63b,0x6ed,0x1db,0x5e4,0x78d,0x661,0x2e4,0x051, + 0x719,0x558,0x7fd,0x4d2,0x348,0x220,0x5e9,0x377,0x434,0x5d3,0x4a1,0x07a,0x301,0x7a9,0x33f,0x372, + 0x52e,0x582,0x70f,0x1d9,0x690,0x6f4,0x391,0x084,0x4a0,0x399,0x7af,0x6f0,0x5ac,0x7f6,0x1ae,0x392, + 0x77b,0x52c,0x7f9,0x2e7,0x0a9,0x5a7,0x3a0,0x6a1,0x5bc,0x6fc,0x32f,0x746,0x6bd,0x16b,0x42d,0x036, + 0x233,0x0f7,0x224,0x480,0x055,0x465,0x4aa,0x159,0x5fe,0x478,0x1c3,0x536,0x518,0x7c2,0x143,0x7e1, + 0x331,0x597,0x199,0x5ab,0x4d5,0x2de,0x0ed,0x0dc,0x317,0x229,0x4db,0x76e,0x351,0x5c1,0x618,0x684, + 0x54b,0x1f4,0x103,0x553,0x64e,0x2b1,0x271,0x775,0x1a5,0x239,0x521,0x51f,0x12f,0x418,0x466,0x134, + 0x468,0x0f9,0x15b,0x192,0x548,0x1bc,0x6b9,0x6e1,0x411,0x653,0x2c1,0x5f0,0x6cd,0x511,0x0af,0x7d1, + 0x5d6,0x5bd,0x3ad,0x34e,0x41a,0x0fd,0x4f4,0x33a,0x666,0x146,0x1dd,0x30f,0x5a8,0x254,0x69d,0x44e, + 0x42c,0x1f1,0x5fb,0x37d,0x3b2,0x080,0x7d8,0x2ac,0x221,0x1ad,0x66f,0x0eb,0x0e6,0x649,0x7fe,0x2a2, + 0x673,0x18e,0x535,0x5cc,0x644,0x293,0x65e,0x1f6,0x573,0x150,0x3da,0x237,0x238,0x3c3,0x45b,0x1f2, + 0x4d4,0x43d,0x1d0,0x63d,0x429,0x386,0x64d,0x46d,0x620,0x7ae,0x453,0x2c7,0x57b,0x697,0x6e7,0x2dd, + 0x5e3,0x09f,0x019,0x41b,0x6e3,0x43e,0x363,0x0db,0x62d,0x341,0x215,0x37e,0x3e9,0x1da,0x32e,0x647, + 0x21b,0x406,0x793,0x58f,0x560,0x0b2,0x569,0x607,0x2cd,0x640,0x38e,0x38a,0x388,0x4c9,0x652,0x185, + 0x219,0x7bf,0x7ab,0x1eb,0x472,0x4ad,0x226,0x2fe,0x53f,0x270,0x739,0x313,0x032,0x7f3,0x70c,0x3e0, + 0x2a9,0x259,0x5b7,0x08c,0x3c7,0x6ad,0x15d,0x2fb,0x10a,0x75d,0x66e,0x4e4,0x1fa,0x68f,0x643,0x2b8, + 0x6bf,0x497,0x6ff,0x405,0x490,0x170,0x50e,0x073,0x693,0x1d8,0x59d,0x53c,0x1e8,0x711,0x740,0x637, + 0x624,0x45e,0x483,0x6f3,0x09a,0x513,0x5bb,0x34c,0x414,0x54c,0x007,0x757,0x74a,0x2a3,0x355,0x017, + 0x72e,0x379,0x5a1,0x4a3,0x2c4,0x671,0x731,0x572,0x65c,0x5d0,0x034,0x1be,0x31f,0x300,0x7b8,0x2d2, + 0x0fe,0x57f,0x7fb,0x6a4,0x227,0x260,0x1c2,0x052,0x0ef,0x5ce,0x547,0x510,0x0f2,0x6ce,0x6ac,0x04f, + 0x2d7,0x0d5,0x5a5,0x29a,0x256,0x3ac,0x195,0x048,0x752,0x6d9,0x606,0x2e6,0x7ff,0x05c,0x3f6,0x0d4, + 0x623,0x602,0x5b3,0x58a,0x77e,0x6f8,0x3f5,0x698,0x587,0x78a,0x450,0x7c7,0x2e9,0x66c,0x49d,0x01d, + 0x2ce,0x046,0x1d1,0x357,0x628,0x718,0x0dd,0x13b,0x685,0x600,0x741,0x072,0x4eb,0x646,0x71f,0x165, + 0x05b,0x63e,0x043,0x136,0x66d,0x0fc,0x500,0x0f8,0x23f,0x31a,0x35a,0x7bb,0x45f,0x710,0x264,0x58d, + 0x2f2,0x079,0x656,0x154,0x444,0x03c,0x12a,0x7b9,0x60e,0x315,0x364,0x3f8,0x725,0x575,0x365,0x7aa, + 0x6e6,0x796,0x009,0x008,0x6a3,0x2ab,0x549,0x47b,0x2a7,0x778,0x730,0x627,0x7f2,0x743,0x3a8,0x39c, + 0x598,0x67f,0x1bd,0x65b,0x71b,0x615,0x6d8,0x27f,0x714,0x13f,0x7d0,0x0e0,0x126,0x118,0x2a6,0x7d2, + 0x4cf,0x2aa,0x60d,0x3dd,0x19f,0x24c,0x225,0x6a7,0x60c,0x7ee,0x6e4,0x41f,0x6ea,0x001,0x687,0x6cc, + 0x6f7,0x514,0x40c,0x4de,0x11c,0x39a,0x1e3,0x53d,0x327,0x050,0x276,0x632,0x11d,0x183,0x0c5,0x3fe, + 0x2a8,0x00b,0x30b,0x4f0,0x79d,0x257,0x3f0,0x15e,0x43c,0x6f1,0x110,0x596,0x2c6,0x5c5,0x0bb,0x318, + 0x77d,0x306,0x1cc,0x267,0x5b6,0x161,0x151,0x160,0x638,0x7f4,0x1d3,0x1e7,0x452,0x6b1,0x057,0x197, + 0x324,0x482,0x333,0x712,0x3ba,0x1a2,0x3f9,0x6ca,0x099,0x266,0x25a,0x17a,0x61d,0x1b8,0x556,0x4b3, + 0x6a6,0x0ac,0x67b,0x792,0x66a,0x0ca,0x098,0x74d,0x75b,0x522,0x629,0x512,0x53a,0x73b,0x529,0x156, + 0x65a,0x094,0x48e,0x737,0x123,0x129,0x1c0,0x18a,0x662,0x7ec,0x6cf,0x438,0x6cb,0x14a,0x4d9,0x728, + 0x534,0x658,0x06c,0x70b,0x184,0x3fc,0x46b,0x791,0x665,0x7df,0x744,0x3fd,0x3ee,0x0e1,0x394,0x56e, + 0x496,0x30a,0x7f1,0x55f,0x6a9,0x28d,0x770,0x2fc,0x41e,0x0ff,0x204,0x494,0x186,0x1c8,0x155,0x2eb, + 0x328,0x5d5,0x49b,0x50c,0x0e7,0x76a,0x235,0x47e,0x62a,0x0fb,0x3f4,0x7c9,0x280,0x4c3,0x7a4,0x756, + 0x0e2,0x5c3,0x24b,0x064,0x305,0x3e2,0x38b,0x7a8,0x31d,0x3d3,0x132,0x2ed,0x0b1,0x61f,0x02b,0x342, + 0x18d,0x00a,0x62b,0x4be,0x72c,0x1ff,0x5c7,0x7de,0x295,0x0b3,0x059,0x7d5,0x253,0x20b,0x1f5,0x5f7, + 0x27d,0x0a3,0x45d,0x7f8,0x1a0,0x088,0x43b,0x1ed,0x037,0x6f9,0x153,0x747,0x269,0x612,0x16a,0x265, + 0x370,0x574,0x504,0x354,0x7a7,0x2b7,0x2d9,0x54a,0x7a0,0x745,0x421,0x734,0x528,0x0d1,0x371,0x4cc, + 0x585,0x07b,0x477,0x58b,0x3cd,0x278,0x38c,0x03b,0x349,0x40a,0x7e7,0x6b4,0x6c5,0x19e,0x493,0x4e7, + 0x4a8,0x382,0x610,0x72d,0x566,0x36c,0x5c8,0x766,0x083,0x34b,0x789,0x7ed,0x0b0,0x173,0x139,0x144, + 0x28c,0x4e1,0x20c,0x3b3,0x41c,0x1bf,0x2e0,0x1a4,0x1f0,0x004,0x77f,0x7ef,0x114,0x63c,0x34a,0x27b, + 0x070,0x4e0,0x537,0x4b4,0x127,0x302,0x033,0x47f,0x5f4,0x3cf,0x3c4,0x07f,0x272,0x102,0x6b5,0x121, + 0x516,0x5f9,0x7b6,0x076,0x334,0x5c0,0x2e2,0x339,0x3e3,0x6b0,0x69c,0x0ea,0x56f,0x168,0x5e0,0x167, + 0x3c9,0x639,0x191,0x762,0x7b5,0x795,0x384,0x772,0x3ce,0x76f,0x02f,0x23c,0x773,0x249,0x2c8,0x03d, + 0x74c,0x06f,0x09c,0x0ae,0x6a2,0x131,0x4ea,0x1fc,0x309,0x2d8,0x3d0,0x51e,0x7e0,0x209,0x111,0x234, + 0x01a,0x782,0x2e5,0x506,0x35c,0x7a5,0x2cc,0x517,0x30c,0x0d7,0x759,0x26a,0x4ce,0x401,0x1f3,0x10c, + 0x449,0x29f,0x5b4,0x79e,0x6c7,0x028,0x530,0x681,0x397,0x00d,0x670,0x2d5,0x5af,0x520,0x0a4,0x6a5, + 0x0df,0x723,0x039,0x4a7,0x281,0x70e,0x1e5,0x0de,0x02a,0x5c4,0x777,0x456,0x142,0x451,0x785,0x17d, + 0x393,0x491,0x419,0x6d0,0x645,0x247,0x11e,0x0a1,0x580,0x473,0x3aa,0x709,0x17c,0x6bb,0x177,0x52f, + 0x268,0x0a7,0x4ca,0x626,0x7a2,0x54e,0x484,0x4f5,0x4bd,0x5f2,0x198,0x4df,0x1c4,0x5a4,0x2d4,0x157, + 0x4c0,0x241,0x531,0x40e,0x44b,0x2f8,0x0a0,0x1d7,0x350,0x152,0x67d,0x6b3,0x6c8,0x288,0x36e,0x7c3, + 0x621,0x67e,0x4ef,0x7b7,0x7fa,0x359,0x408,0x6d7,0x29c,0x5c9,0x590,0x045,0x3c5,0x5b0,0x59e,0x0ce, + 0x50a,0x236,0x1a6,0x641,0x54f,0x61c,0x05f,0x61a,0x74e,0x74b,0x016,0x6fe,0x311,0x39d,0x4ed,0x353, + 0x625,0x4bc,0x335,0x42b,0x5d8,0x07d,0x03f,0x089,0x7e9,0x07c,0x1cf,0x024,0x188,0x53b,0x2bf,0x726, +}; + +static const UINT8 deco56_swap_table[0x800] = +{ + 4,0,7,2,0,0,7,2,0,1,6,3,2,2,2,2,0,5,6,3,7,0,0,5,1,1,1,7,1,0,0,0, + 2,5,6,6,2,0,4,1,5,0,1,7,4,7,0,4,6,2,1,5,3,1,2,4,6,4,2,0,4,3,3,7, + 2,7,0,6,0,5,0,2,2,6,4,0,3,5,5,7,0,4,7,5,4,5,6,3,5,5,3,6,2,0,0,4, + 2,3,7,5,6,4,7,4,3,2,0,0,0,1,5,4,0,3,7,3,1,6,4,1,2,6,7,4,1,3,0,7, + 1,7,2,6,5,6,5,1,6,7,0,3,4,6,5,0,6,2,2,6,4,6,7,3,2,3,2,4,0,0,4,5, + 6,5,0,3,0,6,0,6,0,6,7,1,3,5,0,4,5,3,7,4,3,3,5,1,2,1,6,7,1,6,7,6, + 0,5,2,4,5,1,0,6,3,3,4,1,0,1,1,6,3,4,7,0,4,1,6,5,5,2,2,3,5,3,0,6, + 6,7,4,4,7,3,3,2,0,6,3,0,4,7,7,6,1,1,1,7,1,5,3,7,6,4,6,2,2,4,1,5, + 4,6,5,3,5,5,4,2,7,4,7,4,3,3,5,7,4,0,3,0,4,3,2,2,2,5,0,3,5,7,0,7, + 2,7,7,7,2,3,3,6,4,0,3,7,2,5,1,2,1,0,5,4,3,5,5,3,6,3,4,6,2,2,1,4, + 2,5,4,3,0,4,0,3,6,4,7,1,7,2,3,7,6,2,3,3,4,1,5,7,0,0,6,7,5,2,2,7, + 1,5,7,4,6,3,0,4,4,3,6,6,5,1,1,6,6,1,1,5,1,5,1,4,1,6,5,6,2,6,6,0, + 7,7,3,4,0,3,5,7,4,5,1,6,1,7,5,6,4,6,7,0,7,6,5,2,4,6,2,5,5,3,6,6, + 5,6,2,5,1,7,6,1,3,5,1,4,6,6,6,4,6,0,4,2,5,6,5,0,4,5,1,1,2,2,1,3, + 4,7,3,3,2,0,2,7,6,3,3,3,2,6,4,5,6,4,0,0,6,5,2,5,1,6,1,5,0,2,4,0, + 0,5,6,0,5,1,7,1,5,7,6,5,7,3,2,1,2,0,4,5,7,4,3,5,0,6,1,6,1,6,2,6, + 3,5,6,3,1,1,6,6,4,0,0,7,5,3,2,4,4,3,4,3,3,2,3,3,6,0,1,6,0,7,7,7, + 6,7,5,5,7,0,6,7,4,7,3,5,4,5,0,1,1,7,0,4,1,0,0,3,2,6,2,6,4,5,4,6, + 3,3,4,4,7,4,4,5,3,3,0,0,3,5,2,5,3,4,4,0,5,2,6,5,6,3,0,5,2,3,3,2, + 5,7,0,4,1,7,0,5,7,5,3,6,1,5,2,4,3,4,7,7,5,7,7,5,5,2,5,4,7,2,5,5, + 2,0,3,3,6,4,7,1,7,5,5,0,6,3,4,3,7,7,1,0,2,2,3,0,2,0,6,5,4,0,4,5, + 6,0,3,7,5,0,3,4,0,6,7,0,2,3,6,3,5,6,3,4,6,0,1,1,2,2,1,6,6,1,6,1, + 2,6,0,6,5,4,5,5,5,4,7,3,6,6,5,6,5,5,0,6,4,2,2,4,2,7,5,7,7,0,1,5, + 5,3,4,1,6,4,3,0,1,5,0,2,0,7,4,1,6,4,5,3,4,4,4,6,5,4,7,6,5,1,6,3, + 6,6,0,1,2,2,7,6,5,1,0,2,7,4,3,6,5,5,4,5,6,5,5,0,6,7,0,5,3,0,7,0, + 6,0,3,3,4,6,0,3,5,7,4,5,0,1,1,5,3,4,3,5,2,6,6,1,1,2,7,1,2,1,5,7, + 3,2,3,6,7,5,4,7,1,7,2,1,7,0,5,5,1,2,6,5,0,6,5,6,3,0,5,3,0,5,5,1, + 0,3,0,5,1,5,6,3,2,7,4,1,0,5,6,3,7,5,1,3,0,3,1,0,0,1,1,7,4,0,7,4, + 4,5,4,7,3,7,6,6,1,1,2,5,7,6,4,1,1,5,6,7,1,1,2,7,1,3,6,4,1,3,6,3, + 5,3,5,6,2,0,4,5,3,5,1,1,0,4,2,6,6,5,3,2,5,5,1,0,4,3,5,7,6,3,4,4, + 7,1,6,2,2,2,0,3,3,4,5,1,6,2,0,5,3,0,7,3,6,3,6,7,4,0,0,3,7,4,6,1, + 1,1,6,0,0,0,7,1,2,3,5,5,2,3,0,3,7,2,5,1,3,5,4,0,4,6,2,2,0,7,7,7, + 2,5,3,4,7,7,3,2,3,5,4,1,6,7,0,7,3,7,0,6,0,2,7,6,2,6,1,6,5,0,0,0, + 2,2,2,2,5,5,5,6,5,0,4,1,1,2,2,0,3,5,5,5,6,3,5,1,3,0,1,4,1,0,0,3, + 1,5,3,1,0,5,5,6,4,5,3,0,3,3,1,4,4,4,4,2,7,7,7,0,1,6,1,1,1,7,7,5, + 6,4,7,5,3,6,6,1,1,6,7,1,4,4,7,7,6,0,6,4,6,7,6,6,3,3,1,1,3,7,3,1, + 0,4,4,3,4,2,2,4,7,1,5,1,5,0,3,4,7,3,7,4,5,3,5,4,0,2,0,7,6,0,4,0, + 6,0,7,1,3,4,7,0,0,6,7,5,7,7,2,2,0,7,2,4,7,1,6,1,1,5,5,5,2,5,3,5, + 1,1,5,0,5,4,3,2,2,0,3,1,2,2,6,7,2,7,4,1,4,5,6,0,1,0,6,4,2,1,7,2, + 2,2,4,1,3,0,3,5,7,2,1,1,3,6,2,5,5,7,4,2,7,5,5,5,1,4,4,0,7,2,0,6, + 0,6,2,5,4,7,6,2,1,2,4,5,1,2,3,5,1,6,2,3,0,0,7,5,0,1,0,5,7,7,0,7, + 2,6,0,0,3,6,1,0,4,0,5,1,5,7,4,3,1,5,7,7,6,4,7,3,3,4,6,5,0,4,7,6, + 4,1,2,4,0,4,3,1,5,6,3,1,7,0,2,4,0,2,6,0,7,0,3,3,4,5,2,2,0,6,6,0, + 3,7,7,1,5,0,2,1,5,1,1,5,2,4,5,3,1,6,4,7,6,3,4,3,5,3,6,7,7,4,4,3, + 2,4,0,6,7,4,1,6,2,6,0,2,3,5,3,0,2,2,5,5,2,3,1,5,1,0,0,0,6,3,6,3, + 3,5,6,4,0,4,2,6,3,5,1,2,7,1,3,0,3,3,0,2,3,2,7,0,7,7,4,6,2,4,7,0, + 7,5,6,7,2,2,0,2,5,0,0,3,2,7,3,3,5,7,5,4,3,6,2,2,6,4,3,7,2,6,5,7, + 7,7,6,0,2,6,7,2,4,0,1,0,3,5,3,4,3,1,7,7,5,4,0,1,6,3,0,7,6,4,5,4, + 7,3,0,5,3,5,0,6,2,3,5,0,4,2,5,3,1,1,3,7,4,1,2,7,7,4,1,6,3,7,7,7, + 6,6,4,1,1,3,1,3,4,7,5,6,2,7,2,5,1,1,6,7,0,7,6,3,4,1,4,0,1,2,6,0, + 5,2,2,2,7,7,1,7,0,0,4,5,3,3,7,5,0,4,4,4,0,5,7,0,0,6,7,7,4,1,1,6, + 1,1,0,1,4,5,2,6,0,4,4,5,7,0,3,7,4,6,6,2,1,7,6,4,7,1,7,2,5,5,6,6, + 5,5,0,5,2,0,3,4,4,7,3,7,1,2,1,2,4,0,3,3,3,4,2,3,0,1,7,0,0,0,4,0, + 7,2,1,5,6,3,4,6,2,6,6,3,5,4,3,4,0,4,7,4,7,7,0,2,1,6,7,0,6,7,5,7, + 4,0,3,4,5,4,6,7,1,7,5,3,6,7,1,7,1,0,5,5,7,3,2,6,7,4,4,2,6,7,3,4, + 1,7,4,1,5,3,3,5,3,4,6,4,4,6,0,4,2,6,0,4,3,1,7,2,7,7,1,7,1,0,4,6, + 4,7,1,7,6,3,3,3,6,0,3,6,2,3,6,2,6,4,5,3,1,2,1,6,7,5,0,0,4,0,7,0, + 6,1,1,2,2,7,6,2,5,4,4,6,3,5,4,7,3,1,4,0,0,2,4,1,4,6,3,6,0,7,2,3, + 0,7,7,1,7,0,1,2,7,3,7,2,7,5,1,3,6,2,7,2,0,1,3,5,2,3,4,4,2,4,4,3, + 4,4,0,3,7,2,6,6,6,0,0,7,1,0,1,5,0,1,7,1,4,3,7,7,6,1,0,4,3,3,1,2, + 0,5,6,3,1,2,5,6,0,0,0,4,2,0,1,6,2,4,0,1,5,4,7,1,2,2,7,7,5,3,6,3, + 3,5,4,0,5,3,0,1,5,5,4,0,5,0,1,1,3,6,4,2,3,1,5,5,7,4,0,5,7,0,6,6, + 6,6,7,3,2,2,5,4,0,6,1,1,6,0,4,3,2,0,4,0,3,4,7,3,3,5,7,1,3,5,2,3, + 6,5,6,0,1,1,6,0,6,1,7,2,4,5,6,5,0,4,0,3,2,3,7,7,0,3,5,0,4,1,1,1, +}; + +static const UINT8 deco74_xor_table[0x800] = +{ + 13,13, 0,10, 8,15,12, 0,10, 8,13,15,12, 3,15, 2,11, 1, 8,10,13, 4,10,12,11, 2, 0, 3, 0,11, 8,11, + 5,14,11, 2, 5, 3, 8,11, 8,13,14, 4, 3,13,11,10,14, 6, 9,11,11, 8, 0,15, 2, 4, 5, 7,15, 8,13,11, + 7, 0,12, 3,13, 3, 1, 2, 6,14,10, 3,15,11,15, 7,13,14, 4, 6, 1,10,14, 8, 4,15, 2, 8,15, 9, 3,11, + 15,11, 1,14,11, 5, 6,14, 3, 9,12,14,15,12, 6,15,12,13, 3,15, 4, 0, 8, 0, 6, 8, 0, 1, 6,10,14, 9, + 12,15, 3, 5,11, 4, 9, 6, 9,13,12, 0,12,14, 9, 9,13,10,15, 8,15, 4, 9, 3,15,15,14, 8, 9, 0,10,11, + 15,15, 1,15,10, 6,11,15, 7,11, 8,15, 2,12,15,15, 1,14,10,13, 0,14, 4, 3,12,13, 3, 5, 7, 0, 4, 1, + 3, 5,13, 2, 0, 7, 2,13, 3, 7, 9, 2,15, 0, 2, 2, 2, 8, 6, 6,14, 2,15,11, 8, 0, 1,15, 5, 4, 2,15, + 13, 1, 1,13, 4,10,15, 3,14, 2,12, 8, 9, 8,13, 2, 0,14, 2, 9, 0, 2,12, 3, 4,15,13, 8, 4,12, 3,11, + 13,15, 5, 8, 7, 7, 7,15, 5,11,10, 4, 2, 1, 4,11,11,11, 8,10, 1,13, 5, 3, 1, 5, 8,15,10, 3,10, 9, + 4,14, 2, 8, 6,14,14, 9, 7, 2,15, 0,15, 5,10, 3, 5,12,10, 0, 7, 2, 1,11, 4,13,10,14, 3, 1, 1, 1, + 9,10,11, 0,14, 0, 1,11, 1, 2, 4,14, 9, 1,12,15, 0,10,11, 6,10, 4, 9, 1, 1, 5, 4, 3,15, 9,11, 0, + 7,12,10, 9, 3,14, 4,11,11, 3, 2,10, 1,12, 4, 3,11, 1, 9, 1,15, 9, 3,11,12, 7,11, 6,15, 8, 1, 3, + 10,12,10, 4, 2,13,13,11, 3,13, 1, 2, 7,13, 6, 6, 7,14,12,15, 9, 7,15, 7,15, 6, 5,11, 5, 1,15,11, + 11, 7,14,12,12, 4,11, 3, 8, 9, 8,15,12, 8,10, 6, 0,12, 5, 9, 6, 7,10, 6, 1, 6,13, 1, 3,10, 8, 2, + 1,13, 9, 4, 6,11, 2, 6, 2,15, 4,13, 3, 0, 7, 0, 9, 0, 6,14, 2,12,11, 0, 5,12, 7, 2, 6, 0, 2,10, + 10, 5, 1,12, 5,14,12, 1,13, 2, 6,11, 7,10, 0, 0, 7, 1, 8,10, 2, 3, 6, 4,11,10,10,13,15, 0,14,10, + 3, 8,14,10, 0, 7, 2, 4, 4, 4, 0, 9,15, 9,14, 3, 4, 3, 5, 4, 7,15, 6,13, 7,12, 1,12,10, 1, 8,15, + 5,15,12,13,14,14, 0, 4, 0, 0, 5, 0, 6,14, 8,14,14, 1,11, 5, 5,11, 3, 0, 2,15,11, 2, 7, 1,14,10, + 14, 3, 1, 5, 5,10, 1,10,13,13, 9, 9, 2, 1, 6, 7, 6, 7,11,15, 6, 6, 4,12, 8, 4, 3, 0, 0,15, 8, 2, + 2,14, 1, 8,11, 7,11,10, 3,10, 6,10,14,10,14, 6, 1, 3, 5, 2, 2, 5, 5, 5, 8, 3,12,15, 6, 9,12,10, + 4, 8,11, 6, 1, 8, 9,15,15,10, 0, 6,11, 8, 2, 9,15, 2, 2,10, 0, 5, 6, 5,11, 0, 0, 6, 0, 1,13, 6, + 4, 4, 4, 1, 4, 0, 9,12, 2,10,13, 5,10,12,15,10,12, 3, 4, 7,10,13, 3,15,12,11, 6, 8,13, 2, 8,10, + 3,12,13, 9,10, 4, 2,11, 1, 4, 9, 1,11, 2,14, 5, 2, 0,10,12, 0, 6, 7, 0, 2,10,15, 9, 0, 0, 8, 1, + 0, 9, 1,14, 0,13,12,13, 9, 6,10,12,10, 0,13, 3, 7, 4,12, 0,11, 0, 0,11, 5, 0,14,15,11, 8, 2, 5, + 4, 6, 5, 9,13, 5, 4, 4,13, 4, 0,12,10, 3, 2, 2, 0,13,11,12, 4,12, 9, 7,13,14,14, 8, 5, 0,13, 0, + 1, 4,15,15, 9, 8, 5,12,13, 8,12, 8, 8,10, 0,15, 8,11, 5, 6, 9, 8,10,12, 9,12, 5,14, 6, 9, 7,15, + 1, 9,15, 0, 1, 9, 1, 2, 8, 1, 4,12, 1, 4, 9, 7, 2,10, 8, 1,13, 6, 0,12, 0, 6,12,13, 5, 9, 4,12, + 7,14,10, 4, 6, 8,12, 4, 9, 1, 2, 2, 3,13,10, 2,15, 7, 1, 6, 0,12, 5,10, 9, 1, 0,14,15, 3, 7, 6, + 9,12,13, 7, 0,13, 2, 5, 7,13, 1, 3, 8,15, 9,10, 3, 0,15, 2,11, 5, 7, 3,10, 7, 4, 0, 7, 2,10, 2, + 0, 3, 6, 6,13, 0, 5, 9,13, 8,11, 9, 0, 4, 1,11,15, 5,15, 3, 1,15, 1,15,12, 8, 9, 4, 1, 5, 8,11, + 5, 7, 6,11, 5, 7,15,15, 9, 4, 7,12,14,11, 8, 6, 7, 7,12, 3, 9,12, 6, 9, 5, 8,13,14, 6,14, 4, 7, + 12,12, 2,14,10, 2, 1,10, 3, 8,12,11,12, 7,12,15, 7,13, 9,15, 6, 3, 1,14,13,14, 8,11,14, 4, 9, 2, + 13,13, 0, 2, 9,11, 3, 2, 4,11, 6, 8, 2,14, 7,15, 8, 8, 9, 5, 4,15,11, 7,13, 7, 4,15,15, 4, 2, 1, + 6, 4, 3,15, 0,11,14,15, 6,15,11,14,10, 4, 4, 0, 5, 4, 6,15, 8,10,15, 1, 3, 8,13, 3, 3, 0, 7, 7, + 2, 3, 2,11,14, 1,12,13,10, 2, 4,13, 4,13, 9, 3, 2, 1,14, 9, 8,11,15, 4, 8, 9,13, 2,10,14, 2, 4, + 8,13,13,14,12, 1, 5,15,13, 3,12, 8,11,12,12, 1, 0,15, 9, 2, 6, 9, 3,12, 5, 0,10, 8, 5, 6,11,14, + 7, 7, 0,10, 0,14,10, 8, 4,12, 5, 3,11,10, 5,13,15, 9,14,12,12, 0,14, 3, 2,12, 9,14,11,11, 9, 2, + 8, 9,13, 0,10, 3,14,14,13, 6, 4,14, 2,10,10, 9,10, 4, 5, 4, 5, 3, 4, 6,15, 5,14, 2, 6,10, 4, 8, + 6, 9, 9, 7, 3, 3, 9, 5, 9, 8,10, 5, 0,13, 7, 8, 4, 1, 3,13, 4, 1, 8,10, 3,11,13, 3,12, 0, 2, 0, + 3, 1, 3, 3, 1, 6,13, 2, 3,13,11, 5, 9, 0, 4,12, 6,11, 4, 4, 3, 3,12, 7,13, 2,15,12, 1,11,15, 7, + 10, 0, 9, 3, 3,13,12,12, 9,14, 2, 2, 0, 3,12, 2, 0,15, 0,10, 1, 9, 8, 3, 2, 3, 9, 1, 4, 5,12, 9, + 10,11, 0, 2, 2,11, 5,13, 8, 1, 7, 8, 4,12,11, 1, 2,11, 7, 7, 8, 6, 5, 8, 8,14, 2, 6,10, 6, 1, 9, + 3, 4, 2, 9,11, 1, 4, 9, 8,13, 5, 0,15,13, 0, 9, 9,11, 5,11, 6, 4, 6, 9, 5, 1,13, 8, 8, 2,14,14, + 2, 3,14,12, 4, 6,15, 4,11,14, 7, 2, 3,14, 4,15, 4, 1, 8,13, 5, 5, 7, 0, 6,14, 0, 1, 1,13, 5,10, + 10,14,14,10, 2, 9, 1,11, 5, 6, 8,12, 4, 2, 7, 7,11, 6,13,15, 1, 3, 9, 0,14,12, 9, 2, 3, 2, 1, 9, + 12, 7, 4,12,14, 3, 3, 2, 3,14,10, 5, 8, 4, 9, 9,11,14,13,15,14, 7, 3,13, 0, 9, 4, 9,12,12, 1, 2, + 10,11, 7,11, 1, 9, 2, 8, 1, 4, 5,14, 8,15, 9, 3, 8, 9, 6, 3, 7, 3, 1,10, 7, 5,13,14, 8, 7, 4,10, + 14, 4, 6, 9, 6, 2, 5, 3, 8, 0, 9, 7, 2, 7,12, 8,12, 2,15, 4, 5, 0,11, 8,11, 2,14, 8,15, 0, 8, 9, + 14, 5, 4,13,12,11, 2, 6,11, 9, 9, 7,14, 6, 6, 7, 4, 6, 3, 5,12, 5,11, 1,12,14, 0,13,15,13, 2, 2, + 1, 8, 3,11, 3, 1, 6, 9,12,12, 5,10, 7,13,15, 4,12,10, 9,11,12,14,12,11,15, 2, 3, 2, 7, 8,15, 2, + 2, 0,12,12, 9,11,13,14,13, 7, 3,11,11,14,12, 3, 2, 7, 4, 8, 9,11, 8,11, 5,10, 3, 7,15,11,12,15, + 10, 8, 5,13, 8, 3, 9, 8, 5, 7, 1,15,15, 0,13, 7, 8, 6, 8,10, 8, 6, 6, 3, 4,10,13, 1, 6, 6,10, 1, + 2,11, 4,15,15, 3, 1, 1,14,12, 1,15, 1, 6, 8,10,14,14, 9, 4, 7, 8, 6, 5, 3, 1, 0, 5, 3, 8, 6, 1, + 4, 2,13,15,14, 5,13,11,10,13,11,11, 6,10, 7, 2, 1,15, 2,10, 5, 0,11, 5,15, 8, 0,14, 3,12,11, 7, + 10, 1, 4, 0, 3,15, 7,15,12, 8, 9, 0, 1,15,13, 2, 3, 2,15,15,14,14, 7, 8,12,11,15,15,14, 2, 8, 8, + 2, 0,15, 4, 2, 5,14,10, 4,12, 2, 1, 0,13, 7, 5, 4, 3,11, 6, 0, 2, 6,14, 9,14,10,13, 6,10, 5, 8, + 15, 2, 4, 7, 1, 8, 5, 3,11, 5,12, 1, 3, 1,14, 4, 8,12, 6,10,14, 7,14, 7,15,14, 5,10, 6, 9, 3, 6, + 12,15, 1,12, 0, 6, 1, 4,13,13, 7, 1, 7, 1, 9, 1, 8, 6, 9, 9, 8,12, 5, 2, 8,11, 9, 1, 3, 9, 0,11, + 14, 8, 5, 9, 7, 7,14, 4, 6, 1, 6,11, 4, 0,15, 5, 9, 8, 5,13, 2, 6,13,10,12, 3, 4, 3,15, 5, 6,14, + 2,10,14, 1, 5, 9, 6, 1, 9, 2, 7,11,14, 7,14, 5, 8, 9,14,13,14, 8, 3, 8, 4,10, 3,14, 0,13,12,15, + 9, 9, 0, 4, 6, 7,12,13,12, 1,15, 2,13,13, 8,10,13, 5,12, 5, 4, 0, 2, 1,13,12, 2,14, 9,15,13, 9, + 7,13, 7, 0,14, 7,12,15, 3,11, 0, 5, 8, 1, 0,12, 9, 0,11,13, 6, 3, 3, 7, 2, 2, 3, 5,14,14, 0, 9, + 2, 6, 4,12, 2, 6, 3,12, 3,13, 3,14, 7, 1, 8,15,14, 3, 0,10, 2,15,15, 9,14,11,10,12,13,13,13, 9, + 7, 7,12, 5, 3,14, 1, 5, 1,10, 6, 7, 9, 8,15, 7,13,11, 4, 5, 4,10,14,14,12, 1,13,14,15,14,15,10, +}; + +static const UINT16 deco74_address_table[0x800] = +{ + 0x526,0x684,0x15f,0x1ad,0x736,0x341,0x4c3,0x23c,0x3eb,0x01f,0x18e,0x375,0x029,0x227,0x707,0x506, + 0x5ce,0x0dc,0x5dc,0x5fd,0x15c,0x013,0x7b9,0x3c1,0x77d,0x1eb,0x53d,0x4a9,0x66e,0x0a9,0x4e2,0x361, + 0x32d,0x151,0x16a,0x5ed,0x4b0,0x78a,0x0d1,0x01e,0x4be,0x7dd,0x22d,0x125,0x401,0x118,0x051,0x784, + 0x48a,0x083,0x42f,0x56b,0x448,0x679,0x019,0x076,0x44c,0x663,0x3a1,0x740,0x095,0x242,0x4c5,0x13b, + 0x3c4,0x130,0x122,0x047,0x16b,0x162,0x0d9,0x1f4,0x0be,0x018,0x56c,0x494,0x0b0,0x185,0x3b3,0x257, + 0x764,0x05d,0x7d4,0x2bd,0x159,0x2fb,0x07a,0x365,0x4fd,0x451,0x452,0x52d,0x753,0x5c8,0x1a4,0x50e, + 0x5ff,0x536,0x45b,0x281,0x4b8,0x1ff,0x228,0x5f9,0x1ca,0x587,0x0fd,0x02a,0x0da,0x03f,0x6a4,0x671, + 0x2d9,0x377,0x39c,0x534,0x6c5,0x1b2,0x1db,0x263,0x5c3,0x0c7,0x474,0x4db,0x152,0x3de,0x47d,0x64a, + 0x41c,0x66c,0x3d9,0x769,0x0c1,0x4ec,0x46b,0x274,0x6aa,0x623,0x31a,0x2ef,0x270,0x1e7,0x4e5,0x2e3, + 0x1f9,0x203,0x150,0x4a3,0x7d3,0x0af,0x1c8,0x310,0x4cd,0x1a6,0x14e,0x636,0x3f8,0x04d,0x337,0x441, + 0x3c0,0x1d8,0x482,0x399,0x3ef,0x520,0x260,0x352,0x4f8,0x521,0x271,0x6e6,0x5da,0x763,0x595,0x4e0, + 0x2db,0x3c6,0x012,0x09b,0x14f,0x26b,0x512,0x0cb,0x616,0x605,0x63a,0x5e2,0x139,0x7cd,0x7d0,0x00c, + 0x198,0x234,0x4f7,0x37e,0x0a1,0x4bd,0x1a1,0x2f0,0x3b4,0x0a6,0x1c7,0x51e,0x166,0x567,0x719,0x5cb, + 0x3b5,0x31c,0x751,0x6a1,0x065,0x4fa,0x6e1,0x106,0x1a5,0x331,0x3a2,0x16d,0x756,0x090,0x554,0x241, + 0x19a,0x35c,0x0e9,0x388,0x1c9,0x11b,0x5c7,0x56a,0x168,0x5b2,0x47f,0x5a9,0x551,0x3bb,0x3d3,0x428, + 0x132,0x4d7,0x1d1,0x538,0x5d7,0x297,0x6df,0x0ce,0x728,0x2c5,0x6f6,0x60d,0x2a0,0x45f,0x46d,0x4f0, + 0x5ea,0x1e0,0x4d6,0x442,0x32f,0x243,0x30f,0x0c9,0x344,0x42d,0x22f,0x327,0x2b2,0x158,0x7af,0x3d2, + 0x127,0x6d3,0x411,0x7eb,0x632,0x277,0x60b,0x356,0x307,0x1c3,0x0f1,0x762,0x207,0x13e,0x25a,0x6d0, + 0x38e,0x0a7,0x79a,0x2a5,0x771,0x39e,0x325,0x160,0x014,0x115,0x698,0x712,0x2c8,0x3c3,0x1bc,0x696, + 0x0d6,0x692,0x49f,0x4de,0x5b3,0x0cc,0x2f3,0x667,0x318,0x52c,0x3e0,0x181,0x462,0x1f7,0x366,0x4f4, + 0x547,0x44e,0x1be,0x3ed,0x04e,0x490,0x661,0x703,0x320,0x42e,0x406,0x161,0x259,0x702,0x58b,0x619, + 0x51f,0x502,0x391,0x4ce,0x779,0x0f9,0x05b,0x45e,0x14a,0x66a,0x42b,0x35a,0x363,0x1b8,0x373,0x117, + 0x78f,0x34e,0x2e0,0x2d7,0x7ee,0x27b,0x2c6,0x103,0x7dc,0x23d,0x2ad,0x049,0x68a,0x41f,0x582,0x3d5, + 0x631,0x107,0x2be,0x28e,0x5af,0x119,0x694,0x744,0x546,0x19b,0x766,0x5cf,0x2ee,0x0e0,0x4a5,0x313, + 0x6a3,0x3b1,0x28a,0x104,0x415,0x19e,0x01c,0x009,0x167,0x266,0x397,0x056,0x525,0x416,0x64f,0x689, + 0x706,0x413,0x004,0x6c9,0x244,0x2f8,0x78b,0x510,0x02e,0x505,0x5a6,0x612,0x114,0x4d9,0x1cc,0x20f, + 0x7e9,0x13a,0x584,0x495,0x6d2,0x5f4,0x093,0x43f,0x0e3,0x382,0x746,0x71e,0x794,0x72d,0x3ec,0x7c1, + 0x03a,0x33d,0x1ec,0x128,0x27f,0x700,0x149,0x10c,0x553,0x2bc,0x492,0x080,0x5b0,0x015,0x1c4,0x691, + 0x037,0x59f,0x542,0x4cf,0x253,0x5ae,0x74d,0x407,0x6e8,0x354,0x7b4,0x49b,0x300,0x6f2,0x26e,0x3f4, + 0x086,0x37c,0x1ee,0x347,0x6b1,0x26d,0x105,0x55d,0x1ba,0x70b,0x236,0x3e3,0x0b6,0x2c2,0x33b,0x254, + 0x140,0x2e8,0x5c2,0x03b,0x04c,0x5aa,0x480,0x560,0x6ed,0x633,0x7a6,0x29f,0x789,0x0e4,0x08a,0x15b, + 0x57e,0x4fe,0x532,0x25c,0x215,0x709,0x5f7,0x197,0x586,0x2f1,0x5e0,0x477,0x61b,0x608,0x063,0x01b, + 0x212,0x016,0x795,0x205,0x1fa,0x742,0x777,0x40b,0x146,0x73b,0x503,0x792,0x10e,0x545,0x7f6,0x3f7, + 0x4ad,0x38d,0x3b9,0x516,0x2ac,0x3bd,0x31b,0x214,0x170,0x5d6,0x21b,0x1b1,0x3cd,0x213,0x565,0x40a, + 0x113,0x515,0x724,0x03d,0x5c0,0x334,0x3e9,0x2a8,0x1c5,0x089,0x24e,0x7cb,0x4d5,0x280,0x36c,0x2b0, + 0x430,0x0e6,0x0d5,0x3c5,0x662,0x275,0x60f,0x0de,0x248,0x07b,0x22c,0x7b5,0x340,0x739,0x2b8,0x65a, + 0x508,0x116,0x079,0x7a0,0x4c2,0x099,0x4bb,0x52a,0x4d1,0x389,0x3a3,0x1e6,0x2a4,0x10d,0x4ba,0x581, + 0x0b2,0x302,0x0f4,0x760,0x25d,0x4c6,0x39b,0x12b,0x046,0x637,0x38b,0x0f6,0x109,0x51c,0x40d,0x6e9, + 0x6e2,0x7da,0x4a0,0x487,0x67e,0x65f,0x265,0x439,0x189,0x208,0x4b5,0x250,0x4f1,0x16e,0x496,0x3fc, + 0x272,0x20c,0x7ae,0x292,0x5e3,0x472,0x458,0x66d,0x657,0x722,0x438,0x3b8,0x4e4,0x39a,0x598,0x539, + 0x4b4,0x290,0x18b,0x1de,0x65c,0x2ea,0x6ff,0x20a,0x232,0x058,0x2d3,0x0d3,0x1f1,0x61d,0x0d2,0x1d2, + 0x295,0x466,0x038,0x0ac,0x4c7,0x6c7,0x672,0x040,0x6a0,0x699,0x624,0x71f,0x120,0x10b,0x072,0x192, + 0x3ba,0x638,0x58d,0x530,0x00e,0x761,0x6dd,0x1cd,0x18d,0x142,0x2eb,0x55e,0x7b2,0x367,0x5d3,0x71c, + 0x2d2,0x0a0,0x6b2,0x134,0x286,0x12e,0x0cf,0x5dd,0x2e7,0x74b,0x261,0x082,0x726,0x14d,0x1e3,0x4b7, + 0x7e7,0x435,0x294,0x31f,0x154,0x2cf,0x5f5,0x330,0x400,0x13d,0x629,0x7d1,0x4a2,0x3e6,0x3e8,0x1f5, + 0x3f3,0x368,0x410,0x3ca,0x221,0x71b,0x669,0x195,0x7f2,0x70f,0x006,0x504,0x062,0x461,0x053,0x6f7, + 0x0a3,0x6fa,0x1f2,0x745,0x7df,0x12a,0x05a,0x23b,0x4da,0x568,0x665,0x30d,0x5f6,0x328,0x283,0x169, + 0x17c,0x601,0x201,0x6c3,0x6c0,0x491,0x63f,0x6f5,0x2b5,0x2c7,0x628,0x3f9,0x02b,0x38a,0x2e9,0x60c, + 0x2a9,0x102,0x39f,0x0c3,0x42c,0x7cf,0x3df,0x4f9,0x235,0x3a8,0x7e4,0x485,0x21d,0x349,0x0e8,0x0b8, + 0x345,0x683,0x18c,0x317,0x6ca,0x323,0x17d,0x36a,0x7c9,0x1a0,0x3e1,0x6f9,0x0a2,0x353,0x7b6,0x759, + 0x287,0x7d7,0x25e,0x523,0x092,0x427,0x5a7,0x396,0x136,0x75a,0x3d6,0x507,0x385,0x5de,0x55f,0x0ad, + 0x096,0x239,0x5b8,0x6cb,0x574,0x511,0x41e,0x537,0x074,0x148,0x7a4,0x70e,0x2cb,0x284,0x191,0x06e, + 0x2da,0x51a,0x374,0x6ba,0x41b,0x552,0x460,0x371,0x183,0x0b3,0x444,0x748,0x7f4,0x59e,0x5bd,0x381, + 0x0ab,0x6fd,0x4cc,0x3e5,0x5c5,0x09c,0x717,0x22e,0x708,0x1bb,0x70c,0x4a6,0x778,0x034,0x1d5,0x30b, + 0x7f5,0x743,0x6ae,0x2de,0x2a6,0x613,0x5d0,0x40c,0x0bf,0x209,0x1b7,0x4f5,0x72b,0x620,0x647,0x643, + 0x024,0x2ca,0x0bd,0x501,0x0a4,0x453,0x3ff,0x6b5,0x625,0x2f7,0x556,0x469,0x409,0x747,0x031,0x1f6, + 0x47c,0x2ab,0x1fd,0x533,0x74f,0x395,0x754,0x0d0,0x6b0,0x42a,0x635,0x1af,0x6a9,0x49c,0x77b,0x611, + 0x2ae,0x2b4,0x3a5,0x1b5,0x3fe,0x3ab,0x479,0x498,0x3aa,0x5c1,0x27e,0x26a,0x590,0x29d,0x02c,0x121, + 0x404,0x61c,0x650,0x518,0x33a,0x768,0x0f2,0x0b4,0x686,0x67b,0x301,0x04b,0x1c1,0x7d9,0x772,0x0c8, + 0x49a,0x68f,0x59b,0x419,0x73a,0x750,0x360,0x58e,0x264,0x52e,0x00d,0x46e,0x085,0x46f,0x788,0x164, + 0x3d8,0x6db,0x52b,0x473,0x332,0x073,0x440,0x028,0x35b,0x3f1,0x14b,0x7fb,0x03e,0x28c,0x1ea,0x3f5, + 0x6a8,0x53c,0x5b5,0x0fb,0x585,0x478,0x179,0x4ac,0x137,0x173,0x1e5,0x7c6,0x262,0x027,0x6d8,0x144, + 0x3e4,0x673,0x7b7,0x145,0x6b7,0x596,0x1c6,0x54b,0x110,0x155,0x64e,0x4f6,0x44b,0x7fa,0x422,0x5a4, + 0x06c,0x51d,0x023,0x0aa,0x459,0x5fc,0x11a,0x2dd,0x4e1,0x603,0x224,0x497,0x308,0x5c9,0x3dd,0x4e8, + 0x48d,0x4cb,0x548,0x36f,0x094,0x36e,0x58a,0x299,0x797,0x57d,0x7c8,0x75f,0x321,0x431,0x045,0x131, + 0x543,0x486,0x1ce,0x47b,0x57f,0x38f,0x775,0x1dd,0x34a,0x177,0x4d8,0x634,0x48c,0x2e5,0x5ee,0x255, + 0x644,0x456,0x653,0x1e9,0x0ca,0x72e,0x576,0x710,0x6ab,0x4aa,0x4fb,0x569,0x541,0x309,0x1d9,0x714, + 0x35d,0x757,0x278,0x7ef,0x2ec,0x668,0x6d7,0x335,0x62d,0x3b6,0x5b4,0x676,0x46c,0x0e2,0x5bc,0x7bd, + 0x07f,0x267,0x68e,0x649,0x721,0x53f,0x226,0x0cd,0x6c2,0x312,0x1b9,0x11d,0x53e,0x602,0x6bd,0x561, + 0x19c,0x62a,0x135,0x651,0x09e,0x3c8,0x237,0x204,0x610,0x798,0x690,0x5a5,0x5f3,0x0f8,0x540,0x614, + 0x14c,0x5d1,0x00f,0x402,0x4b9,0x583,0x5c6,0x21e,0x457,0x3f6,0x07e,0x216,0x4b1,0x369,0x06b,0x37f, + 0x091,0x580,0x61a,0x1cf,0x4b2,0x2c4,0x1bf,0x38c,0x0ff,0x314,0x7d8,0x26f,0x7a9,0x31e,0x2f2,0x7ca, + 0x12d,0x101,0x54e,0x32e,0x791,0x4a1,0x76d,0x6b9,0x34d,0x061,0x69c,0x6bb,0x41d,0x571,0x711,0x339, + 0x5bb,0x1e1,0x680,0x026,0x032,0x23f,0x524,0x329,0x488,0x2c9,0x7f8,0x043,0x0dd,0x5c4,0x589,0x6f1, + 0x4c8,0x00b,0x782,0x670,0x6b8,0x196,0x1d4,0x43d,0x10f,0x56e,0x030,0x165,0x559,0x6b6,0x4ef,0x67d, + 0x15d,0x56f,0x2ed,0x7a2,0x04a,0x4c1,0x7a3,0x2e4,0x111,0x5f8,0x725,0x685,0x3bc,0x1fb,0x5a3,0x178, + 0x293,0x3a6,0x3a9,0x036,0x7ab,0x07d,0x4c9,0x5a1,0x5b7,0x19d,0x13c,0x519,0x0ee,0x157,0x5a8,0x23e, + 0x2af,0x62e,0x25b,0x785,0x73d,0x172,0x3be,0x7ed,0x4e6,0x15e,0x5e7,0x211,0x44d,0x682,0x7db,0x5b6, + 0x40f,0x020,0x0f5,0x7c0,0x609,0x5f2,0x6cf,0x08b,0x256,0x514,0x799,0x5d2,0x1e2,0x727,0x7e5,0x279, + 0x30c,0x11c,0x30a,0x58f,0x0df,0x03c,0x577,0x5ef,0x7c2,0x55a,0x5b1,0x776,0x65d,0x2aa,0x225,0x3db, + 0x276,0x6a5,0x5ec,0x229,0x5ca,0x513,0x1a8,0x30e,0x783,0x3fd,0x124,0x535,0x13f,0x64c,0x1a3,0x607, + 0x02f,0x0e5,0x701,0x24c,0x45c,0x566,0x6d1,0x035,0x044,0x455,0x042,0x20e,0x7e8,0x767,0x2fa,0x476, + 0x003,0x2bf,0x37a,0x5d4,0x247,0x660,0x1f0,0x2d6,0x36d,0x564,0x3c2,0x37b,0x2f4,0x17a,0x4a7,0x176, + 0x3d4,0x59a,0x383,0x258,0x08e,0x098,0x528,0x62c,0x72f,0x35e,0x0b5,0x56d,0x6f0,0x44a,0x723,0x45d, + 0x4eb,0x055,0x285,0x0ed,0x182,0x429,0x393,0x470,0x555,0x3a4,0x078,0x1a2,0x43a,0x16c,0x65e,0x087, + 0x7f3,0x74e,0x273,0x386,0x6da,0x550,0x25f,0x206,0x039,0x2a3,0x2e6,0x199,0x1cb,0x445,0x4c0,0x06a, + 0x54c,0x316,0x0d8,0x741,0x194,0x05c,0x606,0x43e,0x100,0x21a,0x43c,0x4c4,0x693,0x5e1,0x1d3,0x240, + 0x20d,0x433,0x796,0x238,0x765,0x4af,0x0eb,0x7e1,0x050,0x4ee,0x2d5,0x75e,0x5a2,0x5be,0x70a,0x3cf, + 0x376,0x005,0x61e,0x002,0x5cd,0x069,0x0c6,0x041,0x084,0x64b,0x60e,0x268,0x51b,0x000,0x464,0x34b, + 0x615,0x3d7,0x5cc,0x1b0,0x233,0x7fe,0x641,0x53a,0x24d,0x00a,0x32a,0x18f,0x282,0x749,0x3dc,0x0b7, + 0x5b9,0x336,0x0c4,0x5eb,0x398,0x475,0x2d8,0x5bf,0x646,0x418,0x5a0,0x3cc,0x531,0x187,0x3ea,0x6bc, + 0x1ab,0x1e4,0x69d,0x63c,0x6f8,0x0f3,0x251,0x2dc,0x648,0x6a7,0x219,0x731,0x573,0x7f1,0x070,0x188, + 0x7d5,0x436,0x730,0x6de,0x27d,0x163,0x129,0x403,0x298,0x2b9,0x06d,0x357,0x249,0x4b3,0x296,0x2b6, + 0x6b4,0x697,0x770,0x484,0x303,0x7fc,0x1da,0x2d1,0x7f0,0x379,0x16f,0x222,0x48f,0x394,0x64d,0x68d, + 0x3b2,0x5ab,0x3e2,0x5f1,0x7ff,0x69b,0x50c,0x384,0x655,0x346,0x446,0x7ea,0x4f3,0x2fc,0x2b1,0x562, + 0x387,0x2ff,0x4ed,0x5e5,0x5d9,0x6fe,0x1ef,0x656,0x47e,0x171,0x067,0x600,0x6eb,0x246,0x4d2,0x73c, + 0x305,0x1d0,0x434,0x5d8,0x6e7,0x781,0x32c,0x2bb,0x4d4,0x4b6,0x493,0x0c0,0x3bf,0x4f2,0x7ba,0x774, + 0x6ad,0x378,0x7c4,0x63b,0x733,0x752,0x454,0x184,0x74c,0x3c9,0x618,0x688,0x054,0x414,0x6c4,0x07c, + 0x2b7,0x3c7,0x2fe,0x73e,0x351,0x4a4,0x3fa,0x6e4,0x6d9,0x4a8,0x1fe,0x517,0x010,0x4d3,0x6c8,0x153, + 0x180,0x593,0x7b1,0x7a5,0x24b,0x141,0x424,0x7e0,0x186,0x405,0x2ce,0x604,0x425,0x447,0x677,0x79b, + 0x76f,0x0ec,0x2cd,0x358,0x1fc,0x3b7,0x0f0,0x32b,0x2cc,0x138,0x735,0x09a,0x549,0x704,0x720,0x786, + 0x3f2,0x088,0x639,0x133,0x7b0,0x4ae,0x2f9,0x007,0x54d,0x68c,0x509,0x08d,0x67a,0x443,0x0ba,0x499, + 0x06f,0x71d,0x0bc,0x695,0x3b0,0x63e,0x734,0x057,0x033,0x7a1,0x068,0x355,0x49d,0x5ba,0x76c,0x675, + 0x54a,0x10a,0x417,0x3a0,0x658,0x1df,0x7aa,0x112,0x6c1,0x372,0x420,0x048,0x011,0x2df,0x202,0x622, + 0x483,0x5e6,0x28d,0x0a8,0x324,0x380,0x6ea,0x449,0x23a,0x6a2,0x066,0x021,0x6fb,0x1e8,0x48b,0x0d4, + 0x666,0x33f,0x077,0x50f,0x370,0x338,0x76a,0x2fd,0x1d6,0x2a2,0x77e,0x489,0x3ad,0x73f,0x7c5,0x17b, + 0x471,0x5df,0x1aa,0x2f5,0x0db,0x7d6,0x6e0,0x7cc,0x645,0x729,0x08c,0x097,0x790,0x41a,0x4dc,0x7a8, + 0x1bd,0x21f,0x01a,0x3ac,0x713,0x193,0x55b,0x59d,0x1c0,0x6ce,0x364,0x33c,0x4e9,0x57b,0x426,0x1a7, + 0x21c,0x1ed,0x343,0x69a,0x732,0x6ef,0x55c,0x72a,0x18a,0x7f9,0x432,0x29b,0x7b3,0x468,0x319,0x0fe, + 0x245,0x7ec,0x7be,0x24f,0x008,0x500,0x31d,0x33e,0x217,0x6be,0x50d,0x230,0x02d,0x15a,0x46a,0x1ac, + 0x220,0x0ae,0x1d7,0x50a,0x558,0x718,0x40e,0x621,0x594,0x52f,0x27a,0x758,0x29e,0x4d0,0x642,0x75b, + 0x156,0x20b,0x350,0x39d,0x0bb,0x08f,0x218,0x075,0x652,0x57c,0x6d5,0x0ea,0x678,0x052,0x5db,0x1b4, + 0x423,0x3a7,0x4df,0x50b,0x77f,0x49e,0x0c5,0x5ac,0x79e,0x3fb,0x591,0x5fa,0x0c2,0x0e1,0x755,0x67c, + 0x66b,0x60a,0x66f,0x481,0x467,0x7a7,0x61f,0x57a,0x17e,0x05f,0x5f0,0x7f7,0x0d7,0x773,0x05e,0x7e2, + 0x6e5,0x659,0x4e7,0x738,0x24a,0x12c,0x77c,0x4bf,0x45a,0x69f,0x7fd,0x69e,0x529,0x19f,0x2ba,0x0b1, + 0x627,0x412,0x65b,0x2f6,0x269,0x342,0x2b3,0x291,0x0fc,0x3da,0x12f,0x4e3,0x592,0x0fa,0x463,0x7bc, + 0x780,0x11f,0x4ff,0x7ac,0x28f,0x175,0x0ef,0x6d6,0x4ea,0x527,0x3ee,0x0f7,0x0b9,0x311,0x27c,0x025, + 0x2c3,0x71a,0x6af,0x190,0x11e,0x588,0x78e,0x6c6,0x147,0x3ae,0x578,0x6ac,0x4fc,0x252,0x7c7,0x43b, + 0x557,0x7e3,0x2d0,0x63d,0x79c,0x62b,0x640,0x123,0x6e3,0x306,0x77a,0x4ab,0x787,0x421,0x1dc,0x390, + 0x1ae,0x1f3,0x705,0x7d2,0x081,0x2e1,0x5e9,0x5fe,0x687,0x2a1,0x59c,0x0a5,0x223,0x78d,0x35f,0x7c3, + 0x326,0x575,0x348,0x715,0x6b3,0x793,0x6f4,0x7b8,0x064,0x210,0x2c0,0x579,0x022,0x3af,0x74a,0x200, + 0x1a9,0x75d,0x7ce,0x72c,0x79f,0x75c,0x09d,0x4dd,0x2e2,0x7e6,0x17f,0x716,0x570,0x7de,0x017,0x76e, + 0x54f,0x362,0x29a,0x522,0x1b3,0x22a,0x572,0x3d1,0x408,0x437,0x3cb,0x6dc,0x58c,0x6a6,0x37d,0x53b, + 0x1b6,0x7bf,0x5e8,0x143,0x289,0x392,0x22b,0x5fb,0x5ad,0x01d,0x2c1,0x26c,0x76b,0x70d,0x44f,0x6fc, + 0x79d,0x4ca,0x450,0x34f,0x3e7,0x1c2,0x664,0x3d0,0x001,0x7ad,0x6f3,0x359,0x544,0x67f,0x563,0x6d4, + 0x108,0x48e,0x3f0,0x04f,0x322,0x6cd,0x2d4,0x597,0x09f,0x62f,0x5e4,0x28b,0x681,0x231,0x630,0x315, + 0x68b,0x059,0x3ce,0x36b,0x654,0x47a,0x29c,0x6bf,0x071,0x6cc,0x2a7,0x333,0x304,0x1f8,0x0e7,0x599, + 0x174,0x060,0x674,0x6ec,0x7bb,0x288,0x6ee,0x737,0x34c,0x617,0x4bc,0x5d5,0x78c,0x465,0x126,0x626, +}; + +static const UINT8 deco74_swap_table[0x800] = +{ + 2,7,5,7,1,1,4,4,7,5,6,7,7,3,4,3,0,2,1,3,0,4,7,7,2,5,3,1,4,4,6,7, + 6,7,4,5,1,3,0,3,7,2,5,0,1,5,2,1,4,0,6,1,1,2,4,2,1,0,6,5,2,6,4,6, + 4,4,2,2,0,6,0,4,6,0,1,7,0,6,1,2,5,0,1,5,0,2,6,2,2,7,0,7,2,4,6,3, + 3,5,1,1,2,3,4,1,4,6,1,4,0,6,6,3,5,4,1,1,3,0,5,7,5,4,5,4,3,6,2,0, + 4,5,7,3,1,3,4,7,7,4,2,7,1,6,4,1,1,4,0,4,2,0,4,0,1,5,6,4,7,7,3,7, + 7,0,1,2,6,7,7,0,5,1,2,4,2,0,4,4,7,4,0,3,7,1,7,4,2,5,7,4,3,7,3,6, + 7,3,0,5,1,7,5,3,0,1,6,1,7,4,7,6,5,1,2,7,3,3,1,4,6,2,3,7,0,4,5,6, + 3,2,3,1,7,6,0,1,5,7,4,0,5,1,4,1,2,0,6,4,3,5,7,4,3,0,0,6,5,1,7,6, + 0,2,4,0,0,5,4,7,4,3,3,0,2,3,5,7,0,3,2,3,7,2,0,0,7,6,3,5,0,1,3,2, + 4,7,2,3,4,7,1,5,6,7,3,6,4,1,7,7,4,4,3,4,0,7,5,3,2,5,7,7,0,4,0,7, + 7,2,5,1,2,4,7,6,0,6,7,0,5,0,1,6,5,0,2,4,5,1,6,7,6,0,7,0,6,0,1,4, + 3,2,0,2,4,6,3,2,3,3,0,5,7,2,3,7,1,2,6,3,7,2,0,5,7,1,2,6,4,3,4,6, + 4,0,1,4,2,3,3,2,3,7,0,7,4,3,2,1,0,3,5,2,5,3,0,0,0,4,6,4,4,6,1,0, + 3,1,1,5,7,1,5,2,0,1,5,7,2,4,5,4,2,6,3,1,4,0,3,0,1,7,3,5,1,1,1,2, + 2,3,4,1,2,0,0,7,1,6,1,5,2,2,2,1,6,6,0,5,5,4,2,3,7,4,6,6,6,3,1,3, + 3,0,1,7,4,6,3,7,0,1,4,2,3,3,1,7,6,0,6,4,1,3,6,1,6,2,3,1,6,5,3,4, + 2,1,3,3,1,6,6,3,6,6,5,0,1,7,1,0,4,6,0,6,0,0,3,6,5,6,4,0,4,2,6,5, + 0,4,2,7,6,2,4,6,6,4,6,6,0,5,6,6,5,2,3,0,4,4,6,4,1,6,6,0,7,0,1,6, + 1,2,2,4,6,4,2,5,4,2,2,5,4,1,3,3,4,5,3,4,5,6,3,5,2,3,7,6,1,0,4,4, + 7,6,0,5,2,6,2,2,3,7,1,5,4,2,6,7,0,5,5,2,5,7,5,6,2,3,0,5,4,5,2,1, + 0,5,3,6,7,2,3,4,0,3,5,7,6,6,5,6,7,2,2,2,3,5,0,2,0,1,2,2,4,6,7,2, + 5,4,4,3,5,7,3,4,5,3,4,7,1,2,3,5,3,3,6,0,4,4,2,5,4,1,7,2,7,7,4,5, + 2,1,0,3,4,1,3,6,2,4,3,3,3,0,0,1,2,0,3,3,6,5,6,7,5,2,0,4,2,0,1,6, + 7,1,0,4,1,7,5,2,3,0,2,7,2,2,4,6,7,5,7,5,0,6,5,3,2,7,2,3,3,6,0,4, + 1,5,2,2,5,6,4,1,3,6,2,7,4,3,4,1,6,0,5,6,0,0,3,1,1,2,4,3,4,1,4,2, + 0,3,0,7,6,3,2,0,2,3,6,5,3,3,6,6,2,4,5,4,1,5,1,6,0,7,5,5,4,7,3,7, + 4,3,5,0,7,4,4,3,5,5,7,7,2,4,6,6,7,0,7,6,1,0,2,4,0,2,3,5,4,6,3,5, + 2,4,2,4,2,4,5,2,6,5,2,4,6,2,2,2,4,4,2,1,4,0,1,1,1,4,7,0,3,1,7,5, + 7,5,5,4,1,0,2,3,5,3,3,7,2,6,1,2,7,4,1,5,2,4,2,5,4,0,5,0,5,4,1,3, + 5,1,7,4,2,2,1,3,3,7,6,3,2,1,7,5,3,2,4,6,6,5,6,2,0,2,5,3,4,2,3,4, + 0,2,6,3,4,6,6,7,3,0,3,0,1,0,2,7,4,6,0,3,5,2,5,5,5,3,6,4,7,3,5,3, + 7,1,1,3,1,5,7,3,0,4,6,5,3,3,2,3,0,7,0,5,1,1,7,2,2,0,0,6,7,6,7,6, + 3,4,7,3,7,6,6,0,7,6,3,0,0,6,2,7,1,0,2,7,6,2,2,2,7,1,3,2,3,4,1,3, + 1,7,5,2,0,7,7,0,6,1,6,0,2,2,6,7,0,6,7,0,6,4,0,1,6,6,6,0,1,3,4,4, + 4,1,2,2,7,3,7,2,4,4,3,4,0,3,1,0,0,7,3,3,6,5,0,4,3,5,5,0,1,7,2,3, + 3,0,6,6,5,6,4,0,6,0,1,7,5,4,2,6,3,7,4,4,5,6,7,6,1,7,2,5,5,5,1,4, + 3,0,6,3,2,3,0,2,0,0,0,1,0,6,3,7,7,4,3,2,3,4,6,4,2,0,5,3,3,6,4,3, + 5,1,4,0,0,1,0,5,2,1,6,3,3,1,1,6,2,0,3,0,7,0,2,0,5,3,6,6,0,6,2,4, + 0,3,0,1,2,1,6,4,5,2,3,4,1,2,0,6,7,0,5,5,0,0,3,7,1,4,1,2,7,3,4,7, + 4,4,5,5,7,0,4,2,0,7,4,4,7,2,7,2,1,7,4,5,5,7,7,4,0,5,2,2,7,0,5,3, + 3,2,0,5,2,1,1,7,0,5,4,3,1,3,2,5,3,4,5,3,4,6,2,2,2,5,4,2,1,3,1,4, + 7,5,5,7,3,2,0,4,6,0,4,1,6,5,6,1,3,0,1,1,0,4,5,1,5,0,2,3,7,2,5,6, + 0,6,4,2,6,1,5,6,3,3,5,0,3,2,0,0,1,2,1,0,2,7,5,1,6,4,1,7,6,5,3,2, + 3,4,3,2,7,1,6,2,3,2,4,3,4,7,0,5,2,0,6,7,2,0,3,7,6,7,4,0,4,3,7,7, + 5,2,6,6,7,6,3,6,6,1,6,2,3,1,5,1,0,5,1,0,3,7,4,5,0,3,2,1,3,5,3,1, + 1,7,4,2,1,2,3,0,4,7,1,1,6,3,6,4,0,2,7,1,0,5,4,6,1,2,7,1,3,6,5,2, + 3,0,5,7,3,5,5,2,2,6,1,6,0,4,5,7,3,4,0,7,0,5,4,3,6,5,7,0,1,0,0,7, + 3,3,4,4,1,4,7,1,2,0,0,7,0,5,3,4,6,3,4,6,4,2,5,0,7,5,5,6,6,7,6,7, + 3,4,5,0,5,5,7,5,4,4,1,4,3,1,4,3,3,2,5,7,6,3,0,4,1,2,5,4,4,3,0,2, + 7,5,5,7,3,7,3,3,7,0,0,5,3,1,4,4,6,0,1,3,1,4,7,2,1,1,4,1,0,7,4,5, + 2,7,2,4,5,7,3,3,7,6,4,4,5,3,2,4,0,3,5,5,5,4,3,6,7,7,5,1,3,0,2,6, + 3,2,0,4,6,7,4,6,7,2,0,6,7,2,5,0,1,3,0,2,4,7,5,1,4,7,7,4,2,3,6,4, + 3,2,0,4,0,6,0,0,5,7,0,4,0,4,6,3,6,0,0,3,1,0,1,2,6,2,1,0,5,7,6,4, + 5,4,1,2,3,6,6,1,3,1,1,2,4,3,1,4,1,0,4,2,0,3,2,1,1,1,1,6,2,1,3,0, + 6,6,2,5,5,5,2,6,7,6,1,1,3,1,1,6,0,2,6,0,3,6,0,6,3,4,3,3,0,2,0,1, + 5,6,5,0,5,3,4,2,7,5,6,4,4,1,1,4,7,7,1,2,3,6,1,6,4,5,3,6,5,1,7,1, + 0,6,6,2,6,2,6,0,2,2,6,1,0,2,5,6,6,7,4,4,7,6,1,0,1,4,3,1,2,1,4,1, + 4,6,2,5,1,2,0,2,3,4,3,0,3,7,7,6,5,1,7,3,1,0,6,1,1,3,0,7,4,3,1,3, + 7,6,1,5,4,3,5,4,7,0,2,5,4,5,1,6,3,7,4,5,6,7,3,6,1,2,3,3,6,6,1,5, + 2,0,7,2,5,4,1,7,6,6,0,1,7,5,2,4,1,2,0,2,2,2,7,4,3,0,6,0,7,2,1,7, + 5,1,7,1,2,2,4,3,1,3,6,5,5,0,2,6,2,6,0,1,4,1,1,4,3,2,6,0,6,3,7,5, + 6,0,7,7,7,2,0,4,2,5,6,3,4,3,2,0,3,1,6,2,3,3,6,7,1,5,6,6,4,0,6,1, + 1,6,2,0,7,6,3,2,5,6,0,4,2,4,4,2,5,7,5,4,4,1,6,3,4,6,5,5,6,0,0,4, + 4,7,2,2,1,3,4,4,1,7,0,2,5,4,7,3,7,6,1,5,6,0,7,4,1,1,5,2,2,6,7,2, +}; + +static void deco_decrypt(UINT8 *src, INT32 len, const UINT8 *xor_table,const UINT16 *address_table,const UINT8 *swap_table,INT32 remap_only) +{ + UINT16 *rom = (UINT16*)src; + len/=2; + UINT16 *buffer = (UINT16*)BurnMalloc(len * sizeof(INT16)); + INT32 i; + +#if 0 + /* we work on 16-bit words but data is loaded as 8-bit, so swap bytes on LSB machines */ + if (ENDIANNESS_NATIVE == ENDIANNESS_LITTLE) + for (i = 0;i < len;i++) + rom[i] = BIG_ENDIANIZE_INT16(rom[i]); +#else + for (i = 0; i < len; i++) { + rom[i] = (rom[i] << 8) | (rom[i] >> 8); + } +#endif + + memcpy(buffer,rom,len*2); + + for (i = 0;i < len;i++) + { + INT32 addr = (i & ~0x7ff) | address_table[i & 0x7ff]; + INT32 pat = swap_table[i & 0x7ff]; + + if (remap_only) + rom[i] = buffer[addr]; + else + rom[i] = BITSWAP16(buffer[addr] ^ xor_masks[xor_table[addr & 0x7ff]], + swap_patterns[pat][0], + swap_patterns[pat][1], + swap_patterns[pat][2], + swap_patterns[pat][3], + swap_patterns[pat][4], + swap_patterns[pat][5], + swap_patterns[pat][6], + swap_patterns[pat][7], + swap_patterns[pat][8], + swap_patterns[pat][9], + swap_patterns[pat][10], + swap_patterns[pat][11], + swap_patterns[pat][12], + swap_patterns[pat][13], + swap_patterns[pat][14], + swap_patterns[pat][15]); + } + + BurnFree(buffer); + +#if 0 + /* we work on 16-bit words but data is loaded as 8-bit, so swap bytes on LSB machines */ + if (ENDIANNESS_NATIVE == ENDIANNESS_LITTLE) + for (i = 0;i < len;i++) + rom[i] = BIG_ENDIANIZE_INT16(rom[i]); +#else + for (i = 0; i < len; i++) { + rom[i] = (rom[i] << 8) | (rom[i] >> 8); + } +#endif +} + +void deco56_decrypt_gfx(UINT8 *rom, INT32 len) +{ + deco_decrypt(rom,len,deco56_xor_table,deco56_address_table,deco56_swap_table, 0); +} + +void deco74_decrypt_gfx(UINT8 *rom, INT32 len) +{ + deco_decrypt(rom,len,deco74_xor_table,deco74_address_table,deco74_swap_table, 0); +} + +void deco56_remap_gfx(UINT8 *rom, INT32 len) +{ + // Apply address remap, but not XOR/shift + deco_decrypt(rom,len,deco56_xor_table,deco56_address_table,deco56_swap_table, 1); +} + +static UINT16 decrypt(UINT16 data, INT32 address, INT32 select_xor) +{ + static const UINT16 xors[16] = + { + 0xb52c,0x2458,0x139a,0xc998,0xce8e,0x5144,0x0429,0xaad4,0xa331,0x3645,0x69a3,0xac64,0x1a53,0x5083,0x4dea,0xd237 + }; + static const UINT8 bitswaps[16][16] = + { + { 12,8,13,11,14,10,15,9, 3,2,1,0,4,5,6,7 }, { 10,11,14,12,15,13,8,9, 6,7,5,3,0,4,2,1 }, + { 14,13,15,9,8,12,11,10, 7,4,1,5,6,0,3,2 }, { 15,14,8,9,10,11,13,12, 1,2,7,3,4,6,0,5 }, + { 10,9,13,14,15,8,12,11, 5,2,1,0,3,4,7,6 }, { 8,9,15,14,10,11,13,12, 0,6,5,4,1,2,3,7 }, + { 14,8,15,9,10,11,13,12, 4,5,3,0,2,7,6,1 }, { 13,11,12,10,15,9,14,8, 6,0,7,5,1,4,3,2 }, + { 12,11,13,10,9,8,14,15, 0,2,4,6,7,5,3,1 }, { 15,13,9,8,10,11,12,14, 2,1,0,7,6,5,4,3 }, + { 13,8,9,10,11,12,15,14, 6,0,1,2,3,7,4,5 }, { 12,11,10,8,9,13,14,15, 6,5,4,0,7,1,2,3 }, + { 12,15,8,13,9,11,14,10, 6,5,4,3,2,1,0,7 }, { 11,12,13,14,15,8,9,10, 4,5,7,1,6,3,2,0 }, + { 13,8,12,14,11,15,10,9, 7,6,5,4,3,2,1,0 }, { 15,14,13,12,11,10,9,8, 0,6,7,4,3,2,1,5 } + }; + INT32 j, xorval; + const UINT8 *bs; + + // calculate bitswap to use + j = ((address ^ select_xor) & 0xf0) >> 4; + if (address & 0x20000) j ^= 4; + bs = bitswaps[j]; + + // calculate xor to use + j = (address ^ select_xor) & 0x0f; + if (address & 0x40000) j ^= 2; // boogwing + xorval = xors[j]; + + // decrypt + return xorval ^ BITSWAP16(data, + bs[0],bs[1],bs[2],bs[3],bs[4],bs[5],bs[6],bs[7], + bs[8],bs[9],bs[10],bs[11],bs[12],bs[13],bs[14],bs[15]); +} + +void deco102_decrypt_cpu(UINT8 *data, UINT8 *ops, INT32 size, INT32 address_xor, INT32 data_select_xor, INT32 opcode_select_xor) +{ + UINT16 *rom = (UINT16*)data; + UINT16 *opcodes = (UINT16*)ops; + UINT16 *buf = (UINT16*)BurnMalloc(size); + + memcpy(buf, rom, size); + +// memory_set_decrypted_region(space, 0, size - 1, opcodes); +// m68k_set_encrypted_opcode_range(devtag_get_device(machine, cputag), 0, size); + + for (INT32 i = 0; i < size / 2; i++) + { + INT32 src; + + // calculate address of encrypted word in ROM + src = i & 0xf0000; + if (i & 0x0001) src ^= 0xbe0b; + if (i & 0x0002) src ^= 0x5699; + if (i & 0x0004) src ^= 0x1322; + if (i & 0x0008) src ^= 0x0004; + if (i & 0x0010) src ^= 0x08a0; + if (i & 0x0020) src ^= 0x0089; + if (i & 0x0040) src ^= 0x0408; + if (i & 0x0080) src ^= 0x1212; + if (i & 0x0100) src ^= 0x08e0; + if (i & 0x0200) src ^= 0x5499; + if (i & 0x0400) src ^= 0x9a8b; + if (i & 0x0800) src ^= 0x1222; + if (i & 0x1000) src ^= 0x1200; + if (i & 0x2000) src ^= 0x0008; + if (i & 0x4000) src ^= 0x1210; + if (i & 0x8000) src ^= 0x00e0; + src ^= address_xor; + + rom[i] = decrypt(buf[src], i, data_select_xor); + opcodes[i] = decrypt(buf[src], i, opcode_select_xor); + } + + BurnFree(buf); +} + + +static void decrypt156(UINT32 *src, UINT32 *dst, INT32 length) +{ + INT32 a; + + for (a = 0; a < length/4; a++) + { + INT32 addr, dword; + + addr = (a & 0xff0000) | 0x92c6; + + if (a & 0x0001) addr ^= 0xce4a; + if (a & 0x0002) addr ^= 0x4db2; + if (a & 0x0004) addr ^= 0xef60; + if (a & 0x0008) addr ^= 0x5737; + if (a & 0x0010) addr ^= 0x13dc; + if (a & 0x0020) addr ^= 0x4bd9; + if (a & 0x0040) addr ^= 0xa209; + if (a & 0x0080) addr ^= 0xd996; + if (a & 0x0100) addr ^= 0xa700; + if (a & 0x0200) addr ^= 0xeca0; + if (a & 0x0400) addr ^= 0x7529; + if (a & 0x0800) addr ^= 0x3100; + if (a & 0x1000) addr ^= 0x33b4; + if (a & 0x2000) addr ^= 0x6161; + if (a & 0x4000) addr ^= 0x1eef; + if (a & 0x8000) addr ^= 0xf5a5; + + dword = src[addr]; + + // note that each of the following lines affects exactly two bits + + if (a & 0x00004) dword ^= 0x04400000; + if (a & 0x00008) dword ^= 0x40000004; + if (a & 0x00010) dword ^= 0x00048000; + if (a & 0x00020) dword ^= 0x00000280; + if (a & 0x00040) dword ^= 0x00200040; + if (a & 0x00080) dword ^= 0x09000000; + if (a & 0x00100) dword ^= 0x00001100; + if (a & 0x00200) dword ^= 0x20002000; + if (a & 0x00400) dword ^= 0x00000022; + if (a & 0x00800) dword ^= 0x000a0000; + if (a & 0x01000) dword ^= 0x10004000; + if (a & 0x02000) dword ^= 0x00010400; + if (a & 0x04000) dword ^= 0x80000010; + if (a & 0x08000) dword ^= 0x00000009; + if (a & 0x10000) dword ^= 0x02100000; + if (a & 0x20000) dword ^= 0x00800800; + + switch (a & 3) + { + case 0: + dword = BITSWAP32( dword ^ 0xec63197a, + 1, 4, 7, 28, 22, 18, 20, 9, + 16, 10, 30, 2, 31, 24, 19, 29, + 6, 21, 23, 11, 12, 13, 5, 0, + 8, 26, 27, 15, 14, 17, 25, 3 ); + break; + + case 1: + dword = BITSWAP32( dword ^ 0x58a5a55f, + 14, 23, 28, 29, 6, 24, 10, 1, + 5, 16, 7, 2, 30, 8, 18, 3, + 31, 22, 25, 20, 17, 0, 19, 27, + 9, 12, 21, 15, 26, 13, 4, 11 ); + break; + + case 2: + dword = BITSWAP32( dword ^ 0xe3a65f16, + 19, 30, 21, 4, 2, 18, 15, 1, + 12, 25, 8, 0, 24, 20, 17, 23, + 22, 26, 28, 16, 9, 27, 6, 11, + 31, 10, 3, 13, 14, 7, 29, 5 ); + break; + + case 3: + dword = BITSWAP32( dword ^ 0x28d93783, + 30, 6, 15, 0, 31, 18, 26, 22, + 14, 23, 19, 17, 10, 8, 11, 20, + 1, 28, 2, 4, 9, 24, 25, 27, + 7, 21, 13, 29, 5, 3, 16, 12 ); + break; + } + + dst[a] = dword; + } +} + +void deco156_decrypt(UINT8 *src, INT32 len) +{ + UINT32 *rom = (UINT32*)src; + UINT32 *buf = (UINT32*)BurnMalloc(len); + + memcpy (buf, rom, len); + + decrypt156(buf, rom, len); + + BurnFree(buf); +} + + + +//--------------------------------------------------------------------------------------------------- +// protection code +// should probably be in own file + +UINT16 *deco16_prot_ram; +UINT16 *deco16_prot_inputs; +UINT16 *deco16_buffer_ram; + +#define DECO_PORT(p) (prot_ram[p/2]) + +static INT32 deco16_buffer_ram_selected=0; +static INT32 deco16_xor=0; +static INT32 deco16_mask=0xffff; +static INT32 decoprot_last_write=0; +static INT32 decoprot_last_write_val=0; + +static INT32 mutantf_port_0e_hack=0, mutantf_port_6a_hack=0,mutantf_port_e8_hack=0; + +void deco16ProtReset() +{ + deco16_buffer_ram_selected = 0; + deco16_xor = 0; + deco16_mask = 0xffff; + decoprot_last_write = 0; + decoprot_last_write_val = 0; + mutantf_port_0e_hack = 0; + mutantf_port_6a_hack = 0; + mutantf_port_e8_hack = 0; +} + + +void deco16ProtScan() +{ + SCAN_VAR(deco16_buffer_ram_selected); + SCAN_VAR(deco16_xor); + SCAN_VAR(deco16_mask); + SCAN_VAR(decoprot_last_write); + SCAN_VAR(deco16_vblank); + SCAN_VAR(decoprot_last_write_val); + SCAN_VAR(mutantf_port_0e_hack); + SCAN_VAR(mutantf_port_6a_hack); + SCAN_VAR(mutantf_port_e8_hack); +} + +void deco16_66_prot_w(INT32 offset, UINT16 data, INT32 mask) /* Mutant Fighter */ +{ + offset = (offset & 0x7ff) / 2; + + if (mask == 0xffff) { + deco16_prot_ram[offset] = data; + } else if (mask == 0xff00) { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | (data & ~mask); + } else { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | ((data << 8) & ~mask); + } + +#if 0 + if (offset == (0x64 / 2)) + { + soundlatch = data; + // cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); // huc6280 + return; + } +#endif + + /* See below */ + if (offset==(0xe/2)) + mutantf_port_0e_hack=data; + else + mutantf_port_0e_hack=0x800; + + if (offset==(0x6a/2)) + mutantf_port_6a_hack=data; + else + mutantf_port_6a_hack=0x2866; + + if (offset==(0xe8/2)) + mutantf_port_e8_hack=data; + else + mutantf_port_e8_hack=0x2401; +} + +UINT16 deco16_66_prot_r(INT32 offset) /* Mutant Fighter */ +{ + offset = (offset & 0x7ff) / 2; + + if (offset!=0xe/2) + mutantf_port_0e_hack=0x0800; + if (offset!=0x6a/2) + mutantf_port_6a_hack=0x2866; + + switch (offset*2) { + case 0xac: /* Dip switches */ + return deco16_prot_inputs[2]; + case 0xc2: /* Dip switches */ + return (deco16_prot_inputs[2]) ^ deco16_prot_ram[0x2c/2]; + case 0x46: /* Coins */ + return ((deco16_prot_inputs[1] & 0x07) | (deco16_vblank & 0x08)) ^ deco16_prot_ram[0x2c/2]; + case 0x50: /* Player 1 & 2 input ports */ + return deco16_prot_inputs[0]; + case 0x63c: /* Player 1 & 2 input ports */ + return deco16_prot_inputs[0] ^ deco16_prot_ram[0x2c/2]; + + case 0x5f4: + return deco16_prot_ram[0x18/2]; + case 0x7e8: + return deco16_prot_ram[0x58/2]; + case 0x1c8: + return deco16_prot_ram[0x6a/2]; + case 0x10: + return deco16_prot_ram[0xc/2]; + case 0x672: + return deco16_prot_ram[0x72/2]; + case 0x5ea: + return deco16_prot_ram[0xb8/2]; + case 0x1e8: + return deco16_prot_ram[0x2/2]; + case 0xf6: + return deco16_prot_ram[0x42/2]; + case 0x692: + return deco16_prot_ram[0x2e/2]; + case 0x63a: + return deco16_prot_ram[0x88/2]; + case 0x7a: + return deco16_prot_ram[0xe/2]; + case 0x40e: + return deco16_prot_ram[0x7a/2]; + case 0x602: + return deco16_prot_ram[0x92/2]; + case 0x5d4: + return deco16_prot_ram[0x34/2]; + case 0x6fa: + return deco16_prot_ram[0x4/2]; + case 0x3dc: + return deco16_prot_ram[0xaa/2]; + case 0x444: + return deco16_prot_ram[0xb0/2]; + case 0x102: + return deco16_prot_ram[0xa2/2]; + case 0x458: + return deco16_prot_ram[0xb6/2]; + case 0x2a6: + return deco16_prot_ram[0xe8/2]; + case 0x626: + return deco16_prot_ram[0xf4/2]; + case 0x762: + return deco16_prot_ram[0x82/2]; + case 0x308: + return deco16_prot_ram[0x38/2]; + case 0x1e6: + return deco16_prot_ram[0x1e/2]; + case 0x566: + return deco16_prot_ram[0xa4/2]; + case 0x5b6: + return deco16_prot_ram[0xe4/2]; + case 0x77c: + return deco16_prot_ram[0xfa/2]; + case 0x4ba: + return deco16_prot_ram[0xdc/2]; + + case 0x1e: + return deco16_prot_ram[0xf4/2] ^ deco16_prot_ram[0x2c/2]; + case 0x18e: + return ((deco16_prot_ram[0x1e/2]&0x000f)<<12) | ((deco16_prot_ram[0x1e/2]&0x0ff0)>>0) | ((deco16_prot_ram[0x1e/2]&0xf000)>>12); + case 0x636: + return ((deco16_prot_ram[0x18/2]&0x00ff)<<8) | ((deco16_prot_ram[0x18/2]&0x0f00)>>4) | ((deco16_prot_ram[0x18/2]&0xf000)>>12); + case 0x7d4: + return ((deco16_prot_ram[0xc/2]&0x0ff0)<<4) | ((deco16_prot_ram[0xc/2]&0x000c)<<2) | ((deco16_prot_ram[0xc/2]&0x0003)<<6); + case 0x542: + return ((deco16_prot_ram[0x92/2]&0x00ff)<<8) ^ deco16_prot_ram[0x2c/2]; + case 0xb0: + return (((deco16_prot_ram[0xc/2]&0x000f)<<12) | ((deco16_prot_ram[0xc/2]&0x00f0)<<4) | ((deco16_prot_ram[0xc/2]&0xff00)>>8)) ^ deco16_prot_ram[0x2c/2]; + case 0x4: + return (((deco16_prot_ram[0x18/2]&0x00f0)<<8) | ((deco16_prot_ram[0x18/2]&0x0003)<<10) | ((deco16_prot_ram[0x18/2]&0x000c)<<6)) & (~deco16_prot_ram[0x36/2]); + + case 0xe: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0800. Hmm */ + { + INT32 ret=mutantf_port_0e_hack; + mutantf_port_0e_hack=0x800; + return ret; + } + + case 0x6a: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0x2866. Hmm */ + { + INT32 ret=mutantf_port_6a_hack; + mutantf_port_6a_hack=0x2866; + return ret; + } + + case 0xe8: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0x2401. Hmm */ + { + INT32 ret=mutantf_port_e8_hack; + mutantf_port_e8_hack=0x2401; + return ret; + } + + case 0xaa: /* ??? */ + return 0xc080; + + case 0x42: /* Strange, but consistent */ + return deco16_prot_ram[0x2c/2]^0x5302; + + case 0x48: /* Correct for test data, but I wonder if the 0x1800 is from an address, not a constant */ + return (0x1800) & (~deco16_prot_ram[0x36/2]); + + case 0x52: + return (0x2188) & (~deco16_prot_ram[0x36/2]); + + case 0x82: + return ((0x0022 ^ deco16_prot_ram[0x2c/2])) & (~deco16_prot_ram[0x36/2]); + + case 0xc: + return 0x2000; + } + + return 0; +} + +void deco16_60_prot_w(INT32 offset, UINT16 data, INT32 mask) +{ + deco16_66_prot_w(offset, data, mask); +} + +UINT16 deco16_60_prot_r(INT32 offset) /* Edward Randy */ +{ + offset = (offset & 0x7ff)/2; + + switch (offset<<1) { + /* Video registers */ + case 0x32a: /* Moved to 0x140006 on INT32 */ + return deco16_prot_ram[0x80/2]; + case 0x380: /* Moved to 0x140008 on INT32 */ + return deco16_prot_ram[0x84/2]; + case 0x63a: /* Moved to 0x150002 on INT32 */ + return deco16_prot_ram[0x88/2]; + case 0x42a: /* Moved to 0x150004 on INT32 */ + return deco16_prot_ram[0x8c/2]; + case 0x030: /* Moved to 0x150006 on INT32 */ + return deco16_prot_ram[0x90/2]; + case 0x6b2: /* Moved to 0x150008 on INT32 */ + return deco16_prot_ram[0x94/2]; + + case 0x6fa: + return deco16_prot_ram[0x4/2]; + case 0xe4: + return (deco16_prot_ram[0x4/2]&0xf000)|((deco16_prot_ram[0x4/2]&0x00ff)<<4)|((deco16_prot_ram[0x4/2]&0x0f00)>>8); + + case 0x390: + return deco16_prot_ram[0x2c/2]; + case 0x3b2: + return deco16_prot_ram[0x3c/2]; + case 0x440: + return deco16_prot_ram[0x3e/2]; + + case 0x6fc: + return deco16_prot_ram[0x66/2]; + + case 0x15a: + return deco16_prot_ram[0xa0/2]; + case 0x102: + return deco16_prot_ram[0xa2/2]; + case 0x566: + return deco16_prot_ram[0xa4/2]; + case 0xd2: + return deco16_prot_ram[0xa6/2]; + case 0x4a6: + return deco16_prot_ram[0xa8/2]; + case 0x3dc: + return deco16_prot_ram[0xaa/2]; + case 0x2a0: + return deco16_prot_ram[0xac/2]; + case 0x392: + return deco16_prot_ram[0xae/2]; + case 0x444: + return deco16_prot_ram[0xb0/2]; + + case 0x5ea: + return deco16_prot_ram[0xb8/2]; + case 0x358: + return deco16_prot_ram[0xba/2]; + case 0x342: + return deco16_prot_ram[0xbc/2]; + case 0x3c: + return deco16_prot_ram[0xbe/2]; + case 0x656: + return deco16_prot_ram[0xc0/2]; + case 0x18c: + return deco16_prot_ram[0xc2/2]; + case 0x370: + return deco16_prot_ram[0xc4/2]; + case 0x5c6: + return deco16_prot_ram[0xc6/2]; + + /* C8 written but not read */ + + case 0x248: + return deco16_prot_ram[0xd0/2]; + case 0x1ea: + return deco16_prot_ram[0xd2/2]; + case 0x4cc: + return deco16_prot_ram[0xd4/2]; + case 0x724: + return deco16_prot_ram[0xd6/2]; + case 0x578: + return deco16_prot_ram[0xd8/2]; + case 0x63e: + return deco16_prot_ram[0xda/2]; + case 0x4ba: + return deco16_prot_ram[0xdc/2]; + case 0x1a: + return deco16_prot_ram[0xde/2]; + case 0x120: + return deco16_prot_ram[0xe0/2]; + case 0x7c2: /* (Not checked for mask/xor but seems standard) */ + return deco16_prot_ram[0x50/2]; + + /* memcpy selectors, transfer occurs in interrupt */ + case 0x32e: return deco16_prot_ram[4]; /* src msb */ + case 0x6d8: return deco16_prot_ram[5]; /* src lsb */ + case 0x010: return deco16_prot_ram[6]; /* dst msb */ + case 0x07a: return deco16_prot_ram[7]; /* src lsb */ + + case 0x37c: return deco16_prot_ram[8]; /* src msb */ + case 0x250: return deco16_prot_ram[9]; + case 0x04e: return deco16_prot_ram[10]; + case 0x5ba: return deco16_prot_ram[11]; + case 0x5f4: return deco16_prot_ram[12]; /* length */ + + case 0x38c: return deco16_prot_ram[13]; /* src msb */ + case 0x02c: return deco16_prot_ram[14]; + case 0x1e6: return deco16_prot_ram[15]; + case 0x3e4: return deco16_prot_ram[16]; + case 0x174: return deco16_prot_ram[17]; /* length */ + + /* Player 1 & 2 controls, read in IRQ then written *back* to protection device */ + case 0x50: /* written to 9e byte */ + return deco16_prot_inputs[0]; + case 0x6f8: /* written to 76 byte */ + return (deco16_prot_inputs[0]>>8)|(deco16_prot_inputs[0]<<8); /* byte swap IN0 */ + + case 0x5c: /* After coin insert, high 0x8000 bit set starts game */ + return deco16_prot_ram[0x3b]; + case 0x3a6: /* Top byte OR'd with above, masked to 7 */ + return deco16_prot_ram[0x9e/2]; + case 0xc6: + return ((deco16_prot_ram[0x9e/2]&0xff00)>>8) | ((deco16_prot_ram[0x9e/2]&0x00ff)<<8); + + case 0xac: /* Dip switches */ + return deco16_prot_inputs[2]; + case 0xc2: + return deco16_prot_inputs[2] ^ deco16_prot_ram[0x2c/2]; + + case 0x5d4: /* The state of the dips last frame */ + return deco16_prot_ram[0x34/2]; + + case 0x7bc: + return ((deco16_prot_ram[0x76/2]&0xff00)>>8) | ((deco16_prot_ram[0x76/2]&0x00ff)<<8); + + case 0x2f6: /* Stage clear flag */ + return (((deco16_prot_ram[0]&0xfff0)>>0) | ((deco16_prot_ram[0]&0x000c)>>2) | ((deco16_prot_ram[0]&0x0003)<<2)) & (~deco16_prot_ram[0x36/2]); + + case 0x76a: /* Coins */ + return (deco16_prot_inputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x284: /* Bit shifting with inverted mask register */ + return (((deco16_prot_ram[0x40/2]&0xfff0)>>0) | ((deco16_prot_ram[0x40/2]&0x0007)<<1) | ((deco16_prot_ram[0x40/2]&0x0008)>>3)) & (~deco16_prot_ram[0x36/2]); + case 0x6c4: /* Bit shifting with inverted mask register */ + return (((deco16_prot_ram[0x54/2]&0xf000)>>4) | ((deco16_prot_ram[0x54/2]&0x0f00)>>4) | ((deco16_prot_ram[0x54/2]&0x00f0)>>4) | ((deco16_prot_ram[0x54/2]&0x0003)<<14) | ((deco16_prot_ram[0x54/2]&0x000c)<<10)) & (~deco16_prot_ram[0x36/2]); + case 0x33e: /* Bit shifting with inverted mask register */ + return (((deco16_prot_ram[0x56/2]&0xff00)>>0) | ((deco16_prot_ram[0x56/2]&0x00f0)>>4) | ((deco16_prot_ram[0x56/2]&0x000f)<<4)) & (~deco16_prot_ram[0x36/2]); + case 0x156: /* Bit shifting with inverted mask register */ + return (((deco16_prot_ram[0x58/2]&0xfff0)>>4) | ((deco16_prot_ram[0x58/2]&0x000e)<<11) | ((deco16_prot_ram[0x58/2]&0x0001)<<15)) & (~deco16_prot_ram[0x36/2]); + case 0x286: /* Bit shifting with inverted mask register */ + return (((deco16_prot_ram[0x6a/2]&0x00f0)<<4) | ((deco16_prot_ram[0x6a/2]&0x0f00)<<4) | ((deco16_prot_ram[0x6a/2]&0x0007)<<5) | ((deco16_prot_ram[0x6a/2]&0x0008)<<1)) & (~deco16_prot_ram[0x36/2]); + + case 0x7d6: /* XOR IN0 */ + return deco16_prot_inputs[0] ^ deco16_prot_ram[0x2c/2]; + case 0x4b4: + return ((deco16_prot_ram[0x32/2]&0x00f0)<<8) | ((deco16_prot_ram[0x32/2]&0x000e)<<7) | ((deco16_prot_ram[0x32/2]&0x0001)<<11); + } + + return 0; +} + +UINT16 deco16_104_cninja_prot_r(INT32 offset) +{ + switch (offset & 0x3fe) { + case 0x80: /* Master level control */ + return deco16_prot_ram[0]; + + case 0xde: /* Restart position control */ + return deco16_prot_ram[1]; + + case 0xe6: /* The number of credits in the system. */ + return deco16_prot_ram[2]; + + case 0x86: /* End of game check. See 0x1814 */ + return deco16_prot_ram[3]; + + /* Video registers */ + case 0x5a: /* Moved to 0x140000 on INT32 */ + return deco16_prot_ram[8]; + case 0x84: /* Moved to 0x14000a on INT32 */ + return deco16_prot_ram[9]; + case 0x20: /* Moved to 0x14000c on INT32 */ + return deco16_prot_ram[10]; + case 0x72: /* Moved to 0x14000e on INT32 */ + return deco16_prot_ram[11]; + case 0xdc: /* Moved to 0x150000 on INT32 */ + return deco16_prot_ram[12]; + case 0x6e: /* Moved to 0x15000a on INT32 */ + return deco16_prot_ram[13]; /* Not used on bootleg */ + case 0x6c: /* Moved to 0x15000c on INT32 */ + return deco16_prot_ram[14]; + case 0x08: /* Moved to 0x15000e on INT32 */ + return deco16_prot_ram[15]; + + case 0x36: /* Dip switches */ + return deco16_prot_inputs[2]; + + case 0x1c8: /* Coins */ + return (deco16_prot_inputs[1] & 0x07) | (deco16_vblank & 0x08); + + case 0x22c: /* Player 1 & 2 input ports */ + return deco16_prot_inputs[0]; + } + + return ~0; +} + +UINT16 deco16_146_funkyjet_prot_r(INT32 offset) +{ + offset = (offset & 0x7fe) / 2; + + switch (offset) + { + case 0x00c >> 1: + return deco16_prot_inputs[0]; + + case 0x0be >> 1: + return deco16_prot_ram[0x106>>1]; + + case 0x11e >> 1: + return deco16_prot_ram[0x500>>1]; + + case 0x148 >> 1: + return deco16_prot_ram[0x70e>>1]; + + case 0x192 >>1: + return ((deco16_prot_ram[0x78e>>1]<<0)&0xf000); + + case 0x1da >> 1: + return deco16_prot_ram[0x100>>1]; + + case 0x21c >> 1: + return deco16_prot_ram[0x504>>1]; + + case 0x226 >> 1: + return deco16_prot_ram[0x58c>>1]; + + case 0x24c >> 1: + return deco16_prot_ram[0x78e>>1]; + + case 0x250 >> 1: + return deco16_prot_ram[0x304>>1]; + + case 0x27c >>1: + return ((deco16_prot_ram[0x70e>>1]>>4)&0x0fff) | ((deco16_prot_ram[0x70e>>1]&0x0001)<<15) | ((deco16_prot_ram[0x70e>>1]&0x000e)<<11); + + case 0x2d4 >> 1: + return deco16_prot_ram[0x102>>1]; + + case 0x2d8 >> 1: + return deco16_prot_ram[0x502>>1]; + + case 0x382 >> 1: + return deco16_prot_inputs[2]; + + case 0x3a6 >> 1: + return deco16_prot_ram[0x104>>1]; + + case 0x3a8 >> 1: + return deco16_prot_ram[0x500>>1]; + + case 0x3e8 >> 1: + return (deco16_prot_ram[0x50c>>1] >> 8) ^ 0xffff; + + case 0x4e4 >> 1: + return deco16_prot_ram[0x702>>1]; + + case 0x562 >> 1: + return deco16_prot_ram[0x18e>>1]; + + case 0x56c >> 1: + return deco16_prot_ram[0x50c>>1]; + + case 0x5be >> 1: + return ((deco16_prot_ram[0x70e>>1]<<4)&0xff00) | (deco16_prot_ram[0x70e>>1]&0x000f); + + case 0x5ca >> 1: + return ((deco16_prot_ram[0x78e>>1]>>4)&0xff00) | (deco16_prot_ram[0x78e>>1]&0x000f) | ((deco16_prot_ram[0x78e>>1]<<8)&0xf000); + + case 0x688 >> 1: + return deco16_prot_ram[0x300>>1]; + + case 0x778 >> 1: { + return (deco16_prot_inputs[1] & 0x07) | (deco16_vblank & 0x08); + } + + case 0x788 >> 1: + return deco16_prot_ram[0x700>>1]; + + case 0x7d4 >> 1: + return 0x10; + } + + return ~0; +} + + + + +void deco16_104_rohga_prot_w(INT32 offset, UINT16 data, INT32 mask) +{ + offset = (offset & 0x7ff) / 2; + + if (deco16_buffer_ram_selected) { + if (mask == 0xffff) { + deco16_buffer_ram[offset] = data; + } else if (mask == 0xff00) { + deco16_buffer_ram[offset] = (deco16_buffer_ram[offset] & mask) | (data & ~mask); + } else { + deco16_buffer_ram[offset] = (deco16_buffer_ram[offset] & mask) | ((data << 8) & ~mask); + } + } else { + if (mask == 0xffff) { + deco16_prot_ram[offset] = data; + } else if (mask == 0xff00) { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | (data & ~mask); + } else { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | ((data << 8) & ~mask); + } + } + + if (offset==0x42/2) + deco16_xor = data; + + if (offset==0xee/2) + deco16_mask = data; +} + +UINT16 deco16_104_rohga_prot_r(INT32 offset) +{ + offset = (offset & 0x7ff) / 2; + + const UINT16 * prot_ram=deco16_buffer_ram_selected ? deco16_buffer_ram : deco16_prot_ram; + + switch (offset) { + case 0x88/2: /* Player 1 & 2 input ports */ + return deco16_prot_inputs[0]; + case 0x36c/2: + return (deco16_prot_inputs[1] & 0x7)|(deco16_vblank & 0x08); + case 0x44c/2: + return ((deco16_prot_inputs[1] & 0x7)<<13)|((deco16_vblank & 0x8)<<9); + case 0x292/2: /* Dips */ + return deco16_prot_inputs[2]; + + case 0x44/2: + return ((((DECO_PORT(0x2c)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask); + case 0x282/2: + return ((DECO_PORT(0x26)&0x000f)<<12) & (~deco16_mask); + case 0xd4/2: + return ((DECO_PORT(0x6e)&0x0ff0)<<4) | ((DECO_PORT(0x6e)&0x000e)<<3) | ((DECO_PORT(0x6e)&0x0001)<<7); + case 0x5a2/2: + return (((DECO_PORT(0x24)&0xff00)>>4) | ((DECO_PORT(0x24)&0x000f)<<0) | ((DECO_PORT(0x24)&0x00f0)<<8)) & (~deco16_mask); + case 0x570/2: + return (((DECO_PORT(0x24)&0xf0f0)>>0) | ((DECO_PORT(0x24)&0x000f)<<8)) ^ deco16_xor; + case 0x32e/2: + return (((DECO_PORT(0x46)&0xf000)>>0) | ((DECO_PORT(0x46)&0x00ff)<<4)) & (~deco16_mask); + case 0x4dc/2: + return ((DECO_PORT(0x62)&0x00ff)<<8); + case 0x1be/2: + return ((((DECO_PORT(0xc2)&0x0ff0)<<4) | ((DECO_PORT(0xc2)&0x0003)<<6) | ((DECO_PORT(0xc2)&0x000c)<<2)) ^ deco16_xor) & (~deco16_mask); + + case 0x420/2: + return ((DECO_PORT(0x2e)&0xf000)>>4) | ((DECO_PORT(0x2e)&0x0f00)<<4) | ((DECO_PORT(0x2e)&0x00f0)>>4) | ((DECO_PORT(0x2e)&0x000f)<<4); + + case 0x390/2: + return DECO_PORT(0x2c); + + case 0x756/2: + return ((DECO_PORT(0x60)&0xfff0)>>4) | ((DECO_PORT(0x60)&0x0007)<<13) | ((DECO_PORT(0x60)&0x0008)<<9); + case 0x424/2: + return ((DECO_PORT(0x60)&0xf000)>>4) | ((DECO_PORT(0x60)&0x0f00)<<4) | ((DECO_PORT(0x60)&0x00f0)>>0) | ((DECO_PORT(0x60)&0x000f)<<0); + + case 0x156/2: + return (((DECO_PORT(0xde)&0xff00)<<0) | ((DECO_PORT(0xde)&0x000f)<<4) | ((DECO_PORT(0xde)&0x00f0)>>4)) & (~deco16_mask); + case 0xa8/2: + return (((DECO_PORT(0xde)&0xff00)>>4) | ((DECO_PORT(0xde)&0x000f)<<0) | ((DECO_PORT(0xde)&0x00f0)<<8)) & (~deco16_mask); + case 0x64a/2: + return (((DECO_PORT(0xde)&0xfff0)>>4) | ((DECO_PORT(0xde)&0x000c)<<10) | ((DECO_PORT(0xde)&0x0003)<<14)) & (~deco16_mask); + + case 0x16e/2: + return DECO_PORT(0x6a); + + case 0x39c/2: + return (DECO_PORT(0x6a)&0x00ff) | ((DECO_PORT(0x6a)&0xf000)>>4) | ((DECO_PORT(0x6a)&0x0f00)<<4); + case 0x212/2: + return (((DECO_PORT(0x6e)&0xff00)>>4) | ((DECO_PORT(0x6e)&0x00f0)<<8) | ((DECO_PORT(0x6e)&0x000f)<<0)) ^ deco16_xor; + + case 0x70a/2: + return (((DECO_PORT(0xde)&0x00f0)<<8) | ((DECO_PORT(0xde)&0x0007)<<9) | ((DECO_PORT(0xde)&0x0008)<<5)) ^ deco16_xor; + + case 0x7a0/2: + return (DECO_PORT(0x6e)&0x00ff) | ((DECO_PORT(0x6e)&0xf000)>>4) | ((DECO_PORT(0x6e)&0x0f00)<<4); + case 0x162/2: + return DECO_PORT(0x6e); + + case 0x384/2: + return ((DECO_PORT(0xdc)&0xf000)>>12) | ((DECO_PORT(0xdc)&0x0ff0)<<4) | ((DECO_PORT(0xdc)&0x000c)<<2) | ((DECO_PORT(0xdc)&0x0003)<<6); + + case 0x302/2: + return DECO_PORT(0x24); + case 0x334/2: + return DECO_PORT(0x30); + case 0x34c/2: + return DECO_PORT(0x3c); + + case 0x514/2: + return (((DECO_PORT(0x32)&0x0ff0)<<4) | ((DECO_PORT(0x32)&0x000c)<<2) | ((DECO_PORT(0x32)&0x0003)<<6)) & (~deco16_mask); + + case 0x34e/2: + return ((DECO_PORT(0xde)&0x0ff0)<<4) | ((DECO_PORT(0xde)&0xf000)>>8) | ((DECO_PORT(0xde)&0x000f)<<0); + case 0x722/2: + return (((DECO_PORT(0xdc)&0x0fff)<<4) ^ deco16_xor) & (~deco16_mask); + case 0x574/2: + return ((((DECO_PORT(0xdc)&0xfff0)>>0) | ((DECO_PORT(0xdc)&0x0003)<<2) | ((DECO_PORT(0xdc)&0x000c)>>2)) ^ deco16_xor) & (~deco16_mask); + + case 0x5ae/2: + return DECO_PORT(0xdc); + case 0x410/2: + return DECO_PORT(0xde); + case 0x340/2: + return ((DECO_PORT(0x90)&0xfff0) | ((DECO_PORT(0x90)&0x7)<<1) | ((DECO_PORT(0x90)&0x8)>>3)) ^ deco16_xor; + case 0x4a4/2: + return (((DECO_PORT(0xce)&0x0ff0) | ((DECO_PORT(0xce)&0xf000)>>12) | ((DECO_PORT(0xce)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask); + case 0x256/2: + return ((((DECO_PORT(0xce)&0xf000)>>12) | ((DECO_PORT(0xce)&0x0fff)<<4))) & (~deco16_mask); + case 0x79a/2: + return (((DECO_PORT(0xc8)&0xfff0)>>4) | ((DECO_PORT(0xc8)&0x0008)<<9) | ((DECO_PORT(0xc8)&0x0007)<<13)) ^ deco16_xor; + + case 0x65e/2: + return DECO_PORT(0x9c); + case 0x79c/2: + return ((DECO_PORT(0xc6)&0xf000) | ((DECO_PORT(0xc6)&0x00ff)<<4) | ((DECO_PORT(0xc6)&0x0f00)>>8)) & (~deco16_mask); + case 0x15e/2: + return (((DECO_PORT(0x98)&0x0ff0)<<4) | ((DECO_PORT(0x98)&0xf000)>>12) | ((DECO_PORT(0x98)&0x0003)<<6) | ((DECO_PORT(0x98)&0x000c)<<2)) ^ deco16_xor; + case 0x6e4/2: + return DECO_PORT(0x98); + case 0x1e/2: + return ((((DECO_PORT(0xc4)&0xf000)>>4) | ((DECO_PORT(0xc4)&0x0f00)<<4) | ((DECO_PORT(0xc4)&0x00ff)<<0)) ^ deco16_xor) & (~deco16_mask); + case 0x23a/2: + return ((((DECO_PORT(0x86)&0xfff0)>>0) | ((DECO_PORT(0x86)&0x0003)<<2) | ((DECO_PORT(0x86)&0x000c)>>2)) ^ deco16_xor); + case 0x6e/2: + return ((((DECO_PORT(0x96)&0xf000)>>8) | ((DECO_PORT(0x96)&0x0f0f)<<0) | ((DECO_PORT(0x96)&0x00f0)<<8)) ^ deco16_xor); + case 0x3a2/2: + return ((((DECO_PORT(0x94)&0xf000)>>8) | ((DECO_PORT(0x94)&0x0f00)>>8) | ((DECO_PORT(0x94)&0x00f0)<<8) | ((DECO_PORT(0x94)&0x000e)<<7) | ((DECO_PORT(0x94)&0x0001)<<11)) ^ deco16_xor);// & (~deco16_mask); + case 0x4a6/2: + return ((DECO_PORT(0x8c)&0xff00)>>0) | ((DECO_PORT(0x8c)&0x00f0)>>4) | ((DECO_PORT(0x8c)&0x000f)<<4); + case 0x7b0/2: + return DECO_PORT(0x80); + case 0x5aa/2: + return ((((DECO_PORT(0x98)&0x0f00)>>8) | ((DECO_PORT(0x98)&0xf000)>>8) | ((DECO_PORT(0x98)&0x00f0)<<8) | ((DECO_PORT(0x98)&0x000e)<<7) | ((DECO_PORT(0x98)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask); + case 0x662/2: + return DECO_PORT(0x8c); + case 0x624/2: + return DECO_PORT(0x9a); + case 0x2c/2: + return (((DECO_PORT(0x82)&0x0f0f)>>0) | ((DECO_PORT(0x82)&0xf000)>>8) | ((DECO_PORT(0x82)&0x00f0)<<8)) & (~deco16_mask); + + case 0x1b4/2: + return ((DECO_PORT(0xcc)&0x00f0)<<4) | ((DECO_PORT(0xcc)&0x000f)<<12); + + case 0x7ce/2: + return ((DECO_PORT(0x80)&0x000e)<<11) | ((DECO_PORT(0x80)&0x0001)<<15); + case 0x41a/2: + return ((((DECO_PORT(0x84)&0x00f0)<<8) | ((DECO_PORT(0x84)&0xf000)>>8) | ((DECO_PORT(0x84)&0x0f00)>>8) | ((DECO_PORT(0x84)&0x0003)<<10) | ((DECO_PORT(0x84)&0x000c)<<6)) ^ deco16_xor); + case 0x168/2: + return ((((DECO_PORT(0x84)&0x0ff0)<<4) | ((DECO_PORT(0x84)&0x000e)<<3) | ((DECO_PORT(0x84)&0x0001)<<5))) & (~deco16_mask); + case 0x314/2: + return ((((DECO_PORT(0x84)&0x0ff0)<<4) | ((DECO_PORT(0x84)&0x000e)<<3) | ((DECO_PORT(0x84)&0x0001)<<5))); + case 0x5e2/2: + return ((((DECO_PORT(0x84)&0x00f0)<<8) | ((DECO_PORT(0x84)&0x000e)<<7) | ((DECO_PORT(0x84)&0x0001)<<9))); + case 0x72a/2: + return ((((DECO_PORT(0x86)&0xfff0)>>4) | ((DECO_PORT(0x86)&0x0003)<<14) | ((DECO_PORT(0x86)&0x000c)<<10)) ^ deco16_xor) & (~deco16_mask); + case 0x178/2: + return (((DECO_PORT(0x88)&0x00ff)<<8) | ((DECO_PORT(0x88)&0xff00)>>8)) & (~deco16_mask); + case 0x40e/2: + return ((((DECO_PORT(0x8a)&0xf000)>>0) | ((DECO_PORT(0x8a)&0x00ff)<<4)) ^ deco16_xor) & (~deco16_mask); + case 0x248/2: + return ((((DECO_PORT(0x8c)&0xff00)>>8) | ((DECO_PORT(0x8c)&0x00f0)<<4) | ((DECO_PORT(0x8c)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask); + + case 0x27e/2: + return ((((DECO_PORT(0x94)&0x00f0)<<8)) ^ deco16_xor) & (~deco16_mask); + + case 0x22c/2: + return ((DECO_PORT(0xc4)&0x00f0)<<8); + case 0x77e/2: + return ((DECO_PORT(0x62)&0xf000)>>12) | ((DECO_PORT(0x62)&0x0ff0)<<0) | ((DECO_PORT(0x62)&0x000f)<<12); + case 0xc/2: + return ((DECO_PORT(0xd6)&0xf000)>>12) | ((DECO_PORT(0xd6)&0x0fff)<<4); + + case 0x90/2: + return DECO_PORT(0x44); + case 0x246/2: + return ((((DECO_PORT(0x48)&0xff00)>>8) | ((DECO_PORT(0x48)&0x00f0)<<8) | ((DECO_PORT(0x48)&0x0f00)>>8) | ((DECO_PORT(0x48)&0x0003)<<10) | ((DECO_PORT(0x48)&0x000c)<<6)) ^ deco16_xor); + case 0x546/2: + return (((DECO_PORT(0x62)&0xf0f0)>>0) | ((DECO_PORT(0x62)&0x000f)<<8)) & (~deco16_mask); + case 0x2e2/2: + return ((DECO_PORT(0xc6)&0x000e)<<11) | ((DECO_PORT(0xc6)&0x0001)<<15); + case 0x3c0/2: + return DECO_PORT(0x22); + case 0x4b8/2: + return (((DECO_PORT(0x46)&0xf000)>>12) | ((DECO_PORT(0x46)&0x0f00)>>4) | ((DECO_PORT(0x46)&0x00ff)<<8)) ^ deco16_xor; + case 0x65c/2: + return ((((DECO_PORT(0x44)&0xf000)>>12) | ((DECO_PORT(0x44)&0x0fff)<<4)) ^ deco16_xor) & (~deco16_mask); + + case 0x32a/2: + return ((((DECO_PORT(0xc0)&0x0ff0)<<4) | ((DECO_PORT(0xc0)&0x000e)<<3) | ((DECO_PORT(0xc0)&0x0001)<<7))) & (~deco16_mask);// ^ deco16_xor; + case 0x8/2: + return ((((DECO_PORT(0x94)&0xfff0)<<0) | ((DECO_PORT(0x94)&0x000e)>>1) | ((DECO_PORT(0x94)&0x0001)<<3))) & (~deco16_mask);// ^ deco16_xor; + case 0x456/2: + return (((DECO_PORT(0x26)&0xfff0)<<0) | ((DECO_PORT(0x26)&0x0007)<<1) | ((DECO_PORT(0x26)&0x0008)>>3));// ^ deco16_xor; + case 0x190/2: + return ((((DECO_PORT(0x44)&0xf000)<<0) | ((DECO_PORT(0x44)&0x00ff)<<4))) & (~deco16_mask);// ^ deco16_xor; + case 0x3f2/2: + return ((((DECO_PORT(0x48)&0x000f)<<12) | ((DECO_PORT(0x48)&0x00f0)<<4))) & (~deco16_mask);// ^ deco16_xor; + case 0x2be/2: + return ((DECO_PORT(0x40)&0x00ff)<<8); + + case 0x19e/2: + return ((((DECO_PORT(0x3c)&0xf000)>>12) | ((DECO_PORT(0x3c)&0x0f00)<<4) | ((DECO_PORT(0x3c)&0x00f0)>>0) | ((DECO_PORT(0x3c)&0x000f)<<8)) ^ deco16_xor) & (~deco16_mask); + case 0x2a2/2: + return ((((DECO_PORT(0x44)&0xff00)>>8) | ((DECO_PORT(0x44)&0x00f0)<<8) | ((DECO_PORT(0x44)&0x000e)<<7) | ((DECO_PORT(0x44)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask); + case 0x748/2: + return (((DECO_PORT(0x44)&0xfff0)<<0) | ((DECO_PORT(0x44)&0x000e)>>1) | ((DECO_PORT(0x44)&0x0001)<<3));// & (~deco16_mask); + case 0x686/2: + return (((DECO_PORT(0x46)&0xf000)>>4) | ((DECO_PORT(0x46)&0x0f00)>>8) | ((DECO_PORT(0x46)&0x00f0)<<8) | ((DECO_PORT(0x46)&0x000f)<<4));// & (~deco16_mask); + case 0x4c4/2: + return ((DECO_PORT(0x3c)&0x000f)<<12) & (~deco16_mask); + case 0x538/2: + return ((DECO_PORT(0x3c)&0x000f)<<12); + case 0x63a/2: + return ((DECO_PORT(0x3c)&0x000f)<<12); + case 0x348/2: + return ((((DECO_PORT(0x44)&0xf000)>>12) | ((DECO_PORT(0x44)&0x0ff0)<<4) | ((DECO_PORT(0x44)&0x000e)<<3) | ((DECO_PORT(0x44)&0x0001)<<7))) ^ deco16_xor;// & (~deco16_mask); + case 0x200/2: + return (((DECO_PORT(0xa0)&0xfff0)>>4) | ((DECO_PORT(0xa0)&0x0007)<<13) | ((DECO_PORT(0xa0)&0x0008)<<9));// & (~deco16_mask); + case 0x254/2: + return ((((DECO_PORT(0x7e)&0x0ff0)<<4) | ((DECO_PORT(0x7e)&0x000c)<<2) | ((DECO_PORT(0x7e)&0x0003)<<6))) ^ deco16_xor;// & (~deco16_mask); + case 0x182/2: + return ((DECO_PORT(0x46)&0xf000)<<0) | ((DECO_PORT(0x46)&0x0f00)>>8) | ((DECO_PORT(0x46)&0x00f0)>>0) | ((DECO_PORT(0x46)&0x000f)<<8); + case 0x58/2: + return DECO_PORT(0x46); + case 0x48e/2: + return ((((DECO_PORT(0x46)&0xf000)>>12) | ((DECO_PORT(0x46)&0x0f00)>>4) | ((DECO_PORT(0x46)&0x00f0)<<4) | ((DECO_PORT(0x46)&0x000f)<<12)));// /*^ deco16_xor*/) & (~deco16_mask); + + case 0x4ba/2: + return (((DECO_PORT(0x24)&0xf000)>>12) | ((DECO_PORT(0x24)&0x0ff0)<<4) | ((DECO_PORT(0x24)&0x000c)<<2) | ((DECO_PORT(0x24)&0x0003)<<6)) & (~deco16_mask); + case 0x92/2: + return (((DECO_PORT(0x3c)&0xfff0)>>0) | ((DECO_PORT(0x3c)&0x0007)<<1) | ((DECO_PORT(0x3c)&0x0008)>>3)); + case 0x1f0/2: + return ((((DECO_PORT(0xa2)&0xf000)>>12) | ((DECO_PORT(0xa2)&0x0f00)>>4) | ((DECO_PORT(0xa2)&0x00ff)<<8)) ^ deco16_xor) & (~deco16_mask); + case 0x24e/2: + return ((((DECO_PORT(0x46)&0xf000)>>8) | ((DECO_PORT(0x46)&0x0f00)>>0) | ((DECO_PORT(0x46)&0x00f0)>>4) | ((DECO_PORT(0x46)&0x000f)<<12)) ^ deco16_xor);// & (~deco16_mask); + case 0x594/2: + return ((((DECO_PORT(0x40)&0x00f0)<<8) | ((DECO_PORT(0x40)&0x000c)<<6) | ((DECO_PORT(0x40)&0x0003)<<10)) ^ deco16_xor);// & (~deco16_mask); + + case 0x7e2/2: + return ((((DECO_PORT(0x96)&0xf000)<<0) | ((DECO_PORT(0x96)&0x00f0)<<4) | ((DECO_PORT(0x96)&0x000f)<<4))) ^ deco16_xor;// | ((DECO_PORT(0x96)&0x0001)<<7));// ^ deco16_xor);// & (~deco16_mask); + case 0x18c/2: + return (((DECO_PORT(0x22)&0xfff0)>>4) | ((DECO_PORT(0x22)&0x000e)<<11) | ((DECO_PORT(0x22)&0x0001)<<15));// ^ deco16_xor);// & (~deco16_mask); + case 0x1fa/2: + return ((((DECO_PORT(0x26)&0xf000)>>8) | ((DECO_PORT(0x26)&0x0f00)<<0) | ((DECO_PORT(0x26)&0x00f0)>>4) | ((DECO_PORT(0x26)&0x000f)<<12))) ^ deco16_xor;// & (~deco16_mask); + case 0x70e/2: + return ((((DECO_PORT(0x26)&0x0ff0)<<4) | ((DECO_PORT(0x26)&0x000c)<<2) | ((DECO_PORT(0x26)&0x0003)<<6))) ^ deco16_xor;// & (~deco16_mask); + case 0x33a/2: + return DECO_PORT(0x60) & (~deco16_mask); + case 0x1e2/2: + return ((DECO_PORT(0xd0)&0xf000)>>12) | ((DECO_PORT(0xd0)&0x0f00)>>4) | ((DECO_PORT(0xd0)&0x00ff)<<8); + case 0x3f4/2: + return DECO_PORT(0x6e)<<4; + + case 0x2ae/2: + return ((DECO_PORT(0x9c)&0xf000)<<0) | ((DECO_PORT(0x9c)&0x0ff0)>>4) | ((DECO_PORT(0x9c)&0x000f)<<8);// & (~deco16_mask); + case 0x96/2: + return ((((DECO_PORT(0x22)&0xff00)>>8) | ((DECO_PORT(0x22)&0x00f0)<<8) | ((DECO_PORT(0x22)&0x000e)<<7) | ((DECO_PORT(0x22)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask); + + case 0x33e/2: + return (((DECO_PORT(0x0)&0xf000)>>12) | ((DECO_PORT(0x0)&0x0f00)>>4) | ((DECO_PORT(0x0)&0x00f0)<<4) | ((DECO_PORT(0x0)&0x000f)<<12)) & (~deco16_mask); + + case 0x6c4/2: /* Reads from here flip buffers */ + deco16_buffer_ram_selected^=1; + // Flip occurs AFTER this data has been calculated + return ((DECO_PORT(0x66)&0xf0f0) | ((DECO_PORT(0x66)&0x000f)<<8)) & (~deco16_mask); + case 0x700/2: /* Reads from here flip buffers */ + deco16_buffer_ram_selected^=1; + return (((DECO_PORT(0x66)&0xf000)>>4) | ((DECO_PORT(0x66)&0x00f0)<<8)) ^ deco16_xor; + case 0x444/2: + deco16_buffer_ram_selected^=1; + return ((DECO_PORT(0x66)&0x00f0)<<8) | ((DECO_PORT(0x66)&0x0007)<<9) | ((DECO_PORT(0x66)&0x0008)<<5); + case 0x2d0/2: + deco16_buffer_ram_selected^=1; + return (((DECO_PORT(0x66)&0xf000)>>4) | ((DECO_PORT(0x66)&0x00f0)<<8)) ^ deco16_xor; + case 0x2b8/2: + deco16_buffer_ram_selected^=1; + return ((DECO_PORT(0x66)&0x00f0)<<8) ^ deco16_xor; + case 0x294/2: + deco16_buffer_ram_selected^=1; + return ((DECO_PORT(0x66)&0x000f)<<12); + case 0x1e8/2: + deco16_buffer_ram_selected^=1; + return 0; // todo + + case 0x49c/2: + return (((DECO_PORT(0x6c)&0x00f0)<<8) ^ deco16_xor) & (~deco16_mask); + + case 0x44e/2: + return (((DECO_PORT(0x44)&0x00f0)<<4) | ((DECO_PORT(0x44)&0x000f)<<12)) ^ deco16_xor; + case 0x3ca/2: + return (((DECO_PORT(0x1e)&0xfff0)>>4) | ((DECO_PORT(0x1e)&0x0003)<<14) | ((DECO_PORT(0x1e)&0x000c)<<10)) ^ deco16_xor; + case 0x2ac/2: + return DECO_PORT(0x1e); + case 0x3c/2: + return (((DECO_PORT(0x1e)&0x0003)<<14) | ((DECO_PORT(0x1e)&0x000c)<<10)) & (~deco16_mask); + case 0x174/2: + return (((DECO_PORT(0x1e)&0xff00)>>8) | ((DECO_PORT(0x1e)&0x00f0)<<8) | ((DECO_PORT(0x1e)&0x0007)<<9) | ((DECO_PORT(0x1e)&0x0008)<<5)) & (~deco16_mask); + case 0x34a/2: + return (((DECO_PORT(0x4)&0xff00)>>0) | ((DECO_PORT(0x4)&0x00f0)>>4) | ((DECO_PORT(0x4)&0x000f)<<4)) & (~deco16_mask); + case 0x324/2: + return (((DECO_PORT(0x6)&0xf000)>>12) | ((DECO_PORT(0x6)&0x0ff0)<<4) | ((DECO_PORT(0x6)&0x0007)<<5) | ((DECO_PORT(0x6)&0x0008)<<1)); + case 0x344/2: + return (((DECO_PORT(0x8)&0xf000)>>8) | ((DECO_PORT(0x8)&0x0f00)>>8) | ((DECO_PORT(0x8)&0x00f0)<<4) | ((DECO_PORT(0x8)&0x000f)<<12)); + case 0x72/2: + return ((((DECO_PORT(0xa)&0xf000)>>8) | ((DECO_PORT(0xa)&0x0ff0)<<4) | ((DECO_PORT(0xa)&0x000f)>>0))) & (~deco16_mask); + case 0x36e/2: + return ((((DECO_PORT(0xc)&0xf000)>>0) | ((DECO_PORT(0xc)&0x0ff0)>>4) | ((DECO_PORT(0xc)&0x000f)<<8))) & (~deco16_mask); + + case 0x590/2: + return ((((DECO_PORT(0xe)&0xfff0)>>4) | ((DECO_PORT(0xe)&0x000e)<<11) | ((DECO_PORT(0xe)&0x0001)<<15))) ^ deco16_xor; + case 0x7b6/2: + return ((((DECO_PORT(0x2)&0xf000)>>8) | ((DECO_PORT(0x2)&0x0ff0)<<4) | ((DECO_PORT(0x2)&0x000f)<<0)) ^ deco16_xor) & (~deco16_mask); + case 0x588/2: + return ((((DECO_PORT(0x4)&0xff00)>>4) | ((DECO_PORT(0x4)&0x00f0)<<8) | ((DECO_PORT(0x4)&0x000f)<<0)) ^ deco16_xor) & (~deco16_mask); + case 0x1f6/2: + return (((DECO_PORT(0x6)&0xf000)>>12) | ((DECO_PORT(0x6)&0x0ff0)<<4) | ((DECO_PORT(0x6)&0x0007)<<5) | ((DECO_PORT(0x6)&0x0008)<<1)) ^ deco16_xor; + case 0x4c0/2: + return (((DECO_PORT(0x8)&0xf000)>>4) | ((DECO_PORT(0x8)&0x0f00)<<4) | ((DECO_PORT(0x8)&0x00f0)>>4) | ((DECO_PORT(0x8)&0x000f)<<4)) & (~deco16_mask); + case 0x63e/2: + return ((((DECO_PORT(0xa)&0x0ff0)<<4) | ((DECO_PORT(0xa)&0xf000)>>12) | ((DECO_PORT(0xa)&0x0003)<<6) | ((DECO_PORT(0xa)&0x000c)<<2))); + case 0x7cc/2: + return ((((DECO_PORT(0xc)&0xfff0)>>4) | ((DECO_PORT(0xc)&0x000e)<<11) | ((DECO_PORT(0xc)&0x0001)<<15)) ^ deco16_xor) & (~deco16_mask); + case 0x1bc/2: + return (((DECO_PORT(0xe)&0xf000)>>12) | ((DECO_PORT(0xe)&0x0f00)>>4) | ((DECO_PORT(0xe)&0x00ff)<<8)) & (~deco16_mask); + + case 0x780/2: + return DECO_PORT(0xb8); + + case 0x454/2: + return (((DECO_PORT(0x82)&0xf000)>>8) | ((DECO_PORT(0x82)&0x0f00)>>0) | ((DECO_PORT(0x82)&0x00f0)>>4) | ((DECO_PORT(0x82)&0x000f)<<12)) ^ deco16_xor; + case 0x53e/2: + return ((DECO_PORT(0x9e)&0x0003)<<14) | ((DECO_PORT(0x9e)&0x000c)<<10); + case 0x250/2: + return (((DECO_PORT(0x62)&0xf0f0)<<0) | ((DECO_PORT(0x62)&0x0f00)>>8) | ((DECO_PORT(0x62)&0x000f)<<8)) & (~deco16_mask); + + + case 0x150/2: /* Shared */ + return DECO_PORT(0x7e); + case 0x10e/2: /* Schmeizr Robo only */ + return DECO_PORT(0x7c); + case 0x56a/2: /* Schmeizr Robo only */ + return (((DECO_PORT(0x7c)&0xfff0)>>4) | ((DECO_PORT(0x7c)&0x000e)<<11) | ((DECO_PORT(0x7c)&0x0001)<<15)) & (~deco16_mask); + case 0x39a/2: /* Schmeizr Robo only */ + return ((((DECO_PORT(0x7e)&0xfff0)>>4) | ((DECO_PORT(0x7e)&0x000e)<<11) | ((DECO_PORT(0x7e)&0x0001)<<15)) ^ deco16_xor) & (~deco16_mask); + case 0x188/2: /* Schmeizr Robo only */ + return (((deco16_mask&0x0003)<<6) | ((deco16_mask&0x000c)<<2) | ((deco16_mask&0x00f0)<<4) | ((deco16_mask&0x0f00)<<4)) & (~deco16_mask); + case 0x3cc/2: /* Schmeizr Robo only */ + return deco16_mask; + case 0x4a/2: /* Schmeizr Robo only */ + return DECO_PORT(0x9e) & (~deco16_mask); + case 0x7e8/2: /* Schmeizr Robo only */ + return DECO_PORT(0x4a) ^ deco16_xor; + case 0xfc/2: /* Schmeizr Robo only */ + return DECO_PORT(0x4a); + case 0x38c/2: /* Schmeizr Robo only */ + return DECO_PORT(0x28); + case 0x28/2: /* Schmeizr Robo only */ + return DECO_PORT(0x58); + } + + return 0; +} + +UINT16 deco16_104_prot_r(INT32 offset) /* Wizard Fire */ +{ + offset = (offset & 0x7ff)/2; + + switch (offset<<1) { + case 0x110: /* Player input */ + return deco16_prot_inputs[0]; + + case 0x36c: /* Coins */ + case 0x334: /* Probably also, c6, 2c0, 2e0, 4b2, 46a, 4da, rohga is 44c */ + return (deco16_prot_inputs[1] & 0x7) | (deco16_vblank & 0x08); + case 0x0dc: + return ((deco16_prot_inputs[1] & 0x7) | (deco16_vblank & 0x08))<<4; + + case 0x494: /* Dips */ + return deco16_prot_inputs[2]; + + case 0x244: + return deco16_prot_ram[0]; + case 0x7cc: + return ((deco16_prot_ram[0]&0x000f)<<12) | ((deco16_prot_ram[0]&0x00f0)<<4) | ((deco16_prot_ram[0]&0x0f00)>>4) | ((deco16_prot_ram[0]&0xf000)>>12); + case 0x0c0: + return (((deco16_prot_ram[0]&0x000e)>>1) | ((deco16_prot_ram[0]&0x0001)<<3))<<12; + case 0x188: + return (((deco16_prot_ram[0]&0x000e)>>1) | ((deco16_prot_ram[0]&0x0001)<<3))<<12; + case 0x65e: + return (((deco16_prot_ram[0]&0x000c)>>2) | ((deco16_prot_ram[0]&0x0003)<<2))<<12; + case 0x5ce: + return ((deco16_prot_ram[0]<<8)&0xf000) | ((deco16_prot_ram[0]&0xe)<<7) | ((deco16_prot_ram[0]&0x1)<<11); + case 0x61a: + return (deco16_prot_ram[0]<<8)&0xff00; + + case 0x496: + return deco16_prot_ram[0x110/2]; + case 0x40a: + return ((deco16_prot_ram[0x110/2]&0x000f)<<12) | ((deco16_prot_ram[0x110/2]&0x00f0)>>4) | ((deco16_prot_ram[0x110/2]&0x0f00)<<0) | ((deco16_prot_ram[0x110/2]&0xf000)>>8); + case 0x1e8: + return ((deco16_prot_ram[0x110/2]&0x00ff)<<8) | ((deco16_prot_ram[0x110/2]&0xff00)>>8); + case 0x4bc: + return ((deco16_prot_ram[0x110/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x110/2]&0x0003)<<6) | ((deco16_prot_ram[0x110/2]&0x000c)<<2); + case 0x46e: + return ((deco16_prot_ram[0x110/2]&0xfff0)<<0) | ((deco16_prot_ram[0x110/2]&0x0007)<<1) | ((deco16_prot_ram[0x110/2]&0x0008)>>3); + case 0x264: + return ((deco16_prot_ram[0x110/2]&0x000f)<<8) | ((deco16_prot_ram[0x110/2]&0x00f0)>>0) | ((deco16_prot_ram[0x110/2]&0x0f00)<<4); + case 0x172: + return ((deco16_prot_ram[0x110/2]&0x000f)<<4) | ((deco16_prot_ram[0x110/2]&0x00f0)<<4) | ((deco16_prot_ram[0x110/2]&0xf000)<<0); + + case 0x214: + return deco16_prot_ram[0x280/2]; + case 0x52e: + return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0); + case 0x07a: + return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0); + case 0x360: + return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0); + case 0x4dc: + return ((deco16_prot_ram[0x280/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x280/2]&0x0007)<<5) | ((deco16_prot_ram[0x280/2]&0x0008)<<1); + case 0x3a8: + return ((deco16_prot_ram[0x280/2]&0x000e)<<3) | ((deco16_prot_ram[0x280/2]&0x0001)<<7) | ((deco16_prot_ram[0x280/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x280/2]&0xf000)>>12); + case 0x2f6: + return ((deco16_prot_ram[0x280/2]&0xff00)>>8) | ((deco16_prot_ram[0x280/2]&0x00f0)<<8) | ((deco16_prot_ram[0x280/2]&0x000c)<<6) | ((deco16_prot_ram[0x280/2]&0x0003)<<10); + + case 0x7e4: + return (deco16_prot_ram[0x290/2]&0x00f0)<<8; + + case 0x536: + return ((deco16_prot_ram[0x2b0/2]&0x000f)<<8) | ((deco16_prot_ram[0x2b0/2]&0x00f0)<<0) | ((deco16_prot_ram[0x2b0/2]&0x0f00)<<4) | ((deco16_prot_ram[0x2b0/2]&0xf000)>>12); + + case 0x0be: + return ((deco16_prot_ram[0x370/2]&0x000f)<<4) | ((deco16_prot_ram[0x370/2]&0x00f0)<<4) | ((deco16_prot_ram[0x370/2]&0x0f00)>>8) | ((deco16_prot_ram[0x370/2]&0xf000)>>0); + + case 0x490: + return (deco16_prot_ram[0x3c0/2]&0xfff0) | ((deco16_prot_ram[0x3c0/2]&0x0007)<<1) | ((deco16_prot_ram[0x3c0/2]&0x0008)>>3); + + case 0x710: + return (deco16_prot_ram[0x430/2]&0xfff0) | ((deco16_prot_ram[0x430/2]&0x0007)<<1) | ((deco16_prot_ram[0x430/2]&0x0008)>>3); + + case 0x22a: + return ((deco16_prot_ram[0x5a0/2]&0xff00)>>8) | ((deco16_prot_ram[0x5a0/2]&0x00f0)<<8) | ((deco16_prot_ram[0x5a0/2]&0x0001)<<11) | ((deco16_prot_ram[0x5a0/2]&0x000e)<<7); + + case 0x626: + return ((deco16_prot_ram[0x5b0/2]&0x000f)<<8) | ((deco16_prot_ram[0x5b0/2]&0x00f0)<<8) | ((deco16_prot_ram[0x5b0/2]&0x0f00)>>4) | ((deco16_prot_ram[0x5b0/2]&0xf000)>>12); + + case 0x444: + return deco16_prot_ram[0x604/2]; //rohga + + case 0x5ac: + return ((deco16_prot_ram[0x6e0/2]&0xfff0)>>4) | ((deco16_prot_ram[0x6e0/2]&0x0007)<<13) | ((deco16_prot_ram[0x6e0/2]&0x0008)<<9); + + case 0x650: + return ((deco16_prot_ram[0x7d0/2]&0xfff0)>>4) | ((deco16_prot_ram[0x7d0/2]&0x000f)<<12); + + case 0x4ac: + return ((deco16_prot_ram[0x460/2]&0x0007)<<13) | ((deco16_prot_ram[0x460/2]&0x0008)<<9); + } + + return 0; +} + + + + + + +static void deco16_146_core_prot_w(INT32 offset, INT32 data, INT32 mask) +{ + const INT32 writeport=offset; + const INT32 sndport=0x260; + const INT32 xorport=0x340; + const INT32 maskport=0x6c0; + if (writeport == sndport) + { +// soundlatch_w(space, 0, data & 0xff); +// cputag_set_input_line(space->machine, "audiocpu", 0, HOLD_LINE); + return; + } + + if (writeport==xorport) + deco16_xor = data; //COMBINE_DATA(&deco16_xor); + if (writeport==maskport) + deco16_mask = data; //COMBINE_DATA(&deco16_mask); + + offset >>= 1; + + if (deco16_buffer_ram_selected) { + if (mask == 0xffff) { + deco16_buffer_ram[offset] = data; + } else if (mask == 0xff00) { + deco16_buffer_ram[offset] = (deco16_buffer_ram[offset] & mask) | (data & ~mask); + } else { + deco16_buffer_ram[offset] = (deco16_buffer_ram[offset] & mask) | ((data << 8) & ~mask); + } + } else { + if (mask == 0xffff) { + deco16_prot_ram[offset] = data; + } else if (mask == 0xff00) { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | (data & ~mask); + } else { + deco16_prot_ram[offset] = (deco16_prot_ram[offset] & mask) | ((data << 8) & ~mask); + } + } +} + +static UINT16 deco16_146_core_prot_r(INT32 offset) +{ + UINT16 val; + const UINT16 * prot_ram=deco16_buffer_ram_selected ? deco16_buffer_ram : deco16_prot_ram; + + switch (offset) + { + case 0x582: /* Player 1 & Player 2 */ + return deco16_prot_inputs[0]; + case 0x04c: /* Coins/VBL */ + return (deco16_prot_inputs[1] & 0x07) | (deco16_vblank & 0x08); + case 0x672: /* Dip switches */ + return deco16_prot_inputs[2]; + + case 0x13a: + return ((DECO_PORT(0x190)&0x00f0)<<8) | ((DECO_PORT(0x190)&0x0003)<<10) | ((DECO_PORT(0x190)&0x000c)<<6); + + case 0x53c: + return ((DECO_PORT(0x30)&0x0ff0)<<4) | ((DECO_PORT(0x30)&0xf000)>>8); + + case 0x6c: + return ((DECO_PORT(0x370)&0x00ff)<<8); + + case 0xa: + return ((DECO_PORT(0x310)&0x0fff)<<4); + + case 0x4f6: + return ((DECO_PORT(0x20)&0x00f0)<<8) | ((DECO_PORT(0x20)&0x0007)<<9) | ((DECO_PORT(0x20)&0x0008)<<5); + + case 0xea: + return ((DECO_PORT(0x1c0)&0xf000)<<0) | ((DECO_PORT(0x1c0)&0x00ff)<<4); + + case 0x12e: + return ((DECO_PORT(0x1f0)&0xf000)>>4) | ((DECO_PORT(0x1f0)&0x0f00)<<4) | ((DECO_PORT(0x1f0)&0x00f0)>>4) | ((DECO_PORT(0x1f0)&0x000f)<<4); + + case 0x316: + return ((DECO_PORT(0x290)&0xf000)>>4) | ((DECO_PORT(0x290)&0x0f00)<<4) | ((DECO_PORT(0x290)&0x00ff)<<0); + + case 0x3c6: + return ((DECO_PORT(0x170)&0xfff0)<<0) | ((DECO_PORT(0x170)&0x000e)>>1) | ((DECO_PORT(0x170)&0x0001)<<3); + + case 0x4d0: + return ((DECO_PORT(0x20)&0x00f0)<<8) | ((DECO_PORT(0x20)&0x0007)<<9) | ((DECO_PORT(0x20)&0x0008)<<5); + + case 0x53a: + return ((DECO_PORT(0x370)&0xffff)<<0); + + case 0x552: + return ((DECO_PORT(0x240)&0xfff0)<<0) | ((DECO_PORT(0x240)&0x0007)<<1) | ((DECO_PORT(0x240)&0x0008)>>3); + + case 0x54c: + return ((DECO_PORT(0x2f0)&0x00ff)<<8); + + case 0x5da: + return ((DECO_PORT(0x130)&0x00f0)<<8) | ((DECO_PORT(0x130)&0x000e)<<7) | ((DECO_PORT(0x130)&0x0001)<<11); + + case 0x6be: + return ((DECO_PORT(0x150)&0xf000)>>12) | ((DECO_PORT(0x150)&0x0ff0)<<0) | ((DECO_PORT(0x150)&0x000f)<<12); + + case 0x70a: + return ((DECO_PORT(0x1d0)&0x0ff0)<<4) | ((DECO_PORT(0x1d0)&0x0003)<<6) | ((DECO_PORT(0x1d0)&0x000c)<<2); + + case 0x7e0: + return ((DECO_PORT(0x2b0)&0xfff0)<<0) | ((DECO_PORT(0x2b0)&0x0003)<<2) | ((DECO_PORT(0x2b0)&0x000c)>>2); + + case 0x1de: + return ((DECO_PORT(0x1b0)&0x0ff0)<<4) | ((DECO_PORT(0x1b0)&0x000e)<<3) | ((DECO_PORT(0x1b0)&0x0001)<<7); + + /*********************************************************************************/ + +// case 0x582: return input_port_read(space->machine, "IN0"); /* IN0 */ +// case 0x672: return input_port_read(space->machine, "IN1"); /* IN1 */ +// case 0x04c: return eeprom_read_bit(devtag_get_device(space->machine, "eeprom")); + + case 0x468: + val=DECO_PORT(0x570); + val=((val&0x0003)<<6) | ((val&0x000c)<<2) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>12); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x1ea: + val=DECO_PORT(0x570); + val=((val&0x0003)<<10) | ((val&0x000c)<<6) | ((val&0x00f0)<<8) | ((val&0x0f00)>>8) | ((val&0xf000)>>8); + return val ^ deco16_xor; + + case 0x7b6: + val=((DECO_PORT(0))&0xffff); + val=((val&0x000c)>>2) | ((val&0x0003)<<2) | ((val&0xfff0)<<0); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x01c: + val=((DECO_PORT(0))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>8); + return val ^ deco16_xor; + + case 0x1e0: + val=((DECO_PORT(0))&0xffff); + val=((val&0x000e)<<3) | ((val&0x0001)<<7) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>12); + return val ^ deco16_xor; + + case 0x1d4: + val=((DECO_PORT(0))&0xffff); + val=((val&0x000f)<<0) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>8); + return val; + + case 0x0c0: + val=((DECO_PORT(0x280))&0xffff); + val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0x0f00)<<4) | ((val&0xf000)>>4); + return val ^ deco16_xor; + + case 0x794: + val=((DECO_PORT(0x280))&0xffff); + val=((val&0x0007)<<1) | ((val&0xfff0)>>0) | ((val&0x0008)>>3); + return val ^ deco16_xor; + + case 0x30: + val=DECO_PORT(0x5e0); + val=((val&0x0007)<<13) | ((val&0x0008)<<9); /* Bottom bits are masked out before XOR */ + return val ^ deco16_xor; + + case 0x422: + val=((DECO_PORT(0x3d0))&0xffff); + val=((val&0x0007)<<1) | ((val&0xfff0)>>0) | ((val&0x0008)>>3); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x558: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000f)<<0) | ((val&0x00f0)<<8) | ((val&0x0f00)>>0) | ((val&0xf000)>>8); + return val; + + case 0x3e: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0x0f00)<<4) | ((val&0xf000)>>4); + return val & (~deco16_mask); + + case 0x328: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000e)<<3) | ((val&0x0001)<<7) | ((val&0x00f0)<<4) | ((val&0xf000)>>12) | ((val&0x0f00)<<4); + return val ^ deco16_xor; + + case 0x476: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000f)<<0) | ((val&0x00f0)<<8) | ((val&0xff00)>>4); + return val; + + case 0x50a: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)>>4) | ((val&0x0f00)<<0) | ((val&0xf000)>>8); + return val; + + case 0x5ae: + val=((DECO_PORT(0x210))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)>>4) | ((val&0x0f00)>>0) | ((val&0xf000)>>8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x1ae: + val=((DECO_PORT(0x3d0))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)<<4); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x7a4: + val=((DECO_PORT(0x620))&0xffff); + val=((val&0x000f)<<4) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>0); + return val; + + case 0x2c4: + val=((DECO_PORT(0x410))&0xffff); + val=((val&0x00ff)<<8) | ((val&0xff00)>>8); + return val ^ deco16_xor; + + case 0x76: /* Bitshifted XOR, with additional inverse mask on final output */ + val=((DECO_PORT(0x2a0))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x714: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x2a0))&0xffff); + val=((val&0x0003)<<14) | ((val&0x000c)<<10) | ((val&0xfff0)>>4); + return val & (~deco16_mask); + + case 0x642: + val=((DECO_PORT(0x2a0))&0xffff); + val=((val&0xf000)>>4) | ((val&0x0f00)>>8)| ((val&0x00f0)<<8) | ((val&0x000f)<<4); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x49a: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x580))&0xffff); + val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0xff00)>>0); + return val & (~deco16_mask); + + case 0x49c: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x580))&0xffff); + val=((val&0x000e)<<7) | ((val&0x00f0)<<8) | ((val&0x0001)<<11); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x584: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x580))&0xffff); + val=((val&0xff00)>>8) | ((val&0x00f0)<<8) | ((val&0x0008)<<5) | ((val&0x0007)<<9); + return val & (~deco16_mask); + + case 0x614: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x580))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>4) | ((val&0xf000)>>12); + return val & (~deco16_mask); + + case 0x162: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0xe0))&0xffff); + val=((val&0x0fff)<<4); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x18: + val=((DECO_PORT(0x230))&0xffff); + val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9); + return val ^ deco16_xor; + + case 0x7f6: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x230))&0xffff); + val=((val&0x000f)<<12) | ((val&0x00f0)<<4); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x1a0: /* Bitshifting with inverse mask on final output */ + val=((DECO_PORT(0x230))&0xffff); + val=((val&0xff00)>>8) | ((val&0x00f0)<<8) | ((val&0x0003)<<10) | ((val&0x000c)<<6); + return val & (~deco16_mask); + + case 0x4f8: + val=((DECO_PORT(0x2d0))&0xffff); + val=((val&0x0fff)<<4); + return val; + + case 0x1d6: + val=((DECO_PORT(0xa0))&0xffff); + val=((val&0x0fff)<<4); + return val ^ deco16_xor; + + case 0x254: + val=((DECO_PORT(0x320))&0xffff); + val=((val&0x0f00)<<4) | ((val&0x00f0)<<0) | ((val&0x000f)<<8); + return val & (~deco16_mask); + + case 0x2ea: + val=((DECO_PORT(0x320))&0xffff); + val=((val&0x00ff)<<8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x21e: + val=((DECO_PORT(0x2f0))&0xffff); + val=((val&0xfff0)<<0) | ((val&0x0007)<<1) | ((val&0x0008)>>3); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x7b0: + val=((DECO_PORT(0x2f0))&0xffff); + val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9); + return val ^ deco16_xor; + + case 0x7da: + val=((DECO_PORT(0x2f0))&0xffff); + val=((val&0xff00)>>8) | ((val&0x000f)<<12) | ((val&0x00f0)<<4); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x280: + val=((DECO_PORT(0x2d0))&0xffff); + val=((val&0x000f)<<8) | ((val&0x00f0)<<8) | ((val&0xf000)>>12) | ((val&0x0f00)>>4); + return val ^ deco16_xor; + + case 0x416: + val=((DECO_PORT(0x2e0))&0xffff); + val=((val&0x000f)<<8) | ((val&0x00f0)>>4) | ((val&0xf000)>>0) | ((val&0x0f00)>>4); + return val; + + + case 0xac: + val=((DECO_PORT(0x350))&0xffff); + val=((val&0x000f)<<4) | ((val&0x00f0)<<4) | ((val&0xf000)>>0) | ((val&0x0f00)>>8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x2c2: + val=((DECO_PORT(0x2e0))&0xffff); + val=((val&0xf000)<<0) | ((val&0x0ff0)>>4) | ((val&0x000f)<<8); + return val; + + case 0x450: + val=((DECO_PORT(0x440))&0xffff); + val=((val&0xff00)>>8) | ((val&0x00f0)<<4) | ((val&0x000f)<<12); + return val; + + case 0x504: + val=((DECO_PORT(0x440))&0xffff); + val=((val&0x000c)<<2) | ((val&0x0003)<<6)| ((val&0x0ff0)<<4); + return val ^ deco16_xor; + + case 0xfe: + val=((DECO_PORT(0x440))&0xffff); + val=((val&0x0fff)<<4); + return val; + + // 1c0 swap address + case 0x1c0: + deco16_buffer_ram_selected^=1; + return 0; + + case 0x0e2: + deco16_buffer_ram_selected^=1; + val=((DECO_PORT(0x6c0))&0xffff); + return val ^ deco16_xor; + + case 0x444: + val=((DECO_PORT(0xa0))&0xffff); + val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9); + return val & (~deco16_mask); + + case 0x46a: + val=((DECO_PORT(0x10))&0xffff); + val=((val&0xff00)>>8) | ((val&0x00f0)<<8)| ((val&0x0007)<<9) | ((val&0x0008)<<5); + return val; + + case 0x80: + return DECO_PORT(0xe0); + + case 0xb2: + val=((DECO_PORT(0x280))&0xffff); + val=((val&0x00f0)<<8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x250: + val=((DECO_PORT(0x160))&0xffff); + val=((val&0xf000)>>12) | ((val&0x0f00)<<4)| ((val&0x00f0)<<4) | ((val&0x000e)<<3) | ((val&0x0001)<<7); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x306: + val=((DECO_PORT(0x160))&0xffff); + val=((val&0x00f0)<<8) | ((val&0xf000)>>4); + return (val ^ deco16_xor); + + case 0x608: + val=((DECO_PORT(0x160))&0xffff); + val=((val&0xf000)>>4) | ((val&0x0f00)>>4)| ((val&0x00f0)<<8) | ((val&0x000f)<<0); + return val & (~deco16_mask); + + case 0x52e: + val=((DECO_PORT(0x160))&0xffff); + val=((val&0xf000)>>4) | ((val&0x0f00)<<4)| ((val&0x00f0)<<0) | ((val&0x000f)<<0); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x67a: + val=((DECO_PORT(0x390))&0xffff); + val=((val&0xf000)>>8) | ((val&0x0ff0)<<4)| ((val&0x000f)<<0); + return val; + + case 0x6c2: + val=((DECO_PORT(0x390))&0xffff); + val=((val&0x00f0)<<8) | ((val&0x000c)<<6)| ((val&0x0003)<<10); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x3d8: + val=((DECO_PORT(0x7e0))&0xffff); + val=((val&0xf000)>>8) | ((val&0x0ff0)<<4)| ((val&0x000f)<<0); + return val & (~deco16_mask); + + case 0x244: + val=((DECO_PORT(0x760))&0xffff); + val=((val&0x0f00)<<4) | ((val&0x00f0)>>0)| ((val&0x000f)<<8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x7e8: + val=((DECO_PORT(0x390))&0xffff); + val=((val&0x0f00)<<4) | ((val&0xf000)>>4)| ((val&0x00ff)>>0); + return (val ^ deco16_xor); + + case 0x276: + val=((DECO_PORT(0x7e0))&0xffff); + val=((val&0x00ff)<<8); + return (val ^ deco16_xor) & (~deco16_mask); + + case 0x540: + val=((DECO_PORT(0x530))&0xffff); + val=((val&0x00f0)<<8) | ((val&0x0007)<<9) | ((val&0x0008)<<5); + return val & (~deco16_mask); + + case 0x5c2: + val=((DECO_PORT(0x7e0))&0xffff); + val=((val&0xf000)>>12) | ((val&0x0ff0)<<4)| ((val&0x000c)<<2)| ((val&0x0003)<<6); + return val; + + case 0x15c: + val=((DECO_PORT(0x230))&0xffff); + val=((val&0xff00)<<0) | ((val&0x000f)<<4) | ((val&0x00f0)>>4); + return (val ^ deco16_xor); + + case 0x2c: + val=((DECO_PORT(0x390))&0xffff); + val=((val&0x00ff)<<8); + return val & (~deco16_mask); + } + + return 0; +} + + +void deco16_146_nitroball_prot_w(INT32 offset, UINT16 data, INT32 mask) +{ + offset = BITSWAP16((offset & 0x7fe), 0, 0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + deco16_146_core_prot_w(offset, data, mask); +} + +UINT16 deco16_146_nitroball_prot_r(INT32 offset) +{ + offset = BITSWAP16((offset & 0x7fe), 0, 0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + return deco16_146_core_prot_r(offset); +} + + +void deco16_146_fghthist_prot_w(INT32 offset, UINT32 data, UINT32 mem_mask) +{ + offset = BITSWAP16(offset << 1, 0, 0, 0, 0, 0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5, 0); + + decoprot_last_write = offset; + decoprot_last_write_val = data >> 16; + + deco16_146_core_prot_w(offset, data >> 16, mem_mask >> 16); +} + +UINT32 deco16_146_fghthist_prot_r(INT32 offset) +{ + offset = BITSWAP16(offset << 1, 0, 0, 0, 0, 0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5, 0); + + if (decoprot_last_write==offset) + { + decoprot_last_write=-1; + return (decoprot_last_write_val<<16)|0xffff; + } + + decoprot_last_write=-1; + + return (deco16_146_core_prot_r(offset)<<16)|0xffff; +} + + + + diff --git a/src/burn/drivers/misc_post90s/deco16ic.h b/src/burn/drivers/misc_post90s/deco16ic.h new file mode 100644 index 00000000..d8078121 --- /dev/null +++ b/src/burn/drivers/misc_post90s/deco16ic.h @@ -0,0 +1,116 @@ + +// deco16 tilemap routines + +extern UINT16 *deco16_pf_control[2]; +extern UINT8 *deco16_pf_ram[4]; +extern UINT8 *deco16_pf_rowscroll[4]; + +extern UINT16 deco16_priority; + +void deco16_set_bank_callback(INT32 tmap, INT32 (*callback)(const INT32 bank)); +void deco16_set_color_base(INT32 tmap, INT32 base); +void deco16_set_color_mask(INT32 tmap, INT32 mask); +void deco16_set_transparency_mask(INT32 tmap, INT32 mask); +void deco16_set_gfxbank(INT32 tmap, INT32 small, INT32 big); +void deco16_set_global_offsets(INT32 x, INT32 y); + +void deco16_set_scroll_offs(INT32 tmap, INT32 size, INT32 offsetx, INT32 offsety); + +INT32 deco16_get_tilemap_size(INT32 tmap); + +extern UINT8 *deco16_prio_map; +void deco16_clear_prio_map(); +void deco16_draw_prio_sprite(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri); +void deco16_draw_prio_sprite(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri, INT32 spri); +void deco16_draw_alphaprio_sprite(UINT32 *palette, UINT8 *gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 pri, INT32 spri, INT32 alpha); + +void deco16_set_graphics(UINT8 *gfx0, INT32 len0, UINT8 *gfx1, INT32 len1, UINT8 *gfx2, INT32 len2); +void deco16_set_graphics(INT32 num, UINT8 *gfx, INT32 len, INT32 size /*tile size*/); // individual bank + +void deco16Init(INT32 no_pf34, INT32 split, INT32 full_width); +void deco16Reset(); +void deco16Exit(); + +void deco16Scan(); + +void deco16_pf12_update(); +void deco16_pf34_update(); + +#define DECO16_LAYER_OPAQUE 0x010000 +#define DECO16_LAYER_PRIORITY(x) ((x) & 0xff) +#define DECO16_LAYER_8BITSPERPIXEL 0x100000 +#define DECO16_LAYER_5BITSPERPIXEL 0x200000 +#define DECO16_LAYER_4BITSPERPIXEL 0x000000 // just to clarify +#define DECO16_LAYER_TRANSMASK0 0x000100 +#define DECO16_LAYER_TRANSMASK1 0x000000 + +void deco16_draw_layer(INT32 tmap, UINT16 *dest, INT32 flags); + +void deco16_tile_decode(UINT8 *src, UINT8 *dst, INT32 len, INT32 type); +void deco16_sprite_decode(UINT8 *gfx, INT32 len); + +void deco16_palette_recalculate(UINT32 *palette, UINT8 *pal); + +#define deco16_write_control_word(num, addr, a, d) \ + if ((addr & 0xfffffff0) == a) { \ + deco16_pf_control[num][(addr & 0x0f)/2] = d; \ + return; \ + } + + +#define deco16_read_control_word(num, addr, a) \ + if ((addr & 0xfffffff0) == a) { \ + return deco16_pf_control[num][(addr & 0x0f)/2]; \ + } + + +#define deco16ic_71_read() (0xffff) + +// common sound hardware... + +extern INT32 deco16_soundlatch; + +void deco16SoundReset(); +void deco16SoundInit(UINT8 *rom, UINT8 *ram, INT32 huc_clock, INT32 ym2203, void (ym2151_port)(UINT32,UINT32), double ym2151vol, INT32 msmclk0, double msmvol0, INT32 msmclk1, double msmvol1); +void deco16SoundExit(); +void deco16SoundUpdate(INT16 *buf, INT32 len); + + +// decrypt routines + +void deco56_decrypt_gfx(UINT8 *rom, INT32 len); +void deco74_decrypt_gfx(UINT8 *rom, INT32 len); +void deco56_remap_gfx(UINT8 *rom, INT32 len); + +void deco102_decrypt_cpu(UINT8 *data, UINT8 *ops, INT32 size, INT32 address_xor, INT32 data_select_xor, INT32 opcode_select_xor); + +void deco156_decrypt(UINT8 *src, INT32 len); + +// protection routines + +extern UINT16 *deco16_prot_ram; +extern UINT16 *deco16_prot_inputs; +extern UINT16 *deco16_buffer_ram; +extern INT32 deco16_vblank; + +void deco16_66_prot_w(INT32 offset, UINT16 data, INT32 mask); // mutant fighter +UINT16 deco16_66_prot_r(INT32 offset); + +void deco16_60_prot_w(INT32 offset, UINT16 data, INT32 mask); // edward randy +UINT16 deco16_60_prot_r(INT32 offset); + +UINT16 deco16_104_cninja_prot_r(INT32 offset); // caveman ninja + +UINT16 deco16_146_funkyjet_prot_r(INT32 offset); // funky jet + +void deco16_104_rohga_prot_w(INT32 offset, UINT16 data, INT32 mask); // rohga +UINT16 deco16_104_rohga_prot_r(INT32 offset); + +UINT16 deco16_104_prot_r(INT32 offset); + +void deco16_146_nitroball_prot_w(INT32 offset, UINT16 data, INT32 mask); +UINT16 deco16_146_nitroball_prot_r(INT32 offset); + +void deco16_146_fghthist_prot_w(INT32 offset, UINT32 data, UINT32 mem_mask); +UINT32 deco16_146_fghthist_prot_r(INT32 offset); + diff --git a/src/burn/drivers/misc_post90s/kanekotb.h b/src/burn/drivers/misc_post90s/kanekotb.h new file mode 100644 index 00000000..ca11a31c --- /dev/null +++ b/src/burn/drivers/misc_post90s/kanekotb.h @@ -0,0 +1,3673 @@ +/* + TODO: + - bonkadv_mcu_43: extract data from MCU (dumped eeprom data for now) + - bloodwar: verify all extracted data against real board (WIP) +*/ + +/*************************************************************************** + + TOYBOX MCU data for Bonk's Adventure + +***************************************************************************/ + +// notes based on test programs results, verified on PCB: +// - bonkadv_mcu_4_30 is the only cmd that ouputs an odd (655) number of bytes +// - bonkadv_mcu_4_33: the 32 'zeroed' bytes every 64 bytes are effectively written by the MCU + +// MCU executed command: 4300 0100 - factory settings +// this command is issued whenever the nvram settings are corrupted +// the MCU writes directly to NVRAM +static UINT16 bonkadv_mcu_43[] = { + 0x8BE0,0x8E71,0x0102,0x0102,0x0300,0x010C,0x0202,0x0202, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0030,0x0020,0x4F6B,0x0305,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0082,0x6F82,0x628C,0xB490,0x6CAB +}; + +// MCU executed command: 0400 0E00 0034 - code +/* +200E00: 7071 moveq #$71, D0 +200E02: 7273 moveq #$73, D1 +200E04: 7475 moveq #$75, D2 +200E06: 7677 moveq #$77, D3 +200E08: 7879 moveq #$79, D4 +200E0A: 7A7B moveq #$7b, D5 +200E0C: 7C7D moveq #$7d, D6 +200E0E: 7E7F moveq #$7f, D7 +200E10: 4E75 rts +*/ +static UINT16 bonkadv_mcu_4_34[] = { + 0x7071,0x7273,0x7475,0x7677,0x7879,0x7a7b,0x7c7d,0x7e7f, + 0x4e75 +}; +// MCU executed command: 0400 0180 0032 - 128 bytes at $200180 +static UINT16 bonkadv_mcu_4_32[] = { + 0x00cc,0xcc0c,0xc0c0,0xc080,0x0484,0xb6a6,0x0404,0x80c0, + 0x80b1,0xb1a1,0xa1b2,0xa2b3,0xb3a3,0xa3b1,0xb1b1,0xb1c0, + 0xc0a1,0xa1a1,0xa1b2,0xb2a2,0xa290,0x9090,0xb9b9,0xa9a9, + 0xbaaa,0xbbbb,0xabab,0xb9b9,0xb9b9,0xc8c8,0xa9a9,0xa9a9, + 0xbaba,0xaaaa,0x9898,0x98b9,0xb9a9,0xa9ba,0xaabb,0xbbab, + 0xabb9,0xb9b9,0xb9c8,0xc8a9,0xa9a9,0xa9ba,0xbaaa,0xaa98, + 0x9898,0xb1b1,0xa1a1,0xb2a2,0xb3b3,0xa3a3,0xb1b1,0xb1b1, + 0xc0c0,0xa1a1,0xa1a1,0xb2b2,0xa2a2,0x9090,0x9000,0x0000 +}; +// MCU executed command: 0400 0280 0031 - 112 bytes at $200280 +static UINT16 bonkadv_mcu_4_31[] = { + 0x1013,0x1411,0x1216,0x1519,0x1a17,0x1824,0x2322,0x211f, + 0x201e,0x1d1c,0x1b27,0x2825,0x2629,0x2a2b,0x2e2f,0x2c2d, + 0x3130,0x3435,0x3233,0x3f3e,0x3d3c,0x3a3b,0x3938,0x3736, + 0x4243,0x4041,0x4445,0x4649,0x4a47,0x484c,0x4b4f,0x504d, + 0x4e5a,0x5958,0x5755,0x5654,0x5352,0x515d,0x5e5b,0x5c5f, + 0x6061,0x6465,0x6263,0x6766,0x6a6b,0x6869,0x7574,0x7372, + 0x7071,0x6f6e,0x6d6c,0x7879,0x7677,0x7a7b,0x7c7d,0x7e7f +}; +// MCU executed command: 0400 0E50 0030 - 655 bytes at $200E50 (656 here) +static UINT16 bonkadv_mcu_4_30[] = { + 0x8c00,0x9700,0xa000,0xa700,0xb200,0xb700,0xc000,0xcc00, + 0xd600,0xdf00,0xef00,0xf500,0xfd00,0x0501,0x0b01,0x1801, + 0x1e01,0x2901,0x3101,0x3701,0x4101,0x4901,0x0b01,0x5d01, + 0xa700,0xb200,0x6c01,0x8101,0xb200,0x8101,0x8101,0x8101, + 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101, + 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101, + 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x2e02, + 0x3602,0x3d02,0x4102,0x4f02,0x5502,0x5502,0x5f02,0x6402, + 0x6d02,0x7302,0x7802,0x7d02,0x8302,0x8a02,0x0165,0x712b, + 0x57fe,0x57a2,0xff00,0x0003,0x7c3a,0x436c,0x66ff,0x0000, + 0x026c,0x6d43,0xff00,0x0000,0x74a5,0x8373,0x3599,0x9fff, + + 0x0000,0x074a,0xff00,0x0002,0x8788,0x3331,0x32ff,0x0000, + 0x0276,0x8c71,0x2d8c,0xfe12,0x8cff,0x0000,0x0171,0x0d29, + 0xfe0d,0x29ff,0x0000,0x0559,0x5a5b,0x8a8b,0xff00,0x0003, + 0x0d0e,0x576a,0x641e,0xfe0d,0x0efe,0x64a3,0xff00,0x0006, + 0x0262,0xff00,0x0007,0x3e3f,0x7a7b,0xff00,0x0007,0x7584, + 0x4c53,0xff00,0x0001,0x6645,0xff00,0x0007,0x0d18,0x2984, + 0x5384,0xfe0d,0x29ff,0x0000,0x0457,0x5cff,0x0000,0x0751, + 0x5202,0x45fe,0x4575,0xff00,0x0000,0x191a,0x1b6e,0xff00, + 0x0006,0x3472,0xff00,0x0000,0x6569,0x090f,0x8b23,0xff00, + 0x0004,0x3b3c,0x3d79,0xff00,0x0080,0x770a,0x8176,0x2a65, + 0x64fe,0x7776,0xfe2a,0x76fe,0x650a,0xff00,0x0000,0x1011, + 0x1226,0x2728,0xa655,0x940f,0x68ff,0x0000,0x8045,0x6477, + 0x0a81,0x762a,0x65fe,0x7776,0xfe2a,0x76fe,0x650a,0xff00, + 0x0000,0x166b,0xff00,0x0007,0x1e30,0x39ff,0x0000,0x0345, + 0x3a77,0x7843,0x4647,0xff00,0x0000,0x7335,0x8399,0x9fff, + 0x0000,0x0237,0x38ff,0x0000,0x0044,0x303b,0xff00,0x0000, + + 0x7d7e,0x7fa1,0x0aff,0x0000,0x0070,0xff00,0x0000,0x3e3f, + 0x7a7b,0x6180,0x89a4,0xff00,0x0006,0x86a5,0x4f42,0xff00, + 0x0000,0x1011,0x1255,0x0f68,0xff00,0x0002,0x8788,0x4033, + 0xff00,0x0005,0x650f,0xff00,0x0008,0x9596,0x9ba7,0xff00, + 0x0000,0x4849,0x82ff,0x0000,0x022e,0x2f30,0xff00,0x0001, + 0x7778,0x5826,0x2728,0xa6ff,0x0000,0x0813,0x1402,0x51ff, + 0x0000,0x072e,0x5c5d,0xff00,0x0006,0x57ff,0x0000,0x0230, + 0x391e,0x65fe,0x6530,0xff00,0x0000,0x4bff,0x0000,0x008e, + 0x8f90,0x91ff,0x0000,0x0092,0x9d17,0xff00,0x0000,0xff00, + 0x0000,0x8d9b,0xa77d,0x7e7f,0xa10a,0x9596,0xff00,0x0001, + 0x1993,0xff00,0x0000,0x67ff,0x0000,0x0067,0xff00,0x0000, + 0x27ff,0x0000,0x0390,0x8e23,0x978b,0xff00,0x0000,0x1d9e, + 0xff00,0x0007,0x3bff,0x0000,0x001d,0xff00,0x0000,0x8e90, + 0xff00,0x0005,0x2495,0x96ff,0x0000,0x009a,0xff00,0x0000 +}; +// MCU executed command: 0400 0400 0033 - 2560 bytes at $200400 +static UINT16 bonkadv_mcu_4_33[] = { + 0x00a4,0x0001,0x00a5,0x005a,0x00a6,0x0074,0x00a7,0x009b, + 0x00a8,0x00d0,0x00a9,0x00fe,0x00aa,0x015d,0x00ab,0x01b0, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0001,0x0002,0x0019,0x005b,0x0022,0x0075,0x002d,0x009c, + 0x0041,0x00d1,0x004e,0x00ff,0x0060,0x015f,0x0072,0x01b1, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0002,0x0008,0x001a,0x0061,0x0023,0x007b,0x002e,0x00a2, + 0x0042,0x00d7,0x004f,0x0107,0x0061,0x0165,0x0073,0x01b7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x000a,0x0000,0x0063,0x0000,0x007d,0x0000,0x00a4, + 0x0000,0x00d9,0x0000,0x0109,0x0000,0x0167,0x0000,0x01b9, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0003,0x000b,0x001b,0x0064,0x0024,0x007e,0x002f,0x00a5, + 0x0043,0x00da,0x0050,0x010a,0x0062,0x0168,0x0074,0x01ba, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x000c,0x0000,0x0065,0x0000,0x007f,0x0000,0x00a6, + 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0004,0x0008,0x001c,0x0061,0x0025,0x007b,0x0030,0x00a2, + 0x0044,0x00d7,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0005,0x000d,0x001d,0x0066,0x0025,0x007b,0x0031,0x00a7, + 0x0045,0x00dc,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0000,0x0017,0x0000,0x0069,0x0000,0x0089,0x0000,0x00af, + 0x0000,0x00df,0x0000,0x0115,0x0000,0x0173,0x0000,0x01c5, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0009,0x0015,0x001e,0x0067,0x0029,0x0087,0x0034,0x00ad, + 0x0046,0x00dd,0x0055,0x0113,0x0067,0x0171,0x0079,0x01c3, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0006,0x000e,0x0006,0x000e,0x0026,0x0080,0x0006,0x000e, + 0x0000,0x0000,0x0052,0x010c,0x0064,0x016a,0x0076,0x01bc, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0007,0x0010,0x0007,0x0010,0x0027,0x0082,0x0032,0x00a8, + 0x0000,0x0000,0x0053,0x010e,0x0065,0x016c,0x0077,0x01be, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0000,0x0013,0x0000,0x0013,0x0000,0x0085,0x0000,0x00ab, + 0x0000,0x0000,0x0000,0x0111,0x0000,0x016f,0x0000,0x01c1, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0008,0x0014,0x0008,0x0014,0x0028,0x0086,0x0033,0x00ac, + 0x0000,0x0000,0x0054,0x0112,0x0066,0x0170,0x0078,0x01c2, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0018,0x0000,0x006a,0x0000,0x008a,0x0000,0x00b0, + 0x0000,0x00e0,0x0000,0x0116,0x0000,0x0174,0x0000,0x01c6, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x000c,0x0000,0x0065,0x0000,0x007f,0x0000,0x00a6, + 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x000a,0x0019,0x001f,0x006b,0x002a,0x008b,0x0035,0x00b1, + 0x0047,0x00e1,0x0056,0x0117,0x0068,0x0175,0x007a,0x01c7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x000b,0x0019,0x0020,0x006b,0x002b,0x008b,0x0036,0x00b1, + 0x0048,0x00e1,0x0057,0x0117,0x0069,0x0175,0x007a,0x01c7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0015,0x003e,0x0015,0x003e,0x0099,0x0095,0x0015,0x003e, + 0x0000,0x0000,0x009e,0x013a,0x006d,0x018f,0x007e,0x01dc, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x000c,0x001d,0x000c,0x001d,0x000c,0x001d,0x000c,0x001d, + 0x0049,0x00e5,0x0058,0x011b,0x006a,0x0179,0x007b,0x01c9, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0000,0x001f,0x0000,0x001f,0x0000,0x001f,0x0000,0x001f, + 0x0000,0x00e7,0x0000,0x011d,0x0000,0x017b,0x0000,0x01cb, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x000d,0x0020,0x0021,0x006f,0x002c,0x008f,0x0037,0x00b5, + 0x004a,0x00e8,0x0059,0x011e,0x006b,0x017c,0x007c,0x01cc, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0022,0x0000,0x0071,0x0000,0x0091,0x0000,0x00b7, + 0x0000,0x00ea,0x0000,0x0120,0x0000,0x017e,0x0000,0x01ce, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0014,0x003b,0x0014,0x003b,0x005d,0x0092,0x0014,0x003b, + 0x0014,0x003b,0x009d,0x0137,0x00a0,0x018c,0x00a1,0x01d9, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0012,0x0036,0x0012,0x0036,0x0012,0x0036,0x0012,0x0036, + 0x008a,0x00e5,0x00be,0x013c,0x006c,0x0184,0x007d,0x01d1, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0013,0x0038,0x0013,0x0038,0x0013,0x0038,0x0013,0x0038, + 0x008a,0x00e5,0x00bf,0x013d,0x006c,0x0184,0x007d,0x01d1, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0038,0x00ba,0x0038,0x00ba,0x0038,0x00ba,0x0038,0x00ba, + 0x0038,0x00ba,0x00a2,0x0128,0x006e,0x019c,0x007f,0x01e7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x005c,0x014d,0x005c,0x014d,0x005c,0x014d,0x005c,0x014d, + 0x0000,0x0000,0x009c,0x0124,0x0071,0x01a5,0x0082,0x01f0, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x005b,0x014d,0x005b,0x014d,0x005b,0x014d,0x005b,0x014d, + 0x0000,0x0000,0x009b,0x0124,0x0070,0x01a1,0x0081,0x01ec, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0044,0x0000,0x0044,0x0000,0x0044,0x0000,0x0044, + 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0018,0x0045,0x0018,0x0045,0x0018,0x0045,0x0018,0x0045, + 0x0044,0x00d7,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x008b,0x000e,0x008b,0x000e,0x008c,0x0080,0x008b,0x000e, + 0x0000,0x0000,0x008d,0x010c,0x008e,0x016a,0x008f,0x01bc, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x0090,0x0010,0x0090,0x0010,0x0091,0x0082,0x0092,0x00a8, + 0x0000,0x0000,0x0093,0x010e,0x0094,0x016c,0x0095,0x01be, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0096,0x003e,0x0096,0x003e,0x009a,0x0095,0x0096,0x003e, + 0x0000,0x0000,0x009f,0x013a,0x0097,0x018f,0x0098,0x01dc, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0049,0x0000,0x0069,0x0000,0x0098,0x0000,0x00af, + 0x0000,0x00df,0x0000,0x0145,0x0000,0x0173,0x0000,0x01c5, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x005e,0x0048,0x005f,0x0068,0x006f,0x0097,0x0080,0x00ae, + 0x00ac,0x00de,0x00ad,0x0144,0x00ae,0x0172,0x00af,0x01c4, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + + 0x004b,0x00ed,0x004b,0x00ed,0x004b,0x00ed,0x004b,0x00ed, + 0x004b,0x00ed,0x00b0,0x012b,0x00b6,0x0186,0x00ba,0x01d3, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0087,0x00f2,0x0087,0x00f2,0x0087,0x00f2,0x0087,0x00f2, + 0x0087,0x00f2,0x00b3,0x0130,0x00b8,0x018b,0x00bc,0x01d8, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x00c1,0x0050,0x00c1,0x0050,0x00c1,0x0050,0x00c1,0x0050, + 0x00c1,0x0050,0x00c3,0x0148,0x00c5,0x019a,0x00c7,0x01e5, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x00c2,0x0050,0x00c2,0x0050,0x00c2,0x0050,0x00c2,0x0050, + 0x00c2,0x0050,0x00c4,0x0148,0x00c6,0x019a,0x00c8,0x01e5, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +}; +// dynamic, per-level (29), in level order +// PC=078896 : MCU executed command: 0400 0300 00xx - xx = subcmd +static UINT16 bonkadv_mcu_4_00[] = { 0x0000,0x04C0,0x0000,0x0100,0x0600,0x0100 }; +static UINT16 bonkadv_mcu_4_02[] = { 0x0000,0x0760,0x0000,0x0100,0x0270,0x0100,0x0320,0x01B0, + 0x0460,0x01B0,0x0510,0x0100,0x05E0,0x0100,0x0620,0x0120, + 0x08A0,0x0120 }; +static UINT16 bonkadv_mcu_4_01[] = { 0x0000,0x0670,0x0000,0x0100,0x0200,0x0100,0x02E0,0x0090, + 0x0400,0x0090,0x04E0,0x0100,0x07B0,0x0100 }; +static UINT16 bonkadv_mcu_4_05[] = { 0x0000,0x0610,0x0000,0x0100,0x0750,0x0100 }; +static UINT16 bonkadv_mcu_4_07[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 }; +static UINT16 bonkadv_mcu_4_06[] = { 0x0000,0x05F0,0x0000,0x0100,0x0730,0x0100 }; +static UINT16 bonkadv_mcu_4_09[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_0D[] = { 0x0000,0x07A0,0x0000,0x0100,0x08E0,0x0100 }; +static UINT16 bonkadv_mcu_4_03[] = { 0x0000,0x0920,0x0000,0x0100,0x0A60,0x0100 }; +static UINT16 bonkadv_mcu_4_08[] = { 0x0000,0x0730,0x0000,0x0100,0x0870,0x0100 }; +static UINT16 bonkadv_mcu_4_04[] = { 0x0000,0x05C0,0x0000,0x0100,0x0200,0x0100,0x0280,0x00C0, + 0x02E0,0x0060,0x03A0,0x0000,0x0700,0x0000 }; +static UINT16 bonkadv_mcu_4_0C[] = { 0x0000,0x06E0,0x0000,0x0100,0x0820,0x0100 }; +static UINT16 bonkadv_mcu_4_0A[] = { 0x0000,0x05A0,0x0000,0x0100,0x06E0,0x0100 }; +static UINT16 bonkadv_mcu_4_0B[] = { 0x0000,0x0470,0x0000,0x0100,0x05B0,0x0100 }; +static UINT16 bonkadv_mcu_4_10[] = { 0x0000,0x06C0,0x0000,0x0100,0x03B0,0x0100,0x0460,0x0050, + 0x05E0,0x0050,0x0650,0xFFE0,0x0800,0xFFE0 }; +static UINT16 bonkadv_mcu_4_0E[] = { 0x0000,0x0630,0x0000,0x0100,0x0770,0x0100 }; +static UINT16 bonkadv_mcu_4_13[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_0F[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_11[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_14[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_12[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 }; +static UINT16 bonkadv_mcu_4_17[] = { 0x0000,0x0520,0x0000,0x0100,0x0660,0x0100 }; +static UINT16 bonkadv_mcu_4_1A[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 }; +static UINT16 bonkadv_mcu_4_15[] = { 0x0000,0x02C0,0x0000,0x0100,0x0400,0x0100 }; +static UINT16 bonkadv_mcu_4_18[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 }; +static UINT16 bonkadv_mcu_4_16[] = { 0x0000,0x02F0,0x0000,0x0100,0x0430,0x0100 }; +static UINT16 bonkadv_mcu_4_19[] = { 0x0000,0x03A0,0x0000,0x0100,0x04E0,0x0100 }; +static UINT16 bonkadv_mcu_4_1B[] = { 0x0000,0x0460,0x0000,0x0100,0x05A0,0x0100 }; +static UINT16 bonkadv_mcu_4_1C[] = { 0x0000,0x02C0,0x0000,0x0100,0x0400,0x0100 }; + + +/*************************************************************************** + + TOYBOX MCU data for Blood Warrior + +***************************************************************************/ + +// bloodwar MCU writes by 16-bytes block, and data seems to be contiguous? +// unknown data: the last 4 words of a cmd are the 4 firsts of the next one +// palette data: when the negative word is not on a 16-bytes boundary, +// it is followed by the first bytes of the next palette +// unknown data are followed by tilemap (last tilemap ends with 0xff) +// palette (last ends with: 0x0004,0xce4a,0x0004 ???) +// fighter: order is unclear - cmd 26 is probably the last (ends with 0xff) + +// --- unknown data --- +static UINT16 bloodwar_mcu_4_01[] = { 0x00E6,0x00C6,0x00E8,0x00D0,0xFC9A,0x05C0,0x0F00,0x08C0, // Warrior 1 + 0x0001,0x0120,0x0090,0x021B,0x00B4,0x0094,0x00AC,0x0094 }; +static UINT16 bloodwar_mcu_4_02[] = { 0x00B4,0x0094,0x00AC,0x0094,0xFCD2,0x03C0,0x1000,0x0900, // Warrior 2 + 0x0001,0x0100,0x0080,0x0118,0x00F0,0x00D0,0x00F4,0x00DC }; +static UINT16 bloodwar_mcu_4_03[] = { 0x00F0,0x00D0,0x00F4,0x00DC,0xFC90,0x03C0,0x0C00,0x0CC0, // Warrior 3 + 0x0001,0x0200,0x0100,0x0930,0x00D2,0x00B2,0x00CA,0x00B0 }; +static UINT16 bloodwar_mcu_4_04[] = { 0x00D2,0x00B2,0x00CA,0x00B0,0xFCB5,0x05C0,0x1000,0x0C00, // Warrior 4 + 0x0001,0x0140,0x00A0,0x031E,0x00A0,0x0080,0x00DC,0x00C4 }; +static UINT16 bloodwar_mcu_4_05[] = { 0x00A0,0x0080,0x00DC,0x00C4,0xFCA2,0x05C0,0x0AC0,0x0880, // Warrior 5 + 0x0001,0x01A0,0x00D0,0x0627,0x00BE,0x009E,0x00C2,0x00A8 }; +static UINT16 bloodwar_mcu_4_06[] = { 0x00BE,0x009E,0x00C2,0x00A8,0xFCBF,0x04C0,0x1100,0x0C00, // Warrior 6 + 0x0001,0x0180,0x00C0,0x0524,0x00C8,0x00A8,0x00D6,0x009C }; +static UINT16 bloodwar_mcu_4_07[] = { 0x00C8,0x00A8,0x00D6,0x009C,0xFCC8,0x05C0,0x0F40,0x0CC0, // Warrior 7 + 0x0001,0x0160,0x00B0,0x0421,0x00AA,0x008A,0x00A0,0x0086 }; +static UINT16 bloodwar_mcu_4_08[] = { 0x00AA,0x008A,0x00A0,0x0086,0xFCDB,0x05C0,0x1380,0x0F80, // Warrior 8 + 0x0000,0x01E0,0x00F0,0x082D,0x00DC,0x00BC,0x00D6,0x00BC }; +static UINT16 bloodwar_mcu_4_09[] = { 0x00DC,0x00BC,0x00D6,0x00BC,0xFCAC,0x04C0,0x10C0,0x1000, // Warrior 9 + 0x0001,0x01C0,0x00E0,0x072A,0xFF08,0xFF02,0x0000,0xFF03 }; + +// --- palette data --- +// number of palettes (>=1) +// palette data follows (each palette is 0x200 bytes long) +// a negative word will end the palette +static UINT16 bloodwar_mcu_4_0a[] = { // Warrior 1 Player 1 + 0x000B,0x0000,0x4232,0x56F8,0x2D8D,0x27FF,0x3BFF,0x53FF, + 0x63FF,0x381F,0x4C1F,0x581F,0x6C1F,0x7C1F,0x7E1F,0x7EBF, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x294A,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x381F,0x4C1F,0x581F,0x6C1E,0x781E,0x7E1F,0x7EBF, + + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0360,0x13E0,0x2BE0,0x3BE9,0x4FEE,0x5FF3,0x6FF8, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x4191,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x2AC0,0x3700,0x47A0,0x5BC0,0x6FE4,0x7BEF,0x7FFB, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x021C,0x0ABE,0x171E,0x275F,0x379F,0x4FBF,0x67BF, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F, + 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F, + 0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,0x4FC0,0x57C0, + 0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,0x7FFA,0x7FFC, + 0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,0x0340, + 0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,0x1DA3, + 0x2243,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407, + 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D, + 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + + 0x7E9F,0x7BDE,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4, + 0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,0x7FFA, + 0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320, + 0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0, + 0x1DA3,0x2243,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,0x12B9, + 0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,0x639F, + 0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x0011,0x0016,0x001A, + 0x1C1D,0x281E,0x341D,0x401E,0x501E,0x581E,0x641E,0x6C1F, + 0x785F,0x7E5F,0x7F3F,0x7BDE,0xFFFF,0x4191,0x2000,0x2800, + 0x3000,0x3400,0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821, + 0x7084,0x7D29,0x7E52,0x7F39,0x7BDE,0xFFFF,0x4191,0x1320, + 0x2340,0x2B60,0x3380,0x3FA0,0x47A0,0x4FC1,0x5BC0,0x67E2, + 0x6FE4,0x77E6,0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x000B +}; +static UINT16 bloodwar_mcu_4_0b[] = { // Warrior 1 Player 2 + 0x000B,0x292A,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x2E2A,0x29E9,0x2609,0x29E9,0x2629,0x2A4A,0x2A4B, + 0x260A,0x25E8,0x25C8,0x1965,0x21A8,0x21A7,0x25E8,0x1DA7, + 0x21A8,0x21A8,0x2186,0x1D86,0x1524,0x2187,0x2146,0x1925, + 0x1504,0x1924,0x18E5,0x0CE2,0x10E2,0x1926,0x10C3,0x14E3, + 0x1082,0x10A0,0x0C40,0x0C60,0x1080,0x14A1,0x18C2,0x1925, + 0x1924,0x0CC3,0x2146,0x0CA2,0x1D25,0x10C0,0x1104,0x1905, + 0x18C4,0x1523,0x1D45,0x1101,0x1D62,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x25A9,0x1906,0x1D67,0x1125, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29C9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x7F88,0x7F88,0x7EA9,0x7B73,0x7E68,0x72CB,0x66CB, + 0x772A,0x6348,0x52A8,0x6F4E,0x66EC,0x5669,0x6B2A,0x5288, + 0x4585,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x62C7,0x62E7,0x4ACC,0x532D, + 0x4B0D,0x294A,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x381F,0x4C1F,0x581F,0x6C1E,0x781E,0x7E1F,0x7EBF, + + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x0360,0x13E0,0x2BE0,0x3BE9,0x4FEE,0x5FF3,0x6FF8, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x4191,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x2AC0,0x3700,0x47A0,0x5BC0,0x6FE4,0x7BEF,0x7FFB, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, + 0x0002,0x021C,0x0ABE,0x171E,0x275F,0x379F,0x4FBF,0x67BF, + 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0, + 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C, + 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509, + 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8, + 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927, + 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509, + + 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945, + 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7, + 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A, + 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F, + 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E, + 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B, + 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3, + 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66, + 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123, + 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523, + 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9, + 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753, + 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226, + 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9, + 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA, + 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC, + + 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD, + 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5, + 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B, + 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8, + 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB, + 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D, + 0x4B0D,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F, + 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F, + 0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,0x4FC0,0x57C0, + 0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,0x7FFA,0x7FFC, + 0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,0x0340, + 0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,0x1DA3, + 0x2243,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407, + 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D, + 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + + 0x7E9F,0x7BDE,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4, + 0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,0x7FFA, + 0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320, + 0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0, + 0x1DA3,0x2243,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,0x12B9, + 0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,0x639F, + 0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x0011,0x0016,0x001A, + 0x1C1D,0x281E,0x341D,0x401E,0x501E,0x581E,0x641E,0x6C1F, + 0x785F,0x7E5F,0x7F3F,0x7BDE,0xFFFF,0x4191,0x2000,0x2800, + 0x3000,0x3400,0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821, + 0x7084,0x7D29,0x7E52,0x7F39,0x7BDE,0xFFFF,0x4191,0x1320, + 0x2340,0x2B60,0x3380,0x3FA0,0x47A0,0x4FC1,0x5BC0,0x67E2, + 0x6FE4,0x77E6,0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0004 +}; +static UINT16 bloodwar_mcu_4_0c[] = { // Warrior 5 Player 1 + 0x0004,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x1422,0x1423,0x2044,0x1803,0x1C23,0x2CA6,0x2445, + 0x2446,0x38CA,0x2C87,0x38EA,0x30A8,0x34A9,0x2C88,0x2887, + 0x2866,0x1824,0x3089,0x28A7,0x2466,0x2867,0x30C9,0x34E9, + 0x59F0,0x59D0,0x6212,0x6654,0x6211,0x5DF0,0x59CE,0x558D, + 0x518F,0x4D2F,0x492E,0x34AB,0x4D4E,0x55B1,0x40EB,0x5591, + 0x40CB,0x59B1,0x5590,0x450D,0x2865,0x5170,0x3D0D,0x2045, + 0x2046,0x51D0,0x4D8D,0x2885,0x30C8,0x3CEA,0x3CEB,0x38C9, + 0x3087,0x3088,0x2465,0x2064,0x1C43,0x1822,0x494E,0x412C, + 0x452D,0x51AC,0x5E0F,0x6653,0x6A53,0x496B,0x55CF,0x34AA, + 0x38A9,0x3CEB,0x3489,0x2006,0x1C05,0x308A,0x450F,0x40EE, + 0x40CD,0x38AC,0x2C48,0x2C89,0x496E,0x55D0,0x59B2,0x55D2, + 0x492E,0x5970,0x5991,0x61D3,0x5DB2,0x44EB,0x55B0,0x494B, + 0x5171,0x5570,0x5571,0x5191,0x38EB,0x34AA,0x2846,0x4D8E, + 0x2CA7,0x2464,0x410C,0x3CCB,0x38CC,0x410B,0x3CEC,0x30CA, + + 0x408B,0x20A7,0x452C,0x51AF,0x454C,0x24A3,0x494C,0x518E, + 0x61F1,0x55AE,0x5DF2,0x5A0E,0x55ED,0x6271,0x38AA,0x30A6, + 0x2887,0x2A40,0x53A0,0x63E1,0x6FE5,0x6FE5,0x5BC2,0x5FC4, + 0x5FC3,0x67C4,0x6FC8,0x73C6,0x6BE6,0x29E0,0x2E00,0x2E00, + 0x3E82,0x5B47,0x1DA0,0x3EC0,0x3681,0x3680,0x4B03,0x5364, + 0x2A00,0x5384,0x5787,0x5B26,0x5FC4,0x5FE2,0x5BE2,0x3F00, + 0x4320,0x3AC0,0x2E40,0x2A20,0x4760,0x4300,0x4B41,0x3240, + 0x3220,0x3A61,0x3260,0x3280,0x2A60,0x32A0,0x2E00,0x3AA0, + 0x4722,0x3AA0,0x31C0,0x3200,0x3220,0x3620,0x3200,0x5385, + 0x67E7,0x5784,0x6388,0x6368,0x73AA,0x73CB,0x3A82,0x73C5, + 0x6BE7,0x1943,0x1542,0x08A1,0x0CE3,0x0CE1,0x1962,0x2164, + 0x29E5,0x25A3,0x25C4,0x2E25,0x3226,0x3227,0x1963,0x21A4, + 0x2DE8,0x1D84,0x25A5,0x1122,0x0460,0x0CE2,0x1543,0x1DA3, + 0x1DA4,0x25E5,0x25C5,0x2DE7,0x29C6,0x2E07,0x3A49,0x42CB, + 0x4F0C,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F, + 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F, + + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x001F,0x0FE0,0x1BE0, + 0x27E0,0x37E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x7FF5, + 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F, + 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92, + 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4, + 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6, + 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB, + 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539, + 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F, + 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F, + 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF, + 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF, + 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F, + 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x79BF, + + 0x79FF,0x7A1F,0x7A5F,0x7A7F,0x7ABF,0x7B5F,0x7B7F,0x7DDF, + 0x7E1F,0x7E5F,0x7F1F,0x7F7F,0x7D7F,0x7E1F,0x7E5F,0x7EBF, + 0x7EFF,0x7F5F,0x7FBF,0x7FDF,0x7E3F,0x7E5F,0x7E7F,0x7E9F, + 0x7EBF,0x7EDF,0x7EFF,0x7F1F,0x7F3F,0x7F5F,0x7F7F,0x7FBF, + 0x7FFF,0x0000,0xFFFF,0x3C48,0x7FE0,0x7C1F,0x7C00,0x001F, + 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7DFF,0x7E9F,0x7BDE,0x7FE0,0x0445,0x08C5,0x04E5,0x0505, + 0x0525,0x0545,0x0565,0x0945,0x0965,0x0966,0x0986,0x09A6, + 0x198C,0x19AA,0x1D66,0x7FE0,0x1D82,0x1DA2,0x1DC2,0x218C, + 0x21AC,0x21C2,0x258D,0x25AC,0x29AD,0x29AE,0x29AF,0x29CF, + 0x29E2,0x2D91,0x2DB0,0x7FE0,0x2DF0,0x31D0,0x31D1,0x31D2, + 0x31F1,0x31F2,0x3592,0x35D1,0x35D2,0x35F2,0x35F3,0x3A33, + 0x3DF3,0x3DF4,0x3DF5,0x7FE0,0x3E14,0x3E15,0x3E33,0x3E34, + 0x3F62,0x41D3,0x41F5,0x4215,0x4216,0x4234,0x4235,0x4236, + 0x4382,0x4616,0x4617,0x7FE0,0x4636,0x4637,0x4639,0x4656, + 0x4657,0x4676,0x4A17,0x4A19,0x4A37,0x4A39,0x4E77,0x4E78, + + 0x4FAD,0x5259,0x525A,0x7FE0,0x5279,0x527A,0x5299,0x5299, + 0x529A,0x53EC,0x53EE,0x5699,0x569A,0x56B9,0x56BA,0x56BC, + 0x5A9C,0x5ABA,0x5ABC,0x7FE0,0x5BF1,0x5EFB,0x5EFC,0x62BD, + 0x62FD,0x62FE,0x631D,0x66FD,0x671D,0x671E,0x673D,0x67B2, + 0x67D4,0x6B3E,0x6B3F,0x7FE0,0x6F7F,0x737F,0x739E,0x739F, + 0x73FD,0x77BF,0x77F9,0x7BBE,0x7BDD,0x7BFC,0x7FFA,0x7FFB, + 0x7FFC,0x7FFD,0x7FFF,0x7FE0,0x1D6C,0x2DD0,0x3E13,0x4635, + 0x5278,0x5ABD,0x6F7F,0x3C48,0x3C48,0x3C48,0x3C48,0x3C48, + 0x3C48,0x3C48,0x3C48,0x3971,0x0842,0x15C6,0x2666,0x1E8C, + 0x270A,0x32F1,0x2EAB,0x3BCF,0x3BD2,0x4BEE,0x53F6,0x5B94, + 0x6BB5,0x6FFB,0x7BDE,0xFFFF,0x0004,0x0000,0x4232,0x56F8 +}; +static UINT16 bloodwar_mcu_4_0d[] = { // Warrior 5 Player 2 + 0x0004,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x0C29,0x0C2A,0x184B,0x100A,0x142A,0x24AD,0x1C4C, + 0x1C4D,0x30D1,0x248E,0x30F1,0x28AF,0x2CB0,0x248F,0x208E, + 0x206D,0x102B,0x2890,0x20AE,0x1C6D,0x206E,0x28D0,0x2CF0, + 0x51F7,0x51D7,0x5A19,0x5E5B,0x5A18,0x55F7,0x51D5,0x4D94, + 0x4996,0x4536,0x4135,0x2CB2,0x4555,0x4DB8,0x38F2,0x4D98, + 0x38D2,0x51B8,0x4D97,0x3D14,0x206C,0x4977,0x3514,0x184C, + 0x184D,0x49D7,0x4594,0x208C,0x28CF,0x34F1,0x34F2,0x30D0, + 0x288E,0x288F,0x1C6C,0x186B,0x144A,0x1029,0x4155,0x3933, + 0x3D34,0x49B3,0x5616,0x5E5A,0x625A,0x4172,0x4DD6,0x2CB1, + 0x30B0,0x34F2,0x2C90,0x180D,0x140C,0x2891,0x3D16,0x38F5, + 0x38D4,0x30B3,0x244F,0x2490,0x4174,0x4DD7,0x51B9,0x4DD9, + 0x4135,0x5177,0x5198,0x59DA,0x55B9,0x3CF2,0x4DB7,0x4152, + 0x4978,0x4D77,0x4D78,0x4998,0x30F2,0x2CB1,0x204D,0x4595, + 0x24AE,0x1C6B,0x3913,0x34D2,0x30D3,0x3912,0x34F3,0x28D1, + + 0x3892,0x18AE,0x3D33,0x49B6,0x3D53,0x1CAA,0x4153,0x4995, + 0x59F8,0x4DB5,0x55F9,0x5215,0x4DF4,0x5A78,0x30B1,0x28AD, + 0x208E,0x2A40,0x53A0,0x63E1,0x6FE5,0x6FE5,0x5BC2,0x5FC4, + 0x5FC3,0x67C4,0x6FC8,0x73C6,0x6BE6,0x29E0,0x2E00,0x2E00, + 0x3E82,0x5B47,0x1DA0,0x3EC0,0x3681,0x3680,0x4B03,0x5364, + 0x2A00,0x5384,0x5787,0x5B26,0x5FC4,0x5FE2,0x5BE2,0x3F00, + 0x4320,0x3AC0,0x2E40,0x2A20,0x4760,0x4300,0x4B41,0x3240, + 0x3220,0x3A61,0x3260,0x3280,0x2A60,0x32A0,0x2E00,0x3AA0, + 0x4722,0x3AA0,0x31C0,0x3200,0x3220,0x3620,0x3200,0x5385, + 0x67E7,0x5784,0x6388,0x6368,0x73AA,0x73CB,0x3A82,0x73C5, + 0x6BE7,0x1943,0x1542,0x08A1,0x0CE3,0x0CE1,0x1962,0x2164, + 0x29E5,0x25A3,0x25C4,0x2E25,0x3226,0x3227,0x1963,0x21A4, + 0x2DE8,0x1D84,0x25A5,0x1122,0x0460,0x0CE2,0x1543,0x1DA3, + 0x1DA4,0x25E5,0x25C5,0x2DE7,0x29C6,0x2E07,0x3A49,0x42CB, + 0x4F0C,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F, + 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F, + + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x001F,0x0FE0,0x1BE0, + 0x27E0,0x37E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x7FF5, + 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F, + 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92, + 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4, + 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6, + 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB, + 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539, + 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F, + 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F, + 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF, + 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF, + 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F, + 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x79BF, + + 0x79FF,0x7A1F,0x7A5F,0x7A7F,0x7ABF,0x7B5F,0x7B7F,0x7DDF, + 0x7E1F,0x7E5F,0x7F1F,0x7F7F,0x7D7F,0x7E1F,0x7E5F,0x7EBF, + 0x7EFF,0x7F5F,0x7FBF,0x7FDF,0x7E3F,0x7E5F,0x7E7F,0x7E9F, + 0x7EBF,0x7EDF,0x7EFF,0x7F1F,0x7F3F,0x7F5F,0x7F7F,0x7FBF, + 0x7FFF,0x0000,0xFFFF,0x3C48,0x7FE0,0x7C1F,0x7C00,0x001F, + 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7DFF,0x7E9F,0x7BDE,0x7FE0,0x0445,0x08C5,0x04E5,0x0505, + 0x0525,0x0545,0x0565,0x0945,0x0965,0x0966,0x0986,0x09A6, + 0x198C,0x19AA,0x1D66,0x7FE0,0x1D82,0x1DA2,0x1DC2,0x218C, + 0x21AC,0x21C2,0x258D,0x25AC,0x29AD,0x29AE,0x29AF,0x29CF, + 0x29E2,0x2D91,0x2DB0,0x7FE0,0x2DF0,0x31D0,0x31D1,0x31D2, + 0x31F1,0x31F2,0x3592,0x35D1,0x35D2,0x35F2,0x35F3,0x3A33, + 0x3DF3,0x3DF4,0x3DF5,0x7FE0,0x3E14,0x3E15,0x3E33,0x3E34, + 0x3F62,0x41D3,0x41F5,0x4215,0x4216,0x4234,0x4235,0x4236, + 0x4382,0x4616,0x4617,0x7FE0,0x4636,0x4637,0x4639,0x4656, + 0x4657,0x4676,0x4A17,0x4A19,0x4A37,0x4A39,0x4E77,0x4E78, + + 0x4FAD,0x5259,0x525A,0x7FE0,0x5279,0x527A,0x5299,0x5299, + 0x529A,0x53EC,0x53EE,0x5699,0x569A,0x56B9,0x56BA,0x56BC, + 0x5A9C,0x5ABA,0x5ABC,0x7FE0,0x5BF1,0x5EFB,0x5EFC,0x62BD, + 0x62FD,0x62FE,0x631D,0x66FD,0x671D,0x671E,0x673D,0x67B2, + 0x67D4,0x6B3E,0x6B3F,0x7FE0,0x6F7F,0x737F,0x739E,0x739F, + 0x73FD,0x77BF,0x77F9,0x7BBE,0x7BDD,0x7BFC,0x7FFA,0x7FFB, + 0x7FFC,0x7FFD,0x7FFF,0x7FE0,0x1D6C,0x2DD0,0x3E13,0x4635, + 0x5278,0x5ABD,0x6F7F,0x3C48,0x3C48,0x3C48,0x3C48,0x3C48, + 0x3C48,0x3C48,0x3C48,0x3971,0x0842,0x15C6,0x2666,0x1E8C, + 0x270A,0x32F1,0x2EAB,0x3BCF,0x3BD2,0x4BEE,0x53F6,0x5B94, + 0x6BB5,0x6FFB,0x7BDE,0xFFFF,0x0005,0x40CE,0x4232,0x56F8 +}; +static UINT16 bloodwar_mcu_4_0e[] = { // Warrior 4 Player 2 + 0x0005,0x40CE,0x4232,0x56F8,0x2D8D,0x1D08,0x254A,0x2D8C, + 0x35CE,0x3E10,0x4652,0x4E94,0x56D6,0x5F18,0x675A,0x6F9C, + 0x7BDE,0x7BF9,0x6FF5,0x6BD4,0x63F1,0x538D,0x63F2,0x57EE, + 0x57EF,0x53EE,0x57CE,0x36E7,0x4FCD,0x4FEC,0x4FCA,0x2F06, + 0x1A63,0x3B29,0x1201,0x1622,0x0DC1,0x3F4A,0x3707,0x1A42, + 0x1221,0x3307,0x2EC6,0x0DE1,0x1E63,0x434B,0x53AC,0x67F0, + 0x1E24,0x3EE9,0x472B,0x4B4C,0x6BF3,0x6FF5,0x73F6,0x73F6, + 0x73F6,0x73F5,0x6FF5,0x5FF0,0x5FF1,0x476A,0x19A1,0x1161, + 0x19E1,0x2AC5,0x32C7,0x32E6,0x3F6A,0x3B28,0x2665,0x0941, + 0x3289,0x47CB,0x4BEB,0x4389,0x1A44,0x2285,0x2AA6,0x2284, + 0x1A23,0x7FFF,0x7FFE,0x7FFD,0x7FFD,0x77F9,0x5370,0x5392, + 0x4B2F,0x5792,0x5BB3,0x4F31,0x7FFD,0x7FFC,0x73D8,0x4F11, + 0x46F0,0x3E8E,0x322B,0x4EF1,0x4ED3,0x5332,0x5773,0x46AF, + 0x428F,0x266F,0x3AB0,0x364C,0x29E9,0x2A6D,0x2DEA,0x29C9, + 0x25C9,0x25C8,0x2E4B,0x1144,0x0D64,0x21A7,0x3B0B,0x2207, + 0x478E,0x4FB0,0x4B8F,0x53D2,0x6FF6,0x7FFA,0x6FF8,0x5FF4, + + 0x36CC,0x536F,0x474D,0x3AEC,0x2A49,0x1DE5,0x2627,0x2E88, + 0x2E89,0x1E05,0x1184,0x0D24,0x15A6,0x1104,0x0D23,0x08E2, + 0x08E1,0x6BFF,0x577D,0x42D8,0x3697,0x3677,0x3256,0x3A98, + 0x3EBA,0x3EB9,0x3AB8,0x3654,0x2E55,0x2A13,0x3274,0x2610, + 0x21F1,0x2A91,0x0545,0x0946,0x2631,0x2A4F,0x2231,0x21AE, + 0x0566,0x15C8,0x29ED,0x25EC,0x222A,0x2EB0,0x36B4,0x3A94, + 0x1E11,0x7FFF,0x77F9,0x3ACA,0x3288,0x2A66,0x4B4E,0x3EEB, + 0x0900,0x2606,0x1563,0x0940,0x1142,0x1E43,0x430C,0x430B, + 0x3F0A,0x5FF3,0x53B0,0x3689,0x1DE3,0x2E67,0x15A2,0x5791, + 0x15A2,0x2E68,0x15A2,0x4F6E,0x2A47,0x4B2E,0x2607,0x2E47, + 0x3A8A,0x5390,0x3688,0x7BF8,0x77FB,0x5FD5,0x5BD4,0x73F7, + 0x77F9,0x3F0A,0x4F4F,0x2608,0x6FF7,0x5FF4,0x5FF1,0x5BB1, + 0x3EEA,0x4F6E,0x3EEC,0x1583,0x4B2D,0x57B1,0x2605,0x25C5, + 0x536F,0x73FA,0x6FF9,0x328A,0x3ECD,0x470D,0x5792,0x474E, + 0x5371,0x4191,0x3C00,0x4000,0x4400,0x4800,0x4C21,0x5063, + 0x5484,0x5CA5,0x64C6,0x7063,0x78A5,0x7DCE,0x7E94,0x7F39, + + 0x7BDE,0xFFFF,0x41D3,0x0300,0x0340,0x0362,0x03A2,0x03C9, + 0x1FCC,0x27EE,0x37F0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF, + 0x6FFF,0x7FFF,0xFFFF,0x4191,0x0019,0x001B,0x001C,0x18DD, + 0x295D,0x319F,0x39DF,0x421F,0x4A5F,0x529F,0x5ADF,0x631F, + 0x6B5F,0x739F,0x7BDE,0xFFFF,0x4191,0x2EE0,0x3300,0x3B20, + 0x4340,0x4760,0x4F80,0x57A1,0x5BC0,0x67E2,0x6FE4,0x77E6, + 0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0005,0x40CE,0x4232 +}; +static UINT16 bloodwar_mcu_4_0f[] = { // Warrior 4 Player 1 + 0x0005,0x40CE,0x4232,0x56F8,0x2D8D,0x20E9,0x292B,0x316D, + 0x39AF,0x41F1,0x4A33,0x5275,0x5AB7,0x62F9,0x6B3B,0x737D, + 0x7BDF,0x7FFA,0x73F6,0x6FF5,0x67F2,0x57CE,0x67F3,0x5BEF, + 0x5BF0,0x57EF,0x5BEF,0x3B08,0x53EE,0x53ED,0x53EB,0x3327, + 0x1E84,0x3B29,0x1201,0x1622,0x0DC1,0x3F4A,0x3707,0x1A42, + 0x1221,0x3307,0x2EC6,0x0DE1,0x1E63,0x434B,0x53AC,0x67F0, + 0x1E24,0x3EE9,0x472B,0x4B4C,0x6BF3,0x6FF5,0x6FF6,0x73F7, + 0x73F6,0x73F7,0x6FF5,0x5FF0,0x5FF1,0x476A,0x19A1,0x1161, + 0x19E1,0x2AC5,0x32C7,0x32E6,0x3F6A,0x3B28,0x2665,0x0941, + 0x3289,0x47CB,0x4BEB,0x4389,0x1A44,0x2285,0x2AA6,0x2284, + 0x1A23,0x7FFF,0x7FFE,0x7FFD,0x7FFC,0x77F9,0x5370,0x5392, + 0x4B2F,0x5792,0x5BB3,0x4F31,0x7FFC,0x7FFB,0x73F8,0x4F11, + 0x46F0,0x3ECE,0x3289,0x4EF1,0x4F32,0x5332,0x5773,0x46AF, + 0x428F,0x1EC8,0x3309,0x368A,0x2A27,0x22C8,0x2E28,0x2A07, + 0x2607,0x25E6,0x2E69,0x1162,0x0D82,0x21C5,0x3B0B,0x2225, + 0x478E,0x4FB0,0x4B8F,0x53D2,0x6FF6,0x7FFA,0x6FF8,0x5FF4, + + 0x36CC,0x538F,0x476D,0x3B0C,0x2A69,0x1E05,0x2647,0x2EA8, + 0x2EA9,0x1E25,0x11C3,0x0D63,0x15E5,0x1143,0x0D62,0x0921, + 0x0920,0x63F8,0x4FF2,0x3B8D,0x2F4C,0x2F2C,0x2B0B,0x334D, + 0x376F,0x376E,0x336D,0x2F09,0x270A,0x22C8,0x2B28,0x1EC5, + 0x1AA6,0x2327,0x05E1,0x05E1,0x1EC5,0x22E5,0x1AC5,0x1A44, + 0x0601,0x0E61,0x2283,0x1E82,0x1A81,0x2B46,0x2F49,0x332A, + 0x16A6,0x7FFF,0x77F9,0x3ACA,0x3288,0x2A66,0x4B4E,0x3EEB, + 0x0900,0x2606,0x1563,0x0940,0x1142,0x1E43,0x430C,0x430B, + 0x3F0A,0x5FF3,0x53B0,0x3689,0x1DE3,0x2E67,0x15A2,0x5791, + 0x15A2,0x2E68,0x15A2,0x4F6E,0x2A47,0x4B2E,0x2607,0x2E47, + 0x3A8A,0x5390,0x3688,0x7BF8,0x77FB,0x5FD5,0x5BD4,0x73F7, + 0x77F9,0x3F0A,0x4F4F,0x2608,0x6FF7,0x5FF4,0x5FF1,0x5BB1, + 0x3EEA,0x4B4D,0x3ACB,0x1162,0x470C,0x5390,0x21E4,0x21A4, + 0x4F4E,0x6FF9,0x6BF8,0x2E69,0x3AAC,0x42EC,0x5371,0x432D, + 0x4F50,0x4191,0x3C00,0x4000,0x4400,0x4800,0x4C21,0x5063, + 0x5484,0x5CA5,0x64C6,0x7063,0x78A5,0x7DCE,0x7E94,0x7F39, + + 0x7BDE,0xFFFF,0x41D3,0x0300,0x0340,0x0362,0x03A2,0x03C9, + 0x1FCC,0x27EE,0x37F0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF, + 0x6FFF,0x7FFF,0xFFFF,0x4191,0x0019,0x001B,0x001C,0x18DD, + 0x295D,0x319F,0x39DF,0x421F,0x4A5F,0x529F,0x5ADF,0x631F, + 0x6B5F,0x739F,0x7BDE,0xFFFF,0x4191,0x2EE0,0x3300,0x3B20, + 0x4340,0x4760,0x4F80,0x57A1,0x5BC0,0x67E2,0x6FE4,0x77E6, + 0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0009,0x0000,0x4232 +}; +static UINT16 bloodwar_mcu_4_10[] = { // Warrior 6 Player 1 + 0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x27FF,0x3BFF,0x53FF, + 0x63FF,0x401E,0x4C1F,0x581F,0x6C1F,0x7C1F,0x7E1F,0x7EBF, + 0x7BDE,0x4BCD,0x47EC,0x43CA,0x3BC8,0x2F45,0x2703,0x22E2, + 0x1EC1,0x1EE1,0x1AE1,0x16C0,0x12C0,0x0E80,0x0E40,0x1221, + 0x0580,0x2765,0x2324,0x1F03,0x1F23,0x1B22,0x12E0,0x12C1, + 0x1281,0x1241,0x0A00,0x05C0,0x0180,0x0140,0x0540,0x0520, + 0x0100,0x1A42,0x1622,0x1201,0x0E01,0x0580,0x0100,0x1A62, + 0x1E83,0x1641,0x0DE0,0x05A0,0x0560,0x53AF,0x3F4A,0x3308, + 0x2A86,0x3B29,0x2E87,0x1E43,0x26A5,0x1A22,0x1201,0x0DA1, + 0x1602,0x00C0,0x0540,0x0521,0x1663,0x1643,0x0DE1,0x1642, + 0x05C0,0x4EEF,0x5312,0x4AD0,0x3E4B,0x3A4B,0x31E9,0x3A2A, + 0x2DC8,0x2DA8,0x2987,0x2566,0x1D25,0x1504,0x25A7,0x2DC7, + 0x3608,0x2986,0x2DE7,0x3A2A,0x3207,0x25A5,0x21A4,0x29C5, + 0x3A4B,0x466A,0x3A08,0x3A28,0x3A08,0x2564,0x31A5,0x29A6, + 0x3184,0x2965,0x1903,0x2143,0x2163,0x2963,0x2164,0x2DA4, + 0x2583,0x31C5,0x1D63,0x2164,0x31A6,0x35E6,0x31C6,0x3E8A, + + 0x3A69,0x2DE7,0x46CD,0x532F,0x3E8B,0x2DE6,0x10E2,0x1502, + 0x4ACD,0x530F,0x2E07,0x08C1,0x25A6,0x10E2,0x1522,0x1523, + 0x25A5,0x4ED1,0x3A2D,0x3A0C,0x31CA,0x360C,0x31EA,0x2DCA, + 0x360B,0x2568,0x2DA9,0x426E,0x468F,0x29A9,0x29A8,0x2588, + 0x1504,0x2988,0x2167,0x360A,0x426D,0x35EC,0x3E2D,0x52D1, + 0x4A90,0x3A2C,0x424E,0x3E4D,0x5310,0x5732,0x426C,0x6795, + 0x5B51,0x5B51,0x6FD5,0x6373,0x52EF,0x1D27,0x2549,0x10C4, + 0x08C2,0x18E6,0x35AE,0x31AC,0x2D8C,0x2DAD,0x31AD,0x256A, + 0x1D28,0x1506,0x0CC4,0x6FF8,0x63B3,0x4AED,0x3E8A,0x4F0F, + 0x42CC,0x6796,0x4A8F,0x3249,0x4AEE,0x5FB2,0x46ED,0x3A6A, + 0x322A,0x7BEE,0x63EA,0x57E9,0x4FA8,0x3B44,0x3AC4,0x2622, + 0x1141,0x4F0B,0x7BF9,0x67F2,0x5FB0,0x25E3,0x4F2D,0x5B70, + 0x4ACD,0x576E,0x574E,0x572F,0x1263,0x0E83,0x0EA3,0x1725, + 0x23C8,0x1304,0x17C4,0x22E6,0x1323,0x0A62,0x0621,0x01C1, + 0x05A1,0x41D3,0x0241,0x02A0,0x02E4,0x0322,0x0369,0x1F8C, + 0x27CE,0x37D0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,0x6FFF, + + 0x7FFF,0xFFFF,0x4191,0x11E0,0x1A20,0x2680,0x32C0,0x3B00, + 0x4740,0x4F61,0x57A0,0x63E2,0x6FE4,0x77E6,0x7BEF,0x7FF4, + 0x7FFB,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,0x3000,0x3400, + 0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,0x7084,0x7D29, + 0x7E52,0x7F39,0x7BDE,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77, + 0x12B9,0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F, + 0x639F,0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x7F40,0x7B60, + 0x7780,0x73A0,0x6FC0,0x6BE0,0x6BE0,0x6FE3,0x73E6,0x77E9, + 0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x4191,0x6000,0x6400, + 0x6800,0x6C00,0x7021,0x7484,0x78C6,0x7D29,0x7D68,0x7DA6, + 0x7DE4,0x7E23,0x7E82,0x7EE1,0x7BDE,0x21A6,0x2000,0x2400, + 0x2C00,0x3400,0x3800,0x3C00,0x4000,0x4400,0x4800,0x4C00, + 0x5000,0x5400,0x5800,0x5C00,0x31EA,0xFFFF,0x4191,0x47FF, + 0x4BFF,0x4FFF,0x53FF,0x57FF,0x5BFF,0x5FFF,0x63FF,0x67FF, + 0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,0x7BDE,0x0421,0x179F, + 0x1BBF,0x1FDF,0x23FF,0x27FF,0x2BFF,0x2FFF,0x33FF,0x37FF, + + 0x3BFF,0x3FFF,0x43FF,0x47FF,0x4BFF,0x7BDE,0x21A6,0x143F, + 0x10BF,0x0D1F,0x099F,0x05FF,0x063F,0x0A7F,0x0ABF,0x0EDF, + 0x0EFF,0x131F,0x133F,0x175F,0x177F,0x31EA,0xFFFF,0x4191, + 0x53E0,0x57E0,0x5BE0,0x5FE0,0x63E0,0x67E0,0x6BE0,0x6FE3, + 0x73E6,0x77E9,0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x0421, + 0x1BE0,0x1FE0,0x23E0,0x27E0,0x2BE0,0x2FE0,0x33E0,0x37E0, + 0x3BE0,0x3FE0,0x43E0,0x47E0,0x4BE0,0x4FE0,0x7BDE,0x21A6, + 0x1600,0x1620,0x1640,0x1660,0x1680,0x16A0,0x16C0,0x16E0, + 0x1700,0x1720,0x1740,0x1760,0x1780,0x1BA0,0x31EA,0xFFFF, + 0x4191,0x03EF,0x03EA,0x03E5,0x03E0,0x03E0,0x17E0,0x2BE0, + 0x3FE0,0x53E0,0x67E0,0x7FE0,0x7FEF,0x7FF4,0x7FF9,0x7BDE, + 0x0000,0x641F,0x501F,0x3C1F,0x281F,0x141F,0x001F,0x00BF, + 0x015F,0x01FF,0x029F,0x033F,0x03FF,0x03F9,0x03F4,0x7BDE, + 0x0000,0x7FEA,0x7FE0,0x7F20,0x7E80,0x7DE0,0x7D40,0x7CA0, + 0x7C00,0x7C05,0x780A,0x7C0F,0x7C14,0x7C19,0x7C1F,0x7BDE, + 0xFFFF,0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x6C1F,0x7C1F +}; +static UINT16 bloodwar_mcu_4_11[] = { // Warrior 6 Player 2 + 0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x6C1F,0x7C1F,0x7E1F, + 0x7EBF,0x5C13,0x5C52,0x6432,0x7075,0x7992,0x7DF6,0x7EF9, + 0x7BDE,0x52F2,0x4F11,0x4AEF,0x42CD,0x368A,0x2E48,0x2A27, + 0x2606,0x2626,0x2226,0x1E05,0x1A05,0x15C4,0x1584,0x1966, + 0x0CC4,0x2E69,0x2A48,0x2627,0x2647,0x2246,0x1A04,0x19E5, + 0x19C5,0x1985,0x1144,0x0D04,0x08C4,0x08A4,0x0CA4,0x0C84, + 0x0864,0x21A6,0x1D86,0x1965,0x1565,0x1104,0x10A4,0x21C6, + 0x25E7,0x1DA5,0x1544,0x1124,0x10E4,0x5B13,0x46AE,0x3A6C, + 0x31EA,0x428D,0x35EB,0x2587,0x2DE9,0x2166,0x1945,0x1505, + 0x1D66,0x0C64,0x10C4,0x10A5,0x1DC7,0x1DA7,0x1545,0x1DA6, + 0x0D24,0x4EEF,0x5312,0x4AD0,0x3E4B,0x3A4B,0x31E9,0x3A2A, + 0x2DC8,0x2DA8,0x2987,0x2566,0x1D25,0x1504,0x25A7,0x2DC7, + 0x3608,0x2986,0x2DE7,0x3A2A,0x3207,0x25A5,0x21A4,0x29C5, + 0x3A4B,0x466A,0x3A08,0x3A28,0x3A08,0x2564,0x31A5,0x29A6, + 0x3184,0x2965,0x1903,0x2143,0x2163,0x2963,0x2164,0x2DA4, + 0x2583,0x31C5,0x1D63,0x2164,0x31A6,0x35E6,0x31C6,0x3E8A, + + 0x3A69,0x2DE7,0x46CD,0x532F,0x3E8B,0x2DE6,0x10E2,0x1502, + 0x4ACD,0x530F,0x2E07,0x08C1,0x25A6,0x10E2,0x1522,0x1523, + 0x25A5,0x4ED1,0x3A2D,0x3A0C,0x31CA,0x360C,0x31EA,0x2DCA, + 0x360B,0x2568,0x2DA9,0x426E,0x468F,0x29A9,0x29A8,0x2588, + 0x1504,0x2988,0x2167,0x360A,0x426D,0x35EC,0x3E2D,0x52D1, + 0x4A90,0x3A2C,0x424E,0x3E4D,0x5310,0x5732,0x426C,0x6795, + 0x5B51,0x5B51,0x6FD5,0x6373,0x52EF,0x1D27,0x2549,0x10C4, + 0x08C2,0x18E6,0x35AE,0x31AC,0x2D8C,0x2DAD,0x31AD,0x256A, + 0x1D28,0x1506,0x0CC4,0x6FF8,0x63B3,0x4AED,0x3E8A,0x4F0F, + 0x42CC,0x6796,0x4A8F,0x3249,0x4AEE,0x5FB2,0x46ED,0x3A6A, + 0x322A,0x7BEE,0x63EA,0x57E9,0x4FA8,0x3B44,0x3AC4,0x2622, + 0x1141,0x4F0B,0x7BF9,0x67F2,0x5FB0,0x25E3,0x4F2D,0x5B70, + 0x4ACD,0x576E,0x574E,0x572F,0x1263,0x0E83,0x0EA3,0x1725, + 0x23C8,0x1304,0x17C4,0x22E6,0x1323,0x0A62,0x0621,0x01C1, + 0x05A1,0x41D3,0x0241,0x02A0,0x02E4,0x0322,0x0369,0x1F8C, + 0x27CE,0x37D0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,0x6FFF, + + 0x7FFF,0xFFFF,0x4191,0x11E0,0x1A20,0x2680,0x32C0,0x3B00, + 0x4740,0x4F61,0x57A0,0x63E2,0x6FE4,0x77E6,0x7BEF,0x7FF4, + 0x7FFB,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,0x3000,0x3400, + 0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,0x7084,0x7D29, + 0x7E52,0x7F39,0x7BDE,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77, + 0x12B9,0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F, + 0x639F,0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x7F40,0x7B60, + 0x7780,0x73A0,0x6FC0,0x6BE0,0x6BE0,0x6FE3,0x73E6,0x77E9, + 0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x4191,0x6000,0x6400, + 0x6800,0x6C00,0x7021,0x7484,0x78C6,0x7D29,0x7D68,0x7DA6, + 0x7DE4,0x7E23,0x7E82,0x7EE1,0x7BDE,0x21A6,0x2000,0x2400, + 0x2C00,0x3400,0x3800,0x3C00,0x4000,0x4400,0x4800,0x4C00, + 0x5000,0x5400,0x5800,0x5C00,0x31EA,0xFFFF,0x4191,0x47FF, + 0x4BFF,0x4FFF,0x53FF,0x57FF,0x5BFF,0x5FFF,0x63FF,0x67FF, + 0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,0x7BDE,0x0421,0x179F, + 0x1BBF,0x1FDF,0x23FF,0x27FF,0x2BFF,0x2FFF,0x33FF,0x37FF, + + 0x3BFF,0x3FFF,0x43FF,0x47FF,0x4BFF,0x7BDE,0x21A6,0x143F, + 0x10BF,0x0D1F,0x099F,0x05FF,0x063F,0x0A7F,0x0ABF,0x0EDF, + 0x0EFF,0x131F,0x133F,0x175F,0x177F,0x31EA,0xFFFF,0x4191, + 0x53E0,0x57E0,0x5BE0,0x5FE0,0x63E0,0x67E0,0x6BE0,0x6FE3, + 0x73E6,0x77E9,0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x0421, + 0x1BE0,0x1FE0,0x23E0,0x27E0,0x2BE0,0x2FE0,0x33E0,0x37E0, + 0x3BE0,0x3FE0,0x43E0,0x47E0,0x4BE0,0x4FE0,0x7BDE,0x21A6, + 0x1600,0x1620,0x1640,0x1660,0x1680,0x16A0,0x16C0,0x16E0, + 0x1700,0x1720,0x1740,0x1760,0x1780,0x1BA0,0x31EA,0xFFFF, + 0x4191,0x03EF,0x03EA,0x03E5,0x03E0,0x03E0,0x17E0,0x2BE0, + 0x3FE0,0x53E0,0x67E0,0x7FE0,0x7FEF,0x7FF4,0x7FF9,0x7BDE, + 0x0000,0x641F,0x501F,0x3C1F,0x281F,0x141F,0x001F,0x00BF, + 0x015F,0x01FF,0x029F,0x033F,0x03FF,0x03F9,0x03F4,0x7BDE, + 0x0000,0x7FEA,0x7FE0,0x7F20,0x7E80,0x7DE0,0x7D40,0x7CA0, + 0x7C00,0x7C05,0x780A,0x7C0F,0x7C14,0x7C19,0x7C1F,0x7BDE, + 0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A +}; +static UINT16 bloodwar_mcu_4_12[] = { // Warrior 9 Player 1 + 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x1AC2,0x1AE2,0x1B02,0x1703,0x1723,0x1743,0x1763, + 0x1784,0x1BA3,0x17A3,0x1BC4,0x1BC6,0x1FE5,0x12C2,0x1BE5, + 0x1FC5,0x1FA5,0x1B65,0x1F64,0x2386,0x2786,0x1B83,0x1BA4, + 0x23A6,0x23E7,0x1FC5,0x23E7,0x1FE6,0x1FE8,0x1FC8,0x1AA4, + 0x1A84,0x1703,0x1704,0x1B04,0x1F84,0x1723,0x1F46,0x23A7, + 0x1B05,0x1BC4,0x13A3,0x16C3,0x1AE4,0x2FE8,0x43EB,0x37EB, + 0x2FEA,0x37EC,0x3BED,0x3FEE,0x3FED,0x43EE,0x43EE,0x43EE, + 0x33EB,0x37EB,0x37EB,0x33EA,0x3BEC,0x3BEC,0x37EB,0x3FEC, + 0x3FED,0x25C7,0x2E08,0x428E,0x5751,0x5F93,0x5B71,0x67F3, + 0x67B5,0x6FD8,0x6793,0x6FF7,0x73F8,0x6BB6,0x73D8,0x77F9, + 0x77FA,0x428F,0x46CD,0x4B0F,0x46D0,0x5732,0x67D5,0x63B5, + 0x63B5,0x6BB6,0x6BD6,0x6FD7,0x67B7,0x73F9,0x6376,0x6776, + 0x5F54,0x1104,0x10E4,0x10E4,0x1524,0x1525,0x1164,0x15A4, + 0x1965,0x1103,0x1544,0x1103,0x1564,0x1584,0x1604,0x1986, + + 0x0CA3,0x1525,0x10E4,0x1925,0x10C4,0x14E5,0x10A4,0x2167, + 0x29A8,0x2587,0x29C9,0x29C8,0x320A,0x320B,0x25A8,0x1DA6, + 0x1D47,0x1128,0x1528,0x1223,0x1664,0x158A,0x19AB,0x1DAC, + 0x21EE,0x21ED,0x220D,0x220C,0x222D,0x194A,0x21CD,0x21AD, + 0x260E,0x220E,0x25EF,0x29E9,0x2DEA,0x3A0C,0x3E2D,0x2A0F, + 0x29EE,0x46D2,0x428F,0x4AD1,0x46B1,0x4690,0x428D,0x2608, + 0x4250,0x2903,0x2D44,0x3565,0x41C8,0x3DA7,0x3986,0x41E8, + 0x4A08,0x41E7,0x45E8,0x524B,0x3526,0x564E,0x49ED,0x3DA8, + 0x416B,0x2E84,0x4746,0x5787,0x4F46,0x57A8,0x4B45,0x5FE9, + 0x5BAB,0x578A,0x57AA,0x5369,0x5FE8,0x53A8,0x4FA7,0x4344, + 0x4345,0x0D63,0x1162,0x1983,0x19A4,0x15A4,0x19C4,0x19E4, + 0x1DE4,0x1A04,0x1E05,0x2246,0x2647,0x2A26,0x2A46,0x2646, + 0x2625,0x2E88,0x3669,0x36AA,0x2626,0x2646,0x2226,0x36EA, + 0x36EB,0x3AEB,0x36CB,0x36CA,0x3ACC,0x3A8B,0x536F,0x63B3, + 0x4B0F,0x290D,0x6004,0x7FFF,0x6409,0x681F,0x281F,0x401F, + 0x2BFF,0x4FFF,0x77FF,0x7C5F,0x681F,0x541F,0x7E15,0x7FE0, + + 0x03E0,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0, + 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC, + 0x7FFF,0x2E88,0x3669,0x1E04,0x0DE2,0x2646,0x2226,0x36EA, + 0x2E6A,0x3AEB,0x36CB,0x32A9,0x430C,0x3A8B,0x536F,0x63B3, + 0x4B0F,0x0000,0x201B,0x241D,0x2C1F,0x341F,0x3C1E,0x401F, + 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B1F, + 0x7BDE,0x7FFA,0x1CC2,0x2065,0x2083,0x24C4,0x24E2,0x2502, + 0x2503,0x28A5,0x2D43,0x2D45,0x2D63,0x2D64,0x3144,0x3145, + 0x3583,0x3584,0x3586,0x3587,0x35C3,0x3986,0x3987,0x39C3, + 0x39E5,0x39E7,0x39E8,0x39E3,0x3A05,0x3A23,0x41C6,0x41E5, + 0x4205,0x420A,0x4226,0x4229,0x4263,0x4265,0x4266,0x4267, + 0x4287,0x46E3,0x4A07,0x4A0B,0x4A26,0x4A27,0x4A29,0x4A65, + 0x4A66,0x4A8A,0x4AA5,0x4AA6,0x4AA8,0x4AC5,0x4AE3,0x524C, + 0x5286,0x5289,0x52A6,0x52C9,0x52E5,0x52E6,0x52E8,0x52E9, + 0x5AC6,0x5AC9,0x5AE6,0x5AE8,0x5AE9,0x5AEB,0x62E6,0x62E8, + 0x62E9,0x62EA,0x62EB,0x62EC,0x6AE8,0x6AEA,0x6AED,0x6AEE, + + 0x6AF0,0x6EE8,0x6EEA,0x6EED,0x6EEE,0x6EF0,0x76EA,0x76EB, + 0x76ED,0x770E,0x7710,0x7711,0x7712,0x7713,0x7F0D,0x7F0F, + 0x7F10,0x7F12,0x7F13,0x7F35,0x7F1A,0x7F1B,0x7F0E,0x7F30, + 0x7F32,0x7F38,0x7F5B,0x7F6B,0x7F70,0x7F92,0x7F95,0x7F97, + 0x7F9A,0x7FBE,0x7FDF,0x7F91,0x7FB2,0x7FB3,0x7FB4,0x7FB5, + 0x7FB6,0x7FB7,0x7FB8,0x7FB9,0x7FBF,0x7FBB,0x7FFF,0x7FFF, + 0x0000,0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108 +}; +static UINT16 bloodwar_mcu_4_13[] = { // Warrior 9 Player 2 + 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x146D,0x1CAF,0x24EF,0x24EF,0x2910,0x3553,0x3DB7, + 0x45B8,0x3993,0x2610,0x4196,0x2632,0x2A52,0x1D2F,0x2652, + 0x569A,0x2A15,0x4A19,0x41D6,0x41F8,0x39D6,0x25F2,0x2613, + 0x2E15,0x2E56,0x2A34,0x2E56,0x2A55,0x2A56,0x2A36,0x1C6D, + 0x2931,0x20B0,0x2D33,0x3133,0x4196,0x3596,0x3575,0x39D6, + 0x3134,0x31D5,0x2994,0x2CF2,0x3113,0x3D98,0x41D8,0x3E3A, + 0x4E1B,0x4DF9,0x521A,0x563B,0x561A,0x5A3C,0x629F,0x5A3C, + 0x49B8,0x5618,0x4DD8,0x4997,0x49F9,0x51F9,0x4DF8,0x561A, + 0x561B,0x25E6,0x2E27,0x42CD,0x5F92,0x5FD2,0x5BB0,0x67F4, + 0x6FF7,0x6FF7,0x67D2,0x6FF6,0x73F7,0x6BF5,0x73F7,0x77F8, + 0x77F9,0x42EC,0x3EE9,0x4B4E,0x470F,0x5771,0x6FF7,0x67F3, + 0x63F3,0x67F4,0x73F7,0x5FB5,0x67F6,0x73F8,0x63B5,0x5FB5, + 0x5F93,0x1063,0x1484,0x18A5,0x0C42,0x1CC6,0x0C42,0x1063, + 0x0C42,0x0C42,0x1484,0x1484,0x1063,0x10C9,0x1449,0x1986, + + 0x0C42,0x1484,0x1063,0x1063,0x1484,0x18A5,0x10A4,0x18A5, + 0x29A8,0x18A5,0x29C9,0x29C8,0x320A,0x320B,0x18A5,0x1484, + 0x1D47,0x1128,0x1528,0x1068,0x146B,0x158A,0x19AB,0x1DAC, + 0x21EE,0x21ED,0x220D,0x220C,0x222D,0x194A,0x21CD,0x21AD, + 0x260E,0x220E,0x25EF,0x29E9,0x2DEA,0x3A0C,0x3E2D,0x2A0F, + 0x29EE,0x46D2,0x428F,0x4AD1,0x46B1,0x4690,0x428D,0x2608, + 0x4250,0x11C2,0x1683,0x2302,0x2305,0x1B22,0x1EC3,0x2385, + 0x3FE6,0x3344,0x2FC4,0x4FE7,0x2AE3,0x376B,0x2B0A,0x22C5, + 0x2688,0x2E84,0x4746,0x5787,0x4F46,0x57A8,0x4B45,0x5FE9, + 0x5BAB,0x578A,0x57AA,0x5369,0x5FE8,0x53A8,0x4FA7,0x4344, + 0x4345,0x0D63,0x1162,0x1983,0x19A4,0x15A4,0x19C4,0x19E4, + 0x1DE4,0x1A04,0x1E05,0x2246,0x2647,0x2A26,0x2A46,0x2646, + 0x2625,0x2E88,0x3669,0x36AA,0x2626,0x2646,0x2226,0x36EA, + 0x36EB,0x3AEB,0x36CB,0x36CA,0x4B0D,0x3A8B,0x4F8E,0x63B3, + 0x4B0F,0x290D,0x6004,0x7FFF,0x6409,0x681F,0x281F,0x401F, + 0x2BFF,0x4FFF,0x77FF,0x7C5F,0x681F,0x541F,0x7E15,0x7FE0, + + 0x03E0,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0, + 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC, + 0x7FFF,0x2E88,0x3669,0x1E04,0x0DE2,0x2646,0x2226,0x36EA, + 0x2E6A,0x3AEB,0x36CB,0x32A9,0x430C,0x3A8B,0x536F,0x63B3, + 0x4B0F,0x0000,0x201B,0x241D,0x2C1F,0x341F,0x3C1E,0x401F, + 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B1F, + 0x7BDE,0x7FFA,0x1CC2,0x2065,0x2083,0x24C4,0x24E2,0x2502, + 0x2503,0x28A5,0x2D43,0x2D45,0x2D63,0x2D64,0x3144,0x3145, + 0x3583,0x3584,0x3586,0x3587,0x35C3,0x3986,0x3987,0x39C3, + 0x39E5,0x39E7,0x39E8,0x39E3,0x3A05,0x3A23,0x41C6,0x41E5, + 0x4205,0x420A,0x4226,0x4229,0x4263,0x4265,0x4266,0x4267, + 0x4287,0x46E3,0x4A07,0x4A0B,0x4A26,0x4A27,0x4A29,0x4A65, + 0x4A66,0x4A8A,0x4AA5,0x4AA6,0x4AA8,0x4AC5,0x4AE3,0x524C, + 0x5286,0x5289,0x52A6,0x52C9,0x52E5,0x52E6,0x52E8,0x52E9, + 0x5AC6,0x5AC9,0x5AE6,0x5AE8,0x5AE9,0x5AEB,0x62E6,0x62E8, + 0x62E9,0x62EA,0x62EB,0x62EC,0x6AE8,0x6AEA,0x6AED,0x6AEE, + + 0x6AF0,0x6EE8,0x6EEA,0x6EED,0x6EEE,0x6EF0,0x76EA,0x76EB, + 0x76ED,0x770E,0x7710,0x7711,0x7712,0x7713,0x7F0D,0x7F0F, + 0x7F10,0x7F12,0x7F13,0x7F35,0x7F1A,0x7F1B,0x7F0E,0x7F30, + 0x7F32,0x7F38,0x7F5B,0x7F6B,0x7F70,0x7F92,0x7F95,0x7F97, + 0x7F9A,0x7FBE,0x7FDF,0x7F91,0x7FB2,0x7FB3,0x7FB4,0x7FB5, + 0x7FB6,0x7FB7,0x7FB8,0x7FB9,0x7FBF,0x7FBB,0x7FFF,0x7FFF, + 0x0000,0xFFFF,0x0006,0x0000,0x4232,0x56F8,0x2D8D,0x2108 +}; +static UINT16 bloodwar_mcu_4_14[] = { // Warrior 7 Player 1 + 0x0006,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x0D00,0x0D00,0x0D40,0x0D40,0x0D60,0x0D80,0x1140, + 0x1561,0x1581,0x15A1,0x15E1,0x1601,0x19A1,0x19C1,0x19C2, + 0x19E1,0x1E23,0x1E42,0x1E43,0x1E82,0x2204,0x2223,0x2242, + 0x2243,0x2244,0x2262,0x2263,0x22A2,0x22A3,0x2664,0x2683, + 0x2684,0x2AA3,0x2AA4,0x2EC3,0x2EC4,0x32A4,0x32C3,0x32C4, + 0x3304,0x3305,0x3325,0x3344,0x36C5,0x3704,0x3705,0x3706, + 0x3707,0x3B45,0x3B46,0x3B65,0x3B84,0x3B85,0x3F05,0x3F27, + 0x3F28,0x3F44,0x3F46,0x3F47,0x3F65,0x3F66,0x3F67,0x3F85, + 0x3FA5,0x4328,0x4347,0x43A6,0x47A7,0x47A8,0x47C6,0x47C7, + 0x47E5,0x47E6,0x4B69,0x4BA7,0x4BA8,0x4BC6,0x4BC7,0x4BC8, + 0x4BE7,0x57E9,0x57E8,0x57E7,0x5BCA,0x5BE9,0x5BEA,0x5BEC, + 0x5BE8,0x5BE9,0x5BE8,0x5BEB,0x5F6E,0x5FCD,0x5FEB,0x5FE9, + 0x5BEC,0x67E9,0x67EA,0x67EC,0x67ED,0x6FED,0x6FED,0x6FEE, + 0x6FEF,0x6FEC,0x6FEC,0x6FED,0x6FEB,0x6FED,0x6FEC,0x73EE, + + 0x73EC,0x77F1,0x77F0,0x77F1,0x7BF1,0x7BF2,0x7BF3,0x7BF1, + 0x7BF2,0x7FF2,0x7FF4,0x7FF2,0x7FF4,0x7FF2,0x7FF4,0x7FF4, + 0x7FF5,0x33E9,0x0D82,0x0DC1,0x0DC2,0x0DE1,0x0DE2,0x0E02, + 0x1223,0x1243,0x1263,0x12A3,0x12C3,0x12E3,0x1303,0x1323, + 0x1343,0x16E3,0x1703,0x1723,0x1743,0x1783,0x1784,0x17A3, + 0x17A4,0x17C4,0x17E4,0x1AC3,0x1AE3,0x1AE4,0x1B03,0x1B04, + 0x1B43,0x1F45,0x1F65,0x1F85,0x1FA4,0x1FA5,0x1FA6,0x1FC5, + 0x1FE5,0x1FE6,0x1FE8,0x23E6,0x23E7,0x23E8,0x23E8,0x27E7, + 0x27E7,0x2BE8,0x2BE9,0x2BEA,0x2BE8,0x2FE9,0x2FEA,0x2FE9, + 0x2FEA,0x2FE9,0x2FE9,0x2FEB,0x33EB,0x3BEB,0x3FEE,0x3FEE, + 0x47F0,0x7FF8,0x25E6,0x29A6,0x29A7,0x2DE7,0x3A0A,0x46AC, + 0x4ACC,0x4EEF,0x4F2F,0x532F,0x574E,0x67F1,0x63D2,0x63EF, + 0x63F1,0x6BF5,0x6BF6,0x6FB7,0x6FF5,0x6FF6,0x6FF7,0x6FF6, + 0x77F6,0x77F7,0x77F8,0x77F9,0x7BF8,0x7FFA,0x7FFB,0x7BDC, + 0x7FFA,0x41D3,0x0000,0x0000,0x131A,0x2BBF,0x4FBF,0x23E0, + 0x43E0,0x67ED,0x4C07,0x6409,0x7CCF,0x3C1F,0x541F,0x6C1F, + + 0x7FFF,0x7C00,0x3786,0x37A6,0x3B86,0x3BC6,0x3F47,0x3F86, + 0x3FC6,0x3FE6,0x3FE7,0x47A7,0x47C6,0x47C7,0x47E6,0x47E7, + 0x4BA7,0x4BA8,0x4BC7,0x4BC8,0x4BE7,0x4BE8,0x4FA8,0x4FC8, + 0x4FE8,0x53C8,0x53CA,0x53CB,0x53EA,0x53EB,0x53EC,0x5BCC, + 0x5BCD,0x5BD0,0x5BEB,0x5BEC,0x5BED,0x5BEE,0x5FD0,0x5FED, + 0x5FEF,0x5FF0,0x5FF2,0x63EF,0x63F1,0x63F2,0x63F3,0x63F5, + 0x63F6,0x6BF3,0x6BF5,0x6BF6,0x6BF7,0x6BF8,0x6FF6,0x6FF7, + 0x6FF8,0x6FFA,0x6FFB,0x6FFC,0x73FB,0x73FC,0x73FD,0x73FF, + 0x7FFF,0x53E7,0x5FE8,0x4FE7,0x4BE7,0x3FE6,0x37C6,0x33A6, + 0x2BA6,0x2366,0x2325,0x2346,0x2304,0x2786,0x2306,0x2746, + 0x1F24,0x1F04,0x2345,0x1F06,0x33C6,0x33E6,0x27A6,0x2785, + 0x2B86,0x1EC4,0x37E6,0x37A6,0x3BE6,0x2745,0x47E6,0x4BE6, + 0x4FE6,0x47E7,0x5BE8,0x5BEA,0x3B86,0x3766,0x4BE8,0x53E8, + 0x5FEA,0x63EB,0x6FEF,0x73F0,0x73F1,0x6FF0,0x6FED,0x6BEC, + 0x63EA,0x5FE9,0x63E9,0x1AE4,0x2365,0x2BA5,0x27A5,0x1AA4, + 0x22C6,0x2B85,0x1A24,0x3386,0x3FC6,0x3FE7,0x2726,0x2B46, + + 0x3366,0x15C4,0x15E5,0x1644,0x1605,0x1604,0x1E84,0x1EC6, + 0x2306,0x15E4,0x1625,0x22C6,0x1664,0x1624,0x1EA6,0x1E86, + 0x1645,0x6ABB,0x6A9B,0x6A5B,0x663A,0x661A,0x5DD9,0x5D99, + 0x5519,0x48B7,0x4896,0x140C,0x140D,0x140B,0x100B,0x100A, + 0x1009,0x0C08,0x0C09,0x200F,0x200D,0x1C0D,0x1C0A,0x200C, + 0x200A,0x2009,0x202A,0x204A,0x208B,0x24C9,0x24C7,0x356D, + 0x1C0C,0x1410,0x1412,0x1C13,0x2015,0x2417,0x2C17,0x3419, + 0x3819,0x4419,0x4877,0x4C39,0x4C59,0x4C79,0x543A,0x5479, + 0x55D6,0x5859,0x5879,0x5CB9,0x5CBA,0x5CDA,0x5D39,0x5D59, + 0x5D9B,0x60F9,0x651B,0x655B,0x6A1B,0x6A3B,0x6ABB,0x6ADB, + 0x6F1B,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F, + 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92, + 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4, + 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6, + + 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB, + 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539, + 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F, + 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F, + 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF, + 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF, + 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F, + 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x75BF, + 0x75FF,0x761F,0x723F,0x725F,0x769F,0x773F,0x7B7F,0x75BF, + 0x75FF,0x7A3F,0x7AFF,0x7F7F,0x755F,0x75FF,0x763F,0x7A9F, + 0x7ADF,0x7F5F,0x7FBF,0x7FDF,0x75FF,0x761F,0x763F,0x765F, + 0x7A7F,0x7A9F,0x7ABF,0x7EDF,0x7EFF,0x7F3F,0x7F7F,0x7FBF, + 0x7FFF,0x0000,0xFFFF,0x31EC,0x7FE0,0x7C1F,0x7C00,0x001F, + 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7DFF,0x7E9F,0x7BDE,0x7FFC,0x1C40,0x1C81,0x2060,0x2880, + 0x2C80,0x38C1,0x38C1,0x38C1,0x38C1,0x38C1,0x3CC0,0x3CC0, + + 0x38E0,0x38E1,0x4100,0x4500,0x4503,0x4503,0x4D00,0x4522, + 0x4522,0x4D20,0x5121,0x5123,0x5124,0x5520,0x5521,0x5920, + 0x4D62,0x5161,0x5561,0x5565,0x5961,0x5964,0x6160,0x6160, + 0x6161,0x6162,0x6562,0x6982,0x55A2,0x59A6,0x59A1,0x59A2, + 0x59A4,0x61A0,0x61A1,0x65A4,0x69A0,0x69A0,0x69A2,0x6DA0, + 0x71A0,0x5DE6,0x5DE0,0x65E3,0x69E0,0x6DE3,0x71E0,0x71E1, + 0x71E3,0x71C3,0x6E20,0x6E24,0x7221,0x7223,0x7224,0x7226, + 0x7261,0x7263,0x7264,0x7265,0x7266,0x7267,0x72A3,0x72A5, + 0x72A8,0x72A9,0x72AB,0x72C3,0x72C5,0x72C7,0x72C9,0x72C1, + 0x7306,0x7306,0x7308,0x7309,0x730B,0x730C,0x730D,0x730E, + 0x7328,0x732A,0x732B,0x7308,0x774C,0x7B90,0x7BB4,0x7FD9, + 0x7728,0x774B,0x7B8C,0x7FB5,0x7FD9,0x7725,0x772A,0x7B4D, + 0x7B70,0x7FB4,0x7FF9,0x7FFC,0x7FFD,0x7B4A,0x7B4B,0x7B4C, + 0x7B2D,0x7B6E,0x7B6F,0x7B90,0x7BB2,0x7BB3,0x7FD6,0x7FD8, + 0x7BDA,0x7FFE,0x0000,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00, + 0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F, + + 0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7F9F,0x1DD0,0x25F0,0x1DF1, + 0x2213,0x1A14,0x1E17,0x2237,0x2637,0x2657,0x2657,0x1E58, + 0x2278,0x2278,0x2678,0x1E99,0x22B9,0x2AB9,0x2EB9,0x1EBB, + 0x2AD9,0x2ED9,0x1EDB,0x2EDC,0x36DC,0x32DC,0x1EDD,0x26DE, + 0x1EDE,0x2B1B,0x271C,0x271D,0x3B3C,0x2B3D,0x331C,0x1B1E, + 0x26FE,0x2B1E,0x2F1F,0x2F1F,0x1F3F,0x335B,0x373B,0x2F3C, + 0x333C,0x333C,0x2B3E,0x2F3E,0x375E,0x235F,0x2F1F,0x2F5F, + 0x235F,0x1B5F,0x2B7A,0x2F9A,0x339C,0x2B9D,0x339E,0x379F, + 0x379F,0x3F9F,0x3F9F,0x3BDE,0x3B9E,0x2F9F,0x379F,0x3B9F, + 0x439F,0x2B9F,0x379F,0x3B9F,0x3F9F,0x439F,0x479F,0x37BF, + 0x3FDF,0x4BDF,0x4FDF,0x57DF,0x37BF,0x3FDF,0x479E,0x4B9F, + 0x539F,0x47DF,0x4BDF,0x4FDF,0x53DF,0x57DF,0x5BDF,0x5FDF, + 0x63FF,0x57FF,0x5BFF,0x5FFF,0x5BDF,0x63DF,0x6BFF,0x73FF, + 0x7BFF,0x5FFF,0x63FF,0x67FF,0x73FF,0x7BFF,0x5FFF,0x63FF, + 0x67FF,0x6FFF,0x73FF,0x77FF,0x7FBF,0x7FDF,0x57FF,0x5BFF, + 0x5FFF,0x63FF,0x67FF,0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF, + + 0x7BFF,0x7FFF,0x7FFF,0x0000,0xFFFF,0x28ED,0x7FE0,0x7C1F, + 0x7C00,0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F, + 0x701F,0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7FFA,0x1180,0x1580, + 0x15C0,0x19C0,0x1600,0x1A00,0x1A40,0x1E40,0x1E80,0x2280, + 0x1EA0,0x22A0,0x1EC0,0x22C0,0x26C0,0x2300,0x2302,0x2303, + 0x2300,0x2702,0x2B03,0x2720,0x2723,0x2743,0x2744,0x2760, + 0x2761,0x2762,0x2B60,0x2B62,0x2F61,0x3366,0x3380,0x3383, + 0x33A6,0x33A1,0x33A2,0x33C3,0x37C3,0x37C0,0x3762,0x3766, + 0x3781,0x3782,0x3784,0x37A0,0x37A1,0x3BA6,0x3BC1,0x3BC2, + 0x3BC4,0x3BE0,0x3BE3,0x3F87,0x3FA1,0x3FA4,0x3FC1,0x3FE4, + 0x3FE0,0x3FE1,0x3FE3,0x3FE4,0x43E0,0x4BE2,0x4BE4,0x4BE6, + 0x4BE8,0x4BEA,0x53E2,0x53E4,0x53E6,0x53E8,0x53EA,0x53EC, + 0x5BE4,0x5BE6,0x5BE8,0x5BEA,0x5BEC,0x5FE4,0x5FE6,0x5FE8, + 0x5FEA,0x5FEC,0x67E2,0x67E4,0x67E6,0x67E8,0x67EA,0x67EC, + 0x6FE8,0x6FEA,0x6FEC,0x6FEE,0x6FF0,0x73E0,0x73E8,0x73F0, + 0x73F4,0x73F9,0x77E0,0x77E8,0x77F0,0x77F4,0x77F9,0x7BE2, + + 0x7BE6,0x7BEC,0x7BF2,0x7BF5,0x7BF9,0x7FFB,0x7BFC,0x77E0, + 0x77E2,0x77E4,0x77E6,0x77E8,0x7BEA,0x7BED,0x7BF0,0x7BF3, + 0x7BF6,0x7BF9,0x7BFB,0x7FFF,0x0000,0xFFFF,0x0006,0x3CB1 +}; +static UINT16 bloodwar_mcu_4_15[] = { // Warrior 7 Player 2 + 0x0006,0x3CB1,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x1CCB,0x1049,0x184A,0x18E9,0x1CAA,0x1C4C,0x20AE, + 0x210D,0x214C,0x20EB,0x210D,0x20CB,0x292D,0x252D,0x292E, + 0x252D,0x254C,0x292E,0x254C,0x252C,0x294D,0x290C,0x2D2D, + 0x294C,0x2D4D,0x314F,0x296F,0x318E,0x3570,0x3571,0x3551, + 0x3531,0x35D0,0x39F1,0x3190,0x3DD1,0x41D1,0x3E12,0x41D3, + 0x3DB3,0x39B2,0x3DF2,0x4253,0x45F3,0x49F2,0x3DD2,0x3E32, + 0x41B3,0x4A55,0x4654,0x41F3,0x4613,0x45D3,0x4A56,0x4A75, + 0x45D4,0x45F4,0x4E35,0x45F2,0x4612,0x4674,0x45F4,0x4A35, + 0x4A35,0x4E35,0x4A55,0x4633,0x4A14,0x4E76,0x5696,0x4E75, + 0x5257,0x5A78,0x5296,0x4E76,0x4A35,0x5278,0x56D7,0x5B19, + 0x4E97,0x673C,0x631B,0x5ADA,0x6B1C,0x673C,0x66FE,0x66FB, + 0x5EFA,0x5ADA,0x5ED9,0x62FC,0x671A,0x6B1B,0x673C,0x677D, + 0x66FA,0x777F,0x777F,0x735F,0x6B7E,0x777F,0x7B9F,0x6F5F, + 0x6B9E,0x733D,0x6B1E,0x737F,0x6F5E,0x6F5E,0x6B3D,0x737F, + + 0x6F3E,0x7FFF,0x7FFF,0x7FDF,0x7BBF,0x7FDF,0x7B9F,0x777F, + 0x7B9F,0x779F,0x7BBF,0x7FFF,0x7FFF,0x7BBF,0x7FDF,0x779F, + 0x7FDF,0x3FE7,0x0940,0x0960,0x0960,0x0980,0x09A0,0x09C0, + 0x1200,0x1220,0x1240,0x16A0,0x1AC0,0x1AE0,0x2760,0x1F40, + 0x1F60,0x26E0,0x2700,0x2720,0x2740,0x2780,0x2781,0x27A0, + 0x27A1,0x27C1,0x27E1,0x22C0,0x22E0,0x22E1,0x2300,0x2300, + 0x2340,0x3762,0x3782,0x37A2,0x37C1,0x37C2,0x37C3,0x37E2, + 0x37E2,0x37E3,0x37E5,0x3BE3,0x3BE4,0x3BE5,0x3BE5,0x3FE4, + 0x3FE4,0x4BE5,0x4BE6,0x4BE7,0x4BE5,0x4FE6,0x4FE7,0x4FE6, + 0x4FE7,0x4FE6,0x4FE6,0x4FE8,0x53E8,0x5BE8,0x5FEB,0x5FEB, + 0x67ED,0x6FF5,0x2245,0x1E03,0x21E5,0x2A46,0x3688,0x3F08, + 0x3707,0x3F48,0x47AB,0x4FAB,0x53AD,0x5FEF,0x57ED,0x57EC, + 0x57EE,0x4FCD,0x57F0,0x5BD1,0x5BEF,0x5FF0,0x5FF1,0x5FF2, + 0x63F0,0x63F1,0x63F2,0x63F3,0x6FF4,0x6BF4,0x6BF5,0x73F6, + 0x77F6,0x41D3,0x0000,0x0000,0x131A,0x2BBF,0x4FBF,0x23E0, + 0x43E0,0x67ED,0x4C07,0x6409,0x7CCF,0x3C1F,0x541F,0x6C1F, + + 0x7FFF,0x7C00,0x3786,0x37A6,0x3B86,0x3BC6,0x3F47,0x3F86, + 0x3FC6,0x3FE6,0x3FE7,0x47A7,0x47C6,0x47C7,0x47E6,0x47E7, + 0x4BA7,0x4BA8,0x4BC7,0x4BC8,0x4BE7,0x4BE8,0x4FA8,0x4FC8, + 0x4FE8,0x53C8,0x53CA,0x53CB,0x53EA,0x53EB,0x53EC,0x5BCC, + 0x5BCD,0x5BD0,0x5BEB,0x5BEC,0x5BED,0x5BEE,0x5FD0,0x5FED, + 0x5FEF,0x5FF0,0x5FF2,0x63EF,0x63F1,0x63F2,0x63F3,0x63F5, + 0x63F6,0x6BF3,0x6BF5,0x6BF6,0x6BF7,0x6BF8,0x6FF6,0x6FF7, + 0x6FF8,0x6FFA,0x6FFB,0x6FFC,0x73FB,0x73FC,0x73FD,0x73FF, + 0x7FFF,0x53E7,0x5FE8,0x4FE7,0x4BE7,0x3FE6,0x37C6,0x33A6, + 0x2BA6,0x2366,0x2325,0x2346,0x2304,0x2786,0x2306,0x2746, + 0x1F24,0x1F04,0x2345,0x1F06,0x33C6,0x33E6,0x27A6,0x2785, + 0x2B86,0x1EC4,0x37E6,0x37A6,0x3BE6,0x2745,0x47E6,0x4BE6, + 0x4FE6,0x47E7,0x5BE8,0x5BEA,0x3B86,0x3766,0x4BE8,0x53E8, + 0x5FEA,0x63EB,0x6FEF,0x73F0,0x73F1,0x6FF0,0x6FED,0x6BEC, + 0x63EA,0x5FE9,0x63E9,0x1AE4,0x2365,0x2BA5,0x27A5,0x1AA4, + 0x22C6,0x2B85,0x1A24,0x3386,0x3FC6,0x3FE7,0x2726,0x2B46, + + 0x3366,0x15C4,0x15E5,0x1644,0x1605,0x1604,0x1E84,0x1EC6, + 0x2306,0x15E4,0x1625,0x22C6,0x1664,0x1624,0x1EA6,0x1E86, + 0x1645,0x6ABB,0x6A9B,0x6A5B,0x663A,0x661A,0x5DD9,0x5D99, + 0x5519,0x48B7,0x4896,0x140C,0x140D,0x140B,0x100B,0x100A, + 0x1009,0x0C08,0x0C09,0x200F,0x200D,0x1C0D,0x1C0A,0x200C, + 0x200A,0x2009,0x202A,0x204A,0x208B,0x24C9,0x24C7,0x356D, + 0x1C0C,0x1410,0x1412,0x1C13,0x2015,0x2417,0x2C17,0x3419, + 0x3819,0x4419,0x4877,0x4C39,0x4C59,0x4C79,0x543A,0x5479, + 0x55D6,0x5859,0x5879,0x5CB9,0x5CBA,0x5CDA,0x5D39,0x5D59, + 0x5D9B,0x60F9,0x651B,0x655B,0x6A1B,0x6A3B,0x6ABB,0x6ADB, + 0x6F1B,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF, + 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF, + 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F, + 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92, + 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4, + 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6, + + 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB, + 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539, + 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F, + 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F, + 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF, + 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF, + 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F, + 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x75BF, + 0x75FF,0x761F,0x723F,0x725F,0x769F,0x773F,0x7B7F,0x75BF, + 0x75FF,0x7A3F,0x7AFF,0x7F7F,0x755F,0x75FF,0x763F,0x7A9F, + 0x7ADF,0x7F5F,0x7FBF,0x7FDF,0x75FF,0x761F,0x763F,0x765F, + 0x7A7F,0x7A9F,0x7ABF,0x7EDF,0x7EFF,0x7F3F,0x7F7F,0x7FBF, + 0x7FFF,0x0000,0xFFFF,0x31EC,0x7FE0,0x7C1F,0x7C00,0x001F, + 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7DFF,0x7E9F,0x7BDE,0x7FFC,0x1C40,0x1C81,0x2060,0x2880, + 0x2C80,0x38C1,0x38C1,0x38C1,0x38C1,0x38C1,0x3CC0,0x3CC0, + + 0x38E0,0x38E1,0x4100,0x4500,0x4503,0x4503,0x4D00,0x4522, + 0x4522,0x4D20,0x5121,0x5123,0x5124,0x5520,0x5521,0x5920, + 0x4D62,0x5161,0x5561,0x5565,0x5961,0x5964,0x6160,0x6160, + 0x6161,0x6162,0x6562,0x6982,0x55A2,0x59A6,0x59A1,0x59A2, + 0x59A4,0x61A0,0x61A1,0x65A4,0x69A0,0x69A0,0x69A2,0x6DA0, + 0x71A0,0x5DE6,0x5DE0,0x65E3,0x69E0,0x6DE3,0x71E0,0x71E1, + 0x71E3,0x71C3,0x6E20,0x6E24,0x7221,0x7223,0x7224,0x7226, + 0x7261,0x7263,0x7264,0x7265,0x7266,0x7267,0x72A3,0x72A5, + 0x72A8,0x72A9,0x72AB,0x72C3,0x72C5,0x72C7,0x72C9,0x72C1, + 0x7306,0x7306,0x7308,0x7309,0x730B,0x730C,0x730D,0x730E, + 0x7328,0x732A,0x732B,0x7308,0x774C,0x7B90,0x7BB4,0x7FD9, + 0x7728,0x774B,0x7B8C,0x7FB5,0x7FD9,0x7725,0x772A,0x7B4D, + 0x7B70,0x7FB4,0x7FF9,0x7FFC,0x7FFD,0x7B4A,0x7B4B,0x7B4C, + 0x7B2D,0x7B6E,0x7B6F,0x7B90,0x7BB2,0x7BB3,0x7FD6,0x7FD8, + 0x7BDA,0x7FFE,0x0000,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00, + 0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F, + + 0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7F9F,0x1DD0,0x25F0,0x1DF1, + 0x2213,0x1A14,0x1E17,0x2237,0x2637,0x2657,0x2657,0x1E58, + 0x2278,0x2278,0x2678,0x1E99,0x22B9,0x2AB9,0x2EB9,0x1EBB, + 0x2AD9,0x2ED9,0x1EDB,0x2EDC,0x36DC,0x32DC,0x1EDD,0x26DE, + 0x1EDE,0x2B1B,0x271C,0x271D,0x3B3C,0x2B3D,0x331C,0x1B1E, + 0x26FE,0x2B1E,0x2F1F,0x2F1F,0x1F3F,0x335B,0x373B,0x2F3C, + 0x333C,0x333C,0x2B3E,0x2F3E,0x375E,0x235F,0x2F1F,0x2F5F, + 0x235F,0x1B5F,0x2B7A,0x2F9A,0x339C,0x2B9D,0x339E,0x379F, + 0x379F,0x3F9F,0x3F9F,0x3BDE,0x3B9E,0x2F9F,0x379F,0x3B9F, + 0x439F,0x2B9F,0x379F,0x3B9F,0x3F9F,0x439F,0x479F,0x37BF, + 0x3FDF,0x4BDF,0x4FDF,0x57DF,0x37BF,0x3FDF,0x479E,0x4B9F, + 0x539F,0x47DF,0x4BDF,0x4FDF,0x53DF,0x57DF,0x5BDF,0x5FDF, + 0x63FF,0x57FF,0x5BFF,0x5FFF,0x5BDF,0x63DF,0x6BFF,0x73FF, + 0x7BFF,0x5FFF,0x63FF,0x67FF,0x73FF,0x7BFF,0x5FFF,0x63FF, + 0x67FF,0x6FFF,0x73FF,0x77FF,0x7FBF,0x7FDF,0x57FF,0x5BFF, + 0x5FFF,0x63FF,0x67FF,0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF, + + 0x7BFF,0x7FFF,0x7FFF,0x0000,0xFFFF,0x28ED,0x7FE0,0x7C1F, + 0x7C00,0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F, + 0x701F,0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7FFA,0x1180,0x1580, + 0x15C0,0x19C0,0x1600,0x1A00,0x1A40,0x1E40,0x1E80,0x2280, + 0x1EA0,0x22A0,0x1EC0,0x22C0,0x26C0,0x2300,0x2302,0x2303, + 0x2300,0x2702,0x2B03,0x2720,0x2723,0x2743,0x2744,0x2760, + 0x2761,0x2762,0x2B60,0x2B62,0x2F61,0x3366,0x3380,0x3383, + 0x33A6,0x33A1,0x33A2,0x33C3,0x37C3,0x37C0,0x3762,0x3766, + 0x3781,0x3782,0x3784,0x37A0,0x37A1,0x3BA6,0x3BC1,0x3BC2, + 0x3BC4,0x3BE0,0x3BE3,0x3F87,0x3FA1,0x3FA4,0x3FC1,0x3FE4, + 0x3FE0,0x3FE1,0x3FE3,0x3FE4,0x43E0,0x4BE2,0x4BE4,0x4BE6, + 0x4BE8,0x4BEA,0x53E2,0x53E4,0x53E6,0x53E8,0x53EA,0x53EC, + 0x5BE4,0x5BE6,0x5BE8,0x5BEA,0x5BEC,0x5FE4,0x5FE6,0x5FE8, + 0x5FEA,0x5FEC,0x67E2,0x67E4,0x67E6,0x67E8,0x67EA,0x67EC, + 0x6FE8,0x6FEA,0x6FEC,0x6FEE,0x6FF0,0x73E0,0x73E8,0x73F0, + 0x73F4,0x73F9,0x77E0,0x77E8,0x77F0,0x77F4,0x77F9,0x7BE2, + + 0x7BE6,0x7BEC,0x7BF2,0x7BF5,0x7BF9,0x7FFB,0x7BFC,0x77E0, + 0x77E2,0x77E4,0x77E6,0x77E8,0x7BEA,0x7BED,0x7BF0,0x7BF3, + 0x7BF6,0x7BF9,0x7BFB,0x7FFF,0x0000,0xFFFF,0x0002,0x0000 +}; +static UINT16 bloodwar_mcu_4_16[] = { // Warrior 8 Player 1 + 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x29A9,0x2DCA,0x31EB,0x360C,0x3A0D,0x3A2D,0x3A4D, + 0x3E4E,0x3E6E,0x3E6F,0x426E,0x428E,0x468E,0x468F,0x4AAF, + 0x4AB0,0x46D0,0x4AD0,0x4AF0,0x4AF1,0x4EF1,0x4F11,0x4F12, + 0x5311,0x5312,0x5330,0x5751,0x5752,0x5B73,0x5B74,0x5B93, + 0x5B94,0x6396,0x67D5,0x67D6,0x67D7,0x67D5,0x67D6,0x6BD6, + 0x6BD7,0x6BD9,0x6BD5,0x6BD6,0x6BD7,0x6BD6,0x6FD6,0x6FD7, + 0x6FD9,0x73D7,0x73D8,0x73DA,0x7BD8,0x7BF9,0x7BFA,0x7BFB, + 0x7BFC,0x7FFB,0x7FFB,0x7FFC,0x7FFD,0x7FFB,0x7FFD,0x7FFD, + 0x7FFE,0x1946,0x1965,0x2187,0x21A5,0x25A7,0x29C7,0x29E8, + 0x360A,0x362B,0x3A8C,0x426D,0x428C,0x46EF,0x4ACF,0x5350, + 0x5352,0x5752,0x5753,0x5791,0x5B53,0x5B73,0x5FB3,0x6374, + 0x63B3,0x63B4,0x63D4,0x67B4,0x67D4,0x67D6,0x6FF6,0x6FF7, + 0x73F7,0x0882,0x0CA3,0x10E3,0x10E4,0x1103,0x1104,0x1524, + 0x1945,0x1965,0x1D65,0x1985,0x1986,0x21A6,0x21A7,0x21C6, + + 0x25A6,0x29E9,0x2E09,0x2E28,0x2E29,0x364B,0x3A4D,0x3E8C, + 0x42CC,0x4B0F,0x4EF2,0x5BD3,0x67F7,0x6BF5,0x73F8,0x77FB, + 0x7FFC,0x1982,0x1DA4,0x21C5,0x25E6,0x2A07,0x2E27,0x2E47, + 0x3267,0x36A8,0x3AC9,0x3EEA,0x3F0A,0x3F2B,0x434C,0x476C, + 0x478C,0x4F8E,0x4FAD,0x4FCE,0x53EF,0x53F0,0x57F0,0x5BF0, + 0x5BF1,0x5FF3,0x5FF4,0x5FF2,0x63F2,0x63F4,0x67F5,0x6BF6, + 0x73F8,0x1E24,0x1E44,0x2265,0x2287,0x22A7,0x26C8,0x26E8, + 0x2B09,0x2F2A,0x3349,0x3F6C,0x438D,0x47AE,0x53D2,0x57F2, + 0x5FF3,0x0C09,0x100A,0x180C,0x1C0D,0x200E,0x240F,0x2810, + 0x3052,0x3473,0x3CB5,0x44F7,0x4D39,0x557B,0x5DBD,0x65FE, + 0x7BBE,0x10C3,0x1905,0x2146,0x2546,0x2988,0x31C8,0x35C9, + 0x39EB,0x3E0C,0x422C,0x464E,0x56F2,0x5733,0x5753,0x5B33, + 0x5B52,0x10E3,0x0CA3,0x10E4,0x1103,0x1104,0x1524,0x1946, + 0x21A5,0x2A08,0x322A,0x366A,0x42EE,0x4F0F,0x5FB2,0x5FB3, + 0x63D3,0x3D71,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300, + 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5, + + 0x7BDE,0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108 +}; +static UINT16 bloodwar_mcu_4_17[] = { // Warrior 8 Player 2 + 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x296A,0x2D8B,0x31AC,0x35CD,0x35EF,0x39F0,0x3A10, + 0x3DD1,0x3E11,0x3E12,0x4230,0x4231,0x4630,0x4631,0x4671, + 0x4673,0x4674,0x4A73,0x4A93,0x4AB3,0x4AB4,0x4E74,0x4E75, + 0x52B3,0x52B4,0x52D3,0x56F4,0x56F5,0x5B16,0x5B17,0x5B36, + 0x5B37,0x6339,0x6778,0x6779,0x677A,0x6778,0x6779,0x6B79, + 0x6B7A,0x6B7C,0x6B78,0x6B79,0x6B7A,0x6B79,0x6F79,0x6F7A, + 0x6F7C,0x737A,0x737B,0x737D,0x7B7B,0x7B9C,0x7B9D,0x7B9E, + 0x7B9F,0x7F9E,0x7F9E,0x7F9F,0x7FBF,0x7F9E,0x7FBF,0x7FBF, + 0x7FBF,0x18E9,0x1908,0x212A,0x2148,0x254A,0x296A,0x298B, + 0x35AD,0x35CE,0x3A2F,0x4210,0x422F,0x4692,0x4A72,0x52D3, + 0x52F5,0x56F5,0x56F6,0x5715,0x5AF6,0x5B16,0x5F36,0x6317, + 0x6356,0x6357,0x6377,0x6757,0x6777,0x6779,0x6F99,0x6F9A, + 0x739A,0x0825,0x0C46,0x1086,0x1087,0x10A6,0x10A7,0x14C7, + 0x18E8,0x1908,0x1D08,0x1928,0x1929,0x2149,0x214A,0x2169, + + 0x2549,0x298C,0x2DAC,0x2DCB,0x2DCC,0x35EE,0x39F0,0x3E2F, + 0x426F,0x4AB2,0x4E95,0x5B76,0x679A,0x6B98,0x739B,0x779E, + 0x7F9F,0x1982,0x1DA4,0x21C5,0x25E6,0x2A07,0x2E27,0x2E47, + 0x3267,0x36A8,0x3AC9,0x3EEA,0x3F0A,0x3F2B,0x434C,0x476C, + 0x478C,0x4F8E,0x4FAD,0x4FCE,0x53EF,0x53F0,0x57F0,0x5BF0, + 0x5BF1,0x5FF3,0x5FF4,0x5FF2,0x63F2,0x63F4,0x67F5,0x6BF6, + 0x739B,0x2810,0x2C31,0x3473,0x3894,0x3CB5,0x40D6,0x44F7, + 0x4918,0x4D39,0x515A,0x557B,0x599C,0x5DBD,0x65FE,0x6A1F, + 0x767F,0x0C09,0x100A,0x180C,0x1C0D,0x200E,0x240F,0x2810, + 0x3052,0x3473,0x3CB5,0x44F7,0x4D39,0x557B,0x5DBD,0x65FE, + 0x7BBE,0x10C3,0x1905,0x2146,0x2546,0x2988,0x31C8,0x35C9, + 0x39EB,0x3E0C,0x422C,0x464E,0x56F2,0x5733,0x5753,0x5B33, + 0x5B52,0x10E3,0x0CA3,0x10E4,0x1103,0x1104,0x1524,0x1946, + 0x21A5,0x2A08,0x322A,0x366A,0x42EE,0x4F0F,0x5FB2,0x5FB3, + 0x63D3,0x3D71,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300, + 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5, + + 0x7BDE,0xFFFF,0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108 +}; +static UINT16 bloodwar_mcu_4_18[] = { // Warrior 2 Player 2 + 0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x1524,0x0CC2,0x0CE2,0x0CE3,0x10E3,0x1103,0x14E3, + 0x1544,0x1946,0x1966,0x2166,0x2167,0x2187,0x2567,0x25A7, + 0x29E8,0x31EA,0x320A,0x3A4B,0x3A4D,0x3A6B,0x3E4D,0x3E6B, + 0x3E6D,0x3E6E,0x3E8D,0x426E,0x428E,0x468F,0x46AE,0x46CF, + 0x46EE,0x46EF,0x4710,0x4AEF,0x4EF0,0x4F10,0x4F11,0x52F1, + 0x5310,0x5312,0x5313,0x5332,0x5732,0x5753,0x5B33,0x5B34, + 0x5B53,0x5F95,0x5FB5,0x5FD4,0x63B4,0x63B5,0x63B6,0x63D5, + 0x67F7,0x6FD7,0x6FF7,0x6FF8,0x6FF7,0x6FF8,0x73FA,0x7BFC, + 0x7FFC,0x0440,0x0080,0x0940,0x0D80,0x11C0,0x1200,0x1240, + 0x1280,0x12E0,0x1300,0x1301,0x1761,0x1B81,0x1BC2,0x1BE1, + 0x1E01,0x1E80,0x1EA0,0x22C0,0x22E1,0x2361,0x2381,0x2382, + 0x2782,0x27C2,0x27E4,0x2BC3,0x2FC4,0x2FE5,0x33E5,0x33E6, + 0x37E8,0x1520,0x1500,0x1940,0x1960,0x1D80,0x25E1,0x2DE3, + 0x3242,0x3262,0x3683,0x3EC3,0x3EC4,0x3F23,0x42A5,0x42C7, + + 0x4765,0x4B08,0x4B46,0x4B66,0x53C7,0x5769,0x57C7,0x5BC8, + 0x5BCA,0x5FC9,0x5FE8,0x5FE9,0x6FEB,0x73ED,0x77EF,0x7FF4, + 0x7FF8,0x2E0A,0x320A,0x3A4E,0x3A6D,0x3E4D,0x3E6D,0x3E6E, + 0x426E,0x46CF,0x5310,0x5312,0x5332,0x5B94,0x5FB6,0x6797, + 0x67D6,0x6BD8,0x6BDA,0x6BF9,0x6BFA,0x6FDC,0x6FFA,0x6FFB, + 0x73FB,0x73FC,0x7BFB,0x7BFC,0x7BFD,0x7BFE,0x7FFD,0x7FFE, + 0x7FFF,0x1504,0x10E4,0x1524,0x1945,0x1965,0x1D67,0x1D87, + 0x2587,0x25A8,0x29E8,0x2A07,0x2E08,0x324A,0x3268,0x3269, + 0x3A68,0x3A8B,0x3EAB,0x42CB,0x4F2E,0x5330,0x534F,0x5352, + 0x57B1,0x5FB3,0x5FB4,0x67F3,0x6BF4,0x6BF5,0x6BF8,0x6FF7, + 0x73F9,0x0461,0x0441,0x0862,0x0882,0x0CC2,0x0CC3,0x0CE2, + 0x0CE3,0x10C3,0x10E3,0x10E4,0x1103,0x1104,0x1123,0x14E4, + 0x1524,0xFFFF,0x390F,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A, + 0x181C,0x1C1F,0x241F,0x0BE0,0x3BE0,0x53E0,0x381F,0x4C1F, + 0x65FF,0x7BDE,0xFFFF,0x41D3,0x0013,0x281F,0x581F,0x6DFF, + 0x2243,0x0000,0x0340,0x4210,0x4A52,0x5294,0x5AD6,0x6318, + + 0x4409,0x7BC0,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0, + 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0, + 0x7FF6,0x7FFC,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809, + 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB, + 0x7DBD,0x7EBD,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013, + 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F, + 0x681F,0x6DFF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F, + 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7E5F,0x7B5F,0x7FFF,0x0000,0x7FE0,0x7C1F,0x0B58,0x13BB, + 0x1FFF,0x33FF,0x43FF,0x47FF,0x4FFF,0x57FF,0x5FFF,0x67FF, + 0x6FFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200, + 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC, + 0x5FF3,0x6FF8,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60, + 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED, + 0x77EE,0x77F5,0x7FFF,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409, + 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15, + + 0x7EBA,0x7F5D,0x7FFF,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8, + 0x5BC4,0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7, + 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0, + 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0, + 0x13E0,0x1DA3,0x2243,0x41D3,0x0842,0x1084,0x18C6,0x2108, + 0x294A,0x318C,0x39CE,0x03A0,0x23E0,0x37E0,0x3FE0,0x4FE0, + 0x67ED,0x77EE,0x7FFF,0xFFFF,0x0003,0x0000,0x4232,0x56F8 +}; +static UINT16 bloodwar_mcu_4_19[] = { // Warrior 2 Player 1 + 0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x1524,0x0CC2,0x0CE2,0x0CE3,0x10E3,0x1103,0x14E3, + 0x1544,0x1946,0x1966,0x2166,0x2167,0x2187,0x2567,0x25A7, + 0x29E8,0x2A05,0x2E05,0x2E45,0x3266,0x3285,0x3285,0x3284, + 0x32A5,0x36C5,0x3AE1,0x3EC1,0x3EE2,0x4704,0x4724,0x4745, + 0x4764,0x4765,0x4786,0x4B65,0x4F66,0x4F86,0x4F87,0x5367, + 0x5386,0x57A8,0x57A9,0x57C8,0x5BC8,0x5BE9,0x5FC9,0x5FCA, + 0x5FE9,0x63EC,0x63EC,0x63EB,0x67EB,0x6BEB,0x6BEE,0x6BED, + 0x6FEF,0x73EE,0x73EE,0x73EF,0x73EE,0x77EF,0x7BF3,0x7FF5, + 0x7FF6,0x0440,0x0080,0x0940,0x0D80,0x11C0,0x1200,0x1240, + 0x1280,0x12E0,0x1300,0x1301,0x1761,0x1B81,0x1BC2,0x1BE1, + 0x1E01,0x1E80,0x1EA0,0x22C0,0x22E1,0x2361,0x2381,0x2382, + 0x2782,0x27C2,0x27E4,0x2BC3,0x2FC4,0x2FE5,0x33E5,0x33E6, + 0x37E8,0x1520,0x1500,0x1940,0x1960,0x1D80,0x25E1,0x2DE3, + 0x3242,0x3262,0x3683,0x3EC3,0x3EC4,0x3F23,0x42A5,0x42C7, + + 0x4765,0x4B08,0x4B46,0x4B66,0x53C7,0x5769,0x57C7,0x5BC8, + 0x5BCA,0x5FC9,0x5FE8,0x5FE9,0x6FEB,0x73ED,0x77EF,0x7FF4, + 0x7FF8,0x2A61,0x2E81,0x32A3,0x36C2,0x3AC2,0x3EE3,0x42E3, + 0x4303,0x4324,0x4B45,0x4F67,0x4F88,0x57A9,0x5BCD,0x63ED, + 0x63EE,0x6BEE,0x6BF0,0x6BEF,0x6BF0,0x6FF2,0x6FF0,0x6FF1, + 0x73F1,0x73F2,0x7BF2,0x7BF3,0x7BF4,0x7BF7,0x7FFC,0x7FFC, + 0x7FFC,0x1504,0x10E4,0x1524,0x1945,0x1965,0x1D67,0x1D87, + 0x2587,0x25A8,0x29E8,0x2A07,0x2E08,0x324A,0x3268,0x3269, + 0x3A68,0x32C0,0x36E0,0x3B00,0x3F20,0x4343,0x4B63,0x4F87, + 0x53A6,0x57C7,0x5BE9,0x5FE7,0x63E8,0x63E9,0x63EC,0x67EC, + 0x6BED,0x0461,0x0441,0x0862,0x0882,0x0CC2,0x0CC3,0x0CE2, + 0x0CE3,0x10C3,0x10E3,0x10E4,0x1103,0x1104,0x1123,0x14E4, + 0x1524,0xFFFF,0x390F,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A, + 0x181C,0x1C1F,0x241F,0x0BE0,0x3BE0,0x53E0,0x381F,0x4C1F, + 0x65FF,0x7BDE,0xFFFF,0x41D3,0x0013,0x281F,0x581F,0x6DFF, + 0x2243,0x0000,0x0340,0x4210,0x4A52,0x5294,0x5AD6,0x6318, + + 0x4409,0x7BC0,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0, + 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0, + 0x7FF6,0x7FFC,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809, + 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB, + 0x7DBD,0x7EBD,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013, + 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F, + 0x681F,0x6DFF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F, + 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7E5F,0x7B5F,0x7FFF,0x0000,0x7FE0,0x7C1F,0x0B58,0x13BB, + 0x1FFF,0x33FF,0x43FF,0x47FF,0x4FFF,0x57FF,0x5FFF,0x67FF, + 0x6FFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200, + 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC, + 0x5FF3,0x6FF8,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60, + 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED, + 0x77EE,0x77F5,0x7FFF,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409, + 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15, + + 0x7EBA,0x7F5D,0x7FFF,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8, + 0x5BC4,0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7, + 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0, + 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0, + 0x13E0,0x1DA3,0x2243,0x41D3,0x0842,0x1084,0x18C6,0x2108, + 0x294A,0x318C,0x39CE,0x03A0,0x23E0,0x37E0,0x3FE0,0x4FE0, + 0x67ED,0x77EE,0x7FFF,0xFFFF,0x0005,0x0000,0x4232,0x56F8 +}; +static UINT16 bloodwar_mcu_4_1a[] = { // Warrior 3 Player 1 + 0x0005,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x08A0,0x0D02,0x1142,0x19C2,0x3EEB,0x430D,0x4B6C, + 0x4F4F,0x4F50,0x432A,0x368A,0x328A,0x3AE9,0x3689,0x3268, + 0x2A26,0x2A27,0x3AE9,0x4B4E,0x3269,0x3EEB,0x3AA8,0x19A3, + 0x08E2,0x21E5,0x2E47,0x3F2A,0x4B4F,0x3F0B,0x3AEB,0x36A8, + 0x25E3,0x1DC6,0x2606,0x2E46,0x36AA,0x2E66,0x36A8,0x36CA, + 0x32A9,0x2604,0x15C2,0x1182,0x0D42,0x1583,0x1162,0x0D22, + 0x15A2,0x19E3,0x11C2,0x1E45,0x1A04,0x2204,0x2E68,0x25E4, + 0x1DA4,0x3268,0x3AC9,0x4B2D,0x36A9,0x430C,0x2A46,0x534F, + 0x532F,0x42EA,0x2A26,0x1964,0x4F8E,0x4F8D,0x4B6C,0x474D, + 0x434A,0x3F29,0x3AE8,0x3B08,0x474B,0x3F09,0x4349,0x4B6B, + 0x1944,0x1D44,0x25C7,0x2E08,0x3AEA,0x3688,0x3247,0x3A2A, + 0x3AC8,0x3689,0x3EAA,0x426E,0x10C3,0x2603,0x1503,0x1925, + 0x42CA,0x42EB,0x3F2A,0x25E3,0x42A8,0x534E,0x1924,0x46CC, + 0x4B0D,0x2EA4,0x1DE4,0x2605,0x2E67,0x3ACA,0x3AAA,0x2A45, + + 0x1185,0x2E46,0x1122,0x0862,0x08C2,0x1562,0x2A25,0x2A26, + 0x2624,0x472E,0x3688,0x4B4D,0x15A3,0x21E4,0x4F4E,0x4F6E, + 0x4F6D,0x5F34,0x5F36,0x5F36,0x5F56,0x4ED1,0x46AF,0x426E, + 0x2E26,0x21C6,0x324A,0x5B14,0x6777,0x6356,0x5F15,0x1380, + 0x1380,0x0F60,0x0F80,0x0F80,0x0F20,0x1300,0x0EE0,0x0F00, + 0x1320,0x0E82,0x1300,0x0A02,0x0DE2,0x0E02,0x09A2,0x0DC2, + 0x0D82,0x0D85,0x0E22,0x0E42,0x1262,0x1720,0x0EE0,0x0F00, + 0x1320,0x0F20,0x0F60,0x1623,0x1AA4,0x1683,0x1283,0x12A3, + 0x0E62,0x15E3,0x13A0,0x0B60,0x1282,0x12A2,0x16E0,0x1760, + 0x1760,0x1B80,0x1780,0x1F80,0x1B80,0x1B60,0x1AE0,0x1B60, + 0x1720,0x5FE5,0x5BE5,0x5BE5,0x5BE4,0x57E4,0x5BE4,0x4FA4, + 0x4B84,0x4B84,0x4F85,0x53A4,0x4B85,0x53A6,0x57C5,0x4366, + 0x4B87,0x4BA7,0x4766,0x2EC4,0x2EA6,0x2643,0x3B07,0x32A3, + 0x36C3,0x57E8,0x57CA,0x4FC4,0x32E3,0x32E4,0x32C3,0x2263, + 0x2AA3,0x2E91,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0, + 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC, + + 0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,0x46E0, + 0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,0x7FFC, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,0x4009, + 0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,0x7EBD, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,0x181C, + 0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,0x6DFF, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,0x401F, + 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B5F, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,0x1358, + 0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,0x77FF, + 0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,0x0260, + 0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,0x6FF8, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300, + 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5, + 0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407, + 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D, + + 0x7BDE,0x3408,0x3C0F,0x4813,0x4C12,0x5413,0x5C0F,0x680D, + 0x700A,0x7484,0x7900,0x7DA0,0x7ECD,0x7F6D,0x7FF5,0x7F7E, + 0x7BDE,0x240C,0x280C,0x2C0C,0x340C,0x380C,0x3C0C,0x400C, + 0x440E,0x4810,0x5012,0x5413,0x400E,0x440E,0x4C0E,0x284F, + 0x2C4E,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6, + 0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA, + 0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0, + 0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6, + 0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09, + 0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD, + 0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A, + 0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F, + 0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F, + 0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F, + 0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5, + 0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF, + + 0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200, + 0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3, + 0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0, + 0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE, + 0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07, + 0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA, + 0x7F5D,0x7BDE,0x0216,0x0257,0x12D8,0x2718,0x2FB8,0x3FB9, + 0x47FA,0x4FFC,0x53FF,0x5BFF,0x5BFF,0x67FE,0x6FFF,0x73DF, + 0x7BDF,0x7FFF,0x01B2,0x01F4,0x0215,0x0237,0x0258,0x027A, + 0x029B,0x02DB,0x02FA,0x033A,0x035B,0x029B,0x02DD,0x031F, + 0x0210,0x0215,0xFFFF,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724, + 0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3, + 0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0, + 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0, + 0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809, + 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB, + + 0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013, + 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F, + 0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F, + 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3, + 0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF, + 0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200, + 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC, + 0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60, + 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED, + 0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409, + 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15, + 0x7EBA,0x7F5D,0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0, + 0x4FC0,0x57C0,0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3, + 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0, + 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0, + + 0x13E0,0x1DA3,0x2243,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1, + 0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0, + 0x77F3,0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00, + 0x36A0,0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2, + 0x7FF0,0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x3809,0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016, + 0x70FB,0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0013,0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F, + 0x581F,0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x301F,0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F, + 0x7C5F,0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F, + 0x02B3,0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF, + 0x5FFF,0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0200,0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7, + 0x47EC,0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0E60,0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0, + + 0x67ED,0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05, + 0x4409,0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF, + 0x7E15,0x7EBA,0x7F5D,0x7BDE,0x19B7,0x21DA,0x31BC,0x3D9E, + 0x499E,0x511D,0x5CFE,0x60DF,0x68BF,0x707F,0x741F,0x7C1F, + 0x7E7F,0x7F5F,0x7F9F,0x7FFF,0x018C,0x018E,0x018F,0x0191, + 0x0192,0x0194,0x0195,0x2597,0x2998,0x3599,0x3D99,0x0195, + 0x0999,0x1199,0x21CF,0x25D4,0xFFFF,0x0005,0x0000,0x4232 +}; +static UINT16 bloodwar_mcu_4_1b[] = { // Warrior 3 Player 2 + 0x0005,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C, + 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C, + 0x7BDE,0x08A0,0x0D02,0x1142,0x19C2,0x3EEB,0x430D,0x4B6C, + 0x4F4F,0x4F50,0x432A,0x368A,0x328A,0x3AE9,0x3689,0x3268, + 0x2A26,0x2A27,0x3AE9,0x4B4E,0x3269,0x3EEB,0x3AA8,0x19A3, + 0x08E2,0x21E5,0x2E47,0x3F2A,0x4B4F,0x3F0B,0x3AEB,0x36A8, + 0x25E3,0x1DC6,0x2606,0x2E46,0x36AA,0x2E66,0x36A8,0x36CA, + 0x32A9,0x2604,0x15C2,0x1182,0x0D42,0x1583,0x1162,0x0D22, + 0x15A2,0x19E3,0x11C2,0x1E45,0x1A04,0x2204,0x2E68,0x25E4, + 0x1DA4,0x3268,0x3AC9,0x4B2D,0x36A9,0x430C,0x2A46,0x534F, + 0x532F,0x42EA,0x2A26,0x1964,0x4F8E,0x4F8D,0x4B6C,0x474D, + 0x434A,0x3F29,0x3AE8,0x3B08,0x474B,0x3F09,0x4349,0x4B6B, + 0x1944,0x1D44,0x25C7,0x2E08,0x3AEA,0x3688,0x3247,0x3A2A, + 0x3AC8,0x3689,0x3EAA,0x426E,0x10C3,0x2603,0x1503,0x1925, + 0x42CA,0x42EB,0x3F2A,0x25E3,0x42A8,0x534E,0x1924,0x46CC, + 0x4B0D,0x2EA4,0x1DE4,0x2605,0x2E67,0x3ACA,0x3AAA,0x2A45, + + 0x1185,0x2E46,0x1122,0x0862,0x08C2,0x1562,0x2A25,0x2A26, + 0x2624,0x472E,0x3688,0x4B4D,0x15A3,0x21E4,0x4F4E,0x4F6E, + 0x4F6D,0x5F34,0x5F36,0x5F36,0x5F56,0x4ED1,0x46AF,0x426E, + 0x2E26,0x21C6,0x324A,0x5B14,0x6777,0x6356,0x5F15,0x036E, + 0x036F,0x032D,0x034D,0x034E,0x030C,0x02ED,0x02CC,0x02EC, + 0x030D,0x0289,0x02EE,0x0207,0x01E7,0x0207,0x09A2,0x0DC2, + 0x0D82,0x0D85,0x0227,0x0249,0x0269,0x030F,0x02CD,0x02ED, + 0x030E,0x030D,0x032E,0x0228,0x02AB,0x028A,0x028A,0x02AA, + 0x0269,0x01E8,0x036E,0x032D,0x0289,0x02A9,0x02CE,0x0332, + 0x0331,0x0351,0x0351,0x0350,0x0350,0x0330,0x02D1,0x0332, + 0x0310,0x5FE5,0x5BE5,0x5BE5,0x5BE4,0x57E4,0x5BE4,0x4FA4, + 0x4B84,0x4B84,0x4F85,0x53A4,0x4B85,0x53A6,0x57C5,0x4366, + 0x4B87,0x4BA7,0x4766,0x2EC4,0x2EA6,0x2643,0x3B07,0x32A3, + 0x36C3,0x57E8,0x57CA,0x4FC4,0x32E3,0x32E4,0x32C3,0x2263, + 0x2AA3,0x2E91,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0, + 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC, + + 0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,0x46E0, + 0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,0x7FFC, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,0x4009, + 0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,0x7EBD, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,0x181C, + 0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,0x6DFF, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,0x401F, + 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B5F, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,0x1358, + 0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,0x77FF, + 0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,0x0260, + 0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,0x6FF8, + 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300, + 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5, + 0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407, + 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D, + + 0x7BDE,0x3408,0x3C0F,0x4813,0x4C12,0x5413,0x5C0F,0x680D, + 0x700A,0x7484,0x7900,0x7DA0,0x7ECD,0x7F6D,0x7FF5,0x7F7E, + 0x7BDE,0x240C,0x280C,0x2C0C,0x340C,0x380C,0x3C0C,0x400C, + 0x440E,0x4810,0x5012,0x5413,0x400E,0x440E,0x4C0E,0x284F, + 0x2C4E,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6, + 0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA, + 0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0, + 0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6, + 0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09, + 0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD, + 0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A, + 0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F, + 0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F, + 0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F, + 0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5, + 0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF, + + 0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200, + 0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3, + 0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0, + 0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE, + 0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07, + 0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA, + 0x7F5D,0x7BDE,0x0216,0x0257,0x12D8,0x2718,0x2FB8,0x3FB9, + 0x47FA,0x4FFC,0x53FF,0x5BFF,0x5BFF,0x67FE,0x6FFF,0x73DF, + 0x7BDF,0x7FFF,0x01B2,0x01F4,0x0215,0x0237,0x0258,0x027A, + 0x029B,0x02DB,0x02FA,0x033A,0x035B,0x029B,0x02DD,0x031F, + 0x0210,0x0215,0xFFFF,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724, + 0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3, + 0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0, + 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0, + 0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809, + 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB, + + 0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013, + 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F, + 0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F, + 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F, + 0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3, + 0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF, + 0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200, + 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC, + 0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60, + 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED, + 0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409, + 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15, + 0x7EBA,0x7F5D,0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0, + 0x4FC0,0x57C0,0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3, + 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0, + 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0, + + 0x13E0,0x1DA3,0x2243,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1, + 0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0, + 0x77F3,0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00, + 0x36A0,0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2, + 0x7FF0,0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x3809,0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016, + 0x70FB,0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0013,0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F, + 0x581F,0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x301F,0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F, + 0x7C5F,0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F, + 0x02B3,0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF, + 0x5FFF,0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0200,0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7, + 0x47EC,0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00, + 0x0E60,0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0, + + 0x67ED,0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05, + 0x4409,0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF, + 0x7E15,0x7EBA,0x7F5D,0x7BDE,0x19B7,0x21DA,0x31BC,0x3D9E, + 0x499E,0x511D,0x5CFE,0x60DF,0x68BF,0x707F,0x741F,0x7C1F, + 0x7E7F,0x7F5F,0x7F9F,0x7FFF,0x018C,0x018E,0x018F,0x0191, + 0x0192,0x0194,0x0195,0x2597,0x2998,0x3599,0x3D99,0x0195, + 0x0999,0x1199,0x21CF,0x25D4,0xFFFF,0x0004,0xCE4A,0x0004 +}; + +// --- tilemap data --- +// tile data (ff means no tiles) followed by routine index (end marker: 0xff00) +static UINT16 bloodwar_mcu_4_1c[] = { // Warrior 8 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0D00,0xFF06, + 0x01BF,0xFF06,0x00FF,0xFF06,0x0008,0x2C01,0xFF06,0x0001, + 0xFF05,0x0002,0x2C02,0xFF06,0x0001,0xFF05,0x0002,0x2C55, + 0xFF06,0x0001,0x2C58,0xFF06,0x0008,0xFF06,0x0007,0xFF05, + 0x0007,0x2C05,0xFF05,0x0007,0x2C59,0xFF06,0x0007,0xFF06, + 0x0007,0xFF05,0x0007,0x2C0D,0xFF05,0x0007,0x2C61,0xFF06, + 0x0007,0xFF05,0x000F,0x2C15,0xFF05,0x000F,0x2C69,0xFF05, + 0x000F,0x2C25,0xFF05,0x000F,0x2C79,0xFF05,0x000F,0x2C35, + 0xFF05,0x000F,0x2C89,0xFF05,0x000F,0x2C45,0xFF05,0x000F, + 0x2C99,0xFF04,0x0002,0xFF09,0x0007,0x28D0,0xFF04,0x0000, + 0xFF05,0x0007,0x28A9,0xFF05,0x000F,0x28C1,0xFF04,0x0002, + 0xFF09,0x0007,0x28E0,0xFF04,0x0000,0xFF05,0x0007,0x28B1, + 0xFF05,0x000F,0x28D1,0xFF04,0x0002,0xFF09,0x0007,0x28F0, + 0xFF04,0x0000,0xFF05,0x0007,0x28B9,0xFF05,0x000F,0x28E1, + 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0E00,0xFF06, + 0x01BF,0xFF06,0x001F,0xFF06,0x0001,0xFF05,0x0002,0x2401, + + 0xFF06,0x001A,0xFF06,0x0001,0xFF05,0x0003,0x2404,0xFF06, + 0x0019,0xFF06,0x0001,0xFF05,0x0004,0x2409,0xFF06,0x0018, + 0xFF06,0x0001,0xFF05,0x0005,0x240E,0xFF06,0x0011,0xFF05, + 0x0003,0x2474,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008, + 0x2414,0xFF06,0x000A,0xFF05,0x0007,0x2478,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0008,0x241D,0xFF06,0x000A,0xFF05, + 0x0007,0x2480,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0009, + 0x2426,0xFF06,0x0009,0xFF05,0x0007,0x2488,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0009,0x2430,0xFF06,0x0008,0xFF05, + 0x0008,0x2490,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x000A, + 0x243A,0xFF06,0x0007,0xFF05,0x0008,0x2499,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x000A,0x2445,0xFF06,0x0007,0xFF05, + 0x0008,0x24A2,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008, + 0x2450,0xFF06,0x0009,0xFF05,0x0008,0x24AB,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0008,0x2459,0xFF06,0x0009,0xFF05, + 0x0008,0x24B4,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008, + + 0x2462,0xFF06,0x0009,0xFF05,0x0008,0x24BD,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0008,0x246B,0xFF06,0x0008,0xFF05, + 0x0009,0x48C6,0xFF06,0x0001,0xFF05,0x001F,0x48C6,0xFF06, + 0x003F,0xFF08,0xFF02,0x0002,0xFF03,0x0400,0xFF01,0x0B00, + 0xFF06,0x01BF,0xFF06,0x005F,0xFF06,0x000A,0xFF05,0x0001, + 0x3001,0xFF06,0x0012,0xFF06,0x0008,0xFF05,0x0004,0x3003, + 0xFF06,0x0011,0xFF06,0x0006,0xFF05,0x0008,0x3008,0xFF06, + 0x000F,0xFF06,0x0004,0xFF05,0x000A,0x3011,0xFF06,0x000F, + 0xFF06,0x0004,0xFF05,0x000B,0x301C,0xFF05,0x0009,0x3461, + 0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x000B,0x3028,0xFF05, + 0x0009,0x346B,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0015, + 0x3034,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0015,0x304A, + 0xFF06,0x0004,0xFF06,0x0004,0xFF0A,0x0015,0x3060,0xFF06, + 0x0004,0xFF06,0x00BF,0xFF08,0xFF02,0x0003,0xFF03,0x0400, + 0xFF01,0x0B00,0xFF06,0x01BF,0xFF06,0x003F,0xFF06,0x000E, + 0xFF05,0x0002,0x34D5,0xFF06,0x0001,0xFF05,0x0002,0x3880, + + 0xFF06,0x0008,0xFF06,0x000E,0xFF05,0x0002,0x34D8,0xFF06, + 0x0000,0xFF05,0x0004,0x3883,0xFF06,0x0007,0xFF06,0x000E, + 0xFF05,0x0002,0x34DB,0xFF06,0x0000,0xFF05,0x0004,0x3888, + 0xFF06,0x0007,0xFF06,0x0011,0xFF05,0x0006,0x388D,0xFF06, + 0x0006,0xFF06,0x0010,0xFF05,0x0007,0x3894,0xFF06,0x0006, + 0xFF06,0x000E,0xFF05,0x000A,0x389C,0xFF06,0x0005,0xFF06, + 0x000F,0xFF05,0x0009,0x38A7,0xFF06,0x0005,0xFF06,0x000E, + 0xFF05,0x000A,0x38B1,0xFF06,0x0004,0xFF06,0x000E,0xFF05, + 0x000A,0x38BD,0xFF06,0x0004,0xFF06,0x000E,0xFF05,0x000A, + 0x38C9,0xFF06,0x0004,0xFF06,0x00BF,0xFF00,0xFF08,0xFF02 +}; +static UINT16 bloodwar_mcu_4_1d[] = { // Warrior 2 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0000,0xFF06, + 0x01BF,0xFF06,0x0003,0x4401,0xFF06,0x0002,0x4401,0xFF05, + 0x0001,0x340B,0xFF06,0x0000,0x4401,0xFF06,0x0005,0xFF04, + 0x0002,0x4401,0xFF06,0x0000,0xFF04,0x0000,0xFF05,0x0002, + 0x341F,0xFF04,0x0002,0x4401,0xFF06,0x0002,0x4401,0xFF04, + 0x0000,0xFF06,0x0002,0xFF06,0x0003,0x4402,0xFF06,0x0002, + 0x4402,0xFF05,0x0001,0x340B,0xFF06,0x0000,0x4402,0xFF06, + 0x0005,0xFF04,0x0002,0x4402,0xFF06,0x0000,0xFF04,0x0000, + 0xFF05,0x0002,0x341F,0xFF04,0x0002,0x4402,0xFF06,0x0002, + 0x4402,0xFF04,0x0000,0xFF06,0x0002,0xFF06,0x0002,0xFF05, + 0x0001,0x4403,0xFF06,0x0001,0xFF05,0x0001,0x4403,0xFF05, + 0x0001,0x340B,0xFF05,0x0001,0x4403,0xFF06,0x0005,0xFF04, + 0x0002,0xFF09,0x0001,0x4404,0xFF04,0x0000,0xFF05,0x0002, + 0x341F,0xFF04,0x0002,0xFF09,0x0001,0x4404,0xFF06,0x0001, + 0xFF09,0x0001,0x4404,0xFF04,0x0000,0xFF06,0x0001,0xFF06, + 0x0002,0xFF05,0x0001,0x4005,0xFF06,0x0001,0xFF05,0x0001, + + 0x4005,0xFF05,0x0001,0x340B,0xFF05,0x0001,0x4005,0xFF06, + 0x0005,0xFF04,0x0002,0xFF09,0x0001,0x4006,0xFF04,0x0000, + 0xFF05,0x0002,0x341F,0xFF04,0x0002,0xFF09,0x0001,0x4006, + 0xFF06,0x0001,0xFF09,0x0001,0x4006,0xFF04,0x0000,0xFF06, + 0x0001,0xFF06,0x0002,0xFF05,0x0001,0x4007,0xFF06,0x0001, + 0xFF05,0x0001,0x4007,0xFF05,0x0001,0x340D,0xFF05,0x0001, + 0x4007,0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x4008, + 0xFF04,0x0000,0xFF05,0x0002,0x3422,0xFF04,0x0002,0xFF09, + 0x0001,0x4008,0xFF06,0x0001,0xFF09,0x0001,0x4008,0xFF04, + 0x0000,0xFF06,0x0001,0xFF06,0x0002,0xFF05,0x0001,0x4409, + 0xFF06,0x0001,0xFF05,0x0001,0x4409,0xFF05,0x0001,0x340F, + 0xFF05,0x0001,0x4409,0xFF06,0x0005,0xFF04,0x0002,0xFF09, + 0x0001,0x440A,0xFF04,0x0000,0xFF05,0x0002,0x3425,0xFF04, + 0x0002,0xFF09,0x0001,0x440A,0xFF06,0x0001,0xFF09,0x0001, + 0x440A,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0008,0xFF05, + 0x0001,0x3411,0xFF06,0x0009,0xFF05,0x0002,0x3428,0xFF06, + + 0x0007,0xFF06,0x0008,0xFF05,0x0001,0x3413,0xFF06,0x0009, + 0xFF05,0x0002,0x342B,0xFF06,0x0007,0xFF06,0x0008,0xFF05, + 0x0001,0x3415,0xFF06,0x0009,0xFF05,0x0002,0x342E,0xFF06, + 0x0007,0xFF06,0x0006,0x383E,0xFF06,0x0000,0xFF05,0x0001, + 0x3417,0x383D,0xFF06,0x0007,0x383E,0xFF05,0x0002,0x3431, + 0x383D,0xFF06,0x0006,0xFF05,0x0007,0x3841,0xFF06,0x0000, + 0xFF05,0x0001,0x3419,0xFF05,0x0009,0x383F,0xFF05,0x0002, + 0x3434,0xFF05,0x0007,0x383F,0xFF05,0x0007,0x384B,0xFF06, + 0x0000,0xFF05,0x0001,0x341B,0xFF05,0x0009,0x3849,0xFF05, + 0x0002,0x3437,0xFF05,0x0007,0x3849,0xFF05,0x0007,0x3855, + 0xFF06,0x0000,0xFF05,0x0001,0x341D,0xFF05,0x0009,0x3853, + 0xFF05,0x0002,0x343A,0xFF05,0x0007,0x3853,0xFF06,0x0006, + 0xFF05,0x0001,0x385E,0xFF06,0x0001,0x385D,0xFF06,0x0007, + 0xFF05,0x0001,0x385E,0xFF06,0x0001,0x385D,0xFF06,0x0006, + 0xFF04,0x0002,0xFF09,0x000D,0x3C71,0xFF04,0x0000,0xFF05, + 0x0011,0x3C60,0xFF04,0x0002,0xFF09,0x000D,0x3C83,0xFF04, + + 0x0000,0xFF05,0x0011,0x3C72,0xFF04,0x0002,0xFF09,0x000D, + 0x3C95,0xFF04,0x0000,0xFF05,0x0011,0x3C84,0xFF04,0x0002, + 0xFF09,0x000D,0x3CA7,0xFF04,0x0000,0xFF05,0x0011,0x3C96, + 0xFF08,0xFF02,0x0001,0xFF03,0x0300,0xFF01,0x0000,0xFF06, + 0x01BF,0xFF06,0x0003,0xFF05,0x0002,0x2CB0,0xFF05,0x0002, + 0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05, + 0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0, + 0xFF05,0x0002,0x2CB0,0xFF06,0x0003,0xFF06,0x0003,0xFF05, + 0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0, + 0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002, + 0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x0003,0x2CB3,0xFF05,0x0003, + 0x2CB3,0xFF05,0x0003,0x2CB3,0xFF05,0x0003,0x2CB3,0xFF05, + 0x0003,0x2CB3,0xFF05,0x0003,0x2CB3,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x2CB7,0xFF06,0x0004,0xFF05,0x0002, + 0x2CB9,0xFF06,0x0004,0xFF05,0x0002,0x2D13,0xFF06,0x0004, + + 0x2D16,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CBC, + 0xFF06,0x0004,0xFF05,0x0002,0x2CBE,0xFF06,0x0004,0xFF05, + 0x0002,0x2D17,0xFF06,0x0004,0x2D1A,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x2CC1,0xFF06,0x0004,0xFF05,0x0002, + 0x2CC3,0xFF06,0x0004,0xFF05,0x0002,0x2D1B,0xFF06,0x0004, + 0x2D1E,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CC6, + 0xFF06,0x0004,0xFF05,0x0002,0x2CC8,0xFF06,0x0004,0xFF05, + 0x0002,0x2D1F,0xFF06,0x0004,0x2D22,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x2CCB,0xFF06,0x0004,0xFF05,0x0002, + 0x2CCD,0xFF06,0x0004,0xFF05,0x0002,0x2D23,0xFF06,0x0004, + 0x2D26,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CD0, + 0xFF06,0x0004,0xFF05,0x0002,0x2CD2,0xFF06,0x0004,0xFF05, + 0x0002,0x2D27,0xFF06,0x0004,0x2D2A,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x2CD5,0xFF06,0x0004,0xFF05,0x0002, + 0x2CD7,0xFF06,0x0004,0xFF05,0x0002,0x2D2B,0xFF06,0x0004, + 0x2D2E,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CDA, + + 0xFF06,0x0004,0xFF05,0x0002,0x2CDC,0xFF06,0x0004,0xFF05, + 0x0002,0x2D2F,0xFF06,0x0004,0x2D32,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x000B,0x2CDF,0xFF05,0x000B,0x2D33,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x000B,0x2CEB,0xFF05,0x000B, + 0x2D3F,0xFF06,0x0003,0xFF06,0x0001,0x2CF7,0xFF05,0x0008, + 0x2CF7,0xFF05,0x0003,0x2D01,0xFF05,0x000C,0x2D4B,0x2CF7, + 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x000D,0x2D05,0xFF05, + 0x000D,0x2D58,0xFF06,0x0001,0xFF06,0x005F,0xFF08,0xFF02, + 0x0002,0xFF03,0x0400,0xFF01,0x0000,0xFF06,0x01BF,0xFF06, + 0x003F,0xFF05,0x0007,0x3001,0xFF05,0x0007,0x3001,0xFF05, + 0x0007,0x3001,0xFF05,0x0007,0x3001,0xFF05,0x0007,0x3009, + 0xFF05,0x0007,0x3009,0xFF05,0x0007,0x3009,0xFF05,0x0007, + 0x3009,0xFF06,0x001F,0xFF03,0x0300,0xFF06,0x0003,0xFF05, + 0x0001,0x2811,0xFF06,0x0003,0xFF05,0x0001,0x2811,0xFF06, + 0x0007,0xFF05,0x0001,0x2811,0xFF06,0x0003,0xFF05,0x0001, + 0x2811,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2813, + + 0xFF06,0x0003,0xFF05,0x0001,0x2813,0xFF06,0x0007,0xFF05, + 0x0001,0x2813,0xFF06,0x0003,0xFF05,0x0001,0x2813,0xFF06, + 0x0003,0xFF06,0x0002,0xFF05,0x0003,0x2815,0xFF06,0x0001, + 0xFF05,0x0003,0x2815,0xFF06,0x0005,0xFF05,0x0003,0x2815, + 0xFF06,0x0001,0xFF05,0x0003,0x2815,0xFF06,0x0002,0xFF06, + 0x0002,0xFF05,0x0003,0x2819,0xFF06,0x0001,0xFF05,0x0003, + 0x2819,0xFF06,0x0005,0xFF05,0x0003,0x2819,0xFF06,0x0001, + 0xFF05,0x0003,0x2819,0xFF06,0x0002,0xFF06,0x0001,0xFF05, + 0x0004,0x281D,0xFF06,0x0000,0xFF05,0x0004,0x281D,0xFF06, + 0x0004,0xFF05,0x0004,0x281D,0xFF06,0x0000,0xFF05,0x0004, + 0x281D,0xFF06,0x0002,0xFF06,0x0001,0xFF05,0x0005,0x2822, + 0xFF05,0x0005,0x2822,0xFF06,0x0003,0xFF05,0x0005,0x2822, + 0xFF05,0x0005,0x2822,0xFF06,0x0001,0xFF06,0x0001,0xFF05, + 0x0005,0x2828,0xFF05,0x0005,0x2828,0xFF06,0x0003,0xFF05, + 0x0005,0x2828,0xFF05,0x0005,0x2828,0xFF06,0x0001,0xFF06, + 0x00BF,0xFF08,0xFF02,0x0003,0xFF03,0x0300,0xFF01,0x0000, + + 0xFF06,0x01BF,0xFF06,0x007F,0xFF06,0x0003,0xFF05,0x0002, + 0x2432,0xFF05,0x0002,0x2046,0xFF05,0x0004,0x2430,0xFF05, + 0x0002,0x2046,0xFF05,0x0004,0x2430,0xFF05,0x0002,0x2046, + 0xFF05,0x0001,0x2430,0xFF06,0x0003,0xFF06,0x0003,0xFF05, + 0x0002,0x2437,0xFF05,0x0002,0x2049,0xFF05,0x0004,0x2435, + 0xFF05,0x0002,0x2049,0xFF05,0x0004,0x2435,0xFF05,0x0002, + 0x2049,0xFF05,0x0001,0x2435,0xFF06,0x0003,0xFF06,0x0003, + 0xFF05,0x0001,0x243C,0xFF05,0x0003,0x204C,0xFF05,0x0003, + 0x243A,0xFF05,0x0003,0x204C,0xFF05,0x0003,0x243A,0xFF05, + 0x0003,0x204C,0xFF05,0x0001,0x243A,0xFF06,0x0003,0xFF06, + 0x0003,0x243F,0xFF05,0x0005,0x2050,0xFF05,0x0001,0x243E, + 0xFF05,0x0005,0x2050,0xFF05,0x0001,0x243E,0xFF05,0x0005, + 0x2050,0x283E,0xFF06,0x0003,0xFF06,0x0003,0x2441,0xFF05, + 0x0005,0x2056,0xFF05,0x0001,0x2440,0xFF05,0x0005,0x2056, + 0xFF05,0x0001,0x2440,0xFF05,0x0005,0x2056,0x2840,0xFF06, + 0x0003,0xFF06,0x0003,0x2443,0xFF05,0x0005,0x205C,0xFF05, + + 0x0001,0x2442,0xFF05,0x0005,0x205C,0xFF05,0x0001,0x2442, + 0xFF05,0x0005,0x205C,0x2842,0xFF06,0x0003,0xFF06,0x0003, + 0x2445,0xFF05,0x0005,0x2062,0xFF05,0x0001,0x2444,0xFF05, + 0x0005,0x2062,0xFF05,0x0001,0x2444,0xFF05,0x0005,0x2062, + 0x2844,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0007,0x2068, + 0xFF05,0x0007,0x2068,0xFF05,0x0007,0x2068,0xFF06,0x0003, + 0xFF06,0x0003,0xFF05,0x0007,0x2070,0xFF05,0x0007,0x2070, + 0xFF05,0x0007,0x2070,0xFF06,0x0003,0xFF06,0x009F,0xFF00, + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0200,0xFF06 +}; +static UINT16 bloodwar_mcu_4_1e[] = { // Warrior 3 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0200,0xFF06, + 0x01BF,0xFF05,0x000F,0x2C01,0xFF05,0x000F,0x2C01,0xFF05, + 0x000F,0x2C11,0xFF05,0x000F,0x2C11,0xFF05,0x0001,0x3C27, + 0xFF06,0x0003,0xFF05,0x0003,0x3C25,0xFF06,0x0003,0xFF05, + 0x0003,0x3C25,0xFF06,0x0003,0xFF05,0x0003,0x3C25,0xFF06, + 0x0003,0xFF05,0x0001,0x3C25,0xFF05,0x0001,0x3C2B,0xFF06, + 0x0003,0xFF05,0x0003,0x3C29,0xFF06,0x0003,0xFF05,0x0003, + 0x3C29,0xFF06,0x0003,0xFF05,0x0003,0x3C29,0xFF06,0x0003, + 0xFF05,0x0001,0x3C29,0xFF05,0x0001,0x3C2F,0xFF06,0x0003, + 0xFF05,0x0003,0x3C2D,0xFF06,0x0003,0xFF05,0x0003,0x3C2D, + 0xFF06,0x0003,0xFF05,0x0003,0x3C2D,0xFF06,0x0003,0xFF05, + 0x0001,0x3C2D,0xFF05,0x0001,0x3C33,0xFF06,0x0003,0xFF05, + 0x0003,0x3C31,0xFF06,0x0003,0xFF05,0x0003,0x3C31,0xFF06, + 0x0003,0xFF05,0x0003,0x3C31,0xFF06,0x0003,0xFF05,0x0001, + 0x3C31,0x3C36,0xFF06,0x0005,0xFF05,0x0001,0x3C35,0xFF06, + 0x0005,0xFF05,0x0001,0x3C35,0xFF06,0x0005,0xFF05,0x0001, + + 0x3C35,0xFF06,0x0005,0x3C35,0xFF06,0x00DF,0xFF03,0x0300, + 0xFF06,0x0001,0xFF05,0x0001,0x2439,0xFF05,0x0001,0x203B, + 0xFF05,0x0002,0x243D,0xFF05,0x000C,0x2040,0xFF04,0x0002, + 0x2040,0xFF09,0x0002,0x243F,0xFF09,0x0001,0x203C,0xFF09, + 0x0001,0x243A,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0000, + 0xFF05,0x0002,0x244E,0xFF05,0x0001,0x2051,0xFF05,0x0002, + 0x2453,0xFF05,0x000C,0x2056,0xFF04,0x0002,0x2056,0xFF09, + 0x0002,0x2455,0xFF09,0x0001,0x2052,0xFF09,0x0002,0x2450, + 0xFF04,0x0000,0xFF06,0x0000,0xFF05,0x0003,0x2463,0xFF05, + 0x0001,0x2067,0xFF05,0x0002,0x2469,0xFF05,0x000C,0x206C, + 0xFF04,0x0002,0x206C,0xFF09,0x0002,0x246B,0xFF09,0x0001, + 0x2068,0xFF09,0x0003,0x2466,0xFF04,0x0000,0xFF05,0x0003, + 0x2479,0xFF05,0x0001,0x207D,0xFF05,0x0002,0x247F,0xFF05, + 0x000C,0x2082,0xFF04,0x0002,0x2082,0xFF09,0x0002,0x2481, + 0xFF09,0x0001,0x207E,0xFF09,0x0003,0x247C,0xFF04,0x0000, + 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0200,0xFF06, + + 0x01BF,0xFF06,0x003F,0xFF06,0x0003,0xFF05,0x0001,0x38AB, + 0xFF06,0x0002,0xFF05,0x0001,0x38AB,0xFF06,0x0009,0xFF04, + 0x0002,0xFF09,0x0001,0x38AC,0xFF06,0x0002,0xFF09,0x0001, + 0x38AC,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05, + 0x0001,0x38AD,0xFF06,0x0002,0xFF05,0x0001,0x38AD,0xFF06, + 0x0009,0xFF04,0x0002,0xFF09,0x0001,0x38AE,0xFF06,0x0002, + 0xFF09,0x0001,0x38AE,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x38AF,0xFF06,0x0002,0xFF05,0x0001, + 0x38AF,0xFF06,0x0009,0xFF04,0x0002,0xFF09,0x0001,0x38B0, + 0xFF06,0x0002,0xFF09,0x0001,0x38B0,0xFF04,0x0000,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B1,0xFF06,0x0002, + 0xFF05,0x0001,0x38B1,0xFF06,0x0009,0xFF04,0x0002,0xFF09, + 0x0001,0x38B2,0xFF06,0x0002,0xFF09,0x0001,0x38B2,0xFF04, + 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B3, + 0xFF06,0x0002,0xFF05,0x0001,0x38B3,0xFF06,0x0000,0xFF05, + 0x0001,0x3490,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001, + + 0x3091,0xFF06,0x0000,0xFF09,0x0001,0x38B4,0xFF06,0x0002, + 0xFF09,0x0001,0x38B4,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x38B5,0xFF06,0x0002,0xFF05,0x0001, + 0x38B5,0xFF06,0x0000,0xFF05,0x0002,0x3492,0xFF06,0x0001, + 0xFF04,0x0002,0xFF09,0x0002,0x3094,0xFF06,0x0000,0xFF09, + 0x0001,0x38B6,0xFF06,0x0002,0xFF09,0x0001,0x38B6,0xFF04, + 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B7, + 0xFF06,0x0002,0xFF05,0x0001,0x38B7,0xFF06,0x0000,0xFF05, + 0x0002,0x3495,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0002, + 0x3097,0xFF06,0x0000,0xFF09,0x0001,0x38B8,0xFF06,0x0002, + 0xFF09,0x0001,0x38B8,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x38B9,0xFF06,0x0002,0xFF05,0x0001, + 0x38B9,0xFF05,0x0003,0x3498,0xFF06,0x0001,0xFF04,0x0002, + 0xFF09,0x0003,0x309B,0xFF09,0x0001,0x38BA,0xFF06,0x0002, + 0xFF09,0x0001,0x38BA,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0001,0x38BB,0xFF06,0x0002,0xFF05,0x0001, + + 0x38BB,0xFF05,0x0004,0x349C,0xFF04,0x0002,0xFF09,0x0004, + 0x30A0,0xFF09,0x0001,0x38BC,0xFF06,0x0002,0xFF09,0x0001, + 0x38BC,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05, + 0x0001,0x38BD,0xFF06,0x0002,0xFF05,0x0001,0x38BD,0xFF05, + 0x0004,0x34A1,0xFF04,0x0002,0xFF09,0x0004,0x30A5,0xFF09, + 0x0001,0x38BE,0xFF06,0x0002,0xFF09,0x0001,0x38BE,0xFF04, + 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38BF, + 0xFF06,0x0002,0xFF05,0x0001,0x38BF,0xFF05,0x0004,0x34A6, + 0xFF04,0x0002,0xFF09,0x0004,0x30AA,0xFF09,0x0001,0x38C0, + 0xFF06,0x0002,0xFF09,0x0001,0x38C0,0xFF04,0x0000,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38C1,0xFF06,0x0002, + 0xFF05,0x0007,0x38C1,0xFF04,0x0002,0xFF09,0x0005,0x38C6, + 0xFF06,0x0002,0xFF09,0x0001,0x38C2,0xFF04,0x0000,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38C9,0xFF06,0x0002, + 0xFF05,0x0007,0x38C9,0xFF04,0x0002,0xFF09,0x0005,0x38CE, + 0xFF06,0x0002,0xFF09,0x0001,0x38CA,0xFF04,0x0000,0xFF06, + + 0x0003,0xFF06,0x005F,0xFF08,0xFF02,0x0002,0xFF03,0x0400, + 0xFF01,0x0100,0xFF06,0x01BF,0xFF06,0x003F,0xFF05,0x0002, + 0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05, + 0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01, + 0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002, + 0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0001,0x2C01,0xFF05, + 0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04, + 0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002, + 0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05, + 0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0001,0x2C04, + 0xFF05,0x0007,0x2C07,0xFF05,0x0007,0x2C07,0xFF05,0x0007, + 0x2C07,0xFF05,0x0007,0x2C07,0xFF05,0x0007,0x2C0F,0xFF05, + 0x0007,0x2C0F,0xFF05,0x0007,0x2C0F,0xFF05,0x0007,0x2C0F, + 0xFF06,0x0002,0x3819,0xFF06,0x0003,0x3819,0xFF06,0x0003, + 0x3819,0xFF06,0x0003,0x3819,0xFF06,0x0003,0x3819,0xFF06, + 0x0003,0x3819,0xFF06,0x0002,0xFF06,0x0002,0x381A,0xFF06, + + 0x0003,0x381A,0xFF06,0x0003,0x381A,0xFF06,0x0003,0x381A, + 0xFF06,0x0003,0x381A,0xFF06,0x0003,0x381A,0xFF06,0x0002, + 0xFF06,0x0002,0x381B,0xFF06,0x0003,0x381B,0xFF06,0x0003, + 0x381B,0xFF06,0x0003,0x381B,0xFF06,0x0003,0x381B,0xFF06, + 0x0003,0x381B,0xFF06,0x0002,0xFF06,0x0002,0x381C,0xFF06, + 0x0003,0x381C,0xFF06,0x0003,0x381C,0xFF06,0x0003,0x381C, + 0xFF06,0x0003,0x381C,0xFF06,0x0003,0x381C,0xFF06,0x0002, + 0xFF06,0x0002,0x381D,0xFF06,0x0003,0x381D,0xFF06,0x0003, + 0x381D,0xFF06,0x0003,0x381D,0xFF06,0x0003,0x381D,0xFF06, + 0x0003,0x381D,0xFF06,0x0002,0xFF06,0x0002,0x381E,0xFF06, + 0x0003,0x381E,0xFF06,0x0003,0x381E,0xFF06,0x0003,0x381E, + 0xFF06,0x0003,0x381E,0xFF06,0x0003,0x381E,0xFF06,0x0002, + 0xFF06,0x0002,0x381F,0xFF06,0x0003,0x381F,0xFF06,0x0003, + 0x381F,0xFF06,0x0003,0x381F,0xFF06,0x0003,0x381F,0xFF06, + 0x0003,0x381F,0xFF06,0x0002,0xFF06,0x0002,0x3820,0xFF06, + 0x0003,0x3820,0xFF06,0x0003,0x3820,0xFF06,0x0003,0x3820, + + 0xFF06,0x0003,0x3820,0xFF06,0x0003,0x3820,0xFF06,0x0002, + 0xFF06,0x0002,0x3821,0xFF06,0x0003,0x3821,0xFF06,0x0003, + 0x3821,0xFF06,0x0003,0x3821,0xFF06,0x0003,0x3821,0xFF06, + 0x0003,0x3821,0xFF06,0x0002,0xFF06,0x005F,0xFF08,0xFF02, + 0x0003,0xFF03,0x0400,0xFF01,0x0100,0xFF06,0x01BF,0xFF06, + 0x00BF,0xFF05,0x0007,0x2C30,0xFF05,0x0007,0x2C30,0xFF05, + 0x0007,0x2C30,0xFF05,0x0007,0x2C30,0xFF05,0x000F,0x2C38, + 0xFF05,0x000F,0x2CA0,0xFF05,0x000F,0x2C48,0xFF05,0x000F, + 0x2CB0,0xFF05,0x000F,0x2C58,0xFF05,0x000F,0x2CC0,0xFF06, + 0x0002,0xFF04,0x0002,0xFF09,0x000B,0x2875,0xFF04,0x0000, + 0xFF05,0x000D,0x2868,0xFF06,0x0002,0xFF06,0x0002,0xFF04, + 0x0002,0xFF09,0x000B,0x2883,0xFF04,0x0000,0xFF05,0x000D, + 0x2876,0xFF06,0x0002,0xFF06,0x0002,0xFF04,0x0002,0xFF09, + 0x000B,0x2891,0xFF04,0x0000,0xFF05,0x000D,0x2884,0xFF06, + 0x0002,0xFF06,0x0002,0xFF04,0x0002,0xFF09,0x000B,0x289F, + 0xFF04,0x0000,0xFF05,0x000D,0x2892,0xFF06,0x0002,0xFF06, + + 0x007F,0xFF00,0xFF08,0xFF02,0x0000,0xFF03,0x0200,0xFF01 +}; +static UINT16 bloodwar_mcu_4_1f[] = { // Warrior 5 + 0xFF08,0xFF02,0x0000,0xFF03,0x0200,0xFF01,0x0800,0xFF06, + 0x01BF,0xFF06,0x007F,0xFF06,0x0009,0xFF05,0x0002,0x2801, + 0xFF05,0x0004,0x3429,0xFF06,0x0000,0xFF05,0x0002,0x342E, + 0xFF05,0x0002,0x2815,0xFF06,0x0006,0xFF06,0x0009,0xFF05, + 0x0002,0x2804,0xFF05,0x0008,0x3431,0xFF05,0x0002,0x2818, + 0xFF06,0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2807,0xFF06, + 0x0000,0xFF05,0x0008,0x343A,0xFF06,0x0000,0xFF05,0x0001, + 0x281B,0xFF06,0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2809, + 0xFF06,0x0000,0xFF05,0x0004,0x3443,0xFF06,0x0000,0xFF05, + 0x0002,0x3448,0xFF06,0x0000,0xFF05,0x0001,0x281D,0xFF06, + 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x280B,0xFF06,0x000A, + 0xFF05,0x0001,0x281F,0xFF06,0x0006,0xFF06,0x0009,0xFF05, + 0x0001,0x280D,0xFF06,0x000A,0xFF05,0x0001,0x2821,0xFF06, + 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x280F,0xFF06,0x000A, + 0xFF05,0x0001,0x2823,0xFF06,0x0006,0xFF06,0x0009,0xFF05, + 0x0001,0x2811,0xFF06,0x000A,0xFF05,0x0001,0x2825,0xFF06, + + 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2813,0xFF06,0x000A, + 0xFF05,0x0001,0x2827,0xFF06,0x0006,0xFF05,0x0007,0x2053, + 0xFF05,0x000F,0x204B,0xFF05,0x0007,0x204B,0xFF05,0x0007, + 0x2063,0xFF05,0x000F,0x205B,0xFF05,0x0007,0x205B,0xFF05, + 0x0007,0x2073,0xFF05,0x000F,0x206B,0xFF05,0x0007,0x206B, + 0xFF06,0x003F,0xFF08,0xFF02,0x0001,0xFF03,0x0200,0xFF01, + 0x0900,0xFF06,0x01BF,0xFF06,0x0001,0xFF05,0x000D,0x2801, + 0xFF05,0x000F,0x284A,0xFF06,0x0003,0xFF05,0x000B,0x280F, + 0xFF05,0x000D,0x285A,0xFF06,0x0001,0xFF06,0x0005,0xFF05, + 0x0009,0x281B,0xFF05,0x000C,0x2868,0xFF06,0x0002,0xFF06, + 0x0006,0xFF05,0x0008,0x2825,0xFF05,0x000A,0x2875,0xFF06, + 0x0004,0xFF06,0x0008,0xFF05,0x0006,0x282E,0xFF05,0x0009, + 0x2880,0xFF06,0x0005,0xFF06,0x0009,0xFF05,0x0005,0x2835, + 0xFF05,0x0006,0x288A,0xFF06,0x0008,0xFF06,0x000A,0xFF05, + 0x0004,0x283B,0xFF05,0x0005,0x2891,0xFF06,0x0009,0xFF06, + 0x000B,0xFF05,0x0003,0x2840,0xFF05,0x0005,0x2897,0xFF06, + + 0x0009,0xFF06,0x000C,0xFF05,0x0002,0x2844,0xFF05,0x0004, + 0x289D,0xFF06,0x000A,0xFF06,0x000C,0x2847,0xFF06,0x0005, + 0x28A2,0xFF06,0x000A,0xFF06,0x000C,0x2848,0xFF06,0x0005, + 0x28A3,0xFF06,0x000A,0xFF06,0x000C,0x2849,0xFF06,0x0005, + 0x28A4,0xFF06,0x000A,0xFF06,0x005F,0xFF03,0x0300,0xFF06, + 0x0000,0xFF04,0x0002,0xFF09,0x000E,0x30B3,0xFF04,0x0000, + 0xFF05,0x000E,0x30A5,0xFF06,0x0000,0xFF04,0x0002,0xFF09, + 0x000F,0x30C3,0xFF04,0x0000,0xFF05,0x000F,0x30B4,0xFF04, + 0x0002,0xFF09,0x000F,0x30D3,0xFF04,0x0000,0xFF05,0x000F, + 0x30C4,0xFF08,0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0400, + 0xFF06,0x01BF,0xFF06,0x005F,0xFF06,0x0005,0xFF05,0x0001, + 0x25C6,0xFF06,0x0005,0xFF05,0x0003,0x2401,0xFF06,0x000D, + 0xFF06,0x0003,0xFF05,0x0003,0x25C8,0xFF05,0x000C,0x2405, + 0xFF06,0x0003,0xFF05,0x0002,0x25E4,0xFF06,0x0003,0xFF06, + 0x0003,0xFF05,0x0003,0x25CC,0xFF05,0x000F,0x2412,0xFF05, + 0x0003,0x25E7,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0003, + + 0x25D0,0xFF05,0x000F,0x2422,0xFF05,0x0003,0x25EB,0xFF06, + 0x0003,0xFF06,0x0003,0xFF05,0x0003,0x25D4,0xFF05,0x000F, + 0x2432,0xFF05,0x0003,0x25EF,0xFF06,0x0003,0xFF06,0x0003, + 0xFF05,0x0003,0x25D8,0xFF05,0x000F,0x2442,0xFF05,0x0003, + 0x25F3,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0003,0x25DC, + 0xFF05,0x000F,0x2452,0xFF05,0x0003,0x25F7,0xFF06,0x0003, + 0xFF06,0x0003,0xFF05,0x0003,0x25E0,0xFF05,0x000F,0x2462, + 0xFF05,0x0003,0x25FB,0xFF06,0x0003,0xFF06,0x005F,0xFF03, + 0x0400,0xFF06,0x0004,0xFF05,0x0002,0x3A01,0xFF06,0x0000, + 0xFF05,0x0001,0x3A07,0xFF06,0x0009,0xFF05,0x0001,0x3A0B, + 0xFF06,0x0000,0xFF05,0x0002,0x3A0F,0xFF06,0x0004,0xFF06, + 0x0004,0xFF05,0x0002,0x3A04,0xFF06,0x0000,0xFF05,0x0001, + 0x3A09,0xFF06,0x0009,0xFF05,0x0001,0x3A0D,0xFF06,0x0000, + 0xFF05,0x0002,0x3A12,0xFF06,0x0004,0xFF06,0x003F,0xFF08, + 0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0600,0xFF06,0x01BF, + 0xFF05,0x000F,0x3C6D,0xFF05,0x000F,0x3C6D,0xFF05,0x000F, + + 0x3C7D,0xFF05,0x000F,0x3C7D,0xFF05,0x000F,0x3C8D,0xFF05, + 0x000F,0x3C8D,0xFF05,0x000F,0x3C6D,0xFF05,0x000F,0x3C6D, + 0xFF05,0x000F,0x3C7D,0xFF05,0x000F,0x3C7D,0xFF05,0x000F, + 0x3C8D,0xFF05,0x000F,0x3C8D,0xFF06,0x007F,0xFF03,0x0300, + 0xFF05,0x0007,0x2C28,0xFF05,0x000F,0x2C20,0xFF05,0x0007, + 0x2C20,0xFF05,0x0007,0x2C38,0xFF05,0x000F,0x2C30,0xFF05, + 0x0007,0x2C30,0xFF05,0x0007,0x2C48,0xFF05,0x000F,0x2C40, + 0xFF05,0x0007,0x2C40,0xFF05,0x0007,0x2C58,0xFF05,0x000F, + 0x2C50,0xFF05,0x0007,0x2C50,0xFF06,0x0003,0xFF05,0x0003, + 0x2C66,0xFF05,0x0004,0x2C60,0xFF06,0x0006,0xFF05,0x0003, + 0x2C66,0xFF05,0x0004,0x2C60,0xFF06,0x0002,0xFF06,0x0005, + 0xFF05,0x0001,0x2C6B,0x2C6A,0xFF06,0x000C,0xFF05,0x0001, + 0x2C6B,0x2C6A,0xFF06,0x0006,0xFF06,0x003F,0xFF00,0xFF08 +}; +static UINT16 bloodwar_mcu_4_20[] = { // Warrior 4 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x1100,0xFF06, + 0x01BF,0xFF06,0x00DF,0xFF06,0x0001,0xFF04,0x0002,0xFF09, + 0x0001,0x2402,0xFF04,0x0000,0xFF06,0x0017,0xFF05,0x0001, + 0x2401,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0004,0x2407, + 0xFF04,0x0000,0xFF06,0x0003,0xFF05,0x0001,0x3837,0xFF06, + 0x0009,0xFF04,0x0002,0xFF09,0x0001,0x3838,0xFF04,0x0000, + 0xFF06,0x0003,0xFF05,0x0004,0x2403,0xFF04,0x0002,0xFF09, + 0x0005,0x240D,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0002, + 0x3839,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0002,0x383B, + 0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0005,0x2408,0xFF04, + 0x0002,0xFF09,0x0005,0x2415,0xFF04,0x0000,0xFF06,0x0002, + 0xFF05,0x0001,0x383C,0xFF06,0x0009,0xFF04,0x0002,0xFF09, + 0x0001,0x383D,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0005, + 0x2410,0xFF04,0x0002,0xFF09,0x0006,0x241E,0xFF04,0x0000, + 0xFF06,0x0001,0xFF05,0x0001,0x383E,0xFF06,0x0009,0xFF04, + 0x0002,0xFF09,0x0001,0x383F,0xFF04,0x0000,0xFF06,0x0001, + + 0xFF05,0x0006,0x2418,0xFF04,0x0002,0xFF09,0x0006,0x2427, + 0xFF04,0x0000,0xFF06,0x0002,0x3840,0xFF06,0x0009,0xFF04, + 0x0002,0x3840,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0006, + 0x2421,0xFF04,0x0002,0xFF09,0x0006,0x2430,0xFF04,0x0000, + 0xFF06,0x0001,0xFF05,0x0002,0x3841,0xFF06,0x0007,0xFF04, + 0x0002,0xFF09,0x0002,0x3843,0xFF04,0x0000,0xFF06,0x0001, + 0xFF05,0x0006,0x242A,0xFF06,0x0000,0xFF04,0x0002,0xFF09, + 0x0001,0x2434,0xFF04,0x0000,0xFF06,0x0005,0xFF05,0x0002, + 0x3844,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0002,0x3846, + 0xFF04,0x0000,0xFF06,0x0005,0xFF05,0x0001,0x2433,0xFF06, + 0x0000,0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x1100, + 0xFF06,0x01BF,0xFF06,0x003F,0xFF06,0x0001,0xFF04,0x0002, + 0xFF09,0x000D,0x347C,0xFF04,0x0000,0xFF05,0x000D,0x346F, + 0xFF06,0x0001,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x000D, + 0x348A,0xFF04,0x0000,0xFF05,0x000D,0x347D,0xFF06,0x0001, + 0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x000E,0x3499,0xFF04, + + 0x0000,0xFF05,0x000E,0x348B,0xFF06,0x0000,0xFF04,0x0002, + 0xFF09,0x000F,0x34A9,0xFF04,0x0000,0xFF05,0x000F,0x349A, + 0xFF04,0x0002,0xFF09,0x000F,0x34B9,0xFF04,0x0000,0xFF05, + 0x000F,0x34AA,0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x000E, + 0x30C8,0xFF04,0x0000,0xFF05,0x000E,0x30BA,0xFF06,0x0000, + 0xFF04,0x0002,0xFF09,0x000F,0x30D8,0xFF04,0x0000,0xFF05, + 0x000F,0x30C9,0xFF04,0x0002,0xFF09,0x000C,0x30E5,0xFF04, + 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x30D9,0xFF04,0x0002, + 0xFF09,0x000C,0x30F2,0xFF04,0x0000,0xFF06,0x0005,0xFF05, + 0x000C,0x30E6,0xFF04,0x0002,0xFF09,0x000C,0x30FF,0xFF04, + 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x30F3,0xFF04,0x0002, + 0xFF09,0x000C,0x310D,0xFF04,0x0000,0xFF06,0x0005,0xFF05, + 0x000C,0x3101,0xFF04,0x0002,0xFF09,0x000C,0x311A,0xFF04, + 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x310E,0xFF06,0x007F, + 0xFF08,0xFF02,0x0002,0xFF03,0x0400,0xFF01,0x0E00,0xFF06, + 0x01BF,0xFF06,0x00BF,0xFF06,0x000A,0xFF05,0x000B,0x2C01, + + 0xFF06,0x0008,0xFF06,0x000A,0xFF05,0x000B,0x2C0D,0xFF06, + 0x0008,0xFF06,0x000A,0xFF05,0x000B,0x2C19,0xFF06,0x0008, + 0xFF06,0x000A,0xFF05,0x000B,0x2C25,0xFF06,0x0008,0xFF06, + 0x000A,0xFF05,0x000B,0x2C31,0xFF06,0x0008,0xFF06,0x000A, + 0xFF05,0x000B,0x2C3D,0xFF06,0x0008,0xFF06,0x000A,0xFF05, + 0x000B,0x2C49,0xFF06,0x0008,0xFF0A,0x000B,0x3C61,0xFF05, + 0x000B,0x2C55,0xFF0A,0x0007,0x3C61,0xFF04,0x0002,0xFF09, + 0x000D,0x3C79,0xFF04,0x0000,0xFF05,0x0001,0x3C62,0xFF05, + 0x000F,0x3C6A,0xFF04,0x0002,0xFF09,0x000D,0x3C89,0xFF04, + 0x0000,0xFF05,0x0001,0x3C64,0xFF05,0x000F,0x3C7A,0xFF04, + 0x0002,0xFF09,0x000D,0x3C99,0xFF04,0x0000,0xFF05,0x0001, + 0x3C66,0xFF05,0x000F,0x3C8A,0xFF04,0x0002,0xFF09,0x000D, + 0x3CA9,0xFF04,0x0000,0xFF05,0x0001,0x3C68,0xFF05,0x000F, + 0x3C9A,0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0E00, + 0xFF06,0x01BF,0xFF05,0x000F,0x20B0,0xFF05,0x000F,0x20B0, + 0xFF05,0x000F,0x20C0,0xFF05,0x000F,0x20C0,0xFF05,0x000F, + + 0x20D0,0xFF05,0x000F,0x20D0,0xFF05,0x000F,0x20E0,0xFF05, + 0x000F,0x20E0,0xFF05,0x000F,0x20F0,0xFF05,0x000F,0x20F0, + 0xFF05,0x000F,0x2101,0xFF05,0x000F,0x2101,0xFF05,0x000F, + 0x2111,0xFF05,0x000F,0x2111,0xFF05,0x000F,0x2121,0xFF05, + 0x000F,0x2121,0xFF06,0x013F,0xFF00,0xFF08,0xFF02,0x0000 +}; +static UINT16 bloodwar_mcu_4_21[] = { // Warrior 6 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0F00,0xFF06, + 0x01BF,0xFF06,0x005F,0xFF06,0x000F,0x4401,0xFF06,0x000E, + 0xFF06,0x000C,0xFF05,0x0005,0x4402,0xFF06,0x000C,0xFF06, + 0x000C,0xFF05,0x0005,0x4408,0xFF06,0x000C,0xFF06,0x000C, + 0xFF05,0x0005,0x440E,0xFF06,0x000C,0xFF06,0x000C,0xFF05, + 0x0005,0x4414,0xFF06,0x000C,0xFF06,0x000C,0xFF05,0x0005, + 0x401A,0xFF06,0x000C,0xFF06,0x0008,0xFF05,0x0001,0x4901, + 0xFF06,0x0000,0xFF05,0x0007,0x4020,0xFF06,0x0000,0xFF04, + 0x0002,0xFF09,0x0001,0x4902,0xFF04,0x0000,0xFF06,0x0008, + 0xFF06,0x0007,0xFF05,0x0002,0x4903,0xFF06,0x0000,0xFF05, + 0x0007,0x4028,0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x0002, + 0x4905,0xFF04,0x0000,0xFF06,0x0007,0xFF06,0x0007,0xFF05, + 0x0002,0x4906,0xFF06,0x0000,0xFF05,0x0007,0x3C30,0xFF06, + 0x0000,0xFF04,0x0002,0xFF09,0x0002,0x4908,0xFF04,0x0000, + 0xFF06,0x0007,0xFF06,0x0007,0xFF05,0x0002,0x4909,0xFF06, + 0x0000,0xFF05,0x0007,0x3C38,0xFF06,0x0000,0xFF04,0x0002, + + 0xFF09,0x0002,0x490B,0xFF04,0x0000,0xFF06,0x0007,0xFF06, + 0x0007,0x490C,0xFF06,0x0000,0x490D,0xFF05,0x0009,0x3C40, + 0xFF04,0x0002,0x490D,0xFF06,0x0000,0x490C,0xFF04,0x0000, + 0xFF06,0x0007,0xFF06,0x0007,0x490E,0xFF06,0x0001,0xFF05, + 0x0009,0x3C4A,0xFF06,0x0001,0xFF04,0x0002,0x490E,0xFF04, + 0x0000,0xFF06,0x0007,0xFF06,0x0007,0x490F,0xFF06,0x0003, + 0xFF05,0x0005,0x3C54,0xFF06,0x0003,0xFF04,0x0002,0x490F, + 0xFF04,0x0000,0xFF06,0x0007,0xFF06,0x003F,0xFF08,0xFF02, + 0x0001,0xFF03,0x0300,0xFF01,0x0F00,0xFF06,0x01BF,0xFF06, + 0x007F,0xFF06,0x0001,0xFF05,0x0001,0x3870,0xFF06,0x0005, + 0xFF05,0x0001,0x3872,0xFF06,0x0007,0xFF05,0x0001,0x38CA, + 0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x3871,0xFF04, + 0x0000,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002,0x3874, + 0xFF06,0x0000,0x3877,0xFF06,0x0001,0xFF05,0x0002,0x3878, + 0xFF06,0x0007,0xFF05,0x0002,0x38CC,0xFF06,0x0003,0xFF04, + 0x0002,0xFF09,0x0002,0x3876,0xFF04,0x0000,0xFF06,0x0001, + + 0xFF06,0x0001,0xFF05,0x0005,0x387B,0xFF06,0x0000,0xFF05, + 0x0003,0x3881,0xFF06,0x0005,0xFF05,0x0003,0x38CF,0xFF06, + 0x0003,0xFF04,0x0002,0xFF09,0x0002,0x387D,0xFF04,0x0000, + 0xFF06,0x0001,0xFF06,0x0000,0xFF05,0x0006,0x3885,0xFF06, + 0x0000,0xFF05,0x0003,0x388C,0xFF06,0x0005,0xFF05,0x0007, + 0x38D3,0xFF04,0x0002,0xFF09,0x0003,0x3888,0xFF04,0x0000, + 0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x0007,0x3890,0xFF06, + 0x0000,0xFF05,0x0002,0x3898,0xFF06,0x0005,0xFF05,0x0007, + 0x38DB,0xFF04,0x0002,0xFF09,0x0003,0x3893,0xFF04,0x0000, + 0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x000B,0x389B,0xFF06, + 0x0005,0xFF05,0x0007,0x38E3,0xFF04,0x0002,0xFF09,0x0003, + 0x389E,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05, + 0x000B,0x38A7,0xFF06,0x0005,0xFF05,0x0007,0x38EB,0xFF04, + 0x0002,0xFF09,0x0003,0x38AA,0xFF04,0x0000,0xFF06,0x0000, + 0xFF06,0x0000,0xFF05,0x000B,0x38B3,0xFF06,0x0005,0xFF05, + 0x0007,0x38F3,0xFF04,0x0002,0xFF09,0x0003,0x38B6,0xFF04, + + 0x0000,0xFF06,0x0000,0xFF06,0x0001,0xFF05,0x000A,0x38BF, + 0xFF06,0x0005,0xFF05,0x0004,0x38FB,0xFF05,0x0002,0x386D, + 0xFF04,0x0002,0xFF09,0x0002,0x38C1,0xFF04,0x0000,0xFF06, + 0x0001,0xFF06,0x009F,0xFF08,0xFF02,0x0002,0xFF03,0x0200, + 0xFF01,0x0C00,0xFF06,0x01BF,0xFF06,0x0001,0x2000,0xFF05, + 0x0001,0x2001,0x2400,0xFF05,0x0001,0x2590,0x2800,0xFF05, + 0x0001,0x29AC,0x2C00,0xFF05,0x0001,0x2DCB,0xFF06,0x0003, + 0xFF04,0x0002,0xFF09,0x0001,0x2002,0x2000,0xFF09,0x0001, + 0x2591,0x2400,0xFF09,0x0001,0x29AD,0x2800,0xFF09,0x0001, + 0x2DCC,0x2C00,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001, + 0x2000,0xFF05,0x0001,0x2003,0xFF05,0x0002,0x2592,0xFF05, + 0x0002,0x29AE,0xFF05,0x0002,0x2DCD,0xFF06,0x0003,0xFF04, + 0x0002,0xFF09,0x0001,0x2004,0x2000,0xFF09,0x0002,0x2594, + 0xFF09,0x0002,0x29B0,0xFF09,0x0002,0x2DCF,0xFF04,0x0000, + 0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05,0x0001,0x2005, + 0xFF05,0x0002,0x2595,0xFF05,0x0002,0x29B1,0xFF05,0x0002, + + 0x2DD0,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001,0x2006, + 0x2000,0xFF09,0x0002,0x2597,0xFF09,0x0002,0x29B3,0xFF09, + 0x0002,0x2DD2,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001, + 0x2000,0xFF05,0x0001,0x2007,0x2400,0xFF05,0x0001,0x2598, + 0xFF05,0x0002,0x29B4,0x2C00,0xFF05,0x0001,0x2DD3,0xFF06, + 0x0003,0xFF04,0x0002,0xFF09,0x0001,0x2008,0x2000,0xFF09, + 0x0001,0x2599,0x2400,0xFF09,0x0002,0x29B6,0xFF09,0x0001, + 0x2DD4,0x2C00,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001, + 0x2000,0xFF05,0x0001,0x2009,0xFF05,0x0002,0x259A,0xFF05, + 0x0002,0x29B7,0x2C00,0xFF05,0x0001,0x2DD5,0xFF06,0x0003, + 0xFF04,0x0002,0xFF09,0x0001,0x200A,0x2000,0xFF09,0x0002, + 0x259C,0xFF09,0x0002,0x29B9,0xFF09,0x0001,0x2DD6,0x2C00, + 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05, + 0x0001,0x200B,0xFF05,0x0002,0x259D,0xFF05,0x0002,0x29BA, + 0x2C00,0xFF05,0x0001,0x2DD7,0xFF06,0x0003,0xFF04,0x0002, + 0xFF09,0x0001,0x200C,0x2000,0xFF09,0x0002,0x259F,0xFF09, + + 0x0002,0x29BC,0xFF09,0x0001,0x2DD8,0x2C00,0xFF04,0x0000, + 0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05,0x0001,0x200D, + 0xFF05,0x0002,0x25A0,0xFF05,0x0002,0x29BD,0x2C00,0xFF05, + 0x0001,0x2DD9,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001, + 0x200E,0x2000,0xFF09,0x0002,0x25A2,0xFF09,0x0002,0x29BF, + 0xFF09,0x0001,0x2DDA,0x2C00,0xFF04,0x0000,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0002,0x200F,0xFF05,0x0002,0x25A3, + 0xFF05,0x0002,0x29C0,0xFF05,0x0002,0x2DDB,0xFF06,0x0003, + 0xFF04,0x0002,0xFF09,0x0002,0x2011,0xFF09,0x0002,0x25A5, + 0xFF09,0x0002,0x29C2,0xFF09,0x0002,0x2DDD,0xFF04,0x0000, + 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002,0x2012,0xFF05, + 0x0002,0x25A6,0xFF05,0x0002,0x29C3,0xFF05,0x0002,0x2DDE, + 0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0002,0x2014,0xFF09, + 0x0002,0x25A8,0xFF09,0x0002,0x29C5,0xFF09,0x0002,0x2DE0, + 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002, + 0x2015,0x25A9,0xFF0A,0x0001,0x2400,0xFF05,0x0002,0x29C6, + + 0x2DE1,0xFF0A,0x0001,0x2C00,0xFF06,0x0003,0xFF04,0x0002, + 0xFF09,0x0002,0x2017,0xFF0A,0x0001,0x2400,0x25A9,0xFF09, + 0x0002,0x29C8,0xFF0A,0x0001,0x2C00,0x2DE1,0xFF04,0x0000, + 0xFF06,0x0001,0xFF06,0x0001,0x2018,0xFF0A,0x0001,0x2000, + 0x25AA,0xFF0A,0x0001,0x2400,0x29C9,0xFF0A,0x0001,0x2800, + 0x2DE2,0xFF0A,0x0001,0x2C00,0xFF06,0x0003,0xFF04,0x0002, + 0xFF0A,0x0001,0x2000,0x2018,0xFF0A,0x0001,0x2400,0x25AA, + 0xFF0A,0x0001,0x2800,0x29C9,0xFF0A,0x0001,0x2C00,0x2DE2, + 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0x2019,0xFF0A, + 0x0001,0x2000,0x25AB,0xFF0A,0x0001,0x2400,0x29CA,0xFF0A, + 0x0001,0x2800,0x2DE3,0xFF0A,0x0001,0x2C00,0xFF06,0x0003, + 0xFF04,0x0002,0xFF0A,0x0001,0x2000,0x2019,0xFF0A,0x0001, + 0x2400,0x25AB,0xFF0A,0x0001,0x2800,0x29CA,0xFF0A,0x0001, + 0x2C00,0x2DE3,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x001F, + 0xFF03,0x0400,0xFF06,0x000B,0xFF05,0x0001,0x3170,0xFF0A, + 0x0004,0x3172,0x3173,0xFF06,0x000B,0xFF06,0x000A,0xFF05, + + 0x0009,0x3174,0xFF06,0x000A,0xFF06,0x000A,0xFF05,0x0009, + 0x317E,0xFF06,0x000A,0xFF06,0x003F,0xFF08,0xFF02,0x0003, + 0xFF03,0x0200,0xFF01,0x0C00,0xFF06,0x01BF,0xFF04,0x0002, + 0xFF09,0x000F,0x343F,0xFF04,0x0000,0xFF05,0x000F,0x3430, + 0xFF04,0x0002,0xFF09,0x000F,0x344F,0xFF04,0x0000,0xFF05, + 0x000F,0x3440,0xFF04,0x0002,0xFF09,0x000F,0x345F,0xFF04, + 0x0000,0xFF05,0x000F,0x3450,0xFF04,0x0002,0xFF0A,0x0001, + 0x3463,0x3471,0x3463,0xFF09,0x0002,0x346E,0xFF0A,0x0001, + 0x3463,0xFF09,0x0001,0x3469,0xFF0A,0x0001,0x3463,0xFF09, + 0x0002,0x3462,0xFF04,0x0000,0xFF05,0x0002,0x3460,0xFF0A, + 0x0001,0x3463,0xFF05,0x0001,0x3468,0xFF0A,0x0001,0x3463, + 0xFF05,0x0002,0x346C,0x3463,0x3471,0xFF0A,0x0001,0x3463, + 0xFF04,0x0002,0xFF0A,0x0001,0x3463,0x3472,0xFF0A,0x0002, + 0x3463,0x346F,0xFF0A,0x0002,0x3463,0x346A,0xFF0A,0x0001, + 0x3463,0xFF09,0x0001,0x3465,0xFF0A,0x0001,0x3463,0xFF04, + 0x0000,0xFF05,0x0001,0x3464,0xFF0A,0x0001,0x3463,0x346A, + + 0xFF0A,0x0002,0x3463,0x346F,0xFF0A,0x0002,0x3463,0x3472, + 0xFF0A,0x0001,0x3463,0xFF04,0x0002,0xFF0A,0x0001,0x341D, + 0x3473,0xFF0A,0x0002,0x341D,0x3470,0xFF0A,0x0002,0x341D, + 0x346B,0xFF0A,0x0001,0x341D,0xFF09,0x0001,0x3467,0xFF0A, + 0x0001,0x341D,0xFF04,0x0000,0xFF05,0x0001,0x3466,0xFF0A, + 0x0001,0x341D,0x346B,0xFF0A,0x0002,0x341D,0x3470,0xFF0A, + 0x0002,0x341D,0x3473,0xFF0A,0x0001,0x341D,0xFF03,0x0300, + 0xFF05,0x000A,0x3474,0xFF06,0x0008,0xFF05,0x0004,0x34BB, + 0xFF04,0x0002,0xFF09,0x0006,0x347A,0xFF04,0x0000,0xFF05, + 0x000B,0x347F,0xFF06,0x0007,0xFF05,0x0004,0x34C0,0xFF04, + 0x0002,0xFF09,0x0006,0x3485,0xFF04,0x0000,0xFF05,0x000B, + 0x348B,0xFF06,0x0007,0xFF05,0x0004,0x34C5,0xFF04,0x0002, + 0xFF09,0x0006,0x3491,0xFF04,0x0000,0xFF05,0x000B,0x3497, + 0xFF06,0x0007,0xFF05,0x0004,0x34CA,0xFF04,0x0002,0xFF09, + 0x0006,0x349D,0xFF04,0x0000,0xFF05,0x000B,0x34A3,0xFF06, + 0x0006,0xFF05,0x0005,0x34CF,0xFF04,0x0002,0xFF09,0x0006, + + 0x34A9,0xFF04,0x0000,0xFF05,0x000B,0x34AF,0xFF06,0x0006, + 0xFF05,0x0005,0x34D5,0xFF04,0x0002,0xFF09,0x0006,0x34B5, + 0xFF04,0x0000,0xFF0A,0x001F,0x301D,0xFF05,0x0003,0x30DB, + 0xFF05,0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x0003, + 0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05, + 0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x000F,0x3121, + 0xFF05,0x000F,0x30DF,0xFF05,0x000F,0x3131,0xFF05,0x000F, + 0x30EF,0xFF05,0x000F,0x3141,0xFF05,0x000F,0x3101,0xFF05, + 0x000F,0x3151,0xFF05,0x000F,0x3111,0xFF00,0xFF08,0xFF02 +}; +static UINT16 bloodwar_mcu_4_22[] = { // Warrior 1 + 0xFF08,0xFF02,0x0000,0xFF03,0x0300,0xFF01,0x0B00,0xFF06, + 0x01BF,0xFF06,0x0001,0x3401,0xFF06,0x0000,0xFF05,0x0002, + 0x3402,0xFF06,0x0010,0xFF05,0x0001,0x3440,0xFF06,0x0001, + 0xFF05,0x0001,0x345C,0xFF06,0x0001,0xFF06,0x0001,0x3405, + 0xFF06,0x0000,0xFF05,0x0002,0x3406,0xFF06,0x0000,0xFF05, + 0x0001,0x4880,0xFF06,0x000C,0x4882,0xFF05,0x0001,0x3442, + 0xFF06,0x0001,0xFF05,0x0001,0x345E,0xFF06,0x0001,0xFF06, + 0x0001,0x3409,0xFF06,0x0000,0xFF05,0x0002,0x340A,0xFF06, + 0x0000,0xFF05,0x000F,0x4883,0xFF05,0x0001,0x3444,0xFF06, + 0x0001,0xFF05,0x0001,0x3460,0xFF06,0x0001,0xFF06,0x0001, + 0x340D,0xFF06,0x0000,0xFF05,0x0002,0x340E,0xFF06,0x0000, + 0xFF05,0x000F,0x4893,0xFF05,0x0001,0x3446,0xFF06,0x0001, + 0xFF05,0x0001,0x3462,0xFF06,0x0001,0xFF06,0x0001,0x3411, + 0xFF06,0x0000,0xFF05,0x0002,0x3412,0xFF06,0x0002,0xFF05, + 0x0001,0x40A3,0x44A5,0xFF06,0x0001,0xFF05,0x0001,0x44A6, + 0xFF06,0x0001,0xFF05,0x0002,0x44A8,0xFF06,0x0001,0xFF05, + + 0x0001,0x3448,0xFF06,0x0001,0xFF05,0x0001,0x3464,0xFF06, + 0x0001,0xFF06,0x0001,0x3415,0xFF06,0x0000,0xFF05,0x0002, + 0x3416,0xFF06,0x0000,0xFF05,0x0003,0x40AB,0xFF05,0x0009, + 0x44AF,0xFF05,0x0001,0x40B9,0xFF05,0x0001,0x344A,0xFF06, + 0x0001,0xFF05,0x0001,0x3466,0xFF06,0x0001,0xFF06,0x0001, + 0x3419,0xFF06,0x0000,0xFF05,0x0002,0x341A,0xFF06,0x0003, + 0xFF05,0x0001,0x44BB,0xFF06,0x0005,0xFF05,0x0001,0x44D0, + 0xFF06,0x0002,0xFF05,0x0001,0x344C,0xFF06,0x0001,0xFF05, + 0x0001,0x3468,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004, + 0x341D,0xFF06,0x0003,0xFF05,0x0001,0x44BD,0xFF06,0x0005, + 0xFF05,0x0001,0x44D2,0xFF06,0x0002,0xFF05,0x0001,0x344E, + 0xFF06,0x0001,0xFF05,0x0001,0x346A,0xFF06,0x0001,0xFF06, + 0x0001,0xFF05,0x0004,0x3422,0xFF06,0x0003,0xFF05,0x0001, + 0x44BF,0xFF06,0x0005,0xFF05,0x0001,0x44D4,0xFF06,0x0002, + 0xFF05,0x0001,0x3450,0xFF06,0x0001,0xFF05,0x0001,0x346C, + 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,0x3427,0xFF06, + + 0x0002,0xFF05,0x0002,0x44C1,0xFF06,0x0005,0xFF05,0x0002, + 0x44D6,0xFF06,0x0001,0xFF05,0x0001,0x3452,0xFF05,0x0001, + 0x3875,0xFF05,0x0001,0x346E,0xFF06,0x0001,0xFF06,0x0001, + 0xFF05,0x0004,0x342C,0xFF06,0x0002,0xFF05,0x0002,0x44C4, + 0xFF06,0x0005,0xFF05,0x0002,0x44D9,0xFF06,0x0001,0xFF05, + 0x0001,0x3454,0xFF05,0x0001,0x3877,0xFF05,0x0001,0x3470, + 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,0x3431,0xFF06, + 0x0002,0xFF05,0x0002,0x44C7,0xFF06,0x0005,0xFF05,0x0002, + 0x44DC,0xFF06,0x0001,0xFF05,0x0001,0x3456,0xFF05,0x0002, + 0x3879,0x3472,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004, + 0x3436,0xFF06,0x0002,0xFF05,0x0002,0x44CA,0xFF06,0x0005, + 0xFF05,0x0002,0x44DF,0xFF06,0x0001,0xFF05,0x0001,0x3458, + 0xFF05,0x0001,0x387C,0xFF06,0x0000,0x3473,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0004,0x343B,0xFF06,0x0002,0xFF05, + 0x0002,0x44CD,0xFF06,0x0005,0xFF05,0x0002,0x44E2,0xFF06, + 0x0001,0xFF05,0x0001,0x345A,0xFF05,0x0001,0x387E,0xFF06, + + 0x0000,0x3474,0xFF06,0x0001,0xFF05,0x0007,0x3CE5,0xFF04, + 0x0002,0xFF09,0x0007,0x3D08,0xFF04,0x0000,0xFF05,0x000F, + 0x3D01,0xFF05,0x0006,0x3CED,0xFF04,0x0002,0xFF09,0x0008, + 0x3D19,0xFF04,0x0000,0xFF05,0x000F,0x3D11,0xFF05,0x0005, + 0x3CF4,0xFF04,0x0002,0xFF09,0x0009,0x3D2A,0xFF04,0x0000, + 0xFF05,0x000F,0x3D21,0xFF05,0x0004,0x3CFA,0xFF04,0x0002, + 0xFF09,0x000A,0x3D3B,0xFF04,0x0000,0xFF05,0x000F,0x3D31, + 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0C00,0xFF06, + 0x01BF,0xFF06,0x003F,0xFF06,0x000D,0xFF05,0x0003,0x2850, + 0xFF06,0x000D,0xFF06,0x000D,0xFF05,0x0003,0x2854,0xFF06, + 0x000D,0xFF06,0x000D,0xFF05,0x0002,0x2858,0xFF06,0x000E, + 0xFF06,0x000D,0xFF05,0x0002,0x285B,0xFF06,0x000E,0xFF03, + 0x0300,0xFF06,0x0011,0xFF05,0x0003,0x307A,0xFF06,0x0009, + 0xFF06,0x000D,0xFF05,0x0007,0x307E,0xFF06,0x0009,0xFF06, + 0x0004,0xFF05,0x0001,0x305E,0xFF06,0x0006,0xFF05,0x000B, + 0x3086,0xFF06,0x0005,0xFF06,0x0004,0xFF05,0x0002,0x3060, + + 0xFF06,0x0005,0xFF05,0x000B,0x3092,0xFF06,0x0005,0xFF06, + 0x0004,0xFF05,0x0004,0x3063,0xFF06,0x0002,0xFF05,0x000D, + 0x309E,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0003,0x3068, + 0xFF06,0x0003,0xFF05,0x000C,0x30AB,0xFF06,0x0005,0xFF06, + 0x0004,0xFF05,0x0006,0x306C,0xFF05,0x000E,0x30B8,0xFF06, + 0x0004,0xFF06,0x0004,0xFF05,0x0006,0x3073,0xFF05,0x000E, + 0x30C7,0xFF06,0x0004,0xFF06,0x007F,0xFF08,0xFF02,0x0002, + 0xFF03,0x0200,0xFF01,0x0900,0xFF06,0x01BF,0xFF05,0x0006, + 0x2001,0xFF06,0x0000,0xFF05,0x0007,0x2008,0xFF05,0x0006, + 0x2001,0xFF06,0x0000,0xFF05,0x0007,0x2008,0xFF05,0x000F, + 0x2010,0xFF05,0x000F,0x2010,0xFF05,0x000F,0x2020,0xFF05, + 0x000F,0x2020,0xFF05,0x000F,0x2030,0xFF05,0x000F,0x2030, + 0xFF05,0x000F,0x2040,0xFF05,0x000F,0x2040,0xFF05,0x000F, + 0x2050,0xFF05,0x000F,0x2050,0xFF05,0x000F,0x2060,0xFF05, + 0x000F,0x2060,0xFF05,0x000F,0x2070,0xFF05,0x000F,0x2070, + 0xFF05,0x000F,0x2080,0xFF05,0x000F,0x2080,0xFF05,0x000D, + + 0x2090,0xFF06,0x0000,0x209E,0xFF05,0x000D,0x2090,0xFF06, + 0x0000,0x209E,0x209F,0xFF06,0x0001,0xFF05,0x000A,0x20A0, + 0xFF06,0x0000,0x20AB,0x209F,0xFF06,0x0001,0xFF05,0x000A, + 0x20A0,0xFF06,0x0000,0x20AB,0x20AC,0xFF06,0x0001,0xFF05, + 0x000A,0x20AD,0xFF06,0x0000,0x20B8,0x20AC,0xFF06,0x0001, + 0xFF05,0x000A,0x20AD,0xFF06,0x0000,0x20B8,0x20B9,0xFF06, + 0x0001,0xFF05,0x000C,0x20BA,0x20B9,0xFF06,0x0001,0xFF05, + 0x000C,0x20BA,0xFF05,0x000F,0x20C7,0xFF05,0x000F,0x20C7, + 0xFF06,0x007F,0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01, + 0x0900,0xFF06,0x01BF,0xFF0A,0x0005,0x2501,0xFF05,0x0009, + 0x2501,0xFF05,0x0004,0x255B,0xFF0A,0x0004,0x2501,0xFF0A, + 0x0005,0x2501,0xFF05,0x0005,0x25A6,0xFF05,0x0009,0x250B, + 0xFF05,0x0005,0x2560,0xFF0A,0x0003,0x2501,0xFF05,0x0005, + 0x25A0,0xFF05,0x0005,0x25B2,0xFF05,0x0009,0x2515,0xFF05, + 0x0006,0x2566,0x2501,0xFF05,0x0001,0x256D,0xFF05,0x0005, + 0x25AC,0xFF05,0x0005,0x25BE,0xFF05,0x0009,0x251F,0xFF05, + + 0x0009,0x256F,0xFF05,0x0005,0x25B8,0xFF05,0x0005,0x25CA, + 0xFF05,0x0009,0x2529,0xFF05,0x0009,0x2579,0xFF05,0x0005, + 0x25C4,0xFF05,0x0005,0x25D6,0xFF05,0x0009,0x2533,0xFF05, + 0x0009,0x2583,0xFF05,0x0005,0x25D0,0xFF05,0x0005,0x25E2, + 0xFF05,0x0009,0x253D,0xFF05,0x0009,0x258D,0xFF05,0x0005, + 0x25DC,0xFF05,0x0005,0x25EE,0xFF05,0x0009,0x2547,0xFF05, + 0x0002,0x2597,0xFF0A,0x0001,0x2501,0x259A,0xFF0A,0x0001, + 0x2501,0xFF05,0x0001,0x259B,0xFF05,0x0005,0x25E8,0xFF05, + 0x0005,0x25FA,0xFF05,0x0009,0x2551,0xFF0A,0x0009,0x2501, + 0xFF05,0x0005,0x25F4,0xFF03,0x0300,0xFF06,0x0006,0x2CE0, + 0xFF06,0x0002,0x2CE1,0xFF06,0x000A,0x2CE0,0xFF06,0x0002, + 0x2CE1,0xFF06,0x0003,0xFF06,0x0005,0xFF05,0x0006,0x2CE2, + 0xFF06,0x0008,0xFF05,0x0006,0x2CE2,0xFF06,0x0002,0xFF06, + 0x0005,0xFF05,0x0006,0x2CE9,0xFF06,0x0008,0xFF05,0x0006, + 0x2CE9,0xFF06,0x0002,0xFF06,0x0005,0xFF05,0x0006,0x2CF0, + 0xFF06,0x0008,0xFF05,0x0006,0x2CF0,0xFF06,0x0002,0xFF06, + + 0x0005,0xFF05,0x0006,0x2CF7,0xFF06,0x0008,0xFF05,0x0006, + 0x2CF7,0xFF06,0x0002,0xFF06,0x007F,0xFF00,0xFF08,0xFF02 +}; +static UINT16 bloodwar_mcu_4_23[] = { // Warrior 9 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0A00,0xFF06, + 0x01BF,0xFF06,0x0006,0xFF05,0x0001,0x3C88,0xFF06,0x0005, + 0xFF05,0x0001,0x4001,0xFF06,0x0005,0xFF04,0x0002,0xFF09, + 0x0001,0x3C89,0xFF04,0x0000,0xFF06,0x0006,0xFF06,0x0006, + 0xFF05,0x0001,0x3C8A,0xFF06,0x0004,0xFF05,0x0002,0x4003, + 0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x3C8B,0xFF04, + 0x0000,0xFF06,0x0006,0xFF06,0x0001,0xFF05,0x0004,0x3032, + 0xFF05,0x0001,0x3C16,0xFF06,0x0004,0xFF05,0x0003,0x4006, + 0xFF06,0x0004,0xFF04,0x0002,0xFF09,0x0001,0x3C17,0xFF09, + 0x0004,0x3036,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0000, + 0xFF05,0x0005,0x3037,0xFF05,0x0001,0x3C18,0xFF06,0x0004, + 0xFF05,0x0003,0x400A,0xFF06,0x0004,0xFF04,0x0002,0xFF09, + 0x0001,0x3C19,0xFF09,0x0005,0x303C,0xFF04,0x0000,0xFF06, + 0x0000,0xFF06,0x0000,0xFF05,0x0005,0x303D,0xFF05,0x0001, + 0x3C1A,0xFF06,0x0004,0xFF05,0x0003,0x400E,0xFF06,0x0004, + 0xFF04,0x0002,0xFF09,0x0001,0x3C1B,0xFF09,0x0005,0x3042, + + 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x0005, + 0x3043,0xFF05,0x0001,0x3C1C,0xFF06,0x0004,0xFF05,0x0003, + 0x4012,0xFF06,0x0004,0xFF04,0x0002,0xFF09,0x0001,0x3C1D, + 0xFF09,0x0005,0x3048,0xFF06,0x0000,0xFF04,0x0000,0xFF05, + 0x0006,0x3049,0xFF05,0x0001,0x3C1E,0xFF06,0x000D,0xFF04, + 0x0002,0xFF09,0x0001,0x3C1F,0xFF09,0x0006,0x304F,0xFF04, + 0x0000,0xFF05,0x0006,0x3050,0xFF05,0x0001,0x3C20,0xFF06, + 0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C21,0xFF09,0x0006, + 0x3056,0xFF04,0x0000,0xFF05,0x0006,0x3057,0xFF05,0x0001, + 0x3C22,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C23, + 0xFF09,0x0006,0x305D,0xFF04,0x0000,0xFF05,0x0005,0x305E, + 0xFF06,0x0000,0xFF05,0x0001,0x3C24,0xFF06,0x000D,0xFF04, + 0x0002,0xFF09,0x0001,0x3C25,0xFF06,0x0000,0xFF09,0x0005, + 0x3063,0xFF04,0x0000,0xFF06,0x0000,0xFF05,0x0004,0x3064, + 0xFF06,0x0000,0xFF05,0x0001,0x3C26,0xFF06,0x000D,0xFF04, + 0x0002,0xFF09,0x0001,0x3C27,0xFF06,0x0000,0xFF09,0x0004, + + 0x3068,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05, + 0x0004,0x3069,0xFF06,0x0000,0xFF05,0x0001,0x3C28,0xFF06, + 0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C29,0xFF06,0x0000, + 0xFF09,0x0004,0x306D,0xFF04,0x0000,0xFF06,0x0000,0xFF06, + 0x0000,0xFF05,0x0004,0x306E,0xFF06,0x0000,0xFF05,0x0001, + 0x3C2A,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C2B, + 0xFF06,0x0000,0xFF09,0x0004,0x3072,0xFF04,0x0000,0xFF06, + 0x0000,0xFF06,0x0000,0xFF05,0x0004,0x3073,0xFF06,0x0000, + 0xFF05,0x0001,0x3C2C,0xFF06,0x000D,0xFF04,0x0002,0xFF09, + 0x0001,0x3C2D,0xFF06,0x0000,0xFF09,0x0004,0x3077,0xFF04, + 0x0000,0xFF06,0x0000,0xFF05,0x0005,0x3078,0xFF06,0x0000, + 0xFF05,0x0001,0x3C2E,0xFF06,0x000D,0xFF04,0x0002,0xFF09, + 0x0001,0x3C2F,0xFF06,0x0000,0xFF09,0x0005,0x307D,0xFF04, + 0x0000,0xFF05,0x0005,0x307E,0xFF06,0x0000,0xFF05,0x0001, + 0x3C30,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C31, + 0xFF06,0x0000,0xFF09,0x0005,0x3083,0xFF04,0x0000,0xFF06, + + 0x003F,0xFF08,0xFF02,0x0001,0xFF03,0x0200,0xFF01,0x0A00, + 0xFF06,0x01BF,0xFF06,0x0009,0xFF05,0x0001,0x3C8C,0xFF06, + 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3C8D,0xFF04,0x0000, + 0xFF06,0x0009,0xFF06,0x0001,0xFF05,0x0002,0x40A0,0xFF06, + 0x0004,0xFF05,0x0001,0x3C8E,0xFF06,0x0002,0xFF05,0x0001, + 0x4090,0xFF06,0x0002,0xFF04,0x0002,0xFF09,0x0001,0x3C8F, + 0xFF06,0x0004,0xFF09,0x0002,0x40A2,0xFF04,0x0000,0xFF06, + 0x0001,0xFF06,0x0001,0xFF05,0x0002,0x40A3,0xFF06,0x0000, + 0xFF05,0x0003,0x34C7,0xFF05,0x0001,0x3CAF,0xFF06,0x0001, + 0xFF05,0x0003,0x4092,0xFF06,0x0001,0xFF04,0x0002,0xFF09, + 0x0001,0x3CB0,0xFF09,0x0003,0x34CA,0xFF06,0x0000,0xFF09, + 0x0002,0x40A5,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001, + 0xFF05,0x0002,0x40A6,0xFF05,0x0004,0x34CB,0xFF05,0x0001, + 0x3CB1,0xFF06,0x0002,0xFF05,0x0001,0x4096,0xFF06,0x0002, + 0xFF04,0x0002,0xFF09,0x0001,0x3CB2,0xFF09,0x0004,0x34CF, + 0xFF09,0x0002,0x40A8,0xFF04,0x0000,0xFF06,0x0001,0xFF06, + + 0x0001,0xFF05,0x0002,0x40A9,0xFF05,0x0004,0x34D0,0xFF05, + 0x0001,0x3CB3,0xFF06,0x0001,0xFF05,0x0003,0x4098,0xFF06, + 0x0001,0xFF04,0x0002,0xFF09,0x0001,0x3CB4,0xFF09,0x0004, + 0x34D4,0xFF09,0x0002,0x40AB,0xFF04,0x0000,0xFF06,0x0001, + 0xFF06,0x0001,0xFF05,0x0002,0x40AC,0xFF05,0x0004,0x34D5, + 0xFF05,0x0001,0x3CB5,0xFF06,0x0001,0xFF05,0x0003,0x409C, + 0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0001,0x3CB6,0xFF09, + 0x0004,0x34D9,0xFF09,0x0002,0x40AE,0xFF04,0x0000,0xFF06, + 0x0001,0xFF06,0x0004,0xFF05,0x0004,0x34DA,0xFF05,0x0001, + 0x3CB7,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CB8, + 0xFF09,0x0004,0x34DE,0xFF04,0x0000,0xFF06,0x0004,0xFF06, + 0x0004,0xFF05,0x0004,0x34DF,0xFF05,0x0001,0x3CB9,0xFF06, + 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CBA,0xFF09,0x0004, + 0x34E3,0xFF04,0x0000,0xFF06,0x0004,0xFF06,0x0004,0xFF05, + 0x0004,0x34E4,0xFF05,0x0001,0x3CBB,0xFF06,0x0007,0xFF04, + 0x0002,0xFF09,0x0001,0x3CBC,0xFF09,0x0004,0x34E8,0xFF04, + + 0x0000,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0004,0x34E9, + 0xFF05,0x0001,0x3CBD,0xFF06,0x0007,0xFF04,0x0002,0xFF09, + 0x0001,0x3CBE,0xFF09,0x0004,0x34ED,0xFF04,0x0000,0xFF06, + 0x0004,0xFF06,0x0004,0xFF05,0x0004,0x34EE,0xFF05,0x0001, + 0x3CBF,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC0, + 0xFF09,0x0004,0x34F2,0xFF04,0x0000,0xFF06,0x0004,0xFF06, + 0x0005,0xFF05,0x0002,0x34F3,0xFF06,0x0000,0xFF05,0x0001, + 0x3CC1,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC2, + 0xFF06,0x0000,0xFF09,0x0002,0x34F5,0xFF04,0x0000,0xFF06, + 0x0005,0xFF06,0x0004,0xFF05,0x0004,0x34F6,0xFF05,0x0001, + 0x3CC3,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC4, + 0xFF09,0x0004,0x34FA,0xFF04,0x0000,0xFF06,0x0004,0xFF06, + 0x0004,0xFF05,0x0004,0x34FB,0xFF05,0x0001,0x3CC5,0xFF06, + 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC6,0xFF09,0x0004, + 0x34FF,0xFF04,0x0000,0xFF06,0x0004,0xFF06,0x007F,0xFF08, + 0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0700,0xFF06,0x01BF, + + 0xFF05,0x000F,0x3C01,0xFF04,0x0002,0xFF09,0x000F,0x3C10, + 0xFF04,0x0000,0xFF06,0x0003,0xFF05,0x000B,0x3C11,0xFF04, + 0x0002,0xFF09,0x000B,0x3C1C,0xFF04,0x0000,0xFF06,0x0003, + 0xFF06,0x0006,0xFF05,0x0001,0x401D,0xFF06,0x0000,0xFF05, + 0x0002,0x3835,0x3C23,0xFF06,0x0000,0xFF05,0x0001,0x401D, + 0xFF06,0x0000,0xFF04,0x0002,0x3C23,0xFF09,0x0002,0x3837, + 0xFF06,0x0000,0xFF09,0x0001,0x401E,0xFF04,0x0000,0xFF06, + 0x0006,0xFF06,0x0006,0xFF05,0x0001,0x401F,0xFF05,0x0003, + 0x3838,0x3C24,0xFF06,0x0000,0xFF05,0x0001,0x401F,0xFF06, + 0x0000,0xFF04,0x0002,0x3C24,0xFF09,0x0003,0x383B,0xFF09, + 0x0001,0x4020,0xFF04,0x0000,0xFF06,0x0006,0xFF06,0x0006, + 0xFF05,0x0001,0x4021,0xFF05,0x0003,0x383C,0x3C25,0xFF06, + 0x0000,0xFF05,0x0001,0x4021,0xFF06,0x0000,0xFF04,0x0002, + 0x3C25,0xFF09,0x0003,0x383F,0xFF09,0x0001,0x4022,0xFF04, + 0x0000,0xFF06,0x0006,0xFF06,0x0008,0xFF05,0x0003,0x3840, + 0x3C26,0xFF06,0x0003,0xFF04,0x0002,0x3C26,0xFF09,0x0003, + + 0x3843,0xFF04,0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05, + 0x0003,0x3844,0x3C27,0xFF06,0x0003,0xFF04,0x0002,0x3C27, + 0xFF09,0x0003,0x3847,0xFF04,0x0000,0xFF06,0x0008,0xFF06, + 0x0008,0xFF05,0x0003,0x3848,0x3C28,0xFF06,0x0003,0xFF04, + 0x0002,0x3C28,0xFF09,0x0003,0x384B,0xFF04,0x0000,0xFF06, + 0x0008,0xFF06,0x0008,0xFF05,0x0003,0x384C,0x3C29,0xFF06, + 0x0003,0xFF04,0x0002,0x3C29,0xFF09,0x0003,0x384F,0xFF04, + 0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05,0x0003,0x3850, + 0x3C2A,0xFF06,0x0003,0xFF04,0x0002,0x3C2A,0xFF09,0x0003, + 0x3853,0xFF04,0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05, + 0x0003,0x3854,0x3C2B,0xFF05,0x0003,0x442D,0xFF04,0x0002, + 0x3C2B,0xFF09,0x0003,0x3857,0xFF04,0x0000,0xFF06,0x0008, + 0xFF06,0x0008,0xFF05,0x0003,0x3858,0x3C2C,0xFF05,0x0003, + 0x4431,0xFF04,0x0002,0x3C2C,0xFF09,0x0003,0x385B,0xFF04, + 0x0000,0xFF06,0x0008,0xFF06,0x0003,0xFF05,0x0017,0x485C, + 0xFF06,0x0003,0xFF05,0x001F,0x4874,0xFF05,0x001F,0x4894, + + 0xFF05,0x001F,0x48B4,0xFF05,0x001F,0x48D4,0xFF05,0x000B, + 0x48F4,0xFF05,0x0013,0x4901,0xFF08,0xFF02,0x0003,0xFF03, + 0x0200,0xFF01,0x0800,0xFF06,0x01BF,0xFF05,0x0007,0x2820, + 0xFF05,0x0007,0x2820,0xFF05,0x0007,0x2820,0xFF05,0x0007, + 0x2820,0xFF05,0x0007,0x2828,0xFF05,0x0007,0x2828,0xFF05, + 0x0007,0x2828,0xFF05,0x0007,0x2828,0xFF05,0x0007,0x2830, + 0xFF05,0x0007,0x2830,0xFF05,0x0007,0x2830,0xFF05,0x0007, + 0x2830,0xFF05,0x0007,0x2438,0xFF05,0x0007,0x2438,0xFF05, + 0x0007,0x2438,0xFF05,0x0007,0x2438,0xFF05,0x0007,0x2040, + 0xFF05,0x0007,0x2040,0xFF05,0x0007,0x2040,0xFF05,0x0007, + 0x2040,0xFF05,0x0007,0x2048,0xFF05,0x0007,0x2048,0xFF05, + 0x0007,0x2048,0xFF05,0x0007,0x2048,0xFF0A,0x001F,0x2C50, + 0xFF05,0x0007,0x2051,0xFF05,0x0007,0x2051,0xFF05,0x0007, + 0x2051,0xFF05,0x0007,0x2051,0xFF05,0x0007,0x2059,0xFF05, + 0x0007,0x2059,0xFF05,0x0007,0x2059,0xFF05,0x0007,0x2059, + 0xFF05,0x0007,0x2461,0xFF05,0x0007,0x2461,0xFF05,0x0007, + + 0x2461,0xFF05,0x0007,0x2461,0xFF05,0x0007,0x2869,0xFF05, + 0x0007,0x2869,0xFF05,0x0007,0x2869,0xFF05,0x0007,0x2869, + 0xFF05,0x0007,0x2871,0xFF05,0x0007,0x2871,0xFF05,0x0007, + 0x2871,0xFF05,0x0007,0x2871,0xFF05,0x0007,0x2879,0xFF05, + 0x0007,0x2879,0xFF05,0x0007,0x2879,0xFF05,0x0007,0x2879, + 0xFF05,0x0007,0x2881,0xFF05,0x0007,0x2881,0xFF05,0x0007, + 0x2881,0xFF05,0x0007,0x2881,0xFF06,0x007F,0xFF00,0xFF08 +}; +static UINT16 bloodwar_mcu_4_24[] = { // Warrior 7 + 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0300,0xFF06, + 0x01BF,0xFF06,0x0000,0x3402,0xFF05,0x0005,0x4C14,0x3402, + 0xFF05,0x0006,0x4C14,0xFF05,0x0006,0x4C14,0xFF04,0x0002, + 0x3402,0xFF04,0x0000,0xFF05,0x0005,0x4C14,0xFF04,0x0002, + 0x3402,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3403, + 0xFF05,0x0005,0x4C1B,0x3403,0xFF05,0x0002,0x4C1B,0xFF05, + 0x0007,0x4B32,0xFF05,0x0002,0x4C1F,0xFF04,0x0002,0x3403, + 0xFF04,0x0000,0xFF05,0x0005,0x4C1B,0xFF04,0x0002,0x3403, + 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3404,0xFF05, + 0x0005,0x4C22,0x3404,0xFF05,0x0002,0x4C22,0xFF05,0x0007, + 0x4B3A,0xFF05,0x0002,0x4C26,0xFF04,0x0002,0x3404,0xFF04, + 0x0000,0xFF05,0x0005,0x4C22,0xFF04,0x0002,0x3404,0xFF04, + 0x0000,0xFF06,0x0000,0xFF05,0x0007,0x340C,0xFF05,0x0007, + 0x340C,0xFF05,0x0007,0x340C,0xFF05,0x0007,0x340C,0xFF06, + 0x0000,0x3401,0xFF05,0x0006,0x2029,0xFF05,0x000D,0x207E, + 0xFF05,0x0006,0x2029,0xFF04,0x0002,0x3401,0xFF04,0x0000, + + 0xFF06,0x0000,0xFF06,0x0000,0x3402,0xFF05,0x0006,0x2030, + 0xFF05,0x000D,0x208C,0xFF05,0x0006,0x2030,0xFF04,0x0002, + 0x3402,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3403, + 0xFF05,0x0006,0x2037,0xFF05,0x000D,0x209A,0xFF05,0x0006, + 0x2037,0xFF04,0x0002,0x3403,0xFF04,0x0000,0xFF06,0x0000, + 0xFF06,0x0000,0x3404,0xFF05,0x0006,0x203E,0xFF05,0x000D, + 0x20A8,0xFF05,0x0006,0x203E,0xFF04,0x0002,0x3404,0xFF04, + 0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3405,0xFF05,0x0006, + 0x2045,0xFF05,0x000D,0x20B6,0xFF05,0x0006,0x2045,0xFF04, + 0x0002,0x3405,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000, + 0x3406,0xFF05,0x0001,0x2076,0xFF05,0x0004,0x204E,0xFF05, + 0x000D,0x20C4,0xFF05,0x0004,0x204C,0xFF05,0x0001,0x207A, + 0xFF04,0x0002,0x3406,0xFF04,0x0000,0xFF06,0x0000,0xFF06, + 0x0000,0x3407,0xFF05,0x0001,0x2078,0xFF05,0x0004,0x2055, + 0xFF05,0x000D,0x20D2,0xFF05,0x0004,0x2053,0xFF05,0x0001, + 0x207C,0xFF04,0x0002,0x3407,0xFF04,0x0000,0xFF06,0x0000, + + 0xFF06,0x0000,0x3408,0xFF05,0x0006,0x205A,0xFF05,0x000D, + 0x20E0,0xFF05,0x0006,0x205A,0xFF04,0x0002,0x3408,0xFF04, + 0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3409,0xFF05,0x0006, + 0x2061,0xFF05,0x000D,0x20EE,0xFF05,0x0006,0x2061,0xFF04, + 0x0002,0x3409,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000, + 0x340A,0xFF05,0x0006,0x2068,0xFF05,0x000D,0x2101,0xFF05, + 0x0006,0x2068,0xFF04,0x0002,0x340A,0xFF04,0x0000,0xFF06, + 0x0000,0xFF06,0x0000,0x340B,0xFF05,0x0006,0x206F,0xFF05, + 0x000D,0x210F,0xFF05,0x0006,0x206F,0xFF04,0x0002,0x340B, + 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x005F,0xFF08,0xFF02, + 0x0001,0xFF03,0x0200,0xFF01,0x0600,0xFF06,0x01BF,0xFF06, + 0x007F,0xFF05,0x001F,0x34D0,0xFF06,0x0003,0x34F0,0xFF05, + 0x0004,0x2507,0xFF05,0x000B,0x2501,0xFF05,0x0004,0x2502, + 0xFF04,0x0002,0x34F0,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x0003,0x34F1,0xFF05,0x0004,0x2513,0xFF05,0x000B,0x250D, + 0xFF05,0x0004,0x250E,0xFF04,0x0002,0x34F1,0xFF04,0x0000, + + 0xFF06,0x0003,0xFF06,0x0003,0x34F2,0xFF05,0x0004,0x251F, + 0xFF05,0x000B,0x2519,0xFF05,0x0004,0x251A,0xFF04,0x0002, + 0x34F2,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F3, + 0xFF05,0x0004,0x252B,0xFF05,0x000B,0x2525,0xFF05,0x0004, + 0x2526,0xFF04,0x0002,0x34F3,0xFF04,0x0000,0xFF06,0x0003, + 0xFF06,0x0003,0x34F4,0xFF05,0x0004,0x2537,0xFF05,0x000B, + 0x2531,0xFF05,0x0004,0x2532,0xFF04,0x0002,0x34F4,0xFF04, + 0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F5,0xFF05,0x0004, + 0x2543,0xFF05,0x000B,0x253D,0xFF05,0x0004,0x253E,0xFF04, + 0x0002,0x34F5,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003, + 0x34F6,0xFF05,0x0004,0x254F,0xFF05,0x000B,0x2549,0xFF05, + 0x0004,0x254A,0xFF04,0x0002,0x34F6,0xFF04,0x0000,0xFF06, + 0x0003,0xFF06,0x0003,0x34F7,0xFF05,0x0004,0x255B,0xFF05, + 0x000B,0x2555,0xFF05,0x0004,0x2556,0xFF04,0x0002,0x34F7, + 0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F8,0xFF05, + 0x0004,0x2567,0xFF05,0x000B,0x2561,0xFF05,0x0004,0x2562, + + 0xFF04,0x0002,0x34F8,0xFF04,0x0000,0xFF06,0x0003,0xFF06, + 0x007F,0xFF08,0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0200, + 0xFF06,0x01BF,0xFF06,0x009F,0xFF05,0x001F,0x3408,0xFF06, + 0x0002,0xFF05,0x0003,0x2830,0x3401,0xFF05,0x0003,0x2830, + 0xFF05,0x0007,0x2C28,0xFF05,0x0003,0x2830,0xFF04,0x0002, + 0x3401,0xFF04,0x0000,0xFF05,0x0003,0x2830,0xFF06,0x0002, + 0xFF06,0x0002,0xFF05,0x0003,0x283C,0x3402,0xFF05,0x0003, + 0x283C,0xFF05,0x0007,0x2C34,0xFF05,0x0003,0x283C,0xFF04, + 0x0002,0x3402,0xFF04,0x0000,0xFF05,0x0003,0x283C,0xFF06, + 0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2848,0x3403,0xFF05, + 0x0003,0x2848,0xFF05,0x0007,0x2C40,0xFF05,0x0003,0x2848, + 0xFF04,0x0002,0x3403,0xFF04,0x0000,0xFF05,0x0003,0x2848, + 0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2854,0x3404, + 0xFF05,0x0003,0x2854,0xFF05,0x0007,0x2C4C,0xFF05,0x0003, + 0x2854,0xFF04,0x0002,0x3404,0xFF04,0x0000,0xFF05,0x0003, + 0x2854,0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2860, + + 0x3405,0xFF05,0x0003,0x2860,0xFF05,0x0007,0x2C58,0xFF05, + 0x0003,0x2860,0xFF04,0x0002,0x3405,0xFF04,0x0000,0xFF05, + 0x0003,0x2860,0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003, + 0x286C,0x3406,0xFF05,0x0003,0x286C,0xFF05,0x0007,0x2C64, + 0xFF05,0x0003,0x286C,0xFF04,0x0002,0x3406,0xFF04,0x0000, + 0xFF05,0x0003,0x286C,0xFF06,0x0002,0xFF06,0x0002,0xFF05, + 0x0003,0x2878,0x3407,0xFF05,0x0003,0x2878,0xFF05,0x0007, + 0x2C70,0xFF05,0x0003,0x2878,0xFF04,0x0002,0x3407,0xFF04, + 0x0000,0xFF05,0x0003,0x2878,0xFF06,0x0002,0xFF06,0x009F, + 0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0200,0xFF06, + 0x01BF,0xFF06,0x00BF,0xFF06,0x0005,0xFF05,0x0004,0x3480, + 0xFF05,0x0004,0x3480,0xFF05,0x0004,0x3480,0xFF05,0x0004, + 0x3480,0xFF06,0x0005,0xFF06,0x0005,0xFF05,0x0013,0x3085, + 0xFF06,0x0005,0xFF06,0x0005,0xFF05,0x0013,0x3099,0xFF06, + 0x0005,0xFF06,0x0005,0xFF05,0x0013,0x30AD,0xFF06,0x0005, + 0xFF06,0x0005,0xFF05,0x0013,0x30C1,0xFF06,0x0005,0xFF06, + + 0x0005,0xFF05,0x0013,0x30D5,0xFF06,0x0005,0xFF05,0x000F, + 0x44E9,0xFF04,0x0002,0xFF09,0x000F,0x44F8,0xFF04,0x0000, + 0xFF05,0x000F,0x4101,0xFF04,0x0002,0xFF09,0x000F,0x4110, + 0xFF04,0x0000,0xFF05,0x000F,0x3D11,0xFF04,0x0002,0xFF09, + 0x000F,0x3D20,0xFF04,0x0000,0xFF05,0x000F,0x3921,0xFF04, + 0x0002,0xFF09,0x000F,0x3930,0xFF04,0x0000,0xFF05,0x000F, + 0x3931,0xFF04,0x0002,0xFF09,0x000F,0x3940,0xFF04,0x0000, + 0xFF05,0x000F,0x3941,0xFF04,0x0002,0xFF09,0x000F,0x3950, + 0xFF04,0x0000,0xFF00,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF +}; + +// --- fighter data: pointers to ROM --- +static UINT16 bloodwar_mcu_4_25[] = { // Warrior 1 + 0x0007,0x2B72,0x0007,0x2B9E,0x0007,0x2C52,0x0007,0x2D36, + 0x0007,0x3584,0x0007,0x2E3A,0x0007,0x2E54,0x0007,0x2E74, + 0x0007,0x2F28,0x0007,0x3022,0x0007,0x35A0,0x0007,0x377C, + 0x0007,0x378E,0x0007,0x37C0,0x0007,0x37F2,0x0007,0x385C, + 0x0007,0x386E,0x0007,0x38A0,0x0007,0x38D2,0x0007,0x3824, + 0x0007,0x3832,0x0007,0x3840,0x0007,0x384E,0x0007,0x3904, + 0x0007,0x3912,0x0007,0x3920,0x0007,0x392E,0x0007,0x30F6, + 0x0007,0x3110,0x0007,0x3142,0x0007,0x31BA,0x0007,0x3232, + 0x0007,0x32AC,0x0007,0x32DE,0x0007,0x3356,0x0007,0x33CE, + 0x0007,0x35BC,0x0007,0x35CE,0x0007,0x3600,0x0007,0x3632, + 0x0007,0x369C,0x0007,0x36AE,0x0007,0x36E0,0x0007,0x3712, + 0x0007,0x3664,0x0007,0x3672,0x0007,0x3680,0x0007,0x368E, + 0x0007,0x3744,0x0007,0x3752,0x0007,0x3760,0x0007,0x376E, + 0x0007,0x3446,0x0007,0x34A4,0x0007,0x3514,0x0007,0x345A, + 0x0007,0x34B8,0x0007,0x3528,0x0007,0x3490,0x0007,0x3500, + 0x0007,0x3570,0x0007,0x3A18,0x0007,0x3A48,0x0007,0x3A9C, + + 0x0007,0x3AF0,0x0007,0x3B44,0x0007,0x3BB0,0x0007,0x3C64, + 0x0007,0x3D18,0x0007,0x3DCC,0x0007,0x3E20,0x0007,0x3E98, + 0x0007,0x3F10,0x0007,0x3F88,0x0007,0x3FD6,0x0007,0x4072, + 0x0007,0x410E,0x0007,0x5180,0x0007,0x51BC,0x0007,0x521C, + 0x0007,0x527C,0x0007,0x52DC,0x0007,0x5330,0x0007,0x53D2, + 0x0007,0x5474,0x0007,0x5516,0x0007,0x5570,0x0007,0x55EE, + 0x0007,0x566C,0x0007,0x56EA,0x0007,0x5768,0x0007,0x580A, + 0x0007,0x58AC,0x0007,0x41AA,0x0007,0x41DA,0x0007,0x422E, + 0x0007,0x4282,0x0007,0x42D6,0x0007,0x4336,0x0007,0x43EE, + 0x0007,0x44A6,0x0007,0x455E,0x0007,0x45BE,0x0007,0x4642, + 0x0007,0x46C6,0x0007,0x474A,0x0007,0x47A4,0x0007,0x4866, + 0x0007,0x4928,0x0007,0x594E,0x0007,0x597E,0x0007,0x59D2, + 0x0007,0x5A26,0x0007,0x5A7A,0x0007,0x5ADA,0x0007,0x5B6E, + 0x0007,0x5C02,0x0007,0x5C96,0x0007,0x5CF0,0x0007,0x5D78, + 0x0007,0x5E00,0x0007,0x5E88,0x0007,0x5EE0,0x0007,0x5F50, + 0x0007,0x5FC0,0x0007,0x49EA,0x0007,0x4A1E,0x0007,0x4AB6, + + 0x0007,0x4B4E,0x0007,0x4BE6,0x0007,0x4C32,0x0007,0x4CA2, + 0x0007,0x4D12,0x0007,0x6030,0x0007,0x6070,0x0007,0x611E, + 0x0007,0x61CC,0x0007,0x627A,0x0007,0x62BA,0x0007,0x631E, + 0x0007,0x6382,0x0007,0x4D82,0x0007,0x4DDA,0x0007,0x4E96, + 0x0007,0x4F52,0x0007,0x500E,0x0007,0x5048,0x0007,0x50B0, + 0x0007,0x5118,0x0007,0x63E6,0x0007,0x6426,0x0007,0x64CA, + 0x0007,0x656E,0x0007,0x6612,0x0007,0x6652,0x0007,0x66B6, + 0x0007,0x671A,0x0007,0x393C,0x0007,0x3992,0x0007,0x39EE, + 0x0007,0x6FA2,0x0007,0x6FAE,0x0007,0x6FCC,0x0007,0x6FF6, + 0x0007,0x7002,0x0007,0x7020,0x0007,0x704A,0x0007,0x7056, + 0x0007,0x7074,0x0007,0x7118,0x0007,0x712E,0x0007,0x709E, + 0x0007,0x70A6,0x0007,0x713A,0x0007,0x73C6,0x0007,0x7262, + 0x0007,0x72D6,0x0007,0x733C,0x0007,0x7384,0x0007,0x7476, + 0x0007,0x7548,0x0007,0x7906,0x0007,0x7712,0x0007,0x7AD0, + 0x0007,0x7852,0x0007,0x7C32,0x0007,0x7D0A,0x0007,0x7DFC, + 0x0007,0x7EEE,0x0007,0x7FE0,0x0007,0x8158,0x0007,0x824A, + + 0x0007,0x833C,0x0007,0x842E,0x0007,0x8F92,0x0007,0x8FB2, + 0x0007,0x8FEE,0x0007,0x902A,0x0007,0x9038,0x0007,0x9066, + 0x0007,0x90C6,0x0007,0x9102,0x0007,0x9108,0x0007,0x9136, + 0x0007,0x9172,0x0007,0x9180,0x0007,0x919E,0x0007,0x91AC, + 0x0007,0x91CA,0x0007,0x9206,0x0007,0x9262,0x0007,0x929C, + 0x0007,0x92AA,0x0007,0x92D0,0x0007,0x930C,0x0007,0x9322, + 0x0007,0x9340,0x0007,0x937C,0x0007,0x93CE,0x0007,0x93E4, + 0x0007,0x9402,0x0007,0x945C,0x0007,0x9462,0x0007,0x9480, + 0x0007,0x94CC,0x0007,0x94EA,0x0007,0x9510,0x0007,0x954C, + 0x0007,0x9552,0x0007,0x677E,0x0007,0x677E,0x0007,0x677E, + 0x0007,0x677E,0x0007,0x67CC,0x0007,0x67CC,0x0007,0x67CC, + 0x0007,0x67CC,0x0007,0x6820,0x0007,0x68A6,0x0007,0x697E, + 0x0007,0x6AA6,0x0007,0x6C1E,0x0007,0x6CBE,0x0007,0x6DAE, + 0x0007,0x6E9E,0x0007,0x6C66,0x0007,0x6D24,0x0007,0x6E14, + 0x0007,0x6F04,0x0007,0x6F8E,0x0007,0x85A6,0x0007,0x85BA, + 0x0007,0x85CE,0x0007,0x862A,0x0007,0x8644,0x0007,0x8658, + + 0x0007,0x862A,0x0007,0x8644,0x0007,0x869C,0x0007,0x86A6, + 0x0007,0xCC3C,0x0007,0xCC68,0x0007,0xCD1C,0x0007,0xCD9A +}; +static UINT16 bloodwar_mcu_4_26[] = { // Warrior 2 + 0x000B,0xB188,0x000B,0xB1C0,0x000B,0xB308,0x000B,0xB590, + 0x000B,0xCF38,0x000B,0xBA00,0x000B,0xBA1A,0x000B,0xBA3A, + 0x000B,0xBE62,0x000B,0xC4AA,0x000B,0xCF54,0x000B,0xD130, + 0x000B,0xD142,0x000B,0xD174,0x000B,0xD1A6,0x000B,0xD210, + 0x000B,0xD222,0x000B,0xD254,0x000B,0xD286,0x000B,0xD1D8, + 0x000B,0xD1E6,0x000B,0xD1F4,0x000B,0xD202,0x000B,0xD2B8, + 0x000B,0xD2C6,0x000B,0xD2D4,0x000B,0xD2E2,0x000B,0xC662, + 0x000B,0xC67C,0x000B,0xC6B4,0x000B,0xC7BC,0x000B,0xC8C4, + 0x000B,0xC9B8,0x000B,0xC9E4,0x000B,0xCB58,0x000B,0xCCCC, + 0x000B,0xCF70,0x000B,0xCF82,0x000B,0xCFB4,0x000B,0xCFE6, + 0x000B,0xD050,0x000B,0xD062,0x000B,0xD094,0x000B,0xD0C6, + 0x000B,0xD018,0x000B,0xD026,0x000B,0xD034,0x000B,0xD042, + 0x000B,0xD0F8,0x000B,0xD106,0x000B,0xD114,0x000B,0xD122, + 0x000B,0xCE18,0x000B,0xCE58,0x000B,0xCECE,0x000B,0xCE2C, + 0x000B,0xCE6C,0x000B,0xCEE2,0x000B,0xCE44,0x000B,0xCEC0, + 0x000B,0xCF2A,0x000B,0xD52A,0x000B,0xD566,0x000B,0xD5C6, + + 0x000B,0xD626,0x000B,0xD686,0x000B,0xD6D4,0x000B,0xD780, + 0x000B,0xD82C,0x000B,0xD8D8,0x000B,0xD920,0x000B,0xD99C, + 0x000B,0xDA18,0x000B,0xDA94,0x000B,0xDAEE,0x000B,0xDB86, + 0x000B,0xDC1E,0x000B,0xED72,0x000B,0xED9C,0x000B,0xEDFA, + 0x000B,0xEE58,0x000B,0xEEB6,0x000B,0xEEF8,0x000B,0xEFB8, + 0x000B,0xF078,0x000B,0xF138,0x000B,0xF186,0x000B,0xF208, + 0x000B,0xF28A,0x000B,0xF30C,0x000B,0xF366,0x000B,0xF3FE, + 0x000B,0xF496,0x000B,0xDCB6,0x000B,0xDCEC,0x000B,0xDD56, + 0x000B,0xDDC0,0x000B,0xDE2A,0x000B,0xDE6C,0x000B,0xDF2C, + 0x000B,0xDFEC,0x000B,0xE0AC,0x000B,0xE10C,0x000B,0xE1A0, + 0x000B,0xE234,0x000B,0xE2C8,0x000B,0xE332,0x000B,0xE3B4, + 0x000B,0xE436,0x000B,0xF52E,0x000B,0xF55E,0x000B,0xF5C2, + 0x000B,0xF626,0x000B,0xF68A,0x000B,0xF6CC,0x000B,0xF77C, + 0x000B,0xF82C,0x000B,0xF8DC,0x000B,0xF93A,0x000B,0xF9B0, + 0x000B,0xFA26,0x000B,0xFA9C,0x000B,0xFAF6,0x000B,0xFB8E, + 0x000B,0xFC26,0x000B,0xE4B8,0x000B,0xE4F8,0x000B,0xE59C, + + 0x000B,0xE640,0x000B,0xE6E4,0x000B,0xE72A,0x000B,0xE794, + 0x000B,0xE7FE,0x000B,0xFCBE,0x000B,0xFCF2,0x000B,0xFD8A, + 0x000B,0xFE22,0x000B,0xFEBA,0x000B,0xFEEE,0x000B,0xFF46, + 0x000B,0xFF9E,0x000B,0xE868,0x000B,0xE8EE,0x000B,0xE9CE, + 0x000B,0xEAAE,0x000B,0xEB8E,0x000B,0xEBEC,0x000B,0xEC6E, + 0x000B,0xECF0,0x000B,0xFFF6,0x000C,0x008E,0x000C,0x0178, + 0x000C,0x0262,0x000C,0x034C,0x000C,0x038C,0x000C,0x03F0, + 0x000C,0x0454,0x000B,0xD2F0,0x000B,0xD450,0x000B,0xD4E2, + 0x000C,0x0946,0x000C,0x0952,0x000C,0x0970,0x000C,0x099A, + 0x000C,0x09A6,0x000C,0x09C4,0x000C,0x09EE,0x000C,0x09FA, + 0x000C,0x0A18,0x000C,0x0ABC,0x000C,0x0AD2,0x000C,0x0A42, + 0x000C,0x0A4A,0x000C,0x0ADE,0x000C,0x0D6A,0x000C,0x0C06, + 0x000C,0x0C7A,0x000C,0x0CE0,0x000C,0x0D28,0x000C,0x0E1A, + 0x000C,0x0EEC,0x000C,0x12AA,0x000C,0x10B6,0x000C,0x1474, + 0x000C,0x11F6,0x000C,0x15D6,0x000C,0x16AE,0x000C,0x17A0, + 0x000C,0x1892,0x000C,0x1984,0x000C,0x1AFC,0x000C,0x1BEE, + + 0x000C,0x1CE0,0x000C,0x1DD2,0x000C,0x246A,0x000C,0x248A, + 0x000C,0x24C6,0x000C,0x2502,0x000C,0x2510,0x000C,0x253E, + 0x000C,0x259E,0x000C,0x25DA,0x000C,0x25E0,0x000C,0x260E, + 0x000C,0x264A,0x000C,0x2658,0x000C,0x2676,0x000C,0x2684, + 0x000C,0x26A2,0x000C,0x26DE,0x000C,0x273A,0x000C,0x2774, + 0x000C,0x2782,0x000C,0x27A8,0x000C,0x27E4,0x000C,0x27FA, + 0x000C,0x2818,0x000C,0x2854,0x000C,0x28A6,0x000C,0x28BC, + 0x000C,0x28DA,0x000C,0x2934,0x000C,0x293A,0x000C,0x2958, + 0x000C,0x29A4,0x000C,0x29C2,0x000C,0x29E8,0x000C,0x2A24, + 0x000C,0x2A2A,0x000C,0x04B8,0x000C,0x0506,0x000C,0x050E, + 0x000C,0x0516,0x000C,0x051E,0x000C,0x0620,0x000C,0x0634, + 0x000C,0x0736,0x000C,0x074A,0x000C,0x0834,0x000C,0x0848, + 0x000C,0x0932,0x000C,0x1F4A,0x000C,0x1F5E,0x000C,0x1F78, + 0x000C,0x1F4A,0x000C,0x1F5E,0x000C,0x1FC2,0x000C,0x1FCC, + 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF +}; +static UINT16 bloodwar_mcu_4_27[] = { // Warrior 3 + 0x0008,0x631C,0x0008,0x6348,0x0008,0x63EC,0x0008,0x6494, + 0x0008,0x6C5C,0x0008,0x6598,0x0008,0x65B2,0x0008,0x65D2, + 0x0008,0x6676,0x0008,0x674A,0x0008,0x6C78,0x0008,0x6E54, + 0x0008,0x6E66,0x0008,0x6E98,0x0008,0x6ECA,0x0008,0x6F34, + 0x0008,0x6F46,0x0008,0x6F78,0x0008,0x6FAA,0x0008,0x6EFC, + 0x0008,0x6F0A,0x0008,0x6F18,0x0008,0x6F26,0x0008,0x6FDC, + 0x0008,0x6FEA,0x0008,0x6FF8,0x0008,0x7006,0x0008,0x681E, + 0x0008,0x6838,0x0008,0x6864,0x0008,0x68CC,0x0008,0x6934, + 0x0008,0x699C,0x0008,0x69C8,0x0008,0x6A30,0x0008,0x6A98, + 0x0008,0x6C94,0x0008,0x6CA6,0x0008,0x6CD8,0x0008,0x6D0A, + 0x0008,0x6D74,0x0008,0x6D86,0x0008,0x6DB8,0x0008,0x6DEA, + 0x0008,0x6D3C,0x0008,0x6D4A,0x0008,0x6D58,0x0008,0x6D66, + 0x0008,0x6E1C,0x0008,0x6E2A,0x0008,0x6E38,0x0008,0x6E46, + 0x0008,0x6B00,0x0008,0x6B64,0x0008,0x6BE0,0x0008,0x6B1A, + 0x0008,0x6B7E,0x0008,0x6C00,0x0008,0x6B4A,0x0008,0x6BC0, + 0x0008,0x6C42,0x0008,0x7100,0x0008,0x7130,0x0008,0x7184, + + 0x0008,0x71D8,0x0008,0x722C,0x0008,0x7280,0x0008,0x7322, + 0x0008,0x73C4,0x0008,0x7466,0x0008,0x74AE,0x0008,0x751A, + 0x0008,0x7586,0x0008,0x75F2,0x0008,0x7658,0x0008,0x76E2, + 0x0008,0x776C,0x0008,0x857A,0x0008,0x85AA,0x0008,0x85FE, + 0x0008,0x8652,0x0008,0x86A6,0x0008,0x870C,0x0008,0x8790, + 0x0008,0x8814,0x0008,0x8898,0x0008,0x88EC,0x0008,0x8964, + 0x0008,0x89DC,0x0008,0x8A54,0x0008,0x8ABA,0x0008,0x8B68, + 0x0008,0x8C16,0x0008,0x77F6,0x0008,0x782C,0x0008,0x7886, + 0x0008,0x78E0,0x0008,0x793A,0x0008,0x7982,0x0008,0x7A28, + 0x0008,0x7ACE,0x0008,0x7B74,0x0008,0x7BA4,0x0008,0x7BF8, + 0x0008,0x7C4C,0x0008,0x7CA0,0x0008,0x7CFA,0x0008,0x7D92, + 0x0008,0x7E2A,0x0008,0x8CC4,0x0008,0x8CF4,0x0008,0x8D48, + 0x0008,0x8D9C,0x0008,0x8DF0,0x0008,0x8E3E,0x0008,0x8EEA, + 0x0008,0x8F96,0x0008,0x9042,0x0008,0x907E,0x0008,0x90DE, + 0x0008,0x913E,0x0008,0x919E,0x0008,0x91FE,0x0008,0x929C, + 0x0008,0x933A,0x0008,0x7EC2,0x0008,0x7EF6,0x0008,0x7F8E, + + 0x0008,0x8026,0x0008,0x80BE,0x0008,0x80FE,0x0008,0x8152, + 0x0008,0x81A6,0x0008,0x93D8,0x0008,0x9412,0x0008,0x94B0, + 0x0008,0x954E,0x0008,0x95EC,0x0008,0x9644,0x0008,0x96C0, + 0x0008,0x973C,0x0008,0x81FA,0x0008,0x823A,0x0008,0x82DE, + 0x0008,0x8382,0x0008,0x8426,0x0008,0x8460,0x0008,0x84BE, + 0x0008,0x851C,0x0008,0x97B8,0x0008,0x97F2,0x0008,0x9890, + 0x0008,0x992E,0x0008,0x99CC,0x0008,0x9A12,0x0008,0x9A7C, + 0x0008,0x9AE6,0x0008,0x7014,0x0008,0x706A,0x0008,0x70C4, + 0x0008,0xA16E,0x0008,0xA17A,0x0008,0xA198,0x0008,0xA1C2, + 0x0008,0xA1CE,0x0008,0xA1EC,0x0008,0xA216,0x0008,0xA222, + 0x0008,0xA240,0x0008,0xA2E4,0x0008,0xA2FA,0x0008,0xA26A, + 0x0008,0xA272,0x0008,0xA306,0x0008,0xA592,0x0008,0xA42E, + 0x0008,0xA4A2,0x0008,0xA508,0x0008,0xA550,0x0008,0xA642, + 0x0008,0xA714,0x0008,0xAAD2,0x0008,0xA8DE,0x0008,0xAC9C, + 0x0008,0xAA1E,0x0008,0xADFE,0x0008,0xAED6,0x0008,0xAFC8, + 0x0008,0xB0BA,0x0008,0xB1AC,0x0008,0xB324,0x0008,0xB416, + + 0x0008,0xB508,0x0008,0xB5FA,0x0008,0xBC1C,0x0008,0xBC3C, + 0x0008,0xBC78,0x0008,0xBCB4,0x0008,0xBCC2,0x0008,0xBCF0, + 0x0008,0xBD50,0x0008,0xBD8C,0x0008,0xBD92,0x0008,0xBDC0, + 0x0008,0xBDFC,0x0008,0xBE0A,0x0008,0xBE28,0x0008,0xBE36, + 0x0008,0xBE54,0x0008,0xBE90,0x0008,0xBEEC,0x0008,0xBF26, + 0x0008,0xBF34,0x0008,0xBF5A,0x0008,0xBF96,0x0008,0xBFAC, + 0x0008,0xBFCA,0x0008,0xC006,0x0008,0xC058,0x0008,0xC06E, + 0x0008,0xC08C,0x0008,0xC0E6,0x0008,0xC0EC,0x0008,0xC10A, + 0x0008,0xC156,0x0008,0xC174,0x0008,0xC19A,0x0008,0xC1D6, + 0x0008,0xC1DC,0x0008,0x9B50,0x0008,0x9BF8,0x0008,0x9CDC, + 0x0008,0x9DC0,0x0008,0x9B52,0x0008,0x9BFA,0x0008,0x9CDE, + 0x0008,0x9DC2,0x0008,0x9EA4,0x0008,0x9EB2,0x0008,0x9F38, + 0x0008,0x9F4C,0x0008,0x9FD2,0x0008,0x9FE6,0x0008,0xA06C, + 0x0008,0xA080,0x0008,0xA106,0x0008,0xA11A,0x0008,0xA11A, + 0x0008,0xA11A,0x0008,0xA11A,0x0008,0xB772,0x0008,0xB786, + 0x0008,0xB7AC,0x0008,0xB7EA,0x0008,0xB7FE,0x0008,0xB818, + + 0x0008,0xB772,0x0008,0xB786,0x0008,0xB87E,0x0008,0xB772, + 0x0008,0xB786,0x0008,0xB8F0,0x0008,0xB912,0x0008,0xB93A, + 0x0008,0xF128,0x0008,0xF148,0x0008,0xF1EC,0x0008,0xF2AA +}; +static UINT16 bloodwar_mcu_4_28[] = { // Warrior 4 + 0x0008,0xF128,0x0008,0xF148,0x0008,0xF1EC,0x0008,0xF2AA, + 0x0008,0xFA80,0x0008,0xF3AA,0x0008,0xF3C4,0x0008,0xF3E4, + 0x0008,0xF4A8,0x0008,0xF56C,0x0008,0xFA9C,0x0008,0xFC78, + 0x0008,0xFC8A,0x0008,0xFCBC,0x0008,0xFCEE,0x0008,0xFD58, + 0x0008,0xFD6A,0x0008,0xFD9C,0x0008,0xFDCE,0x0008,0xFD20, + 0x0008,0xFD2E,0x0008,0xFD3C,0x0008,0xFD4A,0x0008,0xFE00, + 0x0008,0xFE0E,0x0008,0xFE1C,0x0008,0xFE2A,0x0008,0xF630, + 0x0008,0xF64A,0x0008,0xF67C,0x0008,0xF6F4,0x0008,0xF76C, + 0x0008,0xF7E4,0x0008,0xF816,0x0008,0xF88E,0x0008,0xF906, + 0x0008,0xFAB8,0x0008,0xFACA,0x0008,0xFAFC,0x0008,0xFB2E, + 0x0008,0xFB98,0x0008,0xFBAA,0x0008,0xFBDC,0x0008,0xFC0E, + 0x0008,0xFB60,0x0008,0xFB6E,0x0008,0xFB7C,0x0008,0xFB8A, + 0x0008,0xFC40,0x0008,0xFC4E,0x0008,0xFC5C,0x0008,0xFC6A, + 0x0008,0xF97E,0x0008,0xF9D0,0x0008,0xFA28,0x0008,0xF992, + 0x0008,0xF9E4,0x0008,0xFA3C,0x0008,0xF9BC,0x0008,0xFA14, + 0x0008,0xFA6C,0x0008,0xFF1A,0x0008,0xFF4A,0x0008,0xFF9E, + + 0x0008,0xFFF2,0x0009,0x0046,0x0009,0x00A0,0x0009,0x012E, + 0x0009,0x01BC,0x0009,0x024A,0x0009,0x02A4,0x0009,0x0322, + 0x0009,0x03A0,0x0009,0x041E,0x0009,0x046C,0x0009,0x04F8, + 0x0009,0x0584,0x0009,0x16C4,0x0009,0x1700,0x0009,0x1760, + 0x0009,0x17C0,0x0009,0x1820,0x0009,0x1868,0x0009,0x190E, + 0x0009,0x19B4,0x0009,0x1A5A,0x0009,0x1AAE,0x0009,0x1B36, + 0x0009,0x1BBE,0x0009,0x1C46,0x0009,0x1C9A,0x0009,0x1D46, + 0x0009,0x1DF2,0x0009,0x0610,0x0009,0x064C,0x0009,0x06BC, + 0x0009,0x072C,0x0009,0x079C,0x0009,0x07F0,0x0009,0x08BC, + 0x0009,0x0988,0x0009,0x0A54,0x0009,0x0A9C,0x0009,0x0B18, + 0x0009,0x0B94,0x0009,0x0C10,0x0009,0x0C76,0x0009,0x0D10, + 0x0009,0x0DAA,0x0009,0x1E9E,0x0009,0x1ECE,0x0009,0x1F22, + 0x0009,0x1F76,0x0009,0x1FCA,0x0009,0x2024,0x0009,0x20BC, + 0x0009,0x2154,0x0009,0x21EC,0x0009,0x2240,0x0009,0x22C8, + 0x0009,0x2350,0x0009,0x23D8,0x0009,0x243E,0x0009,0x24D8, + 0x0009,0x2572,0x0009,0x0E44,0x0009,0x0E90,0x0009,0x0F40, + + 0x0009,0x0FF0,0x0009,0x10A0,0x0009,0x1104,0x0009,0x117C, + 0x0009,0x11F4,0x0009,0x260C,0x0009,0x2664,0x0009,0x2700, + 0x0009,0x279C,0x0009,0x2838,0x0009,0x2878,0x0009,0x28DC, + 0x0009,0x2940,0x0009,0x126C,0x0009,0x12D0,0x0009,0x1398, + 0x0009,0x1460,0x0009,0x1528,0x0009,0x1574,0x0009,0x15E4, + 0x0009,0x1654,0x0009,0x29A4,0x0009,0x29EA,0x0009,0x2A84, + 0x0009,0x2B1E,0x0009,0x2BB8,0x0009,0x2BFE,0x0009,0x2C58, + 0x0009,0x2CB2,0x0008,0xFE38,0x0008,0xFEA6,0x0008,0xFEF6, + 0x0009,0x3406,0x0009,0x3412,0x0009,0x3430,0x0009,0x345A, + 0x0009,0x3466,0x0009,0x3484,0x0009,0x34AE,0x0009,0x34BA, + 0x0009,0x34D8,0x0009,0x357C,0x0009,0x3592,0x0009,0x3502, + 0x0009,0x350A,0x0009,0x359E,0x0009,0x379A,0x0009,0x3636, + 0x0009,0x36AA,0x0009,0x3710,0x0009,0x3758,0x0009,0x384A, + 0x0009,0x391C,0x0009,0x3CDA,0x0009,0x3AE6,0x0009,0x3EA4, + 0x0009,0x3C26,0x0009,0x4006,0x0009,0x40DE,0x0009,0x41D0, + 0x0009,0x42C2,0x0009,0x43B4,0x0009,0x452C,0x0009,0x461E, + + 0x0009,0x4710,0x0009,0x4802,0x0009,0x4ED8,0x0009,0x4EF8, + 0x0009,0x4F34,0x0009,0x4F70,0x0009,0x4F7E,0x0009,0x4FAC, + 0x0009,0x500C,0x0009,0x5048,0x0009,0x504E,0x0009,0x507C, + 0x0009,0x50B8,0x0009,0x50C6,0x0009,0x50E4,0x0009,0x50F2, + 0x0009,0x5110,0x0009,0x514C,0x0009,0x51A8,0x0009,0x51E2, + 0x0009,0x51F0,0x0009,0x5216,0x0009,0x5252,0x0009,0x5268, + 0x0009,0x5286,0x0009,0x52C2,0x0009,0x5314,0x0009,0x532A, + 0x0009,0x5348,0x0009,0x53A2,0x0009,0x53A8,0x0009,0x53C6, + 0x0009,0x5412,0x0009,0x5430,0x0009,0x5456,0x0009,0x5492, + 0x0009,0x5498,0x0009,0x2D0C,0x0009,0x2DC8,0x0009,0x2E84, + 0x0009,0x2F40,0x0009,0x2D0E,0x0009,0x2DCA,0x0009,0x2E86, + 0x0009,0x2F42,0x0009,0x2FFC,0x0009,0x300A,0x0009,0x300A, + 0x0009,0x300A,0x0009,0x300A,0x0009,0x305E,0x0009,0x3148, + 0x0009,0x3232,0x0009,0x331C,0x0009,0x497A,0x0009,0x498E, + 0x0009,0x49A2,0x0009,0x497A,0x0009,0x498E,0x0009,0x49E6, + 0x0009,0x49F6,0x0009,0x497A,0x0009,0x498E,0x0009,0x4A18, + + 0x0009,0x4A2A,0x0009,0x81A8,0x0009,0x81C8,0x0009,0x8270 +}; +static UINT16 bloodwar_mcu_4_29[] = { // Warrior 5 + 0x0007,0xCC3C,0x0007,0xCC68,0x0007,0xCD1C,0x0007,0xCD9A, + 0x0007,0xD616,0x0007,0xCE38,0x0007,0xCE52,0x0007,0xCE72, + 0x0007,0xCF16,0x0007,0xCFAA,0x0007,0xD632,0x0007,0xD80E, + 0x0007,0xD820,0x0007,0xD852,0x0007,0xD884,0x0007,0xD8EE, + 0x0007,0xD900,0x0007,0xD932,0x0007,0xD964,0x0007,0xD8B6, + 0x0007,0xD8C4,0x0007,0xD8D2,0x0007,0xD8E0,0x0007,0xD996, + 0x0007,0xD9A4,0x0007,0xD9B2,0x0007,0xD9C0,0x0007,0xD064, + 0x0007,0xD07E,0x0007,0xD0C2,0x0007,0xD16A,0x0007,0xD212, + 0x0007,0xD2BA,0x0007,0xD2FE,0x0007,0xD3A6,0x0007,0xD44E, + 0x0007,0xD64E,0x0007,0xD660,0x0007,0xD692,0x0007,0xD6C4, + 0x0007,0xD72E,0x0007,0xD740,0x0007,0xD772,0x0007,0xD7A4, + 0x0007,0xD6F6,0x0007,0xD704,0x0007,0xD712,0x0007,0xD720, + 0x0007,0xD7D6,0x0007,0xD7E4,0x0007,0xD7F2,0x0007,0xD800, + 0x0007,0xD4F6,0x0007,0xD54E,0x0007,0xD5BE,0x0007,0xD50A, + 0x0007,0xD562,0x0007,0xD5D2,0x0007,0xD53A,0x0007,0xD5B0, + 0x0007,0xD602,0x0007,0xDA8C,0x0007,0xDAC8,0x0007,0xDB2C, + + 0x0007,0xDB90,0x0007,0xDBF4,0x0007,0xDC36,0x0007,0xDCE0, + 0x0007,0xDD8A,0x0007,0xDE34,0x0007,0xDE94,0x0007,0xDF3C, + 0x0007,0xDFE4,0x0007,0xE08C,0x0007,0xE0F2,0x0007,0xE1B4, + 0x0007,0xE276,0x0007,0xF2D6,0x0007,0xF30C,0x0007,0xF366, + 0x0007,0xF3C0,0x0007,0xF41A,0x0007,0xF462,0x0007,0xF538, + 0x0007,0xF60E,0x0007,0xF6E4,0x0007,0xF77A,0x0007,0xF862, + 0x0007,0xF94A,0x0007,0xFA32,0x0007,0xFACE,0x0007,0xFBC6, + 0x0007,0xFCBE,0x0007,0xE338,0x0007,0xE36E,0x0007,0xE3C8, + 0x0007,0xE422,0x0007,0xE47C,0x0007,0xE4B8,0x0007,0xE552, + 0x0007,0xE5EC,0x0007,0xE686,0x0007,0xE6E0,0x0007,0xE772, + 0x0007,0xE804,0x0007,0xE896,0x0007,0xE8E2,0x0007,0xE946, + 0x0007,0xE9AA,0x0007,0xFDB6,0x0007,0xFDE6,0x0007,0xFE3A, + 0x0007,0xFE8E,0x0007,0xFEE2,0x0007,0xFF3C,0x0007,0xFFE4, + 0x0008,0x008C,0x0008,0x0134,0x0008,0x01B2,0x0008,0x0282, + 0x0008,0x0352,0x0008,0x0422,0x0008,0x04A6,0x0008,0x0586, + 0x0008,0x0666,0x0007,0xEA0E,0x0007,0xEA6C,0x0007,0xEB22, + + 0x0007,0xEBD8,0x0007,0xEC8E,0x0007,0xECEC,0x0007,0xED72, + 0x0007,0xEDF8,0x0008,0x0746,0x0008,0x079E,0x0008,0x083E, + 0x0008,0x08DE,0x0008,0x097E,0x0008,0x09D6,0x0008,0x0A56, + 0x0008,0x0AD6,0x0007,0xEE7E,0x0007,0xEED0,0x0007,0xEF7A, + 0x0007,0xF024,0x0007,0xF0CE,0x0007,0xF132,0x0007,0xF1BE, + 0x0007,0xF24A,0x0008,0x0B56,0x0008,0x0BB4,0x0008,0x0C5A, + 0x0008,0x0D00,0x0008,0x0DA6,0x0008,0x0E04,0x0008,0x0E8A, + 0x0008,0x0F10,0x0007,0xD9CE,0x0007,0xDA1C,0x0007,0xDA58, + 0x0008,0x1EDC,0x0008,0x1EE8,0x0008,0x1F06,0x0008,0x1F30, + 0x0008,0x1F3C,0x0008,0x1F5A,0x0008,0x1F84,0x0008,0x1F90, + 0x0008,0x1FAE,0x0008,0x204C,0x0008,0x2062,0x0008,0x1FD8, + 0x0008,0x1FE0,0x0008,0x206E,0x0008,0x226A,0x0008,0x2106, + 0x0008,0x217A,0x0008,0x21E0,0x0008,0x2228,0x0008,0x231A, + 0x0008,0x23E6,0x0008,0x27A4,0x0008,0x25B0,0x0008,0x296E, + 0x0008,0x26F0,0x0008,0x2AD0,0x0008,0x2BA8,0x0008,0x2C94, + 0x0008,0x2D80,0x0008,0x2E6C,0x0008,0x2FDE,0x0008,0x30CA, + + 0x0008,0x31B6,0x0008,0x32A2,0x0008,0x3414,0x0008,0x3434, + 0x0008,0x3470,0x0008,0x34AC,0x0008,0x34BA,0x0008,0x34E8, + 0x0008,0x3548,0x0008,0x3584,0x0008,0x358A,0x0008,0x35B8, + 0x0008,0x35F4,0x0008,0x3602,0x0008,0x3620,0x0008,0x362E, + 0x0008,0x364C,0x0008,0x3688,0x0008,0x36E4,0x0008,0x371E, + 0x0008,0x372C,0x0008,0x3752,0x0008,0x378E,0x0008,0x37A4, + 0x0008,0x37C2,0x0008,0x37FE,0x0008,0x3850,0x0008,0x3866, + 0x0008,0x3884,0x0008,0x38DE,0x0008,0x38E4,0x0008,0x3902, + 0x0008,0x394E,0x0008,0x396C,0x0008,0x3992,0x0008,0x39CE, + 0x0008,0x39D4,0x0008,0x0F96,0x0008,0x10A2,0x0008,0x10B6, + 0x0008,0x11C2,0x0008,0x11D6,0x0008,0x12E2,0x0008,0x12F6, + 0x0008,0x1402,0x0008,0x1416,0x0008,0x14E8,0x0008,0x15DE, + 0x0008,0x16DE,0x0008,0x17DE,0x0008,0x1934,0x0008,0x1A8A, + 0x0008,0x1BE0,0x0008,0x1D36,0x0008,0x1D50,0x0008,0x1D70, + 0x0008,0x1DAE,0x0008,0x1DC8,0x0008,0x1DE8,0x0008,0x1E2C, + 0x0008,0x1E46,0x0008,0x1E5A,0x0008,0x1DAE,0x0008,0x1DC8, + + 0x0008,0x1E9A,0x0008,0x1EAC,0x0008,0x631C,0x0008,0x6348 +}; +static UINT16 bloodwar_mcu_4_2a[] = { // Warrior 6 + 0x000A,0x0E3C,0x000A,0x0E5C,0x000A,0x0F00,0x000A,0x0FA8, + 0x000A,0x16E2,0x000A,0x105C,0x000A,0x1076,0x000A,0x1096, + 0x000A,0x113A,0x000A,0x11DE,0x000A,0x16FE,0x000A,0x18DA, + 0x000A,0x18EC,0x000A,0x191E,0x000A,0x1950,0x000A,0x19BA, + 0x000A,0x19CC,0x000A,0x19FE,0x000A,0x1A30,0x000A,0x1982, + 0x000A,0x1990,0x000A,0x199E,0x000A,0x19AC,0x000A,0x1A62, + 0x000A,0x1A70,0x000A,0x1A7E,0x000A,0x1A8C,0x000A,0x1286, + 0x000A,0x12A0,0x000A,0x12D2,0x000A,0x134A,0x000A,0x13C2, + 0x000A,0x143A,0x000A,0x146C,0x000A,0x14E4,0x000A,0x155C, + 0x000A,0x171A,0x000A,0x172C,0x000A,0x175E,0x000A,0x1790, + 0x000A,0x17FA,0x000A,0x180C,0x000A,0x183E,0x000A,0x1870, + 0x000A,0x17C2,0x000A,0x17D0,0x000A,0x17DE,0x000A,0x17EC, + 0x000A,0x18A2,0x000A,0x18B0,0x000A,0x18BE,0x000A,0x18CC, + 0x000A,0x15D4,0x000A,0x1632,0x000A,0x168A,0x000A,0x15E8, + 0x000A,0x1646,0x000A,0x169E,0x000A,0x161E,0x000A,0x1676, + 0x000A,0x16CE,0x000A,0x1B52,0x000A,0x1B82,0x000A,0x1BD6, + + 0x000A,0x1C2A,0x000A,0x1C7E,0x000A,0x1CCC,0x000A,0x1D68, + 0x000A,0x1E04,0x000A,0x1EA0,0x000A,0x1EE8,0x000A,0x1F54, + 0x000A,0x1FC0,0x000A,0x202C,0x000A,0x207A,0x000A,0x2106, + 0x000A,0x2192,0x000A,0x3092,0x000A,0x30C2,0x000A,0x3116, + 0x000A,0x316A,0x000A,0x31BE,0x000A,0x320C,0x000A,0x32B8, + 0x000A,0x3364,0x000A,0x3410,0x000A,0x345E,0x000A,0x34D0, + 0x000A,0x3542,0x000A,0x35B4,0x000A,0x3602,0x000A,0x36AE, + 0x000A,0x375A,0x000A,0x221E,0x000A,0x224E,0x000A,0x22A2, + 0x000A,0x22F6,0x000A,0x234A,0x000A,0x2392,0x000A,0x2438, + 0x000A,0x24DE,0x000A,0x2584,0x000A,0x25C6,0x000A,0x262C, + 0x000A,0x2692,0x000A,0x26F8,0x000A,0x273A,0x000A,0x27DA, + 0x000A,0x287A,0x000A,0x3806,0x000A,0x3836,0x000A,0x388A, + 0x000A,0x38DE,0x000A,0x3932,0x000A,0x3980,0x000A,0x3A2C, + 0x000A,0x3AD8,0x000A,0x3B84,0x000A,0x3BCC,0x000A,0x3C48, + 0x000A,0x3CC4,0x000A,0x3D40,0x000A,0x3D8E,0x000A,0x3E3A, + 0x000A,0x3EE6,0x000A,0x291A,0x000A,0x294E,0x000A,0x29E6, + + 0x000A,0x2A7E,0x000A,0x2B16,0x000A,0x2B56,0x000A,0x2BBA, + 0x000A,0x2C1E,0x000A,0x3F92,0x000A,0x3FC6,0x000A,0x405E, + 0x000A,0x40F6,0x000A,0x418E,0x000A,0x41C2,0x000A,0x421A, + 0x000A,0x4272,0x000A,0x2C82,0x000A,0x2CCE,0x000A,0x2D86, + 0x000A,0x2E3E,0x000A,0x2EF6,0x000A,0x2F42,0x000A,0x2FB2, + 0x000A,0x3022,0x000A,0x42CA,0x000A,0x42FE,0x000A,0x4396, + 0x000A,0x442E,0x000A,0x44C6,0x000A,0x44FA,0x000A,0x4552, + 0x000A,0x45AA,0x000A,0x1A9A,0x000A,0x1AF0,0x000A,0x1B2E, + 0x000A,0x4D2C,0x000A,0x4D38,0x000A,0x4D56,0x000A,0x4D80, + 0x000A,0x4D8C,0x000A,0x4DAA,0x000A,0x4DD4,0x000A,0x4DE0, + 0x000A,0x4DFE,0x000A,0x4EA2,0x000A,0x4EB8,0x000A,0x4E28, + 0x000A,0x4E30,0x000A,0x4EC4,0x000A,0x50C0,0x000A,0x4F5C, + 0x000A,0x4FD0,0x000A,0x5036,0x000A,0x507E,0x000A,0x5170, + 0x000A,0x5242,0x000A,0x5600,0x000A,0x540C,0x000A,0x57CA, + 0x000A,0x554C,0x000A,0x592C,0x000A,0x5A04,0x000A,0x5AF6, + 0x000A,0x5BE8,0x000A,0x5CDA,0x000A,0x5E52,0x000A,0x5F44, + + 0x000A,0x6036,0x000A,0x6128,0x000A,0x6738,0x000A,0x6758, + 0x000A,0x6794,0x000A,0x67D0,0x000A,0x67DE,0x000A,0x680C, + 0x000A,0x686C,0x000A,0x68A8,0x000A,0x68AE,0x000A,0x68DC, + 0x000A,0x6918,0x000A,0x6926,0x000A,0x6944,0x000A,0x6952, + 0x000A,0x6970,0x000A,0x69AC,0x000A,0x6A08,0x000A,0x6A42, + 0x000A,0x6A50,0x000A,0x6A76,0x000A,0x6AB2,0x000A,0x6AC8, + 0x000A,0x6AE6,0x000A,0x6B22,0x000A,0x6B74,0x000A,0x6B8A, + 0x000A,0x6BA8,0x000A,0x6C02,0x000A,0x6C08,0x000A,0x6C26, + 0x000A,0x6C72,0x000A,0x6C90,0x000A,0x6CB6,0x000A,0x6CF2, + 0x000A,0x6CF8,0x000A,0x4602,0x000A,0x4602,0x000A,0x4602, + 0x000A,0x4602,0x000A,0x4644,0x000A,0x46F8,0x000A,0x47AC, + 0x000A,0x4860,0x000A,0x4646,0x000A,0x46FA,0x000A,0x47AE, + 0x000A,0x4862,0x000A,0x4916,0x000A,0x4924,0x000A,0x4A26, + 0x000A,0x4B28,0x000A,0x4C2A,0x000A,0x62A0,0x000A,0x62B4, + 0x000A,0x62DA,0x000A,0x62A0,0x000A,0x62B4,0x000A,0x631E, + 0x000A,0x6338,0x000A,0x94A4,0x000A,0x94C4,0x000A,0x9568 +}; +static UINT16 bloodwar_mcu_4_2b[] = { // Warrior 7 + 0x000A,0x94A4,0x000A,0x94C4,0x000A,0x9568,0x000A,0x9646, + 0x000A,0x9DFC,0x000A,0x9746,0x000A,0x9760,0x000A,0x9780, + 0x000A,0x9824,0x000A,0x98C8,0x000A,0x9E18,0x000A,0x9FF4, + 0x000A,0xA006,0x000A,0xA038,0x000A,0xA06A,0x000A,0xA0D4, + 0x000A,0xA0E6,0x000A,0xA118,0x000A,0xA14A,0x000A,0xA09C, + 0x000A,0xA0AA,0x000A,0xA0B8,0x000A,0xA0C6,0x000A,0xA17C, + 0x000A,0xA18A,0x000A,0xA198,0x000A,0xA1A6,0x000A,0x9970, + 0x000A,0x998A,0x000A,0x99B0,0x000A,0x9A44,0x000A,0x9AD8, + 0x000A,0x9B6C,0x000A,0x9B8C,0x000A,0x9BEA,0x000A,0x9C48, + 0x000A,0x9E34,0x000A,0x9E46,0x000A,0x9E78,0x000A,0x9EAA, + 0x000A,0x9F14,0x000A,0x9F26,0x000A,0x9F58,0x000A,0x9F8A, + 0x000A,0x9EDC,0x000A,0x9EEA,0x000A,0x9EF8,0x000A,0x9F06, + 0x000A,0x9FBC,0x000A,0x9FCA,0x000A,0x9FD8,0x000A,0x9FE6, + 0x000A,0x9CA6,0x000A,0x9D04,0x000A,0x9D86,0x000A,0x9CBA, + 0x000A,0x9D18,0x000A,0x9D9A,0x000A,0x9CF0,0x000A,0x9D72, + 0x000A,0x9DE8,0x000A,0xA260,0x000A,0xA296,0x000A,0xA2F0, + + 0x000A,0xA34A,0x000A,0xA3A4,0x000A,0xA3FE,0x000A,0xA4B0, + 0x000A,0xA562,0x000A,0xA614,0x000A,0xA67A,0x000A,0xA6F8, + 0x000A,0xA776,0x000A,0xA7F4,0x000A,0xA860,0x000A,0xA900, + 0x000A,0xA9A0,0x000A,0xB9F2,0x000A,0xBA22,0x000A,0xBA76, + 0x000A,0xBACA,0x000A,0xBB1E,0x000A,0xBB60,0x000A,0xBC00, + 0x000A,0xBCA0,0x000A,0xBD40,0x000A,0xBD88,0x000A,0xBDF4, + 0x000A,0xBE60,0x000A,0xBECC,0x000A,0xBF20,0x000A,0xBFA8, + 0x000A,0xC030,0x000A,0xAA40,0x000A,0xAA76,0x000A,0xAAD0, + 0x000A,0xAB2A,0x000A,0xAB84,0x000A,0xABEA,0x000A,0xAC88, + 0x000A,0xAD26,0x000A,0xADC4,0x000A,0xAE24,0x000A,0xAEB8, + 0x000A,0xAF4C,0x000A,0xAFE0,0x000A,0xB03A,0x000A,0xB0E2, + 0x000A,0xB18A,0x000A,0xC0B8,0x000A,0xC0E8,0x000A,0xC13C, + 0x000A,0xC190,0x000A,0xC1E4,0x000A,0xC226,0x000A,0xC2C6, + 0x000A,0xC366,0x000A,0xC406,0x000A,0xC44E,0x000A,0xC4BA, + 0x000A,0xC526,0x000A,0xC592,0x000A,0xC5D4,0x000A,0xC694, + 0x000A,0xC754,0x000A,0xB232,0x000A,0xB272,0x000A,0xB316, + + 0x000A,0xB3BA,0x000A,0xB45E,0x000A,0xB49E,0x000A,0xB502, + 0x000A,0xB566,0x000A,0xC814,0x000A,0xC848,0x000A,0xC8E0, + 0x000A,0xC978,0x000A,0xCA10,0x000A,0xCA44,0x000A,0xCA9C, + 0x000A,0xCAF4,0x000A,0xB5CA,0x000A,0xB622,0x000A,0xB6DE, + 0x000A,0xB79A,0x000A,0xB856,0x000A,0xB8A2,0x000A,0xB912, + 0x000A,0xB982,0x000A,0xCB4C,0x000A,0xCB80,0x000A,0xCC0E, + 0x000A,0xCC9C,0x000A,0xCD2A,0x000A,0xCD6A,0x000A,0xCDCE, + 0x000A,0xCE32,0x000A,0xA1B4,0x000A,0xA1F2,0x000A,0xA236, + 0x000A,0xDD1A,0x000A,0xDD26,0x000A,0xDD44,0x000A,0xDD6E, + 0x000A,0xDD7A,0x000A,0xDD98,0x000A,0xDDC2,0x000A,0xDDCE, + 0x000A,0xDDEC,0x000A,0xDE90,0x000A,0xDEA6,0x000A,0xDE16, + 0x000A,0xDE1E,0x000A,0xDEB2,0x000A,0xE13E,0x000A,0xDFDA, + 0x000A,0xE04E,0x000A,0xE0B4,0x000A,0xE0FC,0x000A,0xE1EE, + 0x000A,0xE2C0,0x000A,0xE67E,0x000A,0xE48A,0x000A,0xE848, + 0x000A,0xE5CA,0x000A,0xE9AA,0x000A,0xEA82,0x000A,0xEB74, + 0x000A,0xEC66,0x000A,0xED58,0x000A,0xEED0,0x000A,0xEFC2, + + 0x000A,0xF0B4,0x000A,0xF1A6,0x000A,0xF752,0x000A,0xF772, + 0x000A,0xF7AE,0x000A,0xF7EA,0x000A,0xF7F8,0x000A,0xF826, + 0x000A,0xF886,0x000A,0xF8C2,0x000A,0xF8C8,0x000A,0xF8F6, + 0x000A,0xF932,0x000A,0xF940,0x000A,0xF95E,0x000A,0xF96C, + 0x000A,0xF98A,0x000A,0xF9C6,0x000A,0xFA22,0x000A,0xFA5C, + 0x000A,0xFA6A,0x000A,0xFA90,0x000A,0xFACC,0x000A,0xFAE2, + 0x000A,0xFB00,0x000A,0xFB3C,0x000A,0xFB8E,0x000A,0xFBA4, + 0x000A,0xFBC2,0x000A,0xFC1C,0x000A,0xFC22,0x000A,0xFC40, + 0x000A,0xFC8C,0x000A,0xFCAA,0x000A,0xFCD0,0x000A,0xFD0C, + 0x000A,0xFD12,0x000A,0xCE96,0x000A,0xCFA0,0x000A,0xD0AA, + 0x000A,0xD1B4,0x000A,0xD2BE,0x000A,0xD4FA,0x000A,0xD75A, + 0x000A,0xD9DA,0x000A,0xDC7A,0x000A,0xDC7A,0x000A,0xDC7A, + 0x000A,0xDC7A,0x000A,0xF31E,0x000A,0xF344,0x000A,0xF364, + 0x000A,0xF31E,0x000A,0xF344,0x000A,0xF39C,0x000A,0xF3A6, + 0x000B,0x272C,0x000B,0x274C,0x000B,0x284C,0x000B,0x2924 +}; +static UINT16 bloodwar_mcu_4_2c[] = { // Warrior 8 + 0x000B,0x272C,0x000B,0x274C,0x000B,0x284C,0x000B,0x2924, + 0x000B,0x3242,0x000B,0x2A0E,0x000B,0x2A28,0x000B,0x2A48, + 0x000B,0x2B4C,0x000B,0x2C1A,0x000B,0x325E,0x000B,0x343A, + 0x000B,0x344C,0x000B,0x347E,0x000B,0x34B0,0x000B,0x351A, + 0x000B,0x352C,0x000B,0x355E,0x000B,0x3590,0x000B,0x34E2, + 0x000B,0x34F0,0x000B,0x34FE,0x000B,0x350C,0x000B,0x35C2, + 0x000B,0x35D0,0x000B,0x35DE,0x000B,0x35EC,0x000B,0x2D1A, + 0x000B,0x2D34,0x000B,0x2D66,0x000B,0x2DFE,0x000B,0x2E96, + 0x000B,0x2F2E,0x000B,0x2F66,0x000B,0x2FFE,0x000B,0x3096, + 0x000B,0x327A,0x000B,0x328C,0x000B,0x32BE,0x000B,0x32F0, + 0x000B,0x335A,0x000B,0x336C,0x000B,0x339E,0x000B,0x33D0, + 0x000B,0x3322,0x000B,0x3330,0x000B,0x333E,0x000B,0x334C, + 0x000B,0x3402,0x000B,0x3410,0x000B,0x341E,0x000B,0x342C, + 0x000B,0x312E,0x000B,0x3186,0x000B,0x31E4,0x000B,0x3142, + 0x000B,0x31A0,0x000B,0x31FE,0x000B,0x3172,0x000B,0x31D0, + 0x000B,0x322E,0x000B,0x3702,0x000B,0x373E,0x000B,0x37AE, + + 0x000B,0x381E,0x000B,0x388E,0x000B,0x38D6,0x000B,0x397C, + 0x000B,0x3A22,0x000B,0x3AC8,0x000B,0x3B10,0x000B,0x3B86, + 0x000B,0x3BFC,0x000B,0x3C72,0x000B,0x3CC0,0x000B,0x3D6C, + 0x000B,0x3E18,0x000B,0x4D98,0x000B,0x4DD4,0x000B,0x4E44, + 0x000B,0x4EB4,0x000B,0x4F24,0x000B,0x4F78,0x000B,0x501A, + 0x000B,0x50BC,0x000B,0x515E,0x000B,0x51AC,0x000B,0x5212, + 0x000B,0x5278,0x000B,0x52DE,0x000B,0x5320,0x000B,0x53D0, + 0x000B,0x5480,0x000B,0x3EC4,0x000B,0x3EF4,0x000B,0x3F58, + 0x000B,0x3FBC,0x000B,0x4020,0x000B,0x405C,0x000B,0x4120, + 0x000B,0x41E4,0x000B,0x42A8,0x000B,0x42DE,0x000B,0x4348, + 0x000B,0x43B2,0x000B,0x441C,0x000B,0x4458,0x000B,0x44D8, + 0x000B,0x4558,0x000B,0x5530,0x000B,0x5560,0x000B,0x55C4, + 0x000B,0x5628,0x000B,0x568C,0x000B,0x56C8,0x000B,0x5782, + 0x000B,0x583C,0x000B,0x58F6,0x000B,0x594A,0x000B,0x59BC, + 0x000B,0x5A2E,0x000B,0x5AA0,0x000B,0x5AE8,0x000B,0x5B8E, + 0x000B,0x5C34,0x000B,0x45D8,0x000B,0x4624,0x000B,0x46D4, + + 0x000B,0x4784,0x000B,0x4834,0x000B,0x4880,0x000B,0x48F0, + 0x000B,0x4960,0x000B,0x5CDA,0x000B,0x5D26,0x000B,0x5DD6, + 0x000B,0x5E86,0x000B,0x5F36,0x000B,0x5F82,0x000B,0x5FF2, + 0x000B,0x6062,0x000B,0x49D0,0x000B,0x4A10,0x000B,0x4AB4, + 0x000B,0x4B58,0x000B,0x4BFC,0x000B,0x4C48,0x000B,0x4CB8, + 0x000B,0x4D28,0x000B,0x60D2,0x000B,0x6112,0x000B,0x61B6, + 0x000B,0x625A,0x000B,0x62FE,0x000B,0x634A,0x000B,0x63BA, + 0x000B,0x642A,0x000B,0x35FA,0x000B,0x3666,0x000B,0x36D8, + 0x000B,0x6B1A,0x000B,0x6B26,0x000B,0x6B44,0x000B,0x6B6E, + 0x000B,0x6B7A,0x000B,0x6B98,0x000B,0x6BC2,0x000B,0x6BCE, + 0x000B,0x6BEC,0x000B,0x6C90,0x000B,0x6CA6,0x000B,0x6C16, + 0x000B,0x6C1E,0x000B,0x6CB2,0x000B,0x6EAE,0x000B,0x6D4A, + 0x000B,0x6DBE,0x000B,0x6E24,0x000B,0x6E6C,0x000B,0x6F5E, + 0x000B,0x7030,0x000B,0x73EE,0x000B,0x71FA,0x000B,0x75B8, + 0x000B,0x733A,0x000B,0x771A,0x000B,0x77F2,0x000B,0x78E4, + 0x000B,0x79D6,0x000B,0x7AC8,0x000B,0x7C40,0x000B,0x7D32, + + 0x000B,0x7E24,0x000B,0x7F16,0x000B,0x84AE,0x000B,0x84CE, + 0x000B,0x850A,0x000B,0x8546,0x000B,0x8554,0x000B,0x8582, + 0x000B,0x85E2,0x000B,0x861E,0x000B,0x8624,0x000B,0x8652, + 0x000B,0x868E,0x000B,0x869C,0x000B,0x86BA,0x000B,0x86C8, + 0x000B,0x86E6,0x000B,0x8722,0x000B,0x877E,0x000B,0x87B8, + 0x000B,0x87C6,0x000B,0x87EC,0x000B,0x8828,0x000B,0x883E, + 0x000B,0x885C,0x000B,0x8898,0x000B,0x88EA,0x000B,0x8900, + 0x000B,0x891E,0x000B,0x8978,0x000B,0x897E,0x000B,0x899C, + 0x000B,0x89E8,0x000B,0x8A06,0x000B,0x8A2C,0x000B,0x8A68, + 0x000B,0x8A6E,0x000B,0x649A,0x000B,0x649A,0x000B,0x649A, + 0x000B,0x649A,0x000B,0x64D0,0x000B,0x65B6,0x000B,0x66DC, + 0x000B,0x6802,0x000B,0x6928,0x000B,0x698C,0x000B,0x6A08, + 0x000B,0x6A84,0x000B,0x693C,0x000B,0x69A0,0x000B,0x6A1C, + 0x000B,0x6A98,0x000B,0x6B00,0x000B,0x808E,0x000B,0x80A2, + 0x000B,0x80C8,0x000B,0x808E,0x000B,0x80A2,0x000B,0x811C, + 0x000B,0x813E,0x000B,0xB188,0x000B,0xB1C0,0x000B,0xB308 +}; +static UINT16 bloodwar_mcu_4_2d[] = { // Warrior 9 + 0x0009,0x81A8,0x0009,0x81C8,0x0009,0x8270,0x0009,0x8328, + 0x0009,0x8A98,0x0009,0x8416,0x0009,0x8430,0x0009,0x8450, + 0x0009,0x84E8,0x0009,0x8580,0x0009,0x8AB4,0x0009,0x8C90, + 0x0009,0x8CA2,0x0009,0x8CD4,0x0009,0x8D06,0x0009,0x8D70, + 0x0009,0x8D82,0x0009,0x8DB4,0x0009,0x8DE6,0x0009,0x8D38, + 0x0009,0x8D46,0x0009,0x8D54,0x0009,0x8D62,0x0009,0x8E18, + 0x0009,0x8E26,0x0009,0x8E34,0x0009,0x8E42,0x0009,0x864E, + 0x0009,0x8668,0x0009,0x8694,0x0009,0x870C,0x0009,0x8784, + 0x0009,0x87FC,0x0009,0x8828,0x0009,0x88A0,0x0009,0x8918, + 0x0009,0x8AD0,0x0009,0x8AE2,0x0009,0x8B14,0x0009,0x8B46, + 0x0009,0x8BB0,0x0009,0x8BC2,0x0009,0x8BF4,0x0009,0x8C26, + 0x0009,0x8B78,0x0009,0x8B86,0x0009,0x8B94,0x0009,0x8BA2, + 0x0009,0x8C58,0x0009,0x8C66,0x0009,0x8C74,0x0009,0x8C82, + 0x0009,0x8990,0x0009,0x89EE,0x0009,0x8A46,0x0009,0x89A4, + 0x0009,0x8A02,0x0009,0x8A5A,0x0009,0x89DA,0x0009,0x8A32, + 0x0009,0x8A8A,0x0009,0x8F0E,0x0009,0x8F50,0x0009,0x8FB6, + + 0x0009,0x901C,0x0009,0x9082,0x0009,0x90DC,0x0009,0x9184, + 0x0009,0x922C,0x0009,0x92D4,0x0009,0x9310,0x0009,0x9370, + 0x0009,0x93D0,0x0009,0x9430,0x0009,0x94A2,0x0009,0x9548, + 0x0009,0x95EE,0x0009,0xA4F0,0x0009,0xA520,0x0009,0xA574, + 0x0009,0xA5C8,0x0009,0xA61C,0x0009,0xA66A,0x0009,0xA716, + 0x0009,0xA7C2,0x0009,0xA86E,0x0009,0xA8B0,0x0009,0xA926, + 0x0009,0xA99C,0x0009,0xAA12,0x0009,0xAA78,0x0009,0xAB12, + 0x0009,0xABAC,0x0009,0x9694,0x0009,0x96D0,0x0009,0x9730, + 0x0009,0x9790,0x0009,0x97F0,0x0009,0x9838,0x0009,0x98DE, + 0x0009,0x9984,0x0009,0x9A2A,0x0009,0x9A66,0x0009,0x9AD6, + 0x0009,0x9B46,0x0009,0x9BB6,0x0009,0x9C16,0x0009,0x9CC4, + 0x0009,0x9D72,0x0009,0xAC46,0x0009,0xAC6A,0x0009,0xACB2, + 0x0009,0xACFA,0x0009,0xAD42,0x0009,0xAD84,0x0009,0xAE34, + 0x0009,0xAEE4,0x0009,0xAF94,0x0009,0xAFEC,0x0009,0xB05C, + 0x0009,0xB0CC,0x0009,0xB13C,0x0009,0xB196,0x0009,0xB248, + 0x0009,0xB2FA,0x0009,0x9E20,0x0009,0x9E54,0x0009,0x9EEC, + + 0x0009,0x9F84,0x0009,0xA01C,0x0009,0xA050,0x0009,0xA0A8, + 0x0009,0xA100,0x0009,0xB3AC,0x0009,0xB3E0,0x0009,0xB478, + 0x0009,0xB510,0x0009,0xB5A8,0x0009,0xB5E8,0x0009,0xB64C, + 0x0009,0xB6B0,0x0009,0xA158,0x0009,0xA198,0x0009,0xA23C, + 0x0009,0xA2E0,0x0009,0xA384,0x0009,0xA3C4,0x0009,0xA428, + 0x0009,0xA48C,0x0009,0xB714,0x0009,0xB748,0x0009,0xB7E0, + 0x0009,0xB878,0x0009,0xB910,0x0009,0xB95C,0x0009,0xB9CC, + 0x0009,0xBA3C,0x0009,0x8E50,0x0009,0x8E82,0x0009,0x8ED2, + 0x0009,0xC388,0x0009,0xC394,0x0009,0xC3B2,0x0009,0xC3DC, + 0x0009,0xC3E8,0x0009,0xC406,0x0009,0xC430,0x0009,0xC43C, + 0x0009,0xC45A,0x0009,0xC4FE,0x0009,0xC514,0x0009,0xC484, + 0x0009,0xC48C,0x0009,0xC520,0x0009,0xC71C,0x0009,0xC5B8, + 0x0009,0xC62C,0x0009,0xC692,0x0009,0xC6DA,0x0009,0xC7CC, + 0x0009,0xC89E,0x0009,0xCC5C,0x0009,0xCA68,0x0009,0xCE26, + 0x0009,0xCBA8,0x0009,0xCF88,0x0009,0xD060,0x0009,0xD152, + 0x0009,0xD244,0x0009,0xD336,0x0009,0xD4AE,0x0009,0xD5A0, + + 0x0009,0xD692,0x0009,0xD784,0x0009,0xDDC4,0x0009,0xDDE4, + 0x0009,0xDE20,0x0009,0xDE5C,0x0009,0xDE6A,0x0009,0xDE98, + 0x0009,0xDEF8,0x0009,0xDF34,0x0009,0xDF3A,0x0009,0xDF68, + 0x0009,0xDFA4,0x0009,0xDFB2,0x0009,0xDFD0,0x0009,0xDFDE, + 0x0009,0xDFFC,0x0009,0xE038,0x0009,0xE094,0x0009,0xE0CE, + 0x0009,0xE0DC,0x0009,0xE102,0x0009,0xE13E,0x0009,0xE154, + 0x0009,0xE172,0x0009,0xE1AE,0x0009,0xE200,0x0009,0xE216, + 0x0009,0xE234,0x0009,0xE28E,0x0009,0xE294,0x0009,0xE2B2, + 0x0009,0xE2FE,0x0009,0xE31C,0x0009,0xE342,0x0009,0xE37E, + 0x0009,0xE384,0x0009,0xBAAC,0x0009,0xBAAC,0x0009,0xBAAC, + 0x0009,0xBAAC,0x0009,0xBB44,0x0009,0xBC0C,0x0009,0xBCF4, + 0x0009,0xBDFC,0x0009,0xBF24,0x0009,0xC00E,0x0009,0xC040, + 0x0009,0xC124,0x0009,0xC156,0x0009,0xC240,0x0009,0xC272, + 0x0009,0xC356,0x0009,0xD8FC,0x0009,0xD910,0x0009,0xD936, + 0x0009,0xD8FC,0x0009,0xD910,0x0009,0xD96E,0x0009,0xD8FC, + 0x0009,0xD910,0x0009,0xD9B8,0x0009,0xD9D2,0x000A,0x0E3C +}; diff --git a/src/burn/drivers/misc_post90s/nmk004.cpp b/src/burn/drivers/misc_post90s/nmk004.cpp new file mode 100644 index 00000000..6ba7fea2 --- /dev/null +++ b/src/burn/drivers/misc_post90s/nmk004.cpp @@ -0,0 +1,1008 @@ + +#include "burnint.h" +#include "nmk004.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +UINT8 *NMK004OKIROM0; +UINT8 *NMK004OKIROM1; +UINT8 *NMK004PROGROM; + +#define okim6295_w(x,y,z) MSM6295Command(x, z) +#define okim6295_r(x,y) MSM6295ReadStatus(x) + +#define ym2203_control_port_w(x, y, z) BurnYM2203Write(x, 0, z) +#define ym2203_write_port_w(x, y, z) BurnYM2203Write(x, 1, z) +#define ym2203_status_port_r(x,y) BurnYM2203Read(x, 0); +#define ym2203_read_port_r(x,y) BurnYM2203Read(x, 1) +#define device 0 +#define fatalerror printf +//#define logerror printf + +//-------------------------------------------------------------------------- + +#define FM_CHANNELS 6 +#define PSG_CHANNELS 3 +#define EFFECTS_CHANNELS 8 + +#define FM_FLAG_NEED_INITIALIZATION (1<<0) +#define FM_FLAG_UNKNOWN2 (1<<1) +#define FM_FLAG_NOTE_IS_PAUSE (1<<2) +#define FM_FLAG_UNKNOWN3 (1<<3) +#define FM_FLAG_MODULATE_NOTE (1<<4) +#define FM_FLAG_MUST_SEND_KEYON (1<<5) +#define FM_FLAG_MUST_SEND_CONFIGURATION (1<<6) +#define FM_FLAG_ACTIVE (1<<7) + +#define PSG_FLAG_ACTIVE (1<<0) +#define PSG_FLAG_NOTE_IS_PAUSE (1<<1) +#define PSG_FLAG_NEED_INITIALIZATION (1<<2) +#define PSG_FLAG_INITIALIZE_VOLUME (1<<3) +#define PSG_FLAG_NOTE_IS_NOISE (1<<5) +#define PSG_FLAG_NOISE_NOT_ENABLED (1<<6) + +#define EFFECTS_FLAG_NEED_INITIALIZATION (1<<0) +#define EFFECTS_FLAG_ACTIVE (1<<7) + +#define NOTE_PAUSE 0x0c + +struct psg_control +{ +/* C220 */ UINT8 flags; +/* C221-C222 */ UINT16 note_timer; +/* C223-C224 */ UINT16 note_length; +/* C225 */ UINT8 volume_timer; +/* C227-C228 */ UINT16 current; // current position in control table +/* C229-C22A */ UINT16 return_address[16]; // return address when control table calls a subtable + INT32 return_address_depth; +/* C22B-C22C */ UINT16 loop_start; // first instruction of loop +/* C22D */ UINT8 loop_times; // number of times to loop +/* C22E */ UINT8 volume_shape; +/* C22F */ UINT8 volume_position; +/* C230 */ UINT8 octave; // base octave +/* C231 */ UINT8 note; // note to play +/* C233 */ UINT8 note_period_hi_bits; +}; + +struct fm_control +{ +UINT8 note; +/* C020 */ UINT8 flags; +/* C021 */ UINT8 slot; // for ym2203 keyon command +/* C022-C039 */ UINT8 voice_params[0x18]; // parameters for the YM2203 to configure sound shape +/* C03A-C03B */ UINT16 f_number; +/* C03C */ UINT8 self_feedback; +/* C03D */ UINT8 note_duration_table_select; +/* C03E-C03F */ UINT16 current; // current position in control table +/* C040-C041 */ UINT16 loop_start; // first instruction of loop +/* C042 */ UINT8 loop_times; // number of times to loop +/* C043-C044 */ UINT16 return_address[16]; // return address when control table calls a subtable + INT32 return_address_depth; +/* C045 */ UINT8 octave; +/* C046-C047 */ UINT16 timer1; +/* C048-C049 */ UINT16 timer2; +/* C04A-C04B */ UINT16 timer1_duration; +/* C04C-C04D */ UINT16 timer2_duration; +/* C04E */ UINT8 modulation_table_number; +/* C04F-C050 */ UINT16 modulation_timer; +/* C051-C052 */ UINT16 modulation_table; +/* C053-C054 */ UINT16 modulation_table_position; +/* C055-C056 */ UINT16 note_period; +/* C057-C05A */ UINT8 voice_volume[4]; // parameters for the YM2203 to configure sound shape +/* C05C */ UINT8 must_update_voice_params; +}; + +struct effects_control +{ +/* C1A0 */ UINT8 flags; +/* C1BE-C1BF */ UINT16 current; // current position in control table +/* C1C0-C1C1 */ UINT16 loop_start; // first instruction of loop +/* C1C2 */ UINT8 loop_times; // number of times to loop +/* C1C3-C1C4 */ UINT16 return_address[16]; // return address when control table calls a subtable + INT32 return_address_depth; +/* C1C6-C1C7 */ UINT16 timer; +/* C1CA-C1CB */ UINT16 timer_duration; +}; + +static struct +{ + const UINT8 *rom; // NMK004 data ROM + UINT8 from_main; // command from main CPU + UINT8 to_main; // answer to main CPU + INT32 protection_check; + + INT32 ymdevice; + INT32 oki1device; + INT32 oki2device; + + /* C001 */ UINT8 last_command; // last command received + /* C016 */ UINT8 oki_playing; // bitmap of active Oki channels + /* C020-C19F */ struct fm_control fm_control[FM_CHANNELS]; + /* C220-C2DF */ struct psg_control psg_control[PSG_CHANNELS]; + /* C1A0-C21F */ struct effects_control effects_control[EFFECTS_CHANNELS]; +} NMK004_state; + + +#define SAMPLE_TABLE_0 0xefe0 +#define SAMPLE_TABLE_1 0xefe2 +#define FM_MODULATION_TABLE 0xefe4 +#define FM_NOTE_TABLE 0xefe6 +#define NOTE_LENGTH_TABLE_1 0xefe8 +#define NOTE_LENGTH_TABLE_2 0xefea +#define NOTE_LENGTH_TABLE_3 0xefec +#define PSG_VOLUME_TABLE 0xefee +#define COMMAND_TABLE 0xeff0 +#define PSG_NOTE_TABLE 0xeff2 + +static UINT8 read8(INT32 address) +{ + return NMK004_state.rom[address]; +} + +static UINT16 read16(INT32 address) +{ + return NMK004_state.rom[address] + 256 * NMK004_state.rom[address+1]; +} + +/***************************** + + OKI6295 + +*****************************/ + +static void oki_play_sample(INT32 sample_no) +{ + UINT16 table_start = (sample_no & 0x80) ? read16(SAMPLE_TABLE_1) : read16(SAMPLE_TABLE_0); + UINT8 byte1 = read8(table_start + 2 * (sample_no & 0x7f) + 0); + UINT8 byte2 = read8(table_start + 2 * (sample_no & 0x7f) + 1); + INT32 chip = (byte1 & 0x80) >> 7; + const INT32 okidevice = (chip) ? NMK004_state.oki2device : NMK004_state.oki1device; + + if ((byte1 & 0x7f) == 0) + { + // stop all channels + okim6295_w(okidevice, 0, 0x78 ); + } + else + { + INT32 sample = byte1 & 0x7f; + INT32 ch = byte2 & 0x03; + INT32 force = (byte2 & 0x80) >> 7; + + if (!force && (NMK004_state.oki_playing & (1 << (ch + 4*chip)))) + return; + + NMK004_state.oki_playing |= 1 << (ch + 4*chip); + + // stop channel + okim6295_w(okidevice, 0, (0x08 << ch) ); + + if (sample != 0) + { + UINT8 *rom = (chip == 0) ? NMK004OKIROM0 : NMK004OKIROM1; + INT32 bank = (byte2 & 0x0c) >> 2; + INT32 vol = (byte2 & 0x70) >> 4; + + if (bank != 3) + memcpy(rom + 0x20000,rom + 0x40000 + bank * 0x20000,0x20000); + + okim6295_w(okidevice, 0, 0x80 | sample ); + okim6295_w(okidevice, 0, (0x10 << ch) | vol ); + } + } +} + +static void oki_update_state(void) +{ + NMK004_state.oki_playing = ((okim6295_r(NMK004_state.oki2device, 0) & 0x0f) << 4) | (okim6295_r(NMK004_state.oki1device, 0) & 0x0f); +} + +/***************************** + + EFFECTS (OKI6295) + +*****************************/ + +static void effects_update(INT32 channel) +{ + struct effects_control *effects = &NMK004_state.effects_control[channel]; + + // advance the timers + if (effects->timer) + effects->timer--; + + + if (effects->flags & EFFECTS_FLAG_NEED_INITIALIZATION) + { + effects->flags = EFFECTS_FLAG_ACTIVE; + effects->timer = 0; + } + + + if (effects->flags & EFFECTS_FLAG_ACTIVE) + { + if (effects->timer == 0) + { + UINT8 token; + + do + { + token = read8(effects->current++); + + if (token == 0x0ef || (token & 0xf0) == 0xf0) + { + switch (token) + { + case 0xef: // play sample + oki_play_sample(read8(effects->current++)); + break; + + case 0xf6: // jump + effects->current = read16(effects->current); + break; + + case 0xf7: // begin repeat loop + effects->loop_times = read8(effects->current++); + effects->loop_start = effects->current; + break; + + case 0xf8: // end repeat loop + if (--effects->loop_times > 0) + effects->current = effects->loop_start; + break; + + case 0xf9: // call subtable + effects->return_address[effects->return_address_depth++] = effects->current + 2; + effects->current = read16(effects->current); + break; + + case 0xfa: // return from subtable + effects->current = effects->return_address[--effects->return_address_depth]; + break; + + case 0xfc: // ??? (hachamf command 04) + break; + + case 0xfd: // ??? (hachamf command 04) + break; + + case 0xff: // end + effects->flags = 0; // disable channel + return; + + default: + fatalerror("effects channel %d unsupported token %02x",channel,token); + } + } + } while (token == 0xef || (token & 0xf0) == 0xf0); + + effects->current--; + + if ((read8(effects->current) & 0x80) == 0) + { + if (read8(effects->current++) != 0x0c) + { + // this shouldn't happen on the effects channels (but it happens e.g. hachamf command 04) + } + } + + // optional note length (otherwise use the same length as the previous one) + if (read8(effects->current) & 0x80) + { + UINT16 table_start = read16(NOTE_LENGTH_TABLE_1); + + effects->timer_duration = read16(table_start + 2 * (read8(effects->current++) & 0x7f)); + } + + effects->timer = effects->timer_duration; + } + } +} + +/***************************** + + YM2203 - FM + +*****************************/ + +static void fm_update(INT32 channel) +{ + struct fm_control *fm = &NMK004_state.fm_control[channel]; + + // advance the timers + if (fm->timer1) + fm->timer1--; + + if (fm->timer2) + fm->timer2--; + + if (fm->modulation_timer) + fm->modulation_timer--; + + + if (fm->flags & FM_FLAG_NEED_INITIALIZATION) + { + fm->flags = FM_FLAG_ACTIVE; + fm->timer1 = 0; + } + + + if (fm->flags & FM_FLAG_ACTIVE) + { + if (fm->timer1 == 0) + { + UINT8 token; + + do + { + token = read8(fm->current++); + + if (token == 0x0ef || (token & 0xf0) == 0xf0) + { + INT32 i; + + switch (token) + { + case 0xf0: // slot (for keyon ym2203 command) + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + fm->slot = read8(fm->current++); + if (channel < 3 || !(NMK004_state.fm_control[channel-3].flags & FM_FLAG_ACTIVE)) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off + ym2203_write_port_w(NMK004_state.ymdevice, 0, channel % 3); + } + break; + + case 0xf1: // sound shape + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + for (i = 0x00; i < 0x04; i++) + fm->voice_params[i] = read8(fm->current++); + break; + + case 0xf2: // sound shape + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + for (i = 0; i < 4; i++) + fm->voice_volume[i] = read8(fm->current++); + break; + + case 0xf3: // sound shape + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + for (i = 0x08; i < 0x18; i++) + fm->voice_params[i] = read8(fm->current++); + break; + + case 0xf4: // set self-feedback + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + fm->self_feedback = read8(fm->current++); + break; + + case 0xf5: // select note duration table + fm->note_duration_table_select = read8(fm->current++); + break; + + case 0xf6: // jump + fm->current = read16(fm->current); + break; + + case 0xf7: // begin repeat loop + fm->loop_times = read8(fm->current++); + fm->loop_start = fm->current; + break; + + case 0xf8: // end repeat loop + if (--fm->loop_times > 0) + fm->current = fm->loop_start; + break; + + case 0xf9: // call subtable + fm->return_address[fm->return_address_depth++] = fm->current + 2; + fm->current = read16(fm->current); + break; + + case 0xfa: // return from subtable + fm->current = fm->return_address[--fm->return_address_depth]; + break; + + case 0xfb: // set octave + fm->octave = read8(fm->current++); + break; + + case 0xfc: // ??? + fm->flags |= FM_FLAG_UNKNOWN2; + fm->flags |= FM_FLAG_UNKNOWN3; + break; + + case 0xfd: // ??? + fm->flags &= ~FM_FLAG_UNKNOWN2; + break; + + case 0xfe: // set note modulation + fm->modulation_table_number = read8(fm->current++); + if (fm->modulation_table_number == 0) + { + fm->flags &= ~FM_FLAG_MODULATE_NOTE; + } + else + { + UINT16 table_start = read16(FM_MODULATION_TABLE); + + fm->modulation_table = read16(table_start + 2 * (fm->modulation_table_number - 1)); + fm->modulation_timer = read16(fm->modulation_table); + fm->modulation_table_position = fm->modulation_table + 2; + fm->flags |= FM_FLAG_MODULATE_NOTE; + } + break; + + case 0xff: // end + fm->flags = FM_FLAG_MUST_SEND_CONFIGURATION; // disable channel + for (i = 0x04; i < 0x08; i++) + fm->voice_params[i] = 0x7f; + for (i = 0x14; i < 0x18; i++) + fm->voice_params[i] = 0x0f; + return; + + default: + fatalerror("fm channel %d unsupported token %02x",channel,token); + } + } + } while (token == 0xef || (token & 0xf0) == 0xf0); + + fm->current--; + + if ((read8(fm->current) & 0x80) == 0) + { + INT32 note = read8(fm->current++); + + fm->note = note; + if ((note & 0x0f) == NOTE_PAUSE) + fm->flags |= FM_FLAG_NOTE_IS_PAUSE; + else + { + UINT16 table_start = read16(FM_NOTE_TABLE); + UINT16 period = read16(table_start + 2 * (note & 0x0f)); + UINT8 octave = ((fm->octave << 4) + note) & 0xf0; + + fm->flags &= ~FM_FLAG_NOTE_IS_PAUSE; + fm->note_period = period | (octave << 7); + + fm->must_update_voice_params = 1; + } + } + + // optional note length (otherwise use the same length as the previous one) + if (read8(fm->current) & 0x80) + { + UINT16 table_start; + UINT8 duration = read8(fm->current++) & 0x7f; + + table_start = read16(NOTE_LENGTH_TABLE_1); + fm->timer1_duration = read16(table_start + 2 * duration); + + table_start = fm->note_duration_table_select ? read16(NOTE_LENGTH_TABLE_3) : read16(NOTE_LENGTH_TABLE_2); + fm->timer2_duration = read16(table_start + 2 * duration); + } + + fm->timer1 = fm->timer1_duration; + fm->timer2 = fm->timer2_duration; + + + if (!(fm->flags & FM_FLAG_NOTE_IS_PAUSE) && + ((fm->flags & FM_FLAG_UNKNOWN3) || !(fm->flags & FM_FLAG_UNKNOWN2))) + { + fm->flags &= ~FM_FLAG_UNKNOWN3; + fm->flags |= FM_FLAG_MUST_SEND_KEYON; + fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; + } + } + } + + if ((fm->flags & FM_FLAG_MODULATE_NOTE) && (fm->flags & FM_FLAG_MUST_SEND_KEYON)) + { + fm->modulation_timer = read16(fm->modulation_table); + fm->modulation_table_position = fm->modulation_table + 2; + } + + if (!(fm->flags & FM_FLAG_MODULATE_NOTE) || (fm->flags & FM_FLAG_MUST_SEND_KEYON) || fm->must_update_voice_params) + { + INT32 i; + + fm->must_update_voice_params = 0; + + for (i = 0; i < 4; i++) + fm->voice_params[0x04 + i] = fm->voice_volume[i]; + + fm->f_number = fm->note_period; + } + else + { + if (fm->modulation_timer == 0) + { + INT32 i; + UINT16 a; + + for (i = 0; i < 4; i++) + fm->voice_params[0x04 + i] = fm->voice_volume[i]; + + fm->modulation_table_position++; + a = read8(fm->modulation_table_position++); + if (a & 0x80) // sign extend + a |= 0xff00; + a *= 4; + + fm->f_number = fm->note_period + a; + + fm->modulation_timer = read8(fm->modulation_table_position++); // modulation_timer is UINT16 but this is just 8-bit + + if (read8(fm->modulation_table_position) == 0x80) // end of table - repeat + { + fm->modulation_table_position = fm->modulation_table + 2; + } + else if (read8(fm->modulation_table_position) == 0x88) // end of table - stop + { + fm->flags &= ~FM_FLAG_MODULATE_NOTE; + } + } + } +} + +static void fm_voices_update(void) +{ + static const INT32 ym2203_registers[0x18] = + { + 0x30,0x38,0x34,0x3C,0x40,0x48,0x44,0x4C,0x50,0x58,0x54,0x5C,0x60,0x68,0x64,0x6C, + 0x70,0x78,0x74,0x7C,0x80,0x88,0x84,0x8C + }; + INT32 channel,i; + + for (channel = 0; channel < 3;channel++) + { + struct fm_control *fm1 = &NMK004_state.fm_control[channel]; + struct fm_control *fm2 = &NMK004_state.fm_control[channel + 3]; + + if (fm1->flags & FM_FLAG_MUST_SEND_CONFIGURATION) + { + fm1->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION; + + for (i = 0; i < 0x18; i++) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_registers[i] + channel); + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->voice_params[i]); + } + } + + if (fm2->flags & FM_FLAG_MUST_SEND_CONFIGURATION) + { + fm2->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION; + + if (!(fm1->flags & FM_FLAG_ACTIVE)) + { + for (i = 0; i < 0x18; i++) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_registers[i] + channel); + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->voice_params[i]); + } + } + } + + if (fm1->flags & FM_FLAG_ACTIVE) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xb0 + channel); // self-feedback + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->self_feedback); + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa4 + channel); // F-number + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->f_number >> 8); + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa0 + channel); // F-number + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->f_number & 0xff); + } + else + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xb0 + channel); // self-feedback + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->self_feedback); + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa4 + channel); // F-number + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->f_number >> 8); + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa0 + channel); // F-number + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->f_number & 0xff); + } + + if (fm1->flags & FM_FLAG_MUST_SEND_KEYON) + { + fm1->flags &= ~FM_FLAG_MUST_SEND_KEYON; + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->slot | channel); + } + + if (fm2->flags & FM_FLAG_MUST_SEND_KEYON) + { + fm2->flags &= ~FM_FLAG_MUST_SEND_KEYON; + + if (!(fm1->flags & FM_FLAG_ACTIVE)) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off + ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->slot | channel); + } + } + } +} + +/***************************** + + YM2203 - PSG + +*****************************/ + +static void psg_update(INT32 channel) +{ + struct psg_control *psg = &NMK004_state.psg_control[channel]; + + // advance the timers + if (psg->note_timer) + psg->note_timer--; + + if (psg->volume_timer) + psg->volume_timer--; + + if (psg->flags & PSG_FLAG_NEED_INITIALIZATION) + { + psg->flags &= ~PSG_FLAG_NEED_INITIALIZATION; + psg->flags |= PSG_FLAG_ACTIVE; + + if (psg->flags & PSG_FLAG_NOTE_IS_NOISE) + { + INT32 enable; + + psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE; + psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED; + + // enable noise, disable tone on this channel + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); + enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); + enable |= (0x01 << channel); // disable tone + enable &= ~(0x08 << channel); // enable noise + ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); + } + + + psg->note_timer = 0; + psg->volume_timer = 0; + psg->octave = 0; + } + + if (psg->flags & PSG_FLAG_ACTIVE) + { + if (psg->note_timer == 0) + { + UINT8 token; + + do + { + token = read8(psg->current++); + + if ((token & 0xf0) == 0xf0) + { + INT32 enable; + + switch (token) + { + case 0xf0: // noise + psg->flags |= PSG_FLAG_NOTE_IS_NOISE; + break; + + case 0xf1: // note + psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE; + psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED; + + // enable noise, disable tone on this channel + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); + enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); + enable |= (0x01 << channel); // disable tone + enable &= ~(0x08 << channel); // enable noise + ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); + break; + + case 0xf2: // set volume shape + case 0xf3: + case 0xf4: + case 0xf5: + psg->volume_shape = read8(psg->current++); + break; + + case 0xf6: // jump + psg->current = read16(psg->current); + break; + + case 0xf7: // begin repeat loop + psg->loop_times = read8(psg->current++); + psg->loop_start = psg->current; + break; + + case 0xf8: // end repeat loop + if (--psg->loop_times > 0) + psg->current = psg->loop_start; + break; + + case 0xf9: // call subtable + psg->return_address[psg->return_address_depth++] = psg->current + 2; + psg->current = read16(psg->current); + break; + + case 0xfa: // return from subtable + psg->current = psg->return_address[--psg->return_address_depth]; + break; + + case 0xfb: // set octave + case 0xfc: + case 0xfd: + case 0xfe: + psg->octave = read8(psg->current++); + break; + + case 0xff: // end + psg->flags = 0; // disable channel + psg->volume_shape = 0; + + // mute channel + ym2203_control_port_w(NMK004_state.ymdevice, 0, 8 + channel); + ym2203_write_port_w(NMK004_state.ymdevice, 0, 0); + return; + } + } + } while ((token & 0xf0) == 0xf0); + + // token is the note to play + psg->note = token; + if ((psg->note & 0x0f) > NOTE_PAUSE) + { + + } + + // optional note length (otherwise use the same length as the previous one) + if (read8(psg->current) & 0x80) + { + UINT16 table_start = read16(NOTE_LENGTH_TABLE_1); + + psg->note_length = read16(table_start + 2 * (read8(psg->current++) & 0x7f)); + } + + psg->note_timer = psg->note_length; + psg->volume_timer = 0; + + psg->flags |= PSG_FLAG_INITIALIZE_VOLUME; + + if (psg->note == NOTE_PAUSE) + psg->flags |= PSG_FLAG_NOTE_IS_PAUSE; + else + { + psg->flags &= ~PSG_FLAG_NOTE_IS_PAUSE; + + if (!(psg->flags & PSG_FLAG_NOTE_IS_NOISE)) + { + UINT16 table_start = read16(PSG_NOTE_TABLE); + UINT16 period = read16(table_start + 2 * (psg->note & 0x0f)); + UINT8 octave = psg->octave + ((psg->note & 0xf0) >> 4); + + period >>= octave; + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 2 * channel + 1); + ym2203_write_port_w(NMK004_state.ymdevice, 0, (period & 0x0f00) >> 8); + ym2203_control_port_w(NMK004_state.ymdevice, 0, 2 * channel + 0); + ym2203_write_port_w(NMK004_state.ymdevice, 0, (period & 0x00ff)); + + psg->note_period_hi_bits = (period & 0x0f00) >> 8; + } + else + { + if (!(psg->flags & PSG_FLAG_NOISE_NOT_ENABLED)) + { + INT32 enable; + + psg->flags |= PSG_FLAG_NOISE_NOT_ENABLED; + + // disable noise, enable tone on this channel + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); + enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); + enable &= ~(0x01 << channel); // enable tone + enable |= (0x08 << channel); // disable noise + ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); + } + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x06); // noise period + ym2203_write_port_w(NMK004_state.ymdevice, 0, psg->note); + psg->note_period_hi_bits = psg->note; + } + } + } + + if (psg->volume_timer == 0) + { + UINT16 table_start = read16(PSG_VOLUME_TABLE); + UINT16 vol_table_start = read16(table_start + 2 * psg->volume_shape); + INT32 volume; + + if (psg->flags & PSG_FLAG_INITIALIZE_VOLUME) + { + psg->flags &= ~PSG_FLAG_INITIALIZE_VOLUME; + psg->volume_position = 0; + } + + volume = read8(vol_table_start + psg->volume_position++); + psg->volume_timer = read8(vol_table_start + psg->volume_position++); + + if (psg->flags & PSG_FLAG_NOTE_IS_PAUSE) + volume = 0; + + // set volume + ym2203_control_port_w(NMK004_state.ymdevice, 0, 8 + channel); + ym2203_write_port_w(NMK004_state.ymdevice, 0, volume & 0x0f); + } + } +} + +/***************************** + + Command processing + +*****************************/ + +static void get_command() +{ + static const UINT8 from_main[] = + { + 0x00,0x22,0x62,0x8c,0xc7,0x00,0x00,0x3f,0x7f,0x89,0xc7,0x00,0x00,0x2b,0x6b + }; + static const UINT8 to_main[] = + { + 0x82,0xc7,0x00,0x2c,0x6c,0x00,0x9f,0xc7,0x00,0x29,0x69,0x00,0x8b,0xc7,0x00 + }; + + UINT8 cmd = NMK004_state.from_main; + + if (NMK004_state.protection_check < (INT32)sizeof(to_main)) + { + // startup handshake + if (cmd == from_main[NMK004_state.protection_check]) + { +// logerror("advance handshake to %02x\n",to_main[NMK004_state.protection_check]); + NMK004_state.to_main = to_main[NMK004_state.protection_check++]; + } + } + else + { + // send command back to main CPU to acknowledge reception + NMK004_state.to_main = cmd; + } + + if (NMK004_state.last_command != cmd) + { + UINT16 table_start = read16(COMMAND_TABLE); + UINT16 cmd_table = read16(table_start + 2 * cmd); + + NMK004_state.last_command = cmd; + + if ((cmd_table & 0xff00) == 0) + { + oki_play_sample(cmd_table); + } + else + { + INT32 channel; + + while ((channel = read8(cmd_table++)) != 0xff) + { + table_start = read16(cmd_table); + cmd_table += 2; + + if (channel == 0xef) break; // bioship bug? + + if (channel < FM_CHANNELS) + { + NMK004_state.fm_control[channel].current = table_start; + NMK004_state.fm_control[channel].return_address_depth = 0; + NMK004_state.fm_control[channel].flags |= FM_FLAG_NEED_INITIALIZATION; + } + else + { + channel -= FM_CHANNELS; + if (channel < PSG_CHANNELS) + { + NMK004_state.psg_control[channel].current = table_start; + NMK004_state.psg_control[channel].return_address_depth = 0; + NMK004_state.psg_control[channel].flags |= PSG_FLAG_NEED_INITIALIZATION; + } + else + { + channel -= PSG_CHANNELS; + if (channel >= EFFECTS_CHANNELS) + { + + } + NMK004_state.effects_control[channel].current = table_start; + NMK004_state.effects_control[channel].return_address_depth = 0; + NMK004_state.effects_control[channel].flags |= EFFECTS_FLAG_NEED_INITIALIZATION; + } + } + } + } + } +} + +static void update_music(void) +{ + INT32 channel; + + for (channel = 0; channel < FM_CHANNELS; channel++) + fm_update(channel); + fm_voices_update(); + + for (channel = 0; channel < PSG_CHANNELS; channel++) + psg_update(channel); + + for (channel = 0; channel < EFFECTS_CHANNELS; channel++) + effects_update(channel); +} + +void NMK004_irq(INT32 irq) +{ + if (irq) + { + INT32 status = ym2203_status_port_r(device,0); + + if (status & 1) // timer A expired + { + oki_update_state(); + get_command(); + update_music(); + + // restart timer + ym2203_control_port_w(device, 0, 0x27); + ym2203_write_port_w(device, 0, 0x15); + } + } +} + +void NMK004_init() +{ + static const UINT8 ym2203_init[] = + { + 0x07,0x38,0x08,0x00,0x09,0x00,0x0A,0x00,0x24,0xB3,0x25,0x00,0x26,0xF9,0x27,0x15, + 0x28,0x00,0x28,0x01,0x28,0x02,0x40,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x45,0x00, + 0x46,0x00,0x48,0x00,0x49,0x00,0x4A,0x00,0x4C,0x00,0x4D,0x00,0x4E,0x00,0xFF, + }; + INT32 i; + + memset(&NMK004_state, 0, sizeof(NMK004_state)); + + NMK004_state.ymdevice = 0; + NMK004_state.oki1device = 0; + NMK004_state.oki2device = 1; + NMK004_state.rom = NMK004PROGROM; + + ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x2f); + + i = 0; + while (ym2203_init[i] != 0xff) + { + ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_init[i++]); + ym2203_write_port_w(NMK004_state.ymdevice, 0, ym2203_init[i++]); + } + + NMK004_state.oki_playing = 0; + + oki_play_sample(0); + + NMK004_state.protection_check = 0; +} + +void NMK004Write(INT32, INT32 data) +{ + NMK004_state.from_main = data & 0xff; +} + +UINT8 NMK004Read() +{ + return NMK004_state.to_main; +} + diff --git a/src/burn/drivers/misc_post90s/nmk004.h b/src/burn/drivers/misc_post90s/nmk004.h new file mode 100644 index 00000000..45526df2 --- /dev/null +++ b/src/burn/drivers/misc_post90s/nmk004.h @@ -0,0 +1,10 @@ +extern UINT8 *NMK004OKIROM0; +extern UINT8 *NMK004OKIROM1; +extern UINT8 *NMK004PROGROM; + +void NMK004_init(); + +void NMK004Write(INT32, INT32 data); +UINT8 NMK004Read(); + +void NMK004_irq(INT32 irq); diff --git a/src/burn/drivers/misc_pre90s/d_1942.cpp b/src/burn/drivers/misc_pre90s/d_1942.cpp new file mode 100644 index 00000000..33a6485c --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_1942.cpp @@ -0,0 +1,1091 @@ +#include "tiles_generic.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvFgVideoRam = NULL; +static UINT8 *DrvBgVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPromRed = NULL; +static UINT8 *DrvPromGreen = NULL; +static UINT8 *DrvPromBlue = NULL; +static UINT8 *DrvPromCharLookup = NULL; +static UINT8 *DrvPromTileLookup = NULL; +static UINT8 *DrvPromSpriteLookup = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[6]; + +static UINT8 DrvRomBank; +static UINT8 DrvPaletteBank; +static UINT8 DrvBgScroll[2]; +static UINT8 DrvFlipScreen; +static UINT8 DrvSoundLatch; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 4, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + + +STDINPUTINFO(Drv) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xf7, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x12, 0x01, 0x07, 0x01, "4 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x02, "3 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x04, "2 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x12, 0x01, 0x07, 0x03, "2 Coins 3 Plays" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x08, 0x00, "Upright" }, + {0x12, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x30, 0x30, "20k 80k 80k+" }, + {0x12, 0x01, 0x30, 0x20, "20k 100k 100k+" }, + {0x12, 0x01, 0x30, 0x10, "30k 80k 80k+" }, + {0x12, 0x01, 0x30, 0x00, "30k 100k 100k+" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0xc0, 0x80, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x00, "5" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x07, 0x01, "4 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x02, "3 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x04, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x03, "2 Coins 3 Plays" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x40, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Screen Stop" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo DrvRomDesc[] = { + { "srb-03.m3", 0x04000, 0xd9dafcc3, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "srb-04.m4", 0x04000, 0xda0cf924, BRF_ESS | BRF_PRG }, // 1 + { "srb-05.m5", 0x04000, 0xd102911c, BRF_ESS | BRF_PRG }, // 2 + { "srb-06.m6", 0x02000, 0x466f8248, BRF_ESS | BRF_PRG }, // 3 + { "srb-07.m7", 0x04000, 0x0d31038c, BRF_ESS | BRF_PRG }, // 4 + + { "sr-01.c11", 0x04000, 0xbd87f06b, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "sr-02.f2", 0x02000, 0x6ebca191, BRF_GRA }, // 6 Characters + + { "sr-08.a1", 0x02000, 0x3884d9eb, BRF_GRA }, // 7 Tiles + { "sr-09.a2", 0x02000, 0x999cf6e0, BRF_GRA }, // 8 + { "sr-10.a3", 0x02000, 0x8edb273a, BRF_GRA }, // 9 + { "sr-11.a4", 0x02000, 0x3a2726c3, BRF_GRA }, // 10 + { "sr-12.a5", 0x02000, 0x1bd3d8bb, BRF_GRA }, // 11 + { "sr-13.a6", 0x02000, 0x658f02c4, BRF_GRA }, // 12 + + { "sr-14.l1", 0x04000, 0x2528bec6, BRF_GRA }, // 13 Sprites + { "sr-15.l2", 0x04000, 0xf89287aa, BRF_GRA }, // 14 + { "sr-16.n1", 0x04000, 0x024418f8, BRF_GRA }, // 15 + { "sr-17.n2", 0x04000, 0xe2c7e489, BRF_GRA }, // 16 + + { "sb-5.e8", 0x00100, 0x93ab8153, BRF_GRA }, // 17 PROMs + { "sb-6.e9", 0x00100, 0x8ab44f7d, BRF_GRA }, // 18 + { "sb-7.e10", 0x00100, 0xf4ade9a4, BRF_GRA }, // 19 + { "sb-0.f1", 0x00100, 0x6047d91b, BRF_GRA }, // 20 + { "sb-4.d6", 0x00100, 0x4858968d, BRF_GRA }, // 21 + { "sb-8.k3", 0x00100, 0xf6fad943, BRF_GRA }, // 22 + { "sb-2.d1", 0x00100, 0x8bb8b3df, BRF_GRA }, // 23 + { "sb-3.d2", 0x00100, 0x3b0c99af, BRF_GRA }, // 24 + { "sb-1.k6", 0x00100, 0x712ac508, BRF_GRA }, // 25 + { "sb-9.m11", 0x00100, 0x4921635c, BRF_GRA }, // 26 +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvaRomDesc[] = { + { "sra-03.m3", 0x04000, 0x40201bab, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "sr-04.m4", 0x04000, 0xa60ac644, BRF_ESS | BRF_PRG }, // 1 + { "sr-05.m5", 0x04000, 0x835f7b24, BRF_ESS | BRF_PRG }, // 2 + { "sr-06.m6", 0x02000, 0x821c6481, BRF_ESS | BRF_PRG }, // 3 + { "sr-07.m7", 0x04000, 0x5df525e1, BRF_ESS | BRF_PRG }, // 4 + + { "sr-01.c11", 0x04000, 0xbd87f06b, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "sr-02.f2", 0x02000, 0x6ebca191, BRF_GRA }, // 6 Characters + + { "sr-08.a1", 0x02000, 0x3884d9eb, BRF_GRA }, // 7 Tiles + { "sr-09.a2", 0x02000, 0x999cf6e0, BRF_GRA }, // 8 + { "sr-10.a3", 0x02000, 0x8edb273a, BRF_GRA }, // 9 + { "sr-11.a4", 0x02000, 0x3a2726c3, BRF_GRA }, // 10 + { "sr-12.a5", 0x02000, 0x1bd3d8bb, BRF_GRA }, // 11 + { "sr-13.a6", 0x02000, 0x658f02c4, BRF_GRA }, // 12 + + { "sr-14.l1", 0x04000, 0x2528bec6, BRF_GRA }, // 13 Sprites + { "sr-15.l2", 0x04000, 0xf89287aa, BRF_GRA }, // 14 + { "sr-16.n1", 0x04000, 0x024418f8, BRF_GRA }, // 15 + { "sr-17.n2", 0x04000, 0xe2c7e489, BRF_GRA }, // 16 + + { "sb-5.e8", 0x00100, 0x93ab8153, BRF_GRA }, // 17 PROMs + { "sb-6.e9", 0x00100, 0x8ab44f7d, BRF_GRA }, // 18 + { "sb-7.e10", 0x00100, 0xf4ade9a4, BRF_GRA }, // 19 + { "sb-0.f1", 0x00100, 0x6047d91b, BRF_GRA }, // 20 + { "sb-4.d6", 0x00100, 0x4858968d, BRF_GRA }, // 21 + { "sb-8.k3", 0x00100, 0xf6fad943, BRF_GRA }, // 22 + { "sb-2.d1", 0x00100, 0x8bb8b3df, BRF_GRA }, // 23 + { "sb-3.d2", 0x00100, 0x3b0c99af, BRF_GRA }, // 24 + { "sb-1.k6", 0x00100, 0x712ac508, BRF_GRA }, // 25 + { "sb-9.m11", 0x00100, 0x4921635c, BRF_GRA }, // 26 +}; + +STD_ROM_PICK(Drva) +STD_ROM_FN(Drva) + +static struct BurnRomInfo DrvablRomDesc[] = { + { "3.bin", 0x08000, 0xf3184f5a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "5.bin", 0x04000, 0x835f7b24, BRF_ESS | BRF_PRG }, // 1 + { "7.bin", 0x08000, 0x2f456c6e, BRF_ESS | BRF_PRG }, // 2 + + { "1.bin", 0x04000, 0xbd87f06b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "2.bin", 0x02000, 0x6ebca191, BRF_GRA }, // 4 Characters + + { "9.bin", 0x04000, 0x60329fa4, BRF_GRA }, // 5 Tiles + { "11.bin", 0x04000, 0x66bac116, BRF_GRA }, // 6 + { "13.bin", 0x04000, 0x623fcec1, BRF_GRA }, // 7 + + { "14.bin", 0x08000, 0xdf2345ef, BRF_GRA }, // 8 Sprites + { "16.bin", 0x08000, 0xc106b1ed, BRF_GRA }, // 9 + + { "sb-5.e8", 0x00100, 0x93ab8153, BRF_GRA }, // 10 PROMs + { "sb-6.e9", 0x00100, 0x8ab44f7d, BRF_GRA }, // 11 + { "sb-7.e10", 0x00100, 0xf4ade9a4, BRF_GRA }, // 12 + { "sb-0.f1", 0x00100, 0x6047d91b, BRF_GRA }, // 13 + { "sb-4.d6", 0x00100, 0x4858968d, BRF_GRA }, // 14 + { "sb-8.k3", 0x00100, 0xf6fad943, BRF_GRA }, // 15 + { "sb-2.d1", 0x00100, 0x8bb8b3df, BRF_GRA }, // 16 + { "sb-3.d2", 0x00100, 0x3b0c99af, BRF_GRA }, // 17 + { "sb-1.k6", 0x00100, 0x712ac508, BRF_GRA }, // 18 + { "sb-9.m11", 0x00100, 0x4921635c, BRF_GRA }, // 19 +}; + +STD_ROM_PICK(Drvabl) +STD_ROM_FN(Drvabl) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "sr-03.m3", 0x04000, 0x612975f2, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "sr-04.m4", 0x04000, 0xa60ac644, BRF_ESS | BRF_PRG }, // 1 + { "sr-05.m5", 0x04000, 0x835f7b24, BRF_ESS | BRF_PRG }, // 2 + { "sr-06.m6", 0x02000, 0x821c6481, BRF_ESS | BRF_PRG }, // 3 + { "sr-07.m7", 0x04000, 0x5df525e1, BRF_ESS | BRF_PRG }, // 4 + + { "sr-01.c11", 0x04000, 0xbd87f06b, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "sr-02.f2", 0x02000, 0x6ebca191, BRF_GRA }, // 6 Characters + + { "sr-08.a1", 0x02000, 0x3884d9eb, BRF_GRA }, // 7 Tiles + { "sr-09.a2", 0x02000, 0x999cf6e0, BRF_GRA }, // 8 + { "sr-10.a3", 0x02000, 0x8edb273a, BRF_GRA }, // 9 + { "sr-11.a4", 0x02000, 0x3a2726c3, BRF_GRA }, // 10 + { "sr-12.a5", 0x02000, 0x1bd3d8bb, BRF_GRA }, // 11 + { "sr-13.a6", 0x02000, 0x658f02c4, BRF_GRA }, // 12 + + { "sr-14.l1", 0x04000, 0x2528bec6, BRF_GRA }, // 13 Sprites + { "sr-15.l2", 0x04000, 0xf89287aa, BRF_GRA }, // 14 + { "sr-16.n1", 0x04000, 0x024418f8, BRF_GRA }, // 15 + { "sr-17.n2", 0x04000, 0xe2c7e489, BRF_GRA }, // 16 + + { "sb-5.e8", 0x00100, 0x93ab8153, BRF_GRA }, // 17 PROMs + { "sb-6.e9", 0x00100, 0x8ab44f7d, BRF_GRA }, // 18 + { "sb-7.e10", 0x00100, 0xf4ade9a4, BRF_GRA }, // 19 + { "sb-0.f1", 0x00100, 0x6047d91b, BRF_GRA }, // 20 + { "sb-4.d6", 0x00100, 0x4858968d, BRF_GRA }, // 21 + { "sb-8.k3", 0x00100, 0xf6fad943, BRF_GRA }, // 22 + { "sb-2.d1", 0x00100, 0x8bb8b3df, BRF_GRA }, // 23 + { "sb-3.d2", 0x00100, 0x3b0c99af, BRF_GRA }, // 24 + { "sb-1.k6", 0x00100, 0x712ac508, BRF_GRA }, // 25 + { "sb-9.m11", 0x00100, 0x4921635c, BRF_GRA }, // 26 +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo DrvwRomDesc[] = { + { "sw-03.m3", 0x04000, 0xafd79770, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "sw-04.m4", 0x04000, 0x933d9910, BRF_ESS | BRF_PRG }, // 1 + { "sw-05.m5", 0x04000, 0xe9a71bb6, BRF_ESS | BRF_PRG }, // 2 + { "sw-06.m6", 0x02000, 0x466f8248, BRF_ESS | BRF_PRG }, // 3 + { "sw-07.m7", 0x04000, 0xec41655e, BRF_ESS | BRF_PRG }, // 4 + + { "sr-01.c11", 0x04000, 0xbd87f06b, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "sw-02.f2", 0x02000, 0xf8e9ada2, BRF_GRA }, // 6 Characters + + { "sr-08.a1", 0x02000, 0x3884d9eb, BRF_GRA }, // 7 Tiles + { "sr-09.a2", 0x02000, 0x999cf6e0, BRF_GRA }, // 8 + { "sr-10.a3", 0x02000, 0x8edb273a, BRF_GRA }, // 9 + { "sr-11.a4", 0x02000, 0x3a2726c3, BRF_GRA }, // 10 + { "sr-12.a5", 0x02000, 0x1bd3d8bb, BRF_GRA }, // 11 + { "sr-13.a6", 0x02000, 0x658f02c4, BRF_GRA }, // 12 + + { "sr-14.l1", 0x04000, 0x2528bec6, BRF_GRA }, // 13 Sprites + { "sr-15.l2", 0x04000, 0xf89287aa, BRF_GRA }, // 14 + { "sr-16.n1", 0x04000, 0x024418f8, BRF_GRA }, // 15 + { "sr-17.n2", 0x04000, 0xe2c7e489, BRF_GRA }, // 16 + + { "sb-5.e8", 0x00100, 0x93ab8153, BRF_GRA }, // 17 PROMs + { "sb-6.e9", 0x00100, 0x8ab44f7d, BRF_GRA }, // 18 + { "sb-7.e10", 0x00100, 0xf4ade9a4, BRF_GRA }, // 19 + { "sb-0.f1", 0x00100, 0x6047d91b, BRF_GRA }, // 20 + { "sb-4.d6", 0x00100, 0x4858968d, BRF_GRA }, // 21 + { "sb-8.k3", 0x00100, 0xf6fad943, BRF_GRA }, // 22 + { "sb-2.d1", 0x00100, 0x8bb8b3df, BRF_GRA }, // 23 + { "sb-3.d2", 0x00100, 0x3b0c99af, BRF_GRA }, // 24 + { "sb-1.k6", 0x00100, 0x712ac508, BRF_GRA }, // 25 + { "sb-9.m11", 0x00100, 0x4921635c, BRF_GRA }, // 26 +}; + +STD_ROM_PICK(Drvw) +STD_ROM_FN(Drvw) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x1c000; + DrvZ80Rom2 = Next; Next += 0x04000; + DrvPromRed = Next; Next += 0x00100; + DrvPromGreen = Next; Next += 0x00100; + DrvPromBlue = Next; Next += 0x00100; + DrvPromCharLookup = Next; Next += 0x00100; + DrvPromTileLookup = Next; Next += 0x00100; + DrvPromSpriteLookup = Next; Next += 0x00100; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x01000; + DrvZ80Ram2 = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x00080; + DrvFgVideoRam = Next; Next += 0x00800; + DrvBgVideoRam = Next; Next += 0x00400; + + RamEnd = Next; + + DrvChars = Next; Next += 0x200 * 8 * 8; + DrvTiles = Next; Next += 0x200 * 16 * 16; + DrvSprites = Next; Next += 0x200 * 16 * 16; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + DrvPalette = (UINT32*)Next; Next += 0x00600 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + for (INT32 i = 0; i < 2; i++) { + AY8910Reset(i); + } + + DrvPaletteBank = 0; + DrvBgScroll[0] = 0; + DrvBgScroll[1] = 0; + DrvFlipScreen = 0; + DrvSoundLatch = 0; + DrvRomBank = 0; + + return 0; +} + +UINT8 __fastcall Drv1942Read1(UINT16 a) +{ + switch (a) { + case 0xc000: { + return 0xff - DrvInput[0]; + } + + case 0xc001: { + return 0xff - DrvInput[1]; + } + + case 0xc002: { + return 0xff - DrvInput[2]; + } + + case 0xc003: { + return DrvDip[0]; + } + + case 0xc004: { + return DrvDip[1]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1942Write1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + DrvSoundLatch = d; + return; + } + + case 0xc802: { + DrvBgScroll[0] = d; + return; + } + + case 0xc803: { + DrvBgScroll[1] = d; + return; + } + + case 0xc804: { + DrvFlipScreen = d & 0x80; + if (d & 0x10) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + } + return; + } + + case 0xc805: { + DrvPaletteBank = d; + return; + } + + case 0xc806: { + d &= 0x03; + DrvRomBank = d; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x4000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x4000 ); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Drv1942Read2(UINT16 a) +{ + switch (a) { + case 0x6000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1942Write2(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x8000: { + AY8910Write(0, 0, d); + return; + } + + case 0x8001: { + AY8910Write(0, 1, d); + return; + } + + case 0xc000: { + AY8910Write(1, 0, d); + return; + } + + case 0xc001: { + AY8910Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + + +static INT32 CharPlaneOffsets[2] = { 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 TilePlaneOffsets[3] = { 0, 0x20000, 0x40000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 SpritePlaneOffsets[4] = { 0x40004, 0x40000, 4, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + +static void MachineInit() +{ + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(Drv1942Read1); + ZetSetWriteHandler(Drv1942Write1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xcc00, 0xcc7f, 0, DrvSpriteRam ); + ZetMapArea(0xcc00, 0xcc7f, 1, DrvSpriteRam ); + ZetMapArea(0xcc00, 0xcc7f, 2, DrvSpriteRam ); + ZetMapArea(0xd000, 0xd7ff, 0, DrvFgVideoRam ); + ZetMapArea(0xd000, 0xd7ff, 1, DrvFgVideoRam ); + ZetMapArea(0xd000, 0xd7ff, 2, DrvFgVideoRam ); + ZetMapArea(0xd800, 0xdbff, 0, DrvBgVideoRam ); + ZetMapArea(0xd800, 0xdbff, 1, DrvBgVideoRam ); + ZetMapArea(0xd800, 0xdbff, 2, DrvBgVideoRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(Drv1942Read2); + ZetSetWriteHandler(Drv1942Write2); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom2 ); + ZetMapArea(0x4000, 0x47ff, 0, DrvZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 1, DrvZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x10000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x14000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x18000, 4, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x200, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x02000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x06000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0a000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x200, 3, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c000, 16, 1); if (nRet != 0) return 1; + GfxDecode(0x200, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromRed, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromGreen, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBlue, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromTileLookup, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 22, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 DrvablInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x18000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x14000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 4, 1); if (nRet != 0) return 1; + GfxDecode(0x200, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x200, 3, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x04000, DrvTempRom + 0x10000, 0x4000); + memcpy(DrvTempRom + 0x00000, DrvTempRom + 0x14000, 0x4000); + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x0c000, DrvTempRom + 0x10000, 0x4000); + memcpy(DrvTempRom + 0x08000, DrvTempRom + 0x14000, 0x4000); + GfxDecode(0x200, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromRed, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromGreen, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBlue, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromTileLookup, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 15, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + + for (INT32 i = 0; i < 2; i++) { + AY8910Exit(i); + } + + GenericTilesExit(); + + DrvPaletteBank = 0; + DrvBgScroll[0] = 0; + DrvBgScroll[1] = 0; + DrvFlipScreen = 0; + DrvSoundLatch = 0; + DrvRomBank = 0; + + BurnFree(Mem); + + return 0; +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT32 Palette[256]; + + for (i = 0; i < 256; i++) { + INT32 bit0, bit1, bit2, bit3, r, g, b; + + bit0 = (DrvPromRed[i] >> 0) & 0x01; + bit1 = (DrvPromRed[i] >> 1) & 0x01; + bit2 = (DrvPromRed[i] >> 2) & 0x01; + bit3 = (DrvPromRed[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromGreen[i] >> 0) & 0x01; + bit1 = (DrvPromGreen[i] >> 1) & 0x01; + bit2 = (DrvPromGreen[i] >> 2) & 0x01; + bit3 = (DrvPromGreen[i] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromBlue[i] >> 0) & 0x01; + bit1 = (DrvPromBlue[i] >> 1) & 0x01; + bit2 = (DrvPromBlue[i] >> 2) & 0x01; + bit3 = (DrvPromBlue[i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = BurnHighCol(r, g, b, 0); + } + + for (i = 0; i < 256; i++) { + DrvPalette[i] = Palette[0x80 | DrvPromCharLookup[i]]; + } + + for (i = 0; i < 256; i++) { + DrvPalette[256 + i + 0] = Palette[0x00 | DrvPromTileLookup[i]]; + DrvPalette[256 + i + 256] = Palette[0x10 | DrvPromTileLookup[i]]; + DrvPalette[256 + i + 512] = Palette[0x20 | DrvPromTileLookup[i]]; + DrvPalette[256 + i + 768] = Palette[0x30 | DrvPromTileLookup[i]]; + } + + for (i = 0; i < 256; i++) { + DrvPalette[1280 + i] = Palette[0x40 | DrvPromSpriteLookup[i]]; + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex, xScroll, Flip, xFlip, yFlip; + + xScroll = DrvBgScroll[0] | (DrvBgScroll[1] << 8); + xScroll &= 0x1ff; + + for (mx = 0; mx < 16; mx++) { + for (my = 0; my < 32; my++) { + TileIndex = (my * 16) + mx; + TileIndex = (TileIndex & 0x0f) | ((TileIndex & 0x01f0) << 1); + + Code = DrvBgVideoRam[TileIndex]; + Colour = DrvBgVideoRam[TileIndex + 0x10]; + Code += (Colour & 0x80) << 1; + Flip = (Colour & 0x60) >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + Colour &= 0x1f; + + y = 16 * mx; + x = 16 * my; + x -= xScroll; + if (x < -16) x += 512; + y -= 16; + + if (x > 0 && x < 240 && y > 0 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 256 + (0x100 * DrvPaletteBank), DrvTiles); + } + } + } + } + } +} + +static void DrvRenderSpriteLayer() +{ + INT32 Offset; + + for (Offset = 0x80 - 4; Offset >= 0; Offset -= 4) { + INT32 i, Code, Colour, sx, sy, Dir; + + Code = (DrvSpriteRam[Offset] & 0x7f) + (4 * (DrvSpriteRam[Offset + 1] & 0x20)) + (2 * (DrvSpriteRam[Offset] & 0x80)); + Colour = DrvSpriteRam[Offset + 1] & 0x0f; + sx = DrvSpriteRam[Offset + 3] - (0x10 * (DrvSpriteRam[Offset + 1] & 0x10)); + sy = DrvSpriteRam[Offset + 2]; + Dir = 1; + + i = (DrvSpriteRam[Offset + 1] & 0xc0) >> 6; + if (i == 2) i = 3; + + do { + Render16x16Tile_Mask_Clip(pTransDraw, Code + i, sx, (sy + (16 * i) * Dir) - 16, Colour, 4, 15, 1280, DrvSprites); + + i--; + } while (i >= 0); + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = DrvFgVideoRam[TileIndex]; + Colour = DrvFgVideoRam[TileIndex + 0x400]; + Code += (Colour & 0x80) << 1; + Colour &= 0x3f; + + x = 8 * mx; + y = 8 * my; + + y -= 16; + + if (x > 0 && x < 248 && y > 0 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 0, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSpriteLayer(); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + +// ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 1) { + ZetSetVector(0xcf); + ZetRaiseIrq(0); + } + if (i == 3) { + ZetSetVector(0xd7); + ZetRaiseIrq(0); + } + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetRaiseIrq(0); + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + AY8910Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvPaletteBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvBgScroll); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x4000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x4000 ); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvNineteen42 = { + "1942", NULL, NULL, NULL, "1984", + "1942 (Revision B)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen42a = { + "1942a", "1942", NULL, NULL, "1984", + "1942 (Revision A)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvaRomInfo, DrvaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen42abl = { + "1942abl", "1942", NULL, NULL, "1984", + "1942 (Revision A, bootleg)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvablRomInfo, DrvablRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvablInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen42b = { + "1942b", "1942", NULL, NULL, "1984", + "1942 (First Version)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen42w = { + "1942w", "1942", NULL, NULL, "1985", + "1942 (Williams Electronics license)\0", NULL, "Capcom (Williams Electronics license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvwRomInfo, DrvwRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x600, 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_1943.cpp b/src/burn/drivers/misc_pre90s/d_1943.cpp new file mode 100644 index 00000000..bcb14845 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_1943.cpp @@ -0,0 +1,1477 @@ +#include "tiles_generic.h" +#include "burn_ym2203.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPromRed = NULL; +static UINT8 *DrvPromGreen = NULL; +static UINT8 *DrvPromBlue = NULL; +static UINT8 *DrvPromCharLookup = NULL; +static UINT8 *DrvPromBg2Lookup = NULL; +static UINT8 *DrvPromBg2PalBank = NULL; +static UINT8 *DrvPromBgLookup = NULL; +static UINT8 *DrvPromBgPalBank = NULL; +static UINT8 *DrvPromSpriteLookup = NULL; +static UINT8 *DrvPromSpritePalBank = NULL; +static UINT8 *DrvBgTilemap = NULL; +static UINT8 *DrvBg2Tilemap = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvBg2Tiles = NULL; +static UINT8 *DrvBgTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvSoundLatch; +static UINT8 DrvRomBank; +static UINT8 DrvBg2ScrollX[2]; +static UINT8 DrvBgScrollX[2]; +static UINT8 DrvBgScrollY; +static UINT8 DrvBg2On; +static UINT8 DrvBg1On; +static UINT8 DrvSpritesOn; +static UINT8 DrvCharsOn; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xf8, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Difficulty" }, + {0x11, 0x01, 0x0f, 0x0f, "1 (Easy)" }, + {0x11, 0x01, 0x0f, 0x0e, "2" }, + {0x11, 0x01, 0x0f, 0x0d, "3" }, + {0x11, 0x01, 0x0f, 0x0c, "4" }, + {0x11, 0x01, 0x0f, 0x0b, "5" }, + {0x11, 0x01, 0x0f, 0x0a, "6" }, + {0x11, 0x01, 0x0f, 0x09, "7" }, + {0x11, 0x01, 0x0f, 0x08, "8 (Normal)" }, + {0x11, 0x01, 0x0f, 0x07, "9" }, + {0x11, 0x01, 0x0f, 0x06, "10" }, + {0x11, 0x01, 0x0f, 0x05, "11" }, + {0x11, 0x01, 0x0f, 0x04, "12" }, + {0x11, 0x01, 0x0f, 0x03, "13" }, + {0x11, 0x01, 0x0f, 0x02, "14" }, + {0x11, 0x01, 0x0f, 0x01, "15" }, + {0x11, 0x01, 0x0f, 0x00, "16 (Difficult)" }, + + {0 , 0xfe, 0 , 2 , "2 Player Game" }, + {0x11, 0x01, 0x10, 0x00, "1 Credit / 2 Players" }, + {0x11, 0x01, 0x10, 0x10, "2 Credits / 2 Players" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x20, 0x20, "Off" }, + {0x11, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "4 Coins 1 Play" }, + {0x12, 0x01, 0x38, 0x08, "3 Coins 1 Play" }, + {0x12, 0x01, 0x38, 0x10, "2 Coins 1 Play" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x40, 0x00, "No" }, + {0x12, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x00, "Off" }, + {0x12, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo DrvRomDesc[] = { + { "bme01.12d", 0x08000, 0x55fd447e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bme02.13d", 0x10000, 0x073fc57c, BRF_ESS | BRF_PRG }, // 1 + { "bme03.14d", 0x10000, 0x835822c2, BRF_ESS | BRF_PRG }, // 2 + + { "bm04.5h", 0x08000, 0xee2bd2d7, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "bm05.4k", 0x08000, 0x46cb9d3d, BRF_GRA }, // 4 Characters + + { "bm15.10f", 0x08000, 0x6b1a0443, BRF_GRA }, // 5 BG Tiles + { "bm16.11f", 0x08000, 0x23c908c2, BRF_GRA }, // 6 + { "bm17.12f", 0x08000, 0x46bcdd07, BRF_GRA }, // 7 + { "bm18.14f", 0x08000, 0xe6ae7ba0, BRF_GRA }, // 8 + { "bm19.10j", 0x08000, 0x868ababc, BRF_GRA }, // 9 + { "bm20.11j", 0x08000, 0x0917e5d4, BRF_GRA }, // 10 + { "bm21.12j", 0x08000, 0x9bfb0d89, BRF_GRA }, // 11 + { "bm22.14j", 0x08000, 0x04f3c274, BRF_GRA }, // 12 + + { "bm24.14k", 0x08000, 0x11134036, BRF_GRA }, // 13 BG2 Tiles + { "bm25.14l", 0x08000, 0x092cf9c1, BRF_GRA }, // 14 + + { "bm06.10a", 0x08000, 0x97acc8af, BRF_GRA }, // 15 Sprites + { "bm07.11a", 0x08000, 0xd78f7197, BRF_GRA }, // 16 + { "bm08.12a", 0x08000, 0x1a626608, BRF_GRA }, // 17 + { "bm09.14a", 0x08000, 0x92408400, BRF_GRA }, // 18 + { "bm10.10c", 0x08000, 0x8438a44a, BRF_GRA }, // 19 + { "bm11.11c", 0x08000, 0x6c69351d, BRF_GRA }, // 20 + { "bm12.12c", 0x08000, 0x5e7efdb7, BRF_GRA }, // 21 + { "bm13.14c", 0x08000, 0x1143829a, BRF_GRA }, // 22 + + { "bm14.5f", 0x08000, 0x4d3c6401, BRF_GRA }, // 23 Tilemaps + { "bm23.8k", 0x08000, 0xa52aecbd, BRF_GRA }, // 24 + + { "bm1.12a", 0x00100, 0x74421f18, BRF_GRA }, // 25 PROMs + { "bm2.13a", 0x00100, 0xac27541f, BRF_GRA }, // 26 + { "bm3.14a", 0x00100, 0x251fb6ff, BRF_GRA }, // 27 + { "bm5.7f", 0x00100, 0x206713d0, BRF_GRA }, // 28 + { "bm10.7l", 0x00100, 0x33c2491c, BRF_GRA }, // 29 + { "bm9.6l", 0x00100, 0xaeea4af7, BRF_GRA }, // 30 + { "bm12.12m", 0x00100, 0xc18aa136, BRF_GRA }, // 31 + { "bm11.12l", 0x00100, 0x405aae37, BRF_GRA }, // 32 + { "bm8.8c", 0x00100, 0xc2010a9e, BRF_GRA }, // 33 + { "bm7.7c", 0x00100, 0xb56f30c3, BRF_GRA }, // 34 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 35 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 36 + + { "bm.7k", 0x10000, 0x00000000, BRF_NODUMP }, // 37 MCU +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvuRomDesc[] = { + { "bmu01c.12d", 0x08000, 0xc686cc5c, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bmu02c.13d", 0x10000, 0xd8880a41, BRF_ESS | BRF_PRG }, // 1 + { "bmu03c.14d", 0x10000, 0x3f0ee26c, BRF_ESS | BRF_PRG }, // 2 + + { "bm04.5h", 0x08000, 0xee2bd2d7, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "bm05.4k", 0x08000, 0x46cb9d3d, BRF_GRA }, // 4 Characters + + { "bm15.10f", 0x08000, 0x6b1a0443, BRF_GRA }, // 5 BG Tiles + { "bm16.11f", 0x08000, 0x23c908c2, BRF_GRA }, // 6 + { "bm17.12f", 0x08000, 0x46bcdd07, BRF_GRA }, // 7 + { "bm18.14f", 0x08000, 0xe6ae7ba0, BRF_GRA }, // 8 + { "bm19.10j", 0x08000, 0x868ababc, BRF_GRA }, // 9 + { "bm20.11j", 0x08000, 0x0917e5d4, BRF_GRA }, // 10 + { "bm21.12j", 0x08000, 0x9bfb0d89, BRF_GRA }, // 11 + { "bm22.14j", 0x08000, 0x04f3c274, BRF_GRA }, // 12 + + { "bm24.14k", 0x08000, 0x11134036, BRF_GRA }, // 13 BG2 Tiles + { "bm25.14l", 0x08000, 0x092cf9c1, BRF_GRA }, // 14 + + { "bm06.10a", 0x08000, 0x97acc8af, BRF_GRA }, // 15 Sprites + { "bm07.11a", 0x08000, 0xd78f7197, BRF_GRA }, // 16 + { "bm08.12a", 0x08000, 0x1a626608, BRF_GRA }, // 17 + { "bm09.14a", 0x08000, 0x92408400, BRF_GRA }, // 18 + { "bm10.10c", 0x08000, 0x8438a44a, BRF_GRA }, // 19 + { "bm11.11c", 0x08000, 0x6c69351d, BRF_GRA }, // 20 + { "bm12.12c", 0x08000, 0x5e7efdb7, BRF_GRA }, // 21 + { "bm13.14c", 0x08000, 0x1143829a, BRF_GRA }, // 22 + + { "bm14.5f", 0x08000, 0x4d3c6401, BRF_GRA }, // 23 Tilemaps + { "bm23.8k", 0x08000, 0xa52aecbd, BRF_GRA }, // 24 + + { "bm1.12a", 0x00100, 0x74421f18, BRF_GRA }, // 25 PROMs + { "bm2.13a", 0x00100, 0xac27541f, BRF_GRA }, // 26 + { "bm3.14a", 0x00100, 0x251fb6ff, BRF_GRA }, // 27 + { "bm5.7f", 0x00100, 0x206713d0, BRF_GRA }, // 28 + { "bm10.7l", 0x00100, 0x33c2491c, BRF_GRA }, // 29 + { "bm9.6l", 0x00100, 0xaeea4af7, BRF_GRA }, // 30 + { "bm12.12m", 0x00100, 0xc18aa136, BRF_GRA }, // 31 + { "bm11.12l", 0x00100, 0x405aae37, BRF_GRA }, // 32 + { "bm8.8c", 0x00100, 0xc2010a9e, BRF_GRA }, // 33 + { "bm7.7c", 0x00100, 0xb56f30c3, BRF_GRA }, // 34 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 35 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 36 + + { "bm.7k", 0x10000, 0x00000000, BRF_NODUMP }, // 37 MCU +}; + +STD_ROM_PICK(Drvu) +STD_ROM_FN(Drvu) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "bm01b.12d", 0x08000, 0x363f9f3d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bm02b.13d", 0x10000, 0x7f0d7edc, BRF_ESS | BRF_PRG }, // 1 + { "bm03b.14d", 0x10000, 0x7093da2a, BRF_ESS | BRF_PRG }, // 2 + + { "bm04.5h", 0x08000, 0xee2bd2d7, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "bm05.4k", 0x08000, 0x46cb9d3d, BRF_GRA }, // 4 Characters + + { "bm15.10f", 0x08000, 0x6b1a0443, BRF_GRA }, // 5 BG Tiles + { "bm16.11f", 0x08000, 0x23c908c2, BRF_GRA }, // 6 + { "bm17.12f", 0x08000, 0x46bcdd07, BRF_GRA }, // 7 + { "bm18.14f", 0x08000, 0xe6ae7ba0, BRF_GRA }, // 8 + { "bm19.10j", 0x08000, 0x868ababc, BRF_GRA }, // 9 + { "bm20.11j", 0x08000, 0x0917e5d4, BRF_GRA }, // 10 + { "bm21.12j", 0x08000, 0x9bfb0d89, BRF_GRA }, // 11 + { "bm22.14j", 0x08000, 0x04f3c274, BRF_GRA }, // 12 + + { "bm24.14k", 0x08000, 0x11134036, BRF_GRA }, // 13 BG2 Tiles + { "bm25.14l", 0x08000, 0x092cf9c1, BRF_GRA }, // 14 + + { "bm06.10a", 0x08000, 0x97acc8af, BRF_GRA }, // 15 Sprites + { "bm07.11a", 0x08000, 0xd78f7197, BRF_GRA }, // 16 + { "bm08.12a", 0x08000, 0x1a626608, BRF_GRA }, // 17 + { "bm09.14a", 0x08000, 0x92408400, BRF_GRA }, // 18 + { "bm10.10c", 0x08000, 0x8438a44a, BRF_GRA }, // 19 + { "bm11.11c", 0x08000, 0x6c69351d, BRF_GRA }, // 20 + { "bm12.12c", 0x08000, 0x5e7efdb7, BRF_GRA }, // 21 + { "bm13.14c", 0x08000, 0x1143829a, BRF_GRA }, // 22 + + { "bm14.5f", 0x08000, 0x4d3c6401, BRF_GRA }, // 23 Tilemaps + { "bm23.8k", 0x08000, 0xa52aecbd, BRF_GRA }, // 24 + + { "bm1.12a", 0x00100, 0x74421f18, BRF_GRA }, // 25 PROMs + { "bm2.13a", 0x00100, 0xac27541f, BRF_GRA }, // 26 + { "bm3.14a", 0x00100, 0x251fb6ff, BRF_GRA }, // 27 + { "bm5.7f", 0x00100, 0x206713d0, BRF_GRA }, // 28 + { "bm10.7l", 0x00100, 0x33c2491c, BRF_GRA }, // 29 + { "bm9.6l", 0x00100, 0xaeea4af7, BRF_GRA }, // 30 + { "bm12.12m", 0x00100, 0xc18aa136, BRF_GRA }, // 31 + { "bm11.12l", 0x00100, 0x405aae37, BRF_GRA }, // 32 + { "bm8.8c", 0x00100, 0xc2010a9e, BRF_GRA }, // 33 + { "bm7.7c", 0x00100, 0xb56f30c3, BRF_GRA }, // 34 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 35 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 36 + + { "bm.7k", 0x10000, 0x00000000, BRF_NODUMP }, // 37 MCU +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo DrvjaRomDesc[] = { + { "bm01.12d", 0x08000, 0xf6935937, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bm02.13d", 0x10000, 0xaf971575, BRF_ESS | BRF_PRG }, // 1 + { "bm03.14d", 0x10000, 0x300ec713, BRF_ESS | BRF_PRG }, // 2 + + { "bm04.5h", 0x08000, 0xee2bd2d7, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "bm05.4k", 0x08000, 0x46cb9d3d, BRF_GRA }, // 4 Characters + + { "bm15.10f", 0x08000, 0x6b1a0443, BRF_GRA }, // 5 BG Tiles + { "bm16.11f", 0x08000, 0x23c908c2, BRF_GRA }, // 6 + { "bm17.12f", 0x08000, 0x46bcdd07, BRF_GRA }, // 7 + { "bm18.14f", 0x08000, 0xe6ae7ba0, BRF_GRA }, // 8 + { "bm19.10j", 0x08000, 0x868ababc, BRF_GRA }, // 9 + { "bm20.11j", 0x08000, 0x0917e5d4, BRF_GRA }, // 10 + { "bm21.12j", 0x08000, 0x9bfb0d89, BRF_GRA }, // 11 + { "bm22.14j", 0x08000, 0x04f3c274, BRF_GRA }, // 12 + + { "bm24.14k", 0x08000, 0x11134036, BRF_GRA }, // 13 BG2 Tiles + { "bm25.14l", 0x08000, 0x092cf9c1, BRF_GRA }, // 14 + + { "bm06.10a", 0x08000, 0x97acc8af, BRF_GRA }, // 15 Sprites + { "bm07.11a", 0x08000, 0xd78f7197, BRF_GRA }, // 16 + { "bm08.12a", 0x08000, 0x1a626608, BRF_GRA }, // 17 + { "bm09.14a", 0x08000, 0x92408400, BRF_GRA }, // 18 + { "bm10.10c", 0x08000, 0x8438a44a, BRF_GRA }, // 19 + { "bm11.11c", 0x08000, 0x6c69351d, BRF_GRA }, // 20 + { "bm12.12c", 0x08000, 0x5e7efdb7, BRF_GRA }, // 21 + { "bm13.14c", 0x08000, 0x1143829a, BRF_GRA }, // 22 + + { "bm14.5f", 0x08000, 0x4d3c6401, BRF_GRA }, // 23 Tilemaps + { "bm23.8k", 0x08000, 0xa52aecbd, BRF_GRA }, // 24 + + { "bm1.12a", 0x00100, 0x74421f18, BRF_GRA }, // 25 PROMs + { "bm2.13a", 0x00100, 0xac27541f, BRF_GRA }, // 26 + { "bm3.14a", 0x00100, 0x251fb6ff, BRF_GRA }, // 27 + { "bm5.7f", 0x00100, 0x206713d0, BRF_GRA }, // 28 + { "bm10.7l", 0x00100, 0x33c2491c, BRF_GRA }, // 29 + { "bm9.6l", 0x00100, 0xaeea4af7, BRF_GRA }, // 30 + { "bm12.12m", 0x00100, 0xc18aa136, BRF_GRA }, // 31 + { "bm11.12l", 0x00100, 0x405aae37, BRF_GRA }, // 32 + { "bm8.8c", 0x00100, 0xc2010a9e, BRF_GRA }, // 33 + { "bm7.7c", 0x00100, 0xb56f30c3, BRF_GRA }, // 34 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 35 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 36 + + { "bm.7k", 0x10000, 0x00000000, BRF_NODUMP }, // 37 MCU +}; + +STD_ROM_PICK(Drvja) +STD_ROM_FN(Drvja) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "1.12d", 0x08000, 0x9a2d70ab, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bm02.13d", 0x10000, 0xaf971575, BRF_ESS | BRF_PRG }, // 1 + { "bm03.14d", 0x10000, 0x300ec713, BRF_ESS | BRF_PRG }, // 2 + + { "bm04.5h", 0x08000, 0xee2bd2d7, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "4.5h", 0x08000, 0x0aba2096, BRF_GRA }, // 4 Characters + + { "15.12f", 0x10000, 0x622b4fba, BRF_GRA }, // 5 BG Tiles + { "16.14f", 0x10000, 0x25471a8d, BRF_GRA }, // 6 + { "17.12j", 0x10000, 0x9da79653, BRF_GRA }, // 7 + { "18.14j", 0x10000, 0x1f3aced8, BRF_GRA }, // 8 + + { "bm24.14k", 0x08000, 0x11134036, BRF_GRA }, // 9 BG2 Tiles + { "bm25.14l", 0x08000, 0x092cf9c1, BRF_GRA }, // 10 + + { "bm06.10a", 0x08000, 0x97acc8af, BRF_GRA }, // 11 Sprites + { "bm07.11a", 0x08000, 0xd78f7197, BRF_GRA }, // 12 + { "bm08.12a", 0x08000, 0x1a626608, BRF_GRA }, // 13 + { "bm09.14a", 0x08000, 0x92408400, BRF_GRA }, // 14 + { "bm10.10c", 0x08000, 0x8438a44a, BRF_GRA }, // 15 + { "bm11.11c", 0x08000, 0x6c69351d, BRF_GRA }, // 16 + { "bm12.12c", 0x08000, 0x5e7efdb7, BRF_GRA }, // 17 + { "bm13.14c", 0x08000, 0x1143829a, BRF_GRA }, // 18 + + { "bm14.5f", 0x08000, 0x4d3c6401, BRF_GRA }, // 19 Tilemaps + { "bm23.8k", 0x08000, 0xa52aecbd, BRF_GRA }, // 20 + + { "bm1.12a", 0x00100, 0x74421f18, BRF_GRA }, // 21 PROMs + { "bm2.13a", 0x00100, 0xac27541f, BRF_GRA }, // 22 + { "bm3.14a", 0x00100, 0x251fb6ff, BRF_GRA }, // 23 + { "bm5.7f", 0x00100, 0x206713d0, BRF_GRA }, // 24 + { "bm10.7l", 0x00100, 0x33c2491c, BRF_GRA }, // 25 + { "bm9.6l", 0x00100, 0xaeea4af7, BRF_GRA }, // 26 + { "bm12.12m", 0x00100, 0xc18aa136, BRF_GRA }, // 27 + { "bm11.12l", 0x00100, 0x405aae37, BRF_GRA }, // 28 + { "bm8.8c", 0x00100, 0xc2010a9e, BRF_GRA }, // 29 + { "bm7.7c", 0x00100, 0xb56f30c3, BRF_GRA }, // 30 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 31 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 32 +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo DrvkaiRomDesc[] = { + { "bmk01.12d", 0x08000, 0x7d2211db, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bmk02.13d", 0x10000, 0x2ebbc8c5, BRF_ESS | BRF_PRG }, // 1 + { "bmk03.14d", 0x10000, 0x475a6ac5, BRF_ESS | BRF_PRG }, // 2 + + { "bmk04.5h", 0x08000, 0x25f37957, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "bmk05.4k", 0x08000, 0x884a8692, BRF_GRA }, // 4 Characters + + { "bm15.10f", 0x08000, 0x6b1a0443, BRF_GRA }, // 5 BG Tiles + { "bmk16.11f", 0x08000, 0x9416fe0d, BRF_GRA }, // 6 + { "bmk17.12f", 0x08000, 0x3d5acab9, BRF_GRA }, // 7 + { "bmk18.14f", 0x08000, 0x7b62da1d, BRF_GRA }, // 8 + { "bm19.10j", 0x08000, 0x868ababc, BRF_GRA }, // 9 + { "bmk20.11j", 0x08000, 0xb90364c1, BRF_GRA }, // 10 + { "bmk21.12j", 0x08000, 0x8c7fe74a, BRF_GRA }, // 11 + { "bmk22.14j", 0x08000, 0xd5ef8a0e, BRF_GRA }, // 12 + + { "bmk24.14k", 0x08000, 0xbf186ef2, BRF_GRA }, // 13 BG2 Tiles + { "bmk25.14l", 0x08000, 0xa755faf1, BRF_GRA }, // 14 + + { "bmk06.10a", 0x08000, 0x5f7e38b3, BRF_GRA }, // 15 Sprites + { "bmk07.11a", 0x08000, 0xff3751fd, BRF_GRA }, // 16 + { "bmk08.12a", 0x08000, 0x159d51bd, BRF_GRA }, // 17 + { "bmk09.14a", 0x08000, 0x8683e3d2, BRF_GRA }, // 18 + { "bmk10.10c", 0x08000, 0x1e0d9571, BRF_GRA }, // 19 + { "bmk11.11c", 0x08000, 0xf1fc5ee1, BRF_GRA }, // 20 + { "bmk12.12c", 0x08000, 0x0f50c001, BRF_GRA }, // 21 + { "bmk13.14c", 0x08000, 0xfd1acf8e, BRF_GRA }, // 22 + + { "bmk14.5f", 0x08000, 0xcf0f5a53, BRF_GRA }, // 23 Tilemaps + { "bmk23.8k", 0x08000, 0x17f77ef9, BRF_GRA }, // 24 + + { "bmk1.12a", 0x00100, 0xe001ea33, BRF_GRA }, // 25 PROMs + { "bmk2.13a", 0x00100, 0xaf34d91a, BRF_GRA }, // 26 + { "bmk3.14a", 0x00100, 0x43e9f6ef, BRF_GRA }, // 27 + { "bmk5.7f", 0x00100, 0x41878934, BRF_GRA }, // 28 + { "bmk10.7l", 0x00100, 0xde44b748, BRF_GRA }, // 29 + { "bmk9.6l", 0x00100, 0x59ea57c0, BRF_GRA }, // 30 + { "bmk12.12m", 0x00100, 0x8765f8b0, BRF_GRA }, // 31 + { "bmk11.12l", 0x00100, 0x87a8854e, BRF_GRA }, // 32 + { "bmk8.8c", 0x00100, 0xdad17e2d, BRF_GRA }, // 33 + { "bmk7.7c", 0x00100, 0x76307f8d, BRF_GRA }, // 34 + { "bm4.12c", 0x00100, 0x91a8a2e1, BRF_GRA }, // 35 + { "bm6.4b", 0x00100, 0x0eaf5158, BRF_GRA }, // 36 + + { "bm.7k", 0x10000, 0x00000000, BRF_NODUMP }, // 37 MCU +}; + +STD_ROM_PICK(Drvkai) +STD_ROM_FN(Drvkai) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x30000; + DrvZ80Rom2 = Next; Next += 0x08000; + DrvPromRed = Next; Next += 0x00100; + DrvPromGreen = Next; Next += 0x00100; + DrvPromBlue = Next; Next += 0x00100; + DrvPromCharLookup = Next; Next += 0x00100; + DrvPromBg2Lookup = Next; Next += 0x00100; + DrvPromBg2PalBank = Next; Next += 0x00100; + DrvPromBgLookup = Next; Next += 0x00100; + DrvPromBgPalBank = Next; Next += 0x00100; + DrvPromSpriteLookup = Next; Next += 0x00100; + DrvPromSpritePalBank = Next; Next += 0x00100; + DrvBgTilemap = Next; Next += 0x08000; + DrvBg2Tilemap = Next; Next += 0x08000; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x01000; + DrvZ80Ram2 = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x00400; + DrvPaletteRam = Next; Next += 0x00400; + DrvSpriteRam = Next; Next += 0x01000; + + RamEnd = Next; + + DrvChars = Next; Next += 2048 * 8 * 8; + DrvBg2Tiles = Next; Next += 128 * 32 * 32; + DrvBgTiles = Next; Next += 512 * 32 * 32; + DrvSprites = Next; Next += 2048 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00380 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnYM2203Reset(); + + DrvRomBank = 0; + DrvSoundLatch = 0; + DrvBg2ScrollX[0] = 0; + DrvBg2ScrollX[1] = 0; + DrvBgScrollX[0] = 0; + DrvBgScrollX[1] = 0; + DrvBgScrollY = 0; + DrvBg2On = 0; + DrvBg1On = 0; + DrvSpritesOn = 0; + DrvCharsOn = 0; + + return 0; +} + +UINT8 __fastcall Drv1943Read1(UINT16 a) +{ + switch (a) { + case 0xc000: { + return 0xff - DrvInput[0]; + } + + case 0xc001: { + return 0xff - DrvInput[1]; + } + + case 0xc002: { + return 0xff - DrvInput[2]; + } + + case 0xc003: { + return DrvDip[0]; + } + + case 0xc004: { + return DrvDip[1]; + } + + case 0xc007: { + return ZetBc(-1) >> 8; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall Drvb1943Read1(UINT16 a) +{ + switch (a) { + case 0xc000: { + return 0xff - DrvInput[0]; + } + + case 0xc001: { + return 0xff - DrvInput[1]; + } + + case 0xc002: { + return 0xff - DrvInput[2]; + } + + case 0xc003: { + return DrvDip[0]; + } + + case 0xc004: { + return DrvDip[1]; + } + + case 0xc007: { + return 0x00; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1943Write1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + DrvSoundLatch = d; + return; + } + + case 0xc804: { + DrvRomBank = d & 0x1c; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x1000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x1000 ); + + if (d & 0x40) bprintf(PRINT_NORMAL, _T("c804 write %x\n"), d); + + DrvCharsOn = d & 0x80; + return; + } + + case 0xc806: { + // Watchdog + return; + } + + case 0xc807: { + // NOP + return; + } + + case 0xd800: { + DrvBgScrollX[0] = d; + return; + } + + case 0xd801: { + DrvBgScrollX[1] = d; + return; + } + + case 0xd802: { + DrvBgScrollY = d; + return; + } + + case 0xd803: { + DrvBg2ScrollX[0] = d; + return; + } + + case 0xd804: { + DrvBg2ScrollX[1] = d; + return; + } + + case 0xd806: { + DrvBg1On = d & 0x10; + DrvBg2On = d & 0x20; + DrvSpritesOn = d & 0x40; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Drv1943PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1943PortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Drv1943Read2(UINT16 a) +{ + switch (a) { + case 0xc800: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1943Write2(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xe001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xe002: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xe003: { + BurnYM2203Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Drv1943PortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall Drv1943PortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[2] = { 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 Bg2TilePlaneOffsets[4] = { 0x40004, 0x40000, 4, 0 }; +static INT32 BgTilePlaneOffsets[4] = { 0x100004, 0x100000, 4, 0 }; +static INT32 TileXOffsets[32] = { 0, 1, 2, 3, 8, 9, 10, 11, 512, 513, 514, 515, 520, 521, 522, 523, 1024, 1025, 1026, 1027, 1032, 1033, 1034, 1035, 1536, 1537, 1538, 1539, 1544, 1545, 1546, 1547 }; +static INT32 TileYOffsets[32] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, 336, 352, 368, 384, 400, 416, 432, 448, 464, 480, 496 }; +static INT32 SpritePlaneOffsets[4] = { 0x100004, 0x100000, 4, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x40000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x20000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 4, 1); if (nRet != 0) return 1; + GfxDecode(2048, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg2 tiles + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 14, 1); if (nRet != 0) return 1; + GfxDecode(128, 4, 32, 32, Bg2TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x800, DrvTempRom, DrvBg2Tiles); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 12, 1); if (nRet != 0) return 1; + GfxDecode(512, 4, 32, 32, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x800, DrvTempRom, DrvBgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 22, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the Tilemaps + nRet = BurnLoadRom(DrvBgTilemap, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvBg2Tilemap, 24, 1); if (nRet != 0) return 1; + + // Load the PROMs + nRet = BurnLoadRom(DrvPromRed, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromGreen, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBlue, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBgLookup, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBgPalBank, 30, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBg2Lookup, 31, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBg2PalBank, 32, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 33, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpritePalBank, 34, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(Drv1943Read1); + ZetSetWriteHandler(Drv1943Write1); + ZetSetInHandler(Drv1943PortRead1); + ZetSetOutHandler(Drv1943PortWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xd000, 0xd3ff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 2, DrvVideoRam ); + ZetMapArea(0xd400, 0xd7ff, 0, DrvPaletteRam ); + ZetMapArea(0xd400, 0xd7ff, 1, DrvPaletteRam ); + ZetMapArea(0xd400, 0xd7ff, 2, DrvPaletteRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram1 ); + ZetMapArea(0xf000, 0xffff, 0, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 1, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 2, DrvSpriteRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(Drv1943Read2); + ZetSetWriteHandler(Drv1943Write2); + ZetSetInHandler(Drv1943PortRead2); + ZetSetOutHandler(Drv1943PortWrite2); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom2 ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + BurnYM2203SetVolumeShift(3); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvbInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x40000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x20000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 4, 1); if (nRet != 0) return 1; + GfxDecode(2048, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg2 tiles + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + GfxDecode(128, 4, 32, 32, Bg2TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x800, DrvTempRom, DrvBg2Tiles); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 8, 1); if (nRet != 0) return 1; + GfxDecode(512, 4, 32, 32, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x800, DrvTempRom, DrvBgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x40000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 18, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the Tilemaps + nRet = BurnLoadRom(DrvBgTilemap, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvBg2Tilemap, 20, 1); if (nRet != 0) return 1; + + // Load the PROMs + nRet = BurnLoadRom(DrvPromRed, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromGreen, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBlue, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBgLookup, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBgPalBank, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBg2Lookup, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBg2PalBank, 28, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 29, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpritePalBank, 30, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(Drvb1943Read1); + ZetSetWriteHandler(Drv1943Write1); + ZetSetInHandler(Drv1943PortRead1); + ZetSetOutHandler(Drv1943PortWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xd000, 0xd3ff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 2, DrvVideoRam ); + ZetMapArea(0xd400, 0xd7ff, 0, DrvPaletteRam ); + ZetMapArea(0xd400, 0xd7ff, 1, DrvPaletteRam ); + ZetMapArea(0xd400, 0xd7ff, 2, DrvPaletteRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram1 ); + ZetMapArea(0xf000, 0xffff, 0, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 1, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 2, DrvSpriteRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(Drv1943Read2); + ZetSetWriteHandler(Drv1943Write2); + ZetSetInHandler(Drv1943PortRead2); + ZetSetOutHandler(Drv1943PortWrite2); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom2 ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + BurnYM2203SetVolumeShift(3); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + BurnYM2203Exit(); + + GenericTilesExit(); + + DrvRomBank = 0; + DrvSoundLatch = 0; + DrvBg2ScrollX[0] = 0; + DrvBg2ScrollX[1] = 0; + DrvBgScrollX[0] = 0; + DrvBgScrollX[1] = 0; + DrvBgScrollY = 0; + DrvBg2On = 0; + DrvBg1On = 0; + DrvSpritesOn = 0; + DrvCharsOn = 0; + + BurnFree(Mem); + + return 0; +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT32 Palette[256]; + + for (i = 0; i < 256; i++) { + INT32 bit0, bit1, bit2, bit3, r, g, b; + + bit0 = (DrvPromRed[i] >> 0) & 0x01; + bit1 = (DrvPromRed[i] >> 1) & 0x01; + bit2 = (DrvPromRed[i] >> 2) & 0x01; + bit3 = (DrvPromRed[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromGreen[i] >> 0) & 0x01; + bit1 = (DrvPromGreen[i] >> 1) & 0x01; + bit2 = (DrvPromGreen[i] >> 2) & 0x01; + bit3 = (DrvPromGreen[i] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromBlue[i] >> 0) & 0x01; + bit1 = (DrvPromBlue[i] >> 1) & 0x01; + bit2 = (DrvPromBlue[i] >> 2) & 0x01; + bit3 = (DrvPromBlue[i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = BurnHighCol(r, g, b, 0); + } + + for (i = 0; i < 0x80; i++) { + DrvPalette[i] = Palette[(DrvPromCharLookup[i] & 0x0f) | 0x40]; + } + + for (i = 0x80; i < 0x180; i++) { + DrvPalette[i] = Palette[((DrvPromBgPalBank[i - 0x80] & 0x03) << 4) | (DrvPromBgLookup[i - 0x80] & 0x0f)]; + } + + for (i = 0x180; i < 0x280; i++) { + DrvPalette[i] = Palette[((DrvPromBg2PalBank[i - 0x180] & 0x03) << 4) | (DrvPromBg2Lookup[i - 0x180] & 0x0f)]; + } + + for (i = 0x280; i < 0x380; i++) { + DrvPalette[i] = Palette[((DrvPromSpritePalBank[i - 0x280] & 0x07) << 4) | (DrvPromSpriteLookup[i - 0x280] & 0x0f) | 0x80]; + } +} + +static void DrvRenderBg2Layer() +{ + INT32 mx, my, Offs, Attr, Code, Colour, x, y, TileIndex, xScroll, Flip, xFlip, yFlip; + + xFlip = 0; + yFlip = 0; + + xScroll = DrvBg2ScrollX[0] + (256 * DrvBg2ScrollX[1]); + + for (mx = 0; mx < 8; mx++) { + for (my = 0; my < 2048; my++) { + TileIndex = (my * 8) + mx; + + Offs = TileIndex * 2; + Attr = DrvBg2Tilemap[Offs + 1]; + Code = DrvBg2Tilemap[Offs] & 0x7f; + Colour = ((Attr & 0x3c) >> 2) + 0x18; + Flip = (Attr & 0xc0) >> 6; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + y = 32 * mx; + x = 32 * my; + + x -= xScroll; + y -= 16; + + if (x < -31) x += 65536; + + if (x > 256) continue; + if (y > 240) continue; + + if (x > 0 && x < 224 && y > 0 && y < 192) { + if (xFlip) { + if (yFlip) { + Render32x32Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } else { + Render32x32Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } + } else { + if (yFlip) { + Render32x32Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } else { + Render32x32Tile(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render32x32Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } else { + Render32x32Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } + } else { + if (yFlip) { + Render32x32Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } else { + Render32x32Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBg2Tiles); + } + } + } + } + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Offs, Attr, Code, Colour, x, y, TileIndex, xScroll, yScroll, Flip, xFlip, yFlip; + + xFlip = 0; + yFlip = 0; + + yScroll = (DrvBgScrollY + 16) & 0xff; + xScroll = DrvBgScrollX[0] + (256 * DrvBgScrollX[1]); + + for (mx = 0; mx < 8; mx++) { + for (my = 0; my < 2048; my++) { + TileIndex = (my * 8) + mx; + + Offs = TileIndex * 2; + Attr = DrvBgTilemap[Offs + 1]; + Code = DrvBgTilemap[Offs] + ((Attr & 0x01) << 8); + Colour = ((Attr & 0x3c) >> 2) + 0x08; + Flip = (Attr & 0xc0) >> 6; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + y = 32 * mx; + x = 32 * my; + + x -= xScroll; + y -= yScroll; + + if (x < -31) x += 65536; + if (y < -31) y += 256; + + if (x > 256) continue; + if (y > 240) continue; + + if (x > 0 && x < 224 && y > 0 && y < 192) { + if (xFlip) { + if (yFlip) { + Render32x32Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } else { + Render32x32Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render32x32Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } else { + Render32x32Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render32x32Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } else { + Render32x32Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render32x32Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } else { + Render32x32Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvBgTiles); + } + } + } + } + } +} + +static void DrvRenderSprites(INT32 Priority) +{ + INT32 Offs; + + for (Offs = 0x1000 - 32; Offs >= 0; Offs -= 32) { + INT32 Attr = DrvSpriteRam[Offs + 1]; + INT32 Code = DrvSpriteRam[Offs + 0] + ((Attr & 0xe0) << 3); + INT32 Colour = Attr & 0x0f; + INT32 sx = DrvSpriteRam[Offs + 3] - ((Attr & 0x10) << 4); + INT32 sy = DrvSpriteRam[Offs + 2]; + + sy -= 16; + + if (Priority) { + if (Colour != 0x0a && Colour != 0x0b) { + if (sx > 0 && sx < 240 && sy > 0 && sy < 208) { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour + 0x28, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour + 0x28, 4, 0, 0, DrvSprites); + } + } + } else { + if (Colour == 0x0a || Colour == 0x0b) { + if (sx > 0 && sx < 240 && sy > 0 && sy < 208) { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour + 0x28, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour + 0x28, 4, 0, 0, DrvSprites); + } + } + + } + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = DrvPaletteRam[TileIndex]; + Code = DrvVideoRam[TileIndex] + ((Attr & 0xe0) << 3); + Colour = Attr & 0x1f; + + x = 8 * mx; + y = 8 * my; + + y -= 16; + + if (x > 0 && x < 248 && y > 0 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 0, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + if (DrvBg2On && nBurnLayer & 1) DrvRenderBg2Layer(); + if (DrvSpritesOn) DrvRenderSprites(0); + if (DrvBg1On && nBurnLayer & 2) DrvRenderBgLayer(); + if (DrvSpritesOn) DrvRenderSprites(1); + if (DrvCharsOn && nBurnLayer & 4) DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 100; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 95) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 96) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (i == 20 || i == 40 || i == 60 || i == 80) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 21 || i == 41 || i == 61 || i == 81) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + ZetClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + ZetOpen(1); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvBg2ScrollX[0]); + SCAN_VAR(DrvBg2ScrollX[1]); + SCAN_VAR(DrvBgScrollX[0]); + SCAN_VAR(DrvBgScrollX[1]); + SCAN_VAR(DrvBgScrollY); + SCAN_VAR(DrvBg2On); + SCAN_VAR(DrvBg1On); + SCAN_VAR(DrvSpritesOn); + SCAN_VAR(DrvCharsOn); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x1000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + DrvRomBank * 0x1000 ); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvNineteen43 = { + "1943", NULL, NULL, NULL, "1987", + "1943: The Battle of Midway (Euro)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen43u = { + "1943u", "1943", NULL, NULL, "1987", + "1943: The Battle of Midway (US)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen43j = { + "1943j", "1943", NULL, NULL, "1987", + "1943: Midway Kaisen (Japan, Rev B)\0", NULL, "Capcom", "Miscellaneous", + L"1943: \u30DF\u30C3\u30C9\u30A6\u30A7\u30A4\u6D77\u6226 (Japan, Rev B)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen43ja = { + "1943ja", "1943", NULL, NULL, "1987", + "1943: Midway Kaisen (Japan)\0", NULL, "Capcom", "Miscellaneous", + L"1943: \u30DF\u30C3\u30C9\u30A6\u30A7\u30A4\u6D77\u6226 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvjaRomInfo, DrvjaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen43b = { + "1943b", "1943", NULL, NULL, "1987", + "1943: The Battle of Midway (bootleg, hack of Japan set)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvNineteen43kai = { + "1943kai", NULL, NULL, NULL, "1987", + "1943 Kai: Midway Kaisen (Japan)\0", NULL, "Capcom", "Miscellaneous", + L"1943 \u6539: \u30DF\u30C3\u30C9\u30A6\u30A7\u30A4\u6D77\u6226 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvkaiRomInfo, DrvkaiRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x380, 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_4enraya.cpp b/src/burn/drivers/misc_pre90s/d_4enraya.cpp new file mode 100644 index 00000000..28d8cf8b --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_4enraya.cpp @@ -0,0 +1,530 @@ +// FB Alpha 4 Enraya driver module +// Based on MAME driver by Tomasz Slanina + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvNVRAM; +static UINT8 *DrvVidRAM; +static UINT32 *Palette; +static UINT32 *DrvPalette; + +static INT16 *pAY8910Buffer[3]; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static UINT8 *soundlatch; +static UINT8 *soundcontrol; +static UINT32 sound_bit; + +static struct BurnInputInfo Enraya4InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 6, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 5, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 5, "p2 start" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Enraya4) + +static struct BurnInputInfo UnkpacgInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 1, "dips" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 0, "dips" }, +}; + +STDINPUTINFO(Unkpacg) + +static struct BurnDIPInfo Enraya4DIPList[]= +{ + {0x0d, 0xff, 0xff, 0xfd, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x0d, 0x01, 0x01, 0x01, "Easy" }, + {0x0d, 0x01, 0x01, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0d, 0x01, 0x02, 0x02, "Off" }, + {0x0d, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Pieces" }, + {0x0d, 0x01, 0x04, 0x04, "30" }, + {0x0d, 0x01, 0x04, 0x00, "16" }, + + {0 , 0xfe, 0 , 2, "Speed" }, + {0x0d, 0x01, 0x08, 0x08, "Slow" }, + {0x0d, 0x01, 0x08, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x10, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, +}; + +STDDIPINFO(Enraya4) + +static struct BurnDIPInfo UnkpacgDIPList[]= +{ + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "DIP8" }, + {0x09, 0x01, 0x80, 0x00, "Off" }, + {0x09, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2, "0-0" }, + {0x0a, 0x01, 0x01, 0x00, "Off" }, + {0x0a, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "0-1" }, + {0x0a, 0x01, 0x02, 0x00, "Off" }, + {0x0a, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "0-2" }, + {0x0a, 0x01, 0x04, 0x00, "Off" }, + {0x0a, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "0-3" }, + {0x0a, 0x01, 0x08, 0x00, "Off" }, + {0x0a, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "0-4" }, + {0x0a, 0x01, 0x10, 0x00, "Off" }, + {0x0a, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "0-5" }, + {0x0a, 0x01, 0x20, 0x00, "Off" }, + {0x0a, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "0-6" }, + {0x0a, 0x01, 0x40, 0x00, "Off" }, + {0x0a, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "0-7" }, + {0x0a, 0x01, 0x80, 0x00, "Off" }, + {0x0a, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Unkpacg) + +void __fastcall enraya4_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf000) == 0xd000 || (address & 0xf000) == 0x7000) { + DrvVidRAM[((address & 0x3ff) << 1) + 0] = data; + DrvVidRAM[((address & 0x3ff) << 1) + 1] = (address >> 10) & 3; + + return; + } +} + +static void sound_control(UINT8 data) +{ + if ((*soundcontrol & sound_bit) == sound_bit && (data & sound_bit) == 0) { + AY8910Write(0, ~*soundcontrol & 1, *soundlatch); + } + + *soundcontrol = data; +} + +void __fastcall enraya4_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x20: + case 0x23: + *soundlatch = data; + break; + + case 0x30: + case 0x33: + sound_control(data); + break; + } +} + +UINT8 __fastcall enraya4_in_port(UINT16 port) +{ + static UINT8 nRet = 0; + + switch (port & 0xff) + { + case 0x00: + return DrvDips[0]; + + case 0x01: + return DrvInputs[0]; + + case 0x02: + return DrvInputs[1]; + } + + return nRet; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x00c000; + + DrvGfxROM = Next; Next += 0x010000; + + Palette = (UINT32*)Next; Next += 0x0008 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0008 * sizeof(UINT32); + + DrvNVRAM = Next; Next += 0x001000; + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x001000; + DrvVidRAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + soundcontrol = Next; Next += 0x000001; + + RamEnd = Next; + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 8; i++) { + DrvPalette[i] = BurnHighCol((i & 1) * 0xff, ((i & 2)/2) * 0xff, ((i & 4)/4) * 0xff, 0); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { 0x10000, 0x20000, 0x00000 }; + INT32 XOffs[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x6000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x6000); + + GfxDecode(0x0400, 3, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM); + + BurnFree(tmp); + + return 0; +} + +static void DrvPrgDecode() +{ + for (INT32 i = 0x8000; i < 0xa000; i++) { + DrvZ80ROM[i] = (DrvZ80ROM[i] & 0xfc) | ((DrvZ80ROM[i] & 0x02) >> 1) | ((DrvZ80ROM[i] & 0x01) << 1); + } +} + +static INT32 DrvInit(INT32 game, INT32 sbit) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + BurnLoadRom(DrvZ80ROM + 0x00000, 0, 1); + BurnLoadRom(DrvZ80ROM + 0x08000, 1, 1); + + BurnLoadRom(DrvGfxROM + 0x00000, 2, 1); + BurnLoadRom(DrvGfxROM + 0x02000, 3, 1); + BurnLoadRom(DrvGfxROM + 0x04000, 4, 1); + + if (game) DrvPrgDecode(); + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(1); + ZetOpen(0); + + if (game == 0) // 4enraya + { + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xcfff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xcfff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xcfff, 2, DrvZ80RAM); + // ZetMapArea(0xd000, 0xdfff, 1, DrvVidRAM); + } + else // unkpacg + { + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80ROM); + ZetMapArea(0x6000, 0x6fff, 0, DrvNVRAM); + ZetMapArea(0x6000, 0x6fff, 1, DrvNVRAM); + ZetMapArea(0x6000, 0x6fff, 2, DrvNVRAM); + // ZetMapArea(0xd000, 0xdfff, 1, DrvVidRAM); + ZetMapArea(0x8000, 0x9fff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0x9fff, 2, DrvZ80ROM + 0x8000); + } + + ZetSetOutHandler(enraya4_out_port); + ZetSetInHandler(enraya4_in_port); + ZetSetWriteHandler(enraya4_write); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + sound_bit = sbit; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + ZetExit(); + AY8910Exit(0); + + BurnFree(AllMem); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 code = DrvVidRAM[(offs << 1) + 0] | (DrvVidRAM[(offs << 1) + 1] << 8); + + Render8x8Tile(pTransDraw, code, sx, sy - 16, 0, 0, 0, DrvGfxROM); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvDips[1]; + DrvInputs[1] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 4; + INT32 nCyclesTotal = 4000000 / 60; + INT32 nCyclesDone = 0; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = nCyclesTotal / nInterleave; + + nCyclesDone += ZetRun(nSegment); + + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + } + + if (nAction & ACB_NVRAM) { + ba.Data = DrvNVRAM; + ba.nLen = 0x01000; + ba.nAddress = 0; + ba.szName = "NV RAM"; + BurnAcb(&ba); + } + + return 0; +} + + +// 4 En Raya + +static struct BurnRomInfo enraya4RomDesc[] = { + { "5.bin", 0x8000, 0xcf1cd151, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "4.bin", 0x4000, 0xf9ec1be7, BRF_ESS | BRF_PRG }, // 1 + + { "1.bin", 0x2000, 0x87f92552, BRF_GRA }, // 2 Graphics + { "2.bin", 0x2000, 0x2b0a3793, BRF_GRA }, // 3 + { "3.bin", 0x2000, 0xf6940836, BRF_GRA }, // 4 + + { "1.bpr", 0x0020, 0xdcbd2352, BRF_GRA }, // 5 Address control prom - not used +}; + +STD_ROM_PICK(enraya4) +STD_ROM_FN(enraya4) + +static INT32 enraya4Init() +{ + return DrvInit(0, 4); +} + +struct BurnDriver BurnDrvEnraya4 = { + "4enraya", NULL, NULL, NULL, "1990", + "4 En Raya\0", NULL, "IDSA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, enraya4RomInfo, enraya4RomName, NULL, NULL, Enraya4InputInfo, Enraya4DIPInfo, + enraya4Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x8, + 256, 224, 4, 3 +}; + + +// unknown Pac-Man gambling game + +static struct BurnRomInfo unkpacgRomDesc[] = { + { "1.u14", 0x2000, 0x848c4143, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2.u46", 0x2000, 0x9e6e0bd3, BRF_ESS | BRF_PRG }, // 1 + + { "3.u20", 0x2000, 0xd00b04ea, BRF_GRA }, // 2 Graphics + { "4.u19", 0x2000, 0x4a123a3d, BRF_GRA }, // 3 + { "5.u18", 0x2000, 0x44f272d2, BRF_GRA }, // 4 +}; + +STD_ROM_PICK(unkpacg) +STD_ROM_FN(unkpacg) + +static INT32 unkpacgInit() +{ + return DrvInit(1, 2); +} + +struct BurnDriver BurnDrvUnkpacg = { + "pucky", NULL, NULL, NULL, "199?", + "unknown Pac-Man gambling game\0", NULL, "unknown", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, unkpacgRomInfo, unkpacgRomName, NULL, NULL, UnkpacgInputInfo, UnkpacgDIPInfo, + unkpacgInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x8, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_ambush.cpp b/src/burn/drivers/misc_pre90s/d_ambush.cpp new file mode 100644 index 00000000..38dac152 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_ambush.cpp @@ -0,0 +1,632 @@ +// FB Alpha Ambush driver module +// Based on MAME driver by Zsolt Vasvari + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvScrRAM; +static INT16 *pAY8910Buffer[6]; +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[1]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static UINT8 *color_bank; +static UINT8 *flipscreen; + +static struct BurnInputInfo AmbushInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Ambush) + +static struct BurnDIPInfo AmbushDIPList[]= +{ + {0x11, 0xff, 0xff, 0xc0, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x00, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x11, 0x01, 0x1c, 0x14, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x1c, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x1c, 0x00, "1 Coins 1 Credit" }, + {0x11, 0x01, 0x1c, 0x04, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x1c, 0x18, "2 Coins 5 Credits" }, + {0x11, 0x01, 0x1c, 0x08, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x1c, 0x0c, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x1c, 0x1c, "Free Play / Service" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x20, 0x00, "Easy" }, + {0x11, 0x01, 0x20, 0x20, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x11, 0x01, 0x40, 0x40, "80000" }, + {0x11, 0x01, 0x40, 0x00, "120000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x80, 0x80, "Upright" }, + {0x11, 0x01, 0x80, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Ambush) + +UINT8 __fastcall ambush_read_byte(UINT16 address) +{ + switch (address) + { + case 0xc800: + return DrvDips[0]; + } + + return 0; +} + +void __fastcall ambush_write_byte(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xcc04: + *flipscreen = data; + break; + + case 0xcc05: + *color_bank = (data & 3) << 4; + break; + } +} + +UINT8 __fastcall ambush_in_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return AY8910Read(0); + + case 0x80: + return AY8910Read(1); + } + + return 0; +} + +void __fastcall ambush_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + AY8910Write(0, 0, data); + break; + + case 0x01: + AY8910Write(0, 1, data); + break; + + case 0x80: + AY8910Write(1, 0, data); + break; + + case 0x81: + AY8910Write(1, 1, data); + break; + } +} + +UINT8 AY8910_0_port0(UINT32) +{ + return DrvInputs[0]; +} + +UINT8 AY8910_1_port0(UINT32) +{ + return DrvInputs[1]; +} + +static INT32 DrvDoReset() +{ + memset(AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0;i < 0x100; i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (DrvColPROM[i] >> 3) & 0x01; + bit1 = (DrvColPROM[i] >> 4) & 0x01; + bit2 = (DrvColPROM[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit1 = (DrvColPROM[i] >> 6) & 0x01; + bit2 = (DrvColPROM[i] >> 7) & 0x01; + b = 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static void DrvGfxDecode() +{ + static INT32 Plane[2] = { 0, 0x10000 }; + static INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; + static INT32 YOffs[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + + UINT8 *tmp = (UINT8 *)BurnMalloc(0x4000); + if (tmp == NULL) { + return; + } + + memcpy (tmp, DrvGfxROM0, 0x4000); + + GfxDecode(0x0400, 2, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + + GfxDecode(0x0100, 2, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000100; + + DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + Palette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000200; + DrvColRAM = Next; Next += 0x000100; + DrvScrRAM = Next; Next += 0x000100; + + flipscreen = Next; Next += 0x000001; + color_bank = Next; Next += 0x000001; + + pAY8910Buffer[0] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[3] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[4] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[5] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x6000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x2000, 5, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x0000, 6, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetMapArea(0xc000, 0xc0ff, 0, DrvScrRAM); + ZetMapArea(0xc000, 0xc0ff, 1, DrvScrRAM); + ZetMapArea(0xc000, 0xc0ff, 2, DrvScrRAM); + ZetMapArea(0xc100, 0xc1ff, 0, DrvColRAM); + ZetMapArea(0xc100, 0xc1ff, 1, DrvColRAM); + ZetMapArea(0xc100, 0xc1ff, 2, DrvColRAM); + ZetMapArea(0xc200, 0xc3ff, 0, DrvSprRAM); + ZetMapArea(0xc200, 0xc3ff, 1, DrvSprRAM); + ZetMapArea(0xc200, 0xc3ff, 2, DrvSprRAM); + ZetMapArea(0xc400, 0xc7ff, 0, DrvVidRAM); + ZetMapArea(0xc400, 0xc7ff, 1, DrvVidRAM); + ZetMapArea(0xc400, 0xc7ff, 2, DrvVidRAM); + ZetSetWriteHandler(ambush_write_byte); + ZetSetReadHandler(ambush_read_byte); + ZetSetOutHandler(ambush_out_port); + ZetSetInHandler(ambush_in_port); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, &AY8910_0_port0, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, &AY8910_1_port0, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer(INT32 priority) +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 attr = DrvColRAM[(sy & 0xe0) | (sx >> 3)]; + if ((attr & 0x10) != priority) continue; + + INT32 code = DrvVidRAM[offs] | ((attr & 0x60) << 3); + INT32 color = (attr & 0x0f) | *color_bank; + + sy = (sy + (DrvScrRAM[sx >> 3] ^ 0xff)) & 0xff; + + INT32 flip = 0; + + if (*flipscreen) { + flip = 1; + sx = 248 - sx; + sy = (248 - sy) - 16; + } + + if (priority) { + if (flip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } + } else { + if (flip) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM0); + } + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x200 - 4; offs >= 0; offs -= 4) + { + INT32 sy = DrvSprRAM[offs + 0]; + INT32 sx = DrvSprRAM[offs + 3]; + + if (sy == 0 || sy == 0xff || (sx < 0x40 && DrvSprRAM[offs + 2] & 0x10) || (sx >= 0xc0 && ~DrvSprRAM[offs + 2] & 0x10)) + continue; + + INT32 code = (DrvSprRAM[offs + 1] & 0x3f) | ((DrvSprRAM[offs + 2] & 0x60) << 1); + + INT32 color =(DrvSprRAM[offs + 2] & 0x0f) | *color_bank; + INT32 flipx = DrvSprRAM[offs + 1] & 0x40; + INT32 flipy = DrvSprRAM[offs + 1] & 0x80; + + if (*flipscreen) + { + flipx = !flipx; + flipy = !flipy; + sy -= 16; + } + + if (DrvSprRAM[offs + 2] & 0x80) + { + if (*flipscreen) { + sx = 240 - sx; + } else { + sy = 240 - sy; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } + } else { + code <<= 2; + + if (*flipscreen) { + sx = 248 - sx; + } else { + sy = 248 - sy; + } + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x100; i++) { + INT32 p = Palette[i]; + DrvPalette[i] = BurnHighCol(p >> 16, (p >> 8) & 0xff, p & 0xff, 0); + } + } + + BurnTransferClear(); + + draw_layer(0x00); + draw_sprites(); + draw_layer(0x10); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetOpen(0); + ZetRun(4000000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + AY8910Update(1, &pAY8910Buffer[3], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + } + + return 0; +} + + +// Ambush + +static struct BurnRomInfo ambushjRomDesc[] = { + { "ambush.h7", 0x2000, 0xce306563, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ambush.g7", 0x2000, 0x90291409, BRF_ESS | BRF_PRG }, // 1 + { "ambush.f7", 0x2000, 0xd023ca29, BRF_ESS | BRF_PRG }, // 2 + { "ambush.e7", 0x2000, 0x6cc2d3ee, BRF_ESS | BRF_PRG }, // 3 + + { "ambush.n4", 0x2000, 0xecc0dc85, BRF_GRA }, // 4 Graphics tiles + { "ambush.m4", 0x2000, 0xe86ca98a, BRF_GRA }, // 5 + + { "a.bpr", 0x0100, 0x5f27f511, BRF_GRA }, // 6 color PROMs + + { "b.bpr", 0x0100, 0x1b03fd3b, BRF_OPT }, // 7 Proms - Not used + { "13.bpr", 0x0100, 0x547e970f, BRF_OPT }, // 8 + { "14.bpr", 0x0100, 0x622a8ce7, BRF_OPT }, // 9 +}; + +STD_ROM_PICK(ambushj) +STD_ROM_FN(ambushj) + +struct BurnDriver BurnDrvAmbushj = { + "ambushj", "ambush", NULL, NULL, "1983", + "Ambush (Japan)\0", NULL, "Nippon Amuse Co-Ltd", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, ambushjRomInfo, ambushjRomName, NULL, NULL, AmbushInputInfo, AmbushDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; + + +// Ambush (Tecfri) + +static struct BurnRomInfo ambushRomDesc[] = { + { "a1.i7", 0x2000, 0xa7cd149d, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a2.g7", 0x2000, 0x8328d88a, BRF_ESS | BRF_PRG }, // 1 + { "a3.f7", 0x2000, 0x8db57ab5, BRF_ESS | BRF_PRG }, // 2 + { "a4.e7", 0x2000, 0x4a34d2a4, BRF_ESS | BRF_PRG }, // 3 + + { "fa2.n4", 0x2000, 0xe7f134ba, BRF_GRA }, // 4 Graphics tiles + { "fa1.m4", 0x2000, 0xad10969e, BRF_GRA }, // 5 + + { "a.bpr", 0x0100, 0x5f27f511, BRF_GRA }, // 6 color PROMs + + { "b.bpr", 0x0100, 0x1b03fd3b, BRF_OPT }, // 7 Proms - Not used + { "13.bpr", 0x0100, 0x547e970f, BRF_OPT }, // 8 + { "14.bpr", 0x0100, 0x622a8ce7, BRF_OPT }, // 9 +}; + +STD_ROM_PICK(ambush) +STD_ROM_FN(ambush) + +struct BurnDriver BurnDrvAmbush = { + "ambush", NULL, NULL, NULL, "1983", + "Ambush\0", NULL, "Tecfri", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, ambushRomInfo, ambushRomName, NULL, NULL, AmbushInputInfo, AmbushDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; + + +// Ambush (Volt Elec co-ltd) + +static struct BurnRomInfo ambushvRomDesc[] = { + { "n1_h7.bin", 0x2000, 0x3c0833b4, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ambush.g7", 0x2000, 0x90291409, BRF_ESS | BRF_PRG }, // 1 + { "ambush.f7", 0x2000, 0xd023ca29, BRF_ESS | BRF_PRG }, // 2 + { "ambush.e7", 0x2000, 0x6cc2d3ee, BRF_ESS | BRF_PRG }, // 3 + + { "ambush.n4", 0x2000, 0xecc0dc85, BRF_GRA }, // 4 Graphics tiles + { "ambush.m4", 0x2000, 0xe86ca98a, BRF_GRA }, // 5 + + { "a.bpr", 0x0100, 0x5f27f511, BRF_GRA }, // 6 color PROMs + + { "b.bpr", 0x0100, 0x1b03fd3b, BRF_OPT }, // 7 Proms - Not used + { "13.bpr", 0x0100, 0x547e970f, BRF_OPT }, // 8 + { "14.bpr", 0x0100, 0x622a8ce7, BRF_OPT }, // 9 +}; + +STD_ROM_PICK(ambushv) +STD_ROM_FN(ambushv) + +struct BurnDriver BurnDrvAmbushv = { + "ambushv", "ambush", NULL, NULL, "1983", + "Ambush (Volt Elec co-ltd)\0", NULL, "Volt Elec co-ltd", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, ambushvRomInfo, ambushvRomName, NULL, NULL, AmbushInputInfo, AmbushDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; + + diff --git a/src/burn/drivers/misc_pre90s/d_angelkds.cpp b/src/burn/drivers/misc_pre90s/d_angelkds.cpp new file mode 100644 index 00000000..f080a06f --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_angelkds.cpp @@ -0,0 +1,1029 @@ +// FB Alpha Angel Kids driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROMDec; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgtRAM; +static UINT8 *DrvBgbRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; +static UINT32 *DrvPalette; + +static UINT16 *pTempDraw; + +static UINT8 *main_to_sound; +static UINT8 *sound_to_main; + +static UINT8 bgtopbank; +static UINT8 bgbotbank; +static UINT8 bgtopscroll; +static UINT8 bgbotscroll; +static UINT8 txbank; +static UINT8 layer_ctrl; + +static INT32 DrvZ80Bank0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT16 DrvInputs[3]; + +static struct BurnInputInfo AngelkdsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Left Stick Up", BIT_DIGITAL, DrvJoy2 + 4, "p3 up" }, + {"P1 Left Stick Down", BIT_DIGITAL, DrvJoy2 + 5, "p3 down" }, + {"P1 Left Stick Left", BIT_DIGITAL, DrvJoy2 + 6, "p3 left" }, + {"P1 Left Stick Right", BIT_DIGITAL, DrvJoy2 + 7, "p3 right" }, + {"P1 Right Stick Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Right Stick Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Right Stick Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right Stick Right",BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Left Stick Up", BIT_DIGITAL, DrvJoy3 + 4, "p4 up" }, + {"P2 Left Stick Down", BIT_DIGITAL, DrvJoy3 + 5, "p4 down" }, + {"P2 Left Stick Left", BIT_DIGITAL, DrvJoy3 + 6, "p4 left" }, + {"P2 Left Stick Right", BIT_DIGITAL, DrvJoy3 + 7, "p4 right" }, + {"P2 Right Stick Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up" }, + {"P2 Right Stick Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down" }, + {"P2 Right Stick Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right Stick Right",BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Angelkds) + +static struct BurnInputInfo SpcpostnInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Spcpostn) + +static struct BurnDIPInfo AngelkdsDIPList[]= +{ + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xf8, NULL }, + {0x18, 0xff, 0xff, 0x80, NULL }, + + {0 , 0xfe, 0 , 10, "Coin B" }, + {0x16, 0x01, 0x0f, 0x07, "4 Coins 1 Credits" }, + {0x16, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x16, 0x01, 0x0f, 0x09, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x16, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x16, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x16, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x16, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 10, "Coin A" }, + {0x16, 0x01, 0xf0, 0x70, "4 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0x90, "2 Coins 1 Credits" }, + {0x16, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x16, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x16, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x16, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x16, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x16, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x16, 0x01, 0xf0, 0x00, "Free Play" }, + +// not supported +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x17, 0x01, 0x01, 0x00, "Upright" }, +// {0x17, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "High Score Characters" }, + {0x17, 0x01, 0x02, 0x00, "3" }, + {0x17, 0x01, 0x02, 0x02, "10" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x17, 0x01, 0x0c, 0x0c, "20k, 50k, 100k, 200k and 500k" }, + {0x17, 0x01, 0x0c, 0x08, "50k, 100k, 200k and 500k" }, + {0x17, 0x01, 0x0c, 0x04, "100k, 200k and 500k" }, + {0x17, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x17, 0x01, 0x30, 0x30, "3" }, + {0x17, 0x01, 0x30, 0x20, "4" }, + {0x17, 0x01, 0x30, 0x10, "5" }, + {0x17, 0x01, 0x30, 0x00, "99 (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x17, 0x01, 0xc0, 0xc0, "Very Easy" }, + {0x17, 0x01, 0xc0, 0x40, "Easy" }, + {0x17, 0x01, 0xc0, 0x80, "Hard" }, + {0x17, 0x01, 0xc0, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x18, 0x01, 0x80, 0x00, "On" }, + {0x18, 0x01, 0x80, 0x80, "Off" }, +}; + +STDDIPINFO(Angelkds) + +static struct BurnDIPInfo SpcpostnDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xab, NULL }, + {0x14, 0xff, 0xff, 0x80, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x00, "Off" }, + {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x01, 0x01, "No" }, + {0x13, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Obstruction Car" }, + {0x13, 0x01, 0x02, 0x02, "Normal" }, + {0x13, 0x01, 0x02, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 4, "Time Limit" }, + {0x13, 0x01, 0x0c, 0x00, "1:10" }, + {0x13, 0x01, 0x0c, 0x04, "1:20" }, + {0x13, 0x01, 0x0c, 0x08, "1:30" }, + {0x13, 0x01, 0x0c, 0x0c, "1:40" }, + + {0 , 0xfe, 0 , 4, "Power Down" }, + {0x13, 0x01, 0x30, 0x30, "Slow" }, + {0x13, 0x01, 0x30, 0x20, "Normal" }, + {0x13, 0x01, 0x30, 0x10, "Fast" }, + {0x13, 0x01, 0x30, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Spcpostn) + +static void bankswitch(INT32 data) +{ + DrvZ80Bank0 = (data & 0x0f); + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + 0x10000 + DrvZ80Bank0 * 0x4000); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + 0x10000 + DrvZ80Bank0 * 0x4000); +} + +void __fastcall angelkds_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf000: + bgtopbank = data; + return; + + case 0xf001: + bgtopscroll = data; + return; + + case 0xf002: + bgbotbank = data; + return; + + case 0xf003: + bgbotscroll = data; + return; + + case 0xf004: + txbank = data; + return; + + case 0xf005: + layer_ctrl = data; + return; + } +} + +void __fastcall angelkds_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: // nop + case 0x43: + case 0x83: + return; + + case 0x42: + bankswitch(data); + return; + + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + main_to_sound[port & 3] = data; + return; + } +} + +UINT8 __fastcall angelkds_in_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x40: + return DrvDips[0]; + + case 0x41: + return DrvDips[1]; + + case 0x42: + return 0xff; + + case 0x80: + case 0x81: + case 0x82: + return DrvInputs[port & 3]; + + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + return sound_to_main[port & 3]; + } + + return 0; +} + +void __fastcall main_to_sound_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + BurnYM2203Write(0, port & 1, data); + return; + + case 0x40: + case 0x41: + BurnYM2203Write(1, port & 1, data); + return; + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + sound_to_main[port & 3] = data; + return; + } +} + +UINT8 __fastcall main_to_sound_in_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + return BurnYM2203Read(0, port & 1); + + case 0x40: + case 0x41: + return BurnYM2203Read(1, port & 1); + + case 0x80: + case 0x81: + case 0x82: + case 0x83: + return main_to_sound[port & 3]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + bankswitch(0); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + bgtopbank = 0; + bgbotbank = 0; + bgtopscroll = 0; + bgbotscroll = 0; + txbank = 0; + layer_ctrl = 0; + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x040000; + DrvZ80ROMDec = Next; Next += 0x00c000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x020000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROM3 = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32); + + pTempDraw = (UINT16*)Next; Next += 240 * 256 * sizeof(UINT16); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x002000; + DrvBgtRAM = Next; Next += 0x000400; + DrvBgbRAM = Next; Next += 0x000400; + DrvTxtRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000100; + DrvPalRAM = Next; Next += 0x000400; + + DrvZ80RAM1 = Next; Next += 0x000800; + + sound_to_main = Next; Next += 0x000004; + main_to_sound = Next; Next += 0x000004; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvGfxExpand(UINT8 *gfx, INT32 len) +{ + for (INT32 i = (len - 1); i >= 0; i--) { + gfx[i * 2 + 1] = gfx[i] & 0x0f; + gfx[i * 2 + 0] = gfx[i] >> 4; + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x00000, 0x00004, 0x40000, 0x40004 }; + INT32 XOffs[16] = { 0x00000, 0x00001, 0x00002, 0x00003, 0x00008, 0x00009, 0x0000a, 0x0000b, + 0x00010, 0x00011, 0x00012, 0x00013, 0x00018, 0x00019, 0x0001a, 0x0001b }; + INT32 YOffs[16] = { 0x00000, 0x00020, 0x00040, 0x00060, 0x00080, 0x000a0, 0x000c0, 0x000e0, + 0x00100, 0x00120, 0x00140, 0x00160, 0x00180, 0x001a0, 0x001c0, 0x001e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x010000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM1, 0x10000); + + GfxDecode(0x0200, 4, 16, 16, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + + DrvGfxExpand(DrvGfxROM0, 0x08000); + DrvGfxExpand(DrvGfxROM2, 0x40000); + DrvGfxExpand(DrvGfxROM3, 0x40000); + + return 0; +} + +//----------------------------------------------------------------------------------------------------- +// space position +/* +static void sega_decode_2(UINT8 *rom, UINT8 *decrypted, + const UINT8 opcode_xor[64],const INT32 opcode_swap_select[64], + const UINT8 data_xor[64],const INT32 data_swap_select[64]) +{ + static const UINT8 swaptable[24][4] = + { + { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 }, + { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 }, + { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 }, + { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 }, + { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 }, + { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 }, + }; + + for (INT32 A = 0x0000;A < 0x8000;A++) + { + const UINT8 *tbl; + + INT32 src = rom[A]; + + // pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address + INT32 row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2) + + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5); + + // decode opcodes + tbl = swaptable[opcode_swap_select[row]]; + decrypted[A] = BITSWAP08(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row]; + + // decode data + tbl = swaptable[data_swap_select[row]]; + rom[A] = BITSWAP08(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row]; + } +} + +static void sega_decode_317(UINT8 *src, UINT8 *dst, INT32 order, INT32 opcode_shift, INT32 data_shift) +{ + static const UINT8 xor1_317[1+64] = + { + 0x54, + 0x14,0x15,0x41,0x14,0x50,0x55,0x05,0x41,0x01,0x10,0x51,0x05,0x11,0x05,0x14,0x55, + 0x41,0x05,0x04,0x41,0x14,0x10,0x45,0x50,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00, + 0x54,0x04,0x15,0x10,0x04,0x05,0x11,0x44,0x04,0x01,0x05,0x00,0x44,0x15,0x40,0x45, + 0x10,0x15,0x51,0x50,0x00,0x15,0x51,0x44,0x15,0x04,0x44,0x44,0x50,0x10,0x04,0x04, + }; + + static const UINT8 xor2_317[2+64] = + { + 0x04, + 0x44, + 0x15,0x51,0x41,0x10,0x15,0x54,0x04,0x51,0x05,0x55,0x05,0x54,0x45,0x04,0x10,0x01, + 0x51,0x55,0x45,0x55,0x45,0x04,0x55,0x40,0x11,0x15,0x01,0x40,0x01,0x11,0x45,0x44, + 0x40,0x05,0x15,0x15,0x01,0x50,0x00,0x44,0x04,0x50,0x51,0x45,0x50,0x54,0x41,0x40, + 0x14,0x40,0x50,0x45,0x10,0x05,0x50,0x01,0x40,0x01,0x50,0x50,0x50,0x44,0x40,0x10, + }; + + static const INT32 swap1_317[1+64] = + { + 7, + 1,11,23,17,23, 0,15,19, + 20,12,10, 0,18,18, 5,20, + 13, 0,18,14, 5, 6,10,21, + 1,11, 9, 3,21, 4, 1,17, + 5, 7,16,13,19,23,20, 2, + 10,23,23,15,10,12, 0,22, + 14, 6,15,11,17,15,21, 0, + 6, 1, 1,18, 5,15,15,20, + }; + + static const INT32 swap2_317[2+64] = + { + 7, + 12, + 18, 8,21, 0,22,21,13,21, + 20,13,20,14, 6, 3, 5,20, + 8,20, 4, 8,17,22, 0, 0, + 6,17,17, 9, 0,16,13,21, + 3, 2,18, 6,11, 3, 3,18, + 18,19, 3, 0, 5, 0,11, 8, + 8, 1, 7, 2,10, 8,10, 2, + 1, 3,12,16, 0,17,10, 1, + }; + + if (order) sega_decode_2(src, dst, xor2_317+opcode_shift, swap2_317+opcode_shift, xor1_317+data_shift, swap1_317+data_shift); + else sega_decode_2(src, dst, xor1_317+opcode_shift, swap1_317+opcode_shift, xor2_317+data_shift, swap2_317+data_shift); +}*/ + +// This is used in Sega System 1 (d_sys1.cpp) +void sega_decode_317(UINT8 *pDest, UINT8 *pDestDec, INT32 order, INT32 opcode_shift, INT32 data_shift); + +static void spcpostn_decode() +{ + sega_decode_317(DrvZ80ROM0, DrvZ80ROMDec, 0, 0, 1); +} + +//----------------------------------------------------------------------------------------------------- + +static INT32 DrvInit(INT32 game) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (game == 1) // angelkds + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + + memcpy (DrvZ80ROMDec, DrvZ80ROM0, 0x08000); + + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x18000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x28000, 4, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x18000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x28000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x38000, 16, 1)) return 1; + + memcpy (DrvGfxROM3, DrvGfxROM2, 0x40000); // the data is the same in both gfx regions... + } + else // spcpostn + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + + spcpostn_decode(); + + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x18000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x28000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x30000, 5, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x08000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x10000, 15, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROMDec, DrvZ80ROM0); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe3ff, 0, DrvBgtRAM); + ZetMapArea(0xe000, 0xe3ff, 1, DrvBgtRAM); + ZetMapArea(0xe000, 0xe3ff, 2, DrvBgtRAM); + ZetMapArea(0xe400, 0xe7ff, 0, DrvBgbRAM); + ZetMapArea(0xe400, 0xe7ff, 1, DrvBgbRAM); + ZetMapArea(0xe400, 0xe7ff, 2, DrvBgbRAM); + ZetMapArea(0xe800, 0xebff, 0, DrvTxtRAM); + ZetMapArea(0xe800, 0xebff, 1, DrvTxtRAM); + ZetMapArea(0xe800, 0xebff, 2, DrvTxtRAM); + ZetMapArea(0xec00, 0xecff, 0, DrvSprRAM); + ZetMapArea(0xec00, 0xecff, 1, DrvSprRAM); + ZetMapArea(0xec00, 0xecff, 2, DrvSprRAM); + ZetMapArea(0xed00, 0xefff, 0, DrvPalRAM); + ZetMapArea(0xed00, 0xefff, 1, DrvPalRAM); + ZetMapArea(0xed00, 0xefff, 2, DrvPalRAM); + ZetSetWriteHandler(angelkds_write); + ZetSetOutHandler(angelkds_out_port); + ZetSetInHandler(angelkds_in_port); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetOutHandler(main_to_sound_out_port); + ZetSetInHandler(main_to_sound_in_port); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2203Exit(); + GenericTilesExit(); + + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT8 r,g,b; + for (INT32 i = 0; i < 0x100; i++) { + r = DrvPalRAM[i + 0x000] & 0x0f; + g = DrvPalRAM[i + 0x000] >> 4; + b = DrvPalRAM[i + 0x100] & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_sprites(UINT16 *dest, INT32 enable) +{ + for (INT32 offs = 0x100 - 4; offs >= 0; offs-=4) + { + INT32 attr = DrvSprRAM[offs + 1]; + INT32 sy = DrvSprRAM[offs + 2] ^ 0xff; + INT32 sx = DrvSprRAM[offs + 3]; + INT32 code = DrvSprRAM[offs + 0] + ((attr & 0x08) << 5); + + INT32 color = ((attr & 0x03) << 2) + 0x02; + INT32 flipx = attr & 0x10; + INT32 flipy = attr & 0x20; + + if (attr & enable) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(dest, code, sx, sy - 8, color, 4, 15, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(dest, code, sx, sy - 8, color, 4, 15, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(dest, code, sx, sy - 8, color, 4, 15, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(dest, code, sx, sy - 8, color, 4, 15, 0, DrvGfxROM1); + } + } + } + } +} + +static void draw_layer(UINT16 *dest, UINT8 *ram, UINT8 *gfx, INT32 bank, INT32 coloffs, INT32 scrollx, INT32 trans) +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = ((offs >> 5) << 3) - 8; + + sx -= scrollx; + if (sx < -7) sx += 0x100; + + INT32 code = ram[offs] | (bank << 8); + INT32 color = coloffs; + + Render8x8Tile_Mask_Clip(dest, code, sx, sy, color, 4, trans, 0, gfx); + if (sx < 0) Render8x8Tile_Mask_Clip(dest, code, sx + 256, sy, color, 4, trans, 0, gfx); + } +} + +static INT32 DrvDraw() +{ + DrvPaletteRecalc(); + + // top half - x = 0 -> 127 + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) pTransDraw[i] = 0x003f; + + if (~layer_ctrl & 0x80) draw_layer(pTransDraw, DrvBgtRAM, DrvGfxROM2, bgtopbank, 0, bgtopscroll, 15); + + draw_sprites(pTransDraw, 0x80); + + if (~layer_ctrl & 0x20) draw_layer(pTransDraw, DrvTxtRAM, DrvGfxROM0, txbank, 3, 0, 0); + } + + // bottom half - x = 128 -> 256 + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) pTempDraw[i] = 0x003f; + + if (~layer_ctrl & 0x40) draw_layer(pTempDraw, DrvBgbRAM, DrvGfxROM3, bgbotbank, 0, bgbotscroll, 15); + + draw_sprites(pTempDraw, 0x40); + + if (~layer_ctrl & 0x20) draw_layer(pTempDraw, DrvTxtRAM, DrvGfxROM0, txbank, 3, 0, 0); + } + + // copy bottom half into place + { + UINT16 *source = pTempDraw + 128; + UINT16 *dest = pTransDraw + 128; + for (INT32 y = 0; y < nScreenHeight; y++) { + memcpy (dest, source, 128 * sizeof(UINT16)); + dest += 256, source += 256; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[0] = (DrvInputs[0] & 0x7f) | (DrvDips[2] & 0x80); + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 8000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = nCyclesTotal[0] / nInterleave; + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + ZetOpen(1); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + } + + ZetOpen(1); + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(bgtopbank); + SCAN_VAR(bgbotbank); + SCAN_VAR(bgtopscroll); + SCAN_VAR(bgbotscroll); + SCAN_VAR(txbank); + SCAN_VAR(layer_ctrl); + + SCAN_VAR(DrvZ80Bank0); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(DrvZ80Bank0); + ZetClose(); + } + + return 0; +} + + +// Angel Kids (Japan) + +static struct BurnRomInfo angelkdsRomDesc[] = { + { "11428.c10", 0x8000, 0x90daacd2, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "11424.c1", 0x8000, 0xb55997f6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "11425.c2", 0x8000, 0x299359de, 1 | BRF_PRG | BRF_ESS }, // 2 + { "11426.c3", 0x8000, 0x5fad8bd3, 1 | BRF_PRG | BRF_ESS }, // 3 + { "11427.c4", 0x8000, 0xef920c74, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "11429.d4", 0x8000, 0x0ca50a66, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 #1 Code + + { "11446", 0x8000, 0x45052470, 3 | BRF_GRA }, // 6 Text Tiles + + { "11448.h7", 0x8000, 0x05dab626, 4 | BRF_GRA }, // 7 Sprites + { "11447.f7", 0x8000, 0xb3afc5b3, 4 | BRF_GRA }, // 8 + + { "11437", 0x8000, 0xa520b628, 5 | BRF_GRA }, // 9 Background (Top) Tiles + { "11436", 0x8000, 0x469ab216, 5 | BRF_GRA }, // 10 + { "11435", 0x8000, 0xb0f8c245, 5 | BRF_GRA }, // 11 + { "11434", 0x8000, 0xcbde81f5, 5 | BRF_GRA }, // 12 + { "11433", 0x8000, 0xb63fa414, 5 | BRF_GRA }, // 13 + { "11432", 0x8000, 0x00dc747b, 5 | BRF_GRA }, // 14 + { "11431", 0x8000, 0xac2025af, 5 | BRF_GRA }, // 15 + { "11430", 0x8000, 0xd640f89e, 5 | BRF_GRA }, // 16 + + { "11445", 0x8000, 0xa520b628, 6 | BRF_GRA }, // 17 Background (Bottom) Tiles + { "11444", 0x8000, 0x469ab216, 6 | BRF_GRA }, // 18 + { "11443", 0x8000, 0xb0f8c245, 6 | BRF_GRA }, // 19 + { "11442", 0x8000, 0xcbde81f5, 6 | BRF_GRA }, // 20 + { "11441", 0x8000, 0xb63fa414, 6 | BRF_GRA }, // 21 + { "11440", 0x8000, 0x00dc747b, 6 | BRF_GRA }, // 22 + { "11439", 0x8000, 0xac2025af, 6 | BRF_GRA }, // 23 + { "11438", 0x8000, 0xd640f89e, 6 | BRF_GRA }, // 24 + + { "63s081n.u5", 0x0020, 0x36b98627, 7 | BRF_OPT }, // 25 PROM +}; + +STD_ROM_PICK(angelkds) +STD_ROM_FN(angelkds) + +static INT32 angelkdsInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvAngelkds = { + "angelkds", NULL, NULL, NULL, "1988", + "Angel Kids (Japan)\0", NULL, "Sega / Nasco?", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, angelkdsRomInfo, angelkdsRomName, NULL, NULL, AngelkdsInputInfo, AngelkdsDIPInfo, + angelkdsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x100, + 240, 256, 3, 4 +}; + + +// Space Position (Japan) + +static struct BurnRomInfo spcpostnRomDesc[] = { + { "epr10125.c10", 0x8000, 0xbffd38c6, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "epr10120.c1", 0x8000, 0xd6399f99, 1 | BRF_PRG | BRF_ESS }, // 1 + { "epr10121.c2", 0x8000, 0xd4861560, 1 | BRF_PRG | BRF_ESS }, // 2 + { "epr10122.c3", 0x8000, 0x7a1bff1b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "epr10123.c4", 0x8000, 0x6aed2925, 1 | BRF_PRG | BRF_ESS }, // 4 + { "epr10124.c5", 0x8000, 0xa1d7ae6b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "epr10126.d4", 0x8000, 0xab17f852, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 #1 Code + + { "epr10133.17", 0x8000, 0x642e6609, 3 | BRF_GRA }, // 7 Text Tiles + + { "epr10135.19", 0x8000, 0x0685c4fa, 4 | BRF_GRA }, // 8 Sprites + { "epr10134.18", 0x8000, 0xc674ff88, 4 | BRF_GRA }, // 9 + + { "epr10132.16", 0x8000, 0x2df8b1bd, 5 | BRF_GRA }, // 10 Background (Top) Tiles + { "epr10131.15", 0x8000, 0xde223817, 5 | BRF_GRA }, // 11 + { "epr10130.14", 0x8000, 0xb68fcb36, 5 | BRF_GRA }, // 12 + + { "epr10129.08", 0x8000, 0xa6f21023, 6 | BRF_GRA }, // 13 Background (Bottom) Tiles + { "epr10128.07", 0x8000, 0xde223817, 6 | BRF_GRA }, // 14 + { "epr10127.06", 0x8000, 0xb68fcb36, 6 | BRF_GRA }, // 15 + + { "63s081n.u5", 0x0020, 0x36b98627, 0 | BRF_OPT }, // 16 PROM +}; + +STD_ROM_PICK(spcpostn) +STD_ROM_FN(spcpostn) + +static INT32 spcpostnInit() +{ + return DrvInit(2); +} + +struct BurnDriver BurnDrvSpcpostn = { + "spcpostn", NULL, NULL, NULL, "1986", + "Space Position (Japan)\0", NULL, "Sega / Nasco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, spcpostnRomInfo, spcpostnRomName, NULL, NULL, SpcpostnInputInfo, SpcpostnDIPInfo, + spcpostnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x100, + 240, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_arabian.cpp b/src/burn/drivers/misc_pre90s/d_arabian.cpp new file mode 100644 index 00000000..cbc2d1a4 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_arabian.cpp @@ -0,0 +1,706 @@ +// FB Alpha Arabian driver module +// Based on MAME driver by Jarek Burczynski and various others + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvBlitRAM; +static UINT8 *DrvTempBmp; +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT16 *pAY8910Buffer[3]; + +static UINT8 *arabian_color; +static UINT8 *flipscreen; + +static INT32 custom_cpu_reset; +static INT32 custom_cpu_busy; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvJoy6[8]; +static UINT8 DrvJoy7[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[8]; +static UINT8 DrvReset; + +static struct BurnInputInfo ArabianInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 1, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy4 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy4 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy4 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy4 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy5 + 0, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 2, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy6 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy6 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy6 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy6 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy7 + 0, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Arabian) + +static struct BurnDIPInfo ArabianDIPList[]= +{ + {0x10, 0xff, 0xff, 0x06, NULL }, + {0x11, 0xff, 0xff, 0x0d, NULL }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x10, 0x01, 0x01, 0x00, "3" }, + {0x10, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x10, 0x01, 0x02, 0x02, "Upright" }, + {0x10, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x04, 0x04, "Off" }, + {0x10, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x10, 0x01, 0x08, 0x00, "Easy" }, + {0x10, 0x01, 0x08, 0x08, "Hard" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x10, 0x01, 0xf0, 0x10, "A 2/1 B 2/1" }, + {0x10, 0x01, 0xf0, 0x20, "A 2/1 B 1/3" }, + {0x10, 0x01, 0xf0, 0x00, "A 1/1 B 1/1" }, + {0x10, 0x01, 0xf0, 0x30, "A 1/1 B 1/2" }, + {0x10, 0x01, 0xf0, 0x40, "A 1/1 B 1/3" }, + {0x10, 0x01, 0xf0, 0x50, "A 1/1 B 1/4" }, + {0x10, 0x01, 0xf0, 0x60, "A 1/1 B 1/5" }, + {0x10, 0x01, 0xf0, 0x70, "A 1/1 B 1/6" }, + {0x10, 0x01, 0xf0, 0x80, "A 1/2 B 1/2" }, + {0x10, 0x01, 0xf0, 0x90, "A 1/2 B 1/4" }, + {0x10, 0x01, 0xf0, 0xa0, "A 1/2 B 1/5" }, + {0x10, 0x01, 0xf0, 0xe0, "A 1/2 B 1/6" }, + {0x10, 0x01, 0xf0, 0xb0, "A 1/2 B 1/10" }, + {0x10, 0x01, 0xf0, 0xc0, "A 1/2 B 1/11" }, + {0x10, 0x01, 0xf0, 0xd0, "A 1/2 B 1/12" }, + {0x10, 0x01, 0xf0, 0xf0, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Coin Counters" }, + {0x11, 0x01, 0x01, 0x01, "1" }, + {0x11, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x11, 0x01, 0x0c, 0x0c, "30k 70k 40k+" }, + {0x11, 0x01, 0x0c, 0x04, "20k only" }, + {0x11, 0x01, 0x0c, 0x08, "40k only" }, + {0x11, 0x01, 0x0c, 0x00, "None" }, +}; + +STDDIPINFO(Arabian) + +static struct BurnDIPInfo ArabianaDIPList[]= +{ + {0x10, 0xff, 0xff, 0x06, NULL }, + {0x11, 0xff, 0xff, 0x0d, NULL }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x10, 0x01, 0x01, 0x00, "3" }, + {0x10, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x10, 0x01, 0x02, 0x02, "Upright" }, + {0x10, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x04, 0x04, "Off" }, + {0x10, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x10, 0x01, 0x08, 0x00, "Easy" }, + {0x10, 0x01, 0x08, 0x08, "Hard" }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x10, 0x01, 0xf0, 0x10, "A 2/1 B 2/1" }, + {0x10, 0x01, 0xf0, 0x20, "A 2/1 B 1/3" }, + {0x10, 0x01, 0xf0, 0x00, "A 1/1 B 1/1" }, + {0x10, 0x01, 0xf0, 0x30, "A 1/1 B 1/2" }, + {0x10, 0x01, 0xf0, 0x40, "A 1/1 B 1/3" }, + {0x10, 0x01, 0xf0, 0x50, "A 1/1 B 1/4" }, + {0x10, 0x01, 0xf0, 0x60, "A 1/1 B 1/5" }, + {0x10, 0x01, 0xf0, 0x70, "A 1/1 B 1/6" }, + {0x10, 0x01, 0xf0, 0x80, "A 1/2 B 1/2" }, + {0x10, 0x01, 0xf0, 0x90, "A 1/2 B 1/4" }, + {0x10, 0x01, 0xf0, 0xa0, "A 1/2 B 1/5" }, + {0x10, 0x01, 0xf0, 0xe0, "A 1/2 B 1/6" }, + {0x10, 0x01, 0xf0, 0xb0, "A 1/2 B 1/10" }, + {0x10, 0x01, 0xf0, 0xc0, "A 1/2 B 1/11" }, + {0x10, 0x01, 0xf0, 0xd0, "A 1/2 B 1/12" }, + {0x10, 0x01, 0xf0, 0xf0, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Coin Counters" }, + {0x11, 0x01, 0x01, 0x01, "1" }, + {0x11, 0x01, 0x01, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x11, 0x01, 0x0c, 0x0c, "20k 50k 150k 100k+" }, + {0x11, 0x01, 0x0c, 0x04, "20k only" }, + {0x11, 0x01, 0x0c, 0x08, "40k only" }, + {0x11, 0x01, 0x0c, 0x00, "None" }, +}; + +STDDIPINFO(Arabiana) + +static UINT8 custom_cpu_r(UINT16 offset) +{ + if (custom_cpu_reset || offset < 0x7f0) + return DrvZ80RAM[offset]; + + switch (offset & 0x0f) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + return DrvInputs[(offset & 0x0f)+2]; + + case 6: + return custom_cpu_busy ^= 1; + + case 8: + return DrvZ80RAM[offset - 1]; + + default: + return 0; + } + return 0; +} + +static void blit_area(UINT8 plane, UINT16 src, UINT8 x, UINT8 y, UINT8 sx, UINT8 sy) +{ + UINT8 *srcdata = DrvGfxROM + src * 4; + + for (INT32 i = 0; i <= sx; i++, x += 4) + { + for (INT32 j = 0; j <= sy; j++) + { + UINT8 p1 = *srcdata++; + UINT8 p2 = *srcdata++; + UINT8 p3 = *srcdata++; + UINT8 p4 = *srcdata++; + UINT8 *base = DrvTempBmp + (((y + j) & 0xff) * 256 + (x & 0xff)); + + if (plane & 0x01) + { + if (p4 != 8) base[0] = (base[0] & ~0xf0) | (p4 << 4); + if (p3 != 8) base[1] = (base[1] & ~0xf0) | (p3 << 4); + if (p2 != 8) base[2] = (base[2] & ~0xf0) | (p2 << 4); + if (p1 != 8) base[3] = (base[3] & ~0xf0) | (p1 << 4); + } + + if (plane & 0x04) + { + if (p4 != 8) base[0] = (base[0] & ~0x0f) | p4; + if (p3 != 8) base[1] = (base[1] & ~0x0f) | p3; + if (p2 != 8) base[2] = (base[2] & ~0x0f) | p2; + if (p1 != 8) base[3] = (base[3] & ~0x0f) | p1; + } + } + } +} + +static void arabian_blitter_w(INT32 offset, UINT8 data) +{ + DrvBlitRAM[offset] = data; + + if (offset == 0x0006) + { + INT32 plane = DrvBlitRAM[offset - 6]; + INT32 src = DrvBlitRAM[offset - 5] | (DrvBlitRAM[offset - 4] << 8); + INT32 x = DrvBlitRAM[offset - 2] << 2; + INT32 y = DrvBlitRAM[offset - 3]; + INT32 sx = DrvBlitRAM[offset - 0]; + INT32 sy = DrvBlitRAM[offset - 1]; + + blit_area(plane, src, x, y, sx, sy); + } +} + +void __fastcall arabian_videoram_w(UINT16 offset, UINT8 data) +{ + UINT8 *base; + UINT8 x, y; + + x = (offset >> 8) << 2; + y = offset & 0xff; + + DrvVidRAM[offset & 0x3fff] = data; + + base = &DrvTempBmp[y * 256 + x]; + + if (DrvBlitRAM[0] & 0x08) + { + base[0] = (base[0] & ~0x03) | ((data & 0x10) >> 3) | ((data & 0x01) >> 0); + base[1] = (base[1] & ~0x03) | ((data & 0x20) >> 4) | ((data & 0x02) >> 1); + base[2] = (base[2] & ~0x03) | ((data & 0x40) >> 5) | ((data & 0x04) >> 2); + base[3] = (base[3] & ~0x03) | ((data & 0x80) >> 6) | ((data & 0x08) >> 3); + } + + if (DrvBlitRAM[0] & 0x04) + { + base[0] = (base[0] & ~0x0c) | ((data & 0x10) >> 1) | ((data & 0x01) << 2); + base[1] = (base[1] & ~0x0c) | ((data & 0x20) >> 2) | ((data & 0x02) << 1); + base[2] = (base[2] & ~0x0c) | ((data & 0x40) >> 3) | ((data & 0x04) << 0); + base[3] = (base[3] & ~0x0c) | ((data & 0x80) >> 4) | ((data & 0x08) >> 1); + } + + if (DrvBlitRAM[0] & 0x02) + { + base[0] = (base[0] & ~0x30) | ((data & 0x10) << 1) | ((data & 0x01) << 4); + base[1] = (base[1] & ~0x30) | ((data & 0x20) << 0) | ((data & 0x02) << 3); + base[2] = (base[2] & ~0x30) | ((data & 0x40) >> 1) | ((data & 0x04) << 2); + base[3] = (base[3] & ~0x30) | ((data & 0x80) >> 2) | ((data & 0x08) << 1); + } + + if (DrvBlitRAM[0] & 0x01) + { + base[0] = (base[0] & ~0xc0) | ((data & 0x10) << 3) | ((data & 0x01) << 6); + base[1] = (base[1] & ~0xc0) | ((data & 0x20) << 2) | ((data & 0x02) << 5); + base[2] = (base[2] & ~0xc0) | ((data & 0x40) << 1) | ((data & 0x04) << 4); + base[3] = (base[3] & ~0xc0) | ((data & 0x80) << 0) | ((data & 0x08) << 3); + } +} + +void __fastcall arabian_write(UINT16 address, UINT8 data) +{ + if ((address & 0xc000) == 0x8000) { + arabian_videoram_w(address & 0x3fff, data); + return; + } + + if ((address & 0xf000) == 0xe000) { + arabian_blitter_w(address & 0x0007, data); + return; + } +} + +UINT8 __fastcall arabian_read(UINT16 address) +{ + if ((address & 0xfe00) == 0xc000) { + return DrvInputs[0]; + } + + if ((address & 0xfe00) == 0xc200) { + return DrvDips[0]; + } + + if ((address & 0xff00) == 0xd700) { + return custom_cpu_r(address & 0x7ff); + } + + return 0; +} + +void __fastcall arabian_out(UINT16 port, UINT8 data) +{ + switch (port) + { + case 0xc800: + AY8910Write(0, 0, data); + break; + + case 0xca00: + AY8910Write(0, 1, data); + break; + } +} + +void ay8910_porta_w(UINT32, UINT32 data) +{ + *arabian_color = data >> 3; +} + +void ay8910_portb_w(UINT32, UINT32 data) +{ + custom_cpu_reset = ~data & 0x10; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + custom_cpu_reset = 0; + custom_cpu_busy = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM = Next; Next += 0x010000; + + Palette = (UINT32*)Next; Next += 0x2000 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x2000 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x004000; + DrvBlitRAM = Next; Next += 0x001000; + + DrvTempBmp = Next; Next += 256 * 256; + + flipscreen = Next; Next += 0x000001; + arabian_color = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + UINT32 tpal[0x40]; + + for (INT32 i = 0; i < 64; i++) + { + INT32 r, b, g; + r = ((i >> 5) & 1) * (153*192/255) + ((i >> 4) & 1) * (102*192/255) + ((i & 0x30) ? 63 : 0); + g = ((i >> 3) & 1) * (156*192/255) + ((i >> 2) & 1) * (99*192/255) + ((i & 0x0c) ? 63 : 0); + b = ((i >> 1) & 1) * 192 + ((i >> 0) & 1) * 63; + tpal[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < (1 << 13); i++) + { + INT32 ena = (i >> 12) & 1; + INT32 enb = (i >> 11) & 1; + INT32 abhf = (~i >> 10) & 1; + INT32 aghf = (~i >> 9) & 1; + INT32 arhf = (~i >> 8) & 1; + INT32 az = (i >> 7) & 1; + INT32 ar = (i >> 6) & 1; + INT32 ag = (i >> 5) & 1; + INT32 ab = (i >> 4) & 1; + INT32 bz = (i >> 3) & 1; + INT32 br = (i >> 2) & 1; + INT32 bg = (i >> 1) & 1; + INT32 bb = (i >> 0) & 1; + + INT32 planea = (az | ar | ag | ab) & ena; + + INT32 rhi = planea ? ar : enb ? bz : 0; + INT32 rlo = planea ? ((!arhf & az) ? 0 : ar) : enb ? br : 0; + + INT32 ghi = planea ? ag : enb ? bb : 0; + INT32 glo = planea ? ((!aghf & az) ? 0 : ag) : enb ? bg : 0; + + INT32 bhi = ab; + INT32 bbase = (!abhf & az) ? 0 : ab; + + INT32 t = (rhi << 5) | (rlo << 4) | (ghi << 3) | (glo << 2) | (bhi << 1) | bbase; + + Palette[i] = tpal[t]; + } +} + +static void DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + + for (INT32 offs = 0; offs < 0x4000 * 4; offs+=4) + { + INT32 v1 = DrvGfxROM[(offs / 4) + 0x0000]; + INT32 v2 = DrvGfxROM[(offs / 4) + 0x4000]; + + for (INT32 j = 0; j < 4; j++, v1>>=1, v2>>=1) { + tmp[offs + 3 - j] = (v1 & 1) | ((v1 >> 3) & 2) | ((v2 << 2) & 4) | ((v2 >> 1) & 8); + } + } + + memcpy (DrvGfxROM, tmp, 0x10000); + BurnFree (tmp); +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x6000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x2000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x4000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x6000, 7, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xd000, 0xd6ff, 0, DrvZ80RAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvZ80RAM); + ZetMapArea(0xd000, 0xd7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(arabian_write); + ZetSetReadHandler(arabian_read); + ZetSetOutHandler(arabian_out); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, ay8910_porta_w, ay8910_portb_w); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + AY8910Exit(0); + + BurnFree (AllMem); + + return 0; +} + +static inline void update_flip_state() +{ + *flipscreen = DrvZ80RAM[0x034b]; + + if (DrvZ80RAM[0x0400] != 0 && !(DrvZ80RAM[0x0401] & 0x02)) + *flipscreen = !*flipscreen; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x2000; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, (d >> 8) & 0xff, d & 0xff, 0); + } + } + + update_flip_state(); + + UINT16 *pDst = pTransDraw; + UINT8 *pSrc = DrvTempBmp + (11 * 256); + + if (*flipscreen) { + pDst += nScreenWidth * (nScreenHeight - 1); + for (INT32 y = 11; y < 256-11; y++) { + for (INT32 x = 0; x < 256; x++) { + pDst[x] = pSrc[x ^ 0xff]; + } + pDst -= nScreenWidth; + pSrc += 256; + } + } else { + for (INT32 y = 11; y < 256-11; y++) { + for (INT32 x = 0; x < 256; x++) { + pDst[x] = pSrc[x]; + } + pDst += nScreenWidth; + pSrc += 256; + } + } + + BurnTransferCopy(DrvPalette + (*arabian_color << 8)); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0, 8); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy6[i] & 1) << i; + DrvInputs[6] ^= (DrvJoy7[i] & 1) << i; + } + DrvInputs[1] = DrvDips[0]; + DrvInputs[2] |= 1; + DrvInputs[7] = DrvDips[1]; + } + + ZetOpen(0); + ZetRun(3000000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(custom_cpu_reset); + SCAN_VAR(custom_cpu_busy); + } + + return 0; +} + + +// Arabian + +static struct BurnRomInfo arabianRomDesc[] = { + { "ic1rev2.87", 0x2000, 0x5e1c98b8, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic2rev2.88", 0x2000, 0x092f587e, BRF_ESS | BRF_PRG }, // 1 + { "ic3rev2.89", 0x2000, 0x15145f23, BRF_ESS | BRF_PRG }, // 2 + { "ic4rev2.90", 0x2000, 0x32b77b44, BRF_ESS | BRF_PRG }, // 3 + + { "tvg-91.ic84",0x2000, 0xc4637822, BRF_GRA }, // 4 Graphics + { "tvg-92.ic85",0x2000, 0xf7c6866d, BRF_GRA }, // 5 + { "tvg-93.ic86",0x2000, 0x71acd48d, BRF_GRA }, // 6 + { "tvg-94.ic87",0x2000, 0x82160b9a, BRF_GRA }, // 7 + + { "sun-8212.ic3",0x0800, 0x8869611e, BRF_OPT }, // 8 MCU +}; + +STD_ROM_PICK(arabian) +STD_ROM_FN(arabian) + +struct BurnDriver BurnDrvarabian = { + "arabian", NULL, NULL, NULL, "1983", + "Arabian\0", NULL, "Sun Electronics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, arabianRomInfo, arabianRomName, NULL, NULL, ArabianInputInfo, ArabianDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 234, 256, 3, 4 +}; + +// Arabian (Atari) + +static struct BurnRomInfo arabianaRomDesc[] = { + { "tvg-87.ic1", 0x2000, 0x51e9a6b1, BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "tvg-88.ic2", 0x2000, 0x1cdcc1ab, BRF_ESS | BRF_PRG }, // 1 + { "tvg-89.ic3", 0x2000, 0xb7b7faa0, BRF_ESS | BRF_PRG }, // 2 + { "tvg-90.ic4", 0x2000, 0xdbded961, BRF_ESS | BRF_PRG }, // 3 + + { "tvg-91.ic84",0x2000, 0xc4637822, BRF_GRA }, // 4 Graphics + { "tvg-92.ic85",0x2000, 0xf7c6866d, BRF_GRA }, // 5 + { "tvg-93.ic86",0x2000, 0x71acd48d, BRF_GRA }, // 6 + { "tvg-94.ic87",0x2000, 0x82160b9a, BRF_GRA }, // 7 + + { "sun-8212.ic3",0x0800, 0x8869611e, BRF_OPT }, // 8 MCU +}; + +STD_ROM_PICK(arabiana) +STD_ROM_FN(arabiana) + +struct BurnDriver BurnDrvarabiana = { + "arabiana", "arabian", NULL, NULL, "1983", + "Arabian (Atari)\0", NULL, "[Sun Electronics] (Atari license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, arabianaRomInfo, arabianaRomName, NULL, NULL, ArabianInputInfo, ArabianaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000, + 234, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_arkanoid.cpp b/src/burn/drivers/misc_pre90s/d_arkanoid.cpp new file mode 100644 index 00000000..b5860208 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_arkanoid.cpp @@ -0,0 +1,1890 @@ +// FB Alpha Arkanoid driver module +// Based on MAME driver by Brad Oliver and MANY others. + +#include "tiles_generic.h" +#include "taito_m68705.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvMcuROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvMcuRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static INT16 *pAY8910Buffer[3]; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *flipscreen; +static UINT8 *gfxbank; +static UINT8 *palettebank; +static UINT8 *paddleselect; +static UINT8 *bankselect; + +static UINT8 DrvInputs[4]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[1]; +static UINT8 DrvReset; +static UINT16 DrvAxis[2]; +static UINT32 nAnalogAxis[2] = {0,0}; + +static INT32 arkanoid_bootleg_id; +static INT32 use_mcu; + +static UINT8 arkanoid_bootleg_cmd; + +enum { + ARKUNK=0, + ARKANGC, + ARKANGC2, + ARKBLOCK, + ARKBLOC2, + ARKGCBL, + PADDLE2, + HEXA, + TETRSARK +}; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 4, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 1"}, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 x-axis"), + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 5, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 2, "p2 fire 1"}, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 1, "p1 x-axis"), + + {"Tilt", BIT_DIGITAL, DrvJoy1 + 3, "tilt" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "diag" }, + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo tetrsarkInputList[] = { + {"P1 Coin" , BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL, DrvJoy1 + 4, "p1 start" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 0, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 start" , BIT_DIGITAL, DrvJoy1 + 5, "p2 start" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 0, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(tetrsark) + +static struct BurnInputInfo HexaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, +}; + +STDINPUTINFO(Hexa) + +static struct BurnDIPInfo arkanoidDIPList[]= +{ + {0x0b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0b, 0x01, 0x01, 0x01, "No" }, + {0x0b, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "20K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "20K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + {0x0b, 0x01, 0x20, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +}; + +STDDIPINFO(arkanoid) + +static struct BurnDIPInfo arknoidjDIPList[]= +{ + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0b, 0x01, 0x01, 0x01, "No" }, + {0x0b, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "20K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "20K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + {0x0b, 0x01, 0x20, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x40, 0x00, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(arknoidj) + +static struct BurnDIPInfo ark1ballDIPList[]= +{ + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0b, 0x01, 0x01, 0x01, "No" }, + {0x0b, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "60K 100K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "60K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "1" }, + {0x0b, 0x01, 0x20, 0x00, "2" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x40, 0x00, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(ark1ball) + +static struct BurnDIPInfo arkangcDIPList[]= +{ + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Ball Speed" }, + {0x0b, 0x01, 0x01, 0x01, "Normal" }, + {0x0b, 0x01, 0x01, 0x00, "Faster" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "20K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "20K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + {0x0b, 0x01, 0x20, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x40, 0x00, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(arkangc) + +static struct BurnDIPInfo arkangc2DIPList[]= +{ + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Ball Speed" }, + {0x0b, 0x01, 0x01, 0x01, "Slower" }, + {0x0b, 0x01, 0x01, 0x00, "Normal" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "20K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "20K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + {0x0b, 0x01, 0x20, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x40, 0x00, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(arkangc2) + +static struct BurnDIPInfo arkgcblDIPList[]= +{ + {0x0b, 0xff, 0xff, 0x5f, NULL }, + + {0 , 0xfe, 0 , 2 , "Round Select" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "60K 100K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "60K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x00, "2" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(arkgcbl) + +static struct BurnDIPInfo paddle2DIPList[]= +{ + {0x0b, 0xff, 0xff, 0x5f, NULL }, + + {0 , 0xfe, 0 , 2 , "Round Select" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Controls ?" }, + {0x0b, 0x01, 0x04, 0x04, "Normal" }, + {0x0b, 0x01, 0x04, 0x00, "Alternate" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "60K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "60K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x00, "2" }, + {0x0b, 0x01, 0x20, 0x20, "3" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x40, 0x00, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(paddle2) + +static struct BurnDIPInfo arktayt2DIPList[]= +{ + {0x0b, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0b, 0x01, 0x01, 0x01, "No" }, + {0x0b, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0b, 0x01, 0x08, 0x08, "Easy" }, + {0x0b, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0b, 0x01, 0x10, 0x10, "60K 60K 60K+" }, + {0x0b, 0x01, 0x10, 0x00, "60K" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0b, 0x01, 0x20, 0x20, "2" }, + {0x0b, 0x01, 0x20, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0b, 0x01, 0x40, 0x00, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x40, 0x40, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x80, 0x00, "Upright" }, + {0x0b, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(arktayt2) + +static struct BurnDIPInfo tetrsarkDIPList[]= +{ + {0x0d, 0xff, 0xff, 0xf0, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x10, 0x10, "Upright" }, + {0x0d, 0x01, 0x10, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x20, 0x20, "Off" }, + {0x0d, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0xc0, 0x40, "1C 3C" }, + {0x0d, 0x01, 0xc0, 0x00, "1C 5C" }, +}; + +STDDIPINFO(tetrsark) + +static struct BurnDIPInfo HexaDIPList[]= +{ + {0x09, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x09, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x09, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x09, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x09, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Naughty Pics" }, + {0x09, 0x01, 0x04, 0x04, "Off" }, + {0x09, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x09, 0x01, 0x08, 0x08, "Off" }, + {0x09, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty?" }, + {0x09, 0x01, 0x30, 0x30, "Easy?" }, + {0x09, 0x01, 0x30, 0x20, "Medium?" }, + {0x09, 0x01, 0x30, 0x10, "Hard?" }, + {0x09, 0x01, 0x30, 0x00, "Hardest?" }, + + {0 , 0xfe, 0 , 2, "Pobys" }, + {0x09, 0x01, 0x40, 0x40, "2" }, + {0x09, 0x01, 0x40, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x09, 0x01, 0x80, 0x00, "Off" }, + {0x09, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Hexa) + +static UINT8 arkanoid_bootleg_f002_read() +{ + UINT8 arkanoid_bootleg_val = 0x00; + + switch (arkanoid_bootleg_id) + { + case ARKANGC: + case ARKBLOCK: + case ARKBLOC2: + case ARKANGC2: + break; + + case ARKGCBL: + switch (arkanoid_bootleg_cmd) + { + case 0x8a: + arkanoid_bootleg_val = 0xa5; + break; + case 0xff: + arkanoid_bootleg_val = 0xe2; + break; + default: + break; + } + break; + + case PADDLE2: + switch (arkanoid_bootleg_cmd) + { + case 0x24: // Avoid bad jump to 0x0066 + arkanoid_bootleg_val = 0x9b; + break; + case 0x36: // Avoid "BAD HARDWARE " message + arkanoid_bootleg_val = 0x2d; + break; + case 0x38: // Start of levels table (fixed offset) + arkanoid_bootleg_val = 0xf3; + break; + case 0x8a: // Current level (fixed routine) + arkanoid_bootleg_val = 0xa5; + break; + case 0xc3: // Avoid bad jump to 0xf000 + arkanoid_bootleg_val = 0x1d; + break; + case 0xe3: // Number of bricks left (fixed offset) + arkanoid_bootleg_val = 0x61; + break; + case 0xf7: // Avoid "U69" message + arkanoid_bootleg_val = 0x00; + break; + case 0xff: // Avoid "BAD HARDWARE " message (fixed routine) + arkanoid_bootleg_val = 0xe2; + break; + default: + break; + } + break; + } + + return arkanoid_bootleg_val; +} + +static void arkanoid_bootleg_d018_write(UINT8 data) +{ + arkanoid_bootleg_cmd = 0x00; + + switch (arkanoid_bootleg_id) + { + case ARKANGC: + case ARKBLOCK: + switch (data) + { + case 0x36: // unneeded value : no call 0x2050, unused A and overwritten HL (0x0313 -> 0x0340) + if (ZetPc(-1) == 0x7c47) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x38: // unneeded value : no call 0x2050, unused A and fixed HL (0x7bd5) + if (ZetPc(-1) == 0x7b87) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x8a: // unneeded value : no call 0x2050, unused A and overwritten HL (0x7b77 -> 0x7c1c) + if (ZetPc(-1) == 0x9661) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xe3: // unneeded value : call 0x2050 but fixed A (0x00) and fixed HL (0xed83) + if (ZetPc(-1) == 0x67e3) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xf7: // unneeded value : 3 * 'NOP' at 0x034f + 2 * 'NOP' at 0x35b + if (ZetPc(-1) == 0x0349) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xff: // unneeded value : no call 0x2050, unused A and overwritten HL (0x7c4f -> 0x7d31) + if (ZetPc(-1) == 0x9670) + arkanoid_bootleg_cmd = 0x00; + break; + default: + arkanoid_bootleg_cmd = 0x00; + break; + } + break; + + case ARKANGC2: + switch (data) + { + case 0x36: // unneeded value : call 0x2050 but fixed A (0x2d) + if (ZetPc(-1) == 0x7c4c) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x38: // unneeded value : call 0x2050 but fixed A (0xf3) + if (ZetPc(-1) == 0x7b87) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x88: // unneeded value : no read back + if (ZetPc(-1) == 0x67e3) + arkanoid_bootleg_cmd = 0x00; + if (ZetPc(-1) == 0x7c47) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x89: // unneeded value : no read back + if (ZetPc(-1) == 0x67e5) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x8a: // unneeded value : call 0x2050 but fixed A (0xa5) + if (ZetPc(-1) == 0x9661) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xc0: // unneeded value : no read back + if (ZetPc(-1) == 0x67e7) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xe3: // unneeded value : call 0x2050 but fixed A (0x61) + if (ZetPc(-1) == 0x67e9) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xff: // unneeded value : call 0x2050 but fixed A (0xe2) + if (ZetPc(-1) == 0x9670) + arkanoid_bootleg_cmd = 0x00; + break; + default: + arkanoid_bootleg_cmd = 0x00; + break; + } + break; + + case ARKBLOC2: + switch (data) + { + case 0x36: // unneeded value : call 0x2050 but fixed A (0x2d) + if (ZetPc(-1) == 0x7c4c) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x38: // unneeded value : call 0x2050 but fixed A (0xf3) + if (ZetPc(-1) == 0x7b87) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x88: // unneeded value : no read back + if (ZetPc(-1) == 0x67e3) + arkanoid_bootleg_cmd = 0x00; + if (ZetPc(-1) == 0x7c47) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x89: // unneeded value : no read back + if (ZetPc(-1) == 0x67e5) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x8a: // unneeded value : call 0x2050 but unused HL and fixed DE (0x7c1c) + if (ZetPc(-1) == 0x9661) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xc0: // unneeded value : no read back + if (ZetPc(-1) == 0x67e7) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xe3: // unneeded value : call 0x2050 but fixed A (0x61) + if (ZetPc(-1) == 0x67e9) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xf7: // unneeded value : call 0x2050 but never called (check code at 0x0340) + if (ZetPc(-1) == 0x0349) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xff: // unneeded value : no call 0x2050, unused A and fixed HL (0x7d31) + if (ZetPc(-1) == 0x9670) + arkanoid_bootleg_cmd = 0x00; + break; + default: + arkanoid_bootleg_cmd = 0x00; + break; + } + break; + + case ARKGCBL: + switch (data) + { + case 0x36: // unneeded value : call 0x2050 but fixed A (0x2d) + if (ZetPc(-1) == 0x7c4c) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x38: // unneeded value : call 0x2050 but fixed A (0xf3) + if (ZetPc(-1) == 0x7b87) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x88: // unneeded value : no read back + if (ZetPc(-1) == 0x67e3) + arkanoid_bootleg_cmd = 0x00; + if (ZetPc(-1) == 0x7c47) + arkanoid_bootleg_cmd = 0x00; + case 0x89: // unneeded value : no read back + if (ZetPc(-1) == 0x67e5) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x8a: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x9661) + arkanoid_bootleg_cmd = data; + break; + case 0xc0: // unneeded value : no read back + if (ZetPc(-1) == 0x67e7) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xe3: // unneeded value : call 0x2050 but fixed A (0x61) + if (ZetPc(-1) == 0x67e9) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xf7: // unneeded value : 3 * 'NOP' at 0x034f + 'JR NZ,$035D' at 0x35b + if (ZetPc(-1) == 0x0349) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xff: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x9670) + arkanoid_bootleg_cmd = data; + break; + default: + arkanoid_bootleg_cmd = 0x00; + break; + } + break; + + case PADDLE2: + switch (data) + { + case 0x24: // A read from 0xf002 (expected to be 0x9b) + if (ZetPc(-1) == 0xbd7a) + arkanoid_bootleg_cmd = data; + break; + case 0x36: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x7c4c) + arkanoid_bootleg_cmd = data; + break; + case 0x38: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x7b87) + arkanoid_bootleg_cmd = data; + break; + case 0x88: // unneeded value : no read back + if (ZetPc(-1) == 0x67e3) + arkanoid_bootleg_cmd = 0x00; + if (ZetPc(-1) == 0x7c47) + arkanoid_bootleg_cmd = 0x00; + case 0x89: // unneeded value : no read back + if (ZetPc(-1) == 0x67e5) + arkanoid_bootleg_cmd = 0x00; + break; + case 0x8a: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x9661) + arkanoid_bootleg_cmd = data; + break; + case 0xc0: // unneeded value : no read back + if (ZetPc(-1) == 0x67e7) + arkanoid_bootleg_cmd = 0x00; + break; + case 0xc3: // A read from 0xf002 (expected to be 0x1d) + if (ZetPc(-1) == 0xbd8a) + arkanoid_bootleg_cmd = data; + break; + case 0xe3: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x67e9) + arkanoid_bootleg_cmd = data; + break; + case 0xf7: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x0349) + arkanoid_bootleg_cmd = data; + break; + case 0xff: // call 0x2050 with A read from 0xf002 and wrong HL + if (ZetPc(-1) == 0x9670) + arkanoid_bootleg_cmd = data; + break; + default: + arkanoid_bootleg_cmd = 0x00; + break; + } + break; + + default: + break; + } +} + +static UINT8 arkanoid_bootleg_d008_read() +{ + switch (arkanoid_bootleg_id) + { + case ARKANGC: + case ARKBLOCK: + return 0x00; + + case ARKANGC2: + return 0x02; + + case ARKBLOC2: + return (DrvInputs[2] < 0x40) << 5; + + case ARKGCBL: + return ((DrvInputs[2] < 0x40) << 5) | 0x02; + + case PADDLE2: + return ((DrvInputs[2] < 0x40) << 5) | 0x0f; + + default: + return 0x00; + } + + return 0; +} + +UINT8 __fastcall arkanoid_read(UINT16 address) +{ + switch (address) + { + case 0xd001: + return AY8910Read(0); + + case 0xd008: + return arkanoid_bootleg_d008_read(); + + case 0xd00c: + { + INT32 ret = DrvInputs[0]; + if (use_mcu) { + ret &= 0x3f; + + if (!main_sent) ret |= 0x40; + if (!mcu_sent ) ret |= 0x80; + } + return ret; + } + + case 0xd010: + return DrvInputs[1]; + + case 0xd018: + if (use_mcu) { + return standard_taito_mcu_read(); + } else { + return DrvInputs[2]; + } + + case 0xf002: + return arkanoid_bootleg_f002_read(); + } + + if (address >= 0xf000) return DrvZ80ROM[address]; + + return 0; +} + +void __fastcall arkanoid_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xd000: + case 0xd001: + AY8910Write(0, address & 1, data); + break; + + case 0xd008: + { + *flipscreen = (data >> 0) & 3; + *gfxbank = (data >> 5) & 1; + *palettebank = (data >> 6) & 1; + *paddleselect= (data >> 2) & 1; + } + break; + + case 0xd010: // watchdog + break; + + case 0xd018: + if (use_mcu) { + from_main = data; + main_sent = 1; + } else { + arkanoid_bootleg_d018_write(data); + } + break; + } +} + +static void bankswitch(INT32 data) +{ + bankselect[0] = data; + + INT32 bank = 0x8000 + ((data & 0x10) >> 4) * 0x4000; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + bank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + bank); +} + +void __fastcall hexa_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xd000: + case 0xd001: + AY8910Write(0, address & 1, data); + return; + + case 0xd008: + *flipscreen = data & 0x03; // flipx & flipy + *gfxbank =(data & 0x20) >> 5; + bankswitch(data); + return; + } +} + +static void arkanoid_m68705_portC_write(UINT8 *data) +{ + if ((ddrC & 0x04) && (~*data & 0x04) && (portC_out & 0x04)) + { + main_sent = 0; + portA_in = from_main; + } + if ((ddrC & 0x08) && (~*data & 0x08) && (portC_out & 0x08)) + { + mcu_sent = 1; + from_mcu = portA_out; + } + + portC_out = *data; +} + +static void arkanoid_m68705_portB_read() +{ + ddrB = 0xff; + portB_out = (*paddleselect) ? DrvInputs[3] : DrvInputs[2]; +} + +static m68705_interface arkanoid_m68705_interface = { + NULL, + NULL, + arkanoid_m68705_portC_write, + NULL, + NULL, + NULL, + NULL, + arkanoid_m68705_portB_read, + standard_m68705_portC_in +}; + +static UINT8 ay8910_read_port_4(UINT32) +{ + INT32 ret = DrvDips[0]; + if (arkanoid_bootleg_id == TETRSARK) ret |= DrvInputs[1]; + + return ret; +} + +static UINT8 ay8910_read_port_5(UINT32) +{ + return DrvInputs[0]; +} + +static void DrvPaletteInit() +{ + INT32 len = BurnDrvGetPaletteEntries(); + + for (INT32 i = 0; i < len; i++) + { + INT32 bit0,bit1,bit2,bit3,r,g,b; + + bit0 = (DrvColPROM[i + len * 0] >> 0) & 0x01; + bit1 = (DrvColPROM[i + len * 0] >> 1) & 0x01; + bit2 = (DrvColPROM[i + len * 0] >> 2) & 0x01; + bit3 = (DrvColPROM[i + len * 0] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + len * 1] >> 0) & 0x01; + bit1 = (DrvColPROM[i + len * 1] >> 1) & 0x01; + bit2 = (DrvColPROM[i + len * 1] >> 2) & 0x01; + bit3 = (DrvColPROM[i + len * 1] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + len * 2] >> 0) & 0x01; + bit1 = (DrvColPROM[i + len * 2] >> 1) & 0x01; + bit2 = (DrvColPROM[i + len * 2] >> 2) & 0x01; + bit3 = (DrvColPROM[i + len * 2] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + for (INT32 i = 0; i < 0x40000; i++) { + tmp[i] = ((DrvGfxROM[(i / 8) + 0x00000] >> (i & 7)) & 1) << 0; + tmp[i] |= ((DrvGfxROM[(i / 8) + 0x08000] >> (i & 7)) & 1) << 1; + tmp[i] |= ((DrvGfxROM[(i / 8) + 0x10000] >> (i & 7)) & 1) << 2; + } + + memcpy (DrvGfxROM, tmp, 0x40000); + BurnFree (tmp); +} + +static INT32 GetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *RomLoad = DrvZ80ROM; + UINT8 *GfxLoad = DrvGfxROM; + UINT8 *PrmLoad = DrvColPROM; + use_mcu = 0; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(RomLoad, i, 1)) return 1; + RomLoad += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(DrvMcuROM, i, 1)) return 1; + use_mcu = 1; + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(GfxLoad, i, 1)) return 1; + GfxLoad += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(PrmLoad, i, 1)) return 1; + PrmLoad += ri.nLen; + continue; + } + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + m67805_taito_reset(); + + AY8910Reset(0); + + nAnalogAxis[0] = 0; + nAnalogAxis[1] = 0; + arkanoid_bootleg_cmd = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x010000; + DrvMcuROM = Next; Next += 0x000800; + + DrvGfxROM = Next; Next += 0x040000; + + DrvColPROM = Next; Next += 0x000800; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + DrvMcuRAM = Next; Next += 0x000080; + DrvVidRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + + flipscreen = Next; Next += 0x000001; + gfxbank = Next; Next += 0x000001; + palettebank = Next; Next += 0x000001; + paddleselect = Next; Next += 0x000001; + bankselect = Next; Next += 0x000001; + + RamEnd = Next; + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (GetRoms()) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetMapArea(0xe000, 0xe7ff, 0, DrvVidRAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvVidRAM); + ZetMapArea(0xe000, 0xe7ff, 2, DrvVidRAM); + ZetMapArea(0xe800, 0xefff, 0, DrvSprRAM); + ZetMapArea(0xe800, 0xefff, 1, DrvSprRAM); + ZetMapArea(0xe800, 0xefff, 2, DrvSprRAM); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80ROM + 0xf000); + if (arkanoid_bootleg_id == HEXA) { + ZetSetWriteHandler(hexa_write); + } else { + ZetSetWriteHandler(arkanoid_write); + } + ZetSetReadHandler(arkanoid_read); + ZetMemEnd(); + ZetClose(); + + m67805_taito_init(DrvMcuROM, DrvMcuRAM, &arkanoid_m68705_interface); + + AY8910Init(0, 1500000, nBurnSoundRate, &ay8910_read_port_5, &ay8910_read_port_4, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + m67805_taito_exit(); + + AY8910Exit(0); + + BurnFree (AllMem); + + arkanoid_bootleg_id = 0; + + return 0; +} + +static void draw_background_layer() +{ + for (INT32 offs = 0; offs < 32 * 30; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + if (*flipscreen) { + sx ^= 0xf8; + sy ^= 0xf8; + } + + sy -= 16; + + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 attr = DrvVidRAM[offs * 2 + 0]; + INT32 code = DrvVidRAM[offs * 2 + 1] | ((attr & 0x07) << 8) | (*gfxbank << 11); + INT32 color = ((attr & 0xf8) >> 3) | (*palettebank << 5); + + if (*flipscreen) { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM); + } else { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0x40; offs+=4) + { + INT32 sx = DrvSprRAM[offs + 0]; + INT32 sy = 248 - DrvSprRAM[offs + 1]; + INT32 attr = DrvSprRAM[offs + 2]; + INT32 code = DrvSprRAM[offs + 3] | ((attr & 0x03) << 8) | (*gfxbank << 10); + INT32 color = ((attr & 0xf8) >> 3) | (*palettebank << 5); + + if (*flipscreen) { + sx = 248 - sx; + sy = 248 - sy; + + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code * 2 + 0, sx, sy - 8, color, 3, 0, 0, DrvGfxROM); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code * 2 + 1, sx, sy - 16, color, 3, 0, 0, DrvGfxROM); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code * 2 + 0, sx, sy - 24, color, 3, 0, 0, DrvGfxROM); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code * 2 + 1, sx, sy - 16, color, 3, 0, 0, DrvGfxROM); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_background_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2); + + if (arkanoid_bootleg_id != HEXA) DrvInputs[0] = 0x4f; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + nAnalogAxis[0] -= DrvAxis[0]; + DrvInputs[2] = (~nAnalogAxis[0] >> 8) & 0xfe; + + nAnalogAxis[1] -= DrvAxis[1]; + DrvInputs[3] = (~nAnalogAxis[1] >> 8) & 0xfe; + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { 6000000 / 60, 3000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + ZetOpen(0); + m6805Open(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += ZetRun(nSegment); + + if (use_mcu) { + nSegment = nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += m6805Run(nSegment); + } + } + + ZetRaiseIrq(0); + + m6805Close(); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + if (use_mcu) { + m68705_taito_scan(nAction); + } + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(nAnalogAxis[0]); + SCAN_VAR(nAnalogAxis[1]); + SCAN_VAR(arkanoid_bootleg_cmd); + } + + return 0; +} + +static INT32 HexaScan(INT32 nAction, INT32 *pnMin) +{ + DrvScan(nAction, pnMin); + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(*bankselect); + ZetClose(); + } + + return 0; +} + + +// Arkanoid (World) + +static struct BurnRomInfo arkanoidRomDesc[] = { + { "a75-01-1.ic17",0x8000, 0x5bcda3b0, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a75-11.ic16", 0x8000, 0xeafd7191, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-06.ic14", 0x0800, 0x515d77b6, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-03.ic64", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a75-04.ic63", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a75-05.ic62", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.ic24", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.ic23", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.ic22", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 + + { "arkanoid1_68705p3.ic14", 0x0800, 0x1b68e2d8, 0 | BRF_PRG | BRF_OPT }, // 9 Decapped roms + { "arkanoid_mcu.ic14", 0x0800, 0x4e44b50a, 0 | BRF_PRG | BRF_OPT }, // 10 + { "arkanoid_68705p5.ic14", 0x0800, 0x0be83647, 0 | BRF_PRG | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(arkanoid) +STD_ROM_FN(arkanoid) + +struct BurnDriver BurnDrvarkanoid = { + "arkanoid", NULL, NULL, NULL, "1986", + "Arkanoid (World)\0", NULL, "Taito Corporation Japan", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkanoidRomInfo, arkanoidRomName, NULL, NULL, DrvInputInfo, arkanoidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (US) + +static struct BurnRomInfo arknoiduRomDesc[] = { + { "a75-19.ic17", 0x8000, 0xd3ad37d7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a75-18.ic16", 0x8000, 0xcdc08301, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-20.ic14", 0x0800, 0xde518e47, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-03.ic64", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a75-04.ic63", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a75-05.ic62", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.ic24", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.ic23", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.ic22", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknoidu) +STD_ROM_FN(arknoidu) + +struct BurnDriver BurnDrvarknoidu = { + "arkanoidu", "arkanoid", NULL, NULL, "1986", + "Arkanoid (US)\0", NULL, "Taito America Corporation (Romstar license)", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arknoiduRomInfo, arknoiduRomName, NULL, NULL, DrvInputInfo, arkanoidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (US, older) + +static struct BurnRomInfo arknoiuoRomDesc[] = { + { "a75-01-1.ic17",0x8000, 0x5bcda3b0, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a75-10.ic16", 0x8000, 0xa1769e15, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-06.ic14", 0x0800, 0x515d77b6, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-03.ic64", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a75-04.ic63", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a75-05.ic62", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.ic24", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.ic23", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.ic23", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknoiuo) +STD_ROM_FN(arknoiuo) + +struct BurnDriver BurnDrvarknoiuo = { + "arkanoiduo", "arkanoid", NULL, NULL, "1986", + "Arkanoid (US, older)\0", NULL, "Taito America Corporation (Romstar license)", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arknoiuoRomInfo, arknoiuoRomName, NULL, NULL, DrvInputInfo, arkanoidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Tournament Arkanoid (US) + +static struct BurnRomInfo arkatourRomDesc[] = { + { "a75-27.ic17", 0x8000, 0xe3b8faf5, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a75-28.ic16", 0x8000, 0x326aca4d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-32.ic14", 0x0800, 0xd3249559, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-29.ic64", 0x8000, 0x5ddea3cf, 3 | BRF_GRA }, // 3 Graphics + { "a75-30.ic63", 0x8000, 0x5fcf2e85, 3 | BRF_GRA }, // 4 + { "a75-31.ic62", 0x8000, 0x7b76b192, 3 | BRF_GRA }, // 5 + + { "a75-33.ic24", 0x0200, 0xb4bf3c81, 4 | BRF_GRA }, // 6 Color Proms + { "a75-34.ic23", 0x0200, 0xde85a803, 4 | BRF_GRA }, // 7 + { "a75-35.ic22", 0x0200, 0x38acfd3b, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arkatour) +STD_ROM_FN(arkatour) + +struct BurnDriver BurnDrvarkatour = { + "arkatour", "arkanoid", NULL, NULL, "1987", + "Tournament Arkanoid (US)\0", NULL, "Taito America Corporation (Romstar license)", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkatourRomInfo, arkatourRomName, NULL, NULL, DrvInputInfo, arkanoidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (Japan) + +static struct BurnRomInfo arknoidjRomDesc[] = { + { "a75-21.ic17", 0x8000, 0xbf0455fc, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "a75-22.ic16", 0x8000, 0x3a2688d3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-23.ic14", 0x0800, 0x0a4abef6, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-03.ic64", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a75-04.ic63", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a75-05.ic62", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.ic24", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.ic23", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.ic22", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknoidj) +STD_ROM_FN(arknoidj) + +struct BurnDriver BurnDrvarknoidj = { + "arkanoidj", "arkanoid", NULL, NULL, "1986", + "Arkanoid (Japan)\0", NULL, "Taito Corporation", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arknoidjRomInfo, arknoidjRomName, NULL, NULL, DrvInputInfo, arknoidjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (bootleg with MCU) + +static struct BurnRomInfo arkmcublRomDesc[] = { + { "e1.6d", 0x8000, 0xdd4f2b72, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "e2.6f", 0x8000, 0xbbc33ceb, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-06.ic14", 0x0800, 0x515d77b6, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 + + { "68705p3.6i", 0x0800, 0x389a8cfb, 0 | BRF_OPT | BRF_PRG }, // 9 Another MCU? +}; + +STD_ROM_PICK(arkmcubl) +STD_ROM_FN(arkmcubl) + +struct BurnDriver BurnDrvarkmcubl = { + "arkanoidjb", "arkanoid", NULL, NULL, "1986", + "Arkanoid (bootleg with MCU)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkmcublRomInfo, arkmcublRomName, NULL, NULL, DrvInputInfo, arknoidjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (bootleg with MCU, harder) + +static struct BurnRomInfo ark1ballRomDesc[] = { + { "a-1.7d", 0x8000, 0xdd4f2b72, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2palline.7f", 0x8000, 0xed6b62ab, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-06.ic14", 0x0800, 0x515d77b6, 2 | BRF_ESS | BRF_PRG }, // 2 M68705 MCU + + { "a-3.3a", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 3 Graphics + { "a-4.3d", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 4 + { "a-5.3f", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 5 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 6 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 7 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(ark1ball) +STD_ROM_FN(ark1ball) + +struct BurnDriver BurnDrvark1ball = { + "ark1ball", "arkanoid", NULL, NULL, "1986", + "Arkanoid (bootleg with MCU, harder)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, ark1ballRomInfo, ark1ballRomName, NULL, NULL, DrvInputInfo, ark1ballDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (Game Corporation bootleg, set 1) + +static struct BurnRomInfo arkangcRomDesc[] = { + { "arkgc.1", 0x8000, 0xc54232e6, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "arkgc.2", 0x8000, 0x9f0d4754, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arkangc) +STD_ROM_FN(arkangc) + +static INT32 arkangcInit() +{ + arkanoid_bootleg_id = ARKANGC; + + return DrvInit(); +} + +struct BurnDriver BurnDrvarkangc = { + "arkangc", "arkanoid", NULL, NULL, "1986", + "Arkanoid (Game Corporation bootleg, set 1)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkangcRomInfo, arkangcRomName, NULL, NULL, DrvInputInfo, arkangcDIPInfo, + arkangcInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (Game Corporation bootleg, set 2) + +static struct BurnRomInfo arkangc2RomDesc[] = { + { "1.81", 0x8000, 0xbd6eb996, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2.82", 0x8000, 0x29dbe452, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arkangc2) +STD_ROM_FN(arkangc2) + +static INT32 arkangc2Init() +{ + arkanoid_bootleg_id = ARKANGC2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvarkangc2 = { + "arkangc2", "arkanoid", NULL, NULL, "1986", + "Arkanoid (Game Corporation bootleg, set 2)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkangc2RomInfo, arkangc2RomName, NULL, NULL, DrvInputInfo, arkangc2DIPInfo, + arkangc2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Block (Game Corporation bootleg, set 1) + +static struct BurnRomInfo arkblockRomDesc[] = { + { "ark-6.bin", 0x8000, 0x0be015de, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "arkgc.2", 0x8000, 0x9f0d4754, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arkblock) +STD_ROM_FN(arkblock) + +static INT32 arkblockInit() +{ + arkanoid_bootleg_id = ARKBLOCK; + + return DrvInit(); +} + +struct BurnDriver BurnDrvarkblock = { + "arkblock", "arkanoid", NULL, NULL, "1986", + "Block (Game Corporation bootleg, set 1)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkblockRomInfo, arkblockRomName, NULL, NULL, DrvInputInfo, arkangcDIPInfo, + arkblockInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Block (Game Corporation bootleg, set 2) + +static struct BurnRomInfo arkbloc2RomDesc[] = { + { "block01.bin", 0x8000, 0x5be667e1, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "block02.bin", 0x8000, 0x4f883ef1, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arkbloc2) +STD_ROM_FN(arkbloc2) + +static INT32 arkbloc2Init() +{ + arkanoid_bootleg_id = ARKBLOC2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvarkbloc2 = { + "arkbloc2", "arkanoid", NULL, NULL, "1986", + "Block (Game Corporation bootleg, set 2)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkbloc2RomInfo, arkbloc2RomName, NULL, NULL, DrvInputInfo, arkangcDIPInfo, + arkbloc2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (bootleg on Block hardware) + +static struct BurnRomInfo arkgcblRomDesc[] = { + { "16.6e", 0x8000, 0xb0f73900, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "17.6f", 0x8000, 0x9827f297, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "82s129.5k", 0x0100, 0xfa70b64d, 4 | BRF_GRA }, // 5 Color Proms + { "82s129.5jk", 0x0100, 0xcca69884, 4 | BRF_GRA }, // 6 + { "82s129.5l", 0x0100, 0x3e4d2bf5, 4 | BRF_GRA }, // 7 + { "82s129.5kl", 0x0100, 0x085d625a, 4 | BRF_GRA }, // 8 + { "82s129.5mn", 0x0100, 0x0fe0b108, 4 | BRF_GRA }, // 9 + { "63s141.5m", 0x0100, 0x5553f675, 4 | BRF_GRA }, // 10 + + { "pal16r8.5f", 0x0104, 0x36471917, 0 | BRF_OPT | BRF_GRA }, // 11 PAL +}; + +STD_ROM_PICK(arkgcbl) +STD_ROM_FN(arkgcbl) + +static INT32 arkgcblInit() +{ + arkanoid_bootleg_id = ARKGCBL; + + return DrvInit(); +} + +struct BurnDriver BurnDrvarkgcbl = { + "arkgcbl", "arkanoid", NULL, NULL, "1986", + "Arkanoid (bootleg on Block hardware)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkgcblRomInfo, arkgcblRomName, NULL, NULL, DrvInputInfo, arkgcblDIPInfo, + arkgcblInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Paddle 2 (bootleg on Block hardware) + +static struct BurnRomInfo paddle2RomDesc[] = { + { "paddle2.16", 0x8000, 0xa286333c, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "paddle2.17", 0x8000, 0x04c2acb5, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "a75-03.rom", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "a75-04.rom", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "a75-05.rom", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(paddle2) +STD_ROM_FN(paddle2) + +static INT32 paddle2Init() +{ + arkanoid_bootleg_id = PADDLE2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvpaddle2 = { + "paddle2", "arkanoid", NULL, NULL, "1986", + "Paddle 2 (bootleg on Block hardware)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, paddle2RomInfo, paddle2RomName, NULL, NULL, DrvInputInfo, paddle2DIPInfo, + paddle2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (Tayto bootleg) + +static struct BurnRomInfo arkataytRomDesc[] = { + { "ic81-v.3f", 0x8000, 0x154e2c6f, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic82-w.5f", 0x8000, 0x4fa8cefa, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "1-ic33.2c", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "2-ic34.3c", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "3-ic35.5c", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "ic73.11e", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "ic74.12e", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "ic75.13e", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arkatayt) +STD_ROM_FN(arkatayt) + +struct BurnDriver BurnDrvarkatayt = { + "arkatayt", "arkanoid", NULL, NULL, "1986", + "Arkanoid (Tayto bootleg)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arkataytRomInfo, arkataytRomName, NULL, NULL, DrvInputInfo, arknoidjDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid (Tayto bootleg, harder) + +static struct BurnRomInfo arktayt2RomDesc[] = { + { "ic81.3f", 0x8000, 0x6e0a2b6f, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic82.5f", 0x8000, 0x5a97dd56, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "1-ic33.2c", 0x8000, 0x038b74ba, 3 | BRF_GRA }, // 2 Graphics + { "2-ic34.3c", 0x8000, 0x71fae199, 3 | BRF_GRA }, // 3 + { "3-ic35.5c", 0x8000, 0xc76374e2, 3 | BRF_GRA }, // 4 + + { "ic73.11e", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "ic74.12e", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "ic75.13e", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(arktayt2) +STD_ROM_FN(arktayt2) + +struct BurnDriver BurnDrvarktayt2 = { + "arktayt2", "arkanoid", NULL, NULL, "1986", + "Arkanoid (Tayto bootleg, harder)\0", NULL, "bootleg", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, arktayt2RomInfo, arktayt2RomName, NULL, NULL, DrvInputInfo, arktayt2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Tetris (D.R. Korea) + +static struct BurnRomInfo tetrsarkRomDesc[] = { + { "ic17.1", 0x8000, 0x1a505eda, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic16.2", 0x8000, 0x157bc4df, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "ic64.3", 0x8000, 0xc3e9b290, 3 | BRF_GRA }, // 2 Graphics + { "ic63.4", 0x8000, 0xde9a368f, 3 | BRF_GRA }, // 3 + { "ic62.5", 0x8000, 0xc8e80a00, 3 | BRF_GRA }, // 4 + + { "a75-07.bpr", 0x0200, 0x0af8b289, 4 | BRF_GRA }, // 5 Color Proms + { "a75-08.bpr", 0x0200, 0xabb002fb, 4 | BRF_GRA }, // 6 + { "a75-09.bpr", 0x0200, 0xa7c6c277, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(tetrsark) +STD_ROM_FN(tetrsark) + +static INT32 tetrsarkInit() +{ + arkanoid_bootleg_id = TETRSARK; + + INT32 nRet = DrvInit(); + + if (nRet == 0) { + for (INT32 i = 0; i < 0x8000; i++) { + DrvZ80ROM[i] ^= 0x94; + } + } + + return nRet; +} + +struct BurnDriver BurnDrvtetrsark = { + "tetrsark", NULL, NULL, NULL, "198?", + "Tetris (D.R. Korea)\0", "Wrong colors", "D.R. Korea", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, tetrsarkRomInfo, tetrsarkRomName, NULL, NULL, tetrsarkInputInfo, tetrsarkDIPInfo, + tetrsarkInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Hexa + +static struct BurnRomInfo hexaRomDesc[] = { + { "hexa.20", 0x8000, 0x98b00586, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "hexa.21", 0x8000, 0x3d5d006c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "hexa.17", 0x8000, 0xf6911dd6, 3 | BRF_GRA }, // 2 Graphics + { "hexa.18", 0x8000, 0x6e3d95d2, 3 | BRF_GRA }, // 3 + { "hexa.19", 0x8000, 0xffe97a31, 3 | BRF_GRA }, // 4 + + { "hexa.001", 0x0100, 0x88a055b4, 4 | BRF_GRA }, // 5 Color Proms + { "hexa.003", 0x0100, 0x3e9d4932, 4 | BRF_GRA }, // 6 + { "hexa.002", 0x0100, 0xff15366c, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(hexa) +STD_ROM_FN(hexa) + +static INT32 HexaInit() +{ + arkanoid_bootleg_id = HEXA; + + return DrvInit(); +} + +struct BurnDriver BurnDrvHexa = { + "hexa", NULL, NULL, NULL, "199?", + "Hexa\0", NULL, "D. R. Korea", "Arkanoid", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, hexaRomInfo, hexaRomName, NULL, NULL, HexaInputInfo, HexaDIPInfo, + HexaInit, DrvExit, DrvFrame, DrvDraw, HexaScan, &DrvRecalc, 0x100, + 256, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_armedf.cpp b/src/burn/drivers/misc_pre90s/d_armedf.cpp new file mode 100644 index 00000000..8d539a54 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_armedf.cpp @@ -0,0 +1,1904 @@ +// FB Alpha Armed Formation driver module +// Based on MAME driver by Carlos A. Lozano, Phil Stroffolino, and Takahiro Nogi + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "dac.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *Drv68KRAM2; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvZ80RAM2; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvBgRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvTxRAM; +static UINT32 *DrvPalette; + +static UINT16*DrvMcuCmd; +static UINT16*DrvScroll; +static UINT8 *DrvVidRegs; +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT16 DrvInputs[4]; +static UINT8 DrvReset; + +static INT32 scroll_type; +static INT32 sprite_offy; +static INT32 yoffset; +static INT32 xoffset; +static INT32 irqline; + +static INT16 *DACBuffer; +static INT32 Terrafjb = 0; + +static struct BurnInputInfo ArmedfInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 10, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 11, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 8, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy2 + 10, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Armedf) + +static struct BurnInputInfo Cclimbr2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 10, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 8, "p1 start" }, + {"P1 Up 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down 1", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left 1", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Up 2", BIT_DIGITAL, DrvJoy1 + 4, "p3 up" }, + {"P1 Down 2", BIT_DIGITAL, DrvJoy1 + 5, "p3 down" }, + {"P1 Left 2", BIT_DIGITAL, DrvJoy1 + 6, "p3 left" }, + {"P1 Right 2", BIT_DIGITAL, DrvJoy1 + 7, "p3 right" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 11, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 9, "p2 start" }, + {"P2 Up 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down 1", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left 1", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right 1", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Up 2", BIT_DIGITAL, DrvJoy2 + 4, "p4 up" }, + {"P2 Down 2", BIT_DIGITAL, DrvJoy2 + 5, "p4 down" }, + {"P2 Left 2", BIT_DIGITAL, DrvJoy2 + 6, "p4 left" }, + {"P2 Right 2", BIT_DIGITAL, DrvJoy2 + 7, "p4 right" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 8, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy2 + 10, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Cclimbr2) + +static struct BurnDIPInfo ArmedfDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xdf, NULL }, + {0x16, 0xff, 0xff, 0xcf, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "1st Bonus Life" }, + {0x15, 0x01, 0x04, 0x04, "20k" }, + {0x15, 0x01, 0x04, 0x00, "40k" }, + + {0 , 0xfe, 0 , 2, "2nd Bonus Life" }, + {0x15, 0x01, 0x08, 0x08, "60k" }, + {0x15, 0x01, 0x08, 0x00, "80k" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "20k then every 60k" }, + {0x15, 0x01, 0x0c, 0x04, "20k then every 80k" }, + {0x15, 0x01, 0x0c, 0x08, "40k then every 60k" }, + {0x15, 0x01, 0x0c, 0x00, "40k then every 80k" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x10, 0x00, "Off" }, + {0x15, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x15, 0x01, 0x20, 0x00, "Upright" }, + {0x15, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0xc0, 0xc0, "Easy" }, + {0x15, 0x01, 0xc0, 0x80, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x16, 0x01, 0x0c, 0x04, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x16, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x16, 0x01, 0x30, 0x30, "No" }, + {0x16, 0x01, 0x30, 0x20, "3 Times" }, + {0x16, 0x01, 0x30, 0x10, "5 Times" }, + {0x16, 0x01, 0x30, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Armedf) + +static struct BurnDIPInfo KozureDIPList[]= +{ + {0x15, 0xff, 0xff, 0xcf, NULL }, + {0x16, 0xff, 0xff, 0xcf, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "1st Bonus Life" }, + {0x15, 0x01, 0x04, 0x04, "None" }, + {0x15, 0x01, 0x04, 0x00, "50k" }, + + {0 , 0xfe, 0 , 2, "2nd Bonus Life" }, + {0x15, 0x01, 0x08, 0x08, "60k" }, + {0x15, 0x01, 0x08, 0x00, "90k" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x08, "50k then every 60k" }, + {0x15, 0x01, 0x0c, 0x00, "50k then every 90k" }, + {0x15, 0x01, 0x0c, 0x0c, "Every 60k" }, + {0x15, 0x01, 0x0c, 0x04, "Every 90k" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x15, 0x01, 0x40, 0x40, "Easy" }, + {0x15, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 0, "Coin A" }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x16, 0x01, 0x0c, 0x00, "3 Coins 1 Credits" }, + {0x16, 0x01, 0x0c, 0x04, "2 Coins 3 Credits" }, + {0x16, 0x01, 0x0c, 0x0c, "1 Coin 3 Credits" }, + {0x16, 0x01, 0x0c, 0x08, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x16, 0x01, 0x30, 0x30, "No" }, + {0x16, 0x01, 0x30, 0x20, "3 Times" }, + {0x16, 0x01, 0x30, 0x10, "5 Times" }, + {0x16, 0x01, 0x30, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "No" }, + {0x16, 0x01, 0x40, 0x40, "Yes" }, +}; + +STDDIPINFO(Kozure) + +static struct BurnDIPInfo Cclimbr2DIPList[]= +{ + {0x17, 0xff, 0xff, 0xcf, NULL }, + {0x18, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x17, 0x01, 0x03, 0x03, "3" }, + {0x17, 0x01, 0x03, 0x02, "4" }, + {0x17, 0x01, 0x03, 0x01, "5" }, + {0x17, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "1st Bonus Life" }, + {0x17, 0x01, 0x04, 0x04, "30k" }, + {0x17, 0x01, 0x04, 0x00, "60k" }, + + {0 , 0xfe, 0 , 2, "2nd Bonus Life" }, + {0x17, 0x01, 0x08, 0x08, "70k" }, + {0x17, 0x01, 0x08, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x17, 0x01, 0x0c, 0x0c, "30K and 100k" }, + {0x17, 0x01, 0x0c, 0x08, "60k and 130k" }, + {0x17, 0x01, 0x0c, 0x04, "30k only" }, + {0x17, 0x01, 0x0c, 0x00, "60k only" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x17, 0x01, 0x40, 0x40, "Easy" }, + {0x17, 0x01, 0x40, 0x00, "Normal" }, + + {0 , 0xfe, 0 , 0, "Coin A" }, + {0x18, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x18, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x18, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x18, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x18, 0x01, 0x0c, 0x04, "2 Coins 1 Credits" }, + {0x18, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x18, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x18, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x18, 0x01, 0x10, 0x00, "No" }, + {0x18, 0x01, 0x10, 0x10, "3 Times" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x18, 0x01, 0x20, 0x20, "Off" }, + {0x18, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Partial Invulnerability (Cheat)" }, + {0x18, 0x01, 0x40, 0x40, "Off" }, + {0x18, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Cclimbr2) + +static struct BurnDIPInfo LegionDIPList[]= +{ + {0x15, 0xff, 0xff, 0xf7, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x15, 0x01, 0x04, 0x04, "30k Then Every 100k" }, + {0x15, 0x01, 0x04, 0x00, "50k Only" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x10, 0x10, "Off" }, + {0x15, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Allow Invulnerability (Cheat)" }, + {0x15, 0x01, 0x80, 0x80, "No" }, + {0x15, 0x01, 0x80, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 0, "Coin A" }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Coin B" }, + {0x16, 0x01, 0x0c, 0x04, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x16, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin Slots" }, + {0x16, 0x01, 0x10, 0x10, "Common" }, + {0x16, 0x01, 0x10, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x20, 0x20, "Easy" }, + {0x16, 0x01, 0x20, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "P1 Invulnerability (Cheat)" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "P2 Invulnerability (Cheat)" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Legion) + +static struct BurnDIPInfo TerrafDIPList[]= +{ + {0x15, 0xff, 0xff, 0x0f, NULL }, + {0x16, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + {0x15, 0x01, 0x03, 0x01, "5" }, + {0x15, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "1st Bonus Life" }, + {0x15, 0x01, 0x04, 0x04, "20k" }, + {0x15, 0x01, 0x04, 0x00, "50k" }, + + {0 , 0xfe, 0 , 2, "2nd Bonus Life" }, + {0x15, 0x01, 0x08, 0x08, "60k" }, + {0x15, 0x01, 0x08, 0x00, "90k" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "20k then every 60k" }, + {0x15, 0x01, 0x0c, 0x04, "20k then every 90k" }, + {0x15, 0x01, 0x0c, 0x08, "50k then every 60k" }, + {0x15, 0x01, 0x0c, 0x00, "50k then every 90k" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x10, 0x10, "Off" }, + {0x15, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x16, 0x01, 0x0c, 0x04, "2 Coins 1 Credits" }, + {0x16, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x16, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x16, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0xc0, 0xc0, "No" }, + {0x16, 0x01, 0xc0, 0x80, "Only 3 Times" }, + {0x16, 0x01, 0xc0, 0x40, "Only 5 Times" }, + {0x16, 0x01, 0xc0, 0x00, "Yes" }, +}; + +STDDIPINFO(Terraf) + +void __fastcall armedf_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x06d000: + *DrvVidRegs = data >> 8; + *flipscreen = (data >> 12) & 1; + return; + + case 0x06d002: + DrvScroll[0] = data & 0x3ff; + return; + + case 0x06d004: + DrvScroll[1] = data & 0x1ff; + return; + + case 0x06d006: + DrvScroll[2] = data & 0x3ff; + return; + + case 0x06d008: + DrvScroll[3] = data & 0x1ff; + return; + + case 0x06d00a: + *soundlatch = ((data & 0x7f) << 1) | 1; + return; + } +} + +void __fastcall cclimbr2_write_word(UINT32 address, UINT16 data) +{ + if (scroll_type == 6 && (address & 0xffffc0) == 0x040000) { + DrvMcuCmd[(address >> 1) & 0x1f] = data; + return; + } + + switch (address) + { + case 0x7c000: + { +/* if (Terrafjb) { + // We should be using the extra Z80 - but it doesn't seem to work - the normal simulation does though + static UINT32 OldData = 0; + if ((data & 0x4000) && (OldData & 0x4000) == 0) { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + ZetOpen(0); + } + OldData = data; + } else {*/ + if (scroll_type == 2) { + if (~data & 0x0080) { + memset (DrvTxRAM, 0xff, 0x2000); + } + } + + if (scroll_type == 0 || scroll_type == 3 || scroll_type == 5 || scroll_type == 6) { // scroll6 - hack + if (((data & 0x4100) == 0x4000 && scroll_type != 6) || + ((data & 0x4100) == 0x0000 && scroll_type == 6)) { + UINT16 *ram = (UINT16*)DrvTxRAM; + for (INT32 i = 0x10; i < 0x1000; i++) { + ram[i] = 0x0020; + } + } + } +// } + + *DrvVidRegs = data >> 8; + *flipscreen = (data >> 12) & 1; + } + return; + + case 0x7c002: + DrvScroll[0] = data & 0x3ff; + return; + + case 0x7c004: + DrvScroll[1] = data & 0x1ff; + return; + + case 0x7c00a: + *soundlatch = ((data & 0x7f) << 1) | 1; + return; + + case 0x7c00e: + if (scroll_type == 0 || scroll_type == 3 || scroll_type == 5) { + *DrvMcuCmd = data; + } + return; + } +} + +void __fastcall cclimbr2_write_byte(UINT32 address, UINT8 data) +{ + if (scroll_type != 0) return; + + switch (address) + { + case 0x7c006: + DrvMcuCmd[11] = data; + DrvMcuCmd[31] = 1; + return; + + case 0x7c008: + if (DrvMcuCmd[31]) { + DrvMcuCmd[14] = data >> 4; + DrvMcuCmd[12] = data; + } else { + DrvMcuCmd[13] = data; + } + return; + + case 0xc0000: + DrvMcuCmd[31] = 0; + return; + } +} + +UINT16 __fastcall cclimbr2_read_word(UINT32 address) +{ + switch (address) + { + case 0x78000: + return DrvInputs[0]; + + case 0x78002: + return DrvInputs[1]; + + case 0x78004: + return DrvInputs[2]; + + case 0x78006: + return DrvInputs[3]; + } + + return 0; +} + +void __fastcall armedf_write_port(UINT16 port, UINT8 data) +{ +// bprintf (PRINT_NORMAL, _T("%2.2x %2.2x\n"), port & 0xff, data); + + switch (port & 0xff) + { + case 0x00: + BurnYM3812Write(0, data); + return; + + case 0x01: + BurnYM3812Write(1, data); + return; + + case 0x02: + DACSignedWrite(0, data); + return; + + case 0x03: + DACSignedWrite(1, data); + return; + } +} + +UINT8 __fastcall armedf_read_port(UINT16 port) +{ +// bprintf (PRINT_NORMAL, _T("%2.2x read\n"), port & 0xff); + + switch (port & 0xff) + { + case 0x04: + *soundlatch = 0; + return 0; + + case 0x06: + return *soundlatch; + } + + return 0; +} + +void __fastcall terrafjbextra_write_port(UINT16 port, UINT8 data) +{ + // rendering code reads scroll values from RAM - we write the values to RAM here so that the rendering code still works +// UINT16 *RAM = (UINT16*)DrvTxRAM; + + switch (port & 0xff) { + case 0x00: { +// RAM[13] = data & 0xff; +// RAM[14] = data >> 8; + return; + } + + case 0x01: { +// RAM[11] = data & 0xff; +// RAM[12] = data >> 8; + return; + } + + case 0x02: { + /* + state->m_fg_scrolly = (((data & 0x03) >> 0) << 8) | (state->m_fg_scrolly & 0xff); + state->m_fg_scrollx = (((data & 0x0c) >> 2) << 8) | (state->m_fg_scrollx & 0xff);*/ +// RAM[12] = data;//(data & 0x03) >> 0; +// RAM[14] = data;//(data & 0x0c) >> 2; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Port write %x, %x\n"), port, data); + } + } +} + +UINT8 __fastcall terrafjbextra_read_port(UINT16 port) +{ + switch (port & 0xff) { + default: { + bprintf(PRINT_NORMAL, _T("Port read %x\n"), port); + } + } + + return 0; +} + +void __fastcall terrafjbextra_write(UINT16 address, UINT8 data) +{ + if (address >= 0x4000 && address <= 0x5fff) { + DrvTxRAM[(address ^ 1) - 0x4000] = data; + return; + } + + switch (address) { + default: { + bprintf(PRINT_NORMAL, _T("Write %x, %x\n"), address, data); + } + } +} + +UINT8 __fastcall terrafjbextra_read(UINT16 address) +{ + if (address >= 0x4000 && address <= 0x5fff) { + return DrvTxRAM[(address ^ 1) - 0x4000]; + } + + switch (address) { + default: { + bprintf(PRINT_NORMAL, _T("Read %x\n"), address); + } + } + + return 0; +} + + + + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + if (Terrafjb) { + ZetOpen(1); + ZetReset(); + ZetClose(); + } + + BurnYM3812Reset(); + DACReset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x010000; + Drv68KROM = Next; Next += 0x060000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROM3 = Next; Next += 0x080000; + + if (Terrafjb) { + DrvZ80ROM2 = Next; Next += 0x004000; + } + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + DACBuffer = (INT16*)Next; Next += nBurnSoundLen * 2 * sizeof(INT16); + + AllRam = Next; + + DrvSprRAM = Next; Next += 0x001000; + DrvSprBuf = Next; Next += 0x001000; + DrvBgRAM = Next; Next += 0x001000; + DrvFgRAM = Next; Next += 0x001000; + DrvTxRAM = Next; Next += 0x002000; + DrvPalRAM = Next; Next += 0x001000; + Drv68KRAM0 = Next; Next += 0x005000; + Drv68KRAM1 = Next; Next += 0x001000; + Drv68KRAM2 = Next; Next += 0x001000; + + flipscreen = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + DrvVidRegs = Next; Next += 0x000001; + DrvScroll = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + DrvMcuCmd = (UINT16*)Next; Next += 0x000020 * sizeof(UINT16); + + DrvZ80RAM = Next; Next += 0x004000; + + if (Terrafjb) { + DrvZ80RAM2 = Next; Next += 0x000800; + } + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs0[16] = { 0x004, 0x000, 0x00c, 0x008, 0x014, 0x010, 0x01c, 0x018, + 0x024, 0x020, 0x02c, 0x028, 0x034, 0x030, 0x03c, 0x038 }; + INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + INT32 XOffs1[16] = { 0x000004, 0x000000, 0x100004, 0x100000, 0x00000c, 0x000008, 0x10000c, 0x100008, + 0x000014, 0x000010, 0x100014, 0x100010, 0x00001c, 0x000018, 0x10001c, 0x100018 }; + INT32 YOffs1[16] = { 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 4, 8, 8, Plane, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane, XOffs0, YOffs1, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x20000); + + GfxDecode(0x0400, 4, 16, 16, Plane, XOffs0, YOffs1, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane, XOffs1, YOffs0, 0x200, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static void Armedf68KInit() +{ + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x060000, 0x060fff, SM_RAM); + SekMapMemory(Drv68KRAM0, 0x061000, 0x065fff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x066000, 0x066fff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x067000, 0x067fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x068000, 0x069fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x06a000, 0x06afff, SM_RAM); + SekMapMemory(Drv68KRAM1, 0x06b000, 0x06bfff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x06c000, 0x06c7ff, SM_RAM); + SekSetWriteWordHandler(0, armedf_write_word); +} + +static void Cclimbr268KInit() +{ + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0x060000, 0x060fff, SM_RAM); + SekMapMemory(Drv68KRAM0, 0x061000, 0x063fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x064000, 0x064fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x068000, 0x069fff, SM_RAM); + SekMapMemory(Drv68KRAM1, 0x06a000, 0x06a9ff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x06c000, 0x06c9ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x070000, 0x070fff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x074000, 0x074fff, SM_RAM); + SekSetWriteWordHandler(0, cclimbr2_write_word); + SekSetWriteByteHandler(0, cclimbr2_write_byte); + SekSetReadWordHandler(0, cclimbr2_read_word); +} + +static INT32 DrvInit(INT32 (*pLoadRoms)(), void (*p68KInit)(), INT32 zLen) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pLoadRoms) { + if (pLoadRoms()) return 1; + } + + DrvGfxDecode(); + + SekInit(0, 0x68000); + SekOpen(0); + + if (p68KInit) + { + p68KInit(); + } + + SekClose(); + + if (Terrafjb) { + ZetInit(2); + } else { + ZetInit(1); + } + ZetOpen(0); + ZetMapArea(0x0000, zLen-1, 0, DrvZ80ROM); + ZetMapArea(0x0000, zLen-1, 2, DrvZ80ROM); + ZetMapArea(zLen+0, 0xffff, 0, DrvZ80RAM); + ZetMapArea(zLen+0, 0xffff, 1, DrvZ80RAM); + ZetMapArea(zLen+0, 0xffff, 2, DrvZ80RAM); + ZetSetOutHandler(armedf_write_port); + ZetSetInHandler(armedf_read_port); + ZetMemEnd(); + ZetClose(); + + if (Terrafjb) { + ZetOpen(1); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM2); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM2); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(terrafjbextra_write); + ZetSetReadHandler(terrafjbextra_read); + ZetSetOutHandler(terrafjbextra_write_port); + ZetSetInHandler(terrafjbextra_read_port); + ZetMemEnd(); + ZetClose(); + } + + BurnYM3812Init(4000000, NULL, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + DACInit(0, 0, 0); + DACInit(1, 0, 0); + DACSetVolShift(0, 1); + DACSetVolShift(1, 1); + + GenericTilesInit(); + + if (nScreenWidth == 320) { + xoffset = 96; + yoffset = 8; + } else { + xoffset = 112; + yoffset = 16; + } + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + DACExit(); + BurnYM3812Exit(); + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + Terrafjb = 0; + + return 0; +} + +static inline void DrvPaletteRecalc() +{ + UINT8 r,g,b; + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x1000 / 2; i++) { + INT32 d = pal[i]; + + r = (d >> 4) & 0xf0; + g = (d & 0xf0); + b = (d & 0x0f); + + r |= r >> 4; + g |= g >> 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static inline void AssembleInputs() +{ + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[2] = DrvDips[0] | 0xff00; + DrvInputs[3] = DrvDips[1] | 0xff00; + + if (scroll_type == 1) { + UINT16 *ptr = (UINT16*)Drv68KRAM2; + ptr[0] = DrvInputs[0]; + ptr[1] = DrvInputs[1]; + ptr[2] = DrvInputs[2]; + ptr[3] = DrvInputs[3]; + } +} + +static void draw_layer(UINT8 *ram, UINT8 *gfxbase, INT32 scrollx, INT32 scrolly, INT32 coloff, INT32 code_and) +{ + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sy = (offs & 0x1f) << 4; + INT32 sx = (offs >> 5) << 4; + sy -= scrolly + yoffset; + sx -= scrollx + xoffset; + if (sy < -15) sy += 512; + if (sx < -15) sx += 1024; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 code = vram[offs] & code_and; + INT32 color = vram[offs] >> 11; + + if (*flipscreen) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, (nScreenWidth - 16) - sx, (nScreenHeight - 16) - sy, color, 4, 15, coloff, gfxbase); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, coloff, gfxbase); + } + } +} + +static void draw_txt_layer(INT32 transp) +{ + UINT16 *vram = (UINT16*)DrvTxRAM; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 ofst = 0; + INT32 ofsta = 0x400; + INT32 sx = offs & 0x3f; + INT32 sy = offs >> 6; + + if (scroll_type == 1) { + ofst = (sx << 5) | sy; + ofsta = 0x800; + } else if (scroll_type == 3 || scroll_type == 6) { + ofst = ((sx & 0x1f) << 5) | sy | ((sx >> 5) << 11); + } else { + ofst = ((sy ^ 0x1f) << 5) | (sx & 0x1f) | ((sx >> 5) << 11); + } + + sx = (sx << 3) - xoffset; + sy = (sy << 3) - yoffset; + if (scroll_type != 1) sx += 128; + + if (sx < -7 || sy < -7 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[ofst+ofsta] & 0xff; + INT32 code = (vram[ofst] & 0xff) | ((attr & 3) << 8); + + if (transp) { + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, (nScreenWidth - 8) - sx, (nScreenHeight - 8) - sy, attr >> 4, 4, 15, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, attr >> 4, 4, 15, 0, DrvGfxROM0); + } + } else { + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (nScreenWidth - 8) - sx, (nScreenHeight - 8) -sy, attr >> 4, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, attr >> 4, 4, 0, DrvGfxROM0); + } + } + } +} + +static void draw_sprites(INT32 priority) +{ + UINT16 *spr = (UINT16*)DrvSprBuf; + + INT32 sprlen = 0x1000; + if (scroll_type == 0 || scroll_type == 5) sprlen = 0x400; + + for (INT32 offs = 0; offs < sprlen / 2; offs+=4) + { + INT32 attr = spr[offs + 0]; + if (((attr & 0x3000) >> 12) != priority) continue; + + INT32 code = spr[offs + 1]; + INT32 flipx = code & 0x2000; + INT32 flipy = code & 0x1000; + INT32 color =(spr[offs + 2] >> 8) & 0x1f; + INT32 sx = spr[offs + 3]; + INT32 sy = sprite_offy + 240 - (attr & 0x1ff); + code &= 0xfff; + + if (*flipscreen) { + sx = 320 - sx + 176; + sy = 240 - sy + 1; + flipx = !flipx; + flipy = !flipy; + } + + sy -= yoffset; + sx -= xoffset; + + if (sx < -15 || sy < -15 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteRecalc(); + } + + for (INT32 offs = 0; offs < nScreenWidth * nScreenHeight; offs++) + pTransDraw[offs] = 0x00ff; + + INT32 txt_transp = 1; + + if (scroll_type == 0 || scroll_type == 5) { + if ((*DrvMcuCmd & 0x000f) == 0x000f) txt_transp = 0; + } + + if (scroll_type != 1) { + UINT16 *ram = (UINT16*)DrvTxRAM; + if (scroll_type == 0 || scroll_type == 6) ram = DrvMcuCmd; + + DrvScroll[2] = (ram[13] & 0xff) | ((ram[14] & 3) << 8); + DrvScroll[3] = (ram[11] & 0xff) | ((ram[12] & 1) << 8); + } + + if (*DrvVidRegs & 0x08) draw_layer(DrvBgRAM, DrvGfxROM2, DrvScroll[0], DrvScroll[1], 0x600, 0x3ff); + if ((*DrvMcuCmd & 0x30) == 0x30 && *DrvVidRegs & 0x01) draw_txt_layer(txt_transp); + if (*DrvVidRegs & 0x02) draw_sprites(2); + if ((*DrvMcuCmd & 0x30) == 0x20 && *DrvVidRegs & 0x01) draw_txt_layer(txt_transp); + if (*DrvVidRegs & 0x04) draw_layer(DrvFgRAM, DrvGfxROM1, DrvScroll[2], DrvScroll[3], 0x400, 0x7ff); + if ((*DrvMcuCmd & 0x30) == 0x10 && *DrvVidRegs & 0x01) draw_txt_layer(txt_transp); + if (*DrvVidRegs & 0x02) draw_sprites(1); + if ((*DrvMcuCmd & 0x30) == 0x00 && *DrvVidRegs & 0x01) draw_txt_layer(txt_transp); + if (*DrvVidRegs & 0x02) draw_sprites(0); + + BurnTransferCopy(DrvPalette); + + memcpy (DrvSprBuf, DrvSprRAM, 0x1000); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + AssembleInputs(); + + INT32 nSegment; + INT32 nInterleave = nBurnSoundLen; + INT32 nTotalCycles[3] = { 8000000 / 60, 4000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + INT32 Z80IRQSlice[9]; + for (INT32 i = 0; i < 9; i++) { + Z80IRQSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 10)); + } + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nNext; + + nNext = (i + 1) * nTotalCycles[0] / nInterleave; + nSegment = nNext - nCyclesDone[0]; + nSegment = SekRun(nSegment); + nCyclesDone[0] += nSegment; + + BurnTimerUpdateYM3812(i * (nTotalCycles[1] / nInterleave)); + + for (INT32 j = 0; j < 9; j++) { + if (i == Z80IRQSlice[j]) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[1] += ZetRun(3000); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + } + + if (Terrafjb) { + ZetClose(); + ZetOpen(1); + nNext = (i + 1) * nTotalCycles[2] / nInterleave; + nSegment = nNext - nCyclesDone[2]; + nSegment = ZetRun(nSegment); + nCyclesDone[2] += nSegment; + ZetClose(); + ZetOpen(0); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = DACBuffer + (nSoundBufferPos << 1); + DACUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + BurnTimerEndFrameYM3812(nTotalCycles[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = DACBuffer + (nSoundBufferPos << 1); + if (nSegmentLength) { + DACUpdate(pSoundBuf, nSegmentLength); + } + + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + for (INT32 i = 0; i < nBurnSoundLen; i++) { + pBurnSoundOut[(i << 1) + 0] += DACBuffer[(i << 1) + 0]; + pBurnSoundOut[(i << 1) + 1] += DACBuffer[(i << 1) + 1]; + } + } + + SekSetIRQLine(irqline, SEK_IRQSTATUS_AUTO); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029702; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + DACScan(nAction, pnMin); + } + + return 0; +} + + +// Armed Formation + +static struct BurnRomInfo armedfRomDesc[] = { + { "06.3d", 0x10000, 0x0f9015e2, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "01.3f", 0x10000, 0x816ff7c5, 1 | BRF_PRG | BRF_ESS }, // 1 + { "07.5d", 0x10000, 0x5b3144a5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "02.4f", 0x10000, 0xfa10c29d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "af_08.rom", 0x10000, 0xd1d43600, 1 | BRF_PRG | BRF_ESS }, // 4 + { "af_03.rom", 0x10000, 0xbbe1fe2d, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "af_10.rom", 0x10000, 0xc5eacb87, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "09.11c", 0x08000, 0x5c6993d5, 3 | BRF_GRA }, // 7 Characters + + { "af_04.rom", 0x10000, 0x44d3af4f, 4 | BRF_GRA }, // 8 Foreground Tiles + { "af_05.rom", 0x10000, 0x92076cab, 4 | BRF_GRA }, // 9 + + { "af_14.rom", 0x10000, 0x8c5dc5a7, 5 | BRF_GRA }, // 10 Background Tiles + { "af_13.rom", 0x10000, 0x136a58a3, 5 | BRF_GRA }, // 11 + + { "af_11.rom", 0x20000, 0xb46c473c, 6 | BRF_GRA }, // 12 Sprites + { "af_12.rom", 0x20000, 0x23cb6bfe, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(armedf) +STD_ROM_FN(armedf) + +static struct BurnRomInfo armedffRomDesc[] = { + { "af_06.rom", 0x10000, 0xc5326603, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "af_01.rom", 0x10000, 0x458e9542, 1 | BRF_PRG | BRF_ESS }, // 1 + { "af_07.rom", 0x10000, 0xcc8517f5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "af_02.rom", 0x10000, 0x214ef220, 1 | BRF_PRG | BRF_ESS }, // 3 + { "af_08.rom", 0x10000, 0xd1d43600, 1 | BRF_PRG | BRF_ESS }, // 4 + { "af_03.rom", 0x10000, 0xbbe1fe2d, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "af_10.rom", 0x10000, 0xc5eacb87, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "af_09.rom", 0x08000, 0x7025e92d, 3 | BRF_GRA }, // 7 Characters + + { "af_04.rom", 0x10000, 0x44d3af4f, 4 | BRF_GRA }, // 8 Foreground Tiles + { "af_05.rom", 0x10000, 0x92076cab, 4 | BRF_GRA }, // 9 + + { "af_14.rom", 0x10000, 0x8c5dc5a7, 5 | BRF_GRA }, // 10 Background Tiles + { "af_13.rom", 0x10000, 0x136a58a3, 5 | BRF_GRA }, // 11 + + { "af_11.rom", 0x20000, 0xb46c473c, 6 | BRF_GRA }, // 12 Sprites + { "af_12.rom", 0x20000, 0x23cb6bfe, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(armedff) +STD_ROM_FN(armedff) + +static INT32 ArmedfLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 13, 1)) return 1; + + return 0; +} + +static INT32 ArmedfInit() +{ + scroll_type = 1; + sprite_offy = 128; + irqline = 1; + + return DrvInit(ArmedfLoadRoms, Armedf68KInit, 0xf800); +} + +struct BurnDriver BurnDrvArmedf = { + "armedf", NULL, NULL, NULL, "1988", + "Armed Formation\0", NULL, "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, armedfRomInfo, armedfRomName, NULL, NULL, ArmedfInputInfo, ArmedfDIPInfo, + ArmedfInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvArmedff = { + "armedff", "armedf", NULL, NULL, "1988", + "Armed Formation (Fillmore license)\0", NULL, "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, armedffRomInfo, armedffRomName, NULL, NULL, ArmedfInputInfo, ArmedfDIPInfo, + ArmedfInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 240, 320, 3, 4 +}; + + +// missing text layer on left? + + +// Crazy Climber 2 (Japan) + +static struct BurnRomInfo cclimbr2RomDesc[] = { + { "4.bin", 0x10000, 0x7922ea14, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "1.bin", 0x10000, 0x2ac7ed67, 1 | BRF_PRG | BRF_ESS }, // 1 + { "6.bin", 0x10000, 0x7905c992, 1 | BRF_PRG | BRF_ESS }, // 2 + { "5.bin", 0x10000, 0x47be6c1e, 1 | BRF_PRG | BRF_ESS }, // 3 + { "3.bin", 0x10000, 0x1fb110d6, 1 | BRF_PRG | BRF_ESS }, // 4 + { "2.bin", 0x10000, 0x0024c15b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "11.bin", 0x04000, 0xfe0175be, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + { "12.bin", 0x08000, 0x5ddf18f2, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "10.bin", 0x08000, 0x7f475266, 3 | BRF_GRA }, // 8 Characters + + { "7.bin", 0x10000, 0xcbdd3906, 4 | BRF_GRA }, // 9 Foreground Tiles + { "8.bin", 0x10000, 0xb2a613c0, 4 | BRF_GRA }, // 10 + + { "17.bin", 0x10000, 0xe24bb2d7, 5 | BRF_GRA }, // 11 Background Tiles + { "18.bin", 0x10000, 0x56834554, 5 | BRF_GRA }, // 12 + + { "15.bin", 0x10000, 0x4bf838be, 6 | BRF_GRA }, // 13 Sprites + { "16.bin", 0x10000, 0x21a265c5, 6 | BRF_GRA }, // 14 + { "13.bin", 0x10000, 0x6b6ec999, 6 | BRF_GRA }, // 15 + { "14.bin", 0x10000, 0xf426a4ad, 6 | BRF_GRA }, // 16 + + { "9.bin", 0x04000, 0x740d260f, 7 | BRF_GRA | BRF_OPT }, // 17 MCU data +}; + +STD_ROM_PICK(cclimbr2) +STD_ROM_FN(cclimbr2) + +static INT32 Cclimbr2LoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x004000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x010000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x030000, 16, 1)) return 1; + + return 0; +} + +static INT32 Cclimbr2Init() +{ + scroll_type = 4; + sprite_offy = 0; + irqline = 2; + + return DrvInit(Cclimbr2LoadRoms, Cclimbr268KInit, 0xc000); +} + +struct BurnDriver BurnDrvCclimbr2 = { + "cclimbr2", NULL, NULL, NULL, "1988", + "Crazy Climber 2 (Japan)\0", NULL, "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, cclimbr2RomInfo, cclimbr2RomName, NULL, NULL, Cclimbr2InputInfo, Cclimbr2DIPInfo, + Cclimbr2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Crazy Climber 2 (Japan, Harder) + +static struct BurnRomInfo cclmbr2aRomDesc[] = { + { "4a.bin", 0x10000, 0xe1d3192c, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "1a.bin", 0x10000, 0x3ef84974, 1 | BRF_PRG | BRF_ESS }, // 1 + { "6.bin", 0x10000, 0x7905c992, 1 | BRF_PRG | BRF_ESS }, // 2 + { "5.bin", 0x10000, 0x47be6c1e, 1 | BRF_PRG | BRF_ESS }, // 3 + { "3.bin", 0x10000, 0x1fb110d6, 1 | BRF_PRG | BRF_ESS }, // 4 + { "2.bin", 0x10000, 0x0024c15b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "11.bin", 0x04000, 0xfe0175be, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + { "12.bin", 0x08000, 0x5ddf18f2, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "10.bin", 0x08000, 0x7f475266, 3 | BRF_GRA }, // 8 Characters + + { "7.bin", 0x10000, 0xcbdd3906, 4 | BRF_GRA }, // 9 Foreground Tiles + { "8.bin", 0x10000, 0xb2a613c0, 4 | BRF_GRA }, // 10 + + { "17.bin", 0x10000, 0xe24bb2d7, 5 | BRF_GRA }, // 11 Background Tiles + { "18.bin", 0x10000, 0x56834554, 5 | BRF_GRA }, // 12 + + { "15.bin", 0x10000, 0x4bf838be, 6 | BRF_GRA }, // 13 Sprites + { "16.bin", 0x10000, 0x21a265c5, 6 | BRF_GRA }, // 14 + { "13.bin", 0x10000, 0x6b6ec999, 6 | BRF_GRA }, // 15 + { "14.bin", 0x10000, 0xf426a4ad, 6 | BRF_GRA }, // 16 + + { "9.bin", 0x04000, 0x740d260f, 7 | BRF_GRA | BRF_OPT }, // 17 MCU data +}; + +STD_ROM_PICK(cclmbr2a) +STD_ROM_FN(cclmbr2a) + +struct BurnDriver BurnDrvCclmbr2a = { + "cclimbr2a", "cclimbr2", NULL, NULL, "1988", + "Crazy Climber 2 (Japan, Harder)\0", NULL, "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, cclmbr2aRomInfo, cclmbr2aRomName, NULL, NULL, Cclimbr2InputInfo, Cclimbr2DIPInfo, + Cclimbr2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Kozure Ookami (Japan) + +static struct BurnRomInfo kozureRomDesc[] = { + { "kozure8.6e", 0x10000, 0x6bbfb1e6, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "kozure3.6h", 0x10000, 0xf9178ec8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "kozure7.5e", 0x10000, 0xa7ee09bb, 1 | BRF_PRG | BRF_ESS }, // 2 + { "kozure2.5h", 0x10000, 0x236d820f, 1 | BRF_PRG | BRF_ESS }, // 3 + { "kozure6.3e", 0x10000, 0x9120e728, 1 | BRF_PRG | BRF_ESS }, // 4 + { "kozure1.3h", 0x10000, 0x345fe7a5, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "kozure11.17k", 0x10000, 0xdba51e2d, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "kozure9.11e", 0x08000, 0xe041356e, 3 | BRF_GRA }, // 7 Characters + + { "kozure5.15h", 0x20000, 0x0b510258, 4 | BRF_GRA }, // 8 Foreground Tiles + { "kozure4.14h", 0x10000, 0xfb8e13e6, 4 | BRF_GRA }, // 9 + + { "kozure14.8a", 0x10000, 0x94a9c3d0, 5 | BRF_GRA }, // 10 Background Tiles + + { "kozure12.8d", 0x20000, 0x15f4021d, 6 | BRF_GRA }, // 11 Sprites + { "kozure13.9d", 0x20000, 0xb3b6c753, 6 | BRF_GRA }, // 12 + + { "kozure10.11c", 0x04000, 0xf48be21d, 7 | BRF_GRA | BRF_OPT }, // 13 MCU data + + { "n82s129an.11j", 0x00100, 0x81244757, 8 | BRF_OPT }, // 14 Proms +}; + +STD_ROM_PICK(kozure) +STD_ROM_FN(kozure) + +static INT32 KozureLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 12, 1)) return 1; + + return 0; +} + +static INT32 KozureInit() +{ + scroll_type = 2; + sprite_offy = 128; + irqline = 1; + + return DrvInit(KozureLoadRoms, Cclimbr268KInit, 0xf800); +} + +struct BurnDriver BurnDrvKozure = { + "kozure", NULL, NULL, NULL, "1987", + "Kozure Ookami (Japan)\0", "Imperfect Graphics", "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, kozureRomInfo, kozureRomName, NULL, NULL, ArmedfInputInfo, KozureDIPInfo, + KozureInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Chouji Meikyuu Legion (ver 2.03) + +static struct BurnRomInfo legionRomDesc[] = { + { "lg3.bin", 0x10000, 0x777e4935, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "lg1.bin", 0x10000, 0xc4aeb724, 1 | BRF_PRG | BRF_ESS }, // 1 + { "legion.1d", 0x10000, 0xc2e45e1e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "legion.1b", 0x10000, 0xc306660a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "legion.1h", 0x04000, 0x2ca4f7f0, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 code + + { "lg8.bin", 0x08000, 0xe0596570, 3 | BRF_GRA }, // 5 Characters + + { "legion.1e", 0x10000, 0xa9d70faf, 4 | BRF_GRA }, // 6 Foreground Tiles + { "legion.1f", 0x08000, 0xf018313b, 4 | BRF_GRA }, // 7 + + { "legion.1l", 0x10000, 0x29b8adaa, 5 | BRF_GRA }, // 8 Background Tiles + + { "legion.1k", 0x10000, 0xff5a0db9, 6 | BRF_GRA }, // 9 Sprites + { "legion.1j", 0x10000, 0xbae220c8, 6 | BRF_GRA }, // 10 + + { "lg7.bin", 0x04000, 0x533e2b58, 7 | BRF_GRA | BRF_OPT }, // 11 MCU data + + { "legion.1i", 0x08000, 0x79f4a827, 2 | BRF_OPT }, // 12 Unknown +}; + +STD_ROM_PICK(legion) +STD_ROM_FN(legion) + +static INT32 LegionLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x04000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x018000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 10, 1)) return 1; + + return 0; +} + +static INT32 LegionInit() +{ + scroll_type = 3; + sprite_offy = 0; + irqline = 2; + + INT32 nRet = DrvInit(LegionLoadRoms, Cclimbr268KInit, 0xc000); + + if (nRet == 0) { // hack + *((UINT16*)(Drv68KROM + 0x001d6)) = 0x0001; + *((UINT16*)(Drv68KROM + 0x00488)) = 0x4e71; + } + + return nRet; +} + +struct BurnDriver BurnDrvLegion = { + "legion", NULL, NULL, NULL, "1987", + "Chouji Meikyuu Legion (ver 2.03)\0", "Imperfect Graphics", "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, legionRomInfo, legionRomName, NULL, NULL, ArmedfInputInfo, LegionDIPInfo, + LegionInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 288, 3, 4 +}; + + +// Chouji Meikyuu Legion (ver 1.05) + +static struct BurnRomInfo legionoRomDesc[] = { + { "legion.1c", 0x10000, 0x21226660, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "legion.1a", 0x10000, 0x8c0cda1d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "legion.1d", 0x10000, 0xc2e45e1e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "legion.1b", 0x10000, 0xc306660a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "legion.1h", 0x04000, 0x2ca4f7f0, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 code + + { "legion.1g", 0x08000, 0xc50b0125, 3 | BRF_GRA }, // 5 Characters + + { "legion.1e", 0x10000, 0xa9d70faf, 4 | BRF_GRA }, // 6 Foreground Tiles + { "legion.1f", 0x08000, 0xf018313b, 4 | BRF_GRA }, // 7 + + { "legion.1l", 0x10000, 0x29b8adaa, 5 | BRF_GRA }, // 8 Background Tiles + + { "legion.1k", 0x10000, 0xff5a0db9, 6 | BRF_GRA }, // 9 Sprites + { "legion.1j", 0x10000, 0xbae220c8, 6 | BRF_GRA }, // 10 + + { "legion.1i", 0x08000, 0x79f4a827, 0 | BRF_OPT }, // 11 Unknown +}; + +STD_ROM_PICK(legiono) +STD_ROM_FN(legiono) + +static INT32 LegionoLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x04000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x018000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 10, 1)) return 1; + + return 0; +} + +static INT32 LegionoInit() +{ + scroll_type = 6; + sprite_offy = 0; + irqline = 2; + + INT32 nRet = DrvInit(LegionoLoadRoms, Cclimbr268KInit, 0xc000); + + if (nRet == 0) { // hack + *((UINT16*)(Drv68KROM + 0x001d6)) = 0x0001; + } + + return nRet; +} + +struct BurnDriver BurnDrvLegiono = { + "legiono", "legion", NULL, NULL, "1987", + "Chouji Meikyuu Legion (ver 1.05)\0", "Imperfect Graphics", "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, legionoRomInfo, legionoRomName, NULL, NULL, ArmedfInputInfo, LegionDIPInfo, + LegionoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 288, 3, 4 +}; + + +// Terra Force (set 1) + +static struct BurnRomInfo terrafRomDesc[] = { + { "8.6e", 0x10000, 0xfd58fa06, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "3.6h", 0x10000, 0x54823a7d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "7.4e", 0x10000, 0xfde8de7e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "2.4h", 0x10000, 0xdb987414, 1 | BRF_PRG | BRF_ESS }, // 3 + { "6.3e", 0x10000, 0xa5bb8c3b, 1 | BRF_PRG | BRF_ESS }, // 4 + { "1.3h", 0x10000, 0xd2de6d28, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "11.17k", 0x10000, 0x4407d475, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "9.11e", 0x08000, 0xbc6f7cbc, 3 | BRF_GRA }, // 7 Characters + + { "5.15h", 0x10000, 0x25d23dfd, 4 | BRF_GRA }, // 8 Foreground Tiles + { "4.13h", 0x10000, 0xb9b0fe27, 4 | BRF_GRA }, // 9 + + { "15.8a", 0x10000, 0x2144d8e0, 5 | BRF_GRA }, // 10 Background Tiles + { "14.6a", 0x10000, 0x744f5c9e, 5 | BRF_GRA }, // 11 + + { "12.7d", 0x10000, 0x2d1f2ceb, 6 | BRF_GRA }, // 12 Sprites + { "13.9d", 0x10000, 0x1d2f92d6, 6 | BRF_GRA }, // 13 + + { "10.11c", 0x04000, 0xac705812, 7 | BRF_GRA | BRF_OPT }, // 14 MCU data + + { "n82s129an.11j", 0x00100, 0x81244757, 8 | BRF_OPT }, // 15 Proms +}; + +STD_ROM_PICK(terraf) +STD_ROM_FN(terraf) + +static INT32 TerrafInit() +{ + scroll_type = 0; + sprite_offy = 128; + irqline = 1; + + return DrvInit(ArmedfLoadRoms, Cclimbr268KInit, 0xf800); +} + +struct BurnDriver BurnDrvTerraf = { + "terraf", NULL, NULL, NULL, "1987", + "Terra Force\0", "imperfect graphics", "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, terrafRomInfo, terrafRomName, NULL, NULL, ArmedfInputInfo, TerrafDIPInfo, + TerrafInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + + +// Terra Force (US) + +static struct BurnRomInfo terrafuRomDesc[] = { + { "tf-8.6e", 0x10000, 0xfea6dd64, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tf-3.6h", 0x10000, 0x02f9d05a, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tf-7.4e", 0x10000, 0xfde8de7e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tf-2.4h", 0x10000, 0xdb987414, 1 | BRF_PRG | BRF_ESS }, // 3 + { "tf-6.3e", 0x08000, 0xb91e9ba3, 1 | BRF_PRG | BRF_ESS }, // 4 + { "tf-1.3h", 0x08000, 0xd6e22375, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "tf-001.17k", 0x10000, 0xeb6b4138, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "9.11e", 0x08000, 0xbc6f7cbc, 3 | BRF_GRA }, // 7 Characters + + { "5.15h", 0x10000, 0x25d23dfd, 4 | BRF_GRA }, // 8 Foreground Tiles + { "4.13h", 0x10000, 0xb9b0fe27, 4 | BRF_GRA }, // 9 + + { "15.8a", 0x10000, 0x2144d8e0, 5 | BRF_GRA }, // 10 Background Tiles + { "14.6a", 0x10000, 0x744f5c9e, 5 | BRF_GRA }, // 11 + + { "tf-003.7d", 0x10000, 0xd74085a1, 6 | BRF_GRA }, // 12 Sprites + { "tf-002.9d", 0x10000, 0x148aa0c5, 6 | BRF_GRA }, // 13 + + { "10.11c", 0x04000, 0xac705812, 7 | BRF_GRA | BRF_OPT }, // 14 MCU data + + { "n82s129an.11j", 0x00100, 0x81244757, 8 | BRF_OPT }, // 15 Proms +}; + +STD_ROM_PICK(terrafu) +STD_ROM_FN(terrafu) + +static INT32 TerrafuInit() +{ + scroll_type = 5; + sprite_offy = 128; + irqline = 1; + + return DrvInit(ArmedfLoadRoms, Cclimbr268KInit, 0xf800); +} + +struct BurnDriver BurnDrvTerrafu = { + "terrafu", "terraf", NULL, NULL, "1987", + "Terra Force (US)\0", "imperfect graphics", "Nichibutsu USA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, terrafuRomInfo, terrafuRomName, NULL, NULL, ArmedfInputInfo, TerrafDIPInfo, + TerrafuInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + +// Terra Force (bootleg with additional Z80) + +static struct BurnRomInfo terrafjbRomDesc[] = { + { "tfj-8.bin", 0x10000, 0xb11a6fa7, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tfj-3.bin", 0x10000, 0x6c6aa7ed, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tfj-7.bin", 0x10000, 0xfde8de7e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tfj-2.bin", 0x10000, 0xdb987414, 1 | BRF_PRG | BRF_ESS }, // 3 + { "tfb-6.bin", 0x08000, 0x552c3c63, 1 | BRF_PRG | BRF_ESS }, // 4 + { "tfb-1.bin", 0x08000, 0x6a0b94c7, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "tf-001.17k", 0x10000, 0xeb6b4138, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "tfb-10.bin", 0x04000, 0x3f9aa367, 9 | BRF_PRG | BRF_ESS }, // 7 Z80 Code (Mcu replacement) + + { "9.11e", 0x08000, 0xbc6f7cbc, 3 | BRF_GRA }, // 8 Characters + + { "5.15h", 0x10000, 0x25d23dfd, 4 | BRF_GRA }, // 9 Foreground Tiles + { "4.13h", 0x10000, 0xb9b0fe27, 4 | BRF_GRA }, // 10 + + { "15.8a", 0x10000, 0x2144d8e0, 5 | BRF_GRA }, // 11 Background Tiles + { "14.6a", 0x10000, 0x744f5c9e, 5 | BRF_GRA }, // 12 + + { "tfj-12.7d", 0x10000, 0xd74085a1, 6 | BRF_GRA | BRF_OPT }, // 13 Sprites + { "tfj-13.9d", 0x10000, 0x148aa0c5, 6 | BRF_GRA | BRF_OPT }, // 14 + + { "n82s129an.11j", 0x00100, 0x81244757, 7 | BRF_OPT }, // 15 proms +}; + +STD_ROM_PICK(terrafjb) +STD_ROM_FN(terrafjb) + +static INT32 TerrafjbLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 6, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM2, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 12, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 14, 1)) return 1; + + return 0; +} + +static INT32 TerrafjbInit() +{ + scroll_type = 5; + sprite_offy = 128; + irqline = 1; + + Terrafjb = 1; + + return DrvInit(TerrafjbLoadRoms, Cclimbr268KInit, 0xf800); +} + +struct BurnDriver BurnDrvTerrafjb = { + "terrafjb", "terraf", NULL, NULL, "1987", + "Terra Force (Japan bootleg with additional Z80)\0", "imperfect graphics", "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, terrafjbRomInfo, terrafjbRomName, NULL, NULL, ArmedfInputInfo, TerrafDIPInfo, + TerrafjbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; + +// Terra Force (set 2) + +static struct BurnRomInfo terrafbRomDesc[] = { + { "tf-014.6e", 0x10000, 0x8e5f557f, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tf-011.6h", 0x10000, 0x5320162a, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tf-013.4e", 0x10000, 0xa86951e0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tf-010.4h", 0x10000, 0x58b5f43b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "tf-012.3e", 0x08000, 0x4f0e1d76, 1 | BRF_PRG | BRF_ESS }, // 4 + { "tf-009.3h", 0x08000, 0xd1014280, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "tf-001.17k", 0x10000, 0xeb6b4138, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 code + + { "9.11e", 0x08000, 0xbc6f7cbc, 3 | BRF_GRA }, // 7 Characters + + { "5.15h", 0x10000, 0x25d23dfd, 4 | BRF_GRA }, // 8 Foreground Tiles + { "4.13h", 0x10000, 0xb9b0fe27, 4 | BRF_GRA }, // 9 + + { "15.8a", 0x10000, 0x2144d8e0, 5 | BRF_GRA }, // 10 Background Tiles + { "14.6a", 0x10000, 0x744f5c9e, 5 | BRF_GRA }, // 11 + + { "tfj-12.7d", 0x10000, 0xd74085a1, 6 | BRF_GRA }, // 12 Sprites + { "tfj-13.9d", 0x10000, 0x148aa0c5, 6 | BRF_GRA }, // 13 + + { "tf-10.11c", 0x04000, 0xac705812, 7 | BRF_GRA | BRF_OPT }, // 14 MCU data + + { "n82s129an.11j", 0x00100, 0x81244757, 8 | BRF_OPT }, // 15 Proms +}; + +STD_ROM_PICK(terrafb) +STD_ROM_FN(terrafb) + +struct BurnDriver BurnDrvTerrafb = { + "terrafb", "terraf", NULL, NULL, "1987", + "Terra Force (bootleg)\0", "imperfect graphics", "Nichibutsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, terrafbRomInfo, terrafbRomName, NULL, NULL, ArmedfInputInfo, TerrafDIPInfo, + TerrafuInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_aztarac.cpp b/src/burn/drivers/misc_pre90s/d_aztarac.cpp new file mode 100644 index 00000000..1b461328 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_aztarac.cpp @@ -0,0 +1,656 @@ +// FB Alpha Aztarac driver module +// Based on MAME driver by Mathis Rosenhauer + +// To do: Joystick and dial!! + +#include "burnint.h" +#include "vector.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvVecRAM; +static UINT8 *DrvNVRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static INT32 sound_irq_timer; +static INT32 sound_status; + +static INT32 sound_initialized = 0; +static INT16 *pFMBuffer[12]; + +static INT32 xcenter; +static INT32 ycenter; + +static INT32 watchdog; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvInputs[1]; +static UINT8 DrvReset; + +static INT16 DrvAnalogPort0; +static INT16 DrvAnalogPort1; + +static UINT8 xAxis = 0; +static UINT8 yAxis = 0; +static UINT8 Dial = 0; +static UINT8 DialInputs[2]; + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo AztaracInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 2" }, + + A("Left/Right", BIT_ANALOG_REL, &DrvAnalogPort0, "p1 x-axis" ), + A("Up/Down", BIT_ANALOG_REL, &DrvAnalogPort1, "p1 y-axis" ), + {"Aim Left", BIT_DIGITAL, DialInputs + 0, "p1 fire 3" }, + {"Aim Right", BIT_DIGITAL, DialInputs + 1, "p1 fire 4" }, + + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" }, +}; + +STDINPUTINFO(Aztarac) + +#undef A + +static inline void read_vectorram (INT32 addr, INT32 *x, INT32 *y, INT32 *c) +{ + *c = SekReadWord(0xff8000 + addr); + *x = SekReadWord(0xff9000 + addr) & 0x03ff; + *y = SekReadWord(0xffa000 + addr) & 0x03ff; + if (*x & 0x200) *x |= 0xfffffc00; // signed + if (*y & 0x200) *y |= 0xfffffc00; // signed +} + +static void aztarac_process_vector_list() +{ + INT32 x, y, c, intensity, xoffset, yoffset, color; + INT32 defaddr, objaddr, ndefs; + + vector_reset(); + + for (objaddr = 0; objaddr < 0x800; objaddr++) + { + read_vectorram (objaddr * 2, &xoffset, &yoffset, &c); + + if (c & 0x4000) break; + + if ((c & 0x2000) == 0) + { + defaddr = (c >> 1) & 0x7ff; + + vector_add_point((xcenter + (xoffset << 16)), (ycenter - (yoffset << 16)), 0, 0); + + read_vectorram (defaddr * 2, &x, &ndefs, &c); + ndefs++; + + if (c & 0xff00) + { + intensity = (c >> 8); + color = c & 0x3f; + + while (ndefs--) + { + defaddr++; + read_vectorram (defaddr * 2, &x, &y, &c); + + if ((c & 0xff00) == 0) + vector_add_point((xcenter + ((x + xoffset) << 16)), (ycenter - ((y + yoffset) << 16)), 0, 0); + else + vector_add_point((xcenter + ((x + xoffset) << 16)), (ycenter - ((y + yoffset) << 16)), color, intensity); + } + } + else + { + while (ndefs--) + { + defaddr++; + read_vectorram (defaddr * 2, &x, &y, &c); + + color = c & 0x3f; + vector_add_point((xcenter + ((x + xoffset) << 16)), (ycenter - ((y + yoffset) << 16)), color, c >> 8); + } + } + } + } +} + +static inline void sync_cpu() +{ + INT32 cycles = (SekTotalCycles() / 4) - ZetTotalCycles(); + + if (cycles > 0) ZetRun(cycles); +} + +void __fastcall aztarac_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff00) == 0x022000) { + *((UINT16*)(DrvNVRAM + (address & 0xfe))) = data | 0xfff0; + return; + } + + if (address == 0xffb000) { + if (data) aztarac_process_vector_list(); // used once? + return; + } +} + +void __fastcall aztarac_write_byte(UINT32 address, UINT8 data) +{ + if (address == 0x027009) { + sync_cpu(); + *soundlatch = data; + sound_status ^= 0x21; + + if (sound_status & 0x20) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + + return; + } + + if (address == 0xffb001) { + if (data) aztarac_process_vector_list(); + return; + } +} + +UINT16 __fastcall aztarac_read_word(UINT32 address) +{ + switch (address) + { + case 0x027004: + return 0xff00 | DrvInputs[0]; + + case 0x02700e: + watchdog = 0; + return 0; + } + + return 0; +} + +UINT8 __fastcall aztarac_read_byte(UINT32 address) +{ + switch (address) + { + case 0x027000: + return xAxis - 0x0f; + + case 0x027001: + return yAxis - 0x0f; + + case 0x027005: + return DrvInputs[0]; // inputs + + case 0x027009: + sync_cpu(); + return sound_status & 0x01; + + case 0x02700d: + return Dial; + } + + return 0; +} + +void __fastcall aztarac_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8c00: + case 0x8c01: + case 0x8c02: + case 0x8c03: + case 0x8c04: + case 0x8c05: + case 0x8c06: + case 0x8c07: + AY8910Write((address & 6) / 2, ~address & 1, data); + return; + + case 0x9000: + sound_status &= ~0x10; + return; + } +} + +UINT8 __fastcall aztarac_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8800: + sound_status = (sound_status | 0x01) & ~0x20; + return *soundlatch; + + case 0x8c00: + case 0x8c01: + case 0x8c02: + case 0x8c03: + case 0x8c04: + case 0x8c05: + case 0x8c06: + case 0x8c07: + return AY8910Read((address & 6) / 2); + + case 0x9000: + return sound_status & ~0x01; + } + + return 0; +} + +static INT32 __fastcall aztarac_irq_callback(INT32) +{ + return 0x0c; +} + +static INT32 DrvDoReset(INT32 reset_ram) +{ + if (reset_ram) { + memset (AllRam, 0, RamEnd - AllRam); + } + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + AY8910Reset(2); + AY8910Reset(3); + + sound_status = 0; + sound_irq_timer = 0; + + watchdog = 0; + + vector_reset(); + + return 0; +} + +static void sound_init() // Changed refresh rate causes crashes +{ + for (INT32 i = 0; i < 12; i++) { + pFMBuffer[i] = (INT16*)BurnMalloc(nBurnSoundLen * sizeof(INT16)); + } + + sound_initialized = 1; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x010000; + DrvZ80ROM = Next; Next += 0x002000; + + DrvNVRAM = Next; Next += 0x000400; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x002000; + DrvZ80RAM = Next; Next += 0x000800; + DrvVecRAM = Next; Next += 0x003000; + + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + DrvPalette = (UINT32*)Next; Next += 0x0040 * 256 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x40; i++) // color + { + for (INT32 j = 0; j < 256; j++) // intensity + { + INT32 r = (i >> 4) & 3; + r = (r << 6) | (r << 4) | (r << 2) | (r << 0); + + INT32 g = (i >> 2) & 3; + g = (g << 6) | (g << 4) | (g << 2) | (g << 0); + + INT32 b = (i >> 0) & 3; + b = (b << 6) | (b << 4) | (b << 2) | (b << 0); + + r = (r * j) / 255; + g = (g * j) / 255; + b = (b * j) / 255; + + DrvPalette[i * 256 + j] = (r << 16) | (g << 8) | b; + } + } +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(40.0); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x02001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x02000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x04001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x04000, 5, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x06001, 6, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x06000, 7, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x08001, 8, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x08000, 9, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0a001, 10, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x0a000, 11, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x01000, 13, 1)) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekSetIrqCallback(aztarac_irq_callback); + SekMapMemory(Drv68KROM, 0x000000, 0x00bfff, SM_ROM); + SekMapMemory(DrvNVRAM, 0x022000, 0x0223ff, SM_ROM); + SekMapMemory(DrvVecRAM, 0xff8000, 0xffafff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffe000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, aztarac_write_word); + SekSetWriteByteHandler(0, aztarac_write_byte); + SekSetReadWordHandler(0, aztarac_read_word); + SekSetReadByteHandler(0, aztarac_read_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(aztarac_sound_write); + ZetSetReadHandler(aztarac_sound_read); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(2, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(3, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvPaletteInit(); + + vector_init(); + + xcenter = (1024 / 2) << 16; + ycenter = ( 768 / 2) << 16; + + memset (DrvNVRAM, 0xff, 0x100); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + vector_exit(); + + SekExit(); + ZetExit(); + + AY8910Exit(0); + AY8910Exit(1); + AY8910Exit(2); + AY8910Exit(3); + + BurnFree (AllMem); + + sound_initialized = 0; + for (INT32 i = 0; i < 12; i++) { + BurnFree (pFMBuffer[i]); + } + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_vector(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (sound_initialized == 0) { + if (pBurnSoundOut) { + sound_init(); + } + } + + if (DrvReset) { + DrvDoReset(1); + } + + watchdog++; + if (watchdog == 180) { // 3 seconds? + DrvDoReset(0); + } + + SekNewFrame(); + ZetNewFrame(); + + { + DrvInputs[0] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + + xAxis = (DrvAnalogPort0 >> 7) + 0x0f; + if (xAxis > 0x80) xAxis = 0; + + yAxis = (~DrvAnalogPort1 >> 7) + 0x10; + if (yAxis > 0x1d) yAxis = 0x1d; + + if (DialInputs[0]) { + Dial += 0x04; + } else { + if (DialInputs[1]) { + Dial -= 0x04; + } + } + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { 8000000 / 40, 2000000 / 40 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++, sound_irq_timer++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + //nCyclesDone[1] += ZetRun((SekTotalCycles() / 4) - ZetTotalCycles()); + sync_cpu(); + + if ((sound_irq_timer % 40) == 39) { // every 20000 cycles, 50000 / frame + sound_status ^= 0x10; + if (sound_status & 0x10) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } + + SekClose(); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + + AY8910Update(0, &pFMBuffer[0], nBurnSoundLen); + AY8910Update(1, &pFMBuffer[3], nBurnSoundLen); + AY8910Update(2, &pFMBuffer[6], nBurnSoundLen); + AY8910Update(3, &pFMBuffer[9], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pFMBuffer[ 0][n] / 2; + nSample += pFMBuffer[ 1][n] / 2; + nSample += pFMBuffer[ 2][n] / 2; + nSample += pFMBuffer[ 3][n] / 2; + nSample += pFMBuffer[ 4][n] / 2; + nSample += pFMBuffer[ 5][n] / 2; + nSample += pFMBuffer[ 6][n] / 2; + nSample += pFMBuffer[ 7][n] / 2; + nSample += pFMBuffer[ 8][n] / 2; + nSample += pFMBuffer[ 9][n] / 2; + nSample += pFMBuffer[10][n] / 2; + nSample += pFMBuffer[11][n] / 2; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_ROM) { + ba.Data = Drv68KROM; + ba.nLen = 0x000c000; + ba.nAddress = 0x0000000; + ba.szName = "68K ROM"; + BurnAcb(&ba); + + ba.Data = DrvZ80ROM; + ba.nLen = 0x0002000; + ba.nAddress = 0x0000000; + ba.szName = "Z80 ROM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = Drv68KRAM; + ba.nLen = 0x0002000; + ba.nAddress = 0x0ffe000; + ba.szName = "68K RAM"; + BurnAcb(&ba); + + ba.Data = DrvVecRAM; + ba.nLen = 0x0003000; + ba.nAddress = 0x0ff8000; + ba.szName = "Vector RAM"; + BurnAcb(&ba); + + ba.Data = DrvZ80RAM; + ba.nLen = 0x0000800; + ba.nAddress = 0x0000000; + ba.szName = "Z80 RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM) { + ba.Data = DrvNVRAM; + ba.nLen = 0x000100; + ba.nAddress = 0x022000; + ba.szName = "NV RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(*soundlatch); + SCAN_VAR(sound_irq_timer); + SCAN_VAR(sound_status); + } + + vector_scan(nAction); + + return 0; +} + + +// Aztarac + +static struct BurnRomInfo aztaracRomDesc[] = { + { "l8_6.bin", 0x1000, 0x25f8da18, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "n8_0.bin", 0x1000, 0x04e20626, 1 | BRF_PRG | BRF_ESS }, // 1 + { "l7_7.bin", 0x1000, 0x230e244c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "n7_1.bin", 0x1000, 0x37b12697, 1 | BRF_PRG | BRF_ESS }, // 3 + { "l6_8.bin", 0x1000, 0x1293fb9d, 1 | BRF_PRG | BRF_ESS }, // 4 + { "n6_2.bin", 0x1000, 0x712c206a, 1 | BRF_PRG | BRF_ESS }, // 5 + { "l5_9.bin", 0x1000, 0x743a6501, 1 | BRF_PRG | BRF_ESS }, // 6 + { "n5_3.bin", 0x1000, 0xa65cbf99, 1 | BRF_PRG | BRF_ESS }, // 7 + { "l4_a.bin", 0x1000, 0x9cf1b0a1, 1 | BRF_PRG | BRF_ESS }, // 8 + { "n4_4.bin", 0x1000, 0x5f0080d5, 1 | BRF_PRG | BRF_ESS }, // 9 + { "l3_b.bin", 0x1000, 0x8cc7f7fa, 1 | BRF_PRG | BRF_ESS }, // 10 + { "n3_5.bin", 0x1000, 0x40452376, 1 | BRF_PRG | BRF_ESS }, // 11 + + { "j4_c.bin", 0x1000, 0xe897dfcd, 2 | BRF_PRG | BRF_ESS }, // 12 Z80 Code + { "j3_d.bin", 0x1000, 0x4016de77, 2 | BRF_PRG | BRF_ESS }, // 13 +}; + +STD_ROM_PICK(aztarac) +STD_ROM_FN(aztarac) + +struct BurnDriver BurnDrvAztarac = { + "aztarac", NULL, NULL, NULL, "1983", + "Aztarac\0", "Vector graphics", "Centuri", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, aztaracRomInfo, aztaracRomName, NULL, NULL, AztaracInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40 * 256, + 1024, 768, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_bankp.cpp b/src/burn/drivers/misc_pre90s/d_bankp.cpp new file mode 100644 index 00000000..824bb23c --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_bankp.cpp @@ -0,0 +1,609 @@ +// FB Alpha Bank Panic Driver Module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "sn76496.h" + +static UINT8 *Mem, *Rom, *Gfx0, *Gfx1, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvReset, DrvDips; +static INT32 *Palette; + +static UINT8 scroll_x, priority, flipscreen, interrupt_enable; + +static struct BurnInputInfo bankpInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 5, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 6, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvJoy1 + 6, "p3 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 5, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 6, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 7, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 3"}, + + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 7, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 1, "p2 fire 3"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, &DrvDips, "dip" }, +}; + +STDINPUTINFO(bankp) + +static struct BurnInputInfo combhInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 5, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 6, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvJoy1 + 6, "p3 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy2 + 5, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 6, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 2, "p1 down" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 7, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 3"}, + + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p2 down" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 7, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 1, "p2 fire 3"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, &DrvDips, "dip" }, + +}; + +STDINPUTINFO(combh) + +static struct BurnDIPInfo bankpDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x41, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A/B" }, + {0x10, 0x01, 0x03, 0x03, "3C 1C" }, + {0x10, 0x01, 0x03, 0x02, "2C 1C" }, + {0x10, 0x01, 0x03, 0x01, "1C 1C" }, + {0x10, 0x01, 0x03, 0x00, "1C 2C" }, + + {0 , 0xfe, 0 , 2 , "Coin C" }, + {0x10, 0x01, 0x04, 0x04, "2C 1C" }, + {0x10, 0x01, 0x04, 0x00, "1C 1C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x08, 0x00, "3" }, + {0x10, 0x01, 0x08, 0x08, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x10, 0x00, "70K 200K 500K..." }, + {0x10, 0x01, 0x10, 0x10, "100K 400K 800K..." }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x20, 0x00, "Easy" }, + {0x10, 0x01, 0x20, 0x20, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x40, 0x00, "Off" }, + {0x10, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, +}; + +STDDIPINFO(bankp) + +static struct BurnDIPInfo combhDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x40, NULL }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x10, 0x01, 0x01, 0x00, "Off" }, + {0x10, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x06, 0x06, "2C 1C" }, + {0x10, 0x01, 0x06, 0x00, "1C 1C" }, + {0x10, 0x01, 0x06, 0x02, "1C 2C" }, + {0x10, 0x01, 0x06, 0x04, "1C 3C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x08, 0x00, "3" }, + {0x10, 0x01, 0x08, 0x08, "4" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x10, 0x10, "Upright" }, + {0x10, 0x01, 0x10, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x40, 0x00, "Easy" }, + {0x10, 0x01, 0x40, 0x40, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Fuel" }, + {0x10, 0x01, 0x80, 0x00, "120 Units" }, + {0x10, 0x01, 0x80, 0x80, "90 Units" }, +}; + +STDDIPINFO(combh) + +UINT8 __fastcall bankp_in(UINT16 address) +{ + UINT8 ret = 0; + + switch (address & 0xff) + { + case 0x00: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy1[i] << i; + + // limit controls to 2-way + if ((ret & 0x05) == 0x05) ret &= 0xfa; + if ((ret & 0x0a) == 0x0a) ret &= 0xf5; + + return ret; + } + + case 0x01: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy2[i] << i; + + // limit controls to 2-way + if ((ret & 0x05) == 0x05) ret &= 0xfa; + if ((ret & 0x0a) == 0x0a) ret &= 0xf5; + + return ret; + } + + case 0x02: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy3[i] << i; + + return ret; + } + + case 0x04: + return DrvDips; + } + + return 0; +} + +void __fastcall bankp_out(UINT16 address, UINT8 data) +{ + switch (address & 0xff) + { + case 0x00: + SN76496Write(0, data); + break; + + case 0x01: + SN76496Write(1, data); + break; + + case 0x02: + SN76496Write(2, data); + break; + + case 0x05: + scroll_x = data; + break; + + case 0x07: + { + priority = data & 0x03; + + interrupt_enable = (data >> 4) & 1; + + flipscreen = data & 0x20; + } + break; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Mem + 0xe000, 0, 0x2000); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + scroll_x = 0, priority = 0, flipscreen = 0; + interrupt_enable = 0; + + return 0; +} + +static INT32 bankp_palette_init() +{ + INT32 i; + + UINT32 t_pal[32]; + UINT8 *color_prom = Prom; + + for (i = 0;i < 32;i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (*color_prom >> 0) & 0x01; + bit1 = (*color_prom >> 1) & 0x01; + bit2 = (*color_prom >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (*color_prom >> 3) & 0x01; + bit1 = (*color_prom >> 4) & 0x01; + bit2 = (*color_prom >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (*color_prom >> 6) & 0x01; + bit2 = (*color_prom >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + t_pal[i] = (r << 16) | (g << 8) | b; + + color_prom++; + } + + for (i = 0;i < 32 * 4;i++) { + Palette[i] = t_pal[*color_prom & 0x0f]; + color_prom++; + } + + color_prom += 128; + + for (i = 0;i < 16 * 8;i++) { + Palette[i + 0x80] = t_pal[*color_prom & 0x0f]; + color_prom++; + } + + return 0; +} + +static INT32 bankp_gfx_decode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x10000); + + static INT32 Char1PlaneOffsets[2] = { 0x00, 0x04 }; + static INT32 Char2PlaneOffsets[3] = { 0x00, 0x20000, 0x40000 }; + static INT32 Char1XOffsets[8] = { 0x43, 0x42, 0x41, 0x40, 0x03, 0x02, 0x01, 0x00 }; + static INT32 Char2XOffsets[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + static INT32 CharYOffsets[8] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 }; + + GfxDecode(0x400, 2, 8, 8, Char1PlaneOffsets, Char1XOffsets, CharYOffsets, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x10000); + + GfxDecode(0x800, 3, 8, 8, Char2PlaneOffsets, Char2XOffsets, CharYOffsets, 0x040, tmp, Gfx1); + + for (INT32 i = 0; i < 0x20000; i++) { + Gfx1[i] |= 0x80; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x10000 + 0x20000 + 0x200 + (0x100 * sizeof(INT32))); + if (Mem == NULL) { + return 1; + } + + Rom = Mem + 0x00000; + Gfx0 = Mem + 0x10000; + Gfx1 = Mem + 0x20000; + Prom = Mem + 0x40000; + Palette = (INT32*)(Mem + 0x40200); + + { + for (INT32 i = 0; i < 4; i++) + if (BurnLoadRom(Rom + i * 0x4000, i + 0, 1)) return 1; + + if (BurnLoadRom(Gfx0 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x2000, 5, 1)) return 1; + + for (INT32 i = 0; i < 6; i++) + if (BurnLoadRom(Gfx1 + i * 0x2000, i + 6, 1)) return 1; + + if (BurnLoadRom(Prom + 0x0000, 12, 1)) return 1; + if (BurnLoadRom(Prom + 0x0020, 13, 1)) return 1; + if (BurnLoadRom(Prom + 0x0120, 14, 1)) return 1; + + if (bankp_gfx_decode()) return 1; + bankp_palette_init(); + } + + ZetInit(1); + ZetOpen(0); + ZetSetInHandler(bankp_in); + ZetSetOutHandler(bankp_out); + ZetMapArea(0x0000, 0xdfff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0xdfff, 2, Rom + 0x0000); + ZetMapArea(0xe000, 0xefff, 0, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 1, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, Rom + 0xe000); + ZetMapArea(0xf000, 0xffff, 0, Rom + 0xf000); + ZetMapArea(0xf000, 0xffff, 1, Rom + 0xf000); + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 15468000 / 6, 0); + SN76489Init(1, 15468000 / 6, 1); + SN76489Init(2, 15468000 / 6, 1); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + + SN76496Exit(); + + BurnFree (Mem); + + scroll_x = priority = flipscreen = interrupt_enable = 0; + + Rom = Gfx0 = Gfx1 = Prom = NULL; + Palette = NULL; + + return 0; +} + + +static void bankp_plot_pixel(INT32 x, INT32 y, INT32 color, UINT8 src, INT32 transp) +{ + if (x > 223 || x < 0 || y > 223 || y < 0) return; + + INT32 pxl = Palette[color | src]; + if (transp && !pxl) return; + + PutPix(pBurnDraw + (y * 224 + x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); +} + + +static void draw_8x8_tiles(UINT8 *gfx_base, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 transp) +{ + UINT8 *src = gfx_base + (code << 6); + + if (flipy) + { + for (INT32 y = sy + 7; y >= sy; y--) + { + if (flipx) + { + for (INT32 x = sx + 7; x >= sx; x--, src++) { + bankp_plot_pixel(x, y, color, *src, transp); + } + } else { + for (INT32 x = sx; x < sx + 8; x++, src++) { + bankp_plot_pixel(x, y, color, *src, transp); + } + } + } + } else { + for (INT32 y = sy; y < sy + 8; y++) + { + if (flipx) + { + for (INT32 x = sx + 7; x >= sx; x--, src++) { + bankp_plot_pixel(x, y, color, *src, transp); + + } + } else { + for (INT32 x = sx; x < sx + 8; x++, src++) { + bankp_plot_pixel(x, y, color, *src, transp); + + } + } + } + } +} + +static void draw_bg_tiles(INT32 prio) +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 code, color, flipx, sx, sy; + + code = Rom[0xf800 + offs] | ((Rom[0xfc00 + offs] & 7) << 8); + color = (Rom[0xfc00 + offs] >> 1) & 0x78; + flipx = Rom[0xfc00 + offs] & 0x08; + + if (flipscreen) { + sx = (~offs << 3) & 0xf8; + sy = (~offs >> 2) & 0xf8; + flipx ^= 0x08; + } else { + sx = ( offs << 3) & 0xf8; + sy = ( offs >> 2) & 0xf8; + } + + draw_8x8_tiles(Gfx1, code, color, sx - 24, sy - 16, flipx, flipscreen, prio); + } +} + +static void draw_fg_tiles(INT32 prio) +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 code, color, flipx, sx, sy; + + code = Rom[0xf000 + offs] | ((Rom[0xf400 + offs] & 3) << 8); + color = (Rom[0xf400 + offs] >> 1) & 0x7c; + flipx = Rom[0xf400 + offs] & 0x04; + + if (flipscreen) { + sx = ((~offs << 3) - scroll_x) & 0xff; + sy = (~offs >> 2) & 0xf8; + flipx ^= 4; + } else { + sx = (( offs << 3) - scroll_x) & 0xff; + sy = ( offs >> 2) & 0xf8; + } + + draw_8x8_tiles(Gfx0, code, color, sx - 24, sy - 16, flipx, flipscreen, prio); + } +} + +static INT32 DrvDraw() +{ + if (priority & 0x02) + { + draw_fg_tiles(0); + draw_bg_tiles(1); + } else { + draw_bg_tiles(0); + draw_fg_tiles(1); + } + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetOpen(0); + ZetRun(2578000 / 60); + if (interrupt_enable) ZetNmi(); + ZetClose(); + + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + SN76496Update(2, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0xe000; + ba.nLen = 0x2000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + SCAN_VAR(scroll_x); + SCAN_VAR(priority); + SCAN_VAR(flipscreen); + SCAN_VAR(interrupt_enable); + } + + return 0; +} + +// Bank Panic + +static struct BurnRomInfo bankpRomDesc[] = { + { "epr-6175.7e", 0x4000, 0x044552b8, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "epr-6174.7f", 0x4000, 0xd29b1598, 1 | BRF_ESS | BRF_PRG }, // 1 + { "epr-6173.7h", 0x4000, 0xb8405d38, 1 | BRF_ESS | BRF_PRG }, // 2 + { "epr-6176.7d", 0x2000, 0xc98ac200, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "epr-6165.5l", 0x2000, 0xaef34a93, 2 | BRF_GRA }, // 4 Playfield #1 chars + { "epr-6166.5k", 0x2000, 0xca13cb11, 2 | BRF_GRA }, // 5 + + { "epr-6172.5b", 0x2000, 0xc4c4878b, 3 | BRF_GRA }, // 6 Playfield #2 chars + { "epr-6171.5d", 0x2000, 0xa18165a1, 3 | BRF_GRA }, // 7 + { "epr-6170.5e", 0x2000, 0xb58aa8fa, 3 | BRF_GRA }, // 8 + { "epr-6169.5f", 0x2000, 0x1aa37fce, 3 | BRF_GRA }, // 9 + { "epr-6168.5h", 0x2000, 0x05f3a867, 3 | BRF_GRA }, // 10 + { "epr-6167.5i", 0x2000, 0x3fa337e1, 3 | BRF_GRA }, // 11 + + { "pr-6177.8a", 0x0020, 0xeb70c5ae, 4 | BRF_GRA }, // 12 (UINT32*)Palette + { "pr-6178.6f", 0x0100, 0x0acca001, 4 | BRF_GRA }, // 13 Charset #1 lut + { "pr-6179.5a", 0x0100, 0xe53bafdb, 4 | BRF_GRA }, // 14 Charset #2 lut + + { "315-5074.2c.bin", 0x025b, 0x2e57bbba, 0 | BRF_OPT }, // 15 + { "315-5073.pal16l4", 0x0001, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, // 16 read protected +}; + +STD_ROM_PICK(bankp) +STD_ROM_FN(bankp) + +struct BurnDriver BurnDrvbankp = { + "bankp", NULL, NULL, NULL, "1984", + "Bank Panic\0", NULL, "[Sanritsu] Sega", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, bankpRomInfo, bankpRomName, NULL, NULL, bankpInputInfo, bankpDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x100, + 224, 224, 4, 3 +}; + +// Combat Hawk + +static struct BurnRomInfo combhRomDesc[] = { + { "epr-10904.7e", 0x4000, 0x4b106335, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "epr-10905.7f", 0x4000, 0xa76fc390, 1 | BRF_ESS | BRF_PRG }, // 1 + { "epr-10906.7h", 0x4000, 0x16d54885, 1 | BRF_ESS | BRF_PRG }, // 2 + { "epr-10903.7d", 0x2000, 0xb7a59cab, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "epr-10914.5l", 0x2000, 0x7d7a2340, 2 | BRF_GRA }, // 4 Playfield #1 chars + { "epr-10913.5k", 0x2000, 0xd5c1a8ae, 2 | BRF_GRA }, // 5 + + { "epr-10907.5b", 0x2000, 0x08e5eea3, 3 | BRF_GRA }, // 6 Playfield #2 chars + { "epr-10908.5d", 0x2000, 0xd9e413f5, 3 | BRF_GRA }, // 7 + { "epr-10909.5e", 0x2000, 0xfec7962c, 3 | BRF_GRA }, // 8 + { "epr-10910.5f", 0x2000, 0x33db0fa7, 3 | BRF_GRA }, // 9 + { "epr-10911.5h", 0x2000, 0x565d9e6d, 3 | BRF_GRA }, // 10 + { "epr-10912.5i", 0x2000, 0xcbe22738, 3 | BRF_GRA }, // 11 + + { "pr-10900.8a", 0x0020, 0xf95fcd66, 4 | BRF_GRA }, // 12 (UINT32*)Palette + { "pr-10901.6f", 0x0100, 0x6fd981c8, 4 | BRF_GRA }, // 13 Charset #1 lut + { "pr-10902.5a", 0x0100, 0x84d6bded, 4 | BRF_GRA }, // 14 Charset #2 lut + + { "315-5074.2c.bin", 0x025b, 0x2e57bbba, 0 | BRF_OPT }, // 15 + { "315-5073.pal16l4", 0x0001, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, // 16 read protected +}; + +STD_ROM_PICK(combh) +STD_ROM_FN(combh) + +struct BurnDriver BurnDrvcombh = { + "combh", NULL, NULL, NULL, "1987", + "Combat Hawk\0", NULL, "Sega / Sanritsu", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, combhRomInfo, combhRomName, NULL, NULL, combhInputInfo, combhDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x100, + 224, 224, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_baraduke.cpp b/src/burn/drivers/misc_pre90s/d_baraduke.cpp new file mode 100644 index 00000000..51dde8fd --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_baraduke.cpp @@ -0,0 +1,967 @@ +// FB Alpha Baraduke driver module +// Based on MAME driver by Manuel Abadia and various others + +#include "tiles_generic.h" +#include "m6800_intf.h" +#include "m6809_intf.h" +#include "namco_snd.h" +#include "burn_led.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvHD63701ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvColPROM; +static UINT8 *DrvHD63701RAM1; +static UINT8 *DrvHD63701RAM; +static UINT8 *DrvWavRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *flipscreen; +static UINT8 *buffer_sprites; +static UINT8 *coin_lockout; +static UINT8 *scroll; +static UINT8 *ip_select; + +static INT32 watchdog; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT8 DrvInputs[8]; + +static INT32 nCyclesDone[2]; + +static struct BurnInputInfo BaradukeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Baraduke) + +static struct BurnDIPInfo BaradukeDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Coin B" }, + {0x10, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Demo Sounds" }, + {0x10, 0x01, 0x04, 0x00, "Off" }, + {0x10, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x10, 0x01, 0x18, 0x00, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x18, 0x08, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x18, 0x18, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x18, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x10, 0x01, 0x60, 0x40, "2" }, + {0x10, 0x01, 0x60, 0x60, "3" }, + {0x10, 0x01, 0x60, 0x20, "4" }, + {0x10, 0x01, 0x60, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Freeze" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Select" }, + {0x11, 0x01, 0x08, 0x08, "Off" }, + {0x11, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x11, 0x01, 0x30, 0x20, "Easy" }, + {0x11, 0x01, 0x30, 0x30, "Normal" }, + {0x11, 0x01, 0x30, 0x10, "Hard" }, + {0x11, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x11, 0x01, 0xc0, 0x80, "Every 10k" }, + {0x11, 0x01, 0xc0, 0xc0, "10k And Every 20k" }, + {0x11, 0x01, 0xc0, 0x40, "Every 20k" }, + {0x11, 0x01, 0xc0, 0x00, "None" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x12, 0x01, 0x02, 0x02, "Upright" }, +// {0x12, 0x01, 0x02, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Baraduke) + +static struct BurnDIPInfo MetrocrsDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x10, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x10, 0x01, 0x04, 0x00, "No" }, + {0x10, 0x01, 0x04, 0x04, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x18, 0x10, "Easy" }, + {0x10, 0x01, 0x18, 0x18, "Normal" }, + {0x10, 0x01, 0x18, 0x08, "Hard" }, + {0x10, 0x01, 0x18, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x10, 0x01, 0x60, 0x00, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x60, 0x20, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x60, 0x60, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x60, 0x40, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x11, 0x01, 0x20, 0x20, "Off" }, + {0x11, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Select" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, + +// {0 , 0xfe, 0 , 2, "Cabinet" }, +// {0x12, 0x01, 0x02, 0x02, "Upright" }, +// {0x12, 0x01, 0x02, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Metrocrs) + +void baraduke_main_write(UINT16 address, UINT8 data) +{ + if (address < 0x2000) { + DrvSprRAM[address & 0x1fff] = data; + if (address == 0x1ff2) buffer_sprites[0] = 1; + return; + } + + if ((address & 0xfc00) == 0x4000) { + namcos1_custom30_write(address & 0x3ff, data); + return; + } + + switch (address) + { + case 0x8000: + watchdog = 0; + return; + + case 0x8800: + M6809SetIRQ(0, M6809_IRQSTATUS_NONE); + return; + + case 0xb000: + case 0xb001: + case 0xb002: + case 0xb004: + case 0xb005: + case 0xb006: + scroll[address & 0x07] = data; + return; + } +} + +UINT8 baraduke_main_read(UINT16 address) +{ + if ((address & 0xfc00) == 0x4000) { + return namcos1_custom30_read(address & 0x3ff); + } + + return 0; +} + +void baraduke_mcu_write(UINT16 address, UINT8 data) +{ + if ((address & 0xffe0) == 0x0000) { + m6803_internal_registers_w(address & 0x1f, data); + return; + } + + if ((address & 0xff80) == 0x0080) { + DrvHD63701RAM1[address & 0x7f] = data; + return; + } + + if ((address & 0xfc00) == 0x1000) { + namcos1_custom30_write(address & 0x3ff, data); + return; + } +} + +UINT8 baraduke_mcu_read(UINT16 address) +{ + if ((address & 0xffe0) == 0x0000) { + return m6803_internal_registers_r(address & 0x1f); + } + + if ((address & 0xff80) == 0x0080) { + return DrvHD63701RAM1[address & 0x7f]; + } + + if (address == 0x1105) { + static INT32 kludge = 0; + kludge++; + return kludge>>4; + } + + if ((address & 0xfc00) == 0x1000) { + return namcos1_custom30_read(address & 0x3ff); + } + + return 0; +} + +void baraduke_mcu_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0x1ff) + { + case HD63701_PORT1: + { + switch (data & 0xe0) { + case 0x60: + *ip_select = data & 0x07; + return; + + case 0xc0: + *coin_lockout = ~data & 0x01; + // coin counters 0 -> data & 0x02, 1 -> data & 0x04 + return; + } + } + return; + + case HD63701_PORT2: + BurnLEDSetStatus(0, data & 0x08); + BurnLEDSetStatus(1, data & 0x10); + return; + } +} + +UINT8 baraduke_mcu_read_port(UINT16 port) +{ + switch (port & 0x1ff) + { + case HD63701_PORT1: + return DrvInputs[*ip_select]; + + case HD63701_PORT2: + return 0xff; + } + + return 0; +} + +static INT32 DrvDoReset(INT32 ClearRAM) +{ + if (ClearRAM) { + memset (AllRam, 0, RamEnd - AllRam); + } + + M6809Open(0); + M6809Reset(); + M6809Close(); + +// HD63701Open(0); + HD63701Reset(); +// HD63701Close(); + + BurnLEDReset(); + + BurnLEDSetFlipscreen(1); + + watchdog = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x010000; + DrvHD63701ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x008000; + DrvGfxROM1 = Next; Next += 0x020000; + DrvGfxROM2 = Next; Next += 0x020000; + + DrvColPROM = Next; Next += 0x001000; + + Palette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + DrvHD63701RAM1 = Next; Next += 0x000080; + DrvHD63701RAM = Next; Next += 0x000800; + + NamcoSoundProm = Next; + DrvWavRAM = Next; Next += 0x000400; + + DrvVidRAM = Next; Next += 0x002000; + DrvTxtRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x002000; + + coin_lockout = Next; Next += 0x000001; + ip_select = Next; Next += 0x000001; + buffer_sprites = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + scroll = Next; Next += 0x000008; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x800; i++) + { + INT32 bit0 = (DrvColPROM[0x800 + i] >> 0) & 0x01; + INT32 bit1 = (DrvColPROM[0x800 + i] >> 1) & 0x01; + INT32 bit2 = (DrvColPROM[0x800 + i] >> 2) & 0x01; + INT32 bit3 = (DrvColPROM[0x800 + i] >> 3) & 0x01; + INT32 r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[0x000 + i] >> 0) & 0x01; + bit1 = (DrvColPROM[0x000 + i] >> 1) & 0x01; + bit2 = (DrvColPROM[0x000 + i] >> 2) & 0x01; + bit3 = (DrvColPROM[0x000 + i] >> 3) & 0x01; + INT32 g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[0x000 + i] >> 4) & 0x01; + bit1 = (DrvColPROM[0x000 + i] >> 5) & 0x01; + bit2 = (DrvColPROM[0x000 + i] >> 6) & 0x01; + bit3 = (DrvColPROM[0x000 + i] >> 7) & 0x01; + INT32 b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = (r << 16) | (g << 8) | b; + } + DrvRecalc = 1; +} + +static void DrvGfxExpand() +{ + for (INT32 i = 0; i < 0x2000; i++) { + DrvGfxROM1[0xa000 + i] = DrvGfxROM1[0x8000 + i] << 4; + DrvGfxROM1[0xc000 + i] = DrvGfxROM1[0x8000 + i]; + DrvGfxROM1[0xe000 + i] = DrvGfxROM1[0x8000 + 1] << 4; + } + + for (INT32 i = 0x10000 - 1; i >= 0; i--) { + DrvGfxROM2[i * 2 + 1] = DrvGfxROM2[i] & 0x0f; + DrvGfxROM2[i * 2 + 0] = DrvGfxROM2[i] >> 4; + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[3] = { 0x8000 * 8, 0, 4 }; + INT32 XOffs0[8] = { 8*8, 8*8+1, 8*8+2, 8*8+3, 0, 1, 2, 3 }; + INT32 XOffs1[8] = { 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3 }; + INT32 YOffs0[8] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }; + INT32 YOffs1[8] = { 0*8, 2*8, 4*8, 6*8, 8*8, 10*8, 12*8, 14*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x2000); + + GfxDecode(0x0200, 2, 8, 8, Plane0 + 1, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x10000); + + GfxDecode(0x0400, 3, 8, 8, Plane0 + 0, XOffs1, YOffs1, 0x080, tmp + 0x0000, DrvGfxROM1 + 0x00000); + GfxDecode(0x0400, 3, 8, 8, Plane0 + 0, XOffs1, YOffs1, 0x080, tmp + 0x4000, DrvGfxROM1 + 0x10000); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 type) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x06000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x08000, 1, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x0c000, 2, 1)) return 1; + + if (BurnLoadRom(DrvHD63701ROM + 0x08000, 3, 1)) return 1; + if (BurnLoadRom(DrvHD63701ROM + 0x0f000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x04000, 7, 1)) return 1; + + if (type == 0) { + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0c000, 12, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 13, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00800, 14, 1)) return 1; + } else { + memset (DrvGfxROM1 + 0x08000, 0xff, 0x4000); + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 9, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00800, 11, 1)) return 1; + } + + DrvGfxExpand(); + DrvGfxDecode(); + DrvPaletteInit(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvSprRAM, 0x0000, 0x1fff, M6809_READ | M6809_FETCH); + M6809MapMemory(DrvSprRAM, 0x0000, 0x1eff, M6809_WRITE); + M6809MapMemory(DrvVidRAM, 0x2000, 0x3fff, M6809_RAM); + M6809MapMemory(DrvTxtRAM, 0x4800, 0x4fff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x06000, 0x6000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(baraduke_main_write); + M6809SetReadByteHandler(baraduke_main_read); + M6809Close(); + + HD63701Init(1); +// HD63701Open(0); + HD63701MapMemory(DrvHD63701ROM + 0x8000, 0x8000, 0xbfff, HD63701_ROM); + HD63701MapMemory(DrvHD63701RAM, 0xc000, 0xc7ff, HD63701_RAM); + HD63701MapMemory(DrvHD63701ROM + 0xf000, 0xf000, 0xffff, HD63701_ROM); + HD63701SetReadByteHandler(baraduke_mcu_read); + HD63701SetWriteByteHandler(baraduke_mcu_write); + HD63701SetReadPortHandler(baraduke_mcu_read_port); + HD63701SetWritePortHandler(baraduke_mcu_write_port); +// HD63701Close(); + + NamcoSoundInit(49152000/2048); + + BurnLEDInit(2, LED_POSITION_BOTTOM_RIGHT, LED_SIZE_5x5, LED_COLOR_GREEN, 100); + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnLEDExit(); + + NamcoSoundExit(); + + M6809Exit(); + HD63701Exit(); + + BurnFree (AllMem); + + NamcoSoundProm = NULL; + + return 0; +} + +static void draw_fg_layer() +{ + for (INT32 y = 0; y < 28; y++) + { + for (INT32 x = 0; x < 36; x++) + { + INT32 col = x - 2; + INT32 row = y + 2; + + INT32 offs = 0; + if (col & 0x20) { + offs = row + ((col & 0x1f) << 5); + } else { + offs = col + (row << 5); + } + + INT32 code = DrvTxtRAM[offs + 0x000]; + INT32 color =(DrvTxtRAM[offs + 0x400] & 0x7f) << 2; + + if (*flipscreen) { + Render8x8Tile_Mask_Clip(pTransDraw, code, 280 - (x * 8), 216 - (y * 8), color, 2, 3, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, x * 8, y * 8, color, 2, 3, 0, DrvGfxROM0); + } + } + } +} + +static void draw_bg_layer(INT32 bank, INT32 prio) +{ + UINT8 *src = DrvVidRAM + bank * 0x1000; + INT32 scrollx = (scroll[bank * 4 + 1] + ((scroll[bank * 4 + 0] & 0x01) << 8) + (bank ? 24 : 26)) & 0x1ff; + INT32 scrolly = (scroll[bank * 4 + 2] + 9) & 0xff; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 color = src[offs * 2 + 1]; + INT32 code = src[offs * 2 + 0] + ((color & 0x03) << 8) + bank * 0x400; + + if (prio) { + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, 280 - sx, 216 - sy, color, 3, 7, 0, DrvGfxROM1); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 7, 0, DrvGfxROM1); + } + } else { + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, 280 - sx, 216 - sy, color, 3, 0, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 3, 0, DrvGfxROM1); + } + } + } +} + +static void draw_sprites(INT32 prio) +{ + UINT8 *src = DrvSprRAM + 0x1800; + INT32 sprite_xoffs = src[0x07f5] - ((src[0x07f4] & 0x01) << 8); + INT32 sprite_yoffs = src[0x07f7]; + + for (INT32 offs = 0; offs < 0x800 - 16; offs += 16, src += 16) + { + INT32 priority = src[10] & 0x01; + + if (priority == prio) + { + INT32 attr1 = src[10]; + INT32 sprite = src[11] << 2; + INT32 color = src[12]; + INT32 sx = src[13] + ((color & 0x01) << 8) + sprite_xoffs; + INT32 attr2 = src[14]; + INT32 sy = (240 - src[15]) - sprite_yoffs; + INT32 flipx = (attr1 & 0x20) >> 5; + INT32 flipy = (attr2 & 0x01) >> 0; + INT32 sizex = (attr1 & 0x80) >> 7; + INT32 sizey = (attr2 & 0x04) >> 2; + + if ((attr1 & 0x10) && !sizex) sprite += 1; + if ((attr2 & 0x10) && !sizey) sprite += 2; + + sy -= 16 * sizey; + + if (*flipscreen) + { + sx = 499 - 16 * sizex - sx; + sy = 240 - 16 * sizey - sy; + flipx ^= 1; + flipy ^= 1; + } + + for (INT32 y = 0;y <= sizey;y++) + { + for (INT32 x = 0;x <= sizex;x++) + { + INT32 code = sprite + (y ^ (sizey * flipy)) * 2 + (x ^ (sizex * flipx)); + code &= 0x1ff; + + if (flipy) { + if(flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, -71 + ((sx + 16 * x) & 0x1ff), 1 + ((sy + 16 * y) & 0xff), color >> 1, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, -71 + ((sx + 16 * x) & 0x1ff), 1 + ((sy + 16 * y) & 0xff), color >> 1, 4, 0x0f, 0, DrvGfxROM2); + } + } else { + if(flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, -71 + ((sx + 16 * x) & 0x1ff), 1 + ((sy + 16 * y) & 0xff), color >> 1, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, -71 + ((sx + 16 * x) & 0x1ff), 1 + ((sy + 16 * y) & 0xff), color >> 1, 4, 0x0f, 0, DrvGfxROM2); + } + } + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i++) { + INT32 p = Palette[i]; + DrvPalette[i] = BurnHighCol(p >> 16, p >> 8, p, 0); + } + DrvRecalc = 0; + } + + *flipscreen = DrvSprRAM[0x1ff6] & 0x01; + + BurnLEDSetFlipscreen(*flipscreen); + + INT32 priority = ((scroll[0] & 0x0e) == 0x0c) ? 1 : 0; + + draw_bg_layer(priority ^ 0, 0); + draw_sprites(0); + draw_bg_layer(priority ^ 1, 1); + draw_sprites(1); + + draw_fg_layer(); + + BurnTransferCopy(DrvPalette); + + BurnLEDRender(); + + return 0; +} + +static void DrvSpriteBuffer() +{ + if (buffer_sprites[0] == 0) return; + + for (INT32 i = 0; i < 0x800; i += 16) { + memcpy (DrvSprRAM + 0x180a + i, DrvSprRAM + 0x1804 + i, 6); + } + + buffer_sprites[0] = 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(1); + } + + watchdog++; + if (watchdog > 180) { + DrvDoReset(0); + } + + { + memset (DrvInputs, 0xff, 8); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[4] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[6] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[0] = ((DrvDips[0] & 0xf8) >> 3); + DrvInputs[1] = ((DrvDips[0] & 0x07) << 2) | ((DrvDips[1] & 0xc0) >> 6); + DrvInputs[2] = ((DrvDips[1] & 0x3e) >> 1); + DrvInputs[3] = (DrvDips[2] & 0x0f) | ((DrvDips[0] & 0x01) << 4); + + if (*coin_lockout) DrvInputs[4] |= 0x06; + } + + M6809NewFrame(); + HD63701NewFrame(); + + INT32 nInterleave = 100; // 1000? + INT32 nCyclesTotal[2] = { 1536000 / 60, 6144000 / 60 }; + //INT32 nCyclesDone[2] = { 0, 0 }; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nNext; + + M6809Open(0); + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += M6809Run(nNext - nCyclesDone[0]); + if (i == (nInterleave - 1)) { + M6809SetIRQ(0, M6809_IRQSTATUS_ACK); + } + M6809Close(); + + // HD63701Open(0); + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += HD63701Run(nNext - nCyclesDone[1]); + if (i == (nInterleave - 1)) { + HD63701SetIRQ(0, M6800_IRQSTATUS_AUTO); + } + // HD63701Close(); + } + + if (pBurnSoundOut) { + NamcoSoundUpdate(pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + DrvSpriteBuffer(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + return 1; // Broken :( + + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6809Scan(nAction); + HD63701Scan(nAction); + + NamcoSoundScan(nAction, pnMin); + + BurnLEDScan(nAction, pnMin); + } + + return 0; +} + + +// Alien Sector + +static struct BurnRomInfo aliensecRomDesc[] = { + { "bd1_3.9c", 0x2000, 0xea2ea790, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "bd2_1.9a", 0x4000, 0x9a0a9a87, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bd2_2.9b", 0x4000, 0x383e5458, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "bd1_4.3b", 0x4000, 0xabda0fe7, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "bd1_5.3j", 0x2000, 0x706b7fee, 3 | BRF_GRA }, // 5 Characters + + { "bd2_8.4p", 0x4000, 0x432bd7d9, 4 | BRF_GRA }, // 6 Background Tiles + { "bd1_7.4n", 0x4000, 0x0d7ebec9, 4 | BRF_GRA }, // 7 + { "bd2_6.4m", 0x4000, 0xf4c1df60, 4 | BRF_GRA }, // 8 + + { "bd1_9.8k", 0x4000, 0x87a29acc, 5 | BRF_GRA }, // 9 Sprites + { "bd1_10.8l", 0x4000, 0x72b6d20c, 5 | BRF_GRA }, // 10 + { "bd1_11.8m", 0x4000, 0x3076af9c, 5 | BRF_GRA }, // 11 + { "bd1_12.8n", 0x4000, 0x8b4c09a3, 5 | BRF_GRA }, // 12 + + { "bd1-1.1n", 0x0800, 0x0d78ebc6, 6 | BRF_GRA }, // 13 Color PROMs + { "bd1-2.2m", 0x0800, 0x03f7241f, 6 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(aliensec) +STD_ROM_FN(aliensec) + +static INT32 AlienInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvAliensec = { + "aliensec", NULL, NULL, NULL, "1985", + "Alien Sector\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, aliensecRomInfo, aliensecRomName, NULL, NULL, BaradukeInputInfo, BaradukeDIPInfo, + AlienInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Baraduke + +static struct BurnRomInfo baradukeRomDesc[] = { + { "bd1_3.9c", 0x2000, 0xea2ea790, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "bd1_1.9a", 0x4000, 0x4e9f2bdc, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bd1_2.9b", 0x4000, 0x40617fcd, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "bd1_4b.3b", 0x4000, 0xa47ecd32, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "bd1_5.3j", 0x2000, 0x706b7fee, 3 | BRF_GRA }, // 5 Characters + + { "bd1_8.4p", 0x4000, 0xb0bb0710, 4 | BRF_GRA }, // 6 Background Tiles + { "bd1_7.4n", 0x4000, 0x0d7ebec9, 4 | BRF_GRA }, // 7 + { "bd1_6.4m", 0x4000, 0xe5da0896, 4 | BRF_GRA }, // 8 + + { "bd1_9.8k", 0x4000, 0x87a29acc, 5 | BRF_GRA }, // 9 Sprites + { "bd1_10.8l", 0x4000, 0x72b6d20c, 5 | BRF_GRA }, // 10 + { "bd1_11.8m", 0x4000, 0x3076af9c, 5 | BRF_GRA }, // 11 + { "bd1_12.8n", 0x4000, 0x8b4c09a3, 5 | BRF_GRA }, // 12 + + { "bd1-1.1n", 0x0800, 0x0d78ebc6, 6 | BRF_GRA }, // 13 Color PROMs + { "bd1-2.2m", 0x0800, 0x03f7241f, 6 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(baraduke) +STD_ROM_FN(baraduke) + +struct BurnDriver BurnDrvBaraduke = { + "baraduke", "aliensec", NULL, NULL, "1985", + "Baraduke\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, baradukeRomInfo, baradukeRomName, NULL, NULL, BaradukeInputInfo, BaradukeDIPInfo, + AlienInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Metro-Cross (set 1) + +static struct BurnRomInfo metrocrsRomDesc[] = { + { "mc1-3.9c", 0x2000, 0x3390b33c, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "mc1-1.9a", 0x4000, 0x10b0977e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mc1-2.9b", 0x4000, 0x5c846f35, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "mc1-4.3b", 0x2000, 0x9c88f898, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "mc1-5.3j", 0x2000, 0x9b5ea33a, 3 | BRF_GRA }, // 5 Characters + + { "mc1-7.4p", 0x4000, 0xc9dfa003, 4 | BRF_GRA }, // 6 Background Tiles + { "mc1-6.4n", 0x4000, 0x9686dc3c, 4 | BRF_GRA }, // 7 + + { "mc1-8.8k", 0x4000, 0x265b31fa, 5 | BRF_GRA }, // 8 Sprites + { "mc1-9.8l", 0x4000, 0x541ec029, 5 | BRF_GRA }, // 9 + + { "mc1-1.1n", 0x0800, 0x32a78a8b, 6 | BRF_GRA }, // 10 Color PROMs + { "mc1-2.2m", 0x0800, 0x6f4dca7b, 6 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(metrocrs) +STD_ROM_FN(metrocrs) + +static INT32 MetroInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvMetrocrs = { + "metrocrs", NULL, NULL, NULL, "1985", + "Metro-Cross (set 1)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, metrocrsRomInfo, metrocrsRomName, NULL, NULL, BaradukeInputInfo, MetrocrsDIPInfo, + MetroInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; + + +// Metro-Cross (set 2) + +static struct BurnRomInfo metrocrsaRomDesc[] = { + { "mc2-3.9b", 0x2000, 0xffe08075, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "mc2-1.9a", 0x4000, 0x05a239ea, 1 | BRF_PRG | BRF_ESS }, // 1 + { "mc2-2.9a", 0x4000, 0xdb9b0e6d, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "mc1-4.3b", 0x2000, 0x9c88f898, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "mc1-5.3j", 0x2000, 0x9b5ea33a, 3 | BRF_GRA }, // 5 Characters + + { "mc1-7.4p", 0x4000, 0xc9dfa003, 4 | BRF_GRA }, // 6 Background Tiles + { "mc1-6.4n", 0x4000, 0x9686dc3c, 4 | BRF_GRA }, // 7 + + { "mc1-8.8k", 0x4000, 0x265b31fa, 5 | BRF_GRA }, // 8 Sprites + { "mc1-9.8l", 0x4000, 0x541ec029, 5 | BRF_GRA }, // 9 + + { "mc1-1.1n", 0x0800, 0x32a78a8b, 6 | BRF_GRA }, // 10 Color PROMs + { "mc1-2.2m", 0x0800, 0x6f4dca7b, 6 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(metrocrsa) +STD_ROM_FN(metrocrsa) + +struct BurnDriver BurnDrvMetrocrsa = { + "metrocrsa", "metrocrs", NULL, NULL, "1985", + "Metro-Cross (set 2)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, metrocrsaRomInfo, metrocrsaRomName, NULL, NULL, BaradukeInputInfo, MetrocrsDIPInfo, + MetroInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_bionicc.cpp b/src/burn/drivers/misc_pre90s/d_bionicc.cpp new file mode 100644 index 00000000..00e495dd --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_bionicc.cpp @@ -0,0 +1,945 @@ +// FB Alpha Bionic Commando driver module +// Based on MAME driver by Steven Frew, Phil Stroffolino, and Paul Leaman + +#include "tiles_generic.h" +#include "burn_ym2151.h" + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; +static UINT8 DrvDips[2]; + +static UINT8 *Mem, *MemEnd; +static UINT8 *AllRam, *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM0; +static UINT8 *DrvTextRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT8 *DrvPalRAM; +static UINT8 *Drv68KRAM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSprBuf; + +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + + +static UINT8 *soundlatch; + +static INT32 flipscreen; + +static INT32 fg_scroll_x; +static INT32 fg_scroll_y; +static INT32 bg_scroll_x; +static INT32 bg_scroll_y; + +static INT32 fg_enable; +static INT32 bg_enable; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 5, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p1 right" }, + {"P1 Down", BIT_DIGITAL , DrvJoy2 + 4, "p1 down", }, + {"P1 Up", BIT_DIGITAL , DrvJoy2 + 5, "p1 up", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 1, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 4, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 2, "p2 right" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 4, "p2 down", }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 5, "p2 up", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 1, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 0, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8 , "Coin_A" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credit " }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 1 Credit " }, + {0x11, 0x01, 0x07, 0x02, "2 Coins 1 Credit " }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credit " }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin_B" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credit " }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 1 Credit " }, + {0x11, 0x01, 0x38, 0x10, "2 Coins 1 Credit " }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credit " }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x04, 0x04, "Upright" }, + {0x12, 0x01, 0x04, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus_Life" }, + {0x12, 0x01, 0x18, 0x18, "20K, 40K, every 60K" }, + {0x12, 0x01, 0x18, 0x10, "30K, 50K, every 70K" }, + {0x12, 0x01, 0x18, 0x08, "20K and 60K only" }, + {0x12, 0x01, 0x18, 0x00, "30K and 70K only" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x60, 0x40, "Easy" }, + {0x12, 0x01, 0x60, 0x60, "Medium" }, + {0x12, 0x01, 0x60, 0x20, "Hard" }, + {0x12, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +static void bionicc_palette_write(INT32 offset) +{ + offset >>= 1; + + INT32 r, g, b, bright; + INT32 data = *((UINT16*)(DrvPalRAM + (offset << 1))); + + bright = (data&0x0f); + + r = ((data>>12)&0x0f) * 0x11; + g = ((data>>8 )&0x0f) * 0x11; + b = ((data>>4 )&0x0f) * 0x11; + + if ((bright & 0x08) == 0) + { + r = r * (0x07 + bright) / 0x0e; + g = g * (0x07 + bright) / 0x0e; + b = b * (0x07 + bright) / 0x0e; + } + + Palette[offset] = (r << 16) | (g << 8) | b; + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +void __fastcall bionicc_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfffff800) == 0xff8000) { + address &= 0x7ff; + + DrvPalRAM[address ^ 1] = data; + + bionicc_palette_write(address); + + return; + } + + switch (address) + { + case 0xfe4000: + case 0xfe4001: + flipscreen = data & 0x01; + fg_enable = data & 0x10; + bg_enable = data & 0x20; + return; + } +} + +void __fastcall bionicc_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffff800) == 0xff8000) { + address &= 0x7ff; + + *((UINT16*)(DrvPalRAM + address)) = data; + + bionicc_palette_write(address); + + return; + } + + switch (address) + { + case 0xfe8010: + fg_scroll_x = data & 0x3ff; + return; + + case 0xfe8012: + fg_scroll_y = data & 0x3ff; + return; + + case 0xfe8014: + bg_scroll_x = data & 0x1ff; + return; + + case 0xfe8016: + bg_scroll_y = data & 0x1ff; + return; + + case 0xfe801a: + UINT16 *inp = (UINT16*)(Drv68KRAM1 + 0x3ffa); + inp[0] = (DrvInputs[0] >> 4) ^ 0x0f; + inp[1] = DrvInputs[2] ^ 0xff; + inp[2] = DrvInputs[1] ^ 0xff; + return; + } +} + +UINT8 __fastcall bionicc_read_byte(UINT32 address) +{ + switch (address) + { + case 0xfe4000: + return DrvInputs[0]; + + case 0xfe4001: + return 0xff; + + case 0xfe4002: + return DrvDips[0]; + + case 0xfe4003: + return DrvDips[1]; + } + + return 0; +} + +UINT16 __fastcall bionicc_read_word(UINT32 address) +{ + switch (address) + { + case 0xfe4000: + return 0x00ff | (DrvInputs[0] << 8); + + case 0xfe4002: + return DrvDips[0] | (DrvDips[1] << 8); + } + + return 0; +} + +UINT8 __fastcall bionicc_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8001: + return BurnYM2151ReadStatus(); + + case 0xa000: + return *soundlatch; + } + + return 0; +} + +void __fastcall bionicc_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8000: + BurnYM2151SelectRegister(data); + return; + + case 0x8001: + BurnYM2151WriteRegister(data); + return; + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KROM = Next; Next += 0x0040000; + DrvZ80ROM = Next; Next += 0x0008000; + + DrvGfxROM0 = Next; Next += 0x0020000; + DrvGfxROM1 = Next; Next += 0x0020000; + DrvGfxROM2 = Next; Next += 0x0080000; + DrvGfxROM3 = Next; Next += 0x0080000; + + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM0 = Next; Next += 0x0004000; + Drv68KRAM1 = Next; Next += 0x0004000; + DrvPalRAM = Next; Next += 0x0000800; + DrvTextRAM = Next; Next += 0x0001000; + DrvVidRAM0 = Next; Next += 0x0004000; + DrvVidRAM1 = Next; Next += 0x0004000; + + DrvSprBuf = Next; Next += 0x0000500; + + DrvZ80RAM = Next; Next += 0x0000800; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + fg_scroll_x = 0; + fg_scroll_y = 0; + bg_scroll_x = 0; + bg_scroll_y = 0; + + soundlatch = Drv68KRAM1 + 0x3ff8; + flipscreen = 0; + + fg_enable = 0; + bg_enable = 0; + + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + static INT32 CharPlanes[2] = { 0x000004, 0x000000 }; + static INT32 Tile0Planes[4] = { 0x040004, 0x040000, 0x000004, 0x000000 }; + static INT32 Tile1Planes[4] = { 0x100004, 0x100000, 0x000004, 0x000000 }; + static INT32 SpriPlanes[4] = { 0x180000, 0x100000, 0x080000, 0x000000 }; + static INT32 CharXOffsets[16] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x100, 0x101, 0x102, 0x103, 0x108, 0x109, 0x10a, 0x10b }; + static INT32 SpriXOffsets[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087 }; + static INT32 CharYOffsets[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + static INT32 SpriYOffsets[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x00400, 2, 8, 8, CharPlanes, CharXOffsets, CharYOffsets, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x10000); + + GfxDecode(0x00800, 4, 8, 8, Tile0Planes, CharXOffsets, CharYOffsets, 0x080, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x00800, 4, 16, 16, Tile1Planes, CharXOffsets, CharYOffsets, 0x200, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x40000); + + GfxDecode(0x00800, 4, 16, 16, SpriPlanes, SpriXOffsets, SpriYOffsets, 0x100, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x20001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x20000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x0000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x8000, 7, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x8000, i + 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + i * 0x8000, i + 16, 1)) return 1; + } + + if (DrvGfxDecode()) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRAM0, 0xfe0000, 0xfe3fff, SM_RAM); + SekMapMemory(DrvTextRAM, 0xfec000, 0xfecfff, SM_RAM); + SekMapMemory(DrvVidRAM0, 0xff0000, 0xff3fff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0xff4000, 0xff7fff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xff8000, 0xff87ff, SM_ROM); + SekMapMemory(Drv68KRAM1, 0xffc000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, bionicc_read_byte); + SekSetReadWordHandler(0, bionicc_read_word); + SekSetWriteByteHandler(0, bionicc_write_byte); + SekSetWriteWordHandler(0, bionicc_write_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(bionicc_sound_write); + ZetSetReadHandler(bionicc_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 100.0); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2151Exit(); + SekExit(); + ZetExit(); + + BurnFree (Mem); + + GenericTilesExit(); + + return 0; +} + +static void draw_foreground(INT32 priority) +{ + UINT16 *vidram = (UINT16*)DrvVidRAM0; + + for (INT32 offs = 0; offs < 0x4000 / 4; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sx -= fg_scroll_x; + sy -= fg_scroll_y; + + if (sx < -15) sx += 0x400; + if (sy < -15) sy += 0x400; + if (sx < -15 || sx > 255 || sy < 1 || sy > 239) continue; + sy -= 16; + + INT32 attr = vidram[(offs << 1) | 1]; + INT32 code = (vidram[offs << 1] & 0xff) | ((attr & 0x07) << 8); + INT32 color = (attr & 0x18) >> 3; + INT32 flipx = attr & 0x80; + INT32 flipy = attr & 0x40; + INT32 prior = (attr & 0x20) >> 5; + + if ((attr & 0xc0) == 0xc0) { + flipx = 0; + flipy = 0; + prior = 2; + } + + if (prior != priority) continue; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + memset (pTransDraw, 0, nScreenHeight * nScreenWidth * 2); + + if (fg_enable) { + draw_foreground(2); + } + + if (bg_enable) + { + UINT16 *vidram = (UINT16*)DrvVidRAM1; + + for (INT32 offs = 0; offs < 0x4000 / 4; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= bg_scroll_x; + sy -= bg_scroll_y; + + if (sx < -7) sx += 0x200; + if (sy < -7) sy += 0x200; + if (sy < 9 || sy > 239 || sx < -7 || sx > 255) continue; + sy -= 16; + + INT32 attr = vidram[(offs << 1) | 1]; + INT32 code = (vidram[offs << 1] & 0xff) | ((attr & 0x07) << 8); + INT32 color = (attr & 0x18) >> 3; + INT32 flipx = attr & 0x80; + INT32 flipy = attr & 0x40; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x000, DrvGfxROM1); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x000, DrvGfxROM1); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x000, DrvGfxROM1); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x000, DrvGfxROM1); + } + } + } + } + + if (fg_enable) { + draw_foreground(0); + } + + { + UINT16 *vidram = (UINT16*)DrvSprBuf; + + for (INT32 offs = (0x500-8)/2; offs >= 0; offs -= 4) + { + INT32 code = vidram[offs] & 0x7ff; + + if (code != 0x7ff) + { + INT32 attr = vidram[offs+1]; + INT32 color = (attr&0x3C)>>2; + INT32 flipx = attr & 0x02; + INT32 sx = (INT16)vidram[offs+3]; + INT32 sy = (INT16)vidram[offs+2]; + if(sy>512-16) sy-=512; + + if (sx < -15 || sx > 255 || sy < 1 || sy > 239) continue; + + sy -= 16; + + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM3); + } + } + } + } + + if (fg_enable) { + draw_foreground(1); + } + + { + UINT16 *vidram = (UINT16*)DrvTextRAM; + + for (INT32 offs = 0; offs < 0x800 / 2; offs++) + { + INT32 sx = (offs << 3) & 0xf8; + INT32 sy = (offs >> 2) & 0xf8; + sy -= 16; + if (sy < 0 || sy > 223) continue; + + INT32 attr = vidram[offs + 0x400]; + INT32 code = (vidram[offs] & 0xff) | ((attr & 0xc0) << 2); + INT32 color = attr & 0x3f; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 3, 0x300, DrvGfxROM0); + } + } + + if (flipscreen) { + INT32 nSize = (nScreenWidth * nScreenHeight) - 1; + for (INT32 i = 0; i < nSize >> 1; i++) { + INT32 n = pTransDraw[i]; + pTransDraw[i] = pTransDraw[nSize - i]; + pTransDraw[nSize - i] = n; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 8; + INT32 nTotalCycles[2] = { 12000000 / 60, 3579545 / 60 }; + + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + nTotalCycles[0] -= SekRun(nTotalCycles[0] / (nInterleave - i)); + if (i != (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + nTotalCycles[1] -= ZetRun(nTotalCycles[1] / (nInterleave - i)); + if ((i & 1) == 1) ZetNmi(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + // Lag sprites 1 frame + memcpy (DrvSprBuf, Drv68KRAM0 + 0x800, 0x500); + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029682; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + + SCAN_VAR(fg_scroll_x); + SCAN_VAR(fg_scroll_y); + SCAN_VAR(bg_scroll_x); + SCAN_VAR(bg_scroll_y); + SCAN_VAR(fg_enable); + SCAN_VAR(bg_enable); + SCAN_VAR(flipscreen); + } + + return 0; +} + +// Bionic Commando (Euro) + +static struct BurnRomInfo bioniccRomDesc[] = { + { "tse_02.1a", 0x10000, 0xe4aeefaa, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tse_04.1b", 0x10000, 0xd0c8ec75, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tse_03.2a", 0x10000, 0xb2ac0a45, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tse_05.2b", 0x10000, 0xa79cb406, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ts_01b.4e", 0x08000, 0xa9a6cafa, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "tsu_08.8l", 0x08000, 0x9bf0b7a2, 3 | BRF_GRA }, // 5 Characters + + { "tsu_07.5l", 0x08000, 0x9469efa4, 4 | BRF_GRA }, // 6 Background Tiles + { "tsu_06.4l", 0x08000, 0x40bf0eb4, 4 | BRF_GRA }, // 7 + + { "ts_12.17f", 0x08000, 0xe4b4619e, 5 | BRF_GRA }, // 8 Foreground Tiles + { "ts_11.15f", 0x08000, 0xab30237a, 5 | BRF_GRA }, // 9 + { "ts_17.17g", 0x08000, 0xdeb657e4, 5 | BRF_GRA }, // 10 + { "ts_16.15g", 0x08000, 0xd363b5f9, 5 | BRF_GRA }, // 11 + { "ts_13.18f", 0x08000, 0xa8f5a004, 5 | BRF_GRA }, // 12 + { "ts_18.18g", 0x08000, 0x3b36948c, 5 | BRF_GRA }, // 13 + { "ts_23.18j", 0x08000, 0xbbfbe58a, 5 | BRF_GRA }, // 14 + { "ts_24.18k", 0x08000, 0xf156e564, 5 | BRF_GRA }, // 15 + + { "tse_10.13f", 0x08000, 0xd28eeacc, 6 | BRF_GRA }, // 16 Sprites + { "tsu_09.11f", 0x08000, 0x6a049292, 6 | BRF_GRA }, // 17 + { "tse_15.13g", 0x08000, 0x9b5593c0, 6 | BRF_GRA }, // 18 + { "tsu_14.11g", 0x08000, 0x46b2ad83, 6 | BRF_GRA }, // 19 + { "tse_20.13j", 0x08000, 0xb03db778, 6 | BRF_GRA }, // 20 + { "tsu_19.11j", 0x08000, 0xb5c82722, 6 | BRF_GRA }, // 21 + { "tse_22.17j", 0x08000, 0xd4dedeb3, 6 | BRF_GRA }, // 22 + { "tsu_21.15j", 0x08000, 0x98777006, 6 | BRF_GRA }, // 23 + + { "63s141.18f", 0x00100, 0xb58d0023, 0 | BRF_OPT }, // 24 Priority (not used) + + { "c8751h-88", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(bionicc) +STD_ROM_FN(bionicc) + +struct BurnDriver BurnDrvbionicc = { + "bionicc", NULL, NULL, NULL, "1987", + "Bionic Commando (Euro)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, bioniccRomInfo, bioniccRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Bionic Commando (US set 1) + +static struct BurnRomInfo bionicc1RomDesc[] = { + { "tsu_02b.1a", 0x10000, 0xcf965a0a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tsu_04b.1b", 0x10000, 0xc9884bfb, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tsu_03b.2a", 0x10000, 0x4e157ae2, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tsu_05b.2b", 0x10000, 0xe66ca0f9, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ts_01b.4e", 0x08000, 0xa9a6cafa, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "tsu_08.8l", 0x08000, 0x9bf0b7a2, 3 | BRF_GRA }, // 5 Characters + + { "tsu_07.5l", 0x08000, 0x9469efa4, 4 | BRF_GRA }, // 6 Background Tiles + { "tsu_06.4l", 0x08000, 0x40bf0eb4, 4 | BRF_GRA }, // 7 + + { "ts_12.17f", 0x08000, 0xe4b4619e, 5 | BRF_GRA }, // 8 Foreground Tiles + { "ts_11.15f", 0x08000, 0xab30237a, 5 | BRF_GRA }, // 9 + { "ts_17.17g", 0x08000, 0xdeb657e4, 5 | BRF_GRA }, // 10 + { "ts_16.15g", 0x08000, 0xd363b5f9, 5 | BRF_GRA }, // 11 + { "ts_13.18f", 0x08000, 0xa8f5a004, 5 | BRF_GRA }, // 12 + { "ts_18.18g", 0x08000, 0x3b36948c, 5 | BRF_GRA }, // 13 + { "ts_23.18j", 0x08000, 0xbbfbe58a, 5 | BRF_GRA }, // 14 + { "ts_24.18k", 0x08000, 0xf156e564, 5 | BRF_GRA }, // 15 + + { "tsu_10.13f", 0x08000, 0xf1180d02, 6 | BRF_GRA }, // 16 Sprites + { "tsu_09.11f", 0x08000, 0x6a049292, 6 | BRF_GRA }, // 17 + { "tsu_15.13g", 0x08000, 0xea912701, 6 | BRF_GRA }, // 18 + { "tsu_14.11g", 0x08000, 0x46b2ad83, 6 | BRF_GRA }, // 19 + { "tsu_20.13j", 0x08000, 0x17857ad2, 6 | BRF_GRA }, // 20 + { "tsu_19.11j", 0x08000, 0xb5c82722, 6 | BRF_GRA }, // 21 + { "tsu_22.17j", 0x08000, 0x5ee1ae6a, 6 | BRF_GRA }, // 22 + { "tsu_21.15j", 0x08000, 0x98777006, 6 | BRF_GRA }, // 23 + + { "63s141.18f", 0x00100, 0xb58d0023, 0 | BRF_OPT }, // 24 Priority (not used) + + { "c8751h-88", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(bionicc1) +STD_ROM_FN(bionicc1) + +struct BurnDriver BurnDrvbionicc1 = { + "bionicc1", "bionicc", NULL, NULL, "1987", + "Bionic Commando (US set 1)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, bionicc1RomInfo, bionicc1RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Bionic Commando (US set 2) + +static struct BurnRomInfo bionicc2RomDesc[] = { + { "tsu_02.1a", 0x10000, 0xf2528f08, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tsu_04.1b", 0x10000, 0x38b1c7e4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tsu_03.2a", 0x10000, 0x72c3b76f, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tsu_05.2b", 0x10000, 0x70621f83, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ts_01b.4e", 0x08000, 0xa9a6cafa, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "tsu_08.8l", 0x08000, 0x9bf0b7a2, 3 | BRF_GRA }, // 5 Characters + + { "tsu_07.5l", 0x08000, 0x9469efa4, 4 | BRF_GRA }, // 6 Background Tiles + { "tsu_06.4l", 0x08000, 0x40bf0eb4, 4 | BRF_GRA }, // 7 + + { "ts_12.17f", 0x08000, 0xe4b4619e, 5 | BRF_GRA }, // 8 Foreground Tiles + { "ts_11.15f", 0x08000, 0xab30237a, 5 | BRF_GRA }, // 9 + { "ts_17.17g", 0x08000, 0xdeb657e4, 5 | BRF_GRA }, // 10 + { "ts_16.15g", 0x08000, 0xd363b5f9, 5 | BRF_GRA }, // 11 + { "ts_13.18f", 0x08000, 0xa8f5a004, 5 | BRF_GRA }, // 12 + { "ts_18.18g", 0x08000, 0x3b36948c, 5 | BRF_GRA }, // 13 + { "ts_23.18j", 0x08000, 0xbbfbe58a, 5 | BRF_GRA }, // 14 + { "ts_24.18k", 0x08000, 0xf156e564, 5 | BRF_GRA }, // 15 + + { "tsu_10.13f", 0x08000, 0xf1180d02, 6 | BRF_GRA }, // 16 Sprites + { "tsu_09.11f", 0x08000, 0x6a049292, 6 | BRF_GRA }, // 17 + { "tsu_15.13g", 0x08000, 0xea912701, 6 | BRF_GRA }, // 18 + { "tsu_14.11g", 0x08000, 0x46b2ad83, 6 | BRF_GRA }, // 19 + { "tsu_20.13j", 0x08000, 0x17857ad2, 6 | BRF_GRA }, // 20 + { "tsu_19.11j", 0x08000, 0xb5c82722, 6 | BRF_GRA }, // 21 + { "tsu_22.17j", 0x08000, 0x5ee1ae6a, 6 | BRF_GRA }, // 22 + { "tsu_21.15j", 0x08000, 0x98777006, 6 | BRF_GRA }, // 23 + + { "63s141.18f", 0x00100, 0xb58d0023, 0 | BRF_OPT }, // 24 Priority (not used) + + { "c8751h-88", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(bionicc2) +STD_ROM_FN(bionicc2) + +struct BurnDriver BurnDrvbionicc2 = { + "bionicc2", "bionicc", NULL, NULL, "1987", + "Bionic Commando (US set 2)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, bionicc2RomInfo, bionicc2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Top Secret (Japan) + +static struct BurnRomInfo topsecrtRomDesc[] = { + { "ts_02.1a", 0x10000, 0xb2fe1ddb, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ts_04.1b", 0x10000, 0x427a003d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ts_03.2a", 0x10000, 0x27f04bb6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ts_05.2b", 0x10000, 0xc01547b1, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "ts_01.4e", 0x08000, 0x8ea07917, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "ts_08.8l", 0x08000, 0x96ad379e, 3 | BRF_GRA }, // 5 Characters + + { "ts_07.5l", 0x08000, 0x25cdf8b2, 4 | BRF_GRA }, // 6 Background Tiles + { "ts_06.4l", 0x08000, 0x314fb12d, 4 | BRF_GRA }, // 7 + + { "ts_12.17f", 0x08000, 0xe4b4619e, 5 | BRF_GRA }, // 8 Foreground Tiles + { "ts_11.15f", 0x08000, 0xab30237a, 5 | BRF_GRA }, // 9 + { "ts_17.17g", 0x08000, 0xdeb657e4, 5 | BRF_GRA }, // 10 + { "ts_16.15g", 0x08000, 0xd363b5f9, 5 | BRF_GRA }, // 11 + { "ts_13.18f", 0x08000, 0xa8f5a004, 5 | BRF_GRA }, // 12 + { "ts_18.18g", 0x08000, 0x3b36948c, 5 | BRF_GRA }, // 13 + { "ts_23.18j", 0x08000, 0xbbfbe58a, 5 | BRF_GRA }, // 14 + { "ts_24.18k", 0x08000, 0xf156e564, 5 | BRF_GRA }, // 15 + + { "ts_10.13f", 0x08000, 0xc3587d05, 6 | BRF_GRA }, // 16 Sprites + { "ts_09.11f", 0x08000, 0x6b63eef2, 6 | BRF_GRA }, // 17 + { "ts_15.13g", 0x08000, 0xdb8cebb0, 6 | BRF_GRA }, // 18 + { "ts_14.11g", 0x08000, 0xe2e41abf, 6 | BRF_GRA }, // 19 + { "ts_20.13j", 0x08000, 0xbfd1a695, 6 | BRF_GRA }, // 20 + { "ts_19.11j", 0x08000, 0x928b669e, 6 | BRF_GRA }, // 21 + { "ts_22.17j", 0x08000, 0x3fe05d9a, 6 | BRF_GRA }, // 22 + { "ts_21.15j", 0x08000, 0x27a9bb7c, 6 | BRF_GRA }, // 23 + + { "63s141.18f", 0x00100, 0xb58d0023, 0 | BRF_OPT }, // 24 Priority (not used) + + { "c8751h-88", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(topsecrt) +STD_ROM_FN(topsecrt) + +struct BurnDriver BurnDrvtopsecrt = { + "topsecrt", "bionicc", NULL, NULL, "1987", + "Top Secret (Japan)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, topsecrtRomInfo, topsecrtRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_blktiger.cpp b/src/burn/drivers/misc_pre90s/d_blktiger.cpp new file mode 100644 index 00000000..055bc4dd --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_blktiger.cpp @@ -0,0 +1,1062 @@ +// FB Alpha Black Tiger driver module +// Based on MAME driver by Paul Leaman + +#include "tiles_generic.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvTxRAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *DrvScreenLayout; +static UINT8 *DrvBgEnable; +static UINT8 *DrvFgEnable; +static UINT8 *DrvSprEnable; +static UINT8 *DrvVidBank; +static UINT8 *DrvRomBank; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT8 *coin_lockout; +static UINT8 *watchdog; + +static UINT16 *DrvScrollx; +static UINT16 *DrvScrolly; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static INT32 nCyclesTotal[2]; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Service", BIT_DIGITAL , DrvJoy1 + 5, "service" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0x01, 0x01, NULL }, + + {0x12, 0xfe, 0, 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "4 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "3 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x02, "2 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + + {0x12, 0xfe, 0, 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "4 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "3 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x10, "2 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + + {0x12, 0xfe, 0, 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0x12, 0xfe, 0, 2, "Test" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0x13, 0xfe, 0, 8, "Difficulty" }, + {0x13, 0x01, 0x1c, 0x1c, "1 (Easiest)" }, + {0x13, 0x01, 0x1c, 0x18, "2" }, + {0x13, 0x01, 0x1c, 0x14, "3" }, + {0x13, 0x01, 0x1c, 0x10, "4" }, + {0x13, 0x01, 0x1c, 0x0c, "5 (Normal)" }, + {0x13, 0x01, 0x1c, 0x08, "6" }, + {0x13, 0x01, 0x1c, 0x04, "7" }, + {0x13, 0x01, 0x1c, 0x00, "8 (Hardest)" }, + + {0x13, 0xfe, 0, 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0x13, 0xfe, 0, 2, "Allow Continue" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0x13, 0xfe, 0, 2, "Cabinet" }, + {0x13, 0x01, 0x80, 0x00, "Upright" }, + {0x13, 0x01, 0x80, 0x80, "Cocktail" }, + + {0x14, 0xfe, 0, 2, "Coin Lockout Present?"}, + {0x14, 0x01, 0x01, 0x01, "Yes" }, + {0x14, 0x01, 0x01, 0x00, "No" }, +}; + +STDDIPINFO(Drv) + +static void palette_write(INT32 offset) +{ + UINT8 r,g,b; + UINT16 data = (DrvPalRAM[offset]) | (DrvPalRAM[offset | 0x400] << 8); + + r = (data >> 4) & 0x0f; + g = (data >> 0) & 0x0f; + b = (data >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +static void DrvRomBankswitch(INT32 bank) +{ + *DrvRomBank = bank & 0x0f; + + INT32 nBank = 0x10000 + (bank & 0x0f) * 0x4000; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + nBank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + nBank); +} + +static void DrvVidRamBankswitch(INT32 bank) +{ + *DrvVidBank = bank & 0x03; + + INT32 nBank = (bank & 3) * 0x1000; + + ZetMapArea(0xc000, 0xcfff, 0, DrvBgRAM + nBank); + ZetMapArea(0xc000, 0xcfff, 1, DrvBgRAM + nBank); + ZetMapArea(0xc000, 0xcfff, 2, DrvBgRAM + nBank); +} + +void __fastcall blacktiger_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0xd800) { + DrvPalRAM[address & 0x7ff] = data; + + palette_write(address & 0x3ff); + + return; + } + + return; +} + +UINT8 __fastcall blacktiger_read(UINT16 /*address*/) +{ + return 0; +} + +void __fastcall blacktiger_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + { + // INT64 cycles = ZetTotalCycles(); + // ZetClose(); + // ZetOpen(1); + + // INT32 nCycles = ((INT64)cycles * nCyclesTotal[1] / nCyclesTotal[0]); + // if (nCycles <= ZetTotalCycles()) return; + + // BurnTimerUpdate(nCycles); + // ZetClose(); + // ZetOpen(0); + + *soundlatch = data; + } + return; + + case 0x01: + DrvRomBankswitch(data); + return; + + case 0x03: + if (DrvDips[2] & 1) { + *coin_lockout = ~data << 6; + } + return; + + case 0x04: + if (data & 0x20) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + } + + *flipscreen = data & 0x40; + *DrvFgEnable = ~data & 0x80; + + return; + + case 0x06: + *watchdog = 0; + return; + + case 0x08: + *DrvScrollx = (*DrvScrollx & 0xff00) | data; + return; + + case 0x09: + *DrvScrollx = (*DrvScrollx & 0x00ff) | (data << 8); + return; + + case 0x0a: + *DrvScrolly = (*DrvScrolly & 0xff00) | data; + return; + + case 0x0b: + *DrvScrolly = (*DrvScrolly & 0x00ff) | (data << 8); + return; + + case 0x0c: + *DrvSprEnable = ~data & 0x02; + *DrvBgEnable = ~data & 0x04; + return; + + case 0x0d: + DrvVidRamBankswitch(data); + return; + + case 0x0e: + *DrvScreenLayout = data ? 1 : 0; + return; + } +} + +UINT8 __fastcall blacktiger_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + case 0x02: + return DrvInputs[port & 3]; + + case 0x03: + case 0x04: + return DrvDips[~port & 1]; + + case 0x05: + return 0x01; + + case 0x07: + return ZetDe(-1) >> 8; + } + + return 0; +} + +void __fastcall blacktiger_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + BurnYM2203Write(0, 0, data); + return; + + case 0xe001: + BurnYM2203Write(0, 1, data); + return; + + case 0xe002: + BurnYM2203Write(1, 0, data); + return; + + case 0xe003: + BurnYM2203Write(1, 1, data); + return; + } +} + +UINT8 __fastcall blacktiger_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc800: + return *soundlatch; + + case 0xe000: + return BurnYM2203Read(0, 0); + + case 0xe001: + return BurnYM2203Read(0, 1); + + case 0xe002: + return BurnYM2203Read(1, 0); + + case 0xe003: + return BurnYM2203Read(1, 1); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x050000; + DrvZ80ROM1 = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x001e00; + DrvZ80RAM1 = Next; Next += 0x000800; + + DrvPalRAM = Next; Next += 0x000800; + DrvTxRAM = Next; Next += 0x000800; + DrvBgRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x001200; + DrvSprBuf = Next; Next += 0x001200; + + DrvScreenLayout = Next; Next += 0x000001; + DrvBgEnable = Next; Next += 0x000001; + DrvFgEnable = Next; Next += 0x000001; + DrvSprEnable = Next; Next += 0x000001; + + DrvVidBank = Next; Next += 0x000001; + DrvRomBank = Next; Next += 0x000001; + + DrvScrollx = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + DrvScrolly = (UINT16*)Next; Next += 0x0001 * sizeof (UINT16); + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + coin_lockout = Next; Next += 0x000001; + watchdog = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + DrvRomBankswitch(1); + DrvVidRamBankswitch(1); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { ((0x40000 * 8) / 2) + 4, ((0x40000 * 8) / 2) + 0, 4, 0 }; + INT32 XOffs[16] = { 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3, + 16*16+0, 16*16+1, 16*16+2, 16*16+3, 16*16+8+0, 16*16+8+1, 16*16+8+2, 16*16+8+3 }; + INT32 YOffs[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, + 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0800, 2, 8, 8, Plane + 2, XOffs, YOffs, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane + 0, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane + 0, XOffs, YOffs, 0x200, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3579545; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvZ80ROM0 + i * 0x10000, 0 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM1, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 6, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x10000, 7 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x10000, 11 + i, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0xd000, 0xd7ff, 0, DrvTxRAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvTxRAM); + ZetMapArea(0xd000, 0xd7ff, 2, DrvTxRAM); + ZetMapArea(0xd800, 0xdfff, 0, DrvPalRAM); +// ZetMapArea(0xd800, 0xdfff, 1, DrvPalRAM); + ZetMapArea(0xd800, 0xdfff, 2, DrvPalRAM); + ZetMapArea(0xe000, 0xfdff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xfdff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xfdff, 2, DrvZ80RAM0); + ZetMapArea(0xfe00, 0xffff, 0, DrvSprRAM); + ZetMapArea(0xfe00, 0xffff, 1, DrvSprRAM); + ZetMapArea(0xfe00, 0xffff, 2, DrvSprRAM); + ZetSetWriteHandler(blacktiger_write); + ZetSetReadHandler(blacktiger_read); + ZetSetInHandler(blacktiger_in); + ZetSetOutHandler(blacktiger_out); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(blacktiger_sound_write); + ZetSetReadHandler(blacktiger_sound_read); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + BurnYM2203Init(2, 3579545, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(1); + BurnTimerAttachZet(3579545); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2203Exit(); + ZetExit(); + GenericTilesExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_bg(INT32 type) +{ + // No tile priorities implemented... I really can't notice where it is used. + + INT32 scrollx = (*DrvScrollx) & (0x3ff | (0x200 << type)); + INT32 scrolly = ((*DrvScrolly)+16) & (0x7ff >> type); + + for (INT32 offs = 0; offs < 0x2000; offs++) + { + INT32 sx; + INT32 sy; + INT32 ofst; + + // 1 = 128x64, 0 = 64x128 + if (type) { + sx = (offs & 0x7f); + sy = (offs >> 7); + + ofst = (sx & 0x0f) + ((sy & 0x0f) << 4) + ((sx & 0x70) << 4) + ((sy & 0x30) << 7); + } else { + sx = (offs & 0x3f); + sy = (offs >> 6); + + ofst = (sx & 0x0f) + ((sy & 0x0f) << 4) + ((sx & 0x30) << 4) + ((sy & 0x70) << 7); + } + + sx <<= 4, sy <<= 4; + + sx -= scrollx; + sy -= scrolly; + + if (sx < -15) sx += (0x400 << type); + if (sy < -15) sy += (0x800 >> type); + if (sx > 255 || sy > 223) continue; + + INT32 attr = DrvBgRAM[(ofst << 1) | 1]; + INT32 color = (attr >> 3) & 0x0f; + INT32 code = DrvBgRAM[ofst << 1] | ((attr & 0x07) << 8); + INT32 flipx = attr & 0x80; + + if (*flipscreen) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1); + } + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x1200 - 4; offs >= 0; offs -= 4) + { + INT32 attr = DrvSprBuf[offs+1]; + INT32 sx = DrvSprBuf[offs + 3] - ((attr & 0x10) << 4); + INT32 sy = DrvSprBuf[offs + 2]; + INT32 code = DrvSprBuf[offs] | ((attr & 0xe0) << 3); + INT32 color = attr & 0x07; + INT32 flipx = attr & 0x08; + + if (*flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + } + + sy -= 16; + + if (sy < -15 || sy > 239 || sx < -15 || sx > 255) continue; + + if (*flipscreen) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x200, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x200, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x200, DrvGfxROM2); + } + } + } +} + +static void draw_text_layer() +{ + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 attr = DrvTxRAM[offs | 0x400]; + INT32 code = DrvTxRAM[offs] | ((attr & 0xe0) << 3); + + if (!code) continue; + + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= 16; + INT32 color = attr & 0x1f; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 3, 0x300, DrvGfxROM0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + palette_write(i); + } + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x3ff; + } + + if (*DrvBgEnable) { + draw_bg(*DrvScreenLayout); + } + + if (*DrvSprEnable) { + draw_sprites(); + } + + if (*DrvFgEnable) { + draw_text_layer(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 100; + + if (DrvReset) { + DrvDoReset(); + } + + if (*watchdog >= 60) { + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + watchdog = 0; + } + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[0] |= *coin_lockout; + } + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + INT32 nCyclesDone[2]; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 98) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 99) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + ZetClose(); + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x1200); + +// *watchdog=*watchdog+1; + + return 0; +} + + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + } + + ZetOpen(0); + DrvRomBankswitch(*DrvRomBank); + DrvVidRamBankswitch(*DrvVidBank); + ZetClose(); + + return 0; +} + + +// Black Tiger + +static struct BurnRomInfo blktigerRomDesc[] = { + { "bdu-01a.5e", 0x08000, 0xa8f98f22, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "bdu-02a.6e", 0x10000, 0x7bef96e8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bdu-03a.8e", 0x10000, 0x4089e157, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bd-04.9e", 0x10000, 0xed6af6ec, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bd-05.10e", 0x10000, 0xae59b72e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd-06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "bd-15.2n", 0x08000, 0x70175d78, 3 | BRF_GRA }, // 6 - Characters + + { "bd-12.5b", 0x10000, 0xc4524993, 4 | BRF_GRA }, // 7 - Background Tiles + { "bd-11.4b", 0x10000, 0x7932c86f, 4 | BRF_GRA }, // 8 + { "bd-14.9b", 0x10000, 0xdc49593a, 4 | BRF_GRA }, // 9 + { "bd-13.8b", 0x10000, 0x7ed7a122, 4 | BRF_GRA }, // 10 + + { "bd-08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd-07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd-10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd-09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 + + { "bd.6k", 0x01000, 0xac7d14f1, 7 | BRF_PRG | BRF_OPT }, // 19 I8751 Mcu Code +}; + +STD_ROM_PICK(blktiger) +STD_ROM_FN(blktiger) + +struct BurnDriver BurnDrvBlktiger = { + "blktiger", NULL, NULL, NULL, "1987", + "Black Tiger\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, blktigerRomInfo, blktigerRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Black Tiger (older) + +static struct BurnRomInfo blktigeraRomDesc[] = { + { "bdu-01.5e", 0x08000, 0x47b13922, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "bdu-02.6e", 0x10000, 0x2e0daf1b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bdu-03.8e", 0x10000, 0x3b67dfec, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bd-04.9e", 0x10000, 0xed6af6ec, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bd-05.10e", 0x10000, 0xae59b72e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd-06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "bd-15.2n", 0x08000, 0x70175d78, 3 | BRF_GRA }, // 6 - Characters + + { "bd-12.5b", 0x10000, 0xc4524993, 4 | BRF_GRA }, // 7 - Background Tiles + { "bd-11.4b", 0x10000, 0x7932c86f, 4 | BRF_GRA }, // 8 + { "bd-14.9b", 0x10000, 0xdc49593a, 4 | BRF_GRA }, // 9 + { "bd-13.8b", 0x10000, 0x7ed7a122, 4 | BRF_GRA }, // 10 + + { "bd-08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd-07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd-10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd-09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 + + { "bd.6k", 0x01000, 0xac7d14f1, 7 | BRF_PRG | BRF_OPT }, // 19 I8751 Mcu Code +}; + +STD_ROM_PICK(blktigera) +STD_ROM_FN(blktigera) + +struct BurnDriver BurnDrvBlktigera = { + "blktigera", "blktiger", NULL, NULL, "1987", + "Black Tiger (older)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, blktigeraRomInfo, blktigeraRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Black Tiger (bootleg) + +static struct BurnRomInfo blktigerb1RomDesc[] = { + { "btiger1.f6", 0x08000, 0x9d8464e8, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "bdu-02a.6e", 0x10000, 0x7bef96e8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "btiger3.j6", 0x10000, 0x52c56ed1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bd-04.9e", 0x10000, 0xed6af6ec, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bd-05.10e", 0x10000, 0xae59b72e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd-06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "bd-15.2n", 0x08000, 0x70175d78, 3 | BRF_GRA }, // 6 - Characters + + { "bd-12.5b", 0x10000, 0xc4524993, 4 | BRF_GRA }, // 7 - Background Tiles + { "bd-11.4b", 0x10000, 0x7932c86f, 4 | BRF_GRA }, // 8 + { "bd-14.9b", 0x10000, 0xdc49593a, 4 | BRF_GRA }, // 9 + { "bd-13.8b", 0x10000, 0x7ed7a122, 4 | BRF_GRA }, // 10 + + { "bd-08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd-07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd-10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd-09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 +}; + +STD_ROM_PICK(blktigerb1) +STD_ROM_FN(blktigerb1) + +struct BurnDriver BurnDrvBlktigerb1 = { + "blktigerb1", "blktiger", NULL, NULL, "1987", + "Black Tiger (bootleg set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, blktigerb1RomInfo, blktigerb1RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + + +// Black Tiger (bootleg set 2) + +static struct BurnRomInfo bktigrb2RomDesc[] = { + { "1.bin", 0x08000, 0x47E2B21E, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "bdu-02a.6e", 0x10000, 0x7bef96e8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.bin", 0x10000, 0x52c56ed1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bd-04.9e", 0x10000, 0xed6af6ec, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bd-05.10e", 0x10000, 0xae59b72e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd-06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "bd-15.2n", 0x08000, 0x70175d78, 3 | BRF_GRA }, // 6 - Characters + + { "bd-12.5b", 0x10000, 0xc4524993, 4 | BRF_GRA }, // 7 - Background Tiles + { "bd-11.4b", 0x10000, 0x7932c86f, 4 | BRF_GRA }, // 8 + { "bd-14.9b", 0x10000, 0xdc49593a, 4 | BRF_GRA }, // 9 + { "bd-13.8b", 0x10000, 0x7ed7a122, 4 | BRF_GRA }, // 10 + + { "bd-08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd-07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd-10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd-09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 + + { "bd.5k", 0x01000, 0xac7d14f1, 7 | BRF_PRG | BRF_OPT }, // 19 I8751 Mcu Code +}; + +STD_ROM_PICK(bktigrb2) +STD_ROM_FN(bktigrb2) + +struct BurnDriver BurnDrvBktigrb2 = { + "bktigrb2", "blktiger", NULL, NULL, "1987", + "Black Tiger (bootleg set 2)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, bktigrb2RomInfo, bktigrb2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Black Dragon + +static struct BurnRomInfo blkdrgonRomDesc[] = { + { "bd_01.5e", 0x08000, 0x27ccdfbc, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "bd_02.6e", 0x10000, 0x7d39c26f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bd_03.8e", 0x10000, 0xd1bf3757, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bd_04.9e", 0x10000, 0x4d1d6680, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bd_05.10e", 0x10000, 0xc8d0c45e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd_06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "bd_15.2n", 0x08000, 0x3821ab29, 3 | BRF_GRA }, // 6 - Characters + + { "bd_12.5b", 0x10000, 0x22d0a4b0, 4 | BRF_GRA }, // 7 - Background Tiles + { "bd_13.8b", 0x10000, 0x5b0df8ce, 4 | BRF_GRA }, // 8 + { "bd_14.9b", 0x10000, 0x9498c378, 4 | BRF_GRA }, // 9 + { "bd_11.4b", 0x10000, 0xc8b5fc52, 4 | BRF_GRA }, // 10 + + { "bd_08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd_07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd_10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd_09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 + + { "bd.6k", 0x01000, 0xac7d14f1, 7 | BRF_PRG | BRF_OPT }, // 19 I8751 Mcu Code +}; + +STD_ROM_PICK(blkdrgon) +STD_ROM_FN(blkdrgon) + +struct BurnDriver BurnDrvBlkdrgon = { + "blkdrgon", "blktiger", NULL, NULL, "1987", + "Black Dragon\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, blkdrgonRomInfo, blkdrgonRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Black Dragon (bootleg) + +static struct BurnRomInfo blkdrgonbRomDesc[] = { + { "a1", 0x08000, 0x7caf2ba0, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 #0 Code + { "blkdrgon.6e", 0x10000, 0x7d39c26f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a3", 0x10000, 0xf4cd0f39, 1 | BRF_PRG | BRF_ESS }, // 2 + { "blkdrgon.9e", 0x10000, 0x4d1d6680, 1 | BRF_PRG | BRF_ESS }, // 3 + { "blkdrgon.10e", 0x10000, 0xc8d0c45e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "bd-06.1l", 0x08000, 0x2cf54274, 2 | BRF_PRG | BRF_ESS }, // 5 - Z80 #0 Code + + { "b5", 0x08000, 0x852ad2b7, 3 | BRF_GRA }, // 6 - Characters + + { "blkdrgon.5b", 0x10000, 0x22d0a4b0, 4 | BRF_GRA }, // 7 - Background Tiles + { "b1", 0x10000, 0x053ab15c, 4 | BRF_GRA }, // 8 + { "blkdrgon.9b", 0x10000, 0x9498c378, 4 | BRF_GRA }, // 9 + { "b3", 0x10000, 0x9dc6e943, 4 | BRF_GRA }, // 10 + + { "bd-08.5a", 0x10000, 0xe2f17438, 5 | BRF_GRA }, // 11 - Sprites + { "bd-07.4a", 0x10000, 0x5fccbd27, 5 | BRF_GRA }, // 12 + { "bd-10.9a", 0x10000, 0xfc33ccc6, 5 | BRF_GRA }, // 13 + { "bd-09.8a", 0x10000, 0xf449de01, 5 | BRF_GRA }, // 14 + + { "bd01.8j", 0x00100, 0x29b459e5, 6 | BRF_OPT }, // 15 - Proms (not used) + { "bd02.9j", 0x00100, 0x8b741e66, 6 | BRF_OPT }, // 16 + { "bd03.11k", 0x00100, 0x27201c75, 6 | BRF_OPT }, // 17 + { "bd04.11l", 0x00100, 0xe5490b68, 6 | BRF_OPT }, // 18 +}; + +STD_ROM_PICK(blkdrgonb) +STD_ROM_FN(blkdrgonb) + +struct BurnDriver BurnDrvBlkdrgonb = { + "blkdrgonb", "blktiger", NULL, NULL, "1987", + "Black Dragon (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, blkdrgonbRomInfo, blkdrgonbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_blockout.cpp b/src/burn/drivers/misc_pre90s/d_blockout.cpp new file mode 100644 index 00000000..dfea2508 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_blockout.cpp @@ -0,0 +1,745 @@ +// FB Alpha Block Out driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM0; +static UINT8 *Drv68KRAM1; +static UINT8 *Drv68KRAM2; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvVidRAM0; +static UINT8 *DrvVidRAM1; +static UINT16*DrvTmpBmp; +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT8 DrvInputs[5]; + +static struct BurnInputInfo BlockoutInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy3 + 1, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy3 + 2, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy3 + 3, "p3 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy5 + 6, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4"}, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy5 + 7, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Blockout) + +static struct BurnInputInfo BlckoutjInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy3 + 1, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy3 + 2, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy3 + 3, "p3 coin" }, + + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy5 + 6, "p1 fire 4"}, + + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy5 + 7, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Blckoutj) + +static struct BurnDIPInfo BlockoutDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x16, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "1 Coin to Continue" }, + {0x16, 0x01, 0x10, 0x10, "Off" }, + {0x16, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x03, "Normal" }, + {0x17, 0x01, 0x03, 0x01, "Hard" }, + {0x17, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Rotate Buttons" }, + {0x17, 0x01, 0x04, 0x00, "2" }, + {0x17, 0x01, 0x04, 0x04, "3" }, +}; + +STDDIPINFO(Blockout) + +static struct BurnDIPInfo AgressDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x16, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x16, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x16, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x16, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Opening Cut" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x16, 0x01, 0x20, 0x00, "Off" }, + {0x16, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x03, "Normal" }, + {0x17, 0x01, 0x03, 0x01, "Hard" }, + {0x17, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Players" }, + {0x17, 0x01, 0x04, 0x04, "1" }, + {0x17, 0x01, 0x04, 0x00, "2" }, +}; + +STDDIPINFO(Agress) + +static void palette_write(INT32 offset) +{ + UINT16 rgb = *((UINT16*)(DrvPalRAM + offset)); + + INT32 bit0,bit1,bit2,bit3; + INT32 r,g,b; + + bit0 = (rgb >> 0) & 0x01; + bit1 = (rgb >> 1) & 0x01; + bit2 = (rgb >> 2) & 0x01; + bit3 = (rgb >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (rgb >> 4) & 0x01; + bit1 = (rgb >> 5) & 0x01; + bit2 = (rgb >> 6) & 0x01; + bit3 = (rgb >> 7) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (rgb >> 8) & 0x01; + bit1 = (rgb >> 9) & 0x01; + bit2 = (rgb >> 10) & 0x01; + bit3 = (rgb >> 11) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + DrvPalette[offset/2] = BurnHighCol(r, g, b, 0); +} + +static void update_pixels(INT32 offset) +{ + INT32 x = (offset & 0xff); + INT32 y = (offset >> 8) & 0xff; + if (x >= 320 || y < 8 || y > 247) return; + + UINT16 *src = (UINT16*)DrvVidRAM0 + ((y << 8) | x); + UINT16 *dst = DrvTmpBmp + (y-8) * 320 + x * 2; + + INT32 front = src[0x00000]; + INT32 back = src[0x10000]; + + if (front >> 8) dst[0] = front >> 8; + else dst[0] = (back >> 8) | 0x100; + + if (front & 0xff) dst[1] = front & 0xff; + else dst[1] = (back & 0xff) | 0x100; +} + +void __fastcall blockout_write_byte(UINT32 address, UINT8 data) +{ + if (address >= 0x180000 && address <= 0x1bffff) { + address = (address & 0x3ffff) ^ 1; + DrvVidRAM0[address] = data; + update_pixels(address>>1); + return; + } + + switch (address ^ 1) + { + case 0x100014: + *soundlatch = data & 0xff; + ZetNmi(); + return; + } + + return; +} + +void __fastcall blockout_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0x280200 && address <= 0x2805ff) { + *((UINT16*)(DrvPalRAM + (address - 0x280200))) = data; + palette_write(address & 0x3fe); + return; + } + + if (address >= 0x180000 && address <= 0x1bffff) { + address &= 0x3fffe; + *((UINT16*)(DrvVidRAM0 + address)) = data; + update_pixels(address>>1); + return; + } + + switch (address) + { + case 0x100014: + *soundlatch = data & 0xff; + ZetNmi(); + return; + + case 0x280002: // front color + *((UINT16*)(DrvPalRAM + 0x400)) = data; + palette_write(0x400); + return; + } + + return; +} + +UINT8 __fastcall blockout_read_byte(UINT32 address) +{ + switch (address^1) + { + case 0x100000: + return DrvInputs[0]; + + case 0x100002: + return DrvInputs[1]; + + case 0x100004: + return DrvInputs[2] & 0x0e; + + case 0x100006: + return DrvDips[0]; + + case 0x100008: + return ((DrvDips[1] & 0x3f) | (DrvInputs[4] & 0xc0)); + } + + return 0; +} + +UINT16 __fastcall blockout_read_word(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0]; + + case 0x100002: + return DrvInputs[1]; + + case 0x100004: + return DrvInputs[2] & 0x0e; + + case 0x100006: + return DrvDips[0]; + + case 0x100008: + return ((DrvDips[1] & 0x3f) | (DrvInputs[4] & 0xc0)); + } + + return 0; +} + +void __fastcall blockout_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8800: + BurnYM2151SelectRegister(data); + return; + + case 0x8801: + BurnYM2151WriteRegister(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall blockout_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8801: + return BurnYM2151ReadStatus(); + + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return *soundlatch; + } + + return 0; +} + +void BlockoutYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x008000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0201 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM0 = Next; Next += 0x00c000; + Drv68KRAM1 = Next; Next += 0x00c000; + Drv68KRAM2 = Next; Next += 0x018000; + DrvVidRAM0 = Next; Next += 0x040000; + DrvVidRAM1 = Next; Next += 0x008000; + DrvPalRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + + DrvTmpBmp = (UINT16*)Next; Next += (320 * 240) * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + BurnSetRefreshRate(58.0); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 3, 1)) return 1; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvVidRAM0, 0x180000, 0x1bffff, SM_ROM); + SekMapMemory(Drv68KRAM0, 0x1d4000, 0x1dffff, SM_RAM); + SekMapMemory(Drv68KRAM1, 0x1f4000, 0x1fffff, SM_RAM); + SekMapMemory(DrvVidRAM1, 0x200000, 0x207fff, SM_RAM); + SekMapMemory(Drv68KRAM2, 0x208000, 0x21ffff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x280200, 0x2805ff, SM_ROM); // maps 280000 - 2707ff + SekSetWriteByteHandler(0, blockout_write_byte); + SekSetWriteWordHandler(0, blockout_write_word); + SekSetReadByteHandler(0, blockout_read_byte); + SekSetReadWordHandler(0, blockout_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(blockout_sound_write); + ZetSetReadHandler(blockout_sound_read); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132, 100.0, 1); + + BurnYM2151Init(3579545, 100.0); + BurnYM2151SetIrqHandler(&BlockoutYM2151IrqHandler); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + MSM6295Exit(0); + BurnYM2151Exit(); + + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x402; i+=2) { + palette_write(i); + } + } + + memcpy (pTransDraw, DrvTmpBmp, 320 * 240 * sizeof(UINT16)); + + { + UINT16 *vram = (UINT16*)DrvVidRAM1; + + for (INT32 y = 0; y < 240;y++) + { + for (INT32 x = 0; x < 320; x+=8) + { + INT32 d = vram[((y + 8) << 6) + (x >> 3)]; + + if (d) { + for (INT32 v = 0x80, c = 0; v > 0; v >>= 1, c++) + if (d & v) pTransDraw[(y * 320) + x + c] = 512; + } + } + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + INT32 nTotalCycles[2] = { 10000000 / 58, 3579545 / 58 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + + nSegment = nTotalCycles[0] / nInterleave; + + SekRun(nSegment); + + nSegment = nTotalCycles[1] / nInterleave; + + ZetRun(nSegment); + nSegment = nBurnSoundLen / nInterleave; + + if (pBurnSoundOut) { + INT16 *pSoundBuf = pBurnSoundOut + nSoundBufferPos * 2; + BurnYM2151Render(pSoundBuf, nSegment); + MSM6295Render(0, pSoundBuf, nSegment); + nSoundBufferPos += nSegment; + } + + if (i == (nInterleave / 2)-1) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + } + + if (pBurnSoundOut) { + INT16 *pSoundBuf = pBurnSoundOut + nSoundBufferPos * 2; + nSegment = nBurnSoundLen - nSoundBufferPos; + if (nSegment) { + BurnYM2151Render(pSoundBuf, nSegment); + MSM6295Render(0, pSoundBuf, nSegment); + } + } + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + } + + return 0; +} + + +// Block Out (set 1) + +static struct BurnRomInfo blockoutRomDesc[] = { + { "bo29a0-2.bin", 0x20000, 0xb0103427, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bo29a1-2.bin", 0x20000, 0x5984d5a2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bo29e3-0.bin", 0x08000, 0x3ea01f78, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bo29e2-0.bin", 0x20000, 0x15c5a99d, 3 | BRF_SND }, // 3 Samples + + { "mb7114h.25", 0x00100, 0xb25bbda7, 0 | BRF_OPT }, // 4 Unused Prom +}; + +STD_ROM_PICK(blockout) +STD_ROM_FN(blockout) + +struct BurnDriver BurnDrvBlockout = { + "blockout", NULL, NULL, NULL, "1989", + "Block Out (set 1)\0", NULL, "Technos + California Dreams", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, blockoutRomInfo, blockoutRomName, NULL, NULL, BlockoutInputInfo, BlockoutDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x201, + 320, 240, 4, 3 +}; + + +// Block Out (set 2) + +static struct BurnRomInfo blckout2RomDesc[] = { + { "29a0", 0x20000, 0x605f931e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "29a1", 0x20000, 0x38f07000, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bo29e3-0.bin", 0x08000, 0x3ea01f78, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bo29e2-0.bin", 0x20000, 0x15c5a99d, 3 | BRF_SND }, // 3 Samples + + { "mb7114h.25", 0x00100, 0xb25bbda7, 0 | BRF_OPT }, // 4 Unused Prom +}; + +STD_ROM_PICK(blckout2) +STD_ROM_FN(blckout2) + +struct BurnDriver BurnDrvBlckout2 = { + "blockout2", "blockout", NULL, NULL, "1989", + "Block Out (set 2)\0", NULL, "Technos + California Dreams", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, blckout2RomInfo, blckout2RomName, NULL, NULL, BlockoutInputInfo, BlockoutDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x201, + 320, 240, 4, 3 +}; + + +// Block Out (Japan) + +static struct BurnRomInfo blckoutjRomDesc[] = { + { "2.bin", 0x20000, 0xe16cf065, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "1.bin", 0x20000, 0x950b28a3, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "bo29e3-0.bin", 0x08000, 0x3ea01f78, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "bo29e2-0.bin", 0x20000, 0x15c5a99d, 3 | BRF_SND }, // 3 Samples + + { "mb7114h.25", 0x00100, 0xb25bbda7, 0 | BRF_OPT }, // 4 Unused Prom +}; + +STD_ROM_PICK(blckoutj) +STD_ROM_FN(blckoutj) + +struct BurnDriver BurnDrvBlckoutj = { + "blockoutj", "blockout", NULL, NULL, "1989", + "Block Out (Japan)\0", NULL, "Technos + California Dreams", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, blckoutjRomInfo, blckoutjRomName, NULL, NULL, BlckoutjInputInfo, BlockoutDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x201, + 320, 240, 4, 3 +}; + + +// Agress + +static struct BurnRomInfo agressRomDesc[] = { + { "palco1.81", 0x20000, 0x3acc917a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "palco2.91", 0x20000, 0xabfd5bcc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "palco3.73", 0x08000, 0x2a21c97d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "palco4.78", 0x20000, 0x9dfd9cfe, 3 | BRF_SND }, // 3 Samples + + { "82s129pr.25", 0x00100, 0xb25bbda7, 0 | BRF_OPT }, // 4 Unused Prom +}; + +STD_ROM_PICK(agress) +STD_ROM_FN(agress) + +struct BurnDriver BurnDrvAgress = { + "agress", NULL, NULL, NULL, "1991", + "Agress\0", NULL, "Palco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, agressRomInfo, agressRomName, NULL, NULL, BlockoutInputInfo, AgressDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x201, + 320, 240, 4, 3 +}; + + +// Agress (English bootleg) + +static struct BurnRomInfo agressbRomDesc[] = { + { "palco1.ic81", 0x20000, 0xa1875175, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "palco2.ic91", 0x20000, 0xab3182c3, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "palco3.ic73", 0x08000, 0x2a21c97d, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "palco4.ic78", 0x20000, 0x9dfd9cfe, 3 | BRF_SND }, // 3 Samples + + { "prom29-mb7114h.ic25", 0x00100, 0xb25bbda7, 0 | BRF_OPT }, // 4 Unused Prom +}; + +STD_ROM_PICK(agressb) +STD_ROM_FN(agressb) + +struct BurnDriver BurnDrvAgressb = { + "agressb", "agress", NULL, NULL, "2003", + "Agress (English bootleg)\0", NULL, "Palco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, agressbRomInfo, agressbRomName, NULL, NULL, BlockoutInputInfo, AgressDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x201, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_blueprnt.cpp b/src/burn/drivers/misc_pre90s/d_blueprnt.cpp new file mode 100644 index 00000000..cc6abeff --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_blueprnt.cpp @@ -0,0 +1,750 @@ +// FB Alpha Blue Print driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *RamEnd; +static UINT8 *AllRam; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvScrollRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT32 *DrvPalette; +static INT16 *pAY8910Buffer[6]; + +static UINT8 *watchdog; +static UINT8 *dipsw; +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT8 *gfx_bank; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[2]; + +static UINT8 DrvRecalc; + +static struct BurnInputInfo BlueprntInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 1, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 6, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 7, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 5, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 6, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 7, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 4, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 5, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 2, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Blueprnt) + +static struct BurnDIPInfo BlueprntDIPList[]= +{ + {0x11, 0xff, 0xff, 0xc3, NULL }, + {0x12, 0xff, 0xff, 0xd5, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x11, 0x01, 0x06, 0x00, "20K" }, + {0x11, 0x01, 0x06, 0x02, "30K" }, + {0x11, 0x01, 0x06, 0x04, "40K" }, + {0x11, 0x01, 0x06, 0x06, "50K" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Maze Monster Appears In" }, + {0x11, 0x01, 0x10, 0x00, "2nd Maze" }, + {0x11, 0x01, 0x10, 0x10, "3rd Maze" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x11, 0x01, 0x20, 0x20, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x20, 0x00, "1 Coin 1 Credits " }, + + {0 , 0xfe, 0 , 2, "Coin B" }, + {0x11, 0x01, 0x40, 0x40, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x40, 0x00, "1 Coin 5 Credits " }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x01, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x08, 0x00, "Upright" }, + {0x12, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x00, "Level 1" }, + {0x12, 0x01, 0x30, 0x10, "Level 2" }, + {0x12, 0x01, 0x30, 0x20, "Level 3" }, + {0x12, 0x01, 0x30, 0x30, "Level 4" }, +}; + +STDDIPINFO(Blueprnt) + +static struct BurnInputInfo SaturnInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 1, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 6, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 7, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 5, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 6, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 7, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 4, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 5, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Saturn) + +static struct BurnDIPInfo SaturnDIPList[]= +{ + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x04, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x02, 0x00, "Upright" }, + {0x11, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0xc0, 0x00, "3" }, + {0x11, 0x01, 0xc0, 0x40, "4" }, + {0x11, 0x01, 0xc0, 0x80, "5" }, + {0x11, 0x01, 0xc0, 0xc0, "6" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x12, 0x01, 0x02, 0x02, "A 2/1 B 1/3" }, + {0x12, 0x01, 0x02, 0x00, "A 1/1 B 1/6" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, +}; + +STDDIPINFO(Saturn) + +void __fastcall blueprint_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xd000: + { + *soundlatch = data; + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + } + return; + + case 0xe000: + { + *flipscreen = ~data & 2; + *gfx_bank = (data >> 2) & 1; + } + + return; + } +} + +UINT8 __fastcall blueprint_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + case 0xc001: + return DrvInputs[address & 1]; + + case 0xc003: + return *dipsw; + + case 0xe000: + *watchdog = 0; + return 0; + } + + return 0; +} + +void __fastcall blueprint_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x6000: + AY8910Write(0, 0, data); + return; + + case 0x6001: + AY8910Write(0, 1, data); + return; + + case 0x8000: + AY8910Write(1, 0, data); + return; + + case 0x8001: + AY8910Write(1, 1, data); + return; + } +} + +UINT8 __fastcall blueprint_sound_read(UINT16 address) +{ + switch (address) + { + case 0x6002: + return AY8910Read(0); + + case 0x8002: + return AY8910Read(1); + } + + return 0; +} + +UINT8 ay8910_0_read_port_1(UINT32) +{ + return *soundlatch; +} + +void ay8910_0_write_port_0(UINT32, UINT32 data) +{ + *dipsw = data & 0xff; +} + +UINT8 ay8910_1_read_port_0(UINT32) +{ + return DrvDips[0]; +} + +UINT8 ay8910_1_read_port_1(UINT32) +{ + return DrvDips[1]; +} + +static void palette_init() +{ + for (INT32 i = 0; i < 512 + 8; i++) + { + UINT8 pen; + + if (i < 0x200) + pen = ((i & 0x100) >> 5) | ((i & 0x002) ? ((i & 0x0e0) >> 5) : 0) | ((i & 0x001) ? ((i & 0x01c) >> 2) : 0); + else + pen = i - 0x200; + + INT32 r = ((pen >> 0) & 1) * (((pen & 8) >> 1) ^ 0xff); + INT32 g = ((pen >> 2) & 1) * (((pen & 8) >> 1) ^ 0xff); + INT32 b = ((pen >> 1) & 1) * (((pen & 8) >> 1) ^ 0xff); + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { (0x1000 * 8) * 2, (0x1000 * 8) * 1, (0x1000 * 8) * 0 }; + INT32 XOffs[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x03000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x02000); + + GfxDecode(0x0200, 2, 8, 8, Plane + 1, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x03000); + + GfxDecode(0x0100, 3, 8, 16, Plane + 0, XOffs, YOffs, 0x080, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x008000; + DrvGfxROM1 = Next; Next += 0x008000; + + DrvPalette = (UINT32*)Next; Next += 0x0208 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[3] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[4] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[5] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + AllRam = Next; + + DrvColRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + DrvScrollRAM = Next; Next += 0x000100; + DrvSprRAM = Next; Next += 0x000100; + + DrvZ80RAM0 = Next; Next += 0x000800; + DrvZ80RAM1 = Next; Next += 0x000800; + + dipsw = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + gfx_bank = Next; Next += 0x000001; + watchdog = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + INT32 lofst = 0; + + if (BurnLoadRom(DrvZ80ROM0 + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x1000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x2000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x3000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x4000, 4, 1)) return 1; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "saturnzi")) { + if (BurnLoadRom(DrvZ80ROM0 + 0x5000, 5, 1)) return 1; + lofst = 1; + } + + if (BurnLoadRom(DrvZ80ROM1 + 0x0000, 5+lofst, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x2000, 6+lofst, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 7+lofst, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1000, 8+lofst, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x0000, 9+lofst, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1000, 10+lofst,1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x2000, 11+lofst,1)) return 1; + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM0); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM0); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM0); + ZetMapArea(0x9000, 0x93ff, 0, DrvVidRAM); + ZetMapArea(0x9000, 0x93ff, 1, DrvVidRAM); + ZetMapArea(0x9000, 0x93ff, 2, DrvVidRAM); + ZetMapArea(0x9400, 0x97ff, 0, DrvVidRAM); + ZetMapArea(0x9400, 0x97ff, 1, DrvVidRAM); + ZetMapArea(0x9400, 0x97ff, 2, DrvVidRAM); + ZetMapArea(0xa000, 0xa0ff, 0, DrvScrollRAM); + ZetMapArea(0xa000, 0xa0ff, 1, DrvScrollRAM); + ZetMapArea(0xa000, 0xa0ff, 2, DrvScrollRAM); + ZetMapArea(0xb000, 0xb0ff, 0, DrvSprRAM); + ZetMapArea(0xb000, 0xb0ff, 1, DrvSprRAM); + ZetMapArea(0xb000, 0xb0ff, 2, DrvSprRAM); + ZetMapArea(0xf000, 0xf3ff, 0, DrvColRAM); + ZetMapArea(0xf000, 0xf3ff, 1, DrvColRAM); + ZetMapArea(0xf000, 0xf3ff, 2, DrvColRAM); + ZetSetWriteHandler(blueprint_write); + ZetSetReadHandler(blueprint_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x2fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x2fff, 2, DrvZ80ROM1); + ZetMapArea(0x4000, 0x43ff, 0, DrvZ80RAM1); + ZetMapArea(0x4000, 0x43ff, 1, DrvZ80RAM1); + ZetMapArea(0x4000, 0x43ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(blueprint_sound_write); + ZetSetReadHandler(blueprint_sound_read); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 625000, nBurnSoundRate, NULL, &ay8910_0_read_port_1, &ay8910_0_write_port_0, NULL); + AY8910Init(1, 625000, nBurnSoundRate, &ay8910_1_read_port_0, &ay8910_1_read_port_1, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer(INT32 prio) +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 attr = DrvColRAM[offs]; + if ((attr >> 7) != prio) continue; + + INT32 code = DrvVidRAM[offs] | (*gfx_bank << 8); + INT32 color = attr & 0x7f; + + INT32 sx = (~offs & 0x3e0) >> 2; + INT32 sy = (offs & 0x1f) << 3; + + sy -= DrvScrollRAM[(30 + *flipscreen) - (sx >> 3)]; + if (sy < -7) sy += 0x100; + + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx ^ 0xf8, (248 - sy) - 16, color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 2, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_8x16_tile(INT32 code, INT32 sx, INT32 sy, INT32 fx, INT32 fy) +{ + UINT8 *src = DrvGfxROM1 + (code << 7); + + for (INT32 y = 0; y < 16; y++) + { + INT32 yy = sy + y; + + for (INT32 x = 0; x < 8; x++) + { + INT32 xx = sx + x; + INT32 d = src[((y ^ fy) << 3) | (x ^ fx)]; + + if (yy < 0 || xx < 0 || yy >= nScreenHeight || xx >= nScreenWidth || !d) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = d | 0x200; + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0x100; offs += 4) + { + INT32 code = DrvSprRAM[offs + 1]; + INT32 sx = DrvSprRAM[offs + 3]; + INT32 sy = 240 - DrvSprRAM[offs]; + INT32 flipx = (DrvSprRAM[offs + 2] >> 6) & 1; + INT32 flipy = (DrvSprRAM[offs + 2 - 4] >> 7) & 1; + + if (*flipscreen) + { + sx = 248 - sx; + sy = 240 - sy; + flipx ^= 1; + flipy ^= 1; + } + + draw_8x16_tile(code, sx+2, sy-17, flipx * 0x07, flipy * 0x0f); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + palette_init(); + } + + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + draw_layer(0); + draw_sprites(); + draw_layer(1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + if (*watchdog > 180) { + DrvDoReset(); + } + + *watchdog = *watchdog + 1; + } + + { + DrvInputs[0] = DrvInputs[1] = 0; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] |= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nSegment; + INT32 nInterleave = 256; + INT32 nTotalCycles[2] = { 3500000 / 60, 625000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == 255) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + nSegment = (nTotalCycles[1] - nCyclesDone[1]) / (nInterleave - i); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nSegment); + if ((i & 0x3f) == 0x3f) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + } + + return 0; +} + + +// Blue Print (Midway) + +static struct BurnRomInfo blueprntRomDesc[] = { + { "bp-1.1m", 0x1000, 0xb20069a6, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bp-2.1n", 0x1000, 0x4a30302e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bp-3.1p", 0x1000, 0x6866ca07, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bp-4.1r", 0x1000, 0x5d3cfac3, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bp-5.1s", 0x1000, 0xa556cac4, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "snd-1.3u", 0x1000, 0xfd38777a, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 Code + { "snd-2.3v", 0x1000, 0x33d5bf5b, 2 | BRF_PRG | BRF_ESS }, // 6 + + { "bg-1.3c", 0x1000, 0xac2a61bc, 3 | BRF_GRA }, // 7 Background Tiles + { "bg-2.3d", 0x1000, 0x81fe85d7, 3 | BRF_GRA }, // 8 + + { "red.17d", 0x1000, 0xa73b6483, 4 | BRF_GRA }, // 9 Sprites + { "blue.18d", 0x1000, 0x7d622550, 4 | BRF_GRA }, // 10 + { "green.20d", 0x1000, 0x2fcb4f26, 4 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(blueprnt) +STD_ROM_FN(blueprnt) + +struct BurnDriver BurnDrvBlueprnt = { + "blueprnt", NULL, NULL, NULL, "1982", + "Blue Print (Midway)\0", NULL, "[Zilec Electronics] Bally Midway", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, blueprntRomInfo, blueprntRomName, NULL, NULL, BlueprntInputInfo, BlueprntDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x208, + 224, 256, 3, 4 +}; + + +// Blue Print (Jaleco) + +static struct BurnRomInfo blueprnjRomDesc[] = { + { "bp-1j.1m", 0x1000, 0x2e746693, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "bp-2j.1n", 0x1000, 0xa0eb0b8e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "bp-3j.1p", 0x1000, 0xc34981bb, 1 | BRF_PRG | BRF_ESS }, // 2 + { "bp-4j.1r", 0x1000, 0x525e77b5, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bp-5j.1s", 0x1000, 0x431a015f, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "snd-1.3u", 0x1000, 0xfd38777a, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 Code + { "snd-2.3v", 0x1000, 0x33d5bf5b, 2 | BRF_PRG | BRF_ESS }, // 6 + + { "bg-1j.3c", 0x0800, 0x43718c34, 3 | BRF_GRA }, // 7 Background Tiles + { "bg-2j.3d", 0x0800, 0xd3ce077d, 3 | BRF_GRA }, // 8 + + { "redj.17d", 0x1000, 0x83da108f, 4 | BRF_GRA }, // 9 Sprites + { "bluej.18d", 0x1000, 0xb440f32f, 4 | BRF_GRA }, // 10 + { "greenj.20d", 0x1000, 0x23026765, 4 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(blueprnj) +STD_ROM_FN(blueprnj) + +struct BurnDriver BurnDrvBlueprnj = { + "blueprntj", "blueprnt", NULL, NULL, "1982", + "Blue Print (Jaleco)\0", NULL, "[Zilec Electronics] Jaleco", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, blueprnjRomInfo, blueprnjRomName, NULL, NULL, BlueprntInputInfo, BlueprntDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x208, + 224, 256, 3, 4 +}; + + +// Saturn + +static struct BurnRomInfo saturnziRomDesc[] = { + { "r1", 0x1000, 0x18a6d68e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "r2", 0x1000, 0xa7dd2665, 1 | BRF_PRG | BRF_ESS }, // 1 + { "r3", 0x1000, 0xb9cfa791, 1 | BRF_PRG | BRF_ESS }, // 2 + { "r4", 0x1000, 0xc5a997e7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "r5", 0x1000, 0x43444d00, 1 | BRF_PRG | BRF_ESS }, // 4 + { "r6", 0x1000, 0x4d4821f6, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "r7", 0x1000, 0xdd43e02f, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + { "r8", 0x1000, 0x7f9d0877, 2 | BRF_PRG | BRF_ESS }, // 7 + + { "r10", 0x1000, 0x35987d61, 3 | BRF_GRA }, // 8 Background Tiles + { "r9", 0x1000, 0xca6a7fda, 3 | BRF_GRA }, // 9 + + { "r11", 0x1000, 0x6e4e6e5d, 4 | BRF_GRA }, // 10 Sprites + { "r12", 0x1000, 0x46fc049e, 4 | BRF_GRA }, // 11 + { "r13", 0x1000, 0x8b3e8c32, 4 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(saturnzi) +STD_ROM_FN(saturnzi) + +struct BurnDriver BurnDrvSaturnzi = { + "saturnzi", NULL, NULL, NULL, "1983", + "Saturn\0", NULL, "[Zilec Electronics] Jaleco", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, saturnziRomInfo, saturnziRomName, NULL, NULL, SaturnInputInfo, SaturnDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x208, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_bombjack.cpp b/src/burn/drivers/misc_pre90s/d_bombjack.cpp new file mode 100644 index 00000000..ac587645 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_bombjack.cpp @@ -0,0 +1,960 @@ +#include "tiles_generic.h" + +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +UINT8 DrvJoy1[7] = {0, 0, 0, 0, 0, 0, 0}; +UINT8 DrvJoy2[7] = {0, 0, 0, 0, 0, 0, 0}; +UINT8 BjDip[2] = {0, 0}; +static UINT8 DrvReset = 0; +static INT32 bombjackIRQ = 0; +static INT32 latch; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *BjGfx = NULL; +static UINT8 *BjMap = NULL; +static UINT8 *BjRom = NULL; +static UINT8 *BjRam = NULL; +static UINT8 *BjColRam = NULL; +static UINT8 *BjVidRam = NULL; +static UINT8 *BjSprRam = NULL; + +// sound cpu +static UINT8 *SndRom = NULL; +static UINT8 *SndRam = NULL; + +// graphics tiles +static UINT8 *text = NULL; +static UINT8 *sprites = NULL; +static UINT8 *tiles = NULL; + +// pallete +static UINT8 *BjPalSrc = NULL; +static UINT32 *BjPalReal = NULL; + +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[9]; + +// Dip Switch and Input Definitions +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p1 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 4, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 5, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy2 + 0, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 1, "p2 start" }, + + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 4, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 5, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 1"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip Sw(1)" , BIT_DIPSWITCH, BjDip + 0 , "dip" }, + {"Dip Sw(2)" , BIT_DIPSWITCH, BjDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo BjDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xc0, NULL}, + {0x10, 0xff, 0xff, 0x00, NULL}, + + // Dip Sw(1) + {0, 0xfe, 0, 4, "Coin A"}, + {0x0f, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x0f, 0x01, 0x03, 0x01, "1 coin 2 credits"}, + {0x0f, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + {0x0f, 0x01, 0x03, 0x03, "1 coin 6 credits"}, + + {0, 0xfe, 0, 4, "Coin B"}, + {0x0f, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x0f, 0x01, 0x0c, 0x00, "1 coin 1 credit"}, + {0x0f, 0x01, 0x0c, 0x08, "1 coin 2 credits"}, + {0x0f, 0x01, 0x0c, 0x0c, "1 coin 3 credits"}, + + {0, 0xfe, 0, 4, "Lives"}, + {0x0f, 0x01, 0x30, 0x30, "2"}, + {0x0f, 0x01, 0x30, 0x00, "3"}, + {0x0f, 0x01, 0x30, 0x10, "4"}, + {0x0f, 0x01, 0x30, 0x20, "5"}, + + {0, 0xfe, 0, 2, "Cabinet"}, + {0x0f, 0x01, 0x40, 0x40, "Upright"}, + {0x0f, 0x01, 0x40, 0x00, "Cocktail"}, + + {0, 0xfe, 0, 2, "Demo sounds"}, + {0x0f, 0x01, 0x80, 0x00, "Off"}, + {0x0f, 0x01, 0x80, 0x80, "On"}, + + // Dip Sw(2) + {0, 0xfe, 0, 4, "Initial high score"}, + {0x10, 0x01, 0x07, 0x00, "10000"}, + {0x10, 0x01, 0x07, 0x01, "100000"}, + {0x10, 0x01, 0x07, 0x02, "30000"}, + {0x10, 0x01, 0x07, 0x03, "50000"}, + {0x10, 0x01, 0x07, 0x04, "100000"}, + {0x10, 0x01, 0x07, 0x05, "50000"}, + {0x10, 0x01, 0x07, 0x06, "100000"}, + {0x10, 0x01, 0x07, 0x07, "50000"}, + + {0, 0xfe, 0, 4, "Bird speed"}, + {0x10, 0x01, 0x18, 0x00, "Easy"}, + {0x10, 0x01, 0x18, 0x08, "Medium"}, + {0x10, 0x01, 0x18, 0x10, "Hard"}, + {0x10, 0x01, 0x18, 0x18, "Hardest"}, + + {0, 0xfe, 0, 4, "Enemies number & speed"}, + {0x10, 0x01, 0x60, 0x20, "Easy"}, + {0x10, 0x01, 0x60, 0x00, "Medium"}, + {0x10, 0x01, 0x60, 0x40, "Hard"}, + {0x10, 0x01, 0x60, 0x60, "Hardest"}, + + {0, 0xfe, 0, 2, "Special coin"}, + {0x10, 0x01, 0x80, 0x00, "Easy"}, + {0x10, 0x01, 0x80, 0x80, "Hard"}, +}; + +STDDIPINFO(Bj) + +// Bomb Jack (set 1) +static struct BurnRomInfo BombjackRomDesc[] = { + { "09_j01b.bin", 0x2000, 0xc668dc30, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "10_l01b.bin", 0x2000, 0x52a1e5fb, BRF_ESS | BRF_PRG }, // 1 + { "11_m01b.bin", 0x2000, 0xb68a062a, BRF_ESS | BRF_PRG }, // 2 + { "12_n01b.bin", 0x2000, 0x1d3ecee5, BRF_ESS | BRF_PRG }, // 3 + { "13.1r", 0x2000, 0x70e0244d, BRF_ESS | BRF_PRG }, // 4 + + // graphics 3 bit planes: + { "03_e08t.bin", 0x1000, 0x9f0470d5, BRF_GRA }, // chars + { "04_h08t.bin", 0x1000, 0x81ec12e6, BRF_GRA }, + { "05_k08t.bin", 0x1000, 0xe87ec8b1, BRF_GRA }, + + { "14_j07b.bin", 0x2000, 0x101c858d, BRF_GRA }, // sprites + { "15_l07b.bin", 0x2000, 0x013f58f2, BRF_GRA }, + { "16_m07b.bin", 0x2000, 0x94694097, BRF_GRA }, + + { "06_l08t.bin", 0x2000, 0x51eebd89, BRF_GRA }, // background tiles + { "07_n08t.bin", 0x2000, 0x9dd98e9d, BRF_GRA }, + { "08_r08t.bin", 0x2000, 0x3155ee7d, BRF_GRA }, + + { "02_p04t.bin", 0x1000, 0x398d4a02, BRF_GRA }, // background tilemaps + + { "01_h03t.bin", 0x2000, 0x8407917d, BRF_ESS | BRF_SND }, // sound CPU +}; + +STD_ROM_PICK(Bombjack) +STD_ROM_FN(Bombjack) + + +// Bomb Jack (set 2) +static struct BurnRomInfo Bombjac2RomDesc[] = { + { "09_j01b.bin", 0x2000, 0xc668dc30, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "10_l01b.bin", 0x2000, 0x52a1e5fb, BRF_ESS | BRF_PRG }, // 1 + { "11_m01b.bin", 0x2000, 0xb68a062a, BRF_ESS | BRF_PRG }, // 2 + { "12_n01b.bin", 0x2000, 0x1d3ecee5, BRF_ESS | BRF_PRG }, // 3 + { "13_r01b.bin", 0x2000, 0xbcafdd29, BRF_ESS | BRF_PRG }, // 4 + + // graphics 3 bit planes: + { "03_e08t.bin", 0x1000, 0x9f0470d5, BRF_GRA }, // chars + { "04_h08t.bin", 0x1000, 0x81ec12e6, BRF_GRA }, + { "05_k08t.bin", 0x1000, 0xe87ec8b1, BRF_GRA }, + + { "14_j07b.bin", 0x2000, 0x101c858d, BRF_GRA }, // sprites + { "15_l07b.bin", 0x2000, 0x013f58f2, BRF_GRA }, + { "16_m07b.bin", 0x2000, 0x94694097, BRF_GRA }, + + { "06_l08t.bin", 0x2000, 0x51eebd89, BRF_GRA }, // background tiles + { "07_n08t.bin", 0x2000, 0x9dd98e9d, BRF_GRA }, + { "08_r08t.bin", 0x2000, 0x3155ee7d, BRF_GRA }, + + { "02_p04t.bin", 0x1000, 0x398d4a02, BRF_GRA }, // background tilemaps + + { "01_h03t.bin", 0x2000, 0x8407917d, BRF_ESS | BRF_SND }, // sound CPU +}; + +STD_ROM_PICK(Bombjac2) +STD_ROM_FN(Bombjac2) + + +static INT32 DrvDoReset() +{ + bombjackIRQ = 0; + latch = 0; + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + for (INT32 i = 0; i < 3; i++) { + AY8910Reset(i); + } + return 0; +} + + +UINT8 __fastcall BjMemRead(UINT16 addr) +{ + UINT8 inputs=0; + + if (addr >= 0x9820 && addr <= 0x987f) return BjSprRam[addr - 0x9820]; + + if (addr==0xb000) { + if (DrvJoy1[5]) + inputs|=0x01; + if (DrvJoy1[4]) + inputs|=0x02; + if (DrvJoy1[2]) + inputs|=0x04; + if (DrvJoy1[3]) + inputs|=0x08; + if (DrvJoy1[6]) + inputs|=0x10; + return inputs; + } + if (addr==0xb001) { + if (DrvJoy2[5]) + inputs|=0x01; + if (DrvJoy2[4]) + inputs|=0x02; + if (DrvJoy2[2]) + inputs|=0x04; + if (DrvJoy2[3]) + inputs|=0x08; + if (DrvJoy2[6]) + inputs|=0x10; + return inputs; + } + if (addr==0xb002) { + if (DrvJoy1[0]) + inputs|=0x01; + if (DrvJoy1[1]) + inputs|=0x04; + if (DrvJoy2[0]) + inputs|=0x02; + if (DrvJoy2[1]) + inputs|=0x08; + return inputs; + } + if (addr==0xb004) { + return BjDip[0]; // Dip Sw(1) + } + if (addr==0xb005) { + return BjDip[1]; // Dip Sw(2) + } + return 0; +} + +void __fastcall BjMemWrite(UINT16 addr,UINT8 val) +{ + if (addr >= 0x9820 && addr <= 0x987f) { BjSprRam[addr - 0x9820] = val; return; } + + if (addr==0xb000) + { + bombjackIRQ = val; + } + if(addr==0xb800) + { + latch=val; + return; + } + BjRam[addr]=val; +} + +UINT8 __fastcall SndMemRead(UINT16 a) +{ + if (a==0xFF00) + { + return 0x7f; + } + if(a==0x6000) + { + INT32 res; + res = latch; + latch = 0; + return res; + } + return 0; +} + + + +void __fastcall SndPortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + switch (a) { + case 0x00: { + AY8910Write(0, 0, d); + return; + } + case 0x01: { + AY8910Write(0, 1, d); + return; + } + case 0x10: { + AY8910Write(1, 0, d); + return; + } + case 0x11: { + AY8910Write(1, 1, d); + return; + } + case 0x80: { + AY8910Write(2, 0, d); + return; + } + case 0x81: { + AY8910Write(2, 1, d); + return; + } + } +} + +INT32 BjZInit() +{ + // Init the z80 + ZetInit(2); + // Main CPU setup + ZetOpen(0); + + ZetMapArea (0x0000,0x7fff,0,BjRom+0x0000); // Direct Read from ROM + ZetMapArea (0x0000,0x7fff,2,BjRom+0x0000); // Direct Fetch from ROM + ZetMapArea (0xc000,0xdfff,0,BjRom+0x8000); // Direct Read from ROM + ZetMapArea (0xc000,0xdfff,2,BjRom+0x8000); // Direct Fetch from ROM + + ZetMapArea (0x8000,0x8fff,0,BjRam+0x8000); + ZetMapArea (0x8000,0x8fff,1,BjRam+0x8000); + + ZetMapArea (0x9000,0x93ff,0,BjVidRam); + ZetMapArea (0x9000,0x93ff,1,BjVidRam); + + ZetMapArea (0x9400,0x97ff,0,BjColRam); + ZetMapArea (0x9400,0x97ff,1,BjColRam); + +// ZetMapArea (0x9820,0x987f,0,BjSprRam); +// ZetMapArea (0x9820,0x987f,1,BjSprRam); + + ZetMapArea (0x9c00,0x9cff,0,BjPalSrc); + ZetMapArea (0x9c00,0x9cff,1,BjPalSrc); + + ZetMapArea (0x9e00,0x9e00,0,BjRam+0x9e00); + ZetMapArea (0x9e00,0x9e00,1,BjRam+0x9e00); + + // ZetMapArea (0xb000,0xb000,0,BjRam+0xb000); + // ZetMapArea (0xb000,0xb000,1,BjRam+0xb000); + + // ZetMapArea (0xb800,0xb800,0,BjRam+0xb800); + // ZetMapArea (0xb800,0xb800,1,BjRam+0xb800); + + ZetSetReadHandler(BjMemRead); + ZetSetWriteHandler(BjMemWrite); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea (0x0000,0x1fff,0,SndRom); // Direct Read from ROM + ZetMapArea (0x0000,0x1fff,2,SndRom); // Direct Fetch from ROM + ZetMapArea (0x4000,0x43ff,0,SndRam); + ZetMapArea (0x4000,0x43ff,1,SndRam); + ZetMapArea (0x4000,0x43ff,2,SndRam); // fetch from ram? + ZetMapArea (0xff00,0xffff,0,SndRam); + ZetMapArea (0xff00,0xffff,1,SndRam); + ZetMapArea (0xff00,0xffff,2,SndRam); // more fetch from ram? What the hell . . + + // ZetMapArea (0x6000,0x6000,0,BjRam+0xb800); + // ZetMapArea (0x6000,0x6000,1,BjRam+0xb800); + ZetSetReadHandler(SndMemRead); + ZetSetOutHandler(SndPortWrite); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + pAY8910Buffer[6] = pFMBuffer + nBurnSoundLen * 6; + pAY8910Buffer[7] = pFMBuffer + nBurnSoundLen * 7; + pAY8910Buffer[8] = pFMBuffer + nBurnSoundLen * 8; + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(2, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + // remember to do ZetReset() in main driver + + DrvDoReset(); + return 0; +} + + + +void DecodeTiles(UINT8 *TilePointer, INT32 num,INT32 off1,INT32 off2, INT32 off3) +{ + INT32 c,y,x,dat1,dat2,dat3,col; + for (c=0;c>=1; + dat2>>=1; + dat3>>=1; + } + } + } +} + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + BjRom = Next; Next += 0x10000; + BjGfx = Next; Next += 0x0f000; + BjMap = Next; Next += 0x01000; + SndRom = Next; Next += 0x02000; + RamStart = Next; + BjRam = Next; Next += 0x10000; + SndRam = Next; Next += 0x01000; + BjPalSrc = Next; Next += 0x00100; + BjVidRam = Next; Next += 0x00400; + BjColRam = Next; Next += 0x00400; + BjSprRam = Next; Next += 0x00060; + RamEnd = Next; + text = Next; Next += 512 * 8 * 8; + sprites = Next; Next += 1024 * 8 * 8; + tiles = Next; Next += 1024 * 8 * 8; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 9 * sizeof(INT16); + BjPalReal = (UINT32*)Next; Next += 0x0080 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + + +INT32 BjInit() +{ + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + for (INT32 i =0; i<5 ; i++) + { + BurnLoadRom(BjRom+(0x2000*i),i,1); // load code roms + } + + for (INT32 i=0;i<3;i++) + { + BurnLoadRom(BjGfx+(0x1000*i),i+5,1); + } + + BurnLoadRom(BjGfx+0x3000,8,1); + BurnLoadRom(BjGfx+0x5000,9,1); + BurnLoadRom(BjGfx+0x7000,10,1); + + BurnLoadRom(BjGfx+0x9000,11,1); + BurnLoadRom(BjGfx+0xB000,12,1); + BurnLoadRom(BjGfx+0xD000,13,1); + + BurnLoadRom(BjMap,14,1); // load Background tile maps + BurnLoadRom(SndRom,15,1); // load Sound CPU + + // Set memory access & Init + BjZInit(); + + DecodeTiles(text,512,0,0x1000,0x2000); + DecodeTiles(sprites,1024,0x7000,0x5000,0x3000); + DecodeTiles(tiles,1024,0x9000,0xB000,0xD000); + // done + + GenericTilesInit(); + + DrvDoReset(); + return 0; +} + +INT32 BjExit() +{ + ZetExit(); + + for (INT32 i = 0; i < 3; i++) { + AY8910Exit(i); + } + + GenericTilesExit(); + BurnFree(Mem); + return 0; +} + +static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 0) & 0x0f; + g = (nColour >> 4) & 0x0f; + b = (nColour >> 8) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +INT32 CalcAll() +{ + for (INT32 i = 0; i < 0x100; i++) { + BjPalReal[i / 2] = CalcCol(BjPalSrc[i & ~1] | (BjPalSrc[i | 1] << 8)); + } + + return 0; +} + +void BjRenderFgLayer() +{ + for (INT32 tileCount = 0; tileCount < 1024 ;tileCount++) + { + INT32 code = BjVidRam[tileCount] + 16 * (BjColRam[tileCount] & 0x10); + INT32 color = BjColRam[tileCount] & 0x0f; + INT32 sy = (tileCount % 32); + INT32 sx = 31 - (tileCount / 32); + + sx<<=3; + sx-=16; + sy<<=3; + if (sx >= 0 && sx < 215 && sy >= 0 && sy < 246) + { + Render8x8Tile_Mask(pTransDraw, code,sx,sy,color, 3, 0, 0, text); + } + else + { + Render8x8Tile_Mask_Clip(pTransDraw, code,sx,sy,color, 3, 0, 0, text); + } + } +} + + +void BjRenderBgLayer() +{ + for (INT32 tileCount = 0; tileCount < 256;tileCount++) { + INT32 FlipX; + + INT32 BgSel=BjRam[0x9e00]; + + INT32 offs = (BgSel & 0x07) * 0x200 + tileCount; + INT32 Code = (BgSel & 0x10) ? BjMap[offs] : 0; + + INT32 attr = BjMap[offs + 0x100]; + INT32 Colour = attr & 0x0f; + //INT32 flags = (attr & 0x80) ? TILE_FLIPY : 0; + + + INT32 sy = (tileCount % 16); + INT32 sx = 15 - (tileCount / 16); + FlipX = attr & 0x80; + + /*if (SolomonFlipScreen) { + sx = 31 - sx; + sy = 31 - sy; + FlipX = !FlipX; + FlipY = !FlipY; + }*/ + + sx <<= 4; + sx -=16; + sy <<= 4; + Code <<= 2; + if (sx >= 0 && sx < 215 && sy >= 0 && sy < 246) { + + if (FlipX&0x80) + { + Render8x8Tile_Mask(pTransDraw, Code+0,sx+8,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+1,sx+8,sy+8, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+2,sx+0,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+3,sx+0,sy+8, Colour, 3, 0, 0, tiles); + + } + else + { + Render8x8Tile_Mask(pTransDraw, Code+0,sx+8,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+1,sx+8,sy+8, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+2,sx+0,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask(pTransDraw, Code+3,sx+0,sy+8, Colour, 3, 0, 0, tiles); + } + + } else { + + if (FlipX&0x80) + { + Render8x8Tile_Mask_Clip(pTransDraw, Code+0,sx+8,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+1,sx+8,sy+8, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+2,sx+0,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+3,sx+0,sy+8, Colour, 3, 0, 0, tiles); + + } + else + { + Render8x8Tile_Mask_Clip(pTransDraw, Code+0,sx+8,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+1,sx+8,sy+8, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+2,sx+0,sy+0, Colour, 3, 0, 0, tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code+3,sx+0,sy+8, Colour, 3, 0, 0, tiles); + } + + } + } +} + + +static void BjDrawSprites() +{ + INT32 offs; + + for (offs = 0x60 - 4; offs >= 0; offs -= 4) + { + + /* + abbbbbbb cdefgggg hhhhhhhh iiiiiiii + + a use big sprites (32x32 instead of 16x16) + bbbbbbb sprite code + c x flip + d y flip (used only in death sequence?) + e ? (set when big sprites are selected) + f ? (set only when the bonus (B) materializes?) + gggg color + hhhhhhhh x position + iiiiiiii y position + */ + INT32 sx,sy,flipx,flipy, code, colour, big; + + + sy = BjSprRam[offs+3]; + if (BjSprRam[offs] & 0x80) + sx = BjSprRam[offs+2]; + else + sx = BjSprRam[offs+2]; + flipx = BjSprRam[offs+1] & 0x80; + flipy = BjSprRam[offs+1] & 0x40; + + code = BjSprRam[offs] & 0x7f; + colour = (BjSprRam[offs+1] & 0x0f); + big = (BjSprRam[offs] & 0x80); + + //sy -= 32; + + sx -=16; + if (!big) + { + code <<= 2; + if (sx >= 0 && sx < 215 && sy >= 0 && sy < 246) { + if (!flipy) { + if (!flipx) { + Render8x8Tile_Mask(pTransDraw, code + 0, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code + 1, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code + 2, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code + 3, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, code + 2, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX(pTransDraw, code + 3, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX(pTransDraw, code + 0, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX(pTransDraw, code + 1, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } + } else { + if (!flipx) { + Render8x8Tile_Mask_FlipY(pTransDraw, code + 1, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipY(pTransDraw, code + 0, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipY(pTransDraw, code + 3, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipY(pTransDraw, code + 2, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } else { + Render8x8Tile_Mask_FlipXY(pTransDraw, code + 3, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY(pTransDraw, code + 2, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY(pTransDraw, code + 1, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY(pTransDraw, code + 0, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } + } + } else { + if (!flipy) { + if (!flipx) { + Render8x8Tile_Mask_Clip(pTransDraw, code + 0, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code + 1, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code + 2, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code + 3, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 2, sx + 8, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 3, sx + 8, sy + 8, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 0, sx + 0, sy + 0, colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 1, sx + 0, sy + 8, colour, 3, 0, 0, sprites); + } + } else { + if (!flipx) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 1, sx + 0, sy + 0, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 0, sx + 0, sy + 8, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 3, sx + 8, sy + 0, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 2, sx + 8, sy + 8, colour, 4, 0, 0, sprites); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 3, sx + 8, sy + 0, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 2, sx + 8, sy + 8, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 1, sx + 0, sy + 0, colour, 4, 0, 0, sprites); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 0, sx + 0, sy + 8, colour, 4, 0, 0, sprites); + } + } + } + } + else + { + code&=31; + code <<= 4; + sx-=1; + if (sx >= 0 && sx < 215 && sy >= 0 && sy < 246) + { + if (!flipy) + { + if (!flipx) { + Render8x8Tile_Mask(pTransDraw, code+512,sx+8+16,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+513,sx+8+16,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+514,sx+16,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+515,sx+16,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+516,sx+8+16,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+517,sx+8+16,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+518,sx+16,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+519,sx+16,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+520,sx+8,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+521,sx+8,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+522,sx,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+523,sx,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+524,sx+8,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+525,sx+8,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+526,sx,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask(pTransDraw, code+527,sx,sy+8+16,colour, 3, 0, 0, sprites); + } + } + } + else + { + if (!flipy) + { + if (!flipx) { + Render8x8Tile_Mask_Clip(pTransDraw, code+512,sx+8+16,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+513,sx+8+16,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+514,sx+16,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+515,sx+16,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+516,sx+8+16,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+517,sx+8+16,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+518,sx+16,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+519,sx+16,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+520,sx+8,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+521,sx+8,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+522,sx,sy,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+523,sx,sy+8,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+524,sx+8,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+525,sx+8,sy+8+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+526,sx,sy+16,colour, 3, 0, 0, sprites); + Render8x8Tile_Mask_Clip(pTransDraw, code+527,sx,sy+8+16,colour, 3, 0, 0, sprites); + } + } + } + } + } +} + +INT32 BjFrame() +{ + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 1) + { + if(bombjackIRQ) + { + ZetNmi(); + } + } + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + /*ZetOpen(0); + if (BjRam[0xb000]) + ZetNmi(); + ZetClose();*/ + + ZetOpen(1); + ZetNmi(); + ZetClose(); + + + if (pBurnDraw != NULL) + { + BurnTransferClear(); + CalcAll(); + + BjRenderBgLayer(); + BjRenderFgLayer(); + BjDrawSprites(); + BurnTransferCopy(BjPalReal); + } + return 0; +} + +static INT32 BjScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); // Scan Z80 + + // Scan critical driver variables + SCAN_VAR(bombjackIRQ); + SCAN_VAR(latch); + SCAN_VAR(DrvJoy1); + SCAN_VAR(DrvJoy2); + SCAN_VAR(BjDip); + } + + return 0; +} + +struct BurnDriver BurnDrvBombjack = { + "bombjack", NULL, NULL, NULL, "1984", + "Bomb Jack (set 1)\0", NULL, "Tehkan", "Bomb Jack", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING,2,HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, BombjackRomInfo,BombjackRomName, NULL, NULL,DrvInputInfo,BjDIPInfo, + BjInit,BjExit,BjFrame,NULL,BjScan, + NULL,0x80,224,256,3,4 +}; + +struct BurnDriver BurnDrvBombjac2 = { + "bombjack2", "bombjack", NULL, NULL, "1984", + "Bomb Jack (set 2)\0", NULL, "Tehkan", "Bomb Jack", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE,2,HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, Bombjac2RomInfo,Bombjac2RomName, NULL, NULL,DrvInputInfo,BjDIPInfo, + BjInit,BjExit,BjFrame,NULL,BjScan, + NULL,0x80,224,256,3,4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_chaknpop.cpp b/src/burn/drivers/misc_pre90s/d_chaknpop.cpp new file mode 100644 index 00000000..9e94b83d --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_chaknpop.cpp @@ -0,0 +1,779 @@ +// FB Alpha Chack'n Pop driver module +// Based on MAME driver by BUT + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvMcuROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvMcuRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; +static INT16 *pAY8910Buffer[6]; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *gfxmode; +static UINT8 *gfxflip; +static UINT8 *rambank; + +static UINT8 DrvInputs[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static UINT8 mcu_seed; +static UINT8 mcu_result; +static UINT8 mcu_select; + +static struct BurnInputInfo ChaknpopInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 7, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Chaknpop) + +static struct BurnDIPInfo ChaknpopDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x4f, NULL }, + {0x15, 0xff, 0xff, 0x7d, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x13, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x13, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x03, 0x00, "80k and every 100k" }, + {0x14, 0x01, 0x03, 0x01, "60k and every 100k" }, + {0x14, 0x01, 0x03, 0x02, "40k and every 100k" }, + {0x14, 0x01, 0x03, 0x03, "20k and every 100k" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x18, 0x00, "6" }, + {0x14, 0x01, 0x18, 0x08, "3" }, + {0x14, 0x01, 0x18, 0x10, "2" }, + {0x14, 0x01, 0x18, 0x18, "1" }, + + {0 , 0xfe, 0 , 2, "Training/Difficulty" }, + {0x14, 0x01, 0x20, 0x20, "Off/Every 10 Min." }, + {0x14, 0x01, 0x20, 0x00, "On/Every 7 Min." }, + +// {0 , 0xfe, 0 , 2, "Flip Screen" }, +// {0x14, 0x01, 0x40, 0x40, "Off" }, +// {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x80, 0x00, "Upright" }, + {0x14, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x15, 0x01, 0x01, 0x00, "English" }, + {0x15, 0x01, 0x01, 0x01, "Japanese" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Super Chack'n" }, + {0x15, 0x01, 0x04, 0x04, "pi" }, + {0x15, 0x01, 0x04, 0x00, "1st Chance" }, + + {0 , 0xfe, 0 , 2, "Endless (Cheat)" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Credit Info" }, + {0x15, 0x01, 0x10, 0x00, "Off" }, + {0x15, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Show Year" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Infinite (Cheat)" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x15, 0x01, 0x80, 0x00, "1 Way" }, + {0x15, 0x01, 0x80, 0x80, "2 Way" }, +}; + +STDDIPINFO(Chaknpop) + +static const UINT8 mcu_data[256] = { + 0x3a, 0xe6, 0x80, 0xc6, 0x0e, 0xdd, 0x77, 0xfd, + 0x7e, 0xfe, 0x10, 0x38, 0x10, 0xdd, 0x7e, 0x03, + 0xc6, 0x08, 0xdd, 0x77, 0x03, 0xdd, 0x7e, 0xff, + 0xc6, 0x08, 0xdd, 0x77, 0xff, 0x34, 0x23, 0xc9, + 0x06, 0x10, 0xdd, 0xe5, 0xe1, 0x23, 0x23, 0x23, + 0x4e, 0x23, 0x5e, 0x23, 0x56, 0x23, 0x23, 0x7b, + 0xb2, 0x28, 0x02, 0x79, 0x12, 0x10, 0xf1, 0xc9, + 0xe6, 0x03, 0x87, 0x87, 0x6f, 0x26, 0x00, 0x29, + 0x29, 0x29, 0xe5, 0x29, 0x29, 0x29, 0xc1, 0x09, + 0x01, 0xc3, 0x81, 0x09, 0xe5, 0xdd, 0xe1, 0xc9, + 0x10, 0x00, 0x08, 0x10, 0x20, 0x64, 0x50, 0x00, + 0x08, 0x50, 0xb0, 0x01, 0x34, 0xa0, 0x13, 0x34, + 0xb0, 0x05, 0x34, 0xc0, 0x04, 0x34, 0xd0, 0x02, + 0x34, 0xf0, 0x02, 0x34, 0x00, 0x60, 0x00, 0x00, + 0x3f, 0x00, 0x0c, 0x1f, 0xa0, 0x3f, 0x1e, 0xa2, + 0x01, 0x1e, 0xa1, 0x0a, 0x1e, 0xa2, 0x07, 0x1e, + 0x92, 0x05, 0x1e, 0x02, 0x04, 0x1e, 0x12, 0x09, + 0x3f, 0x22, 0x06, 0x3f, 0x21, 0x03, 0x3f, 0x20, + 0x02, 0x00, 0x00, 0x3f, 0x00, 0x04, 0x02, 0xa0, + 0x40, 0x12, 0xa1, 0x06, 0x12, 0xa2, 0x02, 0x12, + 0xa1, 0x0a, 0x12, 0xa2, 0x07, 0x10, 0x92, 0x05, + 0x10, 0x02, 0x04, 0x12, 0x12, 0x09, 0x12, 0x22, + 0x06, 0x12, 0x21, 0x03, 0x12, 0x20, 0x02, 0x26, + 0x00, 0x14, 0x12, 0x00, 0x00, 0x00, 0x3f, 0x00, + 0x04, 0x1a, 0xa0, 0x40, 0x3f, 0x00, 0x00, 0x00, + 0x3e, 0x3a, 0x87, 0x83, 0x3c, 0x32, 0x87, 0x83, + 0x0f, 0x0f, 0xe6, 0x07, 0xfe, 0x02, 0x20, 0x01, + 0xaf, 0x11, 0x40, 0x98, 0x1d, 0x12, 0x1d, 0x20, + 0xfb, 0x2a, 0x89, 0x83, 0x2b, 0x22, 0x89, 0x83, + 0xc9, 0x3a, 0x5b, 0x81, 0xa7, 0xc0, 0x21, 0x80, + 0x81, 0x11, 0x04, 0x00, 0x06, 0x09, 0x34, 0x19, + 0x10, 0xfc, 0x3e, 0x01, 0x32, 0x5b, 0x81, 0xc9 +}; + +static void mcu_update_seed(UINT8 data) +{ + if (!(data & 0x80)) + { + mcu_seed += 0x83; + mcu_seed = (mcu_seed & 0x80) | (mcu_seed >> 1); + } + + mcu_seed += 0x19; +} + +static void chaknpop_mcu_port_a_write(UINT8 data) +{ + UINT8 mcu_command = data + mcu_seed; + mcu_result = 0; + + if (mcu_command < 0x08) + { + mcu_update_seed(data); + + mcu_result = DrvMcuRAM[mcu_select * 8 + mcu_command] - mcu_seed; + + mcu_update_seed(mcu_result); + } + else if (mcu_command >= 0x28 && mcu_command <= 0x2a) + { + mcu_update_seed(data); + + mcu_result = DrvMcuRAM[0x380 + mcu_command] - mcu_seed; + + mcu_update_seed(mcu_result); + } + else if (mcu_command < 0x80) + { + mcu_update_seed(data); + + if (mcu_command >= 0x40 && mcu_command < 0x60) + { + mcu_select = mcu_command - 0x40; + } + } + else if (mcu_command == 0x9c|| mcu_command == 0xde) + { + mcu_update_seed(data); + } +} + +UINT8 __fastcall chaknpop_read(UINT16 address) +{ + switch (address) + { + case 0x8800: + return mcu_result; + + case 0x8801: + case 0x8802: + return 0xff; // MCU port b & c + + case 0x8804: + case 0x8805: + return AY8910Read(0); + + case 0x8806: + case 0x8807: + return AY8910Read(1); + + case 0x8808: + return DrvDips[2]; + + case 0x8809: + return DrvInputs[1]; + + case 0x880a: + return DrvInputs[0]; + + case 0x880b: + return DrvInputs[2]; + + case 0x880c: + return gfxmode[0]; + } + + return 0; +} + +static void bankswitch(INT32 bank) +{ + if (rambank[0] != bank) { + rambank[0] = bank; + + bank = bank ? 0x4000 : 0; + + ZetMapArea(0xc000, 0xffff, 0, DrvZ80RAM + bank); + ZetMapArea(0xc000, 0xffff, 1, DrvZ80RAM + bank); + ZetMapArea(0xc000, 0xffff, 2, DrvZ80RAM + bank); + } +} + +void __fastcall chaknpop_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8800: + chaknpop_mcu_port_a_write(data); + return; + + case 0x8801: + case 0x8802: // MCU port b & c + return; + + case 0x8804: + case 0x8805: + AY8910Write(0, address & 1, data); + return; + + case 0x8806: + case 0x8807: + AY8910Write(1, address & 1, data); + return; + + case 0x880c: { + gfxflip[0] = data & 0x01; + gfxflip[1] = data & 0x02; + bankswitch(data & 0x04); + gfxmode[0] = data; + } + return; + + case 0x880d: // coin lockout + return; + } +} + +static UINT8 ay8910_0_read_port_A(UINT32) +{ + return DrvDips[0]; +} + +static UINT8 ay8910_0_read_port_B(UINT32) +{ + return DrvDips[1]; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + + mcu_seed = 0x81; + mcu_result = 0; + mcu_select = 0; + + rambank[0] = 0xff; + bankswitch(0); + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 1024; i++) + { + INT32 bit0, bit1, bit2; + + INT32 col = (DrvColPROM[i] & 0x0f) + ((DrvColPROM[i + 1024] & 0x0f) << 4); + + bit0 = (col >> 0) & 0x01; + bit1 = (col >> 1) & 0x01; + bit2 = (col >> 2) & 0x01; + INT32 r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (col >> 3) & 0x01; + bit1 = (col >> 4) & 0x01; + bit2 = (col >> 5) & 0x01; + INT32 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (col >> 6) & 0x01; + bit2 = (col >> 7) & 0x01; + INT32 b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[2] = { 0, 0x2000*8 }; + INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7 , 8*8+0, 8*8+1, 8*8+2, 8*8+3, 8*8+4, 8*8+5, 8*8+6, 8*8+7 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x4000); + + GfxDecode(0x0100, 2, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x4000); + + GfxDecode(0x0400, 2, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x00c000; + + DrvMcuROM = Next; Next += 0x000800; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000800; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[3] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[4] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[5] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x008000; + DrvTxtRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000100; + DrvMcuRAM = Next; Next += 0x000800; + + gfxflip = Next; Next += 0x000002; + gfxmode = Next; Next += 0x000001; + rambank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x6000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0xa000, 4, 1)) return 1; + + // if (BurnLoadRom(DrvMcuROM + 0x0000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x2000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x0000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x2000, 9, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x0000, 10, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x0400, 11, 1)) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvMcuRAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvMcuRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvMcuRAM); + ZetMapArea(0x9000, 0x93ff, 0, DrvTxtRAM); + ZetMapArea(0x9000, 0x93ff, 1, DrvTxtRAM); + ZetMapArea(0x9000, 0x93ff, 2, DrvTxtRAM); + ZetMapArea(0x9800, 0x98ff, 0, DrvSprRAM); + ZetMapArea(0x9800, 0x98ff, 1, DrvSprRAM); + ZetMapArea(0x9800, 0x98ff, 2, DrvSprRAM); + ZetMapArea(0xa000, 0xbfff, 0, DrvZ80ROM + 0xa000); + ZetMapArea(0xa000, 0xbfff, 2, DrvZ80ROM + 0xa000); + bankswitch(0); + ZetSetWriteHandler(chaknpop_write); + ZetSetReadHandler(chaknpop_read); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1536000, nBurnSoundRate, &ay8910_0_read_port_A, &ay8910_0_read_port_B, NULL, NULL); + AY8910Init(1, 1536000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0xc0; offs += 4) + { + INT32 sy = 241 - DrvSprRAM[offs + 0x40]; + INT32 attr = DrvSprRAM[offs + 0x41]; + INT32 color = DrvSprRAM[offs + 0x42] & 0x07; + INT32 sx = DrvSprRAM[offs + 0x43]; + INT32 flipx = attr & 0x40; + INT32 flipy = attr & 0x80; + INT32 code = (attr & 0x3f) | ((DrvSprRAM[offs + 0x42] & 0x38) << 3); + + if (gfxflip[0]) { + sx = 240 - sx; + flipx = !flipx; + } + + if (gfxflip[1]) { + sy = 242 - sy; + flipy = !flipy; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy - 16, color, 2, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy - 16, color, 2, 0, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy - 16, color, 2, 0, 0, DrvGfxROM0); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 2, 0, 0, DrvGfxROM0); + } + } + } +} + +static void draw_layer() +{ + for (INT32 offs = 32 * 2; offs < 32 * 32 - 32 * 2; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = ((offs >> 5) << 3) - 16; + + INT32 code = DrvTxtRAM[offs]; + INT32 color = (code == 0x74) ? DrvSprRAM[0x0b] : DrvSprRAM[0x01]; + + if (gfxmode[0] & 0x20 && code >= 0xc0) code += 0xc0; + + code |= (gfxmode[0] & 0x80) << 2; + + if (gfxflip[1]) sy = ((sy+16)^0xff)-16; + if (gfxflip[0]) sx ^= 0xff; + + if (gfxflip[1]) { + if (gfxflip[0]) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color+8, 2, 0, DrvGfxROM1); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color+8, 2, 0, DrvGfxROM1); + } + } else { + if (gfxflip[0]) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color+8, 2, 0, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color+8, 2, 0, DrvGfxROM1); + } + } + } +} + +static void draw_bitmap() +{ + INT32 dx = gfxflip[0] ? -1 : 1; + + for (INT32 offs = 0+(16*32); offs < 0x2000-(16*32); offs++) + { + INT32 x = ((offs & 0x1f) << 3) + 7; + INT32 y = (offs >> 5) - 16; + + if (!gfxflip[0]) x = 255 - x; + if (!gfxflip[1]) y = 255 - y; + + if (y < 0 || y >= nScreenHeight) continue; + + for (INT32 i = 0x80; i > 0; i >>= 1, x += dx) + { + if (x >= nScreenWidth || x < 0) continue; + + UINT32 color = 0; + + if (DrvZ80RAM[0x0000+offs] & i) color |= 0x200; + if (DrvZ80RAM[0x4000+offs] & i) color |= 0x100; + if (DrvZ80RAM[0x2000+offs] & i) color |= 0x080; + if (DrvZ80RAM[0x6000+offs] & i) color |= 0x040; + + if (color) { + pTransDraw[y * nScreenWidth + x] |= color; + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_layer(); + draw_sprites(); + draw_bitmap(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetOpen(0); + ZetRun(2350000 / 60); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample, xSample; + + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + AY8910Update(0, &pAY8910Buffer[3], nBurnSoundLen); + + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + nSample = (nSample * 15) / 100; + + xSample = pAY8910Buffer[0][n]; + xSample += pAY8910Buffer[1][n]; + xSample += pAY8910Buffer[2][n]; + xSample = (xSample * 10) / 100; + + nSample += xSample; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(mcu_seed); + SCAN_VAR(mcu_result); + SCAN_VAR(mcu_select); + } + + if (nAction & ACB_WRITE) { + INT32 bank = rambank[0]; + rambank[0] = 0xff; + bankswitch(bank); + } + + return 0; +} + + +// Chack'n Pop + +static struct BurnRomInfo chaknpopRomDesc[] = { + { "ao4_01.ic28", 0x2000, 0x386fe1c8, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 code + { "ao4_02.ic27", 0x2000, 0x5562a6a7, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ao4_03.ic26", 0x2000, 0x3e2f0a9c, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ao4_04.ic25", 0x2000, 0x5209c7d4, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ao4_05.ic3", 0x2000, 0x8720e024, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "ao4_06.ic23", 0x0800, 0x00000000, 2 | BRF_NODUMP }, // 5 m68705 code (not dumped) + + { "ao4_08.ic14", 0x2000, 0x5575a021, 3 | BRF_GRA }, // 6 Sprites + { "ao4_07.ic15", 0x2000, 0xae687c18, 3 | BRF_GRA }, // 7 + + { "ao4_09.ic98", 0x2000, 0x757a723a, 4 | BRF_GRA }, // 8 Tiles + { "ao4_10.ic97", 0x2000, 0x3e3fd608, 4 | BRF_GRA }, // 9 + + { "ao4-11.ic96", 0x0400, 0x9bf0e85f, 5 | BRF_GRA }, // 10 Color PROMs + { "ao4-12.ic95", 0x0400, 0x954ce8fc, 5 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(chaknpop) +STD_ROM_FN(chaknpop) + +struct BurnDriver BurnDrvChaknpop = { + "chaknpop", NULL, NULL, NULL, "1983", + "Chack'n Pop\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, chaknpopRomInfo, chaknpopRomName, NULL, NULL, ChaknpopInputInfo, ChaknpopDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_commando.cpp b/src/burn/drivers/misc_pre90s/d_commando.cpp new file mode 100644 index 00000000..ce2bd7ad --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_commando.cpp @@ -0,0 +1,1098 @@ +#include "tiles_generic.h" +#include "burn_ym2203.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom1Op = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvFgVideoRam = NULL; +static UINT8 *DrvFgColourRam = NULL; +static UINT8 *DrvBgVideoRam = NULL; +static UINT8 *DrvBgColourRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteRamBuffer = NULL; +static UINT8 *DrvPromRed = NULL; +static UINT8 *DrvPromGreen = NULL; +static UINT8 *DrvPromBlue = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvBgScrollX[2]; +static UINT8 DrvBgScrollY[2]; +static UINT8 DrvFlipScreen; +static UINT8 DrvSoundLatch; + +static bool bFirstOpCodeEncrypted = false; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + + +STDINPUTINFO(Drv) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x1f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Starting Area" }, + {0x11, 0x01, 0x03, 0x03, "0 (Forest 1)" }, + {0x11, 0x01, 0x03, 0x01, "2 (Forest 1)" }, + {0x11, 0x01, 0x03, 0x02, "4 (Forest 2)" }, + {0x11, 0x01, 0x03, 0x00, "6 (Forest 2)" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x04, "2" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x08, "4" }, + {0x11, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0xc0, 0x00, "2 Coins 1 Play" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x11, 0x01, 0xc0, 0x40, "1 Coin 2 Plays" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0x30, 0x00, "4 Coins 1 Play" }, + {0x11, 0x01, 0x30, 0x20, "3 Coins 1 Play" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x12, 0x01, 0x07, 0x07, "10k 50k+" }, + {0x12, 0x01, 0x07, 0x03, "10k 60k+" }, + {0x12, 0x01, 0x07, 0x05, "20k 60k+" }, + {0x12, 0x01, 0x07, 0x01, "20k 70k+" }, + {0x12, 0x01, 0x07, 0x06, "30k 70k+" }, + {0x12, 0x01, 0x07, 0x02, "30k 80k+" }, + {0x12, 0x01, 0x07, 0x04, "40k 100k+" }, + {0x12, 0x01, 0x07, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x10, 0x10, "Normal" }, + {0x12, 0x01, 0x10, 0x00, "Difficult" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x12, 0x01, 0xc0, 0x00, "Upright" }, + {0x12, 0x01, 0xc0, 0x40, "Upright 2 Players" }, + {0x12, 0x01, 0xc0, 0xc0, "Cocktail" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo DrvRomDesc[] = { + { "cm04.9m", 0x08000, 0x8438b694, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "cm03.8m", 0x04000, 0x35486542, BRF_ESS | BRF_PRG }, // 1 + + { "cm02.9f", 0x04000, 0xf9cc4a74, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "vt01.5d", 0x04000, 0x505726e0, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "vt05.7e", 0x04000, 0x79f16e3d, BRF_GRA }, // 10 Sprites + { "vt06.8e", 0x04000, 0x26fee521, BRF_GRA }, // 11 + { "vt07.9e", 0x04000, 0xca88bdfd, BRF_GRA }, // 12 + { "vt08.7h", 0x04000, 0x2019c883, BRF_GRA }, // 13 + { "vt09.8h", 0x04000, 0x98703982, BRF_GRA }, // 14 + { "vt10.9h", 0x04000, 0xf069d2f8, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvuRomDesc[] = { + { "u4-f.9m", 0x08000, 0xa6118935, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "u3-f.8m", 0x04000, 0x24f49684, BRF_ESS | BRF_PRG }, // 1 + + { "cm02.9f", 0x04000, 0xf9cc4a74, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "vt01.5d", 0x04000, 0x505726e0, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "vt05.7e", 0x04000, 0x79f16e3d, BRF_GRA }, // 10 Sprites + { "vt06.8e", 0x04000, 0x26fee521, BRF_GRA }, // 11 + { "vt07.9e", 0x04000, 0xca88bdfd, BRF_GRA }, // 12 + { "vt08.7h", 0x04000, 0x2019c883, BRF_GRA }, // 13 + { "vt09.8h", 0x04000, 0x98703982, BRF_GRA }, // 14 + { "vt10.9h", 0x04000, 0xf069d2f8, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Drvu) +STD_ROM_FN(Drvu) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "so04.9m", 0x08000, 0xd3f2bfb3, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "so03.8m", 0x04000, 0xed01f472, BRF_ESS | BRF_PRG }, // 1 + + { "so02.9f", 0x04000, 0xca20aca5, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "vt01.5d", 0x04000, 0x505726e0, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "vt05.7e", 0x04000, 0x79f16e3d, BRF_GRA }, // 10 Sprites + { "vt06.8e", 0x04000, 0x26fee521, BRF_GRA }, // 11 + { "vt07.9e", 0x04000, 0xca88bdfd, BRF_GRA }, // 12 + { "vt08.7h", 0x04000, 0x2019c883, BRF_GRA }, // 13 + { "vt09.8h", 0x04000, 0x98703982, BRF_GRA }, // 14 + { "vt10.9h", 0x04000, 0xf069d2f8, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "commandob_04_9m_27256.bin", 0x08000, 0x348a7654, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "cm03.8m", 0x04000, 0x35486542, BRF_ESS | BRF_PRG }, // 1 + + { "cm02.9f", 0x04000, 0xf9cc4a74, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "vt01.5d", 0x04000, 0x505726e0, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "vt05.7e", 0x04000, 0x79f16e3d, BRF_GRA }, // 10 Sprites + { "vt06.8e", 0x04000, 0x26fee521, BRF_GRA }, // 11 + { "vt07.9e", 0x04000, 0xca88bdfd, BRF_GRA }, // 12 + { "vt08.7h", 0x04000, 0x2019c883, BRF_GRA }, // 13 + { "vt09.8h", 0x04000, 0x98703982, BRF_GRA }, // 14 + { "vt10.9h", 0x04000, 0xf069d2f8, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 + + { "commandob_pal16l8a.bin", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, // 22 PLDs +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo SinvasnRomDesc[] = { + { "sp04.9m", 0x08000, 0x33f9601e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "sp03.8m", 0x04000, 0xc7fb43b3, BRF_ESS | BRF_PRG }, // 1 + + { "u2.9f", 0x04000, 0xcbf8c40e, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "u1.5d", 0x04000, 0xf477e13a, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "u5.e7", 0x04000, 0x2a97c933, BRF_GRA }, // 10 Sprites + { "sp06.e8", 0x04000, 0xd7887212, BRF_GRA }, // 11 + { "sp07.e9", 0x04000, 0x9abe7a20, BRF_GRA }, // 12 + { "u8.h7", 0x04000, 0xd6b4aa2e, BRF_GRA }, // 13 + { "sp09.h8", 0x04000, 0x3985b318, BRF_GRA }, // 14 + { "sp10.h9", 0x04000, 0x3c131b0f, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Sinvasn) +STD_ROM_FN(Sinvasn) + +static struct BurnRomInfo SinvasnbRomDesc[] = { + { "u4", 0x08000, 0x834ba0de, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "u3", 0x04000, 0x07e4ee3a, BRF_ESS | BRF_PRG }, // 1 + + { "u2", 0x04000, 0xcbf8c40e, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "u1", 0x04000, 0xf477e13a, BRF_GRA }, // 3 Characters + + { "vt11.5a", 0x04000, 0x7b2e1b48, BRF_GRA }, // 4 Tiles + { "vt12.6a", 0x04000, 0x81b417d3, BRF_GRA }, // 5 + { "vt13.7a", 0x04000, 0x5612dbd2, BRF_GRA }, // 6 + { "vt14.8a", 0x04000, 0x2b2dee36, BRF_GRA }, // 7 + { "vt15.9a", 0x04000, 0xde70babf, BRF_GRA }, // 8 + { "vt16.10a", 0x04000, 0x14178237, BRF_GRA }, // 9 + + { "u5", 0x04000, 0x2a97c933, BRF_GRA }, // 10 Sprites + { "vt06.e8", 0x04000, 0x26fee521, BRF_GRA }, // 11 + { "vt07.e9", 0x04000, 0xca88bdfd, BRF_GRA }, // 12 + { "u8", 0x04000, 0xd6b4aa2e, BRF_GRA }, // 13 + { "vt09.h8", 0x04000, 0x98703982, BRF_GRA }, // 14 + { "vt10.h9", 0x04000, 0xf069d2f8, BRF_GRA }, // 15 + + { "vtb1.1d", 0x00100, 0x3aba15a1, BRF_GRA }, // 16 PROMs + { "vtb2.2d", 0x00100, 0x88865754, BRF_GRA }, // 17 + { "vtb3.3d", 0x00100, 0x4c14c3f6, BRF_GRA }, // 18 + { "vtb4.1h", 0x00100, 0xb388c246, BRF_GRA }, // 19 + { "vtb5.6l", 0x00100, 0x712ac508, BRF_GRA }, // 20 + { "vtb6.6e", 0x00100, 0x0eaf5158, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Sinvasnb) +STD_ROM_FN(Sinvasnb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x0c000; + DrvZ80Rom1Op = Next; Next += 0x0c000; + DrvZ80Rom2 = Next; Next += 0x04000; + DrvPromRed = Next; Next += 0x00100; + DrvPromGreen = Next; Next += 0x00100; + DrvPromBlue = Next; Next += 0x00100; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x01e00; + DrvZ80Ram2 = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x00180; + DrvSpriteRamBuffer = Next; Next += 0x00180; + DrvBgVideoRam = Next; Next += 0x00400; + DrvBgColourRam = Next; Next += 0x00400; + DrvFgVideoRam = Next; Next += 0x00400; + DrvFgColourRam = Next; Next += 0x00400; + + RamEnd = Next; + + DrvChars = Next; Next += 0x400 * 8 * 8; + DrvTiles = Next; Next += 0x400 * 16 * 16; + DrvSprites = Next; Next += 0x300 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnYM2203Reset(); + + DrvBgScrollX[0] = DrvBgScrollX[1] = 0; + DrvBgScrollY[0] = DrvBgScrollY[1] = 0; + DrvFlipScreen = 0; + DrvSoundLatch = 0; + + return 0; +} + +UINT8 __fastcall CommandoRead1(UINT16 a) +{ + switch (a) { + case 0xc000: { + return 0xff - DrvInput[0]; + } + + case 0xc001: { + return 0xff - DrvInput[1]; + } + + case 0xc002: { + return 0xff - DrvInput[2]; + } + + case 0xc003: { + return DrvDip[0]; + } + + case 0xc004: { + return DrvDip[1]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall CommandoWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xc800: { + DrvSoundLatch = d; + return; + } + + case 0xc804: { + DrvFlipScreen = d & 0x80; + + if (d & 0x10) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + } + + return; + } + + case 0xc806: { + // ??? + return; + } + + case 0xc808: { + DrvBgScrollX[0] = d; + return; + } + + case 0xc809: { + DrvBgScrollX[1] = d; + return; + } + + case 0xc80a: { + DrvBgScrollY[0] = d; + return; + } + + case 0xc80b: { + DrvBgScrollY[1] = d; + return; + } + + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall CommandoRead2(UINT16 a) +{ + switch (a) { + case 0x6000: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall CommandoWrite2(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x8000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x8001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0x8002: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0x8003: { + BurnYM2203Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static INT32 CharPlaneOffsets[2] = { 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 TilePlaneOffsets[3] = { 0, 0x40000, 0x80000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 SpritePlaneOffsets[4] = { 0x60004, 0x60000, 4, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x18000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x08000, 1, 1); if (nRet != 0) return 1; + + if (bFirstOpCodeEncrypted) { + for (INT32 A = 0; A < 0xc000; A++) { + INT32 src; + + src = DrvZ80Rom1[A]; + DrvZ80Rom1Op[A] = (src & 0x11) | ((src & 0xe0) >> 4) | ((src & 0x0e) << 4); + } + } else { + DrvZ80Rom1Op[0] = DrvZ80Rom1[0]; + for (INT32 A = 1; A < 0xc000; A++) { + INT32 src; + + src = DrvZ80Rom1[A]; + DrvZ80Rom1Op[A] = (src & 0x11) | ((src & 0xe0) >> 4) | ((src & 0x0e) << 4); + } + } + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 3, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x18000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x18000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 15, 1); if (nRet != 0) return 1; + GfxDecode(0x300, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromRed, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromGreen, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromBlue, 18, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(CommandoRead1); + ZetSetWriteHandler(CommandoWrite1); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom1Op, DrvZ80Rom1 ); + ZetMapArea(0xd000, 0xd3ff, 0, DrvFgVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 1, DrvFgVideoRam ); + ZetMapArea(0xd000, 0xd3ff, 2, DrvFgVideoRam ); + ZetMapArea(0xd400, 0xd7ff, 0, DrvFgColourRam ); + ZetMapArea(0xd400, 0xd7ff, 1, DrvFgColourRam ); + ZetMapArea(0xd400, 0xd7ff, 2, DrvFgColourRam ); + ZetMapArea(0xd800, 0xdbff, 0, DrvBgVideoRam ); + ZetMapArea(0xd800, 0xdbff, 1, DrvBgVideoRam ); + ZetMapArea(0xd800, 0xdbff, 2, DrvBgVideoRam ); + ZetMapArea(0xdc00, 0xdfff, 0, DrvBgColourRam ); + ZetMapArea(0xdc00, 0xdfff, 1, DrvBgColourRam ); + ZetMapArea(0xdc00, 0xdfff, 2, DrvBgColourRam ); + ZetMapArea(0xe000, 0xfdff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xfdff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xfdff, 2, DrvZ80Ram1 ); + ZetMapArea(0xfe00, 0xff7f, 0, DrvSpriteRam ); + ZetMapArea(0xfe00, 0xff7f, 1, DrvSpriteRam ); + ZetMapArea(0xfe00, 0xff7f, 2, DrvSpriteRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(CommandoRead2); + ZetSetWriteHandler(CommandoWrite2); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom2 ); + ZetMapArea(0x4000, 0x47ff, 0, DrvZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 1, DrvZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 BootlegInit() +{ + bFirstOpCodeEncrypted = true; + + return DrvInit(); +} + +static INT32 DrvExit() +{ + ZetExit(); + BurnYM2203Exit(); + + GenericTilesExit(); + + BurnFree(Mem); + + DrvBgScrollX[0] = DrvBgScrollX[1] = 0; + DrvBgScrollY[0] = DrvBgScrollY[1] = 0; + DrvFlipScreen = 0; + DrvSoundLatch = 0; + + bFirstOpCodeEncrypted = false; + + return 0; +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < 256; i++) { + INT32 bit0, bit1, bit2, bit3, r, g, b; + + bit0 = (DrvPromRed[i] >> 0) & 0x01; + bit1 = (DrvPromRed[i] >> 1) & 0x01; + bit2 = (DrvPromRed[i] >> 2) & 0x01; + bit3 = (DrvPromRed[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromGreen[i] >> 0) & 0x01; + bit1 = (DrvPromGreen[i] >> 1) & 0x01; + bit2 = (DrvPromGreen[i] >> 2) & 0x01; + bit3 = (DrvPromGreen[i] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvPromBlue[i] >> 0) & 0x01; + bit1 = (DrvPromBlue[i] >> 1) & 0x01; + bit2 = (DrvPromBlue[i] >> 2) & 0x01; + bit3 = (DrvPromBlue[i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Colour, Attr, x, y, TileIndex, xScroll, yScroll, Flip, xFlip, yFlip; + + xScroll = DrvBgScrollX[0] | (DrvBgScrollX[1] << 8); + xScroll &= 0x3ff; + + yScroll = DrvBgScrollY[0] | (DrvBgScrollY[1] << 8); + yScroll &= 0x3ff; + + for (mx = 0; mx < 32; mx++) { + for (my = 0; my < 32; my++) { + TileIndex = (my * 32) + mx; + + Attr = DrvBgColourRam[TileIndex]; + Code = DrvBgVideoRam[TileIndex] + ((Attr & 0xc0) << 2); + Colour = Attr & 0x0f; + Code &= 0x3ff; + Flip = (Attr & 0x30) >> 4; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + y = 16 * mx; + x = 16 * my; + + y -= 16; + + x -= xScroll; + y -= yScroll; + if (x < -16) x += 512; + if (y < -16) y += 512; + + if (DrvFlipScreen) { + x = 240 - x; + y = 208 - y; + xFlip = !xFlip; + yFlip = !yFlip; + } + + if (x > 0 && x < 240 && y > 0 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } + } + } + } +} + +static void DrvRenderSprites() +{ + for (INT32 Offset = 0x180 - 4; Offset >= 0; Offset -= 4) { + INT32 Attr = DrvSpriteRamBuffer[Offset + 1]; + INT32 Bank = (Attr & 0xc0) >> 6; + INT32 Code = DrvSpriteRamBuffer[Offset + 0] + (Bank << 8); + INT32 Colour = (Attr & 0x30) >> 4; + INT32 xFlip = Attr & 0x04; + INT32 yFlip = Attr & 0x08; + INT32 x = DrvSpriteRamBuffer[Offset + 3] - ((Attr & 0x01) << 8); + INT32 y = DrvSpriteRamBuffer[Offset + 2]; + + y -= 16; + + if (DrvFlipScreen) { + x = 240 - x; + y = 208 - y; + xFlip = !xFlip; + yFlip = !yFlip; + } + + if (Bank < 3) { + if (x > 0 && x < 240 && y > 0 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 128, DrvSprites); + } + } + } + } + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Colour, Attr, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = DrvFgColourRam[TileIndex]; + Code = DrvFgVideoRam[TileIndex] + ((Attr & 0xc0) << 2); + Colour = Attr & 0x0f; + Code &= 0x3ff; + Flip = (Attr & 0x30) >> 4; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + y -= 16; + + if (DrvFlipScreen) { + x = 248 - x; + y = 216 - y; + xFlip = !xFlip; + yFlip = !yFlip; + } + + if (x > 0 && x < 248 && y > 0 && y < 216) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 192, DrvChars); + } + } + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSprites(); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 25; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 24) { + ZetSetVector(0xd7); + ZetRaiseIrq(0); + } + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 5 || i == 10 || i == 15 || i == 20) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1] - nCyclesDone[1]); + ZetClose(); + + if (pBurnDraw) DrvDraw(); + + memcpy(DrvSpriteRamBuffer, DrvSpriteRam, 0x180); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029693; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + BurnYM2203Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvBgScrollX); + SCAN_VAR(DrvBgScrollY); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + } + + return 0; +} + +struct BurnDriver BurnDrvCommando = { + "commando", NULL, NULL, NULL, "1985", + "Commando (World)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCommandu = { + "commandou", "commando", NULL, NULL, "1985", + "Commando (US)\0", NULL, "Capcom (Data East USA license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCommandj = { + "commandoj", "commando", NULL, NULL, "1985", + "Senjou no Ookami\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvCommandb = { + "commandob", "commando", NULL, NULL, "1985", + "Commando (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + BootlegInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSinvasn = { + "sinvasn", "commando", NULL, NULL, "1985", + "Space Invasion (Europe)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, SinvasnRomInfo, SinvasnRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvSinvasnb = { + "sinvasnb", "commando", NULL, NULL, "1985", + "Space Invasion (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, SinvasnbRomInfo, SinvasnbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + BootlegInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_ddragon.cpp b/src/burn/drivers/misc_pre90s/d_ddragon.cpp new file mode 100644 index 00000000..295e5a38 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_ddragon.cpp @@ -0,0 +1,2597 @@ +#include "tiles_generic.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "m6805_intf.h" +#include "m6809_intf.h" +#include "burn_ym2151.h" +#include "msm5205.h" +#include "msm6295.h" +#include "bitswap.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvHD6309Rom = NULL; +static UINT8 *DrvSubCPURom = NULL; +static UINT8 *DrvSoundCPURom = NULL; +static UINT8 *DrvMCURom = NULL; +static UINT8 *DrvMSM5205Rom = NULL; +static UINT8 *DrvHD6309Ram = NULL; +static UINT8 *DrvSubCPURam = NULL; +static UINT8 *DrvSoundCPURam = NULL; +static UINT8 *DrvMCURam = NULL; +static UINT8 *DrvMCUPorts = NULL; +static UINT8 *DrvFgVideoRam = NULL; +static UINT8 *DrvBgVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam1 = NULL; +static UINT8 *DrvPaletteRam2 = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvRomBank; +static UINT8 DrvVBlank; +static UINT8 DrvSubCPUBusy; +static UINT8 DrvSoundLatch; +static UINT8 DrvADPCMIdle[2]; +static UINT32 DrvADPCMPos[2]; +static UINT32 DrvADPCMEnd[2]; +static INT32 DrvADPCMData[2]; + +static UINT16 DrvScrollXHi; +static UINT16 DrvScrollYHi; +static UINT8 DrvScrollXLo; +static UINT8 DrvScrollYLo; + +static INT32 nCyclesDone[4], nCyclesTotal[4]; +static INT32 nCyclesSegment; + +#define DD_CPU_TYPE_NONE 0 +#define DD_CPU_TYPE_HD63701 1 +#define DD_CPU_TYPE_HD6309 2 +#define DD_CPU_TYPE_M6803 3 +#define DD_CPU_TYPE_Z80 4 +#define DD_CPU_TYPE_M6809 5 +static INT32 DrvSubCPUType; +static INT32 DrvSoundCPUType; + +#define DD_VID_TYPE_DD2 1 +static INT32 DrvVidHardwareType; + +#define DD_GAME_DARKTOWR 1 +static INT32 DrvGameType; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 1, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 0, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = 0xff; + DrvInput[2] = 0xe7; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] -= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + DrvInput[2] -= (DrvInputPort2[i] & 1) << i; + } +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "4 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x08, "3 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x10, "2 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x40, 0x40, "Upright" }, + {0x14, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x01, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x02, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x04, 0x00, "Off" }, + {0x15, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x30, 0x10, "20k" }, + {0x15, 0x01, 0x30, 0x00, "40k" }, + {0x15, 0x01, 0x30, 0x30, "30k and every 60k" }, + {0x15, 0x01, 0x30, 0x20, "40k and every 80k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0xc0, 0xc0, "2" }, + {0x15, 0x01, 0xc0, 0x80, "3" }, + {0x15, 0x01, 0xc0, 0x40, "4" }, + {0x15, 0x01, 0xc0, 0x00, "Infinite" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo Drv2DIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x14, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x14, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x14, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x14, 0x01, 0x07, 0x03, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x14, 0x01, 0x38, 0x00, "4 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x08, "3 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x10, "2 Coins 1 Play" }, + {0x14, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x14, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + {0x14, 0x01, 0x38, 0x18, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x40, 0x40, "Upright" }, + {0x14, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Hurricane Kick" }, + {0x15, 0x01, 0x08, 0x00, "Easy" }, + {0x15, 0x01, 0x08, 0x08, "Normal" }, + + {0 , 0xfe, 0 , 4 , "Timer" }, + {0x15, 0x01, 0x30, 0x00, "60" }, + {0x15, 0x01, 0x30, 0x10, "65" }, + {0x15, 0x01, 0x30, 0x30, "70" }, + {0x15, 0x01, 0x30, 0x20, "80" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0xc0, 0xc0, "1" }, + {0x15, 0x01, 0xc0, 0x80, "2" }, + {0x15, 0x01, 0xc0, 0x40, "3" }, + {0x15, 0x01, 0xc0, 0x00, "4" }, +}; + +STDDIPINFO(Drv2) + +static struct BurnDIPInfo DdungeonDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x9d, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x14, 0x01, 0x0f, 0x03, "4 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x02, "3 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x07, "4 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x01, "2 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x06, "3 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x0b, "4 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0f, "4 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x0a, "3 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x05, "2 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x14, 0x01, 0x0f, 0x0e, "3 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x09, "2 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0d, "2 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x04, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x0f, 0x08, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x14, 0x01, 0xf0, 0x30, "4 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x20, "3 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x70, "4 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0x10, "2 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x60, "3 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0xb0, "4 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0xf0, "4 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0xa0, "3 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0x50, "2 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x14, 0x01, 0xf0, 0xe0, "3 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0x90, "2 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0xd0, "2 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0x40, "1 Coin 2 Plays" }, + {0x14, 0x01, 0xf0, 0x80, "1 Coin 3 Plays" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x03, 0x00, "1" }, + {0x15, 0x01, 0x03, 0x01, "2" }, + {0x15, 0x01, 0x03, 0x02, "3" }, + {0x15, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xf0, 0xf0, "Easy" }, + {0x15, 0x01, 0xf0, 0x90, "Medium" }, + {0x15, 0x01, 0xf0, 0x70, "Hard" }, + {0x15, 0x01, 0xf0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ddungeon) + +static struct BurnDIPInfo DarktowrDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x14, 0x01, 0x0f, 0x03, "4 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x02, "3 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x07, "4 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x01, "2 Coins 1 Play" }, + {0x14, 0x01, 0x0f, 0x06, "3 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x0b, "4 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0f, "4 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x0a, "3 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x05, "2 Coins 2 Plays" }, + {0x14, 0x01, 0x0f, 0x00, "1 Coin 1 Play" }, + {0x14, 0x01, 0x0f, 0x0e, "3 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x09, "2 Coins 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0d, "2 Coins 4 Plays" }, + {0x14, 0x01, 0x0f, 0x04, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x0f, 0x08, "1 Coin 3 Plays" }, + {0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x14, 0x01, 0xf0, 0x30, "4 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x20, "3 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x70, "4 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0x10, "2 Coins 1 Play" }, + {0x14, 0x01, 0xf0, 0x60, "3 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0xb0, "4 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0xf0, "4 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0xa0, "3 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0x50, "2 Coins 2 Plays" }, + {0x14, 0x01, 0xf0, 0x00, "1 Coin 1 Play" }, + {0x14, 0x01, 0xf0, 0xe0, "3 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0x90, "2 Coins 3 Plays" }, + {0x14, 0x01, 0xf0, 0xd0, "2 Coins 4 Plays" }, + {0x14, 0x01, 0xf0, 0x40, "1 Coin 2 Plays" }, + {0x14, 0x01, 0xf0, 0x80, "1 Coin 3 Plays" }, + {0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, +}; + +STDDIPINFO(Darktowr) + +static struct BurnRomInfo DrvRomDesc[] = { + { "21j-1-5.26", 0x08000, 0x42045dfd, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21j-2-3.25", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "21j-3.24", 0x08000, 0x3bdea613, BRF_ESS | BRF_PRG }, // 2 + { "21j-4-1.23", 0x08000, 0x728f87b9, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvwRomDesc[] = { + { "21j-1.26", 0x08000, 0xae714964, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21j-2-3.25", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "21a-3.24", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "21j-4.23", 0x08000, 0x6c9f46fa, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvw) +STD_ROM_FN(Drvw) + +static struct BurnRomInfo Drvw1RomDesc[] = { + { "e1-1.26", 0x08000, 0x4b951643, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21a-2-4.25", 0x08000, 0x5cd67657, BRF_ESS | BRF_PRG }, // 1 + { "21a-3.24", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "e4-1.23", 0x08000, 0xb1e26935, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvw1) +STD_ROM_FN(Drvw1) + +static struct BurnRomInfo DrvuRomDesc[] = { + { "21a-1-5.26", 0x08000, 0xe24a6e11, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21j-2-3.25", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "21a-3.24", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "21a-4.23", 0x08000, 0x6ea16072, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvu) +STD_ROM_FN(Drvu) + +static struct BurnRomInfo DrvuaRomDesc[] = { + { "21a-1", 0x08000, 0x1d625008, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21a-2_4", 0x08000, 0x5cd67657, BRF_ESS | BRF_PRG }, // 1 + { "21a-3", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "21a-4_2", 0x08000, 0x9b019598, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvua) +STD_ROM_FN(Drvua) + +static struct BurnRomInfo DrvubRomDesc[] = { + { "21a-1_6.bin", 0x08000, 0xf354b0e1, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21a-2_4", 0x08000, 0x5cd67657, BRF_ESS | BRF_PRG }, // 1 + { "21a-3", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "21a-4_2", 0x08000, 0x9b019598, BRF_ESS | BRF_PRG }, // 3 + + { "21jm-0.ic55", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvub) +STD_ROM_FN(Drvub) + +static struct BurnRomInfo Drvb2RomDesc[] = { + { "4.bin", 0x08000, 0x668dfa19, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "5.bin", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "6.bin", 0x08000, 0x3bdea613, BRF_ESS | BRF_PRG }, // 2 + { "7.bin", 0x08000, 0x728f87b9, BRF_ESS | BRF_PRG }, // 3 + + { "63701.bin", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 4 HD63701 Program Code + + { "b2_3.bin", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "8.bin", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "11.bin", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "12.bin", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "13.bin", 0x10000, 0xc8b91e17, BRF_GRA }, // 9 + { "14.bin", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "15.bin", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "16.bin", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "17.bin", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "18.bin", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "9.bin", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "10.bin", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "19.bin", 0x10000, 0x22d65df2, BRF_GRA }, // 17 + { "20.bin", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "b2_1.bin", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "2.bin", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvb2) +STD_ROM_FN(Drvb2) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "21j-1.26", 0x08000, 0xae714964, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21j-2-3.25", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "21a-3.24", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + { "21j-4.23", 0x08000, 0x6c9f46fa, BRF_ESS | BRF_PRG }, // 3 + + { "ic38", 0x04000, 0x6a6a0325, BRF_ESS | BRF_PRG }, // 4 HD6309 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 5 M6809 Program Code + + { "21j-5", 0x08000, 0x7a8b8db4, BRF_GRA }, // 6 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 7 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 8 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 11 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 12 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static struct BurnRomInfo DrvbaRomDesc[] = { + { "5.bin", 0x08000, 0xae714964, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "4.bin", 0x10000, 0x48045762, BRF_ESS | BRF_PRG }, // 1 + { "3.bin", 0x08000, 0xdbf24897, BRF_ESS | BRF_PRG }, // 2 + + { "2_32.bin", 0x04000, 0x67875473, BRF_ESS | BRF_PRG }, // 3 M6803 Program Code + + { "6.bin", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 4 M6809 Program Code + + { "1.bin", 0x08000, 0x7a8b8db4, BRF_GRA }, // 5 Characters + + { "21j-a", 0x10000, 0x574face3, BRF_GRA }, // 6 Sprites + { "21j-b", 0x10000, 0x40507a76, BRF_GRA }, // 7 + { "21j-c", 0x10000, 0xbb0bc76f, BRF_GRA }, // 8 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 9 + { "21j-e", 0x10000, 0xa0a0c261, BRF_GRA }, // 10 + { "21j-f", 0x10000, 0x6ba152f6, BRF_GRA }, // 11 + { "21j-g", 0x10000, 0x3220a0b6, BRF_GRA }, // 12 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 13 + + { "21j-8", 0x10000, 0x7c435887, BRF_GRA }, // 14 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 15 + { "21j-i", 0x10000, 0x5effb0a0, BRF_GRA }, // 16 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 17 + + { "8.bin", 0x10000, 0x34755de3, BRF_GRA }, // 18 Samples + { "7.bin", 0x10000, 0xf9311f72, BRF_GRA }, // 19 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 20 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Drvba) +STD_ROM_FN(Drvba) + +static struct BurnRomInfo Drv2RomDesc[] = { + { "26a9-04.bin", 0x08000, 0xf2cfc649, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "26aa-03.bin", 0x08000, 0x44dd5d4b, BRF_ESS | BRF_PRG }, // 1 + { "26ab-0.bin", 0x08000, 0x49ddddcd, BRF_ESS | BRF_PRG }, // 2 + { "26ac-0e.63", 0x08000, 0x57acad2c, BRF_ESS | BRF_PRG }, // 3 + + { "26ae-0.bin", 0x10000, 0xea437867, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + + { "26ad-0.bin", 0x08000, 0x75e36cd6, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program Code + + { "26a8-0e.19", 0x10000, 0x4e80cd36, BRF_GRA }, // 6 Characters + + { "26j0-0.bin", 0x20000, 0xdb309c84, BRF_GRA }, // 7 Sprites + { "26j1-0.bin", 0x20000, 0xc3081e0c, BRF_GRA }, // 8 + { "26af-0.bin", 0x20000, 0x3a615aad, BRF_GRA }, // 9 + { "26j2-0.bin", 0x20000, 0x589564ae, BRF_GRA }, // 10 + { "26j3-0.bin", 0x20000, 0xdaf040d6, BRF_GRA }, // 11 + { "26a10-0.bin", 0x20000, 0x6d16d889, BRF_GRA }, // 12 + + { "26j4-0.bin", 0x20000, 0xa8c93e76, BRF_GRA }, // 13 Tiles + { "26j5-0.bin", 0x20000, 0xee555237, BRF_GRA }, // 14 + + { "26j6-0.bin", 0x20000, 0xa84b2a29, BRF_GRA }, // 15 Samples + { "26j7-0.bin", 0x20000, 0xbc6a48d5, BRF_GRA }, // 16 + + { "prom.16", 0x00200, 0x46339529, BRF_GRA }, // 17 PROMs +}; + +STD_ROM_PICK(Drv2) +STD_ROM_FN(Drv2) + +static struct BurnRomInfo Drv2uRomDesc[] = { + { "26a9-04.bin", 0x08000, 0xf2cfc649, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "26aa-03.bin", 0x08000, 0x44dd5d4b, BRF_ESS | BRF_PRG }, // 1 + { "26ab-0.bin", 0x08000, 0x49ddddcd, BRF_ESS | BRF_PRG }, // 2 + { "26ac-02.bin", 0x08000, 0x097eaf26, BRF_ESS | BRF_PRG }, // 3 + + { "26ae-0.bin", 0x10000, 0xea437867, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + + { "26ad-0.bin", 0x08000, 0x75e36cd6, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program Code + + { "26a8-0.bin", 0x10000, 0x3ad1049c, BRF_GRA }, // 6 Characters + + { "26j0-0.bin", 0x20000, 0xdb309c84, BRF_GRA }, // 7 Sprites + { "26j1-0.bin", 0x20000, 0xc3081e0c, BRF_GRA }, // 8 + { "26af-0.bin", 0x20000, 0x3a615aad, BRF_GRA }, // 9 + { "26j2-0.bin", 0x20000, 0x589564ae, BRF_GRA }, // 10 + { "26j3-0.bin", 0x20000, 0xdaf040d6, BRF_GRA }, // 11 + { "26a10-0.bin", 0x20000, 0x6d16d889, BRF_GRA }, // 12 + + { "26j4-0.bin", 0x20000, 0xa8c93e76, BRF_GRA }, // 13 Tiles + { "26j5-0.bin", 0x20000, 0xee555237, BRF_GRA }, // 14 + + { "26j6-0.bin", 0x20000, 0xa84b2a29, BRF_GRA }, // 15 Samples + { "26j7-0.bin", 0x20000, 0xbc6a48d5, BRF_GRA }, // 16 + + { "prom.16", 0x00200, 0x46339529, BRF_GRA }, // 17 PROMs +}; + +STD_ROM_PICK(Drv2u) +STD_ROM_FN(Drv2u) + +static struct BurnRomInfo DdungeonRomDesc[] = { + { "dd26.26", 0x08000, 0xa6e7f608, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "dd25.25", 0x08000, 0x922e719c, BRF_ESS | BRF_PRG }, // 1 + + { "63701.bin", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 2 HD63701 Program Code + + { "dd30.30", 0x08000, 0xef1af99a, BRF_ESS | BRF_PRG }, // 3 M6809 Program Code + + { "dd_mcu.bin", 0x00800, 0x34cbb2d3, BRF_ESS | BRF_PRG }, // 4 M68705 MCU Program Code + + { "dd20.20", 0x08000, 0xd976b78d, BRF_GRA }, // 5 Characters + + { "dd117.117", 0x08000, 0xe912ca81, BRF_GRA }, // 6 Sprites + { "dd113.113", 0x08000, 0x43264ad8, BRF_GRA }, // 7 + + { "dd78.78", 0x08000, 0x3deacae9, BRF_GRA }, // 8 Tiles + { "dd109.109", 0x08000, 0x5a2f31eb, BRF_GRA }, // 9 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 10 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 11 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 12 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Ddungeon) +STD_ROM_FN(Ddungeon) + +static struct BurnRomInfo DarktowrRomDesc[] = { + { "dt.26", 0x08000, 0x8134a472, BRF_ESS | BRF_PRG }, // 0 HD6309 Program Code + { "21j-2-3.25", 0x08000, 0x5779705e, BRF_ESS | BRF_PRG }, // 1 + { "dt.24", 0x08000, 0x523a5413, BRF_ESS | BRF_PRG }, // 2 + + { "63701.bin", 0x04000, 0xf5232d03, BRF_ESS | BRF_PRG }, // 3 HD63701 Program Code + + { "21j-0-1", 0x08000, 0x9efa95bb, BRF_ESS | BRF_PRG }, // 4 M6809 Program Code + + { "68705prt.mcu", 0x00800, 0x34cbb2d3, BRF_ESS | BRF_PRG }, // 5 M68705 MCU Program Code + + { "dt.20", 0x08000, 0x860b0298, BRF_GRA }, // 6 Characters + + { "dt.117", 0x10000, 0x750dd0fa, BRF_GRA }, // 7 Sprites + { "dt.116", 0x10000, 0x22cfa87b, BRF_GRA }, // 8 + { "dt.115", 0x10000, 0x8a9f1c34, BRF_GRA }, // 9 + { "21j-d", 0x10000, 0xcb4f231b, BRF_GRA }, // 10 + { "dt.113", 0x10000, 0x7b4bbf9c, BRF_GRA }, // 11 + { "dt.112", 0x10000, 0xdf3709d4, BRF_GRA }, // 12 + { "dt.111", 0x10000, 0x59032154, BRF_GRA }, // 13 + { "21j-h", 0x10000, 0x65c7517d, BRF_GRA }, // 14 + + { "dt.78", 0x10000, 0x72c15604, BRF_GRA }, // 15 Tiles + { "21j-9", 0x10000, 0xc6640aed, BRF_GRA }, // 16 + { "dt.109", 0x10000, 0x15bdcb62, BRF_GRA }, // 17 + { "21j-j", 0x10000, 0x5fb42e7c, BRF_GRA }, // 18 + + { "21j-6", 0x10000, 0x34755de3, BRF_GRA }, // 19 Samples + { "21j-7", 0x10000, 0x904de6f8, BRF_GRA }, // 20 + + { "21j-k-0", 0x00100, 0xfdb130a9, BRF_GRA }, // 21 PROMs + { "21j-l-0", 0x00200, 0x46339529, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Darktowr) +STD_ROM_FN(Darktowr) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvHD6309Rom = Next; Next += 0x30000; + DrvSubCPURom = Next; Next += 0x04000; + DrvSoundCPURom = Next; Next += 0x08000; + DrvMSM5205Rom = Next; Next += 0x20000; + + RamStart = Next; + + DrvHD6309Ram = Next; Next += 0x01000; + DrvSubCPURam = Next; Next += 0x00fd0; + DrvSoundCPURam = Next; Next += 0x01000; + DrvFgVideoRam = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x01000; + DrvBgVideoRam = Next; Next += 0x00800; + DrvPaletteRam1 = Next; Next += 0x00200; + DrvPaletteRam2 = Next; Next += 0x00200; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0400 * 8 * 8; + DrvTiles = Next; Next += 0x0800 * 16 * 16; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00180 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 Drv2MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvHD6309Rom = Next; Next += 0x30000; + DrvSubCPURom = Next; Next += 0x10000; + DrvSoundCPURom = Next; Next += 0x08000; + MSM6295ROM = Next; Next += 0x40000; + + RamStart = Next; + + DrvHD6309Ram = Next; Next += 0x01800; + DrvSoundCPURam = Next; Next += 0x00800; + DrvFgVideoRam = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x01000; + DrvBgVideoRam = Next; Next += 0x00800; + DrvPaletteRam1 = Next; Next += 0x00200; + DrvPaletteRam2 = Next; Next += 0x00200; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0800 * 8 * 8; + DrvTiles = Next; Next += 0x0800 * 16 * 16; + DrvSprites = Next; Next += 0x1800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00180 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DarktowrMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvHD6309Rom = Next; Next += 0x30000; + DrvSubCPURom = Next; Next += 0x04000; + DrvSoundCPURom = Next; Next += 0x08000; + DrvMCURom = Next; Next += 0x00800; + DrvMSM5205Rom = Next; Next += 0x20000; + + RamStart = Next; + + DrvHD6309Ram = Next; Next += 0x01000; + DrvSubCPURam = Next; Next += 0x00fd0; + DrvSoundCPURam = Next; Next += 0x01000; + DrvMCURam = Next; Next += 0x00078; + DrvMCUPorts = Next; Next += 0x00008; + DrvFgVideoRam = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x01000; + DrvBgVideoRam = Next; Next += 0x00800; + DrvPaletteRam1 = Next; Next += 0x00200; + DrvPaletteRam2 = Next; Next += 0x00200; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0400 * 8 * 8; + DrvTiles = Next; Next += 0x0800 * 16 * 16; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00180 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + HD6309Open(0); + HD6309Reset(); + HD6309Close(); + + if (DrvSubCPUType == DD_CPU_TYPE_HD63701) { + HD63701Reset(); + } + + if (DrvSubCPUType == DD_CPU_TYPE_HD6309) { + HD6309Open(1); + HD6309Reset(); + HD6309Close(); + } + + if (DrvSubCPUType == DD_CPU_TYPE_M6803) { + M6803Reset(); + } + + if (DrvSubCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + M6809Open(0); + M6809Reset(); + M6809Close(); + + MSM5205Reset(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(1); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + } + + if (DrvGameType == DD_GAME_DARKTOWR) { + m68705Reset(); + } + + BurnYM2151Reset(); + + DrvRomBank = 0; + DrvVBlank = 0; + DrvSubCPUBusy = 1; + DrvSoundLatch = 0; + DrvScrollXHi = 0; + DrvScrollYHi = 0; + DrvScrollXLo = 0; + DrvScrollYLo = 0; + + DrvADPCMIdle[0] = 1; + DrvADPCMIdle[1] = 1; + DrvADPCMPos[0] = 0; + DrvADPCMPos[1] = 0; + DrvADPCMEnd[0] = 0; + DrvADPCMEnd[1] = 0; + DrvADPCMData[0] = -1; + DrvADPCMData[1] = -1; + + return 0; +} + +UINT8 DrvDdragonHD6309ReadByte(UINT16 Address) +{ + if (Address >= 0x2000 && Address <= 0x2fff) { + if (Address == 0x2049 && HD6309GetPC() == 0x6261 && DrvSpriteRam[0x0049] == 0x1f) return 0x01; + return DrvSpriteRam[Address - 0x2000]; + } + + if (DrvGameType == DD_GAME_DARKTOWR && Address >= 0x4000 && Address <= 0x7fff) { + UINT32 Offset = Address - 0x4000; + + if (Offset == 0x1401 || Offset == 0x0001) return DrvMCUPorts[0]; + return 0xff; + } + + switch (Address) { + case 0x3800: { + return DrvInput[0]; + } + + case 0x3801: { + return DrvInput[1]; + } + + case 0x3802: { + return DrvInput[2] | ((DrvVBlank) ? 0x08 : 0) | (DrvSubCPUBusy ? 0x10 : 0); + } + + case 0x3803: { + return DrvDip[0]; + } + + case 0x3804: { + return DrvDip[1]; + } + + case 0x380b: { + // ??? + return 0; + } + } + + bprintf(PRINT_NORMAL, _T("HD6309 Read Byte -> %04X\n"), Address); + + return 0; +} + +void DrvDdragonHD6309WriteByte(UINT16 Address, UINT8 Data) +{ + if (DrvGameType == DD_GAME_DARKTOWR && Address >= 0x4000 && Address <= 0x7fff) { + UINT32 Offset = Address - 0x4000; + + if (Offset == 0x1400 || Offset == 0x0000) { + DrvMCUPorts[1] = BITSWAP08(Data, 0, 1, 2, 3, 4, 5, 6, 7); + } + return; + } + + switch (Address) { + case 0x3808: { + UINT8 DrvOldRomBank = DrvRomBank; + DrvRomBank = (Data & 0xe0) >> 5; + HD6309MapMemory(DrvHD6309Rom + 0x8000 + (DrvRomBank * 0x4000), 0x4000, 0x7fff, M6809_ROM); + + DrvScrollXHi = (Data & 0x01) << 8; + DrvScrollYHi = (Data & 0x02) << 7; + + if (Data & 0x10) { + DrvSubCPUBusy = 0; + } else { + if (DrvSubCPUBusy == 0) { + if (DrvSubCPUType == DD_CPU_TYPE_HD63701) { + HD63701SetIRQ(HD63701_INPUT_LINE_NMI, HD63701_IRQSTATUS_ACK); + } + + if (DrvSubCPUType == DD_CPU_TYPE_HD6309) { + HD6309Close(); + HD6309Open(1); + HD6309SetIRQ(HD6309_INPUT_LINE_NMI, HD6309_IRQSTATUS_ACK); + HD6309Close(); + HD6309Open(0); + } + + if (DrvSubCPUType == DD_CPU_TYPE_M6803) { + M6803SetIRQ(M6803_INPUT_LINE_NMI, M6803_IRQSTATUS_ACK); + } + + if (DrvSubCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(0); + ZetNmi(); + ZetClose(); + } + } + } + + if (DrvGameType == DD_GAME_DARKTOWR) { + if (DrvRomBank == 4 && DrvOldRomBank != 4) { + HD6309MemCallback(0x4000, 0x7fff, HD6309_RAM); + } else { + if (DrvRomBank != 4 && DrvOldRomBank == 4) { + HD6309MapMemory(DrvHD6309Rom + 0x8000 + (DrvRomBank * 0x4000), 0x4000, 0x7fff, M6809_ROM); + } + } + } + + return; + } + + case 0x3809: { + DrvScrollXLo = Data; + return; + } + + case 0x380a: { + DrvScrollYLo = Data; + return; + } + + case 0x380b: { + HD6309SetIRQ(HD6309_INPUT_LINE_NMI, HD6309_IRQSTATUS_NONE); + return; + } + + case 0x380c: { + HD6309SetIRQ(HD6309_FIRQ_LINE, HD6309_IRQSTATUS_NONE); + return; + } + + case 0x380d: { + HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_NONE); + return; + } + + case 0x380e: { + DrvSoundLatch = Data; + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + M6809Open(0); + M6809SetIRQ(M6809_IRQ_LINE, M6809_IRQSTATUS_ACK); + M6809Close(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(1); + ZetNmi(); + ZetClose(); + } + return; + } + + case 0x380f: { + // ??? + return; + } + } + + bprintf(PRINT_NORMAL, _T("HD6309 Write Byte -> %04X, %02X\n"), Address, Data); +} + +UINT8 DrvDdragonHD63701ReadByte(UINT16 Address) +{ + if (Address >= 0x0020 && Address <= 0x0fff) { + return DrvSubCPURam[Address - 0x0020]; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + if (Address == 0x8049 && HD63701GetPC() == 0x6261 && DrvSpriteRam[0x0049] == 0x1f) return 0x01; + return DrvSpriteRam[Address - 0x8000]; + } + + bprintf(PRINT_NORMAL, _T("M6800 Read Byte -> %04X\n"), Address); + + return 0; +} + +void DrvDdragonHD63701WriteByte(UINT16 Address, UINT8 Data) +{ + if (Address <= 0x001f) { + if (Address == 0x17) { + if (Data & 3) { + HD6309Open(0); + HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_ACK); + HD6309Close(); + + HD63701SetIRQ(HD63701_INPUT_LINE_NMI, HD63701_IRQSTATUS_NONE); + } + } + return; + } + + if (Address >= 0x0020 && Address <= 0x0fff) { + DrvSubCPURam[Address - 0x0020] = Data; + return; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + if (Address == 0x8000) DrvSubCPUBusy = 1; + DrvSpriteRam[Address - 0x8000] = Data; + return; + } + + bprintf(PRINT_NORMAL, _T("M6800 Write Byte -> %04X, %02X\n"), Address, Data); +} + +UINT8 DrvDdragonbSubHD6309ReadByte(UINT16 Address) +{ + if (Address >= 0x0020 && Address <= 0x0fff) { + return DrvSubCPURam[Address - 0x0020]; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + return DrvSpriteRam[Address - 0x8000]; + } + + bprintf(PRINT_NORMAL, _T("Sub HD6309 Read Byte -> %04X\n"), Address); + + return 0; +} + +void DrvDdragonbSubHD6309WriteByte(UINT16 Address, UINT8 Data) +{ + if (Address <= 0x001f) { + if (Address == 0x17) { + if (Data & 3) { + HD6309Close(); + + HD6309Open(0); + HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_ACK); + HD6309Close(); + + HD6309Open(1); + HD6309SetIRQ(HD6309_INPUT_LINE_NMI, HD6309_IRQSTATUS_NONE); + } + } + return; + } + + if (Address >= 0x0020 && Address <= 0x0fff) { + DrvSubCPURam[Address - 0x0020] = Data; + return; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + if (Address == 0x8000) DrvSubCPUBusy = 1; + DrvSpriteRam[Address - 0x8000] = Data; + return; + } + + bprintf(PRINT_NORMAL, _T("Sub HD6309 Write Byte -> %04X, %02X\n"), Address, Data); +} + +UINT8 DrvDdragonbaM6803ReadByte(UINT16 Address) +{ + if (Address >= 0x0020 && Address <= 0x0fff) { + return DrvSubCPURam[Address - 0x0020]; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + return DrvSpriteRam[Address - 0x8000]; + } + + bprintf(PRINT_NORMAL, _T("M6803 Read Byte -> %04X\n"), Address); + + return 0; +} + +void DrvDdragonbaM6803WriteByte(UINT16 Address, UINT8 Data) +{ + if (Address >= 0x0020 && Address <= 0x0fff) { + DrvSubCPURam[Address - 0x0020] = Data; + return; + } + + if (Address >= 0x8000 && Address <= 0x8fff) { + if (Address == 0x8000) DrvSubCPUBusy = 1; + DrvSpriteRam[Address - 0x8000] = Data; + return; + } + + if (Address <= 0x001f) { + m6803_internal_registers_w(Address, Data); + return; + } + + bprintf(PRINT_NORMAL, _T("M6803 Write Byte -> %04X, %02X\n"), Address, Data); +} + +void DrvDdragonbaM6803WritePort(UINT16, UINT8) +{ + M6803SetIRQ(M6803_INPUT_LINE_NMI, M6803_IRQSTATUS_NONE); + + HD6309Open(0); + HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_ACK); + HD6309Close(); +} + +void __fastcall Ddragon2SubZ80Write(UINT16 Address, UINT8 Data) +{ + if (Address >= 0xc000 && Address <= 0xc3ff) { + if (Address == 0xc000) DrvSubCPUBusy = 1; + DrvSpriteRam[Address - 0xc000] = Data; + return; + } + + switch (Address) { + case 0xd000: { + // Lower NMI + return; + } + + case 0xe000: { + HD6309Open(0); + HD6309SetIRQ(HD6309_IRQ_LINE, HD6309_IRQSTATUS_ACK); + HD6309Close(); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Sub Z80 Write => %04X, %02X\n"), Address, Data); + } + } +} + +UINT8 DrvDdragonM6809ReadByte(UINT16 Address) +{ + switch (Address) { + case 0x1000: { + M6809SetIRQ(M6809_IRQ_LINE, M6809_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + case 0x1800: { + return DrvADPCMIdle[0] + (DrvADPCMIdle[1] << 1); + } + + case 0x2801: { + return BurnYM2151ReadStatus(); + } + } + + bprintf(PRINT_NORMAL, _T("M6809 Read Byte -> %04X\n"), Address); + + return 0; +} + + +void DrvDdragonM6809WriteByte(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x2800: { + BurnYM2151SelectRegister(Data); + return; + } + + case 0x2801: { + BurnYM2151WriteRegister(Data); + return; + } + + case 0x3800: { + DrvADPCMIdle[0] = 0; + MSM5205ResetWrite(0, 0); + return; + } + + case 0x3801: { + DrvADPCMIdle[1] = 0; + MSM5205ResetWrite(1, 0); + return; + } + + case 0x3802: { + DrvADPCMEnd[0] = (Data & 0x7f) * 0x200; + return; + } + + case 0x3803: { + DrvADPCMEnd[1] = (Data & 0x7f) * 0x200; + return; + } + + case 0x3804: { + DrvADPCMPos[0] = (Data & 0x7f) * 0x200; + return; + } + + case 0x3805: { + DrvADPCMPos[1] = (Data & 0x7f) * 0x200; + return; + } + + case 0x3806: { + DrvADPCMIdle[0] = 1; + MSM5205ResetWrite(0, 1); + return; + } + + case 0x3807: { + DrvADPCMIdle[1] = 1; + MSM5205ResetWrite(1, 1); + return; + } + } + + bprintf(PRINT_NORMAL, _T("M6809 Write Byte -> %04X, %02X\n"), Address, Data); +} + +UINT8 __fastcall Ddragon2SoundZ80Read(UINT16 Address) +{ + switch (Address) { + case 0x8801: { + return BurnYM2151ReadStatus(); + } + + case 0x9800: { + return MSM6295ReadStatus(0); + } + + case 0xa000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Sound Z80 Read => %04X\n"), Address); + } + } + + return 0; +} + +void __fastcall Ddragon2SoundZ80Write(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x8800: { + BurnYM2151SelectRegister(Data); + return; + } + + case 0x8801: { + BurnYM2151WriteRegister(Data); + return; + } + + case 0x9800: { + MSM6295Command(0, Data); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Sound Z80 Write => %04X, %02X\n"), Address, Data); + } + } +} + +UINT8 DrvMCUReadByte(UINT16 Address) +{ + if (Address <= 0x0007) { + return DrvMCUPorts[Address]; + } + + bprintf(PRINT_NORMAL, _T("M68705 Read Byte -> %04X\n"), Address); + + return 0; +} + +void DrvMCUWriteByte(UINT16 Address, UINT8 Data) +{ + if (Address <= 0x0007) { + DrvMCUPorts[Address] = Data; + return; + } + + bprintf(PRINT_NORMAL, _T("M68705 Write Byte -> %04X, %02X\n"), Address, Data); +} + +static INT32 CharPlaneOffsets[4] = { 0, 2, 4, 6 }; +static INT32 CharXOffsets[8] = { 1, 0, 65, 64, 129, 128, 193, 192 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 TilePlaneOffsets[4] = { 0x100000, 0x100004, 0, 4 }; +static INT32 DdungeonTilePlaneOffsets[4] = { 0x080000, 0x080004, 0, 4 }; +static INT32 TileXOffsets[16] = { 3, 2, 1, 0, 131, 130, 129, 128, 259, 258, 257, 256, 387, 386, 385, 384 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 SpritePlaneOffsets[4] = { 0x200000, 0x200004, 0, 4 }; +static INT32 Dd2SpritePlaneOffsets[4] = { 0x300000, 0x300004, 0, 4 }; + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_ACK); +#if 1 + // This fixes music tempo but breaks MSM5205 sound if we use the M6809 for the MSM5205 timing, + // because the interleave run count is 190 cycles + nCyclesDone[2] += M6809Run(1000); +#endif + } else { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_NONE); + } +} + +static void Ddragon2YM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(HD6309TotalCycles() * nSoundRate / ((INT32)(nCyclesTotal[0] * 57.444853))); +} + +static void DrvMSM5205Vck0() +{ + if (DrvADPCMPos[0] >= DrvADPCMEnd[0] || DrvADPCMPos[0] >= 0x10000) { + DrvADPCMIdle[0] = 1; + MSM5205ResetWrite(0, 1); + } else { + if (DrvADPCMData[0] != -1) { + MSM5205DataWrite(0, DrvADPCMData[0] & 0x0f); + DrvADPCMData[0] = -1; + } else { + UINT8 *ROM = DrvMSM5205Rom + 0x00000; + + DrvADPCMData[0] = ROM[(DrvADPCMPos[0]++) & 0xffff]; + MSM5205DataWrite(0, DrvADPCMData[0] >> 4); + } + } +} + +static void DrvMSM5205Vck1() +{ + if (DrvADPCMPos[1] >= DrvADPCMEnd[1] || DrvADPCMPos[1] >= 0x10000) { + DrvADPCMIdle[1] = 1; + MSM5205ResetWrite(1, 1); + } else { + if (DrvADPCMData[1] != -1) { + MSM5205DataWrite(1, DrvADPCMData[1] & 0x0f); + DrvADPCMData[1] = -1; + } else { + UINT8 *ROM = DrvMSM5205Rom + 0x10000; + + DrvADPCMData[1] = ROM[(DrvADPCMPos[1]++) & 0xffff]; + MSM5205DataWrite(1, DrvADPCMData[1] >> 4); + } + } +} + +static INT32 DrvMemInit() +{ + INT32 nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + return 0; +} + +static INT32 Drv2MemInit() +{ + INT32 nLen; + + // Allocate and Blank all required memory + Mem = NULL; + Drv2MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + Drv2MemIndex(); + + return 0; +} + +static INT32 DarktowrMemInit() +{ + INT32 nLen; + + // Allocate and Blank all required memory + Mem = NULL; + DarktowrMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + DarktowrMemIndex(); + + return 0; +} + +static INT32 DrvLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load HD6309 Program Roms + nRet = BurnLoadRom(DrvHD6309Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x18000, 3, 1); if (nRet != 0) return 1; + + // Load HD63701 Program Roms + nRet = BurnLoadRom(DrvSubCPURom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvSoundCPURom + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 14, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 18, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load samples + nRet = BurnLoadRom(DrvMSM5205Rom + 0x00000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM5205Rom + 0x10000, 20, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 DrvbaLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load HD6309 Program Roms + nRet = BurnLoadRom(DrvHD6309Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + memcpy(DrvHD6309Rom + 0x18000, DrvHD6309Rom + 0x10000, 0x8000); + nRet = BurnLoadRom(DrvHD6309Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + + // Load M6803 Program Roms + nRet = BurnLoadRom(DrvSubCPURom + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvSoundCPURom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 13, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 17, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load samples + nRet = BurnLoadRom(DrvMSM5205Rom + 0x00000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM5205Rom + 0x10000, 19, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 Drv2LoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0xc0000); + + // Load HD6309 Program Roms + nRet = BurnLoadRom(DrvHD6309Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x18000, 3, 1); if (nRet != 0) return 1; + + // Load HD63701 Program Roms + nRet = BurnLoadRom(DrvSubCPURom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvSoundCPURom + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0xc0000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x1800, 4, 16, 16, Dd2SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0xc0000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 14, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x20000, 16, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 DdungeonLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load HD6309 Program Roms + nRet = BurnLoadRom(DrvHD6309Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + + // Load HD63701 Program Roms + nRet = BurnLoadRom(DrvSubCPURom + 0x00000, 2, 1); if (nRet != 0) return 1; + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvSoundCPURom + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load M68705 MCU Program Roms + nRet = BurnLoadRom(DrvMCURom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, DdungeonTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load samples + nRet = BurnLoadRom(DrvMSM5205Rom + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM5205Rom + 0x10000, 11, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 DarktowrLoadRoms() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load HD6309 Program Roms + nRet = BurnLoadRom(DrvHD6309Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvHD6309Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + + // Load HD63701 Program Roms + nRet = BurnLoadRom(DrvSubCPURom + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvSoundCPURom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load M68705 MCU Program Roms + nRet = BurnLoadRom(DrvMCURom + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 14, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 18, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom, DrvTiles); + + // Load samples + nRet = BurnLoadRom(DrvMSM5205Rom + 0x00000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvMSM5205Rom + 0x10000, 20, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + return 0; +} + +static INT32 DrvMachineInit() +{ + BurnSetRefreshRate(57.444853); + + // Setup the HD6309 emulation + if (DrvSubCPUType == DD_CPU_TYPE_HD6309) { + HD6309Init(2); + } else { + HD6309Init(1); + } + HD6309Open(0); + HD6309MapMemory(DrvHD6309Ram , 0x0000, 0x0fff, M6809_RAM); + HD6309MapMemory(DrvPaletteRam1 , 0x1000, 0x11ff, M6809_RAM); + HD6309MapMemory(DrvPaletteRam2 , 0x1200, 0x13ff, M6809_RAM); + HD6309MapMemory(DrvFgVideoRam , 0x1800, 0x1fff, M6809_RAM); + HD6309MapMemory(DrvSpriteRam , 0x2000, 0x2fff, M6809_WRITE); + HD6309MapMemory(DrvBgVideoRam , 0x3000, 0x37ff, M6809_RAM); + HD6309MapMemory(DrvHD6309Rom + 0x8000, 0x4000, 0x7fff, M6809_ROM); + HD6309MapMemory(DrvHD6309Rom , 0x8000, 0xffff, M6809_ROM); + HD6309SetReadByteHandler(DrvDdragonHD6309ReadByte); + HD6309SetWriteByteHandler(DrvDdragonHD6309WriteByte); + HD6309Close(); + + if (DrvSubCPUType == DD_CPU_TYPE_HD63701) { + HD63701Init(1); + HD63701MapMemory(DrvSubCPURom , 0xc000, 0xffff, HD63701_ROM); + HD63701SetReadByteHandler(DrvDdragonHD63701ReadByte); + HD63701SetWriteByteHandler(DrvDdragonHD63701WriteByte); + } + + if (DrvSubCPUType == DD_CPU_TYPE_HD6309) { + HD6309Open(1); + HD6309MapMemory(DrvSubCPURom , 0xc000, 0xffff, HD6309_ROM); + HD6309SetReadByteHandler(DrvDdragonbSubHD6309ReadByte); + HD6309SetWriteByteHandler(DrvDdragonbSubHD6309WriteByte); + HD6309Close(); + } + + if (DrvSubCPUType == DD_CPU_TYPE_M6803) { + M6803Init(1); + M6803MapMemory(DrvSubCPURom , 0xc000, 0xffff, M6803_ROM); + M6803SetReadByteHandler(DrvDdragonbaM6803ReadByte); + M6803SetWriteByteHandler(DrvDdragonbaM6803WriteByte); + M6803SetWritePortHandler(DrvDdragonbaM6803WritePort); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvSoundCPURam , 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvSoundCPURom , 0x8000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(DrvDdragonM6809ReadByte); + M6809SetWriteByteHandler(DrvDdragonM6809WriteByte); + M6809Close(); + + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM5205Init(0, DrvSynchroniseStream, 375000, DrvMSM5205Vck0, MSM5205_S48_4B, 45, 1); + MSM5205Init(1, DrvSynchroniseStream, 375000, DrvMSM5205Vck1, MSM5205_S48_4B, 45, 1); + } + + if (DrvGameType == DD_GAME_DARKTOWR) { + m6805Init(1, 0x800); + m6805MapMemory(DrvMCURom + 0x80, 0x080, 0x7ff, M6805_ROM); + m6805MapMemory(DrvMCURom, 0x008, 0x07f, M6805_RAM); + m6805SetReadHandler(DrvMCUReadByte); + m6805SetWriteHandler(DrvMCUWriteByte); + } + + nCyclesTotal[0] = (INT32)((double)4000000 / 57.44853); + nCyclesTotal[1] = (INT32)((double)4000000 / 57.44853); + nCyclesTotal[2] = (INT32)((double)1500000 / 57.44853); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 Drv2MachineInit() +{ + // Setup the HD6309 emulation + HD6309Init(1); + HD6309Open(0); + HD6309MapMemory(DrvHD6309Ram , 0x0000, 0x17ff, M6809_RAM); + HD6309MapMemory(DrvFgVideoRam , 0x1800, 0x1fff, M6809_RAM); + HD6309MapMemory(DrvSpriteRam , 0x2000, 0x2fff, M6809_WRITE); + HD6309MapMemory(DrvBgVideoRam , 0x3000, 0x37ff, M6809_RAM); + HD6309MapMemory(DrvPaletteRam1 , 0x3c00, 0x3dff, M6809_RAM); + HD6309MapMemory(DrvPaletteRam2 , 0x3e00, 0x3fff, M6809_RAM); + HD6309MapMemory(DrvHD6309Rom + 0x8000, 0x4000, 0x7fff, M6809_ROM); + HD6309MapMemory(DrvHD6309Rom , 0x8000, 0xffff, M6809_ROM); + HD6309SetReadByteHandler(DrvDdragonHD6309ReadByte); + HD6309SetWriteByteHandler(DrvDdragonHD6309WriteByte); + HD6309Close(); + + ZetInit(2); + ZetOpen(0); + ZetSetWriteHandler(Ddragon2SubZ80Write); + ZetMapArea(0x0000, 0xbfff, 0, DrvSubCPURom); + ZetMapArea(0x0000, 0xbfff, 2, DrvSubCPURom); + ZetMapArea(0xc000, 0xc3ff, 0, DrvSpriteRam); + ZetMapArea(0xc000, 0xc3ff, 2, DrvSpriteRam); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(Ddragon2SoundZ80Read); + ZetSetWriteHandler(Ddragon2SoundZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvSoundCPURom); + ZetMapArea(0x0000, 0x7fff, 2, DrvSoundCPURom); + ZetMapArea(0x8000, 0x87ff, 0, DrvSoundCPURam); + ZetMapArea(0x8000, 0x87ff, 1, DrvSoundCPURam); + ZetMapArea(0x8000, 0x87ff, 2, DrvSoundCPURam); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 25.0); + BurnYM2151SetIrqHandler(&Ddragon2YM2151IrqHandler); + + MSM6295Init(0, 1056000 / 132, 50.0, 1); + + BurnSetRefreshRate(57.444853); + + nCyclesTotal[0] = (INT32)((double)4000000 / 57.44853); + nCyclesTotal[1] = (INT32)((double)4000000 / 57.44853); + nCyclesTotal[2] = (INT32)((double)3579545 / 57.44853); + nCyclesTotal[3] = (INT32)((double)4000000 / 57.44853); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvInit() +{ + DrvSubCPUType = DD_CPU_TYPE_HD63701; + DrvSoundCPUType = DD_CPU_TYPE_M6809; + + if (DrvMemInit()) return 1; + if (DrvLoadRoms()) return 1; + if (DrvMachineInit()) return 1; + + return 0; +} + +static INT32 DrvbInit() +{ + DrvSubCPUType = DD_CPU_TYPE_HD6309; + DrvSoundCPUType = DD_CPU_TYPE_M6809; + + if (DrvMemInit()) return 1; + if (DrvLoadRoms()) return 1; + if (DrvMachineInit()) return 1; + + nCyclesTotal[1] = (INT32)((double)1500000 / 57.44853); + + return 0; +} + +static INT32 DrvbaInit() +{ + DrvSubCPUType = DD_CPU_TYPE_M6803; + DrvSoundCPUType = DD_CPU_TYPE_M6809; + + if (DrvMemInit()) return 1; + if (DrvbaLoadRoms()) return 1; + if (DrvMachineInit()) return 1; + + return 0; +} + +static INT32 Drv2Init() +{ + DrvSubCPUType = DD_CPU_TYPE_Z80; + DrvSoundCPUType = DD_CPU_TYPE_Z80; + DrvVidHardwareType = DD_VID_TYPE_DD2; + + if (Drv2MemInit()) return 1; + if (Drv2LoadRoms()) return 1; + if (Drv2MachineInit()) return 1; + + return 0; +} + +static INT32 DdungeonInit() +{ + DrvSubCPUType = DD_CPU_TYPE_HD63701; + DrvSoundCPUType = DD_CPU_TYPE_M6809; + DrvGameType = DD_GAME_DARKTOWR; + + if (DarktowrMemInit()) return 1; + if (DdungeonLoadRoms()) return 1; + if (DrvMachineInit()) return 1; + + return 0; +} + +static INT32 DarktowrInit() +{ + DrvSubCPUType = DD_CPU_TYPE_HD63701; + DrvSoundCPUType = DD_CPU_TYPE_M6809; + DrvGameType = DD_GAME_DARKTOWR; + + if (DarktowrMemInit()) return 1; + if (DarktowrLoadRoms()) return 1; + if (DrvMachineInit()) return 1; + + return 0; +} + +static INT32 DrvExit() +{ + HD6309Exit(); + M6800Exit(); + m6805Exit(); + M6809Exit(); + ZetExit(); + + BurnYM2151Exit(); + MSM5205Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + + BurnFree(Mem); + + DrvRomBank = 0; + DrvVBlank = 0; + DrvSubCPUBusy = 0; + DrvSoundLatch = 0; + DrvScrollXHi = 0; + DrvScrollYHi = 0; + DrvScrollXLo = 0; + DrvScrollYLo = 0; + + DrvADPCMIdle[0] = 0; + DrvADPCMIdle[1] = 0; + DrvADPCMPos[0] = 0; + DrvADPCMPos[1] = 0; + DrvADPCMEnd[0] = 0; + DrvADPCMEnd[1] = 0; + DrvADPCMData[0] = 0; + DrvADPCMData[1] = 0; + + DrvSubCPUType = DD_CPU_TYPE_NONE; + DrvSoundCPUType = DD_CPU_TYPE_NONE; + DrvVidHardwareType = 0; + DrvGameType = 0; + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < 0x180; i++) { + INT32 Val = DrvPaletteRam1[i] + (DrvPaletteRam2[i] << 8); + + DrvPalette[i] = CalcCol(Val); + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex, xScroll, yScroll, Flip, xFlip, yFlip; + + xScroll = DrvScrollXHi + DrvScrollXLo; + xScroll &= 0x1ff; + + yScroll = DrvScrollYHi + DrvScrollYLo; + yScroll &= 0x1ff; + + for (mx = 0; mx < 32; mx++) { + for (my = 0; my < 32; my++) { + TileIndex = (my & 0x0f) + ((mx & 0x0f) << 4) + ((my & 0x10) << 4) + ((mx & 0x10) << 5); + + Attr = DrvBgVideoRam[(2 * TileIndex) + 0]; + Code = DrvBgVideoRam[(2 * TileIndex) + 1] + ((Attr & 0x07) << 8); + Colour = (Attr >> 3) & 0x07; + Flip = (Attr & 0xc0) >> 6; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + y = 16 * mx; + x = 16 * my; + + x -= xScroll; + if (x < -16) x += 512; + + y -= yScroll; + if (y < -16) y += 512; + + y -= 8; + + if (x > 16 && x < 240 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 256, DrvTiles); + } + } + } + } + } +} + +#define DRAW_SPRITE(Order, sx, sy) \ + if (sx > 16 && sx < 240 && sy > 16 && sy < 224) { \ + if (xFlip) { \ + if (yFlip) { \ + Render16x16Tile_Mask_FlipXY(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } else { \ + Render16x16Tile_Mask_FlipX(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } \ + } else { \ + if (yFlip) { \ + Render16x16Tile_Mask_FlipY(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } else { \ + Render16x16Tile_Mask(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } \ + } \ + } else { \ + if (xFlip) { \ + if (yFlip) { \ + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } else { \ + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } \ + } else { \ + if (yFlip) { \ + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } else { \ + Render16x16Tile_Mask_Clip(pTransDraw, Code + Order, sx, sy, Colour, 4, 0, 128, DrvSprites); \ + } \ + } \ + } + +static void DrvRenderSpriteLayer() +{ + UINT8 *Src = &DrvSpriteRam[0x800]; + + for (INT32 i = 0; i < (64 * 5); i += 5) { + INT32 Attr = Src[i + 1]; + + if (Attr & 0x80) { + INT32 sx = 240 - Src[i + 4] + ((Attr & 2) << 7); + INT32 sy = 232 - Src[i + 0] + ((Attr & 1) << 8); + INT32 Size = (Attr & 0x30) >> 4; + INT32 xFlip = Attr & 0x08; + INT32 yFlip = Attr & 0x04; + INT32 dx = -16; + INT32 dy = -16; + + INT32 Colour; + INT32 Code; + + if (DrvVidHardwareType == DD_VID_TYPE_DD2) { + Colour = (Src[i + 2] >> 5); + Code = Src[i + 3] + ((Src[i + 2] & 0x1f) << 8); + } else { + Colour = (Src[i + 2] >> 4) & 0x07; + Code = Src[i + 3] + ((Src[i + 2] & 0x0f) << 8); + } + + Code &= ~Size; + + switch (Size) { + case 0: { + DRAW_SPRITE(0, sx, sy) + break; + } + + case 1: { + DRAW_SPRITE(0, sx, sy + dy) + DRAW_SPRITE(1, sx, sy) + break; + } + + case 2: { + DRAW_SPRITE(0, sx + dx, sy) + DRAW_SPRITE(2, sx, sy) + break; + } + + case 3: { + DRAW_SPRITE(0, sx + dx, sy + dy) + DRAW_SPRITE(1, sx + dx, sy) + DRAW_SPRITE(2, sx, sy + dy) + DRAW_SPRITE(3, sx, sy) + break; + } + } + } + } +} + +#undef DRAW_SPRITE + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = DrvFgVideoRam[(2 * TileIndex) + 0]; + Code = DrvFgVideoRam[(2 * TileIndex) + 1] + ((Attr & 0x07) << 8); + if (DrvVidHardwareType != DD_VID_TYPE_DD2) Code &= 0x3ff; + + Colour = Attr >> 5; + + x = 8 * mx; + y = 8 * my; + + y -= 8; + + if (x > 0 && x < 248 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSpriteLayer(); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 272; + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) nInterleave = MSM5205CalcInterleave(0, (INT32)(nCyclesTotal[0] * 57.444853)); + INT32 nSoundBufferPos = 0; + + INT32 VBlankSlice = (INT32)((double)(nInterleave * 240) / 272); + INT32 FIRQFireSlice[16]; + for (INT32 i = 0; i < 16; i++) { + FIRQFireSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 17)); + } + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + UINT32 nCyclesToDo[2]; + nCyclesToDo[0] = (INT32)((double)nCyclesTotal[0] * nBurnCPUSpeedAdjust / 0x0100); + nCyclesToDo[1] = (INT32)((double)nCyclesTotal[1] * nBurnCPUSpeedAdjust / 0x0100); + + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = nCyclesDone[3] = 0; + + HD6309NewFrame(); + if (DrvSubCPUType == DD_CPU_TYPE_HD63701) HD63701NewFrame(); + if (DrvSubCPUType == DD_CPU_TYPE_M6803) M6803NewFrame(); + if (DrvSubCPUType == DD_CPU_TYPE_Z80 || DrvSoundCPUType == DD_CPU_TYPE_Z80) ZetNewFrame(); + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) M6809NewFrame(); + if (DrvGameType == DD_GAME_DARKTOWR) m6805NewFrame(); + + DrvVBlank = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + HD6309Open(0); + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += HD6309Run(nCyclesSegment); + MSM5205Update(); + HD6309Close(); + + if (DrvSubCPUType == DD_CPU_TYPE_HD63701) { + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = HD63701Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + + if (DrvSubCPUType == DD_CPU_TYPE_HD6309) { + nCurrentCPU = 1; + HD6309Open(1); + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = HD6309Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + HD6309Close(); + } + + if (DrvSubCPUType == DD_CPU_TYPE_M6803) { + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = M6803Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + + if (DrvSubCPUType == DD_CPU_TYPE_Z80) { + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + nCurrentCPU = 2; + M6809Open(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + M6809Close(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_Z80) { + nCurrentCPU = 2; + ZetOpen(1); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + } + + if (DrvGameType == DD_GAME_DARKTOWR) { + nCurrentCPU = 3; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = m6805Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + + if (i == VBlankSlice) { + DrvVBlank = 1; + HD6309Open(0); + HD6309SetIRQ(HD6309_INPUT_LINE_NMI, HD6309_IRQSTATUS_ACK); + HD6309Close(); + } + + for (INT32 j = 0; j < 16; j++) { + if (i == FIRQFireSlice[j]) { + HD6309Open(0); + HD6309SetIRQ(HD6309_FIRQ_LINE, HD6309_IRQSTATUS_ACK); + HD6309Close(); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + M6809Open(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + M6809Close(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + if (DrvSoundCPUType == DD_CPU_TYPE_M6809) { + M6809Open(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + M6809Close(); + } + + if (DrvSoundCPUType == DD_CPU_TYPE_Z80) { + ZetOpen(1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + if (DrvSoundCPUType == DD_CPU_TYPE_M6809 && pBurnSoundOut) { + M6809Open(0); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + MSM5205Render(1, pBurnSoundOut, nBurnSoundLen); + M6809Close(); + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +struct BurnDriver BurnDrvDdragon = { + "ddragon", NULL, NULL, NULL, "1987", + "Double Dragon (Japan)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragonw = { + "ddragonw", "ddragon", NULL, NULL, "1987", + "Double Dragon (World set 1)\0", NULL, "[Technos] (Taito license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvwRomInfo, DrvwRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragnw1 = { + "ddragonw1", "ddragon", NULL, NULL, "1987", + "Double Dragon (World set 2)\0", NULL, "[Technos] (Taito license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drvw1RomInfo, Drvw1RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragonu = { + "ddragonu", "ddragon", NULL, NULL, "1987", + "Double Dragon (US set 1)\0", NULL, "[Technos] (Taito America license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragoua = { + "ddragonua", "ddragon", NULL, NULL, "1987", + "Double Dragon (US set 2)\0", NULL, "[Technos] (Taito America license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvuaRomInfo, DrvuaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragoub = { + "ddragonub", "ddragon", NULL, NULL, "1987", + "Double Dragon (US set 3)\0", NULL, "[Technos] (Taito America license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvubRomInfo, DrvubRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragob2 = { + "ddragonb2", "ddragon", NULL, NULL, "1987", + "Double Dragon (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drvb2RomInfo, Drvb2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragonb = { + "ddragonb", "ddragon", NULL, NULL, "1987", + "Double Dragon (bootleg with HD6309)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragnba = { + "ddragonba", "ddragon", NULL, NULL, "1987", + "Double Dragon (bootleg with M6803)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvbaRomInfo, DrvbaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvbaInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragon2 = { + "ddragon2", NULL, NULL, NULL, "1988", + "Double Dragon II - The Revenge (World)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drv2RomInfo, Drv2RomName, NULL, NULL, DrvInputInfo, Drv2DIPInfo, + Drv2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDdragon2u = { + "ddragon2u", "ddragon2", NULL, NULL, "1988", + "Double Dragon II - The Revenge (US)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drv2uRomInfo, Drv2uRomName, NULL, NULL, DrvInputInfo, Drv2DIPInfo, + Drv2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriverD BurnDrvDdungeon = { + "ddungeon", NULL, NULL, NULL, "1992", + "Dangerous Dungeons\0", NULL, "Game Room", "Miscellaneous", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DdungeonRomInfo, DdungeonRomName, NULL, NULL, DrvInputInfo, DdungeonDIPInfo, + DdungeonInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDarktowr = { + "darktowr", NULL, NULL, NULL, "1992", + "Dark Tower\0", NULL, "Game Room", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DarktowrRomInfo, DarktowrRomName, NULL, NULL, DrvInputInfo, DarktowrDIPInfo, + DarktowrInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x180, 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_dec0.cpp b/src/burn/drivers/misc_pre90s/d_dec0.cpp new file mode 100644 index 00000000..dd198243 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_dec0.cpp @@ -0,0 +1,2462 @@ +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "msm6295.h" +#include "burn_ym2203.h" +#include "burn_ym3812.h" +#include "h6280_intf.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvM6502Rom = NULL; +static UINT8 *DrvM6502Ram = NULL; +static UINT8 *DrvH6280Rom = NULL; +static UINT8 *DrvH6280Ram = NULL; +static UINT8 *DrvCharRam = NULL; +static UINT8 *DrvCharCtrl0Ram = NULL; +static UINT8 *DrvCharCtrl1Ram = NULL; +static UINT8 *DrvCharColScrollRam = NULL; +static UINT8 *DrvCharRowScrollRam = NULL; +static UINT8 *DrvVideo1Ram = NULL; +static UINT8 *DrvVideo1Ctrl0Ram = NULL; +static UINT8 *DrvVideo1Ctrl1Ram = NULL; +static UINT8 *DrvVideo1ColScrollRam = NULL; +static UINT8 *DrvVideo1RowScrollRam = NULL; +static UINT8 *DrvVideo2Ram = NULL; +static UINT8 *DrvVideo2Ctrl0Ram = NULL; +static UINT8 *DrvVideo2Ctrl1Ram = NULL; +static UINT8 *DrvVideo2ColScrollRam = NULL; +static UINT8 *DrvVideo2RowScrollRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvPalette2Ram = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteDMABufferRam = NULL; +static UINT8 *DrvSharedRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles1 = NULL; +static UINT8 *DrvTiles2 = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; +static UINT16 *pCharLayerDraw = NULL; +static UINT16 *pTile1LayerDraw = NULL; +static UINT16 *pTile2LayerDraw = NULL; + +static INT32 i8751RetVal; +static UINT8 DrvVBlank; +static UINT8 DrvSoundLatch; +static UINT8 DrvFlipScreen; +static INT32 DrvPriority; +static INT32 DrvCharTilemapWidth; +static INT32 DrvCharTilemapHeight; +static INT32 DrvTile1TilemapWidth; +static INT32 DrvTile1TilemapHeight; +static INT32 DrvTile2TilemapWidth; +static INT32 DrvTile2TilemapHeight; + +typedef void (*Dec0Render)(); +static Dec0Render Dec0DrawFunction; +static void BaddudesDraw(); +static void HbarrelDraw(); +static void RobocopDraw(); + +static INT32 nCyclesDone[3], nCyclesTotal[3]; + +static INT32 Dec0Game = 0; + +#define DEC0_GAME_BADDUDES 1 +#define DEC0_GAME_HBARREL 2 +#define DEC0_GAME_BIRDTRY 3 + +static struct BurnInputInfo Dec0InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 fire 3" }, + {"Fire 4" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 fire 4" }, + {"Fire 5" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 fire 5" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"Fire 3 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 fire 3" }, + {"Fire 4 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 fire 4" }, + {"Fire 5 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 6, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Dec0) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); +} + +static struct BurnDIPInfo BaddudesDIPList[]= +{ + // Default Values + {0x18, 0xff, 0xff, 0xff, NULL }, + {0x19, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x18, 0x01, 0x03, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x03, "1 Coin 1 Play" }, + {0x18, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x18, 0x01, 0x0c, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x04, "2 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x0c, "1 Coin 1 Play" }, + {0x18, 0x01, 0x0c, 0x08, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x18, 0x01, 0x10, 0x10, "Off" }, + {0x18, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x18, 0x01, 0x20, 0x00, "Off" }, + {0x18, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x18, 0x01, 0x40, 0x40, "Off" }, + {0x18, 0x01, 0x40, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x19, 0x01, 0x03, 0x01, "1" }, + {0x19, 0x01, 0x03, 0x03, "3" }, + {0x19, 0x01, 0x03, 0x02, "5" }, + {0x19, 0x01, 0x03, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x19, 0x01, 0x0c, 0x08, "Easy" }, + {0x19, 0x01, 0x0c, 0x0c, "Normal" }, + {0x19, 0x01, 0x0c, 0x04, "Hard" }, + {0x19, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow continue" }, + {0x19, 0x01, 0x10, 0x10, "No" }, + {0x19, 0x01, 0x10, 0x00, "Yes" }, +}; + +STDDIPINFO(Baddudes) + +static struct BurnDIPInfo HbarrelDIPList[]= +{ + // Default Values + {0x18, 0xff, 0xff, 0xff, NULL }, + {0x19, 0xff, 0xff, 0xbf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x18, 0x01, 0x03, 0x00, "2 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x03, "1 Coin 1 Play" }, + {0x18, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + {0x18, 0x01, 0x03, 0x01, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x18, 0x01, 0x0c, 0x00, "2 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x0c, "1 Coin 1 Play" }, + {0x18, 0x01, 0x0c, 0x08, "1 Coin 2 Plays" }, + {0x18, 0x01, 0x0c, 0x04, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x18, 0x01, 0x10, 0x10, "Off" }, + {0x18, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x18, 0x01, 0x20, 0x00, "Off" }, + {0x18, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x18, 0x01, 0x40, 0x40, "Off" }, + {0x18, 0x01, 0x40, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x19, 0x01, 0x03, 0x01, "1" }, + {0x19, 0x01, 0x03, 0x03, "3" }, + {0x19, 0x01, 0x03, 0x02, "5" }, + {0x19, 0x01, 0x03, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x19, 0x01, 0x0c, 0x08, "Easy" }, + {0x19, 0x01, 0x0c, 0x0c, "Normal" }, + {0x19, 0x01, 0x0c, 0x04, "Hard" }, + {0x19, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x19, 0x01, 0x30, 0x30, "30k 80k 160k" }, + {0x19, 0x01, 0x30, 0x20, "50k 120k 190k" }, + {0x19, 0x01, 0x30, 0x10, "100k 200k 300k" }, + {0x19, 0x01, 0x30, 0x00, "150k 300k 450k" }, + + {0 , 0xfe, 0 , 2 , "Allow continue" }, + {0x19, 0x01, 0x40, 0x40, "No" }, + {0x19, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Hbarrel) + +static struct BurnDIPInfo HippodrmDIPList[]= +{ + // Default Values + {0x18, 0xff, 0xff, 0xff, NULL }, + {0x19, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x18, 0x01, 0x03, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x03, "1 Coin 1 Play" }, + {0x18, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x18, 0x01, 0x0c, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x04, "2 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x0c, "1 Coin 1 Play" }, + {0x18, 0x01, 0x0c, 0x08, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x18, 0x01, 0x20, 0x00, "Off" }, + {0x18, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x18, 0x01, 0x40, 0x40, "Off" }, + {0x18, 0x01, 0x40, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x19, 0x01, 0x03, 0x01, "1" }, + {0x19, 0x01, 0x03, 0x03, "2" }, + {0x19, 0x01, 0x03, 0x02, "3" }, + {0x19, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x19, 0x01, 0x0c, 0x08, "Easy" }, + {0x19, 0x01, 0x0c, 0x0c, "Normal" }, + {0x19, 0x01, 0x0c, 0x04, "Hard" }, + {0x19, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Player & Enemy Energy" }, + {0x19, 0x01, 0x30, 0x10, "Very Low" }, + {0x19, 0x01, 0x30, 0x20, "Low" }, + {0x19, 0x01, 0x30, 0x30, "Medium" }, + {0x19, 0x01, 0x30, 0x00, "High" }, + + {0 , 0xfe, 0 , 2 , "Energy Power Decrease on Continue"}, + {0x19, 0x01, 0x40, 0x40, "2 Dots" }, + {0x19, 0x01, 0x40, 0x00, "3 Dots" }, +}; + +STDDIPINFO(Hippodrm) + +static struct BurnDIPInfo RobocopDIPList[]= +{ + // Default Values + {0x18, 0xff, 0xff, 0x7f, NULL }, + {0x19, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x18, 0x01, 0x03, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x01, "2 Coins 1 Play" }, + {0x18, 0x01, 0x03, 0x03, "1 Coin 1 Play" }, + {0x18, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x18, 0x01, 0x0c, 0x00, "3 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x04, "2 Coins 1 Play" }, + {0x18, 0x01, 0x0c, 0x0c, "1 Coin 1 Play" }, + {0x18, 0x01, 0x0c, 0x08, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x18, 0x01, 0x20, 0x00, "Off" }, + {0x18, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x18, 0x01, 0x40, 0x40, "Off" }, + {0x18, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x18, 0x01, 0x80, 0x80, "Upright" }, + {0x18, 0x01, 0x80, 0x00, "Cocktail" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Player Energy" }, + {0x19, 0x01, 0x03, 0x01, "Low" }, + {0x19, 0x01, 0x03, 0x03, "Medium" }, + {0x19, 0x01, 0x03, 0x02, "High" }, + {0x19, 0x01, 0x03, 0x00, "Very High" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x19, 0x01, 0x0c, 0x08, "Easy" }, + {0x19, 0x01, 0x0c, 0x0c, "Normal" }, + {0x19, 0x01, 0x0c, 0x04, "Hard" }, + {0x19, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow continue" }, + {0x19, 0x01, 0x10, 0x10, "No" }, + {0x19, 0x01, 0x10, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Bonus Stage Energy" }, + {0x19, 0x01, 0x20, 0x00, "Low" }, + {0x19, 0x01, 0x20, 0x20, "High" }, + + {0 , 0xfe, 0 , 2 , "Brink Time" }, + {0x19, 0x01, 0x40, 0x40, "Normal" }, + {0x19, 0x01, 0x40, 0x00, "Less" }, +}; + +STDDIPINFO(Robocop) + +static struct BurnRomInfo BaddudesRomDesc[] = { + { "ei04-1.3c", 0x10000, 0x4bf158a7, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ei01-1.3a", 0x10000, 0x74f5110c, BRF_ESS | BRF_PRG }, // 1 + { "ei06.6c", 0x10000, 0x3ff8da57, BRF_ESS | BRF_PRG }, // 2 + { "ei03.6a", 0x10000, 0xf8f2bd94, BRF_ESS | BRF_PRG }, // 3 + + { "ei07.8a", 0x08000, 0x9fb1ef4b, BRF_ESS | BRF_PRG }, // 4 6502 Program + + { "ei25.15j", 0x08000, 0xbcf59a69, BRF_GRA }, // 5 Characters + { "ei26.16j", 0x08000, 0x9aff67b8, BRF_GRA }, // 6 + + { "ei18.14d", 0x10000, 0x05cfc3e5, BRF_GRA }, // 7 Tiles 1 + { "ei20.17d", 0x10000, 0xe11e988f, BRF_GRA }, // 8 + { "ei22.14f", 0x10000, 0xb893d880, BRF_GRA }, // 9 + { "ei24.17f", 0x10000, 0x6f226dda, BRF_GRA }, // 10 + + { "ei30.9j", 0x10000, 0x982da0d1, BRF_GRA }, // 11 Tiles 2 + { "ei28.9f", 0x10000, 0xf01ebb3b, BRF_GRA }, // 12 + + { "ei15.16c", 0x10000, 0xa38a7d30, BRF_GRA }, // 13 Sprites + { "ei16.17c", 0x08000, 0x17e42633, BRF_GRA }, // 14 + { "ei11.16a", 0x10000, 0x3a77326c, BRF_GRA }, // 15 + { "ei12.17a", 0x08000, 0xfea2a134, BRF_GRA }, // 16 + { "ei13.13c", 0x10000, 0xe5ae2751, BRF_GRA }, // 17 + { "ei14.14c", 0x08000, 0xe83c760a, BRF_GRA }, // 18 + { "ei09.13a", 0x10000, 0x6901e628, BRF_GRA }, // 19 + { "ei10.14a", 0x08000, 0xeeee8a1a, BRF_GRA }, // 20 + + { "ei08.2c", 0x10000, 0x3c87463e, BRF_SND }, // 21 Samples + + { "ei31.9a", 0x01000, 0x00000000, BRF_PRG | BRF_NODUMP }, // 22 I8751 +}; + +STD_ROM_PICK(Baddudes) +STD_ROM_FN(Baddudes) + +static struct BurnRomInfo DrgninjaRomDesc[] = { + { "eg04.3c", 0x10000, 0x41b8b3f8, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "eg01.3a", 0x10000, 0xe08e6885, BRF_ESS | BRF_PRG }, // 1 + { "eg06.6c", 0x10000, 0x2b81faf7, BRF_ESS | BRF_PRG }, // 2 + { "eg03.6a", 0x10000, 0xc52c2e9d, BRF_ESS | BRF_PRG }, // 3 + + { "eg07.8a", 0x08000, 0x001d2f51, BRF_ESS | BRF_PRG }, // 4 6502 Program + + { "eg25.15j", 0x08000, 0xdd557b19, BRF_GRA }, // 5 Characters + { "eg26.16j", 0x08000, 0x5d75fc8f, BRF_GRA }, // 6 + + { "eg18.14d", 0x10000, 0x05cfc3e5, BRF_GRA }, // 7 Tiles 1 + { "eg20.17d", 0x10000, 0xe11e988f, BRF_GRA }, // 8 + { "eg22.14f", 0x10000, 0xb893d880, BRF_GRA }, // 9 + { "eg24.17f", 0x10000, 0x6f226dda, BRF_GRA }, // 10 + + { "eg30.9j", 0x10000, 0x2438e67e, BRF_GRA }, // 11 Tiles 2 + { "eg28.9f", 0x10000, 0x5c692ab3, BRF_GRA }, // 12 + + { "eg15.16c", 0x10000, 0x5617d67f, BRF_GRA }, // 13 Sprites + { "eg16.17c", 0x08000, 0x17e42633, BRF_GRA }, // 14 + { "eg11.16a", 0x10000, 0xba83e8d8, BRF_GRA }, // 15 + { "eg12.17a", 0x08000, 0xfea2a134, BRF_GRA }, // 16 + { "eg13.13c", 0x10000, 0xfd91e08e, BRF_GRA }, // 17 + { "eg14.14c", 0x08000, 0xe83c760a, BRF_GRA }, // 18 + { "eg09.13a", 0x10000, 0x601b7b23, BRF_GRA }, // 19 + { "eg10.14a", 0x08000, 0xeeee8a1a, BRF_GRA }, // 20 + + { "eg08.2c", 0x10000, 0x92f2c916, BRF_SND }, // 21 Samples + + { "i8751", 0x01000, 0x00000000, BRF_PRG | BRF_NODUMP }, // 22 I8751 +}; + +STD_ROM_PICK(Drgninja) +STD_ROM_FN(Drgninja) + +static struct BurnRomInfo HbarrelRomDesc[] = { + { "hb04.bin", 0x10000, 0x4877b09e, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "hb01.bin", 0x10000, 0x8b41c219, BRF_ESS | BRF_PRG }, // 1 + { "hb05.bin", 0x10000, 0x2087d570, BRF_ESS | BRF_PRG }, // 2 + { "hb02.bin", 0x10000, 0x815536ae, BRF_ESS | BRF_PRG }, // 3 + { "hb06.bin", 0x10000, 0xda4e3fbc, BRF_ESS | BRF_PRG }, // 4 + { "hb03.bin", 0x10000, 0x7fed7c46, BRF_ESS | BRF_PRG }, // 5 + + { "hb07.bin", 0x08000, 0xa127f0f7, BRF_ESS | BRF_PRG }, // 6 6502 Program + + { "hb25.bin", 0x10000, 0x8649762c, BRF_GRA }, // 7 Characters + { "hb26.bin", 0x10000, 0xf8189bbd, BRF_GRA }, // 8 + + { "hb18.bin", 0x10000, 0xef664373, BRF_GRA }, // 9 Tiles 1 + { "hb17.bin", 0x10000, 0xa4f186ac, BRF_GRA }, // 10 + { "hb20.bin", 0x10000, 0x2fc13be0, BRF_GRA }, // 11 + { "hb19.bin", 0x10000, 0xd6b47869, BRF_GRA }, // 12 + { "hb22.bin", 0x10000, 0x50d6a1ad, BRF_GRA }, // 13 + { "hb21.bin", 0x10000, 0xf01d75c5, BRF_GRA }, // 14 + { "hb24.bin", 0x10000, 0xae377361, BRF_GRA }, // 15 + { "hb23.bin", 0x10000, 0xbbdaf771, BRF_GRA }, // 16 + + { "hb29.bin", 0x10000, 0x5514b296, BRF_GRA }, // 17 Tiles 2 + { "hb30.bin", 0x10000, 0x5855e8ef, BRF_GRA }, // 18 + { "hb27.bin", 0x10000, 0x99db7b9c, BRF_GRA }, // 19 + { "hb28.bin", 0x10000, 0x33ce2b1a, BRF_GRA }, // 20 + + { "hb15.bin", 0x10000, 0x21816707, BRF_GRA }, // 21 Sprites + { "hb16.bin", 0x10000, 0xa5684574, BRF_GRA }, // 22 + { "hb11.bin", 0x10000, 0x5c768315, BRF_GRA }, // 23 + { "hb12.bin", 0x10000, 0x8b64d7a4, BRF_GRA }, // 24 + { "hb13.bin", 0x10000, 0x56e3ed65, BRF_GRA }, // 25 + { "hb14.bin", 0x10000, 0xbedfe7f3, BRF_GRA }, // 26 + { "hb09.bin", 0x10000, 0x26240ea0, BRF_GRA }, // 27 + { "hb10.bin", 0x10000, 0x47d95447, BRF_GRA }, // 28 + + { "hb08.bin", 0x10000, 0x645c5b68, BRF_SND }, // 29 Samples + + { "hb31.9a", 0x01000, 0x239d726f, BRF_PRG | BRF_OPT }, // 30 I8751 +}; + +STD_ROM_PICK(Hbarrel) +STD_ROM_FN(Hbarrel) + +static struct BurnRomInfo HbarrelwRomDesc[] = { + { "hb_ec04.rom", 0x10000, 0xd01bc3db, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "hb_ec01.rom", 0x10000, 0x6756f8ae, BRF_ESS | BRF_PRG }, // 1 + { "hb05.bin", 0x10000, 0x2087d570, BRF_ESS | BRF_PRG }, // 2 + { "hb02.bin", 0x10000, 0x815536ae, BRF_ESS | BRF_PRG }, // 3 + { "hb_ec06.rom", 0x10000, 0x61ec20d8, BRF_ESS | BRF_PRG }, // 4 + { "hb_ec03.rom", 0x10000, 0x720c6b13, BRF_ESS | BRF_PRG }, // 5 + + { "hb_ec07.rom", 0x08000, 0x16a5a1aa, BRF_ESS | BRF_PRG }, // 6 6502 Program + + { "hb_ec25.rom", 0x10000, 0x2e5732a2, BRF_GRA }, // 7 Characters + { "hb_ec26.rom", 0x10000, 0x161a2c4d, BRF_GRA }, // 8 + + { "hb18.bin", 0x10000, 0xef664373, BRF_GRA }, // 9 Tiles 1 + { "hb17.bin", 0x10000, 0xa4f186ac, BRF_GRA }, // 10 + { "hb20.bin", 0x10000, 0x2fc13be0, BRF_GRA }, // 11 + { "hb19.bin", 0x10000, 0xd6b47869, BRF_GRA }, // 12 + { "hb22.bin", 0x10000, 0x50d6a1ad, BRF_GRA }, // 13 + { "hb21.bin", 0x10000, 0xf01d75c5, BRF_GRA }, // 14 + { "hb24.bin", 0x10000, 0xae377361, BRF_GRA }, // 15 + { "hb23.bin", 0x10000, 0xbbdaf771, BRF_GRA }, // 16 + + { "hb29.bin", 0x10000, 0x5514b296, BRF_GRA }, // 17 Tiles 2 + { "hb30.bin", 0x10000, 0x5855e8ef, BRF_GRA }, // 18 + { "hb27.bin", 0x10000, 0x99db7b9c, BRF_GRA }, // 19 + { "hb28.bin", 0x10000, 0x33ce2b1a, BRF_GRA }, // 20 + + { "hb15.bin", 0x10000, 0x21816707, BRF_GRA }, // 21 Sprites + { "hb16.bin", 0x10000, 0xa5684574, BRF_GRA }, // 22 + { "hb11.bin", 0x10000, 0x5c768315, BRF_GRA }, // 23 + { "hb12.bin", 0x10000, 0x8b64d7a4, BRF_GRA }, // 24 + { "hb13.bin", 0x10000, 0x56e3ed65, BRF_GRA }, // 25 + { "hb14.bin", 0x10000, 0xbedfe7f3, BRF_GRA }, // 26 + { "hb09.bin", 0x10000, 0x26240ea0, BRF_GRA }, // 27 + { "hb10.bin", 0x10000, 0x47d95447, BRF_GRA }, // 28 + + { "hb_ec08.rom", 0x10000, 0x2159a609, BRF_SND }, // 29 Samples + + { "ec31.9a", 0x01000, 0xaa14a2ae, BRF_PRG | BRF_OPT }, // 30 I8751 +}; + +STD_ROM_PICK(Hbarrelw) +STD_ROM_FN(Hbarrelw) + +static struct BurnRomInfo HippodrmRomDesc[] = { + { "ew02", 0x10000, 0xdf0d7dc6, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ew01", 0x10000, 0xd5670aa7, BRF_ESS | BRF_PRG }, // 1 + { "ew05", 0x10000, 0xc76d65ec, BRF_ESS | BRF_PRG }, // 2 + { "ew00", 0x10000, 0xe9b427a6, BRF_ESS | BRF_PRG }, // 3 + + { "ew04", 0x08000, 0x9871b98d, BRF_ESS | BRF_PRG }, // 4 6502 Program + + { "ew08", 0x10000, 0x53010534, BRF_ESS | BRF_PRG }, // 5 HuC6280 Program + + { "ew14", 0x10000, 0x71ca593d, BRF_GRA }, // 6 Characters + { "ew13", 0x10000, 0x86be5fa7, BRF_GRA }, // 7 + + { "ew19", 0x08000, 0x6b80d7a3, BRF_GRA }, // 8 Tiles 1 + { "ew18", 0x08000, 0x78d3d764, BRF_GRA }, // 9 + { "ew20", 0x08000, 0xce9f5de3, BRF_GRA }, // 10 + { "ew21", 0x08000, 0x487a7ba2, BRF_GRA }, // 11 + + { "ew24", 0x08000, 0x4e1bc2a4, BRF_GRA }, // 12 Tiles 2 + { "ew25", 0x08000, 0x9eb47dfb, BRF_GRA }, // 13 + { "ew23", 0x08000, 0x9ecf479e, BRF_GRA }, // 14 + { "ew22", 0x08000, 0xe55669aa, BRF_GRA }, // 15 + + { "ew15", 0x10000, 0x95423914, BRF_GRA }, // 16 Sprites + { "ew16", 0x10000, 0x96233177, BRF_GRA }, // 17 + { "ew10", 0x10000, 0x4c25dfe8, BRF_GRA }, // 18 + { "ew11", 0x10000, 0xf2e007fc, BRF_GRA }, // 19 + { "ew06", 0x10000, 0xe4bb8199, BRF_GRA }, // 20 + { "ew07", 0x10000, 0x470b6989, BRF_GRA }, // 21 + { "ew17", 0x10000, 0x8c97c757, BRF_GRA }, // 22 + { "ew12", 0x10000, 0xa2d244bc, BRF_GRA }, // 23 + + { "ew03", 0x10000, 0xb606924d, BRF_SND }, // 24 Samples +}; + +STD_ROM_PICK(Hippodrm) +STD_ROM_FN(Hippodrm) + +static struct BurnRomInfo RobocopRomDesc[] = { + { "ep05-4.11c", 0x10000, 0x29c35379, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ep01-4.11b", 0x10000, 0x77507c69, BRF_ESS | BRF_PRG }, // 1 + { "ep04-3", 0x10000, 0x39181778, BRF_ESS | BRF_PRG }, // 2 + { "ep00-3", 0x10000, 0xe128541f, BRF_ESS | BRF_PRG }, // 3 + + { "ep03-3", 0x08000, 0x5b164b24, BRF_ESS | BRF_PRG }, // 4 6502 Program + + { "en_24_mb7124e.a2", 0x00200, 0xb8e2ca98, BRF_ESS | BRF_PRG }, // 5 HuC6280 Program + + { "ep23", 0x10000, 0xa77e4ab1, BRF_GRA }, // 6 Characters + { "ep22", 0x10000, 0x9fbd6903, BRF_GRA }, // 7 + + { "ep20", 0x10000, 0x1d8d38b8, BRF_GRA }, // 8 Tiles 1 + { "ep21", 0x10000, 0x187929b2, BRF_GRA }, // 9 + { "ep18", 0x10000, 0xb6580b5e, BRF_GRA }, // 10 + { "ep19", 0x10000, 0x9bad01c7, BRF_GRA }, // 11 + + { "ep14", 0x08000, 0xca56ceda, BRF_GRA }, // 12 Tiles 2 + { "ep15", 0x08000, 0xa945269c, BRF_GRA }, // 13 + { "ep16", 0x08000, 0xe7fa4d58, BRF_GRA }, // 14 + { "ep17", 0x08000, 0x84aae89d, BRF_GRA }, // 15 + + { "ep07", 0x10000, 0x495d75cf, BRF_GRA }, // 16 Sprites + { "ep06", 0x08000, 0xa2ae32e2, BRF_GRA }, // 17 + { "ep11", 0x10000, 0x62fa425a, BRF_GRA }, // 18 + { "ep10", 0x08000, 0xcce3bd95, BRF_GRA }, // 19 + { "ep09", 0x10000, 0x11bed656, BRF_GRA }, // 20 + { "ep08", 0x08000, 0xc45c7b4c, BRF_GRA }, // 21 + { "ep13", 0x10000, 0x8fca9f28, BRF_GRA }, // 22 + { "ep12", 0x08000, 0x3cd1d0c3, BRF_GRA }, // 23 + + { "ep02", 0x10000, 0x711ce46f, BRF_SND }, // 24 Samples + + { "mb7116e.12c", 0x00400, 0xc288a256, BRF_OPT}, // 25 PROMs + { "mb7122e.17e", 0x00800, 0x64764ecf, BRF_OPT}, // 26 +}; + +STD_ROM_PICK(Robocop) +STD_ROM_FN(Robocop) + +static struct BurnRomInfo RobocopbRomDesc[] = { + { "robop_05.rom", 0x10000, 0xbcef3e9b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "robop_01.rom", 0x10000, 0xc9803685, BRF_ESS | BRF_PRG }, // 1 + { "robop_04.rom", 0x10000, 0x9d7b79e0, BRF_ESS | BRF_PRG }, // 2 + { "robop_00.rom", 0x10000, 0x80ba64ab, BRF_ESS | BRF_PRG }, // 3 + + { "ep03-3", 0x08000, 0x5b164b24, BRF_ESS | BRF_PRG }, // 4 6502 Program + + { "ep23", 0x10000, 0xa77e4ab1, BRF_GRA }, // 5 Characters + { "ep22", 0x10000, 0x9fbd6903, BRF_GRA }, // 6 + + { "ep20", 0x10000, 0x1d8d38b8, BRF_GRA }, // 7 Tiles 1 + { "ep21", 0x10000, 0x187929b2, BRF_GRA }, // 8 + { "ep18", 0x10000, 0xb6580b5e, BRF_GRA }, // 9 + { "ep19", 0x10000, 0x9bad01c7, BRF_GRA }, // 10 + + { "ep14", 0x08000, 0xca56ceda, BRF_GRA }, // 11 Tiles 2 + { "ep15", 0x08000, 0xa945269c, BRF_GRA }, // 12 + { "ep16", 0x08000, 0xe7fa4d58, BRF_GRA }, // 13 + { "ep17", 0x08000, 0x84aae89d, BRF_GRA }, // 14 + + { "ep07", 0x10000, 0x495d75cf, BRF_GRA }, // 15 Sprites + { "ep06", 0x08000, 0xa2ae32e2, BRF_GRA }, // 16 + { "ep11", 0x10000, 0x62fa425a, BRF_GRA }, // 17 + { "ep10", 0x08000, 0xcce3bd95, BRF_GRA }, // 18 + { "ep09", 0x10000, 0x11bed656, BRF_GRA }, // 19 + { "ep08", 0x08000, 0xc45c7b4c, BRF_GRA }, // 20 + { "ep13", 0x10000, 0x8fca9f28, BRF_GRA }, // 21 + { "ep12", 0x08000, 0x3cd1d0c3, BRF_GRA }, // 22 + + { "ep02", 0x10000, 0x711ce46f, BRF_SND }, // 23 Samples +}; + +STD_ROM_PICK(Robocopb) +STD_ROM_FN(Robocopb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x60000; + DrvM6502Rom = Next; Next += 0x08000; + DrvH6280Rom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x10000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x05800; + DrvM6502Ram = Next; Next += 0x00600; + DrvH6280Ram = Next; Next += 0x02000; + DrvCharRam = Next; Next += 0x02000; + DrvCharCtrl0Ram = Next; Next += 0x00008; + DrvCharCtrl1Ram = Next; Next += 0x00008; + DrvCharColScrollRam = Next; Next += 0x00080; + DrvCharRowScrollRam = Next; Next += 0x00400; + DrvVideo1Ram = Next; Next += 0x00800; + DrvVideo1Ctrl0Ram = Next; Next += 0x00008; + DrvVideo1Ctrl1Ram = Next; Next += 0x00008; + DrvVideo1ColScrollRam = Next; Next += 0x00080; + DrvVideo1RowScrollRam = Next; Next += 0x00400; + DrvVideo2Ram = Next; Next += 0x00800; + DrvVideo2Ctrl0Ram = Next; Next += 0x00008; + DrvVideo2Ctrl1Ram = Next; Next += 0x00008; + DrvVideo2ColScrollRam = Next; Next += 0x00080; + DrvVideo2RowScrollRam = Next; Next += 0x00400; + DrvPaletteRam = Next; Next += 0x00800; + DrvPalette2Ram = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x00800; + DrvSpriteDMABufferRam = Next; Next += 0x00800; + DrvSharedRam = Next; Next += 0x02000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x1000 * 8 * 8; + DrvTiles1 = Next; Next += 0x1000 * 16 * 16; + DrvTiles2 = Next; Next += 0x0800 * 16 * 16; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + pCharLayerDraw = (UINT16*)Next; Next += (1024 * 256 * sizeof(UINT16)); + pTile1LayerDraw = (UINT16*)Next; Next += (1024 * 256 * sizeof(UINT16)); + pTile2LayerDraw = (UINT16*)Next; Next += (1024 * 256 * sizeof(UINT16)); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM3812Reset(); + BurnYM2203Reset(); + MSM6295Reset(0); + + i8751RetVal = 0; + DrvVBlank = 0; + DrvSoundLatch = 0; + DrvFlipScreen = 0; + DrvPriority = 0; + + return 0; +} + +static INT32 RobocopDoReset() +{ + INT32 nRet = DrvDoReset(); + + h6280Open(0); + h6280Reset(); + h6280Close(); + + return nRet; +} + +static void BaddudesI8751Write(UINT16 Data) +{ + i8751RetVal = 0; + + switch (Data & 0xffff) { + case 0x714: i8751RetVal = 0x700; break; + case 0x73b: i8751RetVal = 0x701; break; + case 0x72c: i8751RetVal = 0x702; break; + case 0x73f: i8751RetVal = 0x703; break; + case 0x755: i8751RetVal = 0x704; break; + case 0x722: i8751RetVal = 0x705; break; + case 0x72b: i8751RetVal = 0x706; break; + case 0x724: i8751RetVal = 0x707; break; + case 0x728: i8751RetVal = 0x708; break; + case 0x735: i8751RetVal = 0x709; break; + case 0x71d: i8751RetVal = 0x70a; break; + case 0x721: i8751RetVal = 0x70b; break; + case 0x73e: i8751RetVal = 0x70c; break; + case 0x761: i8751RetVal = 0x70d; break; + case 0x753: i8751RetVal = 0x70e; break; + case 0x75b: i8751RetVal = 0x70f; break; + } +} + +static void HbarrelI8751Write(UINT16 Data) +{ + static INT32 Level, State; + + static const INT32 Title[]={ 1, 2, 5, 6, 9,10,13,14,17,18,21,22,25,26,29,30,33,34,37,38,41,42,0, + 3, 4, 7, 8,11,12,15,16,19,20,23,24,27,28,31,32,35,36,39,40,43,44,0, + 45,46,49,50,53,54,57,58,61,62,65,66,69,70,73,74,77,78,81,82,0, + 47,48,51,52,55,56,59,60,63,64,67,68,71,72,75,76,79,80,83,84,0, + 85,86,89,90,93,94,97,98,101,102,105,106,109,110,113,114,117,118,121,122,125,126,0, + 87,88,91,92,95,96,99,100,103,104,107,108,111,112,115,116,119,120,123,124,127,128,0, + 129,130,133,134,137,138,141,142,145,146,149,150,153,154,157,158,161,162,165,166,169,170,173,174,0, + 131,132,135,136,139,140,143,144,147,148,151,152,155,156,159,160,163,164,167,168,171,172,175,176,0, + 0x10b1,0x10b2,0,0x10b3,0x10b4,-1 + }; + + static const INT32 WeaponsTable[][0x20]={ + { 0x558,0x520,0x5c0,0x600,0x520,0x540,0x560,0x5c0,0x688,0x688,0x7a8,0x850,0x880,0x880,0x990,0x9b0,0x9b0,0x9e0,0xffff }, /* Level 1 */ + { 0x330,0x370,0x3d8,0x580,0x5b0,0x640,0x6a0,0x8e0,0x8e0,0x940,0x9f0,0xa20,0xa50,0xa80,0xffff }, /* Level 2 */ + { 0xb20,0xbd0,0xb20,0xb20,0xbd8,0xb50,0xbd8,0xb20,0xbe0,0xb40,0xb80,0xa18,0xa08,0xa08,0x980,0x8e0,0x780,0x790,0x650,0x600,0x5d0,0x5a0,0x570,0x590,0x5e0,0xffff }, /* Level 3 */ + { 0x530,0x5d0,0x5e0,0x5c8,0x528,0x520,0x5d8,0x5e0,0x5d8,0x540,0x570,0x5a0,0x658,0x698,0x710,0x7b8,0x8e0,0x8e0,0x8d8,0x818,0x8e8,0x820,0x8e0,0x848,0x848,0xffff }, /* Level 4 */ + { 0x230,0x280,0x700,0x790,0x790,0x7e8,0x7e8,0x8d0,0x920,0x950,0xad0,0xb90,0xb50,0xb10,0xbe0,0xbe0,0xffff }, /* Level 5 */ + { 0xd20,0xde0,0xd20,0xde0,0xd80,0xd80,0xd90,0xdd0,0xdb0,0xb20,0xa40,0x9e0,0x960,0x8a0,0x870,0x840,0x7e0,0x7b0,0x780,0xffff }, /* Level 6 */ + { 0x730,0x7e0,0x720,0x7e0,0x740,0x7c0,0x730,0x7d0,0x740,0x7c0,0x730,0x7d0,0x720,0x7e0,0x720,0x7e0,0x720,0x7e0,0x720,0x7e0,0x730,0x7d0,0xffff } /* Level 7 */ + }; + + switch (Data >> 8) { + case 0x02: { + i8751RetVal = Level; + break; + } + + case 0x03: { + Level++; + i8751RetVal = 0x301; + break; + } + + case 0x05: { + i8751RetVal = 0xb3b; + Level = 0; + break; + } + + case 0x06: { + i8751RetVal = WeaponsTable[Level][Data & 0x1f]; + break; + } + + case 0x0b: { + i8751RetVal = 0; + break; + } + + default: { + i8751RetVal = 0; + } + } + + if (Data == 7) i8751RetVal = 0xc000; + if (Data == 0x175) i8751RetVal = 0x68b; + if (Data == 0x174) i8751RetVal = 0x68c; + + if (Data == 0x4ff) State=0; + if (Data > 0x3ff && Data < 0x4ff) { + State++; + + if (Title[State - 1] == 0) { + i8751RetVal = 0xfffe; + } else { + if (Title[State - 1] == -1) { + i8751RetVal = 0xffff; + } else { + if (Title[State - 1] > 0x1000) { + i8751RetVal = (Title[State - 1] & 0xfff) + 128 + 15; + } else { + i8751RetVal = Title[State - 1] + 128 + 15 + 0x2000; + } + } + } + } +} + +UINT8 __fastcall Dec068KReadByte(UINT32 a) +{ + if (a >= 0x300000 && a <= 0x30001f) { + // rotary_r + return 0; + } + + switch (a) { + case 0x30c001: { + return 0xff - DrvInput[0]; + } + + case 0x30c003: { + return (0x7f - DrvInput[2]) | ((DrvVBlank) ? 0x80 : 0x00); + } + + case 0x30c004: { + return DrvDip[1]; + } + + case 0x30c005: { + return DrvDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dec068KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x30c011: { + DrvPriority = d; + return; + } + + case 0x30c015: { + DrvSoundLatch = d; + M6502Open(0); + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + M6502Close(); + return; + } + + case 0x30c01f: { + i8751RetVal = 0; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Dec068KReadWord(UINT32 a) +{ + if (a >= 0x300000 && a <= 0x30001f) { + // rotary_r + return 0; + } + + switch (a) { + case 0x30c000: { + return ((0xff - DrvInput[1]) << 8) | (0xff - DrvInput[0]); + } + + case 0x30c002: { + return (0xff7f - DrvInput[2]) | ((DrvVBlank) ? 0x80 : 0x00); + } + + case 0x30c004: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + case 0x30c008: { + return i8751RetVal; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dec068KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x31c000 && a <= 0x31c7ff) { + // ??? + return; + } + + switch (a) { + case 0x240000: + case 0x240002: + case 0x240004: + case 0x240006: { + UINT16 *Control0 = (UINT16*)DrvCharCtrl0Ram; + Control0[(a - 0x240000) >> 1] = d; + return; + } + + case 0x240010: + case 0x240012: + case 0x240014: + case 0x240016: { + UINT16 *Control1 = (UINT16*)DrvCharCtrl1Ram; + Control1[(a - 0x240010) >> 1] = d; + return; + } + + case 0x246000: + case 0x246002: + case 0x246004: + case 0x246006: { + UINT16 *Control0 = (UINT16*)DrvVideo1Ctrl0Ram; + Control0[(a - 0x246000) >> 1] = d; + return; + } + + case 0x246010: + case 0x246012: + case 0x246014: + case 0x246016: { + UINT16 *Control1 = (UINT16*)DrvVideo1Ctrl1Ram; + Control1[(a - 0x246010) >> 1] = d; + return; + } + + case 0x24c000: + case 0x24c002: + case 0x24c004: + case 0x24c006: { + UINT16 *Control0 = (UINT16*)DrvVideo2Ctrl0Ram; + Control0[(a - 0x24c000) >> 1] = d; + return; + } + + case 0x24c010: + case 0x24c012: + case 0x24c014: + case 0x24c016: { + UINT16 *Control1 = (UINT16*)DrvVideo2Ctrl1Ram; + Control1[(a - 0x24c010) >> 1] = d; + return; + } + + case 0x30c010: { + DrvPriority = d; + return; + } + + case 0x30c012: { + memcpy(DrvSpriteDMABufferRam, DrvSpriteRam, 0x800); + return; + } + + case 0x30c014: { + DrvSoundLatch = d & 0xff; + M6502Open(0); + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + M6502Close(); + return; + } + + case 0x30c016: { + if (Dec0Game == DEC0_GAME_BADDUDES) BaddudesI8751Write(d); + if (Dec0Game == DEC0_GAME_HBARREL) HbarrelI8751Write(d); + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + return; + } + + case 0x30c018: { + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + } + + case 0x30c01e: { + i8751RetVal = 0; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall HippodrmShared68KReadByte(UINT32 a) +{ + INT32 Offset = (a - 0x180000) >> 1; + return DrvSharedRam[Offset]; +} + +void __fastcall HippodrmShared68KWriteByte(UINT32 a, UINT8 d) +{ + INT32 Offset = (a - 0x180000) >> 1; + DrvSharedRam[Offset] = d; +} + +UINT16 __fastcall HippodrmShared68KReadWord(UINT32 a) +{ + INT32 Offset = (a - 0x180000) >> 1; + return DrvSharedRam[Offset]; +} + +void __fastcall HippodrmShared68KWriteWord(UINT32 a, UINT16 d) +{ + INT32 Offset = (a - 0x180000) >> 1; + DrvSharedRam[Offset] = d & 0xff; +} + +UINT8 __fastcall RobocopShared68KReadByte(UINT32 a) +{ + INT32 Offset = (a - 0x180000) >> 1; + return DrvSharedRam[Offset]; +} + +void __fastcall RobocopShared68KWriteByte(UINT32 a, UINT8 d) +{ + INT32 Offset = (a - 0x180000) >> 1; + DrvSharedRam[Offset] = d; + if (Offset == 0x7ff) { + bprintf(PRINT_NORMAL, _T("IRQ Raised\n")); + } +} + +UINT16 __fastcall RobocopShared68KReadWord(UINT32 a) +{ + INT32 Offset = (a - 0x180000) >> 1; + return DrvSharedRam[Offset]; +} + +void __fastcall RobocopShared68KWriteWord(UINT32 a, UINT16 d) +{ + INT32 Offset = (a - 0x180000) >> 1; + DrvSharedRam[Offset] = d & 0xff; + if (Offset == 0x7ff) { + bprintf(PRINT_NORMAL, _T("IRQ Raised\n")); + } +} + +UINT8 Dec0SoundReadByte(UINT16 a) +{ + switch (a) { + case 0x3000: { + return DrvSoundLatch; + } + + case 0x3800: { + return MSM6295ReadStatus(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Read Byte %04X\n"), a); + } + } + + return 0; +} + +void Dec0SoundWriteByte(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x0800: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x0801: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0x1000: { + BurnYM3812Write(0, d); + return; + } + + case 0x1001: { + BurnYM3812Write(1, d); + return; + } + + case 0x3800: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Write Byte %04X, %02X\n"), a, d); + } + } +} + +void HippodrmH6280WriteIo(UINT8 Port, UINT8 Data) +{ + bprintf(PRINT_NORMAL, _T("H6280 Write Port %x, %x\n"), Port, Data); +} + +UINT8 HippodrmH6280ReadProg(UINT32 Address) +{ + bprintf(PRINT_NORMAL, _T("H6280 Read Prog %x\n"), Address); + + return 0; +} + +void HippodrmH6280WriteProg(UINT32 Address, UINT8 Data) +{ + if (Address <= 0x00ffff) return; + + bprintf(PRINT_NORMAL, _T("H6280 Write Prog %x, %x\n"), Address, Data); +} + +void RobocopH6280WriteIo(UINT8 Port, UINT8 Data) +{ + bprintf(PRINT_NORMAL, _T("H6280 Write Port %x, %x\n"), Port, Data); +} + +UINT8 RobocopH6280ReadProg(UINT32 Address) +{ + bprintf(PRINT_NORMAL, _T("H6280 Read Prog %x\n"), Address); + + return 0; +} + +void RobocopH6280WriteProg(UINT32 Address, UINT8 Data) +{ + if (Address <= 0x00ffff) return; + + if (Address >= 0x1ff400 && Address <= 0x1ff403) { + h6280_irq_status_w(Address - 0x1ff400, Data); + return; + } + + bprintf(PRINT_NORMAL, _T("H6280 Write Prog %x, %x\n"), Address, Data); +} + +static INT32 CharPlaneOffsets[4] = { 0x000000, 0x040000, 0x020000, 0x060000 }; +static INT32 RobocopCharPlaneOffsets[4] = { 0x000000, 0x080000, 0x040000, 0x0c0000 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 Tile1PlaneOffsets[4] = { 0x080000, 0x180000, 0x000000, 0x100000 }; +static INT32 HbarrelTile1PlaneOffsets[4] = { 0x100000, 0x300000, 0x000000, 0x200000 }; +static INT32 Tile2PlaneOffsets[4] = { 0x040000, 0x0c0000, 0x000000, 0x080000 }; +static INT32 HbarrelTile2PlaneOffsets[4] = { 0x080000, 0x180000, 0x000000, 0x100000 }; +static INT32 SpritePlaneOffsets[4] = { 0x100000, 0x300000, 0x000000, 0x200000 }; +static INT32 TileXOffsets[16] = { 128, 129, 130, 131, 132, 133, 134, 135, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +inline static INT32 Dec0YM2203SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / 10000000; +} + +inline static double Dec0YM2203GetTime() +{ + return (double)SekTotalCycles() / 10000000; +} + +static void Dec0YM3812IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_ACK); + } else { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_NONE); + } +} + +static INT32 Dec0YM3812SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6502TotalCycles() * nSoundRate / 1500000; +} + +static INT32 Dec0MachineInit() +{ + INT32 nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(DrvCharColScrollRam , 0x242000, 0x24207f, SM_RAM); + SekMapMemory(DrvCharRowScrollRam , 0x242400, 0x2427ff, SM_RAM); + SekMapMemory(Drv68KRam + 0x4000 , 0x242800, 0x243fff, SM_RAM); + SekMapMemory(DrvCharRam , 0x244000, 0x245fff, SM_RAM); + SekMapMemory(DrvVideo1ColScrollRam , 0x248000, 0x24807f, SM_RAM); + SekMapMemory(DrvVideo1RowScrollRam , 0x248400, 0x2487ff, SM_RAM); + SekMapMemory(DrvVideo1Ram , 0x24a000, 0x24a7ff, SM_RAM); + SekMapMemory(DrvVideo2ColScrollRam , 0x24c800, 0x24c87f, SM_RAM); + SekMapMemory(DrvVideo2RowScrollRam , 0x24cc00, 0x24cfff, SM_RAM); + SekMapMemory(DrvVideo2Ram , 0x24d000, 0x24d7ff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x310000, 0x3107ff, SM_RAM); + SekMapMemory(DrvPalette2Ram , 0x314000, 0x3147ff, SM_RAM); + SekMapMemory(Drv68KRam , 0xff8000, 0xffbfff, SM_RAM); + SekMapMemory(DrvSpriteRam , 0xffc000, 0xffc7ff, SM_RAM); + SekSetReadByteHandler(0, Dec068KReadByte); + SekSetWriteByteHandler(0, Dec068KWriteByte); + SekSetReadWordHandler(0, Dec068KReadWord); + SekSetWriteWordHandler(0, Dec068KWriteWord); + SekClose(); + + // Setup the M6502 emulation + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502Ram , 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502Rom , 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(Dec0SoundReadByte); + M6502SetWriteByteHandler(Dec0SoundWriteByte); + M6502Close(); + + GenericTilesInit(); + + BurnYM3812Init(3000000, &Dec0YM3812IRQHandler, &Dec0YM3812SynchroniseStream, 1); + BurnTimerAttachM6502YM3812(1500000); + + BurnYM2203Init(1, 1500000, NULL, Dec0YM2203SynchroniseStream, Dec0YM2203GetTime, 0); + BurnTimerAttachSek(10000000); + + MSM6295Init(0, 1023924 / 132, 80, 1); + + return 0; +} + +static INT32 BaddudesInit() +{ + INT32 nRet = 0; + + Dec0MachineInit(); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 3, 2); if (nRet != 0) return 1; + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, DrvTempRom, DrvChars); + + // Load and decode tiles1 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles1); + + // Load and decode tiles2 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x20000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 12, 1); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x08000, DrvTempRom + 0x20000, 0x8000); + memcpy(DrvTempRom + 0x00000, DrvTempRom + 0x28000, 0x8000); + memcpy(DrvTempRom + 0x18000, DrvTempRom + 0x30000, 0x8000); + memcpy(DrvTempRom + 0x10000, DrvTempRom + 0x38000, 0x8000); + GfxDecode(0x400, 4, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles2); + + // Load and decode sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 20, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 21, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + Dec0DrawFunction = BaddudesDraw; + Dec0Game = DEC0_GAME_BADDUDES; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 HbarrelInit() +{ + INT32 nRet = 0; + + Dec0MachineInit(); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 5, 2); if (nRet != 0) return 1; + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom, 6, 1); if (nRet != 0) return 1; + + // Load and decode chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, RobocopCharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, DrvTempRom, DrvChars); + + // Load and decode tiles1 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 16, 1); if (nRet != 0) return 1; + GfxDecode(01000, 4, 16, 16, HbarrelTile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles1); + + // Load and decode tiles2 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 20, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, HbarrelTile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles2); + + // Load and decode sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 27, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 28, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 29, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + Dec0DrawFunction = HbarrelDraw; + Dec0Game = DEC0_GAME_HBARREL; + + UINT16 *Rom = (UINT16 *)Drv68KRom; + Rom[0xb68 >> 1] = 0x8008; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 HippodrmInit() +{ + INT32 nRet = 0; + + Dec0MachineInit(); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20000, 3, 2); if (nRet != 0) return 1; + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom, 4, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvH6280Rom, 5, 1); if (nRet != 0) return 1; + + // Load and decode chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, RobocopCharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, DrvTempRom, DrvChars); + + // Load and decode tiles1 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 11, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles1); + + // Load and decode tiles2 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 15, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles2); + + // Load and decode sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 23, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 24, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + Dec0DrawFunction = RobocopDraw; + + SekOpen(0); +// SekMapMemory(DrvSharedRam, 0x180000, 0x180fff, SM_RAM); + SekMapHandler(1, 0x180000, 0x180fff, SM_RAM); + SekSetReadByteHandler(1, HippodrmShared68KReadByte); + SekSetWriteByteHandler(1, HippodrmShared68KWriteByte); + SekSetReadWordHandler(1, HippodrmShared68KReadWord); + SekSetWriteWordHandler(1, HippodrmShared68KWriteWord); + SekClose(); + + h6280Init(1); + h6280Open(0); + h6280MapMemory(DrvH6280Rom , 0x000000, 0x00ffff, H6280_ROM); +// h6280MapMemory(DrvH6280Ram , 0x1f0000, 0x1f1fff, H6280_RAM); +// h6280MapMemory(DrvSharedRam, 0x1f2000, 0x1f3fff, H6280_RAM); +// h6280MapMemory(DrvH6280Rom , 0x1fe000, 0x1fffff, H6280_ROM); + h6280SetWritePortHandler(HippodrmH6280WriteIo); + h6280SetReadHandler(HippodrmH6280ReadProg); + h6280SetWriteHandler(HippodrmH6280WriteProg); + h6280Close(); + + // Reset the driver + RobocopDoReset(); + + return 0; +} + +static INT32 RobocopInit() +{ + INT32 nRet = 0; + + Dec0MachineInit(); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20000, 3, 2); if (nRet != 0) return 1; + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom, 4, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvH6280Rom + 0x01e00, 5, 1); if (nRet != 0) return 1; + + // Load and decode chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, RobocopCharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, DrvTempRom, DrvChars); + + // Load and decode tiles1 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 11, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles1); + + // Load and decode tiles2 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 15, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles2); + + // Load and decode sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 23, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 24, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + Dec0DrawFunction = RobocopDraw; + + SekOpen(0); + SekMapHandler(1, 0x180000, 0x180fff, SM_RAM); + SekSetReadByteHandler(1, RobocopShared68KReadByte); + SekSetWriteByteHandler(1, RobocopShared68KWriteByte); + SekSetReadWordHandler(1, RobocopShared68KReadWord); + SekSetWriteWordHandler(1, RobocopShared68KWriteWord); + SekClose(); + + h6280Init(1); + h6280Open(0); + h6280MapMemory(DrvH6280Rom , 0x000000, 0x00ffff, H6280_ROM); + h6280MapMemory(DrvH6280Ram , 0x1f0000, 0x1f1fff, H6280_RAM); + h6280MapMemory(DrvSharedRam, 0x1f2000, 0x1f3fff, H6280_RAM); + h6280MapMemory(DrvH6280Rom , 0x1fe000, 0x1fffff, H6280_ROM); + h6280SetWritePortHandler(RobocopH6280WriteIo); + h6280SetReadHandler(RobocopH6280ReadProg); + h6280SetWriteHandler(RobocopH6280WriteProg); + h6280Close(); + + // Reset the driver + RobocopDoReset(); + + return 0; +} + +static INT32 RobocopbInit() +{ + INT32 nRet = 0; + + Dec0MachineInit(); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20000, 3, 2); if (nRet != 0) return 1; + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, RobocopCharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, DrvTempRom, DrvChars); + + // Load and decode tiles1 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x800, 4, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles1); + + // Load and decode tiles2 + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 14, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles2); + + // Load and decode sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 22, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 23, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + Dec0DrawFunction = RobocopDraw; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + M6502Exit(); + + BurnYM2203Exit(); + BurnYM3812Exit(); + MSM6295Exit(0); + + GenericTilesExit(); + + i8751RetVal = 0; + DrvVBlank = 0; + DrvSoundLatch = 0; + DrvFlipScreen = 0; + DrvPriority = 0; + + DrvCharTilemapWidth = 0; + DrvCharTilemapHeight = 0; + DrvTile1TilemapWidth = 0; + DrvTile1TilemapHeight = 0; + DrvTile2TilemapWidth = 0; + DrvTile2TilemapHeight = 0; + + Dec0DrawFunction = NULL; + + Dec0Game = 0; + + BurnFree(Mem); + + return 0; +} + +static void DrvCalcPalette() +{ + UINT16 *PaletteRam = (UINT16*)DrvPaletteRam; + UINT16 *Palette2Ram = (UINT16*)DrvPalette2Ram; + + INT32 r, g, b; + + for (INT32 i = 0; i < 0x400; i++) { + r = (PaletteRam[i] >> 0) & 0xff; + g = (PaletteRam[i] >> 8) & 0xff; + b = (Palette2Ram[i] >> 0) & 0xff; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +#define PLOTPIXEL(x, po) pPixel[x] = nPalette | pTileData[x] | po; +#define PLOTPIXEL_FLIPX(x, a, po) pPixel[x] = nPalette | pTileData[a] | po; +#define PLOTPIXEL_MASK(x, mc, po) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x] | po;} +#define PLOTPIXEL_MASK_FLIPX(x, a, mc, po) if (pTileData[a] != mc) {pPixel[x] = nPalette | pTileData[a] | po;} +#define CLIPPIXEL(x, sx, mx, a) if ((sx + x) >= 0 && (sx + x) < mx) { a; }; + +static void Dec0Render8x8Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * TilemapWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += TilemapWidth, pTileData += 8) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + } +} + +static void Dec0Render8x8Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * TilemapWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= TilemapWidth, pTileData += 8) { + PLOTPIXEL_MASK_FLIPX(7, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(6, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(5, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(4, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(3, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(2, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(1, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(0, 7, nMaskColour, nPaletteOffset); + } +} + +static void Dec0Render16x16Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * TilemapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TilemapWidth, pTileData += 16) { + PLOTPIXEL( 0, nPaletteOffset); + PLOTPIXEL( 1, nPaletteOffset); + PLOTPIXEL( 2, nPaletteOffset); + PLOTPIXEL( 3, nPaletteOffset); + PLOTPIXEL( 4, nPaletteOffset); + PLOTPIXEL( 5, nPaletteOffset); + PLOTPIXEL( 6, nPaletteOffset); + PLOTPIXEL( 7, nPaletteOffset); + PLOTPIXEL( 8, nPaletteOffset); + PLOTPIXEL( 9, nPaletteOffset); + PLOTPIXEL(10, nPaletteOffset); + PLOTPIXEL(11, nPaletteOffset); + PLOTPIXEL(12, nPaletteOffset); + PLOTPIXEL(13, nPaletteOffset); + PLOTPIXEL(14, nPaletteOffset); + PLOTPIXEL(15, nPaletteOffset); + } +} + +static void Dec0Render16x16Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TilemapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TilemapWidth, pTileData += 16) { + PLOTPIXEL_FLIPX(15, 0, nPaletteOffset); + PLOTPIXEL_FLIPX(14, 1, nPaletteOffset); + PLOTPIXEL_FLIPX(13, 2, nPaletteOffset); + PLOTPIXEL_FLIPX(12, 3, nPaletteOffset); + PLOTPIXEL_FLIPX(11, 4, nPaletteOffset); + PLOTPIXEL_FLIPX(10, 5, nPaletteOffset); + PLOTPIXEL_FLIPX( 9, 6, nPaletteOffset); + PLOTPIXEL_FLIPX( 8, 7, nPaletteOffset); + PLOTPIXEL_FLIPX( 7, 8, nPaletteOffset); + PLOTPIXEL_FLIPX( 6, 9, nPaletteOffset); + PLOTPIXEL_FLIPX( 5, 10, nPaletteOffset); + PLOTPIXEL_FLIPX( 4, 11, nPaletteOffset); + PLOTPIXEL_FLIPX( 3, 12, nPaletteOffset); + PLOTPIXEL_FLIPX( 2, 13, nPaletteOffset); + PLOTPIXEL_FLIPX( 1, 14, nPaletteOffset); + PLOTPIXEL_FLIPX( 0, 15, nPaletteOffset); + } +} + +static void Dec0Render16x16Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * TilemapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TilemapWidth, pTileData += 16) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(15, nMaskColour, nPaletteOffset); + } +} + +static void Dec0Render16x16Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile, INT32 TilemapWidth) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TilemapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TilemapWidth, pTileData += 16) { + PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour, nPaletteOffset); + } +} + +#undef PLOTPIXEL +#undef PLOTPIXEL_FLIPX +#undef PLOTPIXEL_MASK +#undef CLIPPIXEL + +#define TILEMAP_BOTH_LAYERS 2 +#define TILEMAP_LAYER0 1 +#define TILEMAP_LAYER1 0 + +static void DrvRenderCustomTilemap(UINT16 *pSrc, UINT16 *pControl0, UINT16 *pControl1, UINT16 *RowScrollRam, UINT16 *ColScrollRam, INT32 TilemapWidth, INT32 TilemapHeight, INT32 Opaque, INT32 DrawLayer) +{ + INT32 x, y, xSrc, ySrc, ColOffset = 0, pPixel; + UINT32 xScroll = pControl1[0]; + UINT32 yScroll = pControl1[1]; + INT32 WidthMask = TilemapWidth - 1; + INT32 HeightMask = TilemapHeight - 1; + INT32 RowScrollEnabled = pControl0[0] & 0x04; + INT32 ColScrollEnabled = pControl0[0] & 0x08; + + ySrc = yScroll; + + for (y = 0; y < nScreenHeight; y++) { + if (RowScrollEnabled) { + xSrc = xScroll + RowScrollRam[(ySrc >> (pControl1[3] & 0x0f)) & (0x1ff >> (pControl1[3] & 0x0f))]; + } else { + xSrc = xScroll; + } + + xSrc &= TilemapWidth - 1; + + if (DrvFlipScreen) xSrc = -xSrc; + + for (x = 0; x < nScreenWidth; x++) { + if (ColScrollEnabled) ColOffset = ColScrollRam[((xSrc >> 3) >> (pControl1[2] & 0x0f)) & (0x3f >> (pControl1[2] & 0x0f))]; + + pPixel = pSrc[(((ySrc + ColOffset + 8) & HeightMask) * TilemapWidth) + (xSrc & WidthMask)]; + + xSrc++; + + if (Opaque || (pPixel & 0x0f)) { + if (DrawLayer == TILEMAP_LAYER0) { + if ((pPixel & 0x88) == 0x88) pTransDraw[(y * nScreenWidth) + x] = pPixel; + } else { + pTransDraw[(y * nScreenWidth) + x] = pPixel; + } + } + } + + ySrc++; + } +} + +static void DrvRenderTile1Layer(INT32 Opaque, INT32 DrawLayer) +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex, Layer; + UINT16 *Control0 = (UINT16*)DrvVideo1Ctrl0Ram; + UINT16 *VideoRam = (UINT16*)DrvVideo1Ram; + + INT32 RenderType = Control0[3] & 0x03; + + switch (RenderType) { + case 0x00: { + DrvTile1TilemapWidth = 1024; + DrvTile1TilemapHeight = 256; + break; + } + + case 0x01: { + DrvTile1TilemapWidth = 512; + DrvTile1TilemapHeight = 512; + break; + } + + case 0x02: { + DrvTile1TilemapWidth = 256; + DrvTile1TilemapHeight = 1024; + break; + } + } + + memset(pTile1LayerDraw, 0, DrvTile1TilemapWidth * DrvTile1TilemapHeight * sizeof(UINT16)); + + for (my = 0; my < (DrvTile1TilemapHeight / 16); my++) { + for (mx = 0; mx < (DrvTile1TilemapWidth / 16); mx++) { + TileIndex = (mx & 0x0f) + ((my & 0x0f) << 4) + ((mx & 0x30) << 4); + if (RenderType == 1) TileIndex = (mx & 0x0f) + ((my & 0x0f) << 4) + ((my & 0x10) << 4) + ((mx & 0x10) << 5); + if (RenderType == 2) TileIndex = (mx & 0x0f) + ((my & 0x3f) << 4); + + Attr = VideoRam[TileIndex]; + Code = Attr & 0xfff; + Colour = Attr >> 12; + Layer = (Attr >> 12) > 7; + + if (DrawLayer == TILEMAP_BOTH_LAYERS || DrawLayer == Layer) { + x = 16 * mx; + y = 16 * my; + + if (Opaque) { + if (DrvFlipScreen) { + x = 240 - x; + y = 240 - y; + x &= (DrvTile1TilemapWidth - 1); + y &= (DrvTile1TilemapHeight - 1); + Dec0Render16x16Tile_FlipXY(pTile1LayerDraw, Code, x, y, Colour, 4, 512, DrvTiles1, DrvTile1TilemapWidth); + } else { + Dec0Render16x16Tile(pTile1LayerDraw, Code, x, y, Colour, 4, 512, DrvTiles1, DrvTile1TilemapWidth); + } + } else { + if (DrvFlipScreen) { + x = 240 - x; + y = 240 - y; + x &= (DrvTile1TilemapWidth - 1); + y &= (DrvTile1TilemapHeight - 1); + Dec0Render16x16Tile_Mask_FlipXY(pTile1LayerDraw, Code, x, y, Colour, 4, 0, 512, DrvTiles1, DrvTile1TilemapWidth); + } else { + Dec0Render16x16Tile_Mask(pTile1LayerDraw, Code, x, y, Colour, 4, 0, 512, DrvTiles1, DrvTile1TilemapWidth); + } + } + } + } + } + + DrvRenderCustomTilemap(pTile1LayerDraw, (UINT16*)DrvVideo1Ctrl0Ram, (UINT16*)DrvVideo1Ctrl1Ram, (UINT16*)DrvVideo1RowScrollRam, (UINT16*)DrvVideo1ColScrollRam, DrvTile1TilemapWidth, DrvTile1TilemapHeight, Opaque, DrawLayer); +} + +static void DrvRenderTile2Layer(INT32 Opaque, INT32 DrawLayer) +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex, Layer; + UINT16 *Control0 = (UINT16*)DrvVideo2Ctrl0Ram; + UINT16 *VideoRam = (UINT16*)DrvVideo2Ram; + + INT32 RenderType = Control0[3] & 0x03; + + switch (RenderType) { + case 0x00: { + DrvTile2TilemapWidth = 1024; + DrvTile2TilemapHeight = 256; + break; + } + + case 0x01: { + DrvTile2TilemapWidth = 512; + DrvTile2TilemapHeight = 512; + break; + } + + case 0x02: { + DrvTile2TilemapWidth = 256; + DrvTile2TilemapHeight = 1024; + break; + } + } + + memset(pTile2LayerDraw, 0, DrvTile2TilemapWidth * DrvTile2TilemapHeight * sizeof(UINT16)); + + for (my = 0; my < (DrvTile2TilemapHeight / 16); my++) { + for (mx = 0; mx < (DrvTile2TilemapWidth / 16); mx++) { + TileIndex = (mx & 0x0f) + ((my & 0x0f) << 4) + ((mx & 0x30) << 4); + if (RenderType == 1) TileIndex = (mx & 0x0f) + ((my & 0x0f) << 4) + ((my & 0x10) << 4) + ((mx & 0x10) << 5); + if (RenderType == 2) TileIndex = (mx & 0x0f) + ((my & 0x3f) << 4); + + Attr = VideoRam[TileIndex]; + Code = Attr & 0xfff; + Colour = Attr >> 12; + Layer = (Attr >> 12) > 7; + + if (DrawLayer == TILEMAP_BOTH_LAYERS || DrawLayer == Layer) { + x = 16 * mx; + y = 16 * my; + + if (Opaque) { + if (DrvFlipScreen) { + x = 240 - x; + y = 240 - y; + x &= (DrvTile2TilemapWidth - 1); + y &= (DrvTile2TilemapHeight - 1); + Dec0Render16x16Tile_FlipXY(pTile2LayerDraw, Code, x, y, Colour, 4, 768, DrvTiles2, DrvTile2TilemapWidth); + } else { + Dec0Render16x16Tile(pTile2LayerDraw, Code, x, y, Colour, 4, 768, DrvTiles2, DrvTile2TilemapWidth); + } + } else { + if (DrvFlipScreen) { + x = 240 - x; + y = 240 - y; + x &= (DrvTile2TilemapWidth - 1); + y &= (DrvTile2TilemapHeight - 1); + Dec0Render16x16Tile_Mask_FlipXY(pTile2LayerDraw, Code, x, y, Colour, 4, 0, 768, DrvTiles2, DrvTile2TilemapWidth); + } else { + Dec0Render16x16Tile_Mask(pTile2LayerDraw, Code, x, y, Colour, 4, 0, 768, DrvTiles2, DrvTile2TilemapWidth); + } + } + } + } + } + + DrvRenderCustomTilemap(pTile2LayerDraw, (UINT16*)DrvVideo2Ctrl0Ram, (UINT16*)DrvVideo2Ctrl1Ram, (UINT16*)DrvVideo2RowScrollRam, (UINT16*)DrvVideo2ColScrollRam, DrvTile2TilemapWidth, DrvTile2TilemapHeight, Opaque, DrawLayer); +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex; + UINT16 *Control0 = (UINT16*)DrvCharCtrl0Ram; + UINT16 *CharRam = (UINT16*)DrvCharRam; + + INT32 RenderType = Control0[3] & 0x03; + + switch (RenderType) { + case 0x00: { + DrvCharTilemapWidth = 1024; + DrvCharTilemapHeight = 256; + break; + } + + case 0x01: { + DrvCharTilemapWidth = 512; + DrvCharTilemapHeight = 512; + break; + } + + case 0x02: { + DrvCharTilemapWidth = 256; + DrvCharTilemapHeight = 1024; + break; + } + } + + memset(pCharLayerDraw, 0, DrvCharTilemapWidth * DrvCharTilemapHeight * sizeof(UINT16)); + + for (my = 0; my < (DrvCharTilemapHeight / 8); my++) { + for (mx = 0; mx < (DrvCharTilemapWidth / 8); mx++) { + TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((mx & 0x60) << 5); + if (RenderType == 1) TileIndex = (mx & 0x1f) + ((my & 0x1f) << 5) + ((my & 0x20) << 5) + ((mx & 0x20) << 6); + if (RenderType == 2) TileIndex = (mx & 0x1f) + ((my & 0x7f) << 5); + + Attr = CharRam[TileIndex]; + Code = Attr & 0xfff; + Colour = Attr >> 12; + + x = 8 * mx; + y = 8 * my; + + if (DrvFlipScreen) { + x = 248 - x; + y = 248 - y; + x &= (DrvCharTilemapWidth - 1); + y &= (DrvCharTilemapHeight - 1); + Dec0Render8x8Tile_Mask_FlipXY(pCharLayerDraw, Code, x, y, Colour, 4, 0, 0, DrvChars, DrvCharTilemapWidth); + } else { + Dec0Render8x8Tile_Mask(pCharLayerDraw, Code, x, y, Colour, 4, 0, 0, DrvChars, DrvCharTilemapWidth); + } + } + } + + DrvRenderCustomTilemap(pCharLayerDraw, (UINT16*)DrvCharCtrl0Ram, (UINT16*)DrvCharCtrl1Ram, (UINT16*)DrvCharRowScrollRam, (UINT16*)DrvCharColScrollRam, DrvCharTilemapWidth, DrvCharTilemapHeight, 0, TILEMAP_BOTH_LAYERS); +} + +static void DrvRenderSprites(INT32 PriorityMask, INT32 PriorityVal) +{ + UINT16 *SpriteRam = (UINT16*)DrvSpriteDMABufferRam; + + for (UINT32 Offset = 0; Offset < 0x400; Offset += 4) { + INT32 x, y, Code, Colour, Multi, xFlip, yFlip, Inc, Flash, Mult, yPlot; + + y = SpriteRam[Offset + 0]; + if ((y & 0x8000) == 0) continue; + + x = SpriteRam[Offset + 2]; + Colour = x >> 12; + if ((Colour & PriorityMask) != PriorityVal) continue; + + Flash= x & 0x800; + if (Flash && (GetCurrentFrame() & 1)) continue; + + xFlip = y & 0x2000; + yFlip = y & 0x4000; + Multi = (1 << ((y & 0x1800) >> 11)) - 1; + + Code = SpriteRam[Offset + 1] & 0x0fff; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 256) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + if (x > 256) continue; + + Code &= ~Multi; + if (yFlip) { + Inc = -1; + } else { + Code += Multi; + Inc = 1; + } + + if (DrvFlipScreen) { + y = 240 - y; + x = 240 - x; + xFlip = !xFlip; + yFlip = !yFlip; + Mult = 16; + } else { + Mult = -16; + } + + while (Multi >= 0) { + yPlot = y + (Mult * Multi) - 8; + if (x > 16 && x < (nScreenWidth - 16) && yPlot > 16 && yPlot < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code - (Multi * Inc), x, yPlot, Colour, 4, 0, 256, DrvSprites); + } + } + } + + Multi--; + } + } +} + +static void BaddudesDraw() +{ + UINT16 *Control0 = (UINT16*)DrvCharCtrl0Ram; + DrvFlipScreen = Control0[0] & 0x80; + + BurnTransferClear(); + DrvCalcPalette(); + + if ((DrvPriority & 0x01) == 0x00) { + DrvRenderTile1Layer(1, TILEMAP_BOTH_LAYERS); + DrvRenderTile2Layer(0, TILEMAP_BOTH_LAYERS); + if (DrvPriority & 0x02) DrvRenderTile1Layer(0, TILEMAP_LAYER0); + DrvRenderSprites(0, 0); + if (DrvPriority & 0x04) DrvRenderTile2Layer(0, TILEMAP_LAYER0); + } else { + DrvRenderTile2Layer(1, TILEMAP_BOTH_LAYERS); + DrvRenderTile1Layer(0, TILEMAP_BOTH_LAYERS); + if (DrvPriority & 0x02) DrvRenderTile2Layer(0, TILEMAP_LAYER0); + DrvRenderSprites(0, 0); + if (DrvPriority & 0x04) DrvRenderTile1Layer(0, TILEMAP_LAYER0); + } + + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static void HbarrelDraw() +{ + UINT16 *Control0 = (UINT16*)DrvCharCtrl0Ram; + DrvFlipScreen = Control0[0] & 0x80; + + BurnTransferClear(); + DrvCalcPalette(); + + DrvRenderTile2Layer(1, TILEMAP_BOTH_LAYERS); + DrvRenderSprites(0x08, 0x08); + DrvRenderTile1Layer(0, TILEMAP_BOTH_LAYERS); + DrvRenderSprites(0x08, 0x00); + + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static void RobocopDraw() +{ + INT32 Trans; + UINT16 *Control0 = (UINT16*)DrvCharCtrl0Ram; + DrvFlipScreen = Control0[0] & 0x80; + + if (DrvPriority & 0x04) { + Trans = 0x08; + } else { + Trans = 0x00; + } + + BurnTransferClear(); + DrvCalcPalette(); + + if (DrvPriority & 0x01) { + DrvRenderTile1Layer(0, TILEMAP_LAYER1); + if (DrvPriority & 0x02) DrvRenderSprites(0x08, Trans); + DrvRenderTile2Layer(1, TILEMAP_BOTH_LAYERS); + } else { + DrvRenderTile2Layer(1, TILEMAP_BOTH_LAYERS); + if (DrvPriority & 0x02) DrvRenderSprites(0x08, Trans); + DrvRenderTile1Layer(0, TILEMAP_BOTH_LAYERS); + } + + if (DrvPriority & 0x02) { + DrvRenderSprites(0x08, Trans ^ 0x08); + } else { + DrvRenderSprites(0x00, 0x00); + } + + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +#undef TILEMAP_BOTH_LAYERS +#undef TILEMAP_LAYER0 +#undef TILEMAP_LAYER1 + +static INT32 DrvFrame() +{ + INT32 nInterleave = 264; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 1500000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + M6502NewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + + nCurrentCPU = 0; + SekOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if (i == 8) DrvVBlank = 0; + if (i == 248) DrvVBlank = 1; + if (i == 263) SekSetIRQLine(6, SEK_IRQSTATUS_ACK); + SekClose(); + + nCurrentCPU = 1; + M6502Open(0); + BurnTimerUpdateYM3812(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + M6502Close(); + } + + SekOpen(0); + BurnTimerEndFrame(nCyclesTotal[0]); + SekClose(); + + M6502Open(0); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + M6502Close(); + + if (pBurnSoundOut) { + SekOpen(0); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + SekClose(); + M6502Open(0); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + M6502Close(); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw && Dec0DrawFunction) Dec0DrawFunction(); + + return 0; +} + +static INT32 RobocopFrame() +{ + INT32 nInterleave = 264; + + if (DrvReset) RobocopDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 1500000 / 60; + nCyclesTotal[2] = 1342329 / 60; + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + SekNewFrame(); + M6502NewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + SekOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if (i == 8) DrvVBlank = 0; + if (i == 248) DrvVBlank = 1; + if (i == 263) SekSetIRQLine(6, SEK_IRQSTATUS_ACK); + SekClose(); + + nCurrentCPU = 2; + h6280Open(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = h6280Run(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + h6280Close(); + + nCurrentCPU = 1; + M6502Open(0); + BurnTimerUpdateYM3812(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + M6502Close(); + } + + SekOpen(0); + BurnTimerEndFrame(nCyclesTotal[0]); + SekClose(); + + M6502Open(0); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + M6502Close(); + + if (pBurnSoundOut) { + SekOpen(0); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + SekClose(); + M6502Open(0); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + M6502Close(); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw && Dec0DrawFunction) Dec0DrawFunction(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029708; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +struct BurnDriver BurnDrvBaddudes = { + "baddudes", NULL, NULL, NULL, "1988", + "Bad Dudes vs. Dragonninja (US)\0", NULL, "Data East USA", "DEC0", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, BaddudesRomInfo, BaddudesRomName, NULL, NULL, Dec0InputInfo, BaddudesDIPInfo, + BaddudesInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDrgninja = { + "drgninja", "baddudes", NULL, NULL, "1988", + "Dragonninja (Japan)\0", NULL, "Data East Corporation", "DEC0", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrgninjaRomInfo, DrgninjaRomName, NULL, NULL, Dec0InputInfo, BaddudesDIPInfo, + BaddudesInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHbarrel = { + "hbarrel", NULL, NULL, NULL, "1987", + "Heavy Barrel (US)\0", NULL, "Data East USA", "DEC0", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, HbarrelRomInfo, HbarrelRomName, NULL, NULL, Dec0InputInfo, HbarrelDIPInfo, + HbarrelInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 240, 256, 3, 4 +}; + +struct BurnDriver BurnDrvHbarrelw = { + "hbarrelw", "hbarrel", NULL, NULL, "1987", + "Heavy Barrel (World)\0", NULL, "Data East USA", "DEC0", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, HbarrelwRomInfo, HbarrelwRomName, NULL, NULL, Dec0InputInfo, HbarrelDIPInfo, + HbarrelInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 240, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvHippodrm = { + "hippodrm", NULL, NULL, NULL, "1989", + "Hippodrome (US)\0", NULL, "Data East USA", "DEC0", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, HippodrmRomInfo, HippodrmRomName, NULL, NULL, Dec0InputInfo, HippodrmDIPInfo, + HippodrmInit, DrvExit, RobocopFrame, NULL, DrvScan, + NULL, 0x400, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRobocop = { + "robocop", NULL, NULL, NULL, "1988", + "Robocop (World revision 4)\0", NULL, "Data East Corporation", "DEC0", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, RobocopRomInfo, RobocopRomName, NULL, NULL, Dec0InputInfo, RobocopDIPInfo, + RobocopInit, DrvExit, RobocopFrame, NULL, DrvScan, + NULL, 0x400, 256, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRobocopb = { + "robocopb", "robocop", NULL, NULL, "1988", + "Robocop (World bootleg)\0", NULL, "bootleg", "DEC0", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, RobocopbRomInfo, RobocopbRomName, NULL, NULL, Dec0InputInfo, RobocopDIPInfo, + RobocopbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_dec8.cpp b/src/burn/drivers/misc_pre90s/d_dec8.cpp new file mode 100644 index 00000000..b05e36bc --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_dec8.cpp @@ -0,0 +1,5385 @@ + +// To do: +// gondo needs rotary inputs hooked up and doesn't read the i8751 value at all - so coins don't work + +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "burn_ym2203.h" +#include "hd6309_intf.h" +#include "m6809_intf.h" +#include "burn_ym3812.h" +#include "burn_ym3526.h" +#include "msm5205.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvMainROM; +static UINT8 *DrvSubROM; +static UINT8 *DrvM6502ROM; +static UINT8 *DrvM6502OPS; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvColPROM; +static UINT8 *DrvMainRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvPf0RAM; +static UINT8 *DrvPf1RAM; +static UINT8 *DrvPf0Ctrl; +static UINT8 *DrvPf1Ctrl; +static UINT8 *DrvRowRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvM6502RAM; +static UINT8 *DrvPalRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *nmi_enable; +static UINT8 *interrupt_enable; +static UINT8 *flipscreen; + +static INT32 i8751_return; +static INT32 i8751_value; +static INT32 vblank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvInputs[5]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static struct BurnInputInfo GhostbInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy4 + 0, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 2, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy4 + 1, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Ghostb) + +static struct BurnDIPInfo GhostbDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xf0, NULL }, + {0x12, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x01, "1" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + {0x12, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Scene Time" }, + {0x12, 0x01, 0x30, 0x00, "4.00" }, + {0x12, 0x01, 0x30, 0x10, "4.30" }, + {0x12, 0x01, 0x30, 0x30, "5.00" }, + {0x12, 0x01, 0x30, 0x20, "6.00" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x40, 0x40, "No" }, + {0x12, 0x01, 0x40, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Beam Energy Pickup" }, + {0x12, 0x01, 0x80, 0x00, "Up 1.5%" }, + {0x12, 0x01, 0x80, 0x80, "Normal" }, +}; + +STDDIPINFO(Ghostb) + +static struct BurnInputInfo Ghostb3InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy4 + 0, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 2, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy4 + 1, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"P3 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p3 coin"}, + {"P3 Start", BIT_DIGITAL, DrvJoy4 + 2, "p3 start"}, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up"}, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down"}, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left"}, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right"}, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1"}, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Ghostb3) + +static struct BurnDIPInfo Ghostb3DIPList[]= +{ + {0x19, 0xff, 0xff, 0xf0, NULL }, + {0x1a, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x19, 0x01, 0x20, 0x00, "Off" }, + {0x19, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x19, 0x01, 0x40, 0x40, "Off" }, + {0x19, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x1a, 0x01, 0x03, 0x01, "1" }, + {0x1a, 0x01, 0x03, 0x03, "3" }, + {0x1a, 0x01, 0x03, 0x02, "5" }, + {0x1a, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x1a, 0x01, 0x0c, 0x04, "Easy" }, + {0x1a, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1a, 0x01, 0x0c, 0x08, "Hard" }, + {0x1a, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Scene Time" }, + {0x1a, 0x01, 0x30, 0x00, "4.00" }, + {0x1a, 0x01, 0x30, 0x10, "4.30" }, + {0x1a, 0x01, 0x30, 0x30, "5.00" }, + {0x1a, 0x01, 0x30, 0x20, "6.00" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x1a, 0x01, 0x40, 0x40, "No" }, + {0x1a, 0x01, 0x40, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Beam Energy Pickup" }, + {0x1a, 0x01, 0x80, 0x00, "Up 1.5%" }, + {0x1a, 0x01, 0x80, 0x80, "Normal" }, +}; + +STDDIPINFO(Ghostb3) + +static struct BurnInputInfo CobracomInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Cobracom) + +static struct BurnDIPInfo CobracomDIPList[]= +{ + {0x11, 0xff, 0xff, 0x7f, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x11, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x11, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x80, 0x00, "Upright" }, + {0x11, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x10, 0x00, "No" }, + {0x12, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x20, 0x20, "50k, 150k" }, + {0x12, 0x01, 0x20, 0x00, "100k, 200k" }, +}; + +STDDIPINFO(Cobracom) + +static struct BurnInputInfo SrdarwinInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 6, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Srdarwin) + +static struct BurnDIPInfo SrdarwinDIPList[]= +{ + {0x10, 0xff, 0xff, 0x7f, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x10, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x10, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x10, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x10, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x10, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x10, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x10, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x10, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x10, 0x01, 0x20, 0x00, "Off" }, + {0x10, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x40, 0x40, "Off" }, + {0x10, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x03, 0x01, "1" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "5" }, + {0x11, 0x01, 0x03, 0x00, "28 (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x0c, 0x04, "Easy" }, + {0x11, 0x01, 0x0c, 0x0c, "Normal" }, + {0x11, 0x01, 0x0c, 0x08, "Hard" }, + {0x11, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Continues" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Srdarwin) + +static struct BurnInputInfo GondoInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy4 + 0, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p1 fire 2"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4"}, // fake - hold space for rotory + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy4 + 1, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 2, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 3, "p2 fire 2"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 4"}, // fake - hold space for rotory + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Gondo) + +static struct BurnDIPInfo GondoDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x01, "1" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + {0x14, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x04, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x10, 0x10, "No" }, + {0x14, 0x01, 0x10, 0x00, "Yes" }, +}; + +STDDIPINFO(Gondo) + +static struct BurnInputInfo GaryoretInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy5 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 6, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy5 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Garyoret) + +static struct BurnDIPInfo GaryoretDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x11, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x11, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x01, 0x01, "3" }, + {0x12, 0x01, 0x01, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, +}; + +STDDIPINFO(Garyoret) + +static struct BurnInputInfo OscarInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Oscar) + +static struct BurnDIPInfo OscarDIPList[]= +{ + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x03, 0x00, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + {0x13, 0x01, 0x03, 0x01, "1 Coin 3 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + {0x13, 0x01, 0x0c, 0x04, "1 Coin 3 Credits " }, + + {0 , 0xfe, 0 , 2, "Freeze Mode" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x80, 0x00, "Upright" }, + {0x13, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x01, "1" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + {0x14, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x04, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "Every 40000" }, + {0x14, 0x01, 0x30, 0x20, "Every 60000" }, + {0x14, 0x01, 0x30, 0x10, "Every 90000" }, + {0x14, 0x01, 0x30, 0x00, "50000 only" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x00, "No" }, + {0x14, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Oscar) + +static struct BurnDIPInfo OscaruDIPList[]= +{ + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 2 Credits " }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 3 Credits " }, + {0x13, 0x01, 0x03, 0x01, "1 Coin 4 Credits " }, + {0x13, 0x01, 0x03, 0x00, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "4 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x04, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x08, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + + {0 , 0xfe, 0 , 2, "Freeze Mode" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x80, 0x00, "Upright" }, + {0x13, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x03, 0x01, "1" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x02, "5" }, + {0x14, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x04, "Easy" }, + {0x14, 0x01, 0x0c, 0x0c, "Normal" }, + {0x14, 0x01, 0x0c, 0x08, "Hard" }, + {0x14, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "Every 40000" }, + {0x14, 0x01, 0x30, 0x20, "Every 60000" }, + {0x14, 0x01, 0x30, 0x10, "Every 90000" }, + {0x14, 0x01, 0x30, 0x00, "50000 only" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x00, "No" }, + {0x14, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Oscaru) + +static struct BurnInputInfo LastmisnInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Lastmisn) + +static struct BurnDIPInfo LastmisnDIPList[]= +{ + {0x13, 0xff, 0xff, 0xcf, NULL }, + {0x14, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x20, 0x00, "Upright" }, + {0x13, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Infinite Lives (Cheat" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x14, 0x01, 0x01, 0x01, "3" }, + {0x14, 0x01, 0x01, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x06, 0x06, "30k, 70k then every 70k" }, + {0x14, 0x01, 0x06, 0x04, "40k, 90k then every 90k" }, + {0x14, 0x01, 0x06, 0x02, "40k and 80k" }, + {0x14, 0x01, 0x06, 0x00, "50k only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x18, 0x08, "Easy" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x10, "Hard" }, + {0x14, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, +}; + +STDDIPINFO(Lastmisn) + +static struct BurnDIPInfo LastmsnjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xcf, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x13, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x10, 0x10, "Off" }, + {0x13, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x20, 0x00, "Upright" }, + {0x13, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Infinite Lives (Cheat" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x14, 0x01, 0x01, 0x01, "3" }, + {0x14, 0x01, 0x01, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x06, 0x06, "30k, 50k then every 50k" }, + {0x14, 0x01, 0x06, 0x04, "30k, 70k then every 70k" }, + {0x14, 0x01, 0x06, 0x02, "50k, 100k then every 100k" }, + {0x14, 0x01, 0x06, 0x00, "50k only" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x18, 0x08, "Easy" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x10, "Hard" }, + {0x14, 0x01, 0x18, 0x00, "Hardest" }, +}; + +STDDIPINFO(Lastmsnj) + +static struct BurnInputInfo ShackledInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Shackled) + +static struct BurnDIPInfo ShackledDIPList[]= +{ + {0x11, 0xff, 0xff, 0xf7, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Leave Off" }, + {0x11, 0x01, 0x10, 0x10, "Off" }, + {0x11, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 16, "Power" }, + {0x12, 0x01, 0x0f, 0x07, "200" }, + {0x12, 0x01, 0x0f, 0x0b, "300" }, + {0x12, 0x01, 0x0f, 0x03, "400" }, + {0x12, 0x01, 0x0f, 0x0d, "500" }, + {0x12, 0x01, 0x0f, 0x05, "600" }, + {0x12, 0x01, 0x0f, 0x09, "700" }, + {0x12, 0x01, 0x0f, 0x01, "800" }, + {0x12, 0x01, 0x0f, 0x0e, "900" }, + {0x12, 0x01, 0x0f, 0x0f, "1000" }, + {0x12, 0x01, 0x0f, 0x06, "2000" }, + {0x12, 0x01, 0x0f, 0x0a, "3000" }, + {0x12, 0x01, 0x0f, 0x02, "4000" }, + {0x12, 0x01, 0x0f, 0x0c, "5000" }, + {0x12, 0x01, 0x0f, 0x04, "6000" }, + {0x12, 0x01, 0x0f, 0x08, "7000" }, + {0x12, 0x01, 0x0f, 0x00, "8000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x20, "Hard" }, + {0x12, 0x01, 0x30, 0x10, "Very Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Shackled) + +static struct BurnInputInfo CsilverInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Csilver) + +static struct BurnDIPInfo CsilverDIPList[]= +{ + {0x11, 0xff, 0xff, 0x7f, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x11, 0x01, 0x03, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x01, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x03, 0x03, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x03, 0x02, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x11, 0x01, 0x0c, 0x00, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x04, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x0c, 0x08, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x80, 0x00, "Upright" }, + {0x11, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x01, "1" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + {0x12, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x10, 0x00, "No" }, + {0x12, 0x01, 0x10, 0x10, "Yes" }, +}; + +STDDIPINFO(Csilver) + +static void ghostb_i8751_write(INT32 offset, INT32 data) +{ + i8751_return = 0; + + switch (offset) + { + case 0: + i8751_value = (i8751_value & 0x00ff) | (data << 8); + break; + + case 1: + i8751_value = (i8751_value & 0xff00) | (data << 0); + break; + } + + if (i8751_value == 0x00aa) i8751_return = 0x655; + if (i8751_value == 0x021a) i8751_return = 0x6e5; // Ghostbusters + if (i8751_value == 0x021b) i8751_return = 0x6e4; // Meikyuuh +} + +static void bankswitch(INT32 data) +{ + INT32 bank = (data & 0x0f) * 0x4000; + + HD6309MapMemory(DrvMainROM + 0x10000 + bank, 0x4000, 0x7fff, HD6309_ROM); // bank +} + +void ghostb_main_write(UINT16 address, UINT8 data) +{ +// bprintf (0, _T("%4.4x, %2.2x\n"), address, data); + + switch (address) + { + case 0x3800: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + case 0x3840: + bankswitch(data >> 4); + + *interrupt_enable = data & 1; + *nmi_enable = data & 2; + *flipscreen = data & 8; + return; + + case 0x3860: + case 0x3861: + ghostb_i8751_write(address & 1, data); + return; + } + + if ((address & 0xffe0) == 0x3820) { + DrvPf0Ctrl[address & 0x1f] = data; + return; + } +} + +UINT8 ghostb_main_read(UINT16 address) +{ + switch (address) + { + case 0x3800: + return DrvInputs[0]; + + case 0x3801: + return DrvInputs[1]; + + case 0x3802: + return DrvInputs[2]; + + case 0x3803: + return (DrvDips[0] & 0xf0) | (DrvInputs[3] & 0x07) | vblank; + + case 0x3820: + return DrvDips[1]; + + case 0x3840: + return i8751_return >> 8; + + case 0x3860: + return i8751_return & 0xff; + } + + return 0; +} + +void ghostb_sound_write(UINT16 address, UINT8 data) +{ +// bprintf (0, _T("%4.4x, %2.2x\n"), address, data); + + switch (address) + { + case 0x2000: + case 0x2001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0x4000: + case 0x4001: + BurnYM3812Write(address & 1, data); + return; + } +} + +UINT8 ghostb_sound_read(UINT16 address) +{ +// bprintf (0, _T("%4.4x, \n"), address); + + switch (address) + { + case 0x3000: + case 0x6000: + return *soundlatch; + } + + return 0; +} + +static INT32 DrvYM3812SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6502TotalCycles() * nSoundRate / 1500000; +} + +static INT32 DrvYM2203SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)HD6309TotalCycles() * nSoundRate / 1200000; +} + +static double DrvYM2203GetTime() +{ + return (double)HD6309TotalCycles() / 1200000; +} + +static INT32 DrvYM2203SynchroniseStream6000000(INT32 nSoundRate) +{ + return (INT64)HD6309TotalCycles() * nSoundRate / 6000000; +} + +static double DrvYM2203GetTime6000000() +{ + return (double)HD6309TotalCycles() / 6000000; +} + +static INT32 DrvYM2203M6809SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6809TotalCycles() * nSoundRate / 2000000; +} + +static double DrvYM2203M6809GetTime() +{ + return (double)M6809TotalCycles() / 2000000; +} + +static INT32 DrvYM2203M6809SynchroniseStream1500000(INT32 nSoundRate) +{ + return (INT64)M6809TotalCycles() * nSoundRate / 1500000; +} + +static double DrvYM2203M6809GetTime1500000() +{ + return (double)M6809TotalCycles() / 1500000; +} + +inline static INT32 CsilverMSM5205SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(M6809TotalCycles() * nSoundRate / 1500000); +} + +static void DrvYM3812FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_ACK); + } else { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + HD6309Open(0); + HD6309Reset(); + HD6309Close(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM3812Reset(); + BurnYM2203Reset(); + + i8751_return = 0; + i8751_value = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvMainROM = Next; Next += 0x050000; + DrvSubROM = Next; Next += 0x020000; + DrvM6502ROM = Next; Next += 0x020000; + DrvM6502OPS = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x100000; + + DrvColPROM = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvMainRAM = Next; Next += 0x002000; + DrvVidRAM = Next; Next += 0x000800; + DrvPf0RAM = Next; Next += 0x001000; + DrvPf1RAM = Next; Next += 0x001000; + DrvPf0Ctrl = Next; Next += 0x000020; + DrvPf1Ctrl = Next; Next += 0x000020; + DrvRowRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + + DrvM6502RAM = Next; Next += 0x000800; + + soundlatch = Next; Next += 0x000001; + nmi_enable = Next; Next += 0x000001; + interrupt_enable = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x400; i++) + { + INT32 bit0, bit1, bit2, bit3, r, g, b; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + bit3 = (DrvColPROM[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + bit0 = (DrvColPROM[i] >> 4) & 0x01; + bit1 = (DrvColPROM[i] >> 5) & 0x01; + bit2 = (DrvColPROM[i] >> 6) & 0x01; + bit3 = (DrvColPROM[i] >> 7) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + bit0 = (DrvColPROM[i + 0x400] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x400] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x400] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x400] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[3] = { 0x6000*8,0x4000*8,0x2000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x40000*8,0x20000*8,0x00000*8 }; + INT32 Plane2[4] = { 0x20000*8,0x00000*8,0x30000*8,0x10000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs1[16]= {16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 XOffs2[16]= {7,6,5,4,3,2,1,0,7+(16*8), 6+(16*8), 5+(16*8), 4+(16*8), 3+(16*8), 2+(16*8), 1+(16*8), 0+(16*8) }; + INT32 YOffs0[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 3, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane2, XOffs2, YOffs0, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static void Deco222Decode() +{ + for (INT32 A = 0x8000;A < 0x10000;A++) + DrvM6502OPS[A] = (DrvM6502ROM[A] & 0x9f) | ((DrvM6502ROM[A] & 0x20) << 1) | ((DrvM6502ROM[A] & 0x40) >> 1); +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (!strncmp(BurnDrvGetTextA(DRV_NAME), "ghostb", 6)) { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x30000, 3, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x40000, 4, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x50000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x70000, 14, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 18, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 19, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00400, 20, 1)) return 1; + + Deco222Decode(); + + } else { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x30000, 3, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x50000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x70000, 13, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 17, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 18, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00400, 19, 1)) return 1; + + memcpy (DrvM6502OPS + 0x8000, DrvM6502ROM + 0x8000, 0x8000); + } + + memset (DrvColPROM + 0x20, 0, 0xe0); // ok? + DrvPaletteInit(); + DrvGfxDecode(); + } + + HD6309Init(1); + HD6309Open(0); + HD6309MapMemory(DrvMainRAM, 0x0000, 0x17ff, HD6309_RAM); + HD6309MapMemory(DrvVidRAM, 0x1800, 0x1fff, HD6309_RAM); + HD6309MapMemory(DrvPf0RAM, 0x2000, 0x2bff, HD6309_RAM);// 0 - 27ff + HD6309MapMemory(DrvRowRAM, 0x2c00, 0x2fff, HD6309_RAM);// c00-dff + HD6309MapMemory(DrvSprRAM, 0x3000, 0x37ff, HD6309_RAM); + HD6309MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, HD6309_ROM); // bank + HD6309MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, HD6309_ROM); + HD6309SetWriteByteHandler(ghostb_main_write); + HD6309SetReadByteHandler(ghostb_main_read); + HD6309Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_READ); + M6502MapMemory(DrvM6502OPS + 0x8000, 0x8000, 0xffff, M6502_FETCH); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(ghostb_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM3812Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 0); + BurnTimerAttachM6502YM3812(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203SynchroniseStream, DrvYM2203GetTime, 1); + BurnTimerAttachHD6309(12000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + HD6309Exit(); + M6502Exit(); + + BurnYM3812Exit(); + BurnYM2203Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_txt_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 code = DrvVidRAM[offs * 2 + 1] | (DrvVidRAM[offs * 2 + 0] << 8); + INT32 color = (code >> 10) & 3; + + code &= 0x3ff; + if (code == 0) continue; // ok? + + sy -= 8; + if (sy < 0 || sy >= nScreenHeight) continue; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } +} + +static void draw_sprites1(INT32 priority) +{ + for (INT32 offs = 0;offs < 0x800;offs += 8) + { + INT32 y = DrvSprBuf[offs + 1] | (DrvSprBuf[offs + 0] << 8); + if (~y & 0x8000) continue; + + INT32 fx = DrvSprBuf[offs+3]; + if (~fx & 0x0001) continue; + + INT32 x = DrvSprBuf[offs + 5] | (DrvSprBuf[offs + 4] << 8); + + INT32 extra = fx & 0x0010; + INT32 fy = fx & 0x0002; + INT32 colour = DrvSprBuf[offs+6] >> 4; + + INT32 sprite = DrvSprBuf[offs+7]+(DrvSprBuf[offs+6]<<8); + sprite &= 0x0fff; + + if (priority == 1 && colour & 8) continue; + if (priority == 2 && ~colour & 8) continue; + + if (extra) {y=y+16;sprite&=0xffe;} + + x = x & 0x01ff; + y = y & 0x01ff; + x=(x+16)&0x1ff; + y=(y+16)&0x1ff; + x=256 - x; + y=256 - y; + + fx &= 0x0004; + + if (*flipscreen) + { + y=240-y; + x=240-x; + if (fx) fx=0; else fx=1; + if (fy) fy=0; else fy=1; + if (extra) y=y-16; + } + + INT32 sprite2; + /* Y Flip determines order of multi-sprite */ + if (extra && fy) + { + sprite2=sprite; + sprite++; + } + else + sprite2=sprite+1; + + y -= 8; + + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite & 0xfff, x, y, colour, 4, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite & 0xfff, x, y, colour, 4, 0, 0x100, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite & 0xfff, x, y, colour, 4, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite & 0xfff, x, y, colour, 4, 0, 0x100, DrvGfxROM1); + } + } + + /* 1 more sprite drawn underneath */ + if (extra) { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite2 & 0xfff, x, y+16, colour, 4, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite2 & 0xfff, x, y+16, colour, 4, 0, 0x100, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite2 & 0xfff, x, y+16, colour, 4, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite2 & 0xfff, x, y+16, colour, 4, 0, 0x100, DrvGfxROM1); + } + } + } + } +} + +static void draw_bg_layer(UINT8 *ram, UINT8 *ctrl, UINT8 *gfx, INT32 coff, INT32 cmask, INT32 mask, INT32 t, INT32 priority) +{ + INT32 rowscroll = ctrl[0x00] & 0x04; + INT32 scrolly = ((ctrl[0x12] << 8) + ctrl[0x13] + 8) & 0x1ff; + INT32 scrollx = ((ctrl[0x10] << 8) | ctrl[0x11]) & 0x1ff; + + if (rowscroll || t > 1) + { + INT32 xscroll[256]; + + for (INT32 i = 0; i < 256; i++) { + xscroll[i] = ((DrvRowRAM[i*2]<<8)+DrvRowRAM[i*2+1])&0x1ff; + } + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sy -= scrolly; + if (sy < -15) sy += 512; + sx -= scrollx; + if (sx < -15) sx += 512; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 ofst = (offs & 0x0f) | ((offs >> 1) & 0x1f0) | ((offs & 0x10) << 5); + + INT32 code = (ram[ofst * 2 + 0] << 8) | ram[ofst * 2 + 1]; + INT32 color = (code >> 12) & cmask; + + if (priority && color < 8) continue; + + { + code &= mask; + color <<= 4; + color += coff; + UINT16 *dst = pTransDraw; + UINT8 *src = gfx + (code << 8); + + for (INT32 y = 0; y < 16; y++, sy++, src+=16) + { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + INT32 xx = sx; + if (rowscroll) { + xx -= xscroll[sy]; + if (xx < -15) xx += 512; + if (xx >= nScreenWidth) continue; + } + + if (t) { + for (INT32 x = 0; x < 16; x++, xx++) + { + INT32 pxl = src[x]; + if (t & (1 << pxl)) continue; + if (xx < 0 || xx >= nScreenWidth) continue; + + dst[xx] = pxl | color; + } + } else { + for (INT32 x = 0; x < 16; x++, xx++) + { + if (xx < 0 || xx >= nScreenWidth) continue; + + dst[xx] = src[x] | color; + } + } + } + } + } + } else { + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + sy -= scrolly; + if (sx < -15) sx += 512; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 ofst = (offs & 0x0f) | ((offs >> 1) & 0x1f0) | ((offs & 0x10) << 5); + + INT32 code = (ram[ofst * 2 + 0] << 8) | ram[ofst * 2 + 1]; + INT32 color = (code >> 12) & cmask; + + if (priority && color < 8) continue; + + if (t) { + Render16x16Tile_Mask_Clip(pTransDraw, code & mask, sx, sy, color, 4, 0, coff, gfx); + } else { + Render16x16Tile_Clip(pTransDraw, code & mask, sx, sy, color, 4, coff, gfx); + } + } + } +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, (d >> 8) & 0xff, d & 0xff, 0); + } + } + + draw_bg_layer(DrvPf0RAM, DrvPf0Ctrl, DrvGfxROM2, 0x200, 0x0f, 0x7ff, 0, 0); + draw_sprites1(0); + draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static inline void do_interrupt() +{ + if (*interrupt_enable) { + HD6309SetIRQ(0, HD6309_IRQSTATUS_AUTO); + } +} + +static void ghostb_interrupt() +{ + static INT32 latch[4]; + INT32 i8751_out = DrvInputs[4] ^ 0x0f; + + if ((i8751_out & 0x8) == 0x8) latch[0] = 1; + if ((i8751_out & 0x4) == 0x4) latch[1] = 1; + if ((i8751_out & 0x2) == 0x2) latch[2] = 1; + if ((i8751_out & 0x1) == 0x1) latch[3] = 1; + + if (((i8751_out & 0x8) != 0x8) && latch[0]) {latch[0] = 0; do_interrupt(); i8751_return = 0x8001; } /* Player 1 coin */ + if (((i8751_out & 0x4) != 0x4) && latch[1]) {latch[1] = 0; do_interrupt(); i8751_return = 0x4001; } /* Player 2 coin */ + if (((i8751_out & 0x2) != 0x2) && latch[2]) {latch[2] = 0; do_interrupt(); i8751_return = 0x2001; } /* Player 3 coin */ + if (((i8751_out & 0x1) != 0x1) && latch[3]) {latch[3] = 0; do_interrupt(); i8751_return = 0x1001; } /* Service */ + + if (*nmi_enable) HD6309SetIRQ(0x20, HD6309_IRQSTATUS_AUTO); +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + HD6309NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = 32; + INT32 nCyclesTotal[2] = { 12000000 / 58, 1500000 / 58 }; +// INT32 nCyclesDone[2] = { 0, 0 }; + + M6502Open(0); + HD6309Open(0); + + vblank = 8; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 1) vblank = 0; + if (i == 31) { + vblank = 8; + ghostb_interrupt(); + } + + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + HD6309Close(); + M6502Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + + return 0; +} + + + + + + +// The Real Ghostbusters (US 2 Players) + +static struct BurnRomInfo ghostbRomDesc[] = { + { "dz01-22.1d", 0x08000, 0xfc65fdf2, 1 }, // 0 maincpu + { "dz02.3d", 0x10000, 0x8e117541, 1 }, // 1 + { "dz03.4d", 0x10000, 0x5606a8f4, 1 }, // 2 + { "dz04-21.6d", 0x10000, 0x7d46582f, 1 }, // 3 + { "dz05-21.7d", 0x10000, 0x23e1c758, 1 }, // 4 + + { "dz06.5f", 0x08000, 0x798f56df, 2 }, // 5 audiocpu + + { "dz00.16b", 0x08000, 0x992b4f31, 3 }, // 6 gfx1 + + { "dz15.14f", 0x10000, 0xa01a5fd9, 4 }, // 7 gfx2 + { "dz16.15f", 0x10000, 0x5a9a344a, 4 }, // 8 + { "dz12.9f", 0x10000, 0x817fae99, 4 }, // 9 + { "dz14.12f", 0x10000, 0x0abbf76d, 4 }, // 10 + { "dz11.8f", 0x10000, 0xa5e19c24, 4 }, // 11 + { "dz13.1f", 0x10000, 0x3e7c0405, 4 }, // 12 + { "dz17.17f", 0x10000, 0x40361b8b, 4 }, // 13 + { "dz18.18f", 0x10000, 0x8d219489, 4 }, // 14 + + { "dz07.12f", 0x10000, 0xe7455167, 5 }, // 15 gfx3 + { "dz08.14f", 0x10000, 0x32f9ddfe, 5 }, // 16 + { "dz09.15f", 0x10000, 0xbb6efc02, 5 }, // 17 + { "dz10.17f", 0x10000, 0x6ef9963b, 5 }, // 18 + + { "dz19a.10d", 0x00400, 0x47e1f83b, 6 }, // 19 proms + { "dz20a.11d", 0x00400, 0xd8fe2d99, 6 }, // 20 + + { "dz-1.1b", 0x01000, 0x18b7e1e6, 7 }, // 21 mcu +}; + +STD_ROM_PICK(ghostb) +STD_ROM_FN(ghostb) + +struct BurnDriver BurnDrvGhostb = { + "ghostb", NULL, NULL, NULL, "1987", + "The Real Ghostbusters (US 2 Players, revision 2)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, ghostbRomInfo, ghostbRomName, NULL, NULL, GhostbInputInfo, GhostbDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// The Real Ghostbusters (US 3 Players) + +static struct BurnRomInfo ghostb3RomDesc[] = { + { "dz01-3b.1d", 0x08000, 0xc8cc862a, 1 }, // 0 maincpu + { "dz02.3d", 0x10000, 0x8e117541, 1 }, // 1 + { "dz03.4d", 0x10000, 0x5606a8f4, 1 }, // 2 + { "dz04-1.6d", 0x10000, 0x3c3eb09f, 1 }, // 3 + { "dz05-1.7d", 0x10000, 0xb4971d33, 1 }, // 4 + + { "dz06.5f", 0x08000, 0x798f56df, 2 }, // 5 audiocpu + + { "dz00.16b", 0x08000, 0x992b4f31, 3 }, // 6 gfx1 + + { "dz15.14f", 0x10000, 0xa01a5fd9, 4 }, // 7 gfx2 + { "dz16.15f", 0x10000, 0x5a9a344a, 4 }, // 8 + { "dz12.9f", 0x10000, 0x817fae99, 4 }, // 9 + { "dz14.12f", 0x10000, 0x0abbf76d, 4 }, // 10 + { "dz11.8f", 0x10000, 0xa5e19c24, 4 }, // 11 + { "dz13.1f", 0x10000, 0x3e7c0405, 4 }, // 12 + { "dz17.17f", 0x10000, 0x40361b8b, 4 }, // 13 + { "dz18.18f", 0x10000, 0x8d219489, 4 }, // 14 + + { "dz07.12f", 0x10000, 0xe7455167, 5 }, // 15 gfx3 + { "dz08.14f", 0x10000, 0x32f9ddfe, 5 }, // 16 + { "dz09.15f", 0x10000, 0xbb6efc02, 5 }, // 17 + { "dz10.17f", 0x10000, 0x6ef9963b, 5 }, // 18 + + { "dz19a.10d", 0x00400, 0x47e1f83b, 6 }, // 19 proms + { "dz20a.11d", 0x00400, 0xd8fe2d99, 6 }, // 20 + + { "dz.1b", 0x01000, 0x18b7e1e6, 7 }, // 21 mcu +}; + +STD_ROM_PICK(ghostb3) +STD_ROM_FN(ghostb3) + +struct BurnDriver BurnDrvGhostb3 = { + "ghostb3", "ghostb", NULL, NULL, "1987", + "The Real Ghostbusters (US 3 Players)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, ghostb3RomInfo, ghostb3RomName, NULL, NULL, Ghostb3InputInfo, Ghostb3DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Meikyuu Hunter G (Japan, set 1) + +static struct BurnRomInfo meikyuhRomDesc[] = { + { "dw01-5.1d", 0x08000, 0x87610c39, 1 }, // 0 maincpu + { "dw02.3d", 0x10000, 0x40c9b0b8, 1 }, // 1 + { "dw03.4d", 0x10000, 0x5606a8f4, 1 }, // 2 + { "dw04.6d", 0x10000, 0x235c0c36, 1 }, // 3 + + { "dw05.5f", 0x08000, 0xc28c4d82, 2 }, // 4 audiocpu + + { "dw00.16b", 0x08000, 0x3d25f15c, 3 }, // 5 gfx1 + + { "dw14.14f", 0x10000, 0x9b0dbfa9, 4 }, // 6 gfx2 + { "dw15.15f", 0x10000, 0x95683fda, 4 }, // 7 + { "dw11.9f", 0x10000, 0x1b1fcca7, 4 }, // 8 + { "dw13.12f", 0x10000, 0xe7413056, 4 }, // 9 + { "dw10.8f", 0x10000, 0x57667546, 4 }, // 10 + { "dw12.1f", 0x10000, 0x4c548db8, 4 }, // 11 + { "dw16.17f", 0x10000, 0xe5bcf927, 4 }, // 12 + { "dw17.18f", 0x10000, 0x9e10f723, 4 }, // 13 + + { "dw06.12f", 0x10000, 0xb65e029d, 5 }, // 14 gfx3 + { "dw07.14f", 0x10000, 0x668d995d, 5 }, // 15 + { "dw08.15f", 0x10000, 0xbb2cf4a0, 5 }, // 16 + { "dw09.17f", 0x10000, 0x6a528d13, 5 }, // 17 + + { "dw18.9d", 0x00400, 0x75f1945f, 6 }, // 18 proms + { "dw19.10d", 0x00400, 0xcc16f3fa, 6 }, // 19 + + { "dw.1b", 0x01000, 0x28e9ced9, 7 | BRF_OPT }, // 20 mcu +}; + +STD_ROM_PICK(meikyuh) +STD_ROM_FN(meikyuh) + +struct BurnDriver BurnDrvMeikyuh = { + "meikyuh", "ghostb", NULL, NULL, "1987", + "Meikyuu Hunter G (Japan, set 1)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, meikyuhRomInfo, meikyuhRomName, NULL, NULL, GhostbInputInfo, GhostbDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Meikyuu Hunter G (Japan, set 2) + +static struct BurnRomInfo meikyuhaRomDesc[] = { + { "27256.1d", 0x08000, 0xd5b5e8a2, 1 }, // 0 maincpu + { "24512.3d", 0x10000, 0x40c9b0b8, 1 }, // 1 + { "24512.4d", 0x10000, 0x5606a8f4, 1 }, // 2 + { "27512.6d", 0x10000, 0x8ca6055d, 1 }, // 3 + + { "27256.5f", 0x08000, 0xc28c4d82, 2 }, // 4 audiocpu + + { "27256.16b", 0x08000, 0x3d25f15c, 3 }, // 5 gfx1 + + { "92.6m", 0x10000, 0x9b0dbfa9, 4 }, // 6 gfx2 + { "93.6o", 0x10000, 0x95683fda, 4 }, // 7 + { "89.6i", 0x10000, 0x1b1fcca7, 4 }, // 8 + { "91.6l", 0x10000, 0xe7413056, 4 }, // 9 + { "88.6h", 0x10000, 0x57667546, 4 }, // 10 + { "90.6k", 0x10000, 0x4c548db8, 4 }, // 11 + { "94.6p", 0x10000, 0xe5bcf927, 4 }, // 12 + { "95.6r", 0x10000, 0x9e10f723, 4 }, // 13 + + { "27512.12f", 0x10000, 0xb65e029d, 5 }, // 14 gfx3 + { "27512.14f", 0x10000, 0x668d995d, 5 }, // 15 + { "27512.15f", 0x10000, 0x547fe4e2, 5 }, // 16 + { "27512.17f", 0x10000, 0x6a528d13, 5 }, // 17 + + { "dw18.9d", 0x00400, 0x75f1945f, 6 }, // 18 proms + { "dw19.10d", 0x00400, 0xcc16f3fa, 6 }, // 19 + + { "dw.1b", 0x01000, 0x28e9ced9, 7 | BRF_OPT }, // 20 mcu +}; + +STD_ROM_PICK(meikyuha) +STD_ROM_FN(meikyuha) + +struct BurnDriver BurnDrvMeikyuha = { + "meikyuha", "ghostb", NULL, NULL, "1987", + "Meikyuu Hunter G (Japan, set 2)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, meikyuhaRomInfo, meikyuhaRomName, NULL, NULL, GhostbInputInfo, GhostbDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + + + + + + +static void m6809_bankswitch(INT32 data) +{ + INT32 bank = (data & 0x0f) * 0x4000; + + M6809MapMemory(DrvMainROM + 0x10000 + bank, 0x4000, 0x7fff, M6809_ROM); // bank +} + + + +void cobra_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3e00: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + M6502Run(500); + return; + + case 0x3c00: + m6809_bankswitch(data); + return; + + case 0x3c02: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + } + + if ((address & 0xffe0) == 0x3800) { + DrvPf0Ctrl[address & 0x1f] = data; + return; + } + + if ((address & 0xffe0) == 0x3a00) { + DrvPf1Ctrl[address & 0x1f] = data; + return; + } +} + +UINT8 cobra_main_read(UINT16 address) +{ + switch (address) + { + case 0x3800: + return DrvInputs[0]; + + case 0x3801: + return DrvInputs[1]; + + case 0x3802: + return DrvDips[0]; + + case 0x3803: + return DrvDips[1]; + + case 0x3a00: + return (DrvInputs[2] & 0x7f) | vblank; + } + + return 0; +} + +static INT32 CobraDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM2203Reset(); + BurnYM3812Reset(); + + i8751_return = 0; + i8751_value = 0; + + return 0; +} + + +static INT32 CobraGfxDecode() +{ + // 0, 0x40, 0x80, 0xc0 for offs + + INT32 Plane0[2] = { 0x4000*8,0x0000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x40000*8,0x20000*8,0x00000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs1[16]= { 16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 YOffs0[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 2, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 CobraInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + memcpy (DrvGfxROM2 + 0x40000, DrvGfxROM2 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 10, 1)) return 1; + memcpy (DrvGfxROM2 + 0x60000, DrvGfxROM2 + 0x28000, 0x08000); + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x20000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x40000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x60000, 14, 1)) return 1; + + memcpy (DrvM6502OPS + 0x8000, DrvM6502ROM + 0x8000, 0x8000); + + CobraGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvMainRAM, 0x0000, 0x07ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x0800, 0x0fff, M6809_RAM); + M6809MapMemory(DrvPf1RAM, 0x1000, 0x1fff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x3000, 0x37ff, M6809_RAM); + M6809MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(cobra_main_write); + M6809SetReadByteHandler(cobra_main_read); + M6809Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); +// m6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_READ); +// m6502MapMemory(DrvM6502OPS + 0x8000, 0x8000, 0xffff, M6502_FETCH); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(ghostb_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203M6809SynchroniseStream, DrvYM2203M6809GetTime, 0); + BurnTimerAttachM6809(2000000); + + BurnYM3812Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 1); + BurnTimerAttachM6502YM3812(1500000); + + GenericTilesInit(); + + CobraDoReset(); + + return 0; +} + +static void draw_cobra_txt_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 code = DrvVidRAM[offs * 2 + 1] | (DrvVidRAM[offs * 2 + 0] << 8); + INT32 color = (code >> 13); + + code &= 0x3ff; + if (code == 0) continue; // ok? + + sy -= 8; + if (sy < 0 || sy >= nScreenHeight) continue; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM0); + } +} + +static void draw_sprites2(INT32 colmask, INT32 priority) +{ + for (INT32 offs = 0;offs < 0x800;offs += 8) + { + INT32 y =DrvSprBuf[offs+1]+(DrvSprBuf[offs]<<8); + if ((y&0x8000) == 0) continue; + INT32 x = DrvSprBuf[offs+5]+(DrvSprBuf[offs+4]<<8); + INT32 colour = (x >> 12); + INT32 flash=x&0x800; + if (flash && (GetCurrentFrame() & 1)) continue; + + if (priority==1 && (colour&4)) continue; + if (priority==2 && !(colour&4)) continue; + + colour &= colmask; + colour += 0x4; + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x1800) >> 11)) - 1; + + INT32 sprite = DrvSprBuf[offs+3]+(DrvSprBuf[offs+2]<<8); + sprite &= 0x0fff; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 256) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + INT32 mult, inc; + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y=240-y; + x=240-x; + if (fx) fx=0; else fx=1; + if (fy) fy=0; else fy=1; + mult=16; + } + else mult=-16; + + y -= 8; + + while (multi >= 0) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, (sprite - multi * inc) & 0xfff, x, y + mult * multi, colour, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, (sprite - multi * inc) & 0xfff, x, y + mult * multi, colour, 4, 0, 0, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, (sprite - multi * inc) & 0xfff, x, y + mult * multi, colour, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, (sprite - multi * inc) & 0xfff, x, y + mult * multi, colour, 4, 0, 0, DrvGfxROM1); + } + } + + multi--; + } + } +} + +static INT32 CobraDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x200; i+=2) { + INT32 d = (DrvPalRAM[i + 0] << 8) | DrvPalRAM[i + 1]; + r = (d >> 0) & 0x0f; + g = (d >> 4) & 0x0f; + b = (d >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i/2] = BurnHighCol(r, g, b, 0); + } + } + + DrvPf0Ctrl[0] &= ~0x04; // disable line scrolling since this game + DrvPf1Ctrl[1] &= ~0x04; // doesn't have ram for the offsets + + draw_bg_layer(DrvPf0RAM, DrvPf0Ctrl, DrvGfxROM2, 0x80, 0x03, 0xfff, 0, 0); + draw_sprites2(0x03, 1); + draw_bg_layer(DrvPf1RAM, DrvPf1Ctrl, DrvGfxROM3, 0xc0, 0x03, 0xfff, 1, 0); + draw_sprites2(0x03, 2); + draw_cobra_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 CobraFrame() +{ + if (DrvReset) { + CobraDoReset(); + } + + M6809NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = 32; + INT32 nCyclesTotal[2] = { 2000000 / 58, 1500000 / 58 }; +// INT32 nCyclesDone[2] = { 0, 0 }; + + M6502Open(0); + M6809Open(0); + + vblank = 0x80; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 1) vblank = 0x80; + if (i == 31) { + vblank = 0; + M6809SetIRQ(0x20 /*NMI*/, M6809_IRQSTATUS_AUTO); + } + + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + } + + M6809Close(); + M6502Close(); + + if (pBurnDraw) { + CobraDraw(); + } + + return 0; +} + +// Cobra-Command (World revision 5) + +static struct BurnRomInfo cobracomRomDesc[] = { + { "el11-5.bin", 0x08000, 0xaf0a8b05, 1 }, // 0 maincpu + { "el12-4.bin", 0x10000, 0x7a44ef38, 1 }, // 1 + { "el13.bin", 0x10000, 0x04505acb, 1 }, // 2 + + { "el10-4.bin", 0x08000, 0xedfad118, 2 }, // 3 audiocpu + + { "el14.bin", 0x08000, 0x47246177, 3 }, // 4 gfx1 + + { "el00-4.bin", 0x10000, 0x122da2a8, 4 }, // 5 gfx2 + { "el01-4.bin", 0x10000, 0x27bf705b, 4 }, // 6 + { "el02-4.bin", 0x10000, 0xc86fede6, 4 }, // 7 + { "el03-4.bin", 0x10000, 0x1d8a855b, 4 }, // 8 + + { "el08.bin", 0x10000, 0xcb0dcf4c, 5 }, // 9 gfx4 + { "el09.bin", 0x10000, 0x1fae5be7, 5 }, // 10 + + { "el05.bin", 0x10000, 0x1c4f6033, 6 }, // 11 gfx3 + { "el06.bin", 0x10000, 0xd24ba794, 6 }, // 12 + { "el04.bin", 0x10000, 0xd80a49ce, 6 }, // 13 + { "el07.bin", 0x10000, 0x6d771fc3, 6 }, // 14 +}; + +STD_ROM_PICK(cobracom) +STD_ROM_FN(cobracom) + +struct BurnDriver BurnDrvCobracom = { + "cobracom", NULL, NULL, NULL, "1988", + "Cobra-Command (World revision 5)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, cobracomRomInfo, cobracomRomName, NULL, NULL, CobracomInputInfo, CobracomDIPInfo, + CobraInit, DrvExit, CobraFrame, CobraDraw, NULL, &DrvRecalc, 0x100, + 256, 240, 4, 3 +}; + + +// Cobra-Command (Japan) + +static struct BurnRomInfo cobracmjRomDesc[] = { + { "eh-11.rom", 0x08000, 0x868637e1, 1 }, // 0 maincpu + { "eh-12.rom", 0x10000, 0x7c878a83, 1 }, // 1 + { "el13.bin", 0x10000, 0x04505acb, 1 }, // 2 + + { "eh-10.rom", 0x08000, 0x62ca5e89, 2 }, // 3 audiocpu + + { "el14.bin", 0x08000, 0x47246177, 3 }, // 4 gfx1 + + { "eh-00.rom", 0x10000, 0xd96b6797, 4 }, // 5 gfx2 + { "eh-01.rom", 0x10000, 0x3fef9c02, 4 }, // 6 + { "eh-02.rom", 0x10000, 0xbfae6c34, 4 }, // 7 + { "eh-03.rom", 0x10000, 0xd56790f8, 4 }, // 8 + + { "el08.bin", 0x10000, 0xcb0dcf4c, 5 }, // 9 gfx4 + { "el09.bin", 0x10000, 0x1fae5be7, 5 }, // 10 + + { "el05.bin", 0x10000, 0x1c4f6033, 6 }, // 11 gfx3 + { "el06.bin", 0x10000, 0xd24ba794, 6 }, // 12 + { "el04.bin", 0x10000, 0xd80a49ce, 6 }, // 13 + { "el07.bin", 0x10000, 0x6d771fc3, 6 }, // 14 +}; + +STD_ROM_PICK(cobracmj) +STD_ROM_FN(cobracmj) + +struct BurnDriver BurnDrvCobracmj = { + "cobracomj", "cobracom", NULL, NULL, "1988", + "Cobra-Command (Japan)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, cobracmjRomInfo, cobracmjRomName, NULL, NULL, CobracomInputInfo, CobracomDIPInfo, + CobraInit, DrvExit, CobraFrame, CobraDraw, NULL, &DrvRecalc, 0x100, + 256, 240, 4, 3 +}; + + +// Cobra-Command (Japan?, set 2) + +static struct BurnRomInfo cobracmjaRomDesc[] = { + { "el-11.rom", 0x08000, 0xc6a102e3, 1 }, // 0 maincpu + { "el-12.rom", 0x10000, 0x72b2dab4, 1 }, // 1 + { "el-13.rom", 0x10000, 0x04505acb, 1 }, // 2 + + { "el-10.rom", 0x08000, 0x62ca5e89, 2 }, // 3 audiocpu + + { "el-14.rom", 0x08000, 0x47246177, 3 }, // 4 gfx1 + + { "eh-00.rom", 0x10000, 0xd96b6797, 4 }, // 5 gfx2 + { "eh-01.rom", 0x10000, 0x3fef9c02, 4 }, // 6 + { "eh-02.rom", 0x10000, 0xbfae6c34, 4 }, // 7 + { "eh-03.rom", 0x10000, 0xd56790f8, 4 }, // 8 + + { "el-08.rom", 0x10000, 0xcb0dcf4c, 5 }, // 9 gfx4 + { "el-09.rom", 0x10000, 0x1fae5be7, 5 }, // 10 + + { "el-05.rom", 0x10000, 0x1c4f6033, 6 }, // 11 gfx3 + { "el-06.rom", 0x10000, 0xd24ba794, 6 }, // 12 + { "el-04.rom", 0x10000, 0xd80a49ce, 6 }, // 13 + { "el-07.rom", 0x10000, 0x6d771fc3, 6 }, // 14 +}; + +STD_ROM_PICK(cobracmja) +STD_ROM_FN(cobracmja) + +struct BurnDriver BurnDrvCobracmja = { + "cobracomja", "cobracom", NULL, NULL, "1988", + "Cobra-Command (Japan?, set 2)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, cobracmjaRomInfo, cobracmjaRomName, NULL, NULL, CobracomInputInfo, CobracomDIPInfo, + CobraInit, DrvExit, CobraFrame, CobraDraw, NULL, &DrvRecalc, 0x100, + 256, 240, 4, 3 +}; + + + + + + + +static void srdarwin_i8751_w(INT32 offset, INT32 data) +{ + static INT32 coins, latch; + i8751_return = 0; + + switch (offset) + { + case 0: /* High byte */ + i8751_value = (i8751_value & 0xff) | (data << 8); + break; + + case 1: /* Low byte */ + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + if (i8751_value == 0x0000) {i8751_return = 0; coins = 0;} + if (i8751_value == 0x3063) i8751_return = 0x9c; /* Protection - Japanese version */ + if (i8751_value == 0x306b) i8751_return = 0x94; /* Protection - World version */ + if ((i8751_value & 0xff00) == 0x4000) i8751_return = i8751_value; /* Coinage settings */ + if (i8751_value == 0x5000) i8751_return =((coins / 10) << 4) | (coins % 10); /* Coin request */ + if (i8751_value == 0x6000) {i8751_value = -1; coins--; } /* Coin clear */ + + if ((DrvInputs[4] & 1) == 1) latch = 1; + if ((DrvInputs[4] & 1) != 1 && latch) {coins++; latch = 0;} + + if (i8751_value == 0x8000) i8751_return = 0xf580 + 0; /* Boss #1: Snake + Bees */ + if (i8751_value == 0x8001) i8751_return = 0xf580 + 30; /* Boss #2: 4 Corners */ + if (i8751_value == 0x8002) i8751_return = 0xf580 + 26; /* Boss #3: Clock */ + if (i8751_value == 0x8003) i8751_return = 0xf580 + 2; /* Boss #4: Pyramid */ + if (i8751_value == 0x8004) i8751_return = 0xf580 + 6; /* Boss #5: Snake + Head Combo */ + if (i8751_value == 0x8005) i8751_return = 0xf580 + 24; /* Boss #6: LED Panels */ + if (i8751_value == 0x8006) i8751_return = 0xf580 + 28; /* Boss #7: Dragon */ + if (i8751_value == 0x8007) i8751_return = 0xf580 + 32; /* Boss #8: Teleport */ + if (i8751_value == 0x8008) i8751_return = 0xf580 + 38; /* Boss #9: Octopus (Pincer) */ + if (i8751_value == 0x8009) i8751_return = 0xf580 + 40; /* Boss #10: Bird */ + if (i8751_value == 0x800a) i8751_return = 0xf580 + 42; /* End Game(bad address?) */ +} + +void srdarwin_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1800: + case 0x1801: + srdarwin_i8751_w(address & 1, data); + return; + + case 0x1802: + i8751_value = 0; + return; + + case 0x1804: + memcpy (DrvSprBuf, DrvSprRAM, 0x200); + return; + + case 0x1805: + m6809_bankswitch(data >> 5); + DrvPf0Ctrl[0x10] = data & 0x01; + return; + + case 0x1806: + DrvPf0Ctrl[0x11] = data; + return; + + case 0x2000: + *soundlatch = data; +// m6502SetIRQ(M6502_NMI); + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + case 0x2001: + *flipscreen = data; + return; + } +} + +UINT8 srdarwin_main_read(UINT16 address) +{ + switch (address) + { + case 0x2000: + return i8751_return >> 8; + + case 0x2001: + return i8751_return & 0xff; + + case 0x3800: + return DrvDips[0]; + + case 0x3801: + return DrvInputs[0]; + + case 0x3802: + return (DrvInputs[1] & ~0x40) | vblank; + + case 0x3803: + return DrvDips[1]; + } + + return 0; +} + +static INT32 SrdarwinGfxDecode() +{ + INT32 Plane0[2] = { 0, 4 }; + INT32 Plane1[4] = { 0x10000*8,0x20000*8,0x00000*8 }; + INT32 Plane2[4] = { 0x4000*8, 0x4000*8+4, 0, 4 }; + + INT32 XOffs0[8] = { 0x2000*8+0, 0x2000*8+1, 0x2000*8+2, 0x2000*8+3, 0, 1, 2, 3 }; + INT32 XOffs1[16] = { 16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 XOffs2[16] = { 0, 1, 2, 3, 1024*8*8+0, 1024*8*8+1, 1024*8*8+2, 1024*8*8+3, + 16*8+0, 16*8+1, 16*8+2, 16*8+3, 16*8+1024*8*8+0, 16*8+1024*8*8+1, 16*8+1024*8*8+2, 16*8+1024*8*8+3 }; + + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 2, 8, 8, Plane0, XOffs0, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x0800, 3, 16, 16, Plane1, XOffs1, YOffs, 0x100, tmp, DrvGfxROM1); + + for (INT32 i = 0; i < 4; i++) { + memcpy (tmp, DrvGfxROM2 + i * 0x10000, 0x08000); + GfxDecode(0x0100, 4, 16, 16, Plane2, XOffs2, YOffs, 0x100, tmp, DrvGfxROM2 + i * 0x10000); + } + + BurnFree (tmp); + + return 0; +} + + +static INT32 SrdarwinInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvMainROM + 0x20000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + memcpy (DrvMainROM + 0x8000, DrvMainROM + 0x28000, 0x08000); + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x18000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x28000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 10, 1)) return 1; + memcpy (DrvGfxROM2 + 0x00000, DrvGfxROM3 + 0x00000, 0x04000); + memcpy (DrvGfxROM2 + 0x10000, DrvGfxROM3 + 0x04000, 0x04000); + memcpy (DrvGfxROM2 + 0x20000, DrvGfxROM3 + 0x08000, 0x04000); + memcpy (DrvGfxROM2 + 0x30000, DrvGfxROM3 + 0x0c000, 0x04000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 11, 1)) return 1; + memcpy (DrvGfxROM2 + 0x04000, DrvGfxROM3 + 0x00000, 0x04000); + memcpy (DrvGfxROM2 + 0x14000, DrvGfxROM3 + 0x04000, 0x04000); + memcpy (DrvGfxROM2 + 0x24000, DrvGfxROM3 + 0x08000, 0x04000); + memcpy (DrvGfxROM2 + 0x34000, DrvGfxROM3 + 0x0c000, 0x04000); + + memcpy (DrvM6502OPS + 0x8000, DrvM6502ROM + 0x8000, 0x8000); + + Deco222Decode(); + SrdarwinGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvMainRAM, 0x0000, 0x05ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x0600, 0x07ff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x0800, 0x0fff, M6809_RAM); + M6809MapMemory(DrvMainRAM + 0x1000, 0x1000, 0x13ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x1400, 0x17ff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x2800, 0x28ff, M6809_RAM); + M6809MapMemory(DrvPalRAM + 0x100, 0x3000, 0x30ff, M6809_RAM); + M6809MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(srdarwin_main_write); + M6809SetReadByteHandler(srdarwin_main_read); + M6809Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_READ); + M6502MapMemory(DrvM6502OPS + 0x8000, 0x8000, 0xffff, M6502_FETCH); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(ghostb_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203M6809SynchroniseStream, DrvYM2203M6809GetTime, 0); + BurnTimerAttachM6809(2000000); + + BurnYM3812Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 1); + BurnTimerAttachM6502YM3812(1500000); + + GenericTilesInit(); + + CobraDoReset(); + + return 0; +} + +static void Srdarwin_draw_layer(INT32 layer) +{ + INT32 scrollx = (DrvPf0Ctrl[0x10] << 8) | DrvPf0Ctrl[0x11]; + + UINT16 layer0t[4] = { 0x0000, 0xff00, 0xff00, 0xffff }; + UINT16 layer1t[4] = { 0xffff, 0x00ff, 0x00ff, 0x0000 }; + UINT16 *layert = layer ? layer1t : layer0t; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sy -= 8; + if (sy >= nScreenHeight) continue; + sx -= scrollx; + if (sx < -15) sx += 512; + if (sx >= nScreenWidth) continue; + + INT32 code = DrvPf0RAM[offs * 2 + 1] | (DrvPf0RAM[offs * 2 + 0] << 8); + INT32 color = (code >> 12) & 3; + + { + code &= 0x3ff; + color <<= 4; + + INT32 t = layert[color>>4]; + UINT8 *src = DrvGfxROM2 + (code << 8); + UINT16 *dst; + + for (INT32 y = 0; y < 16; y++, sy++, src+=16) + { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + INT32 xx = sx; + + for (INT32 x = 0; x < 16; x++, xx++) + { + INT32 pxl = src[x]; + + if (t & (1 << pxl)) continue; + if (xx < 0 || xx >= nScreenWidth) continue; + + dst[xx] = pxl | color; + } + } + } + } +} + +static void srdarwin_txt_draw() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + sy -= 8; + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 code = DrvVidRAM[offs]; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, 0, 2, 0, 0x80, DrvGfxROM0); + } +} + +static void srdarwin_draw_sprites(INT32 pri) +{ + for (INT32 offs = 0;offs < 0x200;offs += 4) + { + INT32 multi,fx,sx,sy,sy2,code,color; + + color = (DrvSprBuf[offs+1] & 0x03) + ((DrvSprBuf[offs+1] & 0x08) >> 1); + if (pri==0 && color!=0) continue; + if (pri==1 && color==0) continue; + + code = DrvSprBuf[offs+3] + ( ( DrvSprBuf[offs+1] & 0xe0 ) << 3 ); + if (!code) continue; + + sy = DrvSprBuf[offs]; + if (sy == 0xf8) continue; + + sx = (241 - DrvSprBuf[offs+2]); + + fx = DrvSprBuf[offs+1] & 0x04; + multi = DrvSprBuf[offs+1] & 0x10; + + if (*flipscreen) + { + sy=240-sy; + sx=240-sx; + if (fx) fx=0; else fx=1; + sy2=sy-16; + } + else sy2=sy+16; + + sy -= 8; + sy2 -= 8; + + if (*flipscreen) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x40, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x40, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x40, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x40, DrvGfxROM1); + } + } + + if (multi) { + code++; + if (*flipscreen) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy2, color, 3, 0, 0x40, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy2, color, 3, 0, 0x40, DrvGfxROM1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy2, color, 3, 0, 0x40, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy2, color, 3, 0, 0x40, DrvGfxROM1); + } + } + } + } +} + +static INT32 SrdarwinDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x100; i++) { + INT32 d = (DrvPalRAM[i + 0]) | (DrvPalRAM[i + 0x100] << 8); + r = (d >> 0) & 0x0f; + g = (d >> 4) & 0x0f; + b = (d >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + Srdarwin_draw_layer(1); + srdarwin_draw_sprites(0); + Srdarwin_draw_layer(0); + srdarwin_draw_sprites(1); + + srdarwin_txt_draw(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 SrdarwinFrame() +{ + if (DrvReset) { + CobraDoReset(); + } + + M6809NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 4); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + DrvInputs[4] = DrvJoy5[0] & 1; + } + + INT32 nInterleave = 32; + INT32 nCyclesTotal[2] = { 2000000 / 58, 1500000 / 58 }; +// INT32 nCyclesDone[2] = { 0, 0 }; + + M6502Open(0); + M6809Open(0); + + vblank = 0x40; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 1) vblank = 0x40; + if (i == 31) { + vblank = 0; + M6809SetIRQ(0x20 /*NMI*/, M6809_IRQSTATUS_AUTO); + } + + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + } + + M6809Close(); + M6502Close(); + + if (pBurnDraw) { + SrdarwinDraw(); + } + + return 0; +} + + +// Super Real Darwin (World) + +static struct BurnRomInfo srdarwinRomDesc[] = { + { "dy01-e.b14", 0x10000, 0x176e9299, 1 }, // 0 maincpu + { "dy00.b16", 0x10000, 0x2bf6b461, 1 }, // 1 + + { "dy04.d7", 0x08000, 0x2ae3591c, 2 }, // 2 audiocpu + + { "dy05.b6", 0x04000, 0x8780e8a3, 3 }, // 3 gfx1 + + { "dy07.h16", 0x08000, 0x97eaba60, 4 }, // 4 gfx2 + { "dy06.h14", 0x08000, 0xc279541b, 4 }, // 5 + { "dy09.k13", 0x08000, 0xd30d1745, 4 }, // 6 + { "dy08.k11", 0x08000, 0x71d645fd, 4 }, // 7 + { "dy11.k16", 0x08000, 0xfd9ccc5b, 4 }, // 8 + { "dy10.k14", 0x08000, 0x88770ab8, 4 }, // 9 + + { "dy03.b4", 0x10000, 0x44f2a4f9, 5 }, // 10 gfx3 + { "dy02.b5", 0x10000, 0x522d9a9e, 5 }, // 11 + + { "id8751h.mcu", 0x01000, 0x00000000, 6 | BRF_NODUMP }, // 12 mcu + + { "dy12.f4", 0x00100, 0xebfaaed9, 7 }, // 13 proms +}; + +STD_ROM_PICK(srdarwin) +STD_ROM_FN(srdarwin) + +struct BurnDriver BurnDrvSrdarwin = { + "srdarwin", NULL, NULL, NULL, "1987", + "Super Real Darwin (World)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, srdarwinRomInfo, srdarwinRomName, NULL, NULL, SrdarwinInputInfo, SrdarwinDIPInfo, + SrdarwinInit, DrvExit, SrdarwinFrame, SrdarwinDraw, NULL, &DrvRecalc, 0x100, + 240, 256, 3, 4 +}; + + +// Super Real Darwin (Japan) + +static struct BurnRomInfo srdarwnjRomDesc[] = { + { "dy_01.rom", 0x10000, 0x1eeee4ff, 1 }, // 0 maincpu + { "dy00.b16", 0x10000, 0x2bf6b461, 1 }, // 1 + + { "dy04.d7", 0x08000, 0x2ae3591c, 2 }, // 2 audiocpu + + { "dy05.b6", 0x04000, 0x8780e8a3, 3 }, // 3 gfx1 + + { "dy07.h16", 0x08000, 0x97eaba60, 4 }, // 4 gfx2 + { "dy06.h14", 0x08000, 0xc279541b, 4 }, // 5 + { "dy09.k13", 0x08000, 0xd30d1745, 4 }, // 6 + { "dy08.k11", 0x08000, 0x71d645fd, 4 }, // 7 + { "dy11.k16", 0x08000, 0xfd9ccc5b, 4 }, // 8 + { "dy10.k14", 0x08000, 0x88770ab8, 4 }, // 9 + + { "dy03.b4", 0x10000, 0x44f2a4f9, 5 }, // 10 gfx3 + { "dy02.b5", 0x10000, 0x522d9a9e, 5 }, // 11 + + { "id8751h.mcu", 0x01000, 0x00000000, 6 | BRF_NODUMP }, // 12 mcu + + { "dy12.f4", 0x00100, 0xebfaaed9, 7 }, // 13 proms +}; + +STD_ROM_PICK(srdarwnj) +STD_ROM_FN(srdarwnj) + +struct BurnDriver BurnDrvSrdarwnj = { + "srdarwinj", "srdarwin", NULL, NULL, "1987", + "Super Real Darwin (Japan)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, srdarwnjRomInfo, srdarwnjRomName, NULL, NULL, SrdarwinInputInfo, SrdarwinDIPInfo, + SrdarwinInit, DrvExit, SrdarwinFrame, SrdarwinDraw, NULL, &DrvRecalc, 0x100, + 240, 256, 3, 4 +}; + + + + + +static void gondo_i8751_write(INT32 offset, UINT8 data) +{ + static INT32 coin1, coin2, latch,snd; + i8751_return = 0; + + UINT8 coin = ~DrvInputs[4] ^ 3; + + switch (offset) + { + case 0: + i8751_value = (i8751_value & 0xff) | (data << 8); + if (*interrupt_enable) HD6309SetIRQ(0, HD6309_IRQSTATUS_AUTO); + break; + + case 1: + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + /* Coins are controlled by the i8751 */ + if ((coin & 3) == 3) latch = 1; + if ((coin & 1) != 1 && latch) {coin1++; snd = 1; latch = 0; } + if ((coin & 2) != 2 && latch) {coin2++; snd = 1; latch = 0; } + + if (i8751_value == 0x0000) {i8751_return = 0x000; coin1 = coin2 = snd = 0;} + if (i8751_value == 0x038a) i8751_return = 0x375; /* Makyou Senshi ID */ + if (i8751_value == 0x038b) i8751_return = 0x374; /* Gondomania ID */ + if ((i8751_value >> 8) == 0x04) i8751_return = 0x40f; /* Coinage settings (Not supported) */ + if ((i8751_value >> 8) == 0x05) {i8751_return = 0x500 | ((coin1 / 10) << 4) | (coin1 % 10); } /* Coin 1 */ + if ((i8751_value >> 8) == 0x06 && coin1 && !offset) {i8751_return = 0x600; coin1--; } /* Coin 1 clear */ + if ((i8751_value >> 8) == 0x07) {i8751_return = 0x700 | ((coin2 / 10) << 4) | (coin2 % 10); } /* Coin 2 */ + if ((i8751_value >> 8) == 0x08 && coin2 && !offset) {i8751_return = 0x800; coin2--; } /* Coin 2 clear */ + + if ((i8751_value >> 8) == 0x0a) {i8751_return = 0xa00 | snd; if (snd) snd = 0; } +} + +static void garyoret_i8751_write(INT32 offset, UINT8 data) +{ + static INT32 coin1, coin2, latch; + i8751_return = 0; + + UINT8 coin = ~DrvInputs[4] ^ 3; + + switch (offset) + { + case 0: /* High byte */ + i8751_value = (i8751_value & 0xff) | (data << 8); + break; + + case 1: /* Low byte */ + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + /* Coins are controlled by the i8751 */ + if ((coin & 3) == 3) latch=1; + if ((coin & 1) != 1 && latch) {coin1++; latch = 0;} + if ((coin & 2) != 2 && latch) {coin2++; latch = 0;} + + /* Work out return values */ + if ((i8751_value >> 8) == 0x00) {i8751_return = 0; coin1 = coin2 = 0;} + if ((i8751_value >> 8) == 0x01) i8751_return = 0x59a; /* ID */ + if ((i8751_value >> 8) == 0x04) i8751_return = i8751_value; /* Coinage settings (Not supported) */ + if ((i8751_value >> 8) == 0x05) {i8751_return = 0x00 | ((coin1 / 10) << 4) | (coin1 % 10); } /* Coin 1 */ + if ((i8751_value >> 8) == 0x06 && coin1 && !offset) {i8751_return = 0x600; coin1--; } /* Coin 1 clear */ +} + +void gondo_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3810: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + case 0x3818: + DrvPf0Ctrl[0x11] = data; + return; + + case 0x3820: + DrvPf0Ctrl[0x13] = data; + return; + + case 0x3828: + DrvPf0Ctrl[0x10] = (data >> 0) & 1; + DrvPf0Ctrl[0x12] = (data >> 1) & 1; + return; + + case 0x3830: + bankswitch(data >> 4); + + *interrupt_enable = data & 1; + *nmi_enable = data & 2; + *flipscreen = data & 8; + return; + + case 0x3838: + case 0x3839: + garyoret_i8751_write(address & 1, data); + return; + + case 0x383a: + case 0x383b: + gondo_i8751_write(address & 1, data); + return; + } +} + +UINT8 gondo_main_read(UINT16 address) +{ + switch (address) + { + case 0x3800: + return DrvDips[0]; + + case 0x3801: + return DrvDips[1]; + + case 0x380a: return 0xff; + case 0x380b: return 0x7f; +// return 0xff; // gondo_player_1_r + + case 0x380c: return 0xff; + case 0x380d: return 0x7f; +// return 0xff; // gondo_player_2_r + + case 0x380e: + return (DrvInputs[3] & 0x7f) | vblank; + + case 0x380f: + return DrvInputs[2]; + + case 0x3838: + bprintf(PRINT_NORMAL, _T("3838\n")); // doesn't read these - so coins don't work + return i8751_return >> 8; + + case 0x3839: + bprintf(PRINT_NORMAL, _T("3839\n")); // doesn't read these - so coins don't work + return i8751_return & 0xff; + } + + return 0; +} + +UINT8 garyoret_main_read(UINT16 address) +{ + switch (address) + { + case 0x3800: + return DrvDips[0]; + + case 0x3801: + return DrvDips[1]; + + case 0x380a: + return (DrvInputs[1] & 0x7f) | vblank; + + case 0x380b: + return DrvInputs[0]; + + case 0x383a: + return i8751_return >> 8; + + case 0x383b: + return i8751_return & 0xff; + } + + return 0; +} + +void gondo_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0800: + case 0x0801: + case 0x2000: + case 0x2001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0x1000: + case 0x1001: + case 0x4000: + case 0x4001: + BurnYM3526Write(address & 1, data); + return; + } +} + +static INT32 GondoDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + HD6309Open(0); + HD6309Reset(); + HD6309Close(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM2203Reset(); + BurnYM3526Reset(); + + i8751_return = 0; + i8751_value = 0; + + return 0; +} + + + +static INT32 GondoGfxDecode() +{ + INT32 Plane0[3] = { 0x6000*8,0x4000*8,0x2000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x40000*8,0x20000*8,0x00000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs1[16]= {16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 YOffs0[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 3, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 GondoInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "garyoret")) { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x30000, 3, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x40000, 4, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x50000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x70000, 14, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 15, 1)) return 1; + memcpy (DrvGfxROM2 + 0x00000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x10000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 16, 1)) return 1; + memcpy (DrvGfxROM2 + 0x08000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x18000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 17, 1)) return 1; + memcpy (DrvGfxROM2 + 0x20000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x30000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 18, 1)) return 1; + memcpy (DrvGfxROM2 + 0x28000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x38000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 19, 1)) return 1; + memcpy (DrvGfxROM2 + 0x40000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x50000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 20, 1)) return 1; + memcpy (DrvGfxROM2 + 0x48000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x58000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 21, 1)) return 1; + memcpy (DrvGfxROM2 + 0x60000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x70000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 22, 1)) return 1; + memcpy (DrvGfxROM2 + 0x68000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x78000, DrvGfxROM3 + 0x08000, 0x08000); + } else { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x30000, 3, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x50000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x70000, 13, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 14, 1)) return 1; + memcpy (DrvGfxROM2 + 0x00000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x10000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 16, 1)) return 1; + memcpy (DrvGfxROM2 + 0x20000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x30000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM2 + 0x28000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 18, 1)) return 1; + memcpy (DrvGfxROM2 + 0x40000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x50000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM2 + 0x48000, 19, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 20, 1)) return 1; + memcpy (DrvGfxROM2 + 0x60000, DrvGfxROM3 + 0x00000, 0x08000); + memcpy (DrvGfxROM2 + 0x70000, DrvGfxROM3 + 0x08000, 0x08000); + if (BurnLoadRom(DrvGfxROM2 + 0x68000, 21, 1)) return 1; + } + + GondoGfxDecode(); + } + + HD6309Init(1); + HD6309Open(0); + HD6309MapMemory(DrvMainRAM, 0x0000, 0x17ff, HD6309_RAM); + HD6309MapMemory(DrvVidRAM, 0x1800, 0x1fff, HD6309_RAM); + HD6309MapMemory(DrvPf0RAM, 0x2000, 0x27ff, HD6309_RAM); + HD6309MapMemory(DrvPalRAM, 0x2800, 0x2fff, HD6309_RAM);//xxxxBBBBGGGGRRRR_split + HD6309MapMemory(DrvSprRAM, 0x3000, 0x37ff, HD6309_RAM); + HD6309MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, HD6309_ROM); // bank + HD6309MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, HD6309_ROM); + HD6309SetWriteByteHandler(gondo_main_write); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "garyoret")) { + HD6309SetReadByteHandler(garyoret_main_read); + } else { + HD6309SetReadByteHandler(gondo_main_read); + } + HD6309Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(gondo_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM3526Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 0); + BurnTimerAttachM6502YM3526(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203SynchroniseStream, DrvYM2203GetTime, 1); + BurnTimerAttachHD6309(1200000); + + GenericTilesInit(); + + GondoDoReset(); + + return 0; +} + +static INT32 GondoExit() +{ + GenericTilesExit(); + HD6309Exit(); + M6502Exit(); + + BurnYM3526Exit(); + BurnYM2203Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void gondo_draw_txt_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= 8; + if (sy < 0 || sy >= nScreenWidth) continue; + + INT32 code = DrvVidRAM[offs * 2 + 1] | (DrvVidRAM[offs * 2 + 0] << 8); + INT32 color = (code >> 12) & 7; + + Render8x8Tile_Mask_Clip(pTransDraw, code & 0xfff, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } +} + +static void gondo_draw_layer(INT32 priority, INT32 layer) +{ + INT32 scrolly = ((DrvPf0Ctrl[0x12] << 8) + DrvPf0Ctrl[0x13] + 8) & 0x1ff; + INT32 scrollx = ((DrvPf0Ctrl[0x10] << 8) | DrvPf0Ctrl[0x11]); + + UINT16 trans = layer ? 0x00ff : 0xff00; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx+=512; + sy -= scrolly; + if (sy < -15) sy+=512; + + if (sx >= nScreenWidth || sy >= nScreenWidth) continue; + + INT32 code = DrvPf0RAM[offs * 2 + 1] | (DrvPf0RAM[offs * 2 + 0] << 8); + INT32 color = code >> 12; + + if (priority && color < 8) continue; + + { + code &= 0xfff; + color <<= 4; + color |= 0x300; + + UINT8 *src = DrvGfxROM2 + (code << 8); + UINT16 *dst; + + for (INT32 y = 0; y < 16; y++, src+=16, sy++) + { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + INT32 xx = sx; + for (INT32 x = 0; x < 16; x++, xx++) + { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = src[x]; + + if (trans & (1 << pxl)) continue; + + dst[xx] = pxl | color; + } + } + } + } +} + +static void GondoPaletteRecalc() +{ + UINT8 r,g,b; + for (INT32 i = 0; i < 0x400; i++) { + INT32 d = (DrvPalRAM[i + 0]) | (DrvPalRAM[i + 0x400] << 8); + r = (d >> 0) & 0x0f; + g = (d >> 4) & 0x0f; + b = (d >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 GondoDraw() +{ + if (DrvRecalc) { + GondoPaletteRecalc(); + } + + gondo_draw_layer(0, 1); + draw_sprites1(2); + gondo_draw_layer(0, 0); + draw_sprites1(1); + gondo_draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 GaryoretDraw() +{ + if (DrvRecalc) { + GondoPaletteRecalc(); + } + + gondo_draw_layer(0, 1); + gondo_draw_layer(0, 0); + draw_sprites1(0); + gondo_draw_layer(1, 1); + gondo_draw_layer(1, 0); + + gondo_draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 GondoFrame() +{ + if (DrvReset) { + GondoDoReset(); + } + + HD6309NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = 32; + INT32 nCyclesTotal[2] = { 12000000 / 58, 1500000 / 58 }; +// INT32 nCyclesDone[2] = { 0, 0 }; + + M6502Open(0); + HD6309Open(0); + + vblank = 0x80; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 1) vblank = 0; + if (i == 31) { + vblank = 0x80; + if (*nmi_enable) HD6309SetIRQ(0x20, HD6309_IRQSTATUS_AUTO); + } + + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + BurnTimerUpdateYM3526(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3526(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + HD6309Close(); + M6502Close(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + + return 0; +} + + +// Gondomania (US) + +static struct BurnRomInfo gondoRomDesc[] = { + { "dt-00.256", 0x08000, 0xa8cf9118, 1 }, // 0 maincpu + { "dt-01.512", 0x10000, 0xc39bb877, 1 }, // 1 + { "dt-02.512", 0x10000, 0xbb5e674b, 1 }, // 2 + { "dt-03.512", 0x10000, 0x99c32b13, 1 }, // 3 + + { "dt-05.256", 0x08000, 0xec08aa29, 2 }, // 4 audiocpu + + { "dt-14.256", 0x08000, 0x4bef16e1, 3 }, // 5 gfx1 + + { "dt-19.512", 0x10000, 0xda2abe4b, 4 }, // 6 gfx2 + { "dt-20.256", 0x08000, 0x42d01002, 4 }, // 7 + { "dt-16.512", 0x10000, 0xe9955d8f, 4 }, // 8 + { "dt-18.256", 0x08000, 0xc0c5df1c, 4 }, // 9 + { "dt-15.512", 0x10000, 0xa54b2eb6, 4 }, // 10 + { "dt-17.256", 0x08000, 0x3bbcff0d, 4 }, // 11 + { "dt-21.512", 0x10000, 0x1c5f682d, 4 }, // 12 + { "dt-22.256", 0x08000, 0xc1876a5f, 4 }, // 13 + + { "dt-08.512", 0x10000, 0xaec483f5, 5 }, // 14 gfx3 + { "dt-09.256", 0x08000, 0x446f0ce0, 5 }, // 15 + { "dt-06.512", 0x10000, 0x3fe1527f, 5 }, // 16 + { "dt-07.256", 0x08000, 0x61f9bce5, 5 }, // 17 + { "dt-12.512", 0x10000, 0x1a72ca8d, 5 }, // 18 + { "dt-13.256", 0x08000, 0xccb81aec, 5 }, // 19 + { "dt-10.512", 0x10000, 0xcfcfc9ed, 5 }, // 20 + { "dt-11.256", 0x08000, 0x53e9cf17, 5 }, // 21 + + { "dt-a.1b", 0x01000, 0x03abceeb, 6 }, // 22 mcu + + { "mb7122e.10b", 0x00400, 0xdcbfec4e, 7 }, // 23 proms +}; + +STD_ROM_PICK(gondo) +STD_ROM_FN(gondo) + +struct BurnDriverD BurnDrvGondo = { + "gondo", NULL, NULL, NULL, "1987", + "Gondomania (US)\0", "Broken inputs", "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, gondoRomInfo, gondoRomName, NULL, NULL, GondoInputInfo, GondoDIPInfo, + GondoInit, GondoExit, GondoFrame, GondoDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Makyou Senshi (Japan) + +static struct BurnRomInfo makyosenRomDesc[] = { + { "ds00", 0x08000, 0x33bb16fe, 1 }, // 0 maincpu + { "dt-01.512", 0x10000, 0xc39bb877, 1 }, // 1 + { "ds02", 0x10000, 0x925307a4, 1 }, // 2 + { "ds03", 0x10000, 0x9c0fcbf6, 1 }, // 3 + + { "ds05", 0x08000, 0xe6e28ca9, 2 }, // 4 audiocpu + + { "ds14", 0x08000, 0x00cbe9c8, 3 }, // 5 gfx1 + + { "dt-19.512", 0x10000, 0xda2abe4b, 4 }, // 6 gfx2 + { "ds20", 0x08000, 0x0eef7f56, 4 }, // 7 + { "dt-16.512", 0x10000, 0xe9955d8f, 4 }, // 8 + { "ds18", 0x08000, 0x2b2d1468, 4 }, // 9 + { "dt-15.512", 0x10000, 0xa54b2eb6, 4 }, // 10 + { "ds17", 0x08000, 0x75ae349a, 4 }, // 11 + { "dt-21.512", 0x10000, 0x1c5f682d, 4 }, // 12 + { "ds22", 0x08000, 0xc8ffb148, 4 }, // 13 + + { "dt-08.512", 0x10000, 0xaec483f5, 5 }, // 14 gfx3 + { "dt-09.256", 0x08000, 0x446f0ce0, 5 }, // 15 + { "dt-06.512", 0x10000, 0x3fe1527f, 5 }, // 16 + { "dt-07.256", 0x08000, 0x61f9bce5, 5 }, // 17 + { "dt-12.512", 0x10000, 0x1a72ca8d, 5 }, // 18 + { "dt-13.256", 0x08000, 0xccb81aec, 5 }, // 19 + { "dt-10.512", 0x10000, 0xcfcfc9ed, 5 }, // 20 + { "dt-11.256", 0x08000, 0x53e9cf17, 5 }, // 21 + + { "ds-a.1b", 0x01000, 0x8bb25edc, 6 }, // 22 mcu + + { "mb7122e.10b", 0x00400, 0xdcbfec4e, 7 }, // 23 proms + + { "pal16r4nc.10u", 0x00104, 0x00000000, 8 | BRF_NODUMP }, // 24 plds + { "pal16r4nc.11g", 0x00104, 0x00000000, 8 | BRF_NODUMP }, // 25 + { "pal16r4nc.1s", 0x00104, 0x00000000, 8 | BRF_NODUMP }, // 26 +}; + +STD_ROM_PICK(makyosen) +STD_ROM_FN(makyosen) + +struct BurnDriverD BurnDrvMakyosen = { + "makyosen", "gondo", NULL, NULL, "1987", + "Makyou Senshi (Japan)\0", "Broken inputs", "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, makyosenRomInfo, makyosenRomName, NULL, NULL, GondoInputInfo, GondoDIPInfo, + GondoInit, GondoExit, GondoFrame, GondoDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + + +// Garyo Retsuden (Japan) + +static struct BurnRomInfo garyoretRomDesc[] = { + { "dv00", 0x08000, 0xcceaaf05, 1 }, // 0 maincpu + { "dv01", 0x10000, 0xc33fc18a, 1 }, // 1 + { "dv02", 0x10000, 0xf9e26ce7, 1 }, // 2 + { "dv03", 0x10000, 0x55d8d699, 1 }, // 3 + { "dv04", 0x10000, 0xed3d00ee, 1 }, // 4 + + { "dv05", 0x08000, 0xc97c347f, 2 }, // 5 audiocpu + + { "dv14", 0x08000, 0xfb2bc581, 3 }, // 6 gfx1 + + { "dv22", 0x10000, 0xcef0367e, 4 }, // 7 gfx2 + { "dv21", 0x08000, 0x90042fb7, 4 }, // 8 + { "dv20", 0x10000, 0x451a2d8c, 4 }, // 9 + { "dv19", 0x08000, 0x14e1475b, 4 }, // 10 + { "dv18", 0x10000, 0x7043bead, 4 }, // 11 + { "dv17", 0x08000, 0x28f449d7, 4 }, // 12 + { "dv16", 0x10000, 0x37e4971e, 4 }, // 13 + { "dv15", 0x08000, 0xca41b6ac, 4 }, // 14 + + { "dv08", 0x10000, 0x89c13e15, 5 }, // 15 gfx3 + { "dv09", 0x10000, 0x6a345a23, 5 }, // 16 + { "dv06", 0x10000, 0x1eb52a20, 5 }, // 17 + { "dv07", 0x10000, 0xe7346ef8, 5 }, // 18 + { "dv12", 0x10000, 0x46ba5af4, 5 }, // 19 + { "dv13", 0x10000, 0xa7af6dfd, 5 }, // 20 + { "dv10", 0x10000, 0x68b6d75c, 5 }, // 21 + { "dv11", 0x10000, 0xb5948aee, 5 }, // 22 + + { "id8751h.mcu", 0x01000, 0x00000000, 6 | BRF_NODUMP }, // 23 mcu +}; + +STD_ROM_PICK(garyoret) +STD_ROM_FN(garyoret) + +struct BurnDriver BurnDrvGaryoret = { + "garyoret", NULL, NULL, NULL, "1987", + "Garyo Retsuden (Japan)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, garyoretRomInfo, garyoretRomName, NULL, NULL, GaryoretInputInfo, GaryoretDIPInfo, + GondoInit, GondoExit, GondoFrame, GaryoretDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + + + + + + +UINT8 oscar_main_read(UINT16 address) +{ + switch (address) + { + case 0x3c00: // in0 + return DrvInputs[0]; + + case 0x3c01: + return DrvInputs[1]; + + case 0x3c02: + return (DrvInputs[2] & 0x7f) | vblank; + + case 0x3c03: + return DrvDips[0]; + + case 0x3c04: + return DrvDips[1]; + } + + return 0; +} + +void oscar_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3c80: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x3d00: + bankswitch(data); + return; + + case 0x3d80: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + case 0x3e80: + HD6309Close(); + HD6309Open(1); + HD6309SetIRQ(0, HD6309_IRQSTATUS_ACK); + HD6309Close(); + HD6309Open(0); + return; + + case 0x3e81: + HD6309SetIRQ(0, HD6309_IRQSTATUS_NONE); + return; + + case 0x3e82: + HD6309SetIRQ(0, HD6309_IRQSTATUS_ACK); + return; + + case 0x3e83: + HD6309Close(); + HD6309Open(1); + HD6309SetIRQ(0, HD6309_IRQSTATUS_NONE); + HD6309Close(); + HD6309Open(0); + return; + } + + if ((address & 0xffe0) == 0x3c00) { + DrvPf0Ctrl[address & 0x1f] = data; + return; + } +} + + +void oscar_sub_write(UINT16 address, UINT8 ) +{ + switch (address) + { + case 0x3e80: + HD6309SetIRQ(0, HD6309_IRQSTATUS_ACK); + HD6309Close(); + HD6309Open(0); + return; + + case 0x3e81: + HD6309Close(); + HD6309Open(0); + HD6309SetIRQ(0, HD6309_IRQSTATUS_NONE); + HD6309Close(); + HD6309Open(1); + return; + + case 0x3e82: + HD6309Close(); + HD6309Open(0); + HD6309SetIRQ(0, HD6309_IRQSTATUS_ACK); + HD6309Close(); + HD6309Open(1); + return; + + case 0x3e83: + HD6309SetIRQ(0, HD6309_IRQSTATUS_NONE); + return; + } +} + +static INT32 OscarDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + HD6309Open(0); + HD6309Reset(); + HD6309Close(); + + HD6309Open(1); + HD6309Reset(); + HD6309Close(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM2203Reset(); + BurnYM3526Reset(); + + i8751_return = 0; + i8751_value = 0; + + return 0; +} + +static INT32 OscarGfxDecode() +{ + INT32 Plane0[3] = { 0x3000*8,0x2000*8,0x1000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x40000*8,0x20000*8,0x00000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs1[16]= {16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 YOffs0[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 3, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 OscarInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + + if (BurnLoadRom(DrvSubROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 12, 1)) return 1; + + Deco222Decode(); + OscarGfxDecode(); + } + + HD6309Init(2); + HD6309Open(0); + HD6309MapMemory(DrvMainRAM, 0x0000, 0x1fff, HD6309_RAM); // all shared? + HD6309MapMemory(DrvVidRAM, 0x2000, 0x28ff, HD6309_RAM); + HD6309MapMemory(DrvPf0RAM, 0x2800, 0x2fff, HD6309_RAM); + HD6309MapMemory(DrvSprRAM, 0x3000, 0x37ff, HD6309_RAM); + HD6309MapMemory(DrvPalRAM, 0x3800, 0x3bff, HD6309_RAM); // xxxxBBBBGGGGRRRR_be_w + HD6309MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, HD6309_ROM); // bank + HD6309MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, HD6309_ROM); + HD6309SetWriteByteHandler(oscar_main_write); + HD6309SetReadByteHandler(oscar_main_read); + HD6309Close(); + + HD6309Open(1); + HD6309MapMemory(DrvMainRAM, 0x0000, 0x0eff, HD6309_RAM); // all shared? AM_RANGE(0x0f00, 0x0fff) AM_RAM not? + HD6309MapMemory(DrvPalRAM + 0x400, 0x0f00, 0x0fff, HD6309_RAM); // not really pal... + HD6309MapMemory(DrvMainRAM + 0x1000, 0x1000, 0x1fff, HD6309_RAM); // all shared? AM_RANGE(0x0f00, 0x0fff) AM_RAM not? + HD6309MapMemory(DrvSubROM + 0x04000, 0x4000, 0xffff, HD6309_ROM); + HD6309SetWriteByteHandler(oscar_sub_write); // 0x3e80, 0x3e83 used... + HD6309Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_READ); + M6502MapMemory(DrvM6502OPS + 0x8000, 0x8000, 0xffff, M6502_FETCH); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(gondo_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM3526Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 0); + BurnTimerAttachM6502YM3526(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203SynchroniseStream6000000, DrvYM2203GetTime6000000, 1); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachHD6309(6000000); + + GenericTilesInit(); + + OscarDoReset(); + + return 0; +} + +static void oscar_draw_txt_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= 8; + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 code = (DrvVidRAM[offs * 2 + 1]) | (DrvVidRAM[offs * 2 + 0] << 8); + INT32 color = code >> 14; + + Render8x8Tile_Mask(pTransDraw, code & 0x3ff, sx, sy, color, 3, 0, 0x100, DrvGfxROM0); + } +} + +static INT32 OscarDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x400; i+=2) { + INT32 d = (DrvPalRAM[i + 0] << 8) | DrvPalRAM[i + 1]; + r = (d >> 0) & 0x0f; + g = (d >> 4) & 0x0f; + b = (d >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i/2] = BurnHighCol(r, g, b, 0); + } + } + + draw_bg_layer(DrvPf0RAM, DrvPf0Ctrl, DrvGfxROM2, 0x180, 0x07, 0x7ff, 0x0000, 0); + draw_sprites2(0xf, 0); + draw_bg_layer(DrvPf0RAM, DrvPf0Ctrl, DrvGfxROM2, 0x180, 0x07, 0x7ff, 0x00ff, 0); + oscar_draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 OscarFrame() +{ + if (DrvReset) { + OscarDoReset(); + } + + HD6309NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[3] = { 6000000 / 58, 6000000 / 58, 1500000 / 58 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + M6502Open(0); + + vblank = 0x80; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 8) vblank = 0; + + HD6309Open(0); + INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1); + nCyclesDone[0] += HD6309Run(nSegment - nCyclesDone[0]); + + if (i == 247) { + static INT32 latch = 1; + if ((DrvInputs[2] & 7) == 7) latch = 1; + if ((DrvInputs[2] & 7) != 7 && latch) { + latch = 0; + HD6309SetIRQ(0x20, HD6309_IRQSTATUS_AUTO); + } + vblank = 0x80; + } + + HD6309Close(); + + HD6309Open(1); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + HD6309Close(); + BurnTimerUpdateYM3526(i * (nCyclesTotal[2] / nInterleave)); + } + + HD6309Open(1); + + BurnTimerEndFrame(nCyclesTotal[1]); + BurnTimerEndFrameYM3526(nCyclesTotal[2]); + + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + M6502Close(); + HD6309Close(); + + if (pBurnDraw) { + OscarDraw(); + } + + return 0; +} + + +// Psycho-Nics Oscar (World revision 0) + +static struct BurnRomInfo oscarRomDesc[] = { + { "du10", 0x08000, 0x120040d8, 1 }, // 0 maincpu + { "ed09", 0x10000, 0xe2d4bba9, 1 }, // 1 + + { "du11", 0x10000, 0xff45c440, 2 }, // 2 sub + + { "ed12", 0x08000, 0x432031c5, 3 }, // 3 audiocpu + + { "ed08", 0x04000, 0x308ac264, 4 }, // 4 gfx1 + + { "ed04", 0x10000, 0x416a791b, 5 }, // 5 gfx2 + { "ed05", 0x10000, 0xfcdba431, 5 }, // 6 + { "ed06", 0x10000, 0x7d50bebc, 5 }, // 7 + { "ed07", 0x10000, 0x8fdf0fa5, 5 }, // 8 + + { "ed01", 0x10000, 0xd3a58e9e, 6 }, // 9 gfx3 + { "ed03", 0x10000, 0x4fc4fb0f, 6 }, // 10 + { "ed00", 0x10000, 0xac201f2d, 6 }, // 11 + { "ed02", 0x10000, 0x7ddc5651, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu +}; + +STD_ROM_PICK(oscar) +STD_ROM_FN(oscar) + +struct BurnDriver BurnDrvOscar = { + "oscar", NULL, NULL, NULL, "1988", + "Psycho-Nics Oscar (World revision 0)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, oscarRomInfo, oscarRomName, NULL, NULL, OscarInputInfo, OscarDIPInfo, + OscarInit, GondoExit, OscarFrame, OscarDraw, NULL, &DrvRecalc, 0x200, + 256, 240, 4, 3 +}; + + +// Psycho-Nics Oscar (US) + +static struct BurnRomInfo oscaruRomDesc[] = { + { "ed10", 0x08000, 0xf9b0d4d4, 1 }, // 0 maincpu + { "ed09", 0x10000, 0xe2d4bba9, 1 }, // 1 + + { "ed11", 0x10000, 0x10e5d919, 2 }, // 2 sub + + { "ed12", 0x08000, 0x432031c5, 3 }, // 3 audiocpu + + { "ed08", 0x04000, 0x308ac264, 4 }, // 4 gfx1 + + { "ed04", 0x10000, 0x416a791b, 5 }, // 5 gfx2 + { "ed05", 0x10000, 0xfcdba431, 5 }, // 6 + { "ed06", 0x10000, 0x7d50bebc, 5 }, // 7 + { "ed07", 0x10000, 0x8fdf0fa5, 5 }, // 8 + + { "ed01", 0x10000, 0xd3a58e9e, 6 }, // 9 gfx3 + { "ed03", 0x10000, 0x4fc4fb0f, 6 }, // 10 + { "ed00", 0x10000, 0xac201f2d, 6 }, // 11 + { "ed02", 0x10000, 0x7ddc5651, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "du-13.bin", 0x00200, 0xbea1f87e, 8 }, // 14 proms +}; + +STD_ROM_PICK(oscaru) +STD_ROM_FN(oscaru) + +struct BurnDriver BurnDrvOscaru = { + "oscaru", "oscar", NULL, NULL, "1987", + "Psycho-Nics Oscar (US)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, oscaruRomInfo, oscaruRomName, NULL, NULL, OscarInputInfo, OscaruDIPInfo, + OscarInit, GondoExit, OscarFrame, OscarDraw, NULL, &DrvRecalc, 0x200, + 256, 240, 4, 3 +}; + + +// Psycho-Nics Oscar (Japan revision 1) + +static struct BurnRomInfo oscarj1RomDesc[] = { + { "du10-1", 0x08000, 0x4ebc9f7a, 1 }, // 0 maincpu + { "ed09", 0x10000, 0xe2d4bba9, 1 }, // 1 + + { "du11", 0x10000, 0xff45c440, 2 }, // 2 sub + + { "ed12", 0x08000, 0x432031c5, 3 }, // 3 audiocpu + + { "ed08", 0x04000, 0x308ac264, 4 }, // 4 gfx1 + + { "ed04", 0x10000, 0x416a791b, 5 }, // 5 gfx2 + { "ed05", 0x10000, 0xfcdba431, 5 }, // 6 + { "ed06", 0x10000, 0x7d50bebc, 5 }, // 7 + { "ed07", 0x10000, 0x8fdf0fa5, 5 }, // 8 + + { "ed01", 0x10000, 0xd3a58e9e, 6 }, // 9 gfx3 + { "ed03", 0x10000, 0x4fc4fb0f, 6 }, // 10 + { "ed00", 0x10000, 0xac201f2d, 6 }, // 11 + { "ed02", 0x10000, 0x7ddc5651, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "du-13.bin", 0x00200, 0xbea1f87e, 8 }, // 14 proms +}; + +STD_ROM_PICK(oscarj1) +STD_ROM_FN(oscarj1) + +struct BurnDriver BurnDrvOscarj1 = { + "oscarj1", "oscar", NULL, NULL, "1987", + "Psycho-Nics Oscar (Japan revision 1)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, oscarj1RomInfo, oscarj1RomName, NULL, NULL, OscarInputInfo, OscaruDIPInfo, + OscarInit, GondoExit, OscarFrame, OscarDraw, NULL, &DrvRecalc, 0x200, + 256, 240, 4, 3 +}; + + +// Psycho-Nics Oscar (Japan revision 2) + +static struct BurnRomInfo oscarj2RomDesc[] = { + { "du10-2", 0x08000, 0x114e898d, 1 }, // 0 maincpu + { "ed09", 0x10000, 0xe2d4bba9, 1 }, // 1 + + { "du11", 0x10000, 0xff45c440, 2 }, // 2 sub + + { "ed12", 0x08000, 0x432031c5, 3 }, // 3 audiocpu + + { "ed08", 0x04000, 0x308ac264, 4 }, // 4 gfx1 + + { "ed04", 0x10000, 0x416a791b, 5 }, // 5 gfx2 + { "ed05", 0x10000, 0xfcdba431, 5 }, // 6 + { "ed06", 0x10000, 0x7d50bebc, 5 }, // 7 + { "ed07", 0x10000, 0x8fdf0fa5, 5 }, // 8 + + { "ed01", 0x10000, 0xd3a58e9e, 6 }, // 9 gfx3 + { "ed03", 0x10000, 0x4fc4fb0f, 6 }, // 10 + { "ed00", 0x10000, 0xac201f2d, 6 }, // 11 + { "ed02", 0x10000, 0x7ddc5651, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "du-13.bin", 0x00200, 0xbea1f87e, 8 }, // 14 proms +}; + +STD_ROM_PICK(oscarj2) +STD_ROM_FN(oscarj2) + +struct BurnDriver BurnDrvOscarj2 = { + "oscarj2", "oscar", NULL, NULL, "1987", + "Psycho-Nics Oscar (Japan revision 2)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, oscarj2RomInfo, oscarj2RomName, NULL, NULL, OscarInputInfo, OscaruDIPInfo, + OscarInit, GondoExit, OscarFrame, OscarDraw, NULL, &DrvRecalc, 0x200, + 256, 240, 4, 3 +}; + + + + + + +static void lastmiss_i8751_write(INT32 offset, INT32 data) +{ + static INT32 coin, latch = 0, snd; + i8751_return = 0; + + INT32 coininp = DrvInputs[2] & 3; //(~DrvInputs[2]) & 3; + + switch (offset) + { + case 0: + i8751_value = (i8751_value & 0xff) | (data << 8); + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); /* Signal main cpu */ + break; + + case 1: + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + if (offset == 0) + { + if (coininp == 3 && !latch) latch = 1; + if (coininp != 3 && latch) {coin++; latch = 0; snd = 0x400; i8751_return = 0x400; return;} + if (i8751_value == 0x007a) i8751_return = 0x0185; /* Japan ID code */ + if (i8751_value == 0x007b) i8751_return = 0x0184; /* USA ID code */ + if (i8751_value == 0x0001) {coin = snd = 0;}//??? + if (i8751_value == 0x0000) {i8751_return = 0x0184;}//??? + if (i8751_value == 0x0401) i8751_return = 0x0184; //??? + if ((i8751_value >> 8) == 0x01) i8751_return = 0x0184; /* Coinage setup */ + if ((i8751_value >> 8) == 0x02) {i8751_return = snd | ((coin / 10) << 4) | (coin % 10); snd = 0;} /* Coin return */ + if ((i8751_value >> 8) == 0x03 && coin) {i8751_return = 0; coin--; } /* Coin clear */ + } +} + +static void shackled_i8751_write(INT32 offset, INT32 data) +{ + static INT32 coin1, coin2, latch = 0; + i8751_return = 0; + + INT32 coininp = DrvInputs[2] & 3; + + switch (offset) + { + case 0: /* High byte */ + i8751_value = (i8751_value & 0xff) | (data << 8); + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); /* Signal main cpu */ + break; + case 1: /* Low byte */ + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + /* Coins are controlled by the i8751 */ + if (!latch) {latch = 1; coin1 = coin2 = 0;} + if ((coininp & 1) != 1 && latch) {coin1 = 1; latch = 0;} + if ((coininp & 2) != 2 && latch) {coin2 = 1; latch = 0;} + + if (i8751_value == 0x0050) i8751_return = 0; /* Breywood ID */ + if (i8751_value == 0x0051) i8751_return = 0; /* Shackled ID */ + if (i8751_value == 0x0102) i8751_return = 0; /* ?? */ + if (i8751_value == 0x0101) i8751_return = 0; /* ?? */ + if (i8751_value == 0x8101) i8751_return = ((coin2 / 10) << 4) | (coin2 % 10) | + ((((coin1 / 10) << 4) | (coin1 % 10)) << 8); /* Coins */ +} + + +static INT32 stopsubcpu = 0; +static INT32 nLastMiss = 0; + +void lastmiss_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1803: + if (M6809GetActive() == 0) { // main + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } else { + M6809Close(); + M6809Open(0); + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + M6809Close(); + M6809Open(1); + } + return; + + case 0x1804: + if (M6809GetActive() == 0) { // main + M6809Close(); + M6809Open(1); + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + M6809Close(); + M6809Open(0); + } else { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + return; + + case 0x1805: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x1807: + *flipscreen = data; + return; + + case 0x180c: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + // main cpu only! + + case 0x1809: + DrvPf0Ctrl[0x11] = data; + return; + + case 0x180b: + DrvPf0Ctrl[0x13] = data; + return; + + case 0x180d: + if (M6809GetActive() == 0) { + m6809_bankswitch(data & 0x0f); + + if (~data & 0x80 && nLastMiss) { + M6809Close(); + M6809Open(1); + M6809Reset(); + M6809Close(); + M6809Open(0); + stopsubcpu = 1; + } else { + stopsubcpu = 0; + } + } else { + if (nLastMiss == 0) { + // M6809Close(); + // M6809Open(0); + // m6809_bankswitch(data); + // M6809Close(); + // M6809Open(1); + } + } + + DrvPf0Ctrl[0x10] = (data >> 5) & 1; + DrvPf0Ctrl[0x12] = (data >> 6) & 1; + return; + + case 0x180e: + case 0x180f: + if (M6809GetActive() == 0) { + if ( nLastMiss) lastmiss_i8751_write(address & 1, data); + } else { + if (!nLastMiss) shackled_i8751_write(address & 1, data); + } + return; + } +} + +UINT8 lastmiss_main_read(UINT16 address) +{ + switch (address) + { + case 0x1800: + return DrvInputs[0]; + + case 0x1801: + return DrvInputs[1]; + + case 0x1802: + return (DrvInputs[2] & 0x7f) | vblank; + + case 0x1803: + return DrvDips[0]; + + case 0x1804: + return DrvDips[1]; + + case 0x1806: + return i8751_return >> 8; + + case 0x1807: + return i8751_return & 0xff; + } + + return 0; +} + +static INT32 LastmissDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + M6809Open(1); + M6809Reset(); + M6809Close(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM2203Reset(); + BurnYM3526Reset(); + + i8751_return = 0; + i8751_value = 0; + + stopsubcpu = 0; + + return 0; +} + +static INT32 LastmissGfxDecode() +{ + INT32 Plane0[3] = { 0x6000*8,0x4000*8,0x2000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x40000*8,0x20000*8,0x00000*8 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs1[16]= {16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8),0,1,2,3,4,5,6,7 }; + INT32 YOffs0[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 3, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs1, YOffs0, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 LastmissInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (!strncmp(BurnDrvGetTextA(DRV_NAME), "lastm", 5)) { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + + if (BurnLoadRom(DrvSubROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 4, 1)) return 1; + memcpy (DrvGfxROM0 + 0x00000, DrvGfxROM3 + 0x00000, 0x02000); + memcpy (DrvGfxROM0 + 0x06000, DrvGfxROM3 + 0x02000, 0x02000); + memcpy (DrvGfxROM0 + 0x04000, DrvGfxROM3 + 0x04000, 0x02000); + memcpy (DrvGfxROM0 + 0x02000, DrvGfxROM3 + 0x06000, 0x02000); + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 12, 1)) return 1; + + nLastMiss = 1; + } else { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x30000, 3, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x40000, 4, 1)) return 1; + + if (BurnLoadRom(DrvSubROM + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x08000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x50000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x70000, 15, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 19, 1)) return 1; + } + + LastmissGfxDecode(); + } + + M6809Init(2); + M6809Open(0); + M6809MapMemory(DrvMainRAM, 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x1000, 0x17ff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvMainRAM + 0x1000, 0x3000, 0x37ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x3800, 0x3fff, M6809_RAM); + M6809MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, M6809_ROM); + M6809MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(lastmiss_main_write); + M6809SetReadByteHandler(lastmiss_main_read); + M6809Close(); + + M6809Open(1); + M6809MapMemory(DrvMainRAM, 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x1000, 0x17ff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvMainRAM + 0x1000, 0x3000, 0x37ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x3800, 0x3fff, M6809_RAM); + M6809MapMemory(DrvSubROM + 0x04000, 0x4000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(lastmiss_main_write); + M6809SetReadByteHandler(lastmiss_main_read); + M6809Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(ghostb_sound_read); + M6502SetWriteByteHandler(gondo_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM3526Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 0); + BurnTimerAttachM6502YM3526(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203M6809SynchroniseStream, DrvYM2203M6809GetTime, 1); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachM6809(2000000); + + GenericTilesInit(); + + LastmissDoReset(); + + return 0; +} + +static INT32 LastmissExit() +{ + GenericTilesExit(); + M6809Exit(); + M6502Exit(); + + BurnYM3526Exit(); + BurnYM2203Exit(); + + BurnFree (AllMem); + + nLastMiss = 0; + + return 0; +} + +static void lastmiss_draw_bg_layer(INT32 priority, INT32 t) +{ + INT32 scrolly = ((DrvPf0Ctrl[0x12] << 8) + DrvPf0Ctrl[0x13] + 8) & 0x1ff; + INT32 scrollx = ((DrvPf0Ctrl[0x10] << 8) | DrvPf0Ctrl[0x11]) & 0x1ff; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 512; + sy -= scrolly; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 ofst = (offs & 0x0f) | ((offs >> 1) & 0xf0) | ((offs & 0x10) << 4) | (offs & 0x200); + + INT32 code = (DrvPf0RAM[ofst * 2 + 1]) | (DrvPf0RAM[ofst * 2 + 0] << 8); + INT32 color = code >> 12; + + if (priority && color < 8) continue; + + { + color = (color << 4) | 0x300; + UINT8 *src = DrvGfxROM2 + ((code & 0xfff) << 8); + UINT16 *dst; + + for (INT32 y = 0; y < 16; y++, sy++, src+=16) + { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + INT32 xx = sx; + for (INT32 x = 0; x < 16; x++, xx++) + { + INT32 pxl = src[x]; + if (t & (1 << pxl)) continue; + + if (xx >= nScreenWidth || xx < 0) continue; + + dst[xx] = pxl | color; + } + } + } + + // Render16x16Tile_Clip(pTransDraw, code & 0xfff, sx, sy, color, 4, 0x300, DrvGfxROM2); + } +} + +static void lastmiss_draw_txt_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= 8; + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 code = (DrvVidRAM[offs * 2 + 1]) | (DrvVidRAM[offs * 2 + 0] << 8); + INT32 color = code >> 14; + + Render8x8Tile_Mask(pTransDraw, code & 0xfff, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } +} + +static void DrvRecalcSplit(INT32 len) +{ + UINT8 r,g,b; + for (INT32 i = 0; i < len; i++) { + INT32 d = (DrvPalRAM[i + 0]) | (DrvPalRAM[i + len] << 8); + r = (d >> 0) & 0x0f; + g = (d >> 4) & 0x0f; + b = (d >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 LastmissDraw() +{ + if (DrvRecalc) { + DrvRecalcSplit(0x400); + } + + lastmiss_draw_bg_layer(0,0); + draw_sprites1(0); + lastmiss_draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 ShackledDraw() +{ + if (DrvRecalc) { + DrvRecalcSplit(0x400); + } + + lastmiss_draw_bg_layer(0, 0xfff0); + lastmiss_draw_bg_layer(0, 0x000f); + lastmiss_draw_bg_layer(1, 0xfff0); + lastmiss_draw_bg_layer(1, 0x000f); + draw_sprites1(0); + lastmiss_draw_txt_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 LastmissFrame() +{ + if (DrvReset) { + LastmissDoReset(); + } + + M6809NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = 256 * 10; // shackled needs very tight sync + INT32 nCyclesTotal[3] = { 2000000 / 58, 2000000 / 58, 1500000 / 58 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + M6502Open(0); + + vblank = 0x80; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 8 * 10) vblank = 0x80; + if (i == 248 * 10) vblank = 0; + + M6809Open(0); + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + M6809Close(); + + M6809Open(1); + INT32 nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + if (stopsubcpu) { + nCyclesDone[1] += nSegment - nCyclesDone[1]; + } else { + nCyclesDone[1] += M6809Run(nSegment - nCyclesDone[1]); + } + M6809Close(); + + BurnTimerUpdateYM3526(i * (nCyclesTotal[2] / nInterleave)); + } + + M6809Open(0); + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3526(nCyclesTotal[2]); + + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + M6502Close(); + M6809Close(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + + +// Last Mission (US revision 6) + +static struct BurnRomInfo lastmisnRomDesc[] = { + { "dl03-6.13h", 0x08000, 0x47751a5e, 1 }, // 0 maincpu + { "lm_dl04.7h", 0x10000, 0x7dea1552, 1 }, // 1 + + { "lm_dl02.18h", 0x10000, 0xec9b5daf, 2 }, // 2 sub + + { "dl05-.5h", 0x08000, 0x1a5df8c0, 3 }, // 3 audiocpu + + { "dl01-.2a", 0x08000, 0xf3787a5d, 4 }, // 4 gfx1 + + { "dl11-.13f", 0x08000, 0x36579d3b, 5 }, // 5 gfx2 + { "dl12-.9f", 0x08000, 0x2ba6737e, 5 }, // 6 + { "dl13-.8f", 0x08000, 0x39a7dc93, 5 }, // 7 + { "dl10-.16f", 0x08000, 0xfe275ea8, 5 }, // 8 + + { "dl09-.12k", 0x10000, 0x6a5a0c5d, 6 }, // 9 gfx3 + { "dl08-.14k", 0x10000, 0x3b38cfce, 6 }, // 10 + { "dl07-.15k", 0x10000, 0x1b60604d, 6 }, // 11 + { "dl06-.17k", 0x10000, 0xc43c26a7, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "dl-14.9c", 0x00100, 0x2e55aa12, 8 }, // 14 proms +}; + +STD_ROM_PICK(lastmisn) +STD_ROM_FN(lastmisn) + +struct BurnDriver BurnDrvLastmisn = { + "lastmisn", NULL, NULL, NULL, "1986", + "Last Mission (US revision 6)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, lastmisnRomInfo, lastmisnRomName, NULL, NULL, LastmisnInputInfo, LastmisnDIPInfo, + LastmissInit, LastmissExit, LastmissFrame, LastmissDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Last Mission (US revision 5) + +static struct BurnRomInfo lastmsnoRomDesc[] = { + { "lm_dl03.13h", 0x08000, 0x357f5f6b, 1 }, // 0 maincpu + { "lm_dl04.7h", 0x10000, 0x7dea1552, 1 }, // 1 + + { "lm_dl02.18h", 0x10000, 0xec9b5daf, 2 }, // 2 sub + + { "dl05-.5h", 0x08000, 0x1a5df8c0, 3 }, // 3 audiocpu + + { "dl01-.2a", 0x08000, 0xf3787a5d, 4 }, // 4 gfx1 + + { "dl11-.13f", 0x08000, 0x36579d3b, 5 }, // 5 gfx2 + { "dl12-.9f", 0x08000, 0x2ba6737e, 5 }, // 6 + { "dl13-.8f", 0x08000, 0x39a7dc93, 5 }, // 7 + { "dl10-.16f", 0x08000, 0xfe275ea8, 5 }, // 8 + + { "dl09-.12k", 0x10000, 0x6a5a0c5d, 6 }, // 9 gfx3 + { "dl08-.14k", 0x10000, 0x3b38cfce, 6 }, // 10 + { "dl07-.15k", 0x10000, 0x1b60604d, 6 }, // 11 + { "dl06-.17k", 0x10000, 0xc43c26a7, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "dl-14.9c", 0x00100, 0x2e55aa12, 8 }, // 14 proms +}; + +STD_ROM_PICK(lastmsno) +STD_ROM_FN(lastmsno) + +struct BurnDriver BurnDrvLastmsno = { + "lastmisno", "lastmisn", NULL, NULL, "1986", + "Last Mission (US revision 5)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, lastmsnoRomInfo, lastmsnoRomName, NULL, NULL, LastmisnInputInfo, LastmisnDIPInfo, + LastmissInit, LastmissExit, LastmissFrame, LastmissDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Last Mission (Japan) + +static struct BurnRomInfo lastmsnjRomDesc[] = { + { "dl03-.13h", 0x08000, 0x4be5e7e1, 1 }, // 0 maincpu + { "dl04-.7h", 0x10000, 0xf026adf9, 1 }, // 1 + + { "dl02-.18h", 0x10000, 0xd0de2b5d, 2 }, // 2 sub + + { "dl05-.5h", 0x08000, 0x1a5df8c0, 3 }, // 3 audiocpu + + { "dl01-.2a", 0x08000, 0xf3787a5d, 4 }, // 4 gfx1 + + { "dl11-.13f", 0x08000, 0x36579d3b, 5 }, // 5 gfx2 + { "dl12-.9f", 0x08000, 0x2ba6737e, 5 }, // 6 + { "dl13-.8f", 0x08000, 0x39a7dc93, 5 }, // 7 + { "dl10-.16f", 0x08000, 0xfe275ea8, 5 }, // 8 + + { "dl09-.12k", 0x10000, 0x6a5a0c5d, 6 }, // 9 gfx3 + { "dl08-.14k", 0x10000, 0x3b38cfce, 6 }, // 10 + { "dl07-.15k", 0x10000, 0x1b60604d, 6 }, // 11 + { "dl06-.17k", 0x10000, 0xc43c26a7, 6 }, // 12 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 13 mcu + + { "dl-14.9c", 0x00100, 0x2e55aa12, 8 }, // 14 proms +}; + +STD_ROM_PICK(lastmsnj) +STD_ROM_FN(lastmsnj) + +struct BurnDriver BurnDrvLastmsnj = { + "lastmisnj", "lastmisn", NULL, NULL, "1986", + "Last Mission (Japan)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, lastmsnjRomInfo, lastmsnjRomName, NULL, NULL, LastmisnInputInfo, LastmsnjDIPInfo, + LastmissInit, LastmissExit, LastmissFrame, LastmissDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Shackled (US) + +static struct BurnRomInfo shackledRomDesc[] = { + { "dk-02.rom", 0x08000, 0x87f8fa85, 1 }, // 0 maincpu + { "dk-06.rom", 0x10000, 0x69ad62d1, 1 }, // 1 + { "dk-05.rom", 0x10000, 0x598dd128, 1 }, // 2 + { "dk-04.rom", 0x10000, 0x36d305d4, 1 }, // 3 + { "dk-03.rom", 0x08000, 0x6fd90fd1, 1 }, // 4 + + { "dk-01.rom", 0x10000, 0x71fe3bda, 2 }, // 5 sub + + { "dk-07.rom", 0x08000, 0x887e4bcc, 3 }, // 6 audiocpu + + { "dk-00.rom", 0x08000, 0x69b975aa, 5 }, // 8 gfx1 + + { "dk-12.rom", 0x10000, 0x615c2371, 6 }, // 9 gfx2 + { "dk-13.rom", 0x10000, 0x479aa503, 6 }, // 10 + { "dk-14.rom", 0x10000, 0xcdc24246, 6 }, // 11 + { "dk-15.rom", 0x10000, 0x88db811b, 6 }, // 12 + { "dk-16.rom", 0x10000, 0x061a76bd, 6 }, // 13 + { "dk-17.rom", 0x10000, 0xa6c5d8af, 6 }, // 14 + { "dk-18.rom", 0x10000, 0x4d466757, 6 }, // 15 + { "dk-19.rom", 0x10000, 0x1911e83e, 6 }, // 16 + + { "dk-11.rom", 0x10000, 0x5cf5719f, 7 }, // 17 gfx3 + { "dk-10.rom", 0x10000, 0x408e6d08, 7 }, // 18 + { "dk-09.rom", 0x10000, 0xc1557fac, 7 }, // 19 + { "dk-08.rom", 0x10000, 0x5e54e9f5, 7 }, // 20 + + { "id8751h.mcu", 0x01000, 0x00000000, 4 | BRF_NODUMP }, // 7 mcu +}; + +STD_ROM_PICK(shackled) +STD_ROM_FN(shackled) + +struct BurnDriver BurnDrvShackled = { + "shackled", NULL, NULL, NULL, "1986", + "Shackled (US)\0", NULL, "Data East USA", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, shackledRomInfo, shackledRomName, NULL, NULL, ShackledInputInfo, ShackledDIPInfo, + LastmissInit, LastmissExit, LastmissFrame, ShackledDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Breywood (Japan revision 2) + +static struct BurnRomInfo breywoodRomDesc[] = { + { "7.bin", 0x08000, 0xc19856b9, 1 }, // 0 maincpu + { "3.bin", 0x10000, 0x2860ea02, 1 }, // 1 + { "4.bin", 0x10000, 0x0fdd915e, 1 }, // 2 + { "5.bin", 0x10000, 0x71036579, 1 }, // 3 + { "6.bin", 0x08000, 0x308f4893, 1 }, // 4 + + { "8.bin", 0x10000, 0x3d9fb623, 2 }, // 5 sub + + { "2.bin", 0x08000, 0x4a471c38, 3 }, // 6 audiocpu + + { "1.bin", 0x08000, 0x815a891a, 5 }, // 8 gfx1 + + { "20.bin", 0x10000, 0x2b7634f2, 6 }, // 9 gfx2 + { "19.bin", 0x10000, 0x4530a952, 6 }, // 10 + { "18.bin", 0x10000, 0x87c28833, 6 }, // 11 + { "17.bin", 0x10000, 0xbfb43a4d, 6 }, // 12 + { "16.bin", 0x10000, 0xf9848cc4, 6 }, // 13 + { "15.bin", 0x10000, 0xbaa3d218, 6 }, // 14 + { "14.bin", 0x10000, 0x12afe533, 6 }, // 15 + { "13.bin", 0x10000, 0x03373755, 6 }, // 16 + + { "9.bin", 0x10000, 0x067e2a43, 7 }, // 17 gfx3 + { "10.bin", 0x10000, 0xc19733aa, 7 }, // 18 + { "11.bin", 0x10000, 0xe37d5dbe, 7 }, // 19 + { "12.bin", 0x10000, 0xbeee880f, 7 }, // 20 + + { "id8751h.mcu", 0x01000, 0x00000000, 4 | BRF_NODUMP }, // 7 mcu +}; + +STD_ROM_PICK(breywood) +STD_ROM_FN(breywood) + +struct BurnDriver BurnDrvBreywood = { + "breywood", "shackled", NULL, NULL, "1986", + "Breywood (Japan revision 2)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, breywoodRomInfo, breywoodRomName, NULL, NULL, ShackledInputInfo, ShackledDIPInfo, + LastmissInit, LastmissExit, LastmissFrame, ShackledDraw, NULL, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + + + +static INT32 MSM5205Next = 0; +static INT32 Toggle = 0; + +static void csilver_i8751_write(INT32 offset, UINT8 data) +{ + static INT32 coin, latch = 0, snd; + i8751_return = 0; + + UINT8 coininp = DrvInputs[2]; + + switch (offset) + { + case 0: /* High byte */ + i8751_value = (i8751_value & 0xff) | (data << 8); + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); /* Signal main cpu */ + break; + case 1: /* Low byte */ + i8751_value = (i8751_value & 0xff00) | data; + break; + } + + if(offset == 0) + { + /* Coins are controlled by the i8751 */ + if ((coininp & 3) == 3 && !latch) latch = 1; + if ((coininp & 3) != 3 && latch) {coin++; latch = 0; snd = 0x1200; i8751_return = 0x1200; return;} + + if (i8751_value == 0x054a) {i8751_return = ~(0x4a); coin = 0; snd = 0;} /* Captain Silver (Japan) ID */ + if (i8751_value == 0x054c) {i8751_return = ~(0x4c); coin = 0; snd = 0;} /* Captain Silver (World) ID */ + if ((i8751_value >> 8) == 0x01) i8751_return = 0; /* Coinage - Not Supported */ + if ((i8751_value >> 8) == 0x02) {i8751_return = snd | coin; snd = 0; } /* Coin Return */ + if ((i8751_value >> 8) == 0x03 && coin) {i8751_return = 0; coin--;} /* Coin Clear */ + } +} + +void csilver_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1803: + if (M6809GetActive() == 0) { // main + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } else { + M6809Close(); + M6809Open(0); + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + M6809Close(); + M6809Open(1); + } + return; + + case 0x1804: + if (M6809GetActive() == 0) { // main + M6809Close(); + M6809Open(1); + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + M6809Close(); + M6809Open(0); + } else { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + return; + + case 0x1805: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + + case 0x1807: + *flipscreen = data; + return; + + case 0x180c: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + + case 0x1808: + case 0x1809: // maincpu + case 0x180a: + case 0x180b: // dec8_scroll2_w + DrvPf0Ctrl[0x10 + (address & 3)] = data; + return; + + + case 0x180d: // main + if (M6809GetActive() == 0) m6809_bankswitch(data); + return; + + case 0x180e: // main + case 0x180f: + if (M6809GetActive() == 0) csilver_i8751_write(address & 1, data); + return; + } +} + +UINT8 csilver_main_read(UINT16 address) +{ + switch (address) + { + case 0x1800: + return DrvInputs[1]; + + case 0x1801: + return DrvInputs[0]; + + case 0x1803: + return (DrvInputs[2] & 0x7f) | vblank; + + case 0x1804: + return DrvDips[1]; + + case 0x1805: + return DrvDips[0]; + + case 0x1c00: + return i8751_return >> 8; + + case 0x1e00: + return i8751_return & 0xff; + } + + return 0; +} + +static void csilver_sound_bank(INT32 data) +{ + M6502MapMemory(DrvM6502ROM + 0x10000 + ((data & 8) >> 3) * 0x4000, 0x4000, 0x7fff, M6502_ROM); +} + +void csilver_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0800: + case 0x0801: + BurnYM2203Write(0, address & 1, data); + return; + + case 0x1000: + case 0x1001: + BurnYM3526Write(address & 1, data); + return; + + case 0x1800: + MSM5205Next = data; + return; + + case 0x2000: + csilver_sound_bank(data); + return; + } +} + +UINT8 csilver_sound_read(UINT16 address) +{ + switch (address) + { + case 0x3000: + return *soundlatch; + + case 0x3400: + MSM5205ResetWrite(0, 0); + return 0; + } + + return 0; +} + +static void CsilverADPCMInt() +{ + Toggle ^= 1; + if (Toggle) M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_AUTO); + + MSM5205DataWrite(0, MSM5205Next >> 4); + MSM5205Next <<= 4; +} + +static INT32 CsilverDoReset() +{ + INT32 nRet = LastmissDoReset(); + + MSM5205Reset(); + + return nRet; +} + +static INT32 CsilverInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvMainROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvMainROM + 0x20000, 2, 1)) return 1; + + if (BurnLoadRom(DrvSubROM + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvM6502ROM + 0x00000, 4, 1)) return 1; + memcpy (DrvM6502ROM + 0x10000, DrvM6502ROM + 0x00000, 0x8000); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x50000, 14, 1)) return 1; + + LastmissGfxDecode(); + } + + M6809Init(2); + M6809Open(0); + M6809MapMemory(DrvMainRAM + 0x00000, 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x1000, 0x17ff, M6809_RAM); // xxxxbbbbggggrrrr + M6809MapMemory(DrvVidRAM, 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvMainRAM + 0x01000, 0x3000, 0x37ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x3800, 0x3fff, M6809_RAM); + M6809MapMemory(DrvMainROM + 0x10000, 0x4000, 0x7fff, M6809_RAM); + M6809MapMemory(DrvMainROM + 0x08000, 0x8000, 0xffff, M6809_RAM); + M6809SetWriteByteHandler(csilver_main_write); + M6809SetReadByteHandler(csilver_main_read); + M6809Close(); + + M6809Open(1); + M6809MapMemory(DrvMainRAM + 0x00000, 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvPalRAM, 0x1000, 0x17ff, M6809_RAM); // xxxxbbbbggggrrrr + M6809MapMemory(DrvVidRAM, 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvMainRAM + 0x01000, 0x3000, 0x37ff, M6809_RAM); + M6809MapMemory(DrvPf0RAM, 0x3800, 0x3fff, M6809_RAM); + M6809MapMemory(DrvSubROM + 0x04000, 0x4000, 0xffff, M6809_RAM); + M6809SetWriteByteHandler(csilver_main_write); + M6809SetReadByteHandler(csilver_main_read); + M6809Close(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502RAM, 0x0000, 0x07ff, M6502_RAM); + M6502MapMemory(DrvM6502ROM + 0x4000, 0x4000, 0x7fff, M6502_ROM); + M6502MapMemory(DrvM6502ROM + 0x8000, 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(csilver_sound_read); + M6502SetWriteByteHandler(csilver_sound_write); + M6502Close(); + + BurnSetRefreshRate(58.00); + + BurnYM3526Init(3000000, &DrvYM3812FMIRQHandler, &DrvYM3812SynchroniseStream, 0); + BurnTimerAttachM6502YM3526(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203M6809SynchroniseStream1500000, DrvYM2203M6809GetTime1500000, 1); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachM6809(1500000); + + MSM5205Init(0, CsilverMSM5205SynchroniseStream, 384000, CsilverADPCMInt, MSM5205_S48_4B, 80, 1); + + GenericTilesInit(); + + CsilverDoReset(); + + return 0; +} + + + + +static INT32 CsilverFrame() +{ + if (DrvReset) { + CsilverDoReset(); + } + + M6809NewFrame(); + M6502NewFrame(); + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nInterleave = MSM5205CalcInterleave(0, 1500000); + INT32 nCyclesTotal[3] = { 1500000 / 58, 1500000 / 58, 1500000 / 58 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + M6502Open(0); + + vblank = 0x80; + + INT32 DrvVBlankSlices[2]; + DrvVBlankSlices[0] = (INT32)((double)nInterleave * 0.03); + DrvVBlankSlices[1] = (INT32)((double)nInterleave * 0.97); + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == DrvVBlankSlices[0]) vblank = 0x80; + + M6809Open(0); + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + M6809Close(); + + M6809Open(1); + INT32 nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1); + nCyclesDone[1] += M6809Run(nSegment - nCyclesDone[1]); + if (i == DrvVBlankSlices[1]) { + vblank = 0; + M6809SetIRQ(0x20, M6809_IRQSTATUS_AUTO); + } + MSM5205Update(); + M6809Close(); + + BurnTimerUpdateYM3526(i * (nCyclesTotal[2] / nInterleave)); + } + + M6809Open(0); + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3526(nCyclesTotal[2]); + + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + + M6502Close(); + M6809Close(); + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + +// Captain Silver (World) + +static struct BurnRomInfo csilverRomDesc[] = { + { "dx03-12.18d", 0x08000, 0x2d926e7c, 1 }, // 0 maincpu + { "dx01.12d", 0x10000, 0x570fb50c, 1 }, // 1 + { "dx02.13d", 0x10000, 0x58625890, 1 }, // 2 + + { "dx04-1.19d", 0x10000, 0x29432691, 2 }, // 3 sub + + { "dx05.3f", 0x10000, 0xeb32cf25, 3 }, // 4 audiocpu + + { "dx00.3d", 0x08000, 0xf01ef985, 4 }, // 5 gfx1 + + { "dx14.15k", 0x10000, 0x80f07915, 5 }, // 6 gfx2 + { "dx13.13k", 0x10000, 0xd32c02e7, 5 }, // 7 + { "dx12.10k", 0x10000, 0xac78b76b, 5 }, // 8 + + { "dx06.5f", 0x10000, 0xb6fb208c, 6 }, // 9 gfx3 + { "dx07.7f", 0x10000, 0xee3e1817, 6 }, // 10 + { "dx08.8f", 0x10000, 0x705900fe, 6 }, // 11 + { "dx09.10f", 0x10000, 0x3192571d, 6 }, // 12 + { "dx10.12f", 0x10000, 0x3ef77a32, 6 }, // 13 + { "dx11.13f", 0x10000, 0x9cf3d5b8, 6 }, // 14 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 15 mcu +}; + +STD_ROM_PICK(csilver) +STD_ROM_FN(csilver) + +struct BurnDriver BurnDrvCsilver = { + "csilver", NULL, NULL, NULL, "1987", + "Captain Silver (World)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, csilverRomInfo, csilverRomName, NULL, NULL, CsilverInputInfo, CsilverDIPInfo, + CsilverInit, LastmissExit, CsilverFrame, LastmissDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Captain Silver (Japan) + +static struct BurnRomInfo csilverjRomDesc[] = { + { "dx03-3.a4", 0x08000, 0x02dd8cfc, 1 }, // 0 maincpu + { "dx01.a2", 0x10000, 0x570fb50c, 1 }, // 1 + { "dx02.a3", 0x10000, 0x58625890, 1 }, // 2 + + { "dx04-1.a5", 0x10000, 0x29432691, 2 }, // 3 sub + + { "dx05.a6", 0x10000, 0xeb32cf25, 3 }, // 4 audiocpu + + { "dx00.a1", 0x08000, 0xf01ef985, 4 }, // 5 gfx1 + + { "dx14.b5", 0x10000, 0x80f07915, 5 }, // 6 gfx2 + { "dx13.b4", 0x10000, 0xd32c02e7, 5 }, // 7 + { "dx12.b3", 0x10000, 0xac78b76b, 5 }, // 8 + + { "dx06.a7", 0x10000, 0xb6fb208c, 6 }, // 9 gfx3 + { "dx07.a8", 0x10000, 0xee3e1817, 6 }, // 10 + { "dx08.a9", 0x10000, 0x705900fe, 6 }, // 11 + { "dx09.a10", 0x10000, 0x3192571d, 6 }, // 12 + { "dx10.b1", 0x10000, 0x3ef77a32, 6 }, // 13 + { "dx11.b2", 0x10000, 0x9cf3d5b8, 6 }, // 14 + + { "id8751h.mcu", 0x01000, 0x00000000, 7 | BRF_NODUMP }, // 15 mcu +}; + +STD_ROM_PICK(csilverj) +STD_ROM_FN(csilverj) + +struct BurnDriver BurnDrvCsilverj = { + "csilverj", "csilver", NULL, NULL, "1987", + "Captain Silver (Japan)\0", NULL, "Data East Corporation", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, csilverjRomInfo, csilverjRomName, NULL, NULL, CsilverInputInfo, CsilverDIPInfo, + CsilverInit, LastmissExit, CsilverFrame, LastmissDraw, NULL, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_dotrikun.cpp b/src/burn/drivers/misc_pre90s/d_dotrikun.cpp new file mode 100644 index 00000000..d074ce98 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_dotrikun.cpp @@ -0,0 +1,249 @@ +// FB Alpha Dottori Kun driver module +// Based on MAME driver by Takahiro Nogi + +#include "tiles_generic.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvReset; +static UINT8 DrvInputs[1]; + +static UINT8 *nColor; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down", }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 start", BIT_DIGITAL, DrvJoy1 + 6, "p1 start" }, + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p1 coin" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, +}; + +STDINPUTINFO(Drv) + +UINT8 __fastcall dotrikun_in_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return DrvInputs[0]; + } + + return 0; +} + +void __fastcall dotrikun_out_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + *nColor = data; + return; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x010000; + + DrvPalette = (UINT32*)Next; Next += 0x000002 * sizeof (UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000800; + + nColor = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM, 0, 1)) return 1; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea (0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea (0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea (0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea (0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea (0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetOutHandler(dotrikun_out_port); + ZetSetInHandler(dotrikun_in_port); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPalette[0] = BurnHighCol((*nColor & 0x08) ? 0xff : 0, (*nColor & 0x10) ? 0xff : 0, (*nColor & 0x20) ? 0xff : 0, 0); + DrvPalette[1] = BurnHighCol((*nColor & 0x01) ? 0xff : 0, (*nColor & 0x02) ? 0xff : 0, (*nColor & 0x04) ? 0xff : 0, 0); + } + + for (INT32 offs = 0; offs < 0x0600; offs++) + { + INT32 sx = (offs & 0x0f) << 4; + INT32 sy = (offs >> 4) << 1; + INT32 px = DrvZ80RAM[offs]; + + for (INT32 i = 0; i < 8; i++, sx+=2) + { + INT32 pen = (px >> (7 - i)) & 1; + + if (sx > nScreenWidth || sy >= nScreenHeight) continue; + + pTransDraw[((sy + 0) << 8) | (sx + 0)] = pen; + pTransDraw[((sy + 0) << 8) | (sx + 1)] = pen; + pTransDraw[((sy + 1) << 8) | (sx + 0)] = pen; + pTransDraw[((sy + 1) << 8) | (sx + 1)] = pen; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + } + + ZetOpen(0); + ZetRun(4000000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + } + + return 0; +} + + +// Dottori Kun (new version) + +static struct BurnRomInfo dotrikunRomDesc[] = { + { "14479a.mpr", 0x4000, 0xb77a50db, BRF_ESS | BRF_PRG }, // Z80 code +}; + +STD_ROM_PICK(dotrikun) +STD_ROM_FN(dotrikun) + +struct BurnDriver BurnDrvdotrikun = { + "dotrikun", NULL, NULL, NULL, "1990", + "Dottori Kun (new version)\0", NULL, "Sega", "Test Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, dotrikunRomInfo, dotrikunRomName, NULL, NULL, DrvInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x02, + 256, 192, 4, 3 +}; + + +// Dottori Kun (old version) + +static struct BurnRomInfo dotriku2RomDesc[] = { + { "14479.mpr", 0x4000, 0xa6aa7fa5, BRF_ESS | BRF_PRG }, // Z80 code +}; + +STD_ROM_PICK(dotriku2) +STD_ROM_FN(dotriku2) + +struct BurnDriver BurnDrvdotriku2 = { + "dotrikun2", "dotrikun", NULL, NULL, "1990", + "Dottori Kun (old version)\0", NULL, "Sega", "Test Hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, dotriku2RomInfo, dotriku2RomName, NULL, NULL, DrvInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x02, + 256, 192, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_dynduke.cpp b/src/burn/drivers/misc_pre90s/d_dynduke.cpp new file mode 100644 index 00000000..8613927c --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_dynduke.cpp @@ -0,0 +1,974 @@ +// FB Alpha Dynamite Duke driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "seibusnd.h" +#include "vez.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvV30ROM0; +static UINT8 *DrvV30ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *DrvV30RAM0; +static UINT8 *DrvV30RAM1; +static UINT8 *DrvShareRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvScrRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *bg_bankbase; +static UINT8 *fg_bankbase; +static UINT8 *bg_enable; +static UINT8 *fg_enable; +static UINT8 *txt_enable; +static UINT8 *sprite_enable; +static UINT8 *flipscreen; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[2]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static const INT32 nInterleave = 60; +static const INT32 nCyclesTotal[3] = { 8000000 / 60, 8000000 / 60, 3579545 / 60 }; +static INT32 nCyclesDone[3] = { 0, 0, 0 }; + +static struct BurnInputInfo DyndukeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Dynduke) + +static struct BurnDIPInfo DyndukeDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x13, 0x01, 0x01, 0x01, "Mode 1" }, + {0x13, 0x01, 0x01, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x06, 0x00, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x06, 0x02, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x06, 0x04, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x06, 0x06, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 5, "Coin B" }, + {0x13, 0x01, 0x18, 0x18, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x18, 0x10, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x18, 0x08, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x18, 0x00, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x18, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 5, "Coinage" }, + {0x13, 0x01, 0x1e, 0x18, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x1e, 0x1a, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x1e, 0x1c, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x1e, 0x1e, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x1e, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2, "Starting Coin" }, + {0x13, 0x01, 0x20, 0x20, "Normal" }, + {0x13, 0x01, 0x20, 0x00, "X 2" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x40, 0x40, "Upright" }, + {0x13, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "80K 100K+" }, + {0x14, 0x01, 0x0c, 0x08, "100K 100K+" }, + {0x14, 0x01, 0x0c, 0x04, "120K 100K+" }, + {0x14, 0x01, 0x0c, 0x00, "120K 120K+" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + {0x14, 0x01, 0x30, 0x10, "Hard" }, + {0x14, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Dynduke) + +static void sync_sound_cpu() +{ + UINT32 cycles = (nCyclesTotal[2] * VezTotalCycles()) / (nCyclesTotal[0] / nInterleave); + + if ((cycles - ZetTotalCycles()) > 0) { + nCyclesDone[2] += cycles - ZetTotalCycles(); + BurnTimerUpdateYM3812(cycles); + } +} + +void __fastcall master_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x0b004: + case 0x0b005: + case 0x0f004: + case 0x0f005: // nop + return; + + case 0x0b006: + // case 0x0b007: + case 0x0f006: + // case 0x0f007: + *bg_enable = ~data & 0x01; + *fg_enable = ~data & 0x02; + *txt_enable = ~data & 0x04; + *sprite_enable = ~data & 0x08; + *flipscreen = data & 0x40; + return; + } + + if ((address & 0xffff0) == 0x0d000 || (address & 0xffff0) == 0x09000) { + sync_sound_cpu(); + seibu_main_word_write(address, data); + return; + } +} + +UINT8 __fastcall master_read(UINT32 address) +{ + switch (address) + { + case 0xb000: + case 0xf000: + return DrvInputs[0]; + + case 0xb001: + case 0xf001: + return DrvInputs[1]; + + case 0xb002: + case 0xf002: + return DrvDips[0]; + + case 0xb003: + case 0xf003: + return DrvDips[1]; + } + + if ((address & 0xffff0) == 0x0d000 || (address & 0xffff0) == 0x09000) { + sync_sound_cpu(); + return seibu_main_word_read(address); + } + + return 0; +} + +static inline void palette_update_entry(INT32 entry) +{ + UINT16 p = *((UINT16*)(DrvPalRAM + (entry * 2))); + + INT32 r = (p >> 0) & 0x0f; + INT32 g = (p >> 4) & 0x0f; + INT32 b = (p >> 8) & 0x0f; + + DrvPalette[entry] = BurnHighCol((r<<4)|r, (g<<4)|g, (b<<4)|b, 0); +} + +void __fastcall slave_write(UINT32 address, UINT8 data) +{ + if ((address & 0xff000) == 0x07000) { + DrvPalRAM[(address & 0xfff)] = data; + palette_update_entry((address & 0xfff)/2); + return; + } + + switch (address) + { + case 0x0a000: + // case 0x0a001: + *bg_bankbase = (data & 0x01) >> 0; + *fg_bankbase = (data & 0x10) >> 4; + return; + + case 0x0c000: + case 0x0c001: // nop + return; + } +} + +static void map_master_cpu() +{ + VezOpen(0); + VezMapArea(0x00000, 0x06fff, 0, DrvV30RAM0); + VezMapArea(0x00000, 0x06fff, 1, DrvV30RAM0); + VezMapArea(0x00000, 0x06fff, 2, DrvV30RAM0); + VezMapArea(0x07000, 0x07fff, 0, DrvSprRAM); + VezMapArea(0x07000, 0x07fff, 1, DrvSprRAM); + VezMapArea(0x07000, 0x07fff, 2, DrvSprRAM); + VezMapArea(0x08000, 0x087ff, 0, DrvScrRAM); // scroll ram (8000-80ff) + VezMapArea(0x08000, 0x087ff, 1, DrvScrRAM); + VezMapArea(0x08000, 0x087ff, 2, DrvScrRAM); + VezMapArea(0x0a000, 0x0afff, 0, DrvShareRAM); + VezMapArea(0x0a000, 0x0afff, 1, DrvShareRAM); + VezMapArea(0x0a000, 0x0afff, 2, DrvShareRAM); + VezMapArea(0x0c000, 0x0c7ff, 0, DrvTxtRAM); + VezMapArea(0x0c000, 0x0c7ff, 1, DrvTxtRAM); + VezMapArea(0x0c000, 0x0c7ff, 2, DrvTxtRAM); + VezMapArea(0xa0000, 0xfffff, 0, DrvV30ROM0 + 0xa0000); + VezMapArea(0xa0000, 0xfffff, 2, DrvV30ROM0 + 0xa0000); + VezSetWriteHandler(master_write); + VezSetReadHandler(master_read); + VezClose(); +} + +static void map_masterj_cpu() +{ + VezOpen(0); + VezMapArea(0x00000, 0x06fff, 0, DrvV30RAM0); + VezMapArea(0x00000, 0x06fff, 1, DrvV30RAM0); + VezMapArea(0x00000, 0x06fff, 2, DrvV30RAM0); + VezMapArea(0x07000, 0x07fff, 0, DrvSprRAM); + VezMapArea(0x07000, 0x07fff, 1, DrvSprRAM); + VezMapArea(0x07000, 0x07fff, 2, DrvSprRAM); + VezMapArea(0x08000, 0x087ff, 0, DrvTxtRAM); + VezMapArea(0x08000, 0x087ff, 1, DrvTxtRAM); + VezMapArea(0x08000, 0x087ff, 2, DrvTxtRAM); + VezMapArea(0x0c000, 0x0c7ff, 0, DrvScrRAM); // scroll ram (8000-80ff) + VezMapArea(0x0c000, 0x0c7ff, 1, DrvScrRAM); + VezMapArea(0x0c000, 0x0c7ff, 2, DrvScrRAM); + VezMapArea(0x0e000, 0x0efff, 0, DrvShareRAM); + VezMapArea(0x0e000, 0x0efff, 1, DrvShareRAM); + VezMapArea(0x0e000, 0x0efff, 2, DrvShareRAM); + VezMapArea(0xa0000, 0xfffff, 0, DrvV30ROM0 + 0xa0000); + VezMapArea(0xa0000, 0xfffff, 2, DrvV30ROM0 + 0xa0000); + VezSetWriteHandler(master_write); + VezSetReadHandler(master_read); + VezClose(); +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + VezOpen(0); + VezReset(); + VezClose(); + + VezOpen(1); + VezReset(); + VezClose(); + + seibu_sound_reset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 4,0,(0x10000*8)+4,0x10000*8 }; + INT32 Plane1[6] = { ((0x80000*8)*2)+4, ((0x80000*8)*2)+0, ((0x80000*8)*1)+4, ((0x80000*8)*1)+0, ((0x80000*8)*0)+4, ((0x80000*8)*0)+0}; + INT32 Plane2[4] = { 12, 8, 4, 0 }; + INT32 Plane3[4] = { 0x80000*8+4, 0x80000*8, 4, 0 }; + INT32 XOffs0[16] = { 0,1,2,3,8,9,10,11,256+0,256+1,256+2,256+3,256+8,256+9,256+10,256+11 }; + INT32 XOffs2[16] = { 0,1,2,3, 16,17,18,19,512+0,512+1,512+2,512+3,512+8+8,512+9+8,512+10+8,512+11+8 }; + INT32 YOffs0[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16,9*16,10*16,11*16,12*16,13*16,14*16,15*16 }; + INT32 YOffs2[16] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(0x0400, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x180000); + + GfxDecode(0x2000, 6, 16, 16, Plane1, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Plane3, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane2, XOffs2, YOffs2, 0x400, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvV30ROM0 = Next; Next += 0x100000; + DrvV30ROM1 = Next; Next += 0x100000; + + SeibuZ80ROM = Next; Next += 0x020000; + SeibuZ80DecROM = Next; Next += 0x020000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM3 = Next; Next += 0x400000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32); + + AllRam = Next; + + DrvV30RAM0 = Next; Next += 0x007000; + DrvV30RAM1 = Next; Next += 0x006000; + DrvShareRAM = Next; Next += 0x001000; + + DrvTxtRAM = Next; Next += 0x000800; + DrvBgRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x000800; + DrvScrRAM = Next; Next += 0x000800; + + DrvSprRAM = Next; Next += 0x001000; + DrvSprBuf = Next; Next += 0x001000; + + DrvPalRAM = Next; Next += 0x001000; + + SeibuZ80RAM = Next; Next += 0x000800; + + bg_bankbase = Next; Next += 0x000001; + fg_bankbase = Next; Next += 0x000001; + bg_enable = Next; Next += 0x000001; + fg_enable = Next; Next += 0x000001; + txt_enable = Next; Next += 0x000001; + sprite_enable = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit(void (*pV30MapCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvV30ROM0 + 0x0a0000, 0, 2)) return 1; + if (BurnLoadRom(DrvV30ROM0 + 0x0a0001, 1, 2)) return 1; + if (BurnLoadRom(DrvV30ROM0 + 0x0c0000, 2, 2)) return 1; + if (BurnLoadRom(DrvV30ROM0 + 0x0c0001, 3, 2)) return 1; + + if (BurnLoadRom(DrvV30ROM1 + 0x0e0000, 4, 2)) return 1; + if (BurnLoadRom(DrvV30ROM1 + 0x0e0001, 5, 2)) return 1; + + if (BurnLoadRom(SeibuZ80ROM + 0x00000, 6, 1)) return 1; + memcpy (SeibuZ80ROM + 0x10000, SeibuZ80ROM + 0x08000, 0x08000); + memcpy (SeibuZ80ROM + 0x18000, SeibuZ80ROM + 0x00000, 0x08000); + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x140000, 14, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x0c0000, 18, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x000001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080000, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080001, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x100001, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x180000, 25, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x180001, 26, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 27, 1)) return 1; + + DrvGfxDecode(); + } + + VezInit(0, V30_TYPE); + VezInit(1, V30_TYPE); + + pV30MapCallback(); + + VezOpen(1); + VezMapArea(0x00000, 0x05fff, 0, DrvV30RAM1); + VezMapArea(0x00000, 0x05fff, 1, DrvV30RAM1); + VezMapArea(0x00000, 0x05fff, 2, DrvV30RAM1); + VezMapArea(0x06000, 0x067ff, 0, DrvBgRAM); + VezMapArea(0x06000, 0x067ff, 1, DrvBgRAM); + VezMapArea(0x06000, 0x067ff, 2, DrvBgRAM); + VezMapArea(0x06800, 0x06fff, 0, DrvFgRAM); + VezMapArea(0x06800, 0x06fff, 1, DrvFgRAM); + VezMapArea(0x06800, 0x06fff, 2, DrvFgRAM); + VezMapArea(0x07000, 0x07fff, 0, DrvPalRAM); +// VezMapArea(0x07000, 0x07fff, 1, DrvPalRAM); + VezMapArea(0x07000, 0x07fff, 2, DrvPalRAM); + VezMapArea(0x08000, 0x08fff, 0, DrvShareRAM); + VezMapArea(0x08000, 0x08fff, 1, DrvShareRAM); + VezMapArea(0x08000, 0x08fff, 2, DrvShareRAM); + VezMapArea(0xc0000, 0xfffff, 0, DrvV30ROM1 + 0xc0000); + VezMapArea(0xc0000, 0xfffff, 2, DrvV30ROM1 + 0xc0000); + VezSetWriteHandler(slave_write); + VezClose(); + + seibu_sound_init(0, 0x20000, 3579545, 3579545, 1320000 / 132); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + VezExit(); + + seibu_sound_exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites(INT32 pri) +{ + if (*sprite_enable == 0) return; + + UINT16 *spr = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0x800-4; offs >= 0; offs -= 4) + { + INT32 attr = spr[offs + 0]; + INT32 code = spr[offs + 1]; + INT32 sx = spr[offs + 2]; + INT32 skip = spr[offs + 3]; + + INT32 prio = (sx >> 13) & 3; + + if ((skip & 0x0f00) != 0x0f00 || prio != pri) continue; + + INT32 flipx = attr & 0x2000; + INT32 flipy = attr & 0x4000; + INT32 sy = attr & 0x00ff; + INT32 color =((attr >> 8) & 0x1f) + 0x30; + + if (sx & 0x100) { + sx = 0 - (0x100 - (sx & 0xff)); + } else { + sx = sx & 0xff; + } + + code &= 0x3fff; + + if (*flipscreen) { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 15, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 15, 0, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy - 16, color, 4, 15, 0, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 4, 15, 0, DrvGfxROM3); + } + } + } +} + +static void draw_bg_layer(INT32 priority) +{ + if (*bg_enable == 0) { + if (priority == 0) BurnTransferClear(); + return; + } + + UINT16 *scrl = (UINT16*)DrvScrRAM; + UINT16 *vram = (UINT16*)DrvBgRAM; + + INT32 scrolly = (((scrl[0x01] & 0x30) << 4) | ((scrl[0x02] & 0x7f) << 1) | ((scrl[0x02] & 0x80) >> 7)) & 0x1ff; + INT32 scrollx = (((scrl[0x09] & 0x30) << 4) | ((scrl[0x0a] & 0x7f) << 1) | ((scrl[0x0a] & 0x80) >> 7)) & 0x1ff; + + UINT16 *dest = pTransDraw; + + for (INT32 sy = 0; sy < nScreenHeight; sy++, dest += nScreenWidth) + { + INT32 scrolly_0 = (scrolly+sy+16) & 0x1ff; + + for (INT32 sx = 0; sx < nScreenWidth + 16; sx+=16) + { + INT32 scrollx_0 = (scrollx+sx) & 0x1ff; + + INT32 offs = ((scrollx_0 >> 4) << 5) | (scrolly_0 >> 4); + + INT32 code = vram[offs]; + INT32 color = code >> 12; + code = (code & 0x0fff) | (*bg_bankbase * 0x1000); + + { + INT32 romoff = ((scrolly_0 & 0x0f) << 4); + + UINT8 *rom = DrvGfxROM1 + (code * 0x100) + romoff; + + color <<= 6; + + INT32 xx = sx - (scrollx_0 & 0x0f); + + for (INT32 x = 0; x < 16; x++, xx++) + { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = rom[x]; + + if ((pxl & 0x20) == priority) { + pxl |= color; + if (pxl & 0x10) pxl += 0x400; + pxl = (pxl & 0x000f) | ((pxl & 0xffc0) >> 2); + + dest[xx] = pxl; + } + } + } + } + } +} + +static void draw_fg_layer() +{ + if (*fg_enable == 0) return; + + UINT16 *scrl = (UINT16*)DrvScrRAM; + UINT16 *vram = (UINT16*)DrvFgRAM; + + INT32 scrolly = (((scrl[0x11] & 0x30) << 4) | ((scrl[0x12] & 0x7f) << 1) | ((scrl[0x12] & 0x80) >> 7)) & 0x1ff; + INT32 scrollx = (((scrl[0x19] & 0x30) << 4) | ((scrl[0x1a] & 0x7f) << 1) | ((scrl[0x1a] & 0x80) >> 7)) & 0x1ff; + + scrolly += 16; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sy = (offs & 0x1f) << 4; + INT32 sx = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 512; + sy -= scrolly; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + code = (code & 0xfff) | (*fg_bankbase * 0x1000); + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x200, DrvGfxROM2); + } +} + +static void draw_tx_layer() +{ + UINT16 *vram = (UINT16*)DrvTxtRAM; + + for (INT32 offs = (32 * 2); offs < (32 * 32) - (32 * 2); offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = ((offs >> 5) << 3) - 16; + + INT32 code = vram[offs]; + INT32 color = (code >> 8) & 0x0f; + code = (code & 0x00ff) | ((code & 0xc000) >> 6); + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 15, 0x500, DrvGfxROM0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000 / 2; i++) { + palette_update_entry(i); + } + DrvRecalc = 0; + } + + if ((nBurnLayer & 1) == 0) { + BurnTransferClear(); + } + + if (nSpriteEnable & 1) draw_sprites(0); // ? + if (nBurnLayer & 1) draw_bg_layer(0x00); + if (nSpriteEnable & 2) draw_sprites(1); + if (nBurnLayer & 2) draw_bg_layer(0x20); + if (nSpriteEnable & 4) draw_sprites(2); + if (nBurnLayer & 4) draw_fg_layer(); + if (nSpriteEnable & 8) draw_sprites(3); + if (nBurnLayer & 8) draw_tx_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + VezNewFrame(); + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 2); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + seibu_coin_input = (DrvJoy3[0] & 1) | ((DrvJoy3[1] & 1) << 1); + } + + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + + VezOpen(0); + nCyclesDone[0] += VezRun(nSegment); + if (i == (nInterleave-1)) VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + + VezClose(); + + VezOpen(1); + nCyclesDone[1] += VezRun(nSegment); + if (i == (nInterleave-1)) VezSetIRQLineAndVector(0, 0xc8/4, VEZ_IRQSTATUS_ACK); + VezClose(); + + nSegment = nCyclesTotal[2] / nInterleave; + nCyclesDone[2] += nSegment; + BurnTimerUpdateYM3812(nSegment * (i+1)); + } + + BurnTimerEndFrameYM3812(nCyclesTotal[2]); + + if (pBurnSoundOut) { + seibu_sound_update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + + return 0; +} + + + + + +// Dynamite Duke (Japan) + +static struct BurnRomInfo dyndukeRomDesc[] = { + { "1.cd8", 0x10000, 0xa5e2a95a, 1 | BRF_PRG | BRF_ESS }, // 0 V30 #0 Code + { "2.cd7", 0x10000, 0x7e51af22, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.e8", 0x20000, 0x98b9d243, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4.e7", 0x20000, 0x4f575177, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "5.p8", 0x10000, 0x883d319c, 2 | BRF_PRG | BRF_ESS }, // 4 V30 #1 Code + { "6.p7", 0x10000, 0xd94cb4ff, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "8.w8", 0x10000, 0x3c29480b, 3 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "9.5k", 0x04000, 0xf2bc9af4, 4 | BRF_GRA }, // 7 Character Tiles + { "10.34k", 0x04000, 0xc2a9f19b, 4 | BRF_GRA }, // 8 + + { "dd.a2", 0x40000, 0x598f343f, 5 | BRF_GRA }, // 9 Background Tiles + { "dd.b2", 0x40000, 0x41a9088d, 5 | BRF_GRA }, // 10 + { "dd.c2", 0x40000, 0xcc341b42, 5 | BRF_GRA }, // 11 + { "dd.d2", 0x40000, 0x4752b4d7, 5 | BRF_GRA }, // 12 + { "dd.de3", 0x40000, 0x44a4cb62, 5 | BRF_GRA }, // 13 + { "dd.ef3", 0x40000, 0xaa8aee1a, 5 | BRF_GRA }, // 14 + + { "dd.mn3", 0x40000, 0x2ee0ca98, 6 | BRF_GRA }, // 15 Foreground Tiles + { "dd.mn4", 0x40000, 0x6c71e2df, 6 | BRF_GRA }, // 16 + { "dd.n45", 0x40000, 0x85d918e1, 6 | BRF_GRA }, // 17 + { "dd.mn5", 0x40000, 0xe71e34df, 6 | BRF_GRA }, // 18 + + { "dd.n1", 0x40000, 0xcf1db927, 7 | BRF_GRA }, // 19 Sprites + { "dd.n2", 0x40000, 0x5328150f, 7 | BRF_GRA }, // 20 + { "dd.m1", 0x40000, 0x80776452, 7 | BRF_GRA }, // 21 + { "dd.m2", 0x40000, 0xff61a573, 7 | BRF_GRA }, // 22 + { "dd.e1", 0x40000, 0x84a0b87c, 7 | BRF_GRA }, // 23 + { "dd.e2", 0x40000, 0xa9585df2, 7 | BRF_GRA }, // 24 + { "dd.f1", 0x40000, 0x9aed24ba, 7 | BRF_GRA }, // 25 + { "dd.f2", 0x40000, 0x3eb5783f, 7 | BRF_GRA }, // 26 + + { "7.x10", 0x10000, 0x9cbc7b41, 8 | BRF_SND }, // 27 Samples +}; + +STD_ROM_PICK(dynduke) +STD_ROM_FN(dynduke) + +static INT32 dyndukeInit() +{ + return DrvInit(map_master_cpu); +} + +struct BurnDriver BurnDrvDynduke = { + "dynduke", NULL, NULL, NULL, "1989", + "Dynamite Duke (Japan)\0", NULL, "Seibu Kaihatsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, dyndukeRomInfo, dyndukeRomName, NULL, NULL, DyndukeInputInfo, DyndukeDIPInfo, + dyndukeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// Dynamite Duke (US) + +static struct BurnRomInfo dyndukefRomDesc[] = { + { "1.cd8", 0x10000, 0xa5e2a95a, 1 | BRF_PRG | BRF_ESS }, // 0 V30 #0 Code + { "2.cd7", 0x10000, 0x7e51af22, 1 | BRF_PRG | BRF_ESS }, // 1 + { "dd3.ef8", 0x20000, 0xa56f8692, 1 | BRF_PRG | BRF_ESS }, // 2 + { "dd4.ef7", 0x20000, 0xee4b87b3, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "5.p8", 0x10000, 0x883d319c, 2 | BRF_PRG | BRF_ESS }, // 4 V30 #1 Code + { "6.p7", 0x10000, 0xd94cb4ff, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "8.w8", 0x10000, 0x3c29480b, 3 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "9.5k", 0x04000, 0xf2bc9af4, 4 | BRF_GRA }, // 7 Character Tiles + { "10.34k", 0x04000, 0xc2a9f19b, 4 | BRF_GRA }, // 8 + + { "dd.a2", 0x40000, 0x598f343f, 5 | BRF_GRA }, // 9 Background Tiles + { "dd.b2", 0x40000, 0x41a9088d, 5 | BRF_GRA }, // 10 + { "dd.c2", 0x40000, 0xcc341b42, 5 | BRF_GRA }, // 11 + { "dd.d2", 0x40000, 0x4752b4d7, 5 | BRF_GRA }, // 12 + { "dd.de3", 0x40000, 0x44a4cb62, 5 | BRF_GRA }, // 13 + { "dd.ef3", 0x40000, 0xaa8aee1a, 5 | BRF_GRA }, // 14 + + { "dd.mn3", 0x40000, 0x2ee0ca98, 6 | BRF_GRA }, // 15 Foreground Tiles + { "dd.mn4", 0x40000, 0x6c71e2df, 6 | BRF_GRA }, // 16 + { "dd.n45", 0x40000, 0x85d918e1, 6 | BRF_GRA }, // 17 + { "dd.mn5", 0x40000, 0xe71e34df, 6 | BRF_GRA }, // 18 + + { "dd.n1", 0x40000, 0xcf1db927, 7 | BRF_GRA }, // 19 Sprites + { "dd.n2", 0x40000, 0x5328150f, 7 | BRF_GRA }, // 20 + { "dd.m1", 0x40000, 0x80776452, 7 | BRF_GRA }, // 21 + { "dd.m2", 0x40000, 0xff61a573, 7 | BRF_GRA }, // 22 + { "dd.e1", 0x40000, 0x84a0b87c, 7 | BRF_GRA }, // 23 + { "dd.e2", 0x40000, 0xa9585df2, 7 | BRF_GRA }, // 24 + { "dd.f1", 0x40000, 0x9aed24ba, 7 | BRF_GRA }, // 25 + { "dd.f2", 0x40000, 0x3eb5783f, 7 | BRF_GRA }, // 26 + + { "7.x10", 0x10000, 0x9cbc7b41, 8 | BRF_SND }, // 27 Samples +}; + +STD_ROM_PICK(dyndukef) +STD_ROM_FN(dyndukef) + +struct BurnDriver BurnDrvDyndukef = { + "dyndukef", "dynduke", NULL, NULL, "1989", + "Dynamite Duke (US)\0", NULL, "Seibu Kaihatsu (Fabtek license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, dyndukefRomInfo, dyndukefRomName, NULL, NULL, DyndukeInputInfo, DyndukeDIPInfo, + dyndukeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// The Double Dynamites (Japan) + +static struct BurnRomInfo dbldynRomDesc[] = { + { "1.cd8", 0x10000, 0xa5e2a95a, 1 | BRF_PRG | BRF_ESS }, // 0 V30 #0 Code + { "2.cd7", 0x10000, 0x7e51af22, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3x.e8", 0x20000, 0x633db1fe, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4x.e7", 0x20000, 0xdc9ee263, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "5x.p8", 0x10000, 0xea56d719, 2 | BRF_PRG | BRF_ESS }, // 4 V30 #1 Code + { "6x.p7", 0x10000, 0x9ffa0ecd, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "8x.w8", 0x10000, 0xf4066081, 3 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "9x.5k", 0x04000, 0x913709e3, 4 | BRF_GRA }, // 7 Character Tiles + { "10x.34k", 0x04000, 0x405daacb, 4 | BRF_GRA }, // 8 + + { "dd.a2", 0x40000, 0x598f343f, 5 | BRF_GRA }, // 9 Background Tiles + { "dd.b2", 0x40000, 0x41a9088d, 5 | BRF_GRA }, // 10 + { "dd.c2", 0x40000, 0xcc341b42, 5 | BRF_GRA }, // 11 + { "dd.d2", 0x40000, 0x4752b4d7, 5 | BRF_GRA }, // 12 + { "dd.de3", 0x40000, 0x44a4cb62, 5 | BRF_GRA }, // 13 + { "dd.ef3", 0x40000, 0xaa8aee1a, 5 | BRF_GRA }, // 14 + + { "dd.mn3", 0x40000, 0x2ee0ca98, 6 | BRF_GRA }, // 15 Foreground Tiles + { "dd.mn4", 0x40000, 0x6c71e2df, 6 | BRF_GRA }, // 16 + { "dd.n45", 0x40000, 0x85d918e1, 6 | BRF_GRA }, // 17 + { "dd.mn5", 0x40000, 0xe71e34df, 6 | BRF_GRA }, // 18 + + { "dd.n1", 0x40000, 0xcf1db927, 7 | BRF_GRA }, // 19 Sprites + { "dd.n2", 0x40000, 0x5328150f, 7 | BRF_GRA }, // 20 + { "dd.m1", 0x40000, 0x80776452, 7 | BRF_GRA }, // 21 + { "dd.m2", 0x40000, 0xff61a573, 7 | BRF_GRA }, // 22 + { "dd.e1", 0x40000, 0x84a0b87c, 7 | BRF_GRA }, // 23 + { "dd.e2", 0x40000, 0xa9585df2, 7 | BRF_GRA }, // 24 + { "dd.f1", 0x40000, 0x9aed24ba, 7 | BRF_GRA }, // 25 + { "dd.f2", 0x40000, 0x3eb5783f, 7 | BRF_GRA }, // 26 + + { "7.x10", 0x10000, 0x9cbc7b41, 8 | BRF_SND }, // 27 Samples +}; + +STD_ROM_PICK(dbldyn) +STD_ROM_FN(dbldyn) + +static INT32 dbldynInit() +{ + return DrvInit(map_masterj_cpu); +} + +struct BurnDriver BurnDrvDbldyn = { + "dbldyn", "dynduke", NULL, NULL, "1989", + "The Double Dynamites (Japan)\0", NULL, "Seibu Kaihatsu", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, dbldynRomInfo, dbldynRomName, NULL, NULL, DyndukeInputInfo, DyndukeDIPInfo, + dbldynInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; + + +// The Double Dynamites (US) + +static struct BurnRomInfo dbldynfRomDesc[] = { + { "1.cd8", 0x10000, 0xa5e2a95a, 1 | BRF_PRG | BRF_ESS }, // 0 V30 #0 Code + { "2.cd7", 0x10000, 0x7e51af22, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.8e", 0x20000, 0x9b785028, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4.7e", 0x20000, 0x0d0f6350, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "5x.p8", 0x10000, 0xea56d719, 2 | BRF_PRG | BRF_ESS }, // 4 V30 #1 Code + { "6x.p7", 0x10000, 0x9ffa0ecd, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "8x.w8", 0x10000, 0xf4066081, 3 | BRF_PRG | BRF_ESS }, // 6 Z80 Code + + { "9x.5k", 0x04000, 0x913709e3, 4 | BRF_GRA }, // 7 Character Tiles + { "10x.34k", 0x04000, 0x405daacb, 4 | BRF_GRA }, // 8 + + { "dd.a2", 0x40000, 0x598f343f, 5 | BRF_GRA }, // 9 Background Tiles + { "dd.b2", 0x40000, 0x41a9088d, 5 | BRF_GRA }, // 10 + { "dd.c2", 0x40000, 0xcc341b42, 5 | BRF_GRA }, // 11 + { "dd.d2", 0x40000, 0x4752b4d7, 5 | BRF_GRA }, // 12 + { "dd.de3", 0x40000, 0x44a4cb62, 5 | BRF_GRA }, // 13 + { "dd.ef3", 0x40000, 0xaa8aee1a, 5 | BRF_GRA }, // 14 + + { "dd.mn3", 0x40000, 0x2ee0ca98, 6 | BRF_GRA }, // 15 Foreground Tiles + { "dd.mn4", 0x40000, 0x6c71e2df, 6 | BRF_GRA }, // 16 + { "dd.n45", 0x40000, 0x85d918e1, 6 | BRF_GRA }, // 17 + { "dd.mn5", 0x40000, 0xe71e34df, 6 | BRF_GRA }, // 18 + + { "dd.n1", 0x40000, 0xcf1db927, 7 | BRF_GRA }, // 19 Sprites + { "dd.n2", 0x40000, 0x5328150f, 7 | BRF_GRA }, // 20 + { "dd.m1", 0x40000, 0x80776452, 7 | BRF_GRA }, // 21 + { "dd.m2", 0x40000, 0xff61a573, 7 | BRF_GRA }, // 22 + { "dd.e1", 0x40000, 0x84a0b87c, 7 | BRF_GRA }, // 23 + { "dd.e2", 0x40000, 0xa9585df2, 7 | BRF_GRA }, // 24 + { "dd.f1", 0x40000, 0x9aed24ba, 7 | BRF_GRA }, // 25 + { "dd.f2", 0x40000, 0x3eb5783f, 7 | BRF_GRA }, // 26 + + { "7.x10", 0x10000, 0x9cbc7b41, 8 | BRF_SND }, // 27 Samples +}; + +STD_ROM_PICK(dbldynf) +STD_ROM_FN(dbldynf) + +struct BurnDriver BurnDrvDbldynf = { + "dbldynf", "dynduke", NULL, NULL, "1989", + "The Double Dynamites (US)\0", NULL, "Seibu Kaihatsu (Fabtek license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, dbldynfRomInfo, dbldynfRomName, NULL, NULL, DyndukeInputInfo, DyndukeDIPInfo, + dyndukeInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x800, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_epos.cpp b/src/burn/drivers/misc_pre90s/d_epos.cpp new file mode 100644 index 00000000..47ca6c1d --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_epos.cpp @@ -0,0 +1,919 @@ +// FB Alpha Epos Tristar Hardware driver module +// Based on MAME driver by Zsolt Vasvari + +#include "tiles_generic.h" +#include "8255ppi.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvVidRAM; +static UINT32 *Palette; +static UINT32 *DrvPalette; + +static INT16* pAY8910Buffer[3]; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static UINT8 *DrvPaletteBank; +static UINT8 *DealerZ80Bank; +static UINT8 *DealerZ80Bank2; + +static struct BurnInputInfo MegadonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Megadon) + +static struct BurnInputInfo SuprglobInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Suprglob) + +static struct BurnInputInfo DealerInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 6, "p1 coin" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy2 + 3, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Dealer) + + +static struct BurnDIPInfo MegadonDIPList[]= +{ + {0x07, 0xff, 0xff, 0x28, NULL }, + {0x08, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x07, 0x01, 0x01, 0x00, "1 Coin 1 Credits " }, + {0x07, 0x01, 0x01, 0x01, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Fuel Consumption" }, + {0x07, 0x01, 0x02, 0x00, "Slow" }, + {0x07, 0x01, 0x02, 0x02, "Fast" }, + + {0 , 0xfe, 0 , 2, "Rotation" }, + {0x07, 0x01, 0x04, 0x04, "Slow" }, + {0x07, 0x01, 0x04, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2, "ERG" }, + {0x07, 0x01, 0x08, 0x08, "Easy" }, + {0x07, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Enemy Fire Rate" }, + {0x07, 0x01, 0x20, 0x20, "Slow" }, + {0x07, 0x01, 0x20, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x07, 0x01, 0x50, 0x00, "3" }, + {0x07, 0x01, 0x50, 0x10, "4" }, + {0x07, 0x01, 0x50, 0x40, "5" }, + {0x07, 0x01, 0x50, 0x50, "6" }, + + {0 , 0xfe, 0 , 2, "Game Mode" }, + {0x07, 0x01, 0x80, 0x00, "Arcade" }, + {0x07, 0x01, 0x80, 0x80, "Contest" }, +}; + +STDDIPINFO(Megadon) + +static struct BurnDIPInfo SuprglobDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0x00, NULL }, + {0x0A, 0xff, 0xff, 0xbe, NULL }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x09, 0x01, 0x01, 0x00, "1 Coin 1 Credits " }, + {0x09, 0x01, 0x01, 0x01, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x09, 0x01, 0x08, 0x00, "10000 + Difficulty * 10000" }, + {0x09, 0x01, 0x08, 0x08, "90000 + Difficulty * 10000" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x09, 0x01, 0x26, 0x00, "1" }, + {0x09, 0x01, 0x26, 0x02, "2" }, + {0x09, 0x01, 0x26, 0x20, "3" }, + {0x09, 0x01, 0x26, 0x22, "4" }, + {0x09, 0x01, 0x26, 0x04, "5" }, + {0x09, 0x01, 0x26, 0x06, "6" }, + {0x09, 0x01, 0x26, 0x24, "7" }, + {0x09, 0x01, 0x26, 0x26, "8" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x09, 0x01, 0x50, 0x00, "3" }, + {0x09, 0x01, 0x50, 0x10, "4" }, + {0x09, 0x01, 0x50, 0x40, "5" }, + {0x09, 0x01, 0x50, 0x50, "6" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x09, 0x01, 0x80, 0x80, "Off" }, + {0x09, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Suprglob) + +static struct BurnDIPInfo IgmoDIPList[]= +{ + {0x09, 0xff, 0xff, 0x00, NULL }, + {0x0A, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x09, 0x01, 0x01, 0x00, "1 Coin 1 Credits " }, + {0x09, 0x01, 0x01, 0x01, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x09, 0x01, 0x22, 0x00, "20000" }, + {0x09, 0x01, 0x22, 0x02, "40000" }, + {0x09, 0x01, 0x22, 0x20, "60000" }, + {0x09, 0x01, 0x22, 0x22, "80000" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x09, 0x01, 0x50, 0x00, "3" }, + {0x09, 0x01, 0x50, 0x10, "4" }, + {0x09, 0x01, 0x50, 0x40, "5" }, + {0x09, 0x01, 0x50, 0x50, "6" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x09, 0x01, 0x8c, 0x00, "1" }, + {0x09, 0x01, 0x8c, 0x04, "2" }, + {0x09, 0x01, 0x8c, 0x08, "3" }, + {0x09, 0x01, 0x8c, 0x0c, "4" }, + {0x09, 0x01, 0x8c, 0x80, "5" }, + {0x09, 0x01, 0x8c, 0x84, "6" }, + {0x09, 0x01, 0x8c, 0x88, "7" }, + {0x09, 0x01, 0x8c, 0x8c, "8" }, +}; + +STDDIPINFO(Igmo) + +static struct BurnDIPInfo CatapultDIPList[]= +{ + {0x09, 0xff, 0xff, 0x00, NULL }, + {0x0A, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x09, 0x01, 0x01, 0x00, "1 Coin 1 Credits " }, + {0x09, 0x01, 0x01, 0x01, "1 Coin 2 Credits " }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x09, 0x01, 0x0c, 0x00, "20000" }, + {0x09, 0x01, 0x0c, 0x04, "40000" }, + {0x09, 0x01, 0x0c, 0x08, "60000" }, + {0x09, 0x01, 0x0c, 0x0c, "80000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x09, 0x01, 0x22, 0x00, "1" }, + {0x09, 0x01, 0x22, 0x02, "2" }, + {0x09, 0x01, 0x22, 0x20, "3" }, + {0x09, 0x01, 0x22, 0x22, "4" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x09, 0x01, 0x50, 0x00, "3" }, + {0x09, 0x01, 0x50, 0x10, "4" }, + {0x09, 0x01, 0x50, 0x40, "5" }, + {0x09, 0x01, 0x50, 0x50, "6" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x09, 0x01, 0x80, 0x80, "Off" }, + {0x09, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Catapult) + +static struct BurnDIPInfo DealerDIPList[]= +{ + {0x08, 0xff, 0xff, 0xfe, NULL }, + {0x09, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x08, 0x01, 0x01, 0x01, "Off" }, + {0x08, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x08, 0x01, 0x02, 0x02, "Off" }, + {0x08, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x08, 0x01, 0x40, 0x40, "Upright" }, + {0x08, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x08, 0x01, 0x80, 0x80, "Off" }, + {0x08, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Dealer) + +UINT8 __fastcall epos_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return DrvDips[0]; + + case 0x01: + return DrvInputs[0]; + + case 0x02: + return DrvInputs[1]; + + case 0x03: + return 0; + } + + return 0; +} + +void __fastcall epos_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + break; + + case 0x01: + *DrvPaletteBank = (data << 1) & 0x10; + break; + + case 0x02: + AY8910Write(0, 1, data); + break; + + case 0x06: + AY8910Write(0, 0, data); + break; + } +} + +static void dealer_set_bank() +{ + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM + (*DealerZ80Bank << 16)); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM + (*DealerZ80Bank << 16)); +} + +static void dealer_bankswitch(INT32 offset) +{ + INT32 nBank = *DealerZ80Bank; + + if (offset & 4) { + nBank = (nBank + 1) & 3; + } else { + nBank = (nBank - 1) & 3; + } + + *DealerZ80Bank = nBank; + + dealer_set_bank(); +} + +static void dealer_bankswitch2(INT32 data) +{ + *DealerZ80Bank2 = data & 1; + + INT32 nBank = 0x6000 + ((data & 1) << 12); + ZetMapArea(0x6000, 0x6fff, 0, DrvZ80ROM + nBank); + ZetMapArea(0x6000, 0x6fff, 2, DrvZ80ROM + nBank); +} + +UINT8 __fastcall dealer_read_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x10: + case 0x11: + case 0x12: + case 0x13: + return ppi8255_r(0, port & 3); + + case 0x38: + return DrvDips[0]; + } + + return 0; +} + +void __fastcall dealer_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x10: + case 0x11: + case 0x12: + case 0x13: + ppi8255_w(0, port & 3, data); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + dealer_bankswitch(port & 7); + break; + } +} + +UINT8 DealerPPIReadA() +{ + return DrvInputs[1]; +} + +void DealerPPIWriteC(UINT8 data) +{ + dealer_bankswitch2(data); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + dealer_set_bank(); + dealer_bankswitch2(0); + ZetClose(); + + AY8910Reset(0); + + return 0; +} + +static void DrvPaletteInit(INT32 num) +{ + UINT8 prom[32] = { // in case the set lacks a prom dump + 0x00, 0xE1, 0xC3, 0xFC, 0xEC, 0xF8, 0x34, 0xFF, + 0x17, 0xF0, 0xEE, 0xEF, 0xAC, 0xC2, 0x1C, 0x07, + 0x00, 0xE1, 0xC3, 0xFC, 0xEC, 0xF8, 0x34, 0xFF, + 0x17, 0xF0, 0xEE, 0xEF, 0xAC, 0xC2, 0x1C, 0x07 + }; + + memcpy (DrvColPROM, prom, 32); + + BurnLoadRom(DrvColPROM, num, 1); + + for (INT32 i = 0; i < 0x20; i++) { + Palette[i] = BITSWAP24(DrvColPROM[i], 7,6,5,7,6,6,7,5,4,3,2,4,3,3,4,2,1,0,1,0,1,1,0,1); + } +} + +static void DealerDecode() +{ + for (INT32 i = 0;i < 0x8000;i++) + DrvZ80ROM[i + 0x00000] = BITSWAP08(DrvZ80ROM[i] ^ 0xbd, 2,6,4,0,5,7,1,3); + + for (INT32 i = 0;i < 0x8000;i++) + DrvZ80ROM[i + 0x10000] = BITSWAP08(DrvZ80ROM[i] ^ 0x00, 7,5,4,6,3,2,1,0); + + for (INT32 i = 0;i < 0x8000;i++) + DrvZ80ROM[i + 0x20000] = BITSWAP08(DrvZ80ROM[i] ^ 0x01, 7,6,5,4,3,0,2,1); + + for (INT32 i = 0;i < 0x8000;i++) + DrvZ80ROM[i + 0x30000] = BITSWAP08(DrvZ80ROM[i] ^ 0x01, 7,5,4,6,3,0,2,1); +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x040000; + + DrvColPROM = Next; Next += 0x000020; + + Palette = (UINT32*)Next; Next += 0x0020 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0020 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16 *)Next; Next += nBurnSoundLen * sizeof(INT16); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x001000; + DrvVidRAM = Next; Next += 0x008000; + + DrvPaletteBank = Next; Next += 0x000001; + DealerZ80Bank = Next; Next += 0x000001; + DealerZ80Bank2 = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x1000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x3000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x4000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x5000, 5, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x6000, 6, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x7000, 7, 1)) return 1; + + DrvPaletteInit(8); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x77ff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x77ff, 2, DrvZ80ROM); + ZetMapArea(0x7800, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7800, 0x7fff, 2, DrvZ80RAM); + ZetMapArea(0x8000, 0xffff, 0, DrvVidRAM); + ZetMapArea(0x8000, 0xffff, 1, DrvVidRAM); + ZetMapArea(0x8000, 0xffff, 2, DrvVidRAM); + ZetSetInHandler(epos_read_port); + ZetSetOutHandler(epos_write_port); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 2750000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DealerInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x6000, 3, 1)) return 1; + + DrvPaletteInit(4); + DealerDecode(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x6fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x6fff, 2, DrvZ80ROM); + ZetMapArea(0x7000, 0x7fff, 0, DrvZ80RAM); + ZetMapArea(0x7000, 0x7fff, 1, DrvZ80RAM); + ZetMapArea(0x7000, 0x7fff, 2, DrvZ80RAM); + ZetMapArea(0x8000, 0xffff, 0, DrvVidRAM); + ZetMapArea(0x8000, 0xffff, 1, DrvVidRAM); + ZetMapArea(0x8000, 0xffff, 2, DrvVidRAM); + ZetSetInHandler(dealer_read_port); + ZetSetOutHandler(dealer_write_port); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 2750000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + ppi8255_init(1); + PPI0PortReadA = DealerPPIReadA; + PPI0PortWriteC = DealerPPIWriteC; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + AY8910Exit(0); + ZetExit(); + + if (PPI0PortReadA) { + ppi8255_exit(); + } + + BurnFree(AllMem); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x20; i++) { + INT32 rgb = Palette[i]; + r = (rgb >> 16) & 0xff; + g = (rgb >> 8) & 0xff; + b = (rgb >> 0) & 0xff; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + } + + for (INT32 i = 0; i < 0x8000; i++) + { + INT32 x = (i % 136) << 1; + INT32 y = (i / 136); + if (y > 235) break; + + pTransDraw[(y * nScreenWidth) + x + 0] = *DrvPaletteBank | ((DrvVidRAM[i] >> 0) & 0x0f); + pTransDraw[(y * nScreenWidth) + x + 1] = *DrvPaletteBank | ((DrvVidRAM[i] >> 4) & 0x0f); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvDips[1]; + DrvInputs[1] = 0xff; + for (INT32 i = 0; i < 8; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + ZetOpen(0); + ZetRun(2750000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + + if (PPI0PortReadA) { + ppi8255_scan(); + + if (nAction & ACB_WRITE) { + dealer_set_bank(); + dealer_bankswitch2(*DealerZ80Bank2); + } + } + } + + return 0; +} + + +// Megadon + +static struct BurnRomInfo megadonRomDesc[] = { + { "2732u10b.bin", 0x1000, 0xaf8fbe80, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "2732u09b.bin", 0x1000, 0x097d1e73, BRF_ESS | BRF_PRG }, // 1 + { "2732u08b.bin", 0x1000, 0x526784da, BRF_ESS | BRF_PRG }, // 2 + { "2732u07b.bin", 0x1000, 0x5b060910, BRF_ESS | BRF_PRG }, // 3 + { "2732u06b.bin", 0x1000, 0x8ac8af6d, BRF_ESS | BRF_PRG }, // 4 + { "2732u05b.bin", 0x1000, 0x052bb603, BRF_ESS | BRF_PRG }, // 5 + { "2732u04b.bin", 0x1000, 0x9b8b7e92, BRF_ESS | BRF_PRG }, // 6 + { "2716u11b.bin", 0x0800, 0x599b8b61, BRF_ESS | BRF_PRG }, // 7 + + { "74s288.bin", 0x0020, 0xc779ea99, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(megadon) +STD_ROM_FN(megadon) + +struct BurnDriver BurnDrvMegadon = { + "megadon", NULL, NULL, NULL, "1982", + "Megadon\0", NULL, "Epos Corporation (Photar Industries License)", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, megadonRomInfo, megadonRomName, NULL, NULL, MegadonInputInfo, MegadonDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// Catapult + +static struct BurnRomInfo catapultRomDesc[] = { + { "co3223.u10", 0x1000, 0x50abcfd2, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "co3223.u09", 0x1000, 0xfd5a9a1c, BRF_ESS | BRF_PRG }, // 1 + { "co3223.u08", 0x1000, 0x4bfc36f3, BRF_ESS | BRF_PRG }, // 2 + { "co3223.u07", 0x1000, 0x4113bb99, BRF_ESS | BRF_PRG }, // 3 + { "co3223.u06", 0x1000, 0x966bb9f5, BRF_ESS | BRF_PRG }, // 4 + { "co3223.u05", 0x1000, 0x65f9fb9a, BRF_ESS | BRF_PRG }, // 5 + { "co3223.u04", 0x1000, 0x648453bc, BRF_ESS | BRF_PRG }, // 6 + { "co3223.u11", 0x0800, 0x08fb8c28, BRF_ESS | BRF_PRG }, // 7 + + { "co3223.u66", 0x0020, 0xe7de76a7, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(catapult) +STD_ROM_FN(catapult) + +struct BurnDriverD BurnDrvCatapult = { + "catapult", NULL, NULL, NULL, "1982", + "Catapult\0", "Bad dump", "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, catapultRomInfo, catapultRomName, NULL, NULL, SuprglobInputInfo, CatapultDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// Super Glob + +static struct BurnRomInfo suprglobRomDesc[] = { + { "u10", 0x1000, 0xc0141324, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "u9", 0x1000, 0x58be8128, BRF_ESS | BRF_PRG }, // 1 + { "u8", 0x1000, 0x6d088c16, BRF_ESS | BRF_PRG }, // 2 + { "u7", 0x1000, 0xb2768203, BRF_ESS | BRF_PRG }, // 3 + { "u6", 0x1000, 0x976c8f46, BRF_ESS | BRF_PRG }, // 4 + { "u5", 0x1000, 0x340f5290, BRF_ESS | BRF_PRG }, // 5 + { "u4", 0x1000, 0x173bd589, BRF_ESS | BRF_PRG }, // 6 + { "u11", 0x0800, 0xd45b740d, BRF_ESS | BRF_PRG }, // 7 + + { "82s123.u66", 0x0020, 0xf4f6ddc5, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(suprglob) +STD_ROM_FN(suprglob) + +struct BurnDriver BurnDrvSuprglob = { + "suprglob", NULL, NULL, NULL, "1983", + "Super Glob\0", NULL, "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, suprglobRomInfo, suprglobRomName, NULL, NULL, SuprglobInputInfo, SuprglobDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// The Glob + +static struct BurnRomInfo theglobRomDesc[] = { + { "globu10.bin", 0x1000, 0x08fdb495, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "globu9.bin", 0x1000, 0x827cd56c, BRF_ESS | BRF_PRG }, // 1 + { "globu8.bin", 0x1000, 0xd1219966, BRF_ESS | BRF_PRG }, // 2 + { "globu7.bin", 0x1000, 0xb1649da7, BRF_ESS | BRF_PRG }, // 3 + { "globu6.bin", 0x1000, 0xb3457e67, BRF_ESS | BRF_PRG }, // 4 + { "globu5.bin", 0x1000, 0x89d582cd, BRF_ESS | BRF_PRG }, // 5 + { "globu4.bin", 0x1000, 0x7ee9fdeb, BRF_ESS | BRF_PRG }, // 6 + { "globu11.bin", 0x0800, 0x9e05dee3, BRF_ESS | BRF_PRG }, // 7 + + { "82s123.u66", 0x0020, 0xf4f6ddc5, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(theglob) +STD_ROM_FN(theglob) + +struct BurnDriver BurnDrvTheglob = { + "theglob", "suprglob", NULL, NULL, "1983", + "The Glob\0", NULL, "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, theglobRomInfo, theglobRomName, NULL, NULL, SuprglobInputInfo, SuprglobDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// The Glob (earlier) + +static struct BurnRomInfo theglob2RomDesc[] = { + { "611293.u10", 0x1000, 0x870af7ce, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "611293.u9", 0x1000, 0xa3679782, BRF_ESS | BRF_PRG }, // 1 + { "611293.u8", 0x1000, 0x67499d1a, BRF_ESS | BRF_PRG }, // 2 + { "611293.u7", 0x1000, 0x55e53aac, BRF_ESS | BRF_PRG }, // 3 + { "611293.u6", 0x1000, 0xc64ad743, BRF_ESS | BRF_PRG }, // 4 + { "611293.u5", 0x1000, 0xf93c3203, BRF_ESS | BRF_PRG }, // 5 + { "611293.u4", 0x1000, 0xceea0018, BRF_ESS | BRF_PRG }, // 6 + { "611293.u11", 0x0800, 0x6ac83f9b, BRF_ESS | BRF_PRG }, // 7 + + { "82s123.u66", 0x0020, 0xf4f6ddc5, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(theglob2) +STD_ROM_FN(theglob2) + +struct BurnDriver BurnDrvTheglob2 = { + "theglob2", "suprglob", NULL, NULL, "1983", + "The Glob (earlier)\0", NULL, "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, theglob2RomInfo, theglob2RomName, NULL, NULL, SuprglobInputInfo, SuprglobDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// The Glob (set 3) + +static struct BurnRomInfo theglob3RomDesc[] = { + { "theglob3.u10", 0x1000, 0x969cfaf6, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "theglob3.u9", 0x1000, 0x8e6c010a, BRF_ESS | BRF_PRG }, // 1 + { "theglob3.u8", 0x1000, 0x1c1ca5c8, BRF_ESS | BRF_PRG }, // 2 + { "theglob3.u7", 0x1000, 0xa54b9d22, BRF_ESS | BRF_PRG }, // 3 + { "theglob3.u6", 0x1000, 0x5a6f82a9, BRF_ESS | BRF_PRG }, // 4 + { "theglob3.u5", 0x1000, 0x72f935db, BRF_ESS | BRF_PRG }, // 5 + { "theglob3.u4", 0x1000, 0x81db53ad, BRF_ESS | BRF_PRG }, // 6 + { "theglob3.u11", 0x0800, 0x0e2e6359, BRF_ESS | BRF_PRG }, // 7 + + { "82s123.u66", 0x0020, 0xf4f6ddc5, BRF_GRA }, // 8 Color PROM +}; + +STD_ROM_PICK(theglob3) +STD_ROM_FN(theglob3) + +struct BurnDriver BurnDrvTheglob3 = { + "theglob3", "suprglob", NULL, NULL, "1983", + "The Glob (set 3)\0", NULL, "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, theglob3RomInfo, theglob3RomName, NULL, NULL, SuprglobInputInfo, SuprglobDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// IGMO + +static struct BurnRomInfo igmoRomDesc[] = { + { "igmo-u10.732", 0x1000, 0xa9f691a4, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "igmo-u9.732", 0x1000, 0x3c133c97, BRF_ESS | BRF_PRG }, // 1 + { "igmo-u8.732", 0x1000, 0x5692f8d8, BRF_ESS | BRF_PRG }, // 2 + { "igmo-u7.732", 0x1000, 0x630ae2ed, BRF_ESS | BRF_PRG }, // 3 + { "igmo-u6.732", 0x1000, 0xd3f20e1d, BRF_ESS | BRF_PRG }, // 4 + { "igmo-u5.732", 0x1000, 0xe26bb391, BRF_ESS | BRF_PRG }, // 5 + { "igmo-u4.732", 0x1000, 0x762a4417, BRF_ESS | BRF_PRG }, // 6 + { "igmo-u11.716", 0x0800, 0x8c675837, BRF_ESS | BRF_PRG }, // 7 + + { "82s123.u66", 0x0020, 0x00000000, BRF_GRA | BRF_NODUMP }, // 8 Color Prom (missing) +}; + +STD_ROM_PICK(igmo) +STD_ROM_FN(igmo) + +struct BurnDriver BurnDrvIgmo = { + "igmo", NULL, NULL, NULL, "1984", + "IGMO\0", "Incorrect Colors", "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, igmoRomInfo, igmoRomName, NULL, NULL, SuprglobInputInfo, IgmoDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// The Dealer + +static struct BurnRomInfo dealerRomDesc[] = { + { "u1.bin", 0x2000, 0xe06f3563, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "u2.bin", 0x2000, 0x726bbbd6, BRF_ESS | BRF_PRG }, // 1 + { "u3.bin", 0x2000, 0xab721455, BRF_ESS | BRF_PRG }, // 2 + { "u4.bin", 0x2000, 0xddb903e4, BRF_ESS | BRF_PRG }, // 3 + + { "82s123.u66", 0x0020, 0x00000000, BRF_GRA | BRF_NODUMP }, // 4 Color Prom (missing) +}; + +STD_ROM_PICK(dealer) +STD_ROM_FN(dealer) + +struct BurnDriver BurnDrvDealer = { + "dealer", NULL, NULL, NULL, "198?", + "The Dealer\0", "No Sound / Incorrect Colors", "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_CASINO, 0, + NULL, dealerRomInfo, dealerRomName, NULL, NULL, DealerInputInfo, DealerDIPInfo, + DealerInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; + + +// Revenger + +static struct BurnRomInfo revengerRomDesc[] = { + { "r06124.u1", 0x2000, 0xfad1a2a5, BRF_ESS | BRF_PRG }, // 0 Z80 code + { "r06124.u2", 0x2000, 0xa8e0ee7b, BRF_ESS | BRF_PRG }, // 1 + { "r06124.u3", 0x2000, 0xcca414a5, BRF_ESS | BRF_PRG }, // 2 + { "r06124.u4", 0x2000, 0x0b81c303, BRF_ESS | BRF_PRG }, // 3 + + { "82s123.u66", 0x0020, 0x00000000, BRF_GRA | BRF_NODUMP }, // 4 Color Prom (missing) +}; + +STD_ROM_PICK(revenger) +STD_ROM_FN(revenger) + +struct BurnDriverD BurnDrvRevenger = { + "revenger", NULL, NULL, NULL, "1984", + "Revenger\0", "Bad dump", "Epos Corporation", "EPOS Tristar", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, revengerRomInfo, revengerRomName, NULL, NULL, DealerInputInfo, DealerDIPInfo, + DealerInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x20, + 236, 272, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_exedexes.cpp b/src/burn/drivers/misc_pre90s/d_exedexes.cpp new file mode 100644 index 00000000..bffa9f43 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_exedexes.cpp @@ -0,0 +1,835 @@ +// FB Alpha Exed Exes driver module +// Based on MAME driver by Richard Davies, Paul Swan, and various others + +#include "tiles_generic.h" +#include "sn76496.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd; +static UINT8 *Rom0, *Rom1, *Gfx0, *Gfx1, *Gfx2, *Gfx3, *Gfx4, *Prom; +static INT16 *pAY8910Buffer[3], *pFMBuffer = NULL; +static UINT32 *Palette, *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *fg_tile_transp; + +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[2], DrvInputs[3], DrvReset; + +static UINT8 exedexes_soundlatch; + +static UINT8 exedexes_txt_enable; +static UINT8 exedexes_obj_enable; +static UINT8 exedexes_bg_enable; +static UINT8 exedexes_fg_enable; + +static UINT16 exedexes_nbg_yscroll; +static UINT16 exedexes_nbg_xscroll; +static UINT16 exedexes_bg_xscroll; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p2 left" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 5, "service" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "1" }, + {0x12, 0x01, 0x0c, 0x04, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x12, 0x01, 0x10, 0x00, "1 Credit" }, + {0x12, 0x01, 0x10, 0x10, "2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x20, 0x00, "English" }, + {0x12, 0x01, 0x20, 0x20, "Japanese" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Drv) + +UINT8 __fastcall exedexes_cpu0_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + case 0xc001: + case 0xc002: + return DrvInputs[address & 3]; + + case 0xc003: + case 0xc004: + return DrvDips[~address & 1]; + } + + return 0; +} + +void __fastcall exedexes_cpu0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc800: + exedexes_soundlatch = data; + break; + + case 0xc804: + exedexes_txt_enable = data >> 7; + break; + + case 0xc806: + break; + + case 0xd800: + exedexes_nbg_yscroll = (exedexes_nbg_yscroll & 0xff00) | (data << 0); + break; + + case 0xd801: + exedexes_nbg_yscroll = (exedexes_nbg_yscroll & 0x00ff) | (data << 8); + break; + + case 0xd802: + exedexes_nbg_xscroll = (exedexes_nbg_xscroll & 0xff00) | (data << 0); + break; + + case 0xd803: + exedexes_nbg_xscroll = (exedexes_nbg_xscroll & 0x00ff) | (data << 8); + break; + + case 0xd804: + exedexes_bg_xscroll = (exedexes_bg_xscroll & 0xff00) | (data << 0); + break; + + case 0xd805: + exedexes_bg_xscroll = (exedexes_bg_xscroll & 0x00ff) | (data << 8); + break; + + case 0xd807: + exedexes_bg_enable = (data >> 4) & 1; + exedexes_fg_enable = (data >> 5) & 1; + exedexes_obj_enable = (data >> 6) & 1; + break; + } +} + +UINT8 __fastcall exedexes_cpu1_read(UINT16 address) +{ + switch (address) + { + case 0x6000: + return exedexes_soundlatch; + } + + return 0; +} + +void __fastcall exedexes_cpu1_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8000: + case 0x8001: + AY8910Write(0, address & 1, data); + break; + + case 0x8002: + case 0x8003: + SN76496Write(address & 1, data); + break; + } +} + +static inline void DrvMakeInputs() +{ + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Rom0 + 0xd000, 0, 0x3000); + memset (Rom1 + 0x4000, 0, 0x0800); + + exedexes_soundlatch = 0; + exedexes_txt_enable = 0; + exedexes_obj_enable = 0; + exedexes_bg_enable = 0; + exedexes_fg_enable = 0; + exedexes_nbg_yscroll = 0; + exedexes_nbg_xscroll = 0; + exedexes_bg_xscroll = 0; + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + AY8910Reset(0); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom0 = Next; Next += 0x10000; + Rom1 = Next; Next += 0x05000; + + Gfx0 = Next; Next += 0x08000; + Gfx1 = Next; Next += 0x10000; + Gfx2 = Next; Next += 0x10000; + Gfx3 = Next; Next += 0x10000; + + Gfx4 = Next; Next += 0x06000; + + Prom = Next; Next += 0x00800; + + fg_tile_transp = Next; Next += 0x00100; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + pFMBuffer = (INT16*)Next; Next += (nBurnSoundLen * 3 * sizeof(INT16)); + + MemEnd = Next; + + return 0; +} + +static INT32 PaletteInit() +{ + UINT32 *tmp = (UINT32*)BurnMalloc(0x100 * sizeof(UINT32)); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x100; i++) + { + INT32 r = Prom[i + 0x000]; + INT32 g = Prom[i + 0x100]; + INT32 b = Prom[i + 0x200]; + + tmp[i] = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b; + } + + Prom += 0x300; + + for (INT32 i = 0; i < 0x100; i++) { + Palette[i] = tmp[Prom[i] | 0xc0]; + } + + for (INT32 i = 0x100; i < 0x200; i++) { + Palette[i] = tmp[Prom[i] | 0x00]; + } + + for (INT32 i = 0x200; i < 0x300; i++) { + Palette[i] = tmp[Prom[i] | 0x40]; + } + + for (INT32 i = 0x300; i < 0x400; i++) { + INT32 entry = Prom[i] | (Prom[i + 0x100] << 4) | 0x80; + Palette[i] = tmp[entry]; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 GraphicsDecode() +{ + static INT32 TilePlanes[2] = { 0x004, 0x000 }; + static INT32 SpriPlanes[4] = { 0x20004, 0x20000, 0x00004, 0x00000 }; + static INT32 TileXOffs[32] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x200, 0x201, 0x202, 0x203, 0x208, 0x209, 0x20a, 0x20b, + 0x400, 0x401, 0x402, 0x403, 0x408, 0x409, 0x40a, 0x40b, + 0x600, 0x601, 0x602, 0x603, 0x608, 0x609, 0x60a, 0x60b }; + static INT32 SpriXOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x100, 0x101, 0x102, 0x103, 0x108, 0x109, 0x10a, 0x10b }; + static INT32 TileYOffs[32] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0, + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, + 0x180, 0x190, 0x1a0, 0x1b0, 0x1c0, 0x1d0, 0x1e0, 0x1f0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x8000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x02000); + + GfxDecode(0x200, 2, 8, 8, TilePlanes, TileXOffs, TileYOffs, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x04000); + + GfxDecode(0x040, 2, 32, 32, TilePlanes, TileXOffs, TileYOffs, 0x800, tmp, Gfx1); + + memcpy (tmp, Gfx2, 0x08000); + + GfxDecode(0x100, 4, 16, 16, SpriPlanes, SpriXOffs, TileYOffs, 0x200, tmp, Gfx2); + + memcpy (tmp, Gfx3, 0x08000); + + GfxDecode(0x100, 4, 16, 16, SpriPlanes, SpriXOffs, TileYOffs, 0x200, tmp, Gfx3); + + for (INT32 i = 0; i < 0x10000; i++) { + if (Gfx2[i]) fg_tile_transp[i>>8] = 1; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 3; i++) { + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + } + + { + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(Rom0 + i * 0x4000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(Rom1, 3, 1)) return 1; + if (BurnLoadRom(Gfx0, 4, 1)) return 1; + if (BurnLoadRom(Gfx1, 5, 1)) return 1; + + for (INT32 i = 0; i < 2; i++) { + if (BurnLoadRom(Gfx2 + i * 0x4000, i + 6, 1)) return 1; + if (BurnLoadRom(Gfx3 + i * 0x4000, i + 8, 1)) return 1; + if (BurnLoadRom(Gfx4 + i * 0x4000, i + 10, 1)) return 1; + } + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(Prom + i * 0x0100, i + 12, 1)) return 1; + } + + if (GraphicsDecode()) return 1; + if (PaletteInit()) return 1; + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0xbfff, 2, Rom0 + 0x0000); + ZetMapArea(0xd000, 0xd7ff, 0, Rom0 + 0xd000); + ZetMapArea(0xd000, 0xd7ff, 1, Rom0 + 0xd000); + ZetMapArea(0xe000, 0xefff, 0, Rom0 + 0xe000); + ZetMapArea(0xe000, 0xefff, 1, Rom0 + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, Rom0 + 0xe000); + ZetMapArea(0xf000, 0xffff, 0, Rom0 + 0xf000); + ZetMapArea(0xf000, 0xffff, 1, Rom0 + 0xf000); + ZetSetWriteHandler(exedexes_cpu0_write); + ZetSetReadHandler(exedexes_cpu0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x3fff, 0, Rom1 + 0x0000); + ZetMapArea(0x0000, 0x3fff, 2, Rom1 + 0x0000); + ZetMapArea(0x4000, 0x47ff, 0, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x47ff, 1, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x47ff, 2, Rom1 + 0x4000); + ZetSetWriteHandler(exedexes_cpu1_write); + ZetSetReadHandler(exedexes_cpu1_read); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + SN76489Init(0, 3000000, 0); + SN76489Init(1, 3000000, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + AY8910Exit(0); + SN76496Exit(); + ZetExit(); + GenericTilesExit(); + + BurnFree (Mem); + + Mem = MemEnd = Rom0 = Rom1 = NULL; + Gfx0 = Gfx1 = Gfx2 = Gfx3 = Gfx4 = Prom = NULL; + for (INT32 i = 0; i < 3; i++) pAY8910Buffer[3] = NULL; + Palette = DrvPalette = NULL; + fg_tile_transp = NULL; + pFMBuffer = NULL; + DrvRecalc = 0; + + return 0; +} + + +static void draw_sprites(INT32 priority) +{ + if (!exedexes_obj_enable) return; + + for (INT32 offs = 0x0fe0; offs >= 0; offs -= 0x20) + { + if ((Rom0[0xf000 + offs + 1] & 0x40) == priority) + { + INT32 code = Rom0[0xf000 + offs]; + INT32 color = Rom0[0xf001 + offs] & 0x0f; + INT32 flipx = Rom0[0xf001 + offs] & 0x10; + INT32 flipy = Rom0[0xf001 + offs] & 0x20; + INT32 sx = Rom0[0xf003 + offs] - ((Rom0[0xf001 + offs] & 0x80) << 1); + INT32 sy = Rom0[0xf002 + offs] - 0x10; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x300, Gfx3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x300, Gfx3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x300, Gfx3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x300, Gfx3); + } + } + } + } +} + +static inline void draw_8x8(INT32 sx, INT32 sy, INT32 code, INT32 color) +{ + UINT8 *src = Gfx0 + (code << 6); + color <<= 2; + + for (INT32 y = sy; y < sy + 8; y++) { + for (INT32 x = sx; x < sx + 8; x++, src++) { + if (y < 0 || x < 0 || y >= nScreenHeight || x >= nScreenWidth) continue; + + INT32 pxl = color | *src; + if (Prom[pxl] == 0x0f) continue; + + pTransDraw[(y * nScreenWidth) + x] = pxl; + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 col = Palette[i]; + DrvPalette[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + if (exedexes_bg_enable) + { + for (INT32 i = 0; i < 16 * 8; i++) { + INT32 sx = ((i & 0x0f) << 5); + INT32 sy = (i >> 4) << 5; + + INT32 sxscr = sx + exedexes_bg_xscroll; + + sx -= (exedexes_bg_xscroll & 0x1f); + + if (sx > 0x100) continue; + sy -= 0x10; + + INT32 offset = ((sxscr & 0xe0) >> 5) | ((sy & 0xe0) >> 2) | ((sxscr & 0x3f00) >> 1) | 0x4000; + + INT32 attr = Gfx4[offset]; + INT32 color = Gfx4[offset + 0x40]; + INT32 code = attr & 0x3f; + INT32 flipx = attr & 0x40; + INT32 flipy = attr & 0x80; + + if (flipy) { + if (flipx) { + Render32x32Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0x100, Gfx1); + } else { + Render32x32Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0x100, Gfx1); + } + } else { + if (flipx) { + Render32x32Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0x100, Gfx1); + } else { + Render32x32Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0x100, Gfx1); + } + } + } + } else { + memset(pTransDraw, 0, nScreenWidth * nScreenHeight * sizeof (UINT16)); + } + + draw_sprites(0x40); + + if (exedexes_fg_enable) + { + for (INT32 i = 0; i < 32 * 16; i++) { + INT32 sx = (i & 0x1f) << 4; + INT32 sy = (i >> 5) << 4; + + INT32 vx = sx + exedexes_nbg_yscroll; + INT32 vy = sy + exedexes_nbg_xscroll; + + sx -= exedexes_nbg_yscroll & 0x0f; + sy -= exedexes_nbg_xscroll & 0x0f; + + if (sx > 0x100) continue; + + INT32 offset = ((vx & 0xf0) >> 4) | (vy & 0xf0) | (vx & 0x700) | ((vy & 0x700) << 3); + + INT32 code = Gfx4[offset]; + + if (!fg_tile_transp[code]) continue; + sy -= 0x10; + + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 2, 0, 0x200, Gfx2); + } + } + + draw_sprites(0); + + if (exedexes_txt_enable) + { + for (INT32 i = 0x40; i < 0x3c0; i++) { + INT32 sx = (i & 0x1f) << 3; + INT32 sy = ((i >> 5) << 3) - 0x10; + INT32 code = Rom0[0xd000 | i] | ((Rom0[0xd400 | i] & 0x80) << 1); + INT32 color = Rom0[0xd400 | i] & 0x3f; + + if (code == 0x0024) continue; + + draw_8x8(sx, sy, code, color); + //Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, Gfx0); + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + DrvMakeInputs(); + + INT32 nInterleave = 16; + INT32 nCyclesDone[2] = { 0, 0 }; + INT32 nCyclesTotal[2] = { 4000000 / 60, 3000000 / 60 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 0) { + ZetSetVector(0xcf); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[nCurrentCPU] += ZetRun(100); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + if (i == ( nInterleave - 2)) { + ZetSetVector(0xd7); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[nCurrentCPU] += ZetRun(100); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if ((i & 3) == 3) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + } + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + + INT32 nSample, nSample0, nSample1; + if (nBurnSoundLen) { + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample >>= 2; + + nSample = BURN_SND_CLIP(nSample); + + nSample0 = pBurnSoundOut[(n << 1) + 0] >> 2; + nSample1 = pBurnSoundOut[(n << 1) + 1] >> 2; + + nSample0 = BURN_SND_CLIP(nSample0 + nSample); + nSample1 = BURN_SND_CLIP(nSample1 + nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample0; + pBurnSoundOut[(n << 1) + 1] = nSample1; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom0 + 0xd000; + ba.nLen = 0x3000; + ba.szName = "All CPU #0 Ram"; + BurnAcb(&ba); + + ba.Data = Rom1 + 0x4000; + ba.nLen = 0x0800; + ba.szName = "All CPU #1 Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + SN76496Scan(nAction, pnMin); + + SCAN_VAR(exedexes_soundlatch); + SCAN_VAR(exedexes_txt_enable); + SCAN_VAR(exedexes_obj_enable); + SCAN_VAR(exedexes_bg_enable); + SCAN_VAR(exedexes_fg_enable); + SCAN_VAR(exedexes_nbg_yscroll); + SCAN_VAR(exedexes_nbg_xscroll); + SCAN_VAR(exedexes_bg_xscroll); + } + + return 0; +} + + +// Exed Exes + +static struct BurnRomInfo exedexesRomDesc[] = { + { "11m_ee04.bin", 0x4000, 0x44140dbd, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "10m_ee03.bin", 0x4000, 0xbf72cfba, 1 | BRF_PRG | BRF_ESS }, // 1 + { "09m_ee02.bin", 0x4000, 0x7ad95e2f, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_ee01.bin", 0x4000, 0x73cdf3b2, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "05c_ee00.bin", 0x2000, 0xcadb75bd, 3 | BRF_GRA }, // 4 Characters + + { "h01_ee08.bin", 0x4000, 0x96a65c1d, 4 | BRF_GRA }, // 5 32x32 tiles + + { "a03_ee06.bin", 0x4000, 0x6039bdd1, 5 | BRF_GRA }, // 6 16x16 tiles + { "a02_ee05.bin", 0x4000, 0xb32d8252, 5 | BRF_GRA }, // 7 + + { "j11_ee10.bin", 0x4000, 0xbc83e265, 6 | BRF_GRA }, // 8 Sprites + { "j12_ee11.bin", 0x4000, 0x0e0f300d, 6 | BRF_GRA }, // 9 + + { "c01_ee07.bin", 0x4000, 0x3625a68d, 7 | BRF_GRA }, // 10 Tile Maps + { "h04_ee09.bin", 0x2000, 0x6057c907, 7 | BRF_GRA }, // 11 + + { "02d_e-02.bin", 0x0100, 0x8d0d5935, 8 | BRF_GRA }, // 12 Color Proms + { "03d_e-03.bin", 0x0100, 0xd3c17efc, 8 | BRF_GRA }, // 13 + { "04d_e-04.bin", 0x0100, 0x58ba964c, 8 | BRF_GRA }, // 14 + { "06f_e-05.bin", 0x0100, 0x35a03579, 8 | BRF_GRA }, // 15 + { "l04_e-10.bin", 0x0100, 0x1dfad87a, 8 | BRF_GRA }, // 16 + { "c04_e-07.bin", 0x0100, 0x850064e0, 8 | BRF_GRA }, // 17 + { "l09_e-11.bin", 0x0100, 0x2bb68710, 8 | BRF_GRA }, // 18 + { "l10_e-12.bin", 0x0100, 0x173184ef, 8 | BRF_GRA }, // 19 + + { "06l_e-06.bin", 0x0100, 0x712ac508, 0 | BRF_OPT }, // 20 Misc. Proms + { "k06_e-08.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 21 + { "l03_e-09.bin", 0x0100, 0x0d968558, 0 | BRF_OPT }, // 22 + { "03e_e-01.bin", 0x0020, 0x1acee376, 0 | BRF_OPT }, // 23 +}; + +STD_ROM_PICK(exedexes) +STD_ROM_FN(exedexes) + +struct BurnDriver BurnDrvExedexes = { + "exedexes", NULL, NULL, NULL, "1985", + "Exed Exes\0", NULL, "Capcom", "Miscellaneous", + L"Exed Exes\0\u30A8\u30B0\u30BC\u30C9 \u30A8\u30B0\u30BC\u30B9\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, exedexesRomInfo, exedexesRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 256, 3, 4 +}; + + +// Savage Bees + +static struct BurnRomInfo savgbeesRomDesc[] = { + { "ee04e.11m", 0x4000, 0xc0caf442, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "ee03e.10m", 0x4000, 0x9cd70ae1, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ee02e.9m", 0x4000, 0xa04e6368, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "ee01e.11e", 0x4000, 0x93d3f952, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "ee00e.5c", 0x2000, 0x5972f95f, 3 | BRF_GRA }, // 4 Characters + + { "h01_ee08.bin", 0x4000, 0x96a65c1d, 4 | BRF_GRA }, // 5 32x32 tiles + + { "a03_ee06.bin", 0x4000, 0x6039bdd1, 5 | BRF_GRA }, // 6 16x16 tiles + { "a02_ee05.bin", 0x4000, 0xb32d8252, 5 | BRF_GRA }, // 7 + + { "j11_ee10.bin", 0x4000, 0xbc83e265, 6 | BRF_GRA }, // 8 Sprites + { "j12_ee11.bin", 0x4000, 0x0e0f300d, 6 | BRF_GRA }, // 9 + + { "c01_ee07.bin", 0x4000, 0x3625a68d, 7 | BRF_GRA }, // 10 Tile Maps + { "h04_ee09.bin", 0x2000, 0x6057c907, 7 | BRF_GRA }, // 11 + + { "02d_e-02.bin", 0x0100, 0x8d0d5935, 8 | BRF_GRA }, // 12 Color Proms + { "03d_e-03.bin", 0x0100, 0xd3c17efc, 8 | BRF_GRA }, // 13 + { "04d_e-04.bin", 0x0100, 0x58ba964c, 8 | BRF_GRA }, // 14 + { "06f_e-05.bin", 0x0100, 0x35a03579, 8 | BRF_GRA }, // 15 + { "l04_e-10.bin", 0x0100, 0x1dfad87a, 8 | BRF_GRA }, // 16 + { "c04_e-07.bin", 0x0100, 0x850064e0, 8 | BRF_GRA }, // 17 + { "l09_e-11.bin", 0x0100, 0x2bb68710, 8 | BRF_GRA }, // 18 + { "l10_e-12.bin", 0x0100, 0x173184ef, 8 | BRF_GRA }, // 19 + + { "06l_e-06.bin", 0x0100, 0x712ac508, 0 | BRF_OPT }, // 20 Misc. Proms + { "k06_e-08.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 21 + { "l03_e-09.bin", 0x0100, 0x0d968558, 0 | BRF_OPT }, // 22 + { "03e_e-01.bin", 0x0020, 0x1acee376, 0 | BRF_OPT }, // 23 +}; + +STD_ROM_PICK(savgbees) +STD_ROM_FN(savgbees) + +struct BurnDriver BurnDrvSavgbees = { + "savgbees", "exedexes", NULL, NULL, "1985", + "Savage Bees\0", NULL, "Capcom (Memetron license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, savgbeesRomInfo, savgbeesRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_flstory.cpp b/src/burn/drivers/misc_pre90s/d_flstory.cpp new file mode 100644 index 00000000..87b2c6cf --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_flstory.cpp @@ -0,0 +1,1437 @@ +#include "tiles_generic.h" +#include "taito_m68705.h" +#include "driver.h" +#include "dac.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvMcuROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvMcuRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT16 *pAY8910Buffer[3]; + +static UINT8 snd_data; +static UINT8 snd_flag; +static INT32 nmi_enable; +static INT32 pending_nmi; +static INT32 char_bank = 0; +static INT32 mcu_select; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[5]; +static UINT8 DrvReset; + +static UINT8 *flipscreen; +static UINT8 *soundlatch; + +static INT32 select_game; + +static struct BurnInputInfo FlstoryInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 3, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Flstory) + +static struct BurnDIPInfo FlstoryDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xec, NULL }, + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0xf8, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0f, 0x01, 0x03, 0x00, "30000 100000" }, + {0x0f, 0x01, 0x03, 0x01, "30000 150000" }, + {0x0f, 0x01, 0x03, 0x02, "50000 150000" }, + {0x0f, 0x01, 0x03, 0x03, "70000 150000" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0x18, 0x08, "3" }, + {0x0f, 0x01, 0x18, 0x10, "4" }, + {0x0f, 0x01, 0x18, 0x18, "5" }, + {0x0f, 0x01, 0x18, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Debug Mode" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0f, 0x01, 0x80, 0x80, "Upright" }, + {0x0f, 0x01, 0x80, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x10, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x10, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x10, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x10, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x10, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x10, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x10, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x10, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x10, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x10, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x10, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x11, 0x01, 0x08, 0x00, "No" }, + {0x11, 0x01, 0x08, 0x08, "Yes" }, + + {0 , 0xfe, 0 , 2, "Attract Animation" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Leave Off" }, + {0x11, 0x01, 0x20, 0x20, "Off" }, + {0x11, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x11, 0x01, 0x80, 0x00, "1" }, + {0x11, 0x01, 0x80, 0x80, "2" }, +}; + +STDDIPINFO(Flstory) + +static struct BurnInputInfo Onna34roInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 5, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 4, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 5, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 4, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 3, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Onna34ro) + +static struct BurnDIPInfo Onna34roDIPList[]= +{ + {0x13, 0xff, 0xff, 0xe0, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x80, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x03, 0x00, "200000 200000" }, + {0x13, 0x01, 0x03, 0x01, "200000 300000" }, + {0x13, 0x01, 0x03, 0x02, "100000 200000" }, + {0x13, 0x01, 0x03, 0x03, "200000 100000" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x18, 0x10, "1" }, + {0x13, 0x01, 0x18, 0x08, "2" }, + {0x13, 0x01, 0x18, 0x00, "3" }, + {0x13, 0x01, 0x18, 0x18, "Endless (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x80, 0x80, "Upright" }, + {0x13, 0x01, 0x80, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x14, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x14, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x14, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x14, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x14, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x14, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x14, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x14, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x14, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x14, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)"}, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Rack Test" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage Display" }, + {0x15, 0x01, 0x10, 0x10, "Off" }, + {0x15, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x60, 0x20, "Easy" }, + {0x15, 0x01, 0x60, 0x00, "Normal" }, + {0x15, 0x01, 0x60, 0x40, "Difficult" }, + {0x15, 0x01, 0x60, 0x60, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x15, 0x01, 0x80, 0x80, "A and B" }, + {0x15, 0x01, 0x80, 0x00, "A only" }, +}; + +STDDIPINFO(Onna34ro) + +static struct BurnInputInfo VictnineInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 5, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 4, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy4 + 2, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy4 + 3, "p1 fire 4" }, + {"P1 Button 5", BIT_DIGITAL, DrvJoy4 + 4, "p1 fire 5" }, + {"P1 Button 6", BIT_DIGITAL, DrvJoy4 + 5, "p1 fire 6" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 5, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 4, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy5 + 2, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy5 + 3, "p2 fire 4" }, + {"P2 Button 5", BIT_DIGITAL, DrvJoy5 + 4, "p2 fire 5" }, + {"P2 Button 6", BIT_DIGITAL, DrvJoy5 + 5, "p2 fire 6" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 3, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Victnine) + +static struct BurnDIPInfo VictnineDIPList[]= +{ + {0x1b, 0xff, 0xff, 0x67, NULL }, + {0x1c, 0xff, 0xff, 0x00, NULL }, + {0x1d, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x1b, 0x01, 0x04, 0x04, "Off" }, + {0x1b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x1b, 0x01, 0x40, 0x40, "Off" }, + {0x1b, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x1b, 0x01, 0xa0, 0x20, "Upright" }, + {0x1b, 0x01, 0xa0, 0xa0, "Cocktail" }, + {0x1b, 0x01, 0xa0, 0x00, "MA / MB" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x1c, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x1c, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x1c, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x1c, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x1c, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x1c, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x1c, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x1c, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x1c, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x1c, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x1c, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x1c, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x1c, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x1c, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x1c, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x1c, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x1c, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 2, "Coinage Display" }, + {0x1d, 0x01, 0x10, 0x00, "Off" }, + {0x1d, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2, "Show Year" }, + {0x1d, 0x01, 0x20, 0x00, "Off" }, + {0x1d, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "No hit" }, + {0x1d, 0x01, 0x40, 0x40, "Off" }, + {0x1d, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x1d, 0x01, 0x80, 0x80, "A and B" }, + {0x1d, 0x01, 0x80, 0x00, "A only" }, +}; + +STDDIPINFO(Victnine) + +static void gfxctrl_write(INT32 data) +{ + char_bank = (data & 0x10) >> 4; + + INT32 bank = (data & 0x20) << 3; + + ZetMapArea(0xdd00, 0xddff, 0, DrvPalRAM + 0x000 + bank); + ZetMapArea(0xdd00, 0xddff, 1, DrvPalRAM + 0x000 + bank); + ZetMapArea(0xde00, 0xdeff, 0, DrvPalRAM + 0x200 + bank); + ZetMapArea(0xde00, 0xdeff, 1, DrvPalRAM + 0x200 + bank); + + if (data & 4) *flipscreen = (~data & 0x01); +} + +static void onna34ro_mcu_write(INT32 data) +{ + INT32 score_adr = (ZetReadByte(0xe29e) << 8) | ZetReadByte(0xe29d); + + mcu_sent = 1; + + switch (data) + { + case 0x0e: + from_mcu = 0xff; + break; + + case 0x01: + from_mcu = 0x6a; + break; + + case 0x40: + from_mcu = ZetReadByte(score_adr); + break; + + case 0x41: + from_mcu = ZetReadByte(score_adr+1); + break; + + case 0x42: + from_mcu = ZetReadByte(score_adr+2) & 0x0f; + break; + + default: + from_mcu = 0x80; + } +} + +static const UINT8 victnine_mcu_data[0x100] = +{ + 0x3e, 0x08, 0xdd, 0x29, 0xcb, 0x14, 0xfd, 0x29, + 0xcb, 0x15, 0xd9, 0x29, 0xd9, 0x30, 0x0d, 0xd9, + 0x19, 0xd9, 0xdd, 0x09, 0x30, 0x01, 0x24, 0xfd, + 0x19, 0x30, 0x01, 0x2c, 0x3d, 0x20, 0xe3, 0xc9, + 0x11, 0x14, 0x00, 0x19, 0x7e, 0x32, 0xed, 0xe4, + 0x2a, 0x52, 0xe5, 0x22, 0xe9, 0xe4, 0x2a, 0x54, + 0xe5, 0x22, 0xeb, 0xe4, 0x21, 0x2a, 0xe6, 0xfe, + 0x06, 0x38, 0x02, 0xcb, 0xc6, 0xcb, 0xce, 0xc9, + 0x06, 0x00, 0x3a, 0xaa, 0xe4, 0x07, 0x07, 0x07, + 0xb0, 0x47, 0x3a, 0xab, 0xe4, 0x07, 0x07, 0xb0, + 0x47, 0x3a, 0xac, 0xe4, 0xe6, 0x03, 0xb0, 0x21, + 0xe3, 0xe6, 0xc9, 0x38, 0xe1, 0x29, 0x07, 0xc9, + 0x23, 0x7e, 0x47, 0xe6, 0x1f, 0x32, 0x0c, 0xe6, + 0x78, 0xe6, 0xe0, 0x07, 0x07, 0x47, 0xe6, 0x03, + 0x28, 0x06, 0xcb, 0x7a, 0x28, 0x02, 0xc6, 0x02, + 0x32, 0x0a, 0xe6, 0x78, 0xe6, 0x80, 0xc9, 0x3a, + 0x21, 0x29, 0xe5, 0x7e, 0xe6, 0xf8, 0xf6, 0x01, + 0x77, 0x23, 0x3a, 0x0a, 0xe6, 0x77, 0x21, 0x08, + 0xe6, 0xcb, 0xc6, 0xcb, 0x8e, 0x3a, 0x2b, 0xe5, + 0x21, 0xff, 0xe5, 0xfe, 0x02, 0xc9, 0x1f, 0xc6, + 0x47, 0x3a, 0xaa, 0xe4, 0xa7, 0x21, 0x00, 0xe5, + 0x28, 0x03, 0x21, 0x1b, 0xe5, 0x70, 0x3a, 0xaa, + 0xe4, 0xee, 0x01, 0x32, 0xaa, 0xe4, 0x21, 0xb0, + 0xe4, 0x34, 0x23, 0x36, 0x00, 0xc9, 0x2b, 0xb2, + 0xaf, 0x77, 0x12, 0x23, 0x13, 0x3c, 0xfe, 0x09, + 0x20, 0xf7, 0x3e, 0x01, 0x32, 0xad, 0xe4, 0x21, + 0x48, 0xe5, 0xcb, 0xfe, 0xc9, 0x32, 0xe5, 0xaa, + 0x21, 0x00, 0x13, 0xe4, 0x47, 0x1b, 0xa1, 0xc9, + 0x00, 0x08, 0x04, 0x0c, 0x05, 0x0d, 0x06, 0x0e, + 0x22, 0x66, 0xaa, 0x22, 0x33, 0x01, 0x11, 0x88, + 0x06, 0x05, 0x03, 0x04, 0x08, 0x01, 0x03, 0x02, + 0x06, 0x07, 0x02, 0x03, 0x15, 0x17, 0x11, 0x13 +}; + +static void victnine_mcu_write(INT32 data) +{ + INT32 seed = ZetReadByte(0xe685); + + if (!seed && (data & 0x37) == 0x37) + { + from_mcu = 0xa6; + } + else + { + data += seed; + + if ((data & ~0x1f) == 0xa0) + { + mcu_select = data & 0x1f; + } + else if (data < 0x20) + { + INT32 offset = mcu_select * 8 + data; + from_mcu = victnine_mcu_data[offset]; + } + else if (data >= 0x38 && data <= 0x3a) + { + from_mcu = ZetReadByte(0xe691 - 0x38 + data); + } + } +} + +void __fastcall flstory_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xff00) == 0xdc00) { + DrvSprRAM[address & 0xff] = data; + + if (select_game == 2 && address == 0xdce0) { + gfxctrl_write((data ^ 1) & ~0x10); + } + + return; + } + + switch (address) + { + case 0xd000: + if (select_game == 2) { + victnine_mcu_write(data); + } if (select_game == 1) { + onna34ro_mcu_write(data); + } else { + standard_taito_mcu_write(data); + } + return; + + case 0xd400: + { + *soundlatch = data; + + if (nmi_enable) { + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + } else { + pending_nmi = 1; + } + } + return; + + case 0xdf03: + if (select_game != 2) gfxctrl_write(data | 0x04); + return; + } +} + +UINT8 __fastcall flstory_main_read(UINT16 address) +{ + switch (address) + { + case 0xd000: + if (select_game == 2) { + return from_mcu - ZetReadByte(0xe685); + } else { + return standard_taito_mcu_read(); + } + + case 0xd400: + snd_flag = 0; + return snd_data; + + case 0xd401: + return snd_flag | 0xfd; + + case 0xd800: + case 0xd801: + case 0xd802: + return DrvDips[address & 3]; + + case 0xd803: + return DrvInputs[0] & 0x3f; + + case 0xd804: + return DrvInputs[1]; + + case 0xd805: + { + INT32 res = 0; + if (!main_sent) res |= 0x01; + if (mcu_sent) res |= 0x02; + + if (select_game == 2) res |= DrvInputs[3]; + + return res; + } + + case 0xd806: + return DrvInputs[2]; + + case 0xd807: + return DrvInputs[4]; + } + + return 0; +} + +void __fastcall flstory_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc800: + case 0xc801: + AY8910Write(0, address & 1, data); + return; + + case 0xca00: + case 0xca01: + case 0xca02: + case 0xca03: + case 0xca04: + case 0xca05: + case 0xca06: + case 0xca07: + case 0xca08: + case 0xca09: + case 0xca0a: + case 0xca0b: + case 0xca0c: + case 0xca0d: + // msm5232 + return; + + case 0xd800: + snd_data = data; + snd_flag = 2; + return; + + case 0xda00: + nmi_enable = 1; + if (pending_nmi) + { + ZetNmi(); + pending_nmi = 0; + } + return; + + case 0xdc00: + nmi_enable = 0; + return; + + case 0xde00: + DACSignedWrite(0, data); + return; + } +} + +UINT8 __fastcall flstory_sound_read(UINT16 address) +{ + if (address == 0xd800) { + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + m67805_taito_reset(); + + AY8910Reset(0); + DACReset(); + + snd_data = 0; + snd_flag = 0; + nmi_enable = 0; + pending_nmi = 0; + char_bank = 0; + mcu_select = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvMcuROM = Next; Next += 0x000800; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + DrvVidRAM = Next; Next += 0x001000; + DrvZ80RAM0 = Next; Next += 0x000800; + DrvZ80RAM1 = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000100; + + DrvMcuRAM = Next; Next += 0x000080; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() // 0, 0x100 +{ + INT32 Plane[4] = { 0x80000, 0x80004, 0x00000, 0x00004 }; + INT32 XOffs[16] = { 3, 2, 1, 0, 8+3, 8+2, 8+1, 8+0, 16*8+3, 16*8+2, 16*8+1, 16*8+0, 16*8+8+3, 16*8+8+2, 16*8+8+1, 16*8+8+0 }; + INT32 YOffs[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 16*16, 17*16, 18*16, 19*16, 20*16, 21*16, 22*16, 23*16 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x20000); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x20000; i++) tmp[i] = DrvGfxROM0[i] ^ 0xff; + + GfxDecode(0x1000, 4, 8, 8, Plane, XOffs, YOffs, 0x080, tmp, DrvGfxROM0); + GfxDecode(0x0400, 4, 16, 16, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (select_game == 0) { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x08000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x02000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x04000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x08000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x14000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x18000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1c000, 12, 1)) return 1; + + if (BurnLoadRom(DrvMcuROM + 0x00000, 13, 1)) return 1; + } else if (select_game == 1) { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x08000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x02000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x04000, 5, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x06000, 6, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x08000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x04000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x08000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x0c000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x14000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x18000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x1c000, 15, 1)) return 1; + } else if (select_game == 2) { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x06000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x08000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x0a000, 5, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x02000, 7, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x04000, 8, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x06000, 9, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x08000, 10, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x0a000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x02000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x04000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x06000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x12000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x14000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x16000, 19, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xcfff, 0, DrvVidRAM); + ZetMapArea(0xc000, 0xcfff, 1, DrvVidRAM); + ZetMapArea(0xc000, 0xcfff, 2, DrvVidRAM); + ZetMapArea(0xdc00, 0xdcff, 0, DrvSprRAM); +// ZetMapArea(0xdc00, 0xdcff, 1, DrvSprRAM); + ZetMapArea(0xdc00, 0xdcff, 2, DrvSprRAM); + ZetMapArea(0xdd00, 0xddff, 0, DrvPalRAM); + ZetMapArea(0xdd00, 0xddff, 1, DrvPalRAM); + ZetMapArea(0xdd00, 0xddff, 2, DrvPalRAM); + ZetMapArea(0xde00, 0xdeff, 0, DrvPalRAM + 0x200); + ZetMapArea(0xde00, 0xdeff, 1, DrvPalRAM + 0x200); + ZetMapArea(0xde00, 0xdeff, 2, DrvPalRAM + 0x200); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80RAM0); + ZetSetWriteHandler(flstory_main_write); + ZetSetReadHandler(flstory_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM1); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM1); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80ROM1 + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80ROM1 + 0xe000); + ZetSetWriteHandler(flstory_sound_write); + ZetSetReadHandler(flstory_sound_read); + ZetMemEnd(); + ZetClose(); + + m67805_taito_init(DrvMcuROM, DrvMcuRAM, &standard_m68705_interface); + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DACInit(0, 0, 1); + DACSetVolShift(0, 4); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + m67805_taito_exit(); + + AY8910Exit(0); + DACExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background_layer(INT32 type, INT32 priority) +{ + INT32 masks[4] = { 0x3fff, 0xc000, 0x8000, 0x7fff }; + INT32 mask = masks[type]; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= DrvSprRAM[0xa0 + (offs & 0x1f)] + 16; + if (sy < -7) sy += 256; + if (sy >= nScreenHeight) continue; + + INT32 attr = DrvVidRAM[offs * 2 + 1]; + INT32 code = DrvVidRAM[offs * 2 + 0] | ((attr & 0xc0) << 2) | 0x400 | (char_bank * 0x800); + + INT32 flipy = attr & 0x10; + INT32 flipx = attr & 0x08; + INT32 color = (attr & 0x0f) << 4; + INT32 prio = (attr & 0x20) >> 5; + if (priority && !prio) continue; + + if (type == 0) { + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 0, DrvGfxROM0); + } + } + } + else if (type == 2) { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 15, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 15, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 15, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color >> 4, 4, 15, 0, DrvGfxROM0); + } + } + } + else + { + if (flipy) flipy = 0x38; + if (flipx) flipy |= 0x07; + UINT8 *src = DrvGfxROM0 + (code * 8 * 8); + UINT16 *dst; + + for (INT32 y = 0; y < 8; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + dst = pTransDraw + sy * nScreenWidth; + + for (INT32 x = 0; x < 8; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = src[((y << 3) | x) ^ flipy]; + if (mask & (1 << pxl)) continue; + + dst[sx] = pxl | color; + } + + sx -= 8; + } + } + } +} + +static void victnine_draw_background_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + sy -= DrvSprRAM[0xa0 + (offs & 0x1f)] + 16; + if (sy < -7) sy += 256; + if (sy >= nScreenHeight) continue; + + INT32 attr = DrvVidRAM[offs * 2 + 1]; + INT32 code = DrvVidRAM[offs * 2 + 0] | ((attr & 0x38) << 5); + + INT32 flipy = attr & 0x80; + INT32 flipx = attr & 0x40; + INT32 color = attr & 0x07; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } + + } +} + +static void draw_sprites(INT32 pri, INT32 type) +{ + for (INT32 i = 0; i < 0x20; i++) + { + INT32 pr = DrvSprRAM[0xa0-1 -i]; + INT32 offs = (pr & 0x1f) * 4; + + if ((pr & 0x80) == pri || type) + { + INT32 sy = DrvSprRAM[offs + 0]; + INT32 attr = DrvSprRAM[offs + 1]; + INT32 code = DrvSprRAM[offs + 2]; + if (type) { + code += (attr & 0x20) << 3; + } else { + code += ((attr & 0x30) << 4); + } + + INT32 sx = DrvSprRAM[offs + 3]; + INT32 flipx = attr & 0x40; + INT32 flipy = attr & 0x80; + + if (*flipscreen) + { + sx = (240 - sx) & 0xff; + sy = sy - 1; + + flipx ^= 0x40; + flipx ^= 0x80; + } + else + sy = 240 - sy - 1; + + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } + } + + if (sx > 240) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx - 256, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx - 256, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx - 256, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx - 256, sy, attr & 0x0f, 4, 15, 0x100, DrvGfxROM1); + } + } + } + } + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + for (INT32 i = 0; i < 0x200; i++) { + INT32 d = DrvPalRAM[i] | (DrvPalRAM[i + 0x200] << 8); + b = (d >> 8) & 0x0f; + g = (d >> 4) & 0x0f; + r = d & 0x0f; + DrvPalette[i] = BurnHighCol((r << 4) | r, (g << 4) | g, (b << 4) | b, 0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + if (nBurnLayer & 1) draw_background_layer(0, 0); + if (nBurnLayer & 2) draw_background_layer(1, 0); + if (nBurnLayer & 4) draw_background_layer(2, 1); + if (nBurnLayer & 8) draw_background_layer(3, 1); + draw_sprites(0x00, 0); + draw_sprites(0x80, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 victnineDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + victnine_draw_background_layer(); + draw_sprites(0, 1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 5); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy5[i] & 1) << i; + } + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 100; + INT32 nCyclesTotal[3] = { 5366500 / 60, 4000000 / 60, 3072000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + if (select_game == 2) nCyclesTotal[0] = nCyclesTotal[1]; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + ZetOpen(1); + nSegment = nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += ZetRun(nSegment); + if (i == (nInterleave / 2) - 1) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + if (i == (nInterleave / 1) - 1) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + if (select_game == 0) { + m6805Open(0); + nSegment = nCyclesTotal[2] / nInterleave; + nCyclesDone[2] += m6805Run(nSegment); + m6805Close(); + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + + DACUpdate(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + + DACUpdate(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) { + BurnDrvRedraw(); + } + + return 0; +} + + +// The FairyLand Story + +static struct BurnRomInfo flstoryRomDesc[] = { + { "cpu-a45.15", 0x4000, 0xf03fc969, 1 }, // 0 maincpu + { "cpu-a45.16", 0x4000, 0x311aa82e, 1 }, // 1 + { "cpu-a45.17", 0x4000, 0xa2b5d17d, 1 }, // 2 + + { "snd.22", 0x2000, 0xd58b201d, 2 }, // 3 audiocpu + { "snd.23", 0x2000, 0x25e7fd9d, 2 }, // 4 + + { "vid-a45.18", 0x4000, 0x6f08f69e, 3 }, // 5 gfx1 + { "vid-a45.06", 0x4000, 0xdc856a75, 3 }, // 6 + { "vid-a45.08", 0x4000, 0xd0b028ca, 3 }, // 7 + { "vid-a45.20", 0x4000, 0x1b0edf34, 3 }, // 8 + { "vid-a45.19", 0x4000, 0x2b572dc9, 3 }, // 9 + { "vid-a45.07", 0x4000, 0xaa4b0762, 3 }, // 10 + { "vid-a45.09", 0x4000, 0x8336be58, 3 }, // 11 + { "vid-a45.21", 0x4000, 0xfc382bd1, 3 }, // 12 + + { "a45.mcu", 0x0800, 0x5378253c, 4 }, // 13 mcu +}; + +STD_ROM_PICK(flstory) +STD_ROM_FN(flstory) + +static INT32 flstoryInit() +{ + select_game = 0; + + return DrvInit(); +} + +struct BurnDriver BurnDrvFlstory = { + "flstory", NULL, NULL, NULL, "1985", + "The FairyLand Story\0", NULL, "Taito", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, flstoryRomInfo, flstoryRomName, NULL, NULL, FlstoryInputInfo, FlstoryDIPInfo, + flstoryInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The FairyLand Story (Japan) + +static struct BurnRomInfo flstoryjRomDesc[] = { + { "cpu-a45.15", 0x4000, 0xf03fc969, 1 }, // 0 maincpu + { "cpu-a45.16", 0x4000, 0x311aa82e, 1 }, // 1 + { "cpu-a45.17", 0x4000, 0xa2b5d17d, 1 }, // 2 + + { "a45_12.8", 0x2000, 0xd6f593fb, 2 }, // 3 audiocpu + { "a45_13.9", 0x2000, 0x451f92f9, 2 }, // 4 + + { "vid-a45.18", 0x4000, 0x6f08f69e, 3 }, // 5 gfx1 + { "vid-a45.06", 0x4000, 0xdc856a75, 3 }, // 6 + { "vid-a45.08", 0x4000, 0xd0b028ca, 3 }, // 7 + { "vid-a45.20", 0x4000, 0x1b0edf34, 3 }, // 8 + { "vid-a45.19", 0x4000, 0x2b572dc9, 3 }, // 9 + { "vid-a45.07", 0x4000, 0xaa4b0762, 3 }, // 10 + { "vid-a45.09", 0x4000, 0x8336be58, 3 }, // 11 + { "vid-a45.21", 0x4000, 0xfc382bd1, 3 }, // 12 + + { "a45.mcu", 0x0800, 0x5378253c, 4 }, // 13 mcu +}; + +STD_ROM_PICK(flstoryj) +STD_ROM_FN(flstoryj) + +struct BurnDriver BurnDrvFlstoryj = { + "flstoryj", "flstory", NULL, NULL, "1985", + "The FairyLand Story (Japan)\0", NULL, "Taito", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, flstoryjRomInfo, flstoryjRomName, NULL, NULL, FlstoryInputInfo, FlstoryDIPInfo, + flstoryInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Onna Sansirou - Typhoon Gal (set 1) + +static struct BurnRomInfo onna34roRomDesc[] = { + { "a52-01-1.40c", 0x4000, 0xffddcb02, 1 }, // 0 maincpu + { "a52-02-1.41c", 0x4000, 0xda97150d, 1 }, // 1 + { "a52-03-1.42c", 0x4000, 0xb9749a53, 1 }, // 2 + + { "a52-12.08s", 0x2000, 0x28f48096, 2 }, // 3 audiocpu + { "a52-13.09s", 0x2000, 0x4d3b16f3, 2 }, // 4 + { "a52-14.10s", 0x2000, 0x90a6f4e8, 2 }, // 5 + { "a52-15.37s", 0x2000, 0x5afc21d0, 2 }, // 6 + { "a52-16.38s", 0x2000, 0xccf42aee, 2 }, // 7 + + { "a52-04.11v", 0x4000, 0x5b126294, 3 }, // 8 gfx1 + { "a52-06.10v", 0x4000, 0x78114721, 3 }, // 9 + { "a52-08.09v", 0x4000, 0x4a293745, 3 }, // 10 + { "a52-10.08v", 0x4000, 0x8be7b4db, 3 }, // 11 + { "a52-05.35v", 0x4000, 0xa1a99588, 3 }, // 12 + { "a52-07.34v", 0x4000, 0x0bf420f2, 3 }, // 13 + { "a52-09.33v", 0x4000, 0x39c543b5, 3 }, // 14 + { "a52-11.32v", 0x4000, 0xd1dda6b3, 3 }, // 15 + + { "a52-17.54c", 0x0800, 0x00000000, 4 | BRF_NODUMP }, // 16 cpu2 +}; + +STD_ROM_PICK(onna34ro) +STD_ROM_FN(onna34ro) + +static INT32 onna34roInit() +{ + select_game = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvOnna34ro = { + "onna34ro", NULL, NULL, NULL, "1985", + "Onna Sansirou - Typhoon Gal (set 1)\0", NULL, "Taito", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, onna34roRomInfo, onna34roRomName, NULL, NULL, Onna34roInputInfo, Onna34roDIPInfo, + onna34roInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Onna Sansirou - Typhoon Gal (set 2) + +static struct BurnRomInfo onna34raRomDesc[] = { + { "ry-08.rom", 0x4000, 0xe4587b85, 1 }, // 0 maincpu + { "ry-07.rom", 0x4000, 0x6ffda515, 1 }, // 1 + { "ry-06.rom", 0x4000, 0x6fefcda8, 1 }, // 2 + + { "a52-12.08s", 0x2000, 0x28f48096, 2 }, // 3 audiocpu + { "a52-13.09s", 0x2000, 0x4d3b16f3, 2 }, // 4 + { "a52-14.10s", 0x2000, 0x90a6f4e8, 2 }, // 5 + { "a52-15.37s", 0x2000, 0x5afc21d0, 2 }, // 6 + { "a52-16.38s", 0x2000, 0xccf42aee, 2 }, // 7 + + { "a52-04.11v", 0x4000, 0x5b126294, 3 }, // 8 gfx1 + { "a52-06.10v", 0x4000, 0x78114721, 3 }, // 9 + { "a52-08.09v", 0x4000, 0x4a293745, 3 }, // 10 + { "a52-10.08v", 0x4000, 0x8be7b4db, 3 }, // 11 + { "a52-05.35v", 0x4000, 0xa1a99588, 3 }, // 12 + { "a52-07.34v", 0x4000, 0x0bf420f2, 3 }, // 13 + { "a52-09.33v", 0x4000, 0x39c543b5, 3 }, // 14 + { "a52-11.32v", 0x4000, 0xd1dda6b3, 3 }, // 15 + + { "a52-17.54c", 0x0800, 0x00000000, 4 | BRF_NODUMP }, // 16 cpu2 +}; + +STD_ROM_PICK(onna34ra) +STD_ROM_FN(onna34ra) + +struct BurnDriver BurnDrvOnna34ra = { + "onna34roa", "onna34ro", NULL, NULL, "1985", + "Onna Sansirou - Typhoon Gal (set 2)\0", NULL, "Taito", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, onna34raRomInfo, onna34raRomName, NULL, NULL, Onna34roInputInfo, Onna34roDIPInfo, + onna34roInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Victorious Nine + +static struct BurnRomInfo victnineRomDesc[] = { + { "a16-19.1", 0x2000, 0xdeb7c439, 1 }, // 0 maincpu + { "a16-20.2", 0x2000, 0x60cdb6ae, 1 }, // 1 + { "a16-21.3", 0x2000, 0x121bea03, 1 }, // 2 + { "a16-22.4", 0x2000, 0xb20e3027, 1 }, // 3 + { "a16-23.5", 0x2000, 0x95fe9cb7, 1 }, // 4 + { "a16-24.6", 0x2000, 0x32b5c155, 1 }, // 5 + + { "a16-12.8", 0x2000, 0x4b9bff43, 2 }, // 6 audiocpu + { "a16-13.9", 0x2000, 0x355121b9, 2 }, // 7 + { "a16-14.10", 0x2000, 0x0f33ef4d, 2 }, // 8 + { "a16-15.37", 0x2000, 0xf91d63dc, 2 }, // 9 + { "a16-16.38", 0x2000, 0x9395351b, 2 }, // 10 + { "a16-17.39", 0x2000, 0x872270b3, 2 }, // 11 + + { "a16-06-1.7", 0x2000, 0xb708134d, 3 }, // 12 gfx1 + { "a16-07-2.8", 0x2000, 0xcdaf7f83, 3 }, // 13 + { "a16-10.90", 0x2000, 0xe8e42454, 3 }, // 14 + { "a16-11-1.91", 0x2000, 0x1f766661, 3 }, // 15 + { "a16-04.5", 0x2000, 0xb2fae99f, 3 }, // 16 + { "a16-05-1.6", 0x2000, 0x85dfbb6e, 3 }, // 17 + { "a16-08.88", 0x2000, 0x1ddb6466, 3 }, // 18 + { "a16-09-1.89", 0x2000, 0x23d4c43c, 3 }, // 19 + + { "a16-18.mcu", 0x0800, 0x00000000, 4 | BRF_NODUMP }, // 20 cpu2 +}; + +STD_ROM_PICK(victnine) +STD_ROM_FN(victnine) + +static INT32 victnineInit() +{ + select_game = 2; + + return DrvInit(); +} + +struct BurnDriverD BurnDrvVictnine = { + "victnine", NULL, NULL, NULL, "1984", + "Victorious Nine\0", NULL, "Taito", "hardware", + NULL, NULL, NULL, NULL, + 0, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, victnineRomInfo, victnineRomName, NULL, NULL, VictnineInputInfo, VictnineDIPInfo, + victnineInit, DrvExit, DrvFrame, victnineDraw, NULL, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_funkybee.cpp b/src/burn/drivers/misc_pre90s/d_funkybee.cpp new file mode 100644 index 00000000..8f41b1b1 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_funkybee.cpp @@ -0,0 +1,752 @@ +// FB Alpha Funky Bee Driver Module +// Based on MAME driver by Zsolt Vasvari + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd, *Rom, *Gfx, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[2], DrvReset; +static UINT32 *Palette, *DrvPal; +static UINT8 DrvRecalcPal; + +static INT16 *pAY8910Buffer[3], *pFMBuffer = NULL; +static INT32 skylancr = 0; + +static INT32 funkybee_gfx_bank, funkybee_scroll_x, funkybee_flipscreen; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 3, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p1 right" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 1, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 4, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo funkybeeDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x01, "1C 3C" }, + {0x10, 0x01, 0x03, 0x00, "1C 4C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0x0c, 0x08, "2C 1C" }, + {0x10, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x10, 0x01, 0x0c, 0x04, "2C 3C" }, + {0x10, 0x01, 0x0c, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "4" }, + {0x10, 0x01, 0x30, 0x10, "5" }, + {0x10, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x40, 0x40, "20000" }, + {0x10, 0x01, 0x40, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(funkybee) + + +static struct BurnDIPInfo funkbeebDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x01, "1C 3C" }, + {0x10, 0x01, 0x03, 0x00, "1C 4C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0x0c, 0x08, "2C 1C" }, + {0x10, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x10, 0x01, 0x0c, 0x04, "2C 3C" }, + {0x10, 0x01, 0x0c, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x30, 0x30, "1" }, + {0x10, 0x01, 0x30, 0x20, "2" }, + {0x10, 0x01, 0x30, 0x10, "3" }, + {0x10, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x40, 0x40, "20000" }, + {0x10, 0x01, 0x40, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(funkbeeb) + +static struct BurnDIPInfo skylancrDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x01, "1C 3C" }, + {0x10, 0x01, 0x03, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0x0c, 0x08, "2C 1C" }, + {0x10, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x10, 0x01, 0x0c, 0x04, "2C 3C" }, + {0x10, 0x01, 0x0c, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x30, 0x30, "1" }, + {0x10, 0x01, 0x30, 0x20, "2" }, + {0x10, 0x01, 0x30, 0x10, "3" }, + {0x10, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x40, 0x40, "20000" }, + {0x10, 0x01, 0x40, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(skylancr) + +static struct BurnDIPInfo skylanceDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x01, "1C 3C" }, + {0x10, 0x01, 0x03, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0x0c, 0x08, "2C 1C" }, + {0x10, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x10, 0x01, 0x0c, 0x04, "2C 3C" }, + {0x10, 0x01, 0x0c, 0x00, "1C 6C" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "4" }, + {0x10, 0x01, 0x30, 0x10, "5" }, + {0x10, 0x01, 0x30, 0x00, "64" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x40, 0x40, "20000 50000" }, + {0x10, 0x01, 0x40, 0x00, "40000 70000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x00, "Upright" }, + {0x10, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(skylance) + + +UINT8 __fastcall funkybee_read(UINT16 address) +{ + UINT8 ret = 0; + + switch (address) + { + case 0xf000: + return 0; + + case 0xf800: + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy1[i] << i; + + return ret | DrvDips[0]; + } + + case 0xf801: + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy2[i] << i; + + return ret; + + } + + case 0xf802: + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy3[i] << i; + + return ret; + } + } + + return 0; +} + +void __fastcall funkybee_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + funkybee_scroll_x = data; + break; + + case 0xe800: + funkybee_flipscreen = data & 1; + break; + + case 0xe802: // coin counter + case 0xe803: + break; + + case 0xe805: + funkybee_gfx_bank = (data & 1) << 9; + break; + + case 0xf800: // watchdog + break; + } +} + +UINT8 __fastcall funkybee_in_port(UINT16 address) +{ + switch (address & 0xff) + { + case 0x02: + return AY8910Read(0); + } + + return 0; +} + +void __fastcall funkybee_out_port(UINT16 address, UINT8 data) +{ + switch (address & 0xff) + { + case 0x00: + case 0x01: + AY8910Write(0, address & 1, data); + break; + } +} + +static UINT8 funkybee_ay8910_read_A(UINT32) +{ + return DrvDips[1]; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + memset (Rom + 0x8000, 0, 0x0800); + memset (Rom + 0xa000, 0, 0x4000); + + funkybee_gfx_bank = 0; + funkybee_scroll_x = 0; + funkybee_flipscreen = 0; + ZetOpen(0); + ZetReset(); + ZetClose(); + + return 0; +} + +static void funkybee_gfx_decode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + if (tmp == NULL) { + return; + } + + static INT32 PlaneOffsets[2] = { 0, 4 }; + + static INT32 XOffsets[8] = { + 0, 1, 2, 3, 64, 65, 66, 67 + }; + + static INT32 YOffsets[32] = { + 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184, + 256, 264, 272, 280, 288, 296, 304, 312, 384, 392, 400, 408, 416, 424, 432, 440 + }; + + memcpy (tmp, Gfx, 0x4000); + + GfxDecode(0x400, 2, 8, 8, PlaneOffsets, XOffsets, YOffsets, 0x080, tmp, Gfx + 0x00000); + GfxDecode(0x100, 2, 8, 32, PlaneOffsets, XOffsets, YOffsets, 0x200, tmp, Gfx + 0x10000); + + BurnFree (tmp); +} + +static void funkybee_palette_init() +{ + for (INT32 i = 0; i < 32; i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (Prom[i] >> 6) & 0x01; + bit2 = (Prom[i] >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom = Next; Next += 0x10000; + Gfx = Next; Next += 0x20000; + Prom = Next; Next += 0x00020; + + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 3 * sizeof(INT16); + + Palette = (UINT32*)Next; Next += 0x00020 * sizeof(UINT32); + DrvPal = (UINT32*)Next; Next += 0x00020 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + if (skylancr) + { + if (BurnLoadRom(Rom + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(Rom + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(Rom + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(Gfx + 0x0000, 3, 1)) return 1; + if (BurnLoadRom(Gfx + 0x2000, 4, 1)) return 1; + if (BurnLoadRom(Prom + 0x0000, 5, 1)) return 1; + } else { + if (BurnLoadRom(Rom + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(Rom + 0x1000, 1, 1)) return 1; + if (BurnLoadRom(Rom + 0x2000, 2, 1)) return 1; + if (BurnLoadRom(Rom + 0x3000, 3, 1)) return 1; + if (BurnLoadRom(Gfx + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(Gfx + 0x2000, 5, 1)) return 1; + if (BurnLoadRom(Prom + 0x0000, 6, 1)) return 1; + } + + funkybee_gfx_decode(); + funkybee_palette_init(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(funkybee_read); + ZetSetWriteHandler(funkybee_write); + ZetSetInHandler(funkybee_in_port); + ZetSetOutHandler(funkybee_out_port); + ZetMapArea(0x0000, 0x4fff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0x4fff, 2, Rom + 0x0000); + ZetMapArea(0x8000, 0x87ff, 0, Rom + 0x8000); + ZetMapArea(0x8000, 0x87ff, 1, Rom + 0x8000); + ZetMapArea(0x8000, 0x87ff, 2, Rom + 0x8000); + ZetMapArea(0xa000, 0xdfff, 0, Rom + 0xa000); + ZetMapArea(0xa000, 0xdfff, 1, Rom + 0xa000); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, &funkybee_ay8910_read_A, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + skylancr = 0; + + ZetExit(); + AY8910Exit(0); + GenericTilesExit(); + + BurnFree (Mem); + + Palette = DrvPal = NULL; + + pFMBuffer = NULL; + Mem = MemEnd = Rom = Gfx = Prom = NULL; + + funkybee_gfx_bank = 0; + funkybee_scroll_x = 0; + funkybee_flipscreen = 0; + DrvRecalcPal = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalcPal) { + for (INT32 i = 0; i < 32; i++) { + UINT32 col = Palette[i]; + DrvPal[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + for (INT32 offa = 0; offa < 0x1c00; offa += 0x100) + { + for (INT32 offb = 0; offb < 0x20; offb++) + { + INT32 sy = (offa >> 5) ^ (funkybee_flipscreen * 0xf8); + INT32 sx = (offb << 3) ^ (funkybee_flipscreen * 0xf8); + + sx = (sx - funkybee_scroll_x) & 0xff; + + INT32 offs = offa + offb; + + INT32 code = Rom[0xa000 + offs] + ((Rom[0xc000 + offs] & 0x80) << 1) + funkybee_gfx_bank; + INT32 color = Rom[0xc000 + offs] & 0x03; + + if (funkybee_flipscreen) + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx - 8, sy - 32, color, 2, 0, Gfx); + else + Render8x8Tile_Clip(pTransDraw, code, sx - 12, sy, color, 2, 0, Gfx); + } + } + + for (INT32 offs = 0x0f; offs >= 0; offs--) + { + INT32 attr = Rom[0xbe00 + offs]; + INT32 code = (attr >> 2) | ((attr & 2) << 5); + INT32 color = 4 | (Rom[0xde10 + offs] & 3); + INT32 flipy = attr & 1; + INT32 flipx = funkybee_flipscreen; + INT32 sx = Rom[0xbe10 + offs] - 12; + INT32 sy = 224 - Rom[0xde00 + offs]; + + code = (code << 2) + funkybee_gfx_bank; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 0, sx, sy + 24, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 1, sx, sy + 16, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 2, sx, sy + 8, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code + 3, sx, sy + 0, color, 2, 0, 0, Gfx); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 0, sx, sy + 24, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 1, sx, sy + 16, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 2, sx, sy + 8, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code + 3, sx, sy + 0, color, 2, 0, 0, Gfx); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 0, sx, sy + 0, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 1, sx, sy + 8, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 2, sx, sy + 16, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code + 3, sx, sy + 24, color, 2, 0, 0, Gfx); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code + 0, sx, sy + 0, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_Clip(pTransDraw, code + 1, sx, sy + 8, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_Clip(pTransDraw, code + 2, sx, sy + 16, color, 2, 0, 0, Gfx); + Render8x8Tile_Mask_Clip(pTransDraw, code + 3, sx, sy + 24, color, 2, 0, 0, Gfx); + } + } + } + + for (INT32 offs = 0x1f;offs >= 0;offs--) + { + INT32 code = Rom[0xbc00 + offs] + funkybee_gfx_bank; + INT32 color = Rom[0xdf10] & 0x03; + INT32 sx = Rom[0xbf10]; + INT32 sy = offs << 3; + + if (funkybee_flipscreen) + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, (232 - sx) + 4, sy ^ 0xf8, color, 2, 0, 0, Gfx); + else + Render8x8Tile_Mask_Clip(pTransDraw, code, sx - 12, sy, color, 2, 0, 0, Gfx); + + code = Rom[0xbd00 + offs] + funkybee_gfx_bank; + color = Rom[0xdf11] & 0x03; + sx = Rom[0xbf11]; + sy = offs << 3; + + if (funkybee_flipscreen) + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, (232 - sx) + 4, sy ^ 0xf8, color, 2, 0, 0, Gfx); + else + Render8x8Tile_Mask_Clip(pTransDraw, code, sx - 12, sy, color, 2, 0, 0, Gfx); + } + + BurnTransferCopy(DrvPal); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetOpen(0); + ZetRun(3072000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0x8000; + ba.nLen = 0x0800; + ba.szName = "Work Ram"; + BurnAcb(&ba); + + ba.Data = Rom + 0xa000; + ba.nLen = 0x4000; + ba.szName = "Video Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(funkybee_gfx_bank); + SCAN_VAR(funkybee_scroll_x); + SCAN_VAR(funkybee_flipscreen); + } + + return 0; +} + +// Funky Bee + +static struct BurnRomInfo funkybeeRomDesc[] = { + { "funkybee.1", 0x1000, 0x3372cb33, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "funkybee.3", 0x1000, 0x7bf7c62f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "funkybee.2", 0x1000, 0x8cc0fe8e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "funkybee.4", 0x1000, 0x1e1aac26, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "funkybee.5", 0x2000, 0x86126655, 2 | BRF_GRA }, // 4 Graphics tiles + { "funkybee.6", 0x2000, 0x5fffd323, 2 | BRF_GRA }, // 5 + + { "funkybee.clr", 0x0020, 0xe2cf5fe2, 3 | BRF_GRA }, // 6 Color prom +}; + +STD_ROM_PICK(funkybee) +STD_ROM_FN(funkybee) + +struct BurnDriver BurnDrvfunkybee = { + "funkybee", NULL, NULL, NULL, "1982", + "Funky Bee\0", NULL, "Orca", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, funkybeeRomInfo, funkybeeRomName, NULL, NULL, DrvInputInfo, funkybeeDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x20, + 224, 232, 3, 4 +}; + + +// Funky Bee (bootleg, harder) + +static struct BurnRomInfo funkbeebRomDesc[] = { + { "senza_orca.fb1", 0x1000, 0x7f2e7f85, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "funkybee.3", 0x1000, 0x7bf7c62f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "funkybee.2", 0x1000, 0x8cc0fe8e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "senza_orca.fb4", 0x1000, 0x53c2db3b, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "funkybee.5", 0x2000, 0x86126655, 2 | BRF_GRA }, // 4 Graphics tiles + { "funkybee.6", 0x2000, 0x5fffd323, 2 | BRF_GRA }, // 5 + + { "funkybee.clr", 0x0020, 0xe2cf5fe2, 3 | BRF_GRA }, // 6 Color prom +}; + +STD_ROM_PICK(funkbeeb) +STD_ROM_FN(funkbeeb) + +struct BurnDriver BurnDrvfunkbeeb = { + "funkybeeb", "funkybee", NULL, NULL, "1982", + "Funky Bee (bootleg, harder)\0", NULL, "bootleg", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, funkbeebRomInfo, funkbeebRomName, NULL, NULL, DrvInputInfo, funkbeebDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x20, + 224, 232, 3, 4 +}; + + +// Sky Lancer + +static struct BurnRomInfo skylancrRomDesc[] = { + { "1sl.5a", 0x2000, 0xe80b315e, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "2sl.5c", 0x2000, 0x9d70567b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3sl.5d", 0x2000, 0x64c39457, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "4sl.6a", 0x2000, 0x9b4469a5, 2 | BRF_GRA }, // 3 Graphics tiles + { "5sl.6c", 0x2000, 0x29afa134, 2 | BRF_GRA }, // 4 + + { "18s030.1a", 0x0020, 0xe645bacb, 3 | BRF_GRA }, // 5 Color prom +}; + +STD_ROM_PICK(skylancr) +STD_ROM_FN(skylancr) + +static INT32 skylancrInit() +{ + skylancr = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvskylancr = { + "skylancr", NULL, NULL, NULL, "1983", + "Sky Lancer\0", NULL, "Orca", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, skylancrRomInfo, skylancrRomName, NULL, NULL, DrvInputInfo, skylancrDIPInfo, + skylancrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x20, + 224, 232, 3, 4 +}; + + +// Sky Lancer (Esco Trading Co license) + +static struct BurnRomInfo skylanceRomDesc[] = { + { "1.5a", 0x2000, 0x82d55824, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "2.5c", 0x2000, 0xdff3a682, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.5d", 0x1000, 0x7c006ee6, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "4.6a", 0x2000, 0x0f8ede07, 2 | BRF_GRA }, // 3 Graphics tiles + { "5.6b", 0x2000, 0x24cec070, 2 | BRF_GRA }, // 4 + + { "18s030.1a", 0x0020, 0xe645bacb, 3 | BRF_GRA }, // 5 Color prom +}; + +STD_ROM_PICK(skylance) +STD_ROM_FN(skylance) + +struct BurnDriver BurnDrvskylance = { + "skylancre", "skylancr", NULL, NULL, "1983", + "Sky Lancer (Esco Trading Co license)\0", NULL, "Orca (Esco Trading Co license)", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, skylanceRomInfo, skylanceRomName, NULL, NULL, DrvInputInfo, skylanceDIPInfo, + skylancrInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x20, + 224, 232, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_galaga.cpp b/src/burn/drivers/misc_pre90s/d_galaga.cpp new file mode 100644 index 00000000..b91ede61 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_galaga.cpp @@ -0,0 +1,1649 @@ +#include "tiles_generic.h" +#include "namco_snd.h" +#include "samples.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[3] = {0, 0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Rom3 = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvSharedRam1 = NULL; +static UINT8 *DrvSharedRam2 = NULL; +static UINT8 *DrvSharedRam3 = NULL; +static UINT8 *DrvPromPalette = NULL; +static UINT8 *DrvPromCharLookup = NULL; +static UINT8 *DrvPromSpriteLookup = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvCPU1FireIRQ; +static UINT8 DrvCPU2FireIRQ; +static UINT8 DrvCPU3FireIRQ; +static UINT8 DrvCPU2Halt; +static UINT8 DrvCPU3Halt; +static UINT8 DrvFlipScreen; +static UINT8 DrvStarControl[6]; +static UINT32 DrvStarScrollX; +static UINT32 DrvStarScrollY; + +static UINT8 IOChipCustomCommand; +static UINT8 IOChipCPU1FireIRQ; +static UINT8 IOChipMode; +static UINT8 IOChipCredits; +static UINT8 IOChipCoinPerCredit; +static UINT8 IOChipCreditPerCoin; +static UINT8 IOChipCustom[16]; +static UINT8 PrevInValue; + +static INT32 nCyclesDone[3], nCyclesTotal[3]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 3, "p2 start" }, + + {"Left" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = 0x7f; + DrvInput[1] = 0xff; + DrvInput[2] = 0xff; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] -= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + DrvInput[2] -= (DrvInputPort2[i] & 1) << i; + } +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x80, NULL }, + {0x0d, 0xff, 0xff, 0xf7, NULL }, + {0x0e, 0xff, 0xff, 0x97, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x80, 0x80, "Off" }, + {0x0c, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0d, 0x01, 0x03, 0x03, "Easy" }, + {0x0d, 0x01, 0x03, 0x00, "Medium" }, + {0x0d, 0x01, 0x03, 0x01, "Hard" }, + {0x0d, 0x01, 0x03, 0x02, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x08, "Off" }, + {0x0d, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0d, 0x01, 0x10, 0x10, "Off" }, + {0x0d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Rack Test" }, + {0x0d, 0x01, 0x20, 0x20, "Off" }, + {0x0d, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x80, 0x80, "Upright" }, + {0x0d, 0x01, 0x80, 0x00, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x0e, 0x01, 0x07, 0x04, "4 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x02, "3 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x06, "2 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x0e, 0x01, 0x07, 0x01, "2 Coins 3 Plays" }, + {0x0e, 0x01, 0x07, 0x03, "1 Coin 2 Plays" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x0e, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x0e, 0x01, 0x38, 0x20, "20k 60k 60k" }, + {0x0e, 0x01, 0x38, 0x18, "20k 60k" }, + {0x0e, 0x01, 0x38, 0x10, "20k 70k 70k" }, + {0x0e, 0x01, 0x38, 0x30, "20k 80k 80k" }, + {0x0e, 0x01, 0x38, 0x38, "30k 80k" }, + {0x0e, 0x01, 0x38, 0x08, "30k 100k 100k" }, + {0x0e, 0x01, 0x38, 0x28, "30k 120k 120k" }, + {0x0e, 0x01, 0x38, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0xc0, 0x00, "2" }, + {0x0e, 0x01, 0xc0, 0x80, "3" }, + {0x0e, 0x01, 0xc0, 0x40, "4" }, + {0x0e, 0x01, 0xc0, 0xc0, "5" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo GalagamwDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x80, NULL }, + {0x0d, 0xff, 0xff, 0xf7, NULL }, + {0x0e, 0xff, 0xff, 0x97, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x80, 0x80, "Off" }, + {0x0c, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits Game" }, + {0x0d, 0x01, 0x01, 0x00, "1 Player" }, + {0x0d, 0x01, 0x01, 0x01, "2 Players" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0d, 0x01, 0x06, 0x06, "Easy" }, + {0x0d, 0x01, 0x06, 0x00, "Medium" }, + {0x0d, 0x01, 0x06, 0x02, "Hard" }, + {0x0d, 0x01, 0x06, 0x04, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x08, "Off" }, + {0x0d, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0d, 0x01, 0x10, 0x10, "Off" }, + {0x0d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Rack Test" }, + {0x0d, 0x01, 0x20, 0x20, "Off" }, + {0x0d, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x80, 0x80, "Upright" }, + {0x0d, 0x01, 0x80, 0x00, "Cocktail" }, + + // Dip 3 + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x0e, 0x01, 0x07, 0x04, "4 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x02, "3 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x06, "2 Coins 1 Play" }, + {0x0e, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x0e, 0x01, 0x07, 0x01, "2 Coins 3 Plays" }, + {0x0e, 0x01, 0x07, 0x03, "1 Coin 2 Plays" }, + {0x0e, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x0e, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x0e, 0x01, 0x38, 0x20, "20k 60k 60k" }, + {0x0e, 0x01, 0x38, 0x18, "20k 60k" }, + {0x0e, 0x01, 0x38, 0x10, "20k 70k 70k" }, + {0x0e, 0x01, 0x38, 0x30, "20k 80k 80k" }, + {0x0e, 0x01, 0x38, 0x38, "30k 80k" }, + {0x0e, 0x01, 0x38, 0x08, "30k 100k 100k" }, + {0x0e, 0x01, 0x38, 0x28, "30k 120k 120k" }, + {0x0e, 0x01, 0x38, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0xc0, 0x00, "2" }, + {0x0e, 0x01, 0xc0, 0x80, "3" }, + {0x0e, 0x01, 0xc0, 0x40, "4" }, + {0x0e, 0x01, 0xc0, 0xc0, "5" }, +}; + +STDDIPINFO(Galagamw) + +static struct BurnRomInfo DrvRomDesc[] = { + { "gg1_1b.3p", 0x01000, 0xab036c9f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "gg1_2b.3m", 0x01000, 0xd9232240, BRF_ESS | BRF_PRG }, // 1 + { "gg1_3.2m", 0x01000, 0x753ce503, BRF_ESS | BRF_PRG }, // 2 + { "gg1_4b.2l", 0x01000, 0x499fcc76, BRF_ESS | BRF_PRG }, // 3 + + { "gg1_5b.3f", 0x01000, 0xbb5caae3, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "gg1_7b.2c", 0x01000, 0xd016686b, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "gg1_9.4l", 0x01000, 0x58b2f47c, BRF_GRA }, // 6 Characters + + { "gg1_11.4d", 0x01000, 0xad447c80, BRF_GRA }, // 7 Sprites + { "gg1_10.4f", 0x01000, 0xdd6f1afc, BRF_GRA }, // 8 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 9 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 10 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 11 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 12 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo GalagaoRomDesc[] = { + { "gg1-1.3p", 0x01000, 0xa3a0f743, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "gg1-2.3m", 0x01000, 0x43bb0d5c, BRF_ESS | BRF_PRG }, // 1 + { "gg1-3.2m", 0x01000, 0x753ce503, BRF_ESS | BRF_PRG }, // 2 + { "gg1-4.2l", 0x01000, 0x83874442, BRF_ESS | BRF_PRG }, // 3 + + { "gg1-5.3f", 0x01000, 0x3102fccd, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "gg1-7.2c", 0x01000, 0x8995088d, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "gg1-9.4l", 0x01000, 0x58b2f47c, BRF_GRA }, // 6 Characters + + { "gg1-11.4d", 0x01000, 0xad447c80, BRF_GRA }, // 7 Sprites + { "gg1-10.4f", 0x01000, 0xdd6f1afc, BRF_GRA }, // 8 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 9 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 10 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 11 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 12 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Galagao) +STD_ROM_FN(Galagao) + +static struct BurnRomInfo GalagamwRomDesc[] = { + { "3200a.bin", 0x01000, 0x3ef0b053, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "3300b.bin", 0x01000, 0x1b280831, BRF_ESS | BRF_PRG }, // 1 + { "3400c.bin", 0x01000, 0x16233d33, BRF_ESS | BRF_PRG }, // 2 + { "3500d.bin", 0x01000, 0x0aaf5c23, BRF_ESS | BRF_PRG }, // 3 + + { "3600e.bin", 0x01000, 0xbc556e76, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "3700g.bin", 0x01000, 0xb07f0aa4, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "2600j.bin", 0x01000, 0x58b2f47c, BRF_GRA }, // 6 Characters + + { "2800l.bin", 0x01000, 0xad447c80, BRF_GRA }, // 7 Sprites + { "2700k.bin", 0x01000, 0xdd6f1afc, BRF_GRA }, // 8 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 9 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 10 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 11 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 12 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Galagamw) +STD_ROM_FN(Galagamw) + +static struct BurnRomInfo GalagamfRomDesc[] = { + { "3200a.bin", 0x01000, 0x3ef0b053, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "3300b.bin", 0x01000, 0x1b280831, BRF_ESS | BRF_PRG }, // 1 + { "3400c.bin", 0x01000, 0x16233d33, BRF_ESS | BRF_PRG }, // 2 + { "3500d.bin", 0x01000, 0x0aaf5c23, BRF_ESS | BRF_PRG }, // 3 + + { "3600fast.bin", 0x01000, 0x23d586e5, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "3700g.bin", 0x01000, 0xb07f0aa4, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "2600j.bin", 0x01000, 0x58b2f47c, BRF_GRA }, // 6 Characters + + { "2800l.bin", 0x01000, 0xad447c80, BRF_GRA }, // 7 Sprites + { "2700k.bin", 0x01000, 0xdd6f1afc, BRF_GRA }, // 8 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 9 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 10 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 11 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 12 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Galagamf) +STD_ROM_FN(Galagamf) + +static struct BurnRomInfo GalagamkRomDesc[] = { + { "mk2-1", 0x01000, 0x23cea1e2, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mk2-2", 0x01000, 0x89695b1a, BRF_ESS | BRF_PRG }, // 1 + { "3400c.bin", 0x01000, 0x16233d33, BRF_ESS | BRF_PRG }, // 2 + { "mk2-4", 0x01000, 0x24b767f5, BRF_ESS | BRF_PRG }, // 3 + + { "gg1-5.3f", 0x01000, 0x3102fccd, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "gg1-7b.2c", 0x01000, 0xd016686b, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "gg1-9.4l", 0x01000, 0x58b2f47c, BRF_GRA }, // 6 Characters + + { "gg1-11.4d", 0x01000, 0xad447c80, BRF_GRA }, // 7 Sprites + { "gg1-10.4f", 0x01000, 0xdd6f1afc, BRF_GRA }, // 8 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 9 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 10 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 11 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 12 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Galagamk) +STD_ROM_FN(Galagamk) + +static struct BurnRomInfo GallagRomDesc[] = { + { "gallag.1", 0x01000, 0xa3a0f743, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "gallag.2", 0x01000, 0x5eda60a7, BRF_ESS | BRF_PRG }, // 1 + { "gallag.3", 0x01000, 0x753ce503, BRF_ESS | BRF_PRG }, // 2 + { "gallag.4", 0x01000, 0x83874442, BRF_ESS | BRF_PRG }, // 3 + + { "gallag.5", 0x01000, 0x3102fccd, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "gallag.7", 0x01000, 0x8995088d, BRF_ESS | BRF_PRG }, // 5 Z80 #3 Program Code + + { "gallag.6", 0x01000, 0x001b70bc, BRF_ESS | BRF_PRG }, // 6 Z80 #4 Program Code + + { "gallag.8", 0x01000, 0x169a98a4, BRF_GRA }, // 7 Characters + + { "gallag.a", 0x01000, 0xad447c80, BRF_GRA }, // 8 Sprites + { "gallag.9", 0x01000, 0xdd6f1afc, BRF_GRA }, // 9 + + { "prom-5.5n", 0x00020, 0x54603c6b, BRF_GRA }, // 10 PROMs + { "prom-4.2n", 0x00100, 0x59b6edab, BRF_GRA }, // 11 + { "prom-3.1c", 0x00100, 0x4a04bb6b, BRF_GRA }, // 12 + { "prom-1.1d", 0x00100, 0x7a2815b4, BRF_GRA }, // 13 + { "prom-2.5c", 0x00100, 0x77245b66, BRF_GRA }, // 14 +}; + +STD_ROM_PICK(Gallag) +STD_ROM_FN(Gallag) + +static struct BurnSampleInfo GalagaSampleDesc[] = { +#if !defined (ROM_VERIFY) + { "bang.wav", SAMPLE_NOLOOP }, + { "bang.wav", SAMPLE_NOLOOP }, +#endif + { "", 0 } +}; + +STD_SAMPLE_PICK(Galaga) +STD_SAMPLE_FN(Galaga) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x04000; + DrvZ80Rom2 = Next; Next += 0x04000; + DrvZ80Rom3 = Next; Next += 0x04000; + DrvPromPalette = Next; Next += 0x00020; + DrvPromCharLookup = Next; Next += 0x00100; + DrvPromSpriteLookup = Next; Next += 0x00100; + NamcoSoundProm = Next; Next += 0x00100; + + RamStart = Next; + + DrvVideoRam = Next; Next += 0x00800; + DrvSharedRam1 = Next; Next += 0x00400; + DrvSharedRam1 = Next; Next += 0x04000; + DrvSharedRam2 = Next; Next += 0x00400; + DrvSharedRam3 = Next; Next += 0x00400; + + RamEnd = Next; + + DrvChars = Next; Next += 0x100 * 8 * 8; + DrvSprites = Next; Next += 0x080 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 576 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnSampleReset(); + + DrvCPU1FireIRQ = 0; + DrvCPU2FireIRQ = 0; + DrvCPU3FireIRQ = 0; + DrvCPU2Halt = 0; + DrvCPU3Halt = 0; + DrvFlipScreen = 0; + for (INT32 i = 0; i < 6; i++) { + DrvStarControl[i] = 0; + } + DrvStarScrollX = 0; + DrvStarScrollY = 0; + + IOChipCustomCommand = 0; + IOChipCPU1FireIRQ = 0; + IOChipMode = 0; + IOChipCredits = 0; + IOChipCoinPerCredit = 0; + IOChipCreditPerCoin = 0; + for (INT32 i = 0; i < 16; i++) { + IOChipCustom[i] = 0; + } + + return 0; +} + +static void Namco54XXWrite(INT32 Data) +{ + static INT32 Fetch; + static INT32 FetchMode; + static UINT8 Config1[4], Config2[4], Config3[5]; + + if (Fetch) { + switch (FetchMode) { + default: + case 1: + Config1[4 - (Fetch--)] = Data; + break; + + case 2: + Config2[4 - (Fetch--)] = Data; + break; + + case 3: + Config3[5 - (Fetch--)] = Data; + break; + } + } else { + switch (Data & 0xf0) { + case 0x00: // nop + break; + + case 0x10: // output sound on pins 4-7 only + if (memcmp(Config1,"\x40\x00\x02\xdf",4) == 0) + // bosco + // galaga + // xevious + BurnSamplePlay(0); +// else if (memcmp(Config1,"\x10\x00\x80\xff",4) == 0) + // xevious +// sample_start(0, 1, 0); +// else if (memcmp(Config1,"\x80\x80\x01\xff",4) == 0) + // xevious +// sample_start(0, 2, 0); + break; + + case 0x20: // output sound on pins 8-11 only +// if (memcmp(Config2,"\x40\x40\x01\xff",4) == 0) + // xevious +// sample_start(1, 3, 0); +// BurnSamplePlay(1); + /*else*/ if (memcmp(Config2,"\x30\x30\x03\xdf",4) == 0) + // bosco + // galaga + BurnSamplePlay(1); +// else if (memcmp(Config2,"\x60\x30\x03\x66",4) == 0) + // polepos +// sample_start( 0, 0, 0 ); + break; + + case 0x30: + Fetch = 4; + FetchMode = 1; + break; + + case 0x40: + Fetch = 4; + FetchMode = 2; + break; + + case 0x50: // output sound on pins 17-20 only +// if (memcmp(Config3,"\x08\x04\x21\x00\xf1",5) == 0) + // bosco +// sample_start(2, 2, 0); + break; + + case 0x60: + Fetch = 5; + FetchMode = 3; + break; + + case 0x70: + // polepos + /* 0x7n = Screech sound. n = pitch (if 0 then no sound) */ + /* followed by 0x60 command? */ + if (( Data & 0x0f ) == 0) { +// if (sample_playing(1)) +// sample_stop(1); + } else { +// INT32 freq = (INT32)( ( 44100.0f / 10.0f ) * (float)(Data & 0x0f) ); + +// if (!sample_playing(1)) +// sample_start(1, 1, 1); +// sample_set_freq(1, freq); + } + break; + } + } +} + +UINT8 __fastcall GalagaZ80ProgRead(UINT16 a) +{ + switch (a) { + case 0x6800: + case 0x6801: + case 0x6802: + case 0x6803: + case 0x6804: + case 0x6805: + case 0x6806: + case 0x6807: { + INT32 Offset = a - 0x6800; + INT32 Bit0 = (DrvDip[2] >> Offset) & 0x01; + INT32 Bit1 = (DrvDip[1] >> Offset) & 0x01; + + return Bit0 | (Bit1 << 1); + } + + case 0x7000: + case 0x7001: + case 0x7002: + case 0x7003: + case 0x7004: + case 0x7005: + case 0x7006: + case 0x7007: + case 0x7008: + case 0x7009: + case 0x700a: + case 0x700b: + case 0x700c: + case 0x700d: + case 0x700e: + case 0x700f: { + INT32 Offset = a - 0x7000; + + switch (IOChipCustomCommand) { + case 0x71: + case 0xb1: { + if (Offset == 0) { + if (IOChipMode) { + return DrvInput[0] | DrvDip[0]; + } else { + UINT8 In; + static UINT8 CoinInserted; + + In = DrvInput[0] | DrvDip[0]; + if (In != PrevInValue) { + if (IOChipCoinPerCredit > 0) { + if ((In & 0x70) != 0x70 && IOChipCredits < 99) { + CoinInserted++; + if (CoinInserted >= IOChipCoinPerCredit) { + IOChipCredits += IOChipCreditPerCoin; + CoinInserted = 0; + } + } + } else { + IOChipCredits = 2; + } + + if ((In & 0x04) == 0) { + if (IOChipCredits >= 1) IOChipCredits--; + } + + if ((In & 0x08) == 0) { + if (IOChipCredits >= 2) IOChipCredits -= 2; + } + } + + PrevInValue = In; + + return (IOChipCredits / 10) * 16 + IOChipCredits % 10; + } + } + + if (Offset == 1) return DrvInput[1]; + if (Offset == 2) return DrvInput[2]; + } + } + + return 0xff; + } + + case 0x7100: { + return IOChipCustomCommand; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #%i Read %04x\n"), ZetGetActive(), a); + } + } + + return 0; +} + +void __fastcall GalagaZ80ProgWrite(UINT16 a, UINT8 d) +{ + if (a >= 0x6800 && a <= 0x681f) { NamcoSoundWrite(a - 0x6800, d); return; } + + switch (a) { + case 0x6820: { + DrvCPU1FireIRQ = d & 0x01; + if (!DrvCPU1FireIRQ) { + + } + return; + } + + case 0x6821: { + DrvCPU2FireIRQ = d & 0x01; + if (!DrvCPU2FireIRQ) { + + } + return; + } + + case 0x6822: { + DrvCPU3FireIRQ = !(d & 0x01); + return; + } + + case 0x6823: { + if (!(d & 0x01)) { + INT32 nActive = ZetGetActive(); + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(2); + ZetReset(); + ZetClose(); + ZetOpen(nActive); + DrvCPU2Halt = 1; + DrvCPU3Halt = 1; + return; + } else { + DrvCPU2Halt = 0; + DrvCPU3Halt = 0; + } + } + + case 0x6830: { + // watchdog write + return; + } + + case 0x7000: + case 0x7001: + case 0x7002: + case 0x7003: + case 0x7004: + case 0x7005: + case 0x7006: + case 0x7007: + case 0x7008: + case 0x7009: + case 0x700a: + case 0x700b: + case 0x700c: + case 0x700d: + case 0x700e: + case 0x700f: { + INT32 Offset = a - 0x7000; + IOChipCustom[Offset] = d; + Namco54XXWrite(d); + + switch (IOChipCustomCommand) { + case 0xe1: { + if (Offset == 7) { + IOChipCoinPerCredit = IOChipCustom[1]; + IOChipCreditPerCoin = IOChipCustom[2]; + } + break; + } + } + + return; + } + + case 0x7100: { + IOChipCustomCommand = d; + IOChipCPU1FireIRQ = 1; + + switch (IOChipCustomCommand) { + case 0x10: { + IOChipCPU1FireIRQ = 0; + return; + } + + case 0xa1: { + IOChipMode = 1; + return; + } + + case 0xe1: { + IOChipCredits = 0; + IOChipMode = 0; + return; + } + } + + return; + } + + case 0xa000: + case 0xa001: + case 0xa002: + case 0xa003: + case 0xa004: + case 0xa005: + case 0xa006: { + DrvStarControl[a - 0xa000] = d & 0x01; + return; + } + + case 0xa007: { + DrvFlipScreen = d & 0x01; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #%i Write %04x, %02x\n"), ZetGetActive(), a, d); + } + } +} + +static INT32 CharPlaneOffsets[2] = { 0, 4 }; +static INT32 CharXOffsets[8] = { 64, 65, 66, 67, 0, 1, 2, 3 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 SpritePlaneOffsets[2] = { 0, 4 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 64, 65, 66, 67, 128, 129, 130, 131, 192, 193, 194, 195 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 256, 264, 272, 280, 288, 296, 304, 312 }; + +static void MachineInit() +{ + ZetInit(3); + ZetOpen(0); + ZetSetReadHandler(GalagaZ80ProgRead); + ZetSetWriteHandler(GalagaZ80ProgWrite); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom1); + ZetMapArea(0x8000, 0x87ff, 0, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 1, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 2, DrvVideoRam); + ZetMapArea(0x8800, 0x8bff, 0, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 1, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 2, DrvSharedRam1); + ZetMapArea(0x9000, 0x93ff, 0, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 1, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 2, DrvSharedRam2); + ZetMapArea(0x9800, 0x9bff, 0, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 1, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 2, DrvSharedRam3); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(GalagaZ80ProgRead); + ZetSetWriteHandler(GalagaZ80ProgWrite); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom2); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom2); + ZetMapArea(0x8000, 0x87ff, 0, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 1, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 2, DrvVideoRam); + ZetMapArea(0x8800, 0x8bff, 0, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 1, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 2, DrvSharedRam1); + ZetMapArea(0x9000, 0x93ff, 0, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 1, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 2, DrvSharedRam2); + ZetMapArea(0x9800, 0x9bff, 0, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 1, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 2, DrvSharedRam3); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(GalagaZ80ProgRead); + ZetSetWriteHandler(GalagaZ80ProgWrite); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom3); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom3); + ZetMapArea(0x8000, 0x87ff, 0, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 1, DrvVideoRam); + ZetMapArea(0x8000, 0x87ff, 2, DrvVideoRam); + ZetMapArea(0x8800, 0x8bff, 0, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 1, DrvSharedRam1); + ZetMapArea(0x8800, 0x8bff, 2, DrvSharedRam1); + ZetMapArea(0x9000, 0x93ff, 0, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 1, DrvSharedRam2); + ZetMapArea(0x9000, 0x93ff, 2, DrvSharedRam2); + ZetMapArea(0x9800, 0x9bff, 0, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 1, DrvSharedRam3); + ZetMapArea(0x9800, 0x9bff, 2, DrvSharedRam3); + ZetMemEnd(); + ZetClose(); + + NamcoSoundInit(18432000 / 6 / 32); + BurnSampleInit(80, 0); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x02000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x02000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x01000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x80, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(NamcoSoundProm, 12, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 GallagInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x02000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x02000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x01000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x80, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromCharLookup, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromSpriteLookup, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(NamcoSoundProm, 13, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + NamcoSoundExit(); + BurnSampleExit(); + ZetExit(); + + BurnFree(Mem); + + DrvCPU1FireIRQ = 0; + DrvCPU2FireIRQ = 0; + DrvCPU3FireIRQ = 0; + DrvCPU2Halt = 0; + DrvCPU3Halt = 0; + DrvFlipScreen = 0; + for (INT32 i = 0; i < 6; i++) { + DrvStarControl[i] = 0; + } + DrvStarScrollX = 0; + DrvStarScrollY = 0; + + IOChipCustomCommand = 0; + IOChipCPU1FireIRQ = 0; + IOChipMode = 0; + IOChipCredits = 0; + IOChipCoinPerCredit = 0; + IOChipCreditPerCoin = 0; + for (INT32 i = 0; i < 16; i++) { + IOChipCustom[i] = 0; + } + + return 0; +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT32 Palette[96]; + + for (i = 0; i < 32; i++) { + INT32 bit0, bit1, bit2, r, g, b; + + bit0 = (DrvPromPalette[i] >> 0) & 0x01; + bit1 = (DrvPromPalette[i] >> 1) & 0x01; + bit2 = (DrvPromPalette[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + bit0 = (DrvPromPalette[i] >> 3) & 0x01; + bit1 = (DrvPromPalette[i] >> 4) & 0x01; + bit2 = (DrvPromPalette[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + bit0 = 0; + bit1 = (DrvPromPalette[i] >> 6) & 0x01; + bit2 = (DrvPromPalette[i] >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = BurnHighCol(r, g, b, 0); + } + + for (i = 0; i < 64; i++) { + INT32 bits, r, g, b; + static const INT32 map[4] = { 0x00, 0x47, 0x97, 0xde }; + + bits = (i >> 0) & 0x03; + r = map[bits]; + bits = (i >> 2) & 0x03; + g = map[bits]; + bits = (i >> 4) & 0x03; + b = map[bits]; + + Palette[32 + i] = BurnHighCol(r, g, b, 0); + } + + for (i = 0; i < 256; i++) { + DrvPalette[i] = Palette[((DrvPromCharLookup[i]) & 0x0f) + 0x10]; + } + + for (i = 0; i < 256; i++) { + DrvPalette[256 + i] = Palette[DrvPromSpriteLookup[i] & 0x0f]; + } + + for (i = 0; i < 64; i++) { + DrvPalette[512 + i] = Palette[32 + i]; + } +} + +struct Star { + UINT16 x, y; + UINT8 Colour, Set; +}; + +const struct Star StarSeedTab[252] = { + // set 0 + {0x0085, 0x0006, 0x35, 0x00}, + {0x008F, 0x0008, 0x30, 0x00}, + {0x00E5, 0x001B, 0x07, 0x00}, + {0x0022, 0x001C, 0x31, 0x00}, + {0x00E5, 0x0025, 0x1D, 0x00}, + {0x0015, 0x0026, 0x29, 0x00}, + {0x0080, 0x002D, 0x3B, 0x00}, + {0x0097, 0x002E, 0x1C, 0x00}, + {0x00BA, 0x003B, 0x05, 0x00}, + {0x0036, 0x003D, 0x36, 0x00}, + {0x0057, 0x0044, 0x09, 0x00}, + {0x00CF, 0x0044, 0x3D, 0x00}, + {0x0061, 0x004E, 0x27, 0x00}, + {0x0087, 0x0064, 0x1A, 0x00}, + {0x00D6, 0x0064, 0x17, 0x00}, + {0x000B, 0x006C, 0x3C, 0x00}, + {0x0006, 0x006D, 0x24, 0x00}, + {0x0018, 0x006E, 0x3A, 0x00}, + {0x00A9, 0x0079, 0x23, 0x00}, + {0x008A, 0x007B, 0x11, 0x00}, + {0x00D6, 0x0080, 0x0C, 0x00}, + {0x0067, 0x0082, 0x3F, 0x00}, + {0x0039, 0x0083, 0x38, 0x00}, + {0x0072, 0x0083, 0x14, 0x00}, + {0x00EC, 0x0084, 0x16, 0x00}, + {0x008E, 0x0085, 0x10, 0x00}, + {0x0020, 0x0088, 0x25, 0x00}, + {0x0095, 0x008A, 0x0F, 0x00}, + {0x000E, 0x008D, 0x00, 0x00}, + {0x0006, 0x0091, 0x2E, 0x00}, + {0x0007, 0x0094, 0x0D, 0x00}, + {0x00AE, 0x0097, 0x0B, 0x00}, + {0x0000, 0x0098, 0x2D, 0x00}, + {0x0086, 0x009B, 0x01, 0x00}, + {0x0058, 0x00A1, 0x34, 0x00}, + {0x00FE, 0x00A1, 0x3E, 0x00}, + {0x00A2, 0x00A8, 0x1F, 0x00}, + {0x0041, 0x00AA, 0x0A, 0x00}, + {0x003F, 0x00AC, 0x32, 0x00}, + {0x00DE, 0x00AC, 0x03, 0x00}, + {0x00D4, 0x00B9, 0x26, 0x00}, + {0x006D, 0x00BB, 0x1B, 0x00}, + {0x0062, 0x00BD, 0x39, 0x00}, + {0x00C9, 0x00BE, 0x18, 0x00}, + {0x006C, 0x00C1, 0x04, 0x00}, + {0x0059, 0x00C3, 0x21, 0x00}, + {0x0060, 0x00CC, 0x0E, 0x00}, + {0x0091, 0x00CC, 0x12, 0x00}, + {0x003F, 0x00CF, 0x06, 0x00}, + {0x00F7, 0x00CF, 0x22, 0x00}, + {0x0044, 0x00D0, 0x33, 0x00}, + {0x0034, 0x00D2, 0x08, 0x00}, + {0x00D3, 0x00D9, 0x20, 0x00}, + {0x0071, 0x00DD, 0x37, 0x00}, + {0x0073, 0x00E1, 0x2C, 0x00}, + {0x00B9, 0x00E3, 0x2F, 0x00}, + {0x00A9, 0x00E4, 0x13, 0x00}, + {0x00D3, 0x00E7, 0x19, 0x00}, + {0x0037, 0x00ED, 0x02, 0x00}, + {0x00BD, 0x00F4, 0x15, 0x00}, + {0x000F, 0x00F6, 0x28, 0x00}, + {0x004F, 0x00F7, 0x2B, 0x00}, + {0x00FB, 0x00FF, 0x2A, 0x00}, + + // set 1 + {0x00FE, 0x0004, 0x3D, 0x01}, + {0x00C4, 0x0006, 0x10, 0x01}, + {0x001E, 0x0007, 0x2D, 0x01}, + {0x0083, 0x000B, 0x1F, 0x01}, + {0x002E, 0x000D, 0x3C, 0x01}, + {0x001F, 0x000E, 0x00, 0x01}, + {0x00D8, 0x000E, 0x2C, 0x01}, + {0x0003, 0x000F, 0x17, 0x01}, + {0x0095, 0x0011, 0x3F, 0x01}, + {0x006A, 0x0017, 0x35, 0x01}, + {0x00CC, 0x0017, 0x02, 0x01}, + {0x0000, 0x0018, 0x32, 0x01}, + {0x0092, 0x001D, 0x36, 0x01}, + {0x00E3, 0x0021, 0x04, 0x01}, + {0x002F, 0x002D, 0x37, 0x01}, + {0x00F0, 0x002F, 0x0C, 0x01}, + {0x009B, 0x003E, 0x06, 0x01}, + {0x00A4, 0x004C, 0x07, 0x01}, + {0x00EA, 0x004D, 0x13, 0x01}, + {0x0084, 0x004E, 0x21, 0x01}, + {0x0033, 0x0052, 0x0F, 0x01}, + {0x0070, 0x0053, 0x0E, 0x01}, + {0x0006, 0x0059, 0x08, 0x01}, + {0x0081, 0x0060, 0x28, 0x01}, + {0x0037, 0x0061, 0x29, 0x01}, + {0x008F, 0x0067, 0x2F, 0x01}, + {0x001B, 0x006A, 0x1D, 0x01}, + {0x00BF, 0x007C, 0x12, 0x01}, + {0x0051, 0x007F, 0x31, 0x01}, + {0x0061, 0x0086, 0x25, 0x01}, + {0x006A, 0x008F, 0x0D, 0x01}, + {0x006A, 0x0091, 0x19, 0x01}, + {0x0090, 0x0092, 0x05, 0x01}, + {0x003B, 0x0096, 0x24, 0x01}, + {0x008C, 0x0097, 0x0A, 0x01}, + {0x0006, 0x0099, 0x03, 0x01}, + {0x0038, 0x0099, 0x38, 0x01}, + {0x00A8, 0x0099, 0x18, 0x01}, + {0x0076, 0x00A6, 0x20, 0x01}, + {0x00AD, 0x00A6, 0x1C, 0x01}, + {0x00EC, 0x00A6, 0x1E, 0x01}, + {0x0086, 0x00AC, 0x15, 0x01}, + {0x0078, 0x00AF, 0x3E, 0x01}, + {0x007B, 0x00B3, 0x09, 0x01}, + {0x0027, 0x00B8, 0x39, 0x01}, + {0x0088, 0x00C2, 0x23, 0x01}, + {0x0044, 0x00C3, 0x3A, 0x01}, + {0x00CF, 0x00C5, 0x34, 0x01}, + {0x0035, 0x00C9, 0x30, 0x01}, + {0x006E, 0x00D1, 0x3B, 0x01}, + {0x00D6, 0x00D7, 0x16, 0x01}, + {0x003A, 0x00D9, 0x2B, 0x01}, + {0x00AB, 0x00E0, 0x11, 0x01}, + {0x00E0, 0x00E2, 0x1B, 0x01}, + {0x006F, 0x00E6, 0x0B, 0x01}, + {0x00B8, 0x00E8, 0x14, 0x01}, + {0x00D9, 0x00E8, 0x1A, 0x01}, + {0x00F9, 0x00E8, 0x22, 0x01}, + {0x0004, 0x00F1, 0x2E, 0x01}, + {0x0049, 0x00F8, 0x26, 0x01}, + {0x0010, 0x00F9, 0x01, 0x01}, + {0x0039, 0x00FB, 0x33, 0x01}, + {0x0028, 0x00FC, 0x27, 0x01}, + + // set 2 + {0x00FA, 0x0006, 0x19, 0x02}, + {0x00E4, 0x0007, 0x2D, 0x02}, + {0x0072, 0x000A, 0x03, 0x02}, + {0x0084, 0x001B, 0x00, 0x02}, + {0x00BA, 0x001D, 0x29, 0x02}, + {0x00E3, 0x0022, 0x04, 0x02}, + {0x00D1, 0x0026, 0x2A, 0x02}, + {0x0089, 0x0032, 0x30, 0x02}, + {0x005B, 0x0036, 0x27, 0x02}, + {0x0084, 0x003A, 0x36, 0x02}, + {0x0053, 0x003F, 0x0D, 0x02}, + {0x0008, 0x0040, 0x1D, 0x02}, + {0x0055, 0x0040, 0x1A, 0x02}, + {0x00AA, 0x0041, 0x31, 0x02}, + {0x00FB, 0x0041, 0x2B, 0x02}, + {0x00BC, 0x0046, 0x16, 0x02}, + {0x0093, 0x0052, 0x39, 0x02}, + {0x00B9, 0x0057, 0x10, 0x02}, + {0x0054, 0x0059, 0x28, 0x02}, + {0x00E6, 0x005A, 0x01, 0x02}, + {0x00A7, 0x005D, 0x1B, 0x02}, + {0x002D, 0x005E, 0x35, 0x02}, + {0x0014, 0x0062, 0x21, 0x02}, + {0x0069, 0x006D, 0x1F, 0x02}, + {0x00CE, 0x006F, 0x0B, 0x02}, + {0x00DF, 0x0075, 0x2F, 0x02}, + {0x00CB, 0x0077, 0x12, 0x02}, + {0x004E, 0x007C, 0x23, 0x02}, + {0x004A, 0x0084, 0x0F, 0x02}, + {0x0012, 0x0086, 0x25, 0x02}, + {0x0068, 0x008C, 0x32, 0x02}, + {0x0003, 0x0095, 0x20, 0x02}, + {0x000A, 0x009C, 0x17, 0x02}, + {0x005B, 0x00A3, 0x08, 0x02}, + {0x005F, 0x00A4, 0x3E, 0x02}, + {0x0072, 0x00A4, 0x2E, 0x02}, + {0x00CC, 0x00A6, 0x06, 0x02}, + {0x008A, 0x00AB, 0x0C, 0x02}, + {0x00E0, 0x00AD, 0x26, 0x02}, + {0x00F3, 0x00AF, 0x0A, 0x02}, + {0x0075, 0x00B4, 0x13, 0x02}, + {0x0068, 0x00B7, 0x11, 0x02}, + {0x006D, 0x00C2, 0x2C, 0x02}, + {0x0076, 0x00C3, 0x14, 0x02}, + {0x00CF, 0x00C4, 0x1E, 0x02}, + {0x0004, 0x00C5, 0x1C, 0x02}, + {0x0013, 0x00C6, 0x3F, 0x02}, + {0x00B9, 0x00C7, 0x3C, 0x02}, + {0x0005, 0x00D7, 0x34, 0x02}, + {0x0095, 0x00D7, 0x3A, 0x02}, + {0x00FC, 0x00D8, 0x02, 0x02}, + {0x00E7, 0x00DC, 0x09, 0x02}, + {0x001D, 0x00E1, 0x05, 0x02}, + {0x0005, 0x00E6, 0x33, 0x02}, + {0x001C, 0x00E9, 0x3B, 0x02}, + {0x00A2, 0x00ED, 0x37, 0x02}, + {0x0028, 0x00EE, 0x07, 0x02}, + {0x00DD, 0x00EF, 0x18, 0x02}, + {0x006D, 0x00F0, 0x38, 0x02}, + {0x00A1, 0x00F2, 0x0E, 0x02}, + {0x0074, 0x00F7, 0x3D, 0x02}, + {0x0069, 0x00F9, 0x22, 0x02}, + {0x003F, 0x00FF, 0x24, 0x02}, + + // set 3 + {0x0071, 0x0010, 0x34, 0x03}, + {0x00AF, 0x0011, 0x23, 0x03}, + {0x00A0, 0x0014, 0x26, 0x03}, + {0x0002, 0x0017, 0x02, 0x03}, + {0x004B, 0x0019, 0x31, 0x03}, + {0x0093, 0x001C, 0x0E, 0x03}, + {0x001B, 0x001E, 0x25, 0x03}, + {0x0032, 0x0020, 0x2E, 0x03}, + {0x00EE, 0x0020, 0x3A, 0x03}, + {0x0079, 0x0022, 0x2F, 0x03}, + {0x006C, 0x0023, 0x17, 0x03}, + {0x00BC, 0x0025, 0x11, 0x03}, + {0x0041, 0x0029, 0x30, 0x03}, + {0x001C, 0x002E, 0x32, 0x03}, + {0x00B9, 0x0031, 0x01, 0x03}, + {0x0083, 0x0032, 0x05, 0x03}, + {0x0095, 0x003A, 0x12, 0x03}, + {0x000D, 0x003F, 0x07, 0x03}, + {0x0020, 0x0041, 0x33, 0x03}, + {0x0092, 0x0045, 0x2C, 0x03}, + {0x00D4, 0x0047, 0x08, 0x03}, + {0x00A1, 0x004B, 0x2D, 0x03}, + {0x00D2, 0x004B, 0x3B, 0x03}, + {0x00D6, 0x0052, 0x24, 0x03}, + {0x009A, 0x005F, 0x1C, 0x03}, + {0x0016, 0x0060, 0x3D, 0x03}, + {0x001A, 0x0063, 0x1F, 0x03}, + {0x00CD, 0x0066, 0x28, 0x03}, + {0x00FF, 0x0067, 0x10, 0x03}, + {0x0035, 0x0069, 0x20, 0x03}, + {0x008F, 0x006C, 0x04, 0x03}, + {0x00CA, 0x006C, 0x2A, 0x03}, + {0x005A, 0x0074, 0x09, 0x03}, + {0x0060, 0x0078, 0x38, 0x03}, + {0x0072, 0x0079, 0x1E, 0x03}, + {0x0037, 0x007F, 0x29, 0x03}, + {0x0012, 0x0080, 0x14, 0x03}, + {0x0029, 0x0082, 0x2B, 0x03}, + {0x0084, 0x0098, 0x36, 0x03}, + {0x0032, 0x0099, 0x37, 0x03}, + {0x00BB, 0x00A0, 0x19, 0x03}, + {0x003E, 0x00A3, 0x3E, 0x03}, + {0x004A, 0x00A6, 0x1A, 0x03}, + {0x0029, 0x00A7, 0x21, 0x03}, + {0x009D, 0x00B7, 0x22, 0x03}, + {0x006C, 0x00B9, 0x15, 0x03}, + {0x000C, 0x00C0, 0x0A, 0x03}, + {0x00C2, 0x00C3, 0x0F, 0x03}, + {0x002F, 0x00C9, 0x0D, 0x03}, + {0x00D2, 0x00CE, 0x16, 0x03}, + {0x00F3, 0x00CE, 0x0B, 0x03}, + {0x0075, 0x00CF, 0x27, 0x03}, + {0x001A, 0x00D5, 0x35, 0x03}, + {0x0026, 0x00D6, 0x39, 0x03}, + {0x0080, 0x00DA, 0x3C, 0x03}, + {0x00A9, 0x00DD, 0x00, 0x03}, + {0x00BC, 0x00EB, 0x03, 0x03}, + {0x0032, 0x00EF, 0x1B, 0x03}, + {0x0067, 0x00F0, 0x3F, 0x03}, + {0x00EF, 0x00F1, 0x18, 0x03}, + {0x00A8, 0x00F3, 0x0C, 0x03}, + {0x00DE, 0x00F9, 0x1D, 0x03}, + {0x002C, 0x00FA, 0x13, 0x03} +}; + +static void DrvRenderStars() +{ + if (DrvStarControl[5] == 1) { + INT32 StarCounter; + INT32 SetA, SetB; + + SetA = DrvStarControl[3]; + SetB = DrvStarControl[4] | 0x02; + + for (StarCounter = 0; StarCounter < 252; StarCounter++) { + INT32 x, y; + + if ((SetA == StarSeedTab[StarCounter].Set) || (SetB == StarSeedTab[StarCounter].Set)) { + x = (StarSeedTab[StarCounter].x + DrvStarScrollX) % 256 + 16; + y = (112 + StarSeedTab[StarCounter].y + DrvStarScrollY) % 256; + + if (x >= 0 && x < 288 && y >= 0 && y < 224) { + pTransDraw[(y * nScreenWidth) + x] = StarSeedTab[StarCounter].Colour + 512; + } + } + + } + } +} + +static void DrvRenderTilemap() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex, Row, Col; + + for (mx = 0; mx < 28; mx++) { + for (my = 0; my < 36; my++) { + Row = mx + 2; + Col = my - 2; + if (Col & 0x20) { + TileIndex = Row + ((Col & 0x1f) << 5); + } else { + TileIndex = Col + (Row << 5); + } + + Code = DrvVideoRam[TileIndex + 0x000] & 0x7f; + Colour = DrvVideoRam[TileIndex + 0x400] & 0x3f; + + y = 8 * mx; + x = 8 * my; + + if (DrvFlipScreen) { + x = 280 - x; + y = 216 - y; + } + + if (x > 8 && x < 280 && y > 8 && y < 216) { + if (DrvFlipScreen) { + Render8x8Tile_FlipXY(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } else { + if (DrvFlipScreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } + } + } +} + +static void DrvRenderSprites() +{ + UINT8 *SpriteRam1 = DrvSharedRam1 + 0x380; + UINT8 *SpriteRam2 = DrvSharedRam2 + 0x380; + UINT8 *SpriteRam3 = DrvSharedRam3 + 0x380; + + for (INT32 Offset = 0; Offset < 0x80; Offset += 2) { + static const INT32 GfxOffset[2][2] = { + { 0, 1 }, + { 2, 3 } + }; + INT32 Sprite = SpriteRam1[Offset + 0] & 0x7f; + INT32 Colour = SpriteRam1[Offset + 1] & 0x3f; + INT32 sx = SpriteRam2[Offset + 1] - 40 + (0x100 * (SpriteRam3[Offset + 1] & 0x03)); + INT32 sy = 256 - SpriteRam2[Offset + 0] + 1; + INT32 xFlip = (SpriteRam3[Offset + 0] & 0x01); + INT32 yFlip = (SpriteRam3[Offset + 0] & 0x02) >> 1; + INT32 xSize = (SpriteRam3[Offset + 0] & 0x04) >> 2; + INT32 ySize = (SpriteRam3[Offset + 0] & 0x08) >> 3; + + sy -= 16 * ySize; + sy = (sy & 0xff) - 32; + + if (DrvFlipScreen) { + xFlip = !xFlip; + yFlip = !yFlip; + } + + for (INT32 y = 0; y <= ySize; y++) { + for (INT32 x = 0; x <= xSize; x++) { + INT32 Code = Sprite + GfxOffset[y ^ (ySize * yFlip)][x ^ (xSize * xFlip)]; + INT32 xPos = sx + 16 * x; + INT32 yPos = sy + 16 * y; + + if (xPos > 16 && xPos < 272 && yPos > 16 && yPos < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, xPos, yPos, Colour, 2, 0, 256, DrvSprites); + } + } + } + } + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderTilemap(); + DrvRenderStars(); + DrvRenderSprites(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = nBurnSoundLen; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = (18432000 / 6) / 60; + nCyclesTotal[1] = (18432000 / 6) / 60; + nCyclesTotal[2] = (18432000 / 6) / 60; + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1) && DrvCPU1FireIRQ) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + if ((i == 0 || i == (nInterleave / 3) || i == (nInterleave / 3 * 2)) && IOChipCPU1FireIRQ) { + ZetNmi(); + } + ZetClose(); + + if (!DrvCPU2Halt) { + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1) && DrvCPU2FireIRQ) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + } + + if (!DrvCPU3Halt) { + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if ((i == (nInterleave / 2) || i == (nInterleave - 1)) && DrvCPU3FireIRQ) { + ZetNmi(); + } + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + static const INT32 Speeds[8] = { -1, -2, -3, 0, 3, 2, 1, 0 }; + + DrvStarScrollX += Speeds[DrvStarControl[0] + (DrvStarControl[1] * 2) + (DrvStarControl[2] * 4)]; + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + NamcoSoundScan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvCPU1FireIRQ); + SCAN_VAR(DrvCPU2FireIRQ); + SCAN_VAR(DrvCPU3FireIRQ); + SCAN_VAR(DrvCPU2Halt); + SCAN_VAR(DrvCPU3Halt); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(DrvStarScrollX); + SCAN_VAR(DrvStarScrollY); + SCAN_VAR(IOChipCustomCommand); + SCAN_VAR(IOChipCPU1FireIRQ); + SCAN_VAR(IOChipMode); + SCAN_VAR(IOChipCredits); + SCAN_VAR(IOChipCoinPerCredit); + SCAN_VAR(IOChipCreditPerCoin); + SCAN_VAR(PrevInValue); + for (INT32 i = 0; i < 6; i++) { + SCAN_VAR(DrvStarControl[i]); + } + for (INT32 i = 0; i < 16; i++) { + SCAN_VAR(IOChipCustom[i]); + } + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + } + + return 0; +} + +struct BurnDriver BurnDrvGalaga = { + "galaga", NULL, NULL, "galaga", "1981", + "Galaga (Namco rev. B)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, DrvRomInfo, DrvRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGalagao = { + "galagao", "galaga", NULL, "galaga", "1981", + "Galaga (Namco)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GalagaoRomInfo, GalagaoRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGalagamw = { + "galagamw", "galaga", NULL, "galaga", "1981", + "Galaga (Midway set 1)\0", NULL, "Namco (Midway License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GalagamwRomInfo, GalagamwRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, GalagamwDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGalagamk = { + "galagamk", "galaga", NULL, "galaga", "1981", + "Galaga (Midway set 2)\0", NULL, "Namco (Midway License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GalagamkRomInfo, GalagamkRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGalagamf = { + "galagamf", "galaga", NULL, "galaga", "1981", + "Galaga (Midway set 1 with fast shoot hack)\0", NULL, "Namco (Midway License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GalagamfRomInfo, GalagamfRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGallag = { + "gallag", "galaga", NULL, "galaga", "1981", + "Gallag\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GallagRomInfo, GallagRomName, GalagaSampleInfo, GalagaSampleName, DrvInputInfo, DrvDIPInfo, + GallagInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 576, 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_gauntlet.cpp b/src/burn/drivers/misc_pre90s/d_gauntlet.cpp new file mode 100644 index 00000000..947d20e9 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_gauntlet.cpp @@ -0,0 +1,2795 @@ +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "burn_ym2151.h" + +UINT8 *Drv68KRom = NULL; +static UINT8 *DrvEEPROM = NULL; + +struct slapstic_params +{ + INT32 reset; + INT32 bank0, bank1, bank2, bank3; + INT32 disable; + INT32 ignore; + INT32 senable; + INT32 sbank0, sbank1, sbank2, sbank3; +}; + + + +/************************************* + * + * Constants + * + *************************************/ + +#define DISABLE_MASK 0x3ff0 +#define IGNORE_MASK 0x007f +#define UNKNOWN 0xffff + +enum state_type { ENABLED, DISABLED, IGNORE, SPECIAL }; + +#define LOG_SLAPSTIC 0 + + + +/************************************* + * + * The master table + * + *************************************/ + +static struct slapstic_params slapstic_table[18] = +{ + /* 137412-101 ESB/Tetris */ + { 0x0000, 0x0080, 0x0090, 0x00a0, 0x00b0, 0x1540,UNKNOWN, 0x1dfe, 0x1b5c, 0x1b5d, 0x1b5e, 0x1b5f }, + /* 137412-102 ???? */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-103 Marble Madness */ + { 0x0000, 0x0040, 0x0050, 0x0060, 0x0070, 0x34c0, 0x002d, 0x3d14, 0x3d24, 0x3d25, 0x3d26, 0x3d27 }, + /* 137412-104 Gauntlet */ +/* { 0x0000, 0x0020, 0x0028, 0x0030, 0x0038, 0x3d90, 0x0069, 0x3735, 0x3764, 0x3765, 0x3766, 0x3767 },*/ +/* EC990621 Gauntlet fix */ + { 0x0000, 0x0020, 0x0028, 0x0030, 0x0038, 0x3da0, 0x0069, 0x3735, 0x3764, 0x3765, 0x3766, 0x3767 }, +/* EC990621 end of Gauntlet fix */ + /* 137412-105 Indiana Jones/Paperboy */ + { 0x0000, 0x0010, 0x0014, 0x0018, 0x001c, 0x35b0, 0x003d, 0x0092, 0x00a4, 0x00a5, 0x00a6, 0x00a7 }, + /* 137412-106 Gauntlet II */ +/* { 0x0000, 0x0008, 0x000a, 0x000c, 0x000e, 0x3da0, 0x002b, 0x0052, 0x0064, 0x0065, 0x0066, 0x0067 },*/ +/* NS990620 Gauntlet II fix */ + { 0x0000, 0x0008, 0x000a, 0x000c, 0x000e, 0x3db0, 0x002b, 0x0052, 0x0064, 0x0065, 0x0066, 0x0067 }, +/* NS990620 end of Gauntlet II fix */ + /* 137412-107 Peter Packrat/Xybots/2-player Gauntlet/720 Degrees */ +/* { 0x0000, 0x0018, 0x001a, 0x001c, 0x001e, 0x00a0, 0x006b, 0x3d52, 0x3d64, 0x3d65, 0x3d66, 0x3d67 },*/ +/* NS990622 Xybots fix */ + { 0x0000, 0x0018, 0x001a, 0x001c, 0x001e, 0x00b0, 0x006b, 0x3d52, 0x3d64, 0x3d65, 0x3d66, 0x3d67 }, +/* NS990622 end of Xybots fix */ + /* 137412-108 Road Runner/Super Sprint */ + { 0x0000, 0x0028, 0x002a, 0x002c, 0x002e, 0x0060, 0x001f,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-109 Championship Sprint */ + { 0x0000, 0x0008, 0x000a, 0x000c, 0x000e, 0x3da0, 0x002b, 0x0052, 0x0064, 0x0065, 0x0066, 0x0067 }, + /* 137412-110 Road Blasters/APB */ + { 0x0000, 0x0040, 0x0050, 0x0060, 0x0070, 0x34c0, 0x002d, 0x3d14, 0x3d24, 0x3d25, 0x3d26, 0x3d27 }, + /* 137412-111 Pit Fighter */ + { 0x0000, 0x0042, 0x0052, 0x0062, 0x0072,UNKNOWN, 0x000a,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-112 ???? */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-113 ???? */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-114 ???? */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-115 ???? */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-116 Hydra/Cyberball 2072 Tournament */ + { 0x0000, 0x0044, 0x004c, 0x0054, 0x005c,UNKNOWN, 0x0069,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-117 Race Drivin' */ + { 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN }, + /* 137412-118 Vindicators II/Rampart */ +/* { 0x0000, 0x0014, 0x0034, 0x0054, 0x0074,UNKNOWN, 0x0002, 0x1950, 0x1958, 0x1960, 0x1968, 0x1970 },*/ +/* EC990622 Rampart fix */ + { 0x0000, 0x0014, 0x0034, 0x0054, 0x0074, 0x30e0, 0x0002, 0x1958, 0x1959, 0x195a, 0x195b, 0x195c }, +/* EC990622 end of Rampart fix */ +}; + + + +/************************************* + * + * Statics + * + *************************************/ + +static struct slapstic_params *slapstic; + +static enum state_type state; +static INT8 next_bank; +static INT8 extra_bank; +static INT8 current_bank; +static UINT8 version; + +#if LOG_SLAPSTIC + static void slapstic_log(INT32 offset); + static FILE *slapsticlog; +#else + #define slapstic_log(o) +#endif + + + +/************************************* + * + * Initialization + * + *************************************/ + +void slapstic_init(INT32 chip) +{ + /* only a small number of chips are known to exist */ + if (chip < 101 || chip > 118) + return; + + /* set up a pointer to the parameters */ + version = chip; + slapstic = slapstic_table + (chip - 101); + + /* reset the chip */ + state = ENABLED; + next_bank = extra_bank = -1; + + /* the 111 and later chips seem to reset to bank 0 */ + if (chip < 111) + current_bank = 3; + else + current_bank = 0; +} + + +void slapstic_reset(void) +{ + slapstic_init(version); +} + + + +/************************************* + * + * Returns active bank without tweaking + * + *************************************/ + +INT32 slapstic_bank(void) +{ + return current_bank; +} + + + +/************************************* + * + * Call this before every access + * + *************************************/ + +INT32 slapstic_tweak(INT32 offset) +{ + /* switch banks now if one is pending */ + if (next_bank != -1) + { + current_bank = next_bank; + next_bank = -1; + extra_bank = -1; + } + + /* state machine */ + switch (state) + { + /* ENABLED state: the chip has been activated and is ready for a bankswitch */ + case ENABLED: + if ((offset & DISABLE_MASK) == slapstic->disable) + { + state = DISABLED; + /* NS990620 Gauntlet II fix */ + if (extra_bank != -1) + next_bank = extra_bank; + /* NS990620 end of Gauntlet II fix */ + } + else if ((offset & IGNORE_MASK) == slapstic->ignore) + { + state = IGNORE; + } + else if (offset == slapstic->bank0) + { + state = DISABLED; + if (extra_bank == -1) + next_bank = 0; + else + next_bank = extra_bank; + } + else if (offset == slapstic->bank1) + { + state = DISABLED; + if (extra_bank == -1) + next_bank = 1; + else + next_bank = extra_bank; + } + else if (offset == slapstic->bank2) + { + state = DISABLED; + if (extra_bank == -1) + next_bank = 2; + else + next_bank = extra_bank; + } + else if (offset == slapstic->bank3) + { + state = DISABLED; + if (extra_bank == -1) + next_bank = 3; + else + next_bank = extra_bank; + } + else if (offset == slapstic->reset) + { + next_bank = -1; + extra_bank = -1; + } + /* This is the transition which has */ + /* not been verified on the HW yet */ + else if (offset == slapstic->senable) + { + state = SPECIAL; + } + break; + + /* DISABLED state: everything is ignored except a reset */ + case DISABLED: + if (offset == slapstic->reset) + { + state = ENABLED; + next_bank = -1; + extra_bank = -1; + } + break; + + /* IGNORE state: next access is interpreted differently */ + case IGNORE: + if (offset == slapstic->senable) + { + state = SPECIAL; + } + else + { + state = ENABLED; + } + break; + + /* SPECIAL state: the special alternate bank switch override method is being used */ + case SPECIAL: + if (offset == slapstic->sbank0) + { + state = ENABLED; + extra_bank = 0; + } + else if (offset == slapstic->sbank1) + { + state = ENABLED; + extra_bank = 1; + } + else if (offset == slapstic->sbank2) + { + state = ENABLED; + extra_bank = 2; + } + else if (offset == slapstic->sbank3) + { + state = ENABLED; + extra_bank = 3; + } + else if (offset == slapstic->reset) + { + state = ENABLED; + next_bank = -1; + extra_bank = -1; + } + else + { + state = ENABLED; + } + break; + } + + /* log this access */ + slapstic_log(offset); + + /* return the active bank */ + return current_bank; +} + + +static UINT8 atarigen_slapstic_num; +static UINT8 *atarigen_slapstic; + +UINT8 __fastcall atarigen_slapstic_r(UINT32 a) +{ + INT32 offset = (a - 0x38000);// >> 1; + INT32 bank = slapstic_tweak(offset / 2) * 0x2000; + //return READ_WORD(&atarigen_slapstic[bank + (offset & 0x1fff)]); + //return atarigen_slapstic[bank + (offset & 0x1fff)]; + +// if (a & 1) { +// return atarigen_slapstic[bank + ((offset + 0) & 0x1fff)]; +// } else { +// return atarigen_slapstic[bank + ((offset + 1) & 0x1fff)]; +// } + + return atarigen_slapstic[(bank + (offset & 0x1fff)) ^ 1]; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Slapstic Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall atarigen_slapstic_w(UINT32 a, UINT8 d) +{ + //slapstic_tweak(offset / 2); + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Slapstic Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall atarigen_slapstic_r_word(UINT32 a) +{ +// UINT16 *Slapstic = (UINT16*)atarigen_slapstic; +// INT32 Offset = (a - 0x38000);// >> 1; +// INT32 Bank = slapstic_tweak(Offset / 2) * 0x2000; +// return Slapstic[Bank + ((Offset >> 1) & 0x1fff)]; + + SEK_DEF_READ_WORD(1, a); + return 0; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Slapstic Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall atarigen_slapstic_w_word(UINT32 a, UINT16 d) +{ + INT32 offset = (a - 0x38000);// >> 1; + slapstic_tweak(offset / 2); + return; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Slapstic Write word => %06X, %04X\n"), a, d); + } + } +} + +void atarigen_slapstic_reset(void) +{ + if (atarigen_slapstic_num) + slapstic_reset(); +} + +void atarigen_slapstic_init(INT32 base, INT32 chipnum) +{ + atarigen_slapstic_num = chipnum; + atarigen_slapstic = NULL; + if (chipnum) + { + slapstic_init(chipnum); + //atarigen_slapstic = install_mem_read_handler(cpunum, base, base + 0x7fff, atarigen_slapstic_r); + //atarigen_slapstic = install_mem_write_handler(cpunum, base, base + 0x7fff, atarigen_slapstic_w); + SekOpen(0); + SekMapHandler(1, base, base + 0x7fff, SM_RAM); + SekSetReadByteHandler(1, atarigen_slapstic_r); + SekSetReadWordHandler(1, atarigen_slapstic_r_word); + SekSetWriteByteHandler(1, atarigen_slapstic_w); + SekSetWriteWordHandler(1, atarigen_slapstic_w_word); + SekClose(); + + atarigen_slapstic = (UINT8*)BurnMalloc(0x8000); + memcpy(atarigen_slapstic, Drv68KRom + 0x38000, 0x8000); + } +} + + + +static UINT8 eeprom_unlocked; + +void atarigen_eeprom_reset(void) +{ + eeprom_unlocked = 0; +} + +void atarigen_eeprom_init() +{ + memset(DrvEEPROM, 0xff, 0x1000); +} + +void atarigen_slapstic_exit() +{ + BurnFree(atarigen_slapstic); +} + + + + + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort5[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +//static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvM6502Rom = NULL; +static UINT8 *DrvM6502Ram = NULL; +//static UINT8 *DrvEEPROM = NULL; +static UINT8 *DrvPlayfieldRam = NULL; +static UINT8 *DrvMOSpriteRam = NULL; +static UINT8 *DrvAlphaRam = NULL; +static UINT8 *DrvMOSlipRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvMotionObjectTiles = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvVBlank; +static UINT16 DrvSoundResetVal; +static UINT8 DrvSoundCPUHalt; +static UINT8 DrvCPUtoSoundReady; +static UINT8 DrvSoundtoCPUReady; +static UINT8 DrvCPUtoSound; +static UINT8 DrvSoundtoCPU; +static INT16 DrvScrollX; +static INT16 DrvScrollY; +static UINT8 DrvTileBank; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +#define GAME_GAUNTLET 0 +#define GAME_GAUNTLET2 1 + +static UINT8 DrvGameType; + + + + +struct atarigen_modesc +{ + INT32 maxmo; /* maximum number of MO's */ + INT32 moskip; /* number of bytes per MO entry */ + INT32 mowordskip; /* number of bytes between MO words */ + INT32 ignoreword; /* ignore an entry if this word == 0xffff */ + INT32 linkword, linkshift, linkmask; /* link = (data[linkword >> linkshift) & linkmask */ + INT32 reverse; /* render in reverse link order */ +}; + +static struct atarigen_modesc *modesc; + +static UINT16 *displaylist; +static UINT16 *displaylist_end; +static UINT16 *displaylist_last; + +static INT32 atarigen_init_display_list (struct atarigen_modesc *_modesc) +{ + modesc = _modesc; + + displaylist = (UINT16*)BurnMalloc (modesc->maxmo * 10 * (/*Machine->drv->screen_height*/ 240 / 8) * sizeof(UINT16)); + if (!displaylist) + return 1; + + displaylist_end = displaylist; + displaylist_last = NULL; + + return 0; +} + +static void atarigen_update_display_list (UINT8 *base, INT32 start, INT32 scanline) +{ + INT32 link = start, match = 0, moskip = modesc->moskip, wordskip = modesc->mowordskip; + INT32 ignoreword = modesc->ignoreword; + UINT16 *d, *startd, *lastd; + UINT8 spritevisit[1024]; + + /* scanline 0 means first update */ + if (scanline <= 0) + { + displaylist_end = displaylist; + displaylist_last = NULL; + } + + /* set up local pointers */ + startd = d = displaylist_end; + lastd = displaylist_last; + + /* if the last list entries were on the same scanline, overwrite them */ + if (lastd) + { + if (*lastd == scanline) + d = startd = lastd; + else + match = 1; + } + + /* visit all the sprites and copy their data into the display list */ + memset (spritevisit, 0, sizeof (spritevisit)); + while (!spritevisit[link]) + { + UINT8 *modata = &base[link * moskip]; + UINT16 data[4]; + + /* bounds checking */ + if (d - displaylist >= modesc->maxmo * 5 * (/*Machine->drv->screen_height*/ 240 / 8)) + { +// if (errorlog) fprintf (errorlog, "Motion object list exceeded maximum\n"); + break; + } + + /* start with the scanline */ + *d++ = scanline; + + /* add the data words */ + data[0] = *d++ = modata[0] | (modata[1] << 8);//READ_WORD (&modata[0]); + data[1] = *d++ = modata[wordskip + 0] | (modata[wordskip + 1] << 8);//READ_WORD (&modata[wordskip]); + data[2] = *d++ = modata[(2 * wordskip) + 0] | (modata[(2 * wordskip) + 1] << 8);//READ_WORD (&modata[2 * wordskip]); + data[3] = *d++ = modata[(3 * wordskip) + 0] | (modata[(3 * wordskip) + 1] << 8);//READ_WORD (&modata[3 * wordskip]); + + /* is this one to ignore? */ + if (data[ignoreword] == 0xffff) + d -= 5; + + /* update our match status */ + else if (match) + { + lastd++; + if (*lastd++ != data[0] || *lastd++ != data[1] || *lastd++ != data[2] || *lastd++ != data[3]) + match = 0; + } + + /* link to the next object */ + spritevisit[link] = 1; + if (modesc->linkword >= 0) + link = (data[modesc->linkword] >> modesc->linkshift) & modesc->linkmask; + else + link = (link + 1) & modesc->linkmask; + } + + /* if we didn't match the last set of entries, update the counters */ + if (!match) + { + displaylist_end = d; + displaylist_last = startd; + } +} + +#define XCHARS 42 +#define YCHARS 30 + +#define XDIM (XCHARS*8) +#define YDIM (YCHARS*8) + +static void atarigen_render_display_list (/*struct osd_bitmap *bitmap, atarigen_morender morender, void *param*/) +{ + UINT16 *base = displaylist; + INT32 last_start_scan = -1; +// struct rectangle clip; + + INT32 xscroll = DrvScrollX; + UINT16 *AlphaRam = (UINT16*)DrvAlphaRam; + INT32 yscroll = AlphaRam[0xf6e >> 1] >> 7; + yscroll &= 0x1ff; + + /* create a clipping rectangle so that only partial sections are updated at a time */ +// clip.min_x = 0; +// clip.max_x = Machine->drv->screen_width - 1; + +// INT32 xMin = 0; +// INT32 xMax = nScreenWidth - 1; + INT32 yMin = 0; + INT32 yMax = nScreenHeight - 1; + + /* loop over the list until the end */ + while (base < displaylist_end) + { + UINT16 *d, *first, *last; + INT32 start_scan = base[0], step; + + last_start_scan = start_scan; +// clip.min_y = start_scan; + yMin = start_scan; + + /* look for an entry whose scanline start is different from ours; that's our bottom */ + for (d = base; d < displaylist_end; d += 5) + if (*d != start_scan) + { +// clip.max_y = *d; + yMax = *d; + break; + } + + /* if we didn't find any additional regions, go until the bottom of the screen */ +// if (d == displaylist_end) +// clip.max_y = Machine->drv->screen_height - 1; + + if (d == displaylist_end) + yMax = nScreenHeight - 1; + + /* set the start and end points */ + if (modesc->reverse) + { + first = d - 5; + last = base - 5; + step = -5; + } + else + { + first = base; + last = d; + step = 5; + } + + /* update the base */ + base = d; + + /* render the mos */ + for (d = first; d != last; d += step) { + //(*morender)(bitmap, &clip, &d[1], param); + + UINT16 *data = &d[1]; + + INT32 sx, sy, x, y, xadv; + + /* extract data from the various words */ + INT32 pict = data[0] & 0x7fff; + INT32 color = (data[1] & 0x0f) | 0x10; + INT32 xpos = -xscroll + (data[1] >> 7); + INT32 vsize = (data[2] & 7) + 1; + INT32 hsize = ((data[2] >> 3) & 7) + 1; + INT32 hflip = data[2] & 0x40; + INT32 ypos = -yscroll - (data[2] >> 7) - vsize * 8; + + /* adjust for h flip */ + if (hflip) + xpos += (hsize - 1) * 8, xadv = -8; + else + xadv = 8; + + /* adjust the final coordinates */ + xpos &= 0x1ff; + ypos &= 0x1ff; + if (xpos >= XDIM) xpos -= 0x200; + if (ypos >= YDIM) ypos -= 0x200; + + /* loop over the height */ + for (y = 0, sy = ypos; y < vsize; y++, sy += 8) + { + /* clip the Y coordinate */ + if (sy <= /*clip->min_y*/ yMin - 8) + { + pict += hsize; + continue; + } + else if (sy > /*clip->max_y*/ yMax) + break; + + /* loop over the width */ + for (x = 0, sx = xpos; x < hsize; x++, sx += xadv, pict++) + { + /* clip the X coordinate */ + if (sx <= -8 || sx >= XDIM) + continue; + + /* draw the sprite */ + //drawgfx (bitmap, Machine->gfx[1], + // pict ^ 0x800, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PEN, 0); + Render8x8Tile_Mask_Clip(pTransDraw, pict ^ 0x800, sx, sy, color, 4, 0, 0, DrvMotionObjectTiles); + } + } + } + } +} + +void atarigen_exit() +{ + BurnFree(displaylist); +} + + + + + + + + + + + + + +static struct BurnInputInfo GauntletInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort5 + 3, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort5 + 2, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , DrvInputPort5 + 1, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , DrvInputPort5 + 0, "p4 coin" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , DrvInputPort2 + 7, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , DrvInputPort2 + 6, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , DrvInputPort2 + 5, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , DrvInputPort2 + 4, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 1, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 0, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , DrvInputPort3 + 7, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , DrvInputPort3 + 6, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , DrvInputPort3 + 5, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , DrvInputPort3 + 4, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , DrvInputPort3 + 1, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , DrvInputPort3 + 0, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort4 + 3, "diag" }, +}; + +STDINPUTINFO(Gauntlet) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x30) == 0x30) { + *nJoystickInputs &= ~0x30; + } + if ((*nJoystickInputs & 0xc0) == 0xc0) { + *nJoystickInputs &= ~0xc0; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = DrvInput[3] = DrvInput[5] = 0x00; + DrvInput[4] = 0x08; // 0x48 when VBLANK, 0x00 and 0x40 for test mode + if (DrvInputPort4[3]) DrvInput[4] -= 0x08; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + DrvInput[3] |= (DrvInputPort3[i] & 1) << i; + DrvInput[5] |= (DrvInputPort5[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); + DrvClearOpposites(&DrvInput[3]); +} + +static struct BurnRomInfo GauntletRomDesc[] = { + { "136037-1307.9a", 0x08000, 0x46fe8743, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1308.9b", 0x08000, 0x276e15c4, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136037-1409.7a", 0x08000, 0x6fb8419c, BRF_ESS | BRF_PRG }, // 4 + { "136037-1410.7b", 0x08000, 0x931bd2a0, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet) +STD_ROM_FN(Gauntlet) + +static struct BurnRomInfo GauntletsRomDesc[] = { + { "136037-1507.9a", 0x08000, 0xb5183228, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1508.9b", 0x08000, 0xafd3c501, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136037-1509.7a", 0x08000, 0x69e50ae9, BRF_ESS | BRF_PRG }, // 4 + { "136037-1510.7b", 0x08000, 0x54e2692c, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlets) +STD_ROM_FN(Gauntlets) + +static struct BurnRomInfo GauntletjRomDesc[] = { + { "136037-1307.9a", 0x08000, 0x46fe8743, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1308.9b", 0x08000, 0x276e15c4, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136037-1309.7a", 0x08000, 0xe8ba39d8, BRF_ESS | BRF_PRG }, // 4 + { "136037-1310.7b", 0x08000, 0xa204d997, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletj) +STD_ROM_FN(Gauntletj) + +static struct BurnRomInfo GauntletgRomDesc[] = { + { "136037-1007.9a", 0x08000, 0x6a224cea, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1008.9b", 0x08000, 0xfa391dab, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136037-1009.7a", 0x08000, 0x75d1f966, BRF_ESS | BRF_PRG }, // 4 + { "136037-1010.7b", 0x08000, 0x28a4197b, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletg) +STD_ROM_FN(Gauntletg) + +static struct BurnRomInfo Gauntletj12RomDesc[] = { + { "136037-1207.9a", 0x08000, 0x6dc0610d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1208.9b", 0x08000, 0xfaa306eb, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136037-1109.7a", 0x08000, 0x500194fb, BRF_ESS | BRF_PRG }, // 4 + { "136037-1110.7b", 0x08000, 0xb2969076, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletj12) +STD_ROM_FN(Gauntletj12) + +static struct BurnRomInfo Gauntletr9RomDesc[] = { + { "136037-907.9a", 0x08000, 0xc13a6399, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-908.9b", 0x08000, 0x417607d9, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-909.7a", 0x08000, 0xfb1cdc1c, BRF_ESS | BRF_PRG }, // 4 + { "136037-910.7b", 0x08000, 0xf188e7b3, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr9) +STD_ROM_FN(Gauntletr9) + +static struct BurnRomInfo Gauntletgr8RomDesc[] = { + { "136037-807.9a", 0x08000, 0x671c0bc2, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-808.9b", 0x08000, 0xf2842af4, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-809.7a", 0x08000, 0x05642d60, BRF_ESS | BRF_PRG }, // 4 + { "136037-810.7b", 0x08000, 0x36d295e3, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletgr8) +STD_ROM_FN(Gauntletgr8) + +static struct BurnRomInfo Gauntletr7RomDesc[] = { + { "136037-207.9a", 0x08000, 0xfd871f81, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-208.9b", 0x08000, 0xbcb2fb1d, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-709.7a", 0x08000, 0x73e1ad79, BRF_ESS | BRF_PRG }, // 4 + { "136037-710.7b", 0x08000, 0xfd248cea, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr7) +STD_ROM_FN(Gauntletr7) + +static struct BurnRomInfo Gauntletgr6RomDesc[] = { + { "136037-307.9a", 0x08000, 0x759827c9, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-308.9b", 0x08000, 0xd71262d1, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-609.7a", 0x08000, 0xcd3381de, BRF_ESS | BRF_PRG }, // 4 + { "136037-610.7b", 0x08000, 0x2cff932a, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletgr6) +STD_ROM_FN(Gauntletgr6) + +static struct BurnRomInfo Gauntletr5RomDesc[] = { + { "136037-207.9a", 0x08000, 0xfd871f81, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-208.9b", 0x08000, 0xbcb2fb1d, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-409.7a", 0x08000, 0xc57377b3, BRF_ESS | BRF_PRG }, // 4 + { "136037-510.7b", 0x08000, 0x1cac2071, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr5) +STD_ROM_FN(Gauntletr5) + +static struct BurnRomInfo Gauntletr4RomDesc[] = { + { "136037-207.9a", 0x08000, 0xfd871f81, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-208.9b", 0x08000, 0xbcb2fb1d, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-409.7a", 0x08000, 0xc57377b3, BRF_ESS | BRF_PRG }, // 4 + { "136037-410.7b", 0x08000, 0x6b971a27, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr4) +STD_ROM_FN(Gauntletr4) + +static struct BurnRomInfo Gauntletgr3RomDesc[] = { + { "136037-307.9a", 0x08000, 0x759827c9, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-308.9b", 0x08000, 0xd71262d1, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-309.7a", 0x08000, 0x7f03696b, BRF_ESS | BRF_PRG }, // 4 + { "136037-310.7b", 0x08000, 0x8d7197fc, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletgr3) +STD_ROM_FN(Gauntletgr3) + +static struct BurnRomInfo Gauntletr2RomDesc[] = { + { "136037-207.9a", 0x08000, 0xfd871f81, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-208.9b", 0x08000, 0xbcb2fb1d, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-209.7a", 0x08000, 0xd810a7dc, BRF_ESS | BRF_PRG }, // 4 + { "136037-210.7b", 0x08000, 0xfbba7290, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr2) +STD_ROM_FN(Gauntletr2) + +static struct BurnRomInfo Gauntletr1RomDesc[] = { + { "136037-107.9a", 0x08000, 0xa5885e14, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-108.9b", 0x08000, 0x0087f1ab, BRF_ESS | BRF_PRG }, // 1 + { "136037-105.10a", 0x04000, 0x4642cd95, BRF_ESS | BRF_PRG }, // 2 + { "136037-106.10b", 0x04000, 0xc8df945e, BRF_ESS | BRF_PRG }, // 3 + { "136037-109.7a", 0x08000, 0x55d87198, BRF_ESS | BRF_PRG }, // 4 + { "136037-110.7b", 0x08000, 0xf84ad06d, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntletr1) +STD_ROM_FN(Gauntletr1) + +static struct BurnRomInfo Gauntlet2pRomDesc[] = { + { "136041-507.9a", 0x08000, 0x8784133f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-508.9b", 0x08000, 0x2843bde3, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-609.7a", 0x08000, 0x5b4ee415, BRF_ESS | BRF_PRG }, // 4 + { "136041-610.7b", 0x08000, 0x41f5c9e2, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2p) +STD_ROM_FN(Gauntlet2p) + +static struct BurnRomInfo Gauntlet2pjRomDesc[] = { + { "136041-507.9a", 0x08000, 0x8784133f, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-508.9b", 0x08000, 0x2843bde3, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-509.7a", 0x08000, 0xfb2ef226, BRF_ESS | BRF_PRG }, // 4 + { "136041-510.7b", 0x08000, 0xa69be8da, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2pj) +STD_ROM_FN(Gauntlet2pj) + +static struct BurnRomInfo Gauntlet2pgRomDesc[] = { + { "136041-407.9a", 0x08000, 0xcde72140, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-408.9b", 0x08000, 0x4ab1af62, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-409.7a", 0x08000, 0x44e01459, BRF_ESS | BRF_PRG }, // 4 + { "136041-410.7b", 0x08000, 0xb58d96d3, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2pg) +STD_ROM_FN(Gauntlet2pg) + +static struct BurnRomInfo Gauntlet2pr3RomDesc[] = { + { "136041-207.9a", 0x08000, 0x0e1af1b4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-208.9b", 0x08000, 0xbf51a238, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-309.7a", 0x08000, 0x5acbcd2b, BRF_ESS | BRF_PRG }, // 4 + { "136041-310.7b", 0x08000, 0x1889ab77, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2pr3) +STD_ROM_FN(Gauntlet2pr3) + +static struct BurnRomInfo Gauntlet2pj2RomDesc[] = { + { "136041-207.9a", 0x08000, 0x0e1af1b4, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-208.9b", 0x08000, 0xbf51a238, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-209.7a", 0x08000, 0xddc9b56f, BRF_ESS | BRF_PRG }, // 4 + { "136041-210.7b", 0x08000, 0xffe78a4f, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2pj2) +STD_ROM_FN(Gauntlet2pj2) + +static struct BurnRomInfo Gauntlet2pg1RomDesc[] = { + { "136041-107.9a", 0x08000, 0x3faf74d8, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136041-108.9b", 0x08000, 0xf1e6d815, BRF_ESS | BRF_PRG }, // 1 + { "136037-205.10a", 0x04000, 0x6d99ed51, BRF_ESS | BRF_PRG }, // 2 + { "136037-206.10b", 0x04000, 0x545ead91, BRF_ESS | BRF_PRG }, // 3 + { "136041-109.7a", 0x08000, 0x56d0c5b8, BRF_ESS | BRF_PRG }, // 4 + { "136041-110.7b", 0x08000, 0x3b9ae397, BRF_ESS | BRF_PRG }, // 5 + + { "136037-120.16r", 0x04000, 0x6ee7f3cc, BRF_ESS | BRF_PRG }, // 6 M6502 Program + { "136037-119.16s", 0x08000, 0xfa19861f, BRF_ESS | BRF_PRG }, // 7 + + { "136037-104.6p", 0x02000, 0x9e2a5b59, BRF_GRA }, // 8 Characters + + { "136037-111.1a", 0x08000, 0x91700f33, BRF_GRA }, // 9 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 10 + { "136037-113.1l", 0x08000, 0xd497d0a8, BRF_GRA }, // 11 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 12 + { "136037-115.2a", 0x08000, 0x9510b898, BRF_GRA }, // 13 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 14 + { "136037-117.2l", 0x08000, 0x29a5db41, BRF_GRA }, // 15 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 16 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 18 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 19 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 20 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gauntlet2pg1) +STD_ROM_FN(Gauntlet2pg1) + +static struct BurnRomInfo Gaunt2RomDesc[] = { + { "136037-1307.9a", 0x08000, 0x46fe8743, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1308.9b", 0x08000, 0x276e15c4, BRF_ESS | BRF_PRG }, // 1 + { "136043-1105.10a", 0x04000, 0x45dfda47, BRF_ESS | BRF_PRG }, // 2 + { "136043-1106.10b", 0x04000, 0x343c029c, BRF_ESS | BRF_PRG }, // 3 + { "136043-1109.7a", 0x08000, 0x58a0a9a3, BRF_ESS | BRF_PRG }, // 4 + { "136043-1110.7b", 0x08000, 0x658f0da8, BRF_ESS | BRF_PRG }, // 5 + { "136043-1121.6a", 0x08000, 0xae301bba, BRF_ESS | BRF_PRG }, // 6 + { "136043-1122.6b", 0x08000, 0xe94aaa8a, BRF_ESS | BRF_PRG }, // 7 + + { "136043-1120.16r", 0x04000, 0x5c731006, BRF_ESS | BRF_PRG }, // 8 M6502 Program + { "136043-1119.16s", 0x08000, 0xdc3591e7, BRF_ESS | BRF_PRG }, // 9 + + { "136043-1104.6p", 0x02000, 0x1343cf6f, BRF_GRA }, // 10 Characters + + { "136043-1111.1a", 0x08000, 0x09df6e23, BRF_GRA }, // 11 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 12 + { "136043-1123.1c", 0x04000, 0xe4c98f01, BRF_GRA }, // 13 + { "136043-1113.1l", 0x08000, 0x33cb476e, BRF_GRA }, // 14 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 15 + { "136043-1124.1p", 0x04000, 0xc4857879, BRF_GRA }, // 16 + { "136043-1115.2a", 0x08000, 0xf71e2503, BRF_GRA }, // 17 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 18 + { "136043-1125.2c", 0x04000, 0xd9c2c2d1, BRF_GRA }, // 19 + { "136043-1117.2l", 0x08000, 0x9e30b2e9, BRF_GRA }, // 20 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 21 + { "136043-1126.2p", 0x04000, 0xa32c732a, BRF_GRA }, // 22 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 23 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 24 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 25 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gaunt2) +STD_ROM_FN(Gaunt2) + +static struct BurnRomInfo Gaunt2gRomDesc[] = { + { "136037-1007.9a", 0x08000, 0x6a224cea, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1008.9b", 0x08000, 0xfa391dab, BRF_ESS | BRF_PRG }, // 1 + { "136043-1105.10a", 0x04000, 0x45dfda47, BRF_ESS | BRF_PRG }, // 2 + { "136043-1106.10b", 0x04000, 0x343c029c, BRF_ESS | BRF_PRG }, // 3 + { "136043-2209.7a", 0x08000, 0x577f4101, BRF_ESS | BRF_PRG }, // 4 + { "136043-2210.7b", 0x08000, 0x03254cf4, BRF_ESS | BRF_PRG }, // 5 + { "136043-2221.6a", 0x08000, 0xc8adcf1a, BRF_ESS | BRF_PRG }, // 6 + { "136043-2222.6b", 0x08000, 0x7788ff84, BRF_ESS | BRF_PRG }, // 7 + + { "136043-1120.16r", 0x04000, 0x5c731006, BRF_ESS | BRF_PRG }, // 8 M6502 Program + { "136043-1119.16s", 0x08000, 0xdc3591e7, BRF_ESS | BRF_PRG }, // 9 + + { "136043-1104.6p", 0x02000, 0x1343cf6f, BRF_GRA }, // 10 Characters + + { "136043-1111.1a", 0x08000, 0x09df6e23, BRF_GRA }, // 11 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 12 + { "136043-1123.1c", 0x04000, 0xe4c98f01, BRF_GRA }, // 13 + { "136043-1113.1l", 0x08000, 0x33cb476e, BRF_GRA }, // 14 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 15 + { "136043-1124.1p", 0x04000, 0xc4857879, BRF_GRA }, // 16 + { "136043-1115.2a", 0x08000, 0xf71e2503, BRF_GRA }, // 17 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 18 + { "136043-1125.2c", 0x04000, 0xd9c2c2d1, BRF_GRA }, // 19 + { "136043-1117.2l", 0x08000, 0x9e30b2e9, BRF_GRA }, // 20 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 21 + { "136043-1126.2p", 0x04000, 0xa32c732a, BRF_GRA }, // 22 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 23 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 24 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 25 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gaunt2g) +STD_ROM_FN(Gaunt2g) + +static struct BurnRomInfo Gaunt22pRomDesc[] = { + { "136037-1307.9a", 0x08000, 0x46fe8743, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1308.9b", 0x08000, 0x276e15c4, BRF_ESS | BRF_PRG }, // 1 + { "136043-1105.10a", 0x04000, 0x45dfda47, BRF_ESS | BRF_PRG }, // 2 + { "136043-1106.10b", 0x04000, 0x343c029c, BRF_ESS | BRF_PRG }, // 3 + { "136044-2109.7a", 0x08000, 0x1102ab96, BRF_ESS | BRF_PRG }, // 4 + { "136044-2110.7b", 0x08000, 0xd2203a2b, BRF_ESS | BRF_PRG }, // 5 + { "136044-2121.6a", 0x08000, 0x753982d7, BRF_ESS | BRF_PRG }, // 6 + { "136044-2122.6b", 0x08000, 0x879149ea, BRF_ESS | BRF_PRG }, // 7 + + { "136043-1120.16r", 0x04000, 0x5c731006, BRF_ESS | BRF_PRG }, // 8 M6502 Program + { "136043-1119.16s", 0x08000, 0xdc3591e7, BRF_ESS | BRF_PRG }, // 9 + + { "136043-1104.6p", 0x02000, 0x1343cf6f, BRF_GRA }, // 10 Characters + + { "136043-1111.1a", 0x08000, 0x09df6e23, BRF_GRA }, // 11 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 12 + { "136043-1123.1c", 0x04000, 0xe4c98f01, BRF_GRA }, // 13 + { "136043-1113.1l", 0x08000, 0x33cb476e, BRF_GRA }, // 14 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 15 + { "136043-1124.1p", 0x04000, 0xc4857879, BRF_GRA }, // 16 + { "136043-1115.2a", 0x08000, 0xf71e2503, BRF_GRA }, // 17 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 18 + { "136043-1125.2c", 0x04000, 0xd9c2c2d1, BRF_GRA }, // 19 + { "136043-1117.2l", 0x08000, 0x9e30b2e9, BRF_GRA }, // 20 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 21 + { "136043-1126.2p", 0x04000, 0xa32c732a, BRF_GRA }, // 22 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 23 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 24 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 25 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gaunt22p) +STD_ROM_FN(Gaunt22p) + +static struct BurnRomInfo Gaunt22p1RomDesc[] = { + { "136037-1307.9a", 0x08000, 0x46fe8743, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1308.9b", 0x08000, 0x276e15c4, BRF_ESS | BRF_PRG }, // 1 + { "136043-1105.10a", 0x04000, 0x45dfda47, BRF_ESS | BRF_PRG }, // 2 + { "136043-1106.10b", 0x04000, 0x343c029c, BRF_ESS | BRF_PRG }, // 3 + { "136044-1109.7a", 0x08000, 0x31f805eb, BRF_ESS | BRF_PRG }, // 4 + { "136044-1110.7b", 0x08000, 0x5285c0e2, BRF_ESS | BRF_PRG }, // 5 + { "136044-1121.6a", 0x08000, 0xd1f3b32a, BRF_ESS | BRF_PRG }, // 6 + { "136044-1122.6b", 0x08000, 0x3485785f, BRF_ESS | BRF_PRG }, // 7 + + { "136043-1120.16r", 0x04000, 0x5c731006, BRF_ESS | BRF_PRG }, // 8 M6502 Program + { "136043-1119.16s", 0x08000, 0xdc3591e7, BRF_ESS | BRF_PRG }, // 9 + + { "136043-1104.6p", 0x02000, 0x1343cf6f, BRF_GRA }, // 10 Characters + + { "136043-1111.1a", 0x08000, 0x09df6e23, BRF_GRA }, // 11 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 12 + { "136043-1123.1c", 0x04000, 0xe4c98f01, BRF_GRA }, // 13 + { "136043-1113.1l", 0x08000, 0x33cb476e, BRF_GRA }, // 14 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 15 + { "136043-1124.1p", 0x04000, 0xc4857879, BRF_GRA }, // 16 + { "136043-1115.2a", 0x08000, 0xf71e2503, BRF_GRA }, // 17 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 18 + { "136043-1125.2c", 0x04000, 0xd9c2c2d1, BRF_GRA }, // 19 + { "136043-1117.2l", 0x08000, 0x9e30b2e9, BRF_GRA }, // 20 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 21 + { "136043-1126.2p", 0x04000, 0xa32c732a, BRF_GRA }, // 22 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 23 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 24 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 25 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gaunt22p1) +STD_ROM_FN(Gaunt22p1) + +static struct BurnRomInfo Gaunt22pgRomDesc[] = { + { "136037-1007.9a", 0x08000, 0x6a224cea, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "136037-1008.9b", 0x08000, 0xfa391dab, BRF_ESS | BRF_PRG }, // 1 + { "136043-1105.10a", 0x04000, 0x45dfda47, BRF_ESS | BRF_PRG }, // 2 + { "136043-1106.10b", 0x04000, 0x343c029c, BRF_ESS | BRF_PRG }, // 3 + { "136044-2209.7a", 0x08000, 0x9da52ecd, BRF_ESS | BRF_PRG }, // 4 + { "136044-2210.7b", 0x08000, 0x63d0f6a7, BRF_ESS | BRF_PRG }, // 5 + { "136044-2221.6a", 0x08000, 0x8895b31b, BRF_ESS | BRF_PRG }, // 6 + { "136044-2222.6b", 0x08000, 0xa4456cc7, BRF_ESS | BRF_PRG }, // 7 + + { "136043-1120.16r", 0x04000, 0x5c731006, BRF_ESS | BRF_PRG }, // 8 M6502 Program + { "136043-1119.16s", 0x08000, 0xdc3591e7, BRF_ESS | BRF_PRG }, // 9 + + { "136043-1104.6p", 0x02000, 0x1343cf6f, BRF_GRA }, // 10 Characters + + { "136043-1111.1a", 0x08000, 0x09df6e23, BRF_GRA }, // 11 Motion Objects + { "136037-112.1b", 0x08000, 0x869330be, BRF_GRA }, // 12 + { "136043-1123.1c", 0x04000, 0xe4c98f01, BRF_GRA }, // 13 + { "136043-1113.1l", 0x08000, 0x33cb476e, BRF_GRA }, // 14 + { "136037-114.1mn", 0x08000, 0x29ef9882, BRF_GRA }, // 15 + { "136043-1124.1p", 0x04000, 0xc4857879, BRF_GRA }, // 16 + { "136043-1115.2a", 0x08000, 0xf71e2503, BRF_GRA }, // 17 + { "136037-116.2b", 0x08000, 0x11e0ac5b, BRF_GRA }, // 18 + { "136043-1125.2c", 0x04000, 0xd9c2c2d1, BRF_GRA }, // 19 + { "136043-1117.2l", 0x08000, 0x9e30b2e9, BRF_GRA }, // 20 + { "136037-118.2mn", 0x08000, 0x8bf3b263, BRF_GRA }, // 21 + { "136043-1126.2p", 0x04000, 0xa32c732a, BRF_GRA }, // 22 + + { "74s472-136037-101.7u", 0x00200, 0x2964f76f, BRF_GRA }, // 23 PROM (Motion Timing) + { "74s472-136037-102.5l", 0x00200, 0x4d4fec6c, BRF_GRA }, // 24 PROM (Motion Flip Control) + { "74s287-136037-103.4r", 0x00100, 0x6c5ccf08, BRF_GRA }, // 25 PROM (Motion Position/Size) +}; + +STD_ROM_PICK(Gaunt22pg) +STD_ROM_FN(Gaunt22pg) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x80000; + DrvM6502Rom = Next; Next += 0x10000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x03000; + DrvM6502Ram = Next; Next += 0x01000; + DrvEEPROM = Next; Next += 0x01000; + DrvPlayfieldRam = Next; Next += 0x02000; + DrvMOSpriteRam = Next; Next += 0x02000; + DrvAlphaRam = Next; Next += 0x00f80; + DrvMOSlipRam = Next; Next += 0x00080; + DrvPaletteRam = Next; Next += 0x00800; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0400 * 8 * 8; + DrvMotionObjectTiles = Next; Next += /*0x2000*/0x3000 * 8 * 8; + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM2151Reset(); + + atarigen_slapstic_reset(); + atarigen_eeprom_reset(); + + DrvVBlank = 1; + DrvSoundResetVal = 0; + DrvSoundCPUHalt = 0; + DrvCPUtoSoundReady = 0; + DrvSoundtoCPUReady = 0; + DrvCPUtoSound = 0; + DrvSoundtoCPU = 0; + + return 0; +} + +UINT8 __fastcall Gauntlet68KReadByte(UINT32 a) +{ + if (a >= 0x802000 && a <= 0x802fff) { + UINT16 *Eeprom = (UINT16*)DrvEEPROM; + INT32 Offset = (a - 0x802000) >> 1; + return Eeprom[Offset] | 0xff00; + } + + switch (a) { + case 0x803009: { + UINT8 Res = DrvInput[4] | (DrvVBlank ? 0x40 : 0x00); + if (DrvCPUtoSoundReady) Res ^= 0x20; + if (DrvSoundtoCPUReady) Res ^= 0x10; + return Res; + } + + case 0x80300f: { + DrvSoundtoCPUReady = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + return DrvSoundtoCPU; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Gauntlet68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x802000 && a <= 0x802fff) { + if (!eeprom_unlocked) return; + + UINT16 *Eeprom = (UINT16*)DrvEEPROM; + INT32 Offset = (a - 0x802000) >> 1; + eeprom_unlocked = 0; + Eeprom[Offset] = d; + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Gauntlet68KReadWord(UINT32 a) +{ + switch (a) { + case 0x803000: { + return 0xffff - DrvInput[0]; + } + + case 0x803002: { + return 0xffff - DrvInput[1]; + } + + case 0x803004: { + return 0xffff - DrvInput[2]; + } + + case 0x803006: { + return 0xffff - DrvInput[3]; + } + + case 0x803008: { + UINT8 Res = DrvInput[4] | (DrvVBlank ? 0x40 : 0x00); + if (DrvCPUtoSoundReady) Res ^= 0x20; + if (DrvSoundtoCPUReady) Res ^= 0x10; + return 0xff00 | Res; + } + + case 0x80300e: { + DrvSoundtoCPUReady = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + return 0xff00 | DrvSoundtoCPU; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Gauntlet68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x803100: { + // watchdog_reset16_w + return; + } + + case 0x803120: + case 0x80312e: { + INT32 OldVal = DrvSoundResetVal; + DrvSoundResetVal = d; + if ((OldVal ^ DrvSoundResetVal) & 1) { + if (DrvSoundResetVal & 1) { + DrvSoundCPUHalt = 0; + bprintf(PRINT_NORMAL, _T("Enabling sound CPU\n")); + } else { + M6502Open(0); + M6502Reset(); + M6502Close(); + DrvSoundCPUHalt = 1; + bprintf(PRINT_NORMAL, _T("Disabling sound CPU\n")); + } + } + + return; + } + + case 0x803140: { + // irq_ack + return; + } + + case 0x803150: { + eeprom_unlocked = 1; + return; + } + + case 0x803170: { + DrvCPUtoSound = d & 0xff; + DrvCPUtoSoundReady = 1; + M6502Open(0); + nCyclesDone[1] += M6502Run(100); + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + nCyclesDone[1] += M6502Run(100); + M6502Close(); + return; + } + + case 0x930000: { + DrvScrollX = d & 0x1ff; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 GauntletSoundRead(UINT16 Address) +{ + switch (Address) { + case 0x1010: { + DrvCPUtoSoundReady = 0; + return DrvCPUtoSound; + } + + case 0x1020: { + return 0xff - DrvInput[5]; + } + + case 0x1030: + case 0x1031: { + /*INT32 temp = 0x30; + + if (atarigen_cpu_to_sound_ready) temp ^= 0x80; + if (atarigen_sound_to_cpu_ready) temp ^= 0x40; + if (tms5220_ready_r(devtag_get_device(space->machine, "tms"))) temp ^= 0x20; + if (!(input_port_read(space->machine, "803008") & 0x0008)) temp ^= 0x10; + + return temp;*/ + + UINT8 Res = 0x30; + UINT8 Input = DrvInput[4] | (DrvVBlank ? 0x40 : 0x00); + + if (DrvCPUtoSoundReady) Res ^= 0x80; + if (DrvSoundtoCPUReady) Res ^= 0x40; + Res ^= 0x20; + if (!(Input & 0x08)) Res ^= 0x10; + return Res; + } + + case 0x1800: + case 0x1801: + case 0x1802: + case 0x1803: + case 0x1804: + case 0x1805: + case 0x1806: + case 0x1807: + case 0x1808: + case 0x1809: + case 0x180a: + case 0x180b: + case 0x180c: + case 0x180d: + case 0x180e: + case 0x180f: { + // pokey_r + return 0; + } + + case 0x1811: { + return BurnYM2151ReadStatus(); + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Read Byte %04X\n"), Address); + } + } + + return 0; +} + +void GauntletSoundWrite(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x1000: + case 0x1001: + case 0x1002: + case 0x1003: + case 0x1004: + case 0x1005: + case 0x1006: + case 0x1007: + case 0x1008: + case 0x1009: + case 0x100a: + case 0x100b: + case 0x100c: + case 0x100d: + case 0x100e: + case 0x100f: { + DrvSoundtoCPU = Data; + DrvSoundtoCPUReady = 1; + SekOpen(0); + SekSetIRQLine(6, SEK_IRQSTATUS_ACK); + SekClose(); + return; + } + + case 0x1030: + case 0x1031: + case 0x1032: + case 0x1033: + case 0x1034: + case 0x1035: { + // sound_ctl_w + return; + } + + case 0x1800: + case 0x1801: + case 0x1802: + case 0x1803: + case 0x1804: + case 0x1805: + case 0x1806: + case 0x1807: + case 0x1808: + case 0x1809: + case 0x180a: + case 0x180b: + case 0x180c: + case 0x180d: + case 0x180e: + case 0x180f: { + // pokey_w + return; + } + + case 0x1810: { + BurnYM2151SelectRegister(Data); + return; + } + + case 0x1811: { + BurnYM2151WriteRegister(Data); + return; + } + + case 0x1820: { + // tms5220_w + return; + } + + case 0x1830: { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_NONE); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Write Byte %04X, %02X\n"), Address, Data); + } + } +} + +void atarigen_swap_mem(void *ptr1, void *ptr2, INT32 bytes) +{ + UINT8 *p1 = (UINT8 *)ptr1; + UINT8 *p2 = (UINT8 *)ptr2; + while (bytes--) { + INT32 temp = *p1; + *p1++ = *p2; + *p2++ = temp; + } +} + +static INT32 CharPlaneOffsets[2] = { 0, 4 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +//static INT32 MOPlaneOffsets[4] = { 0x180000, 0x100000, 0x080000, 0x000000 }; +static INT32 MOPlaneOffsets[4] = { 3*8*0x18000, 2*8*0x18000, 1*8*0x18000, 0*8*0x18000 }; +static INT32 MOXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 MOYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(/*0x40000*/0x60000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 5, 2); if (nRet != 0) return 1; + + atarigen_swap_mem(Drv68KRom + 0x000000, Drv68KRom + 0x008000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x040000, Drv68KRom + 0x048000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x050000, Drv68KRom + 0x058000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x060000, Drv68KRom + 0x068000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x070000, Drv68KRom + 0x078000, 0x8000); + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom + 0x0000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6502Rom + 0x4000, 7, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, /*0x40000*/0x60000); + /*nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 16, 1); if (nRet != 0) return 1;*/ + nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 16, 1); if (nRet != 0) return 1; + for (UINT32 i = 0; i < /*0x40000*/0x60000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(/*0x2000*/12288, 4, 8, 8, MOPlaneOffsets, MOXOffsets, MOYOffsets, 0x40, DrvTempRom, DrvMotionObjectTiles); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68010); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPlayfieldRam , 0x900000, 0x901fff, SM_RAM); + SekMapMemory(DrvMOSpriteRam , 0x902000, 0x903fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x2000 , 0x904000, 0x904fff, SM_RAM); + SekMapMemory(DrvAlphaRam , 0x905000, 0x905f7f, SM_RAM); + SekMapMemory(DrvMOSlipRam , 0x905f80, 0x905fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x910000, 0x9107ff, SM_RAM); + SekSetReadByteHandler(0, Gauntlet68KReadByte); + SekSetWriteByteHandler(0, Gauntlet68KWriteByte); + SekSetReadWordHandler(0, Gauntlet68KReadWord); + SekSetWriteWordHandler(0, Gauntlet68KWriteWord); + SekClose(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502Ram , 0x0000, 0x0fff, M6502_RAM); + M6502MapMemory(DrvM6502Rom , 0x4000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(GauntletSoundRead); + M6502SetWriteByteHandler(GauntletSoundWrite); + M6502Close(); + + atarigen_slapstic_init(0x038000, 104); + atarigen_eeprom_init(); + + BurnYM2151Init(14318180 / 4, 25.0); + + GenericTilesInit(); + + static struct atarigen_modesc gauntlet_modesc = + { + 1024, /* maximum number of MO's */ + 2, /* number of bytes per MO entry */ + 0x800, /* number of bytes between MO words */ + 3, /* ignore an entry if this word == 0xffff */ + 3, 0, 0x3ff, /* link = (data[linkword] >> linkshift) & linkmask */ + 0 /* render in reverse link order */ + }; + + atarigen_init_display_list (&gauntlet_modesc); + + DrvGameType = GAME_GAUNTLET; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 Gaunt2pInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(/*0x40000*/0x60000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 5, 2); if (nRet != 0) return 1; + + atarigen_swap_mem(Drv68KRom + 0x000000, Drv68KRom + 0x008000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x040000, Drv68KRom + 0x048000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x050000, Drv68KRom + 0x058000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x060000, Drv68KRom + 0x068000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x070000, Drv68KRom + 0x078000, 0x8000); + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom + 0x0000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6502Rom + 0x4000, 7, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, /*0x40000*/0x60000); + /*nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 16, 1); if (nRet != 0) return 1;*/ + nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 16, 1); if (nRet != 0) return 1; + for (UINT32 i = 0; i < /*0x40000*/0x60000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(/*0x2000*/12288, 4, 8, 8, MOPlaneOffsets, MOXOffsets, MOYOffsets, 0x40, DrvTempRom, DrvMotionObjectTiles); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68010); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPlayfieldRam , 0x900000, 0x901fff, SM_RAM); + SekMapMemory(DrvMOSpriteRam , 0x902000, 0x903fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x2000 , 0x904000, 0x904fff, SM_RAM); + SekMapMemory(DrvAlphaRam , 0x905000, 0x905f7f, SM_RAM); + SekMapMemory(DrvMOSlipRam , 0x905f80, 0x905fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x910000, 0x9107ff, SM_RAM); + SekSetReadByteHandler(0, Gauntlet68KReadByte); + SekSetWriteByteHandler(0, Gauntlet68KWriteByte); + SekSetReadWordHandler(0, Gauntlet68KReadWord); + SekSetWriteWordHandler(0, Gauntlet68KWriteWord); + SekClose(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502Ram , 0x0000, 0x0fff, M6502_RAM); + M6502MapMemory(DrvM6502Rom , 0x4000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(GauntletSoundRead); + M6502SetWriteByteHandler(GauntletSoundWrite); + M6502Close(); + + atarigen_slapstic_init(0x038000, 107); + atarigen_eeprom_init(); + + BurnYM2151Init(14318180 / 4, 25.0); + + GenericTilesInit(); + + static struct atarigen_modesc gauntlet_modesc = + { + 1024, /* maximum number of MO's */ + 2, /* number of bytes per MO entry */ + 0x800, /* number of bytes between MO words */ + 3, /* ignore an entry if this word == 0xffff */ + 3, 0, 0x3ff, /* link = (data[linkword] >> linkshift) & linkmask */ + 0 /* render in reverse link order */ + }; + + atarigen_init_display_list (&gauntlet_modesc); + + DrvGameType = GAME_GAUNTLET; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 Gaunt2Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(/*0x40000*/0x60000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x38000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x50001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x50000, 7, 2); if (nRet != 0) return 1; + + atarigen_swap_mem(Drv68KRom + 0x000000, Drv68KRom + 0x008000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x040000, Drv68KRom + 0x048000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x050000, Drv68KRom + 0x058000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x060000, Drv68KRom + 0x068000, 0x8000); + atarigen_swap_mem(Drv68KRom + 0x070000, Drv68KRom + 0x078000, 0x8000); + + // Load M6502 Program Rom + nRet = BurnLoadRom(DrvM6502Rom + 0x0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6502Rom + 0x4000, 9, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x0400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, /*0x40000*/0x60000); + /*nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 16, 1); if (nRet != 0) return 1;*/ + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x2c000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x44000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x5c000, 22, 1); if (nRet != 0) return 1; + for (UINT32 i = 0; i < /*0x40000*/0x60000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(/*0x2000*/12288, 4, 8, 8, MOPlaneOffsets, MOXOffsets, MOYOffsets, 0x40, DrvTempRom, DrvMotionObjectTiles); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68010); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvPlayfieldRam , 0x900000, 0x901fff, SM_RAM); + SekMapMemory(DrvMOSpriteRam , 0x902000, 0x903fff, SM_RAM); + SekMapMemory(Drv68KRam + 0x2000 , 0x904000, 0x904fff, SM_RAM); + SekMapMemory(DrvAlphaRam , 0x905000, 0x905f7f, SM_RAM); + SekMapMemory(DrvMOSlipRam , 0x905f80, 0x905fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0x910000, 0x9107ff, SM_RAM); + SekSetReadByteHandler(0, Gauntlet68KReadByte); + SekSetWriteByteHandler(0, Gauntlet68KWriteByte); + SekSetReadWordHandler(0, Gauntlet68KReadWord); + SekSetWriteWordHandler(0, Gauntlet68KWriteWord); + SekClose(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502Ram , 0x0000, 0x0fff, M6502_RAM); + M6502MapMemory(DrvM6502Rom , 0x4000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(GauntletSoundRead); + M6502SetWriteByteHandler(GauntletSoundWrite); + M6502Close(); + + atarigen_slapstic_init(0x038000, 106); + atarigen_eeprom_init(); + + BurnYM2151Init(14318180 / 4, 25.0); + + GenericTilesInit(); + + static struct atarigen_modesc gauntlet_modesc = + { + 1024, /* maximum number of MO's */ + 2, /* number of bytes per MO entry */ + 0x800, /* number of bytes between MO words */ + 3, /* ignore an entry if this word == 0xffff */ + 3, 0, 0x3ff, /* link = (data[linkword] >> linkshift) & linkmask */ + 0 /* render in reverse link order */ + }; + + atarigen_init_display_list (&gauntlet_modesc); + + DrvGameType = GAME_GAUNTLET2; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + M6502Exit(); + + GenericTilesExit(); + + atarigen_exit(); + atarigen_slapstic_exit(); + + BurnFree(Mem); + + DrvVBlank = 0; + DrvSoundResetVal = 0; + DrvSoundCPUHalt = 0; + DrvGameType = 0; + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + static const UINT8 ztable[16] = { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 }; + INT32 i, r, g, b; + + i = ztable[(nColour >> 12) & 15]; + r = ((nColour >> 8) & 15) * i; + g = ((nColour >> 4) & 15) * i; + b = ((nColour >> 0) & 15) * i; + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x400; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +#if 0 +static TILE_GET_INFO( get_playfield_tile_info ) +{ + UINT16 data = atarigen_playfield[tile_index]; + int code = ((playfield_tile_bank * 0x1000) + (data & 0xfff)) ^ 0x800; + int color = 0x10 + (playfield_color_bank * 8) + ((data >> 12) & 7); + SET_TILE_INFO(0, code, color, (data >> 15) & 1); +} +#endif + +static void DrvRenderPlayfield(INT32 PriorityDraw) +{ + INT32 mx, my, Data, Code, Colour, x, y, TileIndex, Priority; + + UINT16 *VideoRam = (UINT16*)DrvPlayfieldRam; + + for (mx = 0; mx < 64; mx++) { + for (my = 0; my < 64; my++) { + TileIndex = (my * 64) + mx; + Data = VideoRam[TileIndex]; + Code = ((DrvTileBank * 0x1000) + (Data & 0xfff)) ^ 0x800; + + if (Code < 0x3000) { + Colour = 0x10 + ((DrvGameType == GAME_GAUNTLET || DrvGameType == GAME_GAUNTLET2) ? 0x08 : 0x00) + (0x100 >> 4) + ((Data >> 12) & 7); + + y = 8 * mx; + x = 8 * my; + + x -= DrvScrollX; + y -= DrvScrollY; + if (x < -8) x += 512; + if (y < -8) y += 512; + + Priority = (Data >> 15) & 1; //xFlip + + if (Priority == PriorityDraw) { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvMotionObjectTiles); + } + } + } + } +} + +//static void DrvRenderSprites() +//{ +//} + +#if 0 + UINT16 data = atarigen_alpha[tile_index]; + int code = data & 0x3ff; + int color = ((data >> 10) & 0x0f) | ((data >> 9) & 0x20); + int opaque = data & 0x8000; + SET_TILE_INFO(1, code, color, opaque ? TILE_FORCE_LAYER0 : 0); +#endif +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, Opaque, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvAlphaRam; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + UINT16 Data = VideoRam[TileIndex]; + Code = Data & 0x3ff; + Colour = ((Data >> 10) & 0x0f) | ((Data >> 9) & 0x20); + Opaque = Data & 0x8000; + + x = 8 * mx; + y = 8 * my; + + if (Opaque) { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + + DrvRenderPlayfield(0); + DrvRenderPlayfield(1); + atarigen_render_display_list(); + DrvRenderCharLayer(); + + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 262; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = (14318180 / 2) / 60; + nCyclesTotal[1] = (14318180 / 8) / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + + INT32 NextScanline = 0; + + UINT16 *AlphaRam = (UINT16*)DrvAlphaRam; + DrvScrollY = AlphaRam[0xf6e >> 1]; + DrvTileBank = DrvScrollY & 0x03; + DrvScrollY >>= 7; + DrvScrollY &= 0x1ff; + + if (DrvGameType == GAME_GAUNTLET) { + if (DrvTileBank > 1) DrvTileBank -= 2; + } + + if (DrvGameType == GAME_GAUNTLET2) { + if (DrvTileBank == 3) DrvTileBank = 0; + } + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 11) DrvVBlank = 0; + if (i == 250) DrvVBlank = 1; + if (i == 261) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (i == NextScanline) { + INT32 Link = (DrvMOSlipRam[2 * (((i + DrvScrollY) / 8) & 0x3f) + 0] | (DrvMOSlipRam[2 * (((i + DrvScrollY) / 8) & 0x3f) + 1] << 8)) & 0x3ff; + atarigen_update_display_list(DrvMOSpriteRam, Link, i); + + if (!NextScanline) { + NextScanline += 8 - (DrvScrollY & 7); + } else { + NextScanline += 8; + } + } + + if (!DrvSoundCPUHalt) { + M6502Open(0); + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6502Run(nCyclesSegment); + if (i == 64 || i == 128 || i == 192 || i == 256) M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_ACK); + M6502Close(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029607; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +struct BurnDriver BurnDrvGauntlet = { + "gauntlet", NULL, NULL, NULL, "1985", + "Gauntlet (rev 14)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, GauntletRomInfo, GauntletRomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlets = { + "gauntlets", "gauntlet", NULL, NULL, "1985", + "Gauntlet (Spanish, rev 15)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, GauntletsRomInfo, GauntletsRomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletj = { + "gauntletj", "gauntlet", NULL, NULL, "1985", + "Gauntlet (Japanese, rev 13)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, GauntletjRomInfo, GauntletjRomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletg = { + "gauntletg", "gauntlet", NULL, NULL, "1985", + "Gauntlet (German, rev 10)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, GauntletgRomInfo, GauntletgRomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletj12 = { + "gauntletj12", "gauntlet", NULL, NULL, "1985", + "Gauntlet (Japanese, rev 12)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletj12RomInfo, Gauntletj12RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr9 = { + "gauntletr9", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 9)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr9RomInfo, Gauntletr9RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletgr8 = { + "gauntletgr8", "gauntlet", NULL, NULL, "1985", + "Gauntlet (German, rev 8)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletgr8RomInfo, Gauntletgr8RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr7 = { + "gauntletr7", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 7)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr7RomInfo, Gauntletr7RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletgr6 = { + "gauntletgr6", "gauntlet", NULL, NULL, "1985", + "Gauntlet (German, rev 6)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletgr6RomInfo, Gauntletgr6RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr5 = { + "gauntletr5", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 5)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr5RomInfo, Gauntletr5RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr4 = { + "gauntletr4", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 4)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr4RomInfo, Gauntletr4RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletgr3 = { + "gauntletgr3", "gauntlet", NULL, NULL, "1985", + "Gauntlet (German, rev 3)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletgr3RomInfo, Gauntletgr3RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr2 = { + "gauntletr2", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 2)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr2RomInfo, Gauntletr2RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntletr1 = { + "gauntletr1", "gauntlet", NULL, NULL, "1985", + "Gauntlet (rev 1)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntletr1RomInfo, Gauntletr1RomName, NULL, NULL , GauntletInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2p = { + "gauntlet2p", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, rev 6)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pRomInfo, Gauntlet2pRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2pj = { + "gauntlet2pj", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, Japanese, rev 5)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pjRomInfo, Gauntlet2pjRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2pg = { + "gauntlet2pg", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, German, rev 4)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pgRomInfo, Gauntlet2pgRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2pr3 = { + "gauntlet2pr3", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, rev 3)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pr3RomInfo, Gauntlet2pr3RomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2pj2 = { + "gauntlet2pj2", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, Japanese rev 2)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pj2RomInfo, Gauntlet2pj2RomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGauntlet2pg1 = { + "gauntlet2pg1", "gauntlet", NULL, NULL, "1985", + "Gauntlet (2 Players, German, rev 1)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gauntlet2pg1RomInfo, Gauntlet2pg1RomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2pInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGaunt2 = { + "gaunt2", NULL, NULL, NULL, "1986", + "Gauntlet II\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gaunt2RomInfo, Gaunt2RomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGaunt2g = { + "gaunt2g", "gaunt2", NULL, NULL, "1986", + "Gauntlet II (German)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gaunt2gRomInfo, Gaunt2gRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGaunt22p = { + "gaunt22p", "gaunt2", NULL, NULL, "1986", + "Gauntlet II (2 Players, rev 2)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gaunt22pRomInfo, Gaunt22pRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGaunt22p1 = { + "gaunt22p1", "gaunt2", NULL, NULL, "1986", + "Gauntlet II (2 Players, rev 1)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gaunt22p1RomInfo, Gaunt22p1RomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGaunt22pg = { + "gaunt22pg", "gaunt2", NULL, NULL, "1986", + "Gauntlet II (2 Players, German)\0", NULL, "Atari Games", "Atari Gauntlet", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, Gaunt22pgRomInfo, Gaunt22pgRomName, NULL, NULL , GauntletInputInfo, NULL, + Gaunt2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 336, 240, 4, 3 +}; + +//GAME( 1988, vindctr2, 0, gauntlet, vindctr2, vindctr2, ROT0, "Atari Games", "Vindicators Part II (rev 3)", 0 ) +//GAME( 1988, vindc2r2, vindctr2, gauntlet, vindctr2, vindctr2, ROT0, "Atari Games", "Vindicators Part II (rev 2)", 0 ) +//GAME( 1988, vindc2r1, vindctr2, gauntlet, vindctr2, vindctr2, ROT0, "Atari Games", "Vindicators Part II (rev 1)", 0 ) diff --git a/src/burn/drivers/misc_pre90s/d_gberet.cpp b/src/burn/drivers/misc_pre90s/d_gberet.cpp new file mode 100644 index 00000000..2109163f --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_gberet.cpp @@ -0,0 +1,1109 @@ +// FB Alpha Green Beret driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "sn76496.h" + +static UINT8 *Mem, *MemEnd, *Rom, *Gfx0, *Gfx1, *Prom; +static UINT32 *Palette, *DrvPalette; +static UINT8 DrvRecalcPal; + +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[4], DrvReset; + +static UINT8 nmi_enable, irq_enable; +static UINT16 gberetb_scroll; +static UINT8 flipscreen; +static UINT8 gberet_spritebank; +static INT32 mrgoemon_bank; + +static INT32 game_type = 0; // 0 gberet / rushatck, 1 gberetb, 2 mrgoemon + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy3 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy3 + 1, "p2 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 3, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 4, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 3, "p1 down" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p2 right" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 3, "p2 down" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , DrvJoy3 + 2, "service" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDips + 2, "dip" }, + +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo gberetbInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy3 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy3 + 6, "p2 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 5, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 4, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 3, "p1 down" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 3, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(gberetb) + +static struct BurnDIPInfo gberetDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x12, 0x82, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + + {0x13, 0xff, 0xff, 0x4a, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "30K 70K 70K+" }, + {0x13, 0x01, 0x18, 0x10, "40K 80K 80K+" }, + {0x13, 0x01, 0x18, 0x08, "50K 100K 100K+" }, + {0x13, 0x01, 0x18, 0x00, "50K 200K 200K+" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0x14, 0xff, 0xff, 0x0f, NULL }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x02, 0x02, "Single" }, + {0x14, 0x01, 0x02, 0x00, "Dual" }, +}; + +STDDIPINFO(gberet) + +static struct BurnDIPInfo gberetbDIPList[]= +{ + {0x0b, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0b, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x0b, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x0b, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x0b, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x0b, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x0b, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x0b, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x0b, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x0b, 0x82, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + {0x0b, 0x82, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x0b, 0x00, 0x0f, 0x00, NULL }, + + {0x0c, 0xff, 0xff, 0x4a, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x03, 0x03, "2" }, + {0x0c, 0x01, 0x03, 0x02, "3" }, + {0x0c, 0x01, 0x03, 0x01, "5" }, + {0x0c, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x04, 0x00, "Upright" }, + {0x0c, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0c, 0x01, 0x18, 0x18, "30K 70K 70K+" }, + {0x0c, 0x01, 0x18, 0x10, "40K 80K 80K+" }, + {0x0c, 0x01, 0x18, 0x08, "50K 100K 100K+" }, + {0x0c, 0x01, 0x18, 0x00, "50K 200K 200K+" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x60, 0x60, "Easy" }, + {0x0c, 0x01, 0x60, 0x40, "Normal" }, + {0x0c, 0x01, 0x60, 0x20, "Difficult" }, + {0x0c, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x80, 0x80, "Off" }, + {0x0c, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(gberetb) + +static struct BurnDIPInfo mrgoemonDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x12, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x12, 0x82, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + {0x12, 0x82, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x12, 0x00, 0x0f, 0x00, NULL }, + + {0x13, 0xff, 0xff, 0x4a, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x02, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "20K 60K+" }, + {0x13, 0x01, 0x18, 0x10, "30K 70K+" }, + {0x13, 0x01, 0x18, 0x08, "40K 80K+" }, + {0x13, 0x01, 0x18, 0x00, "50K 90K+" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x60, "Easy" }, + {0x13, 0x01, 0x60, 0x40, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0x14, 0xff, 0xff, 0x0f, NULL }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x02, 0x02, "Single" }, + {0x14, 0x01, 0x02, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, +}; + +STDDIPINFO(mrgoemon) + +static void mrgoemon_bankswitch(INT32 nBank) +{ + mrgoemon_bank = nBank; + ZetMapArea(0xf800, 0xffff, 0, Rom + 0x10000 + mrgoemon_bank); + ZetMapArea(0xf800, 0xffff, 2, Rom + 0x10000 + mrgoemon_bank); +} + +void __fastcall gberet_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe040: + case 0xe041: + case 0xe042: + return; + + case 0xe043: + gberet_spritebank = data; + return; + + case 0xe044: + { + nmi_enable = data & 0x01; + irq_enable = data & ((game_type & 2) ? 0x02 : 0x04); + + flipscreen = data & 0x08; + } + return; + + case 0xf000: + { + // Coin counters + + if (game_type == 2) { + mrgoemon_bankswitch((data >> 5) << 11); + } + } + return; + + case 0xf400: + SN76496Write(0, data); + return; + + case 0xf600: // watchdog + return; + + case 0xf900: + case 0xf901: + gberetb_scroll = (((address & 1) << 8) | data) + 0x38; + return; + } + + if (address >= 0xe000 && address <= 0xe03f) { + Rom[address] = data; + return; + } + + if (game_type != 1) return; + + if (address >= 0xe900 && address <= 0xe9ff) { + Rom[address] = data; + return; + } +} + +UINT8 __fastcall gberet_read(UINT16 address) +{ + UINT8 nRet = 0xff; + + switch (address) + { + case 0xf200: + return DrvDips[1]; + + case 0xf400: + return DrvDips[2]; + + case 0xf600: + return DrvDips[0]; + + case 0xf601: + { + if (game_type & 1) return DrvDips[3]; + + for (INT32 i = 0; i < 8; i++) nRet ^= DrvJoy2[i] << i; + + return nRet; + } + + + case 0xf602: + { + for (INT32 i = 0; i < 8; i++) nRet ^= DrvJoy1[i] << i; + + return nRet; + } + + + case 0xf603: + { + for (INT32 i = 0; i < 8; i++) nRet ^= DrvJoy3[i] << i; + + return nRet; + } + } + + if (address >= 0xe000 && address <= 0xe03f) { + return Rom[address]; + } + + if (game_type != 1) return 0; + + if (address >= 0xe900 && address <= 0xe9ff) { + return Rom[address]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + flipscreen = 0; + nmi_enable = 0; + irq_enable = 0; + mrgoemon_bank = 0; + gberetb_scroll = 0; + gberet_spritebank = 0; + + ZetOpen(0); + ZetReset(); + + if (game_type & 2) { + mrgoemon_bankswitch(0); + } + + ZetClose(); + + return 0; +} + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom = Next; Next += 0x14000; + + Gfx0 = Next; Next += 0x08000; + Gfx1 = Next; Next += 0x20000; + + Prom = Next; Next += 0x00220; + + Palette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static void DrvCreatePalette() +{ + UINT32 tmp[0x20]; + + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0, bit1, bit2; + INT32 r, g, b; + + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (Prom[i] >> 6) & 0x01; + bit2 = (Prom[i] >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + tmp[i] = (r << 16) | (g << 8) | b; + } + + Prom += 0x20; + + for (INT32 i = 0; i < 0x100; i++) + { + UINT8 ctabentry; + + ctabentry = (Prom[0x000 + i] & 0x0f) | 0x10; + Palette[0x000 + i] = tmp[ctabentry]; + + ctabentry = (Prom[0x100 + i] & 0x0f); + Palette[0x100 + i] = tmp[ctabentry]; + } +} + +static void Graphics_Decode(INT32 *CharPlanes, INT32 *CharXOffs, INT32 *CharYOffs, INT32 *SprPlanes, INT32 *SprXOffs, INT32 *SprYOffs, INT32 SprMod) +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return; + } + + memcpy (tmp, Gfx0, 0x4000); + + GfxDecode(0x200, 4, 8, 8, CharPlanes, CharXOffs, CharYOffs, 0x100, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x10000); + + GfxDecode(0x200, 4, 16, 16, SprPlanes, SprXOffs, SprYOffs, SprMod, tmp, Gfx1); + + BurnFree (tmp); +} + +static void DrvGfxDecode() +{ + static INT32 Planes[4] = { 0, 1, 2, 3 }; + static INT32 XOffs[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; + static INT32 YOffs[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; + + Graphics_Decode(Planes, XOffs, YOffs, Planes, XOffs, YOffs, 0x400); +} + +static void BootGfxDecode() +{ + static INT32 CharPlanes[4] = { 0, 1, 2, 3 }; + static INT32 CharXOffs[8] = { 24, 28, 0, 4, 8, 12, 16, 20 }; + static INT32 CharYOffs[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + static INT32 SpriPlanes[4] = { 0, 0x20000, 0x40000, 0x60000 }; + static INT32 SpriXOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; + static INT32 SpriYOffs[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + Graphics_Decode(CharPlanes, CharXOffs, CharYOffs, SpriPlanes, SpriXOffs, SpriYOffs, 0x100); +} + +static INT32 GetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *Load0 = Rom; + UINT8 *Load1 = Gfx0; + UINT8 *Load2 = Gfx1; + UINT8 *Load3 = Prom; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(Load0, i, 1)) return 1; + Load0 += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(Load1, i, 1)) return 1; + Load1 += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(Load2, i, 1)) return 1; + Load2 += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(Load3, i, 1)) return 1; + Load3 += ri.nLen; + + continue; + } + } + + if (game_type == 2) { + memcpy (Rom + 0x10000, Rom + 0x0c000, 0x04000); + memset (Rom + 0x0c000, 0, 0x04000); + } + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + if (GetRoms()) return 1; + + if (game_type == 1) { + BootGfxDecode(); + } else { + DrvGfxDecode(); + } + DrvCreatePalette(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(gberet_read); + ZetSetWriteHandler(gberet_write); + ZetMapArea(0x0000, 0xbfff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0xbfff, 2, Rom + 0x0000); + ZetMapArea(0xc000, 0xcfff, 0, Rom + 0xc000); + ZetMapArea(0xc000, 0xcfff, 1, Rom + 0xc000); + ZetMapArea(0xd000, 0xd0ff, 0, Rom + 0xd000); + ZetMapArea(0xd000, 0xd0ff, 1, Rom + 0xd000); + ZetMapArea(0xd100, 0xd1ff, 0, Rom + 0xd100); + ZetMapArea(0xd100, 0xd1ff, 1, Rom + 0xd100); + ZetMapArea(0xd200, 0xdfff, 0, Rom + 0xd200); + ZetMapArea(0xd200, 0xdfff, 1, Rom + 0xd200); + ZetMapArea(0xd200, 0xdfff, 2, Rom + 0xd200); + if (game_type == 2) { + ZetMapArea(0xe800, 0xe8ff, 0, Rom + 0xe800); + ZetMapArea(0xe800, 0xe8ff, 1, Rom + 0xe800); + ZetMapArea(0xe800, 0xe8ff, 2, Rom + 0xe800); + } + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 18432000 / 12, 0); + + DrvDoReset(); + + if (game_type == 0) { + BurnSetRefreshRate(30.0); + } + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + BurnFree (Rom); + + game_type = 0; + + + return 0; +} + +static inline void put_pixel(INT32 x, INT32 y, INT32 src, INT32 color) +{ + INT32 pxl = color | src; + + if (y < 0 || x < 0 || x >= nScreenWidth || y >= nScreenHeight || !Prom[pxl]) return; + + pTransDraw[(y * nScreenWidth) + x] = pxl; +} + +static void gberet_draw_16x16(INT32 num, INT32 sx, INT32 sy, INT32 color, INT32 flipx, INT32 flipy) +{ + color |= 0x100; + UINT8 *src = Gfx1 + (num << 8); + + if (flipy) { + if (flipx) { + for (INT32 y = sy + 15; y >= sy; y--) { + for (INT32 x = sx + 15; x >= sx; x--, src++) { + put_pixel(x, y, *src, color); + } + } + } else { + for (INT32 y = sy + 15; y >= sy; y--) { + for (INT32 x = sx; x < sx + 16; x++, src++) { + put_pixel(x, y, *src, color); + } + } + } + } else { + if (flipx) { + for (INT32 y = sy; y < sy + 16; y++) { + for (INT32 x = sx + 15; x >= sx; x--, src++) { + put_pixel(x, y, *src, color); + } + } + } else { + for (INT32 y = sy; y < sy + 16; y++) { + for (INT32 x = sx; x < sx + 16; x++, src++) { + put_pixel(x, y, *src, color); + } + } + } + } +} + +static void gberet_draw_sprites() +{ + UINT8 *sr = Rom + 0xd000 + ((~gberet_spritebank & 8) << 5); + + for (INT32 offs = 0; offs < 0xc0; offs += 4) + { + if (sr[offs + 3]) + { + INT32 attr = sr[offs + 1]; + INT32 code = sr[offs + 0] + ((attr & 0x40) << 2); + INT32 sx = sr[offs + 2] - 2 * (attr & 0x80); + INT32 sy = sr[offs + 3]; + INT32 color = (attr & 0x0f) << 4; + INT32 flipx = attr & 0x10; + INT32 flipy = attr & 0x20; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + sx -= 8; + + gberet_draw_16x16(code, sx, sy, color, flipx, flipy); + } + } +} + +static void gberetb_draw_sprites() +{ + for (INT32 offs = 0x100 - 4; offs >= 0; offs -= 4) + { + if (Rom[0xe901 + offs]) + { + INT32 attr = Rom[0xe903 + offs]; + INT32 code = Rom[0xe900 + offs] + ((attr & 0x40) << 2); + INT32 sx = Rom[0xe902 + offs] - 2 * (attr & 0x80); + INT32 sy = 240 - Rom[0xe901 + offs]; + INT32 color = (attr & 0x0f) << 4; + INT32 flipx = attr & 0x10; + INT32 flipy = attr & 0x20; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + sx -= 8; + + gberet_draw_16x16(code, sx, sy, color, flipx, flipy); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalcPal) { + for (INT32 i = 0; i < 0x200; i++) { + DrvPalette[i] = BurnHighCol(Palette[i] >> 16, Palette[i] >> 8, Palette[i], 0); + } + } + + for (INT32 offs = 0x40; offs < 0x7c0; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 3) & 0xf8; + INT32 attr = Rom[0xc000 + offs]; + INT32 code = Rom[0xc800 + offs] + ((attr & 0x40) << 2); + INT32 color = attr & 0x0f; + INT32 flipy = attr & 0x20; + INT32 flipx = attr & 0x10; + + INT32 scroll = 0; + + if (game_type & 1) { + if (sy > 0x2f && sy < 0xe8) { + scroll = gberetb_scroll; + } + } else { + scroll = Rom[0xe000 | (sy >> 3)] | (Rom[0xe020 | (sy >> 3)] << 8); + } + + sx -= scroll; + sx += (sx >> 21) & 0x200; + + if (flipscreen) { + sx = 248 - sx; + sy = 248 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + sx -= 8; + + if (sx < -7 || sx >= 0x100 || sy < 0 || sy > 223) continue; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + + } + } + } + + if (game_type & 1) { + gberetb_draw_sprites(); + } else { + gberet_draw_sprites(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = game_type ? 16 : 32; + + if (DrvReset) { + DrvDoReset(); + } + + ZetOpen(0); + + INT32 nCyclesDone, nCyclesTotal; + + nCyclesDone = 0; + nCyclesTotal = 3072000 / (nBurnFPS / 256); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCyclesSegment = (nCyclesTotal - nCyclesDone) / (nInterleave - i); + + nCyclesDone = ZetRun(nCyclesSegment); + + if (irq_enable && i == (nInterleave - 1)) { + ZetRaiseIrq(0); + } + + if (nmi_enable && (i & 1)) { + ZetNmi(); + } + } + + ZetClose(); + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029675; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0xc000; + ba.nLen = 0x4000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + SCAN_VAR(nmi_enable); + SCAN_VAR(irq_enable); + SCAN_VAR(flipscreen); + SCAN_VAR(mrgoemon_bank); + SCAN_VAR(gberetb_scroll); + SCAN_VAR(gberet_spritebank); + + ZetOpen(0); + mrgoemon_bankswitch(mrgoemon_bank); + ZetClose(); + } + + return 0; +} + + +// Green Beret + +static struct BurnRomInfo gberetRomDesc[] = { + { "577l03.10c", 0x4000, 0xae29e4ff, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "577l02.8c", 0x4000, 0x240836a5, 1 | BRF_PRG | BRF_ESS }, // 1 + { "577l01.7c", 0x4000, 0x41fa3e1f, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "577l07.3f", 0x4000, 0x4da7bd1b, 2 | BRF_GRA }, // 3 Characters + + { "577l06.5e", 0x4000, 0x0f1cb0ca, 3 | BRF_GRA }, // 4 Sprites + { "577l05.4e", 0x4000, 0x523a8b66, 3 | BRF_GRA }, // 5 + { "577l08.4f", 0x4000, 0x883933a4, 3 | BRF_GRA }, // 6 + { "577l04.3e", 0x4000, 0xccecda4c, 3 | BRF_GRA }, // 7 + + { "577h09.2f", 0x0020, 0xc15e7c80, 4 | BRF_GRA }, // 8 Color Proms + { "577h11.6f", 0x0100, 0x2a1a992b, 4 | BRF_GRA }, // 9 + { "577h10.5f", 0x0100, 0xe9de1e53, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(gberet) +STD_ROM_FN(gberet) + +struct BurnDriver BurnDrvGberet = { + "gberet", NULL, NULL, NULL, "1985", + "Green Beret\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, gberetRomInfo, gberetRomName, NULL, NULL, DrvInputInfo, gberetDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x200, + 240, 224, 4, 3 +}; + + +// Rush'n Attack (US) + +static struct BurnRomInfo rushatckRomDesc[] = { + { "577h03.10c", 0x4000, 0x4d276b52, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "577h02.8c", 0x4000, 0xb5802806, 1 | BRF_PRG | BRF_ESS }, // 1 + { "577h01.7c", 0x4000, 0xda7c8f3d, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "577h07.3f", 0x4000, 0x03f9815f, 2 | BRF_GRA }, // 3 Characters + + { "577l06.5e", 0x4000, 0x0f1cb0ca, 3 | BRF_GRA }, // 4 Sprites + { "577h05.4e", 0x4000, 0x9d028e8f, 3 | BRF_GRA }, // 5 + { "577l08.4f", 0x4000, 0x883933a4, 3 | BRF_GRA }, // 6 + { "577l04.3e", 0x4000, 0xccecda4c, 3 | BRF_GRA }, // 7 + + { "577h09.2f", 0x0020, 0xc15e7c80, 4 | BRF_GRA }, // 8 Color Proms + { "577h11.6f", 0x0100, 0x2a1a992b, 4 | BRF_GRA }, // 9 + { "577h10.5f", 0x0100, 0xe9de1e53, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(rushatck) +STD_ROM_FN(rushatck) + +struct BurnDriver BurnDrvRushatck = { + "rushatck", "gberet", NULL, NULL, "1985", + "Rush'n Attack (US)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, rushatckRomInfo, rushatckRomName, NULL, NULL, DrvInputInfo, gberetDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x200, + 240, 224, 4, 3 +}; + + +// Green Beret (bootleg) + +static struct BurnRomInfo gberetbRomDesc[] = { + { "2-ic82.10g", 0x8000, 0x6d6fb494, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "3-ic81.10f", 0x4000, 0xf1520a0a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1-ic92.12c", 0x4000, 0xb0189c87, 2 | BRF_GRA }, // 2 Characters + + { "7-1c8.2b", 0x4000, 0x86334522, 3 | BRF_GRA }, // 3 Sprites + { "6-ic9.2c", 0x4000, 0xbda50d3e, 3 | BRF_GRA }, // 4 + { "5-ic10.2d", 0x4000, 0x6a7b3881, 3 | BRF_GRA }, // 5 + { "4-ic11.2e", 0x4000, 0x3fb186c9, 3 | BRF_GRA }, // 6 + + { "577h09", 0x0020, 0xc15e7c80, 4 | BRF_GRA }, // 7 Color Proms + { "577h11.6f", 0x0100, 0x2a1a992b, 4 | BRF_GRA }, // 8 + { "577h10.5f", 0x0100, 0xe9de1e53, 4 | BRF_GRA }, // 9 + + { "ic35.5h.bin", 0x0001, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(gberetb) +STD_ROM_FN(gberetb) + +static INT32 gberetbInit() +{ + game_type = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvGberetb = { + "gberetb", "gberet", NULL, NULL, "1985", + "Green Beret (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, gberetbRomInfo, gberetbRomName, NULL, NULL, gberetbInputInfo, gberetbDIPInfo, + gberetbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x200, + 240, 224, 4, 3 +}; + + +// Mr. Goemon (Japan) + +static struct BurnRomInfo mrgoemonRomDesc[] = { + { "621d01.10c", 0x8000, 0xb2219c56, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "621d02.12c", 0x8000, 0xc3337a97, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "621a05.6d", 0x4000, 0xf0a6dfc5, 2 | BRF_GRA }, // 2 Characters + + { "621d03.4d", 0x8000, 0x66f2b973, 3 | BRF_GRA }, // 3 Sprites + { "621d04.5d", 0x8000, 0x47df6301, 3 | BRF_GRA }, // 4 + + { "621a06.5f", 0x0020, 0x7c90de5f, 4 | BRF_GRA }, // 5 Color Proms + { "621a08.7f", 0x0100, 0x2fb244dd, 4 | BRF_GRA }, // 6 + { "621a07.6f", 0x0100, 0x3980acdc, 4 | BRF_GRA }, // 7 +}; + +STD_ROM_PICK(mrgoemon) +STD_ROM_FN(mrgoemon) + +static INT32 mrgoemonInit() +{ + game_type = 2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvMrgoemon = { + "mrgoemon", NULL, NULL, NULL, "1986", + "Mr. Goemon (Japan)\0", NULL, "Konami", "Miscellaneous", + L"Mr. Goemon \u4E94\u53F3\u885B\u9580 (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, mrgoemonRomInfo, mrgoemonRomName, NULL, NULL, DrvInputInfo, mrgoemonDIPInfo, + mrgoemonInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x200, + 240, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_ginganin.cpp b/src/burn/drivers/misc_pre90s/d_ginganin.cpp new file mode 100644 index 00000000..47cef346 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_ginganin.cpp @@ -0,0 +1,766 @@ +// FB Alpha Ginga NinkyouDen driver module +// Based on MAME driver by Luca Elia and Takahiro Nogi + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "burn_y8950.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvGfxROM4; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvM6809RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT16 *pAY8910Buffer[3]; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT16 *layer_control; +static UINT16 *scroll; + +static UINT8 MC6840_idx0; +static UINT8 MC6840_idx1; +static UINT8 MC6840_reg0; +static UINT8 MC6840_reg1; +static UINT8 MC6840_tempo; +static UINT8 MC6840_tempo2; +static UINT8 MC6840_ctr; +static UINT8 MC6840_flag; + +static UINT8 DrvJoy1[16]; +static UINT16 DrvInputs[1]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static struct BurnInputInfo GinganinInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 12, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 14, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 13, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 6, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 7, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 8, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 9, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ginganin) + +static struct BurnDIPInfo GinganinDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x00, "5 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x04, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x02, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x38, 0x00, "5 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x20, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x10, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x30, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x08, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 2, "Infinite Lives" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Free Play & Invulnerability" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x00, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x08, 0x00, "Upright" }, + {0x12, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze (Cheat)" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ginganin) + +void __fastcall ginganin_write_word(UINT32 address, UINT16 data) +{ + if (address < 0x20000) return; + + switch (address) + { + case 0x060000: // scrolly fg + case 0x060002: // scrollx fg + case 0x060004: // scrolly bg + case 0x060006: // scrollx bg + scroll[(address & 6) / 2] = data; + return; + + case 0x060008: + *layer_control = data; + return; + + case 0x06000c: + *flipscreen = ~data & 1; + return; + + case 0x06000e: + *soundlatch = data & 0xff; + M6809SetIRQ(0x20, M6809_IRQSTATUS_AUTO); // nmi + return; + } +} + +UINT16 __fastcall ginganin_read_word(UINT32 address) +{ + switch (address) + { + case 0x070000: + return DrvInputs[0]; + + case 0x070002: + return (DrvDips[0] | (DrvDips[1] << 8)); + } + + return 0; +} + +void __fastcall ginganin_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ + return; +} + +UINT8 __fastcall ginganin_read_byte(UINT32 /*address*/) +{ + return 0; +} + +void ginganin_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x0800: + { + MC6840_idx0 = data; + MC6840_flag = MC6840_idx0 / 0x80; + + if (MC6840_flag && MC6840_reg0 != MC6840_tempo && MC6840_reg0 != 0) { + MC6840_tempo = MC6840_reg0; + } + } + return; + + case 0x0801: + MC6840_idx1 = data; + return; + + case 0x0802: + MC6840_reg0 = data; + return; + + case 0x0803: + MC6840_reg1 = data; + return; + + case 0x2000: + case 0x2001: // y8950 + BurnY8950Write(address & 1, data); + return; + + case 0x2800: + case 0x2801: + AY8910Write(0, address & 1, data); + return; + } +} + +UINT8 ginganin_sound_read(UINT16 address) +{ + if (address == 0x1800) { + return *soundlatch; + } + + bprintf(PRINT_NORMAL, _T("read %x\n"), address); + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6809TotalCycles() * nSoundRate / 1000000; +} + +static void DrvGfxDecode(UINT8 *src, INT32 len, INT32 size) +{ + INT32 Planes[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x200, 0x204, 0x208, 0x20c, 0x210, 0x214, 0x218, 0x21c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0 }; + + UINT8 *tmp = (UINT8*)malloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, src, len); + + GfxDecode((len * 2) / (size * size), 4, size, size, Planes, XOffs, YOffs, (size * size * 4), tmp, src); + + if (tmp) { + free (tmp); + tmp = NULL; + } +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + AY8910Reset(0); + BurnY8950Reset(); + + MC6840_idx0 = 0; + MC6840_idx1 = 0; + MC6840_reg0 = 0; + MC6840_reg1 = 0; + MC6840_flag = 0; + MC6840_tempo = 0; + MC6840_tempo2 = 0; + MC6840_ctr = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x020000; + DrvM6809ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x040000; + DrvGfxROM2 = Next; Next += 0x008000; + DrvGfxROM3 = Next; Next += 0x100000; + DrvGfxROM4 = Next; Next += 0x008000; + + DrvSndROM = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvM6809RAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x004000; + DrvTxtRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + + layer_control = (UINT16*)Next; Next += 0x000001 * sizeof(UINT16); + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + scroll = (UINT16*)Next; Next += 0x000004 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvM6809ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x010000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 8, 1)) return 1; + memcpy (DrvGfxROM3 + 0x40000, DrvGfxROM3 + 0x10000, 0x10000); + if (BurnLoadRom(DrvGfxROM3 + 0x010000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x020000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x030000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM4 + 0x000000, 12, 1)) return 1; + BurnByteswap(DrvGfxROM4, 0x8000); + + if (BurnLoadRom(DrvSndROM + 0x000000, 13, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x010000, 14, 1)) return 1; + + DrvGfxDecode(DrvGfxROM0, 0x20000, 16); + DrvGfxDecode(DrvGfxROM1, 0x20000, 16); + DrvGfxDecode(DrvGfxROM2, 0x04000, 8); + DrvGfxDecode(DrvGfxROM3, 0x50000, 16); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x020000, 0x023fff, SM_RAM); + SekMapMemory(DrvTxtRAM, 0x030000, 0x0307ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x040000, 0x0407ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x050000, 0x0507ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x068000, 0x06bfff, SM_RAM); + SekSetWriteWordHandler(0, ginganin_write_word); + SekSetWriteByteHandler(0, ginganin_write_byte); + SekSetReadWordHandler(0, ginganin_read_word); + SekSetReadByteHandler(0, ginganin_read_byte); + SekClose(); + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809RAM, 0x0000, 0x07ff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x4000, 0x4000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(ginganin_sound_write); + M6809SetReadByteHandler(ginganin_sound_read); + M6809Close(); + + AY8910Init(0, 3579545 / 2, nBurnSoundRate, NULL, NULL, NULL, NULL); + + BurnY8950Init(3579545, DrvSndROM, 0x20000, NULL, &DrvSynchroniseStream, 1); + BurnTimerAttachM6809Y8950(1000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + M6809Exit(); + + BurnY8950Exit(); + AY8910Exit(0); + + BurnFree (AllMem); + + return 0; +} + +static void DrvRecalcPalette() +{ + UINT16 *pal = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x800 / 2; i++) + { + INT32 r = (pal[i] >> 12) & 0x0f; + INT32 g = (pal[i] >> 8) & 0x0f; + INT32 b = (pal[i] >> 4) & 0x0f; + + DrvPalette[i] = BurnHighCol((r << 4) | r, (g << 4) | g, (b << 4) | b, 0); + } +} + +static void draw_layer(UINT8 *ram, UINT8 *gfx, INT32 color_offset, INT32 wide, INT32 scroll_offset, INT32 transparent) +{ + INT32 scrollx = scroll[scroll_offset + 1] & ((wide * 16) - 1); + INT32 scrolly = scroll[scroll_offset + 0] & 0x01ff; + + UINT16 *vram = (UINT16*)ram; + + for (INT32 offs = 0; offs < 16 * 16 + 16; offs++) + { + INT32 ofst = ((((offs >> 4) + (scrollx >> 4)) & (wide-1)) << 5) + (((offs & 0xf) + (scrolly >> 4)) & 0x01f); + + INT32 sy = ((offs & 0xf) << 4) - (scrolly & 0x0f); + INT32 sx = ((offs >> 4) << 4) - (scrollx & 0x0f); + + INT32 attr = vram[ofst]; + + if (*flipscreen) { + if (transparent) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, attr & 0x3ff, 240 - sx, 240 - sy - 16, attr >> 12, 4, 0x0f, color_offset, gfx); + } else { + Render16x16Tile_FlipXY_Clip(pTransDraw, attr & 0x3ff, 240 - sx, 240 - sy - 16, attr >> 12, 4, color_offset, gfx); + } + } else { + if (transparent) { + Render16x16Tile_Mask_Clip(pTransDraw, attr & 0x3ff, sx, sy - 16, attr >> 12, 4, 0x0f, color_offset, gfx); + } else { + Render16x16Tile_Clip(pTransDraw, attr & 0x3ff, sx, sy - 16, attr >> 12, 4, color_offset, gfx); + } + } + } +} + +static void draw_txt_layer() +{ + UINT16 *vram = (UINT16*)DrvTxtRAM; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + if (sy < 16 || sy > 240) continue; + + INT32 attr = vram[offs]; + + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, attr & 0x1ff, sx ^ 0xf8, (sy ^ 0xf8) - 16, attr >> 12, 4, 0x0f, 0x000, DrvGfxROM2); + } else { + Render8x8Tile_Mask(pTransDraw, attr & 0x1ff, sx, sy - 16, attr >> 12, 4, 0x0f, 0x000, DrvGfxROM2); + } + } +} + +static void draw_sprites() +{ + UINT16 *vram = (UINT16*)DrvSprRAM; + + for (INT32 offs = 0; offs < 0x800 / 2; offs += 4) + { + INT32 sy = vram[offs + 0]; + INT32 sx = vram[offs + 1]; + INT32 code = vram[offs + 2]; + INT32 color = vram[offs + 3] >> 12; + INT32 flipx = code & 0x4000; + INT32 flipy = code & 0x8000; + + sx = (sx & 0xff) - (sx & 0x100); + sy = (sy & 0xff) - (sy & 0x100); + code &= 0xfff; + + if (code >= 0xa00) continue; + + if (*flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx ^= 0x4000; + flipy ^= 0x8000; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0x0f, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0x0f, 0x100, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0x0f, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0x0f, 0x100, DrvGfxROM3); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvRecalcPalette(); + } + + if (*layer_control & 0x01) { + draw_layer(DrvGfxROM4, DrvGfxROM0, 0x300, 0x200, 2, 0); + } else { + BurnTransferClear(); + } + + if (*layer_control & 0x02) { + draw_layer(DrvFgRAM, DrvGfxROM1, 0x200, 0x100, 0, 1); + } + + if (*layer_control & 0x08) { + draw_sprites(); + } + + if (*layer_control & 0x04) { + draw_txt_layer(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void sound_interrupt() +{ + if (MC6840_tempo2 != MC6840_tempo) { + MC6840_tempo2 = MC6840_tempo; + MC6840_ctr = 0; + } + + if (MC6840_flag) { + if (MC6840_ctr > MC6840_tempo) { + MC6840_ctr = 0; + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } else { + MC6840_ctr++; + } + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xffff; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + } + + INT32 nInterleave = 60; + INT32 nCyclesTotal[2] = { 6000000 / 60, 1000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + M6809NewFrame(); + + SekOpen(0); + M6809Open(0); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment; + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + nSegment = nCyclesTotal[1] / nInterleave; + BurnTimerUpdateY8950(i * (nCyclesTotal[1] / nInterleave)); + sound_interrupt(); + } + + SekClose(); + + BurnTimerEndFrameY8950(nCyclesTotal[1]); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + + BurnY8950Update(pBurnSoundOut, nBurnSoundLen); + } + + M6809Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(MC6840_idx0); + SCAN_VAR(MC6840_idx1); + SCAN_VAR(MC6840_reg0); + SCAN_VAR(MC6840_reg1); + SCAN_VAR(MC6840_tempo); + SCAN_VAR(MC6840_tempo2); + SCAN_VAR(MC6840_ctr); + SCAN_VAR(MC6840_flag); + } + + return 0; +} + + +// Ginga NinkyouDen (set 1) + +static struct BurnRomInfo ginganinRomDesc[] = { + { "gn_02.bin", 0x10000, 0x4a4e012f, 1 | BRF_PRG | BRF_ESS }, // 0 M68000 Code + { "gn_01.bin", 0x10000, 0x30256fcb, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gn_05.bin", 0x10000, 0xe76e10e7, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code + + { "gn_15.bin", 0x10000, 0x1b8ac9fb, 3 | BRF_GRA }, // 3 Background Tiles + { "gn_14.bin", 0x10000, 0xe73fe668, 3 | BRF_GRA }, // 4 + + { "gn_12.bin", 0x10000, 0xc134a1e9, 4 | BRF_GRA }, // 5 Foreground Tiles + { "gn_13.bin", 0x10000, 0x1d3bec21, 4 | BRF_GRA }, // 6 + + { "gn_10.bin", 0x04000, 0xae371b2d, 5 | BRF_GRA }, // 7 Characters + + { "gn_06.bin", 0x20000, 0xbdc65835, 6 | BRF_GRA }, // 8 Sprites + { "gn_07.bin", 0x10000, 0xc2b8eafe, 6 | BRF_GRA }, // 9 + { "gn_08.bin", 0x10000, 0xf7c73c18, 6 | BRF_GRA }, // 10 + { "gn_09.bin", 0x10000, 0xa5e07c3b, 6 | BRF_GRA }, // 11 + + { "gn_11.bin", 0x08000, 0xf0d0e605, 7 | BRF_GRA }, // 12 Background Tilemap + + { "gn_04.bin", 0x10000, 0x0ed9133b, 8 | BRF_SND }, // 13 Y8950 Samples + { "gn_03.bin", 0x10000, 0xf1ba222c, 8 | BRF_SND }, // 14 +}; + +STD_ROM_PICK(ginganin) +STD_ROM_FN(ginganin) + +struct BurnDriver BurnDrvGinganin = { + "ginganin", NULL, NULL, NULL, "1987", + "Ginga NinkyouDen (set 1)\0", NULL, "Jaleco", "Miscellaneous", + L"\u9280\u6CB3\u4EFB\u4FA0\u4F1D (set 1)\0Ginga NinkyouDen (set 1)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, ginganinRomInfo, ginganinRomName, NULL, NULL, GinganinInputInfo, GinganinDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Ginga NinkyouDen (set 2) + +static struct BurnRomInfo ginganinaRomDesc[] = { + { "2.bin", 0x10000, 0x6da1d8a3, 1 | BRF_PRG | BRF_ESS }, // 0 M68000 Code + { "1.bin", 0x10000, 0x0bd32d59, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gn_05.bin", 0x10000, 0xe76e10e7, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code + + { "gn_15.bin", 0x10000, 0x1b8ac9fb, 3 | BRF_GRA }, // 3 Background Tiles + { "gn_14.bin", 0x10000, 0xe73fe668, 3 | BRF_GRA }, // 4 + + { "gn_12.bin", 0x10000, 0xc134a1e9, 4 | BRF_GRA }, // 5 Foreground Tiles + { "gn_13.bin", 0x10000, 0x1d3bec21, 4 | BRF_GRA }, // 6 + + { "10.bin", 0x04000, 0x48a20745, 5 | BRF_GRA }, // 7 Characters + + { "gn_06.bin", 0x20000, 0xbdc65835, 6 | BRF_GRA }, // 8 Sprites + { "gn_07.bin", 0x10000, 0xc2b8eafe, 6 | BRF_GRA }, // 9 + { "gn_08.bin", 0x10000, 0xf7c73c18, 6 | BRF_GRA }, // 10 + { "gn_09.bin", 0x10000, 0xa5e07c3b, 6 | BRF_GRA }, // 11 + + { "gn_11.bin", 0x08000, 0xf0d0e605, 7 | BRF_GRA }, // 12 Background Tilemap + + { "gn_04.bin", 0x10000, 0x0ed9133b, 8 | BRF_SND }, // 13 Y8950 Samples + { "gn_03.bin", 0x10000, 0xf1ba222c, 8 | BRF_SND }, // 14 +}; + +STD_ROM_PICK(ginganina) +STD_ROM_FN(ginganina) + +struct BurnDriver BurnDrvGinganina = { + "ginganina", "ginganin", NULL, NULL, "1987", + "Ginga NinkyouDen (set 2)\0", NULL, "Jaleco", "Miscellaneous", + L"\u9280\u6CB3\u4EFB\u4FA0\u4F1D (set 2)\0Ginga NinkyouDen (set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, ginganinaRomInfo, ginganinaRomName, NULL, NULL, GinganinInputInfo, GinganinDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_gng.cpp b/src/burn/drivers/misc_pre90s/d_gng.cpp new file mode 100644 index 00000000..b50c1fb5 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_gng.cpp @@ -0,0 +1,1481 @@ +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "burn_ym2203.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvM6809Rom = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvM6809Ram = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvFgVideoRam = NULL; +static UINT8 *DrvBgVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteRamBuffer = NULL; +static UINT8 *DrvPaletteRam1 = NULL; +static UINT8 *DrvPaletteRam2 = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvRomBank; +static UINT8 DrvBgScrollX[2]; +static UINT8 DrvBgScrollY[2]; +static UINT8 DrvSoundLatch; + +static INT32 RomLoadOffset = 0; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static INT32 Diamond; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 5, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo DiamondInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Diamond) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xfb, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Plays" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Plays" }, + {0x12, 0x01, 0x0f, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Coinage affects" }, + {0x12, 0x01, 0x10, 0x10, "Coin A" }, + {0x12, 0x01, 0x10, 0x00, "Coin B" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "20k 70k 70k" }, + {0x13, 0x01, 0x18, 0x10, "30k 80k 80k" }, + {0x13, 0x01, 0x18, 0x08, "20k 80k" }, + {0x13, 0x01, 0x18, 0x00, "30k 80k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x40, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo DrvjDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xfb, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Plays" }, + {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, + {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Plays" }, + {0x12, 0x01, 0x0f, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Coinage affects" }, + {0x12, 0x01, 0x10, 0x10, "Coin A" }, + {0x12, 0x01, 0x10, 0x00, "Coin B" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x02, "4" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x04, 0x00, "Upright" }, + {0x13, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x18, 0x18, "20k 70k 70k" }, + {0x13, 0x01, 0x18, 0x10, "30k 80k 80k" }, + {0x13, 0x01, 0x18, 0x08, "20k 80k" }, + {0x13, 0x01, 0x18, 0x00, "30k 80k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x60, 0x40, "Easy" }, + {0x13, 0x01, 0x60, 0x60, "Normal" }, + {0x13, 0x01, 0x60, 0x20, "Difficult" }, + {0x13, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drvj) + +static struct BurnDIPInfo DiamondDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0x81, NULL }, + {0x0b, 0xff, 0xff, 0x07, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0a, 0x01, 0x03, 0x00, "2" }, + {0x0a, 0x01, 0x03, 0x01, "3" }, + {0x0a, 0x01, 0x03, 0x02, "4" }, + {0x0a, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 4 , "Credits A" }, + {0x0a, 0x01, 0x0c, 0x00, "x1" }, + {0x0a, 0x01, 0x0c, 0x04, "x2" }, + {0x0a, 0x01, 0x0c, 0x08, "x3" }, + {0x0a, 0x01, 0x0c, 0x0c, "x4" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0a, 0x01, 0x30, 0x30, "4 Coins 1 Play" }, + {0x0a, 0x01, 0x30, 0x20, "3 Coins 1 Play" }, + {0x0a, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x0a, 0x01, 0x30, 0x00, "1 Coin 1 Play" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0a, 0x01, 0x80, 0x80, "Off" }, + {0x0a, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Energy Loss" }, + {0x0b, 0x01, 0x0f, 0x00, "Slowest" }, + {0x0b, 0x01, 0x0f, 0x01, "-6 Slower" }, + {0x0b, 0x01, 0x0f, 0x02, "-5 Slower" }, + {0x0b, 0x01, 0x0f, 0x03, "-4 Slower" }, + {0x0b, 0x01, 0x0f, 0x04, "-3 Slower" }, + {0x0b, 0x01, 0x0f, 0x05, "-2 Slower" }, + {0x0b, 0x01, 0x0f, 0x06, "-1 Slower" }, + {0x0b, 0x01, 0x0f, 0x07, "Normal" }, + {0x0b, 0x01, 0x0f, 0x08, "+1 Faster" }, + {0x0b, 0x01, 0x0f, 0x09, "+2 Faster" }, + {0x0b, 0x01, 0x0f, 0x0a, "+3 Faster" }, + {0x0b, 0x01, 0x0f, 0x0b, "+4 Faster" }, + {0x0b, 0x01, 0x0f, 0x0c, "+5 Faster" }, + {0x0b, 0x01, 0x0f, 0x0d, "+6 Faster" }, + {0x0b, 0x01, 0x0f, 0x0e, "+7 Faster" }, + {0x0b, 0x01, 0x0f, 0x0f, "Fastest" }, + + {0 , 0xfe, 0 , 4 , "Credits B" }, + {0x0b, 0x01, 0x30, 0x00, "x1" }, + {0x0b, 0x01, 0x30, 0x10, "x2" }, + {0x0b, 0x01, 0x30, 0x20, "x3" }, + {0x0b, 0x01, 0x30, 0x30, "x4" }, +}; + +STDDIPINFO(Diamond) + +static struct BurnRomInfo DrvRomDesc[] = { + { "gg4.bin", 0x04000, 0x66606beb, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "gg3.bin", 0x08000, 0x9e01c65e, BRF_ESS | BRF_PRG }, // 1 + { "gg5.bin", 0x08000, 0xd6397b2b, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gg17.bin", 0x04000, 0x93e50a8f, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gg14.bin", 0x04000, 0x6aaf12f9, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 + + { "gg-pal10l8.bin",0x0002c, 0x87f1b7e0, BRF_GRA }, // 19 PLDs +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvaRomDesc[] = { + { "gng.n10", 0x04000, 0x60343188, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "gng.n9", 0x04000, 0xb6b91cfb, BRF_ESS | BRF_PRG }, // 1 + { "gng.n8", 0x04000, 0xa5cfa928, BRF_ESS | BRF_PRG }, // 2 + { "gng.n13", 0x04000, 0xfd9a8dda, BRF_ESS | BRF_PRG }, // 3 + { "gng.n12", 0x04000, 0x13cf6238, BRF_ESS | BRF_PRG }, // 4 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 5 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 6 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 7 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 8 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 9 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 10 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 11 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 12 + + { "gg17.bin", 0x04000, 0x93e50a8f, BRF_GRA }, // 13 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 14 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 15 + { "gg14.bin", 0x04000, 0x6aaf12f9, BRF_GRA }, // 16 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 17 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 18 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 19 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 20 +}; + +STD_ROM_PICK(Drva) +STD_ROM_FN(Drva) + +static struct BurnRomInfo DrvcRomDesc[] = { + { "mm_c_04", 0x04000, 0x4f94130f, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "mm_c_03", 0x08000, 0x1def138a, BRF_ESS | BRF_PRG }, // 1 + { "mm_c_05", 0x08000, 0xed28e86e, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gg17.bin", 0x04000, 0x93e50a8f, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gg14.bin", 0x04000, 0x6aaf12f9, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Drvc) +STD_ROM_FN(Drvc) + +static struct BurnRomInfo DrvblRomDesc[] = { + { "5.84490.10n", 0x04000, 0x66606beb, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "4.84490.9n", 0x04000, 0x527f5c39, BRF_ESS | BRF_PRG }, // 1 + { "3.84490.8n", 0x04000, 0x1c5175d5, BRF_ESS | BRF_PRG }, // 2 + { "7.84490.13n", 0x04000, 0xfd9a8dda, BRF_ESS | BRF_PRG }, // 3 + { "6.84490.12n", 0x04000, 0xc83dbd10, BRF_ESS | BRF_PRG }, // 4 + + { "2.8529.13h", 0x08000, 0x55cfb196, BRF_ESS | BRF_PRG }, // 5 Z80 Program + + { "1.84490.11e", 0x04000, 0xecfccf07, BRF_GRA }, // 6 Characters + + { "13.84490.3e", 0x04000, 0xddd56fa9, BRF_GRA }, // 7 Tiles + { "12.84490.1e", 0x04000, 0x7302529d, BRF_GRA }, // 8 + { "11.84490.3c", 0x04000, 0x20035bda, BRF_GRA }, // 9 + { "10.84490.1c", 0x04000, 0xf12ba271, BRF_GRA }, // 10 + { "9.84490.3b", 0x04000, 0xe525207d, BRF_GRA }, // 11 + { "8.84490.1b", 0x04000, 0x2d77e9b2, BRF_GRA }, // 12 + + { "19.84472.4n", 0x04000, 0x4613afdc, BRF_GRA }, // 13 Sprites + { "18.84472.3n", 0x04000, 0x06d7e5ca, BRF_GRA }, // 14 + { "17.84472.1n", 0x04000, 0xbc1fe02d, BRF_GRA }, // 15 + { "16.84472.4l", 0x04000, 0x608d68d5, BRF_GRA }, // 16 + { "15.84490.3l", 0x04000, 0xe80c3fca, BRF_GRA }, // 17 + { "14.84490.1l", 0x04000, 0x7780a925, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Drvbl) +STD_ROM_FN(Drvbl) + +static struct BurnRomInfo DrvblitaRomDesc[] = { + { "3", 0x04000, 0x4859d068, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "4-5", 0x08000, 0x233a4589, BRF_ESS | BRF_PRG }, // 1 + { "1-2", 0x08000, 0xed28e86e, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gg17.bin", 0x04000, 0x93e50a8f, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gg14.bin", 0x04000, 0x6aaf12f9, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 + + { "gg-pal10l8.bin",0x0002c, 0x87f1b7e0, BRF_GRA }, // 19 PLDs +}; + +STD_ROM_PICK(Drvblita) +STD_ROM_FN(Drvblita) + +static struct BurnRomInfo DrvtRomDesc[] = { + { "mm04", 0x04000, 0x652406f6, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "mm03", 0x08000, 0xfb040b42, BRF_ESS | BRF_PRG }, // 1 + { "mm05", 0x08000, 0x8f7cff61, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gg17.bin", 0x04000, 0x93e50a8f, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gg14.bin", 0x04000, 0x6aaf12f9, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Drvt) +STD_ROM_FN(Drvt) + +static struct BurnRomInfo MakaimurRomDesc[] = { + { "10n.rom", 0x04000, 0x81e567e0, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "8n.rom", 0x08000, 0x9612d66c, BRF_ESS | BRF_PRG }, // 1 + { "12n.rom", 0x08000, 0x65a6a97b, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gng13.n4", 0x04000, 0x4613afdc, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gng16.l4", 0x04000, 0x608d68d5, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Makaimur) +STD_ROM_FN(Makaimur) + +static struct BurnRomInfo MakaimucRomDesc[] = { + { "mj04c.bin", 0x04000, 0x1294edb1, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "mj03c.bin", 0x08000, 0xd343332d, BRF_ESS | BRF_PRG }, // 1 + { "mj05c.bin", 0x08000, 0x535342c2, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gng13.n4", 0x04000, 0x4613afdc, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gng16.l4", 0x04000, 0x608d68d5, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Makaimuc) +STD_ROM_FN(Makaimuc) + +static struct BurnRomInfo MakaimugRomDesc[] = { + { "mj04g.bin", 0x04000, 0x757c94d3, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "mj03g.bin", 0x08000, 0x61b043bb, BRF_ESS | BRF_PRG }, // 1 + { "mj05g.bin", 0x08000, 0xf2fdccf5, BRF_ESS | BRF_PRG }, // 2 + + { "gg2.bin", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 3 Z80 Program + + { "gg1.bin", 0x04000, 0xecfccf07, BRF_GRA }, // 4 Characters + + { "gg11.bin", 0x04000, 0xddd56fa9, BRF_GRA }, // 5 Tiles + { "gg10.bin", 0x04000, 0x7302529d, BRF_GRA }, // 6 + { "gg9.bin", 0x04000, 0x20035bda, BRF_GRA }, // 7 + { "gg8.bin", 0x04000, 0xf12ba271, BRF_GRA }, // 8 + { "gg7.bin", 0x04000, 0xe525207d, BRF_GRA }, // 9 + { "gg6.bin", 0x04000, 0x2d77e9b2, BRF_GRA }, // 10 + + { "gng13.n4", 0x04000, 0x4613afdc, BRF_GRA }, // 11 Sprites + { "gg16.bin", 0x04000, 0x06d7e5ca, BRF_GRA }, // 12 + { "gg15.bin", 0x04000, 0xbc1fe02d, BRF_GRA }, // 13 + { "gng16.l4", 0x04000, 0x608d68d5, BRF_GRA }, // 14 + { "gg13.bin", 0x04000, 0xe80c3fca, BRF_GRA }, // 15 + { "gg12.bin", 0x04000, 0x7780a925, BRF_GRA }, // 16 + + { "tbp24s10.14k", 0x00100, 0x0eaf5158, BRF_GRA }, // 17 PROMs + { "63s141.2e", 0x00100, 0x4a1285a4, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Makaimug) +STD_ROM_FN(Makaimug) + +static struct BurnRomInfo DiamondRomDesc[] = { + { "d3o", 0x04000, 0xba4bf9f1, BRF_ESS | BRF_PRG }, // 0 M6809 Program Code + { "d3", 0x08000, 0xf436d6fa, BRF_ESS | BRF_PRG }, // 1 + { "d5o", 0x08000, 0xae58bd3a, BRF_ESS | BRF_PRG }, // 2 + { "d5", 0x08000, 0x453f3f9e, BRF_ESS | BRF_PRG }, // 3 + + { "d2", 0x08000, 0x615f5b6f, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "d1", 0x04000, 0x3a24e504, BRF_GRA }, // 5 Characters + + { "d11", 0x04000, 0x754357d7, BRF_GRA }, // 6 Tiles + { "d10", 0x04000, 0x7531edcd, BRF_GRA }, // 7 + { "d9", 0x04000, 0x22eeca08, BRF_GRA }, // 8 + { "d8", 0x04000, 0x6b61be60, BRF_GRA }, // 9 + { "d7", 0x04000, 0xfd595274, BRF_GRA }, // 10 + { "d6", 0x04000, 0x7f51dcd2, BRF_GRA }, // 11 + + { "d17", 0x04000, 0x8164b005, BRF_GRA }, // 12 Sprites + { "d14", 0x04000, 0x6f132163, BRF_GRA }, // 13 + + { "prom1", 0x00100, 0x0eaf5158, BRF_GRA }, // 14 PROMs + { "prom2", 0x00100, 0x4a1285a4, BRF_GRA }, // 15 +}; + +STD_ROM_PICK(Diamond) +STD_ROM_FN(Diamond) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvM6809Rom = Next; Next += 0x14000; + DrvZ80Rom = Next; Next += 0x08000; + + RamStart = Next; + + DrvM6809Ram = Next; Next += 0x01e00; + DrvZ80Ram = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x00200; + DrvSpriteRamBuffer = Next; Next += 0x00200; + DrvFgVideoRam = Next; Next += 0x00800; + DrvBgVideoRam = Next; Next += 0x00800; + DrvPaletteRam1 = Next; Next += 0x00100; + DrvPaletteRam2 = Next; Next += 0x00100; + + RamEnd = Next; + + DrvChars = Next; Next += 0x400 * 8 * 8; + DrvTiles = Next; Next += 0x400 * 16 * 16; + DrvSprites = Next; Next += 0x400 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + DrvRomBank = 0; + DrvBgScrollX[0] = DrvBgScrollX[1] = 0; + DrvBgScrollY[0] = DrvBgScrollY[1] = 0; + DrvSoundLatch = 0; + + return 0; +} + +UINT8 DrvGngM6809ReadByte(UINT16 Address) +{ + switch (Address) { + case 0x3000: { + return 0xff - DrvInput[0]; + } + + case 0x3001: { + return 0xff - DrvInput[1]; + } + + case 0x3002: { + return 0xff - DrvInput[2]; + } + + case 0x3003: { + return DrvDip[0]; + } + + case 0x3004: { + return DrvDip[1]; + } + + case 0x3c00: { + // nop + return 0; + } + } + + bprintf(PRINT_NORMAL, _T("M6809 Read Byte -> %04X\n"), Address); + + return 0; +} + + +void DrvGngM6809WriteByte(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x3a00: { + DrvSoundLatch = Data; + return; + } + + case 0x3b08: { + DrvBgScrollX[0] = Data; + return; + } + + case 0x3b09: { + DrvBgScrollX[1] = Data; + return; + } + + case 0x3b0a: { + DrvBgScrollY[0] = Data; + return; + } + + case 0x3b0b: { + DrvBgScrollY[1] = Data; + return; + } + + case 0x3c00: { + // nop + return; + } + + case 0x3d00: { + // flipscreen + return; + } + + case 0x3d01: { + // ??? + return; + } + + case 0x3e00: { + DrvRomBank = Data & 3; + if (Data == 4) { + DrvRomBank = 4; + M6809MapMemory(DrvM6809Rom, 0x4000, 0x5fff, M6809_ROM); + } else { + M6809MapMemory(DrvM6809Rom + 0xc000 + (DrvRomBank * 0x2000), 0x4000, 0x5fff, M6809_ROM); + } + return; + } + } + + bprintf(PRINT_NORMAL, _T("M6809 Write Byte -> %04X, %02X\n"), Address, Data); +} + +UINT8 __fastcall DrvGngZ80Read(UINT16 a) +{ + switch (a) { + case 0xc800: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall DrvGngZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xe001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xe002: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xe003: { + BurnYM2203Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[2] = { 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 TilePlaneOffsets[3] = { 0x80000, 0x40000, 0 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 SpritePlaneOffsets[4] = { 0x80004, 0x80000, 4, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x20000); + + // Load M6809 Program Roms + if (RomLoadOffset == 2) { + nRet = BurnLoadRom(DrvM6809Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x08000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x0c000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x10000, 4, 1); if (nRet != 0) return 1; + } else { + nRet = BurnLoadRom(DrvM6809Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x0c000, 2, 1); if (nRet != 0) return 1; + } + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 3 + RomLoadOffset, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 4 + RomLoadOffset, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x20000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 6 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 7 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c000, 8 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 10 + RomLoadOffset, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0xff, 0x20000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 12 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 13 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 15 + RomLoadOffset, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 16 + RomLoadOffset, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + // Setup the M6809 emulation + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809Ram , 0x0000, 0x1dff, M6809_RAM); + M6809MapMemory(DrvSpriteRam , 0x1e00, 0x1fff, M6809_RAM); + M6809MapMemory(DrvFgVideoRam , 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvBgVideoRam , 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvPaletteRam2 , 0x3800, 0x38ff, M6809_RAM); + M6809MapMemory(DrvPaletteRam1 , 0x3900, 0x39ff, M6809_RAM); + M6809MapMemory(DrvM6809Rom , 0x4000, 0x5fff, M6809_ROM); + M6809MapMemory(DrvM6809Rom + 0x2000 , 0x6000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(DrvGngM6809ReadByte); + M6809SetWriteByteHandler(DrvGngM6809WriteByte); + M6809Close(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(DrvGngZ80Read); + ZetSetWriteHandler(DrvGngZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(4); + BurnTimerAttachZet(3000000); + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DiamondInit() +{ + INT32 nRet = 0, nLen; + + Diamond = 1; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x20000); + + // Load M6809 Program Roms + nRet = BurnLoadRom(DrvM6809Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x04000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x0c000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6809Rom + 0x14000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the tiles + memset(DrvTempRom, 0, 0x20000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x04000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0c000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x14000, 11, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, DrvTempRom, DrvTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0xff, 0x20000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 13 + RomLoadOffset, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + // Setup the M6809 emulation + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809Ram , 0x0000, 0x1dff, M6809_RAM); + M6809MapMemory(DrvSpriteRam , 0x1e00, 0x1fff, M6809_RAM); + M6809MapMemory(DrvFgVideoRam , 0x2000, 0x27ff, M6809_RAM); + M6809MapMemory(DrvBgVideoRam , 0x2800, 0x2fff, M6809_RAM); + M6809MapMemory(DrvPaletteRam2 , 0x3800, 0x38ff, M6809_RAM); + M6809MapMemory(DrvPaletteRam1 , 0x3900, 0x39ff, M6809_RAM); + M6809MapMemory(DrvM6809Rom , 0x4000, 0x5fff, M6809_ROM); + M6809MapMemory(DrvM6809Rom + 0x2000 , 0x6000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(DrvGngM6809ReadByte); + M6809SetWriteByteHandler(DrvGngM6809WriteByte); + M6809Close(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(DrvGngZ80Read); + ZetSetWriteHandler(DrvGngZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(4); + BurnTimerAttachZet(3000000); + + GenericTilesInit(); + + DrvM6809Rom[0x2000] = 0; + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 GngaInit() +{ + RomLoadOffset = 2; + + return DrvInit(); +} + +static INT32 DrvExit() +{ + M6809Exit(); + ZetExit(); + + BurnYM2203Exit(); + + GenericTilesExit(); + + BurnFree(Mem); + + DrvRomBank = 0; + DrvBgScrollX[0] = DrvBgScrollX[1] = 0; + DrvBgScrollY[0] = DrvBgScrollY[1] = 0; + DrvSoundLatch = 0; + + RomLoadOffset = 0; + Diamond = 0; + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 12); + g = pal4bit(nColour >> 8); + b = pal4bit(nColour >> 4); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < 0x100; i++) { + INT32 Val = DrvPaletteRam1[i] + (DrvPaletteRam2[i] << 8); + + DrvPalette[i] = CalcCol(Val); + } +} + +static void DrvRenderBgLayer(INT32 Priority, INT32 Opaque) +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex, xScroll, yScroll, Split, Flip, xFlip, yFlip; + + xScroll = DrvBgScrollX[0] | (DrvBgScrollX[1] << 8); + xScroll &= 0x1ff; + + yScroll = DrvBgScrollY[0] | (DrvBgScrollY[1] << 8); + yScroll &= 0x1ff; + + for (mx = 0; mx < 32; mx++) { + for (my = 0; my < 32; my++) { + TileIndex = (my * 32) + mx; + + Attr = DrvBgVideoRam[TileIndex + 0x400]; + Code = DrvBgVideoRam[TileIndex + 0x000]; + + Code += (Attr & 0xc0) << 2; + Colour = Attr & 0x07; + + Split = (Attr & 0x08) >> 3; + + if (Split != Priority) continue; + + Flip = (Attr & 0x30) >> 4; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + y = 16 * mx; + x = 16 * my; + + x -= xScroll; + if (x < -16) x += 512; + y -= yScroll; + if (y < -16) y += 512; + + y -= 16; + + if (Opaque) { + if (x > 16 && x < 240 && y > 16 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 0, DrvTiles); + } + } + } + } else { + if (x > 16 && x < 240 && y > 16 && y < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvTiles); + } + } + } + } + } + } +} + +static void DrvRenderSprites() +{ + for (INT32 Offs = 0x200 - 4; Offs >= 0; Offs -= 4) { + UINT8 Attr = DrvSpriteRamBuffer[Offs + 1]; + INT32 sx = DrvSpriteRamBuffer[Offs + 3] - (0x100 * (Attr & 0x01)); + INT32 sy = DrvSpriteRamBuffer[Offs + 2]; + INT32 xFlip = Attr & 0x04; + INT32 yFlip = Attr & 0x08; + INT32 Code = DrvSpriteRamBuffer[Offs + 0] + ((Attr << 2) & 0x300); + INT32 Colour = (Attr >> 4) & 3; + + if (sx > 16 && sx < 240 && sy > 16 && sy < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy - 16, Colour, 4, 15, 0x40, DrvSprites); + } + } + } + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = DrvFgVideoRam[TileIndex + 0x400]; + Code = DrvFgVideoRam[TileIndex + 0x000]; + + Code += (Attr & 0xc0) << 2; + Colour = Attr & 0x0f; + + Flip = (Attr & 0x30) >> 4; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + y -= 16; + + if (x > 8 && x < 248 && y > 8 && y < 216) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x80, DrvChars); + } + } + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(0, 1); + DrvRenderSprites(); + DrvRenderBgLayer(1, 0); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 25; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 1500000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run M6809 + nCurrentCPU = 0; + M6809Open(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + if (i == 24) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + M6809Close(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (i == 5 || i == 10 || i == 15 || i == 20) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 6 || i == 11 || i == 16 || i == 21) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[1]); + ZetClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(0); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (pBurnDraw) DrvDraw(); + + memcpy(DrvSpriteRamBuffer, DrvSpriteRam, 0x200); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029696; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + M6809Scan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvBgScrollX); + SCAN_VAR(DrvBgScrollY); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + } + + return 0; +} + +struct BurnDriver BurnDrvGng = { + "gng", NULL, NULL, NULL, "1985", + "Ghosts'n Goblins (World? set 1)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGnga = { + "gnga", "gng", NULL, NULL, "1985", + "Ghosts'n Goblins (World? set 2)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvaRomInfo, DrvaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + GngaInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGngbl = { + "gngbl", "gng", NULL, NULL, "1985", + "Ghosts'n Goblins (bootleg with Cross)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvblRomInfo, DrvblRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + GngaInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGngblita = { + "gngblita", "gng", NULL, NULL, "1985", + "Ghosts'n Goblins (Italian bootleg, harder)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvblitaRomInfo, DrvblitaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGngt = { + "gngt", "gng", NULL, NULL, "1985", + "Ghosts'n Goblins (US)\0", NULL, "Capcom (Taito America License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvtRomInfo, DrvtRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGngc = { + "gngc", "gng", NULL, NULL, "1985", + "Ghosts'n Goblins (World Revision C)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DrvcRomInfo, DrvcRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMakaimur = { + "makaimur", "gng", NULL, NULL, "1985", + "Makai-Mura (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, MakaimurRomInfo, MakaimurRomName, NULL, NULL, DrvInputInfo, DrvjDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMakaimuc = { + "makaimurc", "gng", NULL, NULL, "1985", + "Makai-Mura (Japan revision C)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, MakaimucRomInfo, MakaimucRomName, NULL, NULL, DrvInputInfo, DrvjDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMakaimug = { + "makaimurg", "gng", NULL, NULL, "1985", + "Makai-Mura (Japan revision G)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, MakaimugRomInfo, MakaimugRomName, NULL, NULL, DrvInputInfo, DrvjDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDiamond = { + "diamond", NULL, NULL, NULL, "1985", + "Diamond Run\0", NULL, "KH Video", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, DiamondRomInfo, DiamondRomName, NULL, NULL, DiamondInputInfo, DiamondDIPInfo, + DiamondInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_gunsmoke.cpp b/src/burn/drivers/misc_pre90s/d_gunsmoke.cpp new file mode 100644 index 00000000..7d324be1 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_gunsmoke.cpp @@ -0,0 +1,1011 @@ +// FB Alpha Gun.Smoke driver module +// Based on MAME driver by Paul Leaman + +#include "tiles_generic.h" +#include "burn_ym2203.h" + +static UINT8 *Mem, *MemEnd, *Rom0, *Rom1, *Ram; +static UINT8 *Gfx0, *Gfx1, *Gfx2, *Gfx3, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[2], DrvReset; +static UINT32 *Palette, *DrvPal; +static UINT8 DrvCalcPal; +static UINT8 *SprTrnsp; + +static UINT8 soundlatch; +static UINT8 flipscreen; +static INT32 nGunsmokeBank; + +static UINT8 sprite3bank; +static UINT8 chon, bgon, objon; +static UINT8 gunsmoke_scrollx[2], gunsmoke_scrolly; + + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy2 + 6, "p1 fire 3"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p2 left" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy3 + 6, "p2 fire 3"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 4, "service" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip" }, + +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x03, 0x01, "30k 80k 80k+" }, + {0x14, 0x01, 0x03, 0x03, "30k 100k 100k+" }, + {0x14, 0x01, 0x03, 0x00, "30k 100k 150k+" }, + {0x14, 0x01, 0x03, 0x02, "30k 100k" }, + + {0 , 0xfe, 0 , 2 , "Demo" }, + {0x14, 0x01, 0x04, 0x00, "Off" }, + {0x14, 0x01, 0x04, 0x04, "On" }, +}; + +static struct BurnDIPInfo gunsmokaDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xf7, NULL }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x03, 0x01, "30k 80k 80k+" }, + {0x14, 0x01, 0x03, 0x03, "30k 100k 100k+" }, + {0x14, 0x01, 0x03, 0x00, "30k 100k 150k+" }, + {0x14, 0x01, 0x03, 0x02, "30k 100k" }, + + {0 , 0xfe, 0 , 2 , "Lifes" }, + {0x14, 0x01, 0x04, 0x04, "3" }, + {0x14, 0x01, 0x04, 0x00, "5" }, +}; + +static struct BurnDIPInfo gunsmokeDIPList[]= +{ + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x08, 0x00, "Upright" }, + {0x14, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x30, 0x20, "Easy" }, + {0x14, 0x01, 0x30, 0x30, "Normal" }, + {0x14, 0x01, 0x30, 0x10, "Difficult" }, + {0x14, 0x01, 0x30, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x15, 0x01, 0x07, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x07, 0x01, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x07, 0x02, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x07, 0x03, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x15, 0x01, 0x38, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x38, 0x08, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x38, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x15, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x15, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x15, 0x01, 0x38, 0x18, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x40, 0x00, "No" }, + {0x15, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFOEXT(Drv, Drv, gunsmoke) +STDDIPINFOEXT(gunsmoka, gunsmoka, gunsmoke) + + +static inline void gunsmoke_bankswitch(INT32 nBank) +{ + if (nGunsmokeBank != nBank) { + nGunsmokeBank = nBank; + + ZetMapArea(0x8000, 0xbfff, 0, Rom0 + 0x10000 + nBank * 0x04000); + ZetMapArea(0x8000, 0xbfff, 2, Rom0 + 0x10000 + nBank * 0x04000); + } +} + +void __fastcall gunsmoke_cpu0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc800: + soundlatch = data; + break; + + case 0xc804: + gunsmoke_bankswitch((data >> 2) & 3); + + flipscreen = data & 0x40; + chon = data & 0x80; + break; + + case 0xc806: + break; + + case 0xd800: + case 0xd801: + gunsmoke_scrollx[address & 1] = data; + break; + + case 0xd802: + case 0xd803: + gunsmoke_scrolly = data; + break; + + case 0xd806: + sprite3bank = data & 0x07; + + bgon = data & 0x10; + objon = data & 0x20; + break; + } +} + +UINT8 __fastcall gunsmoke_cpu0_read(UINT16 address) +{ + UINT8 ret = 0xff; + + switch (address) + { + case 0xc000: + { + for (INT32 i = 0; i < 8; i++) + ret ^= DrvJoy1[i] << i; + + return ret | 0x08; + } + + case 0xc001: + { + for (INT32 i = 0; i < 8; i++) + ret ^= DrvJoy2[i] << i; + + return ret; + } + + case 0xc002: + { + for (INT32 i = 0; i < 8; i++) + ret ^= DrvJoy3[i] << i; + + return ret; + } + + case 0xc003: // dips + return DrvDips[0]; + + case 0xc004: + return DrvDips[1]; + + // reads at c4c9 - c4cb are part of some sort of protection or bug + case 0xc4c9: + return 0xff; + case 0xc4ca: + case 0xc4cb: + return 0; + } + + return 0; +} + +void __fastcall gunsmoke_cpu1_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: // control 0 + BurnYM2203Write(0, 0, data); + break; + + case 0xe001: // write 0 + BurnYM2203Write(0, 1, data); + break; + + case 0xe002: // control 1 + BurnYM2203Write(1, 0, data); + break; + + case 0xe003: // write 1 + BurnYM2203Write(1, 1, data); + break; + } +} + +UINT8 __fastcall gunsmoke_cpu1_read(UINT16 address) +{ + if (address == 0xc800) return soundlatch; + + return 0; +} + + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Ram, 0, 0x4000); + + nGunsmokeBank = -1; + soundlatch = 0; + flipscreen = 0; + + sprite3bank = 0; + chon = bgon = objon = 0; + gunsmoke_scrollx[0] = gunsmoke_scrollx[1] = 0; + gunsmoke_scrolly = 0; + + ZetOpen(0); + ZetReset(); + gunsmoke_bankswitch(0); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + return 0; +} + +static INT32 gunsmoke_palette_init() +{ + INT32 i, ctabentry; + UINT32 tmp[0x100]; + + for (i = 0; i < 0x100; i++) + { + UINT8 r, g, b; + + r = Prom[i + 0x000] & 0x0f; + r |= r << 4; + g = Prom[i + 0x100] & 0x0f; + g |= g << 4; + b = Prom[i + 0x200] & 0x0f; + b |= b << 4; + + tmp[i] = (r << 16) | (g << 8) | b; + } + + for (i = 0; i < 0x100; i++) + { + ctabentry = Prom[0x300 + i] | 0x40; + Palette[0x000 + i] = tmp[ctabentry]; + + ctabentry = Prom[0x400 + i] | ((Prom[0x500 + i] & 0x03) << 4); + Palette[0x100 + i] = tmp[ctabentry]; + + ctabentry = Prom[0x600 + i] | ((Prom[0x700 + i] & 0x07) << 4) | 0x80; + Palette[0x200 + i] = tmp[ctabentry]; + } + + return 0; +} + +static INT32 gunsmoke_gfx_decode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (!tmp) return 1; + + static INT32 Planes[4] = { 0x100004, 0x100000, 4, 0 }; + + static INT32 CharXOffs[8] = { 11, 10, 9, 8, 3, 2, 1, 0 }; + static INT32 CharYOffs[8] = { 112, 96, 80, 64, 48, 32, 16, 0 }; + + static INT32 TileXOffs[32] = { 0, 1, 2, 3, 8, 9, 10, 11, + 512, 513, 514, 515, 520, 521, 522, 523, + 1024, 1025, 1026, 1027, 1032, 1033, 1034, 1035, + 1536, 1537, 1538, 1539, 1544, 1545, 1546, 1547 }; + + static INT32 TileYOffs[32] = { 0, 16, 32, 48, 64, 80, 96, 112, + 128, 144, 160, 176, 192, 208, 224, 240, + 256, 272, 288, 304, 320, 336, 352, 368, + 384, 400, 416, 432, 448, 464, 480, 496 }; + + static INT32 SpriXOffs[16] = { 0, 1, 2, 3, 8, 9, 10, 11, + 256, 257, 258, 259, 264, 265, 266, 267 }; + + memcpy (tmp, Gfx0, 0x04000); + GfxDecode(0x400, 2, 8, 8, Planes + 2, CharXOffs, CharYOffs, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x40000); + GfxDecode(0x200, 4, 32, 32, Planes + 0, TileXOffs, TileYOffs, 0x800, tmp, Gfx1); + + memcpy (tmp, Gfx2, 0x40000); + GfxDecode(0x800, 4, 16, 16, Planes + 0, SpriXOffs, TileYOffs, 0x200, tmp, Gfx2); + + BurnFree (tmp); + + { + memset (SprTrnsp, 1, 0x800); + + for (INT32 i = 0; i < 0x80000; i++) + if (Gfx2[i]) SprTrnsp[i >> 8] = 0; + } + + return 0; +} + +static INT32 gunsmokeSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3000000; +} + +static double gunsmokeGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom0 = Next; Next += 0x20000; + Rom1 = Next; Next += 0x08000; + Ram = Next; Next += 0x04000; + Gfx0 = Next; Next += 0x10000; + Gfx1 = Next; Next += 0x80000; + Gfx2 = Next; Next += 0x80000; + Gfx3 = Next; Next += 0x08000; + Prom = Next; Next += 0x00800; + + SprTrnsp = Next; Next += 0x00800; + + Palette = (UINT32*)Next; Next += 0x00300 * sizeof(UINT32); + DrvPal = (UINT32*)Next; Next += 0x00300 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Rom0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(Rom0 + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(Rom0 + 0x18000, 2, 1)) return 1; + + if (BurnLoadRom(Rom1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(Gfx0 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(Gfx3 + 0x00000, 21, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(Gfx1 + i * 0x8000, 5 + i, 1)) return 1; + if (BurnLoadRom(Gfx2 + i * 0x8000, 13 + i, 1)) return 1; + if (BurnLoadRom(Prom + i * 0x0100, 22 + i, 1)) return 1; + } + + gunsmoke_gfx_decode(); + gunsmoke_palette_init(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, Rom0 + 0x00000); + ZetMapArea(0x0000, 0x7fff, 2, Rom0 + 0x00000); + ZetMapArea(0x8000, 0xbfff, 0, Rom0 + 0x10000); + ZetMapArea(0x8000, 0xbfff, 2, Rom0 + 0x10000); + ZetMapArea(0xd000, 0xd7ff, 0, Ram + 0x00000); + ZetMapArea(0xd000, 0xd7ff, 1, Ram + 0x00000); + ZetMapArea(0xe000, 0xefff, 0, Ram + 0x01000); + ZetMapArea(0xe000, 0xefff, 1, Ram + 0x01000); + ZetMapArea(0xe000, 0xefff, 2, Ram + 0x01000); + ZetMapArea(0xf000, 0xffff, 0, Ram + 0x02000); + ZetMapArea(0xf000, 0xffff, 1, Ram + 0x02000); + ZetSetReadHandler(gunsmoke_cpu0_read); + ZetSetWriteHandler(gunsmoke_cpu0_write); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, Rom1 + 0x00000); + ZetMapArea(0x0000, 0x7fff, 2, Rom1 + 0x00000); + ZetMapArea(0xc000, 0xc7ff, 0, Ram + 0x03000); + ZetMapArea(0xc000, 0xc7ff, 1, Ram + 0x03000); + ZetMapArea(0xc000, 0xc7ff, 2, Ram + 0x03000); + ZetSetReadHandler(gunsmoke_cpu1_read); + ZetSetWriteHandler(gunsmoke_cpu1_write); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + BurnYM2203Init(2, 1500000, NULL, gunsmokeSynchroniseStream, gunsmokeGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(3000000); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + BurnYM2203Exit(); + + BurnFree (Mem); + + Mem = MemEnd = Rom0 = Rom1 = Ram = NULL; + Gfx0 = Gfx1 = Gfx2 = Gfx3 = Prom = NULL; + SprTrnsp = NULL; + Palette = DrvPal = NULL; + + soundlatch = flipscreen = nGunsmokeBank; + + sprite3bank = chon = bgon = objon = 0; + gunsmoke_scrollx[0] = gunsmoke_scrollx[1] = 0; + gunsmoke_scrolly = 0; + + return 0; +} + +static void draw_bg_layer() +{ + UINT16 scroll = gunsmoke_scrollx[0] + (gunsmoke_scrollx[1] << 8); + + UINT8 *tilerom = Gfx3 + ((scroll >> 1) & ~0x0f); + + for (INT32 offs = 0; offs < 0x50; offs++) + { + INT32 attr = tilerom[1]; + INT32 code = tilerom[0] + ((attr & 1) << 8); + INT32 color = (attr & 0x3c) >> 2; + INT32 flipy = attr & 0x80; + INT32 flipx = attr & 0x40; + + INT32 sy = (offs & 7) << 5; + INT32 sx = (offs >> 3) << 5; + + sy -= gunsmoke_scrolly; + sx -= (scroll & 0x1f); + + if (flipscreen) { + flipy ^= 0x80; + flipx ^= 0x40; + + sy = 224 - sy; + sx = 224 - sx; + } + + sy -= 16; + + if (flipy) { + if (flipx) { + Render32x32Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, Gfx1); + } else { + Render32x32Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, Gfx1); + } + } else { + if (flipx) { + Render32x32Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, Gfx1); + } else { + Render32x32Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, Gfx1); + } + } + + tilerom += 2; + } +} + +static void draw_fg_layer() +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs << 3) & 0xf8; + INT32 sy = (offs >> 2) & 0xf8; + + INT32 attr = Ram[0x0400 + offs]; + INT32 code = Ram[0x0000 + offs] + ((attr & 0xe0) << 2); + INT32 color = attr & 0x1f; + + if (code == 0x0024) continue; + + UINT8 *src = Gfx0 + (code << 6); + color <<= 2; + + if (flipscreen) { + sy = 240 - sy; + sx = 240 - sx; + + sy -= 8; + + for (INT32 y = sy + 7; y >= sy; y--) + { + for (INT32 x = sx + 7; x >= sx; x--, src++) + { + if (y < 0 || x < 0 || y > 223 || x > 255) continue; + if (!Palette[color|*src]) continue; + + pTransDraw[(y << 8) | x] = color | *src; + } + } + } else { + sy -= 16; + + for (INT32 y = sy; y < sy + 8; y++) + { + for (INT32 x = sx; x < sx + 8; x++, src++) + { + if (y < 0 || x < 0 || y > 223 || x > 255) continue; + if (!Palette[color|*src]) continue; + + pTransDraw[(y << 8) | x] = color | *src; + } + } + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x1000 - 32; offs >= 0; offs -= 32) + { + INT32 attr = Ram[0x2001 + offs]; + INT32 bank = (attr & 0xc0) >> 6; + INT32 code = Ram[0x2000 + offs]; + INT32 color = attr & 0x0f; + INT32 flipx = 0; + INT32 flipy = attr & 0x10; + INT32 sx = Ram[0x2003 + offs] - ((attr & 0x20) << 3); + INT32 sy = Ram[0x2002 + offs]; + + if (sy == 0 || sy > 0xef) continue; + + if (bank == 3) bank += sprite3bank; + code += 256 * bank; + + if (SprTrnsp[code]) continue; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, Gfx2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x200, Gfx2); + } + } + } +} + +static INT32 DrvDraw() +{ + // Recalculate palette + if (DrvCalcPal) { + for (INT32 i = 0; i < 0x300; i++) { + UINT32 col = Palette[i]; + DrvPal[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + if (!bgon) memset (pTransDraw, 0, 224 * 256 * 2); + + if (bgon) draw_bg_layer(); + if (objon) draw_sprites(); + if (chon) draw_fg_layer(); + + BurnTransferCopy(DrvPal); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + INT32 nInterleave = 25; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + INT32 nCyclesDone[2], nCyclesTotal[2]; + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #0 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 20) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 21) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + if (i == 5 || i == 10 || i == 15 || i == 20) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 6 || i == 11 || i == 16 || i == 21) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + ZetClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(1); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Ram; + ba.nLen = 0x4000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + BurnYM2203Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen); + SCAN_VAR(nGunsmokeBank); + SCAN_VAR(sprite3bank); + SCAN_VAR(chon); + SCAN_VAR(bgon); + SCAN_VAR(objon); + SCAN_VAR(gunsmoke_scrollx[0]); + SCAN_VAR(gunsmoke_scrollx[1]); + SCAN_VAR(gunsmoke_scrolly); + } + + return 0; +} + + +// Gun. Smoke (World) + +static struct BurnRomInfo gunsmokeRomDesc[] = { + { "09n_gs03.bin", 0x8000, 0x40a06cef, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "10n_gs04.bin", 0x8000, 0x8d4b423f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "12n_gs05.bin", 0x8000, 0x2b5667fb, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "14h_gs02.bin", 0x8000, 0xcd7a2c38, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "11f_gs01.bin", 0x4000, 0xb61ece9b, 3 | BRF_GRA }, // 4 Character Tiles + + { "06c_gs13.bin", 0x8000, 0xf6769fc5, 4 | BRF_GRA }, // 5 32x32 Tiles + { "05c_gs12.bin", 0x8000, 0xd997b78c, 4 | BRF_GRA }, // 6 + { "04c_gs11.bin", 0x8000, 0x125ba58e, 4 | BRF_GRA }, // 7 + { "02c_gs10.bin", 0x8000, 0xf469c13c, 4 | BRF_GRA }, // 8 + { "06a_gs09.bin", 0x8000, 0x539f182d, 4 | BRF_GRA }, // 9 + { "05a_gs08.bin", 0x8000, 0xe87e526d, 4 | BRF_GRA }, // 10 + { "04a_gs07.bin", 0x8000, 0x4382c0d2, 4 | BRF_GRA }, // 11 + { "02a_gs06.bin", 0x8000, 0x4cafe7a6, 4 | BRF_GRA }, // 12 + + { "06n_gs22.bin", 0x8000, 0xdc9c508c, 5 | BRF_GRA }, // 13 Sprites + { "04n_gs21.bin", 0x8000, 0x68883749, 5 | BRF_GRA }, // 14 + { "03n_gs20.bin", 0x8000, 0x0be932ed, 5 | BRF_GRA }, // 15 + { "01n_gs19.bin", 0x8000, 0x63072f93, 5 | BRF_GRA }, // 16 + { "06l_gs18.bin", 0x8000, 0xf69a3c7c, 5 | BRF_GRA }, // 17 + { "04l_gs17.bin", 0x8000, 0x4e98562a, 5 | BRF_GRA }, // 18 + { "03l_gs16.bin", 0x8000, 0x0d99c3b3, 5 | BRF_GRA }, // 19 + { "01l_gs15.bin", 0x8000, 0x7f14270e, 5 | BRF_GRA }, // 20 + + { "11c_gs14.bin", 0x8000, 0x0af4f7eb, 6 | BRF_GRA }, // 21 Background Tilemaps + + { "03b_g-01.bin", 0x0100, 0x02f55589, 7 | BRF_GRA }, // 22 Color Proms + { "04b_g-02.bin", 0x0100, 0xe1e36dd9, 7 | BRF_GRA }, // 23 + { "05b_g-03.bin", 0x0100, 0x989399c0, 7 | BRF_GRA }, // 24 + { "09d_g-04.bin", 0x0100, 0x906612b5, 7 | BRF_GRA }, // 25 + { "14a_g-06.bin", 0x0100, 0x4a9da18b, 7 | BRF_GRA }, // 26 + { "15a_g-07.bin", 0x0100, 0xcb9394fc, 7 | BRF_GRA }, // 27 + { "09f_g-09.bin", 0x0100, 0x3cee181e, 7 | BRF_GRA }, // 28 + { "08f_g-08.bin", 0x0100, 0xef91cdd2, 7 | BRF_GRA }, // 29 + + { "02j_g-10.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 30 Video Timing + { "01f_g-05.bin", 0x0100, 0x25c90c2a, 0 | BRF_OPT }, // 31 Priority +}; + +STD_ROM_PICK(gunsmoke) +STD_ROM_FN(gunsmoke) + +struct BurnDriver BurnDrvGunsmoke = { + "gunsmoke", NULL, NULL, NULL, "1985", + "Gun. Smoke (World)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, gunsmokeRomInfo, gunsmokeRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x300, + 224, 256, 3, 4 +}; + + +// Gun. Smoke (Japan) + +static struct BurnRomInfo gunsmokjRomDesc[] = { + { "gs03_9n.rom", 0x8000, 0xb56b5df6, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "10n_gs04.bin", 0x8000, 0x8d4b423f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "12n_gs05.bin", 0x8000, 0x2b5667fb, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "14h_gs02.bin", 0x8000, 0xcd7a2c38, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "11f_gs01.bin", 0x4000, 0xb61ece9b, 3 | BRF_GRA }, // 4 Character Tiles + + { "06c_gs13.bin", 0x8000, 0xf6769fc5, 4 | BRF_GRA }, // 5 32x32 Tiles + { "05c_gs12.bin", 0x8000, 0xd997b78c, 4 | BRF_GRA }, // 6 + { "04c_gs11.bin", 0x8000, 0x125ba58e, 4 | BRF_GRA }, // 7 + { "02c_gs10.bin", 0x8000, 0xf469c13c, 4 | BRF_GRA }, // 8 + { "06a_gs09.bin", 0x8000, 0x539f182d, 4 | BRF_GRA }, // 9 + { "05a_gs08.bin", 0x8000, 0xe87e526d, 4 | BRF_GRA }, // 10 + { "04a_gs07.bin", 0x8000, 0x4382c0d2, 4 | BRF_GRA }, // 11 + { "02a_gs06.bin", 0x8000, 0x4cafe7a6, 4 | BRF_GRA }, // 12 + + { "06n_gs22.bin", 0x8000, 0xdc9c508c, 5 | BRF_GRA }, // 13 Sprites + { "04n_gs21.bin", 0x8000, 0x68883749, 5 | BRF_GRA }, // 14 + { "03n_gs20.bin", 0x8000, 0x0be932ed, 5 | BRF_GRA }, // 15 + { "01n_gs19.bin", 0x8000, 0x63072f93, 5 | BRF_GRA }, // 16 + { "06l_gs18.bin", 0x8000, 0xf69a3c7c, 5 | BRF_GRA }, // 17 + { "04l_gs17.bin", 0x8000, 0x4e98562a, 5 | BRF_GRA }, // 18 + { "03l_gs16.bin", 0x8000, 0x0d99c3b3, 5 | BRF_GRA }, // 19 + { "01l_gs15.bin", 0x8000, 0x7f14270e, 5 | BRF_GRA }, // 20 + + { "11c_gs14.bin", 0x8000, 0x0af4f7eb, 6 | BRF_GRA }, // 21 Background Tilemaps + + { "03b_g-01.bin", 0x0100, 0x02f55589, 7 | BRF_GRA }, // 22 Color Proms + { "04b_g-02.bin", 0x0100, 0xe1e36dd9, 7 | BRF_GRA }, // 23 + { "05b_g-03.bin", 0x0100, 0x989399c0, 7 | BRF_GRA }, // 24 + { "09d_g-04.bin", 0x0100, 0x906612b5, 7 | BRF_GRA }, // 25 + { "14a_g-06.bin", 0x0100, 0x4a9da18b, 7 | BRF_GRA }, // 26 + { "15a_g-07.bin", 0x0100, 0xcb9394fc, 7 | BRF_GRA }, // 27 + { "09f_g-09.bin", 0x0100, 0x3cee181e, 7 | BRF_GRA }, // 28 + { "08f_g-08.bin", 0x0100, 0xef91cdd2, 7 | BRF_GRA }, // 29 + + { "02j_g-10.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 30 Video Timing + { "01f_g-05.bin", 0x0100, 0x25c90c2a, 0 | BRF_OPT }, // 31 Priority +}; + +STD_ROM_PICK(gunsmokj) +STD_ROM_FN(gunsmokj) + +struct BurnDriver BurnDrvGunsmokj = { + "gunsmokej", "gunsmoke", NULL, NULL, "1985", + "Gun. Smoke (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, gunsmokjRomInfo, gunsmokjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x300, + 224, 256, 3, 4 +}; + + +// Gun. Smoke (US set 1) + +static struct BurnRomInfo gunsmokuRomDesc[] = { + { "9n_gs03.bin", 0x8000, 0x592f211b, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "10n_gs04.bin", 0x8000, 0x8d4b423f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "12n_gs05.bin", 0x8000, 0x2b5667fb, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "14h_gs02.bin", 0x8000, 0xcd7a2c38, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "11f_gs01.bin", 0x4000, 0xb61ece9b, 3 | BRF_GRA }, // 4 Character Tiles + + { "06c_gs13.bin", 0x8000, 0xf6769fc5, 4 | BRF_GRA }, // 5 32x32 Tiles + { "05c_gs12.bin", 0x8000, 0xd997b78c, 4 | BRF_GRA }, // 6 + { "04c_gs11.bin", 0x8000, 0x125ba58e, 4 | BRF_GRA }, // 7 + { "02c_gs10.bin", 0x8000, 0xf469c13c, 4 | BRF_GRA }, // 8 + { "06a_gs09.bin", 0x8000, 0x539f182d, 4 | BRF_GRA }, // 9 + { "05a_gs08.bin", 0x8000, 0xe87e526d, 4 | BRF_GRA }, // 10 + { "04a_gs07.bin", 0x8000, 0x4382c0d2, 4 | BRF_GRA }, // 11 + { "02a_gs06.bin", 0x8000, 0x4cafe7a6, 4 | BRF_GRA }, // 12 + + { "06n_gs22.bin", 0x8000, 0xdc9c508c, 5 | BRF_GRA }, // 13 Sprites + { "04n_gs21.bin", 0x8000, 0x68883749, 5 | BRF_GRA }, // 14 + { "03n_gs20.bin", 0x8000, 0x0be932ed, 5 | BRF_GRA }, // 15 + { "01n_gs19.bin", 0x8000, 0x63072f93, 5 | BRF_GRA }, // 16 + { "06l_gs18.bin", 0x8000, 0xf69a3c7c, 5 | BRF_GRA }, // 17 + { "04l_gs17.bin", 0x8000, 0x4e98562a, 5 | BRF_GRA }, // 18 + { "03l_gs16.bin", 0x8000, 0x0d99c3b3, 5 | BRF_GRA }, // 19 + { "01l_gs15.bin", 0x8000, 0x7f14270e, 5 | BRF_GRA }, // 20 + + { "11c_gs14.bin", 0x8000, 0x0af4f7eb, 6 | BRF_GRA }, // 21 Background Tilemaps + + { "03b_g-01.bin", 0x0100, 0x02f55589, 7 | BRF_GRA }, // 22 Color Proms + { "04b_g-02.bin", 0x0100, 0xe1e36dd9, 7 | BRF_GRA }, // 23 + { "05b_g-03.bin", 0x0100, 0x989399c0, 7 | BRF_GRA }, // 24 + { "09d_g-04.bin", 0x0100, 0x906612b5, 7 | BRF_GRA }, // 25 + { "14a_g-06.bin", 0x0100, 0x4a9da18b, 7 | BRF_GRA }, // 26 + { "15a_g-07.bin", 0x0100, 0xcb9394fc, 7 | BRF_GRA }, // 27 + { "09f_g-09.bin", 0x0100, 0x3cee181e, 7 | BRF_GRA }, // 28 + { "08f_g-08.bin", 0x0100, 0xef91cdd2, 7 | BRF_GRA }, // 29 + + { "02j_g-10.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 30 Video Timing + { "01f_g-05.bin", 0x0100, 0x25c90c2a, 0 | BRF_OPT }, // 31 Priority +}; + +STD_ROM_PICK(gunsmoku) +STD_ROM_FN(gunsmoku) + +struct BurnDriver BurnDrvGunsmoku = { + "gunsmokeu", "gunsmoke", NULL, NULL, "1985", + "Gun. Smoke (US set 1)\0", NULL, "Capcom (Romstar License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, gunsmokuRomInfo, gunsmokuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x300, + 224, 256, 3, 4 +}; + + +// Gun. Smoke (US set 2) + +static struct BurnRomInfo gunsmokaRomDesc[] = { + { "gs03.9n", 0x8000, 0x51dc3f76, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "gs04.10n", 0x8000, 0x5ecf31b8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gs05.12n", 0x8000, 0x1c9aca13, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "14h_gs02.bin", 0x8000, 0xcd7a2c38, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "11f_gs01.bin", 0x4000, 0xb61ece9b, 3 | BRF_GRA }, // 4 Character Tiles + + { "06c_gs13.bin", 0x8000, 0xf6769fc5, 4 | BRF_GRA }, // 5 32x32 Tiles + { "05c_gs12.bin", 0x8000, 0xd997b78c, 4 | BRF_GRA }, // 6 + { "04c_gs11.bin", 0x8000, 0x125ba58e, 4 | BRF_GRA }, // 7 + { "02c_gs10.bin", 0x8000, 0xf469c13c, 4 | BRF_GRA }, // 8 + { "06a_gs09.bin", 0x8000, 0x539f182d, 4 | BRF_GRA }, // 9 + { "05a_gs08.bin", 0x8000, 0xe87e526d, 4 | BRF_GRA }, // 10 + { "04a_gs07.bin", 0x8000, 0x4382c0d2, 4 | BRF_GRA }, // 11 + { "02a_gs06.bin", 0x8000, 0x4cafe7a6, 4 | BRF_GRA }, // 12 + + { "06n_gs22.bin", 0x8000, 0xdc9c508c, 5 | BRF_GRA }, // 13 Sprites + { "04n_gs21.bin", 0x8000, 0x68883749, 5 | BRF_GRA }, // 14 + { "03n_gs20.bin", 0x8000, 0x0be932ed, 5 | BRF_GRA }, // 15 + { "01n_gs19.bin", 0x8000, 0x63072f93, 5 | BRF_GRA }, // 16 + { "06l_gs18.bin", 0x8000, 0xf69a3c7c, 5 | BRF_GRA }, // 17 + { "04l_gs17.bin", 0x8000, 0x4e98562a, 5 | BRF_GRA }, // 18 + { "03l_gs16.bin", 0x8000, 0x0d99c3b3, 5 | BRF_GRA }, // 19 + { "01l_gs15.bin", 0x8000, 0x7f14270e, 5 | BRF_GRA }, // 20 + + { "11c_gs14.bin", 0x8000, 0x0af4f7eb, 6 | BRF_GRA }, // 21 Background Tilemaps + + { "03b_g-01.bin", 0x0100, 0x02f55589, 7 | BRF_GRA }, // 22 Color Proms + { "04b_g-02.bin", 0x0100, 0xe1e36dd9, 7 | BRF_GRA }, // 23 + { "05b_g-03.bin", 0x0100, 0x989399c0, 7 | BRF_GRA }, // 24 + { "09d_g-04.bin", 0x0100, 0x906612b5, 7 | BRF_GRA }, // 25 + { "14a_g-06.bin", 0x0100, 0x4a9da18b, 7 | BRF_GRA }, // 26 + { "15a_g-07.bin", 0x0100, 0xcb9394fc, 7 | BRF_GRA }, // 27 + { "09f_g-09.bin", 0x0100, 0x3cee181e, 7 | BRF_GRA }, // 28 + { "08f_g-08.bin", 0x0100, 0xef91cdd2, 7 | BRF_GRA }, // 29 + + { "02j_g-10.bin", 0x0100, 0x0eaf5158, 0 | BRF_OPT }, // 30 Video Timing + { "01f_g-05.bin", 0x0100, 0x25c90c2a, 0 | BRF_OPT }, // 31 Priority +}; + +STD_ROM_PICK(gunsmoka) +STD_ROM_FN(gunsmoka) + +struct BurnDriver BurnDrvGunsmoka = { + "gunsmokeua", "gunsmoke", NULL, NULL, "1986", + "Gun. Smoke (US set 2)\0", NULL, "Capcom (Romstar License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, gunsmokaRomInfo, gunsmokaRomName, NULL, NULL, DrvInputInfo, gunsmokaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x300, + 224, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_gyruss.cpp b/src/burn/drivers/misc_pre90s/d_gyruss.cpp new file mode 100644 index 00000000..79718b89 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_gyruss.cpp @@ -0,0 +1,1081 @@ +// FB Alpha Gyruss driver module +// Based on MAME driver by Mirko Buffoni, Michael Cuddy, and Nicola Salmoria + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "i8039.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvM6809DecROM; +static UINT8 *DrvI8039ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvColPROM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvShareRAM; +static UINT8 *DrvM6809RAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static INT16 *pAY8910Buffer[15]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *flipscreen; +static UINT8 *interrupt_enable0; +static UINT8 *interrupt_enable1; + +static INT32 scanline; +static UINT16 *pTemp; + +static struct BurnInputInfo GyrussInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Gyruss) + +static struct BurnDIPInfo GyrussDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0x3b, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x10, 0x01, 0x0f, 0x02, "4 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x05, "3 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x08, "2 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x04, "3 Coins 2 Credits " }, + {0x10, 0x01, 0x0f, 0x01, "4 Coins 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits " }, + {0x10, 0x01, 0x0f, 0x03, "3 Coins 4 Credits " }, + {0x10, 0x01, 0x0f, 0x07, "2 Coins 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits " }, + {0x10, 0x01, 0x0f, 0x06, "2 Coins 5 Credits " }, + {0x10, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits " }, + {0x10, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits " }, + {0x10, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits " }, + {0x10, 0x01, 0x0f, 0x09, "1 Coin 7 Credits " }, + {0x10, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x10, 0x01, 0xf0, 0x20, "4 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x50, "3 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x80, "2 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x40, "3 Coins 2 Credits " }, + {0x10, 0x01, 0xf0, 0x10, "4 Coins 3 Credits " }, + {0x10, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits " }, + {0x10, 0x01, 0xf0, 0x30, "3 Coins 4 Credits " }, + {0x10, 0x01, 0xf0, 0x70, "2 Coins 3 Credits " }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits " }, + {0x10, 0x01, 0xf0, 0x60, "2 Coins 5 Credits " }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits " }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits " }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits " }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits " }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 7 Credits " }, + {0x10, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x01, "5" }, + {0x11, 0x01, 0x03, 0x00, "255 (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x04, 0x00, "Upright" }, + {0x11, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x11, 0x01, 0x08, 0x08, "30k 90k 60k+" }, + {0x11, 0x01, 0x08, 0x00, "40k 110k 70k+" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x11, 0x01, 0x70, 0x70, "1 (Easiest)" }, + {0x11, 0x01, 0x70, 0x60, "2" }, + {0x11, 0x01, 0x70, 0x50, "3" }, + {0x11, 0x01, 0x70, 0x40, "4" }, + {0x11, 0x01, 0x70, 0x30, "5 (Average)" }, + {0x11, 0x01, 0x70, 0x20, "6" }, + {0x11, 0x01, 0x70, 0x10, "7" }, + {0x11, 0x01, 0x70, 0x00, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Music" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFO(Gyruss) + +static struct BurnDIPInfo GyrussceDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0x3b, NULL }, + {0x12, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x10, 0x01, 0x0f, 0x02, "4 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x05, "3 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x08, "2 Coins 1 Credits " }, + {0x10, 0x01, 0x0f, 0x04, "3 Coins 2 Credits " }, + {0x10, 0x01, 0x0f, 0x01, "4 Coins 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits " }, + {0x10, 0x01, 0x0f, 0x03, "3 Coins 4 Credits " }, + {0x10, 0x01, 0x0f, 0x07, "2 Coins 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits " }, + {0x10, 0x01, 0x0f, 0x06, "2 Coins 5 Credits " }, + {0x10, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits " }, + {0x10, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits " }, + {0x10, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits " }, + {0x10, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits " }, + {0x10, 0x01, 0x0f, 0x09, "1 Coin 7 Credits " }, + {0x10, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x10, 0x01, 0xf0, 0x20, "4 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x50, "3 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x80, "2 Coins 1 Credits " }, + {0x10, 0x01, 0xf0, 0x40, "3 Coins 2 Credits " }, + {0x10, 0x01, 0xf0, 0x10, "4 Coins 3 Credits " }, + {0x10, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits " }, + {0x10, 0x01, 0xf0, 0x30, "3 Coins 4 Credits " }, + {0x10, 0x01, 0xf0, 0x70, "2 Coins 3 Credits " }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits " }, + {0x10, 0x01, 0xf0, 0x60, "2 Coins 5 Credits " }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits " }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits " }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits " }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits " }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 7 Credits " }, + {0x10, 0x01, 0xf0, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x01, "5" }, + {0x11, 0x01, 0x03, 0x00, "255 (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x04, 0x00, "Upright" }, + {0x11, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 0, "Bonus Life" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x11, 0x01, 0x08, 0x08, "50k 120k 70k+" }, + {0x11, 0x01, 0x08, 0x00, "60k 140k 80k+" }, + + {0 , 0xfe, 0 , 8, "Difficulty" }, + {0x11, 0x01, 0x70, 0x70, "1 (Easiest)" }, + {0x11, 0x01, 0x70, 0x60, "2" }, + {0x11, 0x01, 0x70, 0x50, "3" }, + {0x11, 0x01, 0x70, 0x40, "4" }, + {0x11, 0x01, 0x70, 0x30, "5 (Average)" }, + {0x11, 0x01, 0x70, 0x20, "6" }, + {0x11, 0x01, 0x70, 0x10, "7" }, + {0x11, 0x01, 0x70, 0x00, "8 (Hardest)" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Music" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFO(Gyrussce) + +void __fastcall gyruss_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: // watchdog + return; + + case 0xc080: + ZetClose(); + ZetOpen(1); + ZetRaiseIrq(0xff); + ZetClose(); + ZetOpen(0); + return; + + case 0xc100: + *soundlatch = data; + return; + + case 0xc180: + *interrupt_enable0 = data; + return; + + case 0xc185: + *flipscreen = data & 1; + return; + } +} + +UINT8 __fastcall gyruss_main_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + return DrvDips[1]; + + case 0xc080: + return DrvInputs[0]; + + case 0xc0a0: + return DrvInputs[1]; + + case 0xc0c0: + return DrvInputs[2]; + + case 0xc0e0: + return DrvDips[0]; + + case 0xc100: + return DrvDips[2]; + } + + return 0; +} + +void gyruss_sub_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x2000: + *interrupt_enable1 = data; + return; + } +} + +UINT8 gyruss_sub_read(UINT16 address) +{ + switch (address) + { + case 0x0000: + return (scanline & 0x7f); + } + + return 0; +} + +UINT8 __fastcall gyruss_sound0_read(UINT16 address) +{ + switch (address) + { + case 0x8000: + return *soundlatch; + } + + return 0; +} + +UINT8 __fastcall gyruss_sound0_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x01: + return AY8910Read(0); + + case 0x05: + return AY8910Read(1); + + case 0x09: + return AY8910Read(2); + + case 0x0d: + return AY8910Read(3); + + case 0x11: + return AY8910Read(4); + } + + return 0; +} + +void __fastcall gyruss_sound0_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + AY8910Write(0, 0, data); + return; + + case 0x02: + AY8910Write(0, 1, data); + return; + + case 0x04: + AY8910Write(1, 0, data); + return; + + case 0x06: + AY8910Write(1, 1, data); + return; + + case 0x08: + AY8910Write(2, 0, data); + return; + + case 0x0a: + AY8910Write(2, 1, data); + return; + + case 0x0c: + AY8910Write(3, 0, data); + return; + + case 0x0e: + AY8910Write(3, 1, data); + return; + + case 0x10: + AY8910Write(4, 0, data); + return; + + case 0x12: + AY8910Write(4, 1, data); + return; + + case 0x14: // clear i8039 irq + return; + + case 0x18: + *soundlatch2 = data; + return; + } +} + +UINT8 AY8910_3_portA(UINT32) +{ + static const INT32 gyruss_timer[10] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0a, 0x0b, 0x0a, 0x0d + }; + + return gyruss_timer[((ZetTotalCycles() * 60) >> 10) % 10]; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvM6809ROM = Next; Next += 0x010000; + DrvM6809DecROM = Next; Next += 0x010000; + + DrvI8039ROM = Next; Next += 0x001000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + DrvGfxROM2 = Next; Next += 0x008000; + + DrvColPROM = Next; Next += 0x000300; + + Palette = (UINT32*)Next; Next += 0x0140 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0140 * sizeof(UINT32); + + pAY8910Buffer[ 0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 3] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 4] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 5] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 6] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 7] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 8] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[ 9] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[10] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[11] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[12] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[13] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[14] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + pTemp = (UINT16*)Next; Next += 0x10000 * 2; + + AllRam = Next; + + flipscreen = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + + interrupt_enable0 = Next; Next += 0x000001; + interrupt_enable1 = Next; Next += 0x000001; + + DrvShareRAM = Next; Next += 0x000800; + DrvColRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + DrvZ80RAM0 = Next; Next += 0x001000; + DrvZ80RAM1 = Next; Next += 0x000400; + + DrvM6809RAM = Next; Next += 0x000800; + + DrvSprRAM = DrvM6809RAM + 0x000040; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x20004, 0x20000, 4, 0 }; + INT32 XOffs[8] = { 0, 1, 2, 3, 64, 65, 66, 67 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 32*8, 33*8, 34*8, 35*8, 36*8, 37*8, 38*8, 39*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x8000); + + GfxDecode(0x0200, 4, 8, 16, Plane , XOffs, YOffs, 0x200, tmp , DrvGfxROM0); + GfxDecode(0x0200, 4, 8, 16, Plane , XOffs, YOffs, 0x200, tmp + 0x10, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x2000); + + GfxDecode(0x0200, 2, 8, 8, Plane + 2, XOffs, YOffs, 0x080, tmp , DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvPaletteInit() +{ + UINT8 *color_prom = DrvColPROM; + UINT32 *tmp = (UINT32*)BurnMalloc(32 * sizeof(UINT32)); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0, bit1, bit2; + UINT8 r, g, b; + + bit0 = (color_prom[i] >> 0) & 0x01; + bit1 = (color_prom[i] >> 1) & 0x01; + bit2 = (color_prom[i] >> 2) & 0x01; + r = (INT32)(double((bit0 * 33 + bit1 * 70 + bit2 * 151)+0.5)); + + bit0 = (color_prom[i] >> 3) & 0x01; + bit1 = (color_prom[i] >> 4) & 0x01; + bit2 = (color_prom[i] >> 5) & 0x01; + g = (INT32)(double((bit0 * 33 + bit1 * 70 + bit2 * 151)+0.5)); + + bit0 = (color_prom[i] >> 6) & 0x01; + bit1 = (color_prom[i] >> 7) & 0x01; + b = (INT32)(double((bit0 * 78 + bit1 * 151)+0.5)); + + tmp[i] = (r << 16) | (g << 8) | b; + } + + color_prom += 32; + + for (INT32 i = 0; i < 0x140; i++) { + UINT8 ctabentry = color_prom[i] & 0x0f; + Palette[i] = tmp[ctabentry | ((i >> 4) & 0x10)]; + } + + BurnFree (tmp); + return 0; +} + +static void gyrussDecode() +{ + for (INT32 i = 0xe000; i < 0x10000; i++) + { + UINT8 xor1 = 0; + + if ( i & 0x02) xor1 |= 0x80; + else xor1 |= 0x20; + if ( i & 0x08) xor1 |= 0x08; + else xor1 |= 0x02; + + DrvM6809DecROM[i] = DrvM6809ROM[i] ^ xor1; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + AY8910Reset(2); + AY8910Reset(3); + AY8910Reset(4); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x4000, 2, 1)) return 1; + + if (BurnLoadRom(DrvM6809ROM + 0xe000, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x2000, 5, 1)) return 1; + + if (BurnLoadRom(DrvI8039ROM + 0x0000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x2000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x4000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x6000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x0000, 11, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x0000, 12, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x0020, 13, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x0120, 14, 1)) return 1; + + gyrussDecode(); + DrvGfxDecode(); + DrvPaletteInit(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0x83ff, 0, DrvColRAM); + ZetMapArea(0x8000, 0x83ff, 1, DrvColRAM); + ZetMapArea(0x8000, 0x83ff, 2, DrvColRAM); + ZetMapArea(0x8400, 0x87ff, 0, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 1, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 2, DrvVidRAM); + ZetMapArea(0x9000, 0x9fff, 0, DrvZ80RAM0); + ZetMapArea(0x9000, 0x9fff, 1, DrvZ80RAM0); + ZetMapArea(0x9000, 0x9fff, 2, DrvZ80RAM0); + ZetMapArea(0xa000, 0xa7ff, 0, DrvShareRAM); + ZetMapArea(0xa000, 0xa7ff, 1, DrvShareRAM); + ZetMapArea(0xa000, 0xa7ff, 2, DrvShareRAM); + ZetSetReadHandler(gyruss_main_read); + ZetSetWriteHandler(gyruss_main_write); + ZetMemEnd(); + ZetClose(); + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809RAM, 0x4000, 0x47ff, M6809_RAM); + M6809MapMemory(DrvShareRAM, 0x6000, 0x67ff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0xe000, 0xe000, 0xffff, M6809_READ); + M6809MapMemory(DrvM6809DecROM + 0xe000, 0xe000, 0xffff, M6809_FETCH); + M6809SetReadByteHandler(gyruss_sub_read); + M6809SetWriteByteHandler(gyruss_sub_write); + M6809Close(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM1); + ZetMapArea(0x6000, 0x63ff, 0, DrvZ80RAM1); + ZetMapArea(0x6000, 0x63ff, 1, DrvZ80RAM1); + ZetMapArea(0x6000, 0x63ff, 2, DrvZ80RAM1); + ZetSetReadHandler(gyruss_sound0_read); + ZetSetOutHandler(gyruss_sound0_out); + ZetSetInHandler(gyruss_sound0_in); + ZetMemEnd(); + ZetClose(); + + // don't bother with i8039 right now, descrete sounds not emulated + + AY8910Init(0, 1789773, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1789773, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(2, 1789773, nBurnSoundRate, AY8910_3_portA, NULL, NULL, NULL); + AY8910Init(3, 1789773, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(4, 1789773, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + ZetExit(); + M6809Exit(); + + AY8910Exit(0); + AY8910Exit(1); + AY8910Exit(2); + AY8910Exit(3); + AY8910Exit(4); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background(INT32 transp) +{ + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 attr = DrvColRAM[offs]; + INT32 code = ((attr & 0x20) << 3) | DrvVidRAM[offs]; + INT32 color = attr & 0x0f; + INT32 flipx = (attr >> 6) & 1; + INT32 flipy = attr >> 7; + + INT32 group = ((~DrvColRAM[offs] >> 4) & 1); + if (transp && group == 0) continue; + + if (*flipscreen) { + flipx ^= 1; + flipy ^= 1; + sx ^= 0xf8; + sy ^= 0xf8; + } + + sy -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 2, transp, 0x100, DrvGfxROM2); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 2, transp, 0x100, DrvGfxROM2); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 2, transp, 0x100, DrvGfxROM2); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, transp, 0x100, DrvGfxROM2); + } + } + } +} + +static void draw_8x16_tile_line(INT32 sx, INT32 sy, INT32 color, UINT8 *gfx_base, INT32 code, INT32 flipx, INT32 flipy, INT32 line) +{ + line -= 16; + + if (line < 0 || line >= nScreenHeight) return; + + INT32 y = line - sy; // right? + if (y < 0 || y >= 16) return; + + if (flipy) flipy = 0x78; + + UINT8 *src = gfx_base + (code * 0x80) + ((y << 3) ^ flipy); + color <<= 4; + + if (flipx) flipx = 0x07; + + for (INT32 x = 0; x < 8; x++, sx++) + { + INT32 pxl = src[x ^ flipx]; + + if (sx < 0 || sx >= nScreenWidth || !pxl) continue; + + pTransDraw[(line * nScreenWidth) + sx] = pxl | color; + } +} + +static void draw_sprites(INT32 line) +{ + for (INT32 offs = 0xbc; offs >= 0; offs -= 4) + { + INT32 sx = DrvSprRAM[offs]; + INT32 sy = (241 - DrvSprRAM[offs + 3]); + + if (sy <= (line-16) || sy >= (line+16)) continue; + + INT32 bank = DrvSprRAM[offs + 1] & 0x01; + INT32 code = ((DrvSprRAM[offs + 2] & 0x20) << 2) | (DrvSprRAM[offs + 1] >> 1); + INT32 color = DrvSprRAM[offs + 2] & 0x0f; + INT32 flipx = ~DrvSprRAM[offs + 2] & 0x40; + INT32 flipy = DrvSprRAM[offs + 2] & 0x80; + + UINT8 *gfx_base = bank ? DrvGfxROM1 : DrvGfxROM0; + + draw_8x16_tile_line(sx, sy-16, color, gfx_base, code, flipx, flipy, line); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x140; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + BurnTransferClear(); + + draw_background(0); + +// draw_background(0x0f); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 5; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + ZetNewFrame(); + + INT32 nCyclesSegment; + INT32 nInterleave = 256; + INT32 nCyclesTotal[4] = { 3072000 / 60, 2000000 / 60, 3579545 / 60, 8000000 / 60 }; + INT32 nCyclesDone[4] = { 0, 0, 0, 0 }; + + DrvDraw(); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nNext; + scanline = i; + + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesDone[0] += ZetRun(nCyclesSegment); + if (i == (nInterleave - 1) && *interrupt_enable0) { + ZetNmi(); + } + + M6809Open(0); + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesDone[1] += M6809Run(nCyclesSegment); + if (i == (nInterleave - 1) && *interrupt_enable1) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + M6809Close(); + ZetClose(); + + ZetOpen(1); + nNext = (i + 1) * nCyclesTotal[2] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[2]; + nCyclesDone[2] += ZetRun(nCyclesSegment); + ZetClose(); + + draw_sprites(scanline); + } + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[ 0], nBurnSoundLen); + AY8910Update(1, &pAY8910Buffer[ 3], nBurnSoundLen); + AY8910Update(2, &pAY8910Buffer[ 6], nBurnSoundLen); + AY8910Update(3, &pAY8910Buffer[ 9], nBurnSoundLen); + AY8910Update(4, &pAY8910Buffer[12], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[ 0][n] >> 2; + nSample += pAY8910Buffer[ 1][n] >> 2; + nSample += pAY8910Buffer[ 2][n] >> 2; + nSample += pAY8910Buffer[ 3][n] >> 2; + nSample += pAY8910Buffer[ 4][n] >> 2; + nSample += pAY8910Buffer[ 5][n] >> 2; + nSample += pAY8910Buffer[ 6][n] >> 2; + nSample += pAY8910Buffer[ 7][n] >> 2; + nSample += pAY8910Buffer[ 8][n] >> 2; + nSample += pAY8910Buffer[ 9][n] >> 2; + nSample += pAY8910Buffer[10][n] >> 2; + nSample += pAY8910Buffer[11][n] >> 2; + nSample += pAY8910Buffer[12][n] >> 2; + nSample += pAY8910Buffer[13][n] >> 2; + nSample += pAY8910Buffer[14][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + BurnTransferCopy(DrvPalette); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029704; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + M6809Scan(nAction); + + AY8910Scan(nAction, pnMin); + } + + return 0; +} + + +// Gyruss (Konami) + +static struct BurnRomInfo gyrussRomDesc[] = { + { "gyrussk.1", 0x2000, 0xc673b43d, 1 | BRF_PRG | BRF_ESS }, // 0 Main Z80 Code + { "gyrussk.2", 0x2000, 0xa4ec03e4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gyrussk.3", 0x2000, 0x27454a98, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "gyrussk.9", 0x2000, 0x822bf27e, 2 | BRF_PRG | BRF_ESS }, // 3 Sub M6809 Code + + { "gyrussk.1a", 0x2000, 0xf4ae1c17, 3 | BRF_PRG | BRF_ESS }, // 4 Audio Z80 Code + { "gyrussk.2a", 0x2000, 0xba498115, 3 | BRF_PRG | BRF_ESS }, // 5 + + { "gyrussk.3a", 0x1000, 0x3f9b5dea, 4 | BRF_PRG | BRF_ESS }, // 6 Audio i8039 + + { "gyrussk.6", 0x2000, 0xc949db10, 5 | BRF_GRA }, // 7 Sprites + { "gyrussk.5", 0x2000, 0x4f22411a, 5 | BRF_GRA }, // 8 + { "gyrussk.8", 0x2000, 0x47cd1fbc, 5 | BRF_GRA }, // 9 + { "gyrussk.7", 0x2000, 0x8e8d388c, 5 | BRF_GRA }, // 10 + + { "gyrussk.4", 0x2000, 0x27d8329b, 6 | BRF_GRA }, // 11 Background Tiles + + { "gyrussk.pr3", 0x0020, 0x98782db3, 7 | BRF_GRA }, // 12 Color Proms + { "gyrussk.pr1", 0x0100, 0x7ed057de, 7 | BRF_GRA }, // 13 + { "gyrussk.pr2", 0x0100, 0xde823a81, 7 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(gyruss) +STD_ROM_FN(gyruss) + +struct BurnDriver BurnDrvGyruss = { + "gyruss", NULL, NULL, NULL, "1983", + "Gyruss (Konami)\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, gyrussRomInfo, gyrussRomName, NULL, NULL, GyrussInputInfo, GyrussDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x140, + 224, 256, 3, 4 +}; + + +// Gyruss (Centuri) + +static struct BurnRomInfo gyrussceRomDesc[] = { + { "gya-1.bin", 0x2000, 0x85f8b7c2, 1 | BRF_PRG | BRF_ESS }, // 0 Main Z80 Code + { "gya-2.bin", 0x2000, 0x1e1a970f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gya-3.bin", 0x2000, 0xf6dbb33b, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "gyrussk.9", 0x2000, 0x822bf27e, 2 | BRF_PRG | BRF_ESS }, // 3 Sub M6809 Code + + { "gyrussk.1a", 0x2000, 0xf4ae1c17, 3 | BRF_PRG | BRF_ESS }, // 4 Audio Z80 Code + { "gyrussk.2a", 0x2000, 0xba498115, 3 | BRF_PRG | BRF_ESS }, // 5 + + { "gyrussk.3a", 0x1000, 0x3f9b5dea, 4 | BRF_PRG | BRF_ESS }, // 6 Audio i8039 + + { "gyrussk.6", 0x2000, 0xc949db10, 5 | BRF_GRA }, // 7 Sprites + { "gyrussk.5", 0x2000, 0x4f22411a, 5 | BRF_GRA }, // 8 + { "gyrussk.8", 0x2000, 0x47cd1fbc, 5 | BRF_GRA }, // 9 + { "gyrussk.7", 0x2000, 0x8e8d388c, 5 | BRF_GRA }, // 10 + + { "gyrussk.4", 0x2000, 0x27d8329b, 6 | BRF_GRA }, // 11 Background Tiles + + { "gyrussk.pr3", 0x0020, 0x98782db3, 7 | BRF_GRA }, // 12 Color Proms + { "gyrussk.pr1", 0x0100, 0x7ed057de, 7 | BRF_GRA }, // 13 + { "gyrussk.pr2", 0x0100, 0xde823a81, 7 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(gyrussce) +STD_ROM_FN(gyrussce) + +struct BurnDriver BurnDrvGyrussce = { + "gyrussce", "gyruss", NULL, NULL, "1983", + "Gyruss (Centuri)\0", NULL, "Konami (Centuri license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, gyrussceRomInfo, gyrussceRomName, NULL, NULL, GyrussInputInfo, GyrussceDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x140, + 224, 256, 3, 4 +}; + + +// Gyruss (bootleg) + +static struct BurnRomInfo gyrussbRomDesc[] = { + { "1.bin", 0x2000, 0x6bc21c10, 1 | BRF_PRG | BRF_ESS }, // 0 Main Z80 Code + { "gyrussk.2", 0x2000, 0xa4ec03e4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "gyrussk.3", 0x2000, 0x27454a98, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "gyrussk.9", 0x2000, 0x822bf27e, 2 | BRF_PRG | BRF_ESS }, // 3 Sub M6809 Code + + { "gyrussk.1a", 0x2000, 0xf4ae1c17, 3 | BRF_PRG | BRF_ESS }, // 4 Audio Z80 Code + { "gyrussk.2a", 0x2000, 0xba498115, 3 | BRF_PRG | BRF_ESS }, // 5 + + { "gyrussk.3a", 0x1000, 0x3f9b5dea, 4 | BRF_PRG | BRF_ESS }, // 6 Audio i8039 + + { "gyrussk.6", 0x2000, 0xc949db10, 5 | BRF_GRA }, // 7 Sprites + { "gyrussk.5", 0x2000, 0x4f22411a, 5 | BRF_GRA }, // 8 + { "gyrussk.8", 0x2000, 0x47cd1fbc, 5 | BRF_GRA }, // 9 + { "gyrussk.7", 0x2000, 0x8e8d388c, 5 | BRF_GRA }, // 10 + + { "gyrussk.4", 0x2000, 0x27d8329b, 6 | BRF_GRA }, // 11 Background Tiles + + { "gyrussk.pr3", 0x0020, 0x98782db3, 7 | BRF_GRA }, // 12 Color Proms + { "gyrussk.pr1", 0x0100, 0x7ed057de, 7 | BRF_GRA }, // 13 + { "gyrussk.pr2", 0x0100, 0xde823a81, 7 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(gyrussb) +STD_ROM_FN(gyrussb) + +struct BurnDriver BurnDrvGyrussb = { + "gyrussb", "gyruss", NULL, NULL, "1983", + "Gyruss (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, gyrussbRomInfo, gyrussbRomName, NULL, NULL, GyrussInputInfo, GyrussDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x140, + 224, 256, 3, 4 +}; + + +// Venus + +static struct BurnRomInfo venusRomDesc[] = { + { "r1", 0x2000, 0xd030abb1, 1 | BRF_PRG | BRF_ESS }, // 0 Main Z80 Code + { "r2", 0x2000, 0xdbf65d4d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "r3", 0x2000, 0xdb246fcd, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "gyrussk.9", 0x2000, 0x822bf27e, 2 | BRF_PRG | BRF_ESS }, // 3 Sub M6809 Code + + { "gyrussk.1a", 0x2000, 0xf4ae1c17, 3 | BRF_PRG | BRF_ESS }, // 4 Audio Z80 Code + { "gyrussk.2a", 0x2000, 0xba498115, 3 | BRF_PRG | BRF_ESS }, // 5 + + { "gyrussk.3a", 0x1000, 0x3f9b5dea, 4 | BRF_PRG | BRF_ESS }, // 6 Audio i8039 + + { "gyrussk.6", 0x2000, 0xc949db10, 5 | BRF_GRA }, // 7 Sprites + { "gyrussk.5", 0x2000, 0x4f22411a, 5 | BRF_GRA }, // 8 + { "gyrussk.8", 0x2000, 0x47cd1fbc, 5 | BRF_GRA }, // 9 + { "gyrussk.7", 0x2000, 0x8e8d388c, 5 | BRF_GRA }, // 10 + + { "gyrussk.4", 0x2000, 0x27d8329b, 6 | BRF_GRA }, // 11 Background Tiles + + { "gyrussk.pr3", 0x0020, 0x98782db3, 7 | BRF_GRA }, // 12 Color Proms + { "gyrussk.pr1", 0x0100, 0x7ed057de, 7 | BRF_GRA }, // 13 + { "gyrussk.pr2", 0x0100, 0xde823a81, 7 | BRF_GRA }, // 14 +}; + +STD_ROM_PICK(venus) +STD_ROM_FN(venus) + +struct BurnDriver BurnDrvVenus = { + "venus", "gyruss", NULL, NULL, "1983", + "Venus\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, venusRomInfo, venusRomName, NULL, NULL, GyrussInputInfo, GyrussDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x140, + 224, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_higemaru.cpp b/src/burn/drivers/misc_pre90s/d_higemaru.cpp new file mode 100644 index 00000000..aa49b373 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_higemaru.cpp @@ -0,0 +1,537 @@ +// FB Alpha Pirate Ship Higemaru Module +// Based on MAME driver by Mirko Buffoni + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd, *Rom, *Gfx0, *Gfx1, *Prom; +static INT16 *pAY8910Buffer[6], *pFMBuffer = NULL; +static UINT32 *DrvPalette, *Palette; +static UINT8 DrvRecalc = 0; + +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[3], DrvReset; + +static INT32 flipscreen; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy3 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy3 + 6, "p2 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy3 + 5, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy3 + 4, "p2 start" }, + + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 1, "p1 left" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 3, "p1 fire 1"}, + + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p2 left" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 1, "p2 fire 1"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDips + 2, "dip 3" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x10, 0x01, 0x07, 0x01, "5 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x02, "4 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x03, "3 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x04, "1 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x10, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x10, 0x01, 0x38, 0x08, "5 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x10, "4 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x18, "3 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x20, "1 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x10, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x38, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0xc0, 0x80, "1" }, + {0x10, 0x01, 0xc0, 0x40, "2" }, + {0x10, 0x01, 0xc0, 0xc0, "3" }, + {0x10, 0x01, 0xc0, 0x00, "5" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x11, 0x01, 0x0e, 0x0e, "10k 50k 50k" }, + {0x11, 0x01, 0x0e, 0x0c, "10k 60k 60k" }, + {0x11, 0x01, 0x0e, 0x0a, "20k 60k 60k" }, + {0x11, 0x01, 0x0e, 0x08, "20k 70k 70k" }, + {0x11, 0x01, 0x0e, 0x06, "30k 70k 70k" }, + {0x11, 0x01, 0x0e, 0x04, "30k 80k 80k" }, + {0x11, 0x01, 0x0e, 0x02, "40k 100k 100k" }, + {0x11, 0x01, 0x0e, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x10, 0x00, "Off" }, + {0x11, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Music" }, + {0x11, 0x01, 0x20, 0x00, "Off" }, + {0x11, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +void __fastcall higemaru_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc800: + flipscreen = data >> 7; + break; + + case 0xc801: + case 0xc802: + AY8910Write(0, (address - 1) & 1, data); + break; + + case 0xc803: + case 0xc804: + AY8910Write(1, (address - 1) & 1, data); + break; + } +} + +UINT8 __fastcall higemaru_read(UINT16 address) +{ + UINT8 ret; + + switch (address) + { + case 0xc000: + { + ret = 0xff; + + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy1[i] << i; + } + + return ret; + } + + case 0xc001: + { + ret = 0xff; + + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy2[i] << i; + } + + return ret; + } + + case 0xc002: + { + ret = DrvDips[0]; + + for (INT32 i = 0; i < 8; i++) + ret ^= DrvJoy3[i] << i; + + return ret; + } + + case 0xc003: + return DrvDips[1]; + + case 0xc004: + return DrvDips[2]; + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom = Next; Next += 0x10000; + Gfx0 = Next; Next += 0x08000; + Gfx1 = Next; Next += 0x08000; + Prom = Next; Next += 0x00300; + + Palette = (UINT32*)Next; Next += 0x00180 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00180 * sizeof(UINT32); + + pFMBuffer = (INT16*)Next; Next += (nBurnSoundLen * 6 * sizeof(INT16)); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (Rom + 0xd000, 0, 0x2000); + + AY8910Reset(0); + AY8910Reset(1); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + flipscreen = 0; + + return 0; +} + +static void DrvPaletteInit() +{ + UINT32 tmp[0x20]; + + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0, bit1, bit2; + + bit0 = (Prom[i] >> 0) & 1; + bit1 = (Prom[i] >> 1) & 1; + bit2 = (Prom[i] >> 2) & 1; + INT32 r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 1; + bit1 = (Prom[i] >> 4) & 1; + bit2 = (Prom[i] >> 5) & 1; + INT32 g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit1 = (Prom[i] >> 6) & 1; + bit2 = (Prom[i] >> 7) & 1; + INT32 b = 0x47 * bit1 + 0x97 * bit2; + + tmp[i] = (r << 16) | (g << 8) | b; + } + + Prom += 0x100; + + for (INT32 i = 0; i < 0x80; i++) { + Palette[i] = tmp[Prom[i] & 0x0f]; + } + + for (INT32 i = 0x80; i < 0x180; i++) { + Palette[i] = tmp[(Prom[i + 0x80] & 0x0f) | 0x10]; + } +} + +static INT32 DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x2000); + + static INT32 Planes[4] = { 0x10004, 0x10000, 0x00004, 0x00000 }; + static INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x100, 0x101, 0x102, 0x103, 0x108, 0x109, 0x10a, 0x10b }; + static INT32 YOffs[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + + GfxDecode(0x200, 2, 8, 8, Planes + 2, XOffs, YOffs, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x4000); + + GfxDecode(0x080, 4, 16, 16, Planes, XOffs, YOffs, 0x200, tmp, Gfx1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + } + + { + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Rom + i * 0x2000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(Gfx0 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(Gfx1 + 0x0000, 5, 1)) return 1; + if (BurnLoadRom(Gfx1 + 0x2000, 6, 1)) return 1; + + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(Prom + i * 0x100, i + 7, 1)) return 1; + } + + if (DrvGfxDecode()) return 1; + DrvPaletteInit(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0x7fff, 2, Rom + 0x0000); + ZetMapArea(0xd000, 0xd7ff, 0, Rom + 0xd000); + ZetMapArea(0xd000, 0xd9ff, 1, Rom + 0xd000); + ZetMapArea(0xe000, 0xefff, 0, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 1, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, Rom + 0xe000); + ZetSetWriteHandler(higemaru_write); + ZetSetReadHandler(higemaru_read); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + GenericTilesExit(); + + BurnFree (Mem); + + Mem = MemEnd = Rom = Gfx0 = Gfx1 = Prom = NULL; + DrvPalette = Palette = NULL; + pFMBuffer = NULL; + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = NULL; + } + + flipscreen = 0; + DrvRecalc = 0; + + return 0; +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x100; i++) { + INT32 color = Palette[i]; + DrvPalette[i] = BurnHighCol(color >> 16, color >> 8, color, 0); + } + } + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 sx = (offs << 3) & 0xf8; + INT32 sy = (offs >> 2) & 0xf8; + + INT32 code = Rom[0xd000 + offs] | ((Rom[0xd400 + offs] & 0x80) << 1); + INT32 color = Rom[0xd400 + offs] & 0x1f; + + sy -= 16; + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx ^ 0xf8, 216 - sy, color, 2, 0, Gfx0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0, Gfx0); + } + } + + for (INT32 offs = 0x170; offs >= 0; offs -= 16) + { + INT32 code,color,sx,sy,flipx,flipy; + + code = Rom[0xd880 + offs] & 0x7f; + color = Rom[0xd884 + offs] & 0x0f; + sx = Rom[0xd88c + offs]; + sy = Rom[0xd888 + offs]; + flipx = Rom[0xd884 + offs] & 0x10; + flipy = Rom[0xd884 + offs] & 0x20; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x80, Gfx1); + if (sx > 0xf0) Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx - 256, sy, color, 4, 0x0f, 0x80, Gfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x80, Gfx1); + if (sx > 0xf0) Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx - 256, sy, color, 4, 0x0f, 0x80, Gfx1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x80, Gfx1); + if (sx > 0xf0) Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx - 256, sy, color, 4, 0x0f, 0x80, Gfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x80, Gfx1); + if (sx > 0xf0) Render16x16Tile_Mask_Clip(pTransDraw, code, sx - 256, sy, color, 4, 0x0f, 0x80, Gfx1); + } + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetOpen(0); + ZetRun(33333); +// ZetRaiseIrq(0xd7); + ZetSetVector(0xd7); + ZetRaiseIrq(0); + ZetRun(33334); +// ZetRaiseIrq(0xcf); + ZetSetVector(0xcf); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom + 0xd000; + ba.nLen = 0x2000; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(flipscreen); + } + + return 0; +} + + +// Pirate Ship Higemaru + +static struct BurnRomInfo higemaruRomDesc[] = { + { "hg4.p12", 0x2000, 0xdc67a7f9, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "hg5.m12", 0x2000, 0xf65a4b68, 1 | BRF_PRG | BRF_ESS }, // 1 + { "hg6.p11", 0x2000, 0x5f5296aa, 1 | BRF_PRG | BRF_ESS }, // 2 + { "hg7.m11", 0x2000, 0xdc5d455d, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "hg3.m1", 0x2000, 0xb37b88c8, 2 | BRF_GRA }, // 4 Characters + + { "hg1.c14", 0x2000, 0xef4c2f5d, 3 | BRF_GRA }, // 5 Sprites + { "hg2.e14", 0x2000, 0x9133f804, 3 | BRF_GRA }, // 6 + + { "hgb3.l6", 0x0020, 0x629cebd8, 4 | BRF_GRA }, // 7 Color Proms + { "hgb5.m4", 0x0100, 0xdbaa4443, 4 | BRF_GRA }, // 8 + { "hgb1.h7", 0x0100, 0x07c607ce, 4 | BRF_GRA }, // 9 + + { "hgb4.l9", 0x0100, 0x712ac508, 0 | BRF_OPT }, // 10 Misc. Proms (not used) + { "hgb2.k7", 0x0100, 0x4921635c, 0 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(higemaru) +STD_ROM_FN(higemaru) + +struct BurnDriver BurnDrvhigemaru = { + "higemaru", NULL, NULL, NULL, "1984", + "Pirate Ship Higemaru\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, higemaruRomInfo, higemaruRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x180, + 256, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_ikki.cpp b/src/burn/drivers/misc_pre90s/d_ikki.cpp new file mode 100644 index 00000000..67985492 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_ikki.cpp @@ -0,0 +1,666 @@ +// FB Alpha Ikki / Farmers Rebellion driver module +// Based on MAME driver by Uki + +#include "tiles_generic.h" +#include "sn76496.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvVidAttr; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvShareRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvVidRAM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 *DrvTransMask; +static UINT8 DrvRecalc; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; + +static UINT8 *flipscreen; +static UINT8 *ikki_scroll; + +static INT32 vblank; + +static struct BurnInputInfo IkkiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ikki) + +static struct BurnDIPInfo IkkiDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x10, 0x01, 0x01, 0x00, "3" }, + {0x10, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2, "2 Player Game" }, + {0x10, 0x01, 0x02, 0x00, "2 Credits" }, + {0x10, 0x01, 0x02, 0x02, "1 Credit" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x10, 0x01, 0x04, 0x00, "Off" }, + {0x10, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 16, "Coin1 / Coin2" }, + {0x10, 0x01, 0xf0, 0x00, "1 Coin 1 Credit / 1 Coin 1 Credit " }, + {0x10, 0x01, 0xf0, 0x10, "2 Coins 1 Credit / 2 Coins 1 Credit " }, + {0x10, 0x01, 0xf0, 0x20, "2 Coins 1 Credit / 1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0x30, "1 Coin 1 Credit / 1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0x40, "1 Coin 1 Credit / 1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0x50, "1 Coin 1 Credit / 1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0x60, "1 Coin 1 Credit / 1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0x70, "1 Coin 1 Credit / 1 Coin 6 Credits" }, + {0x10, 0x01, 0xf0, 0x80, "1 Coin 2 Credits / 1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 2 Credits / 1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 2 Credits / 1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 2 Credits / 1 Coin 10 Credits" }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 2 Credits / 1 Coin 11 Credits" }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 2 Credits / 1 Coin 12 Credits" }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits / 1 Coin 6 Credits" }, + {0x10, 0x01, 0xf0, 0xf0, "Free_Play" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x06, 0x00, "1 (Normal)" }, + {0x11, 0x01, 0x06, 0x02, "2" }, + {0x11, 0x01, 0x06, 0x04, "3" }, + {0x11, 0x01, 0x06, 0x06, "4 (Difficult)" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Ikki) + +void __fastcall ikki_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe008: + *flipscreen = data & 4; + return; + + case 0xe00a: + case 0xe00b: + ikki_scroll[address & 1] = data; + return; + } +} + +UINT8 __fastcall ikki_main_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + return (vblank ? 2 : 0); + + case 0xe001: + return DrvDips[0]; + + case 0xe002: + return DrvDips[1]; + + case 0xe003: + return DrvInputs[2]; + + case 0xe004: + return DrvInputs[0]; + + case 0xe005: + return DrvInputs[1]; + } + + return 0; +} + +void __fastcall ikki_sub_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xd801: + SN76496Write(0, data); + return; + + case 0xd802: + SN76496Write(1, data); + return; + } +} + +UINT8 __fastcall ikki_sub_read(UINT16 /*address*/) +{ + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + return 0; +} + +static void DrvPaletteInit() +{ + UINT32 *tmp = (UINT32*)BurnMalloc(0x100 * sizeof(UINT32)); + + for (INT32 i = 0; i < 0x100; i++) + { + UINT8 r, g, b; + + r = DrvColPROM[i + 0x000] & 0x0f; + g = DrvColPROM[i + 0x100] & 0x0f; + b = DrvColPROM[i + 0x200] & 0x0f; + + tmp[i] = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b; + } + + DrvColPROM += 0x300; + + memset (DrvTransMask, 1, 0x200); + + for (INT32 i = 0; i < 0x200; i++) + { + UINT16 ctabentry = DrvColPROM[i] ^ 0xff; + + if ((i & 0x07) == 0x07 && ctabentry == 0) DrvTransMask[i] = 0; + if ((i & 0x07) == 0x00) DrvTransMask[i] = 0; // Seems to work... + + Palette[i] = tmp[ctabentry]; + } + + for (INT32 i = 0x200; i < 0x400; i++) { + Palette[i] = tmp[DrvColPROM[i]]; + } + + BurnFree(tmp); +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { 16384*8*2,16384*8,0 }; + INT32 XOffs[16] = { 7,6,5,4,3,2,1,0,8*16+7,8*16+6,8*16+5,8*16+4,8*16+3,8*16+2,8*16+1,8*16+0 }; + INT32 YOffs[32] = { 8*0, 8*1, 8*2, 8*3, 8*4, 8*5, 8*6, 8*7, 8*8,8*9,8*10,8*11,8*12,8*13,8*14,8*15, + 8*32,8*33,8*34,8*35,8*36,8*37,8*38,8*39, 8*40,8*41,8*42,8*43,8*44,8*45,8*46,8*47 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0xc000); + + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0xc000); + + GfxDecode(0x800, 3, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0xc000); + + GfxDecode(0x100, 3, 16, 32, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000800; + + DrvVidAttr = Next; Next += 0x000100; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + Palette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x020000; + + DrvTransMask = Next; Next += 0x000200; + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x000800; + DrvShareRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000800; + + ikki_scroll = Next; Next += 0x000002; + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x0000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x8000, DrvZ80ROM0 + 0x2000, 0x2000); + + if (BurnLoadRom(DrvZ80ROM0 + 0x2000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x4000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x6000, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x0000, 4, 1)) return 1; + + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(DrvGfxROM1 + 0x4000 * i, 5 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x4000 * i, 8 + i, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x0100 * i, 11 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvColPROM + 0x0300, 14, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x0500, 15, 1)) return 1; + + if (BurnLoadRom(DrvVidAttr + 0x0000, 16, 1)) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x9fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x9fff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM0); + ZetMapArea(0xc800, 0xcfff, 0, DrvShareRAM); + ZetMapArea(0xc800, 0xcfff, 1, DrvShareRAM); + ZetMapArea(0xc800, 0xcfff, 2, DrvShareRAM); + ZetMapArea(0xd000, 0xd7ff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xd7ff, 2, DrvVidRAM); + ZetSetWriteHandler(ikki_main_write); + ZetSetReadHandler(ikki_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80ROM1); + ZetMapArea(0xc000, 0xc7ff, 0, DrvSprRAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvSprRAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvSprRAM); + ZetMapArea(0xc800, 0xcfff, 0, DrvShareRAM); + ZetMapArea(0xc800, 0xcfff, 1, DrvShareRAM); + ZetMapArea(0xc800, 0xcfff, 2, DrvShareRAM); + ZetSetWriteHandler(ikki_sub_write); + ZetSetReadHandler(ikki_sub_read); + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 8000000/4, 0); + SN76489Init(1, 8000000/2, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SN76496Exit(); + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0x800; offs += 4) + { + INT32 code = (DrvSprRAM[offs + 2] & 0x80) | (DrvSprRAM[offs + 1] >> 1); + INT32 color = DrvSprRAM[offs + 2] & 0x3f; + + INT32 sx = DrvSprRAM[offs + 3]; + INT32 sy = DrvSprRAM[offs + 0]; + + if (*flipscreen) + sx = 240 - sx; + else + sy = 224 - sy; + + sx &= 0xff; + sy &= 0xff; + if (sx > 248) sx -= 256; + if (sy > 240) sy -= 256; + + sy -= 16; + sx -= 8; + + { + UINT8 *src = DrvGfxROM1 + (code << 9); + color <<= 3; + + if (*flipscreen) { + for (INT32 y = 31; y >= 0; y--) + { + INT32 yy = sy + y; + + for (INT32 x = 15; x >= 0; x--) + { + INT32 xx = sx + x; + INT32 pxl = src[15-x] | color; + + if (xx < 0 || yy < 0 || xx >= nScreenWidth || yy >= nScreenHeight) continue; + + if (DrvTransMask[pxl]) + pTransDraw[(yy * nScreenWidth) + xx] = pxl; + } + + src += 16; + } + } else { + for (INT32 y = 0; y < 32; y++) + { + INT32 yy = sy + y; + + for (INT32 x = 0; x < 16; x++) + { + INT32 xx = sx + x; + INT32 pxl = src[x] | color; + + if (xx < 0 || yy < 0 || xx >= nScreenWidth || yy >= nScreenHeight) continue; + + if (DrvTransMask[pxl]) + pTransDraw[(yy * nScreenWidth) + xx] = pxl; + } + + src += 16; + } + } + } + } +} + +static void draw_bg_layer(INT32 prio) +{ + for (INT32 offs = 0; offs < 0x800 / 2; offs++) + { + INT32 x = (offs >> 5) << 3; + INT32 y = (offs & 0x1f) << 3; + INT32 d = DrvVidAttr[x >> 3]; + + if (d != 0 && d != 0x0d) { + if (prio) continue; + } + + INT32 color = DrvVidRAM[offs << 1]; + INT32 code = DrvVidRAM[(offs << 1) | 1] + ((color & 0xe0) << 3); + color = (color & 0x1f) | ((color & 0x80) >> 2); + + if (d == 0x02 && prio == 0) { + x -= ikki_scroll[1]; + if (x < 0) x += 176; + + y = (y + ~ikki_scroll[0]) & 0xff; + } + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (248-x)-8, (248-y)-16, color, 3, 0x200, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, x-8, y-16, color, 3, 0x200, DrvGfxROM0); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + draw_bg_layer(0); + draw_sprites(); + draw_bg_layer(1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0x00, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // clear opposites + if (DrvJoy1[2] && DrvJoy1[3]) DrvInputs[0] &= ~0x0c; + if (DrvJoy1[1] && DrvJoy1[0]) DrvInputs[0] &= ~0x03; + if (DrvJoy2[3] && DrvJoy2[2]) DrvInputs[1] &= ~0x0c; + if (DrvJoy2[1] && DrvJoy2[0]) DrvInputs[1] &= ~0x03; + } + + INT32 nCycleSegment; + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 4000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + vblank = 1; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCycleSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nCycleSegment); + if (i == 15) { + vblank = 0; + ZetRaiseIrq(0); + } + if (i == 239) { + ZetRaiseIrq(0); + vblank = 1; + } + ZetClose(); + + nCycleSegment = (nCyclesTotal[1] - nCyclesDone[1]) / (nInterleave - i); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nCycleSegment); + if (i == 15) ZetRaiseIrq(0); + if (i == 239)ZetRaiseIrq(0); + ZetClose(); + } + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029698; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + // SN76496Scan(nAction, pnMin); + } + + return 0; +} + + +// Ikki (Japan) + +static struct BurnRomInfo ikkiRomDesc[] = { + { "tvg17_1", 0x4000, 0xcb28167c, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tvg17_2", 0x2000, 0x756c7450, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tvg17_3", 0x2000, 0x91f0a8b6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tvg17_4", 0x2000, 0x696fcf7d, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "tvg17_5", 0x2000, 0x22bdb40e, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + + { "tvg17_6", 0x4000, 0xdc8aa269, 3 | BRF_GRA }, // 5 Sprites + { "tvg17_7", 0x4000, 0x0e9efeba, 3 | BRF_GRA }, // 6 + { "tvg17_8", 0x4000, 0x45c9087a, 3 | BRF_GRA }, // 7 + + { "tvg17_9", 0x4000, 0xc594f3c5, 4 | BRF_GRA }, // 8 Background Tiles + { "tvg17_10", 0x4000, 0x2e510b4e, 4 | BRF_GRA }, // 9 + { "tvg17_11", 0x4000, 0x35012775, 4 | BRF_GRA }, // 10 + + { "prom17_3", 0x0100, 0xdbcd3bec, 5 | BRF_GRA }, // 11 Color Proms + { "prom17_4", 0x0100, 0x9eb7b6cf, 5 | BRF_GRA }, // 12 + { "prom17_5", 0x0100, 0x9b30a7f3, 5 | BRF_GRA }, // 13 + { "prom17_6", 0x0200, 0x962e619d, 5 | BRF_GRA }, // 14 + { "prom17_7", 0x0200, 0xb1f5148c, 5 | BRF_GRA }, // 15 + + { "prom17_1", 0x0100, 0xca0af30c, 6 | BRF_OPT }, // 16 Unused Proms + { "prom17_2", 0x0100, 0xf3c55174, 6 | BRF_OPT }, // 17 +}; + +STD_ROM_PICK(ikki) +STD_ROM_FN(ikki) + +struct BurnDriver BurnDrvIkki = { + "ikki", NULL, NULL, NULL, "1985", + "Ikki (Japan)\0", NULL, "Sun Electronics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, ikkiRomInfo, ikkiRomName, NULL, NULL, IkkiInputInfo, IkkiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// Farmers Rebellion + +static struct BurnRomInfo farmerRomDesc[] = { + { "tvg-1.10", 0x4000, 0x2c0bd392, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tvg-2.9", 0x2000, 0xb86efe02, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tvg-3.8", 0x2000, 0xfd686ff4, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tvg-4.7", 0x2000, 0x1415355d, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "tvg-5.30", 0x2000, 0x22bdb40e, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + + { "tvg-6.104", 0x4000, 0xdc8aa269, 3 | BRF_GRA }, // 5 Sprites + { "tvg-7.103", 0x4000, 0x0e9efeba, 3 | BRF_GRA }, // 6 + { "tvg-8.102", 0x4000, 0x45c9087a, 3 | BRF_GRA }, // 7 + + { "tvg17_9", 0x4000, 0xc594f3c5, 4 | BRF_GRA }, // 8 Background Tiles + { "tvg17_10", 0x4000, 0x2e510b4e, 4 | BRF_GRA }, // 9 + { "tvg17_11", 0x4000, 0x35012775, 4 | BRF_GRA }, // 10 + + { "prom17_3", 0x0100, 0xdbcd3bec, 5 | BRF_GRA }, // 11 Color Proms + { "prom17_4", 0x0100, 0x9eb7b6cf, 5 | BRF_GRA }, // 12 + { "prom17_5", 0x0100, 0x9b30a7f3, 5 | BRF_GRA }, // 13 + { "prom17_6", 0x0200, 0x962e619d, 5 | BRF_GRA }, // 14 + { "prom17_7", 0x0200, 0xb1f5148c, 5 | BRF_GRA }, // 15 + + { "prom17_1", 0x0100, 0xca0af30c, 6 | BRF_OPT }, // 16 Unused Proms + { "prom17_2", 0x0100, 0xf3c55174, 6 | BRF_OPT }, // 17 +}; + +STD_ROM_PICK(farmer) +STD_ROM_FN(farmer) + +struct BurnDriver BurnDrvFarmer = { + "farmer", "ikki", NULL, NULL, "1985", + "Farmers Rebellion\0", NULL, "Sun Electronics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE | GBF_SCRFIGHT, 0, + NULL, farmerRomInfo, farmerRomName, NULL, NULL, IkkiInputInfo, IkkiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_jack.cpp b/src/burn/drivers/misc_pre90s/d_jack.cpp new file mode 100644 index 00000000..c352a521 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_jack.cpp @@ -0,0 +1,1926 @@ +// FB Alpha Jack the Giantkiller driver module +// Based on MAME driver by Brad Oliver + +#include "tiles_generic.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + + +static UINT8 *Mem, *Rom0, *Rom1, *Gfx, *Prom, *User; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvJoy4[8], DrvReset, DrvDips[2]; +static INT16 *pAY8910Buffer[3], *pFMBuffer = NULL; +static INT32 tri_fix, joinem, loverb, suprtriv; +static INT32 timer_rate, flip_screen; +static UINT32 *Palette, *DrvPal; +static UINT8 DrvCalcPal; + +static UINT8 soundlatch; +static INT32 question_address, question_rom, remap_address[16]; +static INT32 joinem_snd_bit; + +static INT32 nCyclesSegment; +static INT32 nCyclesDone[2], nCyclesTotal[2]; + +static struct BurnInputInfo JackInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"p1 Up" , BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down", }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p1 left" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 1, "p1 fire 2"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 5, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"p2 Up" , BIT_DIGITAL, DrvJoy2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down", }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 6, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 7, "p2 left" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Jack) + +static struct BurnInputInfo ZzyzzyxxInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 5, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 1"}, + + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 4, "p2 Up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Zzyzzyxx) + +static struct BurnInputInfo FreezeInputList[] = { + {"Coin" , BIT_DIGITAL , DrvJoy1 + 5, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 1, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Freeze) + +static struct BurnInputInfo SucasinoInputList[] = { + {"Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p1 left" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 1"}, + + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 6, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 7, "p2 left" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Sucasino) + +static struct BurnInputInfo TripoolInputList[] = { + {"Select Game 1", BIT_DIGITAL , DrvJoy1 + 2, "Select Game 1"}, + {"Select Game 2", BIT_DIGITAL, DrvJoy1 + 3, "Select Game 2"}, + {"Select Game 3", BIT_DIGITAL, DrvJoy1 + 4, "Select Game 3"}, + + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 1, "p1 down", }, + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p1 left" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 1, "p1 fire 2"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 5, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 4, "p1 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down", }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 6, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 7, "p2 left" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, +}; + +STDINPUTINFO(Tripool) + +static struct BurnInputInfo JoinemInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy3 + 0, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down", }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy3 + 1, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down", }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p2 left" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Joinem) + +static struct BurnInputInfo LoverboyInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy3 + 0, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down", }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy3 + 1, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down", }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p2 left" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Loverboy) + +static struct BurnInputInfo StrivInputList[] = { + {"Coin" , BIT_DIGITAL , DrvJoy3 + 1, "p1 coin" }, + + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 1, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 2, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 3, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 4"}, + + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 1, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 2, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 3, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 4"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Striv) + +static struct BurnDIPInfo JackDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL}, + {0x12, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coin B"}, + {0x11, 0x01, 0x03, 0x01, "2 coins 1 credit"}, + {0x11, 0x01, 0x03, 0x03, "4 coins 3 credits"}, + {0x11, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + + {0 , 0xfe, 0 , 4 , "Coin A"}, + {0x11, 0x01, 0x0c, 0x00, "3 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x08, "4 coins 3 credits"}, + {0x11, 0x01, 0x0c, 0x0c, "1 coin 1 credits"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x11, 0x01, 0x10, 0x00, "3"}, + {0x11, 0x01, 0x10, 0x10, "5"}, + + {0 , 0xfe, 0 , 2 , "Bonus Life"}, + {0x11, 0x01, 0x20, 0x00, "Every 10000"}, + {0x11, 0x01, 0x20, 0x20, "10000 ONly"}, + + {0 , 0xfe, 0 , 2 , "Difficulty"}, + {0x11, 0x01, 0x40, 0x00, "Start on Level 1"}, + {0x11, 0x01, 0x40, 0x40, "Start on Level 13"}, + + {0 , 0xfe, 0 , 2 , "Bullets per Bean Collected"}, + {0x11, 0x01, 0x80, 0x00, "1"}, + {0x11, 0x01, 0x80, 0x80, "2"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Invulnerability (Cheat)"}, + {0x12, 0x01, 0x40, 0x00, "Off"}, + {0x12, 0x01, 0x40, 0x40, "On"}, + + {0 , 0xfe, 0 , 4 , "255 Lives (Cheat)"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(Jack) + + +static struct BurnDIPInfo Jack2DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL}, + {0x12, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coin B"}, + {0x11, 0x01, 0x03, 0x03, "4 coins 3 credits"}, + {0x11, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x03, 0x01, "1 coin 2 credits"}, + {0x11, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + + {0 , 0xfe, 0 , 4 , "Coin A"}, + {0x11, 0x01, 0x0c, 0x08, "3 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x0c, "4 coins 3 credits"}, + {0x11, 0x01, 0x0c, 0x00, "1 coin 1 credits"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x11, 0x01, 0x10, 0x00, "3"}, + {0x11, 0x01, 0x10, 0x10, "5"}, + + {0 , 0xfe, 0 , 2 , "Bonus Life"}, + {0x11, 0x01, 0x20, 0x00, "Every 10000"}, + {0x11, 0x01, 0x20, 0x20, "10000 ONly"}, + + {0 , 0xfe, 0 , 2 , "Difficulty"}, + {0x11, 0x01, 0x40, 0x00, "Start on Level 1"}, + {0x11, 0x01, 0x40, 0x40, "Start on Level 13"}, + + {0 , 0xfe, 0 , 2 , "Bullets per Bean Collected"}, + {0x11, 0x01, 0x80, 0x00, "1"}, + {0x11, 0x01, 0x80, 0x80, "2"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Invulnerability (Cheat)"}, + {0x12, 0x01, 0x40, 0x00, "Off"}, + {0x12, 0x01, 0x40, 0x40, "On"}, + + {0 , 0xfe, 0 , 4 , "255 Lives (Cheat)"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(Jack2) + +static struct BurnDIPInfo Jack3DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL}, + {0x12, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coin B"}, + {0x11, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x03, 0x01, "1 coin 2 credits"}, + {0x11, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + {0x11, 0x01, 0x03, 0x03, "1 coin 5 credits"}, + + {0 , 0xfe, 0 , 4 , "Coin A"}, + {0x11, 0x01, 0x0c, 0x0c, "4 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x08, "3 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x00, "1 coin 1 credit"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x11, 0x01, 0x10, 0x00, "3"}, + {0x11, 0x01, 0x10, 0x10, "5"}, + + {0 , 0xfe, 0 , 2 , "Bonus Life"}, + {0x11, 0x01, 0x20, 0x00, "Every 10000"}, + {0x11, 0x01, 0x20, 0x20, "10000 ONly"}, + + {0 , 0xfe, 0 , 2 , "Difficulty"}, + {0x11, 0x01, 0x40, 0x00, "Start on Level 1"}, + {0x11, 0x01, 0x40, 0x40, "Start on Level 13"}, + + {0 , 0xfe, 0 , 2 , "Bullets per Bean Collected"}, + {0x11, 0x01, 0x80, 0x00, "1"}, + {0x11, 0x01, 0x80, 0x80, "2"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Invulnerability (Cheat)"}, + {0x12, 0x01, 0x40, 0x00, "Off"}, + {0x12, 0x01, 0x40, 0x40, "On"}, + + {0 , 0xfe, 0 , 4 , "255 Lives (Cheat)"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(Jack3) + +static struct BurnDIPInfo TreahuntDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL}, + {0x12, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coin B"}, + {0x11, 0x01, 0x03, 0x01, "2 coins 1 credit"}, + {0x11, 0x01, 0x03, 0x03, "4 coins 3 credits"}, + {0x11, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + + {0 , 0xfe, 0 , 4 , "Coin A"}, + {0x11, 0x01, 0x0c, 0x08, "3 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x11, 0x01, 0x0c, 0x0c, "4 coins 3 credits"}, + {0x11, 0x01, 0x0c, 0x00, "1 coin 1 credit"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x11, 0x01, 0x10, 0x00, "3"}, + {0x11, 0x01, 0x10, 0x10, "5"}, + + {0 , 0xfe, 0 , 2 , "Bonus Life"}, + {0x11, 0x01, 0x20, 0x00, "Every 10000"}, + {0x11, 0x01, 0x20, 0x20, "10000 ONly"}, + + {0 , 0xfe, 0 , 2 , "Difficulty"}, + {0x11, 0x01, 0x40, 0x00, "Start on Level 1"}, + {0x11, 0x01, 0x40, 0x40, "Start on Level 6"}, + + {0 , 0xfe, 0 , 2 , "Bullets per Bean Collected"}, + {0x11, 0x01, 0x80, 0x00, "5"}, + {0x11, 0x01, 0x80, 0x80, "20"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Invulnerability (Cheat)"}, + {0x12, 0x01, 0x40, 0x00, "Off"}, + {0x12, 0x01, 0x40, 0x40, "On"}, + + {0 , 0xfe, 0 , 4 , "255 Lives (Cheat)"}, + {0x12, 0x01, 0x80, 0x00, "Off"}, + {0x12, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(Treahunt) + + +static struct BurnDIPInfo ZzyzzyxxDIPList[]= +{ + // Default Values + {0x0A, 0xff, 0xff, 0x00, NULL}, + {0x0B, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coinage"}, + {0x0A, 0x01, 0x03, 0x01, "2 coins 1 credit"}, + {0x0A, 0x01, 0x03, 0x03, "4 coins 3 credits"}, + {0x0A, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x0A, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x0A, 0x01, 0x04, 0x00, "3"}, + {0x0A, 0x01, 0x04, 0x04, "2"}, + + {0 , 0xfe, 0 , 2 , "Credits on Reset"}, + {0x0A, 0x01, 0x08, 0x00, "Off"}, + {0x0A, 0x01, 0x08, 0x08, "On"}, + + {0 , 0xfe, 0 , 2 , "Demo Sounds"}, + {0x0A, 0x01, 0x10, 0x10, "Off"}, + {0x0A, 0x01, 0x10, 0x00, "On"}, + + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x0A, 0x01, 0x20, 0x20, "Upright"}, + {0x0A, 0x01, 0x20, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Free Play"}, + {0x0A, 0x01, 0x80, 0x00, "Off"}, + {0x0A, 0x01, 0x80, 0x80, "On"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Bonus Life"}, + {0x0B, 0x01, 0x03, 0x02, "None"}, + {0x0B, 0x01, 0x03, 0x00, "10000 50000"}, + {0x0B, 0x01, 0x03, 0x01, "25000 100000"}, + {0x0B, 0x01, 0x03, 0x03, "100000 300000"}, + + {0 , 0xfe, 0 , 2 , "2nd Bonus Given"}, + {0x0B, 0x01, 0x04, 0x00, "No"}, + {0x0B, 0x01, 0x04, 0x04, "Yes"}, + + {0 , 0xfe, 0 , 2 , "Starting Laps"}, + {0x0B, 0x01, 0x08, 0x00, "2"}, + {0x0B, 0x01, 0x08, 0x08, "3"}, + + {0 , 0xfe, 0 , 2 , "Difficulty of Pleasing Lola"}, + {0x0B, 0x01, 0x10, 0x00, "Easy"}, + {0x0B, 0x01, 0x10, 0x10, "Hard"}, + + {0 , 0xfe, 0 , 2 , "Show Intermissions"}, + {0x0B, 0x01, 0x20, 0x00, "No"}, + {0x0B, 0x01, 0x20, 0x20, "Yes"}, + + {0 , 0xfe, 0 , 3 , "Show Intermissions"}, + {0x0B, 0x01, 0xc0, 0x00, "3 under 4000 pts"}, + {0x0B, 0x01, 0xc0, 0x80, "5 under 4000 pts"}, + {0x0B, 0x01, 0xc0, 0x40, "None"}, +}; + +STDDIPINFO(Zzyzzyxx) + +static struct BurnDIPInfo FreezeDIPList[]= +{ + // Default Values + {0x08, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 2 , "Flip Screen"}, + {0x08, 0x01, 0x01, 0x00, "Off"}, + {0x08, 0x01, 0x01, 0x01, "On"}, + + {0 , 0xfe, 0 , 2 , "Difficulty"}, + {0x08, 0x01, 0x04, 0x00, "Easy"}, + {0x08, 0x01, 0x04, 0x04, "Hard"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x08, 0x01, 0x08, 0x00, "3"}, + {0x08, 0x01, 0x08, 0x08, "5"}, + + {0 , 0xfe, 0 , 4 , "Bonus Life"}, + {0x08, 0x01, 0x30, 0x00, "10000"}, + {0x08, 0x01, 0x30, 0x10, "10000 40000"}, + {0x08, 0x01, 0x30, 0x20, "10000 60000"}, + {0x08, 0x01, 0x30, 0x30, "20000 100000"}, + + {0 , 0xfe, 0 , 4 , "Coinage"}, + {0x08, 0x01, 0xc0, 0x80, "2 Coins 1 Credit"}, + {0x08, 0x01, 0xc0, 0x00, "1 Coin 1 Credit"}, + {0x08, 0x01, 0xc0, 0x40, "1 Coin 2 Credits"}, + {0x08, 0x01, 0xc0, 0xc0, "Free Play"}, +}; + +STDDIPINFO(Freeze) + +static struct BurnDIPInfo SucasinoDIPList[]= +{ + // Default Values + {0x0A, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coinage"}, + {0x0A, 0x01, 0x03, 0x00, "1 Coin 1 Credit"}, + {0x0A, 0x01, 0x03, 0x01, "1 Coin 2 Credits"}, + {0x0A, 0x01, 0x03, 0x02, "1 Coin 3 Credits"}, + {0x0A, 0x01, 0x03, 0x03, "1 Coin 4 Credits"}, + + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x0A, 0x01, 0x04, 0x00, "Upright"}, + {0x0A, 0x01, 0x04, 0x04, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Flip Screen"}, + {0x0A, 0x01, 0x08, 0x00, "Off"}, + {0x0A, 0x01, 0x08, 0x08, "On"}, +}; + +STDDIPINFO(Sucasino) + +static struct BurnDIPInfo JoinemDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x00, NULL}, + {0x0e, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 4 , "Coin A"}, + {0x0d, 0x01, 0x03, 0x01, "2 coins 1 credit"}, + {0x0d, 0x01, 0x03, 0x03, "4 coins 3 credits"}, + {0x0d, 0x01, 0x03, 0x00, "1 coin 1 credit"}, + {0x0d, 0x01, 0x03, 0x02, "1 coin 3 credits"}, + + {0 , 0xfe, 0 , 4 , "Coin B"}, + {0x0d, 0x01, 0x0c, 0x08, "3 coins 1 credit"}, + {0x0d, 0x01, 0x0c, 0x04, "2 coins 1 credit"}, + {0x0d, 0x01, 0x0c, 0x0c, "4 coins 3 credits"}, + {0x0d, 0x01, 0x0c, 0x00, "1 coin 1 credit"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x0d, 0x01, 0x10, 0x00, "2"}, + {0x0d, 0x01, 0x10, 0x10, "5"}, + + // DSW2 + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x0e, 0x01, 0x01, 0x01, "Upright"}, + {0x0e, 0x01, 0x01, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Sound Check"}, + {0x0e, 0x01, 0x20, 0x00, "Off"}, + {0x0e, 0x01, 0x20, 0x20, "On"}, + + {0 , 0xfe, 0 , 2 , "Infinite Lives"}, + {0x0e, 0x01, 0x80, 0x00, "2"}, + {0x0e, 0x01, 0x80, 0x80, "3"}, +}; + +STDDIPINFO(Joinem) + +static struct BurnDIPInfo LoverboyDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x00, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 15 , "Coin A"}, + {0x0f, 0x01, 0x0f, 0x0c, "4 Coins 1 Credit"}, + {0x0f, 0x01, 0x0f, 0x08, "3 Coins 1 Credit"}, + {0x0f, 0x01, 0x0f, 0x0d, "4 Coins 2 Credit"}, + {0x0f, 0x01, 0x0f, 0x04, "2 Coins 1 Credit"}, + {0x0f, 0x01, 0x0f, 0x09, "3 Coins 2 Credit"}, + {0x0f, 0x01, 0x0f, 0x0e, "4 Coins 3 Credit"}, + {0x0f, 0x01, 0x0f, 0x0f, "4 Coins 4 Credit"}, + {0x0f, 0x01, 0x0f, 0x0a, "3 Coins 3 Credit"}, + {0x0f, 0x01, 0x0f, 0x05, "2 Coins 2 Credit"}, + {0x0f, 0x01, 0x0f, 0x00, "1 Coins 1 Credit"}, + {0x0f, 0x01, 0x0f, 0x0b, "3 Coins 4 Credit"}, + {0x0f, 0x01, 0x0f, 0x06, "2 Coins 3 Credit"}, + {0x0f, 0x01, 0x0f, 0x07, "2 Coins 4 Credit"}, + {0x0f, 0x01, 0x0f, 0x01, "1 Coins 2 Credit"}, + {0x0f, 0x01, 0x0f, 0x02, "1 Coins 3 Credit"}, + {0x0f, 0x01, 0x0f, 0x03, "1 Coins 4 Credit"}, + + {0 , 0xfe, 0 , 2 , "Bonus"}, + {0x0f, 0x01, 0x20, 0x00, "20,000"}, + {0x0f, 0x01, 0x20, 0x20, "30,000"}, + + {0 , 0xfe, 0 , 2 , "Lives"}, + {0x0f, 0x01, 0x40, 0x00, "3"}, + {0x0f, 0x01, 0x40, 0x40, "5"}, + + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x0f, 0x01, 0x80, 0x80, "Upright"}, + {0x0f, 0x01, 0x80, 0x00, "Cocktail"}, +}; + +STDDIPINFO(Loverboy) + +static struct BurnDIPInfo StrivDIPList[]= +{ + // Default Values + {0x0A, 0xff, 0xff, 0xfd, NULL}, + + // DSW1 + {0 , 0xfe, 0 , 2 , "Monitor"}, + {0x0A, 0x01, 0x02, 0x02, "Horizontal"}, + {0x0A, 0x01, 0x02, 0x00, "Vertical"}, + + {0 , 0xfe, 0 , 8 , "Gaming Option Number"}, + {0x0A, 0x01, 0x05, 0x01, "2"}, + {0x0A, 0x01, 0x05, 0x05, "3"}, + {0x0A, 0x01, 0x05, 0x00, "4"}, + {0x0A, 0x01, 0x05, 0x04, "5"}, + {0x0A, 0x01, 0x05, 0x01, "4"}, + {0x0A, 0x01, 0x05, 0x05, "5"}, + {0x0A, 0x01, 0x05, 0x00, "6"}, + {0x0A, 0x01, 0x05, 0x04, "7"}, + + {0 , 0xfe, 0 , 2 , "Cabinet"}, + {0x0A, 0x01, 0x08, 0x08, "Upright"}, + {0x0A, 0x01, 0x08, 0x00, "Cocktail"}, + + {0 , 0xfe, 0 , 2 , "Coinage"}, + {0x0A, 0x01, 0x10, 0x00, "2 Coins 1 Credit"}, + {0x0A, 0x01, 0x10, 0x10, "1 Coin 1 Credit"}, + + {0 , 0xfe, 0 , 2 , "Gaming Options"}, + {0x0A, 0x01, 0x20, 0x20, "Number of Wrong Answer"}, + {0x0A, 0x01, 0x20, 0x00, "Number of Questions"}, + + {0 , 0xfe, 0 , 2 , "Show Correct Answer"}, + {0x0A, 0x01, 0x40, 0x00, "No"}, + {0x0A, 0x01, 0x40, 0x40, "Yes"}, +}; + +STDDIPINFO(Striv) + +static UINT8 timer_r(UINT32) +{ + return ZetTotalCycles() / timer_rate; +} + +static UINT8 soundlatch_r(UINT32) +{ + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return soundlatch; +} + +static UINT8 __fastcall striv_question_r(UINT16 offset) +{ + if((offset & 0xc00) == 0x800) + { + remap_address[offset & 0x0f] = (offset & 0xf0) >> 4; + } + else if((offset & 0xc00) == 0xc00) + { + question_rom = offset & 7; + question_address = (offset & 0xf8) << 7; + } + else + { + UINT8 *ROM = User; + INT32 real_address; + + real_address = question_address | (offset & 0x3f0) | remap_address[offset & 0x0f]; + + if(offset & 0x400) + real_address |= 0x8000 * (question_rom + 8); + else + real_address |= 0x8000 * question_rom; + + return ROM[real_address]; + } + + return 0; +} + +void jack_paletteram_w(UINT16 offset, UINT8 data) +{ + UINT32 *pl = Palette + (offset & 0x1f); + + Rom0[offset] = data; + + DrvCalcPal = 1; + + data ^= 0xff; + + *pl = ((data & 7) << 21) | ((data & 7) << 18) | ((data & 6) << 15); + + data >>= 3; + + *pl |= ((data & 7) << 13) | ((data & 7) << 10) | ((data & 6) << 7); + + data >>= 3; + + *pl |= ((data & 3) << 6) | ((data & 3) << 4) | ((data & 3) << 2) | (data & 3); +} + +UINT8 __fastcall jack_cpu0_read(UINT16 address) +{ + UINT8 ret = 0; + + switch (address) + { + case 0xb500: + return DrvDips[0]; + + case 0xb501: + { + ret = DrvDips[1]; + if (joinem && DrvJoy2[7] && !joinem_snd_bit) ret |= 0x20; + + return ret; + } + + case 0xb502: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy1[i] << i; + + return ret; + } + + case 0xb503: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy2[i] << i; + + return ret; + } + + case 0xb504: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy3[i] << i; + if (joinem || loverb) ret |= 0x40; + + return ret; + } + + case 0xb505: + { + for (INT32 i = 0; i < 8; i++) ret |= DrvJoy4[i] << i; + + return ret; + } + + case 0xb506: + case 0xb507: + flip_screen = (address & 1) ^ suprtriv; + return 0; + } + + if (suprtriv && address >= 0xc000 && address <= 0xcfff) { + return striv_question_r(address & 0x0fff); + } + + return 0; +} + +void __fastcall jack_cpu0_write(UINT16 address, UINT8 data) +{ + if (address >= 0xb600 && address <= 0xb61f) + { + jack_paletteram_w(address, data); + return; + } + + switch (address) + { + case 0xb400: + soundlatch = data; + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + break; + + case 0xb506: + flip_screen = 1; + break; + + case 0xb700: + flip_screen = data >> 7; + joinem_snd_bit = data & 1; + break; + } +} + +UINT8 __fastcall jack_in_port(UINT16 port) +{ + switch (port & 0xff) + { + case 0x40: + return AY8910Read(0); + } + + return 0; +} + +void __fastcall jack_out_port(UINT16 address, UINT8 data) +{ + switch (address & 0xff) + { + case 0x40: + AY8910Write(0, 1, data); + return; + + case 0x80: + AY8910Write(0, 0, data); + return; + } +} + +void __fastcall jack_cpu1_write() +{ +} + + +static INT32 DrvDoReset() +{ + flip_screen = 0; + DrvReset = 0; + soundlatch = 0; + + if (loverb || joinem) { + memset (Rom0 + 0x8000, 0, 0x1000); + } else { + memset ((UINT8*)Palette, 0, 0x400); + memset (Rom0 + 0x4000, 0, 0x1000); + } + + memset (Rom0 + 0xb000, 0, 0x1000); + memset (Rom1 + 0x4000, 0, 0x0400); + memset ((UINT8*)remap_address, 0, 0x40); + + question_address = question_rom = 0; + joinem_snd_bit = 0; + soundlatch = 0; + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + AY8910Reset(0); + + return 0; +} + +static INT32 GetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *Load0 = Rom0; + UINT8 *Load1 = Rom1; + UINT8 *Loadg = Gfx; + UINT8 *Loadt = User; + INT32 gCount = 0; + + if (!joinem && !loverb) Loadg += 0x2000; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (ri.nLen == 0x2000) + { + if (BurnLoadRom(Load0, i, 1)) return 1; + Load0 += ri.nLen; + } + else + { + if (BurnLoadRom(Load0, i, 1)) return 1; + Load0 += ri.nLen; + + if (tri_fix && i == 0) { + Load0 += 0x1000; + } + + if (i == (3 - tri_fix)) Load0 += 0x8000; + } + + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(Load1, i, 1)) return 1; + Load1 += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(Loadg, i, 1)) return 1; + Loadg += ri.nLen; + if (joinem) Loadg += 0x1000; + gCount++; + + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(Prom + 0x000, i + 0, 1)) return 1; + if (BurnLoadRom(Prom + 0x200, i + 1, 1)) return 1; + i++; + + // Roms are nibbles, (1/2 byte), #0 is low, #1 is high + for (INT32 j = 0; j < 0x200; j++) { + Prom[j] = Prom[j] | (Prom[j + 0x200] << 4); + } + + continue; + } + + if ((ri.nType & 7) == 5) { + if (BurnLoadRom(Loadt, i, 1)) return 1; + Loadt += ri.nLen; + + continue; + } + } + + // sucasino, tripool, tripoola + if (gCount == 2) { + memcpy (Gfx + 0x4000, Gfx + 0x3000, 0x1000); + memset (Gfx + 0x3000, 0, 0x1000); + } + + return 0; +} + +static void gfx_decode() +{ + UINT8* tmp = (UINT8*)BurnMalloc( 0x2000 * 3 ); + if (!tmp) return; + + memcpy (tmp, Gfx, 0x6000); + + static INT32 Planes[3] = { 0, 1024*8*8, 1024*8*8*2 }; + static INT32 YOffs[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + static INT32 XOffs[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + + GfxDecode(1024, 3, 8, 8, Planes, XOffs, YOffs, 64, tmp, Gfx); + + BurnFree (tmp); +} + +static INT32 DrvInit() +{ + Mem = (UINT8 *)BurnMalloc (0x100000); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)malloc (nBurnSoundLen * 3 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom0 = Mem + 0x00000; + Rom1 = Mem + 0x10000; + Gfx = Mem + 0x20000; + User = Mem + 0x30000; + Prom = Mem + 0xb0000; + Palette = (UINT32*)(Mem + 0xc0000); + DrvPal = (UINT32*)(Mem + 0xc1000); + + GetRoms(); + + gfx_decode(); + + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(jack_cpu0_read); + ZetSetWriteHandler(jack_cpu0_write); + + if (joinem || loverb) + { + ZetMapArea(0x0000, 0x8fff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0x8fff, 2, Rom0 + 0x0000); + + ZetMapArea(0x8000, 0x8fff, 1, Rom0 + 0x8000); + + ZetMapArea(0xb500, 0xb5ff, 0, Rom0 + 0xb500); // controls hack + } else { + ZetMapArea(0x0000, 0x3fff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0x3fff, 2, Rom0 + 0x0000); + + ZetMapArea(0x4000, 0x5fff, 0, Rom0 + 0x4000); + ZetMapArea(0x4000, 0x5fff, 1, Rom0 + 0x4000); + ZetMapArea(0x4000, 0x5fff, 2, Rom0 + 0x4000); + } + + ZetMapArea(0xb000, 0xb0ff, 0, Rom0 + 0xb000); + ZetMapArea(0xb000, 0xb0ff, 1, Rom0 + 0xb000); + + ZetMapArea(0xb800, 0xbbff, 0, Rom0 + 0xb800); + ZetMapArea(0xb800, 0xbbff, 1, Rom0 + 0xb800); + + ZetMapArea(0xbc00, 0xbfff, 0, Rom0 + 0xbc00); + ZetMapArea(0xbc00, 0xbfff, 1, Rom0 + 0xbc00); + + if (suprtriv) + { + ZetMapArea(0xd000, 0xffff, 0, Rom0 + 0xc000); + ZetMapArea(0xd000, 0xffff, 2, Rom0 + 0xc000); + } else { + ZetMapArea(0xc000, 0xffff, 0, Rom0 + 0xc000); + ZetMapArea(0xc000, 0xffff, 2, Rom0 + 0xc000); + } + + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetInHandler(jack_in_port); + ZetSetOutHandler(jack_out_port); + ZetMapArea(0x0000, 0x1fff, 0, Rom1 + 0x0000); + ZetMapArea(0x0000, 0x1fff, 2, Rom1 + 0x0000); + ZetMapArea(0x4000, 0x43ff, 0, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x43ff, 1, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x43ff, 2, Rom1 + 0x4000); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + AY8910Init(0, 1500000, nBurnSoundRate, &soundlatch_r, &timer_r, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + GenericTilesExit(); + + BurnFree (pFMBuffer); + BurnFree (Mem); + + DrvPal = Palette = NULL; + pFMBuffer = NULL; + Mem = Rom0 = Rom1 = Gfx = User = NULL; + pAY8910Buffer[0] = pAY8910Buffer[1] = pAY8910Buffer[2] = NULL; + + tri_fix = 0; + joinem = 0; + loverb = 0; + suprtriv = 0; + + return 0; +} + + +static INT32 DrvDraw() +{ + if (DrvCalcPal) + { + for (INT32 i = 0; i < 0x100; i++) { + UINT32 col = Palette[i]; + DrvPal[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + DrvCalcPal = 0; + } + + UINT8 *sram = Rom0 + 0xb000; // sprite ram + UINT8 *vram = Rom0 + 0xb800; // video ram + UINT8 *cram = Rom0 + 0xbc00; // color ram + INT32 offs, sx, sy, num, color, flipx, flipy; + + for (offs = 0; offs < 0x400; offs++) + { + sx = (offs & 0x1f) << 3; + sy = (offs >> 2) & 0xf8; + + if (joinem || loverb) { + num = vram[offs] + ((cram[offs] & 0x03) << 8); + color = (cram[offs] & 0x38) >> 2; + } else { + num = vram[offs] + ((cram[offs] & 0x18) << 5); + color = (cram[offs] & 0x07); + } + + if (flip_screen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, num, sx ^ 0xf8, sy ^ 0xf8, color, 2, 0, Gfx); + } else { + sx -= 16; + Render8x8Tile_Clip(pTransDraw, num, sx, sy, color, 2, 0, Gfx); + } + } + + for (offs = 0; offs < 0x80; offs += 4) + { + sx = 248 - sram[offs]; + sy = sram[offs + 1]; + + if (joinem || loverb) { + num = sram[offs + 2] + ((sram[offs + 3] & 0x01) << 8); + color = (sram[offs + 3] & 0x38) >> 2; + } else { + num = sram[offs + 2] + ((sram[offs + 3] & 0x08) << 5); + color = (sram[offs + 3] & 0x07); + } + + flipx = sram[offs + 3] & 0x40; + flipy = sram[offs + 3] & 0x80; + + if (flip_screen) { + flipx = !flipx; + flipy = !flipy; + sx = 248 - sx; + sy = 248 - sy; + } + + sx -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, num, sx, sy, color, 2, 0, 0, Gfx); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, num, sx, sy, color, 2, 0, 0, Gfx); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, num, sx, sy, color, 2, 0, 0, Gfx); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, num, sx, sy, color, 2, 0, 0, Gfx); + } + } + } + + BurnTransferCopy(DrvPal); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + if (joinem || loverb) { + for (INT32 i = 0; i < 6; i++) + Rom0[0xb500 + i] = jack_cpu0_read(0xb500 + i); + } + + INT32 nInterleave = 1000; + INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = 3000000 / 60; + nCyclesTotal[1] = 1500000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #0 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + if (joinem) + if (i == (nInterleave / 3) || i == ((nInterleave / 3) * 2)) + ZetRaiseIrq(0); + + if (tri_fix && i == (nInterleave / 2)) ZetRaiseIrq(0); + + if (i == (nInterleave - 1)) + { + if (joinem) { // joinem + if (!DrvJoy3[7]) ZetNmi(); + } else if (loverb) { // loverboy + ZetNmi(); + + } else { // other + ZetRaiseIrq(0); + } + } + + ZetClose(); + + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut && !suprtriv) { // disable sound for suprtriv + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut && !suprtriv) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +//------------------------------------------------------------------------------------- +// Save states + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + if (joinem || loverb) { + ba.Data = Rom0 + 0x8000; + } else { + ba.Data = Rom0 + 0x4000; + } + ba.nLen = 0x01000; + ba.szName = "Main Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom0 + 0xb000; + ba.nLen = 0x01000; + ba.szName = "Video Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = (UINT8*)Palette; + ba.nLen = 0x00400; + ba.szName = "Palette"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = (UINT8*)remap_address; + ba.nLen = 0x00040; + ba.szName = "striv question addresses"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(question_address); + SCAN_VAR(question_rom); + SCAN_VAR(soundlatch); + SCAN_VAR(joinem_snd_bit); + } + + return 0; +} + + +// Jack the Giantkiller (set 1) + +static struct BurnRomInfo jackRomDesc[] = { + { "j8", 0x1000, 0xc8e73998, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "jgk.j6", 0x1000, 0x36d7810e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jgk.j7", 0x1000, 0xb15ff3ee, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jgk.j5", 0x1000, 0x4a63d242, 1 | BRF_PRG | BRF_ESS }, // 3 + { "jgk.j3", 0x1000, 0x605514a8, 1 | BRF_PRG | BRF_ESS }, // 4 + { "jgk.j4", 0x1000, 0xbce489b7, 1 | BRF_PRG | BRF_ESS }, // 5 + { "jgk.j2", 0x1000, 0xdb21bd55, 1 | BRF_PRG | BRF_ESS }, // 6 + { "jgk.j1", 0x1000, 0x49fffe31, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "jgk.j9", 0x1000, 0xc2dc1e00, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "jgk.j12", 0x1000, 0xce726df0, 3 | BRF_GRA }, // 9 Graphics + { "jgk.j13", 0x1000, 0x6aec2c8d, 3 | BRF_GRA }, // 10 + { "jgk.j11", 0x1000, 0xfd14c525, 3 | BRF_GRA }, // 11 + { "jgk.j10", 0x1000, 0xeab890b2, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(jack) +STD_ROM_FN(jack) + +static INT32 jackInit() +{ + timer_rate = 128; + + return DrvInit(); +} + +struct BurnDriver BurnDrvjack = { + "jack", NULL, NULL, NULL, "1982", + "Jack the Giantkiller (set 1)\0", NULL, "Cinematronics", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, jackRomInfo, jackRomName, NULL, NULL, JackInputInfo, JackDIPInfo, + jackInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Jack the Giantkiller (set 2) + +static struct BurnRomInfo jack2RomDesc[] = { + { "jgk.j8", 0x1000, 0xfe229e20, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "jgk.j6", 0x1000, 0x36d7810e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jgk.j7", 0x1000, 0xb15ff3ee, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jgk.j5", 0x1000, 0x4a63d242, 1 | BRF_PRG | BRF_ESS }, // 3 + { "jgk.j3", 0x1000, 0x605514a8, 1 | BRF_PRG | BRF_ESS }, // 4 + { "jgk.j4", 0x1000, 0xbce489b7, 1 | BRF_PRG | BRF_ESS }, // 5 + { "jgk.j2", 0x1000, 0xdb21bd55, 1 | BRF_PRG | BRF_ESS }, // 6 + { "jgk.j1", 0x1000, 0x49fffe31, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "jgk.j9", 0x1000, 0xc2dc1e00, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "jgk.j12", 0x1000, 0xce726df0, 3 | BRF_GRA }, // 9 Graphics + { "jgk.j13", 0x1000, 0x6aec2c8d, 3 | BRF_GRA }, // 10 + { "jgk.j11", 0x1000, 0xfd14c525, 3 | BRF_GRA }, // 11 + { "jgk.j10", 0x1000, 0xeab890b2, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(jack2) +STD_ROM_FN(jack2) + +struct BurnDriver BurnDrvjack2 = { + "jack2", "jack", NULL, NULL, "1982", + "Jack the Giantkiller (set 2)\0", NULL, "Cinematronics", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, jack2RomInfo, jack2RomName, NULL, NULL, JackInputInfo, Jack2DIPInfo, + jackInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Jack the Giantkiller (set 3) + +static struct BurnRomInfo jack3RomDesc[] = { + { "jack8", 0x1000, 0x632151d2, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "jack6", 0x1000, 0xf94f80d9, 1 | BRF_PRG | BRF_ESS }, // 1 + { "jack7", 0x1000, 0xc830ff1e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "jack5", 0x1000, 0x8dea17e7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "jgk.j3", 0x1000, 0x605514a8, 1 | BRF_PRG | BRF_ESS }, // 4 // bank 2 + { "jgk.j4", 0x1000, 0xbce489b7, 1 | BRF_PRG | BRF_ESS }, // 5 + { "jgk.j2", 0x1000, 0xdb21bd55, 1 | BRF_PRG | BRF_ESS }, // 6 + { "jack1", 0x1000, 0x7e75ea3d, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "jgk.j9", 0x1000, 0xc2dc1e00, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "jack12", 0x1000, 0x80320647, 3 | BRF_GRA }, // 9 Graphics + { "jgk.j13", 0x1000, 0x6aec2c8d, 3 | BRF_GRA }, // 10 + { "jgk.j11", 0x1000, 0xfd14c525, 3 | BRF_GRA }, // 11 + { "jgk.j10", 0x1000, 0xeab890b2, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(jack3) +STD_ROM_FN(jack3) + +struct BurnDriver BurnDrvjack3 = { + "jack3", "jack", NULL, NULL, "1982", + "Jack the Giantkiller (set 3)\0", NULL, "Cinematronics", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, jack3RomInfo, jack3RomName, NULL, NULL, JackInputInfo, Jack3DIPInfo, + jackInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Treasure Hunt (bootleg?) + +static struct BurnRomInfo treahuntRomDesc[] = { + { "thunt-1.f2", 0x1000, 0x0b35858c, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "thunt-2.f3", 0x1000, 0x67305a51, 1 | BRF_PRG | BRF_ESS }, // 1 + { "thunt-3.4f", 0x1000, 0xd7a969c3, 1 | BRF_PRG | BRF_ESS }, // 2 + { "thunt-4.6f", 0x1000, 0x2483f14d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "thunt-5.7f", 0x1000, 0xc69d5e21, 1 | BRF_PRG | BRF_ESS }, // 4 + { "thunt-6.7e", 0x1000, 0x11bf3d49, 1 | BRF_PRG | BRF_ESS }, // 5 + { "thunt-7.6e", 0x1000, 0x7c2d6279, 1 | BRF_PRG | BRF_ESS }, // 6 + { "thunt-8.4e", 0x1000, 0xf73b86fb, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "jgk.j9", 0x1000, 0xc2dc1e00, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "thunt-13.a4", 0x1000, 0xe03f1f09, 3 | BRF_GRA }, // 9 Graphics + { "thunt-12.a3", 0x1000, 0xda4ee9eb, 3 | BRF_GRA }, // 10 + { "thunt-10.a1", 0x1000, 0x51ec7934, 3 | BRF_GRA }, // 11 + { "thunt-11.a2", 0x1000, 0xf9781143, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(treahunt) +STD_ROM_FN(treahunt) + +static void treahunt_decode() +{ + for (INT32 i = 0; i < 0x4000; i++) + { + if (i & 0x1000) + { + User[i] = BITSWAP08(Rom0[i], 0, 2, 5, 1, 3, 6, 4, 7); + + if (~i & 0x04) User[i] ^= 0x81; + } + else + { + User[i] = BITSWAP08(Rom0[i], 7, 2, 5, 1, 3, 6, 4, 0) ^ 0x81; + } + } + + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 2, User, Rom0); + ZetClose(); +} + +static INT32 treahuntInit() +{ + timer_rate = 128; + + INT32 nRet = DrvInit(); + + treahunt_decode(); + + return nRet; +} + +struct BurnDriver BurnDrvtreahunt = { + "treahunt", "jack", NULL, NULL, "1982", + "Treasure Hunt (bootleg?)\0", NULL, "Hara Industries", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, treahuntRomInfo, treahuntRomName, NULL, NULL, JackInputInfo, TreahuntDIPInfo, + treahuntInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Zzyzzyxx (set 1) + +static struct BurnRomInfo zzyzzyxxRomDesc[] = { + { "a.2f", 0x1000, 0xa9102e34, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "zzyzzyxx.b", 0x1000, 0xefa9d4c6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "zzyzzyxx.c", 0x1000, 0xb0a365b1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "zzyzzyxx.d", 0x1000, 0x5ed6dd9a, 1 | BRF_PRG | BRF_ESS }, // 3 + { "zzyzzyxx.e", 0x1000, 0x5966fdbf, 1 | BRF_PRG | BRF_ESS }, // 4 + { "f.7e", 0x1000, 0x12f24c68, 1 | BRF_PRG | BRF_ESS }, // 5 + { "g.6e", 0x1000, 0x408f2326, 1 | BRF_PRG | BRF_ESS }, // 6 + { "h.4e", 0x1000, 0xf8bbabe0, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "i.5a", 0x1000, 0xc7742460, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + { "j.6a", 0x1000, 0x72166ccd, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "n.1c", 0x1000, 0x4f64538d, 3 | BRF_GRA }, // 10 Graphics + { "m.1d", 0x1000, 0x217b1402, 3 | BRF_GRA }, // 11 + { "k.1b", 0x1000, 0xb8b2b8cc, 3 | BRF_GRA }, // 12 + { "l.1a", 0x1000, 0xab421a83, 3 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(zzyzzyxx) +STD_ROM_FN(zzyzzyxx) + +static INT32 zzyzzyxxInit() +{ + timer_rate = 16; + + return DrvInit(); +} + +struct BurnDriver BurnDrvzzyzzyxx = { + "zzyzzyxx", NULL, NULL, NULL, "1982", + "Zzyzzyxx (set 1)\0", NULL, "Cinematronics + Advanced Microcomputer Systems", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, zzyzzyxxRomInfo, zzyzzyxxRomName, NULL, NULL, ZzyzzyxxInputInfo, ZzyzzyxxDIPInfo, + zzyzzyxxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Zzyzzyxx (set 2) + +static struct BurnRomInfo zzyzzyx2RomDesc[] = { + { "a.2f", 0x1000, 0xa9102e34, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b.3f", 0x1000, 0x4277beab, 1 | BRF_PRG | BRF_ESS }, // 1 + { "c.4f", 0x1000, 0x72ac99e1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "d.6f", 0x1000, 0x7c7eec2b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "e.7f", 0x1000, 0xcffc4a68, 1 | BRF_PRG | BRF_ESS }, // 4 + { "f.7e", 0x1000, 0x12f24c68, 1 | BRF_PRG | BRF_ESS }, // 5 + { "g.6e", 0x1000, 0x408f2326, 1 | BRF_PRG | BRF_ESS }, // 6 + { "h.4e", 0x1000, 0xf8bbabe0, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "i.5a", 0x1000, 0xc7742460, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + { "j.6a", 0x1000, 0x72166ccd, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "n.1c", 0x1000, 0x4f64538d, 3 | BRF_GRA }, // 10 Graphics + { "m.1d", 0x1000, 0x217b1402, 3 | BRF_GRA }, // 11 + { "k.1b", 0x1000, 0xb8b2b8cc, 3 | BRF_GRA }, // 12 + { "l.1a", 0x1000, 0xab421a83, 3 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(zzyzzyx2) +STD_ROM_FN(zzyzzyx2) + +struct BurnDriver BurnDrvzzyzzyx2 = { + "zzyzzyxx2", "zzyzzyxx", NULL, NULL, "1982", + "Zzyzzyxx (set 2)\0", NULL, "Cinematronics + Advanced Microcomputer Systems", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, zzyzzyx2RomInfo, zzyzzyx2RomName, NULL, NULL, ZzyzzyxxInputInfo, ZzyzzyxxDIPInfo, + zzyzzyxxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Brix + +static struct BurnRomInfo brixRomDesc[] = { + { "a", 0x1000, 0x050e0d70, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b", 0x1000, 0x668118ae, 1 | BRF_PRG | BRF_ESS }, // 1 + { "c", 0x1000, 0xff5ed6cf, 1 | BRF_PRG | BRF_ESS }, // 2 + { "d", 0x1000, 0xc3ae45a9, 1 | BRF_PRG | BRF_ESS }, // 3 + { "e", 0x1000, 0xdef99fa9, 1 | BRF_PRG | BRF_ESS }, // 4 + { "f", 0x1000, 0xdde717ed, 1 | BRF_PRG | BRF_ESS }, // 5 + { "g", 0x1000, 0xadca02d8, 1 | BRF_PRG | BRF_ESS }, // 6 + { "h", 0x1000, 0xbc3b878c, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "i.5a", 0x1000, 0xc7742460, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + { "j.6a", 0x1000, 0x72166ccd, 2 | BRF_PRG | BRF_ESS }, // 9 + + { "n", 0x1000, 0x8064910e, 3 | BRF_GRA }, // 10 Graphics + { "m.1d", 0x1000, 0x217b1402, 3 | BRF_GRA }, // 11 + { "k", 0x1000, 0xc7d7e2a0, 3 | BRF_GRA }, // 12 + { "l.1a", 0x1000, 0xab421a83, 3 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(brix) +STD_ROM_FN(brix) + +struct BurnDriver BurnDrvbrix = { + "brix", "zzyzzyxx", NULL, NULL, "1982", + "Brix\0", NULL, "Cinematronics + Advanced Microcomputer Systems", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, brixRomInfo, brixRomName, NULL, NULL, ZzyzzyxxInputInfo, ZzyzzyxxDIPInfo, + zzyzzyxxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Freeze + +static struct BurnRomInfo freezeRomDesc[] = { + { "freeze.f2", 0x1000, 0x0a431665, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "freeze.f3", 0x1000, 0x1189b8ad, 1 | BRF_PRG | BRF_ESS }, // 1 + { "freeze.f4", 0x1000, 0x10c4a5ea, 1 | BRF_PRG | BRF_ESS }, // 2 + { "freeze.f5", 0x1000, 0x16024c53, 1 | BRF_PRG | BRF_ESS }, // 3 + { "freeze.f7", 0x1000, 0xea0b0765, 1 | BRF_PRG | BRF_ESS }, // 4 + { "freeze.e7", 0x1000, 0x1155c00b, 1 | BRF_PRG | BRF_ESS }, // 5 + { "freeze.e5", 0x1000, 0x95c18d75, 1 | BRF_PRG | BRF_ESS }, // 6 + { "freeze.e4", 0x1000, 0x7e8f5afc, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "freeze.a1", 0x1000, 0x7771f5b9, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "freeze.5a", 0x1000, 0x6c8a98a0, 3 | BRF_GRA }, // 9 Graphics + { "freeze.3a", 0x1000, 0x6d2125e4, 3 | BRF_GRA }, // 10 + { "freeze.1a", 0x1000, 0x3a7f2fa9, 3 | BRF_GRA }, // 11 + { "freeze.2a", 0x1000, 0xdd70ddd6, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(freeze) +STD_ROM_FN(freeze) + +struct BurnDriver BurnDrvfreeze = { + "freeze", NULL, NULL, NULL, "1984", + "Freeze\0", NULL, "Cinematronics", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, freezeRomInfo, freezeRomName, NULL, NULL, FreezeInputInfo, FreezeDIPInfo, + jackInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Super Casino + +static struct BurnRomInfo sucasinoRomDesc[] = { + { "1", 0x1000, 0xe116e979, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "2", 0x1000, 0x2a2635f5, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3", 0x1000, 0x69864d90, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4", 0x1000, 0x174c9373, 1 | BRF_PRG | BRF_ESS }, // 3 + { "5", 0x1000, 0x115bcb1e, 1 | BRF_PRG | BRF_ESS }, // 4 + { "6", 0x1000, 0x434caa17, 1 | BRF_PRG | BRF_ESS }, // 5 + { "7", 0x1000, 0x67c68b82, 1 | BRF_PRG | BRF_ESS }, // 6 + { "8", 0x1000, 0xf5b63006, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "9", 0x1000, 0x67cf8aec, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 #1 Code + + { "11", 0x1000, 0xf92c4c5b, 3 | BRF_GRA }, // 9 Graphics + { "10", 0x1000, 0x3b0783ce, 3 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(sucasino) +STD_ROM_FN(sucasino) + +struct BurnDriver BurnDrvsucasino = { + "sucasino", NULL, NULL, NULL, "1984", + "Super Casino\0", NULL, "Data Amusement", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_CASINO, 0, + NULL, sucasinoRomInfo, sucasinoRomName, NULL, NULL, SucasinoInputInfo, SucasinoDIPInfo, + jackInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Tri-Pool (Casino Tech) + +static struct BurnRomInfo tripoolRomDesc[] = { + { "tri73a.bin", 0x1000, 0x96893aa7, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tri62a.bin", 0x1000, 0x3299dc65, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tri52b.bin", 0x1000, 0x27ef765e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tri33c.bin", 0x1000, 0xd7ef061d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "tri45c.bin", 0x1000, 0x51b813b1, 1 | BRF_PRG | BRF_ESS }, // 4 + { "tri25d.bin", 0x1000, 0x8e64512d, 1 | BRF_PRG | BRF_ESS }, // 5 + { "tri13d.bin", 0x1000, 0xad268e9b, 1 | BRF_PRG | BRF_ESS }, // 6 + + { "trisnd.bin", 0x1000, 0x945c4b8b, 2 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + + { "tri105a.bin", 0x1000, 0x366a753c, 3 | BRF_GRA }, // 8 Graphics + { "tri93a.bin", 0x1000, 0x35213782, 3 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(tripool) +STD_ROM_FN(tripool) + +static INT32 tripoolInit() +{ + tri_fix = 1; + timer_rate = 128; + + return DrvInit(); +} + +struct BurnDriver BurnDrvtripool = { + "tripool", NULL, NULL, NULL, "1981", + "Tri-Pool (Casino Tech)\0", NULL, "Noma (Casino Tech license)", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, tripoolRomInfo, tripoolRomName, NULL, NULL, TripoolInputInfo, NULL, + tripoolInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Tri-Pool (Costal Games) + +static struct BurnRomInfo tripoolaRomDesc[] = { + { "tri73a.bin", 0x1000, 0x96893aa7, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tri62a.bin", 0x1000, 0x3299dc65, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tri52b.bin", 0x1000, 0x27ef765e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tri33c.bin", 0x1000, 0xd7ef061d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "tri45c.bin", 0x1000, 0x51b813b1, 1 | BRF_PRG | BRF_ESS }, // 4 + { "tri25d.bin", 0x1000, 0x8e64512d, 1 | BRF_PRG | BRF_ESS }, // 5 + { "tp1ckt", 0x1000, 0x72ec43a3, 1 | BRF_PRG | BRF_ESS }, // 6 + + { "trisnd.bin", 0x1000, 0x945c4b8b, 2 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + + { "tri105a.bin", 0x1000, 0x366a753c, 3 | BRF_GRA }, // 8 Graphics + { "tri93a.bin", 0x1000, 0x35213782, 3 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(tripoola) +STD_ROM_FN(tripoola) + +struct BurnDriver BurnDrvtripoola = { + "tripoola", "tripool", NULL, NULL, "1981", + "Tri-Pool (Costal Games)\0", NULL, "Noma (Costal Games license)", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, tripoolaRomInfo, tripoolaRomName, NULL, NULL, TripoolInputInfo, NULL, + tripoolInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + +// Joinem + +static struct BurnRomInfo joinemRomDesc[] = { + { "join1.r0", 0x2000, 0xb5b2e2cc, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "join2.r2", 0x2000, 0xbcf140e6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "join3.r4", 0x2000, 0xfe04e4d4, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "join7.s0", 0x1000, 0xbb8a7814, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "join4.p3", 0x1000, 0x4964c82c, 3 | BRF_GRA }, // 4 Graphics + { "join5.p2", 0x1000, 0xae78fa89, 3 | BRF_GRA }, // 5 + { "join6.p1", 0x1000, 0x2b533261, 3 | BRF_GRA }, // 6 + + { "l82s129.11n", 0x0100, 0x7b724211, 4 | BRF_GRA }, // 7 Color Proms + { "h82s129.12n", 0x0100, 0x2e81c5ff, 4 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(joinem) +STD_ROM_FN(joinem) + +static void joinem_palette_init() +{ + for (INT32 i = 0; i < 0x100; i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (Prom[i] >> 0) & 1; + bit1 = (Prom[i] >> 1) & 1; + bit2 = (Prom[i] >> 2) & 1; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 1; + bit1 = (Prom[i] >> 4) & 1; + bit2 = (Prom[i] >> 5) & 1; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (Prom[i] >> 6) & 1; + bit2 = (Prom[i] >> 7) & 1; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 joinemInit() +{ + joinem = 1; + timer_rate = 16; + + INT32 nRet = DrvInit(); + + joinem_palette_init(); + + return nRet; +} + +struct BurnDriver BurnDrvjoinem = { + "joinem", NULL, NULL, NULL, "1986", + "Joinem\0", NULL, "Global Corporation", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, joinemRomInfo, joinemRomName, NULL, NULL, JoinemInputInfo, JoinemDIPInfo, + joinemInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 240, 3, 4 +}; + + +// Lover Boy + +static struct BurnRomInfo loverboyRomDesc[] = { + { "lover.r0", 0x2000, 0xffec4e41, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "lover.r2", 0x2000, 0x04052262, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lover.r4", 0x2000, 0xce5f3b49, 1 | BRF_PRG | BRF_ESS }, // 2 + { "lover.r6", 0x1000, 0x839d79b7, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "lover.s0", 0x1000, 0xec38111c, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + + { "lover.p3", 0x2000, 0x1a519c8f, 3 | BRF_GRA }, // 5 Graphics + { "lover.p2", 0x2000, 0xe465372f, 3 | BRF_GRA }, // 6 + { "lover.p1", 0x2000, 0xcda0d87e, 3 | BRF_GRA }, // 7 + + { "color.n11", 0x0200, 0xcf4a16ae, 4 | BRF_GRA }, // 8 Color Proms + { "color.n12", 0x0200, 0x4b11ac21, 4 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(loverboy) +STD_ROM_FN(loverboy) + +static INT32 loverboyInit() +{ + loverb = 1; + timer_rate = 16; + + INT32 nRet = DrvInit(); + + // Hack (Protection?) + Rom0[0x12] = 0x9d; + Rom0[0x13] = 0x01; + + joinem_palette_init(); + + return nRet; +} + +struct BurnDriver BurnDrvloverboy = { + "loverboy", NULL, NULL, NULL, "1983", + "Lover Boy\0", "No sound", "G.T Enterprise Inc", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, loverboyRomInfo, loverboyRomName, NULL, NULL, LoverboyInputInfo, LoverboyDIPInfo, + loverboyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 240, 3, 4 +}; + + +// Super Triv + +static struct BurnRomInfo strivRomDesc[] = { + { "pr1.f2", 0x1000, 0xdcf5da6e, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "pr2.4f", 0x1000, 0x921610ba, 1 | BRF_PRG | BRF_ESS }, // 1 + { "pr3.5f", 0x1000, 0xc36f0e21, 1 | BRF_PRG | BRF_ESS }, // 2 + { "pr4.6f", 0x1000, 0x0dc98a97, 1 | BRF_PRG | BRF_ESS }, // 3 + { "bc3.7e", 0x1000, 0x83f03885, 1 | BRF_PRG | BRF_ESS }, // 4 + { "bc2.6e", 0x1000, 0x75f18361, 1 | BRF_PRG | BRF_ESS }, // 5 + { "bc1.5e", 0x1000, 0x0d150385, 1 | BRF_PRG | BRF_ESS }, // 6 + + { "snd.5a", 0x1000, 0xb7ddf84f, 2 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + + { "chr0.1a", 0x1000, 0x8f60229b, 3 | BRF_GRA }, // 8 Graphics + { "chr2.4a", 0x1000, 0x8f982a9c, 3 | BRF_GRA }, // 9 + { "chr3.5a", 0x1000, 0x8f982a9c, 3 | BRF_GRA }, // 10 + { "chr1.2a", 0x1000, 0x7ad4358e, 3 | BRF_GRA }, // 11 + + { "rom.u6", 0x8000, 0xa32d7a28, 5 | BRF_PRG | BRF_ESS }, // 12 Question ROMs + { "rom.u7", 0x8000, 0xbc44ae18, 5 | BRF_PRG | BRF_ESS }, // 13 + { "tbfd2.u8", 0x8000, 0x9572984a, 5 | BRF_PRG | BRF_ESS }, // 14 + { "tbfd3.u9", 0x8000, 0xd904a2f1, 5 | BRF_PRG | BRF_ESS }, // 15 + { "tbfl0.u10", 0x8000, 0x680264a2, 5 | BRF_PRG | BRF_ESS }, // 16 + { "tbfl1.u11", 0x8000, 0x33e99d00, 5 | BRF_PRG | BRF_ESS }, // 17 + { "tbfl2.u12", 0x8000, 0x2e7a941f, 5 | BRF_PRG | BRF_ESS }, // 18 + { "tbft0.u13", 0x8000, 0x7d2e5e89, 5 | BRF_PRG | BRF_ESS }, // 19 + { "tbft1.u14", 0x8000, 0xd36246cf, 5 | BRF_PRG | BRF_ESS }, // 20 + { "tbfd1.u15", 0x8000, 0x745db398, 5 | BRF_PRG | BRF_ESS }, // 21 + + { "tbfd0.u21", 0x2000, 0x15b83099, 0 | BRF_OPT }, // 22 Junk +}; + +STD_ROM_PICK(striv) +STD_ROM_FN(striv) + +static INT32 strivInit() +{ + suprtriv = 1; + timer_rate = 128; + + INT32 nRet = DrvInit(); + + for (INT32 i = 0; i < 0x4000; i++) + { + if (i & 0x1000) + { + if (i & 4) + Rom0[i] = BITSWAP08(Rom0[i],7,2,5,1,3,6,4,0) ^ 1; + else + Rom0[i] = BITSWAP08(Rom0[i],0,2,5,1,3,6,4,7) ^ 0x81; + } + else + { + if (i & 4) + Rom0[i] = BITSWAP08(Rom0[i],7,2,5,1,3,6,4,0) ^ 1; + else + Rom0[i] = BITSWAP08(Rom0[i],0,2,5,1,3,6,4,7); + } + } + + return nRet; +} + +struct BurnDriver BurnDrvstriv = { + "striv", NULL, NULL, NULL, "1985", + "Super Triv\0", "No sound", "Hara Industries", "Jack the Giantkiller", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_QUIZ, 0, + NULL, strivRomInfo, strivRomName, NULL, NULL, StrivInputInfo, StrivDIPInfo, + strivInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvCalcPal, 0x100, + 224, 256, 3, 4 +}; + + diff --git a/src/burn/drivers/misc_pre90s/d_kangaroo.cpp b/src/burn/drivers/misc_pre90s/d_kangaroo.cpp new file mode 100644 index 00000000..c3c89915 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_kangaroo.cpp @@ -0,0 +1,752 @@ + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd, *AllRAM; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvGfxROM; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static UINT32 *DrvVidRAM32; + +static INT16* pAY8910Buffer[3]; +static INT16 *pFMBuffer; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static UINT8 kangaroo_clock; +static UINT8 soundlatch; +static UINT8 *DrvVidControl; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy2 + 0, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 1, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 3, "p2 left" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 1"}, + + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag" }, + {"Reset" , BIT_DIGITAL ,&DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Music" }, + {0x10, 0x01, 0x20, 0x20, "Off" }, + {0x10, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x00, "Upright" }, + {0x10, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x10, 0x01, 0x80, 0x00, "Off" }, + {0x10, 0x01, 0x80, 0x80, "On" }, + + // Default Values + {0x11, 0xff, 0xff, 0x00, NULL }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x01, 0x00, "3" }, + {0x11, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x02, 0x00, "Easy" }, + {0x11, 0x01, 0x02, 0x02, "Hard" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x11, 0x01, 0x0c, 0x08, "10000 30000" }, + {0x11, 0x01, 0x0c, 0x0c, "20000 40000" }, + {0x11, 0x01, 0x0c, 0x04, "10000" }, + {0x11, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 0x10, "Coinage" }, + {0x11, 0x01, 0xf0, 0x10, "2C_1C" }, + {0x11, 0x01, 0xf0, 0x20, "A 2C/1C B 1C/3C" }, + {0x11, 0x01, 0xf0, 0x00, "1C_1C" }, + {0x11, 0x01, 0xf0, 0x30, "A 1C/1C B 1C/2C" }, + {0x11, 0x01, 0xf0, 0x40, "A 1C/1C B 1C/3C" }, + {0x11, 0x01, 0xf0, 0x50, "A 1C/1C B 1C/4C" }, + {0x11, 0x01, 0xf0, 0x60, "A 1C/1C B 1C/5C" }, + {0x11, 0x01, 0xf0, 0x70, "A 1C/1C B 1C/6C" }, + {0x11, 0x01, 0xf0, 0x80, "1C_2C" }, + {0x11, 0x01, 0xf0, 0x90, "A 1C/2C B 1C/4C" }, + {0x11, 0x01, 0xf0, 0xa0, "A 1C/2C B 1C/5C" }, + {0x11, 0x01, 0xf0, 0xe0, "A 1C/2C B 1C/6C" }, + {0x11, 0x01, 0xf0, 0xb0, "A 1C/2C B 1C/10C" }, + {0x11, 0x01, 0xf0, 0xc0, "A 1C/2C B 1C/11C" }, + {0x11, 0x01, 0xf0, 0xd0, "A 1C/2C B 1C/12C" }, + {0x11, 0x01, 0xf0, 0xf0, "Free_Play" }, +}; + +STDDIPINFO(Drv) + + +static void videoram_write(UINT16 offset, UINT8 data, UINT8 mask) +{ + UINT32 expdata, layermask; + + // data contains 4 2-bit values packed as DCBADCBA; expand these into 4 8-bit values + expdata = 0; + if (data & 0x01) expdata |= 0x00000055; + if (data & 0x10) expdata |= 0x000000aa; + if (data & 0x02) expdata |= 0x00005500; + if (data & 0x20) expdata |= 0x0000aa00; + if (data & 0x04) expdata |= 0x00550000; + if (data & 0x40) expdata |= 0x00aa0000; + if (data & 0x08) expdata |= 0x55000000; + if (data & 0x80) expdata |= 0xaa000000; + + // determine which layers are enabled + layermask = 0; + if (mask & 0x08) layermask |= 0x30303030; + if (mask & 0x04) layermask |= 0xc0c0c0c0; + if (mask & 0x02) layermask |= 0x03030303; + if (mask & 0x01) layermask |= 0x0c0c0c0c; + + // update layers + DrvVidRAM32[offset] = (DrvVidRAM32[offset] & ~layermask) | (expdata & layermask); +} + +static void blitter_execute() +{ + UINT16 src = DrvVidControl[0] | (DrvVidControl[1] << 8); + UINT16 dst = DrvVidControl[2] | (DrvVidControl[3] << 8); + UINT8 height = DrvVidControl[5]; + UINT8 width = DrvVidControl[4]; + UINT8 mask = DrvVidControl[8]; + + // during DMA operations, the top 2 bits are ORed together, as well as the bottom 2 bits + // adjust the mask to account for this + mask |= ((mask & 0x41) << 1) | ((mask & 0x82) >> 1); + + // loop over height, then width + for (INT32 y = 0; y <= height; y++, dst += 256) { + for (INT32 x = 0; x <= width; x++) { + UINT16 effdst = (dst + x) & 0x3fff; + UINT16 effsrc = src++ & 0x1fff; + videoram_write(effdst, DrvGfxROM[0x0000 + effsrc], mask & 0x05); + videoram_write(effdst, DrvGfxROM[0x2000 + effsrc], mask & 0x0a); + } + } +} + +void __fastcall kangaroo_main_write(UINT16 address, UINT8 data) +{ + if (address >= 0x8000 && address <= 0xbfff) { + videoram_write(address & 0x3fff, data, DrvVidControl[8]); + return; + } + + if ((address & 0xec00) == 0xe800) address &= 0xfc0f; + if ((address & 0xec00) == 0xec00) address &= 0xff00; + + switch (address) + { + case 0xe800: + case 0xe801: + case 0xe802: + case 0xe803: + case 0xe804: + DrvVidControl[address & 0x0f] = data; + return; + + case 0xe805: + DrvVidControl[address & 0x0f] = data; + + blitter_execute(); + return; + + case 0xe806: + case 0xe807: + DrvVidControl[address & 0x0f] = data; + return; + + case 0xe808: + DrvVidControl[address & 0x0f] = data; + + ZetMapArea(0xc000, 0xdfff, 0, DrvGfxROM + ((data & 0x05) ? 0 : 0x2000)); + return; + + case 0xe809: + case 0xe80a: + DrvVidControl[address & 0x0f] = data; + return; + + case 0xec00: + soundlatch = data; + return; + + case 0xed00: + // coin counter + return; + } + + + + if (address > 0x5fff) bprintf (PRINT_NORMAL, _T("%4.4x, %2.2x wm\n"), address, data); + + return; +} + +UINT8 __fastcall kangaroo_main_read(UINT16 address) +{ + if ((address & 0xec00) == 0xe400) address &= 0xfc00; + if ((address & 0xec00) == 0xec00) address &= 0xff00; + + switch (address) + { + case 0xe400: + return DrvDips[1]; + + case 0xec00: // in0 + { + UINT8 ret = DrvDips[0]; + if (DrvJoy1[7]) ret |= 0x01; // service + if (DrvJoy1[1]) ret |= 0x02; + if (DrvJoy2[1]) ret |= 0x04; + if (DrvJoy1[0]) ret |= 0x08; + if (DrvJoy2[0]) ret |= 0x10; + return ret; + } + + case 0xed00: // in1 + { + UINT8 ret = 0; + if (DrvJoy1[2]) ret |= 0x01; + if (DrvJoy1[3]) ret |= 0x02; + if (DrvJoy1[4]) ret |= 0x04; + if (DrvJoy1[5]) ret |= 0x08; + if (DrvJoy1[6]) ret |= 0x10; + // if (DrvJoy1[7]) ret |= 0x80; // service? + return ret; + } + + + case 0xee00: // in2 + { + UINT8 ret = 0; + if (DrvJoy2[2]) ret |= 0x01; + if (DrvJoy2[3]) ret |= 0x02; + if (DrvJoy2[4]) ret |= 0x04; + if (DrvJoy2[5]) ret |= 0x08; + if (DrvJoy2[6]) ret |= 0x10; + return ret; + } + + case 0xef00: + return ++kangaroo_clock & 0x0f; + } + + bprintf (PRINT_NORMAL, _T("%4.4x, rm\n"), address); + + return 0; +} + +UINT8 __fastcall kangaroo_sound_read(UINT16 address) +{ + switch (address & 0xf000) + { + case 0x6000: + return soundlatch; + } + + bprintf (PRINT_NORMAL, _T("%4.4x, rs\n"), address); + + return 0; +} + +void __fastcall kangaroo_sound_write(UINT16 address, UINT8 data) +{ + switch (address & 0xf000) + { + case 0x7000: + AY8910Write(0, 1, data); + return; + + case 0x8000: + AY8910Write(0, 0, data); + return; + } + + bprintf (PRINT_NORMAL, _T("%4.4x, %2.2x ws\n"), address, data); + + return; +} + +static INT32 MemIndex() +{ + UINT8 *Next; + + Next = Mem; Next += 0x10000; // buffer + + DrvZ80ROM0 = Next; Next += 0x06000; + DrvZ80ROM1 = Next; Next += 0x01000; + DrvGfxROM = Next; Next += 0x04000; + + Palette = (UINT32*)Next; Next += 0x00008 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00008 * sizeof(UINT32); + + AllRAM = Next; + + DrvZ80RAM0 = Next; Next += 0x00400; + DrvZ80RAM1 = Next; Next += 0x00400; + + DrvVidRAM32 = (UINT32*)Next; Next += 0x4000 * sizeof(UINT32); + + DrvVidControl = Next; Next += 16; + + pFMBuffer = (INT16 *)Next; Next += nBurnSoundLen * 3 * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRAM, 0, MemEnd - AllRAM); + + ZetOpen(0); + ZetReset(); + ZetNmi(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + soundlatch = 0; + kangaroo_clock = 0; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 3; i++) + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + + // kangaroo + if (strncmp ("kangaro", BurnDrvGetTextA(DRV_NAME), 7) == 0) + { + for (INT32 i = 0; i < 6; i++) + if (BurnLoadRom(DrvZ80ROM0 + i * 0x1000, 0 + i, 0)) return 1; + + if (BurnLoadRom(DrvZ80ROM1, 6, 0)) return 1; + + for (INT32 i = 0; i < 4; i++) + if (BurnLoadRom(DrvGfxROM + i * 0x1000, 7 + i, 0)) return 1; + } + // funkyfish + else + { + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvZ80ROM0 + i * 0x1000, 0 + i, 0)) return 1; + if (BurnLoadRom(DrvGfxROM + i * 0x1000, 5 + i, 0)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM1, 4, 0)) return 1; + } + + for (INT32 i = 0; i < 8; i++) + Palette[i] = ((i & 4 ? 0xff : 0) << 16) | ((i & 2 ? 0xff : 0) << 8) | (i & 1 ? 0xff : 0); + + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM0); + + ZetMapArea(0xc000, 0xdfff, 0, DrvGfxROM ); // Gfx are banked here + + ZetMapArea(0xe000, 0xe3ff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe3ff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe3ff, 2, DrvZ80RAM0); + + ZetSetWriteHandler(kangaroo_main_write); + ZetSetReadHandler(kangaroo_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x0fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x0fff, 2, DrvZ80ROM1); + + // mirrored 4x + ZetMapArea(0x4000, 0x43ff, 0, DrvZ80RAM1); + ZetMapArea(0x4000, 0x43ff, 1, DrvZ80RAM1); + ZetMapArea(0x4000, 0x43ff, 2, DrvZ80RAM1); + + ZetSetWriteHandler(kangaroo_sound_write); + ZetSetReadHandler(kangaroo_sound_read); + ZetSetInHandler(kangaroo_sound_read); + ZetSetOutHandler(kangaroo_sound_write); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1250000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnFree (Mem); + + GenericTilesExit(); + ZetExit(); + AY8910Exit(0); + + return 0; +} + + +static INT32 DrvDraw() +{ + UINT8 scrolly = DrvVidControl[6]; + UINT8 scrollx = DrvVidControl[7]; + UINT8 maska = (DrvVidControl[10] & 0x28) >> 3; + UINT8 maskb = (DrvVidControl[10] & 0x07) >> 0; + UINT8 xora = (DrvVidControl[9] & 0x20) ? 0xff : 0x00; + UINT8 xorb = (DrvVidControl[9] & 0x10) ? 0xff : 0x00; + UINT8 enaa = (DrvVidControl[9] & 0x08); + UINT8 enab = (DrvVidControl[9] & 0x04); + UINT8 pria = (~DrvVidControl[9] & 0x02); + UINT8 prib = (~DrvVidControl[9] & 0x01); + INT32 x, y; + + if (DrvRecalc) { + for (x = 0; x < 8; x++) { + UINT32 col = Palette[x]; + DrvPalette[x] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + // iterate over pixels + for (y = 0; y < nScreenHeight; y++) + { + UINT16 *dest = pTransDraw + (y * nScreenWidth); + + for (x = 0; x < nScreenWidth; x += 2) + { + UINT8 effxa = scrollx + ((x / 2) ^ xora); + UINT8 effya = scrolly + (y ^ xora); + UINT8 effxb = (x / 2) ^ xorb; + UINT8 effyb = y ^ xorb; + UINT8 pixa = (DrvVidRAM32[effya + 256 * (effxa / 4)] >> (8 * (effxa % 4) + 0)) & 0x0f; + UINT8 pixb = (DrvVidRAM32[effyb + 256 * (effxb / 4)] >> (8 * (effxb % 4) + 4)) & 0x0f; + UINT8 finalpens; + + // for each layer, contribute bits if (a) enabled, and (b) either has priority or the opposite plane is 0 + finalpens = 0; + if (enaa && (pria || pixb == 0)) + finalpens |= pixa; + if (enab && (prib || pixa == 0)) + finalpens |= pixb; + + // store the first of two pixels, which is always full brightness + dest[x + 0] = finalpens & 7; + + // KOS1 alternates at 5MHz, offset from the pixel clock by 1/2 clock + // when 0, it enables the color mask for pixels with Z = 0 + finalpens = 0; + if (enaa && (pria || pixb == 0)) + { + if (!(pixa & 0x08)) pixa &= maska; + finalpens |= pixa; + } + if (enab && (prib || pixa == 0)) + { + if (!(pixb & 0x08)) pixb &= maskb; + finalpens |= pixb; + } + + // store the second of two pixels, which is affected by KOS1 and the A/B masks + dest[x + 1] = finalpens & 7; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 2500000 / 60, 1250000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1)) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1)) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + ZetClose(); + +/* ZetOpen(0); + nCyclesDone[0] -= ZetRun(nCyclesDone[0] / (nInterleave - i)); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + // Run Z80 #1 + ZetOpen(1); + nCyclesDone[1] -= ZetRun(nCyclesDone[1] / (nInterleave - i)); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose();*/ + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +// Funky Fish + +static struct BurnRomInfo fnkyfishRomDesc[] = { + { "tvg_64.0", 0x1000, 0xaf728803, 1 | BRF_ESS | BRF_PRG }, // 0 Main Z80 Code + { "tvg_65.1", 0x1000, 0x71959e6b, 1 | BRF_ESS | BRF_PRG }, // 1 + { "tvg_66.2", 0x1000, 0x5ccf68d4, 1 | BRF_ESS | BRF_PRG }, // 2 + { "tvg_67.3", 0x1000, 0x938ff36f, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "tvg_68.8", 0x1000, 0xd36bb2be, 2 | BRF_ESS | BRF_PRG }, // 4 Sound Z80 Code + + { "tvg_69.v0", 0x1000, 0xcd532d0b, 3 | BRF_GRA }, // 5 Graphics + { "tvg_71.v2", 0x1000, 0xa59c9713, 3 | BRF_GRA }, // 6 + { "tvg_70.v1", 0x1000, 0xfd308ef1, 3 | BRF_GRA }, // 7 + { "tvg_72.v3", 0x1000, 0x6ae9b584, 3 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(fnkyfish) +STD_ROM_FN(fnkyfish) + +struct BurnDriver BurnDrvfnkyfish = { + "fnkyfish", NULL, NULL, NULL, "1981", + "Funky Fish\0", NULL, "Sun Electronics", "Kangaroo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, fnkyfishRomInfo, fnkyfishRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, + &DrvRecalc, 0x08, 256, 512, 3, 4 +}; + + +// Kangaroo + +static struct BurnRomInfo kangarooRomDesc[] = { + { "tvg_75.0", 0x1000, 0x0d18c581, 1 | BRF_ESS | BRF_PRG }, // 0 Main Z80 Code + { "tvg_76.1", 0x1000, 0x5978d37a, 1 | BRF_ESS | BRF_PRG }, // 1 + { "tvg_77.2", 0x1000, 0x522d1097, 1 | BRF_ESS | BRF_PRG }, // 2 + { "tvg_78.3", 0x1000, 0x063da970, 1 | BRF_ESS | BRF_PRG }, // 3 + { "tvg_79.4", 0x1000, 0x9e5cf8ca, 1 | BRF_ESS | BRF_PRG }, // 4 + { "tvg_80.5", 0x1000, 0x2fc18049, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "tvg_81.8", 0x1000, 0xfb449bfd, 2 | BRF_ESS | BRF_PRG }, // 6 Sound Z80 Code + + { "tvg_83.v0", 0x1000, 0xc0446ca6, 3 | BRF_GRA }, // 7 Graphics + { "tvg_85.v2", 0x1000, 0x72c52695, 3 | BRF_GRA }, // 8 + { "tvg_84.v1", 0x1000, 0xe4cb26c2, 3 | BRF_GRA }, // 9 + { "tvg_86.v3", 0x1000, 0x9e6a599f, 3 | BRF_GRA }, // 10 + + { "tvg_82.12", 0x0800, 0x57766f69, 0 | BRF_ESS | BRF_PRG }, // 11 MB8841 custom microcontroller data (unused) + + { "mb8841.ic29", 0x0800, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, // 12 MB8841 custom microcontroller prg (unused) +}; + +STD_ROM_PICK(kangaroo) +STD_ROM_FN(kangaroo) + +struct BurnDriver BurnDrvkangaroo = { + "kangaroo", NULL, NULL, NULL, "1982", + "Kangaroo\0", NULL, "Sun Electronics", "Kangaroo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, kangarooRomInfo, kangarooRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, + &DrvRecalc, 0x08, 256, 512, 3, 4 +}; + + +// Kangaroo (Atari) +static struct BurnRomInfo kangaroaRomDesc[] = { + { "136008-101.ic7", 0x1000, 0x0d18c581, 1 | BRF_ESS | BRF_PRG }, // 0 Main Z80 Code + { "136008-102.ic8", 0x1000, 0x5978d37a, 1 | BRF_ESS | BRF_PRG }, // 1 + { "136008-103.ic9", 0x1000, 0x522d1097, 1 | BRF_ESS | BRF_PRG }, // 2 + { "136008-104.ic10", 0x1000, 0x063da970, 1 | BRF_ESS | BRF_PRG }, // 3 + { "136008-105.ic16", 0x1000, 0x82a26c7d, 1 | BRF_ESS | BRF_PRG }, // 4 + { "136008-106.ic17", 0x1000, 0x3dead542, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "136008-107.ic24", 0x1000, 0xfb449bfd, 2 | BRF_ESS | BRF_PRG }, // 6 Sound Z80 Code + + { "136008-108.ic76", 0x1000, 0xc0446ca6, 3 | BRF_GRA }, // 7 Graphics + { "136008-110.ic77", 0x1000, 0x72c52695, 3 | BRF_GRA }, // 8 + { "136008-109.ic52", 0x1000, 0xe4cb26c2, 3 | BRF_GRA }, // 9 + { "136008-111.ic53", 0x1000, 0x9e6a599f, 3 | BRF_GRA }, // 10 + + { "136008-112.ic28", 0x0800, 0x57766f69, 0 | BRF_ESS | BRF_PRG }, // 11 MB8841 custom microcontroller (unused) + + { "mb8841.ic29", 0x0800, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, // 12 MB8841 custom microcontroller prg (unused) +}; + +STD_ROM_PICK(kangaroa) +STD_ROM_FN(kangaroa) + +struct BurnDriver BurnDrvkangaroa = { + "kangarooa", "kangaroo", NULL, NULL, "1982", + "Kangaroo (Atari)\0", NULL, "[Sun Electronics] (Atari license)", "Kangaroo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, kangaroaRomInfo, kangaroaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, + &DrvRecalc, 0x08, 256, 512, 3, 4 +}; + + +// Kangaroo (bootleg) + +static struct BurnRomInfo kangarobRomDesc[] = { + { "tvg_75.0", 0x1000, 0x0d18c581, 1 | BRF_ESS | BRF_PRG }, // 0 Main Z80 Code + { "tvg_76.1", 0x1000, 0x5978d37a, 1 | BRF_ESS | BRF_PRG }, // 1 + { "tvg_77.2", 0x1000, 0x522d1097, 1 | BRF_ESS | BRF_PRG }, // 2 + { "tvg_78.3", 0x1000, 0x063da970, 1 | BRF_ESS | BRF_PRG }, // 3 + { "tvg_79.4", 0x1000, 0x9e5cf8ca, 1 | BRF_ESS | BRF_PRG }, // 4 + { "k6", 0x1000, 0x7644504a, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "tvg_81.8", 0x1000, 0xfb449bfd, 2 | BRF_ESS | BRF_PRG }, // 6 Sound Z80 Code + + { "tvg_83.v0", 0x1000, 0xc0446ca6, 3 | BRF_GRA }, // 7 Graphics + { "tvg_85.v2", 0x1000, 0x72c52695, 3 | BRF_GRA }, // 8 + { "tvg_84.v1", 0x1000, 0xe4cb26c2, 3 | BRF_GRA }, // 9 + { "tvg_86.v3", 0x1000, 0x9e6a599f, 3 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(kangarob) +STD_ROM_FN(kangarob) + +struct BurnDriver BurnDrvkangarob = { + "kangaroob", "kangaroo", NULL, NULL, "1982", + "Kangaroo (bootleg)\0", NULL, "Bootleg", "Kangaroo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, kangarobRomInfo, kangarobRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, + &DrvRecalc, 0x08, 256, 512, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_karnov.cpp b/src/burn/drivers/misc_pre90s/d_karnov.cpp new file mode 100644 index 00000000..4d16cff1 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_karnov.cpp @@ -0,0 +1,1547 @@ +// FB Alpha Chelnov / Karnov / Wonder Planet driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "burn_ym2203.h" +#include "burn_ym3526.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv6502ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvColPROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPfRAM; +static UINT8 *Drv6502RAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 *DrvScroll; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; + +static UINT16 i8751_return; +static UINT16 i8751_needs_ack; +static UINT16 i8751_coin_pending; +static UINT16 i8751_command_queue; +static INT32 i8751_level; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT16 DrvInput[3]; +static UINT8 DrvDip[2]; +static UINT8 DrvReset; + +static bool bUseAsm68KCoreOldValue = false; + +enum { KARNOV=0, KARNOVJ, CHELNOV, CHELNOVJ, CHELNOVW, WNDRPLNT }; +static INT32 microcontroller_id; +static INT32 coin_mask; +static INT32 vblank; + +static struct BurnInputInfo KarnovInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Karnov) + +static struct BurnInputInfo ChelnovInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Chelnov) + +static struct BurnDIPInfo KarnovDIPList[]= +{ + {0x14, 0xff, 0xff, 0xaf, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0x03, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x0c, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0c, 0x04, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x40, 0x00, "Upright" }, + {0x14, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "5" }, + {0x15, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "50 K" }, + {0x15, 0x01, 0x0c, 0x08, "70 K" }, + {0x15, 0x01, 0x0c, 0x04, "90 K" }, + {0x15, 0x01, 0x0c, 0x00, "100 K" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x30, 0x30, "Easy" }, + {0x15, 0x01, 0x30, 0x10, "Normal" }, + {0x15, 0x01, 0x30, 0x20, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x40, 0x00, "Off" }, + {0x15, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Timer Speed" }, + {0x15, 0x01, 0x80, 0x80, "Normal" }, + {0x15, 0x01, 0x80, 0x00, "Fast" }, +}; + +STDDIPINFO(Karnov) + +static struct BurnDIPInfo WndrplntDIPList[]= +{ + {0x14, 0xff, 0xff, 0x6f, NULL }, + {0x15, 0xff, 0xff, 0xd3, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0x03, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x0c, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0c, 0x04, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x80, 0x00, "Upright" }, + {0x14, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "5" }, + {0x15, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x10, 0x00, "No" }, + {0x15, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0xc0, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Wndrplnt) + +static struct BurnDIPInfo ChelnovDIPList[]= +{ + {0x14, 0xff, 0xff, 0x6f, NULL }, + {0x15, 0xff, 0xff, 0xdf, NULL }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 4 Credits" }, + {0x14, 0x01, 0x03, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0x0c, 0x00, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x04, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x08, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x80, 0x00, "Upright" }, + {0x14, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "5" }, + {0x15, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x04, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x08, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x10, 0x00, "No" }, + {0x15, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Chelnov) + +static struct BurnDIPInfo ChelnovuDIPList[]= +{ + {0x14, 0xff, 0xff, 0x6f, NULL }, + {0x15, 0xff, 0xff, 0xdf, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0x03, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x14, 0x01, 0x0c, 0x00, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x0c, 0x0c, "1 Coin 1 Credits" }, + {0x14, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0c, 0x04, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x80, 0x00, "Upright" }, + {0x14, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x15, 0x01, 0x03, 0x01, "1" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "5" }, + {0x15, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x0c, 0x04, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x08, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x15, 0x01, 0x10, 0x00, "No" }, + {0x15, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Chelnovu) + +//------------------------------------------------------------------------------------------------ +// These are pretty much ripped straight from MAME + +static void karnov_i8751_w(INT32 data) +{ + if (i8751_needs_ack) + { + i8751_command_queue=data; + return; + } + + i8751_return=0; + if (data==0x100 && microcontroller_id==KARNOVJ) i8751_return=0x56a; /* Japan version */ + if (data==0x100 && microcontroller_id==KARNOV) i8751_return=0x56b; /* USA version */ + if ((data&0xf00)==0x300) i8751_return=(data&0xff)*0x12; /* Player sprite mapping */ + + if (data==0x400) i8751_return=0x4000; /* Get The Map... */ + if (data==0x402) i8751_return=0x40a6; /* Ancient Ruins */ + if (data==0x403) i8751_return=0x4054; /* Forest... */ + if (data==0x404) i8751_return=0x40de; /* ^Rocky hills */ + if (data==0x405) i8751_return=0x4182; /* Sea */ + if (data==0x406) i8751_return=0x41ca; /* Town */ + if (data==0x407) i8751_return=0x421e; /* Desert */ + if (data==0x401) i8751_return=0x4138; /* ^Whistling wind */ + if (data==0x408) i8751_return=0x4276; /* ^Heavy Gates */ + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); /* Signal main cpu task is complete */ + i8751_needs_ack=1; +} + +static void wndrplnt_i8751_w(INT32 data) +{ + if (i8751_needs_ack) + { + i8751_command_queue=data; + return; + } + + i8751_return=0; + if (data==0x100) i8751_return=0x67a; + if (data==0x200) i8751_return=0x214; + if (data==0x300) i8751_return=0x17; /* Copyright text on title screen */ +// if (data==0x300) i8751_return=0x1; /* (USA) Copyright text on title screen */ + + if ((data&0x600)==0x600) + { + switch (data&0x18) + { + case 0x00: i8751_return=0x4d53; break; + case 0x08: i8751_return=0x4b54; break; + case 0x10: i8751_return=0x5453; break; + case 0x18: i8751_return=0x5341; break; + } + } + + if (data==0x400) i8751_return=0x594; + if (data==0x401) i8751_return=0x5ea; + if (data==0x402) i8751_return=0x628; + if (data==0x403) i8751_return=0x66c; + if (data==0x404) i8751_return=0x6a4; + if (data==0x405) i8751_return=0x6a4; + if (data==0x406) i8751_return=0x6a4; + + if (data==0x50c) i8751_return=0x13fc; + if (data==0x50b) i8751_return=0x00ff; + if (data==0x50a) i8751_return=0x0006; + if (data==0x509) i8751_return=0x0000; + if (data==0x508) i8751_return=0x4a39; + if (data==0x507) i8751_return=0x0006; + if (data==0x506) i8751_return=0x0000; + if (data==0x505) i8751_return=0x66f8; + if (data==0x504) i8751_return=0x4a39; + if (data==0x503) i8751_return=0x000c; + if (data==0x502) i8751_return=0x0003; + if (data==0x501) i8751_return=0x6bf8; + if (data==0x500) i8751_return=0x4e75; + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + i8751_needs_ack=1; +} + + +static void chelnov_i8751_w(INT32 data) +{ + + if (i8751_needs_ack) + { + i8751_command_queue=data; + return; + } + + i8751_return=0; + if (data==0x200 && microcontroller_id==CHELNOVJ) i8751_return=0x7734; /* Japan version */ + if (data==0x200 && microcontroller_id==CHELNOV) i8751_return=0x783e; /* USA version */ + if (data==0x200 && microcontroller_id==CHELNOVW) i8751_return=0x7736; /* World version */ + if (data==0x100 && microcontroller_id==CHELNOVJ) i8751_return=0x71a; /* Japan version */ + if (data==0x100 && microcontroller_id==CHELNOV) i8751_return=0x71b; /* USA version */ + if (data==0x100 && microcontroller_id==CHELNOVW) i8751_return=0x71c; /* World version */ + + if (data>=0x6000 && data<0x8000) i8751_return=1; /* patched */ + if ((data&0xf000)==0x1000) i8751_level=1; /* Level 1 */ + if ((data&0xf000)==0x2000) i8751_level++; /* Level Increment */ + + if ((data&0xf000)==0x3000) + { /* Sprite table mapping */ + INT32 b=data&0xff; + switch (i8751_level) + { + case 1: /* Level 1, Sprite mapping tables */ + if (microcontroller_id==CHELNOV) + { /* USA */ + if (b<2) i8751_return=0; + else if (b<6) i8751_return=1; + else if (b<0xb) i8751_return=2; + else if (b<0xf) i8751_return=3; + else if (b<0x13) i8751_return=4; + else i8751_return=5; + } + else + { /* Japan, World */ + if (b<3) i8751_return=0; + else if (b<8) i8751_return=1; + else if (b<0x0c) i8751_return=2; + else if (b<0x10) i8751_return=3; + else if (b<0x19) i8751_return=4; + else if (b<0x1b) i8751_return=5; + else if (b<0x22) i8751_return=6; + else if (b<0x28) i8751_return=7; + else i8751_return=8; + } + break; + case 2: /* Level 2, Sprite mapping tables, USA & Japan are the same */ + if (b<3) i8751_return=0; + else if (b<9) i8751_return=1; + else if (b<0x11) i8751_return=2; + else if (b<0x1b) i8751_return=3; + else if (b<0x21) i8751_return=4; + else if (b<0x28) i8751_return=5; + else i8751_return=6; + break; + case 3: /* Level 3, Sprite mapping tables, USA & Japan are the same */ + if (b<5) i8751_return=0; + else if (b<9) i8751_return=1; + else if (b<0x0d) i8751_return=2; + else if (b<0x11) i8751_return=3; + else if (b<0x1b) i8751_return=4; + else if (b<0x1c) i8751_return=5; + else if (b<0x22) i8751_return=6; + else if (b<0x27) i8751_return=7; + else i8751_return=8; + break; + case 4: /* Level 4, Sprite mapping tables, USA & Japan are the same */ + if (b<4) i8751_return=0; + else if (b<0x0c) i8751_return=1; + else if (b<0x0f) i8751_return=2; + else if (b<0x19) i8751_return=3; + else if (b<0x1c) i8751_return=4; + else if (b<0x22) i8751_return=5; + else if (b<0x29) i8751_return=6; + else i8751_return=7; + break; + case 5: /* Level 5, Sprite mapping tables */ + if (b<7) i8751_return=0; + else if (b<0x0e) i8751_return=1; + else if (b<0x14) i8751_return=2; + else if (b<0x1a) i8751_return=3; + else if (b<0x23) i8751_return=4; + else if (b<0x27) i8751_return=5; + else i8751_return=6; + break; + case 6: /* Level 6, Sprite mapping tables */ + if (b<3) i8751_return=0; + else if (b<0x0b) i8751_return=1; + else if (b<0x11) i8751_return=2; + else if (b<0x17) i8751_return=3; + else if (b<0x1d) i8751_return=4; + else if (b<0x24) i8751_return=5; + else i8751_return=6; + break; + case 7: /* Level 7, Sprite mapping tables */ + if (b<5) i8751_return=0; + else if (b<0x0b) i8751_return=1; + else if (b<0x11) i8751_return=2; + else if (b<0x1a) i8751_return=3; + else if (b<0x21) i8751_return=4; + else if (b<0x27) i8751_return=5; + else i8751_return=6; + break; + } + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + i8751_needs_ack=1; +} + +static void karnov_control_w(INT32 offset, INT32 data) +{ + switch (offset<<1) + { + case 0: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + + if (i8751_needs_ack) + { + if (i8751_coin_pending) + { + i8751_return=i8751_coin_pending; + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + i8751_coin_pending=0; + } + else if (i8751_command_queue) + { + i8751_needs_ack=0; + karnov_control_w(3,i8751_command_queue); + i8751_command_queue=0; + } + else + { + i8751_needs_ack=0; + } + } + return; + + case 2: + *soundlatch = data; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + break; + + case 4: + memcpy (DrvSprBuf, DrvSprRAM, 0x1000); + break; + + case 6: + if (microcontroller_id==KARNOV || microcontroller_id==KARNOVJ) karnov_i8751_w(data); + if (microcontroller_id==CHELNOV || microcontroller_id==CHELNOVJ || microcontroller_id==CHELNOVW) chelnov_i8751_w(data); + if (microcontroller_id==WNDRPLNT) wndrplnt_i8751_w(data); + break; + + case 8: + DrvScroll[0] = data; + *flipscreen = data >> 15; + break; + + case 0xa: + DrvScroll[1] = data; + break; + + case 0xc: + i8751_needs_ack=0; + i8751_coin_pending=0; + i8751_command_queue=0; + i8751_return=0; + break; + + case 0xe: + SekSetIRQLine(7, SEK_IRQSTATUS_NONE); + break; + } +} + +static UINT16 karnov_control_r(INT32 offset) +{ + switch (offset<<1) + { + case 0: + return DrvInput[0]; + case 2: + return DrvInput[1] ^ vblank; + case 4: + return (DrvDip[1] << 8) | DrvDip[0]; + case 6: + return i8751_return; + } + + return ~0; +} + +//------------------------------------------------------------------------------------------ + +void __fastcall karnov_main_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff800) == 0x0a1800) { + UINT16 *ptr = (UINT16*)DrvPfRAM; + + INT32 offset = (address >> 1) & 0x3ff; + offset = ((offset & 0x1f) << 5) | ((offset & 0x3e0) >> 5); + + ptr[offset] = data; + return; + } + + if ((address & 0xfffff0) == 0x0c0000) { + karnov_control_w((address >> 1) & 0x07, data); + return; + } +} + +void __fastcall karnov_main_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xfff800) == 0x0a1800) { + INT32 offset = (address >> 1) & 0x3ff; + offset = ((offset & 0x1f) << 5) | ((offset & 0x3e0) >> 5); + + DrvPfRAM[(offset << 1) | (~address & 1)] = data; + return; + } + + if ((address & 0xfffff0) == 0x0c0000) { + karnov_control_w((address >> 1) & 0x07, data); + + } +} + +UINT16 __fastcall karnov_main_read_word(UINT32 address) +{ + if ((address & 0xfffff0) == 0x0c0000) { + return karnov_control_r((address >> 1) & 7); + } + + return 0; +} + +UINT8 __fastcall karnov_main_read_byte(UINT32 address) +{ + if ((address & 0xfffff0) == 0x0c0000) { + return karnov_control_r((address >> 1) & 7) >> ((~address & 1) << 3); + } + + return 0; +} + +void karnov_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x1000: + case 0x1001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0x1800: + case 0x1801: + BurnYM3526Write(address & 1, data); + return; + } +} + +UINT8 karnov_sound_read(UINT16 address) +{ + switch (address) + { + case 0x0800: +// m6502SetIRQ(M6502_CLEAR); + return *soundlatch; + } + + return 0; +} + +static void DrvYM3526FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_ACK); + } else { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_NONE); + } +} + +static INT32 DrvYM3526SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6502TotalCycles() * nSoundRate / 1500000; +} + +static INT32 DrvYM2203SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / 10000000; +} + +static double DrvYM2203GetTime() +{ + return (double)SekTotalCycles() / 10000000; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + BurnYM3526Reset(); + BurnYM2203Reset(); + + i8751_return = 0; + i8751_needs_ack = 0; + i8751_coin_pending = 0; + i8751_command_queue = 0; + i8751_level = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x060000; + Drv6502ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x100000; + + DrvColPROM = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPfRAM = Next; Next += 0x000800; + Drv6502RAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x001000; + DrvSprBuf = Next; Next += 0x001000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + DrvScroll = (UINT16*)Next; Next += 0x0002 * sizeof(UINT16); + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x300; i++) + { + INT32 bit0,bit1,bit2,bit3,r,g,b; + + bit0 = (DrvColPROM[0x000 + i] >> 0) & 0x01; + bit1 = (DrvColPROM[0x000 + i] >> 1) & 0x01; + bit2 = (DrvColPROM[0x000 + i] >> 2) & 0x01; + bit3 = (DrvColPROM[0x000 + i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[0x000 + i] >> 4) & 0x01; + bit1 = (DrvColPROM[0x000 + i] >> 5) & 0x01; + bit2 = (DrvColPROM[0x000 + i] >> 6) & 0x01; + bit3 = (DrvColPROM[0x000 + i] >> 7) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[0x400 + i] >> 0) & 0x01; + bit1 = (DrvColPROM[0x400 + i] >> 1) & 0x01; + bit2 = (DrvColPROM[0x400 + i] >> 2) & 0x01; + bit3 = (DrvColPROM[0x400 + i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = (r << 16) | (g << 8) | b; + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[3] = { 0x6000*8,0x4000*8,0x2000*8 }; + INT32 Plane1[4] = { 0x60000*8,0x00000*8,0x20000*8,0x40000*8 }; + INT32 XOffs[16] = { 16*8, 1+(16*8), 2+(16*8), 3+(16*8), 4+(16*8), 5+(16*8), 6+(16*8), 7+(16*8), 0,1,2,3,4,5,6,7 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 ,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x80000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 3, 8, 8, Plane0, XOffs + 8, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x80000); + + GfxDecode(0x0800, 4, 16, 16, Plane1, XOffs + 0, YOffs, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x80000); + + GfxDecode(0x1000, 4, 16, 16, Plane1, XOffs + 0, YOffs, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 5, 2)) return 1; + + if (BurnLoadRom(Drv6502ROM + 0x08000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x60000, 11, 1)) return 1; + + if (microcontroller_id == CHELNOVJ || microcontroller_id == CHELNOVW || microcontroller_id == CHELNOV) { + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 15, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 16, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00400, 17, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x50000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x70000, 19, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 20, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00400, 21, 1)) return 1; + } + + DrvPaletteInit(); + DrvGfxDecode(); + } + + // These games really don't like the ASM core, so disable it for now + // and restore it on exit. + if (bBurnUseASMCPUEmulation) { + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x060000, 0x063fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvVidRAM, 0x0a0000, 0x0a07ff, SM_RAM); + SekMapMemory(DrvVidRAM, 0x0a0800, 0x0a0fff, SM_RAM); + SekMapMemory(DrvPfRAM, 0x0a1000, 0x0a17ff, SM_WRITE); + SekSetWriteWordHandler(0, karnov_main_write_word); + SekSetWriteByteHandler(0, karnov_main_write_byte); + SekSetReadWordHandler(0, karnov_main_read_word); + SekSetReadByteHandler(0, karnov_main_read_byte); + SekClose(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(Drv6502RAM, 0x0000, 0x05ff, M6502_RAM); + M6502MapMemory(Drv6502ROM + 0x8000, 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(karnov_sound_read); + M6502SetWriteByteHandler(karnov_sound_write); + M6502Close(); + + BurnYM3526Init(3000000, &DrvYM3526FMIRQHandler, &DrvYM3526SynchroniseStream, 0); + BurnTimerAttachM6502YM3526(1500000); + + BurnYM2203Init(1, 1500000, NULL, DrvYM2203SynchroniseStream, DrvYM2203GetTime, 1); + BurnTimerAttachSek(10000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + M6502Exit(); + + BurnYM3526Exit(); + BurnYM2203Exit(); + + BurnFree (AllMem); + + if (bUseAsm68KCoreOldValue) { + bBurnUseASMCPUEmulation = true; + } + + return 0; +} + +static void draw_txt_layer(INT32 swap) +{ + UINT16 *vram = (UINT16*)DrvVidRAM; + for (INT32 offs = 0x20; offs < 0x3e0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + if (swap) { + INT32 t = sx; + sx = sy; + sy = t; + } + + if (*flipscreen) { + sy ^= 0xf8; + sx ^= 0xf8; + } + + sy -= 8; + + INT32 code = vram[offs] & 0x0fff; + INT32 color = vram[offs] >> 14; + + if (code == 0) continue; + + if (*flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_bg_layer() +{ + INT32 scrollx = DrvScroll[0] & 0x1ff; + INT32 scrolly = DrvScroll[1] & 0x1ff; + + UINT16 *vram = (UINT16*)DrvPfRAM; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sy -= scrolly; + if (sy < -15) sy+=512; + sx -= scrollx; + if (sx < -15) sx+=512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs]; + INT32 code = attr & 0x7ff; + INT32 color= attr >> 12; + + if (*flipscreen) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, 240 - sx, (240 - sy) - 8, color, 4, 0x200, DrvGfxROM1); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0x200, DrvGfxROM1); + } + } +} + +static inline void sprite_routine(INT32 code, INT32 sx, INT32 sy, INT32 color, INT32 fy, INT32 fx) +{ + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x100, DrvGfxROM2); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0x100, DrvGfxROM2); + } + } +} + +static void draw_sprites() +{ + UINT16 *ram = (UINT16*)DrvSprBuf; + + for (INT32 offs = 0; offs < 0x800; offs+=4) + { + INT32 y = ram[offs]; + INT32 x = ram[offs + 2] & 0x1ff; + if (~y & 0x8000) continue; + y &= 0x1ff; + + INT32 sprite = ram[offs + 3]; + INT32 color = sprite >> 12; + sprite &= 0xfff; + + INT32 flipx = ram[offs + 1]; + INT32 flipy = flipx & 0x02; + INT32 extra = flipx & 0x10; + flipx &= 0x04; + + x = (x + 16) & 0x1ff; + y = (y + 16 + extra) & 0x1ff; + x = 256 - x; + y = 256 - y; + + if (*flipscreen) { + y = 240 - y; + x = 240 - x; + flipx ^= 0x04; + flipy ^= 0x02; + if (extra) y -= 16; + y -= 8; + } + + INT32 sprite2 = sprite + 1; + if (extra && flipy) { + sprite2--; + sprite++; + } + + sprite_routine(sprite, x, y, color, flipy, flipx); + + if (extra) sprite_routine(sprite2, x, y + 16, color, flipy, flipx); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x300; i++) { + INT32 d = Palette[i]; + + r = d >> 16; + g = d >> 8; + b = d >> 0; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } + DrvRecalc = 0; + } + + draw_bg_layer(); + draw_sprites(); + draw_txt_layer(microcontroller_id == WNDRPLNT); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void DrvInterrupt() +{ + static INT32 latch; + + if (DrvInput[2] == coin_mask) latch=1; + if (DrvInput[2] != coin_mask && latch) + { + if (i8751_needs_ack) + { + i8751_coin_pending = DrvInput[2] | 0x8000; + } + else + { + i8751_return = DrvInput[2] | 0x8000; + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + i8751_needs_ack=1; + } + latch=0; + } + + SekSetIRQLine(7, SEK_IRQSTATUS_AUTO); +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + M6502NewFrame(); + + { + memset (DrvInput, 0xff, 2 * sizeof(INT16)); + DrvInput[2] = coin_mask; + for (INT32 i = 0; i < 16; i++) { + DrvInput[0] ^= (DrvJoy1[i] & 1) << i; + DrvInput[1] ^= (DrvJoy2[i] & 1) << i; + DrvInput[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 32; + INT32 nCyclesTotal[2] = { 10000000 / 60, 1500000 / 60 }; + + M6502Open(0); + SekOpen(0); + + vblank = 0x80; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 1) vblank = 0x80; + if (i == 31) { + vblank = 0; + DrvInterrupt(); + } + + BurnTimerUpdate(i * (nCyclesTotal[0] / nInterleave)); + + BurnTimerUpdateYM3526(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[0]); + BurnTimerEndFrameYM3526(nCyclesTotal[1]); + + if (pBurnSoundOut) { + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + + SekClose(); + M6502Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + M6502Scan(nAction); + + BurnYM3526Scan(nAction, pnMin); + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(i8751_return); + SCAN_VAR(i8751_needs_ack); + SCAN_VAR(i8751_coin_pending); + SCAN_VAR(i8751_command_queue); + SCAN_VAR(i8751_level); + } + + return 0; +} + + +// Karnov (US) + +static struct BurnRomInfo karnovRomDesc[] = { + { "dn08-5", 0x10000, 0xdb92c264, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "dn11-5", 0x10000, 0x05669b4b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "dn07-", 0x10000, 0xfc14291b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "dn10-", 0x10000, 0xa4a34e37, 1 | BRF_PRG | BRF_ESS }, // 3 + { "dn06-5", 0x10000, 0x29d64e42, 1 | BRF_PRG | BRF_ESS }, // 4 + { "dn09-5", 0x10000, 0x072d7c49, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "dn05-5", 0x08000, 0xfa1a31a8, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "dn00-", 0x08000, 0x0ed77c6d, 3 | BRF_GRA}, // 7 Characters + + { "dn04-", 0x10000, 0xa9121653, 4 | BRF_GRA}, // 8 Tiles + { "dn01-", 0x10000, 0x18697c9e, 4 | BRF_GRA}, // 9 + { "dn03-", 0x10000, 0x90d9dd9c, 4 | BRF_GRA}, // 10 + { "dn02-", 0x10000, 0x1e04d7b9, 4 | BRF_GRA}, // 11 + + { "dn12-", 0x10000, 0x9806772c, 5 | BRF_GRA}, // 12 Sprites + { "dn14-5", 0x08000, 0xac9e6732, 5 | BRF_GRA}, // 13 + { "dn13-", 0x10000, 0xa03308f9, 5 | BRF_GRA}, // 14 + { "dn15-5", 0x08000, 0x8933fcb8, 5 | BRF_GRA}, // 15 + { "dn16-", 0x10000, 0x55e63a11, 5 | BRF_GRA}, // 16 + { "dn17-5", 0x08000, 0xb70ae950, 5 | BRF_GRA}, // 17 + { "dn18-", 0x10000, 0x2ad53213, 5 | BRF_GRA}, // 18 + { "dn19-5", 0x08000, 0x8fd4fa40, 5 | BRF_GRA}, // 19 + + { "karnprom.21", 0x00400, 0xaab0bb93, 6 | BRF_GRA}, // 20 Color Color Proms + { "karnprom.20", 0x00400, 0x02f78ffb, 6 | BRF_GRA}, // 21 + + { "karnov_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(karnov) +STD_ROM_FN(karnov) + +static INT32 KarnovInit() +{ + microcontroller_id = KARNOV; + coin_mask = 0; + + return DrvInit(); +} + +struct BurnDriver BurnDrvKarnov = { + "karnov", NULL, NULL, NULL, "1987", + "Karnov (US)\0", NULL, "Data East USA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, karnovRomInfo, karnovRomName, NULL, NULL, KarnovInputInfo, KarnovDIPInfo, + KarnovInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 256, 240, 4, 3 +}; + + + +// Karnov (Japan) + +static struct BurnRomInfo karnovjRomDesc[] = { + { "kar8", 0x10000, 0x3e17e268, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "kar11", 0x10000, 0x417c936d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "dn07-", 0x10000, 0xfc14291b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "dn10-", 0x10000, 0xa4a34e37, 1 | BRF_PRG | BRF_ESS }, // 3 + { "kar6", 0x10000, 0xc641e195, 1 | BRF_PRG | BRF_ESS }, // 4 + { "kar9", 0x10000, 0xd420658d, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "kar5", 0x08000, 0x7c9158f1, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "dn00-", 0x08000, 0x0ed77c6d, 3 | BRF_GRA}, // 7 Characters + + { "dn04-", 0x10000, 0xa9121653, 4 | BRF_GRA}, // 8 Tiles + { "dn01-", 0x10000, 0x18697c9e, 4 | BRF_GRA}, // 9 + { "dn03-", 0x10000, 0x90d9dd9c, 4 | BRF_GRA}, // 10 + { "dn02-", 0x10000, 0x1e04d7b9, 4 | BRF_GRA}, // 11 + + { "dn12-", 0x10000, 0x9806772c, 5 | BRF_GRA}, // 12 Sprites + { "kar14", 0x08000, 0xc6b39595, 5 | BRF_GRA}, // 13 + { "dn13-", 0x10000, 0xa03308f9, 5 | BRF_GRA}, // 14 + { "kar15", 0x08000, 0x2f72cac0, 5 | BRF_GRA}, // 15 + { "dn16-", 0x10000, 0x55e63a11, 5 | BRF_GRA}, // 16 + { "kar17", 0x08000, 0x7851c70f, 5 | BRF_GRA}, // 17 + { "dn18-", 0x10000, 0x2ad53213, 5 | BRF_GRA}, // 18 + { "kar19", 0x08000, 0x7bc174bb, 5 | BRF_GRA}, // 19 + + { "karnprom.21", 0x00400, 0xaab0bb93, 6 | BRF_GRA}, // 20 Color Proms + { "karnprom.20", 0x00400, 0x02f78ffb, 6 | BRF_GRA}, // 21 + + { "karnovj_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(karnovj) +STD_ROM_FN(karnovj) + +static INT32 KarnovjInit() +{ + microcontroller_id = KARNOVJ; + coin_mask = 0; + + return DrvInit(); +} + +struct BurnDriver BurnDrvKarnovj = { + "karnovj", "karnov", NULL, NULL, "1987", + "Karnov (Japan)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, karnovjRomInfo, karnovjRomName, NULL, NULL, KarnovInputInfo, KarnovDIPInfo, + KarnovjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 256, 240, 4, 3 +}; + + +// Wonder Planet (Japan) + +static struct BurnRomInfo wndrplntRomDesc[] = { + { "ea08.bin", 0x10000, 0xb0578a14, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ea11.bin", 0x10000, 0x271edc6c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ea07.bin", 0x10000, 0x7095a7d5, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ea10.bin", 0x10000, 0x81a96475, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ea06.bin", 0x10000, 0x5951add3, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ea09.bin", 0x10000, 0xc4b3cb1e, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ea05.bin", 0x08000, 0x8dbb6231, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "ea00.bin", 0x08000, 0x9f3cac4c, 3 | BRF_GRA}, // 7 Characters + + { "ea04.bin", 0x10000, 0x7d701344, 4 | BRF_GRA}, // 8 Tiles + { "ea01.bin", 0x10000, 0x18df55fb, 4 | BRF_GRA}, // 9 + { "ea03.bin", 0x10000, 0x922ef050, 4 | BRF_GRA}, // 10 + { "ea02.bin", 0x10000, 0x700fde70, 4 | BRF_GRA}, // 11 + + { "ea12.bin", 0x10000, 0xa6d4e99d, 5 | BRF_GRA}, // 12 Sprites + { "ea14.bin", 0x10000, 0x915ffdc9, 5 | BRF_GRA}, // 13 + { "ea13.bin", 0x10000, 0xcd839f3a, 5 | BRF_GRA}, // 14 + { "ea15.bin", 0x10000, 0xa1f14f16, 5 | BRF_GRA}, // 15 + { "ea16.bin", 0x10000, 0x7a1d8a9c, 5 | BRF_GRA}, // 16 + { "ea17.bin", 0x10000, 0x21a3223d, 5 | BRF_GRA}, // 17 + { "ea18.bin", 0x10000, 0x3fb2cec7, 5 | BRF_GRA}, // 18 + { "ea19.bin", 0x10000, 0x87cf03b5, 5 | BRF_GRA}, // 19 + + { "ea21.prm", 0x00400, 0xc8beab49, 6 | BRF_GRA}, // 20 Color Proms + { "ea20.prm", 0x00400, 0x619f9d1e, 6 | BRF_GRA}, // 21 + + { "wndrplnt_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(wndrplnt) +STD_ROM_FN(wndrplnt) + +static INT32 WndrplntInit() +{ + microcontroller_id = WNDRPLNT; + coin_mask = 0; + + return DrvInit(); +} + +struct BurnDriver BurnDrvWndrplnt = { + "wndrplnt", NULL, NULL, NULL, "1987", + "Wonder Planet (Japan)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, wndrplntRomInfo, wndrplntRomName, NULL, NULL, KarnovInputInfo, WndrplntDIPInfo, + WndrplntInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 240, 256, 3, 4 +}; + + +// Chelnov - Atomic Runner (World) + +static struct BurnRomInfo chelnovRomDesc[] = { + { "ee08-e.j16", 0x10000, 0x8275cc3a, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ee11-e.j19", 0x10000, 0x889e40a0, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a-j14.bin", 0x10000, 0x51465486, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a-j18.bin", 0x10000, 0xd09dda33, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ee06-e.j13", 0x10000, 0x55acafdb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ee09-e.j17", 0x10000, 0x303e252c, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ee05-.f3", 0x08000, 0x6a8936b4, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "ee00-e.c5", 0x08000, 0xe06e5c6b, 3 | BRF_GRA}, // 7 Characters + + { "ee04-.d18", 0x10000, 0x96884f95, 4 | BRF_GRA}, // 8 Tiles + { "ee01-.c15", 0x10000, 0xf4b54057, 4 | BRF_GRA}, // 9 + { "ee03-.d15", 0x10000, 0x7178e182, 4 | BRF_GRA}, // 10 + { "ee02-.c18", 0x10000, 0x9d7c45ae, 4 | BRF_GRA}, // 11 + + { "ee12-.f8", 0x10000, 0x9b1c53a5, 5 | BRF_GRA}, // 12 Sprites + { "ee13-.f9", 0x10000, 0x72b8ae3e, 5 | BRF_GRA}, // 13 + { "ee14-.f13", 0x10000, 0xd8f4bbde, 5 | BRF_GRA}, // 14 + { "ee15-.f15", 0x10000, 0x81e3e68b, 5 | BRF_GRA}, // 15 + + { "ee21.k8", 0x00400, 0xb1db6586, 6 | BRF_GRA}, // 16 Color Proms + { "ee20.l6", 0x00400, 0x41816132, 6 | BRF_GRA}, // 17 + + { "chelnov_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(chelnov) +STD_ROM_FN(chelnov) + +static INT32 ChelnovInit() +{ + microcontroller_id = CHELNOVW; + coin_mask = 0xe0; + + INT32 nRet = DrvInit(); + + if (nRet == 0) { + *((UINT16*)(Drv68KROM + 0x0A26)) = 0x4E71; + *((UINT16*)(Drv68KROM + 0x062a)) = 0x4E71; + } + + return nRet; +} + +struct BurnDriver BurnDrvChelnov = { + "chelnov", NULL, NULL, NULL, "1988", + "Chelnov - Atomic Runner (World)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, chelnovRomInfo, chelnovRomName, NULL, NULL, ChelnovInputInfo, ChelnovDIPInfo, + ChelnovInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 256, 240, 4, 3 +}; + + +// Chelnov - Atomic Runner (US) + +static struct BurnRomInfo chelnovuRomDesc[] = { + { "ee08-a.j15", 0x10000, 0x2f2fb37b, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "ee11-a.j20", 0x10000, 0xf306d05f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ee07-a.j14", 0x10000, 0x9c69ed56, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ee10-a.j18", 0x10000, 0xd5c5fe4b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ee06-e.j13", 0x10000, 0x55acafdb, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ee09-e.j17", 0x10000, 0x303e252c, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ee05-.f3", 0x08000, 0x6a8936b4, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "ee00-e.c5", 0x08000, 0xe06e5c6b, 3 | BRF_GRA}, // 7 Characters + + { "ee04-.d18", 0x10000, 0x96884f95, 4 | BRF_GRA}, // 8 Tiles + { "ee01-.c15", 0x10000, 0xf4b54057, 4 | BRF_GRA}, // 9 + { "ee03-.d15", 0x10000, 0x7178e182, 4 | BRF_GRA}, // 10 + { "ee02-.c18", 0x10000, 0x9d7c45ae, 4 | BRF_GRA}, // 11 + + { "ee12-.f8", 0x10000, 0x9b1c53a5, 5 | BRF_GRA}, // 12 Sprites + { "ee13-.f9", 0x10000, 0x72b8ae3e, 5 | BRF_GRA}, // 13 + { "ee14-.f13", 0x10000, 0xd8f4bbde, 5 | BRF_GRA}, // 14 + { "ee15-.f15", 0x10000, 0x81e3e68b, 5 | BRF_GRA}, // 15 + + { "ee21.k8", 0x00400, 0xb1db6586, 6 | BRF_GRA}, // 16 Color Proms + { "ee20.l6", 0x00400, 0x41816132, 6 | BRF_GRA}, // 17 + + { "chelnovu_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(chelnovu) +STD_ROM_FN(chelnovu) + +static INT32 ChelnovuInit() +{ + microcontroller_id = CHELNOV; + coin_mask = 0xe0; + + INT32 nRet = DrvInit(); + + if (nRet == 0) { + *((UINT16*)(Drv68KROM + 0x0A26)) = 0x4E71; + *((UINT16*)(Drv68KROM + 0x062a)) = 0x4E71; + } + + return nRet; +} + +struct BurnDriver BurnDrvChelnovu = { + "chelnovu", "chelnov", NULL, NULL, "1988", + "Chelnov - Atomic Runner (US)\0", NULL, "Data East USA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, chelnovuRomInfo, chelnovuRomName, NULL, NULL, ChelnovInputInfo, ChelnovuDIPInfo, + ChelnovuInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 256, 240, 4, 3 +}; + + +// Chelnov - Atomic Runner (Japan) + +static struct BurnRomInfo chelnovjRomDesc[] = { + { "a-j15.bin", 0x10000, 0x1978cb52, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "a-j20.bin", 0x10000, 0xe0ed3d99, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a-j14.bin", 0x10000, 0x51465486, 1 | BRF_PRG | BRF_ESS }, // 2 + { "a-j18.bin", 0x10000, 0xd09dda33, 1 | BRF_PRG | BRF_ESS }, // 3 + { "a-j13.bin", 0x10000, 0xcd991507, 1 | BRF_PRG | BRF_ESS }, // 4 + { "a-j17.bin", 0x10000, 0x977f601c, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ee05-.f3", 0x08000, 0x6a8936b4, 2 | BRF_PRG | BRF_ESS }, // 6 m6502 Code + + { "a-c5.bin", 0x08000, 0x1abf2c6d, 3 | BRF_GRA}, // 7 Characters + + { "ee04-.d18", 0x10000, 0x96884f95, 4 | BRF_GRA}, // 8 Tiles + { "ee01-.c15", 0x10000, 0xf4b54057, 4 | BRF_GRA}, // 9 + { "ee03-.d15", 0x10000, 0x7178e182, 4 | BRF_GRA}, // 10 + { "ee02-.c18", 0x10000, 0x9d7c45ae, 4 | BRF_GRA}, // 11 + + { "ee12-.f8", 0x10000, 0x9b1c53a5, 5 | BRF_GRA}, // 12 Sprites + { "ee13-.f9", 0x10000, 0x72b8ae3e, 5 | BRF_GRA}, // 13 + { "ee14-.f13", 0x10000, 0xd8f4bbde, 5 | BRF_GRA}, // 14 + { "ee15-.f15", 0x10000, 0x81e3e68b, 5 | BRF_GRA}, // 15 + + { "a-k7.bin", 0x00400, 0x309c49d8, 6 | BRF_GRA}, // 16 Color Proms + { "ee20.l6", 0x00400, 0x41816132, 6 | BRF_GRA}, // 17 + + { "chelnovj_i8751", 0x01000, 0x00000000, BRF_OPT | BRF_NODUMP}, +}; + +STD_ROM_PICK(chelnovj) +STD_ROM_FN(chelnovj) + +static INT32 ChelnovjInit() +{ + microcontroller_id = CHELNOVJ; + coin_mask = 0xe0; + + INT32 nRet = DrvInit(); + + if (nRet == 0) { + *((UINT16*)(Drv68KROM + 0x0A2e)) = 0x4E71; + *((UINT16*)(Drv68KROM + 0x062a)) = 0x4E71; + } + + return nRet; +} + +struct BurnDriver BurnDrvChelnovj = { + "chelnovj", "chelnov", NULL, NULL, "1988", + "Chelnov - Atomic Runner (Japan)\0", NULL, "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_HORSHOOT, 0, + NULL, chelnovjRomInfo, chelnovjRomName, NULL, NULL, ChelnovInputInfo, ChelnovuDIPInfo, + ChelnovjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x300, 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_kyugo.cpp b/src/burn/drivers/misc_pre90s/d_kyugo.cpp new file mode 100644 index 00000000..4237c032 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_kyugo.cpp @@ -0,0 +1,2610 @@ +#include "tiles_generic.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static UINT8 KyugoInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 KyugoInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 KyugoInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 KyugoDip[2] = {0, 0}; +static UINT8 KyugoInput[3] = {0x00, 0x00, 0x00}; +static UINT8 KyugoReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *KyugoZ80Rom1 = NULL; +static UINT8 *KyugoZ80Rom2 = NULL; +static UINT8 *KyugoSharedZ80Ram = NULL; +static UINT8 *KyugoZ80Ram2 = NULL; +static UINT8 *KyugoSprite1Ram = NULL; +static UINT8 *KyugoSprite2Ram = NULL; +static UINT8 *KyugoFgVideoRam = NULL; +static UINT8 *KyugoBgVideoRam = NULL; +static UINT8 *KyugoBgAttrRam = NULL; +static UINT8 *KyugoPromRed = NULL; +static UINT8 *KyugoPromGreen = NULL; +static UINT8 *KyugoPromBlue = NULL; +static UINT8 *KyugoPromCharLookup = NULL; +static UINT8 *KyugoChars = NULL; +static UINT8 *KyugoTiles = NULL; +static UINT8 *KyugoSprites = NULL; +static UINT8 *KyugoTempRom = NULL; +static UINT32 *KyugoPalette = NULL; +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[6]; + +static UINT8 KyugoIRQEnable; +static UINT8 KyugoSubCPUEnable; +static UINT8 KyugoFgColour; +static UINT8 KyugoBgPaletteBank; +static UINT8 KyugoBgScrollXHi; +static UINT8 KyugoBgScrollXLo; +static UINT8 KyugoBgScrollY; +static UINT8 KyugoFlipScreen; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static INT32 KyugoNumZ80Rom1; +static INT32 KyugoNumZ80Rom2; +static INT32 KyugoNumSpriteRom; +static INT32 KyugoSizeZ80Rom1; +static INT32 KyugoSizeZ80Rom2; +static INT32 KyugoSizeSpriteRom; + +static struct BurnInputInfo KyugoInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , KyugoInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , KyugoInputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , KyugoInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , KyugoInputPort0 + 4, "p2 start" }, + + {"Up" , BIT_DIGITAL , KyugoInputPort1 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , KyugoInputPort1 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , KyugoInputPort1 + 0, "p1 left" }, + {"Right" , BIT_DIGITAL , KyugoInputPort1 + 1, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , KyugoInputPort1 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , KyugoInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 2, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 3, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 0, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 1, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , KyugoInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &KyugoReset , "reset" }, + {"Service" , BIT_DIGITAL , KyugoInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, KyugoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, KyugoDip + 1 , "dip" }, +}; + + +STDINPUTINFO(Kyugo) + +inline void KyugoClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void KyugoMakeInputs() +{ + // Reset Inputs + KyugoInput[0] = KyugoInput[1] = KyugoInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + KyugoInput[0] |= (KyugoInputPort0[i] & 1) << i; + KyugoInput[1] |= (KyugoInputPort1[i] & 1) << i; + KyugoInput[2] |= (KyugoInputPort2[i] & 1) << i; + } + + // Clear Opposites + KyugoClearOpposites(&KyugoInput[1]); + KyugoClearOpposites(&KyugoInput[2]); +} + +static struct BurnDIPInfo AirwolfDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbb, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "4" }, + {0x12, 0x01, 0x03, 0x02, "5" }, + {0x12, 0x01, 0x03, 0x01, "6" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Airwolf) + +static struct BurnDIPInfo SkywolfDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbb, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Skywolf) + +static struct BurnDIPInfo FlashgalDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xaf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "Every 50000" }, + {0x12, 0x01, 0x04, 0x00, "Every 70000" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Flashgal) + +static struct BurnDIPInfo GyrodineDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x10, 0x10, "Easy" }, + {0x12, 0x01, 0x10, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x20, 0x20, "20000 50000" }, + {0x12, 0x01, 0x20, 0x00, "40000 70000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Gyrodine) + +static struct BurnDIPInfo LegendDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life / Continue" }, + {0x12, 0x01, 0x04, 0x04, "Every 50000 / No" }, + {0x12, 0x01, 0x04, 0x00, "Every 70000 / Yes" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Legend) + +static struct BurnDIPInfo SonofphxDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xbf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "Every 50000" }, + {0x12, 0x01, 0x04, 0x00, "Every 70000" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0xc0, 0xc0, "Easy" }, + {0x13, 0x01, 0xc0, 0x80, "Normal" }, + {0x13, 0x01, 0xc0, 0x40, "Hard" }, + {0x13, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Sonofphx) + +static struct BurnDIPInfo SrdmissnDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xbf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life / Continue" }, + {0x12, 0x01, 0x04, 0x04, "Every 50000 / No" }, + {0x12, 0x01, 0x04, 0x00, "Every 70000 / Yes" }, + + {0 , 0xfe, 0 , 2 , "Slow Motion" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Sound Test" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 2 Plays" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + {0x13, 0x01, 0x07, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "5 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x20, "3 Coins 4 Plays" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, +}; + +STDDIPINFO(Srdmissn) + +static struct BurnRomInfo AirwolfRomDesc[] = { + { "b.2s", 0x08000, 0x8c993cce, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + + { "a.7s", 0x08000, 0xa3c7af5c, BRF_ESS | BRF_PRG }, // 1 Z80 #2 Program + + { "f.4a", 0x01000, 0x4df44ce9, BRF_GRA }, // 2 Characters + + { "09h_14.bin", 0x02000, 0x25e57e1f, BRF_GRA }, // 3 Tiles + { "10h_13.bin", 0x02000, 0xcf0de5e9, BRF_GRA }, // 4 + { "11h_12.bin", 0x02000, 0x4050c048, BRF_GRA }, // 5 + + { "e.6a", 0x08000, 0xe8fbc7d2, BRF_GRA }, // 6 Sprites + { "d.8a", 0x08000, 0xc5d4156b, BRF_GRA }, // 7 + { "c.10a", 0x08000, 0xde91dfb1, BRF_GRA }, // 8 + + { "01j.bin", 0x00100, 0x6a94b2a3, BRF_GRA }, // 9 PROMs + { "01h.bin", 0x00100, 0xec0923d3, BRF_GRA }, // 10 + { "01f.bin", 0x00100, 0xade97052, BRF_GRA }, // 11 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 12 + + { "pal16l8a.2j", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, // 13 PLDs + { "epl12p6a.9j", 0x00034, 0x19808f14, BRF_OPT }, // 14 + { "epl12p6a.9k", 0x00034, 0xf5acad85, BRF_OPT }, // 15 +}; + +STD_ROM_PICK(Airwolf) +STD_ROM_FN(Airwolf) + +static struct BurnRomInfo AirwolfaRomDesc[] = { + { "airwolf.2", 0x08000, 0xbc1a8587, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + + { "airwolf.1", 0x08000, 0xa3c7af5c, BRF_ESS | BRF_PRG }, // 1 Z80 #2 Program + + { "airwolf.6", 0x02000, 0x5b0a01e9, BRF_GRA }, // 2 Characters + + { "airwolf.9", 0x02000, 0x25e57e1f, BRF_GRA }, // 3 Tiles + { "airwolf.8", 0x02000, 0xcf0de5e9, BRF_GRA }, // 4 + { "airwolf.7", 0x02000, 0x4050c048, BRF_GRA }, // 5 + + { "airwolf.5", 0x08000, 0xe8fbc7d2, BRF_GRA }, // 6 Sprites + { "airwolf.4", 0x08000, 0xc5d4156b, BRF_GRA }, // 7 + { "airwolf.3", 0x08000, 0xde91dfb1, BRF_GRA }, // 8 + + { "01j.bin", 0x00100, 0x6a94b2a3, BRF_GRA }, // 9 PROMs + { "01h.bin", 0x00100, 0xec0923d3, BRF_GRA }, // 10 + { "01f.bin", 0x00100, 0xade97052, BRF_GRA }, // 11 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 12 + + { "pal16l8a.2j", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, // 13 PLDs + { "epl12p6a.9j", 0x00034, 0x19808f14, BRF_OPT }, // 14 + { "epl12p6a.9k", 0x00034, 0xf5acad85, BRF_OPT }, // 15 +}; + +STD_ROM_PICK(Airwolfa) +STD_ROM_FN(Airwolfa) + +static struct BurnRomInfo SkywolfRomDesc[] = { + { "02s_03.bin", 0x04000, 0xa0891798, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "03s_04.bin", 0x04000, 0x5f515d46, BRF_ESS | BRF_PRG }, // 1 Z80 + + { "07s_01.bin", 0x04000, 0xc680a905, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + { "08s_02.bin", 0x04000, 0x3d66bf26, BRF_ESS | BRF_PRG }, // 3 Z80 + + { "04a_11.bin", 0x01000, 0x219de9aa, BRF_GRA }, // 4 Characters + + { "09h_14.bin", 0x02000, 0x25e57e1f, BRF_GRA }, // 5 Tiles + { "10h_13.bin", 0x02000, 0xcf0de5e9, BRF_GRA }, // 6 + { "11h_12.bin", 0x02000, 0x4050c048, BRF_GRA }, // 7 + + { "06a_10.bin", 0x04000, 0x1c809383, BRF_GRA }, // 6 Sprites + { "07a_09.bin", 0x04000, 0x5665d774, BRF_GRA }, // 7 + { "08a_08.bin", 0x04000, 0x6dda8f2a, BRF_GRA }, // 8 + { "09a_07.bin", 0x04000, 0x6a21ddb8, BRF_GRA }, // 9 + { "10a_06.bin", 0x04000, 0xf2e548e0, BRF_GRA }, // 10 + { "11a_05.bin", 0x04000, 0x8681b112, BRF_GRA }, // 11 + + { "01j.bin", 0x00100, 0x6a94b2a3, BRF_GRA }, // 12 PROMs + { "01h.bin", 0x00100, 0xec0923d3, BRF_GRA }, // 13 + { "01f.bin", 0x00100, 0xade97052, BRF_GRA }, // 14 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 15 +}; + +STD_ROM_PICK(Skywolf) +STD_ROM_FN(Skywolf) + +static struct BurnRomInfo Skywolf2RomDesc[] = { + { "z80_2.bin", 0x08000, 0x34db7bda, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + + { "07s_01.bin", 0x04000, 0xc680a905, BRF_ESS | BRF_PRG }, // 1 Z80 #2 Program + { "08s_02.bin", 0x04000, 0x3d66bf26, BRF_ESS | BRF_PRG }, // 2 Z80 + + { "04a_11.bin", 0x01000, 0x219de9aa, BRF_GRA }, // 3 Characters + + { "09h_14.bin", 0x02000, 0x25e57e1f, BRF_GRA }, // 4 Tiles + { "10h_13.bin", 0x02000, 0xcf0de5e9, BRF_GRA }, // 5 + { "11h_12.bin", 0x02000, 0x4050c048, BRF_GRA }, // 6 + + { "06a_10.bin", 0x04000, 0x1c809383, BRF_GRA }, // 7 Sprites + { "07a_09.bin", 0x04000, 0x5665d774, BRF_GRA }, // 8 + { "08a_08.bin", 0x04000, 0x6dda8f2a, BRF_GRA }, // 9 + { "09a_07.bin", 0x04000, 0x6a21ddb8, BRF_GRA }, // 10 + { "10a_06.bin", 0x04000, 0xf2e548e0, BRF_GRA }, // 11 + { "11a_05.bin", 0x04000, 0x8681b112, BRF_GRA }, // 12 + + { "01j.bin", 0x00100, 0x6a94b2a3, BRF_GRA }, // 13 PROMs + { "01h.bin", 0x00100, 0xec0923d3, BRF_GRA }, // 14 + { "01f.bin", 0x00100, 0xade97052, BRF_GRA }, // 15 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 16 +}; + +STD_ROM_PICK(Skywolf2) +STD_ROM_FN(Skywolf2) + +static struct BurnRomInfo Skywolf3RomDesc[] = { + { "1.bin", 0x08000, 0x74a86ec8, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "2.bin", 0x08000, 0xf02143de, BRF_ESS | BRF_PRG }, // 1 + + { "3.bin", 0x08000, 0x787cdd0a, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + { "4.bin", 0x08000, 0x07a2c814, BRF_ESS | BRF_PRG }, // 3 Z80 + + { "8.bin", 0x08000, 0xb86d3dac, BRF_GRA }, // 4 Characters + + { "11.bin", 0x08000, 0xfc7bbf7a, BRF_GRA }, // 5 Tiles + { "10.bin", 0x08000, 0x1a3710ab, BRF_GRA }, // 6 + { "9.bin", 0x08000, 0xa184349a, BRF_GRA }, // 7 + + { "7.bin", 0x08000, 0x086612e8, BRF_GRA }, // 8 Sprites + { "6.bin", 0x08000, 0x3a9beabd, BRF_GRA }, // 9 + { "5.bin", 0x08000, 0xbd83658e, BRF_GRA }, // 10 + + { "82s129-1.bin", 0x00100, 0x6a94b2a3, BRF_GRA }, // 11 PROMs + { "82s129-2.bin", 0x00100, 0xec0923d3, BRF_GRA }, // 12 + { "82s129-3.bin", 0x00100, 0xade97052, BRF_GRA }, // 13 + { "74s288-2.bin", 0x00020, 0x190a55ad, BRF_GRA }, // 14 + { "74s288-1.bin", 0x00020, 0x5ddb2d15, BRF_GRA }, // 15 +}; + +STD_ROM_PICK(Skywolf3) +STD_ROM_FN(Skywolf3) + +static struct BurnRomInfo FlashgalRomDesc[] = { + { "epr-7167.4f", 0x02000, 0xcf5ad733, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7168.4h", 0x02000, 0x00c4851f, BRF_ESS | BRF_PRG }, // 1 + { "epr-7169.4j", 0x02000, 0x1ef0b8f7, BRF_ESS | BRF_PRG }, // 2 + { "epr-7170.4k", 0x02000, 0x885d53de, BRF_ESS | BRF_PRG }, // 3 + + { "epr-7163.2f", 0x02000, 0xeee2134d, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program + { "epr-7164.2h", 0x02000, 0xe5e0cd22, BRF_ESS | BRF_PRG }, // 5 + { "epr-7165.2j", 0x02000, 0x4cd3fe5e, BRF_ESS | BRF_PRG }, // 6 + { "epr-7166.2k", 0x02000, 0x552ca339, BRF_ESS | BRF_PRG }, // 7 + + { "epr-7177.4a", 0x01000, 0xdca9052f, BRF_GRA }, // 8 Characters + + { "epr-7178.9h", 0x02000, 0x2f5b62c0, BRF_GRA }, // 9 Tiles + { "epr-7179.10h", 0x02000, 0x8fbb49b5, BRF_GRA }, // 10 + { "epr-7180.11h", 0x02000, 0x26a8e5c3, BRF_GRA }, // 11 + + { "epr-7171.6a", 0x04000, 0x62caf2a1, BRF_GRA }, // 12 Sprites + { "epr-7172.7a", 0x04000, 0x10f78a10, BRF_GRA }, // 13 + { "epr-7173.8a", 0x04000, 0x36ea1d59, BRF_GRA }, // 14 + { "epr-7174.9a", 0x04000, 0xf527d837, BRF_GRA }, // 15 + { "epr-7175.10a", 0x04000, 0xba76e4c1, BRF_GRA }, // 16 + { "epr-7176.11a", 0x04000, 0xf095d619, BRF_GRA }, // 17 + + { "7161.1j", 0x00100, 0x02c4043f, BRF_GRA }, // 18 PROMs + { "7160.1h", 0x00100, 0x225938d1, BRF_GRA }, // 19 + { "7159.1f", 0x00100, 0x1e0a1cd3, BRF_GRA }, // 20 + { "7162.5j", 0x00020, 0xcce2e29f, BRF_GRA }, // 21 + { "bpr.2c", 0x00020, 0x83a39201, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Flashgal) +STD_ROM_FN(Flashgal) + +static struct BurnRomInfo FlashgalaRomDesc[] = { + { "flashgal.5", 0x02000, 0xaa889ace, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7168.4h", 0x02000, 0x00c4851f, BRF_ESS | BRF_PRG }, // 1 + { "epr-7169.4j", 0x02000, 0x1ef0b8f7, BRF_ESS | BRF_PRG }, // 2 + { "epr-7170.4k", 0x02000, 0x885d53de, BRF_ESS | BRF_PRG }, // 3 + + { "flashgal.1", 0x02000, 0x55171cc1, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program + { "flashgal.2", 0x02000, 0x3fd21aac, BRF_ESS | BRF_PRG }, // 5 + { "flashgal.3", 0x02000, 0xa1223b74, BRF_ESS | BRF_PRG }, // 6 + { "flashgal.4", 0x02000, 0x04d2a05f, BRF_ESS | BRF_PRG }, // 7 + + { "epr-7177.4a", 0x01000, 0xdca9052f, BRF_GRA }, // 8 Characters + + { "epr-7178.9h", 0x02000, 0x2f5b62c0, BRF_GRA }, // 9 Tiles + { "epr-7179.10h", 0x02000, 0x8fbb49b5, BRF_GRA }, // 10 + { "epr-7180.11h", 0x02000, 0x26a8e5c3, BRF_GRA }, // 11 + + { "epr-7171.6a", 0x04000, 0x62caf2a1, BRF_GRA }, // 12 Sprites + { "epr-7172.7a", 0x04000, 0x10f78a10, BRF_GRA }, // 13 + { "epr-7173.8a", 0x04000, 0x36ea1d59, BRF_GRA }, // 14 + { "epr-7174.9a", 0x04000, 0xf527d837, BRF_GRA }, // 15 + { "epr-7175.10a", 0x04000, 0xba76e4c1, BRF_GRA }, // 16 + { "epr-7176.11a", 0x04000, 0xf095d619, BRF_GRA }, // 17 + + { "7161.1j", 0x00100, 0x02c4043f, BRF_GRA }, // 18 PROMs + { "7160.1h", 0x00100, 0x225938d1, BRF_GRA }, // 19 + { "7159.1f", 0x00100, 0x1e0a1cd3, BRF_GRA }, // 20 + { "7162.5j", 0x00020, 0xcce2e29f, BRF_GRA }, // 21 + { "bpr.2c", 0x00020, 0x83a39201, BRF_GRA }, // 22 +}; + +STD_ROM_PICK(Flashgala) +STD_ROM_FN(Flashgala) + +static struct BurnRomInfo GyrodineRomDesc[] = { + { "rom2", 0x02000, 0x85ddea38, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a21.03", 0x02000, 0x4e9323bd, BRF_ESS | BRF_PRG }, // 1 + { "a21.04", 0x02000, 0x57e659d4, BRF_ESS | BRF_PRG }, // 2 + { "a21.05", 0x02000, 0x1e7293f3, BRF_ESS | BRF_PRG }, // 3 + + { "a21.01", 0x02000, 0xb2ce0aa2, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program + + { "a21.15", 0x01000, 0xadba18d0, BRF_GRA }, // 5 Characters + + { "a21.08", 0x02000, 0xa57df1c9, BRF_GRA }, // 6 Tiles + { "a21.07", 0x02000, 0x63623ba3, BRF_GRA }, // 7 + { "a21.06", 0x02000, 0x4cc969a9, BRF_GRA }, // 8 + + { "a21.14", 0x02000, 0x9c5c4d5b, BRF_GRA }, // 9 Sprites + { "a21.13", 0x02000, 0xd36b5aad, BRF_GRA }, // 10 + { "a21.12", 0x02000, 0xf387aea2, BRF_GRA }, // 11 + { "a21.11", 0x02000, 0x87967d7d, BRF_GRA }, // 12 + { "a21.10", 0x02000, 0x59640ab4, BRF_GRA }, // 13 + { "a21.09", 0x02000, 0x22ad88d8, BRF_GRA }, // 14 + + { "a21.16", 0x00100, 0xcc25fb56, BRF_GRA }, // 15 PROMs + { "a21.17", 0x00100, 0xca054448, BRF_GRA }, // 16 + { "a21.18", 0x00100, 0x23c0c449, BRF_GRA }, // 17 + { "a21.20", 0x00020, 0xefc4985e, BRF_GRA }, // 18 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 19 +}; + +STD_ROM_PICK(Gyrodine) +STD_ROM_FN(Gyrodine) + +static struct BurnRomInfo GyrodinetRomDesc[] = { + { "a21.02", 0x02000, 0xc5ec4a50, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a21.03", 0x02000, 0x4e9323bd, BRF_ESS | BRF_PRG }, // 1 + { "a21.04", 0x02000, 0x57e659d4, BRF_ESS | BRF_PRG }, // 2 + { "a21.05", 0x02000, 0x1e7293f3, BRF_ESS | BRF_PRG }, // 3 + + { "a21.01", 0x02000, 0xb2ce0aa2, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program + + { "a21.15", 0x01000, 0xadba18d0, BRF_GRA }, // 5 Characters + + { "a21.08", 0x02000, 0xa57df1c9, BRF_GRA }, // 6 Tiles + { "a21.07", 0x02000, 0x63623ba3, BRF_GRA }, // 7 + { "a21.06", 0x02000, 0x4cc969a9, BRF_GRA }, // 8 + + { "a21.14", 0x02000, 0x9c5c4d5b, BRF_GRA }, // 9 Sprites + { "a21.13", 0x02000, 0xd36b5aad, BRF_GRA }, // 10 + { "a21.12", 0x02000, 0xf387aea2, BRF_GRA }, // 11 + { "a21.11", 0x02000, 0x87967d7d, BRF_GRA }, // 12 + { "a21.10", 0x02000, 0x59640ab4, BRF_GRA }, // 13 + { "a21.09", 0x02000, 0x22ad88d8, BRF_GRA }, // 14 + + { "a21.16", 0x00100, 0xcc25fb56, BRF_GRA }, // 15 PROMs + { "a21.17", 0x00100, 0xca054448, BRF_GRA }, // 16 + { "a21.18", 0x00100, 0x23c0c449, BRF_GRA }, // 17 + { "a21.20", 0x00020, 0xefc4985e, BRF_GRA }, // 18 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 19 +}; + +STD_ROM_PICK(Gyrodinet) +STD_ROM_FN(Gyrodinet) + +static struct BurnRomInfo BuzzardRomDesc[] = { + { "rom2", 0x02000, 0x85ddea38, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a21.03", 0x02000, 0x4e9323bd, BRF_ESS | BRF_PRG }, // 1 + { "a21.04", 0x02000, 0x57e659d4, BRF_ESS | BRF_PRG }, // 2 + { "a21.05", 0x02000, 0x1e7293f3, BRF_ESS | BRF_PRG }, // 3 + + { "a21.01", 0x02000, 0xb2ce0aa2, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program + + { "buzl01.bin", 0x01000, 0x65d728d0, BRF_GRA }, // 5 Characters + + { "a21.08", 0x02000, 0xa57df1c9, BRF_GRA }, // 6 Tiles + { "a21.07", 0x02000, 0x63623ba3, BRF_GRA }, // 7 + { "a21.06", 0x02000, 0x4cc969a9, BRF_GRA }, // 8 + + { "a21.14", 0x02000, 0x9c5c4d5b, BRF_GRA }, // 9 Sprites + { "a21.13", 0x02000, 0xd36b5aad, BRF_GRA }, // 10 + { "a21.12", 0x02000, 0xf387aea2, BRF_GRA }, // 11 + { "a21.11", 0x02000, 0x87967d7d, BRF_GRA }, // 12 + { "a21.10", 0x02000, 0x59640ab4, BRF_GRA }, // 13 + { "a21.09", 0x02000, 0x22ad88d8, BRF_GRA }, // 14 + + { "a21.16", 0x00100, 0xcc25fb56, BRF_GRA }, // 15 PROMs + { "a21.17", 0x00100, 0xca054448, BRF_GRA }, // 16 + { "a21.18", 0x00100, 0x23c0c449, BRF_GRA }, // 17 + { "a21.20", 0x00020, 0xefc4985e, BRF_GRA }, // 18 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 19 +}; + +STD_ROM_PICK(Buzzard) +STD_ROM_FN(Buzzard) + +static struct BurnRomInfo LegendRomDesc[] = { + { "a_r2.rom", 0x04000, 0x0cc1c4f4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a_r3.rom", 0x04000, 0x4b270c6b, BRF_ESS | BRF_PRG }, // 1 + + { "a_r7.rom", 0x02000, 0xabfe5eb4, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + { "a_r8.rom", 0x02000, 0x7e7b9ba9, BRF_ESS | BRF_PRG }, // 3 + { "a_r9.rom", 0x02000, 0x66737f1e, BRF_ESS | BRF_PRG }, // 4 + { "a_n7.rom", 0x02000, 0x13915a53, BRF_ESS | BRF_PRG }, // 5 + + { "b_a4.rom", 0x01000, 0xc7dd3cf7, BRF_GRA }, // 6 Characters + + { "b_h9.rom", 0x02000, 0x1fe8644a, BRF_GRA }, // 7 Tiles + { "b_h10.rom", 0x02000, 0x5f7dc82e, BRF_GRA }, // 8 + { "b_h11.rom", 0x02000, 0x46741643, BRF_GRA }, // 9 + + { "b_a6.rom", 0x04000, 0x1689f21c, BRF_GRA }, // 10 Sprites + { "b_a7.rom", 0x04000, 0xf527c909, BRF_GRA }, // 11 + { "b_a8.rom", 0x04000, 0x8d618629, BRF_GRA }, // 12 + { "b_a9.rom", 0x04000, 0x7d7e2d55, BRF_GRA }, // 13 + { "b_a10.rom", 0x04000, 0xf12232fe, BRF_GRA }, // 14 + { "b_a11.rom", 0x04000, 0x8c09243d, BRF_GRA }, // 15 + + { "82s129.1j", 0x00100, 0x40590ac0, BRF_GRA }, // 16 PROMs + { "82s129.1h", 0x00100, 0xe542b363, BRF_GRA }, // 17 + { "82s129.1f", 0x00100, 0x75536fc8, BRF_GRA }, // 18 + { "82s123.5j", 0x00020, 0xc98f0651, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 + + { "epl10p8.2j", 0x0002c, 0x8abc03bf, BRF_OPT }, // 21 PLDs + { "epl12p6.9k", 0x00034, 0x9b0bd6f8, BRF_OPT }, // 22 + { "epl12p6.9j", 0x00034, 0xdcae870d, BRF_OPT }, // 23 +}; + +STD_ROM_PICK(Legend) +STD_ROM_FN(Legend) + +static struct BurnRomInfo SonofphxRomDesc[] = { + { "5.f4", 0x02000, 0xe0d2c6cf, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "6.h4", 0x02000, 0x3a0d0336, BRF_ESS | BRF_PRG }, // 1 + { "7.j4", 0x02000, 0x57a8e900, BRF_ESS | BRF_PRG }, // 2 + + { "1.f2", 0x02000, 0xc485c621, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + { "2.h2", 0x02000, 0xb3c6a886, BRF_ESS | BRF_PRG }, // 4 + { "3.j2", 0x02000, 0x197e314c, BRF_ESS | BRF_PRG }, // 5 + { "4.k2", 0x02000, 0x4f3695a1, BRF_ESS | BRF_PRG }, // 6 + + { "14.4a", 0x01000, 0xb3859b8b, BRF_GRA }, // 7 Characters + + { "15.9h", 0x02000, 0xc9213469, BRF_GRA }, // 8 Tiles + { "16.10h", 0x02000, 0x7de5d39e, BRF_GRA }, // 9 + { "17.11h", 0x02000, 0x0ba5f72c, BRF_GRA }, // 10 + + { "8.6a", 0x04000, 0x0e9f757e, BRF_GRA }, // 11 Sprites + { "9.7a", 0x04000, 0xf7d2e650, BRF_GRA }, // 12 + { "10.8a", 0x04000, 0xe717baf4, BRF_GRA }, // 13 + { "11.9a", 0x04000, 0x04b2250b, BRF_GRA }, // 14 + { "12.10a", 0x04000, 0xd110e140, BRF_GRA }, // 15 + { "13.11a", 0x04000, 0x8fdc713c, BRF_GRA }, // 16 + + { "b.1j", 0x00100, 0x3ea35431, BRF_GRA }, // 17 PROMs + { "g.1h", 0x00100, 0xacd7a69e, BRF_GRA }, // 18 + { "r.1f", 0x00100, 0xb7f48b41, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 +}; + +STD_ROM_PICK(Sonofphx) +STD_ROM_FN(Sonofphx) + +static struct BurnRomInfo RepulseRomDesc[] = { + { "repulse.b5", 0x02000, 0xfb2b7c9d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "repulse.b6", 0x02000, 0x99129918, BRF_ESS | BRF_PRG }, // 1 + { "7.j4", 0x02000, 0x57a8e900, BRF_ESS | BRF_PRG }, // 2 + + { "1.f2", 0x02000, 0xc485c621, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + { "2.h2", 0x02000, 0xb3c6a886, BRF_ESS | BRF_PRG }, // 4 + { "3.j2", 0x02000, 0x197e314c, BRF_ESS | BRF_PRG }, // 5 + { "repulse.b4", 0x02000, 0x86b267f3, BRF_ESS | BRF_PRG }, // 6 + + { "repulse.a11", 0x01000, 0x8e1de90a, BRF_GRA }, // 7 Characters + + { "15.9h", 0x02000, 0xc9213469, BRF_GRA }, // 8 Tiles + { "16.10h", 0x02000, 0x7de5d39e, BRF_GRA }, // 9 + { "17.11h", 0x02000, 0x0ba5f72c, BRF_GRA }, // 10 + + { "8.6a", 0x04000, 0x0e9f757e, BRF_GRA }, // 11 Sprites + { "9.7a", 0x04000, 0xf7d2e650, BRF_GRA }, // 12 + { "10.8a", 0x04000, 0xe717baf4, BRF_GRA }, // 13 + { "11.9a", 0x04000, 0x04b2250b, BRF_GRA }, // 14 + { "12.10a", 0x04000, 0xd110e140, BRF_GRA }, // 15 + { "13.11a", 0x04000, 0x8fdc713c, BRF_GRA }, // 16 + + { "b.1j", 0x00100, 0x3ea35431, BRF_GRA }, // 17 PROMs + { "g.1h", 0x00100, 0xacd7a69e, BRF_GRA }, // 18 + { "r.1f", 0x00100, 0xb7f48b41, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 +}; + +STD_ROM_PICK(Repulse) +STD_ROM_FN(Repulse) + +static struct BurnRomInfo Lstwar99RomDesc[] = { + { "1999.4f", 0x02000, 0xe3cfc09f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "1999.4h", 0x02000, 0xfd58c6e1, BRF_ESS | BRF_PRG }, // 1 + { "7.j4", 0x02000, 0x57a8e900, BRF_ESS | BRF_PRG }, // 2 + + { "1.f2", 0x02000, 0xc485c621, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + { "2.h2", 0x02000, 0xb3c6a886, BRF_ESS | BRF_PRG }, // 4 + { "3.j2", 0x02000, 0x197e314c, BRF_ESS | BRF_PRG }, // 5 + { "repulse.b4", 0x02000, 0x86b267f3, BRF_ESS | BRF_PRG }, // 6 + + { "1999.4a", 0x01000, 0x49a2383e, BRF_GRA }, // 7 Characters + + { "15.9h", 0x02000, 0xc9213469, BRF_GRA }, // 8 Tiles + { "16.10h", 0x02000, 0x7de5d39e, BRF_GRA }, // 9 + { "17.11h", 0x02000, 0x0ba5f72c, BRF_GRA }, // 10 + + { "8.6a", 0x04000, 0x0e9f757e, BRF_GRA }, // 11 Sprites + { "9.7a", 0x04000, 0xf7d2e650, BRF_GRA }, // 12 + { "10.8a", 0x04000, 0xe717baf4, BRF_GRA }, // 13 + { "11.9a", 0x04000, 0x04b2250b, BRF_GRA }, // 14 + { "12.10a", 0x04000, 0xd110e140, BRF_GRA }, // 15 + { "13.11a", 0x04000, 0x8fdc713c, BRF_GRA }, // 16 + + { "b.1j", 0x00100, 0x3ea35431, BRF_GRA }, // 17 PROMs + { "g.1h", 0x00100, 0xacd7a69e, BRF_GRA }, // 18 + { "r.1f", 0x00100, 0xb7f48b41, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 +}; + +STD_ROM_PICK(Lstwar99) +STD_ROM_FN(Lstwar99) + +static struct BurnRomInfo Lstwra99RomDesc[] = { + { "4f.bin", 0x02000, 0xefe2908d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "4h.bin", 0x02000, 0x5b79c342, BRF_ESS | BRF_PRG }, // 1 + { "4j.bin", 0x02000, 0xd2a62c1b, BRF_ESS | BRF_PRG }, // 2 + + { "2f.bin", 0x02000, 0xcb9d8291, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + { "2h.bin", 0x02000, 0x24dbddc3, BRF_ESS | BRF_PRG }, // 4 + { "2j.bin", 0x02000, 0x16879c4c, BRF_ESS | BRF_PRG }, // 5 + { "repulse.b4", 0x02000, 0x86b267f3, BRF_ESS | BRF_PRG }, // 6 + + { "1999.4a", 0x01000, 0x49a2383e, BRF_GRA }, // 7 Characters + + { "9h.bin", 0x02000, 0x59993c27, BRF_GRA }, // 8 Tiles + { "10h.bin", 0x02000, 0xdfbf0280, BRF_GRA }, // 9 + { "11h.bin", 0x02000, 0xe4f29fc0, BRF_GRA }, // 10 + + { "6a.bin", 0x04000, 0x98d44410, BRF_GRA }, // 11 Sprites + { "7a.bin", 0x04000, 0x4c54d281, BRF_GRA }, // 12 + { "8a.bin", 0x04000, 0x81018101, BRF_GRA }, // 13 + { "9a.bin", 0x04000, 0x347b91fd, BRF_GRA }, // 14 + { "10a.bin", 0x04000, 0xf07de4fa, BRF_GRA }, // 15 + { "11a.bin", 0x04000, 0x34a04f48, BRF_GRA }, // 16 + + { "b.1j", 0x00100, 0x3ea35431, BRF_GRA }, // 17 PROMs + { "g.1h", 0x00100, 0xacd7a69e, BRF_GRA }, // 18 + { "r.1f", 0x00100, 0xb7f48b41, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 +}; + +STD_ROM_PICK(Lstwra99) +STD_ROM_FN(Lstwra99) + +static struct BurnRomInfo Lstwrk99RomDesc[] = { + { "1999.4f", 0x02000, 0xe3cfc09f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "1999.4h", 0x02000, 0xfd58c6e1, BRF_ESS | BRF_PRG }, // 1 + { "7.j4", 0x02000, 0x57a8e900, BRF_ESS | BRF_PRG }, // 2 + + { "1.f2", 0x02000, 0xc485c621, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + { "2.h2", 0x02000, 0xb3c6a886, BRF_ESS | BRF_PRG }, // 4 + { "3.j2", 0x02000, 0x197e314c, BRF_ESS | BRF_PRG }, // 5 + { "repulse.b4", 0x02000, 0x86b267f3, BRF_ESS | BRF_PRG }, // 6 + + { "1999-14.rom", 0x01000, 0xb4995072, BRF_GRA }, // 7 Characters + + { "15.9h", 0x02000, 0xc9213469, BRF_GRA }, // 8 Tiles + { "16.10h", 0x02000, 0x7de5d39e, BRF_GRA }, // 9 + { "17.11h", 0x02000, 0x0ba5f72c, BRF_GRA }, // 10 + + { "8.6a", 0x04000, 0x0e9f757e, BRF_GRA }, // 11 Sprites + { "9.7a", 0x04000, 0xf7d2e650, BRF_GRA }, // 12 + { "10.8a", 0x04000, 0xe717baf4, BRF_GRA }, // 13 + { "11.9a", 0x04000, 0x04b2250b, BRF_GRA }, // 14 + { "12.10a", 0x04000, 0xd110e140, BRF_GRA }, // 15 + { "13.11a", 0x04000, 0x8fdc713c, BRF_GRA }, // 16 + + { "b.1j", 0x00100, 0x3ea35431, BRF_GRA }, // 17 PROMs + { "g.1h", 0x00100, 0xacd7a69e, BRF_GRA }, // 18 + { "r.1f", 0x00100, 0xb7f48b41, BRF_GRA }, // 19 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 20 + { "1999-00.rom", 0x00800, 0x0c0c449f, BRF_GRA }, // 21 +}; + +STD_ROM_PICK(Lstwrk99) +STD_ROM_FN(Lstwrk99) + +static struct BurnRomInfo SrdmissnRomDesc[] = { + { "5.t2", 0x04000, 0xa682b48c, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "7.t3", 0x04000, 0x1719c58c, BRF_ESS | BRF_PRG }, // 1 + + { "1.t7", 0x04000, 0xdc48595e, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + { "3.t8", 0x04000, 0x216be1e8, BRF_ESS | BRF_PRG }, // 3 + + { "15.4a", 0x01000, 0x4961f7fd, BRF_GRA }, // 4 Characters + + { "17.9h", 0x02000, 0x41211458, BRF_GRA }, // 5 Tiles + { "18.10h", 0x02000, 0x740eccd4, BRF_GRA }, // 6 + { "16.11h", 0x02000, 0xc1f4a5db, BRF_GRA }, // 7 + + { "14.6a", 0x04000, 0x3d4c0447, BRF_GRA }, // 8 Sprites + { "13.7a", 0x04000, 0x22414a67, BRF_GRA }, // 9 + { "12.8a", 0x04000, 0x61e34283, BRF_GRA }, // 10 + { "11.9a", 0x04000, 0xbbbaffef, BRF_GRA }, // 11 + { "10.10a", 0x04000, 0xde564f97, BRF_GRA }, // 12 + { "9.11a", 0x04000, 0x890dc815, BRF_GRA }, // 13 + + { "mr.1j", 0x00100, 0x110a436e, BRF_GRA }, // 14 PROMs + { "mg.1h", 0x00100, 0x0fbfd9f0, BRF_GRA }, // 15 + { "mb.1f", 0x00100, 0xa342890c, BRF_GRA }, // 16 + { "m2.5j", 0x00020, 0x190a55ad, BRF_GRA }, // 17 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Srdmissn) +STD_ROM_FN(Srdmissn) + +static struct BurnRomInfo FxRomDesc[] = { + { "fx.01", 0x04000, 0xb651754b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "fx.02", 0x04000, 0xf3d2dcc1, BRF_ESS | BRF_PRG }, // 1 + + { "fx.03", 0x04000, 0x8907df6b, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + { "fx.04", 0x04000, 0xc665834f, BRF_ESS | BRF_PRG }, // 3 + + { "fx.05", 0x01000, 0x4a504286, BRF_GRA }, // 4 Characters + + { "17.9h", 0x02000, 0x41211458, BRF_GRA }, // 5 Tiles + { "18.10h", 0x02000, 0x740eccd4, BRF_GRA }, // 6 + { "16.11h", 0x02000, 0xc1f4a5db, BRF_GRA }, // 7 + + { "14.6a", 0x04000, 0x3d4c0447, BRF_GRA }, // 8 Sprites + { "13.7a", 0x04000, 0x22414a67, BRF_GRA }, // 9 + { "12.8a", 0x04000, 0x61e34283, BRF_GRA }, // 10 + { "11.9a", 0x04000, 0xbbbaffef, BRF_GRA }, // 11 + { "10.10a", 0x04000, 0xde564f97, BRF_GRA }, // 12 + { "9.11a", 0x04000, 0x890dc815, BRF_GRA }, // 13 + + { "mr.1j", 0x00100, 0x110a436e, BRF_GRA }, // 14 PROMs + { "mg.1h", 0x00100, 0x0fbfd9f0, BRF_GRA }, // 15 + { "mb.1f", 0x00100, 0xa342890c, BRF_GRA }, // 16 + { "m2.5j", 0x00020, 0x190a55ad, BRF_GRA }, // 17 + { "m1.2c", 0x00020, 0x83a39201, BRF_GRA }, // 18 +}; + +STD_ROM_PICK(Fx) +STD_ROM_FN(Fx) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + KyugoZ80Rom1 = Next; Next += 0x08000; + KyugoZ80Rom2 = Next; Next += 0x08000; + KyugoPromRed = Next; Next += 0x00100; + KyugoPromGreen = Next; Next += 0x00100; + KyugoPromBlue = Next; Next += 0x00100; + KyugoPromCharLookup = Next; Next += 0x00020; + + RamStart = Next; + + KyugoSharedZ80Ram = Next; Next += 0x00800; + KyugoZ80Ram2 = Next; Next += 0x00800; + KyugoSprite1Ram = Next; Next += 0x00800; + KyugoSprite2Ram = Next; Next += 0x00800; + KyugoFgVideoRam = Next; Next += 0x00800; + KyugoBgVideoRam = Next; Next += 0x00800; + KyugoBgAttrRam = Next; Next += 0x00800; + + RamEnd = Next; + + KyugoChars = Next; Next += 0x100 * 8 * 8; + KyugoTiles = Next; Next += 0x400 * 8 * 8; + KyugoSprites = Next; Next += 0x400 * 16 * 16; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + KyugoPalette = (UINT32*)Next; Next += 256 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 KyugoDoReset() +{ + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + for (INT32 i = 0; i < 2; i++) { + AY8910Reset(i); + } + + KyugoIRQEnable = 0; + KyugoSubCPUEnable = 0; + KyugoFgColour = 0; + KyugoBgPaletteBank = 0; + KyugoBgScrollXHi = 0; + KyugoBgScrollXLo = 0; + KyugoBgScrollY = 0; + KyugoFlipScreen = 0; + + return 0; +} + +UINT8 __fastcall KyugoRead1(UINT16 a) +{ + if (a >= 0x9800 && a <= 0x9fff) { + return KyugoSprite2Ram[a - 0x9800] | 0xf0; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall KyugoWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xa800: { + KyugoBgScrollXLo = d; + return; + } + + case 0xb000: { + KyugoBgScrollXHi = d & 1; + KyugoFgColour = (d & 0x20) >> 5; + KyugoBgPaletteBank = (d & 0x40) >> 6; + return; + } + + case 0xb800: { + KyugoBgScrollY = d; + return; + } + + + case 0xe000: { + // watchdog write + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall FlashgalPortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x40: { + KyugoIRQEnable = d & 1; + return; + } + + case 0x41: { + KyugoFlipScreen = d & 1; + return; + } + + case 0x42: { + KyugoSubCPUEnable = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall FlashgalaPortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0xc0: { + KyugoIRQEnable = d & 1; + return; + } + + case 0xc1: { + KyugoFlipScreen = d & 1; + return; + } + + case 0xc2: { + KyugoSubCPUEnable = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall GyrodinePortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + KyugoIRQEnable = d & 1; + return; + } + + case 0x01: { + KyugoFlipScreen = d & 1; + return; + } + + case 0x02: { + KyugoSubCPUEnable = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall SrdmissnPortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x08: { + KyugoIRQEnable = d & 1; + return; + } + + case 0x09: { + KyugoFlipScreen = d & 1; + return; + } + + case 0x0a: { + KyugoSubCPUEnable = d & 1; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall FlashgalRead2(UINT16 a) +{ + switch (a) { + case 0xc000: { + return KyugoInput[2]; + } + + case 0xc040: { + return KyugoInput[1]; + } + + case 0xc080: { + return KyugoInput[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall FlashgalaRead2(UINT16 a) +{ + switch (a) { + case 0xc040: { + return KyugoInput[0]; + } + + case 0xc080: { + return KyugoInput[1]; + } + + case 0xc0c0: { + return KyugoInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall GyrodineRead2(UINT16 a) +{ + switch (a) { + case 0x8000: { + return KyugoInput[2]; + } + + case 0x8040: { + return KyugoInput[1]; + } + + case 0x8080: { + return KyugoInput[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall SrdmissnRead2(UINT16 a) +{ + switch (a) { + case 0xf400: { + return KyugoInput[0]; + } + + case 0xf401: { + return KyugoInput[1]; + } + + case 0xf402: { + return KyugoInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall LegendRead2(UINT16 a) +{ + switch (a) { + case 0xf800: { + return KyugoInput[0]; + } + + case 0xf801: { + return KyugoInput[1]; + } + + case 0xf802: { + return KyugoInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall KyugoWrite2(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KyugoPortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x02: { + return AY8910Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall FlashgalaPortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x42: { + return AY8910Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall SrdmissnPortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x82: { + return AY8910Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall FlashgalPortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + AY8910Write(0, 0, d); + return; + } + + case 0x01: { + AY8910Write(0, 1, d); + return; + } + + case 0x40: { + AY8910Write(1, 0, d); + return; + } + + case 0x41: { + AY8910Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall FlashgalaPortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x40: { + AY8910Write(0, 0, d); + return; + } + + case 0x41: { + AY8910Write(0, 1, d); + return; + } + + case 0x80: { + AY8910Write(1, 0, d); + return; + } + + case 0x81: { + AY8910Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall GyrodinePortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + AY8910Write(0, 0, d); + return; + } + + case 0x01: { + AY8910Write(0, 1, d); + return; + } + + case 0xc0: { + AY8910Write(1, 0, d); + return; + } + + case 0xc1: { + AY8910Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +void __fastcall SrdmissnPortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x80: { + AY8910Write(0, 0, d); + return; + } + + case 0x81: { + AY8910Write(0, 1, d); + return; + } + + case 0x84: { + AY8910Write(1, 0, d); + return; + } + + case 0x85: { + AY8910Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[2] = { 0, 4 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 64, 65, 66, 67 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 TilePlaneOffsets[3] = { 0, 0x10000, 0x20000 }; +static INT32 TileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TileYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 SpritePlaneOffsets[3] = { 0, 0x40000, 0x80000 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + +static UINT8 KyugoDip0Read(UINT32 /*a*/) +{ + return KyugoDip[0]; +} + +static UINT8 KyugoDip1Read(UINT32 /*a*/) +{ + return KyugoDip[1]; +} + +static INT32 KyugoInit() +{ + INT32 nRet = 0, nLen, i; + + KyugoNumZ80Rom1 = 4; + KyugoNumZ80Rom2 = 4; + KyugoNumSpriteRom = 6; + KyugoSizeZ80Rom1 = 0x2000; + KyugoSizeZ80Rom2 = 0x2000; + KyugoSizeSpriteRom = 0x4000; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "airwolf") || !strcmp(BurnDrvGetTextA(DRV_NAME), "airwolfa")) { + KyugoNumZ80Rom1 = 1; + KyugoNumZ80Rom2 = 1; + KyugoNumSpriteRom = 3; + KyugoSizeZ80Rom1 = 0x8000; + KyugoSizeZ80Rom2 = 0x8000; + KyugoSizeSpriteRom = 0x8000; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodine") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodinet") || !strcmp(BurnDrvGetTextA(DRV_NAME), "buzzard")) { + KyugoNumZ80Rom2 = 1; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "legend")) { + KyugoNumZ80Rom1 = 2; + KyugoNumZ80Rom2 = 4; + KyugoSizeZ80Rom1 = 0x4000; + KyugoSizeZ80Rom2 = 0x2000; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "sonofphx") || !strcmp(BurnDrvGetTextA(DRV_NAME), "repulse") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwar") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwara") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwark")) { + KyugoNumZ80Rom1 = 3; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "skywolf") || !strcmp(BurnDrvGetTextA(DRV_NAME), "srdmissn") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fx")) { + KyugoNumZ80Rom1 = 2; + KyugoNumZ80Rom2 = 2; + KyugoSizeZ80Rom1 = 0x4000; + KyugoSizeZ80Rom2 = 0x4000; + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "skywolf2")) { + KyugoNumZ80Rom1 = 1; + KyugoNumZ80Rom2 = 2; + KyugoSizeZ80Rom1 = 0x8000; + KyugoSizeZ80Rom2 = 0x4000; + } + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + KyugoTempRom = (UINT8 *)BurnMalloc(0x18000); + + // Load Z80 #1 Program Roms + for (i = 0; i < KyugoNumZ80Rom1; i++) { + nRet = BurnLoadRom(KyugoZ80Rom1 + (KyugoSizeZ80Rom1 * i), i, 1); if (nRet != 0) return 1; + } + + // Load Z80 #2 Program Roms + for (i = KyugoNumZ80Rom1; i < KyugoNumZ80Rom2 + KyugoNumZ80Rom1; i++) { + nRet = BurnLoadRom(KyugoZ80Rom2 + (KyugoSizeZ80Rom2 * (i - KyugoNumZ80Rom1)), i, 1); if (nRet != 0) return 1; + } + + // Load and decode the chars + nRet = BurnLoadRom(KyugoTempRom, KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 0, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, KyugoTempRom, KyugoChars); + + // Load and decode the tiles + memset(KyugoTempRom, 0, 0x18000); + nRet = BurnLoadRom(KyugoTempRom + 0x00000, KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoTempRom + 0x02000, KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoTempRom + 0x04000, KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 3, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, KyugoTempRom, KyugoTiles); + + // Load and decode the sprites + memset(KyugoTempRom, 0, 0x18000); + for (i = KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 4; i < KyugoNumSpriteRom + KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 4; i++) { + nRet = BurnLoadRom(KyugoTempRom + (KyugoSizeSpriteRom * (i - KyugoNumZ80Rom2 - KyugoNumZ80Rom1 - 4)), i, 1); if (nRet != 0) return 1; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "airwolf") || !strcmp(BurnDrvGetTextA(DRV_NAME), "airwolfa")) { + UINT8 *Temp = (UINT8*)BurnMalloc(0x18000); + memcpy(Temp, KyugoTempRom, 0x18000); + memcpy(KyugoTempRom + 0x00000, Temp + 0x00000, 0x2000); + memcpy(KyugoTempRom + 0x04000, Temp + 0x02000, 0x2000); + memcpy(KyugoTempRom + 0x02000, Temp + 0x04000, 0x2000); + memcpy(KyugoTempRom + 0x06000, Temp + 0x06000, 0x2000); + memcpy(KyugoTempRom + 0x08000, Temp + 0x08000, 0x2000); + memcpy(KyugoTempRom + 0x0c000, Temp + 0x0a000, 0x2000); + memcpy(KyugoTempRom + 0x0a000, Temp + 0x0c000, 0x2000); + memcpy(KyugoTempRom + 0x0e000, Temp + 0x0e000, 0x2000); + memcpy(KyugoTempRom + 0x10000, Temp + 0x10000, 0x2000); + memcpy(KyugoTempRom + 0x14000, Temp + 0x12000, 0x2000); + memcpy(KyugoTempRom + 0x12000, Temp + 0x14000, 0x2000); + memcpy(KyugoTempRom + 0x16000, Temp + 0x16000, 0x2000); + BurnFree(Temp); + } + GfxDecode(0x400, 3, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, KyugoTempRom, KyugoSprites); + + // Load the PROMs + nRet = BurnLoadRom(KyugoPromRed, KyugoNumSpriteRom + KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoPromGreen, KyugoNumSpriteRom + KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoPromBlue, KyugoNumSpriteRom + KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 6, 1); if (nRet != 0) return 1; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "flashgal") || !strcmp(BurnDrvGetTextA(DRV_NAME), "flashgala") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodine") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodinet") || !strcmp(BurnDrvGetTextA(DRV_NAME), "buzzard") || !strcmp(BurnDrvGetTextA(DRV_NAME), "legend") || !strcmp(BurnDrvGetTextA(DRV_NAME), "srdmissn") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fx")) { + nRet = BurnLoadRom(KyugoPromCharLookup, KyugoNumSpriteRom + KyugoNumZ80Rom2 + KyugoNumZ80Rom1 + 7, 1); if (nRet != 0) return 1; + } + + BurnFree(KyugoTempRom); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(KyugoRead1); + ZetSetWriteHandler(KyugoWrite1); + ZetMapArea(0x0000, 0x7fff, 0, KyugoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, KyugoZ80Rom1 ); + ZetMapArea(0x8000, 0x87ff, 0, KyugoBgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 1, KyugoBgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 2, KyugoBgVideoRam ); + ZetMapArea(0x8800, 0x8fff, 0, KyugoBgAttrRam ); + ZetMapArea(0x8800, 0x8fff, 1, KyugoBgAttrRam ); + ZetMapArea(0x8800, 0x8fff, 2, KyugoBgAttrRam ); + ZetMapArea(0x9000, 0x97ff, 0, KyugoFgVideoRam ); + ZetMapArea(0x9000, 0x97ff, 1, KyugoFgVideoRam ); + ZetMapArea(0x9000, 0x97ff, 2, KyugoFgVideoRam ); + ZetMapArea(0x9800, 0x9fff, 1, KyugoSprite2Ram ); + ZetMapArea(0x9800, 0x9fff, 2, KyugoSprite2Ram ); + ZetMapArea(0xa000, 0xa7ff, 0, KyugoSprite1Ram ); + ZetMapArea(0xa000, 0xa7ff, 1, KyugoSprite1Ram ); + ZetMapArea(0xa000, 0xa7ff, 2, KyugoSprite1Ram ); + ZetMapArea(0xf000, 0xf7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, KyugoSharedZ80Ram ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetWriteHandler(KyugoWrite2); + ZetSetInHandler(KyugoPortRead2); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodine") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodinet") || !strcmp(BurnDrvGetTextA(DRV_NAME), "buzzard")) { + ZetMapArea(0x0000, 0x1fff, 0, KyugoZ80Rom2 ); + ZetMapArea(0x0000, 0x1fff, 2, KyugoZ80Rom2 ); + } else { + ZetMapArea(0x0000, 0x7fff, 0, KyugoZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, KyugoZ80Rom2 ); + } + ZetMemEnd(); + ZetClose(); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "airwolf") || !strcmp(BurnDrvGetTextA(DRV_NAME), "airwolfa") || !strcmp(BurnDrvGetTextA(DRV_NAME), "skywolf") || !strcmp(BurnDrvGetTextA(DRV_NAME), "skywolf2")) { + ZetOpen(0); + ZetSetOutHandler(SrdmissnPortWrite1); + ZetMapArea(0xe000, 0xe7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(SrdmissnRead2); + ZetSetInHandler(SrdmissnPortRead2); + ZetSetOutHandler(SrdmissnPortWrite2); + ZetMapArea(0x8000, 0x87ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "flashgal")) { + ZetOpen(0); + ZetSetOutHandler(FlashgalPortWrite1); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(FlashgalRead2); + ZetSetOutHandler(FlashgalPortWrite2); + ZetMapArea(0xa000, 0xa7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xa000, 0xa7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xa000, 0xa7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "flashgala")) { + ZetOpen(0); + ZetSetOutHandler(FlashgalaPortWrite1); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(FlashgalaRead2); + ZetSetInHandler(FlashgalaPortRead2); + ZetSetOutHandler(FlashgalaPortWrite2); + ZetMapArea(0xe000, 0xe7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodine") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gyrodinet") || !strcmp(BurnDrvGetTextA(DRV_NAME), "buzzard")) { + ZetOpen(0); + ZetSetOutHandler(GyrodinePortWrite1); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(GyrodineRead2); + ZetSetOutHandler(GyrodinePortWrite2); + ZetMapArea(0x4000, 0x47ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0x4000, 0x47ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0x4000, 0x47ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "legend")) { + ZetOpen(0); + ZetSetOutHandler(GyrodinePortWrite1); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(LegendRead2); + ZetSetInHandler(SrdmissnPortRead2); + ZetSetOutHandler(SrdmissnPortWrite2); + ZetMapArea(0xc000, 0xc7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xc000, 0xc7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "sonofphx") || !strcmp(BurnDrvGetTextA(DRV_NAME), "repulse") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwar") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwara") || !strcmp(BurnDrvGetTextA(DRV_NAME), "99lstwark")) { + ZetOpen(0); + ZetSetOutHandler(GyrodinePortWrite1); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(FlashgalRead2); + ZetSetOutHandler(FlashgalPortWrite2); + ZetMapArea(0xa000, 0xa7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xa000, 0xa7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xa000, 0xa7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "srdmissn") || !strcmp(BurnDrvGetTextA(DRV_NAME), "fx")) { + ZetOpen(0); + ZetSetOutHandler(SrdmissnPortWrite1); + ZetMapArea(0xe000, 0xe7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(SrdmissnRead2); + ZetSetInHandler(SrdmissnPortRead2); + ZetSetOutHandler(SrdmissnPortWrite2); + ZetMapArea(0x8000, 0x87ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, KyugoSharedZ80Ram ); + ZetMapArea(0x8800, 0x8fff, 0, KyugoZ80Ram2 ); + ZetMapArea(0x8800, 0x8fff, 1, KyugoZ80Ram2 ); + ZetMapArea(0x8800, 0x8fff, 2, KyugoZ80Ram2 ); + ZetClose(); + } + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 18432000 / 12, nBurnSoundRate, &KyugoDip0Read, &KyugoDip1Read, NULL, NULL); + AY8910Init(1, 18432000 / 12, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + // Reset the driver + KyugoDoReset(); + + return 0; +} + +static INT32 Skywolf3Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + KyugoTempRom = (UINT8 *)BurnMalloc(0x18000); + UINT8 *pTemp = (UINT8*)BurnMalloc(0x8000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(pTemp, 0, 1); if (nRet != 0) return 1; + memcpy(KyugoZ80Rom1 + 0x00000, pTemp + 0x04000, 0x4000); + nRet = BurnLoadRom(pTemp, 1, 1); if (nRet != 0) return 1; + memcpy(KyugoZ80Rom1 + 0x04000, pTemp + 0x04000, 0x4000); + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(pTemp, 2, 1); if (nRet != 0) return 1; + memcpy(KyugoZ80Rom2 + 0x00000, pTemp + 0x04000, 0x4000); + nRet = BurnLoadRom(pTemp, 3, 1); if (nRet != 0) return 1; + memcpy(KyugoZ80Rom2 + 0x04000, pTemp + 0x04000, 0x4000); + + // Load and decode the chars + nRet = BurnLoadRom(pTemp, 4, 1); if (nRet != 0) return 1; + memcpy(KyugoTempRom + 0x00000, pTemp + 0x07000, 0x1000); + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, KyugoTempRom, KyugoChars); + + // Load and decode the tiles + memset(KyugoTempRom, 0, 0x18000); + nRet = BurnLoadRom(pTemp, 5, 1); if (nRet != 0) return 1; + memcpy(KyugoTempRom + 0x00000, pTemp + 0x06000, 0x2000); + nRet = BurnLoadRom(pTemp, 6, 1); if (nRet != 0) return 1; + memcpy(KyugoTempRom + 0x02000, pTemp + 0x06000, 0x2000); + nRet = BurnLoadRom(pTemp, 7, 1); if (nRet != 0) return 1; + memcpy(KyugoTempRom + 0x04000, pTemp + 0x06000, 0x2000); + GfxDecode(0x400, 3, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, KyugoTempRom, KyugoTiles); + + // Load and decode the sprites + memset(KyugoTempRom, 0, 0x18000); + nRet = BurnLoadRom(KyugoTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoTempRom + 0x08000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoTempRom + 0x10000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, KyugoTempRom, KyugoSprites); + + // Load the PROMs + nRet = BurnLoadRom(KyugoPromRed, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoPromGreen, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(KyugoPromBlue, 13, 1); if (nRet != 0) return 1; + + BurnFree(KyugoTempRom); + BurnFree(pTemp); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(KyugoRead1); + ZetSetWriteHandler(KyugoWrite1); + ZetMapArea(0x0000, 0x7fff, 0, KyugoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, KyugoZ80Rom1 ); + ZetMapArea(0x8000, 0x87ff, 0, KyugoBgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 1, KyugoBgVideoRam ); + ZetMapArea(0x8000, 0x87ff, 2, KyugoBgVideoRam ); + ZetMapArea(0x8800, 0x8fff, 0, KyugoBgAttrRam ); + ZetMapArea(0x8800, 0x8fff, 1, KyugoBgAttrRam ); + ZetMapArea(0x8800, 0x8fff, 2, KyugoBgAttrRam ); + ZetMapArea(0x9000, 0x97ff, 0, KyugoFgVideoRam ); + ZetMapArea(0x9000, 0x97ff, 1, KyugoFgVideoRam ); + ZetMapArea(0x9000, 0x97ff, 2, KyugoFgVideoRam ); + ZetMapArea(0x9800, 0x9fff, 1, KyugoSprite2Ram ); + ZetMapArea(0x9800, 0x9fff, 2, KyugoSprite2Ram ); + ZetMapArea(0xa000, 0xa7ff, 0, KyugoSprite1Ram ); + ZetMapArea(0xa000, 0xa7ff, 1, KyugoSprite1Ram ); + ZetMapArea(0xa000, 0xa7ff, 2, KyugoSprite1Ram ); + ZetMapArea(0xf000, 0xf7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xf000, 0xf7ff, 2, KyugoSharedZ80Ram ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetWriteHandler(KyugoWrite2); + ZetSetInHandler(KyugoPortRead2); + ZetMapArea(0x0000, 0x7fff, 0, KyugoZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, KyugoZ80Rom2 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(0); + ZetSetOutHandler(SrdmissnPortWrite1); + ZetMapArea(0xe000, 0xe7ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(SrdmissnRead2); + ZetSetInHandler(SrdmissnPortRead2); + ZetSetOutHandler(SrdmissnPortWrite2); + ZetMapArea(0x8000, 0x87ff, 0, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 1, KyugoSharedZ80Ram ); + ZetMapArea(0x8000, 0x87ff, 2, KyugoSharedZ80Ram ); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 18432000 / 12, nBurnSoundRate, &KyugoDip0Read, &KyugoDip1Read, NULL, NULL); + AY8910Init(1, 18432000 / 12, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + // Reset the driver + KyugoDoReset(); + + return 0; +} + +static INT32 KyugoExit() +{ + ZetExit(); + + for (INT32 i = 0; i < 2; i++) { + AY8910Exit(i); + } + + GenericTilesExit(); + + KyugoIRQEnable = 0; + KyugoSubCPUEnable = 0; + KyugoFgColour = 0; + KyugoBgPaletteBank = 0; + KyugoBgScrollXHi = 0; + KyugoBgScrollXLo = 0; + KyugoBgScrollY = 0; + KyugoFlipScreen = 0; + + KyugoNumZ80Rom1 = 0; + KyugoNumZ80Rom2 = 0; + KyugoNumSpriteRom = 0; + KyugoSizeZ80Rom1 = 0; + KyugoSizeZ80Rom2 = 0; + KyugoSizeSpriteRom = 0; + + BurnFree(Mem); + + return 0; +} + +static void KyugoCalcPalette() +{ + INT32 i; + + for (i = 0; i < 256; i++) { + INT32 bit0, bit1, bit2, bit3, r, g, b; + + bit0 = (KyugoPromRed[i] >> 0) & 0x01; + bit1 = (KyugoPromRed[i] >> 1) & 0x01; + bit2 = (KyugoPromRed[i] >> 2) & 0x01; + bit3 = (KyugoPromRed[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (KyugoPromGreen[i] >> 0) & 0x01; + bit1 = (KyugoPromGreen[i] >> 1) & 0x01; + bit2 = (KyugoPromGreen[i] >> 2) & 0x01; + bit3 = (KyugoPromGreen[i] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (KyugoPromBlue[i] >> 0) & 0x01; + bit1 = (KyugoPromBlue[i] >> 1) & 0x01; + bit2 = (KyugoPromBlue[i] >> 2) & 0x01; + bit3 = (KyugoPromBlue[i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + KyugoPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void KyugoRenderBgLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex = 0, xScroll, Flip, xFlip, yFlip; + + xScroll = KyugoBgScrollXLo + (KyugoBgScrollXHi * 256); + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = KyugoBgVideoRam[TileIndex]; + Attr = KyugoBgAttrRam[TileIndex]; + Code = Code | ((Attr & 0x03) << 8); + Code &= 0x3ff; + Colour = (Attr >> 4) | (KyugoBgPaletteBank << 4); + Flip = (Attr & 0x0c) >> 2; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (KyugoFlipScreen) { + xFlip = !xFlip; + yFlip = !yFlip; + y = 248 - y; + x = 504 - x; + x -= xScroll; + y += KyugoBgScrollY; + } else { + x -= xScroll; + y -= KyugoBgScrollY; + } + + if (x < -8) x += 512; + if (y < -8) y += 256; + if (y > 264) y -= 256; + + x -= 32; + y -= 16; + + if (x > 8 && x < 280 && y > 8 && y < 216) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } else { + Render8x8Tile_FlipX(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } else { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } else { + Render8x8Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 0, KyugoTiles); + } + } + } + + TileIndex++; + } + } +} + +static void KyugoRenderSpriteLayer() +{ + UINT8 *SpriteRam_Area1 = &KyugoSprite1Ram[0x28]; + UINT8 *SpriteRam_Area2 = &KyugoSprite2Ram[0x28]; + UINT8 *SpriteRam_Area3 = &KyugoFgVideoRam[0x28]; + + INT32 i; + + for (i = 0; i < 24; i++) { + INT32 Offset, y, sy, sx, Colour; + + Offset = 2 * (i % 12) + 64 * (i / 12); + + sx = SpriteRam_Area3[Offset + 1] + 256 * (SpriteRam_Area2[Offset + 1] & 1); + if (sx > 320) sx -= 512; + sy = 255 - SpriteRam_Area1[Offset] + 2; + if (sy > 0xf0) sy -= 256; + if (KyugoFlipScreen) sy = 240 - sy; + sy -= 16; + + Colour = SpriteRam_Area1[Offset + 1] & 0x1f; + + for (y = 0; y < 16; y++) { + INT32 Code, Attr, FlipX, FlipY, yPos; + + Code = SpriteRam_Area3[Offset + 128 * y]; + Attr = SpriteRam_Area2[Offset + 128 * y]; + Code = Code | ((Attr & 0x01) << 9) | ((Attr & 0x02) << 7); + Code &= 0x3ff; + + FlipX = Attr & 0x08; + FlipY = Attr & 0x04; + + yPos = sy + 16 * y; + + if (KyugoFlipScreen) { + FlipX = !FlipX; + FlipY = !FlipY; + yPos = sy - 16 * y; + } + + if (sx > 16 && sx < 272 && yPos > 16 && yPos < 208) { + if (FlipX) { + if (FlipY) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } + } else { + if (FlipY) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } + } + } else { + if (FlipX) { + if (FlipY) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } + } else { + if (FlipY) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, yPos, Colour, 3, 0, 0, KyugoSprites); + } + } + } + } + } +} + +static void KyugoRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, FlipX = 0, FlipY = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = KyugoFgVideoRam[TileIndex]; + Colour = 2 * KyugoPromCharLookup[Code >> 3] + KyugoFgColour; + Code &= 0xff; + + x = 8 * mx; + y = 8 * my; + + if (KyugoFlipScreen) { + FlipX = 1; + FlipY = 1; + y = 248 - y; + x = 280 - x; + } + + y -= 16; + + if (x > 0 && x < 280 && y > 0 && y < 216) { + if (FlipX) { + if (FlipY) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } + } else { + if (FlipY) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } + } + } else { + if (FlipX) { + if (FlipY) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } + } else { + if (FlipY) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, KyugoChars); + } + } + } + + TileIndex++; + } + } +} + +static void KyugoDraw() +{ + BurnTransferClear(); + KyugoCalcPalette(); + KyugoRenderBgLayer(); + KyugoRenderSpriteLayer(); + KyugoRenderCharLayer(); + BurnTransferCopy(KyugoPalette); +} + +static INT32 KyugoFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (KyugoReset) KyugoDoReset(); + + KyugoMakeInputs(); + + nCyclesTotal[0] = (18432000 / 6) / 60; + nCyclesTotal[1] = (18432000 / 6) / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 9 && KyugoIRQEnable) ZetNmi(); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + if (KyugoSubCPUEnable) { + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 2 || i == 4 || i == 6 || i == 8) ZetRaiseIrq(0); + ZetClose(); + } + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) KyugoDraw(); + + return 0; +} + +static INT32 KyugoScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029674; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + AY8910Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(KyugoDip); + SCAN_VAR(KyugoInput); + SCAN_VAR(KyugoIRQEnable); + SCAN_VAR(KyugoSubCPUEnable); + SCAN_VAR(KyugoFgColour); + SCAN_VAR(KyugoBgPaletteBank); + SCAN_VAR(KyugoBgScrollXHi); + SCAN_VAR(KyugoBgScrollXLo); + SCAN_VAR(KyugoBgScrollY); + SCAN_VAR(KyugoFlipScreen); + } + + + return 0; +} + +struct BurnDriver BurnDrvAirwolf = { + "airwolf", NULL, NULL, NULL, "1987", + "Airwolf\0", NULL, "Kyugo", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, AirwolfRomInfo, AirwolfRomName, NULL, NULL, KyugoInputInfo, AirwolfDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAirwolfa = { + "airwolfa", "airwolf", NULL, NULL, "1987", + "Airwolf (US)\0", NULL, "Kyugo (UA Theatre license)", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, AirwolfaRomInfo, AirwolfaRomName, NULL, NULL, KyugoInputInfo, AirwolfDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSkywolf = { + "skywolf", "airwolf", NULL, NULL, "1987", + "Sky Wolf (set 1)\0", NULL, "bootleg", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, SkywolfRomInfo, SkywolfRomName, NULL, NULL, KyugoInputInfo, SkywolfDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSkywolf2 = { + "skywolf2", "airwolf", NULL, NULL, "1987", + "Sky Wolf (set 2)\0", NULL, "bootleg", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, Skywolf2RomInfo, Skywolf2RomName, NULL, NULL, KyugoInputInfo, AirwolfDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSkywolf3 = { + "skywolf3", "airwolf", NULL, NULL, "1987", + "Sky Wolf (set 3)\0", NULL, "bootleg", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, Skywolf3RomInfo, Skywolf3RomName, NULL, NULL, KyugoInputInfo, AirwolfDIPInfo, + Skywolf3Init, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlashgal = { + "flashgal", NULL, NULL, NULL, "1985", + "Flashgal (set 1)\0", NULL, "Sega", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, FlashgalRomInfo, FlashgalRomName, NULL, NULL, KyugoInputInfo, FlashgalDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlashgala = { + "flashgala", "flashgal", NULL, NULL, "1985", + "Flashgal (set 2)\0", NULL, "Sega", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, FlashgalaRomInfo, FlashgalaRomName, NULL, NULL, KyugoInputInfo, FlashgalDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGyrodine = { + "gyrodine", NULL, NULL, NULL, "1984", + "Gyrodine\0", NULL, "Crux", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GyrodineRomInfo, GyrodineRomName, NULL, NULL, KyugoInputInfo, GyrodineDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvGyrodinet = { + "gyrodinet", "gyrodine", NULL, NULL, "1984", + "Gyrodine (Taito Corporation license)\0", NULL, "Crux (Taito Corporation license)", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, GyrodinetRomInfo, GyrodinetRomName, NULL, NULL, KyugoInputInfo, GyrodineDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvBuzzard = { + "buzzard", "gyrodine", NULL, NULL, "1984", + "Buzzard\0", NULL, "Crux", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, BuzzardRomInfo, BuzzardRomName, NULL, NULL, KyugoInputInfo, GyrodineDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvLegend = { + "legend", NULL, NULL, NULL, "1986", + "Legend\0", NULL, "Sega / Coreland", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, LegendRomInfo, LegendRomName, NULL, NULL, KyugoInputInfo, LegendDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSonofphx = { + "sonofphx", "repulse", NULL, NULL, "1985", + "Son of Phoenix\0", NULL, "Associated Overseas MFR, Inc", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, SonofphxRomInfo, SonofphxRomName, NULL, NULL, KyugoInputInfo, SonofphxDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvRepulse = { + "repulse", NULL, NULL, NULL, "1985", + "Repulse\0", NULL, "Sega", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, RepulseRomInfo, RepulseRomName, NULL, NULL, KyugoInputInfo, SonofphxDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrv99lstwar = { + "99lstwar", "repulse", NULL, NULL, "1985", + "'99: The Last War\0", NULL, "Proma", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, Lstwar99RomInfo, Lstwar99RomName, NULL, NULL, KyugoInputInfo, SonofphxDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrv99lstwara = { + "99lstwara", "repulse", NULL, NULL, "1985", + "'99: The Last War (alternate)\0", NULL, "Proma", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, Lstwra99RomInfo, Lstwra99RomName, NULL, NULL, KyugoInputInfo, SonofphxDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrv99lstwark = { + "99lstwark", "repulse", NULL, NULL, "1985", + "'99: The Last War (Kyugo)\0", NULL, "Kyugo", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, Lstwrk99RomInfo, Lstwrk99RomName, NULL, NULL, KyugoInputInfo, SonofphxDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvSrdmissn = { + "srdmissn", NULL, NULL, NULL, "1986", + "S.R.D. Mission\0", NULL, "Taito Corporation", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, SrdmissnRomInfo, SrdmissnRomName, NULL, NULL, KyugoInputInfo, SrdmissnDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; + +struct BurnDriver BurnDrvFx = { + "fx", "srdmissn", NULL, NULL, "1986", + "F-X\0", NULL, "bootleg", "Kyugo", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, FxRomInfo, FxRomName, NULL, NULL, KyugoInputInfo, SrdmissnDIPInfo, + KyugoInit, KyugoExit, KyugoFrame, NULL, KyugoScan, + NULL, 0x100, 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_ladybug.cpp b/src/burn/drivers/misc_pre90s/d_ladybug.cpp new file mode 100644 index 00000000..fa72b70f --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_ladybug.cpp @@ -0,0 +1,1528 @@ +// FB Alpha Lady Bug driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "sn76496.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80Ops0; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvColRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvGridRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *flipscreen; +static UINT8 *soundlatch; +static UINT8 *gridcolor; +static UINT8 *enablestars; +static UINT8 *starspeed; + +static INT32 stars_offset; +static INT32 stars_state; +static INT32 vblank; +static INT32 ladybug = 0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[4]; +static UINT8 DrvReset; + +static struct BurnInputInfo LadybugInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy4 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy3 + 0, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy4 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 7, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ladybug) + +static struct BurnInputInfo SraiderInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Sraider) + +static struct BurnDIPInfo LadybugDIPList[]= +{ + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x03, "Easy" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "High Score Names" }, + {0x12, 0x01, 0x04, 0x00, "3 Letters" }, + {0x12, 0x01, 0x04, 0x04, "10 Letters" }, + + {0 , 0xfe, 0 , 2, "Rack Test (Cheat)" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x20, 0x00, "Upright" }, + {0x12, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x40, 0x40, "No" }, + {0x12, 0x01, 0x40, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x80, 0x80, "3" }, + {0x12, 0x01, 0x80, 0x00, "5" }, + + {0 , 0xfe, 0 , 10, "Coin B" }, + {0x13, 0x01, 0x0f, 0x06, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 10, "Coin A" }, + {0x13, 0x01, 0xf0, 0x60, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, +}; + +STDDIPINFO(Ladybug) + +static struct BurnDIPInfo SnapjackDIPList[]= +{ + {0x12, 0xff, 0xff, 0xf7, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x03, "Easy" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "High Score Names" }, + {0x12, 0x01, 0x04, 0x00, "3 Letters" }, + {0x12, 0x01, 0x04, 0x04, "10 Letters" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x08, 0x00, "Upright" }, + {0x12, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + + {0 , 0xfe, 0 , 11, "Coin B" }, + {0x13, 0x01, 0x0f, 0x05, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x13, 0x01, 0xf0, 0x50, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, +}; + +STDDIPINFO(Snapjack) + +static struct BurnDIPInfo CavengerDIPList[]= +{ + {0x12, 0xff, 0xff, 0xc7, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x03, "Easy" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "High Score Names" }, + {0x12, 0x01, 0x04, 0x00, "3 Letters" }, + {0x12, 0x01, 0x04, 0x04, "10 Letters" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x08, 0x00, "Upright" }, + {0x12, 0x01, 0x08, 0x08, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Initial High Score" }, + {0x12, 0x01, 0x30, 0x00, "0" }, + {0x12, 0x01, 0x30, 0x30, "5000" }, + {0x12, 0x01, 0x30, 0x20, "8000" }, + {0x12, 0x01, 0x30, 0x10, "10000" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, + {0x12, 0x01, 0xc0, 0x40, "5" }, + + {0 , 0xfe, 0 , 10, "Coin B" }, + {0x13, 0x01, 0x0f, 0x06, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 10, "Coin A" }, + {0x13, 0x01, 0xf0, 0x60, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, +}; + +STDDIPINFO(Cavenger) + +static struct BurnDIPInfo DorodonDIPList[]= +{ + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x03, 0x03, "Easy" }, + {0x12, 0x01, 0x03, 0x02, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x04, 0x04, "20000" }, + {0x12, 0x01, 0x04, 0x00, "30000" }, + + {0 , 0xfe, 0 , 2, "Rack Test (Cheat)" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x20, 0x00, "Upright" }, + {0x12, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x12, 0x01, 0x40, 0x40, "No" }, + {0x12, 0x01, 0x40, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x80, 0x80, "3" }, + {0x12, 0x01, 0x80, 0x00, "5" }, + + {0 , 0xfe, 0 , 10, "Coin B" }, + {0x13, 0x01, 0x0f, 0x06, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "3 Coins 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 10, "Coin A" }, + {0x13, 0x01, 0xf0, 0x60, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "3 Coins 2 Credits" }, + {0x13, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, +}; + +STDDIPINFO(Dorodon) + +static struct BurnDIPInfo SraiderDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xdf, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x0f, 0x01, 0x03, 0x03, "Easy" }, + {0x0f, 0x01, 0x03, 0x02, "Medium" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "High Score Names" }, + {0x0f, 0x01, 0x04, 0x00, "3 Letters" }, + {0x0f, 0x01, 0x04, 0x04, "10 Letters" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x0f, 0x01, 0x08, 0x08, "No" }, + {0x0f, 0x01, 0x08, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0f, 0x01, 0x20, 0x00, "Upright" }, + {0x0f, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0f, 0x01, 0xc0, 0x00, "2" }, + {0x0f, 0x01, 0xc0, 0xc0, "3" }, + {0x0f, 0x01, 0xc0, 0x80, "4" }, + {0x0f, 0x01, 0xc0, 0x40, "5" }, + + {0 , 0xfe, 0 , 11, "Coin A" }, + {0x10, 0x01, 0x0f, 0x06, "4 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0a, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x07, "3 Coins 2 Credits" }, + {0x10, 0x01, 0x0f, 0x09, "2 Coins 2 Credits" }, + {0x10, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x10, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x10, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x10, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x10, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 11, "Coin B" }, + {0x10, 0x01, 0xf0, 0x60, "4 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0xa0, "2 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x70, "3 Coins 2 Credits" }, + {0x10, 0x01, 0xf0, 0x90, "2 Coins 2 Credits" }, + {0x10, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0x00, "Free Play" }, +}; + +STDDIPINFO(Sraider) + +void __fastcall ladybug_write(UINT16 address, UINT8 data) +{ + switch (address & 0xf000) + { + case 0xa000: + *flipscreen = data & 1; + return; + + case 0xb000: + SN76496Write(0, data); + return; + + case 0xc000: + SN76496Write(1, data); + return; + } +} + +UINT8 __fastcall ladybug_read(UINT16 address) +{ + switch (address) + { + case 0x8005: + return 0x3e; + + case 0x9000: + return DrvInputs[0]; + + case 0x9001: { + if (ladybug) { + if (DrvDips[0] & 0x20) { + return DrvInputs[1] ^ vblank; + } else { + return (DrvInputs[0] & 0x7f) ^ vblank; + } + } + + return DrvInputs[1] ^ vblank; + } + + case 0x9002: + return DrvDips[0]; + + case 0x9003: + return DrvDips[1]; + + case 0xe000: + return DrvInputs[2]; + } + + return 0; +} + +void __fastcall sraider_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8006: + soundlatch[0] = data; + return; + + case 0x8007: + soundlatch[1] = data; + return; + } +} + +void __fastcall sraider_sub_write(UINT16 address, UINT8 data) +{ + if (address == 0xe800) { + *flipscreen = data & 0x80; + *gridcolor = data & 0x70; + *enablestars = data & 0x08; + *starspeed =(data & 0x07) - 1; + } +} + +UINT8 __fastcall sraider_sub_read(UINT16 address) +{ + switch (address) + { + case 0x8000: + return soundlatch[0]; + + case 0xa000: + return soundlatch[1]; + } + + return 0; +} + +void __fastcall sraider_sub_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + SN76496Write(0, data); + return; + + case 0x08: + SN76496Write(1, data); + return; + + case 0x10: + SN76496Write(2, data); + return; + + case 0x18: + SN76496Write(3, data); + return; + + case 0x20: + SN76496Write(4, data); + return; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + stars_offset = 0; + stars_state = 0; + vblank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; + DrvZ80Ops0 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x008000; + DrvGfxROM1 = Next; Next += 0x008000; + DrvGfxROM2 = Next; Next += 0x008000; + DrvGfxROM3 = Next; Next += 0x008000; + + DrvColPROM = Next; Next += 0x000040; + + Palette = (UINT32*)Next; Next += 0x0082 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0082 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x001000; + DrvZ80RAM1 = Next; Next += 0x000400; + + DrvColRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000400; + DrvGridRAM = Next; Next += 0x000100; + + flipscreen = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000002; + gridcolor = Next; Next += 0x000001; + enablestars = Next; Next += 0x000001; + starspeed = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[2] = { 0x0000, 0x8000 }; + INT32 Plane1[2] = { 0x0001, 0x0000 }; + INT32 XOffs0[8] = { 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000 }; + INT32 YOffs0[8] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038 }; + INT32 XOffs1[16] = { 0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e, + 0x080, 0x082, 0x084, 0x086, 0x088, 0x08a, 0x08c, 0x08e }; + INT32 YOffs1[16] = { 0x170, 0x160, 0x150, 0x140, 0x130, 0x120, 0x110, 0x100, + 0x070, 0x060, 0x050, 0x040, 0x030, 0x020, 0x010, 0x000 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x2000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x2000); + + GfxDecode(0x200, 2, 8, 8, Plane0, XOffs0, YOffs0 + 0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x2000); + + GfxDecode(0x080, 2, 16, 16, Plane1, XOffs1, YOffs1 + 0, 0x200, tmp, DrvGfxROM1); + GfxDecode(0x200, 2, 8, 8, Plane1, XOffs1, YOffs1 + 8, 0x080, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x1000); + + GfxDecode(0x200, 1, 8, 8, Plane0, XOffs0, YOffs0 + 0, 0x040, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static void DrvPaletteInit(INT32 sh0, INT32 sh1, INT32 sh2, INT32 sh3, INT32 sh4, INT32 sh5) +{ + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0 = (~DrvColPROM[i] >> sh0) & 0x01; + INT32 bit1 = (~DrvColPROM[i] >> sh1) & 0x01; + INT32 r = bit0 * 82 + bit1 * 173; + + bit0 = (~DrvColPROM[i] >> sh2) & 0x01; + bit1 = (~DrvColPROM[i] >> sh3) & 0x01; + INT32 g = bit0 * 82 + bit1 * 173; + + bit0 = (~DrvColPROM[i] >> sh4) & 0x01; + bit1 = (~DrvColPROM[i] >> sh5) & 0x01; + INT32 b = bit0 * 82 + bit1 * 173; + + DrvPalette[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 0x20; i++) + { + Palette[i + 0x00] = DrvPalette[((i << 3) & 0x18) | ((i >> 2) & 0x07)]; + Palette[i + 0x20] = DrvPalette[BITSWAP08(DrvColPROM[i + 0x20] & 0x0f, 7,6,5,4,0,1,2,3)]; + Palette[i + 0x40] = DrvPalette[BITSWAP08(DrvColPROM[i + 0x20] >> 4, 7,6,5,4,0,1,2,3)]; + } + + DrvRecalc = 1; +} + +static void SraiderPaletteInit() +{ + DrvPaletteInit(3, 0, 5, 4, 7, 6); + + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0 = (i >> 3) & 0x01; + INT32 bit1 = (i >> 4) & 0x01; + INT32 b = 0x47 * bit0 + 0x97 * bit1; + + bit0 = (i >> 1) & 0x01; + bit1 = (i >> 2) & 0x01; + INT32 g = 0x47 * bit0 + 0x97 * bit1; + + bit0 = (i >> 0) & 0x01; + INT32 r = 0x47 * bit0; + + Palette[i + 0x60] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DorodonDecode() +{ + UINT8 *tmp = DrvZ80RAM0; + + if (BurnLoadRom(tmp + 0x000, 7, 1)) return 1; + if (BurnLoadRom(tmp + 0x100, 8, 1)) return 1; + for (INT32 i = 0; i < 0x100; i++) { + tmp[i] = (tmp[i] << 4) | tmp[i + 0x100]; + } + + for (INT32 i = 0; i < 0x10000; i++) { + DrvZ80Ops0[i] = tmp[DrvZ80ROM0[i]]; + } + + return 0; +} + +static INT32 DrvInit(INT32 game_select) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + switch (game_select) + { + case 0: // ladybug, snapjack + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x01000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x03000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x05000, 5, 1)) return 1; + memcpy (DrvZ80Ops0, DrvZ80ROM0, 0x10000); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x01000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x01000, 9, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00020, 11, 1)) return 1; + + ladybug = 1; + } + break; + + case 1: // cavenger + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x01000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x03000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x05000, 5, 1)) return 1; + memcpy (DrvZ80Ops0, DrvZ80ROM0, 0x10000); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x01000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00020, 10, 1)) return 1; + } + break; + + case 2: // dorodon + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x01000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x01000, 6, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00020, 10, 1)) return 1; + + DorodonDecode(); + } + break; + } + + DrvPaletteInit(0, 5, 2, 6, 4, 7); + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80Ops0, DrvZ80ROM0); + ZetMapArea(0x6000, 0x6fff, 0, DrvZ80RAM0); + ZetMapArea(0x6000, 0x6fff, 1, DrvZ80RAM0); + ZetMapArea(0x6000, 0x6fff, 2, DrvZ80RAM0); + ZetMapArea(0x7000, 0x73ff, 0, DrvSprRAM); + ZetMapArea(0x7000, 0x73ff, 1, DrvSprRAM); + ZetMapArea(0x7000, 0x73ff, 2, DrvSprRAM); + ZetMapArea(0xd000, 0xd3ff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xd3ff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xd3ff, 2, DrvVidRAM); + ZetMapArea(0xd400, 0xd7ff, 0, DrvColRAM); + ZetMapArea(0xd400, 0xd7ff, 1, DrvColRAM); + ZetMapArea(0xd400, 0xd7ff, 2, DrvColRAM); + ZetSetWriteHandler(ladybug_write); + ZetSetReadHandler(ladybug_read); + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 4000000, 0); + SN76489Init(1, 4000000, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 SraiderInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x02000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x04000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x01000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x01000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 10, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 11, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00020, 12, 1)) return 1; + + SraiderPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM0); + ZetMapArea(0x6000, 0x6fff, 0, DrvZ80RAM0); + ZetMapArea(0x6000, 0x6fff, 1, DrvZ80RAM0); + ZetMapArea(0x6000, 0x6fff, 2, DrvZ80RAM0); + ZetMapArea(0x7000, 0x73ff, 0, DrvSprRAM); + ZetMapArea(0x7000, 0x73ff, 1, DrvSprRAM); + ZetMapArea(0x7000, 0x73ff, 2, DrvSprRAM); + ZetMapArea(0xd000, 0xd3ff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xd3ff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xd3ff, 2, DrvVidRAM); + ZetMapArea(0xd400, 0xd7ff, 0, DrvColRAM); + ZetMapArea(0xd400, 0xd7ff, 1, DrvColRAM); + ZetMapArea(0xd400, 0xd7ff, 2, DrvColRAM); + ZetSetWriteHandler(sraider_main_write); + ZetSetReadHandler(ladybug_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM1); + ZetMapArea(0x6000, 0x63ff, 0, DrvZ80RAM1); + ZetMapArea(0x6000, 0x63ff, 1, DrvZ80RAM1); + ZetMapArea(0x6000, 0x63ff, 2, DrvZ80RAM1); + ZetMapArea(0xe000, 0xe0ff, 0, DrvGridRAM); + ZetMapArea(0xe000, 0xe0ff, 1, DrvGridRAM); + ZetMapArea(0xe000, 0xe0ff, 2, DrvGridRAM); + ZetSetWriteHandler(sraider_sub_write); + ZetSetReadHandler(sraider_sub_read); + ZetSetOutHandler(sraider_sub_out); + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 4000000, 0); + SN76489Init(1, 4000000, 1); + SN76489Init(2, 4000000, 1); + SN76489Init(3, 4000000, 1); + SN76489Init(4, 4000000, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + SN76496Exit(); + + BurnFree (AllMem); + + ladybug = 0; + + return 0; +} + +static void draw_layer() +{ + for (INT32 offs = 4 * 32; offs < 32 * 28; offs++) { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5); + + sx -= DrvVidRAM[((sy & 3) << 5) | (sy >> 2)] + 8; + if (sx < -7) sx += 256; + + INT32 code = DrvVidRAM[offs] | ((DrvColRAM[offs] & 0x08) << 5); + INT32 color = DrvColRAM[offs] & 0x07; + + if (*flipscreen) { + sx = 240 - sx; + sy = 196 - sy; + + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, (sy * 8) - 32, color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, (sy * 8) - 32, color, 2, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_grid() +{ + for (INT32 offs = 4 * 32; offs < 32 * 28; offs++) + { + INT32 sx = ((offs & 0x1f) << 3) - 8; + INT32 sy = ((offs >> 5) << 3) - 32; + + if (*flipscreen) { + sx = 240 - sx; + sy = 196 - sy; + + if (offs & 0x200) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, (offs & 0x1ff) ^ 0x1e0, sx, sy, 0, 1, 0, 0x80, DrvGfxROM3); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, offs, sx, sy, 0, 1, 0, 0x80, DrvGfxROM3); + } + } else { + if (offs & 0x200) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, (offs & 0x1ff) ^ 0x1e0, sx, sy, 0, 1, 0, 0x80, DrvGfxROM3); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, offs, sx, sy, 0, 1, 0, 0x80, DrvGfxROM3); + } + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x400 - 2*0x40;offs >= 2*0x40;offs -= 0x40) + { + INT32 i = 0; + + while (i < 0x40 && DrvSprRAM[offs + i + 0] != 0) + i += 4; + + while (i > 0) + { + i -= 4; + + if (DrvSprRAM[offs + i + 0] & 0x80) + { + INT32 size = (DrvSprRAM[offs + i + 0] >> 6) & 0x01; + INT32 code = (DrvSprRAM[offs + i + 1] >> 2) + ((DrvSprRAM[offs + i + 2] & 0x10) << (4 >> size)); + INT32 color = (DrvSprRAM[offs + i + 2] & 0x0f) + 8; + INT32 flipx = DrvSprRAM[offs + i + 0] & 0x20; + INT32 flipy = DrvSprRAM[offs + i + 0] & 0x10; + INT32 sx = DrvSprRAM[offs + i + 3] - 8; + INT32 sy = (DrvSprRAM[offs + i + 0] & 0x0f) + offs / 4 - 32; + + if (size) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy - 8, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy - 8, color, 2, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy - 8, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy - 8, color, 2, 0, 0, DrvGfxROM1); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } + } + } + } + } +} + +static void redclash_update_stars() +{ + static INT32 count = 0; + + if (*enablestars == 0) + return; + + count = (count + 1) & 1; + + if (count == 0) + { + stars_offset += ((*starspeed << 1) - 0x09); + stars_offset &= 0xffff; + stars_state = 0; + } + else + { + stars_state = 0x1fc71; + } +} + +static void redclash_draw_stars(INT32 palette_offset, INT32 sraider, INT32 firstx, INT32 lastx) +{ + UINT8 tempbit, feedback, star_color, hcond,vcond; + + if (*enablestars == 0) + return; + + UINT32 state = stars_state; + + for (INT32 i = 0; i < 256 * 256; i++) + { + INT32 xloc = (stars_offset + i) & 0xff; + INT32 yloc = ((stars_offset + i) >> 8) & 0xff; + + xloc -= 8; + yloc -= 32; + + if ((state & 0x10000) == 0) + tempbit = 1; + else + tempbit = 0; + + if ((state & 0x00020) != 0) + feedback = tempbit ^ 1; + else + feedback = tempbit ^ 0; + + hcond = ((xloc + 8) & 0x10) >> 4; + + if (sraider) + vcond = 1; + else + vcond = yloc & 0x01; + + if (xloc >= 0 && xloc < nScreenWidth && + yloc >= 0 && yloc < nScreenHeight) + { + if ((hcond ^ vcond) == 0) + { + if (((state & 0x000ff) == 0x000ff) && (feedback == 0)) + { + if ((xloc >= firstx) && (xloc <= lastx)) + { + star_color = (state >> 9) & 0x1f; + pTransDraw[(yloc * nScreenWidth) + xloc] = palette_offset + star_color; + } + } + } + } + + state = ((state << 1) & 0x1fffe) | feedback; + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x60; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, d >> 8, d, 0); + } + DrvRecalc = 0; + } + + BurnTransferClear(); + + draw_layer(); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 SraiderDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x80; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, d >> 8, d, 0); + } + DrvRecalc = 0; + } + + DrvPalette[0x81] = BurnHighCol((*gridcolor & 0x40) ? 0xff : 0, (*gridcolor & 0x20) ? 0xff : 0, (*gridcolor & 0x10) ? 0xff : 0, 0); + + BurnTransferClear(); + + if (*flipscreen) { + redclash_draw_stars(0x60, 1, 0x27, 0xff); + } else { + redclash_draw_stars(0x60, 1, 0x00, 0xd8); + } + redclash_update_stars(); + + draw_grid(); + + draw_layer(); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 coin = 0; + + { + INT32 previous = DrvInputs[3] ^ 0xff; + + memset (DrvInputs, 0xff, 4); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy4[i] & 1) << i; + } + if ((previous & 1) != (~DrvInputs[3] & 1)) coin |= 1; + if ((previous & 2) != (~DrvInputs[3] & 2)) coin |= 2; + DrvInputs[1] &= 0x7f; + } + + ZetOpen(0); + if (coin & 1) Z80SetIrqLine(0x20, DrvJoy4[0] ? Z80_ASSERT_LINE : Z80_CLEAR_LINE); + if (coin & 2) Z80SetIrqLine(0x00, DrvJoy4[1] ? Z80_ASSERT_LINE : Z80_CLEAR_LINE); + + vblank = 0xc0; + + for (INT32 i = 0; i < 32; i++) { + if (i == 5) vblank = 0; + if (i == 31) vblank = 0xc0; + + INT32 nSegment = (4000000 / 60) / 32; + + ZetRun(nSegment); + } + + ZetClose(); + + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 SraiderFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 100; + INT32 nTotalCycles[2] = { 4000000 / 60, 4000000 / 60 }; + + for (INT32 i = 0; i < nInterleave; i++) { + ZetOpen(0); + ZetRun(nTotalCycles[0] / nInterleave); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + ZetOpen(1); + ZetRun(nTotalCycles[1] / nInterleave); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + } + + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + SN76496Update(2, pBurnSoundOut, nBurnSoundLen); + SN76496Update(3, pBurnSoundOut, nBurnSoundLen); + SN76496Update(4, pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) { + SraiderDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029706; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + SN76496Scan(nAction, pnMin); + + SCAN_VAR(stars_offset); + SCAN_VAR(stars_state); + } + + return 0; +} + + +// Lady Bug + +static struct BurnRomInfo ladybugRomDesc[] = { + { "l1.c4", 0x1000, 0xd09e0adb, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "l2.d4", 0x1000, 0x88bc4a0a, 1 | BRF_PRG | BRF_ESS }, // 1 + { "l3.e4", 0x1000, 0x53e9efce, 1 | BRF_PRG | BRF_ESS }, // 2 + { "l4.h4", 0x1000, 0xffc424d7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "l5.j4", 0x1000, 0xad6af809, 1 | BRF_PRG | BRF_ESS }, // 4 + { "l6.k4", 0x1000, 0xcf1acca4, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "l9.f7", 0x1000, 0x77b1da1e, 2 | BRF_GRA }, // 6 Characters + { "l0.h7", 0x1000, 0xaa82e00b, 2 | BRF_GRA }, // 7 + + { "l8.l7", 0x1000, 0x8b99910b, 3 | BRF_GRA }, // 8 Sprites + { "l7.m7", 0x1000, 0x86a5b448, 3 | BRF_GRA }, // 9 + + { "10-2.k1", 0x0020, 0xdf091e52, 4 | BRF_GRA }, // 10 Color PROMs + { "10-1.f4", 0x0020, 0x40640d8f, 4 | BRF_GRA }, // 11 + { "10-3.c4", 0x0020, 0x27fa3a50, 4 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(ladybug) +STD_ROM_FN(ladybug) + +static INT32 LadybugInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvLadybug = { + "ladybug", NULL, NULL, NULL, "1981", + "Lady Bug\0", NULL, "Universal", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, ladybugRomInfo, ladybugRomName, NULL, NULL, LadybugInputInfo, LadybugDIPInfo, + LadybugInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 196, 240, 3, 4 +}; + + +// Lady Bug (bootleg set 1) + +static struct BurnRomInfo ladybugbRomDesc[] = { + { "lb1a.cpu", 0x1000, 0xec135e54, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "lb2a.cpu", 0x1000, 0x3049c5c6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lb3a.cpu", 0x1000, 0xb0fef837, 1 | BRF_PRG | BRF_ESS }, // 2 + { "l4.h4", 0x1000, 0xffc424d7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "l5.j4", 0x1000, 0xad6af809, 1 | BRF_PRG | BRF_ESS }, // 4 + { "lb6a.cpu", 0x1000, 0x88c8002a, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "l9.f7", 0x1000, 0x77b1da1e, 2 | BRF_GRA }, // 6 Characters + { "l0.h7", 0x1000, 0xaa82e00b, 2 | BRF_GRA }, // 7 + + { "l8.l7", 0x1000, 0x8b99910b, 3 | BRF_GRA }, // 8 Sprites + { "l7.m7", 0x1000, 0x86a5b448, 3 | BRF_GRA }, // 9 + + { "10-2.k1", 0x0020, 0xdf091e52, 4 | BRF_GRA }, // 10 Color PROMs + { "10-1.f4", 0x0020, 0x40640d8f, 4 | BRF_GRA }, // 11 + { "10-3.c4", 0x0020, 0x27fa3a50, 4 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(ladybugb) +STD_ROM_FN(ladybugb) + +struct BurnDriver BurnDrvLadybugb = { + "ladybugb", "ladybug", NULL, NULL, "1981", + "Lady Bug (bootleg set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, ladybugbRomInfo, ladybugbRomName, NULL, NULL, LadybugInputInfo, LadybugDIPInfo, + LadybugInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 196, 240, 3, 4 +}; + + +// Lady Bug (bootleg set 2) + +static struct BurnRomInfo ladybgb2RomDesc[] = { + { "lb1b.cpu", 0x1000, 0x35d61e65, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "lb2b.cpu", 0x1000, 0xa13e0fe4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "lb3b.cpu", 0x1000, 0xee8ac716, 1 | BRF_PRG | BRF_ESS }, // 2 + { "l4.h4", 0x1000, 0xffc424d7, 1 | BRF_PRG | BRF_ESS }, // 3 + { "l5.j4", 0x1000, 0xad6af809, 1 | BRF_PRG | BRF_ESS }, // 4 + { "lb6b.cpu", 0x1000, 0xdc906e89, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "l9.f7", 0x1000, 0x77b1da1e, 2 | BRF_GRA }, // 6 Characters + { "l0.h7", 0x1000, 0xaa82e00b, 2 | BRF_GRA }, // 7 + + { "l8.l7", 0x1000, 0x8b99910b, 3 | BRF_GRA }, // 8 Sprites + { "l7.m7", 0x1000, 0x86a5b448, 3 | BRF_GRA }, // 9 + + { "10-2.k1", 0x0020, 0xdf091e52, 4 | BRF_GRA }, // 10 Color PROMs + { "10-1.f4", 0x0020, 0x40640d8f, 4 | BRF_GRA }, // 11 + { "10-3.c4", 0x0020, 0x27fa3a50, 4 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(ladybgb2) +STD_ROM_FN(ladybgb2) + +struct BurnDriver BurnDrvLadybgb2 = { + "ladybgb2", "ladybug", NULL, NULL, "1981", + "Lady Bug (bootleg set 2)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, ladybgb2RomInfo, ladybgb2RomName, NULL, NULL, LadybugInputInfo, LadybugDIPInfo, + LadybugInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 196, 240, 3, 4 +}; + + +// Snap Jack + +static struct BurnRomInfo snapjackRomDesc[] = { + { "sj1.c4", 0x1000, 0x6b30fcda, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "sj2.d4", 0x1000, 0x1f1088d1, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sj3.e4", 0x1000, 0xedd65f3a, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sj4.h4", 0x1000, 0xf4481192, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sj5.j4", 0x1000, 0x1bff7d05, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sj6.k4", 0x1000, 0x21793edf, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sj9.f7", 0x1000, 0xff2011c7, 2 | BRF_GRA }, // 6 Characters + { "sj0.h7", 0x1000, 0xf097babb, 2 | BRF_GRA }, // 7 + + { "sj8.l7", 0x1000, 0xb7f105b6, 3 | BRF_GRA }, // 8 Sprites + { "sj7.m7", 0x1000, 0x1cdb03a8, 3 | BRF_GRA }, // 9 + + { "10-2.k1", 0x0020, 0xcbbd9dd1, 4 | BRF_GRA }, // 10 Color PROMs + { "10-1.f4", 0x0020, 0x5b16fbd2, 4 | BRF_GRA }, // 11 + { "10-3.c4", 0x0020, 0x27fa3a50, 4 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(snapjack) +STD_ROM_FN(snapjack) + +struct BurnDriver BurnDrvSnapjack = { + "snapjack", NULL, NULL, NULL, "1982", + "Snap Jack\0", NULL, "Universal", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, snapjackRomInfo, snapjackRomName, NULL, NULL, LadybugInputInfo, SnapjackDIPInfo, + LadybugInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 240, 196, 4, 3 +}; + + +// Cosmic Avenger + +static struct BurnRomInfo cavengerRomDesc[] = { + { "1.c4", 0x1000, 0x9e0cc781, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "2.d4", 0x1000, 0x5ce5b950, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.e4", 0x1000, 0xbc28218d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4.h4", 0x1000, 0x2b32e9f5, 1 | BRF_PRG | BRF_ESS }, // 3 + { "5.j4", 0x1000, 0xd117153e, 1 | BRF_PRG | BRF_ESS }, // 4 + { "6.k4", 0x1000, 0xc7d366cb, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "9.f7", 0x1000, 0x63357785, 2 | BRF_GRA }, // 6 Characters + { "0.h7", 0x1000, 0x52ad1133, 2 | BRF_GRA }, // 7 + + { "8.l7", 0x1000, 0xb022bf2d, 3 | BRF_GRA }, // 8 Sprites + + { "10-2.k1", 0x0020, 0x42a24dd5, 4 | BRF_GRA }, // 9 Color PROMs + { "10-1.f4", 0x0020, 0xd736b8de, 4 | BRF_GRA }, // 10 + { "10-3.c4", 0x0020, 0x27fa3a50, 4 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(cavenger) +STD_ROM_FN(cavenger) + +static INT32 CavengerInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvCavenger = { + "cavenger", NULL, NULL, NULL, "1981", + "Cosmic Avenger\0", NULL, "Universal", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, cavengerRomInfo, cavengerRomName, NULL, NULL, LadybugInputInfo, CavengerDIPInfo, + CavengerInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 240, 196, 4, 3 +}; + + +// Dorodon (set 1) + +static struct BurnRomInfo dorodonRomDesc[] = { + { "dorodon.0", 0x2000, 0x460aaf26, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "dorodon.1", 0x2000, 0xd2451eb6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "dorodon.2", 0x2000, 0xd3c6ee6c, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "dorodon.5", 0x1000, 0x5eee2b85, 2 | BRF_GRA }, // 3 Characters + { "dorodon.6", 0x1000, 0x395ac25a, 2 | BRF_GRA }, // 4 + + { "dorodon.4", 0x1000, 0xd70bb50a, 3 | BRF_GRA }, // 5 Sprites + { "dorodon.3", 0x1000, 0xe44e59e6, 3 | BRF_GRA }, // 6 + + { "dorodon.bp4", 0x0100, 0xf865c135, 4 | BRF_PRG | BRF_ESS }, // 7 Protection PROMs + { "dorodon.bp3", 0x0100, 0x47b2f0bb, 4 | BRF_PRG | BRF_ESS }, // 8 + + { "dorodon.bp0", 0x0020, 0x8fcf0bc8, 5 | BRF_GRA }, // 9 Color PROMs + { "dorodon.bp1", 0x0020, 0x3f209be4, 5 | BRF_GRA }, // 10 + { "dorodon.bp2", 0x0020, 0x27fa3a50, 5 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(dorodon) +STD_ROM_FN(dorodon) + +static INT32 DorodonInit() +{ + return DrvInit(2); +} + +struct BurnDriver BurnDrvDorodon = { + "dorodon", NULL, NULL, NULL, "1982", + "Dorodon (set 1)\0", NULL, "Falcon", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, dorodonRomInfo, dorodonRomName, NULL, NULL, LadybugInputInfo, DorodonDIPInfo, + DorodonInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 196, 240, 3, 4 +}; + + +// Dorodon (set 2) + +static struct BurnRomInfo dorodon2RomDesc[] = { + { "1.3fg", 0x2000, 0x4d05d6f8, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "2.3h", 0x2000, 0x27b43b09, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.3k", 0x2000, 0x38d2f295, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "6.6a", 0x1000, 0x2a2d8b9c, 2 | BRF_GRA }, // 3 Characters + { "7.6bc", 0x1000, 0xd14f95fa, 2 | BRF_GRA }, // 4 + + { "5.3t", 0x1000, 0x54c04f58, 3 | BRF_GRA }, // 5 Sprites + { "4.3r", 0x1000, 0x1ebb6493, 3 | BRF_GRA }, // 6 + + { "dorodon.bp4", 0x0100, 0xf865c135, 4 | BRF_PRG | BRF_ESS }, // 7 Protection PROMs + { "dorodon.bp3", 0x0100, 0x47b2f0bb, 4 | BRF_PRG | BRF_ESS }, // 8 + + { "dorodon.bp0", 0x0020, 0x8fcf0bc8, 5 | BRF_GRA }, // 9 Color PROMs + { "dorodon.bp1", 0x0020, 0x3f209be4, 5 | BRF_GRA }, // 10 + { "dorodon.bp2", 0x0020, 0x27fa3a50, 5 | BRF_OPT }, // 11 +}; + +STD_ROM_PICK(dorodon2) +STD_ROM_FN(dorodon2) + +struct BurnDriver BurnDrvDorodon2 = { + "dorodon2", "dorodon", NULL, NULL, "1982", + "Dorodon (set 2)\0", NULL, "Falcon", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, dorodon2RomInfo, dorodon2RomName, NULL, NULL, LadybugInputInfo, DorodonDIPInfo, + DorodonInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x60, + 196, 240, 3, 4 +}; + + +// Space Raider + +static struct BurnRomInfo sraiderRomDesc[] = { + { "sraid3.r4", 0x2000, 0x0f389774, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "sraid2.n4", 0x2000, 0x38a48db0, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sraid1.m4", 0x2000, 0x2f302a4e, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "sraid-s4.h6", 0x2000, 0x57173a12, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + { "sraid-s5.j6", 0x2000, 0x5a459179, 2 | BRF_PRG | BRF_ESS }, // 4 + { "sraid-s6.l6", 0x2000, 0xea3aa25d, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "sraid-s0.k6", 0x1000, 0xa0373909, 3 | BRF_GRA }, // 6 Characters + { "sraids11.l6", 0x1000, 0xba22d949, 3 | BRF_GRA }, // 7 + + { "sraid-s7.m2", 0x1000, 0x299f8e07, 4 | BRF_GRA }, // 8 Sprites + { "sraid-s8.n2", 0x1000, 0x57ba8888, 4 | BRF_GRA }, // 9 + + { "sraid-s9.f6", 0x1000, 0x2380b90f, 5 | BRF_GRA }, // 10 Grid Tiles + + { "srpr10-1.a2", 0x0020, 0x121fdb99, 6 | BRF_GRA }, // 11 Color PROMs + { "srpr10-2.l3", 0x0020, 0x88b67e70, 6 | BRF_GRA }, // 12 + { "srpr10-3.c1", 0x0020, 0x27fa3a50, 6 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(sraider) +STD_ROM_FN(sraider) + +struct BurnDriver BurnDrvSraider = { + "sraider", NULL, NULL, NULL, "1982", + "Space Raider\0", NULL, "Universal", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, sraiderRomInfo, sraiderRomName, NULL, NULL, SraiderInputInfo, SraiderDIPInfo, + SraiderInit, DrvExit, SraiderFrame, SraiderDraw, DrvScan, &DrvRecalc, 0x82, + 196, 240, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_lkage.cpp b/src/burn/drivers/misc_pre90s/d_lkage.cpp new file mode 100644 index 00000000..379c334c --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_lkage.cpp @@ -0,0 +1,1072 @@ +// FB Alpha Legend of Kage driver Module +// Based on MAME driver by Phil Stroffolino + +#include "tiles_generic.h" +#include "taito_m68705.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvPortData; +static UINT8 *DrvMcuROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvMcuRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvUnkRAM; +static UINT8 *lkage_scroll; +static UINT8 *DrvVidReg; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvInps[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; + +static UINT8 flipscreen_x; +static UINT8 flipscreen_y; +static UINT8 soundlatch; + +static INT32 DrvNmiEnable; +static INT32 pending_nmi; + +static INT32 use_mcu; +static INT32 Lkageb; +static INT32 FakeMCUVal; + +static struct BurnInputInfo LkageInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 5, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 4, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 5, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 4, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 3, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Lkage) + +static struct BurnDIPInfo LkageDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0x7f, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus_Life" }, + {0x12, 0x01, 0x03, 0x03, "30000 100000" }, + {0x12, 0x01, 0x03, 0x02, "30000 70000" }, + {0x12, 0x01, 0x03, 0x01, "20000 70000" }, + {0x12, 0x01, 0x03, 0x00, "20000 50000" }, + + {0 , 0xfe, 0 , 2, "Free_Play" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x18, 0x18, "3" }, + {0x12, 0x01, 0x18, 0x10, "4" }, + {0x12, 0x01, 0x18, 0x08, "5" }, + {0x12, 0x01, 0x18, 0x00, "255 (Cheat)" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x80, 0x00, "Upright" }, + {0x12, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 16, "Coin_A" }, + {0x13, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x13, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x13, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x13, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin_B" }, + {0x13, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x13, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x13, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x13, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Initial Season" }, + {0x14, 0x01, 0x02, 0x02, "Spring" }, + {0x14, 0x01, 0x02, 0x00, "Winter" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x0c, 0x0c, "Easiest" }, + {0x14, 0x01, 0x0c, 0x08, "Easy" }, + {0x14, 0x01, 0x0c, 0x04, "Normal" }, + {0x14, 0x01, 0x0c, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Coinage Display" }, + {0x14, 0x01, 0x10, 0x10, "Coins/Credits" }, + {0x14, 0x01, 0x10, 0x00, "Insert Coin" }, + + {0 , 0xfe, 0 , 2, "Year Display" }, + {0x14, 0x01, 0x20, 0x00, "1985" }, + {0x14, 0x01, 0x20, 0x20, "MCMLXXXIV" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Slots" }, + {0x14, 0x01, 0x80, 0x80, "A and B" }, + {0x14, 0x01, 0x80, 0x00, "A only" }, +}; + +STDDIPINFO(Lkage) + +void __fastcall lkage_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0xe800) { + + DrvPalRAM[address & 0x7ff] = data; + + UINT16 col = (DrvPalRAM[(address & 0x7fe) | 1] << 8) | DrvPalRAM[(address & 0x7fe) | 0]; + + UINT8 r, g, b; + + r = (col >> 8) & 0x0f; + r |= r << 4; + + g = (col >> 4) & 0x0f; + g |= g << 4; + + b = (col >> 0) & 0x0f; + b |= b << 4; + + Palette[(address & 0x7ff) >> 1] = (r << 16) | (g << 8) | b; + DrvPalette[(address & 0x7ff) >> 1] = BurnHighCol(r, g, b, 0); + + return; + } + + switch (address) + { + case 0xf000: + case 0xf001: + case 0xf002: + case 0xf003: + DrvVidReg[address & 3] = data; + return; + + case 0xf060: + soundlatch = data; + if (DrvNmiEnable) { + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + } else { + pending_nmi = 1; + } + return; + + case 0xf061: + case 0xf063: + case 0xf0e1: + return; + + case 0xf062: { + if (Lkageb) { + FakeMCUVal = data; + } else { + standard_taito_mcu_write(data); + } + return; + } + + case 0xf0a0: + case 0xf0a1: + case 0xf0a2: + case 0xf0a3: + DrvUnkRAM[address & 3] = data; + return; + + case 0xf0c0: + case 0xf0c1: + case 0xf0c2: + case 0xf0c3: + case 0xf0c4: + case 0xf0c5: + lkage_scroll[address & 7] = data; + return; + } +} + +UINT8 __fastcall lkage_main_read(UINT16 address) +{ + switch (address) + { + case 0xf000: + case 0xf001: + case 0xf002: + case 0xf003: + return DrvVidReg[address & 3]; + + case 0xf062: { + if (Lkageb) { + switch (FakeMCUVal) { + case 0x01: return FakeMCUVal - 0x01; + case 0x90: return FakeMCUVal + 0x43; + case 0xa6: return FakeMCUVal + 0x27; + case 0x34: return FakeMCUVal + 0x7f; + case 0x48: return FakeMCUVal + 0xb7; + default: return FakeMCUVal; + } + } else { + return standard_taito_mcu_read(); + } + } + + case 0xf080: + case 0xf081: + case 0xf082: + return DrvDips[address & 3]; + + case 0xf083: + return DrvInps[0]; + + case 0xf084: + case 0xf085: + return DrvInps[address - 0xf083]; + + case 0xf087: { + if (Lkageb) { + return 0x03; + } else { + INT32 res = 0; + if (!main_sent) res |= 0x01; + if (mcu_sent) res |= 0x02; + return res; + } + } + + case 0xf0a0: + case 0xf0a1: + case 0xf0a2: + case 0xf0a3: + return DrvUnkRAM[address & 3]; + + case 0xf0c0: + case 0xf0c1: + case 0xf0c2: + case 0xf0c3: + case 0xf0c4: + case 0xf0c5: + return lkage_scroll[address & 7]; + } + + return 0; +} + +UINT8 __fastcall lkage_main_in(UINT16 port) +{ + if ((port & 0xc000) == 0x4000) { + return DrvPortData[port & 0x3fff]; + } + + return 0; +} + +UINT8 __fastcall lkage_sound_read(UINT16 address) +{ + switch (address) + { + case 0x9000: + return BurnYM2203Read(0, 0); + + case 0xa000: + return BurnYM2203Read(1, 0); + + case 0xb000: + return soundlatch; + + case 0xb001: + return 0; + } + + return 0; +} + +void __fastcall lkage_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x9000: + case 0x9001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0xa000: + case 0xa001: + BurnYM2203Write(1, address & 1, data); + return; + + case 0xb000: + return; + + case 0xb001: + { + DrvNmiEnable = 1; + if (pending_nmi) { + ZetNmi(); + pending_nmi = 0; + } + } + return; + + case 0xb002: + DrvNmiEnable = 0; + return; + } +} + +inline static void DrvYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 6000000.0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + m67805_taito_reset(); + + BurnYM2203Reset(); + + soundlatch = 0; + flipscreen_x = 0; + flipscreen_y = 0; + + DrvNmiEnable = 0; + pending_nmi = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvMcuROM = Next; Next += 0x000800; + + DrvPortData = Next; Next += 0x004000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + AllRam = Next; + + DrvVidRAM = Next; Next += 0x000c00; + + DrvZ80RAM0 = Next; Next += 0x000800; + DrvZ80RAM1 = Next; Next += 0x000800; + + DrvPalRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000100; + + DrvUnkRAM = Next; Next += 0x000004; + + DrvMcuRAM = Next; Next += 0x000080; + + lkage_scroll = Next; Next += 0x000006; + DrvVidReg = Next; Next += 0x000004; + + Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x20000, 0x00000, 0x60000, 0x40000 }; + INT32 XOffs[16] = { 7, 6, 5, 4, 3, 2, 1, 0, + 64+7, 64+6, 64+5, 64+4, 64+3, 64+2, 64+1, 64+0}; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 128+0*8, 128+1*8, 128+2*8, 128+3*8, 128+4*8, 128+5*8, 128+6*8, 128+7*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x10000); + + GfxDecode(0x800, 4, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM0); + GfxDecode(0x200, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + use_mcu = ~BurnDrvGetFlags() & BDF_BOOTLEG; + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x8000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x0000, 2, 1)) return 1; + + if (BurnLoadRom(DrvPortData, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x4000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x8000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0xc000, 7, 1)) return 1; + + if (use_mcu) { + if (BurnLoadRom(DrvMcuROM + 0x0000, 9, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xdfff, 2, DrvZ80ROM0); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80RAM0); + ZetMapArea(0xe800, 0xefff, 0, DrvPalRAM); +// ZetMapArea(0xe800, 0xefff, 1, DrvPalRAM); + ZetMapArea(0xe800, 0xefff, 2, DrvPalRAM); + ZetMapArea(0xf100, 0xf1ff, 0, DrvSprRAM); // 0xf100 - 0xf15f + ZetMapArea(0xf100, 0xf1ff, 1, DrvSprRAM); + ZetMapArea(0xf100, 0xf1ff, 2, DrvSprRAM); + ZetMapArea(0xf400, 0xffff, 0, DrvVidRAM); + ZetMapArea(0xf400, 0xffff, 1, DrvVidRAM); + ZetMapArea(0xf400, 0xffff, 2, DrvVidRAM); + ZetSetWriteHandler(lkage_main_write); + ZetSetReadHandler(lkage_main_read); + ZetSetInHandler(lkage_main_in); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + //ZetMapArea(0xe000, 0xefff, 0, DrvZ80ROM1 + 0xe000); + //ZetMapArea(0xe000, 0xefff, 2, DrvZ80ROM1 + 0xe000); + ZetSetWriteHandler(lkage_sound_write); + ZetSetReadHandler(lkage_sound_read); + ZetMemEnd(); + ZetClose(); + + m67805_taito_init(DrvMcuROM, DrvMcuRAM, &standard_m68705_interface); + + BurnYM2203Init(2, 4000000, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(1); + BurnTimerAttachZet(6000000); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + m67805_taito_exit(); + + BurnYM2203Exit(); + + BurnFree (AllMem); + + Lkageb = 0; + FakeMCUVal = 0; + + return 0; +} + + +static void draw_sprites(INT32 prio) +{ + const UINT8 *source = DrvSprRAM + 0x60 - 4; + const UINT8 *finish = DrvSprRAM; + + while (source >= finish) + { + INT32 attributes = source[2]; + INT32 priority = attributes >> 7; + if (priority != prio) { + source -= 4; + continue; + } + + INT32 color = (attributes>>4)&7; + INT32 flipx = attributes & 0x01; + INT32 flipy = attributes & 0x02; + INT32 height = (attributes & 0x08) ? 2 : 1; + INT32 sx = source[0]-15; + INT32 sy = 256-16*height-source[1]; + INT32 sprite_number = source[3] + ((attributes & 0x04) << 6); + INT32 y; + + if (flipscreen_x) + { + sx = 239 - sx - 24; + flipx = !flipx; + sx += 16; + } + if (flipscreen_y) + { + sy = 254 - 16*height - sy; + flipy = !flipy; + } + if (height == 2 && !flipy) + { + sprite_number ^= 1; + } + + sx -= 16; + sy -= 16; + + if (sx < -15) sx += 256; + + for (y = 0;y < height;y++) + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite_number ^ y, sx, sy + (y << 4), color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite_number ^ y, sx, sy + (y << 4), color, 4, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite_number ^ y, sx, sy + (y << 4), color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite_number ^ y, sx, sy + (y << 4), color, 4, 0, 0, DrvGfxROM1); + } + } + } + source -= 4; + } +} + +static void draw_layer(INT32 offset, INT32 bank, INT32 color, INT32 transp, INT32 scrollx, INT32 scrolly) +{ + color >>= 4; + + if (flipscreen_x) { + scrollx *= -1; + } + + if (flipscreen_y) { + scrolly *= -1; + } + + UINT8 *src = DrvVidRAM + offset; + + INT32 x_minus = flipscreen_x ? 24 : 16; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 code = src[offs] | (bank << 8); + + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + if (flipscreen_x) sx ^= 0xf8; + if (flipscreen_y) sy ^= 0xf8; + + sx -= scrollx; + sy -= scrolly; + + sx -= x_minus; + sy -= 16; + + if (sx < -7) sx += 256; + if (sy < -15) sy += 256; + if (sx > 239) sx -= 256; + if (sy > 223) sy -= 256; + + if (transp) { + if (flipscreen_y) { + if (flipscreen_x) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } else { + if (flipscreen_x) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } + } else { + if (flipscreen_y) { + if (flipscreen_x) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } else { + if (flipscreen_x) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + DrvRecalc = 0; + } + + flipscreen_x = ~DrvVidReg[2] & 0x01; + flipscreen_y = ~DrvVidReg[2] & 0x02; + + INT32 color_bank = (DrvVidReg[1] & 0xf0); + INT32 bg_bank = ((DrvVidReg[1] & 0x08) >> 1) + 1; + INT32 fg_bank = (DrvVidReg[0] & 0x04) >> 2; + + if ((DrvVidReg[2] & 0xf0) == 0xf0) + { + draw_layer(0x800, bg_bank, 0x300 | color_bank, 0, lkage_scroll[4]+5, lkage_scroll[5]); + + draw_sprites(1); + + if (~DrvVidReg[1] & 2) draw_sprites(0); + + draw_layer(0x400, fg_bank, 0x200 | color_bank, 1, lkage_scroll[2]+3, lkage_scroll[3]); + + if ( DrvVidReg[1] & 2) draw_sprites(0); + + draw_layer(0x000, 0, 0x110, 1, lkage_scroll[0]+1, lkage_scroll[1]); + } + else + { + if (nBurnLayer & 4)draw_layer(0x000, 0, 0x110, 0, lkage_scroll[0]+1, lkage_scroll[1]); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + DrvInps[0] = 0x0b; + DrvInps[1] = DrvInps[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + DrvInps[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[3] = { 6000000 / 60, 6000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 99) ZetRaiseIrq(0); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + + if (use_mcu) { + m6805Open(0); + nCyclesSegment = nCyclesTotal[2] / nInterleave; + nCyclesDone[2] += m6805Run(nCyclesSegment); + m6805Close(); + } + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029697; + } + + if (nAction & ACB_VOLATILE) { + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + + ZetScan(nAction); + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen_x); + SCAN_VAR(flipscreen_y); + SCAN_VAR(DrvNmiEnable); + SCAN_VAR(pending_nmi); + } + + return 0; +} + + +// The Legend of Kage + +static struct BurnRomInfo lkageRomDesc[] = { + { "a54-01-2.37", 0x8000, 0x60fd9734, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a54-02-2.38", 0x8000, 0x878a25ce, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "a54-05-1.84", 0x4000, 0x0033c06a, 4 | BRF_GRA }, // 4 Graphics + { "a54-06-1.85", 0x4000, 0x9f04d9ad, 4 | BRF_GRA }, // 5 + { "a54-07-1.86", 0x4000, 0xb20561a4, 4 | BRF_GRA }, // 6 + { "a54-08-1.87", 0x4000, 0x3ff3b230, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) + + { "a54-09.53", 0x0800, 0x0e8b8846, 6 | BRF_PRG | BRF_OPT }, // 9 68705 Code (unused) + + { "pal16l8-a54-11.34", 0x0104, 0x56232113, 7 | BRF_OPT }, // 10 Plds (unused) + { "pal16l8-a54-12.76", 0x0104, 0xe57c3c89, 7 | BRF_OPT }, // 11 + { "pal16l8a-a54-13.27", 0x0104, 0xc9b1938e, 7 | BRF_OPT }, // 12 + { "pal16l8a-a54-14.35", 0x0104, 0xa89c644e, 7 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(lkage) +STD_ROM_FN(lkage) + +struct BurnDriver BurnDrvLkage = { + "lkage", NULL, NULL, NULL, "1984", + "The Legend of Kage\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkageRomInfo, lkageRomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// The Legend of Kage (older) + +static struct BurnRomInfo lkageoRomDesc[] = { + { "a54-01-1.37", 0x8000, 0x973da9c5, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a54-02-1.38", 0x8000, 0x27b509da, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "a54-05-1.84", 0x4000, 0x0033c06a, 4 | BRF_GRA }, // 4 Graphics + { "a54-06-1.85", 0x4000, 0x9f04d9ad, 4 | BRF_GRA }, // 5 + { "a54-07-1.86", 0x4000, 0xb20561a4, 4 | BRF_GRA }, // 6 + { "a54-08-1.87", 0x4000, 0x3ff3b230, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) + + { "a54-09.53", 0x0800, 0x0e8b8846, 6 | BRF_PRG | BRF_OPT }, // 9 68705 Code + + { "pal16l8-a54-11.34", 0x0104, 0x56232113, 7 | BRF_OPT }, // 10 Plds (unused) + { "pal16l8-a54-12.76", 0x0104, 0xe57c3c89, 7 | BRF_OPT }, // 11 + { "pal16l8a-a54-13.27", 0x0104, 0xc9b1938e, 7 | BRF_OPT }, // 12 + { "pal16l8a-a54-14.35", 0x0104, 0xa89c644e, 7 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(lkageo) +STD_ROM_FN(lkageo) + +struct BurnDriver BurnDrvLkageo = { + "lkageo", "lkage", NULL, NULL, "1984", + "The Legend of Kage (older)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkageoRomInfo, lkageoRomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// The Legend of Kage (oldest) + +static struct BurnRomInfo lkageooRomDesc[] = { + { "a54-01.37", 0x8000, 0x34eab2c5, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a54-02.38", 0x8000, 0xea471d8a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "a54-05.84", 0x4000, 0x76753e52, 4 | BRF_GRA }, // 4 Graphics + { "a54-06.85", 0x4000, 0xf33c015c, 4 | BRF_GRA }, // 5 + { "a54-07.86", 0x4000, 0x0e02c2e8, 4 | BRF_GRA }, // 6 + { "a54-08.87", 0x4000, 0x4ef5f073, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) + + { "a54-09.53", 0x0800, 0x0e8b8846, 6 | BRF_PRG | BRF_OPT }, // 9 68705 Code + + { "pal16l8-a54-11.34", 0x0104, 0x56232113, 7 | BRF_OPT }, // 10 Plds (unused) + { "pal16l8-a54-12.76", 0x0104, 0xe57c3c89, 7 | BRF_OPT }, // 11 + { "pal16l8a-a54-13.27", 0x0104, 0xc9b1938e, 7 | BRF_OPT }, // 12 + { "pal16l8a-a54-14.35", 0x0104, 0xa89c644e, 7 | BRF_OPT }, // 13 +}; + +STD_ROM_PICK(lkageoo) +STD_ROM_FN(lkageoo) + +struct BurnDriver BurnDrvLkageoo = { + "lkageoo", "lkage", NULL, NULL, "1984", + "The Legend of Kage (oldest)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkageooRomInfo, lkageooRomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// The Legend of Kage (bootleg set 1) + +static struct BurnRomInfo lkagebRomDesc[] = { + { "ic37_1", 0x8000, 0x05694f7b, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "ic38_2", 0x8000, 0x22efe29e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "ic93_5", 0x4000, 0x76753e52, 4 | BRF_GRA }, // 4 Graphics + { "ic94_6", 0x4000, 0xf33c015c, 4 | BRF_GRA }, // 5 + { "ic95_7", 0x4000, 0x0e02c2e8, 4 | BRF_GRA }, // 6 + { "ic96_8", 0x4000, 0x4ef5f073, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) +}; + +STD_ROM_PICK(lkageb) +STD_ROM_FN(lkageb) + +static INT32 LkagebInit() +{ + Lkageb = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvLkageb = { + "lkageb", "lkage", NULL, NULL, "1984", + "The Legend of Kage (bootleg set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkagebRomInfo, lkagebRomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + LkagebInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// The Legend of Kage (bootleg set 2) + +static struct BurnRomInfo lkageb2RomDesc[] = { + { "lok.a", 0x8000, 0x866df793, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "lok.b", 0x8000, 0xfba9400f, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "ic93_5", 0x4000, 0x76753e52, 4 | BRF_GRA }, // 4 Graphics + { "ic94_6", 0x4000, 0xf33c015c, 4 | BRF_GRA }, // 5 + { "ic95_7", 0x4000, 0x0e02c2e8, 4 | BRF_GRA }, // 6 + { "ic96_8", 0x4000, 0x4ef5f073, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) +}; + +STD_ROM_PICK(lkageb2) +STD_ROM_FN(lkageb2) + +struct BurnDriver BurnDrvLkageb2 = { + "lkageb2", "lkage", NULL, NULL, "1984", + "The Legend of Kage (bootleg set 2)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkageb2RomInfo, lkageb2RomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + + +// The Legend of Kage (bootleg set 3) + +static struct BurnRomInfo lkageb3RomDesc[] = { + { "z1.bin", 0x8000, 0x60cac488, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "z2.bin", 0x8000, 0x22c95f17, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a54-04.54", 0x8000, 0x541faf9a, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "a54-03.51", 0x4000, 0x493e76d8, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #0 Data + + { "ic93_5", 0x4000, 0x76753e52, 4 | BRF_GRA }, // 4 Graphics + { "ic94_6", 0x4000, 0xf33c015c, 4 | BRF_GRA }, // 5 + { "ic95_7", 0x4000, 0x0e02c2e8, 4 | BRF_GRA }, // 6 + { "ic96_8", 0x4000, 0x4ef5f073, 4 | BRF_GRA }, // 7 + + { "a54-10.2", 0x0200, 0x17dfbd14, 5 | BRF_OPT }, // 8 Prom (unused) +}; + +STD_ROM_PICK(lkageb3) +STD_ROM_FN(lkageb3) + +struct BurnDriver BurnDrvLkageb3 = { + "lkageb3", "lkage", NULL, NULL, "1984", + "The Legend of Kage (bootleg set 3)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, lkageb3RomInfo, lkageb3RomName, NULL, NULL, LkageInputInfo, LkageDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_lwings.cpp b/src/burn/drivers/misc_pre90s/d_lwings.cpp new file mode 100644 index 00000000..75c280f1 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_lwings.cpp @@ -0,0 +1,2165 @@ +// FB Alpha "Legendary Wings" driver module +// Based on MAME driver by Paul Leaman + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm5205.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvTileMap; +static UINT8 *DrvGfxMask; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvBgRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *ScrollX; +static UINT8 *ScrollY; +static UINT8 DrvRecalc; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDip[2]; +static UINT8 DrvInp[3]; + +static UINT8 interrupt_enable; +static UINT8 soundlatch; +static UINT8 soundlatch2; +static UINT8 flipscreen; +static UINT8 DrvZ80Bank; + +static UINT8 avengers_param[4]; +static UINT32 avengers_palette_pen; +static UINT8 avengers_soundlatch2; +static UINT8 avengers_soundstate; + +static UINT8 trojan_bg2_scrollx; +static UINT8 trojan_bg2_image; + +static INT32 avengers = 0; +static INT32 MSM5205InUse = 0; + +static INT32 nCyclesTotal[3]; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo LwingsDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x08, "5" }, + {0x11, 0x01, 0x0c, 0x00, "6" }, + + {0 , 0xfe, 0 , 4, "Coin_B" }, + {0x11, 0x01, 0x30, 0x00, "4C_1C" }, + {0x11, 0x01, 0x30, 0x20, "3C_1C" }, + {0x11, 0x01, 0x30, 0x10, "2C_1C" }, + {0x11, 0x01, 0x30, 0x30, "1C_1C" }, + + {0 , 0xfe, 0 , 4, "Coin_A" }, + {0x11, 0x01, 0xc0, 0xc0, "1C_1C" }, + {0x11, 0x01, 0xc0, 0x00, "2C_4C" }, + {0x11, 0x01, 0xc0, 0x40, "1C_2C" }, + {0x11, 0x01, 0xc0, 0x80, "1C_3C" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x06, 0x02, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Medium" }, + {0x12, 0x01, 0x06, 0x04, "Hard" }, + {0x12, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x10, 0x00, "No" }, + {0x12, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 8, "Bonus_Life" }, + {0x12, 0x01, 0xe0, 0xe0, "20000 and every 50000"}, + {0x12, 0x01, 0xe0, 0x60, "20000 and every 60000"}, + {0x12, 0x01, 0xe0, 0xa0, "20000 and every 70000"}, + {0x12, 0x01, 0xe0, 0x20, "30000 and every 60000"}, + {0x12, 0x01, 0xe0, 0xc0, "30000 and every 70000"}, + {0x12, 0x01, 0xe0, 0x40, "30000 and every 80000"}, + {0x12, 0x01, 0xe0, 0x80, "40000 and every 100000"}, + {0x12, 0x01, 0xe0, 0x00, "None" }, +}; + +STDDIPINFO(Lwings) + +static struct BurnDIPInfo LwingsbDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x0c, 0x0c, "2" }, + {0x11, 0x01, 0x0c, 0x04, "3" }, + {0x11, 0x01, 0x0c, 0x08, "4" }, + {0x11, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Coin_B" }, + {0x11, 0x01, 0x30, 0x00, "4C_1C" }, + {0x11, 0x01, 0x30, 0x20, "3C_1C" }, + {0x11, 0x01, 0x30, 0x10, "2C_1C" }, + {0x11, 0x01, 0x30, 0x30, "1C_1C" }, + + {0 , 0xfe, 0 , 4, "Coin_A" }, + {0x11, 0x01, 0xc0, 0xc0, "1C_1C" }, + {0x11, 0x01, 0xc0, 0x00, "2C_4C" }, + {0x11, 0x01, 0xc0, 0x40, "1C_2C" }, + {0x11, 0x01, 0xc0, 0x80, "1C_3C" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x06, 0x02, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Medium" }, + {0x12, 0x01, 0x06, 0x04, "Hard" }, + {0x12, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x10, 0x00, "No" }, + {0x12, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 8, "Bonus_Life" }, + {0x12, 0x01, 0xe0, 0xe0, "20000 and every 50000" }, + {0x12, 0x01, 0xe0, 0x60, "20000 and every 60000" }, + {0x12, 0x01, 0xe0, 0xa0, "20000 and every 70000" }, + {0x12, 0x01, 0xe0, 0x20, "30000 and every 60000" }, + {0x12, 0x01, 0xe0, 0xc0, "30000 and every 70000" }, + {0x12, 0x01, 0xe0, 0x40, "30000 and every 80000" }, + {0x12, 0x01, 0xe0, 0x80, "40000 and every 100000" }, + {0x12, 0x01, 0xe0, 0x00, "None" }, +}; + +STDDIPINFO(Lwingsb) + +static struct BurnDIPInfo SectionzDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x3f, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x0c, 0x04, "2" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x08, "4" }, + {0x11, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Coin_A" }, + {0x11, 0x01, 0x30, 0x00, "4C_1C" }, + {0x11, 0x01, 0x30, 0x20, "3C_1C" }, + {0x11, 0x01, 0x30, 0x10, "2C_1C" }, + {0x11, 0x01, 0x30, 0x30, "1C_1C" }, + + {0 , 0xfe, 0 , 4, "Coin_B" }, + {0x11, 0x01, 0xc0, 0x00, "2C_1C" }, + {0x11, 0x01, 0xc0, 0xc0, "1C_1C" }, + {0x11, 0x01, 0xc0, 0x40, "1C_2C" }, + {0x11, 0x01, 0xc0, 0x80, "1C_3C" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x01, 0x00, "No" }, + {0x12, 0x01, 0x01, 0x01, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x06, 0x02, "Easy" }, + {0x12, 0x01, 0x06, 0x06, "Normal" }, + {0x12, 0x01, 0x06, 0x04, "Hard" }, + {0x12, 0x01, 0x06, 0x00, "Very_Hard" }, + + {0 , 0xfe, 0 , 8, "Bonus_Life" }, + {0x12, 0x01, 0x38, 0x38, "20000 50000" }, + {0x12, 0x01, 0x38, 0x18, "20000 60000" }, + {0x12, 0x01, 0x38, 0x28, "20000 70000" }, + {0x12, 0x01, 0x38, 0x08, "30000 60000" }, + {0x12, 0x01, 0x38, 0x30, "30000 70000" }, + {0x12, 0x01, 0x38, 0x10, "30000 80000" }, + {0x12, 0x01, 0x38, 0x20, "40000 100000" }, + {0x12, 0x01, 0x38, 0x00, "None" }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x12, 0x01, 0xc0, 0x00, "Upright One Player" }, + {0x12, 0x01, 0xc0, 0x40, "Upright Two Players" }, + {0x12, 0x01, 0xc0, 0xc0, "Cocktail" }, +}; + +STDDIPINFO(Sectionz) + +static struct BurnDIPInfo TrojanlsDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x1c, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x11, 0x01, 0x03, 0x00, "Upright 1 Player" }, + {0x11, 0x01, 0x03, 0x02, "Upright 2 Players" }, + {0x11, 0x01, 0x03, 0x03, "Cocktail" }, + + {0 , 0xfe, 0 , 8, "Bonus_Life" }, + {0x11, 0x01, 0x1c, 0x10, "20000 60000" }, + {0x11, 0x01, 0x1c, 0x0c, "20000 70000" }, + {0x11, 0x01, 0x1c, 0x08, "20000 80000" }, + {0x11, 0x01, 0x1c, 0x1c, "30000 60000" }, + {0x11, 0x01, 0x1c, 0x18, "30000 70000" }, + {0x11, 0x01, 0x1c, 0x14, "30000 80000" }, + {0x11, 0x01, 0x1c, 0x04, "40000 80000" }, + {0x11, 0x01, 0x1c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Coin_A" }, + {0x12, 0x01, 0x03, 0x00, "2C_1C" }, + {0x12, 0x01, 0x03, 0x03, "1C_1C" }, + {0x12, 0x01, 0x03, 0x02, "1C_2C" }, + {0x12, 0x01, 0x03, 0x01, "1C_3C" }, + + {0 , 0xfe, 0 , 4, "Coin_B" }, + {0x12, 0x01, 0x0c, 0x00, "4C_1C" }, + {0x12, 0x01, 0x0c, 0x04, "3C_1C" }, + {0x12, 0x01, 0x0c, 0x08, "2C_1C" }, + {0x12, 0x01, 0x0c, 0x0c, "1C_1C" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x30, 0x20, "2" }, + {0x12, 0x01, 0x30, 0x30, "3" }, + {0x12, 0x01, 0x30, 0x10, "4" }, + {0x12, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Trojanls) + +static struct BurnDIPInfo TrojanDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfc, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 3, "Cabinet" }, + {0x11, 0x01, 0x03, 0x00, "Upright 1 Player" }, + {0x11, 0x01, 0x03, 0x02, "Upright 2 Players" }, + {0x11, 0x01, 0x03, 0x03, "Cocktail" }, + + {0 , 0xfe, 0 , 8, "Bonus_Life" }, + {0x11, 0x01, 0x1c, 0x10, "20000 60000" }, + {0x11, 0x01, 0x1c, 0x0c, "20000 70000" }, + {0x11, 0x01, 0x1c, 0x08, "20000 80000" }, + {0x11, 0x01, 0x1c, 0x1c, "30000 60000" }, + {0x11, 0x01, 0x1c, 0x18, "30000 70000" }, + {0x11, 0x01, 0x1c, 0x14, "30000 80000" }, + {0x11, 0x01, 0x1c, 0x04, "40000 80000" }, + {0x11, 0x01, 0x1c, 0x00, "None" }, + + {0 , 0xfe, 0 , 6, "Starting Level" }, + {0x11, 0x01, 0xe0, 0xe0, "1" }, + {0x11, 0x01, 0xe0, 0xc0, "2" }, + {0x11, 0x01, 0xe0, 0xa0, "3" }, + {0x11, 0x01, 0xe0, 0x80, "4" }, + {0x11, 0x01, 0xe0, 0x60, "5" }, + {0x11, 0x01, 0xe0, 0x40, "6" }, + + {0 , 0xfe, 0 , 4, "Coin_A" }, + {0x12, 0x01, 0x03, 0x00, "2C_1C" }, + {0x12, 0x01, 0x03, 0x03, "1C_1C" }, + {0x12, 0x01, 0x03, 0x02, "1C_2C" }, + {0x12, 0x01, 0x03, 0x01, "1C_3C" }, + + {0 , 0xfe, 0 , 4, "Coin_B" }, + {0x12, 0x01, 0x0c, 0x00, "4C_1C" }, + {0x12, 0x01, 0x0c, 0x04, "3C_1C" }, + {0x12, 0x01, 0x0c, 0x08, "2C_1C" }, + {0x12, 0x01, 0x0c, 0x0c, "1C_1C" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x30, 0x20, "2" }, + {0x12, 0x01, 0x30, 0x30, "3" }, + {0x12, 0x01, 0x30, 0x10, "4" }, + {0x12, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Trojan) + +static struct BurnDIPInfo AvengersDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin_B" }, + {0x12, 0x01, 0x1c, 0x00, "4C_1C" }, + {0x12, 0x01, 0x1c, 0x10, "3C_1C" }, + {0x12, 0x01, 0x1c, 0x08, "2C_1C" }, + {0x12, 0x01, 0x1c, 0x1c, "1C_1C" }, + {0x12, 0x01, 0x1c, 0x0c, "1C_2C" }, + {0x12, 0x01, 0x1c, 0x14, "1C_3C" }, + {0x12, 0x01, 0x1c, 0x04, "1C_4C" }, + {0x12, 0x01, 0x1c, 0x18, "1C_6C" }, + + {0 , 0xfe, 0 , 8, "Coin_A" }, + {0x12, 0x01, 0xe0, 0x00, "4C_1C" }, + {0x12, 0x01, 0xe0, 0x80, "3C_1C" }, + {0x12, 0x01, 0xe0, 0x40, "2C_1C" }, + {0x12, 0x01, 0xe0, 0xe0, "1C_1C" }, + {0x12, 0x01, 0xe0, 0x60, "1C_2C" }, + {0x12, 0x01, 0xe0, 0xa0, "1C_3C" }, + {0x12, 0x01, 0xe0, 0x20, "1C_4C" }, + {0x12, 0x01, 0xe0, 0xc0, "1C_6C" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x11, 0x01, 0x01, 0x00, "No" }, + {0x11, 0x01, 0x01, 0x01, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x11, 0x01, 0x02, 0x00, "Off" }, + {0x11, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x0c, 0x04, "Easy" }, + {0x11, 0x01, 0x0c, 0x0c, "Normal" }, + {0x11, 0x01, 0x0c, 0x08, "Hard" }, + {0x11, 0x01, 0x0c, 0x00, "Very_Hard" }, + + {0 , 0xfe, 0 , 4, "Bonus_Life" }, + {0x11, 0x01, 0x30, 0x30, "20k 60k" }, + {0x11, 0x01, 0x30, 0x10, "20k 70k" }, + {0x11, 0x01, 0x30, 0x20, "20k 80k" }, + {0x11, 0x01, 0x30, 0x00, "30k 80k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0xc0, 0xc0, "3" }, + {0x11, 0x01, 0xc0, 0x40, "4" }, + {0x11, 0x01, 0xc0, 0x80, "5" }, + {0x11, 0x01, 0xc0, 0x00, "6" }, +}; + +STDDIPINFO(Avengers) + + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x020000; + DrvZ80ROM1 = Next; Next += 0x008000; + DrvZ80ROM2 = Next; Next += 0x010000; + + DrvTileMap = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + DrvGfxROM3 = Next; Next += 0x020000; + + DrvGfxMask = Next; Next += 0x000020; + + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x002000; + DrvZ80RAM1 = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x000800; + DrvBgRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000200; + DrvSprBuf = Next; Next += 0x000200; + + Palette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + ScrollX = Next; Next += 0x000002; + ScrollY = Next; Next += 0x000002; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +// Avengers protection code ripped directly from MAME +static void avengers_protection_w(UINT8 data) +{ + INT32 pc = ZetPc(-1); + + if (pc == 0x2eeb) + { + avengers_param[0] = data; + } + else if (pc == 0x2f09) + { + avengers_param[1] = data; + } + else if (pc == 0x2f26) + { + avengers_param[2] = data; + } + else if (pc == 0x2f43) + { + avengers_param[3] = data; + } + else if (pc == 0x0445) + { + avengers_soundstate = 0x80; + soundlatch = data; + } +} + +static INT32 avengers_fetch_paldata() +{ + static const char pal_data[] = + // page 1: 0x03,0x02,0x01,0x00 + "0000000000000000" "A65486A6364676D6" "C764C777676778A7" "A574E5E5C5756AE5" + "0000000000000000" "F51785D505159405" "A637B6A636269636" "F45744E424348824" + "0000000000000000" "A33263B303330203" "4454848454440454" "A27242C232523632" + "0000000000000000" "1253327202421102" "3386437373631373" "41A331A161715461" + "0000000000000000" "1341715000711203" "4442635191622293" "5143D48383D37186" + "0000000000000000" "2432423000412305" "6633343302333305" "7234A565A5A4A2A8" + "0000000000000000" "46232422A02234A7" "88241624A21454A7" "A3256747A665D3AA" + "0000000000000000" "070406020003050B" "0A05090504050508" "05060A090806040C" + + // page2: 0x07,0x06,0x05,0x04 + "0000000000000000" "2472030503230534" "6392633B23433B53" "0392846454346423" + "0000000000000000" "1313052405050423" "3223754805354832" "323346A38686A332" + "0000000000000000" "72190723070723D2" "81394776070776D1" "A15929F25959F2F1" + "0000000000000000" "650706411A2A1168" "770737C43A3A3466" "87071F013C0C3175" + "0000000000000000" "2001402727302020" "4403048F4A484344" "4A050B074E0E4440" + "0000000000000000" "3003800C35683130" "5304035C587C5453" "5607080C5B265550" + "0000000000000000" "4801D00043854245" "6C020038669A6569" "6604050A69446764" + "0000000000000000" "0504000001030504" "0A05090504060307" "04090D0507010403" + + // page3: 0x0b,0x0a,0x09,0x08 + "0000000000000000" "685A586937F777F7" "988A797A67A7A7A7" "B8CA898DC737F787" + "0000000000000000" "4738A61705150505" "8797672835250535" "7777072A25350525" + "0000000000000000" "3525642404340404" "6554453554440454" "5544053634540434" + "0000000000000000" "2301923203430303" "4333834383630373" "3324034473730363" + "0000000000000000" "3130304000762005" "5352525291614193" "6463635483D06581" + "0000000000000000" "4241415100483107" "6463631302335304" "76757415A5A077A3" + "0000000000000000" "53525282A02A43AA" "76747424A31565A5" "88888536A66089A4" + "0000000000000000" "05040304000D050C" "0806050604070707" "0A0A060808000C06" + + // page4: 0x0f,0x0e,0x0d,0x0c + "0000000000000000" "3470365956342935" "5590578997554958" "73C078A8C573687A" + "0000000000000000" "5355650685030604" "2427362686042607" "010A070584010508" + "0000000000000000" "0208432454022403" "737A243455733406" "000D050353000307" + "0000000000000000" "000A023233003202" "424C134234424204" "000F241132001105" + "0000000000000000" "3031113030300030" "5152215252512051" "7273337374723272" + "0000000000000000" "4141214041411041" "6263326363623162" "8385448585834383" + "0000000000000000" "5153225152512051" "7375437475734273" "9598559697946495" + "0000000000000000" "0205020303020102" "0407040606040304" "060A060809060506" + + // page5: 0x13,0x12,0x11,0x10 + "0000000000000000" "4151D141D3D177F7" "5454C44482C4A7A7" "0404D45491D4F787" + "0000000000000000" "0303032374230505" "9696962673560535" "0505054502850525" + "0000000000000000" "0303030355030404" "7777770754470454" "0606060603760434" + "0000000000000000" "0505053547050303" "4949492945390373" "0808083804580363" + "0000000000000000" "0B0C444023442005" "3D3F333433334193" "0000043504046581" + "0000000000000000" "0809565085863107" "0B6A352374455304" "00700644050677A3" + "0000000000000000" "06073879C8C843AA" "09492739A58765A5" "0050084A060889A4" + "0000000000000000" "05060B070B0B050C" "0707090707090707" "00000B08070B0C06" + + // page6: 0x17,0x16,0x15,0x14 + "0000000000000000" "0034308021620053" "0034417042512542" "0034526064502E31" + "0000000000000000" "0106412032733060" "11A6522053628350" "22A6632072620D42" + "0000000000000000" "1308223052242080" "2478233071235170" "3578243090230960" + "0000000000000000" "2111334333331404" "3353324232324807" "45B5314131310837" + "0000000000000000" "3232445444445302" "445443534343B725" "567642524242B745" + "0000000000000000" "4343556555550201" "5575546454540524" "6787536353537554" + "0000000000000000" "6474667676660100" "7696657575650423" "88A8647474645473" + "0000000000000000" "0001070701050004" "0003060603040303" "0005050505040302"; + + INT32 bank = avengers_palette_pen/64; + INT32 offs = avengers_palette_pen%64; + INT32 page = bank/4; // 0..7 + INT32 base = (3-(bank&3)); // 0..3 + INT32 row = offs&0xf; // 0..15 + INT32 col = offs/16 + base*4; // 0..15 + INT32 digit0 = pal_data[page*256*2 + (31-row*2)*16+col]; + INT32 digit1 = pal_data[page*256*2 + (30-row*2)*16+col]; + INT32 result; + + if( digit0>='A' ) digit0 += 10 - 'A'; else digit0 -= '0'; + if( digit1>='A' ) digit1 += 10 - 'A'; else digit1 -= '0'; + result = digit0 * 16 + digit1; + + if( (avengers_palette_pen&0x3f)!=0x3f ) avengers_palette_pen++; + + return result; +} + +static UINT8 avengers_protection_r() +{ + static const INT32 xpos[8] = { 10, 7, 0, -7, -10, -7, 0, 7 }; + static const INT32 ypos[8] = { 0, 7, 10, 7, 0, -7, -10, -7 }; + INT32 best_dist = 0; + INT32 best_dir = 0; + INT32 x,y; + INT32 dx,dy,dist,dir; + + if(ZetPc(-1) == 0x7c7 ) + { + // palette data + return avengers_fetch_paldata(); + } + + // int to Angle Function + // + // Input: two cartesian points + // Output: direction code (north,northeast,east,...) + // + x = avengers_param[0] - avengers_param[2]; + y = avengers_param[1] - avengers_param[3]; + for( dir=0; dir<8; dir++ ) + { + dx = xpos[dir]-x; + dy = ypos[dir]-y; + dist = dx*dx+dy*dy; + if( dist < best_dist || dir==0 ) + { + best_dir = dir; + best_dist = dist; + } + } + return best_dir<<5; +} + + + +UINT8 __fastcall lwings_main_read(UINT16 address) +{ + switch (address) + { + case 0xf808: + case 0xf809: + case 0xf80a: + return DrvInp[address - 0xf808]; + + case 0xf80b: + case 0xf80c: + return DrvDip[address - 0xf80b]; + + case 0xf80d: + return avengers_protection_r(); + } + + return 0; +} + +static void lwings_bankswitch_w(UINT8 data) +{ + DrvZ80Bank = data; + + INT32 bankaddress = 0x10000 + ((data >> 1) & 3) * 0x4000; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + bankaddress); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + bankaddress); +} + +void __fastcall lwings_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0xf000) { + DrvPalRAM[address & 0x7ff] = data; + + UINT8 r, g, b; + UINT16 coldata = DrvPalRAM[(address & 0x3ff) | 0x400] | (DrvPalRAM[address & 0x3ff] << 8); + + r = (coldata >> 8) & 0xf0; + g = (coldata >> 4) & 0xf0; + b = (coldata >> 0) & 0xf0; + + r |= r >> 4; + g |= g >> 4; + b |= b >> 4; + + Palette[address & 0x3ff] = (r << 16) | (g << 8) | b; + DrvPalette[address & 0x3ff] = BurnHighCol(r, g, b, 0); + + return; + } + + // hack + if (avengers && (address & 0xfff8) == 0xf808) address += 0x10; + + switch (address) + { + case 0xf800: + case 0xf801: + case 0xf808: + case 0xf809: + ScrollX[address & 1] = data; + return; + + case 0xf802: + case 0xf803: + case 0xf80a: + case 0xf80b: + ScrollY[address & 1] = data; + return; + + case 0xf804: + trojan_bg2_scrollx = data; + return; + + case 0xf805: + trojan_bg2_image = data; + return; + + case 0xf80c: + soundlatch = data; + return; + + case 0xf80d: + soundlatch2 = data; + return; + + case (0xf80e + 0x10): + case 0xf80e: + lwings_bankswitch_w(data); + + flipscreen = ~data & 0x01; + + interrupt_enable = data & 0x08; + return; + + case (0xf809 + 0x10): + avengers_protection_w(data); + return; + + case (0xf80c + 0x10): + avengers_palette_pen = data << 6; + return; + + case (0xf80d + 0x10): + soundlatch2 = data; + return; + } +} + +void __fastcall lwings_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + BurnYM2203Write((address & 2) >> 1, address & 1, data); + return; + + case 0xe006: + avengers_soundlatch2 = data; + return; + } +} + +UINT8 __fastcall lwings_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc800: + return soundlatch; + + case 0xe006: + UINT8 Data = avengers_soundlatch2 | avengers_soundstate; + avengers_soundstate = 0; + return Data; + } + + return 0; +} + +void __fastcall trojan_adpcm_out(UINT16 port, UINT8 data) +{ + if ((port & 0xff) == 0x01) { + MSM5205ResetWrite(0, (data >> 7) & 1); + MSM5205DataWrite(0, data); + MSM5205VCLKWrite(0, 1); + MSM5205VCLKWrite(0, 0); + } +} + +UINT8 __fastcall trojan_adpcm_in(UINT16 port) +{ + port &= 0xff; + + UINT8 ret = 0; + + if (port == 0x00) { + ret = soundlatch2; + } + + return ret; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + if (i == 0) lwings_bankswitch_w(0); + ZetClose(); + } + + if (MSM5205InUse) { + ZetOpen(2); + ZetReset(); + ZetClose(); + } + + BurnYM2203Reset(); + + if (MSM5205InUse) MSM5205Reset(); + + trojan_bg2_scrollx = 0; + trojan_bg2_image = 0; + + memset(avengers_param, 0, 4); + avengers_palette_pen = 0; + + avengers_soundlatch2 = 0; + avengers_soundstate = 0; + + DrvZ80Bank = 0; + flipscreen = 0; + interrupt_enable = 0; + soundlatch = 0; + soundlatch2 = 0; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[2] = { 0x000000, 0x000004 }; + INT32 Plane1[4] = { 0x080004, 0x080000, 0x000004, 0x000000 }; + INT32 Plane1a[4] = { 0x100004, 0x100000, 0x000004, 0x000000 }; + INT32 Plane2[4] = { 0x180000, 0x100000, 0x080000, 0x000000 }; + INT32 Plane3[4] = { 0x040000, 0x040004, 0x000000, 0x000004 }; + + // sprite, char + INT32 XOffs0[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; + INT32 YOffs0[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + + // background + INT32 XOffs1[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; + INT32 YOffs1[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0800, 2, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Plane2, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + if (DrvTileMap != NULL) { + GfxDecode(0x0800, 4, 16, 16, Plane1a, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x10000); + + GfxDecode(0x0200, 4, 16, 16, Plane3, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM3); + } else { + GfxDecode(0x0400, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM2); + } + + BurnFree (tmp); + + return 0; +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static INT32 DrvMSM5205SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / (nCyclesTotal[0] * 60)); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static void lwings_main_cpu_init() +{ + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + // 8000 - bfff banked + ZetMapArea(0xc000, 0xddff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xddff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xddff, 2, DrvZ80RAM0); + + ZetMapArea(0xde00, 0xdfff, 0, DrvSprRAM); + ZetMapArea(0xde00, 0xdfff, 1, DrvSprRAM); + ZetMapArea(0xde00, 0xdfff, 2, DrvSprRAM); + + ZetMapArea(0xe000, 0xe7ff, 0, DrvFgRAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvFgRAM); + ZetMapArea(0xe000, 0xe7ff, 2, DrvFgRAM); + + ZetMapArea(0xe800, 0xefff, 0, DrvBgRAM); + ZetMapArea(0xe800, 0xefff, 1, DrvBgRAM); + ZetMapArea(0xe800, 0xefff, 2, DrvBgRAM); + + ZetMapArea(0xf000, 0xf7ff, 0, DrvPalRAM); +// ZetMapArea(0xf000, 0xf7ff, 1, DrvPalRAM); // write handler + ZetMapArea(0xf000, 0xf7ff, 2, DrvPalRAM); + ZetSetReadHandler(lwings_main_read); + ZetSetWriteHandler(lwings_main_write); + ZetMemEnd(); + ZetClose(); +} + +static void lwings_sound_init() +{ + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM1); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM1); + ZetSetReadHandler(lwings_sound_read); + ZetSetWriteHandler(lwings_sound_write); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1500000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(4); + BurnTimerAttachZet(3000000); +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + DrvTileMap = NULL; + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x18000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 4, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x8000, i + 5, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x8000, i + 13, 1)) return 1; + } + + DrvGfxDecode(); + } + + ZetInit(2); + lwings_main_cpu_init(); + lwings_sound_init(); + + GenericTilesInit(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesTotal[2] = 0; + + DrvDoReset(); + + return 0; +} + +static INT32 TrojanInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x18000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM2 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x8000, i + 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x8000, i + 14, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x0000, 22, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x8000, 23, 1)) return 1; + + if (BurnLoadRom(DrvTileMap, 24, 1)) return 1; + + DrvGfxDecode(); + + { + for (INT32 i = 0; i < 32; i++) { + DrvGfxMask[i] = (0xf07f0001 & (1 << i)) ? 1 : 0; + } + } + } + + ZetInit(3); + lwings_main_cpu_init(); + lwings_sound_init(); + + ZetOpen(2); + ZetMapArea(0x0000, 0xffff, 0, DrvZ80ROM2); + ZetMapArea(0x0000, 0xffff, 2, DrvZ80ROM2); + ZetSetInHandler(trojan_adpcm_in); + ZetSetOutHandler(trojan_adpcm_out); + ZetMemEnd(); + ZetClose(); + + MSM5205Init(0, DrvMSM5205SynchroniseStream, 455000, NULL, MSM5205_SEX_4B, 50, 1); + MSM5205InUse = 1; + + GenericTilesInit(); + + nCyclesTotal[0] = 3000000 / 60; + nCyclesTotal[1] = 3000000 / 60; + nCyclesTotal[2] = 3000000 / 60; + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + BurnYM2203Exit(); + MSM5205Exit(); + + BurnFree (AllMem); + + avengers = 0; + MSM5205InUse = 0; + + return 0; +} + +static void draw_foreground(INT32 colbase) +{ + for (INT32 offs = 0x20; offs < 0x3e0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 color = DrvFgRAM[offs | 0x400]; + INT32 code = DrvFgRAM[offs] | ((color & 0xc0) << 2); + + INT32 flipx = color & 0x10; + INT32 flipy = color & 0x20; + + color &= 0x0f; + + sy -= 8; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 2, 0x03, colbase, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 2, 0x03, colbase, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 2, 0x03, colbase, DrvGfxROM0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 0x03, colbase, DrvGfxROM0); + } + } + } +} + +static void draw_background() +{ + INT32 scrollx = (ScrollX[0] | (ScrollX[1] << 8)) & 0x1ff; + INT32 scrolly = (ScrollY[0] | (ScrollY[1] << 8)) & 0x1ff; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sy = (offs & 0x1f) << 4; + INT32 sx = (offs >> 5) << 4; + sy -= 8; + + sx -= scrollx; + sy -= scrolly; + if (sx < -15) sx += 512; + if (sy < -15) sy += 512; + + if (sy < -15 || sx < -15 || sy >= nScreenHeight || sx >= nScreenWidth) + continue; + + INT32 color = DrvBgRAM[offs | 0x400]; + INT32 code = DrvBgRAM[offs] | (color & 0xe0) << 3;; + + INT32 flipx = color & 0x08; + INT32 flipy = color & 0x10; + + color &= 0x07; + + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM1); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM1); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM1); + } + } + } +} + +static void lwings_draw_sprites() +{ + for (INT32 offs = 0x200 - 4; offs >= 0; offs -= 4) + { + INT32 sx = DrvSprBuf[offs + 3] - 0x100 * (DrvSprBuf[offs + 1] & 0x01); + INT32 sy = DrvSprBuf[offs + 2]; + + if (sy && sx) + { + INT32 code,color,flipx,flipy; + + if (sy > 0xf8) sy-=0x100; + + code = DrvSprBuf[offs] | ((DrvSprBuf[offs + 1] & 0xc0) << 2); + color = (DrvSprBuf[offs + 1] & 0x38) >> 3; + flipx = DrvSprBuf[offs + 1] & 0x02; + flipy = DrvSprBuf[offs + 1] & 0x04; + + color += 0x18; + + sy -= 8; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } + } + } + } +} + + +static void draw_16x16_with_mask(INT32 sx, INT32 sy, INT32 code, INT32 color, UINT8 *gfxbase, UINT8 *mask, INT32 flipx, INT32 flipy) +{ + UINT8 *src = gfxbase + (code << 8); + + color = (color << 4) | 0x100; + + if (flipy) { + src += 0xf0; + + if (flipx) { + for (INT32 y = 15; y >= 0; y--, src-=16) + { + INT32 yy = sy + y; + if (yy < 0) break; + if (yy >= nScreenHeight) continue; + + for (INT32 x = 15; x >= 0; x--) + { + INT32 xx = sx + x; + if (xx < 0) break; + if (xx >= nScreenWidth) continue; + + INT32 o = color | src[15-x]; + if (mask[src[15-x]]) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = o; + } + } + } else { + for (INT32 y = 15; y >= 0; y--, src-=16) + { + INT32 yy = sy + y; + if (yy < 0) break; + if (yy >= nScreenHeight) continue; + + for (INT32 x = 0; x < 16; x++) + { + INT32 xx = sx + x; + if (xx < 0) continue; + if (xx >= nScreenWidth) break; + + INT32 o = color | src[x]; + if (mask[src[x]]) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = o; + } + } + } + } else { + if (flipx) { + for (INT32 y = 0; y < 16; y++, src+=16) + { + INT32 yy = sy + y; + if (yy < 0) continue; + if (yy >= nScreenHeight) break; + + for (INT32 x = 15; x >= 0; x--) + { + INT32 xx = sx + x; + if (xx < 0) break; + if (xx >= nScreenWidth) continue; + + INT32 o = color | src[15-x]; + if (mask[src[15-x]]) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = o; + } + } + } else { + for (INT32 y = 0; y < 16; y++, src+=16) + { + INT32 yy = sy + y; + if (yy < 0) continue; + if (yy >= nScreenHeight) break; + + for (INT32 x = 0; x < 16; x++) + { + INT32 xx = sx + x; + if (xx < 0) continue; + if (xx >= nScreenWidth) break; + + INT32 o = color | src[x]; + if (mask[src[x]]) continue; + + pTransDraw[(yy * nScreenWidth) + xx] = o; + } + } + } + } +} + +static void trojan_draw_background(INT32 priority) +{ + INT32 scrollx = (ScrollX[0] | (ScrollX[1] << 8)) & 0x1ff; + INT32 scrolly = (ScrollY[0] | (ScrollY[1] << 8)) & 0x1ff; + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 color = DrvBgRAM[offs | 0x400]; + if (priority && ((~color >> 3) & 1)) continue; + + INT32 sy = (offs & 0x1f) << 4; + INT32 sx = (offs >> 5) << 4; + sy -= 8; + + sx -= scrollx; + sy -= scrolly; + if (sx < -15) sx += 512; + if (sy < -15) sy += 512; + + if (sy < -15 || sx < -15 || sy >= nScreenHeight || sx >= nScreenWidth) + continue; + + INT32 code = DrvBgRAM[offs] | ((color & 0xe0) << 3); + INT32 flipx = color & 0x10; + INT32 flipy = 0; + + color &= 0x07; + + if (avengers) color ^= 6; + + draw_16x16_with_mask(sx, sy, code, color, DrvGfxROM1, DrvGfxMask + priority * 16, flipx, flipy); +/* + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x00, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x00, 0x100, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x00, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x00, 0x100, DrvGfxROM1); + } + } +*/ + } +} + +static void trojan_draw_background2() +{ + for (INT32 offs = 0; offs < 32 * 16; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= trojan_bg2_scrollx; + if (sx < -15) sx += 512; + sy -= 8; + + if (sy < -15 || sx < -15 || sy >= nScreenHeight || sx >= nScreenWidth) + continue; + + INT32 offset = ((((offs << 6) & 0x7800) | ((offs << 1) & 0x3e)) + (trojan_bg2_image << 5)) & 0x7fff; + + INT32 color = DrvTileMap[offset + 1]; + INT32 code = DrvTileMap[offset + 0] | ((color & 0x80) << 1); + INT32 flipx = color & 0x10; + INT32 flipy = color & 0x20; + + color &= 7; + + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM3); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM3); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM3); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM3); + } + } + } +} + +static void trojan_draw_sprites() +{ + for (INT32 offs = 0x180 - 4; offs >= 0; offs -= 4) + { + INT32 sx = DrvSprBuf[offs + 3] - 0x100 * (DrvSprBuf[offs + 1] & 0x01); + INT32 sy = DrvSprBuf[offs + 2]; + + if (sy && sx) + { + INT32 flipx, flipy; + + if (sy > 0xf8) sy-=0x100; + + INT32 color = DrvSprBuf[offs + 1]; + INT32 code = DrvSprBuf[offs] | ((color & 0x20) << 4) | ((color & 0x40) << 2) | ((color & 0x80) << 3); + + if (avengers) + { + flipx = 0; + flipy = ~color & 0x10; + } + else + { + flipx = color & 0x10; + flipy = 1; + } + + color = ((color >> 1) & 7) + 0x28; + + sy -= 8; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0x0f, 0, DrvGfxROM2); + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + if (DrvTileMap == NULL) { + draw_background(); + lwings_draw_sprites(); + draw_foreground(0x200); + } else { + trojan_draw_background2(); + trojan_draw_background(0); + trojan_draw_sprites(); + trojan_draw_background(1); + draw_foreground(0x300); + } + + if (flipscreen) { + UINT16 *ptr = pTransDraw + (nScreenWidth * nScreenHeight) - 1; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight / 2; i++, ptr--) + { + INT32 n = pTransDraw[i]; + pTransDraw[i] = *ptr; + *ptr = n; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInp, 0xff, 3); + + for (INT32 i = 0; i < 8; i++) { + DrvInp[0] ^= (DrvJoy1[i] & 1) << i; + DrvInp[1] ^= (DrvJoy2[i] & 1) << i; + DrvInp[2] ^= (DrvJoy3[i] & 1) << i; + } + + if ((DrvInp[1] & 0x03) == 0) DrvInp[1] |= 0x03; + if ((DrvInp[1] & 0x0c) == 0) DrvInp[1] |= 0x0c; + if ((DrvInp[2] & 0x03) == 0) DrvInp[2] |= 0x03; + if ((DrvInp[2] & 0x0c) == 0) DrvInp[2] |= 0x0c; + } + + INT32 nInterleave; + INT32 MSMIRQSlice[67]; + + if (MSM5205InUse) { + nInterleave = MSM5205CalcInterleave(0, 6000000); + + for (INT32 i = 0; i < 67; i++) { + MSMIRQSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 68)); + } + } else { + nInterleave = 16; + } + + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (interrupt_enable && i == (nInterleave - 1)) { + if (avengers & 1) { + ZetNmi(); + } else { + ZetSetVector(0xd7); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } + if (MSM5205InUse) MSM5205Update(); + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if ((i % (nInterleave / 4)) == ((nInterleave / 4) - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + if (MSM5205InUse) { + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + for (INT32 j = 0; j < 67; j++) { + if (i == MSMIRQSlice[j]) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + nCyclesDone[nCurrentCPU] += ZetRun(1000); + } + } + ZetClose(); + } + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + if (MSM5205InUse) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x200); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029692; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + if (MSM5205InUse) MSM5205Scan(nAction, pnMin); + + SCAN_VAR(interrupt_enable); + SCAN_VAR(soundlatch); + SCAN_VAR(soundlatch2); + SCAN_VAR(flipscreen); + SCAN_VAR(DrvZ80Bank); + + SCAN_VAR(*((UINT32*)avengers_param)); + SCAN_VAR(avengers_palette_pen); + SCAN_VAR(avengers_soundlatch2); + SCAN_VAR(avengers_soundstate); + SCAN_VAR(trojan_bg2_scrollx); + SCAN_VAR(trojan_bg2_image); + } + + ZetOpen(0); + lwings_bankswitch_w(DrvZ80Bank); + ZetClose(); + + return 0; +} + + +// Section Z (set 1) + +static struct BurnRomInfo sectionzRomDesc[] = { + { "6c_sz01.bin", 0x8000, 0x69585125, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "7c_sz02.bin", 0x8000, 0x22f161b8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "9c_sz03.bin", 0x8000, 0x4c7111ed, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_sz04.bin", 0x8000, 0xa6073566, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "9h_sz05.bin", 0x4000, 0x3173ba2e, 4 | BRF_GRA }, // 4 Characters + + { "3e_sz14.bin", 0x8000, 0x63782e30, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "1e_sz08.bin", 0x8000, 0xd57d9f13, 5 | BRF_GRA }, // 6 + { "3d_sz13.bin", 0x8000, 0x1b3d4d7f, 5 | BRF_GRA }, // 7 + { "1d_sz07.bin", 0x8000, 0xf5b3a29f, 5 | BRF_GRA }, // 8 + { "3b_sz12.bin", 0x8000, 0x11d47dfd, 5 | BRF_GRA }, // 9 + { "1b_sz06.bin", 0x8000, 0xdf703b68, 5 | BRF_GRA }, // 10 + { "3f_sz15.bin", 0x8000, 0x36bb9bf7, 5 | BRF_GRA }, // 11 + { "1f_sz09.bin", 0x8000, 0xda8f06c9, 5 | BRF_GRA }, // 12 + + { "3j_sz17.bin", 0x8000, 0x8df7b24a, 6 | BRF_GRA }, // 13 Sprites + { "1j_sz11.bin", 0x8000, 0x685d4c54, 6 | BRF_GRA }, // 14 + { "3h_sz16.bin", 0x8000, 0x500ff2bb, 6 | BRF_GRA }, // 15 + { "1h_sz10.bin", 0x8000, 0x00b3d244, 6 | BRF_GRA }, // 16 + + { "mb7114e.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(sectionz) +STD_ROM_FN(sectionz) + +struct BurnDriver BurnDrvSectionz = { + "sectionz", NULL, NULL, NULL, "1985", + "Section Z (set 1)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, sectionzRomInfo, sectionzRomName, NULL, NULL, DrvInputInfo, SectionzDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Section Z (set 2) + +static struct BurnRomInfo sctionzaRomDesc[] = { + { "sz-01a.bin", 0x8000, 0x98df49fd, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "7c_sz02.bin", 0x8000, 0x22f161b8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sz-03j.bin", 0x8000, 0x94547abf, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_sz04.bin", 0x8000, 0xa6073566, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "9h_sz05.bin", 0x4000, 0x3173ba2e, 4 | BRF_GRA }, // 4 Characters + + { "3e_sz14.bin", 0x8000, 0x63782e30, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "1e_sz08.bin", 0x8000, 0xd57d9f13, 5 | BRF_GRA }, // 6 + { "3d_sz13.bin", 0x8000, 0x1b3d4d7f, 5 | BRF_GRA }, // 7 + { "1d_sz07.bin", 0x8000, 0xf5b3a29f, 5 | BRF_GRA }, // 8 + { "3b_sz12.bin", 0x8000, 0x11d47dfd, 5 | BRF_GRA }, // 9 + { "1b_sz06.bin", 0x8000, 0xdf703b68, 5 | BRF_GRA }, // 10 + { "3f_sz15.bin", 0x8000, 0x36bb9bf7, 5 | BRF_GRA }, // 11 + { "1f_sz09.bin", 0x8000, 0xda8f06c9, 5 | BRF_GRA }, // 12 + + { "3j_sz17.bin", 0x8000, 0x8df7b24a, 6 | BRF_GRA }, // 13 Sprites + { "1j_sz11.bin", 0x8000, 0x685d4c54, 6 | BRF_GRA }, // 14 + { "3h_sz16.bin", 0x8000, 0x500ff2bb, 6 | BRF_GRA }, // 15 + { "1h_sz10.bin", 0x8000, 0x00b3d244, 6 | BRF_GRA }, // 16 + + { "mb7114e.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(sctionza) +STD_ROM_FN(sctionza) + +struct BurnDriver BurnDrvSctionza = { + "sectionza", "sectionz", NULL, NULL, "1985", + "Section Z (set 2)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, sctionzaRomInfo, sctionzaRomName, NULL, NULL, DrvInputInfo, SectionzDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Legendary Wings (US set 1) + +static struct BurnRomInfo lwingsRomDesc[] = { + { "6c_lw01.bin", 0x8000, 0xb55a7f60, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "7c_lw02.bin", 0x8000, 0xa5efbb1b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "9c_lw03.bin", 0x8000, 0xec5cc201, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_lw04.bin", 0x8000, 0xa20337a2, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "9h_lw05.bin", 0x4000, 0x091d923c, 4 | BRF_GRA }, // 4 Characters + + { "3e_lw14.bin", 0x8000, 0x5436392c, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "1e_lw08.bin", 0x8000, 0xb491bbbb, 5 | BRF_GRA }, // 6 + { "3d_lw13.bin", 0x8000, 0xfdd1908a, 5 | BRF_GRA }, // 7 + { "1d_lw07.bin", 0x8000, 0x5c73d406, 5 | BRF_GRA }, // 8 + { "3b_lw12.bin", 0x8000, 0x32e17b3c, 5 | BRF_GRA }, // 9 + { "1b_lw06.bin", 0x8000, 0x52e533c1, 5 | BRF_GRA }, // 10 + { "3f_lw15.bin", 0x8000, 0x99e134ba, 5 | BRF_GRA }, // 11 + { "1f_lw09.bin", 0x8000, 0xc8f28777, 5 | BRF_GRA }, // 12 + + { "3j_lw17.bin", 0x8000, 0x5ed1bc9b, 6 | BRF_GRA }, // 13 Sprites + { "1j_lw11.bin", 0x8000, 0x2a0790d6, 6 | BRF_GRA }, // 14 + { "3h_lw16.bin", 0x8000, 0xe8834006, 6 | BRF_GRA }, // 15 + { "1h_lw10.bin", 0x8000, 0xb693f5a5, 6 | BRF_GRA }, // 16 + + { "63s141.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(lwings) +STD_ROM_FN(lwings) + +struct BurnDriver BurnDrvLwings = { + "lwings", NULL, NULL, NULL, "1986", + "Legendary Wings (US set 1)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, lwingsRomInfo, lwingsRomName, NULL, NULL, DrvInputInfo, LwingsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Legendary Wings (US set 2) + +static struct BurnRomInfo lwings2RomDesc[] = { + { "u13-l", 0x8000, 0x3069c01c, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "u14-k", 0x8000, 0x5d91c828, 1 | BRF_PRG | BRF_ESS }, // 1 + { "9c_lw03.bin", 0x8000, 0xec5cc201, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_lw04.bin", 0x8000, 0xa20337a2, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "9h_lw05.bin", 0x4000, 0x091d923c, 4 | BRF_GRA }, // 4 Characters + + { "b_03e.rom", 0x8000, 0x176e3027, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "b_01e.rom", 0x8000, 0xf5d25623, 5 | BRF_GRA }, // 6 + { "b_03d.rom", 0x8000, 0x001caa35, 5 | BRF_GRA }, // 7 + { "b_01d.rom", 0x8000, 0x0ba008c3, 5 | BRF_GRA }, // 8 + { "b_03b.rom", 0x8000, 0x4f8182e9, 5 | BRF_GRA }, // 9 + { "b_01b.rom", 0x8000, 0xf1617374, 5 | BRF_GRA }, // 10 + { "b_03f.rom", 0x8000, 0x9b374dcc, 5 | BRF_GRA }, // 11 + { "b_01f.rom", 0x8000, 0x23654e0a, 5 | BRF_GRA }, // 12 + + { "b_03j.rom", 0x8000, 0x8f3c763a, 6 | BRF_GRA }, // 13 Sprites + { "b_01j.rom", 0x8000, 0x7cc90a1d, 6 | BRF_GRA }, // 14 + { "b_03h.rom", 0x8000, 0x7d58f532, 6 | BRF_GRA }, // 15 + { "b_01h.rom", 0x8000, 0x3e396eda, 6 | BRF_GRA }, // 16 + + { "63s141.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(lwings2) +STD_ROM_FN(lwings2) + +struct BurnDriver BurnDrvLwings2 = { + "lwings2", "lwings", NULL, NULL, "1986", + "Legendary Wings (US set 2)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, lwings2RomInfo, lwings2RomName, NULL, NULL, DrvInputInfo, LwingsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Ares no Tsubasa (Japan) + +static struct BurnRomInfo lwingsjpRomDesc[] = { + { "a_06c.rom", 0x8000, 0x2068a738, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a_07c.rom", 0x8000, 0xd6a2edc4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "9c_lw03.bin", 0x8000, 0xec5cc201, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "11e_lw04.bin", 0x8000, 0xa20337a2, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "9h_lw05.bin", 0x4000, 0x091d923c, 4 | BRF_GRA }, // 4 Characters + + { "b_03e.rom", 0x8000, 0x176e3027, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "b_01e.rom", 0x8000, 0xf5d25623, 5 | BRF_GRA }, // 6 + { "b_03d.rom", 0x8000, 0x001caa35, 5 | BRF_GRA }, // 7 + { "b_01d.rom", 0x8000, 0x0ba008c3, 5 | BRF_GRA }, // 8 + { "b_03b.rom", 0x8000, 0x4f8182e9, 5 | BRF_GRA }, // 9 + { "b_01b.rom", 0x8000, 0xf1617374, 5 | BRF_GRA }, // 10 + { "b_03f.rom", 0x8000, 0x9b374dcc, 5 | BRF_GRA }, // 11 + { "b_01f.rom", 0x8000, 0x23654e0a, 5 | BRF_GRA }, // 12 + + { "b_03j.rom", 0x8000, 0x8f3c763a, 6 | BRF_GRA }, // 13 Sprites + { "b_01j.rom", 0x8000, 0x7cc90a1d, 6 | BRF_GRA }, // 14 + { "b_03h.rom", 0x8000, 0x7d58f532, 6 | BRF_GRA }, // 15 + { "b_01h.rom", 0x8000, 0x3e396eda, 6 | BRF_GRA }, // 16 + + { "63s141.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(lwingsjp) +STD_ROM_FN(lwingsjp) + +struct BurnDriver BurnDrvLwingsjp = { + "lwingsj", "lwings", NULL, NULL, "1986", + "Ares no Tsubasa (Japan)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, lwingsjpRomInfo, lwingsjpRomName, NULL, NULL, DrvInputInfo, LwingsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Legendary Wings (bootleg) + +static struct BurnRomInfo lwingsbRomDesc[] = { + { "ic17.bin", 0x8000, 0xfe8a8823, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "ic18.bin", 0x8000, 0x2a00cde8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ic19.bin", 0x8000, 0xec5cc201, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "ic37.bin", 0x8000, 0xa20337a2, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "ic60.bin", 0x4000, 0x091d923c, 4 | BRF_GRA }, // 4 Characters + + { "ic50.bin", 0x8000, 0x5436392c, 5 | BRF_GRA }, // 5 Background Layer 1 Tiles + { "ic49.bin", 0x8000, 0xffdbdd69, 5 | BRF_GRA }, // 6 + { "ic26.bin", 0x8000, 0xfdd1908a, 5 | BRF_GRA }, // 7 + { "ic25.bin", 0x8000, 0x5c73d406, 5 | BRF_GRA }, // 8 + { "ic2.bin", 0x8000, 0x32e17b3c, 5 | BRF_GRA }, // 9 + { "ic1.bin", 0x8000, 0x52e533c1, 5 | BRF_GRA }, // 10 + { "ic63.bin", 0x8000, 0x99e134ba, 5 | BRF_GRA }, // 11 + { "ic62.bin", 0x8000, 0xc8f28777, 5 | BRF_GRA }, // 12 + + { "ic99.bin", 0x8000, 0x163946da, 6 | BRF_GRA }, // 13 Sprites + { "ic98.bin", 0x8000, 0x7cc90a1d, 6 | BRF_GRA }, // 14 + { "ic87.bin", 0x8000, 0xbca275ac, 6 | BRF_GRA }, // 15 + { "ic86.bin", 0x8000, 0x3e396eda, 6 | BRF_GRA }, // 16 + + { "63s141.15g", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 17 Proms (not used) +}; + +STD_ROM_PICK(lwingsb) +STD_ROM_FN(lwingsb) + +struct BurnDriver BurnDrvLwingsb = { + "lwingsb", "lwings", NULL, NULL, "1986", + "Legendary Wings (bootleg)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, lwingsbRomInfo, lwingsbRomName, NULL, NULL, DrvInputInfo, LwingsbDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Trojan (US) + +static struct BurnRomInfo trojanRomDesc[] = { + { "t4", 0x8000, 0xc1bbeb4e, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "t6", 0x8000, 0xd49592ef, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tb05.bin", 0x8000, 0x9273b264, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "tb02.bin", 0x8000, 0x21154797, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "tb01.bin", 0x4000, 0x1c0f91b2, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "tb03.bin", 0x4000, 0x581a2b4c, 4 | BRF_GRA }, // 5 Characters + + { "tb13.bin", 0x8000, 0x285a052b, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "tb09.bin", 0x8000, 0xaeb693f7, 5 | BRF_GRA }, // 7 + { "tb12.bin", 0x8000, 0xdfb0fe5c, 5 | BRF_GRA }, // 8 + { "tb08.bin", 0x8000, 0xd3a4c9d1, 5 | BRF_GRA }, // 9 + { "tb11.bin", 0x8000, 0x00f0f4fd, 5 | BRF_GRA }, // 10 + { "tb07.bin", 0x8000, 0xdff2ee02, 5 | BRF_GRA }, // 11 + { "tb14.bin", 0x8000, 0x14bfac18, 5 | BRF_GRA }, // 12 + { "tb10.bin", 0x8000, 0x71ba8a6d, 5 | BRF_GRA }, // 13 + + { "tb18.bin", 0x8000, 0x862c4713, 6 | BRF_GRA }, // 14 Sprites + { "tb16.bin", 0x8000, 0xd86f8cbd, 6 | BRF_GRA }, // 15 + { "tb17.bin", 0x8000, 0x12a73b3f, 6 | BRF_GRA }, // 16 + { "tb15.bin", 0x8000, 0xbb1a2769, 6 | BRF_GRA }, // 17 + { "tb22.bin", 0x8000, 0x39daafd4, 6 | BRF_GRA }, // 18 + { "tb20.bin", 0x8000, 0x94615d2a, 6 | BRF_GRA }, // 19 + { "tb21.bin", 0x8000, 0x66c642bd, 6 | BRF_GRA }, // 20 + { "tb19.bin", 0x8000, 0x81d5ab36, 6 | BRF_GRA }, // 21 + + { "tb25.bin", 0x8000, 0x6e38c6fa, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "tb24.bin", 0x8000, 0x14fc6cf2, 7 | BRF_GRA }, // 23 + + { "tb23.bin", 0x8000, 0xeda13c0e, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbp24s10.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "mb7114e.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(trojan) +STD_ROM_FN(trojan) + +struct BurnDriver BurnDrvTrojan = { + "trojan", NULL, NULL, NULL, "1986", + "Trojan (US)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, trojanRomInfo, trojanRomName, NULL, NULL, DrvInputInfo, TrojanlsDIPInfo, + TrojanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Trojan (Romstar) + +static struct BurnRomInfo trojanrRomDesc[] = { + { "tb04.bin", 0x8000, 0x92670f27, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tb06.bin", 0x8000, 0xa4951173, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tb05.bin", 0x8000, 0x9273b264, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "tb02.bin", 0x8000, 0x21154797, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "tb01.bin", 0x4000, 0x1c0f91b2, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "tb03.bin", 0x4000, 0x581a2b4c, 4 | BRF_GRA }, // 5 Characters + + { "tb13.bin", 0x8000, 0x285a052b, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "tb09.bin", 0x8000, 0xaeb693f7, 5 | BRF_GRA }, // 7 + { "tb12.bin", 0x8000, 0xdfb0fe5c, 5 | BRF_GRA }, // 8 + { "tb08.bin", 0x8000, 0xd3a4c9d1, 5 | BRF_GRA }, // 9 + { "tb11.bin", 0x8000, 0x00f0f4fd, 5 | BRF_GRA }, // 10 + { "tb07.bin", 0x8000, 0xdff2ee02, 5 | BRF_GRA }, // 11 + { "tb14.bin", 0x8000, 0x14bfac18, 5 | BRF_GRA }, // 12 + { "tb10.bin", 0x8000, 0x71ba8a6d, 5 | BRF_GRA }, // 13 + + { "tb18.bin", 0x8000, 0x862c4713, 6 | BRF_GRA }, // 14 Sprites + { "tb16.bin", 0x8000, 0xd86f8cbd, 6 | BRF_GRA }, // 15 + { "tb17.bin", 0x8000, 0x12a73b3f, 6 | BRF_GRA }, // 16 + { "tb15.bin", 0x8000, 0xbb1a2769, 6 | BRF_GRA }, // 17 + { "tb22.bin", 0x8000, 0x39daafd4, 6 | BRF_GRA }, // 18 + { "tb20.bin", 0x8000, 0x94615d2a, 6 | BRF_GRA }, // 19 + { "tb21.bin", 0x8000, 0x66c642bd, 6 | BRF_GRA }, // 20 + { "tb19.bin", 0x8000, 0x81d5ab36, 6 | BRF_GRA }, // 21 + + { "tb25.bin", 0x8000, 0x6e38c6fa, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "tb24.bin", 0x8000, 0x14fc6cf2, 7 | BRF_GRA }, // 23 + + { "tb23.bin", 0x8000, 0xeda13c0e, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbp24s10.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "mb7114e.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(trojanr) +STD_ROM_FN(trojanr) + +struct BurnDriver BurnDrvTrojanr = { + "trojanr", "trojan", NULL, NULL, "1986", + "Trojan (Romstar)\0", NULL, "Capcom (Romstar license)", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, trojanrRomInfo, trojanrRomName, NULL, NULL, DrvInputInfo, TrojanDIPInfo, + TrojanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Tatakai no Banka (Japan) + +static struct BurnRomInfo trojanjRomDesc[] = { + { "troj-04.rom", 0x8000, 0x0b5a7f49, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "troj-06.rom", 0x8000, 0xdee6ed92, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tb05.bin", 0x8000, 0x9273b264, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "tb02.bin", 0x8000, 0x21154797, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "tb01.bin", 0x4000, 0x1c0f91b2, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "tb03.bin", 0x4000, 0x581a2b4c, 4 | BRF_GRA }, // 5 Characters + + { "tb13.bin", 0x8000, 0x285a052b, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "tb09.bin", 0x8000, 0xaeb693f7, 5 | BRF_GRA }, // 7 + { "tb12.bin", 0x8000, 0xdfb0fe5c, 5 | BRF_GRA }, // 8 + { "tb08.bin", 0x8000, 0xd3a4c9d1, 5 | BRF_GRA }, // 9 + { "tb11.bin", 0x8000, 0x00f0f4fd, 5 | BRF_GRA }, // 10 + { "tb07.bin", 0x8000, 0xdff2ee02, 5 | BRF_GRA }, // 11 + { "tb14.bin", 0x8000, 0x14bfac18, 5 | BRF_GRA }, // 12 + { "tb10.bin", 0x8000, 0x71ba8a6d, 5 | BRF_GRA }, // 13 + + { "tb18.bin", 0x8000, 0x862c4713, 6 | BRF_GRA }, // 14 Sprites + { "tb16.bin", 0x8000, 0xd86f8cbd, 6 | BRF_GRA }, // 15 + { "tb17.bin", 0x8000, 0x12a73b3f, 6 | BRF_GRA }, // 16 + { "tb15.bin", 0x8000, 0xbb1a2769, 6 | BRF_GRA }, // 17 + { "tb22.bin", 0x8000, 0x39daafd4, 6 | BRF_GRA }, // 18 + { "tb20.bin", 0x8000, 0x94615d2a, 6 | BRF_GRA }, // 19 + { "tb21.bin", 0x8000, 0x66c642bd, 6 | BRF_GRA }, // 20 + { "tb19.bin", 0x8000, 0x81d5ab36, 6 | BRF_GRA }, // 21 + + { "tb25.bin", 0x8000, 0x6e38c6fa, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "tb24.bin", 0x8000, 0x14fc6cf2, 7 | BRF_GRA }, // 23 + + { "tb23.bin", 0x8000, 0xeda13c0e, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbp24s10.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "mb7114e.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(trojanj) +STD_ROM_FN(trojanj) + +struct BurnDriver BurnDrvTrojanj = { + "trojanj", "trojan", NULL, NULL, "1986", + "Tatakai no Banka (Japan)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM | GBF_SCRFIGHT, 0, + NULL, trojanjRomInfo, trojanjRomName, NULL, NULL, DrvInputInfo, TrojanDIPInfo, + TrojanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 240, 4, 3 +}; + + +// Avengers (US set 1) + +static struct BurnRomInfo avengersRomDesc[] = { + { "04.10n", 0x8000, 0xa94aadcc, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "06.13n", 0x8000, 0x39cd80bd, 1 | BRF_PRG | BRF_ESS }, // 1 + { "05.12n", 0x8000, 0x06b1cec9, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "02.15h", 0x8000, 0x107a2e17, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "01.6d", 0x8000, 0xc1e5d258, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "03.8k", 0x8000, 0xefb5883e, 4 | BRF_GRA }, // 5 Characters + + { "13.6b", 0x8000, 0x9b5ff305, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "09.6a", 0x8000, 0x08323355, 5 | BRF_GRA }, // 7 + { "12.4b", 0x8000, 0x6d5261ba, 5 | BRF_GRA }, // 8 + { "08.4a", 0x8000, 0xa13d9f54, 5 | BRF_GRA }, // 9 + { "11.3b", 0x8000, 0xa2911d8b, 5 | BRF_GRA }, // 10 + { "07.3a", 0x8000, 0xcde78d32, 5 | BRF_GRA }, // 11 + { "14.8b", 0x8000, 0x44ac2671, 5 | BRF_GRA }, // 12 + { "10.8a", 0x8000, 0xb1a717cb, 5 | BRF_GRA }, // 13 + + { "18.7l", 0x8000, 0x3c876a17, 6 | BRF_GRA }, // 14 Sprites + { "16.3l", 0x8000, 0x4b1ff3ac, 6 | BRF_GRA }, // 15 + { "17.5l", 0x8000, 0x4eb543ef, 6 | BRF_GRA }, // 16 + { "15.2l", 0x8000, 0x8041de7f, 6 | BRF_GRA }, // 17 + { "22.7n", 0x8000, 0xbdaa8b22, 6 | BRF_GRA }, // 18 + { "20.3n", 0x8000, 0x566e3059, 6 | BRF_GRA }, // 19 + { "21.5n", 0x8000, 0x301059aa, 6 | BRF_GRA }, // 20 + { "19.2n", 0x8000, 0xa00485ec, 6 | BRF_GRA }, // 21 + + { "25.15n", 0x8000, 0x230d9e30, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "24.13n", 0x8000, 0xa6354024, 7 | BRF_GRA }, // 23 + + { "23.9n", 0x8000, 0xc0a93ef6, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbb_2bpr.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "tbb_1bpr.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(avengers) +STD_ROM_FN(avengers) + +static INT32 AvengersInit() +{ + avengers = 1; + + return TrojanInit(); +} + +struct BurnDriver BurnDrvAvengers = { + "avengers", NULL, NULL, NULL, "1987", + "Avengers (US set 1)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, avengersRomInfo, avengersRomName, NULL, NULL, DrvInputInfo, AvengersDIPInfo, + AvengersInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Avengers (US set 2) + +static struct BurnRomInfo avenger2RomDesc[] = { + { "avg4.bin", 0x8000, 0x0fea7ac5, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "av_06a.13n", 0x8000, 0x491a712c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "av_05.12n", 0x8000, 0x9a214b42, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "02.15h", 0x8000, 0x107a2e17, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "01.6d", 0x8000, 0xc1e5d258, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "03.8k", 0x8000, 0xefb5883e, 4 | BRF_GRA }, // 5 Characters + + { "13.6b", 0x8000, 0x9b5ff305, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "09.6a", 0x8000, 0x08323355, 5 | BRF_GRA }, // 7 + { "12.4b", 0x8000, 0x6d5261ba, 5 | BRF_GRA }, // 8 + { "08.4a", 0x8000, 0xa13d9f54, 5 | BRF_GRA }, // 9 + { "11.3b", 0x8000, 0xa2911d8b, 5 | BRF_GRA }, // 10 + { "07.3a", 0x8000, 0xcde78d32, 5 | BRF_GRA }, // 11 + { "14.8b", 0x8000, 0x44ac2671, 5 | BRF_GRA }, // 12 + { "10.8a", 0x8000, 0xb1a717cb, 5 | BRF_GRA }, // 13 + + { "18.7l", 0x8000, 0x3c876a17, 6 | BRF_GRA }, // 14 Sprites + { "16.3l", 0x8000, 0x4b1ff3ac, 6 | BRF_GRA }, // 15 + { "17.5l", 0x8000, 0x4eb543ef, 6 | BRF_GRA }, // 16 + { "15.2l", 0x8000, 0x8041de7f, 6 | BRF_GRA }, // 17 + { "22.7n", 0x8000, 0xbdaa8b22, 6 | BRF_GRA }, // 18 + { "20.3n", 0x8000, 0x566e3059, 6 | BRF_GRA }, // 19 + { "21.5n", 0x8000, 0x301059aa, 6 | BRF_GRA }, // 20 + { "19.2n", 0x8000, 0xa00485ec, 6 | BRF_GRA }, // 21 + + { "25.15n", 0x8000, 0x230d9e30, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "24.13n", 0x8000, 0xa6354024, 7 | BRF_GRA }, // 23 + + { "23.9n", 0x8000, 0xc0a93ef6, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbb_2bpr.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "tbb_1bpr.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(avenger2) +STD_ROM_FN(avenger2) + +struct BurnDriver BurnDrvAvenger2 = { + "avengers2", "avengers", NULL, NULL, "1987", + "Avengers (US set 2)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, avenger2RomInfo, avenger2RomName, NULL, NULL, DrvInputInfo, AvengersDIPInfo, + AvengersInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; + + +// Hissatsu Buraiken (Japan) + +static struct BurnRomInfo buraikenRomDesc[] = { + { "av_04a.10n", 0x8000, 0x361fc614, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "av_06a.13n", 0x8000, 0x491a712c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "av_05.12n", 0x8000, 0x9a214b42, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "02.15h", 0x8000, 0x107a2e17, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "01.6d", 0x8000, 0xc1e5d258, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "03.8k", 0x8000, 0xefb5883e, 4 | BRF_GRA }, // 5 Characters + + { "13.6b", 0x8000, 0x9b5ff305, 5 | BRF_GRA }, // 6 Background Layer 1 Tiles + { "09.6a", 0x8000, 0x08323355, 5 | BRF_GRA }, // 7 + { "12.4b", 0x8000, 0x6d5261ba, 5 | BRF_GRA }, // 8 + { "08.4a", 0x8000, 0xa13d9f54, 5 | BRF_GRA }, // 9 + { "11.3b", 0x8000, 0xa2911d8b, 5 | BRF_GRA }, // 10 + { "07.3a", 0x8000, 0xcde78d32, 5 | BRF_GRA }, // 11 + { "14.8b", 0x8000, 0x44ac2671, 5 | BRF_GRA }, // 12 + { "10.8a", 0x8000, 0xb1a717cb, 5 | BRF_GRA }, // 13 + + { "18.7l", 0x8000, 0x3c876a17, 6 | BRF_GRA }, // 14 Sprites + { "16.3l", 0x8000, 0x4b1ff3ac, 6 | BRF_GRA }, // 15 + { "17.5l", 0x8000, 0x4eb543ef, 6 | BRF_GRA }, // 16 + { "15.2l", 0x8000, 0x8041de7f, 6 | BRF_GRA }, // 17 + { "22.7n", 0x8000, 0xbdaa8b22, 6 | BRF_GRA }, // 18 + { "20.3n", 0x8000, 0x566e3059, 6 | BRF_GRA }, // 19 + { "21.5n", 0x8000, 0x301059aa, 6 | BRF_GRA }, // 20 + { "19.2n", 0x8000, 0xa00485ec, 6 | BRF_GRA }, // 21 + + { "av_25.15n", 0x8000, 0x88a505a7, 7 | BRF_GRA }, // 22 Background Layer 2 Tiles + { "av_24.13n", 0x8000, 0x1f4463c8, 7 | BRF_GRA }, // 23 + + { "23.9n", 0x8000, 0xc0a93ef6, 8 | BRF_GRA }, // 24 Background Layer 2 Tile Map + + { "tbb_2bpr.7j", 0x0100, 0xd96bcc98, 0 | BRF_OPT }, // 25 Proms (not used) + { "tbb_1bpr.1e", 0x0100, 0x5052fa9d, 0 | BRF_OPT }, // 26 +}; + +STD_ROM_PICK(buraiken) +STD_ROM_FN(buraiken) + +struct BurnDriver BurnDrvBuraiken = { + "buraiken", "avengers", NULL, NULL, "1987", + "Hissatsu Buraiken (Japan)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, buraikenRomInfo, buraikenRomName, NULL, NULL, DrvInputInfo, AvengersDIPInfo, + AvengersInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_madgear.cpp b/src/burn/drivers/misc_pre90s/d_madgear.cpp new file mode 100644 index 00000000..e68fe63d --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_madgear.cpp @@ -0,0 +1,1934 @@ +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[3] = {0, 0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Drv68KRom = NULL; +static UINT8 *Drv68KRam = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvSpriteRamBuffer = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvScroll1Ram = NULL; +static UINT8 *DrvScroll2Ram = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvBgTiles = NULL; +static UINT8 *DrvFgTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT16 DrvFgScrollX; +static UINT16 DrvFgScrollY; +static UINT16 DrvBgScrollX; +static UINT16 DrvBgScrollY; +static UINT8 DrvSpritePriMask; +static UINT8 DrvSpriteFlipYMask; +static UINT8 DrvZ80RomBank; +static UINT8 DrvSoundLatch; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 fire 1" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo LastduelInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort2 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 5, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort2 + 3, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Lastduel) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[0]); + DrvClearOpposites(&DrvInput[1]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Allow continue" }, + {0x11, 0x01, 0x01, 0x00, "No" }, + {0x11, 0x01, 0x01, 0x01, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x0c, 0x08, "Easy" }, + {0x11, 0x01, 0x0c, 0x0c, "Normal" }, + {0x11, 0x01, 0x0c, 0x04, "Difficult" }, + {0x11, 0x01, 0x0c, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x11, 0x01, 0x30, 0x30, "Upright (One Player)" }, + {0x11, 0x01, 0x30, 0x00, "Upright (Two Players)" }, + {0x11, 0x01, 0x30, 0x10, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Background Music" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, + + // Dip3 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x12, 0x01, 0xf0, 0x20, "6 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x40, "5 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x50, "4 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x70, "3 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x10, "8 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0x90, "2 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x30, "5 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0x60, "3 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x12, 0x01, 0xf0, 0x80, "2 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Plays" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Plays" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Plays" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Plays" }, + {0x12, 0x01, 0xf0, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x12, 0x01, 0x0f, 0x02, "6 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x04, "5 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x05, "4 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x07, "3 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x01, "8 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x09, "2 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x03, "5 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x06, "3 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x12, 0x01, 0x0f, 0x08, "2 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Plays" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo LastduelDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "4 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x08, "3 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x10, "2 Coins 1 Play" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 6 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Difficult" }, + {0x14, 0x01, 0x03, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x20, "20000, 60000, 80000" }, + {0x14, 0x01, 0x30, 0x30, "30000, 80000, 80000" }, + {0x14, 0x01, 0x30, 0x10, "40000, 80000, 80000" }, + {0x14, 0x01, 0x30, 0x00, "40000, 80000, 100000" }, + + // Dip3 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x03, 0x03, "3" }, + {0x15, 0x01, 0x03, 0x02, "4" }, + {0x15, 0x01, 0x03, 0x01, "6" }, + {0x15, 0x01, 0x03, 0x00, "8" }, + + {0 , 0xfe, 0 , 2 , "Type" }, + {0x15, 0x01, 0x04, 0x04, "Car" }, + {0x15, 0x01, 0x04, 0x00, "Plane" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow continue" }, + {0x15, 0x01, 0x40, 0x00, "No" }, + {0x15, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + +}; + +STDDIPINFO(Lastduel) + +static struct BurnRomInfo DrvRomDesc[] = { + { "mg_04.8b", 0x20000, 0xb112257d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mg_03.7b", 0x20000, 0xb2672465, BRF_ESS | BRF_PRG }, // 1 + { "mg_02.6b", 0x20000, 0x9f5ebe16, BRF_ESS | BRF_PRG }, // 2 + { "mg_01.5b", 0x20000, 0x1cea2af0, BRF_ESS | BRF_PRG }, // 3 + + { "mg_05.14j", 0x10000, 0x2fbfc945, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "mg_06.10k", 0x08000, 0x382ee59b, BRF_GRA }, // 5 Characters + + { "ls-12.7l", 0x40000, 0x6c1b2c6c, BRF_GRA }, // 6 BG Tiles + + { "ls-11.2l", 0x80000, 0x6bf81c64, BRF_GRA }, // 7 FG Tiles + + { "mg_m11.rom0", 0x10000, 0xee319a64, BRF_GRA }, // 8 Sprites + { "mg_m07.rom2", 0x10000, 0xe5c0b211, BRF_GRA }, // 9 + { "mg_m12.rom1", 0x10000, 0x887ef120, BRF_GRA }, // 10 + { "mg_m08.rom3", 0x10000, 0x59709aa3, BRF_GRA }, // 11 + { "mg_m13.rom0", 0x10000, 0xeae07db4, BRF_GRA }, // 12 + { "mg_m09.rom2", 0x10000, 0x40ee83eb, BRF_GRA }, // 13 + { "mg_m14.rom1", 0x10000, 0x21e5424c, BRF_GRA }, // 14 + { "mg_m10.rom3", 0x10000, 0xb64afb54, BRF_GRA }, // 15 + + { "ls-06.10e", 0x20000, 0x88d39a5b, BRF_SND }, // 16 Samples + { "ls-05.12e", 0x20000, 0xb06e03b5, BRF_SND }, // 17 + + { "29.14k", 0x00100, 0x7f862e1e, BRF_GRA }, // 18 PROM (Priority) +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "mdj_04.8b", 0x20000, 0x9ebbebb1, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mdj_03.7b", 0x20000, 0xa5579c2d, BRF_ESS | BRF_PRG }, // 1 + { "mg_02.6b", 0x20000, 0x9f5ebe16, BRF_ESS | BRF_PRG }, // 2 + { "mg_01.5b", 0x20000, 0x1cea2af0, BRF_ESS | BRF_PRG }, // 3 + + { "mg_05.14j", 0x10000, 0x2fbfc945, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "mg_06.10k", 0x08000, 0x382ee59b, BRF_GRA }, // 5 Characters + + { "ls-12.7l", 0x40000, 0x6c1b2c6c, BRF_GRA }, // 6 BG Tiles + + { "ls-11.2l", 0x80000, 0x6bf81c64, BRF_GRA }, // 7 FG Tiles + + { "mg_m11.rom0", 0x10000, 0xee319a64, BRF_GRA }, // 8 Sprites + { "mg_m07.rom2", 0x10000, 0xe5c0b211, BRF_GRA }, // 9 + { "mg_m12.rom1", 0x10000, 0x887ef120, BRF_GRA }, // 10 + { "mg_m08.rom3", 0x10000, 0x59709aa3, BRF_GRA }, // 11 + { "mg_m13.rom0", 0x10000, 0xeae07db4, BRF_GRA }, // 12 + { "mg_m09.rom2", 0x10000, 0x40ee83eb, BRF_GRA }, // 13 + { "mg_m14.rom1", 0x10000, 0x21e5424c, BRF_GRA }, // 14 + { "mg_m10.rom3", 0x10000, 0xb64afb54, BRF_GRA }, // 15 + + { "ls-06.10e", 0x20000, 0x88d39a5b, BRF_SND }, // 16 Samples + { "ls-05.12e", 0x20000, 0xb06e03b5, BRF_SND }, // 17 + + { "29.14k", 0x00100, 0x7f862e1e, BRF_GRA }, // 18 PROM (Priority) +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo DrvuRomDesc[] = { + { "mdu_04.8b", 0x20000, 0x7f7f8329, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "mdu_03.7b", 0x20000, 0x11fa542f, BRF_ESS | BRF_PRG }, // 1 + { "mde_02.6b", 0x20000, 0x9f5ebe16, BRF_ESS | BRF_PRG }, // 2 + { "mde_01.5b", 0x20000, 0x1cea2af0, BRF_ESS | BRF_PRG }, // 3 + + { "mde_05.14j", 0x10000, 0x2fbfc945, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "mdu_06.10k", 0x08000, 0x54bfdc02, BRF_GRA }, // 5 Characters + + { "ls-12.7l", 0x40000, 0x6c1b2c6c, BRF_GRA }, // 6 BG Tiles + + { "ls-11.2l", 0x80000, 0x6bf81c64, BRF_GRA }, // 7 FG Tiles + + { "11.rom0", 0x10000, 0xee319a64, BRF_GRA }, // 8 Sprites + { "07u.rom2", 0x10000, 0x7152b212, BRF_GRA }, // 9 + { "12.rom1", 0x10000, 0x887ef120, BRF_GRA }, // 10 + { "08u.rom3", 0x10000, 0x72e5d525, BRF_GRA }, // 11 + { "13.rom0", 0x10000, 0xeae07db4, BRF_GRA }, // 12 + { "09u.rom2", 0x10000, 0x7b5175cb, BRF_GRA }, // 13 + { "14.rom1", 0x10000, 0x21e5424c, BRF_GRA }, // 14 + { "10u.rom3", 0x10000, 0x6db7ca64, BRF_GRA }, // 15 + + { "ls-06.10e", 0x20000, 0x88d39a5b, BRF_SND }, // 16 Samples + { "ls-05.12e", 0x20000, 0xb06e03b5, BRF_SND }, // 17 + + { "29.14k", 0x00100, 0x7f862e1e, BRF_GRA }, // 18 PROM (Priority) +}; + +STD_ROM_PICK(Drvu) +STD_ROM_FN(Drvu) + +static struct BurnRomInfo Ledstrm2RomDesc[] = { + { "lsu-04.8b", 0x20000, 0x56a2f079, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "lsu-03.7b", 0x20000, 0x9b6408c0, BRF_ESS | BRF_PRG }, // 1 + { "ls-02.6b", 0x20000, 0x05c0285e, BRF_ESS | BRF_PRG }, // 2 + { "ls-01.5b", 0x20000, 0x8bf934dd, BRF_ESS | BRF_PRG }, // 3 + + { "ls-07.14j", 0x10000, 0x98af7838, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "ls-08.10k", 0x08000, 0x8803cf49, BRF_GRA }, // 5 Characters + + { "ls-12.7l", 0x40000, 0x6c1b2c6c, BRF_GRA }, // 6 BG Tiles + + { "ls-11.2l", 0x80000, 0x6bf81c64, BRF_GRA }, // 7 FG Tiles + + { "ls-09.5a", 0x40000, 0x80875e1d, BRF_GRA }, // 8 Sprites + { "ls-10.13a", 0x40000, 0xc5993f93, BRF_GRA }, // 9 + + { "ls-06.10e", 0x20000, 0x88d39a5b, BRF_SND }, // 10 Samples + { "ls-05.12e", 0x20000, 0xb06e03b5, BRF_SND }, // 11 + + { "29.14k", 0x00100, 0x7f862e1e, BRF_GRA }, // 12 PROM (Priority) +}; + +STD_ROM_PICK(Ledstrm2) +STD_ROM_FN(Ledstrm2) + +static struct BurnRomInfo LastduelRomDesc[] = { + { "ldu_06b.13k", 0x20000, 0x0e71acaf, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ldu_05b.12k", 0x20000, 0x47a85bea, BRF_ESS | BRF_PRG }, // 1 + { "ldu_04b.11k", 0x10000, 0xaa4bf001, BRF_ESS | BRF_PRG }, // 2 + { "ldu_03b.9k", 0x10000, 0xbbaac8ab, BRF_ESS | BRF_PRG }, // 3 + + { "ld_02.16h", 0x10000, 0x91834d0c, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "ld_01.12f", 0x08000, 0xad3c6f87, BRF_GRA }, // 5 Characters + + { "ld-15.6p", 0x20000, 0xd977a175, BRF_GRA }, // 6 BG Tiles + { "ld-13.6m", 0x20000, 0xbc25729f, BRF_GRA }, // 7 + + { "ld-14.15n", 0x80000, 0xd0653739, BRF_GRA }, // 8 FG Tiles + + { "ld-11.12b", 0x20000, 0x49d4dbbd, BRF_GRA }, // 9 Sprites + { "ld-09.12a", 0x20000, 0x6efadb74, BRF_GRA }, // 10 + { "ld-12.17b", 0x20000, 0x313e5338, BRF_GRA }, // 11 + { "ld-10.17a", 0x20000, 0xb8d3b2e3, BRF_GRA }, // 12 + + { "ld.3d", 0x00100, 0x729a1ddc, BRF_GRA }, // 13 PROM (Priority) +}; + +STD_ROM_PICK(Lastduel) +STD_ROM_FN(Lastduel) + +static struct BurnRomInfo LastdueloRomDesc[] = { + { "ldu_06.13k", 0x20000, 0x4228a00b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ldu_05.12k", 0x20000, 0x7260434f, BRF_ESS | BRF_PRG }, // 1 + { "ldu_04.11k", 0x10000, 0x429fb964, BRF_ESS | BRF_PRG }, // 2 + { "ldu_03.9k", 0x10000, 0x5aa4df72, BRF_ESS | BRF_PRG }, // 3 + + { "ld_02.16h", 0x10000, 0x91834d0c, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "ld_01.12f", 0x08000, 0xad3c6f87, BRF_GRA }, // 5 Characters + + { "ld-15.6p", 0x20000, 0xd977a175, BRF_GRA }, // 6 BG Tiles + { "ld-13.6m", 0x20000, 0xbc25729f, BRF_GRA }, // 7 + + { "ld-14.15n", 0x80000, 0xd0653739, BRF_GRA }, // 8 FG Tiles + + { "ld-11.12b", 0x20000, 0x49d4dbbd, BRF_GRA }, // 9 Sprites + { "ld-09.12a", 0x20000, 0x6efadb74, BRF_GRA }, // 10 + { "ld-12.17b", 0x20000, 0x313e5338, BRF_GRA }, // 11 + { "ld-10.17a", 0x20000, 0xb8d3b2e3, BRF_GRA }, // 12 + + { "ld.3d", 0x00100, 0x729a1ddc, BRF_GRA }, // 13 PROM (Priority) +}; + +STD_ROM_PICK(Lastduelo) +STD_ROM_FN(Lastduelo) + +static struct BurnRomInfo LastdueljRomDesc[] = { + { "ld_06.13k", 0x20000, 0x58a9e12b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ld_05.12k", 0x20000, 0x14685d78, BRF_ESS | BRF_PRG }, // 1 + { "ld_04.11k", 0x10000, 0xaa4bf001, BRF_ESS | BRF_PRG }, // 2 + { "ld_03.9k", 0x10000, 0xbbaac8ab, BRF_ESS | BRF_PRG }, // 3 + + { "ld_02.16h", 0x10000, 0x91834d0c, BRF_ESS | BRF_PRG }, // 4 Z80 Program + + { "ld_01.12f", 0x08000, 0xad3c6f87, BRF_GRA }, // 5 Characters + + { "ld-15.6p", 0x20000, 0xd977a175, BRF_GRA }, // 6 BG Tiles + { "ld-13.6m", 0x20000, 0xbc25729f, BRF_GRA }, // 7 + + { "ld-14.15n", 0x80000, 0xd0653739, BRF_GRA }, // 8 FG Tiles + + { "ld-11.12b", 0x20000, 0x49d4dbbd, BRF_GRA }, // 9 Sprites + { "ld-09.12a", 0x20000, 0x6efadb74, BRF_GRA }, // 10 + { "ld-12.17b", 0x20000, 0x313e5338, BRF_GRA }, // 11 + { "ld-10.17a", 0x20000, 0xb8d3b2e3, BRF_GRA }, // 12 + + { "ld.3d", 0x00100, 0x729a1ddc, BRF_GRA }, // 13 PROM (Priority) +}; + +STD_ROM_PICK(Lastduelj) +STD_ROM_FN(Lastduelj) + +static struct BurnRomInfo LastduelbRomDesc[] = { + { "ld_08.bin", 0x10000, 0x43811a96, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "ld_07.bin", 0x10000, 0x63c30946, BRF_ESS | BRF_PRG }, // 1 + { "ld_04.bin", 0x10000, 0x46a4e0f8, BRF_ESS | BRF_PRG }, // 2 + { "ld_03.bin", 0x10000, 0x8d5f204a, BRF_ESS | BRF_PRG }, // 3 + { "ldu-04.rom", 0x10000, 0x429fb964, BRF_ESS | BRF_PRG }, // 4 + { "ldu-03.rom", 0x10000, 0x5aa4df72, BRF_ESS | BRF_PRG }, // 5 + + { "ld_02.bin", 0x10000, 0x91834d0c, BRF_ESS | BRF_PRG }, // 6 Z80 Program + + { "ld_01.bin", 0x08000, 0xad3c6f87, BRF_GRA }, // 7 Characters + + { "ld_17.bin", 0x10000, 0x7188bfdd, BRF_GRA }, // 8 BG Tiles + { "ld_18.bin", 0x10000, 0xa62af66a, BRF_GRA }, // 9 + { "ld_19.bin", 0x10000, 0x4b762e50, BRF_GRA }, // 10 + { "ld_20.bin", 0x10000, 0xb140188e, BRF_GRA }, // 11 + + { "ld_28.bin", 0x10000, 0x06778248, BRF_GRA }, // 12 FG Tiles + { "ld_27.bin", 0x10000, 0x48c78675, BRF_GRA }, // 13 + { "ld_26.bin", 0x10000, 0xb0edac81, BRF_GRA }, // 14 + { "ld_25.bin", 0x10000, 0xc541ae9a, BRF_GRA }, // 15 + { "ld_24.bin", 0x10000, 0x66eac4df, BRF_GRA }, // 16 + { "ld_23.bin", 0x10000, 0xd817332c, BRF_GRA }, // 17 + { "ld_22.bin", 0x10000, 0xf80f8812, BRF_GRA }, // 18 + { "ld_21.bin", 0x10000, 0xb74f0c0e, BRF_GRA }, // 19 + + { "ld_09.bin", 0x10000, 0xf8fd5243, BRF_GRA }, // 20 Sprites + { "ld_10.bin", 0x10000, 0xb49ad746, BRF_GRA }, // 21 + { "ld_11.bin", 0x10000, 0x1a0d180e, BRF_GRA }, // 22 + { "ld_12.bin", 0x10000, 0xb2745e26, BRF_GRA }, // 23 + { "ld_15.bin", 0x10000, 0x96b13bbc, BRF_GRA }, // 24 + { "ld_16.bin", 0x10000, 0x9d80f7e6, BRF_GRA }, // 25 + { "ld_13.bin", 0x10000, 0xa1a598ac, BRF_GRA }, // 26 + { "ld_14.bin", 0x10000, 0xedf515cc, BRF_GRA }, // 27 + + { "ld.3d", 0x00100, 0x729a1ddc, BRF_GRA }, // 28 PROM (Priority) +}; + +STD_ROM_PICK(Lastduelb) +STD_ROM_FN(Lastduelb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x80000; + DrvZ80Rom = Next; Next += 0x10000; + MSM6295ROM = Next; Next += 0x40000; + + RamStart = Next; + + Drv68KRam = Next; Next += 0x20000; + DrvZ80Ram = Next; Next += 0x00800; + DrvSpriteRam = Next; Next += 0x00800; + DrvSpriteRamBuffer = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x02000; + DrvPaletteRam = Next; Next += 0x00800; + DrvScroll1Ram = Next; Next += 0x04000; + DrvScroll2Ram = Next; Next += 0x08000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0800 * 8 * 8; + DrvBgTiles = Next; Next += 0x0800 * 16 * 16; + DrvFgTiles = Next; Next += 0x1000 * 16 * 16; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + DrvFgScrollX = 0; + DrvFgScrollY = 0; + DrvBgScrollX = 0; + DrvBgScrollY = 0; + DrvZ80RomBank = 0; + DrvSoundLatch = 0; + + return 0; +} + +static INT32 MadgearDoReset() +{ + DrvDoReset(); + + MSM6295Reset(0); + + return 0; +} + +UINT8 __fastcall Madgear68KReadByte(UINT32 a) +{ + switch (a) { + case 0xfc4000: { + return DrvDip[0]; + } + + case 0xfc4001: { + return DrvDip[1]; + } + + case 0xfc4002: { + return DrvDip[2]; + } + + case 0xfc4004: { + return 0xff - DrvInput[0]; + } + + case 0xfc4005: { + return 0xff - DrvInput[1]; + } + + case 0xfc4006: { + return 0xff - DrvInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Madgear68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xfc4000: { + // flip + return; + } + + case 0xfc4002: { + DrvSoundLatch = d & 0xff; + return; + } + + case 0xfd0000: { + DrvFgScrollY = d & 0x1ff; + return; + } + + case 0xfd0002: { + DrvFgScrollX = d & 0x3ff; + return; + } + + case 0xfd0004: { + DrvBgScrollY = d & 0x1ff; + return; + } + + case 0xfd0006: { + DrvBgScrollX = d & 0x3ff; + return; + } + + case 0xfd0008: + case 0xfd000e: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall MadgearZ80Read(UINT16 a) +{ + switch (a) { + case 0xf000: { + return BurnYM2203Read(0, 0); + } + + case 0xf002: { + return BurnYM2203Read(1, 0); + } + + case 0xf006: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall MadgearZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xf000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xf001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xf002: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xf003: { + BurnYM2203Write(1, 1, d); + return; + } + + case 0xf004: { + MSM6295Command(0, d); + return; + } + + case 0xf00a: { + DrvZ80RomBank = d & 1; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x8000 + DrvZ80RomBank * 0x4000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x8000 + DrvZ80RomBank * 0x4000 ); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +void __fastcall Lastduel68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xfc4001: { + // flip + return; + } + + case 0xfc4003: { + DrvSoundLatch = d & 0xff; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Lastduel68KReadWord(UINT32 a) +{ + switch (a) { + case 0xfc4000: { + return 0xffff - ((DrvInput[1] << 8) | DrvInput[0]); + } + + case 0xfc4002: { + return 0xffff - DrvInput[2]; + } + + case 0xfc4004: { + return (DrvDip[1] << 8) | DrvDip[0]; + } + + case 0xfc4006: { + return DrvDip[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read Word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Lastduel68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xfc0000: + case 0xfc0002: { + // NOP + return; + } + + case 0xfc8000: { + DrvFgScrollY = d & 0x1ff; + return; + } + + case 0xfc8002: { + DrvFgScrollX = d & 0x3ff; + return; + } + + case 0xfc8004: { + DrvBgScrollY = d & 0x1ff; + return; + } + + case 0xfc8006: { + DrvBgScrollX = d & 0x3ff; + return; + } + + case 0xfc8008: + case 0xfc800e: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall LastduelZ80Read(UINT16 a) +{ + switch (a) { + case 0xe800: { + return BurnYM2203Read(0, 0); + } + + case 0xf000: { + return BurnYM2203Read(1, 0); + } + + case 0xf800: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall LastduelZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe800: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xe801: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xf000: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xf001: { + BurnYM2203Write(1, 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +inline static void DrvYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3579545; +} + +static INT32 CharPlaneOffsets[2] = { 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 BgTilePlaneOffsets[4] = { 12, 8, 4, 0 }; +static INT32 FgTilePlaneOffsets[4] = { 4, 12, 0, 8 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 16, 17, 18, 19, 512, 513, 514, 515, 528, 529, 530, 531 }; +static INT32 TileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 }; +static INT32 SpritePlaneOffsets[4] = { 0, 0x100000, 0x200000, 0x300000 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvBgTiles); + + // Load and decode the fg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, FgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvFgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 15, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x20000, 17, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0xfc1800, 0xfc1fff, SM_RAM); + SekMapMemory(DrvVideoRam , 0xfc8000, 0xfc9fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0xfcc000, 0xfcc7ff, SM_RAM); + SekMapMemory(DrvScroll1Ram , 0xfd4000, 0xfd7fff, SM_RAM); + SekMapMemory(DrvScroll2Ram , 0xfd8000, 0xfdffff, SM_RAM); + SekMapMemory(Drv68KRam , 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, Madgear68KWriteWord); + SekSetReadByteHandler(0, Madgear68KReadByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(MadgearZ80Read); + ZetSetWriteHandler(MadgearZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x8000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x8000 ); + ZetMapArea(0xd000, 0xd7ff, 0, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 1, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + DrvSpritePriMask = 0x10; + DrvSpriteFlipYMask = 0x80; + + BurnYM2203Init(2, 3579545, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(3); + BurnTimerAttachZet(3579545); + + MSM6295Init(0, 7575, 98, 1); + + // Reset the driver + MadgearDoReset(); + + return 0; +} + +static INT32 Ledstrm2Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvBgTiles); + + // Load and decode the fg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, FgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvFgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + // Load the samples + nRet = BurnLoadRom(MSM6295ROM + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(MSM6295ROM + 0x20000, 11, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0xfc1800, 0xfc1fff, SM_RAM); + SekMapMemory(DrvVideoRam , 0xfc8000, 0xfc9fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0xfcc000, 0xfcc7ff, SM_RAM); + SekMapMemory(DrvScroll1Ram , 0xfd4000, 0xfd7fff, SM_RAM); + SekMapMemory(DrvScroll2Ram , 0xfd8000, 0xfdffff, SM_RAM); + SekMapMemory(Drv68KRam , 0xff0000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, Madgear68KWriteWord); + SekSetReadByteHandler(0, Madgear68KReadByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(MadgearZ80Read); + ZetSetWriteHandler(MadgearZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x8000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x8000 ); + ZetMapArea(0xd000, 0xd7ff, 0, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 1, DrvZ80Ram ); + ZetMapArea(0xd000, 0xd7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + DrvSpritePriMask = 0x10; + DrvSpriteFlipYMask = 0x80; + + BurnYM2203Init(2, 3579545, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(3); + BurnTimerAttachZet(3579545); + + MSM6295Init(0, 7575, 98, 1); + + // Reset the driver + MadgearDoReset(); + + return 0; +} + +static INT32 LastduelInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 3, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(DrvZ80Rom, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00001, 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 2); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvBgTiles); + + // Load and decode the fg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvFgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0xfc0800, 0xfc0fff, SM_RAM); + SekMapMemory(DrvVideoRam , 0xfcc000, 0xfcdfff, SM_RAM); + SekMapMemory(DrvScroll1Ram , 0xfd0000, 0xfd3fff, SM_RAM); + SekMapMemory(DrvScroll2Ram , 0xfd4000, 0xfd7fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0xfd8000, 0xfd87ff, SM_RAM); + SekMapMemory(Drv68KRam , 0xfe0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, Lastduel68KReadWord); + SekSetWriteWordHandler(0, Lastduel68KWriteWord); + SekSetWriteByteHandler(0, Lastduel68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(LastduelZ80Read); + ZetSetWriteHandler(LastduelZ80Write); + ZetMapArea(0x0000, 0xdfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xdfff, 2, DrvZ80Rom ); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + DrvSpritePriMask = 0x00; + DrvSpriteFlipYMask = 0x40; + + BurnYM2203Init(2, 3579545, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(3); + BurnTimerAttachZet(3579545); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 LastduelbInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load 68000 Program Roms + nRet = BurnLoadRom(Drv68KRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x00000, 1, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20001, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x20000, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40001, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(Drv68KRom + 0x40000, 5, 2); if (nRet != 0) return 1; + + // Load Z80 Program Rom + nRet = BurnLoadRom(DrvZ80Rom, 6, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00001, 8, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20001, 9, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 11, 2); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvBgTiles); + + // Load and decode the fg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00001, 12, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20001, 14, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 15, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40001, 16, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 17, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60001, 18, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 19, 2); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, BgTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, DrvTempRom, DrvFgTiles); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 24, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 25, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 26, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 27, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(DrvSpriteRam , 0xfc0800, 0xfc0fff, SM_RAM); + SekMapMemory(DrvVideoRam , 0xfcc000, 0xfcdfff, SM_RAM); + SekMapMemory(DrvScroll1Ram , 0xfd0000, 0xfd3fff, SM_RAM); + SekMapMemory(DrvScroll2Ram , 0xfd4000, 0xfd7fff, SM_RAM); + SekMapMemory(DrvPaletteRam , 0xfd8000, 0xfd87ff, SM_RAM); + SekMapMemory(Drv68KRam , 0xfe0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, Lastduel68KReadWord); + SekSetWriteWordHandler(0, Lastduel68KWriteWord); + SekSetWriteByteHandler(0, Lastduel68KWriteByte); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(LastduelZ80Read); + ZetSetWriteHandler(LastduelZ80Write); + ZetMapArea(0x0000, 0xdfff, 0, DrvZ80Rom ); + ZetMapArea(0x0000, 0xdfff, 2, DrvZ80Rom ); + ZetMapArea(0xe000, 0xe7ff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xe7ff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + DrvSpritePriMask = 0x00; + DrvSpriteFlipYMask = 0x40; + + BurnYM2203Init(2, 3579545, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(3); + BurnTimerAttachZet(3579545); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + SekExit(); + ZetExit(); + + BurnYM2203Exit(); + + GenericTilesExit(); + + DrvFgScrollX = 0; + DrvFgScrollY = 0; + DrvBgScrollX = 0; + DrvBgScrollY = 0; + DrvSpritePriMask = 0; + DrvSpriteFlipYMask = 0; + DrvZ80RomBank = 0; + DrvSoundLatch = 0; + + BurnFree(Mem); + + return 0; +} + +static INT32 MadgearExit() +{ + MSM6295Exit(0); + return DrvExit(); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + static const UINT8 ztable[16] = { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 }; + INT32 i, r, g, b; + + i = ztable[(nColour >> 0) & 15]; + r = ((nColour >> 12) & 15) * i; + g = ((nColour >> 8) & 15) * i; + b = ((nColour >> 4) & 15) * i; + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)DrvScroll2Ram; + + for (mx = 0; mx < 32; mx++) { + for (my = 0; my < 64; my++) { + TileIndex = (my * 32) + mx; + Code = VideoRam[TileIndex] & 0x1fff; + Colour = VideoRam[TileIndex + 0x800]; + Flip = (Colour & 0x60) >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + Colour &= 0x0f; + + y = 16 * mx; + x = 16 * my; + + x -= DrvBgScrollX; + y -= DrvBgScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 512; + x -= 64; + y -= 8; + + if (x > 16 && x < 368 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } + } + } + } +} + +static void DrvRenderFgLayer(INT32 Priority) +{ + INT32 mx, my, Code, Colour, x, y, TileIndex, Split, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)DrvScroll1Ram; + + for (mx = 0; mx < 32; mx++) { + for (my = 0; my < 64; my++) { + TileIndex = (my * 32) + mx; + Code = VideoRam[TileIndex] & 0x1fff; + Colour = VideoRam[TileIndex + 0x800]; + Flip = (Colour & 0x60) >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + Split = (Colour & 0x10) >> 4; + Colour &= 0x0f; + + if (Split != Priority) continue; + + y = 16 * mx; + x = 16 * my; + + x -= DrvFgScrollX; + y -= DrvFgScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 512; + x -= 64; + y -= 8; + + if (x > 16 && x < 368 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0x0f, 0x100, DrvFgTiles); + } + } + } + } + } +} + +static void LastduelRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)DrvScroll2Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[2 * TileIndex] & 0x1fff; + Colour = VideoRam[2 * TileIndex + 1]; + Flip = (Colour & 0x60) >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + Colour &= 0x0f; + + x = 16 * mx; + y = 16 * my; + + x -= DrvBgScrollX; + y -= DrvBgScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 1024; + x -= 64; + y -= 8; + + if (x > 16 && x < 368 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 0, DrvBgTiles); + } + } + } + + TileIndex++; + } + } +} + +static void LastduelRenderFgLayer(INT32 Priority) +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, Split, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)DrvScroll1Ram; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Code = VideoRam[2 * TileIndex] & 0x1fff; + Colour = VideoRam[2 * TileIndex + 1]; + Flip = (Colour & 0x60) >> 5; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + Split = (Colour & 0x80) >> 7; + Colour &= 0x0f; + + if (Split != Priority) continue; + + x = 16 * mx; + y = 16 * my; + + x -= DrvFgScrollX; + y -= DrvFgScrollY; + if (x < -16) x += 1024; + if (y < -16) y += 1024; + x -= 64; + y -= 8; + + if (x > 16 && x < 368 && y > 16 && y < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0x100, DrvFgTiles); + } + } + } + + TileIndex++; + } + } +} + +static void DrvRenderSprites(INT32 Priority) +{ + INT32 Offset; + UINT16 *SpriteRam = (UINT16*)DrvSpriteRamBuffer; + + for (Offset = 0x400 - 4; Offset >= 0; Offset -= 4) { + INT32 Attr, sy, sx, xFlip, yFlip, Code, Colour; + + Attr = SpriteRam[Offset + 1]; + if (DrvSpritePriMask) { + if (Priority == 1 && (Attr & DrvSpritePriMask)) continue; + if (Priority == 0 && !(Attr & DrvSpritePriMask)) continue; + } + + Code = SpriteRam[Offset] & 0xfff; + sx = SpriteRam[Offset + 3] & 0x1ff; + sy = SpriteRam[Offset + 2] & 0x1ff; + if (sy > 0x100) sy -= 0x200; + + xFlip = Attr & 0x20; + yFlip = Attr & DrvSpriteFlipYMask; + Colour = Attr & 0x0f; + + sx -= 64; + sy -= 8; + + if (sx > 16 && sx < 368 && sy > 16 && sy < 224) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0x0f, 0x200, DrvSprites); + } + } + } + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, yFlip, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)DrvVideoRam; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + yFlip = 0; + Code = VideoRam[TileIndex]; + Colour = Code >> 12; + if (Code & 0x800) yFlip = 1; + Code &= 0x7ff; + + x = 8 * mx; + y = 8 * my; + + x -= 64; + y -= 8; + + if (x > 0 && x < 376 && y > 8 && y < 232) { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 2, 3, 0x300, DrvChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 3, 0x300, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x300, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 3, 0x300, DrvChars); + } + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderFgLayer(0); + DrvRenderSprites(0); + DrvRenderFgLayer(1); + DrvRenderSprites(1); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static void LastduelDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + LastduelRenderBgLayer(); + LastduelRenderFgLayer(0); + DrvRenderSprites(0); + LastduelRenderFgLayer(1); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 100; + + if (DrvReset) MadgearDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 33 || i == 66) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) DrvDraw(); + + SekOpen(0); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + memcpy(DrvSpriteRamBuffer, DrvSpriteRam, 0x800); + + return 0; +} + +static INT32 LastduelFrame() +{ + INT32 nInterleave = 100; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 3579545 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 33 || i == 66) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) LastduelDraw(); + + SekOpen(0); + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + memcpy(DrvSpriteRamBuffer, DrvSpriteRam, 0x800); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029672; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); // Scan Z80 + BurnYM2203Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvZ80RomBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvFgScrollX); + SCAN_VAR(DrvFgScrollY); + SCAN_VAR(DrvBgScrollX); + SCAN_VAR(DrvBgScrollY); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + } + + return 0; +} + +static INT32 MadgearScan(INT32 nAction, INT32 *pnMin) +{ + INT32 i = DrvScan(nAction, pnMin); + + if (i == 0) { + if (nAction & ACB_DRIVER_DATA) { + MSM6295Scan(0, nAction); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x8000 + DrvZ80RomBank * 0x4000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x8000 + DrvZ80RomBank * 0x4000 ); + ZetClose(); + } + } + + return i; +} + +struct BurnDriver BurnDrvLastduel = { + "lastduel", NULL, NULL, NULL, "1988", + "Last Duel (US New Ver.)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, LastduelRomInfo, LastduelRomName, NULL, NULL, LastduelInputInfo, LastduelDIPInfo, + LastduelInit, DrvExit, LastduelFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvLastduelo = { + "lastduelo", "lastduel", NULL, NULL, "1988", + "Last Duel (US Old Ver.)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, LastdueloRomInfo, LastdueloRomName, NULL, NULL, LastduelInputInfo, LastduelDIPInfo, + LastduelInit, DrvExit, LastduelFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvLastduelj = { + "lastduelj", "lastduel", NULL, NULL, "1988", + "Last Duel (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, LastdueljRomInfo, LastdueljRomName, NULL, NULL, LastduelInputInfo, LastduelDIPInfo, + LastduelInit, DrvExit, LastduelFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvLsstduelb = { + "lastduelb", "lastduel", NULL, NULL, "1988", + "Last Duel (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, LastduelbRomInfo, LastduelbRomName, NULL, NULL, LastduelInputInfo, LastduelDIPInfo, + LastduelbInit, DrvExit, LastduelFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvMadgear = { + "madgear", NULL, NULL, NULL, "1989", + "Mad Gear (US)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, MadgearExit, DrvFrame, NULL, MadgearScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvMadgearj = { + "madgearj", "madgear", NULL, NULL, "1989", + "Mad Gear (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, MadgearExit, DrvFrame, NULL, MadgearScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvMadgearu = { + "ledstorm", "madgear", NULL, NULL, "1988", + "Led Storm (US)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, MadgearExit, DrvFrame, NULL, MadgearScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvLedstrm2 = { + "ledstorm2", "madgear", NULL, NULL, "1988", + "Led Storm Rally 2011 (US)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, Ledstrm2RomInfo, Ledstrm2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + Ledstrm2Init, MadgearExit, DrvFrame, NULL, MadgearScan, + NULL, 0x800, 240, 384, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_marineb.cpp b/src/burn/drivers/misc_pre90s/d_marineb.cpp new file mode 100644 index 00000000..10d0e4ce --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_marineb.cpp @@ -0,0 +1,850 @@ +// Based on original MAME driver writen by Zsolt Vasvari + + +#include "tiles_generic.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +enum { SPRINGER = 0, MARINEB }; + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *RamStart; +static UINT8 *RamEnd; +static UINT32 *TempPalette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalcPalette; + +static UINT8 DrvInputPort0[8]; +static UINT8 DrvInputPort1[8]; +static UINT8 DrvInputPort2[8]; +static UINT8 DrvDip; +static UINT8 DrvInput[3]; +static UINT8 DrvReset; + +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvColPROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; + +static UINT8 DrvPaletteBank; +static UINT8 DrvColumnScroll; +static UINT8 ActiveLowFlipscreen; +static UINT8 DrvFlipScreenY; +static UINT8 DrvFlipScreenX; +static INT32 DrvInterruptEnable; +static INT32 hardware; + +static INT16 *pAY8910Buffer[3]; + + + +static struct BurnInputInfo MarinebInputList[] = +{ + + {"P1 Coin" , BIT_DIGITAL , DrvInputPort2 + 0, "p1 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 right" }, + {"P1 Fire" , BIT_DIGITAL , DrvInputPort2 + 4, "p1 fire 1" }, + + {"P2 Start" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 right" }, + {"P2 Fire" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip" , BIT_DIPSWITCH, &DrvDip , "dip" }, + +}; + +STDINPUTINFO(Marineb) + +static struct BurnDIPInfo MarinebDIPList[]= +{ + {0x0E, 0xFF, 0xFF, 0x40, NULL }, + + {0 , 0xFE, 0 , 4, "Lives" }, + {0x0E, 0x01, 0x03, 0x00, "3" }, + {0x0E, 0x01, 0x03, 0x01, "4" }, + {0x0E, 0x01, 0x03, 0x02, "5" }, + {0x0E, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xFE, 0 , 2, "Coinage" }, + {0x0E, 0x01, 0x1C, 0x00, "1 Coin 1 Credit" }, + {0x0E, 0x01, 0x1C, 0x1C, "Free Play" }, + + {0 , 0xFE, 0 , 2, "Bonus Life" }, + {0x0E, 0x01, 0x20, 0x00, "20000 50000" }, + {0x0E, 0x01, 0x20, 0x20, "40000 70000" }, + + {0 , 0xFE, 0 , 2, "Cabinet" }, + {0x0E, 0x01, 0x40, 0x40, "Upright" }, + {0x0E, 0x01, 0x40, 0x00, "Cocktail" }, + +}; + +STDDIPINFO(Marineb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x10000; + DrvColPROM = Next; Next += 0x200; + DrvGfxROM0 = Next; Next += 512 * 8 * 8; + DrvGfxROM1 = Next; Next += 64 * 16 * 16; + DrvGfxROM2 = Next; Next += 64 * 32 * 32; + + TempPalette = (UINT32*)Next; Next += 0x100 * sizeof(UINT32); // calculate one time + DrvPalette = (UINT32*)Next; Next += 0x100 * sizeof(UINT32); + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + RamStart = Next; + + DrvZ80RAM = Next; Next += 0x800; + DrvVidRAM = Next; Next += 0x400; + DrvSprRAM = Next; Next += 0x100; + DrvColRAM = Next; Next += 0x400; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static void CleanAndInitStuff() +{ + DrvPaletteBank = 0; + DrvColumnScroll = 0; + DrvFlipScreenY = 0; + DrvFlipScreenX = 0; + DrvInterruptEnable = 0; + hardware = 0; + ActiveLowFlipscreen = 0; + + memset(DrvInputPort0, 0, 8); + memset(DrvInputPort1, 0, 8); + memset(DrvInputPort2, 0, 8); + memset(DrvInput, 0, 3); + + DrvDip = 0; + DrvReset = 0; +} + + +UINT8 __fastcall marineb_read(UINT16 address) +{ + switch (address) { + case 0xa800: + return DrvInput[0]; + + case 0xa000: + return DrvInput[1]; + + case 0xb000: + return DrvDip; + + case 0xb800: + return DrvInput[2]; + } + + return 0; +} + + +void __fastcall marineb_write(UINT16 address, UINT8 data) +{ + switch (address) { + + case 0x9800: + DrvColumnScroll = data; + return; + + case 0x9a00: + DrvPaletteBank = (DrvPaletteBank & 0x02) | (data & 0x01); + return; + + case 0x9c00: + DrvPaletteBank = (DrvPaletteBank & 0x01) | ((data & 0x01) << 1); + return; + + + case 0xa000: + DrvInterruptEnable = data; + return; + + case 0xa001: + DrvFlipScreenY = data ^ ActiveLowFlipscreen; + return; + + case 0xa002: + DrvFlipScreenX = data ^ ActiveLowFlipscreen; + return; + } +} + +void __fastcall marineb_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0xFF) { + case 0x08: + case 0x09: + AY8910Write(0, port & 1, data); + break; + } +} + +static INT32 DrvDoReset() +{ + memset (RamStart, 0, RamEnd - RamStart); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + DrvPaletteBank = 0; + DrvColumnScroll = 0; + DrvFlipScreenY = 0; + DrvFlipScreenX = 0; + DrvInterruptEnable = 0; + + return 0; +} + +static void DrvCreatePalette() +{ + for (INT32 i = 0; i < 256; i++) + { + INT32 bit0, bit1, bit2, r, g, b; + + // Red + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + // Green + bit0 = (DrvColPROM[i] >> 3) & 0x01; + bit1 = (DrvColPROM[i + 256] >> 0) & 0x01; + bit2 = (DrvColPROM[i + 256] >> 1) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + // Blue + bit0 = 0; + bit1 = (DrvColPROM[i + 256] >> 2) & 0x01; + bit2 = (DrvColPROM[i + 256] >> 3) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + TempPalette[i] = (r << 16) | (g << 8) | (b << 0); + } +} + + +static INT32 MarinebCharPlane[2] = { 0, 4 }; +static INT32 MarinebCharXOffs[8] = { 0, 1, 2, 3, 64, 65, 66, 67 }; +static INT32 MarinebCharYOffs[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +static INT32 MarinebSmallSpriteCharPlane[2] = { 0, 65536 }; +static INT32 MarinebSmallSpriteXOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; +static INT32 MarinebSmallSpriteYOffs[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + +static INT32 MarinebBigSpriteCharPlane[2] = { 0, 65536 }; +static INT32 MarinebBigSpriteXOffs[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71, 256, 257, 258, 259, 260, 261, 262, 263, 320, 321, 322, 323, 324, 325, 326, 327 }; +static INT32 MarinebBigSpriteYOffs[32] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184, 512, 520, 528, 536, 544, 552, 560, 568, 640, 648, 656, 664, 672, 680, 688, 696 }; + + +static INT32 MarinebLoadRoms() +{ + // Load roms + + // Z80 + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvZ80ROM + (i * 0x1000), i, 1)) return 1; + } + + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + if (tmp == NULL) return 1; + + // Chars + memset(tmp, 0, 0x2000); + if (BurnLoadRom(tmp, 5, 1)) return 1; + GfxDecode(0x200, 2, 8, 8, MarinebCharPlane, MarinebCharXOffs, MarinebCharYOffs, 0x80, tmp, DrvGfxROM0); + + // Sprites + memset(tmp, 0, 0x4000); + if (BurnLoadRom(tmp, 6, 1)) return 1; + if (BurnLoadRom(tmp + 0x2000, 7, 1)) return 1; + + // Small Sprites + GfxDecode(0x40, 2, 16, 16, MarinebSmallSpriteCharPlane, MarinebSmallSpriteXOffs, MarinebSmallSpriteYOffs, 0x100, tmp, DrvGfxROM1); + + // Big Sprites + GfxDecode(0x40, 2, 32, 32, MarinebBigSpriteCharPlane, MarinebBigSpriteXOffs, MarinebBigSpriteYOffs, 0x400, tmp, DrvGfxROM2); + + BurnFree(tmp); + + // ColorRoms + if (BurnLoadRom(DrvColPROM, 8, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x100, 9, 1)) return 1; + + return 0; +} + +static INT32 SpringerLoadRoms() +{ + // Load roms + + // Z80 + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(DrvZ80ROM + (i * 0x1000), i, 1)) return 1; + } + + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + if (tmp == NULL) return 1; + + // Chars + memset(tmp, 0, 0x4000); + if (BurnLoadRom(tmp, 5, 1)) return 1; + if (BurnLoadRom(tmp + 0x1000, 6, 1)) return 1; + + GfxDecode(0x200, 2, 8, 8, MarinebCharPlane, MarinebCharXOffs, MarinebCharYOffs, 0x80, tmp, DrvGfxROM0); + + memset(tmp, 0, 0x4000); + if (BurnLoadRom(tmp, 7, 1)) return 1; + if (BurnLoadRom(tmp + 0x2000, 8, 1)) return 1; + + // Small Sprites + GfxDecode(0x40, 2, 16, 16, MarinebSmallSpriteCharPlane, MarinebSmallSpriteXOffs, MarinebSmallSpriteYOffs, 0x100, tmp, DrvGfxROM1); + // Big Sprites + GfxDecode(0x40, 2, 32, 32, MarinebBigSpriteCharPlane, MarinebBigSpriteXOffs, MarinebBigSpriteYOffs, 0x400, tmp, DrvGfxROM2); + + BurnFree(tmp); + + // ColorRoms + if (BurnLoadRom(DrvColPROM, 9, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x100, 10, 1)) return 1; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + switch(hardware) { + case MARINEB: + MarinebLoadRoms(); + break; + case SPRINGER: + SpringerLoadRoms(); + break; + } + + DrvCreatePalette(); + + ZetInit(1); + ZetOpen(0); + + ZetMapArea (0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea (0x0000, 0x7fff, 2, DrvZ80ROM); + + ZetMapArea (0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea (0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea (0x8000, 0x87ff, 2, DrvZ80RAM); + + ZetMapArea (0x8800, 0x8bff, 0, DrvVidRAM); + ZetMapArea (0x8800, 0x8bff, 1, DrvVidRAM); + ZetMapArea (0x8800, 0x8bff, 2, DrvVidRAM); + + ZetMapArea (0x8c00, 0x8c3f, 0, DrvSprRAM); + ZetMapArea (0x8c00, 0x8c3f, 1, DrvSprRAM); + ZetMapArea (0x8c00, 0x8c3f, 2, DrvSprRAM); + + ZetMapArea (0x9000, 0x93ff, 0, DrvColRAM); + ZetMapArea (0x9000, 0x93ff, 1, DrvColRAM); + ZetMapArea (0x9000, 0x93ff, 2, DrvColRAM); + + ZetSetReadHandler(marineb_read); + ZetSetWriteHandler(marineb_write); + ZetSetOutHandler(marineb_write_port); + + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + DrvDoReset(); + + return 0; + +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + ZetExit(); + AY8910Exit(0); + + BurnFree (AllMem); + + CleanAndInitStuff(); + + return 0; +} + +static void RenderMarinebBg() +{ + INT32 TileIndex = 0; + + for (INT32 my = 0; my < 32; my++) { + for (INT32 mx = 0; mx < 32; mx++) { + + TileIndex = (my * 32) + mx; + + INT32 code = DrvVidRAM[TileIndex]; + INT32 color = DrvColRAM[TileIndex]; + + code |= ((color & 0xc0) << 2); + + color &= 0x0f; + color |= DrvPaletteBank << 4; + + INT32 flipx = (color >> 4) & 0x02; + INT32 flipy = (color >> 4) & 0x01; + + INT32 x = mx << 3; + INT32 y = my << 3; + + // stuff from 192 to 256 does not scroll + if ((x >> 3) < 24) { + y -= DrvColumnScroll; + if (y < -7) y += 256; + } + + y -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } + } + } + } +} + + +static void RenderSpringerBg() +{ + INT32 TileIndex = 0; + + for (INT32 my = 0; my < 32; my++) { + for (INT32 mx = 0; mx < 32; mx++) { + + TileIndex = (my * 32) + mx; + + INT32 code = DrvVidRAM[TileIndex]; + INT32 color = DrvColRAM[TileIndex]; + + code |= ((color & 0xc0) << 2); + + color &= 0x0f; + color |= DrvPaletteBank << 4; + + INT32 flipx = (color >> 4) & 0x02; + INT32 flipy = (color >> 4) & 0x01; + + INT32 x = mx << 3; + INT32 y = my << 3; + + y -= 16; // remove garbage on left side + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, x, y, color, 2, 0, DrvGfxROM0); + } + } + } + } +} + +static void MarinebDrawSprites() +{ + // Render Tiles + RenderMarinebBg(); + + for (INT32 offs = 0x0f; offs >= 0; offs--) { + + INT32 gfx, sx, sy, code, color, flipx, flipy, offs2; + + if ((offs == 0) || (offs == 2)) + continue; + + if (offs < 8) { + offs2 = 0x0018 + offs; + } else { + offs2 = 0x03d8 - 8 + offs; + } + + code = DrvVidRAM[offs2]; + sx = DrvVidRAM[offs2 + 0x20]; + sy = DrvColRAM[offs2]; + color = (DrvColRAM[offs2 + 0x20] & 0x0f) + 16 * DrvPaletteBank; + flipx = code & 0x02; + flipy = !(code & 0x01); + + if (offs < 4) { + gfx = 2; + code = (code >> 4) | ((code & 0x0c) << 2); + } else { + gfx = 1; + code >>= 2; + } + + if (!DrvFlipScreenY) { + + if (gfx == 1) { + sy = 256 - 16 - sy; + } else { + sy = 256 - 32 - sy; + } + flipy = !flipy; + } + + if (DrvFlipScreenX) { + sx++; + } + + sy -= 16; // proper alignement + + // Small Sprites + if (gfx == 1) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } + // Big sprites + } else { + if (flipy) { + if (flipx) { + Render32x32Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render32x32Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render32x32Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render32x32Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } + } + } +} + +static void SpringerDrawSprites() +{ + // Render Tiles + RenderSpringerBg(); + + for (INT32 offs = 0x0f; offs >= 0; offs--) + { + INT32 gfx, sx, sy, code, color, flipx, flipy, offs2; + + if ((offs == 0) || (offs == 2)) + continue; + + offs2 = 0x0010 + offs; + + code = DrvVidRAM[offs2]; + sx = 240 - DrvVidRAM[offs2 + 0x20]; + sy = DrvColRAM[offs2]; + color = (DrvColRAM[offs2 + 0x20] & 0x0f) + 16 * DrvPaletteBank; + flipx = !(code & 0x02); + flipy = !(code & 0x01); + + if (offs < 4) + { + sx -= 0x10; + gfx = 2; + code = (code >> 4) | ((code & 0x0c) << 2); + } + else + { + gfx = 1; + code >>= 2; + } + + if (!DrvFlipScreenY) { + + if (gfx == 1) { + sy = 256 - 16 - sy; + } else { + sy = 256 - 32 - sy; + } + flipy = !flipy; + } + + if (!DrvFlipScreenX) + { + sx--; + } + + sy -= 16; // proper alignement + + // Small Sprites + if (gfx == 1) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM1); + } + } + // Big Sprites + } else { + if (flipy) { + if (flipx) { + Render32x32Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render32x32Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } else { + if (flipx) { + Render32x32Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } else { + Render32x32Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 0, 0, DrvGfxROM2); + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalcPalette) { + for (INT32 i = 0; i < 256; i++) { + UINT32 tmp = TempPalette[i]; + // Recalc Colors + DrvPalette[i] = BurnHighCol((tmp >> 16) & 0xFF, (tmp >> 8) & 0xFF, tmp & 0xFF, 0); + } + DrvRecalcPalette = 0; + } + + switch(hardware) { + case MARINEB: + MarinebDrawSprites(); + break; + + case SPRINGER: + SpringerDrawSprites(); + break; + } + + BurnTransferCopy(DrvPalette); + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0; + + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + ZetOpen(0); + ZetRun(3072000 / 60); + + if (DrvInterruptEnable) ZetNmi(); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029708; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + } + + + return 0; +} + +static INT32 MarinebInit() +{ + CleanAndInitStuff(); + hardware = MARINEB; + + return DrvInit(); +} + +static INT32 SpringerInit() +{ + CleanAndInitStuff(); + + ActiveLowFlipscreen = 1; + hardware = SPRINGER; + + return DrvInit(); +} + +// Marine Boy + +static struct BurnRomInfo MarinebRomDesc[] = { + + { "marineb.1", 0x1000, 0x661d6540, BRF_ESS | BRF_PRG }, // 0 maincpu + { "marineb.2", 0x1000, 0x922da17f, BRF_ESS | BRF_PRG }, // 1 + { "marineb.3", 0x1000, 0x820a235b, BRF_ESS | BRF_PRG }, // 2 + { "marineb.4", 0x1000, 0xa157a283, BRF_ESS | BRF_PRG }, // 3 + { "marineb.5", 0x1000, 0x9ffff9c0, BRF_ESS | BRF_PRG }, // 4 + + { "marineb.6", 0x2000, 0xee53ec2e, BRF_GRA }, // 5 gfx1 + + { "marineb.8", 0x2000, 0xdc8bc46c, BRF_GRA }, // 6 gfx2 + { "marineb.7", 0x2000, 0x9d2e19ab, BRF_GRA }, // 7 + + { "marineb.1b", 0x100, 0xf32d9472, BRF_GRA }, // 8 proms + { "marineb.1c", 0x100, 0x93c69d3e, BRF_GRA }, // 9 +}; + +STD_ROM_PICK(Marineb) +STD_ROM_FN(Marineb) + +struct BurnDriver BurnDrvMarineb = { + "marineb", NULL, NULL, NULL, "1982", + "Marine Boy\0", NULL, "Orca", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, 0, 0, + NULL, MarinebRomInfo, MarinebRomName, NULL, NULL, MarinebInputInfo, MarinebDIPInfo, + MarinebInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalcPalette, 0x100, 256, 224, 4, 3 +}; + +// Springer + +static struct BurnRomInfo SpringerRomDesc[] = { + + { "springer.1", 0x1000, 0x0794103a, BRF_ESS | BRF_PRG }, // 0 maincpu + { "springer.2", 0x1000, 0xf4aecd9a, BRF_ESS | BRF_PRG }, // 1 + { "springer.3", 0x1000, 0x2f452371, BRF_ESS | BRF_PRG }, // 2 + { "springer.4", 0x1000, 0x859d1bf5, BRF_ESS | BRF_PRG }, // 3 + { "springer.5", 0x1000, 0x72adbbe3, BRF_ESS | BRF_PRG }, // 4 + + { "springer.6", 0x1000, 0x6a961833, BRF_GRA }, // 5 gfx1 + { "springer.7", 0x1000, 0x95ab8fc0, BRF_GRA }, // 6 + + { "springer.8", 0x1000, 0xa54bafdc, BRF_GRA }, // 7 gfx2 + { "springer.9", 0x1000, 0xfa302775, BRF_GRA }, // 8 + + { "1b.vid", 0x100, 0xa2f935aa, BRF_GRA }, // 9 proms + { "1c.vid", 0x100, 0xb95421f4, BRF_GRA }, // 10 +}; + +STD_ROM_PICK(Springer) +STD_ROM_FN(Springer) + +struct BurnDriver BurnDrvSpringer = { + "springer", NULL, NULL, NULL, "1982", + "Springer\0", NULL, "Orca", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, 0, 0, + NULL, SpringerRomInfo, SpringerRomName, NULL, NULL, MarinebInputInfo, MarinebDIPInfo, + SpringerInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalcPalette, 0x100, 224, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_markham.cpp b/src/burn/drivers/misc_pre90s/d_markham.cpp new file mode 100644 index 00000000..c22fc127 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_markham.cpp @@ -0,0 +1,531 @@ + // FB Alpha Markham driver module +// Based on MAME driver by Uki + +#include "tiles_generic.h" +#include "sn76496.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *MemEnd; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvVidRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvShareRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *scroll; + +static UINT8 flipscreen; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo MarkhamInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Markham) + +static struct BurnDIPInfo MarkhamDIPList[]= +{ + {0x12, 0xff, 0xff, 0x02, NULL }, + {0x13, 0xff, 0xff, 0x7e, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Lives" }, + {0x12, 0x01, 0x01, 0x00, "3" }, + {0x12, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x02, 0x02, "Upright" }, + {0x12, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Chutes" }, + {0x12, 0x01, 0x08, 0x00, "Individual" }, + {0x12, 0x01, 0x08, 0x08, "Common" }, + + {0 , 0xfe, 0 , 16, "Coin1 / Coin2" }, + {0x12, 0x01, 0xf0, 0x00, "1C 1C / 1C 1C" }, + {0x12, 0x01, 0xf0, 0x10, "2C 1C / 2C 1C" }, + {0x12, 0x01, 0xf0, 0x20, "2C 1C / 1C 3C" }, + {0x12, 0x01, 0xf0, 0x30, "1C 1C / 1C 2C" }, + {0x12, 0x01, 0xf0, 0x40, "1C 1C / 1C 3C" }, + {0x12, 0x01, 0xf0, 0x50, "1C 1C / 1C 4C" }, + {0x12, 0x01, 0xf0, 0x60, "1C 1C / 1C 5C" }, + {0x12, 0x01, 0xf0, 0x70, "1C 1C / 1C 6C" }, + {0x12, 0x01, 0xf0, 0x80, "1C 2C / 1C 2C" }, + {0x12, 0x01, 0xf0, 0x90, "1C 2C / 1C 4C" }, + {0x12, 0x01, 0xf0, 0xa0, "1C 2C / 1C 5C" }, + {0x12, 0x01, 0xf0, 0xb0, "1C 2C / 1C 10C" }, + {0x12, 0x01, 0xf0, 0xc0, "1C 2C / 1C 11C" }, + {0x12, 0x01, 0xf0, 0xd0, "1C 2C / 1C 12C" }, + {0x12, 0x01, 0xf0, 0xe0, "1C 2C / 1C 6C" }, + {0x12, 0x01, 0xf0, 0xf0, "Free Play" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x03, 0x00, "None" }, + {0x13, 0x01, 0x03, 0x01, "20000" }, + {0x13, 0x01, 0x03, 0x02, "20000, Every 50000" }, + {0x13, 0x01, 0x03, 0x03, "20000, Every 80000" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(Markham) + +void __fastcall markham_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe00c: + scroll[0] = data; + return; + + case 0xe00d: + scroll[1] = data; + return; + + case 0xe00e: + flipscreen = data & 1; + return; + } +} + +UINT8 __fastcall markham_main_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + return DrvDips[1]; + + case 0xe001: + return DrvDips[0]; + + case 0xe002: + return DrvInputs[0]; + + case 0xe003: + return DrvInputs[1]; + + case 0xe005: + return (DrvInputs[2] & ~0x10) | (DrvDips[2] & 0x10); + } + + return 0; +} + +void __fastcall markham_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc000: + SN76496Write(0, data); + return; + + case 0xc001: + SN76496Write(1, data); + return; + } +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + flipscreen = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x006000; + DrvZ80ROM1 = Next; Next += 0x006000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000700; + + Palette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0400 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + DrvShareRAM = Next; Next += 0x000800; + + scroll = Next; Next += 0x000002; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { 0x00000, 0x10000, 0x20000 }; + INT32 XOffs[16] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80 }; + INT32 YOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x6000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x6000); + + GfxDecode(0x0100, 3, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x6000); + + GfxDecode(0x0400, 3, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) + { + INT32 r = DrvColPROM[i + 0x000] & 0x0f; + INT32 g = DrvColPROM[i + 0x100] & 0x0f; + INT32 b = DrvColPROM[i + 0x200] & 0x0f; + + DrvPalette[i] = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | (b << 0); + } + + for (INT32 i = 0; i < 0x400; i++) { + Palette[i] = DrvPalette[DrvColPROM[0x300 + i]]; + } + + DrvRecalc = 1; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM1 + 0x04000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x02000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x04000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x02000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x04000, 10, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 11, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 12, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 13, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00300, 14, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00500, 15, 1)) return 1; + + DrvGfxDecode(); + DrvPaletteInit(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM0); + ZetMapArea(0xc800, 0xcfff, 0, DrvSprRAM); + ZetMapArea(0xc800, 0xcfff, 1, DrvSprRAM); + ZetMapArea(0xc800, 0xcfff, 2, DrvSprRAM); + ZetMapArea(0xd000, 0xd7ff, 0, DrvVidRAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvVidRAM); + ZetMapArea(0xd000, 0xd7ff, 2, DrvVidRAM); + ZetMapArea(0xd800, 0xdfff, 0, DrvShareRAM); + ZetMapArea(0xd800, 0xdfff, 1, DrvShareRAM); + ZetMapArea(0xd800, 0xdfff, 2, DrvShareRAM); + ZetSetWriteHandler(markham_main_write); + ZetSetReadHandler(markham_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x5fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x5fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvShareRAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvShareRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvShareRAM); + ZetSetWriteHandler(markham_sound_write); + ZetMemEnd(); + ZetClose(); + + SN76489Init(0, 4000000, 0); + SN76489Init(1, 4000000, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + SN76496Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background_layer() +{ + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs >> 5) << 3; + INT32 sy = (offs & 0x1f) << 3; + + if (sy >= 32 && sy < 128) sx -= scroll[0]; + if (sy >= 128 && sy < 256) sx -= scroll[1]; + + if (sx < -7) sx += 256; + + INT32 attr = DrvVidRAM[offs * 2 + 0]; + INT32 code = DrvVidRAM[offs * 2 + 1] | ((attr & 0x60) << 3); + INT32 color = (attr & 0x1f) | ((attr & 0x80) >> 2); + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (248 - sx) - 8, (248 - sy) - 16, color, 3, 0x200, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx - 8, sy - 16, color, 3, 0x200, DrvGfxROM1); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x60; offs < 0x100; offs +=4) + { + INT32 sy = DrvSprRAM[offs + 0]; + INT32 code = DrvSprRAM[offs + 1]; + INT32 color = DrvSprRAM[offs + 2] & 0x3f; + INT32 sx = DrvSprRAM[offs + 3]; + + if (flipscreen) { + sx = (240 - sx) & 0xff; + } else { + sx = (sx - 2) & 0xff; + sy = 240 - sy; + } + + if (sx > 248) sx -= 256; + + RenderTileTranstab(pTransDraw, DrvGfxROM0, code, color << 3, 0, sx - 8, sy - 16, flipscreen, flipscreen, 16, 16, DrvColPROM + 0x300); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, (d >> 8) & 0xff, d & 0xff, 0); + } + DrvRecalc = 0; + } + + draw_background_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 10; + INT32 nCyclesTotal[2] = { 4000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nSegment = nCyclesTotal[0] / nInterleave; + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + ZetOpen(1); + nCyclesDone[1] += ZetRun(nSegment); + if (i == (nInterleave - 1)) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + } + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + SCAN_VAR(flipscreen); + } + + return 0; +} + + +// Markham + +static struct BurnRomInfo markhamRomDesc[] = { + { "tv3.9", 0x2000, 0x59391637, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "tvg4.10", 0x2000, 0x1837bcce, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tvg5.11", 0x2000, 0x651da602, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "tvg1.5", 0x2000, 0xc5299766, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + { "tvg2.6", 0x2000, 0xb216300a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "tvg6.84", 0x2000, 0xab933ae5, 3 | BRF_GRA }, // 5 Sprites + { "tvg7.85", 0x2000, 0xce8edda7, 3 | BRF_GRA }, // 6 + { "tvg8.86", 0x2000, 0x74d1536a, 3 | BRF_GRA }, // 7 + + { "tvg9.87", 0x2000, 0x42168675, 4 | BRF_GRA }, // 8 Tiles + { "tvg10.88", 0x2000, 0xfa9feb67, 4 | BRF_GRA }, // 9 + { "tvg11.89", 0x2000, 0x71f3dd49, 4 | BRF_GRA }, // 10 + + { "14-3.99", 0x0100, 0x89d09126, 5 | BRF_GRA }, // 11 Color PROMs + { "14-4.100", 0x0100, 0xe1cafe6c, 5 | BRF_GRA }, // 12 + { "14-5.101", 0x0100, 0x2d444fa6, 5 | BRF_GRA }, // 13 + { "14-1.61", 0x0200, 0x3ad8306d, 5 | BRF_GRA }, // 14 + { "14-2.115", 0x0200, 0x12a4f1ff, 5 | BRF_GRA }, // 15 +}; + +STD_ROM_PICK(markham) +STD_ROM_FN(markham) + +struct BurnDriver BurnDrvMarkham = { + "markham", NULL, NULL, NULL, "1983", + "Markham\0", NULL, "Sun Electronics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, markhamRomInfo, markhamRomName, NULL, NULL, MarkhamInputInfo, MarkhamDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 240, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_meijinsn.cpp b/src/burn/drivers/misc_pre90s/d_meijinsn.cpp new file mode 100644 index 00000000..865f4990 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_meijinsn.cpp @@ -0,0 +1,559 @@ +// FB Alpha Meijinsen Driver Module +// Based on MAME driver by Tomasz Slanina + +#include "burnint.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT32 *Palette; +static UINT8 *Mem, *M68KRom, *Z80Rom, *Prom; +static INT16 *pFMBuffer, *pAY8910Buffer[3]; +static UINT8 DrvJoy1[9], DrvJoy2[8], DrvReset, DrvDips; +static UINT8 soundlatch, deposits1, deposits2, credits; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 coin" }, + {"Start 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Clear Credit", BIT_DIGITAL, DrvJoy1 + 8, "clear credit" }, + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip Switches", BIT_DIPSWITCH, &DrvDips, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[] = +{ + // Defaults + {0x12, 0xFF, 0xFF, 0x08, NULL}, + + {0, 0xFE, 0, 8, "Game time (actual game)"}, + {0x12, 0x01, 0x07, 0x07, "01:00"}, + {0x12, 0x01, 0x07, 0x06, "02:00"}, + {0x12, 0x01, 0x07, 0x05, "03:00"}, + {0x12, 0x01, 0x07, 0x04, "04:00"}, + {0x12, 0x01, 0x07, 0x03, "05:00"}, + {0x12, 0x01, 0x07, 0x02, "10:00"}, + {0x12, 0x01, 0x07, 0x01, "20:00"}, + {0x12, 0x01, 0x07, 0x00, "00:30"}, + + {0, 0xFE, 0, 2, "Coinage"}, + {0x12, 0x01, 0x08, 0x08, "A 1C/1C B 1C/5C"}, + {0x12, 0x01, 0x08, 0x00, "A 1C/2C B 2C/1C"}, + + {0, 0xFE, 0, 2, "2 Player"}, + {0x12, 0x01, 0x10, 0x00, "1C"}, + {0x12, 0x01, 0x10, 0x10, "2C"}, + + {0, 0xFE, 0, 2, "Game time (tsumeshougi)"}, + {0x12, 0x01, 0x20, 0x20, "01:00"}, + {0x12, 0x01, 0x20, 0x00, "02:00"}, +}; + +STDDIPINFO(Drv) + + +UINT16 inputs(INT32 inp) +{ + UINT8 ret = 0; + + switch (inp) + { + case 0x00: { // start + service + ret |= DrvJoy1[7] << 0; // + ret |= DrvJoy2[7] << 1; + ret |= DrvJoy1[8] << 7; // clear credit + } + break; + + case 0x01: { // player 1 controls + for (INT32 i = 0; i < 6; i++) ret |= DrvJoy1[i] << i; + } + break; + + case 0x02: { // player 2 controls + for (INT32 i = 0; i < 6; i++) ret |= DrvJoy2[i] << i; + } + break; + + case 0x03: { // coins + ret = (DrvJoy1[6] | (DrvJoy2[6] << 1)) ^ 3; + } + break; + + break; + } + + return ret; +} + +UINT8 soundlatch_r(UINT32) +{ + return soundlatch; +} + +UINT8 __fastcall alpha_mcu_r(UINT8 offset) +{ + static UINT8 coinvalue = 0; + static const UINT8 coinage1[2][2] = { {1, 1}, {1, 2} }; + static const UINT8 coinage2[2][2] = { {1, 5}, {2, 1} }; + + static INT32 latch; + + switch (offset) + { + case 0x01: // Dipswitch 2 + M68KRom[0x180e44] = DrvDips & 0xff; + return 0; + + case 0x45: // Coin value + M68KRom[0x180e44] = credits & 0xff; + return 0; + + case 0x53: // Query microcontroller for coin insert + { + credits = 0; + + if ((inputs(3) & 0x03) == 0x03) latch = 0; + + M68KRom[0x180e52] = 0x22; + + if ((inputs(3) & 0x03) != 0x03 && latch == 0) + { + M68KRom[0x180e44] = 0x00; + + latch = 1; + + coinvalue = (~DrvDips>>3) & 1; + + if (~inputs(3) & 0x01) + { + deposits1++; + if (deposits1 == coinage1[coinvalue][0]) + { + credits = coinage1[coinvalue][1]; + deposits1 = 0; + } + else + credits = 0; + } + else if (~inputs(3) & 0x02) + { + deposits2++; + if (deposits2 == coinage2[coinvalue][0]) + { + credits = coinage2[coinvalue][1]; + deposits2 = 0; + } + else + credits = 0; + } + } + } + + return 0; + } + + return 0; +} + +UINT8 __fastcall meijinsn_read_byte(UINT32 a) +{ + if ((a & ~0xff) == 0x080e00) { + return alpha_mcu_r(a & 0xff); + } + + switch (a) + { + case 0x1a0000: + return inputs(0); + + case 0x1a0001: + return inputs(1); + + case 0x1c0000: + return inputs(2); + } + + return 0; +} + +void __fastcall meijinsn_write_byte(UINT32 a, UINT8 d) +{ + if (a == 0x1a0001) { + soundlatch = d & 0xff; + return; + } +} + + +UINT8 __fastcall meijinsn_in_port(UINT16 a) +{ + if ((a & 0xff) == 0x01) { // AY8910 read port + return AY8910Read(0); + } + + return 0; +} + +void __fastcall meijinsn_out_port(UINT16 a, UINT8 data) +{ + switch (a & 0xff) + { + case 0x00: // AY8910 control port + AY8910Write(0, 0, data); + break; + + case 0x01: // AY8910 write port + AY8910Write(0, 1, data); + break; + + case 0x02: // Soundlatch clear + soundlatch = 0; + break; + } +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (M68KRom + 0x100000, 0, 0x082000); // clear 68k RAM + memset (Z80Rom + 0x008000, 0, 0x000800); // clear z80 RAM + + deposits1 = 0; + deposits2 = 0; + credits = 0; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + return 0; +} + +static void Pallete_Init() +{ +#define combine_3_weights(tab,w0,w1,w2) ((int)(((tab)[0]*(w0) + (tab)[1]*(w1) + (tab)[2]*(w2)) + 0.5)) + + float weights_r[3] = { 41.697944, 73.045335, 140.256721}; + float weights_g[3] = { 41.697944, 73.045335, 140.256721}; + float weights_b[3] = { 83.228546, 159.809836, 0.000000}; + + for (INT32 i = 0; i < 0x10; i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + // red component + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = combine_3_weights(weights_r, bit0, bit1, bit2); + + // green component + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = combine_3_weights(weights_g, bit0, bit1, bit2); + + // blue component + bit0 = (Prom[i] >> 6) & 0x01; + bit1 = (Prom[i] >> 7) & 0x01; + b = combine_3_weights(weights_b, bit0, bit1, 0); + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static INT32 DrvInit() +{ + Mem = (UINT8 *)BurnMalloc(0x210020 + (0x10 * sizeof(UINT32))); + if (Mem == NULL) { + return 1; + } + + M68KRom = Mem + 0x000000; + Z80Rom = Mem + 0x200000; + Prom = Mem + 0x210000; + Palette = (UINT32 *)(Mem + 0x210020); + + pFMBuffer = (INT16 *)malloc (nBurnSoundLen * 3 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + // Load roms + { + INT32 i; + for (i = 0; i < 8; i+=2) { + BurnLoadRom(M68KRom + 0x100001, i + 0, 2); + BurnLoadRom(M68KRom + 0x100000, i + 1, 2); + + memcpy (M68KRom + 0x00000 + 0x08000 * (i >> 1), M68KRom + 0x100000, 0x08000); + memcpy (M68KRom + 0x20000 + 0x08000 * (i >> 1), M68KRom + 0x108000, 0x08000); + } + + BurnLoadRom(Z80Rom + 0x00000, 8, 1); + BurnLoadRom(Z80Rom + 0x04000, 9, 1); + BurnLoadRom(Prom, 10, 1); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(M68KRom, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(M68KRom + 0x100000, 0x100000, 0x181fff, SM_RAM); + SekSetReadByteHandler(0, meijinsn_read_byte); + SekSetWriteByteHandler(0, meijinsn_write_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xffff, 0, Z80Rom); + ZetMapArea(0x0000, 0x7fff, 2, Z80Rom); + ZetMapArea(0x8000, 0x87ff, 0, Z80Rom + 0x8000); + ZetMapArea(0x8000, 0x87ff, 1, Z80Rom + 0x8000); + ZetMapArea(0x8000, 0x87ff, 2, Z80Rom + 0x8000); + ZetSetInHandler(meijinsn_in_port); + ZetSetOutHandler(meijinsn_out_port); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 2000000, nBurnSoundRate, &soundlatch_r, NULL, NULL, NULL); + + Pallete_Init(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + AY8910Exit(0); + SekExit(); + ZetExit(); + + BurnFree (Mem); + Palette = NULL; + BurnFree (pFMBuffer); + Mem = M68KRom = Z80Rom = Prom = NULL; + pFMBuffer = NULL; + pAY8910Buffer[0] = pAY8910Buffer[1] = pAY8910Buffer[2] = NULL; + + return 0; +} + + +static INT32 DrvDraw() +{ + for (INT32 i = 0; i < 0x4000; i++) + { + INT32 sx, sy, x, data1, data2, color, data; + + sx = (i >> 6) & 0xfc; + sy = i & 0xff; + + if (sy < 16 || sy > 239 || sx < 12 || sx > 240) continue; + sx -= 12; sy = (sy - 16) * 232; + + data1 = M68KRom[0x100001 + (i << 1)]; + data2 = M68KRom[0x100000 + (i << 1)]; + + for (x = 0; x < 4; x++) + { + color = ((data1 >> x) & 1) | ((data1 >> (3 + x)) & 2); + data = ((data2 >> x) & 1) | ((data2 >> (3 + x)) & 2); + + UINT32 c = Palette[(color << 2) | data]; + + PutPix(pBurnDraw + (sy + sx + (x ^ 3)) * nBurnBpp, BurnHighCol(c >> 16, c >> 8, c, 0)); + } + } + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = 160; + + INT32 nCyclesSegment; + INT32 nCyclesDone[2], nCyclesTotal[2]; + + nCyclesTotal[0] = 9000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[0]; + nCyclesDone[0] += SekRun(nCyclesSegment); + if (i == 79) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == 159) SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + nNext = (i + 1) * nCyclesTotal[1] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[1]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[1] += nCyclesSegment; + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + ZetClose(); + SekClose(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = M68KRom + 0x100000; + ba.nLen = 0x082000; + ba.szName = "Main 68K Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = Z80Rom + 0x8000; + ba.nLen = 0x00800; + ba.szName = "Main Z80 Ram"; + BurnAcb(&ba); + + SekScan(nAction); // Scan 68K + ZetScan(nAction); // Scan Z80 + AY8910Scan(nAction, pnMin); // Scan AY8910 + + // Scan critical driver variables + SCAN_VAR(soundlatch); + SCAN_VAR(deposits1); + SCAN_VAR(deposits2); + SCAN_VAR(credits); + } + + return 0; +} + + +// Meijinsen + +static struct BurnRomInfo meijinsnRomDesc[] = { + { "p1", 0x08000, 0x8c9697a3, BRF_PRG | BRF_ESS }, // 0 M68000 Code + { "p2", 0x08000, 0xf7da3535, BRF_PRG | BRF_ESS }, // 1 + { "p3", 0x08000, 0x0af0b266, BRF_PRG | BRF_ESS }, // 2 + { "p4", 0x08000, 0xaab159c5, BRF_PRG | BRF_ESS }, // 3 + { "p5", 0x08000, 0x0ed10a47, BRF_PRG | BRF_ESS }, // 4 + { "p6", 0x08000, 0x60b58755, BRF_PRG | BRF_ESS }, // 5 + { "p7", 0x08000, 0x604c76f1, BRF_PRG | BRF_ESS }, // 6 + { "p8", 0x08000, 0xe3eaef19, BRF_PRG | BRF_ESS }, // 7 + + { "p9", 0x04000, 0xaedfefdf, BRF_PRG | BRF_ESS }, // 8 Z80 Code + { "p10", 0x04000, 0x93b4d764, BRF_PRG | BRF_ESS }, // 9 + + { "clr", 0x00020, 0x7b95b5a7, BRF_GRA }, // 10 Color Prom +}; + +STD_ROM_PICK(meijinsn) +STD_ROM_FN(meijinsn) + +struct BurnDriver BurnDrvMeijinsn = { + "meijinsn", NULL, NULL, NULL, "1986", + "Meijinsen\0", NULL, "SNK Electronics corp.", "Miscellaneous", + L"\u540D\u4EBA\u6226\0Meijinsen\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, meijinsnRomInfo, meijinsnRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x10, + 232, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_minivdr.cpp b/src/burn/drivers/misc_pre90s/d_minivdr.cpp new file mode 100644 index 00000000..fe804bb2 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_minivdr.cpp @@ -0,0 +1,197 @@ +// FB Alpha Minivader driver module +//Based on MAME Driver by Takahiro Nogi + +#include "tiles_generic.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80RAM; + +static UINT8 DrvJoy1[4]; +static UINT8 DrvInputs[1]; +static UINT8 DrvReset; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 3, "p1 coin" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 2, "p1 fire 1"}, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, +}; + +STDINPUTINFO(Drv) + +UINT8 __fastcall minivdr_read(UINT16 address) +{ + if (address == 0xe008) { + return DrvInputs[0]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x010000; + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x002000; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM, 0, 1)) return 1; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea (0x0000, 0x1fff, 0, DrvZ80ROM); + ZetMapArea (0x0000, 0x1fff, 2, DrvZ80ROM); + ZetMapArea (0xa000, 0xbfff, 0, DrvZ80RAM); + ZetMapArea (0xa000, 0xbfff, 1, DrvZ80RAM); + ZetMapArea (0xa000, 0xbfff, 2, DrvZ80RAM); + ZetSetReadHandler(minivdr_read); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static INT32 DrvDraw() +{ + UINT32 DrvPalette[2]; + + DrvPalette[0] = 0; + DrvPalette[1] = BurnHighCol(0xff, 0xff, 0xff, 0); + + for (INT32 offs = 0x200; offs < 0x1e00; offs++) + { + INT32 sx = (offs << 3) & 0xf8; + INT32 sy = ((offs >> 5) - 0x10) << 8; + INT32 d = DrvZ80RAM[offs]; + + for (INT32 i = 0; i < 8; i++, sx++) + { + pTransDraw[sx + sy] = (d >> (7 - i)) & 1; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xff; + for (INT32 i = 0; i < 4; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + } + + ZetOpen(0); + ZetRun(4000000 / 60); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + } + + return 0; +} + + +// Minivader + +static struct BurnRomInfo minivadrRomDesc[] = { + { "d26-01.bin", 0x2000, 0xa96c823d, BRF_ESS | BRF_PRG }, // Z80 code +}; + +STD_ROM_PICK(minivadr) +STD_ROM_FN(minivadr) + +struct BurnDriver BurnDrvminivadr = { + "minivadr", NULL, NULL, NULL, "1990", + "Minivader\0", NULL, "Taito Corporation", "Minivader", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, minivadrRomInfo, minivadrRomName, NULL, NULL, DrvInputInfo, NULL, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_mitchell.cpp b/src/burn/drivers/misc_pre90s/d_mitchell.cpp new file mode 100644 index 00000000..fff67175 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_mitchell.cpp @@ -0,0 +1,3250 @@ +#include "tiles_generic.h" +#include "eeprom.h" +#include "burn_ym2413.h" +#include "msm6295.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort5[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort6[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort7[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort9[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort10[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort11[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvReset = 0; +static INT16 DrvDial1 = 0; +static INT16 DrvDial2 = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom = NULL; +static UINT8 *DrvZ80Code = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvSoundRom = NULL; +static UINT8 *DrvZ80Ram = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvAttrRam = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static UINT8 DrvRomBank; +static UINT8 DrvPaletteRamBank; +static UINT8 DrvOkiBank; +static UINT8 DrvFlipScreen; +static UINT8 DrvVideoBank; +static UINT8 DrvInput5Toggle; +static UINT8 DrvPort5Kludge; +static INT32 DrvTileMask; +static UINT8 DrvHasEEPROM; +static INT32 DrvNumColours; +static INT32 DrvNVRamSize; +static INT32 DrvNVRamAddress; +static UINT8 DrvDialSelected; +static INT32 DrvDial[2]; +static UINT8 DrvSoundLatch; + +static UINT8 DrvInputType; +static INT32 DrvMahjongKeyMatrix; + +#define DRV_INPUT_TYPE_MAHJONG 1 +#define DRV_INPUT_TYPE_BLOCK 2 + +static struct BurnInputInfo MgakuenInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort7 + 2, "p2 start" }, + + {"P1 A" , BIT_DIGITAL , DrvInputPort1 + 7, "mah a" }, + {"P1 B" , BIT_DIGITAL , DrvInputPort2 + 7, "mah b" }, + {"P1 C" , BIT_DIGITAL , DrvInputPort4 + 7, "mah c" }, + {"P1 D" , BIT_DIGITAL , DrvInputPort5 + 7, "mah d" }, + {"P1 E" , BIT_DIGITAL , DrvInputPort1 + 6, "mah e" }, + {"P1 F" , BIT_DIGITAL , DrvInputPort2 + 6, "mah f" }, + {"P1 G" , BIT_DIGITAL , DrvInputPort4 + 6, "mah g" }, + {"P1 H" , BIT_DIGITAL , DrvInputPort5 + 6, "mah h" }, + {"P1 I" , BIT_DIGITAL , DrvInputPort1 + 5, "mah i" }, + {"P1 J" , BIT_DIGITAL , DrvInputPort2 + 5, "mah j" }, + {"P1 K" , BIT_DIGITAL , DrvInputPort4 + 5, "mah k" }, + {"P1 L" , BIT_DIGITAL , DrvInputPort5 + 5, "mah l" }, + {"P1 M" , BIT_DIGITAL , DrvInputPort1 + 4, "mah m" }, + {"P1 N" , BIT_DIGITAL , DrvInputPort2 + 4, "mah n" }, + {"P1 Pon" , BIT_DIGITAL , DrvInputPort5 + 4, "mah pon" }, + {"P1 Chi" , BIT_DIGITAL , DrvInputPort4 + 4, "mah chi" }, + {"P1 Kan" , BIT_DIGITAL , DrvInputPort1 + 3, "mah kan" }, + {"P1 Ron" , BIT_DIGITAL , DrvInputPort4 + 3, "mah ron" }, + {"P1 Reach" , BIT_DIGITAL , DrvInputPort2 + 3, "mah reach" }, + {"P1 Flip Flop" , BIT_DIGITAL , DrvInputPort6 + 4, "mah ff" }, + + {"P2 A" , BIT_DIGITAL , DrvInputPort7 + 7, "mah a" }, + {"P2 B" , BIT_DIGITAL , DrvInputPort8 + 7, "mah b" }, + {"P2 C" , BIT_DIGITAL , DrvInputPort9 + 7, "mah c" }, + {"P2 D" , BIT_DIGITAL , DrvInputPort10 + 7, "mah d" }, + {"P2 E" , BIT_DIGITAL , DrvInputPort7 + 6, "mah e" }, + {"P2 F" , BIT_DIGITAL , DrvInputPort8 + 6, "mah f" }, + {"P2 G" , BIT_DIGITAL , DrvInputPort9 + 6, "mah g" }, + {"P2 H" , BIT_DIGITAL , DrvInputPort10 + 6, "mah h" }, + {"P2 I" , BIT_DIGITAL , DrvInputPort7 + 5, "mah i" }, + {"P2 J" , BIT_DIGITAL , DrvInputPort8 + 5, "mah j" }, + {"P2 K" , BIT_DIGITAL , DrvInputPort9 + 5, "mah k" }, + {"P2 L" , BIT_DIGITAL , DrvInputPort10 + 5, "mah l" }, + {"P2 M" , BIT_DIGITAL , DrvInputPort7 + 4, "mah m" }, + {"P2 N" , BIT_DIGITAL , DrvInputPort2 + 4, "mah n" }, + {"P2 Pon" , BIT_DIGITAL , DrvInputPort10 + 4, "mah pon" }, + {"P2 Chi" , BIT_DIGITAL , DrvInputPort9 + 4, "mah chi" }, + {"P2 Kan" , BIT_DIGITAL , DrvInputPort7 + 3, "mah kan" }, + {"P2 Ron" , BIT_DIGITAL , DrvInputPort9 + 3, "mah ron" }, + {"P2 Reach" , BIT_DIGITAL , DrvInputPort8 + 3, "mah reach" }, + {"P2 Flip Flop" , BIT_DIGITAL , DrvInputPort11 + 4, "mah ff" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Mgakuen) + +static struct BurnInputInfo MarukinInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort7 + 2, "p2 start" }, + + {"P1 A" , BIT_DIGITAL , DrvInputPort1 + 7, "mah a" }, + {"P1 B" , BIT_DIGITAL , DrvInputPort2 + 7, "mah b" }, + {"P1 C" , BIT_DIGITAL , DrvInputPort4 + 7, "mah c" }, + {"P1 D" , BIT_DIGITAL , DrvInputPort5 + 7, "mah d" }, + {"P1 E" , BIT_DIGITAL , DrvInputPort1 + 6, "mah e" }, + {"P1 F" , BIT_DIGITAL , DrvInputPort2 + 6, "mah f" }, + {"P1 G" , BIT_DIGITAL , DrvInputPort4 + 6, "mah g" }, + {"P1 H" , BIT_DIGITAL , DrvInputPort5 + 6, "mah h" }, + {"P1 I" , BIT_DIGITAL , DrvInputPort1 + 5, "mah i" }, + {"P1 J" , BIT_DIGITAL , DrvInputPort2 + 5, "mah j" }, + {"P1 K" , BIT_DIGITAL , DrvInputPort4 + 5, "mah k" }, + {"P1 L" , BIT_DIGITAL , DrvInputPort5 + 5, "mah l" }, + {"P1 M" , BIT_DIGITAL , DrvInputPort1 + 4, "mah m" }, + {"P1 N" , BIT_DIGITAL , DrvInputPort2 + 4, "mah n" }, + {"P1 Pon" , BIT_DIGITAL , DrvInputPort5 + 4, "mah pon" }, + {"P1 Chi" , BIT_DIGITAL , DrvInputPort4 + 4, "mah chi" }, + {"P1 Kan" , BIT_DIGITAL , DrvInputPort1 + 3, "mah kan" }, + {"P1 Ron" , BIT_DIGITAL , DrvInputPort4 + 3, "mah ron" }, + {"P1 Reach" , BIT_DIGITAL , DrvInputPort2 + 3, "mah reach" }, + {"P1 Flip Flop" , BIT_DIGITAL , DrvInputPort6 + 4, "mah ff" }, + + {"P2 A" , BIT_DIGITAL , DrvInputPort7 + 7, "mah a" }, + {"P2 B" , BIT_DIGITAL , DrvInputPort8 + 7, "mah b" }, + {"P2 C" , BIT_DIGITAL , DrvInputPort9 + 7, "mah c" }, + {"P2 D" , BIT_DIGITAL , DrvInputPort10 + 7, "mah d" }, + {"P2 E" , BIT_DIGITAL , DrvInputPort7 + 6, "mah e" }, + {"P2 F" , BIT_DIGITAL , DrvInputPort8 + 6, "mah f" }, + {"P2 G" , BIT_DIGITAL , DrvInputPort9 + 6, "mah g" }, + {"P2 H" , BIT_DIGITAL , DrvInputPort10 + 6, "mah h" }, + {"P2 I" , BIT_DIGITAL , DrvInputPort7 + 5, "mah i" }, + {"P2 J" , BIT_DIGITAL , DrvInputPort8 + 5, "mah j" }, + {"P2 K" , BIT_DIGITAL , DrvInputPort9 + 5, "mah k" }, + {"P2 L" , BIT_DIGITAL , DrvInputPort10 + 5, "mah l" }, + {"P2 M" , BIT_DIGITAL , DrvInputPort7 + 4, "mah m" }, + {"P2 N" , BIT_DIGITAL , DrvInputPort2 + 4, "mah n" }, + {"P2 Pon" , BIT_DIGITAL , DrvInputPort10 + 4, "mah pon" }, + {"P2 Chi" , BIT_DIGITAL , DrvInputPort9 + 4, "mah chi" }, + {"P2 Kan" , BIT_DIGITAL , DrvInputPort7 + 3, "mah kan" }, + {"P2 Ron" , BIT_DIGITAL , DrvInputPort9 + 3, "mah ron" }, + {"P2 Reach" , BIT_DIGITAL , DrvInputPort8 + 3, "mah reach" }, + {"P2 Flip Flop" , BIT_DIGITAL , DrvInputPort11 + 4, "mah ff" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Marukin) + +static struct BurnInputInfo PkladiesInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort7 + 2, "p2 start" }, + + {"P1 A" , BIT_DIGITAL , DrvInputPort1 + 7, "mah a" }, + {"P1 B" , BIT_DIGITAL , DrvInputPort2 + 7, "mah b" }, + {"P1 C" , BIT_DIGITAL , DrvInputPort4 + 7, "mah c" }, + {"P1 D" , BIT_DIGITAL , DrvInputPort5 + 7, "mah d" }, + {"P1 E" , BIT_DIGITAL , DrvInputPort1 + 6, "mah e" }, + {"P1 Deal" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 1" }, + {"P1 Cancel" , BIT_DIGITAL , DrvInputPort2 + 5, "p1 fire 2" }, + {"P1 Flip" , BIT_DIGITAL , DrvInputPort4 + 5, "p1 fire 3" }, + + {"P2 A" , BIT_DIGITAL , DrvInputPort7 + 7, "mah a" }, + {"P2 B" , BIT_DIGITAL , DrvInputPort8 + 7, "mah b" }, + {"P2 C" , BIT_DIGITAL , DrvInputPort9 + 7, "mah c" }, + {"P2 D" , BIT_DIGITAL , DrvInputPort10 + 7, "mah d" }, + {"P2 E" , BIT_DIGITAL , DrvInputPort7 + 6, "mah e" }, + {"P2 Deal" , BIT_DIGITAL , DrvInputPort7 + 5, "p2 fire 1" }, + {"P2 Cancel" , BIT_DIGITAL , DrvInputPort8 + 5, "p2 fire 2" }, + {"P2 Flip" , BIT_DIGITAL , DrvInputPort9 + 5, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 0, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Pkladies) + +static struct BurnInputInfo PangInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Pang) + +static struct BurnInputInfo Qtono1InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 4" }, + + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Qtono1) + +static struct BurnInputInfo MstworldInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, +}; + +STDINPUTINFO(Mstworld) + +static struct BurnInputInfo BlockInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvInputPort11 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort11 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + + {"P2 Left" , BIT_DIGITAL , DrvInputPort11 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort11 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Block) + +static struct BurnInputInfo BlockjoyInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 6, "service" }, + {"Diagnostics" , BIT_DIGITAL , DrvInputPort3 + 1, "diag" }, +}; + +STDINPUTINFO(Blockjoy) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x30) == 0x30) { + *nJoystickInputs &= ~0x30; + } + if ((*nJoystickInputs & 0xc0) == 0xc0) { + *nJoystickInputs &= ~0xc0; + } +} + +static inline void DrvMakeInputs() +{ + for (INT32 i = 0; i < 12; i++) DrvInput[i] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + DrvInput[ 0] |= (DrvInputPort0[ i] & 1) << i; + DrvInput[ 1] |= (DrvInputPort1[ i] & 1) << i; + DrvInput[ 2] |= (DrvInputPort2[ i] & 1) << i; + DrvInput[ 3] |= (DrvInputPort3[ i] & 1) << i; + DrvInput[ 4] |= (DrvInputPort4[ i] & 1) << i; + DrvInput[ 5] |= (DrvInputPort5[ i] & 1) << i; + DrvInput[ 6] |= (DrvInputPort6[ i] & 1) << i; + DrvInput[ 7] |= (DrvInputPort7[ i] & 1) << i; + DrvInput[ 8] |= (DrvInputPort8[ i] & 1) << i; + DrvInput[ 9] |= (DrvInputPort9[ i] & 1) << i; + DrvInput[10] |= (DrvInputPort10[i] & 1) << i; + DrvInput[11] |= (DrvInputPort11[i] & 1) << i; + } + + if (DrvInputType == DRV_INPUT_TYPE_BLOCK) { + if (DrvInputPort11[0]) DrvDial1 -= 0x04; + if (DrvInputPort11[1]) DrvDial1 += 0x04; + if (DrvDial1 >= 0x100) DrvDial1 = 0; + if (DrvDial1 < 0) DrvDial1 = 0xfc; + + if (DrvInputPort11[2]) DrvDial2 -= 0x04; + if (DrvInputPort11[3]) DrvDial2 += 0x04; + if (DrvDial2 >= 0x100) DrvDial2 = 0; + if (DrvDial2 < 0) DrvDial2 = 0xfc; + } else { + if (DrvInputType != DRV_INPUT_TYPE_MAHJONG) { + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); + } + } +} + +static struct BurnDIPInfo MgakuenDIPList[]= +{ + // Default Values + {0x2c, 0xff, 0xff, 0xef, NULL }, + {0x2d, 0xff, 0xff, 0x8f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x2c, 0x01, 0x07, 0x00, "4 Coins 1 Play" }, + {0x2c, 0x01, 0x07, 0x01, "3 Coins 1 Play" }, + {0x2c, 0x01, 0x07, 0x02, "2 Coins 1 Play" }, + {0x2c, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x2c, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x2c, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x2c, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + {0x2c, 0x01, 0x07, 0x03, "1 Coin 6 Plays" }, + + {0 , 0xfe, 0 , 2 , "Rules" }, + {0x2c, 0x01, 0x08, 0x08, "Kantou" }, + {0x2c, 0x01, 0x08, 0x00, "Kansai" }, + + {0 , 0xfe, 0 , 2 , "Harness Type" }, + {0x2c, 0x01, 0x10, 0x10, "Generic" }, + {0x2c, 0x01, 0x10, 0x00, "Royal Mahjong" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x2c, 0x01, 0x20, 0x20, "Off" }, + {0x2c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x2c, 0x01, 0x40, 0x40, "Off" }, + {0x2c, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x2c, 0x01, 0x80, 0x80, "Off" }, + {0x2c, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Player 1 Skill" }, + {0x2d, 0x01, 0x03, 0x03, "Weak" }, + {0x2d, 0x01, 0x03, 0x02, "Normal" }, + {0x2d, 0x01, 0x03, 0x01, "Strong" }, + {0x2d, 0x01, 0x03, 0x00, "Very Strong" }, + + {0 , 0xfe, 0 , 4 , "Player 2 Skill" }, + {0x2d, 0x01, 0x0c, 0x0c, "Weak" }, + {0x2d, 0x01, 0x0c, 0x08, "Normal" }, + {0x2d, 0x01, 0x0c, 0x04, "Strong" }, + {0x2d, 0x01, 0x0c, 0x00, "Very Strong" }, + + {0 , 0xfe, 0 , 2 , "Music" }, + {0x2d, 0x01, 0x10, 0x10, "Off" }, + {0x2d, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x2d, 0x01, 0x20, 0x20, "Off" }, + {0x2d, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Help Mode" }, + {0x2d, 0x01, 0x40, 0x40, "Off" }, + {0x2d, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Mgakuen) + +static struct BurnDIPInfo MstworldDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xb0, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x15, 0x01, 0x07, 0x03, "A 1C/4P B 1C/4P" }, + {0x15, 0x01, 0x07, 0x02, "A 1C/3P B 1C/3P" }, + {0x15, 0x01, 0x07, 0x01, "A 1C/2P B 1C/2P" }, + {0x15, 0x01, 0x07, 0x00, "A 1C/1P B 1C/4P" }, + {0x15, 0x01, 0x07, 0x04, "A 2C/1P B 1C/2P" }, + {0x15, 0x01, 0x07, 0x05, "A 2C/1P B 1C/3P" }, + {0x15, 0x01, 0x07, 0x06, "A 3C/1P B 1C/2P" }, + {0x15, 0x01, 0x07, 0x07, "A 4C/1P B 1C/1P" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x18, 0x00, "1" }, + {0x15, 0x01, 0x18, 0x08, "2" }, + {0x15, 0x01, 0x18, 0x10, "3" }, + {0x15, 0x01, 0x18, 0x18, "4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x60, 0x00, "Easy" }, + {0x15, 0x01, 0x60, 0x20, "Normal" }, + {0x15, 0x01, 0x60, 0x40, "Hard" }, + {0x15, 0x01, 0x60, 0x60, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Mstworld) + +static struct BurnRomInfo MgakuenRomDesc[] = { + { "mg-1.1j", 0x08000, 0xbf02ea6b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mg-2.1l", 0x20000, 0x64141b0c, BRF_ESS | BRF_PRG }, // 1 + + { "mg-1.13h", 0x80000, 0xfd6a0805, BRF_GRA }, // 2 Characters + { "mg-2.14h", 0x80000, 0xe26e871e, BRF_GRA }, // 3 + { "mg-3.16h", 0x80000, 0xdd781d9a, BRF_GRA }, // 4 + { "mg-4.17h", 0x80000, 0x97afcc79, BRF_GRA }, // 5 + + { "mg-6.4l", 0x20000, 0x34594e62, BRF_GRA }, // 6 Sprites + { "mg-7.6l", 0x20000, 0xf304c806, BRF_GRA }, // 7 + + { "mg-5.1c", 0x80000, 0x170332f1, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Mgakuen) +STD_ROM_FN(Mgakuen) + +static struct BurnRomInfo SeventoitsuRomDesc[] = { + { "mc01.1j", 0x08000, 0x0bebe45f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mc02.1l", 0x20000, 0x375378b0, BRF_ESS | BRF_PRG }, // 1 + + { "mg-1.13h", 0x80000, 0xfd6a0805, BRF_GRA }, // 2 Characters + { "mg-2.14h", 0x80000, 0xe26e871e, BRF_GRA }, // 3 + { "mg-3.16h", 0x80000, 0xdd781d9a, BRF_GRA }, // 4 + { "mg-4.17h", 0x80000, 0x97afcc79, BRF_GRA }, // 5 + + { "mc06.4l", 0x20000, 0x0ef83926, BRF_GRA }, // 6 Sprites + { "mc07.6l", 0x20000, 0x59f9ffb1, BRF_GRA }, // 7 + + { "mg-5.1c", 0x80000, 0x170332f1, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Seventoitsu) +STD_ROM_FN(Seventoitsu) + +static struct BurnRomInfo Mgakuen2RomDesc[] = { + { "mg2-xf.1j", 0x08000, 0xc8165d2d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mg2-y.1l", 0x20000, 0x75bbcc14, BRF_ESS | BRF_PRG }, // 1 + { "mg2-z.3l", 0x20000, 0xbfdba961, BRF_ESS | BRF_PRG }, // 2 + + { "mg2-a.13h", 0x80000, 0x31a0c55e, BRF_GRA }, // 3 Characters + { "mg2-b.14h", 0x80000, 0xc18488fa, BRF_GRA }, // 4 + { "mg2-c.16h", 0x80000, 0x9425b364, BRF_GRA }, // 5 + { "mg2-d.17h", 0x80000, 0x6cc9eeba, BRF_GRA }, // 6 + + { "mg2-f.4l", 0x20000, 0x3172c9fe, BRF_GRA }, // 7 Sprites + { "mg2-g.6l", 0x20000, 0x19b8b61c, BRF_GRA }, // 8 + + { "mg2-e.1c", 0x80000, 0x70fd0809, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Mgakuen2) +STD_ROM_FN(Mgakuen2) + +static struct BurnRomInfo PkladiesRomDesc[] = { + { "pko-prg1.14f", 0x08000, 0x86585a94, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "pko-prg2.15f", 0x10000, 0x86cbe82d, BRF_ESS | BRF_PRG }, // 1 + + { "pko-001.8h", 0x80000, 0x1ead5d9b, BRF_GRA }, // 2 Characters + { "pko-003.8j", 0x80000, 0x339ab4e6, BRF_GRA }, // 3 + { "pko-002.9h", 0x80000, 0x1cf02586, BRF_GRA }, // 4 + { "pko-004.9j", 0x80000, 0x09ccb442, BRF_GRA }, // 5 + + { "pko-chr1.2j", 0x20000, 0x31ce33cd, BRF_GRA }, // 6 Sprites + { "pko-chr2.3j", 0x20000, 0xad7e055f, BRF_GRA }, // 7 + + { "pko-voi1.2d", 0x20000, 0x07e0f531, BRF_SND }, // 8 Samples + { "pko-voi2.3d", 0x20000, 0x18398bf6, BRF_SND }, // 9 +}; + +STD_ROM_PICK(Pkladies) +STD_ROM_FN(Pkladies) + +static struct BurnRomInfo PkladieslRomDesc[] = { + { "pk05.14f", 0x08000, 0xea1740a6, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "pk06.15f", 0x20000, 0x3078ff5e, BRF_ESS | BRF_PRG }, // 1 + + { "pko-001.8h", 0x80000, 0x1ead5d9b, BRF_GRA }, // 2 Characters + { "pko-003.8j", 0x80000, 0x339ab4e6, BRF_GRA }, // 3 + { "pko-002.9h", 0x80000, 0x1cf02586, BRF_GRA }, // 4 + { "pko-004.9j", 0x80000, 0x09ccb442, BRF_GRA }, // 5 + + { "pko-chr1.2j", 0x20000, 0x31ce33cd, BRF_GRA }, // 6 Sprites + { "pko-chr2.3j", 0x20000, 0xad7e055f, BRF_GRA }, // 7 + + { "pko-voi1.2d", 0x20000, 0x07e0f531, BRF_SND }, // 8 Samples + { "pko-voi2.3d", 0x20000, 0x18398bf6, BRF_SND }, // 9 +}; + +STD_ROM_PICK(Pkladiesl) +STD_ROM_FN(Pkladiesl) + +static struct BurnRomInfo PkladieslaRomDesc[] = { + { "05.14f", 0x08000, 0xfa18e16a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "06.15f", 0x10000, 0xa2fb7646, BRF_ESS | BRF_PRG }, // 1 + + { "pko-001.8h", 0x80000, 0x1ead5d9b, BRF_GRA }, // 2 Characters + { "pko-003.8j", 0x80000, 0x339ab4e6, BRF_GRA }, // 3 + { "pko-002.9h", 0x80000, 0x1cf02586, BRF_GRA }, // 4 + { "pko-004.9j", 0x80000, 0x09ccb442, BRF_GRA }, // 5 + + { "pko-chr1.2j", 0x20000, 0x31ce33cd, BRF_GRA }, // 6 Sprites + { "pko-chr2.3j", 0x20000, 0xad7e055f, BRF_GRA }, // 7 + + { "pko-voi1.2d", 0x20000, 0x07e0f531, BRF_SND }, // 8 Samples + { "pko-voi2.3d", 0x20000, 0x18398bf6, BRF_SND }, // 9 +}; + +STD_ROM_PICK(Pkladiesla) +STD_ROM_FN(Pkladiesla) + +static struct BurnRomInfo DokabenRomDesc[] = { + { "db06.11h", 0x08000, 0x413e0886, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "db07.13h", 0x20000, 0x8bdcf49e, BRF_ESS | BRF_PRG }, // 1 + { "db08.14h", 0x20000, 0x1643bdd9, BRF_ESS | BRF_PRG }, // 2 + + { "db02.1e", 0x20000, 0x9aa8470c, BRF_GRA }, // 3 Characters + { "db03.2e", 0x20000, 0x3324e43d, BRF_GRA }, // 4 + { "db04.1g", 0x20000, 0xc0c5b6c2, BRF_GRA }, // 5 + { "db05.2g", 0x20000, 0xd2ab25f2, BRF_GRA }, // 6 + + { "db10.2k", 0x20000, 0x9e70f7ae, BRF_GRA }, // 7 Sprites + { "db09.1k", 0x20000, 0x2d9263f7, BRF_GRA }, // 8 + + { "db01.1d", 0x20000, 0x62fa6b81, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Dokaben) +STD_ROM_FN(Dokaben) + +static struct BurnRomInfo PangRomDesc[] = { + { "pang6.bin", 0x08000, 0x68be52cd, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "pang7.bin", 0x20000, 0x4a2e70f6, BRF_ESS | BRF_PRG }, // 1 + + { "pang_09.bin", 0x20000, 0x3a5883f5, BRF_GRA }, // 2 Characters + { "bb3.bin", 0x20000, 0x79a8ed08, BRF_GRA }, // 3 + { "pang_11.bin", 0x20000, 0x166a16ae, BRF_GRA }, // 4 + { "bb5.bin", 0x20000, 0x2fb3db6c, BRF_GRA }, // 5 + + { "bb10.bin", 0x20000, 0xfdba4f6e, BRF_GRA }, // 6 Sprites + { "bb9.bin", 0x20000, 0x39f47a63, BRF_GRA }, // 7 + + { "bb1.bin", 0x20000, 0xc52e5b8e, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Pang) +STD_ROM_FN(Pang) + +static struct BurnRomInfo BbrosRomDesc[] = { + { "bb6.bin", 0x08000, 0xa3041ca4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bb7.bin", 0x20000, 0x09231c68, BRF_ESS | BRF_PRG }, // 1 + + { "bb2.bin", 0x20000, 0x62f29992, BRF_GRA }, // 2 Characters + { "bb3.bin", 0x20000, 0x79a8ed08, BRF_GRA }, // 3 + { "bb4.bin", 0x20000, 0xf705aa89, BRF_GRA }, // 4 + { "bb5.bin", 0x20000, 0x2fb3db6c, BRF_GRA }, // 5 + + { "bb10.bin", 0x20000, 0xfdba4f6e, BRF_GRA }, // 6 Sprites + { "bb9.bin", 0x20000, 0x39f47a63, BRF_GRA }, // 7 + + { "bb1.bin", 0x20000, 0xc52e5b8e, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Bbros) +STD_ROM_FN(Bbros) + +static struct BurnRomInfo PompingwRomDesc[] = { + { "pwj_06.11h", 0x08000, 0x4a0a6426, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "pwj_07.13h", 0x20000, 0xa9402420, BRF_ESS | BRF_PRG }, // 1 + + { "pw_02.1e", 0x20000, 0x4b5992e4, BRF_GRA }, // 2 Characters + { "bb3.bin", 0x20000, 0x79a8ed08, BRF_GRA }, // 3 + { "pwj_04.1g", 0x20000, 0x01e49081, BRF_GRA }, // 4 + { "bb5.bin", 0x20000, 0x2fb3db6c, BRF_GRA }, // 5 + + { "bb10.bin", 0x20000, 0xfdba4f6e, BRF_GRA }, // 6 Sprites + { "bb9.bin", 0x20000, 0x39f47a63, BRF_GRA }, // 7 + + { "bb1.bin", 0x20000, 0xc52e5b8e, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Pompingw) +STD_ROM_FN(Pompingw) + +static struct BurnRomInfo PangbRomDesc[] = { + { "pang_04.bin", 0x10000, 0xf68f88a5, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "pang_02.bin", 0x20000, 0x3f15bb61, BRF_ESS | BRF_PRG }, // 1 + { "pang_03.bin", 0x20000, 0x0c8477ae, BRF_ESS | BRF_PRG }, // 2 + + { "pang_09.bin", 0x20000, 0x3a5883f5, BRF_GRA }, // 3 Characters + { "bb3.bin", 0x20000, 0x79a8ed08, BRF_GRA }, // 4 + { "pang_11.bin", 0x20000, 0x166a16ae, BRF_GRA }, // 5 + { "bb5.bin", 0x20000, 0x2fb3db6c, BRF_GRA }, // 6 + + { "bb10.bin", 0x20000, 0xfdba4f6e, BRF_GRA }, // 7 Sprites + { "bb9.bin", 0x20000, 0x39f47a63, BRF_GRA }, // 8 + + { "bb1.bin", 0x20000, 0xc52e5b8e, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Pangb) +STD_ROM_FN(Pangb) + +static struct BurnRomInfo PangboldRomDesc[] = { + { "4.6l", 0x10000, 0xf68f88a5, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "2.3l", 0x20000, 0x3f15bb61, BRF_ESS | BRF_PRG }, // 1 + { "3.5l", 0x20000, 0xce6375e4, BRF_ESS | BRF_PRG }, // 2 + + { "9.10o", 0x20000, 0x3a5883f5, BRF_GRA }, // 3 Characters + { "10.14o", 0x20000, 0x79a8ed08, BRF_GRA }, // 4 + { "11.17j", 0x20000, 0x166a16ae, BRF_GRA }, // 5 + { "12.20j", 0x20000, 0x2fb3db6c, BRF_GRA }, // 6 + + { "8.7o", 0x10000, 0xf3188aa1, BRF_GRA }, // 7 Sprites + { "7.5o", 0x10000, 0x011da14b, BRF_GRA }, // 8 + { "6.3o", 0x10000, 0x0e25e797, BRF_GRA }, // 9 + { "5.1o", 0x10000, 0x6daa4e27, BRF_GRA }, // 10 + + { "1.1a", 0x10000, 0xb6463907, BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(Pangbold) +STD_ROM_FN(Pangbold) + +static struct BurnRomInfo CworldRomDesc[] = { + { "cw05.bin", 0x08000, 0xd3c1723d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "cw06.bin", 0x20000, 0xd71ed4a3, BRF_ESS | BRF_PRG }, // 1 + { "cw07.bin", 0x20000, 0xd419ce08, BRF_ESS | BRF_PRG }, // 2 + + { "cw08.bin", 0x20000, 0x6c80da3c, BRF_GRA }, // 3 Characters + { "cw09.bin", 0x20000, 0x7607da71, BRF_GRA }, // 4 + { "cw10.bin", 0x20000, 0x6f0e639f, BRF_GRA }, // 5 + { "cw11.bin", 0x20000, 0x130bd7c0, BRF_GRA }, // 6 + { "cw18.bin", 0x20000, 0xbe6ee0c9, BRF_GRA }, // 7 + { "cw19.bin", 0x20000, 0x51fc5532, BRF_GRA }, // 8 + { "cw20.bin", 0x20000, 0x58381d58, BRF_GRA }, // 9 + { "cw21.bin", 0x20000, 0x910cc753, BRF_GRA }, // 10 + + { "cw16.bin", 0x20000, 0xf90217d1, BRF_GRA }, // 11 Sprites + { "cw17.bin", 0x20000, 0xc953c702, BRF_GRA }, // 12 + + { "cw01.bin", 0x20000, 0xf4368f5b, BRF_SND }, // 13 Samples +}; + +STD_ROM_PICK(Cworld) +STD_ROM_FN(Cworld) + +static struct BurnRomInfo HatenaRomDesc[] = { + { "q2-05.rom", 0x08000, 0x66c9e1da, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "q2-06.rom", 0x20000, 0x5fc39916, BRF_ESS | BRF_PRG }, // 1 + { "q2-07.rom", 0x20000, 0xec6d5e5e, BRF_ESS | BRF_PRG }, // 2 + + { "q2-08.rom", 0x20000, 0x6c80da3c, BRF_GRA }, // 3 Characters + { "q2-09.rom", 0x20000, 0xabe3e15c, BRF_GRA }, // 4 + { "q2-10.rom", 0x20000, 0x6963450d, BRF_GRA }, // 5 + { "q2-11.rom", 0x20000, 0x1e319fa2, BRF_GRA }, // 6 + { "q2-18.rom", 0x20000, 0xbe6ee0c9, BRF_GRA }, // 7 + { "q2-19.rom", 0x20000, 0x70300445, BRF_GRA }, // 8 + { "q2-20.rom", 0x20000, 0x21a6ff42, BRF_GRA }, // 9 + { "q2-21.rom", 0x20000, 0x076280c9, BRF_GRA }, // 10 + + { "q2-16.rom", 0x20000, 0xec19b2f0, BRF_GRA }, // 11 Sprites + { "q2-17.rom", 0x20000, 0xecd69d92, BRF_GRA }, // 12 + + { "q2-01.rom", 0x20000, 0x149e7a89, BRF_SND }, // 13 Samples +}; + +STD_ROM_PICK(Hatena) +STD_ROM_FN(Hatena) + +static struct BurnRomInfo SpangRomDesc[] = { + { "spe_06.rom", 0x08000, 0x1af106fb, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "spe_07.rom", 0x20000, 0x208b5f54, BRF_ESS | BRF_PRG }, // 1 + { "spe_08.rom", 0x20000, 0x2bc03ade, BRF_ESS | BRF_PRG }, // 2 + + { "spe_02.rom", 0x20000, 0x63c9dfd2, BRF_GRA }, // 3 Characters + { "03.f2", 0x20000, 0x3ae28bc1, BRF_GRA }, // 4 + { "spe_04.rom", 0x20000, 0x9d7b225b, BRF_GRA }, // 5 + { "05.g2", 0x20000, 0x4a060884, BRF_GRA }, // 6 + + { "spj10_2k.bin", 0x20000, 0xeedd0ade, BRF_GRA }, // 7 Sprites + { "spj09_1k.bin", 0x20000, 0x04b41b75, BRF_GRA }, // 8 + + { "spe_01.rom", 0x20000, 0x2d19c133, BRF_SND }, // 9 Samples + + { "eeprom-spang.bin", 0x80, 0xdeae1291, BRF_PRG }, +}; + +STD_ROM_PICK(Spang) +STD_ROM_FN(Spang) + +static struct BurnRomInfo SpangjRomDesc[] = { + { "spj_11h.bin", 0x08000, 0x1a548b0b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "spj7_13h.bin", 0x20000, 0x14c2b765, BRF_ESS | BRF_PRG }, // 1 + { "spj8_14h.bin", 0x20000, 0x4be4e5b7, BRF_ESS | BRF_PRG }, // 2 + + { "spj02_1e.bin", 0x20000, 0x419f69d7, BRF_GRA }, // 3 Characters + { "03.f2", 0x20000, 0x3ae28bc1, BRF_GRA }, // 4 + { "spj04_1g.bin", 0x20000, 0x6870506f, BRF_GRA }, // 5 + { "05.g2", 0x20000, 0x4a060884, BRF_GRA }, // 6 + + { "spj10_2k.bin", 0x20000, 0xeedd0ade, BRF_GRA }, // 7 Sprites + { "spj09_1k.bin", 0x20000, 0x04b41b75, BRF_GRA }, // 8 + + { "01.d1", 0x20000, 0xb96ea126, BRF_SND }, // 9 Samples + + { "eeprom-spangj.bin",0x80, 0x237c00eb, BRF_PRG }, +}; + +STD_ROM_PICK(Spangj) +STD_ROM_FN(Spangj) + +static struct BurnRomInfo SbbrosRomDesc[] = { + { "06.j12", 0x08000, 0x292eee6a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "07.j13", 0x20000, 0xf46b698d, BRF_ESS | BRF_PRG }, // 1 + { "08.j14", 0x20000, 0xa75e7fbe, BRF_ESS | BRF_PRG }, // 2 + + { "02.f1", 0x20000, 0x0c22ffc6, BRF_GRA }, // 3 Characters + { "03.f2", 0x20000, 0x3ae28bc1, BRF_GRA }, // 4 + { "04.g2", 0x20000, 0xbb3dee5b, BRF_GRA }, // 5 + { "05.g2", 0x20000, 0x4a060884, BRF_GRA }, // 6 + + { "10.l2", 0x20000, 0xd6675d8f, BRF_GRA }, // 7 Sprites + { "09.l1", 0x20000, 0x8f678bc8, BRF_GRA }, // 8 + + { "01.d1", 0x20000, 0xb96ea126, BRF_SND }, // 9 Samples + + { "eeprom-sbbros.bin",0x80, 0xed69d3cd, BRF_PRG }, +}; + +STD_ROM_PICK(Sbbros) +STD_ROM_FN(Sbbros) + +static struct BurnRomInfo MstworldRomDesc[] = { + { "mw-1.rom", 0x80000, 0xc4e51fb4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + + { "mw-2.rom", 0x08000, 0x12c4fea9, BRF_ESS | BRF_PRG }, // 1 Z80 #2 Program Code + + { "mw-4.rom", 0x20000, 0x28a3af15, BRF_GRA }, // 2 Characters + { "mw-5.rom", 0x20000, 0xffdf7e9f, BRF_GRA }, // 3 + { "mw-6.rom", 0x20000, 0x1ed773a3, BRF_GRA }, // 4 + { "mw-7.rom", 0x20000, 0x8eb7525c, BRF_GRA }, // 5 + + { "mw-8.rom", 0x20000, 0xb9b92a3c, BRF_GRA }, // 6 Sprites + { "mw-9.rom", 0x20000, 0x75fc3375, BRF_GRA }, // 7 + + { "mw-3.rom", 0x80000, 0x110c6a68, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Mstworld) +STD_ROM_FN(Mstworld) + +static struct BurnRomInfo MarukinRomDesc[] = { + { "mg3-01.9d", 0x08000, 0x04357973, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mg3-02.10d", 0x20000, 0x50d08da0, BRF_ESS | BRF_PRG }, // 1 + + { "mg3-a.3k", 0x80000, 0x420f1de7, BRF_GRA }, // 2 Characters + { "mg3-b.4k", 0x80000, 0xd8de13fa, BRF_GRA }, // 3 + { "mg3-c.6k", 0x80000, 0xfbeb66e8, BRF_GRA }, // 4 + { "mg3-d.7k", 0x80000, 0x8f6bd831, BRF_GRA }, // 5 + + { "mg3-05.2g", 0x20000, 0x7a738d2d, BRF_GRA }, // 6 Sprites + { "mg3-04.1g", 0x20000, 0x56f30515, BRF_GRA }, // 7 + + { "mg3-e.1d", 0x80000, 0x106c2fa9, BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(Marukin) +STD_ROM_FN(Marukin) + +static struct BurnRomInfo Qtono1RomDesc[] = { + { "q3-05.rom", 0x08000, 0x1dd0a344, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "q3-06.rom", 0x20000, 0xbd6a2110, BRF_ESS | BRF_PRG }, // 1 + { "q3-07.rom", 0x20000, 0x61e53c4f, BRF_ESS | BRF_PRG }, // 2 + + { "q3-08.rom", 0x20000, 0x1533b978, BRF_GRA }, // 3 Characters + { "q3-09.rom", 0x20000, 0xa32db2f2, BRF_GRA }, // 4 + { "q3-10.rom", 0x20000, 0xed681aa8, BRF_GRA }, // 5 + { "q3-11.rom", 0x20000, 0x38b2fd10, BRF_GRA }, // 6 + { "q3-18.rom", 0x20000, 0x9e4292ac, BRF_GRA }, // 7 + { "q3-19.rom", 0x20000, 0xb7f6d40f, BRF_GRA }, // 8 + { "q3-20.rom", 0x20000, 0x6cd7f38d, BRF_GRA }, // 9 + { "q3-21.rom", 0x20000, 0xb4aa6b4b, BRF_GRA }, // 10 + + { "q3-16.rom", 0x20000, 0x863d6836, BRF_GRA }, // 11 Sprites + { "q3-17.rom", 0x20000, 0x459bf59c, BRF_GRA }, // 12 + + { "q3-01.rom", 0x20000, 0x6c1be591, BRF_SND }, // 13 Samples +}; + +STD_ROM_PICK(Qtono1) +STD_ROM_FN(Qtono1) + +static struct BurnRomInfo QsangokuRomDesc[] = { + { "q4-05c.rom", 0x08000, 0xe1d010b4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "q4-06.rom", 0x20000, 0xa0301849, BRF_ESS | BRF_PRG }, // 1 + { "q4-07.rom", 0x20000, 0x2941ef5b, BRF_ESS | BRF_PRG }, // 2 + + { "q4-08.rom", 0x20000, 0xdc84c6cb, BRF_GRA }, // 3 Characters + { "q4-09.rom", 0x20000, 0xcbb6234c, BRF_GRA }, // 4 + { "q4-10.rom", 0x20000, 0xc20a27a8, BRF_GRA }, // 5 + { "q4-11.rom", 0x20000, 0x4ff66aed, BRF_GRA }, // 6 + { "q4-18.rom", 0x20000, 0xca3acea5, BRF_GRA }, // 7 + { "q4-19.rom", 0x20000, 0x1fd92b7d, BRF_GRA }, // 8 + { "q4-20.rom", 0x20000, 0xb02dc6a1, BRF_GRA }, // 9 + { "q4-21.rom", 0x20000, 0x432b1dc1, BRF_GRA }, // 10 + + { "q4-16.rom", 0x20000, 0x77342320, BRF_GRA }, // 11 Sprites + { "q4-17.rom", 0x20000, 0x1275c436, BRF_GRA }, // 12 + + { "q4-01.rom", 0x20000, 0x5d0d07d8, BRF_SND }, // 13 Samples +}; + +STD_ROM_PICK(Qsangoku) +STD_ROM_FN(Qsangoku) + +static struct BurnRomInfo BlockRomDesc[] = { + { "ble_05.rom", 0x08000, 0xc12e7f4c, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ble_06.rom", 0x20000, 0xcdb13d55, BRF_ESS | BRF_PRG }, // 1 + { "ble_07.rom", 0x20000, 0x1d114f13, BRF_ESS | BRF_PRG }, // 2 + + { "bl_08.rom", 0x20000, 0xaa0f4ff1, BRF_GRA }, // 3 Characters + { "bl_09.rom", 0x20000, 0x6fa8c186, BRF_GRA }, // 4 + { "bl_18.rom", 0x20000, 0xc0acafaf, BRF_GRA }, // 5 + { "bl_19.rom", 0x20000, 0x1ae942f5, BRF_GRA }, // 6 + + { "bl_16.rom", 0x20000, 0xfadcaff7, BRF_GRA }, // 7 Sprites + { "bl_17.rom", 0x20000, 0x5f8cab42, BRF_GRA }, // 8 + + { "bl_01.rom", 0x20000, 0xc2ec2abb, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Block) +STD_ROM_FN(Block) + +static struct BurnRomInfo BlockjRomDesc[] = { + { "blj_05.rom", 0x08000, 0x3b55969a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ble_06.rom", 0x20000, 0xcdb13d55, BRF_ESS | BRF_PRG }, // 1 + { "blj_07.rom", 0x20000, 0x1723883c, BRF_ESS | BRF_PRG }, // 2 + + { "bl_08.rom", 0x20000, 0xaa0f4ff1, BRF_GRA }, // 3 Characters + { "bl_09.rom", 0x20000, 0x6fa8c186, BRF_GRA }, // 4 + { "bl_18.rom", 0x20000, 0xc0acafaf, BRF_GRA }, // 5 + { "bl_19.rom", 0x20000, 0x1ae942f5, BRF_GRA }, // 6 + + { "bl_16.rom", 0x20000, 0xfadcaff7, BRF_GRA }, // 7 Sprites + { "bl_17.rom", 0x20000, 0x5f8cab42, BRF_GRA }, // 8 + + { "bl_01.rom", 0x20000, 0xc2ec2abb, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Blockj) +STD_ROM_FN(Blockj) + +static struct BurnRomInfo BlockjoyRomDesc[] = { + { "ble_05.bin", 0x08000, 0xfa2a4536, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "blf_06.bin", 0x20000, 0xe114ebde, BRF_ESS | BRF_PRG }, // 1 + { "ble_07.rom", 0x20000, 0x1d114f13, BRF_ESS | BRF_PRG }, // 2 + + { "bl_08.rom", 0x20000, 0xaa0f4ff1, BRF_GRA }, // 3 Characters + { "bl_09.rom", 0x20000, 0x6fa8c186, BRF_GRA }, // 4 + { "bl_18.rom", 0x20000, 0xc0acafaf, BRF_GRA }, // 5 + { "bl_19.rom", 0x20000, 0x1ae942f5, BRF_GRA }, // 6 + + { "bl_16.rom", 0x20000, 0xfadcaff7, BRF_GRA }, // 7 Sprites + { "bl_17.rom", 0x20000, 0x5f8cab42, BRF_GRA }, // 8 + + { "bl_01.rom", 0x20000, 0xc2ec2abb, BRF_SND }, // 9 Samples +}; + +STD_ROM_PICK(Blockjoy) +STD_ROM_FN(Blockjoy) + +static struct BurnRomInfo BlockblRomDesc[] = { + { "m7.l6", 0x10000, 0x3b576fd9, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "m5.l3", 0x40000, 0x7c988bb7, BRF_ESS | BRF_PRG }, // 1 + { "m6.l5", 0x20000, 0x5768d8eb, BRF_ESS | BRF_PRG }, // 2 + + { "m12.o10", 0x20000, 0x963154d9, BRF_GRA }, // 3 Characters + { "m13.o14", 0x20000, 0x069480bb, BRF_GRA }, // 4 + { "m4.j17", 0x20000, 0x9e3b6f4f, BRF_GRA }, // 5 + { "m3.j20", 0x20000, 0x629d58fe, BRF_GRA }, // 6 + + { "m11.o7", 0x10000, 0x255180a5, BRF_GRA }, // 7 Sprites + { "m10.o5", 0x10000, 0x3201c088, BRF_GRA }, // 8 + { "m9.o3", 0x10000, 0x29357fe4, BRF_GRA }, // 9 + { "m8.o2", 0x10000, 0xabd665d1, BRF_GRA }, // 10 + + { "bl_01.rom", 0x20000, 0xc2ec2abb, BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(Blockbl) +STD_ROM_FN(Blockbl) + +static const eeprom_interface MitchellEEPROMIntf = +{ + 6, + 16, + "0110", + "0101", + "0111", + 0, + 0, + 0, + 0 +}; + +static INT32 MgakuenMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom = Next; Next += 0x50000; + MSM6295ROM = Next; Next += 0x40000; + DrvSoundRom = Next; Next += 0x80000; + + RamStart = Next; + + DrvZ80Ram = Next; Next += 0x01000; + DrvPaletteRam = Next; Next += 0x00800; + DrvAttrRam = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x01000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x10000 * 8 * 8; + DrvSprites = Next; Next += 0x00800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 PangMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom = Next; Next += 0x50000; + DrvZ80Code = Next; Next += 0x50000; + DrvSoundRom = Next; Next += 0x20000; + + RamStart = Next; + + DrvZ80Ram = Next; Next += 0x02000; + DrvPaletteRam = Next; Next += 0x01000; + DrvAttrRam = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x01000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x8000 * 8 * 8; + DrvSprites = Next; Next += 0x0800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 MahjongMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom = Next; Next += 0x50000; + DrvZ80Code = Next; Next += 0x50000; + MSM6295ROM = Next; Next += 0x40000; + DrvSoundRom = Next; Next += 0x80000; + + RamStart = Next; + + DrvZ80Ram = Next; Next += 0x02000; + DrvPaletteRam = Next; Next += 0x01000; + DrvAttrRam = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x01000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x10000 * 8 * 8; + DrvSprites = Next; Next += 0x00800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 MstworldMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom = Next; Next += 0x50000; + DrvZ80Code = Next; Next += 0x50000; + DrvZ80Rom2 = Next; Next += 0x08000; + MSM6295ROM = Next; Next += 0x40000; + DrvSoundRom = Next; Next += 0x100000; + + RamStart = Next; + + DrvZ80Ram = Next; Next += 0x02000; + DrvZ80Ram2 = Next; Next += 0x00800; + DrvPaletteRam = Next; Next += 0x01000; + DrvAttrRam = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x01000; + + RamEnd = Next; + + DrvChars = Next; Next += 0x4000 * 8 * 8; + DrvSprites = Next; Next += 0x0800 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + ZetOpen(0); + DrvRomBank = 0; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + if (DrvHasEEPROM) { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } else { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } + ZetReset(); + ZetClose(); + + BurnYM2413Reset(); + MSM6295Reset(0); + + if (DrvHasEEPROM) EEPROMReset(); + + DrvPaletteRamBank = 0; + DrvVideoBank = 0; + DrvDialSelected = 0; + + return 0; +} + +static INT32 MstworldDoReset() +{ + ZetOpen(0); + DrvRomBank = 0; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + + DrvPaletteRamBank = 0; + DrvVideoBank = 0; + DrvSoundLatch = 0; + + return 0; +} + +static UINT8 BlockDialRead(INT32 Offset) +{ + static INT32 Dir[2]; + + if (DrvDialSelected) { + INT32 Delta; + + Delta = ((Offset ? DrvDial2 : DrvDial1) - DrvDial[Offset]) & 0xff; + if (Delta & 0x80) { + Delta = (-Delta) & 0xff; + if (Dir[Offset]) { + Dir[Offset] = 0; + Delta = 0; + } + } else { + if (Delta > 0) { + if (Dir[Offset] == 0) { + Dir[Offset] = 1; + Delta = 0; + } + } + } + + if (Delta > 0x3f) Delta = 0x3f; + + return Delta << 2; + } else { + INT32 Res = (0xff - DrvInput[Offset + 1]) & 0xf7; + if (Dir[Offset]) Res |= 0x08; + + return Res; + } +} + +UINT8 __fastcall MitchellZ80Read(UINT16 a) +{ + if (a >= 0xc000 && a <= 0xc7ff) { + return DrvPaletteRam[(a - 0xc000) + (DrvPaletteRamBank ? 0x800 : 0x000)]; + } + + if (a >= 0xd000 && a <= 0xdfff) { + INT32 Offset = a - 0xd000; + if (DrvVideoBank) { + return DrvSpriteRam[Offset]; + } else { + return DrvVideoRam[Offset]; + } + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall MitchellZ80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xc000 && a <= 0xc7ff) { + DrvPaletteRam[(a - 0xc000) + (DrvPaletteRamBank ? 0x800 : 0x000)] = d; + return; + } + + if (a >= 0xd000 && a <= 0xdfff) { + INT32 Offset = a - 0xd000; + if (DrvVideoBank) { + DrvSpriteRam[Offset] = d; + } else { + DrvVideoRam[Offset] = d; + } + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MitchellZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - DrvInput[0]; + } + + case 0x01: { + switch (DrvInputType) { + case DRV_INPUT_TYPE_MAHJONG: { + if (DrvMahjongKeyMatrix & (0x80 >> 0)) return 0xff - DrvInput[1]; + if (DrvMahjongKeyMatrix & (0x80 >> 1)) return 0xff - DrvInput[2]; + if (DrvMahjongKeyMatrix & (0x80 >> 2)) return 0xff - DrvInput[4]; + if (DrvMahjongKeyMatrix & (0x80 >> 3)) return 0xff - DrvInput[5]; + if (DrvMahjongKeyMatrix & (0x80 >> 4)) return 0xff - DrvInput[6]; + } + + case DRV_INPUT_TYPE_BLOCK: { + return BlockDialRead(0); + } + } + + return 0xff - DrvInput[1]; + } + + case 0x02: { + switch (DrvInputType) { + case DRV_INPUT_TYPE_MAHJONG: { + if (DrvMahjongKeyMatrix & (0x80 >> 0)) return 0xff - DrvInput[7]; + if (DrvMahjongKeyMatrix & (0x80 >> 1)) return 0xff - DrvInput[8]; + if (DrvMahjongKeyMatrix & (0x80 >> 2)) return 0xff - DrvInput[9]; + if (DrvMahjongKeyMatrix & (0x80 >> 3)) return 0xff - DrvInput[10]; + if (DrvMahjongKeyMatrix & (0x80 >> 4)) return 0xff - DrvInput[11]; + } + + case DRV_INPUT_TYPE_BLOCK: { + return BlockDialRead(1); + } + } + + return 0xff - DrvInput[2]; + } + + case 0x03: { + return DrvDip[0]; + } + + case 0x04: { + return DrvDip[1]; + } + + case 0x05: { + INT32 Bit = DrvHasEEPROM ? (EEPROMRead() & 0x01) << 7 : 0x80; + if (DrvInput5Toggle) { + Bit |= 0x01; + } else { + Bit |= 0x08; + } + + if (DrvPort5Kludge) Bit ^= 0x08; + + return ((0xff - DrvInput[3]) & 0x76) | Bit; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0xff; +} + +void __fastcall MitchellZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DrvFlipScreen = d & 0x04; + if (DrvOkiBank != (d & 0x10)) { + DrvOkiBank = d & 0x10; + if (DrvOkiBank) { + memcpy(MSM6295ROM, DrvSoundRom + 0x40000, 0x40000); + } else { + memcpy(MSM6295ROM, DrvSoundRom + 0x00000, 0x40000); + } + } + DrvPaletteRamBank = d & 0x20; + return; + } + + case 0x01: { + switch (DrvInputType) { + case DRV_INPUT_TYPE_MAHJONG: { + DrvMahjongKeyMatrix = d; + return; + } + + case DRV_INPUT_TYPE_BLOCK: { + if (d == 0x08) { + DrvDial[0] = DrvDial1; + DrvDial[1] = DrvDial2; + } else { + if (d == 0x80) { + DrvDialSelected = 0; + } else { + DrvDialSelected = 1; + } + } + return; + } + } + + return; + } + + case 0x02: { + DrvRomBank = d & 0x0f; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + if (DrvHasEEPROM) { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } else { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } + return; + } + + case 0x03: { + BurnYM2413Write(1, d); + return; + } + + case 0x04: { + BurnYM2413Write(0, d); + return; + } + + case 0x05: { + MSM6295Command(0, d); + return; + } + + case 0x06:{ + // nop + return; + } + + case 0x07: { + DrvVideoBank = d; + return; + } + + case 0x08 :{ + if (DrvHasEEPROM) EEPROMSetCSLine(d ? 0 : 1); + return; + } + + case 0x10 :{ + if (DrvHasEEPROM) EEPROMSetClockLine(d ? 0 : 1); + return; + } + + case 0x18 :{ + if (DrvHasEEPROM) EEPROMWriteBit(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MstworldZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - DrvInput[0]; + } + + case 0x01: { + return 0xfe - DrvInput[1]; + } + + case 0x02: { + return 0xfe - DrvInput[2]; + } + + case 0x03: { + return DrvDip[0]; + } + + case 0x05: { + return 0xff - DrvInput[3]; + } + + case 0x06: { + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0xff; +} + +void __fastcall MstworldZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DrvFlipScreen = d & 0x04; + DrvPaletteRamBank = d & 0x20; + return; + } + + case 0x02: { + DrvRomBank = d & 0x0f; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + return; + } + + case 0x03: { + DrvSoundLatch = d; + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + } + + case 0x06: { + // nop + return; + } + + case 0x07: { + DrvVideoBank = d & 0x01; + return; + } + + case 0x08: + case 0x10: + case 0x18: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall MstworldSoundZ80Read(UINT16 a) +{ + switch (a) { + case 0x9800: { + return MSM6295ReadStatus(0); + } + + case 0xa000: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall MstworldSoundZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + DrvOkiBank = d & 0x03; + memcpy(MSM6295ROM, DrvSoundRom + (DrvOkiBank * 0x40000), 0x40000); + return; + } + + case 0x9800: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +// Kabuki - we use the module from the CPS-1 Q-Sound games +extern void kabuki_decode(UINT8 *src, UINT8 *dest_op, UINT8 *dest_data, INT32 base_addr, INT32 length, INT32 swap_key1, INT32 swap_key2, INT32 addr_key, INT32 xor_key); + +static void mitchell_decode(INT32 swap_key1, INT32 swap_key2, INT32 addr_key, INT32 xor_key) +{ + UINT8 *rom = DrvZ80Rom; + UINT8 *decrypt = DrvZ80Code; + INT32 numbanks = (0x50000 - 0x10000) / 0x4000; + INT32 i; + + kabuki_decode(rom, decrypt, rom, 0x0000, 0x8000, swap_key1, swap_key2, addr_key, xor_key); + + rom += 0x10000; + decrypt += 0x10000; + for (i = 0; i < numbanks; i++) + kabuki_decode(rom + i * 0x4000,decrypt + i * 0x4000, rom + i * 0x4000, 0x8000, 0x4000, swap_key1, swap_key2, addr_key, xor_key); +} + +static void mgakuen2_decode() { mitchell_decode(0x76543210, 0x01234567, 0xaa55, 0xa5); } +static void pang_decode() { mitchell_decode(0x01234567, 0x76543210, 0x6548, 0x24); } +static void cworld_decode() { mitchell_decode(0x04152637, 0x40516273, 0x5751, 0x43); } +static void hatena_decode() { mitchell_decode(0x45670123, 0x45670123, 0x5751, 0x43); } +static void spang_decode() { mitchell_decode(0x45670123, 0x45670123, 0x5852, 0x43); } +static void spangj_decode() { mitchell_decode(0x45123670, 0x67012345, 0x55aa, 0x5a); } +static void sbbros_decode() { mitchell_decode(0x45670123, 0x45670123, 0x2130, 0x12); } +static void marukin_decode() { mitchell_decode(0x54321076, 0x54321076, 0x4854, 0x4f); } +static void qtono1_decode() { mitchell_decode(0x12345670, 0x12345670, 0x1111, 0x11); } +static void qsangoku_decode() { mitchell_decode(0x23456701, 0x23456701, 0x1828, 0x18); } +static void block_decode() { mitchell_decode(0x02461357, 0x64207531, 0x0002, 0x01); } + +static INT32 CharPlaneOffsets[4] = { 0x400004, 0x400000, 4, 0 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 }; +static INT32 CharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 MahjongCharPlaneOffsets[4] = { 12, 8, 4, 0 }; +static INT32 MahjongCharXOffsets[8] = { 0, 1, 2, 3, 16, 17, 18, 19 }; +static INT32 MahjongCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 0x100004, 0x100000, 4, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; +static INT32 MstworldCharPlaneOffsets[4] = { 0x200000, 0x300000, 0, 0x100000 }; +static INT32 MstworldCharXOffsets[8] = { 7, 6, 5, 4, 3, 2, 1, 0 }; +static INT32 MstworldCharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 MstworldSpritePlaneOffsets[4] = { 4, 0, 0x100004, 0x100000 }; +static INT32 MstworldSpriteXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; +static INT32 MstworldSpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 }; + +static void MitchellMachineInit() +{ + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(MitchellZ80Read); + ZetSetWriteHandler(MitchellZ80Write); + ZetSetInHandler(MitchellZ80PortRead); + ZetSetOutHandler(MitchellZ80PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom + 0x00000 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Code + 0x00000, DrvZ80Rom + 0x00000); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000, DrvZ80Rom + 0x10000); + ZetMapArea(0xc800, 0xcfff, 0, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 1, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvAttrRam ); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + BurnYM2413Init(4000000, 1.0); + BurnYM2413DecreaseVolume(40); + MSM6295Init(0, 1000000 / 132, 10.0, 1); + MSM6295ROM = DrvSoundRom; + + EEPROMInit(&MitchellEEPROMIntf); + DrvHasEEPROM = 1; + + GenericTilesInit(); + + DrvTileMask = 0x7fff; + DrvNumColours = 0x800; +} + +static void MahjongMachineInit() +{ + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(MitchellZ80Read); + ZetSetWriteHandler(MitchellZ80Write); + ZetSetInHandler(MitchellZ80PortRead); + ZetSetOutHandler(MitchellZ80PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom + 0x00000 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Code + 0x00000, DrvZ80Rom + 0x00000); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000, DrvZ80Rom + 0x10000); + ZetMapArea(0xc800, 0xcfff, 0, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 1, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvAttrRam ); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + BurnYM2413Init(4000000, 1.0); + BurnYM2413DecreaseVolume(40); + MSM6295Init(0, 990000 / 132, 10.0, 1); + memcpy(MSM6295ROM, DrvSoundRom, 0x40000); + + EEPROMInit(&MitchellEEPROMIntf); + DrvHasEEPROM = 1; + + GenericTilesInit(); + + DrvTileMask = 0xffff; + DrvNumColours = 0x800; +} + +static INT32 MgakuenInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MgakuenMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MgakuenMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x010000, 1, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x10000, 4, 8, 8, MahjongCharPlaneOffsets, MahjongCharXOffsets, MahjongCharYOffsets, 0x100, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x00800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x000000, 8, 1); if (nRet != 0) return 1; + + ZetInit(1); + ZetOpen(0); + ZetSetInHandler(MitchellZ80PortRead); + ZetSetOutHandler(MitchellZ80PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom + 0x00000); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom + 0x00000); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x10000); + ZetMapArea(0xc000, 0xc7ff, 0, DrvPaletteRam ); + ZetMapArea(0xc000, 0xc7ff, 1, DrvPaletteRam ); + ZetMapArea(0xc000, 0xc7ff, 2, DrvPaletteRam ); + ZetMapArea(0xc800, 0xcfff, 0, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 1, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvAttrRam ); + ZetMapArea(0xd000, 0xdfff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 2, DrvVideoRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram ); + ZetMapArea(0xf000, 0xffff, 0, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 1, DrvSpriteRam ); + ZetMapArea(0xf000, 0xffff, 2, DrvSpriteRam ); + ZetMemEnd(); + ZetClose(); + + BurnYM2413Init(4000000, 1.0); + BurnYM2413DecreaseVolume(40); + MSM6295Init(0, 990000 / 132, 10.0, 1); + memcpy(MSM6295ROM, DrvSoundRom, 0x40000); + + GenericTilesInit(); + + DrvTileMask = 0xffff; + DrvNumColours = 0x400; + DrvHasEEPROM = 0; + + DrvInputType = DRV_INPUT_TYPE_MAHJONG; + + DrvDoReset(); + + return 0; +} + +static INT32 Mgakuen2Init() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MahjongMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MahjongMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x010000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x030000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x10000, 4, 8, 8, MahjongCharPlaneOffsets, MahjongCharXOffsets, MahjongCharYOffsets, 0x100, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x00800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x000000, 9, 1); if (nRet != 0) return 1; + + mgakuen2_decode(); + + MahjongMachineInit(); + + DrvInputType = DRV_INPUT_TYPE_MAHJONG; + + DrvPort5Kludge = 1; + + DrvDoReset(); + + return 0; +} + +static INT32 PkladiesInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MahjongMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MahjongMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x010000, 1, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x000001, 3, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 4, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100001, 5, 2); if (nRet != 0) return 1; + GfxDecode(0x10000, 4, 8, 8, MahjongCharPlaneOffsets, MahjongCharXOffsets, MahjongCharYOffsets, 0x100, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x00800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x000000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvSoundRom + 0x020000, 9, 1); if (nRet != 0) return 1; + + mgakuen2_decode(); + + MahjongMachineInit(); + + DrvInputType = DRV_INPUT_TYPE_MAHJONG; + + DrvDoReset(); + + return 0; +} + +static INT32 DokabenInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + mgakuen2_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 PangInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 8, 1); if (nRet != 0) return 1; + + pang_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 PangbInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Code + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Code + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom + 0x0000, DrvZ80Code + 0x8000, 0x8000); + memset(DrvZ80Code + 0x8000, 0, 0x8000); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 PangboldInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Code + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Code + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 2, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom + 0x0000, DrvZ80Code + 0x8000, 0x8000); + memset(DrvZ80Code + 0x8000, 0, 0x8000); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 11, 1); if (nRet != 0) return 1; + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 CworldInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc0000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xe0000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 13, 1); if (nRet != 0) return 1; + + cworld_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 HatenaInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc0000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xe0000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 13, 1); if (nRet != 0) return 1; + + hatena_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 SpangInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + + spang_decode(); + + MitchellMachineInit(); + + if (!EEPROMAvailable()) EEPROMFill(DrvTempRom, 0, 128); + + BurnFree(DrvTempRom); + + DrvNVRamSize = 0x0080; + DrvNVRamAddress = 0x0000; + + DrvDoReset(); + + return 0; +} + +static INT32 SpangjInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + + spangj_decode(); + + MitchellMachineInit(); + + if (!EEPROMAvailable()) EEPROMFill(DrvTempRom, 0, 128); + + BurnFree(DrvTempRom); + + DrvNVRamSize = 0x0080; + DrvNVRamAddress = 0x0000; + + DrvDoReset(); + + return 0; +} + +static INT32 SbbrosInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + + sbbros_decode(); + + MitchellMachineInit(); + + if (!EEPROMAvailable()) EEPROMFill(DrvTempRom, 0, 128); + + BurnFree(DrvTempRom); + + DrvNVRamSize = 0x0080; + DrvNVRamAddress = 0x0000; + + DrvDoReset(); + + return 0; +} + +static INT32 MstworldInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MstworldMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MstworldMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 1, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0x00, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 5, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x80000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(0x4000, 4, 8, 8, MstworldCharPlaneOffsets, MstworldCharXOffsets, MstworldCharYOffsets, 0x40, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0x00, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 7, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x40000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(0x0800, 4, 16, 16, MstworldSpritePlaneOffsets, MstworldSpriteXOffsets, MstworldSpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + nRet = BurnLoadRom(DrvTempRom + 0x00000, 8, 1); if (nRet != 0) return 1; + memcpy(DrvSoundRom + 0x000000, DrvTempRom + 0x000000, 0x20000); + memcpy(DrvSoundRom + 0x020000, DrvTempRom + 0x000000, 0x20000); + memcpy(DrvSoundRom + 0x040000, DrvTempRom + 0x000000, 0x20000); + memcpy(DrvSoundRom + 0x060000, DrvTempRom + 0x020000, 0x20000); + memcpy(DrvSoundRom + 0x080000, DrvTempRom + 0x000000, 0x20000); + memcpy(DrvSoundRom + 0x0a0000, DrvTempRom + 0x040000, 0x20000); + memcpy(DrvSoundRom + 0x0c0000, DrvTempRom + 0x000000, 0x20000); + memcpy(DrvSoundRom + 0x0e0000, DrvTempRom + 0x060000, 0x20000); + + static const INT32 tablebank[] = { + 0, 0, + 1, 1, + -1, -1, + -1, -1, + 10, 4, + 5, 13, + 7, 17, + 21, 2, + 18, 9, + 15, 3, + 6, 11, + 19, 8, + -1, -1, + -1, -1, + -1, -1, + -1, -1, + 20, 20, + 14, 14, + 16, 16, + 12, 12, + }; + + memcpy(DrvTempRom, DrvZ80Rom, 0x80000); + for (INT32 x = 0; x < 40; x += 2) { + if (tablebank[x] != -1) { + memcpy(&DrvZ80Rom[(x / 2) * 0x4000], &DrvTempRom[tablebank[x] * 0x4000], 0x4000); + memcpy(&DrvZ80Code[(x / 2) * 0x4000], &DrvTempRom[tablebank[x + 1] * 0x4000], 0x4000); + } + } + + BurnFree(DrvTempRom); + + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(MitchellZ80Read); + ZetSetWriteHandler(MitchellZ80Write); + ZetSetInHandler(MstworldZ80PortRead); + ZetSetOutHandler(MstworldZ80PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom + 0x00000 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Code + 0x00000, DrvZ80Rom + 0x00000); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000, DrvZ80Rom + 0x10000); + ZetMapArea(0xc800, 0xcfff, 0, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 1, DrvAttrRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvAttrRam ); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80Ram ); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80Ram ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(MstworldSoundZ80Read); + ZetSetWriteHandler(MstworldSoundZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom2); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom2); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80Ram2); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80Ram2); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80Ram2); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 990000 / 132, 25.0, 0); + memcpy(MSM6295ROM, DrvSoundRom, 0x40000); + + DrvHasEEPROM = 0; + + GenericTilesInit(); + + DrvTileMask = 0x3fff; + DrvNumColours = 0x800; + + MstworldDoReset(); + + return 0; +} + +static INT32 MarukinInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MahjongMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MahjongMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x200000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x000000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x010000, 1, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x080000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x100000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x180000, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x10000, 4, 8, 8, MahjongCharPlaneOffsets, MahjongCharXOffsets, MahjongCharYOffsets, 0x100, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x200000); + nRet = BurnLoadRom(DrvTempRom + 0x000000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x020000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x00800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x000000, 8, 1); if (nRet != 0) return 1; + + marukin_decode(); + + MahjongMachineInit(); + + DrvInputType = DRV_INPUT_TYPE_MAHJONG; + + DrvDoReset(); + + return 0; +} + +static INT32 Qtono1Init() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc0000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xe0000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 13, 1); if (nRet != 0) return 1; + + qtono1_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 QsangokuInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xc0000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xe0000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 13, 1); if (nRet != 0) return 1; + + qsangoku_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 BlockInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + block_decode(); + + MitchellMachineInit(); + + DrvInputType = DRV_INPUT_TYPE_BLOCK; + + DrvNVRamSize = 0x0080; + DrvNVRamAddress = 0x1f80; + + DrvDoReset(); + + return 0; +} + +static INT32 BlockjoyInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 9, 1); if (nRet != 0) return 1; + + block_decode(); + + MitchellMachineInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 BlockblInit() +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + PangMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + PangMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x100000); + + nRet = BurnLoadRom(DrvZ80Code + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Code + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom + 0x30000, 2, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom + 0x00000, DrvZ80Code + 0x08000, 0x08000); + memset(DrvZ80Code + 0x08000, 0, 0x08000); + memcpy(DrvZ80Rom + 0x10000, DrvZ80Code + 0x30000, 0x20000); + memset(DrvZ80Code + 0x30000, 0, 0x20000); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x80000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0xa0000, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x8000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0xff, 0x100000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x0800, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + BurnFree(DrvTempRom); + + nRet = BurnLoadRom(DrvSoundRom + 0x00000, 11, 1); if (nRet != 0) return 1; + + MitchellMachineInit(); + + DrvInputType = DRV_INPUT_TYPE_BLOCK; + + DrvNVRamSize = 0x0080; + DrvNVRamAddress = 0x1f80; + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + BurnYM2413Exit(); + MSM6295Exit(0); + if (DrvHasEEPROM) EEPROMExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + DrvRomBank = 0; + DrvPaletteRamBank = 0; + DrvOkiBank = 0; + DrvFlipScreen = 0; + DrvVideoBank = 0; + DrvInputType = 0; + DrvMahjongKeyMatrix = 0; + DrvTileMask = 0; + DrvInput5Toggle = 0; + DrvPort5Kludge = 0; + DrvHasEEPROM = 0; + DrvNumColours = 0; + DrvNVRamSize = 0; + DrvNVRamAddress = 0; + DrvDialSelected = 0; + DrvSoundLatch = 0; + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 8); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < DrvNumColours * 2; i += 2) { + INT32 Val = DrvPaletteRam[i & ~1] + (DrvPaletteRam[i | 1] << 8); + + DrvPalette[i >> 1] = CalcCol(Val); + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, TileIndex = 0, xFlip; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = DrvAttrRam[TileIndex]; + Code = DrvVideoRam[(2 * TileIndex) + 0] + (DrvVideoRam[(2 * TileIndex) + 1] << 8); + Colour = Attr & (DrvNumColours == 0x800 ? 0x7f : 0x3f); + xFlip = (Attr & 0x80); + + x = 8 * mx; + y = 8 * my; + + if (DrvFlipScreen) { + x = 504 - x; + y = 248 - y; + xFlip = !xFlip; + } + + x -= 64; + y -= 8; + + Code &= DrvTileMask; + + if (DrvFlipScreen) { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } + } else { + if (xFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } + } + } else { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } + } else { + if (xFlip) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 0, DrvChars); + } + } + } + + TileIndex++; + } + } +} + +static void DrvRenderSpriteLayer() +{ + INT32 sx, sy; + + for (INT32 Offset = 0x1000 - 0x40; Offset >= 0; Offset -= 0x20) { + INT32 Code = DrvSpriteRam[Offset + 0]; + INT32 Attr = DrvSpriteRam[Offset + 1]; + INT32 Colour = Attr & 0x0f; + sx = DrvSpriteRam[Offset + 3] + ((Attr & 0x10) << 4); + sy = ((DrvSpriteRam[Offset + 2] + 8) & 0xff) - 8; + Code += (Attr & 0xe0) << 3; + + if (DrvFlipScreen) { + sx = 496 - sx; + sy = 240 - sy; + } + + sx -= 64; + sy -= 8; + + if (DrvFlipScreen) { + if (sx > 16 && sx < (nScreenWidth - 16) && sy > 16 && sy < (nScreenHeight - 16)) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 15, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 15, 0, DrvSprites); + } + } else { + if (sx > 16 && sx < (nScreenWidth - 16) && sy > 16 && sy < (nScreenHeight - 16)) { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 15, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 15, 0, DrvSprites); + } + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSpriteLayer(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 8000000 / 60; + nCyclesDone[0] = 0; + + DrvInput5Toggle = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 4) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[nCurrentCPU] += ZetRun(500); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + if (i == 7) DrvInput5Toggle = 1; + if (i == 9) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[nCurrentCPU] += ZetRun(500); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2413Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + BurnYM2413Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 MstworldFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (DrvReset) MstworldDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = 24000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 9) { + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[nCurrentCPU] += ZetRun(500); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM && DrvNVRamSize) { + memset(&ba, 0, sizeof(ba)); + ba.Data = DrvZ80Ram + DrvNVRamAddress; + ba.nLen = DrvNVRamSize; + ba.szName = "NVRam"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + BurnYM2413Scan(nAction); + MSM6295Scan(0, nAction); + + if (DrvHasEEPROM) EEPROMScan(nAction, pnMin); + + SCAN_VAR(nCyclesDone[0]); + SCAN_VAR(nCyclesDone[1]); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvPaletteRamBank); + SCAN_VAR(DrvOkiBank); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(DrvVideoBank); + SCAN_VAR(DrvInput5Toggle); + SCAN_VAR(DrvDialSelected); + SCAN_VAR(DrvDial[0]); + SCAN_VAR(DrvDial[1]); + SCAN_VAR(DrvDial1); + SCAN_VAR(DrvDial2); + SCAN_VAR(DrvMahjongKeyMatrix); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + if (DrvHasEEPROM) { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } else { + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + } + ZetClose(); + + if (DrvOkiBank) { + memcpy(MSM6295ROM, DrvSoundRom + 0x40000, 0x40000); + } + } + + return 0; +} + +static INT32 MstworldScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + MSM6295Scan(0, nAction); + + SCAN_VAR(nCyclesDone[0]); + SCAN_VAR(nCyclesDone[1]); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvPaletteRamBank); + SCAN_VAR(DrvOkiBank); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(DrvVideoBank); + SCAN_VAR(DrvSoundLatch); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Code + 0x10000 + (DrvRomBank * 0x4000), DrvZ80Rom + 0x10000 + (DrvRomBank * 0x4000)); + ZetClose(); + + memcpy(MSM6295ROM, DrvSoundRom + (DrvOkiBank * 0x40000), 0x40000); + } + + return 0; +} + +struct BurnDriver BurnDrvMgakuen = { + "mgakuen", NULL, NULL, NULL, "1988", + "Mahjong Gakuen\0", NULL, "Yuga", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, MgakuenRomInfo, MgakuenRomName, NULL, NULL, MgakuenInputInfo, MgakuenDIPInfo, + MgakuenInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSeventoitsu = { + "7toitsu", "mgakuen", NULL, NULL, "1988", + "Chi-Toitsu\0", NULL, "Yuga", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, SeventoitsuRomInfo, SeventoitsuRomName, NULL, NULL, MgakuenInputInfo, MgakuenDIPInfo, + MgakuenInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x400, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMgakuen2 = { + "mgakuen2", NULL, NULL, NULL, "1989", + "Mahjong Gakuen 2 Gakuen-chou no Fukushuu\0", NULL, "Face", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, Mgakuen2RomInfo, Mgakuen2RomName, NULL, NULL, MarukinInputInfo, NULL, + Mgakuen2Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPkladies = { + "pkladies", NULL, NULL, NULL, "1989", + "Poker Ladies\0", NULL, "Mitchell", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, PkladiesRomInfo, PkladiesRomName, NULL, NULL, PkladiesInputInfo, NULL, + PkladiesInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPkladiesl = { + "pkladiesl", "pkladies", NULL, NULL, "1989", + "Poker Ladies (Leprechaun ver. 510)\0", NULL, "Leprechaun", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, PkladieslRomInfo, PkladieslRomName, NULL, NULL, PkladiesInputInfo, NULL, + PkladiesInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPkladiesla = { + "pkladiesla", "pkladies", NULL, NULL, "1989", + "Poker Ladies (Leprechaun ver. 401)\0", NULL, "Leprechaun", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, PkladieslaRomInfo, PkladieslaRomName, NULL, NULL, PkladiesInputInfo, NULL, + PkladiesInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvDokaben = { + "dokaben", NULL, NULL, NULL, "1989", + "Dokaben (Japan)\0", NULL, "Dokaben", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, DokabenRomInfo, DokabenRomName, NULL, NULL, PangInputInfo, NULL, + DokabenInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPang = { + "pang", NULL, NULL, NULL, "1989", + "Pang (World)\0", NULL, "Mitchell", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, PangRomInfo, PangRomName, NULL, NULL, PangInputInfo, NULL, + PangInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBbros = { + "bbros", "pang", NULL, NULL, "1989", + "Buster Bros. (US)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, BbrosRomInfo, BbrosRomName, NULL, NULL, PangInputInfo, NULL, + PangInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPompingw = { + "pompingw", "pang", NULL, NULL, "1989", + "Pomping World (Japan)\0", NULL, "Mitchell", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, PompingwRomInfo, PompingwRomName, NULL, NULL, PangInputInfo, NULL, + PangInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPangb = { + "pangb", "pang", NULL, NULL, "1989", + "Pang (bootleg, set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, PangbRomInfo, PangbRomName, NULL, NULL, PangInputInfo, NULL, + PangbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPangbold = { + "pangbold", "pang", NULL, NULL, "1989", + "Pang (bootleg, set 2)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, PangboldRomInfo, PangboldRomName, NULL, NULL, PangInputInfo, NULL, + PangboldInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvCworld = { + "cworld", NULL, NULL, NULL, "1990", + "Capcom World (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, CworldRomInfo, CworldRomName, NULL, NULL, Qtono1InputInfo, NULL, + CworldInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHatena = { + "hatena", NULL, NULL, NULL, "1990", + "Adventure Quiz 2 Hatena Hatena no Dai-Bouken (Japan 900228)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, HatenaRomInfo, HatenaRomName, NULL, NULL, Qtono1InputInfo, NULL, + HatenaInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSpang = { + "spang", NULL, NULL, NULL, "1990", + "Super Pang (World 900914)\0", NULL, "Mitchell", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, SpangRomInfo, SpangRomName, NULL, NULL, PangInputInfo, NULL, + SpangInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSpangj = { + "spangj", "spang", NULL, NULL, "1990", + "Super Pang (Japan 901023)\0", NULL, "Mitchell", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, SpangjRomInfo, SpangjRomName, NULL, NULL, PangInputInfo, NULL, + SpangjInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSbbros = { + "sbbros", "spang", NULL, NULL, "1990", + "Super Buster Bros. (US 901001)\0", NULL, "Mitchell + Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, SbbrosRomInfo, SbbrosRomName, NULL, NULL, PangInputInfo, NULL, + SbbrosInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMstworld = { + "mstworld", NULL, NULL, NULL, "1994", + "Monsters World\0", NULL, "TCH", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0, + NULL, MstworldRomInfo, MstworldRomName, NULL, NULL, MstworldInputInfo, MstworldDIPInfo, + MstworldInit, DrvExit, MstworldFrame, NULL, MstworldScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvMarukin = { + "marukin", NULL, NULL, NULL, "1990", + "Super Marukin-Ban (Japan 901017)\0", NULL, "Yuga", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAHJONG, 0, + NULL, MarukinRomInfo, MarukinRomName, NULL, NULL, MarukinInputInfo, NULL, + MarukinInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvQtono1 = { + "qtono1", NULL, NULL, NULL, "1991", + "Quiz Tonosama no Yabou (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, Qtono1RomInfo, Qtono1RomName, NULL, NULL, Qtono1InputInfo, NULL, + Qtono1Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvQsangoku = { + "qsangoku", NULL, NULL, NULL, "1991", + "Quiz Sangokushi (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_QUIZ, 0, + NULL, QsangokuRomInfo, QsangokuRomName, NULL, NULL, Qtono1InputInfo, NULL, + QsangokuInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBlock = { + "block", NULL, NULL, NULL, "1991", + "Block Block (World 910910)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_BREAKOUT, 0, + NULL, BlockRomInfo, BlockRomName, NULL, NULL, BlockInputInfo, NULL, + BlockInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvBlockj = { + "blockj", "block", NULL, NULL, "1991", + "Block Block (Japan 910910)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_BREAKOUT, 0, + NULL, BlockjRomInfo, BlockjRomName, NULL, NULL, BlockInputInfo, NULL, + BlockInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvBlockjoy = { + "blockjoy", "block", NULL, NULL, "1991", + "Block Block (World 911116 Joystick)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_BREAKOUT, 0, + NULL, BlockjoyRomInfo, BlockjoyRomName, NULL, NULL, BlockjoyInputInfo, NULL, + BlockjoyInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; + +struct BurnDriver BurnDrvBlockbl = { + "blockbl", "block", NULL, NULL, "1991", + "Block Block (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_BREAKOUT, 0, + NULL, BlockblRomInfo, BlockblRomName, NULL, NULL, BlockInputInfo, NULL, + BlockblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x800, 240, 384, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_mole.cpp b/src/burn/drivers/misc_pre90s/d_mole.cpp new file mode 100644 index 00000000..7f009445 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_mole.cpp @@ -0,0 +1,499 @@ +// Mole Attack FB Driver Module +// Based on MAME driver by Jason Nelson and Phil Stroffolino + +#include "burnint.h" +#include "m6502_intf.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + + +//-------------------------------------------------------------------------------------- +// Variables + + +static UINT8 *Mem, *Rom, *Gfx, *BankRam; +static UINT8 DrvJoy1[12], DrvJoy2[12], DrvReset, DrvDips; +static INT32 *Palette; +static INT16 *pAY8910Buffer[3], *pFMBuffer = NULL; + +static INT32 tile_bank, flipscreen; + + +//-------------------------------------------------------------------------------------- +// Inputs + +// buttons are laid out as follows: +// 7 8 9 +// 4 5 6 +// 1 2 3 + + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL, DrvJoy1 + 9, "p1 coin" }, + {"Start 1" , BIT_DIGITAL, DrvJoy1 + 10, "p1 start" }, + {"Start 2" , BIT_DIGITAL, DrvJoy2 + 10, "p2 start" }, + {"P1 button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1", }, + {"P1 button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2", }, + {"P1 button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3", }, + {"P1 button 4", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 4", }, + {"P1 button 5", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 5", }, + {"P1 button 6", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 6", }, + {"P1 button 7", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 7", }, + {"P1 button 8", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 8", }, + {"P1 button 9", BIT_DIGITAL, DrvJoy1 + 8, "p1 fire 9", }, + + {"P2 button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1", }, + {"P2 button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2", }, + {"P2 button 3", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 3", }, + {"P2 button 4", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 4", }, + {"P2 button 5", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 5", }, + {"P2 button 6", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 6", }, + {"P2 button 7", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 7", }, + {"P2 button 8", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 8", }, + {"P2 button 9", BIT_DIGITAL, DrvJoy2 + 8, "p2 fire 9", }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, &DrvDips, "dip" }, +}; + +STDINPUTINFO(Drv) + + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2 , "Passing Points" }, + {0x16, 0x01, 0x01, 0x00, "300" }, + {0x16, 0x01, 0x01, 0x01, "400" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x16, 0x01, 0x02, 0x00, "1 Coin 1 Play" }, + {0x16, 0x01, 0x02, 0x02, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x16, 0x01, 0x10, 0x00, "Upright" }, + {0x16, 0x01, 0x10, 0x10, "Cocktail" }, +}; + +STDDIPINFO(Drv) + + +//-------------------------------------------------------------------------------------- +// Memory handling + + +static UINT8 mole_protection_r(UINT8 offset) +{ + switch (offset) + { + case 0x08: // random mole placement + return 0xb0; + + case 0x26: + if (M6502GetPC() == 0x53d7) + { + return 0x06; // bonus round + } + else // pc == 0x515b, 0x5162 + { + return 0xc6; // game start + } + + case 0x86: // game over + return 0x91; + + case 0xae: // coinage + return 0x32; + } + + return 0x00; +} + +void mole_write_byte(UINT16 address, UINT8 data) +{ + // Tile RAM + if (address >= 0x8000 && address <= 0x83ff) + { + BankRam[address & 0x3ff] = tile_bank; + Rom[address] = data; + return; + } + + switch (address) + { + case 0x0800: // ? + case 0x0820: + case 0x8c40: + case 0x8c80: + case 0x8c81: + break; + + case 0x8400: + tile_bank = data; + break; + + case 0x8c00: // ay8910_write_port + case 0x8c01: // ay8910_control_port + AY8910Write(0, ~address & 1, data); + break; + + case 0x8d00: // watchdog + break; + + case 0x8dc0: // flipscreen + flipscreen = data & 1; + break; + } + + if (address <= 0x3ff) { + Rom[address] = data; + } +} + +UINT8 mole_read_byte(UINT16 address) +{ + UINT8 ret = 0; + + switch (address) + { + case 0x8d00: // input port 0 + return DrvDips & 0x03; + + case 0x8d40: // input port 1 + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy1[i] << i; + + return ret; + } + + case 0x8d80: // input port 2 + { + ret |= DrvJoy1[8]; + ret |= DrvJoy2[0] << 1; + ret |= DrvJoy2[1] << 2; + ret |= DrvJoy2[2] << 3; + ret |= DrvDips & 0x10; + ret |= DrvJoy2[10] << 5; + ret |= DrvJoy1[10] << 6; + ret |= DrvJoy1[ 9] << 7; + + return ret; + } + + case 0x8dc0: // input port 3 + { + ret |= DrvJoy2[7]; + ret |= DrvJoy2[6] << 1; + ret |= DrvJoy2[3] << 2; + ret |= DrvJoy2[8] << 3; + ret |= DrvJoy2[5] << 4; + ret |= DrvJoy2[4] << 5; + + return ret; + } + } + + // Protection read + if (address >= 0x800 && address <= 0x8ff) + { + return mole_protection_r(address & 0xff); + } + + if (address <= 0x3ff) { + return Rom[address]; + } + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Initilizing functions + + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Rom + 0x0000, 0, 0x0400); + memset (Rom + 0x8000, 0, 0x0400); + memset (BankRam, 0, 0x0400); + + tile_bank = 0; + flipscreen = 0; + + M6502Open(0); + M6502Reset(); + M6502Close(); + + AY8910Reset(0); + + return 0; +} + +static void mole_palette_init() +{ + for (INT32 i = 0; i < 8; i++) { + Palette[i] |= (i & 1) ? 0xff0000 : 0; + Palette[i] |= (i & 4) ? 0x00ff00 : 0; + Palette[i] |= (i & 2) ? 0x0000ff : 0; + } + +} + +static INT32 mole_gfx_convert() +{ + UINT8 a, b, c; + UINT8 *tmp = (UINT8*)BurnMalloc(0x6000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx, 0x6000); + + for (INT32 i = 0; i < 0x8000; i++) + { + a = (tmp[0x0000 + (i >> 3)] >> (i & 7)) & 1; + b = (tmp[0x1000 + (i >> 3)] >> (i & 7)) & 1; + c = (tmp[0x2000 + (i >> 3)] >> (i & 7)) & 1; + + Gfx[0x0007 ^ i] = (a << 2) | (b << 1) | c; + + a = (tmp[0x3000 + (i >> 3)] >> (i & 7)) & 1; + b = (tmp[0x4000 + (i >> 3)] >> (i & 7)) & 1; + c = (tmp[0x5000 + (i >> 3)] >> (i & 7)) & 1; + + Gfx[0x8007 ^ i] = (a << 2) | (b << 1) | c; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x10000 + 0x400 + (0x20 * sizeof(INT32))); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)BurnMalloc(nBurnSoundLen * 3 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + memset (Mem, 0, 0x20420); + + Rom = Mem + 0x00000; + Gfx = Mem + 0x10000; + BankRam = Mem + 0x20000; + Palette = (INT32 *)(Mem + 0x20400); + + { + BurnLoadRom(Rom + 0x5000, 0, 1); + BurnLoadRom(Rom + 0x6000, 1, 1); + BurnLoadRom(Rom + 0x7000, 2, 1); + + BurnLoadRom(Gfx + 0x0000, 3, 1); + BurnLoadRom(Gfx + 0x1000, 4, 1); + BurnLoadRom(Gfx + 0x2000, 5, 1); + BurnLoadRom(Gfx + 0x3000, 6, 1); + BurnLoadRom(Gfx + 0x4000, 7, 1); + BurnLoadRom(Gfx + 0x5000, 8, 1); + } + + mole_gfx_convert(); + mole_palette_init(); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(Rom + 0x0000, 0x0000, 0x03ff, M6502_RAM); // Rom + M6502MapMemory(Rom + 0x5000, 0x5000, 0x7fff, M6502_ROM); // Rom + M6502MapMemory(Rom + 0x5000, 0xd000, 0xffff, M6502_ROM); // Rom Mirror + M6502SetReadByteHandler(mole_read_byte); + M6502SetWriteByteHandler(mole_write_byte); + M6502SetReadMemIndexHandler(mole_read_byte); + M6502SetWriteMemIndexHandler(mole_write_byte); + M6502SetReadOpHandler(mole_read_byte); + M6502SetReadOpArgHandler(mole_read_byte); + M6502Close(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + M6502Exit(); + AY8910Exit(0); + + BurnFree (Mem); + BurnFree (pFMBuffer); + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Drawing functions + + +static INT32 DrvDraw() +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sy = ((offs / 40) % 25) << 3; + INT32 sx = (offs % 40) << 3; + + INT32 code = ((BankRam[offs] & 3) << 14) | ((Rom[0x8000 + offs]) << 6); + + UINT8 *gfxsrc = Gfx + code; + + for (INT32 y = sy; y < sy + 8; y++) + { + for (INT32 x = sx; x < sx + 8; x++, gfxsrc++) + { + INT32 pxl = Palette[*gfxsrc]; + + INT32 pos; + + if (flipscreen) + pos = (199 - y) * 320 + (319 - x); + else + pos = y * 320 + x; + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + M6502Open(0); + M6502Run(4000000 / 60); + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_AUTO); + M6502Close(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Savestates + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0x0000; + ba.nLen = 0x0400; + ba.szName = "Work Ram"; + BurnAcb(&ba); + + ba.Data = Rom + 0x8000; + ba.nLen = 0x0400; + ba.szName = "Video Ram"; + BurnAcb(&ba); + + ba.Data = BankRam; + ba.nLen = 0x0400; + ba.szName = "Bank Ram"; + BurnAcb(&ba); + + M6502Scan(nAction); // Scan m6502 + AY8910Scan(nAction, pnMin); // Scan AY8910 + + // Scan critical driver variables + SCAN_VAR(tile_bank); + SCAN_VAR(flipscreen); + } + + return 0; +} + + +//-------------------------------------------------------------------------------------- +// Game drivers + + +// Mole Attack + +static struct BurnRomInfo moleRomDesc[] = { + { "m3a.5h", 0x1000, 0x5fbbdfef, 1 | BRF_ESS | BRF_PRG }, // 0 M6502 Code + { "m2a.7h", 0x1000, 0xf2a90642, 1 | BRF_ESS | BRF_PRG }, // 1 + { "m1a.8h", 0x1000, 0xcff0119a, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "mea.4a", 0x1000, 0x49d89116, 2 | BRF_GRA }, // 3 Graphics tiles + { "mca.6a", 0x1000, 0x04e90300, 2 | BRF_GRA }, // 4 + { "maa.9a", 0x1000, 0x6ce9442b, 2 | BRF_GRA }, // 5 + { "mfa.3a", 0x1000, 0x0d0c7d13, 2 | BRF_GRA }, // 6 + { "mda.5a", 0x1000, 0x41ae1842, 2 | BRF_GRA }, // 7 + { "mba.8a", 0x1000, 0x50c43fc9, 2 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(mole) +STD_ROM_FN(mole) + +struct BurnDriver BurnDrvMole = { + "mole", NULL, NULL, NULL, "1982", + "Mole Attack\0", NULL, "Yachiyo Electronics, Ltd.", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, moleRomInfo, moleRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x08, + 320, 200, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_mrdo.cpp b/src/burn/drivers/misc_pre90s/d_mrdo.cpp new file mode 100644 index 00000000..04a47348 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_mrdo.cpp @@ -0,0 +1,761 @@ +// FB Alpha Mr. Do! driver module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "sn76496.h" + +static UINT8 *Mem, *Rom, *Gfx0, *Gfx1, *Gfx2, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvReset, DrvDips[2]; +static INT32 *Palette; + +static INT32 flipscreen, scroll_x, scroll_y; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy2 + 6, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 5, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy1 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy2 + 7, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 6, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + + {"Tilt" , BIT_DIGITAL , DrvJoy1 + 7, "tilt" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0xdf, NULL }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x03, "Easy" }, + {0x10, 0x01, 0x03, 0x02, "Medium" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Rack Test (cheat)" }, + {0x10, 0x01, 0x04, 0x04, "Off" }, + {0x10, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Special" }, + {0x10, 0x01, 0x08, 0x08, "Easy" }, + {0x10, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Extra" }, + {0x10, 0x01, 0x10, 0x10, "Easy" }, + {0x10, 0x01, 0x10, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x20, 0x00, "Upright" }, + {0x10, 0x01, 0x20, 0x20, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0xc0, 0x00, "2" }, + {0x10, 0x01, 0xc0, 0xc0, "3" }, + {0x10, 0x01, 0xc0, 0x80, "4" }, + {0x10, 0x01, 0xc0, 0x40, "5" }, + + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 11 , "Coin B" }, + {0x11, 0x01, 0x0f, 0x06, "4C_1C" }, + {0x11, 0x01, 0x0f, 0x08, "3C_1C" }, + {0x11, 0x01, 0x0f, 0x0a, "2C_1C" }, + {0x11, 0x01, 0x0f, 0x07, "3C_2C" }, + {0x11, 0x01, 0x0f, 0x0f, "1C_1C" }, + {0x11, 0x01, 0x0f, 0x09, "2C_3C" }, + {0x11, 0x01, 0x0f, 0x0e, "1C_2C" }, + {0x11, 0x01, 0x0f, 0x0d, "1C_3C" }, + {0x11, 0x01, 0x0f, 0x0c, "1C_4C" }, + {0x11, 0x01, 0x0f, 0x0b, "1C_5C" }, + {0x11, 0x01, 0x0f, 0x00, "Free_Play" }, + + {0 , 0xfe, 0 , 11 , "Coin A" }, + {0x11, 0x01, 0xf0, 0x60, "4C_1C" }, + {0x11, 0x01, 0xf0, 0x80, "3C_1C" }, + {0x11, 0x01, 0xf0, 0xa0, "2C_1C" }, + {0x11, 0x01, 0xf0, 0x70, "3C_2C" }, + {0x11, 0x01, 0xf0, 0xf0, "1C_1C" }, + {0x11, 0x01, 0xf0, 0x90, "2C_3C" }, + {0x11, 0x01, 0xf0, 0xe0, "1C_2C" }, + {0x11, 0x01, 0xf0, 0xd0, "1C_3C" }, + {0x11, 0x01, 0xf0, 0xc0, "1C_4C" }, + {0x11, 0x01, 0xf0, 0xb0, "1C_5C" }, + {0x11, 0x01, 0xf0, 0x00, "Free_Play" }, +}; + +STDDIPINFO(Drv) + +void __fastcall mrdo_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf000) == 0xf000) address &= 0xf800; + + switch (address) + { + case 0x9800: + flipscreen = data & 1; + break; + + case 0x9801: + SN76496Write(0, data); + + case 0x9802: + SN76496Write(1, data); + break; + + case 0xf000: + scroll_x = data; + break; + + case 0xf800: + scroll_y = data ^ (flipscreen ? 0xff : 0); + break; + } +} + +UINT8 __fastcall mrdo_read(UINT16 address) +{ + UINT8 ret = 0xff; + + switch (address) + { + case 0x9803: // Protection + return Rom[ZetHL(-1)]; + + case 0xa000: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy1[i] << i; + return ret; + } + + case 0xa001: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy2[i] << i; + return ret; + } + + case 0xa002: + return DrvDips[0]; + + case 0xa003: + return DrvDips[1]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Rom + 0x8000, 0, 0x8000); + + flipscreen = 0; + scroll_x = scroll_y = 0; + + ZetOpen(0); + ZetReset(); + ZetClose(); + + return 0; +} + +static void mrdo_palette_init() +{ + INT32 weight[16]; + + for (INT32 i = 0x0f; i >= 0; i--) + { + float par = 0, pot = 0; + + if (i & 1) par += 1.0/150; + if (i & 2) par += 1.0/120; + if (i & 4) par += 1.0/100; + if (i & 8) par += 1.0/75; + if (par) + { + par = 1 / par; + pot = 200 / (200 + par) - 0.2f; + } + else pot = 0; + + weight[i] = (INT32)(0xff * pot / 0.684615); + } + + for (INT32 i = 0; i < 0x100; i++) + { + INT32 a1,a2; + INT32 bits0, bits2; + INT32 r, g, b; + + a1 = ((i >> 3) & 0x1c) + (i & 0x03) + 32; + a2 = ((i >> 0) & 0x1c) + (i & 0x03); + + bits0 = (Prom[a1] >> 0) & 0x03; + bits2 = (Prom[a2] >> 0) & 0x03; + r = weight[bits0 + (bits2 << 2)]; + + bits0 = (Prom[a1] >> 2) & 0x03; + bits2 = (Prom[a2] >> 2) & 0x03; + g = weight[bits0 + (bits2 << 2)]; + + bits0 = (Prom[a1] >> 4) & 0x03; + bits2 = (Prom[a2] >> 4) & 0x03; + b = weight[bits0 + (bits2 << 2)]; + + Palette[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 0x40; i++) + { + UINT8 ctbl = Prom[0x40 + (i & 0x1f)] >> ((i & 0x20) >> 3); + + Palette[0x100 + i] = Palette[ctbl & 0x0f]; + } +} + +static void mrdo_gfx_decode() +{ + static INT32 CharPlane[2] = { 0, 0x8000 }; + static INT32 CharXOffs[8] = { 7, 6, 5, 4, 3, 2, 1, 0 }; + static INT32 CharYOffs[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + + static INT32 SpriPlane[2] = { 4, 0 }; + static INT32 SpriXOffs[16] = { 3, 2, 1, 0, 11, 10, 9, 8, 19, 18, 17, 16, 27, 26, 25, 24 }; + static INT32 SpriYOffs[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x2000); + if (!tmp) return; + + memcpy (tmp, Gfx0, 0x2000); + + GfxDecode(0x200, 2, 8, 8, CharPlane, CharXOffs, CharYOffs, 0x040, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x2000); + + GfxDecode(0x200, 2, 8, 8, CharPlane, CharXOffs, CharYOffs, 0x040, tmp, Gfx1); + + memcpy (tmp, Gfx2, 0x2000); + + GfxDecode(0x080, 2, 16, 16, SpriPlane, SpriXOffs, SpriYOffs, 0x200, tmp, Gfx2); + + BurnFree (tmp); +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x8000 + 0x8000 + 0x8000 + 0x80 + 0x500); + if (!Mem) return 1; + + Rom = Mem + 0x00000; + Gfx0 = Mem + 0x10000; + Gfx1 = Mem + 0x18000; + Gfx2 = Mem + 0x20000; + Prom = Mem + 0x28000; + Palette = (INT32*)(Mem + 0x28080); + + { + for (INT32 i = 0; i < 4; i++) { + if(BurnLoadRom(Rom + i * 0x2000, 0 + i, 1)) return 1; + if(BurnLoadRom(Prom + i * 0x0020, 10 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 2; i++) { + if(BurnLoadRom(Gfx0 + i * 0x1000, 4 + i, 1)) return 1; + if(BurnLoadRom(Gfx1 + i * 0x1000, 6 + i, 1)) return 1; + if(BurnLoadRom(Gfx2 + i * 0x1000, 8 + i, 1)) return 1; + } + + mrdo_palette_init(); + mrdo_gfx_decode(); + } + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(mrdo_read); + ZetSetWriteHandler(mrdo_write); + ZetMapArea(0x0000, 0x7fff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0x7fff, 2, Rom + 0x0000); + ZetMapArea(0x8000, 0x8fff, 0, Rom + 0x8000); + ZetMapArea(0x8000, 0x8fff, 1, Rom + 0x8000); + ZetMapArea(0x9000, 0x90ff, 1, Rom + 0x9000); + ZetMapArea(0xe000, 0xefff, 0, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 1, Rom + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, Rom + 0xe000); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(5000000.0/312/262); + + SN76489Init(0, 4000000, 0); + SN76489Init(1, 4000000, 1); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + + SN76496Exit(); + + BurnFree (Mem); + + Mem = Rom = Gfx0 = Gfx1 = Gfx2 = Prom = NULL; + Palette = NULL; + + flipscreen = scroll_x = scroll_y = 0; + + return 0; +} + +static void draw_sprites() +{ + for (INT32 offs = 0x100 - 4; offs >= 0; offs -= 4) + { + if (Rom[0x9001 + offs]) + { + INT32 sx = Rom[0x9003 + offs]; + INT32 sy = Rom[0x9001 + offs] ^ 0xff; + + INT32 code = Rom[0x9000 + offs] & 0x7f; + INT32 color = ((Rom[0x9002 + offs] & 0x0f) << 2) | 0x100; + + INT32 flipx = Rom[0x9002 + offs] & 0x10; + INT32 flipy = Rom[0x9002 + offs] & 0x20; + + UINT8 *src = Gfx2 + (code << 8); + + sx -= 8; + sy -= 32; + + if (flipy) + { + for (INT32 y = sy + 15; y >= sy; y--) + { + if (flipx) + { + for (INT32 x = sx + 15; x >= sx; x--, src++) + { + if (y < 0 || x < 0 || y > 191 || x > 239) continue; + if (!*src) continue; + + INT32 pxl = Palette[color | *src]; + + PutPix(pBurnDraw + ((y * 240) + x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } else { + for (INT32 x = sx; x < sx + 16; x++, src++) + { + if (y < 0 || x < 0 || y > 191 || x > 239) continue; + if (!*src) continue; + + INT32 pxl = Palette[color | *src]; + + PutPix(pBurnDraw + ((y * 240) + x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + } else { + for (INT32 y = sy; y < sy + 16; y++) + { + if (flipx) + { + for (INT32 x = sx + 15; x >= sx; x--, src++) + { + if (y < 0 || x < 0 || y > 191 || x > 239) continue; + if (!*src) continue; + + INT32 pxl = Palette[color | *src]; + + PutPix(pBurnDraw + ((y * 240) + x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } else { + for (INT32 x = sx; x < sx + 16; x++, src++) + { + if (y < 0 || x < 0 || y > 191 || x > 239) continue; + if (!*src) continue; + + INT32 pxl = Palette[color | *src]; + + PutPix(pBurnDraw + ((y * 240) + x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + } + } + } +} + +static void draw_8x8_tiles(UINT8 *vram, UINT8 *gfx_base, INT32 scrollx, INT32 scrolly) +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 2) & 0xf8; + + INT32 code = vram[0x400 + offs] | ((vram[offs] & 0x80) << 1); + INT32 color = (vram[offs] & 0x3f) << 2; + INT32 forcelayer0 = vram[offs] & 0x40; + + UINT8 *src = gfx_base + (code << 6); + + sx = (UINT8)(sx - scrollx); + sy = (UINT8)(sy - scrolly); + + sx -= 8; + sy -= 32; + + for (INT32 y = sy; y < sy + 8; y++) + { + for (INT32 x = sx; x < sx + 8; x++, src++) + { + if (x < 0 || y < 0 || x > 239 || y > 191) continue; + + INT32 pxl = Palette[color | *src]; + if (!*src && !forcelayer0) continue; + + INT32 pos = y * 240 + x; + if (flipscreen) pos = (192 - y) * 240 + (240 - x); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } +} + +static INT32 DrvDraw() +{ + memset (pBurnDraw, 0, 240 * 191 * nBurnBpp); + + draw_8x8_tiles(Rom + 0x8000, Gfx1, scroll_x, scroll_y); + draw_8x8_tiles(Rom + 0x8800, Gfx0, 0, 0); + draw_sprites(); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetOpen(0); + ZetRun(4000000 / 60); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0x8000; + ba.nLen = 0x8000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + SCAN_VAR(flipscreen); + SCAN_VAR(scroll_x); + SCAN_VAR(scroll_y); + } + + return 0; +} + + +// Mr. Do! + +static struct BurnRomInfo mrdoRomDesc[] = { + { "a4-01.bin", 0x2000, 0x03dcfba2, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "c4-02.bin", 0x2000, 0x0ecdd39c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "e4-03.bin", 0x2000, 0x358f5dc2, 1 | BRF_ESS | BRF_PRG }, // 2 + { "f4-04.bin", 0x2000, 0xf4190cfc, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "s8-09.bin", 0x1000, 0xaa80c5b6, 2 | BRF_GRA }, // 4 FG Tiles + { "u8-10.bin", 0x1000, 0xd20ec85b, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "h5-05.bin", 0x1000, 0xe1218cc5, 4 | BRF_GRA }, // 8 Sprite Tiles + { "k5-06.bin", 0x1000, 0xb1f68b04, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrdo) +STD_ROM_FN(mrdo) + +struct BurnDriver BurnDrvmrdo = { + "mrdo", NULL, NULL, NULL, "1982", + "Mr. Do!\0", NULL, "Universal", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrdoRomInfo, mrdoRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + + +// Mr. Do! (Taito license) + +static struct BurnRomInfo mrdotRomDesc[] = { + { "d1", 0x2000, 0x3dcd9359, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "d2", 0x2000, 0x710058d8, 1 | BRF_ESS | BRF_PRG }, // 1 + { "d3", 0x2000, 0x467d12d8, 1 | BRF_ESS | BRF_PRG }, // 2 + { "d4", 0x2000, 0xfce9afeb, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "d9", 0x1000, 0xde4cfe66, 2 | BRF_GRA }, // 4 FG Tiles + { "d10", 0x1000, 0xa6c2f38b, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "h5-05.bin", 0x1000, 0xe1218cc5, 4 | BRF_GRA }, // 8 Sprite Tiles + { "k5-06.bin", 0x1000, 0xb1f68b04, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrdot) +STD_ROM_FN(mrdot) + +struct BurnDriver BurnDrvmrdot = { + "mrdot", "mrdo", NULL, NULL, "1982", + "Mr. Do! (Taito license)\0", NULL, "Universal (Taito license)", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrdotRomInfo, mrdotRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + +// Mr. Do! (bugfixed) + +static struct BurnRomInfo mrdofixRomDesc[] = { + { "d1", 0x2000, 0x3dcd9359, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "d2", 0x2000, 0x710058d8, 1 | BRF_ESS | BRF_PRG }, // 1 + { "dofix.d3", 0x2000, 0x3a7d039b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "dofix.d4", 0x2000, 0x32db845f, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "d9", 0x1000, 0xde4cfe66, 2 | BRF_GRA }, // 4 FG Tiles + { "d10", 0x1000, 0xa6c2f38b, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "h5-05.bin", 0x1000, 0xe1218cc5, 4 | BRF_GRA }, // 8 Sprite Tiles + { "k5-06.bin", 0x1000, 0xb1f68b04, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrdofix) +STD_ROM_FN(mrdofix) + +struct BurnDriver BurnDrvmrdofix = { + "mrdofix", "mrdo", NULL, NULL, "1982", + "Mr. Do! (bugfixed)\0", NULL, "Universal (Taito license)", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrdofixRomInfo, mrdofixRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + + +// Mr. Lo! + +static struct BurnRomInfo mrloRomDesc[] = { + { "mrlo01.bin", 0x2000, 0x6f455e7d, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "d2", 0x2000, 0x710058d8, 1 | BRF_ESS | BRF_PRG }, // 1 + { "dofix.d3", 0x2000, 0x3a7d039b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "mrlo04.bin", 0x2000, 0x49c10274, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "mrlo09.bin", 0x1000, 0xfdb60d0d, 2 | BRF_GRA }, // 4 FG Tiles + { "mrlo10.bin", 0x1000, 0x0492c10e, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "h5-05.bin", 0x1000, 0xe1218cc5, 4 | BRF_GRA }, // 8 Sprite Tiles + { "k5-06.bin", 0x1000, 0xb1f68b04, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrlo) +STD_ROM_FN(mrlo) + +struct BurnDriver BurnDrvmrlo = { + "mrlo", "mrdo", NULL, NULL, "1982", + "Mr. Lo!\0", NULL, "Bootleg", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrloRomInfo, mrloRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + + +// Mr. Du! + +static struct BurnRomInfo mrduRomDesc[] = { + { "d1", 0x2000, 0x3dcd9359, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "d2", 0x2000, 0x710058d8, 1 | BRF_ESS | BRF_PRG }, // 1 + { "d3", 0x2000, 0x467d12d8, 1 | BRF_ESS | BRF_PRG }, // 2 + { "du4.bin", 0x2000, 0x893bc218, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "du9.bin", 0x1000, 0x4090dcdc, 2 | BRF_GRA }, // 4 FG Tiles + { "du10.bin", 0x1000, 0x1e63ab69, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "h5-05.bin", 0x1000, 0xe1218cc5, 4 | BRF_GRA }, // 8 Sprite Tiles + { "k5-06.bin", 0x1000, 0xb1f68b04, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrdu) +STD_ROM_FN(mrdu) + +struct BurnDriver BurnDrvmrdu = { + "mrdu", "mrdo", NULL, NULL, "1982", + "Mr. Du!\0", NULL, "Bootleg", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrduRomInfo, mrduRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + + +// Mr. Do! (prototype) + +static struct BurnRomInfo mrdoyRomDesc[] = { + { "dosnow.1", 0x2000, 0xd3454e2c, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "dosnow.2", 0x2000, 0x5120a6b2, 1 | BRF_ESS | BRF_PRG }, // 1 + { "dosnow.3", 0x2000, 0x96416dbe, 1 | BRF_ESS | BRF_PRG }, // 2 + { "dosnow.4", 0x2000, 0xc05051b6, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "dosnow.9", 0x1000, 0x85d16217, 2 | BRF_GRA }, // 4 FG Tiles + { "dosnow.10", 0x1000, 0x61a7f54b, 2 | BRF_GRA }, // 5 + + { "dosnow.8", 0x1000, 0x2bd1239a, 3 | BRF_GRA }, // 6 BG Tiles + { "dosnow.7", 0x1000, 0xac8ffddf, 3 | BRF_GRA }, // 7 + + { "dosnow.5", 0x1000, 0x7662d828, 4 | BRF_GRA }, // 8 Sprite Tiles + { "dosnow.6", 0x1000, 0x413f88d1, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(mrdoy) +STD_ROM_FN(mrdoy) + +struct BurnDriver BurnDrvmrdoy = { + "mrdoy", "mrdo", NULL, NULL, "1982", + "Mr. Do! (prototype)\0", NULL, "Universal", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, mrdoyRomInfo, mrdoyRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + + +// Yankee DO! + +static struct BurnRomInfo yankeedoRomDesc[] = { + { "a4-01.bin", 0x2000, 0x03dcfba2, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "yd_d2.c4", 0x2000, 0x7c9d7ce0, 1 | BRF_ESS | BRF_PRG }, // 1 + { "e4-03.bin", 0x2000, 0x358f5dc2, 1 | BRF_ESS | BRF_PRG }, // 2 + { "f4-04.bin", 0x2000, 0xf4190cfc, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "s8-09.bin", 0x1000, 0xaa80c5b6, 2 | BRF_GRA }, // 4 FG Tiles + { "u8-10.bin", 0x1000, 0xd20ec85b, 2 | BRF_GRA }, // 5 + + { "r8-08.bin", 0x1000, 0xdbdc9ffa, 3 | BRF_GRA }, // 6 BG Tiles + { "n8-07.bin", 0x1000, 0x4b9973db, 3 | BRF_GRA }, // 7 + + { "yd_d5.h5", 0x1000, 0xf530b79b, 4 | BRF_GRA }, // 8 Sprite Tiles + { "yd_d6.k5", 0x1000, 0x790579aa, 4 | BRF_GRA }, // 9 + + { "u02--2.bin", 0x0020, 0x238a65d7, 5 | BRF_GRA }, // 10 Palette (high bits) + { "t02--3.bin", 0x0020, 0xae263dc0, 5 | BRF_GRA }, // 11 Palette (low bits) + { "f10--1.bin", 0x0020, 0x16ee4ca2, 5 | BRF_GRA }, // 12 Sprite color lookup table + { "j10--4.bin", 0x0020, 0xff7fe284, 5 | BRF_GRA }, // 13 Timing (not used) +}; + +STD_ROM_PICK(yankeedo) +STD_ROM_FN(yankeedo) + +struct BurnDriver BurnDrvyankeedo = { + "yankeedo", "mrdo", NULL, NULL, "1982", + "Yankee DO!\0", NULL, "hack", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, yankeedoRomInfo, yankeedoRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x140, + 192, 240, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_mrflea.cpp b/src/burn/drivers/misc_pre90s/d_mrflea.cpp new file mode 100644 index 00000000..c2cfd65a --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_mrflea.cpp @@ -0,0 +1,643 @@ +// FB Alpha Amazing Adventures of Mr. F. Lea driver module +// Based on MAME driver by Phil Stroffolino + +#include "burnint.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *Rom0, *Rom1, *Ram, *Gfx0, *Gfx1; +static INT32 *Palette; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvDips[2], DrvReset; + +static INT16 *pFMBuffer, *pAY8910Buffer[9]; + +static INT32 mrflea_io; +static INT32 mrflea_main; +static INT32 mrflea_status; +static INT32 mrflea_select[4]; +static UINT8 mrflea_gfx_bank; + +static struct BurnInputInfo DrvInputList[] = { + {"Start 1" , BIT_DIGITAL , DrvJoy1 + 3, "p1 start" }, + {"Start 2" , BIT_DIGITAL , DrvJoy1 + 2, "p2 start" }, + {"P1 Coin" , BIT_DIGITAL , DrvJoy2 + 2, "p1 coin" }, + + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 4, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 5, "p1 left" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 6, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 7, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 1, "p1 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips+0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips+1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Bonus" }, + {0x09, 0x01, 0x03, 0x03, "A" }, + {0x09, 0x01, 0x03, 0x02, "B" }, + {0x09, 0x01, 0x03, 0x01, "C" }, + {0x09, 0x01, 0x03, 0x00, "D" }, + + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0a, 0x01, 0x03, 0x02, "2C 1C" }, + {0x0a, 0x01, 0x03, 0x03, "1C 1C" }, + {0x0a, 0x01, 0x03, 0x00, "2C 3C" }, + {0x0a, 0x01, 0x03, 0x01, "1C 2C" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0a, 0x01, 0x0c, 0x0c, "3" }, + {0x0a, 0x01, 0x0c, 0x08, "4" }, + {0x0a, 0x01, 0x0c, 0x04, "5" }, + {0x0a, 0x01, 0x0c, 0x00, "7" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0x30, 0x30, "Easy" }, + {0x0a, 0x01, 0x30, 0x20, "Medium" }, + {0x0a, 0x01, 0x30, 0x10, "Hard" }, + {0x0a, 0x01, 0x30, 0x00, "Hardest" }, +}; + +STDDIPINFO(Drv) + +void __fastcall mrflea_write(UINT16 a, UINT8 d) +{ + if (a >= 0xe000 && a <= 0xe7ff) // video ram + { + Ram[0xe000 + (a & 0x3ff)] = d; + Ram[0xe400 + (a & 0x3ff)] = (a >> 10) & 1; + return; + } + + if (a >= 0xe800 && a <= 0xe83f) // palette ram + { + Ram[a] = d; + + Palette[(a >> 1) & 0x1f] = ((Ram[a | 1] & 0x0f) | (Ram[a | 1] << 4)) << 16; + Palette[(a >> 1) & 0x1f] |= ((Ram[a &~1] & 0xf0) | (Ram[a &~1] >> 4)) << 8; + Palette[(a >> 1) & 0x1f] |= ((Ram[a &~1] & 0x0f) | (Ram[a &~1] << 4)) << 0; + + return; + } + + if (a >= 0xec00 && a <= 0xecff) // sprite ram + { + if (a & 2) { // tile number + Ram[a | 1] = a & 1; + a &= 0xfffe; + } + + Ram[a] = d; + + return; + } +} + + +void _fastcall mrflea_out_port(UINT16 a, UINT8 data) +{ + switch (a & 0xff) + { + case 0x00: // watchdog? + case 0x43: + break; + + case 0x40: + { + mrflea_status |= 0x08; + mrflea_io = data; + + ZetClose(); + ZetOpen(1); + ZetRaiseIrq(0); + ZetClose(); + ZetOpen(0); + } + break; + + case 0x60: + mrflea_gfx_bank = data; + break; + } +} + +UINT8 _fastcall mrflea_in_port(UINT16 a) +{ + switch (a & 0xff) + { + case 0x41: + mrflea_status &= ~0x01; + return mrflea_main; + + break; + + case 0x42: + return (mrflea_status ^ 0x08); + break; + } + + return 0; +} + +void _fastcall mrflea_cpu1_out_port(UINT16 a, UINT8 data) +{ + switch (a & 0xff) + { + case 0x00: // watchdog + case 0x10: + case 0x11: + case 0x23: + break; + + case 0x21: + mrflea_status |= 0x01; + mrflea_main = data; + break; + + case 0x40: + AY8910Write(0, 0, mrflea_select[0]); + AY8910Write(0, 1, data); + break; + + case 0x42: + break; + + case 0x44: + AY8910Write(1, 0, mrflea_select[2]); + AY8910Write(1, 1, data); + break; + + case 0x46: + AY8910Write(2, 0, mrflea_select[3]); + AY8910Write(2, 1, data); + break; + + case 0x41: + case 0x43: + case 0x45: + case 0x47: + mrflea_select[(a >> 1) & 3] = data; + break; + } +} + +UINT8 __fastcall mrflea_cpu1_in_port(UINT16 a) +{ + UINT8 ret = 0; + + switch (a & 0xff) + { + case 0x10: + if (mrflea_status & 0x08) return 0x00; + return 0x01; + break; + + case 0x20: + mrflea_status &= ~0x08; + return mrflea_io; + + case 0x22: + return (mrflea_status ^ 0x01); + + case 0x40: + if (mrflea_select[0] == 0x0f) { + for (INT32 i = 0; i < 8; i++) { + ret |= DrvJoy1[i] << i; + } + return ~ret; + } + if (mrflea_select[0] == 0x0e) { + for (INT32 i = 0; i < 8; i++) { + ret |= DrvJoy2[i] << i; + } + return ~ret; + } + return 0; + + case 0x44: + if (mrflea_select[2] == 0x0f) return 0xff; + if (mrflea_select[2] == 0x0e) return 0xff; + return 0; + + case 0x42: + case 0x46: + return 0; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + memset (Ram, 0, 0x10000); + + memset (mrflea_select, 0, sizeof(INT32) * 4); + + mrflea_io = 0; + mrflea_main = 0; + mrflea_status = 0; + mrflea_gfx_bank = 0; + + DrvReset = 0; + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + for (INT32 i = 0; i < 3; i++) { + AY8910Reset(i); + } + + return 0; +} + +static INT32 convert_gfx() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x10000); + + for (INT32 i = 0; i < 0x20000; i++) // sprites + { + Gfx0[i^0x07] = ((tmp[0x0000 + (i >> 3)] >> (i & 7)) & 1) << 3; + Gfx0[i^0x07] |= ((tmp[0x4000 + (i >> 3)] >> (i & 7)) & 1) << 2; + Gfx0[i^0x07] |= ((tmp[0x8000 + (i >> 3)] >> (i & 7)) & 1) << 1; + Gfx0[i^0x07] |= ((tmp[0xc000 + (i >> 3)] >> (i & 7)) & 1); + } + + memcpy (tmp, Gfx1, 0x10000); + + for (INT32 i = 0; i < 0x20000; i+=2) // chars + { + Gfx1[i + 0] = (tmp[i>>1] >> 4) & 0x0f; + Gfx1[i + 1] = (tmp[i>>1] >> 0) & 0x0f; + } + + BurnFree (tmp); + + return 0; +} + + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x70000 + (128 * sizeof(INT32))); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16*)BurnMalloc(nBurnSoundLen * 9 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + memset (Mem, 0, 0x70080); + + Rom0 = Mem + 0x000000; + Rom1 = Mem + 0x010000; + Ram = Mem + 0x020000; + Gfx0 = Mem + 0x030000; + Gfx1 = Mem + 0x050000; + Palette = (INT32*)(Mem + 0x70000); + + { + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(Rom0 + i * 0x2000, i, 1)) return 1; + } + + if (BurnLoadRom(Rom1 + 0x0000, 6, 1)) return 1; + if (BurnLoadRom(Rom1 + 0x2000, 7, 1)) return 1; + if (BurnLoadRom(Rom1 + 0x3000, 8, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(Gfx0 + i * 0x2000, i + 9, 1)) return 1; + if (BurnLoadRom(Gfx1 + i * 0x2000, i + 17, 1)) return 1; + } + + if (convert_gfx()) return 1; + } + + ZetInit(2); + ZetOpen(0); + ZetSetInHandler(mrflea_in_port); + ZetSetOutHandler(mrflea_out_port); + ZetSetWriteHandler(mrflea_write); + ZetMapArea(0x0000, 0xbfff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0xbfff, 2, Rom0 + 0x0000); + ZetMapArea(0xc000, 0xcfff, 0, Ram + 0xc000); + ZetMapArea(0xc000, 0xcfff, 1, Ram + 0xc000); + ZetMapArea(0xc000, 0xcfff, 2, Ram + 0xc000); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetInHandler(mrflea_cpu1_in_port); + ZetSetOutHandler(mrflea_cpu1_out_port); + ZetMapArea(0x0000, 0x3fff, 0, Rom1 + 0x0000); + ZetMapArea(0x0000, 0x3fff, 2, Rom1 + 0x0000); + ZetMapArea(0x8000, 0x80ff, 0, Ram + 0x8000); + ZetMapArea(0x8000, 0x80ff, 1, Ram + 0x8000); + ZetMapArea(0x8000, 0x80ff, 2, Ram + 0x8000); + ZetMapArea(0x9000, 0x905a, 0, Ram + 0x9000); + ZetMapArea(0x9000, 0x905a, 1, Ram + 0x9000); + ZetMapArea(0x9000, 0x905a, 2, Ram + 0x9000); + ZetMemEnd(); + ZetClose(); + + for (INT32 i = 0; i < 9; i++) + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + + AY8910Init(0, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(2, 2000000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + AY8910Exit(2); + + BurnFree (Mem); + BurnFree (pFMBuffer); + + Rom0 = Rom1 = Ram = Gfx0 = Gfx1 = NULL; + + pFMBuffer = NULL; + for (INT32 i = 0; i < 9; i++) + pAY8910Buffer[i] = NULL; + + Palette = NULL; + + return 0; +} + + +static INT32 DrvDraw() +{ + INT32 base = ((mrflea_gfx_bank & 0x04) << 8) | ((mrflea_gfx_bank & 0x10) << 5); + + for (INT32 i = 0; i < 0x400; i++) + { + INT32 sy = (i >> 2) & 0xf8; + INT32 sx = (i << 3) & 0xf8; + + if (sy >= 0xf8) continue; + + INT32 code = base + Ram[0xe000 + i] + (Ram[0xe400 + i] << 8); + + UINT8 *src = Gfx1 + code * 64; + + for (INT32 y = sy; y < sy + 8; y++) + { + for (INT32 x = sx; x < sx + 8; x++, src++) + { + INT32 pxl = Palette[*src]; + + PutPix(pBurnDraw + ((y << 8) | x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + + for (INT32 i = 0; i < 0x100; i+=4) + { + INT32 sx = Ram[0xec00 + i + 1]; + INT32 sy = Ram[0xec00 + i + 0] - 13; + + INT32 code = (Ram[0xec00 + i + 2] | (Ram[0xec00 + i + 3] << 8)) << 8; + + UINT8 *src = Gfx0 + code; + + for (INT32 y = sy; y < sy + 16; y++) + { + for (INT32 x = sx; x < sx + 16; x++, src++) + { + if (!*src || x >= 0xff || y >= 0xf8 || y < 0) continue; + + INT32 pxl = Palette[0x10|*src]; + + PutPix(pBurnDraw + ((y << 8) | x) * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + INT32 nInterleave = 200; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + INT32 nCyclesDone[2], nCyclesTotal[2]; + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #0 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if ((mrflea_status&0x08) || i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = Ram; + ba.nLen = 0x10000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = (UINT8*)Palette; + ba.nLen = 0x80 * sizeof(INT32); + ba.szName = "Palette"; + BurnAcb(&ba); + + ZetScan(nAction); // Scan Z80 + + AY8910Scan(nAction, pnMin); // Scan AY8910 + + // Scan critical driver variables + SCAN_VAR(mrflea_io); + SCAN_VAR(mrflea_main); + SCAN_VAR(mrflea_status); + SCAN_VAR(mrflea_gfx_bank); + SCAN_VAR(mrflea_select[0]); + SCAN_VAR(mrflea_select[1]); + SCAN_VAR(mrflea_select[2]); + SCAN_VAR(mrflea_select[3]); + } + + return 0; +} + + +// The Amazing Adventures of Mr. F. Lea + +static struct BurnRomInfo mrfleaRomDesc[] = { + { "cpu_d1", 0x2000, 0xd286217c, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 0 Code + { "cpu_d3", 0x2000, 0x95cf94bc, 1 | BRF_ESS | BRF_PRG }, // 1 + { "cpu_d5", 0x2000, 0x466ca77e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "cpu_b1", 0x2000, 0x721477d6, 1 | BRF_ESS | BRF_PRG }, // 3 + { "cpu_b3", 0x2000, 0xf55b01e4, 1 | BRF_ESS | BRF_PRG }, // 4 + { "cpu_b5", 0x2000, 0x79f560aa, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "io_a11", 0x1000, 0x7a20c3ee, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 1 Code + { "io_c11", 0x1000, 0x8d26e0c8, 2 | BRF_ESS | BRF_PRG }, // 7 + { "io_d11", 0x1000, 0xabd9afc0, 2 | BRF_ESS | BRF_PRG }, // 8 + + { "vd_l10", 0x2000, 0x48b2adf9, 3 | BRF_GRA }, // 9 Sprites + { "vd_l11", 0x2000, 0x2ff168c0, 3 | BRF_GRA }, // 10 + { "vd_l6", 0x2000, 0x100158ca, 3 | BRF_GRA }, // 11 + { "vd_l7", 0x2000, 0x34501577, 3 | BRF_GRA }, // 12 + { "vd_j10", 0x2000, 0x3f29b8c3, 3 | BRF_GRA }, // 13 + { "vd_j11", 0x2000, 0x39380bea, 3 | BRF_GRA }, // 14 + { "vd_j6", 0x2000, 0x2b4b110e, 3 | BRF_GRA }, // 15 + { "vd_j7", 0x2000, 0x3a3c8b1e, 3 | BRF_GRA }, // 16 + + { "vd_k1", 0x2000, 0x7540e3a7, 4 | BRF_GRA }, // 17 Characters + { "vd_k2", 0x2000, 0x6c688219, 4 | BRF_GRA }, // 18 + { "vd_k3", 0x2000, 0x15e96f3c, 4 | BRF_GRA }, // 19 + { "vd_k4", 0x2000, 0xfe5100df, 4 | BRF_GRA }, // 20 + { "vd_l1", 0x2000, 0xd1e3d056, 4 | BRF_GRA }, // 21 + { "vd_l2", 0x2000, 0x4d7fb925, 4 | BRF_GRA }, // 22 + { "vd_l3", 0x2000, 0x6d81588a, 4 | BRF_GRA }, // 23 + { "vd_l4", 0x2000, 0x423735a5, 4 | BRF_GRA }, // 24 +}; + +STD_ROM_PICK(mrflea) +STD_ROM_FN(mrflea) + +struct BurnDriver BurnDrvmrflea = { + "mrflea", NULL, NULL, NULL, "1982", + "The Amazing Adventures of Mr. F. Lea\0", NULL, "Pacific Novelty", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 1, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, mrfleaRomInfo, mrfleaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x80, + 248, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_mystston.cpp b/src/burn/drivers/misc_pre90s/d_mystston.cpp new file mode 100644 index 00000000..335cedc0 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_mystston.cpp @@ -0,0 +1,670 @@ +// FB Alpha Mysterious Stones Driver Module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + + +static UINT8 *Mem, *Rom, *Gfx0, *Gfx1, *Gfx2, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvReset, DrvDips[2]; +static INT16 *pAY8910Buffer[6], *pFMBuffer = NULL; +static INT32 *Palette; + +static INT32 VBLK = 0x80; +static INT32 soundlatch; +static UINT8 mystston_scroll_x = 0; +static INT32 mystston_fgcolor, mystston_flipscreen; + + +//---------------------------------------------------------------------------------------------- +// Input Handlers + + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy2 + 6, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 1, "p1 left" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p2 left" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x11, 0x01, 0x01, 0x01, "3" }, + {0x11, 0x01, 0x01, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x02, 0x02, "Easy" }, + {0x11, 0x01, 0x02, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + // Default Values + {0x12, 0xff, 0xff, 0x1f, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x12, 0x01, 0x03, 0x00, "2C 1C" }, + {0x12, 0x01, 0x03, 0x03, "1C 1C" }, + {0x12, 0x01, 0x03, 0x02, "1C 2C" }, + {0x12, 0x01, 0x03, 0x01, "1C 3C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x12, 0x01, 0x0c, 0x00, "2C 1C" }, + {0x12, 0x01, 0x0c, 0x0c, "1C 1C" }, + {0x12, 0x01, 0x0c, 0x08, "1C 2C" }, + {0x12, 0x01, 0x0c, 0x04, "1C 3C" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x40, 0x00, "Upright" }, + {0x12, 0x01, 0x40, 0x40, "Cocktail" }, +}; + +STDDIPINFO(Drv) + + +//---------------------------------------------------------------------------------------------- +// Memory Read/Write Handlers + + +static void mystston_soundcontrol_w(UINT16, UINT8 data) +{ + static INT32 last; + + if ((last & 0x20) == 0x20 && (data & 0x20) == 0x00) + { + if (last & 0x10) + AY8910Write(0, 0, soundlatch); + else + AY8910Write(0, 1, soundlatch); + } + + if ((last & 0x80) == 0x80 && (data & 0x80) == 0x00) + { + if (last & 0x40) + AY8910Write(1, 0, soundlatch); + else + AY8910Write(1, 1, soundlatch); + } + + last = data; +} + +UINT8 mystston_read_byte(UINT16 address) +{ + UINT8 ret = 0; + + switch (address) + { + case 0x2000: + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy1[i] << i; + + return ~ret; + } + + case 0x2010: + { + for (INT32 i = 0; i < 8; i++) + ret |= DrvJoy2[i] << i; + + return ~ret; + } + + case 0x2020: + return DrvDips[0]; + + case 0x2030: + return DrvDips[1] | VBLK; + } + + return 0; +} + +void mystston_write_byte(UINT16 address, UINT8 data) +{ +#define pal2bit(bits) (((bits & 3) << 6) | ((bits & 3) << 4) | ((bits & 3) << 2) | (bits & 3)) +#define pal3bit(bits) (((bits & 7) << 5) | ((bits & 7) << 2) | ((bits & 7) >> 1)) + + switch (address) + { + case 0x2000: + { + mystston_fgcolor = ((data & 0x01) << 1) + ((data & 0x02) >> 1); + mystston_flipscreen = (data & 0x80) ^ ((DrvDips[1] & 0x20) ? 0x80 : 0); + } + break; + + case 0x2010: + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_NONE); + break; + + case 0x2020: + mystston_scroll_x = data; + break; + + case 0x2030: + soundlatch = data; + break; + + case 0x2040: + mystston_soundcontrol_w(0, data); + break; + } + + if (address >= 0x2060 && address <= 0x2077) + { + Palette[address & 0x1f] = (pal3bit(data) << 16) | (pal3bit(data >> 3) << 8) | pal2bit(data >> 6); + } + +#undef pal2bit +#undef pal3bit +} + + +//---------------------------------------------------------------------------------------------- +// Initilization Routines + + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Rom, 0, 0x2000); + + VBLK = 0x80; + soundlatch = 0; + mystston_flipscreen = 0; + mystston_scroll_x = 0; + mystston_fgcolor = 0; + + AY8910Reset(0); + AY8910Reset(1); + + M6502Open(0); + M6502Reset(); + M6502Close(); + + return 0; +} + +static void mystston_palette_init() +{ + for (INT32 i = 0; i < 32; i++) + { + INT32 bit0, bit1, bit2, r, g, b; + + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit1 = (Prom[i] >> 6) & 0x01; + bit2 = (Prom[i] >> 7) & 0x01; + b = 0x21 * 0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i + 24] = (r << 16) | (g << 8) | b; + } +} + +static INT32 mystston_gfx_convert() +{ + static INT32 PlaneOffsets[3] = { 0x40000, 0x20000, 0 }; + static INT32 XOffsets[16] = { 128, 129, 130, 131, 132, 133, 134, 135, 0, 1, 2, 3, 4, 5, 6, 7 }; + static INT32 YOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x10000); + + GfxDecode(0x800, 3, 8, 8, PlaneOffsets, XOffsets + 8, YOffsets, 0x040, tmp, Gfx0); + GfxDecode(0x200, 3, 16, 16, PlaneOffsets, XOffsets + 0, YOffsets, 0x100, tmp, Gfx2); + + memcpy (tmp, Gfx1, 0x10000); + + GfxDecode(0x200, 3, 16, 16, PlaneOffsets, XOffsets + 0, YOffsets, 0x100, tmp, Gfx1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x20000 + 0x20000 + 0x20000 + 0x20 + (0x38 * sizeof(INT32))); + if (Mem == NULL) { + return 1; + } + memset (Mem, 0, 0x70000 + 0x20); + + pFMBuffer = (INT16 *)BurnMalloc (nBurnSoundLen * 6 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom = Mem + 0x00000; + Gfx0 = Mem + 0x10000; + Gfx1 = Mem + 0x30000; + Gfx2 = Mem + 0x50000; + Prom = Mem + 0x70000; + Palette = (INT32*)(Mem + 0x70020); + + // Load Roms + { + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(Rom + i * 0x2000 + 0x4000, i + 0, 1)) return 1; + if (BurnLoadRom(Gfx0 + i * 0x2000 + 0x0000, i + 6, 1)) return 1; + if (BurnLoadRom(Gfx1 + i * 0x2000 + 0x0000, i + 12, 1)) return 1; + } + + if (BurnLoadRom(Prom, 18, 1)) return 1; + + if(mystston_gfx_convert()) return 1; + mystston_palette_init(); + } + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(Rom + 0x0000, 0x0000, 0x1fff, M6502_RAM); + M6502MapMemory(Rom + 0x4000, 0x4000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(mystston_read_byte); + M6502SetWriteByteHandler(mystston_write_byte); + M6502Close(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + +// BurnSetRefreshRate(57.445); + + return 0; +} + +static INT32 DrvExit() +{ + M6502Exit(); + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (Mem); + BurnFree (pFMBuffer); + + pFMBuffer = NULL; + Palette = NULL; + Rom = Gfx0 = Gfx1 = Gfx2 = Prom = NULL; + + VBLK = 0x00; + soundlatch = 0; + mystston_scroll_x = 0; + mystston_fgcolor = mystston_flipscreen = 0; + + return 0; +} + + +//---------------------------------------------------------------------------------------------- +// Drawing Routines + + +static inline void mystston_putpix(INT32 x, INT32 y, UINT8 src, INT32 color, INT32 transp) +{ + INT32 pos, pxl; + + if (y > 255 || x > 239 || x < 0 || (!src && transp)) return; + + if (mystston_flipscreen) + pos = ((255 - y) * 240) + (239 - x); + else + pos = (y * 240) + x; + + pxl = Palette[color | src]; + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); +} + +static void draw_16x16(INT32 sx, INT32 sy, UINT8 *gfx_base, INT32 code, INT32 color, INT32 flipx, INT32 flipy, INT32 transp) +{ + UINT8 *src = gfx_base + code; + + if (flipx) + { + for (INT32 x = sx + 15; x >= sx; x--) + { + if (flipy) + { + for (INT32 y = sy; y < sy + 16; y++, src++) { + mystston_putpix(x, y, *src, color, transp); + } + } else { + for (INT32 y = sy + 15; y >= sy; y--, src++) { + mystston_putpix(x, y, *src, color, transp); + } + } + } + } else { + for (INT32 x = sx; x < sx + 16; x++) + { + if (flipy) + { + for (INT32 y = sy; y < sy + 16; y++, src++) { + mystston_putpix(x, y, *src, color, transp); + } + } else { + for (INT32 y = sy + 15; y >= sy; y--, src++) { + mystston_putpix(x, y, *src, color, transp); + } + } + } + } +} + +static INT32 DrvDraw() +{ + for (INT32 offs = 0; offs < 0x200; offs++) + { + INT32 code = (Rom[0x1800 + offs] + ((Rom[0x1a00 + offs] & 0x01) << 8)) << 8; + INT32 flipx = offs & 0x10; + INT32 sx = ((offs & 0x1f) << 4) - (mystston_scroll_x + 8); + INT32 sy = ((offs >> 5) << 4); + + draw_16x16(sx, sy, Gfx1, code, 0x10, flipx, 0, 0); + } + + for (INT32 offs = 0; offs < 0x60; offs += 4) + { + INT32 attr = Rom[0x0780 + offs]; + + if (attr & 0x01) + { + INT32 code = (Rom[0x0781 + offs] + ((attr & 0x10) << 4)) << 8; + INT32 color = attr & 0x08; + INT32 flipy = attr & 0x04; + INT32 flipx = attr & 0x02; + INT32 sy = Rom[0x0783 + offs]; + INT32 sx = (240 - Rom[0x0782 + offs]) - 9; + + draw_16x16(sx, sy, Gfx2, code, color, flipx, flipy, 1); + } + } + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 code = (Rom[0x1000 | offs] + ((Rom[0x1400 + offs] & 0x07) << 8)) << 6; + INT32 color = (mystston_fgcolor << 3) + 0x18; + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 2) & 0xf8; + if (sx >= 248 || sx < 8) continue; + sx -= 8; + + UINT8 *src = Gfx0 + code; + + for (INT32 x = sx; x < sx + 8; x++) + { + for (INT32 y = sy + 7; y >= sy; y--, src++) + { + if (!*src) continue; + + INT32 pos; + if (mystston_flipscreen) + pos = ((255 - y) * 240) + (239 - x); + else + pos = (y * 240) + x; + + INT32 pxl = Palette[color | *src]; + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + + return 0; +} + +static void mystston_interrupt_handler(INT32 scanline) +{ + static INT32 coin; + INT32 inp = (DrvJoy1[6] << 6) | (DrvJoy1[7] << 7); + + if ((~inp & 0xc0) != 0xc0) + { + if (coin == 0) + { + coin = 1; + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + return; + } + } + else coin = 0; + + if (scanline == 8) + VBLK = 0; + + if (scanline == 248) + VBLK = 0x80; + + if ((scanline & 0x0f) == 0) + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_ACK); +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nTotalCycles = (INT32)((double)(1500000 / 57.45)); + INT32 nCyclesRun = 0; + + M6502Open(0); + + for (INT32 i = 0; i < 272; i++) { + nCyclesRun += M6502Run(nTotalCycles / 272); + mystston_interrupt_handler(i); + } + + M6502Close(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +//---------------------------------------------------------------------------------------------- +// Save State + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom + 0x0000; + ba.nLen = 0x2000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = Mem + 0x70020; + ba.nLen = 24 * sizeof(INT32); + ba.szName = "Palette"; + BurnAcb(&ba); + + M6502Scan(nAction); + AY8910Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(mystston_flipscreen); + SCAN_VAR(mystston_scroll_x); + SCAN_VAR(mystston_fgcolor); + SCAN_VAR(soundlatch); + SCAN_VAR(VBLK); + } + + return 0; +} + + +//---------------------------------------------------------------------------------------------- +// Game Drivers + + +// Mysterious Stones - Dr. John's Adventure + +static struct BurnRomInfo myststonRomDesc[] = { + { "rom6.bin", 0x2000, 0x7bd9c6cd, 1 | BRF_PRG | BRF_ESS }, // 0 M6205 Code + { "rom5.bin", 0x2000, 0xa83f04a6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rom4.bin", 0x2000, 0x46c73714, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rom3.bin", 0x2000, 0x34f8b8a3, 1 | BRF_PRG | BRF_ESS }, // 3 + { "rom2.bin", 0x2000, 0xbfd22cfc, 1 | BRF_PRG | BRF_ESS }, // 4 + { "rom1.bin", 0x2000, 0xfb163e38, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ms6", 0x2000, 0x85c83806, 2 | BRF_GRA }, // 6 Character + Sprite Tiles + { "ms9", 0x2000, 0xb146c6ab, 2 | BRF_GRA }, // 7 + { "ms7", 0x2000, 0xd025f84d, 2 | BRF_GRA }, // 8 + { "ms10", 0x2000, 0xd85015b5, 2 | BRF_GRA }, // 9 + { "ms8", 0x2000, 0x53765d89, 2 | BRF_GRA }, // 10 + { "ms11", 0x2000, 0x919ee527, 2 | BRF_GRA }, // 11 + + { "ms12", 0x2000, 0x72d8331d, 3 | BRF_GRA }, // 12 Sprite Tiles + { "ms13", 0x2000, 0x845a1f9b, 3 | BRF_GRA }, // 13 + { "ms14", 0x2000, 0x822874b0, 3 | BRF_GRA }, // 14 + { "ms15", 0x2000, 0x4594e53c, 3 | BRF_GRA }, // 15 + { "ms16", 0x2000, 0x2f470b0f, 3 | BRF_GRA }, // 16 + { "ms17", 0x2000, 0x38966d1b, 3 | BRF_GRA }, // 17 + + { "ic61", 0x0020, 0xe802d6cf, 4 | BRF_GRA }, // 18 Color Prom +}; + +STD_ROM_PICK(mystston) +STD_ROM_FN(mystston) + +struct BurnDriver BurnDrvmystston = { + "mystston", NULL, NULL, NULL, "1984", + "Mysterious Stones - Dr. John's Adventure\0", NULL, "Technos", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, myststonRomInfo, myststonRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 24, + 240, 256, 3, 4 +}; + + +// Mysterious Stones - Dr. Kick in Adventure + +static struct BurnRomInfo myststnoRomDesc[] = { + { "ms0", 0x2000, 0x6dacc05f, 1 | BRF_PRG | BRF_ESS }, // 0 M6205 Code + { "ms1", 0x2000, 0xa3546df7, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ms2", 0x2000, 0x43bc6182, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ms3", 0x2000, 0x9322222b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ms4", 0x2000, 0x47cefe9b, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ms5", 0x2000, 0xb37ae12b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ms6", 0x2000, 0x85c83806, 2 | BRF_GRA }, // 6 Character + Sprite Tiles + { "ms9", 0x2000, 0xb146c6ab, 2 | BRF_GRA }, // 7 + { "ms7", 0x2000, 0xd025f84d, 2 | BRF_GRA }, // 8 + { "ms10", 0x2000, 0xd85015b5, 2 | BRF_GRA }, // 9 + { "ms8", 0x2000, 0x53765d89, 2 | BRF_GRA }, // 10 + { "ms11", 0x2000, 0x919ee527, 2 | BRF_GRA }, // 11 + + { "ms12", 0x2000, 0x72d8331d, 3 | BRF_GRA }, // 12 Sprite Tiles + { "ms13", 0x2000, 0x845a1f9b, 3 | BRF_GRA }, // 13 + { "ms14", 0x2000, 0x822874b0, 3 | BRF_GRA }, // 14 + { "ms15", 0x2000, 0x4594e53c, 3 | BRF_GRA }, // 15 + { "ms16", 0x2000, 0x2f470b0f, 3 | BRF_GRA }, // 16 + { "ms17", 0x2000, 0x38966d1b, 3 | BRF_GRA }, // 17 + + { "ic61", 0x0020, 0xe802d6cf, 4 | BRF_GRA }, // 18 Color Prom +}; + +STD_ROM_PICK(myststno) +STD_ROM_FN(myststno) + +struct BurnDriver BurnDrvmyststno = { + "myststono", "mystston", NULL, NULL, "1984", + "Mysterious Stones - Dr. Kick in Adventure\0", NULL, "Technos", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, myststnoRomInfo, myststnoRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 24, + 240, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_pac2650.cpp b/src/burn/drivers/misc_pre90s/d_pac2650.cpp new file mode 100644 index 00000000..2aeae148 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_pac2650.cpp @@ -0,0 +1,612 @@ +// FB Alpha Pac-Man-based S2650 game hardware driver module +// Based on MAME driver by Nicola Salmoria and many others + +#include "tiles_generic.h" +#include "s2650_intf.h" +#include "sn76496.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvPrgROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvPrgRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvScrRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvSprRAM0; +static UINT8 *DrvSprRAM1; +static UINT8 *DrvSprRAM2; +static UINT8 *flipscreen; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvDips[1]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; + +static INT32 s2650_bank; +static INT32 watchdog; +static INT32 vblank; + +static struct BurnInputInfo DrivfrcpInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Drivfrcp) + +static struct BurnInputInfo _8bpmInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(_8bpm) + +static struct BurnInputInfo PorkyInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 5, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 6, "p2 start" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, +}; + +STDINPUTINFO(Porky) + +static struct BurnDIPInfo DrivfrcpDIPList[]= +{ + {0x07, 0xff, 0xff, 0x00, NULL }, +}; + +STDDIPINFO(Drivfrcp) + +static struct BurnDIPInfo _8bpmDIPList[]= +{ + {0x0f, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0f, 0x01, 0x01, 0x00, "Upright" }, + {0x0f, 0x01, 0x01, 0x01, "Cocktail" }, +}; + +STDDIPINFO(_8bpm) + +static struct BurnDIPInfo PorkyDIPList[]= +{ + {0x0e, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0e, 0x01, 0x01, 0x00, "Upright" }, + {0x0e, 0x01, 0x01, 0x01, "Cocktail" }, +}; + +STDDIPINFO(Porky) + +static inline void bankswitch(INT32 data) +{ + INT32 bank = (data & 1) ? 0x4000 : 0; + + if (s2650_bank != (data & 1)) { + + for (INT32 i = 0; i <= 0x8000; i+= 0x8000) { + s2650MapMemory(DrvPrgROM + 0x00000 + bank, 0x0000 | i, 0x0fff | i, S2650_ROM); + s2650MapMemory(DrvPrgROM + 0x01000 + bank, 0x2000 | i, 0x2fff | i, S2650_ROM); + s2650MapMemory(DrvPrgROM + 0x02000 + bank, 0x4000 | i, 0x4fff | i, S2650_ROM); + s2650MapMemory(DrvPrgROM + 0x03000 + bank, 0x6000 | i, 0x6fff | i, S2650_ROM); + } + + s2650_bank = data & 1; + } +} + +static void s2650games_write(UINT16 address, UINT8 data) +{ + switch (address & 0x1fff) + { + case 0x1503: + *flipscreen = data & 1; + return; + + case 0x1507: // coin counter + return; + + case 0x15c0: + watchdog = 0; + return; + + case 0x15c7: + bankswitch(data); + return; + } + + if ((address & 0x1c00) == 0x1000) { + DrvColRAM[address & 0x1f] = data; + return; + } + + if ((address & 0x1ff0) == 0x1560) { + DrvSprRAM2[address & 0x0f] = data; + return; + } +} + +static UINT8 s2650games_read(UINT16 address) +{ + switch (address & 0x1fff) + { + case 0x1500: + return DrvInputs[0]; + + case 0x1540: + return DrvInputs[1]; + + case 0x1580: + return DrvDips[0]; + } + + return 0; +} + +static void s2650games_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0x1ff) + { + case S2650_DATA_PORT: + SN76496Write(0, data); + return; + } +} + +static UINT8 s2650games_read_port(UINT16 port) +{ + switch (port & 0x1ff) + { + case S2650_SENSE_PORT: + return vblank ? 0 : 0x80; + + case 0x01: + { + switch (s2650GetPc()) + { + case 0x0030: // drivfrcp & _8bpm + case 0x0034: // porky + case 0x0291: // drivfrcp + case 0x0466: // _8bpm + return 1; + } + + return 0; + } + } + + return 0; +} + +static INT32 DrvDoReset(INT32 clear_ram) +{ + if (clear_ram) { + memset (AllRam, 0, RamEnd - AllRam); + } + + s2650Open(0); + s2650_bank = -1; + bankswitch(0); + s2650Reset(); + s2650Close(); + + watchdog = 0; + + return 0; +} + +static void DrvPaletteInit() +{ + UINT32 tmp[32]; + + for (INT32 i = 0; i < 32; i++) + { + INT32 bit0, bit1, bit2; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + INT32 r = (bit0 * 33) + (bit1 * 71) + (bit2 * 151); + + bit0 = (DrvColPROM[i] >> 3) & 0x01; + bit1 = (DrvColPROM[i] >> 4) & 0x01; + bit2 = (DrvColPROM[i] >> 5) & 0x01; + INT32 g = (bit0 * 33) + (bit1 * 71) + (bit2 * 151); + + bit0 = (DrvColPROM[i] >> 6) & 0x01; + bit1 = (DrvColPROM[i] >> 7) & 0x01; + INT32 b = (bit0 * 81) + (bit1 * 174); + + tmp[i] = BurnHighCol(r, g, b, 0); + } + + for (INT32 i = 0; i < 128; i++) + { + INT32 ctabentry = DrvColPROM[i + 0x20] &= 0x0f; + DrvPalette[i] = tmp[ctabentry]; + } +} + +static void DrvGfxDecode() +{ + INT32 Planes[2] = { 0, 4 }; + INT32 XOffs0[8] = { 8*8, 8*8+1, 8*8+2, 8*8+3, 0, 1, 2, 3 }; + INT32 XOffs1[16] = { 8*8, 8*8+1, 8*8+2, 8*8+3, 16*8+0, 16*8+1, 16*8+2, 16*8+3, 24*8+0, 24*8+1, 24*8+2, 24*8+3, 0, 1, 2, 3 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,32*8, 33*8, 34*8, 35*8, 36*8, 37*8, 38*8, 39*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc( 0x4000 ); + if (tmp) + { + memcpy (tmp, DrvGfxROM0, 0x4000); + + GfxDecode(0x400, 2, 8, 8, Planes, XOffs0, YOffs, 0x080, tmp, DrvGfxROM0); + GfxDecode(0x100, 2, 16, 16, Planes, XOffs1, YOffs, 0x200, tmp, DrvGfxROM1); + + BurnFree (tmp); + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvPrgROM = Next; Next += 0x008000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000120; + + DrvPalette = (UINT32*)Next; Next += 0x080 * sizeof(UINT32); + + AllRam = Next; + + DrvPrgRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + DrvScrRAM = Next; Next += 0x000100; + DrvColRAM = Next; Next += 0x000020; + DrvSprRAM2 = Next; Next += 0x000010; + DrvSprRAM1 = DrvScrRAM + 0x090; + DrvSprRAM0 = DrvPrgRAM + 0x3f0; + + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit(INT32 game, INT32 swap) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvPrgROM, 0, 1)) return 1; + memcpy (DrvPrgROM + 0x4000, DrvPrgROM, 0x4000); + + if (game) { + if (BurnLoadRom(DrvPrgROM + 0x4000, 1, 1)) return 1; + } + + for (INT32 i = 0; i < 0x8000; i++) { // porky & 8bpm have data lines scrambled + DrvPrgROM[i] = (DrvPrgROM[i] & ~(1 | (1 << swap))) | ((DrvPrgROM[i] >> swap) & 1) | ((DrvPrgROM[i] & 1) << swap); + } + + if (BurnLoadRom(DrvGfxROM1, 1 + game, 1)) return 1; + + for (INT32 i = 0; i < 0x4000; i++) { + DrvGfxROM0[((i & 0x2000) >> 1) | ((i & 0x1000) << 1) | (i & 0xfff)] = DrvGfxROM1[i]; + } + + if (BurnLoadRom(DrvColPROM + 0x000, 2 + game, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x020, 3 + game, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + s2650Init(1); + s2650Open(0); + for (INT32 i = 0; i <= 0xe000; i+= 0x2000) { + s2650MapMemory(DrvScrRAM, 0x1400 | i, 0x14ff | i, S2650_RAM); + s2650MapMemory(DrvVidRAM, 0x1800 | i, 0x1bff | i, S2650_RAM); + s2650MapMemory(DrvPrgRAM, 0x1c00 | i, 0x1fff | i, S2650_RAM); + } + s2650SetWriteHandler(s2650games_write); + s2650SetReadHandler(s2650games_read); + s2650SetOutHandler(s2650games_write_port); + s2650SetInHandler(s2650games_read_port); + s2650Close(); + + SN76489Init(0, 307200, 0); + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 drivfrcpInit() { return DrvInit(0,0); } +static INT32 _8bpmInit() { return DrvInit(0,6); } +static INT32 porkyInit() { return DrvInit(1,4); } + +static INT32 DrvExit() +{ + GenericTilesExit(); + + s2650Exit(); + SN76496Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer() +{ + UINT8 *ram = DrvScrRAM + 0x00a0; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sy = (offs >> 5) << 3; + INT32 sx = (offs & 0x1f) << 3; + + sy -= DrvScrRAM[offs & 0x1f] + 16; + if (sy < -7) sy += 256; + + if (sy >= nScreenHeight) continue; + + INT32 code = DrvVidRAM[offs] | ((ram[offs & 0x1f] & 0x03) << 8); + INT32 color = DrvColRAM[offs & 0x1f] & 0x1f; + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, 248 - sx, 216 - sy, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x0e; offs >= 0; offs -= 2) + { + INT32 attr = DrvSprRAM0[offs]; + INT32 sx = DrvSprRAM2[offs + 1] ^ 0xff; + INT32 sy = DrvSprRAM2[offs] - 15; + INT32 color = DrvSprRAM0[offs + 1] & 0x1f; + INT32 code = (attr >> 2) | ((DrvSprRAM1[offs] & 3) << 6); + INT32 flipx = attr & 0x01; + INT32 flipy = attr & 0x02; + + if (offs <= 4) sy += 1; // hack + + RenderTileTranstab(pTransDraw, DrvGfxROM1, code, color << 2, 0, sx, sy - 16, flipx, flipy, 16, 16, DrvColPROM + 0x020); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + DrvPaletteInit(); + DrvRecalc = 0; + } + + draw_layer(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(1); + } + + if (watchdog >= 180) { + DrvDoReset(0); + } + watchdog++; + + { + memset (DrvInputs, 0xff, 2); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + s2650Open(0); + + vblank = 0; + + for (INT32 i = 0; i < 32; i++) { + if (i == 31) { + vblank = 1; + s2650_set_irq_line(0x03, 1); + } + INT32 nSegment = (1536000 / 60) / 32; + + s2650Run(nSegment); + + if (i == 31) { + s2650_set_irq_line(0x03, 0); + } + } + + s2650Close(); + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029709; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + s2650Scan(nAction, pnMin); + + SCAN_VAR(watchdog); + SCAN_VAR(s2650_bank); + } + + if (nAction & ACB_WRITE) { + s2650Open(0); + INT32 bank = s2650_bank; + s2650_bank = -1; + bankswitch(bank); + s2650Close(); + } + + return 0; +} + + +// Driving Force (Pac-Man conversion) + +static struct BurnRomInfo drivfrcpRomDesc[] = { + { "drivforc.1", 0x4000, 0x10b59d27, 1 | BRF_PRG | BRF_ESS }, // 0 s2650 Code + + { "drivforc.2", 0x4000, 0x56331cb5, 2 | BRF_GRA }, // 1 Tiles and Sprites + + { "drivforc.pr1", 0x0020, 0x045aa47f, 3 | BRF_GRA }, // 2 Color PROMs + { "drivforc.pr2", 0x0100, 0x9e6d2f1d, 3 | BRF_GRA }, // 3 +}; + +STD_ROM_PICK(drivfrcp) +STD_ROM_FN(drivfrcp) + +struct BurnDriver BurnDrvDrivfrcp = { + "drivfrcp", NULL, NULL, NULL, "1984", + "Driving Force (Pac-Man conversion)\0", NULL, "Shinkai Inc. (Magic Eletronics Inc. license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_PACMAN, GBF_RACING, 0, + NULL, drivfrcpRomInfo, drivfrcpRomName, NULL, NULL, DrivfrcpInputInfo, DrivfrcpDIPInfo, + drivfrcpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x80, + 224, 256, 3, 4 +}; + + +// Eight Ball Action (Pac-Man conversion) + +static struct BurnRomInfo _8bpmRomDesc[] = { + { "8bpmp.bin", 0x4000, 0xb4f7eba7, 1 | BRF_PRG | BRF_ESS }, // 0 s2650 Code + + { "8bpmc.bin", 0x4000, 0x1c894a6d, 2 | BRF_GRA }, // 1 Tiles and Sprites + + { "8bpm.7f", 0x0020, 0x4cf54241, 3 | BRF_GRA }, // 2 Color PROMs + { "8bpm.4a", 0x0100, 0x618505a0, 3 | BRF_GRA }, // 3 +}; + +STD_ROM_PICK(_8bpm) +STD_ROM_FN(_8bpm) + +struct BurnDriver BurnDrv_8bpm = { + "8bpm", "8ballact", NULL, NULL, "1985", + "Eight Ball Action (Pac-Man conversion)\0", NULL, "Seatongrove Ltd (Magic Eletronics USA license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_SPORTSMISC, 0, + NULL, _8bpmRomInfo, _8bpmRomName, NULL, NULL, _8bpmInputInfo, _8bpmDIPInfo, + _8bpmInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x80, + 224, 256, 3, 4 +}; + + +// Porky + +static struct BurnRomInfo porkyRomDesc[] = { + { "pp", 0x4000, 0x00592624, 1 | BRF_PRG | BRF_ESS }, // 0 s2650 Code + { "ps", 0x4000, 0x2efb9861, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "pc", 0x4000, 0xa20e3d39, 2 | BRF_GRA }, // 2 Tiles and Sprites + + { "7f", 0x0020, 0x98bce7cc, 3 | BRF_GRA }, // 3 Color PROMs + { "4a", 0x0100, 0x30fe0266, 3 | BRF_GRA }, // 4 +}; + +STD_ROM_PICK(porky) +STD_ROM_FN(porky) + +struct BurnDriver BurnDrvPorky = { + "porky", NULL, NULL, NULL, "1985", + "Porky\0", NULL, "Shinkai Inc. (Magic Eletronics Inc. license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MISC, 0, + NULL, porkyRomInfo, porkyRomName, NULL, NULL, PorkyInputInfo, PorkyDIPInfo, + porkyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x80, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_pacman.cpp b/src/burn/drivers/misc_pre90s/d_pacman.cpp new file mode 100644 index 00000000..0bfe4006 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_pacman.cpp @@ -0,0 +1,6349 @@ +// FB Alpha Puckman module +// Based on MAME driver by Nicola Salmoria and many others + +// Fix Shoot the Bull inputs + +#include "tiles_generic.h" +#include "bitswap.h" +#include "sn76496.h" +#include "namco_snd.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvQROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprRAM2; +static UINT8 *DrvColPROM; +static UINT8 *DrvTransTable; + +static INT16 *pAY8910Buffer[3]; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[8] = {0,0,0,0,0,0,0,0}; +static UINT8 DrvJoy2[8] = {0,0,0,0,0,0,0,0}; +static UINT8 DrvInputs[2] = {0,0}; +static UINT8 DrvDips[4] = {0,0,0,0}; +static INT16 DrvAxis[2] = { 0, 0 }; +static INT16 nAnalogAxis[2] = {0,0}; +static UINT8 nCharAxis[2] = {0,0}; + +enum { PACMAN=0, MSPACMAN, CANNONBP, MAKETRAX, PIRANHA, VANVAN, NMOUSE, DREMSHPR, + MSCHAMP, BIGBUCKS, ROCKTRV2, ALIBABA, CRUSHS, SHOOTBUL, BIRDIY, EPOS, PENGO }; + +static INT32 game_select; +static INT32 acitya = 0; + +static UINT8 *flipscreen; + +static INT32 interrupt_mode; +static INT32 interrupt_mask; + +static UINT8 colortablebank; +static UINT8 palettebank; +static UINT8 spritebank; +static UINT8 charbank; +static INT32 nPacBank; + +static INT32 alibaba_mystery; +static UINT8 *rocktrv2_prot_data; +static INT8 epos_hardware_counter; +static UINT8 mschamp_counter; +static UINT8 cannonb_bit_to_read; + +static UINT32 watchdog; + +//------------------------------------------------------------------------------------------------------ + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1 ", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo lizwizInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 4, "diag"}, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 6, "tilt"}, + + {"Dip Switches 1 ", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(lizwiz) + +static struct BurnInputInfo PengoInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip D", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(Pengo) + +static struct BurnInputInfo mschampInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Coin 3", BIT_DIGITAL, DrvJoy1 + 7, "p3 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(mschamp) + +static struct BurnInputInfo eyesInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Tilt", BIT_DIGITAL, DrvJoy1 + 6, "tilt"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(eyes) + +static struct BurnInputInfo theglobpInputList[] = { + {"Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 2"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, +}; + +STDINPUTINFO(theglobp) + +static struct BurnInputInfo ponpokoInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 3, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(ponpoko) + +static struct BurnInputInfo vanvanInputList[] = { + {"Coin", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(vanvan) + +static struct BurnInputInfo vanvankInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin"}, + + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(vanvank) + +static struct BurnInputInfo cannonbpInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(cannonbp) + +static struct BurnInputInfo rocktrv2InputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + + {"Tilt", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 3, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(rocktrv2) + +static struct BurnInputInfo bigbucksInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, +}; + +STDINPUTINFO(bigbucks) + +static struct BurnInputInfo woodpekInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(woodpek) + +static struct BurnInputInfo acityaInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 4"}, + {"P1 Button 5", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 5"}, + {"P1 Button 6", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 6"}, + + {"Service Mode 1", BIT_DIGITAL, DrvJoy1 + 4, "diag"}, + {"Service Mode 2", BIT_DIGITAL, DrvJoy2 + 4, "diag"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, +}; + +STDINPUTINFO(acitya) + +static struct BurnInputInfo bwcasinoInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 3"}, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 4"}, + {"P1 Button 5", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 5"}, + {"P1 Button 6", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 6"}, + + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 3"}, + {"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 4"}, + {"P2 Button 5", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 5"}, + {"P2 Button 6", BIT_DIGITAL, DrvJoy1 + 7, "p2 fire 6"}, + + {"Service Mode ", BIT_DIGITAL, DrvJoy1 + 4, "diag"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 0, "dip"}, +}; + +STDINPUTINFO(bwcasino) + +static struct BurnInputInfo dremshprInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire "}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(dremshpr) + +static struct BurnInputInfo alibabaInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(alibaba) + +static struct BurnInputInfo jumpshotInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(jumpshot) + +static struct BurnInputInfo korosukeInputList[] = { + {"Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin"}, + {"Start 1", BIT_DIGITAL, DrvJoy2 + 5, "p1 start"}, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 6, "p2 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 2, "p2 right"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag"}, + + {"Dip Switches 1 ", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, + {"Dip Switches 4", BIT_DIPSWITCH, DrvDips + 3, "dip"}, +}; + +STDINPUTINFO(korosuke) + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo shootbulInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 coin"}, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 6, "p2 coin"}, + {"Coin 3", BIT_DIGITAL, DrvJoy1 + 7, "p3 coin"}, + {"Start", BIT_DIGITAL, DrvJoy2 + 6, "p1 start"}, + + A("P1 X Axis", BIT_ANALOG_REL, DrvAxis + 0, "mouse x-axis"), + A("P1 Y Axis", BIT_ANALOG_REL, DrvAxis + 1, "mouse y-axis"), + + {"P1 Button A", BIT_DIGITAL, DrvJoy2 + 5, "mouse button 1"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + + {"Dip Switches 1", BIT_DIPSWITCH, DrvDips + 2, "dip"}, + {"Dip Switches 2", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip Switches 3", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(shootbul) + +#undef A + + +static struct BurnDIPInfo DrvDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xc9, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x30, 0x00, "10000" }, + {0x0e, 0x01, 0x30, 0x10, "15000" }, + {0x0e, 0x01, 0x30, 0x20, "20000" }, + {0x0e, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x40, 0x40, "Normal" }, + {0x0e, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Ghost Names" }, + {0x0e, 0x01, 0x80, 0x80, "Normal" }, + {0x0e, 0x01, 0x80, 0x00, "Alternate" }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo PengoDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xb0, NULL }, + {0x12, 0xff, 0xff, 0xcc, NULL }, + + {0 , 0xfe, 0 , 1, "Service Mode" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x11, 0x01, 0x01, 0x00, "30000" }, + {0x11, 0x01, 0x01, 0x01, "50000" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x11, 0x01, 0x04, 0x00, "Upright" }, + {0x11, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x18, 0x18, "2" }, + {0x11, 0x01, 0x18, 0x10, "3" }, + {0x11, 0x01, 0x18, 0x08, "4" }, + {0x11, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Rack Test (Cheat)" }, + {0x11, 0x01, 0x20, 0x20, "Off" }, + {0x11, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0xc0, 0xc0, "Easy" }, + {0x11, 0x01, 0xc0, 0x80, "Medium" }, + {0x11, 0x01, 0xc0, 0x40, "Hard" }, + {0x11, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x12, 0x01, 0x0f, 0x00, "4 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x08, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x04, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x0f, 0x09, "2 Coins/1 Credit 5/3" }, + {0x12, 0x01, 0x0f, 0x05, "2 Coins/1 Credit 4/3" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin/1 Credit 5/6" }, + {0x12, 0x01, 0x0f, 0x03, "1 Coin/1 Credit 4/5" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin/1 Credit 2/3" }, + {0x12, 0x01, 0x0f, 0x02, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x0f, 0x07, "1 Coin/2 Credits 5/11" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin/2 Credits 4/9" }, + {0x12, 0x01, 0x0f, 0x0a, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x0f, 0x06, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x0f, 0x01, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x12, 0x01, 0xf0, 0x00, "4 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x80, "3 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x40, "2 Coins 1 Credits" }, + {0x12, 0x01, 0xf0, 0x90, "2 Coins/1 Credit 5/3" }, + {0x12, 0x01, 0xf0, 0x50, "2 Coins/1 Credit 4/3" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 1 Credits" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin/1 Credit 5/6" }, + {0x12, 0x01, 0xf0, 0x30, "1 Coin/1 Credit 4/5" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin/1 Credit 2/3" }, + {0x12, 0x01, 0xf0, 0x20, "1 Coin 2 Credits" }, + {0x12, 0x01, 0xf0, 0x70, "1 Coin/2 Credits 5/11" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin/2 Credits 4/9" }, + {0x12, 0x01, 0xf0, 0xa0, "1 Coin 3 Credits" }, + {0x12, 0x01, 0xf0, 0x60, "1 Coin 4 Credits" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 5 Credits" }, + {0x12, 0x01, 0xf0, 0x10, "1 Coin 6 Credits" }, +}; + +STDDIPINFO(Pengo) + +static struct BurnDIPInfo mspacmanDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xc9, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x30, 0x00, "10000" }, + {0x0e, 0x01, 0x30, 0x10, "15000" }, + {0x0e, 0x01, 0x30, 0x20, "20000" }, + {0x0e, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x40, 0x40, "Normal" }, + {0x0e, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, +}; + +STDDIPINFO(mspacman) + +static struct BurnDIPInfo mschampDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xc9, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x30, 0x00, "10000" }, + {0x0e, 0x01, 0x30, 0x10, "15000" }, + {0x0e, 0x01, 0x30, 0x20, "20000" }, + {0x0e, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x40, 0x40, "Normal" }, + {0x0e, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Game" }, + {0x11, 0x01, 0x01, 0x01, "Champion Edition" }, + {0x11, 0x01, 0x01, 0x00, "Super Zola Pac Gal" }, +}; + +STDDIPINFO(mschamp) + +static struct BurnDIPInfo maketraxDIPList[]= +{ + {0x0e, 0xff, 0x3f, 0x31, NULL }, + {0x0f, 0xff, 0xff, 0xef, NULL }, + {0x10, 0xff, 0x6f, 0x6f, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x10, 0x00, "Upright" }, + {0x0f, 0x01, 0x10, 0x10, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "3" }, + {0x0e, 0x01, 0x0c, 0x04, "4" }, + {0x0e, 0x01, 0x0c, 0x08, "5" }, + {0x0e, 0x01, 0x0c, 0x0c, "6" }, + + {0 , 0xfe, 0 , 2 , "First Pattern" }, + {0x0e, 0x01, 0x30, 0x10, "Easy" }, + {0x0e, 0x01, 0x30, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Teleport Holes" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(maketrax) + +static struct BurnDIPInfo mbrushDIPList[]= +{ + {0x0e, 0xff, 0xff, 0x39, NULL }, + {0x0f, 0xff, 0xff, 0xef, NULL }, + {0x10, 0xff, 0xff, 0x6f, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x10, 0x00, "Upright" }, + {0x0f, 0x01, 0x10, 0x10, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x0c, "4" }, +}; + +STDDIPINFO(mbrush) + +static struct BurnDIPInfo crushsDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2 , "Teleport Holes" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x11, 0x01, 0x0f, 0x08, "2C 1C" }, + {0x11, 0x01, 0x0f, 0x09, "2C 2C" }, + {0x11, 0x01, 0x0f, 0x00, "1C 1C" }, + {0x11, 0x01, 0x0f, 0x0a, "2C 3C" }, + {0x11, 0x01, 0x0f, 0x0b, "2C 4C" }, + {0x11, 0x01, 0x0f, 0x01, "2C 2C" }, + {0x11, 0x01, 0x0f, 0x0c, "1C 5C" }, + {0x11, 0x01, 0x0f, 0x0d, "2C 6C" }, + {0x11, 0x01, 0x0f, 0x02, "1C 3C" }, + {0x11, 0x01, 0x0f, 0x0e, "2C 7C" }, + {0x11, 0x01, 0x0f, 0x0f, "2C 8C" }, + {0x11, 0x01, 0x0f, 0x03, "1C 4C" }, + {0x11, 0x01, 0x0f, 0x04, "1C 5C" }, + {0x11, 0x01, 0x0f, 0x05, "1C 6C" }, + {0x11, 0x01, 0x0f, 0x06, "1C 7C" }, + {0x11, 0x01, 0x0f, 0x07, "1C 8C" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x11, 0x01, 0xf0, 0x80, "2C 1C" }, + {0x11, 0x01, 0xf0, 0x90, "2C 2C" }, + {0x11, 0x01, 0xf0, 0x00, "1C 1C" }, + {0x11, 0x01, 0xf0, 0xa0, "2C 3C" }, + {0x11, 0x01, 0xf0, 0xb0, "2C 4C" }, + {0x11, 0x01, 0xf0, 0x10, "2C 2C" }, + {0x11, 0x01, 0xf0, 0xc0, "1C 5C" }, + {0x11, 0x01, 0xf0, 0xd0, "2C 6C" }, + {0x11, 0x01, 0xf0, 0x20, "1C 3C" }, + {0x11, 0x01, 0xf0, 0xe0, "2C 7C" }, + {0x11, 0x01, 0xf0, 0xf0, "2C 8C" }, + {0x11, 0x01, 0xf0, 0x30, "1C 4C" }, + {0x11, 0x01, 0xf0, 0x40, "1C 5C" }, + {0x11, 0x01, 0xf0, 0x50, "1C 6C" }, + {0x11, 0x01, 0xf0, 0x60, "1C 7C" }, + {0x11, 0x01, 0xf0, 0x70, "1C 8C" }, +}; + +STDDIPINFO(crushs) + +static struct BurnDIPInfo ponpokoDIPList[]= +{ + {0x10, 0xff, 0xff, 0xd1, NULL }, + {0x11, 0xff, 0xff, 0xb1, NULL }, + {0x12, 0xff, 0xff, 0xe0, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x03, 0x00, "10000" }, + {0x10, 0x01, 0x03, 0x01, "30000" }, + {0x10, 0x01, 0x03, 0x02, "50000" }, + {0x10, 0x01, 0x03, 0x03, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x10, "3" }, + {0x10, 0x01, 0x30, 0x20, "4" }, + {0x10, 0x01, 0x30, 0x30, "5" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x40, "Upright" }, + {0x10, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x11, 0x01, 0x0f, 0x04, "A 3/1 B 3/1" }, + {0x11, 0x01, 0x0f, 0x0e, "A 3/1 B 1/2" }, + {0x11, 0x01, 0x0f, 0x0f, "A 3/1 B 1/4" }, + {0x11, 0x01, 0x0f, 0x02, "A 2/1 B 2/1" }, + {0x11, 0x01, 0x0f, 0x0d, "A 2/1 B 1/1" }, + {0x11, 0x01, 0x0f, 0x07, "A 2/1 B 1/3" }, + {0x11, 0x01, 0x0f, 0x0b, "A 2/1 B 1/5" }, + {0x11, 0x01, 0x0f, 0x0c, "A 2/1 B 1/6" }, + {0x11, 0x01, 0x0f, 0x01, "A 1/1 B 1/1" }, + {0x11, 0x01, 0x0f, 0x06, "A 1/1 B 4/5" }, + {0x11, 0x01, 0x0f, 0x05, "A 1/1 B 2/3" }, + {0x11, 0x01, 0x0f, 0x0a, "A 1/1 B 1/3" }, + {0x11, 0x01, 0x0f, 0x08, "A 1/1 B 1/5" }, + {0x11, 0x01, 0x0f, 0x09, "A 1/1 B 1/6" }, + {0x11, 0x01, 0x0f, 0x03, "A 1/2 B 1/2" }, + {0x11, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(ponpoko) + +static struct BurnDIPInfo bwcasinoDIPList[]= +{ + {0x0f, 0xff, 0xff, 0x7f, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x80, 0x00, "Upright" }, + {0x0f, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 16 , "Hands Per Game" }, + {0x10, 0x01, 0x1e, 0x1e, "3" }, + {0x10, 0x01, 0x1e, 0x1c, "4" }, + {0x10, 0x01, 0x1e, 0x1a, "5" }, + {0x10, 0x01, 0x1e, 0x18, "6" }, + {0x10, 0x01, 0x1e, 0x16, "7" }, + {0x10, 0x01, 0x1e, 0x14, "8" }, + {0x10, 0x01, 0x1e, 0x12, "9" }, + {0x10, 0x01, 0x1e, 0x10, "10" }, + {0x10, 0x01, 0x1e, 0x0e, "11" }, + {0x10, 0x01, 0x1e, 0x0c, "12" }, + {0x10, 0x01, 0x1e, 0x0a, "13" }, + {0x10, 0x01, 0x1e, 0x07, "14" }, + {0x10, 0x01, 0x1e, 0x06, "15" }, + {0x10, 0x01, 0x1e, 0x04, "16" }, + {0x10, 0x01, 0x1e, 0x02, "17" }, + {0x10, 0x01, 0x1e, 0x00, "18" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x20, 0x20, "Off" }, + {0x10, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(bwcasino) + +static struct BurnDIPInfo acityaDIPList[]= +{ + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16 , "Hands Per Game" }, + {0x0b, 0x01, 0x1e, 0x1e, "3" }, + {0x0b, 0x01, 0x1e, 0x1c, "4" }, + {0x0b, 0x01, 0x1e, 0x1a, "5" }, + {0x0b, 0x01, 0x1e, 0x18, "6" }, + {0x0b, 0x01, 0x1e, 0x16, "7" }, + {0x0b, 0x01, 0x1e, 0x14, "8" }, + {0x0b, 0x01, 0x1e, 0x12, "9" }, + {0x0b, 0x01, 0x1e, 0x10, "10" }, + {0x0b, 0x01, 0x1e, 0x0e, "11" }, + {0x0b, 0x01, 0x1e, 0x0c, "12" }, + {0x0b, 0x01, 0x1e, 0x0a, "13" }, + {0x0b, 0x01, 0x1e, 0x07, "14" }, + {0x0b, 0x01, 0x1e, 0x06, "15" }, + {0x0b, 0x01, 0x1e, 0x04, "16" }, + {0x0b, 0x01, 0x1e, 0x02, "17" }, + {0x0b, 0x01, 0x1e, 0x00, "18" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x20, 0x20, "Off" }, + {0x0b, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(acitya) + +static struct BurnDIPInfo eyesDIPList[]= +{ + {0x10, 0xff, 0xff, 0xfb, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x03, 0x01, "2C 1C" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "2" }, + {0x10, 0x01, 0x0c, 0x08, "3" }, + {0x10, 0x01, 0x0c, 0x04, "4" }, + {0x10, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x30, 0x30, "50000" }, + {0x10, 0x01, 0x30, 0x20, "75000" }, + {0x10, 0x01, 0x30, 0x10, "100000" }, + {0x10, 0x01, 0x30, 0x00, "125000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x40, "Upright" }, + {0x10, 0x01, 0x40, 0x00, "Cocktail" }, +}; + +STDDIPINFO(eyes) + +static struct BurnDIPInfo mrtntDIPList[]= +{ + {0x10, 0xff, 0xff, 0xfb, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x10, 0x01, 0x03, 0x01, "2C 1C" }, + {0x10, 0x01, 0x03, 0x03, "1C 1C" }, + {0x10, 0x01, 0x03, 0x02, "1C 2C" }, + {0x10, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "2" }, + {0x10, 0x01, 0x0c, 0x08, "3" }, + {0x10, 0x01, 0x0c, 0x04, "4" }, + {0x10, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x30, 0x30, "75000" }, + {0x10, 0x01, 0x30, 0x20, "100000" }, + {0x10, 0x01, 0x30, 0x10, "125000" }, + {0x10, 0x01, 0x30, 0x00, "150000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x40, "Upright" }, + {0x10, 0x01, 0x40, 0x00, "Cocktail" }, +}; + +STDDIPINFO(mrtnt) + +static struct BurnDIPInfo alibabaDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xd9, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x03, 0x03, "2C 1C" }, + {0x11, 0x01, 0x03, 0x01, "1C 1C" }, + {0x11, 0x01, 0x03, 0x02, "1C 2C" }, + {0x11, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x00, "1" }, + {0x11, 0x01, 0x0c, 0x04, "2" }, + {0x11, 0x01, 0x0c, 0x08, "3" }, + {0x11, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x11, 0x01, 0x30, 0x00, "10000" }, + {0x11, 0x01, 0x30, 0x10, "15000" }, + {0x11, 0x01, 0x30, 0x20, "20000" }, + {0x11, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x40, 0x40, "Normal" }, + {0x11, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(alibaba) + +static struct BurnDIPInfo theglobpDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x80, 0x80, "Upright" }, + {0x0f, 0x01, 0x80, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x03, 0x03, "3" }, + {0x10, 0x01, 0x03, 0x02, "4" }, + {0x10, 0x01, 0x03, 0x01, "5" }, + {0x10, 0x01, 0x03, 0x00, "6" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x10, 0x01, 0x1c, 0x1c, "Easiest" }, + {0x10, 0x01, 0x1c, 0x18, "Very Easy" }, + {0x10, 0x01, 0x1c, 0x14, "Easy" }, + {0x10, 0x01, 0x1c, 0x10, "Normal" }, + {0x10, 0x01, 0x1c, 0x0c, "Difficult" }, + {0x10, 0x01, 0x1c, 0x08, "Very Difficult" }, + {0x10, 0x01, 0x1c, 0x04, "Very Hard" }, + {0x10, 0x01, 0x1c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x20, 0x20, "Off" }, + {0x10, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(theglobp) + +static struct BurnDIPInfo woodpekDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xc1, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x03, 0x03, "2C 1C" }, + {0x11, 0x01, 0x03, 0x01, "1C 1C" }, + {0x11, 0x01, 0x03, 0x02, "1C 2C" }, + {0x11, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x00, "3" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x08, "5" }, + {0x11, 0x01, 0x0c, 0x0c, "6" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x11, 0x01, 0x30, 0x00, "5000" }, + {0x11, 0x01, 0x30, 0x10, "10000" }, + {0x11, 0x01, 0x30, 0x20, "15000" }, + {0x11, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x40, 0x40, "Upright" }, + {0x11, 0x01, 0x40, 0x00, "Cocktail" }, +}; + +STDDIPINFO(woodpek) + +static struct BurnDIPInfo lizwizDIPList[]= +{ + {0x11, 0xff, 0xff, 0xfb, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x03, 0x01, "2C 1C" }, + {0x11, 0x01, 0x03, 0x03, "1C 1C" }, + {0x11, 0x01, 0x03, 0x02, "1C 2C" }, + {0x11, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x00, "5" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x08, "3" }, + {0x11, 0x01, 0x0c, 0x0c, "2" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x11, 0x01, 0x30, 0x00, "75000" }, + {0x11, 0x01, 0x30, 0x10, "100000" }, + {0x11, 0x01, 0x30, 0x20, "125000" }, + {0x11, 0x01, 0x30, 0x30, "150000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x11, 0x01, 0x40, 0x40, "Normal" }, + {0x11, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(lizwiz) + +static struct BurnDIPInfo vanvanDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xda, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x01, 0x00, "Upright" }, + {0x0f, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0f, 0x01, 0x0c, 0x08, "20k and 100k" }, + {0x0f, 0x01, 0x0c, 0x04, "40k and 140k" }, + {0x0f, 0x01, 0x0c, 0x00, "70k and 200k" }, + {0x0f, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x30, 0x30, "1" }, + {0x0f, 0x01, 0x30, 0x20, "2" }, + {0x0f, 0x01, 0x30, 0x10, "3" }, + {0x0f, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0f, 0x01, 0xc0, 0x00, "2c_1c" }, + {0x0f, 0x01, 0xc0, 0xc0, "1C_1C" }, + {0x0f, 0x01, 0xc0, 0x80, "1c_2C" }, + {0x0f, 0x01, 0xc0, 0x40, "1C_3C" }, +}; + +STDDIPINFO(vanvan) + +static struct BurnDIPInfo nmouseDIPList[]= +{ + {0x0e, 0xff, 0xff, 0xc9, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x00, "1" }, + {0x0e, 0x01, 0x0c, 0x04, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x30, 0x00, "5000" }, + {0x0e, 0x01, 0x30, 0x10, "10000" }, + {0x0e, 0x01, 0x30, 0x20, "15000" }, + {0x0e, 0x01, 0x30, 0x30, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x40, 0x40, "Normal" }, + {0x0e, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Rack Test (Cheat)" }, + {0x0f, 0x01, 0x10, 0x10, "Off" }, + {0x0f, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x80, 0x80, "Upright" }, + {0x10, 0x01, 0x80, 0x00, "Cocktail" }, +}; + +STDDIPINFO(nmouse) + +static struct BurnDIPInfo jumpshotDIPList[]= +{ + {0x10, 0xff, 0xff, 0xf1, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 3 , "Time" }, + {0x10, 0x01, 0x03, 0x02, "2 Minutes" }, + {0x10, 0x01, 0x03, 0x03, "3 Minutes" }, + {0x10, 0x01, 0x03, 0x01, "4 Minutes" }, + + {0 , 0xfe, 0 , 4 , "Player Skin Tone" }, + {0x10, 0x01, 0x04, 0x04, "Lighter" }, + {0x10, 0x01, 0x04, 0x00, "Darker" }, + + {0 , 0xfe, 0 , 4 , "Player Skin Tone" }, + {0x10, 0x01, 0x08, 0x08, "Lighter" }, + {0x10, 0x01, 0x08, 0x00, "Darker" }, + + {0 , 0xfe, 0 , 2 , "Free play" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x10, 0x01, 0x20, 0x20, "1 Credit" }, + {0x10, 0x01, 0x20, 0x00, "2 Credits" }, +}; + +STDDIPINFO(jumpshot) + +static struct BurnDIPInfo jumpshtpDIPList[]= +{ + {0x10, 0xff, 0xff, 0xf1, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 3 , "Time" }, + {0x10, 0x01, 0x03, 0x02, "Short" }, + {0x10, 0x01, 0x03, 0x03, "Average" }, + {0x10, 0x01, 0x03, 0x01, "Above Average" }, + + {0 , 0xfe, 0 , 4 , "Player Skin Tone" }, + {0x10, 0x01, 0x04, 0x04, "Lighter" }, + {0x10, 0x01, 0x04, 0x00, "Darker" }, + + {0 , 0xfe, 0 , 4 , "Player Skin Tone" }, + {0x10, 0x01, 0x08, 0x08, "Lighter" }, + {0x10, 0x01, 0x08, 0x00, "Darker" }, + + {0 , 0xfe, 0 , 2 , "Free play" }, + {0x10, 0x01, 0x10, 0x10, "Off" }, + {0x10, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "2 Players Game" }, + {0x10, 0x01, 0x20, 0x20, "1 Credit" }, + {0x10, 0x01, 0x20, 0x00, "2 Credits" }, +}; + +STDDIPINFO(jumpshtp) + +static struct BurnDIPInfo dremshprDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + {0x0f, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x01, 0x01, "Upright" }, + {0x0f, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0f, 0x01, 0x0c, 0x08, "30000" }, + {0x0f, 0x01, 0x0c, 0x04, "50000" }, + {0x0f, 0x01, 0x0c, 0x00, "70000" }, + {0x0f, 0x01, 0x0c, 0x0c, "none" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x30, 0x30, "3" }, + {0x0f, 0x01, 0x30, 0x20, "4" }, + {0x0f, 0x01, 0x30, 0x10, "5" }, + {0x0f, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0, 4, "Coinage" }, + {0x0f, 0x01, 0xc0, 0x00, "2C 1C" }, + {0x0f, 0x01, 0xc0, 0xc0, "1C 1C" }, + {0x0f, 0x01, 0xc0, 0x80, "1C 2C" }, + {0x0f, 0x01, 0xc0, 0x40, "1C 3C" }, +}; + +STDDIPINFO(dremshpr) + +static struct BurnDIPInfo cannonbpDIPList[]= +{ + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Display" }, + {0x0f, 0x01, 0x03, 0x03, "Scores and Progression Bars" }, + {0x0f, 0x01, 0x03, 0x01, "Scores only" }, + {0x0f, 0x01, 0x03, 0x02, "Progression Bars only" }, + {0x0f, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x04, 0x04, "Upright" }, + {0x0f, 0x01, 0x04, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x18, 0x00, "3" }, + {0x0f, 0x01, 0x18, 0x08, "4" }, + {0x0f, 0x01, 0x18, 0x10, "5" }, + {0x0f, 0x01, 0x18, 0x18, "6" }, +}; + +STDDIPINFO(cannonbp) + +static struct BurnDIPInfo rocktrv2DIPList[]= +{ + {0x0e, 0xff, 0x3f, 0x33, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0e, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0e, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0e, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0e, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 8 , "Questions Per Game" }, + {0x0e, 0x01, 0x1c, 0x1c, "2" }, + {0x0e, 0x01, 0x1c, 0x18, "3" }, + {0x0e, 0x01, 0x1c, 0x14, "4" }, + {0x0e, 0x01, 0x1c, 0x10, "5" }, + {0x0e, 0x01, 0x1c, 0x0c, "6" }, + {0x0e, 0x01, 0x1c, 0x08, "7" }, + {0x0e, 0x01, 0x1c, 0x04, "8" }, + {0x0e, 0x01, 0x1c, 0x00, "9" }, + + {0 , 0xfe, 0 , 4 , "Clock Speed" }, + {0x0e, 0x01, 0x60, 0x60, "Beginner" }, + {0x0e, 0x01, 0x60, 0x40, "Intermediate" }, + {0x0e, 0x01, 0x60, 0x20, "Professional" }, + {0x0e, 0x01, 0x60, 0x00, "Super - Pro" }, + + {0 , 0xfe, 0 , 2 , "Freeze Image" }, + {0x0e, 0x01, 0x80, 0x80, "Off" }, + {0x0e, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Mode" }, + {0x0f, 0x01, 0x01, 0x01, "Amusement" }, + {0x0f, 0x01, 0x01, 0x00, "Credit" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x02, 0x02, "Upright" }, + {0x0f, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "K.O. Switch" }, + {0x0f, 0x01, 0x04, 0x04, "Auto" }, + {0x0f, 0x01, 0x04, 0x00, "Manual" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x0f, 0x01, 0x70, 0x70, "10000" }, + {0x0f, 0x01, 0x70, 0x60, "17500" }, + {0x0f, 0x01, 0x70, 0x50, "25000" }, + {0x0f, 0x01, 0x70, 0x40, "32500" }, + {0x0f, 0x01, 0x70, 0x30, "40000" }, + {0x0f, 0x01, 0x70, 0x20, "47500" }, + {0x0f, 0x01, 0x70, 0x10, "55000" }, + {0x0f, 0x01, 0x70, 0x00, "62500" }, + + {0 , 0xfe, 0 , 2 , "Music" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, +}; + +STDDIPINFO(rocktrv2) + +static struct BurnDIPInfo bigbucksDIPList[]= +{ + {0x0c, 0xff, 0xff, 0xff, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Enable Adult Affairs Category" }, + {0x0c, 0x01, 0x10, 0x00, "Off" }, + {0x0c, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Time to bet / answer" }, + {0x0d, 0x01, 0x01, 0x00, "15 sec. / 10 sec." }, + {0x0d, 0x01, 0x01, 0x01, "20 sec. / 15 sec." }, + + {0 , 0xfe, 0 , 2 , "Continue if player busts"}, + {0x0d, 0x01, 0x02, 0x00, "Off" }, + {0x0d, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Show correct answer" }, + {0x0d, 0x01, 0x04, 0x00, "Off" }, + {0x0d, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Coinage" }, + {0x0d, 0x01, 0x10, 0x00, "2C 1C" }, + {0x0d, 0x01, 0x10, 0x10, "1C 1C" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x20, 0x20, "Upright" }, + {0x0d, 0x01, 0x20, 0x00, "Cocktail" }, +}; + +STDDIPINFO(bigbucks) + +static struct BurnDIPInfo korosukeDIPList[]= +{ + {0x0f, 0xff, 0x3f, 0x31, NULL }, + {0x10, 0xff, 0xff, 0xef, NULL }, + {0x11, 0xff, 0x6f, 0x6f, NULL }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x10, 0x00, "Upright" }, + {0x10, 0x01, 0x10, 0x10, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0f, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0f, 0x01, 0x03, 0x01, "1C 1C" }, + {0x0f, 0x01, 0x03, 0x02, "1C 2C" }, + {0x0f, 0x01, 0x03, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x0c, 0x00, "3" }, + {0x0f, 0x01, 0x0c, 0x04, "4" }, + {0x0f, 0x01, 0x0c, 0x08, "5" }, + {0x0f, 0x01, 0x0c, 0x0c, "6" }, + + {0 , 0xfe, 0 , 2 , "First Pattern" }, + {0x0f, 0x01, 0x30, 0x10, "Easy" }, + {0x0f, 0x01, 0x30, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Teleport Holes" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(korosuke) + +static struct BurnDIPInfo shootbulDIPList[]= +{ + {0x08, 0xff, 0xff, 0xff, NULL }, + {0x09, 0xff, 0xff, 0xe0, NULL }, + {0x0A, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 5 , "Time" }, + {0x08, 0x01, 0x03, 0x01, "Short" }, + {0x08, 0x01, 0x03, 0x07, "Average" }, + {0x08, 0x01, 0x03, 0x03, "Long" }, + {0x08, 0x01, 0x03, 0x05, "Longer" }, + {0x08, 0x01, 0x03, 0x06, "Longest" }, + + {0 , 0xfe, 0 , 2 , "Title Page Sounds" }, + {0x08, 0x01, 0x08, 0x00, "Off" }, + {0x08, 0x01, 0x08, 0x08, "On" }, +}; + +STDDIPINFO(shootbul) + +//------------------------------------------------------------------------------------------------------ + +static void mschamp_set_bank() +{ + nPacBank = DrvDips[3] & 1; + + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM + 0x0000 + (nPacBank * 0x08000)); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM + 0x0000 + (nPacBank * 0x08000)); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x4000 + (nPacBank * 0x08000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x4000 + (nPacBank * 0x08000)); +} + +static void epos_hardware_set_bank(INT32 nBank) +{ + nPacBank = nBank & 3; + + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM + 0x10000 + (nPacBank * 0x04000)); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM + 0x10000 + (nPacBank * 0x04000)); +} + +static UINT8 cannonbp_protection_r(UINT16 offset) +{ + switch (offset) + { + case 0x0004: + cannonb_bit_to_read = 7; + case 0x0000: + case 0x0003: + case 0x0012: + case 0x0105: + return 0x00; + + case 0x0001: + if (ZetPc(-1) == 0x2b97) + return ((0x46 >> (cannonb_bit_to_read--)) & 1) << 7; + else + return 0xff; + + case 0x0107: + return 0x40; + } + + return 0; +} + +static UINT8 epos_hardware_decrypt_rom(UINT16 offset) +{ + if (offset & 0x01) + { + epos_hardware_counter = epos_hardware_counter - 1; + if (epos_hardware_counter < 0) + epos_hardware_counter = 0x0f; + } + else + { + epos_hardware_counter = (epos_hardware_counter + 1) & 0x0f; + } + + if (epos_hardware_counter >= 0x08 && epos_hardware_counter <= 0x0b) { + epos_hardware_set_bank(epos_hardware_counter); + } + + return 0; +} + +static UINT8 maketrax_special_port2_r(UINT16 offset) // and korosuke +{ + INT32 data = DrvDips[2]; + INT32 pc = ZetPc(-1); + + if (pc == 0x1973 || pc == 0x2389 || pc == 0x196e || pc == 0x2387) return data | 0x40; + + switch (offset) + { + case 0x01: + case 0x04: data |= 0x40; break; + case 0x05: data |= 0xc0; break; + + default: data &= 0x3f; break; + } + + return data; +} + +static UINT8 maketrax_special_port3_r(UINT16 offset) +{ + INT32 pc = ZetPc(-1); + + if (pc == 0x040e || pc == 0x0445) return 0x20; + if (pc == 0x115e || pc == 0x3ae2 || pc == 0x115b || pc == 0x3ae6) return 0x00; + + switch (offset) + { + case 0x00: return 0x1f; + case 0x09: return 0x30; + case 0x0c: return 0x00; + + default: return 0x20; + } +} + +UINT8 __fastcall pacman_read(UINT16 a) +{ + switch (game_select) + { + case ALIBABA: + { + if (a == 0x50c0) return rand() & 0xff; + if (a == 0x50c1) { + alibaba_mystery++; + return (alibaba_mystery >> 10) & 1; + } + } + break; + + case CANNONBP: + { + if ((a & 0xf000) == 0x3000) return cannonbp_protection_r(a & 0xfff); + } + break; + + case MAKETRAX: + { + if ((a & 0xffc0) == 0x5080) return maketrax_special_port2_r(a & 0x3f); + if ((a & 0xffc0) == 0x50c0) return maketrax_special_port3_r(a & 0x3f); + } + break; + + case CRUSHS: + { + if (a == 0x5080) return DrvInputs[1]; + } + break; + + case ROCKTRV2: + { + if ((a & 0xfff0) == 0x5fe0) return (rocktrv2_prot_data[(a >> 2) & 3] >> 4); + + if (a == 0x5fff) return DrvDips[3]; + + if ((a & 0x8000) == 0x8000) return DrvQROM[(a & 0x7fff) | (nPacBank * 0x8000)]; + } + break; + } + + switch (a & ~0x003f) + { + case 0x5000: return DrvInputs[0]; + case 0x5040: return DrvInputs[1]; + case 0x5080: return DrvDips[2]; + case 0x50c0: return DrvDips[3]; + } + + if ((a & 0xfc00) == 0x4800) return 0xbf; + + return 0; +} + +void __fastcall pacman_write(UINT16 a, UINT8 d) +{ + switch (game_select) + { + case BIRDIY: + { + if ((a & 0xffe0) == 0x5080) a -= 0x0040; + if ((a & 0xfff0) == 0x50a0) a -= 0x0020; + if (a == 0x5000) return; + if (a == 0x5001) interrupt_mask = d & 1; + } + break; + + case ALIBABA: + { + if (a == 0x50c2) { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + interrupt_mask = d; + return; + } + + if ((a & 0xfff0) == 0x5040) { + NamcoSoundWrite((a & 0x0f) | 0x00, d); + return; + } + + if ((a & 0xfff0) == 0x5060) { + NamcoSoundWrite((a & 0x0f) | 0x10, d); + return; + } + + if ((a & 0xfff0) == 0x5050) { + DrvSprRAM2[a & 0x0f] = d; + return; + } + + if (a == 0x5000) { + watchdog = 0; + return; + } + } + break; + + case ROCKTRV2: + { + if ((a & 0xfffc) == 0x5fe0) { + rocktrv2_prot_data[a & 3] = d; + return; + } + + if (a == 0x5ff0) { + nPacBank = d; + return; + } + } + break; + + case VANVAN: + { + if (a == 0x5001) { + for (INT32 i = 0; i < 0x100; i++) { + if (DrvColPROM[0x100 + i] == 0) { + Palette[i] = (d & 1) ? BurnHighCol(0xaa, 0xaa, 0xaa, 0) : 0; + } + } + return; + } + } + break; + + case BIGBUCKS: + if (a == 0x6000) { + nPacBank = d; + return; + } + break; + } + + if ((a & 0xffe0) == 0x5040) { + NamcoSoundWrite(a & 0x1f, d); + return; + } + + if ((a & 0xfff0) == 0x5060) { + DrvSprRAM2[a & 0x0f] = d; + return; + } + + switch (a) + { + case 0x5000: + interrupt_mask = d & 1; + break; + + case 0x5001: + // pacman_sound_enable_w + break; + + case 0x5003: + *flipscreen = d & 1; + break; + + case 0x5002:// nop + case 0x5007:// coin counter + break; + + case 0x50c0: + watchdog = 0; + break; + } +} + +UINT8 __fastcall pacman_in_port(UINT16 a) +{ + if (game_select == BIGBUCKS) { + return DrvQROM[(nPacBank << 16) | (a ^ 0xffff)]; + } + + a &= 0xff; + + switch (game_select) + { + case CRUSHS: + if (a == 1) return DrvDips[3]; + if (a == 2) return DrvDips[2]; + return 0; + + case EPOS: + return epos_hardware_decrypt_rom(a); + + case MSCHAMP: + if (a == 0) return mschamp_counter++; + return 0; + } + + return 0; +} + +void __fastcall pacman_out_port(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (game_select) + { + case CRUSHS: + if (a == 0 || a == 1) { + AY8910Write(0, ~a & 1, d); + } + return; + + case DREMSHPR: + if (a == 6 || a == 7) { + AY8910Write(0, ~a & 1, d); + } + return; + + case VANVAN: + if (a == 1 || a == 2) { + SN76496Write(a - 1, d); + } + return; + + case PIRANHA: + if (a == 0) { + if (d == 0xfa) d = 0x78; + interrupt_mode = d; + } + return; + + case NMOUSE: + if (a == 0) { + if (d == 0xbf) d = 0x3c; + if (d == 0xc6) d = 0x40; + interrupt_mode = d; + } + return; + } + + if (a == 0) // pacman & clones only + { + interrupt_mode = d; + ZetSetVector(d); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +UINT8 __fastcall mspacman_read(UINT16 a) +{ + if ((a < 0x4000) || (a >= 0x8000 && a <= 0xbfff)) + { + if ((a >= 0x0038 && a <= 0x003f) | + (a >= 0x03b0 && a <= 0x03b7) | + (a >= 0x1600 && a <= 0x1607) | + (a >= 0x2120 && a <= 0x2127) | + (a >= 0x3ff0 && a <= 0x3ff7) | + (a >= 0x8000 && a <= 0x8007) | + (a >= 0x97f0 && a <= 0x97f7)) + { + nPacBank = 0; + } + + if (a >= 0x3ff8 && a <= 0x3fff) { + nPacBank = 1; + } + + return DrvZ80ROM[(nPacBank << 16) + a]; + } + + if ((a & 0xfc00) == 0x4800) return 0xbf; // unmapped read + + if ((a & 0xff00) == 0x5000) a &= ~0x003f; + + switch (a) + { + case 0x5000: return DrvInputs[0]; + case 0x5040: return DrvInputs[1]; + case 0x5080: return DrvDips[2]; + case 0x50c0: return DrvDips[3]; + } + + return 0; +} + +void __fastcall mspacman_write(UINT16 a, UINT8 d) +{ + if ((a >= 0x0038 && a <= 0x003f) | + (a >= 0x03b0 && a <= 0x03b7) | + (a >= 0x1600 && a <= 0x1607) | + (a >= 0x2120 && a <= 0x2127) | + (a >= 0x3ff0 && a <= 0x3ff7) | + (a >= 0x8000 && a <= 0x8007) | + (a >= 0x97f0 && a <= 0x97f7)) + { + nPacBank = 0; + } + + if (a >= 0x3ff8 && a <= 0x3fff) { + nPacBank = 1; + } + + if ((a & 0xffe0) == 0x5040) { + NamcoSoundWrite(a & 0x1f, d); + return; + } + + if ((a & 0xfff0) == 0x5060) { + DrvSprRAM2[a & 0x0f] = d; + return; + } + + switch (a) + { + case 0x5000: + interrupt_mask = d & 1; + break; + + case 0x5001: + // pacman_sound_enable_w + break; + + case 0x5003: + *flipscreen = d & 1; + break; + + case 0x5002: // nop + case 0x5004: + case 0x5005: // leds + case 0x5006: // coin lockout + case 0x5007: // coin counter + case 0x5080: // nop + return; + + case 0x50c0: + watchdog = 0; + break; + } +} + +void __fastcall pengo_write(UINT16 a, UINT8 d) +{ + if ((a & 0xffe0) == 0x9000) { + NamcoSoundWrite(a & 0x1f, d); + return; + } + + if ((a & 0xfff0) == 0x9020) { + DrvSprRAM2[a & 0x0f] = d; + return; + } + + switch (a) + { + case 0x9040: + interrupt_mask = d & 1; + return; + + case 0x9042: + palettebank = d; + return; + + case 0x9043: + *flipscreen = d & 1; + return; + + case 0x9044: + case 0x9045: // coin counter + return; + + case 0x9046: + colortablebank = d; + return; + + case 0x9047: + charbank = d & 1; + spritebank = d & 1; + return; + + case 0x9070: + watchdog = 0; + return; + } +} + +UINT8 __fastcall pengo_read(UINT16 a) +{ + switch (a & ~0x003f) + { + case 0x9000: return DrvDips[3]; + case 0x9040: return DrvDips[2]; + case 0x9080: return DrvInputs[1]; + case 0x90c0: return DrvInputs[0]; + } + + return 0; +} + +//------------------------------------------------------------------------------------------------------ + +static INT32 DrvDoReset(INT32 clear_ram) +{ + if (clear_ram) { + memset (AllRam, 0, RamEnd - AllRam); + } + + watchdog = 0; + nPacBank = 0; + + ZetOpen(0); + ZetReset(); + + switch (game_select) + { + case EPOS: + epos_hardware_counter = 0x0A + acitya; + epos_hardware_set_bank(epos_hardware_counter); + break; + + case MSCHAMP: + mschamp_set_bank(); + break; + } + + ZetClose(); + + AY8910Reset(0); + + mschamp_counter = 0; + cannonb_bit_to_read = 0; + alibaba_mystery = 0; + + interrupt_mode = 0; + interrupt_mask = 0; + colortablebank = 0; + palettebank = 0; + spritebank = 0; + charbank = 0; + + return 0; +} + +static void DrvTransTableInit() +{ + for (INT32 i = 0; i < 0x100; i++) { + DrvTransTable[i] = (DrvColPROM[(i & 0xff) + 0x100] & 0x0f) ? 1 : 0; + } +} + +static void pacman_palette_init() +{ + UINT32 t_pal[32]; + + for (INT32 i = 0; i < 32; i++) + { + INT32 bit0 = (DrvColPROM[i] >> 0) & 0x01; + INT32 bit1 = (DrvColPROM[i] >> 1) & 0x01; + INT32 bit2 = (DrvColPROM[i] >> 2) & 0x01; + UINT8 r = (bit0 * 33) + (bit1 * 71) + (bit2 * 151); + + bit0 = (DrvColPROM[i] >> 3) & 0x01; + bit1 = (DrvColPROM[i] >> 4) & 0x01; + bit2 = (DrvColPROM[i] >> 5) & 0x01; + UINT8 g = (bit0 * 33) + (bit1 * 71) + (bit2 * 151); + + bit0 = (DrvColPROM[i] >> 6) & 0x01; + bit1 = (DrvColPROM[i] >> 7) & 0x01; + UINT8 b = (bit0 * 81) + (bit1 * 174); + + t_pal[i] = BurnHighCol(r, g, b, 0); + } + + for (INT32 i = 0; i < 256; i++) + { + UINT8 ctabentry = DrvColPROM[i + 0x100] & 0x0f; + + Palette[0x000 + i] = t_pal[ctabentry + 0x00]; + Palette[0x100 + i] = t_pal[ctabentry + 0x10]; + } + + DrvRecalc = 1; +} + +static void convert_gfx() +{ + static INT32 PlaneOffsets[2] = { 0, 4 }; + static INT32 CharXOffsets[8] = { 64, 65, 66, 67, 0, 1, 2, 3 }; + static INT32 SpriXOffsets[16] = { 8*8, 8*8+1, 8*8+2, 8*8+3, 16*8+0, 16*8+1, 16*8+2, 16*8+3, 24*8+0, 24*8+1, 24*8+2, 24*8+3, 0, 1, 2, 3 }; + static INT32 YOffsets[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 32*8, 33*8, 34*8, 35*8, 36*8, 37*8, 38*8, 39*8 }; + + INT32 size = (game_select == PENGO) ? 0x2000 : 0x1000; + + UINT8 *tmp = (UINT8*)BurnMalloc( size * 2 ); + + if (tmp) + { + memcpy (tmp, DrvGfxROM, size * 2); + + GfxDecode(((size * 4) / 0x040), 2, 8, 8, PlaneOffsets, CharXOffsets + 0, YOffsets, 0x080, tmp, DrvGfxROM + 0x0000); + GfxDecode(((size * 4) / 0x100), 2, 16, 16, PlaneOffsets, SpriXOffsets + 0, YOffsets, 0x200, tmp + size, DrvGfxROM + 0x8000); + } + + BurnFree (tmp); +} + +static INT32 pacman_load() +{ + char* pRomName; + struct BurnRomInfo ri; + + INT32 pOffset = 0; + UINT8 *gLoad = DrvGfxROM; + UINT8 *cLoad = DrvColPROM; + UINT8 *sLoad = NamcoSoundProm; + UINT8 *qLoad = DrvQROM; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(DrvZ80ROM + pOffset, i, 1)) return 1; + + if (game_select == MSPACMAN) { + pOffset += 0x1000; + } else { + pOffset += ri.nLen; + } + + if (pOffset == 0x4000 && game_select != PENGO) { + pOffset = 0x8000; + } + + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(gLoad, i, 1)) return 1; + gLoad += ri.nLen; + + continue; + } + + if ((ri.nType & 7) == 3) { + if (game_select != BIRDIY) { + if (BurnLoadRom(cLoad, i, 1)) return 1; + cLoad += 0x100; + } + + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(sLoad, i, 1)) return 1; + sLoad += 0x100; + + continue; + } + + if ((ri.nType & 7) == 7) { + if (BurnLoadRom(qLoad, i, 1)) return 1; + qLoad += ri.nLen; + + continue; + } + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x020000; + + DrvQROM = Next; + if (game_select == BIGBUCKS) Next += 0x060000; + if (game_select == ROCKTRV2) Next += 0x040000; + + DrvGfxROM = Next; Next += 0x010000; + + DrvColPROM = Next; Next += 0x000500; + NamcoSoundProm = Next; Next += 0x000200; + + DrvTransTable = Next; Next += 0x000200; + + Palette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x001000; + + DrvSprRAM = DrvZ80RAM + ((game_select == ALIBABA) ? 0x6f0 : 0x7f0); + DrvSprRAM2 = Next; Next += 0x000010; + + DrvColRAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + + rocktrv2_prot_data = Next; Next += 0x000004; + + flipscreen = Next; Next += 0x000001; + + RamEnd = Next; + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static void StandardMap() +{ + for (INT32 i = 0; i <= 0x8000; i += 0x8000)// mirror + { + ZetMapArea(0x0000 + i, 0x3fff + i, 0, DrvZ80ROM); + ZetMapArea(0x0000 + i, 0x3fff + i, 2, DrvZ80ROM); + + for (INT32 j = 0; j <= 0x2000; j+= 0x2000) // mirrors + { + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 0, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 1, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 2, DrvVidRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 0, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 1, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 2, DrvColRAM); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 0, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 1, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 2, DrvZ80RAM + 0x0400); + } + } + + ZetSetWriteHandler(pacman_write); + ZetSetReadHandler(pacman_read); + ZetSetOutHandler(pacman_out_port); + ZetSetInHandler(pacman_in_port); +} + +static void CannonbpMap() +{ + for (INT32 i = 0; i <= 0x8000; i += 0x8000) { // mirror + + ZetMapArea(0x0000 + i, 0x2fff + i, 0, DrvZ80ROM); + ZetMapArea(0x0000 + i, 0x2fff + i, 2, DrvZ80ROM); + + for (INT32 j = 0; j <= 0x2000; j+= 0x2000) { // mirrors + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 0, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 1, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 2, DrvVidRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 0, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 1, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 2, DrvColRAM); + ZetMapArea(0x4800 + i + j, 0x4bff + i + j, 0, DrvZ80RAM + 0x0000); + ZetMapArea(0x4800 + i + j, 0x4bff + i + j, 1, DrvZ80RAM + 0x0000); + ZetMapArea(0x4800 + i + j, 0x4bff + i + j, 2, DrvZ80RAM + 0x0000); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 0, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 1, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 2, DrvZ80RAM + 0x0400); + } + } + + ZetSetWriteHandler(pacman_write); + ZetSetReadHandler(pacman_read); + ZetSetOutHandler(pacman_out_port); + ZetSetInHandler(pacman_in_port); +} + +static void DremshprMap() // and vanvan +{ + CannonbpMap(); + + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x8000); +} + +static void WoodpekMap() +{ + StandardMap(); + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x8000); +} + +static void Rocktrv2Map() +{ + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea(0x4000, 0x43ff, 0, DrvVidRAM); + ZetMapArea(0x4000, 0x43ff, 1, DrvVidRAM); + ZetMapArea(0x4000, 0x43ff, 2, DrvVidRAM); + ZetMapArea(0x4400, 0x47ff, 0, DrvColRAM); + ZetMapArea(0x4400, 0x47ff, 1, DrvColRAM); + ZetMapArea(0x4400, 0x47ff, 2, DrvColRAM); + ZetMapArea(0x4c00, 0x4fff, 0, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00, 0x4fff, 1, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00, 0x4fff, 2, DrvZ80RAM + 0x0400); + + ZetMapArea(0x6000, 0x7fff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x6000, 0x7fff, 2, DrvZ80ROM + 0x8000); + + ZetSetWriteHandler(pacman_write); + ZetSetReadHandler(pacman_read); + ZetSetOutHandler(pacman_out_port); + ZetSetInHandler(pacman_in_port); +} + +static void BigbucksMap() +{ + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea(0x4000, 0x43ff, 0, DrvVidRAM); + ZetMapArea(0x4000, 0x43ff, 1, DrvVidRAM); + ZetMapArea(0x4000, 0x43ff, 2, DrvVidRAM); + ZetMapArea(0x4400, 0x47ff, 0, DrvColRAM); + ZetMapArea(0x4400, 0x47ff, 1, DrvColRAM); + ZetMapArea(0x4400, 0x47ff, 2, DrvColRAM); + ZetMapArea(0x4c00, 0x4fff, 0, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00, 0x4fff, 1, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00, 0x4fff, 2, DrvZ80RAM + 0x0400); + + ZetMapArea(0x8000, 0x9fff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0x9fff, 2, DrvZ80ROM + 0x8000); + + ZetSetWriteHandler(pacman_write); + ZetSetReadHandler(pacman_read); + ZetSetOutHandler(pacman_out_port); + ZetSetInHandler(pacman_in_port); +} + +static void AlibabaMap() +{ + StandardMap(); + + ZetMapArea(0x8000, 0x8fff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0x8fff, 2, DrvZ80ROM + 0x8000); + + for (INT32 i = 0; i < 0x1000; i+= 0x400) { + ZetMapArea(0x9000 + i, 0x93ff + i, 0, DrvZ80RAM + 0x0000); + ZetMapArea(0x9000 + i, 0x93ff + i, 1, DrvZ80RAM + 0x0000); + ZetMapArea(0x9000 + i, 0x93ff + i, 2, DrvZ80RAM + 0x0000); + } + + for (INT32 i = 0x0000; i < 0x2000; i += 0x0800) { + ZetMapArea(0xa000 + i, 0xa7ff + i, 0, DrvZ80ROM + 0xa000); + ZetMapArea(0xa000 + i, 0xa7ff + i, 2, DrvZ80ROM + 0xa000); + } +} + +static void PengoMap() +{ + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); +// ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM + 0x8000, DrvZ80ROM); + ZetMapArea(0x8000, 0x83ff, 0, DrvVidRAM); + ZetMapArea(0x8000, 0x83ff, 1, DrvVidRAM); + ZetMapArea(0x8000, 0x83ff, 2, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 0, DrvColRAM); + ZetMapArea(0x8400, 0x87ff, 1, DrvColRAM); + ZetMapArea(0x8400, 0x87ff, 2, DrvColRAM); + ZetMapArea(0x8800, 0x8fff, 0, DrvZ80RAM); + ZetMapArea(0x8800, 0x8fff, 1, DrvZ80RAM); + ZetMapArea(0x8800, 0x8fff, 2, DrvZ80RAM); + + ZetSetWriteHandler(pengo_write); + ZetSetReadHandler(pengo_read); +} + +static void MspacmanMap() +{ + for (INT32 i = 0; i <= 0x8000; i += 0x8000)// mirror + { + for (INT32 j = 0; j <= 0x2000; j+= 0x2000) // mirrors + { + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 0, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 1, DrvVidRAM); + ZetMapArea(0x4000 + i + j, 0x43ff + i + j, 2, DrvVidRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 0, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 1, DrvColRAM); + ZetMapArea(0x4400 + i + j, 0x47ff + i + j, 2, DrvColRAM); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 0, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 1, DrvZ80RAM + 0x0400); + ZetMapArea(0x4c00 + i + j, 0x4fff + i + j, 2, DrvZ80RAM + 0x0400); + } + } + + ZetSetWriteHandler(mspacman_write); + ZetSetReadHandler(mspacman_read); + ZetSetOutHandler(pacman_out_port); +} + +static INT32 DrvInit(void (*mapCallback)(), void (*pInitCallback)(), INT32 select) +{ + game_select = select; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (pacman_load()) return 1; + + if (pInitCallback) { + pInitCallback(); + } + + convert_gfx(); + pacman_palette_init(); + DrvTransTableInit(); + + ZetInit(1); + ZetOpen(0); + mapCallback(); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1789750, nBurnSoundRate, NULL, NULL, NULL, NULL); + + SN76496Init(0, 1789750, 0); + SN76496Init(1, 1789750, 1); + + NamcoSoundInit(18432000 / 6 / 32); + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + AY8910Exit(0); + SN76496Exit(); + NamcoSoundExit(); + + game_select = PACMAN; + acitya = 0; + + nPacBank = -1; + + BurnFree (AllMem); + + return 0; +} + +static void DrawBackground() +{ + for (INT32 offs = 0; offs < 36 * 28; offs++) + { + INT32 sx = (offs % 36); + INT32 sy = offs / 36; + + INT32 row = sy + 2; + INT32 col = sx - 2; + + INT32 ofst; + + if (col & 0x20) + ofst = row + ((col & 0x1f) << 5); + else + ofst = col + (row << 5); + + INT32 code = (charbank << 8) | DrvVidRAM[ofst]; + INT32 color = (DrvColRAM[ofst] & 0x1f) | (colortablebank << 5) | (palettebank << 6); + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, (272 - (sx * 8)) + 8, (224 - (sy * 8)) - 8, color, 2, 0, DrvGfxROM); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx * 8, sy * 8, color, 2, 0, DrvGfxROM); + } + } +} + +static void DrawSprites() +{ + INT32 invert = (game_select == BIRDIY) ? 1 : 0; + + for (INT32 offs = 0x10 - 2;offs >= 0;offs -= 2) + { + INT32 code = (DrvSprRAM[offs] >> 2) | (spritebank << 6); + INT32 color = (DrvSprRAM[offs + 1] & 0x1f ) | (colortablebank << 5) | (palettebank << 6); + + INT32 sx = DrvSprRAM2[offs + 1]; + INT32 sy = DrvSprRAM2[offs]; + INT32 flipx = DrvSprRAM [offs] & 1; + INT32 flipy = DrvSprRAM [offs] & 2; + + if (*flipscreen ^ invert) { + sy = (240 - sy) - 8; + sx += 8; + flipy = !flipy; + flipx = !flipx; + } else { + sx = 272 - sx; + sy = sy - 31; + } + + RenderTileTranstab(pTransDraw, DrvGfxROM + 0x8000, code, color << 2, 0, sx, sy, flipx, flipy, 16, 16, DrvTransTable); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + pacman_palette_init(); + DrvRecalc = 0; + } + + DrawBackground(); + DrawSprites(); + + BurnTransferCopy(Palette); + + return 0; +} + +static INT32 DrvFrame() +{ + watchdog++; + if (watchdog >= 16) { + bprintf (0, _T("watchdog triggered\n")); + DrvDoReset(0); + } + + if (DrvReset) { + DrvDoReset(1); + } + + { + memset (DrvInputs, 0, 2); + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + if (!acitya && game_select != SHOOTBUL) { + if ((DrvInputs[0] & 6) == 6) DrvInputs[0] &= ~0x06; + if ((DrvInputs[0] & 9) == 9) DrvInputs[0] &= ~0x09; + if ((DrvInputs[1] & 6) == 6) DrvInputs[1] &= ~0x06; + if ((DrvInputs[1] & 9) == 9) DrvInputs[1] &= ~0x09; + } + + DrvInputs[0] ^= DrvDips[0]; + DrvInputs[1] ^= DrvDips[1]; + + nAnalogAxis[0] -= DrvAxis[0]; + nAnalogAxis[1] -= DrvAxis[1]; + + nCharAxis[0] = (DrvAxis[0] >> 12) & 0x0f; + nCharAxis[1] = (DrvAxis[1] >> 12) & 0x0f; + + if (game_select == SHOOTBUL) { + DrvInputs[0] ^= nCharAxis[0]; + DrvInputs[1] ^= nCharAxis[1]; + } + } + + ZetOpen(0); + + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesTotal = (18432000 / 6) / 60; + INT32 nCyclesDone = 0; + INT32 nCyclesSegment; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + nNext = (i + 1) * nCyclesTotal / nInterleave; + nCyclesSegment = nNext - nCyclesDone; + nCyclesDone += ZetRun(nCyclesSegment); + + if (game_select == BIGBUCKS) { + INT32 nInterleaveIRQFire = nBurnSoundLen / 20; + for (INT32 j = 0; j < 20; j++) { + if (i == (nInterleaveIRQFire * j) - 1) ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } else { + if (game_select == DREMSHPR || game_select == VANVAN) { + if (i == (nInterleave - 1)) ZetNmi(); + } else { + if (i == (nInterleave - 1) && interrupt_mask) { + ZetSetVector(interrupt_mode); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + if (game_select == DREMSHPR || game_select == CRUSHS) { + INT32 nSample; + + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } else { + if (game_select == VANVAN) { + SN76496Update(0, pSoundBuf, nSegmentLength); + SN76496Update(1, pSoundBuf, nSegmentLength); + } else { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + } + } + } + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + if (game_select == DREMSHPR || game_select == CRUSHS) { + INT32 nSample; + + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } else { + if (game_select == VANVAN) { + SN76496Update(0, pSoundBuf, nSegmentLength); + SN76496Update(1, pSoundBuf, nSegmentLength); + } else { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + } + } + } + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +//------------------------------------------------------------------------------------------------------ + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029693; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + NamcoSoundScan(nAction, pnMin); + AY8910Scan(nAction, pnMin); + SN76496Scan(nAction, pnMin); + + SCAN_VAR(nPacBank); + + SCAN_VAR(interrupt_mode); + SCAN_VAR(interrupt_mask); + + SCAN_VAR(colortablebank); + SCAN_VAR(palettebank); + SCAN_VAR(spritebank); + SCAN_VAR(charbank); + + SCAN_VAR(alibaba_mystery); + SCAN_VAR(epos_hardware_counter); + SCAN_VAR(mschamp_counter); + SCAN_VAR(cannonb_bit_to_read); + } + + if (nAction & ACB_WRITE) { + if (game_select == MSCHAMP) { + mschamp_set_bank(); + } + + if (game_select == EPOS) { + epos_hardware_set_bank(nPacBank); + } + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------------ + + +// PuckMan (Japan set 1, Probably Bootleg) + +static struct BurnRomInfo puckmanRomDesc[] = { + { "namcopac.6e", 0x1000, 0xfee263b3, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "namcopac.6f", 0x1000, 0x39d1fc83, 1 | BRF_ESS | BRF_PRG }, // 1 + { "namcopac.6h", 0x1000, 0x02083b03, 1 | BRF_ESS | BRF_PRG }, // 2 + { "namcopac.6j", 0x1000, 0x7a36fe55, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(puckman) +STD_ROM_FN(puckman) + +static INT32 puckmanInit() +{ + return DrvInit(StandardMap, NULL, PACMAN); +} + +struct BurnDriver BurnDrvpuckman = { + "puckman", NULL, NULL, NULL, "1980", + "PuckMan (Japan set 1, Probably Bootleg)\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, puckmanRomInfo, puckmanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// PuckMan (Japan set 1 with speedup hack) + +static struct BurnRomInfo puckmanfRomDesc[] = { + { "namcopac.6e", 0x1000, 0xfee263b3, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "nampfast.6f", 0x1000, 0x51b38db9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "namcopac.6h", 0x1000, 0x02083b03, 1 | BRF_ESS | BRF_PRG }, // 2 + { "namcopac.6j", 0x1000, 0x7a36fe55, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(puckmanf) +STD_ROM_FN(puckmanf) + +struct BurnDriver BurnDrvpuckmanf = { + "puckmanf", "puckman", NULL, NULL, "1980", + "PuckMan (Japan set 1 with speedup hack)\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, puckmanfRomInfo, puckmanfRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// PuckMan (Japan set 3) + +static struct BurnRomInfo puckmodRomDesc[] = { + { "namcopac.6e", 0x1000, 0xfee263b3, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "namcopac.6f", 0x1000, 0x39d1fc83, 1 | BRF_ESS | BRF_PRG }, // 1 + { "namcopac.6h", 0x1000, 0x02083b03, 1 | BRF_ESS | BRF_PRG }, // 2 + { "npacmod.6j", 0x1000, 0x7d98d5f5, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(puckmod) +STD_ROM_FN(puckmod) + +struct BurnDriver BurnDrvpuckmod = { + "puckmod", "puckman", NULL, NULL, "1981", + "PuckMan (Japan set 3)\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, puckmodRomInfo, puckmodRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// PuckMan (Japan set 2) + +static struct BurnRomInfo puckmanaRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "prg7", 0x0800, 0xb6289b26, 1 | BRF_ESS | BRF_PRG }, // 3 + { "prg8", 0x0800, 0x17a88c13, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "chg1", 0x0800, 0x2066a0b7, 2 | BRF_GRA }, // 5 Graphics + { "chg2", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 6 + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(puckmana) +STD_ROM_FN(puckmana) + +struct BurnDriver BurnDrvpuckmana = { + "puckmana", "puckman", NULL, NULL, "1981", + "PuckMan (Japan set 2)\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, puckmanaRomInfo, puckmanaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Man (Midway) + +static struct BurnRomInfo pacmanRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.6j", 0x1000, 0x817d94e3, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(pacman) +STD_ROM_FN(pacman) + +struct BurnDriver BurnDrvpacman = { + "pacman", "puckman", NULL, NULL, "1980", + "Pac-Man (Midway)\0", NULL, "[Namco] (Midway license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacmanRomInfo, pacmanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Man (Midway, with speedup hack) + +static struct BurnRomInfo pacmanfRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacfast.6f", 0x1000, 0x720dc3ee, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.6j", 0x1000, 0x817d94e3, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(pacmanf) +STD_ROM_FN(pacmanf) + +struct BurnDriver BurnDrvpacmanf = { + "pacmanf", "puckman", NULL, NULL, "1980", + "Pac-Man (Midway, with speedup hack)\0", NULL, "[Namco] (Midway license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacmanfRomInfo, pacmanfRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Hangly-Man (set 1) + +static struct BurnRomInfo hanglyRomDesc[] = { + { "hangly.6e", 0x1000, 0x5fe8610a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "hangly.6f", 0x1000, 0x73726586, 1 | BRF_ESS | BRF_PRG }, // 1 + { "hangly.6h", 0x1000, 0x4e7ef99f, 1 | BRF_ESS | BRF_PRG }, // 2 + { "hangly.6j", 0x1000, 0x7f4147e6, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(hangly) +STD_ROM_FN(hangly) + +struct BurnDriver BurnDrvhangly = { + "hangly", "puckman", NULL, NULL, "1981", + "Hangly-Man (set 1)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, hanglyRomInfo, hanglyRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Hangly-Man (set 2) + +static struct BurnRomInfo hangly2RomDesc[] = { + { "hangly.6e", 0x1000, 0x5fe8610a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "hangly2.6f", 0x0800, 0x5ba228bb, 1 | BRF_ESS | BRF_PRG }, // 1 + { "hangly2.6m", 0x0800, 0xbaf5461e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "hangly.6h", 0x1000, 0x4e7ef99f, 1 | BRF_ESS | BRF_PRG }, // 3 + { "hangly2.6j", 0x0800, 0x51305374, 1 | BRF_ESS | BRF_PRG }, // 4 + { "hangly2.6p", 0x0800, 0x427c9d4d, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "pacmanh.5e", 0x1000, 0x299fb17a, 2 | BRF_GRA }, // 6 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(hangly2) +STD_ROM_FN(hangly2) + +struct BurnDriver BurnDrvhangly2 = { + "hangly2", "puckman", NULL, NULL, "1981", + "Hangly-Man (set 2)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, hangly2RomInfo, hangly2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Hangly-Man (set 3) + +static struct BurnRomInfo hangly3RomDesc[] = { + { "hm1.6e", 0x0800, 0x9d027c4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "hm5.6k", 0x0800, 0x194c7189, 1 | BRF_ESS | BRF_PRG }, // 1 + { "hangly2.6f", 0x0800, 0x5ba228bb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "hangly2.6m", 0x0800, 0xbaf5461e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "hm3.6h", 0x0800, 0x08419c4a, 1 | BRF_ESS | BRF_PRG }, // 4 + { "hm7.6n", 0x0800, 0xab74b51f, 1 | BRF_ESS | BRF_PRG }, // 5 + { "hm4.6j", 0x0800, 0x5039b082, 1 | BRF_ESS | BRF_PRG }, // 6 + { "hm8.6p", 0x0800, 0x931770d7, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "hm9.5e", 0x0800, 0x5f4be3cc, 2 | BRF_GRA }, // 8 Graphics + { "hm11.5h", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 9 + { "hm10.5f", 0x0800, 0x9e39323a, 2 | BRF_GRA }, // 10 + { "hm12.5j", 0x0800, 0x1b1d9096, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(hangly3) +STD_ROM_FN(hangly3) + +struct BurnDriver BurnDrvhangly3 = { + "hangly3", "puckman", NULL, NULL, "1981", + "Hangly-Man (set 3)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, hangly3RomInfo, hangly3RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Popeye Man + +static struct BurnRomInfo popeyemanRomDesc[] = { + { "1.6e", 0x0800, 0x9d027c4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "5.6k", 0x0800, 0x194c7189, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.6f", 0x0800, 0x5ba228bb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6.6m", 0x0800, 0xbaf5461e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.6h", 0x0800, 0x08419c4a, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.6n", 0x0800, 0xab74b51f, 1 | BRF_ESS | BRF_PRG }, // 5 + { "4.6j", 0x0800, 0x5039b082, 1 | BRF_ESS | BRF_PRG }, // 6 + { "8.6p", 0x0800, 0x931770d7, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "9.5e", 0x0800, 0xb569c4c1, 2 | BRF_GRA }, // 8 Graphics + { "11.5h", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 9 + { "10.5f", 0x0800, 0x014fb5a4, 2 | BRF_GRA }, // 10 + { "12.5j", 0x0800, 0x21b91c64, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(popeyeman) +STD_ROM_FN(popeyeman) + +struct BurnDriver BurnDrvpopeyeman = { + "popeyeman", "puckman", NULL, NULL, "1981", + "Popeye-Man\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HACK, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, popeyemanRomInfo, popeyemanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crock-Man + +static struct BurnRomInfo crockmanRomDesc[] = { + { "p1.6e", 0x0800, 0x2c0fa0ab, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "p5.6k", 0x0800, 0xafeca2f1, 1 | BRF_ESS | BRF_PRG }, // 1 + { "p2.6f", 0x0800, 0x7d177853, 1 | BRF_ESS | BRF_PRG }, // 2 + { "p6.6m", 0x0800, 0xd3e8914c, 1 | BRF_ESS | BRF_PRG }, // 3 + { "p3.6h", 0x0800, 0x9045a44c, 1 | BRF_ESS | BRF_PRG }, // 4 + { "p7.6n", 0x0800, 0x93f344c5, 1 | BRF_ESS | BRF_PRG }, // 5 + { "p4.6j", 0x0800, 0xbed4a077, 1 | BRF_ESS | BRF_PRG }, // 6 + { "p8.6p", 0x0800, 0x800be41e, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "p9.5e", 0x0800, 0xa10218c4, 2 | BRF_GRA }, // 8 Graphics + { "p11.5h", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 9 + { "p10.5f", 0x0800, 0x9e39323a, 2 | BRF_GRA }, // 10 + { "p12.5j", 0x0800, 0x1b1d9096, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(crockman) +STD_ROM_FN(crockman) + +struct BurnDriver BurnDrvcrockman = { + "crockman", "puckman", NULL, NULL, "1980", + "Crock-Man (bootleg, Rene-Pierre)\0", NULL, "bootleg (Rene-Pierre)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_BOOTLEG, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crockmanRomInfo, crockmanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Man (Midway, harder) + +static struct BurnRomInfo pacmodRomDesc[] = { + { "pacmanh.6e", 0x1000, 0x3b2ec270, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacmanh.6h", 0x1000, 0x18811780, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacmanh.6j", 0x1000, 0x5c96a733, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacmanh.5e", 0x1000, 0x299fb17a, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(pacmod) +STD_ROM_FN(pacmod) + +struct BurnDriver BurnDrvpacmod = { + "pacmod", "puckman", NULL, NULL, "1981", + "Pac-Man (Midway, harder)\0", NULL, "[Namco] (Midway license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacmodRomInfo, pacmodRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Puckman (Falcom?) + +static struct BurnRomInfo puckmanhRomDesc[] = { + { "pm01.6e", 0x1000, 0x5fe8610a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pm02.6f", 0x1000, 0x61d38c6c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pm03.6h", 0x1000, 0x4e7ef99f, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pm04.6j", 0x1000, 0x8939ddd2, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pm9.5e", 0x0800, 0x2229ab07, 2 | BRF_GRA }, // 4 Graphics + { "pm11.5h", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 5 + { "pm10.5f", 0x0800, 0x9e39323a, 2 | BRF_GRA }, // 6 + { "pm12.5j", 0x0800, 0x1b1d9096, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(puckmanh) +STD_ROM_FN(puckmanh) + +struct BurnDriver BurnDrvpuckmanh = { + "puckmanh", "puckman", NULL, NULL, "1981", + "Puckman (Falcom?)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, puckmanhRomInfo, puckmanhRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// New Puck-X + +static struct BurnRomInfo newpuckxRomDesc[] = { + { "puckman.6e", 0x1000, 0xa8ae23c5, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "puckman.6h", 0x1000, 0x197443f8, 1 | BRF_ESS | BRF_PRG }, // 2 + { "puckman.6j", 0x1000, 0x2e64a3ba, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacman.5e", 0x1000, 0x0c944964, 2 | BRF_GRA }, // 4 Graphics + { "pacman.5f", 0x1000, 0x958fedf9, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(newpuckx) +STD_ROM_FN(newpuckx) + +struct BurnDriver BurnDrvnewpuckx = { + "newpuckx", "puckman", NULL, NULL, "1980", + "New Puck-X\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, newpuckxRomInfo, newpuckxRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Man (Hearts) + +static struct BurnRomInfo pacheartRomDesc[] = { + { "1.6e", 0x0800, 0xd844b679, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacheart.pg2", 0x0800, 0xb9152a38, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.6f", 0x0800, 0x7d177853, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacheart.pg4", 0x0800, 0x842d6574, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.6h", 0x0800, 0x9045a44c, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.6n", 0x0800, 0x888f3c3e, 1 | BRF_ESS | BRF_PRG }, // 5 + { "pacheart.pg7", 0x0800, 0xf5265c10, 1 | BRF_ESS | BRF_PRG }, // 6 + { "pacheart.pg8", 0x0800, 0x1a21a381, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "pacheart.ch1", 0x0800, 0xc62bbabf, 2 | BRF_GRA }, // 8 Graphics + { "chg2", 0x0800, 0x3591b89d, 2 | BRF_GRA }, // 9 + { "pacheart.ch3", 0x0800, 0xca8c184c, 2 | BRF_GRA }, // 10 + { "pacheart.ch4", 0x0800, 0x1b1d9096, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(pacheart) +STD_ROM_FN(pacheart) + +struct BurnDriver BurnDrvpacheart = { + "pacheart", "puckman", NULL, NULL, "1981", + "Pac-Man (Hearts)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacheartRomInfo, pacheartRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Joyman + +static struct BurnRomInfo joymanRomDesc[] = { + { "1.6e", 0x0800, 0xd844b679, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "5.6k", 0x0800, 0xab9c8f29, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.6f", 0x0800, 0x7d177853, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6.6m", 0x0800, 0xb3c8d32e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.6h", 0x0800, 0x9045a44c, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.6n", 0x0800, 0x888f3c3e, 1 | BRF_ESS | BRF_PRG }, // 5 + { "4.6j", 0x0800, 0x00b553f8, 1 | BRF_ESS | BRF_PRG }, // 6 + { "8.6p", 0x0800, 0x5d5ce992, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "9.5e", 0x0800, 0x39b557bc, 2 | BRF_GRA }, // 8 Graphics + { "11.5h", 0x0800, 0x33e0289e, 2 | BRF_GRA }, // 9 + { "10.5f", 0x0800, 0x338771a6, 2 | BRF_GRA }, // 10 + { "12.5j", 0x0800, 0xf4f0add5, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(joyman) +STD_ROM_FN(joyman) + +struct BurnDriver BurnDrvjoyman = { + "joyman", "puckman", NULL, NULL, "1982", + "Joyman\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, joymanRomInfo, joymanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Buccaneer + +static struct BurnRomInfo bucanerRomDesc[] = { + { "1.6e", 0x0800, 0x2c0fa0ab, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "5.6k", 0x0800, 0xafeca2f1, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.6f", 0x0800, 0x6b53ada9, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6.6m", 0x0800, 0x35f3ca84, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.6h", 0x0800, 0x9045a44c, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.6n", 0x0800, 0x888f3c3e, 1 | BRF_ESS | BRF_PRG }, // 5 + { "4.6j", 0x0800, 0x292de161, 1 | BRF_ESS | BRF_PRG }, // 6 + { "8.6p", 0x0800, 0x884af858, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "9.5e", 0x0800, 0x4060c077, 2 | BRF_GRA }, // 8 Graphics + { "11.5h", 0x0800, 0xe3861283, 2 | BRF_GRA }, // 9 + { "10.5f", 0x0800, 0x09f66dec, 2 | BRF_GRA }, // 10 + { "12.5j", 0x0800, 0x653314e7, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(bucaner) +STD_ROM_FN(bucaner) + +struct BurnDriver BurnDrvbucaner = { + "bucaner", "puckman", NULL, NULL, "19??", + "Buccaneer\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, bucanerRomInfo, bucanerRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Caterpillar Pacman Hack + +static struct BurnRomInfo ctrpllrpRomDesc[] = { + { "c1.bin", 0x0800, 0x9d027c4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "c5.bin", 0x0800, 0xf39846d3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "c2.bin", 0x0800, 0xafa149a8, 1 | BRF_ESS | BRF_PRG }, // 2 + { "c6.bin", 0x0800, 0xbaf5461e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "c3.bin", 0x0800, 0x6bb282a1, 1 | BRF_ESS | BRF_PRG }, // 4 + { "c7.bin", 0x0800, 0xfa2140f5, 1 | BRF_ESS | BRF_PRG }, // 5 + { "c4.bin", 0x0800, 0x86c91e0e, 1 | BRF_ESS | BRF_PRG }, // 6 + { "c8.bin", 0x0800, 0x3d28134e, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "c9.bin", 0x0800, 0x1c4617be, 2 | BRF_GRA }, // 8 Graphics + { "c11.bin", 0x0800, 0x46f72fef, 2 | BRF_GRA }, // 9 + { "c10.bin", 0x0800, 0xba9ec199, 2 | BRF_GRA }, // 10 + { "c12.bin", 0x0800, 0x41c09655, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(ctrpllrp) +STD_ROM_FN(ctrpllrp) + +struct BurnDriver BurnDrvctrpllrp = { + "ctrpllrp", "puckman", NULL, NULL, "1982", + "Caterpillar Pacman Hack\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, ctrpllrpRomInfo, ctrpllrpRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Man Plus + +static struct BurnRomInfo pacplusRomDesc[] = { + { "pacplus.6e", 0x1000, 0xd611ef68, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacplus.6f", 0x1000, 0xc7207556, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacplus.6h", 0x1000, 0xae379430, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacplus.6j", 0x1000, 0x5a6dff7b, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pacplus.5e", 0x1000, 0x022c35da, 2 | BRF_GRA }, // 4 Graphics + { "pacplus.5f", 0x1000, 0x4de65cdd, 2 | BRF_GRA }, // 5 + + { "pacplus.7f", 0x0020, 0x063dd53a, 3 | BRF_GRA }, // 6 Color Proms + { "pacplus.4a", 0x0100, 0xe271a166, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(pacplus) +STD_ROM_FN(pacplus) + +static UINT8 pacplus_decrypt(INT32 addr, UINT8 e) +{ + static const UINT8 swap_xor_table[6][9] = + { + { 7,6,5,4,3,2,1,0, 0x00 }, + { 7,6,5,4,3,2,1,0, 0x28 }, + { 6,1,3,2,5,7,0,4, 0x96 }, + { 6,1,5,2,3,7,0,4, 0xbe }, + { 0,3,7,6,4,2,1,5, 0xd5 }, + { 0,3,4,6,7,2,1,5, 0xdd } + }; + + static const INT32 picktable[32] = + { + 0,2,4,2,4,0,4,2,2,0,2,2,4,0,4,2, + 2,2,4,0,4,2,4,0,0,4,0,4,4,2,4,2 + }; + + INT32 method = picktable[(addr & 0x001) | ((addr & 0x004) >> 1) | ((addr & 0x020) >> 3) | ((addr & 0x080) >> 4) | ((addr & 0x200) >> 5)]; + + if (addr & 0x800) method ^= 1; + + const UINT8 *tbl = swap_xor_table[method]; + + return BITSWAP08(e,tbl[0],tbl[1],tbl[2],tbl[3],tbl[4],tbl[5],tbl[6],tbl[7]) ^ tbl[8]; +} + +void pacplus_decode() +{ + for (INT32 i = 0; i < 0x4000; i++) + { + DrvZ80ROM[i] = pacplus_decrypt(i, DrvZ80ROM[i]); + } +} + +static INT32 pacplusInit() +{ + return DrvInit(StandardMap, pacplus_decode, PACMAN); +} + +struct BurnDriver BurnDrvpacplus = { + "pacplus", NULL, NULL, NULL, "1982", + "Pac-Man Plus\0", NULL, "[Namco] (Midway license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacplusRomInfo, pacplusRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + pacplusInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Newpuc2 + +static struct BurnRomInfo newpuc2RomDesc[] = { + { "6e.cpu", 0x0800, 0x69496a98, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6k.cpu", 0x0800, 0x158fc01c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6f.cpu", 0x0800, 0x7d177853, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6m.cpu", 0x0800, 0x70810ccf, 1 | BRF_ESS | BRF_PRG }, // 3 + { "6h.cpu", 0x0800, 0x81719de8, 1 | BRF_ESS | BRF_PRG }, // 4 + { "6n.cpu", 0x0800, 0x3f250c58, 1 | BRF_ESS | BRF_PRG }, // 5 + { "6j.cpu", 0x0800, 0xe6675736, 1 | BRF_ESS | BRF_PRG }, // 6 + { "6p.cpu", 0x0800, 0x1f81e765, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "5e.cpu", 0x0800, 0x2066a0b7, 2 | BRF_GRA }, // 8 Graphics + { "5h.cpu", 0x0800, 0x777c70d3, 2 | BRF_GRA }, // 9 + { "5f.cpu", 0x0800, 0xca8c184c, 2 | BRF_GRA }, // 10 + { "5j.cpu", 0x0800, 0x7dc75a81, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(newpuc2) +STD_ROM_FN(newpuc2) + +struct BurnDriver BurnDrvnewpuc2 = { + "newpuc2", "puckman", NULL, NULL, "1980", + "Newpuc2\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, newpuc2RomInfo, newpuc2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Newpuc2b + +static struct BurnRomInfo newpuc2bRomDesc[] = { + { "np2b1.bin", 0x0800, 0x9d027c4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6k.cpu", 0x0800, 0x158fc01c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6f.cpu", 0x0800, 0x7d177853, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6m.cpu", 0x0800, 0x70810ccf, 1 | BRF_ESS | BRF_PRG }, // 3 + { "np2b3.bin", 0x0800, 0xf5e4b2b1, 1 | BRF_ESS | BRF_PRG }, // 4 + { "6n.cpu", 0x0800, 0x3f250c58, 1 | BRF_ESS | BRF_PRG }, // 5 + { "np2b4.bin", 0x0800, 0xf068e009, 1 | BRF_ESS | BRF_PRG }, // 6 + { "np2b8.bin", 0x0800, 0x1fadcc2f, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "5e.cpu", 0x0800, 0x2066a0b7, 2 | BRF_GRA }, // 8 Graphics + { "5h.cpu", 0x0800, 0x777c70d3, 2 | BRF_GRA }, // 9 + { "5f.cpu", 0x0800, 0xca8c184c, 2 | BRF_GRA }, // 10 + { "5j.cpu", 0x0800, 0x7dc75a81, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Prom + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(newpuc2b) +STD_ROM_FN(newpuc2b) + +struct BurnDriver BurnDrvnewpuc2b = { + "newpuc2b", "puckman", NULL, NULL, "1980", + "Newpuc2b\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, newpuc2bRomInfo, newpuc2bRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// MS Pacman + +static struct BurnRomInfo mspacmanRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.6j", 0x1000, 0x817d94e3, 1 | BRF_ESS | BRF_PRG }, // 3 + { "u5", 0x0800, 0xf45fbbcd, 1 | BRF_ESS | BRF_PRG }, // 4 + { "u6", 0x1000, 0xa90e7000, 1 | BRF_ESS | BRF_PRG }, // 5 + { "u7", 0x1000, 0xc82cd714, 1 | BRF_ESS | BRF_PRG }, // 6 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 7 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 8 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 9 Color Prom + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 10 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 11 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 12 Timing Prom (not used) +}; + +STD_ROM_PICK(mspacman) +STD_ROM_FN(mspacman) + +static void MspacmanDecode() +{ +#define ADD0SWAP(x) BITSWAP16(x,15,14,13,12,11,3,7,9,10,8,6,5,4,2,1,0) +#define ADD1SWAP(x) BITSWAP16(x,15,14,13,12,11,8,7,5,9,10,6,3,4,2,1,0) +#define DATASWAP(x) BITSWAP08(x,0,4,5,7,6,3,2,1) + + static const UINT16 tab[10 * 8] = { // even is dst, odd is src + 0x0410, 0x8008, 0x08E0, 0x81D8, 0x0A30, 0x8118, 0x0BD0, 0x80D8, + 0x0C20, 0x8120, 0x0E58, 0x8168, 0x0EA8, 0x8198, 0x1000, 0x8020, + 0x1008, 0x8010, 0x1288, 0x8098, 0x1348, 0x8048, 0x1688, 0x8088, + 0x16B0, 0x8188, 0x16D8, 0x80C8, 0x16F8, 0x81C8, 0x19A8, 0x80A8, + 0x19B8, 0x81A8, 0x2060, 0x8148, 0x2108, 0x8018, 0x21A0, 0x81A0, + 0x2298, 0x80A0, 0x23E0, 0x80E8, 0x2418, 0x8000, 0x2448, 0x8058, + 0x2470, 0x8140, 0x2488, 0x8080, 0x24B0, 0x8180, 0x24D8, 0x80C0, + 0x24F8, 0x81C0, 0x2748, 0x8050, 0x2780, 0x8090, 0x27B8, 0x8190, + 0x2800, 0x8028, 0x2B20, 0x8100, 0x2B30, 0x8110, 0x2BF0, 0x81D0, + 0x2CC0, 0x80D0, 0x2CD8, 0x80E0, 0x2CF0, 0x81E0, 0x2D60, 0x8160 + }; + + memcpy (DrvZ80ROM + 0x0b000, DrvZ80ROM + 0x0a000, 0x01000); + memcpy (DrvZ80ROM + 0x10000, DrvZ80ROM + 0x00000, 0x03000); + + for (INT32 i = 0; i < 0x1000; i++) + { + DrvZ80ROM[0x13000+i] = DATASWAP(DrvZ80ROM[0xb000+ADD0SWAP(i)]); + } + + for (INT32 i = 0; i < 0x800; i++) + { + DrvZ80ROM[0x18000+i] = DATASWAP(DrvZ80ROM[0x8000+ADD1SWAP(i)]); + DrvZ80ROM[0x18800+i] = DATASWAP(DrvZ80ROM[0x9800+ADD0SWAP(i)]); + DrvZ80ROM[0x19000+i] = DATASWAP(DrvZ80ROM[0x9000+ADD0SWAP(i)]); + DrvZ80ROM[0x19800+i] = DrvZ80ROM[0x1800+i]; + } + + memcpy (DrvZ80ROM + 0x1a000, DrvZ80ROM + 0x02000, 0x2000); + + for (INT32 i = 0; i < 80; i+=2) { // apply patches + memcpy (DrvZ80ROM + 0x10000 + tab[i], DrvZ80ROM + 0x10000 + tab[i+1], 8); + } + + memcpy (DrvZ80ROM + 0x8000, DrvZ80ROM, 0x4000); +} + +static INT32 mspacmanInit() +{ + return DrvInit(MspacmanMap, MspacmanDecode, MSPACMAN); +} + +struct BurnDriver BurnDrvmspacman = { + "mspacman", NULL, NULL, NULL, "1980", + "MS Pacman\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacmanRomInfo, mspacmanRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pac-Man (with speedup hack) + +static struct BurnRomInfo mspacmnfRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacfast.6f", 0x1000, 0x720dc3ee, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.6j", 0x1000, 0x817d94e3, 1 | BRF_ESS | BRF_PRG }, // 3 + { "u5", 0x0800, 0xf45fbbcd, 1 | BRF_ESS | BRF_PRG }, // 4 + { "u6", 0x1000, 0xa90e7000, 1 | BRF_ESS | BRF_PRG }, // 5 + { "u7", 0x1000, 0xc82cd714, 1 | BRF_ESS | BRF_PRG }, // 6 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 7 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 8 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 9 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(mspacmnf) +STD_ROM_FN(mspacmnf) + +struct BurnDriver BurnDrvmspacmnf = { + "mspacmnf", "mspacman", NULL, NULL, "1980", + "Ms. Pac-Man (with speedup hack)\0", NULL, "Midway", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacmnfRomInfo, mspacmnfRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pac Attack + +static struct BurnRomInfo mspacmatRomDesc[] = { + { "pacman.6e", 0x1000, 0xc1e6ab10, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.6h", 0x1000, 0xbcdd1beb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.6j", 0x1000, 0x817d94e3, 1 | BRF_ESS | BRF_PRG }, // 3 + { "u5", 0x0800, 0xf45fbbcd, 1 | BRF_ESS | BRF_PRG }, // 4 + { "u6pacatk", 0x1000, 0xf6d83f4d, 1 | BRF_ESS | BRF_PRG }, // 5 + { "u7", 0x1000, 0xc82cd714, 1 | BRF_ESS | BRF_PRG }, // 6 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 7 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 8 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 9 Color Prom + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 10 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 11 + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 12 Sound Prom (not used) +}; + +STD_ROM_PICK(mspacmat) +STD_ROM_FN(mspacmat) + +struct BurnDriver BurnDrvmspacmat = { + "mspacmat", "mspacman", NULL, NULL, "1980", + "Ms. Pac Attack\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacmatRomInfo, mspacmatRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// MS Pacman (bootleg) + +static struct BurnRomInfo mspacmabRomDesc[] = { + { "boot1", 0x1000, 0xd16b31b7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "boot2", 0x1000, 0x0d32de5e, 1 | BRF_ESS | BRF_PRG }, // 1 + { "boot3", 0x1000, 0x1821ee0b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "boot4", 0x1000, 0x165a9dd8, 1 | BRF_ESS | BRF_PRG }, // 3 + { "boot5", 0x1000, 0x8c3e6de6, 1 | BRF_ESS | BRF_PRG }, // 4 + { "boot6", 0x1000, 0x368cb165, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 6 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(mspacmab) +STD_ROM_FN(mspacmab) + +static INT32 mspacmanbInit() +{ + return DrvInit(MspacmanMap, NULL, PACMAN); +} + +struct BurnDriver BurnDrvmspacmab = { + "mspacmab", "mspacman", NULL, NULL, "1981", + "MS Pacman (bootleg)\0", NULL, "Namco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacmabRomInfo, mspacmabRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pac-Man (bootleg, (encrypted)) + +static struct BurnRomInfo mspacmbeRomDesc[] = { + { "boot1", 0x1000, 0xd16b31b7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2.bin", 0x1000, 0x04e6c486, 1 | BRF_ESS | BRF_PRG }, // 1 + { "boot3", 0x1000, 0x1821ee0b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "boot4", 0x1000, 0x165a9dd8, 1 | BRF_ESS | BRF_PRG }, // 3 + { "boot5", 0x1000, 0x8c3e6de6, 1 | BRF_ESS | BRF_PRG }, // 4 + { "6.bin", 0x1000, 0x206a9623, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 6 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(mspacmbe) +STD_ROM_FN(mspacmbe) + +static void mspacmbe_decode() +{ + for(INT32 i = 0x1000; i < 0x2000; i+=4) + { + if (!(i & 8)) + { + INT32 t = DrvZ80ROM[i+1]; + DrvZ80ROM[i+1] = DrvZ80ROM[i+2]; + DrvZ80ROM[i+2] = t; + }; + } +} + +static INT32 mspacmbeInit() +{ + return DrvInit(MspacmanMap, mspacmbe_decode, PACMAN); +} + +struct BurnDriver BurnDrvmspacmbe = { + "mspacmbe", "mspacman", NULL, NULL, "1981", + "Ms. Pac-Man (bootleg, (encrypted))\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacmbeRomInfo, mspacmbeRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmbeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pac-Gal + +static struct BurnRomInfo pacgalRomDesc[] = { + { "boot1", 0x1000, 0xd16b31b7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "boot2", 0x1000, 0x0d32de5e, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pacman.7fh", 0x1000, 0x513f4d5c, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pacman.7hj", 0x1000, 0x70694c8e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "boot5", 0x1000, 0x8c3e6de6, 1 | BRF_ESS | BRF_PRG }, // 4 + { "boot6", 0x1000, 0x368cb165, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 6 Graphics + { "pacman.5ef", 0x0800, 0x65a3ee71, 2 | BRF_GRA }, // 7 + { "pacman.5hj", 0x0800, 0x50c7477d, 2 | BRF_GRA }, // 8 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 9 Color Proms + { "82s129.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 10 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 11 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 12 Timing Prom (not used) +}; + +STD_ROM_PICK(pacgal) +STD_ROM_FN(pacgal) + +struct BurnDriver BurnDrvpacgal = { + "pacgal", "mspacman", NULL, NULL, "1981", + "Pac-Gal\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pacgalRomInfo, pacgalRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pac-Man Plus + +static struct BurnRomInfo mspacplsRomDesc[] = { + { "boot1", 0x1000, 0xd16b31b7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "mspacatk.2", 0x1000, 0x0af09d31, 1 | BRF_ESS | BRF_PRG }, // 1 + { "boot3", 0x1000, 0x1821ee0b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "boot4", 0x1000, 0x165a9dd8, 1 | BRF_ESS | BRF_PRG }, // 3 + { "mspacatk.5", 0x1000, 0xe6e06954, 1 | BRF_ESS | BRF_PRG }, // 4 + { "mspacatk.6", 0x1000, 0x3b5db308, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x1000, 0x5c281d01, 2 | BRF_GRA }, // 6 Graphics + { "5f", 0x1000, 0x615af909, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(mspacpls) +STD_ROM_FN(mspacpls) + +struct BurnDriver BurnDrvmspacpls = { + "mspacpls", "mspacman", NULL, NULL, "1981", + "Ms. Pac-Man Plus\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mspacplsRomInfo, mspacplsRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + mspacmanbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pacman Champion Edition / Zola-Puc Gal + +static struct BurnRomInfo mschampRomDesc[] = { + { "9fg.bin", 0x10000, 0x04dba113, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + + { "8e.bin", 0x2000, 0x17435f53, 2 | BRF_GRA }, // 1 Graphics + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 2 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 3 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 4 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 5 Timing Prom (not used)) ) +}; + +STD_ROM_PICK(mschamp) +STD_ROM_FN(mschamp) + +static void mschampCallback() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x1000); + + memcpy (tmp + 0x0000, DrvGfxROM + 0x0800, 0x1000); + memcpy (DrvGfxROM + 0x1000, tmp + 0x0000, 0x0800); + memcpy (DrvGfxROM + 0x0800, tmp + 0x0800, 0x0800); + + BurnFree(tmp); +} + +static INT32 mschampInit() +{ + return DrvInit(WoodpekMap, mschampCallback, MSCHAMP); +} + +struct BurnDriver BurnDrvmschamp = { + "mschamp", "mspacman", NULL, NULL, "1995", + "Ms. Pacman Champion Edition / Zola-Puc Gal\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mschampRomInfo, mschampRomName, NULL, NULL, mschampInputInfo, mschampDIPInfo, + mschampInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ms. Pacman Champion Edition / Super Zola Pac Gal + +static struct BurnRomInfo mschampsRomDesc[] = { + { "pm4.bin", 0x10000, 0x7d6b6303, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + + { "pm5.bin", 0x2000, 0x7fe6b9e2, 2 | BRF_GRA }, // 1 Graphics + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 2 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 3 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 4 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 5 Timing Prom (not used)) ) +}; + +STD_ROM_PICK(mschamps) +STD_ROM_FN(mschamps) + +struct BurnDriver BurnDrvmschamps = { + "mschamps", "mspacman", NULL, NULL, "1995", + "Ms. Pacman Champion Edition / Super Zola Pac Gal\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mschampsRomInfo, mschampsRomName, NULL, NULL, mschampInputInfo, mschampDIPInfo, + mschampInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (Kural Samno) + +static struct BurnRomInfo crushRomDesc[] = { + { "crushkrl.6e", 0x1000, 0xa8dd8f54, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "crushkrl.6f", 0x1000, 0x91387299, 1 | BRF_ESS | BRF_PRG }, // 1 + { "crushkrl.6h", 0x1000, 0xd4455f27, 1 | BRF_ESS | BRF_PRG }, // 2 + { "crushkrl.6j", 0x1000, 0xd59fc251, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "maketrax.5e", 0x1000, 0x91bad2da, 2 | BRF_GRA }, // 4 Graphics + { "maketrax.5f", 0x1000, 0xaea79f55, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Prom + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(crush) +STD_ROM_FN(crush) + +static void maketraxCallback() +{ + DrvZ80ROM[0x0224] = 0x00; + DrvZ80ROM[0x0225] = 0x00; + DrvZ80ROM[0x0226] = 0x00; + DrvZ80ROM[0x022D] = 0x00; + DrvZ80ROM[0x022F] = 0x00; + DrvZ80ROM[0x023C] = 0x00; + DrvZ80ROM[0x023D] = 0x00; + DrvZ80ROM[0x023E] = 0x00; + DrvZ80ROM[0x0415] = 0xc9; + DrvZ80ROM[0x0428] = 0xC6; + DrvZ80ROM[0x0429] = 0x12; + DrvZ80ROM[0x115E] = 0xC9; + DrvZ80ROM[0x1481] = 0x28; + DrvZ80ROM[0x1492] = 0x20; + DrvZ80ROM[0x14A5] = 0xC8; + DrvZ80ROM[0x1978] = 0x18; + DrvZ80ROM[0x1C9F] = 0xA7; + DrvZ80ROM[0x1CA0] = 0xC9; + DrvZ80ROM[0x238e] = 0xc9; + DrvZ80ROM[0x3AE5] = 0x3E; + DrvZ80ROM[0x3AE7] = 0xFE; + DrvZ80ROM[0x3AE8] = 0x3F; + DrvZ80ROM[0x3AE9] = 0xC9; +} + +static INT32 crushInit() +{ + return DrvInit(StandardMap, maketraxCallback, PACMAN); +} + +struct BurnDriver BurnDrvcrush = { + "crush", NULL, NULL, NULL, "1981", + "Crush Roller (Kural Samno)\0", NULL, "Kural Samno Electric", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crushRomInfo, crushRomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + crushInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (bootleg) + +static struct BurnRomInfo crushblRomDesc[] = { + { "cr1.bin", 0x1000, 0xe2e84cd1, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "cr2.bin", 0x1000, 0xec020e6f, 1 | BRF_ESS | BRF_PRG }, // 1 + { "cr3.bin", 0x1000, 0xd4455f27, 1 | BRF_ESS | BRF_PRG }, // 2 + { "cr4.bin", 0x1000, 0x9936ae06, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "maketrax.5e", 0x1000, 0x91bad2da, 2 | BRF_GRA }, // 4 Graphics + { "maketrax.5f", 0x1000, 0xaea79f55, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Prom + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(crushbl) +STD_ROM_FN(crushbl) + +struct BurnDriver BurnDrvcrushbl = { + "crushbl", "crush", NULL, NULL, "1981", + "Crush Roller (bootleg)\0", NULL, "Kural Samno Electric", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crushblRomInfo, crushblRomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (bootleg?) + +static struct BurnRomInfo crushbl2RomDesc[] = { + { "cr5.7d", 0x1000, 0x4954d51d, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "cr6.7e", 0x1000, 0x27eb4299, 1 | BRF_ESS | BRF_PRG }, // 1 + { "cr7.7h", 0x1000, 0xd297108e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "cr8.7j", 0x1000, 0xbcc40eaf, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "cr1.5e", 0x0800, 0xc7617198, 2 | BRF_GRA }, // 4 Graphics + { "cr3.5h", 0x0800, 0xc15b6967, 2 | BRF_GRA }, // 5 + { "cr2.5f", 0x0800, 0xd5bc5cb8, 2 | BRF_GRA }, // 6 + { "cr4.5j", 0x0800, 0xd35d1caf, 2 | BRF_GRA }, // 7 + + { "74s288.8a", 0x0020, 0xff344446, 3 | BRF_GRA }, // 8 Color Prom + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(crushbl2) +STD_ROM_FN(crushbl2) + +struct BurnDriver BurnDrvcrushbl2 = { + "crushbl2", "crush", NULL, NULL, "1981", + "Crush Roller (bootleg?)\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crushbl2RomInfo, crushbl2RomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (Kural Esco - bootleg?) + +static struct BurnRomInfo crush2RomDesc[] = { + { "tp1", 0x0800, 0xf276592e, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "tp5a", 0x0800, 0x3d302abe, 1 | BRF_ESS | BRF_PRG }, // 1 + { "tp2", 0x0800, 0x25f42e70, 1 | BRF_ESS | BRF_PRG }, // 2 + { "tp6", 0x0800, 0x98279cbe, 1 | BRF_ESS | BRF_PRG }, // 3 + { "tp3", 0x0800, 0x8377b4cb, 1 | BRF_ESS | BRF_PRG }, // 4 + { "tp7", 0x0800, 0xd8e76c8c, 1 | BRF_ESS | BRF_PRG }, // 5 + { "tp4", 0x0800, 0x90b28fa3, 1 | BRF_ESS | BRF_PRG }, // 6 + { "tp8", 0x0800, 0x10854e1b, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "tpa", 0x0800, 0xc7617198, 2 | BRF_GRA }, // 8 Graphics + { "tpc", 0x0800, 0xe129d76a, 2 | BRF_GRA }, // 9 + { "tpb", 0x0800, 0xd1899f05, 2 | BRF_GRA }, // 10 + { "tpd", 0x0800, 0xd35d1caf, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(crush2) +STD_ROM_FN(crush2) + +struct BurnDriver BurnDrvcrush2 = { + "crush2", "crush", NULL, NULL, "1981", + "Crush Roller (Kural Esco - bootleg?)\0", NULL, "Kural Esco Electric", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crush2RomInfo, crush2RomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (Kural - bootleg?) + +static struct BurnRomInfo crush3RomDesc[] = { + { "unkmol.4e", 0x0800, 0x49150ddf, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "unkmol.6e", 0x0800, 0x21f47e17, 1 | BRF_ESS | BRF_PRG }, // 1 + { "unkmol.4f", 0x0800, 0x9b6dd592, 1 | BRF_ESS | BRF_PRG }, // 2 + { "unkmol.6f", 0x0800, 0x755c1452, 1 | BRF_ESS | BRF_PRG }, // 3 + { "unkmol.4h", 0x0800, 0xed30a312, 1 | BRF_ESS | BRF_PRG }, // 4 + { "unkmol.6h", 0x0800, 0xfe4bb0eb, 1 | BRF_ESS | BRF_PRG }, // 5 + { "unkmol.4j", 0x0800, 0x072b91c9, 1 | BRF_ESS | BRF_PRG }, // 6 + { "unkmol.6j", 0x0800, 0x66fba07d, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "unkmol.5e", 0x0800, 0x338880a0, 2 | BRF_GRA }, // 8 Graphics + { "unkmol.5h", 0x0800, 0x4ce9c81f, 2 | BRF_GRA }, // 9 + { "unkmol.5f", 0x0800, 0x752e3780, 2 | BRF_GRA }, // 10 + { "unkmol.5j", 0x0800, 0x6e00d2ac, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(crush3) +STD_ROM_FN(crush3) + +static void eyes_gfx_decode(UINT8 *src) +{ + UINT8 buf[8]; + + for (INT32 i = 0; i < 8; i++) { + buf[i] = BITSWAP08(src[((i & 1) << 2) | ((i & 4) >> 2) | (i & 2)],7,4,5,6,3,2,1,0); + } + + memcpy (src, buf, 8); +} + +static void eyes_decode() +{ + for (INT32 i = 0; i < 0x4000; i++) + DrvZ80ROM[i] = BITSWAP08(DrvZ80ROM[i],7,6,3,4,5,2,1,0); + + for (INT32 i = 0;i < 0x2000; i += 8) + eyes_gfx_decode(DrvGfxROM + i); +} + +static INT32 crush3Init() +{ + return DrvInit(StandardMap, eyes_decode, PACMAN); +} + +struct BurnDriver BurnDrvcrush3 = { + "crush3", "crush", NULL, NULL, "1981", + "Crush Roller (Kural - bootleg?)\0", NULL, "Kural Electric", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crush3RomInfo, crush3RomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + crush3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (Kural TWT) + +static struct BurnRomInfo crush4RomDesc[] = { + { "crtwt.2", 0x10000, 0xadbd21f7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code (banked) + + { "crtwt.1", 0x4000, 0x4250a9ea, 2 | BRF_GRA }, // 1 Graphics + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 2 Color Proms + { "82s129.bin", 0x0100, 0x2bc5d339, 3 | BRF_GRA }, // 3 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 4 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 5 Timing Prom (not used) +}; + +STD_ROM_PICK(crush4) +STD_ROM_FN(crush4) + +static void crush4Callback() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x4000); + + memcpy (tmp + 0x0000, DrvGfxROM + 0x0000, 0x04000); + memcpy (DrvGfxROM + 0x1000, tmp + 0x0800, 0x00800); + memcpy (DrvGfxROM + 0x0800, tmp + 0x1000, 0x00800); + memcpy (DrvGfxROM + 0x3000, tmp + 0x2800, 0x00800); + memcpy (DrvGfxROM + 0x2800, tmp + 0x3000, 0x00800); + + memcpy (DrvZ80ROM + 0x00000, DrvZ80ROM + 0x08000, 0x04000); + memcpy (DrvZ80ROM + 0x08000, DrvZ80ROM + 0x0c000, 0x04000); + memset (DrvZ80ROM + 0x0c000, 0, 0x4000); + + BurnFree (tmp); +} + +static INT32 crush4Init() +{ + return DrvInit(StandardMap, crush4Callback, PACMAN); +} + +struct BurnDriver BurnDrvcrush4 = { + "crush4", "crush", NULL, NULL, "1981", + "Crush Roller (Kural TWT)\0", NULL, "Kural TWT", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crush4RomInfo, crush4RomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + crush4Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Paint Roller + +static struct BurnRomInfo paintrlrRomDesc[] = { + { "paintrlr.1", 0x0800, 0x556d20b5, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "paintrlr.5", 0x0800, 0x4598a965, 1 | BRF_ESS | BRF_PRG }, // 1 + { "paintrlr.2", 0x0800, 0x2da29c81, 1 | BRF_ESS | BRF_PRG }, // 2 + { "paintrlr.6", 0x0800, 0x1f561c54, 1 | BRF_ESS | BRF_PRG }, // 3 + { "paintrlr.3", 0x0800, 0xe695b785, 1 | BRF_ESS | BRF_PRG }, // 4 + { "paintrlr.7", 0x0800, 0x00e6eec0, 1 | BRF_ESS | BRF_PRG }, // 5 + { "paintrlr.4", 0x0800, 0x0fd5884b, 1 | BRF_ESS | BRF_PRG }, // 6 + { "paintrlr.8", 0x0800, 0x4900114a, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "tpa", 0x0800, 0xc7617198, 2 | BRF_GRA }, // 8 Graphics + { "mbrush.5h", 0x0800, 0xc15b6967, 2 | BRF_GRA }, // 9 + { "mbrush.5f", 0x0800, 0xd5bc5cb8, 2 | BRF_GRA }, // 10 + { "tpd", 0x0800, 0xd35d1caf, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (unused) +}; + +STD_ROM_PICK(paintrlr) +STD_ROM_FN(paintrlr) + +struct BurnDriver BurnDrvpaintrlr = { + "paintrlr", "crush", NULL, NULL, "1981", + "Paint Roller\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, paintrlrRomInfo, paintrlrRomName, NULL, NULL, DrvInputInfo, mbrushDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Crush Roller (Sidam bootleg) + +static struct BurnRomInfo crushsRomDesc[] = { + { "11105-0.0j", 0x1000, 0xdd425429, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "11105-1.1j", 0x1000, 0xf9d89eef, 1 | BRF_ESS | BRF_PRG }, // 1 + { "11105-2.2j", 0x1000, 0x40c23a27, 1 | BRF_ESS | BRF_PRG }, // 2 + { "11105-3.3j", 0x1000, 0x5802644f, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "11105-4.4j", 0x1000, 0x91bad2da, 2 | BRF_GRA }, // 4 Graphics + { "11105-5.5j", 0x1000, 0xb5c14376, 2 | BRF_GRA }, // 5 + + { "74s288.8a", 0x0020, 0xff344446, 3 | BRF_GRA }, // 6 Color Proms + { "24s10.6b", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + // uses AY8910 +}; + +STD_ROM_PICK(crushs) +STD_ROM_FN(crushs) + +static INT32 crushsInit() +{ + return DrvInit(StandardMap, NULL, CRUSHS); +} + +struct BurnDriver BurnDrvcrushs = { + "crushs", "crush", NULL, NULL, "19??", + "Crush Roller (Sidam bootleg)\0", NULL, "[Kural] (Sidam bootleg)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, crushsRomInfo, crushsRomName, NULL, NULL, DrvInputInfo, crushsDIPInfo, + crushsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Make Trax (set 1) + +static struct BurnRomInfo maketraxRomDesc[] = { + { "maketrax.6e", 0x1000, 0x0150fb4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "maketrax.6f", 0x1000, 0x77531691, 1 | BRF_ESS | BRF_PRG }, // 1 + { "maketrax.6h", 0x1000, 0xa2cdc51e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "maketrax.6j", 0x1000, 0x0b4b5e0a, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "maketrax.5e", 0x1000, 0x91bad2da, 2 | BRF_GRA }, // 4 Graphics + { "maketrax.5f", 0x1000, 0xaea79f55, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(maketrax) +STD_ROM_FN(maketrax) + +static INT32 maketraxInit() +{ + return DrvInit(StandardMap, maketraxCallback, MAKETRAX); +} + +struct BurnDriver BurnDrvmaketrax = { + "maketrax", "crush", NULL, NULL, "1981", + "Make Trax (set 1)\0", NULL, "[Kural] (Williams license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, maketraxRomInfo, maketraxRomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + maketraxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Make Trax (set 2) + +static struct BurnRomInfo maketrxbRomDesc[] = { + { "maketrax.6e", 0x1000, 0x0150fb4a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "maketrax.6f", 0x1000, 0x77531691, 1 | BRF_ESS | BRF_PRG }, // 1 + { "maketrxb.6h", 0x1000, 0x6ad342c9, 1 | BRF_ESS | BRF_PRG }, // 2 + { "maketrxb.6j", 0x1000, 0xbe27f729, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "maketrax.5e", 0x1000, 0x91bad2da, 2 | BRF_GRA }, // 4 Graphics + { "maketrax.5f", 0x1000, 0xaea79f55, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(maketrxb) +STD_ROM_FN(maketrxb) + +struct BurnDriver BurnDrvmaketrxb = { + "maketrxb", "crush", NULL, NULL, "1981", + "Make Trax (set 2)\0", NULL, "[Kural] (Williams license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, maketrxbRomInfo, maketrxbRomName, NULL, NULL, DrvInputInfo, maketraxDIPInfo, + maketraxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Magic Brush + +static struct BurnRomInfo mbrushRomDesc[] = { + { "mbrush.6e", 0x1000, 0x750fbff7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "mbrush.6f", 0x1000, 0x27eb4299, 1 | BRF_ESS | BRF_PRG }, // 1 + { "mbrush.6h", 0x1000, 0xd297108e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "mbrush.6j", 0x1000, 0x6fd719d0, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "tpa", 0x0800, 0xc7617198, 2 | BRF_GRA }, // 4 Graphics + { "mbrush.5h", 0x0800, 0xc15b6967, 2 | BRF_GRA }, // 5 + { "mbrush.5f", 0x0800, 0xd5bc5cb8, 2 | BRF_GRA }, // 6 + { "tpd", 0x0800, 0xd35d1caf, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(mbrush) +STD_ROM_FN(mbrush) + +static void mbrushCallback() +{ + DrvZ80ROM[0x3AE2] = 0x3E; + DrvZ80ROM[0x3AE3] = 0x00; + DrvZ80ROM[0x3AE4] = 0x00; +} + +static INT32 mbrushInit() +{ + return DrvInit(StandardMap, mbrushCallback, PACMAN); +} + +struct BurnDriver BurnDrvmbrush = { + "mbrush", "crush", NULL, NULL, "1981", + "Magic Brush\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mbrushRomInfo, mbrushRomName, NULL, NULL, DrvInputInfo, mbrushDIPInfo, + mbrushInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Korosuke Roller + +static struct BurnRomInfo korosukeRomDesc[] = { + { "kr.6e", 0x1000, 0x69f6e2da, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "kr.6f", 0x1000, 0xabf34d23, 1 | BRF_ESS | BRF_PRG }, // 1 + { "kr.6h", 0x1000, 0x76a2e2e2, 1 | BRF_ESS | BRF_PRG }, // 2 + { "kr.6j", 0x1000, 0x33e0e3bb, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "kr.5e", 0x1000, 0xe0380be8, 2 | BRF_GRA }, // 4 Graphics + { "kr.5f", 0x1000, 0x63fec9ee, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "2s140.4a", 0x0100, 0x63efb927, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(korosuke) +STD_ROM_FN(korosuke) + +static void korosukeCallback() +{ + DrvZ80ROM[0x0233] = 0x00; + DrvZ80ROM[0x0234] = 0x00; + DrvZ80ROM[0x0235] = 0x00; + DrvZ80ROM[0x023c] = 0x00; + DrvZ80ROM[0x023e] = 0x00; + DrvZ80ROM[0x024b] = 0x00; + DrvZ80ROM[0x024c] = 0x00; + DrvZ80ROM[0x024d] = 0x00; + DrvZ80ROM[0x044c] = 0xc9; + DrvZ80ROM[0x115B] = 0xC9; + DrvZ80ROM[0x1AE9] = 0x18; + DrvZ80ROM[0x1CA7] = 0xA7; + DrvZ80ROM[0x1CA8] = 0xC9; + DrvZ80ROM[0x238c] = 0xc9; + DrvZ80ROM[0x3AE9] = 0x3E; + DrvZ80ROM[0x3AEB] = 0xFE; + DrvZ80ROM[0x3AEC] = 0x3F; + DrvZ80ROM[0x3AEE] = 0xC9; + DrvZ80ROM[0x045d] = 0xC6; + DrvZ80ROM[0x045e] = 0x12; + DrvZ80ROM[0x1481] = 0x28; + DrvZ80ROM[0x1492] = 0x20; + DrvZ80ROM[0x14A5] = 0xC8; +} + +static INT32 korosukeInit() +{ + return DrvInit(StandardMap, korosukeCallback, MAKETRAX); +} + +struct BurnDriver BurnDrvkorosuke = { + "korosuke", "crush", NULL, NULL, "1981", + "Korosuke Roller\0", NULL, "Kural Electric", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, korosukeRomInfo, korosukeRomName, NULL, NULL, korosukeInputInfo, korosukeDIPInfo, + korosukeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Eyes (Digitrex Techstar) + +static struct BurnRomInfo eyesRomDesc[] = { + { "d7", 0x1000, 0x3b09ac89, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "e7", 0x1000, 0x97096855, 1 | BRF_ESS | BRF_PRG }, // 1 + { "f7", 0x1000, 0x731e294e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "h7", 0x1000, 0x22f7a719, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "d5", 0x1000, 0xd6af0030, 2 | BRF_GRA }, // 5 Graphics + { "e5", 0x1000, 0xa42b5201, 2 | BRF_GRA }, // 6 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 7 Color Proms + { "82s129.4a", 0x0100, 0xd8d78829, 3 | BRF_GRA }, // 8 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 9 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 10 Timing Prom (not used) +}; + +STD_ROM_PICK(eyes) +STD_ROM_FN(eyes) + +static INT32 eyesInit() +{ + return DrvInit(StandardMap, eyes_decode, PACMAN); +} + +struct BurnDriver BurnDrveyes = { + "eyes", NULL, NULL, NULL, "1982", + "Eyes (Digitrex Techstar)\0", NULL, "Digitrex Techstar (Rock-ola license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, eyesRomInfo, eyesRomName, NULL, NULL, eyesInputInfo, eyesDIPInfo, + eyesInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Eyes (Techstar) + +static struct BurnRomInfo eyes2RomDesc[] = { + { "g38201.7d", 0x1000, 0x2cda7185, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "g38202.7e", 0x1000, 0xb9fe4f59, 1 | BRF_ESS | BRF_PRG }, // 1 + { "g38203.7f", 0x1000, 0xd618ba66, 1 | BRF_ESS | BRF_PRG }, // 2 + { "g38204.7h", 0x1000, 0xcf038276, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "g38205.5d", 0x1000, 0x03b1b4c7, 2 | BRF_GRA }, // 4 Graphics + { "e5", 0x1000, 0xa42b5201, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s129.4a", 0x0100, 0xd8d78829, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(eyes2) +STD_ROM_FN(eyes2) + +struct BurnDriver BurnDrveyes2 = { + "eyes2", "eyes", NULL, NULL, "1982", + "Eyes (Techstar)\0", NULL, "Techstar (Rock-ola license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, eyes2RomInfo, eyes2RomName, NULL, NULL, eyesInputInfo, eyesDIPInfo, + eyesInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Eyes (Zaccaria) + +static struct BurnRomInfo eyeszacRomDesc[] = { + { "1.bin", 0x0800, 0xa4a9d7a0, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "5.bin", 0x0800, 0xc32b3f73, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.bin", 0x0800, 0x195b9473, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6.bin", 0x0800, 0x292886cb, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.bin", 0x0800, 0xff94b015, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.bin", 0x0800, 0x9271c58c, 1 | BRF_ESS | BRF_PRG }, // 5 + { "4.bin", 0x0800, 0x965cf32b, 1 | BRF_ESS | BRF_PRG }, // 6 + { "8.bin", 0x0800, 0xc254e92e, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "x.bin", 0x0800, 0x59dce22e, 2 | BRF_GRA }, // 8 Graphics + { "c.bin", 0x0800, 0xaaa7a537, 2 | BRF_GRA }, // 9 + { "b.bin", 0x0800, 0x1969792b, 2 | BRF_GRA }, // 10 + { "p.bin", 0x0800, 0x99af4b30, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s129.4a", 0x0100, 0xd8d78829, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) + + { "11.bin", 0x0800, 0x69c1602a, 0 | BRF_PRG }, // 16 (Not used) +}; + +STD_ROM_PICK(eyeszac) +STD_ROM_FN(eyeszac) + +struct BurnDriver BurnDrveyeszac = { + "eyeszac", "eyes", NULL, NULL, "1982", + "Eyes (Zaccaria)\0", NULL, "Zaccaria / bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, eyeszacRomInfo, eyeszacRomName, NULL, NULL, eyesInputInfo, eyesDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Mr. TNT + +static struct BurnRomInfo mrtntRomDesc[] = { + { "tnt.1", 0x1000, 0x0e836586, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "tnt.2", 0x1000, 0x779c4c5b, 1 | BRF_ESS | BRF_PRG }, // 1 + { "tnt.3", 0x1000, 0xad6fc688, 1 | BRF_ESS | BRF_PRG }, // 2 + { "tnt.4", 0x1000, 0xd77557b3, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "tnt.5", 0x1000, 0x3038cc0e, 2 | BRF_GRA }, // 4 Graphics + { "tnt.6", 0x1000, 0x97634d8b, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 7 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 8 Timing Prom (not used) +}; + +STD_ROM_PICK(mrtnt) +STD_ROM_FN(mrtnt) + +struct BurnDriver BurnDrvmrtnt = { + "mrtnt", NULL, NULL, NULL, "1982", + "Mr. TNT\0", NULL, "Telko", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, mrtntRomInfo, mrtntRomName, NULL, NULL, eyesInputInfo, mrtntDIPInfo, + eyesInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Gorkans + +static struct BurnRomInfo gorkansRomDesc[] = { + { "gorkans8.rom", 0x0800, 0x55100b18, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "gorkans4.rom", 0x0800, 0xb5c604bf, 1 | BRF_ESS | BRF_PRG }, // 1 + { "gorkans7.rom", 0x0800, 0xb8c6def4, 1 | BRF_ESS | BRF_PRG }, // 2 + { "gorkans3.rom", 0x0800, 0x4602c840, 1 | BRF_ESS | BRF_PRG }, // 3 + { "gorkans6.rom", 0x0800, 0x21412a62, 1 | BRF_ESS | BRF_PRG }, // 4 + { "gorkans2.rom", 0x0800, 0xa013310b, 1 | BRF_ESS | BRF_PRG }, // 5 + { "gorkans5.rom", 0x0800, 0x122969b2, 1 | BRF_ESS | BRF_PRG }, // 6 + { "gorkans1.rom", 0x0800, 0xf2524b11, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "gorkgfx4.rom", 0x0800, 0x39cd0dbc, 2 | BRF_GRA }, // 8 Graphics + { "gorkgfx2.rom", 0x0800, 0x33d52535, 2 | BRF_GRA }, // 9 + { "gorkgfx3.rom", 0x0800, 0x4b6b7970, 2 | BRF_GRA }, // 10 + { "gorkgfx1.rom", 0x0800, 0xed70bb3c, 2 | BRF_GRA }, // 11 + + { "gorkprom.4", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "gorkprom.1", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "gorkprom.3", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "gorkprom.2", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(gorkans) +STD_ROM_FN(gorkans) + +struct BurnDriver BurnDrvgorkans = { + "gorkans", "mrtnt", NULL, NULL, "1983", + "Gorkans\0", NULL, "Techstar", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, gorkansRomInfo, gorkansRomName, NULL, NULL, eyesInputInfo, mrtntDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Eggor + +static struct BurnRomInfo eggorRomDesc[] = { + { "1.bin", 0x0800, 0x818ed154, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "5.bin", 0x0800, 0xa4b21d93, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2.bin", 0x0800, 0x5d7a23ed, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6.bin", 0x0800, 0xe9dbca8d, 1 | BRF_ESS | BRF_PRG }, // 3 + { "3.bin", 0x0800, 0x4318ab85, 1 | BRF_ESS | BRF_PRG }, // 4 + { "7.bin", 0x0800, 0x03214d7f, 1 | BRF_ESS | BRF_PRG }, // 5 + { "4.bin", 0x0800, 0xdc805be4, 1 | BRF_ESS | BRF_PRG }, // 6 + { "8.bin", 0x0800, 0xf9ae204b, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "9.bin", 0x0800, 0x96ad8626, 2 | BRF_GRA }, // 8 Graphics + { "11.bin", 0x0800, 0xcc324017, 2 | BRF_GRA }, // 9 + { "10.bin", 0x0800, 0x7c97f513, 2 | BRF_GRA }, // 10 + { "12.bin", 0x0800, 0x2e930602, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(eggor) +STD_ROM_FN(eggor) + +struct BurnDriver BurnDrveggor = { + "eggor", NULL, NULL, NULL, "1982", + "Eggor\0", NULL, "Telko", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, eggorRomInfo, eggorRomName, NULL, NULL, eyesInputInfo, mrtntDIPInfo, + eyesInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + + +// Piranha + +static struct BurnRomInfo piranhaRomDesc[] = { + { "pir1.bin", 0x0800, 0x69a3e6ea, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pir5.bin", 0x0800, 0x245e753f, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pir2.bin", 0x0800, 0x62cb6954, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pir6.bin", 0x0800, 0xcb0700bc, 1 | BRF_ESS | BRF_PRG }, // 3 + { "pir3.bin", 0x0800, 0x843fbfe5, 1 | BRF_ESS | BRF_PRG }, // 4 + { "pir7.bin", 0x0800, 0x73084d5e, 1 | BRF_ESS | BRF_PRG }, // 5 + { "pir4.bin", 0x0800, 0x4cdf6704, 1 | BRF_ESS | BRF_PRG }, // 6 + { "pir8.bin", 0x0800, 0xb86fedb3, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "pir9.bin", 0x0800, 0x0f19eb28, 2 | BRF_GRA }, // 8 Graphics + { "pir11.bin", 0x0800, 0x5f8bdabe, 2 | BRF_GRA }, // 9 + { "pir10.bin", 0x0800, 0xd19399fb, 2 | BRF_GRA }, // 10 + { "pir12.bin", 0x0800, 0xcfb4403d, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Prom + { "piranha.4a", 0x0100, 0x08c9447b, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(piranha) +STD_ROM_FN(piranha) + +static INT32 piranhaInit() +{ + return DrvInit(StandardMap, eyes_decode, PIRANHA); +} + +struct BurnDriver BurnDrvpiranha = { + "piranha", "puckman", NULL, NULL, "1981", + "Piranha\0", NULL, "GL (US Billiards License)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, piranhaRomInfo, piranhaRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + piranhaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Piranha (older) + +static struct BurnRomInfo piranhaoRomDesc[] = { + { "p1.bin", 0x0800, 0xc6ce1bfc, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "p5.bin", 0x0800, 0xa2655a33, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pir2.bin", 0x0800, 0x62cb6954, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pir6.bin", 0x0800, 0xcb0700bc, 1 | BRF_ESS | BRF_PRG }, // 3 + { "pir3.bin", 0x0800, 0x843fbfe5, 1 | BRF_ESS | BRF_PRG }, // 4 + { "pir7.bin", 0x0800, 0x73084d5e, 1 | BRF_ESS | BRF_PRG }, // 5 + { "p4.bin", 0x0800, 0x9363a4d1, 1 | BRF_ESS | BRF_PRG }, // 6 + { "p8.bin", 0x0800, 0x2769979c, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "p9.bin", 0x0800, 0x94eb7563, 2 | BRF_GRA }, // 8 Graphics + { "p11.bin", 0x0800, 0xa3606973, 2 | BRF_GRA }, // 9 + { "p10.bin", 0x0800, 0x84165a2c, 2 | BRF_GRA }, // 10 + { "p12.bin", 0x0800, 0x2699ba9e, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "piranha.4a", 0x0100, 0x08c9447b, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(piranhao) +STD_ROM_FN(piranhao) + +struct BurnDriver BurnDrvpiranhao = { + "piranhao", "puckman", NULL, NULL, "1981", + "Piranha (older)\0", NULL, "GL (US Billiards License)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, piranhaoRomInfo, piranhaoRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + piranhaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Piranha (hack) + +static struct BurnRomInfo piranhahRomDesc[] = { + { "pr1.cpu", 0x1000, 0xbc5ad024, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "pacman.6f", 0x1000, 0x1a6fb2d4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "pr3.cpu", 0x1000, 0x473c379d, 1 | BRF_ESS | BRF_PRG }, // 2 + { "pr4.cpu", 0x1000, 0x63fbf895, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "pr5.cpu", 0x0800, 0x3fc4030c, 2 | BRF_GRA }, // 4 Graphics + { "pr7.cpu", 0x0800, 0x30b9a010, 2 | BRF_GRA }, // 5 + { "pr6.cpu", 0x0800, 0xf3e9c9d5, 2 | BRF_GRA }, // 6 + { "pr8.cpu", 0x0800, 0x133d720d, 2 | BRF_GRA }, // 7 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 8 Color Prom + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(piranhah) +STD_ROM_FN(piranhah) + +struct BurnDriver BurnDrvpiranhah = { + "piranhah", "puckman", NULL, NULL, "1981", + "Piranha (hack)\0", NULL, "hack", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, piranhahRomInfo, piranhahRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Abscam + +static struct BurnRomInfo abscamRomDesc[] = { + { "as0.bin", 0x0800, 0x0b102302, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "as4.bin", 0x0800, 0x3116a8ec, 1 | BRF_ESS | BRF_PRG }, // 1 + { "as1.bin", 0x0800, 0xbc0281e0, 1 | BRF_ESS | BRF_PRG }, // 2 + { "as5.bin", 0x0800, 0x428ee2e8, 1 | BRF_ESS | BRF_PRG }, // 3 + { "as2.bin", 0x0800, 0xe05d46ad, 1 | BRF_ESS | BRF_PRG }, // 4 + { "as6.bin", 0x0800, 0x3ae9a8cb, 1 | BRF_ESS | BRF_PRG }, // 5 + { "as3.bin", 0x0800, 0xb39eb940, 1 | BRF_ESS | BRF_PRG }, // 6 + { "as7.bin", 0x0800, 0x16cf1c67, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "as8.bin", 0x0800, 0x61daabe5, 2 | BRF_GRA }, // 8 Graphics + { "as10.bin", 0x0800, 0x81d50c98, 2 | BRF_GRA }, // 9 + { "as9.bin", 0x0800, 0xa3bd1613, 2 | BRF_GRA }, // 10 + { "as11.bin", 0x0800, 0x9d802b68, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "as4a.bin", 0x0100, 0x1605b324, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(abscam) +STD_ROM_FN(abscam) + +struct BurnDriver BurnDrvabscam = { + "abscam", "puckman", NULL, NULL, "1981", + "Abscam\0", NULL, "GL (US Billiards License)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, abscamRomInfo, abscamRomName, NULL, NULL, DrvInputInfo, mspacmanDIPInfo, + piranhaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Jump Shot + +static struct BurnRomInfo jumpshotRomDesc[] = { + { "6e", 0x1000, 0xf00def9a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6f", 0x1000, 0xf70deae2, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6h", 0x1000, 0x894d6f68, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6j", 0x1000, 0xf15a108a, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "5e", 0x1000, 0xd9fa90f5, 2 | BRF_GRA }, // 4 Graphics + { "5f", 0x1000, 0x2ec711c1, 2 | BRF_GRA }, // 5 + + { "prom.7f", 0x0020, 0x872b42f3, 3 | BRF_GRA }, // 6 Color Prom + { "prom.4a", 0x0100, 0x0399f39f, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(jumpshot) +STD_ROM_FN(jumpshot) + +static UINT8 jumpshot_decrypt(INT32 addr, UINT8 e) +{ + static const UINT8 swap_xor_table[6][9] = { + { 7,6,5,4,3,2,1,0, 0x00 }, + { 7,6,3,4,5,2,1,0, 0x20 }, + { 5,0,4,3,7,1,2,6, 0xa4 }, + { 5,0,4,3,7,1,2,6, 0x8c }, + { 2,3,1,7,4,6,0,5, 0x6e }, + { 2,3,4,7,1,6,0,5, 0x4e } + }; + + static const INT32 picktable[32] = { + 0,2,4,4,4,2,0,2,2,0,2,4,4,2,0,2, + 5,3,5,1,5,3,5,3,1,5,1,5,5,3,5,3 + }; + + INT32 method = picktable[(addr & 0x001) | ((addr & 0x004) >> 1) | ((addr & 0x020) >> 3) | ((addr & 0x080) >> 4) |((addr & 0x200) >> 5)]; + + if ((addr & 0x800) == 0x800) + method ^= 1; + + const UINT8 *tbl = swap_xor_table[method]; + return BITSWAP08(e,tbl[0],tbl[1],tbl[2],tbl[3],tbl[4],tbl[5],tbl[6],tbl[7]) ^ tbl[8]; +} + +static void jumpshot_decode() +{ + for (INT32 i = 0; i < 0x4000; i++) { + DrvZ80ROM[i] = jumpshot_decrypt(i, DrvZ80ROM[i]); + } +} + +static INT32 jumpshotInit() +{ + return DrvInit(StandardMap, jumpshot_decode, PACMAN); +} + +struct BurnDriver BurnDrvjumpshot = { + "jumpshot", NULL, NULL, NULL, "1985", + "Jump Shot\0", NULL, "Bally Midway", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_SPORTSMISC, 0, + NULL, jumpshotRomInfo, jumpshotRomName, NULL, NULL, jumpshotInputInfo, jumpshotDIPInfo, + jumpshotInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Jump Shot Engineering Sample + +static struct BurnRomInfo jumpshotpRomDesc[] = { + { "js6e.bin", 0x1000, 0xacc5e15e, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "js6f.bin", 0x1000, 0x62b48ba4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "js6h.bin", 0x1000, 0x7c9b5e30, 1 | BRF_ESS | BRF_PRG }, // 2 + { "js6j.bin", 0x1000, 0x9f0c39f6, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "5e", 0x1000, 0xd9fa90f5, 2 | BRF_GRA }, // 4 Graphics + { "5f", 0x1000, 0x2ec711c1, 2 | BRF_GRA }, // 5 + + { "prom.7f", 0x0020, 0x872b42f3, 3 | BRF_GRA }, // 6 Color Proms + { "prom.4a", 0x0100, 0x0399f39f, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(jumpshotp) +STD_ROM_FN(jumpshotp) + +struct BurnDriver BurnDrvjumpshotp = { + "jumpshotp", "jumpshot", NULL, NULL, "1985", + "Jump Shot Engineering Sample\0", NULL, "Bally Midway", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_SPORTSMISC, 0, + NULL, jumpshotpRomInfo, jumpshotpRomName, NULL, NULL, jumpshotInputInfo, jumpshtpDIPInfo, + jumpshotInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Shoot the Bull + +static struct BurnRomInfo shootbulRomDesc[] = { + { "sb6e.cpu", 0x1000, 0x25daa5e9, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "sb6f.cpu", 0x1000, 0x92144044, 1 | BRF_ESS | BRF_PRG }, // 1 + { "sb6h.cpu", 0x1000, 0x43b7f99d, 1 | BRF_ESS | BRF_PRG }, // 2 + { "sb6j.cpu", 0x1000, 0xbc4d3bbf, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "sb5e.cpu", 0x1000, 0x07c6c5aa, 2 | BRF_GRA }, // 4 Graphics + { "sb5f.cpu", 0x1000, 0xeaec6837, 2 | BRF_GRA }, // 5 + + { "7f.rom", 0x0020, 0xec578b98, 3 | BRF_GRA }, // 6 Color Proms + { "4a.rom", 0x0100, 0x81a6b30f, 3 | BRF_GRA }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(shootbul) +STD_ROM_FN(shootbul) + +static INT32 shootbulInit() +{ + return DrvInit(StandardMap, jumpshot_decode, SHOOTBUL); +} + +struct BurnDriverD BurnDrvshootbul = { + "shootbul", NULL, NULL, NULL, "1985", + "Shoot the Bull\0", "Analog inputs not hooked up", "Bally Midway", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_SPORTSMISC, 0, + NULL, shootbulRomInfo, shootbulRomName, NULL, NULL, shootbulInputInfo, shootbulDIPInfo, + shootbulInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Cannon Ball (Pacman Hardware) + +static struct BurnRomInfo cannonbpRomDesc[] = { + { "n1-6e", 0x0800, 0xc68878c7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "n2-6k", 0x0800, 0xff3951a5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "n3-6f", 0x0800, 0x2329079d, 1 | BRF_ESS | BRF_PRG }, // 2 + { "n4-6m", 0x0800, 0xfcc57ecb, 1 | BRF_ESS | BRF_PRG }, // 3 + { "n5-6h", 0x0800, 0x52846c9d, 1 | BRF_ESS | BRF_PRG }, // 4 + { "n6-6n", 0x0800, 0x59e890dd, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "z1-5e", 0x0800, 0x125779e0, 2 | BRF_GRA }, // 6 Graphics + { "z3-5h", 0x0800, 0x78f866c0, 2 | BRF_GRA }, // 7 + { "z2-5f", 0x0800, 0xfbd2c99d, 2 | BRF_GRA }, // 8 + { "z4-5j", 0x0800, 0x8734c904, 2 | BRF_GRA }, // 9 + + { "colorprom_1", 0x0020, 0x08f8ae7e, 3 | BRF_GRA }, // 10 Color Proms + { "colorprom_2", 0x0100, 0x359a15dc, 3 | BRF_GRA }, // 11 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 12 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom (not used) +}; + +STD_ROM_PICK(cannonbp) +STD_ROM_FN(cannonbp) + +static INT32 cannonbpInit() +{ + return DrvInit(CannonbpMap, NULL, CANNONBP); +} + +struct BurnDriver BurnDrvcannonbp = { + "cannonbp", NULL, NULL, NULL, "198?", + "Cannon Ball (Pacman Hardware)\0", "wrong colors", "Novomatic", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_BREAKOUT, 0, + NULL, cannonbpRomInfo, cannonbpRomName, NULL, NULL, cannonbpInputInfo, cannonbpDIPInfo, + cannonbpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Woodpecker (set 1) + +static struct BurnRomInfo woodpeckRomDesc[] = { + { "f.bin", 0x1000, 0x37ea66ca, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "i.bin", 0x1000, 0xcd115dba, 1 | BRF_ESS | BRF_PRG }, // 1 + { "e.bin", 0x1000, 0xd40b2321, 1 | BRF_ESS | BRF_PRG }, // 2 + { "g.bin", 0x1000, 0x024092f4, 1 | BRF_ESS | BRF_PRG }, // 3 + { "h.bin", 0x1000, 0x18ef0fc8, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "a.5e", 0x0800, 0x15a87f62, 2 | BRF_GRA }, // 5 Graphics + { "c.5h", 0x0800, 0xab4abd88, 2 | BRF_GRA }, // 6 + { "b.5f", 0x0800, 0x5b9ba95b, 2 | BRF_GRA }, // 7 + { "d.5j", 0x0800, 0xd7b80a45, 2 | BRF_GRA }, // 8 + + { "pr.8h", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 9 Color Prom + { "pr.4a", 0x0100, 0xd8772167, 3 | BRF_GRA }, // 10 + + { "pr.1k", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 11 Sound Prom + { "pr.3k", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 12 Timing Prom (not used) +}; + +STD_ROM_PICK(woodpeck) +STD_ROM_FN(woodpeck) + +static void woodpeckCallback() +{ + memcpy (DrvZ80ROM + 0xb000, DrvZ80ROM + 0x8000, 0x1000); + memcpy (DrvZ80ROM + 0x8000, DrvZ80ROM + 0x1000, 0x3000); + + memset (DrvZ80ROM + 0x1000, 0, 0x3000); + + for (INT32 i = 0; i < 0x2000; i += 8) + eyes_gfx_decode(DrvGfxROM + i); +} + +static INT32 woodpeckInit() +{ + return DrvInit(WoodpekMap, woodpeckCallback, PACMAN); +} + +struct BurnDriver BurnDrvwoodpeck = { + "woodpeck", NULL, NULL, NULL, "1981", + "Woodpecker (set 1)\0", NULL, "Amenip (Palcom Queen River)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, woodpeckRomInfo, woodpeckRomName, NULL, NULL, woodpekInputInfo, woodpekDIPInfo, + woodpeckInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Woodpecker (set 2) + +static struct BurnRomInfo woodpekaRomDesc[] = { + { "0", 0x1000, 0xb5ee8bca, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "1", 0x1000, 0xc5ec2de6, 1 | BRF_PRG | BRF_ESS }, // 1 + { "2", 0x1000, 0x07ea534e, 1 | BRF_PRG | BRF_ESS }, // 2 + { "3", 0x1000, 0xa3a3253a, 1 | BRF_PRG | BRF_ESS }, // 3 + { "4", 0x1000, 0x6c50546b, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "10.5f", 0x1000, 0x0bf52102, 2 | BRF_GRA }, // 5 Graphics + { "11.5h", 0x1000, 0x0ed8def8, 2 | BRF_GRA }, // 6 + + { "pr.8h", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 7 Color Proms + { "pr.4a", 0x0100, 0xd8772167, 3 | BRF_GRA }, // 8 + + { "pr.1k", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 9 + { "pr.3k", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 10 Timing Prom (not used) +}; + +STD_ROM_PICK(woodpeka) +STD_ROM_FN(woodpeka) + +struct BurnDriver BurnDrvwoodpeka = { + "woodpeca", "woodpeck", NULL, NULL, "1981", + "Woodpecker (set 2)\0", NULL, "Amenip (Palcom Queen River)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, woodpekaRomInfo, woodpekaRomName, NULL, NULL, woodpekInputInfo, woodpekDIPInfo, + woodpeckInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Lizard Wizard + +static struct BurnRomInfo lizwizRomDesc[] = { + { "6e.cpu", 0x1000, 0x32bc1990, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6f.cpu", 0x1000, 0xef24b414, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6h.cpu", 0x1000, 0x30bed83d, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6j.cpu", 0x1000, 0xdd09baeb, 1 | BRF_ESS | BRF_PRG }, // 3 + { "wiza", 0x1000, 0xf6dea3a6, 1 | BRF_ESS | BRF_PRG }, // 4 + { "wizb", 0x1000, 0xf27fb5a8, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e.cpu", 0x1000, 0x45059e73, 2 | BRF_GRA }, // 6 Graphics + { "5f.cpu", 0x1000, 0xd2469717, 2 | BRF_GRA }, // 7 + + { "7f.cpu", 0x0020, 0x7549a947, 3 | BRF_GRA }, // 8 Color Proms + { "4a.cpu", 0x0100, 0x5fdca536, 3 | BRF_GRA }, // 9 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 10 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom (not used) +}; + +STD_ROM_PICK(lizwiz) +STD_ROM_FN(lizwiz) + +static INT32 lizwizInit() +{ + return DrvInit(WoodpekMap, NULL, PACMAN); +} + +struct BurnDriver BurnDrvlizwiz = { + "lizwiz", NULL, NULL, NULL, "1985", + "Lizard Wizard\0", NULL, "Techstar (Sunn license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_SHOOT, 0, + NULL, lizwizRomInfo, lizwizRomName, NULL, NULL, lizwizInputInfo, lizwizDIPInfo, + lizwizInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ponpoko + +static struct BurnRomInfo ponpokoRomDesc[] = { + { "ppokoj1.bin", 0x1000, 0xffa3c004, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ppokoj2.bin", 0x1000, 0x4a496866, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ppokoj3.bin", 0x1000, 0x17da6ca3, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ppokoj4.bin", 0x1000, 0x9d39a565, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ppoko5.bin", 0x1000, 0x54ca3d7d, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ppoko6.bin", 0x1000, 0x3055c7e0, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ppoko7.bin", 0x1000, 0x3cbe47ca, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ppokoj8.bin", 0x1000, 0x04b63fc6, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ppoko9.bin", 0x1000, 0xb73e1a06, 2 | BRF_GRA }, // 8 Graphics + { "ppoko10.bin", 0x1000, 0x62069b5d, 2 | BRF_GRA }, // 9 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 10 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 11 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 12 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom (not used) +}; + +STD_ROM_PICK(ponpoko) +STD_ROM_FN(ponpoko) + +static void ponpoko_decode() +{ + for (INT32 i = 0; i < 0x1000; i += 0x10) // Characters + { + for (INT32 j = 0; j < 8; j++) + { + INT32 t = DrvGfxROM[i+j+0x08]; + DrvGfxROM[i+j+0x08] = DrvGfxROM[i+j+0x00]; + DrvGfxROM[i+j+0x00] = t; + } + } + + for (INT32 i = 0x1000; i < 0x2000; i += 0x20) // Sprites + { + for (INT32 j = 0; j < 8; j++) + { + INT32 t = DrvGfxROM[i+j+0x18]; + DrvGfxROM[i+j+0x18] = DrvGfxROM[i+j+0x10]; + DrvGfxROM[i+j+0x10] = DrvGfxROM[i+j+0x08]; + DrvGfxROM[i+j+0x08] = DrvGfxROM[i+j+0x00]; + DrvGfxROM[i+j+0x00] = t; + } + } +} + +static INT32 ponpokoInit() +{ + return DrvInit(WoodpekMap, ponpoko_decode, PACMAN); +} + +struct BurnDriver BurnDrvponpoko = { + "ponpoko", NULL, NULL, NULL, "1982", + "Ponpoko\0", NULL, "Sigma Enterprises Inc.", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, ponpokoRomInfo, ponpokoRomName, NULL, NULL, ponpokoInputInfo, ponpokoDIPInfo, + ponpokoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// Ponpoko (Venture Line) + +static struct BurnRomInfo ponpokovRomDesc[] = { + { "ppoko1.bin", 0x1000, 0x49077667, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ppoko2.bin", 0x1000, 0x5101781a, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ppoko3.bin", 0x1000, 0xd790ed22, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ppoko4.bin", 0x1000, 0x4e449069, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ppoko5.bin", 0x1000, 0x54ca3d7d, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ppoko6.bin", 0x1000, 0x3055c7e0, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ppoko7.bin", 0x1000, 0x3cbe47ca, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ppoko8.bin", 0x1000, 0xb39be27d, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ppoko9.bin", 0x1000, 0xb73e1a06, 2 | BRF_GRA }, // 8 Graphics + { "ppoko10.bin", 0x1000, 0x62069b5d, 2 | BRF_GRA }, // 9 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 10 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 11 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 12 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom (not used) +}; + +STD_ROM_PICK(ponpokov) +STD_ROM_FN(ponpokov) + +struct BurnDriver BurnDrvponpokov = { + "ponpokov", "ponpoko", NULL, NULL, "1982", + "Ponpoko (Venture Line)\0", NULL, "Sigma Enterprises Inc. (Venture Line license)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, ponpokovRomInfo, ponpokovRomName, NULL, NULL, ponpokoInputInfo, ponpokoDIPInfo, + ponpokoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 288, 224, 4, 3 +}; + + +// The Glob (Pac-Man hardware) + +static struct BurnRomInfo theglobpRomDesc[] = { + { "glob.u2", 0x2000, 0x829d0bea, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "glob.u3", 0x2000, 0x31de6628, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "glob.5e", 0x1000, 0x53688260, 2 | BRF_GRA }, // 2 Graphics + { "glob.5f", 0x1000, 0x051f59c7, 2 | BRF_GRA }, // 3 + + { "glob.7f", 0x0020, 0x1f617527, 3 | BRF_GRA }, // 4 Color Proms + { "glob.4a", 0x0100, 0x28faa769, 3 | BRF_GRA }, // 5 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 6 Sound Prom + { "82s126.3m" , 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 7 Timing Prom (not used) +}; + +STD_ROM_PICK(theglobp) +STD_ROM_FN(theglobp) + +static void theglobp_decrypt() +{ + for (INT32 i = 0; i < 0x4000; i++) { + DrvZ80ROM[0x10000 + i] = BITSWAP08(DrvZ80ROM[i] ^ 0xfc, 3, 7, 0, 6, 4, 1, 2, 5); + DrvZ80ROM[0x14000 + i] = BITSWAP08(DrvZ80ROM[i] ^ 0xf6, 1, 7, 0, 3, 4, 6, 2, 5); + DrvZ80ROM[0x18000 + i] = BITSWAP08(DrvZ80ROM[i] ^ 0x7d, 3, 0, 4, 6, 7, 1, 2, 5); + DrvZ80ROM[0x1c000 + i] = BITSWAP08(DrvZ80ROM[i] ^ 0x77, 1, 0, 4, 3, 7, 6, 2, 5); + } +} + +static INT32 theglobpInit() +{ + return DrvInit(StandardMap, theglobp_decrypt, EPOS); +} + +struct BurnDriver BurnDrvtheglobp = { + "theglobp", "suprglob", NULL, NULL, "1983", + "The Glob (Pac-Man hardware)\0", NULL, "Epos Corporation", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, theglobpRomInfo, theglobpRomName, NULL, NULL, theglobpInputInfo, theglobpDIPInfo, + theglobpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Super Glob (Pac-Man hardware) + +static struct BurnRomInfo sprglobpRomDesc[] = { + { "glob.u2", 0x2000, 0x829d0bea, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "glob.u3", 0x2000, 0x31de6628, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5e_2532.dat", 0x1000, 0x1aa16109, 2 | BRF_GRA }, // 2 Graphics + { "5f_2532.dat", 0x1000, 0xafe72a89, 2 | BRF_GRA }, // 3 + + { "glob.7f", 0x0020, 0x1f617527, 3 | BRF_GRA }, // 4 Color Prom + { "glob.4a", 0x0100, 0x28faa769, 3 | BRF_GRA }, // 5 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 6 Sound Prom + { "82s126.3m" , 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 7 Timing Prom (not used) +}; + +STD_ROM_PICK(sprglobp) +STD_ROM_FN(sprglobp) + +struct BurnDriver BurnDrvsprglobp = { + "sprglobp", "suprglob", NULL, NULL, "1983", + "Super Glob (Pac-Man hardware)\0", NULL, "Epos Corporation", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, sprglobpRomInfo, sprglobpRomName, NULL, NULL, theglobpInputInfo, theglobpDIPInfo, + theglobpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Super Glob (Pac-Man hardware) German + +static struct BurnRomInfo sprglbpgRomDesc[] = { + { "ic8.1", 0x1000, 0xa2df2073, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic7.2", 0x1000, 0x3d2c22d9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ic15.3", 0x1000, 0xa252047f, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ic14.4", 0x1000, 0x7efa81f1, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "ic92.5", 0x2000, 0xE54F484D, 2 | BRF_GRA }, // 4 Graphics + + { "ic78.prm", 0x0020, 0x1f617527, 3 | BRF_GRA }, // 5 Color Prom + { "ic88.prm", 0x0100, 0x28faa769, 3 | BRF_GRA }, // 6 + + { "ic51.prm", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 7 Sound Prom + { "ic70.prm" , 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 8 Timing Prom (not used) +}; + +STD_ROM_PICK(sprglbpg) +STD_ROM_FN(sprglbpg) + +struct BurnDriver BurnDrvsprglbpg = { + "sprglbpg", "suprglob", NULL, NULL, "1983", + "Super Glob (Pac-Man hardware) German\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, sprglbpgRomInfo, sprglbpgRomName, NULL, NULL, theglobpInputInfo, theglobpDIPInfo, + puckmanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Beastie Feastie + +static struct BurnRomInfo beastfRomDesc[] = { + { "bf-u2.bin", 0x2000, 0x3afc517b, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "bf-u3.bin", 0x2000, 0x8dbd76d0, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "beastf.5e", 0x1000, 0x5654dc34, 2 | BRF_GRA }, // 2 Graphics + { "beastf.5f", 0x1000, 0x1b30ca61, 2 | BRF_GRA }, // 3 + + { "glob.7f", 0x0020, 0x1f617527, 3 | BRF_GRA }, // 4 Color Proms + { "glob.4a", 0x0100, 0x28faa769, 3 | BRF_GRA }, // 5 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 6 Sound Prom + { "82s126.3m" , 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 7 Timing Prom (not used) +}; + +STD_ROM_PICK(beastf) +STD_ROM_FN(beastf) + +struct BurnDriver BurnDrvbeastf = { + "beastf", "suprglob", NULL, NULL, "1984", + "Beastie Feastie\0", NULL, "Epos Corporation", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, beastfRomInfo, beastfRomName, NULL, NULL, theglobpInputInfo, theglobpDIPInfo, + theglobpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Van-Van Car + +static struct BurnRomInfo vanvanRomDesc[] = { + { "van-1.50", 0x1000, 0xcf1b2df0, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "van-2.51", 0x1000, 0xdf58e1cb, 1 | BRF_ESS | BRF_PRG }, // 1 + { "van-3.52", 0x1000, 0x15571e24, 1 | BRF_ESS | BRF_PRG }, // 2 + { "van-4.53", 0x1000, 0xb724cbe0, 1 | BRF_ESS | BRF_PRG }, // 3 + { "van-5.39", 0x1000, 0xdb67414c, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "van-20.18", 0x1000, 0x60efbe66, 2 | BRF_GRA }, // 5 Graphics + { "van-21.19", 0x1000, 0x5dd53723, 2 | BRF_GRA }, // 6 + + { "6331-1.6", 0x0020, 0xce1d9503, 3 | BRF_GRA }, // 7 Color Proms + { "6301-1.37", 0x0100, 0x4b803d9f, 3 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(vanvan) +STD_ROM_FN(vanvan) + +static void vanvanCallback() +{ + memcpy (DrvZ80ROM + 0x9000, DrvZ80ROM + 0x8000, 0x1000); + memcpy (DrvZ80ROM + 0xa000, DrvZ80ROM + 0x8000, 0x1000); + memcpy (DrvZ80ROM + 0xb000, DrvZ80ROM + 0x8000, 0x1000); +} + +static INT32 vanvanInit() +{ + return DrvInit(DremshprMap, vanvanCallback, VANVAN); +} + +struct BurnDriver BurnDrvvanvan = { + "vanvan", NULL, NULL, NULL, "1983", + "Van-Van Car\0", NULL, "Sanritsu", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, vanvanRomInfo, vanvanRomName, NULL, NULL, vanvanInputInfo, vanvanDIPInfo, + vanvanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Van-Van Car (Karateco) + +static struct BurnRomInfo vanvankRomDesc[] = { + { "van1.bin", 0x1000, 0x00f48295, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "van-2.51", 0x1000, 0xdf58e1cb, 1 | BRF_ESS | BRF_PRG }, // 1 + { "van-3.52", 0x1000, 0x15571e24, 1 | BRF_ESS | BRF_PRG }, // 2 + { "van4.bin", 0x1000, 0xf8b37ed5, 1 | BRF_ESS | BRF_PRG }, // 3 + { "van5.bin", 0x1000, 0xb8c1e089, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "van-20.18", 0x1000, 0x60efbe66, 2 | BRF_GRA }, // 5 Graphics + { "van-21.19", 0x1000, 0x5dd53723, 2 | BRF_GRA }, // 6 + + { "6331-1.6", 0x0020, 0xce1d9503, 3 | BRF_GRA }, // 7 Color Proms + { "6301-1.37", 0x0100, 0x4b803d9f, 3 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(vanvank) +STD_ROM_FN(vanvank) + +struct BurnDriver BurnDrvvanvank = { + "vanvank", "vanvan", NULL, NULL, "1983", + "Van-Van Car (Karateco)\0", NULL, "Karateco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, vanvankRomInfo, vanvankRomName, NULL, NULL, vanvankInputInfo, vanvanDIPInfo, + vanvanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Van-Van Car (set 3) + +static struct BurnRomInfo vanvanbRomDesc[] = { + { "vv1.bin", 0x1000, 0xcf1b2df0, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "vv2.bin", 0x1000, 0x80eca6a5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "vv3.bin", 0x1000, 0x15571e24, 1 | BRF_ESS | BRF_PRG }, // 2 + { "vv4.bin", 0x1000, 0xb1f04006, 1 | BRF_ESS | BRF_PRG }, // 3 + { "vv5.bin", 0x1000, 0xdb67414c, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "vv20.bin", 0x1000, 0xeb56cb51, 2 | BRF_GRA }, // 5 Graphics + { "vv21.bin", 0x1000, 0x5dd53723, 2 | BRF_GRA }, // 6 + + { "6331-1.6", 0x0020, 0xce1d9503, 3 | BRF_GRA }, // 7 Color Proms + { "6301-1.37", 0x0100, 0x4b803d9f, 3 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(vanvanb) +STD_ROM_FN(vanvanb) + +struct BurnDriver BurnDrvvanvanb = { + "vanvanb", "vanvan", NULL, NULL, "1983", + "Van-Van Car (set 3)\0", NULL, "Karateco", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, vanvanbRomInfo, vanvanbRomName, NULL, NULL, vanvankInputInfo, vanvanDIPInfo, + vanvanInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Naughty Mouse (set 1) + +static struct BurnRomInfo nmouseRomDesc[] = { + { "naumouse.d7", 0x0800, 0xe447ecfa, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "naumouse.d6", 0x0800, 0x2e6f13d9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "naumouse.e7", 0x0800, 0x44a80f97, 1 | BRF_ESS | BRF_PRG }, // 2 + { "naumouse.e6", 0x0800, 0x9c7a46bd, 1 | BRF_ESS | BRF_PRG }, // 3 + { "naumouse.h7", 0x0800, 0x5bc94c5d, 1 | BRF_ESS | BRF_PRG }, // 4 + { "naumouse.h6", 0x0800, 0x1af29e22, 1 | BRF_ESS | BRF_PRG }, // 5 + { "naumouse.j7", 0x0800, 0xcc3be185, 1 | BRF_ESS | BRF_PRG }, // 6 + { "naumouse.j6", 0x0800, 0x66b3e5dc, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "naumouse.d5", 0x0800, 0x2ea7cc3f, 2 | BRF_GRA }, // 8 Graphics + { "naumouse.h5", 0x0800, 0x0511fcea, 2 | BRF_GRA }, // 9 + { "naumouse.e5", 0x0800, 0xf5a627cd, 2 | BRF_GRA }, // 10 + { "naumouse.j5", 0x0800, 0x65f2580e, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "naumouse.a4", 0x0100, 0xd8772167, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(nmouse) +STD_ROM_FN(nmouse) + +static INT32 nmouseInit() +{ + return DrvInit(StandardMap, eyes_decode, NMOUSE); +} + +struct BurnDriver BurnDrvnmouse = { + "nmouse", NULL, NULL, NULL, "1981", + "Naughty Mouse (set 1)\0", NULL, "Amenip (Palcom Queen River)", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, nmouseRomInfo, nmouseRomName, NULL, NULL, DrvInputInfo, nmouseDIPInfo, + nmouseInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Naughty Mouse (set 2) + +static struct BurnRomInfo nmousebRomDesc[] = { + { "naumouse.d7", 0x0800, 0xe447ecfa, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "naumouse.d6", 0x0800, 0x2e6f13d9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "naumouse.e7", 0x0800, 0x44a80f97, 1 | BRF_ESS | BRF_PRG }, // 2 + { "naumouse.e6", 0x0800, 0x9c7a46bd, 1 | BRF_ESS | BRF_PRG }, // 3 + { "snatch2.bin", 0x0800, 0x405aa389, 1 | BRF_ESS | BRF_PRG }, // 4 + { "snatch6.bin", 0x0800, 0xf58e7df4, 1 | BRF_ESS | BRF_PRG }, // 5 + { "snatch3.bin", 0x0800, 0x06fb18ec, 1 | BRF_ESS | BRF_PRG }, // 6 + { "snatch7.bin", 0x0800, 0xd187b82b, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "naumouse.d5", 0x0800, 0x2ea7cc3f, 2 | BRF_GRA }, // 8 Graphics + { "naumouse.h5", 0x0800, 0x0511fcea, 2 | BRF_GRA }, // 9 + { "naumouse.e5", 0x0800, 0xf5a627cd, 2 | BRF_GRA }, // 10 + { "snatch11.bin", 0x0800, 0x330230a5, 2 | BRF_GRA }, // 11 + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 12 Color Proms + { "naumouse.a4", 0x0100, 0xd8772167, 3 | BRF_GRA }, // 13 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 14 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 15 Timing Prom (not used) +}; + +STD_ROM_PICK(nmouseb) +STD_ROM_FN(nmouseb) + +struct BurnDriver BurnDrvnmouseb = { + "nmouseb", "nmouse", NULL, NULL, "1981", + "Naughty Mouse (set 2)\0", NULL, "Amenip Nova Games Ltd.", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_PLATFORM, 0, + NULL, nmousebRomInfo, nmousebRomName, NULL, NULL, DrvInputInfo, nmouseDIPInfo, + nmouseInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Dream Shopper + +static struct BurnRomInfo dremshprRomDesc[] = { + { "red_1.50", 0x1000, 0x830c6361, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "red_2.51", 0x1000, 0xd22551cc, 1 | BRF_ESS | BRF_PRG }, // 1 + { "red_3.52", 0x1000, 0x0713a34a, 1 | BRF_ESS | BRF_PRG }, // 2 + { "red_4.53", 0x1000, 0xf38bcaaa, 1 | BRF_ESS | BRF_PRG }, // 3 + { "red_5.39", 0x1000, 0x6a382267, 1 | BRF_ESS | BRF_PRG }, // 4 + { "red_6.40", 0x1000, 0x4cf8b121, 1 | BRF_ESS | BRF_PRG }, // 5 + { "red_7.41", 0x1000, 0xbd4fc4ba, 1 | BRF_ESS | BRF_PRG }, // 6 + + { "red-20.18", 0x1000, 0x2d6698dc, 2 | BRF_GRA }, // 7 Graphics + { "red-21.19", 0x1000, 0x38c9ce9b, 2 | BRF_GRA }, // 8 + + { "6331-1.6", 0x0020, 0xce1d9503, 3 | BRF_GRA }, // 9 Color Proms + { "6301-1.37", 0x0100, 0x39d6fb5c, 3 | BRF_GRA }, // 10 + + // Uses AY8910 +}; + +STD_ROM_PICK(dremshpr) +STD_ROM_FN(dremshpr) + +static INT32 dremshprInit() +{ + return DrvInit(DremshprMap, NULL, DREMSHPR); +} + +struct BurnDriver BurnDrvdremshpr = { + "dremshpr", NULL, NULL, NULL, "1982", + "Dream Shopper\0", NULL, "Sanritsu", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_PUZZLE, 0, + NULL, dremshprRomInfo, dremshprRomName, NULL, NULL, dremshprInputInfo, dremshprDIPInfo, + dremshprInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Boardwalk Casino + +static struct BurnRomInfo bwcasinoRomDesc[] = { + { "bwc_u2.bin", 0x2000, 0xe2eea868, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "bwc_u3.bin", 0x2000, 0xa935571e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "bwc_5e.bin", 0x1000, 0xe334c01e, 2 | BRF_GRA }, // 2 Graphics + + { "aca_7f.bin", 0x0020, 0x133bb744, 3 | BRF_GRA }, // 3 Color Proms + { "aca_4a.bin", 0x0100, 0x8e29208f, 3 | BRF_GRA }, // 4 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 5 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 6 Timing Prom (not used) +}; + +STD_ROM_PICK(bwcasino) +STD_ROM_FN(bwcasino) + +static void acitya_decode() +{ + for (INT32 i = 0; i < 0x4000; i++) { + DrvZ80ROM[i + 0x10000] = BITSWAP08(DrvZ80ROM[i] ^ 0xb5, 1, 6, 7, 3, 4, 0, 2, 5); + DrvZ80ROM[i + 0x14000] = BITSWAP08(DrvZ80ROM[i] ^ 0xa7, 7, 6, 1, 3, 4, 0, 2, 5); + DrvZ80ROM[i + 0x18000] = BITSWAP08(DrvZ80ROM[i] ^ 0xfc, 1, 0, 7, 6, 4, 3, 2, 5); + DrvZ80ROM[i + 0x1c000] = BITSWAP08(DrvZ80ROM[i] ^ 0xee, 7, 0, 1, 6, 4, 3, 2, 5); + } +} + +static INT32 acityaInit() +{ + acitya = 1; + + return DrvInit(StandardMap, acitya_decode, EPOS); +} + +struct BurnDriver BurnDrvbwcasino = { + "bwcasino", NULL, NULL, NULL, "1983", + "Boardwalk Casino\0", NULL, "EPOS Corporation", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_CASINO, 0, + NULL, bwcasinoRomInfo, bwcasinoRomName, NULL, NULL, bwcasinoInputInfo, bwcasinoDIPInfo, + acityaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Atlantic City Action + +static struct BurnRomInfo acityaRomDesc[] = { + { "aca_u2.bin", 0x2000, 0x261c2fdc, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "aca_u3.bin", 0x2000, 0x05fab4ca, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "aca_5e.bin", 0x1000, 0x7f2dd2c9, 2 | BRF_GRA }, // 2 Graphics + + { "aca_7f.bin", 0x0020, 0x133bb744, 3 | BRF_GRA }, // 3 Color Proms + { "aca_4a.bin", 0x0100, 0x8e29208f, 3 | BRF_GRA }, // 4 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 5 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 6 Timing Prom (not used) +}; + +STD_ROM_PICK(acitya) +STD_ROM_FN(acitya) + +struct BurnDriver BurnDrvacitya = { + "acitya", "bwcasino", NULL, NULL, "1983", + "Atlantic City Action\0", NULL, "EPOS Corporation", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_CASINO, 0, + NULL, acityaRomInfo, acityaRomName, NULL, NULL, acityaInputInfo, acityaDIPInfo, + acityaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Big Bucks + +static struct BurnRomInfo bigbucksRomDesc[] = { + { "p.rom", 0x4000, 0xeea6c1c9, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "m.rom", 0x2000, 0xbb8f7363, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5e.cpu", 0x1000, 0x18442c37, 2 | BRF_GRA }, // 2 Graphics + + { "82s123.7f", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 3 Color Proms + { "82s126.4a", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 4 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 5 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 6 Timing Prom + + { "rom1.rom", 0x8000, 0x90b7785f, 7 | BRF_PRG | BRF_ESS }, // 7 Question Roms + { "rom2.rom", 0x8000, 0x60172d77, 7 | BRF_PRG | BRF_ESS }, // 8 + { "rom3.rom", 0x8000, 0xa2207320, 7 | BRF_PRG | BRF_ESS }, // 9 + { "rom4.rom", 0x8000, 0x5a74c1f9, 7 | BRF_PRG | BRF_ESS }, // 10 + { "rom5.rom", 0x8000, 0x93bc1080, 7 | BRF_PRG | BRF_ESS }, // 11 + { "rom6.rom", 0x8000, 0xeea2423f, 7 | BRF_PRG | BRF_ESS }, // 12 + { "rom7.rom", 0x8000, 0x96694055, 7 | BRF_PRG | BRF_ESS }, // 13 + { "rom8.rom", 0x8000, 0xe68ebf8e, 7 | BRF_PRG | BRF_ESS }, // 14 + { "rom9.rom", 0x8000, 0xfd20921d, 7 | BRF_PRG | BRF_ESS }, // 15 + { "rom10.rom", 0x8000, 0x5091b951, 7 | BRF_PRG | BRF_ESS }, // 16 + { "rom11.rom", 0x8000, 0x705128db, 7 | BRF_PRG | BRF_ESS }, // 17 + { "rom12.rom", 0x8000, 0x74c776e7, 7 | BRF_PRG | BRF_ESS }, // 18 +}; + +STD_ROM_PICK(bigbucks) +STD_ROM_FN(bigbucks) + +static INT32 bigbucksInit() +{ + return DrvInit(BigbucksMap, NULL, BIGBUCKS); +} + +struct BurnDriver BurnDrvbigbucks = { + "bigbucks", NULL, NULL, NULL, "1986", + "Big Bucks\0", NULL, "Dynasoft Inc.", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_QUIZ, 0, + NULL, bigbucksRomInfo, bigbucksRomName, NULL, NULL, bigbucksInputInfo, bigbucksDIPInfo, + bigbucksInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// MTV Rock-N-Roll Trivia (Part 2) + +static struct BurnRomInfo rocktrv2RomDesc[] = { + { "1.aux", 0x4000, 0xd182947b, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2.aux", 0x2000, 0x27a7461d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5e.cpu", 0x1000, 0x0a6cc43b, 2 | BRF_GRA }, // 2 Graphics + + { "7f.cpu", 0x0020, 0x7549a947, 3 | BRF_GRA }, // 3 Color Proms + { "4a.cpu", 0x0100, 0xddd5d88e, 3 | BRF_GRA }, // 4 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 5 Sound Prom + { "82s126.3m" , 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 6 Timing Prom (not used) + + { "3.aux", 0x4000, 0x5b117ca6, 7 | BRF_PRG | BRF_ESS }, // 7 Question Roms + { "4.aux", 0x4000, 0x81bfd4c3, 7 | BRF_PRG | BRF_ESS }, // 8 + { "5.aux", 0x4000, 0xe976423c, 7 | BRF_PRG | BRF_ESS }, // 9 + { "6.aux", 0x4000, 0x425946bf, 7 | BRF_PRG | BRF_ESS }, // 10 + { "7.aux", 0x4000, 0x7056fc8f, 7 | BRF_PRG | BRF_ESS }, // 11 + { "8.aux", 0x4000, 0x8b86464f, 7 | BRF_PRG | BRF_ESS }, // 12 + { "9.aux", 0x4000, 0x17d8eba4, 7 | BRF_PRG | BRF_ESS }, // 13 + { "10.aux", 0x4000, 0x398c8eb4, 7 | BRF_PRG | BRF_ESS }, // 14 + { "11.aux", 0x4000, 0x7f376424, 7 | BRF_PRG | BRF_ESS }, // 15 + { "12.aux", 0x4000, 0x8d5bbf81, 7 | BRF_PRG | BRF_ESS }, // 16 + { "13.aux", 0x4000, 0x99fe2c21, 7 | BRF_PRG | BRF_ESS }, // 17 + { "14.aux", 0x4000, 0xdf4cf5e7, 7 | BRF_PRG | BRF_ESS }, // 18 + { "15.aux", 0x4000, 0x2a32de26, 7 | BRF_PRG | BRF_ESS }, // 19 + { "16.aux", 0x4000, 0xfcd42187, 7 | BRF_PRG | BRF_ESS }, // 20 + { "17.aux", 0x4000, 0x24d5c388, 7 | BRF_PRG | BRF_ESS }, // 21 + { "18.aux", 0x4000, 0xfeb195fd, 7 | BRF_PRG | BRF_ESS }, // 22 +}; + +STD_ROM_PICK(rocktrv2) +STD_ROM_FN(rocktrv2) + +static void rocktrv2Callback() +{ + DrvZ80ROM[0x9ffe] = 0xa7; + DrvZ80ROM[0x9fee] = 0x6d; +} + +static INT32 rocktrv2Init() +{ + return DrvInit(Rocktrv2Map, rocktrv2Callback, ROCKTRV2); +} + +struct BurnDriver BurnDrvrocktrv2 = { + "rocktrv2", NULL, NULL, NULL, "1986", + "MTV Rock-N-Roll Trivia (Part 2)\0", NULL, "Triumph Software Inc.", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_QUIZ, 0, + NULL, rocktrv2RomInfo, rocktrv2RomName, NULL, NULL, rocktrv2InputInfo, rocktrv2DIPInfo, + rocktrv2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Ali Baba and 40 Thieves + +static struct BurnRomInfo alibabaRomDesc[] = { + { "6e", 0x1000, 0x38d701aa, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6f", 0x1000, 0x3d0e35f3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6h", 0x1000, 0x823bee89, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6k", 0x1000, 0x474d032f, 1 | BRF_ESS | BRF_PRG }, // 3 + { "6l", 0x1000, 0x5ab315c1, 1 | BRF_ESS | BRF_PRG }, // 4 + { "6m", 0x0800, 0x438d0357, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x0800, 0x85bcb8f8, 2 | BRF_GRA }, // 6 Graphics + { "5h", 0x0800, 0x38e50862, 2 | BRF_GRA }, // 7 + { "5f", 0x0800, 0xb5715c86, 2 | BRF_GRA }, // 8 + { "5k", 0x0800, 0x713086b3, 2 | BRF_GRA }, // 9 + + { "82s123.e7", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 10 Color Proms + { "82s129.a4", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 11 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 12 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom + + { "ab7.bin", 0x0800, 0x52294ef5, 0 | BRF_OPT }, // 14 Mystery Rom? (1st & 2nd halves identical) +}; + +STD_ROM_PICK(alibaba) +STD_ROM_FN(alibaba) + +static void alibabaCallback() +{ + memcpy (DrvZ80ROM + 0xa000, DrvZ80ROM + 0x9000, 0x0800); + memset (DrvZ80ROM + 0x9000, 0, 0x800); +} + +static INT32 alibabaInit() +{ + return DrvInit(AlibabaMap, alibabaCallback, ALIBABA); +} + +struct BurnDriver BurnDrvalibaba = { + "alibaba", NULL, NULL, NULL, "1982", + "Ali Baba and 40 Thieves\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, alibabaRomInfo, alibabaRomName, NULL, NULL, alibabaInputInfo, alibabaDIPInfo, + alibabaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Mustafa and 40 Thieves (bootleg) + +static struct BurnRomInfo alibababRomDesc[] = { + { "6e", 0x1000, 0x38d701aa, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "6f", 0x1000, 0x3d0e35f3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "6h", 0x1000, 0x823bee89, 1 | BRF_ESS | BRF_PRG }, // 2 + { "6k", 0x1000, 0x474d032f, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ab5.bin", 0x1000, 0xae2f4aac, 1 | BRF_ESS | BRF_PRG }, // 4 + { "6m", 0x0800, 0x438d0357, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5e", 0x0800, 0x85bcb8f8, 2 | BRF_GRA }, // 6 Graphics + { "5h", 0x0800, 0x38e50862, 2 | BRF_GRA }, // 7 + { "5f", 0x0800, 0xb5715c86, 2 | BRF_GRA }, // 8 + { "5k", 0x0800, 0x713086b3, 2 | BRF_GRA }, // 9 + + { "82s123.e7", 0x0020, 0x2fc650bd, 3 | BRF_GRA }, // 10 Color Proms + { "82s129.a4", 0x0100, 0x3eb3a8e4, 3 | BRF_GRA }, // 11 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 12 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom + + { "ab7.bin", 0x0800, 0x52294ef5, 0 | BRF_OPT }, // 14 Mystery Rom? (1st & 2nd halves identical) +}; + +STD_ROM_PICK(alibabab) +STD_ROM_FN(alibabab) + +struct BurnDriver BurnDrvalibabab = { + "alibabab", "alibaba", NULL, NULL, "1982", + "Mustafa and 40 Thieves (bootleg)\0", NULL, "bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, alibababRomInfo, alibababRomName, NULL, NULL, alibabaInputInfo, alibabaDIPInfo, + alibabaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Birdiy + +static struct BurnRomInfo birdiyRomDesc[] = { + { "a6.bin", 0x1000, 0x3a58f8ad, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "c6.bin", 0x1000, 0xfec61ea2, 1 | BRF_ESS | BRF_PRG }, // 1 + { "a4.bin", 0x1000, 0x3392783b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "c4.bin", 0x1000, 0x2391d83d, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "c1.bin", 0x1000, 0x8f6bf54f, 2 | BRF_GRA }, // 4 Graphics + { "c3.bin", 0x1000, 0x10b55440, 2 | BRF_GRA }, // 5 + + { "82s123.7f", 0x0020, 0x00000000, 3 | BRF_GRA | BRF_NODUMP }, // 6 Color Proms + { "82s126.4a", 0x0100, 0x00000000, 3 | BRF_GRA | BRF_NODUMP }, // 7 + + { "82s126.1m", 0x0100, 0xa9cc86bf, 4 | BRF_SND }, // 8 Sound Prom + { "82s126.3m", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 9 Timing Prom (not used) +}; + +STD_ROM_PICK(birdiy) +STD_ROM_FN(birdiy) + +static void BirdiyCallback() +{ + // hard code some colours (puckman) + UINT8 PromData1[32] = { 0x00, 0x07, 0x66, 0xef, 0x00, 0xf8, 0xea, 0x6f, 0x00, 0x3f, 0x00, 0xc9, 0x38, 0xaa, 0xaf, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + UINT8 PromData2[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0B, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0B, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x01, 0x0C, 0x0F, + 0x00, 0x0E, 0x00, 0x0B, 0x00, 0x0C, 0x0B, 0x0E, 0x00, 0x0C, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x0F, 0x00, 0x07, 0x0C, 0x02, 0x00, 0x09, 0x06, 0x0F, 0x00, 0x0D, 0x0C, 0x0F, + 0x00, 0x05, 0x03, 0x09, 0x00, 0x0F, 0x0B, 0x00, 0x00, 0x0E, 0x00, 0x0B, 0x00, 0x0E, 0x00, 0x0B, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x01, 0x00, 0x0F, 0x0B, 0x0E, 0x00, 0x0E, 0x00, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + DrvColPROM = PromData1; + UINT8 *Prom = DrvColPROM + 0x100; + Prom = PromData2; +} + +static INT32 birdiyInit() +{ + return DrvInit(StandardMap, BirdiyCallback, BIRDIY); +} + +struct BurnDriverD BurnDrvbirdiy = { + "birdiy", NULL, NULL, NULL, "1982", + "Birdiy\0", "Bad colors, no sound (incomplete dump)", "Mama Top", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, birdiyRomInfo, birdiyRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + birdiyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (set 1 rev c) + +static struct BurnRomInfo pengoRomDesc[] = { + { "ep1689c.8", 0x1000, 0xf37066a8, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ep1690b.7", 0x1000, 0xbaf48143, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ep1691b.15", 0x1000, 0xadf0eba0, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ep1692b.14", 0x1000, 0xa086d60f, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ep1693b.21", 0x1000, 0xb72084ec, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ep1694b.20", 0x1000, 0x94194a89, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ep5118b.32", 0x1000, 0xaf7b12c4, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ep5119c.31", 0x1000, 0x933950fe, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ep1640.92", 0x2000, 0xd7eec6cd, 2 | BRF_GRA }, // 8 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 9 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 10 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 11 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 12 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom +}; + +STD_ROM_PICK(pengo) +STD_ROM_FN(pengo) + +static void PengoDecode() +{ + static const UINT8 convtable[32][4] = + { + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 }, + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, + { 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 }, + { 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, + { 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 }, + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, + { 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 }, + { 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 }, + { 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 }, + { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, + { 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 }, + { 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 }, + { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, + { 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 } + }; + + UINT8 *decrypted = DrvZ80ROM + 0x8000; + + for (INT32 A = 0x0000;A < 0x8000;A++) + { + INT32 xorval = 0; + UINT8 src = DrvZ80ROM[A]; + + INT32 row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3); + + INT32 col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); + + if (src & 0x80) + { + col = 3 - col; + xorval = 0xa8; + } + + decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xorval); + DrvZ80ROM[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xorval); + + if (convtable[2*row][col] == 0xff) decrypted[A] = 0xee; + if (convtable[2*row+1][col] == 0xff) DrvZ80ROM[A] = 0xee; + } +} + +static void PengoGraphicsReorder() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x2000); + + memcpy (tmp + 0x0000, DrvGfxROM + 0x2000, 0x1000); + memcpy (tmp + 0x1000, DrvGfxROM + 0x1000, 0x1000); + memcpy (DrvGfxROM + 0x1000, tmp + 0x0000, 0x2000); + + BurnFree (tmp); +} + +static void PengoCallback() +{ + PengoDecode(); + + PengoGraphicsReorder(); +} + +static INT32 pengoInit() +{ + return DrvInit(PengoMap, PengoCallback, PENGO); +} + +struct BurnDriver BurnDrvpengo = { + "pengo", NULL, NULL, NULL, "1982", + "Pengo (set 1 rev c)\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengoRomInfo, pengoRomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (set 2) + +static struct BurnRomInfo pengo2RomDesc[] = { + { "ic8.2", 0x1000, 0xe4924b7b, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ic7.2", 0x1000, 0x72e7775d, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ic15.2", 0x1000, 0x7410ef1e, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ic14.2", 0x1000, 0x55b3f379, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ep1693b.21", 0x1000, 0xb72084ec, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ic20.2", 0x1000, 0x770570cf, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ep5118b.32", 0x1000, 0xaf7b12c4, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ic31.2", 0x1000, 0x669555c1, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ep1640.92", 0x2000, 0xd7eec6cd, 2 | BRF_GRA }, // 8 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 9 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 10 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 11 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 12 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom +}; + +STD_ROM_PICK(pengo2) +STD_ROM_FN(pengo2) + +struct BurnDriver BurnDrvpengo2 = { + "pengo2", "pengo", NULL, NULL, "1982", + "Pengo (set 2)\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengo2RomInfo, pengo2RomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (set 2 not encrypted) + +static struct BurnRomInfo pengo2uRomDesc[] = { + { "epr5128.u8", 0x1000, 0x3dfeb20e, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "epr5129.u7", 0x1000, 0x1db341bd, 1 | BRF_ESS | BRF_PRG }, // 1 + { "epr5130.u15", 0x1000, 0x7c2842d5, 1 | BRF_ESS | BRF_PRG }, // 2 + { "epr5131.u14", 0x1000, 0x6e3c1f2f, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ep5124.21", 0x1000, 0x95f354ff, 1 | BRF_ESS | BRF_PRG }, // 4 + { "epr5133.u20", 0x1000, 0x0fdb04b8, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ep5126.32", 0x1000, 0xe5920728, 1 | BRF_ESS | BRF_PRG }, // 6 + { "epr5135.u31", 0x1000, 0x13de47ed, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ep1640.92", 0x2000, 0xd7eec6cd, 2 | BRF_GRA }, // 8 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 9 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 10 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 11 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 12 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom +}; + +STD_ROM_PICK(pengo2u) +STD_ROM_FN(pengo2u) + +static void PengouCallback() +{ + memcpy (DrvZ80ROM + 0x8000, DrvZ80ROM, 0x8000); + + PengoGraphicsReorder(); +} + +static INT32 pengouInit() +{ + return DrvInit(PengoMap, PengouCallback, PENGO); +} + +struct BurnDriver BurnDrvpengo2u = { + "pengo2u", "pengo", NULL, NULL, "1982", + "Pengo (set 2 not encrypted)\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengo2uRomInfo, pengo2uRomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengouInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (set 3 not encrypted) + +static struct BurnRomInfo pengo3uRomDesc[] = { + { "ep5120.8", 0x1000, 0xf01afb60, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ep5121.7", 0x1000, 0x2eb38353, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ep5122.15", 0x1000, 0xc33400d7, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ep5123.14", 0x1000, 0x6a85c6a2, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ep5124.21", 0x1000, 0x95f354ff, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ep5125.20", 0x1000, 0x1a42310f, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ep5126.32", 0x1000, 0xe5920728, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ep5127.31", 0x1000, 0xa7d3d1d6, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ep1640.92", 0x2000, 0xd7eec6cd, 2 | BRF_GRA }, // 8 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 9 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 10 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 11 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 12 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom +}; + +STD_ROM_PICK(pengo3u) +STD_ROM_FN(pengo3u) + +struct BurnDriver BurnDrvpengo3u = { + "pengo3u", "pengo", NULL, NULL, "1982", + "Pengo (set 3 not encrypted)\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengo3uRomInfo, pengo3uRomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengouInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (set 4) + +static struct BurnRomInfo pengo4RomDesc[] = { + { "ep1738.8", 0x1000, 0x68ba25ea, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "ep1739.7", 0x1000, 0x41e7b5b3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ep1740.15", 0x1000, 0x27f05f59, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ep1741.14", 0x1000, 0x27d93ec1, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ep1742.21", 0x1000, 0xb72084ec, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ep1743.20", 0x1000, 0x770570cf, 1 | BRF_ESS | BRF_PRG }, // 5 + { "ep1744.32", 0x1000, 0xaf7b12c4, 1 | BRF_ESS | BRF_PRG }, // 6 + { "ep1745.31", 0x1000, 0x507e18b9, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "ep1640.92", 0x2000, 0xd7eec6cd, 2 | BRF_GRA }, // 8 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 9 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 10 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 11 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 12 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 13 Timing Prom +}; + +STD_ROM_PICK(pengo4) +STD_ROM_FN(pengo4) + +struct BurnDriver BurnDrvpengo4 = { + "pengo4", "pengo", NULL, NULL, "1982", + "Pengo (set 4)\0", NULL, "Sega", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengo4RomInfo, pengo4RomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Pengo (bootleg) + +static struct BurnRomInfo pengobRomDesc[] = { + { "1", 0x2000, 0xe04064db, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "2", 0x2000, 0x75752424, 1 | BRF_ESS | BRF_PRG }, // 1 + { "021_pn03.bin", 0x1000, 0x7824e3ef, 1 | BRF_ESS | BRF_PRG }, // 2 + { "020_pn07.bin", 0x1000, 0x377b9663, 1 | BRF_ESS | BRF_PRG }, // 3 + { "032_pn04.bin", 0x1000, 0xbfde44c1, 1 | BRF_ESS | BRF_PRG }, // 4 + { "031_pn08.bin", 0x1000, 0x64e8c30d, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "5", 0x2000, 0x1232437b, 2 | BRF_GRA }, // 6 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 7 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 8 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 9 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 10 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom +}; + +STD_ROM_PICK(pengob) +STD_ROM_FN(pengob) + +static void PentaDecode() +{ + static const UINT8 data_xortable[2][8] = + { + { 0xa0,0x82,0x28,0x0a,0x82,0xa0,0x0a,0x28 }, + { 0x88,0x0a,0x82,0x00,0x88,0x0a,0x82,0x00 } + }; + + static const UINT8 opcode_xortable[8][8] = + { + { 0x02,0x08,0x2a,0x20,0x20,0x2a,0x08,0x02 }, + { 0x88,0x88,0x00,0x00,0x88,0x88,0x00,0x00 }, + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, + { 0x2a,0x08,0x2a,0x08,0x8a,0xa8,0x8a,0xa8 }, + { 0x2a,0x08,0x2a,0x08,0x8a,0xa8,0x8a,0xa8 }, + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 } + }; + + UINT8 *decrypt = DrvZ80ROM + 0x8000; + + for (INT32 A = 0; A < 0x8000; A++) + { + UINT8 src = DrvZ80ROM[A]; + + INT32 i = A & 1; + + INT32 j = ((src >> 1) & 1) + (((src >> 3) & 1) << 1) + (((src >> 5) & 1) << 2); + + if (src & 0x80) j = 7 - j; + + DrvZ80ROM[A] = src ^ data_xortable[i][j]; + + i = ((A >> 4) & 1) + (((A >> 8) & 1) << 1) + (((A >> 12) & 1) << 2); + + decrypt[A] = src ^ opcode_xortable[i][j]; + } +} + +static void PengobCallback() +{ + PentaDecode(); + + PengoGraphicsReorder(); +} + +static INT32 pengobInit() +{ + return DrvInit(PengoMap, PengobCallback, PENGO); +} + +struct BurnDriver BurnDrvpengob = { + "pengob", "pengo", NULL, NULL, "1982", + "Pengo (bootleg)\0", NULL, "Bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pengobRomInfo, pengobRomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengobInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + +// Penta + +static struct BurnRomInfo pentaRomDesc[] = { + { "008_pn01.bin", 0x1000, 0x22f328df, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "007_pn05.bin", 0x1000, 0x15bbc7d3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "015_pn02.bin", 0x1000, 0xde82b74a, 1 | BRF_ESS | BRF_PRG }, // 2 + { "014_pn06.bin", 0x1000, 0x160f3836, 1 | BRF_ESS | BRF_PRG }, // 3 + { "021_pn03.bin", 0x1000, 0x7824e3ef, 1 | BRF_ESS | BRF_PRG }, // 4 + { "020_pn07.bin", 0x1000, 0x377b9663, 1 | BRF_ESS | BRF_PRG }, // 5 + { "032_pn04.bin", 0x1000, 0xbfde44c1, 1 | BRF_ESS | BRF_PRG }, // 6 + { "031_pn08.bin", 0x1000, 0x64e8c30d, 1 | BRF_ESS | BRF_PRG }, // 7 + + { "092_pn09.bin", 0x2000, 0x6afeba9d, 2 | BRF_GRA }, // 6 Graphics + { "ep1695.105", 0x2000, 0x5bfd26e9, 2 | BRF_GRA }, // 7 + + { "pr1633.78", 0x0020, 0x3a5844ec, 3 | BRF_GRA }, // 8 Color Proms + { "pr1634.88", 0x0400, 0x766b139b, 3 | BRF_GRA }, // 9 + + { "pr1635.51", 0x0100, 0xc29dea27, 4 | BRF_SND }, // 10 Sound Prom + { "pr1636.70", 0x0100, 0x77245b66, 0 | BRF_SND | BRF_OPT }, // 11 Timing Prom +}; + +STD_ROM_PICK(penta) +STD_ROM_FN(penta) + +struct BurnDriver BurnDrvpenta = { + "penta", "pengo", NULL, NULL, "1982", + "Penta\0", NULL, "Bootleg", "Pac-man", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PACMAN, GBF_MAZE, 0, + NULL, pentaRomInfo, pentaRomName, NULL, NULL, PengoInputInfo, PengoDIPInfo, + pengobInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 288, 3, 4 +}; + + diff --git a/src/burn/drivers/misc_pre90s/d_pkunwar.cpp b/src/burn/drivers/misc_pre90s/d_pkunwar.cpp new file mode 100644 index 00000000..ac84a722 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_pkunwar.cpp @@ -0,0 +1,624 @@ +// FB Alpha Penguin-Kun Wars Driver Module +// Based on MAME Driver by David Haywood and Phil Stroffolino + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + + +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvDips, DrvReset; +static INT16 *pAY8910Buffer[6], *pFMBuffer = NULL; +static UINT8 *Mem, *Rom, *Gfx0, *Gfx1; +static INT32 *Palette; + +static INT32 flipscreen, vblank; + + +//------------------------------------------------------------------------------------------------- +// Input Handlers + + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy2 + 7, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy1 + 5, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 2, "p1 fire 1"}, + + {"P2 start" , BIT_DIGITAL , DrvJoy2 + 5, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 2, "p2 fire 1"}, + + {"Service Mode", BIT_DIGITAL, DrvJoy2 + 6, "diag" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, &DrvDips , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0x03, 0x00, "3C 1C" }, + {0x0b, 0x01, 0x03, 0x02, "2C 1C" }, + {0x0b, 0x01, 0x03, 0x03, "1C 1C" }, + {0x0b, 0x01, 0x03, 0x01, "1C 2C" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x04, 0x00, "Upright" }, + {0x0b, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x30, 0x10, "Easy" }, + {0x0b, 0x01, 0x30, 0x30, "Medium" }, + {0x0b, 0x01, 0x30, 0x20, "Hard" }, + {0x0b, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Flip screen" }, + {0x0b, 0x01, 0x40, 0x40, "Off" }, + {0x0b, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x0b, 0x01, 0x80, 0x80, "Off" }, + {0x0b, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + + +//------------------------------------------------------------------------------------------------- +// Memory Handlers + + +UINT8 __fastcall pkunwar_read(UINT16 address) +{ + switch (address) + { + case 0xa001: + return AY8910Read(0); + break; + + case 0xa003: + return AY8910Read(1); + break; + } + + return 0; +} + +void __fastcall pkunwar_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xa000: + AY8910Write(0, 0, data); + break; + + case 0xa001: + AY8910Write(0, 1, data); + break; + + case 0xa002: + AY8910Write(1, 0, data); + break; + + case 0xa003: + AY8910Write(1, 1, data); + break; + } +} + +void __fastcall pkunwar_out(UINT16 address, UINT8 data) +{ + address &= 0xff; + + if (address == 0) flipscreen = data & 1; +} + + +//------------------------------------------------------------------------------------------------- +// AY8910 Ports + + +static UINT8 pkunwar_port_0(UINT32) +{ + UINT8 ret = 0x7f | (vblank ^= 0x80); + + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy1[i] << i; + } + + return ret; +} + +static UINT8 pkunwar_port_1(UINT32) +{ + UINT8 ret = 0xff; + + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy2[i] << i; + } + + return ret; +} + +static UINT8 pkunwar_port_2(UINT32) +{ + return 0xff; +} + +static UINT8 pkunwar_port_3(UINT32) +{ + return DrvDips; +} + + +//------------------------------------------------------------------------------------------------- +// Initialization Routines + + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (Rom + 0x8000, 0, 0x1000); + memset (Rom + 0xc000, 0, 0x0800); + + flipscreen = 0; + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + AY8910Reset(1); + + return 0; +} + +static void pkunwar_palette_init(UINT8 *Prom) +{ + for (INT32 i = 0; i < 0x200; i++) + { + INT32 entry; + INT32 intensity,r,g,b; + + if ((i & 0xf) == 1) + { + entry = ((i & 0xf0) >> 4) | ((i & 0x100) >> 4); + } + else + { + entry = ((i & 0x0f) >> 0) | ((i & 0x100) >> 4); + } + + intensity = Prom[entry] & 0x03; + + r = (((Prom[entry] >> 0) & 0x0c) | intensity) * 0x11; + g = (((Prom[entry] >> 2) & 0x0c) | intensity) * 0x11; + b = (((Prom[entry] >> 4) & 0x0c) | intensity) * 0x11; + + Palette[i] = (r << 16) | (g << 8) | b; + } +} + +static void pkunwar_gfx_decode(UINT8 *Gfx) +{ + static INT32 PlaneOffsets[4] = { 0, 1, 2, 3 }; + + static INT32 XOffsets[16] = { + 0x00000, 0x00004, 0x40000, 0x40004, 0x00008, 0x0000c, 0x40008, 0x4000c, + 0x00080, 0x00084, 0x40080, 0x40084, 0x00088, 0x0008c, 0x40088, 0x4008c + }; + + static INT32 YOffsets[16] = { + 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170 + }; + + GfxDecode(0x800, 4, 8, 8, PlaneOffsets, XOffsets, YOffsets, 0x080, Gfx, Gfx0); + GfxDecode(0x200, 4, 16, 16, PlaneOffsets, XOffsets, YOffsets, 0x200, Gfx, Gfx1); +} + +static INT32 LoadRoms() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + if (BurnLoadRom(Rom + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(Rom + 0x4000, 1, 1)) return 1; + if (BurnLoadRom(Rom + 0xe000, 2, 1)) return 1; + + if (BurnLoadRom(Gfx0 + 0x0000, 3, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x4000, 4, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x8000, 5, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0xc000, 6, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + INT32 j = ((i & 1) << 2) | ((i >> 1) & 3); + memcpy (tmp + j * 0x2000, Gfx0 + i * 0x2000, 0x2000); + } + + pkunwar_gfx_decode(tmp); + + if (BurnLoadRom(tmp + 0x0000, 7, 1)) return 1; + + pkunwar_palette_init(tmp); + + BurnFree(tmp); + + return 0; +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + (0x20000 * 2) + (0x200 * sizeof(INT32))); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)BurnMalloc (nBurnSoundLen * 6 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom = Mem + 0x00000; + Gfx0 = Mem + 0x10000; + Gfx1 = Mem + 0x30000; + Palette = (INT32*)(Mem + 0x40000); + + if (LoadRoms()) return 1; + + ZetInit(1); + ZetOpen(0); + ZetSetOutHandler(pkunwar_out); + ZetSetReadHandler(pkunwar_read); + ZetSetWriteHandler(pkunwar_write); + ZetMapArea(0x0000, 0x7fff, 0, Rom + 0x00000); + ZetMapArea(0x0000, 0x7fff, 2, Rom + 0x00000); + ZetMapArea(0x8000, 0x8fff, 0, Rom + 0x08000); + ZetMapArea(0x8000, 0x8fff, 1, Rom + 0x08000); + ZetMapArea(0xc000, 0xc7ff, 0, Rom + 0x0c000); + ZetMapArea(0xc000, 0xc7ff, 1, Rom + 0x0c000); + ZetMapArea(0xc000, 0xc7ff, 2, Rom + 0x0c000); + ZetMapArea(0xe000, 0xffff, 0, Rom + 0x0e000); + ZetMapArea(0xe000, 0xffff, 2, Rom + 0x0e000); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 1500000, nBurnSoundRate, &pkunwar_port_0, &pkunwar_port_1, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, &pkunwar_port_2, &pkunwar_port_3, NULL, NULL); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (pFMBuffer); + BurnFree (Mem); + + Rom = Gfx0 = Gfx1 = Mem = NULL; + Palette = NULL; + + vblank = flipscreen = 0; + + return 0; +} + + +//------------------------------------------------------------------------------------------------- +// Drawing Routines + + +static INT32 DrawChars(INT32 priority) +{ + INT32 offs; + + for (offs = 0x3c0 - 1;offs >= 0x40;offs--) + { + if (Rom[0x8c00 + offs] & 0x08 || !priority) + { + INT32 sx,sy,num,color,pxl,pos; + + sx = (offs & 0x1f) << 3; + sy = (offs >> 2) & 0xf8; + + if (sy < 32 || sy > 223) continue; + sy -= 32; + + num = Rom[0x8800 + offs] | ((Rom[0x8c00 + offs] & 7) << 8); + color = 0x100 | (Rom[0x8c00 + offs] & 0xf0); + + UINT8 *src = Gfx0 + (num << 6); + + for (INT32 y = sy; y < sy + 8; y++) + { + for (INT32 x = sx; x < sx + 8; x++, src++) + { + if (!*src && priority) continue; + + pxl = Palette[color | *src]; + + if (flipscreen) + pos = ((191 - y) << 8) | (~x & 0xff); + else + pos = (y << 8) | (x & 0xff); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + } + + return 0; +} + +static INT32 DrvDraw() +{ + INT32 offs; + + DrawChars(0); + + for (offs = 0;offs < 0x800;offs += 32) + { + INT32 sx,sy,flipx,flipy,num,color,pxl,pos; + + sx = Rom[0x8001 + offs]; + sy = Rom[0x8002 + offs]; + + if (sy < 16 || sy > 223) continue; + sy -= 32; + + flipx = Rom[0x8000 + offs] & 0x01; + flipy = Rom[0x8000 + offs] & 0x02; + + num = ((Rom[0x8000 + offs] & 0xfc) >> 2) + ((Rom[0x8003 + offs] & 7) << 6); + color = Rom[0x8003 + offs] & 0xf0; + + UINT8 *src = Gfx1 + (num << 8); + + if (flipy) + { + for (INT32 y = sy + 15; y >= sy; y--) + { + if (flipx) + { + for (INT32 x = sx + 15; x >= sx; x--, src++) + { + if (y > 191 || y < 0 || !*src) continue; + + pxl = Palette[color | *src]; + + if (flipscreen) + pos = ((191 - y) << 8) | (~x & 0xff); + else + pos = (y << 8) | (x & 0xff); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } else { + for (INT32 x = sx; x < sx + 16; x++, src++) + { + if (y > 191 || y < 0 || !*src) continue; + + pxl = Palette[color | *src]; + + if (flipscreen) + pos = ((191 - y) << 8) | (~x & 0xff); + else + pos = (y << 8) | (x & 0xff); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + } else { + for (INT32 y = sy; y < sy + 16; y++) + { + if (flipx) + { + for (INT32 x = sx + 15; x >= sx; x--, src++) + { + if (y > 191 || y < 0 || !*src) continue; + + pxl = Palette[color | *src]; + + if (flipscreen) + pos = ((191 - y) << 8) | (~x & 0xff); + else + pos = (y << 8) | (x & 0xff); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } else { + for (INT32 x = sx; x < sx + 16; x++, src++) + { + if (y > 191 || y < 0 || !*src) continue; + + pxl = Palette[color | *src]; + + if (flipscreen) + pos = ((191 - y) << 8) | (~x & 0xff); + else + pos = (y << 8) | (x & 0xff); + + PutPix(pBurnDraw + pos * nBurnBpp, BurnHighCol(pxl >> 16, pxl >> 8, pxl, 0)); + } + } + } + } + } + + DrawChars(1); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + vblank = 0; + + ZetOpen(0); + ZetRun(3000000 / 60); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------- +// Save State + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0x8000; + ba.nLen = 0x1000; + ba.szName = "Video Ram"; + BurnAcb(&ba); + + ba.Data = Rom + 0xc000; + ba.nLen = 0x0800; + ba.szName = "Work Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(flipscreen); + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------- +// Game drivers + + +// Penguin-Kun Wars (US) + +static struct BurnRomInfo pkunwarRomDesc[] = { + { "pkwar.01r", 0x4000, 0xce2d2c7b, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "pkwar.02r", 0x4000, 0xabc1f661, 1 | BRF_PRG | BRF_ESS }, // 1 + { "pkwar.03r", 0x2000, 0x56faebea, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "pkwar.01y", 0x4000, 0x428d3b92, 2 | BRF_GRA }, // 3 Graphics + { "pkwar.02y", 0x4000, 0xce1da7bc, 2 | BRF_GRA }, // 4 + { "pkwar.03y", 0x4000, 0x63204400, 2 | BRF_GRA }, // 5 + { "pkwar.04y", 0x4000, 0x061dfca8, 2 | BRF_GRA }, // 6 + + { "pkwar.col", 0x0020, 0xaf0fc5e2, 3 | BRF_GRA }, // 7 Color Prom +}; + +STD_ROM_PICK(pkunwar) +STD_ROM_FN(pkunwar) + +struct BurnDriver BurnDrvpkunwar = { + "pkunwar", NULL, NULL, NULL, "1985", + "Penguin-Kun Wars (US)\0", NULL, "UPL", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, pkunwarRomInfo, pkunwarRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x200, + 256, 192, 4, 3 +}; + + +// Penguin-Kun Wars (Japan) + +static struct BurnRomInfo pkunwarjRomDesc[] = { + { "pgunwar.6", 0x4000, 0x357f3ef3, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 Code + { "pgunwar.5", 0x4000, 0x0092e49e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "pkwar.03r", 0x2000, 0x56faebea, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "pkwar.01y", 0x4000, 0x428d3b92, 2 | BRF_GRA }, // 3 Graphics + { "pkwar.02y", 0x4000, 0xce1da7bc, 2 | BRF_GRA }, // 4 + { "pgunwar.2", 0x4000, 0xa2a43443, 2 | BRF_GRA }, // 5 + { "pkwar.04y", 0x4000, 0x061dfca8, 2 | BRF_GRA }, // 6 + + { "pkwar.col", 0x0020, 0xaf0fc5e2, 3 | BRF_GRA }, // 7 Color Prom +}; + +STD_ROM_PICK(pkunwarj) +STD_ROM_FN(pkunwarj) + +struct BurnDriver BurnDrvpkunwarj = { + "pkunwarj", "pkunwar", NULL, NULL, "1985", + "Penguin-Kun Wars (Japan)\0", NULL, "UPL", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0, + NULL, pkunwarjRomInfo, pkunwarjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x200, + 256, 192, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_pooyan.cpp b/src/burn/drivers/misc_pre90s/d_pooyan.cpp new file mode 100644 index 00000000..a3fad424 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_pooyan.cpp @@ -0,0 +1,772 @@ +// FB Alpha Pooyan Driver Module +// Based on MAME driver by Allard van der Bas, Mike Cuddy, Nicola Salmoria, Martin Binder, and Marco Cassili + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd; +static UINT8 *Rom0, *Rom1, *Gfx0, *Gfx1, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[2], DrvReset; +static UINT32 *Palette, *DrvPalette; +static UINT8 DrvRecalcPalette; + +static INT16 *pFMBuffer; +static INT16 *pAY8910Buffer[6]; + +static UINT8 irqtrigger; +static UINT8 irq_enable; +static UINT8 flipscreen; +static UINT8 soundlatch; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 3, "p1 start" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 3, "p1 down" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 4, "p2 start" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 3, "p2 down" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 2, "service" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0c, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" }, + {0x0c, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" }, + {0x0c, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" }, + {0x0c, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x0c, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x0c, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x0c, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x0c, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x0c, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x0c, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x0c, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x0c, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x0c, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x0c, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x0c, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x0c, 0x01, 0x0f, 0x00, "Free Play" }, + + {0 , 0xfe, 0 , 15 , "Coin B" }, + {0x0c, 0x82, 0xf0, 0x20, "4 Coins 1 Credit" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x50, "3 Coins 1 Credit" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x80, "2 Coins 1 Credit" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + {0x0c, 0x82, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x0c, 0x00, 0x0f, 0x00, NULL }, + + // Default Values + {0x0d, 0xff, 0xff, 0x7b, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0d, 0x01, 0x03, 0x03, "3" }, + {0x0d, 0x01, 0x03, 0x02, "4" }, + {0x0d, 0x01, 0x03, 0x01, "5" }, + {0x0d, 0x01, 0x03, 0x00, "256" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x04, 0x00, "Upright" }, + {0x0d, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0d, 0x01, 0x08, 0x08, "50K 80K+" }, + {0x0d, 0x01, 0x08, 0x00, "30K 70K+" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x0d, 0x01, 0x70, 0x70, "1 (Easy)" }, + {0x0d, 0x01, 0x70, 0x60, "2" }, + {0x0d, 0x01, 0x70, 0x50, "3" }, + {0x0d, 0x01, 0x70, 0x40, "4" }, + {0x0d, 0x01, 0x70, 0x30, "5" }, + {0x0d, 0x01, 0x70, 0x20, "6" }, + {0x0d, 0x01, 0x70, 0x10, "7" }, + {0x0d, 0x01, 0x70, 0x00, "8 (Hard)" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x80, 0x80, "Off" }, + {0x0d, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +UINT8 __fastcall pooyan_cpu0_read(UINT16 address) +{ + UINT8 ret = 0xff; + + switch (address) + { + case 0xa000: + return DrvDips[1]; + + case 0xa080: + { + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy1[i] << i; + } + + return ret; + } + + case 0xa0a0: + { + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy2[i] << i; + } + + return ret; + } + + case 0xa0c0: + { + for (INT32 i = 0; i < 8; i++) { + ret ^= DrvJoy3[i] << i; + } + + return ret; + } + + case 0xa0e0: + return DrvDips[0]; + + } + + return 0; +} + +void __fastcall pooyan_cpu0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xa000: + // watchdog + break; + + case 0xa100: + soundlatch = data; + break; + + case 0xa180: + irq_enable = data & 1; + + if (!irq_enable) + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + break; + + case 0xa181: + { + if (irqtrigger == 0 && data) { + ZetClose(); + ZetOpen(1); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + ZetOpen(0); + } + + irqtrigger = data; + } + break; + + case 0xa183: + break; + + case 0xa187: + flipscreen = ~data & 1; + break; + } +} + +UINT8 __fastcall pooyan_cpu1_read(UINT16 address) +{ + switch (address & 0xf000) + { + case 0x4000: + return AY8910Read(0); + + case 0x6000: + return AY8910Read(1); + } + + return 0; +} + +void __fastcall pooyan_cpu1_write(UINT16 address, UINT8 data) +{ + switch (address & 0xf000) + { + case 0x4000: + AY8910Write(0, 1, data); + break; + + case 0x5000: + AY8910Write(0, 0, data); + break; + + case 0x6000: + AY8910Write(1, 1, data); + break; + + case 0x7000: + AY8910Write(1, 0, data); + break; + + case 0x8000: + case 0x9000: + case 0xa000: + case 0xb000: + case 0xc000: + case 0xd000: + case 0xe000: + case 0xf000: + // timeplt_filter_w + break; + } +} + +static UINT8 AY8910_0_port0(UINT32) +{ + return soundlatch; +} + +static UINT8 AY8910_0_port1(UINT32) +{ + static INT32 timeplt_timer[10] = + { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x90, 0xa0, 0xb0, 0xa0, 0xd0 + }; + + return timeplt_timer[(ZetTotalCycles() >> 9) % 10]; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + AY8910Reset(0); + AY8910Reset(1); + + memset (Rom0 + 0x8000, 0, 0x1800); + memset (Rom1 + 0x3000, 0, 0x0400); + + irqtrigger = 0; + flipscreen = 0; + soundlatch = 0; + irq_enable = 0; + + return 0; +} + +static void DrvPaletteInit() +{ + INT32 i; + UINT32 c_pal[0x20]; + + for (i = 0; i < 0x20; i++) + { + INT32 r, g, b; + INT32 bit0, bit1, bit2; + + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = 33 * bit0 + 71 * bit1 + 151 * bit2; + + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = 33 * bit0 + 71 * bit1 + 151 * bit2; + + bit0 = (Prom[i] >> 6) & 0x01; + bit1 = (Prom[i] >> 7) & 0x01; + b = 80 * bit0 + 171 * bit1; + + c_pal[i] = (r << 16) | (g << 8) | b; + } + + for (i = 0; i < 0x100; i++) + { + Palette[i + 0x000] = c_pal[(Prom[i + 0x020] & 0x0f) | 0x10]; + Palette[i + 0x100] = c_pal[(Prom[i + 0x120] & 0x0f) | 0x00]; + } +} + +static INT32 DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x2000); + if (!tmp) return 1; + + static INT32 Planes[4] = { 0x8004, 0x8000, 4, 0 }; + static INT32 XOffs[16] = { 0, 1, 2, 3, 0x40, 0x41, 0x42, 0x43, 0x80, 0x81, 0x82, 0x83, 0xc0, 0xc1, 0xc2, 0xc3 }; + static INT32 YOffs[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 256, 264, 272, 280, 288, 296, 304, 312 }; + + memcpy (tmp, Gfx0, 0x2000); + + GfxDecode(0x100, 4, 8, 8, Planes, XOffs, YOffs, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x2000); + + GfxDecode(0x40, 4, 16, 16, Planes, XOffs, YOffs, 0x200, tmp, Gfx1); + + BurnFree(tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom0 = Next; Next += 0x10000; + Rom1 = Next; Next += 0x04000; + Gfx0 = Next; Next += 0x04000; + Gfx1 = Next; Next += 0x04000; + Prom = Next; Next += 0x00220; + + Palette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + + pFMBuffer = (INT16 *)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + { + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Rom0 + i * 0x2000, 0 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 2; i++) { + if (BurnLoadRom(Rom1 + i * 0x1000, 4 + i, 1)) return 1; + if (BurnLoadRom(Gfx0 + i * 0x1000, 6 + i, 1)) return 1; + if (BurnLoadRom(Gfx1 + i * 0x1000, 8 + i, 1)) return 1; + } + + if (BurnLoadRom(Prom + 0x000, 10, 1)) return 1; + if (BurnLoadRom(Prom + 0x020, 11, 1)) return 1; + if (BurnLoadRom(Prom + 0x120, 12, 1)) return 1; + + if (DrvGfxDecode()) return 1; + DrvPaletteInit(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0x7fff, 2, Rom0 + 0x0000); + ZetMapArea(0x8000, 0x8fff, 0, Rom0 + 0x8000); + ZetMapArea(0x8000, 0x8fff, 1, Rom0 + 0x8000); + ZetMapArea(0x8000, 0x8fff, 2, Rom0 + 0x8000); + ZetMapArea(0x9000, 0x90ff, 0, Rom0 + 0x9000); + ZetMapArea(0x9000, 0x90ff, 1, Rom0 + 0x9000); + ZetMapArea(0x9000, 0x90ff, 2, Rom0 + 0x9000); + ZetMapArea(0x9400, 0x94ff, 0, Rom0 + 0x9400); + ZetMapArea(0x9400, 0x94ff, 1, Rom0 + 0x9400); + ZetMapArea(0x9400, 0x94ff, 2, Rom0 + 0x9400); + ZetSetWriteHandler(pooyan_cpu0_write); + ZetSetReadHandler(pooyan_cpu0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMemEnd(); + ZetMapArea(0x0000, 0x1fff, 0, Rom1 + 0x0000); + ZetMapArea(0x0000, 0x1fff, 2, Rom1 + 0x0000); + ZetMapArea(0x3000, 0x33ff, 0, Rom1 + 0x3000); + ZetMapArea(0x3000, 0x33ff, 1, Rom1 + 0x3000); + ZetMapArea(0x3000, 0x33ff, 2, Rom1 + 0x3000); + ZetSetWriteHandler(pooyan_cpu1_write); + ZetSetReadHandler(pooyan_cpu1_read); + ZetClose(); + + GenericTilesInit(); + + AY8910Init(0, 1789773, nBurnSoundRate, &AY8910_0_port0, &AY8910_0_port1, NULL, NULL); + AY8910Init(1, 1789773, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + + GenericTilesExit(); + + BurnFree (Mem); + + Mem = MemEnd = NULL; + Rom0 = Rom1 = Gfx0 = Gfx1 = Prom = NULL; + + Palette = DrvPalette = NULL; + pFMBuffer = NULL; + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = NULL; + } + + irqtrigger = 0; + irq_enable = 0; + flipscreen = 0; + soundlatch = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalcPalette) { + for (INT32 i = 0; i < 0x200; i++) { + UINT32 col = Palette[i]; + DrvPalette[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + for (INT32 i = 0; i < 0x0400; i++) + { + INT32 attr = Rom0[0x8000 + i]; + INT32 code = Rom0[0x8400 + i]; + INT32 color = attr & 0x0f; + INT32 flipx = (attr >> 6) & 1; + INT32 flipy = (attr >> 7) & 1; + + INT32 sx = (i << 3) & 0xf8; + INT32 sy = (i >> 2) & 0xf8; + + if (flipscreen) { + sx ^= 0xf8; + sy ^= 0xf8; + flipx ^= 1; + flipy ^= 1; + } + + if (sy > 239 || sy < 16) continue; + sy -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } + } + } + + for (INT32 i = 0x10; i < 0x40; i += 2) + { + INT32 sx = Rom0[0x9000 + i]; + INT32 sy = 240 - Rom0[0x9401 + i]; + + INT32 code = Rom0[0x9001 + i] & 0x3f; + INT32 color = (Rom0[0x9400 + i] & 0x0f) | 0x10; + INT32 flipx = ~Rom0[0x9400 + i] & 0x40; + INT32 flipy = Rom0[0x9400 + i] & 0x80; + + if (sy == 0 || sy >= 240) continue; + + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, Gfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, Gfx1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, Gfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, Gfx1); + } + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nInterleave = 10; + + INT32 nCyclesSegment; + INT32 nCyclesTotal[2], nCyclesDone[2]; + + nCyclesTotal[0] = 3072000 / 60; + nCyclesTotal[1] = 1789773 / 60; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (irq_enable && i == (nInterleave - 1)) ZetNmi(); + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom0 + 0x8000; + ba.nLen = 0x1800; + ba.szName = "Cpu #0 Ram"; + BurnAcb(&ba); + + ba.Data = Rom1 + 0x3000; + ba.nLen = 0x0400; + ba.szName = "Cpu #1 Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(soundlatch); + SCAN_VAR(irqtrigger); + SCAN_VAR(irq_enable); + SCAN_VAR(flipscreen); + } + + return 0; +} + + +// Pooyan + +static struct BurnRomInfo pooyanRomDesc[] = { + { "1.4a", 0x2000, 0xbb319c63, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "2.5a", 0x2000, 0xa1463d98, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.6a", 0x2000, 0xfe1a9e08, 1 | BRF_PRG | BRF_ESS }, // 2 + { "4.7a", 0x2000, 0x9e0f9bcc, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "xx.7a", 0x1000, 0xfbe2b368, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + { "xx.8a", 0x1000, 0xe1795b3d, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "8.10g", 0x1000, 0x931b29eb, 3 | BRF_GRA }, // 6 Characters + { "7.9g", 0x1000, 0xbbe6d6e4, 3 | BRF_GRA }, // 7 + + { "6.9a", 0x1000, 0xb2d8c121, 4 | BRF_GRA }, // 8 Sprites + { "5.8a", 0x1000, 0x1097c2b6, 4 | BRF_GRA }, // 9 + + { "pooyan.pr1", 0x0020, 0xa06a6d0e, 5 | BRF_GRA }, // 10 Color Proms + { "pooyan.pr3", 0x0100, 0x8cd4cd60, 5 | BRF_GRA }, // 11 + { "pooyan.pr2", 0x0100, 0x82748c0b, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(pooyan) +STD_ROM_FN(pooyan) + +struct BurnDriver BurnDrvPooyan = { + "pooyan", NULL, NULL, NULL, "1982", + "Pooyan\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, pooyanRomInfo, pooyanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPalette, 0x200, + 224, 256, 3, 4 +}; + + +// Pooyan (Stern) + +static struct BurnRomInfo pooyansRomDesc[] = { + { "ic22_a4.cpu", 0x2000, 0x916ae7d7, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "ic23_a5.cpu", 0x2000, 0x8fe38c61, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ic24_a6.cpu", 0x2000, 0x2660218a, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ic25_a7.cpu", 0x2000, 0x3d2a10ad, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "xx.7a", 0x1000, 0xfbe2b368, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + { "xx.8a", 0x1000, 0xe1795b3d, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "ic13_g10.cpu", 0x1000, 0x7433aea9, 3 | BRF_GRA }, // 6 Characters + { "ic14_g9.cpu", 0x1000, 0x87c1789e, 3 | BRF_GRA }, // 7 + + { "6.9a", 0x1000, 0xb2d8c121, 4 | BRF_GRA }, // 8 Sprites + { "5.8a", 0x1000, 0x1097c2b6, 4 | BRF_GRA }, // 9 + + { "pooyan.pr1", 0x0020, 0xa06a6d0e, 5 | BRF_GRA }, // 10 Color Proms + { "pooyan.pr3", 0x0100, 0x8cd4cd60, 5 | BRF_GRA }, // 11 + { "pooyan.pr2", 0x0100, 0x82748c0b, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(pooyans) +STD_ROM_FN(pooyans) + +struct BurnDriver BurnDrvPooyans = { + "pooyans", "pooyan", NULL, NULL, "1982", + "Pooyan (Stern)\0", NULL, "[Konami] (Stern license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, pooyansRomInfo, pooyansRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPalette, 0x200, + 224, 256, 3, 4 +}; + + +// Pootan + +static struct BurnRomInfo pootanRomDesc[] = { + { "poo_ic22.bin", 0x2000, 0x41b23a24, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "poo_ic23.bin", 0x2000, 0xc9d94661, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3.6a", 0x2000, 0xfe1a9e08, 1 | BRF_PRG | BRF_ESS }, // 2 + { "poo_ic25.bin", 0x2000, 0x8ae459ef, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "xx.7a", 0x1000, 0xfbe2b368, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 #1 Code + { "xx.8a", 0x1000, 0xe1795b3d, 2 | BRF_PRG | BRF_ESS }, // 5 + + { "poo_ic13.bin", 0x1000, 0x0be802e4, 3 | BRF_GRA }, // 6 Characters + { "poo_ic14.bin", 0x1000, 0xcba29096, 3 | BRF_GRA }, // 7 + + { "6.9a", 0x1000, 0xb2d8c121, 4 | BRF_GRA }, // 8 Sprites + { "5.8a", 0x1000, 0x1097c2b6, 4 | BRF_GRA }, // 9 + + { "pooyan.pr1", 0x0020, 0xa06a6d0e, 5 | BRF_GRA }, // 10 Color Proms + { "pooyan.pr3", 0x0100, 0x8cd4cd60, 5 | BRF_GRA }, // 11 + { "pooyan.pr2", 0x0100, 0x82748c0b, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(pootan) +STD_ROM_FN(pootan) + +struct BurnDriver BurnDrvPootan = { + "pootan", "pooyan", NULL, NULL, "1982", + "Pootan\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, pootanRomInfo, pootanRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPalette, 0x200, + 224, 256, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_prehisle.cpp b/src/burn/drivers/misc_pre90s/d_prehisle.cpp new file mode 100644 index 00000000..140e168f --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_prehisle.cpp @@ -0,0 +1,886 @@ +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "upd7759.h" + +// Input Related Variables +static UINT8 PrehisleInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 PrehisleInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 PrehisleInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 PrehisleDip[2] = {0, 0}; +static UINT8 PrehisleInput[3] = {0x00, 0x00, 0x00}; +static UINT8 PrehisleReset = 0; + +// Memory Holders +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *PrehisleRom = NULL; +static UINT8 *PrehisleZ80Rom = NULL; +static UINT8 *PrehisleTileMapRom = NULL; +static UINT8 *PrehisleADPCMSamples = NULL; +static UINT8 *PrehisleRam = NULL; +static UINT8 *PrehisleVideoRam = NULL; +static UINT8 *PrehisleSpriteRam = NULL; +static UINT8 *PrehisleVideo2Ram = NULL; +static UINT8 *PrehislePaletteRam = NULL; +static UINT8 *PrehisleZ80Ram = NULL; +static UINT32 *PrehislePalette = NULL; +static UINT8 *PrehisleTextTiles = NULL; +static UINT8 *PrehisleSprites = NULL; +static UINT8 *PrehisleBack1Tiles = NULL; +static UINT8 *PrehisleBack2Tiles = NULL; +static UINT8 *PrehisleTempGfx = NULL; + +// Misc Variables, system control values, etc. +static INT32 ControlsInvert; +static UINT16 VidControl[7]; +static INT32 SoundLatch; + +// CPU Interleave Variables +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +// Dip Switch and Input Definitions +static struct BurnInputInfo PrehisleInputList[] = { + {"Coin 1" , BIT_DIGITAL , PrehisleInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , PrehisleInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , PrehisleInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , PrehisleInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , PrehisleInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , PrehisleInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , PrehisleInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , PrehisleInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , PrehisleInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , PrehisleInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , PrehisleInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , PrehisleInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , PrehisleInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , PrehisleInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , PrehisleInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , PrehisleInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , PrehisleInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , PrehisleInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &PrehisleReset , "reset" }, + {"Service" , BIT_DIGITAL , PrehisleInputPort2 + 2, "service" }, + {"Diagnostics" , BIT_DIGITAL , PrehisleInputPort2 + 3, "diag" }, + {"Tilt" , BIT_DIGITAL , PrehisleInputPort2 + 4, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, PrehisleDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, PrehisleDip + 1 , "dip" }, +}; + +STDINPUTINFO(Prehisle) + +inline void PrehisleClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void PrehisleMakeInputs() +{ + // Reset Inputs + PrehisleInput[0] = PrehisleInput[1] = PrehisleInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + PrehisleInput[0] |= (PrehisleInputPort0[i] & 1) << i; + PrehisleInput[1] |= (PrehisleInputPort1[i] & 1) << i; + PrehisleInput[2] |= (PrehisleInputPort2[i] & 1) << i; + } + + // Clear Opposites + PrehisleClearOpposites(&PrehisleInput[0]); + PrehisleClearOpposites(&PrehisleInput[1]); +} + +static struct BurnDIPInfo PrehisleDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Display" }, + {0x16, 0x01, 0x01, 0x01, "Normal" }, + {0x16, 0x01, 0x01, 0x00, "Inverse" }, + + {0 , 0xfe, 0 , 2 , "Level Select" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Bonus" }, + {0x16, 0x01, 0x04, 0x04, "2nd" }, + {0x16, 0x01, 0x04, 0x00, "Every" }, + +// {0 , 0xfe, 0 , 2 , "Unknown" }, +// {0x16, 0x01, 0x08, 0x08, "Off" }, +// {0x16, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x16, 0x01, 0x30, 0x30, "A 1-1 B 1-1" }, + {0x16, 0x01, 0x30, 0x20, "A 2-1 B 1-2" }, + {0x16, 0x01, 0x30, 0x10, "A 3-1 B 1-3" }, + {0x16, 0x01, 0x30, 0x00, "A 4-1 B 1-4" }, + + {0 , 0xfe, 0 , 4 , "Hero" }, + {0x16, 0x01, 0xc0, 0x80, "2" }, + {0x16, 0x01, 0xc0, 0xc0, "3" }, + {0x16, 0x01, 0xc0, 0x40, "4" }, + {0x16, 0x01, 0xc0, 0x00, "5" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Level" }, + {0x17, 0x01, 0x03, 0x02, "1 (Easy)" }, + {0x17, 0x01, 0x03, 0x03, "2 (Standard)" }, + {0x17, 0x01, 0x03, 0x01, "3 (Middle)" }, + {0x17, 0x01, 0x03, 0x00, "4 (Difficult)" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x17, 0x01, 0x0c, 0x08, "Demo Sound Off" }, + {0x17, 0x01, 0x0c, 0x0c, "Demo Sound On" }, + {0x17, 0x01, 0x0c, 0x00, "Stop Video" }, + {0x17, 0x01, 0x0c, 0x04, "Never Finish" }, + + {0 , 0xfe, 0 , 4 , "Bonus 1st/2nd" }, + {0x17, 0x01, 0x30, 0x30, "100000/200000" }, + {0x17, 0x01, 0x30, 0x20, "150000/300000" }, + {0x17, 0x01, 0x30, 0x10, "300000/500000" }, + {0x17, 0x01, 0x30, 0x00, "No Bonus" }, + + {0 , 0xfe, 0 , 2 , "Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Prehisle) + +// Rom Definitions +static struct BurnRomInfo PrehisleRomDesc[] = { + { "gt-e2.2h", 0x20000, 0x7083245a, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gt-e3.3h", 0x20000, 0x6d8cdf58, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gt15.b15", 0x08000, 0xac652412, BRF_GRA }, // 2 Text Layer Tiles + { "pi8914.b14", 0x40000, 0x207d6187, BRF_GRA }, // 3 Background2 Layer Tiles + { "pi8916.h16", 0x40000, 0x7cffe0f6, BRF_GRA }, // 4 Background1 Layer Tiles + { "pi8910.k14", 0x80000, 0x5a101b0b, BRF_GRA }, // 5 Sprite Layer Tiles + { "gt5.5", 0x20000, 0x3d3ab273, BRF_GRA }, // 6 Sprite Layer Tiles + { "gt11.11", 0x10000, 0xb4f0fcf0, BRF_GRA }, // 7 Background 2 TileMap + + { "gt1.1", 0x10000, 0x80a4c093, BRF_SND }, // 8 Z80 Program Code + + { "gt4.4", 0x20000, 0x85dfb9ec, BRF_SND }, // 9 ADPCM Samples +}; + + +STD_ROM_PICK(Prehisle) +STD_ROM_FN(Prehisle) + +static struct BurnRomInfo PrehisluRomDesc[] = { + { "gt-u2.2h", 0x20000, 0xa14f49bb, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gt-u3.3h", 0x20000, 0xf165757e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gt15.b15", 0x08000, 0xac652412, BRF_GRA }, // 2 Text Layer Tiles + { "pi8914.b14", 0x40000, 0x207d6187, BRF_GRA }, // 3 Background2 Layer Tiles + { "pi8916.h16", 0x40000, 0x7cffe0f6, BRF_GRA }, // 4 Background1 Layer Tiles + { "pi8910.k14", 0x80000, 0x5a101b0b, BRF_GRA }, // 5 Sprite Layer Tiles + { "gt5.5", 0x20000, 0x3d3ab273, BRF_GRA }, // 6 Sprite Layer Tiles + { "gt11.11", 0x10000, 0xb4f0fcf0, BRF_GRA }, // 7 Background 2 TileMap + + { "gt1.1", 0x10000, 0x80a4c093, BRF_SND }, // 8 Z80 Program Code + + { "gt4.4", 0x20000, 0x85dfb9ec, BRF_SND }, // 9 ADPCM Samples +}; + + +STD_ROM_PICK(Prehislu) +STD_ROM_FN(Prehislu) + +static struct BurnRomInfo PrehislkRomDesc[] = { + { "gt-k2.2h", 0x20000, 0xf2d3544d, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gt-k3.3h", 0x20000, 0xebf7439b, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gt15.b15", 0x08000, 0xac652412, BRF_GRA }, // 2 Text Layer Tiles + { "pi8914.b14", 0x40000, 0x207d6187, BRF_GRA }, // 3 Background2 Layer Tiles + { "pi8916.h16", 0x40000, 0x7cffe0f6, BRF_GRA }, // 4 Background1 Layer Tiles + { "pi8910.k14", 0x80000, 0x5a101b0b, BRF_GRA }, // 5 Sprite Layer Tiles + { "gt5.5", 0x20000, 0x3d3ab273, BRF_GRA }, // 6 Sprite Layer Tiles + { "gt11.11", 0x10000, 0xb4f0fcf0, BRF_GRA }, // 7 Background 2 TileMap + + { "gt1.1", 0x10000, 0x80a4c093, BRF_SND }, // 8 Z80 Program Code + + { "gt4.4", 0x20000, 0x85dfb9ec, BRF_SND }, // 9 ADPCM Samples +}; + + +STD_ROM_PICK(Prehislk) +STD_ROM_FN(Prehislk) + +static struct BurnRomInfo GensitouRomDesc[] = { + { "gt-j2.2h", 0x20000, 0xa2da0b6b, BRF_ESS | BRF_PRG }, // 0 68000 Program Code + { "gt-j3.3h", 0x20000, 0xc1a0ae8e, BRF_ESS | BRF_PRG }, // 1 68000 Program Code + + { "gt15.b15", 0x08000, 0xac652412, BRF_GRA }, // 2 Text Layer Tiles + { "pi8914.b14", 0x40000, 0x207d6187, BRF_GRA }, // 3 Background2 Layer Tiles + { "pi8916.h16", 0x40000, 0x7cffe0f6, BRF_GRA }, // 4 Background1 Layer Tiles + { "pi8910.k14", 0x80000, 0x5a101b0b, BRF_GRA }, // 5 Sprite Layer Tiles + { "gt5.5", 0x20000, 0x3d3ab273, BRF_GRA }, // 6 Sprite Layer Tiles + { "gt11.11", 0x10000, 0xb4f0fcf0, BRF_GRA }, // 7 Background 2 TileMap + + { "gt1.1", 0x10000, 0x80a4c093, BRF_SND }, // 8 Z80 Program Code + + { "gt4.4", 0x20000, 0x85dfb9ec, BRF_SND }, // 9 ADPCM Samples +}; + + +STD_ROM_PICK(Gensitou) +STD_ROM_FN(Gensitou) + +// Misc Driver Functions and Memory Handlers +INT32 PrehisleDoReset() +{ + ControlsInvert = 0; + SoundLatch = 0; + VidControl[0] = VidControl[1] = VidControl[2] = VidControl[3] = VidControl[4] = VidControl[5] = VidControl[6] = 0; + + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + UPD7759Reset(); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Callbacks for the FM chip + +static void prehisleFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 prehisleSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +// VBlank + +inline UINT16 PrehisleVBlankRegister() +{ + INT32 nCycles = SekTotalCycles(); + + // 262 == approximate number of scanlines on an arcade monitor + if (nCycles >= (262 - 16) * ((9000000 / 60) / 262)) { + return 0x80; + } else { + if (nCycles < (262 - 210 - 16) * ((9000000 / 60) / 262)) { + return 0x80; + } + } + + return 0x00; +} + +UINT16 __fastcall PrehisleReadWord(UINT32 a) +{ + switch (a) { + case 0x0e0010: { + return 0xff - PrehisleInput[1]; + } + + case 0x0e0020: { + return 0xff - PrehisleInput[2]; + } + + case 0x0e0040: { + return 0xff - (PrehisleInput[0] ^ ControlsInvert); + } + + case 0x0e0042: { + return PrehisleDip[0]; + } + + case 0x0e0044: { + return PrehisleDip[1] + PrehisleVBlankRegister(); + } + } + + return 0; +} + +void __fastcall PrehisleWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x0f0000: { + VidControl[0] = d; + return; + } + + case 0x0f0010: { + VidControl[1] = d; + return; + } + + case 0x0f0020: { + VidControl[2] = d; + return; + } + + case 0x0f0030: { + VidControl[3] = d; + return; + } + + case 0x0f0046: { + ControlsInvert = d ? 0xff : 0x00; + return; + } + + case 0x0f0050: { + VidControl[4] = d; + return; + } + + case 0x0f0052: { + VidControl[5] = d; + return; + } + + case 0x0f0060: { + VidControl[6] = d; + return; + } + + case 0x0f0070: { + SoundLatch = d & 0xff; + ZetNmi(); + return; + } + } +} + +UINT8 __fastcall PrehisleZ80PortRead(UINT16 a) +{ + a &= 0xff; + switch (a) { + case 0x00: { + return BurnYM3812Read(0); + } + } + + return 0; +} + +void __fastcall PrehisleZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + switch (a) { + case 0x00: { + BurnYM3812Write(0, d); + return; + } + + case 0x20: { + BurnYM3812Write(1, d); + return; + } + + case 0x40: { + UPD7759PortWrite(0,d); + UPD7759StartWrite(0,0); + UPD7759StartWrite(0,1); + return; + } + + case 0x80: { + UPD7759ResetWrite(0,d); + return; + } + } +} + +UINT8 __fastcall PrehisleZ80Read(UINT16 a) +{ + switch (a) { + case 0xf800: { + return SoundLatch; + } + } + + return 0; +} + +// Function to Allocate and Index required memory +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + PrehisleRom = Next; Next += 0x40000; + PrehisleZ80Rom = Next; Next += 0x10000; + PrehisleTileMapRom = Next; Next += 0x10000; + PrehisleADPCMSamples = Next; Next += 0x20000; + + RamStart = Next; + + PrehisleRam = Next; Next += 0x04000; + PrehisleVideoRam = Next; Next += 0x00800; + PrehisleSpriteRam = Next; Next += 0x00800; + PrehisleVideo2Ram = Next; Next += 0x04000; + PrehislePaletteRam = Next; Next += 0x00800; + PrehisleZ80Ram = Next; Next += 0x00800; + + RamEnd = Next; + + PrehisleTextTiles = Next; Next += (1024 * 8 * 8); + PrehisleSprites = Next; Next += (5120 * 16 * 16); + PrehisleBack1Tiles = Next; Next += (2048 * 16 * 16); + PrehisleBack2Tiles = Next; Next += (2048 * 16 * 16); + PrehislePalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 512, 516, 520, 524, 528, 532, 536, 540 }; +static INT32 TileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 }; + +// Driver Init and Exit Functions +INT32 PrehisleInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + PrehisleTempGfx = (UINT8*)BurnMalloc(0xa0000); + + // Load and byte-swap 68000 Program roms + nRet = BurnLoadRom(PrehisleRom + 0x00001, 0, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(PrehisleRom + 0x00000, 1, 2); if (nRet != 0) return 1; + + // Load and decode Text Tiles rom + memset(PrehisleTempGfx, 0, 0xa0000); + nRet = BurnLoadRom(PrehisleTempGfx, 2, 1); if (nRet != 0) return 1; + GfxDecode(1024, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, PrehisleTempGfx, PrehisleTextTiles); + + // Load and decode Background2 Tile rom + memset(PrehisleTempGfx, 0, 0xa0000); + nRet = BurnLoadRom(PrehisleTempGfx, 3, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, PrehisleTempGfx, PrehisleBack2Tiles); + + // Load and decode Background1 Tile rom + memset(PrehisleTempGfx, 0, 0xa0000); + nRet = BurnLoadRom(PrehisleTempGfx, 4, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, PrehisleTempGfx, PrehisleBack1Tiles); + + // Load and decode Sprite roms + memset(PrehisleTempGfx, 0, 0xa0000); + nRet = BurnLoadRom(PrehisleTempGfx + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(PrehisleTempGfx + 0x80000, 6, 1); if (nRet != 0) return 1; + GfxDecode(5120, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, PrehisleTempGfx, PrehisleSprites); + + BurnFree(PrehisleTempGfx); + + // Load Background2 Tilemap rom + nRet = BurnLoadRom(PrehisleTileMapRom, 7, 1); if (nRet != 0) return 1; + + // Load Z80 Program rom + nRet = BurnLoadRom(PrehisleZ80Rom, 8, 1); if (nRet != 0) return 1; + + // Load ADPCM Samples + nRet = BurnLoadRom(PrehisleADPCMSamples, 9, 1); if (nRet != 0) return 1; + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(PrehisleRom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(PrehisleRam , 0x070000, 0x073fff, SM_RAM); + SekMapMemory(PrehisleVideoRam , 0x090000, 0x0907ff, SM_RAM); + SekMapMemory(PrehisleSpriteRam , 0x0a0000, 0x0a07ff, SM_RAM); + SekMapMemory(PrehisleVideo2Ram , 0x0b0000, 0x0b3fff, SM_RAM); + SekMapMemory(PrehislePaletteRam, 0x0d0000, 0x0d07ff, SM_RAM); + SekSetReadWordHandler(0, PrehisleReadWord); + SekSetWriteWordHandler(0, PrehisleWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, PrehisleZ80Rom); + ZetMapArea(0x0000, 0xefff, 2, PrehisleZ80Rom); + ZetMapArea(0xf000, 0xf7ff, 0, PrehisleZ80Ram); + ZetMapArea(0xf000, 0xf7ff, 1, PrehisleZ80Ram); + ZetMapArea(0xf000, 0xf7ff, 2, PrehisleZ80Ram); + ZetMemEnd(); + ZetSetReadHandler(PrehisleZ80Read); + ZetSetInHandler(PrehisleZ80PortRead); + ZetSetOutHandler(PrehisleZ80PortWrite); + ZetClose(); + + BurnYM3812Init(4000000, &prehisleFMIRQHandler, &prehisleSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, PrehisleADPCMSamples); + + GenericTilesInit(); + + // Reset the driver + PrehisleDoReset(); + + return 0; +} + +INT32 PrehisleExit() +{ + BurnYM3812Exit(); + UPD7759Exit(); + + SekExit(); + ZetExit(); + + GenericTilesExit(); + + BurnFree(Mem); + + return 0; +} + +// Graphics Emulation +void PrehisleRenderBack2TileLayer() +{ + INT32 TileBase, mx, my, Tile, Colour, Scrollx, Scrolly, x, y, Flipx; + + TileBase = ((VidControl[3] >> 4) & 0x3ff) * 32; + TileBase &= 0x7fff; + Scrollx = -(VidControl[3] & 0x0f); + Scrolly = -VidControl[2]; + + for (mx = 0; mx < 17; mx++) { + for (my = 0; my < 32; my++) { + Tile = (PrehisleTileMapRom[2 * TileBase + 0] << 8) + PrehisleTileMapRom[2 * TileBase + 1]; + Colour = Tile >> 12; + Flipx = Tile & 0x800; + x = 16 * mx + Scrollx; + y = (16 * my + Scrolly) & 0x1ff; + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + if (!Flipx) { + Render16x16Tile(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 768, PrehisleBack2Tiles); + } else { + Render16x16Tile_FlipX(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 768, PrehisleBack2Tiles); + } + } else { + if (!Flipx) { + Render16x16Tile_Clip(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 768, PrehisleBack2Tiles); + } else { + Render16x16Tile_FlipX_Clip(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 768, PrehisleBack2Tiles); + } + } + + TileBase ++; + if (TileBase == 0x8000) TileBase = 0; + } + } +} + +void PrehisleRenderBack1TileLayer() +{ + INT32 TileBase, mx, my, Tile, Colour, Scrollx, Scrolly, x, y, Flipy; + + TileBase = ((VidControl[1] >> 4) & 0xff) * 32; + TileBase &= 0x1fff; + Scrollx = -(VidControl[1] & 0x0f); + Scrolly = -VidControl[0]; + + for (mx = 0; mx < 17; mx++) { + for (my = 0; my < 32; my++) { + Tile = (PrehisleVideo2Ram[2 * TileBase + 1] << 8) + PrehisleVideo2Ram[2 * TileBase + 0]; + Colour = Tile >> 12; + Flipy = Tile & 0x800; + x = 16 * mx + Scrollx; + y = (16 * my + Scrolly) & 0x1ff; + y -= 16; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + if (!Flipy) { + Render16x16Tile_Mask(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 0x0f, 512, PrehisleBack1Tiles); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 0x0f, 512, PrehisleBack1Tiles); + } + } else { + if (!Flipy) { + Render16x16Tile_Mask_Clip(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 0x0f, 512, PrehisleBack1Tiles); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile & 0x7ff, x, y, Colour, 4, 0x0f, 512, PrehisleBack1Tiles); + } + } + + TileBase ++; + if (TileBase == 0x2000) TileBase = 0; + } + } +} + +void PrehisleRenderSpriteLayer() +{ + INT32 offs; + + for (offs = 0; offs < 0x800; offs += 8) { + INT32 x, y, Sprite, Colour, Flipx, Flipy; + + y = (PrehisleSpriteRam[offs + 1] << 8) + PrehisleSpriteRam[offs + 0]; + if (y > 254) continue; + y -= 16; + x = (PrehisleSpriteRam[offs + 3] << 8) + PrehisleSpriteRam[offs + 2]; + if (x & 0x200) x = -(0xff - (x & 0xff)); + if (x > 256) continue; + + Sprite = (PrehisleSpriteRam[offs + 5] << 8) + PrehisleSpriteRam[offs + 4]; + Colour = ((PrehisleSpriteRam[offs + 7] << 8) + PrehisleSpriteRam[offs + 6]) >> 12; + Flipy = Sprite & 0x8000; + Flipx = Sprite & 0x4000; + Sprite &= 0x1fff; + if (Sprite > 0x13ff) Sprite = 0x13ff; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + if (!Flipy) { + if (!Flipx) { + Render16x16Tile_Mask(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } + } else { + if (!Flipx) { + Render16x16Tile_Mask_FlipY(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } + } + } else { + if (!Flipy) { + if (!Flipx) { + Render16x16Tile_Mask_Clip(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } + } else { + if (!Flipx) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Sprite, x, y, Colour, 4, 0x0f, 256, PrehisleSprites); + } + } + } + } +} + +void PrehisleRenderTextLayer() +{ + INT32 offs, mx, my, Colour, Tile, x, y; + + mx = -1; + my = 0; + for (offs = 0x000; offs < 0x800; offs+=2) { + mx++; + if (mx == 32) { + mx = 0; + my++; + } + Tile = (PrehisleVideoRam[offs + 1] << 8) + PrehisleVideoRam[offs + 0]; + Colour = Tile >> 12; + x = 8 * mx; + y = 8 * my; + y -= 16; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Tile & 0xfff, x, y, Colour, 4, 0x0f, 0, PrehisleTextTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Tile & 0xfff, x, y, Colour, 4, 0x0f, 0, PrehisleTextTiles); + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 12) & 0x0f; + g = (nColour >> 8) & 0x0f; + b = (nColour >> 4) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +INT32 PrehisleCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)PrehislePaletteRam, pd = PrehislePalette; i < 0x800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } + + return 0; +} + +void PrehisleDraw() +{ + PrehisleCalcPalette(); + PrehisleRenderBack2TileLayer(); + PrehisleRenderBack1TileLayer(); + PrehisleRenderSpriteLayer(); + PrehisleRenderTextLayer(); + BurnTransferCopy(PrehislePalette); +} + +// Frame Function +INT32 PrehisleFrame() +{ + INT32 nInterleave = 1; + + if (PrehisleReset) PrehisleDoReset(); + + PrehisleMakeInputs(); + + nCyclesTotal[0] = 9000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + UPD7759Update(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) PrehisleDraw(); + + return 0; +} + +// Scan RAM +static INT32 PrehisleScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + BurnYM3812Scan(nAction, pnMin); + UPD7759Scan(0, nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(PrehisleInput); + SCAN_VAR(PrehisleDip); + SCAN_VAR(ControlsInvert); + SCAN_VAR(VidControl); + SCAN_VAR(nCyclesDone); + } + + return 0; +} + +// Driver Declarations +struct BurnDriver BurnDrvPrehisle = { + "prehisle", NULL, NULL, NULL, "1989", + "Prehistoric Isle in 1930 (World)\0", NULL, "SNK", "Prehistoric Isle (SNK)", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, PrehisleRomInfo, PrehisleRomName, NULL, NULL, PrehisleInputInfo, PrehisleDIPInfo, + PrehisleInit, PrehisleExit, PrehisleFrame, NULL, PrehisleScan, + NULL, 0x800, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPrehislu = { + "prehisleu", "prehisle", NULL, NULL, "1989", + "Prehistoric Isle in 1930 (US)\0", NULL, "SNK of America", "Prehistoric Isle (SNK)", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, PrehisluRomInfo, PrehisluRomName, NULL, NULL, PrehisleInputInfo, PrehisleDIPInfo, + PrehisleInit, PrehisleExit, PrehisleFrame, NULL, PrehisleScan, + NULL, 0x800, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPrehislk = { + "prehislek", "prehisle", NULL, NULL, "1989", + "Prehistoric Isle in 1930 (Korea)\0", NULL, "SNK (Victor license)", "Prehistoric Isle (SNK)", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, PrehislkRomInfo, PrehislkRomName, NULL, NULL, PrehisleInputInfo, PrehisleDIPInfo, + PrehisleInit, PrehisleExit, PrehisleFrame, NULL, PrehisleScan, + NULL, 0x800, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGensitou = { + "gensitou", "prehisle", NULL, NULL, "1989", + "Genshi-Tou 1930's (Japan)\0", NULL, "SNK", "Prehistoric Isle (SNK)", + L"Genshi-Tou 1930's (Japan)\0\u539F\u59CB\u5CF6 1930's (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, GensitouRomInfo, GensitouRomName, NULL, NULL, PrehisleInputInfo, PrehisleDIPInfo, + PrehisleInit, PrehisleExit, PrehisleFrame, NULL, PrehisleScan, + NULL, 0x800, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_quizo.cpp b/src/burn/drivers/misc_pre90s/d_quizo.cpp new file mode 100644 index 00000000..3ad752c4 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_quizo.cpp @@ -0,0 +1,381 @@ +// FB Alpha Quiz Olympic driver module +// Based on MAME driver by Tomasz Slanina + +#include "burnint.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} +#include "bitswap.h" + +static UINT8 *Mem, *Rom, *Prom, *RomBank, *VideoRam, *framebuffer; +static UINT8 DrvJoy[8], DrvDips, DrvReset; +static UINT32 *Palette; +static UINT8 port60 = 0, port70 = 0, dirty = 0; + +static INT16* pAY8910Buffer[3]; +static INT16 *pFMBuffer = NULL; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy + 0, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy + 1, "p1 coin2" }, + {"Start 1", BIT_DIGITAL, DrvJoy + 2, "p1 start" }, + + {"P1 Button 1", BIT_DIGITAL, DrvJoy + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy + 4, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy + 5, "p1 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Tilt", BIT_DIGITAL, DrvJoy + 6, "tilt" }, + {"Dip Switches", BIT_DIPSWITCH, &DrvDips, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[] = +{ + // Defaults + {0x08, 0xFF, 0xFF, 0x40, NULL}, + + {0, 0xFE, 0, 2, "Test mode"}, + {0x08, 0x01, 0x08, 0x00, "Off"}, + {0x08, 0x01, 0x08, 0x08, "On"}, + {0, 0xFE, 0, 2, "Show the answer"}, // look the star + {0x08, 0x01, 0x10, 0x00, "Off"}, + {0x08, 0x01, 0x10, 0x10, "On"}, + {0, 0xFE, 0, 2, "Coin A"}, + {0x08, 0x01, 0x40, 0x00, "2 coins 1 credit"}, + {0x08, 0x01, 0x40, 0x40, "1 coin 1 credit"}, +}; + +STDDIPINFO(Drv) + + +static void quizo_palette_init() +{ + INT32 i; UINT8 *color_prom = Prom; + + for (i = 0;i < 16;i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = 0; + bit1 = (*color_prom >> 0) & 0x01; + bit2 = (*color_prom >> 1) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (*color_prom >> 2) & 0x01; + bit1 = (*color_prom >> 3) & 0x01; + bit2 = (*color_prom >> 4) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (*color_prom >> 5) & 0x01; + bit1 = (*color_prom >> 6) & 0x01; + bit2 = (*color_prom >> 7) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = (r << 16) | (g << 8) | b; + color_prom++; + } +} + + +static INT32 DrvDraw() +{ + INT32 x,y; + UINT32 *src = (UINT32 *)framebuffer; + + if(dirty) + { + for(y=0;y<200;y++) + { + for(x=0;x<80;x++) + { + INT32 data=VideoRam[y*80+x]; + INT32 data1=VideoRam[y*80+x+0x4000]; + INT32 pix; + + pix=(data&1)|(((data>>4)&1)<<1)|((data1&1)<<2)|(((data1>>4)&1)<<3); + src[((x*4+3) + (y * 320))] = Palette[pix&15]; + data>>=1; + data1>>=1; + pix=(data&1)|(((data>>4)&1)<<1)|((data1&1)<<2)|(((data1>>4)&1)<<3); + src[((x*4+2) + (y * 320))] = Palette[pix&15]; + data>>=1; + data1>>=1; + pix=(data&1)|(((data>>4)&1)<<1)|((data1&1)<<2)|(((data1>>4)&1)<<3); + src[((x*4+1) + (y * 320))] = Palette[pix&15]; + data>>=1; + data1>>=1; + pix=(data&1)|(((data>>4)&1)<<1)|((data1&1)<<2)|(((data1>>4)&1)<<3); + src[((x*4+0) + (y * 320))] = Palette[pix&15]; + } + } + } + dirty = 0; + + for (x = 0; x < 320 * 200; x++) { + PutPix(pBurnDraw + x * nBurnBpp, BurnHighCol(src[x]>>16, src[x]>>8, src[x], 0)); + } + + return 0; +} + + +void port60_w(UINT16, UINT8 data) +{ + static const UINT8 rombankLookup[]={ 2, 3, 4, 4, 4, 4, 4, 5, 0, 1}; + + if (data > 9) + { + data=0; + } + + port60 = data; + + ZetMapArea(0x8000, 0xbfff, 0, RomBank + rombankLookup[data] * 0x4000); + ZetMapArea(0x8000, 0xbfff, 2, RomBank + rombankLookup[data] * 0x4000); +} + +void __fastcall quizo_write(UINT16 a, UINT8 data) +{ + if (a >= 0xc000) { + INT32 bank = (port70 & 8) ? 1 : 0; + VideoRam[(a & 0x3fff) + bank * 0x4000] = data; + dirty=1; + return; + } +} + +void __fastcall quizo_out_port(UINT16 a, UINT8 d) +{ + switch (a & 0xff) + { + case 0x50: + AY8910Write(0, 0, d); + break; + + case 0x51: + AY8910Write(0, 1, d); + break; + + case 0x60: + port60_w(0, d); + break; + + case 0x70: + port70 = d; + break; + } +} + +UINT8 __fastcall quizo_in_port(UINT16 a) +{ + switch (a & 0xff) + { + case 0x00: // input port 0 + return (DrvJoy[0] | (DrvJoy[1] << 2) | (DrvJoy[6] << 3) | (DrvJoy[2] << 4)) ^ 0x18; + + case 0x10: // input port 1 + return (DrvJoy[3] | (DrvJoy[4] << 1) | (DrvJoy[5] << 2)) ^ 0xff; + + case 0x40: // input port 2 + return DrvDips; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + dirty = 1; + port70 = port60 = 0; + + DrvReset = 0; + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + memset (Rom + 0x4000, 0, 0x0400); + memset (VideoRam, 0, 0x8000); + memset (framebuffer, 0, 320 * 200 * 4); + + return 0; +} + + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x30000 + 0x20 + (0x10 * sizeof(INT32)) + 0x3e800); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)BurnMalloc (nBurnSoundLen * 3 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom = Mem + 0x00000; + RomBank = Mem + 0x10000; + VideoRam = Mem + 0x28000; + Prom = Mem + 0x30000; + Palette = (UINT32*)(Mem + 0x30020); + framebuffer = Mem + 0x30060; + + if (BurnLoadRom(Rom, 0, 1)) return 1; + memcpy (Rom, Rom + 0x4000, 0x4000); + + if (BurnLoadRom(RomBank + 0x00000, 1, 1)) return 1; + if (BurnLoadRom(RomBank + 0x08000, 2, 1)) return 1; + if (BurnLoadRom(RomBank + 0x10000, 3, 1)) return 1; + + if (BurnLoadRom(Prom, 4, 1)) return 1; + + quizo_palette_init(); + + ZetInit(1); + ZetOpen(0); + ZetSetWriteHandler(quizo_write); + ZetSetInHandler(quizo_in_port); + ZetSetOutHandler(quizo_out_port); + ZetMapArea(0x0000, 0x3fff, 0, Rom + 0x0000); + ZetMapArea(0x0000, 0x3fff, 2, Rom + 0x0000); + ZetMapArea(0x4000, 0x47ff, 0, Rom + 0x4000); + ZetMapArea(0x4000, 0x47ff, 1, Rom + 0x4000); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + AY8910Init(0, 1342329, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) DrvDoReset(); + + INT32 nSoundBufferPos = 0; + + ZetOpen(0); + ZetRun(4000000 / 60); + ZetRaiseIrq(1); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + + +static INT32 DrvExit() +{ + Mem = Rom = Prom = RomBank = VideoRam = framebuffer = NULL; + Palette = NULL; + pFMBuffer = NULL; + AY8910Exit(0); + ZetExit(); + + BurnFree (Mem); + BurnFree (pFMBuffer); + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = VideoRam; + ba.nLen = 0x08000; + ba.szName = "Video Ram"; + BurnAcb(&ba); + + ba.Data = Rom + 0x4000; + ba.nLen = 0x00400; + ba.szName = "Main Ram"; + BurnAcb(&ba); + + ba.Data = framebuffer; + ba.nLen = 320 * 200 * 4; + ba.szName = "Main Ram"; + BurnAcb(&ba); + + ZetScan(nAction); // Scan Z80 + AY8910Scan(nAction, pnMin); // Scan AY8910 + + // Scan critical driver variables + SCAN_VAR(port60); + SCAN_VAR(port70); + SCAN_VAR(dirty); + + port60_w(0, port60); + } + + return 0; +} + + +// Quiz Olympic + +static struct BurnRomInfo quizoRomDesc[] = { + { "rom1", 0x8000, 0x6731735f, BRF_ESS | BRF_PRG }, // 0 Z80 code + + { "rom2", 0x8000, 0xa700eb30, BRF_ESS | BRF_PRG }, // 1 Z80 code banks + { "rom3", 0x8000, 0xd344f97e, BRF_ESS | BRF_PRG }, // 2 + { "rom4", 0x8000, 0xab1eb174, BRF_ESS | BRF_PRG }, // 3 + + { "82s123", 0x0020, 0xc3f15914, BRF_GRA }, // 4 Color Prom +}; + +STD_ROM_PICK(quizo) +STD_ROM_FN(quizo) + +struct BurnDriver BurnDrvQuizo = { + "quizo", NULL, NULL, NULL, "1985", + "Quiz Olympic\0", NULL, "Seoul Coin Corp.", "Miscellaneous", + L"\uD034\uC988\uC62C\uB9BC\uD53D\0Quiz Olympic\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_PRE90S, GBF_QUIZ, 0, + NULL, quizoRomInfo, quizoRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, NULL, 0x10, + 320, 200, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_rallyx.cpp b/src/burn/drivers/misc_pre90s/d_rallyx.cpp new file mode 100644 index 00000000..6bbac1c7 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_rallyx.cpp @@ -0,0 +1,1534 @@ +#include "tiles_generic.h" +#include "namco_snd.h" +#include "samples.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0, 0, 0}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvRadarAttrRam = NULL; +static UINT8 *DrvPromPalette = NULL; +static UINT8 *DrvPromLookup = NULL; +static UINT8 *DrvPromVidLayout = NULL; +static UINT8 *DrvPromVidTiming = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvDots = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvCPUFireIRQ; +static UINT8 DrvCPUIRQVector; +static UINT8 xScroll; +static UINT8 yScroll; +static UINT8 DrvLastBang; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo DrvInputList[] = +{ + { "Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + { "Start 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 start" }, + { "Coin 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 coin" }, + { "Start 2" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 start" }, + + { "Up" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 up" }, + { "Down" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 down" }, + { "Left" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 left" }, + { "Right" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 right" }, + { "Fire 1" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 fire 1" }, + + { "Up (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 up" }, + { "Down (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 down" }, + { "Left (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 left" }, + { "Right (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 right" }, + { "Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 fire 1" }, + + { "Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + { "Service" , BIT_DIGITAL , DrvInputPort0 + 0, "service" }, + { "Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + { "Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo JunglerInputList[] = +{ + { "Coin 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 coin" }, + { "Start 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 start" }, + { "Coin 2" , BIT_DIGITAL , DrvInputPort0 + 6, "p2 coin" }, + { "Start 2" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 start" }, + + { "Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" }, + { "Down" , BIT_DIGITAL , DrvInputPort2 + 7, "p1 down" }, + { "Left" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 left" }, + { "Right" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 right" }, + { "Fire 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 fire 1" }, + + { "Up (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" }, + { "Down (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" }, + { "Left (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 left" }, + { "Right (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 right" }, + { "Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 fire 1" }, + + { "Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + { "Service" , BIT_DIGITAL , DrvInputPort0 + 2, "service" }, + { "Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, +}; + +STDINPUTINFO(Jungler) + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = 0xff; + DrvInput[1] = 0xfe; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] -= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + } +} + +static inline void JunglerMakeInputs() +{ + // Reset Inputs + DrvInput[0] = 0xff; + DrvInput[1] = 0xff; + DrvInput[2] = 0xff; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] -= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + DrvInput[2] -= (DrvInputPort1[i] & 1) << i; + } +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0x01, NULL }, + {0x11, 0xff, 0xff, 0xcb, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Cocktail" }, + {0x10, 0x01, 0x01, 0x01, "Upright" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, // This is conditional on difficulty + {0x11, 0x01, 0x06, 0x02, "15000" }, + {0x11, 0x01, 0x06, 0x04, "30000" }, + {0x11, 0x01, 0x06, 0x06, "40000" }, + {0x11, 0x01, 0x06, 0x00, "None" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x11, 0x01, 0x38, 0x10, "1 Car, Medium" }, + {0x11, 0x01, 0x38, 0x28, "1 Car, Hard" }, + {0x11, 0x01, 0x38, 0x00, "2 Cars, Easy" }, + {0x11, 0x01, 0x38, 0x18, "2 Cars, Medium" }, + {0x11, 0x01, 0x38, 0x30, "2 Cars, Hard" }, + {0x11, 0x01, 0x38, 0x08, "3 Cars, Easy" }, + {0x11, 0x01, 0x38, 0x20, "3 Cars, Medium" }, + {0x11, 0x01, 0x38, 0x38, "3 Cars, Hard" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + {0x11, 0x01, 0xc0, 0x00, "Freeplay" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo JunglerDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0xbf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x10, 0x01, 0x07, 0x01, "4 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x02, "3 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x03, "2 Coins 1 Play" }, + {0x10, 0x01, 0x07, 0x00, "4 Coins 3 Plays" }, + {0x10, 0x01, 0x07, 0x07, "1 Coin 1 Play" }, + {0x10, 0x01, 0x07, 0x06, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x07, 0x05, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x07, 0x04, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x10, 0x01, 0x38, 0x08, "4 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x10, "3 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x18, "2 Coins 1 Play" }, + {0x10, 0x01, 0x38, 0x00, "4 Coins 3 Plays" }, + {0x10, 0x01, 0x38, 0x38, "1 Coin 1 Play" }, + {0x10, 0x01, 0x38, 0x30, "1 Coin 2 Plays" }, + {0x10, 0x01, 0x38, 0x28, "1 Coin 3 Plays" }, + {0x10, 0x01, 0x38, 0x20, "1 Coin 4 Plays" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x40, 0x40, "Cocktail" }, + {0x10, 0x01, 0x40, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Test Mode (255 lives)" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Jungler) + +static struct BurnRomInfo RallyxRomDesc[] = { + { "1b", 0x01000, 0x5882700d, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "rallyxn.1e", 0x01000, 0xed1eba2b, BRF_ESS | BRF_PRG }, // 1 + { "rallyxn.1h", 0x01000, 0x4f98dd1c, BRF_ESS | BRF_PRG }, // 2 + { "rallyxn.1k", 0x01000, 0x9aacccf0, BRF_ESS | BRF_PRG }, // 3 + + { "8e", 0x01000, 0x277c1de5, BRF_GRA }, // 4 Characters & Sprites + + { "rx1-6.8m", 0x00100, 0x3c16f62c, BRF_GRA }, // 5 Dots + + { "rx1-1.11n", 0x00020, 0xc7865434, BRF_GRA }, // 6 Palette PROM + { "rx1-7.8p", 0x00100, 0x834d4fda, BRF_GRA }, // 7 Lookup PROM + { "rx1-2.4n", 0x00020, 0x8f574815, BRF_GRA }, // 8 Video Layout PROM + { "rx1-3.7k", 0x00020, 0xb8861096, BRF_GRA }, // 9 Video Timing PROM + + { "rx1-5.3p", 0x00100, 0x4bad7017, BRF_SND }, // 10 Sound PROMs + { "rx1-4.2m", 0x00100, 0x77245b66, BRF_SND }, // 11 +}; + +STD_ROM_PICK(Rallyx) +STD_ROM_FN(Rallyx) + +static struct BurnRomInfo RallyxaRomDesc[] = { + { "rx1_prg_1.1b", 0x00800, 0xef9238db, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "rx1_prg_2.1c", 0x00800, 0x7cbeb656, BRF_ESS | BRF_PRG }, // 1 + { "rx1_prg_3.1d", 0x00800, 0x334b1042, BRF_ESS | BRF_PRG }, // 2 + { "rx1_prg_4.1e", 0x00800, 0xd6618add, BRF_ESS | BRF_PRG }, // 3 + { "rx1_prg_5.bin", 0x00800, 0x3d69f24e, BRF_ESS | BRF_PRG }, // 4 + { "rx1_prg_6.bin", 0x00800, 0xe9740f16, BRF_ESS | BRF_PRG }, // 5 + { "rx1_prg_7.1k", 0x00800, 0x843109f2, BRF_ESS | BRF_PRG }, // 6 + { "rx1_prg_8.1l", 0x00800, 0x9b846ec9, BRF_ESS | BRF_PRG }, // 7 + + { "rx1_chg_1.8e", 0x00800, 0x1fff38a4, BRF_GRA }, // 8 Characters & Sprites + { "rx1_chg_2.8d", 0x00800, 0x68dff552, BRF_GRA }, // 9 + + { "rx1-6.8m", 0x00100, 0x3c16f62c, BRF_GRA }, // 10 Dots + + { "rx1-1.11n", 0x00020, 0xc7865434, BRF_GRA }, // 11 Palette PROM + { "rx1-7.8p", 0x00100, 0x834d4fda, BRF_GRA }, // 12 Lookup PROM + { "rx1-2.4n", 0x00020, 0x8f574815, BRF_GRA }, // 13 Video Layout PROM + { "rx1-3.7k", 0x00020, 0xb8861096, BRF_GRA }, // 14 Video Timing PROM + + { "rx1-5.3p", 0x00100, 0x4bad7017, BRF_SND }, // 15 Sound PROMs + { "rx1-4.2m", 0x00100, 0x77245b66, BRF_SND }, // 16 +}; + +STD_ROM_PICK(Rallyxa) +STD_ROM_FN(Rallyxa) + +static struct BurnRomInfo RallyxmRomDesc[] = { + { "1b", 0x01000, 0x5882700d, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "1e", 0x01000, 0x786585ec, BRF_ESS | BRF_PRG }, // 1 + { "1h", 0x01000, 0x110d7dcd, BRF_ESS | BRF_PRG }, // 2 + { "1k", 0x01000, 0x473ab447, BRF_ESS | BRF_PRG }, // 3 + + { "8e", 0x01000, 0x277c1de5, BRF_GRA }, // 4 Characters & Sprites + + { "rx1-6.8m", 0x00100, 0x3c16f62c, BRF_GRA }, // 5 Dots + + { "rx1-1.11n", 0x00020, 0xc7865434, BRF_GRA }, // 6 Palette PROM + { "rx1-7.8p", 0x00100, 0x834d4fda, BRF_GRA }, // 7 Lookup PROM + { "rx1-2.4n", 0x00020, 0x8f574815, BRF_GRA }, // 8 Video Layout PROM + { "rx1-3.7k", 0x00020, 0xb8861096, BRF_GRA }, // 9 Video Timing PROM + + { "rx1-5.3p", 0x00100, 0x4bad7017, BRF_SND }, // 10 Sound PROMs + { "rx1-4.2m", 0x00100, 0x77245b66, BRF_SND }, // 11 +}; + +STD_ROM_PICK(Rallyxm) +STD_ROM_FN(Rallyxm) + +static struct BurnRomInfo NrallyxRomDesc[] = { + { "nrx_prg1.1d", 0x01000, 0xba7de9fc, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code + { "nrx_prg2.1e", 0x01000, 0xeedfccae, BRF_ESS | BRF_PRG }, // 1 + { "nrx_prg3.1k", 0x01000, 0xb4d5d34a, BRF_ESS | BRF_PRG }, // 2 + { "nrx_prg4.1l", 0x01000, 0x7da5496d, BRF_ESS | BRF_PRG }, // 3 + + { "nrx_chg1.8e", 0x00800, 0x1fff38a4, BRF_GRA }, // 4 Characters & Sprites + { "nrx_chg2.8d", 0x00800, 0x85d9fffd, BRF_GRA }, // 5 + + { "rx1-6.8m", 0x00100, 0x3c16f62c, BRF_GRA }, // 6 Dots + + { "nrx1-1.11n", 0x00020, 0xa0a49017, BRF_GRA }, // 7 Palette PROM + { "nrx1-7.8p", 0x00100, 0x4e46f485, BRF_GRA }, // 8 Lookup PROM + { "rx1-2.4n", 0x00020, 0x8f574815, BRF_GRA }, // 9 Video Layout PROM + { "rx1-3.7k", 0x00020, 0xb8861096, BRF_GRA }, // 10 Video Timing PROM + + { "rx1-5.3p", 0x00100, 0x4bad7017, BRF_SND }, // 11 Sound PROMs + { "rx1-4.2m", 0x00100, 0x77245b66, BRF_SND }, // 12 +}; + +STD_ROM_PICK(Nrallyx) +STD_ROM_FN(Nrallyx) + + + + +static struct BurnRomInfo JunglerRomDesc[] = { + { "jungr1", 0x01000, 0x5bd6ad15, BRF_ESS | BRF_PRG }, // 0 Z80 Program Code #1 + { "jungr2", 0x01000, 0xdc99f1e3, BRF_ESS | BRF_PRG }, // 1 + { "jungr3", 0x01000, 0x3dcc03da, BRF_ESS | BRF_PRG }, // 2 + { "jungr4", 0x01000, 0xf92e9940, BRF_ESS | BRF_PRG }, // 3 + + { "1b", 0x01000, 0xf86999c3, BRF_ESS | BRF_PRG }, // 4 Z80 Program Code #2 + + { "5k", 0x00800, 0x924262bf, BRF_GRA }, // 5 Characters & Sprites + { "5m", 0x00800, 0x131a08ac, BRF_GRA }, // 6 + + { "82s129.10g", 0x00100, 0xc59c51b7, BRF_GRA }, // 7 Dots + + { "18s030.8b", 0x00020, 0x55a7e6d1, BRF_GRA }, // 8 Palette PROM + { "tbp24s10.9d", 0x00100, 0xd223f7b8, BRF_GRA }, // 9 Lookup PROM + { "18s030.7a", 0x00020, 0x8f574815, BRF_GRA }, // 10 Video Layout PROM + { "6331-1.10a", 0x00020, 0xb8861096, BRF_GRA }, // 11 Video Timing PROM +}; + +STD_ROM_PICK(Jungler) +STD_ROM_FN(Jungler) + +static struct BurnSampleInfo RallyxSampleDesc[] = { + { "bang.wav", SAMPLE_NOLOOP }, + { "", 0 } +}; + +STD_SAMPLE_PICK(Rallyx) +STD_SAMPLE_FN(Rallyx) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x04000; + DrvPromPalette = Next; Next += 0x00020; + DrvPromLookup = Next; Next += 0x00100; + DrvPromVidLayout = Next; Next += 0x00020; + DrvPromVidTiming = Next; Next += 0x00020; + NamcoSoundProm = Next; Next += 0x00100; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvRadarAttrRam = Next; Next += 0x00010; + + RamEnd = Next; + + DrvChars = Next; Next += 0x100 * 8 * 8; + DrvSprites = Next; Next += 0x040 * 16 * 16; + DrvDots = Next; Next += 0x008 * 4 * 4; + DrvPalette = (UINT32*)Next; Next += 260 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 JunglerMemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x08000; + DrvZ80Rom2 = Next; Next += 0x02000; + DrvPromPalette = Next; Next += 0x00020; + DrvPromLookup = Next; Next += 0x00100; + DrvPromVidLayout = Next; Next += 0x00020; + DrvPromVidTiming = Next; Next += 0x00020; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x00800; + DrvZ80Ram2 = Next; Next += 0x00400; + DrvVideoRam = Next; Next += 0x01000; + DrvRadarAttrRam = Next; Next += 0x00010; + + RamEnd = Next; + + DrvChars = Next; Next += 0x100 * 8 * 8; + DrvSprites = Next; Next += 0x040 * 16 * 16; + DrvDots = Next; Next += 0x008 * 4 * 4; + DrvPalette = (UINT32*)Next; Next += 324 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnSampleReset(); + + DrvCPUFireIRQ = 0; + DrvCPUIRQVector = 0; + xScroll = 0; + yScroll = 0; + DrvLastBang = 0; + + return 0; +} + +static INT32 JunglerDoReset() +{ + ZetOpen(0); + ZetReset(); + ZetClose(); + + DrvCPUFireIRQ = 0; + DrvCPUIRQVector = 0; + xScroll = 0; + yScroll = 0; + + return 0; +} + +UINT8 __fastcall RallyxZ80ProgRead(UINT16 a) +{ + switch (a) { + case 0xa000: { + return DrvInput[0]; + } + + case 0xa080: { + return DrvInput[1] | DrvDip[0]; + } + + case 0xa100: { + return DrvDip[1]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04x\n"), a); + } + } + + return 0; +} + +void __fastcall RallyxZ80ProgWrite(UINT16 a, UINT8 d) +{ + if (a >= 0xa100 && a <= 0xa11f) { NamcoSoundWrite(a - 0xa100, d); return; } + + switch (a) { + case 0xa080: { + // watchdog write + return; + } + + case 0xa130: { + xScroll = d; + return; + } + + case 0xa140: { + yScroll = d; + return; + } + + case 0xa170: { + // NOP + return; + } + + case 0xa180: { + UINT8 Bit = d & 0x01; + if (Bit == 0 && DrvLastBang != 0) { + BurnSamplePlay(0); + } + DrvLastBang = Bit; + return; + } + + case 0xa181: { + DrvCPUFireIRQ = d & 0x01; + if (!DrvCPUFireIRQ) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return; + } + + case 0xa182: { + // sound on + return; + } + + case 0xa183: { + // flip screen !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + return; + } + + case 0xa184: { + // lamp + return; + } + + case 0xa185: { + // lamp + return; + } + + case 0xa186: { + // coin lockout + return; + } + + case 0xa187: { + // coin counter + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04x, %02x\n"), a, d); + } + } +} + +UINT8 __fastcall RallyxZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall RallyxZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DrvCPUIRQVector = d; + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall JunglerZ80ProgRead1(UINT16 a) +{ + switch (a) { + case 0xa000: { + return DrvInput[0]; + } + + case 0xa080: { + return DrvInput[1]; + } + + case 0xa100: { + return DrvInput[2]; + } + + case 0xa180: { + return DrvDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read %04x\n"), a); + } + } + + return 0; +} + +void __fastcall JunglerZ80ProgWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xa080: { + // watchdog write + return; + } + + case 0xa130: { + xScroll = d; + return; + } + + case 0xa140: { + yScroll = d; + return; + } + + case 0xa181: { + DrvCPUFireIRQ = d & 0x01; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write %04x, %02x\n"), a, d); + } + } +} + +UINT8 __fastcall JunglerZ80PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall JunglerZ80PortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall JunglerZ80ProgRead2(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read %04x\n"), a); + } + } + + return 0; +} + +void __fastcall JunglerZ80ProgWrite2(UINT16 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write %04x, %02x\n"), a, d); + } + } +} + +UINT8 __fastcall JunglerZ80PortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall JunglerZ80PortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[2] = { 0, 4 }; +static INT32 CharXOffsets[8] = { 64, 65, 66, 67, 0, 1, 2, 3 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 JunglerCharPlaneOffsets[2] = { 4, 0 }; +static INT32 SpritePlaneOffsets[2] = { 0, 4 }; +static INT32 SpriteXOffsets[16] = { 64, 65, 66, 67, 128, 129, 130, 131, 192, 193, 194, 195, 0, 1, 2, 3 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 256, 264, 272, 280, 288, 296, 304, 312 }; +static INT32 JunglerSpritePlaneOffsets[2] = { 4, 0 }; +static INT32 JunglerSpriteXOffsets[16] = { 64, 65, 66, 67, 0, 1, 2, 3, 192, 193, 194, 195, 128, 129, 130, 131 }; +static INT32 DotPlaneOffsets[2] = { 6, 7 }; +static INT32 DotXOffsets[4] = { 0, 8, 16, 24 }; +static INT32 DotYOffsets[4] = { 0, 32, 64, 96 }; + +static void MachineInit() +{ + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(RallyxZ80ProgRead); + ZetSetWriteHandler(RallyxZ80ProgWrite); + ZetSetInHandler(RallyxZ80PortRead); + ZetSetOutHandler(RallyxZ80PortWrite); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80Rom1); + ZetMapArea(0x8000, 0x8fff, 0, DrvVideoRam); + ZetMapArea(0x8000, 0x8fff, 1, DrvVideoRam); + ZetMapArea(0x8000, 0x8fff, 2, DrvVideoRam); + ZetMapArea(0x9800, 0x9fff, 0, DrvZ80Ram1); + ZetMapArea(0x9800, 0x9fff, 1, DrvZ80Ram1); + ZetMapArea(0x9800, 0x9fff, 2, DrvZ80Ram1); + ZetMapArea(0xa000, 0xa00f, 1, DrvRadarAttrRam); + ZetMemEnd(); + ZetClose(); + + NamcoSoundInit(18432000 / 6 / 32); + BurnSampleInit(80, 0); + + GenericTilesInit(); + + DrvDoReset(); +} + +static void JunglerMachineInit() +{ + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(JunglerZ80ProgRead1); + ZetSetWriteHandler(JunglerZ80ProgWrite1); + ZetSetInHandler(JunglerZ80PortRead1); + ZetSetOutHandler(JunglerZ80PortWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1); + ZetMapArea(0x8000, 0x8fff, 0, DrvVideoRam); + ZetMapArea(0x8000, 0x8fff, 1, DrvVideoRam); + ZetMapArea(0x8000, 0x8fff, 2, DrvVideoRam); + ZetMapArea(0x9800, 0x9fff, 0, DrvZ80Ram1); + ZetMapArea(0x9800, 0x9fff, 1, DrvZ80Ram1); + ZetMapArea(0x9800, 0x9fff, 2, DrvZ80Ram1); + ZetMapArea(0xa000, 0xa00f, 1, DrvRadarAttrRam); + ZetMapArea(0xa030, 0xa03f, 1, DrvRadarAttrRam); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + JunglerDoReset(); +} + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x01000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars and sprites + nRet = BurnLoadRom(DrvTempRom, 4, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(0x40, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the dots + memset(DrvTempRom, 0, 0x1000); + nRet = BurnLoadRom(DrvTempRom, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x08, 2, 4, 4, DotPlaneOffsets, DotXOffsets, DotYOffsets, 0x80, DrvTempRom, DrvDots); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromLookup, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidLayout, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidTiming, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(NamcoSoundProm, 10, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 DrvaInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x01000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00800, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01800, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02800, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03800, 7, 1); if (nRet != 0) return 1; + + // Load and decode the chars and sprites + nRet = BurnLoadRom(DrvTempRom + 0x0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0800, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(0x40, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the dots + memset(DrvTempRom, 0, 0x1000); + nRet = BurnLoadRom(DrvTempRom, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x08, 2, 4, 4, DotPlaneOffsets, DotXOffsets, DotYOffsets, 0x80, DrvTempRom, DrvDots); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromLookup, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidLayout, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidTiming, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(NamcoSoundProm, 15, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 NrallyxInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x01000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvTempRom, 0, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom1 + 0x0000, DrvTempRom + 0x0000, 0x800); + memcpy(DrvZ80Rom1 + 0x1000, DrvTempRom + 0x0800, 0x800); + nRet = BurnLoadRom(DrvTempRom, 1, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom1 + 0x0800, DrvTempRom + 0x0000, 0x800); + memcpy(DrvZ80Rom1 + 0x1800, DrvTempRom + 0x0800, 0x800); + nRet = BurnLoadRom(DrvTempRom, 2, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom1 + 0x2000, DrvTempRom + 0x0000, 0x800); + memcpy(DrvZ80Rom1 + 0x3000, DrvTempRom + 0x0800, 0x800); + nRet = BurnLoadRom(DrvTempRom, 3, 1); if (nRet != 0) return 1; + memcpy(DrvZ80Rom1 + 0x2800, DrvTempRom + 0x0000, 0x800); + memcpy(DrvZ80Rom1 + 0x3800, DrvTempRom + 0x0800, 0x800); + + // Load and decode the chars and sprites + memset(DrvTempRom, 0, 0x1000); + nRet = BurnLoadRom(DrvTempRom + 0x0000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x0800, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(0x40, 2, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the dots + memset(DrvTempRom, 0, 0x1000); + nRet = BurnLoadRom(DrvTempRom, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x08, 2, 4, 4, DotPlaneOffsets, DotXOffsets, DotYOffsets, 0x80, DrvTempRom, DrvDots); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromLookup, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidLayout, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidTiming, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(NamcoSoundProm, 11, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + MachineInit(); + + return 0; +} + +static INT32 JunglerInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + JunglerMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + JunglerMemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x01000); + + // Load Z80 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x01000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x02000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x03000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 Sound Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the chars and sprites + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00800, 6, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 2, 8, 8, JunglerCharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + GfxDecode(0x40, 2, 16, 16, JunglerSpritePlaneOffsets, JunglerSpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the dots + memset(DrvTempRom, 0, 0x1000); + nRet = BurnLoadRom(DrvTempRom, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x08, 2, 4, 4, DotPlaneOffsets, DotXOffsets, DotYOffsets, 0x80, DrvTempRom, DrvDots); + + // Load the PROMs + nRet = BurnLoadRom(DrvPromPalette, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromLookup, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidLayout, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvPromVidTiming, 11, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + JunglerMachineInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + NamcoSoundExit(); + BurnSampleExit(); + ZetExit(); + + BurnFree(Mem); + + DrvCPUFireIRQ = 0; + DrvCPUIRQVector = 0; + xScroll = 0; + yScroll = 0; + DrvLastBang = 0; + + return 0; +} + +#define MAX_NETS 3 +#define MAX_RES_PER_NET 18 +#define Combine2Weights(tab,w0,w1) ((int)(((tab)[0]*(w0) + (tab)[1]*(w1)) + 0.5)) +#define Combine3Weights(tab,w0,w1,w2) ((int)(((tab)[0]*(w0) + (tab)[1]*(w1) + (tab)[2]*(w2)) + 0.5)) + +static double ComputeResistorWeights(INT32 MinVal, INT32 MaxVal, double Scaler, INT32 Count1, const INT32 *Resistances1, double *Weights1, INT32 PullDown1, INT32 PullUp1, INT32 Count2, const INT32 *Resistances2, double *Weights2, INT32 PullDown2, INT32 PullUp2, INT32 Count3, const INT32 *Resistances3, double *Weights3, INT32 PullDown3, INT32 PullUp3) +{ + INT32 NetworksNum; + + INT32 ResCount[MAX_NETS]; + double r[MAX_NETS][MAX_RES_PER_NET]; + double w[MAX_NETS][MAX_RES_PER_NET]; + double ws[MAX_NETS][MAX_RES_PER_NET]; + INT32 r_pd[MAX_NETS]; + INT32 r_pu[MAX_NETS]; + + double MaxOut[MAX_NETS]; + double *Out[MAX_NETS]; + + INT32 i, j, n; + double Scale; + double Max; + + NetworksNum = 0; + for (n = 0; n < MAX_NETS; n++) { + INT32 Count, pd, pu; + const INT32 *Resistances; + double *Weights; + + switch (n) { + case 0: { + Count = Count1; + Resistances = Resistances1; + Weights = Weights1; + pd = PullDown1; + pu = PullUp1; + break; + } + + case 1: { + Count = Count2; + Resistances = Resistances2; + Weights = Weights2; + pd = PullDown2; + pu = PullUp2; + break; + } + + case 2: + default: { + Count = Count3; + Resistances = Resistances3; + Weights = Weights3; + pd = PullDown3; + pu = PullUp3; + break; + } + } + + if (Count > 0) { + ResCount[NetworksNum] = Count; + for (i = 0; i < Count; i++) { + r[NetworksNum][i] = 1.0 * Resistances[i]; + } + Out[NetworksNum] = Weights; + r_pd[NetworksNum] = pd; + r_pu[NetworksNum] = pu; + NetworksNum++; + } + } + + for (i = 0; i < NetworksNum; i++) { + double R0, R1, Vout, Dst; + + for (n = 0; n < ResCount[i]; n++) { + R0 = (r_pd[i] == 0) ? 1.0 / 1e12 : 1.0 / r_pd[i]; + R1 = (r_pu[i] == 0) ? 1.0 / 1e12 : 1.0 / r_pu[i]; + + for (j = 0; j < ResCount[i]; j++) { + if (j == n) { + if (r[i][j] != 0.0) R1 += 1.0 / r[i][j]; + } else { + if (r[i][j] != 0.0) R0 += 1.0 / r[i][j]; + } + } + + R0 = 1.0/R0; + R1 = 1.0/R1; + Vout = (MaxVal - MinVal) * R0 / (R1 + R0) + MinVal; + + Dst = (Vout < MinVal) ? MinVal : (Vout > MaxVal) ? MaxVal : Vout; + + w[i][n] = Dst; + } + } + + j = 0; + Max = 0.0; + for (i = 0; i < NetworksNum; i++) { + double Sum = 0.0; + + for (n = 0; n < ResCount[i]; n++) Sum += w[i][n]; + + MaxOut[i] = Sum; + if (Max < Sum) { + Max = Sum; + j = i; + } + } + + if (Scaler < 0.0) { + Scale = ((double)MaxVal) / MaxOut[j]; + } else { + Scale = Scaler; + } + + for (i = 0; i < NetworksNum; i++) { + for (n = 0; n < ResCount[i]; n++) { + ws[i][n] = w[i][n] * Scale; + (Out[i])[n] = ws[i][n]; + } + } + + return Scale; + +} + +static void DrvCalcPalette() +{ + static const INT32 ResistancesRG[3] = { 1000, 470, 220 }; + static const INT32 ResistancesB[2] = { 470, 220 }; + double rWeights[3], gWeights[3], bWeights[2]; + UINT32 Palette[32]; + UINT32 i; + + ComputeResistorWeights(0, 255, -1.0, 3, &ResistancesRG[0], rWeights, 0, 0, 3, &ResistancesRG[0], gWeights, 0, 0, 2, &ResistancesB[0], bWeights, 1000, 0); + + for (i = 0; i < 32; i++) { + INT32 Bit0, Bit1, Bit2; + INT32 r, g, b; + + Bit0 = (DrvPromPalette[i] >> 0) & 0x01; + Bit1 = (DrvPromPalette[i] >> 1) & 0x01; + Bit2 = (DrvPromPalette[i] >> 2) & 0x01; + r = Combine3Weights(rWeights, Bit0, Bit1, Bit2); + + /* green component */ + Bit0 = (DrvPromPalette[i] >> 3) & 0x01; + Bit1 = (DrvPromPalette[i] >> 4) & 0x01; + Bit2 = (DrvPromPalette[i] >> 5) & 0x01; + g = Combine3Weights(gWeights, Bit0, Bit1, Bit2); + + /* blue component */ + Bit0 = (DrvPromPalette[i] >> 6) & 0x01; + Bit1 = (DrvPromPalette[i] >> 7) & 0x01; + b = Combine2Weights(bWeights, Bit0, Bit1); + + Palette[i] = BurnHighCol(r, g, b, 0); + } + + for (i = 0; i < 256; i++) { + UINT8 PaletteEntry = DrvPromLookup[i] & 0x0f; + DrvPalette[i] = Palette[PaletteEntry]; + } + + for (i = 256; i < 260; i++) { + DrvPalette[i] = Palette[(i - 0x100) | 0x10]; + } +} + +#undef MAX_NETS +#undef MAX_RES_PER_NET +#undef Combine2Weights +#undef Combine3Weights + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Code = DrvVideoRam[TileIndex + 0x400 + 0x000]; + Colour = DrvVideoRam[TileIndex + 0x400 + 0x800]; + Flip = ((Colour >> 6) & 0x03) ^ 1; + xFlip = Flip & 0x01; + yFlip = Flip & 0x02; + Colour &= 0x3f; + + x = 8 * mx; + y = 8 * my; + + x -= xScroll; + y -= yScroll; + + x += 3; + y -= 16; + + if (x < -8) x += 256; + if (x > 247) x -= 256; + if (y < -8) y += 256; + + if (x < 224) { + if (x > 8 && x < 280 && y > 8 && y < 216) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_FlipX(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } + } + } + + TileIndex++; + } + } +} + +static void DrvRenderFgLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex, Flip, xFlip, yFlip; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 8; mx++) { + TileIndex = mx + (my << 5); + Code = DrvVideoRam[TileIndex + 0x000 + 0x000]; + Colour = DrvVideoRam[TileIndex + 0x000 + 0x800]; + Flip = ((Colour >> 6) & 0x03) ^ 1; + xFlip = Flip & 0x01; + yFlip = Flip & 0x02; + Colour &= 0x3f; + + x = 8 * mx; + y = 8 * my; + + y -= 16; + + x -= 32; + if (x < 0) x += 64; + + x += 224; + + if (x > 8 && x < 280 && y > 8 && y < 216) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_FlipX(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 2, 0, DrvChars); + } + } + } + } + } +} + +static void DrvRenderSprites(INT32 Displacement) +{ + UINT32 SpriteRamBase = 0x14; + UINT8 *SpriteRam = DrvVideoRam; + UINT8 *SpriteRam2 = DrvVideoRam + 0x800; + + for (UINT32 Offs = 0x20 - 2; Offs >= SpriteRamBase; Offs -= 2) { + INT32 sx = SpriteRam[Offs + 1] + ((SpriteRam2[Offs + 1] & 0x80) << 1) - Displacement; + INT32 sy = 241 - SpriteRam2[Offs] - Displacement; + INT32 Colour = SpriteRam2[Offs + 1] & 0x3f; + INT32 xFlip = SpriteRam[Offs] & 1; + INT32 yFlip = SpriteRam[Offs] & 2; + INT32 Code = (SpriteRam[Offs] & 0xfc) >> 2; + +// if (flip_screen_get(machine)) +// sx -= 2 * displacement; + + + sy -= 16; + + if (sx > 16 && sx < 272 && sy > 16 && sy < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 2, 0, 0, DrvSprites); + } + } + } + } +} + +static void DrvRenderBullets() +{ + UINT32 SpriteRamBase = 0x14; + UINT8 *RadarX = DrvVideoRam + 0x020; + UINT8 *RadarY = DrvVideoRam + 0x820; + + for (UINT32 Offs = SpriteRamBase; Offs < 0x20; Offs++) { + INT32 x, y, Code; + + x = RadarX[Offs] + ((~DrvRadarAttrRam[Offs & 0x0f] & 0x01) << 8); + y = 253 - RadarY[Offs]; + Code = ((DrvRadarAttrRam[Offs & 0x0f] & 0x0e) >> 1) ^ 0x07; + + y -= 16; + +// if (flip_screen_get(machine)) +// x -= 3; + +// if (transpen) +// drawgfx_transpen(bitmap,cliprect,machine->gfx[2], +// ((state->radarattr[offs & 0x0f] & 0x0e) >> 1) ^ 0x07, +// 0, +// 0,0, +// x,y, +// 3); +// else +// drawgfx_transtable(bitmap,cliprect,machine->gfx[2], +// ((state->radarattr[offs & 0x0f] & 0x0e) >> 1) ^ 0x07, +// 0, +// 0,0, +// x,y, +/// state->drawmode_table,machine->shadow_table); + + RenderCustomTile_Mask_Clip(pTransDraw, 4, 4, Code, x, y, 0, 2, 3, 0x100, DrvDots); + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSprites(1); + DrvRenderFgLayer(); + DrvRenderBullets(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = nBurnSoundLen; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = (18432000 / 6) / 60; + nCyclesDone[0] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1) && DrvCPUFireIRQ) { + ZetSetVector(DrvCPUIRQVector); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 JunglerFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) JunglerDoReset(); + + JunglerMakeInputs(); + +// INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = (18432000 / 6) / 60; + nCyclesTotal[1] = (14318180 / 8) / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == (nInterleave - 1) && DrvCPUFireIRQ) { + ZetNmi(); + } + ZetClose(); + +/* if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + nSoundBufferPos += nSegmentLength; + }*/ + } + +/* if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + BurnSampleRender(pSoundBuf, nSegmentLength); + } + }*/ + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029708; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + NamcoSoundScan(nAction, pnMin); + } + + return 0; +} + +struct BurnDriver BurnDrvRallyx = { + "rallyx", NULL, NULL, "rallyx", "1980", + "Rally X (32k Ver.?))\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, RallyxRomInfo, RallyxRomName, RallyxSampleInfo, RallyxSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 260, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRallyxa = { + "rallyxa", "rallyx", NULL, "rallyx", "1980", + "Rally X\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, RallyxaRomInfo, RallyxaRomName, RallyxSampleInfo, RallyxSampleName, DrvInputInfo, DrvDIPInfo, + DrvaInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 260, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRallyxm = { + "rallyxm", "rallyx", NULL, "rallyx", "1980", + "Rally X (Midway)\0", NULL, "Namco (Midway License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, RallyxmRomInfo, RallyxmRomName, RallyxSampleInfo, RallyxSampleName, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 260, 288, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNrallyx = { + "nrallyx", NULL, NULL, "rallyx", "1981", + "New Rally X\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, NrallyxRomInfo, NrallyxRomName, RallyxSampleInfo, RallyxSampleName, DrvInputInfo, DrvDIPInfo, + NrallyxInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 260, 288, 224, 4, 3 +}; + + + +struct BurnDriverD BurnDrvJungler = { + "jungler", NULL, NULL, NULL, "1981", + "Jungler\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, JunglerRomInfo, JunglerRomName, NULL, NULL, JunglerInputInfo, JunglerDIPInfo, + JunglerInit, DrvExit, JunglerFrame, NULL, DrvScan, + NULL, 324, 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_renegade.cpp b/src/burn/drivers/misc_pre90s/d_renegade.cpp new file mode 100644 index 00000000..e99775cb --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_renegade.cpp @@ -0,0 +1,1417 @@ +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "m6805_intf.h" +#include "m6809_intf.h" +#include "burn_ym3526.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvM6502Rom = NULL; +static UINT8 *DrvM6809Rom = NULL; +static UINT8 *DrvM68705Rom = NULL; +static UINT8 *DrvM68705Ram = NULL; +static UINT8 *DrvADPCMRom = NULL; +static UINT8 *DrvM6502Ram = NULL; +static UINT8 *DrvM6809Ram = NULL; +static UINT8 *DrvVideoRam1 = NULL; +static UINT8 *DrvVideoRam2 = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam1 = NULL; +static UINT8 *DrvPaletteRam2 = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvRomBank; +static UINT8 DrvVBlank; +static UINT8 DrvScrollX[2]; +static UINT8 DrvSoundLatch; + +static INT32 nCyclesTotal[3]; + +// MCU Simulation Variables +#define MCU_TYPE_NONE 0 +#define MCU_TYPE_RENEGADE 1 +#define MCU_TYPE_KUNIOKUN 2 + +#define MCU_BUFFER_MAX 6 +static UINT8 mcu_buffer[MCU_BUFFER_MAX]; +static UINT8 mcu_input_size; +static UINT8 mcu_output_byte; +static INT8 mcu_key; + +static INT32 mcu_type; +static const UINT8 *mcu_encrypt_table; +static INT32 mcu_encrypt_table_len; + +static INT32 DisableMCUEmulation = 0; + +// MCU Emulation Variables +static INT32 nSimulateMCU; +static INT32 MCUFromMain; +static INT32 MCUFromMcu; +static INT32 MCUMainSent; +static INT32 MCUMcuSent; +static UINT8 MCUDdrA; +static UINT8 MCUDdrB; +static UINT8 MCUDdrC; +static UINT8 MCUPortAOut; +static UINT8 MCUPortBOut; +static UINT8 MCUPortCOut; +static UINT8 MCUPortAIn; +static UINT8 MCUPortBIn; +static UINT8 MCUPortCIn; + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort2 + 7, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + + +STDINPUTINFO(Drv) + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = 0xff; + DrvInput[2] = 0x9c; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] -= (DrvInputPort0[i] & 1) << i; + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + DrvInput[2] -= (DrvInputPort2[i] & 1) << i; + } +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xbf, NULL }, + {0x15, 0xff, 0xff, 0x03, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x03, 0x00, "2 Coins 1 Play" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 1 Play" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0x0c, 0x00, "2 Coins 1 Play" }, + {0x14, 0x01, 0x0c, 0x0c, "1 Coin 1 Play" }, + {0x14, 0x01, 0x0c, 0x08, "1 Coin 2 Plays" }, + {0x14, 0x01, 0x0c, 0x04, "1 Coin 3 Plays" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x10, 0x10, "1" }, + {0x14, 0x01, 0x10, 0x00, "2" }, + + {0 , 0xfe, 0 , 4 , "Bonus" }, + {0x14, 0x01, 0x20, 0x20, "30k" }, + {0x14, 0x01, 0x20, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x40, 0x00, "Upright" }, + {0x14, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Normal" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Very Hard" }, +}; + +STDDIPINFO(Drv) + +static struct BurnRomInfo DrvRomDesc[] = { + { "nb-5.ic51", 0x08000, 0xba683ddf, BRF_ESS | BRF_PRG }, // 0 M6502 Program Code + { "na-5.ic52", 0x08000, 0xde7e7df4, BRF_ESS | BRF_PRG }, // 1 + + { "n0-5.ic13", 0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, // 2 M6809 Program Code + + { "nc-5.bin", 0x08000, 0x9adfaa5d, BRF_GRA }, // 3 Characters + + { "n1-5.ic1", 0x08000, 0x4a9f47f3, BRF_GRA }, // 4 Tiles + { "n6-5.ic28", 0x08000, 0xd62a0aa8, BRF_GRA }, // 5 + { "n7-5.ic27", 0x08000, 0x7ca5a532, BRF_GRA }, // 6 + { "n2-5.ic14", 0x08000, 0x8d2e7982, BRF_GRA }, // 7 + { "n8-5.ic26", 0x08000, 0x0dba31d3, BRF_GRA }, // 8 + { "n9-5.ic25", 0x08000, 0x5b621b6a, BRF_GRA }, // 9 + + { "nh-5.bin", 0x08000, 0xdcd7857c, BRF_GRA }, // 10 Sprites + { "nd-5.bin", 0x08000, 0x2de1717c, BRF_GRA }, // 11 + { "nj-5.bin", 0x08000, 0x0f96a18e, BRF_GRA }, // 12 + { "nn-5.bin", 0x08000, 0x1bf15787, BRF_GRA }, // 13 + { "ne-5.bin", 0x08000, 0x924c7388, BRF_GRA }, // 14 + { "nk-5.bin", 0x08000, 0x69499a94, BRF_GRA }, // 15 + { "ni-5.bin", 0x08000, 0x6f597ed2, BRF_GRA }, // 16 + { "nf-5.bin", 0x08000, 0x0efc8d45, BRF_GRA }, // 17 + { "nl-5.bin", 0x08000, 0x14778336, BRF_GRA }, // 18 + { "no-5.bin", 0x08000, 0x147dd23b, BRF_GRA }, // 19 + { "ng-5.bin", 0x08000, 0xa8ee3720, BRF_GRA }, // 20 + { "nm-5.bin", 0x08000, 0xc100258e, BRF_GRA }, // 21 + + { "n5-5.ic31", 0x08000, 0x7ee43a3c, BRF_GRA }, // 22 ADPCM + { "n4-5.ic32", 0x08000, 0x6557564c, BRF_GRA }, // 23 + { "n3-5.ic33", 0x08000, 0x78fd6190, BRF_GRA }, // 24 + + { "nz-5.ic97", 0x00800, 0x32e47560, BRF_ESS | BRF_PRG }, // 25 MCU +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "nb-01.bin", 0x08000, 0x93fcfdf5, BRF_ESS | BRF_PRG }, // 0 M6502 Program Code + { "ta18-11.bin", 0x08000, 0xf240f5cd, BRF_ESS | BRF_PRG }, // 1 + + { "n0-5.bin", 0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, // 2 M6809 Program Code + + { "ta18-25.bin", 0x08000, 0x9bd2bea3, BRF_GRA }, // 3 Characters + + { "ta18-01.bin", 0x08000, 0xdaf15024, BRF_GRA }, // 4 Tiles + { "ta18-06.bin", 0x08000, 0x1f59a248, BRF_GRA }, // 5 + { "n7-5.bin", 0x08000, 0x7ca5a532, BRF_GRA }, // 6 + { "ta18-02.bin", 0x08000, 0x994c0021, BRF_GRA }, // 7 + { "ta18-04.bin", 0x08000, 0x55b9e8aa, BRF_GRA }, // 8 + { "ta18-03.bin", 0x08000, 0x0475c99a, BRF_GRA }, // 9 + + { "ta18-20.bin", 0x08000, 0xc7d54139, BRF_GRA }, // 10 Sprites + { "ta18-24.bin", 0x08000, 0x84677d45, BRF_GRA }, // 11 + { "ta18-18.bin", 0x08000, 0x1c770853, BRF_GRA }, // 12 + { "ta18-14.bin", 0x08000, 0xaf656017, BRF_GRA }, // 13 + { "ta18-23.bin", 0x08000, 0x3fd19cf7, BRF_GRA }, // 14 + { "ta18-17.bin", 0x08000, 0x74c64c6e, BRF_GRA }, // 15 + { "ta18-19.bin", 0x08000, 0xc8795fd7, BRF_GRA }, // 16 + { "ta18-22.bin", 0x08000, 0xdf3a2ff5, BRF_GRA }, // 17 + { "ta18-16.bin", 0x08000, 0x7244bad0, BRF_GRA }, // 18 + { "ta18-13.bin", 0x08000, 0xb6b14d46, BRF_GRA }, // 19 + { "ta18-21.bin", 0x08000, 0xc95e009b, BRF_GRA }, // 20 + { "ta18-15.bin", 0x08000, 0xa5d61d01, BRF_GRA }, // 21 + + { "ta18-07.bin", 0x08000, 0x02e3f3ed, BRF_GRA }, // 22 ADPCM + { "ta18-08.bin", 0x08000, 0xc9312613, BRF_GRA }, // 23 + { "ta18-09.bin", 0x08000, 0x07ed4705, BRF_GRA }, // 24 + + { "mcu", 0x08000, 0x00000000, BRF_PRG | BRF_NODUMP }, // 25 MCU +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo DrvbRomDesc[] = { + { "ta18-10.bin", 0x08000, 0xa90cf44a, BRF_ESS | BRF_PRG }, // 0 M6502 Program Code + { "ta18-11.bin", 0x08000, 0xf240f5cd, BRF_ESS | BRF_PRG }, // 1 + + { "n0-5.bin", 0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, // 2 M6809 Program Code + + { "ta18-25.bin", 0x08000, 0x9bd2bea3, BRF_GRA }, // 3 Characters + + { "ta18-01.bin", 0x08000, 0xdaf15024, BRF_GRA }, // 4 Tiles + { "ta18-06.bin", 0x08000, 0x1f59a248, BRF_GRA }, // 5 + { "n7-5.bin", 0x08000, 0x7ca5a532, BRF_GRA }, // 6 + { "ta18-02.bin", 0x08000, 0x994c0021, BRF_GRA }, // 7 + { "ta18-04.bin", 0x08000, 0x55b9e8aa, BRF_GRA }, // 8 + { "ta18-03.bin", 0x08000, 0x0475c99a, BRF_GRA }, // 9 + + { "ta18-20.bin", 0x08000, 0xc7d54139, BRF_GRA }, // 10 Sprites + { "ta18-24.bin", 0x08000, 0x84677d45, BRF_GRA }, // 11 + { "ta18-18.bin", 0x08000, 0x1c770853, BRF_GRA }, // 12 + { "ta18-14.bin", 0x08000, 0xaf656017, BRF_GRA }, // 13 + { "ta18-23.bin", 0x08000, 0x3fd19cf7, BRF_GRA }, // 14 + { "ta18-17.bin", 0x08000, 0x74c64c6e, BRF_GRA }, // 15 + { "ta18-19.bin", 0x08000, 0xc8795fd7, BRF_GRA }, // 16 + { "ta18-22.bin", 0x08000, 0xdf3a2ff5, BRF_GRA }, // 17 + { "ta18-16.bin", 0x08000, 0x7244bad0, BRF_GRA }, // 18 + { "ta18-13.bin", 0x08000, 0xb6b14d46, BRF_GRA }, // 19 + { "ta18-21.bin", 0x08000, 0xc95e009b, BRF_GRA }, // 20 + { "ta18-15.bin", 0x08000, 0xa5d61d01, BRF_GRA }, // 21 + + { "ta18-07.bin", 0x08000, 0x02e3f3ed, BRF_GRA }, // 22 ADPCM + { "ta18-08.bin", 0x08000, 0xc9312613, BRF_GRA }, // 23 + { "ta18-09.bin", 0x08000, 0x07ed4705, BRF_GRA }, // 24 +}; + +STD_ROM_PICK(Drvb) +STD_ROM_FN(Drvb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvM6502Rom = Next; Next += 0x10000; + DrvM6809Rom = Next; Next += 0x08000; + DrvM68705Rom = Next; Next += 0x00800; + DrvADPCMRom = Next; Next += 0x20000; + + RamStart = Next; + + DrvM6502Ram = Next; Next += 0x01800; + DrvM6809Ram = Next; Next += 0x01000; + DrvM68705Ram = Next; Next += 0x00070; + DrvSpriteRam = Next; Next += 0x00800; + DrvVideoRam1 = Next; Next += 0x00800; + DrvVideoRam2 = Next; Next += 0x00800; + DrvPaletteRam1 = Next; Next += 0x00100; + DrvPaletteRam2 = Next; Next += 0x00100; + + RamEnd = Next; + + DrvChars = Next; Next += 0x0400 * 8 * 8; + DrvTiles = Next; Next += 0x0800 * 16 * 16; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvPalette = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static const UINT8 kuniokun_xor_table[0x2a] = +{ + 0x48, 0x8a, 0x48, 0xa5, 0x01, 0x48, 0xa9, 0x00, + 0x85, 0x01, 0xa2, 0x10, 0x26, 0x10, 0x26, 0x11, + 0x26, 0x01, 0xa5, 0x01, 0xc5, 0x00, 0x90, 0x04, + 0xe5, 0x00, 0x85, 0x01, 0x26, 0x10, 0x26, 0x11, + 0xca, 0xd0, 0xed, 0x68, 0x85, 0x01, 0x68, 0xaa, + 0x68, 0x60 +}; + +static UINT8 mcu_reset_r() +{ + if (nSimulateMCU) { + mcu_key = -1; + mcu_input_size = 0; + mcu_output_byte = 0; + } else { + m6805Open(0); + m68705Reset(); + m6805Close(); + } + + return 0; +} + +static void mcu_w(UINT8 data) +{ + if (nSimulateMCU) { + mcu_output_byte = 0; + + if (mcu_key < 0) { + mcu_key = 0; + mcu_input_size = 1; + mcu_buffer[0] = data; + } else { + data ^= mcu_encrypt_table[mcu_key++]; + if (mcu_key == mcu_encrypt_table_len) + mcu_key = 0; + if (mcu_input_size < MCU_BUFFER_MAX) + mcu_buffer[mcu_input_size++] = data; + } + } else { + MCUFromMain = data; + MCUMainSent = 1; + m6805Open(0); + m68705SetIrqLine(0, 1); + m6805Close(); + } +} + +static void mcu_process_command(void) +{ + mcu_input_size = 0; + mcu_output_byte = 0; + + switch (mcu_buffer[0]) { + case 0x10: + mcu_buffer[0] = mcu_type; + break; + + case 0x26: { + INT32 sound_code = mcu_buffer[1]; + static const UINT8 sound_command_table[256] = { + 0xa0, 0xa1, 0xa2, 0x80, 0x81, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x97, 0x96, 0x9b, 0x9a, 0x95, + 0x9e, 0x98, 0x90, 0x93, 0x9d, 0x9c, 0xa3, 0x91, + 0x9f, 0x99, 0xa6, 0xae, 0x94, 0xa5, 0xa4, 0xa7, + 0x92, 0xab, 0xac, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, + 0x50, 0x50, 0x90, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x90, + 0x30, 0x30, 0x30, 0xb0, 0xb0, 0xb0, 0xb0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xd0, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x10, 0x50, 0x30, 0xb0, 0xb0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x10, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x8f, 0x8f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xef, 0xef, 0xcf, 0x8f, 0x8f, 0x0f, 0x0f, 0x0f + }; + mcu_buffer[0] = 1; + mcu_buffer[1] = sound_command_table[sound_code]; + break; + } + + + case 0x33: { + INT32 joy_bits = mcu_buffer[2]; + static const UINT8 joy_table[0x10] = { + 0, 3, 7, 0, 1, 2, 8, 0, 5, 4, 6, 0, 0, 0, 0, 0 + }; + mcu_buffer[0] = 1; + mcu_buffer[1] = joy_table[joy_bits & 0xf]; + break; + } + + + case 0x44: { + INT32 difficulty = mcu_buffer[2] & 0x3; + INT32 stage = mcu_buffer[3]; + static const UINT8 difficulty_table[4] = { 5, 3, 1, 2 }; + INT32 result = difficulty_table[difficulty]; + + if (stage == 0) + result--; + result += stage / 4; + if (result > 0x21) + result += 0xc0; + + mcu_buffer[0] = 1; + mcu_buffer[1] = result; + break; + } + + case 0x55: { + INT32 difficulty = mcu_buffer[4] & 0x3; + static const UINT16 table[4] = { + 0x4001, 0x5001, 0x1502, 0x0002 + }; + + mcu_buffer[0] = 3; + mcu_buffer[2] = table[difficulty] >> 8; + mcu_buffer[3] = table[difficulty] & 0xff; + break; + } + + + case 0x41: { + mcu_buffer[0] = 2; + mcu_buffer[1] = 0x20; + mcu_buffer[2] = 0x78; + break; + } + + + case 0x40: { + INT32 difficulty = mcu_buffer[2]; + INT32 enemy_type = mcu_buffer[3]; + INT32 health; + + if (enemy_type <= 4) { + health = 0x18 + difficulty * 2; + if (health > 0x40) + health = 0x40; /* max 0x40 */ + } else { + health = 0x06 + difficulty * 2; + if (health > 0x20) + health = 0x20; /* max 0x20 */ + } + mcu_buffer[0] = 1; + mcu_buffer[1] = health; + break; + } + + + case 0x42: { + INT32 stage = mcu_buffer[2] & 0x3; + INT32 indx = mcu_buffer[3]; + INT32 enemy_type=0; + + static const INT32 table[] = { + 0x01, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, /* for stage#: 0 */ + 0x02, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, /* for stage#: 1 */ + 0x03, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, /* for stage#: 2 */ + 0x04, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* for stage#: 3 */ + 0x3d, 0x23, 0x26, 0x0a, 0xb6, 0x11, 0xa4, 0x0f, /* strange data (maybe out of table) */ + }; + INT32 offset = stage * 8 + indx; + + if (stage >= 2) + offset--; + + enemy_type = table[offset]; + + mcu_buffer[0] = 1; + mcu_buffer[1] = enemy_type; + break; + } + } +} + +static UINT8 mcu_r() +{ + if (nSimulateMCU) { + INT32 result = 1; + + if (mcu_input_size) + mcu_process_command(); + + if (mcu_output_byte < MCU_BUFFER_MAX) + result = mcu_buffer[mcu_output_byte++]; + + return result; + } else { + MCUMcuSent = 0; + return MCUFromMcu; + } +} + +static UINT8 mcu_status_r() +{ + UINT8 Res = 0; + + if (nSimulateMCU || DisableMCUEmulation) { + Res = 1; + } else { + if (!MCUMainSent) + Res |= 0x01; + if (!MCUMcuSent) + Res |= 0x02; + } + + return Res; +} + +struct adpcm_state +{ + INT32 signal; + INT32 step; +}; + +static struct renegade_adpcm_state +{ + struct adpcm_state adpcm; + UINT32 current, end; + UINT8 nibble; + UINT8 playing; + UINT8 *base; +} renegade_adpcm; + +static INT32 diff_lookup[49*16]; +static INT32 tables_computed = 0; + +static UINT32 nUpdateStep; + +static void compute_tables(void) +{ + static const INT32 nbl2bit[16][4] = + { + { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1}, + { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1}, + {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1}, + {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1} + }; + + INT32 step, nib; + + for (step = 0; step <= 48; step++) + { + INT32 stepval = (INT32)floor(16.0 * pow(11.0 / 10.0, (double)step)); + + for (nib = 0; nib < 16; nib++) + { + diff_lookup[step*16 + nib] = nbl2bit[nib][0] * + (stepval * nbl2bit[nib][1] + + stepval/2 * nbl2bit[nib][2] + + stepval/4 * nbl2bit[nib][3] + + stepval/8); + } + } + + tables_computed = 1; +} + +static void reset_adpcm(struct adpcm_state *state) +{ + if (!tables_computed) + compute_tables(); + + state->signal = -2; + state->step = 0; +} + +static void RenegadeADPCMInit(INT32 clock) +{ + struct renegade_adpcm_state *state = &renegade_adpcm; + state->playing = 0; + state->base = DrvADPCMRom; + reset_adpcm(&state->adpcm); + + nUpdateStep = (INT32)(((float)clock / nBurnSoundRate) * 32768); +} + +static INT32 DrvDoReset() +{ + M6502Open(0); + M6502Reset(); + M6502Close(); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + if (!nSimulateMCU && !DisableMCUEmulation) { + m6805Open(0); + m68705Reset(); + m6805Close(); + + MCUFromMain = 0; + MCUFromMcu = 0; + MCUMainSent = 0; + MCUMcuSent = 0; + MCUDdrA = 0; + MCUDdrB = 0; + MCUDdrC = 0; + MCUPortAOut = 0; + MCUPortBOut = 0; + MCUPortCOut = 0; + MCUPortAIn = 0; + MCUPortBIn = 0; + MCUPortCIn = 0; + } + + BurnYM3526Reset(); + reset_adpcm(&renegade_adpcm.adpcm); + + DrvRomBank = 0; + DrvVBlank = 0; + memset(DrvScrollX, 0, 2); + DrvSoundLatch = 0; + + return 0; +} + +UINT8 RenegadeReadByte(UINT16 Address) +{ + switch (Address) { + case 0x3800: { + return DrvInput[0]; + } + + case 0x3801: { + return DrvInput[1]; + } + + case 0x3802: { + UINT8 MCUStatus = mcu_status_r(); + if (MCUStatus) MCUStatus = (MCUStatus - 1) * 0x10; + return DrvInput[2] + DrvDip[1] + (DrvVBlank ? 0x40 : 0) + MCUStatus; + } + + case 0x3803: { + return DrvDip[0]; + } + + case 0x3804: { + if (!DisableMCUEmulation) { + return mcu_r(); + } + return 0; + } + + case 0x3805: { + if (!DisableMCUEmulation) { + return mcu_reset_r(); + } + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Read Byte %04X\n"), Address); + } + } + + return 0; +} + +void RenegadeWriteByte(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x3800: { + DrvScrollX[0] = Data; + return; + } + + case 0x3801: { + DrvScrollX[1] = Data; + return; + } + + case 0x3802: { + DrvSoundLatch = Data; + M6809Open(0); + M6809SetIRQ(M6809_IRQ_LINE, M6809_IRQSTATUS_AUTO); + M6809Close(); + return; + } + + case 0x3803: { + // flipscreen + return; + } + + case 0x3804: { + if (!DisableMCUEmulation) mcu_w(Data); + return; + } + + case 0x3805: { + DrvRomBank = Data & 1; + M6502MapMemory(DrvM6502Rom + 0x8000 + (DrvRomBank * 0x4000), 0x4000, 0x7fff, M6502_ROM); + return; + } + + case 0x3806: { + // nop + return; + } + + case 0x3807: { + // coin counter + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("M6502 Write Byte %04X, %02X\n"), Address, Data); + } + } +} + +UINT8 RenegadeM6809ReadByte(UINT16 Address) +{ + switch (Address) { + case 0x1000: { + return DrvSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("M6809 Read Byte %04X\n"), Address); + } + } + + return 0; +} + +void RenegadeM6809WriteByte(UINT16 Address, UINT8 Data) +{ + switch (Address) { + case 0x1800: { + // nop??? + return; + } + + case 0x2000: { + INT32 Offset, Length; + + Offset = (Data - 0x2c) * 0x2000; + Length = 0x2000 * 2; + + if ((Offset + Length) > 0x20000) Length = 0x1000; + + if (Offset >= 0 && (Offset + Length) < 0x20000) { + renegade_adpcm.current = Offset << 15; + renegade_adpcm.end = Offset + (Length / 2); + renegade_adpcm.nibble = 4; + renegade_adpcm.playing = 1; + } + return; + } + + case 0x2800: { + BurnYM3526Write(0, Data); + return; + } + + case 0x2801: { + BurnYM3526Write(1, Data); + return; + } + + case 0x3000: { + // nop??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("M6809 Write Byte %04X, %02X\n"), Address, Data); + } + } +} + +UINT8 MCUReadByte(UINT16 address) +{ + switch (address & 0x7ff) { + case 0x000: { + return (MCUPortAOut & MCUDdrA) | (MCUPortAIn & ~MCUDdrA); + } + + case 0x001: { + return (MCUPortBOut & MCUDdrB) | (MCUPortBIn & ~MCUDdrB); + } + + case 0x002: { + MCUPortCIn = 0; + if (MCUMainSent) MCUPortCIn |= 0x01; + if (!MCUMcuSent) MCUPortCIn |= 0x02; + + return (MCUPortCOut & MCUDdrC) | (MCUPortCIn & ~MCUDdrC); + } + + default: { + bprintf(PRINT_NORMAL, _T("MCU Read %x\n"), address); + } + } + + return 0; +} + +void MCUWriteByte(UINT16 address, UINT8 data) +{ + switch (address & 0x7ff) { + case 0x000: { + MCUPortAOut = data; + break; + } + + case 0x001: { + if ((MCUDdrB & 0x02) && (~data & 0x02) && (MCUPortBOut & 0x02)) { + MCUPortAIn = MCUFromMain; + + if (MCUMainSent) { + m68705SetIrqLine(0, 0); + MCUMainSent = 0; + } + } + + if ((MCUDdrB & 0x04) && (data & 0x04) && (~MCUPortBOut & 0x04)) { + MCUFromMcu = MCUPortAOut; + MCUMcuSent = 1; + } + + MCUPortBOut = data; + break; + } + + case 0x002: { + MCUPortCOut = data; + break; + } + + case 0x004: { + MCUDdrA = data; + break; + } + + case 0x005: { + MCUDdrB = data; + break; + } + + case 0x006: { + MCUDdrC = data; + break; + } + + default: { + bprintf(PRINT_NORMAL, _T("MCU Write %x, %x\n"), address, data); + } + } +} + +static INT32 CharPlaneOffsets[3] = { 2, 4, 6 }; +static INT32 CharXOffsets[8] = { 1, 0, 65, 64, 129, 128, 193, 192 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 Tile1PlaneOffsets[3] = { 0x00004, 0x40000, 0x40004 }; +static INT32 Tile2PlaneOffsets[3] = { 0x00000, 0x60000, 0x60004 }; +static INT32 Tile3PlaneOffsets[3] = { 0x20004, 0x80000, 0x80004 }; +static INT32 Tile4PlaneOffsets[3] = { 0x20000, 0xa0000, 0xa0004 }; +static INT32 TileXOffsets[16] = { 3, 2, 1, 0, 131, 130, 129, 128, 259, 258, 257, 256, 387, 386, 385, 384 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_ACK); + } else { + M6809SetIRQ(M6809_FIRQ_LINE, M6809_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)M6809TotalCycles() * nSoundRate / 1500000; +} + +static INT32 DrvInit(INT32 nMcuType) +{ + INT32 nRet = 0, nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x60000); + + nRet = BurnLoadRom(DrvM6502Rom + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvM6502Rom + 0x08000, 1, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvM6809Rom + 0x00000, 2, 1); if (nRet != 0) return 1; + + nRet = BurnLoadRom(DrvTempRom, 3, 1); if (nRet != 0) return 1; + GfxDecode(0x400, 3, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars); + + memset(DrvTempRom, 0, 0x60000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x000 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x100 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x200 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x300 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x400 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x500 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x600 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x700 * 16 * 16)); + + memset(DrvTempRom, 0, 0x60000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 21, 1); if (nRet != 0) return 1; + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x000 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x100 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x200 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x300 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x400 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x500 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x600 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x700 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0x800 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0x900 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0xa00 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0xb00 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xc00 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xd00 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xe00 * 16 * 16)); + GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xf00 * 16 * 16)); + + nRet = BurnLoadRom(DrvADPCMRom + 0x00000, 22, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvADPCMRom + 0x10000, 23, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvADPCMRom + 0x18000, 24, 1); if (nRet != 0) return 1; + + BurnFree(DrvTempRom); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502MapMemory(DrvM6502Ram , 0x0000, 0x17ff, M6502_RAM); + M6502MapMemory(DrvVideoRam2 , 0x1800, 0x1fff, M6502_RAM); + M6502MapMemory(DrvSpriteRam , 0x2000, 0x27ff, M6502_RAM); + M6502MapMemory(DrvVideoRam1 , 0x2800, 0x2fff, M6502_RAM); + M6502MapMemory(DrvPaletteRam1 , 0x3000, 0x30ff, M6502_RAM); + M6502MapMemory(DrvPaletteRam2 , 0x3100, 0x31ff, M6502_RAM); + M6502MapMemory(DrvM6502Rom + 0x8000 , 0x4000, 0x7fff, M6502_ROM); + M6502MapMemory(DrvM6502Rom , 0x8000, 0xffff, M6502_ROM); + M6502SetReadByteHandler(RenegadeReadByte); + M6502SetWriteByteHandler(RenegadeWriteByte); + M6502Close(); + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809Ram , 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvM6809Rom , 0x8000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(RenegadeM6809ReadByte); + M6809SetWriteByteHandler(RenegadeM6809WriteByte); + M6809Close(); + + if (nMcuType == MCU_TYPE_RENEGADE) { + nSimulateMCU = 0; + + nRet = BurnLoadRom(DrvM68705Rom, 25, 1); if (nRet != 0) return 1; + + m6805Init(1, 0x800); + m6805Open(0); + m6805MapMemory(DrvM68705Ram , 0x0010, 0x007f, M6805_RAM); + m6805MapMemory(DrvM68705Rom + 0x0080, 0x0080, 0x07ff, M6805_ROM); + m6805SetWriteHandler(MCUWriteByte); + m6805SetReadHandler(MCUReadByte); + m6805Close(); + } + + if (nMcuType == MCU_TYPE_KUNIOKUN) { + mcu_type = 0x85; + mcu_encrypt_table = kuniokun_xor_table; + mcu_encrypt_table_len = 0x2a; + nSimulateMCU = 1; + } + + if (nMcuType == MCU_TYPE_NONE) { + DisableMCUEmulation = 1; + } + + BurnYM3526Init(3000000, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachM6809YM3526(1500000); + + RenegadeADPCMInit(8000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 RenegadeInit() +{ + return DrvInit(MCU_TYPE_RENEGADE); +} + +static INT32 KuniokunInit() +{ + return DrvInit(MCU_TYPE_KUNIOKUN); +} + +static INT32 KuniokunbInit() +{ + return DrvInit(MCU_TYPE_NONE); +} + +static INT32 DrvExit() +{ + M6502Exit(); + M6809Exit(); + m6805Exit(); + + BurnYM3526Exit(); + + GenericTilesExit(); + + BurnFree(Mem); + + mcu_type = 0; + mcu_encrypt_table = NULL; + mcu_encrypt_table_len = 0; + + memset(mcu_buffer, 0, MCU_BUFFER_MAX); + mcu_input_size = 0; + mcu_output_byte = 0; + mcu_key = 0; + + DisableMCUEmulation = 0; + + nSimulateMCU = 0; + MCUFromMain = 0; + MCUFromMcu = 0; + MCUMainSent = 0; + MCUMcuSent = 0; + MCUDdrA = 0; + MCUDdrB = 0; + MCUDdrC = 0; + MCUPortAOut = 0; + MCUPortBOut = 0; + MCUPortCOut = 0; + MCUPortAIn = 0; + MCUPortBIn = 0; + MCUPortCIn = 0; + + DrvRomBank = 0; + DrvVBlank = 0; + memset(DrvScrollX, 0, 2); + DrvSoundLatch = 0; + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < 0x100; i++) { + INT32 Val = DrvPaletteRam1[i] + (DrvPaletteRam2[i] << 8); + + DrvPalette[i] = CalcCol(Val); + } +} + +static void DrvRenderBgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, xScroll; + + xScroll = DrvScrollX[0] + (DrvScrollX[1] << 8); + xScroll &= 0x3ff; + xScroll -= 256; + + for (my = 0; my < 16; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = DrvVideoRam1[TileIndex + 0x400]; + Code = DrvVideoRam1[TileIndex + 0x000]; + Colour = Attr >> 5; + + x = 16 * mx; + y = 16 * my; + + x -= xScroll; + if (x < -16) x += 1024; + + x -= 8; + + if (x > 0 && x < 224 && y > 0 && y < 224) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 3, 192, DrvTiles + ((Attr & 0x07) * 0x100 * 16 * 16)); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 192, DrvTiles + ((Attr & 0x07) * 0x100 * 16 * 16)); + } + + TileIndex++; + } + } +} + +static void DrvRenderSprites() +{ + UINT8 *Source = DrvSpriteRam; + UINT8 *Finish = Source + 96 * 4; + + while (Source < Finish) { + INT32 sy = 240 - Source[0]; + + if (sy >= 16) { + INT32 Attr = Source[1]; + INT32 sx = Source[3]; + INT32 Code = Source[2]; + INT32 SpriteBank = Attr & 0xf; + INT32 Colour = (Attr >> 4) & 0x3; + INT32 xFlip = Attr & 0x40; + + if (sx > 248) sx -= 256; + + sx -= 8; + + if (Attr & 0x80) { + Code &= ~1; + if (sx > 16 && sx < 224 && (sy + 16) > 0 && (sy + 16) < 224) { + if (xFlip) { + Render16x16Tile_Mask_FlipX(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } else { + Render16x16Tile_Mask(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } + } else { + if (xFlip) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } + } + } else { + sy += 16; + } + + if (sx > 16 && sx < 224 && sy > 0 && sy < 224) { + if (xFlip) { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } + } else { + if (xFlip) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16)); + } + } + } + Source += 4; + } +} + +static void DrvRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 32; mx++) { + Attr = DrvVideoRam2[TileIndex + 0x400]; + Code = ((Attr & 3) << 8) + DrvVideoRam2[TileIndex + 0x000]; + Colour = Attr >> 6; + + x = 8 * mx; + y = 8 * my; + + x -= 8; + + if (x > 0 && x < 232 && y > 0 && y < 232) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvChars); + } + + TileIndex++; + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + DrvCalcPalette(); + DrvRenderBgLayer(); + DrvRenderSprites(); + DrvRenderCharLayer(); + BurnTransferCopy(DrvPalette); +} + +static void DrvInterrupt() +{ + static INT32 Count; + Count = !Count; + if (Count) { + M6502SetIRQ(M6502_INPUT_LINE_NMI, M6502_IRQSTATUS_AUTO); + } else { + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_AUTO); + } +} + +static const INT32 index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +INT16 clock_adpcm(struct adpcm_state *state, UINT8 nibble) +{ + state->signal += diff_lookup[(state->step >> 15) * 16 + (nibble & 15)]; + + if (state->signal > 2047) + state->signal = 2047; + else if (state->signal < -2048) + state->signal = -2048; + + state->step += index_shift[nibble & 7] * nUpdateStep; + if ((state->step >> 15) > 48) + state->step = 48 << 15; + else if ((state->step >> 15) < 0) + state->step = 0; + + return state->signal; +} + +static void RenderADPCMSample(INT16 *pSoundBuf, INT32 nLength) +{ + while (renegade_adpcm.playing && nLength > 0) { + INT32 val = (renegade_adpcm.base[renegade_adpcm.current >> 15] >> renegade_adpcm.nibble) & 15; + + renegade_adpcm.nibble ^= 4; + if (renegade_adpcm.nibble == 4) { + renegade_adpcm.current += nUpdateStep;//++; + if ((renegade_adpcm.current >> 15) >= renegade_adpcm.end) renegade_adpcm.playing = 0; + } + + INT16 Sample = clock_adpcm(&renegade_adpcm.adpcm, val) << 2; + INT32 Left = pSoundBuf[0] + Sample; + INT32 Right = pSoundBuf[1] + Sample; + + pSoundBuf[0] = BURN_SND_CLIP(Left); + pSoundBuf[1] = BURN_SND_CLIP(Right); + pSoundBuf += 2; + nLength--; + } +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 262; + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesTotal[0] = (12000000 / 8) / 60; + nCyclesTotal[1] = (12000000 / 8) / 60; + nCyclesTotal[2] = (12000000 / 4) / 60; + + INT32 nCyclesDone[3] = { 0, 0, 0 }; + INT32 nCyclesSegment; + + DrvVBlank = 0; + + M6502NewFrame(); + M6809NewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + M6502Open(0); + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6502Run(nCyclesSegment); + if (i == ((nInterleave / 10) * 7)) DrvVBlank = 1; + if (i == (nInterleave / 2) || i == ((nInterleave / 10) * 9)) DrvInterrupt(); + M6502Close(); + + if (!nSimulateMCU && !DisableMCUEmulation) { + m6805Open(0); + nCurrentCPU = 2; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += m6805Run(nCyclesSegment); + m6805Close(); + } + + M6809Open(0); + BurnTimerUpdateYM3526(i * (nCyclesTotal[1] / nInterleave)); + M6809Close(); + } + + M6809Open(0); + BurnTimerEndFrameYM3526(nCyclesTotal[1]); + M6809Close(); + + M6809Open(0); + BurnYM3526Update(pBurnSoundOut, nBurnSoundLen); + RenderADPCMSample(pBurnSoundOut, nBurnSoundLen); + M6809Close(); + + if (pBurnDraw) DrvDraw(); + + return 0; +} + + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029696; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +struct BurnDriver BurnDrvRenegade = { + "renegade", NULL, NULL, NULL, "1986", + "Renegade (US)\0", NULL, "Technos (Taito America license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + RenegadeInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 240, 240, 4, 3 +}; + +struct BurnDriver BurnDrvKuniokun = { + "kuniokun", "renegade", NULL, NULL, "1986", + "Nekketsu Kouha Kunio-kun (Japan)\0", NULL, "Technos", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + KuniokunInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 240, 240, 4, 3 +}; + +struct BurnDriver BurnDrvKuniokunb = { + "kuniokunb", "renegade", NULL, NULL, "1986", + "Nekketsu Kouha Kunio-kun (Japan bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + KuniokunbInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 240, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_retofinv.cpp b/src/burn/drivers/misc_pre90s/d_retofinv.cpp new file mode 100644 index 00000000..72c819d2 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_retofinv.cpp @@ -0,0 +1,987 @@ +// FB Alpha Return of the Invaders driver module +// Based on MAME driver by Jarek Parchanski and Andrea Mazzoleni + +#include "tiles_generic.h" +#include "taito_m68705.h" +#include "bitswap.h" +#include "sn76496.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvMcuROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvColPROM; +static UINT8 *DrvFgVRAM; +static UINT8 *DrvBgVRAM; +static UINT8 *DrvShareRAM; +static UINT8 *DrvZ80RAM2; +static UINT8 *DrvMcuRAM; + +static UINT16 *DrvTileOfst; +static UINT8 *DrvColTable; +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *coinlockout; +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *flipscreen; +static UINT8 *gfxbank; + +static INT32 enable_interrupt[2]; +static INT32 disable_cpu[3]; + +static INT32 use_mcu; + +static INT32 watchdog; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo RetofinvInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 7, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 2, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Retofinv) + +static struct BurnDIPInfo RetofinvDIPList[]= +{ + {0x0d, 0xff, 0xff, 0x6f, NULL }, + {0x0e, 0xff, 0xff, 0x00, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0d, 0x01, 0x03, 0x03, "30k, 80k & every 80k" }, + {0x0d, 0x01, 0x03, 0x02, "30k, 80k" }, + {0x0d, 0x01, 0x03, 0x01, "30k" }, + {0x0d, 0x01, 0x03, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Free Play" }, + {0x0d, 0x01, 0x04, 0x04, "No" }, + {0x0d, 0x01, 0x04, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x0d, 0x01, 0x18, 0x18, "1" }, + {0x0d, 0x01, 0x18, 0x10, "2" }, + {0x0d, 0x01, 0x18, 0x08, "3" }, + {0x0d, 0x01, 0x18, 0x00, "5 (retofin2 4)" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x0d, 0x01, 0x40, 0x40, "Off" }, + {0x0d, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x0d, 0x01, 0x80, 0x00, "Upright" }, + {0x0d, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x0e, 0x01, 0x0f, 0x0f, "9 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x0e, "8 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x0d, "7 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x0c, "6 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x0a, "4 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x09, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x00, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0x0f, 0x01, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x0f, 0x02, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x0f, 0x03, "1 Coin 4 Credits" }, + {0x0e, 0x01, 0x0f, 0x04, "1 Coin 5 Credits" }, + {0x0e, 0x01, 0x0f, 0x05, "1 Coin 6 Credits" }, + {0x0e, 0x01, 0x0f, 0x06, "1 Coin 7 Credits" }, + {0x0e, 0x01, 0x0f, 0x07, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x0e, 0x01, 0xf0, 0xf0, "9 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0xe0, "8 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0xd0, "7 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0xc0, "6 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0xb0, "5 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0xa0, "4 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0x90, "3 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x0e, 0x01, 0xf0, 0x00, "1 Coin 1 Credits" }, + {0x0e, 0x01, 0xf0, 0x10, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0xf0, 0x20, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0xf0, 0x30, "1 Coin 4 Credits" }, + {0x0e, 0x01, 0xf0, 0x40, "1 Coin 5 Credits" }, + {0x0e, 0x01, 0xf0, 0x50, "1 Coin 6 Credits" }, + {0x0e, 0x01, 0xf0, 0x60, "1 Coin 7 Credits" }, + {0x0e, 0x01, 0xf0, 0x70, "1 Coin 8 Credits" }, + + {0 , 0xfe, 0 , 2, "Push Start to Skip Stage (Cheat)" }, + {0x0f, 0x01, 0x01, 0x01, "Off" }, + {0x0f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coin Per Play Display" }, + {0x0f, 0x01, 0x10, 0x00, "No" }, + {0x0f, 0x01, 0x10, 0x10, "Yes" }, + + {0 , 0xfe, 0 , 2, "Year Display" }, + {0x0f, 0x01, 0x20, 0x00, "No" }, + {0x0f, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 2, "Invulnerability (Cheat)" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x0f, 0x01, 0x80, 0x80, "A and B" }, + {0x0f, 0x01, 0x80, 0x00, "A only" }, +}; + +STDDIPINFO(Retofinv) + +// Reset cpu and keep sync +static inline void retofinv_cpu_reset(INT32 cpu, INT32 data) +{ + INT32 cycles = ZetTotalCycles(); + ZetClose(); + ZetOpen(cpu); + cycles -= ZetTotalCycles(); + if (data) { + ZetIdle(cycles - ZetTotalCycles()); + } else { + ZetRun(cycles); + ZetReset(); + } + disable_cpu[cpu-1] = data; + ZetClose(); + ZetOpen(0); +} + +void __fastcall retofinv_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xb800: + *flipscreen = data & 1; + return; + + case 0xb801: + gfxbank[0] = data & 1; + return; + + case 0xb802: + gfxbank[1] = data & 1; + return; + + case 0xc800: + { + data &= 1; + if (!data) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + enable_interrupt[0] = data; + } + return; + + case 0xc801: + *coinlockout = (data & 1) * 0xff; + return; + + case 0xc802: + retofinv_cpu_reset(2, data); + return; + + case 0xc803: + m67805_taito_reset(); + disable_cpu[2] = data; + return; + + case 0xc804: + { + data &= 1; + if (!data) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + enable_interrupt[1] = data; + } + return; + + case 0xc805: + retofinv_cpu_reset(1, data); + return; + + case 0xd000: + watchdog = 0; + return; + + case 0xd800: + { + *soundlatch = data; + ZetClose(); + ZetOpen(2); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + } + return; + + case 0xe800: + standard_taito_mcu_write(data); + return; + } +} + +UINT8 __fastcall retofinv_main_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + return DrvInputs[0]; + + case 0xc001: + return DrvInputs[1]; + + case 0xc002: // must be < 0x80; + return 0; + + case 0xc003: // mcu status + { + INT32 res = 0; + if (!main_sent) res |= 0x10; + if (mcu_sent) res |= 0x20; + return res; + } + + case 0xc004: + return DrvInputs[2] & (*coinlockout | 0xcf); + + case 0xc005: + return DrvDips[0]; + + case 0xc006: + return DrvDips[1]; + + case 0xc007: + return DrvDips[2]; + + case 0xf800: + return *soundlatch2; + + case 0xe000: + return standard_taito_mcu_read(); + } + + return 0; +} + +void __fastcall retofinv_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x6000: + *soundlatch2 = data; + return; + + case 0x8000: + SN76496Write(0, data); + return; + + case 0xa000: + SN76496Write(1, data); + return; + } +} + +UINT8 __fastcall retofinv_sound_read(UINT16 address) +{ + switch (address) + { + case 0x4000: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + m67805_taito_reset(); + + enable_interrupt[0] = 0; + enable_interrupt[1] = 0; + disable_cpu[0] = 1; + disable_cpu[1] = 1; + disable_cpu[2] = 1; + + watchdog = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + DrvZ80ROM2 = Next; Next += 0x010000; + + DrvMcuROM = Next; Next += 0x000800; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + DrvGfxROM2 = Next; Next += 0x008000; + + DrvColPROM = Next; Next += 0x000b00; + + AllRam = Next; + + DrvFgVRAM = Next; Next += 0x000800; + DrvBgVRAM = Next; Next += 0x000800; + DrvShareRAM = Next; Next += 0x001800; + + DrvZ80RAM2 = Next; Next += 0x000800; + + DrvMcuRAM = Next; Next += 0x000080; + + coinlockout = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + gfxbank = Next; Next += 0x000002; + + RamEnd = Next; + + DrvColTable = Next; Next += 0x000a00; + Palette = (UINT32*)Next; Next += 0x0a00 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0a00 * sizeof(UINT32); + + DrvTileOfst = (UINT16*)Next; Next += 0x0400 * sizeof(UINT16); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[1] = { 0x00000 }; + INT32 Plane1[4] = { 0x00000, 0x20004, 0x20000, 0x00004 }; + INT32 XOffs0[8] = { 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000 }; + INT32 XOffs1[16] = { 0x000, 0x001, 0x002, 0x003, 0x040, 0x041, 0x042, 0x043, + 0x080, 0x081, 0x082, 0x083, 0x0c0, 0x0c1, 0x0c2, 0x0c3 }; + INT32 YOffs[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x100, 0x108, 0x110, 0x118, 0x120, 0x128, 0x130, 0x138 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x8000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x2000); + + GfxDecode(0x0200, 1, 8, 8, Plane0, XOffs0, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x8000); + + GfxDecode(0x0100, 4, 16, 16, Plane1, XOffs1, YOffs, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x8000); + + GfxDecode(0x0200, 4, 8, 8, Plane1, XOffs1, YOffs, 0x080, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) + { + INT32 r = DrvColPROM[i + 0x000] & 0x0f; + INT32 g = DrvColPROM[i + 0x100] & 0x0f; + INT32 b = DrvColPROM[i + 0x200] & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 0x200; i++) { // foreground + DrvColTable[i] = (i >> 1) * (i & 1); + Palette[i + 0x000] = DrvPalette[DrvColTable[i]]; + } + + for (INT32 i = 0; i < 0x800; i++) { // everything else + DrvColTable[i + 0x200] = BITSWAP08(DrvColPROM[i + 0x300],4,5,6,7,3,2,1,0); + Palette[i + 0x200] = DrvPalette[DrvColTable[i + 0x200]]; + DrvColTable[i + 0x200] = (DrvColTable[i + 0x200] == 0xff) ? 0 : 1; + } + + DrvRecalc = 1; +} + +// Calculate offsets for tiles on screen +static void DrvCalculateOffsets() +{ + for (INT32 offs = 0; offs < 36 * 28; offs++) { + INT32 col = (offs % 36) - 2; + INT32 row = (offs / 36) + 2; + + if (col & 0x20) + DrvTileOfst[offs] = ((col & 0x1f) << 5) + row; + else + DrvTileOfst[offs] = (row << 5) + col; + } +} + +static INT32 DecodeBoot3PROMs() +{ + UINT8 *tmp = DrvGfxROM2 + 0x8000; // empty before gfx decode + + if (BurnLoadRom(tmp + 0x000, 16, 1)) return 1; + if (BurnLoadRom(tmp + 0x400, 18, 1)) return 1; + if (BurnLoadRom(tmp + 0x800, 15, 1)) return 1; + if (BurnLoadRom(tmp + 0xc00, 17, 1)) return 1; + + for (INT32 i = 0; i < 0x800; i++) { + DrvColPROM[i + 0x300] = (tmp[i] & 0x0f) | (tmp[i + 0x800] << 4); + } + + memset (tmp, 0, 0x1000); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x02000, 1, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x04000, 2, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM2 + 0x00000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x02000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x04000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x06000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 11, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 12, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 13, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 14, 1)) return 1; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "retofin3") == 0) { + DecodeBoot3PROMs(); + } else { + if (BurnLoadRom(DrvColPROM + 0x00300, 15, 1)) return 1; + + if (BurnLoadRom(DrvMcuROM + 0x00000, 16, 1)) return 1; + } + + DrvCalculateOffsets(); + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(3); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0x87ff, 0, DrvFgVRAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvFgVRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvFgVRAM); + ZetMapArea(0x8800, 0x9fff, 0, DrvShareRAM); + ZetMapArea(0x8800, 0x9fff, 1, DrvShareRAM); + ZetMapArea(0x8800, 0x9fff, 2, DrvShareRAM); + ZetMapArea(0xa000, 0xa7ff, 0, DrvBgVRAM); + ZetMapArea(0xa000, 0xa7ff, 1, DrvBgVRAM); + ZetMapArea(0xa000, 0xa7ff, 2, DrvBgVRAM); + ZetSetWriteHandler(retofinv_main_write); + ZetSetReadHandler(retofinv_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvFgVRAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvFgVRAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvFgVRAM); + ZetMapArea(0x8800, 0x9fff, 0, DrvShareRAM); + ZetMapArea(0x8800, 0x9fff, 1, DrvShareRAM); + ZetMapArea(0x8800, 0x9fff, 2, DrvShareRAM); + ZetMapArea(0xa000, 0xa7ff, 0, DrvBgVRAM); + ZetMapArea(0xa000, 0xa7ff, 1, DrvBgVRAM); + ZetMapArea(0xa000, 0xa7ff, 2, DrvBgVRAM); + ZetSetWriteHandler(retofinv_main_write); + ZetSetReadHandler(retofinv_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM2); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80ROM2); + ZetMapArea(0x2000, 0x27ff, 0, DrvZ80RAM2); + ZetMapArea(0x2000, 0x27ff, 1, DrvZ80RAM2); + ZetMapArea(0x2000, 0x27ff, 2, DrvZ80RAM2); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80ROM2 + 0xe000); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80ROM2 + 0xe000); + ZetSetWriteHandler(retofinv_sound_write); + ZetSetReadHandler(retofinv_sound_read); + ZetClose(); + + m67805_taito_init(DrvMcuROM, DrvMcuRAM, &standard_m68705_interface); + + use_mcu = ~BurnDrvGetFlags() & BDF_BOOTLEG; + + SN76489Init(0, 18432000 / 6, 0); + SN76489Init(1, 18432000 / 6, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + m67805_taito_exit(); + + SN76496Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background_layer() +{ + for (INT32 offs = 0; offs < 36 * 28; offs++) + { + INT32 sx = (offs % 36) << 3; + INT32 sy = (offs / 36) << 3; + + + INT32 ofst = DrvTileOfst[offs]; + + INT32 code = DrvBgVRAM[ofst] | (gfxbank[1] << 8); + INT32 color = (DrvBgVRAM[ofst + 0x400] & 0x3f) + 0x60; + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, 280 - sx, 216 - sy, color, 4, 0, DrvGfxROM2); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM2); + } + } +} + +static void draw_foreground_layer() +{ + INT32 flip = *flipscreen ? 0x3f : 0; + + for (INT32 offs = 0; offs < 36 * 28; offs++) + { + INT32 sx = (offs % 36) << 3; + INT32 sy = (offs / 36) << 3; + + if (*flipscreen) { + sx = 280 - sx; + sy = 216 - sy; + } + + INT32 ofst = DrvTileOfst[offs]; + + INT32 code = DrvFgVRAM[ofst + 0x000] | (gfxbank[0] << 8); + INT32 color = DrvFgVRAM[ofst + 0x400]; + + { + color <<= 1; + UINT8 *src = DrvGfxROM0 + code * 0x40; + UINT16 *dst = pTransDraw + (sy * nScreenWidth) + sx; + + for (INT32 y = 0; y < 8; y++) { + for (INT32 x = 0; x < 8; x++) { + INT32 pxl = src[((y << 3) | x) ^ flip] | color; + + if (DrvColTable[pxl]) { + dst[x] = pxl; + } + } + dst += nScreenWidth; + } + } + } +} + +static inline void draw_masked_sprite(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 fx, INT32 fy) +{ + UINT16 *dst; + UINT8 *src = DrvGfxROM1 + code * 0x100; + + if (fx) fx = 0x0f; + if (fy) fx |= 0xf0; + + for (INT32 y = 0; y < 16; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + for (INT32 x = 0; x < 16; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = src[((y << 4) | x) ^ fx] | color; + + if (DrvColTable[pxl]) { + dst[sx] = pxl; + } + } + + sx -= 16; + } +} + +static void draw_sprites() +{ + static const INT32 gfx_offs[2][2] = + { + { 0, 1 }, + { 2, 3 } + }; + + UINT8 *ram0 = DrvShareRAM + 0x780; + UINT8 *ram1 = DrvShareRAM + 0xf80; + UINT8 *ram2 = DrvShareRAM + 0x1780; + + for (INT32 offs = 0; offs < 0x80; offs += 2) + { + INT32 attr = ram2[offs]; + INT32 sprite= ram0[offs+0]; + INT32 color = (ram0[offs+1] & 0x3f) + 0x20; + INT32 sx = ((ram1[offs+1] << 1) + ((ram2[offs+1] & 0x80) >> 7)) - 39; + INT32 sy = 256 - ((ram1[offs] << 1) + ((attr & 0x80) >> 7)) + 1; + INT32 flipx = (attr & 0x01); + INT32 flipy = (attr & 0x02) >> 1; + INT32 sizey = (attr & 0x04) >> 2; + INT32 sizex = (attr & 0x08) >> 3; + + sprite &= ~sizex; + sprite &= ~(sizey << 1); + + if (*flipscreen) + { + flipx ^= 1; + flipy ^= 1; + } + + sy -= sizey << 4; + sy = (sy & 0xff) - 32; + + for (INT32 y = 0; y <= sizey; y++) + { + for (INT32 x = 0; x <= sizex; x++) + { + INT32 code = sprite + gfx_offs[y ^ (sizey * flipy)][x ^ (sizex * flipx)]; + draw_masked_sprite(code, color << 4, sx + 16*x, sy + 16*y, flipx, flipy); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0xa00; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, (d >> 8) & 0xff, d & 0xff, 0); + } + DrvRecalc = 0; + } + + draw_background_layer(); + draw_sprites(); + draw_foreground_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + watchdog++; + if (DrvReset || watchdog > 59) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + DrvInputs[0] = 0xff; + DrvInputs[1] = 0xff; + DrvInputs[2] = 0xcf; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[4] = { 3072000 / 60, 3072000 / 60, 3072000 / 60, 3072000 / 60 }; + INT32 nCyclesDone[4] = { 0, 0, 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCycleSegment = (nCyclesTotal[0] / nInterleave); + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nCycleSegment); + if (i == (nInterleave - 1) && enable_interrupt[0]) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + + nCycleSegment *= (i + 1); + + if (disable_cpu[0]) { + ZetOpen(1); + nCyclesDone[1] += ZetRun(nCycleSegment - ZetTotalCycles()); + if (i == (nInterleave - 1) && enable_interrupt[1]) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + } + + if (disable_cpu[1]) { + ZetOpen(2); + nCyclesDone[1] += ZetRun(nCycleSegment - ZetTotalCycles()); + if (i == (nInterleave - 1) || i == (nInterleave / 2)-1) ZetNmi(); + ZetClose(); + } + + if (disable_cpu[2] && use_mcu) { + m6805Open(0); + nCycleSegment = nCyclesTotal[3] / nInterleave; + nCyclesDone[3] += m6805Run(nCycleSegment); + m6805Close(); + } + } + + if (pBurnSoundOut) { + SN76496Update(0, pBurnSoundOut, nBurnSoundLen); + SN76496Update(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + SN76496Scan(nAction, pnMin); + + SCAN_VAR(enable_interrupt[0]); + SCAN_VAR(enable_interrupt[1]); + SCAN_VAR(disable_cpu[0]); + SCAN_VAR(disable_cpu[1]); + SCAN_VAR(disable_cpu[2]); + SCAN_VAR(from_main); + SCAN_VAR(from_mcu); + SCAN_VAR(mcu_sent); + SCAN_VAR(main_sent); + } + + return 0; +} + + +// Return of the Invaders + +static struct BurnRomInfo retofinvRomDesc[] = { + { "a37-03.70", 0x2000, 0xeae7459d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a37-02.71", 0x2000, 0x72895e37, 1 | BRF_PRG | BRF_ESS }, // 1 + { "a37-01.72", 0x2000, 0x505dd20b, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "a37-04.62", 0x2000, 0xd2899cc1, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "a37-05.17", 0x2000, 0x9025abea, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "a37-16.61", 0x2000, 0x4e3f501c, 4 | BRF_GRA }, // 5 Characters + + { "a37-10.8", 0x2000, 0x6afdeec8, 5 | BRF_GRA }, // 6 Sprites + { "a37-11.9", 0x2000, 0xd3dc9da3, 5 | BRF_GRA }, // 7 + { "a37-12.10", 0x2000, 0xd10b2eed, 5 | BRF_GRA }, // 8 + { "a37-13.11", 0x2000, 0x00ca6b3d, 5 | BRF_GRA }, // 9 + + { "a37-14.55", 0x2000, 0xef7f8651, 6 | BRF_GRA }, // 10 Tiles + { "a37-15.56", 0x2000, 0x03b40905, 6 | BRF_GRA }, // 11 + + { "a37-06.13", 0x0100, 0xe9643b8b, 7 | BRF_GRA }, // 12 Color Proms + { "a37-07.4", 0x0100, 0xe8f34e11, 7 | BRF_GRA }, // 13 + { "a37-08.3", 0x0100, 0x50030af0, 7 | BRF_GRA }, // 14 + { "82s191n", 0x0800, 0x93c891e3, 7 | BRF_GRA }, // 15 + + { "a37-09.37", 0x0800, 0x79bd6ded, 8 | BRF_PRG | BRF_ESS }, // 16 68705 Code +}; + +STD_ROM_PICK(retofinv) +STD_ROM_FN(retofinv) + +struct BurnDriver BurnDrvRetofinv = { + "retofinv", NULL, NULL, NULL, "1985", + "Return of the Invaders\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, retofinvRomInfo, retofinvRomName, NULL, NULL, RetofinvInputInfo, RetofinvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0xa00, + 224, 288, 3, 4 +}; + + +// Return of the Invaders (bootleg set 1) + +static struct BurnRomInfo retofin1RomDesc[] = { + { "roi.02", 0x2000, 0xd98fd462, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "roi.01b", 0x2000, 0x3379f930, 1 | BRF_PRG | BRF_ESS }, // 1 + { "roi.01", 0x2000, 0x57679062, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "a37-04.62", 0x2000, 0xd2899cc1, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "a37-05.17", 0x2000, 0x9025abea, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "a37-16.61", 0x2000, 0x4e3f501c, 4 | BRF_GRA }, // 5 Characters + + { "a37-10.8", 0x2000, 0x6afdeec8, 5 | BRF_GRA }, // 6 Sprites + { "a37-11.9", 0x2000, 0xd3dc9da3, 5 | BRF_GRA }, // 7 + { "a37-12.10", 0x2000, 0xd10b2eed, 5 | BRF_GRA }, // 8 + { "a37-13.11", 0x2000, 0x00ca6b3d, 5 | BRF_GRA }, // 9 + + { "a37-14.55", 0x2000, 0xef7f8651, 6 | BRF_GRA }, // 10 Tiles + { "a37-15.56", 0x2000, 0x03b40905, 6 | BRF_GRA }, // 11 + + { "a37-06.13", 0x0100, 0xe9643b8b, 7 | BRF_GRA }, // 12 Color Proms + { "a37-07.4", 0x0100, 0xe8f34e11, 7 | BRF_GRA }, // 13 + { "a37-08.3", 0x0100, 0x50030af0, 7 | BRF_GRA }, // 14 + { "82s191n", 0x0800, 0x93c891e3, 7 | BRF_GRA }, // 15 +}; + +STD_ROM_PICK(retofin1) +STD_ROM_FN(retofin1) + +struct BurnDriver BurnDrvRetofin1 = { + "retofinv1", "retofinv", NULL, NULL, "1985", + "Return of the Invaders (bootleg set 1)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, retofin1RomInfo, retofin1RomName, NULL, NULL, RetofinvInputInfo, RetofinvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0xa00, + 224, 288, 3, 4 +}; + + +// Return of the Invaders (bootleg set 2) + +static struct BurnRomInfo retofin2RomDesc[] = { + { "ri-c.1e", 0x2000, 0xe3c31260, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "roi.01b", 0x2000, 0x3379f930, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ri-a.1c", 0x2000, 0x3ae7c530, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "a37-04.62", 0x2000, 0xd2899cc1, 2 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "a37-05.17", 0x2000, 0x9025abea, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 #2 Code + + { "a37-16.61", 0x2000, 0x4e3f501c, 4 | BRF_GRA }, // 5 Characters + + { "a37-10.8", 0x2000, 0x6afdeec8, 5 | BRF_GRA }, // 6 Sprites + { "a37-11.9", 0x2000, 0xd3dc9da3, 5 | BRF_GRA }, // 7 + { "a37-12.10", 0x2000, 0xd10b2eed, 5 | BRF_GRA }, // 8 + { "a37-13.11", 0x2000, 0x00ca6b3d, 5 | BRF_GRA }, // 9 + + { "a37-14.55", 0x2000, 0xef7f8651, 6 | BRF_GRA }, // 10 Tiles + { "a37-15.56", 0x2000, 0x03b40905, 6 | BRF_GRA }, // 11 + + { "a37-06.13", 0x0100, 0xe9643b8b, 7 | BRF_GRA }, // 12 Color Proms + { "a37-07.4", 0x0100, 0xe8f34e11, 7 | BRF_GRA }, // 13 + { "a37-08.3", 0x0100, 0x50030af0, 7 | BRF_GRA }, // 14 + { "82s191n", 0x0800, 0x93c891e3, 7 | BRF_GRA }, // 15 +}; + +STD_ROM_PICK(retofin2) +STD_ROM_FN(retofin2) + +struct BurnDriver BurnDrvRetofin2 = { + "retofinv2", "retofinv", NULL, NULL, "1985", + "Return of the Invaders (bootleg set 2)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, retofin2RomInfo, retofin2RomName, NULL, NULL, RetofinvInputInfo, RetofinvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0xa00, + 224, 288, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_route16.cpp b/src/burn/drivers/misc_pre90s/d_route16.cpp new file mode 100644 index 00000000..1b8b4eff --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_route16.cpp @@ -0,0 +1,1087 @@ +// FB Alpha Route 16 driver module +// Based on code by Zsolt Vasvari + +#include "burnint.h" +#include "driver.h" +#include "dac.h" +extern "C" { +#include "ay8910.h" +} + +//------------------------------------------------------------------------------------------------ + +static INT32 draw_type; +static UINT8 *Mem = NULL; +static UINT8 *Rom0, *Rom1, *Prom; + +static UINT8 flipscreen, palette_1, palette_2, ttmahjng_port_select; +static INT32 speakres_vrx; + +static INT16 *pAY8910Buffer[3]; +static INT16 *pFMBuffer = NULL; + +static UINT8 DrvJoy1[24], DrvJoy2[8], Dips, DrvReset; + +//------------------------------------------------------------------------------------------------ + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 2, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 3, "p1 left" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 1"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 0, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 1, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 4, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 1"}, + + {"Service Mode", BIT_DIGITAL, DrvJoy1 + 7, "diag" }, + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, &Dips , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo mahjongInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 1, "p1 start"}, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 2, "p2 start"}, + {"A", BIT_DIGITAL, DrvJoy1 + 3, "mah a"}, + {"E", BIT_DIGITAL, DrvJoy1 + 4, "mah e"}, + {"I", BIT_DIGITAL, DrvJoy1 + 5, "mah i"}, + {"M", BIT_DIGITAL, DrvJoy1 + 6, "mah m"}, + {"Kan", BIT_DIGITAL, DrvJoy1 + 7, "mah kan"}, + {"B", BIT_DIGITAL, DrvJoy1 + 8, "mah b"}, + {"F", BIT_DIGITAL, DrvJoy1 + 9, "mah f"}, + {"J", BIT_DIGITAL, DrvJoy1 + 10, "mah j"}, + {"N", BIT_DIGITAL, DrvJoy1 + 11, "mah n"}, + {"Reach", BIT_DIGITAL, DrvJoy1 + 12, "mah reach"}, + {"C", BIT_DIGITAL, DrvJoy1 + 13, "mah c"}, + {"G", BIT_DIGITAL, DrvJoy1 + 14, "mah g"}, + {"K", BIT_DIGITAL, DrvJoy1 + 15, "mah k"}, + {"Chi", BIT_DIGITAL, DrvJoy1 + 16, "mah chi"}, + {"Ron", BIT_DIGITAL, DrvJoy1 + 17, "mah ron"}, + {"D", BIT_DIGITAL, DrvJoy1 + 18, "mah d"}, + {"H", BIT_DIGITAL, DrvJoy1 + 19, "mah h"}, + {"L", BIT_DIGITAL, DrvJoy1 + 20, "mah l"}, + {"Pon", BIT_DIGITAL, DrvJoy1 + 21, "mah pon"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, +}; + +STDINPUTINFO(mahjong) + + + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x01, 0x00, "3" }, + {0x0f, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 3 , "Coinage" }, + {0x0f, 0x01, 0x18, 0x08, "2C_1C" }, + {0x0f, 0x01, 0x18, 0x00, "1C_1C" }, + {0x0f, 0x01, 0x18, 0x18, "1C_2C" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x20, 0x20, "Upright" }, + {0x0f, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo stratvoxDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0f, 0x01, 0x01, 0x00, "3" }, + {0x0f, 0x01, 0x01, 0x01, "5" }, + + {0 , 0xfe, 0 , 2 , "Replenish Astronauts" }, + {0x0f, 0x01, 0x02, 0x00, "No" }, + {0x0f, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 4 , "2 Attackers At Wave" }, + {0x0f, 0x01, 0x0c, 0x00, "2" }, + {0x0f, 0x01, 0x0c, 0x04, "3" }, + {0x0f, 0x01, 0x0c, 0x08, "4" }, + {0x0f, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 3 , "Astronauts Kidnapped" }, + {0x0f, 0x01, 0x10, 0x00, "Less Often" }, + {0x0f, 0x01, 0x10, 0x10, "More Often" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x20, 0x20, "Upright" }, + {0x0f, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(stratvox) + +static struct BurnDIPInfo speakresDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x20, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x03, 0x00, "3" }, + {0x0f, 0x01, 0x03, 0x01, "4" }, + {0x0f, 0x01, 0x03, 0x02, "5" }, + {0x0f, 0x01, 0x03, 0x03, "6" }, + + {0 , 0xfe, 0 , 4 , "2 Attackers At Wave" }, + {0x0f, 0x01, 0x0c, 0x00, "2" }, + {0x0f, 0x01, 0x0c, 0x04, "3" }, + {0x0f, 0x01, 0x0c, 0x08, "4" }, + {0x0f, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 3 , "Bonus Life" }, + {0x0f, 0x01, 0x10, 0x00, "5000" }, + {0x0f, 0x01, 0x10, 0x10, "8000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x20, 0x20, "Upright" }, + {0x0f, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x40, 0x00, "Off" }, + {0x0f, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x80, 0x00, "Off" }, + {0x0f, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(speakres) + + +//------------------------------------------------------------------------------------------------ + +static UINT8 ttmahjng_input_port_matrix_r() +{ + UINT8 ret = 0; + + switch (ttmahjng_port_select) + { + case 1: { + for (INT32 i = 0; i < 5; i++) ret |= DrvJoy1[ 3 + i] << i; + ret |= DrvJoy1[1] << 5; + } + break; + case 2: { + for (INT32 i = 0; i < 5; i++) ret |= DrvJoy1[ 8 + i] << i; + ret |= DrvJoy1[2] << 5; + } + break; + case 4: { + for (INT32 i = 0; i < 5; i++) ret |= DrvJoy1[13 + i] << i; + } + break; + case 8: { + for (INT32 i = 0; i < 4; i++) ret |= DrvJoy1[18 + i] << i; + } + break; + default: break; + } + + return ~ret; +} + + +UINT8 __fastcall route16_cpu0_read(UINT16 offset) +{ + UINT8 nRet = 0; + + switch (offset) + { + case 0x4800: + return Dips; + + case 0x5000: + { + if (draw_type == 1) { // ttmahjng + nRet = (DrvJoy1[0] << 7) ^ 0xff; + } else { + if (DrvJoy1[2]) nRet |= 0x01; + if (DrvJoy1[3]) nRet |= 0x02; + if (DrvJoy1[4]) nRet |= 0x04; + if (DrvJoy1[5]) nRet |= 0x08; + if (DrvJoy1[6]) nRet |= 0x10; + if (DrvJoy1[7]) nRet |= 0x40; // service mode + if (DrvJoy1[0]) nRet |= 0x80; // coin + } + return nRet; + } + + + case 0x5800: + { + if (draw_type == 1) { // ttmahjng + nRet = ttmahjng_input_port_matrix_r(); + } else { + if (DrvJoy2[1]) nRet |= 0x01; + if (DrvJoy2[2]) nRet |= 0x02; + if (DrvJoy2[3]) nRet |= 0x04; + if (DrvJoy2[4]) nRet |= 0x08; + if (DrvJoy2[5]) nRet |= 0x10; + if (DrvJoy2[0]) nRet |= 0x40; // start 2 + if (DrvJoy1[1]) nRet |= 0x80; // start 1 + } + + return nRet; + } + + case 0x6000: // speakres + { + INT32 bit2=4, bit1=2, bit0=1; + + // just using a counter, the constants are the number of reads + // before going low, each read is 40 cycles apart. the constants + // were chosen based on the startup tests and for vr0=vr2 + speakres_vrx++; + if(speakres_vrx>0x300) bit0=0; /* VR0 100k ohm - speech */ + if(speakres_vrx>0x200) bit1=0; /* VR1 50k ohm - main volume */ + if(speakres_vrx>0x300) bit2=0; /* VR2 100k ohm - explosion */ + + return 0xf8|bit2|bit1|bit0; + } + + case 0x6400: // routex + { + if (ZetPc(-1) == 0x2f) + return 0xfb; + else + return 0; + } + } + + return 0; +} + + +void __fastcall route16_cpu0_write(UINT16 offset, UINT8 data) +{ + if (offset >= 0x4000 && offset < 0x4400) { + Rom0[offset] = data; + + // 4313-4319 are used in Route 16 as triggers to wake the other CPU + if (offset >= 0x4313 && offset <= 0x4319 && data == 0xff) + { + // Let the other CPU run + // cpu_yield(); + ZetRunEnd(); // Correct? + } + + return; + } + + switch (offset) + { + case 0x2800: // stratvox + DACWrite(0, data); + break; + + case 0x4800: + palette_1 = data & 0x1f; + break; + + case 0x5000: + palette_2 = data & 0x1f; + flipscreen = (data >> 5) & 0x01; + break; + + case 0x5800: // speakres, ttmahjng + ttmahjng_port_select = data; + speakres_vrx = 0; + break; + + case 0x6800: // ttmahjng + AY8910Write(0, 1, data); + break; + + case 0x6900: // ttmahjng + AY8910Write(0, 0, data); + break; + } +} + +void __fastcall route16_cpu0_out(UINT16 offset, UINT8 data) +{ + switch (offset & 0x1ff) + { + case 0x000: + AY8910Write(0, 1, data); + break; + + case 0x100: + AY8910Write(0, 0, data); + break; + } +} + + +static INT32 GetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *Rom0Load = Rom0; + UINT8 *Rom1Load = Rom1; + UINT8 *PromLoad = Prom; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(Rom0Load, i, 1)) return 1; + Rom0Load += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(Rom1Load, i, 1)) return 1; + Rom1Load += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(PromLoad, i, 1)) return 1; + PromLoad += ri.nLen; + continue; + } + } + + return 0; +} + + +static INT32 DrvDoReset() +{ + flipscreen = palette_1 = palette_2 = ttmahjng_port_select = 0; + speakres_vrx = 0; + + DrvReset = 0; + + memset (Rom0 + 0x4000, 0, 0xc000); // Shared & video ram + memset (Rom1 + 0x8000, 0, 0x4000); + + ZetOpen(0); + ZetReset(); + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + return 0; +} + +void stratvox_sn76477_write(UINT32, UINT32) +{ + +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x10000 + 0x200); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)BurnMalloc (nBurnSoundLen * 3 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom0 = Mem + 0x00000; + Rom1 = Mem + 0x10000; + Prom = Mem + 0x20000; + + // Load Roms + if (GetRoms()) return 1; + + ZetInit(2); + ZetOpen(0); + ZetSetOutHandler(route16_cpu0_out); + ZetSetReadHandler(route16_cpu0_read); + ZetSetWriteHandler(route16_cpu0_write); + ZetMapArea (0x0000, 0x3fff, 0, Rom0 + 0x0000); // ROM + ZetMapArea (0x0000, 0x3fff, 2, Rom0 + 0x0000); + ZetMapArea (0x4000, 0x43ff, 0, Rom0 + 0x4000); // Read Shared RAM + ZetMapArea (0x8000, 0xbfff, 0, Rom0 + 0x8000); // Video RAM + ZetMapArea (0x8000, 0xbfff, 1, Rom0 + 0x8000); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetWriteHandler(route16_cpu0_write); + ZetMapArea (0x0000, 0x1fff, 0, Rom1 + 0x0000); // ROM + ZetMapArea (0x0000, 0x1fff, 2, Rom1 + 0x0000); + ZetMapArea (0x4000, 0x43ff, 0, Rom0 + 0x4000); // Read Shared RAM + ZetMapArea (0x8000, 0xbfff, 0, Rom1 + 0x8000); // Video RAM + ZetMapArea (0x8000, 0xbfff, 1, Rom1 + 0x8000); + ZetMemEnd(); + ZetClose(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + + AY8910Init(0, 1250000, nBurnSoundRate, NULL, NULL, &stratvox_sn76477_write, NULL); + + DACInit(0, 0, 1); + DACSetVolShift(0, 2); + + DrvDoReset(); + + return 0; +} + + +static INT32 DrvExit() +{ + DACExit(); + ZetExit(); + AY8910Exit(0); + + BurnFree (Mem); + BurnFree (pFMBuffer); + + draw_type = 0; + + pFMBuffer = NULL; + Mem = NULL; + Rom0 = Rom1 = Prom = NULL; + pAY8910Buffer[0] = pAY8910Buffer[1] = pAY8910Buffer[2] = NULL; + + return 0; +} + + +//------------------------------------------------------------------------------------------------ +// Drawing functions + +static inline UINT32 route16_make_pen(UINT8 color) +{ + UINT32 ret = 0; + if (color & 1) ret |= 0x00ff0000; + if (color & 2) ret |= 0x0000ff00; + if (color & 4) ret |= 0x000000ff; + return ret; +} + + +static inline UINT32 ttmajng_make_pen(UINT8 color) +{ + UINT32 ret = 0; + if (color & 4) ret |= 0x00ff0000; + if (color & 2) ret |= 0x0000ff00; + if (color & 1) ret |= 0x000000ff; + return ret; +} + + +static INT32 DrvDraw() +{ + UINT8 *prom1 = Prom + 0x0000; + UINT8 *prom2 = Prom + 0x0100; + + for (INT32 offs = 0; offs < 0x4000; offs++) + { + UINT8 y = offs >> 6; + UINT8 x = offs << 2; + + UINT8 d1 = Rom0[0x8000 + offs]; + UINT8 d2 = Rom1[0x8000 + offs]; + + for (INT32 i = 0; i < 4; i++) + { + UINT8 color1, color2; + + // stratvox & ttmahjng + if (draw_type) { + color1 = prom1[(palette_1 << 2) | ((d1 >> 3) & 2) | (d1 & 1)]; + color2 = prom2[(((d1 << 3) & 0x80) | ((d1 << 7) & 0x80)) | (palette_2 << 2) | ((d2 >> 3) & 2) | (d2 & 1)]; + } else { + color1 = prom1[((palette_1 << 6) & 0x80) | (palette_1 << 2) | ((d1 >> 3) & 0x02) | ((d1 >> 0) & 0x01)]; + color2 = prom2[((palette_2 << 6) & 0x80) | (((color1 << 6) & 0x80) | ((color1 << 7) & 0x80)) | (palette_2 << 2) | ((d2 >> 3) & 2) | (d2 & 1)]; + } + + UINT8 final_color = color1 | color2; + + UINT32 pen; + if (draw_type == 1) { + pen = ttmajng_make_pen(final_color); + } else { + pen = route16_make_pen(final_color); + } + + if (flipscreen) + PutPix(pBurnDraw + ((x << 8) | (y ^ 0xff)) * nBurnBpp, BurnHighCol(pen>>16, pen>>8, pen, 0)); + else + PutPix(pBurnDraw + (((x ^ 0xff) << 8) | y) * nBurnBpp, BurnHighCol(pen>>16, pen>>8, pen, 0)); + + x += 1; + d1 >>= 1; + d2 >>= 1; + } + } + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = nBurnSoundLen; + + INT32 DACIRQFireSlice[48]; + for (INT32 i = 0; i < 48; i++) { + DACIRQFireSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 49)); + } + + INT32 nCyclesSegment; + INT32 nCyclesDone[2], nCyclesTotal[2]; + + nCyclesTotal[0] = 2500000 / 60; + nCyclesTotal[1] = 2500000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #0 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i+1 == nInterleave) ZetRaiseIrq(1); + ZetClose(); + + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (draw_type == 3) { // space echo + for (INT32 j = 0; j < 48; j++) { + if (i == DACIRQFireSlice[j]) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + } + } + } + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + + DACUpdate(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + + DACUpdate(pSoundBuf, nSegmentLength); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------ +// Savestates + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom0 + 0x4000; + ba.nLen = 0x0400; + ba.szName = "Shared RAM"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom0 + 0x8000; + ba.nLen = 0x4000; + ba.szName = "Cpu0 Video RAM"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = Rom1 + 0x8000; + ba.nLen = 0x4000; + ba.szName = "Cpu1 Video RAM"; + BurnAcb(&ba); + + ZetScan(nAction); // Scan Z80 + AY8910Scan(nAction, pnMin); // Scan AY8910 + + // Scan critical driver variables + SCAN_VAR(flipscreen); + SCAN_VAR(palette_1); + SCAN_VAR(palette_2); + SCAN_VAR(ttmahjng_port_select); + SCAN_VAR(speakres_vrx); + } + + return 0; +} + + +//------------------------------------------------------------------------------------------------ +// Drivers + + +// Route 16 + +static struct BurnRomInfo route16RomDesc[] = { + { "route16.a0", 0x0800, 0x8f9101bd, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "route16.a1", 0x0800, 0x389bc077, 1 | BRF_ESS | BRF_PRG }, // 1 + { "route16.a2", 0x0800, 0x1065a468, 1 | BRF_ESS | BRF_PRG }, // 2 + { "route16.a3", 0x0800, 0x0b1987f3, 1 | BRF_ESS | BRF_PRG }, // 3 + { "route16.a4", 0x0800, 0xf67d853a, 1 | BRF_ESS | BRF_PRG }, // 4 + { "route16.a5", 0x0800, 0xd85cf758, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "route16.b0", 0x0800, 0x0f9588a7, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "route16.b1", 0x0800, 0x2b326cf9, 2 | BRF_ESS | BRF_PRG }, // 7 + { "route16.b2", 0x0800, 0x529cad13, 2 | BRF_ESS | BRF_PRG }, // 8 + { "route16.b3", 0x0800, 0x3bd8b899, 2 | BRF_ESS | BRF_PRG }, // 9 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 10 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(route16) +STD_ROM_FN(route16) + +static INT32 route16Init() +{ + INT32 nRet; + + draw_type = 0; + + nRet = DrvInit(); + + if (nRet == 0) + { + // Patch protection + Rom0[0x00e9] = 0x3a; + Rom0[0x0754] = 0xc3; + Rom0[0x0755] = 0x63; + Rom0[0x0756] = 0x07; + } + + return nRet; +} + +struct BurnDriver BurnDrvroute16 = { + "route16", NULL, NULL, NULL, "1981", + "Route 16\0", NULL, "Tehkan/Sun (Centuri license)", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, route16RomInfo, route16RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + route16Init, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Route 16 (set 2) + +static struct BurnRomInfo route16aRomDesc[] = { + { "vg-54", 0x0800, 0x0c966319, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "vg-55", 0x0800, 0xa6a8c212, 1 | BRF_ESS | BRF_PRG }, // 1 + { "vg-56", 0x0800, 0x5c74406a, 1 | BRF_ESS | BRF_PRG }, // 2 + { "vg-57", 0x0800, 0x313e68ab, 1 | BRF_ESS | BRF_PRG }, // 3 + { "vg-58", 0x0800, 0x40824e3c, 1 | BRF_ESS | BRF_PRG }, // 4 + { "vg-59", 0x0800, 0x9313d2c2, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "route16.b0", 0x0800, 0x0f9588a7, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "vg-61", 0x0800, 0xb216c88c, 2 | BRF_ESS | BRF_PRG }, // 7 + { "route16.b2", 0x0800, 0x529cad13, 2 | BRF_ESS | BRF_PRG }, // 8 + { "route16.b3", 0x0800, 0x3bd8b899, 2 | BRF_ESS | BRF_PRG }, // 9 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 10 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(route16a) +STD_ROM_FN(route16a) + +static INT32 route16aInit() +{ + INT32 nRet; + + draw_type = 0; + + nRet = DrvInit(); + + if (nRet == 0) + { + // Patch protection + Rom0[0x00e9] = 0x3a; + + Rom0[0x0105] = 0x00; // jp nz,$4109 (nirvana) - NOP's in route16 + Rom0[0x0106] = 0x00; + Rom0[0x0107] = 0x00; + + Rom0[0x0731] = 0x00; // jp nz,$4238 (nirvana) + Rom0[0x0732] = 0x00; + Rom0[0x0733] = 0x00; + + Rom0[0x0747] = 0xc3; + Rom0[0x0748] = 0x56; + Rom0[0x0749] = 0x07; + } + + return nRet; +} + +struct BurnDriver BurnDrvroute16a = { + "route16a", "route16", NULL, NULL, "1981", + "Route 16 (set 2)\0", NULL, "Tehkan/Sun (Centuri license)", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, route16aRomInfo, route16aRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + route16aInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Route 16 (bootleg) + +static struct BurnRomInfo route16bRomDesc[] = { + { "rt16.0", 0x0800, 0xb1f0f636, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "rt16.1", 0x0800, 0x3ec52fe5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "rt16.2", 0x0800, 0xa8e92871, 1 | BRF_ESS | BRF_PRG }, // 2 + { "rt16.3", 0x0800, 0xa0fc9fc5, 1 | BRF_ESS | BRF_PRG }, // 3 + { "rt16.4", 0x0800, 0x6dcaf8c4, 1 | BRF_ESS | BRF_PRG }, // 4 + { "rt16.5", 0x0800, 0x63d7b05b, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "rt16.6", 0x0800, 0xfef605f3, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "rt16.7", 0x0800, 0xd0d6c189, 2 | BRF_ESS | BRF_PRG }, // 7 + { "rt16.8", 0x0800, 0xdefc5797, 2 | BRF_ESS | BRF_PRG }, // 8 + { "rt16.9", 0x0800, 0x88d94a66, 2 | BRF_ESS | BRF_PRG }, // 9 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 10 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(route16b) +STD_ROM_FN(route16b) + +static INT32 route16bInit() +{ + draw_type = 0; + + return DrvInit(); +} + +struct BurnDriver BurnDrvroute16b = { + "route16b", "route16", NULL, NULL, "1981", + "Route 16 (bootleg)\0", NULL, "bootleg", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, route16bRomInfo, route16bRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + route16Init, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Route X (bootleg) + +static struct BurnRomInfo routexRomDesc[] = { + { "routex01.a0", 0x0800, 0x99b500e7, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "rt16.1", 0x0800, 0x3ec52fe5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "rt16.2", 0x0800, 0xa8e92871, 1 | BRF_ESS | BRF_PRG }, // 2 + { "rt16.3", 0x0800, 0xa0fc9fc5, 1 | BRF_ESS | BRF_PRG }, // 3 + { "routex05.a4", 0x0800, 0x2fef7653, 1 | BRF_ESS | BRF_PRG }, // 4 + { "routex06.a5", 0x0800, 0xa39ef648, 1 | BRF_ESS | BRF_PRG }, // 5 + { "routex07.a6", 0x0800, 0x89f80c1c, 1 | BRF_ESS | BRF_PRG }, // 6 + + { "routex11.b0", 0x0800, 0xb51edd1d, 2 | BRF_ESS | BRF_PRG }, // 7 Z80 #1 Code + { "rt16.7", 0x0800, 0xd0d6c189, 2 | BRF_ESS | BRF_PRG }, // 8 + { "rt16.8", 0x0800, 0xdefc5797, 2 | BRF_ESS | BRF_PRG }, // 9 + { "rt16.9", 0x0800, 0x88d94a66, 2 | BRF_ESS | BRF_PRG }, // 10 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 11 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(routex) +STD_ROM_FN(routex) + +struct BurnDriver BurnDrvroutex = { + "routex", "route16", NULL, NULL, "1981", + "Route X (bootleg)\0", NULL, "bootleg", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, routexRomInfo, routexRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + route16bInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Speak & Rescue + +static struct BurnRomInfo speakresRomDesc[] = { + { "speakres.1", 0x0800, 0x6026e4ea, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "speakres.2", 0x0800, 0x93f0d4da, 1 | BRF_ESS | BRF_PRG }, // 1 + { "speakres.3", 0x0800, 0xa3874304, 1 | BRF_ESS | BRF_PRG }, // 2 + { "speakres.4", 0x0800, 0xf484be3a, 1 | BRF_ESS | BRF_PRG }, // 3 + { "speakres.5", 0x0800, 0x61b12a67, 1 | BRF_ESS | BRF_PRG }, // 4 + { "speakres.6", 0x0800, 0x220e0ab2, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "speakres.7", 0x0800, 0xd417be13, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "speakres.8", 0x0800, 0x52485d60, 2 | BRF_ESS | BRF_PRG }, // 7 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 8 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(speakres) +STD_ROM_FN(speakres) + +static INT32 speakresInit() +{ + draw_type = 2; + + return DrvInit(); +} + +struct BurnDriver BurnDrvspeakres = { + "speakres", NULL, NULL, NULL, "1980", + "Speak & Rescue\0", NULL, "Sun Electronics", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, speakresRomInfo, speakresRomName, NULL, NULL, DrvInputInfo, speakresDIPInfo, + speakresInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Stratovox + +static struct BurnRomInfo stratvoxRomDesc[] = { + { "ls01.bin", 0x0800, 0xbf4d582e, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "ls02.bin", 0x0800, 0x16739dd4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ls03.bin", 0x0800, 0x083c28de, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ls04.bin", 0x0800, 0xb0927e3b, 1 | BRF_ESS | BRF_PRG }, // 3 + { "ls05.bin", 0x0800, 0xccd25c4e, 1 | BRF_ESS | BRF_PRG }, // 4 + { "ls06.bin", 0x0800, 0x07a907a7, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "ls07.bin", 0x0800, 0x4d333985, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "ls08.bin", 0x0800, 0x35b753fc, 2 | BRF_ESS | BRF_PRG }, // 7 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 8 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(stratvox) +STD_ROM_FN(stratvox) + +struct BurnDriver BurnDrvstratvox = { + "stratvox", "speakres", NULL, NULL, "1980", + "Stratovox\0", NULL, "[Sun Electronics] (Taito license)", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, stratvoxRomInfo, stratvoxRomName, NULL, NULL, DrvInputInfo, stratvoxDIPInfo, + speakresInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Stratovox (bootleg) + +static struct BurnRomInfo stratvobRomDesc[] = { + { "j0-1", 0x0800, 0x93c78274, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "j0-2", 0x0800, 0x93b2b02d, 1 | BRF_ESS | BRF_PRG }, // 1 + { "j0-3", 0x0800, 0x655facb5, 1 | BRF_ESS | BRF_PRG }, // 2 + { "j0-4", 0x0800, 0xb0927e3b, 1 | BRF_ESS | BRF_PRG }, // 3 + { "j0-5", 0x0800, 0x9d2178d9, 1 | BRF_ESS | BRF_PRG }, // 4 + { "j0-6", 0x0800, 0x79118ffc, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "b0-a", 0x0800, 0x4d333985, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "j0-a", 0x0800, 0x3416a830, 2 | BRF_ESS | BRF_PRG }, // 7 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 8 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(stratvob) +STD_ROM_FN(stratvob) + +struct BurnDriver BurnDrvstratvob = { + "stratvoxb", "speakres", NULL, NULL, "1980", + "Stratovox (bootleg)\0", NULL, "bootleg", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, stratvobRomInfo, stratvobRomName, NULL, NULL, DrvInputInfo, stratvoxDIPInfo, + speakresInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Space Echo (bootleg) + +static struct BurnRomInfo spacechoRomDesc[] = { + { "rom.a0", 0x0800, 0x40d74dce, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "rom.a1", 0x0800, 0xa5f0a34f, 1 | BRF_ESS | BRF_PRG }, // 1 + { "rom.a2", 0x0800, 0xcbbb3acb, 1 | BRF_ESS | BRF_PRG }, // 2 + { "rom.a3", 0x0800, 0x311050ca, 1 | BRF_ESS | BRF_PRG }, // 3 + { "rom.a4", 0x0800, 0x28943803, 1 | BRF_ESS | BRF_PRG }, // 4 + { "rom.a5", 0x0800, 0x851c9f28, 1 | BRF_ESS | BRF_PRG }, // 5 + + { "rom.b0", 0x0800, 0xdb45689d, 2 | BRF_ESS | BRF_PRG }, // 6 Z80 #1 Code + { "rom.b2", 0x0800, 0x1e074157, 2 | BRF_ESS | BRF_PRG }, // 7 + { "rom.b3", 0x0800, 0xd50a8b20, 2 | BRF_ESS | BRF_PRG }, // 8 + + { "im5623.f10", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 9 Graphics + { "im5623.f12", 0x0100, 0x08793ef7, 3 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(spacecho) +STD_ROM_FN(spacecho) + +static INT32 spacechoInit() +{ + INT32 nRet; + + draw_type = 3; + + nRet = DrvInit(); + + memcpy (Rom1 + 0x1000, Rom1 + 0x800, 0x1000); + + return nRet; +} + +struct BurnDriver BurnDrvspacecho = { + "spacecho", "speakres", NULL, NULL, "1980", + "Space Echo (bootleg)\0", NULL, "bootleg", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, spacechoRomInfo, spacechoRomName, NULL, NULL, DrvInputInfo, stratvoxDIPInfo, + spacechoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 3, 4 +}; + + +// Mahjong + +static struct BurnRomInfo ttmahjngRomDesc[] = { + { "ju04", 0x1000, 0xfe7c693a, 1 | BRF_ESS | BRF_PRG }, // 0 Z80 #0 Code + { "ju05", 0x1000, 0x985723d3, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ju06", 0x1000, 0x2cd69bc8, 1 | BRF_ESS | BRF_PRG }, // 2 + { "ju07", 0x1000, 0x30e8ec63, 1 | BRF_ESS | BRF_PRG }, // 3 + + { "ju01", 0x0800, 0x0f05ca3c, 2 | BRF_ESS | BRF_PRG }, // 4 Z80 #1 Code + { "ju02", 0x0800, 0xc1ffeceb, 2 | BRF_ESS | BRF_PRG }, // 5 + { "ju08", 0x0800, 0x2dcc76b5, 2 | BRF_ESS | BRF_PRG }, // 6 + + { "ju03", 0x0100, 0x27d47624, 3 | BRF_GRA }, // 7 Graphics + { "ju09", 0x0100, 0x27d47624, 3 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(ttmahjng) +STD_ROM_FN(ttmahjng) + +static INT32 ttmahjngInit() +{ + draw_type = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvttmahjng = { + "ttmahjng", NULL, NULL, NULL, "1980", + "Mahjong\0", NULL, "Taito", "Route 16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MAHJONG, 0, + NULL, ttmahjngRomInfo, ttmahjngRomName, NULL, NULL, mahjongInputInfo, NULL, + ttmahjngInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0, + 256, 256, 4, 3 +}; + + diff --git a/src/burn/drivers/misc_pre90s/d_scotrsht.cpp b/src/burn/drivers/misc_pre90s/d_scotrsht.cpp new file mode 100644 index 00000000..51223a7a --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_scotrsht.cpp @@ -0,0 +1,650 @@ +// FB Alpha Scooter Shooter driver module +// Based on MAME driver by Pierpaolo Prazzoli + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static UINT8 *scroll; + +static UINT8 *soundlatch; +static UINT8 *charbank; +static UINT8 *irq_enable; +static UINT8 *flipscreen; +static UINT8 *palbank; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvReset; +static UINT8 DrvDips[3]; +static UINT8 DrvInputs[3]; + +static struct BurnInputInfo ScotrshtInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Scotrsht) + +static struct BurnDIPInfo ScotrshtDIPList[]= +{ + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0x5d, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 16, "Coin A" }, + {0x10, 0x01, 0x0f, 0x02, "4 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x05, "3 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x08, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" }, + {0x10, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" }, + {0x10, 0x01, 0x0f, 0x0f, "1 Coin 1 Credits" }, + {0x10, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" }, + {0x10, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" }, + {0x10, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x10, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" }, + {0x10, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x10, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x10, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x10, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x10, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x10, 0x01, 0x0f, 0x00, "Invalid" }, + + {0 , 0xfe, 0 , 16, "Coin B" }, + {0x10, 0x01, 0xf0, 0x20, "4 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x50, "3 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x80, "2 Coins 1 Credits" }, + {0x10, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" }, + {0x10, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" }, + {0x10, 0x01, 0xf0, 0xf0, "1 Coin 1 Credits" }, + {0x10, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" }, + {0x10, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" }, + {0x10, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" }, + {0x10, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x10, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x10, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x10, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x10, 0x01, 0xf0, 0x00, "Invalid" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x03, 0x03, "2" }, + {0x11, 0x01, 0x03, 0x02, "3" }, + {0x11, 0x01, 0x03, 0x01, "4" }, + {0x11, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x11, 0x01, 0x08, 0x08, "30K 80K" }, + {0x11, 0x01, 0x08, 0x00, "40K 90K" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x30, 0x30, "Easy" }, + {0x11, 0x01, 0x30, 0x20, "Normal" }, + {0x11, 0x01, 0x30, 0x10, "Difficult" }, + {0x11, 0x01, 0x30, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, +}; + +STDDIPINFO(Scotrsht) + +void scotrsht_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x2043: + *charbank = data & 1; + return; + + case 0x2044: + *irq_enable = data & 2; + *flipscreen = data & 8; + return; + + case 0x3000: + *palbank = (data & 0x70) >> 4; + return; + + case 0x3100: + *soundlatch = data; + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + return; + + case 0x3300: + // watchdog + return; + } + + if ((address & 0xffe0) == 0x2000) { + scroll[address & 0x1f] = data; + return; + } +} + +UINT8 scotrsht_main_read(UINT16 address) +{ + switch (address) + { + case 0x3100: + return DrvDips[1]; + + case 0x3200: + return DrvDips[2]; + + case 0x3300: + return DrvInputs[0]; + + case 0x3301: + return DrvInputs[1]; + + case 0x3302: + return DrvInputs[2]; + + case 0x3303: + return DrvDips[0]; + } + + if ((address & 0xffe0) == 0x2000) { + return scroll[address & 0x1f]; + } + + return 0; +} + +UINT8 __fastcall scotrsht_sound_read(UINT16 address) +{ + if (address == 0x8000) { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +void __fastcall scotrsht_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + BurnYM2203Write(0, port & 1, data); + return; + } +} + +UINT8 __fastcall scotrsht_sound_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + case 0x01: + return BurnYM2203Read(0, port & 1); + } + + return 0; +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3072000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3072000.0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x010000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x020000; + + DrvColPROM = Next; Next += 0x000500; + + DrvPalette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + Palette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + AllRam = Next; + + scroll = Next; Next += 0x000020; + + DrvSprRAM = Next; Next += 0x001000; + DrvColRAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000800; + + DrvZ80RAM = Next; Next += 0x000400; + + soundlatch = Next; Next += 0x000001; + charbank = Next; Next += 0x000001; + irq_enable = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + palbank = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) + { + INT32 r = DrvColPROM[i + 0x000] & 0x0f; + INT32 g = DrvColPROM[i + 0x100] & 0x0f; + INT32 b = DrvColPROM[i + 0x200] & 0x0f; + + DrvPalette[i] = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | (b << 0); + } + + for (INT32 i = 0; i < 0x200; i++) { + for (INT32 j = 0; j < 8; j++) { + INT32 col = ((~i & 0x100) >> 1) | (j << 4) | (DrvColPROM[i + 0x300] & 0x0f); + Palette[((i & 0x100) << 3) | (j << 8) | (i & 0xff)] = DrvPalette[col]; + } + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[4] = { 0x000, 0x001, 0x002, 0x003 }; + INT32 XOffs[16] = { 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x100, 0x104, 0x108, 0x10c, 0x110, 0x114, 0x118, 0x11c }; + INT32 YOffs[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 4, 8, 8, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x10000); + + GfxDecode(0x0200, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x08000, 0, 1)) return 1; + memcpy (DrvM6809ROM + 0x4000, DrvM6809ROM + 0xc000, 0x4000); + if (BurnLoadRom(DrvM6809ROM + 0x0c000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 5, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 7, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 8, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00300, 9, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00400, 10, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvColRAM, 0x0000, 0x07ff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x0800, 0x0fff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x1000, 0x1fff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x04000, 0x4000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(scotrsht_main_write); + M6809SetReadByteHandler(scotrsht_main_read); + M6809Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM); + ZetMapArea(0x4000, 0x43ff, 0, DrvZ80RAM); + ZetMapArea(0x4000, 0x43ff, 1, DrvZ80RAM); + ZetMapArea(0x4000, 0x43ff, 2, DrvZ80RAM); + ZetSetReadHandler(scotrsht_sound_read); + ZetSetOutHandler(scotrsht_sound_out); + ZetSetInHandler(scotrsht_sound_in); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 3072000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(3072000); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + M6809Exit(); + ZetExit(); + + BurnYM2203Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_layer() +{ + for (INT32 offs = 0x0000; offs < 0x0800; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + if (sx & 0x100) continue; + + sy -= scroll[offs & 0x1f]; + if (sy < -7) sy += 256; + + INT32 attr = DrvColRAM[offs]; + INT32 code = DrvVidRAM[offs] | (*charbank << 9) | ((attr & 0x40) << 2); + INT32 color= (attr & 0x0f) | (*palbank << 4); + INT32 flipx = attr & 0x10; + INT32 flipy = attr & 0x20; + + if (*flipscreen) + { + flipx = !flipx; + flipy = !flipy; + sy = 248 - sy; + sx = 248 - sx; + } + + sy -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM0); + } + } + } +} + +static void draw_sprites() +{ + for (INT32 i = 0; i < 0xc0; i += 4) + { + INT32 attr = DrvSprRAM[i + 1]; + INT32 code = DrvSprRAM[i + 0] + ((attr & 0x40) << 2); + INT32 sx = DrvSprRAM[i + 2] - ((attr & 0x80) << 1); + INT32 sy = DrvSprRAM[i + 3]; + INT32 color = (attr & 0x0f) | (*palbank << 4); + INT32 flipx = attr & 0x10; + INT32 flipy = attr & 0x20; + + if (*flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 16; + + { + if (flipx) flipx = 0x0f; + if (flipy) flipx |= 0xf0; + + color = (color << 4) | 0x800; + + UINT8 *src = DrvGfxROM1 + (code << 8); + + for (INT32 y = 0; y < 16; y++, sy++) + { + if (sy < 0 || sy >= nScreenHeight) continue; + + INT32 xx = sx; + + for (INT32 x = 0; x < 16; x++, xx++) + { + if (xx < 0 || xx >= nScreenWidth) continue; + + INT32 pxl = src[((y << 4) | x) ^ flipx] | color; + INT32 trans = DrvPalette[pxl & 0xfff]; + + if (trans) { + pTransDraw[(sy * nScreenWidth) + xx] = pxl; + } + } + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x1000; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + BurnTransferClear(); + draw_layer(); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + + // Clear opposites + if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03; + if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c; + if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03; + if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c; + } + + INT32 nInterleave = 100; + INT32 nCyclesTotal[2] = { 3072000 / 60, 3072000 / 60 }; + + M6809Open(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + + M6809Run(nCyclesTotal[0] / nInterleave); + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (*irq_enable) M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + M6809Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029706; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + M6809Scan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + } + + return 0; +} + + +// Scooter Shooter + +static struct BurnRomInfo scotrshtRomDesc[] = { + { "gx545_g03_12c.bin", 0x8000, 0xb808e0d3, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "gx545_g02_10c.bin", 0x4000, 0xb22c0586, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gx545_g01_8c.bin", 0x4000, 0x46a7cc65, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "gx545_g05_5f.bin", 0x8000, 0x856c349c, 3 | BRF_GRA }, // 3 Characters + + { "gx545_g06_6f.bin", 0x8000, 0x14ad7601, 4 | BRF_GRA }, // 4 Sprites + { "gx545_h04_4f.bin", 0x8000, 0xc06c11a3, 4 | BRF_GRA }, // 5 + + { "gx545_6301_1f.bin", 0x0100, 0xf584586f, 5 | BRF_GRA }, // 6 Color Proms + { "gx545_6301_2f.bin", 0x0100, 0xad464db1, 5 | BRF_GRA }, // 7 + { "gx545_6301_3f.bin", 0x0100, 0xbd475d23, 5 | BRF_GRA }, // 8 + { "gx545_6301_7f.bin", 0x0100, 0x2b0cd233, 5 | BRF_GRA }, // 9 + { "gx545_6301_8f.bin", 0x0100, 0xc1c7cf58, 5 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(scotrsht) +STD_ROM_FN(scotrsht) + +struct BurnDriver BurnDrvScotrsht = { + "scotrsht", NULL, NULL, NULL, "1985", + "Scooter Shooter\0", NULL, "Konami", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, scotrshtRomInfo, scotrshtRomName, NULL, NULL, ScotrshtInputInfo, ScotrshtDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_scregg.cpp b/src/burn/drivers/misc_pre90s/d_scregg.cpp new file mode 100644 index 00000000..c6c99efb --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_scregg.cpp @@ -0,0 +1,724 @@ +#include "tiles_generic.h" +#include "m6502_intf.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *Rom, *Gfx0, *Gfx1, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvDips[2], DrvReset; +static UINT32 *Palette, *DrvPalette; +static UINT8 DrvRecalcPal = 0; +static INT16 *pFMBuffer, *pAY8910Buffer[6]; + +static INT32 flipscreen = 0; +static INT32 VBLK = 0; + +static INT32 scregg = 0, rockduck = 0; + +static struct BurnInputInfo DrvInputList[] = { + {"P1 Coin" , BIT_DIGITAL , DrvJoy1 + 6, "p1 coin" }, + {"P1 start" , BIT_DIGITAL , DrvJoy2 + 6, "p1 start" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 1, "p1 left" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + + {"P2 Coin" , BIT_DIGITAL , DrvJoy1 + 7, "p2 coin" }, + {"P2 start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p2 left" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x03, 0x00, "2C 1C" }, + {0x0f, 0x01, 0x03, 0x03, "1C 1C" }, + {0x0f, 0x01, 0x03, 0x01, "1C 2C" }, + {0x0f, 0x01, 0x03, 0x02, "1C 3C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0x0c, 0x00, "2C 1C" }, + {0x0f, 0x01, 0x0c, 0x0c, "1C 3C" }, + {0x0f, 0x01, 0x0c, 0x04, "1C 2C" }, + {0x0f, 0x01, 0x0c, 0x08, "1C 3C" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x40, 0x40, "Cocktail" }, + {0x0f, 0x01, 0x40, 0x00, "Upright" }, + + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x10, 0x01, 0x01, 0x01, "3" }, + {0x10, 0x01, 0x01, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x06, 0x04, "30000" }, + {0x10, 0x01, 0x06, 0x02, "50000" }, + {0x10, 0x01, 0x06, 0x06, "70000" }, + {0x10, 0x01, 0x06, 0x00, "Never" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x80, 0x80, "Easy" }, + {0x10, 0x01, 0x80, 0x00, "Hard" }, +}; + +STDDIPINFO(Drv) + +static inline INT32 calc_mirror_offset(UINT16 address) +{ + INT32 x, y, offset; + offset = address & 0x3ff; + + x = offset >> 5; + y = offset & 0x1f; + + return ((y << 5) | x); +} + +UINT8 eggs_readmem(UINT16 address) +{ + UINT8 ret = 0xff; + + if ((address & 0xf800) == 0x1800) { + return Rom[0x2000 + (address & 0x400) + calc_mirror_offset(address)]; + } + + switch (address) + { + case 0x2000: + return VBLK | DrvDips[0]; + + case 0x2001: + return DrvDips[1]; + + case 0x2002: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy1[i] << i; + + return ret; + } + + case 0x2003: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy2[i] << i; + + return ret; + } + } + + return 0; +} + +void eggs_writemem(UINT16 address, UINT8 data) +{ + if ((address & 0xf800) == 0x1800) { + Rom[0x2000 + (address & 0x400) + calc_mirror_offset(address)] = data; + return; + } + + switch (address) + { + case 0x2000: + flipscreen = data & 1; + break; + + case 0x2001: + break; + + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + AY8910Write((address >> 1) & 1, address & 1, data); + break; + } +} + +UINT8 dommy_readmem(UINT16 address) +{ + UINT8 ret = 0xff; + + if (address >= 0x2800 && address <= 0x2bff) { + return Rom[0x2000 + calc_mirror_offset(address)]; + } + + switch (address) + { + case 0x4000: + return DrvDips[0] | VBLK; + + case 0x4001: + return DrvDips[1]; + + case 0x4002: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy1[i] << i; + + return ret; + } + + case 0x4003: + { + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy2[i] << i; + + return ret; + } + } + + return 0; +} + +void dommy_writemem(UINT16 address, UINT8 data) +{ + if (address >= 0x2800 && address <= 0x2bff) { + Rom[0x2000 + calc_mirror_offset(address)] = data; + return; + } + + switch (address) + { + case 0x4000: + break; + + case 0x4001: + flipscreen = data & 1; + break; + + case 0x4004: + case 0x4005: + case 0x4006: + case 0x4007: + AY8910Write((address >> 1) & 1, address & 1, data); + break; + } +} + + +static INT32 DrvDoReset() +{ + memset (Rom, 0, 0x3000); + + flipscreen = 0; + + M6502Open(0); + M6502Reset(); + M6502Close(); + + AY8910Reset(0); + AY8910Reset(1); + + return 0; +} + + +static INT32 scregg_gfx_convert() +{ + static INT32 PlaneOffsets[3] = { 0x20000, 0x10000, 0 }; + static INT32 XOffsets[16] = { 128, 129, 130, 131, 132, 133, 134, 135, 0, 1, 2, 3, 4, 5, 6, 7 }; + static INT32 YOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x6000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x6000); + + GfxDecode(0x400, 3, 8, 8, PlaneOffsets, XOffsets + 8, YOffsets, 0x040, tmp, Gfx0); + GfxDecode(0x100, 3, 16, 16, PlaneOffsets, XOffsets + 0, YOffsets, 0x100, tmp, Gfx1); + + BurnFree (tmp); + + return 0; +} + +static INT32 scregg_palette_init() +{ + for (INT32 i = 0;i < 8;i++) + { + INT32 bit0,bit1,bit2,r,g,b; + + bit0 = (Prom[i] >> 0) & 0x01; + bit1 = (Prom[i] >> 1) & 0x01; + bit2 = (Prom[i] >> 2) & 0x01; + r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (Prom[i] >> 3) & 0x01; + bit1 = (Prom[i] >> 4) & 0x01; + bit2 = (Prom[i] >> 5) & 0x01; + g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (Prom[i] >> 6) & 0x01; + bit2 = (Prom[i] >> 7) & 0x01; + b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + Palette[i] = (r << 16) | (g << 8) | b; + } + + return 0; +} + +static INT32 DrvInit() +{ + Mem = (UINT8*)BurnMalloc(0x10000 + 0x10000 + 0x10000 + (0x08 * sizeof(UINT32)) + (0x10 * sizeof(UINT32))); + if (Mem == NULL) { + return 1; + } + + pFMBuffer = (INT16 *)BurnMalloc (nBurnSoundLen * 6 * sizeof(INT16)); + if (pFMBuffer == NULL) { + return 1; + } + + Rom = Mem + 0x00000; + Gfx0 = Mem + 0x10000; + Gfx1 = Mem + 0x20000; + Prom = Mem + 0x30000; + Palette = (UINT32*)(Mem + 0x30020); + DrvPalette = (UINT32*)(Mem + 0x30040); + + if (scregg) + { + if (rockduck) { + if (BurnLoadRom(Rom + 0x4000, 0, 1)) return 1; + if (BurnLoadRom(Rom + 0x6000, 1, 1)) return 1; + if (BurnLoadRom(Rom + 0x8000, 2, 1)) return 1; + memcpy (Rom + 0x3000, Rom + 0x5000, 0x1000); + memcpy (Rom + 0x5000, Rom + 0x7000, 0x1000); + memcpy (Rom + 0xe000, Rom + 0x8000, 0x2000); + memcpy (Rom + 0x7000, Rom + 0x9000, 0x1000); + + if (BurnLoadRom(Gfx0 + 0x0000, 3, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x2000, 4, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x4000, 5, 1)) return 1; + + if (BurnLoadRom(Prom + 0x0000, 6, 1)) return 1; + + for (INT32 i = 0x2000; i < 0x6000; i++) + Gfx0[i] = BITSWAP08(Gfx0[i],2,0,3,6,1,4,7,5); + + } else { + for (INT32 i = 0; i < 5; i++) + if (BurnLoadRom(Rom + 0x3000 + i * 0x1000, i, 1)) return 1; + + memcpy (Rom + 0xf000, Rom + 0x7000, 0x1000); + + for (INT32 i = 0; i < 6; i++) + if (BurnLoadRom(Gfx0 + i * 0x1000, i + 5, 1)) return 1; + + if (BurnLoadRom(Prom, 11, 1)) return 1; + } + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502SetReadByteHandler(eggs_readmem); + M6502SetWriteByteHandler(eggs_writemem); + M6502SetReadMemIndexHandler(eggs_readmem); + M6502SetWriteMemIndexHandler(eggs_writemem); + M6502SetReadOpHandler(eggs_readmem); + M6502SetReadOpArgHandler(eggs_readmem); + M6502MapMemory(Rom + 0x0000, 0x0000, 0x07ff, M6502_RAM); + M6502MapMemory(Rom + 0x2000, 0x1000, 0x17ff, M6502_RAM); + M6502MapMemory(Rom + 0x3000, 0x3000, 0x7fff, M6502_ROM); + M6502MapMemory(Rom + 0xf000, 0xf000, 0xffff, M6502_ROM); + M6502Close(); + } else { + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(Rom + 0xa000 + i * 0x2000, i, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x0000 + i * 0x2000, 3 + i, 1)) return 1; + } + + if (BurnLoadRom(Prom, 6, 1)) return 1; + memcpy (Prom, Prom + 0x18, 8); + + M6502Init(0, TYPE_M6502); + M6502Open(0); + M6502SetReadByteHandler(dommy_readmem); + M6502SetWriteByteHandler(dommy_writemem); + M6502SetReadMemIndexHandler(dommy_readmem); + M6502SetWriteMemIndexHandler(dommy_writemem); + M6502SetReadOpHandler(dommy_readmem); + M6502SetReadOpArgHandler(dommy_readmem); + M6502MapMemory(Rom + 0x0000, 0x0000, 0x07ff, M6502_RAM); + M6502MapMemory(Rom + 0x2000, 0x2000, 0x27ff, M6502_RAM); + M6502MapMemory(Rom + 0xa000, 0xa000, 0xffff, M6502_ROM); + M6502Close(); + } + + scregg_gfx_convert(); + scregg_palette_init(); + +// BurnSetRefreshRate(57); // Proper rate, but the AY8910 can't handle it + + GenericTilesInit(); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + M6502Exit(); + AY8910Exit(0); + AY8910Exit(1); + GenericTilesExit(); + + BurnFree (Mem); + + DrvRecalcPal = 0; + flipscreen = 0; + + scregg = rockduck = 0; + VBLK = 0; + + return 0; +} + +static void draw_chars() +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (~offs >> 2) & 0xf8; + INT32 sy = ( offs & 0x1f) << 3; + + UINT16 code = Rom[0x2000 | offs] | ((Rom[0x2400 | offs] & 3) << 8); + + if (flipscreen) + { + sx ^= 0xf8; + sy ^= 0xf8; + } + + sy -= 8; + if (scregg) sx -= 8; + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, 0, 3, 0, Gfx0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, 0, 3, 0, Gfx0); + } + } +} + +static void draw_sprites() +{ + for (INT32 i = 0, offs = 0; i < 8; i++, offs += 4*0x20) + { + INT32 sx, sy, code; + UINT8 flipx,flipy; + + if (!(Rom[0x2000 + offs] & 0x01)) continue; + + sx = 240 - Rom[0x2000 + offs + 0x60]; + sy = 240 - Rom[0x2000 + offs + 0x40]; + + flipx = Rom[0x2000 + offs] & 0x04; + flipy = Rom[0x2000 + offs] & 0x02; + + code = Rom[0x2000 + offs + 0x20]; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + + flipx = !flipx; + flipy = !flipy; + } + + sy -= 8; + if (scregg) sx -= 8; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, 0, 3, 0, 0, Gfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, 0, 3, 0, 0, Gfx1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, 0, 3, 0, 0, Gfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 3, 0, 0, Gfx1); + } + } + } +} + +static INT32 DrvDraw() +{ + // check to see if we need to recalculate the palette + if (DrvRecalcPal) { + for (INT32 i = 0; i < 8; i++) { + INT32 col = Palette[i]; + DrvPalette[i] = BurnHighCol(col >> 16, col >> 8, col, 0); + } + } + + draw_chars(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static inline void scregg_interrupt_handler(INT32 scanline) +{ + if (scanline == 0) + VBLK = 0; + + if (scanline == 14) + VBLK = 0x80; + + M6502SetIRQ(M6502_IRQ_LINE, M6502_IRQSTATUS_AUTO); +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nTotalCycles = (INT32)((double)(1500000 / 57)); + INT32 nCyclesRun = 0; + + M6502Open(0); + + for (INT32 i = 0; i < 16; i++) { + nCyclesRun += M6502Run((nTotalCycles - nCyclesRun) / (16 - i)); + scregg_interrupt_handler(i); + } + + M6502Close(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen; + INT16* pSoundBuf = pBurnSoundOut; + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom + 0x0000; + ba.nLen = 0x3000; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6502Scan(nAction); + AY8910Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(flipscreen); + } + + return 0; +} + + +// Dommy + +static struct BurnRomInfo dommyRomDesc[] = { + { "dommy.e01", 0x2000, 0x9ae064ed, 1 | BRF_ESS | BRF_PRG }, // 0 M6502 Code + { "dommy.e11", 0x2000, 0x7c4fad5c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "dommy.e21", 0x2000, 0xcd1a4d55, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "dommy.e50", 0x2000, 0x5e9db0a4, 2 | BRF_GRA }, // 3 Graphics + { "dommy.e40", 0x2000, 0x4d1c36fb, 2 | BRF_GRA }, // 4 + { "dommy.e30", 0x2000, 0x4e68bb12, 2 | BRF_GRA }, // 5 + + { "dommy.e70", 0x0020, 0x50c1d86e, 3 | BRF_GRA }, // 6 Palette + + { "dommy.e60", 0x0020, 0x24da2b63, 4 | BRF_OPT }, // 7 +}; + +STD_ROM_PICK(dommy) +STD_ROM_FN(dommy) + +struct BurnDriver BurnDrvdommy = { + "dommy", NULL, NULL, NULL, "198?", + "Dommy\0", NULL, "Technos", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, dommyRomInfo, dommyRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x08, + 240, 248, 3, 4 +}; + + +// Scrambled Egg + +static struct BurnRomInfo screggRomDesc[] = { + { "d00.e14", 0x1000, 0x29226d77, 1 | BRF_ESS | BRF_PRG }, // 0 M6502 Code + { "d10.d14", 0x1000, 0xeb143880, 1 | BRF_ESS | BRF_PRG }, // 1 + { "d20.c14", 0x1000, 0x4455f262, 1 | BRF_ESS | BRF_PRG }, // 2 + { "d30.b14", 0x1000, 0x044ac5d2, 1 | BRF_ESS | BRF_PRG }, // 3 + { "d40.a14", 0x1000, 0xb5a0814a, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "d50.j12", 0x1000, 0xa485c10c, 2 | BRF_GRA }, // 5 Graphics + { "d60.j10", 0x1000, 0x1fd4e539, 2 | BRF_GRA }, // 6 + { "d70.h12", 0x1000, 0x8454f4b2, 2 | BRF_GRA }, // 7 + { "d80.h10", 0x1000, 0x72bd89ee, 2 | BRF_GRA }, // 8 + { "d90.g12", 0x1000, 0xff3c2894, 2 | BRF_GRA }, // 9 + { "da0.g10", 0x1000, 0x9c20214a, 2 | BRF_GRA }, // 10 + + { "dc0.c6 ", 0x0020, 0xff23bdd6, 3 | BRF_GRA }, // 11 Palette + + { "db1.b4", 0x0020, 0x7cc4824b, 0 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(scregg) +STD_ROM_FN(scregg) + +static INT32 screggInit() +{ + scregg = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvscregg = { + "scregg", NULL, NULL, NULL, "1983", + "Scrambled Egg\0", NULL, "Technos", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, screggRomInfo, screggRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + screggInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x08, + 240, 240, 3, 4 +}; + + +// Eggs + +static struct BurnRomInfo eggsRomDesc[] = { + { "e14.bin", 0x1000, 0x4e216f9d, 1 | BRF_ESS | BRF_PRG }, // 0 M6502 Code + { "d14.bin", 0x1000, 0x4edb267f, 1 | BRF_ESS | BRF_PRG }, // 1 + { "c14.bin", 0x1000, 0x15a5c48c, 1 | BRF_ESS | BRF_PRG }, // 2 + { "b14.bin", 0x1000, 0x5c11c00e, 1 | BRF_ESS | BRF_PRG }, // 3 + { "a14.bin", 0x1000, 0x953faf07, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "j12.bin", 0x1000, 0xce4a2e46, 2 | BRF_GRA }, // 5 Graphics + { "j10.bin", 0x1000, 0xa1bcaffc, 2 | BRF_GRA }, // 6 + { "h12.bin", 0x1000, 0x9562836d, 2 | BRF_GRA }, // 7 + { "h10.bin", 0x1000, 0x3cfb3a8e, 2 | BRF_GRA }, // 8 + { "g12.bin", 0x1000, 0x679f8af7, 2 | BRF_GRA }, // 9 + { "g10.bin", 0x1000, 0x5b58d3b5, 2 | BRF_GRA }, // 10 + + { "eggs.c6", 0x0020, 0xe8408c81, 3 | BRF_GRA }, // 11 Palette + + { "db1.b4", 0x0020, 0x7cc4824b, 0 | BRF_OPT }, // 12 +}; + +STD_ROM_PICK(eggs) +STD_ROM_FN(eggs) + +struct BurnDriver BurnDrveggs = { + "eggs", "scregg", NULL, NULL, "1983", + "Eggs\0", NULL, "[Technos] Universal USA", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, eggsRomInfo, eggsRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + screggInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x08, + 240, 240, 3, 4 +}; + + +// Rock Duck (prototype?) + +static struct BurnRomInfo rockduckRomDesc[] = { + { "rde.bin", 0x2000, 0x56e2a030, 1 | BRF_ESS | BRF_PRG }, // 0 M6502 Code + { "rdc.bin", 0x2000, 0x482d9a0c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "rdb.bin", 0x2000, 0x974626f2, 1 | BRF_ESS | BRF_PRG }, // 2 + + + { "rd3.rdg", 0x2000, 0x8a3f1e53, 2 | BRF_GRA }, // 3 Graphics + { "rd2.rdh", 0x2000, 0xe94e673e, 2 | BRF_GRA }, // 4 + { "rd1.rdj", 0x2000, 0x654afff2, 2 | BRF_GRA }, // 5 + + { "eggs.c6", 0x0020, 0xe8408c81, 3 | BRF_GRA }, // 6 Palette +}; + +STD_ROM_PICK(rockduck) +STD_ROM_FN(rockduck) + +static INT32 rockduckInit() +{ + scregg = 1; + rockduck = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvrockduck = { + "rockduck", NULL, NULL, NULL, "1983", + "Rock Duck (prototype?)\0", "incorrect colors", "Datel SAS", "misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, rockduckRomInfo, rockduckRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + rockduckInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalcPal, 0x08, + 240, 240, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_sf.cpp b/src/burn/drivers/misc_pre90s/d_sf.cpp new file mode 100644 index 00000000..1c866ff7 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_sf.cpp @@ -0,0 +1,1720 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm5205.h" + +static UINT8 *Mem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68kRom; +static UINT8 *DrvZ80Rom0; +static UINT8 *DrvZ80Rom1; +static UINT8 *Drv68kPalRam; +static UINT8 *Drv68kVidRam; +static UINT8 *Drv68kRam; +static UINT8 *DrvZ80Ram0; +static UINT8 *Gfx0; +static UINT8 *Gfx1; +static UINT8 *Gfx2; +static UINT8 *Gfx3; +static UINT8 *Gfx4; +static UINT8 *Gfx1Trans; +static UINT8 *Gfx3Trans; +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvJoy4[16]; +static UINT8 DrvJoy5[16]; +static UINT8 DrvDips[ 4]; +static UINT8 DrvReset; +static UINT16 DrvInputs[8]; + +static INT32 version; + +static INT32 sf_fg_scroll_x; +static INT32 sf_bg_scroll_x; + +static INT32 soundlatch; +static INT32 flipscreen; + +static INT32 sf_active; +static INT32 sound2_bank; + +static struct BurnInputInfo SfInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy3 + 3, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy3 + 2, "p1 down", }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy4 + 1, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy4 + 2, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy4 + 8, "p1 fire 4"}, + {"P1 Button 5" , BIT_DIGITAL , DrvJoy4 + 9, "p1 fire 5"}, + {"P1 Button 6" , BIT_DIGITAL , DrvJoy4 + 10, "p1 fire 6"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 11, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 10, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 9, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 8, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy5 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy5 + 1, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy5 + 2, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy5 + 8, "p2 fire 4"}, + {"P2 Button 5" , BIT_DIGITAL , DrvJoy5 + 9, "p2 fire 5"}, + {"P2 Button 6" , BIT_DIGITAL , DrvJoy5 + 10, "p2 fire 6"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 2, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(Sf) + +static struct BurnInputInfo SfjpInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy3 + 3, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy3 + 2, "p1 down", }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 8, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 9, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy3 + 10, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy3 + 12, "p1 fire 4"}, + {"P1 Button 5" , BIT_DIGITAL , DrvJoy3 + 13, "p1 fire 5"}, + {"P1 Button 6" , BIT_DIGITAL , DrvJoy3 + 14, "p1 fire 6"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy4 + 3, "p1 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy4 + 2, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy4 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy4 + 0, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 8, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 9, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy4 + 10, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy4 + 12, "p2 fire 4"}, + {"P2 Button 5" , BIT_DIGITAL , DrvJoy4 + 13, "p2 fire 5"}, + {"P2 Button 6" , BIT_DIGITAL , DrvJoy4 + 14, "p2 fire 6"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 2, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(Sfjp) + +static struct BurnInputInfo SfusInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy2 + 1, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy3 + 3, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy3 + 2, "p1 down", }, + {"P1 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy2 + 9, "p1 fire 3"}, + {"P1 Button 4" , BIT_DIGITAL , DrvJoy3 + 6, "p1 fire 4"}, + {"P1 Button 5" , BIT_DIGITAL , DrvJoy3 + 7, "p1 fire 5"}, + {"P1 Button 6" , BIT_DIGITAL , DrvJoy2 + 2, "p1 fire 6"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 11, "p1 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 10, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 9, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 8, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 12, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 13, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 10, "p2 fire 3"}, + {"P2 Button 4" , BIT_DIGITAL , DrvJoy3 + 14, "p2 fire 4"}, + {"P2 Button 5" , BIT_DIGITAL , DrvJoy3 + 15, "p2 fire 5"}, + {"P2 Button 6" , BIT_DIGITAL , DrvJoy2 + 8, "p2 fire 6"}, + + {"Service" , BIT_DIGITAL , DrvJoy1 + 2, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvDips + 2, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvDips + 3, "dip" }, +}; + +STDINPUTINFO(Sfus) + +static struct BurnDIPInfo SfDIPList[]= +{ + {0x1a, 0xff, 0xff, 0xff, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xf8, NULL }, + {0x1d, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Attract Music" }, + {0x1a, 0x01, 0x02, 0x00, "Off" }, + {0x1a, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Speed" }, + {0x1a, 0x01, 0x10, 0x00, "Slow" }, + {0x1a, 0x01, 0x10, 0x10, "Normal" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1a, 0x01, 0x20, 0x20, "Off" }, + {0x1a, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1a, 0x01, 0x40, 0x40, "Off" }, + {0x1a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x1b, 0x01, 0x07, 0x00, "4 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x01, "3 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x02, "2 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x1b, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0x07, 0x03, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x1b, 0x01, 0x38, 0x00, "4 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x08, "3 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x10, "2 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x1b, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0x38, 0x18, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 6 , "Buy-in max stage" }, + {0x1c, 0x01, 0x38, 0x38, "5th" }, + {0x1c, 0x01, 0x38, 0x30, "4th" }, + {0x1c, 0x01, 0x38, 0x28, "3rd" }, + {0x1c, 0x01, 0x38, 0x20, "2nd" }, + {0x1c, 0x01, 0x38, 0x18, "1st" }, + {0x1c, 0x01, 0x38, 0x08, "No buy-in" }, + + {0 , 0xfe, 0 , 2 , "Number of start countries" }, + {0x1c, 0x01, 0x40, 0x40, "4" }, + {0x1c, 0x01, 0x40, 0x00, "2" }, + + {0 , 0xfe, 0 , 6 , "Continuation max stage" }, + {0x1d, 0x01, 0x07, 0x07, "5th" }, + {0x1d, 0x01, 0x07, 0x06, "4th" }, + {0x1d, 0x01, 0x07, 0x05, "3rd" }, + {0x1d, 0x01, 0x07, 0x04, "2nd" }, + {0x1d, 0x01, 0x07, 0x03, "1st" }, + {0x1d, 0x01, 0x07, 0x02, "No continuation" }, + + {0 , 0xfe, 0 , 4 , "Round time" }, + {0x1d, 0x01, 0x18, 0x18, "100" }, + {0x1d, 0x01, 0x18, 0x10, "150" }, + {0x1d, 0x01, 0x18, 0x08, "200" }, + {0x1d, 0x01, 0x18, 0x00, "250" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1d, 0x01, 0x60, 0x60, "Normal" }, + {0x1d, 0x01, 0x60, 0x40, "Easy" }, + {0x1d, 0x01, 0x60, 0x20, "Difficult" }, + {0x1d, 0x01, 0x60, 0x00, "Very difficult" }, +}; + +STDDIPINFO(Sf) + +static struct BurnDIPInfo SfusDIPList[]= +{ + {0x1a, 0xff, 0xff, 0xff, NULL }, + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xf8, NULL }, + {0x1d, 0xff, 0xff, 0x7f, NULL }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x1a, 0x01, 0x01, 0x01, "Off" }, + {0x1a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Attract Music" }, + {0x1a, 0x01, 0x02, 0x00, "Off" }, + {0x1a, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Speed" }, + {0x1a, 0x01, 0x10, 0x00, "Slow" }, + {0x1a, 0x01, 0x10, 0x10, "Normal" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1a, 0x01, 0x20, 0x20, "Off" }, + {0x1a, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Freeze" }, + {0x1a, 0x01, 0x40, 0x40, "Off" }, + {0x1a, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x1b, 0x01, 0x07, 0x00, "4 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x01, "3 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x02, "2 Coins 1 Credit" }, + {0x1b, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x1b, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0x07, 0x03, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x1b, 0x01, 0x38, 0x00, "4 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x08, "3 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x10, "2 Coins 1 Credit" }, + {0x1b, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x1b, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x1b, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x1b, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x1b, 0x01, 0x38, 0x18, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 6 , "Buy-in max stage" }, + {0x1c, 0x01, 0x38, 0x38, "5th" }, + {0x1c, 0x01, 0x38, 0x30, "4th" }, + {0x1c, 0x01, 0x38, 0x28, "3rd" }, + {0x1c, 0x01, 0x38, 0x20, "2nd" }, + {0x1c, 0x01, 0x38, 0x18, "1st" }, + {0x1c, 0x01, 0x38, 0x08, "No buy-in" }, + + {0 , 0xfe, 0 , 2 , "Number of start countries" }, + {0x1c, 0x01, 0x40, 0x00, "4" }, + {0x1c, 0x01, 0x40, 0x40, "2" }, + + {0 , 0xfe, 0 , 6 , "Continuation max stage" }, + {0x1d, 0x01, 0x07, 0x07, "5th" }, + {0x1d, 0x01, 0x07, 0x06, "4th" }, + {0x1d, 0x01, 0x07, 0x05, "3rd" }, + {0x1d, 0x01, 0x07, 0x04, "2nd" }, + {0x1d, 0x01, 0x07, 0x03, "1st" }, + {0x1d, 0x01, 0x07, 0x02, "No continuation" }, + + {0 , 0xfe, 0 , 4 , "Round time" }, + {0x1d, 0x01, 0x18, 0x18, "100" }, + {0x1d, 0x01, 0x18, 0x10, "150" }, + {0x1d, 0x01, 0x18, 0x08, "200" }, + {0x1d, 0x01, 0x18, 0x00, "250" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1d, 0x01, 0x60, 0x60, "Normal" }, + {0x1d, 0x01, 0x60, 0x40, "Easy" }, + {0x1d, 0x01, 0x60, 0x20, "Difficult" }, + {0x1d, 0x01, 0x60, 0x00, "Very difficult" }, +}; + +STDDIPINFO(Sfus) + +static void protection_w() +{ + static const INT32 maplist[4][10] = { + { 1, 0, 3, 2, 4, 5, 6, 7, 8, 9 }, + { 4, 5, 6, 7, 1, 0, 3, 2, 8, 9 }, + { 3, 2, 1, 0, 6, 7, 4, 5, 8, 9 }, + { 6, 7, 4, 5, 3, 2, 1, 0, 8, 9 } + }; + INT32 map; + + map = maplist[SekReadByte(0xffc006)][(SekReadByte(0xffc003)<<1) + (SekReadWord(0xffc004)>>8)]; + + switch (SekReadByte(0xffc684)) + { + case 1: + { + INT32 base; + + base = 0x1b6e8+0x300e*map; + + SekWriteLong(0xffc01c, 0x16bfc+0x270*map); + SekWriteLong(0xffc020, base+0x80); + SekWriteLong(0xffc024, base); + SekWriteLong(0xffc028, base+0x86); + SekWriteLong(0xffc02c, base+0x8e); + SekWriteLong(0xffc030, base+0x20e); + SekWriteLong(0xffc034, base+0x30e); + SekWriteLong(0xffc038, base+0x38e); + SekWriteLong(0xffc03c, base+0x40e); + SekWriteLong(0xffc040, base+0x80e); + SekWriteLong(0xffc044, base+0xc0e); + SekWriteLong(0xffc048, base+0x180e); + SekWriteLong(0xffc04c, base+0x240e); + SekWriteLong(0xffc050, 0x19548+0x60*map); + SekWriteLong(0xffc054, 0x19578+0x60*map); + break; + } + + case 2: + { + static const INT32 delta1[10] = { + 0x1f80, 0x1c80, 0x2700, 0x2400, 0x2b80, 0x2e80, 0x3300, 0x3600, 0x3a80, 0x3d80 + }; + static const INT32 delta2[10] = { + 0x2180, 0x1800, 0x3480, 0x2b00, 0x3e00, 0x4780, 0x5100, 0x5a80, 0x6400, 0x6d80 + }; + + INT32 d1 = delta1[map] + 0xc0; + INT32 d2 = delta2[map]; + + SekWriteWord(0xffc680, d1); + SekWriteWord(0xffc682, d2); + SekWriteWord(0xffc00c, 0xc0); + SekWriteWord(0xffc00e, 0); + + sf_fg_scroll_x = d1; + sf_bg_scroll_x = d2; + + break; + } + + case 4: + { + INT32 pos = SekReadByte(0xffc010); + pos = (pos+1) & 3; + SekWriteByte(0xffc010, pos); + + if(!pos) { + INT32 d1 = SekReadWord(0xffc682); + INT32 off = SekReadWord(0xffc00e); + if(off!=512) { + off++; + d1++; + } else { + off = 0; + d1 -= 512; + } + SekWriteWord(0xffc682, d1); + SekWriteWord(0xffc00e, off); + + sf_bg_scroll_x = d1; + } + break; + } + } +} + +static inline void write_palette(UINT16 data, INT32 offset) +{ + INT32 r = (data >> 8) & 0x0f; + INT32 g = (data >> 4) & 0x0f; + INT32 b = (data >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + Palette[offset] = (r << 16) | (g << 8) | b; + DrvPalette[offset] = BurnHighCol(r, g, b, 0); +} + +void __fastcall sf_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfff800) == 0xb00000) { + UINT16 *pal = (UINT16*)(Drv68kPalRam + (address & 0x7ff)); + + *pal = data; + + write_palette(*pal, (address >> 1) & 0x3ff); + + return; + } + + switch (address) + { + case 0xc00010: + return; + + case 0xc00014: + sf_fg_scroll_x = data; + return; + + case 0xc00018: + sf_bg_scroll_x = data; + return; + + case 0xc0001c: + { + soundlatch = data & 0xff; + + ZetOpen(0); + ZetNmi(); + ZetClose(); + } + return; + + case 0xc0001e: + if (version == 3) { + protection_w(); + } + return; + } +} + +void __fastcall sf_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xc0001b: + { + sf_active = data & 0xff; + flipscreen = data & 0x04; + } + return; + } +} + +UINT16 __fastcall sf_read_word(UINT32 address) +{ + switch (address) + { + case 0xc00000: + return DrvInputs[3]; + + case 0xc00002: + return DrvInputs[4]; + + case 0xc00004: + return DrvInputs[5]; + + case 0xc00006: + return DrvInputs[6]; + + case 0xc00008: + return DrvInputs[0]; + + case 0xc0000a: + return DrvInputs[1]; + + case 0xc0000c: + return DrvInputs[2]; + + case 0xc0000e: + return 0xffff; + } + + return 0; +} + +UINT8 __fastcall sf_read_byte(UINT32 address) +{ + switch (address) + { + case 0xc00000: + case 0xc00001: + return DrvInputs[3] >> ((~address & 1) << 3); + + case 0xc00002: + case 0xc00003: + return DrvInputs[4] >> ((~address & 1) << 3); + + case 0xc00004: + case 0xc00005: + return DrvInputs[5] >> ((~address & 1) << 3); + + case 0xc00006: + case 0xc00007: + return DrvInputs[6] >> ((~address & 1) << 3); + + case 0xc00008: + case 0xc00009: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0xc0000a: + case 0xc0000b: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0xc0000c: + case 0xc0000d: + return DrvInputs[2] >> ((~address & 1) << 3); + + case 0xc0000e: + case 0xc0000f: + return 0xff; + } + + return 0; +} + +void __fastcall sf_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + BurnYM2151SelectRegister(data); + return; + + case 0xe001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall sf_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc800: + return soundlatch; + + case 0xe001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +static void sound2_bank_w(INT32 data) +{ + sound2_bank = (data + 1) << 15; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80Rom1 + sound2_bank); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80Rom1 + sound2_bank); +} + +void __fastcall sf_sound2_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + MSM5205ResetWrite(0, data & 0x80); + MSM5205DataWrite(0, data); + MSM5205VCLKWrite(0, 1); + MSM5205VCLKWrite(0, 0); + return; + + case 0x01: + MSM5205ResetWrite(1, data & 0x80); + MSM5205DataWrite(1, data); + MSM5205VCLKWrite(1, 1); + MSM5205VCLKWrite(1, 0); + return; + + case 0x02: + sound2_bank_w(data); + return; + } +} + +UINT8 __fastcall sf_sound2_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x01: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return soundlatch; + } + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static INT32 DrvGfxDecode() +{ + static INT32 Gfx0Planes[4] = { 4, 0, 0x200004, 0x200000 }; + static INT32 Gfx1Planes[4] = { 4, 0, 0x400004, 0x400000 }; + static INT32 Gfx2Planes[4] = { 4, 0, 0x700004, 0x700000 }; + static INT32 Gfx3Planes[2] = { 4, 0 }; + + static INT32 GfxXOffsets[16] = { 0, 1, 2, 3, 8, 9, 10, 11, 256, 257, 258, 259, 264, 265, 266, 267 }; + static INT32 GfxYOffsets[16] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x1C0000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, Gfx0, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Gfx0Planes, GfxXOffsets, GfxYOffsets, 0x200, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0x100000); + + GfxDecode(0x2000, 4, 16, 16, Gfx1Planes, GfxXOffsets, GfxYOffsets, 0x200, tmp, Gfx1); + + memcpy (tmp, Gfx2, 0x1c0000); + + GfxDecode(0x3800, 4, 16, 16, Gfx2Planes, GfxXOffsets, GfxYOffsets, 0x200, tmp, Gfx2); + + memcpy (tmp, Gfx3, 0x004000); + + GfxDecode(0x0400, 2, 8, 8, Gfx3Planes, GfxXOffsets, GfxYOffsets, 0x080, tmp, Gfx3); + + memset (Gfx1Trans, 1, 0x2000); + for (INT32 i = 0; i < 0x2000 * 0x100; i++) { + if (Gfx1[i] != 15) Gfx1Trans[i/0x100] = 0; + } + + memset (Gfx3Trans, 1, 0x400); + for (INT32 i = 0; i < 0x400 * 0x40; i++) { + if (Gfx3[i] != 3) Gfx3Trans[i/0x40] = 0; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + sf_fg_scroll_x = 0; + sf_bg_scroll_x = 0; + + soundlatch = 0; + flipscreen = 0; + + sf_active = 0; + + sound2_bank = 0; + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + MSM5205Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68kRom = Next; Next += 0x060000; + DrvZ80Rom0 = Next; Next += 0x008000; + DrvZ80Rom1 = Next; Next += 0x040000; + + Gfx0 = Next; Next += 0x100000; + Gfx1 = Next; Next += 0x200000; + Gfx1Trans = Next; Next += 0x002000; + Gfx2 = Next; Next += 0x380000; + Gfx3 = Next; Next += 0x010000; + Gfx3Trans = Next; Next += 0x000400; + Gfx4 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x00401 * sizeof(UINT32); + + AllRam = Next; + + Drv68kPalRam = Next; Next += 0x000800; + Drv68kVidRam = Next; Next += 0x001000; + Drv68kRam = Next; Next += 0x008000; + + DrvZ80Ram0 = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x00401 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +void sfYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvInit(INT32 initver) +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + if (initver == 4) + { + if (BurnLoadRom(Drv68kRom + 1, 0, 2)) return 1; + if (BurnLoadRom(Drv68kRom + 0, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80Rom0, 2, 1)) return 1; + if (BurnLoadRom(DrvZ80Rom1, 3, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx0 + i * 0x20000, i + 4, 1)) return 1; + } + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(Gfx1 + i * 0x20000, i + 8, 1)) return 1; + } + + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(Gfx2 + 0x00000 + i * 0x10000, i + 16, 1)) return 1; + if (BurnLoadRom(Gfx2 + 0xe0000 + i * 0x10000, i + 22, 1)) return 1; + } + + if (BurnLoadRom(Gfx3, 28, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx4 + i * 0x10000, i + 29, 1)) return 1; + } + } else { + for (INT32 i = 0; i < 6; i+=2) { + if (BurnLoadRom(Drv68kRom + 1 + i * 0x10000, i + 0, 2)) return 1; + if (BurnLoadRom(Drv68kRom + 0 + i * 0x10000, i + 1, 2)) return 1; + } + + if (BurnLoadRom(DrvZ80Rom0, 6, 1)) return 1; + + if (BurnLoadRom(DrvZ80Rom1 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvZ80Rom1 + 0x20000, 8, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx0 + i * 0x20000, i + 9, 1)) return 1; + } + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(Gfx1 + i * 0x20000, i + 13, 1)) return 1; + } + + for (INT32 i = 0; i < 14; i++) { + if (BurnLoadRom(Gfx2 + i * 0x20000, i + 21, 1)) return 1; + } + + if (BurnLoadRom(Gfx3, 35, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx4 + i * 0x10000, i + 36, 1)) return 1; + } + } + + if (DrvGfxDecode()) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68kRom, 0x000000, 0x04ffff, SM_ROM); + SekMapMemory(Drv68kVidRam, 0x800000, 0x800fff, SM_RAM); + SekMapMemory(Drv68kRam, 0xff8000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, sf_write_byte); + SekSetWriteWordHandler(0, sf_write_word); + SekSetReadByteHandler(0, sf_read_byte); + SekSetReadWordHandler(0, sf_read_word); + SekClose(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom0); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80Ram0); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80Ram0); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80Ram0); + ZetSetWriteHandler(sf_sound_write); + ZetSetReadHandler(sf_sound_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1); + ZetSetOutHandler(sf_sound2_out); + ZetSetInHandler(sf_sound2_in); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 60.0); + BurnYM2151SetIrqHandler(&sfYM2151IrqHandler); + + MSM5205Init(0, DrvSynchroniseStream, 384000, NULL, MSM5205_SEX_4B, 100, 1); + MSM5205Init(1, DrvSynchroniseStream, 384000, NULL, MSM5205_SEX_4B, 100, 1); + + GenericTilesInit(); + + DrvDoReset(); + + version = initver; + + Palette[0x400] = 0xff00ff; + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2151Exit(); + SekExit(); + ZetExit(); + + MSM5205Exit(); + + version = 0; + + GenericTilesExit(); + + BurnFree (Mem); + + sf_fg_scroll_x = 0; + sf_bg_scroll_x = 0; + + soundlatch = 0; + flipscreen = 0; + + sf_active = 0; + sound2_bank = 0; + + return 0; +} + +static void draw_background() +{ + UINT8 *base = Gfx4 + ((sf_bg_scroll_x >> 4) << 5); + + for (INT32 offs = 0; offs < 0x200; offs++, base += 2) + { + INT32 sx = (offs & 0x1f0) - (sf_bg_scroll_x & 0x0f); + INT32 sy = (offs << 4) & 0xf0; + + if (sx < 49 || sx >= 448 || sy < 16 || sy > 239) continue; + + INT32 attr = base[0x10000]; + INT32 color = base[0x00000]; + INT32 code = (base[0x10001] << 8) | base[1]; + + INT32 flipx = attr & 1; + INT32 flipy = attr & 2; + + if (flipscreen) { + flipx = !flipx; + flipy = !flipy; + sx = ((sx + (sf_bg_scroll_x & 0x0f)) ^ 0x1f0) + (sf_bg_scroll_x & 0x0f); + sy ^= 0xf0; + } + + sx -= 64; + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, Gfx0); + } + } + } +} + +static void draw_foreground() +{ + UINT8 *base = 0x20000 + Gfx4 + ((sf_fg_scroll_x >> 4) << 5); + + for (INT32 offs = 0; offs < 0x200; offs++, base += 2) + { + INT32 sx = (offs & 0x1f0) - (sf_fg_scroll_x & 0x0f); + INT32 sy = (offs << 4) & 0xf0; + + if (sx < 49 || sx >= 448 || sy < 16 || sy > 239) continue; + + INT32 code = (base[0x10001] << 8) | base[1]; + if (Gfx1Trans[code]) continue; + + INT32 attr = base[0x10000]; + INT32 color = base[0x00000]; + + INT32 flipx = attr & 1; + INT32 flipy = attr & 2; + + if (flipscreen) { + flipx = !flipx; + flipy = !flipy; + sx = ((sx + (sf_fg_scroll_x & 0x0f)) ^ 0x1f0) + (sf_fg_scroll_x & 0x0f); + sy ^= 0xf0; + } + + sx -= 64; + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, Gfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, Gfx1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, Gfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0x100, Gfx1); + } + } + } +} + +static void draw_characters() +{ + UINT16 *fg_ram = (UINT16*)(Drv68kVidRam); + + for (INT32 offs = 0x100 / 2; offs < 0x0f00 / 2; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + if (sx < 64 || sx > 447) continue; + + INT32 attr = fg_ram[offs]; + INT32 code = attr & 0x3ff; + if (Gfx3Trans[code]) continue; + + INT32 color = attr >> 12; + + INT32 flipx = attr & 0x400; + INT32 flipy = attr & 0x800; + + if (flipscreen) { + flipx = !flipx; + flipy = !flipy; + sx ^= 0x1f8; + sy ^= 0x0f8; + } + + sx -= 64; + sy -= 16; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 2, 3, 0x300, Gfx3); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 2, 3, 0x300, Gfx3); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 2, 3, 0x300, Gfx3); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 2, 3, 0x300, Gfx3); + } + } + } +} + +static inline INT32 sf_invert(INT32 nb) +{ + static const INT32 delta[4] = {0x00, 0x18, 0x18, 0x00}; + return nb ^ delta[(nb >> 3) & 3]; +} + +static void draw_sprites() +{ + UINT16 *sf_objectram = (UINT16*)(Drv68kRam + 0x6000); + + for (INT32 offs = 0x1000-0x20;offs >= 0;offs -= 0x20) + { + INT32 c = sf_objectram[offs]; + INT32 attr = sf_objectram[offs+1]; + INT32 sy = sf_objectram[offs+2]; + INT32 sx = sf_objectram[offs+3]; + INT32 color = attr & 0x000f; + INT32 flipx = attr & 0x0100; + INT32 flipy = attr & 0x0200; + + if (attr & 0x400) // large sprite + { + INT32 c1,c2,c3,c4,t; + + if (flipscreen) + { + sx = 480 - sx; + sy = 224 - sy; + flipx = !flipx; + flipy = !flipy; + } + + if (sy > 239 || sx < 33 || sx > 447) continue; + + sx -= 64; + sy -= 16; + + c1 = c; + c2 = c+1; + c3 = c+16; + c4 = c+17; + + if (flipx) + { + t = c1; c1 = c2; c2 = t; + t = c3; c3 = c4; c4 = t; + } + if (flipy) + { + t = c1; c1 = c3; c3 = t; + t = c2; c2 = c4; c4 = t; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sf_invert(c1), sx , sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sf_invert(c2), sx + 16, sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sf_invert(c3), sx , sy + 16, color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sf_invert(c4), sx + 16, sy + 16, color, 4, 15, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sf_invert(c1), sx , sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sf_invert(c2), sx + 16, sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sf_invert(c3), sx , sy + 16, color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sf_invert(c4), sx + 16, sy + 16, color, 4, 15, 0x200, Gfx2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sf_invert(c1), sx , sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sf_invert(c2), sx + 16, sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sf_invert(c3), sx , sy + 16, color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sf_invert(c4), sx + 16, sy + 16, color, 4, 15, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sf_invert(c1), sx , sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_Clip(pTransDraw, sf_invert(c2), sx + 16, sy , color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_Clip(pTransDraw, sf_invert(c3), sx , sy + 16, color, 4, 15, 0x200, Gfx2); + Render16x16Tile_Mask_Clip(pTransDraw, sf_invert(c4), sx + 16, sy + 16, color, 4, 15, 0x200, Gfx2); + } + } + } + else + { + if (flipscreen) + { + sx = 496 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + if (sy < 1 || sy > 239 || sx < 49 || sx > 447) continue; + + sx -= 64; + sy -= 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sf_invert(c), sx, sy, color, 4, 15, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sf_invert(c), sx, sy, color, 4, 15, 0x200, Gfx2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sf_invert(c), sx, sy, color, 4, 15, 0x200, Gfx2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sf_invert(c), sx, sy, color, 4, 15, 0x200, Gfx2); + } + } + } + } +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x401; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + if (nBurnLayer & 8) { + if (sf_active & 0x20) + draw_background(); + else + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * sizeof(INT16)); + } else { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) + pTransDraw[i] = 0x0400; // point to magenta + } + + if (sf_active & 0x40 && nBurnLayer & 4) + draw_foreground(); + + if (sf_active & 0x80 && nBurnLayer & 1) + draw_sprites(); + + if (sf_active & 0x08 && nBurnLayer & 2) + draw_characters(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static void DrvMakeInputs() +{ + DrvInputs[0] = (DrvDips[0] << 8) | DrvDips[1]; + DrvInputs[1] = (DrvDips[2] << 4) | DrvDips[3] | 0xf800; + + DrvInputs[2] = 0xff7f; + DrvInputs[3] = 0xffff; + DrvInputs[4] = 0xffff; + DrvInputs[5] = 0xffff; + DrvInputs[6] = 0xffff; + + for (INT32 i = 0; i < 16; i++) { + DrvInputs[2] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[3] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy3[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy4[i] & 1) << i; + } + + // clear opposites + { + if (!(DrvInputs[4] & 0x0003)) DrvInputs[4] |= 0x0003; // p1 left/right + if (!(DrvInputs[4] & 0x000c)) DrvInputs[4] |= 0x000c; // p1 up/down + if (!(DrvInputs[4] & 0x0300)) DrvInputs[4] |= 0x0300; // p2 left/right + if (!(DrvInputs[4] & 0x0c00)) DrvInputs[4] |= 0x0c00; // p2 up/down + } + + // World & prototype -- simulate analogue buttons + if (version == 1 || version == 4) + { + static const INT32 scale[8] = { 0x00, 0x60, 0xe0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }; + + INT32 t = (DrvJoy4[0] & 1) | ((DrvJoy4[1] & 1) << 1) | ((DrvJoy4[2] & 1) << 2); + DrvInputs[5] = scale[t]; + t = (DrvJoy5[0] & 1) | ((DrvJoy5[1] & 1) << 1) | ((DrvJoy5[2] & 1) << 2); + DrvInputs[5] |= scale[t] << 8; + + t = (DrvJoy4[8] & 1) | ((DrvJoy4[9] & 1) << 1) | ((DrvJoy4[10] & 1) << 2); + DrvInputs[6] = scale[t]; + + t = (DrvJoy5[8] & 1) | ((DrvJoy5[9] & 1) << 1) | ((DrvJoy5[10] & 1) << 2); + DrvInputs[6] |= scale[t] << 8; + } +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + DrvMakeInputs(); + + INT32 nSoundBufferPos = 0; + INT32 nInterleave = (133 * 2) / 3; // sample cpu irqs + INT32 nCyclesTotal[3]; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + INT32 nNext[3] = { 0, 0, 0 }; + + nCyclesTotal[0] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)3579545 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = 3579545 / 60; //(INT32)((INT64)3579545 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + nNext[0] += nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nNext[0] - nCyclesDone[0]); + + ZetOpen(0); + nNext[1] += nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += ZetRun(nNext[1] - nCyclesDone[1]); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + + nSoundBufferPos += nSegmentLength; + } + + ZetClose(); + + ZetOpen(1); + nNext[2] += nCyclesTotal[2] / nInterleave; + nCyclesDone[2] += ZetRun(nNext[2] - nCyclesDone[2]); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + } + + SekSetIRQLine((version == 4) ? 6 : 1, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + } + + ZetOpen(1); + if ((nCyclesTotal[2] - nCyclesDone[2]) > 0) { + ZetRun(nCyclesTotal[2] - nCyclesDone[2]); + } + + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + MSM5205Render(1, pBurnSoundOut, nBurnSoundLen); + ZetClose(); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + MSM5205Scan(nAction, pnMin); + BurnYM2151Scan(nAction); + + SCAN_VAR(sf_fg_scroll_x); + SCAN_VAR(sf_bg_scroll_x); + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen); + SCAN_VAR(sf_active); + SCAN_VAR(sound2_bank); + } + + if (nAction & ACB_WRITE) { + ZetOpen(1); + sound2_bank_w(sound2_bank); + ZetClose(); + } + + return 0; +} + + +// Street Fighter (World) + +static struct BurnRomInfo sfRomDesc[] = { + { "sfe-19", 0x10000, 0x8346c3ca, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sfe-22", 0x10000, 0x3a4bfaa8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sfe-20", 0x10000, 0xb40e67ee, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sfe-23", 0x10000, 0x477c3d5b, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sfe-21", 0x10000, 0x2547192b, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sfe-24", 0x10000, 0x79680f4e, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sf-02.bin", 0x08000, 0x4a9ac534, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 #0 Code + + { "sfu-00", 0x20000, 0xa7cce903, 3 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + { "sf-01.bin", 0x20000, 0x86e0f0d5, 3 | BRF_PRG | BRF_ESS }, // 8 + + { "sf-39.bin", 0x20000, 0xcee3d292, 4 | BRF_GRA }, // 9 Background Tiles + { "sf-38.bin", 0x20000, 0x2ea99676, 4 | BRF_GRA }, // 10 + { "sf-41.bin", 0x20000, 0xe0280495, 4 | BRF_GRA }, // 11 + { "sf-40.bin", 0x20000, 0xc70b30de, 4 | BRF_GRA }, // 12 + + { "sf-25.bin", 0x20000, 0x7f23042e, 5 | BRF_GRA }, // 13 More tiles? + { "sf-28.bin", 0x20000, 0x92f8b91c, 5 | BRF_GRA }, // 14 + { "sf-30.bin", 0x20000, 0xb1399856, 5 | BRF_GRA }, // 15 + { "sf-34.bin", 0x20000, 0x96b6ae2e, 5 | BRF_GRA }, // 16 + { "sf-26.bin", 0x20000, 0x54ede9f5, 5 | BRF_GRA }, // 17 + { "sf-29.bin", 0x20000, 0xf0649a67, 5 | BRF_GRA }, // 18 + { "sf-31.bin", 0x20000, 0x8f4dd71a, 5 | BRF_GRA }, // 19 + { "sf-35.bin", 0x20000, 0x70c00fb4, 5 | BRF_GRA }, // 20 + + { "sf-15.bin", 0x20000, 0xfc0113db, 6 | BRF_GRA }, // 21 Sprites + { "sf-16.bin", 0x20000, 0x82e4a6d3, 6 | BRF_GRA }, // 22 + { "sf-11.bin", 0x20000, 0xe112df1b, 6 | BRF_GRA }, // 23 + { "sf-12.bin", 0x20000, 0x42d52299, 6 | BRF_GRA }, // 24 + { "sf-07.bin", 0x20000, 0x49f340d9, 6 | BRF_GRA }, // 25 + { "sf-08.bin", 0x20000, 0x95ece9b1, 6 | BRF_GRA }, // 26 + { "sf-03.bin", 0x20000, 0x5ca05781, 6 | BRF_GRA }, // 27 + { "sf-17.bin", 0x20000, 0x69fac48e, 6 | BRF_GRA }, // 28 + { "sf-18.bin", 0x20000, 0x71cfd18d, 6 | BRF_GRA }, // 29 + { "sf-13.bin", 0x20000, 0xfa2eb24b, 6 | BRF_GRA }, // 30 + { "sf-14.bin", 0x20000, 0xad955c95, 6 | BRF_GRA }, // 31 + { "sf-09.bin", 0x20000, 0x41b73a31, 6 | BRF_GRA }, // 32 + { "sf-10.bin", 0x20000, 0x91c41c50, 6 | BRF_GRA }, // 33 + { "sf-05.bin", 0x20000, 0x538c7cbe, 6 | BRF_GRA }, // 34 + + { "sf-27.bin", 0x04000, 0x2b09b36d, 7 | BRF_GRA }, // 35 Characters + + { "sf-37.bin", 0x10000, 0x23d09d3d, 8 | BRF_GRA }, // 36 Tilemaps + { "sf-36.bin", 0x10000, 0xea16df6c, 8 | BRF_GRA }, // 37 + { "sf-32.bin", 0x10000, 0x72df2bd9, 8 | BRF_GRA }, // 38 + { "sf-33.bin", 0x10000, 0x3e99d3d5, 8 | BRF_GRA }, // 39 + + { "mb7114h.12k", 0x0100, 0x75af3553, 0 | BRF_OPT }, // 40 Proms + { "mb7114h.11h", 0x0100, 0xc0e56586, 0 | BRF_OPT }, // 41 + { "mb7114h.12j", 0x0100, 0x4c734b64, 0 | BRF_OPT }, // 42 + { "mmi-7603.13h",0x0020, 0x06bcda53, 0 | BRF_OPT }, // 43 +}; + +STD_ROM_PICK(sf) +STD_ROM_FN(sf) + +static INT32 SfInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvsf = { + "sf", NULL, NULL, NULL, "1987", + "Street Fighter (World)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, FBF_SF, + NULL, sfRomInfo, sfRomName, NULL, NULL, SfInputInfo, SfDIPInfo, + SfInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x401, 384, 224, 4, 3 +}; + + + +// Street Fighter (US set 1) + +static struct BurnRomInfo sfuRomDesc[] = { + { "sfd-19", 0x10000, 0xfaaf6255, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sfd-22", 0x10000, 0xe1fe3519, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sfd-20", 0x10000, 0x44b915bd, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sfd-23", 0x10000, 0x79c43ff8, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sfd-21", 0x10000, 0xe8db799b, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sfd-24", 0x10000, 0x466a3440, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sf-02.bin", 0x08000, 0x4a9ac534, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 #0 Code + + { "sfu-00", 0x20000, 0xa7cce903, 3 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + { "sf-01.bin", 0x20000, 0x86e0f0d5, 3 | BRF_PRG | BRF_ESS }, // 8 + + { "sf-39.bin", 0x20000, 0xcee3d292, 4 | BRF_GRA }, // 9 Background Tiles + { "sf-38.bin", 0x20000, 0x2ea99676, 4 | BRF_GRA }, // 10 + { "sf-41.bin", 0x20000, 0xe0280495, 4 | BRF_GRA }, // 11 + { "sf-40.bin", 0x20000, 0xc70b30de, 4 | BRF_GRA }, // 12 + + { "sf-25.bin", 0x20000, 0x7f23042e, 5 | BRF_GRA }, // 13 Foreground Tiles + { "sf-28.bin", 0x20000, 0x92f8b91c, 5 | BRF_GRA }, // 14 + { "sf-30.bin", 0x20000, 0xb1399856, 5 | BRF_GRA }, // 15 + { "sf-34.bin", 0x20000, 0x96b6ae2e, 5 | BRF_GRA }, // 16 + { "sf-26.bin", 0x20000, 0x54ede9f5, 5 | BRF_GRA }, // 17 + { "sf-29.bin", 0x20000, 0xf0649a67, 5 | BRF_GRA }, // 18 + { "sf-31.bin", 0x20000, 0x8f4dd71a, 5 | BRF_GRA }, // 19 + { "sf-35.bin", 0x20000, 0x70c00fb4, 5 | BRF_GRA }, // 20 + + { "sf-15.bin", 0x20000, 0xfc0113db, 6 | BRF_GRA }, // 21 Sprites + { "sf-16.bin", 0x20000, 0x82e4a6d3, 6 | BRF_GRA }, // 22 + { "sf-11.bin", 0x20000, 0xe112df1b, 6 | BRF_GRA }, // 23 + { "sf-12.bin", 0x20000, 0x42d52299, 6 | BRF_GRA }, // 24 + { "sf-07.bin", 0x20000, 0x49f340d9, 6 | BRF_GRA }, // 25 + { "sf-08.bin", 0x20000, 0x95ece9b1, 6 | BRF_GRA }, // 26 + { "sf-03.bin", 0x20000, 0x5ca05781, 6 | BRF_GRA }, // 27 + { "sf-17.bin", 0x20000, 0x69fac48e, 6 | BRF_GRA }, // 28 + { "sf-18.bin", 0x20000, 0x71cfd18d, 6 | BRF_GRA }, // 29 + { "sf-13.bin", 0x20000, 0xfa2eb24b, 6 | BRF_GRA }, // 30 + { "sf-14.bin", 0x20000, 0xad955c95, 6 | BRF_GRA }, // 31 + { "sf-09.bin", 0x20000, 0x41b73a31, 6 | BRF_GRA }, // 32 + { "sf-10.bin", 0x20000, 0x91c41c50, 6 | BRF_GRA }, // 33 + { "sf-05.bin", 0x20000, 0x538c7cbe, 6 | BRF_GRA }, // 34 + + { "sf-27.bin", 0x04000, 0x2b09b36d, 7 | BRF_GRA }, // 35 Characters + + { "sf-37.bin", 0x10000, 0x23d09d3d, 8 | BRF_GRA }, // 36 Tilemaps + { "sf-36.bin", 0x10000, 0xea16df6c, 8 | BRF_GRA }, // 37 + { "sf-32.bin", 0x10000, 0x72df2bd9, 8 | BRF_GRA }, // 38 + { "sf-33.bin", 0x10000, 0x3e99d3d5, 8 | BRF_GRA }, // 39 + + { "mb7114h.12k", 0x0100, 0x75af3553, 0 | BRF_OPT }, // 40 Proms + { "mb7114h.11h", 0x0100, 0xc0e56586, 0 | BRF_OPT }, // 41 + { "mb7114h.12j", 0x0100, 0x4c734b64, 0 | BRF_OPT }, // 42 + { "mmi-7603.13h",0x0020, 0x06bcda53, 0 | BRF_OPT }, // 43 +}; + +STD_ROM_PICK(sfu) +STD_ROM_FN(sfu) + +static INT32 SfusInit() +{ + return DrvInit(2); +} + +struct BurnDriver BurnDrvsfu = { + "sfu", "sf", NULL, NULL, "1987", + "Street Fighter (US set 1)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, FBF_SF, + NULL, sfuRomInfo, sfuRomName, NULL, NULL, SfusInputInfo, SfusDIPInfo, + SfusInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x401, 384, 224, 4, 3 +}; + + +// Street Fighter (US set 2) + +static struct BurnRomInfo sfuaRomDesc[] = { + { "sfs19u.1a", 0x10000, 0xc8e41c49, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sfs22u.1b", 0x10000, 0x667e9309, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sfs20u.2a", 0x10000, 0x303065bf, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sfs23u.2b", 0x10000, 0xde6927a3, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sfs21u.3a", 0x10000, 0x004a418b, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sfs24u.3b", 0x10000, 0x2b4545ff, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sf-02.bin", 0x08000, 0x4a9ac534, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 #0 Code + + { "sfu-00", 0x20000, 0xa7cce903, 3 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + { "sf-01.bin", 0x20000, 0x86e0f0d5, 3 | BRF_PRG | BRF_ESS }, // 8 + + { "sf-39.bin", 0x20000, 0xcee3d292, 4 | BRF_GRA }, // 9 Background Tiles + { "sf-38.bin", 0x20000, 0x2ea99676, 4 | BRF_GRA }, // 10 + { "sf-41.bin", 0x20000, 0xe0280495, 4 | BRF_GRA }, // 11 + { "sf-40.bin", 0x20000, 0xc70b30de, 4 | BRF_GRA }, // 12 + + { "sf-25.bin", 0x20000, 0x7f23042e, 5 | BRF_GRA }, // 13 Foreground Tiles + { "sf-28.bin", 0x20000, 0x92f8b91c, 5 | BRF_GRA }, // 14 + { "sf-30.bin", 0x20000, 0xb1399856, 5 | BRF_GRA }, // 15 + { "sf-34.bin", 0x20000, 0x96b6ae2e, 5 | BRF_GRA }, // 16 + { "sf-26.bin", 0x20000, 0x54ede9f5, 5 | BRF_GRA }, // 17 + { "sf-29.bin", 0x20000, 0xf0649a67, 5 | BRF_GRA }, // 18 + { "sf-31.bin", 0x20000, 0x8f4dd71a, 5 | BRF_GRA }, // 19 + { "sf-35.bin", 0x20000, 0x70c00fb4, 5 | BRF_GRA }, // 20 + + { "sf-15.bin", 0x20000, 0xfc0113db, 6 | BRF_GRA }, // 21 Sprites + { "sf-16.bin", 0x20000, 0x82e4a6d3, 6 | BRF_GRA }, // 22 + { "sf-11.bin", 0x20000, 0xe112df1b, 6 | BRF_GRA }, // 23 + { "sf-12.bin", 0x20000, 0x42d52299, 6 | BRF_GRA }, // 24 + { "sf-07.bin", 0x20000, 0x49f340d9, 6 | BRF_GRA }, // 25 + { "sf-08.bin", 0x20000, 0x95ece9b1, 6 | BRF_GRA }, // 26 + { "sf-03.bin", 0x20000, 0x5ca05781, 6 | BRF_GRA }, // 27 + { "sf-17.bin", 0x20000, 0x69fac48e, 6 | BRF_GRA }, // 28 + { "sf-18.bin", 0x20000, 0x71cfd18d, 6 | BRF_GRA }, // 29 + { "sf-13.bin", 0x20000, 0xfa2eb24b, 6 | BRF_GRA }, // 30 + { "sf-14.bin", 0x20000, 0xad955c95, 6 | BRF_GRA }, // 31 + { "sf-09.bin", 0x20000, 0x41b73a31, 6 | BRF_GRA }, // 32 + { "sf-10.bin", 0x20000, 0x91c41c50, 6 | BRF_GRA }, // 33 + { "sf-05.bin", 0x20000, 0x538c7cbe, 6 | BRF_GRA }, // 34 + + { "sf-27.bin", 0x04000, 0x2b09b36d, 7 | BRF_GRA }, // 35 Characters + + { "sf-37.bin", 0x10000, 0x23d09d3d, 8 | BRF_GRA }, // 36 Tilemaps + { "sf-36.bin", 0x10000, 0xea16df6c, 8 | BRF_GRA }, // 37 + { "sf-32.bin", 0x10000, 0x72df2bd9, 8 | BRF_GRA }, // 38 + { "sf-33.bin", 0x10000, 0x3e99d3d5, 8 | BRF_GRA }, // 39 + + { "sfb05.bin", 0x0100, 0x864199ad, 0 | BRF_OPT }, // 40 Proms + { "sfb00.bin", 0x0100, 0xbd3f8c5d, 0 | BRF_OPT }, // 41 + { "mb7114h.12j", 0x0100, 0x4c734b64, 0 | BRF_OPT }, // 42 + { "mmi-7603.13h",0x0020, 0x06bcda53, 0 | BRF_OPT }, // 43 + + { "i8751.bin", 0x00800, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(sfua) +STD_ROM_FN(sfua) + +static INT32 SfuaInit() +{ + return DrvInit(3); +} + +struct BurnDriver BurnDrvsfua = { + "sfua", "sf", NULL, NULL, "1987", + "Street Fighter (US set 2)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, FBF_SF, + NULL, sfuaRomInfo, sfuaRomName, NULL, NULL, SfjpInputInfo, SfusDIPInfo, + SfuaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x401, 384, 224, 4, 3 +}; + + +// Street Fighter (Japan) + +static struct BurnRomInfo sfjpRomDesc[] = { + { "sf-19.bin", 0x10000, 0x116027d7, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "sf-22.bin", 0x10000, 0xd3cbd09e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sf-20.bin", 0x10000, 0xfe07e83f, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sf-23.bin", 0x10000, 0x1e435d33, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sf-21.bin", 0x10000, 0xe086bc4c, 1 | BRF_PRG | BRF_ESS }, // 4 + { "sf-24.bin", 0x10000, 0x13a6696b, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "sf-02.bin", 0x08000, 0x4a9ac534, 2 | BRF_PRG | BRF_ESS }, // 6 Z80 #0 Code + + { "sf-00.bin", 0x20000, 0x4b733845, 3 | BRF_PRG | BRF_ESS }, // 7 Z80 #1 Code + { "sf-01.bin", 0x20000, 0x86e0f0d5, 3 | BRF_PRG | BRF_ESS }, // 8 + + { "sf-39.bin", 0x20000, 0xcee3d292, 4 | BRF_GRA }, // 9 Background Tiles + { "sf-38.bin", 0x20000, 0x2ea99676, 4 | BRF_GRA }, // 10 + { "sf-41.bin", 0x20000, 0xe0280495, 4 | BRF_GRA }, // 11 + { "sf-40.bin", 0x20000, 0xc70b30de, 4 | BRF_GRA }, // 12 + + { "sf-25.bin", 0x20000, 0x7f23042e, 5 | BRF_GRA }, // 13 Foreground Tiles + { "sf-28.bin", 0x20000, 0x92f8b91c, 5 | BRF_GRA }, // 14 + { "sf-30.bin", 0x20000, 0xb1399856, 5 | BRF_GRA }, // 15 + { "sf-34.bin", 0x20000, 0x96b6ae2e, 5 | BRF_GRA }, // 16 + { "sf-26.bin", 0x20000, 0x54ede9f5, 5 | BRF_GRA }, // 17 + { "sf-29.bin", 0x20000, 0xf0649a67, 5 | BRF_GRA }, // 18 + { "sf-31.bin", 0x20000, 0x8f4dd71a, 5 | BRF_GRA }, // 19 + { "sf-35.bin", 0x20000, 0x70c00fb4, 5 | BRF_GRA }, // 20 + + { "sf-15.bin", 0x20000, 0xfc0113db, 6 | BRF_GRA }, // 21 Sprites + { "sf-16.bin", 0x20000, 0x82e4a6d3, 6 | BRF_GRA }, // 22 + { "sf-11.bin", 0x20000, 0xe112df1b, 6 | BRF_GRA }, // 23 + { "sf-12.bin", 0x20000, 0x42d52299, 6 | BRF_GRA }, // 24 + { "sf-07.bin", 0x20000, 0x49f340d9, 6 | BRF_GRA }, // 25 + { "sf-08.bin", 0x20000, 0x95ece9b1, 6 | BRF_GRA }, // 26 + { "sf-03.bin", 0x20000, 0x5ca05781, 6 | BRF_GRA }, // 27 + { "sf-17.bin", 0x20000, 0x69fac48e, 6 | BRF_GRA }, // 28 + { "sf-18.bin", 0x20000, 0x71cfd18d, 6 | BRF_GRA }, // 29 + { "sf-13.bin", 0x20000, 0xfa2eb24b, 6 | BRF_GRA }, // 30 + { "sf-14.bin", 0x20000, 0xad955c95, 6 | BRF_GRA }, // 31 + { "sf-09.bin", 0x20000, 0x41b73a31, 6 | BRF_GRA }, // 32 + { "sf-10.bin", 0x20000, 0x91c41c50, 6 | BRF_GRA }, // 33 + { "sf-05.bin", 0x20000, 0x538c7cbe, 6 | BRF_GRA }, // 34 + + { "sf-27.bin", 0x04000, 0x2b09b36d, 7 | BRF_GRA }, // 35 Characters + + { "sf-37.bin", 0x10000, 0x23d09d3d, 8 | BRF_GRA }, // 36 Tilemaps + { "sf-36.bin", 0x10000, 0xea16df6c, 8 | BRF_GRA }, // 37 + { "sf-32.bin", 0x10000, 0x72df2bd9, 8 | BRF_GRA }, // 38 + { "sf-33.bin", 0x10000, 0x3e99d3d5, 8 | BRF_GRA }, // 39 + + { "sfb05.bin", 0x0100, 0x864199ad, 0 | BRF_OPT }, // 40 Proms + { "sfb00.bin", 0x0100, 0xbd3f8c5d, 0 | BRF_OPT }, // 41 + { "mb7114h.12j", 0x0100, 0x4c734b64, 0 | BRF_OPT }, // 42 + { "mmi-7603.13h",0x0020, 0x06bcda53, 0 | BRF_OPT }, // 43 + + { "68705.bin", 0x00800, 0x00000000, 0 | BRF_NODUMP }, +}; + +STD_ROM_PICK(sfjp) +STD_ROM_FN(sfjp) + +static INT32 SfjpInit() +{ + return DrvInit(3); +} + +struct BurnDriver BurnDrvsfjp = { + "sfj", "sf", NULL, NULL, "1987", + "Street Fighter (Japan)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, FBF_SF, + NULL, sfjpRomInfo, sfjpRomName, NULL, NULL, SfjpInputInfo, SfusDIPInfo, + SfjpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x401, 384, 224, 4, 3 +}; + + +// Street Fighter (Prototype) + +static struct BurnRomInfo sfpRomDesc[] = { + { "prg8.2a", 0x20000, 0xd48d06a3, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "prg0.2c", 0x20000, 0xe8606c1a, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "sound.9j", 0x08000, 0x43cd32ae, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #0 Code + + { "voice.1g", 0x10000, 0x3f23c180, 3 | BRF_PRG | BRF_ESS }, // 3 Z80 #1 Code + + { "bkchr.2k", 0x20000, 0xe4d47aca, 4 | BRF_GRA }, // 4 Background Tiles + { "bkchr.1k", 0x20000, 0x5a1cbc1b, 4 | BRF_GRA }, // 5 + { "bkchr.4k", 0x20000, 0xc351bd48, 4 | BRF_GRA }, // 6 + { "bkchr.3k", 0x20000, 0x6bb2b050, 4 | BRF_GRA }, // 7 + + { "mchr.1d", 0x20000, 0xab06a60b, 5 | BRF_GRA }, // 8 Foreground Tiles + { "mchr.1e", 0x20000, 0xd221387d, 5 | BRF_GRA }, // 9 + { "mchr.1g", 0x20000, 0x1e4c1712, 5 | BRF_GRA }, // 10 + { "mchr.1h", 0x20000, 0xa381f529, 5 | BRF_GRA }, // 11 + { "mchr.2d", 0x20000, 0xe52303c4, 5 | BRF_GRA }, // 12 + { "mchr.2e", 0x20000, 0x23b9a6a1, 5 | BRF_GRA }, // 13 + { "mchr.2g", 0x20000, 0x1283ac09, 5 | BRF_GRA }, // 14 + { "mchr.2h", 0x20000, 0xcc6bf05c, 5 | BRF_GRA }, // 15 + + { "b1m.bin", 0x10000, 0x64758232, 6 | BRF_GRA }, // 16 Sprites + { "b2m.bin", 0x10000, 0xd958f5ad, 6 | BRF_GRA }, // 17 + { "b1k.bin", 0x10000, 0xe766f5fe, 6 | BRF_GRA }, // 18 + { "b2k.bin", 0x10000, 0xe71572d3, 6 | BRF_GRA }, // 19 + { "b1h.bin", 0x10000, 0x8494f38c, 6 | BRF_GRA }, // 20 + { "b2h.bin", 0x10000, 0x1fc5f049, 6 | BRF_GRA }, // 21 + { "b3m.bin", 0x10000, 0xd136802e, 6 | BRF_GRA }, // 22 + { "b4m.bin", 0x10000, 0xb4fa85d3, 6 | BRF_GRA }, // 23 + { "b3k.bin", 0x10000, 0x40e11cc8, 6 | BRF_GRA }, // 24 + { "b4k.bin", 0x10000, 0x5ca9716e, 6 | BRF_GRA }, // 25 + { "b3h.bin", 0x10000, 0x8c3d9173, 6 | BRF_GRA }, // 26 + { "b4h.bin", 0x10000, 0xa2df66f8, 6 | BRF_GRA }, // 27 + + { "vram.4d", 0x04000, 0xbfadfb32, 7 | BRF_GRA }, // 28 Characters + + { "bks1j10.5h", 0x10000, 0x4934aacd, 8 | BRF_GRA }, // 29 Tilemaps + { "bks1j18.3h", 0x10000, 0x551ffc88, 8 | BRF_GRA }, // 30 + { "ms1j10.3g", 0x10000, 0xf92958b8, 8 | BRF_GRA }, // 31 + { "ms1j18.5g", 0x10000, 0x89e35dc1, 8 | BRF_GRA }, // 32 + + { "sfb05.bin", 0x0100, 0x864199ad, 0 | BRF_OPT }, // 33 Proms + { "sfb00.bin", 0x0100, 0xbd3f8c5d, 0 | BRF_OPT }, // 34 + { "mb7114h.12j", 0x0100, 0x4c734b64, 0 | BRF_OPT }, // 35 + { "mmi-7603.13h", 0x0020, 0x06bcda53, 0 | BRF_OPT }, // 36 +}; + +STD_ROM_PICK(sfp) +STD_ROM_FN(sfp) + +static INT32 SfpInit() +{ + return DrvInit(4); +} + +struct BurnDriver BurnDrvsfp = { + "sfp", "sf", NULL, NULL, "1987", + "Street Fighter (Prototype)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, FBF_SF, + NULL, sfpRomInfo, sfpRomName, NULL, NULL, SfInputInfo, SfDIPInfo, + SfpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x401, 384, 224, 4, 3 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_skyfox.cpp b/src/burn/drivers/misc_pre90s/d_skyfox.cpp new file mode 100644 index 00000000..f71d9104 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_skyfox.cpp @@ -0,0 +1,624 @@ +// FB Alpha Skyfox Driver Module +// Based on MAME driver by Luca Elia + +#include "tiles_generic.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvVidRegs; +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[1]; +static UINT8 DrvDips[1]; +static UINT8 DrvInputs[1]; +static UINT8 DrvReset; + +static UINT8 *soundlatch; +static UINT8 *DrvBgCtrl; +static INT32 *DrvBgPos; + +static INT32 vblank; + +static struct BurnInputInfo SkyfoxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 2, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Skyfox) + +static struct BurnDIPInfo SkyfoxDIPList[]= +{ + {0x09, 0xff, 0xff, 0x6f, NULL }, + {0x0a, 0xff, 0xff, 0xf0, NULL }, + {0x0b, 0xff, 0xff, 0xfa, NULL }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x09, 0x01, 0x18, 0x00, "20K" }, + {0x09, 0x01, 0x18, 0x08, "30K" }, + {0x09, 0x01, 0x18, 0x10, "40K" }, + {0x09, 0x01, 0x18, 0x18, "50K" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x09, 0x01, 0x20, 0x20, "Medium" }, + {0x09, 0x01, 0x20, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x09, 0x01, 0x40, 0x40, "Off" }, + {0x09, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x09, 0x01, 0x80, 0x00, "Upright" }, + {0x09, 0x01, 0x80, 0x80, "Cocktail" }, + + {0 , 0xfe, 0 , 8, "Coinage" }, + {0x0a, 0x01, 0x0e, 0x0e, "5 Coins 1 Credits" }, + {0x0a, 0x01, 0x0e, 0x0a, "4 Coins 1 Credits" }, + {0x0a, 0x01, 0x0e, 0x06, "3 Coins 1 Credits" }, + {0x0a, 0x01, 0x0e, 0x02, "2 Coins 1 Credits" }, + {0x0a, 0x01, 0x0e, 0x00, "1 Coin 1 Credits" }, + {0x0a, 0x01, 0x0e, 0x04, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0x0e, 0x08, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0x0e, 0x0c, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 6, "Lives" }, + {0x0b, 0x01, 0x07, 0x00, "1" }, + {0x0b, 0x01, 0x07, 0x01, "2" }, + {0x0b, 0x01, 0x07, 0x02, "3" }, + {0x0b, 0x01, 0x07, 0x03, "4" }, + {0x0b, 0x01, 0x07, 0x04, "5" }, + {0x0b, 0x01, 0x07, 0x07, "Infinite (Cheat)" }, +}; + +STDDIPINFO(Skyfox) + +void __fastcall skyfox_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe008: + case 0xe009: + case 0xe00a: + case 0xe00b: + case 0xe00c: + case 0xe00d: + case 0xe00e: + case 0xe00f: + DrvVidRegs[address & 7] = data; + return; + } +} + +UINT8 __fastcall skyfox_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + return DrvInputs[0]; + + case 0xe001: + return DrvDips[0]; + + case 0xe002: + return DrvDips[1] | vblank; + + case 0xf001: + return DrvDips[2]; + } + + return 0; +} + +void __fastcall skyfox_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xa000: + case 0xa001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0xc000: + case 0xc001: + BurnYM2203Write(1, address & 1, data); + return; + } +} + +UINT8 __fastcall skyfox_sound_read(UINT16 address) +{ + switch (address) + { + case 0xa001: + return BurnYM2203Read(0, 0); + + case 0xb000: + return *soundlatch; + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x010000; + DrvZ80ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x060000; + DrvGfxROM1 = Next; Next += 0x008000; + + DrvColPROM = Next; Next += 0x000300; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + Palette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x001000; + DrvZ80RAM1 = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x001000; + + DrvVidRegs = Next; + DrvBgCtrl = Next; + soundlatch = Next + 1; Next += 0x000008; + + DrvBgPos = (INT32*)Next; Next += 0x00001 * sizeof(INT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x60000); + + for (INT32 i = 0; i < 0x60000; i++) { + tmp[i] = DrvGfxROM0[(i&~0x3ff) | (i&7) | (((i>>3)&7)<<5) | (((i>>6)&3)<<3) | (i&0x300)]; + } + + memcpy (DrvGfxROM0, tmp, 0x60000); + + BurnFree (tmp); +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 256; i++) + { + INT32 bit0,bit1,bit2,bit3,r,g,b; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit2 = (DrvColPROM[i] >> 2) & 0x01; + bit3 = (DrvColPROM[i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 256] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 256] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 256] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 256] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 2*256] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 2*256] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 2*256] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 2*256] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + Palette[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 256; i++) + { + Palette[i | 0x100] = (i << 16) | (i << 8) | i; + } +} + +static INT32 DrvDoReset() +{ + memset(AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + return 0; +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 1748000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 1748000.0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM0 + 0x08000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x20000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x30000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x40000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x50000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 9, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 11, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 12, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 1, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xcfff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 2, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 0, DrvSprRAM); + ZetMapArea(0xd000, 0xdfff, 1, DrvSprRAM); + ZetMapArea(0xd000, 0xdfff, 2, DrvSprRAM); + ZetSetWriteHandler(skyfox_write); + ZetSetReadHandler(skyfox_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(skyfox_sound_write); + ZetSetReadHandler(skyfox_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 1748000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(1748000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2203Exit(); + GenericTilesExit(); + ZetExit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_sprites() +{ + INT32 shift = (*DrvBgCtrl & 0x80) ? (4-1) : 4; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 xstart, ystart, xend, yend; + INT32 xinc, yinc, dx, dy; + INT32 low_code, n; + + INT32 y = DrvSprRAM[offs + 0]; + INT32 x = DrvSprRAM[offs + 1]; + INT32 code = DrvSprRAM[offs + 2] | (DrvSprRAM[offs+3] << 8); + INT32 flipx = code & 0x02; + INT32 flipy = code & 0x04; + + x = (x << 1) | (code & 1); + + INT32 high_code = ((code >> 4) & 0x7f0) + ((code & 0x8000) >> shift); + + switch (code & 0x88) + { + case 0x88: n = 4; low_code = 0; break; + case 0x08: n = 2; low_code = ((code & 0x20) >> 2) + ((code & 0x10) >> 3); break; + default: n = 1; low_code = (code >> 4) & 0x0f; break; + } + + if (*DrvBgCtrl & 1) + { + x = ((nScreenWidth-1) - x - ((n - 1) << 3)) + 88; + y = ((nScreenHeight-1) - y - ((n - 1) << 3)) + 8; + flipx = !flipx; + flipy = !flipy; + } else { + x -= 0x60; + y -= 0x10; + } + + if (flipx) { xstart = n-1; xend = -1; xinc = -1; } + else { xstart = 0; xend = n; xinc = +1; } + + if (flipy) { ystart = n-1; yend = -1; yinc = -1; } + else { ystart = 0; yend = n; yinc = +1; } + + code = low_code + high_code; + + for (dy = ystart; dy != yend; dy += yinc) + { + INT32 sy = y + (dy << 3); + + for (dx = xstart; dx != xend; dx += xinc) + { + INT32 sx = x + (dx << 3); + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code++, sx, sy, 0, 8, 0xff, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code++, sx, sy, 0, 8, 0xff, 0, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code++,sx, sy, 0, 8, 0xff, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code++, sx, sy, 0, 8, 0xff, 0, DrvGfxROM0); + } + } + } + + code += n & 2; + } + } +} + +static void draw_background() +{ + INT32 pos = (*DrvBgPos >> 4) & 0x3ff; + + for (INT32 i = 0; i < 0x1000; i++) + { + INT32 offs = ((*DrvBgCtrl << 9) & 0x6000) + (i << 1); + INT32 attr = DrvGfxROM1[offs]; + INT32 x = (DrvGfxROM1[offs + 1] << 1) + (i & 1) + pos + ((i & 8) << 6); + INT32 y = ((i >> 4) << 3) | (i & 7); + INT32 pen = (attr & 0x7f) | 0x100; + + if (*DrvBgCtrl & 1) + { + x = 0x400 - (x & 0x3ff); + y = 0x100 - (y & 0x0ff); + } + + for (INT32 j = 0; j <= ((attr & 0x80) ? 0 : 3); j++) + { + INT32 sx = ((((j >> 0) & 1) + x) & 0x1ff) - 0x60; + INT32 sy = ((((j >> 1) & 1) + y) & 0x0ff) - 0x10; + + if (sx < 0 || sy < 0 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + pTransDraw[sy * nScreenWidth + sx] = pen; + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x200; i++) { + INT32 p = Palette[i]; + DrvPalette[i] = BurnHighCol(p >> 16, p >> 8, p, 0); + } + } + + for (INT32 offs = 0; offs < nScreenWidth * nScreenHeight; offs++) { + pTransDraw[offs] = 0x00ff; + } + + draw_background(); + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + *DrvBgPos += (*DrvBgCtrl >> 1) & 7; + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + } + + ZetNewFrame(); + vblank = 0; + + INT32 nCycleSegment; + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 4000000 / 60, 1748000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + if (i == 8 || i == 248) vblank ^= 1; + + nCycleSegment = nCyclesTotal[0] / nInterleave; + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nCycleSegment); + if (i == (nInterleave-1) && DrvJoy2[0]) ZetNmi(); + ZetClose(); + + nCycleSegment = nCyclesTotal[1] / nInterleave; + + ZetOpen(1); + //nCyclesDone[1] += ZetRun(nCycleSegment); + BurnTimerUpdate(i * nCycleSegment); + ZetClose(); + } + + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + + ZetScan(nAction); + BurnYM2203Scan(nAction, pnMin); + } + + return 0; +} + + +// Sky Fox + +static struct BurnRomInfo skyfoxRomDesc[] = { + { "skyfox1.bin", 0x08000, 0xb4d4bb6f, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "skyfox2.bin", 0x08000, 0xe15e0263, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "skyfox9.bin", 0x08000, 0x0b283bf5, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "skyfox3.bin", 0x10000, 0x3a17a929, 3 | BRF_GRA }, // 3 Sprites + { "skyfox4.bin", 0x10000, 0x358053bb, 3 | BRF_GRA }, // 4 + { "skyfox5.bin", 0x10000, 0xc1215a6e, 3 | BRF_GRA }, // 5 + { "skyfox6.bin", 0x10000, 0xcc37e15d, 3 | BRF_GRA }, // 6 + { "skyfox7.bin", 0x10000, 0xfa2ab5b4, 3 | BRF_GRA }, // 7 + { "skyfox8.bin", 0x10000, 0x0e3edc49, 3 | BRF_GRA }, // 8 + + { "skyfox10.bin", 0x08000, 0x19f58f9c, 4 | BRF_GRA }, // 9 Starfield + + { "sfoxrprm.bin", 0x00100, 0x79913c7f, 5 | BRF_GRA }, // 10 Color Proms + { "sfoxgprm.bin", 0x00100, 0xfb73d434, 5 | BRF_GRA }, // 11 + { "sfoxbprm.bin", 0x00100, 0x60d2ab41, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(skyfox) +STD_ROM_FN(skyfox) + +struct BurnDriver BurnDrvSkyfox = { + "skyfox", NULL, NULL, NULL, "1987", + "Sky Fox\0", NULL, "Jaleco (Nichibutsu USA license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, skyfoxRomInfo, skyfoxRomName, NULL, NULL, SkyfoxInputInfo, SkyfoxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 320, 3, 4 +}; + + +// Exerizer (Japan) (bootleg) + +static struct BurnRomInfo exerizrbRomDesc[] = { + { "1-a", 0x08000, 0x5df72a5d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "skyfox2.bin", 0x08000, 0xe15e0263, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "skyfox9.bin", 0x08000, 0x0b283bf5, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "1-c", 0x10000, 0x450e9381, 3 | BRF_GRA }, // 3 Sprites + { "skyfox4.bin", 0x10000, 0x358053bb, 3 | BRF_GRA }, // 4 + { "1-e", 0x10000, 0x50a38c60, 3 | BRF_GRA }, // 5 + { "skyfox6.bin", 0x10000, 0xcc37e15d, 3 | BRF_GRA }, // 6 + { "1-g", 0x10000, 0xc9bbfe5c, 3 | BRF_GRA }, // 7 + { "skyfox8.bin", 0x10000, 0x0e3edc49, 3 | BRF_GRA }, // 8 + + { "skyfox10.bin", 0x08000, 0x19f58f9c, 4 | BRF_GRA }, // 9 Starfield + + { "sfoxrprm.bin", 0x00100, 0x79913c7f, 5 | BRF_GRA }, // 10 Color Proms + { "sfoxgprm.bin", 0x00100, 0xfb73d434, 5 | BRF_GRA }, // 11 + { "sfoxbprm.bin", 0x00100, 0x60d2ab41, 5 | BRF_GRA }, // 12 +}; + +STD_ROM_PICK(exerizrb) +STD_ROM_FN(exerizrb) + +struct BurnDriver BurnDrvExerizrb = { + "exerizerb", "skyfox", NULL, NULL, "1987", + "Exerizer (Japan) (bootleg)\0", NULL, "Jaleco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, exerizrbRomInfo, exerizrbRomName, NULL, NULL, SkyfoxInputInfo, SkyfoxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, &DrvRecalc, 0x200, + 224, 320, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_skykid.cpp b/src/burn/drivers/misc_pre90s/d_skykid.cpp new file mode 100644 index 00000000..224a5e95 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_skykid.cpp @@ -0,0 +1,1087 @@ +// FB Alpha Sky Kid driver module +// Based on MAME driver by Manuel Abadia and various others + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "m6800_intf.h" +#include "namco_snd.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvHD63701ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvColPROM; +static UINT8 *DrvHD63701RAM1; +static UINT8 *DrvHD63701RAM; +static UINT8 *DrvWavRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvTxtRAM; +static UINT8 *DrvSprRAM; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *m6809_bank; +static UINT8 *interrupt_enable; +static UINT8 *flipscreen; +static UINT8 *priority; +static UINT8 *coin_lockout; +static UINT16 *scroll; +static UINT8 *ip_select; + +static INT32 watchdog; +static INT32 hd63701_in_reset = 0; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvDips[3]; +static UINT8 DrvReset; +static UINT8 DrvInputs[8]; + +static INT32 nCyclesDone[2]; + +static struct BurnInputInfo SkykidInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy3 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy3 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy3 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy3 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 2, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 4, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy4 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy4 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy4 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy4 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 0, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Skykid) + +static struct BurnDIPInfo SkykidDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xf2, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x12, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Skip" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x12, 0x01, 0x60, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x60, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x60, 0x40, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, // swapped + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Buy In" }, + {0x13, 0x01, 0x02, 0x00, "No" }, + {0x13, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x30, 0x00, "20k every 80k" }, + {0x13, 0x01, 0x30, 0x10, "20k and 80k" }, + {0x13, 0x01, 0x30, 0x20, "30k every 90k" }, + {0x13, 0x01, 0x30, 0x30, "30k and 90k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x80, "1" }, + {0x13, 0x01, 0xc0, 0x40, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Skykid) + +static struct BurnDIPInfo SkykidsDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xf2, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x12, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Select" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x12, 0x01, 0x60, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x60, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x60, 0x40, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, // swapped + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Buy In" }, + {0x13, 0x01, 0x02, 0x00, "No" }, + {0x13, 0x01, 0x02, 0x02, "Yes" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x13, 0x01, 0x30, 0x00, "30k every 80k" }, + {0x13, 0x01, 0x30, 0x10, "30k and 80k" }, + {0x13, 0x01, 0x30, 0x20, "40k every 90k" }, + {0x13, 0x01, 0x30, 0x30, "40k and 90k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0xc0, 0x80, "1" }, + {0x13, 0x01, 0xc0, 0x40, "2" }, + {0x13, 0x01, 0xc0, 0xc0, "3" }, + {0x13, 0x01, 0xc0, 0x00, "5" }, +}; + +STDDIPINFO(Skykids) + +static struct BurnDIPInfo DrgnbstrDIPList[]= +{ + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x12, 0x01, 0x03, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x03, 0x03, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Round Skip" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x00, "Off" }, + {0x12, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x12, 0x01, 0x60, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x20, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x60, 0x60, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x60, 0x40, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x13, 0x01, 0x01, 0x01, "No" }, + {0x13, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Bonus Level" }, + {0x13, 0x01, 0x02, 0x02, "Full" }, + {0x13, 0x01, 0x02, 0x00, "Partial" }, + + {0 , 0xfe, 0 , 4, "Bonus Vitality" }, + {0x13, 0x01, 0x0c, 0x00, "64" }, + {0x13, 0x01, 0x0c, 0x08, "48/64" }, + {0x13, 0x01, 0x0c, 0x04, "32/64" }, + {0x13, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Starting Vitality" }, + {0x13, 0x01, 0x30, 0x00, "160" }, + {0x13, 0x01, 0x30, 0x30, "128" }, + {0x13, 0x01, 0x30, 0x10, "96" }, + {0x13, 0x01, 0x30, 0x20, "64" }, + + {0 , 0xfe, 0 , 2, "Level of Monster" }, + {0x13, 0x01, 0x40, 0x40, "Normal" }, + {0x13, 0x01, 0x40, 0x00, "Difficult" }, + + {0 , 0xfe, 0 , 2, "Spurt Time" }, + {0x13, 0x01, 0x80, 0x80, "Normal" }, + {0x13, 0x01, 0x80, 0x00, "Difficult" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x14, 0x01, 0x02, 0x02, "Upright" }, + {0x14, 0x01, 0x02, 0x00, "Cocktail" }, +}; + +STDDIPINFO(Drgnbstr) + +static inline void sync_HD63701(INT32 run) +{ + INT32 nNext = (INT32)((float)((102400.000 * nM6809CyclesTotal) / 25600)); + + if (nNext > 0) { + if (run) { + nCyclesDone[1] += HD63701Run(nNext - nCyclesDone[1]); + } else { + nCyclesDone[1] += nNext - nCyclesDone[1]; + } + } +} + +static void m6809Bankswitch(INT32 bank) +{ + bank &= 1; + + if (m6809_bank[0] != bank) { + m6809_bank[0] = bank; + + M6809MapMemory(DrvM6809ROM + 0x10000 + bank * 0x2000, 0x0000, 0x1fff, M6809_ROM); + } +} + +void skykid_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xff00) == 0x6000) { + scroll[1] = address & 0x0ff; + return; + } + + if ((address & 0xfe00) == 0x6200) { + scroll[0] = address & 0x1ff; + return; + } + + if ((address & 0xfc00) == 0x6800) { + namcos1_custom30_write(address & 0x3ff, data); + return; + } + + if ((address & 0xf000) == 0x7000) { + INT32 b = (~address & 0x0800) / 0x0800; + + interrupt_enable[0] = b; + if (b == 0) M6809SetIRQ(0, M6809_IRQSTATUS_NONE); + return; + } + + if ((address & 0xf000) == 0x8000) { + INT32 b = (~address & 0x0800) / 0x0800; + + if (b == 0) { + if (hd63701_in_reset == 0) { // sync the HD63701 and then reset it + sync_HD63701(1); + HD63701Reset(); + hd63701_in_reset = 1; + } + } + else + { + if (hd63701_in_reset) { // burn cycles and then re-enable the HD63701 + sync_HD63701(0); + hd63701_in_reset = 0; + } + } + + return; + } + + if ((address & 0xf000) == 0x9000) { + INT32 b = (~address & 0x0800) / 0x0800; + + m6809Bankswitch(b); + return; + } + + if ((address & 0xfffe) == 0xa000) { + *flipscreen = address & 1; + *priority = ((data & 0xf0) == 0x50) ? 1 : 0; + return; + } +} + +UINT8 skykid_main_read(UINT16 address) +{ + if ((address & 0xfc00) == 0x6800) { + return namcos1_custom30_read(address & 0x3ff); + } + + if ((address & 0xf800) == 0x7800) { + watchdog = 0; + return 0; + } + + return 0; +} + +void skykid_mcu_write(UINT16 address, UINT8 data) +{ + if ((address & 0xffe0) == 0x0000) { + m6803_internal_registers_w(address & 0x1f, data); + return; + } + + if ((address & 0xff80) == 0x0080) { + DrvHD63701RAM1[address & 0x7f] = data; + return; + } + + if ((address & 0xfc00) == 0x1000) { + namcos1_custom30_write(address & 0x3ff, data); + return; + } + + if ((address & 0xe000) == 0x2000) { + watchdog = 0; + return; + } + + if ((address & 0xc000) == 0x4000) { + INT32 b = (~address & 0x2000) / 0x2000; + + interrupt_enable[1] = b; + + if (b == 0) HD63701SetIRQ(0, HD63701_IRQSTATUS_NONE); + return; + } +} + +UINT8 skykid_mcu_read(UINT16 address) +{ + if ((address & 0xffe0) == 0x0000) { + return m6803_internal_registers_r(address & 0x1f); + } + + if ((address & 0xff80) == 0x0080) { + return DrvHD63701RAM1[address & 0x7f]; + } + + if ((address & 0xfc00) == 0x1000) { + return namcos1_custom30_read(address & 0x3ff); + } + + return 0; +} + +void skykid_mcu_write_port(UINT16 port, UINT8 data) +{ + switch (port & 0x1ff) + { + case HD63701_PORT1: + { + switch (data & 0xe0) { + case 0x60: + *ip_select = data & 0x07; + return; + + case 0xc0: + *coin_lockout = ~data & 0x01; + // coin counters 0 -> data & 0x02, 1 -> data & 0x04 + return; + } + } + return; + + case HD63701_PORT2: + // led0 = data & 8, led1 = data & 0x10 + return; + } +} + +UINT8 skykid_mcu_read_port(UINT16 port) +{ + switch (port & 0x1ff) + { + case HD63701_PORT1: + return DrvInputs[*ip_select]; + + case HD63701_PORT2: + return 0xff; + } + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 0; i < 0x100; i++) { + INT32 r = DrvColPROM[i + 0x000] & 0x0f; + INT32 g = DrvColPROM[i + 0x100] & 0x0f; + INT32 b = DrvColPROM[i + 0x200] & 0x0f; + + Palette[i] = (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | (b << 0); + } + + for (INT32 i = 0; i < 0x400; i++) { + Palette[i + 0x100] = Palette[DrvColPROM[0x300 + i]]; + } +} + +static void DrvSpriteExpand() +{ + for (INT32 i = 0; i < 0x2000; i++) { + DrvGfxROM2[0x8000 + i] = DrvGfxROM2[0x4000 + i]; + DrvGfxROM2[0xa000 + i] = DrvGfxROM2[0x4000 + i] >> 4; + DrvGfxROM2[0x4000 + i] = DrvGfxROM2[0x6000 + i]; + } +} + +static INT32 DrvGfxDecode() +{ + INT32 Planes[3] = { (0x8000 * 8) + 4, 0, 4 }; + INT32 XOffs0[8] = { 8*8, 8*8+1, 8*8+2, 8*8+3, 0, 1, 2, 3 }; + INT32 XOffs1[8] = { 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3 }; + INT32 XOffs2[16]= { 0, 1, 2, 3, 8*8, 8*8+1, 8*8+2, 8*8+3, 16*8+0, 16*8+1, 16*8+2, 16*8+3, 24*8+0, 24*8+1, 24*8+2, 24*8+3 }; + INT32 YOffs0[16]= { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 32*8, 33*8, 34*8, 35*8, 36*8, 37*8, 38*8, 39*8 }; + INT32 YOffs1[8] = { 0*8, 2*8, 4*8, 6*8, 8*8, 10*8, 12*8, 14*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x10000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x2000); + + GfxDecode(0x0200, 2, 8, 8, Planes + 1, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x2000); + + GfxDecode(0x0200, 2, 8, 8, Planes + 1, XOffs1, YOffs1, 0x080, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x10000); + + GfxDecode(0x0200, 3, 16, 16, Planes + 0, XOffs2, YOffs0, 0x200, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset(INT32 ClearRAM) +{ + if (ClearRAM) { + memset (AllRam, 0, RamEnd - AllRam); + } + + M6809Open(0); + M6809Reset(); + m6809_bank[0] = ~0; + m6809Bankswitch(0); + M6809Close(); + +// HD63701Open(0); + HD63701Reset(); +// HD63701Close(); + + watchdog = 0; + hd63701_in_reset = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x014000; + DrvHD63701ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x010000; + DrvGfxROM2 = Next; Next += 0x030000; + + DrvColPROM = Next; Next += 0x000700; + + Palette = (UINT32*)Next; Next += 0x0500 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0500 * sizeof(UINT32); + + AllRam = Next; + + DrvHD63701RAM1 = Next; Next += 0x000080; + DrvHD63701RAM = Next; Next += 0x000800; + + NamcoSoundProm = Next; + DrvWavRAM = Next; Next += 0x000500; + + DrvVidRAM = Next; Next += 0x001000; + DrvTxtRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x001800; + + m6809_bank = Next; Next += 0x000001; + interrupt_enable = Next; Next += 0x000002; + flipscreen = Next; Next += 0x000001; + priority = Next; Next += 0x000001; + coin_lockout = Next; Next += 0x000001; + ip_select = Next; Next += 0x000001; + + scroll = (UINT16*)Next; Next += 0x0002 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x08000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x0c000, 1, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x10000, 2, 1)) return 1; + + if (BurnLoadRom(DrvHD63701ROM + 0x08000, 3, 1)) return 1; + if (BurnLoadRom(DrvHD63701ROM + 0x0f000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x04000, 8, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00000, 9, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00100, 10, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00200, 11, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00300, 12, 1)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00500, 13, 1)) return 1; + + DrvSpriteExpand(); + DrvGfxDecode(); + DrvPaletteInit(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809ROM + 0x10000, 0x0000, 0x1fff, M6809_ROM); + M6809MapMemory(DrvVidRAM, 0x2000, 0x2fff, M6809_RAM); + M6809MapMemory(DrvTxtRAM, 0x4000, 0x47ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x4800, 0x5fff, M6809_RAM); + M6809MapMemory(DrvM6809ROM + 0x08000, 0x8000, 0xffff, M6809_ROM); + M6809SetWriteByteHandler(skykid_main_write); + M6809SetReadByteHandler(skykid_main_read); + M6809Close(); + + HD63701Init(1); +// HD63701Open(0); + HD63701MapMemory(DrvHD63701ROM + 0x8000, 0x8000, 0xbfff, HD63701_ROM); + HD63701MapMemory(DrvHD63701RAM, 0xc000, 0xc7ff, HD63701_RAM); + HD63701MapMemory(DrvHD63701ROM + 0xf000, 0xf000, 0xffff, HD63701_ROM); + HD63701SetReadByteHandler(skykid_mcu_read); + HD63701SetWriteByteHandler(skykid_mcu_write); + HD63701SetReadPortHandler(skykid_mcu_read_port); + HD63701SetWritePortHandler(skykid_mcu_write_port); +// HD63701Close(); + + NamcoSoundInit(49152000/2048); + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + NamcoSoundExit(); + + M6809Exit(); + HD63701Exit(); + + BurnFree (AllMem); + + NamcoSoundProm = NULL; + + return 0; +} + +static void draw_fg_layer() +{ + INT32 bank = *flipscreen ? 0x100 : 0; + + for (INT32 y = 0; y < 28; y++) + { + for (INT32 x = 0; x < 36; x++) + { + INT32 col = x - 2; + INT32 row = y + 2; + + INT32 offs = 0; + if (col & 0x20) { + offs = row + ((col & 0x1f) << 5); + } else { + offs = col + (row << 5); + } + + INT32 code = DrvTxtRAM[offs + 0x000] + bank; + INT32 color = DrvTxtRAM[offs + 0x400] & 0x3f; + + if (*flipscreen) { + Render8x8Tile_Mask_Clip(pTransDraw, code, 280 - (x * 8), 216 - (y * 8), color, 2, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, x * 8, y * 8, color, 2, 0, 0, DrvGfxROM0); + } + } + } +} + +static void draw_bg_layer() +{ + INT32 scrollx, scrolly; + + if (*flipscreen) { + scrollx = 189 - (scroll[0] ^ 1); + scrolly = 7 - (scroll[1] ^ 0); + } else { + scrollx = scroll[0] + 35; + scrolly = scroll[1] + 25; + } + scrollx &= 0x1ff; + scrolly &= 0x0ff; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = DrvVidRAM[offs + 0x800]; + INT32 code = DrvVidRAM[offs + 0x000] + ((attr & 0x01) << 8); + INT32 color = ((attr & 0x7e) >> 1) | ((attr & 0x01) << 6); + + if (*flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, 280 - sx, 216 - sy, color + (0x100 >> 2), 2, 0, DrvGfxROM1); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color + (0x100 >> 2), 2, 0, DrvGfxROM1); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0; offs < 0x80; offs += 2) + { + INT32 attrib = DrvSprRAM[0x1780 + offs + 0]; + INT32 sprite = DrvSprRAM[0x0780 + offs + 0] + ((attrib & 0x80) << 1); + INT32 color =(DrvSprRAM[0x0780 + offs + 1] & 0x3f) * 8 + 0x300; + INT32 sx =(DrvSprRAM[0x0f80 + offs + 1]) + ((DrvSprRAM[0x1780 + offs + 1] & 1) << 8) - 71; + INT32 sy = 256 - DrvSprRAM[0x0f80 + offs + 0] - 7; + INT32 flipx = (attrib & 0x01); + INT32 flipy = (attrib & 0x02) >> 1; + INT32 sizex = (attrib & 0x04) >> 2; + INT32 sizey = (attrib & 0x08) >> 3; + + sprite &= ~sizex; + sprite &= ~(sizey << 1); + + if (*flipscreen) + { + flipx ^= 1; + flipy ^= 1; + } + + sy -= 16 * sizey; + sy = (sy & 0xff) - 32; + + for (INT32 y = 0; y <= sizey; y++) + { + for (INT32 x = 0; x <= sizex; x++) + { + INT32 code = sprite + (y ^ (sizey * flipy)) * 2 + (x ^ (sizex * flipx)); + + RenderTileTranstab(pTransDraw, DrvGfxROM2, code, color, 0xff, sx + x * 16, sy + y * 16, flipx, flipy, 16, 16, DrvColPROM + 0x200); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x500; i++) { + INT32 p = Palette[i]; + DrvPalette[i] = BurnHighCol(p >> 16, p >> 8, p, 0); + } + DrvRecalc = 0; + } + + draw_bg_layer(); + + if (*priority == 0) draw_sprites(); + + draw_fg_layer(); + + if (*priority == 1) draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(1); + } + + watchdog++; + if (watchdog > 180) { + DrvDoReset(0); + } + + { + memset (DrvInputs, 0xff, 8); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[3] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[4] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[5] ^= (DrvJoy4[i] & 1) << i; + DrvInputs[6] ^= (DrvJoy3[i] & 1) << i; + } + + DrvInputs[0] = ((DrvDips[1] & 0xf8) >> 3); + DrvInputs[1] = ((DrvDips[1] & 0x07) << 2) | ((DrvDips[0] & 0xc0) >> 6); + DrvInputs[2] = ((DrvDips[0] & 0x3e) >> 1); + DrvInputs[3] = ((DrvInputs[3] & 0x0d) | (DrvDips[2] & 0x02)) | ((DrvDips[0] & 0x01) << 4); + + if (*coin_lockout) DrvInputs[4] |= 0x03; + } + + M6809NewFrame(); + HD63701NewFrame(); + + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 1536000 / 60, 6144000 / 60 }; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nNext; + + M6809Open(0); + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += M6809Run(nNext - nCyclesDone[0]); + if (i == (nInterleave - 1) && interrupt_enable[0]) { + M6809SetIRQ(0, M6809_IRQSTATUS_ACK); + } + M6809Close(); + + // HD63701Open(0); + if (hd63701_in_reset == 0) { + sync_HD63701(1); + + if (i == (nInterleave - 1) && interrupt_enable[1]) { + HD63701SetIRQ(0, M6800_IRQSTATUS_ACK); + } + } else { + sync_HD63701(0); + } + // HD63701Close(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + NamcoSoundUpdate(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + return 1; // Broken :( + + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6809Scan(nAction); + HD63701Scan(nAction); + + NamcoSoundScan(nAction, pnMin); + + SCAN_VAR(hd63701_in_reset); + } + + if (nAction & ACB_WRITE) { + M6809Open(0); + m6809Bankswitch(m6809_bank[0]); + M6809Close(); + } + + return 0; +} + + +// Sky Kid (new version) + +static struct BurnRomInfo skykidRomDesc[] = { + { "sk2_2.6c", 0x4000, 0xea8a5822, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "sk1-1c.6b", 0x4000, 0x7abe6c6c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sk1_3.6d", 0x4000, 0x314b8765, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "sk2_4.3c", 0x2000, 0xa460d0e0, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus63-63a1.mcu", 0x1000, 0x6ef08fb3, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "sk1_6.6l", 0x2000, 0x58b731b9, 3 | BRF_GRA }, // 5 Characters + + { "sk1_5.7e", 0x2000, 0xc33a498e, 4 | BRF_GRA }, // 6 Background Tiles + + { "sk1_8.10n", 0x4000, 0x44bb7375, 5 | BRF_GRA }, // 7 Sprites + { "sk1_7.10m", 0x4000, 0x3454671d, 5 | BRF_GRA }, // 8 + + { "sk1-1.2n", 0x0100, 0x0218e726, 6 | BRF_GRA }, // 9 Color PROMs + { "sk1-2.2p", 0x0100, 0xfc0d5b85, 6 | BRF_GRA }, // 10 + { "sk1-3.2r", 0x0100, 0xd06b620b, 6 | BRF_GRA }, // 11 + { "sk1-4.5n", 0x0200, 0xc697ac72, 6 | BRF_GRA }, // 12 + { "sk1-5.6n", 0x0200, 0x161514a4, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(skykid) +STD_ROM_FN(skykid) + +struct BurnDriver BurnDrvSkykid = { + "skykid", NULL, NULL, NULL, "1985", + "Sky Kid (new version)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, skykidRomInfo, skykidRomName, NULL, NULL, SkykidInputInfo, SkykidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 288, 224, 4, 3 +}; + + +// Sky Kid (old version) + +static struct BurnRomInfo skykidoRomDesc[] = { + { "sk2_2.6c", 0x4000, 0xea8a5822, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "sk1_1.6b", 0x4000, 0x070a49d4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sk1_3.6d", 0x4000, 0x314b8765, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "sk2_4.3c", 0x2000, 0xa460d0e0, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus63-63a1.mcu", 0x1000, 0x6ef08fb3, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "sk1_6.6l", 0x2000, 0x58b731b9, 3 | BRF_GRA }, // 5 Characters + + { "sk1_5.7e", 0x2000, 0xc33a498e, 4 | BRF_GRA }, // 6 Background Tiles + + { "sk1_8.10n", 0x4000, 0x44bb7375, 5 | BRF_GRA }, // 7 Sprites + { "sk1_7.10m", 0x4000, 0x3454671d, 5 | BRF_GRA }, // 8 + + { "sk1-1.2n", 0x0100, 0x0218e726, 6 | BRF_GRA }, // 9 Color PROMs + { "sk1-2.2p", 0x0100, 0xfc0d5b85, 6 | BRF_GRA }, // 10 + { "sk1-3.2r", 0x0100, 0xd06b620b, 6 | BRF_GRA }, // 11 + { "sk1-4.5n", 0x0200, 0xc697ac72, 6 | BRF_GRA }, // 12 + { "sk1-5.6n", 0x0200, 0x161514a4, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(skykido) +STD_ROM_FN(skykido) + +struct BurnDriver BurnDrvSkykido = { + "skykido", "skykid", NULL, NULL, "1985", + "Sky Kid (old version)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, skykidoRomInfo, skykidoRomName, NULL, NULL, SkykidInputInfo, SkykidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 288, 224, 4, 3 +}; + + +// Sky Kid (CUS60 version) + +static struct BurnRomInfo skykiddRomDesc[] = { + { "sk1_2.6c", 0x4000, 0x8370671a, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "sk1_1.6b", 0x4000, 0x070a49d4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sk1_3.6d", 0x4000, 0x314b8765, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "sk1_4.3c", 0x2000, 0x887137cc, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "sk1_6.6l", 0x2000, 0x58b731b9, 3 | BRF_GRA }, // 5 Characters + + { "sk1_5.7e", 0x2000, 0xc33a498e, 4 | BRF_GRA }, // 6 Background Tiles + + { "sk1_8.10n", 0x4000, 0x44bb7375, 5 | BRF_GRA }, // 7 Sprites + { "sk1_7.10m", 0x4000, 0x3454671d, 5 | BRF_GRA }, // 8 + + { "sk1-1.2n", 0x0100, 0x0218e726, 6 | BRF_GRA }, // 9 Color PROMs + { "sk1-2.2p", 0x0100, 0xfc0d5b85, 6 | BRF_GRA }, // 10 + { "sk1-3.2r", 0x0100, 0xd06b620b, 6 | BRF_GRA }, // 11 + { "sk1-4.5n", 0x0200, 0xc697ac72, 6 | BRF_GRA }, // 12 + { "sk1-5.6n", 0x0200, 0x161514a4, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(skykidd) +STD_ROM_FN(skykidd) + +struct BurnDriver BurnDrvSkykidd = { + "skykidd", "skykid", NULL, NULL, "1985", + "Sky Kid (CUS60 version)\0", NULL, "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, skykiddRomInfo, skykiddRomName, NULL, NULL, SkykidInputInfo, SkykidDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 288, 224, 4, 3 +}; + + +// Sky Kid (Sipem) + +static struct BurnRomInfo skykidsRomDesc[] = { + { "sk2a.6c", 0x4000, 0x68492672, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "sk1a.6b", 0x4000, 0xe16abe25, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sk1_3.6d", 0x4000, 0x314b8765, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "sk2_4.3c", 0x2000, 0xa460d0e0, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus63-63a1.mcu", 0x1000, 0x6ef08fb3, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "sk1_6.6l", 0x2000, 0x58b731b9, 3 | BRF_GRA }, // 5 Characters + + { "sk1_5.7e", 0x2000, 0xc33a498e, 4 | BRF_GRA }, // 6 Background Tiles + + { "sk1_8.10n", 0x4000, 0x44bb7375, 5 | BRF_GRA }, // 7 Sprites + { "sk1_7.10m", 0x4000, 0x3454671d, 5 | BRF_GRA }, // 8 + + { "sk1-1.2n", 0x0100, 0x0218e726, 6 | BRF_GRA }, // 9 Color PROMs + { "sk1-2.2p", 0x0100, 0xfc0d5b85, 6 | BRF_GRA }, // 10 + { "sk1-3.2r", 0x0100, 0xd06b620b, 6 | BRF_GRA }, // 11 + { "sk1-4.5n", 0x0200, 0xc697ac72, 6 | BRF_GRA }, // 12 + { "sk1-5.6n", 0x0200, 0x161514a4, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(skykids) +STD_ROM_FN(skykids) + +struct BurnDriver BurnDrvSkykids = { + "skykids", "skykid", NULL, NULL, "1985", + "Sky Kid (Sipem)\0", NULL, "Namco [Sipem license]", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, skykidsRomInfo, skykidsRomName, NULL, NULL, SkykidInputInfo, SkykidsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 288, 224, 4, 3 +}; + + +// Dragon Buster + +static struct BurnRomInfo drgnbstrRomDesc[] = { + { "db1_2b.6c", 0x4000, 0x0f11cd17, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "db1_1.6b", 0x4000, 0x1c7c1821, 1 | BRF_PRG | BRF_ESS }, // 1 + { "db1_3.6d", 0x4000, 0x6da169ae, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "db1_4.3c", 0x2000, 0x8a0b1fc1, 2 | BRF_PRG | BRF_ESS }, // 3 HD63701 Code + { "cus60-60a1.mcu", 0x1000, 0x076ea82a, 2 | BRF_PRG | BRF_ESS }, // 4 + + { "db1_6.6l", 0x2000, 0xc080b66c, 3 | BRF_GRA }, // 5 Characters + + { "db1_5.7e", 0x2000, 0x28129aed, 4 | BRF_GRA }, // 6 Background Tiles + + { "db1_8.10n", 0x4000, 0x11942c61, 5 | BRF_GRA }, // 7 Sprites + { "db1_7.10m", 0x4000, 0xcc130fe2, 5 | BRF_GRA }, // 8 + + { "db1-1.2n", 0x0100, 0x3f8cce97, 6 | BRF_GRA }, // 9 Color PROMs + { "db1-2.2p", 0x0100, 0xafe32436, 6 | BRF_GRA }, // 10 + { "db1-3.2r", 0x0100, 0xc95ff576, 6 | BRF_GRA }, // 11 + { "db1-4.5n", 0x0200, 0xb2180c21, 6 | BRF_GRA }, // 12 + { "db1-5.6n", 0x0200, 0x5e2b3f74, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(drgnbstr) +STD_ROM_FN(drgnbstr) + +struct BurnDriver BurnDrvDrgnbstr = { + "drgnbstr", NULL, NULL, NULL, "1984", + "Dragon Buster\0", "Missing sounds", "Namco", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, drgnbstrRomInfo, drgnbstrRomName, NULL, NULL, SkykidInputInfo, DrgnbstrDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 288, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_snk68.cpp b/src/burn/drivers/misc_pre90s/d_snk68.cpp new file mode 100644 index 00000000..df8f7c93 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_snk68.cpp @@ -0,0 +1,1878 @@ +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "upd7759.h" + +// To Do: +// Analog Inputs +// Fix savestates (crash due to snd?) + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvInputs[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT32 nAnalogAxis[2] = {0,0}; +static UINT16 DrvAxis[2]; + +static INT32 Rotary1 = 0; +static INT32 Rotary1OldVal = 0; +static INT32 Rotary2 = 0; +static INT32 Rotary2OldVal = 0; + +static UINT8 *Mem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KRom; +static UINT8 *Drv68KRomBank; +static UINT8 *DrvZ80Rom; +static UINT8 *Drv68KRam; +static UINT8 *DrvVidRam; +static UINT8 *DrvSprRam; +static UINT8 *DrvPalRam; +static UINT8 *DrvZ80Ram; +static UINT8 *DrvGfx0; +static UINT8 *DrvGfx0Trans; +static UINT8 *DrvGfx1; +static UINT8 *DrvSnd0; + +static UINT32 *Palette; +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static INT32 game_select; + +static INT32 invert_controls; +static INT32 soundlatch; +static INT32 flipscreen; +static INT32 sprite_flip; +static INT32 pow_charbase; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down", }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 3"}, + + {"Service 1", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo IkariInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy3 + 4, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up", }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down", }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy1 + 6, "p1 fire 3"}, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 z-axis"), + + {"P2 Start" , BIT_DIGITAL , DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up", }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down", }, + {"P2 Left" , BIT_DIGITAL , DrvJoy2 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy2 + 6, "p2 fire 3"}, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 1, "p2 z-axis"), + + {"Service 1", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Ikari) + + +static struct BurnDIPInfo PowDIPList[]= +{ + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x03, 0x00, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0x0c, 0x0c, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x04, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x00, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x10, 0x00, "2" }, + {0x14, 0x01, 0x10, 0x10, "3" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x14, 0x01, 0x14, 0x00, "1st & 2nd only" }, + {0x14, 0x01, 0x14, 0x14, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x14, 0x01, 0x40, 0x00, "English" }, + {0x14, 0x01, 0x40, 0x40, "Japanese" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x02, 0x02, "No" }, + {0x15, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x00, "20k 50k" }, + {0x15, 0x01, 0x0c, 0x08, "40k 100k" }, + {0x15, 0x01, 0x0c, 0x04, "60k 150k" }, + {0x15, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x15, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x15, 0x01, 0x30, 0x14, "Demo Sounds Off" }, + {0x15, 0x01, 0x30, 0x30, "Freeze" }, + {0x15, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0x00, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Pow) + + +static struct BurnDIPInfo PowjDIPList[]= +{ + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x03, 0x00, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + {0x14, 0x01, 0x03, 0x03, "1 Coin 4 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0x0c, 0x0c, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x04, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x00, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x10, 0x00, "2" }, + {0x14, 0x01, 0x10, 0x10, "3" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x14, 0x01, 0x14, 0x00, "1st & 2nd only" }, + {0x14, 0x01, 0x14, 0x14, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x02, 0x02, "No" }, + {0x15, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x00, "20k 50k" }, + {0x15, 0x01, 0x0c, 0x08, "40k 100k" }, + {0x15, 0x01, 0x0c, 0x04, "60k 150k" }, + {0x15, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x15, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x15, 0x01, 0x30, 0x14, "Demo Sounds Off" }, + {0x15, 0x01, 0x30, 0x30, "Freeze" }, + {0x15, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0x00, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Powj) + +static struct BurnDIPInfo StreetsmDIPList[]= +{ + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x02, "1" }, + {0x14, 0x01, 0x03, 0x00, "2" }, + {0x14, 0x01, 0x03, 0x01, "3" }, + {0x14, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 4 , "Coin A & B" }, + {0x14, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x0c, 0x00, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x0c, 0x04, "1 Coin 2 Credits" }, + {0x14, 0x01, 0x0c, 0x0c, "Free Play" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x14, 0x01, 0x14, 0x00, "1st & 2nd only" }, + {0x14, 0x01, 0x14, 0x14, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x02, 0x02, "No" }, + {0x15, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x00, "200k 400k" }, + {0x15, 0x01, 0x0c, 0x08, "400k 500k" }, + {0x15, 0x01, 0x0c, 0x04, "600k 800k" }, + {0x15, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x15, 0x01, 0x30, 0x14, "Demo Sounds Off" }, + {0x15, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x15, 0x01, 0x30, 0x30, "Freeze" }, + {0x15, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0x00, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Streetsm) + +static struct BurnDIPInfo StreetsjDIPList[]= +{ + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x02, "1" }, + {0x14, 0x01, 0x03, 0x00, "2" }, + {0x14, 0x01, 0x03, 0x01, "3" }, + {0x14, 0x01, 0x03, 0x03, "4" }, + + {0 , 0xfe, 0 , 4 , "Coin A & B" }, + {0x14, 0x01, 0x0c, 0x0c, "A 4/1 B 1/4" }, + {0x14, 0x01, 0x0c, 0x04, "A 3/1 B 1/3" }, + {0x14, 0x01, 0x0c, 0x08, "A 2/1 B 1/2" }, + {0x14, 0x01, 0x0c, 0x00, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x14, 0x01, 0x14, 0x00, "1st & 2nd only" }, + {0x14, 0x01, 0x14, 0x14, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x02, 0x02, "No" }, + {0x15, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x00, "200k 400k" }, + {0x15, 0x01, 0x0c, 0x08, "400k 500k" }, + {0x15, 0x01, 0x0c, 0x04, "600k 800k" }, + {0x15, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x15, 0x01, 0x30, 0x14, "Demo Sounds Off" }, + {0x15, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x15, 0x01, 0x30, 0x30, "Freeze" }, + {0x15, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0x00, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Streetsj) + +static struct BurnDIPInfo SarDIPList[]= +{ + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2 , "Joystick" }, + {0x16, 0x01, 0x01, 0x00, "Rotary" }, + {0x16, 0x01, 0x01, 0x01, "Standard" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x0c, 0x08, "2" }, + {0x16, 0x01, 0x0c, 0x00, "3" }, + {0x16, 0x01, 0x0c, 0x04, "4" }, + {0x16, 0x01, 0x0c, 0x0c, "5" }, + + {0 , 0xfe, 0 , 4 , "Coin A & B" }, + {0x16, 0x01, 0x30, 0x16, "2 Coins 1 Credit" }, + {0x16, 0x01, 0x30, 0x00, "1 Coin 1 Credit" }, + {0x16, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + {0x16, 0x01, 0x30, 0x30, "Free Play" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x16, 0x01, 0x40, 0x00, "1st & 2nd only" }, + {0x16, 0x01, 0x40, 0x40, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x80, 0x00, "Off" }, + {0x16, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x02, 0x02, "No" }, + {0x17, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x17, 0x01, 0x0c, 0x00, "50k 200k" }, + {0x17, 0x01, 0x0c, 0x08, "70k 270k" }, + {0x17, 0x01, 0x0c, 0x04, "90k 350k" }, + {0x17, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x17, 0x01, 0x30, 0x16, "Demo Sounds Off" }, + {0x17, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x17, 0x01, 0x30, 0x30, "Freeze" }, + {0x17, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0xc0, 0x80, "Easy" }, + {0x17, 0x01, 0xc0, 0x00, "Normal" }, + {0x17, 0x01, 0xc0, 0x40, "Hard" }, + {0x17, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Sar) + +static struct BurnDIPInfo IkariDIPList[]= +{ + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x03, 0x02, "2" }, + {0x16, 0x01, 0x03, 0x00, "3" }, + {0x16, 0x01, 0x03, 0x01, "4" }, + {0x16, 0x01, 0x03, 0x03, "5" }, + + {0 , 0xfe, 0 , 4 , "Coin A & B" }, + {0x16, 0x01, 0x0c, 0x08, "First 2C_1C, then 1C_1C"}, + {0x16, 0x01, 0x0c, 0x00, "1 Coin 1 Credit" }, + {0x16, 0x01, 0x0c, 0x04, "First 1C_2C, then 1C_1C"}, + {0x16, 0x01, 0x0c, 0x0c, "Free Play" }, + + {0 , 0xfe, 0 , 2 , "Bonus Ocurrence" }, + {0x16, 0x01, 0x16, 0x00, "1st & 2nd only" }, + {0x16, 0x01, 0x16, 0x16, "1st & every 2nd" }, + + {0 , 0xfe, 0 , 2 , "Blood" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x80, 0x00, "Off" }, + {0x16, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x17, 0x01, 0x01, 0x00, "Off" }, + {0x17, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x02, 0x02, "No" }, + {0x17, 0x01, 0x02, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x17, 0x01, 0x0c, 0x00, "20k 50k" }, + {0x17, 0x01, 0x0c, 0x08, "40k 100k" }, + {0x17, 0x01, 0x0c, 0x04, "60k 150k" }, + {0x17, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4 , "Game Mode" }, + {0x17, 0x01, 0x30, 0x16, "Demo Sounds Off" }, + {0x17, 0x01, 0x30, 0x00, "Demo Sounds On" }, + {0x17, 0x01, 0x30, 0x30, "Freeze" }, + {0x17, 0x01, 0x30, 0x10, "Infinite Lives (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0xc0, 0x00, "Easy" }, + {0x17, 0x01, 0xc0, 0x80, "Normal" }, + {0x17, 0x01, 0xc0, 0x40, "Hard" }, + {0x17, 0x01, 0xc0, 0xc0, "Hardest" }, +}; + +STDDIPINFO(Ikari) + + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + DrvRecalc = 1; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + UPD7759Reset(); + + soundlatch = 0; + flipscreen = 0; + sprite_flip = 0; + pow_charbase = 0; + invert_controls = 0; + + nAnalogAxis[1] = 0; + nAnalogAxis[0] = 0; + + return 0; +} + +void pow_paletteram16_word_w(UINT32 address) +{ + INT32 r,g,b; + UINT16 data = *((UINT16*)(DrvPalRam + (address & 0x0ffe))); + + r = ((data >> 7) & 0x1e) | ((data >> 14) & 0x01); + g = ((data >> 3) & 0x1e) | ((data >> 13) & 0x01); + b = ((data << 1) & 0x1e) | ((data >> 12) & 0x01); + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + Palette[(address >> 1) & 0x7ff] = (r << 16) | (g << 8) | b; + DrvPalette[(address >> 1) & 0x7ff] = BurnHighCol(r, g, b, 0); +} + +void __fastcall pow_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xffff8000) == 0x100000 && game_select & 1) { + if (!(address & 2)) + data |= 0xff00; + + *((UINT16 *)(DrvSprRam + (address & 0x7fff))) = data; + + return; + } + + if ((address & 0xfffff000) == 0x400000) { + *((UINT16 *)(DrvPalRam + (address & 0x0ffe))) = data; + + pow_paletteram16_word_w(address); + + return; + } +} + +void __fastcall pow_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xffff8000) == 0x100000 && game_select == 1) { + if ((address & 3) == 3) data = 0xff; + + DrvSprRam[address & 0x7fff] = data; + + return; + } + + if ((address & 0xfffff000) == 0x400000) { + DrvPalRam[address & 0x0fff] = data; + + pow_paletteram16_word_w(address); + + return; + } + + switch (address) + { + case 0x080000: + soundlatch = data; + ZetNmi(); + return; + + case 0x080007: + invert_controls = ((data & 0xff) == 0x07) ? 0xff : 0x00; + return; + + case 0x0c0001: + flipscreen = data & 8; + sprite_flip = data & 4; + pow_charbase = (data & 0x70) << 4; + return; + } +} + + +UINT16 __fastcall pow_read_word(UINT32 address) +{ + bprintf (PRINT_NORMAL, _T("read %x, w\n"), address); + + return 0; +} + +UINT8 __fastcall pow_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080000: + return DrvInputs[1]; + + case 0x080001: + return DrvInputs[0]; + + case 0x0c0000: + case 0x0c0001: + return DrvInputs[2]; + + case 0x0e0000: + case 0x0e0001: + case 0x0e8000: + case 0x0e8001: + return 0xff; + + case 0x0f0000: + case 0x0f0001: + return DrvDips[0]; + + case 0x0f0008: + case 0x0f0009: + return DrvDips[1]; + } + + return 0; +} + +UINT8 __fastcall sar_read_byte(UINT32 address) +{ + switch (address) + { + case 0x080001: + case 0x080003: + case 0x080005: + return DrvInputs[(address >> 1) & 3] ^ invert_controls; + + case 0x0c0000: { + INT32 RetVal = Rotary1; + RetVal = (~(1 << RetVal)) & 0xff; + return (UINT8)RetVal; + } + + case 0x0c8000: { + INT32 RetVal = Rotary2; + RetVal = (~(1 << RetVal)) & 0xff; + return (UINT8)RetVal; + } + + case 0x0d0000: { + INT32 RetVal = 0xff; + + if (Rotary1 == 8) RetVal -= 0x01; + if (Rotary1 == 9) RetVal -= 0x02; + if (Rotary1 == 10) RetVal -= 0x04; + if (Rotary1 == 11) RetVal -= 0x08; + + if (Rotary2 == 8) RetVal -= 0x10; + if (Rotary2 == 9) RetVal -= 0x20; + if (Rotary2 == 10) RetVal -= 0x40; + if (Rotary2 == 11) RetVal -= 0x80; + return (UINT8)RetVal; + } + + case 0x0f0000: + case 0x0f0001: + return DrvDips[0]; + + case 0x0f0008: + case 0x0f0009: + return DrvDips[1]; + + case 0x0f8000: + return 1; + } + + return 0; +} + +void __fastcall pow_sound_write(UINT16, UINT8) +{ +} + +void __fastcall pow_sound_out(UINT16 address, UINT8 data) +{ + switch (address & 0xff) + { + case 0x00: + case 0x20: + BurnYM3812Write((address >> 5) & 1, data); + return; + + case 0x40: + UPD7759PortWrite(0, data); + UPD7759StartWrite(0, 0); + UPD7759StartWrite(0, 1); + return; + + case 0x80: + UPD7759ResetWrite(0, data); + return; + } + +} + +UINT8 __fastcall pow_sound_read(UINT16 address) +{ + if (address == 0xf800) return soundlatch; + + return 0; +} + +UINT8 __fastcall pow_sound_in(UINT16 address) +{ + address &= 0xff; + + if (address == 0x0000) return BurnYM3812Read(0); + + return 0; +} + +static void powFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 powSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static INT32 DrvGfxDecode(INT32 *spriPlanes, INT32 *spriXOffs, INT32 *spriYOffs, INT32 modulo) +{ + static INT32 tilePlanes[4] = { 0x00000, 0x00004, 0x40000, 0x40004 }; + static INT32 tileXOffs[8] = { 0x43, 0x42, 0x41, 0x40, 0x03, 0x02, 0x01, 0x00 }; + static INT32 tileYOffs[8] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x300000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfx0, 0x010000); + + GfxDecode(0x0800, 4, 8, 8, tilePlanes, tileXOffs, tileYOffs, 0x0080, tmp, DrvGfx0); + + memcpy (tmp, DrvGfx1, 0x300000); + + GfxDecode(0x6000, 4, 16, 16, spriPlanes, spriXOffs, spriYOffs, modulo, tmp, DrvGfx1); + + BurnFree (tmp); + + memset (DrvGfx0Trans, 1, 0x800); + for (INT32 i = 0; i < 0x20000; i++) { + if (DrvGfx0[i]) { + DrvGfx0Trans[i>>6] = 0; + i|=0x3f; + } + } + + return 0; +} + +static INT32 PowGfxDecode() +{ + static INT32 spriPlanes[4] = { 0x000000, 0x400000, 0x800000, 0xc00000 }; + static INT32 spriXOffs[16] = { 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + static INT32 spriYOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + return DrvGfxDecode(spriPlanes, spriXOffs, spriYOffs, 0x100); +} + +static INT32 SarGfxDecode() +{ + static INT32 spriPlanes[4] = { 0x000000, 0x000008,0xc00000, 0xc00008 }; + static INT32 spriXOffs[16] = { 0x107, 0x106, 0x105, 0x104, 0x103, 0x102, 0x101, 0x100, + 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000 }; + static INT32 spriYOffs[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + + return DrvGfxDecode(spriPlanes, spriXOffs, spriYOffs, 0x200); +} + +static INT32 IkariGfxDecode() +{ + static INT32 spriPlanes[4] = { 0xa00000, 0x000000, 0x500000, 0xf00000 }; + static INT32 spriXOffs[16] = { 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + static INT32 spriYOffs[16] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }; + + return DrvGfxDecode(spriPlanes, spriXOffs, spriYOffs, 0x100); +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Drv68KRom = Next; Next += 0x040000; + Drv68KRomBank = Next; Next += 0x040000; + DrvZ80Rom = Next; Next += 0x010000; + + DrvGfx0 = Next; Next += 0x020000; + DrvGfx1 = Next; Next += 0x600000; + + DrvGfx0Trans = Next; Next += 0x000800; + + DrvSnd0 = Next; Next += 0x020000; + + AllRam = Next; + + Drv68KRam = Next; Next += 0x004000; + DrvVidRam = Next; Next += 0x001000; + DrvSprRam = Next; Next += 0x008000; + DrvPalRam = Next; Next += 0x001000; + + DrvZ80Ram = Next; Next += 0x000800; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + RamEnd = Next; + + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + + +static void pow_map_68k() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRam, 0x040000, 0x043fff, SM_RAM); + SekMapMemory(DrvVidRam, 0x100000, 0x100fff, SM_RAM); // video ram + SekMapMemory(DrvSprRam, 0x200000, 0x207fff, SM_RAM); // sprite ram + SekMapMemory(DrvPalRam, 0x400000, 0x400fff, SM_ROM); // palette ram + SekSetWriteByteHandler(0, pow_write_byte); + SekSetWriteWordHandler(0, pow_write_word); + SekSetReadByteHandler(0, pow_read_byte); + SekSetReadWordHandler(0, pow_read_word); + SekClose(); +} + +static void sar_map_68k() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KRom, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KRam, 0x040000, 0x043fff, SM_RAM); + SekMapMemory(DrvSprRam, 0x100000, 0x107fff, SM_ROM); // sprite ram + SekMapMemory(DrvVidRam, 0x200000, 0x200fff, SM_RAM); // video ram + SekMapMemory(DrvVidRam, 0x201000, 0x201fff, SM_WRITE); // video ram mirror + SekMapMemory(Drv68KRomBank, 0x300000, 0x33ffff, SM_ROM); // extra rom + SekMapMemory(DrvPalRam, 0x400000, 0x400fff, SM_ROM); // palette ram + SekSetWriteByteHandler(0, pow_write_byte); + SekSetWriteWordHandler(0, pow_write_word); + SekSetReadByteHandler(0, sar_read_byte); + SekSetReadWordHandler(0, pow_read_word); + SekClose(); +} + + +static INT32 DrvGetRoms() +{ + char* pRomName; + struct BurnRomInfo ri; + UINT8 *LoadP0 = Drv68KRom; + UINT8 *LoadP1 = DrvZ80Rom; + UINT8 *LoadG0 = DrvGfx0; + UINT8 *LoadG1 = DrvGfx1; + UINT8 *LoadS0 = DrvSnd0; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & 7) == 1) { + if (BurnLoadRom(LoadP0 + 1, i + 0, 2)) return 1; + if (BurnLoadRom(LoadP0 + 0, i + 1, 2)) return 1; + LoadP0 += ri.nLen * 2; + i++; + continue; + } + + if ((ri.nType & 7) == 2) { + if (BurnLoadRom(LoadP1, i, 1)) return 1; + LoadP1 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 3) { + if (BurnLoadRom(LoadG0, i, 1)) return 1; + LoadG0 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 4) { + if (BurnLoadRom(LoadG1, i, 1)) return 1; + LoadG1 += ri.nLen; + continue; + } + + if ((ri.nType & 7) == 5) { + if (BurnLoadRom(LoadS0, i, 1)) return 1; + LoadS0 += ri.nLen; + continue; + } + } + + return 0; +} + +static INT32 DrvInit(INT32 game) +{ + game_select = game; + + Mem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + if (DrvGetRoms()) return 1; + + switch (game_select) + { + case 0: // Pow + if (PowGfxDecode()) return 1; + pow_map_68k(); + break; + + case 1: // searchar + if (SarGfxDecode()) return 1; + sar_map_68k(); + break; + + case 2: // streets + if (SarGfxDecode()) return 1; + pow_map_68k(); + break; + + case 3: // ikari + if (IkariGfxDecode()) return 1; + sar_map_68k(); + break; + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xefff, 0, DrvZ80Rom); + ZetMapArea(0x0000, 0xefff, 2, DrvZ80Rom); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80Ram); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80Ram); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80Ram); + ZetSetWriteHandler(pow_sound_write); + ZetSetReadHandler(pow_sound_read); + ZetSetInHandler(pow_sound_in); + ZetSetOutHandler(pow_sound_out); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(4000000, &powFMIRQHandler, &powSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSnd0); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + UPD7759Exit(); + + GenericTilesExit(); + SekExit(); + ZetExit(); + + BurnFree (Mem); + + game_select = 0; + + return 0; +} + + +static void pow_sprites(INT32 j, INT32 pos) +{ + INT32 offs,mx,my,color,tile,fx,fy,i; + + UINT16 *spriteram16 = (UINT16*)(DrvSprRam); + + for (offs = pos; offs < pos+0x800; offs += 0x80 ) + { + mx=(spriteram16[(offs+4+(4*j))>>1]&0xff)<<4; + my=spriteram16[(offs+6+(4*j))>>1]; + mx=mx+(my>>12); + mx=((mx+16)&0x1ff)-16; + + mx=((mx+0x100)&0x1ff)-0x100; + my=((my+0x100)&0x1ff)-0x100; + + my=0x200 - my; + my-=0x200; + + if (flipscreen) { + mx=240-mx; + my=240-my; + } + + my -= 16; + + for (i = 0; i < 0x80; i+=4) + { + color = spriteram16[(offs+i+(0x1000*j)+0x1000)>>1]&0x7f; + + if (color) + { + tile=spriteram16[(offs+2+i+(0x1000*j)+0x1000)>>1]; + fy=tile&0x8000; + fx=tile&0x4000; + tile&=0x3fff; + + if (flipscreen) { + if (fx) fx=0; else fx=1; + if (fy) fy=0; else fy=1; + } + + if (mx > -16 && mx < 256 && my > -16 && my < 224) { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } + } + } + } + + if (flipscreen) { + my-=16; + if (my < -0x100) my+=0x200; + } + else { + my+=16; + if (my > 0x100) my-=0x200; + } + } + } +} + +static void sar_sprites(INT32 j, INT32 z, INT32 pos) +{ + INT32 offs,mx,my,color,tile,fx,fy,i; + + UINT16 *spriteram16 = (UINT16*)(DrvSprRam); + + for (offs = pos; offs < pos+0x800 ; offs += 0x80 ) + { + mx=spriteram16[(offs+j)>>1]; + my=spriteram16[(offs+j+2)>>1]; + + mx=mx<<4; + mx=mx|((my>>12)&0xf); + my=my&0x1ff; + + mx=(mx+0x100)&0x1ff; + my=(my+0x100)&0x1ff; + mx-=0x100; + my-=0x100; + my=0x200 - my; + my-=0x200; + + if (flipscreen) { + mx=240-mx; + my=240-my; + } + + my -= 16; + + for (i = 0; i < 0x80; i += 4) + { + color = spriteram16[(offs+i+z)>>1] & 0x7f; + + if (color) + { + tile = spriteram16[(offs+2+i+z)>>1]; + + if (sprite_flip) { + fx=0; + fy=tile&0x8000; + } else { + fy=0; + fx=tile&0x8000; + } + + if (flipscreen) { + if (fx) fx=0; else fx=1; + if (fy) fy=0; else fy=1; + } + + tile&=0x7fff; + if (tile>0x5fff) break; + + if (mx > -16 && mx < 256 && my > -16 && my < 224) { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, tile, mx, my, color, 4, 0, 0, DrvGfx1); + } + } + } + } + + if (flipscreen) { + my-=16; + if (my < -0x100) my+=0x200; + } + else { + my+=16; + if (my > 0x100) my-=0x200; + } + } + } +} + +static void pow_foreground() +{ + UINT16 *vidram = (UINT16*)DrvVidRam; + + for (INT32 offs = 0; offs < 0x1000 / 2; offs+=2) + { + INT32 sy = (offs << 2) & 0xf8; + INT32 sx = (offs >> 3) & 0xf8; + + if (flipscreen) { + sy ^= 0xf8; + sx ^= 0xf8; + } + + if (sy < 16 || sy > 239) continue; + sy -= 16; + + INT32 code = (vidram[offs | 0] & 0xff) | pow_charbase; + INT32 color = vidram[offs | 1] & 0x0f; + + if (DrvGfx0Trans[code]) continue; + + if (flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfx0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfx0); + } + } +} + +static void sar_foreground() +{ + UINT16 *vidram = (UINT16*)DrvVidRam; + + for (INT32 offs = 0; offs < 0x1000 / 2; offs+=2) + { + INT32 sy = (offs << 2) & 0xf8; + INT32 sx = (offs >> 3) & 0xf8; + + if (flipscreen) { + sy ^= 0xf8; + sx ^= 0xf8; + } + + if (sy < 16 || sy > 239) continue; + sy -= 16; + + INT32 code = vidram[offs]; + INT32 color = code >> 12; + + // kludge for bad tile (ikari) + if (code == 0x80ff) { + code = 0x02ca; + color = 0x07; + } + + code &= 0x0fff; + + if (DrvGfx0Trans[code]) continue; + + if (flipscreen) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfx0); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfx0); + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + for (INT32 offs = 0; offs < nScreenHeight * nScreenWidth; offs++) { + pTransDraw[offs] = 0x7ff; + } + + if (!game_select) { + pow_sprites(1, 0x000); + pow_sprites(1, 0x800); + pow_sprites(2, 0x000); + pow_sprites(2, 0x800); + pow_sprites(0, 0x000); + pow_sprites(0, 0x800); + } else { + sar_sprites(8, 0x2000, 0x000); + sar_sprites(8, 0x2000, 0x800); + sar_sprites(12,0x3000, 0x000); + sar_sprites(12,0x3000, 0x800); + sar_sprites(4, 0x1000, 0x000); + sar_sprites(4, 0x1000, 0x800); + } + + if (game_select & 1) { + sar_foreground(); + } else { + pow_foreground(); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = DrvInputs[1] = DrvInputs[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + + nAnalogAxis[0] -= DrvAxis[0]; + DrvInputs[6] = (~nAnalogAxis[0] >> 8) & 0xfe; + + nAnalogAxis[1] -= DrvAxis[1]; + DrvInputs[7] = (~nAnalogAxis[1] >> 8) & 0xfe; + } + + if (game_select == 1 || game_select == 3) { + if ((DrvInputs[6] >> 4) < Rotary1OldVal) { + Rotary1++; + } + + if ((DrvInputs[6] >> 4) > Rotary1OldVal) { + Rotary1--; + } + Rotary1OldVal = DrvInputs[6] >> 4; + if (Rotary1 > 11) Rotary1 = 0; + if (Rotary1 < 0) Rotary1 = 11; + + if ((DrvInputs[7] >> 4) < Rotary2OldVal) { + Rotary2++; + } + + if ((DrvInputs[7] >> 4) > Rotary2OldVal) { + Rotary2--; + } + Rotary2OldVal = DrvInputs[7] >> 4; + if (Rotary2 > 11) Rotary2 = 0; + if (Rotary2 < 0) Rotary2 = 11; + } + + INT32 nTotalCycles[2] = { ((game_select == 1) ? 9000000 : 10000000) / 60, 4000000 / 60 }; + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekRun(nTotalCycles[0]); + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrameYM3812(nTotalCycles[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + UPD7759Update(0, pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + if (nAction & ACB_WRITE) + DrvRecalc = 1; + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + UPD7759Scan(0, nAction, pnMin); + + SCAN_VAR(invert_controls); + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen); + SCAN_VAR(sprite_flip); + SCAN_VAR(pow_charbase); + SCAN_VAR(nAnalogAxis[0]); + SCAN_VAR(nAnalogAxis[1]); + SCAN_VAR(Rotary1); + SCAN_VAR(Rotary1OldVal); + SCAN_VAR(Rotary2); + SCAN_VAR(Rotary2OldVal); + } + + return 0; +} + + +// P.O.W. - Prisoners of War (US version 1) + +static struct BurnRomInfo powRomDesc[] = { + { "dg1ver1.j14", 0x20000, 0x8e71a8af, 1 | BRF_PRG }, // 0 68k COde + { "dg2ver1.l14", 0x20000, 0x4287affc, 1 | BRF_PRG }, // 1 + + { "dg8.e25", 0x10000, 0xd1d61da3, 2 | BRF_PRG }, // 2 Z80 Code + + { "dg9.l25", 0x08000, 0xdf864a08, 3 | BRF_GRA }, // 3 Characters + { "dg10.m25", 0x08000, 0x9e470d53, 3 | BRF_GRA }, // 4 + + { "snk880.11a", 0x20000, 0xe70fd906, 4 | BRF_GRA }, // 5 Sprites + { "snk880.12a", 0x20000, 0x628b1aed, 4 | BRF_GRA }, // 6 + { "snk880.13a", 0x20000, 0x19dc8868, 4 | BRF_GRA }, // 7 + { "snk880.14a", 0x20000, 0x47cd498b, 4 | BRF_GRA }, // 8 + { "snk880.15a", 0x20000, 0x7a90e957, 4 | BRF_GRA }, // 9 + { "snk880.16a", 0x20000, 0xe40a6c13, 4 | BRF_GRA }, // 10 + { "snk880.17a", 0x20000, 0xc7931cc2, 4 | BRF_GRA }, // 11 + { "snk880.18a", 0x20000, 0xeed72232, 4 | BRF_GRA }, // 12 + { "snk880.19a", 0x20000, 0x1775b8dd, 4 | BRF_GRA }, // 13 + { "snk880.20a", 0x20000, 0xf8e752ec, 4 | BRF_GRA }, // 14 + { "snk880.21a", 0x20000, 0x27e9fffe, 4 | BRF_GRA }, // 15 + { "snk880.22a", 0x20000, 0xaa9c00d8, 4 | BRF_GRA }, // 16 + { "snk880.23a", 0x20000, 0xadb6ad68, 4 | BRF_GRA }, // 17 + { "snk880.24a", 0x20000, 0xdd41865a, 4 | BRF_GRA }, // 18 + { "snk880.25a", 0x20000, 0x055759ad, 4 | BRF_GRA }, // 19 + { "snk880.26a", 0x20000, 0x9bc261c5, 4 | BRF_GRA }, // 20 + + { "dg7.d20", 0x10000, 0xaba9a9d3, 5 | BRF_SND }, // 21 upd7759 samples + + { "pal20l10.a6", 0x000cc, 0xc3d9e729, 0 | BRF_OPT }, // 22 pld +}; + +STD_ROM_PICK(pow) +STD_ROM_FN(pow) + +static INT32 powInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvpow = { + "pow", NULL, NULL, NULL, "1988", + "P.O.W. - Prisoners of War (US version 1)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, powRomInfo, powRomName, NULL, NULL, DrvInputInfo, PowDIPInfo, + powInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + + +// Datsugoku - Prisoners of War (Japan) + +static struct BurnRomInfo powjRomDesc[] = { + { "1-2", 0x20000, 0x2f17bfb0, 1 | BRF_PRG }, // 0 68k Code + { "2-2", 0x20000, 0xbaa32354, 1 | BRF_PRG }, // 1 + + { "dg8.e25", 0x10000, 0xd1d61da3, 2 | BRF_PRG }, // 2 Z80 Code + + { "dg9.l25", 0x08000, 0xdf864a08, 3 | BRF_GRA }, // 3 Characters + { "dg10.m25", 0x08000, 0x9e470d53, 3 | BRF_GRA }, // 4 + + { "snk880.11a", 0x20000, 0xe70fd906, 4 | BRF_GRA }, // 5 Sprites + { "snk880.12a", 0x20000, 0x628b1aed, 4 | BRF_GRA }, // 6 + { "snk880.13a", 0x20000, 0x19dc8868, 4 | BRF_GRA }, // 7 + { "snk880.14a", 0x20000, 0x47cd498b, 4 | BRF_GRA }, // 8 + { "snk880.15a", 0x20000, 0x7a90e957, 4 | BRF_GRA }, // 9 + { "snk880.16a", 0x20000, 0xe40a6c13, 4 | BRF_GRA }, // 10 + { "snk880.17a", 0x20000, 0xc7931cc2, 4 | BRF_GRA }, // 11 + { "snk880.18a", 0x20000, 0xeed72232, 4 | BRF_GRA }, // 12 + { "snk880.19a", 0x20000, 0x1775b8dd, 4 | BRF_GRA }, // 13 + { "snk880.20a", 0x20000, 0xf8e752ec, 4 | BRF_GRA }, // 14 + { "snk880.21a", 0x20000, 0x27e9fffe, 4 | BRF_GRA }, // 15 + { "snk880.22a", 0x20000, 0xaa9c00d8, 4 | BRF_GRA }, // 16 + { "snk880.23a", 0x20000, 0xadb6ad68, 4 | BRF_GRA }, // 17 + { "snk880.24a", 0x20000, 0xdd41865a, 4 | BRF_GRA }, // 18 + { "snk880.25a", 0x20000, 0x055759ad, 4 | BRF_GRA }, // 19 + { "snk880.26a", 0x20000, 0x9bc261c5, 4 | BRF_GRA }, // 20 + + { "dg7.d20", 0x10000, 0xaba9a9d3, 5 | BRF_SND }, // 21 upd7759 samples + + { "pal20l10.a6", 0x000cc, 0xc3d9e729, 0 | BRF_OPT }, // 22 pld +}; + +STD_ROM_PICK(powj) +STD_ROM_FN(powj) + +struct BurnDriver BurnDrvpowj = { + "powj", "pow", NULL, NULL, "1988", + "Datsugoku - Prisoners of War (Japan)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, powjRomInfo, powjRomName, NULL, NULL, DrvInputInfo, PowjDIPInfo, + powInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + + +// SAR - Search And Rescue (World) + +static struct BurnRomInfo searcharRomDesc[] = { + { "bhw.2", 0x20000, 0xe1430138, 1 | BRF_PRG }, // 0 68k Code + { "bhw.3", 0x20000, 0xee1f9374, 1 | BRF_PRG }, // 1 + { "bhw.1", 0x20000, 0x62b60066, 1 | BRF_PRG }, // 2 + { "bhw.4", 0x20000, 0x16d8525c, 1 | BRF_PRG }, // 3 + + { "bh.5", 0x10000, 0x53e2fa76, 2 | BRF_PRG }, // 4 Z80 Code + + { "bh.7", 0x08000, 0xb0f1b049, 3 | BRF_GRA }, // 5 Characters + { "bh.8", 0x08000, 0x174ddba7, 3 | BRF_GRA }, // 6 + + { "bh.c1", 0x80000, 0x1fb8f0ae, 4 | BRF_GRA }, // 7 Sprites + { "bh.c3", 0x80000, 0xfd8bc407, 4 | BRF_GRA }, // 8 + { "bh.c5", 0x80000, 0x1d30acc3, 4 | BRF_GRA }, // 9 + { "bh.c2", 0x80000, 0x7c803767, 4 | BRF_GRA }, // 10 + { "bh.c4", 0x80000, 0xeede7c43, 4 | BRF_GRA }, // 11 + { "bh.c6", 0x80000, 0x9f785cd9, 4 | BRF_GRA }, // 12 + + { "bh.v1", 0x20000, 0x07a6114b, 5 | BRF_SND }, // 13 upd7759 samples +}; + +STD_ROM_PICK(searchar) +STD_ROM_FN(searchar) + +static INT32 searcharInit() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvsearchar = { + "searchar", NULL, NULL, NULL, "1989", + "SAR - Search And Rescue (World)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, searcharRomInfo, searcharRomName, NULL, NULL, IkariInputInfo, SarDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 224, 256, 3, 4 +}; + + +// SAR - Search And Rescue (US) + +static struct BurnRomInfo sercharuRomDesc[] = { + { "bh.2", 0x20000, 0xc852e2e2, 1 | BRF_PRG }, // 0 68k Code + { "bh.3", 0x20000, 0xbc04a4a1, 1 | BRF_PRG }, // 1 + { "bh.1", 0x20000, 0xba9ca70b, 1 | BRF_PRG }, // 2 + { "bh.4", 0x20000, 0xeabc5ddf, 1 | BRF_PRG }, // 3 + + { "bh.5", 0x10000, 0x53e2fa76, 2 | BRF_PRG }, // 4 Z80 Code + + { "bh.7", 0x08000, 0xb0f1b049, 3 | BRF_GRA }, // 5 Characters + { "bh.8", 0x08000, 0x174ddba7, 3 | BRF_GRA }, // 6 + + { "bh.c1", 0x80000, 0x1fb8f0ae, 4 | BRF_GRA }, // 7 Sprites + { "bh.c3", 0x80000, 0xfd8bc407, 4 | BRF_GRA }, // 8 + { "bh.c5", 0x80000, 0x1d30acc3, 4 | BRF_GRA }, // 9 + { "bh.c2", 0x80000, 0x7c803767, 4 | BRF_GRA }, // 10 + { "bh.c4", 0x80000, 0xeede7c43, 4 | BRF_GRA }, // 11 + { "bh.c6", 0x80000, 0x9f785cd9, 4 | BRF_GRA }, // 12 + + { "bh.v1", 0x20000, 0x07a6114b, 5 | BRF_SND }, // 13 upd7759 samples +}; + +STD_ROM_PICK(sercharu) +STD_ROM_FN(sercharu) + +struct BurnDriver BurnDrvsercharu = { + "searcharu", "searchar", NULL, NULL, "1989", + "SAR - Search And Rescue (US)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, sercharuRomInfo, sercharuRomName, NULL, NULL, IkariInputInfo, SarDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 224, 256, 3, 4 +}; + + +// SAR - Search And Rescue (Japan) + +static struct BurnRomInfo sercharjRomDesc[] = { + { "bh2ver3j.9c", 0x20000, 0x7ef7b172, 1 | BRF_PRG }, // 0 68k Code + { "bh3ver3j.10c",0x20000, 0x3fdea793, 1 | BRF_PRG }, // 1 + { "bhw.1", 0x20000, 0x62b60066, 1 | BRF_PRG }, // 2 + { "bhw.4", 0x20000, 0x16d8525c, 1 | BRF_PRG }, // 3 + + { "bh.5", 0x10000, 0x53e2fa76, 2 | BRF_PRG }, // 4 Z80 Code + + { "bh.7", 0x08000, 0xb0f1b049, 3 | BRF_GRA }, // 5 Characters + { "bh.8", 0x08000, 0x174ddba7, 3 | BRF_GRA }, // 6 + + { "bh.c1", 0x80000, 0x1fb8f0ae, 4 | BRF_GRA }, // 7 Sprites + { "bh.c3", 0x80000, 0xfd8bc407, 4 | BRF_GRA }, // 8 + { "bh.c5", 0x80000, 0x1d30acc3, 4 | BRF_GRA }, // 9 + { "bh.c2", 0x80000, 0x7c803767, 4 | BRF_GRA }, // 10 + { "bh.c4", 0x80000, 0xeede7c43, 4 | BRF_GRA }, // 11 + { "bh.c6", 0x80000, 0x9f785cd9, 4 | BRF_GRA }, // 12 + + { "bh.v1", 0x20000, 0x07a6114b, 5 | BRF_SND }, // 13 upd7759 samples +}; + +STD_ROM_PICK(sercharj) +STD_ROM_FN(sercharj) + +struct BurnDriver BurnDrvsercharj = { + "searcharj", "searchar", NULL, NULL, "1989", + "SAR - Search And Rescue (Japan)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, sercharjRomInfo, sercharjRomName, NULL, NULL, IkariInputInfo, SarDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 224, 256, 3, 4 +}; + + + +// Street Smart (US version 2) + +static struct BurnRomInfo streetsmRomDesc[] = { + { "s2-1ver2.14h", 0x20000, 0x655f4773, 1 | BRF_PRG }, // 0 68k Code + { "s2-2ver2.14k", 0x20000, 0xefae4823, 1 | BRF_PRG }, // 1 + + { "s2-5.16c", 0x10000, 0xca4b171e, 2 | BRF_PRG }, // 2 Z80 Code + + { "s2-9.25l", 0x08000, 0x09b6ac67, 3 | BRF_GRA }, // 3 Characters + { "s2-10.25m", 0x08000, 0x89e4ee6f, 3 | BRF_GRA }, // 4 + + { "stsmart.900", 0x80000, 0xa8279a7e, 4 | BRF_GRA }, // 5 Sprites + { "stsmart.902", 0x80000, 0x2f021aa1, 4 | BRF_GRA }, // 6 + { "stsmart.904", 0x80000, 0x167346f7, 4 | BRF_GRA }, // 7 + { "stsmart.901", 0x80000, 0xc305af12, 4 | BRF_GRA }, // 8 + { "stsmart.903", 0x80000, 0x73c16d35, 4 | BRF_GRA }, // 9 + { "stsmart.905", 0x80000, 0xa5beb4e2, 4 | BRF_GRA }, // 10 + + { "s2-6.18d", 0x20000, 0x47db1605, 5 | BRF_SND }, // 11 upd7759 samples + + { "pl20l10a.1n", 0x000cc, 0x00000000, 0 | BRF_NODUMP }, /* PAL is read protected */ +}; + +STD_ROM_PICK(streetsm) +STD_ROM_FN(streetsm) + +static INT32 streetsmInit() +{ + return DrvInit(2); +} + +struct BurnDriver BurnDrvstreetsm = { + "streetsm", NULL, NULL, NULL, "1989", + "Street Smart (US version 2)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, streetsmRomInfo, streetsmRomName, NULL, NULL, DrvInputInfo, StreetsmDIPInfo, + streetsmInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + + +// Street Smart (US version 1) + +static struct BurnRomInfo streets1RomDesc[] = { + { "s2-1ver1.9c", 0x20000, 0xb59354c5, 1 | BRF_PRG }, // 0 68k Code + { "s2-2ver1.10c", 0x20000, 0xe448b68b, 1 | BRF_PRG }, // 1 + + { "s2-5.16c", 0x10000, 0xca4b171e, 2 | BRF_PRG }, // 2 Z80 Code + + { "s2-7.15l", 0x08000, 0x22bedfe5, 3 | BRF_GRA }, // 3 Characters + { "s2-8.15m", 0x08000, 0x6a1c70ab, 3 | BRF_GRA }, // 4 + + { "stsmart.900", 0x80000, 0xa8279a7e, 4 | BRF_GRA }, // 5 Sprites + { "stsmart.902", 0x80000, 0x2f021aa1, 4 | BRF_GRA }, // 6 + { "stsmart.904", 0x80000, 0x167346f7, 4 | BRF_GRA }, // 7 + { "stsmart.901", 0x80000, 0xc305af12, 4 | BRF_GRA }, // 8 + { "stsmart.903", 0x80000, 0x73c16d35, 4 | BRF_GRA }, // 9 + { "stsmart.905", 0x80000, 0xa5beb4e2, 4 | BRF_GRA }, // 10 + + { "s2-6.18d", 0x20000, 0x47db1605, 5 | BRF_SND }, // 11 upd7759 samples +}; + +STD_ROM_PICK(streets1) +STD_ROM_FN(streets1) + +struct BurnDriver BurnDrvstreets1 = { + "streetsm1", "streetsm", NULL, NULL, "1989", + "Street Smart (US version 1)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, streets1RomInfo, streets1RomName, NULL, NULL, DrvInputInfo, StreetsmDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + + +// Street Smart (World version 1) + +static struct BurnRomInfo streetswRomDesc[] = { + { "s-smart1.bin", 0x20000, 0xa1f5ceab, 1 | BRF_PRG }, // 0 68k Code + { "s-smart2.bin", 0x20000, 0x263f615d, 1 | BRF_PRG }, // 1 + + { "s2-5.16c", 0x10000, 0xca4b171e, 2 | BRF_PRG }, // 2 Z80 Code + + { "s2-7.15l", 0x08000, 0x22bedfe5, 3 | BRF_GRA }, // 3 Characters + { "s2-8.15m", 0x08000, 0x6a1c70ab, 3 | BRF_GRA }, // 4 + + { "stsmart.900", 0x80000, 0xa8279a7e, 4 | BRF_GRA }, // 5 Sprites + { "stsmart.902", 0x80000, 0x2f021aa1, 4 | BRF_GRA }, // 6 + { "stsmart.904", 0x80000, 0x167346f7, 4 | BRF_GRA }, // 7 + { "stsmart.901", 0x80000, 0xc305af12, 4 | BRF_GRA }, // 8 + { "stsmart.903", 0x80000, 0x73c16d35, 4 | BRF_GRA }, // 9 + { "stsmart.905", 0x80000, 0xa5beb4e2, 4 | BRF_GRA }, // 10 + + { "s2-6.18d", 0x20000, 0x47db1605, 5 | BRF_SND }, // 11 upd7759 samples +}; + +STD_ROM_PICK(streetsw) +STD_ROM_FN(streetsw) + +struct BurnDriver BurnDrvstreetsw = { + "streetsmw", "streetsm", NULL, NULL, "1989", + "Street Smart (World version 1)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, streetswRomInfo, streetswRomName, NULL, NULL, DrvInputInfo, StreetsjDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + + +// Street Smart (Japan version 1) + +static struct BurnRomInfo streetsjRomDesc[] = { + { "s2v1j_01.bin", 0x20000, 0xf031413c, 1 | BRF_PRG }, // 0 68k Code + { "s2v1j_02.bin", 0x20000, 0xe403a40b, 1 | BRF_PRG }, // 1 + + { "s2-5.16c", 0x10000, 0xca4b171e, 2 | BRF_PRG }, // 2 Z80 Code + + { "s2-7.15l", 0x08000, 0x22bedfe5, 3 | BRF_GRA }, // 3 Characters + { "s2-8.15m", 0x08000, 0x6a1c70ab, 3 | BRF_GRA }, // 4 + + { "stsmart.900", 0x80000, 0xa8279a7e, 4 | BRF_GRA }, // 5 Sprites + { "stsmart.902", 0x80000, 0x2f021aa1, 4 | BRF_GRA }, // 6 + { "stsmart.904", 0x80000, 0x167346f7, 4 | BRF_GRA }, // 7 + { "stsmart.901", 0x80000, 0xc305af12, 4 | BRF_GRA }, // 8 + { "stsmart.903", 0x80000, 0x73c16d35, 4 | BRF_GRA }, // 9 + { "stsmart.905", 0x80000, 0xa5beb4e2, 4 | BRF_GRA }, // 10 + + { "s2-6.18d", 0x20000, 0x47db1605, 5 | BRF_SND }, // 11 upd7759 samples +}; + +STD_ROM_PICK(streetsj) +STD_ROM_FN(streetsj) + +struct BurnDriver BurnDrvstreetsj = { + "streetsmj", "streetsm", NULL, NULL, "1989", + "Street Smart (Japan version 1)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, streetsjRomInfo, streetsjRomName, NULL, NULL, DrvInputInfo, StreetsjDIPInfo, + searcharInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + +// Ikari III - The Rescue (8-Way Joystick) + +static struct BurnRomInfo ikari3RomDesc[] = { + { "ik3-2-ver1.c10", 0x20000, 0x1bae8023, 1 | BRF_PRG }, // 0 68k Code + { "ik3-3-ver1.c9", 0x20000, 0x10e38b66, 1 | BRF_PRG }, // 1 + { "ik3-1.c8", 0x10000, 0x47e4d256, 1 | BRF_PRG }, // 2 + { "ik3-4.c12", 0x10000, 0xa43af6b5, 1 | BRF_PRG }, // 3 + + { "ik3-5.bin", 0x10000, 0xce6706fc, 2 | BRF_PRG }, // 4 Z80 Code + + { "ik3-7.bin", 0x08000, 0x0b4804df, 3 | BRF_GRA }, // 5 Characters + { "ik3-8.bin", 0x08000, 0x10ab4e50, 3 | BRF_GRA }, // 6 + + { "ik3-13.bin", 0x20000, 0x9a56bd32, 4 | BRF_GRA }, // 7 Sprites + { "ik3-12.bin", 0x20000, 0x0ce6a10a, 4 | BRF_GRA }, // 8 + { "ik3-11.bin", 0x20000, 0xe4e2be43, 4 | BRF_GRA }, // 9 + { "ik3-10.bin", 0x20000, 0xac222372, 4 | BRF_GRA }, // 10 + { "ik3-9.bin", 0x20000, 0xc33971c2, 4 | BRF_GRA }, // 11 + { "ik3-14.bin", 0x20000, 0x453bea77, 4 | BRF_GRA }, // 12 + { "ik3-15.bin", 0x20000, 0x781a81fc, 4 | BRF_GRA }, // 13 + { "ik3-16.bin", 0x20000, 0x80ba400b, 4 | BRF_GRA }, // 14 + { "ik3-17.bin", 0x20000, 0x0cc3ce4a, 4 | BRF_GRA }, // 15 + { "ik3-18.bin", 0x20000, 0xba106245, 4 | BRF_GRA }, // 16 + { "ik3-23.bin", 0x20000, 0xd0fd5c77, 4 | BRF_GRA }, // 17 + { "ik3-22.bin", 0x20000, 0x4878d883, 4 | BRF_GRA }, // 18 + { "ik3-21.bin", 0x20000, 0x50d0fbf0, 4 | BRF_GRA }, // 19 + { "ik3-20.bin", 0x20000, 0x9a851efc, 4 | BRF_GRA }, // 20 + { "ik3-19.bin", 0x20000, 0x4ebdba89, 4 | BRF_GRA }, // 21 + { "ik3-24.bin", 0x20000, 0xe9b26d68, 4 | BRF_GRA }, // 22 + { "ik3-25.bin", 0x20000, 0x073b03f1, 4 | BRF_GRA }, // 23 + { "ik3-26.bin", 0x20000, 0x9c613561, 4 | BRF_GRA }, // 24 + { "ik3-27.bin", 0x20000, 0x16dd227e, 4 | BRF_GRA }, // 25 + { "ik3-28.bin", 0x20000, 0x711715ae, 4 | BRF_GRA }, // 26 + + { "ik3-6.bin", 0x20000, 0x59d256a4, 5 | BRF_SND }, // 27 upd7759 samples +}; + +STD_ROM_PICK(ikari3) +STD_ROM_FN(ikari3) + +static INT32 ikari3Init() +{ + return DrvInit(3); +} + +struct BurnDriver BurnDrvikari3 = { + "ikari3", NULL, NULL, NULL, "1989", + "Ikari III - The Rescue (8-Way Joystick)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, ikari3RomInfo, ikari3RomName, NULL, NULL, IkariInputInfo, IkariDIPInfo, + ikari3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + +// Ikari III - The Rescue (US, Rotary Joystick) + +static struct BurnRomInfo ikari3uRomDesc[] = { + { "ik3-2.c10", 0x20000, 0xa7b34dcd, 1 | BRF_PRG }, // 0 68k Code + { "ik3-3.c9", 0x20000, 0x50f2b83d, 1 | BRF_PRG }, // 1 + { "ik3-1.c8", 0x10000, 0x47e4d256, 1 | BRF_PRG }, // 2 + { "ik3-4.c12", 0x10000, 0xa43af6b5, 1 | BRF_PRG }, // 3 + + { "ik3-5.bin", 0x10000, 0xce6706fc, 2 | BRF_PRG }, // 4 Z80 Code + + { "ik3-7.bin", 0x08000, 0x0b4804df, 3 | BRF_GRA }, // 5 Characters + { "ik3-8.bin", 0x08000, 0x10ab4e50, 3 | BRF_GRA }, // 6 + + { "ik3-13.bin", 0x20000, 0x9a56bd32, 4 | BRF_GRA }, // 7 Sprites + { "ik3-12.bin", 0x20000, 0x0ce6a10a, 4 | BRF_GRA }, // 8 + { "ik3-11.bin", 0x20000, 0xe4e2be43, 4 | BRF_GRA }, // 9 + { "ik3-10.bin", 0x20000, 0xac222372, 4 | BRF_GRA }, // 10 + { "ik3-9.bin", 0x20000, 0xc33971c2, 4 | BRF_GRA }, // 11 + { "ik3-14.bin", 0x20000, 0x453bea77, 4 | BRF_GRA }, // 12 + { "ik3-15.bin", 0x20000, 0x781a81fc, 4 | BRF_GRA }, // 13 + { "ik3-16.bin", 0x20000, 0x80ba400b, 4 | BRF_GRA }, // 14 + { "ik3-17.bin", 0x20000, 0x0cc3ce4a, 4 | BRF_GRA }, // 15 + { "ik3-18.bin", 0x20000, 0xba106245, 4 | BRF_GRA }, // 16 + { "ik3-23.bin", 0x20000, 0xd0fd5c77, 4 | BRF_GRA }, // 17 + { "ik3-22.bin", 0x20000, 0x4878d883, 4 | BRF_GRA }, // 18 + { "ik3-21.bin", 0x20000, 0x50d0fbf0, 4 | BRF_GRA }, // 19 + { "ik3-20.bin", 0x20000, 0x9a851efc, 4 | BRF_GRA }, // 20 + { "ik3-19.bin", 0x20000, 0x4ebdba89, 4 | BRF_GRA }, // 21 + { "ik3-24.bin", 0x20000, 0xe9b26d68, 4 | BRF_GRA }, // 22 + { "ik3-25.bin", 0x20000, 0x073b03f1, 4 | BRF_GRA }, // 23 + { "ik3-26.bin", 0x20000, 0x9c613561, 4 | BRF_GRA }, // 24 + { "ik3-27.bin", 0x20000, 0x16dd227e, 4 | BRF_GRA }, // 25 + { "ik3-28.bin", 0x20000, 0x711715ae, 4 | BRF_GRA }, // 26 + + { "ik3-6.bin", 0x20000, 0x59d256a4, 5 | BRF_SND }, // 27 upd7759 samples +}; + +STD_ROM_PICK(ikari3u) +STD_ROM_FN(ikari3u) + +struct BurnDriver BurnDrvikari3u = { + "ikari3u", "ikari3", NULL, NULL, "1989", + "Ikari III - The Rescue (US, Rotary Joystick)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, ikari3uRomInfo, ikari3uRomName, NULL, NULL, IkariInputInfo, IkariDIPInfo, + ikari3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; + +// Ikari Three - The Rescue (Japan, Rotary Joystick) + +static struct BurnRomInfo ikari3jRomDesc[] = { + { "ik3-2-j.c10", 0x20000, 0x7b1b4be4, 1 | BRF_PRG }, // 0 68k Code + { "ik3-3-j.c9", 0x20000, 0x8e6e2aa9, 1 | BRF_PRG }, // 1 + { "ik3-1.c8", 0x10000, 0x47e4d256, 1 | BRF_PRG }, // 2 + { "ik3-4.c12", 0x10000, 0xa43af6b5, 1 | BRF_PRG }, // 3 + + { "ik3-5.bin", 0x10000, 0xce6706fc, 2 | BRF_PRG }, // 4 Z80 Code + + { "ik3-7.bin", 0x08000, 0x0b4804df, 3 | BRF_GRA }, // 5 Characters + { "ik3-8.bin", 0x08000, 0x10ab4e50, 3 | BRF_GRA }, // 6 + + { "ik3-13.bin", 0x20000, 0x9a56bd32, 4 | BRF_GRA }, // 7 Sprites + { "ik3-12.bin", 0x20000, 0x0ce6a10a, 4 | BRF_GRA }, // 8 + { "ik3-11.bin", 0x20000, 0xe4e2be43, 4 | BRF_GRA }, // 9 + { "ik3-10.bin", 0x20000, 0xac222372, 4 | BRF_GRA }, // 10 + { "ik3-9.bin", 0x20000, 0xc33971c2, 4 | BRF_GRA }, // 11 + { "ik3-14.bin", 0x20000, 0x453bea77, 4 | BRF_GRA }, // 12 + { "ik3-15.bin", 0x20000, 0x781a81fc, 4 | BRF_GRA }, // 13 + { "ik3-16.bin", 0x20000, 0x80ba400b, 4 | BRF_GRA }, // 14 + { "ik3-17.bin", 0x20000, 0x0cc3ce4a, 4 | BRF_GRA }, // 15 + { "ik3-18.bin", 0x20000, 0xba106245, 4 | BRF_GRA }, // 16 + { "ik3-23.bin", 0x20000, 0xd0fd5c77, 4 | BRF_GRA }, // 17 + { "ik3-22.bin", 0x20000, 0x4878d883, 4 | BRF_GRA }, // 18 + { "ik3-21.bin", 0x20000, 0x50d0fbf0, 4 | BRF_GRA }, // 19 + { "ik3-20.bin", 0x20000, 0x9a851efc, 4 | BRF_GRA }, // 20 + { "ik3-19.bin", 0x20000, 0x4ebdba89, 4 | BRF_GRA }, // 21 + { "ik3-24.bin", 0x20000, 0xe9b26d68, 4 | BRF_GRA }, // 22 + { "ik3-25.bin", 0x20000, 0x073b03f1, 4 | BRF_GRA }, // 23 + { "ik3-26.bin", 0x20000, 0x9c613561, 4 | BRF_GRA }, // 24 + { "ik3-27.bin", 0x20000, 0x16dd227e, 4 | BRF_GRA }, // 25 + { "ik3-28.bin", 0x20000, 0x711715ae, 4 | BRF_GRA }, // 26 + + { "ik3-6.bin", 0x20000, 0x59d256a4, 5 | BRF_SND }, // 27 upd7759 samples +}; + +STD_ROM_PICK(ikari3j) +STD_ROM_FN(ikari3j) + +struct BurnDriver BurnDrvikari3j = { + "ikari3j", "ikari3", NULL, NULL, "1989", + "Ikari Three - The Rescue (Japan, Rotary Joystick)\0", NULL, "SNK", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, ikari3jRomInfo, ikari3jRomName, NULL, NULL, IkariInputInfo, IkariDIPInfo, + ikari3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x800, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_solomon.cpp b/src/burn/drivers/misc_pre90s/d_solomon.cpp new file mode 100644 index 00000000..f8190900 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_solomon.cpp @@ -0,0 +1,817 @@ +#include "tiles_generic.h" + +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static UINT8 SolomonInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 SolomonInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 SolomonInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 SolomonDip[2] = {0, 0}; +static UINT8 SolomonInput[3] = {0x00, 0x00, 0x00}; +static UINT8 SolomonReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *SolomonZ80Rom1 = NULL; +static UINT8 *SolomonZ80Rom2 = NULL; +static UINT8 *SolomonZ80Ram1 = NULL; +static UINT8 *SolomonZ80Ram2 = NULL; +static UINT8 *SolomonColourRam = NULL; +static UINT8 *SolomonVideoRam = NULL; +static UINT8 *SolomonBgColourRam = NULL; +static UINT8 *SolomonBgVideoRam = NULL; +static UINT8 *SolomonSpriteRam = NULL; +static UINT8 *SolomonPaletteRam = NULL; +static UINT32 *SolomonPalette = NULL; +static UINT8 *SolomonBgTiles = NULL; +static UINT8 *SolomonFgTiles = NULL; +static UINT8 *SolomonSprites = NULL; +static UINT8 *SolomonTempRom = NULL; + +static INT32 SolomonIrqFire = 0; + +static INT32 SolomonFlipScreen = 0; + +static INT32 SolomonSoundLatch = 0; +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[9]; + + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo SolomonInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , SolomonInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , SolomonInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , SolomonInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , SolomonInputPort2 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , SolomonInputPort0 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , SolomonInputPort0 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , SolomonInputPort0 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , SolomonInputPort0 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , SolomonInputPort0 + 5, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , SolomonInputPort0 + 4, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 2, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 3, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 5, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , SolomonInputPort1 + 4, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &SolomonReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, SolomonDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, SolomonDip + 1 , "dip" }, +}; + +STDINPUTINFO(Solomon) + +inline void SolomonClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline void SolomonMakeInputs() +{ + // Reset Inputs + SolomonInput[0] = SolomonInput[1] = SolomonInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + SolomonInput[0] |= (SolomonInputPort0[i] & 1) << i; + SolomonInput[1] |= (SolomonInputPort1[i] & 1) << i; + SolomonInput[2] |= (SolomonInputPort2[i] & 1) << i; + } + + // Clear Opposites + SolomonClearOpposites(&SolomonInput[0]); + SolomonClearOpposites(&SolomonInput[1]); +} + +static struct BurnDIPInfo SolomonDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x02, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x02, 0x02, "Upright" }, + {0x11, 0x01, 0x02, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x0c, "2" }, + {0x11, 0x01, 0x0c, 0x00, "3" }, + {0x11, 0x01, 0x0c, 0x08, "4" }, + {0x11, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0xc0, 0x80, "2 Coins 1 Play" }, + {0x11, 0x01, 0xc0, 0x00, "1 Coin 1 Play" }, + {0x11, 0x01, 0xc0, 0x40, "1 Coin 2 Play" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 3 Play" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0x30, 0x20, "2 Coins 1 Play" }, + {0x11, 0x01, 0x30, 0x00, "1 Coin 1 Play" }, + {0x11, 0x01, 0x30, 0x10, "1 Coin 2 Play" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 3 Play" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x00, "Normal" }, + {0x12, 0x01, 0x03, 0x01, "Harder" }, + {0x12, 0x01, 0x03, 0x03, "Difficult" }, + + {0 , 0xfe, 0 , 4 , "Timer Speed" }, + {0x12, 0x01, 0x0c, 0x08, "Slow" }, + {0x12, 0x01, 0x0c, 0x00, "Normal" }, + {0x12, 0x01, 0x0c, 0x04, "Faster" }, + {0x12, 0x01, 0x0c, 0x0c, "Fastest" }, + + {0 , 0xfe, 0 , 2 , "Extra" }, + {0x12, 0x01, 0x10, 0x00, "Normal" }, + {0x12, 0x01, 0x10, 0x10, "Difficult" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x12, 0x01, 0xe0, 0x00, "30k 200k 500k" }, + {0x12, 0x01, 0xe0, 0x80, "100k 300k 800k" }, + {0x12, 0x01, 0xe0, 0x40, "30k 200k" }, + {0x12, 0x01, 0xe0, 0xc0, "100k 300k" }, + {0x12, 0x01, 0xe0, 0x20, "30k" }, + {0x12, 0x01, 0xe0, 0xa0, "100k" }, + {0x12, 0x01, 0xe0, 0x60, "200k" }, + {0x12, 0x01, 0xe0, 0xe0, "None" }, +}; + +STDDIPINFO(Solomon) + +static struct BurnRomInfo SolomonRomDesc[] = { + { "6.3f", 0x04000, 0x645eb0f3, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "7.3h", 0x08000, 0x1bf5c482, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "8.3jk", 0x08000, 0x0a6cdefc, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "1.3jk", 0x04000, 0xfa6e562e, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "12.3t", 0x08000, 0xb371291c, BRF_GRA }, // 4 Characters + { "11.3r", 0x08000, 0x6f94d2af, BRF_GRA }, // 5 Characters + { "10.3p", 0x08000, 0x8310c2a1, BRF_GRA }, // 6 Characters + { "9.3m", 0x08000, 0xab7e6c42, BRF_GRA }, // 7 Characters + { "2.5lm", 0x04000, 0x80fa2be3, BRF_GRA }, // 8 Sprites + { "3.6lm", 0x04000, 0x236106b4, BRF_GRA }, // 9 Sprites + { "4.7lm", 0x04000, 0x088fe5d9, BRF_GRA }, // 10 Sprites + { "5.8lm", 0x04000, 0x8366232a, BRF_GRA }, // 11 Sprites +}; + + +STD_ROM_PICK(Solomon) +STD_ROM_FN(Solomon) + +static struct BurnRomInfo SolomonjRomDesc[] = { + { "slmn_06.bin", 0x04000, 0xe4d421ff, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "slmn_07.bin", 0x08000, 0xd52d7e38, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "slmn_08.bin", 0x01000, 0xb924d162, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "slmn_01.bin", 0x04000, 0xfa6e562e, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "slmn_12.bin", 0x08000, 0xaa26dfcb, BRF_GRA }, // 4 Characters + { "slmn_11.bin", 0x08000, 0x6f94d2af, BRF_GRA }, // 5 Characters + { "slmn_10.bin", 0x08000, 0x8310c2a1, BRF_GRA }, // 6 Characters + { "slmn_09.bin", 0x08000, 0xab7e6c42, BRF_GRA }, // 7 Characters + { "slmn_02.bin", 0x04000, 0x80fa2be3, BRF_GRA }, // 8 Sprites + { "slmn_03.bin", 0x04000, 0x236106b4, BRF_GRA }, // 9 Sprites + { "slmn_04.bin", 0x04000, 0x088fe5d9, BRF_GRA }, // 10 Sprites + { "slmn_05.bin", 0x04000, 0x8366232a, BRF_GRA }, // 11 Sprites +}; + + +STD_ROM_PICK(Solomonj) +STD_ROM_FN(Solomonj) + +INT32 SolomonDoReset() +{ + SolomonIrqFire = 0; + SolomonFlipScreen = 0; + SolomonSoundLatch = 0; + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + for (INT32 i = 0; i < 3; i++) { + AY8910Reset(i); + } + + return 0; +} + +UINT8 __fastcall SolomonRead1(UINT16 a) +{ + switch (a) { + case 0xe600: { + return SolomonInput[0]; + } + + case 0xe601: { + return SolomonInput[1]; + } + + case 0xe602: { + return SolomonInput[2]; + } + + case 0xe604: { + return SolomonDip[0]; + } + + case 0xe605: { + return SolomonDip[1]; + } + } + + return 0; +} + +void __fastcall SolomonWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe600: { + SolomonIrqFire = d; + return; + } + + case 0xe604: { + SolomonFlipScreen = d & 1; + return; + } + + case 0xe800: { + SolomonSoundLatch = d; + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + } +} + +UINT8 __fastcall SolomonRead2(UINT16 a) +{ + switch (a) { + case 0x8000: { + return SolomonSoundLatch; + } + } + + return 0; +} + +void __fastcall SolomonPortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x10: { + AY8910Write(0, 0, d); + return; + } + + case 0x11: { + AY8910Write(0, 1, d); + return; + } + + case 0x20: { + AY8910Write(1, 0, d); + return; + } + + case 0x21: { + AY8910Write(1, 1, d); + return; + } + + case 0x30: { + AY8910Write(2, 0, d); + return; + } + + case 0x31: { + AY8910Write(2, 1, d); + return; + } + } +} + +static INT32 SolomonMemIndex() +{ + UINT8 *Next; Next = Mem; + + SolomonZ80Rom1 = Next; Next += 0x10000; + SolomonZ80Rom2 = Next; Next += 0x04000; + + RamStart = Next; + + SolomonZ80Ram1 = Next; Next += 0x01000; + SolomonZ80Ram2 = Next; Next += 0x00800; + SolomonColourRam = Next; Next += 0x00400; + SolomonVideoRam = Next; Next += 0x00400; + SolomonBgColourRam = Next; Next += 0x00400; + SolomonBgVideoRam = Next; Next += 0x00400; + SolomonSpriteRam = Next; Next += 0x00080; + SolomonPaletteRam = Next; Next += 0x00200; + + RamEnd = Next; + + SolomonBgTiles = Next; Next += 2048 * 8 * 8; + SolomonFgTiles = Next; Next += 2048 * 8 * 8; + SolomonSprites = Next; Next += 2048 * 8 * 8; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 9 * sizeof(INT16); + SolomonPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 TileYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 0, 131072, 262144, 393216 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + +INT32 SolomonInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + SolomonMemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + SolomonMemIndex(); + + SolomonTempRom = (UINT8 *)BurnMalloc(0x10000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(SolomonZ80Rom1, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom, 1, 1); if (nRet != 0) return 1; + memcpy(SolomonZ80Rom1 + 0x4000, SolomonTempRom + 0x4000, 0x4000); + memcpy(SolomonZ80Rom1 + 0x8000, SolomonTempRom + 0x0000, 0x4000); + memset(SolomonTempRom, 0, 0x10000); + nRet = BurnLoadRom(SolomonTempRom, 2, 1); if (nRet != 0) return 1; + memcpy(SolomonZ80Rom1 + 0xf000, SolomonTempRom, 0x1000); + + // Load Z80 #2 Program Rom + nRet = BurnLoadRom(SolomonZ80Rom2, 3, 1); if (nRet != 0) return 1; + + // Load and decode Bg Tiles + memset(SolomonTempRom, 0, 0x10000); + nRet = BurnLoadRom(SolomonTempRom + 0x0000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom + 0x8000, 7, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, SolomonTempRom, SolomonBgTiles); + + // Load and decode Fg Tiles + memset(SolomonTempRom, 0, 0x10000); + nRet = BurnLoadRom(SolomonTempRom + 0x0000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom + 0x8000, 5, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x100, SolomonTempRom, SolomonFgTiles); + + // Load and decode Sprite Tiles + memset(SolomonTempRom, 0, 0x10000); + nRet = BurnLoadRom(SolomonTempRom + 0x0000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom + 0x4000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom + 0x8000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(SolomonTempRom + 0xc000, 11, 1); if (nRet != 0) return 1; +// SolomonDecodeSprites(SolomonSprites, 2048, 0x0000, 0x4000, 0x8000, 0xc000); + GfxDecode(512, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, SolomonTempRom, SolomonSprites); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(SolomonRead1); + ZetSetWriteHandler(SolomonWrite1); + ZetMapArea(0x0000, 0xbfff, 0, SolomonZ80Rom1 ); + ZetMapArea(0x0000, 0xbfff, 2, SolomonZ80Rom1 ); + ZetMapArea(0xc000, 0xcfff, 0, SolomonZ80Ram1 ); + ZetMapArea(0xc000, 0xcfff, 1, SolomonZ80Ram1 ); + ZetMapArea(0xc000, 0xcfff, 2, SolomonZ80Ram1 ); + ZetMapArea(0xd000, 0xd3ff, 0, SolomonColourRam ); + ZetMapArea(0xd000, 0xd3ff, 1, SolomonColourRam ); + ZetMapArea(0xd000, 0xd3ff, 2, SolomonColourRam ); + ZetMapArea(0xd400, 0xd7ff, 0, SolomonVideoRam ); + ZetMapArea(0xd400, 0xd7ff, 1, SolomonVideoRam ); + ZetMapArea(0xd400, 0xd7ff, 2, SolomonVideoRam ); + ZetMapArea(0xd800, 0xdbff, 0, SolomonBgColourRam ); + ZetMapArea(0xd800, 0xdbff, 1, SolomonBgColourRam ); + ZetMapArea(0xd800, 0xdbff, 2, SolomonBgColourRam ); + ZetMapArea(0xdc00, 0xdfff, 0, SolomonBgVideoRam ); + ZetMapArea(0xdc00, 0xdfff, 1, SolomonBgVideoRam ); + ZetMapArea(0xdc00, 0xdfff, 2, SolomonBgVideoRam ); + ZetMapArea(0xe000, 0xe07f, 0, SolomonSpriteRam ); + ZetMapArea(0xe000, 0xe07f, 1, SolomonSpriteRam ); + ZetMapArea(0xe000, 0xe07f, 2, SolomonSpriteRam ); + ZetMapArea(0xe400, 0xe5ff, 0, SolomonPaletteRam ); + ZetMapArea(0xe400, 0xe5ff, 1, SolomonPaletteRam ); + ZetMapArea(0xe400, 0xe5ff, 2, SolomonPaletteRam ); + ZetMapArea(0xf000, 0xffff, 0, SolomonZ80Rom1 + 0xf000); + ZetMapArea(0xf000, 0xffff, 2, SolomonZ80Rom1 + 0xf000); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(SolomonRead2); + ZetSetOutHandler(SolomonPortWrite2); + ZetMapArea(0x0000, 0x3fff, 0, SolomonZ80Rom2 ); + ZetMapArea(0x0000, 0x3fff, 2, SolomonZ80Rom2 ); + ZetMapArea(0x4000, 0x47ff, 0, SolomonZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 1, SolomonZ80Ram2 ); + ZetMapArea(0x4000, 0x47ff, 2, SolomonZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnFree(SolomonTempRom); + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + pAY8910Buffer[6] = pFMBuffer + nBurnSoundLen * 6; + pAY8910Buffer[7] = pFMBuffer + nBurnSoundLen * 7; + pAY8910Buffer[8] = pFMBuffer + nBurnSoundLen * 8; + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(2, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + // Reset the driver + SolomonDoReset(); + + return 0; +} + +INT32 SolomonExit() +{ + ZetExit(); + + for (INT32 i = 0; i < 3; i++) { + AY8910Exit(i); + } + + GenericTilesExit(); + + BurnFree(Mem); + + return 0; +} + +void SolomonRenderBgLayer() +{ + for (INT32 Offs = 0; Offs < 0x400; Offs++) { + INT32 sx, sy, Attr, Code, Colour, FlipX, FlipY; + + sx = (Offs % 32); + sy = (Offs / 32); + Attr = SolomonBgColourRam[Offs]; + Code = SolomonBgVideoRam[Offs] + 256 * (Attr & 0x07); + Colour = (Attr & 0x70) >> 4; + FlipX = Attr & 0x80; + FlipY = Attr & 0x08; + + if (SolomonFlipScreen) { + sx = 31 - sx; + sy = 31 - sy; + FlipX = !FlipX; + FlipY = !FlipY; + } + + sx *= 8; + sy *= 8; + sy -= 16; + + if (sx >= 0 && sx < 247 && sy >= 0 && sy < 215) { + if (!FlipY) { + if (!FlipX) { + Render8x8Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } + } else { + if (!FlipX) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } else { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } + } else { + if (!FlipX) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 128, SolomonBgTiles); + } + } + } + } +} + +void SolomonRenderFgLayer() +{ + for (INT32 Offs = 0x400 - 1; Offs >= 0; Offs--) { + INT32 sx, sy, Code, Colour; + + sx = (Offs % 32); + sy = (Offs / 32); + Code = SolomonVideoRam[Offs] + 256 * (SolomonColourRam[Offs] & 0x07); + Colour = (SolomonColourRam[Offs] & 0x70) >> 4; + + if (SolomonFlipScreen) { + sx = 31 - sx; + sy = 31 - sy; + } + + sx *= 8; + sy *= 8; + sy -= 16; + + if (sx >= 0 && sx < 247 && sy >= 0 && sy < 215) { + if (!SolomonFlipScreen) { + Render8x8Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonFgTiles); + } else { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonFgTiles); + } + } else { + if (!SolomonFlipScreen) { + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonFgTiles); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonFgTiles); + } + } + } +} + +void SolomonRenderSpriteLayer() +{ + for (INT32 Offs = 0x80 - 4; Offs >= 0; Offs -= 4) { + INT32 sx, sy, Attr, Code, Colour, FlipX, FlipY; + + sx = SolomonSpriteRam[Offs + 3]; + sy = 241 - SolomonSpriteRam[Offs + 2]; + Attr = SolomonSpriteRam[Offs + 1]; + Code = SolomonSpriteRam[Offs] + 16 * (Attr & 0x10); + Colour = (Attr & 0x0e) >> 1; + FlipX = Attr & 0x40; + FlipY = Attr & 0x80; + + if (SolomonFlipScreen & 1) { + sx = 240 - sx; + sy = 240 - sy; + FlipX = !FlipX; + FlipY = !FlipY; + } + + sy -= 16; + + if (sx >= 0 && sx < 239 && sy >= 0 && sy < 207) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, SolomonSprites); + } + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 0) & 0x0f; + g = (nColour >> 4) & 0x0f; + b = (nColour >> 8) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +INT32 SolomonCalcPalette() +{ + for (INT32 i = 0; i < 0x200; i++) { + SolomonPalette[i / 2] = CalcCol(SolomonPaletteRam[i & ~1] | (SolomonPaletteRam[i | 1] << 8)); + } + + return 0; +} + +void SolomonDraw() +{ + BurnTransferClear(); + SolomonCalcPalette(); + SolomonRenderBgLayer(); + SolomonRenderFgLayer(); + SolomonRenderSpriteLayer(); + BurnTransferCopy(SolomonPalette); +} + +INT32 SolomonFrame() +{ + INT32 nInterleave = 2; + INT32 nSoundBufferPos = 0; + + if (SolomonReset) SolomonDoReset(); + + SolomonMakeInputs(); + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 3072000 / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == 1) if(SolomonIrqFire) ZetNmi(); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + ZetRaiseIrq(0); + ZetClose(); + + // Render Sound Segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + AY8910Update(2, &pAY8910Buffer[6], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + nSample += pAY8910Buffer[6][n] >> 2; + nSample += pAY8910Buffer[7][n] >> 2; + nSample += pAY8910Buffer[8][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + + if (pBurnDraw) SolomonDraw(); + + return 0; +} + +static INT32 SolomonScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x02945; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + + // Scan critical driver variables + SCAN_VAR(SolomonIrqFire); + SCAN_VAR(SolomonFlipScreen); + SCAN_VAR(SolomonSoundLatch); + SCAN_VAR(SolomonInput); + SCAN_VAR(SolomonDip); + } + + return 0; +} + +struct BurnDriver BurnDrvSolomon = { + "solomon", NULL, NULL, NULL, "1986", + "Solomon's Key (US)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, SolomonRomInfo, SolomonRomName, NULL, NULL, SolomonInputInfo, SolomonDIPInfo, + SolomonInit, SolomonExit, SolomonFrame, NULL, SolomonScan, + NULL, 0x200, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSolomonj = { + "solomonj", "solomon", NULL, NULL, "1986", + "Solomon's Key (Japan)\0", NULL, "Tecmo", "Miscellaneous", + L"Solomon's Key (Japan)\0Solomon's Key \u30BD\u30ED\u30E2\u30F3\u306E\u9375\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PUZZLE, 0, + NULL, SolomonjRomInfo, SolomonjRomName, NULL, NULL, SolomonInputInfo, SolomonDIPInfo, + SolomonInit, SolomonExit, SolomonFrame, NULL, SolomonScan, + NULL, 0x200, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_sonson.cpp b/src/burn/drivers/misc_pre90s/d_sonson.cpp new file mode 100644 index 00000000..fcf3b787 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_sonson.cpp @@ -0,0 +1,768 @@ +// FB Alpha Son Son driver module +// Based on MAME driver by Mirko Buffoni + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvM6809ROM0; +static UINT8 *DrvM6809ROM1; +static UINT8 *DrvM6809RAM0; +static UINT8 *DrvM6809RAM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvColPROM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvColRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvScrollX; +static UINT32 *DrvPalette; +static UINT32 *Palette; +static UINT8 DrvRecalc; + +static INT16 *pAY8910Buffer[6]; +static INT16 *pFMBuffer; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvInps[3]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static UINT8 soundlatch; +static UINT8 flipscreen; + +static UINT8 DrvSoundTrigger; +static UINT8 DrvSoundIrqTrigger; + +static INT32 sonsonj; + +static struct BurnInputInfo SonsonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 4, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 5, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 1" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p2 fire 1" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Sonson) + +static struct BurnDIPInfo SonsonDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xdf, NULL }, + {0x10, 0xff, 0xff, 0xeb, NULL }, + + {0 , 0xfe, 0 , 16, "Coinage" }, + {0x0f, 0x01, 0x0f, 0x02, "4C_1C" }, + {0x0f, 0x01, 0x0f, 0x05, "3C_1C" }, + {0x0f, 0x01, 0x0f, 0x08, "2C_1C" }, + {0x0f, 0x01, 0x0f, 0x04, "3C_2C" }, + {0x0f, 0x01, 0x0f, 0x01, "4C_3C" }, + {0x0f, 0x01, 0x0f, 0x0f, "1C_1C" }, + {0x0f, 0x01, 0x0f, 0x03, "3C_4C" }, + {0x0f, 0x01, 0x0f, 0x07, "2C_3C" }, + {0x0f, 0x01, 0x0f, 0x0e, "1C_2C" }, + {0x0f, 0x01, 0x0f, 0x06, "2C_5C" }, + {0x0f, 0x01, 0x0f, 0x0d, "1C_3C" }, + {0x0f, 0x01, 0x0f, 0x0c, "1C_4C" }, + {0x0f, 0x01, 0x0f, 0x0b, "1C_5C" }, + {0x0f, 0x01, 0x0f, 0x0a, "1C_6C" }, + {0x0f, 0x01, 0x0f, 0x09, "1C_7C" }, + {0x0f, 0x01, 0x0f, 0x00, "Free_Play" }, + + {0 , 0xfe, 0 , 2, "Coinage affects" }, + {0x0f, 0x01, 0x10, 0x10, "Coin A" }, + {0x0f, 0x01, 0x10, 0x00, "Coin B" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x0f, 0x01, 0x20, 0x20, "Off" }, + {0x0f, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x10, 0x01, 0x03, 0x03, "3" }, + {0x10, 0x01, 0x03, 0x02, "4" }, + {0x10, 0x01, 0x03, 0x01, "5" }, + {0x10, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "2 Players Game" }, + {0x10, 0x01, 0x04, 0x04, "1 Credit" }, + {0x10, 0x01, 0x04, 0x00, "2 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus_Life" }, + {0x10, 0x01, 0x18, 0x08, "20000 80000 100000" }, + {0x10, 0x01, 0x18, 0x00, "30000 90000 120000" }, + {0x10, 0x01, 0x18, 0x18, "20000" }, + {0x10, 0x01, 0x18, 0x10, "30000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x10, 0x01, 0x60, 0x60, "Easy" }, + {0x10, 0x01, 0x60, 0x40, "Medium" }, + {0x10, 0x01, 0x60, 0x20, "Hard" }, + {0x10, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Freeze" }, + {0x10, 0x01, 0x80, 0x80, "Off" }, + {0x10, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Sonson) + +static void sonson_sound_irqtrigger(UINT8 data) +{ + data &= 1; + + if (DrvSoundTrigger == 0 && data == 1) + { + DrvSoundIrqTrigger = 1; + } + + DrvSoundTrigger = data; +} + +void sonson_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x3000: + for (INT32 i = 5; i < 32; i++) { + DrvScrollX[i] = data; + } + return; + + case 0x3008: + return; + + case 0x3010: + soundlatch = data; + return; + + case 0x3018: + flipscreen = ~data & 1; + return; + + case 0x3019: + sonson_sound_irqtrigger(data); + return; + } +} + +UINT8 sonson_main_read(UINT16 address) +{ + switch (address) + { + case 0x3002: + case 0x3003: + case 0x3004: + return DrvInps[address - 0x3002]; + + case 0x3005: + case 0x3006: + return DrvDips[address - 0x3005]; + } + + return 0; +} + +void sonson_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x2000: + AY8910Write(0, 0, data); + return; + + case 0x2001: + AY8910Write(0, 1, data); + return; + + case 0x4000: + AY8910Write(1, 0, data); + return; + + case 0x4001: + AY8910Write(1, 1, data); + return; + } +} + +UINT8 sonson_sound_read(UINT16 address) +{ + switch (address) + { + case 0xa000: + return soundlatch; + } + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[2] = { 0x10000, 0x00000 }; + INT32 Plane1[3] = { 0x40000, 0x20000, 0x00000 }; + INT32 XOffs0[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + INT32 XOffs[16] = { 8*16+7, 8*16+6, 8*16+5, 8*16+4, 8*16+3, 8*16+2, 8*16+1, 8*16+0, 7, 6, 5, 4, 3, 2, 1, 0 }; + INT32 YOffs[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0xC000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x4000); + + GfxDecode(0x400, 2, 8, 8, Plane0, XOffs0, YOffs, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0xc000); + + GfxDecode(0x200, 3, 16, 16, Plane1, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvPaletteInit() +{ + UINT32 *tmp = (UINT32*)BurnMalloc(0x20 * sizeof (UINT32)); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x20; i++) + { + INT32 bit0, bit1, bit2, bit3; + INT32 r, g, b; + + bit0 = (DrvColPROM[i + 0x100] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x100] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x100] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x100] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 0x000] >> 4) & 0x01; + bit1 = (DrvColPROM[i + 0x000] >> 5) & 0x01; + bit2 = (DrvColPROM[i + 0x000] >> 6) & 0x01; + bit3 = (DrvColPROM[i + 0x000] >> 7) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (DrvColPROM[i + 0x000] >> 0) & 0x01; + bit1 = (DrvColPROM[i + 0x000] >> 1) & 0x01; + bit2 = (DrvColPROM[i + 0x000] >> 2) & 0x01; + bit3 = (DrvColPROM[i + 0x000] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + tmp[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 0x200; i++) { + Palette[i] = tmp[(DrvColPROM[0x200 + i] & 0x0f) | ((i >> 4) & 0x10)]; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM0 = Next; Next += 0x010000; + DrvM6809ROM1 = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x010000; + DrvGfxROM1 = Next; Next += 0x020000; + + DrvColPROM = Next; Next += 0x000400; + + Palette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + + AllRam = Next; + + DrvM6809RAM0 = Next; Next += 0x001000; + DrvM6809RAM1 = Next; Next += 0x001800; + + DrvVidRAM = Next; Next += 0x000400; + DrvColRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x000100; + + DrvScrollX = Next; Next += 0x000020; + + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof (INT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + for (INT32 i = 0; i < 2; i++) { + M6809Open(i); + M6809Reset(); + M6809Close(); + } + + AY8910Reset(0); + AY8910Reset(1); + + soundlatch = 0; + flipscreen = 0; + + DrvSoundIrqTrigger = 0; + DrvSoundTrigger = 0; + + return 0; +} + + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + } + + if (sonsonj) + { + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(DrvM6809ROM0 + 0x4000 + i * 0x2000, i, 1)) return 1; + } + + if (BurnLoadRom(DrvM6809ROM1 + 0xe000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x2000, 8, 1)) return 1; + + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x2000, i + 9, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvColPROM + i * 0x0100, i + 15, 1)) return 1; + } + } else { + if (BurnLoadRom(DrvM6809ROM0 + 0x4000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM0 + 0x8000, 1, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM0 + 0xc000, 2, 1)) return 1; + + if (BurnLoadRom(DrvM6809ROM1 + 0xe000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x0000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x2000, 5, 1)) return 1; + + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x2000, i + 6, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvColPROM + i * 0x0100, i + 12, 1)) return 1; + } + } + + DrvPaletteInit(); + DrvGfxDecode(); + + M6809Init(2); + M6809Open(0); + M6809MapMemory(DrvM6809RAM0, 0x0000, 0x0fff, M6809_RAM); + M6809MapMemory(DrvVidRAM, 0x1000, 0x13ff, M6809_RAM); + M6809MapMemory(DrvColRAM, 0x1400, 0x17ff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x2020, 0x207f, M6809_RAM); // 0x100 min + M6809MapMemory(DrvM6809ROM0 + 0x04000, 0x4000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(sonson_main_read); + M6809SetWriteByteHandler(sonson_main_write); + M6809Close(); + + M6809Open(1); + M6809MapMemory(DrvM6809RAM1, 0x0000, 0x07ff, M6809_RAM); + M6809MapMemory(DrvM6809ROM1 + 0x0e000, 0xe000, 0xffff, M6809_ROM); + M6809SetReadByteHandler(sonson_sound_read); + M6809SetWriteByteHandler(sonson_sound_write); + M6809Close(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + M6809Exit(); + AY8910Exit(0); + AY8910Exit(1); + + BurnFree (AllMem); + + sonsonj = 0; + + return 0; +} + +static void draw_background() +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + if (flipscreen) + { + sx ^= 0xf8; + sy ^= 0xf8; + + sx += DrvScrollX[sy >> 3]; + if (sx > 255) sx -= 256; + } else { + sx -= DrvScrollX[sy >> 3]; + if (sx < -7) sx += 256; + } + + sy -= 8; + sx -= 8; + + INT32 attr = DrvColRAM[offs]; + INT32 code = DrvVidRAM[offs] | ((attr & 0x03) << 8); + INT32 color = attr >> 2; + + if (flipscreen) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM0); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0, DrvGfxROM0); + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x80 - 4; offs >= 0x20; offs -= 4) + { + INT32 color = DrvSprRAM[offs + 1]; + INT32 code = DrvSprRAM[offs + 2] + ((color & 0x20) << 3); + INT32 flipx = ~color & 0x40; + INT32 flipy = ~color & 0x80; + INT32 sx = DrvSprRAM[offs + 3]; + INT32 sy = DrvSprRAM[offs + 0]; + + color &= 0x1f; + + if (flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy -= 8; + sx -= 8; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x100, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x100, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0x100, DrvGfxROM1); + } + } + } +} + + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x200; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + draw_background(); + + draw_sprites(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + INT32 nInterleave = 16; + + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInps[0] = DrvInps[1] = DrvInps[2] = 0xff; + + for (INT32 i = 0 ; i < 8; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + DrvInps[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nCyclesSegment = 0; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 2000000 / 60, 2000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + M6809Open(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + if (i == (nInterleave - 1)) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + M6809Close(); + + nCurrentCPU = 1; + M6809Open(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (DrvSoundIrqTrigger) { + M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); + DrvSoundIrqTrigger = 0; + } + nCyclesDone[nCurrentCPU] += M6809Run(nCyclesSegment); + if (i == 3 || i == 7 || i == 11 || i == 15) { + M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + } + M6809Close(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + nSample += pAY8910Buffer[3][n]; + nSample += pAY8910Buffer[4][n]; + nSample += pAY8910Buffer[5][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + nSample += pAY8910Buffer[3][n]; + nSample += pAY8910Buffer[4][n]; + nSample += pAY8910Buffer[5][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029695; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + M6809Scan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(soundlatch); + SCAN_VAR(flipscreen); + SCAN_VAR(DrvSoundTrigger); + } + + return 0; +} + + +// Son Son + +static struct BurnRomInfo sonsonRomDesc[] = { + { "ss.01e", 0x4000, 0xcd40cc54, 1 | BRF_PRG | BRF_ESS }, // 0 Main m6809 + { "ss.02e", 0x4000, 0xc3476527, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ss.03e", 0x4000, 0x1fd0e729, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "ss_6.c11", 0x2000, 0x1135c48a, 2 | BRF_PRG | BRF_ESS }, // 3 Sound m6809 + + { "ss_7.b6", 0x2000, 0x990890b1, 3 | BRF_GRA }, // 4 Characters + { "ss_8.b5", 0x2000, 0x9388ff82, 3 | BRF_GRA }, // 5 + + { "ss_9.m5", 0x2000, 0x8cb1cacf, 4 | BRF_GRA }, // 6 Sprites + { "ss_10.m6", 0x2000, 0xf802815e, 4 | BRF_GRA }, // 7 + { "ss_11.m3", 0x2000, 0x4dbad88a, 4 | BRF_GRA }, // 8 + { "ss_12.m4", 0x2000, 0xaa05e687, 4 | BRF_GRA }, // 9 + { "ss_13.m1", 0x2000, 0x66119bfa, 4 | BRF_GRA }, // 10 + { "ss_14.m2", 0x2000, 0xe14ef54e, 4 | BRF_GRA }, // 11 + + { "ssb4.b2", 0x0020, 0xc8eaf234, 5 | BRF_GRA }, // 12 Color Proms + { "ssb5.b1", 0x0020, 0x0e434add, 5 | BRF_GRA }, // 13 + { "ssb2.c4", 0x0100, 0xc53321c6, 5 | BRF_GRA }, // 14 + { "ssb3.h7", 0x0100, 0x7d2c324a, 5 | BRF_GRA }, // 15 + + { "ssb1.k11", 0x0100, 0xa04b0cfe, 0 | BRF_OPT }, // 16 Timing Prom +}; + +STD_ROM_PICK(sonson) +STD_ROM_FN(sonson) + +struct BurnDriver BurnDrvSonson = { + "sonson", NULL, NULL, NULL, "1984", + "Son Son\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, sonsonRomInfo, sonsonRomName, NULL, NULL, SonsonInputInfo, SonsonDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 240, 240, 4, 3 +}; + + +// Son Son (Japan) + +static struct BurnRomInfo sonsonjRomDesc[] = { + { "ss_0.l9", 0x2000, 0x705c168f, 1 | BRF_PRG | BRF_ESS }, // 0 Main m6809 + { "ss_1.j9", 0x2000, 0x0f03b57d, 1 | BRF_PRG | BRF_ESS }, // 1 + { "ss_2.l8", 0x2000, 0xa243a15d, 1 | BRF_PRG | BRF_ESS }, // 2 + { "ss_3.j8", 0x2000, 0xcb64681a, 1 | BRF_PRG | BRF_ESS }, // 3 + { "ss_4.l7", 0x2000, 0x4c3e9441, 1 | BRF_PRG | BRF_ESS }, // 4 + { "ss_5.j7", 0x2000, 0x847f660c, 1 | BRF_PRG | BRF_ESS }, // 5 + + { "ss_6.c11", 0x2000, 0x1135c48a, 2 | BRF_PRG | BRF_ESS }, // 6 Sound m6809 + + { "ss_7.b6", 0x2000, 0x990890b1, 3 | BRF_GRA }, // 7 Characters + { "ss_8.b5", 0x2000, 0x9388ff82, 3 | BRF_GRA }, // 8 + + { "ss_9.m5", 0x2000, 0x8cb1cacf, 4 | BRF_GRA }, // 9 Sprites + { "ss_10.m6", 0x2000, 0xf802815e, 4 | BRF_GRA }, // 10 + { "ss_11.m3", 0x2000, 0x4dbad88a, 4 | BRF_GRA }, // 11 + { "ss_12.m4", 0x2000, 0xaa05e687, 4 | BRF_GRA }, // 12 + { "ss_13.m1", 0x2000, 0x66119bfa, 4 | BRF_GRA }, // 13 + { "ss_14.m2", 0x2000, 0xe14ef54e, 4 | BRF_GRA }, // 14 + + { "ssb4.b2", 0x0020, 0xc8eaf234, 5 | BRF_GRA }, // 15 Color Proms + { "ssb5.b1", 0x0020, 0x0e434add, 5 | BRF_GRA }, // 16 + { "ssb2.c4", 0x0100, 0xc53321c6, 5 | BRF_GRA }, // 17 + { "ssb3.h7", 0x0100, 0x7d2c324a, 5 | BRF_GRA }, // 18 + + { "ssb1.k11", 0x0100, 0xa04b0cfe, 0 | BRF_OPT }, // 19 Timing Prom +}; + +STD_ROM_PICK(sonsonj) +STD_ROM_FN(sonsonj) + +static INT32 SonsonjInit() +{ + sonsonj = 1; + + return DrvInit(); +} + +struct BurnDriver BurnDrvSonsonj = { + "sonsonj", "sonson", NULL, NULL, "1984", + "Son Son (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, sonsonjRomInfo, sonsonjRomName, NULL, NULL, SonsonInputInfo, SonsonDIPInfo, + SonsonjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 240, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_srumbler.cpp b/src/burn/drivers/misc_pre90s/d_srumbler.cpp new file mode 100644 index 00000000..107bae74 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_srumbler.cpp @@ -0,0 +1,829 @@ +// FB Alpha The Speed Rumbler driver module +// Based on MAME driver by Paul Leaman + +#include "tiles_generic.h" +#include "m6809_intf.h" +#include "burn_ym2203.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *DrvM6809ROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvPROM; +static UINT8 *DrvM6809RAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvBgRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *DrvBank; +static UINT8 *DrvScroll; +static UINT8 *flipscreen; +static UINT8 *soundlatch; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static struct BurnInputInfo SrumblerInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy2 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 7, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Srumbler) + +static struct BurnDIPInfo SrumblerDIPList[]= +{ + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x73, NULL }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x10, "2 Coins 1 Credits" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x04, 0x00, "Upright" }, + {0x12, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x12, 0x01, 0x18, 0x18, "20k 70k and every 70k"}, + {0x12, 0x01, 0x18, 0x10, "30k 80k and every 80k"}, + {0x12, 0x01, 0x18, 0x08, "20k 80k" }, + {0x12, 0x01, 0x18, 0x00, "30k 80k" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x60, 0x40, "Easy" }, + {0x12, 0x01, 0x60, 0x60, "Normal" }, + {0x12, 0x01, 0x60, 0x20, "Difficult" }, + {0x12, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Srumbler) + +static void bankswitch(INT32 data) +{ + DrvBank[0] = data; + + for (INT32 i = 0x05; i < 0x10; i++) + { + INT32 bank = DrvPROM[(data & 0xf0) | i] | DrvPROM[0x100 | ((data & 0x0f) << 4) | i]; + + M6809MapMemory(DrvM6809ROM + bank * 0x1000, 0x1000 * i, 0x1000 * i + 0x0fff, M6809_ROM); + } +} + +void srumbler_main_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x4008: + bankswitch(data); + return; + + case 0x4009: + *flipscreen = data & 1; + return; + + case 0x400a: + case 0x400b: + case 0x400c: + case 0x400d: + DrvScroll[address - 0x400a] = data; + return; + + case 0x400e: + *soundlatch = data; + return; + } +} + +UINT8 srumbler_main_read(UINT16 address) +{ + switch (address) + { + case 0x4008: + return DrvInputs[0]; + + case 0x4009: + return DrvInputs[1]; + + case 0x400a: + return DrvInputs[2]; + + case 0x400b: + return DrvDips[0]; + + case 0x400c: + return DrvDips[1]; + } + + return 0; +} + +void __fastcall srumbler_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8000: + case 0x8001: + BurnYM2203Write(0, address & 1, data); + return; + + case 0xa000: + case 0xa001: + BurnYM2203Write(1, address & 1, data); + return; + } +} + +UINT8 __fastcall srumbler_sound_read(UINT16 address) +{ + if (address == 0xe000) { + return *soundlatch; + } + + return 0; +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 3000000); +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + M6809Open(0); + bankswitch(0); + M6809Reset(); + M6809Close(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvM6809ROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x080000; + DrvGfxROM2 = Next; Next += 0x080000; + + DrvPROM = Next; Next += 0x000200; + + DrvPalette = (UINT32*)Next; Next += 0x00200 * sizeof(UINT32); + + AllRam = Next; + + DrvM6809RAM = Next; Next += 0x001e00; + DrvSprRAM = Next; Next += 0x000200; + DrvSprBuf = Next; Next += 0x000200; + + DrvBgRAM = Next; Next += 0x002000; + DrvFgRAM = Next; Next += 0x001000; + DrvPalRAM = Next; Next += 0x000400; + + DrvZ80RAM = Next; Next += 0x000800; + + DrvBank = Next; Next += 0x000001; + DrvScroll = Next; Next += 0x000004; + + flipscreen = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[2] = { 0x000004, 0x000000 }; + INT32 Plane1[4] = { 0x100004, 0x100000, 0x000004, 0x000000 }; + INT32 Plane2[4] = { 0x180000, 0x100000, 0x080000, 0x000000 }; + INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x100, 0x101, 0x102, 0x103, 0x108, 0x109, 0x10a, 0x10b }; + INT32 XOffs1[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087 }; + INT32 YOffs0[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + INT32 YOffs1[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x400, 2, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x800, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x800, 4, 16, 16, Plane2, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvM6809ROM + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x08000, 1, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x10000, 2, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x18000, 3, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x20000, 4, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x28000, 5, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x30000, 6, 1)) return 1; + if (BurnLoadRom(DrvM6809ROM + 0x38000, 7, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 8, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x08000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x10000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x18000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x20000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x28000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x30000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x38000, 17, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x08000, 19, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x10000, 20, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x18000, 21, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 22, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x28000, 23, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x30000, 24, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x38000, 25, 1)) return 1; + + if (BurnLoadRom(DrvPROM + 0x00000, 26, 1)) return 1; + if (BurnLoadRom(DrvPROM + 0x00100, 27, 1)) return 1; + + for (INT32 i = 0; i < 0x100; i++) { + DrvPROM[i + 0x000] = (DrvPROM[i] & 0x03) << 4; + DrvPROM[i + 0x100] &= 0x0f; + } + + DrvGfxDecode(); + } + + M6809Init(1); + M6809Open(0); + M6809MapMemory(DrvM6809RAM, 0x0000, 0x1dff, M6809_RAM); + M6809MapMemory(DrvSprRAM, 0x1e00, 0x1fff, M6809_RAM); + M6809MapMemory(DrvBgRAM, 0x2000, 0x3fff, M6809_RAM); + M6809MapMemory(DrvFgRAM, 0x5000, 0x5fff, M6809_WRITE); + M6809MapMemory(DrvPalRAM, 0x7000, 0x73ff, M6809_WRITE); + M6809SetReadByteHandler(srumbler_main_read); + M6809SetWriteByteHandler(srumbler_main_write); + M6809Close(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(srumbler_sound_write); + ZetSetReadHandler(srumbler_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 4000000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(3000000); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + M6809Exit(); + ZetExit(); + + BurnYM2203Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_background_layer(INT32 type) +{ + INT32 scrollx = ((DrvScroll[1] << 8) | DrvScroll[0]) & 0x3ff; + INT32 scrolly = ((DrvScroll[3] << 8) | DrvScroll[2]) & 0x3ff; + + INT32 masks[4] = { 0xffff, 0x0000, 0x07ff, 0xf800 }; // 0, 1 + INT32 mask = masks[type]; + + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sy = (offs & 0x3f) << 4; + INT32 sx = (offs >> 6) << 4; + + sy -= scrolly + 8; + if (sy < -15) sy += 1024; + sx -= scrollx + 80; + if (sx < -15) sx += 1024; + + if (sy >= nScreenHeight || sx >= nScreenWidth) continue; + + INT32 attr = DrvBgRAM[offs * 2 + 0]; + INT32 code = DrvBgRAM[offs * 2 + 1] | ((attr & 0x07) << 8); + INT32 color = attr >> 5; + INT32 flipy = attr & 0x08; + + INT32 group = (attr & 0x10) >> 4; + if ((type >> 1) != group) continue; + + { + color = (color << 4) + 0x80; + if (flipy) flipy = 0xf0; + UINT8 *src = DrvGfxROM1 + (code << 8); + UINT16 *dst; + + if (*flipscreen) { + flipy ^= 0xff; + sx = 336 - sx; + sy = 224 - sy; + } + + for (INT32 y = 0; y < 16; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + dst = pTransDraw + sy * nScreenWidth; + + for (INT32 x = 0; x < 16; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = src[((y << 4) | x) ^ flipy]; + + if (mask & (1 << pxl)) continue; + + dst[sx] = pxl | color; + } + + sx -= 16; + } + } + } +} + +static void draw_foreground_layer(INT32 priority) +{ + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sy = (offs & 0x1f) << 3; + INT32 sx = (offs >> 5) << 3; + + sx -= 80; + sy -= 8; + + if (sx < -15 || sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = DrvFgRAM[offs * 2 + 0]; + + INT32 code = DrvFgRAM[offs * 2 + 1] | ((attr & 0x03) << 8); + INT32 color = (attr & 0x3c) >> 2; + INT32 prio = (attr & 0x40) >> 6; + + if (prio != priority) continue; + + if (*flipscreen) { + sx = 344 - sx; + sy = 232 - sy; + + if (priority) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 2, 0x1c0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx - 80, sy, color, 2, 3, 0x1c0, DrvGfxROM0); + } + } else { + if (priority) { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 2, 0x1c0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 2, 3, 0x1c0, DrvGfxROM0); + } + } + } +} + +static void draw_sprites() +{ + for (INT32 offs = 0x200-4; offs >= 0; offs -= 4) + { + INT32 attr = DrvSprBuf[offs + 1]; + INT32 code = DrvSprBuf[offs + 0] | ((attr & 0xe0) << 3); + INT32 sy = DrvSprBuf[offs + 2]; + INT32 sx = DrvSprBuf[offs + 3] | ((attr & 0x01) << 8); + INT32 color = (attr & 0x1c) >> 2; + INT32 flipy = (attr & 0x02); + INT32 flipx = 0; + + if (*flipscreen) + { + sx = 496 - sx; + sy = 240 - sy; + flipy ^= 2; + flipx = 1; + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx - 80, sy - 8, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx - 80, sy - 8, color, 4, 15, 0x100, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx - 80, sy - 8, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx - 80, sy - 8, color, 4, 15, 0x100, DrvGfxROM2); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + UINT8 r,g,b; + for (INT32 i = 0; i < 0x400; i+=2) { + INT32 d = DrvPalRAM[i + 1] | (DrvPalRAM[i + 0] << 8); + + r = (d >> 12); + g = (d >> 8) & 0x0f; + b = (d >> 4) & 0x0f; + + DrvPalette[i >> 1] = BurnHighCol((r << 4) | r, (g << 4) | g, (b << 4) | b, 0); + } + } + + if (nSpriteEnable & 1) draw_background_layer(1); // opaque + else BurnTransferClear(); + + if (nBurnLayer & 2) draw_background_layer(3); + if (nBurnLayer & 4) draw_foreground_layer(0); + + draw_sprites(); + + if (nBurnLayer & 1) draw_background_layer(2); + if (nBurnLayer & 8) draw_foreground_layer(1); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + { + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + DrvInputs[2] ^= (DrvJoy3[i] & 1) << i; + } + } + + INT32 nInterleave = 4; + INT32 nCyclesTotal[2] = { 1500000 / 60, 3000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + M6809Open(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + nCyclesDone[0] += M6809Run(nCyclesTotal[0] / nInterleave); + if (i == (nInterleave / 2) - 1) M6809SetIRQ(1, M6809_IRQSTATUS_AUTO); + if (i == (nInterleave / 1) - 1) M6809SetIRQ(0, M6809_IRQSTATUS_AUTO); + + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetRaiseIrq(0); + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + M6809Close(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x200); + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029706; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + M6809Scan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + } + + { + M6809Open(0); + bankswitch(DrvBank[0]); + M6809Close(); + } + + return 0; +} + + +// The Speed Rumbler (set 1) + +static struct BurnRomInfo srumblerRomDesc[] = { + { "14e_sr04.bin", 0x8000, 0xa68ce89c, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "13e_sr03.bin", 0x8000, 0x87bda812, 1 | BRF_PRG | BRF_ESS }, // 1 + { "12e_sr02.bin", 0x8000, 0xd8609cca, 1 | BRF_PRG | BRF_ESS }, // 2 + { "11e_sr01.bin", 0x8000, 0x27ec4776, 1 | BRF_PRG | BRF_ESS }, // 3 + { "14f_sr09.bin", 0x8000, 0x2146101d, 1 | BRF_PRG | BRF_ESS }, // 4 + { "13f_sr08.bin", 0x8000, 0x838369a6, 1 | BRF_PRG | BRF_ESS }, // 5 + { "12f_sr07.bin", 0x8000, 0xde785076, 1 | BRF_PRG | BRF_ESS }, // 6 + { "11f_sr06.bin", 0x8000, 0xa70f4fd4, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "2f_sr05.bin", 0x8000, 0x0177cebe, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "6g_sr10.bin", 0x4000, 0xadabe271, 3 | BRF_GRA }, // 9 Characters + + { "11a_sr11.bin", 0x8000, 0x5fa042ba, 4 | BRF_GRA }, // 10 Tiles + { "13a_sr12.bin", 0x8000, 0xa2db64af, 4 | BRF_GRA }, // 11 + { "14a_sr13.bin", 0x8000, 0xf1df5499, 4 | BRF_GRA }, // 12 + { "15a_sr14.bin", 0x8000, 0xb22b31b3, 4 | BRF_GRA }, // 13 + { "11c_sr15.bin", 0x8000, 0xca3a3af3, 4 | BRF_GRA }, // 14 + { "13c_sr16.bin", 0x8000, 0xc49a4a11, 4 | BRF_GRA }, // 15 + { "14c_sr17.bin", 0x8000, 0xaa80aaab, 4 | BRF_GRA }, // 16 + { "15c_sr18.bin", 0x8000, 0xce67868e, 4 | BRF_GRA }, // 17 + + { "15e_sr20.bin", 0x8000, 0x3924c861, 5 | BRF_GRA }, // 18 Sprites + { "14e_sr19.bin", 0x8000, 0xff8f9129, 5 | BRF_GRA }, // 19 + { "15f_sr22.bin", 0x8000, 0xab64161c, 5 | BRF_GRA }, // 20 + { "14f_sr21.bin", 0x8000, 0xfd64bcd1, 5 | BRF_GRA }, // 21 + { "15h_sr24.bin", 0x8000, 0xc972af3e, 5 | BRF_GRA }, // 22 + { "14h_sr23.bin", 0x8000, 0x8c9abf57, 5 | BRF_GRA }, // 23 + { "15j_sr26.bin", 0x8000, 0xd4f1732f, 5 | BRF_GRA }, // 24 + { "14j_sr25.bin", 0x8000, 0xd2a4ea4f, 5 | BRF_GRA }, // 25 + + { "63s141.12a", 0x0100, 0x8421786f, 6 | BRF_PRG | BRF_ESS }, // 26 Rom Bank Proms + { "63s141.13a", 0x0100, 0x6048583f, 6 | BRF_PRG | BRF_ESS }, // 27 + + { "63s141.8j", 0x0100, 0x1a89a7ff, 0 | BRF_OPT }, // 28 Priority Prom +}; + +STD_ROM_PICK(srumbler) +STD_ROM_FN(srumbler) + +struct BurnDriver BurnDrvSrumbler = { + "srumbler", NULL, NULL, NULL, "1986", + "The Speed Rumbler (set 1)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, srumblerRomInfo, srumblerRomName, NULL, NULL, SrumblerInputInfo, SrumblerDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x200, 240, 352, 3, 4 +}; + + +// The Speed Rumbler (set 2) + +static struct BurnRomInfo srumblr2RomDesc[] = { + { "14e_sr04.bin", 0x8000, 0xa68ce89c, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "rc03.13e", 0x8000, 0xe82f78d4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rc02.12e", 0x8000, 0x009a62d8, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rc01.11e", 0x8000, 0x2ac48d1d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "rc09.14f", 0x8000, 0x64f23e72, 1 | BRF_PRG | BRF_ESS }, // 4 + { "rc08.13f", 0x8000, 0x74c71007, 1 | BRF_PRG | BRF_ESS }, // 5 + { "12f_sr07.bin", 0x8000, 0xde785076, 1 | BRF_PRG | BRF_ESS }, // 6 + { "11f_sr06.bin", 0x8000, 0xa70f4fd4, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "rc05.2f", 0x8000, 0xea04fa07, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "6g_sr10.bin", 0x4000, 0xadabe271, 3 | BRF_GRA }, // 9 Characters + + { "11a_sr11.bin", 0x8000, 0x5fa042ba, 4 | BRF_GRA }, // 10 Tiles + { "13a_sr12.bin", 0x8000, 0xa2db64af, 4 | BRF_GRA }, // 11 + { "14a_sr13.bin", 0x8000, 0xf1df5499, 4 | BRF_GRA }, // 12 + { "15a_sr14.bin", 0x8000, 0xb22b31b3, 4 | BRF_GRA }, // 13 + { "11c_sr15.bin", 0x8000, 0xca3a3af3, 4 | BRF_GRA }, // 14 + { "13c_sr16.bin", 0x8000, 0xc49a4a11, 4 | BRF_GRA }, // 15 + { "14c_sr17.bin", 0x8000, 0xaa80aaab, 4 | BRF_GRA }, // 16 + { "15c_sr18.bin", 0x8000, 0xce67868e, 4 | BRF_GRA }, // 17 + + { "15e_sr20.bin", 0x8000, 0x3924c861, 5 | BRF_GRA }, // 18 Sprites + { "14e_sr19.bin", 0x8000, 0xff8f9129, 5 | BRF_GRA }, // 19 + { "15f_sr22.bin", 0x8000, 0xab64161c, 5 | BRF_GRA }, // 20 + { "14f_sr21.bin", 0x8000, 0xfd64bcd1, 5 | BRF_GRA }, // 21 + { "15h_sr24.bin", 0x8000, 0xc972af3e, 5 | BRF_GRA }, // 22 + { "14h_sr23.bin", 0x8000, 0x8c9abf57, 5 | BRF_GRA }, // 23 + { "15j_sr26.bin", 0x8000, 0xd4f1732f, 5 | BRF_GRA }, // 24 + { "14j_sr25.bin", 0x8000, 0xd2a4ea4f, 5 | BRF_GRA }, // 25 + + { "63s141.12a", 0x0100, 0x8421786f, 6 | BRF_PRG | BRF_ESS }, // 26 Rom Bank Proms + { "63s141.13a", 0x0100, 0x6048583f, 6 | BRF_PRG | BRF_ESS }, // 27 + + { "63s141.8j", 0x0100, 0x1a89a7ff, 0 | BRF_OPT }, // 28 Priority Prom +}; + +STD_ROM_PICK(srumblr2) +STD_ROM_FN(srumblr2) + +struct BurnDriver BurnDrvSrumblr2 = { + "srumbler2", "srumbler", NULL, NULL, "1986", + "The Speed Rumbler (set 2)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, srumblr2RomInfo, srumblr2RomName, NULL, NULL, SrumblerInputInfo, SrumblerDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x200, 240, 352, 3, 4 +}; + + +// Rush & Crash (Japan) + +static struct BurnRomInfo rushcrshRomDesc[] = { + { "14e_sr04.bin", 0x8000, 0xa68ce89c, 1 | BRF_PRG | BRF_ESS }, // 0 M6809 Code + { "rc03.bin", 0x8000, 0xa49c9be0, 1 | BRF_PRG | BRF_ESS }, // 1 + { "rc02.12e", 0x8000, 0x009a62d8, 1 | BRF_PRG | BRF_ESS }, // 2 + { "rc01.11e", 0x8000, 0x2ac48d1d, 1 | BRF_PRG | BRF_ESS }, // 3 + { "rc09.14f", 0x8000, 0x64f23e72, 1 | BRF_PRG | BRF_ESS }, // 4 + { "rc08.bin", 0x8000, 0x2c25874b, 1 | BRF_PRG | BRF_ESS }, // 5 + { "12f_sr07.bin", 0x8000, 0xde785076, 1 | BRF_PRG | BRF_ESS }, // 6 + { "11f_sr06.bin", 0x8000, 0xa70f4fd4, 1 | BRF_PRG | BRF_ESS }, // 7 + + { "rc05.2f", 0x8000, 0xea04fa07, 2 | BRF_PRG | BRF_ESS }, // 8 Z80 Code + + { "rc10.bin", 0x4000, 0x0a3c0b0d, 3 | BRF_GRA }, // 9 Characters + + { "11a_sr11.bin", 0x8000, 0x5fa042ba, 4 | BRF_GRA }, // 10 Tiles + { "13a_sr12.bin", 0x8000, 0xa2db64af, 4 | BRF_GRA }, // 11 + { "14a_sr13.bin", 0x8000, 0xf1df5499, 4 | BRF_GRA }, // 12 + { "15a_sr14.bin", 0x8000, 0xb22b31b3, 4 | BRF_GRA }, // 13 + { "11c_sr15.bin", 0x8000, 0xca3a3af3, 4 | BRF_GRA }, // 14 + { "13c_sr16.bin", 0x8000, 0xc49a4a11, 4 | BRF_GRA }, // 15 + { "14c_sr17.bin", 0x8000, 0xaa80aaab, 4 | BRF_GRA }, // 16 + { "15c_sr18.bin", 0x8000, 0xce67868e, 4 | BRF_GRA }, // 17 + + { "15e_sr20.bin", 0x8000, 0x3924c861, 5 | BRF_GRA }, // 18 Sprites + { "14e_sr19.bin", 0x8000, 0xff8f9129, 5 | BRF_GRA }, // 19 + { "15f_sr22.bin", 0x8000, 0xab64161c, 5 | BRF_GRA }, // 20 + { "14f_sr21.bin", 0x8000, 0xfd64bcd1, 5 | BRF_GRA }, // 21 + { "15h_sr24.bin", 0x8000, 0xc972af3e, 5 | BRF_GRA }, // 22 + { "14h_sr23.bin", 0x8000, 0x8c9abf57, 5 | BRF_GRA }, // 23 + { "15j_sr26.bin", 0x8000, 0xd4f1732f, 5 | BRF_GRA }, // 24 + { "14j_sr25.bin", 0x8000, 0xd2a4ea4f, 5 | BRF_GRA }, // 25 + + { "63s141.12a", 0x0100, 0x8421786f, 6 | BRF_PRG | BRF_ESS }, // 26 Rom Bank Proms + { "63s141.13a", 0x0100, 0x6048583f, 6 | BRF_PRG | BRF_ESS }, // 27 + + { "63s141.8j", 0x0100, 0x1a89a7ff, 0 | BRF_OPT }, // 28 Priority Prom +}; + +STD_ROM_PICK(rushcrsh) +STD_ROM_FN(rushcrsh) + +struct BurnDriver BurnDrvRushcrsh = { + "rushcrsh", "srumbler", NULL, NULL, "1986", + "Rush & Crash (Japan)\0", NULL, "Capcom", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0, + NULL, rushcrshRomInfo, rushcrshRomName, NULL, NULL, SrumblerInputInfo, SrumblerDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, + &DrvRecalc, 0x200, 240, 352, 3, 4 +}; + diff --git a/src/burn/drivers/misc_pre90s/d_tecmo.cpp b/src/burn/drivers/misc_pre90s/d_tecmo.cpp new file mode 100644 index 00000000..c0fb889d --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_tecmo.cpp @@ -0,0 +1,1558 @@ +// FB Alpha Tecmo driver Module +// Based on MAME driver by Nicola Salmoria + +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "msm5205.h" + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvJoy4[8]; +static UINT8 DrvJoy5[8]; +static UINT8 DrvJoy6[8]; +static UINT8 DrvJoy11[8]; +static UINT8 DrvReset; +static UINT8 DrvInputs[11]; + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvPalRAM; +static UINT8 *DrvTextRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvForeRAM; +static UINT8 *DrvBackRAM; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT16 *DrvBgScroll; +static UINT16 *DrvFgScroll; + +static INT32 tecmo_video_type; + +static UINT32 adpcm_pos; +static UINT32 adpcm_end; +static UINT32 adpcm_size; +static INT32 adpcm_data; +static UINT8 DrvHasADPCM; + +static UINT32 DrvZ80Bank; +static UINT8 soundlatch; +static UINT8 flipscreen; +static UINT8 DrvEnableNmi; + +static struct BurnInputInfo RygarInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy5 + 3, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy5 + 2, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy5 + 1, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Down", BIT_DIGITAL , DrvJoy1 + 2, "p1 down", }, + {"P1 Up", BIT_DIGITAL , DrvJoy1 + 3, "p1 up", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 1, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy5 + 0, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down", }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 2"}, + + {"Service", BIT_DIGITAL , DrvJoy2 + 2, "diag" }, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvInputs + 6, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvInputs + 7, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvInputs + 8, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvInputs + 9, "dip" }, +}; + +STDINPUTINFO(Rygar) + +static struct BurnInputInfo BackfirtInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy6 + 2, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy6 + 3, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy6 + 1, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Down", BIT_DIGITAL , DrvJoy1 + 2, "p1 down", }, + {"P1 Up", BIT_DIGITAL , DrvJoy1 + 3, "p1 up", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 1, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy2 + 2, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy6 + 0, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down", }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy4 + 2, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvInputs + 6, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvInputs + 7, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvInputs + 8, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvInputs + 9, "dip" }, +}; + +STDINPUTINFO(Backfirt) + +static struct BurnInputInfo GeminiInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy6 + 2, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy6 + 3, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy6 + 0, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Down", BIT_DIGITAL , DrvJoy1 + 2, "p1 down", }, + {"P1 Up", BIT_DIGITAL , DrvJoy1 + 3, "p1 up", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 1, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 2"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy6 + 1, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down", }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvInputs + 6, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvInputs + 7, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvInputs + 8, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvInputs + 9, "dip" }, +}; + +STDINPUTINFO(Gemini) + +static struct BurnInputInfo SilkwormInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy11 + 2, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy11 + 3, "p2 coin" }, + + {"P1 Start" , BIT_DIGITAL , DrvJoy11 + 0, "p1 start" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvJoy1 + 1, "p1 right" }, + {"P1 Down", BIT_DIGITAL , DrvJoy1 + 2, "p1 down", }, + {"P1 Up", BIT_DIGITAL , DrvJoy1 + 3, "p1 up", }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 1, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 0, "p1 fire 2"}, + {"P1 Button 3" , BIT_DIGITAL , DrvJoy2 + 2, "p1 fire 3"}, + + {"P2 Start" , BIT_DIGITAL , DrvJoy11 + 1, "p2 start" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 1, "p2 right" }, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 2, "p2 down", }, + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 3, "p2 up", }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy4 + 1, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy4 + 0, "p2 fire 2"}, + {"P2 Button 3" , BIT_DIGITAL , DrvJoy4 + 2, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL , &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvInputs + 6, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvInputs + 7, "dip" }, + {"Dip 3", BIT_DIPSWITCH, DrvInputs + 8, "dip" }, + {"Dip 4", BIT_DIPSWITCH, DrvInputs + 9, "dip" }, + +}; + +STDINPUTINFO(Silkworm) + +static struct BurnDIPInfo RygarDIPList[]= +{ + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0x12, 0xfe, 0, 4, "Coin A" }, + {0x12, 0x01, 0x03, 0x01, "2C 1C" }, + {0x12, 0x01, 0x03, 0x00, "1C 1C" }, + {0x12, 0x01, 0x03, 0x02, "1C 2C" }, + {0x12, 0x01, 0x03, 0x03, "1C 3C" }, + + {0x12, 0xfe, 0, 4, "Coin B" }, + {0x12, 0x01, 0x0C, 0x04, "2C 1C" }, + {0x12, 0x01, 0x0C, 0x00, "1C 1C" }, + {0x12, 0x01, 0x0C, 0x08, "1C 2C" }, + {0x12, 0x01, 0x0C, 0x0C, "1C 3C" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x00, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x02, "5" }, + + {0x13, 0xfe, 0, 2, "Cabinet" }, + {0x13, 0x01, 0x04, 0x04, "Upright" }, + {0x13, 0x01, 0x04, 0x00, "Cocktail" }, + + {0x14, 0xfe, 0, 4, "Bonus Life" }, + {0x14, 0x01, 0x03, 0x00, "50000 200000 500000" }, + {0x14, 0x01, 0x03, 0x01, "100000 300000 600000" }, + {0x14, 0x01, 0x03, 0x02, "200000 500000" }, + {0x14, 0x01, 0x03, 0x03, "100000" }, + + {0x15, 0xfe, 0, 4, "Difficulty" }, + {0x15, 0x01, 0x03, 0x00, "Easy" }, + {0x15, 0x01, 0x03, 0x01, "Normal" }, + {0x15, 0x01, 0x03, 0x02, "Hard" }, + {0x15, 0x01, 0x03, 0x03, "Hardest" }, + + {0x15, 0xfe, 0, 2, "2P Can Start Anytime" }, + {0x15, 0x01, 0x04, 0x00, "No" }, + {0x15, 0x01, 0x04, 0x04, "Yes" }, + + {0x15, 0xfe, 0, 2, "Allow Continue" }, + {0x15, 0x01, 0x08, 0x00, "No" }, + {0x15, 0x01, 0x08, 0x08, "Yes" }, +}; + +STDDIPINFO(Rygar) + +static struct BurnDIPInfo GeminiDIPList[]= +{ + {0x11, 0xff, 0xff, 0x00, NULL }, + {0x12, 0xff, 0xff, 0x00, NULL }, + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + + {0x11, 0xfe, 0, 8, "Coin A" }, + {0x11, 0x01, 0x07, 0x06, "2C 1C" }, + {0x11, 0x01, 0x07, 0x00, "1C 1C" }, + {0x11, 0x01, 0x07, 0x07, "2C 3C" }, + {0x11, 0x01, 0x07, 0x01, "1C 2C" }, + {0x11, 0x01, 0x07, 0x02, "1C 3C" }, + {0x11, 0x01, 0x07, 0x03, "1C 4C" }, + {0x11, 0x01, 0x07, 0x04, "1C 5C" }, + {0x11, 0x01, 0x07, 0x05, "1C 6C" }, + + {0x11, 0xfe, 0, 2, "Final Round Continuation" }, + {0x11, 0x01, 0x08, 0x00, "Round 6" }, + {0x11, 0x01, 0x08, 0x08, "Round 7" }, + + {0x12, 0xfe, 0, 8, "Coin B" }, + {0x12, 0x01, 0x07, 0x06, "2C 1C" }, + {0x12, 0x01, 0x07, 0x00, "1C 1C" }, + {0x12, 0x01, 0x07, 0x07, "2C 3C" }, + {0x12, 0x01, 0x07, 0x01, "1C 2C" }, + {0x12, 0x01, 0x07, 0x02, "1C 3C" }, + {0x12, 0x01, 0x07, 0x03, "1C 4C" }, + {0x12, 0x01, 0x07, 0x04, "1C 5C" }, + {0x12, 0x01, 0x07, 0x05, "1C 6C" }, + + {0x12, 0xfe, 0, 2, "Buy in During Final Round" }, + {0x12, 0x01, 0x08, 0x00, "No" }, + {0x12, 0x01, 0x08, 0x08, "Yes" }, + + {0x13, 0xfe, 0, 4, "Lives" }, + {0x13, 0x01, 0x03, 0x03, "2" }, + {0x13, 0x01, 0x03, 0x00, "3" }, + {0x13, 0x01, 0x03, 0x01, "4" }, + {0x13, 0x01, 0x03, 0x02, "5" }, + + {0x13, 0xfe, 0, 4, "Difficulty" }, + {0x13, 0x01, 0x0c, 0x00, "Easy" }, + {0x13, 0x01, 0x0c, 0x04, "Normal" }, + {0x13, 0x01, 0x0c, 0x08, "Hard" }, + {0x13, 0x01, 0x0c, 0x0c, "Hardest" }, + + {0x14, 0xfe, 0, 8, "Bonus Life" }, + {0x14, 0x01, 0x07, 0x00, "50000 200000" }, + {0x14, 0x01, 0x07, 0x01, "50000 300000" }, + {0x14, 0x01, 0x07, 0x02, "100000 500000" }, + {0x14, 0x01, 0x07, 0x03, "50000" }, + {0x14, 0x01, 0x07, 0x04, "100000" }, + {0x14, 0x01, 0x07, 0x05, "200000" }, + {0x14, 0x01, 0x07, 0x06, "300000" }, + {0x14, 0x01, 0x07, 0x07, "None" }, + + {0x14, 0xfe, 0, 2, "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, +}; + +STDDIPINFO(Gemini) + +static struct BurnDIPInfo SilkwormDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + {0x13, 0xfe, 0, 4, "Coin A" }, + {0x13, 0x01, 0x3, 0x01, "2C 1C" }, + {0x13, 0x01, 0x3, 0x00, "1C 1C" }, + {0x13, 0x01, 0x3, 0x02, "1C 2C" }, + {0x13, 0x01, 0x3, 0x03, "1C 3C" }, + + {0x13, 0xfe, 0, 4, "Coin B" }, + {0x13, 0x01, 0xC, 0x04, "2C 1C" }, + {0x13, 0x01, 0xC, 0x00, "1C 1C" }, + {0x13, 0x01, 0xC, 0x08, "1C 2C" }, + {0x13, 0x01, 0xC, 0x0C, "1C 3C" }, + + {0x14, 0xfe, 0, 4 , "Lives" }, + {0x14, 0x01, 0x3, 0x03, "2" }, + {0x14, 0x01, 0x3, 0x00, "3" }, + {0x14, 0x01, 0x3, 0x01, "4" }, + {0x14, 0x01, 0x3, 0x02, "5" }, + + {0x14, 0xfe, 0, 2 , "Demo Sounds" }, + {0x14, 0x01, 0x8, 0x00, "Off" }, + {0x14, 0x01, 0x8, 0x08, "On" }, + + {0x15, 0xfe, 0, 8, "Bonus Life" }, + {0x15, 0x01, 0x7, 0x00, "50000 200000 500000" }, + {0x15, 0x01, 0x7, 0x01, "100000 300000 800000" }, + {0x15, 0x01, 0x7, 0x02, "50000 200000" }, + {0x15, 0x01, 0x7, 0x03, "100000 300000" }, + {0x15, 0x01, 0x7, 0x04, "50000" }, + {0x15, 0x01, 0x7, 0x05, "100000" }, + {0x15, 0x01, 0x7, 0x06, "200000" }, + {0x15, 0x01, 0x7, 0x07, "None" }, + + {0x16, 0xfe, 0, 6, "Difficulty" }, + {0x16, 0x01, 0x7, 0x00, "0" }, + {0x16, 0x01, 0x7, 0x01, "1" }, + {0x16, 0x01, 0x7, 0x02, "2" }, + {0x16, 0x01, 0x7, 0x03, "3" }, + {0x16, 0x01, 0x7, 0x04, "4" }, + {0x16, 0x01, 0x7, 0x05, "5" }, + + {0x16, 0xfe, 0, 2, "Allow Continue" }, + {0x16, 0x01, 0x8, 0x08, "No" }, + {0x16, 0x01, 0x8, 0x00, "Yes" }, +}; + +STDDIPINFO(Silkworm) + +static struct BurnDIPInfo BackfirtDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x10, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + + {0x13, 0xfe, 0, 4, "Coin A" }, + {0x13, 0x01, 0x3, 0x00, "1C 1C" }, + {0x13, 0x01, 0x3, 0x01, "1C 2C" }, + {0x13, 0x01, 0x3, 0x02, "1C 3C" }, + {0x13, 0x01, 0x3, 0x03, "1C 6C" }, + + {0x13, 0xfe, 0, 4, "Coin B" }, + {0x13, 0x01, 0xC, 0x04, "2C 1C" }, + {0x13, 0x01, 0xC, 0x00, "1C 1C" }, + {0x13, 0x01, 0xC, 0x08, "1C 2C" }, + {0x13, 0x01, 0xC, 0x0C, "1C 3C" }, + + {0x14, 0xfe, 0, 2, "Cabinet" }, + {0x14, 0x01, 0x10, 0x10, "Upright" }, + {0x14, 0x01, 0x10, 0x00, "Cocktail" }, + + {0x15, 0xfe, 0, 8, "Bonus Life" }, + {0x15, 0x01, 0x07, 0x00, "50000 200000 500000" }, + {0x15, 0x01, 0x07, 0x01, "100000 300000 800000" }, + {0x15, 0x01, 0x07, 0x02, "50000 200000" }, + {0x15, 0x01, 0x07, 0x03, "100000 300000" }, + {0x15, 0x01, 0x07, 0x04, "50000" }, + {0x15, 0x01, 0x07, 0x05, "100000" }, + {0x15, 0x01, 0x07, 0x06, "200000" }, + {0x15, 0x01, 0x07, 0x07, "None" }, + + // not verified + {0x15, 0xfe, 0, 6, "Difficulty" }, + {0x15, 0x01, 0x38, 0x00, "0" }, + {0x15, 0x01, 0x38, 0x08, "1" }, + {0x15, 0x01, 0x38, 0x10, "2" }, + {0x15, 0x01, 0x38, 0x18, "3" }, + {0x15, 0x01, 0x38, 0x20, "4" }, + {0x15, 0x01, 0x38, 0x28, "5" }, + + {0x16, 0xfe, 0, 2, "Allow Continue" }, + {0x16, 0x01, 0x04, 0x04, "No" }, + {0x16, 0x01, 0x04, 0x00, "Yes" }, + + {0x16, 0xfe, 0, 2, "Invincibility (Cheat)" }, + {0x16, 0x01, 0x08, 0x08, "No" }, + {0x16, 0x01, 0x08, 0x00, "Yes" }, +}; + +STDDIPINFO(Backfirt) + +UINT8 __fastcall rygar_main_read(UINT16 address) +{ + switch (address) + { + case 0xf800: + case 0xf801: + case 0xf802: + case 0xf803: + case 0xf804: + case 0xf805: + case 0xf806: + case 0xf807: + case 0xf808: + case 0xf809: + return DrvInputs[address & 0x0f]; + + case 0xf80f: + return DrvInputs[10]; + } + + return 0; +} + +static void bankswitch_w(INT32 data) +{ + DrvZ80Bank = 0x10000 + ((data & 0xf8) << 8); + + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80ROM0 + DrvZ80Bank); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80ROM0 + DrvZ80Bank); +} + +static inline void palette_write(INT32 offset) +{ + UINT16 data; + UINT8 r,g,b; + + data = *((UINT16*)(DrvPalRAM + (offset & ~1))); + data = (data << 8) | (data >> 8); + + r = (data >> 4) & 0x0f; + g = (data >> 0) & 0x0f; + b = (data >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[offset >> 1] = BurnHighCol(r, g, b, 0); +} + +void __fastcall rygar_main_write(UINT16 address, UINT8 data) +{ + if ((address & 0xf000) == 0xe000) { + DrvPalRAM[address & 0x7ff] = data; + palette_write(address & 0x7ff); + return; + } + + switch (address) + { + case 0xf800: + DrvFgScroll[0] = (DrvFgScroll[0] & 0xff00) | data; + return; + + case 0xf801: + DrvFgScroll[0] = (DrvFgScroll[0] & 0x00ff) | (data << 8); + return; + + case 0xf802: + DrvFgScroll[1] = data; + return; + + case 0xf803: + DrvBgScroll[0] = (DrvBgScroll[0] & 0xff00) | data; + return; + + case 0xf804: + DrvBgScroll[0] = (DrvBgScroll[0] & 0x00ff) | (data << 8); + return; + + case 0xf805: + DrvBgScroll[1] = data; + return; + + case 0xf806: + soundlatch = data; + DrvEnableNmi = 1; + return; + + case 0xf807: + flipscreen = data & 1; + return; + + case 0xf808: + bankswitch_w(data); + return; + + case 0xf80b: + // watchdog reset + return; + } + + return; +} + +UINT8 __fastcall rygar_sound_read(UINT16 address) +{ + switch (address) + { + case 0xc000: + return soundlatch; + } + + return 0; +} + +void __fastcall rygar_sound_write(UINT16 address, UINT8 data) +{ + if ((address & 0xff80) == 0x2000) { + DrvZ80ROM1[address] = data; + return; + } + + switch (address) + { + case 0x8000: + case 0xa000: + BurnYM3812Write(0, data); + return; + + case 0x8001: + case 0xa001: + BurnYM3812Write(1, data); + return; + + case 0xc000: + adpcm_pos = data << 8; + MSM5205ResetWrite(0, 0); + return; + + case 0xc400: + case 0xd000: + adpcm_end = (data + 1) << 8; + return; + + case 0xc800: + case 0xe000: + MSM5205SetVolume(0, (data & 0x0f) * 100 / 15); + return; + + case 0xf000: + return; + } + + return; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x20000; + DrvZ80ROM1 = Next; Next += 0x08000; + + DrvSndROM = Next; Next += adpcm_size; + + DrvGfxROM0 = Next; Next += 0x10000; + DrvGfxROM1 = Next; Next += 0x80000; + DrvGfxROM2 = Next; Next += 0x80000; + DrvGfxROM3 = Next; Next += 0x80000; + + AllRam = Next; + + DrvZ80RAM0 = Next; Next += 0x01000; + DrvZ80RAM1 = Next; Next += 0x00800; + + DrvPalRAM = Next; Next += 0x00800; + DrvTextRAM = Next; Next += 0x00800; + DrvBackRAM = Next; Next += 0x00400; + DrvForeRAM = Next; Next += 0x00400; + DrvSprRAM = Next; Next += 0x00800; + + DrvBgScroll = (UINT16*)Next; Next += 0x00002 * sizeof(UINT16); + DrvFgScroll = (UINT16*)Next; Next += 0x00002 * sizeof(UINT16); + + DrvPalette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x40000); + if (tmp == NULL) { + return 1; + } + + static INT32 Planes[4] = { + 0x000, 0x001, 0x002, 0x003 + }; + + static INT32 XOffs[16] = { + 0x000, 0x004, 0x008, 0x00c, 0x010, 0x014, 0x018, 0x01c, + 0x100, 0x104, 0x108, 0x10c, 0x110, 0x114, 0x118, 0x11c + }; + + static INT32 YOffs[16] = { + 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0, + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 + }; + + memcpy (tmp, DrvGfxROM0, 0x08000); + + GfxDecode(0x0400, 4, 8, 8, Planes, XOffs, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x40000); + + GfxDecode(0x2000, 4, 8, 8, Planes, XOffs, YOffs, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Planes, XOffs, YOffs, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x40000); + + GfxDecode(0x0800, 4, 16, 16, Planes, XOffs, YOffs, 0x400, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + bankswitch_w(0); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + if (DrvHasADPCM) MSM5205Reset(); + BurnYM3812Reset(); + + if (tecmo_video_type) { + memset (DrvZ80ROM1 + 0x2000, 0, 0x80); + } + + soundlatch = 0; + flipscreen = 0; + + adpcm_pos = 0; + adpcm_end = 0; + adpcm_data = -1; + + return 0; +} + +static void TecmoFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 TecmoSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static void TecmoMSM5205Vck() +{ + if (adpcm_pos >= adpcm_end || adpcm_pos >= adpcm_size) { + MSM5205ResetWrite(0, 1); + } else { + if (adpcm_data != -1) { + MSM5205DataWrite(0, adpcm_data & 0x0f); + adpcm_data = -1; + } else { + adpcm_data = DrvSndROM[adpcm_pos++ & (adpcm_size - 1)]; + MSM5205DataWrite(0, adpcm_data >> 4); + } + } +} + +static INT32 RygarInit() +{ + tecmo_video_type = 0; + DrvHasADPCM = 1; + adpcm_size = 0x4000; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xcfff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 2, DrvZ80RAM0); + ZetMapArea(0xd000, 0xd7ff, 0, DrvTextRAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvTextRAM); + ZetMapArea(0xd800, 0xdbff, 0, DrvForeRAM); + ZetMapArea(0xd800, 0xdbff, 1, DrvForeRAM); + ZetMapArea(0xdc00, 0xdfff, 0, DrvBackRAM); + ZetMapArea(0xdc00, 0xdfff, 1, DrvBackRAM); + ZetMapArea(0xe000, 0xe7ff, 0, DrvSprRAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvSprRAM); + ZetMapArea(0xe800, 0xefff, 0, DrvPalRAM); + ZetSetWriteHandler(rygar_main_write); + ZetSetReadHandler(rygar_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x3fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x3fff, 2, DrvZ80ROM1); + ZetMapArea(0x4000, 0x47ff, 0, DrvZ80RAM1); + ZetMapArea(0x4000, 0x47ff, 1, DrvZ80RAM1); + ZetMapArea(0x4000, 0x47ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(rygar_sound_write); + ZetSetReadHandler(rygar_sound_read); + ZetMemEnd(); + ZetClose(); + + { + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(DrvZ80ROM0 + i * 0x8000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM1, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 4, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x8000, i + 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x8000, i + 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + i * 0x8000, i + 13, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 17, 1)) return 1; + + DrvGfxDecode(); + } + + BurnYM3812Init(4000000, &TecmoFMIRQHandler, &TecmoSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + MSM5205Init(0, TecmoSynchroniseStream, 400000, TecmoMSM5205Vck, MSM5205_S48_4B, 100, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + + +static INT32 SilkwormInit() +{ + tecmo_video_type = 1; + DrvHasADPCM = 1; + adpcm_size = 0x8000; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xc3ff, 0, DrvBackRAM); + ZetMapArea(0xc000, 0xc3ff, 1, DrvBackRAM); + ZetMapArea(0xc400, 0xc7ff, 0, DrvForeRAM); + ZetMapArea(0xc400, 0xc7ff, 1, DrvForeRAM); + ZetMapArea(0xc800, 0xcfff, 0, DrvTextRAM); + ZetMapArea(0xc800, 0xcfff, 1, DrvTextRAM); + ZetMapArea(0xd000, 0xdfff, 0, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 1, DrvZ80RAM0); + ZetMapArea(0xd000, 0xdfff, 2, DrvZ80RAM0); + ZetMapArea(0xe000, 0xe7ff, 0, DrvSprRAM); + ZetMapArea(0xe000, 0xe7ff, 1, DrvSprRAM); + ZetMapArea(0xe800, 0xefff, 0, DrvPalRAM); + ZetSetWriteHandler(rygar_main_write); + ZetSetReadHandler(rygar_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(rygar_sound_write); + ZetSetReadHandler(rygar_sound_read); + ZetMemEnd(); + ZetClose(); + + { + for (INT32 i = 0; i < 2; i++) { + if (BurnLoadRom(DrvZ80ROM0 + i * 0x10000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM1, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 3, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x10000, i + 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x10000, i + 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + i * 0x10000, i + 12, 1)) return 1; + } + + if (BurnLoadRom(DrvSndROM, 16, 1)) return 1; + + DrvGfxDecode(); + } + + BurnYM3812Init(4000000, &TecmoFMIRQHandler, &TecmoSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + MSM5205Init(0, TecmoSynchroniseStream, 400000, TecmoMSM5205Vck, MSM5205_S48_4B, 100, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 GeminiInit() +{ + tecmo_video_type = 2; + DrvHasADPCM = 1; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "backfirt")) DrvHasADPCM = 0; + if (DrvHasADPCM) adpcm_size = 0x8000; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80ROM0); + ZetMapArea(0xc000, 0xcfff, 0, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 1, DrvZ80RAM0); + ZetMapArea(0xc000, 0xcfff, 2, DrvZ80RAM0); + ZetMapArea(0xd000, 0xd7ff, 0, DrvTextRAM); + ZetMapArea(0xd000, 0xd7ff, 1, DrvTextRAM); + ZetMapArea(0xd800, 0xdbff, 0, DrvForeRAM); + ZetMapArea(0xd800, 0xdbff, 1, DrvForeRAM); + ZetMapArea(0xdc00, 0xdfff, 0, DrvBackRAM); + ZetMapArea(0xdc00, 0xdfff, 1, DrvBackRAM); + ZetMapArea(0xe000, 0xe7ff, 0, DrvPalRAM); + ZetMapArea(0xe800, 0xefff, 0, DrvSprRAM); + ZetMapArea(0xe800, 0xefff, 1, DrvSprRAM); + ZetSetWriteHandler(rygar_main_write); + ZetSetReadHandler(rygar_main_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM1); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM1); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM1); + ZetSetWriteHandler(rygar_sound_write); + ZetSetReadHandler(rygar_sound_read); + ZetMemEnd(); + ZetClose(); + + { + for (INT32 i = 0; i < 2; i++) { + if (BurnLoadRom(DrvZ80ROM0 + i * 0x10000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM1, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0, 3, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x10000, i + 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x10000, i + 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + i * 0x10000, i + 12, 1)) return 1; + } + + BurnLoadRom(DrvSndROM, 16, 1); + + DrvGfxDecode(); + } + + BurnYM3812Init(4000000, &TecmoFMIRQHandler, &TecmoSynchroniseStream, 0); + BurnTimerAttachZetYM3812(4000000); + + if (DrvHasADPCM) MSM5205Init(0, TecmoSynchroniseStream, 400000, TecmoMSM5205Vck, MSM5205_S48_4B, 100, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + MSM5205Exit(); + BurnYM3812Exit(); + + GenericTilesExit(); + + ZetExit(); + + BurnFree (AllMem); + + DrvHasADPCM = 0; + + return 0; +} + +static inline INT32 calc_sprite_offset(INT32 code, INT32 x, INT32 y) +{ + INT32 ofst = 0; + if (x & 0x001) ofst |= 0x01; + if (y & 0x001) ofst |= 0x02; + if (x & 0x002) ofst |= 0x04; + if (y & 0x002) ofst |= 0x08; + if (x & 0x004) ofst |= 0x10; + if (y & 0x004) ofst |= 0x20; + + return (ofst + code) & 0x1fff; +} + +static void draw_sprites(INT32 priority) +{ + for (INT32 offs = 0; offs < 0x800; offs += 8) + { + INT32 flags = DrvSprRAM[offs+3]; + if (priority != (flags >> 6)) continue; + + INT32 bank = DrvSprRAM[offs+0]; + + if (bank & 4) + { + INT32 which = DrvSprRAM[offs+1]; + INT32 code, xpos, ypos, flipx, flipy, x, y; + INT32 size = DrvSprRAM[offs + 2] & 3; + + if (tecmo_video_type) + code = which + ((bank & 0xf8) << 5); + else + code = which + ((bank & 0xf0) << 4); + + code &= ~((1 << (size << 1)) - 1); + size = 1 << size; + + xpos = DrvSprRAM[offs + 5] - ((flags & 0x10) << 4); + ypos = DrvSprRAM[offs + 4] - ((flags & 0x20) << 3); + flipx = bank & 1; + flipy = bank & 2; + + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) + { + INT32 sx = xpos + ((flipx ? (size - 1 - x) : x) << 3); + INT32 sy = ypos + ((flipy ? (size - 1 - y) : y) << 3); + sy -= 16; + + if (sy < -7 || sx < -7 || sx > 255 || sy > 223) continue; + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, calc_sprite_offset(code, x, y), sx, sy, flags & 0x0f, 4, 0, 0, DrvGfxROM1); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, calc_sprite_offset(code, x, y), sx, sy, flags & 0x0f, 4, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, calc_sprite_offset(code, x, y), sx, sy, flags & 0x0f, 4, 0, 0, DrvGfxROM1); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, calc_sprite_offset(code, x, y), sx, sy, flags & 0x0f, 4, 0, 0, DrvGfxROM1); + } + } + } + } + } + } +} + +static INT32 draw_layer(UINT8 *vidram, UINT8 *gfx_base, INT32 paloffs, UINT16 *scroll) +{ + for (INT32 offs = 0; offs < 32 * 16; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scroll[0] & 0x1ff; + + if (flipscreen) { + sx += 48 + 256; + } else { + sx -= 48; + } + + if (sx < -15) sx += 0x200; + if (sx > 511) sx -= 0x200; + sy -= scroll[1] + 16; + if (sy < -15) sy += 0x100; + + if (sx > nScreenWidth || sy > nScreenHeight) continue; + + UINT8 color = vidram[0x200 | offs]; + INT32 code = vidram[offs]; + + if (tecmo_video_type == 2) { + color = (color << 4) | (color >> 4); + } + + code |= ((color & 7) << 8); + color >>= 4; + + if (sx < 0 || sy < 0 || sx > nScreenWidth - 16 || sy > nScreenHeight - 16) { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, paloffs, gfx_base); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, paloffs, gfx_base); + } + } + + return 0; +} + +static void draw_text_layer() +{ + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 color = DrvTextRAM[offs | 0x400]; + + INT32 code = DrvTextRAM[offs] | ((color & 3) << 8); + + color >>= 4; + + if (sy < 16 || sy > 239) continue; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy-16, color, 4, 0, 0x100, DrvGfxROM0); + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i+=2) { + palette_write(i); + } + DrvRecalc = 0; + } + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x100; + } + + draw_sprites(3); + + draw_layer(DrvBackRAM, DrvGfxROM3, 0x300, DrvBgScroll); + + draw_sprites(2); + + draw_layer(DrvForeRAM, DrvGfxROM2, 0x200, DrvFgScroll); + + draw_sprites(1); + draw_sprites(0); + + draw_text_layer(); + + if (flipscreen) { + INT32 nSize = (nScreenWidth * nScreenHeight) - 1; + for (INT32 i = 0; i < nSize >> 1; i++) { + INT32 n = pTransDraw[i]; + pTransDraw[i] = pTransDraw[nSize - i]; + pTransDraw[nSize - i] = n; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0, 6); + DrvInputs[10] = 0; + + for (INT32 i = 0; i < 8; i++) { + DrvInputs[ 0] ^= DrvJoy1[i] << i; + DrvInputs[ 1] ^= DrvJoy2[i] << i; + DrvInputs[ 2] ^= DrvJoy3[i] << i; + DrvInputs[ 3] ^= DrvJoy4[i] << i; + DrvInputs[ 4] ^= DrvJoy5[i] << i; + DrvInputs[ 5] ^= DrvJoy6[i] << i; + DrvInputs[10] ^= DrvJoy11[i] << i; + } + } + + ZetNewFrame(); + + INT32 nSegment; + INT32 nInterleave = 10; + if (DrvHasADPCM) nInterleave = MSM5205CalcInterleave(0, 4000000); + INT32 nTotalCycles[2] = { 6000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + nSegment = (nTotalCycles[0] - nCyclesDone[0]) / (nInterleave - i); + + ZetOpen(0); + nCyclesDone[0] += ZetRun(nSegment); + if (i == (nInterleave-1)) ZetRaiseIrq(0); + ZetClose(); + + ZetOpen(1); + if (DrvEnableNmi) { + ZetNmi(); + DrvEnableNmi = 0; + } + BurnTimerUpdateYM3812(i * (nTotalCycles[1] / nInterleave)); + if (DrvHasADPCM) MSM5205Update(); + ZetClose(); + } + + ZetOpen(1); + if (pBurnSoundOut) { + BurnTimerEndFrameYM3812(nTotalCycles[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + if (DrvHasADPCM) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029622; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ba.Data = DrvZ80ROM1 + 0x2000; + ba.nLen = 0x80; + ba.szName = "Sound Z80 RAM"; + BurnAcb(&ba); + + ZetScan(nAction); + BurnYM3812Scan(nAction, pnMin); + if (DrvHasADPCM) MSM5205Scan(nAction, pnMin); + + SCAN_VAR(flipscreen); + SCAN_VAR(soundlatch); + SCAN_VAR(DrvZ80Bank); + + SCAN_VAR(adpcm_pos); + SCAN_VAR(adpcm_end); + } + + ZetOpen(0); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80ROM0 + DrvZ80Bank); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80ROM0 + DrvZ80Bank); + ZetClose(); + + return 0; +} + + +// Rygar (US set 1) + +static struct BurnRomInfo rygarRomDesc[] = { + { "5.5p", 0x08000, 0x062cd55d, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "cpu_5m.bin", 0x04000, 0x7ac5191b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "cpu_5j.bin", 0x08000, 0xed76d606, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "cpu_4h.bin", 0x02000, 0xe4a2fa87, 2 | BRF_PRG | BRF_ESS }, // 3 - Z80 Code + + { "cpu_8k.bin", 0x08000, 0x4d482fb6, 3 | BRF_GRA }, // 4 - Characters + + { "vid_6k.bin", 0x08000, 0xaba6db9e, 4 | BRF_GRA }, // 5 - Sprites + { "vid_6j.bin", 0x08000, 0xae1f2ed6, 4 | BRF_GRA }, // 6 + { "vid_6h.bin", 0x08000, 0x46d9e7df, 4 | BRF_GRA }, // 7 + { "vid_6g.bin", 0x08000, 0x45839c9a, 4 | BRF_GRA }, // 8 + + { "vid_6p.bin", 0x08000, 0x9eae5f8e, 5 | BRF_GRA }, // 9 - Foreground Tiles + { "vid_6o.bin", 0x08000, 0x5a10a396, 5 | BRF_GRA }, // 10 + { "vid_6n.bin", 0x08000, 0x7b12cf3f, 5 | BRF_GRA }, // 11 + { "vid_6l.bin", 0x08000, 0x3cea7eaa, 5 | BRF_GRA }, // 12 + + { "vid_6f.bin", 0x08000, 0x9840edd8, 6 | BRF_GRA }, // 13 - Background Tiles + { "vid_6e.bin", 0x08000, 0xff65e074, 6 | BRF_GRA }, // 14 + { "vid_6c.bin", 0x08000, 0x89868c85, 6 | BRF_GRA }, // 15 + { "vid_6b.bin", 0x08000, 0x35389a7b, 6 | BRF_GRA }, // 16 + + { "cpu_1f.bin", 0x04000, 0x3cc98c5a, 7 | BRF_SND }, // 17 - Samples +}; + +STD_ROM_PICK(rygar) +STD_ROM_FN(rygar) + +struct BurnDriver BurnDrvRygar = { + "rygar", NULL, NULL, NULL, "1986", + "Rygar (US set 1)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, rygarRomInfo, rygarRomName, NULL, NULL, RygarInputInfo, RygarDIPInfo, + RygarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Rygar (US set 2) + +static struct BurnRomInfo rygar2RomDesc[] = { + { "5p.bin", 0x08000, 0x151ffc0b, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "cpu_5m.bin", 0x04000, 0x7ac5191b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "cpu_5j.bin", 0x08000, 0xed76d606, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "cpu_4h.bin", 0x02000, 0xe4a2fa87, 2 | BRF_PRG | BRF_ESS }, // 3 - Z80 Code + + { "cpu_8k.bin", 0x08000, 0x4d482fb6, 3 | BRF_GRA }, // 4 - Characters + + { "vid_6k.bin", 0x08000, 0xaba6db9e, 4 | BRF_GRA }, // 5 - Sprites + { "vid_6j.bin", 0x08000, 0xae1f2ed6, 4 | BRF_GRA }, // 6 + { "vid_6h.bin", 0x08000, 0x46d9e7df, 4 | BRF_GRA }, // 7 + { "vid_6g.bin", 0x08000, 0x45839c9a, 4 | BRF_GRA }, // 8 + + { "vid_6p.bin", 0x08000, 0x9eae5f8e, 5 | BRF_GRA }, // 9 - Foreground Tiles + { "vid_6o.bin", 0x08000, 0x5a10a396, 5 | BRF_GRA }, // 10 + { "vid_6n.bin", 0x08000, 0x7b12cf3f, 5 | BRF_GRA }, // 11 + { "vid_6l.bin", 0x08000, 0x3cea7eaa, 5 | BRF_GRA }, // 12 + + { "vid_6f.bin", 0x08000, 0x9840edd8, 6 | BRF_GRA }, // 13 - Background Tiles + { "vid_6e.bin", 0x08000, 0xff65e074, 6 | BRF_GRA }, // 14 + { "vid_6c.bin", 0x08000, 0x89868c85, 6 | BRF_GRA }, // 15 + { "vid_6b.bin", 0x08000, 0x35389a7b, 6 | BRF_GRA }, // 16 + + { "cpu_1f.bin", 0x04000, 0x3cc98c5a, 7 | BRF_SND }, // 17 - Samples +}; + +STD_ROM_PICK(rygar2) +STD_ROM_FN(rygar2) + +struct BurnDriver BurnDrvRygar2 = { + "rygar2", "rygar", NULL, NULL, "1986", + "Rygar (US set 2)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, rygar2RomInfo, rygar2RomName, NULL, NULL, RygarInputInfo, RygarDIPInfo, + RygarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Rygar (US set 3, old version) + +static struct BurnRomInfo rygar3RomDesc[] = { + { "cpu_5p.bin", 0x08000, 0xe79c054a, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "cpu_5m.bin", 0x04000, 0x7ac5191b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "cpu_5j.bin", 0x08000, 0xed76d606, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "cpu_4h.bin", 0x02000, 0xe4a2fa87, 2 | BRF_PRG | BRF_ESS }, // 3 - Z80 Code + + { "cpu_8k.bin", 0x08000, 0x4d482fb6, 3 | BRF_GRA }, // 4 - Characters + + { "vid_6k.bin", 0x08000, 0xaba6db9e, 4 | BRF_GRA }, // 5 - Sprites + { "vid_6j.bin", 0x08000, 0xae1f2ed6, 4 | BRF_GRA }, // 6 + { "vid_6h.bin", 0x08000, 0x46d9e7df, 4 | BRF_GRA }, // 7 + { "vid_6g.bin", 0x08000, 0x45839c9a, 4 | BRF_GRA }, // 8 + + { "vid_6p.bin", 0x08000, 0x9eae5f8e, 5 | BRF_GRA }, // 9 - Foreground Tiles + { "vid_6o.bin", 0x08000, 0x5a10a396, 5 | BRF_GRA }, // 10 + { "vid_6n.bin", 0x08000, 0x7b12cf3f, 5 | BRF_GRA }, // 11 + { "vid_6l.bin", 0x08000, 0x3cea7eaa, 5 | BRF_GRA }, // 12 + + { "vid_6f.bin", 0x08000, 0x9840edd8, 6 | BRF_GRA }, // 13 - Background Tiles + { "vid_6e.bin", 0x08000, 0xff65e074, 6 | BRF_GRA }, // 14 + { "vid_6c.bin", 0x08000, 0x89868c85, 6 | BRF_GRA }, // 15 + { "vid_6b.bin", 0x08000, 0x35389a7b, 6 | BRF_GRA }, // 16 + + { "cpu_1f.bin", 0x04000, 0x3cc98c5a, 7 | BRF_SND }, // 17 - Samples +}; + +STD_ROM_PICK(rygar3) +STD_ROM_FN(rygar3) + +struct BurnDriver BurnDrvRygar3 = { + "rygar3", "rygar", NULL, NULL, "1986", + "Rygar (US set 3, old version)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, rygar3RomInfo, rygar3RomName, NULL, NULL, RygarInputInfo, RygarDIPInfo, + RygarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Argus no Senshi (Japan) + +static struct BurnRomInfo rygarjRomDesc[] = { + { "cpuj_5p.bin",0x08000, 0xb39698ba, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "cpuj_5m.bin",0x04000, 0x3f180979, 1 | BRF_PRG | BRF_ESS }, // 1 + { "cpuj_5j.bin",0x08000, 0x69e44e8f, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "cpu_4h.bin", 0x02000, 0xe4a2fa87, 2 | BRF_PRG | BRF_ESS }, // 3 - Z80 Code + + { "cpuj_8k.bin",0x08000, 0x45047707, 3 | BRF_GRA }, // 4 - Characters + + { "vid_6k.bin", 0x08000, 0xaba6db9e, 4 | BRF_GRA }, // 5 - Sprites + { "vid_6j.bin", 0x08000, 0xae1f2ed6, 4 | BRF_GRA }, // 6 + { "vid_6h.bin", 0x08000, 0x46d9e7df, 4 | BRF_GRA }, // 7 + { "vid_6g.bin", 0x08000, 0x45839c9a, 4 | BRF_GRA }, // 8 + + { "vid_6p.bin", 0x08000, 0x9eae5f8e, 5 | BRF_GRA }, // 9 - Foreground Tiles + { "vid_6o.bin", 0x08000, 0x5a10a396, 5 | BRF_GRA }, // 10 + { "vid_6n.bin", 0x08000, 0x7b12cf3f, 5 | BRF_GRA }, // 11 + { "vid_6l.bin", 0x08000, 0x3cea7eaa, 5 | BRF_GRA }, // 12 + + { "vid_6f.bin", 0x08000, 0x9840edd8, 6 | BRF_GRA }, // 13 - Background Tiles + { "vid_6e.bin", 0x08000, 0xff65e074, 6 | BRF_GRA }, // 14 + { "vid_6c.bin", 0x08000, 0x89868c85, 6 | BRF_GRA }, // 15 + { "vid_6b.bin", 0x08000, 0x35389a7b, 6 | BRF_GRA }, // 16 + + { "cpu_1f.bin", 0x04000, 0x3cc98c5a, 7 | BRF_SND }, // 17 - Samples +}; + +STD_ROM_PICK(rygarj) +STD_ROM_FN(rygarj) + +struct BurnDriver BurnDrvRygarj = { + "rygarj", "rygar", NULL, NULL, "1986", + "Argus no Senshi (Japan)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, rygarjRomInfo, rygarjRomName, NULL, NULL, RygarInputInfo, RygarDIPInfo, + RygarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Silk Worm (set 1) + +static struct BurnRomInfo silkwormRomDesc[] = { + { "silkworm.4", 0x10000, 0xa5277cce, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "silkworm.5", 0x10000, 0xa6c7bb51, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "silkworm.3", 0x08000, 0xb589f587, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "silkworm.2", 0x08000, 0xe80a1cd9, 3 | BRF_GRA }, // 3 - Characters + + { "silkworm.6", 0x10000, 0x1138d159, 4 | BRF_GRA }, // 4 - Sprites + { "silkworm.7", 0x10000, 0xd96214f7, 4 | BRF_GRA }, // 5 + { "silkworm.8", 0x10000, 0x0494b38e, 4 | BRF_GRA }, // 6 + { "silkworm.9", 0x10000, 0x8ce3cdf5, 4 | BRF_GRA }, // 7 + + { "silkworm.10", 0x10000, 0x8c7138bb, 5 | BRF_GRA }, // 8 - Foreground Tiles + { "silkworm.11", 0x10000, 0x6c03c476, 5 | BRF_GRA }, // 9 + { "silkworm.12", 0x10000, 0xbb0f568f, 5 | BRF_GRA }, // 10 + { "silkworm.13", 0x10000, 0x773ad0a4, 5 | BRF_GRA }, // 11 + + { "silkworm.14", 0x10000, 0x409df64b, 6 | BRF_GRA }, // 12 - Background Tiles + { "silkworm.15", 0x10000, 0x6e4052c9, 6 | BRF_GRA }, // 13 + { "silkworm.16", 0x10000, 0x9292ed63, 6 | BRF_GRA }, // 14 + { "silkworm.17", 0x10000, 0x3fa4563d, 6 | BRF_GRA }, // 15 + + { "silkworm.1", 0x08000, 0x5b553644, 7 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(silkworm) +STD_ROM_FN(silkworm) + +struct BurnDriver BurnDrvSilkworm = { + "silkworm", NULL, NULL, NULL, "1988", + "Silk Worm\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, silkwormRomInfo, silkwormRomName, NULL, NULL, SilkwormInputInfo, SilkwormDIPInfo, + SilkwormInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Silk Worm (set 1) + +static struct BurnRomInfo silkwrmjRomDesc[] = { + { "silkwormj.4", 0x10000, 0x6df3df22, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "silkworm.5", 0x10000, 0xa6c7bb51, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "silkwormj.3", 0x08000, 0xb79848d0, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "silkworm.2", 0x08000, 0xe80a1cd9, 3 | BRF_GRA }, // 3 - Characters + + { "silkworm.6", 0x10000, 0x1138d159, 4 | BRF_GRA }, // 4 - Sprites + { "silkworm.7", 0x10000, 0xd96214f7, 4 | BRF_GRA }, // 5 + { "silkworm.8", 0x10000, 0x0494b38e, 4 | BRF_GRA }, // 6 + { "silkworm.9", 0x10000, 0x8ce3cdf5, 4 | BRF_GRA }, // 7 + + { "silkworm.10", 0x10000, 0x8c7138bb, 5 | BRF_GRA }, // 8 - Foreground Tiles + { "silkworm.11", 0x10000, 0x6c03c476, 5 | BRF_GRA }, // 9 + { "silkworm.12", 0x10000, 0xbb0f568f, 5 | BRF_GRA }, // 10 + { "silkworm.13", 0x10000, 0x773ad0a4, 5 | BRF_GRA }, // 11 + + { "silkworm.14", 0x10000, 0x409df64b, 6 | BRF_GRA }, // 12 - Background Tiles + { "silkworm.15", 0x10000, 0x6e4052c9, 6 | BRF_GRA }, // 13 + { "silkworm.16", 0x10000, 0x9292ed63, 6 | BRF_GRA }, // 14 + { "silkworm.17", 0x10000, 0x3fa4563d, 6 | BRF_GRA }, // 15 + + { "silkworm.1", 0x08000, 0x5b553644, 7 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(silkwrmj) +STD_ROM_FN(silkwrmj) + +struct BurnDriver BurnDrvSilkwrmj = { + "silkwormj", "silkworm", NULL, NULL, "1988", + "Silk Worm (Japan)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, silkwrmjRomInfo, silkwrmjRomName, NULL, NULL, SilkwormInputInfo, SilkwormDIPInfo, + SilkwormInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Back Fire (Tecmo) (Japan, Bootleg, Prototype?) + +static struct BurnRomInfo backfirtRomDesc[] = { + { "b5-e3.bin", 0x10000, 0x0ab3bd4d, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "b4-f3.bin", 0x10000, 0x150B6949, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b2-e10.bin", 0x08000, 0x9b2ac54f, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "b3-c10.bin", 0x08000, 0x08ce729f, 3 | BRF_GRA }, // 3 - Characters + + { "b6-c2.bin", 0x10000, 0xc8c25e45, 4 | BRF_GRA }, // 4 - Sprites + { "b7-d2.bin", 0x10000, 0x25fb6a57, 4 | BRF_GRA }, // 5 + { "b8-e2.bin", 0x10000, 0x6bccac4e, 4 | BRF_GRA }, // 6 + { "b9-h2.bin", 0x10000, 0x566a99b8, 4 | BRF_GRA }, // 7 + + { "b13-p1.bin", 0x10000, 0x8c7138bb, 5 | BRF_GRA }, // 8 - Foreground Tiles + { "b12-p2.bin", 0x10000, 0x6c03c476, 5 | BRF_GRA }, // 9 + { "b11-p2.bin", 0x10000, 0x0bc84b4b, 5 | BRF_GRA }, // 10 + { "b10-p3.bin", 0x10000, 0xec149ec3, 5 | BRF_GRA }, // 11 + + { "b17-s1.bin", 0x10000, 0x409df64b, 6 | BRF_GRA }, // 12 - Background Tiles + { "b16-s2.bin", 0x10000, 0x6e4052c9, 6 | BRF_GRA }, // 13 + { "b15-s2.bin", 0x10000, 0x2b6cc20e, 6 | BRF_GRA }, // 14 + { "b14-s3.bin", 0x08000, 0x4d29637a, 6 | BRF_GRA }, // 15 +}; + +STD_ROM_PICK(backfirt) +STD_ROM_FN(backfirt) + +struct BurnDriver BurnDrvbackfirt = { + "backfirt", NULL, NULL, NULL, "1988", + "Back Fire (Tecmo) (Japan, Bootleg, Prototype?)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_HORSHOOT, 0, + NULL, backfirtRomInfo, backfirtRomName, NULL, NULL, BackfirtInputInfo, BackfirtDIPInfo, + GeminiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 256, 224, 4, 3 +}; + + +// Gemini Wing + +static struct BurnRomInfo geminiRomDesc[] = { + { "gw04-5s.rom", 0x10000, 0xff9de855, 1 | BRF_PRG | BRF_ESS }, // 0 - Z80 Code + { "gw05-6s.rom", 0x10000, 0x5a6947a9, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "gw03-5h.rom", 0x08000, 0x9bc79596, 2 | BRF_PRG | BRF_ESS }, // 2 - Z80 Code + + { "gw02-3h.rom", 0x08000, 0x7acc8d35, 3 | BRF_GRA }, // 3 - Characters + + { "gw06-1c.rom", 0x10000, 0x4ea51631, 4 | BRF_GRA }, // 4 - Sprites + { "gw07-1d.rom", 0x10000, 0xda42637e, 4 | BRF_GRA }, // 5 + { "gw08-1f.rom", 0x10000, 0x0b4e8d70, 4 | BRF_GRA }, // 6 + { "gw09-1h.rom", 0x10000, 0xb65c5e4c, 4 | BRF_GRA }, // 7 + + { "gw10-1n.rom", 0x10000, 0x5e84cd4f, 5 | BRF_GRA }, // 8 - Foreground Tiles + { "gw11-2na.rom", 0x10000, 0x08b458e1, 5 | BRF_GRA }, // 9 + { "gw12-2nb.rom", 0x10000, 0x229c9714, 5 | BRF_GRA }, // 10 + { "gw13-3n.rom", 0x10000, 0xc5dfaf47, 5 | BRF_GRA }, // 11 + + { "gw14-1r.rom", 0x10000, 0x9c10e5b5, 6 | BRF_GRA }, // 12 - Background Tiles + { "gw15-2ra.rom", 0x10000, 0x4cd18cfa, 6 | BRF_GRA }, // 13 + { "gw16-2rb.rom", 0x10000, 0xf911c7be, 6 | BRF_GRA }, // 14 + { "gw17-3r.rom", 0x10000, 0x79a9ce25, 6 | BRF_GRA }, // 15 + + { "gw01-6a.rom", 0x08000, 0xd78afa05, 7 | BRF_SND }, // 16 - Samples +}; + +STD_ROM_PICK(gemini) +STD_ROM_FN(gemini) + +struct BurnDriver BurnDrvGemini = { + "gemini", NULL, NULL, NULL, "1987", + "Gemini Wing\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, geminiRomInfo, geminiRomName, NULL, NULL, GeminiInputInfo, GeminiDIPInfo, + GeminiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_tigerheli.cpp b/src/burn/drivers/misc_pre90s/d_tigerheli.cpp new file mode 100644 index 00000000..33deb0a8 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_tigerheli.cpp @@ -0,0 +1,2942 @@ +// Tiger Heli, Get Star / Guardian, & Slap Fight + +#include "burnint.h" +#include "taito_m68705.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { + #include "ay8910.h" +} + +static INT32 nWhichGame; + +static bool bInterruptEnable; +static bool bSoundCPUEnable; +static bool bSoundNMIEnable; + +static INT32 nStatusIndex; +static INT32 nProtectIndex; + +static UINT8 getstar_e803_r(); +static void getstar_e803_w(); + +// --------------------------------------------------------------------------- +// Inputs + +static UINT8 tigerhInput[4] = {0,0,0,0}; +static UINT8 tigerhInpJoy1[8]; +static UINT8 tigerhInpMisc[8]; +static UINT8 tigerhReset = 0; + +// Dip Switch and Input Definitions +static struct BurnInputInfo tigerhInputList[] = { + {"P1 Coin", BIT_DIGITAL, tigerhInpMisc + 6, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, tigerhInpMisc + 4, "p1 start"}, + {"P1 Up", BIT_DIGITAL, tigerhInpJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, tigerhInpJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, tigerhInpJoy1 + 3, "p1 left"}, + {"P1 Right", BIT_DIGITAL, tigerhInpJoy1 + 2, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, tigerhInpMisc + 1, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, tigerhInpMisc + 0, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, tigerhInpMisc + 7, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, tigerhInpMisc + 5, "p2 start"}, + {"P2 Up", BIT_DIGITAL, tigerhInpJoy1 + 4, "p2 up"}, + {"P2 Down", BIT_DIGITAL, tigerhInpJoy1 + 5, "p2 down"}, + {"P2 Left", BIT_DIGITAL, tigerhInpJoy1 + 7, "p2 left"}, + {"P2 Right", BIT_DIGITAL, tigerhInpJoy1 + 6, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, tigerhInpMisc + 3, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, tigerhInpMisc + 2, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &tigerhReset, "reset"}, + + {"Dip A", BIT_DIPSWITCH, tigerhInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, tigerhInput + 3, "dip"}, +}; + +STDINPUTINFO(tigerh) + +static struct BurnInputInfo getstarInputList[] = { + {"P1 Coin", BIT_DIGITAL, tigerhInpMisc + 6, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, tigerhInpMisc + 4, "p1 start"}, + {"P1 Up", BIT_DIGITAL, tigerhInpJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, tigerhInpJoy1 + 2, "p1 down"}, + {"P1 Left", BIT_DIGITAL, tigerhInpJoy1 + 3, "p1 left"}, + {"P1 Right", BIT_DIGITAL, tigerhInpJoy1 + 1, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, tigerhInpMisc + 1, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, tigerhInpMisc + 0, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, tigerhInpMisc + 7, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, tigerhInpMisc + 5, "p2 start"}, + {"P2 Up", BIT_DIGITAL, tigerhInpJoy1 + 4, "p2 up"}, + {"P2 Down", BIT_DIGITAL, tigerhInpJoy1 + 6, "p2 down"}, + {"P2 Left", BIT_DIGITAL, tigerhInpJoy1 + 7, "p2 left"}, + {"P2 Right", BIT_DIGITAL, tigerhInpJoy1 + 5, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, tigerhInpMisc + 3, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, tigerhInpMisc + 2, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &tigerhReset, "reset"}, + + {"Dip A", BIT_DIPSWITCH, tigerhInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, tigerhInput + 3, "dip"}, +}; + +STDINPUTINFO(getstar) + +static struct BurnDIPInfo tigerhDIPList[] = { + // Defaults + {0x11, 0xFF, 0xFF, 0x10, NULL}, + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP A + {0, 0xFE, 0, 2, "Hero speed"}, + {0x11, 0x01, 0x80, 0x00, "Normal"}, + {0x11, 0x01, 0x80, 0x80, "Fast"}, + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x40, 0x00, "Normal game"}, + {0x11, 0x01, 0x40, 0x40, "DIP switch test"}, + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x20, 0x00, "Normal screen"}, + {0x11, 0x01, 0x20, 0x20, "Invert screen"}, + {0, 0xFE, 0, 2, "Cabinet"}, + {0x11, 0x01, 0x10, 0x10, "Upright"}, + {0x11, 0x01, 0x10, 0x00, "Table"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x11, 0x01, 0x08, 0x00, "On"}, + {0x11, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 7, "Coinage"}, + {0x11, 0x01, 0x07, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x07, 0x01, "1 coin 2 credits"}, + {0x11, 0x01, 0x07, 0x02, "1 coin 3 credits"}, + {0x11, 0x01, 0x07, 0x03, "2 coins 1 credit"}, + {0x11, 0x01, 0x07, 0x04, "2 coins 3 credits"}, + {0x11, 0x01, 0x07, 0x05, "3 coins 1 credit"}, + {0x11, 0x01, 0x07, 0x07, "Free play"}, + {0x11, 0x01, 0x07, 0x06, "3 coins 1 credit"}, + + // DIP B + {0, 0xFE, 0, 2, "Extend"}, + {0x12, 0x01, 0x10, 0x00, "20000 & 80000"}, + {0x12, 0x01, 0x10, 0x10, "50000 & 120000"}, + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x12, 0x01, 0x0C, 0x00, "0"}, + {0x12, 0x01, 0x0C, 0x04, "1"}, + {0x12, 0x01, 0x0C, 0x08, "2"}, + {0x12, 0x01, 0x0C, 0x0C, "3"}, + {0, 0xFE, 0, 4, "Number of heroes"}, + {0x12, 0x01, 0x03, 0x00, "3"}, + {0x12, 0x01, 0x03, 0x01, "5"}, + {0x12, 0x01, 0x03, 0x02, "1"}, + {0x12, 0x01, 0x03, 0x03, "2"}, +}; + +STDDIPINFO(tigerh) + +static struct BurnDIPInfo getstarDIPList[] = { + // Defaults + {0x11, 0xFF, 0xFF, 0x10, NULL}, + + // DIP A + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x40, 0x00, "Normal game"}, + {0x11, 0x01, 0x40, 0x40, "DIP switch test"}, + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x20, 0x00, "Normal screen"}, + {0x11, 0x01, 0x20, 0x20, "Invert screen"}, + {0, 0xFE, 0, 2, "Cabinet"}, + {0x11, 0x01, 0x10, 0x10, "Upright"}, + {0x11, 0x01, 0x10, 0x00, "Table"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x11, 0x01, 0x08, 0x00, "On"}, + {0x11, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 7, "Coinage"}, + {0x11, 0x01, 0x07, 0x00, "1 coin 1 credit"}, + {0x11, 0x01, 0x07, 0x01, "1 coin 2 credits"}, + {0x11, 0x01, 0x07, 0x02, "1 coin 3 credits"}, + {0x11, 0x01, 0x07, 0x03, "2 coins 1 credit"}, + {0x11, 0x01, 0x07, 0x04, "2 coins 3 credits"}, + {0x11, 0x01, 0x07, 0x05, "3 coins 1 credit"}, + {0x11, 0x01, 0x07, 0x07, "Free play"}, + {0x11, 0x01, 0x07, 0x06, "3 coins 1 credit"}, + + // DIP B + {0, 0xFE, 0, 2, "Extend"}, + {0x12, 0x01, 0x10, 0x00, "30000 & 100000"}, + {0x12, 0x01, 0x10, 0x10, "50000 & 150000"}, + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x12, 0x01, 0x0C, 0x00, "0"}, + {0x12, 0x01, 0x0C, 0x04, "1"}, + {0x12, 0x01, 0x0C, 0x08, "2"}, + {0x12, 0x01, 0x0C, 0x0C, "3"}, +}; + +static struct BurnDIPInfo getstarHeroesDIPList[] = +{ + // Defaults + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP B + {0, 0xFE, 0, 4, "Number of heroes"}, + {0x12, 0x01, 0x03, 0x02, "1"}, + {0x12, 0x01, 0x03, 0x03, "2"}, + {0x12, 0x01, 0x03, 0x00, "3"}, + {0x12, 0x01, 0x03, 0x01, "5"}, +}; + +static struct BurnDIPInfo getstarb2HeroesDIPList[] = +{ + // Defaults + {0x12, 0xFF, 0xFF, 0x01, NULL}, + + // DIP B + {0, 0xFE, 0, 4, "Number of heroes"}, + {0x12, 0x01, 0x03, 0x01, "3"}, + {0x12, 0x01, 0x03, 0x02, "4"}, + {0x12, 0x01, 0x03, 0x03, "5"}, + {0x12, 0x01, 0x03, 0x00, "240 (cheat)"}, +}; + +STDDIPINFOEXT(getstar, getstar, getstarHeroes) +STDDIPINFOEXT(getstarb2, getstar, getstarb2Heroes) + +static struct BurnDIPInfo slapfighDIPList[] = { + // Defaults + {0x11, 0xFF, 0xFF, 0x80, NULL}, + {0x12, 0xFF, 0xFF, 0x00, NULL}, + + // DIP A + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x80, 0x80, "Up-right type"}, + {0x11, 0x01, 0x80, 0x00, "Table type"}, + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x40, 0x00, "Normal screen"}, + {0x11, 0x01, 0x40, 0x40, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x11, 0x01, 0x20, 0x00, "Normal game"}, + {0x11, 0x01, 0x20, 0x20, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x11, 0x01, 0x10, 0x00, "On"}, + {0x11, 0x01, 0x10, 0x10, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x11, 0x01, 0x0C, 0x00, "1 coin 1 play"}, + {0x11, 0x01, 0x0C, 0x08, "1 coin 2 plays"}, + {0x11, 0x01, 0x0C, 0x04, "2 coins 1 play"}, + {0x11, 0x01, 0x0C, 0x0C, "2 coins 3 plays"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x11, 0x01, 0x03, 0x00, "1 coin 1 play"}, + {0x11, 0x01, 0x03, 0x02, "1 coin 2 plays"}, + {0x11, 0x01, 0x03, 0x01, "2 coins 1 play"}, + {0x11, 0x01, 0x03, 0x03, "2 coins 3 plays"}, + + // DIP B + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x12, 0x01, 0xC0, 0x00, "B"}, + {0x12, 0x01, 0xC0, 0x80, "A"}, + {0x12, 0x01, 0xC0, 0x40, "C"}, + {0x12, 0x01, 0xC0, 0xC0, "D"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x12, 0x01, 0x30, 0x00, "30000, 100000"}, + {0x12, 0x01, 0x30, 0x20, "50000, 200000"}, + {0x12, 0x01, 0x30, 0x10, "50000 only"}, + {0x12, 0x01, 0x30, 0x30, "100000 only"}, + {0, 0xFE, 0, 4, "Fighter counts"}, + {0x12, 0x01, 0x0C, 0x00, "3"}, + {0x12, 0x01, 0x0C, 0x08, "5"}, + {0x12, 0x01, 0x0C, 0x04, "1"}, + {0x12, 0x01, 0x0C, 0x0C, "2"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal game"}, + {0x12, 0x01, 0x02, 0x02, "DIP-switch display"}, +}; + +STDDIPINFO(slapfigh) + +// --------------------------------------------------------------------------- + +static UINT8 *Mem, *MemEnd, *RamStart, *RamEnd; + +static UINT8 *Rom01, *Rom02, *Rom03; +static UINT8 *TigerHeliTileROM, *TigerHeliSpriteROM, *TigerHeliTextROM; + +static UINT8 *Ram01, *RamShared, *Ram03; +static UINT8 *TigerHeliTileRAM, *TigerHeliSpriteRAM, *TigerHeliSpriteBuf, *TigerHeliTextRAM; + +static UINT8* TigerHeliPaletteROM; +static UINT32* TigerHeliPalette; + +static INT16* pFMBuffer; +static INT16* pAY8910Buffer[6]; + +static INT32 use_mcu = 0; + +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + Rom01 = Next; Next += 0x012000; // Z80 main program + Rom02 = Next; Next += 0x002000; // Z80 sound program + Rom03 = Next; Next += 0x000800; // m68705 mcu program + TigerHeliTextROM = Next; Next += 0x010000; + TigerHeliSpriteROM = Next; Next += 0x040000; + TigerHeliTileROM = Next; Next += 0x040000; + RamStart = Next; + Ram01 = Next; Next += 0x000800; // Z80 main work RAM + RamShared = Next; Next += 0x000800; // Shared RAM + TigerHeliTextRAM = Next; Next += 0x001000; + TigerHeliSpriteRAM = Next; Next += 0x000800; + TigerHeliSpriteBuf = Next; Next += 0x000800; + TigerHeliTileRAM = Next; Next += 0x001000; + Ram03 = Next; Next += 0x000080; + RamEnd = Next; + pFMBuffer = (INT16*)Next; Next += nBurnSoundLen * 6 * sizeof(INT16); + TigerHeliPaletteROM = Next; Next += 0x000300; + TigerHeliPalette = (UINT32*)Next; Next += 0x000100 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// --------------------------------------------------------------------------- +// Graphics + +static INT32 nTigerHeliTileXPosLo, nTigerHeliTileXPosHi, nTigerHeliTileYPosLo; +static INT32 nTigerHeliTileMask; + +static UINT8* pTileData; + +static INT32 nTileNumber; +static INT32 nTilePalette; + +static UINT16* pTileRow; +static UINT16* pTile; + +static INT32 nTileXPos, nTileYPos; + +// --------------------------------------------------------------------------- +// Palette + +static UINT8 tigerhRecalcPalette = 0; + +static void TigerHeliPaletteInit() +{ + for (INT32 i = 0; i < 0x0100; i++) { + INT32 r, g, b; + + r = TigerHeliPaletteROM[i + 0x0000]; // Red + r |= r << 4; + g = TigerHeliPaletteROM[i + 0x0100]; // Green + g |= g << 4; + b = TigerHeliPaletteROM[i + 0x0200]; // Blue + b |= b << 4; + + TigerHeliPalette[i] = BurnHighCol(r, g, b, 0); + } + + return; +} + +static void TigerHeliPaletteUpdate() +{ + if (tigerhRecalcPalette) { + tigerhRecalcPalette = 0; + + TigerHeliPaletteInit(); + } +} + +// --------------------------------------------------------------------------- +// Text layer + +static UINT8* TigerHeliTextAttrib = NULL; + +static void TigerHeliTextExit() +{ + BurnFree(TigerHeliTextAttrib); +} + +static INT32 TigerHeliTextInit() +{ + if ((TigerHeliTextAttrib = (UINT8*)BurnMalloc(0x0400)) == NULL) { + return 1; + } + + for (INT32 i = 0; i < 0x0400; i++) { + bool bEmpty = true; + + for (INT32 j = 0; j < 64; j++) { + if (TigerHeliTextROM[(i << 6) + j]) { + bEmpty = false; + break; + } + } + + if (bEmpty) { + TigerHeliTextAttrib[i] = 0; + } else { + TigerHeliTextAttrib[i] = 1; + } + } + + return 0; +} + +#define PLOTPIXEL(x) if (pTileData[x]) { pPixel[x] = nPalette + pTileData[x]; } + +static void TigerHeliRenderTextTile() +{ + UINT16 nPalette = nTilePalette << 2; + pTileData = TigerHeliTextROM + (nTileNumber << 6); + + UINT16* pPixel = pTile; + + for (INT32 y = 0; y < 8; y++, pPixel += 280, pTileData += 8) { + + if ((nTileYPos + y) >= 240) { + break; + } + if ((nTileYPos + y) < 0) { + continue; + } + + PLOTPIXEL(0); + PLOTPIXEL(1); + PLOTPIXEL(2); + PLOTPIXEL(3); + PLOTPIXEL(4); + PLOTPIXEL(5); + PLOTPIXEL(6); + PLOTPIXEL(7); + } +} + +#undef PLOTPIXEL + +static void TigerHeliTextRender() +{ + UINT8* pTextRAM; + + if ((nBurnLayer & 2) == 0) { + return; + } + + switch (nWhichGame) { + case 0: // Tiger Heli + nTileYPos = -15; + break; + case 1: // Get Star + nTileYPos = -15; + break; + case 2: // Slap Fight + nTileYPos = -16; + break; + } + pTileRow = pTransDraw + nTileYPos * 280; + + for (INT32 y = 0; y < 32; y++, nTileYPos += 8, pTileRow += (280 << 3)) { + if (nTileYPos <= -8 || nTileYPos >= 240 ) { + continue; + } + pTextRAM = TigerHeliTextRAM + (y << 6); + pTile = pTileRow; + for (INT32 x = 1; x < 36; x++, pTile += 8) { + nTileNumber = pTextRAM[x] | (pTextRAM[0x0800 + x] << 8); + nTilePalette = nTileNumber >> 10; + nTileNumber &= 0x03FF; + + if (TigerHeliTextAttrib[nTileNumber]) { + TigerHeliRenderTextTile(); + } + } + } + + return; +} + +// --------------------------------------------------------------------------- +// Tile layer + +static void TigerHeliTileExit() +{ + return; +} + +static INT32 TigerHeliTileInit() +{ + return 0; +} + +#define PLOTPIXEL(x) pPixel[x] = nPalette + pTileData[x]; +#define CLIPPIXEL(a,b) if ((nTileXPos + a) >= 0 && (nTileXPos + a) < 280) { b; } + +static void TigerHeliRenderTileNoClip() +{ + UINT8 nPalette = nTilePalette << 4; + pTileData = TigerHeliTileROM + (nTileNumber << 6); + + UINT16* pPixel = pTile; + + for (INT32 y = 0; y < 8; y++, pPixel += 280, pTileData += 8) { + PLOTPIXEL(0); + PLOTPIXEL(1); + PLOTPIXEL(2); + PLOTPIXEL(3); + PLOTPIXEL(4); + PLOTPIXEL(5); + PLOTPIXEL(6); + PLOTPIXEL(7); + } +} + +static void TigerHeliRenderTileClip() +{ + UINT8 nPalette = nTilePalette << 4; + pTileData = TigerHeliTileROM + (nTileNumber << 6); + + UINT16* pPixel = pTile; + + for (INT32 y = 0; y < 8; y++, pPixel += 280, pTileData += 8) { + + if ((nTileYPos + y) >= 240) { + break; + } + if ((nTileYPos + y) < 0) { + continue; + } + + CLIPPIXEL(0, PLOTPIXEL(0)); + CLIPPIXEL(1, PLOTPIXEL(1)); + CLIPPIXEL(2, PLOTPIXEL(2)); + CLIPPIXEL(3, PLOTPIXEL(3)); + CLIPPIXEL(4, PLOTPIXEL(4)); + CLIPPIXEL(5, PLOTPIXEL(5)); + CLIPPIXEL(6, PLOTPIXEL(6)); + CLIPPIXEL(7, PLOTPIXEL(7)); + } +} + +#undef CLIPPIXEL +#undef PLOTPIXEL + +static void TigerHeliTileRender() +{ + UINT8* pTileRAM; + + if ((nBurnLayer & 3) == 0) { + BurnTransferClear(); + return; + } + + INT32 nTigerHeliTileXPos = nTigerHeliTileXPosLo + (nTigerHeliTileXPosHi << 8); + INT32 nTigerHeliTileYPos = nTigerHeliTileYPosLo; + + switch (nWhichGame) { + case 0: // Tiger Heli + nTigerHeliTileYPos -= 1; + break; + case 1: // Get Star + nTigerHeliTileYPos -= 1; + break; + case 2: // Slap Fight + nTigerHeliTileYPos += 1; + break; + } + + INT32 nXPos = -nTigerHeliTileXPos & 7; + nTileYPos = -nTigerHeliTileYPos & 7; + + if (nTigerHeliTileXPos & 7) { + nXPos -= 8; + } + if (nTigerHeliTileYPos & 7) { + nTileYPos -= 8; + } + + pTileRow = pTransDraw; + pTileRow -= (nTigerHeliTileXPos & 7); + pTileRow -= (nTigerHeliTileYPos & 7) * 280; + + for (INT32 y = 2; y < 33; y++, nTileYPos += 8, pTileRow += (280 << 3)) { + pTileRAM = TigerHeliTileRAM + (((y + (nTigerHeliTileYPos >> 3)) << 6) & 0x07C0); + pTile = pTileRow; + nTileXPos = nXPos; + for (INT32 x = 1; x < 37; x++, nTileXPos += 8, pTile += 8) { + INT32 x2 = (x + ((nTigerHeliTileXPos >> 3) & 0x3F)); + nTileNumber = pTileRAM[x2] | (pTileRAM[0x0800 + x2] << 8); + nTilePalette = nTileNumber >> 12; + nTileNumber &= nTigerHeliTileMask; + + if (nTileXPos < 0 || nTileXPos > 272 || nTileYPos < 0 || nTileYPos > 232) { + TigerHeliRenderTileClip(); + } else { + TigerHeliRenderTileNoClip(); + } + } + } + + return; +} + +// --------------------------------------------------------------------------- +// Sprites + +static INT32 nSpriteXPos, nSpriteYPos, nSpriteNumber, nSpritePalette; + +static INT32 nTigerHeliSpriteMask; + +static void TigerHeliSpriteExit() +{ + return; +} + +static INT32 TigerHeliSpriteInit() +{ + return 0; +} + +#define PLOTPIXEL(a) if (pSpriteData[a]) { pPixel[a] = nPalette + pSpriteData[a]; } +#define CLIPPIXEL(a,b) if ((nSpriteXPos + a) >= 0 && (nSpriteXPos + a) < 280) { b; } + +static void TigerHeliRenderSpriteNoClip() +{ + UINT8 nPalette = nSpritePalette << 4; + UINT8* pSpriteData = TigerHeliSpriteROM + (nSpriteNumber << 8); + + UINT16* pPixel = pTransDraw + nSpriteXPos + nSpriteYPos * 280; + + for (INT32 y = 0; y < 16; y++, pPixel += 280, pSpriteData += 16) { + PLOTPIXEL( 0); + PLOTPIXEL( 1); + PLOTPIXEL( 2); + PLOTPIXEL( 3); + PLOTPIXEL( 4); + PLOTPIXEL( 5); + PLOTPIXEL( 6); + PLOTPIXEL( 7); + PLOTPIXEL( 8); + PLOTPIXEL( 9); + PLOTPIXEL(10); + PLOTPIXEL(11); + PLOTPIXEL(12); + PLOTPIXEL(13); + PLOTPIXEL(14); + PLOTPIXEL(15); + } +} + +static void TigerHeliRenderSpriteClip() +{ + UINT8 nPalette = nSpritePalette << 4; + UINT8* pSpriteData = TigerHeliSpriteROM + (nSpriteNumber << 8); + + UINT16* pPixel = pTransDraw + nSpriteXPos + nSpriteYPos * 280; + + for (INT32 y = 0; y < 16; y++, pPixel += 280, pSpriteData += 16) { + + if ((nSpriteYPos + y) < 0 || (nSpriteYPos + y) >= 240) { + continue; + } + + CLIPPIXEL( 0, PLOTPIXEL( 0)); + CLIPPIXEL( 1, PLOTPIXEL( 1)); + CLIPPIXEL( 2, PLOTPIXEL( 2)); + CLIPPIXEL( 3, PLOTPIXEL( 3)); + CLIPPIXEL( 4, PLOTPIXEL( 4)); + CLIPPIXEL( 5, PLOTPIXEL( 5)); + CLIPPIXEL( 6, PLOTPIXEL( 6)); + CLIPPIXEL( 7, PLOTPIXEL( 7)); + CLIPPIXEL( 8, PLOTPIXEL( 8)); + CLIPPIXEL( 9, PLOTPIXEL( 9)); + CLIPPIXEL(10, PLOTPIXEL(10)); + CLIPPIXEL(11, PLOTPIXEL(11)); + CLIPPIXEL(12, PLOTPIXEL(12)); + CLIPPIXEL(13, PLOTPIXEL(13)); + CLIPPIXEL(14, PLOTPIXEL(14)); + CLIPPIXEL(15, PLOTPIXEL(15)); + } +} + +#undef CLIPPIXEL +#undef PLOTPIXEL + +static void TigerHeliSpriteRender() +{ + UINT8* pSpriteRAM = TigerHeliSpriteBuf; + INT32 nSpriteYOffset = 0; + + if ((nBurnLayer & 1) == 0) { + return; + } + + switch (nWhichGame) { + case 0: // Tiger Heli + nSpriteYOffset = -16; + break; + case 1: // Get Star + nSpriteYOffset = -16; + break; + case 2: // Slap Fight + nSpriteYOffset = -17; + break; + } + + for (INT32 i = 0; i < 0x0800; i += 4) { + nSpriteNumber = pSpriteRAM[i + 0x00] | ((pSpriteRAM[i + 0x02] & 0xC0) << 2); + nSpriteNumber &= nTigerHeliSpriteMask; + nSpritePalette = (pSpriteRAM[i + 0x02] >> 1) & 0x0F; + nSpriteXPos = (pSpriteRAM[i + 0x01] | ((pSpriteRAM[i + 0x02] & 0x01) << 8)) - 21; + nSpriteYPos = pSpriteRAM[i + 0x03] + nSpriteYOffset; + + if (nSpriteXPos > -16 && nSpriteXPos < 280 && nSpriteYPos > -16 && nSpriteYPos < 240) { + if (nSpriteXPos >= 0 && nSpriteXPos <= 264 && nSpriteYPos >= 0 && nSpriteYPos <= 224) { + TigerHeliRenderSpriteNoClip(); + } else { + TigerHeliRenderSpriteClip(); + } + } + } + + return; +} + +static void TigerHeliBufferSprites() +{ + memcpy(TigerHeliSpriteBuf, TigerHeliSpriteRAM, 0x0800); +} + +// --------------------------------------------------------------------------- + + +static inline void sync_mcu() +{ + INT32 cycles = (ZetTotalCycles() / 2) - m6805TotalCycles(); + if (cycles > 0) { + // bprintf (0, _T("mcu %d\n"), cycles); + m6805Run(cycles); + } +} + +UINT8 __fastcall tigerhReadCPU0(UINT16 a) +{ + if (a >= 0xc800 && a <= 0xcfff) { + if (ZetPc(-1) == 0x6d34) return 0xff; + return RamShared[a - 0xc800]; + } + + switch (a) { + case 0xE803: { + if (use_mcu) { + sync_mcu(); + return standard_taito_mcu_read(); + } + + if (nWhichGame == 1) return getstar_e803_r(); + + UINT8 nProtectSequence[3] = { 0, 1, (0 + 5) ^ 0x56 }; + + //if (nProtectIndex == 3) { + // nProtectIndex = 0; + //} + +// bprintf(PRINT_NORMAL, "Protection read (%02X) PC: %04X.\n", nProtectSequence[nProtectIndex], ZetPc(-1)); + //return nProtectSequence[nProtectIndex++]; + + UINT8 val = nProtectSequence[nProtectIndex]; + nProtectIndex = (nProtectIndex + 1) % 3; + return val; + } + +// default: +// bprintf(PRINT_NORMAL, _T("Attempt by CPU0 to read address %04X.\n"), a); + } + + return 0; +} + +UINT8 __fastcall tigerhReadCPU0_tigerhb1(UINT16 a) +{ + if (a >= 0xc800 && a <= 0xcfff) { + if (ZetPc(-1) == 0x6d34) return 0xff; + return RamShared[a - 0xc800]; + } + + switch (a) { + case 0xE803: { + return 0x83; + } + } + + return 0; +} + + +void __fastcall tigerhWriteCPU0(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xE800: + nTigerHeliTileXPosLo = d; + break; + case 0xE801: + nTigerHeliTileXPosHi = d; + break; + case 0xE802: + nTigerHeliTileYPosLo = d; + break; + + case 0xe803: + if (use_mcu) { + sync_mcu(); + from_main = d; + main_sent = 1; + if (nWhichGame == 0) mcu_sent = 0; + m68705SetIrqLine(0, 1 /*ASSERT_LINE*/); + } + if (nWhichGame == 1) getstar_e803_w(); + break; + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU0 to write address %04X -> %02X.\n", a, d); + } +} + +void __fastcall tigerhWriteCPU0_slapbtuk(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xE800: + nTigerHeliTileXPosHi = d; + break; + case 0xE802: + nTigerHeliTileYPosLo = d; + break; + case 0xE803: + nTigerHeliTileXPosLo = d; + break; +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU0 to write address %04X -> %02X.\n", a, d); + } +} + +UINT8 __fastcall tigerhInCPU0(UINT16 a) +{ + a &= 0xFF; + + switch (a) { + case 0x00: { + + UINT8 nStatusSequence[3] = { 0xC7, 0x55, 0x00 }; + + //if (nStatusIndex == 3) { + // nStatusIndex = 0; + //} + +// bprintf(PRINT_NORMAL, "Status read (%02X) PC: %04X.\n", nStatusSequence[nStatusIndex], ZetPc(-1)); + //return nStatusSequence[nStatusIndex++]; + + UINT8 nStatus = nStatusSequence[nStatusIndex]; + nStatusIndex++; + if (nStatusIndex > 2) nStatusIndex = 0; + + if (use_mcu) { + sync_mcu(); + nStatus &= 0xf9; + if (!main_sent) nStatus |= 0x02; + if (!mcu_sent) nStatus |= 0x04; + } + + return nStatus; + + } + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU0 to read port %02X.\n", a); + } + + return 0; +} + +UINT8 __fastcall tigerhInCPU0_gtstarba(UINT16 a) +{ + a &= 0xFF; + + switch (a) { + case 0x00: { + if (ZetPc(-1) == 0x6d1e) return 0; + if (ZetPc(-1) == 0x6d24) return 6; + if (ZetPc(-1) == 0x6d2c) return 2; + if (ZetPc(-1) == 0x6d34) return 4; + return 0; + } + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU0 to read port %02X.\n", a); + } + + return 0; +} + +void __fastcall tigerhOutCPU0(UINT16 a, UINT8 /* d */) +{ + a &= 0xFF; + + switch (a) { + case 0x00: // Assert reset line on sound CPU +// bprintf(PRINT_NORMAL, "Sound CPU disabled.\n"); + + if (bSoundCPUEnable) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + + bSoundCPUEnable = false; + } + + break; + case 0x01: // Release reset line on sound CPU +// bprintf(PRINT_NORMAL, "Sound CPU enabled.\n"); + + bSoundCPUEnable = true; + break; + +// case 0x03: +// break; + +// case 0x05: +// bprintf(PRINT_NORMAL, "Sound NMI triggered.\n"); +/* + if (bSoundNMIEnable) { + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + } +*/ +// break; + + case 0x06: // Disable interrupts +// bprintf(PRINT_NORMAL, "Interrupts disabled.\n"); + + bInterruptEnable = false; + ZetLowerIrq(); + break; + case 0x07: // Enable interrupts +// bprintf(PRINT_NORMAL, "Interrupts enabled.\n"); + + bInterruptEnable = true; + break; + + case 0x08: +// bprintf(PRINT_NORMAL, "ROM bank 0 selected.\n"); + + // ROM bank 0 selected + ZetMapArea(0x8000, 0xBFFF, 0, Rom01 + 0x8000); + ZetMapArea(0x8000, 0xBFFF, 2, Rom01 + 0x8000); + break; + case 0x09: +// bprintf(PRINT_NORMAL, "ROM bank 1 selected.\n"); + + // ROM bank 1 selected + ZetMapArea(0x8000, 0xBFFF, 0, Rom01 + 0xC000); + ZetMapArea(0x8000, 0xBFFF, 2, Rom01 + 0xC000); + break; + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU0 to write port %02X -> %02X.\n", a, d); + } +} + +UINT8 __fastcall tigerhReadCPU1(UINT16 a) +{ + switch (a) { + case 0xA081: +// bprintf(PRINT_NORMAL, "AY8910 0 read (%02X).\n", AY8910Read(0)); + return AY8910Read(0); + case 0xA091: +// bprintf(PRINT_NORMAL, "AY8910 1 read (%02X).\n", AY8910Read(1)); + return AY8910Read(1); + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU1 to read address %04X.\n", a); + } + + return 0; +} + +void __fastcall tigerhWriteCPU1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xA080: +// bprintf(PRINT_NORMAL, "AY8910 0 Register select (%02X).\n", d); + AY8910Write(0, 0, d); + break; + case 0xA082: +// bprintf(PRINT_NORMAL, "AY8910 0 Register Write (%02X).\n", d); + AY8910Write(0, 1, d); + break; + case 0xA090: +// bprintf(PRINT_NORMAL, "AY8910 1 Register select (%02X).\n", d); + AY8910Write(1, 0, d); + break; + case 0xA092: +// bprintf(PRINT_NORMAL, "AY8910 1 Register Write (%02X).\n", d); + AY8910Write(1, 1, d); + break; + + case 0xA0E0: +// bprintf(PRINT_NORMAL, "Sound NMI enabled.\n"); + bSoundNMIEnable = true; + break; + +// default: +// bprintf(PRINT_NORMAL, "Attempt by CPU1 to write address %04X -> %02X.\n", a, d); + } +} + +UINT8 __fastcall tigerhInCPU1(UINT16 /* a */) +{ +// bprintf(PRINT_NORMAL, "Attempt by CPU1 to read port %02X.\n", a); + + return 0; +} + +void __fastcall tigerhOutCPU1(UINT16 /* a */, UINT8 /* d */) +{ +// bprintf(PRINT_NORMAL, _T("Attempt by CPU1 to write port %02X -> %02X.\n"), a, d); +} + +static UINT8 tigerhReadPort0(UINT32) +{ + return ~tigerhInput[0]; +} +static UINT8 tigerhReadPort1(UINT32) +{ + return ~tigerhInput[1]; +} +static UINT8 tigerhReadPort2(UINT32) +{ + return ~tigerhInput[2]; +} +static UINT8 tigerhReadPort3(UINT32) +{ + return ~tigerhInput[3]; +} + +//---------------------------------------------------------------------------- +// MCU Handling + +void tigerh_m68705_portA_write(UINT8 *data) +{ + from_mcu = *data; + mcu_sent = 1; +} + +void tigerh_m68705_portC_read() +{ + portC_in = 0; + if (!main_sent) portC_in |= 0x01; + if ( mcu_sent) portC_in |= 0x02; +} + +static m68705_interface tigerh_m68705_interface = { + tigerh_m68705_portA_write, standard_m68705_portB_out, NULL, + NULL, NULL, NULL, + NULL, NULL, tigerh_m68705_portC_read +}; + +void slapfigh_m68705_portA_write(UINT8 *data) +{ + from_mcu = *data; +} + +void slapfigh_m68705_portB_out(UINT8 *data) +{ + if ((ddrB & 0x02) && (~*data & 0x02) && (portB_out & 0x02)) + { + portA_in = from_main; + if (main_sent) + m68705SetIrqLine(0, 0 /*CLEAR_LINE*/); + main_sent = 0; + } + if ((ddrB & 0x04) && (*data & 0x04) && (~portB_out & 0x04)) + { + from_mcu = portA_out; + mcu_sent = 1; + } + + if ((ddrB & 0x08) && (~*data & 0x08) && (portB_out & 0x08)) + { + nTigerHeliTileXPosLo = portA_out; + } + if ((ddrB & 0x10) && (~*data & 0x10) && (portB_out & 0x10)) + { + nTigerHeliTileXPosHi = portA_out; + } +} + +void slapfigh_m68705_portC_read() +{ + portC_in = 0; + if (main_sent) portC_in |= 0x01; + if (!mcu_sent) portC_in |= 0x02; +} + +static m68705_interface slapfigh_m68705_interface = { + slapfigh_m68705_portA_write, slapfigh_m68705_portB_out, NULL, + NULL, NULL, NULL, + NULL, NULL, slapfigh_m68705_portC_read +}; + +//---------------------------------------------------------------------------- +// Get Star MCU Simulation + +#define GETSTAR 1 +#define GETSTARJ 2 +#define GETSTARB1 3 +#define GETSTARB2 4 + +static UINT8 GetStarType = 0; + +static UINT8 GSa = 0; +static UINT8 GSd = 0; +static UINT8 GSe = 0; +static UINT8 GSCommand = 0; + +#define GS_SAVE_REGS GSa = ZetBc(-1) >> 0; \ + GSd = ZetDe(-1) >> 8; \ + GSe = ZetDe(-1) >> 0; + +#define GS_RESET_REGS GSa = 0; \ + GSd = 0; \ + GSe = 0; + +static UINT8 getstar_e803_r() +{ + UINT16 tmp = 0; /* needed for values computed on 16 bits */ + UINT8 getstar_val = 0; + UINT8 phase_lookup_table[] = {0x00, 0x01, 0x03, 0xff, 0xff, 0x02, 0x05, 0xff, 0xff, 0x05}; /* table at 0x0e05 in 'gtstarb1' */ + UINT8 lives_lookup_table[] = {0x03, 0x05, 0x01, 0x02}; /* table at 0x0e62 in 'gtstarb1' */ + UINT8 lgsb2_lookup_table[] = {0x00, 0x03, 0x04, 0x05}; /* fake tanle for "test mode" in 'gtstarb2' */ + + switch (GetStarType) { + case GETSTAR: + case GETSTARJ: { + switch (GSCommand) { + case 0x20: /* continue play */ + getstar_val = ((GSa & 0x30) == 0x30) ? 0x20 : 0x80; + break; + case 0x21: /* lose life */ + getstar_val = (GSa << 1) | (GSa >> 7); + break; + case 0x22: /* starting difficulty */ + getstar_val = ((GSa & 0x0c) >> 2) + 1; + break; + case 0x23: /* starting lives */ + getstar_val = lives_lookup_table[GSa]; + break; + case 0x24: /* game phase */ + getstar_val = phase_lookup_table[((GSa & 0x18) >> 1) | (GSa & 0x03)]; + break; + case 0x25: /* players inputs */ + getstar_val = BITSWAP08(GSa, 3, 2, 1, 0, 7, 5, 6, 4); + break; + case 0x26: /* background (1st read) */ + tmp = 0x8800 + (0x001f * GSa); + getstar_val = (tmp & 0x00ff) >> 0; + GSCommand |= 0x80; /* to allow a second consecutive read */ + break; + case 0xa6: /* background (2nd read) */ + tmp = 0x8800 + (0x001f * GSa); + getstar_val = (tmp & 0xff00) >> 8; + break; + case 0x29: /* unknown effect */ + getstar_val = 0x00; + break; + case 0x2a: /* change player (if 2 players game) */ + getstar_val = (GSa ^ 0x40); + break; + case 0x37: /* foreground (1st read) */ + tmp = ((0xd0 + ((GSe >> 2) & 0x0f)) << 8) | (0x40 * (GSe & 03) + GSd); + getstar_val = (tmp & 0x00ff) >> 0; + GSCommand |= 0x80; /* to allow a second consecutive read */ + break; + case 0xb7: /* foreground (2nd read) */ + tmp = ((0xd0 + ((GSe >> 2) & 0x0f)) << 8) | (0x40 * (GSe & 03) + GSd); + getstar_val = (tmp & 0xff00) >> 8; + break; + case 0x38: /* laser position (1st read) */ + tmp = 0xf740 - (((GSe >> 4) << 8) | ((GSe & 0x08) ? 0x80 : 0x00)) + (0x02 + (GSd >> 2)); + getstar_val = (tmp & 0x00ff) >> 0; + GSCommand |= 0x80; /* to allow a second consecutive read */ + break; + case 0xb8: /* laser position (2nd read) */ + tmp = 0xf740 - (((GSe >> 4) << 8) | ((GSe & 0x08) ? 0x80 : 0x00)) + (0x02 + (GSd >> 2)); + getstar_val = (tmp & 0xff00) >> 8; + break; + case 0x73: /* avoid "BAD HW" message */ + getstar_val = 0x76; + break; + } + } + + case GETSTARB1: { + /* value isn't computed by the bootleg but we want to please the "test mode" */ + if (ZetPc(-1) == 0x6b04) return (lives_lookup_table[GSa]); + break; + } + + case GETSTARB2: { + /* + 056B: 21 03 E8 ld hl,$E803 + 056E: 7E ld a,(hl) + 056F: BE cp (hl) + 0570: 28 FD jr z,$056F + 0572: C6 05 add a,$05 + 0574: EE 56 xor $56 + 0576: BE cp (hl) + 0577: C2 6E 05 jp nz,$056E + */ + if (ZetPc(-1) == 0x056e) return (getstar_val); + if (ZetPc(-1) == 0x0570) return (getstar_val+1); + if (ZetPc(-1) == 0x0577) return ((getstar_val+0x05) ^ 0x56); + /* value isn't computed by the bootleg but we want to please the "test mode" */ + if (ZetPc(-1) == 0x6b04) return (lgsb2_lookup_table[GSa]); + break; + } + } + + return getstar_val; +} + +static void getstar_e803_w() +{ + switch (GetStarType) { + case GETSTAR: { + /* unknown effect - not read back */ + if (ZetPc(-1) == 0x00bf) + { + GSCommand = 0x00; + GS_RESET_REGS + } + /* players inputs */ + if (ZetPc(-1) == 0x0560) + { + GSCommand = 0x25; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x056d) + { + GSCommand = 0x25; + GS_SAVE_REGS + } + /* lose life */ + if (ZetPc(-1) == 0x0a0a) + { + GSCommand = 0x21; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0a17) + { + GSCommand = 0x21; + GS_SAVE_REGS + } + /* unknown effect */ + if (ZetPc(-1) == 0x0a51) + { + GSCommand = 0x29; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0a6e) + { + GSCommand = 0x29; + GS_SAVE_REGS + } + /* continue play */ + if (ZetPc(-1) == 0x0ae3) + { + GSCommand = 0x20; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0af0) + { + GSCommand = 0x20; + GS_SAVE_REGS + } + /* unknown effect - not read back */ + if (ZetPc(-1) == 0x0b62) + { + GSCommand = 0x00; /* 0x1f */ + GS_RESET_REGS + } + /* change player (if 2 players game) */ + if (ZetPc(-1) == 0x0bab) + { + GSCommand = 0x2a; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0bb8) + { + GSCommand = 0x2a; + GS_SAVE_REGS + } + /* game phase */ + if (ZetPc(-1) == 0x0d37) + { + GSCommand = 0x24; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0d44) + { + GSCommand = 0x24; + GS_SAVE_REGS + } + /* starting lives */ + if (ZetPc(-1) == 0x0d79) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0d8a) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + /* starting difficulty */ + if (ZetPc(-1) == 0x0dc1) + { + GSCommand = 0x22; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0dd0) + { + GSCommand = 0x22; + GS_SAVE_REGS + } + /* starting lives (again) */ + if (ZetPc(-1) == 0x1011) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x101e) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + /* hardware test */ + if (ZetPc(-1) == 0x107a) + { + GSCommand = 0x73; + GS_RESET_REGS + } + /* game phase (again) */ + if (ZetPc(-1) == 0x10c6) + { + GSCommand = 0x24; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x10d3) + { + GSCommand = 0x24; + GS_SAVE_REGS + } + /* background */ + if (ZetPc(-1) == 0x1910) + { + GSCommand = 0x26; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x191d) + { + GSCommand = 0x26; + GS_SAVE_REGS + } + /* foreground */ + if (ZetPc(-1) == 0x19d5) + { + GSCommand = 0x37; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x19e4) + { + GSCommand = 0x37; + GS_SAVE_REGS + } + if (ZetPc(-1) == 0x19f1) + { + GSCommand = 0x37; + /* do NOT update the registers because there are 2 writes before 2 reads ! */ + } + /* laser position */ + if (ZetPc(-1) == 0x26af) + { + GSCommand = 0x38; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x26be) + { + GSCommand = 0x38; + GS_SAVE_REGS + } + if (ZetPc(-1) == 0x26cb) + { + GSCommand = 0x38; + /* do NOT update the registers because there are 2 writes before 2 reads ! */ + } + /* starting lives (for "test mode") */ + if (ZetPc(-1) == 0x6a27) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x6a38) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + break; + } + + case GETSTARJ: { + /* unknown effect - not read back */ + if (ZetPc(-1) == 0x00bf) + { + GSCommand = 0x00; + GS_RESET_REGS + } + /* players inputs */ + if (ZetPc(-1) == 0x0560) + { + GSCommand = 0x25; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x056d) + { + GSCommand = 0x25; + GS_SAVE_REGS + } + /* lose life */ + if (ZetPc(-1) == 0x0ad5) + { + GSCommand = 0x21; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0ae2) + { + GSCommand = 0x21; + GS_SAVE_REGS + } + /* unknown effect */ + if (ZetPc(-1) == 0x0b1c) + { + GSCommand = 0x29; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0b29) + { + GSCommand = 0x29; + GS_SAVE_REGS + } + /* continue play */ + if (ZetPc(-1) == 0x0bae) + { + GSCommand = 0x20; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0bbb) + { + GSCommand = 0x20; + GS_SAVE_REGS + } + /* unknown effect - not read back */ + if (ZetPc(-1) == 0x0c2d) + { + GSCommand = 0x00; /* 0x1f */ + GS_RESET_REGS + } + /* change player (if 2 players game) */ + if (ZetPc(-1) == 0x0c76) + { + GSCommand = 0x2a; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0c83) + { + GSCommand = 0x2a; + GS_SAVE_REGS + } + /* game phase */ + if (ZetPc(-1) == 0x0e02) + { + GSCommand = 0x24; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0e0f) + { + GSCommand = 0x24; + GS_SAVE_REGS + } + /* starting lives */ + if (ZetPc(-1) == 0x0e44) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0e55) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + /* starting difficulty */ + if (ZetPc(-1) == 0x0e8c) + { + GSCommand = 0x22; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x0e9b) + { + GSCommand = 0x22; + GS_SAVE_REGS + } + /* starting lives (again) */ + if (ZetPc(-1) == 0x10d6) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x10e3) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + /* hardware test */ + if (ZetPc(-1) == 0x113f) + { + GSCommand = 0x73; + GS_RESET_REGS + } + /* game phase (again) */ + if (ZetPc(-1) == 0x118b) + { + GSCommand = 0x24; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x1198) + { + GSCommand = 0x24; + GS_SAVE_REGS + } + /* background */ + if (ZetPc(-1) == 0x19f8) + { + GSCommand = 0x26; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x1a05) + { + GSCommand = 0x26; + GS_SAVE_REGS + } + /* foreground */ + if (ZetPc(-1) == 0x1abd) + { + GSCommand = 0x37; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x1acc) + { + GSCommand = 0x37; + GS_SAVE_REGS + } + if (ZetPc(-1) == 0x1ad9) + { + GSCommand = 0x37; + /* do NOT update the registers because there are 2 writes before 2 reads ! */ + } + /* laser position */ + if (ZetPc(-1) == 0x2792) + { + GSCommand = 0x38; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x27a1) + { + GSCommand = 0x38; + GS_SAVE_REGS + } + if (ZetPc(-1) == 0x27ae) + { + GSCommand = 0x38; + /* do NOT update the registers because there are 2 writes before 2 reads ! */ + } + /* starting lives (for "test mode") */ + if (ZetPc(-1) == 0x6ae2) + { + GSCommand = 0x23; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x6af3) + { + GSCommand = 0x23; + GS_SAVE_REGS + } + break; + } + + case GETSTARB1: { + /* "Test mode" doesn't compute the lives value : + 6ADA: 3E 23 ld a,$23 + 6ADC: CD 52 11 call $1152 + 6ADF: 32 03 E8 ld ($E803),a + 6AE2: DB 00 in a,($00) + 6AE4: CB 4F bit 1,a + 6AE6: 28 FA jr z,$6AE2 + 6AE8: 3A 0A C8 ld a,($C80A) + 6AEB: E6 03 and $03 + 6AED: CD 52 11 call $1152 + 6AF0: 32 03 E8 ld ($E803),a + 6AF3: DB 00 in a,($00) + 6AF5: CB 57 bit 2,a + 6AF7: 20 FA jr nz,$6AF3 + 6AF9: 00 nop + 6AFA: 00 nop + 6AFB: 00 nop + 6AFC: 00 nop + 6AFD: 00 nop + 6AFE: 00 nop + 6AFF: 00 nop + 6B00: 00 nop + 6B01: 3A 03 E8 ld a,($E803) + We save the regs though to hack it in 'getstar_e803_r' read handler. + */ + if (ZetPc(-1) == 0x6ae2) + { + GSCommand = 0x00; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x6af3) + { + GSCommand = 0x00; + GS_SAVE_REGS + } + break; + } + + case GETSTARB2: { + /* "Test mode" doesn't compute the lives value : + 6ADA: 3E 23 ld a,$23 + 6ADC: CD 52 11 call $1152 + 6ADF: 32 03 E8 ld ($E803),a + 6AE2: DB 00 in a,($00) + 6AE4: CB 4F bit 1,a + 6AE6: 00 nop + 6AE7: 00 nop + 6AE8: 3A 0A C8 ld a,($C80A) + 6AEB: E6 03 and $03 + 6AED: CD 52 11 call $1152 + 6AF0: 32 03 E8 ld ($E803),a + 6AF3: DB 00 in a,($00) + 6AF5: CB 57 bit 2,a + 6AF7: 00 nop + 6AF8: 00 nop + 6AF9: 00 nop + 6AFA: 00 nop + 6AFB: 00 nop + 6AFC: 00 nop + 6AFD: 00 nop + 6AFE: 00 nop + 6AFF: 00 nop + 6B00: 00 nop + 6B01: 3A 03 E8 ld a,($E803) + We save the regs though to hack it in 'getstar_e803_r' read handler. + */ + if (ZetPc(-1) == 0x6ae2) + { + GSCommand = 0x00; + GS_RESET_REGS + } + if (ZetPc(-1) == 0x6af3) + { + GSCommand = 0x00; + GS_SAVE_REGS + } + break; + } + } +} + +// --------------------------------------------------------------------------- + +static INT32 tigerhLoadROMs() +{ + INT32 nRomOffset = 0; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb2")) nRomOffset = 1; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb3")) nRomOffset = 2; + + // Z80 main program + switch (nWhichGame) { + case 0: // Tiger Heli + if (BurnLoadRom(Rom01 + 0x0000, 0, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x4000, 1, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x8000, 2, 1)) { + return 1; + } + break; + case 1: // Get Star + if (BurnLoadRom(Rom01 + 0x0000, 0, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x4000, 1, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x8000, 2, 1)) { + return 1; + } + break; + case 2: { // Slap Fight + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb2")) { + if (BurnLoadRom(Rom01 + 0x0000, 0, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x4000, 1, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x8000, 2, 1)) { + return 1; + } + break; + } else { + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb3")) { + if (BurnLoadRom(Rom01 + 0x0000, 0, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x4000, 1, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x10000, 2, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x8000, 3, 1)) { + return 1; + } + break; + } else { + if (BurnLoadRom(Rom01 + 0x0000, 0, 1)) { + return 1; + } + if (BurnLoadRom(Rom01 + 0x8000, 1, 1)) { + return 1; + } + break; + } + } + } + } + + // Sprites + { + INT32 nRet = 0, nBaseROM = 0; + switch (nWhichGame) { + case 0: // Tiger Heli + nBaseROM = 3; + break; + case 1: // Get Star + nBaseROM = 3; + break; + case 2: // Slap Fight + nBaseROM = 2 + nRomOffset; + break; + } + + INT32 nSize; + + { + struct BurnRomInfo ri; + + ri.nType = 0; + ri.nLen = 0; + + BurnDrvGetRomInfo(&ri, nBaseROM); + + nSize = ri.nLen; + } + + UINT8* pTemp = (UINT8*)BurnMalloc(nSize * 4); + + for (INT32 i = 0; i < 4; i++) { + nRet |= BurnLoadRom(pTemp + nSize * i, nBaseROM + i, 1); + } + + for (INT32 i = 0; i < nSize; i++) { + for (INT32 j = 0; j < 8; j++) { + TigerHeliSpriteROM[(i << 3) + j] = ((pTemp[i + nSize * 0] >> (7 - j)) & 1) << 3; + TigerHeliSpriteROM[(i << 3) + j] |= ((pTemp[i + nSize * 1] >> (7 - j)) & 1) << 2; + TigerHeliSpriteROM[(i << 3) + j] |= ((pTemp[i + nSize * 2] >> (7 - j)) & 1) << 1; + TigerHeliSpriteROM[(i << 3) + j] |= ((pTemp[i + nSize * 3] >> (7 - j)) & 1) << 0; + } + } + + BurnFree(pTemp); + + nTigerHeliSpriteMask = (nSize >> 5) - 1; + + if (nRet) { + return 1; + } + } + + // Text layer + { + INT32 nBaseROM = 0; + switch (nWhichGame) { + case 0: // Tiger Heli + nBaseROM = 7; + break; + case 1: // Get Star + nBaseROM = 7; + break; + case 2: // Slap Fight + nBaseROM = 6 + nRomOffset; + break; + } + + UINT8* pTemp = (UINT8*)BurnMalloc(0x4000); + + if (BurnLoadRom(pTemp + 0x0000, nBaseROM + 0, 1)) { + return 1; + } + if (BurnLoadRom(pTemp + 0x2000, nBaseROM + 1, 1)) { + return 1; + } + + for (INT32 i = 0; i < 0x02000; i++) { + for (INT32 j = 0; j < 8; j++) { + TigerHeliTextROM[(i << 3) + j] = ((pTemp[i + 0x0000] >> (7 - j)) & 1) << 1; + TigerHeliTextROM[(i << 3) + j] |= ((pTemp[i + 0x2000] >> (7 - j)) & 1) << 0; + } + } + + BurnFree(pTemp); + } + + // Tile layer + { + INT32 nRet = 0, nBaseROM = 0; + switch (nWhichGame) { + case 0: // Tiger Heli + nBaseROM = 9; + break; + case 1: // Get Star + nBaseROM = 9; + break; + case 2: // Slap Fight + nBaseROM = 8 + nRomOffset; + break; + } + + INT32 nSize; + + { + struct BurnRomInfo ri; + + ri.nType = 0; + ri.nLen = 0; + + BurnDrvGetRomInfo(&ri, nBaseROM); + + nSize = ri.nLen; + } + + UINT8* pTemp = (UINT8*)BurnMalloc(nSize * 4); + + for (INT32 i = 0; i < 4; i++) { + nRet |= BurnLoadRom(pTemp + nSize * i, nBaseROM + i, 1); + } + + for (INT32 i = 0; i < nSize; i++) { + for (INT32 j = 0; j < 8; j++) { + TigerHeliTileROM[(i << 3) + j] = ((pTemp[i + nSize * 0] >> (7 - j)) & 1) << 3; + TigerHeliTileROM[(i << 3) + j] |= ((pTemp[i + nSize * 1] >> (7 - j)) & 1) << 2; + TigerHeliTileROM[(i << 3) + j] |= ((pTemp[i + nSize * 2] >> (7 - j)) & 1) << 1; + TigerHeliTileROM[(i << 3) + j] |= ((pTemp[i + nSize * 3] >> (7 - j)) & 1) << 0; + } + } + + BurnFree(pTemp); + + nTigerHeliTileMask = (nSize >> 3) - 1; + + if (nRet) { + return 1; + } + } + + // Colour PROMs + { + INT32 nBaseROM = 0; + switch (nWhichGame) { + case 0: // Tiger Heli + nBaseROM = 13; + break; + case 1: // Get Star + nBaseROM = 13; + break; + case 2: // Slap Fight + nBaseROM = 12 + nRomOffset; + break; + } + + if (BurnLoadRom(TigerHeliPaletteROM + 0x0000, nBaseROM + 0, 1)) { + return 1; + } + if (BurnLoadRom(TigerHeliPaletteROM + 0x0100, nBaseROM + 1, 1)) { + return 1; + } + if (BurnLoadRom(TigerHeliPaletteROM + 0x0200, nBaseROM + 2, 1)) { + return 1; + } + } + + // Z80 program + { + INT32 nBaseROM = 0; + switch (nWhichGame) { + case 0: // Tiger Heli + nBaseROM = 16; + break; + case 1: // Get Star + nBaseROM = 16; + break; + case 2: // Slap Fight + nBaseROM = 15 + nRomOffset; + break; + } + + if (BurnLoadRom(Rom02, nBaseROM, 1)) { + return 1; + } + } + + // MCU program + { + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "tigerh") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhj") == 0) { + if (BurnLoadRom(Rom03, 17, 1)) { + return 1; + } + + use_mcu = 1; + } + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "alcon") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "slapfigh") == 0) { + if (BurnLoadRom(Rom03, 16, 1)) { + return 1; + } + + use_mcu = 1; + } + + } + + return 0; +} + +static INT32 tigerhExit() +{ + BurnTransferExit(); + + TigerHeliSpriteExit(); + TigerHeliTextExit(); + TigerHeliTileExit(); + + ZetExit(); + + if (use_mcu) { + use_mcu = 0; + m67805_taito_exit(); + } + + // Deallocate all used memory + BurnFree(Mem); + + GetStarType = 0; + + return 0; +} + +static void tigerhDoReset() +{ + bInterruptEnable = false; + bSoundNMIEnable = false; + bSoundCPUEnable = true; + + nStatusIndex = 0; + nProtectIndex = 0; + + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + if (use_mcu) { + m67805_taito_reset(); + } + + return; +} + +static INT32 tigerhInit() +{ + INT32 nLen; + + nWhichGame = -1; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "tigerh") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhj") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhb1") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhb2") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhb3") == 0) { + nWhichGame = 0; + } + if (strcmp(BurnDrvGetTextA(DRV_NAME), "getstar") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "getstarj") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb1") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb2") == 0) { + nWhichGame = 1; + if (strcmp(BurnDrvGetTextA(DRV_NAME), "getstar") == 0) GetStarType = GETSTAR; + if (strcmp(BurnDrvGetTextA(DRV_NAME), "getstarj") == 0) GetStarType = GETSTARJ; + if (strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb1") == 0) GetStarType = GETSTARB1; + if (strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb2") == 0) GetStarType = GETSTARB2; + } + if (strcmp(BurnDrvGetTextA(DRV_NAME), "alcon") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "slapfigh") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb1") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb2") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb3") == 0) { + nWhichGame = 2; + } + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8*)0; + if ((Mem = (UINT8*)BurnMalloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (tigerhLoadROMs()) { + return 1; + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb1")) Rom01[0x6d56] = 0xc3; + + { + ZetInit(2); + + // Main CPU setup + ZetOpen(0); + + // Program ROM + ZetMapArea(0x0000, 0x7FFF, 0, Rom01); + ZetMapArea(0x0000, 0x7FFF, 2, Rom01); + // Banked ROM + ZetMapArea(0x8000, 0xBFFF, 0, Rom01 + 0x8000); + ZetMapArea(0x8000, 0xBFFF, 2, Rom01 + 0x8000); + + // Work RAM + ZetMapArea(0xC000, 0xC7FF, 0, Ram01); + ZetMapArea(0xC000, 0xC7FF, 1, Ram01); + ZetMapArea(0xC000, 0xC7FF, 2, Ram01); + + // Shared RAM + if (strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb1")) { + ZetMapArea(0xC800, 0xCFFF, 0, RamShared); + } + ZetMapArea(0xC800, 0xCFFF, 1, RamShared); + ZetMapArea(0xC800, 0xCFFF, 2, RamShared); + + // Tile RAM + ZetMapArea(0xD000, 0xDFFF, 0, TigerHeliTileRAM); + ZetMapArea(0xD000, 0xDFFF, 1, TigerHeliTileRAM); + ZetMapArea(0xD000, 0xDFFF, 2, TigerHeliTileRAM); + // Sprite RAM + ZetMapArea(0xE000, 0xE7FF, 0, TigerHeliSpriteRAM); + ZetMapArea(0xE000, 0xE7FF, 1, TigerHeliSpriteRAM); + ZetMapArea(0xE000, 0xE7FF, 2, TigerHeliSpriteRAM); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb2") || !strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb3")) { + ZetMapArea(0xec00, 0xeFFF, 0, Rom01 + 0x10c00); + ZetMapArea(0xec00, 0xeFFF, 2, Rom01 + 0x10c00); + } + + // Text RAM + ZetMapArea(0xF000, 0xFFFF, 0, TigerHeliTextRAM); + ZetMapArea(0xF000, 0xFFFF, 1, TigerHeliTextRAM); + ZetMapArea(0xF000, 0xFFFF, 2, TigerHeliTextRAM); + + ZetMemEnd(); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "tigerhb1")) { + ZetSetReadHandler(tigerhReadCPU0_tigerhb1); + } else { + ZetSetReadHandler(tigerhReadCPU0); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb2") || !strcmp(BurnDrvGetTextA(DRV_NAME), "slapfighb3")) { + ZetSetWriteHandler(tigerhWriteCPU0_slapbtuk); + } else { + ZetSetWriteHandler(tigerhWriteCPU0); + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gtstarb1")) { + ZetSetInHandler(tigerhInCPU0_gtstarba); + } else { + ZetSetInHandler(tigerhInCPU0); + } + + ZetSetOutHandler(tigerhOutCPU0); + + ZetClose(); + + // Sound CPU setup + ZetOpen(1); + + // Program ROM + ZetMapArea(0x0000, 0x1FFF, 0, Rom02); + ZetMapArea(0x0000, 0x1FFF, 2, Rom02); + + // Work RAM + ZetMapArea(0xC800, 0xCFFF, 0, RamShared); + ZetMapArea(0xC800, 0xCFFF, 1, RamShared); + ZetMapArea(0xC800, 0xCFFF, 2, RamShared); + + ZetMemEnd(); + + ZetSetReadHandler(tigerhReadCPU1); + ZetSetWriteHandler(tigerhWriteCPU1); + ZetSetInHandler(tigerhInCPU1); + ZetSetOutHandler(tigerhOutCPU1); + + ZetClose(); + + if (use_mcu) { + if (nWhichGame == 0) m67805_taito_init(Rom03, Ram03, &tigerh_m68705_interface); + if (nWhichGame == 2) m67805_taito_init(Rom03, Ram03, &slapfigh_m68705_interface); + } + } + + pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0; + pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1; + pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2; + pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3; + pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4; + pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5; + + AY8910Init(0, 1500000, nBurnSoundRate, &tigerhReadPort0, &tigerhReadPort1, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, &tigerhReadPort2, &tigerhReadPort3, NULL, NULL); + + TigerHeliTileInit(); + TigerHeliTextInit(); + TigerHeliSpriteInit(); + TigerHeliPaletteInit(); + + BurnTransferInit(); + + tigerhDoReset(); + + return 0; +} + +static INT32 tigerhScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); // Scan Z80 + + // Scan critical driver variables + SCAN_VAR(bInterruptEnable); + SCAN_VAR(bSoundCPUEnable); + SCAN_VAR(bSoundNMIEnable); + SCAN_VAR(nStatusIndex); + SCAN_VAR(nProtectIndex); + SCAN_VAR(tigerhInput); + } + + return 0; +} + +static void tigerhDraw() +{ + TigerHeliPaletteUpdate(); + + TigerHeliTileRender(); + TigerHeliSpriteRender(); + TigerHeliTextRender(); + + BurnTransferCopy(TigerHeliPalette); + + return; +} + +static inline INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 tigerhFrame() +{ + INT32 nCyclesTotal[3], nCyclesDone[3]; + + if (tigerhReset) { // Reset machine + tigerhDoReset(); + } + + ZetNewFrame(); + m6805NewFrame(); + + // Compile digital inputs + tigerhInput[0] = 0x00; + tigerhInput[1] = 0x00; + for (INT32 i = 0; i < 8; i++) { + tigerhInput[0] |= (tigerhInpJoy1[i] & 1) << i; + if (nWhichGame == 0 && i < 4) { + tigerhInput[1] |= (tigerhInpMisc[i] & 1) << (i ^ 1); + } else { + tigerhInput[1] |= (tigerhInpMisc[i] & 1) << i; + } + } + + if ((tigerhInput[0] & 0x03) == 0x03) { + tigerhInput[0] &= ~0x03; + } + if ((tigerhInput[0] & 0x0C) == 0x0C) { + tigerhInput[0] &= ~0x0C; + } + if ((tigerhInput[0] & 0x30) == 0x30) { + tigerhInput[0] &= ~0x30; + } + if ((tigerhInput[0] & 0xC0) == 0xC0) { + tigerhInput[0] &= ~0xC0; + } + + if (nWhichGame == 1) { + tigerhInput[0] = (tigerhInput[0] & 0x99) | ((tigerhInput[0] << 1) & 0x44) | ((tigerhInput[0] >> 1) & 0x22); + } + + nCyclesTotal[0] = nCyclesTotal[1] = 6000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + nCyclesTotal[2] = 3000000 / 60; + + const INT32 nVBlankCycles = 248 * 6000000 / 60 / 262; + const INT32 nInterleave = 12; + + INT32 nSoundBufferPos = 0; + INT32 nSoundNMIMask = 0; + switch (nWhichGame) { + case 0: + nSoundNMIMask = 1; + break; + case 1: + nSoundNMIMask = 3; + break; + case 2: + nSoundNMIMask = 3; + break; + } + + bool bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext, nCyclesSegment; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + if (nNext > nVBlankCycles && !bVBlank) { + nCyclesDone[nCurrentCPU] += ZetRun(nNext - nVBlankCycles); + + if (pBurnDraw != NULL) { + tigerhDraw(); // Draw screen if needed + } + + TigerHeliBufferSprites(); + + bVBlank = true; + + if (bInterruptEnable) { + ZetRaiseIrq(0xFF); +#if 0 + ZetClose(); + ZetOpen(1); + ZetRaiseIrq(0xFF); + ZetClose(); + ZetOpen(0); +#endif + } + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + + ZetClose(); + + if (use_mcu) { + m6805Open(0); + nCyclesSegment = (nCyclesTotal[2] * (i + 1)) / nInterleave; + nCyclesSegment -= m6805TotalCycles(); + if (nCyclesSegment > 0) { + nCyclesDone[2] += m6805Run(nCyclesSegment); + } + m6805Close(); + } + + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + + if (bSoundCPUEnable) { + ZetOpen(nCurrentCPU); + + if ((i & nSoundNMIMask) == 0) { + if (bSoundNMIEnable) { + ZetNmi(); + } + } + + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + ZetClose(); + } else { + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + + { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } + } + } + } + + return 0; +} + +// --------------------------------------------------------------------------- +// Rom information + +static struct BurnRomInfo tigerhRomDesc[] = { + { "0.4", 0x004000, 0x4BE73246, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "1.4", 0x004000, 0xAAD04867, BRF_ESS | BRF_PRG }, // 1 + { "2.4", 0x004000, 0x4843F15C, BRF_ESS | BRF_PRG }, // 2 + + { "a47_13.8j", 0x004000, 0x739A7E7E, BRF_GRA }, // 3 Sprite data + { "a47_12.6j", 0x004000, 0xC064ECDB, BRF_GRA }, // 4 + { "a47_11.8h", 0x004000, 0x744FAE9B, BRF_GRA }, // 5 + { "a47_10.6h", 0x004000, 0xE1CF844E, BRF_GRA }, // 6 + + { "a47_05.6f", 0x002000, 0xC5325B49, BRF_GRA }, // 7 Text layer + { "a47_04.6g", 0x002000, 0xCD59628E, BRF_GRA }, // 8 + + { "a47_09.4m", 0x004000, 0x31FAE8A8, BRF_GRA }, // 9 Background layer + { "a47_08.6m", 0x004000, 0xE539AF2B, BRF_GRA }, // 10 + { "a47_07.6n", 0x004000, 0x02FDD429, BRF_GRA }, // 11 + { "a47_06.6p", 0x004000, 0x11FBCC8C, BRF_GRA }, // 12 + + { "82s129.12q", 0x000100, 0x2C69350D, BRF_GRA }, // 13 + { "82s129.12m", 0x000100, 0x7142E972, BRF_GRA }, // 14 + { "82s129.12n", 0x000100, 0x25F273F2, BRF_GRA }, // 15 + + { "a47_03.12d", 0x002000, 0xD105260F, BRF_ESS | BRF_PRG }, // 16 + + { "a47_14.6a", 0x000800, 0x4042489F, BRF_ESS | BRF_PRG }, // 17 MCU + + { "pal16r4a.2e", 260, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(tigerh) +STD_ROM_FN(tigerh) + +static struct BurnRomInfo tigerhjRomDesc[] = { + { "a47_00.8p", 0x004000, 0xcbdbe3cc, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a47_01.8n", 0x004000, 0x65df2152, BRF_ESS | BRF_PRG }, // 1 + { "a47_02.8k", 0x004000, 0x633D324B, BRF_ESS | BRF_PRG }, // 2 + + { "a47_13.8j", 0x004000, 0x739A7E7E, BRF_GRA }, // 3 Sprite data + { "a47_12.6j", 0x004000, 0xC064ECDB, BRF_GRA }, // 4 + { "a47_11.8h", 0x004000, 0x744FAE9B, BRF_GRA }, // 5 + { "a47_10.6h", 0x004000, 0xE1CF844E, BRF_GRA }, // 6 + + { "a47_05.6f", 0x002000, 0xC5325B49, BRF_GRA }, // 7 Text layer + { "a47_04.6g", 0x002000, 0xCD59628E, BRF_GRA }, // 8 + + { "a47_09.4m", 0x004000, 0x31FAE8A8, BRF_GRA }, // 9 Background layer + { "a47_08.6m", 0x004000, 0xE539AF2B, BRF_GRA }, // 10 + { "a47_07.6n", 0x004000, 0x02FDD429, BRF_GRA }, // 11 + { "a47_06.6p", 0x004000, 0x11FBCC8C, BRF_GRA }, // 12 + + { "82s129.12q", 0x000100, 0x2C69350D, BRF_GRA }, // 13 + { "82s129.12m", 0x000100, 0x7142E972, BRF_GRA }, // 14 + { "82s129.12n", 0x000100, 0x25F273F2, BRF_GRA }, // 15 + + { "a47_03.12d", 0x002000, 0xD105260F, BRF_ESS | BRF_PRG }, // 16 + + { "a47_14.6a", 0x000800, 0x4042489F, BRF_ESS | BRF_PRG }, // 17 MCU +}; + + +STD_ROM_PICK(tigerhj) +STD_ROM_FN(tigerhj) + +static struct BurnRomInfo tigerhb1RomDesc[] = { + { "b0.5", 0x004000, 0x6ae7e13c, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a47_01.8n", 0x004000, 0x65df2152, BRF_ESS | BRF_PRG }, // 1 + { "a47_02.8k", 0x004000, 0x633D324B, BRF_ESS | BRF_PRG }, // 2 + + { "a47_13.8j", 0x004000, 0x739A7E7E, BRF_GRA }, // 3 Sprite data + { "a47_12.6j", 0x004000, 0xC064ECDB, BRF_GRA }, // 4 + { "a47_11.8h", 0x004000, 0x744FAE9B, BRF_GRA }, // 5 + { "a47_10.6h", 0x004000, 0xE1CF844E, BRF_GRA }, // 6 + + { "a47_05.6f", 0x002000, 0xC5325B49, BRF_GRA }, // 7 Text layer + { "a47_04.6g", 0x002000, 0xCD59628E, BRF_GRA }, // 8 + + { "a47_09.4m", 0x004000, 0x31FAE8A8, BRF_GRA }, // 9 Background layer + { "a47_08.6m", 0x004000, 0xE539AF2B, BRF_GRA }, // 10 + { "a47_07.6n", 0x004000, 0x02FDD429, BRF_GRA }, // 11 + { "a47_06.6p", 0x004000, 0x11FBCC8C, BRF_GRA }, // 12 + + { "82s129.12q", 0x000100, 0x2C69350D, BRF_GRA }, // 13 + { "82s129.12m", 0x000100, 0x7142E972, BRF_GRA }, // 14 + { "82s129.12n", 0x000100, 0x25F273F2, BRF_GRA }, // 15 + + { "a47_03.12d", 0x002000, 0xD105260F, BRF_ESS | BRF_PRG }, // 16 +}; + + +STD_ROM_PICK(tigerhb1) +STD_ROM_FN(tigerhb1) + +static struct BurnRomInfo tigerhb2RomDesc[] = { + { "rom00_09.bin", 0x004000, 0xef738c68, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a47_01.8n", 0x004000, 0x65df2152, BRF_ESS | BRF_PRG }, // 1 + { "rom02_07.bin", 0x004000, 0x36e250b9, BRF_ESS | BRF_PRG }, // 2 + + { "a47_13.8j", 0x004000, 0x739A7E7E, BRF_GRA }, // 3 Sprite data + { "a47_12.6j", 0x004000, 0xC064ECDB, BRF_GRA }, // 4 + { "a47_11.8h", 0x004000, 0x744FAE9B, BRF_GRA }, // 5 + { "a47_10.6h", 0x004000, 0xE1CF844E, BRF_GRA }, // 6 + + { "a47_05.6f", 0x002000, 0xC5325B49, BRF_GRA }, // 7 Text layer + { "a47_04.6g", 0x002000, 0xCD59628E, BRF_GRA }, // 8 + + { "a47_09.4m", 0x004000, 0x31FAE8A8, BRF_GRA }, // 9 Background layer + { "a47_08.6m", 0x004000, 0xE539AF2B, BRF_GRA }, // 10 + { "a47_07.6n", 0x004000, 0x02FDD429, BRF_GRA }, // 11 + { "a47_06.6p", 0x004000, 0x11FBCC8C, BRF_GRA }, // 12 + + { "82s129.12q", 0x000100, 0x2C69350D, BRF_GRA }, // 13 + { "82s129.12m", 0x000100, 0x7142E972, BRF_GRA }, // 14 + { "82s129.12n", 0x000100, 0x25F273F2, BRF_GRA }, // 15 + + { "a47_03.12d", 0x002000, 0xD105260F, BRF_ESS | BRF_PRG }, // 16 +}; + + +STD_ROM_PICK(tigerhb2) +STD_ROM_FN(tigerhb2) + +static struct BurnRomInfo tigerhb3RomDesc[] = { + { "14", 0x004000, 0xCA59DD73, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "13", 0x004000, 0x38BD54DB, BRF_ESS | BRF_PRG }, // 1 + { "a47_02.8k", 0x004000, 0x633D324B, BRF_ESS | BRF_PRG }, // 2 + + { "a47_13.8j", 0x004000, 0x739A7E7E, BRF_GRA }, // 3 Sprite data + { "a47_12.6j", 0x004000, 0xC064ECDB, BRF_GRA }, // 4 + { "a47_11.8h", 0x004000, 0x744FAE9B, BRF_GRA }, // 5 + { "a47_10.6h", 0x004000, 0xE1CF844E, BRF_GRA }, // 6 + + { "a47_05.6f", 0x002000, 0xC5325B49, BRF_GRA }, // 7 Text layer + { "a47_04.6g", 0x002000, 0xCD59628E, BRF_GRA }, // 8 + + { "a47_09.4m", 0x004000, 0x31FAE8A8, BRF_GRA }, // 9 Background layer + { "a47_08.6m", 0x004000, 0xE539AF2B, BRF_GRA }, // 10 + { "a47_07.6n", 0x004000, 0x02FDD429, BRF_GRA }, // 11 + { "a47_06.6p", 0x004000, 0x11FBCC8C, BRF_GRA }, // 12 + + { "82s129.12q", 0x000100, 0x2C69350D, BRF_GRA }, // 13 + { "82s129.12m", 0x000100, 0x7142E972, BRF_GRA }, // 14 + { "82s129.12n", 0x000100, 0x25F273F2, BRF_GRA }, // 15 + + { "a47_03.12d", 0x002000, 0xD105260F, BRF_ESS | BRF_PRG }, // 16 +}; + + +STD_ROM_PICK(tigerhb3) +STD_ROM_FN(tigerhb3) + +static struct BurnRomInfo getstarRomDesc[] = { + { "a68_00-1", 0x004000, 0x6A8BDC6C, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a68_01-1", 0x004000, 0xEBE8DB3C, BRF_ESS | BRF_PRG }, // 1 + { "a68_02-1", 0x008000, 0x343E8415, BRF_ESS | BRF_PRG }, // 2 + + { "a68-13", 0x008000, 0x643FB282, BRF_GRA }, // 3 Sprite data + { "a68-12", 0x008000, 0x11F74E32, BRF_GRA }, // 4 + { "a68-11", 0x008000, 0xF24158CF, BRF_GRA }, // 5 + { "a68-10", 0x008000, 0x83161Ed0, BRF_GRA }, // 6 + + { "a68_05-1", 0x002000, 0x06F60107, BRF_GRA }, // 7 Text layer + { "a68_04-1", 0x002000, 0x1FC8F277, BRF_GRA }, // 8 + + { "a68_09", 0x008000, 0xA293CC2E, BRF_GRA }, // 9 Background layer + { "a68_08", 0x008000, 0x37662375, BRF_GRA }, // 10 + { "a68_07", 0x008000, 0xCF1A964C, BRF_GRA }, // 11 + { "a68_06", 0x008000, 0x05F9EB9A, BRF_GRA }, // 12 + + { "rom21", 0x000100, 0xD6360B4D, BRF_GRA }, // 13 + { "rom20", 0x000100, 0x4CA01887, BRF_GRA }, // 14 + { "rom19", 0x000100, 0x513224F0, BRF_GRA }, // 15 + + { "a68-03", 0x002000, 0x18DAA44C, BRF_ESS | BRF_PRG }, // 16 + + { "a68_14", 0x000800, 0x00000000, BRF_NODUMP | BRF_OPT | BRF_PRG }, // 17 MCU ROM +}; + + +STD_ROM_PICK(getstar) +STD_ROM_FN(getstar) + +static struct BurnRomInfo getstarjRomDesc[] = { + { "a68_00.bin", 0x004000, 0xad1a0143, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a68_01.bin", 0x004000, 0x3426eb7c, BRF_ESS | BRF_PRG }, // 1 + { "a68_02.bin", 0x008000, 0x3567da17, BRF_ESS | BRF_PRG }, // 2 + + { "a68-13", 0x008000, 0x643FB282, BRF_GRA }, // 3 Sprite data + { "a68-12", 0x008000, 0x11F74E32, BRF_GRA }, // 4 + { "a68-11", 0x008000, 0xF24158CF, BRF_GRA }, // 5 + { "a68-10", 0x008000, 0x83161Ed0, BRF_GRA }, // 6 + + { "a68_05.bin", 0x002000, 0xe3d409e7, BRF_GRA }, // 7 Text layer + { "a68_04.bin", 0x002000, 0x6e5ac9d4, BRF_GRA }, // 8 + + { "a68_09", 0x008000, 0xA293CC2E, BRF_GRA }, // 9 Background layer + { "a68_08", 0x008000, 0x37662375, BRF_GRA }, // 10 + { "a68_07", 0x008000, 0xCF1A964C, BRF_GRA }, // 11 + { "a68_06", 0x008000, 0x05F9EB9A, BRF_GRA }, // 12 + + { "rom21", 0x000100, 0xD6360B4D, BRF_GRA }, // 13 + { "rom20", 0x000100, 0x4CA01887, BRF_GRA }, // 14 + { "rom19", 0x000100, 0x513224F0, BRF_GRA }, // 15 + + { "a68-03", 0x002000, 0x18DAA44C, BRF_ESS | BRF_PRG }, // 16 + + { "68705.bin", 0x000800, 0x00000000, BRF_NODUMP | BRF_OPT | BRF_PRG }, // 17 MCU ROM +}; + + +STD_ROM_PICK(getstarj) +STD_ROM_FN(getstarj) + +static struct BurnRomInfo gtstarb2RomDesc[] = { + { "gs_14.rom", 0x004000, 0x1A57A920, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "gs_13.rom", 0x004000, 0x805F8E77, BRF_ESS | BRF_PRG }, // 1 + { "a68_02.bin", 0x008000, 0x3567DA17, BRF_ESS | BRF_PRG }, // 2 + + { "a68-13", 0x008000, 0x643FB282, BRF_GRA }, // 3 Sprite data + { "a68-12", 0x008000, 0x11F74E32, BRF_GRA }, // 4 + { "a68-11", 0x008000, 0xF24158CF, BRF_GRA }, // 5 + { "a68-10", 0x008000, 0x83161Ed0, BRF_GRA }, // 6 + + { "a68_05.bin", 0x002000, 0xE3D409E7, BRF_GRA }, // 7 Text layer + { "a68_04.bin", 0x002000, 0x6E5AC9D4, BRF_GRA }, // 8 + + { "a68_09", 0x008000, 0xA293CC2E, BRF_GRA }, // 9 Background layer + { "a68_08", 0x008000, 0x37662375, BRF_GRA }, // 10 + { "a68_07", 0x008000, 0xCF1A964C, BRF_GRA }, // 11 + { "a68_06", 0x008000, 0x05F9EB9A, BRF_GRA }, // 12 + + { "rom21", 0x000100, 0xD6360B4D, BRF_GRA }, // 13 + { "rom20", 0x000100, 0x4CA01887, BRF_GRA }, // 14 + { "rom19", 0x000100, 0x513224F0, BRF_GRA }, // 15 + + { "a68-03", 0x002000, 0x18DAA44C, BRF_ESS | BRF_PRG }, // 16 +}; + + +STD_ROM_PICK(gtstarb2) +STD_ROM_FN(gtstarb2) + +static struct BurnRomInfo gtstarb1RomDesc[] = { + { "gs_rb_1.bin", 0x004000, 0x9afad7e0, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "gs_rb_2.bin", 0x004000, 0x5feb0a60, BRF_ESS | BRF_PRG }, // 1 + { "gs_rb_3.bin", 0x008000, 0xe3cfb1ba, BRF_ESS | BRF_PRG }, // 2 + + { "a68-13", 0x008000, 0x643FB282, BRF_GRA }, // 3 Sprite data + { "a68-12", 0x008000, 0x11F74E32, BRF_GRA }, // 4 + { "a68-11", 0x008000, 0xF24158CF, BRF_GRA }, // 5 + { "a68-10", 0x008000, 0x83161Ed0, BRF_GRA }, // 6 + + { "a68_05.bin", 0x002000, 0xE3D409E7, BRF_GRA }, // 7 Text layer + { "a68_04.bin", 0x002000, 0x6E5AC9D4, BRF_GRA }, // 8 + + { "a68_09", 0x008000, 0xA293CC2E, BRF_GRA }, // 9 Background layer + { "a68_08", 0x008000, 0x37662375, BRF_GRA }, // 10 + { "a68_07", 0x008000, 0xCF1A964C, BRF_GRA }, // 11 + { "a68_06", 0x008000, 0x05F9EB9A, BRF_GRA }, // 12 + + { "rom21", 0x000100, 0xD6360B4D, BRF_GRA }, // 13 + { "rom20", 0x000100, 0x4CA01887, BRF_GRA }, // 14 + { "rom19", 0x000100, 0x513224F0, BRF_GRA }, // 15 + + { "a68-03", 0x002000, 0x18DAA44C, BRF_ESS | BRF_PRG }, // 16 +}; + + +STD_ROM_PICK(gtstarb1) +STD_ROM_FN(gtstarb1) + +static struct BurnRomInfo alconRomDesc[] = { + { "a77_00-1.8p", 0x008000, 0x2ba82d60, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a77_01-1.8n", 0x008000, 0x18bb2f12, BRF_ESS | BRF_PRG }, // 1 + + { "a77_12.8j", 0x008000, 0x8545d397, BRF_GRA }, // 2 Sprite data + { "a77_11.7j", 0x008000, 0xb1b7b925, BRF_GRA }, // 3 + { "a77_10.8h", 0x008000, 0x422d946b, BRF_GRA }, // 4 + { "a77_09.7h", 0x008000, 0x587113ae, BRF_GRA }, // 5 + + { "a77_04-1.6f", 0x002000, 0x31003483, BRF_GRA }, // 6 Text layer + { "a77_03-1.6g", 0x002000, 0x404152c0, BRF_GRA }, // 7 + + { "a77_08.6k", 0x008000, 0xB6358305, BRF_GRA }, // 8 Background layer + { "a77_07.6m", 0x008000, 0xE92D9D60, BRF_GRA }, // 9 + { "a77_06.6n", 0x008000, 0x5FAEEEA3, BRF_GRA }, // 10 + { "a77_05.6p", 0x008000, 0x974E2EA9, BRF_GRA }, // 11 + + { "21_82s129.12q",0x000100, 0xA0EFAF99, BRF_GRA }, // 12 + { "20_82s129.12m",0x000100, 0xA56D57E5, BRF_GRA }, // 13 + { "19_82s129.12n",0x000100, 0x5CBF9FBF, BRF_GRA }, // 14 + + { "a77_02.12d", 0x002000, 0x87F4705A, BRF_ESS | BRF_PRG }, // 15 + + { "a77_13.6a", 0x000800, 0xa70c81d9, BRF_ESS | BRF_PRG }, // 16 MCU ROM +}; + + +STD_ROM_PICK(alcon) +STD_ROM_FN(alcon) + +static struct BurnRomInfo slapfighRomDesc[] = { + { "a77_00.8p", 0x008000, 0x674C0E0F, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "a77_01.8n", 0x008000, 0x3C42E4A7, BRF_ESS | BRF_PRG }, // 1 + + { "a77_12.8j", 0x008000, 0x8545d397, BRF_GRA }, // 2 Sprite data + { "a77_11.7j", 0x008000, 0xb1b7b925, BRF_GRA }, // 3 + { "a77_10.8h", 0x008000, 0x422d946b, BRF_GRA }, // 4 + { "a77_09.7h", 0x008000, 0x587113ae, BRF_GRA }, // 5 + + { "a77_04.6f", 0x002000, 0x2AC7B943, BRF_GRA }, // 6 Text layer + { "a77_03.6g", 0x002000, 0x33CADC93, BRF_GRA }, // 7 + + { "a77_08.6k", 0x008000, 0xB6358305, BRF_GRA }, // 8 Background layer + { "a77_07.6m", 0x008000, 0xE92D9D60, BRF_GRA }, // 9 + { "a77_06.6n", 0x008000, 0x5FAEEEA3, BRF_GRA }, // 10 + { "a77_05.6p", 0x008000, 0x974E2EA9, BRF_GRA }, // 11 + + { "21_82s129.12q",0x000100, 0xA0EFAF99, BRF_GRA }, // 12 + { "20_82s129.12m",0x000100, 0xA56D57E5, BRF_GRA }, // 13 + { "19_82s129.12n",0x000100, 0x5CBF9FBF, BRF_GRA }, // 14 + + { "a77_02.12d", 0x002000, 0x87F4705A, BRF_ESS | BRF_PRG }, // 15 + + { "a77_13.6a", 0x000800, 0xa70c81d9, BRF_ESS | BRF_PRG }, // 16 MCU ROM +}; + + +STD_ROM_PICK(slapfigh) +STD_ROM_FN(slapfigh) + +static struct BurnRomInfo slapbtjpRomDesc[] = { + { "sf_r19jb.bin", 0x008000, 0x9A7AC8B3, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "sf_rh.bin", 0x008000, 0x3C42E4A7, BRF_ESS | BRF_PRG }, // 1 + + { "sf_r03.bin", 0x008000, 0x8545D397, BRF_GRA }, // 2 Sprite data + { "sf_r01.bin", 0x008000, 0xB1B7B925, BRF_GRA }, // 3 + { "sf_r04.bin", 0x008000, 0x422D946B, BRF_GRA }, // 4 + { "sf_r02.bin", 0x008000, 0x587113AE, BRF_GRA }, // 5 + + { "sf_r11.bin", 0x002000, 0x2AC7B943, BRF_GRA }, // 6 Text layer + { "sf_r10.bin", 0x002000, 0x33CADC93, BRF_GRA }, // 7 + + { "sf_r06.bin", 0x008000, 0xB6358305, BRF_GRA }, // 8 Background layer + { "sf_r09.bin", 0x008000, 0xE92D9D60, BRF_GRA }, // 9 + { "sf_r08.bin", 0x008000, 0x5FAEEEA3, BRF_GRA }, // 10 + { "sf_r07.bin", 0x008000, 0x974E2EA9, BRF_GRA }, // 11 + + { "sf_col21.bin", 0x000100, 0xA0EFAF99, BRF_GRA }, // 12 + { "sf_col20.bin", 0x000100, 0xA56D57E5, BRF_GRA }, // 13 + { "sf_col19.bin", 0x000100, 0x5CBF9FBF, BRF_GRA }, // 14 + + { "sf_r05.bin", 0x002000, 0x87F4705A, BRF_ESS | BRF_PRG }, // 15 +}; + + +STD_ROM_PICK(slapbtjp) +STD_ROM_FN(slapbtjp) + +static struct BurnRomInfo slapbtukRomDesc[] = { + { "sf_r19eb.bin", 0x004000, 0x2efe47af, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "sf_r20eb.bin", 0x004000, 0xf42c7951, BRF_ESS | BRF_PRG }, // 1 + { "sf_rh.bin", 0x008000, 0x3C42E4A7, BRF_ESS | BRF_PRG }, // 1 + + { "sf_r03.bin", 0x008000, 0x8545D397, BRF_GRA }, // 2 Sprite data + { "sf_r01.bin", 0x008000, 0xB1B7B925, BRF_GRA }, // 3 + { "sf_r04.bin", 0x008000, 0x422D946B, BRF_GRA }, // 4 + { "sf_r02.bin", 0x008000, 0x587113AE, BRF_GRA }, // 5 + + { "sf_r11.bin", 0x002000, 0x2AC7B943, BRF_GRA }, // 6 Text layer + { "sf_r10.bin", 0x002000, 0x33CADC93, BRF_GRA }, // 7 + + { "sf_r06.bin", 0x008000, 0xB6358305, BRF_GRA }, // 8 Background layer + { "sf_r09.bin", 0x008000, 0xE92D9D60, BRF_GRA }, // 9 + { "sf_r08.bin", 0x008000, 0x5FAEEEA3, BRF_GRA }, // 10 + { "sf_r07.bin", 0x008000, 0x974E2EA9, BRF_GRA }, // 11 + + { "sf_col21.bin", 0x000100, 0xA0EFAF99, BRF_GRA }, // 12 + { "sf_col20.bin", 0x000100, 0xA56D57E5, BRF_GRA }, // 13 + { "sf_col19.bin", 0x000100, 0x5CBF9FBF, BRF_GRA }, // 14 + + { "sf_r05.bin", 0x002000, 0x87F4705A, BRF_ESS | BRF_PRG }, // 15 +}; + + +STD_ROM_PICK(slapbtuk) +STD_ROM_FN(slapbtuk) + +static struct BurnRomInfo slapfgtrRomDesc[] = { + { "k1-10.u90", 0x004000, 0x2efe47af, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "k1-09.u89", 0x004000, 0x17c187c5, BRF_ESS | BRF_PRG }, // 1 + { "k1-08.u88", 0x002000, 0x945af97f, BRF_ESS | BRF_PRG }, // 1 + { "k1-07.u87", 0x008000, 0x3C42E4A7, BRF_ESS | BRF_PRG }, // 1 + + { "k1-15.u60", 0x008000, 0x8545D397, BRF_GRA }, // 2 Sprite data + { "k1-13.u50", 0x008000, 0xB1B7B925, BRF_GRA }, // 3 + { "k1-14.u59", 0x008000, 0x422D946B, BRF_GRA }, // 4 + { "k1-12.u49", 0x008000, 0x587113AE, BRF_GRA }, // 5 + + { "k1-02.u57" , 0x002000, 0x2AC7B943, BRF_GRA }, // 6 Text layer + { "k1-03.u58", 0x002000, 0x33CADC93, BRF_GRA }, // 7 + + { "k1-01.u49" , 0x008000, 0xB6358305, BRF_GRA }, // 8 Background layer + { "k1-04.u62", 0x008000, 0xE92D9D60, BRF_GRA }, // 9 + { "k1-05.u63", 0x008000, 0x5FAEEEA3, BRF_GRA }, // 10 + { "k1-06.u64", 0x008000, 0x974E2EA9, BRF_GRA }, // 11 + + { "sf_col21.bin", 0x000100, 0xA0EFAF99, BRF_GRA }, // 12 + { "sf_col20.bin", 0x000100, 0xA56D57E5, BRF_GRA }, // 13 + { "sf_col19.bin", 0x000100, 0x5CBF9FBF, BRF_GRA }, // 14 + + { "k1-11.u89", 0x002000, 0x87F4705A, BRF_ESS | BRF_PRG }, // 15 +}; + + +STD_ROM_PICK(slapfgtr) +STD_ROM_FN(slapfgtr) + +struct BurnDriver BurnDrvTigerH = { + "tigerh", NULL, NULL, NULL, "1985", + "Tiger Heli (US)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tigerhRomInfo, tigerhRomName, NULL, NULL, tigerhInputInfo, tigerhDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvTigerhJ = { + "tigerhj", "tigerh", NULL, NULL, "1985", + "Tiger Heli (Japan)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tigerhjRomInfo, tigerhjRomName, NULL, NULL, tigerhInputInfo, tigerhDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvTigerHB1 = { + "tigerhb1", "tigerh", NULL, NULL, "1985", + "Tiger Heli (bootleg, set 1)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tigerhb1RomInfo, tigerhb1RomName, NULL, NULL, tigerhInputInfo, tigerhDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvTigerHB2 = { + "tigerhb2", "tigerh", NULL, NULL, "1985", + "Tiger Heli (bootleg, set 2)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tigerhb2RomInfo, tigerhb2RomName, NULL, NULL, tigerhInputInfo, tigerhDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvTigerHB3 = { + "tigerhb3", "tigerh", NULL, NULL, "1985", + "Tiger Heli (bootleg, set 3)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, tigerhb3RomInfo, tigerhb3RomName, NULL, NULL, tigerhInputInfo, tigerhDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvGetStar = { + "getstar", NULL, NULL, NULL, "1986", + "Guardian\0", NULL, "Toaplan / Taito America Corporation (Kitkorp license)", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, getstarRomInfo, getstarRomName, NULL, NULL, getstarInputInfo, getstarDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 280, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGetStarj = { + "getstarj", "getstar", NULL, NULL, "1986", + "Get Star (Japan)\0", NULL, "Toaplan / Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, getstarjRomInfo, getstarjRomName, NULL, NULL, getstarInputInfo, getstarDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 280, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGetStarb2 = { + "gtstarb2", "getstar", NULL, NULL, "1986", + "Get Star (bootleg, set 2)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, gtstarb2RomInfo, gtstarb2RomName, NULL, NULL, tigerhInputInfo, getstarb2DIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 280, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGetStarb1 = { + "gtstarb1", "getstar", NULL, NULL, "1986", + "Get Star (bootleg, set 1)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, gtstarb1RomInfo, gtstarb1RomName, NULL, NULL, getstarInputInfo, getstarDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 280, 240, 4, 3 +}; + +struct BurnDriver BurnDrvAlcon = { + "alcon", NULL, NULL, NULL, "1986", + "Alcon (US)\0", NULL, "Taito America Corp.", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, alconRomInfo, alconRomName, NULL, NULL, tigerhInputInfo, slapfighDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvSlapFigh = { + "slapfigh", "alcon", NULL, NULL, "1986", + "Slap Fight (Japan set 1)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, slapfighRomInfo, slapfighRomName, NULL, NULL, tigerhInputInfo, slapfighDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvSlapBtJP = { + "slapfighb1", "alcon", NULL, NULL, "1986", + "Slap Fight (bootleg set 1)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, slapbtjpRomInfo, slapbtjpRomName, NULL, NULL, tigerhInputInfo, slapfighDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvSlapBtUK = { + "slapfighb2", "alcon", NULL, NULL, "1986", + "Slap Fight (bootleg set 2)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, slapbtukRomInfo, slapbtukRomName, NULL, NULL, tigerhInputInfo, slapfighDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; + +struct BurnDriver BurnDrvSlapFghtr = { + "slapfighb3", "alcon", NULL, NULL, "1986", + "Slap Fight (bootleg set 3)\0", NULL, "Taito", "Early Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, slapfgtrRomInfo, slapfgtrRomName, NULL, NULL, tigerhInputInfo, slapfighDIPInfo, + tigerhInit, tigerhExit, tigerhFrame, NULL, tigerhScan, &tigerhRecalcPalette, 0x100, + 240, 280, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_tigeroad.cpp b/src/burn/drivers/misc_pre90s/d_tigeroad.cpp new file mode 100644 index 00000000..467bb876 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_tigeroad.cpp @@ -0,0 +1,1424 @@ +// FB Alpha Tiger Road driver module +// Based on MAME driver by Phil Stroffolino +// F1 Dream protection code by Eric Hustvedt + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm5205.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvVidRAM; +static UINT8 *DrvScrollRAM; +static UINT32 *DrvPalette; +static UINT8 *DrvTransMask; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDip[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static UINT8 *soundlatch; +static UINT8 *soundlatch2; +static UINT8 *flipscreen; +static UINT8 *bgcharbank; +static UINT8 *coin_lockout; + +static INT32 nF1dream = 0; +static INT32 toramich = 0; + +static struct BurnInputInfo TigeroadInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 14, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 8, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 15, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 9, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 11, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 9, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 8, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Tigeroad) + +static struct BurnDIPInfo TigeroadDIPList[] = +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x02, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x10, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x04, 0x00, "Upright" }, + {0x12, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x12, 0x01, 0x18, 0x18, "20000 70000 70000" }, + {0x12, 0x01, 0x18, 0x10, "20000 80000 80000" }, + {0x12, 0x01, 0x18, 0x08, "30000 80000 80000" }, + {0x12, 0x01, 0x18, 0x00, "30000 90000 90000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x60, 0x20, "Very_Easy" }, + {0x12, 0x01, 0x60, 0x40, "Easy" }, + {0x12, 0x01, 0x60, 0x60, "Normal" }, + {0x12, 0x01, 0x60, 0x00, "Difficult" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Tigeroad) + +static struct BurnDIPInfo ToramichDIPList[] = +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x02, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x10, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x04, 0x00, "Upright" }, + {0x12, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x12, 0x01, 0x08, 0x08, "20000 70000 70000" }, + {0x12, 0x01, 0x08, 0x00, "20000 80000 80000" }, + + {0 , 0xfe, 0 , 2, "Allow Level Select" }, + {0x12, 0x01, 0x10, 0x10, "No" }, + {0x12, 0x01, 0x10, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x60, 0x40, "Easy" }, + {0x12, 0x01, 0x60, 0x60, "Normal" }, + {0x12, 0x01, 0x60, 0x20, "Difficult" }, + {0x12, 0x01, 0x60, 0x00, "Very Difficult" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Toramich) + +static struct BurnDIPInfo F1dreamDIPList[] = +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xbb, NULL }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x01, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x02, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x07, 0x04, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x07, 0x03, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x08, "3 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x10, "2 Coins 1 Credits " }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credits " }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 2 Credits " }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits " }, + {0x11, 0x01, 0x38, 0x20, "1 Coin 4 Credits " }, + {0x11, 0x01, 0x38, 0x18, "1 Coin 6 Credits " }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x11, 0x01, 0x40, 0x00, "On" }, + {0x11, 0x01, 0x40, 0x40, "Off" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x02, "4" }, + {0x12, 0x01, 0x03, 0x01, "5" }, + {0x12, 0x01, 0x03, 0x00, "7" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x04, 0x00, "Upright" }, + {0x12, 0x01, 0x04, 0x04, "Cocktail" }, + + {0 , 0xfe, 0 , 4, "F1 Up Point" }, + {0x12, 0x01, 0x18, 0x18, "12" }, + {0x12, 0x01, 0x18, 0x10, "16" }, + {0x12, 0x01, 0x18, 0x08, "18" }, + {0x12, 0x01, 0x18, 0x00, "20" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x12, 0x01, 0x20, 0x20, "Normal" }, + {0x12, 0x01, 0x20, 0x00, "Difficult" }, + + {0 , 0xfe, 0 , 2, "Version" }, + {0x12, 0x01, 0x40, 0x00, "International" }, + {0x12, 0x01, 0x40, 0x40, "Japan" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x12, 0x01, 0x80, 0x00, "No" }, + {0x12, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(F1dream) + +static void palette_write(INT32 offset) +{ + UINT16 data = *((UINT16 *)(DrvPalRAM + offset + 0x200)); + + UINT8 r,g,b; + + r = (data >> 8) & 0x0f; + g = (data >> 4) & 0x0f; + b = (data >> 0) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[offset / 2] = BurnHighCol(r, g, b, 0); +} + +static const UINT16 f1dream_613ea_lookup[16] = { +0x0052, 0x0031, 0x00a7, 0x0043, 0x0007, 0x008a, 0x00b1, 0x0066, 0x009f, 0x00cc, 0x0009, 0x004d, 0x0033, 0x0028, 0x00d0, 0x0025}; + +static const UINT16 f1dream_613eb_lookup[256] = { +0x0001, 0x00b5, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b7, 0x0001, 0x00b8, 0x002f, 0x002f, 0x002f, 0x002f, 0x00b9, +0x00aa, 0x0031, 0x00ab, 0x00ab, 0x00ab, 0x00ac, 0x00ad, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x0091, +0x009c, 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x009b, 0x0091, +0x00bc, 0x0092, 0x000b, 0x0009, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0073, 0x0001, 0x0098, 0x0099, 0x009a, 0x009b, 0x0091, +0x00bc, 0x007b, 0x000b, 0x0008, 0x0087, 0x0088, 0x0089, 0x008a, 0x007f, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, +0x00bd, 0x007b, 0x000b, 0x0007, 0x007c, 0x007d, 0x007e, 0x0001, 0x007f, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, +0x00bc, 0x0070, 0x000b, 0x0006, 0x0071, 0x0072, 0x0073, 0x0001, 0x0074, 0x000d, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, +0x00bc, 0x00ba, 0x000a, 0x0005, 0x0065, 0x0066, 0x0067, 0x0068, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, +0x00bc, 0x0059, 0x0001, 0x0004, 0x005a, 0x005b, 0x0001, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, +0x0014, 0x004d, 0x0001, 0x0003, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0001, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, +0x0014, 0x0043, 0x0001, 0x0002, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x00bb, 0x004a, 0x004b, 0x004c, 0x0001, 0x0001, +0x0014, 0x002b, 0x0001, 0x0038, 0x0039, 0x003a, 0x003b, 0x0031, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0001, +0x0014, 0x002d, 0x0001, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0001, 0x0014, 0x0037, 0x0001, +0x0014, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x0001, 0x0001, 0x0001, 0x002a, 0x002b, 0x002c, +0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001e, 0x001e, 0x001e, 0x001f, 0x0020, +0x000c, 0x000d, 0x000e, 0x0001, 0x000f, 0x0010, 0x0011, 0x0012, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x0013 }; + +static const UINT16 f1dream_17b74_lookup[128] = { +0x0003, 0x0040, 0x0005, 0x0080, 0x0003, 0x0080, 0x0005, 0x00a0, 0x0003, 0x0040, 0x0005, 0x00c0, 0x0003, 0x0080, 0x0005, 0x00e0, +0x0003, 0x0040, 0x0006, 0x0000, 0x0003, 0x0080, 0x0006, 0x0020, 0x0003, 0x0040, 0x0006, 0x0040, 0x0003, 0x0080, 0x0006, 0x0060, +0x0000, 0x00a0, 0x0009, 0x00e0, 0x0000, 0x00e0, 0x000a, 0x0000, 0x0000, 0x00a0, 0x000a, 0x0020, 0x0000, 0x00e0, 0x000a, 0x0040, +0x0000, 0x00a0, 0x000a, 0x0060, 0x0000, 0x00e0, 0x000a, 0x0080, 0x0000, 0x00a0, 0x000a, 0x00a0, 0x0000, 0x00e0, 0x000a, 0x00c0, +0x0003, 0x0040, 0x0005, 0x0080, 0x0003, 0x0080, 0x0005, 0x00a0, 0x0003, 0x0040, 0x0005, 0x00c0, 0x0003, 0x0080, 0x0005, 0x00e0, +0x0003, 0x0040, 0x0006, 0x0000, 0x0003, 0x0080, 0x0006, 0x0020, 0x0003, 0x0040, 0x0006, 0x0040, 0x0003, 0x0080, 0x0006, 0x0060, +0x0000, 0x00a0, 0x0009, 0x00e0, 0x0000, 0x00e0, 0x000a, 0x0000, 0x0000, 0x00a0, 0x000a, 0x0020, 0x0000, 0x00e0, 0x000a, 0x0040, +0x0000, 0x00a0, 0x000a, 0x0060, 0x0000, 0x00e0, 0x000a, 0x0080, 0x0000, 0x00a0, 0x000a, 0x00a0, 0x0000, 0x00e0, 0x000a, 0x00c0 }; + +static const UINT16 f1dream_2450_lookup[32] = { +0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0, 0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0, +0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0, 0x0003, 0x0080, 0x0006, 0x0060, 0x0000, 0x00e0, 0x000a, 0x00c0 }; + +static void f1dream_protection_w() +{ + INT32 indx; + INT32 value = 255; + INT32 prevpc = SekGetPC(0)-8; + UINT16* ram16 = (UINT16*)Drv68KRAM; + + if (prevpc == 0x244c) + { + indx = ram16[0x3ff0/2]; + ram16[0x3fe6/2] = f1dream_2450_lookup[indx]; + ram16[0x3fe8/2] = f1dream_2450_lookup[++indx]; + ram16[0x3fea/2] = f1dream_2450_lookup[++indx]; + ram16[0x3fec/2] = f1dream_2450_lookup[++indx]; + } + else if (prevpc == 0x613a) + { + if (ram16[0x3ff6/2] < 15) + { + indx = f1dream_613ea_lookup[ram16[0x3ff6/2]] - ram16[0x3ff4/2]; + if (indx > 255) + { + indx <<= 4; + indx += ram16[0x3ff6/2] & 0x00ff; + value = f1dream_613eb_lookup[indx]; + } + } + + ram16[0x3ff2/2] = value; + } + else if (prevpc == 0x17b70) + { + if (ram16[0x3ff0/2] >= 0x04) indx = 128; + else if (ram16[0x3ff0/2] > 0x02) indx = 96; + else if (ram16[0x3ff0/2] == 0x02) indx = 64; + else if (ram16[0x3ff0/2] == 0x01) indx = 32; + else indx = 0; + + indx += ram16[0x3fee/2]; + if (indx < 128) + { + ram16[0x3fe6/2] = f1dream_17b74_lookup[indx]; + ram16[0x3fe8/2] = f1dream_17b74_lookup[++indx]; + ram16[0x3fea/2] = f1dream_17b74_lookup[++indx]; + ram16[0x3fec/2] = f1dream_17b74_lookup[++indx]; + } + else + { + ram16[0x3fe6/2] = 0x00ff; + ram16[0x3fe8/2] = 0x00ff; + ram16[0x3fea/2] = 0x00ff; + ram16[0x3fec/2] = 0x00ff; + } + } + else if ((prevpc == 0x27f8) || (prevpc == 0x511a) || (prevpc == 0x5142) || (prevpc == 0x516a)) + { + *soundlatch = ram16[0x3ffc/2] & 0xff; + } +} + +void __fastcall tigeroad_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0xfe4000: + *flipscreen = data & 0x02; + *bgcharbank = (data & 0x04) >> 2; + *coin_lockout = (~data & 0x30) << 1; + return; + + case 0xfe4002: + if (nF1dream) { + f1dream_protection_w(); + } else { + *soundlatch = data; + } + return; + } +} + +void __fastcall tigeroad_write_word(UINT32 address, UINT16 data) +{ + if (address >= 0xff8200 && address <= 0xff867f) { + *((UINT16*)(DrvPalRAM + (address - 0xff8000))) = data; + + palette_write(address - 0xff8200); + + return; + } + + switch (address) + { + case 0xfe8000: + case 0xfe8002: + *((UINT16 *)(DrvScrollRAM + (address & 2))) = data; + return; + + case 0xfe800e: + // watchdog + return; + } +} + +UINT8 __fastcall tigeroad_read_byte(UINT32 address) +{ + switch (address) + { + case 0xfe4000: + case 0xfe4001: + return DrvInputs[0] >> ((~address & 1) << 3); + + case 0xfe4002: + case 0xfe4003: + return DrvInputs[1] >> ((~address & 1) << 3); + + case 0xfe4004: + case 0xfe4005: + return DrvDip[~address & 1]; + } + + return 0; +} + +UINT16 __fastcall tigeroad_read_word(UINT32 address) +{ + switch (address) + { + case 0xfe4000: + return DrvInputs[0]; + + case 0xfe4002: + return DrvInputs[1]; + + case 0xfe4004: + return ((DrvDip[1] << 8) | DrvDip[0]); + } + + return 0; +} + +void __fastcall tigeroad_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8000: + BurnYM2203Write(0, 0, data); + return; + + case 0x8001: + BurnYM2203Write(0, 1, data); + return; + + case 0xa000: + BurnYM2203Write(1, 0, data); + return; + + case 0xa001: + BurnYM2203Write(1, 1, data); + return; + } +} + +void __fastcall tigeroad_sound_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x7f: + *soundlatch2 = data; + return; + } +} + +UINT8 __fastcall tigeroad_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8000: + return BurnYM2203Read(0, 0); + + case 0xa000: + return BurnYM2203Read(1, 0); + + case 0xe000: + return *soundlatch; + } + + return 0; +} + +void __fastcall tigeroad_sample_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x01: + MSM5205ResetWrite(0, (data >> 7) & 1); + MSM5205DataWrite(0, data); + MSM5205VCLKWrite(0, 1); + MSM5205VCLKWrite(0, 0); + return; + } +} + +UINT8 __fastcall tigeroad_sample_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return *soundlatch2; + } + + return 0; +} + +static void TigeroadIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 TigeroadSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static double TigeroadGetTime() +{ + return (double)ZetTotalCycles() / 3579545; +} + +inline static INT32 DrvMSM5205SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(SekTotalCycles() * nSoundRate / 10000000); +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2203Reset(); + + if (toramich) { + ZetOpen(1); + ZetReset(); + ZetClose(); + + MSM5205Reset(); + } + + if (pBurnSoundOut) { // fix ym2203 junk.. + memset (pBurnSoundOut, 0, nBurnSoundLen); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x008000; + DrvSndROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x020000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x008000; + + DrvPalette = (UINT32*)Next; Next += 0x0240 * sizeof(UINT32); + + DrvTransMask = Next; Next += 0x000010; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvVidRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x001400; + DrvSprBuf = Next; Next += 0x000500; + + DrvZ80RAM = Next; Next += 0x000800; + + DrvScrollRAM = Next; Next += 0x000004; + + soundlatch = Next; Next += 0x000001; + soundlatch2 = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + bgcharbank = Next; Next += 0x000001; + coin_lockout = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { ((0x20000 * 8) * 4) + 4, ((0x20000 * 8) * 4) + 0, 4, 0 }; + INT32 XOffs0[32] = { 0, 1, 2, 3, 8+0, 8+1, 8+2, 8+3, + 64*8+0, 64*8+1, 64*8+2, 64*8+3, 64*8+8+0, 64*8+8+1, 64*8+8+2, 64*8+8+3, + 2*64*8+0, 2*64*8+1, 2*64*8+2, 2*64*8+3, 2*64*8+8+0, 2*64*8+8+1, 2*64*8+8+2, 2*64*8+8+3, + 3*64*8+0, 3*64*8+1, 3*64*8+2, 3*64*8+3, 3*64*8+8+0, 3*64*8+8+1, 3*64*8+8+2, 3*64*8+8+3 }; + INT32 YOffs0[32] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, + 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16, + 16*16, 17*16, 18*16, 19*16, 20*16, 21*16, 22*16, 23*16, + 24*16, 25*16, 26*16, 27*16, 28*16, 29*16, 30*16, 31*16 }; + + INT32 Plane1[4] = { (0x20000*8)*3, (0x20000*8)*2, (0x20000*8)*1, (0x20000*8)*0 }; + INT32 XOffs1[16] = { 0, 1, 2, 3, 4, 5, 6, 7, + 16*8+0, 16*8+1, 16*8+2, 16*8+3, 16*8+4, 16*8+5, 16*8+6, 16*8+7 }; + INT32 YOffs1[16] = { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }; + + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x008000); + + GfxDecode(0x0800, 2, 8, 8, Plane0 + 2, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(0x0800, 4, 32, 32, Plane0 + 0, XOffs0, YOffs0, 0x800, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane1 + 0, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM2); + + for (INT32 i = 0; i < 16; i++) { + DrvTransMask[i] = (0xfe00 >> i) & 1; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit(INT32 (*pInitCallback)()) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (pInitCallback()) return 1; + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvSprRAM, 0xfe0800, 0xfe1bff, SM_RAM); + SekMapMemory(DrvVidRAM, 0xfec000, 0xfec7ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0xff8000, 0xff87ff, SM_ROM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteByteHandler(0, tigeroad_write_byte); + SekSetWriteWordHandler(0, tigeroad_write_word); + SekSetReadByteHandler(0, tigeroad_read_byte); + SekSetReadWordHandler(0, tigeroad_read_word); + SekClose(); + + if (toramich) { + ZetInit(2); + } else { + ZetInit(1); + } + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0xc000, 0xc7ff, 0, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 1, DrvZ80RAM); + ZetMapArea(0xc000, 0xc7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(tigeroad_sound_write); + ZetSetReadHandler(tigeroad_sound_read); + ZetSetOutHandler(tigeroad_sound_out); + ZetMemEnd(); + ZetClose(); + + if (toramich) { + ZetOpen(1); + ZetMapArea(0x0000, 0xffff, 0, DrvSndROM); + ZetMapArea(0x0000, 0xffff, 2, DrvSndROM); + ZetSetOutHandler(tigeroad_sample_out); + ZetSetInHandler(tigeroad_sample_in); + ZetMemEnd(); + ZetClose(); + } + + BurnYM2203Init(2, 3579545, &TigeroadIRQHandler, TigeroadSynchroniseStream, TigeroadGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(3579545); + + if (toramich) MSM5205Init(0, DrvMSM5205SynchroniseStream, 384000, NULL, MSM5205_SEX_4B, 100, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM2203Exit(); + MSM5205Exit(); + + GenericTilesExit(); + + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + nF1dream = 0; + toramich = 0; + + return 0; +} + +static void draw_sprites() +{ + UINT16 *source = (UINT16*)DrvSprBuf; + + for (INT32 offs = (0x500 - 8) / 2; offs >= 0; offs -=4) + { + INT32 tile_number = source[offs + 0]; + + if (tile_number != 0xfff) { + INT32 attr = source[offs + 1]; + INT32 sy = source[offs + 2] & 0x1ff; + INT32 sx = source[offs + 3] & 0x1ff; + + INT32 flipx = attr & 0x02; + INT32 flipy = attr & 0x01; + INT32 color = (attr >> 2) & 0x0f; + + if (sx > 0x100) sx -= 0x200; + if (sy > 0x100) sy -= 0x200; + + if (*flipscreen) + { + sx = 240 - sx; + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy = (240 - sy) - 16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, tile_number, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, tile_number, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, tile_number, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, tile_number, sx, sy, color, 4, 15, 0x100, DrvGfxROM2); + } + } + } + } +} + +static void draw_32x32_mask_tile(INT32 sx, INT32 sy, INT32 code, INT32 color, INT32 flipx, INT32 flipy) +{ + UINT8 *src = DrvGfxROM1 + (code * 0x400) + (flipy * 0x3e0); + UINT16 *dst; + + INT32 increment = flipy ? -32 : 32; + + for (INT32 y = 0; y < 32; y++, sy++) + { + if (sy >= nScreenHeight) break; + + if (sy >= 0) + { + dst = pTransDraw + (sy * nScreenWidth); + + if (flipx) { + for (INT32 x = 31; x >= 0; x--) + { + if ((sx+x) < 0 || (sx+x) >= nScreenWidth) continue; + + if (DrvTransMask[src[x^0x1f]]) + dst[sx+x] = src[x^0x1f] | color; + } + } else { + for (INT32 x = 0; x < 32; x++) + { + if ((sx+x) < 0 || (sx+x) >= nScreenWidth) continue; + + if (DrvTransMask[src[x]]) + dst[sx+x] = src[x] | color; + } + } + } + + src += increment; + } +} + +static void draw_background(INT32 priority) +{ + INT32 scrollx = *((UINT16*)(DrvScrollRAM + 0)); + INT32 scrolly = *((UINT16*)(DrvScrollRAM + 2)); + + scrollx &= 0xfff; + + scrolly = 0 - scrolly; + scrolly -= 0x100; + scrolly &= 0xfff; + + for (INT32 y = 0; y < 8+1; y++) + { + for (INT32 x = 0; x < 8+1; x++) + { + INT32 sx = x + (scrollx >> 5); + INT32 sy = y + (scrolly >> 5); + + INT32 ofst = ((sx & 7) << 1) + (((127 - sy) & 7) << 4) + ((sx >> 3) << 7) + (((127 - sy) >> 3) << 11); + + INT32 attr = DrvGfxROM3[ofst + 1]; + INT32 prio = attr & 0x10; + if (priority && !prio) continue; + + INT32 data = DrvGfxROM3[ofst]; + INT32 code = data + ((attr & 0xc0) << 2) + (*bgcharbank << 10); + INT32 color = attr & 0x0f; + INT32 flipx = attr & 0x20; + INT32 flipy = 0; + + sx = (x << 5) - (scrollx & 0x1f); + sy = (y << 5) - (scrolly & 0x1f); + + if (*flipscreen) { + flipx ^= 0x20; + flipy ^= 1; + + sx = 224 - sx; + sy = 224 - sy; + } + + if (!priority) { + if (flipy) { + if (flipx) { + Render32x32Tile_FlipXY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM1); + } else { + Render32x32Tile_FlipY_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render32x32Tile_FlipX_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM1); + } else { + Render32x32Tile_Clip(pTransDraw, code, sx, sy - 16, color, 4, 0, DrvGfxROM1); + } + } + } else { + draw_32x32_mask_tile(sx, sy - 16, code, color << 4, flipx, flipy); + } + } + } +} + +static void draw_text_layer() +{ + UINT16 *vram = (UINT16*)DrvVidRAM; + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 data = vram[offs]; + INT32 attr = data >> 8; + INT32 code = (data & 0xff) + ((attr & 0xc0) << 2) + ((attr & 0x20) << 5); + if (code == 0x400) continue; + + INT32 color = attr & 0x0f; + INT32 flipx = attr & 0x10; + INT32 flipy = 0; + + if (*flipscreen) { + sx ^= 0xf8; + sy ^= 0xf8; + flipx ^= 0x10; + flipy ^= 0x01; + } + + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy - 16, color, 2, 3, 0x200, DrvGfxROM0); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy - 16, color, 2, 3, 0x200, DrvGfxROM0); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx - 16, sy, color, 2, 3, 0x200, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy - 16, color, 2, 3, 0x200, DrvGfxROM0); + } + } + } +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x240 * 2; i+=2) { + palette_write(i); + } + } + + memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + draw_background(0); + draw_sprites(); + draw_background(1); + draw_text_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = ~0; + DrvInputs[1] = ~0; + + for (INT32 i = 0; i < 16; i++) + { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + + DrvInputs[1] |= *coin_lockout << 8; + } + + INT32 nCyclesTotal[3] = { 10000000 / 60, 3579545 / 60, 3579545 / 60 }; + INT32 nCyclesDone[3] = { 0, 0, 0 }; + + SekNewFrame(); + ZetNewFrame(); + + INT32 nInterleave = 10; + INT32 MSMIRQSlice[67]; + + if (toramich) { + nInterleave = MSM5205CalcInterleave(0, 10000000); + + for (INT32 i = 0; i < 67; i++) { + MSMIRQSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 68)); + } + } + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + MSM5205Update(); + SekClose(); + + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave)); + ZetClose(); + + if (toramich) { + nCurrentCPU = 2; + ZetOpen(1); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + for (INT32 j = 0; j < 67; j++) { + if (i == MSMIRQSlice[j]) { + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + nCyclesDone[nCurrentCPU] += ZetRun(1000); + } + } + ZetClose(); + } + } + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + if (toramich) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x500); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029698; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + } + + return 0; +} + + +// Tiger Road (US) + +static struct BurnRomInfo tigeroadRomDesc[] = { + { "tru02.bin", 0x20000, 0x8d283a95, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tru04.bin", 0x20000, 0x72e2ef20, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "tru05.bin", 0x08000, 0xf9a7c9bf, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "tr01.bin", 0x08000, 0x74a9f08c, 3 | BRF_GRA }, // 3 Character Tiles + + { "tr-01a.bin", 0x20000, 0xa8aa2e59, 4 | BRF_GRA }, // 4 Background Tiles + { "tr-04a.bin", 0x20000, 0x8863a63c, 4 | BRF_GRA }, // 5 + { "tr-02a.bin", 0x20000, 0x1a2c5f89, 4 | BRF_GRA }, // 6 + { "tr05.bin", 0x20000, 0x5bf453b3, 4 | BRF_GRA }, // 7 + { "tr-03a.bin", 0x20000, 0x1e0537ea, 4 | BRF_GRA }, // 8 + { "tr-06a.bin", 0x20000, 0xb636c23a, 4 | BRF_GRA }, // 9 + { "tr-07a.bin", 0x20000, 0x5f907d4d, 4 | BRF_GRA }, // 10 + { "tr08.bin", 0x20000, 0xadee35e2, 4 | BRF_GRA }, // 11 + + { "tr-09a.bin", 0x20000, 0x3d98ad1e, 5 | BRF_GRA }, // 12 Sprites + { "tr-10a.bin", 0x20000, 0x8f6f03d7, 5 | BRF_GRA }, // 13 + { "tr-11a.bin", 0x20000, 0xcd9152e5, 5 | BRF_GRA }, // 14 + { "tr-12a.bin", 0x20000, 0x7d8a99d0, 5 | BRF_GRA }, // 15 + + { "tr13.bin", 0x08000, 0xa79be1eb, 6 | BRF_GRA }, // 16 Background Tilemaps + + { "trprom.bin", 0x00100, 0xec80ae36, 7 | BRF_GRA | BRF_OPT }, // 17 Priority Proms (unused) +}; + +STD_ROM_PICK(tigeroad) +STD_ROM_FN(tigeroad) + +static INT32 TigeroadLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x20000, 4 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x20000, 12 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 16, 1)) return 1; + + if (toramich) if (BurnLoadRom(DrvSndROM + 0x000000, 18, 1)) return 1; + + return 0; +} + +static INT32 TigeroadInit() +{ + return DrvInit(TigeroadLoadRoms); +} + +struct BurnDriver BurnDrvTigeroad = { + "tigeroad", NULL, NULL, NULL, "1987", + "Tiger Road (US)\0", NULL, "Capcom (Romstar license)", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, tigeroadRomInfo, tigeroadRomName, NULL, NULL, TigeroadInputInfo, TigeroadDIPInfo, + TigeroadInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// Tora-he no Michi (Japan) + +static struct BurnRomInfo toramichRomDesc[] = { + { "tr_02.bin", 0x20000, 0xb54723b1, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tr_04.bin", 0x20000, 0xab432479, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "tr_05.bin", 0x08000, 0x3ebe6e62, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "tr01.bin", 0x08000, 0x74a9f08c, 3 | BRF_GRA }, // 3 Character Tiles + + { "tr-01a.bin", 0x20000, 0xa8aa2e59, 4 | BRF_GRA }, // 4 Background Tiles + { "tr-04a.bin", 0x20000, 0x8863a63c, 4 | BRF_GRA }, // 5 + { "tr-02a.bin", 0x20000, 0x1a2c5f89, 4 | BRF_GRA }, // 6 + { "tr05.bin", 0x20000, 0x5bf453b3, 4 | BRF_GRA }, // 7 + { "tr-03a.bin", 0x20000, 0x1e0537ea, 4 | BRF_GRA }, // 8 + { "tr-06a.bin", 0x20000, 0xb636c23a, 4 | BRF_GRA }, // 9 + { "tr-07a.bin", 0x20000, 0x5f907d4d, 4 | BRF_GRA }, // 10 + { "tr08.bin", 0x20000, 0xadee35e2, 4 | BRF_GRA }, // 11 + + { "tr-09a.bin", 0x20000, 0x3d98ad1e, 5 | BRF_GRA }, // 12 Sprites + { "tr-10a.bin", 0x20000, 0x8f6f03d7, 5 | BRF_GRA }, // 13 + { "tr-11a.bin", 0x20000, 0xcd9152e5, 5 | BRF_GRA }, // 14 + { "tr-12a.bin", 0x20000, 0x7d8a99d0, 5 | BRF_GRA }, // 15 + + { "tr13.bin", 0x08000, 0xa79be1eb, 6 | BRF_GRA }, // 16 Background Tilemaps + + { "trprom.bin", 0x00100, 0xec80ae36, 7 | BRF_GRA | BRF_OPT }, // 17 Priority Proms (unused) + + { "tr_03.bin", 0x10000, 0xea1807ef, 8 | BRF_PRG | BRF_ESS }, // 18 Sample Z80 Code +}; + +STD_ROM_PICK(toramich) +STD_ROM_FN(toramich) + +static INT32 ToramichInit() +{ + toramich = 1; + + return DrvInit(TigeroadLoadRoms); +} + +struct BurnDriver BurnDrvToramich = { + "toramich", "tigeroad", NULL, NULL, "1987", + "Tora-he no Michi (Japan)\0", NULL, "Capcom", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, toramichRomInfo, toramichRomName, NULL, NULL, TigeroadInputInfo, ToramichDIPInfo, + ToramichInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// Tiger Road (US bootleg) + +static struct BurnRomInfo tigerodbRomDesc[] = { + { "tgrroad.3", 0x10000, 0x14c87e07, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "tgrroad.5", 0x10000, 0x0904254c, 1 | BRF_PRG | BRF_ESS }, // 1 + { "tgrroad.2", 0x10000, 0xcedb1f46, 1 | BRF_PRG | BRF_ESS }, // 2 + { "tgrroad.4", 0x10000, 0xe117f0b1, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "tru05.bin", 0x08000, 0xf9a7c9bf, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "tr01.bin", 0x08000, 0x74a9f08c, 3 | BRF_GRA }, // 5 Character Tiles + + { "tr-01a.bin", 0x20000, 0xa8aa2e59, 4 | BRF_GRA }, // 6 Background Tiles + { "tr-04a.bin", 0x20000, 0x8863a63c, 4 | BRF_GRA }, // 7 + { "tr-02a.bin", 0x20000, 0x1a2c5f89, 4 | BRF_GRA }, // 8 + { "tr05.bin", 0x20000, 0x5bf453b3, 4 | BRF_GRA }, // 9 + { "tr-03a.bin", 0x20000, 0x1e0537ea, 4 | BRF_GRA }, // 10 + { "tr-06a.bin", 0x20000, 0xb636c23a, 4 | BRF_GRA }, // 11 + { "tr-07a.bin", 0x20000, 0x5f907d4d, 4 | BRF_GRA }, // 12 + { "tgrroad.17", 0x10000, 0x3f7539cc, 4 | BRF_GRA }, // 13 + { "tgrroad.18", 0x10000, 0xe2e053cb, 4 | BRF_GRA }, // 14 + + { "tr-09a.bin", 0x20000, 0x3d98ad1e, 5 | BRF_GRA }, // 15 Sprites + { "tr-10a.bin", 0x20000, 0x8f6f03d7, 5 | BRF_GRA }, // 16 + { "tr-11a.bin", 0x20000, 0xcd9152e5, 5 | BRF_GRA }, // 17 + { "tr-12a.bin", 0x20000, 0x7d8a99d0, 5 | BRF_GRA }, // 18 + + { "tr13.bin", 0x08000, 0xa79be1eb, 6 | BRF_GRA }, // 19 Background Tilemaps + + { "trprom.bin", 0x00100, 0xec80ae36, 7 | BRF_GRA | BRF_OPT }, // 20 Priority Proms (unused) +}; + +STD_ROM_PICK(tigerodb) +STD_ROM_FN(tigerodb) + +static INT32 TigerodbLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x20000, 6 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM1 + 0xf0000, 14, 1)) return 1; + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x20000, 15 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 19, 1)) return 1; + + return 0; +} + +static INT32 TigerodbInit() +{ + return DrvInit(TigerodbLoadRoms); +} + +struct BurnDriver BurnDrvTigerodb = { + "tigeroadb", "tigeroad", NULL, NULL, "1987", + "Tiger Road (US bootleg)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT | GBF_PLATFORM, 0, + NULL, tigerodbRomInfo, tigerodbRomName, NULL, NULL, TigeroadInputInfo, TigeroadDIPInfo, + TigerodbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// F-1 Dream + +static struct BurnRomInfo f1dreamRomDesc[] = { + { "06j_02.bin", 0x20000, 0x3c2ec697, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "06k_03.bin", 0x20000, 0x85ebad91, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "12k_04.bin", 0x08000, 0x4b9a7524, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "10d_01.bin", 0x08000, 0x361caf00, 3 | BRF_GRA }, // 3 Character Tiles + + { "03f_12.bin", 0x10000, 0xbc13e43c, 4 | BRF_GRA }, // 4 Background Tiles + { "01f_10.bin", 0x10000, 0xf7617ad9, 4 | BRF_GRA }, // 5 + { "03h_14.bin", 0x10000, 0xe33cd438, 4 | BRF_GRA }, // 6 + { "02f_11.bin", 0x10000, 0x4aa49cd7, 4 | BRF_GRA }, // 7 + { "17f_09.bin", 0x10000, 0xca622155, 4 | BRF_GRA }, // 8 + { "02h_13.bin", 0x10000, 0x2a63961e, 4 | BRF_GRA }, // 9 + + { "03b_06.bin", 0x10000, 0x5e54e391, 5 | BRF_GRA }, // 10 Sprites + { "02b_05.bin", 0x10000, 0xcdd119fd, 5 | BRF_GRA }, // 11 + { "03d_08.bin", 0x10000, 0x811f2e22, 5 | BRF_GRA }, // 12 + { "02d_07.bin", 0x10000, 0xaa9a1233, 5 | BRF_GRA }, // 13 + + { "07l_15.bin", 0x08000, 0x978758b7, 6 | BRF_GRA }, // 14 Background Tilemaps + + { "09e_tr.bin", 0x00100, 0xec80ae36, 7 | BRF_GRA | BRF_OPT }, // 15 Priority Proms (unused) + + { "c8751h-88", 0x01000, 0x00000000, 0 | BRF_OPT | BRF_NODUMP }, +}; + +STD_ROM_PICK(f1dream) +STD_ROM_FN(f1dream) + +static INT32 F1dreamLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 3, 1)) return 1; + + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(DrvGfxROM1 + 0x00000 + i * 0x10000, 4 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000 + i * 0x10000, 7 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x20000, 10 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 14, 1)) return 1; + + return 0; +} + +static INT32 F1dreamInit() +{ + nF1dream = 1; + + return DrvInit(F1dreamLoadRoms); +} + +struct BurnDriver BurnDrvF1dream = { + "f1dream", NULL, NULL, NULL, "1988", + "F-1 Dream\0", NULL, "Capcom (Romstar license)", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, f1dreamRomInfo, f1dreamRomName, NULL, NULL, TigeroadInputInfo, F1dreamDIPInfo, + F1dreamInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; + + +// F-1 Dream (bootleg) + +static struct BurnRomInfo f1dreambRomDesc[] = { + { "f1d_04.bin", 0x10000, 0x903febad, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "f1d_05.bin", 0x10000, 0x666fa2a7, 1 | BRF_PRG | BRF_ESS }, // 1 + { "f1d_02.bin", 0x10000, 0x98973c4c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "f1d_03.bin", 0x10000, 0x3d21c78a, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "12k_04.bin", 0x08000, 0x4b9a7524, 2 | BRF_PRG | BRF_ESS }, // 4 Z80 Code + + { "10d_01.bin", 0x08000, 0x361caf00, 3 | BRF_GRA }, // 5 Character Tiles + + { "03f_12.bin", 0x10000, 0xbc13e43c, 4 | BRF_GRA }, // 6 Background Tiles + { "01f_10.bin", 0x10000, 0xf7617ad9, 4 | BRF_GRA }, // 7 + { "03h_14.bin", 0x10000, 0xe33cd438, 4 | BRF_GRA }, // 8 + { "02f_11.bin", 0x10000, 0x4aa49cd7, 4 | BRF_GRA }, // 9 + { "17f_09.bin", 0x10000, 0xca622155, 4 | BRF_GRA }, // 10 + { "02h_13.bin", 0x10000, 0x2a63961e, 4 | BRF_GRA }, // 11 + + { "03b_06.bin", 0x10000, 0x5e54e391, 5 | BRF_GRA }, // 12 Sprites + { "02b_05.bin", 0x10000, 0xcdd119fd, 5 | BRF_GRA }, // 13 + { "03d_08.bin", 0x10000, 0x811f2e22, 5 | BRF_GRA }, // 14 + { "02d_07.bin", 0x10000, 0xaa9a1233, 5 | BRF_GRA }, // 15 + + { "07l_15.bin", 0x08000, 0x978758b7, 6 | BRF_GRA }, // 16 Background Tilemaps + + { "09e_tr.bin", 0x00100, 0xec80ae36, 7 | BRF_GRA | BRF_OPT }, // 17 Priority Proms (unused) +}; + +STD_ROM_PICK(f1dreamb) +STD_ROM_FN(f1dreamb) + +static INT32 F1dreambLoadRoms() +{ + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x020000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 5, 1)) return 1; + + for (INT32 i = 0; i < 3; i++) { + if (BurnLoadRom(DrvGfxROM1 + 0x00000 + i * 0x10000, 6 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000 + i * 0x10000, 9 + i, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(DrvGfxROM2 + i * 0x20000, 12 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 16, 1)) return 1; + + return 0; +} + +static INT32 F1dreambInit() +{ + return DrvInit(F1dreambLoadRoms); +} + +struct BurnDriver BurnDrvF1dreamb = { + "f1dreamb", "f1dream", NULL, NULL, "1988", + "F-1 Dream (bootleg)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0, + NULL, f1dreambRomInfo, f1dreambRomName, NULL, NULL, TigeroadInputInfo, F1dreamDIPInfo, + F1dreambInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x240, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_tnzs.cpp b/src/burn/drivers/misc_pre90s/d_tnzs.cpp new file mode 100644 index 00000000..ab403ef0 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_tnzs.cpp @@ -0,0 +1,2728 @@ +// FB Alpha The NewZealand Story driver module +// Based on MAME driver by Chris Moore, Brad Oliver, Nicola Salmoria, and many others + +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "burn_ym2151.h" +#include "tnzs_prot.h" +#include "dac.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM0; +static UINT8 *DrvZ80ROM1; +static UINT8 *DrvZ80ROM2; +static UINT8 *DrvGfxROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvShareRAM; +static UINT8 *DrvScrollRAM; +static UINT8 *DrvVidRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvZ80RAM0; +static UINT8 *DrvZ80RAM1; +static UINT8 *DrvZ80RAM2; +static UINT8 *DrvObjCtrl; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *coin_lockout; +static UINT8 *soundlatch; +static UINT8 *tnzs_bg_flag; + +static INT32 kageki_csport_sel; +static double kageki_sample_pos; +static INT32 kageki_sample_select; +static INT16 *kageki_sample_data[0x30]; +static INT32 kageki_sample_size[0x30]; + +static INT32 cpu1_reset; +static INT32 tnzs_banks[3]; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvDips[2]; +static UINT8 DrvInputs[3]; +static UINT8 DrvReset; + +static UINT16 DrvAxis[2]; +static INT32 nAnalogAxis[2] = {0,0}; + +static INT16 *SampleBuffer = NULL; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common) + +static struct BurnInputInfo InsectxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Insectx) + +static struct BurnInputInfo Arknoid2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 x-axis" ), + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 3, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 0, "p2 fire 1" }, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 1, "p2 x-axis" ), + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy2 + 5, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy2 + 7, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Arknoid2) + +static struct BurnInputInfo PlumppopInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 x-axis" ), + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 1, "p2 x-axis" ), + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Plumppop) + +static struct BurnInputInfo JpopnicsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 6, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 x-axis" ), + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 6, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + A("P2 Right / left", BIT_ANALOG_REL, DrvAxis + 1, "p2 x-axis" ), + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Jpopnics) + +static struct BurnDIPInfo ExtrmatnDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Damage Multiplier" }, + {0x14, 0x01, 0xc0, 0xc0, "*1" }, + {0x14, 0x01, 0xc0, 0x80, "*1.5" }, + {0x14, 0x01, 0xc0, 0x40, "*2" }, + {0x14, 0x01, 0xc0, 0x00, "*3" }, +}; + +STDDIPINFO(Extrmatn) + +static struct BurnDIPInfo DrtoppelDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_WORLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "30k 100k 200k 100k+" }, + {0x14, 0x01, 0x0c, 0x00, "50k 100k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x04, "30k 100k" }, + {0x14, 0x01, 0x0c, 0x08, "30k only" }, + + TNZS_LIVES_DIPSETTING(0x14) +}; + +STDDIPINFO(Drtoppel) + +static struct BurnDIPInfo DrtoppluDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "30k 100k 200k 100k+" }, + {0x14, 0x01, 0x0c, 0x00, "50k 100k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x04, "30k 100k" }, + {0x14, 0x01, 0x0c, 0x08, "30k only" }, + + TNZS_LIVES_DIPSETTING(0x14) +}; + +STDDIPINFO(Drtopplu) + +static struct BurnDIPInfo ChukataiDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_WORLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "100k 300k 440k" }, + {0x14, 0x01, 0x0c, 0x00, "100k 300k 500k" }, + {0x14, 0x01, 0x0c, 0x0c, "100k 400k" }, + {0x14, 0x01, 0x0c, 0x04, "100k 500k" }, + + TNZS_LIVES_DIPSETTING(0x14) +}; + +STDDIPINFO(Chukatai) + +static struct BurnDIPInfo ChukatauDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "100k 300k 440k" }, + {0x14, 0x01, 0x0c, 0x00, "100k 300k 500k" }, + {0x14, 0x01, 0x0c, 0x0c, "100k 400k" }, + {0x14, 0x01, 0x0c, 0x04, "100k 500k" }, + + TNZS_LIVES_DIPSETTING(0x14) +}; + +STDDIPINFO(Chukatau) + +static struct BurnDIPInfo TnzsDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_COINAGE_WORLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x00, "50k 150k 150k+" }, + {0x14, 0x01, 0x0c, 0x0c, "70k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x04, "100k 250k 250k+" }, + {0x14, 0x01, 0x0c, 0x08, "200k 300k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x14) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x14, 0x40) +}; + +STDDIPINFO(Tnzs) + +static struct BurnDIPInfo TnzsjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x00, "50k 150k 150k+" }, + {0x14, 0x01, 0x0c, 0x0c, "70k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x04, "100k 250k 250k+" }, + {0x14, 0x01, 0x0c, 0x08, "200k 300k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x14) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x14, 0x40) +}; + +STDDIPINFO(Tnzsj) + +static struct BurnDIPInfo TnzsjoDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + {0 , 0xfe, 0 , 4, "Invulnerability (Debug)" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x00, "50k 150k 150k+" }, + {0x14, 0x01, 0x0c, 0x0c, "70k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x04, "100k 250k 250k+" }, + {0x14, 0x01, 0x0c, 0x08, "200k 300k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x14) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x14, 0x40) +}; + +STDDIPINFO(Tnzsjo) + +static struct BurnDIPInfo TnzsopDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_COINAGE_WORLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x00, "10k 100k 100k+" }, + {0x14, 0x01, 0x0c, 0x0c, "10k 150k 150k+" }, + {0x14, 0x01, 0x0c, 0x04, "10k 200k 200k+" }, + {0x14, 0x01, 0x0c, 0x08, "10k 300k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x14) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x14, 0x40) +}; + +STDDIPINFO(Tnzsop) + +static struct BurnDIPInfo InsectxDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_WORLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "100k 200k 300k 440k" }, + {0x14, 0x01, 0x0c, 0x0c, "100k 400k" }, + {0x14, 0x01, 0x0c, 0x04, "100k 500k" }, + {0x14, 0x01, 0x0c, 0x00, "150000 Only" }, + + TNZS_LIVES_DIPSETTING(0x14) +}; + +STDDIPINFO(Insectx) + +static struct BurnDIPInfo KagekiDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Cabinet type in Japan set only + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_COINAGE_JAPAN_OLD(0x13) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x14, 0x80) +}; + +STDDIPINFO(Kageki) + +static struct BurnDIPInfo Arknoid2DIPList[]= +{ + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x0b) + + TNZS_DEMOSOUNDS_DIPSETTING(0x0b) + + TNZS_COINAGE_WORLD(0x0b) + + TNZS_DIFFICULTY_DIPSETTING(0x0c) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0c, 0x01, 0x0c, 0x00, "50k 150k" }, + {0x0c, 0x01, 0x0c, 0x0c, "100k 200k" }, + {0x0c, 0x01, 0x0c, 0x04, "50k Only" }, + {0x0c, 0x01, 0x0c, 0x08, "100k Only" }, + + TNZS_LIVES_DIPSETTING(0x0c) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x0c, 0x80) +}; + +STDDIPINFO(Arknoid2) + +static struct BurnDIPInfo Arknid2uDIPList[]= +{ + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x0b) + + TNZS_DEMOSOUNDS_DIPSETTING(0x0b) + + TNZS_COINAGE_JAPAN_OLD(0x0b) + + TNZS_DIFFICULTY_DIPSETTING(0x0c) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0c, 0x01, 0x0c, 0x00, "50k 150k" }, + {0x0c, 0x01, 0x0c, 0x0c, "100k 200k" }, + {0x0c, 0x01, 0x0c, 0x04, "50k Only" }, + {0x0c, 0x01, 0x0c, 0x08, "100k Only" }, + + TNZS_LIVES_DIPSETTING(0x0c) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x0c, 0x80) +}; + +STDDIPINFO(Arknid2u) + +static struct BurnDIPInfo PlumppopDIPList[]= +{ + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x0d) + + TNZS_DEMOSOUNDS_DIPSETTING(0x0d) + + TNZS_COINAGE_JAPAN_OLD(0x0d) + + TNZS_DIFFICULTY_DIPSETTING(0x0e) + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x0e, 0x01, 0x0c, 0x08, "50k 200k 150k+" }, + {0x0e, 0x01, 0x0c, 0x0c, "50k 250k 200k+" }, + {0x0e, 0x01, 0x0c, 0x04, "100k 300k 200k+" }, + {0x0e, 0x01, 0x0c, 0x00, "100k 400k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x0e) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x0c, 0x80) +}; + +STDDIPINFO(Plumppop) + +static struct BurnDIPInfo JpopnicsDIPList[]= +{ + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x0b) + + TNZS_DEMOSOUNDS_DIPSETTING(0x0b) + + TNZS_DIFFICULTY_DIPSETTING(0x0c) + + {0 , 0xfe, 0 , 0, "Bonus Life" }, + {0x0c, 0x01, 0x0c, 0x08, "50k 200k 150k+" }, + {0x0c, 0x01, 0x0c, 0x0c, "50k 250k 200k+" }, + {0x0c, 0x01, 0x0c, 0x04, "100k 300k 200k+" }, + {0x0c, 0x01, 0x0c, 0x00, "100k 400k 300k+" }, + + TNZS_LIVES_DIPSETTING(0x0c) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x0c, 0x80) +}; + +STDDIPINFO(Jpopnics) + +static struct BurnDIPInfo KabukizDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x13, 0x80) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + TNZS_COINAGE_WORLD(0x14) +}; + +STDDIPINFO(Kabukiz) + +static struct BurnDIPInfo KabukizjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + TNZS_CABINET_FLIP_SERVICE_DIPSETTING(0x13) + + TNZS_DEMOSOUNDS_DIPSETTING(0x13) + + TNZS_ALLOWCONTINUE_DIPSETTING(0x13, 0x80) + + TNZS_DIFFICULTY_DIPSETTING(0x14) + + TNZS_COINAGE_JAPAN_OLD(0x14) +}; + +STDDIPINFO(Kabukizj) + +void __fastcall bankswitch0(UINT8 data) +{ + // CPU #0 expects CPU #1 to be stopped while reset line is triggered. + if ((~data & 0x10) != cpu1_reset) { + INT32 cycles = ZetTotalCycles(); + ZetClose(); + ZetOpen(1); + cycles -= ZetTotalCycles(); + ZetIdle(cycles); + if (~data & 0x10) ZetReset(); + ZetClose(); + ZetOpen(0); + } + + cpu1_reset = ~data & 0x10; + + tnzs_banks[0] = data; + + INT32 bank = (data & 7) * 0x4000; + + // Low banks are RAM regions high ones are ROM. + if ((data & 6) == 0) { + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80RAM0 + bank); + ZetMapArea(0x8000, 0xbfff, 1, DrvZ80RAM0 + bank); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80RAM0 + bank); + } else { + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + 0x10000 + bank); + ZetMapArea(0x8000, 0xbfff, 1, DrvZ80ROM0 + 0x10000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + 0x10000 + bank); + } +} + +void __fastcall bankswitch1(UINT8 data) +{ + tnzs_banks[1] = data & ~0x04; + + if (data & 0x04) { + tnzs_mcu_reset(); + } + + *coin_lockout = ~data & 0x30; + + ZetMapArea(0x8000, 0x9fff, 0, DrvZ80ROM1 + 0x08000 + 0x2000 * (data & 3)); + ZetMapArea(0x8000, 0x9fff, 2, DrvZ80ROM1 + 0x08000 + 0x2000 * (data & 3)); +} + +void __fastcall tnzs_cpu0_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xf400: + *tnzs_bg_flag = data; + break; + + case 0xf600: + bankswitch0(data); + break; + } + + if ((address & 0xff00) == 0xf300) { + DrvObjCtrl[address & 3] = data; + return; + } +} + +UINT8 __fastcall tnzs_cpu0_read(UINT16 address) +{ + // This is a hack to keep tnzs & clones from freezing. The sub cpu + // writes back 0xff to shared ram as an acknowledge and the main + // cpu doesn't expect it so soon. This can be fixed by an extremely + // high sync, but this hack is much less costly. + if ((address & 0xf000) == 0xe000) { + if (address == 0xef10 && DrvShareRAM[0x0f10] == 0xff) { + return 0; + } + return DrvShareRAM[address & 0xfff]; + } + + return 0; +} + +void __fastcall tnzsb_cpu1_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xa000: + bankswitch1(data); + break; + + case 0xb004: + *soundlatch = data; + ZetClose(); + ZetOpen(2); + ZetSetVector(0xff); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(1); + break; + } +} + +UINT8 __fastcall tnzsb_cpu1_read(UINT16 address) +{ + switch (address) + { + case 0xb002: + return DrvDips[0]; + + case 0xb003: + return DrvDips[1]; + + case 0xc000: + case 0xc001: + return DrvInputs[address & 1]; + + case 0xc002: + return DrvInputs[2] | *coin_lockout; + } + + if (address >= 0xf000 && address <= 0xf003) { + return DrvPalRAM[address & 0x0003]; + } + + return 0; +} + +void __fastcall tnzs_cpu1_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xa000: + bankswitch1(data); + break; + + case 0xb000: + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + BurnYM2151SelectRegister(data); + } else { + BurnYM2203Write(0, 0, data); + } + break; + + case 0xb001: + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + BurnYM2151WriteRegister(data); + } else { + BurnYM2203Write(0, 1, data); + } + break; + + case 0xc000: + case 0xc001: + tnzs_mcu_write(address, data); + break; + } +} + +UINT8 __fastcall tnzs_cpu1_read(UINT16 address) +{ + switch (address) + { + case 0xb000: + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) + return 0; + return BurnYM2203Read(0, 0); + + case 0xb001: + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) + return BurnYM2151ReadStatus(); + return BurnYM2203Read(0, 1); + + case 0xc000: + case 0xc001: + return tnzs_mcu_read(address); + + case 0xc002: + return DrvInputs[2]; + + case 0xc600: + return DrvDips[0]; + + case 0xc601: + return DrvDips[1]; + + case 0xf000: + return (~nAnalogAxis[0] >> 12) & 0xff; + + case 0xf001: + return (~nAnalogAxis[0] >> 20) & 0x0f; + + case 0xf002: + return (~nAnalogAxis[1] >> 12) & 0xff; + + case 0xf003: + return (~nAnalogAxis[1] >> 20) & 0x0f; + } + + return 0; +} + +void __fastcall tnzs_cpu2_out(UINT16 port, UINT8 data) +{ + switch (port & 0xff) + { + case 0x00: + BurnYM2203Write(0, 0, data); + break; + + case 0x01: + BurnYM2203Write(0, 1, data); + break; + } +} + +UINT8 __fastcall tnzs_cpu2_in(UINT16 port) +{ + switch (port & 0xff) + { + case 0x00: + return BurnYM2203Read(0, 0); + + case 0x02: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static void kabukiz_sound_bankswitch(UINT32, UINT32 data) +{ + if (data != 0xff) { + tnzs_banks[2] = data; + + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM2 + 0x0000 + 0x4000 * (data & 0x07)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM2 + 0x0000 + 0x4000 * (data & 0x07)); + } +} + +static void kabukiz_dac_write(UINT32, UINT32 data) +{ + if (data != 0xff) { + DACWrite(0, data); + } +} + +static UINT8 tnzs_ym2203_portA(UINT32 ) +{ + return DrvDips[0]; +} + +static UINT8 tnzs_ym2203_portB(UINT32 ) +{ + return DrvDips[1]; +} + +static UINT8 kageki_ym2203_portA(UINT32) +{ + INT32 dsw1 = DrvDips[0]; + INT32 dsw2 = DrvDips[1]; + UINT8 dsw = 0x0f; + + switch (kageki_csport_sel & 3) + { + case 0x00: + dsw = (((dsw2 & 0x10) >> 1) | ((dsw2 & 0x01) << 2) | ((dsw1 & 0x10) >> 3) | ((dsw1 & 0x01) >> 0)); + break; + + case 0x01: + dsw = (((dsw2 & 0x40) >> 3) | ((dsw2 & 0x04) >> 0) | ((dsw1 & 0x40) >> 5) | ((dsw1 & 0x04) >> 2)); + break; + + case 0x02: + dsw = (((dsw2 & 0x20) >> 2) | ((dsw2 & 0x02) << 1) | ((dsw1 & 0x20) >> 4) | ((dsw1 & 0x02) >> 1)); + break; + + case 0x03: + dsw = (((dsw2 & 0x80) >> 4) | ((dsw2 & 0x08) >> 1) | ((dsw1 & 0x80) >> 6) | ((dsw1 & 0x08) >> 3)); + break; + } + + return dsw; +} + +static void kageki_ym2203_write_portB(UINT32, UINT32 data) +{ + if (data > 0x3f) { + kageki_csport_sel = data; + } else { + if (data > 0x2f) { + kageki_sample_select = -1; + } else { + kageki_sample_select = data; + kageki_sample_pos = 0; + } + } +} + +inline static void DrvYM2203IRQHandler(INT32, INT32 nStatus) +{ + Z80SetIrqLine(Z80_INPUT_LINE_NMI, nStatus & 1); +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 6000000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + memcpy (DrvPalRAM, DrvColPROM, 0x400); + + cpu1_reset = 0; + + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + if (i == 0) bankswitch0(0x12); + if (i == 1) bankswitch1(0); + if (i == 2) kabukiz_sound_bankswitch(0, 0); + ZetClose(); + } + + tnzs_mcu_reset(); + + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + BurnYM2151Reset(); + } else { + BurnYM2203Reset(); + } + + DACReset(); + + kageki_sample_pos = 0; + kageki_sample_select = -1; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM0 = Next; Next += 0x040000; + DrvZ80ROM1 = Next; Next += 0x020000; + DrvZ80ROM2 = Next; Next += 0x020000; + + DrvGfxROM = Next; Next += 0x400000; + + DrvColPROM = Next; Next += 0x000400; + + DrvSndROM = Next; Next += 0x010000; + + DrvPalette = (UINT32*)Next; Next += 0x0200 * sizeof(UINT32); + + SampleBuffer = (INT16*)Next; Next += nBurnSoundLen * 2 * sizeof(INT16); + + AllRam = Next; + + DrvObjCtrl = Next; Next += 0x000004; + + DrvPalRAM = Next; Next += 0x000400; + DrvSprRAM = Next; Next += 0x002000; + DrvShareRAM = Next; Next += 0x001000; + DrvScrollRAM = Next; Next += 0x000100; + DrvVidRAM = Next; Next += 0x000200; + + DrvZ80RAM0 = Next; Next += 0x008000; + DrvZ80RAM1 = Next; Next += 0x001000; + DrvZ80RAM2 = Next; Next += 0x002000; + + coin_lockout = Next; Next += 0x000001; + soundlatch = Next; Next += 0x000001; + tnzs_bg_flag = Next; Next += 0x000001; + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void kageki_sample_init() +{ + UINT8 *src = DrvSndROM + 0x0090; + + for (INT32 i = 0; i < 0x2f; i++) + { + INT32 start = (src[(i * 2) + 1] << 8) + src[(i * 2)]; + UINT8 *scan = &src[start]; + INT32 size = 0; + + while (1) { + if (*scan++ == 0x00) { + break; + } else { + size++; + } + } + + kageki_sample_data[i] = (INT16*)BurnMalloc(size * sizeof(INT16)); + kageki_sample_size[i] = size; + + if (start < 0x100) start = size = 0; + + INT16 *dest = kageki_sample_data[i]; + scan = &src[start]; + for (INT32 n = 0; n < size; n++) + { + *dest++ = ((*scan++) ^ 0x80) << 8; + } + } +} + +static void kageki_sample_exit() +{ + for (INT32 i = 0; i < 0x30; i++) { + BurnFree (kageki_sample_data[i]); + } +} + +static INT32 tnzs_gfx_decode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x200000); + + static INT32 Plane[4] = { 0xc00000, 0x800000, 0x400000, 0x000000 }; + static INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; + static INT32 YOffs[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + + GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM); + + // the drawing routines allow for 0x4000 tiles, but some (most) games + // only have 0x2000. Mirroring the second half is cheaper and easier than + // masking the tile code. + if (memcmp (DrvGfxROM + 0x200000, DrvGfxROM + 0x300000, 0x100000) == 0) { + memcpy (DrvGfxROM + 0x200000, DrvGfxROM + 0x000000, 0x200000); + } + + BurnFree (tmp); + + return 0; +} + +static INT32 insectx_gfx_decode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x100000); + + static INT32 Plane[4] = { 0x000008, 0x000000, 0x400008, 0x400000 }; + static INT32 XOffs[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; + static INT32 YOffs[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 256, 272, 288, 304, 320, 336, 352, 368 }; + + GfxDecode(0x2000, 4, 16, 16, Plane, XOffs, YOffs, 0x200, tmp, DrvGfxROM); + + memcpy (DrvGfxROM + 0x200000, DrvGfxROM + 0x000000, 0x200000); + + BurnFree (tmp); + + return 0; +} + +static INT32 Type1Init(INT32 mcutype) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + switch (mcutype) + { + case MCU_CHUKATAI: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 11, 1)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_TNZS: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 10, 1)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_DRTOPPEL: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 11, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00001, 12, 2)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00000, 13, 2)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_EXTRMATN: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 7, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00001, 8, 2)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00000, 9, 2)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_NONE_INSECTX: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 3, 1)) return 1; + + insectx_gfx_decode(); + } + break; + + case MCU_ARKANOID: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 6, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00001, 7, 2)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00000, 8, 2)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_PLUMPOP: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x010000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x030000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x090000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0b0000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x110000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x130000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x190000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1b0000, 11, 1)) return 1; + + if (BurnLoadRom(DrvColPROM + 0x00001, 12, 2)) return 1; + if (BurnLoadRom(DrvColPROM + 0x00000, 13, 2)) return 1; + + if (tnzs_gfx_decode()) return 1; + } + break; + + case MCU_NONE_KAGEKI: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + if (BurnLoadRom(DrvZ80ROM0 + 0x20000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 11, 1)) return 1; + + if (tnzs_gfx_decode()) return 1; + + kageki_sample_init(); + } + break; + + case MCU_NONE_JPOPNICS: + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0 + 0x00000, DrvZ80ROM0 + 0x10000, 0x08000); + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x000000, 2, 1)) return 1; + memcpy (DrvGfxROM + 0x020000, DrvGfxROM + 0x010000, 0x010000); + if (BurnLoadRom(DrvGfxROM + 0x080000, 3, 1)) return 1; + memcpy (DrvGfxROM + 0x0a0000, DrvGfxROM + 0x090000, 0x010000); + if (BurnLoadRom(DrvGfxROM + 0x100000, 4, 1)) return 1; + memcpy (DrvGfxROM + 0x120000, DrvGfxROM + 0x110000, 0x010000); + if (BurnLoadRom(DrvGfxROM + 0x180000, 5, 1)) return 1; + memcpy (DrvGfxROM + 0x1a0000, DrvGfxROM + 0x190000, 0x010000); + + if (tnzs_gfx_decode()) return 1; + } + break; + } + + ZetInit(3); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + 0x18000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + 0x18000); + ZetMapArea(0xc000, 0xdfff, 0, DrvSprRAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvSprRAM); + ZetMapArea(0xe000, 0xeeff, 0, DrvShareRAM); + if (mcutype != MCU_TNZS) { + ZetMapArea(0xef00, 0xefff, 0, DrvShareRAM + 0x0f00); + } + ZetMapArea(0xe000, 0xefff, 1, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvShareRAM); + ZetMapArea(0xf000, 0xf1ff, 0, DrvVidRAM); + ZetMapArea(0xf000, 0xf1ff, 1, DrvVidRAM); + ZetMapArea(0xf200, 0xf2ff, 1, DrvScrollRAM); + if (mcutype != MCU_DRTOPPEL) { + ZetMapArea(0xf800, 0xfbff, 0, DrvPalRAM); + ZetMapArea(0xf800, 0xfbff, 1, DrvPalRAM); + } + ZetSetWriteHandler(tnzs_cpu0_write); + ZetSetReadHandler(tnzs_cpu0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x9fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x9fff, 2, DrvZ80ROM1); + ZetMapArea(0xd000, 0xdfff, 0, DrvZ80RAM1); + ZetMapArea(0xd000, 0xdfff, 1, DrvZ80RAM1); + ZetMapArea(0xd000, 0xdfff, 2, DrvZ80RAM1); + ZetMapArea(0xe000, 0xefff, 0, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 1, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvShareRAM); + ZetSetWriteHandler(tnzs_cpu1_write); + ZetSetReadHandler(tnzs_cpu1_read); + ZetMemEnd(); + ZetClose(); + + tnzs_mcu_init(mcutype); + + if (mcutype == MCU_NONE_JPOPNICS) { + BurnYM2151Init(3000000, 30.0); // jpopnics + } else { + BurnYM2203Init(1, 3000000, NULL, DrvSynchroniseStream, DrvGetTime, 0); + + if (mcutype == MCU_NONE_KAGEKI) { + BurnYM2203SetPorts(0, &kageki_ym2203_portA, NULL, NULL, &kageki_ym2203_write_portB); + BurnYM2203SetVolumeShift(2); + } else { + BurnYM2203SetPorts(0, &tnzs_ym2203_portA, &tnzs_ym2203_portB, NULL, NULL); + } + + if (mcutype == MCU_EXTRMATN || mcutype == MCU_DRTOPPEL) { + BurnYM2203SetVolumeShift(2); + } + } + + DACInit(0, 0, 0); // kabukiz + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 Type2Init() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM0 + 0x10000, 0, 1)) return 1; + memcpy (DrvZ80ROM0, DrvZ80ROM0 + 0x10000, 0x08000); + + if (BurnLoadRom(DrvZ80ROM1 + 0x00000, 1, 1)) return 1; + + if (BurnLoadRom(DrvZ80ROM2 + 0x00000, 2, 1)) return 1; + + if (strncmp(BurnDrvGetTextA(DRV_NAME), "kabukiz", 7) == 0) { + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 6, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x020000, 4, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x080000, 5, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x0a0000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x100000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x120000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x180000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1a0000, 10, 1)) return 1; + } + + if (tnzs_gfx_decode()) return 1; + } + + ZetInit(3); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM0); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM0 + 0x18000); + ZetMapArea(0x8000, 0xbfff, 1, DrvZ80ROM0 + 0x18000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM0 + 0x18000); + ZetMapArea(0xc000, 0xdfff, 0, DrvSprRAM); + ZetMapArea(0xc000, 0xdfff, 1, DrvSprRAM); + ZetMapArea(0xc000, 0xdfff, 2, DrvSprRAM); + ZetMapArea(0xe000, 0xeeff, 0, DrvShareRAM); + if (strncmp(BurnDrvGetTextA(DRV_NAME), "kabukiz", 7) == 0) { + ZetMapArea(0xef00, 0xefff, 0, DrvShareRAM + 0x0f00); + } + ZetMapArea(0xe000, 0xefff, 1, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvShareRAM); + ZetMapArea(0xf000, 0xf1ff, 0, DrvVidRAM); + ZetMapArea(0xf000, 0xf1ff, 1, DrvVidRAM); + ZetMapArea(0xf000, 0xf1ff, 2, DrvVidRAM); + ZetMapArea(0xf200, 0xf2ff, 0, DrvScrollRAM); + ZetMapArea(0xf200, 0xf2ff, 1, DrvScrollRAM); + ZetSetWriteHandler(tnzs_cpu0_write); + ZetSetReadHandler(tnzs_cpu0_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x9fff, 0, DrvZ80ROM1); + ZetMapArea(0x0000, 0x9fff, 2, DrvZ80ROM1); + ZetMapArea(0xd000, 0xdfff, 0, DrvZ80RAM1); + ZetMapArea(0xd000, 0xdfff, 1, DrvZ80RAM1); + ZetMapArea(0xd000, 0xdfff, 2, DrvZ80RAM1); + ZetMapArea(0xe000, 0xefff, 0, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 1, DrvShareRAM); + ZetMapArea(0xe000, 0xefff, 2, DrvShareRAM); + ZetMapArea(0xf000, 0xf3ff, 1, DrvPalRAM); // tnzsb + ZetMapArea(0xf800, 0xfbff, 1, DrvPalRAM); // kabukiz + ZetSetWriteHandler(tnzsb_cpu1_write); + ZetSetReadHandler(tnzsb_cpu1_read); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM2 + 0x0000); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM2 + 0x0000); + ZetMapArea(0xc000, 0xdfff, 0, DrvZ80RAM2); // tnzsb + ZetMapArea(0xc000, 0xdfff, 1, DrvZ80RAM2); + ZetMapArea(0xc000, 0xdfff, 2, DrvZ80RAM2); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80RAM2); // kabukiz + ZetMapArea(0xe000, 0xffff, 1, DrvZ80RAM2); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80RAM2); + ZetSetOutHandler(tnzs_cpu2_out); + ZetSetInHandler(tnzs_cpu2_in); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 3000000, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetPorts(0, NULL, NULL, &kabukiz_sound_bankswitch, &kabukiz_dac_write); + BurnTimerAttachZet(6000000); + + DACInit(0, 0, 0); // kabukiz + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + ZetExit(); + + BurnYM2203Exit(); + BurnYM2151Exit(); + DACExit(); + + BurnFree (AllMem); + + if (tnzs_mcu_type() == MCU_NONE_KAGEKI) { + kageki_sample_exit(); + } + + tnzs_mcu_init(0); + + return 0; +} + +// Stolen from TMNT. Thanks to Barry. :) +static void kageki_sample_render(INT16 *pSoundBuf, INT32 nLength) +{ + if (kageki_sample_select == -1) return; + + double Addr = kageki_sample_pos; + double Step = (double)7000 / nBurnSoundRate; + + double size = kageki_sample_size[kageki_sample_select]; + short *ptr = kageki_sample_data[kageki_sample_select]; + + for (INT32 i = 0; i < nLength; i += 2) { + if (Addr >= size) break; + short Sample = ptr[(INT32)Addr]; + + pSoundBuf[i ] = Sample; + pSoundBuf[i + 1] = Sample; + + Addr += Step; + } + + kageki_sample_pos = Addr; + if (Addr >= size) kageki_sample_select = -1; +} + +static void draw_16x16(INT32 sx, INT32 sy, INT32 code, INT32 color, INT32 flipx, INT32 flipy, INT32 transp) +{ + if (transp) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, DrvGfxROM); + } + } + } +} + +static void draw_background(INT32 ctrl, INT32 flipscreen) +{ + INT32 scrollx, scrolly; + UINT8 *m = DrvSprRAM + 0x400; + + if ((ctrl ^ (ctrl << 1)) & 0x40) + { + m += 0x800; + } + + INT32 transpen = (*tnzs_bg_flag & 0x80) ^ 0x80; + + INT32 tot = DrvObjCtrl[1] & 0x1f; + if (tot == 1) tot = 16; + + UINT32 upperbits = DrvObjCtrl[2] | (DrvObjCtrl[3] << 8); + + for (INT32 column = 0; column < tot; column++) + { + scrollx = DrvScrollRAM[(column << 4) | 4] - ((upperbits & 0x01) << 8); + if (flipscreen) + scrolly = DrvScrollRAM[column << 4] + 1 - 256; + else + scrolly = -DrvScrollRAM[column << 4] + 1; + + for (INT32 y = 0; y < 16; y++) + { + for (INT32 x = 0; x < 2; x++) + { + INT32 i = ((column ^ 8) << 5) | (y << 1) | x; + + INT32 code = m[i + 0x0000] | ((m[i + 0x1000] & 0x3f) << 8); + INT32 color = m[i + 0x1200] >> 3; + INT32 flipx = m[i + 0x1000] & 0x80; + INT32 flipy = m[i + 0x1000] & 0x40; + INT32 sx = x << 4; + INT32 sy = y << 4; + if (flipscreen) + { + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + } + + sy = (sy + scrolly) & 0xff; + sx += scrollx; + + if (sx >= nScreenWidth || sx < -15 || sy >= nScreenHeight + 16 || sy < 1) continue; + + draw_16x16(sx, sy - 16, code, color, flipx, flipy, transpen); + } + } + + upperbits >>= 1; + } +} + +static void draw_foreground(INT32 ctrl, INT32 flipscreen) +{ + UINT8 *char_pointer = DrvSprRAM + 0x0000; + UINT8 *x_pointer = DrvSprRAM + 0x0200; + UINT8 *y_pointer = DrvVidRAM + 0x0000; + UINT8 *ctrl_pointer = DrvSprRAM + 0x1000; + UINT8 *color_pointer = DrvSprRAM + 0x1200; + + if ((ctrl ^ (ctrl << 1)) & 0x40) + { + char_pointer += 0x800; + x_pointer += 0x800; + ctrl_pointer += 0x800; + color_pointer += 0x800; + } + + for (INT32 i = 0x1ff; i >= 0; i--) + { + INT32 code = char_pointer[i] + ((ctrl_pointer[i] & 0x3f) << 8); + INT32 color = (color_pointer[i] & 0xf8) >> 3; + INT32 sx = x_pointer[i] - ((color_pointer[i] & 1) << 8); + INT32 sy = 240 - y_pointer[i]; + INT32 flipx = ctrl_pointer[i] & 0x80; + INT32 flipy = ctrl_pointer[i] & 0x40; + if (flipscreen) + { + sy = 240 - sy; + flipx = !flipx; + flipy = !flipy; + if ((sy == 0) && (code == 0)) sy += 240; + } + + if (sx >= nScreenWidth || sx < -15) continue; + + draw_16x16(sx, sy - 14, code, color, flipx, flipy, 1); + } +} + +static inline void DrvRecalcPalette() +{ + UINT8 r,g,b; + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + for (INT32 i = 0; i < 0x400; i+=2) { + UINT16 pal = (DrvPalRAM[i] << 8) | DrvPalRAM[i | 1]; + + r = (pal >> 4) & 0x0f; + g = (pal >> 12) & 0x0f; + b = (pal >> 8) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i / 2] = BurnHighCol(r, g, b, 0); + } + } else { + for (INT32 i = 0; i < 0x400; i+=2) { + UINT16 pal = (DrvPalRAM[i | 1] << 8) | DrvPalRAM[i]; + + r = (pal >> 10) & 0x1f; + g = (pal >> 5) & 0x1f; + b = (pal >> 0) & 0x1f; + + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + + DrvPalette[i / 2] = BurnHighCol(r, g, b, 0); + } + } +} + +static void sprite_buffer(INT32 ctrl) +{ + if (ctrl & 0x20) + { + if (ctrl & 0x40) { + memcpy (DrvSprRAM + 0x0000, DrvSprRAM + 0x0800, 0x0400); + memcpy (DrvSprRAM + 0x1000, DrvSprRAM + 0x1800, 0x0400); + } else { + memcpy (DrvSprRAM + 0x0800, DrvSprRAM + 0x0000, 0x0400); + memcpy (DrvSprRAM + 0x1800, DrvSprRAM + 0x1000, 0x0400); + } + + memcpy (DrvSprRAM + 0x0400, DrvSprRAM + 0x0c00, 0x0400); + memcpy (DrvSprRAM + 0x1400, DrvSprRAM + 0x1c00, 0x0400); + } +} + +static INT32 DrvDraw() +{ + DrvRecalcPalette(); + + INT32 flip = DrvObjCtrl[0] & 0x40; + INT32 ctrl = (DrvObjCtrl[1] & 0x60) ^ 0x20; + + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x1f0; + } + + draw_background(ctrl, flip); + draw_foreground(ctrl, flip); + + BurnTransferCopy(DrvPalette); + + sprite_buffer(ctrl); + + return 0; +} + +static void assemble_inputs() +{ + tnzs_mcu_inputs = DrvInputs; + memset (DrvInputs, 0xff, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + + nAnalogAxis[0] -= DrvAxis[0] << 7; + nAnalogAxis[1] -= DrvAxis[1] << 7; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + ZetNewFrame(); + + assemble_inputs(); + + INT32 nInterleave = nBurnSoundLen ? nBurnSoundLen : 100; + INT32 nSoundBufferPos = 0; + + INT32 nCyclesSegment; + INT32 nCyclesDone[3], nCyclesTotal[3]; + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesTotal[2] = 6000000 / 60; + + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + INT32 irq_trigger[2] = { nInterleave - 2, nInterleave - 1 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #0 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == irq_trigger[0]) { + tnzs_mcu_interrupt(); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + if (i == irq_trigger[1]) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #1 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (cpu1_reset == 0) { + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + if (i == irq_trigger[0]) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == irq_trigger[1]) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #2 + if (tnzs_mcu_type() == MCU_NONE) + { + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + INT16* pSoundBuf2 = SampleBuffer + (nSoundBufferPos << 1); + ZetOpen(2); + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + kageki_sample_render(pSoundBuf2, nSegmentLength); + DACUpdate(pSoundBuf2, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + ZetOpen(2); + if (tnzs_mcu_type() == MCU_NONE) { + BurnTimerEndFrame(nCyclesTotal[2]); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + INT16* pSoundBuf2 = SampleBuffer + (nSoundBufferPos << 1); + if (nSegmentLength) { + if (tnzs_mcu_type() == MCU_NONE_JPOPNICS) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + kageki_sample_render(pSoundBuf2, nSegmentLength); + DACUpdate(pSoundBuf2, nSegmentLength); + } + } + + if (tnzs_mcu_type() != MCU_NONE_JPOPNICS) { + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + for (INT32 i = 0; i < nBurnSoundLen; i++) { + pBurnSoundOut[(i << 1) + 0] += SampleBuffer[(i << 1) + 0]; + pBurnSoundOut[(i << 1) + 1] += SampleBuffer[(i << 1) + 1]; + } + } + } + + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + BurnYM2151Scan(nAction); + DACScan(nAction, pnMin); + + tnzs_mcu_scan(); + + SCAN_VAR(tnzs_banks[0]); + SCAN_VAR(tnzs_banks[1]); + SCAN_VAR(tnzs_banks[2]); + SCAN_VAR(cpu1_reset); + + SCAN_VAR(nAnalogAxis[0]); + SCAN_VAR(nAnalogAxis[1]); + + SCAN_VAR(kageki_csport_sel); + SCAN_VAR(kageki_sample_pos); + SCAN_VAR(kageki_sample_select); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch0(tnzs_banks[0]); + ZetClose(); + + ZetOpen(1); + bankswitch1(tnzs_banks[1]); + ZetClose(); + + ZetOpen(2); + kabukiz_sound_bankswitch(0,tnzs_banks[2]); + ZetClose(); + } + + return 0; +} + + +// Plump Pop (Japan) + +static struct BurnRomInfo plumppopRomDesc[] = { + { "a98-09.bin", 0x10000, 0x107f9e06, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "a98-10.bin", 0x10000, 0xdf6e6af2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "a98-11.bin", 0x10000, 0xbc56775c, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "plmp8742.bin", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "a98-01.bin", 0x10000, 0xf3033dca, 4 | BRF_GRA }, // 4 Graphics + { "a98-02.bin", 0x10000, 0xf2d17b0c, 4 | BRF_GRA }, // 5 + { "a98-03.bin", 0x10000, 0x1a519b0a, 4 | BRF_GRA }, // 6 + { "a98-04.bin", 0x10000, 0xb64501a1, 4 | BRF_GRA }, // 7 + { "a98-05.bin", 0x10000, 0x45c36963, 4 | BRF_GRA }, // 8 + { "a98-06.bin", 0x10000, 0xe075341b, 4 | BRF_GRA }, // 9 + { "a98-07.bin", 0x10000, 0x8e16cd81, 4 | BRF_GRA }, // 10 + { "a98-08.bin", 0x10000, 0xbfa7609a, 4 | BRF_GRA }, // 11 + + { "a98-13.bpr", 0x00200, 0x7cde2da5, 5 | BRF_GRA }, // 12 Color PROMs + { "a98-12.bpr", 0x00200, 0x90dc9da7, 5 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(plumppop) +STD_ROM_FN(plumppop) + +static INT32 PlumppopInit() +{ + return Type1Init(MCU_PLUMPOP); +} + +struct BurnDriver BurnDrvPlumppop = { + "plumppop", NULL, NULL, NULL, "1987", + "Plump Pop (Japan)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, plumppopRomInfo, plumppopRomName, NULL, NULL, PlumppopInputInfo, PlumppopDIPInfo, + PlumppopInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Extermination (World) + +static struct BurnRomInfo extrmatnRomDesc[] = { + { "b06-05.11c", 0x10000, 0x918e1fe3, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b06-06.9c", 0x10000, 0x8842e105, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b06-19.4e", 0x10000, 0x8de43ed9, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "extr8742.4f", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b06-01.13a", 0x20000, 0xd2afbf7e, 4 | BRF_GRA }, // 4 Graphics + { "b06-02.10a", 0x20000, 0xe0c2757a, 4 | BRF_GRA }, // 5 + { "b06-03.7a", 0x20000, 0xee80ab9d, 4 | BRF_GRA }, // 6 + { "b06-04.4a", 0x20000, 0x3697ace4, 4 | BRF_GRA }, // 7 + + { "b06-09.15f", 0x00200, 0xf388b361, 5 | BRF_GRA }, // 8 Color PROMs + { "b06-08.17f", 0x00200, 0x10c9aac3, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(extrmatn) +STD_ROM_FN(extrmatn) + +static INT32 ExtrmatnInit() +{ + return Type1Init(MCU_EXTRMATN); +} + +struct BurnDriver BurnDrvExtrmatn = { + "extrmatn", NULL, NULL, NULL, "1987", + "Extermination (World)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, extrmatnRomInfo, extrmatnRomName, NULL, NULL, CommonInputInfo, ExtrmatnDIPInfo, + ExtrmatnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Extermination (US) + +static struct BurnRomInfo extrmatuRomDesc[] = { + { "b06-20.11c", 0x10000, 0x04e3fc1f, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b06-21.9c", 0x10000, 0x1614d6a2, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b06-22.4e", 0x10000, 0x744f2c84, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "extr8742.4f", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b06-01.13a", 0x20000, 0xd2afbf7e, 4 | BRF_GRA }, // 4 Graphics + { "b06-02.10a", 0x20000, 0xe0c2757a, 4 | BRF_GRA }, // 5 + { "b06-03.7a", 0x20000, 0xee80ab9d, 4 | BRF_GRA }, // 6 + { "b06-04.4a", 0x20000, 0x3697ace4, 4 | BRF_GRA }, // 7 + + { "b06-09.15f", 0x00200, 0xf388b361, 5 | BRF_GRA }, // 8 Color PROMs + { "b06-08.17f", 0x00200, 0x10c9aac3, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(extrmatu) +STD_ROM_FN(extrmatu) + +struct BurnDriver BurnDrvExtrmatu = { + "extrmatnu", "extrmatn", NULL, NULL, "1987", + "Extermination (US)\0", NULL, "[Taito] World Games", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, extrmatuRomInfo, extrmatuRomName, NULL, NULL, CommonInputInfo, ExtrmatnDIPInfo, + ExtrmatnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Extermination (Japan) + +static struct BurnRomInfo extrmatjRomDesc[] = { + { "b06-05.11c", 0x10000, 0x918e1fe3, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b06-06.9c", 0x10000, 0x8842e105, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b06-07.4e", 0x10000, 0xb37fb8b3, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "extr8742.4f", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b06-01.13a", 0x20000, 0xd2afbf7e, 4 | BRF_GRA }, // 4 Graphics + { "b06-02.10a", 0x20000, 0xe0c2757a, 4 | BRF_GRA }, // 5 + { "b06-03.7a", 0x20000, 0xee80ab9d, 4 | BRF_GRA }, // 6 + { "b06-04.4a", 0x20000, 0x3697ace4, 4 | BRF_GRA }, // 7 + + { "b06-09.15f", 0x00200, 0xf388b361, 5 | BRF_GRA }, // 8 Color PROMs + { "b06-08.17f", 0x00200, 0x10c9aac3, 5 | BRF_GRA }, // 9 +}; + +STD_ROM_PICK(extrmatj) +STD_ROM_FN(extrmatj) + +struct BurnDriver BurnDrvExtrmatj = { + "extrmatnj", "extrmatn", NULL, NULL, "1987", + "Extermination (Japan)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, extrmatjRomInfo, extrmatjRomName, NULL, NULL, CommonInputInfo, ExtrmatnDIPInfo, + ExtrmatnInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid - Revenge of DOH (World) + +static struct BurnRomInfo arknoid2RomDesc[] = { + { "b08_05.11c", 0x10000, 0x136edf9d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b08_13.3e", 0x10000, 0xe8035ef1, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "ark28742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 2 I8742 MCU + + { "b08-01.13a", 0x20000, 0x2ccc86b4, 4 | BRF_GRA }, // 3 Graphics + { "b08-02.10a", 0x20000, 0x056a985f, 4 | BRF_GRA }, // 4 + { "b08-03.7a", 0x20000, 0x274a795f, 4 | BRF_GRA }, // 5 + { "b08-04.4a", 0x20000, 0x9754f703, 4 | BRF_GRA }, // 6 + + { "b08-08.15f", 0x00200, 0xa4f7ebd9, 5 | BRF_GRA }, // 7 Color PROMs + { "b08-07.16f", 0x00200, 0xea34d9f7, 5 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknoid2) +STD_ROM_FN(arknoid2) + +static INT32 Arknoid2Init() +{ + return Type1Init(MCU_ARKANOID); +} + +struct BurnDriver BurnDrvArknoid2 = { + "arknoid2", NULL, NULL, NULL, "1987", + "Arkanoid - Revenge of DOH (World)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, arknoid2RomInfo, arknoid2RomName, NULL, NULL, Arknoid2InputInfo, Arknoid2DIPInfo, + Arknoid2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid - Revenge of DOH (US) + +static struct BurnRomInfo arknid2uRomDesc[] = { + { "b08_11.11c", 0x10000, 0x99555231, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b08_12.3e", 0x10000, 0xdc84e27d, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "ark28742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 2 I8742 MCU + + { "b08-01.13a", 0x20000, 0x2ccc86b4, 4 | BRF_GRA }, // 3 Graphics + { "b08-02.10a", 0x20000, 0x056a985f, 4 | BRF_GRA }, // 4 + { "b08-03.7a", 0x20000, 0x274a795f, 4 | BRF_GRA }, // 5 + { "b08-04.4a", 0x20000, 0x9754f703, 4 | BRF_GRA }, // 6 + + { "b08-08.15f", 0x00200, 0xa4f7ebd9, 5 | BRF_GRA }, // 7 Color PROMs + { "b08-07.16f", 0x00200, 0xea34d9f7, 5 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknid2u) +STD_ROM_FN(arknid2u) + +struct BurnDriver BurnDrvArknid2u = { + "arknoid2u", "arknoid2", NULL, NULL, "1987", + "Arkanoid - Revenge of DOH (US)\0", NULL, "Taito America Corporation (Romstar license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, arknid2uRomInfo, arknid2uRomName, NULL, NULL, Arknoid2InputInfo, Arknid2uDIPInfo, + Arknoid2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Arkanoid - Revenge of DOH (Japan) + +static struct BurnRomInfo arknid2jRomDesc[] = { + { "b08_05.11c", 0x10000, 0x136edf9d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b08_06.3e", 0x10000, 0xadfcd40c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "ark28742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 2 I8742 MCU + + { "b08-01.13a", 0x20000, 0x2ccc86b4, 4 | BRF_GRA }, // 3 Graphics + { "b08-02.10a", 0x20000, 0x056a985f, 4 | BRF_GRA }, // 4 + { "b08-03.7a", 0x20000, 0x274a795f, 4 | BRF_GRA }, // 5 + { "b08-04.4a", 0x20000, 0x9754f703, 4 | BRF_GRA }, // 6 + + { "b08-08.15f", 0x00200, 0xa4f7ebd9, 5 | BRF_GRA }, // 7 Color PROMs + { "b08-07.16f", 0x00200, 0xea34d9f7, 5 | BRF_GRA }, // 8 +}; + +STD_ROM_PICK(arknid2j) +STD_ROM_FN(arknid2j) + +struct BurnDriver BurnDrvArknid2j = { + "arknoid2j", "arknoid2", NULL, NULL, "1987", + "Arkanoid - Revenge of DOH (Japan)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, arknid2jRomInfo, arknid2jRomName, NULL, NULL, Arknoid2InputInfo, Arknid2uDIPInfo, + Arknoid2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Dr. Toppel's Adventure (World) + +static struct BurnRomInfo drtoppelRomDesc[] = { + { "b19-09.11c", 0x10000, 0x3e654f82, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b19-10.9c", 0x10000, 0x7e72fd25, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b19-15.3e", 0x10000, 0x37a0d3fb, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "drt8742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b19-01.13a", 0x20000, 0xa7e8a0c1, 4 | BRF_GRA }, // 4 Graphics + { "b19-02.12a", 0x20000, 0x790ae654, 4 | BRF_GRA }, // 5 + { "b19-03.10a", 0x20000, 0x495c4c5a, 4 | BRF_GRA }, // 6 + { "b19-04.8a", 0x20000, 0x647007a0, 4 | BRF_GRA }, // 7 + { "b19-05.7a", 0x20000, 0x49f2b1a5, 4 | BRF_GRA }, // 8 + { "b19-06.5a", 0x20000, 0x2d39f1d0, 4 | BRF_GRA }, // 9 + { "b19-07.4a", 0x20000, 0x8bb06f41, 4 | BRF_GRA }, // 10 + { "b19-08.2a", 0x20000, 0x3584b491, 4 | BRF_GRA }, // 11 + + { "b19-13.15f", 0x00200, 0x6a547980, 5 | BRF_GRA }, // 12 Color PROMs + { "b19-12.16f", 0x00200, 0x5754e9d8, 5 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(drtoppel) +STD_ROM_FN(drtoppel) + +static INT32 DrtoppelInit() +{ + return Type1Init(MCU_DRTOPPEL); +} + +struct BurnDriver BurnDrvDrtoppel = { + "drtoppel", NULL, NULL, NULL, "1987", + "Dr. Toppel's Adventure (World)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, drtoppelRomInfo, drtoppelRomName, NULL, NULL, CommonInputInfo, DrtoppelDIPInfo, + DrtoppelInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Dr. Toppel's Adventure (US) + +static struct BurnRomInfo drtoppluRomDesc[] = { + { "b19-09.11c", 0x10000, 0x3e654f82, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b19-10.9c", 0x10000, 0x7e72fd25, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b19-14.3e", 0x10000, 0x05565b22, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "drt8742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b19-01.13a", 0x20000, 0xa7e8a0c1, 4 | BRF_GRA }, // 4 Graphics + { "b19-02.12a", 0x20000, 0x790ae654, 4 | BRF_GRA }, // 5 + { "b19-03.10a", 0x20000, 0x495c4c5a, 4 | BRF_GRA }, // 6 + { "b19-04.8a", 0x20000, 0x647007a0, 4 | BRF_GRA }, // 7 + { "b19-05.7a", 0x20000, 0x49f2b1a5, 4 | BRF_GRA }, // 8 + { "b19-06.5a", 0x20000, 0x2d39f1d0, 4 | BRF_GRA }, // 9 + { "b19-07.4a", 0x20000, 0x8bb06f41, 4 | BRF_GRA }, // 10 + { "b19-08.2a", 0x20000, 0x3584b491, 4 | BRF_GRA }, // 11 + + { "b19-13.15f", 0x00200, 0x6a547980, 5 | BRF_GRA }, // 12 Color PROMs + { "b19-12.16f", 0x00200, 0x5754e9d8, 5 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(drtopplu) +STD_ROM_FN(drtopplu) + +struct BurnDriver BurnDrvDrtopplu = { + "drtoppelu", "drtoppel", NULL, NULL, "1987", + "Dr. Toppel's Adventure (US)\0", NULL, "Taito America Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, drtoppluRomInfo, drtoppluRomName, NULL, NULL, CommonInputInfo, DrtoppluDIPInfo, + DrtoppelInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Dr. Toppel's Tankentai (Japan) + +static struct BurnRomInfo drtoppljRomDesc[] = { + { "b19-09.11c", 0x10000, 0x3e654f82, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b19-10.9c", 0x10000, 0x7e72fd25, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b19-11.3e", 0x10000, 0x524dc249, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "drt8742.3g", 0x00800, 0x00000000, 3 | BRF_NODUMP }, // 3 I8742 MCU + + { "b19-01.13a", 0x20000, 0xa7e8a0c1, 4 | BRF_GRA }, // 4 Graphics + { "b19-02.12a", 0x20000, 0x790ae654, 4 | BRF_GRA }, // 5 + { "b19-03.10a", 0x20000, 0x495c4c5a, 4 | BRF_GRA }, // 6 + { "b19-04.8a", 0x20000, 0x647007a0, 4 | BRF_GRA }, // 7 + { "b19-05.7a", 0x20000, 0x49f2b1a5, 4 | BRF_GRA }, // 8 + { "b19-06.5a", 0x20000, 0x2d39f1d0, 4 | BRF_GRA }, // 9 + { "b19-07.4a", 0x20000, 0x8bb06f41, 4 | BRF_GRA }, // 10 + { "b19-08.2a", 0x20000, 0x3584b491, 4 | BRF_GRA }, // 11 + + { "b19-13.15f", 0x00200, 0x6a547980, 5 | BRF_GRA }, // 12 Color PROMs + { "b19-12.16f", 0x00200, 0x5754e9d8, 5 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(drtopplj) +STD_ROM_FN(drtopplj) + +struct BurnDriver BurnDrvDrtopplj = { + "drtoppelj", "drtoppel", NULL, NULL, "1987", + "Dr. Toppel's Tankentai (Japan)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, drtoppljRomInfo, drtoppljRomName, NULL, NULL, CommonInputInfo, DrtoppluDIPInfo, + DrtoppelInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Kageki (US) + +static struct BurnRomInfo kagekiRomDesc[] = { + { "b35-16.11c", 0x10000, 0xa4e6fd58, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b35-10.9c", 0x10000, 0xb150457d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b35-17.43e", 0x10000, 0xfdd9c246, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b35-01.13a", 0x20000, 0x01d83a69, 4 | BRF_GRA }, // 3 Graphics + { "b35-02.12a", 0x20000, 0xd8af47ac, 4 | BRF_GRA }, // 4 + { "b35-03.10a", 0x20000, 0x3cb68797, 4 | BRF_GRA }, // 5 + { "b35-04.8a", 0x20000, 0x71c03f91, 4 | BRF_GRA }, // 6 + { "b35-05.7a", 0x20000, 0xa4e20c08, 4 | BRF_GRA }, // 7 + { "b35-06.5a", 0x20000, 0x3f8ab658, 4 | BRF_GRA }, // 8 + { "b35-07.4a", 0x20000, 0x1b4af049, 4 | BRF_GRA }, // 9 + { "b35-08.2a", 0x20000, 0xdeb2268c, 4 | BRF_GRA }, // 10 + + { "b35-15.98g", 0x10000, 0xe6212a0f, 6 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(kageki) +STD_ROM_FN(kageki) + +static INT32 KagekiInit() +{ + return Type1Init(MCU_NONE_KAGEKI); +} + +struct BurnDriver BurnDrvKageki = { + "kageki", NULL, NULL, NULL, "1988", + "Kageki (US)\0", "Imperfect Sound", "Taito America Corporation (Romstar license)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, kagekiRomInfo, kagekiRomName, NULL, NULL, CommonInputInfo, KagekiDIPInfo, + KagekiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Kageki (Japan) + +static struct BurnRomInfo kagekijRomDesc[] = { + { "b35-09.11c", 0x10000, 0x829637d5, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b35-10.9c", 0x10000, 0xb150457d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b35-11.43e", 0x10000, 0x64d093fc, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b35-01.13a", 0x20000, 0x01d83a69, 4 | BRF_GRA }, // 3 Graphics + { "b35-02.12a", 0x20000, 0xd8af47ac, 4 | BRF_GRA }, // 4 + { "b35-03.10a", 0x20000, 0x3cb68797, 4 | BRF_GRA }, // 5 + { "b35-04.8a", 0x20000, 0x71c03f91, 4 | BRF_GRA }, // 6 + { "b35-05.7a", 0x20000, 0xa4e20c08, 4 | BRF_GRA }, // 7 + { "b35-06.5a", 0x20000, 0x3f8ab658, 4 | BRF_GRA }, // 8 + { "b35-07.4a", 0x20000, 0x1b4af049, 4 | BRF_GRA }, // 9 + { "b35-08.2a", 0x20000, 0xdeb2268c, 4 | BRF_GRA }, // 10 + + { "b35-12.98g", 0x10000, 0x184409f1, 6 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(kagekij) +STD_ROM_FN(kagekij) + +struct BurnDriver BurnDrvKagekij = { + "kagekij", "kageki", NULL, NULL, "1988", + "Kageki (Japan)\0", "Imperfect Sound", "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, kagekijRomInfo, kagekijRomName, NULL, NULL, CommonInputInfo, KagekiDIPInfo, + KagekiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Kageki (hack) + +static struct BurnRomInfo kagekihRomDesc[] = { + { "b35_16.11c", 0x10000, 0x1cf67603, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b35-10.9c", 0x10000, 0xb150457d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b35-11.43e", 0x10000, 0x64d093fc, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b35-01.13a", 0x20000, 0x01d83a69, 4 | BRF_GRA }, // 3 Graphics + { "b35-02.12a", 0x20000, 0xd8af47ac, 4 | BRF_GRA }, // 4 + { "b35-03.10a", 0x20000, 0x3cb68797, 4 | BRF_GRA }, // 5 + { "b35-04.8a", 0x20000, 0x71c03f91, 4 | BRF_GRA }, // 6 + { "b35-05.7a", 0x20000, 0xa4e20c08, 4 | BRF_GRA }, // 7 + { "b35-06.5a", 0x20000, 0x3f8ab658, 4 | BRF_GRA }, // 8 + { "b35-07.4a", 0x20000, 0x1b4af049, 4 | BRF_GRA }, // 9 + { "b35-08.2a", 0x20000, 0xdeb2268c, 4 | BRF_GRA }, // 10 + + { "b35-12.98g", 0x10000, 0x184409f1, 6 | BRF_SND }, // 11 Samples +}; + +STD_ROM_PICK(kagekih) +STD_ROM_FN(kagekih) + +struct BurnDriver BurnDrvKagekih = { + "kagekih", "kageki", NULL, NULL, "1992", + "Kageki (hack)\0", "Imperfect Sound", "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, kagekihRomInfo, kagekihRomName, NULL, NULL, CommonInputInfo, KagekiDIPInfo, + KagekiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 224, 256, 3, 4 +}; + + +// Chuka Taisen (World) + +static struct BurnRomInfo chukataiRomDesc[] = { + { "b44-10", 0x10000, 0x8c69e008, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b44-11", 0x10000, 0x32484094, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b44-12w", 0x10000, 0xe80ecdca, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b44-8742.mcu", 0x00800, 0x7dff3f9f, 3 | BRF_PRG | BRF_OPT }, // 3 I8742 MCU + + { "b44-01.a13", 0x20000, 0xaae7b3d5, 4 | BRF_GRA }, // 4 Graphics + { "b44-02.a12", 0x20000, 0x7f0b9568, 4 | BRF_GRA }, // 5 + { "b44-03.a10", 0x20000, 0x5a54a3b9, 4 | BRF_GRA }, // 6 + { "b44-04.a08", 0x20000, 0x3c5f544b, 4 | BRF_GRA }, // 7 + { "b44-05.a07", 0x20000, 0xd1b7e314, 4 | BRF_GRA }, // 8 + { "b44-06.a05", 0x20000, 0x269978a8, 4 | BRF_GRA }, // 9 + { "b44-07.a04", 0x20000, 0x3e0e737e, 4 | BRF_GRA }, // 10 + { "b44-08.a02", 0x20000, 0x6cb1e8fc, 4 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(chukatai) +STD_ROM_FN(chukatai) + +static INT32 ChukataiInit() +{ + return Type1Init(MCU_CHUKATAI); +} + +struct BurnDriver BurnDrvChukatai = { + "chukatai", NULL, NULL, NULL, "1988", + "Chuka Taisen (World)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, chukataiRomInfo, chukataiRomName, NULL, NULL, CommonInputInfo, ChukataiDIPInfo, + ChukataiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Chuka Taisen (US) + +static struct BurnRomInfo chukatauRomDesc[] = { + { "b44-10", 0x10000, 0x8c69e008, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b44-11", 0x10000, 0x32484094, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b44-12u", 0x10000, 0x9f09fd5c, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b44-8742.mcu", 0x00800, 0x7dff3f9f, 3 | BRF_PRG | BRF_OPT }, // 3 I8742 MCU + + { "b44-01.a13", 0x20000, 0xaae7b3d5, 4 | BRF_GRA }, // 4 Graphics + { "b44-02.a12", 0x20000, 0x7f0b9568, 4 | BRF_GRA }, // 5 + { "b44-03.a10", 0x20000, 0x5a54a3b9, 4 | BRF_GRA }, // 6 + { "b44-04.a08", 0x20000, 0x3c5f544b, 4 | BRF_GRA }, // 7 + { "b44-05.a07", 0x20000, 0xd1b7e314, 4 | BRF_GRA }, // 8 + { "b44-06.a05", 0x20000, 0x269978a8, 4 | BRF_GRA }, // 9 + { "b44-07.a04", 0x20000, 0x3e0e737e, 4 | BRF_GRA }, // 10 + { "b44-08.a02", 0x20000, 0x6cb1e8fc, 4 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(chukatau) +STD_ROM_FN(chukatau) + +struct BurnDriver BurnDrvChukatau = { + "chukataiu", "chukatai", NULL, NULL, "1988", + "Chuka Taisen (US)\0", NULL, "Taito America Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, chukatauRomInfo, chukatauRomName, NULL, NULL, CommonInputInfo, ChukatauDIPInfo, + ChukataiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Chuka Taisen (Japan) + +static struct BurnRomInfo chukatajRomDesc[] = { + { "b44-10", 0x10000, 0x8c69e008, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "b44-11", 0x10000, 0x32484094, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b44-12", 0x10000, 0x0600ace6, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 #1 Code + + { "b44-8742.mcu", 0x00800, 0x7dff3f9f, 3 | BRF_PRG | BRF_OPT }, // 3 I8742 MCU + + { "b44-01.a13", 0x20000, 0xaae7b3d5, 4 | BRF_GRA }, // 4 Graphics + { "b44-02.a12", 0x20000, 0x7f0b9568, 4 | BRF_GRA }, // 5 + { "b44-03.a10", 0x20000, 0x5a54a3b9, 4 | BRF_GRA }, // 6 + { "b44-04.a08", 0x20000, 0x3c5f544b, 4 | BRF_GRA }, // 7 + { "b44-05.a07", 0x20000, 0xd1b7e314, 4 | BRF_GRA }, // 8 + { "b44-06.a05", 0x20000, 0x269978a8, 4 | BRF_GRA }, // 9 + { "b44-07.a04", 0x20000, 0x3e0e737e, 4 | BRF_GRA }, // 10 + { "b44-08.a02", 0x20000, 0x6cb1e8fc, 4 | BRF_GRA }, // 11 +}; + +STD_ROM_PICK(chukataj) +STD_ROM_FN(chukataj) + +struct BurnDriver BurnDrvChukataj = { + "chukataij", "chukatai", NULL, NULL, "1988", + "Chuka Taisen (Japan)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, chukatajRomInfo, chukatajRomName, NULL, NULL, CommonInputInfo, ChukatauDIPInfo, + ChukataiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The NewZealand Story (World, newer) + +static struct BurnRomInfo tnzsRomDesc[] = { + { "b53-24.1", 0x20000, 0xd66824c6, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b53-25.3", 0x10000, 0xd6ac4e71, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b53-26.34", 0x10000, 0xcfd5649c, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "b53-16.8", 0x20000, 0xc3519c2a, 4 | BRF_GRA }, // 3 Graphics + { "b53-17.7", 0x20000, 0x2bf199e8, 4 | BRF_GRA }, // 4 + { "b53-18.6", 0x20000, 0x92f35ed9, 4 | BRF_GRA }, // 5 + { "b53-19.5", 0x20000, 0xedbb9581, 4 | BRF_GRA }, // 6 + { "b53-22.4", 0x20000, 0x59d2aef6, 4 | BRF_GRA }, // 7 + { "b53-23.3", 0x20000, 0x74acfb9b, 4 | BRF_GRA }, // 8 + { "b53-20.2", 0x20000, 0x095d0dc0, 4 | BRF_GRA }, // 9 + { "b53-21.1", 0x20000, 0x9800c54d, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(tnzs) +STD_ROM_FN(tnzs) + +struct BurnDriver BurnDrvtnzs = { + "tnzs", NULL, NULL, NULL, "1988", + "The NewZealand Story (World, newer)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, tnzsRomInfo, tnzsRomName, NULL, NULL, CommonInputInfo, TnzsDIPInfo, + Type2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The NewZealand Story (Japan, newer) + +static struct BurnRomInfo tnzsjRomDesc[] = { + { "b53-24.1", 0x20000, 0xd66824c6, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b53-27.u3", 0x10000, 0xb3415fc3, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b53-26.34", 0x10000, 0xcfd5649c, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "b53-16.8", 0x20000, 0xc3519c2a, 4 | BRF_GRA }, // 3 Graphics + { "b53-17.7", 0x20000, 0x2bf199e8, 4 | BRF_GRA }, // 4 + { "b53-18.6", 0x20000, 0x92f35ed9, 4 | BRF_GRA }, // 5 + { "b53-19.5", 0x20000, 0xedbb9581, 4 | BRF_GRA }, // 6 + { "b53-22.4", 0x20000, 0x59d2aef6, 4 | BRF_GRA }, // 7 + { "b53-23.3", 0x20000, 0x74acfb9b, 4 | BRF_GRA }, // 8 + { "b53-20.2", 0x20000, 0x095d0dc0, 4 | BRF_GRA }, // 9 + { "b53-21.1", 0x20000, 0x9800c54d, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(tnzsj) +STD_ROM_FN(tnzsj) + +struct BurnDriver BurnDrvtnzsj = { + "tnzsj", "tnzs", NULL, NULL, "1988", + "The NewZealand Story (Japan, new version, newer PCB)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0, + NULL, tnzsjRomInfo, tnzsjRomName, NULL, NULL, CommonInputInfo, TnzsjDIPInfo, + Type2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The NewZealand Story (Japan, old version) (older PCB) + +static struct BurnRomInfo tnzsjoRomDesc[] = { + { "b53-10.32", 0x20000, 0xa73745c6, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b53-11.38", 0x10000, 0x9784d443, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b53-09.u46", 0x00800, 0xa4bfce19, 3 | BRF_PRG | BRF_OPT }, // 2 I8742 MCU + + { "b53-08.8", 0x20000, 0xc3519c2a, 4 | BRF_GRA }, // 3 Graphics + { "b53-07.7", 0x20000, 0x2bf199e8, 4 | BRF_GRA }, // 4 + { "b53-06.6", 0x20000, 0x92f35ed9, 4 | BRF_GRA }, // 5 + { "b53-05.5", 0x20000, 0xedbb9581, 4 | BRF_GRA }, // 6 + { "b53-04.4", 0x20000, 0x59d2aef6, 4 | BRF_GRA }, // 7 + { "b53-03.3", 0x20000, 0x74acfb9b, 4 | BRF_GRA }, // 8 + { "b53-02.2", 0x20000, 0x095d0dc0, 4 | BRF_GRA }, // 9 + { "b53-01.1", 0x20000, 0x9800c54d, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(tnzsjo) +STD_ROM_FN(tnzsjo) + +static INT32 TnzsoInit() +{ + return Type1Init(MCU_TNZS); +} + +struct BurnDriver BurnDrvTnzsjo = { + "tnzsjo", "tnzs", NULL, NULL, "1988", + "The NewZealand Story (Japan, old version) (older PCB)\0", NULL, "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tnzsjoRomInfo, tnzsjoRomName, NULL, NULL, CommonInputInfo, TnzsjoDIPInfo, + TnzsoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The NewZealand Story (World, old version) (older PCB) + +static struct BurnRomInfo tnzsoRomDesc[] = { + { "u32", 0x20000, 0xedf3b39e, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "u38", 0x10000, 0x60340d63, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b53-06.u46", 0x00800, 0xa4bfce19, 3 | BRF_PRG | BRF_OPT }, // 2 I8742 MCU + + { "b53-08.8", 0x20000, 0xc3519c2a, 4 | BRF_GRA }, // 3 Graphics + { "b53-07.7", 0x20000, 0x2bf199e8, 4 | BRF_GRA }, // 4 + { "b53-06.6", 0x20000, 0x92f35ed9, 4 | BRF_GRA }, // 5 + { "b53-05.5", 0x20000, 0xedbb9581, 4 | BRF_GRA }, // 6 + { "b53-04.4", 0x20000, 0x59d2aef6, 4 | BRF_GRA }, // 7 + { "b53-03.3", 0x20000, 0x74acfb9b, 4 | BRF_GRA }, // 8 + { "b53-02.2", 0x20000, 0x095d0dc0, 4 | BRF_GRA }, // 9 + { "b53-01.1", 0x20000, 0x9800c54d, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(tnzso) +STD_ROM_FN(tnzso) + +struct BurnDriver BurnDrvTnzso = { + "tnzso", "tnzs", NULL, NULL, "1988", + "The NewZealand Story (World, old version) (older PCB)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tnzsoRomInfo, tnzsoRomName, NULL, NULL, CommonInputInfo, TnzsopDIPInfo, + TnzsoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// The NewZealand Story (World, prototype?) (older PCB) + +static struct BurnRomInfo tnzsopRomDesc[] = { + { "ns_c-11.rom", 0x20000, 0x3c1dae7b, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "ns_e-3.rom", 0x10000, 0xc7662e96, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b53-09.u46", 0x00800, 0xa4bfce19, 3 | BRF_PRG | BRF_OPT }, // 2 I8742 MCU + + { "ns_a13.rom", 0x20000, 0x7e0bd5bb, 4 | BRF_GRA }, // 3 Graphics + { "ns_a12.rom", 0x20000, 0x95880726, 4 | BRF_GRA }, // 4 + { "ns_a10.rom", 0x20000, 0x2bc4c053, 4 | BRF_GRA }, // 5 + { "ns_a08.rom", 0x20000, 0x8ff8d88c, 4 | BRF_GRA }, // 6 + { "ns_a07.rom", 0x20000, 0x291bcaca, 4 | BRF_GRA }, // 7 + { "ns_a05.rom", 0x20000, 0x6e762e20, 4 | BRF_GRA }, // 8 + { "ns_a04.rom", 0x20000, 0xe1fd1b9d, 4 | BRF_GRA }, // 9 + { "ns_a02.rom", 0x20000, 0x2ab06bda, 4 | BRF_GRA }, // 10 +}; + +STD_ROM_PICK(tnzsop) +STD_ROM_FN(tnzsop) + +struct BurnDriver BurnDrvTnzsop = { + "tnzsop", "tnzs", NULL, NULL, "1988", + "The NewZealand Story (World, prototype?) (older PCB)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tnzsopRomInfo, tnzsopRomName, NULL, NULL, CommonInputInfo, TnzsopDIPInfo, + TnzsoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Kabuki-Z (World) + +static struct BurnRomInfo kabukizRomDesc[] = { + { "b50-05.u1", 0x20000, 0x9cccb129, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b50-08.1e", 0x10000, 0xcb92d34c, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b50-07.u34", 0x20000, 0xbf7fc2ed, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "b50-04.u35", 0x80000, 0x04829aa9, 4 | BRF_GRA }, // 3 Graphics + { "b50-03.u39", 0x80000, 0x31489a4c, 4 | BRF_GRA }, // 4 + { "b50-02.u43", 0x80000, 0x90b8a8e7, 4 | BRF_GRA }, // 5 + { "b50-01.u46", 0x80000, 0xf4277751, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(kabukiz) +STD_ROM_FN(kabukiz) + +struct BurnDriverD BurnDrvKabukiz = { + "kabukiz", NULL, NULL, NULL, "1988", + "Kabuki-Z (World)\0", "Imperfect graphics", "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, kabukizRomInfo, kabukizRomName, NULL, NULL, CommonInputInfo, KabukizDIPInfo, + Type2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Kabuki-Z (Japan) + +static struct BurnRomInfo kabukizjRomDesc[] = { + { "b50-05.u1", 0x20000, 0x9cccb129, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b50-06.u3", 0x10000, 0x45650aab, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b50-07.u34", 0x20000, 0xbf7fc2ed, 3 | BRF_PRG | BRF_ESS }, // 2 Z80 #2 Code + + { "b50-04.u35", 0x80000, 0x04829aa9, 4 | BRF_GRA }, // 3 Graphics + { "b50-03.u39", 0x80000, 0x31489a4c, 4 | BRF_GRA }, // 4 + { "b50-02.u43", 0x80000, 0x90b8a8e7, 4 | BRF_GRA }, // 5 + { "b50-01.u46", 0x80000, 0xf4277751, 4 | BRF_GRA }, // 6 +}; + +STD_ROM_PICK(kabukizj) +STD_ROM_FN(kabukizj) + +struct BurnDriverD BurnDrvKabukizj = { + "kabukizj", "kabukiz", NULL, NULL, "1988", + "Kabuki-Z (Japan)\0", "Imperfect graphics", "Taito Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, kabukizjRomInfo, kabukizjRomName, NULL, NULL, CommonInputInfo, KabukizjDIPInfo, + Type2Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Insector X (World) + +static struct BurnRomInfo insectxRomDesc[] = { + { "b97-03.u32", 0x20000, 0x18eef387, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "b97-07.u38", 0x10000, 0x324b28c9, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "b97-01.u1", 0x80000, 0xd00294b1, 4 | BRF_GRA }, // 2 Graphics + { "b97-02.u2", 0x80000, 0xdb5a7434, 4 | BRF_GRA }, // 3 +}; + +STD_ROM_PICK(insectx) +STD_ROM_FN(insectx) + +static INT32 InsectxInit() +{ + return Type1Init(MCU_NONE_INSECTX); +} + +struct BurnDriver BurnDrvInsectx = { + "insectx", NULL, NULL, NULL, "1989", + "Insector X (World)\0", NULL, "Taito Corporation Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, insectxRomInfo, insectxRomName, NULL, NULL, InsectxInputInfo, InsectxDIPInfo, + InsectxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; + + +// Jumping Pop (Nics, Korean bootleg of Plump Pop) + +static struct BurnRomInfo jpopnicsRomDesc[] = { + { "u96cpu2", 0x20000, 0x649e951c, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + + { "u124cpu1", 0x10000, 0x8453e8e4, 2 | BRF_PRG | BRF_ESS }, // 1 Z80 #1 Code + + { "u94gfx", 0x20000, 0xe49f2fdd, 4 | BRF_GRA }, // 2 Graphics + { "u93gfx", 0x20000, 0xa7791b5b, 4 | BRF_GRA }, // 3 + { "u92gfx", 0x20000, 0xb30caac7, 4 | BRF_GRA }, // 4 + { "u91gfx", 0x20000, 0x18ada5f2, 4 | BRF_GRA }, // 5 +}; + +STD_ROM_PICK(jpopnics) +STD_ROM_FN(jpopnics) + +static INT32 JpopnicsInit() +{ + return Type1Init(MCU_NONE_JPOPNICS); +} + +struct BurnDriver BurnDrvJpopnics = { + "jpopnics", NULL, NULL, NULL, "1992", + "Jumping Pop (Nics, Korean bootleg of Plump Pop)\0", "Imperfect graphics", "Nics", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MISC, 0, + NULL, jpopnicsRomInfo, jpopnicsRomName, NULL, NULL, JpopnicsInputInfo, JpopnicsDIPInfo, + JpopnicsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200, + 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_toki.cpp b/src/burn/drivers/misc_pre90s/d_toki.cpp new file mode 100644 index 00000000..f4d0cb27 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_toki.cpp @@ -0,0 +1,1974 @@ +#include "tiles_generic.h" +#include "burn_ym3812.h" +#include "msm6295.h" +#include "msm5205.h" +#include "bitswap.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvZ80DecROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvBg1RAM; +static UINT8 *DrvBg2RAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvScrollRAM; + +static UINT8 DrvReset; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[2]; +static UINT8 DrvDips[2]; +static UINT16 DrvInps[2]; + +static UINT32 *DrvPalette; +static UINT32 *Palette; + +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; + +static UINT8 main2sub[2],sub2main[2]; +static INT32 main2sub_pending,sub2main_pending; + +static INT32 is_bootleg = 0; + +static UINT8 TokibMSM5205Next = 0; +static UINT8 TokibMSM5205Toggle = 0; + +static INT32 nCyclesTotal[2] = { 10000000 / 60, 3579545 / 60 }; + +static struct BurnInputInfo TokiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 4, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Toki) + +static struct BurnDIPInfo TokiDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 20, "Coinage" }, + {0x12, 0x01, 0x1f, 0x15, "6 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x17, "5 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x19, "4 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x1b, "3 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x03, "8 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x1d, "2 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x05, "5 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x07, "3 Coins 2 Credits " }, + {0x12, 0x01, 0x1f, 0x1f, "1 Coin 1 Credits " }, + {0x12, 0x01, 0x1f, 0x09, "2 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x13, "1 Coin 2 Credits " }, + {0x12, 0x01, 0x1f, 0x11, "1 Coin 3 Credits " }, + {0x12, 0x01, 0x1f, 0x0f, "1 Coin 4 Credits " }, + {0x12, 0x01, 0x1f, 0x0d, "1 Coin 5 Credits " }, + {0x12, 0x01, 0x1f, 0x0b, "1 Coin 6 Credits " }, + {0x12, 0x01, 0x1f, 0x1e, "A 1/1 B 1/2" }, + {0x12, 0x01, 0x1f, 0x14, "A 2/1 B 1/3" }, + {0x12, 0x01, 0x1f, 0x0a, "A 3/1 B 1/5" }, + {0x12, 0x01, 0x1f, 0x00, "A 5/1 B 1/6" }, + {0x12, 0x01, 0x1f, 0x01, "Free_Play" }, + + {0 , 0xfe, 0 , 2, "Joysticks" }, + {0x12, 0x01, 0x20, 0x20, "1" }, + {0x12, 0x01, 0x20, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x40, 0x40, "Upright" }, + {0x12, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Bonus_Life" }, + {0x13, 0x01, 0x0c, 0x08, "50000 150000" }, + {0x13, 0x01, 0x0c, 0x00, "70000 140000 210000" }, + {0x13, 0x01, 0x0c, 0x0c, "70000" }, + {0x13, 0x01, 0x0c, 0x04, "100000 200000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x30, 0x20, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Medium" }, + {0x13, 0x01, 0x30, 0x10, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Toki) + +static struct BurnInputInfo TokibInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 4, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvJoy2 + 2, "service"}, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip"}, +}; + +STDINPUTINFO(Tokib) + + +static struct BurnDIPInfo TokibDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xdf, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 20, "Coinage" }, + {0x12, 0x01, 0x1f, 0x15, "6 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x17, "5 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x19, "4 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x1b, "3 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x03, "8 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x1d, "2 Coins 1 Credits " }, + {0x12, 0x01, 0x1f, 0x05, "5 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x07, "3 Coins 2 Credits " }, + {0x12, 0x01, 0x1f, 0x1f, "1 Coin 1 Credits " }, + {0x12, 0x01, 0x1f, 0x09, "2 Coins 3 Credits " }, + {0x12, 0x01, 0x1f, 0x13, "1 Coin 2 Credits " }, + {0x12, 0x01, 0x1f, 0x11, "1 Coin 3 Credits " }, + {0x12, 0x01, 0x1f, 0x0f, "1 Coin 4 Credits " }, + {0x12, 0x01, 0x1f, 0x0d, "1 Coin 5 Credits " }, + {0x12, 0x01, 0x1f, 0x0b, "1 Coin 6 Credits " }, + {0x12, 0x01, 0x1f, 0x1e, "A 1/1 B 1/2" }, + {0x12, 0x01, 0x1f, 0x14, "A 2/1 B 1/3" }, + {0x12, 0x01, 0x1f, 0x0a, "A 3/1 B 1/5" }, + {0x12, 0x01, 0x1f, 0x00, "A 5/1 B 1/6" }, + {0x12, 0x01, 0x1f, 0x01, "Free_Play" }, + + {0 , 0xfe, 0 , 2, "Joysticks" }, + {0x12, 0x01, 0x20, 0x20, "1" }, + {0x12, 0x01, 0x20, 0x00, "2" }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x12, 0x01, 0x40, 0x40, "Upright" }, + {0x12, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip_Screen" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x13, 0x01, 0x03, 0x02, "2" }, + {0x13, 0x01, 0x03, 0x03, "3" }, + {0x13, 0x01, 0x03, 0x01, "5" }, + {0x13, 0x01, 0x03, 0x00, "Infinite (Cheat)" }, + + {0 , 0xfe, 0 , 4, "Bonus_Life" }, + {0x13, 0x01, 0x0c, 0x08, "50000 150000" }, + {0x13, 0x01, 0x0c, 0x00, "70000 140000 210000" }, + {0x13, 0x01, 0x0c, 0x0c, "70000" }, + {0x13, 0x01, 0x0c, 0x04, "100000 200000" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x13, 0x01, 0x30, 0x20, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Medium" }, + {0x13, 0x01, 0x30, 0x10, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow_Continue" }, + {0x13, 0x01, 0x40, 0x00, "No" }, + {0x13, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo_Sounds" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Tokib) + +static void palette_write(INT32 offset) +{ + UINT16 data = *((UINT16*)(DrvPalRAM + offset)); + + UINT8 r, g, b; + +// 4b4g4r handler + + r = (data & 0x0f); + r |= r << 4; + + g = (data & 0xf0); + g |= g >> 4; + + b = (data >> 8) & 0x0f; + b |= b << 4; + + Palette[offset >> 1] = (r << 16) | (g << 8) | b; + DrvPalette[offset >> 1] = BurnHighCol(r, g, b, 0); +} + +enum +{ + VECTOR_INIT, + RST10_ASSERT, + RST10_CLEAR, + RST18_ASSERT, + RST18_CLEAR +}; + +static void update_irq_lines(INT32 param) +{ + static INT32 irq1,irq2; + + switch(param) + { + case VECTOR_INIT: + irq1 = irq2 = 0xff; + break; + + case RST10_ASSERT: + irq1 = 0xd7; + break; + + case RST10_CLEAR: + irq1 = 0xff; + break; + + case RST18_ASSERT: + irq2 = 0xdf; + break; + + case RST18_CLEAR: + irq2 = 0xff; + break; + } + + if ((irq1 & irq2) == 0xff) { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } else { + if (irq2 == 0xdf) { // this shouldn't be required - Raiden needs it too though??? + ZetSetVector(irq1 & irq2); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + } + } +} + +UINT8 seibu_main_word_r(INT32 offset) +{ + offset = (offset >> 1) & 7; + + switch (offset) + { + case 2: + case 3: + return sub2main[offset-2]; + case 5: + return main2sub_pending ? 1 : 0; + default: + return 0xff; + } +} + +void seibu_main_word_w(INT32 offset, UINT8 data) +{ + offset = (offset >> 1) & 7; + + switch (offset) + { + case 0: + case 1: + main2sub[offset] = data; + break; + case 4: + if (!is_bootleg) update_irq_lines(RST18_ASSERT); + break; + case 6: + /* just a guess */ + sub2main_pending = 0; + main2sub_pending = 1; + break; + default: + break; + } +} + +void __fastcall tokib_write_byte(UINT32 address, UINT8 data) +{ + if ((address & 0xff800) == 0x6e000) { + DrvPalRAM[address & 0x7ff] = data; + + palette_write(address & 0x7fe); + + return; + } + + if (address >= 0x7180e && address <= 0x71e45) { + address ^= 1; + if (is_bootleg) DrvSprRAM[address & 0x7ff] = data; + return; + } + + if (address >= 0xa0000 && address <= 0xa0057) { + if (!is_bootleg)DrvScrollRAM[address & 0x3ff] = data; + return; + } + + switch (address) + { + case 0x71000: + case 0x71001: + // nop + return; + + + case 0x75000: + case 0x75001: { + *soundlatch = data & 0xff; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0x75004: + case 0x75005: + case 0x75006: + case 0x75007: + case 0x75008: + case 0x75009: + case 0x7500a: + case 0x7500b: + if (is_bootleg) DrvScrollRAM[address-0x75004] = data; + return; + + case 0x80000: + case 0x80001: + case 0x80002: + case 0x80003: + case 0x80004: + case 0x80005: + case 0x80006: + case 0x80007: + case 0x80008: + case 0x80009: + case 0x8000a: + case 0x8000b: + case 0x8000c: + case 0x8000d: { + seibu_main_word_w(address, data); + return; + } + } +} + +void __fastcall tokib_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xff800) == 0x6e000) { + *((UINT16*)(DrvPalRAM + (address & 0x7fe))) = data; + + palette_write(address & 0x7fe); + + return; + } + + if (address >= 0x7180e && address <= 0x71e45) { + if (is_bootleg)*((UINT16*)(DrvSprRAM + (address & 0x7fe))) = data; + return; + } + + if (address >= 0xa0000 && address <= 0xa0057) { + if (!is_bootleg)*((UINT16*)(DrvScrollRAM + (address & 0x3fe))) = data; + return; + } + + switch (address) + { + case 0x71000: + // nop + return; + + + case 0x75000: { + *soundlatch = data & 0xff; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0x75004: + case 0x75006: + case 0x75008: + case 0x7500a: + if (is_bootleg)*((UINT16*)(DrvScrollRAM + (address - 0x75004))) = data; + return; + + + case 0x80000: + case 0x80001: + case 0x80002: + case 0x80003: + case 0x80004: + case 0x80005: + case 0x80006: + case 0x80007: + case 0x80008: + case 0x80009: + case 0x8000a: + case 0x8000b: + case 0x8000c: + case 0x8000d: { + seibu_main_word_w(address, data); + return; + } + +// AM_RANGE(0x080000, 0x08000d) AM_READWRITE(seibu_main_word_r, seibu_main_word_w) + + } +} + +UINT8 __fastcall tokib_read_byte(UINT32 address) +{ + switch (address) + { + case 0x72000: + case 0x72001: + return 0;// watchdog reset + + case 0x80000: + case 0x80001: + case 0x80002: + case 0x80003: + case 0x80004: + case 0x80005: + case 0x80006: + case 0x80007: + case 0x80008: + case 0x80009: + case 0x8000a: + case 0x8000b: + case 0x8000c: + case 0x8000d: { + return seibu_main_word_r(address); + } + + case 0xc0000: + case 0xc0001: + return DrvDips[~address & 1]; + + case 0xc0002: return DrvInps[0] >> 8; + case 0xc0003: return DrvInps[0] & 0xff; + + case 0xc0004: return DrvInps[1] >> 8; + case 0xc0005: return DrvInps[1] & 0xff; + + case 0xc000e: + case 0xc000f: + return 0xff; + } + + return 0; +} + +UINT16 __fastcall tokib_read_word(UINT32 address) +{ + switch (address) + { + case 0x72000: + return 0;// watchdog reset + + case 0x80000: + case 0x80001: + case 0x80002: + case 0x80003: + case 0x80004: + case 0x80005: + case 0x80006: + case 0x80007: + case 0x80008: + case 0x80009: + case 0x8000a: + case 0x8000b: + case 0x8000c: + case 0x8000d: { + return seibu_main_word_r(address); + } + + case 0xc0000: + return (DrvDips[1] << 8) | (DrvDips[0]); + + case 0xc0002: + return DrvInps[0]; + + case 0xc0004: + return DrvInps[1]; + + case 0xc000e: + return 0xffff; + } + + return 0; +} + + +static void seibu_z80_bank(INT32 bank) +{ + INT32 nBank = bank & 1; + + ZetMapArea(0x8000, 0xffff, 0, DrvZ80ROM + 0x10000 + nBank * 0x8000); + ZetMapArea(0x8000, 0xffff, 2, DrvZ80ROM + 0x10000 + nBank * 0x8000); +} + +void __fastcall toki_seibu_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x4000: + main2sub_pending = 0; + sub2main_pending = 1; + return; + + case 0x4001: + update_irq_lines(VECTOR_INIT); + return; + + case 0x4002: + //seibu_rst10_ack_w - unused + return; + + case 0x4003: + update_irq_lines(RST18_CLEAR); + return; + + case 0x4007: + seibu_z80_bank(data); + return; + + case 0x4008: + BurnYM3812Write(0, data); + return; + + + case 0x4009: + BurnYM3812Write(1, data); + return; + + case 0x4018: + case 0x4019: + sub2main[address & 1] = data; + return; + + + case 0x401b: + //seibu_coin_w + return; + + + case 0x6000: + MSM6295Command(0, data); + return; + } + + bprintf (PRINT_NORMAL, _T("%4.4x, %2.2x\n"), address, data); +} + +UINT8 __fastcall toki_seibu_sound_read(UINT16 address) +{ + switch (address) + { + case 0x4008: + return BurnYM3812Read(0); + + case 0x4010: + case 0x4011: + return main2sub[address & 1]; + + case 0x4012: + return sub2main_pending ? 1 : 0; + + case 0x4013: + return (DrvJoy3[1] << 1) | DrvJoy3[0]; // COIN + + case 0x6000: + return MSM6295ReadStatus(0); + } + + bprintf (PRINT_NORMAL, _T("%4.4x,\n"), address); + + return 0; +} + +static void toki_adpcm_control_w(INT32 data) +{ + INT32 bankaddress = data & 1; + + UINT8 *RAM = DrvZ80ROM + 0x8000 + bankaddress * 0x4000; + + + /* the code writes either 2 or 3 in the bottom two bits */ +// bankaddress = 0x10000 + (data & 0x01) * 0x4000; +// memory_set_bankptr(1,&RAM[bankaddress]); + + ZetMapArea(0x8000, 0xbfff, 0, RAM); + ZetMapArea(0x8000, 0xbfff, 2, RAM); + + + MSM5205ResetWrite(0, data & 0x08); +} + + +void __fastcall tokib_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + toki_adpcm_control_w(data); + return; + + case 0xe400: + TokibMSM5205Next = data; + return; + + case 0xec00: + case 0xec08: + BurnYM3812Write(0, data); + return; + + case 0xec01: + case 0xec09: + BurnYM3812Write(1, data); + return; + } +} + +UINT8 __fastcall tokib_sound_read(UINT16 address) +{ + switch (address) + { + case 0xec00: + return BurnYM3812Read(0); + + case 0xf800: + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return *soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + if (!is_bootleg) update_irq_lines(VECTOR_INIT); + ZetClose(); + + BurnYM3812Reset(); + if (!is_bootleg) MSM6295Reset(0); + + return 0; +} + +static INT32 TokibDoReset() +{ + TokibMSM5205Next = 0; + TokibMSM5205Toggle = 0; + + MSM5205Reset(); + + return DrvDoReset(); +} + + +static void tokib_rom_decode() +{ + UINT8 *temp = (UINT8*)malloc(65536 * 2); + INT32 i, offs, len; + UINT8 *rom; + + /* invert the sprite data in the ROMs */ + len = 0x100000; + rom = DrvGfxROM1; + for (i = 0; i < len; i++) + rom[i] ^= 0xff; + + /* merge background tile graphics together */ + len = 0x080000; + rom = DrvGfxROM2; + for (offs = 0; offs < len; offs += 0x20000) + { + UINT8 *base = &rom[offs]; + memcpy (temp, base, 65536 * 2); + for (i = 0; i < 16; i++) + { + memcpy (&base[0x00000 + i * 0x800], &temp[0x0000 + i * 0x2000], 0x800); + memcpy (&base[0x10000 + i * 0x800], &temp[0x0800 + i * 0x2000], 0x800); + memcpy (&base[0x08000 + i * 0x800], &temp[0x1000 + i * 0x2000], 0x800); + memcpy (&base[0x18000 + i * 0x800], &temp[0x1800 + i * 0x2000], 0x800); + } + } + len = 0x080000; + rom = DrvGfxROM3; + for (offs = 0; offs < len; offs += 0x20000) + { + UINT8 *base = &rom[offs]; + memcpy (temp, base, 65536 * 2); + for (i = 0; i < 16; i++) + { + memcpy (&base[0x00000 + i * 0x800], &temp[0x0000 + i * 0x2000], 0x800); + memcpy (&base[0x10000 + i * 0x800], &temp[0x0800 + i * 0x2000], 0x800); + memcpy (&base[0x08000 + i * 0x800], &temp[0x1000 + i * 0x2000], 0x800); + memcpy (&base[0x18000 + i * 0x800], &temp[0x1800 + i * 0x2000], 0x800); + } + } + + if (temp) { + free (temp); + temp = NULL; + } +} + + + + + + + +static INT32 TokibGfxDecode() +{ + INT32 Plane0[4] = { 4096*8*8*3, 4096*8*8*2, 4096*8*8*1, 4096*8*8*0 }; // char + INT32 Plane1[4] = { 8192*16*16*3,8192*16*16*2,8192*16*16*1,8192*16*16*0 }; // spr + INT32 Plane2[4] = { 4096*16*16*3,4096*16*16*2,4096*16*16*1,4096*16*16*0 }; // tile +// char & spr + INT32 XOffs0[16] = { 0, 1, 2, 3, 4, 5, 6, 7, + 128+0, 128+1, 128+2, 128+3, 128+4, 128+5, 128+6, 128+7 }; + INT32 YOffs0[16] = { 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120 }; + +// tiles + INT32 XOffs1[16] = { 0, 1, 2, 3, 4, 5, 6, 7, + 0x8000*8+0, 0x8000*8+1, 0x8000*8+2, 0x8000*8+3, 0x8000*8+4, + 0x8000*8+5, 0x8000*8+6, 0x8000*8+7 }; + + INT32 YOffs1[32] = { 0,8,16,24,32,40,48,56, + 0x10000*8+ 0, 0x10000*8+ 8, 0x10000*8+16, 0x10000*8+24, 0x10000*8+32, + 0x10000*8+40, 0x10000*8+48, 0x10000*8+56 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(4096, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x040, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(8192, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(4096, 4, 16, 16, Plane2, XOffs1, YOffs1, 0x040, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x080000); + + GfxDecode(4096, 4, 16, 16, Plane2, XOffs1, YOffs1, 0x040, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x060000; + + DrvZ80ROM = Next; Next += 0x020000; + DrvZ80DecROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x200000; + DrvGfxROM2 = Next; Next += 0x100000; + DrvGfxROM3 = Next; Next += 0x100000; + + DrvSndROM = Next; Next += 0x020000; + + DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + AllRam = Next; + + DrvBg1RAM = Next; Next += 0x000800; + DrvBg2RAM = Next; Next += 0x000800; + DrvFgRAM = Next; Next += 0x000800; + Drv68KRAM = Next; Next += 0x00e000; + DrvZ80RAM = Next; Next += 0x000800; + DrvPalRAM = Next; Next += 0x000800; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + + DrvScrollRAM = Next; Next += 0x000060 + 0x3b0; // + buffer space + + soundlatch = Next; Next += 0x000001; + + Palette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3579545; +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + update_irq_lines(RST10_ASSERT); + } else { + update_irq_lines(RST10_CLEAR); + } +} + +inline static INT32 TokibSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 4000000); +} + +static void toki_adpcm_int() +{ + MSM5205DataWrite(0, TokibMSM5205Next); + TokibMSM5205Next >>= 4; + + TokibMSM5205Toggle ^= 1; + if (TokibMSM5205Toggle) ZetNmi(); +} + +static INT32 TokibInit() +{ + is_bootleg = 1; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + + for (INT32 i = 0; i < 4; i++) + if (BurnLoadRom(DrvGfxROM0 + i * 0x8000, 5 + i, 1)) return 1; + + for (INT32 i = 0; i < 8; i++) { + if (BurnLoadRom(DrvGfxROM1 + i * 0x20000, 9 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + i * 0x10000, 17 + i, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + i * 0x10000, 25 + i, 1)) return 1; + } + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 4, 1)) return 1; + + tokib_rom_decode(); + + TokibGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x060000, 0x06dfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x06e000, 0x06e7ff, SM_ROM); // 4b4g4r handler + SekMapMemory(DrvBg1RAM, 0x06e800, 0x06efff, SM_RAM); + SekMapMemory(DrvBg2RAM, 0x06f000, 0x06f7ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x06f800, 0x06ffff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x071800, 0x0718ff, SM_ROM); // allow writes to 0x7180e - 0x71e45 + SekSetWriteByteHandler(0, tokib_write_byte); + SekSetWriteWordHandler(0, tokib_write_word); + SekSetReadByteHandler(0, tokib_read_byte); + SekSetReadWordHandler(0, tokib_read_word); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80ROM + 0x8000); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80ROM + 0x8000); + ZetMapArea(0xf000, 0xf7ff, 0, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 1, DrvZ80RAM); + ZetMapArea(0xf000, 0xf7ff, 2, DrvZ80RAM); + ZetSetWriteHandler(tokib_sound_write); + ZetSetReadHandler(tokib_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(3579545, NULL, &TokibSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + MSM5205Init(0, TokibSynchroniseStream, 384000, toki_adpcm_int, MSM5205_S96_4B, 45, 1); + + GenericTilesInit(); + + TokibDoReset(); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 4096*16*8+0, 4096*16*8+4, 0, 4 }; // char + INT32 Plane1[4] = { 2*4, 3*4, 0*4, 1*4 }; // spr, tile + INT32 XOffs0[8] = { 3, 2, 1, 0, 8+3, 8+2, 8+1, 8+0 }; // char + INT32 YOffs0[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 }; + +// tiles + INT32 XOffs1[16] = { 3, 2, 1, 0, 16+3, 16+2, 16+1, 16+0, + 64*8+3, 64*8+2, 64*8+1, 64*8+0, 64*8+16+3, 64*8+16+2, 64*8+16+1, 64*8+16+0 }; + + INT32 YOffs1[32] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, + 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x100000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(4096, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x100000); + + GfxDecode(8192, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(4096, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM2); + + memcpy (tmp, DrvGfxROM3, 0x080000); + + GfxDecode(4096, 4, 16, 16, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM3); + + BurnFree (tmp); + + return 0; +} + +static UINT8 decrypt_data(INT32 a,INT32 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0); + + return src; +} + +static UINT8 decrypt_opcode(INT32 a,INT32 src) +{ + if ( BIT(a,9) & BIT(a,8)) src ^= 0x80; + if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40; + if (~BIT(a,13) & BIT(a,12)) src ^= 0x20; + if (~BIT(a,6) & BIT(a,1)) src ^= 0x10; + if (~BIT(a,12) & BIT(a,2)) src ^= 0x08; + if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04; + if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02; + if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01; + + if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1); + if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0); + if (BIT(a,12) & BIT(a,9)) src = BITSWAP08(src,7,6,4,5,3,2,1,0); + if (BIT(a,11) & ~BIT(a,6)) src = BITSWAP08(src,6,7,5,4,3,2,1,0); + + return src; +} + +static void seibu_sound_decrypt(INT32 length) +{ + UINT8 *decrypt = DrvZ80DecROM; + UINT8 *rom = DrvZ80ROM; + INT32 i; + + for (i = 0;i < length;i++) + { + UINT8 src = rom[i]; + + rom[i] = decrypt_data(i,src); + decrypt[i] = decrypt_opcode(i,src); + } +} + +static INT32 DrvInit() +{ + is_bootleg = 0; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (BurnLoadRom(Drv68KROM + 0x00001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 4, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x10000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 11, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 12, 1)) return 1; + + seibu_sound_decrypt(0x2000); + + DrvGfxDecode(); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x060000, 0x06d7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x06d800, 0x06dfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x06e000, 0x06e7ff, SM_ROM); // 4b4g4r handler + SekMapMemory(DrvBg1RAM, 0x06e800, 0x06efff, SM_RAM); + SekMapMemory(DrvBg2RAM, 0x06f000, 0x06f7ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x06f800, 0x06ffff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x0a0000, 0x0a0057, SM_ROM); // a03ff + SekSetWriteByteHandler(0, tokib_write_byte); + SekSetWriteWordHandler(0, tokib_write_word); + SekSetReadByteHandler(0, tokib_read_byte); + SekSetReadWordHandler(0, tokib_read_word); + SekClose(); + + ZetInit(1); + + ZetOpen(0); + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80DecROM, DrvZ80ROM ); + ZetMapArea(0x2000, 0x27ff, 0, DrvZ80RAM); + ZetMapArea(0x2000, 0x27ff, 1, DrvZ80RAM); + ZetMapArea(0x2000, 0x27ff, 2, DrvZ80RAM); + ZetSetWriteHandler(toki_seibu_sound_write); + ZetSetReadHandler(toki_seibu_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(3579545, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + MSM6295Init(0, 1000000 / 132, 100.0, 1); + MSM6295ROM = DrvSndROM; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 JujubInit() +{ + is_bootleg = 0; + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + if (BurnLoadRom(Drv68KROM + 0x20001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x20000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x00000, 3, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40001, 4, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x40000, 5, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x00000, 6, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x10000, 7, 1)) return 1; + memcpy(DrvZ80ROM, DrvZ80ROM + 0x2000, 0x6000); + + if (BurnLoadRom(DrvGfxROM0 + 0x00000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x10000, 9, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x00000, 10, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x00001, 11, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40000, 12, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x40001, 13, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80000, 14, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x80001, 15, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0xc0000, 16, 2)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0xc0001, 17, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x00001, 18, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20001, 19, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40001, 20, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60001, 21, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x00000, 22, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x20000, 23, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x40000, 24, 2)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x60000, 25, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x00001, 26, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x20001, 27, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x40001, 28, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x60001, 29, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x00000, 30, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x20000, 31, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x40000, 32, 2)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x60000, 33, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x00000, 34, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x10000, 35, 1)) return 1; + + UINT16 *PrgRom = (UINT16*)Drv68KROM; + for (INT32 i = 0; i < 0x30000; i++) { + PrgRom[i] = BITSWAP16(PrgRom[i], 15, 12, 13, 14, 11, 10, 9, 8, 7, 6, 5, 3, 4, 2, 1, 0); + } + + UINT8 *Decrypt = DrvZ80DecROM; + UINT8 *Rom = DrvZ80ROM; + memcpy(Decrypt, Rom, 0x2000); + for (INT32 i = 0;i < 0x2000; i++) { + UINT8 Src = Decrypt[i]; + Rom[i] = Src ^ 0x55; + } + + DrvGfxDecode(); + + UINT8 *Temp = (UINT8*)BurnMalloc(0x20000); + memcpy(Temp, DrvSndROM, 0x20000); + for (INT32 i = 0; i < 0x20000; i++ ) { + DrvSndROM[i] = Temp[BITSWAP24(i, 23, 22, 21, 20, 19, 18, 17, 16, 13, 14, 15, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)]; + } + BurnFree(Temp); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Drv68KRAM, 0x060000, 0x06d7ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x06d800, 0x06dfff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x06e000, 0x06e7ff, SM_ROM); // 4b4g4r handler + SekMapMemory(DrvBg1RAM, 0x06e800, 0x06efff, SM_RAM); + SekMapMemory(DrvBg2RAM, 0x06f000, 0x06f7ff, SM_RAM); + SekMapMemory(DrvFgRAM, 0x06f800, 0x06ffff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x0a0000, 0x0a0057, SM_ROM); // a03ff + SekSetWriteByteHandler(0, tokib_write_byte); + SekSetWriteWordHandler(0, tokib_write_word); + SekSetReadByteHandler(0, tokib_read_byte); + SekSetReadWordHandler(0, tokib_read_word); + SekClose(); + + ZetInit(1); + + ZetOpen(0); + ZetMapArea(0x0000, 0x1fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x1fff, 2, DrvZ80DecROM, DrvZ80ROM ); + ZetMapArea(0x2000, 0x27ff, 0, DrvZ80RAM); + ZetMapArea(0x2000, 0x27ff, 1, DrvZ80RAM); + ZetMapArea(0x2000, 0x27ff, 2, DrvZ80RAM); + ZetSetWriteHandler(toki_seibu_sound_write); + ZetSetReadHandler(toki_seibu_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM3812Init(3579545, &DrvFMIRQHandler, &DrvSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3579545); + + MSM6295Init(0, 1000000 / 132, 100.0, 1); + MSM6295ROM = DrvSndROM; + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + BurnYM3812Exit(); + + SekExit(); + ZetExit(); + + BurnFree (AllMem); + + TokibMSM5205Next = 0; + TokibMSM5205Toggle = 0; + + return 0; +} + +static void draw_text_layer() +{ + UINT16 *vram = (UINT16*)DrvFgRAM; + + for (INT32 offs = 0x040; offs < 0x3c0; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + sy -= 16; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + code &= 0xfff; + + if (code == 0) continue; + + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0x0f, 0x100, DrvGfxROM0); + } +} + +static void draw_bg_layer(UINT8 *vidsrc, UINT8 *gfxbase, INT32 transp, INT32 gfxoffs, INT32 scrollx, INT32 scrolly) +{ + UINT16 *vram = (UINT16*)vidsrc; + + scrollx &= 0x1ff; + scrolly &= 0x1ff; + + for (INT32 offs = 0; offs < 0x800 / 2; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x200; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + INT32 code = vram[offs]; + INT32 color = code >> 12; + + if (transp) { + Render16x16Tile_Mask_Clip(pTransDraw, code & 0xfff, sx, sy, color, 4, 0x0f, gfxoffs, gfxbase); + } else { + Render16x16Tile_Clip(pTransDraw, code & 0xfff, sx, sy, color, 4, gfxoffs, gfxbase); + } + } +} + +static void draw_bg_layer_by_line(UINT8 *vidsrc, UINT8 *gfxbase, INT32 transp, INT32 gfxoffs, INT32 scrollx, INT32 scrolly, INT32 line) +{ + UINT8 *src; + UINT16 *vram = (UINT16*)vidsrc; + + INT32 starty = line + scrolly; + if (starty > 0x1ff) starty -= 0x200; + starty = (starty & 0x1f0) << 1; + + for (INT32 offs = starty; offs < starty + 0x20; offs++) + { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx -= scrollx; + if (sx < -15) sx += 0x200; + sy -= scrolly; + if (sy < -15) sy += 0x200; + + INT32 code = vram[offs]; + INT32 color = ((code >> 8) & 0xf0) | gfxoffs; + + if (sx < -15 || sx >= nScreenWidth) continue; + src = gfxbase + ((code & 0xfff) << 8) + ((line - sy) << 4); + + sy = line * nScreenWidth; + + if (transp) { + for (INT32 x = 0; x < 16; x++, sx++) { + if (src[x] != 0x0f && sx >= 0 && sx < nScreenWidth) { + pTransDraw[sy + sx] = color | src[x]; + } + } + } else { + for (INT32 x = 0; x < 16; x++, sx++) { + if (sx >= 0 && sx < nScreenWidth) { + pTransDraw[sy + sx] = color | src[x]; + } + } + } + } +} + +static void tokib_draw_sprites() +{ + INT32 x,y,code,flipx,color,offs; + UINT16 *sprite_buffer = (UINT16*)(DrvSprBuf + 0xe); + UINT16 *sprite_word; + + for (offs = 0;offs < 0x642 / 2;offs += 4) + { + sprite_word = &sprite_buffer[offs]; + + if (sprite_word[0] == 0xf100) + break; + + if (sprite_word[2]) + { + x = sprite_word[3] & 0x1ff; + if (x > 256) + x -= 512; + + y = sprite_word[0] & 0x1ff; + if (y > 256) + y = (512-y)+240; + else + y = 240-y; + + flipx = sprite_word[1] & 0x4000; + code = sprite_word[1] & 0x1fff; + color = sprite_word[2] >> 12; + + y-=1+16; + + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } + } + } +} + + +static void toki_draw_sprites() +{ + INT32 x,y,xoffs,yoffs,code,flipx,flipy,color,offs; + UINT16 *sprite_buffer = (UINT16*)DrvSprBuf; + UINT16 *sprite_word; + + for (offs = (0x800/2)-4;offs >= 0;offs -= 4) + { + sprite_word = &sprite_buffer[offs]; + + if ((sprite_word[2] != 0xf000) && (sprite_word[0] != 0xffff)) + { + xoffs = (sprite_word[0] &0xf0); + x = (sprite_word[2] + xoffs) & 0x1ff; + if (x > 256) + x -= 512; + + yoffs = (sprite_word[0] &0xf) << 4; + y = (sprite_word[3] + yoffs) & 0x1ff; + if (y > 256) + y -= 512; + + color = sprite_word[1] >> 12; + flipx = sprite_word[0] & 0x100; + flipy = 0; + code = (sprite_word[1] & 0xfff) + ((sprite_word[2] & 0x8000) >> 3); + + if (0) { // flipscreen + x=240-x; + y=240-y; + if (flipx) flipx=0; else flipx=1; + flipy=1; + } + + y-=16; + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, x, y, color, 4, 0x0f, 0, DrvGfxROM1); + } + } + } + } +} + + +static INT32 TokibDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + UINT16 *scrollram = (UINT16 *)DrvScrollRAM; + + if (scrollram[3] & 0x2000) { + draw_bg_layer(DrvBg1RAM, DrvGfxROM2, 0, 0x200, scrollram[1]-0x103, scrollram[0]+1+16); + draw_bg_layer(DrvBg2RAM, DrvGfxROM3, 1, 0x300, scrollram[3]-0x101, scrollram[2]+1+16); + } else { + draw_bg_layer(DrvBg2RAM, DrvGfxROM3, 0, 0x300, scrollram[3]-0x101, scrollram[2]+1+16); + draw_bg_layer(DrvBg1RAM, DrvGfxROM2, 1, 0x200, scrollram[1]-0x103, scrollram[0]+1+16); + } + + tokib_draw_sprites(); + + draw_text_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +void assemble_inputs(UINT16 in0base, UINT16 in1base) +{ + DrvInps[0] = in0base; + DrvInps[1] = in1base; + + for (INT32 i = 0; i < 16; i++) { + DrvInps[0] ^= (DrvJoy1[i] & 1) << i; + DrvInps[1] ^= (DrvJoy2[i] & 1) << i; + } +} + +static INT32 TokibFrame() +{ + if (DrvReset) { + TokibDoReset(); + } + + INT32 nInterleave = MSM5205CalcInterleave(0, 4000000); + + SekNewFrame(); + ZetNewFrame(); + + assemble_inputs(0x3f3f, 0xff1f); + + INT32 nCyclesToDo[2] = { 12000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext, nCyclesSegment; + + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nCyclesToDo[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerUpdateYM3812(i * (nCyclesToDo[1] / nInterleave)); + MSM5205Update(); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrameYM3812(nCyclesToDo[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + if (pBurnDraw) { + TokibDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + UINT16 *scrollram = (UINT16*)DrvScrollRAM; + INT32 bgscrolly,bgscrollx,fgscrolly,fgscrollx; + + bgscrollx = ((scrollram[0x06] & 0x7f) << 1) | ((scrollram[0x06] & 0x80) >> 7) | ((scrollram[0x05] & 0x10) << 4); + bgscrolly = ((scrollram[0x0e] & 0x7f) << 1) | ((scrollram[0x0e] & 0x80) >> 7) | ((scrollram[0x0d] & 0x10) << 4); + + fgscrollx = ((scrollram[0x16] & 0x7f) << 1) | ((scrollram[0x16] & 0x80) >> 7) | ((scrollram[0x15] & 0x10) << 4); + fgscrolly = ((scrollram[0x1e] & 0x7f) << 1) | ((scrollram[0x1e] & 0x80) >> 7) | ((scrollram[0x1d] & 0x10) << 4); + + if (~nBurnLayer & 1) memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + if (scrollram[0x28] & 0x0100) { + if (nBurnLayer & 1) draw_bg_layer(DrvBg1RAM, DrvGfxROM2, 0, 0x200, bgscrollx, bgscrolly+16); + if (nBurnLayer & 2) draw_bg_layer(DrvBg2RAM, DrvGfxROM3, 1, 0x300, fgscrollx, fgscrolly+16); + } else { + if (nBurnLayer & 2) draw_bg_layer(DrvBg2RAM, DrvGfxROM3, 0, 0x300, fgscrollx, fgscrolly+16); + if (nBurnLayer & 1) draw_bg_layer(DrvBg1RAM, DrvGfxROM2, 1, 0x200, bgscrollx, bgscrolly+16); + } +#if 0 + flip_screen_set((toki_scrollram16[0x28]&0x8000)==0); + +#endif + + toki_draw_sprites(); + + draw_text_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrawByLine(INT32 line) +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x400; i++) { + INT32 rgb = Palette[i]; + DrvPalette[i] = BurnHighCol(rgb >> 16, rgb >> 8, rgb, 0); + } + } + + UINT16 *scrollram = (UINT16*)DrvScrollRAM; + INT32 bgscrolly,bgscrollx,fgscrolly,fgscrollx; + + bgscrollx = ((scrollram[0x06] & 0x7f) << 1) | ((scrollram[0x06] & 0x80) >> 7) | ((scrollram[0x05] & 0x10) << 4); + bgscrolly = ((scrollram[0x0e] & 0x7f) << 1) | ((scrollram[0x0e] & 0x80) >> 7) | ((scrollram[0x0d] & 0x10) << 4); + + fgscrollx = ((scrollram[0x16] & 0x7f) << 1) | ((scrollram[0x16] & 0x80) >> 7) | ((scrollram[0x15] & 0x10) << 4); + fgscrolly = ((scrollram[0x1e] & 0x7f) << 1) | ((scrollram[0x1e] & 0x80) >> 7) | ((scrollram[0x1d] & 0x10) << 4); + + //memset (pTransDraw + line * 2, 0, nScreenWidth * 2); + if (~nBurnLayer & 1) memset (pTransDraw, 0, nScreenWidth * nScreenHeight * 2); + + if (scrollram[0x28] & 0x0100) { + if (nBurnLayer & 1) draw_bg_layer_by_line(DrvBg1RAM, DrvGfxROM2, 0, 0x200, bgscrollx, bgscrolly+16, line); + if (nBurnLayer & 2) draw_bg_layer_by_line(DrvBg2RAM, DrvGfxROM3, 1, 0x300, fgscrollx, fgscrolly+16, line); + } else { + if (nBurnLayer & 2) draw_bg_layer_by_line(DrvBg2RAM, DrvGfxROM3, 0, 0x300, fgscrollx, fgscrolly+16, line); + if (nBurnLayer & 1) draw_bg_layer_by_line(DrvBg1RAM, DrvGfxROM2, 1, 0x200, bgscrollx, bgscrolly+16, line); + } + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + SekNewFrame(); + ZetNewFrame(); + + assemble_inputs(0xffff, 0xffff); + + INT32 nInterleave = 256 * 2; + INT32 nCycleSegment; + nCyclesTotal[0] = 10000000 / 60; + nCyclesTotal[1] = 3579545 / 60 ; + INT32 nCyclesDone[2] = { 0, 0 }; + + + SekOpen(0); + ZetOpen(0); +//bprintf (PRINT_NORMAL, _T("before run\n")); + + for (INT32 i = 0; i < nInterleave; i++) + { + nCycleSegment = (nCyclesTotal[0] - nCyclesDone[0]) / (nInterleave - i); + nCyclesDone[0] += SekRun(nCycleSegment); + + BurnTimerUpdateYM3812(i * (nCyclesTotal[1] / nInterleave)); + + INT32 scanline = i >> 1; + + if (pTransDraw && scanline > 15 && scanline < 240 && !(i&1)) { + DrawByLine(scanline-16); + } + } + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + + ZetClose(); + SekClose(); +//bprintf (PRINT_NORMAL, _T("before sprites\n")); + if (pBurnDraw) { + toki_draw_sprites(); + + draw_text_layer(); + + BurnTransferCopy(DrvPalette); + } + + if (pBurnSoundOut) { + ZetOpen(0); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x800); +//bprintf (PRINT_NORMAL, _T("end\n")); + + return 0; +} + + +// Toki (World set 1) + +static struct BurnRomInfo tokiRomDesc[] = { + { "l10_6.bin", 0x20000, 0x94015d91, 1 }, // 0 main + { "k10_4e.bin", 0x20000, 0x531bd3ef, 1 }, // 1 + { "tokijp.005", 0x10000, 0xd6a82808, 1 }, // 2 + { "tokijp.003", 0x10000, 0xa01a5b10, 1 }, // 3 + + { "tokijp.008", 0x02000, 0x6c87c4c5, 2 }, // 4 audio + { "tokijp.007", 0x10000, 0xa67969c4, 2 }, // 5 + + { "tokijp.001", 0x10000, 0x8aa964a2, 3 }, // 6 gfx1 + { "tokijp.002", 0x10000, 0x86e87e48, 3 }, // 7 + + { "toki.ob1", 0x80000, 0xa27a80ba, 4 }, // 8 gfx2 + { "toki.ob2", 0x80000, 0xfa687718, 4 }, // 9 + + { "toki.bk1", 0x80000, 0xfdaa5f4b, 5 }, // 10 gfx3 + + { "toki.bk2", 0x80000, 0xd86ac664, 6 }, // 11 gfx4 + + { "tokijp.009", 0x20000, 0xae7a6b8b, 7 }, // 12 oki +}; + +STD_ROM_PICK(toki) +STD_ROM_FN(toki) + +struct BurnDriver BurnDrvToki = { + "toki", NULL, NULL, NULL, "1989", + "Toki (World set 1)\0", NULL, "Tad", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tokiRomInfo, tokiRomName, NULL, NULL, TokiInputInfo, TokiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Toki (World set 2) + +static struct BurnRomInfo tokiaRomDesc[] = { + { "tokijp.006", 0x20000, 0x03d726b1, 1 }, // 0 main + { "4c.10k", 0x20000, 0xb2c345c5, 1 }, // 1 + { "tokijp.005", 0x10000, 0xd6a82808, 1 }, // 2 + { "tokijp.003", 0x10000, 0xa01a5b10, 1 }, // 3 + + { "tokijp.008", 0x02000, 0x6c87c4c5, 2 }, // 4 audio + { "tokijp.007", 0x10000, 0xa67969c4, 2 }, // 5 + + { "tokijp.001", 0x10000, 0x8aa964a2, 3 }, // 6 gfx1 + { "tokijp.002", 0x10000, 0x86e87e48, 3 }, // 7 + + { "toki.ob1", 0x80000, 0xa27a80ba, 4 }, // 8 gfx2 + { "toki.ob2", 0x80000, 0xfa687718, 4 }, // 9 + + { "toki.bk1", 0x80000, 0xfdaa5f4b, 5 }, // 10 gfx3 + + { "toki.bk2", 0x80000, 0xd86ac664, 6 }, // 11 gfx4 + + { "tokijp.009", 0x20000, 0xae7a6b8b, 7 }, // 12 oki +}; + +STD_ROM_PICK(tokia) +STD_ROM_FN(tokia) + +struct BurnDriver BurnDrvTokia = { + "tokia", "toki", NULL, NULL, "1989", + "Toki (World set 2)\0", NULL, "Tad", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tokiaRomInfo, tokiaRomName, NULL, NULL, TokiInputInfo, TokiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Toki (US) + +static struct BurnRomInfo tokiuRomDesc[] = { + { "6b.10m", 0x20000, 0x3674d9fe, 1 }, // 0 main + { "14.10k", 0x20000, 0xbfdd48af, 1 }, // 1 + { "tokijp.005", 0x10000, 0xd6a82808, 1 }, // 2 + { "tokijp.003", 0x10000, 0xa01a5b10, 1 }, // 3 + + { "tokijp.008", 0x02000, 0x6c87c4c5, 2 }, // 4 audio + { "tokijp.007", 0x10000, 0xa67969c4, 2 }, // 5 + + { "tokijp.001", 0x10000, 0x8aa964a2, 3 }, // 6 gfx1 + { "tokijp.002", 0x10000, 0x86e87e48, 3 }, // 7 + + { "toki.ob1", 0x80000, 0xa27a80ba, 4 }, // 8 gfx2 + { "toki.ob2", 0x80000, 0xfa687718, 4 }, // 9 + + { "toki.bk1", 0x80000, 0xfdaa5f4b, 5 }, // 10 gfx3 + + { "toki.bk2", 0x80000, 0xd86ac664, 6 }, // 11 gfx4 + + { "tokijp.009", 0x20000, 0xae7a6b8b, 7 }, // 12 oki +}; + +STD_ROM_PICK(tokiu) +STD_ROM_FN(tokiu) + +struct BurnDriver BurnDrvTokiu = { + "tokiu", "toki", NULL, NULL, "1989", + "Toki (US)\0", NULL, "Tad (Fabtek license)", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tokiuRomInfo, tokiuRomName, NULL, NULL, TokiInputInfo, TokiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// JuJu Densetsu (Japan) + +static struct BurnRomInfo jujuRomDesc[] = { + { "tokijp.006", 0x20000, 0x03d726b1, 1 }, // 0 main + { "tokijp.004", 0x20000, 0x54a45e12, 1 }, // 1 + { "tokijp.005", 0x10000, 0xd6a82808, 1 }, // 2 + { "tokijp.003", 0x10000, 0xa01a5b10, 1 }, // 3 + + { "tokijp.008", 0x02000, 0x6c87c4c5, 2 }, // 4 audio + { "tokijp.007", 0x10000, 0xa67969c4, 2 }, // 5 + + { "tokijp.001", 0x10000, 0x8aa964a2, 3 }, // 6 gfx1 + { "tokijp.002", 0x10000, 0x86e87e48, 3 }, // 7 + + { "toki.ob1", 0x80000, 0xa27a80ba, 4 }, // 8 gfx2 + { "toki.ob2", 0x80000, 0xfa687718, 4 }, // 9 + + { "toki.bk1", 0x80000, 0xfdaa5f4b, 5 }, // 10 gfx3 + + { "toki.bk2", 0x80000, 0xd86ac664, 6 }, // 11 gfx4 + + { "tokijp.009", 0x20000, 0xae7a6b8b, 7 }, // 12 oki +}; + +STD_ROM_PICK(juju) +STD_ROM_FN(juju) + +struct BurnDriver BurnDrvJuju = { + "juju", "toki", NULL, NULL, "1989", + "JuJu Densetsu (Japan)\0", NULL, "Tad", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, jujuRomInfo, jujuRomName, NULL, NULL, TokiInputInfo, TokiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// JuJu Densetsu (Japan, bootleg) + +static struct BurnRomInfo jujubRomDesc[] = { + { "8.19g", 0x10000, 0x208fb08a, 1 }, // 0 main + { "5.19e", 0x10000, 0x722e5183, 1 }, // 1 + { "9.20g", 0x10000, 0xcb82cc33, 1 }, // 2 + { "6.20e", 0x10000, 0x826ab39d, 1 }, // 3 + { "10.21g", 0x10000, 0x6c7a3ffe, 1 }, // 4 + { "7.21e", 0x10000, 0xb0628230, 1 }, // 5 + + { "3.9c", 0x08000, 0x808f5e44, 2 }, // 6 audio + { "4.11c", 0x10000, 0xa67969c4, 2 }, // 7 + + { "5.19h", 0x10000, 0x8aa964a2, 3 }, // 8 gfx1 + { "6.20h", 0x10000, 0x86e87e48, 3 }, // 9 + + { "1.17d", 0x20000, 0xa027bd8e, 4 }, // 10 gfx2 + { "27.17b", 0x20000, 0x43a767ea, 4 }, // 11 + { "2.18d", 0x20000, 0x1aecc9d8, 4 }, // 12 + { "28.18b", 0x20000, 0xd65c0c6d, 4 }, // 13 + { "3.20d", 0x20000, 0xcedaccaf, 4 }, // 14 + { "29.20b", 0x20000, 0x013f539b, 4 }, // 15 + { "4.21d", 0x20000, 0x6a8e6e22, 4 }, // 16 + { "30.21b", 0x20000, 0x25d9a16c, 4 }, // 17 + + { "11.1j", 0x10000, 0x6ad15560, 5 }, // 18 gfx3 + { "12.2j", 0x10000, 0x68534844, 5 }, // 19 + { "13.4j", 0x10000, 0xf271be5a, 5 }, // 20 + { "14.5j", 0x10000, 0x5d4c187a, 5 }, // 21 + { "19.1l", 0x10000, 0x10afdf03, 5 }, // 22 + { "20.2l", 0x10000, 0x2dc54f41, 5 }, // 23 + { "21.4l", 0x10000, 0x946862a3, 5 }, // 24 + { "22.5l", 0x10000, 0xb45f5608, 5 }, // 25 + + { "15.18j", 0x10000, 0xcb8b1d31, 6 }, // 26 gfx4 + { "16.19j", 0x10000, 0x81594e0a, 6 }, // 27 + { "17.20j", 0x10000, 0x4acd44ce, 6 }, // 28 + { "18.21j", 0x10000, 0x25cfe9c3, 6 }, // 29 + { "23.18l", 0x10000, 0x06c8d622, 6 }, // 30 + { "24.19l", 0x10000, 0x362a0506, 6 }, // 31 + { "25.20l", 0x10000, 0xbe064c4b, 6 }, // 32 + { "26.21l", 0x10000, 0xf8b5b38d, 6 }, // 33 + + { "1.6a", 0x10000, 0x377153ad, 7 }, // 34 oki + { "2.7a", 0x10000, 0x093ca15d, 7 }, // 35 +}; + +STD_ROM_PICK(jujub) +STD_ROM_FN(jujub) + +struct BurnDriver BurnDrvJujub = { + "jujub", "toki", NULL, NULL, "1989", + "JuJu Densetsu (Japan, bootleg)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, jujubRomInfo, jujubRomName, NULL, NULL, TokiInputInfo, TokiDIPInfo, + JujubInit, DrvExit, DrvFrame, DrvDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + +// Toki (bootleg) + +static struct BurnRomInfo tokibRomDesc[] = { + { "toki.e3", 0x20000, 0xae9b3da4, 1 }, // 0 main + { "toki.e5", 0x20000, 0x66a5a1d6, 1 }, // 1 + { "tokijp.005", 0x10000, 0xd6a82808, 1 }, // 2 + { "tokijp.003", 0x10000, 0xa01a5b10, 1 }, // 3 + + { "toki.e1", 0x10000, 0x2832ef75, 2 }, // 4 audio + + { "toki.e21", 0x08000, 0xbb8cacbd, 3 }, // 5 gfx1 + { "toki.e13", 0x08000, 0x052ad275, 3 }, // 6 + { "toki.e22", 0x08000, 0x04dcdc21, 3 }, // 7 + { "toki.e7", 0x08000, 0x70729106, 3 }, // 8 + + { "toki.e26", 0x20000, 0xa8ba71fc, 4 }, // 9 gfx2 + { "toki.e28", 0x20000, 0x29784948, 4 }, // 10 + { "toki.e34", 0x20000, 0xe5f6e19b, 4 }, // 11 + { "toki.e36", 0x20000, 0x96e8db8b, 4 }, // 12 + { "toki.e30", 0x20000, 0x770d2b1b, 4 }, // 13 + { "toki.e32", 0x20000, 0xc289d246, 4 }, // 14 + { "toki.e38", 0x20000, 0x87f4e7fb, 4 }, // 15 + { "toki.e40", 0x20000, 0x96e87350, 4 }, // 16 + + { "toki.e23", 0x10000, 0xfeb13d35, 5 }, // 17 gfx3 + { "toki.e24", 0x10000, 0x5b365637, 5 }, // 18 + { "toki.e15", 0x10000, 0x617c32e6, 5 }, // 19 + { "toki.e16", 0x10000, 0x2a11c0f0, 5 }, // 20 + { "toki.e17", 0x10000, 0xfbc3d456, 5 }, // 21 + { "toki.e18", 0x10000, 0x4c2a72e1, 5 }, // 22 + { "toki.e8", 0x10000, 0x46a1b821, 5 }, // 23 + { "toki.e9", 0x10000, 0x82ce27f6, 5 }, // 24 + + { "toki.e25", 0x10000, 0x63026cad, 6 }, // 25 gfx4 + { "toki.e20", 0x10000, 0xa7f2ce26, 6 }, // 26 + { "toki.e11", 0x10000, 0x48989aa0, 6 }, // 27 + { "toki.e12", 0x10000, 0xc2ad9342, 6 }, // 28 + { "toki.e19", 0x10000, 0x6cd22b18, 6 }, // 29 + { "toki.e14", 0x10000, 0x859e313a, 6 }, // 30 + { "toki.e10", 0x10000, 0xe15c1d0f, 6 }, // 31 + { "toki.e6", 0x10000, 0x6f4b878a, 6 }, // 32 +}; + +STD_ROM_PICK(tokib) +STD_ROM_FN(tokib) + +struct BurnDriver BurnDrvTokib = { + "tokib", "toki", NULL, NULL, "1989", + "Toki (bootleg)\0", NULL, "bootleg", "hardware", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0, + NULL, tokibRomInfo, tokibRomName, NULL, NULL, TokibInputInfo, TokibDIPInfo, + TokibInit, DrvExit, TokibFrame, TokibDraw, NULL, NULL, 0x400, + 256, 224, 4, 3 +}; + + diff --git a/src/burn/drivers/misc_pre90s/d_vaportra.cpp b/src/burn/drivers/misc_pre90s/d_vaportra.cpp new file mode 100644 index 00000000..f8ceecf8 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_vaportra.cpp @@ -0,0 +1,820 @@ +// FB Alpha Vapor Trail driver module +// Based on MAME driver by Bryan McPhail + +#include "tiles_generic.h" +#include "deco16ic.h" +#include "burn_ym2203.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvHucROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvGfxROM3; +static UINT8 *DrvSndROM0; +static UINT8 *DrvSndROM1; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM0; +static UINT8 *DrvPalRAM1; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; + +static UINT32 *DrvPalette; +static UINT8 DrvRecalc; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT16 *priority; + +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; +static UINT16 DrvInputs[2]; + +static struct BurnInputInfo VaportraInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 15, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Vaportra) + +static struct BurnDIPInfo VaportraDIPList[]= +{ + {0x11, 0xff, 0xff, 0x7f, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x11, 0x01, 0x03, 0x00, "2" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x02, "4" }, + {0x11, 0x01, 0x03, 0x01, "5" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x11, 0x01, 0x0c, 0x08, "Easy" }, + {0x11, 0x01, 0x0c, 0x0c, "Normal" }, + {0x11, 0x01, 0x0c, 0x04, "Hard" }, + {0x11, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x11, 0x01, 0x30, 0x20, "150k, 300k and 600k" }, + {0x11, 0x01, 0x30, 0x30, "200k and 600k" }, + {0x11, 0x01, 0x30, 0x10, "300k only" }, + {0x11, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x11, 0x01, 0x40, 0x00, "No" }, + {0x11, 0x01, 0x40, 0x40, "Yes" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x12, 0x01, 0x07, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x01, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x12, 0x01, 0x38, 0x00, "3 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x08, "2 Coins 1 Credits" }, + {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x12, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x12, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x12, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x12, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + {0x12, 0x01, 0x38, 0x10, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Vaportra) + +void __fastcall vaportra_main_write_word(UINT32 address, UINT16 data) +{ + deco16_write_control_word(1, address, 0x240000, data) + deco16_write_control_word(0, address, 0x2c0000, data) + + switch (address) + { + case 0x100000: + case 0x100002: + priority[(address & 2)/2] = data; + return; + + case 0x100006: + *soundlatch = data; + // cpu_set_input_line(state->Huc6280 Code, 0, ASSERT_LINE); + return; + + case 0x30c000: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + } +} + +void __fastcall vaportra_main_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x100000: + case 0x100001: + case 0x100002: + case 0x100003: + priority[(address & 2)/2] = data; + return; + + case 0x100006: + case 0x100007: + *soundlatch = data; + // cpu_set_input_line(state->Huc6280 Code, 0, ASSERT_LINE); + return; + + case 0x30c000: + case 0x30c001: + memcpy (DrvSprBuf, DrvSprRAM, 0x800); + return; + } +} + +UINT16 __fastcall vaportra_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0]; + + case 0x100002: + return (DrvInputs[1] & 0xfff7) | (deco16_vblank & 0x08); + + case 0x100004: + return (DrvDips[1] << 8) | (DrvDips[0] << 0); + + case 0x100006: + case 0x100008: + case 0x10000a: + case 0x10000c: + case 0x10000e: + return 0xffff; + } + + return 0; +} + +UINT8 __fastcall vaportra_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x100000: + return DrvInputs[0] >> 8; + + case 0x100001: + return DrvInputs[0] >> 0; + + case 0x100002: + case 0x100003: + return (DrvInputs[1] & 0xf7) | (deco16_vblank & 0x08); + + case 0x100004: + return DrvDips[1]; + + case 0x100005: + return DrvDips[0]; + + case 0x100006: + case 0x100007: + case 0x100008: + case 0x100009: + case 0x10000a: + case 0x10000b: + case 0x10000c: + case 0x10000d: + case 0x10000e: + case 0x10000f: + return 0xff; + } + + return 0; +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return 0 * nSoundRate; //(INT64)HucTotalCycles() * nSoundRate / 8055000; +} + +static double DrvGetTime() +{ + return 0; //(double)HucTotalCycles() / 8055000.0; +} + +static void DrvYM2151IrqHandler(INT32 state) +{ + state = state; // kill warnings... +// HucSetIRQLine(1, state ? HUC_IRQSTATUS_ACK : HUC_IRQSTATUS_NONE); +} + +static INT32 vaportra_bank_callback( const INT32 bank ) +{ + return ((bank >> 4) & 0x7) * 0x1000; +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + // Huc6280 + + BurnYM2203Reset(); + BurnYM2151Reset(); + MSM6295Reset(0); + MSM6295Reset(1); + + deco16Reset(); + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvHucROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x100000; + DrvGfxROM1 = Next; Next += 0x100000; + DrvGfxROM2 = Next; Next += 0x200000; + DrvGfxROM3 = Next; Next += 0x200000; + + MSM6295ROM = Next; + DrvSndROM0 = Next; Next += 0x040000; + DrvSndROM1 = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x0500 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvSprRAM = Next; Next += 0x000800; + DrvSprBuf = Next; Next += 0x000800; + DrvPalRAM0 = Next; Next += 0x000a00; + DrvPalRAM1 = Next; Next += 0x000a00; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + priority = (UINT16*)Next; Next += 0x000002 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static void VaportraDecode() +{ + for (INT32 i = 0x00000; i < 0x80000; i++) + Drv68KROM[i] = (Drv68KROM[i] & 0x7e) | ((Drv68KROM[i] & 0x01) << 7) | ((Drv68KROM[i] & 0x80) >> 7); +} + +static INT32 DrvInit(INT32 type) +{ + BurnSetRefreshRate(58.00); + + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + VaportraDecode(); + + if (BurnLoadRom(DrvHucROM + 0x000000, 4, 1)) return 1; + + if (type) // world revision 3 + { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x000001, 6, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040000, 7, 2)) return 1; + if (BurnLoadRom(DrvGfxROM0 + 0x040001, 8, 2)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 10, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080000, 12, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 13, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 14, 1)) return 1; + } else { + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x080000, 7, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM3 + 0x000000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM3 + 0x080000, 9, 1)) return 1; + + if (BurnLoadRom(DrvSndROM0 + 0x000000, 10, 1)) return 1; + + if (BurnLoadRom(DrvSndROM1 + 0x000000, 11, 1)) return 1; + } + + memcpy (DrvGfxROM1 + 0x040000, DrvGfxROM0 + 0x000000, 0x040000); + memcpy (DrvGfxROM1 + 0x000000, DrvGfxROM0 + 0x040000, 0x040000); + + deco16_tile_decode(DrvGfxROM1, DrvGfxROM0, 0x080000, 1); + deco16_tile_decode(DrvGfxROM1, DrvGfxROM1, 0x080000, 0); + deco16_tile_decode(DrvGfxROM2, DrvGfxROM2, 0x100000, 0); + deco16_tile_decode(DrvGfxROM3, DrvGfxROM3, 0x100000, 0); + } + + deco16Init(0, 0, 1); + deco16_set_graphics(DrvGfxROM0, 0x100000, DrvGfxROM1, 0x100000, DrvGfxROM2, 0x200000); + deco16_set_color_base(0, 0x000); + deco16_set_color_base(1, 0x200); + deco16_set_color_base(2, 0x300); + deco16_set_color_base(3, 0x400); + deco16_set_bank_callback(0, vaportra_bank_callback); + deco16_set_bank_callback(1, vaportra_bank_callback); + deco16_set_bank_callback(2, vaportra_bank_callback); + deco16_set_bank_callback(3, vaportra_bank_callback); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(deco16_pf_ram[2], 0x200000, 0x201fff, SM_RAM); + SekMapMemory(deco16_pf_ram[3], 0x202000, 0x203fff, SM_RAM); + SekMapMemory(deco16_pf_ram[0], 0x280000, 0x281fff, SM_RAM); + SekMapMemory(deco16_pf_ram[1], 0x282000, 0x283fff, SM_RAM); + SekMapMemory(DrvPalRAM0, 0x300000, 0x3009ff, SM_RAM); + SekMapMemory(DrvPalRAM1, 0x304000, 0x3049ff, SM_RAM); + SekMapMemory(DrvSprRAM, 0xff8000, 0xff87ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, vaportra_main_write_word); + SekSetWriteByteHandler(0, vaportra_main_write_byte); + SekSetReadWordHandler(0, vaportra_main_read_word); + SekSetReadByteHandler(0, vaportra_main_read_byte); + SekClose(); + + // Huc6280... + + BurnYM2151Init(3580000, 40.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + BurnYM2203Init(1, 4027500, NULL, DrvSynchroniseStream, DrvGetTime, 1); +// BurnTimerAttachHuc(8055000); + + MSM6295Init(0, 1006875 / 132, 75.0, 1); + MSM6295Init(1, 2013750 / 132, 60.0, 1); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + deco16Exit(); + + BurnYM2203Exit(); + BurnYM2151Exit(); + MSM6295Exit(0); + MSM6295Exit(1); + + SekExit(); + + BurnFree (AllMem); + + MSM6295ROM = NULL; + + return 0; +} + +static void DrvPaletteRecalc() +{ + UINT16 *p0 = (UINT16*)DrvPalRAM0; + UINT16 *p1 = (UINT16*)DrvPalRAM1; + + for (INT32 i = 0; i < 0xa00 / 2; i++) { + DrvPalette[i] = BurnHighCol(p0[i] & 0xff, p0[i] >> 8, p1[i]& 0xff, 0); + } +} + +static void draw_sprites(INT32 pri) +{ + UINT16 *buffered_spriteram = (UINT16*)DrvSprBuf; + + INT32 priority_value = priority[1]; + + for (INT32 offs = 0; offs < 0x400; offs += 4) + { + INT32 inc, mult; + + INT32 y = buffered_spriteram[offs + 0]; + if ((y & 0x8000) == 0) continue; + + INT32 sprite = buffered_spriteram[offs + 1] & 0x1fff; + + INT32 x = buffered_spriteram[offs + 2]; + + INT32 colour = (x >> 12) & 0xf; + + if ( pri && (colour >= priority_value)) continue; + if (!pri && !(colour >= priority_value)) continue; + + if ((x & 0x0800) && (nCurrentFrame & 1)) continue; // flash + + INT32 fx = y & 0x2000; + INT32 fy = y & 0x4000; + INT32 multi = (1 << ((y & 0x1800) >> 11)) - 1; + + x = x & 0x01ff; + y = y & 0x01ff; + if (x >= 256) x -= 512; + if (y >= 256) y -= 512; + x = 240 - x; + y = 240 - y; + + if (x > 256) continue; + + sprite &= ~multi; + if (fy) + inc = -1; + else + { + sprite += multi; + inc = 1; + } + + if (*flipscreen) + { + y = 240 - y; + x = 240 - x; + if (fx) fx = 0; else fx = 1; + if (fy) fy = 0; else fy = 1; + mult = 16; + } + else mult = -16; + + while (multi >= 0) + { + if (fy) { + if (fx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x100, DrvGfxROM3); + } + } else { + if (fx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x100, DrvGfxROM3); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, sprite - multi * inc, x, (y + mult * multi) - 8, colour, 4, 0, 0x100, DrvGfxROM3); + } + } + + multi--; + } + } +} + +static INT32 DrvDraw() +{ +// if (DrvRecalc) { + DrvPaletteRecalc(); + DrvRecalc = 0; +// } + + deco16_pf12_update(); + deco16_pf34_update(); + + INT32 layer_prio = priority[0] & 0x03; + INT32 layer_order[4][4] = { { 3, 2, 1, 0 }, { 2, 3, 1, 0 }, { 3, 1, 2, 0 }, { 2, 1, 3, 0 } }; + + deco16_draw_layer(layer_order[layer_prio][0], pTransDraw, DECO16_LAYER_OPAQUE); + deco16_draw_layer(layer_order[layer_prio][1], pTransDraw, 0); + draw_sprites(0); + deco16_draw_layer(layer_order[layer_prio][2], pTransDraw, 0); + draw_sprites(1); + deco16_draw_layer(layer_order[layer_prio][3], pTransDraw, 0); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 2 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + DrvInputs[1] ^= (DrvJoy2[i] & 1) << i; + } + } + + INT32 nInterleave = 256; + INT32 nCyclesTotal[2] = { 12000000 / 58, 8055000 / 58 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + + deco16_vblank = 0; + + for (INT32 i = 0; i < nInterleave; i++) + { + nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave); + // nCyclesDone[1] += HucRun(nCyclesTotal[1] / nInterleave); + + if (i == 248) deco16_vblank = 0x08; + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + SekClose(); + + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + // huc6280 + + deco16Scan(); + + BurnYM2203Scan(nAction, pnMin); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + } + + return 0; +} + + +// Vapor Trail - Hyper Offence Formation (World revision 1) + +static struct BurnRomInfo vaportraRomDesc[] = { + { "fl_02-1.bin", 0x20000, 0x9ae36095, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fl_00-1.bin", 0x20000, 0xc08cc048, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fl_03.bin", 0x20000, 0x80bd2844, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fl_01.bin", 0x20000, 0x9474b085, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fj04", 0x10000, 0xe9aedf9b, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "vtmaa00.bin", 0x80000, 0x0330e13b, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + + { "vtmaa01.bin", 0x80000, 0xc217a31b, 4 | BRF_GRA }, // 7 + { "vtmaa02.bin", 0x80000, 0x091ff98e, 4 | BRF_GRA }, // 6 Background Tiles + + { "vtmaa04.bin", 0x80000, 0xb713e9cc, 5 | BRF_GRA }, // 9 + { "vtmaa03.bin", 0x80000, 0x1a30bf81, 5 | BRF_GRA }, // 8 Sprites + + { "fj06", 0x20000, 0x6e98a235, 6 | BRF_SND }, // 10 OKI M6295 Samples 0 + + { "fj05", 0x20000, 0x39cda2b5, 7 | BRF_SND }, // 11 OKI M6295 Samples 1 + + { "fj-27.bin", 0x00200, 0x65045742, 8 | BRF_OPT }, // 12 Unknown PROMs + + { "pal16l8a.6l", 0x00104, 0xee748e8f, 9 | BRF_OPT }, // 13 PLDs + { "pal16l8b.13g", 0x00104, 0x6da13bda, 9 | BRF_OPT }, // 14 + { "pal16l8b.13h", 0x00104, 0x62a9e098, 9 | BRF_OPT }, // 15 + { "pal16l8b.14g", 0x00104, 0x036768aa, 9 | BRF_OPT }, // 16 + { "pal16l8b.14h", 0x00104, 0xbf421fce, 9 | BRF_OPT }, // 17 +}; + +STD_ROM_PICK(vaportra) +STD_ROM_FN(vaportra) + +static INT32 VaportraInit() +{ + return DrvInit(0); +} + +struct BurnDriver BurnDrvVaportra = { + "vaportra", NULL, NULL, NULL, "1989", + "Vapor Trail - Hyper Offence Formation (World revision 1)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vaportraRomInfo, vaportraRomName, NULL, NULL, VaportraInputInfo, VaportraDIPInfo, + VaportraInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 240, 256, 3, 4 +}; + + +// Vapor Trail - Hyper Offence Formation (World revision 3) + +static struct BurnRomInfo vaportraw3RomDesc[] = { + { "fl02-3.bin", 0x20000, 0x6c59be54, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fl00-3.bin", 0x20000, 0x69f8bef4, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fl_03.bin", 0x20000, 0x80bd2844, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fl_01.bin", 0x20000, 0x9474b085, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fj04", 0x10000, 0xe9aedf9b, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "fl23", 0x20000, 0x6089f9e7, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + { "fl25", 0x20000, 0x3989290a, 3 | BRF_GRA }, // 6 + { "fl24", 0x20000, 0x41551bfa, 3 | BRF_GRA }, // 7 + { "fl26", 0x20000, 0xdc67fa5c, 3 | BRF_GRA }, // 8 + + { "vtmaa01.bin", 0x80000, 0xc217a31b, 4 | BRF_GRA }, // 9 Background Tiles + { "vtmaa02.bin", 0x80000, 0x091ff98e, 4 | BRF_GRA }, // 10 + + { "vtmaa04.bin", 0x80000, 0xb713e9cc, 5 | BRF_GRA }, // 11 Sprites + { "vtmaa03.bin", 0x80000, 0x1a30bf81, 5 | BRF_GRA }, // 12 + + { "fj06", 0x20000, 0x6e98a235, 6 | BRF_SND }, // 13 OKI M6295 Samples 0 + + { "fj05", 0x20000, 0x39cda2b5, 7 | BRF_SND }, // 14 OKI M6295 Samples 1 + + { "fj-27.bin", 0x00200, 0x65045742, 8 | BRF_OPT }, // 15 Unknown PROMs + + { "pal16l8a.6l", 0x00104, 0xee748e8f, 9 | BRF_OPT }, // 13 PLDs + { "pal16l8b.13g", 0x00104, 0x6da13bda, 9 | BRF_OPT }, // 14 + { "pal16l8b.13h", 0x00104, 0x62a9e098, 9 | BRF_OPT }, // 15 + { "pal16l8b.14g", 0x00104, 0x036768aa, 9 | BRF_OPT }, // 16 + { "pal16l8b.14h", 0x00104, 0xbf421fce, 9 | BRF_OPT }, // 17 +}; + +STD_ROM_PICK(vaportraw3) +STD_ROM_FN(vaportraw3) + +static INT32 Vaportraw3Init() +{ + return DrvInit(1); +} + +struct BurnDriver BurnDrvVaportraw3 = { + "vaportra3", "vaportra", NULL, NULL, "1989", + "Vapor Trail - Hyper Offence Formation (World revision 3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vaportraw3RomInfo, vaportraw3RomName, NULL, NULL, VaportraInputInfo, VaportraDIPInfo, + Vaportraw3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 240, 256, 3, 4 +}; + + +// Vapor Trail - Hyper Offence Formation (US) + +static struct BurnRomInfo vaportrauRomDesc[] = { + { "fj02", 0x20000, 0xa2affb73, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fj00", 0x20000, 0xef05e07b, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fj03", 0x20000, 0x44893379, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fj01", 0x20000, 0x97fbc107, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fj04", 0x10000, 0xe9aedf9b, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "vtmaa00.bin", 0x80000, 0x0330e13b, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + + { "vtmaa01.bin", 0x80000, 0xc217a31b, 4 | BRF_GRA }, // 7 + { "vtmaa02.bin", 0x80000, 0x091ff98e, 4 | BRF_GRA }, // 6 Background Tiles + + { "vtmaa04.bin", 0x80000, 0xb713e9cc, 5 | BRF_GRA }, // 9 + { "vtmaa03.bin", 0x80000, 0x1a30bf81, 5 | BRF_GRA }, // 8 Sprites + + { "fj06", 0x20000, 0x6e98a235, 6 | BRF_SND }, // 10 OKI M6295 Samples 0 + + { "fj05", 0x20000, 0x39cda2b5, 7 | BRF_SND }, // 11 OKI M6295 Samples 1 + + { "fj-27.bin", 0x00200, 0x65045742, 8 | BRF_OPT }, // 12 Unknown PROMs + + { "pal16l8a.6l", 0x00104, 0xee748e8f, 9 | BRF_OPT }, // 13 PLDs + { "pal16l8b.13g", 0x00104, 0x6da13bda, 9 | BRF_OPT }, // 14 + { "pal16l8b.13h", 0x00104, 0x62a9e098, 9 | BRF_OPT }, // 15 + { "pal16l8b.14g", 0x00104, 0x036768aa, 9 | BRF_OPT }, // 16 + { "pal16l8b.14h", 0x00104, 0xbf421fce, 9 | BRF_OPT }, // 17 +}; + +STD_ROM_PICK(vaportrau) +STD_ROM_FN(vaportrau) + +struct BurnDriver BurnDrvVaportrau = { + "vaportrau", "vaportra", NULL, NULL, "1989", + "Vapor Trail - Hyper Offence Formation (US)\0", "No sound", "Data East USA", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vaportrauRomInfo, vaportrauRomName, NULL, NULL, VaportraInputInfo, VaportraDIPInfo, + VaportraInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 240, 256, 3, 4 +}; + + +// Kuhga - Operation Code 'Vapor Trail' (Japan revision 3) + +static struct BurnRomInfo kuhgaRomDesc[] = { + { "fp02-3.bin", 0x20000, 0xd0705ef4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "fp00-3.bin", 0x20000, 0x1da92e48, 1 | BRF_PRG | BRF_ESS }, // 1 + { "fp03.bin", 0x20000, 0xea0da0f1, 1 | BRF_PRG | BRF_ESS }, // 2 + { "fp01.bin", 0x20000, 0xe3ecbe86, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "fj04", 0x10000, 0xe9aedf9b, 2 | BRF_PRG | BRF_ESS }, // 4 Huc6280 Code + + { "vtmaa00.bin", 0x80000, 0x0330e13b, 3 | BRF_GRA }, // 5 Characters and Foreground Tiles + + { "vtmaa01.bin", 0x80000, 0xc217a31b, 4 | BRF_GRA }, // 7 + { "vtmaa02.bin", 0x80000, 0x091ff98e, 4 | BRF_GRA }, // 6 Background Tiles + + { "vtmaa04.bin", 0x80000, 0xb713e9cc, 5 | BRF_GRA }, // 9 + { "vtmaa03.bin", 0x80000, 0x1a30bf81, 5 | BRF_GRA }, // 8 Sprites + + { "fj06", 0x20000, 0x6e98a235, 6 | BRF_SND }, // 10 OKI M6295 Samples 0 + + { "fj05", 0x20000, 0x39cda2b5, 7 | BRF_SND }, // 11 OKI M6295 Samples 1 + + { "fj-27.bin", 0x00200, 0x65045742, 8 | BRF_OPT }, // 12 Unknown PROMs +}; + +STD_ROM_PICK(kuhga) +STD_ROM_FN(kuhga) + +struct BurnDriver BurnDrvKuhga = { + "kuhga", "vaportra", NULL, NULL, "1989", + "Kuhga - Operation Code 'Vapor Trail' (Japan revision 3)\0", "No sound", "Data East Corporation", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, kuhgaRomInfo, kuhgaRomName, NULL, NULL, VaportraInputInfo, VaportraDIPInfo, + VaportraInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x500, + 240, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_vigilant.cpp b/src/burn/drivers/misc_pre90s/d_vigilant.cpp new file mode 100644 index 00000000..f2c6e606 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_vigilant.cpp @@ -0,0 +1,2190 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "dac.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[3] = {0, 0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram2 = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvChars = NULL; +static UINT8 *DrvBackTiles = NULL; +static UINT8 *DrvSprites = NULL; +static UINT8 *DrvSamples = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvRomBank; +static UINT8 DrvSoundLatch; +static UINT8 DrvIrqVector; + +static INT32 DrvRearColour; +static INT32 DrvRearDisable; +static INT32 DrvHorizScrollLo; +static INT32 DrvHorizScrollHi; +static INT32 DrvRearHorizScrollLo; +static INT32 DrvRearHorizScrollHi; +static INT32 DrvSampleAddress; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +static UINT8 DrvHasYM2203 = 0; +static UINT8 DrvKikcubicDraw = 0; + +static INT16 *DACBuffer = NULL; + +#define VECTOR_INIT 0 +#define YM2151_ASSERT 1 +#define YM2151_CLEAR 2 +#define Z80_ASSERT 3 +#define Z80_CLEAR 4 + +static struct BurnInputInfo DrvInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 2, "service" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnInputInfo BuccanrsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 6, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Buccanrs) + +static struct BurnInputInfo BuccanrsaInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, DrvDip + 2 , "dip" }, +}; + +STDINPUTINFO(Buccanrsa) + +static struct BurnInputInfo KikcubicInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort0 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , DrvInputPort1 + 3, "p1 up" }, + {"Down" , BIT_DIGITAL , DrvInputPort1 + 2, "p1 down" }, + {"Left" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , DrvInputPort1 + 7, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 2" }, + + {"Up (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 3, "p2 up" }, + {"Down (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 2, "p2 down" }, + {"Left (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 left" }, + {"Right (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 right" }, + {"Fire 1 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 7, "p2 fire 1" }, + {"Fire 2 (Cocktail)" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Kikcubic) + +static inline void DrvClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +static inline void DrvMakeInputs() +{ + // Reset Inputs + DrvInput[0] = DrvInput[1] = DrvInput[2] = 0x00; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvInputPort0[i] & 1) << i; + DrvInput[1] |= (DrvInputPort1[i] & 1) << i; + DrvInput[2] |= (DrvInputPort2[i] & 1) << i; + } + + // Clear Opposites + DrvClearOpposites(&DrvInput[1]); + DrvClearOpposites(&DrvInput[2]); +} + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x03, 0x02, "2" }, + {0x12, 0x01, 0x03, 0x03, "3" }, + {0x12, 0x01, 0x03, 0x01, "4" }, + {0x12, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x12, 0x01, 0x04, 0x04, "Normal" }, + {0x12, 0x01, 0x04, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Energy Decrease Rate" }, + {0x12, 0x01, 0x08, 0x08, "Slow" }, + {0x12, 0x01, 0x08, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x12, 0x01, 0xf0, 0xa0, "6 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0xb0, "5 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0xc0, "4 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0xd0, "3 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x10, "8 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0xe0, "2 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x20, "5 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0x30, "3 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x12, 0x01, 0xf0, 0x40, "2 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0x90, "1 Coin 2 Plays" }, + {0x12, 0x01, 0xf0, 0x80, "1 Coin 3 Plays" }, + {0x12, 0x01, 0xf0, 0x70, "1 Coin 4 Plays" }, + {0x12, 0x01, 0xf0, 0x60, "1 Coin 5 Plays" }, + {0x12, 0x01, 0xf0, 0x50, "1 Coin 6 Plays" }, + {0x12, 0x01, 0xf0, 0x00, "Freeplay" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x02, 0x00, "Upright" }, + {0x13, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x13, 0x01, 0x04, 0x04, "Mode 1" }, + {0x13, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x10, 0x00, "Off" }, + {0x13, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Stop Mode" }, + {0x13, 0x01, 0x20, 0x20, "Off" }, + {0x13, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x13, 0x01, 0x40, 0x40, "Off" }, + {0x13, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Drv) + +static struct BurnDIPInfo BuccanrsDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0x2f, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 12 , "Coin A" }, + {0x12, 0x01, 0x0f, 0x04, "4 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x07, "3 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x00, "5 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0a, "2 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x06, "3 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x03, "4 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 12 , "Coin B" }, + {0x12, 0x01, 0xf0, 0x40, "4 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x70, "3 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x00, "5 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0xa0, "2 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x60, "3 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0x30, "4 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 5 Plays" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Plays" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Plays" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x06, 0x06, "2" }, + {0x13, 0x01, 0x06, 0x04, "3" }, + {0x13, 0x01, 0x06, 0x02, "4" }, + {0x13, 0x01, 0x06, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Medium" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Invincibilty" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x20, 0x20, "Upright" }, + {0x13, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Buccanrs) + +static struct BurnDIPInfo BuccanrsaDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xf4, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + {0x13, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0xf4, 0xf4, "Off" }, + {0x11, 0x01, 0xf4, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 12 , "Coin A" }, + {0x12, 0x01, 0x0f, 0x04, "4 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x07, "3 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x00, "5 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0a, "2 Coins 1 Play" }, + {0x12, 0x01, 0x0f, 0x06, "3 Coins 2 Plays" }, + {0x12, 0x01, 0x0f, 0x03, "4 Coins 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Play" }, + {0x12, 0x01, 0x0f, 0x05, "3 Coins 5 Plays" }, + {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Plays" }, + {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Plays" }, + {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Plays" }, + {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Plays" }, + + {0 , 0xfe, 0 , 12 , "Coin B" }, + {0x12, 0x01, 0xf0, 0x40, "4 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x70, "3 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x00, "5 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0xa0, "2 Coins 1 Play" }, + {0x12, 0x01, 0xf0, 0x60, "3 Coins 2 Plays" }, + {0x12, 0x01, 0xf0, 0x30, "4 Coins 3 Plays" }, + {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x12, 0x01, 0xf0, 0x50, "3 Coins 5 Plays" }, + {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Plays" }, + {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Plays" }, + {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Plays" }, + {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Plays" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x06, 0x06, "2" }, + {0x13, 0x01, 0x06, 0x04, "3" }, + {0x13, 0x01, 0x06, 0x02, "4" }, + {0x13, 0x01, 0x06, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Medium" }, + {0x13, 0x01, 0x18, 0x10, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Invincibilty" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x20, 0x20, "Upright" }, + {0x13, 0x01, 0x20, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x40, 0x00, "Off" }, + {0x13, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Buccanrsa) + +static struct BurnDIPInfo KikcubicDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xd5, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x03, 0x02, "Easy" }, + {0x11, 0x01, 0x03, 0x03, "Medium" }, + {0x11, 0x01, 0x03, 0x01, "Hard" }, + {0x11, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x08, "1" }, + {0x11, 0x01, 0x0c, 0x04, "2" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x00, "4" }, + + {0 , 0xfe, 0 , 12 , "Coinage" }, + {0x11, 0x01, 0xf0, 0xa0, "6 Coins 1 Play" }, + {0x11, 0x01, 0xf0, 0xb0, "5 Coins 1 Play" }, + {0x11, 0x01, 0xf0, 0xc0, "4 Coins 1 Play" }, + {0x11, 0x01, 0xf0, 0xd0, "3 Coins 1 Play" }, + {0x11, 0x01, 0xf0, 0xe0, "2 Coins 1 Play" }, + {0x11, 0x01, 0xf0, 0xf0, "1 Coin 1 Play" }, + {0x11, 0x01, 0xf0, 0x70, "1 Coin 2 Plays" }, + {0x11, 0x01, 0xf0, 0x60, "1 Coin 3 Plays" }, + {0x11, 0x01, 0xf0, 0x50, "1 Coin 4 Plays" }, + {0x11, 0x01, 0xf0, 0x40, "1 Coin 5 Plays" }, + {0x11, 0x01, 0xf0, 0x30, "1 Coin 6 Plays" }, + {0x11, 0x01, 0xf0, 0x00, "Freeplay" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x02, 0x00, "Upright" }, + {0x12, 0x01, 0x02, 0x02, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Coin Mode" }, + {0x12, 0x01, 0x04, 0x04, "Mode 1" }, + {0x12, 0x01, 0x04, 0x00, "Mode 2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Level Select" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Player Adding" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x80, 0x80, "Off" }, + {0x12, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Kikcubic) + +static struct BurnRomInfo DrvRomDesc[] = { + { "g07_c03.bin", 0x08000, 0x9dcca081, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "j07_c04.bin", 0x10000, 0xe0159105, BRF_ESS | BRF_PRG }, // 1 + + { "g05_c02.bin", 0x10000, 0x10582b2d, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "f05_c08.bin", 0x10000, 0x01579d20, BRF_GRA }, // 3 Characters + { "h05_c09.bin", 0x10000, 0x4f5872f0, BRF_GRA }, // 4 + + { "n07_c12.bin", 0x10000, 0x10af8eb2, BRF_GRA }, // 5 Sprites + { "k07_c10.bin", 0x10000, 0x9576f304, BRF_GRA }, // 6 + { "o07_c13.bin", 0x10000, 0xb1d9d4dc, BRF_GRA }, // 7 + { "l07_c11.bin", 0x10000, 0x4598be4a, BRF_GRA }, // 8 + { "t07_c16.bin", 0x10000, 0xf5425e42, BRF_GRA }, // 9 + { "p07_c14.bin", 0x10000, 0xcb50a17c, BRF_GRA }, // 10 + { "v07_c17.bin", 0x10000, 0x959ba3c7, BRF_GRA }, // 11 + { "s07_c15.bin", 0x10000, 0x7f2e91c5, BRF_GRA }, // 12 + + { "d01_c05.bin", 0x10000, 0x81b1ee5c, BRF_GRA }, // 13 Background + { "e01_c06.bin", 0x10000, 0xd0d33673, BRF_GRA }, // 14 + { "f01_c07.bin", 0x10000, 0xaae81695, BRF_GRA }, // 15 + + { "d04_c01.bin", 0x10000, 0x9b85101d, BRF_SND }, // 16 Samples + + { "pal16l8.8r", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 PALs + { "pal16l8.4m", 0x00104, 0x6c628a26, BRF_GRA }, // 18 + { "pal16l8.1b", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 19 +}; + +STD_ROM_PICK(Drv) +STD_ROM_FN(Drv) + +static struct BurnRomInfo Drv1RomDesc[] = { + { "vg_a-8h-c.rom", 0x08000, 0xd72682e8, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "vg_a-8l-a.rom", 0x10000, 0x690d812f, BRF_ESS | BRF_PRG }, // 1 + + { "g05_c02.bin", 0x10000, 0x10582b2d, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "f05_c08.bin", 0x10000, 0x01579d20, BRF_GRA }, // 3 Characters + { "h05_c09.bin", 0x10000, 0x4f5872f0, BRF_GRA }, // 4 + + { "n07_c12.bin", 0x10000, 0x10af8eb2, BRF_GRA }, // 5 Sprites + { "k07_c10.bin", 0x10000, 0x9576f304, BRF_GRA }, // 6 + { "o07_c13.bin", 0x10000, 0xb1d9d4dc, BRF_GRA }, // 7 + { "l07_c11.bin", 0x10000, 0x4598be4a, BRF_GRA }, // 8 + { "t07_c16.bin", 0x10000, 0xf5425e42, BRF_GRA }, // 9 + { "p07_c14.bin", 0x10000, 0xcb50a17c, BRF_GRA }, // 10 + { "v07_c17.bin", 0x10000, 0x959ba3c7, BRF_GRA }, // 11 + { "s07_c15.bin", 0x10000, 0x7f2e91c5, BRF_GRA }, // 12 + + { "d01_c05.bin", 0x10000, 0x81b1ee5c, BRF_GRA }, // 13 Background + { "e01_c06.bin", 0x10000, 0xd0d33673, BRF_GRA }, // 14 + { "f01_c07.bin", 0x10000, 0xaae81695, BRF_GRA }, // 15 + + { "d04_c01.bin", 0x10000, 0x9b85101d, BRF_SND }, // 16 Samples + + { "pal16l8.8r", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 PALs + { "pal16l8.4m", 0x00104, 0x6c628a26, BRF_GRA }, // 18 + { "pal16l8.1b", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 19 +}; + +STD_ROM_PICK(Drv1) +STD_ROM_FN(Drv1) + +static struct BurnRomInfo DrvuRomDesc[] = { + { "a-8h", 0x08000, 0x8d15109e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a-8l", 0x10000, 0x7f95799b, BRF_ESS | BRF_PRG }, // 1 + + { "g05_c02.bin", 0x10000, 0x10582b2d, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "f05_c08.bin", 0x10000, 0x01579d20, BRF_GRA }, // 3 Characters + { "h05_c09.bin", 0x10000, 0x4f5872f0, BRF_GRA }, // 4 + + { "n07_c12.bin", 0x10000, 0x10af8eb2, BRF_GRA }, // 5 Sprites + { "k07_c10.bin", 0x10000, 0x9576f304, BRF_GRA }, // 6 + { "o07_c13.bin", 0x10000, 0xb1d9d4dc, BRF_GRA }, // 7 + { "l07_c11.bin", 0x10000, 0x4598be4a, BRF_GRA }, // 8 + { "t07_c16.bin", 0x10000, 0xf5425e42, BRF_GRA }, // 9 + { "p07_c14.bin", 0x10000, 0xcb50a17c, BRF_GRA }, // 10 + { "v07_c17.bin", 0x10000, 0x959ba3c7, BRF_GRA }, // 11 + { "s07_c15.bin", 0x10000, 0x7f2e91c5, BRF_GRA }, // 12 + + { "d01_c05.bin", 0x10000, 0x81b1ee5c, BRF_GRA }, // 13 Background + { "e01_c06.bin", 0x10000, 0xd0d33673, BRF_GRA }, // 14 + { "f01_c07.bin", 0x10000, 0xaae81695, BRF_GRA }, // 15 + + { "d04_c01.bin", 0x10000, 0x9b85101d, BRF_SND }, // 16 Samples + + { "pal16l8.8r", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 PALs + { "pal16l8.4m", 0x00104, 0x6c628a26, BRF_GRA }, // 18 + { "pal16l8.1b", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 19 +}; + +STD_ROM_PICK(Drvu) +STD_ROM_FN(Drvu) + +static struct BurnRomInfo Drvu2RomDesc[] = { + { "vg-a-8h-g.bin", 0x08000, 0x9444c04e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a-8l", 0x10000, 0x7f95799b, BRF_ESS | BRF_PRG }, // 1 + + { "g05_c02.bin", 0x10000, 0x10582b2d, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "f05_c08.bin", 0x10000, 0x01579d20, BRF_GRA }, // 3 Characters + { "h05_c09.bin", 0x10000, 0x4f5872f0, BRF_GRA }, // 4 + + { "n07_c12.bin", 0x10000, 0x10af8eb2, BRF_GRA }, // 5 Sprites + { "k07_c10.bin", 0x10000, 0x9576f304, BRF_GRA }, // 6 + { "o07_c13.bin", 0x10000, 0xb1d9d4dc, BRF_GRA }, // 7 + { "l07_c11.bin", 0x10000, 0x4598be4a, BRF_GRA }, // 8 + { "t07_c16.bin", 0x10000, 0xf5425e42, BRF_GRA }, // 9 + { "p07_c14.bin", 0x10000, 0xcb50a17c, BRF_GRA }, // 10 + { "v07_c17.bin", 0x10000, 0x959ba3c7, BRF_GRA }, // 11 + { "s07_c15.bin", 0x10000, 0x7f2e91c5, BRF_GRA }, // 12 + + { "d01_c05.bin", 0x10000, 0x81b1ee5c, BRF_GRA }, // 13 Background + { "e01_c06.bin", 0x10000, 0xd0d33673, BRF_GRA }, // 14 + { "f01_c07.bin", 0x10000, 0xaae81695, BRF_GRA }, // 15 + + { "d04_c01.bin", 0x10000, 0x9b85101d, BRF_SND }, // 16 Samples + + { "pal16l8.8r", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 PALs + { "pal16l8.4m", 0x00104, 0x6c628a26, BRF_GRA }, // 18 + { "pal16l8.1b", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 19 +}; + +STD_ROM_PICK(Drvu2) +STD_ROM_FN(Drvu2) + +static struct BurnRomInfo DrvjRomDesc[] = { + { "vg_a-8h.rom", 0x08000, 0xba848713, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "vg_a-8l.rom", 0x10000, 0x3b12b1d8, BRF_ESS | BRF_PRG }, // 1 + + { "g05_c02.bin", 0x10000, 0x10582b2d, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "f05_c08.bin", 0x10000, 0x01579d20, BRF_GRA }, // 3 Characters + { "h05_c09.bin", 0x10000, 0x4f5872f0, BRF_GRA }, // 4 + + { "n07_c12.bin", 0x10000, 0x10af8eb2, BRF_GRA }, // 5 Sprites + { "k07_c10.bin", 0x10000, 0x9576f304, BRF_GRA }, // 6 + { "o07_c13.bin", 0x10000, 0xb1d9d4dc, BRF_GRA }, // 7 + { "l07_c11.bin", 0x10000, 0x4598be4a, BRF_GRA }, // 8 + { "t07_c16.bin", 0x10000, 0xf5425e42, BRF_GRA }, // 9 + { "p07_c14.bin", 0x10000, 0xcb50a17c, BRF_GRA }, // 10 + { "v07_c17.bin", 0x10000, 0x959ba3c7, BRF_GRA }, // 11 + { "s07_c15.bin", 0x10000, 0x7f2e91c5, BRF_GRA }, // 12 + + { "d01_c05.bin", 0x10000, 0x81b1ee5c, BRF_GRA }, // 13 Background + { "e01_c06.bin", 0x10000, 0xd0d33673, BRF_GRA }, // 14 + { "f01_c07.bin", 0x10000, 0xaae81695, BRF_GRA }, // 15 + + { "d04_c01.bin", 0x10000, 0x9b85101d, BRF_SND }, // 16 Samples + + { "pal16l8.8r", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 PALs + { "pal16l8.4m", 0x00104, 0x6c628a26, BRF_GRA }, // 18 + { "pal16l8.1b", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 19 +}; + +STD_ROM_PICK(Drvj) +STD_ROM_FN(Drvj) + +static struct BurnRomInfo BuccanrsRomDesc[] = { + { "11.u58", 0x10000, 0xbf1d7e6f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "12.u25", 0x10000, 0x87303ba8, BRF_ESS | BRF_PRG }, // 1 + + { "1.u128", 0x10000, 0xeb65f8c3, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "7.u212", 0x10000, 0x95e3c517, BRF_GRA }, // 3 Characters + { "8.u189", 0x10000, 0xfe2377ab, BRF_GRA }, // 4 + + { "3.u100", 0x20000, 0x16dc435f, BRF_GRA }, // 5 Sprites + { "4.u80", 0x10000, 0x4fe3bf97, BRF_GRA }, // 6 + { "6.u52", 0x20000, 0x078aef7f, BRF_GRA }, // 7 + { "5.u70", 0x10000, 0xf650fa90, BRF_GRA }, // 8 + + { "9.u49", 0x20000, 0x0c6188fb, BRF_GRA }, // 9 Background + { "10.u27", 0x20000, 0x2d383ff8, BRF_GRA }, // 10 + + { "2.u74", 0x10000, 0x36ee1dac, BRF_SND }, // 11 Samples + + { "prom1.u54", 0x00100, 0xc324835e, BRF_GRA }, // 12 PROMs + { "prom4.u79", 0x00100, 0xe6506ef4, BRF_GRA }, // 13 + { "prom3.u88", 0x00100, 0xb43d094f, BRF_GRA }, // 14 + { "prom2.u99", 0x00100, 0xe0aa8869, BRF_GRA }, // 15 + + { "pal16l8.u103", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 16 PALs + { "pal16l8.u156", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 17 + { "pal16l8.u42", 0x00104, 0x00000000, BRF_GRA | BRF_NODUMP }, // 18 +}; + +STD_ROM_PICK(Buccanrs) +STD_ROM_FN(Buccanrs) + +static struct BurnRomInfo BuccanrsaRomDesc[] = { + { "bc-011", 0x08000, 0x6b657ef1, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "12.u25", 0x10000, 0x87303ba8, BRF_ESS | BRF_PRG }, // 1 + + { "1.u128", 0x10000, 0xeb65f8c3, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "7.u212", 0x10000, 0x95e3c517, BRF_GRA }, // 3 Characters + { "8.u189", 0x10000, 0xfe2377ab, BRF_GRA }, // 4 + + { "3.u100", 0x20000, 0x16dc435f, BRF_GRA }, // 5 Sprites + { "4.u80", 0x10000, 0x4fe3bf97, BRF_GRA }, // 6 + { "6.u52", 0x20000, 0x078aef7f, BRF_GRA }, // 7 + { "5.u70", 0x10000, 0xf650fa90, BRF_GRA }, // 8 + + { "9.u49", 0x20000, 0x0c6188fb, BRF_GRA }, // 9 Background + { "10.u27", 0x20000, 0x2d383ff8, BRF_GRA }, // 10 + + { "2.u74", 0x10000, 0x36ee1dac, BRF_SND }, // 11 Samples + + { "prom1.u54", 0x00100, 0xc324835e, BRF_GRA }, // 12 PROMs + { "prom4.u79", 0x00100, 0xe6506ef4, BRF_GRA }, // 13 + { "prom3.u88", 0x00100, 0xb43d094f, BRF_GRA }, // 14 + { "prom2.u99", 0x00100, 0xe0aa8869, BRF_GRA }, // 15 +}; + +STD_ROM_PICK(Buccanrsa) +STD_ROM_FN(Buccanrsa) + +static struct BurnRomInfo KikcubicRomDesc[] = { + { "mqj-p0", 0x08000, 0x9cef394a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "mqj-b0", 0x10000, 0xd9bcf4cd, BRF_ESS | BRF_PRG }, // 1 + { "mqj-b1", 0x10000, 0x54a0abe1, BRF_ESS | BRF_PRG }, // 2 + + { "mqj-sp", 0x10000, 0xbbcf3582, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "mqj-c0", 0x10000, 0x975585c5, BRF_GRA }, // 4 Characters + { "mqj-c1", 0x10000, 0x49d9936d, BRF_GRA }, // 5 + + { "mqj-00", 0x40000, 0x7fb0c58f, BRF_GRA }, // 6 Sprites + { "mqj-10", 0x40000, 0x3a189205, BRF_GRA }, // 7 + + { "mqj-v0", 0x10000, 0x54762956, BRF_SND }, // 8 Samples + + { "8d", 0x00100, 0x7379bb12, BRF_GRA }, // 9 PROMs + { "6h", 0x00020, 0xface0cbb, BRF_GRA }, // 10 + { "7s", 0x00020, 0xface0cbb, BRF_GRA }, // 11 +}; + +STD_ROM_PICK(Kikcubic) +STD_ROM_FN(Kikcubic) + +static struct BurnRomInfo KikcubicbRomDesc[] = { + { "1.bin", 0x08000, 0xd3a589ba, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "4.bin", 0x10000, 0x9ae1e1a6, BRF_ESS | BRF_PRG }, // 1 + { "5.bin", 0x08000, 0xa5a6bffd, BRF_ESS | BRF_PRG }, // 2 + + { "mqj-sp", 0x10000, 0xbbcf3582, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "7.bin", 0x10000, 0x1788d51a, BRF_GRA }, // 4 Characters + { "mqj-c1", 0x10000, 0x49d9936d, BRF_GRA }, // 5 + + { "11.bin", 0x10000, 0x0f0cac92, BRF_GRA }, // 6 Sprites + { "10.bin", 0x10000, 0x7d3822a8, BRF_GRA }, // 7 + { "9.bin", 0x10000, 0x56fb4fa3, BRF_GRA }, // 8 + { "8.bin", 0x10000, 0x947dbd4e, BRF_GRA }, // 9 + + { "mqj-v0", 0x10000, 0x54762956, BRF_SND }, // 10 Samples + + { "8d", 0x00100, 0x7379bb12, BRF_GRA }, // 11 PROMs + { "6h", 0x00020, 0xface0cbb, BRF_GRA }, // 12 + { "7s", 0x00020, 0xface0cbb, BRF_GRA }, // 13 +}; + +STD_ROM_PICK(Kikcubicb) +STD_ROM_FN(Kikcubicb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x28000; + DrvZ80Rom2 = Next; Next += 0x10000; + DrvSamples = Next; Next += 0x10000; + + RamStart = Next; + + DrvZ80Ram1 = Next; Next += 0x02000; + DrvZ80Ram2 = Next; Next += 0x01000; + DrvSpriteRam = Next; Next += 0x00100; + DrvPaletteRam = Next; Next += 0x00800; + DrvVideoRam = Next; Next += 0x01000; + DrvPalette = (UINT32*)Next; Next += (512 + 32) * sizeof(UINT32); + + RamEnd = Next; + + DrvChars = Next; Next += 0x1000 * 8 * 8; + DrvSprites = Next; Next += 0x1000 * 16 * 16; + DrvBackTiles = Next; Next += 0x4000 * 32; + + DACBuffer = (INT16*)Next; Next += nBurnSoundLen * 2 * sizeof(INT16); + + MemEnd = Next; + + return 0; +} + +static void DrvSetVector(INT32 Status) +{ + switch (Status) { + case VECTOR_INIT: { + DrvIrqVector = 0xff; + break; + } + + case YM2151_ASSERT: { + DrvIrqVector &= 0xef; + break; + } + + case YM2151_CLEAR: { + DrvIrqVector |= 0x10; + break; + } + + case Z80_ASSERT: { + DrvIrqVector &= 0xdf; + break; + } + + case Z80_CLEAR: { + DrvIrqVector |= 0x20; + break; + } + } + + if (DrvIrqVector == 0xff) { +// ZetSetVector(DrvIrqVector); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } else { + ZetSetVector(DrvIrqVector); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + nCyclesDone[1] += ZetRun(1000); + } +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + if (i == 1) DrvSetVector(VECTOR_INIT); + ZetClose(); + } + + if (DrvHasYM2203) { + BurnYM2203Reset(); + } else { + BurnYM2151Reset(); + } + + DACReset(); + + DrvRomBank = 0; + DrvSoundLatch = 0; + DrvRearColour = 0; + DrvRearDisable = 0; + DrvHorizScrollLo = 0; + DrvHorizScrollHi = 0; + DrvRearHorizScrollLo = 0; + DrvRearHorizScrollHi = 0; + DrvSampleAddress = 0; + + return 0; +} + +UINT8 __fastcall VigilanteZ80Read1(UINT16 a) +{ + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall VigilanteZ80Write1(UINT16 a, UINT8 d) +{ + if (a >= 0xc020 && a <= 0xc0df) { + DrvSpriteRam[a - 0xc020] = d; + return; + } + + if (a >= 0xc800 && a <= 0xcfff) { + INT32 Offset = a & 0x7ff; + INT32 Bank = Offset & 0x400; + INT32 r, g, b; + + DrvPaletteRam[Offset] = d; + + Offset &= 0xff; + r = (DrvPaletteRam[Bank + Offset + 0x000] << 3) & 0xff; + g = (DrvPaletteRam[Bank + Offset + 0x100] << 3) & 0xff; + b = (DrvPaletteRam[Bank + Offset + 0x200] << 3) & 0xff; + + DrvPalette[(Bank >> 2) + Offset] = BurnHighCol(r, g, b, 0); + return; + } + + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall VigilanteZ80PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - DrvInput[0]; + } + + case 0x01: { + return 0xff - DrvInput[1]; + } + + case 0x02: { + return 0xff - DrvInput[2]; + } + + case 0x03: { + return DrvDip[0]; + } + + case 0x04: { + return DrvDip[1]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall BuccanrsZ80PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return (0xd0 - DrvInput[0]) | DrvDip[0]; + } + + case 0x01: { + return 0xff - DrvInput[1]; + } + + case 0x02: { + return 0xff - DrvInput[2]; + } + + case 0x03: { + return DrvDip[1]; + } + + case 0x04: { + return DrvDip[2]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall BuccanrsaZ80PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return (0x0b - DrvInput[0]) | DrvDip[0]; + } + + case 0x01: { + return 0xff - DrvInput[1]; + } + + case 0x02: { + return 0xff - DrvInput[2]; + } + + case 0x03: { + return DrvDip[1]; + } + + case 0x04: { + return DrvDip[2]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall VigilanteZ80PortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DrvSoundLatch = d; + ZetClose(); + ZetOpen(1); + DrvSetVector(Z80_ASSERT); + ZetClose(); + ZetOpen(0); + return; + } + + case 0x01: { + // output port? + return; + } + + case 0x04: { + DrvRomBank = d & 0x07; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + return; + } + + case 0x80: { + DrvHorizScrollLo = d; + return; + } + + case 0x81: { + DrvHorizScrollHi = (d & 0x01) << 8; + return; + } + + case 0x82: { + DrvRearHorizScrollLo = d; + return; + } + + case 0x83: { + DrvRearHorizScrollHi = (d & 0x07) << 8; + return; + } + + case 0x84: { + DrvRearColour = d & 0x0d; + DrvRearDisable = d & 0x40; + return; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KikcubicZ80Read1(UINT16 a) +{ + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall KikcubicZ80Write1(UINT16 a, UINT8 d) +{ + if (a >= 0xc800 && a <= 0xcaff) { + INT32 Offset = a & 0x3ff; + INT32 Bank = Offset & 0x400; + INT32 r, g, b; + + DrvPaletteRam[Offset] = d; + + Offset &= 0xff; + r = (DrvPaletteRam[Bank + Offset + 0x000] << 3) & 0xff; + g = (DrvPaletteRam[Bank + Offset + 0x100] << 3) & 0xff; + b = (DrvPaletteRam[Bank + Offset + 0x200] << 3) & 0xff; + + DrvPalette[(Bank >> 2) + Offset] = BurnHighCol(r, g, b, 0); + return; + } + + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall KikcubicZ80PortRead1(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return DrvDip[0]; + } + + case 0x01: { + return DrvDip[1]; + } + + case 0x02: { + return 0xff - DrvInput[1]; + } + + case 0x03: { + return 0xff - DrvInput[0]; + } + + case 0x04: { + return 0xff - DrvInput[2]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall KikcubicZ80PortWrite1(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + // coin write + return; + } + + case 0x04: { + DrvRomBank = d & 0x07; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + return; + } + + case 0x06: { + if (d == 0x20) return; // ??? + DrvSoundLatch = d; + ZetClose(); + ZetOpen(1); + DrvSetVector(Z80_ASSERT); + ZetClose(); + ZetOpen(0); + return; + } + + case 0x07: { + // nop??? + return; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #1 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall VigilanteZ80Read2(UINT16 a) +{ + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall VigilanteZ80Write2(UINT16 a, UINT8 /*d*/) +{ + switch (a) { + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall VigilanteZ80PortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x01: { + return BurnYM2151ReadStatus(); + } + + case 0x80: { + return DrvSoundLatch; + } + + case 0x84: { + return DrvSamples[DrvSampleAddress]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall VigilanteZ80PortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x01: { + BurnYM2151WriteRegister(d); + return; + } + + case 0x80: { + DrvSampleAddress = (DrvSampleAddress & 0xff00) | ((d << 0) & 0x00ff); + return; + } + + case 0x81: { + DrvSampleAddress = (DrvSampleAddress & 0x00ff) | ((d << 8) & 0xff00); + return; + } + + case 0x82: { + DACSignedWrite(0, d); + DrvSampleAddress = (DrvSampleAddress + 1) & 0xffff; + return; + } + + case 0x83: { + DrvSetVector(Z80_CLEAR); + return; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall BuccanrsZ80PortRead2(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return YM2203Read(0, 0); + } + + case 0x02: { + return YM2203Read(1, 0); + } + + case 0x80: { + return DrvSoundLatch; + } + + case 0x84: { + return DrvSamples[DrvSampleAddress]; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall BuccanrsZ80PortWrite2(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x01: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0x02: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0x03: { + BurnYM2203Write(1, 1, d); + return; + } + + case 0x80: { + DrvSampleAddress = (DrvSampleAddress & 0xff00) | ((d << 0) & 0x00ff); + return; + } + + case 0x81: { + DrvSampleAddress = (DrvSampleAddress & 0x00ff) | ((d << 8) & 0xff00); + return; + } + + case 0x82: { + DACSignedWrite(0, d); + DrvSampleAddress = (DrvSampleAddress + 1) & 0xffff; + return; + } + + case 0x83: { + DrvSetVector(Z80_CLEAR); + return; + } + + default: { +// bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +static void VigilantYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + DrvSetVector(YM2151_ASSERT); + } else { + DrvSetVector(YM2151_CLEAR); + } +} + +inline static void BuccanrsYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + DrvSetVector(YM2151_ASSERT); + } else { + DrvSetVector(YM2151_CLEAR); + } +} + +inline static INT32 BuccanrsSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (18432000 / 6); +} + +inline static double BuccanrsGetTime() +{ + return (double)ZetTotalCycles() / (18432000 / 6); +} + +static INT32 CharPlaneOffsets[4] = { 0x80000, 0x80004, 0, 4 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 64, 65, 66, 67 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 SpritePlaneOffsets[4] = { 0x200000, 0x200004, 0, 4 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 128, 129, 130, 131, 256, 257, 258, 259, 384, 385, 386, 387 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 BackTilePlaneOffsets[4] = { 0, 2, 4, 6 }; +static INT32 BackTileXOffsets[32] = { 1, 0, 9, 8, 17, 16, 25, 24, 33, 32, 41, 40, 49, 48, 57, 56, 65, 64, 73, 72, 81, 80, 89, 88, 97, 96, 105, 104, 113, 112, 121, 120 }; +static INT32 BackTileYOffsets[1] = { 0 }; +static INT32 BuccSpriteXOffsets[16] = { 3, 2, 1, 0, 131, 130, 129, 128, 259, 258, 257, 256, 387, 386, 385, 384 }; +static INT32 BuccBackTilePlaneOffsets[4] = { 6, 4, 2, 0 }; + +static INT32 DrvInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 4, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 12, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 15, 1); if (nRet != 0) return 1; + GfxDecode(0x4000, 4, 32, 1, BackTilePlaneOffsets, BackTileXOffsets, BackTileYOffsets, 0x80, DrvTempRom, DrvBackTiles); + + BurnFree(DrvTempRom); + + // Load sample Roms + nRet = BurnLoadRom(DrvSamples + 0x00000, 16, 1); if (nRet != 0) return 1; + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(VigilanteZ80Read1); + ZetSetWriteHandler(VigilanteZ80Write1); + ZetSetInHandler(VigilanteZ80PortRead1); + ZetSetOutHandler(VigilanteZ80PortWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xc800, 0xcfff, 0, DrvPaletteRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvPaletteRam ); + ZetMapArea(0xd000, 0xdfff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 2, DrvVideoRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(VigilanteZ80Read2); + ZetSetWriteHandler(VigilanteZ80Write2); + ZetSetInHandler(VigilanteZ80PortRead2); + ZetSetOutHandler(VigilanteZ80PortWrite2); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom2 ); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(55.0); + nCyclesTotal[0] = 3579645 / 55; + nCyclesTotal[1] = 3579645 / 55; + + GenericTilesInit(); + BurnYM2151Init(3579645, 25.0); + BurnYM2151SetIrqHandler(&VigilantYM2151IrqHandler); + DACInit(0, 0, 1); + DACSetVolShift(0, 1); + + DrvDoReset(); + + return 0; +} + +static INT32 BuccanrsInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 4, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x20000, DrvTempRom + 0x10000, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 7, 1); if (nRet != 0) return 1; + memcpy(DrvTempRom + 0x60000, DrvTempRom + 0x50000, 0x10000); + nRet = BurnLoadRom(DrvTempRom + 0x50000, 8, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, BuccSpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load and decode the bg tiles + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1; + GfxDecode(0x4000, 4, 32, 1, BuccBackTilePlaneOffsets, BackTileXOffsets, BackTileYOffsets, 0x80, DrvTempRom, DrvBackTiles); + + BurnFree(DrvTempRom); + + // Load sample Roms + nRet = BurnLoadRom(DrvSamples + 0x00000, 11, 1); if (nRet != 0) return 1; + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(VigilanteZ80Read1); + ZetSetWriteHandler(VigilanteZ80Write1); + ZetSetInHandler(BuccanrsZ80PortRead1); + ZetSetOutHandler(VigilanteZ80PortWrite1); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "buccanrsa")) ZetSetInHandler(BuccanrsaZ80PortRead1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xc800, 0xcfff, 0, DrvPaletteRam ); + ZetMapArea(0xc800, 0xcfff, 2, DrvPaletteRam ); + ZetMapArea(0xd000, 0xdfff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 2, DrvVideoRam ); + ZetMapArea(0xe000, 0xefff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xefff, 2, DrvZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(VigilanteZ80Read2); + ZetSetWriteHandler(VigilanteZ80Write2); + ZetSetInHandler(BuccanrsZ80PortRead2); + ZetSetOutHandler(BuccanrsZ80PortWrite2); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom2 ); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(55.0); + nCyclesTotal[0] = 5688800 / 55; + nCyclesTotal[1] = (18432000 / 6) / 55; + + GenericTilesInit(); + + DrvHasYM2203 = 1; + BurnYM2203Init(2, 18432000 / 6, &BuccanrsYM2203IRQHandler, BuccanrsSynchroniseStream, BuccanrsGetTime, 0); + BurnYM2203SetVolumeShift(2); + BurnTimerAttachZet(18432000 / 6); + DACInit(0, 0, 0); + DACSetVolShift(0, 1); + + DrvDoReset(); + + return 0; +} + +static INT32 KikcubicInit() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + DrvTempRom = (UINT8 *)BurnMalloc(0x80000); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "kikcubicb")) { + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x20000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x28000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 9, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load sample Roms + nRet = BurnLoadRom(DrvSamples + 0x00000, 10, 1); if (nRet != 0) return 1; + } else { + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x20000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load and decode the chars + nRet = BurnLoadRom(DrvTempRom + 0x00000, 4, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 5, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x80, DrvTempRom, DrvChars); + + // Load and decode the sprites + memset(DrvTempRom, 0, 0x80000); + nRet = BurnLoadRom(DrvTempRom + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 7, 1); if (nRet != 0) return 1; + GfxDecode(0x1000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, DrvTempRom, DrvSprites); + + // Load sample Roms + nRet = BurnLoadRom(DrvSamples + 0x00000, 8, 1); if (nRet != 0) return 1; + } + + BurnFree(DrvTempRom); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(KikcubicZ80Read1); + ZetSetWriteHandler(KikcubicZ80Write1); + ZetSetInHandler(KikcubicZ80PortRead1); + ZetSetOutHandler(KikcubicZ80PortWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xc000, 0xc0ff, 0, DrvSpriteRam ); + ZetMapArea(0xc000, 0xc0ff, 1, DrvSpriteRam ); + ZetMapArea(0xc000, 0xc0ff, 2, DrvSpriteRam ); + ZetMapArea(0xc800, 0xcaff, 0, DrvPaletteRam ); + ZetMapArea(0xc800, 0xcaff, 2, DrvPaletteRam ); + ZetMapArea(0xd000, 0xdfff, 0, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 1, DrvVideoRam ); + ZetMapArea(0xd000, 0xdfff, 2, DrvVideoRam ); + ZetMapArea(0xe000, 0xffff, 0, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xffff, 1, DrvZ80Ram1 ); + ZetMapArea(0xe000, 0xffff, 2, DrvZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(VigilanteZ80Read2); + ZetSetWriteHandler(VigilanteZ80Write2); + ZetSetInHandler(VigilanteZ80PortRead2); + ZetSetOutHandler(VigilanteZ80PortWrite2); + ZetMapArea(0x0000, 0xbfff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0xbfff, 2, DrvZ80Rom2 ); + ZetMapArea(0xf000, 0xffff, 0, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 1, DrvZ80Ram2 ); + ZetMapArea(0xf000, 0xffff, 2, DrvZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnSetRefreshRate(55.0); + nCyclesTotal[0] = 3579645 / 55; + nCyclesTotal[1] = 3579645 / 55; + + GenericTilesInit(); + BurnYM2151Init(3579645, 25.0); + BurnYM2151SetIrqHandler(&VigilantYM2151IrqHandler); + DACInit(0, 0, 1); + DACSetVolShift(0, 1); + + DrvKikcubicDraw = 1; + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + BurnYM2151Exit(); + BurnYM2203Exit(); + + GenericTilesExit(); + + BurnFree(Mem); + + DrvRomBank = 0; + DrvSoundLatch = 0; + DrvIrqVector = 0; + DrvRearColour = 0; + DrvRearDisable = 0; + DrvHorizScrollLo = 0; + DrvHorizScrollHi = 0; + DrvRearHorizScrollLo = 0; + DrvRearHorizScrollHi = 0; + DrvSampleAddress = 0; + + DrvHasYM2203 = 0; + DrvKikcubicDraw = 0; + + return 0; +} + +static void DrvRenderBackground() +{ + INT32 CharCode = 0; + INT32 Scroll = 0x17a - (DrvRearHorizScrollLo + DrvRearHorizScrollHi); + if (Scroll > 0) Scroll -= 2048; + + for (INT32 i = 0; i < 16; i++) { + INT32 r, g, b; + + r = (DrvPaletteRam[0x400 + 16 * DrvRearColour + i] << 3) & 0xff; + g = (DrvPaletteRam[0x500 + 16 * DrvRearColour + i] << 3) & 0xff; + b = (DrvPaletteRam[0x600 + 16 * DrvRearColour + i] << 3) & 0xff; + + DrvPalette[512 + i] = BurnHighCol(r, g, b, 0); + + r = (DrvPaletteRam[0x400 + 16 * DrvRearColour + 32 + i] << 3) & 0xff; + g = (DrvPaletteRam[0x500 + 16 * DrvRearColour + 32 + i] << 3) & 0xff; + b = (DrvPaletteRam[0x600 + 16 * DrvRearColour + 32 + i] << 3) & 0xff; + + DrvPalette[512 + 16 + i] = BurnHighCol(r, g, b, 0); + } + + for (INT32 Page = 0; Page < 4; Page++) { + for (INT32 Row = 0; Row < 256; Row++) { + for (INT32 Col = 0; Col < 512; Col += 32) { + INT32 Colour = (Row < 128) ? 0 : 1; + UINT32 nPalette = 512 | (Colour << 4); + + for (INT32 px = 0; px < 32; px++) { + UINT8 c = DrvBackTiles[(CharCode * 32) + px]; + INT32 xPos = (512 * Page) + Col + px + Scroll; + + if (Row >= 0 && Row < nScreenHeight) { + UINT16* pPixel = pTransDraw + (Row * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + + CharCode++; + } + } + } +} + +static void DrvDrawForeground(INT32 Priority, INT32 Opaque) +{ + INT32 Scroll = -(DrvHorizScrollLo + DrvHorizScrollHi); + + for (INT32 Offset = 0; Offset < 0x1000; Offset += 2) { + INT32 sy = 8 * ((Offset / 2) / 64); + INT32 sx = 8 * ((Offset / 2) % 64); + INT32 Attr = DrvVideoRam[Offset + 1]; + INT32 Colour = Attr & 0x0f; + INT32 Tile = DrvVideoRam[Offset + 0] | ((Attr & 0xf0) << 4); + + if (Priority) { + // Sprite masking + if ((Colour & 0x0c) == 0x0c) { + if (sy >= 48) { + sx = (sx + Scroll) & 0x1ff; + + sx -= 128; + + INT32 px, py; + UINT32 nPalette = 256 | (Colour << 4); + + for (py = 0; py < 8; py++) { + for (px = 0; px < 8; px++) { + UINT8 c = DrvChars[(Tile * 64) + (py * 8) + px]; + + if (((0xff >> c) & 0x01) == 0) { + INT32 xPos = sx + px; + INT32 yPos = sy + py; + + if (yPos >= 0 && yPos < nScreenHeight) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + } + } + } else { + if (sy >= 48) sx = (sx + Scroll) & 0x1ff; + + sx -= 128; + + if (sx >= 0 && sx < (nScreenWidth - 8) && sy >= 0 && sy < (nScreenHeight - 8)) { + if (Opaque || Colour >= 4) { + Render8x8Tile(pTransDraw, Tile, sx, sy, Colour, 4, 256, DrvChars); + } else { + Render8x8Tile_Mask(pTransDraw, Tile, sx, sy, Colour, 4, 0, 256, DrvChars); + } + } else { + if (Opaque || Colour >= 4) { + Render8x8Tile_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 256, DrvChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 0, 256, DrvChars); + } + } + } + } +} + +static void DrvDrawSprites() +{ + INT32 DrvSpriteRamSize = 0xc0; + if (DrvKikcubicDraw) DrvSpriteRamSize = 0x100; + + for (INT32 Offset = 0; Offset < DrvSpriteRamSize; Offset += 8) { + INT32 Code, Colour, sx, sy, xFlip, yFlip, h; + + Code = DrvSpriteRam[Offset + 4] | ((DrvSpriteRam[Offset + 5] & 0x0f) << 8); + Colour = DrvSpriteRam[Offset + 0] & 0x0f; + sx = (DrvSpriteRam[Offset + 6] | ((DrvSpriteRam[Offset + 7] & 0x01) << 8)); + sy = 256 + 128 - (DrvSpriteRam[Offset + 2] | ((DrvSpriteRam[Offset + 3] & 0x01) << 8)); + xFlip = DrvSpriteRam[Offset + 5] & 0x40; + yFlip = DrvSpriteRam[Offset + 5] & 0x80; + h = 1 << ((DrvSpriteRam[Offset + 5] & 0x30) >> 4); + sy -= 16 * h; + + Code &= ~(h - 1); + + if (DrvKikcubicDraw) { + sx -= 64; + } else { + sx -= 128; + } + + for (INT32 y = 0; y < h; y++) { + INT32 c = Code; + + if (yFlip) { + c += h - 1 - y; + } else { + c += y; + } + + if (sx > 16 && sx < (nScreenWidth - 16) && (sy + (16 * y)) > 16 && (sy + (16 * y)) < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, c, sx, sy + (16 * y), Colour, 4, 0, 0, DrvSprites); + } + } + } + } + } +} + +static void DrvDraw() +{ + BurnTransferClear(); + + if (DrvRearDisable) { + DrvDrawForeground(0, 1); + DrvDrawSprites(); + DrvDrawForeground(1, 0); + } else { + DrvRenderBackground(); + DrvDrawForeground(0, 0); + DrvDrawSprites(); + DrvDrawForeground(1, 0); + } + + BurnTransferCopy(DrvPalette); +} + +static void KikcubicDraw() +{ + BurnTransferClear(); + + for (INT32 Offset = 0; Offset < 0x1000; Offset += 2) { + INT32 sy = 8 * ((Offset / 2) / 64); + INT32 sx = 8 * ((Offset / 2) % 64); + INT32 Attr = DrvVideoRam[Offset + 1]; + INT32 Colour = (Attr & 0xf0) >> 4; + INT32 Code = DrvVideoRam[Offset] | ((Attr & 0x0f) << 8); + + sx -= 64; + if (sx >= 0 && sx < (nScreenWidth - 8) && sy >= 0 && sy < (nScreenHeight - 8)) { + Render8x8Tile(pTransDraw, Code, sx, sy, Colour, 4, 0, DrvChars); + } else { + Render8x8Tile_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, DrvChars); + } + } + + DrvDrawSprites(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = nBurnSoundLen; + INT32 nSoundBufferPos = 0; + + INT32 MSMIRQSlice[128]; + + for (INT32 i = 0; i < 128; i++) { + MSMIRQSlice[i] = (INT32)((double)((nInterleave * (i + 1)) / 129)); + } + + if (DrvReset) DrvDoReset(); + + DrvMakeInputs(); + + nCyclesDone[0] = nCyclesDone[1] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == (nInterleave - 1)) ZetRaiseIrq(0); + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + if (!DrvHasYM2203) { + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + } else { + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + } + for (INT32 j = 0; j < 128; j++) { + if (i == MSMIRQSlice[j]) { + ZetNmi(); + } + } + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + INT16* pSoundBuf2 = DACBuffer + (nSoundBufferPos << 1); + ZetOpen(1); + if (DrvHasYM2203) { + DACUpdate(pSoundBuf2, nSegmentLength); + } else { + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + if (DrvHasYM2203) { + ZetOpen(1); + BurnTimerEndFrame(nCyclesTotal[1]); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + INT16* pSoundBuf2 = DACBuffer + (nSoundBufferPos << 1); + ZetOpen(1); + if (DrvHasYM2203) { + DACUpdate(pSoundBuf2, nSegmentLength); + } else { + BurnYM2151Render(pSoundBuf, nSegmentLength); + DACUpdate(pSoundBuf, nSegmentLength); + } + ZetClose(); + } + } + + if (DrvHasYM2203 && pBurnSoundOut) { + ZetOpen(1); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + for (INT32 i = 0; i < nBurnSoundLen; i++) { + pBurnSoundOut[(i << 1) + 0] += DACBuffer[(i << 1) + 0]; + pBurnSoundOut[(i << 1) + 1] += DACBuffer[(i << 1) + 1]; + } + } + + if (pBurnDraw) { + if (DrvKikcubicDraw) { + KikcubicDraw(); + } else { + DrvDraw(); + } + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029705; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + if (DrvHasYM2203) { + BurnYM2203Scan(nAction, pnMin); + } else { + BurnYM2151Scan(nAction); + } + DACScan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(DrvDip); + SCAN_VAR(DrvInput); + SCAN_VAR(DrvIrqVector); + SCAN_VAR(DrvRearColour); + SCAN_VAR(DrvRearDisable); + SCAN_VAR(DrvHorizScrollLo); + SCAN_VAR(DrvHorizScrollHi); + SCAN_VAR(DrvRearHorizScrollLo); + SCAN_VAR(DrvRearHorizScrollHi); + SCAN_VAR(DrvSampleAddress); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetClose(); + } + + return 0; +} + +#undef VECTOR_INIT +#undef YM2151_ASSERT +#undef YM2151_CLEAR +#undef Z80_ASSERT +#undef Z80_CLEAR + +struct BurnDriver BurnDrvVigilant = { + "vigilant", NULL, NULL, NULL, "1988", + "Vigilante (World, set 1)\0", NULL, "Irem", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvRomInfo, DrvRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvVigilant1 = { + "vigilant1", "vigilant", NULL, NULL, "1988", + "Vigilante (World, set 2)\0", NULL, "Irem", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drv1RomInfo, Drv1RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvVigilantu = { + "vigilantu", "vigilant", NULL, NULL, "1988", + "Vigilante (US)\0", NULL, "Irem (Data East USA License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvVigilantu2 = { + "vigilantu2", "vigilant", NULL, NULL, "1988", + "Vigilante (US, rev G)\0", NULL, "Irem (Data East USA License)", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, Drvu2RomInfo, Drvu2RomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvVigilantj = { + "vigilantj", "vigilant", NULL, NULL, "1988", + "Vigilante (Japan)\0", NULL, "Irem", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKikcubic = { + "kikcubic", NULL, NULL, NULL, "1988", + "Meikyu Jima (Japan)\0", NULL, "Irem", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, KikcubicRomInfo, KikcubicRomName, NULL, NULL, KikcubicInputInfo, KikcubicDIPInfo, + KikcubicInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvKikcubicb = { + "kikcubicb", "kikcubic", NULL, NULL, "1988", + "Kickle Cubele\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0, + NULL, KikcubicbRomInfo, KikcubicbRomName, NULL, NULL, KikcubicInputInfo, KikcubicDIPInfo, + KikcubicInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 384, 256, 4, 3 +}; + +struct BurnDriver BurnDrvBuccanrs = { + "buccanrs", NULL, NULL, NULL, "1989", + "Buccaneers (set 1)\0", NULL, "Duintronic", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, BuccanrsRomInfo, BuccanrsRomName, NULL, NULL, BuccanrsInputInfo, BuccanrsDIPInfo, + BuccanrsInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; + +struct BurnDriver BurnDrvBuccanrsa = { + "buccanrsa", "buccanrs", NULL, NULL, "1989", + "Buccaneers (set 2)\0", NULL, "Duintronic", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0, + NULL, BuccanrsaRomInfo, BuccanrsaRomName, NULL, NULL, BuccanrsaInputInfo, BuccanrsaDIPInfo, + BuccanrsInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 544, 256, 256, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_vulgus.cpp b/src/burn/drivers/misc_pre90s/d_vulgus.cpp new file mode 100644 index 00000000..08b3de2d --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_vulgus.cpp @@ -0,0 +1,826 @@ +// FB Alpha Vulgus drive module +// Based on MAME driver by Mirko Buffoni + +// To do: flip screen + +#include "tiles_generic.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *Mem, *MemEnd, *Rom0, *Rom1, *Gfx0, *Gfx1, *Gfx2, *Prom; +static UINT8 DrvJoy1[8], DrvJoy2[8], DrvJoy3[8], DrvDips[2], DrvReset; +static INT16 *pAY8910Buffer[6], *pFMBuffer = NULL; +static UINT32 *DrvPalette, *Palette; +static UINT8 DrvRecalc; + +static INT32 vulgus_soundlatch; +static INT32 vulgus_scroll[2]; +static INT32 vulgus_palette_bank; +static INT32 vulgus_flipscreen; + +static struct BurnInputInfo DrvInputList[] = { + {"Coin 1" , BIT_DIGITAL , DrvJoy1 + 7, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , DrvJoy1 + 6, "p2 coin" }, + {"P1 Start" , BIT_DIGITAL , DrvJoy1 + 0, "p1 start" }, + {"P2 Start" , BIT_DIGITAL , DrvJoy1 + 1, "p2 start" }, + + {"P1 Right" , BIT_DIGITAL , DrvJoy2 + 0, "p1 right" }, + {"P1 Left" , BIT_DIGITAL , DrvJoy2 + 1, "p1 left" }, + {"P1 Down" , BIT_DIGITAL , DrvJoy2 + 2, "p1 down" }, + {"P1 Up" , BIT_DIGITAL , DrvJoy2 + 3, "p1 up" }, + {"P1 Button 1" , BIT_DIGITAL , DrvJoy2 + 4, "p1 fire 1"}, + {"P1 Button 2" , BIT_DIGITAL , DrvJoy2 + 5, "p1 fire 2"}, + + {"P2 Right" , BIT_DIGITAL , DrvJoy3 + 0, "p2 right" }, + {"P2 Left" , BIT_DIGITAL , DrvJoy3 + 1, "p2 left" }, + {"P2 Down" , BIT_DIGITAL , DrvJoy3 + 2, "p2 down" }, + {"P2 Up" , BIT_DIGITAL , DrvJoy3 + 3, "p2 up" }, + {"P2 Button 1" , BIT_DIGITAL , DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2" , BIT_DIGITAL , DrvJoy3 + 5, "p2 fire 2"}, + + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDips + 0, "dip 1" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDips + 1, "dip 2" }, +}; + +STDINPUTINFO(Drv) + +static struct BurnDIPInfo DrvDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x03, 0x01, "1" }, + {0x11, 0x01, 0x03, 0x02, "2" }, + {0x11, 0x01, 0x03, 0x03, "3" }, + {0x11, 0x01, 0x03, 0x00, "5" }, + + {0 , 0xfe, 0 , 7 , "Coin B" }, + {0x11, 0x01, 0x1c, 0x10, "5 Coins 1 Play" }, + {0x11, 0x01, 0x1c, 0x08, "4 Coins 1 Play" }, + {0x11, 0x01, 0x1c, 0x18, "3 Coins 1 Play" }, + {0x11, 0x01, 0x1c, 0x04, "2 Coins 1 Play" }, + {0x11, 0x01, 0x1c, 0x1c, "1 Coin 1 Play" }, + {0x11, 0x01, 0x1c, 0x0c, "1 Coin 2 Plays" }, + {0x11, 0x01, 0x1c, 0x14, "1 Coin 3 Plays" }, +// {0x11, 0x01, 0x1c, 0x00, "Invalid" }, + + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x11, 0x01, 0xe0, 0x80, "5 Coins 1 Play" }, + {0x11, 0x01, 0xe0, 0x40, "4 Coins 1 Play" }, + {0x11, 0x01, 0xe0, 0xc0, "3 Coins 1 Play" }, + {0x11, 0x01, 0xe0, 0x20, "2 Coins 1 Play" }, + {0x11, 0x01, 0xe0, 0xe0, "1 Coin 1 Play" }, + {0x11, 0x01, 0xe0, 0x60, "1 Coin 2 Plays" }, + {0x11, 0x01, 0xe0, 0xa0, "1 Coin 3 Plays" }, + {0x11, 0x01, 0xe0, 0x00, "Freeplay" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty?" }, + {0x12, 0x01, 0x03, 0x02, "Easy?" }, + {0x12, 0x01, 0x03, 0x03, "Normal?" }, + {0x12, 0x01, 0x03, 0x01, "Hard?" }, + {0x12, 0x01, 0x03, 0x00, "Hardest?" }, + + {0 , 0xfe, 0 , 2 , "Demo Music" }, + {0x12, 0x01, 0x04, 0x00, "Off" }, + {0x12, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x08, 0x00, "Off" }, + {0x12, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x12, 0x01, 0x70, 0x30, "10000 50000" }, + {0x12, 0x01, 0x70, 0x50, "10000 60000" }, + {0x12, 0x01, 0x70, 0x10, "10000 70000" }, + {0x12, 0x01, 0x70, 0x70, "20000 60000" }, + {0x12, 0x01, 0x70, 0x60, "20000 70000" }, + {0x12, 0x01, 0x70, 0x20, "20000 80000" }, + {0x12, 0x01, 0x70, 0x40, "30000 70000" }, + {0x12, 0x01, 0x70, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x80, 0x00, "Upright" }, + {0x12, 0x01, 0x80, 0x80, "Cocktail" }, +}; + +STDDIPINFO(Drv) + +void __fastcall vulgus_write_main(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xc800: + vulgus_soundlatch = data; + break; + + case 0xc802: + case 0xc803: + vulgus_scroll[address & 1] = (vulgus_scroll[address & 1] & 0xff00) | data; + break; + + case 0xc804: + vulgus_flipscreen = data >> 7; + break; + + case 0xc805: + vulgus_palette_bank = data & 3; + break; + + case 0xc902: + case 0xc903: + vulgus_scroll[address & 1] = (vulgus_scroll[address & 1] & 0x00ff) | (data << 8); + break; + } +} + +UINT8 __fastcall vulgus_read_main(UINT16 address) +{ + UINT8 ret; + + switch (address) + { + case 0xc000: + { + ret = 0xff; + + for (INT32 i = 0; i < 8; i++) ret ^= DrvJoy1[i] << i; + + return ret; + } + + case 0xc001: + { + ret = 0xff; + + for (INT32 i = 0; i < 5; i++) ret ^= DrvJoy2[i] << i; + + return ret; + } + + case 0xc002: + { + ret = 0xff; + + for (INT32 i = 0; i < 5; i++) ret ^= DrvJoy3[i] << i; + + return ret; + } + + case 0xc003: + return DrvDips[0]; + + case 0xc004: + return DrvDips[1]; + } + + return 0; +} + +void __fastcall vulgus_write_sound(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8000: + case 0x8001: + case 0xc000: + case 0xc001: + AY8910Write((address >> 14) & 1, address & 1, data); + break; + } +} + +UINT8 __fastcall vulgus_read_sound(UINT16 address) +{ + switch (address) + { + case 0x6000: + return vulgus_soundlatch; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + + vulgus_flipscreen = 0; + vulgus_soundlatch = 0; + vulgus_palette_bank = 0; + + vulgus_scroll[0] = 0; + vulgus_scroll[1] = 0; + + memset (Rom0 + 0xcc00, 0, 0x2400); + memset (Rom1 + 0x4000, 0, 0x0800); + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + + AY8910Reset(i); + } + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Rom0 = Next; Next += 0x10000; + Rom1 = Next; Next += 0x05000; + Gfx0 = Next; Next += 0x08000; + Gfx1 = Next; Next += 0x20000; + Gfx2 = Next; Next += 0x10000; + Prom = Next; Next += 0x00600; + + Palette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + pFMBuffer = (INT16*)Next; Next += (nBurnSoundLen * 6 * sizeof(INT16)); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvPaletteInit() +{ + UINT32 *tmp = (UINT32*)BurnMalloc(0x100 * sizeof(UINT32)); + if (tmp == NULL) { + return 1; + } + + for (INT32 i = 0; i < 256; i++) + { + INT32 bit0,bit1,bit2,bit3,r,g,b; + + bit0 = (Prom[ 0 + i] >> 0) & 0x01; + bit1 = (Prom[ 0 + i] >> 1) & 0x01; + bit2 = (Prom[ 0 + i] >> 2) & 0x01; + bit3 = (Prom[ 0 + i] >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (Prom[256 + i] >> 0) & 0x01; + bit1 = (Prom[256 + i] >> 1) & 0x01; + bit2 = (Prom[256 + i] >> 2) & 0x01; + bit3 = (Prom[256 + i] >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + bit0 = (Prom[512 + i] >> 0) & 0x01; + bit1 = (Prom[512 + i] >> 1) & 0x01; + bit2 = (Prom[512 + i] >> 2) & 0x01; + bit3 = (Prom[512 + i] >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + tmp[i] = (r << 16) | (g << 8) | b; + } + + for (INT32 i = 0; i < 0x100; i++) { + Palette[i] = tmp[32 + Prom[0x300 + i]]; + } + + for (INT32 i = 0; i < 0x100; i++) { + Palette[0x100 + i] = tmp[16 + Prom[0x400 + i]]; + } + + for (INT32 i = 0; i < 0x100; i++) { + Palette[0x400 + i] = tmp[Prom[0x500 + i] + 0x00]; + Palette[0x500 + i] = tmp[Prom[0x500 + i] + 0x40]; + Palette[0x600 + i] = tmp[Prom[0x500 + i] + 0x80]; + Palette[0x700 + i] = tmp[Prom[0x500 + i] + 0xc0]; + } + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + UINT8 *tmp = (UINT8*)BurnMalloc(0xc000); + if (tmp == NULL) { + return 1; + } + + static INT32 SpriPlanes[4] = { 0x20004, 0x20000, 0x00004, 0x00000 }; + static INT32 SpriXOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x008, 0x009, 0x00a, 0x00b, + 0x100, 0x101, 0x102, 0x103, 0x108, 0x109, 0x10a, 0x10b }; + static INT32 SpriYOffs[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, + 0x080, 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0 }; + + static INT32 TilePlanes[3] = { 0x00000, 0x20000, 0x40000 }; + static INT32 TileXOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, + 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087 }; + static INT32 TileYOffs[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + + memcpy (tmp, Gfx0, 0x2000); + + GfxDecode(0x200, 2, 8, 8, SpriPlanes + 2, SpriXOffs, SpriYOffs, 0x080, tmp, Gfx0); + + memcpy (tmp, Gfx1, 0xc000); + + GfxDecode(0x200, 3, 16, 16, TilePlanes + 0, TileXOffs, TileYOffs, 0x100, tmp, Gfx1); + + memcpy (tmp, Gfx2, 0x8000); + + GfxDecode(0x100, 4, 16, 16, SpriPlanes + 0, SpriXOffs, SpriYOffs, 0x200, tmp, Gfx2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = pFMBuffer + nBurnSoundLen * i; + } + + { + for (INT32 i = 0; i < 5; i++) { + if (BurnLoadRom(Rom0 + i * 0x2000, i + 0, 1)) return 1; + } + + if (BurnLoadRom(Rom1 + 0x0000, 5, 1)) return 1; + if (BurnLoadRom(Gfx0 + 0x0000, 6, 1)) return 1; + + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(Gfx1 + i * 0x2000, i + 7, 1)) return 1; + } + + for (INT32 i = 0; i < 4; i++) { + if (BurnLoadRom(Gfx2 + i * 0x2000, i + 13, 1)) return 1; + } + + for (INT32 i = 0; i < 6; i++) { + if (BurnLoadRom(Prom + i * 0x0100, i + 17, 1)) return 1; + } + + if (DrvPaletteInit()) return 1; + if (DrvGfxDecode()) return 1; + } + + ZetInit(2); + ZetOpen(0); + ZetMapArea(0x0000, 0x9fff, 0, Rom0 + 0x0000); + ZetMapArea(0x0000, 0x9fff, 2, Rom0 + 0x0000); + ZetMapArea(0xcc00, 0xccff, 0, Rom0 + 0xcc00); + ZetMapArea(0xcc00, 0xccff, 1, Rom0 + 0xcc00); + ZetMapArea(0xd000, 0xdfff, 0, Rom0 + 0xd000); + ZetMapArea(0xd000, 0xdfff, 1, Rom0 + 0xd000); + ZetMapArea(0xe000, 0xefff, 0, Rom0 + 0xe000); + ZetMapArea(0xe000, 0xefff, 1, Rom0 + 0xe000); + ZetMapArea(0xe000, 0xefff, 2, Rom0 + 0xe000); + ZetSetWriteHandler(vulgus_write_main); + ZetSetReadHandler(vulgus_read_main); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x1fff, 0, Rom1 + 0x0000); + ZetMapArea(0x0000, 0x1fff, 2, Rom1 + 0x0000); + ZetMapArea(0x4000, 0x47ff, 0, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x47ff, 1, Rom1 + 0x4000); + ZetMapArea(0x4000, 0x47ff, 2, Rom1 + 0x4000); + ZetSetWriteHandler(vulgus_write_sound); + ZetSetReadHandler(vulgus_read_sound); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + AY8910Init(1, 1500000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + AY8910Exit(0); + AY8910Exit(1); + GenericTilesExit(); + + BurnFree (Mem); + + Mem = MemEnd = Rom0 = Rom1 = NULL; + Gfx0 = Gfx1 = Gfx2 = Prom = NULL; + pFMBuffer = NULL; + + for (INT32 i = 0; i < 6; i++) { + pAY8910Buffer[i] = NULL; + } + + DrvPalette = Palette = NULL; + + DrvRecalc = 0; + + vulgus_soundlatch = 0; + vulgus_scroll[0] = vulgus_scroll[1] = 0; + vulgus_palette_bank = 0; + vulgus_flipscreen = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 0x800; i++) { + INT32 color = Palette[i]; + DrvPalette[i] = BurnHighCol(color >> 16, color >> 8, color, 0); + } + } + + for (INT32 offs = 0; offs < 0x400; offs++) + { + INT32 sx, sy, color, code, flipx, flipy; + + sx = (offs >> 1) & 0x1f0; + sy = (offs << 4) & 0x1f0; + + sx -= vulgus_scroll[1]; + sy -= vulgus_scroll[0]; + + if (sx < -15) sx += 0x200; // wrap + if (sy < -15) sy += 0x200; + + color = Rom0[0xdc00 + offs]; + code = Rom0[0xd800 + offs] | ((color & 0x80) << 1); + + flipx = color & 0x20; + flipy = color & 0x40; + + color = (color & 0x1f) | (vulgus_palette_bank << 5); + + sy -= 0x10; + + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 3, 0x400, Gfx1); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 3, 0x400, Gfx1); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 3, 0x400, Gfx1); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 3, 0x400, Gfx1); + } + } + } + + for (INT32 offs = 0x7c; offs >= 0; offs -= 4) + { + INT32 code, i, color, sx, sy; + + code = Rom0[0xcc00 + offs]; + color = Rom0[0xcc01 + offs] & 0x0f; + sx = Rom0[0xcc03 + offs]; + sy = Rom0[0xcc02 + offs]; + + sy -= 0x10; + + i = Rom0[0xcc01 + offs] >> 6; + if (i == 2) i = 3; + + for (; i >= 0; i--) { + INT32 ssy = sy + (i << 4); + Render16x16Tile_Mask_Clip(pTransDraw, code + i, sx, ssy, color, 4, 0x0f, 0x100, Gfx2); + if (ssy > 240) { // wrap + Render16x16Tile_Mask_Clip(pTransDraw, code + i, sx, ssy - 256, color, 4, 0x0f, 0x100, Gfx2); + } + } + } + + for (INT32 offs = 0x40; offs < 0x3c0; offs++) + { + INT32 sx, sy, color, code; + + color = Rom0[0xd400 + offs]; + code = Rom0[0xd000 + offs] | ((color & 0x80) << 1); + + if (code == 0x20) continue; + + UINT8 *src = Gfx0 + (code << 6); + + color = (color & 0x3f) << 2; + + sx = (offs << 3) & 0xf8; + sy = (offs >> 2) & 0xf8; + + sy -= 0x10; + + for (INT32 y = sy; y < sy + 8; y++) { + for (INT32 x = sx; x < sx + 8; x++, src++) { + INT32 pxl = color | *src; + if (Prom[0x300 | pxl] == 0x0f) continue; + pTransDraw[(y << 8) | x] = pxl; + } + } + } + + if (vulgus_flipscreen) { + INT32 nSize = (nScreenWidth * nScreenHeight) - 1; + for (INT32 i = 0; i < nSize >> 1; i++) { + INT32 n = pTransDraw[i]; + pTransDraw[i] = pTransDraw[nSize - i]; + pTransDraw[nSize - i] = n; + } + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + INT32 nInterleave = 8; + INT32 nSoundBufferPos = 0; + INT32 nCycles[2] = { 4000000 / 60, 3000000 / 60 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + ZetOpen(0); + nCycles[0] -= ZetRun(nCycles[0] / (nInterleave - i)); + if (i == ((nInterleave / 2) - 1)) { + ZetSetVector(0xd7); + ZetRaiseIrq(0); + } + if (i == ( nInterleave - 1)) { + ZetSetVector(0xcf); + ZetRaiseIrq(0); + } + ZetClose(); + + ZetOpen(1); + nCycles[1] -= ZetRun(nCycles[1] / (nInterleave - i)); + ZetRaiseIrq(0); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) | 0] = nSample; + pSoundBuf[(n << 1) | 1] = nSample; + } + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSample; + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + AY8910Update(0, &pAY8910Buffer[0], nSegmentLength); + AY8910Update(1, &pAY8910Buffer[3], nSegmentLength); + for (INT32 n = 0; n < nSegmentLength; n++) { + nSample = pAY8910Buffer[0][n] >> 2; + nSample += pAY8910Buffer[1][n] >> 2; + nSample += pAY8910Buffer[2][n] >> 2; + nSample += pAY8910Buffer[3][n] >> 2; + nSample += pAY8910Buffer[4][n] >> 2; + nSample += pAY8910Buffer[5][n] >> 2; + + nSample = BURN_SND_CLIP(nSample); + + pSoundBuf[(n << 1) | 0] = nSample; + pSoundBuf[(n << 1) | 1] = nSample; + } + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029521; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = Rom0 + 0xcc00; + ba.nLen = 0x2400; + ba.szName = "All CPU #0 Ram"; + BurnAcb(&ba); + + ba.Data = Rom1 + 0x4000; + ba.nLen = 0x0800; + ba.szName = "All CPU #1 Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + AY8910Scan(nAction, pnMin); + + SCAN_VAR(vulgus_flipscreen); + SCAN_VAR(vulgus_soundlatch); + SCAN_VAR(vulgus_palette_bank); + SCAN_VAR(vulgus_scroll[0]); + SCAN_VAR(vulgus_scroll[1]); + } + + return 0; +} + + +// Vulgus (set 1) + +static struct BurnRomInfo vulgusRomDesc[] = { + { "vulgus.002", 0x2000, 0xe49d6c5d, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "vulgus.003", 0x2000, 0x51acef76, 1 | BRF_PRG | BRF_ESS }, // 1 + { "vulgus.004", 0x2000, 0x489e7f60, 1 | BRF_PRG | BRF_ESS }, // 2 + { "vulgus.005", 0x2000, 0xde3a24a8, 1 | BRF_PRG | BRF_ESS }, // 3 + { "1-8n.bin", 0x2000, 0x6ca5ca41, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "1-11c.bin", 0x2000, 0x3bd2acf4, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 #1 Code + + { "1-3d.bin", 0x2000, 0x8bc5d7a5, 3 | BRF_GRA }, // 6 Foreground Tiles + + { "2-2a.bin", 0x2000, 0xe10aaca1, 4 | BRF_GRA }, // 7 Background Tiles + { "2-3a.bin", 0x2000, 0x8da520da, 4 | BRF_GRA }, // 8 + { "2-4a.bin", 0x2000, 0x206a13f1, 4 | BRF_GRA }, // 9 + { "2-5a.bin", 0x2000, 0xb6d81984, 4 | BRF_GRA }, // 10 + { "2-6a.bin", 0x2000, 0x5a26b38f, 4 | BRF_GRA }, // 11 + { "2-7a.bin", 0x2000, 0x1e1ca773, 4 | BRF_GRA }, // 12 + + { "2-2n.bin", 0x2000, 0x6db1b10d, 5 | BRF_GRA }, // 13 Sprites + { "2-3n.bin", 0x2000, 0x5d8c34ec, 5 | BRF_GRA }, // 14 + { "2-4n.bin", 0x2000, 0x0071a2e3, 5 | BRF_GRA }, // 15 + { "2-5n.bin", 0x2000, 0x4023a1ec, 5 | BRF_GRA }, // 16 + + { "e8.bin", 0x0100, 0x06a83606, 6 | BRF_GRA }, // 17 Color Proms + { "e9.bin", 0x0100, 0xbeacf13c, 6 | BRF_GRA }, // 18 + { "e10.bin", 0x0100, 0xde1fb621, 6 | BRF_GRA }, // 19 + { "d1.bin", 0x0100, 0x7179080d, 6 | BRF_GRA }, // 20 + { "j2.bin", 0x0100, 0xd0842029, 6 | BRF_GRA }, // 21 + { "c9.bin", 0x0100, 0x7a1f0bd6, 6 | BRF_GRA }, // 22 + + { "82s126.9k", 0x0100, 0x32b10521, 0 | BRF_OPT }, // 23 Misc. Proms + { "82s129.8n", 0x0100, 0x4921635c, 0 | BRF_OPT }, // 24 +}; + +STD_ROM_PICK(vulgus) +STD_ROM_FN(vulgus) + +struct BurnDriver BurnDrvvulgus = { + "vulgus", NULL, NULL, NULL, "1984", + "Vulgus (set 1)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vulgusRomInfo, vulgusRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 256, 3, 4 +}; + + +// Vulgus (set 2) + +static struct BurnRomInfo vulgusaRomDesc[] = { + { "v2", 0x2000, 0x3e18ff62, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "v3", 0x2000, 0xb4650d82, 1 | BRF_PRG | BRF_ESS }, // 1 + { "v4", 0x2000, 0x5b26355c, 1 | BRF_PRG | BRF_ESS }, // 2 + { "v5", 0x2000, 0x4ca7f10e, 1 | BRF_PRG | BRF_ESS }, // 3 + { "1-8n.bin", 0x2000, 0x6ca5ca41, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "1-11c.bin", 0x2000, 0x3bd2acf4, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 #1 Code + + { "1-3d.bin", 0x2000, 0x8bc5d7a5, 3 | BRF_GRA }, // 6 Foreground Tiles + + { "2-2a.bin", 0x2000, 0xe10aaca1, 4 | BRF_GRA }, // 7 Background Tiles + { "2-3a.bin", 0x2000, 0x8da520da, 4 | BRF_GRA }, // 8 + { "2-4a.bin", 0x2000, 0x206a13f1, 4 | BRF_GRA }, // 9 + { "2-5a.bin", 0x2000, 0xb6d81984, 4 | BRF_GRA }, // 10 + { "2-6a.bin", 0x2000, 0x5a26b38f, 4 | BRF_GRA }, // 11 + { "2-7a.bin", 0x2000, 0x1e1ca773, 4 | BRF_GRA }, // 12 + + { "2-2n.bin", 0x2000, 0x6db1b10d, 5 | BRF_GRA }, // 13 Sprites + { "2-3n.bin", 0x2000, 0x5d8c34ec, 5 | BRF_GRA }, // 14 + { "2-4n.bin", 0x2000, 0x0071a2e3, 5 | BRF_GRA }, // 15 + { "2-5n.bin", 0x2000, 0x4023a1ec, 5 | BRF_GRA }, // 16 + + { "e8.bin", 0x0100, 0x06a83606, 6 | BRF_GRA }, // 17 Color Proms + { "e9.bin", 0x0100, 0xbeacf13c, 6 | BRF_GRA }, // 18 + { "e10.bin", 0x0100, 0xde1fb621, 6 | BRF_GRA }, // 19 + { "d1.bin", 0x0100, 0x7179080d, 6 | BRF_GRA }, // 20 + { "j2.bin", 0x0100, 0xd0842029, 6 | BRF_GRA }, // 21 + { "c9.bin", 0x0100, 0x7a1f0bd6, 6 | BRF_GRA }, // 22 + + { "82s126.9k", 0x0100, 0x32b10521, 0 | BRF_OPT }, // 23 Misc. Proms + { "82s129.8n", 0x0100, 0x4921635c, 0 | BRF_OPT }, // 24 +}; + +STD_ROM_PICK(vulgusa) +STD_ROM_FN(vulgusa) + +struct BurnDriver BurnDrvvulgusa = { + "vulgusa", "vulgus", NULL, NULL, "1984", + "Vulgus (set 2)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vulgusaRomInfo, vulgusaRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 256, 3, 4 +}; + + +// Vulgus (Japan) + +static struct BurnRomInfo vulgusjRomDesc[] = { + { "1-4n.bin", 0x2000, 0xfe5a5ca5, 1 | BRF_PRG | BRF_ESS }, // 0 Z80 #0 Code + { "1-5n.bin", 0x2000, 0x847e437f, 1 | BRF_PRG | BRF_ESS }, // 1 + { "1-6n.bin", 0x2000, 0x4666c436, 1 | BRF_PRG | BRF_ESS }, // 2 + { "1-7n.bin", 0x2000, 0xff2097f9, 1 | BRF_PRG | BRF_ESS }, // 3 + { "1-8n.bin", 0x2000, 0x6ca5ca41, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "1-11c.bin", 0x2000, 0x3bd2acf4, 2 | BRF_PRG | BRF_ESS }, // 5 Z80 #1 Code + + { "1-3d.bin", 0x2000, 0x8bc5d7a5, 3 | BRF_GRA }, // 6 Foreground Tiles + + { "2-2a.bin", 0x2000, 0xe10aaca1, 4 | BRF_GRA }, // 7 Background Tiles + { "2-3a.bin", 0x2000, 0x8da520da, 4 | BRF_GRA }, // 8 + { "2-4a.bin", 0x2000, 0x206a13f1, 4 | BRF_GRA }, // 9 + { "2-5a.bin", 0x2000, 0xb6d81984, 4 | BRF_GRA }, // 10 + { "2-6a.bin", 0x2000, 0x5a26b38f, 4 | BRF_GRA }, // 11 + { "2-7a.bin", 0x2000, 0x1e1ca773, 4 | BRF_GRA }, // 12 + + { "2-2n.bin", 0x2000, 0x6db1b10d, 5 | BRF_GRA }, // 13 Sprites + { "2-3n.bin", 0x2000, 0x5d8c34ec, 5 | BRF_GRA }, // 14 + { "2-4n.bin", 0x2000, 0x0071a2e3, 5 | BRF_GRA }, // 15 + { "2-5n.bin", 0x2000, 0x4023a1ec, 5 | BRF_GRA }, // 16 + + { "e8.bin", 0x0100, 0x06a83606, 6 | BRF_GRA }, // 17 Color Proms + { "e9.bin", 0x0100, 0xbeacf13c, 6 | BRF_GRA }, // 18 + { "e10.bin", 0x0100, 0xde1fb621, 6 | BRF_GRA }, // 19 + { "d1.bin", 0x0100, 0x7179080d, 6 | BRF_GRA }, // 20 + { "j2.bin", 0x0100, 0xd0842029, 6 | BRF_GRA }, // 21 + { "c9.bin", 0x0100, 0x7a1f0bd6, 6 | BRF_GRA }, // 22 + + { "82s126.9k", 0x0100, 0x32b10521, 0 | BRF_OPT }, // 23 Misc. Proms + { "82s129.8n", 0x0100, 0x4921635c, 0 | BRF_OPT }, // 24 +}; + +STD_ROM_PICK(vulgusj) +STD_ROM_FN(vulgusj) + +struct BurnDriver BurnDrvvulgusj = { + "vulgusj", "vulgus", NULL, NULL, "1984", + "Vulgus (Japan?)\0", NULL, "Capcom", "Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0, + NULL, vulgusjRomInfo, vulgusjRomName, NULL, NULL, DrvInputInfo, DrvDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800, + 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/misc_pre90s/d_wallc.cpp b/src/burn/drivers/misc_pre90s/d_wallc.cpp new file mode 100644 index 00000000..6045eaaf --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_wallc.cpp @@ -0,0 +1,484 @@ +// FB Alpha Wall Crash driver module +// Based on MAME driver by Jarek Burczynski + +#include "tiles_generic.h" +#include "bitswap.h" +#include "driver.h" +extern "C" { +#include "ay8910.h" +} + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM; +static UINT8 *DrvColPROM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvVidRAM; +static UINT32 *Palette; +static UINT32 *DrvPalette; + +static INT16 *pAY8910Buffer[3]; + +static UINT8 DrvRecalc; + +static UINT8 DrvJoy1[8]; +static UINT8 DrvDips[2]; +static UINT16 DrvAxis[1]; +static UINT8 DrvInputs[2]; +static UINT8 DrvReset; +static UINT32 nAnalogAxis; + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo WallcInputList[] = { + {"Coin 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 coin" }, + {"Coin 2", BIT_DIGITAL, DrvJoy1 + 5, "p2 coin" }, + {"Coin 3", BIT_DIGITAL, DrvJoy1 + 6, "p3 coin" }, + {"Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 0, "p1 fire 2" }, + + A("P1 Right / left", BIT_ANALOG_REL, DrvAxis + 0, "p1 x-axis"), + + {"Service", BIT_DIGITAL, DrvJoy1 + 6, "service" }, + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Dip 1", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip 2", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Wallc) + +static struct BurnDIPInfo WallcDIPList[]= +{ + {0x09, 0xff, 0xff, 0x61, NULL }, + {0x0a, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x09, 0x01, 0x03, 0x03, "5" }, + {0x09, 0x01, 0x03, 0x02, "4" }, + {0x09, 0x01, 0x03, 0x01, "3" }, + {0x09, 0x01, 0x03, 0x00, "2" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x09, 0x01, 0x0c, 0x0c, "100K/200K/400K/800K" }, + {0x09, 0x01, 0x0c, 0x08, "80K/160K/320K/640K" }, + {0x09, 0x01, 0x0c, 0x04, "60K/120K/240K/480K" }, + {0x09, 0x01, 0x0c, 0x00, "Off" }, + + {0 , 0xfe, 0 , 2 , "Curve Effect" }, + {0x09, 0x01, 0x10, 0x10, "Normal" }, + {0x09, 0x01, 0x10, 0x00, "More" }, + + {0 , 0xfe, 0 , 4 , "Timer Speed" }, + {0x09, 0x01, 0x60, 0x60, "Slow" }, + {0x09, 0x01, 0x60, 0x40, "Normal" }, + {0x09, 0x01, 0x60, 0x20, "Fast" }, + {0x09, 0x01, 0x60, 0x00, "Super Fast" }, + + {0 , 0xfe, 0 , 2 , "Service" }, + {0x09, 0x01, 0x80, 0x80, "Free Play and Level Select" }, + {0x09, 0x01, 0x80, 0x00, "Normal" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0a, 0x01, 0x03, 0x03, "2C 1C" }, + {0x0a, 0x01, 0x03, 0x00, "1C 1C" }, + {0x0a, 0x01, 0x03, 0x01, "1C 2C" }, + {0x0a, 0x01, 0x03, 0x02, "1C 5C" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0a, 0x01, 0x0c, 0x0c, "2C 1C" }, + {0x0a, 0x01, 0x0c, 0x00, "1C 1C" }, + {0x0a, 0x01, 0x0c, 0x04, "1C 2C" }, + {0x0a, 0x01, 0x0c, 0x08, "1C 5C" }, + + {0 , 0xfe, 0 , 4 , "Coin C" }, + {0x0a, 0x01, 0x30, 0x30, "2C 1C" }, + {0x0a, 0x01, 0x30, 0x00, "1C 1C" }, + {0x0a, 0x01, 0x30, 0x10, "1C 2C" }, + {0x0a, 0x01, 0x30, 0x20, "1C 5C" }, +}; + +STDDIPINFO(Wallc) + +void __fastcall wallc_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xb500: + AY8910Write(0, 0, data); + break; + + case 0xb600: + AY8910Write(0, 1, data); + break; + } +} + +UINT8 __fastcall wallc_read(UINT16 address) +{ + switch (address) + { + case 0xb000: + return DrvDips[0]; + + case 0xb200: + return DrvInputs[0]; + + case 0xb400: + return DrvInputs[1]; + + case 0xb600: + return DrvDips[1]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + DrvReset = 0; + nAnalogAxis = 0; + + memset(AllRam, 0, RamEnd - AllRam); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + AY8910Reset(0); + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane[3] = { 0x04000, 0x0c000, 0x14000 }; + INT32 XOffs[8] = { 7, 6, 5, 4, 3, 2, 1, 0 }; + INT32 YOffs[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x3000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM, 0x3000); + + GfxDecode(0x0100, 3, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM); + + BurnFree (tmp); + + return 0; +} + +static void DrvPaletteInit() +{ + for (INT32 i = 8; i < 16; i++) + { + INT32 bit0,bit1,bit7,r,g,b; + + bit0 = (DrvColPROM[i] >> 5) & 0x01; + bit1 = (DrvColPROM[i] >> 6) & 0x01; + r = ((77 * bit1) + (115 * bit0)) + 1; + + bit0 = (DrvColPROM[i] >> 2) & 0x01; + bit1 = (DrvColPROM[i] >> 3) & 0x01; + g = ((77 * bit1) + (115 * bit0)) + 1; + + bit0 = (DrvColPROM[i] >> 0) & 0x01; + bit1 = (DrvColPROM[i] >> 1) & 0x01; + bit7 = (DrvColPROM[i] >> 7) & 0x01; + b = ((54 * bit7) + (84 * bit1) + (115 * bit0)); + + Palette[i-8] = (r << 16) | (g << 8) | b; + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + DrvZ80ROM = Next; Next += 0x008000; + + DrvGfxROM = Next; Next += 0x004000; + + DrvColPROM = Next; Next += 0x000020; + + Palette = (UINT32*)Next; Next += 0x0008 * sizeof(UINT32); + DrvPalette = (UINT32*)Next; Next += 0x0008 * sizeof(UINT32); + + AllRam = Next; + + DrvZ80RAM = Next; Next += 0x000400; + DrvVidRAM = Next; Next += 0x000400; + + pAY8910Buffer[0] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[1] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + pAY8910Buffer[2] = (INT16*)Next; Next += nBurnSoundLen * sizeof(INT16); + + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit(INT32 incr) +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (BurnLoadRom(DrvZ80ROM + 0x0000, 0, 1)) return 1; + if (BurnLoadRom(DrvZ80ROM + 0x2000, 1, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM + 0x0000 + incr, 2, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x1000 + incr, 3, 1)) return 1; + if (BurnLoadRom(DrvGfxROM + 0x2000 + incr, 4, 1)) return 1; + + if (BurnLoadRom(DrvColPROM, 5, 1)) return 1; + + DrvPaletteInit(); + DrvGfxDecode(); + } + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x83ff, 0, DrvVidRAM); + ZetMapArea(0x8000, 0x83ff, 1, DrvVidRAM); + ZetMapArea(0x8000, 0x83ff, 2, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 0, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 1, DrvVidRAM); + ZetMapArea(0x8400, 0x87ff, 2, DrvVidRAM); + ZetMapArea(0x8800, 0x8bff, 0, DrvVidRAM); + ZetMapArea(0x8800, 0x8bff, 1, DrvVidRAM); + ZetMapArea(0x8800, 0x8bff, 2, DrvVidRAM); + ZetMapArea(0x8c00, 0x8fff, 0, DrvVidRAM); + ZetMapArea(0x8c00, 0x8fff, 1, DrvVidRAM); + ZetMapArea(0x8c00, 0x8fff, 2, DrvVidRAM); + ZetMapArea(0xa000, 0xa3ff, 0, DrvZ80RAM); + ZetMapArea(0xa000, 0xa3ff, 1, DrvZ80RAM); + ZetMapArea(0xa000, 0xa3ff, 2, DrvZ80RAM); + ZetSetWriteHandler(wallc_write); + ZetSetReadHandler(wallc_read); + ZetMemEnd(); + ZetClose(); + + AY8910Init(0, 1536000, nBurnSoundRate, NULL, NULL, NULL, NULL); + + GenericTilesInit(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + ZetExit(); + AY8910Exit(0); + + BurnFree (AllMem); + + return 0; +} + +static INT32 DrvDraw() +{ + if (DrvRecalc) { + for (INT32 i = 0; i < 8; i++) { + INT32 d = Palette[i]; + DrvPalette[i] = BurnHighCol(d >> 16, (d >> 8) & 0xff, d & 0xff, 0); + } + } + + for (INT32 offs = 0; offs < 0x400; offs ++) + { + INT32 sy = (~offs & 0x1f) << 3; + INT32 sx = ( offs >> 5) << 3; + INT32 code = DrvVidRAM[offs]; + + Render8x8Tile(pTransDraw, code, sx, sy, 0, 0, 0, DrvGfxROM); + } + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + DrvInputs[0] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] ^= (DrvJoy1[i] & 1) << i; + } + + nAnalogAxis -= DrvAxis[0]; + DrvInputs[1] = nAnalogAxis >> 8; + } + + ZetOpen(0); +// ZetRun(3072000 / 60); +// ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetRun(3000000 / 60); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetRun(72000 / 60); + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSample; + AY8910Update(0, &pAY8910Buffer[0], nBurnSoundLen); + for (INT32 n = 0; n < nBurnSoundLen; n++) { + nSample = pAY8910Buffer[0][n]; + nSample += pAY8910Buffer[1][n]; + nSample += pAY8910Buffer[2][n]; + + nSample /= 4; + + nSample = BURN_SND_CLIP(nSample); + + pBurnSoundOut[(n << 1) + 0] = nSample; + pBurnSoundOut[(n << 1) + 1] = nSample; + } + } + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + + ZetScan(nAction); + + AY8910Scan(nAction, pnMin); + + SCAN_VAR(nAnalogAxis); + } + + return 0; +} + + +// Wall Crash (set 1) + +static struct BurnRomInfo wallcRomDesc[] = { + { "wac05.h7", 0x2000, 0xab6e472e, 0 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "wac1-52.h6", 0x2000, 0x988eaa6d, 0 | BRF_ESS | BRF_PRG }, // 1 + + { "wc1.e3", 0x1000, 0xca5c4b53, 1 | BRF_GRA }, // 2 Graphics + { "wc2.e2", 0x1000, 0xb7f52a59, 1 | BRF_GRA }, // 3 + { "wc3.e1", 0x1000, 0xf6854b3a, 1 | BRF_GRA }, // 4 + + { "74s288.c2", 0x0020, 0x83e3e293, 2 | BRF_GRA }, // 5 Color Prom +}; + +STD_ROM_PICK(wallc) +STD_ROM_FN(wallc) + +static void wallcDecode() +{ + for (INT32 i = 0; i < 0x4000; i++) { + DrvZ80ROM[i] = BITSWAP08(DrvZ80ROM[i] ^ 0xaa, 4,2,6,0,7,1,3,5); + } +} + +static INT32 wallcInit() +{ + INT32 nRet = DrvInit(0); + + if (nRet == 0) { + wallcDecode(); + } + + return nRet; +} + +struct BurnDriver BurnDrvWallc = { + "wallc", NULL, NULL, NULL, "1984", + "Wall Crash (set 1)\0", NULL, "Midcoin", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 1, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, wallcRomInfo, wallcRomName, NULL, NULL, WallcInputInfo, WallcDIPInfo, + wallcInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x08, + 256, 256, 4, 3 +}; + + +// Wall Crash (set 2) + +static struct BurnRomInfo wallcaRomDesc[] = { + { "rom4.rom", 0x2000, 0xce43af1b, 0 | BRF_ESS | BRF_PRG }, // 0 Z80 Code + { "rom5.rom", 0x2000, 0xb789a705, 0 | BRF_ESS | BRF_PRG }, // 1 + + { "rom3.rom", 0x0800, 0x6634db73, 1 | BRF_GRA }, // 2 Graphics + { "rom2.rom", 0x0800, 0x79f49c2c, 1 | BRF_GRA }, // 3 + { "rom1.rom", 0x0800, 0x3884fd4f, 1 | BRF_GRA }, // 4 + + { "74s288.c2", 0x0020, 0x83e3e293, 2 | BRF_GRA }, // 5 Color Prom +}; + +STD_ROM_PICK(wallca) +STD_ROM_FN(wallca) + +static void wallcaDecode() +{ + for (INT32 i = 0; i < 0x4000; i++) { + if (i & 0x100) { + DrvZ80ROM[i] = BITSWAP08(DrvZ80ROM[i] ^ 0x4a, 4,7,1,3,2,0,5,6); + } else { + DrvZ80ROM[i] = BITSWAP08(DrvZ80ROM[i] ^ 0xa5, 0,2,3,6,1,5,7,4); + } + } +} + +static INT32 wallcaInit() +{ + INT32 nRet = DrvInit(0x800); + + if (nRet == 0) { + wallcaDecode(); + } + + return nRet; +} + +struct BurnDriver BurnDrvWallca = { + "wallca", "wallc", NULL, NULL, "1984", + "Wall Crash (set 2)\0", NULL, "Midcoin", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_MISC_PRE90S, GBF_BREAKOUT, 0, + NULL, wallcaRomInfo, wallcaRomName, NULL, NULL, WallcInputInfo, WallcDIPInfo, + wallcaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x08, + 256, 256, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_wc90.cpp b/src/burn/drivers/misc_pre90s/d_wc90.cpp new file mode 100644 index 00000000..12564612 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_wc90.cpp @@ -0,0 +1,1306 @@ +// FB Alpha - World Cup '90 driver + +#include "tiles_generic.h" +#include "burn_ym2608.h" + +static UINT8 Wc90InputPort0[6] = {0, 0, 0, 0, 0, 0}; +static UINT8 Wc90InputPort1[6] = {0, 0, 0, 0, 0, 0}; +static UINT8 Wc90InputPort2[6] = {0, 0, 0, 0, 0, 0}; +static UINT8 Wc90Dip[2] = {0, 0}; +static UINT8 Wc90Input[3] = {0x00, 0x00, 0x00}; +static UINT8 Wc90Reset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Wc90Z80Rom1 = NULL; +static UINT8 *Wc90Z80Rom2 = NULL; +static UINT8 *Wc90Z80Rom3 = NULL; +static UINT8 *Wc90Z80Ram1 = NULL; +static UINT8 *Wc90Z80Ram2 = NULL; +static UINT8 *Wc90Z80Ram3 = NULL; +static UINT8 *Wc90FgVideoRam = NULL; +static UINT8 *Wc90BgVideoRam = NULL; +static UINT8 *Wc90TextVideoRam = NULL; +static UINT8 *Wc90SpriteRam = NULL; +static UINT8 *Wc90PaletteRam = NULL; +static UINT8 *Wc90SharedRam = NULL; +static UINT32 *Wc90Palette = NULL; +static UINT8 *Wc90CharTiles = NULL; +static UINT8 *Wc90BgTiles = NULL; +static UINT8 *Wc90FgTiles = NULL; +static UINT8 *Wc90Sprites = NULL; +static UINT8 *Wc90TempGfx = NULL; +static UINT8 *Wc90YM2608Rom = NULL; + +static INT32 Wc90Scroll0YLo; +static INT32 Wc90Scroll0YHi; +static INT32 Wc90Scroll0XLo; +static INT32 Wc90Scroll0XHi; +static INT32 Wc90Scroll1YLo; +static INT32 Wc90Scroll1YHi; +static INT32 Wc90Scroll1XLo; +static INT32 Wc90Scroll1XHi; +static INT32 Wc90Scroll2YLo; +static INT32 Wc90Scroll2YHi; +static INT32 Wc90Scroll2XLo; +static INT32 Wc90Scroll2XHi; + +static INT32 Wc90SoundLatch = 0; + +static INT32 nCyclesDone[3], nCyclesTotal[3]; +static INT32 nCyclesSegment; + +static INT32 nTileType; + +static struct BurnInputInfo Wc90InputList[] = { + {"Coin 1" , BIT_DIGITAL , Wc90InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Wc90InputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Wc90InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Wc90InputPort2 + 3, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Wc90InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Wc90InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Wc90InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Wc90InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Wc90InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Wc90InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Wc90InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Wc90InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Wc90InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Wc90InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Wc90InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Wc90InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Wc90Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, Wc90Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, Wc90Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Wc90) + +inline static void Wc90ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline static void Wc90MakeInputs() +{ + Wc90Input[0] = Wc90Input[1] = 0x00; + Wc90Input[2] = 0x03; + + for (INT32 i = 0; i < 6; i++) { + Wc90Input[0] |= (Wc90InputPort0[i] & 1) << i; + Wc90Input[1] |= (Wc90InputPort1[i] & 1) << i; + } + + if (Wc90InputPort2[0]) Wc90Input[2] -= 0x01; + if (Wc90InputPort2[1]) Wc90Input[2] -= 0x02; + if (Wc90InputPort2[2]) Wc90Input[2] |= 0x04; + if (Wc90InputPort2[3]) Wc90Input[2] |= 0x08; + + Wc90ClearOpposites(&Wc90Input[0]); + Wc90ClearOpposites(&Wc90Input[1]); +} + +static struct BurnDIPInfo Wc90DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x11, 0x01, 0x0f, 0x00, "10 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x08, " 9 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x04, " 8 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0c, " 7 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x02, " 6 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0a, " 5 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x06, " 4 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0e, " 3 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x01, " 2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x09, " 2 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0f, " 1 Coin 1 Credit" }, + {0x11, 0x01, 0x0f, 0x07, " 1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, " 1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x03, " 1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, " 1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x05, " 1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x30, 0x30, "Easy" }, + {0x11, 0x01, 0x30, 0x10, "Normal" }, + {0x11, 0x01, 0x30, 0x20, "Hard" }, + {0x11, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Countdown Speed" }, + {0x11, 0x01, 0x40, 0x40, "Normal" }, + {0x11, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "1 Player Game Time" }, + {0x12, 0x01, 0x03, 0x01, "1:00" }, + {0x12, 0x01, 0x03, 0x02, "1:30" }, + {0x12, 0x01, 0x03, 0x03, "2:00" }, + {0x12, 0x01, 0x03, 0x00, "2:30" }, + + {0 , 0xfe, 0 , 8 , "2 Players Game Time" }, + {0x12, 0x01, 0x1c, 0x0c, "1:00" }, + {0x12, 0x01, 0x1c, 0x14, "1:30" }, + {0x12, 0x01, 0x1c, 0x04, "2:00" }, + {0x12, 0x01, 0x1c, 0x18, "2:30" }, + {0x12, 0x01, 0x1c, 0x1c, "3:00" }, + {0x12, 0x01, 0x1c, 0x08, "3:30" }, + {0x12, 0x01, 0x1c, 0x10, "4:00" }, + {0x12, 0x01, 0x1c, 0x00, "5:00" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x80, 0x00, "English" }, + {0x12, 0x01, 0x80, 0x80, "Japanese" }, +}; + +STDDIPINFO(Wc90) + +static struct BurnRomInfo Wc90RomDesc[] = { + { "ic87_01.bin", 0x08000, 0x4a1affbc, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic95_02.bin", 0x10000, 0x847d439c, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "ic67_04.bin", 0x10000, 0xdc6eaf00, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "ic56_03.bin", 0x10000, 0x1ac02b3b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "ic54_05.bin", 0x10000, 0x27c348b3, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "ic85_07v.bin", 0x10000, 0xc5219426, BRF_GRA }, // 5 Characters + { "ic86_08v.bin", 0x20000, 0x8fa1a1ff, BRF_GRA }, // 6 Fg Tiles + { "ic90_09v.bin", 0x20000, 0x99f8841c, BRF_GRA }, // 7 Fg Tiles + { "ic87_10v.bin", 0x20000, 0x8232093d, BRF_GRA }, // 8 Bg Tiles + { "ic91_11v.bin", 0x20000, 0x188d3789, BRF_GRA }, // 9 Bg Tiles + { "ic50_12v.bin", 0x20000, 0xda1fe922, BRF_GRA }, // 10 Sprites + { "ic54_13v.bin", 0x20000, 0x9ad03c2c, BRF_GRA }, // 11 Sprites + { "ic60_14v.bin", 0x20000, 0x499dfb1b, BRF_GRA }, // 12 Sprites + { "ic65_15v.bin", 0x20000, 0xd8ea5c81, BRF_GRA }, // 13 Sprites + + { "ic82_06.bin", 0x20000, 0x2fd692ed, BRF_SND }, // 14 ADPCM Samples +}; + +STD_ROM_PICK(Wc90) +STD_ROM_FN(Wc90) + +static struct BurnRomInfo Wc90aRomDesc[] = { + { "wc90-1.bin", 0x08000, 0xd1804e1a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic95_02.bin", 0x10000, 0x847d439c, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "ic67_04.bin", 0x10000, 0xdc6eaf00, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "ic56_03.bin", 0x10000, 0x1ac02b3b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "ic54_05.bin", 0x10000, 0x27c348b3, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "ic85_07v.bin", 0x10000, 0xc5219426, BRF_GRA }, // 5 Characters + { "ic86_08v.bin", 0x20000, 0x8fa1a1ff, BRF_GRA }, // 6 Fg Tiles + { "ic90_09v.bin", 0x20000, 0x99f8841c, BRF_GRA }, // 7 Fg Tiles + { "ic87_10v.bin", 0x20000, 0x8232093d, BRF_GRA }, // 8 Bg Tiles + { "ic91_11v.bin", 0x20000, 0x188d3789, BRF_GRA }, // 9 Bg Tiles + { "ic50_12v.bin", 0x20000, 0xda1fe922, BRF_GRA }, // 10 Sprites + { "ic54_13v.bin", 0x20000, 0x9ad03c2c, BRF_GRA }, // 11 Sprites + { "ic60_14v.bin", 0x20000, 0x499dfb1b, BRF_GRA }, // 12 Sprites + { "ic65_15v.bin", 0x20000, 0xd8ea5c81, BRF_GRA }, // 13 Sprites + + { "ic82_06.bin", 0x20000, 0x2fd692ed, BRF_SND }, // 14 ADPCM Samples +}; + +STD_ROM_PICK(Wc90a) +STD_ROM_FN(Wc90a) + +static struct BurnRomInfo Wc90bRomDesc[] = { + { "ic87-1b.bin", 0x08000, 0xd024a971, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic95_02.bin", 0x10000, 0x847d439c, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "ic67_04.bin", 0x10000, 0xdc6eaf00, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "ic56_03.bin", 0x10000, 0x1ac02b3b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "ic54_05.bin", 0x10000, 0x27c348b3, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "ic85_07v.bin", 0x10000, 0xc5219426, BRF_GRA }, // 5 Characters + { "ic86_08v.bin", 0x20000, 0x8fa1a1ff, BRF_GRA }, // 6 Fg Tiles + { "ic90_09v.bin", 0x20000, 0x99f8841c, BRF_GRA }, // 7 Fg Tiles + { "ic87_10v.bin", 0x20000, 0x8232093d, BRF_GRA }, // 8 Bg Tiles + { "ic91_11v.bin", 0x20000, 0x188d3789, BRF_GRA }, // 9 Bg Tiles + { "ic50_12v.bin", 0x20000, 0xda1fe922, BRF_GRA }, // 10 Sprites + { "ic54_13v.bin", 0x20000, 0x9ad03c2c, BRF_GRA }, // 11 Sprites + { "ic60_14v.bin", 0x20000, 0x499dfb1b, BRF_GRA }, // 12 Sprites + { "ic65_15v.bin", 0x20000, 0xd8ea5c81, BRF_GRA }, // 13 Sprites + + { "ic82_06.bin", 0x20000, 0x2fd692ed, BRF_SND }, // 14 ADPCM Samples +}; + +STD_ROM_PICK(Wc90b) +STD_ROM_FN(Wc90b) + +static struct BurnRomInfo Wc90tRomDesc[] = { + { "wc90a-1.bin", 0x08000, 0xb6f51a68, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "wc90a-2.bin", 0x10000, 0xc50f2a98, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "ic67_04.bin", 0x10000, 0xdc6eaf00, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "wc90a-3.bin", 0x10000, 0x8c7a9542, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "ic54_05.bin", 0x10000, 0x27c348b3, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "ic85_07v.bin", 0x10000, 0xc5219426, BRF_GRA }, // 5 Characters + { "ic86_08v.bin", 0x20000, 0x8fa1a1ff, BRF_GRA }, // 6 Fg Tiles + { "ic90_09v.bin", 0x20000, 0x99f8841c, BRF_GRA }, // 7 Fg Tiles + { "ic87_10v.bin", 0x20000, 0x8232093d, BRF_GRA }, // 8 Bg Tiles + { "ic91_11v.bin", 0x20000, 0x188d3789, BRF_GRA }, // 9 Bg Tiles + { "ic50_12v.bin", 0x20000, 0xda1fe922, BRF_GRA }, // 10 Sprites + { "ic54_13v.bin", 0x20000, 0x9ad03c2c, BRF_GRA }, // 11 Sprites + { "ic60_14v.bin", 0x20000, 0x499dfb1b, BRF_GRA }, // 12 Sprites + { "ic65_15v.bin", 0x20000, 0xd8ea5c81, BRF_GRA }, // 13 Sprites + + { "ic82_06.bin", 0x20000, 0x2fd692ed, BRF_SND }, // 14 ADPCM Samples +}; + +STD_ROM_PICK(Wc90t) +STD_ROM_FN(Wc90t) + +static INT32 Wc90DoReset() +{ + Wc90Scroll0XLo = Wc90Scroll0XHi = Wc90Scroll0YLo = Wc90Scroll0YHi = 0; + Wc90Scroll1XLo = Wc90Scroll1XHi = Wc90Scroll1YLo = Wc90Scroll1YHi = 0; + Wc90Scroll2XLo = Wc90Scroll2XHi = Wc90Scroll2YLo = Wc90Scroll2YHi = 0; + + Wc90SoundLatch = 0; + + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnYM2608Reset(); + + HiscoreReset(); + + return 0; +} + +static void wc90FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static inline void wc90SendSoundCommand(INT32 nCommand) +{ + INT32 nCycles = ZetTotalCycles() * 2 / 3; + + Wc90SoundLatch = nCommand; + + ZetClose(); + ZetOpen(2); + + if (nCycles > ZetTotalCycles()) { + BurnTimerUpdate(nCycles); + } + + ZetNmi(); + + ZetClose(); + ZetOpen(0); +} + +static INT32 wc90SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double wc90GetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +UINT8 __fastcall Wc90Read1(UINT16 a) +{ + switch (a) { + case 0xfc00: { + return 0xff - Wc90Input[0]; + } + + case 0xfc02: { + return 0xff - Wc90Input[1]; + } + + case 0xfc05: { + return 0xff - Wc90Input[2]; + } + + case 0xfc06: { + return Wc90Dip[0]; + } + + case 0xfc07: { + return Wc90Dip[1]; + } + } + + return 0; +} + +void __fastcall Wc90Write1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfc02: { + Wc90Scroll0YLo = d; + return; + } + + case 0xfc03: { + Wc90Scroll0YHi = d; + return; + } + + case 0xfc06: { + Wc90Scroll0XLo = d; + return; + } + + case 0xfc07: { + Wc90Scroll0XHi = d; + return; + } + + case 0xfc22: { + Wc90Scroll1YLo = d; + return; + } + + case 0xfc23: { + Wc90Scroll1YHi = d; + return; + } + + case 0xfc26: { + Wc90Scroll1XLo = d; + return; + } + + case 0xfc27: { + Wc90Scroll1XHi = d; + return; + } + + case 0xfc42: { + Wc90Scroll2YLo = d; + return; + } + + case 0xfc43: { + Wc90Scroll2YHi = d; + return; + } + + case 0xfc46: { + Wc90Scroll2XLo = d; + return; + } + + case 0xfc47: { + Wc90Scroll2XHi = d; + return; + } + + case 0xfcc0: { + wc90SendSoundCommand(d); + return; + } + + case 0xfce0: { + INT32 BankAddress; + + BankAddress = 0x10000 + ((d & 0xf8) << 8); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90Z80Rom1 + BankAddress); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90Z80Rom1 + BankAddress); + return; + } + } +} + +void __fastcall Wc90Write2(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfc00: { + INT32 BankAddress; + + BankAddress = 0x10000 + ((d & 0xf8) << 8); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90Z80Rom2 + BankAddress); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90Z80Rom2 + BankAddress); + return; + } + } +} + +UINT8 __fastcall Wc90Read3(UINT16 a) +{ + switch (a) { + case 0xf800: { + return BurnYM2608Read(0); + } + + case 0xf802: { + return BurnYM2608Read(2); + } + + case 0xfc10: { + return Wc90SoundLatch; + } + } + + return 0; +} + +void __fastcall Wc90Write3(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xf800: { + BurnYM2608Write(0, d); + return; + } + + case 0xf801: { + BurnYM2608Write(1, d); + return; + } + + case 0xf802: { + BurnYM2608Write(2, d); + return; + } + + case 0xf803: { + BurnYM2608Write(3, d); + return; + } + } +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Wc90Z80Rom1 = Next; Next += 0x20000; + Wc90Z80Rom2 = Next; Next += 0x20000; + Wc90Z80Rom3 = Next; Next += 0x10000; + Wc90YM2608Rom = Next; Next += 0x20000; + + RamStart = Next; + + Wc90Z80Ram1 = Next; Next += 0x04000; + Wc90Z80Ram2 = Next; Next += 0x01800; + Wc90Z80Ram3 = Next; Next += 0x00800; + Wc90FgVideoRam = Next; Next += 0x01000; + Wc90BgVideoRam = Next; Next += 0x01000; + Wc90TextVideoRam = Next; Next += 0x01000; + Wc90SpriteRam = Next; Next += 0x00800; + Wc90PaletteRam = Next; Next += 0x00800; + Wc90SharedRam = Next; Next += 0x00400; + + RamEnd = Next; + + Wc90CharTiles = Next; Next += (2048 * 8 * 8); + Wc90BgTiles = Next; Next += (2048 * 16 * 16); + Wc90FgTiles = Next; Next += (2048 * 16 * 16); + Wc90Sprites = Next; Next += (4096 * 16 * 16); + Wc90Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static void Wc90RenderBgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90BgVideoRam[TileIndex]; + Code = Wc90BgVideoRam[TileIndex + 0x800] + 256 * ((Attr & 3) + ((Attr >> 1) & 4)); + Colour = Attr >> 4; + + x = 16 * mx; + y = 16 * my; + + x -= Wc90Scroll2XLo + 256 * Wc90Scroll2XHi; + y -= Wc90Scroll2YLo + 256 * Wc90Scroll2YHi; + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 768, Wc90BgTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 768, Wc90BgTiles); + } + + TileIndex++; + } + } +} + +static void Wc90tRenderBgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90BgVideoRam[TileIndex]; + Code = Wc90BgVideoRam[TileIndex + 0x800] + 256 * (Attr & 7); + Colour = Attr >> 4; + + x = 16 * mx; + y = 16 * my; + + x -= Wc90Scroll2XLo + 256 * Wc90Scroll2XHi; + y -= Wc90Scroll2YLo + 256 * Wc90Scroll2YHi; + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 768, Wc90BgTiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 768, Wc90BgTiles); + } + + TileIndex++; + } + } +} + +static void Wc90RenderFgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90FgVideoRam[TileIndex]; + Code = Wc90FgVideoRam[TileIndex + 0x800] + 256 * ((Attr & 3) + ((Attr >> 1) & 4)); + Colour = Attr >> 4; + + x = 16 * mx; + y = 16 * my; + + x -= Wc90Scroll1XLo + 256 * Wc90Scroll1XHi; + y -= Wc90Scroll1YLo + 256 * Wc90Scroll1YHi; + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512, Wc90FgTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512, Wc90FgTiles); + } + + TileIndex++; + } + } +} + +static void Wc90tRenderFgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90FgVideoRam[TileIndex]; + Code = Wc90FgVideoRam[TileIndex + 0x800] + 256 * (Attr & 7); + Colour = Attr >> 4; + + x = 16 * mx; + y = 16 * my; + + x -= Wc90Scroll1XLo + 256 * Wc90Scroll1XHi; + y -= Wc90Scroll1YLo + 256 * Wc90Scroll1YHi; + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 512, Wc90FgTiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 512, Wc90FgTiles); + } + + TileIndex++; + } + } +} + +static void Wc90RenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = Wc90TextVideoRam[TileIndex + 0x800] + ((Wc90TextVideoRam[TileIndex] & 0x07) << 8); + Colour = Wc90TextVideoRam[TileIndex] >> 4; + + x = 8 * mx; + y = 8 * my; + + x -= Wc90Scroll0XLo + 256 * Wc90Scroll0XHi; + y -= Wc90Scroll0YLo + 256 * Wc90Scroll0YHi; + + x &= 0x1ff; + y &= 0x0ff; + + y -= 16; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 256, Wc90CharTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 256, Wc90CharTiles); + } + + TileIndex++; + } + } +} + +static void Wc90RenderSprite(INT32 Code, INT32 Colour, INT32 FlipX, INT32 FlipY, INT32 x, INT32 y) +{ + if (x > 15 && x < 240 && y > 15 && y < 208) { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } else { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } + } + } else { + if (!FlipY) { + if (!FlipX) { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } + } else { + if (!FlipX) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } else { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, Wc90Sprites); + } + } + } +} + +static const char p32x32[4][4] = { + { 0, 1, 2, 3 }, + { 1, 0, 3, 2 }, + { 2, 3, 0, 1 }, + { 3, 2, 1, 0 } +}; + +static const char p32x64[4][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 5, 4, 7, 6, 1, 0, 3, 2 }, + { 2, 3, 0, 1, 6, 7, 4, 5 }, + { 7, 6, 5, 4, 3, 2, 1, 0 } +}; + +static const char p64x32[4][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 1, 0, 3, 2, 5, 4, 7, 6 }, + { 6, 7, 4, 5, 2, 3, 0, 1 }, + { 7, 6, 5, 4, 3, 2, 1, 0 } +}; + +static const char p64x64[4][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10 }, + { 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5 }, + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } +}; + +static void drawsprite_16x16(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + Wc90RenderSprite(Code, Attr >> 4, Bank & 1, Bank & 2, x, y); +} + +static void drawsprite_16x32(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + if (Bank & 2) { + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + } else { + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + } +} + +static void drawsprite_16x64(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + if (Bank & 2) { + Wc90RenderSprite(Code + 3, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 48); + Wc90RenderSprite(Code + 2, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 32); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + } else { + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + 2, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 32); + Wc90RenderSprite(Code + 3, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 48); + } +} + +static void drawsprite_32x16(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + if (Bank & 1) { + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + } else { + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + } +} + +static void drawsprite_32x32(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + const char *p = p32x32[Bank & 3]; + + Wc90RenderSprite(Code + p[0], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + p[1], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + p[2], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + p[3], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 16); +} + +static void drawsprite_32x64(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + const char *p = p32x64[Bank & 3]; + + Wc90RenderSprite(Code + p[0], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + p[1], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + p[2], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + p[3], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 16); + Wc90RenderSprite(Code + p[4], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 32); + Wc90RenderSprite(Code + p[5], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 32); + Wc90RenderSprite(Code + p[6], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 48); + Wc90RenderSprite(Code + p[7], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 48); +} + +static void drawsprite_64x16(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + if (Bank & 1) { + Wc90RenderSprite(Code + 3, Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 0); + Wc90RenderSprite(Code + 2, Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 0); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + } else { + Wc90RenderSprite(Code + 0, Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + 1, Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + 2, Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 0); + Wc90RenderSprite(Code + 3, Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 0); + } +} + +static void drawsprite_64x32(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + const char *p = p64x32[Bank & 3]; + + Wc90RenderSprite(Code + p[0], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + p[1], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + p[2], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + p[3], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 16); + Wc90RenderSprite(Code + p[4], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 0); + Wc90RenderSprite(Code + p[5], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 0); + Wc90RenderSprite(Code + p[6], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 16); + Wc90RenderSprite(Code + p[7], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 16); +} + +static void drawsprite_64x64(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) +{ + const char *p = p64x64[Bank & 3]; + + Wc90RenderSprite(Code + p[ 0], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 0); + Wc90RenderSprite(Code + p[ 1], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 0); + Wc90RenderSprite(Code + p[ 2], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 16); + Wc90RenderSprite(Code + p[ 3], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 16); + Wc90RenderSprite(Code + p[ 4], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 0); + Wc90RenderSprite(Code + p[ 5], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 0); + Wc90RenderSprite(Code + p[ 6], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 16); + Wc90RenderSprite(Code + p[ 7], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 16); + Wc90RenderSprite(Code + p[ 8], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 32); + Wc90RenderSprite(Code + p[ 9], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 32); + Wc90RenderSprite(Code + p[10], Attr >> 4, Bank & 1, Bank & 2, x + 0, y + 48); + Wc90RenderSprite(Code + p[11], Attr >> 4, Bank & 1, Bank & 2, x + 16, y + 48); + Wc90RenderSprite(Code + p[12], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 32); + Wc90RenderSprite(Code + p[13], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 32); + Wc90RenderSprite(Code + p[14], Attr >> 4, Bank & 1, Bank & 2, x + 32, y + 48); + Wc90RenderSprite(Code + p[15], Attr >> 4, Bank & 1, Bank & 2, x + 48, y + 48); +} + +static void drawsprite_invalid(INT32 Code, INT32 x, INT32 y, INT32 Bank, INT32 Attr) { +#ifdef FBA_DEBUG + bprintf(PRINT_NORMAL, _T("8 Pixel Size not Supported! %X, %d, %d, %X, %X\n"), Code, x, y, Bank, Attr); +#else + (void)Code; (void)x; (void)y; (void)Bank; (void)Attr; +#endif +} + +typedef void (*drawsprites_procdef)(int, int, int, int, int); + +static drawsprites_procdef drawsprites_proc[16] = { + drawsprite_invalid, /* 0000 = 08x08 */ + drawsprite_invalid, /* 0001 = 16x08 */ + drawsprite_invalid, /* 0010 = 32x08 */ + drawsprite_invalid, /* 0011 = 64x08 */ + drawsprite_invalid, /* 0100 = 08x16 */ + drawsprite_16x16, /* 0101 = 16x16 */ + drawsprite_32x16, /* 0110 = 32x16 */ + drawsprite_64x16, /* 0111 = 64x16 */ + drawsprite_invalid, /* 1000 = 08x32 */ + drawsprite_16x32, /* 1001 = 16x32 */ + drawsprite_32x32, /* 1010 = 32x32 */ + drawsprite_64x32, /* 1011 = 64x32 */ + drawsprite_invalid, /* 1100 = 08x64 */ + drawsprite_16x64, /* 1101 = 16x64 */ + drawsprite_32x64, /* 1110 = 32x64 */ + drawsprite_64x64 /* 1111 = 64x64 */ +}; + +static void Wc90RenderSprites(INT32 Priority) +{ + INT32 Code, Attr, x, y; + + for (INT32 Offs = 0; Offs < 0x800; Offs += 16) { + INT32 Bank = Wc90SpriteRam[Offs + 0]; + + if ((Bank >> 4) == Priority) { + if (Bank & 4) { + Code = (Wc90SpriteRam[Offs + 2] >> 2) + (Wc90SpriteRam[Offs + 3] << 6); + + x = Wc90SpriteRam[Offs + 8] + ((Wc90SpriteRam[Offs + 9] & 3) << 8); + y = Wc90SpriteRam[Offs + 6] + ((Wc90SpriteRam[Offs + 7] & 1) << 8); + + if (x >= 0x300) x -= 0x400; + + y -= 16; + + Attr = Wc90SpriteRam[Offs + 4]; + (*(drawsprites_proc[Attr & 0x0f]))(Code, x, y, Bank, Attr); + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 4) & 0x0f; + g = (nColour >> 0) & 0x0f; + b = (nColour >> 8) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +static INT32 Wc90CalcPalette() +{ + INT32 i; + + for (i = 0; i < 0x800; i++) { + Wc90Palette[i / 2] = CalcCol(Wc90PaletteRam[i | 1] | (Wc90PaletteRam[i & ~1] << 8)); + } + + return 0; +} + +static void Wc90Draw() +{ + Wc90CalcPalette(); + Wc90RenderBgLayer(); + Wc90RenderSprites(2); + Wc90RenderFgLayer(); + Wc90RenderSprites(1); + Wc90RenderCharLayer(); + Wc90RenderSprites(0); + BurnTransferCopy(Wc90Palette); +} + +static void Wc90tDraw() +{ + Wc90CalcPalette(); + Wc90tRenderBgLayer(); + Wc90RenderSprites(2); + Wc90tRenderFgLayer(); + Wc90RenderSprites(1); + Wc90RenderCharLayer(); + Wc90RenderSprites(0); + BurnTransferCopy(Wc90Palette); +} + +typedef void (*drawscreen_procdef)(void); + +static drawscreen_procdef drawscreen_proc[2] = { + Wc90Draw, + Wc90tDraw, +}; + +static INT32 Wc90Frame() +{ + INT32 nInterleave = 16; + INT32 nCurrentCPU; + + if (Wc90Reset) Wc90DoReset(); + + Wc90MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 59.17)); + nCyclesTotal[1] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 59.17)); + nCyclesTotal[2] = (INT32)(double)(4000000 / 59.17); + + ZetNewFrame(); + + // Compensate for extra cycles executed + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetIdle(nCyclesDone[i]); + ZetClose(); + } + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - ZetTotalCycles(); + ZetRun(nCyclesSegment); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - ZetTotalCycles(); + ZetRun(nCyclesSegment); + ZetClose(); + } + + for (INT32 i = 0; i < 2; i++) { + ZetOpen(i); + ZetRaiseIrq(0); + nCyclesDone[i] = ZetTotalCycles() - nCyclesTotal[i]; + ZetClose(); + } + + ZetOpen(2); + BurnTimerEndFrame(nCyclesTotal[2]); + BurnYM2608Update(pBurnSoundOut, nBurnSoundLen); + nCyclesDone[2] = ZetTotalCycles() - nCyclesTotal[2]; + ZetClose(); + + if (pBurnDraw) (*(drawscreen_proc[nTileType]))(); + + return 0; +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 TilePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TileXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 256, 260, 264, 268, 272, 276, 280, 284 }; +static INT32 TileYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 SpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 SpriteXOffsets[16] = { 0, 4, 0x200000, 0x200004, 8, 12, 0x200008, 0x20000c, 128, 132, 0x200080, 0x200084, 136, 140, 0x200088, 0x20008c }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 256, 272, 288, 304, 320, 336, 352, 368 }; + +static INT32 Wc90Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + Wc90TempGfx = (UINT8*)BurnMalloc(0x80000); + if (Wc90TempGfx == NULL) return 1; + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(Wc90Z80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90Z80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(Wc90Z80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90Z80Rom2 + 0x10000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Rom + nRet = BurnLoadRom(Wc90Z80Rom3 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and Decode Char Tile Rom + memset(Wc90TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90TempGfx + 0x00000, 5, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, Wc90TempGfx, Wc90CharTiles); + + // Load and Decode Fg Tile Roms + memset(Wc90TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90TempGfx + 0x00000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90TempGfx + 0x20000, 7, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, Wc90TempGfx, Wc90FgTiles); + + // Load and Decode Bg Tile Roms + memset(Wc90TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90TempGfx + 0x00000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90TempGfx + 0x20000, 9, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x400, Wc90TempGfx, Wc90BgTiles); + + // Load and Decode Sprite Roms + memset(Wc90TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90TempGfx + 0x00000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90TempGfx + 0x20000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90TempGfx + 0x40000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90TempGfx + 0x60000, 13, 1); if (nRet != 0) return 1; + GfxDecode(4096, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x200, Wc90TempGfx, Wc90Sprites); + + BurnFree(Wc90TempGfx); + + // Load ADPCM Rom + nRet = BurnLoadRom(Wc90YM2608Rom, 14, 1); if (nRet !=0) return 1; + + // Setup the Z80 emulation + ZetInit(3); + ZetOpen(0); + ZetSetReadHandler(Wc90Read1); + ZetSetWriteHandler(Wc90Write1); + ZetMapArea(0x0000, 0x7fff, 0, Wc90Z80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, Wc90Z80Rom1 ); + ZetMapArea(0x8000, 0x9fff, 0, Wc90Z80Ram1 + 0x00000); + ZetMapArea(0x8000, 0x9fff, 1, Wc90Z80Ram1 + 0x00000); + ZetMapArea(0x8000, 0x9fff, 2, Wc90Z80Ram1 + 0x00000); + ZetMapArea(0xa000, 0xafff, 0, Wc90FgVideoRam ); + ZetMapArea(0xa000, 0xafff, 1, Wc90FgVideoRam ); + ZetMapArea(0xa000, 0xafff, 2, Wc90FgVideoRam ); + ZetMapArea(0xb000, 0xbfff, 0, Wc90Z80Ram1 + 0x02000); + ZetMapArea(0xb000, 0xbfff, 1, Wc90Z80Ram1 + 0x02000); + ZetMapArea(0xb000, 0xbfff, 2, Wc90Z80Ram1 + 0x02000); + ZetMapArea(0xc000, 0xcfff, 0, Wc90BgVideoRam ); + ZetMapArea(0xc000, 0xcfff, 1, Wc90BgVideoRam ); + ZetMapArea(0xc000, 0xcfff, 2, Wc90BgVideoRam ); + ZetMapArea(0xd000, 0xdfff, 0, Wc90Z80Ram1 + 0x03000); + ZetMapArea(0xd000, 0xdfff, 1, Wc90Z80Ram1 + 0x03000); + ZetMapArea(0xd000, 0xdfff, 2, Wc90Z80Ram1 + 0x03000); + ZetMapArea(0xe000, 0xefff, 0, Wc90TextVideoRam ); + ZetMapArea(0xe000, 0xefff, 1, Wc90TextVideoRam ); + ZetMapArea(0xe000, 0xefff, 2, Wc90TextVideoRam ); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90Z80Rom1 + 0x10000); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90Z80Rom1 + 0x10000); + ZetMapArea(0xf800, 0xfbff, 0, Wc90SharedRam ); + ZetMapArea(0xf800, 0xfbff, 1, Wc90SharedRam ); + ZetMapArea(0xf800, 0xfbff, 2, Wc90SharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetWriteHandler(Wc90Write2); + ZetMapArea(0x0000, 0xbfff, 0, Wc90Z80Rom2 ); + ZetMapArea(0x0000, 0xbfff, 2, Wc90Z80Rom2 ); + ZetMapArea(0xc000, 0xcfff, 0, Wc90Z80Ram2 + 0x00000); + ZetMapArea(0xc000, 0xcfff, 1, Wc90Z80Ram2 + 0x00000); + ZetMapArea(0xc000, 0xcfff, 2, Wc90Z80Ram2 + 0x00000); + ZetMapArea(0xd000, 0xd7ff, 0, Wc90SpriteRam ); + ZetMapArea(0xd000, 0xd7ff, 1, Wc90SpriteRam ); + ZetMapArea(0xd000, 0xd7ff, 2, Wc90SpriteRam ); + ZetMapArea(0xd800, 0xdfff, 0, Wc90Z80Ram2 + 0x01000); + ZetMapArea(0xd800, 0xdfff, 1, Wc90Z80Ram2 + 0x01000); + ZetMapArea(0xd800, 0xdfff, 2, Wc90Z80Ram2 + 0x01000); + ZetMapArea(0xe000, 0xe7ff, 0, Wc90PaletteRam ); + ZetMapArea(0xe000, 0xe7ff, 1, Wc90PaletteRam ); + ZetMapArea(0xe000, 0xe7ff, 2, Wc90PaletteRam ); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90Z80Rom2 + 0x10000); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90Z80Rom2 + 0x10000); + ZetMapArea(0xf800, 0xfbff, 0, Wc90SharedRam ); + ZetMapArea(0xf800, 0xfbff, 1, Wc90SharedRam ); + ZetMapArea(0xf800, 0xfbff, 2, Wc90SharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(Wc90Read3); + ZetSetWriteHandler(Wc90Write3); + ZetMapArea(0x0000, 0xbfff, 0, Wc90Z80Rom3 ); + ZetMapArea(0x0000, 0xbfff, 2, Wc90Z80Rom3 ); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90Z80Ram3 ); + ZetMapArea(0xf000, 0xf7ff, 1, Wc90Z80Ram3 ); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90Z80Ram3 ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "wc90t")) { + nTileType = 1; + } else { + nTileType = 0; + } + + BurnSetRefreshRate(59.17); + + INT32 Wc90YM2608RomSize = 0x20000; + BurnYM2608Init(8000000, Wc90YM2608Rom, &Wc90YM2608RomSize, &wc90FMIRQHandler, wc90SynchroniseStream, wc90GetTime, 0); + BurnTimerAttachZet(4000000); + + // Reset the driver + Wc90DoReset(); + + return 0; +} + +static INT32 Wc90Exit() +{ + ZetExit(); + GenericTilesExit(); + BurnYM2608Exit(); + + BurnFree(Mem); + + Wc90Scroll0YLo = 0; + Wc90Scroll0YHi = 0; + Wc90Scroll0XLo = 0; + Wc90Scroll0XHi = 0; + Wc90Scroll1YLo = 0; + Wc90Scroll1YHi = 0; + Wc90Scroll1XLo = 0; + Wc90Scroll1XHi = 0; + Wc90Scroll2YLo = 0; + Wc90Scroll2YHi = 0; + Wc90Scroll2XLo = 0; + Wc90Scroll2XHi = 0; + Wc90SoundLatch = 0; + + nTileType = 0; + + return 0; +} + +static INT32 Wc90Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + + BurnYM2608Scan(nAction, pnMin); // Scan YM2608 + + // Scan critical driver variables + SCAN_VAR(Wc90SoundLatch); + SCAN_VAR(Wc90Input); + SCAN_VAR(Wc90Dip); + SCAN_VAR(Wc90Scroll0YLo); + SCAN_VAR(Wc90Scroll0YHi); + SCAN_VAR(Wc90Scroll0XLo); + SCAN_VAR(Wc90Scroll0XHi); + SCAN_VAR(Wc90Scroll1YLo); + SCAN_VAR(Wc90Scroll1YHi); + SCAN_VAR(Wc90Scroll1XLo); + SCAN_VAR(Wc90Scroll1XHi); + SCAN_VAR(Wc90Scroll2YLo); + SCAN_VAR(Wc90Scroll2YHi); + SCAN_VAR(Wc90Scroll2XLo); + SCAN_VAR(Wc90Scroll2XHi); + } + + return 0; +} + +struct BurnDriver BurnDrvWc90 = { + "wc90", NULL, NULL, NULL, "1989", + "World Cup '90 (World)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HISCORE_SUPPORTED, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90RomInfo, Wc90RomName, NULL, NULL, Wc90InputInfo, Wc90DIPInfo, + Wc90Init, Wc90Exit, Wc90Frame, NULL, Wc90Scan, + NULL, 0x400, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWc90a = { + "wc90a", "wc90", NULL, NULL, "1989", + "World Cup '90 (Euro set 1)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90aRomInfo, Wc90aRomName, NULL, NULL, Wc90InputInfo, Wc90DIPInfo, + Wc90Init, Wc90Exit, Wc90Frame, NULL, Wc90Scan, + NULL, 0x400, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWc90b = { + "wc90b", "wc90", NULL, NULL, "1989", + "World Cup '90 (Euro set 2)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HISCORE_SUPPORTED, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90bRomInfo, Wc90bRomName, NULL, NULL, Wc90InputInfo, Wc90DIPInfo, + Wc90Init, Wc90Exit, Wc90Frame, NULL, Wc90Scan, + NULL, 0x400, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWc90t = { + "wc90t", "wc90", NULL, NULL, "1989", + "World Cup '90 (trackball)\0", NULL, "Tecmo", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90tRomInfo, Wc90tRomName, NULL, NULL, Wc90InputInfo, Wc90DIPInfo, + Wc90Init, Wc90Exit, Wc90Frame, NULL, Wc90Scan, + NULL, 0x400, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_wc90b.cpp b/src/burn/drivers/misc_pre90s/d_wc90b.cpp new file mode 100644 index 00000000..85fdb331 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_wc90b.cpp @@ -0,0 +1,977 @@ +#include "tiles_generic.h" +#include "burn_ym2203.h" +#include "msm5205.h" + +static UINT8 Wc90b1InputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Wc90b1InputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 Wc90b1Dip[2] = {0, 0}; +static UINT8 Wc90b1Input[2] = {0x00, 0x00}; +static UINT8 Wc90b1Reset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *Wc90b1Z80Rom1 = NULL; +static UINT8 *Wc90b1Z80Rom2 = NULL; +static UINT8 *Wc90b1Z80Rom3 = NULL; +static UINT8 *Wc90b1Z80Ram1 = NULL; +static UINT8 *Wc90b1Z80Ram2 = NULL; +static UINT8 *Wc90b1Z80Ram3 = NULL; +static UINT8 *Wc90b1FgVideoRam = NULL; +static UINT8 *Wc90b1BgVideoRam = NULL; +static UINT8 *Wc90b1TextVideoRam = NULL; +static UINT8 *Wc90b1SpriteRam = NULL; +static UINT8 *Wc90b1PaletteRam = NULL; +static UINT8 *Wc90b1SharedRam = NULL; +static UINT32 *Wc90b1Palette = NULL; +static UINT8 *Wc90b1CharTiles = NULL; +static UINT8 *Wc90b1Tiles = NULL; +static UINT8 *Wc90b1Sprites = NULL; +static UINT8 *Wc90b1TempGfx = NULL; + +static UINT8 Wc90b1Scroll0Y; +static UINT8 Wc90b1Scroll0X; +static UINT8 Wc90b1Scroll1Y; +static UINT8 Wc90b1Scroll1X; +static UINT8 Wc90b1ScrollXLo; + +static UINT8 Wc90b1SoundLatch = 0; +static INT32 Wc90b1MSM5205Next; + +static INT32 nCyclesDone[3], nCyclesTotal[3]; +static INT32 nCyclesSegment; + +static struct BurnInputInfo Wc90b1InputList[] = { + {"Coin 1" , BIT_DIGITAL , Wc90b1InputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , Wc90b1InputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , Wc90b1InputPort1 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , Wc90b1InputPort1 + 6, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , Wc90b1InputPort0 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , Wc90b1InputPort0 + 2, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , Wc90b1InputPort0 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , Wc90b1InputPort0 + 0, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , Wc90b1InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , Wc90b1InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , Wc90b1InputPort1 + 3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , Wc90b1InputPort1 + 2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , Wc90b1InputPort1 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , Wc90b1InputPort1 + 0, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , Wc90b1InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , Wc90b1InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &Wc90b1Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, Wc90b1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, Wc90b1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Wc90b1) + +inline static void Wc90b1ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0c) == 0x0c) { + *nJoystickInputs &= ~0x0c; + } +} + +inline static void Wc90b1MakeInputs() +{ + Wc90b1Input[0] = Wc90b1Input[1] = 0x00; + + for (INT32 i = 0; i < 8; i++) { + Wc90b1Input[0] |= (Wc90b1InputPort0[i] & 1) << i; + Wc90b1Input[1] |= (Wc90b1InputPort1[i] & 1) << i; + } + + Wc90b1ClearOpposites(&Wc90b1Input[0]); + Wc90b1ClearOpposites(&Wc90b1Input[1]); +} + +static struct BurnDIPInfo Wc90b1DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 16 , "Coinage" }, + {0x11, 0x01, 0x0f, 0x00, "10 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x08, " 9 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x04, " 8 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0c, " 7 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x02, " 6 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0a, " 5 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x06, " 4 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0e, " 3 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x01, " 2 Coins 3 Credits" }, + {0x11, 0x01, 0x0f, 0x09, " 2 Coins 1 Credit" }, + {0x11, 0x01, 0x0f, 0x0f, " 1 Coin 1 Credit" }, + {0x11, 0x01, 0x0f, 0x07, " 1 Coin 2 Credits" }, + {0x11, 0x01, 0x0f, 0x0b, " 1 Coin 3 Credits" }, + {0x11, 0x01, 0x0f, 0x03, " 1 Coin 4 Credits" }, + {0x11, 0x01, 0x0f, 0x0d, " 1 Coin 5 Credits" }, + {0x11, 0x01, 0x0f, 0x05, " 1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x30, 0x30, "Easy" }, + {0x11, 0x01, 0x30, 0x10, "Normal" }, + {0x11, 0x01, 0x30, 0x20, "Hard" }, + {0x11, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Countdown Speed" }, + {0x11, 0x01, 0x40, 0x40, "Normal" }, + {0x11, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "1 Player Game Time" }, + {0x12, 0x01, 0x03, 0x01, "1:00" }, + {0x12, 0x01, 0x03, 0x02, "1:30" }, + {0x12, 0x01, 0x03, 0x03, "2:00" }, + {0x12, 0x01, 0x03, 0x00, "2:30" }, + + {0 , 0xfe, 0 , 8 , "2 Players Game Time" }, + {0x12, 0x01, 0x1c, 0x0c, "1:00" }, + {0x12, 0x01, 0x1c, 0x14, "1:30" }, + {0x12, 0x01, 0x1c, 0x04, "2:00" }, + {0x12, 0x01, 0x1c, 0x18, "2:30" }, + {0x12, 0x01, 0x1c, 0x1c, "3:00" }, + {0x12, 0x01, 0x1c, 0x08, "3:30" }, + {0x12, 0x01, 0x1c, 0x10, "4:00" }, + {0x12, 0x01, 0x1c, 0x00, "5:00" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x80, 0x00, "English" }, + {0x12, 0x01, 0x80, 0x80, "Japanese" }, +}; + +STDDIPINFO(Wc90b1) + +static struct BurnRomInfo Wc90b1RomDesc[] = { + { "a02.bin", 0x10000, 0x192a03dd, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a03.bin", 0x10000, 0xf54ff17a, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "a04.bin", 0x10000, 0x3d535e2f, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "a05.bin", 0x10000, 0x9e421c4b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "a01.bin", 0x10000, 0x3d317622, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "a06.bin", 0x04000, 0x3b5387b7, BRF_GRA }, // 5 Characters + { "a08.bin", 0x04000, 0xc622a5a3, BRF_GRA }, // 6 Characters + { "a10.bin", 0x04000, 0x0923d9f6, BRF_GRA }, // 7 Characters + { "a20.bin", 0x04000, 0xb8dec83e, BRF_GRA }, // 8 Characters + { "a07.bin", 0x20000, 0x38c31817, BRF_GRA }, // 9 Fg Tiles + { "a09.bin", 0x20000, 0x32e39e29, BRF_GRA }, // 10 Fg Tiles + { "a11.bin", 0x20000, 0x5ccec796, BRF_GRA }, // 11 Bg Tiles + { "a21.bin", 0x20000, 0x0c54a091, BRF_GRA }, // 12 Bg Tiles + { "146_a12.bin", 0x10000, 0xd5a60096, BRF_GRA }, // 13 Sprites + { "147_a13.bin", 0x10000, 0x36bbf467, BRF_GRA }, // 14 Sprites + { "148_a14.bin", 0x10000, 0x26371c18, BRF_GRA }, // 15 Sprites + { "149_a15.bin", 0x10000, 0x75aa9b86, BRF_GRA }, // 16 Sprites + { "150_a16.bin", 0x10000, 0x0da825f9, BRF_GRA }, // 17 Sprites + { "151_a17.bin", 0x10000, 0x228429d8, BRF_GRA }, // 18 Sprites + { "152_a18.bin", 0x10000, 0x516b6c09, BRF_GRA }, // 19 Sprites + { "153_a19.bin", 0x10000, 0xf36390a9, BRF_GRA }, // 20 Sprites + + { "el_ic39_gal16v8_0.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 21 PLDs + { "el_ic44_gal16v8_1.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 22 PLDs + { "el_ic54_gal16v8_2.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 23 PLDs + { "el_ic100_gal16v8_3.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 24 PLDs + { "el_ic143_gal16v8_4.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 25 PLDs +}; + +STD_ROM_PICK(Wc90b1) +STD_ROM_FN(Wc90b1) + +static struct BurnRomInfo Wc90b2RomDesc[] = { + { "a02", 0x10000, 0x1e6e94c9, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a03.bin", 0x10000, 0xf54ff17a, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "a04.bin", 0x10000, 0x3d535e2f, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + { "a05.bin", 0x10000, 0x9e421c4b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "a01.bin", 0x10000, 0x3d317622, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program Code + + { "a06", 0x08000, 0x0c054481, BRF_GRA }, // 5 Characters + { "a08", 0x08000, 0xebb3eb48, BRF_GRA }, // 6 Characters + { "a10", 0x08000, 0xc0232af8, BRF_GRA }, // 7 Characters + { "a20", 0x08000, 0xa36e17fb, BRF_GRA }, // 8 Characters + { "a07.bin", 0x20000, 0x38c31817, BRF_GRA }, // 9 Fg Tiles + { "a09.bin", 0x20000, 0x32e39e29, BRF_GRA }, // 10 Fg Tiles + { "a11.bin", 0x20000, 0x5ccec796, BRF_GRA }, // 11 Bg Tiles + { "a21.bin", 0x20000, 0x0c54a091, BRF_GRA }, // 12 Bg Tiles + { "146_a12.bin", 0x10000, 0xd5a60096, BRF_GRA }, // 13 Sprites + { "147_a13", 0x10000, 0x5b16fd48, BRF_GRA }, // 14 Sprites + { "148_a14.bin", 0x10000, 0x26371c18, BRF_GRA }, // 15 Sprites + { "149_a15", 0x10000, 0xb2423962, BRF_GRA }, // 16 Sprites + { "150_a16.bin", 0x10000, 0x0da825f9, BRF_GRA }, // 17 Sprites + { "151_a17", 0x10000, 0xaf98778e, BRF_GRA }, // 18 Sprites + { "152_a18.bin", 0x10000, 0x516b6c09, BRF_GRA }, // 19 Sprites + { "153_a19", 0x10000, 0x8caa2745, BRF_GRA }, // 20 Sprites + + { "el_ic39_gal16v8_0.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 21 PLDs + { "el_ic44_gal16v8_1.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 22 PLDs + { "el_ic54_gal16v8_2.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 23 PLDs + { "el_ic100_gal16v8_3.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 24 PLDs + { "el_ic143_gal16v8_4.bin", 0x00117, 0x00000000, BRF_OPT | BRF_NODUMP }, // 25 PLDs +}; + +STD_ROM_PICK(Wc90b2) +STD_ROM_FN(Wc90b2) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + Wc90b1Z80Rom1 = Next; Next += 0x20000; + Wc90b1Z80Rom2 = Next; Next += 0x20000; + Wc90b1Z80Rom3 = Next; Next += 0x10000; + + RamStart = Next; + + Wc90b1Z80Ram1 = Next; Next += 0x04000; + Wc90b1Z80Ram2 = Next; Next += 0x01800; + Wc90b1Z80Ram3 = Next; Next += 0x00800; + Wc90b1FgVideoRam = Next; Next += 0x01000; + Wc90b1BgVideoRam = Next; Next += 0x01000; + Wc90b1TextVideoRam = Next; Next += 0x01000; + Wc90b1SpriteRam = Next; Next += 0x00800; + Wc90b1PaletteRam = Next; Next += 0x00800; + Wc90b1SharedRam = Next; Next += 0x00400; + + RamEnd = Next; + + Wc90b1CharTiles = Next; Next += (2048 * 8 * 8); + Wc90b1Tiles = Next; Next += (4096 * 16 * 16); + Wc90b1Sprites = Next; Next += (4096 * 16 * 16); + Wc90b1Palette = (UINT32*)Next; Next += 0x00400 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 Wc90b1DoReset() +{ + Wc90b1Scroll0X = Wc90b1Scroll0Y = 0; + Wc90b1Scroll1X = Wc90b1Scroll1Y = 0; + Wc90b1ScrollXLo = 0; + + Wc90b1SoundLatch = 0; + Wc90b1MSM5205Next = 0; + + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnYM2203Reset(); + MSM5205Reset(); + +// HiscoreReset(); + + return 0; +} + +UINT8 __fastcall Wc90b1Read1(UINT16 a) +{ + switch (a) { + case 0xfd00: { + return 0xff - Wc90b1Input[0]; + } + + case 0xfd02: { + return 0xff - Wc90b1Input[1]; + } + + case 0xfd06: { + return Wc90b1Dip[0]; + } + + case 0xfd08: { + return Wc90b1Dip[1]; + } + + case 0xfd0c: { + // ??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Wc90b1Write1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfc00: { + INT32 BankAddress; + + BankAddress = 0x10000 + ((d & 0xf8) << 8); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90b1Z80Rom1 + BankAddress); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90b1Z80Rom1 + BankAddress); + return; + } + + case 0xfd00: { + Wc90b1SoundLatch = d; + ZetClose(); + ZetOpen(2); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + ZetOpen(0); + return; + } + + case 0xfd04: { + Wc90b1Scroll0Y = d; + return; + } + + case 0xfd06: { + Wc90b1Scroll0X = d; + return; + } + + case 0xfd08: { + Wc90b1Scroll1Y = d; + return; + } + + case 0xfd0a: { + Wc90b1Scroll1X = d; + return; + } + + case 0xfd0e: { + Wc90b1ScrollXLo = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Wc90b1Read2(UINT16 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Wc90b1Write2(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfc00: { + INT32 BankAddress; + + BankAddress = 0x10000 + ((d & 0xf8) << 8); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90b1Z80Rom2 + BankAddress); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90b1Z80Rom2 + BankAddress); + return; + } + + case 0xfd0c: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Wc90b1Read3(UINT16 a) +{ + switch (a) { + case 0xe800: { + return BurnYM2203Read(0, 0); + } + + case 0xf800: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return Wc90b1SoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Wc90b1Write3(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + INT32 BankAddress; + + BankAddress = 0x8000 + ((d & 0x01) * 0x4000); + ZetMapArea(0x8000, 0xbfff, 0, Wc90b1Z80Rom3 + BankAddress); + ZetMapArea(0x8000, 0xbfff, 2, Wc90b1Z80Rom3 + BankAddress); + + MSM5205ResetWrite(0, d & 0x08); + return; + } + + case 0xe400: { + Wc90b1MSM5205Next = d; + return; + } + + case 0xe800: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xe801: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xec00: + case 0xec01: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Write => %04X, %02X\n"), a, d); + } + } +} + +inline static INT32 Wc90b1SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 5000000; +} + +inline static double Wc90b1GetTime() +{ + return (double)ZetTotalCycles() / 5000000; +} + +static void Wc90b1MSM5205Vck0() +{ + static INT32 Toggle = 0; + + Toggle ^= 1; + + if (Toggle) { + MSM5205DataWrite(0, (Wc90b1MSM5205Next & 0xf0) >> 4); + ZetNmi(); + } else { + MSM5205DataWrite(0, Wc90b1MSM5205Next & 0x0f); + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 0x20000, 0x40000, 0x60000 }; +static INT32 CharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 CharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 TilePlaneOffsets[4] = { 0, 0x100000, 0x200000, 0x300000 }; +static INT32 TileXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007 }; +static INT32 TileYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 0x4000, 0x4008, 0x4010, 0x4018, 0x4020, 0x4028, 0x4030, 0x4038 }; +static INT32 SpritePlaneOffsets[4] = { 0x300000, 0x200000, 0x100000, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; + +static INT32 Wc90b1Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + Wc90b1TempGfx = (UINT8*)BurnMalloc(0x80000); + if (Wc90b1TempGfx == NULL) return 1; + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(Wc90b1Z80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1Z80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(Wc90b1Z80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1Z80Rom2 + 0x10000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Rom + nRet = BurnLoadRom(Wc90b1Z80Rom3 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and Decode Char Tile Roms + memset(Wc90b1TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90b1TempGfx + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x04000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x08000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x0c000, 8, 1); if (nRet != 0) return 1; + GfxDecode(2048, 4, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x40, Wc90b1TempGfx, Wc90b1CharTiles); + + // Load and Decode Tile Roms + memset(Wc90b1TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90b1TempGfx + 0x00000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x20000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x60000, 12, 1); if (nRet != 0) return 1; + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x00000, Wc90b1Tiles + ( 0 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x02000, Wc90b1Tiles + ( 1 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x04000, Wc90b1Tiles + ( 2 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x06000, Wc90b1Tiles + ( 3 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x08000, Wc90b1Tiles + ( 4 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x0a000, Wc90b1Tiles + ( 5 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x0c000, Wc90b1Tiles + ( 6 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x0e000, Wc90b1Tiles + ( 7 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x10000, Wc90b1Tiles + ( 8 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x12000, Wc90b1Tiles + ( 9 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x14000, Wc90b1Tiles + (10 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x16000, Wc90b1Tiles + (11 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x18000, Wc90b1Tiles + (12 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x1a000, Wc90b1Tiles + (13 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x1c000, Wc90b1Tiles + (14 * 256 * 16 * 16)); + GfxDecode(256, 4, 16, 16, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, Wc90b1TempGfx + 0x1e000, Wc90b1Tiles + (15 * 256 * 16 * 16)); + + // Load and Decode Sprite Roms + memset(Wc90b1TempGfx, 0, 0x80000); + nRet = BurnLoadRom(Wc90b1TempGfx + 0x00000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x10000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x20000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x30000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x40000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x50000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x60000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(Wc90b1TempGfx + 0x70000, 20, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x80000; i++) { + Wc90b1TempGfx[i] ^= 0xff; + } + GfxDecode(4096, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, Wc90b1TempGfx, Wc90b1Sprites); + + BurnFree(Wc90b1TempGfx); + + // Setup the Z80 emulation + ZetInit(3); + ZetOpen(0); + ZetSetReadHandler(Wc90b1Read1); + ZetSetWriteHandler(Wc90b1Write1); + ZetMapArea(0x0000, 0x7fff, 0, Wc90b1Z80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, Wc90b1Z80Rom1 ); + ZetMapArea(0x8000, 0x9fff, 0, Wc90b1Z80Ram1 + 0x00000); + ZetMapArea(0x8000, 0x9fff, 1, Wc90b1Z80Ram1 + 0x00000); + ZetMapArea(0x8000, 0x9fff, 2, Wc90b1Z80Ram1 + 0x00000); + ZetMapArea(0xa000, 0xafff, 0, Wc90b1FgVideoRam ); + ZetMapArea(0xa000, 0xafff, 1, Wc90b1FgVideoRam ); + ZetMapArea(0xa000, 0xafff, 2, Wc90b1FgVideoRam ); + ZetMapArea(0xc000, 0xcfff, 0, Wc90b1BgVideoRam ); + ZetMapArea(0xc000, 0xcfff, 1, Wc90b1BgVideoRam ); + ZetMapArea(0xc000, 0xcfff, 2, Wc90b1BgVideoRam ); + ZetMapArea(0xd000, 0xdfff, 0, Wc90b1Z80Ram1 + 0x03000); + ZetMapArea(0xd000, 0xdfff, 1, Wc90b1Z80Ram1 + 0x03000); + ZetMapArea(0xd000, 0xdfff, 2, Wc90b1Z80Ram1 + 0x03000); + ZetMapArea(0xe000, 0xefff, 0, Wc90b1TextVideoRam ); + ZetMapArea(0xe000, 0xefff, 1, Wc90b1TextVideoRam ); + ZetMapArea(0xe000, 0xefff, 2, Wc90b1TextVideoRam ); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90b1Z80Rom1 + 0x10000); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90b1Z80Rom1 + 0x10000); + ZetMapArea(0xf800, 0xfbff, 0, Wc90b1SharedRam ); + ZetMapArea(0xf800, 0xfbff, 1, Wc90b1SharedRam ); + ZetMapArea(0xf800, 0xfbff, 2, Wc90b1SharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(Wc90b1Read2); + ZetSetWriteHandler(Wc90b1Write2); + ZetMapArea(0x0000, 0xbfff, 0, Wc90b1Z80Rom2 ); + ZetMapArea(0x0000, 0xbfff, 2, Wc90b1Z80Rom2 ); + ZetMapArea(0xc000, 0xcfff, 0, Wc90b1Z80Ram2 + 0x00000); + ZetMapArea(0xc000, 0xcfff, 1, Wc90b1Z80Ram2 + 0x00000); + ZetMapArea(0xc000, 0xcfff, 2, Wc90b1Z80Ram2 + 0x00000); + ZetMapArea(0xd000, 0xd7ff, 0, Wc90b1SpriteRam ); + ZetMapArea(0xd000, 0xd7ff, 1, Wc90b1SpriteRam ); + ZetMapArea(0xd000, 0xd7ff, 2, Wc90b1SpriteRam ); + ZetMapArea(0xd800, 0xdfff, 0, Wc90b1Z80Ram2 + 0x01000); + ZetMapArea(0xd800, 0xdfff, 1, Wc90b1Z80Ram2 + 0x01000); + ZetMapArea(0xd800, 0xdfff, 2, Wc90b1Z80Ram2 + 0x01000); + ZetMapArea(0xe000, 0xe7ff, 0, Wc90b1PaletteRam ); + ZetMapArea(0xe000, 0xe7ff, 1, Wc90b1PaletteRam ); + ZetMapArea(0xe000, 0xe7ff, 2, Wc90b1PaletteRam ); + ZetMapArea(0xe800, 0xefff, 0, Wc90b1Z80Rom2 + 0x0e800); + ZetMapArea(0xe800, 0xefff, 2, Wc90b1Z80Rom2 + 0x0e800); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90b1Z80Rom2 + 0x10000); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90b1Z80Rom2 + 0x10000); + ZetMapArea(0xf800, 0xfbff, 0, Wc90b1SharedRam ); + ZetMapArea(0xf800, 0xfbff, 1, Wc90b1SharedRam ); + ZetMapArea(0xf800, 0xfbff, 2, Wc90b1SharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(Wc90b1Read3); + ZetSetWriteHandler(Wc90b1Write3); + ZetMapArea(0x0000, 0x7fff, 0, Wc90b1Z80Rom3 ); + ZetMapArea(0x0000, 0x7fff, 2, Wc90b1Z80Rom3 ); + ZetMapArea(0x8000, 0xbfff, 0, Wc90b1Z80Rom3 + 0x8000 ); + ZetMapArea(0x8000, 0xbfff, 2, Wc90b1Z80Rom3 + 0x8000 ); + ZetMapArea(0xf000, 0xf7ff, 0, Wc90b1Z80Ram3 ); + ZetMapArea(0xf000, 0xf7ff, 1, Wc90b1Z80Ram3 ); + ZetMapArea(0xf000, 0xf7ff, 2, Wc90b1Z80Ram3 ); + ZetMemEnd(); + ZetClose(); + + GenericTilesInit(); + + BurnYM2203Init(1, 1250000, NULL, Wc90b1SynchroniseStream, Wc90b1GetTime, 0); + BurnTimerAttachZet(5000000); + + MSM5205Init(0, Wc90b1SynchroniseStream, 384000, Wc90b1MSM5205Vck0, MSM5205_S96_4B, 100, 1); + + Wc90b1DoReset(); + + return 0; +} + +static INT32 Wc90b1Exit() +{ + ZetExit(); + GenericTilesExit(); + BurnYM2203Exit(); + MSM5205Exit(); + + BurnFree(Mem); + + Wc90b1Scroll0X = Wc90b1Scroll0Y = 0; + Wc90b1Scroll1X = Wc90b1Scroll1Y = 0; + Wc90b1ScrollXLo = 0; + Wc90b1SoundLatch = 0; + Wc90b1MSM5205Next = 0; + + return 0; +} + +static void Wc90b1RenderBgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90b1BgVideoRam[TileIndex]; + Code = Wc90b1BgVideoRam[TileIndex + 0x800]; + Colour = Attr >> 4; + + Code |= ((Attr & 3) + ((Attr >> 1) & 4)) * 256; + Code |= 2048; + + x = 16 * mx; + y = 16 * my; + + x -= 8 * (Wc90b1Scroll1X & 0x7f) + 256 - 4 + (Wc90b1ScrollXLo & 0x07); + y -= Wc90b1Scroll1Y + 1 + ((Wc90b1Scroll1X & 0x80) ? 256 : 0); + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile(pTransDraw, Code, x, y, Colour, 4, 768, Wc90b1Tiles); + } else { + Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 4, 768, Wc90b1Tiles); + } + + TileIndex++; + } + } +} + +static void Wc90b1RenderFgLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = Wc90b1FgVideoRam[TileIndex]; + Code = Wc90b1FgVideoRam[TileIndex + 0x800]; + Colour = Attr >> 4; + + Code |= ((Attr & 3) + ((Attr >> 1) & 4)) * 256; + + x = 16 * mx; + y = 16 * my; + + x -= 8 * (Wc90b1Scroll0X & 0x7f) + 256 - 6 + ((Wc90b1ScrollXLo & 0x38) >> 3); + y -= Wc90b1Scroll0Y + 1 + ((Wc90b1Scroll0X & 0x80) ? 256 : 0); + + x &= 0x3ff; + y &= 0x1ff; + + y -= 16; + if (x > 968) x -= 1024; + + if (x > 15 && x < 240 && y > 15 && y < 208) { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 15, 512, Wc90b1Tiles); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 512, Wc90b1Tiles); + } + + TileIndex++; + } + } +} + +static void Wc90b1RenderCharLayer() +{ + INT32 mx, my, Code, Colour, x, y, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = Wc90b1TextVideoRam[TileIndex + 0x800] + ((Wc90b1TextVideoRam[TileIndex] & 0x07) << 8); + Colour = Wc90b1TextVideoRam[TileIndex] >> 4; + + x = 8 * mx; + y = 8 * my; + + x &= 0x1ff; + y &= 0x0ff; + + y -= 16; + + if (x > 7 && x < 248 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 15, 256, Wc90b1CharTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 15, 256, Wc90b1CharTiles); + } + + TileIndex++; + } + } +} + +static void Wc90b1RenderSpriteLayer(INT32 Priority) +{ + INT32 Offset, sx, sy; + + for (Offset = 0x800 - 8; Offset >= 0; Offset -= 8) { + if ((~(Wc90b1SpriteRam[Offset + 3] >> 7) & 1) == Priority) { + INT32 Code = (Wc90b1SpriteRam[Offset + 3] & 0x3f) << 4; + INT32 Bank = Wc90b1SpriteRam[Offset + 0]; + INT32 Flags = Wc90b1SpriteRam[Offset + 4]; + INT32 xFlip = Bank & 0x01; + INT32 yFlip = Bank & 0x02; + + Code += (Bank & 0xf0) >> 4; + Code <<= 2; + Code += (Bank & 0x0f) >> 2; + + sx = Wc90b1SpriteRam[Offset + 2]; + if (!(Wc90b1SpriteRam[Offset + 3] & 0x40)) sx -= 0x100; + + sy = 240 - Wc90b1SpriteRam[Offset + 1]; + + sy -= 16; + + if (sx > 15 && sx < 240 && sy > 15 && sy < 208) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Flags >> 4, 4, 15, 0, Wc90b1Sprites); + } + } + } + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour >> 0) & 0x0f; + g = (nColour >> 4) & 0x0f; + b = (nColour >> 8) & 0x0f; + + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + + return BurnHighCol(r, g, b, 0); +} + +static INT32 Wc90b1CalcPalette() +{ + INT32 i; + + for (i = 0; i < 0x800; i++) { + Wc90b1Palette[i / 2] = CalcCol(Wc90b1PaletteRam[i | 1] | (Wc90b1PaletteRam[i & ~1] << 8)); + } + + return 0; +} + +static void Wc90b1Draw() +{ + BurnTransferClear(); + Wc90b1CalcPalette(); + Wc90b1RenderBgLayer(); + Wc90b1RenderFgLayer(); + Wc90b1RenderSpriteLayer(1); + Wc90b1RenderCharLayer(); + Wc90b1RenderSpriteLayer(0); + BurnTransferCopy(Wc90b1Palette); +} + +static INT32 Wc90b1Frame() +{ + INT32 nInterleave = MSM5205CalcInterleave(0, 5000000); + INT32 nVBlankIRQFire = (INT32)((double)242 / 260 * nInterleave); + + if (Wc90b1Reset) Wc90b1DoReset(); + + Wc90b1MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)7159090 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)7159090 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = (INT32)(double)(5000000 / 60); + + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext, nCurrentCPU; + + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == nVBlankIRQFire) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == nVBlankIRQFire + 1) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + if (i == nVBlankIRQFire) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == nVBlankIRQFire + 1) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[2] / nInterleave)); + MSM5205Update(); + ZetClose(); + } + + ZetOpen(2); + BurnTimerEndFrame(nCyclesTotal[2]); + if (pBurnSoundOut) { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + } + ZetClose(); + + if (pBurnDraw) Wc90b1Draw(); + + return 0; +} + +static INT32 Wc90b1Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029709; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + + BurnYM2203Scan(nAction, pnMin); + + SCAN_VAR(Wc90b1SoundLatch); + SCAN_VAR(Wc90b1MSM5205Next); + SCAN_VAR(Wc90b1Input); + SCAN_VAR(Wc90b1Dip); + SCAN_VAR(Wc90b1Scroll0Y); + SCAN_VAR(Wc90b1Scroll0X); + SCAN_VAR(Wc90b1Scroll1Y); + SCAN_VAR(Wc90b1Scroll1X); + SCAN_VAR(Wc90b1ScrollXLo); + } + + return 0; +} + +struct BurnDriver BurnDrvWc90b1 = { + "wc90b1", "wc90", NULL, NULL, "1989", + "Euro League (Italian hack of Tecmo World Cup '90)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90b1RomInfo, Wc90b1RomName, NULL, NULL, Wc90b1InputInfo, Wc90b1DIPInfo, + Wc90b1Init, Wc90b1Exit, Wc90b1Frame, NULL, Wc90b1Scan, + NULL, 0x400, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWc90b2 = { + "wc90b2", "wc90", NULL, NULL, "1989", + "World Cup '90 (bootleg)\0", NULL, "bootleg", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSFOOTBALL, 0, + NULL, Wc90b2RomInfo, Wc90b2RomName, NULL, NULL, Wc90b1InputInfo, Wc90b1DIPInfo, + Wc90b1Init, Wc90b1Exit, Wc90b1Frame, NULL, Wc90b1Scan, + NULL, 0x400, 256, 224, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/d_wwfsstar.cpp b/src/burn/drivers/misc_pre90s/d_wwfsstar.cpp new file mode 100644 index 00000000..033871b7 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/d_wwfsstar.cpp @@ -0,0 +1,1009 @@ +// FB Alpha WWF Superstars driver module +// Based on MAME driver by David Haywood + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "msm6295.h" + +static UINT8 *AllMem; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *MemEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *DrvGfxROM0; +static UINT8 *DrvGfxROM1; +static UINT8 *DrvGfxROM2; +static UINT8 *DrvSndROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvZ80RAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvFgRAM; +static UINT8 *DrvBgRAM; + +static UINT32 *DrvPalette; + +static UINT8 *soundlatch; +static UINT8 *flipscreen; +static UINT16 *scroll; + +static UINT16 DrvInputs[3]; +static UINT8 DrvJoy1[16]; +static UINT8 DrvJoy2[16]; +static UINT8 DrvJoy3[16]; +static UINT8 DrvDips[2]; +static UINT8 DrvReset; + +static INT32 vblank = 0; + +static struct BurnInputInfo WwfsstarInputList[] = { + {"Start 1", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" }, + {"Start 2", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" }, + {"Start 3", BIT_DIGITAL, DrvJoy2 + 6, "p3 start" }, + + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p1 coin" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down"} , + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 2, "p2 coin" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 3, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Wwfsstar) + +static struct BurnDIPInfo WwfsstarDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x07, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x01, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x07, 0x07, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0x38, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x08, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x38, 0x38, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x38, 0x30, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x13, 0x01, 0x38, 0x20, "1 Coin 4 Credits" }, + {0x13, 0x01, 0x38, 0x18, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Normal" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x04, 0x00, "Off" }, + {0x14, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Super Techniques" }, + {0x14, 0x01, 0x08, 0x08, "Normal" }, + {0x14, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 4, "Time" }, + {0x14, 0x01, 0x30, 0x20, "+2:30" }, + {0x14, 0x01, 0x30, 0x30, "Default" }, + {0x14, 0x01, 0x30, 0x10, "-2:30" }, + {0x14, 0x01, 0x30, 0x00, "-5:00" }, + + {0 , 0xfe, 0 , 2, "Health For Winning" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, +}; + +STDDIPINFO(Wwfsstar) + +void __fastcall wwfsstar_main_write_byte(UINT32 , UINT8 ) +{ + +} + +void __fastcall wwfsstar_main_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x180000: + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return; + + case 0x180002: + SekSetIRQLine(5, SEK_IRQSTATUS_NONE); + return; + + case 0x180004: + scroll[0] = data & 0x1ff; + return; + + case 0x180006: + scroll[1] = data & 0x1ff; + return; + + case 0x180008: + *soundlatch = data; + ZetNmi(); + return; + + case 0x18000a: + *flipscreen = data & 1; + return; + } +} + +UINT8 __fastcall wwfsstar_main_read_byte(UINT32 address) +{ + switch (address) + { + case 0x180003: + return DrvDips[1]; + + case 0x180004: + return DrvInputs[0] >> 8; + + case 0x180005: + return DrvInputs[0]; + + case 0x180006: + return DrvInputs[1] >> 8; + + case 0x180007: + return DrvInputs[1]; + + case 0x180008: + return DrvInputs[2] >> 8; + + case 0x180009: + return (DrvInputs[2] & 0xfe) | vblank; + } + + return 0; +} + +UINT16 __fastcall wwfsstar_main_read_word(UINT32 address) +{ + switch (address) + { + case 0x180000: + return 0xff00 | DrvDips[0]; + + case 0x180002: + return 0xff00 | DrvDips[1]; + + case 0x180004: + return DrvInputs[0]; + + case 0x180006: + return DrvInputs[1]; + + case 0x180008: + return (DrvInputs[2] & 0xfffe) | vblank; + } + + return 0; +} + +void __fastcall wwfsstar_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0x8800: + BurnYM2151SelectRegister(data); + return; + + case 0x8801: + BurnYM2151WriteRegister(data); + return; + + case 0x9800: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall wwfsstar_sound_read(UINT16 address) +{ + switch (address) + { + case 0x8800: + case 0x8801: + return BurnYM2151ReadStatus(); + + case 0x9800: + return MSM6295ReadStatus(0); + + case 0xa000: + return *soundlatch; + } + + return 0; +} + +static void DrvYM2151IrqHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvDoReset() +{ + memset (AllRam, 0, RamEnd - AllRam); + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM2151Reset(); + + MSM6295Reset(0); + + vblank = 1; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + DrvZ80ROM = Next; Next += 0x010000; + + DrvGfxROM0 = Next; Next += 0x040000; + DrvGfxROM1 = Next; Next += 0x400000; + DrvGfxROM2 = Next; Next += 0x100000; + + MSM6295ROM = Next; + DrvSndROM = Next; Next += 0x040000; + + DrvPalette = (UINT32*)Next; Next += 0x180 * sizeof(UINT32); + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvZ80RAM = Next; Next += 0x000800; + + DrvSprRAM = Next; Next += 0x000400; + DrvPalRAM = Next; Next += 0x001000; + DrvFgRAM = Next; Next += 0x001000; + DrvBgRAM = Next; Next += 0x001000; + + soundlatch = Next; Next += 0x000001; + flipscreen = Next; Next += 0x000001; + + scroll = (UINT16*)Next; Next += 2 * sizeof(UINT16); + + RamEnd = Next; + + MemEnd = Next; + + return 0; +} + +static INT32 DrvGfxDecode() +{ + INT32 Plane0[4] = { 0x000000, 0x000002, 0x000004, 0x000006 }; + INT32 Plane1[4] = { 0x800000, 0x800004, 0x000000, 0x000004 }; + INT32 Plane2[4] = { 0x200000, 0x200004, 0x000000, 0x000004 }; + + INT32 XOffs0[8] = { 0x001, 0x000, 0x041, 0x040, 0x081, 0x080, 0x0c1, 0x0c0 }; + INT32 YOffs[16] = { 0x000, 0x008, 0x010, 0x018, 0x020, 0x028, 0x030, 0x038, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078 }; + INT32 XOffs1[16] = { 0x003, 0x002, 0x001, 0x000, 0x083, 0x082, 0x081, 0x080, + 0x103, 0x102, 0x101, 0x100, 0x183, 0x182, 0x181, 0x180 }; + + UINT8 *tmp = (UINT8*)BurnMalloc(0x200000); + if (tmp == NULL) { + return 1; + } + + memcpy (tmp, DrvGfxROM0, 0x020000); + + GfxDecode(0x1000, 4, 8, 8, Plane0, XOffs0, YOffs, 0x100, tmp, DrvGfxROM0); + + memcpy (tmp, DrvGfxROM1, 0x200000); + + GfxDecode(0x4000, 4, 16, 16, Plane1, XOffs1, YOffs, 0x200, tmp, DrvGfxROM1); + + memcpy (tmp, DrvGfxROM2, 0x080000); + + GfxDecode(0x1000, 4, 16, 16, Plane2, XOffs1, YOffs, 0x200, tmp, DrvGfxROM2); + + BurnFree (tmp); + + return 0; +} + +static INT32 DrvInit() +{ + AllMem = NULL; + MemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(); + + { + if (strcmp(BurnDrvGetTextA(DRV_NAME), "wwfsstara") == 0) { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x020000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 6, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1c0000, 11, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 13, 1)) return 1; + } else { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x000000, 3, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x020000, 4, 1)) return 1; + if (BurnLoadRom(DrvSndROM + 0x030000, 5, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 6, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x010000, 8, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x020000, 9, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x030000, 10, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x040000, 11, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x050000, 12, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x060000, 13, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x070000, 14, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x080000, 15, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x090000, 16, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 17, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0b0000, 18, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 19, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0d0000, 20, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 21, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x0f0000, 22, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x100000, 23, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x110000, 24, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x120000, 25, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x130000, 26, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x140000, 27, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x150000, 28, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x160000, 29, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x170000, 30, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x180000, 31, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x190000, 32, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1a0000, 33, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1b0000, 34, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1c0000, 35, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1d0000, 36, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1e0000, 37, 1)) return 1; + if (BurnLoadRom(DrvGfxROM1 + 0x1f0000, 38, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 39, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x010000, 40, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x020000, 41, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x030000, 42, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x040000, 43, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x050000, 44, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x060000, 45, 1)) return 1; + if (BurnLoadRom(DrvGfxROM2 + 0x070000, 46, 1)) return 1; + } + + DrvGfxDecode(); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvFgRAM, 0x080000, 0x080fff, SM_RAM); + SekMapMemory(DrvBgRAM, 0x0c0000, 0x0c0fff, SM_RAM); + SekMapMemory(DrvSprRAM, 0x100000, 0x1003ff, SM_RAM); + SekMapMemory(DrvPalRAM, 0x140000, 0x140fff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x1c0000, 0x1c3fff, SM_RAM); + SekSetReadWordHandler(0, wwfsstar_main_read_word); + SekSetReadByteHandler(0, wwfsstar_main_read_byte); + SekSetWriteWordHandler(0, wwfsstar_main_write_word); + SekSetWriteByteHandler(0, wwfsstar_main_write_byte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM); + ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM); + ZetSetWriteHandler(wwfsstar_sound_write); + ZetSetReadHandler(wwfsstar_sound_read); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(3579545, 45.0); + BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler); + + MSM6295Init(0, 1056000 / 132, 47.0, 1); + + DrvDoReset(); + + GenericTilesInit(); + + return 0; +} + +static INT32 DrvExit() +{ + GenericTilesExit(); + + SekExit(); + ZetExit(); + + MSM6295Exit(0); + BurnYM2151Exit(); + + BurnFree (AllMem); + + return 0; +} + +static void draw_fg_layer() +{ + UINT16 *vram = (UINT16*)DrvFgRAM; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 sx = (offs & 0x1f) << 3; + INT32 sy = (offs >> 5) << 3; + + INT32 attr = vram[(offs * 2) + 0]; + INT32 code = (vram[(offs * 2) + 1] & 0xff) | ((attr & 0x0f) << 8); + INT32 color = (attr & 0xf0) >> 4; + + if (*flipscreen) { + sy = (sy ^ 0xf8) - 16; + sx = sx ^ 0xf8; + + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM0); + } + } +} + +static void draw_bg_layer() +{ + UINT16 *vram = (UINT16*)DrvBgRAM; + + for (INT32 offs = 0; offs < 32 * 32; offs++) + { + INT32 row = offs >> 5; + INT32 col = offs & 0x1f; + + INT32 sx = col << 4; + INT32 sy = row << 4; + + sx -= scroll[0]; + if (sx < -15) sx += 512; + sy -= scroll[1]; + if (sy < -15) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 ofst = (col & 0x0f) | ((row & 0x0f) << 4) | ((col & 0x10) << 4) | ((row & 0x10) << 5); + + INT32 attr = vram[(ofst * 2) + 0]; + INT32 code = (vram[(ofst * 2) + 1] & 0xff) | ((attr & 0x0f) << 8); + INT32 color = (attr & 0x70) >> 4; + INT32 flipx = attr & 0x80; + + if (*flipscreen) { + sy = (240 - sy) - 16; + sx = 240 - sx; + + if (flipx) { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, DrvGfxROM2); // 0 transparent? + } else { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, DrvGfxROM2); // 0 transparent? + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, DrvGfxROM2); // 0 transparent? + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0x100, DrvGfxROM2); // 0 transparent? + } + } + } +} + +static void draw_sprites() +{ + UINT16 *source = (UINT16*)DrvSprRAM; + UINT16 *finish = source + 0x3ff / 2; + + while (source < finish) + { + if (source[1] & 0x0001) + { + INT32 ypos = (source[0] & 0xff) | ((source[1] & 0x04) << 6); + INT32 xpos = (source[4] & 0xff) | ((source[1] & 0x08) << 5); + INT32 flipx = (source[2] & 0x80 ) >> 7; + INT32 flipy = (source[2] & 0x40 ) >> 6; + INT32 chain = (source[1] & 0x02 ) >> 1; + INT32 number = (source[3] & 0xff) | ((source[2] & 0x3f) << 8); + INT32 color = ((source[1] & 0xf0) + 0x80) >> 4; + + ypos = (((256 - ypos) & 0x1ff) - 16) ; + xpos = (((256 - xpos) & 0x1ff) - 16); + chain += 1; + number &= ~(chain - 1); + + if (*flipscreen) + { + flipy = !flipy; + flipx = !flipx; + ypos = 240 - ypos; + xpos = 240 - xpos; + ypos -= 16; + } + + for (INT32 count = 0; count < chain; count++) + { + INT32 yy = ypos; + + if (*flipscreen) { + if (flipy) { + yy += (16*(chain-1))-(16*count); + } else { + yy += 16 * count; + } + } else { + if (flipy) { + yy -= 16 * count; + } else { + yy -= (16*(chain-1))-(16*count); + } + } + + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, number+count, xpos, yy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, number+count, xpos, yy, color, 4, 0, 0, DrvGfxROM1); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, number+count, xpos, yy, color, 4, 0, 0, DrvGfxROM1); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, number+count, xpos, yy, color, 4, 0, 0, DrvGfxROM1); + } + } + } + } + + source+=5; + } +} + +static void DrvPaletteRecalculate() +{ + UINT8 r,g,b; + UINT16 *p = (UINT16*)DrvPalRAM; + for (INT32 i = 0; i < 0x180; i++) { + r = (p[i] >> 0) & 0x0f; + b = (p[i] >> 8) & 0x0f; + g = (p[i] >> 4) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + DrvPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static INT32 DrvDraw() +{ + DrvPaletteRecalculate(); + + draw_bg_layer(); + + draw_sprites(); + + draw_fg_layer(); + + BurnTransferCopy(DrvPalette); + + return 0; +} + +static inline void interrupt(INT32 scanline) +{ + if (scanline == 0) vblank = 0; + if (scanline == (240-1)) vblank = 1; + if ((scanline & 0x0f) == 0) SekSetIRQLine(5, SEK_IRQSTATUS_ACK); + if (scanline == 240) SekSetIRQLine(6, SEK_IRQSTATUS_ACK); +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + { + memset (DrvInputs, 0xff, 3 * sizeof(INT16)); + for (INT32 i = 0; i < 16; i++) { + DrvInputs[0] ^= DrvJoy1[i] << i; + DrvInputs[1] ^= DrvJoy2[i] << i; + DrvInputs[2] ^= DrvJoy3[i] << i; + } + } + + INT32 nInterleave = 256; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 10000000 / 60, 3579545 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + SekOpen(0); + ZetOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nSegment; + + nSegment = nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nSegment); + if (i >= 8 && i <= 248) interrupt(i - 8); + + nSegment = nCyclesTotal[1] / nInterleave; + nCyclesDone[1] += ZetRun(nSegment); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0,pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0,pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029706; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd-AllRam; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + SCAN_VAR(vblank); + } + + return 0; +} + + +// WWF Superstars (Europe) + +static struct BurnRomInfo wwfsstarRomDesc[] = { + { "24ac-0_j-1.34", 0x20000, 0xec8fd2c9, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "24ad-0_j-1.35", 0x20000, 0x54e614e4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b.12", 0x08000, 0x1e44f8aa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "24a9.46", 0x20000, 0x703ff08f, 3 | BRF_SND }, // 3 oki + { "wwfs03.bin", 0x10000, 0x8a35a20e, 3 | BRF_SND }, // 4 + { "wwfs05.bin", 0x10000, 0x6df08962, 3 | BRF_SND }, // 5 + + { "24a4-0.58", 0x20000, 0xcb12ba40, 4 | BRF_GRA | BRF_NODUMP }, // 6 Characters + + { "wwfs39.bin", 0x10000, 0xd807b09a, 5 | BRF_GRA }, // 7 Sprites + { "wwfs38.bin", 0x10000, 0xd8ea94d3, 5 | BRF_GRA }, // 8 + { "wwfs37.bin", 0x10000, 0x5e8d7407, 5 | BRF_GRA }, // 9 + { "wwfs36.bin", 0x10000, 0x9005e942, 5 | BRF_GRA }, // 10 + { "wwfs43.bin", 0x10000, 0xaafc4a38, 5 | BRF_GRA }, // 11 + { "wwfs42.bin", 0x10000, 0xe48b88fb, 5 | BRF_GRA }, // 12 + { "wwfs41.bin", 0x10000, 0xed7f69d5, 5 | BRF_GRA }, // 13 + { "wwfs40.bin", 0x10000, 0x4d75fd89, 5 | BRF_GRA }, // 14 + { "wwfs19.bin", 0x10000, 0x7426d444, 5 | BRF_GRA }, // 15 + { "wwfs18.bin", 0x10000, 0xaf11ad2a, 5 | BRF_GRA }, // 16 + { "wwfs17.bin", 0x10000, 0xef12069f, 5 | BRF_GRA }, // 17 + { "wwfs16.bin", 0x10000, 0x08343e7f, 5 | BRF_GRA }, // 18 + { "wwfs15.bin", 0x10000, 0xaac5a928, 5 | BRF_GRA }, // 19 + { "wwfs14.bin", 0x10000, 0x67eb7bea, 5 | BRF_GRA }, // 20 + { "wwfs13.bin", 0x10000, 0x970b6e76, 5 | BRF_GRA }, // 21 + { "wwfs12.bin", 0x10000, 0x242caff5, 5 | BRF_GRA }, // 22 + { "wwfs27.bin", 0x10000, 0xf3eb8ab9, 5 | BRF_GRA }, // 23 + { "wwfs26.bin", 0x10000, 0x2ca91eaf, 5 | BRF_GRA }, // 24 + { "wwfs25.bin", 0x10000, 0xbbf69c6a, 5 | BRF_GRA }, // 25 + { "wwfs24.bin", 0x10000, 0x76b08bcd, 5 | BRF_GRA }, // 26 + { "wwfs23.bin", 0x10000, 0x681f5b5e, 5 | BRF_GRA }, // 27 + { "wwfs22.bin", 0x10000, 0x81fe1bf7, 5 | BRF_GRA }, // 28 + { "wwfs21.bin", 0x10000, 0xc52eee5e, 5 | BRF_GRA }, // 29 + { "wwfs20.bin", 0x10000, 0xb2a8050e, 5 | BRF_GRA }, // 30 + { "wwfs35.bin", 0x10000, 0x9d648d82, 5 | BRF_GRA }, // 31 + { "wwfs34.bin", 0x10000, 0x742a79db, 5 | BRF_GRA }, // 32 + { "wwfs33.bin", 0x10000, 0xf6923db6, 5 | BRF_GRA }, // 33 + { "wwfs32.bin", 0x10000, 0x9becd621, 5 | BRF_GRA }, // 34 + { "wwfs31.bin", 0x10000, 0xf94c74d5, 5 | BRF_GRA }, // 35 + { "wwfs30.bin", 0x10000, 0x94094518, 5 | BRF_GRA }, // 36 + { "wwfs29.bin", 0x10000, 0x7b5b9d83, 5 | BRF_GRA }, // 37 + { "wwfs28.bin", 0x10000, 0x70fda626, 5 | BRF_GRA }, // 38 + + { "wwfs51.bin", 0x10000, 0x51157385, 6 | BRF_GRA }, // 39 Tiles + { "wwfs50.bin", 0x10000, 0x7fc79df5, 6 | BRF_GRA }, // 40 + { "wwfs49.bin", 0x10000, 0xa14076b0, 6 | BRF_GRA }, // 41 + { "wwfs48.bin", 0x10000, 0x251372fd, 6 | BRF_GRA }, // 42 + { "wwfs47.bin", 0x10000, 0x6fd7b6ea, 6 | BRF_GRA }, // 43 + { "wwfs46.bin", 0x10000, 0x985e5180, 6 | BRF_GRA }, // 44 + { "wwfs45.bin", 0x10000, 0xb2fad792, 6 | BRF_GRA }, // 45 + { "wwfs44.bin", 0x10000, 0x4f965fa9, 6 | BRF_GRA }, // 46 +}; + +STD_ROM_PICK(wwfsstar) +STD_ROM_FN(wwfsstar) + +struct BurnDriver BurnDrvWwfsstar = { + "wwfsstar", NULL, NULL, NULL, "1989", + "WWF Superstars (Europe)\0", NULL, "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, wwfsstarRomInfo, wwfsstarRomName, NULL, NULL, WwfsstarInputInfo, WwfsstarDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x180, + 256, 240, 4, 3 +}; + + +// WWF Superstars (US) + +static struct BurnRomInfo wwfsstaruRomDesc[] = { + { "24ac-04.34", 0x20000, 0xee9b850e, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "24ad-04.35", 0x20000, 0x057c2eef, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "b.12", 0x08000, 0x1e44f8aa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "24a9.46", 0x20000, 0x703ff08f, 3 | BRF_SND }, // 3 oki + { "wwfs03.bin", 0x10000, 0x8a35a20e, 3 | BRF_SND }, // 4 + { "wwfs05.bin", 0x10000, 0x6df08962, 3 | BRF_SND }, // 5 + + { "24a4-0.58", 0x20000, 0xcb12ba40, 4 | BRF_GRA }, // 6 Characters + + { "wwfs39.bin", 0x10000, 0xd807b09a, 5 | BRF_GRA }, // 7 Sprites + { "wwfs38.bin", 0x10000, 0xd8ea94d3, 5 | BRF_GRA }, // 8 + { "wwfs37.bin", 0x10000, 0x5e8d7407, 5 | BRF_GRA }, // 9 + { "wwfs36.bin", 0x10000, 0x9005e942, 5 | BRF_GRA }, // 10 + { "wwfs43.bin", 0x10000, 0xaafc4a38, 5 | BRF_GRA }, // 11 + { "wwfs42.bin", 0x10000, 0xe48b88fb, 5 | BRF_GRA }, // 12 + { "wwfs41.bin", 0x10000, 0xed7f69d5, 5 | BRF_GRA }, // 13 + { "wwfs40.bin", 0x10000, 0x4d75fd89, 5 | BRF_GRA }, // 14 + { "wwfs19.bin", 0x10000, 0x7426d444, 5 | BRF_GRA }, // 15 + { "wwfs18.bin", 0x10000, 0xaf11ad2a, 5 | BRF_GRA }, // 16 + { "wwfs17.bin", 0x10000, 0xef12069f, 5 | BRF_GRA }, // 17 + { "wwfs16.bin", 0x10000, 0x08343e7f, 5 | BRF_GRA }, // 18 + { "wwfs15.bin", 0x10000, 0xaac5a928, 5 | BRF_GRA }, // 19 + { "wwfs14.bin", 0x10000, 0x67eb7bea, 5 | BRF_GRA }, // 20 + { "wwfs13.bin", 0x10000, 0x970b6e76, 5 | BRF_GRA }, // 21 + { "wwfs12.bin", 0x10000, 0x242caff5, 5 | BRF_GRA }, // 22 + { "wwfs27.bin", 0x10000, 0xf3eb8ab9, 5 | BRF_GRA }, // 23 + { "wwfs26.bin", 0x10000, 0x2ca91eaf, 5 | BRF_GRA }, // 24 + { "wwfs25.bin", 0x10000, 0xbbf69c6a, 5 | BRF_GRA }, // 25 + { "wwfs24.bin", 0x10000, 0x76b08bcd, 5 | BRF_GRA }, // 26 + { "wwfs23.bin", 0x10000, 0x681f5b5e, 5 | BRF_GRA }, // 27 + { "wwfs22.bin", 0x10000, 0x81fe1bf7, 5 | BRF_GRA }, // 28 + { "wwfs21.bin", 0x10000, 0xc52eee5e, 5 | BRF_GRA }, // 29 + { "wwfs20.bin", 0x10000, 0xb2a8050e, 5 | BRF_GRA }, // 30 + { "wwfs35.bin", 0x10000, 0x9d648d82, 5 | BRF_GRA }, // 31 + { "wwfs34.bin", 0x10000, 0x742a79db, 5 | BRF_GRA }, // 32 + { "wwfs33.bin", 0x10000, 0xf6923db6, 5 | BRF_GRA }, // 33 + { "wwfs32.bin", 0x10000, 0x9becd621, 5 | BRF_GRA }, // 34 + { "wwfs31.bin", 0x10000, 0xf94c74d5, 5 | BRF_GRA }, // 35 + { "wwfs30.bin", 0x10000, 0x94094518, 5 | BRF_GRA }, // 36 + { "wwfs29.bin", 0x10000, 0x7b5b9d83, 5 | BRF_GRA }, // 37 + { "wwfs28.bin", 0x10000, 0x70fda626, 5 | BRF_GRA }, // 38 + + { "wwfs51.bin", 0x10000, 0x51157385, 6 | BRF_GRA }, // 39 Tiles + { "wwfs50.bin", 0x10000, 0x7fc79df5, 6 | BRF_GRA }, // 40 + { "wwfs49.bin", 0x10000, 0xa14076b0, 6 | BRF_GRA }, // 41 + { "wwfs48.bin", 0x10000, 0x251372fd, 6 | BRF_GRA }, // 42 + { "wwfs47.bin", 0x10000, 0x6fd7b6ea, 6 | BRF_GRA }, // 43 + { "wwfs46.bin", 0x10000, 0x985e5180, 6 | BRF_GRA }, // 44 + { "wwfs45.bin", 0x10000, 0xb2fad792, 6 | BRF_GRA }, // 45 + { "wwfs44.bin", 0x10000, 0x4f965fa9, 6 | BRF_GRA }, // 46 +}; + +STD_ROM_PICK(wwfsstaru) +STD_ROM_FN(wwfsstaru) + +struct BurnDriver BurnDrvWwfsstaru = { + "wwfsstaru", "wwfsstar", NULL, NULL, "1989", + "WWF Superstars (US)\0", NULL, "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, wwfsstaruRomInfo, wwfsstaruRomName, NULL, NULL, WwfsstarInputInfo, WwfsstarDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x180, + 256, 240, 4, 3 +}; + + +// WWF Superstars (US, Newer) + +static struct BurnRomInfo wwfsstaraRomDesc[] = { + { "24ac-06.34", 0x20000, 0x924a50e4, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "24ad-07.35", 0x20000, 0x9a76a50e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "24ab-0.12", 0x08000, 0x1e44f8aa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "24a9-0.46", 0x20000, 0x703ff08f, 3 | BRF_SND }, // 3 oki + { "24j8-0.45", 0x20000, 0x61138487, 3 | BRF_SND }, // 4 + + { "24aa-0.58", 0x20000, 0xcb12ba40, 4 | BRF_GRA }, // 5 Characters + + { "c951.114", 0x80000, 0xfa76d1f0, 5 | BRF_GRA }, // 6 Sprites + { "24j4-0.115", 0x40000, 0xc4a589a3, 5 | BRF_GRA }, // 7 + { "24j5-0.116", 0x40000, 0xd6bca436, 5 | BRF_GRA }, // 8 + { "c950.117", 0x80000, 0xcca5703d, 5 | BRF_GRA }, // 9 + { "24j2-0.118", 0x40000, 0xdc1b7600, 5 | BRF_GRA }, // 10 + { "24j3-0.119", 0x40000, 0x3ba12d43, 5 | BRF_GRA }, // 11 + + { "24j7-0.113", 0x40000, 0xe0a1909e, 6 | BRF_GRA }, // 12 Tiles + { "24j6-0.112", 0x40000, 0x77932ef8, 6 | BRF_GRA }, // 13 +}; + +STD_ROM_PICK(wwfsstara) +STD_ROM_FN(wwfsstara) + +struct BurnDriver BurnDrvWwfsstara = { + "wwfsstara", "wwfsstar", NULL, NULL, "1989", + "WWF Superstars (US, Newer)\0", NULL, "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, wwfsstaraRomInfo, wwfsstaraRomName, NULL, NULL, WwfsstarInputInfo, WwfsstarDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x180, + 256, 240, 4, 3 +}; + + +// WWF Superstars (Japan) + +static struct BurnRomInfo wwfsstarjRomDesc[] = { + { "24ac-0_j-1_japan.34",0x20000, 0xf872e968, 1 | BRF_PRG | BRF_ESS }, // 0 68k Code + { "24ad-0_j-1_japan.35",0x20000, 0x00000000, 1 | BRF_PRG | BRF_ESS | BRF_NODUMP }, // 1 + + { "b.12", 0x08000, 0x1e44f8aa, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code + + { "24a9.46", 0x20000, 0x703ff08f, 3 | BRF_SND }, // 3 oki + { "wwfs03.bin", 0x10000, 0x8a35a20e, 3 | BRF_SND }, // 4 + { "wwfs05.bin", 0x10000, 0x6df08962, 3 | BRF_SND }, // 5 + + { "24a4-0.58", 0x20000, 0xcb12ba40, 4 | BRF_GRA }, // 6 Characters + + { "wwfs39.bin", 0x10000, 0xd807b09a, 5 | BRF_GRA }, // 7 Sprites + { "wwfs38.bin", 0x10000, 0xd8ea94d3, 5 | BRF_GRA }, // 8 + { "wwfs37.bin", 0x10000, 0x5e8d7407, 5 | BRF_GRA }, // 9 + { "wwfs36.bin", 0x10000, 0x9005e942, 5 | BRF_GRA }, // 10 + { "wwfs43.bin", 0x10000, 0xaafc4a38, 5 | BRF_GRA }, // 11 + { "wwfs42.bin", 0x10000, 0xe48b88fb, 5 | BRF_GRA }, // 12 + { "wwfs41.bin", 0x10000, 0xed7f69d5, 5 | BRF_GRA }, // 13 + { "wwfs40.bin", 0x10000, 0x4d75fd89, 5 | BRF_GRA }, // 14 + { "wwfs19.bin", 0x10000, 0x7426d444, 5 | BRF_GRA }, // 15 + { "wwfs18.bin", 0x10000, 0xaf11ad2a, 5 | BRF_GRA }, // 16 + { "wwfs17.bin", 0x10000, 0xef12069f, 5 | BRF_GRA }, // 17 + { "wwfs16.bin", 0x10000, 0x08343e7f, 5 | BRF_GRA }, // 18 + { "wwfs15.bin", 0x10000, 0xaac5a928, 5 | BRF_GRA }, // 19 + { "wwfs14.bin", 0x10000, 0x67eb7bea, 5 | BRF_GRA }, // 20 + { "wwfs13.bin", 0x10000, 0x970b6e76, 5 | BRF_GRA }, // 21 + { "wwfs12.bin", 0x10000, 0x242caff5, 5 | BRF_GRA }, // 22 + { "wwfs27.bin", 0x10000, 0xf3eb8ab9, 5 | BRF_GRA }, // 23 + { "wwfs26.bin", 0x10000, 0x2ca91eaf, 5 | BRF_GRA }, // 24 + { "wwfs25.bin", 0x10000, 0xbbf69c6a, 5 | BRF_GRA }, // 25 + { "wwfs24.bin", 0x10000, 0x76b08bcd, 5 | BRF_GRA }, // 26 + { "wwfs23.bin", 0x10000, 0x681f5b5e, 5 | BRF_GRA }, // 27 + { "wwfs22.bin", 0x10000, 0x81fe1bf7, 5 | BRF_GRA }, // 28 + { "wwfs21.bin", 0x10000, 0xc52eee5e, 5 | BRF_GRA }, // 29 + { "wwfs20.bin", 0x10000, 0xb2a8050e, 5 | BRF_GRA }, // 30 + { "wwfs35.bin", 0x10000, 0x9d648d82, 5 | BRF_GRA }, // 31 + { "wwfs34.bin", 0x10000, 0x742a79db, 5 | BRF_GRA }, // 32 + { "wwfs33.bin", 0x10000, 0xf6923db6, 5 | BRF_GRA }, // 33 + { "wwfs32.bin", 0x10000, 0x9becd621, 5 | BRF_GRA }, // 34 + { "wwfs31.bin", 0x10000, 0xf94c74d5, 5 | BRF_GRA }, // 35 + { "wwfs30.bin", 0x10000, 0x94094518, 5 | BRF_GRA }, // 36 + { "wwfs29.bin", 0x10000, 0x7b5b9d83, 5 | BRF_GRA }, // 37 + { "wwfs28.bin", 0x10000, 0x70fda626, 5 | BRF_GRA }, // 38 + + { "wwfs51.bin", 0x10000, 0x51157385, 6 | BRF_GRA }, // 39 Tiles + { "wwfs50.bin", 0x10000, 0x7fc79df5, 6 | BRF_GRA }, // 40 + { "wwfs49.bin", 0x10000, 0xa14076b0, 6 | BRF_GRA }, // 41 + { "wwfs48.bin", 0x10000, 0x251372fd, 6 | BRF_GRA }, // 42 + { "wwfs47.bin", 0x10000, 0x6fd7b6ea, 6 | BRF_GRA }, // 43 + { "wwfs46.bin", 0x10000, 0x985e5180, 6 | BRF_GRA }, // 44 + { "wwfs45.bin", 0x10000, 0xb2fad792, 6 | BRF_GRA }, // 45 + { "wwfs44.bin", 0x10000, 0x4f965fa9, 6 | BRF_GRA }, // 46 +}; + +STD_ROM_PICK(wwfsstarj) +STD_ROM_FN(wwfsstarj) + +struct BurnDriverD BurnDrvWwfsstarj = { + "wwfsstarj", "wwfsstar", NULL, NULL, "1989", + "WWF Superstars (Japan)\0", "Missing program ROM", "Technos Japan", "Miscellaneous", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0, + NULL, wwfsstarjRomInfo, wwfsstarjRomName, NULL, NULL, WwfsstarInputInfo, WwfsstarDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x180, + 256, 240, 4, 3 +}; diff --git a/src/burn/drivers/misc_pre90s/tnzs_prot.cpp b/src/burn/drivers/misc_pre90s/tnzs_prot.cpp new file mode 100644 index 00000000..60975778 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/tnzs_prot.cpp @@ -0,0 +1,465 @@ +// The New Zealand Story protection module +// Based on MAME version 0.67 mcu simulation + +#include "burnint.h" +#include "tnzs_prot.h" + +#define UNLOCK 0x0f +#define LOCK 0x0c + +static INT32 mcu_type; + +static INT32 mcu_initializing; +static INT32 mcu_coinage_init; +static INT32 mcu_command,mcu_readcredits; +static INT32 mcu_reportcoin; +static UINT8 mcu_coinage[4]; +static UINT8 mcu_coinsA; +static UINT8 mcu_coinsB; +static UINT8 mcu_credits; +static UINT8 mcu_coin_lockout; + +UINT8 *tnzs_mcu_inputs; + +void tnzs_mcu_reset() +{ + mcu_initializing = 3; + mcu_coinage_init = 0; + mcu_coinage[0] = 1; + mcu_coinage[1] = 1; + mcu_coinage[2] = 1; + mcu_coinage[3] = 1; + mcu_coinsA = 0; + mcu_coinsB = 0; + mcu_credits = 0; + mcu_reportcoin = 0; + mcu_command = 0; + mcu_coin_lockout = LOCK; +} + +void tnzs_mcu_init(INT32 type) +{ + tnzs_mcu_reset(); + mcu_type = type; +} + +static void mcu_handle_coins(INT32 coin) +{ + static INT32 insertcoin; + + if (coin & 0x08) + mcu_reportcoin = coin; + else if (coin && coin != insertcoin) + { + if (coin & 0x01) + { + mcu_coinsA++; + if (mcu_coinsA >= mcu_coinage[0]) + { + mcu_coinsA -= mcu_coinage[0]; + mcu_credits += mcu_coinage[1]; + if (mcu_credits >= 9) + { + mcu_credits = 9; + mcu_coin_lockout = LOCK; + } + else + { + mcu_coin_lockout = UNLOCK; + } + } + } + if (coin & 0x02) + { + mcu_coinsB++; + if (mcu_coinsB >= mcu_coinage[2]) + { + mcu_coinsB -= mcu_coinage[2]; + mcu_credits += mcu_coinage[3]; + if (mcu_credits >= 9) + { + mcu_credits = 9; + mcu_coin_lockout = LOCK; + } + else + { + mcu_coin_lockout = UNLOCK; + } + } + } + if (coin & 0x04) + { + mcu_credits++; + } + mcu_reportcoin = coin; + } + else + { + if (mcu_credits < 9) + mcu_coin_lockout = UNLOCK; + mcu_reportcoin = 0; + } + insertcoin = coin; +} + +static UINT8 mcu_arknoid2_r(INT32 offset) +{ + const char *mcu_startup = "\x55\xaa\x5a"; + + if (offset == 0) + { + if (mcu_initializing) + { + mcu_initializing--; + return mcu_startup[2 - mcu_initializing]; + } + + switch (mcu_command) + { + case 0x41: + return mcu_credits; + + case 0xc1: + if (mcu_readcredits == 0) + { + mcu_readcredits = 1; + if (mcu_reportcoin & 0x08) + { + mcu_initializing = 3; + return 0xee; + } + else return mcu_credits; + } + else return tnzs_mcu_inputs[0]; + + default: + return 0xff; + break; + } + } + else + { + if (mcu_reportcoin & 0x08) return 0xe1; + if (mcu_reportcoin & 0x01) return 0x11; + if (mcu_reportcoin & 0x02) return 0x21; + if (mcu_reportcoin & 0x04) return 0x31; + return 0x01; + } +} + +static void mcu_arknoid2_w(INT32 offset, INT32 data) +{ + if (offset == 0) + { + if (mcu_command == 0x41) + { + mcu_credits = (mcu_credits + data) & 0xff; + } + } + else + { + if (mcu_initializing) + { + mcu_coinage[mcu_coinage_init++] = data; + if (mcu_coinage_init == 4) mcu_coinage_init = 0; + } + + if (data == 0xc1) + mcu_readcredits = 0; + + if (data == 0x15) + mcu_credits = (mcu_credits - 1) & 0xff; + + mcu_command = data; + } +} + +static UINT8 mcu_chukatai_r(INT32 offset) +{ + const char *mcu_startup = "\xa5\x5a\xaa"; + + if (offset == 0) + { + if (mcu_initializing) + { + mcu_initializing--; + return mcu_startup[2 - mcu_initializing]; + } + + switch (mcu_command) + { + case 0x1f: + return (tnzs_mcu_inputs[2] >> 4) ^ 0x0f; + + case 0x03: + return tnzs_mcu_inputs[2] & 0x0f; + + case 0x41: + return mcu_credits; + + case 0x93: + if (mcu_readcredits == 0) + { + mcu_readcredits += 1; + if (mcu_reportcoin & 0x08) + { + mcu_initializing = 3; + return 0xee; + } + else return mcu_credits; + } + + if (mcu_readcredits == 1) + { + mcu_readcredits += 1; + return tnzs_mcu_inputs[0]; + } + + if (mcu_readcredits == 2) + { + return tnzs_mcu_inputs[1]; + } + + default: + return 0xff; + break; + } + } + else + { + if (mcu_reportcoin & 0x08) return 0xe1; + if (mcu_reportcoin & 0x01) return 0x11; + if (mcu_reportcoin & 0x02) return 0x21; + if (mcu_reportcoin & 0x04) return 0x31; + return 0x01; + } +} + +static void mcu_chukatai_w(INT32 offset, INT32 data) +{ + if (offset == 0) + { + if (mcu_command == 0x41) + { + mcu_credits = (mcu_credits + data) & 0xff; + } + } + else + { + if (mcu_initializing) + { + mcu_coinage[mcu_coinage_init++] = data; + if (mcu_coinage_init == 4) mcu_coinage_init = 0; + } + + if (data == 0x93) + mcu_readcredits = 0; + + mcu_command = data; + } +} + +static UINT8 mcu_tnzs_r(INT32 offset) +{ + const char *mcu_startup = "\x5a\xa5\x55"; + + if (offset == 0) + { + if (mcu_initializing) + { + mcu_initializing--; + return mcu_startup[2 - mcu_initializing]; + } + + switch (mcu_command) + { + case 0x01: + return ~tnzs_mcu_inputs[0]; + + case 0x02: + return ~tnzs_mcu_inputs[1]; + + case 0x1a: + if (mcu_type == MCU_DRTOPPEL) return (tnzs_mcu_inputs[2] >> 2) ^ 0x03; + return tnzs_mcu_inputs[2] >> 4; + + case 0x21: + return tnzs_mcu_inputs[2] & 0x0f; + + case 0x41: + return mcu_credits; + + case 0xa0: + if (mcu_reportcoin & 0x08) + { + mcu_initializing = 3; + return 0xee; + } + else return mcu_credits; + + case 0xa1: + if (mcu_readcredits == 0) + { + mcu_readcredits = 1; + if (mcu_reportcoin & 0x08) + { + mcu_initializing = 3; + return 0xee; + } + else return mcu_credits; + } + else + return ~((tnzs_mcu_inputs[0] & 0xf0) | (tnzs_mcu_inputs[1] & 0x0f)); + + default: + return 0xff; + break; + } + } + else + { + if (mcu_reportcoin & 0x08) return 0xe1; + + if (mcu_type == MCU_TNZS) + { + if (mcu_reportcoin & 0x01) return 0x31; + if (mcu_reportcoin & 0x02) return 0x21; + if (mcu_reportcoin & 0x04) return 0x11; + } + else + { + if (mcu_reportcoin & 0x01) return 0x11; + if (mcu_reportcoin & 0x02) return 0x21; + if (mcu_reportcoin & 0x04) return 0x31; + } + return 0x01; + } +} + +static void mcu_tnzs_w(INT32 offset, INT32 data) +{ + if (offset == 0) { + if (mcu_command == 0x41) { + mcu_credits = (mcu_credits + data) & 0xff; + } + } + else + { + if (mcu_initializing) + { + mcu_coinage[mcu_coinage_init++] = data; + if (mcu_coinage_init == 4) mcu_coinage_init = 0; + } + + if (data == 0xa1) + mcu_readcredits = 0; + + if ((data == 0x09) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP)) + mcu_credits = (mcu_credits - 1) & 0xff; + + if ((data == 0x18) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP)) + mcu_credits = (mcu_credits - 2) & 0xff; + + mcu_command = data; + } +} + +UINT8 tnzs_mcu_read(INT32 offset) +{ + switch (mcu_type) + { + case MCU_ARKANOID: + return mcu_arknoid2_r(offset & 1); + break; + + case MCU_CHUKATAI: + return mcu_chukatai_r(offset & 1); + break; + + case MCU_EXTRMATN: + case MCU_DRTOPPEL: + case MCU_TNZS: + case MCU_PLUMPOP: + return mcu_tnzs_r(offset & 1); + break; + + case MCU_NONE_INSECTX: + case MCU_NONE_KAGEKI: + case MCU_NONE_JPOPNICS: + case MCU_NONE: + return tnzs_mcu_inputs[offset & 1]; + break; + } + + return 0xff; +} + +void tnzs_mcu_write(INT32 offset, INT32 data) +{ + switch (mcu_type) + { + case MCU_ARKANOID: + mcu_arknoid2_w(offset & 1, data); + break; + + case MCU_CHUKATAI: + mcu_chukatai_w(offset & 1, data); + break; + + case MCU_EXTRMATN: + case MCU_DRTOPPEL: + case MCU_TNZS: + case MCU_PLUMPOP: + mcu_tnzs_w(offset & 1, data); + break; + } +} + +void tnzs_mcu_interrupt() +{ + INT32 coin; + + switch (mcu_type) + { + case MCU_ARKANOID: + coin = (~tnzs_mcu_inputs[1] >> 4) & 0x0f; + coin = (coin & 0x08) | ((coin & 0x03) << 1) | ((coin & 0x04) >> 2); + coin &= mcu_coin_lockout; + mcu_handle_coins(coin); + break; + + case MCU_EXTRMATN: + case MCU_DRTOPPEL: + case MCU_PLUMPOP: + case MCU_CHUKATAI: + case MCU_TNZS: + coin = (((~tnzs_mcu_inputs[2] & 0x30) >> 4) | ((~tnzs_mcu_inputs[2] & 0x03) << 2)); + coin &= mcu_coin_lockout; + mcu_handle_coins(coin); + break; + + case MCU_NONE: + break; + } +} + +INT32 tnzs_mcu_type() +{ + return mcu_type; +} + +void tnzs_mcu_scan() +{ + SCAN_VAR(mcu_initializing); + SCAN_VAR(mcu_coinage_init); + SCAN_VAR(mcu_coinage[0]); + SCAN_VAR(mcu_coinage[1]); + SCAN_VAR(mcu_coinage[2]); + SCAN_VAR(mcu_coinage[3]); + SCAN_VAR(mcu_coinsA); + SCAN_VAR(mcu_coinsB); + SCAN_VAR(mcu_credits); + SCAN_VAR(mcu_reportcoin); + SCAN_VAR(mcu_command); + SCAN_VAR(mcu_coin_lockout); +} diff --git a/src/burn/drivers/misc_pre90s/tnzs_prot.h b/src/burn/drivers/misc_pre90s/tnzs_prot.h new file mode 100644 index 00000000..4ccc2838 --- /dev/null +++ b/src/burn/drivers/misc_pre90s/tnzs_prot.h @@ -0,0 +1,100 @@ +enum +{ + MCU_NONE, + MCU_EXTRMATN, + MCU_ARKANOID, + MCU_DRTOPPEL, + MCU_CHUKATAI, + MCU_PLUMPOP, + MCU_TNZS, + MCU_NONE_INSECTX, + MCU_NONE_KAGEKI, + MCU_NONE_JPOPNICS +}; + +INT32 tnzs_mcu_type(); +void tnzs_mcu_reset(); +void tnzs_mcu_init(INT32 type); +void tnzs_mcu_interrupt(); +void tnzs_mcu_scan(); + +UINT8 tnzs_mcu_read(INT32 offset); +void tnzs_mcu_write(INT32 offset, INT32 data); + +extern UINT8 *tnzs_mcu_inputs; + +#define TNZS_DIFFICULTY_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 4, "Difficulty" }, \ + {dip, 0x01, 0x03, 0x02, "Easy" }, \ + {dip, 0x01, 0x03, 0x03, "Medium" }, \ + {dip, 0x01, 0x03, 0x01, "Hard" }, \ + {dip, 0x01, 0x03, 0x00, "Hardest" }, \ + +#define TNZS_LIVES_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 0, "Lives" }, \ + {dip, 0x01, 0x30, 0x20, "2" }, \ + {dip, 0x01, 0x30, 0x30, "3" }, \ + {dip, 0x01, 0x30, 0x10, "4" }, \ + {dip, 0x01, 0x30, 0x00, "5" }, \ + +#define TNZS_CABINET_FLIP_SERVICE_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 2, "Cabinet" }, \ + {dip, 0x01, 0x01, 0x00, "Upright" }, \ + {dip, 0x01, 0x01, 0x01, "Cocktail" }, \ + \ + {0 , 0xfe, 0 , 2, "Flip Screen" }, \ + {dip, 0x01, 0x02, 0x02, "Off" }, \ + {dip, 0x01, 0x02, 0x00, "On" }, \ + \ + {0 , 0xfe, 0 , 2, "Service Mode" }, \ + {dip, 0x01, 0x04, 0x04, "Off" }, \ + {dip, 0x01, 0x04, 0x00, "On" }, \ + +#define TNZS_DEMOSOUNDS_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 2, "Demo Sounds" }, \ + {dip, 0x01, 0x08, 0x00, "Off" }, \ + {dip, 0x01, 0x08, 0x08, "On" }, \ + +#define TNZS_ALLOWCONTINUE_DIPSETTING(dip, val) \ + {0 , 0xfe, 0 , 2, "Allow Continue" }, \ + {dip, 0x01, val, 0x00, "No" }, \ + {dip, 0x01, val, val, "Yes" }, \ + +// Type 1 is old-style +#define TNZS_COINA_TYPE1_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 4, "Coin A" }, \ + {dip, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, \ + {dip, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, \ + {dip, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, \ + {dip, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, \ + +#define TNZS_COINB_TYPE1_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 4, "Coin B" }, \ + {dip, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, \ + {dip, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, \ + {dip, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, \ + {dip, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, \ + +// Type 2 is new-style +#define TNZS_COINA_TYPE2_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 4, "Coin A" }, \ + {dip, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, \ + {dip, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, \ + {dip, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, \ + {dip, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, \ + +#define TNZS_COINB_TYPE2_DIPSETTING(dip) \ + {0 , 0xfe, 0 , 4, "Coin B" }, \ + {dip, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, \ + {dip, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, \ + {dip, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, \ + {dip, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, \ + + +#define TNZS_COINAGE_WORLD(dip) \ + TNZS_COINA_TYPE2_DIPSETTING(dip) \ + TNZS_COINB_TYPE2_DIPSETTING(dip) + +#define TNZS_COINAGE_JAPAN_OLD(dip) \ + TNZS_COINA_TYPE1_DIPSETTING(dip) \ + TNZS_COINB_TYPE1_DIPSETTING(dip) diff --git a/src/burn/drivers/neogeo/d_neogeo.cpp b/src/burn/drivers/neogeo/d_neogeo.cpp new file mode 100644 index 00000000..d17dfc24 --- /dev/null +++ b/src/burn/drivers/neogeo/d_neogeo.cpp @@ -0,0 +1,13918 @@ +// FB Alpha Neo Geo driver module + +#include "neogeo.h" +#include "bitswap.h" + +#if !defined ROM_VERIFY + // enable to match Neo Geo BIOS to MAME's (also affects dipswitches -- leaves only the MVS BIOS option) + // #define ROM_VERIFY +#endif + +static struct BurnRomInfo emptyRomDesc[] = { + { "", 0, 0, 0 }, +}; + +// ----------------------------------------------------------------------------- +// Common data + +static struct BurnInputInfo neogeoInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 +// {"P1 Coin 2", BIT_DIGITAL, NeoButton2 + 3, "p1 coin 2"}, + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 2 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 3 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 4 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 5 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 6 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 7 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 8 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 9 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, // A + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // B +// {"P2 Coin 2", BIT_DIGITAL, NeoButton2 + 4, "p2 coin 2"}, + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // C + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // D + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // E + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // F + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // 10 + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // 11 + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 12 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 13 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 14 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 15 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 16 + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 17 + {"Service", BIT_DIGITAL, NeoButton2 + 2, "service"}, // 18 + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // 19 + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // 1A + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 1B + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, // 1C + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 1D + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 1E +}; + +STDINPUTINFO(neogeo) + +static struct BurnInputInfo neoMVSInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 +// {"P1 Coin 2", BIT_DIGITAL, NeoButton2 + 3, "p1 coin 2"}, + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 2 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 3 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 4 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 5 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 6 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 7 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 8 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 9 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, // A + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // B +// {"P2 Coin 2", BIT_DIGITAL, NeoButton2 + 4, "p2 coin 2"}, + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // C + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // D + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // E + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // F + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // 10 + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // 11 + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 12 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 13 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 14 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 15 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 16 + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 17 + {"Service", BIT_DIGITAL, NeoButton2 + 2, "service"}, // 18 + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // 19 + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // 1A + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 1B + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 1C + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 1D +}; + +STDINPUTINFO(neoMVS) + +static struct BurnDIPInfo ms5pcbDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x86, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x0D, 0x01, 0x04, 0x00, "Off"}, + {0x0D, 0x01, 0x04, 0x04, "On"}, + + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x00, 0x01, 0x01, 0x00, "Off"}, + {0x00, 0x01, 0x01, 0x01, "On"}, + + // 1 or 2 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x02, 0x02, 0x00, "1"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x02, 0x02, 0x02, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + // 2 or 4 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x82, 0x02, 0x00, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x82, 0x02, 0x02, "4"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x00, 0x01, 0x38, 0x00, "Disabled"}, + {0x00, 0x01, 0x38, 0x08, "Setting 1"}, + {0x00, 0x01, 0x38, 0x10, "Setting 2"}, + {0x00, 0x01, 0x38, 0x18, "Setting 3"}, + {0x00, 0x01, 0x38, 0x20, "Setting 4"}, + {0x00, 0x01, 0x38, 0x28, "Setting 5"}, + {0x00, 0x01, 0x38, 0x30, "Setting 6"}, + {0x00, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x00, 0x01, 0x40, 0x00, "Off"}, + {0x00, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x00, 0x01, 0x80, 0x00, "Off"}, + {0x00, 0x01, 0x80, 0x80, "On"}, + + // Region + {0, 0xFD, 0, 2, "Region"}, + {0x02, 0x02, 0x03, 0x02, "Asia / Europe"}, + {0x02, 0x00, 0x30, 0x00, NULL}, + {0x02, 0x02, 0x03, 0x03, "Japan"}, + {0x02, 0x00, 0x30, 0x00, NULL}, +}; + +STDDIPINFO(ms5pcb) + +static struct BurnDIPInfo svcpcbDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x86, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x0D, 0x01, 0x04, 0x00, "Off"}, + {0x0D, 0x01, 0x04, 0x04, "On"}, + + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x00, 0x01, 0x01, 0x00, "Off"}, + {0x00, 0x01, 0x01, 0x01, "On"}, + + // 1 or 2 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x02, 0x02, 0x00, "1"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x02, 0x02, 0x02, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + // 2 or 4 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x82, 0x02, 0x00, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x82, 0x02, 0x02, "4"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x00, 0x01, 0x38, 0x00, "Disabled"}, + {0x00, 0x01, 0x38, 0x08, "Setting 1"}, + {0x00, 0x01, 0x38, 0x10, "Setting 2"}, + {0x00, 0x01, 0x38, 0x18, "Setting 3"}, + {0x00, 0x01, 0x38, 0x20, "Setting 4"}, + {0x00, 0x01, 0x38, 0x28, "Setting 5"}, + {0x00, 0x01, 0x38, 0x30, "Setting 6"}, + {0x00, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x00, 0x01, 0x40, 0x00, "Off"}, + {0x00, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x00, 0x01, 0x80, 0x00, "Off"}, + {0x00, 0x01, 0x80, 0x80, "On"}, + + // Region + {0, 0xFD, 0, 2, "Region"}, + {0x02, 0x02, 0x03, 0x02, "Asia / Europe"}, + {0x02, 0x00, 0x30, 0x00, NULL}, + {0x02, 0x02, 0x03, 0x03, "Japan"}, + {0x02, 0x00, 0x30, 0x00, NULL}, +}; + +STDDIPINFO(svcpcb) + +static struct BurnDIPInfo kf2k3pcbDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x86, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x0D, 0x01, 0x04, 0x00, "Off"}, + {0x0D, 0x01, 0x04, 0x04, "On"}, + + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x00, 0x01, 0x01, 0x00, "Off"}, + {0x00, 0x01, 0x01, 0x01, "On"}, + + // 1 or 2 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x02, 0x02, 0x00, "1"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x02, 0x02, 0x02, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + // 2 or 4 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x82, 0x02, 0x00, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x82, 0x02, 0x02, "4"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x00, 0x01, 0x38, 0x00, "Disabled"}, + {0x00, 0x01, 0x38, 0x08, "Setting 1"}, + {0x00, 0x01, 0x38, 0x10, "Setting 2"}, + {0x00, 0x01, 0x38, 0x18, "Setting 3"}, + {0x00, 0x01, 0x38, 0x20, "Setting 4"}, + {0x00, 0x01, 0x38, 0x28, "Setting 5"}, + {0x00, 0x01, 0x38, 0x30, "Setting 6"}, + {0x00, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x00, 0x01, 0x40, 0x00, "Off"}, + {0x00, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x00, 0x01, 0x80, 0x00, "Off"}, + {0x00, 0x01, 0x80, 0x80, "On"}, +}; + +STDDIPINFO(kf2k3pcb) + +static struct BurnInputInfo neoCDInputList[] = { + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 0 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 1 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 2 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 3 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 4 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 5 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 6 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 7 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 8 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, // 9 + + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // A + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // B + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // C + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // D + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // E + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // F + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 10 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 11 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 12 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 13 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 14 + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 15 + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 16 +}; + +STDINPUTINFO(neoCD) + +#define A(a, b, c, d) { a, b, (UINT8*)(c), d } + +static struct BurnInputInfo neopaddleInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 2 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 3 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 4 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 5 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 6 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 7 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 8 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 9 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "mouse button 1"}, // A + A("P1 Paddle", BIT_ANALOG_REL, NeoAxis + 0, "mouse x-axis"), // B + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // C + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // D + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // E + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // F + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // 10 + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // 11 + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // 12 + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 13 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 14 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 15 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 16 + A("P2 Paddle", BIT_ANALOG_REL, NeoAxis + 1, "p2 x-axis"), // 17 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 18 + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 19 + {"Service", BIT_DIGITAL, NeoButton2 + 2, "service"}, // 1A + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // 1B + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // 1C + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 1D + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, // 1E + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 1F + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 1G +}; + +STDINPUTINFO(neopaddle) + +static struct BurnInputInfo neotrackballInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + + A("P1 X Axis", BIT_ANALOG_REL, NeoAxis + 0, "mouse x-axis"), // 2 + A("P1 Y Axis", BIT_ANALOG_REL, NeoAxis + 1, "mouse y-axis"), // 3 + + {"P1 Button A", BIT_DIGITAL, NeoJoy2 + 4, "mouse button 1"}, // 4 + {"P1 Button B", BIT_DIGITAL, NeoJoy2 + 5, "mouse button 2"}, // 5 + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // 6 + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // 7 + + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 1"}, // 8 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 2"}, // 9 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // A + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // B + {"Service", BIT_DIGITAL, NeoButton2 + 2, "service"}, // C + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // D + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // E + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // F + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, // 10 + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 11 + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 12 +}; + +STDINPUTINFO(neotrackball) + +#undef A + +static struct BurnInputInfo neodualInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 2 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 3 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 4 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 5 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 6 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 7 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 8 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 9 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, // A + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // B + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // C + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // D + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // E + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // F + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // 10 + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // 11 + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 12 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 13 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 14 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 15 + + {"P3 Coin", BIT_DIGITAL, NeoButton4 + 0, "p3 coin"}, // 16 + {"P3 Start", BIT_DIGITAL, NeoButton3 + 0, "p3 start"}, // 17 + {"P3 Select", BIT_DIGITAL, NeoButton3 + 1, "p3 select"}, // 18 + + {"P3 Up", BIT_DIGITAL, NeoJoy3 + 0, "p3 up"}, // 19 + {"P3 Down", BIT_DIGITAL, NeoJoy3 + 1, "p3 down"}, // 1A + {"P3 Left", BIT_DIGITAL, NeoJoy3 + 2, "p3 left"}, // 1B + {"P3 Right", BIT_DIGITAL, NeoJoy3 + 3, "p3 right"}, // 1C + {"P3 Button A", BIT_DIGITAL, NeoJoy3 + 4, "p3 fire 1"}, // 1D + {"P3 Button B", BIT_DIGITAL, NeoJoy3 + 5, "p3 fire 2"}, // 1E + {"P3 Button C", BIT_DIGITAL, NeoJoy3 + 6, "p3 fire 3"}, // 1F + {"P3 Button D", BIT_DIGITAL, NeoJoy3 + 7, "p3 fire 4"}, // 20 + + {"P4 Coin", BIT_DIGITAL, NeoButton4 + 1, "p4 coin"}, // 21 + {"P4 Start", BIT_DIGITAL, NeoButton3 + 2, "p4 start"}, // 22 + {"P4 Select", BIT_DIGITAL, NeoButton3 + 3, "p4 select"}, // 23 + + {"P4 Up", BIT_DIGITAL, NeoJoy4 + 0, "p4 up"}, // 24 + {"P4 Down", BIT_DIGITAL, NeoJoy4 + 1, "p4 down"}, // 25 + {"P4 Left", BIT_DIGITAL, NeoJoy4 + 2, "p4 left"}, // 26 + {"P4 Right", BIT_DIGITAL, NeoJoy4 + 3, "p4 right"}, // 27 + {"P4 Button A", BIT_DIGITAL, NeoJoy4 + 4, "p4 fire 1"}, // 28 + {"P4 Button B", BIT_DIGITAL, NeoJoy4 + 5, "p4 fire 2"}, // 29 + {"P4 Button C", BIT_DIGITAL, NeoJoy4 + 6, "p4 fire 3"}, // 2A + {"P4 Button D", BIT_DIGITAL, NeoJoy4 + 7, "p4 fire 4"}, // 2B + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 2C + + {"Test 1", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 2D + {"Service 1", BIT_DIGITAL, NeoButton2 + 2, "service"}, // 2E + {"Test 2", BIT_DIGITAL, NeoDiag + 1, ""}, // 2F + {"Service 2", BIT_DIGITAL, NeoButton4 + 2, ""}, // 30 + + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // 31 + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // 32 + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 33 + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, // 34 + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 35 + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 36 +}; + +STDINPUTINFO(neodual) + +static struct BurnInputInfo neomahjongInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, // 0 + {"P1 Start", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, // 1 + {"P1 Select", BIT_DIGITAL, NeoButton1 + 1, "p1 select"}, // 2 + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, // 3 + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, // 4 + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, // 5 + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, // 6 + {"P1 Button A", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, // 7 + {"P1 Button B", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, // 8 + {"P1 Button C", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, // 9 + {"P1 Button D", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, // A + + {"A", BIT_DIGITAL, NeoButton1 + 8, "key tab"}, // B + {"B", BIT_DIGITAL, NeoButton1 + 9, "key q"}, // C + {"C", BIT_DIGITAL, NeoButton1 + 10, "key w"}, // D + {"D", BIT_DIGITAL, NeoButton1 + 11, "key e"}, // E + {"E", BIT_DIGITAL, NeoButton1 + 12, "key r"}, // F + {"F", BIT_DIGITAL, NeoButton1 + 13, "key t"}, // 10 + {"G", BIT_DIGITAL, NeoButton1 + 14, "key y"}, // 11 + {"H", BIT_DIGITAL, NeoButton1 + 16, "key u"}, // 12 + {"I", BIT_DIGITAL, NeoButton1 + 17, "key i"}, // 13 + {"J", BIT_DIGITAL, NeoButton1 + 18, "key o"}, // 14 + {"K", BIT_DIGITAL, NeoButton1 + 19, "key p"}, // 15 + {"L", BIT_DIGITAL, NeoButton1 + 20, "key ["}, // 16 + {"M", BIT_DIGITAL, NeoButton1 + 21, "key ]"}, // 17 + {"N", BIT_DIGITAL, NeoButton1 + 22, "key backslash"}, // 18 + {"Pon", BIT_DIGITAL, NeoButton1 + 24, "key a"}, // 19 + {"Chi", BIT_DIGITAL, NeoButton1 + 25, "key s"}, // 1A + {"Kan", BIT_DIGITAL, NeoButton1 + 26, "key d"}, // 1B + {"Ron", BIT_DIGITAL, NeoButton1 + 27, "key f"}, // 1C + {"Reach", BIT_DIGITAL, NeoButton1 + 28, "key g"}, // 1D + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, // 1E + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, // 1F + {"P2 Select", BIT_DIGITAL, NeoButton1 + 3, "p2 select"}, // 20 + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, // 21 + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, // 22 + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, // 23 + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, // 24 + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, // 25 + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, // 26 + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, // 27 + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, // 28 + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, // 29 + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, // 2A + {"Service", BIT_DIGITAL, NeoButton2 + 2, "service"}, // 2B + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, // 2C + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, // 2D + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, // 2E + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, // 2F + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, // 30 + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, // 31 +}; + +STDINPUTINFO(neomahjong) + +static struct BurnInputInfo vlinerInputList[] = { + {"P1 Coin", BIT_DIGITAL, NeoButton2 + 0, "p1 coin"}, + {"P1 Payout", BIT_DIGITAL, NeoButton1 + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, NeoJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, NeoJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, NeoJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, NeoJoy1 + 3, "p1 right"}, + {"P1 Big", BIT_DIGITAL, NeoJoy1 + 4, "p1 fire 1"}, + {"P1 Small", BIT_DIGITAL, NeoJoy1 + 5, "p1 fire 2"}, + {"P1 Double Up", BIT_DIGITAL, NeoJoy1 + 6, "p1 fire 3"}, + {"P1 Start/Collect", BIT_DIGITAL, NeoJoy1 + 7, "p1 fire 4"}, + + {"P2 Coin", BIT_DIGITAL, NeoButton2 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, NeoButton1 + 2, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, NeoJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, NeoJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, NeoJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, NeoJoy2 + 3, "p2 right"}, + {"P2 Button A", BIT_DIGITAL, NeoJoy2 + 4, "p2 fire 1"}, + {"P2 Button B", BIT_DIGITAL, NeoJoy2 + 5, "p2 fire 2"}, + {"P2 Button C", BIT_DIGITAL, NeoJoy2 + 6, "p2 fire 3"}, + {"P2 Button D", BIT_DIGITAL, NeoJoy2 + 7, "p2 fire 4"}, + + {"Operator Menu", BIT_DIGITAL, NeoButton2 + 4, "op menu"}, + {"Clear Credit", BIT_DIGITAL, NeoButton2 + 5, "clear credit"}, + {"Hopper Out", BIT_DIGITAL, NeoButton2 + 7, "hopper"}, + + {"Reset", BIT_DIGITAL, &NeoReset, "reset"}, + {"Test", BIT_DIGITAL, NeoDiag + 0, "diag"}, + {"Dip 1", BIT_DIPSWITCH, NeoInput + 4, "dip"}, + {"Dip 2", BIT_DIPSWITCH, NeoInput + 5, "dip"}, + + {"System", BIT_DIPSWITCH, &NeoSystem, "dip"}, + {"Slots", BIT_DIPSWITCH, &nNeoNumSlots, "dip"}, + + {"Debug Dip 1", BIT_DIPSWITCH, NeoDebugDip + 0,"dip"}, + {"Debug Dip 2", BIT_DIPSWITCH, NeoDebugDip + 1,"dip"}, +}; + +STDINPUTINFO(vliner) + +static struct BurnDIPInfo neodefaultDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x80, NULL}, + {0x03, 0xFF, 0xFF, 0x01, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, +}; + +static struct BurnDIPInfo neousadefaultDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x83, NULL}, + {0x03, 0xFF, 0xFF, 0x02, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, +}; + +static struct BurnDIPInfo neounidefaultDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x8e, NULL}, + {0x03, 0xFF, 0xFF, 0x02, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, +}; + +static struct BurnDIPInfo neopaddleDIPList[] = { + // Offset + {0x1B, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x80, NULL}, + {0x03, 0xFF, 0xFF, 0x01, NULL}, +}; + +static struct BurnDIPInfo neodualDIPList[] = { + // Offset + {0x31, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x80, NULL}, + {0x03, 0xFF, 0xFF, 0x01, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, +}; + +static struct BurnDIPInfo neomahjongDIPList[] = { + // Offset + {0x2C, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x02, 0xFF, 0xFF, 0x80, NULL}, + {0x03, 0xFF, 0xFF, 0x01, NULL}, + + {0, 0xFE, 0, 2, "Mahjong control panel"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, +}; + +static struct BurnDIPInfo neogeoDIPList[] = { + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x00, 0x01, 0x01, 0x00, "Off"}, + {0x00, 0x01, 0x01, 0x01, "On"}, + + // 1 or 2 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x02, 0x02, 0x00, "1"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x02, 0x02, 0x02, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + // 2 or 4 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x82, 0x02, 0x00, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x82, 0x02, 0x02, "4"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x00, 0x01, 0x38, 0x00, "Disabled"}, + {0x00, 0x01, 0x38, 0x08, "Setting 1"}, + {0x00, 0x01, 0x38, 0x10, "Setting 2"}, + {0x00, 0x01, 0x38, 0x18, "Setting 3"}, + {0x00, 0x01, 0x38, 0x20, "Setting 4"}, + {0x00, 0x01, 0x38, 0x28, "Setting 5"}, + {0x00, 0x01, 0x38, 0x30, "Setting 6"}, + {0x00, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x00, 0x01, 0x40, 0x00, "Off"}, + {0x00, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x00, 0x01, 0x80, 0x00, "Off"}, + {0x00, 0x01, 0x80, 0x80, "On"}, + + // Fake DIPs + // BIOS + {0, 0xFD, 0, 25, "BIOS" }, + {0x02, 0x01, 0x1f, 0x00, "MVS Asia/Europe ver. 6 (1 slot)" }, + {0x02, 0x01, 0x1f, 0x01, "MVS Asia/Europe ver. 5 (1 slot)" }, + {0x02, 0x01, 0x1f, 0x02, "MVS Asia/Europe ver. 3 (4 slot)" }, + {0x02, 0x01, 0x1f, 0x03, "MVS USA ver. 5 (2 slot)" }, + {0x02, 0x01, 0x1f, 0x04, "MVS USA ver. 5 (6 slot)" }, + {0x02, 0x01, 0x1f, 0x05, "MVS Japan ver. 6 (? slot)" }, + {0x02, 0x01, 0x1f, 0x06, "MVS Japan ver. 5 (? slot)" }, + {0x02, 0x01, 0x1f, 0x07, "MVS Japan ver. 3 (4 slot)" }, + {0x02, 0x01, 0x1f, 0x08, "NEO-MVH MV1C" }, + {0x02, 0x01, 0x1f, 0x09, "MVS Japan (J3)" }, + {0x02, 0x01, 0x1f, 0x0a, "AES Japan" }, + {0x02, 0x01, 0x1f, 0x0b, "AES Asia" }, + {0x02, 0x01, 0x1f, 0x0c, "Development Kit" }, + {0x02, 0x01, 0x1f, 0x0d, "Deck ver. 6 (Git Ver 1.3)" }, + {0x02, 0x01, 0x1f, 0x0e, "Universe BIOS ver. 2.3" }, + {0x02, 0x01, 0x1f, 0x0f, "Universe BIOS ver. 2.3 (alt)" }, + {0x02, 0x01, 0x1f, 0x10, "Universe BIOS ver. 2.2" }, + {0x02, 0x01, 0x1f, 0x11, "Universe BIOS ver. 2.1" }, + {0x02, 0x01, 0x1f, 0x12, "Universe BIOS ver. 2.0" }, + {0x02, 0x01, 0x1f, 0x13, "Universe BIOS ver. 1.3" }, + {0x02, 0x01, 0x1f, 0x14, "Universe BIOS ver. 1.2" }, + {0x02, 0x01, 0x1f, 0x15, "Universe BIOS ver. 1.2 (alt)" }, + {0x02, 0x01, 0x1f, 0x16, "Universe BIOS ver. 1.1" }, + {0x02, 0x01, 0x1f, 0x17, "Universe BIOS ver. 1.0" }, + {0x02, 0x01, 0x1f, 0x18, "NeoOpen BIOS v0.1 beta" }, + + // Memory card + {0, 0xFD, 0, 2, "Memory card"}, + {0x02, 0x01, 0x80, 0x80, "Writable"}, + {0x02, 0x01, 0x80, 0x00, "Write-protected"}, + {0, 0xFD, 0, 2, "New card type"}, + {0x02, 0x01, 0x40, 0x40, "1 Megabit"}, + {0x02, 0x01, 0x40, 0x00, "Normal"}, +}; + +STDDIPINFOEXT(neogeo, neodefault, neogeo) +STDDIPINFOEXT(neopaddle, neopaddle, neogeo) +STDDIPINFOEXT(neodual, neodual, neogeo) +STDDIPINFOEXT(neomahjong, neomahjong, neogeo) +STDDIPINFOEXT(neogeousa, neousadefault, neogeo) +STDDIPINFOEXT(neogeouni, neounidefault, neogeo) + +static struct BurnDIPInfo neoKOFDIPList[] = { + // Offset + {0x19, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x00, NULL}, + {0x01, 0xFF, 0x7F, 0x00, NULL}, + + {0, 0xFE, 0, 2, "Autofire"}, + {0x00, 0x01, 0x04, 0x00, "Off"}, + {0x00, 0x01, 0x04, 0x04, "On"}, + + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x00, 0x01, 0x01, 0x00, "Off"}, + {0x00, 0x01, 0x01, 0x01, "On"}, + + // 1 or 2 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x02, 0x02, 0x00, "1"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x02, 0x02, 0x02, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + // 2 or 4 coin slots + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x00, 0x82, 0x02, 0x00, "2"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + {0x00, 0x82, 0x02, 0x02, "4"}, + {0x02, 0x00, 0x3F, 0x06, NULL}, + + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x00, 0x01, 0x38, 0x00, "Disabled"}, + {0x00, 0x01, 0x38, 0x08, "Setting 1"}, + {0x00, 0x01, 0x38, 0x10, "Setting 2"}, + {0x00, 0x01, 0x38, 0x18, "Setting 3"}, + {0x00, 0x01, 0x38, 0x20, "Setting 4"}, + {0x00, 0x01, 0x38, 0x28, "Setting 5"}, + {0x00, 0x01, 0x38, 0x30, "Setting 6"}, + {0x00, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x00, 0x01, 0x40, 0x00, "Off"}, + {0x00, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x00, 0x01, 0x80, 0x00, "Off"}, + {0x00, 0x01, 0x80, 0x80, "On"}, +}; + +static struct BurnDIPInfo neoFakeDIPList[] = { + // default + {0x02, 0xFF, 0xFF, 0x80, NULL}, + + // Fake DIPs + // BIOS + {0, 0xFD, 0, 25, "BIOS" }, + {0x02, 0x01, 0x1f, 0x00, "MVS Asia/Europe ver. 6 (1 slot)" }, + {0x02, 0x01, 0x1f, 0x01, "MVS Asia/Europe ver. 5 (1 slot)" }, + {0x02, 0x01, 0x1f, 0x02, "MVS Asia/Europe ver. 3 (4 slot)" }, + {0x02, 0x01, 0x1f, 0x03, "MVS USA ver. 5 (2 slot)" }, + {0x02, 0x01, 0x1f, 0x04, "MVS USA ver. 5 (6 slot)" }, + {0x02, 0x01, 0x1f, 0x05, "MVS Japan ver. 6 (? slot)" }, + {0x02, 0x01, 0x1f, 0x06, "MVS Japan ver. 5 (? slot)" }, + {0x02, 0x01, 0x1f, 0x07, "MVS Japan ver. 3 (4 slot)" }, + {0x02, 0x01, 0x1f, 0x08, "NEO-MVH MV1C" }, + {0x02, 0x01, 0x1f, 0x09, "MVS Japan (J3)" }, + {0x02, 0x01, 0x1f, 0x0a, "AES Japan" }, + {0x02, 0x01, 0x1f, 0x0b, "AES Asia" }, + {0x02, 0x01, 0x1f, 0x0c, "Development Kit" }, + {0x02, 0x01, 0x1f, 0x0d, "Deck ver. 6 (Git Ver 1.3)" }, + {0x02, 0x01, 0x1f, 0x0e, "Universe BIOS ver. 2.3" }, + {0x02, 0x01, 0x1f, 0x0f, "Universe BIOS ver. 2.3 (alt)" }, + {0x02, 0x01, 0x1f, 0x10, "Universe BIOS ver. 2.2" }, + {0x02, 0x01, 0x1f, 0x11, "Universe BIOS ver. 2.1" }, + {0x02, 0x01, 0x1f, 0x12, "Universe BIOS ver. 2.0" }, + {0x02, 0x01, 0x1f, 0x13, "Universe BIOS ver. 1.3" }, + {0x02, 0x01, 0x1f, 0x14, "Universe BIOS ver. 1.2" }, + {0x02, 0x01, 0x1f, 0x15, "Universe BIOS ver. 1.2 (alt)" }, + {0x02, 0x01, 0x1f, 0x16, "Universe BIOS ver. 1.1" }, + {0x02, 0x01, 0x1f, 0x17, "Universe BIOS ver. 1.0" }, + {0x02, 0x01, 0x1f, 0x18, "NeoOpen BIOS v0.1 beta" }, + + // Memory card + {0, 0xFD, 0, 2, "Memory card"}, + {0x02, 0x01, 0x80, 0x80, "Writable"}, + {0x02, 0x01, 0x80, 0x00, "Write-protected"}, + {0, 0xFD, 0, 2, "New card type"}, + {0x02, 0x01, 0x40, 0x40, "1 Megabit"}, + {0x02, 0x01, 0x40, 0x00, "Normal"}, +}; + +STDDIPINFOEXT(neoMVS, neoKOF, neoFake) + +static struct BurnDIPInfo neoCDDIPList[] = { + // Offset + {0x16, 0xF0, 0x00, 0x00, NULL}, + + // Defaults + {0x00, 0xFF, 0xFF, 0x02, NULL}, + + // Region + {0, 0xFE, 0, 4, "Region"}, + {0x00, 0x01, 0x03, 0x00, "Japan"}, + {0x00, 0x01, 0x03, 0x01, "USA"}, + {0x00, 0x01, 0x03, 0x02, "Europe"}, + {0x00, 0x01, 0x03, 0x03, "Portugese"}, + +#if 0 + + // Memory card + {0, 0xFD, 0, 2, "Memory card"}, + {0x00, 0x01, 0x80, 0x80, "Writable"}, + {0x00, 0x01, 0x80, 0x00, "Write-protected"}, + {0, 0xFD, 0, 2, "New card type"}, + {0x00, 0x01, 0x40, 0x40, "1 Megabit"}, + {0x00, 0x01, 0x40, 0x00, "Normal"}, + +#endif + +}; + +STDDIPINFO(neoCD) + +static struct BurnDIPInfo neotrackballDIPList[] = { + // Defaults + {0x0D, 0xFF, 0xFF, 0x00, NULL}, + {0x0E, 0xFF, 0x7F, 0x00, NULL}, + // Fake DIPs + {0x0F, 0xFF, 0xFF, 0x86, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Setting mode"}, + {0x0D, 0x01, 0x01, 0x00, "Off"}, + {0x0D, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Coin chutes"}, + {0x0D, 0x01, 0x02, 0x00, "1"}, + {0x0D, 0x01, 0x02, 0x02, "2"}, + {0, 0xFE, 0, 2, "Autofire"}, + {0x0D, 0x01, 0x04, 0x00, "Off"}, + {0x0D, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 5, "Commmunicaton"}, + {0x0D, 0x01, 0x38, 0x00, "Disabled"}, + {0x0D, 0x01, 0x38, 0x08, "Setting 1"}, + {0x0D, 0x01, 0x38, 0x10, "Setting 2"}, + {0x0D, 0x01, 0x38, 0x18, "Setting 3"}, + {0x0D, 0x01, 0x38, 0x20, "Setting 4"}, + {0x0D, 0x01, 0x38, 0x28, "Setting 5"}, + {0x0D, 0x01, 0x38, 0x30, "Setting 6"}, + {0x0D, 0x01, 0x38, 0x38, "Setting 7"}, + {0, 0xFE, 0, 2, "Free play"}, + {0x0D, 0x01, 0x40, 0x00, "Off"}, + {0x0D, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Stop mode"}, + {0x0D, 0x01, 0x80, 0x00, "Off"}, + {0x0D, 0x01, 0x80, 0x80, "On"}, + + // MVS/AES system + {0, 0xFD, 0, 2, NULL}, + {0x0F, 0x02, 0x04, 0x04, "MVS system"}, + {0x0F, 0x00, 0x30, 0x00, NULL}, + {0x0F, 0x02, 0x04, 0x00, "AES system"}, + {0x0F, 0x00, 0x30, 0x00, NULL}, + // Region + {0, 0xFD, 0, 3, "Region"}, + {0x0F, 0x01, 0x03, 0x00, "Japan"}, + {0x0F, 0x01, 0x03, 0x01, "USA"}, + {0x0F, 0x01, 0x03, 0x02, "Asia / Europe"}, + {0x0F, 0x01, 0x03, 0x03, "Japan"}, + + // Memory card + {0, 0xFD, 0, 2, "Memory card"}, + {0x0F, 0x01, 0x80, 0x80, "Writable"}, + {0x0F, 0x01, 0x80, 0x00, "Write-protected"}, + {0, 0xFD, 0, 2, "Default card type"}, + {0x0F, 0x01, 0x40, 0x40, "1 Megabit"}, + {0x0F, 0x01, 0x40, 0x00, "Normal"}, +}; + +STDDIPINFO(neotrackball) + +// Rom information +static struct BurnRomInfo neogeoRomDesc[] = { + { "asia-s3.rom", 0x20000, 0x91b64be3, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT }, // 0 MVS Asia/Europe ver. 6 (1 slot) + { "sp-s2.sp1", 0x20000, 0x9036d879, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 1 MVS Asia/Europe ver. 5 (1 slot) + { "sp-s.sp1", 0x20000, 0xc7f2fa45, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 2 MVS Asia/Europe ver. 3 (4 slot) + { "usa_2slt.bin", 0x20000, 0xe72943de, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 3 MVS USA ver. 5 (2 slot) + { "sp-e.sp1", 0x20000, 0x2723a5b5, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 4 MVS USA ver. 5 (6 slot) + { "vs-bios.rom", 0x20000, 0xf0e8f27d, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 5 MVS Japan ver. 6 (? slot) + { "sp-j2.sp1", 0x20000, 0xacede59C, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 6 MVS Japan ver. 5 (? slot) + { "sp1.jipan.1024", 0x20000, 0x9fb0abe4, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 7 MVS Japan ver. 3 (4 slot) + { "sp-45.sp1", 0x80000, 0x03cc9f6a, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 8 NEO-MVH MV1C + { "japan-j3.bin", 0x20000, 0xdff6d41f, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 9 MVS Japan (J3) +#if !defined (ROM_VERIFY) + { "neo-po.bin", 0x20000, 0x16d0c132, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 10 AES Japan + { "neo-epo.bin", 0x20000, 0xd27a71f1, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 11 AES Asia + { "neodebug.bin", 0x20000, 0x698ebb7d, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 12 Development Kit +#else + { "", 0x00000, 0x00000000, 0 }, // 10 + { "", 0x00000, 0x00000000, 0 }, // 11 + { "", 0x00000, 0x00000000, 0 }, // 12 +#endif + { "sp-1v1_3db8c.bin", 0x20000, 0x162f0ebe, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 13 Deck ver. 6 (Git Ver 1.3) + { "uni-bios_2_3.rom", 0x20000, 0x27664eb5, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 14 Universe BIOS ver. 2.3 + { "uni-bios_2_3o.rom", 0x20000, 0x601720ae, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 15 Universe BIOS ver. 2.3 (alt) + { "uni-bios_2_2.rom", 0x20000, 0x2d50996a, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 16 Universe BIOS ver. 2.2 + { "uni-bios_2_1.rom", 0x20000, 0x8dabf76b, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 17 Universe BIOS ver. 2.1 + { "uni-bios_2_0.rom", 0x20000, 0x0c12c2ad, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 18 Universe BIOS ver. 2.0 + { "uni-bios_1_3.rom", 0x20000, 0xb24b44a0, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 19 Universe BIOS ver. 1.3 + { "uni-bios_1_2.rom", 0x20000, 0x4fa698e9, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 20 Universe BIOS ver. 1.2 + { "uni-bios_1_2o.rom", 0x20000, 0xe19d3ce9, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 21 Universe BIOS ver. 1.2 (alt) + { "uni-bios_1_1.rom", 0x20000, 0x5dda0d84, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 22 Universe BIOS ver. 1.1 + { "uni-bios_1_0.rom", 0x20000, 0x0ce453a0, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 23 Universe BIOS ver. 1.0 +#if !defined (ROM_VERIFY) + { "neopen.sp1", 0x20000, 0xcb915e76, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 24 NeoOpen BIOS v0.1 beta +#else + { "", 0x00000, 0x00000000, 0 }, // 24 +#endif + { "", 0x00000, 0x00000000, 0 }, // 25 Trackball BIOS loaded here + { "", 0x00000, 0x00000000, 0 }, // 26 PCB BIOS loaded here + + { "sm1.sm1", 0x20000, 0x94416d67, BRF_ESS | BRF_PRG | BRF_BIOS }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +STD_ROM_PICK(neogeo) +STD_ROM_FN(neogeo) + +// Rom information +static struct BurnRomInfo neoMVSRomDesc[] = { + { "asia-s3.rom", 0x20000, 0x91b64be3, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT }, // 0 MVS Asia/Europe ver. 6 (1 slot) + { "sp-s2.sp1", 0x20000, 0x9036d879, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 1 MVS Asia/Europe ver. 5 (1 slot) + { "sp-s.sp1", 0x20000, 0xc7f2fa45, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 2 MVS Asia/Europe ver. 3 (4 slot) + { "usa_2slt.bin", 0x20000, 0xe72943de, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 3 MVS USA ver. 5 (2 slot) + { "sp-e.sp1", 0x20000, 0x2723a5b5, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 4 MVS USA ver. 5 (6 slot) + { "vs-bios.rom", 0x20000, 0xf0e8f27d, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 5 MVS Japan ver. 6 (? slot) + { "sp-j2.sp1", 0x20000, 0xacede59C, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 6 MVS Japan ver. 5 (? slot) + { "sp1.jipan.1024", 0x20000, 0x9fb0abe4, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 7 MVS Japan ver. 3 (4 slot) + { "sp-45.sp1", 0x80000, 0x03cc9f6a, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 8 NEO-MVH MV1C + { "japan-j3.bin", 0x20000, 0xdff6d41f, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 9 MVS Japan (J3) + { "neo-po.bin", 0x20000, 0x16d0c132, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 10 AES Japan + { "neo-epo.bin", 0x20000, 0xd27a71f1, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 11 AES Asia + { "neodebug.bin", 0x20000, 0x698ebb7d, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 12 Development Kit + { "sp-1v1_3db8c.bin", 0x20000, 0x162f0ebe, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 13 Deck ver. 6 (Git Ver 1.3) + { "uni-bios_2_3.rom", 0x20000, 0x27664eb5, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 14 Universe BIOS ver. 2.3 + { "uni-bios_2_3o.rom", 0x20000, 0x601720ae, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 15 Universe BIOS ver. 2.3 (alt) + { "uni-bios_2_2.rom", 0x20000, 0x2d50996a, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 16 Universe BIOS ver. 2.2 + { "uni-bios_2_1.rom", 0x20000, 0x8dabf76b, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 17 Universe BIOS ver. 2.1 + { "uni-bios_2_0.rom", 0x20000, 0x0c12c2ad, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 18 Universe BIOS ver. 2.0 + { "uni-bios_1_3.rom", 0x20000, 0xb24b44a0, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 19 Universe BIOS ver. 1.3 + { "uni-bios_1_2.rom", 0x20000, 0x4fa698e9, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 20 Universe BIOS ver. 1.2 + { "uni-bios_1_2o.rom", 0x20000, 0xe19d3ce9, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 21 Universe BIOS ver. 1.2 (alt) + { "uni-bios_1_1.rom", 0x20000, 0x5dda0d84, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 22 Universe BIOS ver. 1.1 + { "uni-bios_1_0.rom", 0x20000, 0x0ce453a0, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 23 Universe BIOS ver. 1.0 + { "neopen.sp1", 0x20000, 0xcb915e76, BRF_ESS | BRF_PRG | BRF_BIOS | BRF_SELECT | BRF_OPT }, // 24 NeoOpen BIOS v0.1 beta + { "", 0x00000, 0x00000000, 0 }, // 25 Trackball BIOS loaded here + { "", 0x00000, 0x00000000, 0 }, // 26 PCB BIOS loaded here + + { "sm1.sm1", 0x20000, 0x94416d67, BRF_ESS | BRF_PRG | BRF_BIOS }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +STD_ROM_PICK(neoMVS) +STD_ROM_FN(neoMVS) + +static struct BurnRomInfo neotrackballRomDesc[] = { + { "", 0x00000, 0x00000000, 0 }, // 0 + { "", 0x00000, 0x00000000, 0 }, // 1 + { "", 0x00000, 0x00000000, 0 }, // 2 + { "", 0x00000, 0x00000000, 0 }, // 3 + { "", 0x00000, 0x00000000, 0 }, // 4 + { "", 0x00000, 0x00000000, 0 }, // 5 + { "", 0x00000, 0x00000000, 0 }, // 6 + { "", 0x00000, 0x00000000, 0 }, // 7 + { "", 0x00000, 0x00000000, 0 }, // 8 + { "", 0x00000, 0x00000000, 0 }, // 9 + { "", 0x00000, 0x00000000, 0 }, // 10 + { "", 0x00000, 0x00000000, 0 }, // 11 + { "", 0x00000, 0x00000000, 0 }, // 12 + { "", 0x00000, 0x00000000, 0 }, // 13 + { "", 0x00000, 0x00000000, 0 }, // 14 + { "", 0x00000, 0x00000000, 0 }, // 15 + { "", 0x00000, 0x00000000, 0 }, // 16 + { "", 0x00000, 0x00000000, 0 }, // 17 + { "", 0x00000, 0x00000000, 0 }, // 18 + { "", 0x00000, 0x00000000, 0 }, // 19 + { "", 0x00000, 0x00000000, 0 }, // 20 + { "", 0x00000, 0x00000000, 0 }, // 21 + { "", 0x00000, 0x00000000, 0 }, // 22 + { "", 0x00000, 0x00000000, 0 }, // 23 + { "", 0x00000, 0x00000000, 0 }, // 24 + { "236-bios.sp1", 0x20000, 0x853e6b96, BRF_ESS | BRF_PRG | BRF_BIOS }, // 25 Trackball BIOS + { "", 0x00000, 0x00000000, 0 }, // 26 + + { "sm1.sm1", 0x20000, 0x94416d67, BRF_ESS | BRF_PRG | BRF_BIOS }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +static struct BurnRomInfo ms5pcbBIOSRomDesc[] = { + { "", 0x00000, 0x00000000, 0 }, // 0 + { "", 0x00000, 0x00000000, 0 }, // 1 + { "", 0x00000, 0x00000000, 0 }, // 2 + { "", 0x00000, 0x00000000, 0 }, // 3 + { "", 0x00000, 0x00000000, 0 }, // 4 + { "", 0x00000, 0x00000000, 0 }, // 5 + { "", 0x00000, 0x00000000, 0 }, // 6 + { "", 0x00000, 0x00000000, 0 }, // 7 + { "", 0x00000, 0x00000000, 0 }, // 8 + { "", 0x00000, 0x00000000, 0 }, // 9 + { "", 0x00000, 0x00000000, 0 }, // 10 + { "", 0x00000, 0x00000000, 0 }, // 11 + { "", 0x00000, 0x00000000, 0 }, // 12 + { "", 0x00000, 0x00000000, 0 }, // 13 + { "", 0x00000, 0x00000000, 0 }, // 14 + { "", 0x00000, 0x00000000, 0 }, // 15 + { "", 0x00000, 0x00000000, 0 }, // 16 + { "", 0x00000, 0x00000000, 0 }, // 17 + { "", 0x00000, 0x00000000, 0 }, // 18 + { "", 0x00000, 0x00000000, 0 }, // 19 + { "", 0x00000, 0x00000000, 0 }, // 20 + { "", 0x00000, 0x00000000, 0 }, // 21 + { "", 0x00000, 0x00000000, 0 }, // 22 + { "", 0x00000, 0x00000000, 0 }, // 23 + { "", 0x00000, 0x00000000, 0 }, // 24 + { "", 0x00000, 0x00000000, 0 }, // 25 + { "sp-4x.sp1", 0x80000, 0xb4590283, BRF_ESS | BRF_PRG | BRF_BIOS }, // 26 PCB BIOS + + { "", 0x00000, 0x00000000, 0 }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +static struct BurnRomInfo svcpcbBIOSRomDesc[] = { + { "", 0x00000, 0x00000000, 0 }, // 0 + { "", 0x00000, 0x00000000, 0 }, // 1 + { "", 0x00000, 0x00000000, 0 }, // 2 + { "", 0x00000, 0x00000000, 0 }, // 3 + { "", 0x00000, 0x00000000, 0 }, // 4 + { "", 0x00000, 0x00000000, 0 }, // 5 + { "", 0x00000, 0x00000000, 0 }, // 6 + { "", 0x00000, 0x00000000, 0 }, // 7 + { "", 0x00000, 0x00000000, 0 }, // 8 + { "", 0x00000, 0x00000000, 0 }, // 9 + { "", 0x00000, 0x00000000, 0 }, // 10 + { "", 0x00000, 0x00000000, 0 }, // 11 + { "", 0x00000, 0x00000000, 0 }, // 12 + { "", 0x00000, 0x00000000, 0 }, // 13 + { "", 0x00000, 0x00000000, 0 }, // 14 + { "", 0x00000, 0x00000000, 0 }, // 15 + { "", 0x00000, 0x00000000, 0 }, // 16 + { "", 0x00000, 0x00000000, 0 }, // 17 + { "", 0x00000, 0x00000000, 0 }, // 18 + { "", 0x00000, 0x00000000, 0 }, // 19 + { "", 0x00000, 0x00000000, 0 }, // 20 + { "", 0x00000, 0x00000000, 0 }, // 21 + { "", 0x00000, 0x00000000, 0 }, // 22 + { "", 0x00000, 0x00000000, 0 }, // 23 + { "", 0x00000, 0x00000000, 0 }, // 24 + { "", 0x00000, 0x00000000, 0 }, // 25 + { "sp-4x.sp1", 0x80000, 0xb4590283, BRF_ESS | BRF_PRG | BRF_BIOS }, // 26 PCB BIOS + + { "", 0x00000, 0x00000000, 0 }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +static struct BurnRomInfo kf2k3pcbBIOSRomDesc[] = { + { "", 0x00000, 0x00000000, 0 }, // 0 + { "", 0x00000, 0x00000000, 0 }, // 1 + { "", 0x00000, 0x00000000, 0 }, // 2 + { "", 0x00000, 0x00000000, 0 }, // 3 + { "", 0x00000, 0x00000000, 0 }, // 4 + { "", 0x00000, 0x00000000, 0 }, // 5 + { "", 0x00000, 0x00000000, 0 }, // 6 + { "", 0x00000, 0x00000000, 0 }, // 7 + { "", 0x00000, 0x00000000, 0 }, // 8 + { "", 0x00000, 0x00000000, 0 }, // 9 + { "", 0x00000, 0x00000000, 0 }, // 10 + { "", 0x00000, 0x00000000, 0 }, // 11 + { "", 0x00000, 0x00000000, 0 }, // 12 + { "", 0x00000, 0x00000000, 0 }, // 13 + { "", 0x00000, 0x00000000, 0 }, // 14 + { "", 0x00000, 0x00000000, 0 }, // 15 + { "", 0x00000, 0x00000000, 0 }, // 16 + { "", 0x00000, 0x00000000, 0 }, // 17 + { "", 0x00000, 0x00000000, 0 }, // 18 + { "", 0x00000, 0x00000000, 0 }, // 19 + { "", 0x00000, 0x00000000, 0 }, // 20 + { "", 0x00000, 0x00000000, 0 }, // 21 + { "", 0x00000, 0x00000000, 0 }, // 22 + { "", 0x00000, 0x00000000, 0 }, // 23 + { "", 0x00000, 0x00000000, 0 }, // 24 + { "", 0x00000, 0x00000000, 0 }, // 25 + { "spj.sp1", 0x80000, 0x148dd727, BRF_ESS | BRF_PRG | BRF_BIOS }, // 26 PCB BIOS + + { "", 0x00000, 0x00000000, 0 }, // 27 Z80 BIOS + { "sfix.sfix", 0x20000, 0xc2ea0cfd, BRF_GRA | BRF_BIOS }, // 28 Text layer tiles + { "000-lo.lo", 0x20000, 0x5a86cff2, BRF_ESS | BRF_BIOS }, // 29 Zoom table +}; + +struct BurnDriver BurnDrvNeoGeo = { + "neogeo", NULL, NULL, NULL, "1990", + "Neo Geo\0", "BIOS only", "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_BOARDROM, 0, HARDWARE_SNK_NEOGEO, 0, 0, + NULL, neogeoRomInfo, neogeoRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNeoGeoMVS = { + "neogeo", NULL, NULL, NULL, "1990", + "Neo Geo MVS system\0", "System - cartridges selected seperately", "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING /*| BDF_SYSTEM_ONLY*/, 2, HARDWARE_SNK_MVS, 0, 0, + NULL, neoMVSRomInfo, neoMVSRomName, NULL, NULL, neoMVSInputInfo, neoMVSDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// ---------------------------------------------------------------------------- +// Neo Geo CDZ system + +static struct BurnRomInfo neocdzRomDesc[] = { + { "neocd.bin", 0x080000, 0xDF9DE490, BRF_ESS | BRF_PRG | BRF_BIOS }, + { "000-lo.lo", 0x020000, 0x5a86cff2, BRF_ESS | BRF_PRG | BRF_BIOS }, +}; + +STD_ROM_PICK(neocdz) +STD_ROM_FN(neocdz) + +struct BurnDriver BurnDrvneocdz = { + "neocdz", NULL, "neogeo", NULL, "1996", + "Neo Geo CDZ system\0", "System - media selected seperately", "SNK", "Neo Geo CDZ", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING /*| BDF_SYSTEM_ONLY*/, 2, HARDWARE_SNK_NEOCD, 0, 0, + NULL, neocdzRomInfo, neocdzRomName, NULL, NULL, neoCDInputInfo, neoCDDIPInfo, + NeoCDInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// ---------------------------------------------------------------------------- +// Extra code for SMA protection + +INT32 nSMARandomNumber[MAX_SLOT]; + +static UINT32 nNeoSMARNGAddress[MAX_SLOT][2] = { 0, 0 }; + +static pSekWriteWordHandler pSMABankswitchHandler[MAX_SLOT] = { NULL, }; + +// Bank in an area of memory +void NeoSMABankswitch() +{ + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + if (nNeoSMARNGAddress[0] > 0 || nNeoSMARNGAddress[1] > 0) { + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFBFF, SM_ROM); + } else { + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFFFF, SM_ROM); + } +} + +// Extra protection +UINT16 __fastcall neogeoReadWordSMA9A37(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, " -- SMA9A37 0x%08X (word)\n", sekAddress); + + if (sekAddress == 0x2FE446) { + return 0x9A37; + } + + return *((UINT16*)(Neo68KROMActive + nNeo68KROMBank + sekAddress - 0x200000)); +} + +UINT8 __fastcall neogeoReadByteSMA9A37(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, " -- SMA9A37 0x%08X (byte)\n", sekAddress); + + if (sekAddress == 0x2FE446) { + return 0x9A; + } + if (sekAddress == 0x2FE447) { + return 0x37; + } + + return Neo68KROMActive[(nNeo68KROMBank + sekAddress - 0x200000) ^ 1]; +} + +// Random number generator +UINT16 __fastcall neogeoReadWordSMARNG(UINT32 sekAddress) +{ + if (sekAddress == nNeoSMARNGAddress[nNeoActiveSlot][0] || sekAddress == nNeoSMARNGAddress[nNeoActiveSlot][1]) { + INT32 nRandomNumber = nSMARandomNumber[nNeoActiveSlot]; + + INT32 nNewbit = ( + (nSMARandomNumber[nNeoActiveSlot] >> 2) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 3) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 5) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 6) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 7) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 11) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 12) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 15)) & 1; + + nSMARandomNumber[nNeoActiveSlot] = ((nSMARandomNumber[nNeoActiveSlot] << 1) | nNewbit) & 0x0FFFFF; + + return nRandomNumber; + } + + return *((UINT16*)(Neo68KROMActive + nNeo68KROMBank + sekAddress - 0x200000)); +} + +UINT8 __fastcall neogeoReadByteSMARNG(UINT32 sekAddress) +{ + if ((sekAddress & ~1) == nNeoSMARNGAddress[nNeoActiveSlot][0] || (sekAddress & ~1) == nNeoSMARNGAddress[nNeoActiveSlot][1]) { + INT32 nRandomNumber = nSMARandomNumber[nNeoActiveSlot]; + + INT32 nNewbit = ( + (nSMARandomNumber[nNeoActiveSlot] >> 2) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 3) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 5) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 6) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 7) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 11) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 12) ^ + (nSMARandomNumber[nNeoActiveSlot] >> 15)) & 1; + + nSMARandomNumber[nNeoActiveSlot] = ((nSMARandomNumber[nNeoActiveSlot] << 1) | nNewbit) & 0x0FFFFF; + + if (sekAddress & 1) { + return nRandomNumber & 0xFF; + } else { + return nRandomNumber >> 8; + } + } + + return Neo68KROMActive[(nNeo68KROMBank + sekAddress - 0x200000) ^ 1]; +} + +INT32 NeoSMAScan(INT32 nAction, INT32* /*pnMin*/) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nSMARandomNumber); + } + + return 0; +} + +static void NeoSMAInstallHanders() +{ +// bprintf(PRINT_NORMAL, _T(" Installing handlers for slot %i\n"), nNeoActiveSlot); + + SekMapHandler(8, 0x2FFC00, 0x2FFFFF, SM_WRITE); // Bankswitch + + SekSetWriteWordHandler(8, pSMABankswitchHandler[nNeoActiveSlot]); + + SekMapHandler(6, 0x2FE400, 0x2FE7FF, SM_ROM); // Protection + + SekSetReadWordHandler(6, neogeoReadWordSMA9A37); + SekSetReadByteHandler(6, neogeoReadByteSMA9A37); + + if (nNeoSMARNGAddress[nNeoActiveSlot][0] > 0 || nNeoSMARNGAddress[nNeoActiveSlot][1] > 0) { + SekMapHandler(7, 0x2FFC00, 0x2FFFFF, SM_ROM); // Randum number generator + + SekSetReadWordHandler(7, neogeoReadWordSMARNG); + SekSetReadByteHandler(7, neogeoReadByteSMARNG); + } +} + +// Install handlers +static INT32 NeoSMAInit(void (*pInitCallback)(), pSekWriteWordHandler pBankswitchHandler, UINT32 nRNGAddress0, UINT32 nRNGAddress1) +{ + nNeoSMARNGAddress[nNeoActiveSlot][0] = nRNGAddress0; nNeoSMARNGAddress[nNeoActiveSlot][1] = nRNGAddress1; + pSMABankswitchHandler[nNeoActiveSlot] = pBankswitchHandler; + + NeoCallbackActive->pInitialise = pInitCallback; + NeoCallbackActive->pInstallHandlers = NeoSMAInstallHanders; + NeoCallbackActive->pBankswitch = NeoSMABankswitch; + NeoCallbackActive->pScan = NeoSMAScan; + + nSMARandomNumber[nNeoActiveSlot] = 0x2345; + + return NeoInit(); +} + +INT32 NeoSMAExit() +{ + NeoExit(); + + nNeoSMARNGAddress[nNeoActiveSlot][0] = nNeoSMARNGAddress[nNeoActiveSlot][1] = 0; + + return 0; +} + +// ---------------------------------------------------------------------------- +// Extra code for PCM2 protection + +struct PCM2DecryptP2Info { UINT32 nAddressOffset[16]; }; + +struct PCM2DecryptV2Info { INT32 nAddressOffset; INT32 nAddressXor; UINT8 nDataXor[8]; }; + +static void PCM2DecryptP() +{ + // Descamble P-ROMs + + UINT8* pTemp = (UINT8*)malloc(0x400000); + + if (pTemp) { + memcpy(pTemp, Neo68KROMActive + 0x100000, 0x400000); + + for (INT32 i = 0; i < 4; i++) { + memcpy(Neo68KROMActive + 0x100000 + i * 0x100000, pTemp + 0x000000 + (((((i + 2) & 1) << 2) | ((i + 2) & 2)) << 19), 0x80000); + memcpy(Neo68KROMActive + 0x180000 + i * 0x100000, pTemp + 0x080000 + (((((i + 1) & 1) << 2) | ((i + 1) & 2)) << 19), 0x80000); + } + + free(pTemp); + pTemp = NULL; + } +} + +static void PCM2DecryptV(INT32 size, INT32 bit) +{ + for (INT32 i = 0; i < size / 2; i += (2 << bit)) { + UINT16 buffer[8]; + memcpy(buffer, ((UINT16*)(YM2610ADPCMAROM[nNeoActiveSlot])) + i, 16); + for (INT32 j = (2 << bit) - 1; j >= 0; j--) { + ((UINT16*)(YM2610ADPCMAROM[nNeoActiveSlot]))[i + j] = buffer[j ^ (1 << bit)]; + } + } +} + +static void PCM2DecryptV2(const PCM2DecryptV2Info* const pInfo) +{ + // Decrypt V-ROMs + + UINT8* pTemp = (UINT8*)malloc(0x01000000); + + if (pTemp) { + memcpy(pTemp, YM2610ADPCMAROM[nNeoActiveSlot], 0x01000000); + + for (INT32 i = 0; i < 0x01000000; i++) { + INT32 nAddress = ((i & 0x00FEFFFE) | ((i & 0x00010000) >> 16) | ((i & 0x00000001) << 16)) ^ pInfo->nAddressOffset; + + YM2610ADPCMAROM[nNeoActiveSlot][nAddress] = pTemp[(i + pInfo->nAddressXor) & 0xffffff] ^ pInfo->nDataXor[nAddress & 0x07]; + } + + free(pTemp); + pTemp = NULL; + } +} + +static void PCM2DecryptP2(const PCM2DecryptP2Info* const pInfo) +{ + // Descamble P-ROMs + + UINT8* pTemp = (UINT8*)malloc(0x800000); + + if (pTemp) { + memcpy(pTemp, Neo68KROMActive, 0x800000); + + for (INT32 i = 0; i < 16; i++) { + memcpy(Neo68KROMActive + i * 0x80000, pTemp + pInfo->nAddressOffset[i], 0x80000); + } + + free(pTemp); + pTemp = NULL; + } +} + +// ---------------------------------------------------------------------------- +// PVC protection + +static UINT8 *PVCRAM = NULL; + +void NeoPVCPallette01() // unpack palette word to RGB dword +{ + UINT8 b1, b2; + b1 = PVCRAM[0x1fe1]; + b2 = PVCRAM[0x1fe0]; + + PVCRAM[0x1fe2] = ((b2 & 0xf) << 1) | ((b1 >> 4) & 1); + PVCRAM[0x1fe3] = (((b2 >> 4) & 0xf) << 1) | ((b1 >> 5) & 1); + PVCRAM[0x1fe4] = ((b1 & 0xf) << 1) | ((b1 >> 6) & 1); + PVCRAM[0x1fe5] = b1 >> 7; +} + +void NeoPVCPallette02() // pack RGB dword to palette word +{ + UINT8 b1, b2, b3, b4; + b1 = PVCRAM[0x1fe9]; + b2 = PVCRAM[0x1fe8]; + b3 = PVCRAM[0x1feb]; + b4 = PVCRAM[0x1fea]; + + PVCRAM[0x1fec] = (b2 >> 1) | ((b1 >> 1) << 4); + PVCRAM[0x1fed] = (b4 >> 1) | ((b2 & 1) << 4) | ((b1 & 1) << 5) | ((b4 & 1) << 6) | ((b3 & 1) << 7); +} + +void NeoPVCBankswitch() +{ + UINT32 nBank = (PVCRAM[0x1ff3] << 16) | (PVCRAM[0x1ff2] << 8) | PVCRAM[0x1ff1]; + nBank += (Neo68KROMActive[0x108] & 0x10) << 16; // for kof2003 (bank 0 is $100000) + + if (nNeo68KROMBank != nBank) + { + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); + } + + PVCRAM[0x1ff0] = 0xa0; + PVCRAM[0x1ff1] &= 0xfe; + PVCRAM[0x1ff3] &= 0x7f; +} + +void __fastcall PVCWriteByteBankSwitch(UINT32 sekAddress, UINT8 byteValue) +{ + PVCRAM[(sekAddress & 0x1fff) ^ 1] = byteValue; + if (sekAddress >= 0x2fffe0 && sekAddress <= 0x2fffe1) NeoPVCPallette01(); + else if(sekAddress >= 0x2fffe8 && sekAddress <= 0x2fffeb) NeoPVCPallette02(); + else if (sekAddress >= 0x2ffff0 && sekAddress <= 0x2ffff3) NeoPVCBankswitch(); +} + +void __fastcall PVCWriteWordBankSwitch(UINT32 sekAddress, UINT16 wordValue) +{ + *((UINT16 *)(PVCRAM + (sekAddress & 0x1ffe))) = wordValue; + if (sekAddress >= 0x2fffe0 && sekAddress <= 0x2fffe1) NeoPVCPallette01(); + else if (sekAddress >= 0x2fffe8 && sekAddress <= 0x2fffeb) NeoPVCPallette02(); + else if (sekAddress >= 0x2ffff0 && sekAddress <= 0x2ffff3) NeoPVCBankswitch(); +} + +static void NeoPVCMapBank() +{ + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); +} + +static INT32 NeoPVCScan(INT32 nAction, INT32*) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PVCRAM; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Neo-PVC 68K RAM"; + BurnAcb(&ba); + } + + return 0; +} + +static void NeoPVCInstallHandlers() +{ + // Install cart PVC protections + SekMapMemory(PVCRAM, 0x2fe000, 0x2fffff, SM_READ); + + SekMapHandler(6, 0x2fe000, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(6, PVCWriteWordBankSwitch); + SekSetWriteByteHandler(6, PVCWriteByteBankSwitch); +} + +static INT32 NeoPVCInit() +{ + PVCRAM = (UINT8*)malloc(0x2000); + if (!PVCRAM) return 1; + + memset(PVCRAM, 0, 0x2000); + + NeoCallbackActive->pInstallHandlers = NeoPVCInstallHandlers; + NeoCallbackActive->pBankswitch = NeoPVCMapBank; + NeoCallbackActive->pScan = NeoPVCScan; + + return NeoInit(); +} + +static INT32 NeoPVCExit() +{ + if (PVCRAM) { + free(PVCRAM); + PVCRAM = NULL; + } + + return NeoExit(); +} + + +// ---------------------------------------------------------------------------- +// Helper functions + +static void lans2004_sx_decode() +{ + INT32 i, j, n; + for (i = 0; i < 0x20000; i+= 0x10) { + for (j = 0; j < 0x08; j++) { + n = NeoTextROM[nNeoActiveSlot][i + j + 8]; + NeoTextROM[nNeoActiveSlot][i + j + 8] = NeoTextROM[nNeoActiveSlot][i + j]; + NeoTextROM[nNeoActiveSlot][i + j + 0] = n; + } + } +} + +static void lans2004_cx_decode(INT32 nLen) +{ + INT32 i, j, n; + for (i = 0; i < nLen; i+= 0x80) { + for (j = 0; j < 0x40; j++) { + n = NeoSpriteROM[nNeoActiveSlot][i + j + 0x40]; + NeoSpriteROM[nNeoActiveSlot][i + j + 0x40] = NeoSpriteROM[nNeoActiveSlot][i + j]; + NeoSpriteROM[nNeoActiveSlot][i + j] = n; + } + } +} + +static void DoPerm(INT32 g) // 0 - cthd2003, 1 - svcboot +{ + static INT32 idx[ 2 ][ 16 ] = { + { 0, 1, 2, 3, 3, 4, 4, 5, 0, 1, 2, 3, 3, 4, 4, 5 }, // 0 + { 0, 1, 0, 1, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5, 4, 5 }, // 1 + }; + + static INT32 tbl[ 6 ][ 4 ] = { + { 3, 0, 1, 2 }, + { 2, 3, 0, 1 }, + { 1, 2, 3, 0 }, + { 0, 1, 2, 3 }, + { 3, 2, 1, 0 }, + { 3, 0, 2, 1 }, + }; + + INT32 i, j, k, *b; + UINT8 dst[0x800]; + + for (i = 0; i < 0x4000000 >> 11; i++) + { + for(j = 0; j < 0x800 >> 7; j++) + { + b = tbl[idx[g][(i >> (5 ^ g)) & 0x0f]]; + k = BITSWAP08(j, 7, 6, 5, 4, b[3], b[2], b[1], b[0]); + + memcpy (dst + (j << 7), NeoSpriteROM[nNeoActiveSlot] + (i << 11) + (k << 7), 0x80); + } + + memcpy (NeoSpriteROM[nNeoActiveSlot] + (i << 11), dst, 0x800); + } +} + +// ---------------------------------------------------------------------------- +// Game drivers (games in MAME) + +// NAM-1975 (NGM-001)(NGH-001) + +static struct BurnRomInfo nam1975RomDesc[] = { + { "001-p1.p1", 0x080000, 0xcc9fc951, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "001-s1.s1", 0x020000, 0x7988ba51, 2 | BRF_GRA }, // 1 Text layer tiles + + { "001-c1.c1", 0x080000, 0x32ea98e1, 3 | BRF_GRA }, // 2 Sprite data + { "001-c2.c2", 0x080000, 0xcbc4064c, 3 | BRF_GRA }, // 3 + { "001-c3.c3", 0x080000, 0x0151054c, 3 | BRF_GRA }, // 4 + { "001-c4.c4", 0x080000, 0x0a32570d, 3 | BRF_GRA }, // 5 + { "001-c5.c5", 0x080000, 0x90b74cc2, 3 | BRF_GRA }, // 6 + { "001-c6.c6", 0x080000, 0xe62bed58, 3 | BRF_GRA }, // 7 + + { "001-m1.m1", 0x040000, 0xba874463, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "001-v11.v11", 0x080000, 0xa7c3d5e5, 5 | BRF_SND }, // 9 Sound data + { "001-v21.v21", 0x080000, 0x55e670b3, 6 | BRF_SND }, // 10 + { "001-v22.v22", 0x080000, 0xab0d8368, 6 | BRF_SND }, // 11 + { "001-v23.v23", 0x080000, 0xdf468e28, 6 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(nam1975, nam1975, neogeo) +STD_ROM_FN(nam1975) + +struct BurnDriver BurnDrvNam1975 = { + "nam1975", NULL, "neogeo", NULL, "1990", + "NAM-1975 (NGM-001)(NGH-001)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, nam1975RomInfo, nam1975RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Baseball Stars Professional (NGM-002) + +static struct BurnRomInfo bstarsRomDesc[] = { + { "002-pg.p1", 0x080000, 0xc100b5f5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "002-s1.s1", 0x020000, 0x1a7fd0c6, 2 | BRF_GRA }, // 1 Text layer tiles + + { "002-c1.c1", 0x080000, 0xaaff2a45, 3 | BRF_GRA }, // 2 Sprite data + { "002-c2.c2", 0x080000, 0x3ba0f7e4, 3 | BRF_GRA }, // 3 + { "002-c3.c3", 0x080000, 0x96f0fdfa, 3 | BRF_GRA }, // 4 + { "002-c4.c4", 0x080000, 0x5fd87f2f, 3 | BRF_GRA }, // 5 + { "002-c5.c5", 0x080000, 0x807ed83b, 3 | BRF_GRA }, // 6 + { "002-c6.c6", 0x080000, 0x5a3cad41, 3 | BRF_GRA }, // 7 + + { "002-m1.m1", 0x040000, 0x4ecaa4ee, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "002-v11.v11", 0x080000, 0xb7b925bd, 5 | BRF_SND }, // 9 Sound data + { "002-v12.v12", 0x080000, 0x329f26fc, 5 | BRF_SND }, // 10 + { "002-v13.v13", 0x080000, 0x0c39f3c8, 5 | BRF_SND }, // 11 + { "002-v14.v14", 0x080000, 0xc7e11c38, 5 | BRF_SND }, // 12 + { "002-v21.v21", 0x080000, 0x04a733d1, 6 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(bstars, bstars, neogeo) +STD_ROM_FN(bstars) + +struct BurnDriver BurnDrvBstars = { + "bstars", NULL, "neogeo", NULL, "1990", + "Baseball Stars Professional (NGM-002)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bstarsRomInfo, bstarsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Baseball Stars Professional (NGH-002) + +static struct BurnRomInfo bstarshRomDesc[] = { + { "002-p1.p1", 0x080000, 0x3bc7790e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "002-s1.s1", 0x020000, 0x1a7fd0c6, 2 | BRF_GRA }, // 1 Text layer tiles + + { "002-c1.c1", 0x080000, 0xaaff2a45, 3 | BRF_GRA }, // 2 Sprite data + { "002-c2.c2", 0x080000, 0x3ba0f7e4, 3 | BRF_GRA }, // 3 + { "002-c3.c3", 0x080000, 0x96f0fdfa, 3 | BRF_GRA }, // 4 + { "002-c4.c4", 0x080000, 0x5fd87f2f, 3 | BRF_GRA }, // 5 + { "002-c5.c5", 0x080000, 0x807ed83b, 3 | BRF_GRA }, // 6 + { "002-c6.c6", 0x080000, 0x5a3cad41, 3 | BRF_GRA }, // 7 + + { "002-m1.m1", 0x040000, 0x4ecaa4ee, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "002-v11.v11", 0x080000, 0xb7b925bd, 5 | BRF_SND }, // 9 Sound data + { "002-v12.v12", 0x080000, 0x329f26fc, 5 | BRF_SND }, // 10 + { "002-v13.v13", 0x080000, 0x0c39f3c8, 5 | BRF_SND }, // 11 + { "002-v14.v14", 0x080000, 0xc7e11c38, 5 | BRF_SND }, // 12 + { "002-v21.v21", 0x080000, 0x04a733d1, 6 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(bstarsh, bstarsh, neogeo) +STD_ROM_FN(bstarsh) + +struct BurnDriver BurnDrvBstarsh = { + "bstarsh", "bstars", "neogeo", NULL, "1990", + "Baseball Stars Professional (NGH-002)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bstarshRomInfo, bstarshRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Top Player's Golf (NGM-003)(NGH-003) + +static struct BurnRomInfo tpgolfRomDesc[] = { + { "003-p1.p1", 0x080000, 0xf75549ba, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "003-p2.p2", 0x080000, 0xb7809a8f, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "003-s1.s1", 0x020000, 0x7b3eb9b1, 2 | BRF_GRA }, // 2 Text layer tiles + + { "003-c1.c1", 0x080000, 0x0315fbaf, 3 | BRF_GRA }, // 3 Sprite data + { "003-c2.c2", 0x080000, 0xb4c15d59, 3 | BRF_GRA }, // 4 + { "003-c3.c3", 0x080000, 0x8ce3e8da, 3 | BRF_GRA }, // 5 + { "003-c4.c4", 0x080000, 0x29725969, 3 | BRF_GRA }, // 6 + { "003-c5.c5", 0x080000, 0x9a7146da, 3 | BRF_GRA }, // 7 + { "003-c6.c6", 0x080000, 0x1e63411a, 3 | BRF_GRA }, // 8 + { "003-c7.c7", 0x080000, 0x2886710c, 3 | BRF_GRA }, // 9 + { "003-c8.c8", 0x080000, 0x422af22d, 3 | BRF_GRA }, // 10 + + { "003-m1.m1", 0x020000, 0x4cc545e6, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "003-v11.v11", 0x080000, 0xff97f1cb, 5 | BRF_SND }, // 12 Sound data + { "003-v21.v21", 0x080000, 0xd34960c6, 6 | BRF_SND }, // 13 + { "003-v22.v22", 0x080000, 0x9a5f58d4, 6 | BRF_SND }, // 14 + { "003-v23.v23", 0x080000, 0x30f53e54, 6 | BRF_SND }, // 15 + { "003-v24.v24", 0x080000, 0x5ba0f501, 6 | BRF_SND }, // 16 +}; + +STDROMPICKEXT(tpgolf, tpgolf, neogeo) +STD_ROM_FN(tpgolf) + +struct BurnDriver BurnDrvTpgolf = { + "tpgolf", NULL, "neogeo", NULL, "1990", + "Top Player's Golf (NGM-003)(NGH-003)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, tpgolfRomInfo, tpgolfRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Mahjong Kyo Retsuden (NGM-004)(NGH-004) + +static struct BurnRomInfo mahretsuRomDesc[] = { + { "004-p1.p1", 0x080000, 0xfc6f53db, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "004-s1.s1", 0x020000, 0x2bd05a06, 2 | BRF_GRA }, // 1 Text layer tiles + + { "004-c1.c1", 0x080000, 0xf1ae16bc, 3 | BRF_GRA }, // 2 Sprite data + { "004-c2.c2", 0x080000, 0xbdc13520, 3 | BRF_GRA }, // 3 + { "004-c3.c3", 0x080000, 0x9c571a37, 3 | BRF_GRA }, // 4 + { "004-c4.c4", 0x080000, 0x7e81cb29, 3 | BRF_GRA }, // 5 + + { "004-m1.m1", 0x020000, 0xc71fbb3b, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "004-v11.v11", 0x080000, 0xb2fb2153, 5 | BRF_SND }, // 7 Sound data + { "004-v12.v12", 0x080000, 0x8503317b, 5 | BRF_SND }, // 8 + { "004-v21.v21", 0x080000, 0x4999fb27, 6 | BRF_SND }, // 9 + { "004-v22.v22", 0x080000, 0x776fa2a2, 6 | BRF_SND }, // 10 + { "004-v23.v23", 0x080000, 0xb3e7eeea, 6 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(mahretsu, mahretsu, neogeo) +STD_ROM_FN(mahretsu) + +struct BurnDriver BurnDrvMahretsu = { + "mahretsu", NULL, "neogeo", NULL, "1990", + "Mahjong Kyo Retsuden (NGM-004)(NGH-004)\0", NULL, "SNK", "Neo Geo MVS", + L"\u9EBB\u96C0\u72C2\u5217\u4F1D (NGM-004)(NGH-004)\0Mahjong Kyo Retsuden (NGM-004)(NGH-004)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_MAHJONG, GBF_MAHJONG, 0, + NULL, mahretsuRomInfo, mahretsuRomName, NULL, NULL, neomahjongInputInfo, neomahjongDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Riding Hero (NGM-006)(NGH-006) + +static struct BurnRomInfo ridheroRomDesc[] = { + { "006-p1.p1", 0x080000, 0xd4aaf597, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "006-s1.s1", 0x020000, 0xeb5189f0, 2 | BRF_GRA }, // 1 Text layer tiles + + { "006-c1.c1", 0x080000, 0x4a5c7f78, 3 | BRF_GRA }, // 2 Sprite data + { "006-c2.c2", 0x080000, 0xe0b70ece, 3 | BRF_GRA }, // 3 + { "006-c3.c3", 0x080000, 0x8acff765, 3 | BRF_GRA }, // 4 + { "006-c4.c4", 0x080000, 0x205e3208, 3 | BRF_GRA }, // 5 + + { "006-m1.m1", 0x040000, 0x92e7b4fe, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "006-v11.v11", 0x080000, 0xcdf74a42, 5 | BRF_SND }, // 7 Sound data + { "006-v12.v12", 0x080000, 0xe2fd2371, 5 | BRF_SND }, // 8 + { "006-v21.v21", 0x080000, 0x94092bce, 6 | BRF_SND }, // 9 + { "006-v22.v22", 0x080000, 0x4e2cd7c3, 6 | BRF_SND }, // 10 + { "006-v23.v23", 0x080000, 0x069c71ed, 6 | BRF_SND }, // 11 + { "006-v24.v24", 0x080000, 0x89fbb825, 6 | BRF_SND }, // 12 + + { "hd6301v1p.com", 0x001000, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STDROMPICKEXT(ridhero, ridhero, neogeo) +STD_ROM_FN(ridhero) + +struct BurnDriver BurnDrvRidhero = { + "ridhero", NULL, "neogeo", NULL, "1990", + "Riding Hero (NGM-006)(NGH-006)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_RACING, 0, + NULL, ridheroRomInfo, ridheroRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Riding Hero (set 2) + +static struct BurnRomInfo ridherohRomDesc[] = { + { "006-pg1.p1", 0x080000, 0x52445646, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "006-s1.s1", 0x020000, 0xeb5189f0, 2 | BRF_GRA }, // 1 Text layer tiles + + { "006-c1.c1", 0x080000, 0x4a5c7f78, 3 | BRF_GRA }, // 2 Sprite data + { "006-c2.c2", 0x080000, 0xe0b70ece, 3 | BRF_GRA }, // 3 + { "006-c3.c3", 0x080000, 0x8acff765, 3 | BRF_GRA }, // 4 + { "006-c4.c4", 0x080000, 0x205e3208, 3 | BRF_GRA }, // 5 + + { "006-m1.m1", 0x040000, 0x92e7b4fe, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "006-v11.v11", 0x080000, 0xcdf74a42, 5 | BRF_SND }, // 7 Sound data + { "006-v12.v12", 0x080000, 0xe2fd2371, 5 | BRF_SND }, // 8 + { "006-v21.v21", 0x080000, 0x94092bce, 6 | BRF_SND }, // 9 + { "006-v22.v22", 0x080000, 0x4e2cd7c3, 6 | BRF_SND }, // 10 + { "006-v23.v23", 0x080000, 0x069c71ed, 6 | BRF_SND }, // 11 + { "006-v24.v24", 0x080000, 0x89fbb825, 6 | BRF_SND }, // 12 + + { "hd6301v1p.com", 0x001000, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STDROMPICKEXT(ridheroh, ridheroh, neogeo) +STD_ROM_FN(ridheroh) + +struct BurnDriver BurnDrvRidheroh = { + "ridheroh", "ridhero", "neogeo", NULL, "1990", + "Riding Hero (set 2)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_RACING, 0, + NULL, ridherohRomInfo, ridherohRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Alpha Mission II / ASO II - Last Guardian (NGM-007)(NGH-007) + +static struct BurnRomInfo alpham2RomDesc[] = { + { "007-p1.p1", 0x080000, 0x5b266f47, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "007-p2.p2", 0x020000, 0xeb9c1044, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "007-s1.s1", 0x020000, 0x85ec9acf, 2 | BRF_GRA }, // 2 Text layer tiles + + { "007-c1.c1", 0x100000, 0x8fba8ff3, 3 | BRF_GRA }, // 3 Sprite data + { "007-c2.c2", 0x100000, 0x4dad2945, 3 | BRF_GRA }, // 4 + { "007-c3.c3", 0x080000, 0x68c2994e, 3 | BRF_GRA }, // 5 + { "007-c4.c4", 0x080000, 0x7d588349, 3 | BRF_GRA }, // 6 + + { "007-m1.m1", 0x020000, 0x28dfe2cd, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "007-v1.v1", 0x100000, 0xcd5db931, 5 | BRF_SND }, // 8 Sound data + { "007-v2.v2", 0x100000, 0x63e9b574, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(alpham2, alpham2, neogeo) +STD_ROM_FN(alpham2) + +struct BurnDriver BurnDrvAlpham2 = { + "alpham2", NULL, "neogeo", NULL, "1991", + "Alpha Mission II / ASO II - Last Guardian (NGM-007)(NGH-007)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, alpham2RomInfo, alpham2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Alpha Mission II / ASO II - Last Guardian (prototype) + +static struct BurnRomInfo alpham2pRomDesc[] = { + { "proto_007-p1.bin", 0x080000, 0xc763e52a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "proto_007-p2.bin", 0x080000, 0x7a0b435c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "proto_007-s1.bin", 0x020000, 0xefc9ae2e, 2 | BRF_GRA }, // 2 Text layer tiles + + { "proto_007-c1.bin", 0x080000, 0x24841639, 3 | BRF_GRA }, // 3 Sprite data + { "proto_007-c2.bin", 0x080000, 0x912763ab, 3 | BRF_GRA }, // 4 + { "proto_007-c3.bin", 0x080000, 0x0743bde2, 3 | BRF_GRA }, // 5 + { "proto_007-c4.bin", 0x080000, 0x61240212, 3 | BRF_GRA }, // 6 + { "proto_007-c5.bin", 0x080000, 0xcf9f4c53, 3 | BRF_GRA }, // 7 + { "proto_007-c6.bin", 0x080000, 0x3d903b19, 3 | BRF_GRA }, // 8 + { "proto_007-c7.bin", 0x080000, 0xe41e3875, 3 | BRF_GRA }, // 9 + { "proto_007-c8.bin", 0x080000, 0x4483e2cf, 3 | BRF_GRA }, // 10 + + { "proto_007-m1.bin", 0x020000, 0x5976b464, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "proto_007-v11.bin", 0x080000, 0x18eaa9e1, 5 | BRF_SND }, // 12 Sound data + { "proto_007-v12.bin", 0x080000, 0x2487d495, 5 | BRF_SND }, // 13 + { "proto_007-v13.bin", 0x080000, 0x25e60f25, 5 | BRF_SND }, // 14 + { "proto_007-v21.bin", 0x080000, 0xac44b75a, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(alpham2p, alpham2p, neogeo) +STD_ROM_FN(alpham2p) + +static void Alpham2pCallback() +{ + BurnLoadRom(Neo68KROMActive + 0x000000, 0, 2); + BurnLoadRom(Neo68KROMActive + 0x000001, 1, 2); +} + +static INT32 Alpham2pInit() +{ + NeoCallbackActive->pInitialise = Alpham2pCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvAlpham2p = { + "alpham2p", "alpham2", "neogeo", NULL, "1991", + "Alpha Mission II / ASO II - Last Guardian (prototype)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SPRITE32, GBF_VERSHOOT, 0, + NULL, alpham2pRomInfo, alpham2pRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + Alpham2pInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Cyber-Lip (NGM-010) + +static struct BurnRomInfo cyberlipRomDesc[] = { + { "010-p1.p1", 0x080000, 0x69a6b42d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "010-s1.s1", 0x020000, 0x79a35264, 2 | BRF_GRA }, // 1 Text layer tiles + + { "010-c1.c1", 0x080000, 0x8bba5113, 3 | BRF_GRA }, // 2 Sprite data + { "010-c2.c2", 0x080000, 0xcbf66432, 3 | BRF_GRA }, // 3 + { "010-c3.c3", 0x080000, 0xe4f86efc, 3 | BRF_GRA }, // 4 + { "010-c4.c4", 0x080000, 0xf7be4674, 3 | BRF_GRA }, // 5 + { "010-c5.c5", 0x080000, 0xe8076da0, 3 | BRF_GRA }, // 6 + { "010-c6.c6", 0x080000, 0xc495c567, 3 | BRF_GRA }, // 7 + + { "010-m1.m1", 0x020000, 0x8be3a078, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "010-v11.v11", 0x080000, 0x90224d22, 5 | BRF_SND }, // 9 Sound data + { "010-v12.v12", 0x080000, 0xa0cf1834, 5 | BRF_SND }, // 10 + { "010-v13.v13", 0x080000, 0xae38bc84, 5 | BRF_SND }, // 11 + { "010-v14.v14", 0x080000, 0x70899bd2, 5 | BRF_SND }, // 12 + { "010-v21.v21", 0x080000, 0x586f4cb2, 6 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(cyberlip, cyberlip, neogeo) +STD_ROM_FN(cyberlip) + +struct BurnDriver BurnDrvCyberlip = { + "cyberlip", NULL, "neogeo", NULL, "1990", + "Cyber-Lip (NGM-010)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, cyberlipRomInfo, cyberlipRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The Super Spy (NGM-011)(NGH-011) + +static struct BurnRomInfo superspyRomDesc[] = { + { "011-p1.p1", 0x080000, 0xc7f944b5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "sp2.p2", 0x020000, 0x811a4faf, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "011-s1.s1", 0x020000, 0xec5fdb96, 2 | BRF_GRA }, // 2 Text layer tiles + + { "011-c1.c1", 0x100000, 0xcae7be57, 3 | BRF_GRA }, // 3 Sprite data + { "011-c2.c2", 0x100000, 0x9e29d986, 3 | BRF_GRA }, // 4 + { "011-c3.c3", 0x100000, 0x14832ff2, 3 | BRF_GRA }, // 5 + { "011-c4.c4", 0x100000, 0xb7f63162, 3 | BRF_GRA }, // 6 + + { "011-m1.m1", 0x040000, 0xca661f1b, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "011-v11.v11", 0x100000, 0x5c674d5c, 5 | BRF_SND }, // 8 Sound data + { "011-v12.v12", 0x080000, 0x9f513d5a, 5 | BRF_SND }, // 9 + { "011-v21.v21", 0x080000, 0x426cd040, 6 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(superspy, superspy, neogeo) +STD_ROM_FN(superspy) + +struct BurnDriver BurnDrvSuperspy = { + "superspy", NULL, "neogeo", NULL, "1990", + "The Super Spy (NGM-011)(NGH-011)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, superspyRomInfo, superspyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Mutation Nation (NGM-014)(NGH-014) + +static struct BurnRomInfo mutnatRomDesc[] = { + { "014-p1.p1", 0x080000, 0x6f1699c8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "014-s1.s1", 0x020000, 0x99419733, 2 | BRF_GRA }, // 1 Text layer tiles + + { "014-c1.c1", 0x100000, 0x5e4381bf, 3 | BRF_GRA }, // 2 Sprite data + { "014-c2.c2", 0x100000, 0x69ba4e18, 3 | BRF_GRA }, // 3 + { "014-c3.c3", 0x100000, 0x890327d5, 3 | BRF_GRA }, // 4 + { "014-c4.c4", 0x100000, 0xe4002651, 3 | BRF_GRA }, // 5 + + { "014-m1.m1", 0x020000, 0xb6683092, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "014-v1.v1", 0x100000, 0x25419296, 5 | BRF_SND }, // 7 Sound data + { "014-v2.v2", 0x100000, 0x0de53d5e, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(mutnat, mutnat, neogeo) +STD_ROM_FN(mutnat) + +struct BurnDriver BurnDrvMutnat = { + "mutnat", NULL, "neogeo", NULL, "1992", + "Mutation Nation (NGM-014)(NGH-014)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, mutnatRomInfo, mutnatRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// King of the Monsters (set 1) + +static struct BurnRomInfo kotmRomDesc[] = { + { "016-p1.p1", 0x080000, 0x1b818731, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "016-p2.p2", 0x020000, 0x12afdc2b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "016-s1.s1", 0x020000, 0x1a2eeeb3, 2 | BRF_GRA }, // 2 Text layer tiles + + { "016-c1.c1", 0x100000, 0x71471c25, 3 | BRF_GRA }, // 3 Sprite data + { "016-c2.c2", 0x100000, 0x320db048, 3 | BRF_GRA }, // 4 + { "016-c3.c3", 0x100000, 0x98de7995, 3 | BRF_GRA }, // 5 + { "016-c4.c4", 0x100000, 0x070506e2, 3 | BRF_GRA }, // 6 + + { "016-m1.m1", 0x020000, 0x9da9ca10, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "016-v1.v1", 0x100000, 0x86c0a502, 5 | BRF_SND }, // 8 Sound data + { "016-v2.v2", 0x100000, 0x5bc23ec5, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(kotm, kotm, neogeo) +STD_ROM_FN(kotm) + +struct BurnDriver BurnDrvKotm = { + "kotm", NULL, "neogeo", NULL, "1991", + "King of the Monsters (set 1)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, kotmRomInfo, kotmRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// King of the Monsters (set 2) + +static struct BurnRomInfo kotmhRomDesc[] = { + { "016-hp1.p1", 0x080000, 0xb774621e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "016-p2.p2", 0x020000, 0x12afdc2b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "016-s1.s1", 0x020000, 0x1a2eeeb3, 2 | BRF_GRA }, // 2 Text layer tiles + + { "016-c1.c1", 0x100000, 0x71471c25, 3 | BRF_GRA }, // 3 Sprite data + { "016-c2.c2", 0x100000, 0x320db048, 3 | BRF_GRA }, // 4 + { "016-c3.c3", 0x100000, 0x98de7995, 3 | BRF_GRA }, // 5 + { "016-c4.c4", 0x100000, 0x070506e2, 3 | BRF_GRA }, // 6 + + { "016-m1.m1", 0x020000, 0x9da9ca10, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "016-v1.v1", 0x100000, 0x86c0a502, 5 | BRF_SND }, // 8 Sound data + { "016-v2.v2", 0x100000, 0x5bc23ec5, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(kotmh, kotmh, neogeo) +STD_ROM_FN(kotmh) + +struct BurnDriver BurnDrvKotmh = { + "kotmh", "kotm", "neogeo", NULL, "1991", + "King of the Monsters (set 2)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, kotmhRomInfo, kotmhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Sengoku / Sengoku Denshou (NGM-017)(NGH-017) + +static struct BurnRomInfo sengokuRomDesc[] = { + { "017-p1.p1", 0x080000, 0xf8a63983, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "017-p2.p2", 0x020000, 0x3024bbb3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "017-s1.s1", 0x020000, 0xb246204d, 2 | BRF_GRA }, // 2 Text layer tiles + + { "017-c1.c1", 0x100000, 0xb4eb82a1, 3 | BRF_GRA }, // 3 Sprite data + { "017-c2.c2", 0x100000, 0xd55c550d, 3 | BRF_GRA }, // 4 + { "017-c3.c3", 0x100000, 0xed51ef65, 3 | BRF_GRA }, // 5 + { "017-c4.c4", 0x100000, 0xf4f3c9cb, 3 | BRF_GRA }, // 6 + + { "017-m1.m1", 0x020000, 0x9b4f34c6, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "017-v1.v1", 0x100000, 0x23663295, 5 | BRF_SND }, // 8 Sound data + { "017-v2.v2", 0x100000, 0xf61e6765, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(sengoku, sengoku, neogeo) +STD_ROM_FN(sengoku) + +struct BurnDriver BurnDrvSengoku = { + "sengoku", NULL, "neogeo", NULL, "1991", + "Sengoku / Sengoku Denshou (NGM-017)(NGH-017)\0", NULL, "SNK", "Neo Geo MVS", + L"Sengoku / Sengoku Denshou (NGM-017)(NGH-017)\0\u6226\u56FD\u4F1D\u627F (NGM-017)(NGH-017)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, sengokuRomInfo, sengokuRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Sengoku / Sengoku Denshou (NGH-017)(US) + +static struct BurnRomInfo sengokuhRomDesc[] = { + { "017-hp1.p1", 0x080000, 0x33eccae0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "017-p2.p2", 0x020000, 0x3024bbb3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "017-s1.s1", 0x020000, 0xb246204d, 2 | BRF_GRA }, // 2 Text layer tiles + + { "017-c1.c1", 0x100000, 0xb4eb82a1, 3 | BRF_GRA }, // 3 Sprite data + { "017-c2.c2", 0x100000, 0xd55c550d, 3 | BRF_GRA }, // 4 + { "017-c3.c3", 0x100000, 0xed51ef65, 3 | BRF_GRA }, // 5 + { "017-c4.c4", 0x100000, 0xf4f3c9cb, 3 | BRF_GRA }, // 6 + + { "017-m1.m1", 0x020000, 0x9b4f34c6, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "017-v1.v1", 0x100000, 0x23663295, 5 | BRF_SND }, // 8 Sound data + { "017-v2.v2", 0x100000, 0xf61e6765, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(sengokuh, sengokuh, neogeo) +STD_ROM_FN(sengokuh) + +struct BurnDriver BurnDrvSengokuh = { + "sengokuh", "sengoku", "neogeo", NULL, "1991", + "Sengoku / Sengoku Denshou (NGH-017)(US)\0", NULL, "SNK", "Neo Geo MVS", + L"Sengoku / Sengoku Denshou (NGH-017)(US)\0\u6226\u56FD\u4F1D\u627F (NGH-017)(US)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, sengokuhRomInfo, sengokuhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Burning Fight (NGM-018)(NGH-018) + +static struct BurnRomInfo burningfRomDesc[] = { + { "018-p1.p1", 0x080000, 0x4092c8db, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "018-s1.s1", 0x020000, 0x6799ea0d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "018-c1.c1", 0x100000, 0x25a25e9b, 3 | BRF_GRA }, // 2 Sprite data + { "018-c2.c2", 0x100000, 0xd4378876, 3 | BRF_GRA }, // 3 + { "018-c3.c3", 0x100000, 0x862b60da, 3 | BRF_GRA }, // 4 + { "018-c4.c4", 0x100000, 0xe2e0aff7, 3 | BRF_GRA }, // 5 + + { "018-m1.m1", 0x020000, 0x0c939ee2, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "018-v1.v1", 0x100000, 0x508c9ffc, 5 | BRF_SND }, // 7 Sound data + { "018-v2.v2", 0x100000, 0x854ef277, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(burningf, burningf, neogeo) +STD_ROM_FN(burningf) + +struct BurnDriver BurnDrvBurningf = { + "burningf", NULL, "neogeo", NULL, "1991", + "Burning Fight (NGM-018)(NGH-018)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, burningfRomInfo, burningfRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Burning Fight (NGH-018)(US) + +static struct BurnRomInfo burningfhRomDesc[] = { + { "018-hp1.p1", 0x080000, 0xddffcbf4, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "018-s1.s1", 0x020000, 0x6799ea0d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "018-c1.c1", 0x100000, 0x25a25e9b, 3 | BRF_GRA }, // 2 Sprite data + { "018-c2.c2", 0x100000, 0xd4378876, 3 | BRF_GRA }, // 3 + { "018-c3.c3", 0x100000, 0x862b60da, 3 | BRF_GRA }, // 4 + { "018-c4.c4", 0x100000, 0xe2e0aff7, 3 | BRF_GRA }, // 5 + + { "018-m1.m1", 0x020000, 0x0c939ee2, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "018-v1.v1", 0x100000, 0x508c9ffc, 5 | BRF_SND }, // 7 Sound data + { "018-v2.v2", 0x100000, 0x854ef277, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(burningfh, burningfh, neogeo) +STD_ROM_FN(burningfh) + +struct BurnDriver BurnDrvBurningfh = { + "burningfh", "burningf", "neogeo", NULL, "1991", + "Burning Fight (NGH-018)(US)\0", NULL, "SNK", "Neo Geo AES", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, burningfhRomInfo, burningfhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Burning Fight (prototype) + +static struct BurnRomInfo burningfpRomDesc[] = { + { "proto_018.p1", 0x080000, 0x5b4032e7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "proto_018.p2", 0x080000, 0x78762f68, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "proto_018.s1", 0x020000, 0xf3d130e8, 2 | BRF_GRA }, // 2 Text layer tiles + + { "proto_018.c1", 0x080000, 0x6569018b, 3 | BRF_GRA }, // 3 Sprite data + { "proto_018.c2", 0x080000, 0x6949b501, 3 | BRF_GRA }, // 4 + { "proto_018.c3", 0x080000, 0x410f653b, 3 | BRF_GRA }, // 5 + { "proto_018.c4", 0x080000, 0xd43bf2a5, 3 | BRF_GRA }, // 6 + { "proto_018.c5", 0x080000, 0x837d09d3, 3 | BRF_GRA }, // 7 + { "proto_018.c6", 0x080000, 0x5fee51e7, 3 | BRF_GRA }, // 8 + { "proto_018.c7", 0x080000, 0x0f3f0823, 3 | BRF_GRA }, // 9 + { "proto_018.c8", 0x080000, 0x67cc9e34, 3 | BRF_GRA }, // 10 + + { "proto_018.m1", 0x020000, 0x470dd5d4, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "proto_018.v11",0x080000, 0xdc07ea3c, 5 | BRF_SND }, // 12 Sound data + { "proto_018.v12",0x080000, 0xf1ae637c, 5 | BRF_SND }, // 13 + { "proto_018.v21",0x080000, 0x9f3b4eda, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(burningfp, burningfp, neogeo) +STD_ROM_FN(burningfp) + +static void BurningfpCallback() +{ + BurnLoadRom(Neo68KROMActive + 0x000000, 0, 2); + BurnLoadRom(Neo68KROMActive + 0x000001, 1, 2); +} + +static INT32 BurningfpInit() +{ + NeoCallbackActive->pInitialise = BurningfpCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvBurningfp = { + "burningfp", "burningf", "neogeo", NULL, "1991", + "Burning Fight (prototype)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SPRITE32, GBF_SCRFIGHT, 0, + NULL, burningfpRomInfo, burningfpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + BurningfpInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// League Bowling (NGM-019)(NGH-019) + +static struct BurnRomInfo lbowlingRomDesc[] = { + { "019-p1.p1", 0x080000, 0xa2de8445, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "019-s1.s1", 0x020000, 0x5fcdc0ed, 2 | BRF_GRA }, // 1 Text layer tiles + + { "019-c1.c1", 0x080000, 0x4ccdef18, 3 | BRF_GRA }, // 2 Sprite data + { "019-c2.c2", 0x080000, 0xd4dd0802, 3 | BRF_GRA }, // 3 + + { "019-m1.m1", 0x020000, 0xd568c17d, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "019-v11.v11", 0x080000, 0x0fb74872, 5 | BRF_SND }, // 5 Sound data + { "019-v12.v12", 0x080000, 0x029faa57, 5 | BRF_SND }, // 6 + { "019-v21.v21", 0x080000, 0x2efd5ada, 6 | BRF_SND }, // 7 + + { "hd6301v1p.com", 0x001000, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STDROMPICKEXT(lbowling, lbowling, neogeo) +STD_ROM_FN(lbowling) + +struct BurnDriver BurnDrvLbowling = { + "lbowling", NULL, "neogeo", NULL, "1990", + "League Bowling (NGM-019)(NGH-019)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, lbowlingRomInfo, lbowlingRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ghost Pilots (NGM-020)(NGH-020) + +static struct BurnRomInfo gpilotsRomDesc[] = { + { "020-p1.p1", 0x080000, 0xe6f2fe64, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "020-p2.p2", 0x020000, 0xedcb22ac, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "020-s1.s1", 0x020000, 0xa6d83d53, 2 | BRF_GRA }, // 2 Text layer tiles + + { "020-c1.c1", 0x100000, 0xbd6fe78e, 3 | BRF_GRA }, // 3 Sprite data + { "020-c2.c2", 0x100000, 0x5f4a925c, 3 | BRF_GRA }, // 4 + { "020-c3.c3", 0x100000, 0xd1e42fd0, 3 | BRF_GRA }, // 5 + { "020-c4.c4", 0x100000, 0xedde439b, 3 | BRF_GRA }, // 6 + + { "020-m1.m1", 0x020000, 0x48409377, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "020-v11.v11", 0x100000, 0x1b526c8b, 5 | BRF_SND }, // 8 Sound data + { "020-v12.v12", 0x080000, 0x4a9e6f03, 5 | BRF_SND }, // 9 + { "020-v21.v21", 0x080000, 0x7abf113d, 6 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(gpilots, gpilots, neogeo) +STD_ROM_FN(gpilots) + +struct BurnDriver BurnDrvGpilots = { + "gpilots", NULL, "neogeo", NULL, "1991", + "Ghost Pilots (NGM-020)(NGH-020)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, gpilotsRomInfo, gpilotsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ghost Pilots (NGH-020)(US) + +static struct BurnRomInfo gpilotshRomDesc[] = { + { "020-hp1.p1", 0x080000, 0x7cdb01ce, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "020-p2.p2", 0x020000, 0xedcb22ac, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "020-s1.s1", 0x020000, 0xa6d83d53, 2 | BRF_GRA }, // 2 Text layer tiles + + { "020-c1.c1", 0x100000, 0xbd6fe78e, 3 | BRF_GRA }, // 3 Sprite data + { "020-c2.c2", 0x100000, 0x5f4a925c, 3 | BRF_GRA }, // 4 + { "020-c3.c3", 0x100000, 0xd1e42fd0, 3 | BRF_GRA }, // 5 + { "020-c4.c4", 0x100000, 0xedde439b, 3 | BRF_GRA }, // 6 + + { "020-m1.m1", 0x020000, 0x48409377, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "020-v11.v11", 0x100000, 0x1b526c8b, 5 | BRF_SND }, // 8 Sound data + { "020-v12.v12", 0x080000, 0x4a9e6f03, 5 | BRF_SND }, // 9 + { "020-v21.v21", 0x080000, 0x7abf113d, 6 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(gpilotsh, gpilotsh, neogeo) +STD_ROM_FN(gpilotsh) + +struct BurnDriver BurnDrvGpilotsh = { + "gpilotsh", "gpilots", "neogeo", NULL, "1991", + "Ghost Pilots (NGH-020)(US)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, gpilotshRomInfo, gpilotshRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Puzzled / Joy Joy Kid (NGM-021)(NGH-021) + +static struct BurnRomInfo joyjoyRomDesc[] = { + { "021-p1.p1", 0x080000, 0x39c3478f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "021-s1.s1", 0x020000, 0x6956d778, 2 | BRF_GRA }, // 1 Text layer tiles + + { "021-c1.c1", 0x080000, 0x509250ec, 3 | BRF_GRA }, // 2 Sprite data + { "021-c2.c2", 0x080000, 0x09ed5258, 3 | BRF_GRA }, // 3 + + { "021-m1.m1", 0x040000, 0x5a4be5e8, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "021-v11.v11", 0x080000, 0x66c1e5c4, 5 | BRF_SND }, // 5 Sound data + { "021-v21.v21", 0x080000, 0x8ed20a86, 6 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(joyjoy, joyjoy, neogeo) +STD_ROM_FN(joyjoy) + +struct BurnDriver BurnDrvJoyjoy = { + "joyjoy", NULL, "neogeo", NULL, "1990", + "Puzzled / Joy Joy Kid (NGM-021)(NGH-021)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, joyjoyRomInfo, joyjoyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Quiz Daisousa Sen - The Last Count Down (NGM-023)(NGH-023) + +static struct BurnRomInfo quizdaisRomDesc[] = { + { "023-p1.p1", 0x100000, 0xc488fda3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "023-s1.s1", 0x020000, 0xac31818a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "023-c1.c1", 0x100000, 0x2999535a, 3 | BRF_GRA }, // 2 Sprite data + { "023-c2.c2", 0x100000, 0x876a99e6, 3 | BRF_GRA }, // 3 + + { "023-m1.m1", 0x020000, 0x2a2105e0, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "023-v1.v1", 0x100000, 0xa53e5bd3, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(quizdais, quizdais, neogeo) +STD_ROM_FN(quizdais) + +struct BurnDriver BurnDrvQuizdais = { + "quizdais", NULL, "neogeo", NULL, "1991", + "Quiz Daisousa Sen - The Last Count Down (NGM-023)(NGH-023)\0", NULL, "SNK", "Neo Geo MVS", + L"\u30AF\u30A4\u30BA\u5927\u635C\u67FB\u7DDA - the last count down (NGM-023)(NGH-023)\0Quiz Daisousa Sen - The Last Count Down (NGM-023)(NGH-023)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, quizdaisRomInfo, quizdaisRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Quiz Daisousa Sen - The Last Count Down (Korean release) + +static struct BurnRomInfo quizdaiskRomDesc[] = { + { "123-p1.p1", 0x100000, 0xa6f35eae, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "123-s1.s1", 0x020000, 0x53de938a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "123-c1.c1", 0x100000, 0xe579a606, 3 | BRF_GRA }, // 2 Sprite data + { "123-c2.c2", 0x100000, 0xe182c837, 3 | BRF_GRA }, // 3 + + { "123-m1.m1", 0x020000, 0xd67f53f9, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "123-v1.v1", 0x200000, 0x986f4af9, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(quizdaisk, quizdaisk, neogeo) +STD_ROM_FN(quizdaisk) + +struct BurnDriver BurnDrvQuizdaisk = { + "quizdaisk", "quizdais", "neogeo", NULL, "1991", + "Quiz Daisousa Sen - The Last Count Down (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + L"\u30AF\u30A4\u30BA\u5927\u635C\u67FB\u7DDA - The Last Count Down (Korean release)\0Quiz Daisousa Sen - The Last Count Down (Korean release)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, quizdaiskRomInfo, quizdaiskRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Last Resort + +static struct BurnRomInfo lresortRomDesc[] = { + { "024-p1.p1", 0x080000, 0x89c4ab97, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "024-s1.s1", 0x020000, 0x5cef5cc6, 2 | BRF_GRA }, // 1 Text layer tiles + + { "024-c1.c1", 0x100000, 0x3617c2dc, 3 | BRF_GRA }, // 2 Sprite data + { "024-c2.c2", 0x100000, 0x3f0a7fd8, 3 | BRF_GRA }, // 3 + { "024-c3.c3", 0x080000, 0xe9f745f8, 3 | BRF_GRA }, // 4 + { "024-c4.c4", 0x080000, 0x7382fefb, 3 | BRF_GRA }, // 5 + + { "024-m1.m1", 0x020000, 0xcec19742, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "024-v1.v1", 0x100000, 0xefdfa063, 5 | BRF_SND }, // 7 Sound data + { "024-v2.v2", 0x100000, 0x3c7997c0, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(lresort, lresort, neogeo) +STD_ROM_FN(lresort) + +struct BurnDriver BurnDrvLresort = { + "lresort", NULL, "neogeo", NULL, "1992", + "Last Resort\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0, + NULL, lresortRomInfo, lresortRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Eight Man (NGM-025)(NGH-025) + +static struct BurnRomInfo eightmanRomDesc[] = { + { "025-p1.p1", 0x080000, 0x43344cb0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "025-s1.s1", 0x020000, 0xa402202b, 2 | BRF_GRA }, // 1 Text layer tiles + + { "025-c1.c1", 0x100000, 0x555e16a4, 3 | BRF_GRA }, // 2 Sprite data + { "025-c2.c2", 0x100000, 0xe1ee51c3, 3 | BRF_GRA }, // 3 + { "025-c3.c3", 0x080000, 0x0923d5b0, 3 | BRF_GRA }, // 4 + { "025-c4.c4", 0x080000, 0xe3eca67b, 3 | BRF_GRA }, // 5 + + { "025-m1.m1", 0x020000, 0x9927034c, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "025-v1.v1", 0x100000, 0x4558558a, 5 | BRF_SND }, // 7 Sound data + { "025-v2.v2", 0x100000, 0xc5e052e9, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(eightman, eightman, neogeo) +STD_ROM_FN(eightman) + +struct BurnDriver BurnDrvEightman = { + "eightman", NULL, "neogeo", NULL, "1991", + "Eight Man (NGM-025)(NGH-025)\0", NULL, "SNK / Pallas", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, eightmanRomInfo, eightmanRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Legend of Success Joe / Ashitano Joe Densetsu + +static struct BurnRomInfo legendosRomDesc[] = { + { "029-p1.p1", 0x080000, 0x9d563f19, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "029-s1.s1", 0x020000, 0xbcd502f0, 2 | BRF_GRA }, // 1 Text layer tiles + + { "029-c1.c1", 0x100000, 0x2f5ab875, 3 | BRF_GRA }, // 2 Sprite data + { "029-c2.c2", 0x100000, 0x318b2711, 3 | BRF_GRA }, // 3 + { "029-c3.c3", 0x100000, 0x6bc52cb2, 3 | BRF_GRA }, // 4 + { "029-c4.c4", 0x100000, 0x37ef298c, 3 | BRF_GRA }, // 5 + + { "029-m1.m1", 0x020000, 0x6f2843f0, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "029-v1.v1", 0x100000, 0x85065452, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(legendos, legendos, neogeo) +STD_ROM_FN(legendos) + +struct BurnDriver BurnDrvLegendos = { + "legendos", NULL, "neogeo", NULL, "1991", + "Legend of Success Joe / Ashitano Joe Densetsu\0", NULL, "SNK", "Neo Geo MVS", + L"Legend of Success Joe / Ashitano Joe Densetsu\0\u3042\u3057\u305F\u306E\u30B8\u30E7\u30FC\u4F1D\u8AAC\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, legendosRomInfo, legendosRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// 2020 Super Baseball (set 1) + +static struct BurnRomInfo bb2020RomDesc[] = { + { "030-p1.p1", 0x080000, 0xd396c9cb, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "030-s1.s1", 0x020000, 0x7015b8fc, 2 | BRF_GRA }, // 1 Text layer tiles + + { "030-c1.c1", 0x100000, 0x4f5e19bd, 3 | BRF_GRA }, // 2 Sprite data + { "030-c2.c2", 0x100000, 0xd6314bf0, 3 | BRF_GRA }, // 3 + { "030-c3.c3", 0x100000, 0x47fddfee, 3 | BRF_GRA }, // 4 + { "030-c4.c4", 0x100000, 0x780d1c4e, 3 | BRF_GRA }, // 5 + + { "030-m1.m1", 0x020000, 0x4cf466ec, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "030-v1.v1", 0x100000, 0xd4ca364e, 5 | BRF_SND }, // 7 Sound data + { "030-v2.v2", 0x100000, 0x54994455, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(bb2020, bb2020, neogeo) +STD_ROM_FN(bb2020) + +struct BurnDriver BurnDrvbb2020 = { + "2020bb", NULL, "neogeo", NULL, "1991", + "2020 Super Baseball (set 1)\0", NULL, "SNK / Pallas", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bb2020RomInfo, bb2020RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// 2020 Super Baseball (set 2) + +static struct BurnRomInfo bba2020RomDesc[] = { + { "030-epr.p1", 0x080000, 0xc59be3dd, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "030-s1.s1", 0x020000, 0x7015b8fc, 2 | BRF_GRA }, // 1 Text layer tiles + + { "030-c1.c1", 0x100000, 0x4f5e19bd, 3 | BRF_GRA }, // 2 Sprite data + { "030-c2.c2", 0x100000, 0xd6314bf0, 3 | BRF_GRA }, // 3 + { "030-c3.c3", 0x100000, 0x47fddfee, 3 | BRF_GRA }, // 4 + { "030-c4.c4", 0x100000, 0x780d1c4e, 3 | BRF_GRA }, // 5 + + { "030-m1.m1", 0x020000, 0x4cf466ec, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "030-v1.v1", 0x100000, 0xd4ca364e, 5 | BRF_SND }, // 7 Sound data + { "030-v2.v2", 0x100000, 0x54994455, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(bba2020, bba2020, neogeo) +STD_ROM_FN(bba2020) + +struct BurnDriver BurnDrvbba2020 = { + "2020bba", "2020bb", "neogeo", NULL, "1991", + "2020 Super Baseball (set 2)\0", NULL, "SNK / Pallas", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bba2020RomInfo, bba2020RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// 2020 Super Baseball (set 3) + +static struct BurnRomInfo bbh2020RomDesc[] = { + { "030-pg1.p1", 0x080000, 0x12d048d7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "030-s1.s1", 0x020000, 0x7015b8fc, 2 | BRF_GRA }, // 1 Text layer tiles + + { "030-c1.c1", 0x100000, 0x4f5e19bd, 3 | BRF_GRA }, // 2 Sprite data + { "030-c2.c2", 0x100000, 0xd6314bf0, 3 | BRF_GRA }, // 3 + { "030-c3.c3", 0x100000, 0x47fddfee, 3 | BRF_GRA }, // 4 + { "030-c4.c4", 0x100000, 0x780d1c4e, 3 | BRF_GRA }, // 5 + + { "030-m1.m1", 0x020000, 0x4cf466ec, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "030-v1.v1", 0x100000, 0xd4ca364e, 5 | BRF_SND }, // 7 Sound data + { "030-v2.v2", 0x100000, 0x54994455, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(bbh2020, bbh2020, neogeo) +STD_ROM_FN(bbh2020) + +struct BurnDriver BurnDrvbbh2020 = { + "2020bbh", "2020bb", "neogeo", NULL, "1991", + "2020 Super Baseball (set 3)\0", NULL, "SNK / Pallas", "Neo Geo AES", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bbh2020RomInfo, bbh2020RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Soccer Brawl (NGM-031) + +static struct BurnRomInfo socbrawlRomDesc[] = { + { "031-pg1.p1", 0x080000, 0x17f034a7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "031-s1.s1", 0x020000, 0x4c117174, 2 | BRF_GRA }, // 1 Text layer tiles + + { "031-c1.c1", 0x100000, 0xbd0a4eb8, 3 | BRF_GRA }, // 2 Sprite data + { "031-c2.c2", 0x100000, 0xefde5382, 3 | BRF_GRA }, // 3 + { "031-c3.c3", 0x080000, 0x580f7f33, 3 | BRF_GRA }, // 4 + { "031-c4.c4", 0x080000, 0xed297de8, 3 | BRF_GRA }, // 5 + + { "031-m1.m1", 0x020000, 0xcb37427c, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "031-v1.v1", 0x100000, 0xcc78497e, 5 | BRF_SND }, // 7 Sound data + { "031-v2.v2", 0x100000, 0xdda043c6, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(socbrawl, socbrawl, neogeo) +STD_ROM_FN(socbrawl) + +struct BurnDriver BurnDrvSocbrawl = { + "socbrawl", NULL, "neogeo", NULL, "1991", + "Soccer Brawl (NGM-031)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSFOOTBALL, 0, + NULL, socbrawlRomInfo, socbrawlRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Soccer Brawl (NGH-031) + +static struct BurnRomInfo socbrawlhRomDesc[] = { + { "031-p1.p1", 0x080000, 0xa2801c24, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "031-s1.s1", 0x020000, 0x4c117174, 2 | BRF_GRA }, // 1 Text layer tiles + + { "031-c1.c1", 0x100000, 0xbd0a4eb8, 3 | BRF_GRA }, // 2 Sprite data + { "031-c2.c2", 0x100000, 0xefde5382, 3 | BRF_GRA }, // 3 + { "031-c3.c3", 0x080000, 0x580f7f33, 3 | BRF_GRA }, // 4 + { "031-c4.c4", 0x080000, 0xed297de8, 3 | BRF_GRA }, // 5 + + { "031-m1.m1", 0x020000, 0xcb37427c, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "031-v1.v1", 0x100000, 0xcc78497e, 5 | BRF_SND }, // 7 Sound data + { "031-v2.v2", 0x100000, 0xdda043c6, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(socbrawlh, socbrawlh, neogeo) +STD_ROM_FN(socbrawlh) + +struct BurnDriver BurnDrvSocbrawlh = { + "socbrawlh", "socbrawl", "neogeo", NULL, "1991", + "Soccer Brawl (NGH-031)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSFOOTBALL, 0, + NULL, socbrawlhRomInfo, socbrawlhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Fatal Fury - King of Fighters / Garou Densetsu - shukumei no tatakai (NGM-033)(NGH-033) + +static struct BurnRomInfo fatfury1RomDesc[] = { + { "033-p1.p1", 0x080000, 0x47ebdc2f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "033-p2.p2", 0x020000, 0xc473af1c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "033-s1.s1", 0x020000, 0x3c3bdf8c, 2 | BRF_GRA }, // 2 Text layer tiles + + { "033-c1.c1", 0x100000, 0x74317e54, 3 | BRF_GRA }, // 3 Sprite data + { "033-c2.c2", 0x100000, 0x5bb952f3, 3 | BRF_GRA }, // 4 + { "033-c3.c3", 0x100000, 0x9b714a7c, 3 | BRF_GRA }, // 5 + { "033-c4.c4", 0x100000, 0x9397476a, 3 | BRF_GRA }, // 6 + + { "033-m1.m1", 0x020000, 0x5be10ffd, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "033-v1.v1", 0x100000, 0x212fd20d, 5 | BRF_SND }, // 8 Sound data + { "033-v2.v2", 0x100000, 0xfa2ae47f, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(fatfury1, fatfury1, neogeo) +STD_ROM_FN(fatfury1) + +struct BurnDriver BurnDrvFatFury1 = { + "fatfury1", NULL, "neogeo", NULL, "1992", + "Fatal Fury - King of Fighters / Garou Densetsu - shukumei no tatakai (NGM-033)(NGH-033)\0", NULL, "SNK", "Neo Geo MVS", + L"Fatal Fury - King of Fighters\0\u9913\u72FC\u4F1D\u8AAC - \u5BBF\u547D\u306E\u95D8\u3044 (NGM-033)(NGH-033)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, fatfury1RomInfo, fatfury1RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Robo Army + +static struct BurnRomInfo roboarmyRomDesc[] = { + { "032-p1.p1", 0x080000, 0xcd11cbd4, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "032-s1.s1", 0x020000, 0xac0daa1b, 2 | BRF_GRA }, // 1 Text layer tiles + + { "032-c1.c1", 0x100000, 0x97984c6c, 3 | BRF_GRA }, // 2 Sprite data + { "032-c2.c2", 0x100000, 0x65773122, 3 | BRF_GRA }, // 3 + { "032-c3.c3", 0x080000, 0x40adfccd, 3 | BRF_GRA }, // 4 + { "032-c4.c4", 0x080000, 0x462571de, 3 | BRF_GRA }, // 5 + + { "032-m1.m1", 0x020000, 0x35ec952d, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "032-v1.v1", 0x100000, 0x63791533, 5 | BRF_SND }, // 7 Sound data + { "032-v2.v2", 0x100000, 0xeb95de70, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(roboarmy, roboarmy, neogeo) +STD_ROM_FN(roboarmy) + +struct BurnDriver BurnDrvRoboarmy = { + "roboarmy", NULL, "neogeo", NULL, "1991", + "Robo Army\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, roboarmyRomInfo, roboarmyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Football Frenzy (NGM-034)(NGH-034) + +static struct BurnRomInfo fbfrenzyRomDesc[] = { + { "034-p1.p1", 0x080000, 0xcdef6b19, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "034-s1.s1", 0x020000, 0x8472ed44, 2 | BRF_GRA }, // 1 Text layer tiles + + { "034-c1.c1", 0x100000, 0x91c56e78, 3 | BRF_GRA }, // 2 Sprite data + { "034-c2.c2", 0x100000, 0x9743ea2f, 3 | BRF_GRA }, // 3 + { "034-c3.c3", 0x080000, 0xe5aa65f5, 3 | BRF_GRA }, // 4 + { "034-c4.c4", 0x080000, 0x0eb138cc, 3 | BRF_GRA }, // 5 + + { "034-m1.m1", 0x020000, 0xf41b16b8, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "034-v1.v1", 0x100000, 0x50c9d0dd, 5 | BRF_SND }, // 7 Sound data + { "034-v2.v2", 0x100000, 0x5aa15686, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(fbfrenzy, fbfrenzy, neogeo) +STD_ROM_FN(fbfrenzy) + +struct BurnDriver BurnDrvFbfrenzy = { + "fbfrenzy", NULL, "neogeo", NULL, "1992", + "Football Frenzy (NGM-034)(NGH-034)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, fbfrenzyRomInfo, fbfrenzyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// King of the Monsters 2 - The Next Thing (NGM-039)(NGH-039) + +static struct BurnRomInfo kotm2RomDesc[] = { + { "039-p1.p1", 0x080000, 0xb372d54c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "039-p2.p2", 0x080000, 0x28661afe, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "039-s1.s1", 0x020000, 0x63ee053a, 2 | BRF_GRA }, // 2 Text layer tiles + + { "039-c1.c1", 0x200000, 0x6d1c4aa9, 3 | BRF_GRA }, // 3 Sprite data + { "039-c2.c2", 0x200000, 0xf7b75337, 3 | BRF_GRA }, // 4 + { "039-c3.c3", 0x080000, 0xbfc4f0b2, 3 | BRF_GRA }, // 5 + { "039-c4.c4", 0x080000, 0x81c9c250, 3 | BRF_GRA }, // 6 + + { "039-m1.m1", 0x020000, 0x0c5b2ad5, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "039-v2.v2", 0x200000, 0x86d34b25, 5 | BRF_SND }, // 8 Sound data + { "039-v4.v4", 0x100000, 0x8fa62a0b, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(kotm2, kotm2, neogeo) +STD_ROM_FN(kotm2) + +struct BurnDriver BurnDrvKotm2 = { + "kotm2", NULL, "neogeo", NULL, "1992", + "King of the Monsters 2 - The Next Thing (NGM-039)(NGH-039)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, kotm2RomInfo, kotm2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// King of the Monsters 2 - The Next Thing (prototype) + +static struct BurnRomInfo kotm2pRomDesc[] = { + { "p1.bin", 0x080000, 0x3c1d17e7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "p2.bin", 0x080000, 0xbc9691f0, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "s1.bin", 0x020000, 0x63ee053a, 2 | BRF_GRA }, // 2 Text layer tiles + + { "c1.bin", 0x100000, 0x7192a787, 3 | BRF_GRA }, // 3 Sprite data + { "c2.bin", 0x100000, 0x7157eca1, 3 | BRF_GRA }, // 4 + { "c3.bin", 0x100000, 0x11d75727, 3 | BRF_GRA }, // 5 + { "c4.bin", 0x100000, 0x7ad48b28, 3 | BRF_GRA }, // 6 + { "c5.bin", 0x080000, 0x5bdaf9ca, 3 | BRF_GRA }, // 7 + { "c6.bin", 0x080000, 0x21d4be8c, 3 | BRF_GRA }, // 8 + { "c7.bin", 0x080000, 0xda55fd00, 3 | BRF_GRA }, // 9 + { "c8.bin", 0x080000, 0x592e9267, 3 | BRF_GRA }, // 10 + + { "m1.bin", 0x020000, 0x0c5b2ad5, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "v1.bin", 0x080000, 0xdd3566f1, 5 | BRF_SND }, // 12 Sound data + { "v2.bin", 0x080000, 0x57f60274, 5 | BRF_SND }, // 13 + { "v3.bin", 0x080000, 0x0f008a07, 5 | BRF_SND }, // 14 + { "v4.bin", 0x080000, 0x1943d0fe, 5 | BRF_SND }, // 15 + { "v5.bin", 0x080000, 0x13be045b, 5 | BRF_SND }, // 16 + { "v6.bin", 0x080000, 0xd1dd3fd6, 5 | BRF_SND }, // 17 +}; + +STDROMPICKEXT(kotm2p, kotm2p, neogeo) +STD_ROM_FN(kotm2p) + +static void Kotm2pCallback() +{ + BurnLoadRom(Neo68KROMActive + 0x000000, 0, 2); + BurnLoadRom(Neo68KROMActive + 0x000001, 1, 2); +} + +static INT32 Kotm2pInit() +{ + NeoCallbackActive->pInitialise = Kotm2pCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvKotm2p = { + "kotm2p", "kotm2", "neogeo", NULL, "1992", + "King of the Monsters 2 - The Next Thing (prototype)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SPRITE32, GBF_VSFIGHT, 0, + NULL, kotm2pRomInfo, kotm2pRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + Kotm2pInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Sengoku 2 / Sengoku Denshou 2 + +static struct BurnRomInfo sengoku2RomDesc[] = { + { "040-p1.p1", 0x100000, 0x6dde02c2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "040-s1.s1", 0x020000, 0xcd9802a3, 2 | BRF_GRA }, // 1 Text layer tiles + + { "040-c1.c1", 0x200000, 0xfaa8ea99, 3 | BRF_GRA }, // 2 Sprite data + { "040-c2.c2", 0x200000, 0x87d0ec65, 3 | BRF_GRA }, // 3 + { "040-c3.c3", 0x080000, 0x24b5ba80, 3 | BRF_GRA }, // 4 + { "040-c4.c4", 0x080000, 0x1c9e9930, 3 | BRF_GRA }, // 5 + + { "040-m1.m1", 0x020000, 0xd4de4bca, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "040-v1.v1", 0x200000, 0x71cb4b5d, 5 | BRF_SND }, // 7 Sound data + { "040-v2.v2", 0x100000, 0xc5cece01, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(sengoku2, sengoku2, neogeo) +STD_ROM_FN(sengoku2) + +struct BurnDriver BurnDrvSengoku2 = { + "sengoku2", NULL, "neogeo", NULL, "1993", + "Sengoku 2 / Sengoku Denshou 2\0", NULL, "SNK", "Neo Geo MVS", + L"Sengoku 2\0\u6226\u56FD\u4F1D\u627F\uFF12\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_SCRFIGHT, 0, + NULL, sengoku2RomInfo, sengoku2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Baseball Stars 2 + +static struct BurnRomInfo bstars2RomDesc[] = { + { "041-p1.p1", 0x080000, 0x523567fd, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "041-s1.s1", 0x020000, 0x015c5c94, 2 | BRF_GRA }, // 1 Text layer tiles + + { "041-c1.c1", 0x100000, 0xb39a12e1, 3 | BRF_GRA }, // 2 Sprite data + { "041-c2.c2", 0x100000, 0x766cfc2f, 3 | BRF_GRA }, // 3 + { "041-c3.c3", 0x100000, 0xfb31339d, 3 | BRF_GRA }, // 4 + { "041-c4.c4", 0x100000, 0x70457a0c, 3 | BRF_GRA }, // 5 + + { "041-m1.m1", 0x020000, 0x15c177a6, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "041-v1.v1", 0x100000, 0xcb1da093, 5 | BRF_SND }, // 7 Sound data + { "041-v2.v2", 0x100000, 0x1c954a9d, 5 | BRF_SND }, // 8 + { "041-v3.v3", 0x080000, 0xafaa0180, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(bstars2, bstars2, neogeo) +STD_ROM_FN(bstars2) + +struct BurnDriver BurnDrvBstars2 = { + "bstars2", NULL, "neogeo", NULL, "1992", + "Baseball Stars 2\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, bstars2RomInfo, bstars2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Quiz Meitantei Neo & Geo - Quiz Daisousa Sen part 2 (NGM-042)(NGH-042) + +static struct BurnRomInfo quizdai2RomDesc[] = { + { "042-p1.p1", 0x100000, 0xed719dcf, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "042-s1.s1", 0x020000, 0x164fd6e6, 2 | BRF_GRA }, // 1 Text layer tiles + + { "042-c1.c1", 0x100000, 0xcb5809a1, 3 | BRF_GRA }, // 2 Sprite data + { "042-c2.c2", 0x100000, 0x1436dfeb, 3 | BRF_GRA }, // 3 + { "042-c3.c3", 0x080000, 0xbcd4a518, 3 | BRF_GRA }, // 4 + { "042-c4.c4", 0x080000, 0xd602219b, 3 | BRF_GRA }, // 5 + + { "042-m1.m1", 0x020000, 0xbb19995d, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "042-v1.v1", 0x100000, 0xaf7f8247, 5 | BRF_SND }, // 7 Sound data + { "042-v2.v2", 0x100000, 0xc6474b59, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(quizdai2, quizdai2, neogeo) +STD_ROM_FN(quizdai2) + +struct BurnDriver BurnDrvQuizdai2 = { + "quizdai2", NULL, "neogeo", NULL, "1992", + "Quiz Meitantei Neo & Geo - Quiz Daisousa Sen part 2 (NGM-042)(NGH-042)\0", NULL, "SNK", "Neo Geo MVS", + L"\u30AF\u30A4\u30BA\u8FF7\u63A2\u5075\u30CD\u30AA\uFF06\u30B8\u30AA - Quiz Daisousa Sen part 2 (NGM-042)(NGH-042)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, quizdai2RomInfo, quizdai2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// 3 Count Bout / Fire Suplex (NGM-043)(NGH-043) + +static struct BurnRomInfo countb3RomDesc[] = { + { "043-p1.p1", 0x100000, 0xffbdd928, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "043-s1.s1", 0x020000, 0xc362d484, 2 | BRF_GRA }, // 1 Text layer tiles + + { "043-c1.c1", 0x200000, 0xbad2d67f, 3 | BRF_GRA }, // 2 Sprite data + { "043-c2.c2", 0x200000, 0xa7fbda95, 3 | BRF_GRA }, // 3 + { "043-c3.c3", 0x200000, 0xf00be011, 3 | BRF_GRA }, // 4 + { "043-c4.c4", 0x200000, 0x1887e5c0, 3 | BRF_GRA }, // 5 + + { "043-m1.m1", 0x020000, 0x7eab59cb, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "043-v1.v1", 0x200000, 0x63688ce8, 5 | BRF_SND }, // 7 Sound data + { "043-v2.v2", 0x200000, 0xc69a827b, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(countb3, countb3, neogeo) +STD_ROM_FN(countb3) + +struct BurnDriver BurnDrv3Countb = { + "3countb", NULL, "neogeo", NULL, "1993", + "3 Count Bout / Fire Suplex (NGM-043)(NGH-043)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, countb3RomInfo, countb3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Art of Fighting / Ryuuko no Ken (NGM-044)(NGH-044) + +static struct BurnRomInfo aofRomDesc[] = { + { "044-p1.p1", 0x080000, 0xca9f7a6d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "044-s1.s1", 0x020000, 0x89903f39, 2 | BRF_GRA }, // 1 Text layer tiles + + { "044-c1.c1", 0x200000, 0xddab98a7, 3 | BRF_GRA }, // 2 Sprite data + { "044-c2.c2", 0x200000, 0xd8ccd575, 3 | BRF_GRA }, // 3 + { "044-c3.c3", 0x200000, 0x403e898a, 3 | BRF_GRA }, // 4 + { "044-c4.c4", 0x200000, 0x6235fbaa, 3 | BRF_GRA }, // 5 + + { "044-m1.m1", 0x020000, 0x0987e4bb, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "044-v2.v2", 0x200000, 0x3ec632ea, 5 | BRF_SND }, // 7 Sound data + { "044-v4.v4", 0x200000, 0x4b0f8e23, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(aof, aof, neogeo) +STD_ROM_FN(aof) + +struct BurnDriver BurnDrvAof = { + "aof", NULL, "neogeo", NULL, "1992", + "Art of Fighting / Ryuuko no Ken (NGM-044)(NGH-044)\0", NULL, "SNK", "Neo Geo MVS", + L"Art of Fighting\0\u9F8D\u864E\u306E\u62F3 (NGM-044)(NGH-044)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, aofRomInfo, aofRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown / Samurai Spirits (NGM-045) + +static struct BurnRomInfo samshoRomDesc[] = { + { "045-p1.p1", 0x100000, 0xdfe51bf0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "045-pg2.sp2", 0x100000, 0x46745b94, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "045-s1.s1", 0x020000, 0x9142a4d3, 2 | BRF_GRA }, // 2 Text layer tiles + + { "045-c1.c1", 0x200000, 0x2e5873a4, 3 | BRF_GRA }, // 3 Sprite data + { "045-c2.c2", 0x200000, 0x04febb10, 3 | BRF_GRA }, // 4 + { "045-c3.c3", 0x200000, 0xf3dabd1e, 3 | BRF_GRA }, // 5 + { "045-c4.c4", 0x200000, 0x935c62f0, 3 | BRF_GRA }, // 6 + { "045-c51.c5", 0x100000, 0x81932894, 3 | BRF_GRA }, // 7 + { "045-c61.c6", 0x100000, 0xbe30612e, 3 | BRF_GRA }, // 8 + + { "045-m1.m1", 0x020000, 0x95170640, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "045-v1.v1", 0x200000, 0x37f78a9b, 5 | BRF_SND }, // 10 Sound data + { "045-v2.v2", 0x200000, 0x568b20cf, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(samsho, samsho, neogeo) +STD_ROM_FN(samsho) + +struct BurnDriver BurnDrvSamSho = { + "samsho", NULL, "neogeo", NULL, "1993", + "Samurai Shodown / Samurai Spirits (NGM-045)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samshoRomInfo, samshoRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Samurai Shodown / Samurai Spirits (NGH-045) + +static struct BurnRomInfo samshohRomDesc[] = { + { "045-p1.p1", 0x100000, 0xdfe51bf0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "045-p2.sp2", 0x080000, 0x38ee9ba9, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "045-s1.s1", 0x020000, 0x9142a4d3, 2 | BRF_GRA }, // 2 Text layer tiles + + { "045-c1.c1", 0x200000, 0x2e5873a4, 3 | BRF_GRA }, // 3 Sprite data + { "045-c2.c2", 0x200000, 0x04febb10, 3 | BRF_GRA }, // 4 + { "045-c3.c3", 0x200000, 0xf3dabd1e, 3 | BRF_GRA }, // 5 + { "045-c4.c4", 0x200000, 0x935c62f0, 3 | BRF_GRA }, // 6 + { "045-c5.c5", 0x080000, 0xa2bb8284, 3 | BRF_GRA }, // 7 + { "045-c6.c6", 0x080000, 0x4fa71252, 3 | BRF_GRA }, // 8 + + { "045-m1.m1", 0x020000, 0x95170640, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "045-v1.v1", 0x200000, 0x37f78a9b, 5 | BRF_SND }, // 10 Sound data + { "045-v2.v2", 0x200000, 0x568b20cf, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(samshoh, samshoh, neogeo) +STD_ROM_FN(samshoh) + +struct BurnDriver BurnDrvSamShoh = { + "samshoh", "samsho", "neogeo", NULL, "1993", + "Samurai Shodown / Samurai Spirits (NGH-045)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samshohRomInfo, samshohRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Top Hunter - Roddy & Cathy (NGM-046) + +static struct BurnRomInfo tophuntrRomDesc[] = { + { "046-p1.p1", 0x100000, 0x69fa9e29, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "046-p2.sp2", 0x100000, 0xf182cb3e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "046-s1.s1", 0x020000, 0x14b01d7b, 2 | BRF_GRA }, // 2 Text layer tiles + + { "046-c1.c1", 0x100000, 0xfa720a4a, 3 | BRF_GRA }, // 3 Sprite data + { "046-c2.c2", 0x100000, 0xc900c205, 3 | BRF_GRA }, // 4 + { "046-c3.c3", 0x100000, 0x880e3c25, 3 | BRF_GRA }, // 5 + { "046-c4.c4", 0x100000, 0x7a2248aa, 3 | BRF_GRA }, // 6 + { "046-c5.c5", 0x100000, 0x4b735e45, 3 | BRF_GRA }, // 7 + { "046-c6.c6", 0x100000, 0x273171df, 3 | BRF_GRA }, // 8 + { "046-c7.c7", 0x100000, 0x12829c4c, 3 | BRF_GRA }, // 9 + { "046-c8.c8", 0x100000, 0xc944e03d, 3 | BRF_GRA }, // 10 + + { "046-m1.m1", 0x020000, 0x3f84bb9f, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "046-v1.v1", 0x100000, 0xc1f9c2db, 5 | BRF_SND }, // 12 Sound data + { "046-v2.v2", 0x100000, 0x56254a64, 5 | BRF_SND }, // 13 + { "046-v3.v3", 0x100000, 0x58113fb1, 5 | BRF_SND }, // 14 + { "046-v4.v4", 0x100000, 0x4f54c187, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(tophuntr, tophuntr, neogeo) +STD_ROM_FN(tophuntr) + +struct BurnDriver BurnDrvtophntr = { + "tophuntr", NULL, "neogeo", NULL, "1994", + "Top Hunter - Roddy & Cathy (NGM-046)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, tophuntrRomInfo, tophuntrRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Top Hunter - Roddy & Cathy (NGH-046) + +static struct BurnRomInfo tophuntrhRomDesc[] = { + { "046-pg1.p1", 0x100000, 0x771e39bc, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "046-p2.sp2", 0x100000, 0xf182cb3e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "046-sg1.s1", 0x020000, 0x92e9ac8c, 2 | BRF_GRA }, // 2 Text layer tiles + + { "046-c1.c1", 0x100000, 0xfa720a4a, 3 | BRF_GRA }, // 3 Sprite data + { "046-c2.c2", 0x100000, 0xc900c205, 3 | BRF_GRA }, // 4 + { "046-c3.c3", 0x100000, 0x880e3c25, 3 | BRF_GRA }, // 5 + { "046-c4.c4", 0x100000, 0x7a2248aa, 3 | BRF_GRA }, // 6 + { "046-c5.c5", 0x100000, 0x4b735e45, 3 | BRF_GRA }, // 7 + { "046-c6.c6", 0x100000, 0x273171df, 3 | BRF_GRA }, // 8 + { "046-c7.c7", 0x100000, 0x12829c4c, 3 | BRF_GRA }, // 9 + { "046-c8.c8", 0x100000, 0xc944e03d, 3 | BRF_GRA }, // 10 + + { "046-m1.m1", 0x020000, 0x3f84bb9f, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "046-v1.v1", 0x100000, 0xc1f9c2db, 5 | BRF_SND }, // 12 Sound data + { "046-v2.v2", 0x100000, 0x56254a64, 5 | BRF_SND }, // 13 + { "046-v3.v3", 0x100000, 0x58113fb1, 5 | BRF_SND }, // 14 + { "046-v4.v4", 0x100000, 0x4f54c187, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(tophuntrh, tophuntrh, neogeo) +STD_ROM_FN(tophuntrh) + +struct BurnDriver BurnDrvtophntrh = { + "tophuntrh", "tophuntr", "neogeo", NULL, "1994", + "Top Hunter - Roddy & Cathy (NGH-046)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, tophuntrhRomInfo, tophuntrhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Fatal Fury 2 / Garou Densetsu 2 - arata-naru tatakai (NGM-047)(NGH-047) + +static struct BurnRomInfo fatfury2RomDesc[] = { + { "047-p1.p1", 0x100000, 0xecfdbb69, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "047-s1.s1", 0x020000, 0xd7dbbf39, 2 | BRF_GRA }, // 2 Text layer tiles + + { "047-c1.c1", 0x200000, 0xf72a939e, 3 | BRF_GRA }, // 3 Sprite data + { "047-c2.c2", 0x200000, 0x05119a0d, 3 | BRF_GRA }, // 4 + { "047-c3.c3", 0x200000, 0x01e00738, 3 | BRF_GRA }, // 5 + { "047-c4.c4", 0x200000, 0x9fe27432, 3 | BRF_GRA }, // 6 + + { "047-m1.m1", 0x020000, 0x820b0ba7, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "047-v1.v1", 0x200000, 0xd9d00784, 5 | BRF_SND }, // 8 Sound data + { "047-v2.v2", 0x200000, 0x2c9a4b33, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(fatfury2, fatfury2, neogeo) +STD_ROM_FN(fatfury2) + +static INT32 prot_data; + +UINT8 __fastcall fatfury2ReadByteProtection(UINT32 sekAddress) +{ + UINT16 res = (prot_data >> 24) & 0xFF; + +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X read byte (PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + switch (sekAddress) { + case 0x255551: + case 0x2FFFF1: + case 0x200001: + case 0x2FF001: + + case 0x236001: + case 0x236009: +// bprintf(PRINT_NORMAL, _T(" - prot read byte: 0x%02X (PC: 0x%06X)\n"), res, SekGetPC(-1)); + return res; + + case 0x236005: + case 0x23600D: +// bprintf(PRINT_NORMAL, _T(" - prot read byte: 0x%02X (PC: 0x%06X)\n"), ((res & 0xF0) >> 4) | ((res & 0x0F) << 4), SekGetPC(-1)); + return ((res & 0xF0) >> 4) | ((res & 0x0F) << 4); + +// default: +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X read byte (PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + } + + return 0; +} + +UINT16 __fastcall fatfury2ReadWordProtection(UINT32 sekAddress) +{ + UINT16 res = (prot_data >> 24) & 0xFF; + +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X read word (PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + switch (sekAddress) { + case 0x255550: + case 0x2FFFF0: + case 0x200000: + case 0x2FF000: + + case 0x236000: + case 0x236008: +// bprintf(PRINT_NORMAL, _T(" - prot read word: 0x%02X (PC: 0x%06X)\n"), res, SekGetPC(-1)); + return res; + + case 0x236004: + case 0x23600C: +// bprintf(PRINT_NORMAL, _T(" - prot read word: 0x%02X (PC: 0x%06X)\n"), ((res & 0xF0) >> 4) | ((res & 0x0F) << 4), SekGetPC(-1)); + return ((res & 0xF0) >> 4) | ((res & 0x0F) << 4); + +// default: +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X read word (PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + } + + return 0; +} + +void __fastcall fatfury2WriteByteProtection(UINT32 sekAddress, UINT8 /*byteValue*/) +{ +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + + switch (sekAddress) { + case 0x255551: + case 0x2FFFF1: + case 0x2FF001: + + case 0x236001: + case 0x236005: + case 0x236009: + case 0x23600D: + prot_data <<= 8; + break; + +// default: +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X -> 0x%02X\n"), sekAddress, byteValue); + } +} + +void __fastcall fatfury2WriteWordProtection(UINT32 sekAddress, UINT16 /*wordValue*/) +{ +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X -> 0x%04X (PC: 0x%06X)\n"), sekAddress, wordValue, SekGetPC(-1)); + + switch (sekAddress) { + case 0x211112: // data = 0x1111, expects 0xFF000000 back + prot_data = 0xFF000000; +/* + prot_data = (wordValue & 0x1000) << 19; + prot_data |= (wordValue & 0x0100) << 22; + prot_data |= (wordValue & 0x0010) << 25; + prot_data |= (wordValue & 0x0001) << 28; + + prot_data |= prot_data >> 4; +*/ +// bprintf(PRINT_NORMAL, _T(" prot data -> 0x%08X\n"), prot_data); + break; + + case 0x233332: // data = 0x3333, expects 0x0000FFFF back + prot_data = 0x0000FFFF; +/* + prot_data = wordValue << 0; + prot_data |= wordValue << 2; +*/ +// bprintf(PRINT_NORMAL, _T(" prot data -> 0x%08X\n"), prot_data); + break; + + case 0x244442: // data = 0x4444, expects 0x00FF0000 back + prot_data = 0x00FF0000; +/* + prot_data = (wordValue & 0x4000) << 9; + prot_data |= (wordValue & 0x0400) << 12; + prot_data |= (wordValue & 0x0040) << 15; + prot_data |= (wordValue & 0x0004) << 18; + + prot_data |= prot_data >> 4; +*/ +// bprintf(PRINT_NORMAL, _T(" prot data -> 0x%08X\n"), prot_data); + break; + + case 0x255552: // data == 0x5555; read back from 55550, ffff0, 00000, ff000 + prot_data = 0xFF00FF00; + break; + + case 0x256782: // data == 0x1234; read back from 36000 *or* 36004 + prot_data = 0xF05A3601; + break; + + case 0x242812: // data == 0x1824; read back from 36008 *or* 3600c + prot_data = 0x81422418; + break; + +// default: +// bprintf(PRINT_NORMAL, _T(" - prot 0x%06X -> 0x%02X\n"), sekAddress, wordValue); + } +} + +INT32 fatfury2Scan(INT32 nAction, INT32* /*pnMin*/) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(prot_data); + } + + return 0; +} + +static void fatfury2InstallHanders() +{ + // Install protection handler + SekMapHandler(6, 0x200000, 0x2FFFFF, SM_WRITE); + SekMapHandler(6, 0x200000, 0x2FFFFF, SM_READ); + SekSetWriteWordHandler(6, fatfury2WriteWordProtection); + SekSetWriteByteHandler(6, fatfury2WriteByteProtection); + SekSetReadWordHandler(6, fatfury2ReadWordProtection); + SekSetReadByteHandler(6, fatfury2ReadByteProtection); +} + +static INT32 fatfury2Init() +{ + NeoCallbackActive->pInstallHandlers = fatfury2InstallHanders; + NeoCallbackActive->pScan = fatfury2Scan; + + return NeoInit(); +} + +struct BurnDriver BurnDrvFatfury2 = { + "fatfury2", NULL, "neogeo", NULL, "1992", + "Fatal Fury 2 / Garou Densetsu 2 - arata-naru tatakai (NGM-047)(NGH-047)\0", NULL, "SNK", "Neo Geo MVS", + L"Fatal Fury 2\0\u9913\u72FC\u4F1D\u8AAC\uFF12 - \u65B0\u305F\u306A\u308B\u95D8 (NGM-047)(NGH-047)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, FBF_FATFURY, + NULL, fatfury2RomInfo, fatfury2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + fatfury2Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Super Sidekicks / Tokuten Ou + +static struct BurnRomInfo ssidekiRomDesc[] = { + { "052-p1.p1", 0x080000, 0x9cd97256, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "052-s1.s1", 0x020000, 0x97689804, 2 | BRF_GRA }, // 1 Text layer tiles + + { "052-c1.c1", 0x200000, 0x53e1c002, 3 | BRF_GRA }, // 2 Sprite data + { "052-c2.c2", 0x200000, 0x776a2d1f, 3 | BRF_GRA }, // 3 + + { "052-m1.m1", 0x020000, 0x49f17d2d, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "052-v1.v1", 0x200000, 0x22c097a5, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(ssideki, ssideki, neogeo) +STD_ROM_FN(ssideki) + +// This game uses protection similar to Fatal Fury 2 + +struct BurnDriver BurnDrvSsideki = { + "ssideki", NULL, "neogeo", NULL, "1992", + "Super Sidekicks / Tokuten Ou\0", NULL, "SNK", "Neo Geo MVS", + L"Super Sidekicks\0\u5F97\u70B9\u738B\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_SPORTSFOOTBALL, 0, + NULL, ssidekiRomInfo, ssidekiRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + fatfury2Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '94 (NGM-055)(NGH-055) + +static struct BurnRomInfo kof94RomDesc[] = { + { "055-p1.p1", 0x200000, 0xf10a2042, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "055-s1.s1", 0x020000, 0x825976c1, 2 | BRF_GRA }, // 1 Text layer tiles + + { "055-c1.c1", 0x200000, 0xb96ef460, 3 | BRF_GRA }, // 2 Sprite data + { "055-c2.c2", 0x200000, 0x15e096a7, 3 | BRF_GRA }, // 3 + { "055-c3.c3", 0x200000, 0x54f66254, 3 | BRF_GRA }, // 4 + { "055-c4.c4", 0x200000, 0x0b01765f, 3 | BRF_GRA }, // 5 + { "055-c5.c5", 0x200000, 0xee759363, 3 | BRF_GRA }, // 6 + { "055-c6.c6", 0x200000, 0x498da52c, 3 | BRF_GRA }, // 7 + { "055-c7.c7", 0x200000, 0x62f66888, 3 | BRF_GRA }, // 8 + { "055-c8.c8", 0x200000, 0xfe0a235d, 3 | BRF_GRA }, // 9 + + { "055-m1.m1", 0x020000, 0xf6e77cf5, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "055-v1.v1", 0x200000, 0x8889596d, 5 | BRF_SND }, // 11 Sound data + { "055-v2.v2", 0x200000, 0x25022b27, 5 | BRF_SND }, // 12 + { "055-v3.v3", 0x200000, 0x83cf32c0, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof94, kof94, neogeo) +STD_ROM_FN(kof94) + +struct BurnDriver BurnDrvKof94 = { + "kof94", NULL, "neogeo", NULL, "1994", + "The King of Fighters '94 (NGM-055)(NGH-055)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, FBF_KOF, + NULL, kof94RomInfo, kof94RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Art of Fighting 2 / Ryuuko no Ken 2 (NGM-056) + +static struct BurnRomInfo aof2RomDesc[] = { + { "056-p1.p1", 0x100000, 0xa3b1d021, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "056-s1.s1", 0x020000, 0x8b02638e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "056-c1.c1", 0x200000, 0x17b9cbd2, 3 | BRF_GRA }, // 2 Sprite data + { "056-c2.c2", 0x200000, 0x5fd76b67, 3 | BRF_GRA }, // 3 + { "056-c3.c3", 0x200000, 0xd2c88768, 3 | BRF_GRA }, // 4 + { "056-c4.c4", 0x200000, 0xdb39b883, 3 | BRF_GRA }, // 5 + { "056-c5.c5", 0x200000, 0xc3074137, 3 | BRF_GRA }, // 6 + { "056-c6.c6", 0x200000, 0x31de68d3, 3 | BRF_GRA }, // 7 + { "056-c7.c7", 0x200000, 0x3f36df57, 3 | BRF_GRA }, // 8 + { "056-c8.c8", 0x200000, 0xe546d7a8, 3 | BRF_GRA }, // 9 + + { "056-m1.m1", 0x020000, 0xf27e9d52, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "056-v1.v1", 0x200000, 0x4628fde0, 5 | BRF_SND }, // 11 Sound data + { "056-v2.v2", 0x200000, 0xb710e2f2, 5 | BRF_SND }, // 12 + { "056-v3.v3", 0x100000, 0xd168c301, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(aof2, aof2, neogeo) +STD_ROM_FN(aof2) + +struct BurnDriver BurnDrvAof2 = { + "aof2", NULL, "neogeo", NULL, "1994", + "Art of Fighting 2 / Ryuuko no Ken 2 (NGM-056)\0", NULL, "SNK", "Neo Geo MVS", + L"Art of Fighting 2\0\u9F8D\u864E\u306E\u62F3\uFF12 (NGM-056)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, aof2RomInfo, aof2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Art of Fighting 2 / Ryuuko no Ken 2 (NGH-056) + +static struct BurnRomInfo aof2aRomDesc[] = { + { "056-p1.p1", 0x100000, 0xa3b1d021, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "056-s1.s1", 0x020000, 0x8b02638e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "056-c1.c1", 0x200000, 0x17b9cbd2, 3 | BRF_GRA }, // 2 Sprite data + { "056-c2.c2", 0x200000, 0x5fd76b67, 3 | BRF_GRA }, // 3 + { "056-c3.c3", 0x200000, 0xd2c88768, 3 | BRF_GRA }, // 4 + { "056-c4.c4", 0x200000, 0xdb39b883, 3 | BRF_GRA }, // 5 + { "056-c5.c5", 0x200000, 0xc3074137, 3 | BRF_GRA }, // 6 + { "056-c6.c6", 0x200000, 0x31de68d3, 3 | BRF_GRA }, // 7 + { "056-c7.c7", 0x200000, 0x3f36df57, 3 | BRF_GRA }, // 8 + { "056-c8.c8", 0x200000, 0xe546d7a8, 3 | BRF_GRA }, // 9 + + { "056-m1.m1", 0x020000, 0xf27e9d52, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "056-v1.v1", 0x200000, 0x4628fde0, 5 | BRF_SND }, // 11 Sound data + { "056-v2.v2", 0x200000, 0xb710e2f2, 5 | BRF_SND }, // 12 + { "056-v3.v3", 0x100000, 0xd168c301, 5 | BRF_SND }, // 13 + + { "056-epr.ep1", 0x080000, 0x75d6301c, 0 | BRF_ESS | BRF_PRG }, // 14 +}; + +STDROMPICKEXT(aof2a, aof2a, neogeo) +STD_ROM_FN(aof2a) + +static void aof2aCallback() +{ + BurnLoadRom(Neo68KROMActive, 14, 1); +} + +static INT32 aof2aInit() +{ + NeoCallbackActive->pInitialise = aof2aCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvAof2a = { + "aof2a", "aof2", "neogeo", NULL, "1994", + "Art of Fighting 2 / Ryuuko no Ken 2 (NGH-056)\0", NULL, "SNK", "Neo Geo MVS", + L"Art of Fighting 2\0\u9F8D\u864E\u306E\u62F3\uFF12 (NGH-056)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, aof2aRomInfo, aof2aRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + aof2aInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Fatal Fury Special / Garou Densetsu Special (set 1)(NGM-058)(NGH-058) + +static struct BurnRomInfo fatfurspRomDesc[] = { + { "058-p1.p1", 0x100000, 0x2f585ba2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "058-p2.sp2", 0x080000, 0xd7c71a6b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "058-s1.s1", 0x020000, 0x2df03197, 2 | BRF_GRA }, // 2 Text layer tiles + + { "058-c1.c1", 0x200000, 0x044ab13c, 3 | BRF_GRA }, // 3 Sprite data + { "058-c2.c2", 0x200000, 0x11e6bf96, 3 | BRF_GRA }, // 4 + { "058-c3.c3", 0x200000, 0x6f7938d5, 3 | BRF_GRA }, // 5 + { "058-c4.c4", 0x200000, 0x4ad066ff, 3 | BRF_GRA }, // 6 + { "058-c5.c5", 0x200000, 0x49c5e0bf, 3 | BRF_GRA }, // 7 + { "058-c6.c6", 0x200000, 0x8ff1f43d, 3 | BRF_GRA }, // 8 + + { "058-m1.m1", 0x020000, 0xccc5186e, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "058-v1.v1", 0x200000, 0x55d7ce84, 5 | BRF_SND }, // 10 Sound data + { "058-v2.v2", 0x200000, 0xee080b10, 5 | BRF_SND }, // 11 + { "058-v3.v3", 0x100000, 0xf9eb3d4a, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(fatfursp, fatfursp, neogeo) +STD_ROM_FN(fatfursp) + +struct BurnDriver BurnDrvFatfursp = { + "fatfursp", NULL, "neogeo", NULL, "1993", + "Fatal Fury Special / Garou Densetsu Special (set 1)(NGM-058)(NGH-058)\0", NULL, "SNK", "Neo Geo MVS", + L"Fatal Fury Special\0\u9913\u72FC\u4F1D\u8AAC Special (set 1)(NGM-058)(NGH-058)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, fatfurspRomInfo, fatfurspRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Fatal Fury Special / Garou Densetsu Special (set 2)(NGM-058)(NGH-058) + +static struct BurnRomInfo fatfurspaRomDesc[] = { + { "058-p1.p1", 0x100000, 0x2f585ba2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "058-p2.sp2", 0x080000, 0xd7c71a6b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "058-s1.s1", 0x020000, 0x2df03197, 2 | BRF_GRA }, // 2 Text layer tiles + + { "058-c1.c1", 0x200000, 0x044ab13c, 3 | BRF_GRA }, // 3 Sprite data + { "058-c2.c2", 0x200000, 0x11e6bf96, 3 | BRF_GRA }, // 4 + { "058-c3.c3", 0x200000, 0x6f7938d5, 3 | BRF_GRA }, // 5 + { "058-c4.c4", 0x200000, 0x4ad066ff, 3 | BRF_GRA }, // 6 + { "058-c5.c5", 0x200000, 0x49c5e0bf, 3 | BRF_GRA }, // 7 + { "058-c6.c6", 0x200000, 0x8ff1f43d, 3 | BRF_GRA }, // 8 + + { "058-m1.m1", 0x020000, 0xccc5186e, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "058-v1.v1", 0x200000, 0x55d7ce84, 5 | BRF_SND }, // 10 Sound data + { "058-v2.v2", 0x200000, 0xee080b10, 5 | BRF_SND }, // 11 + { "058-v3.v3", 0x100000, 0xf9eb3d4a, 5 | BRF_SND }, // 12 + + { "058-epr.ep1", 0x080000, 0x9f0c1e1a, 0 | BRF_ESS | BRF_PRG }, // 13 +}; + +STDROMPICKEXT(fatfurspa, fatfurspa, neogeo) +STD_ROM_FN(fatfurspa) + +static void fatfurspaCallback() +{ + BurnLoadRom(Neo68KROMActive, 13, 1); +} + +static INT32 fatfurspaInit() +{ + NeoCallbackActive->pInitialise = fatfurspaCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvFatfurspa = { + "fatfurspa", "fatfursp", "neogeo", NULL, "1993", + "Fatal Fury Special / Garou Densetsu Special (set 2)(NGM-058)(NGH-058)\0", NULL, "SNK", "Neo Geo MVS", + L"Fatal Fury Special\0\u9913\u72FC\u4F1D\u8AAC Special (set 2)(NGM-058)(NGH-058)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, fatfurspaRomInfo, fatfurspaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + fatfurspaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Savage Reign / Fu'un Mokushiroku - kakutou sousei + +static struct BurnRomInfo savagereRomDesc[] = { + { "059-p1.p1", 0x200000, 0x01d4e9c0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "059-s1.s1", 0x020000, 0xe08978ca, 2 | BRF_GRA }, // 1 Text layer tiles + + { "059-c1.c1", 0x200000, 0x763ba611, 3 | BRF_GRA }, // 2 Sprite data + { "059-c2.c2", 0x200000, 0xe05e8ca6, 3 | BRF_GRA }, // 3 + { "059-c3.c3", 0x200000, 0x3e4eba4b, 3 | BRF_GRA }, // 4 + { "059-c4.c4", 0x200000, 0x3c2a3808, 3 | BRF_GRA }, // 5 + { "059-c5.c5", 0x200000, 0x59013f9e, 3 | BRF_GRA }, // 6 + { "059-c6.c6", 0x200000, 0x1c8d5def, 3 | BRF_GRA }, // 7 + { "059-c7.c7", 0x200000, 0xc88f7035, 3 | BRF_GRA }, // 8 + { "059-c8.c8", 0x200000, 0x484ce3ba, 3 | BRF_GRA }, // 9 + + { "059-m1.m1", 0x020000, 0x29992eba, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "059-v1.v1", 0x200000, 0x530c50fd, 5 | BRF_SND }, // 11 Sound data + { "059-v2.v2", 0x200000, 0xeb6f1cdb, 5 | BRF_SND }, // 12 + { "059-v3.v3", 0x200000, 0x7038c2f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(savagere, savagere, neogeo) +STD_ROM_FN(savagere) + +struct BurnDriver BurnDrvSavagere = { + "savagere", NULL, "neogeo", NULL, "1995", + "Savage Reign / Fu'un Mokushiroku - kakutou sousei\0", NULL, "SNK", "Neo Geo MVS", + L"Savage Reign\0\u98A8\u96F2\u9ED9\u793A\u9332 - \u683C\u95D8\u5275\u4E16\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, savagereRomInfo, savagereRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Super Sidekicks 2 - The World Championship / Tokuten Ou 2 - real fight football (NGM-061)(NGH-061) + +static struct BurnRomInfo ssideki2RomDesc[] = { + { "061-p1.p1", 0x100000, 0x5969e0dc, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "061-s1.s1", 0x020000, 0x226d1b68, 2 | BRF_GRA }, // 1 Text layer tiles + + { "061-c1-16.c1", 0x200000, 0xa626474f, 3 | BRF_GRA }, // 2 Sprite data + { "061-c2-16.c2", 0x200000, 0xc3be42ae, 3 | BRF_GRA }, // 3 + { "061-c3-16.c3", 0x200000, 0x2a7b98b9, 3 | BRF_GRA }, // 4 + { "061-c4-16.c4", 0x200000, 0xc0be9a1f, 3 | BRF_GRA }, // 5 + + { "061-m1.m1", 0x020000, 0x156f6951, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "061-v1.v1", 0x200000, 0xf081c8d3, 5 | BRF_SND }, // 7 Sound data + { "061-v2.v2", 0x200000, 0x7cd63302, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(ssideki2, ssideki2, neogeo) +STD_ROM_FN(ssideki2) + +struct BurnDriver BurnDrvSsideki2 = { + "ssideki2", NULL, "neogeo", NULL, "1994", + "Super Sidekicks 2 - The World Championship / Tokuten Ou 2 - real fight football (NGM-061)(NGH-061)\0", NULL, "SNK", "Neo Geo MVS", + L"Super Sidekicks 2 - the world championship\0\u5F97\u70B9\u738B\uFF12 - \u30EA\u30A2\u30EB\u30D5\u30A1\u30A4\u30C8\u30D5\u30C3\u30C8\u30DC\u30FC\u30EB (NGM-061)(NGH-061)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSFOOTBALL, 0, + NULL, ssideki2RomInfo, ssideki2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Samurai Shodown II / Shin Samurai Spirits - Haohmaru jigokuhen (NGM-063)(NGH-063) + +static struct BurnRomInfo samsho2RomDesc[] = { + { "063-p1.p1", 0x200000, 0x22368892, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "063-s1.s1", 0x020000, 0x64a5cd66, 2 | BRF_GRA }, // 1 Text layer tiles + + { "063-c1.c1", 0x200000, 0x86cd307c, 3 | BRF_GRA }, // 2 Sprite data + { "063-c2.c2", 0x200000, 0xcdfcc4ca, 3 | BRF_GRA }, // 3 + { "063-c3.c3", 0x200000, 0x7a63ccc7, 3 | BRF_GRA }, // 4 + { "063-c4.c4", 0x200000, 0x751025ce, 3 | BRF_GRA }, // 5 + { "063-c5.c5", 0x200000, 0x20d3a475, 3 | BRF_GRA }, // 6 + { "063-c6.c6", 0x200000, 0xae4c0a88, 3 | BRF_GRA }, // 7 + { "063-c7.c7", 0x200000, 0x2df3cbcf, 3 | BRF_GRA }, // 8 + { "063-c8.c8", 0x200000, 0x1ffc6dfa, 3 | BRF_GRA }, // 9 + + { "063-m1.m1", 0x020000, 0x56675098, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "063-v1.v1", 0x200000, 0x37703f91, 5 | BRF_SND }, // 11 Sound data + { "063-v2.v2", 0x200000, 0x0142bde8, 5 | BRF_SND }, // 12 + { "063-v3.v3", 0x200000, 0xd07fa5ca, 5 | BRF_SND }, // 13 + { "063-v4.v4", 0x100000, 0x24aab4bb, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(samsho2, samsho2, neogeo) +STD_ROM_FN(samsho2) + +struct BurnDriver BurnDrvSamSho2 = { + "samsho2", NULL, "neogeo", NULL, "1994", + "Samurai Shodown II / Shin Samurai Spirits - Haohmaru jigokuhen (NGM-063)(NGH-063)\0", NULL, "SNK", "Neo Geo MVS", + L"Samurai Shodown II\0\u771F Samurai Spirits - \u8987\u738B\u4E38\u5730\u7344\u5909 (NGM-063)(NGH-063)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho2RomInfo, samsho2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Saulabi Spirits / Jin Saulabi Tu Hon (Korean release of Samurai Shodown II) + +static struct BurnRomInfo samsho2kRomDesc[] = { + { "063-p1-kan.p1",0x200000, 0x147cc6d7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "063-s1-kan.s1",0x020000, 0xff08f80b, 2 | BRF_GRA }, // 1 Text layer tiles + + { "063-c1.c1", 0x200000, 0x86cd307c, 3 | BRF_GRA }, // 2 Sprite data + { "063-c2.c2", 0x200000, 0xcdfcc4ca, 3 | BRF_GRA }, // 3 + { "063-c3.c3", 0x200000, 0x7a63ccc7, 3 | BRF_GRA }, // 4 + { "063-c4.c4", 0x200000, 0x751025ce, 3 | BRF_GRA }, // 5 + { "063-c5.c5", 0x200000, 0x20d3a475, 3 | BRF_GRA }, // 6 + { "063-c6.c6", 0x200000, 0xae4c0a88, 3 | BRF_GRA }, // 7 + { "063-c7.c7", 0x200000, 0x2df3cbcf, 3 | BRF_GRA }, // 8 + { "063-c8.c8", 0x200000, 0x1ffc6dfa, 3 | BRF_GRA }, // 9 + + { "063-m1.m1", 0x020000, 0x56675098, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "063-v1.v1", 0x200000, 0x37703f91, 5 | BRF_SND }, // 11 Sound data + { "063-v2.v2", 0x200000, 0x0142bde8, 5 | BRF_SND }, // 12 + { "063-v3.v3", 0x200000, 0xd07fa5ca, 5 | BRF_SND }, // 13 + { "063-v4.v4", 0x100000, 0x24aab4bb, 5 | BRF_SND }, // 14 + + { "063-ep1-kan.ep1", 0x080000, 0xfa32e2d8, 0 | BRF_ESS | BRF_PRG }, // 15 + { "063-ep2-kan.ep2", 0x080000, 0x70b1a4d9, 0 | BRF_ESS | BRF_PRG }, // 16 +}; + +STDROMPICKEXT(samsho2k, samsho2k, neogeo) +STD_ROM_FN(samsho2k) + +static void samsho2kCallback() +{ + BurnLoadRom(Neo68KROMActive + 0x000000, 15, 1); + BurnLoadRom(Neo68KROMActive + 0x080000, 16, 1); +} + +static INT32 samsho2kInit() +{ + NeoCallbackActive->pInitialise = samsho2kCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvsamsho2k = { + "samsho2k", "samsho2", "neogeo", NULL, "1994", + "Saulabi Spirits / Jin Saulabi Tu Hon (Korean release of Samurai Shodown II)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho2kRomInfo, samsho2kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsho2kInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Fatal Fury 3 - Road to the Final Victory / Garou Densetsu 3 - haruka-naru tatakai (NGM-069)(NGH-069) + +static struct BurnRomInfo fatfury3RomDesc[] = { + { "069-p1.p1", 0x100000, 0xa8bcfbbc, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "069-sp2.sp2", 0x200000, 0xdbe963ed, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "069-s1.s1", 0x020000, 0x0b33a800, 2 | BRF_GRA }, // 2 Text layer tiles + + { "069-c1.c1", 0x400000, 0xe302f93c, 3 | BRF_GRA }, // 3 Sprite data + { "069-c2.c2", 0x400000, 0x1053a455, 3 | BRF_GRA }, // 4 + { "069-c3.c3", 0x400000, 0x1c0fde2f, 3 | BRF_GRA }, // 5 + { "069-c4.c4", 0x400000, 0xa25fc3d0, 3 | BRF_GRA }, // 6 + { "069-c5.c5", 0x200000, 0xb3ec6fa6, 3 | BRF_GRA }, // 7 + { "069-c6.c6", 0x200000, 0x69210441, 3 | BRF_GRA }, // 8 + + { "069-m1.m1", 0x020000, 0xfce72926, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "069-v1.v1", 0x400000, 0x2bdbd4db, 5 | BRF_SND }, // 10 Sound data + { "069-v2.v2", 0x400000, 0xa698a487, 5 | BRF_SND }, // 11 + { "069-v3.v3", 0x200000, 0x581c5304, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(fatfury3, fatfury3, neogeo) +STD_ROM_FN(fatfury3) + +struct BurnDriver BurnDrvFatfury3 = { + "fatfury3", NULL, "neogeo", NULL, "1995", + "Fatal Fury 3 - Road to the Final Victory / Garou Densetsu 3 - haruka-naru tatakai (NGM-069)(NGH-069)\0", NULL, "SNK", "Neo Geo MVS", + L"Fatal Fury 3 - Road to the Final Victory\0\u9913\u72FC\u4F1D\u8AAC\uFF13 (NGM-069)(NGH-069)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, fatfury3RomInfo, fatfury3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Super Sidekicks 3 - The Next Glory / Tokuten Ou 3 - eikoue no michi + +static struct BurnRomInfo ssideki3RomDesc[] = { + { "081-p1.p1", 0x200000, 0x6bc27a3d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "081-s1.s1", 0x020000, 0x7626da34, 2 | BRF_GRA }, // 1 Text layer tiles + + { "081-c1.c1", 0x200000, 0x1fb68ebe, 3 | BRF_GRA }, // 2 Sprite data + { "081-c2.c2", 0x200000, 0xb28d928f, 3 | BRF_GRA }, // 3 + { "081-c3.c3", 0x200000, 0x3b2572e8, 3 | BRF_GRA }, // 4 + { "081-c4.c4", 0x200000, 0x47d26a7c, 3 | BRF_GRA }, // 5 + { "081-c5.c5", 0x200000, 0x17d42f0d, 3 | BRF_GRA }, // 6 + { "081-c6.c6", 0x200000, 0x6b53fb75, 3 | BRF_GRA }, // 7 + + { "081-m1.m1", 0x020000, 0x82fcd863, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "081-v1.v1", 0x200000, 0x201fa1e1, 5 | BRF_SND }, // 9 Sound data + { "081-v2.v2", 0x200000, 0xacf29d96, 5 | BRF_SND }, // 10 + { "081-v3.v3", 0x200000, 0xe524e415, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(ssideki3, ssideki3, neogeo) +STD_ROM_FN(ssideki3) + +struct BurnDriver BurnDrvSsideki3 = { + "ssideki3", NULL, "neogeo", NULL, "1995", + "Super Sidekicks 3 - The Next Glory / Tokuten Ou 3 - eikoue no michi\0", NULL, "SNK", "Neo Geo MVS", + L"Super Sidekicks 3 - The Next Glory\0\u5F97\u70B9\u738B\uFF13 - \u6804\u5149\u3078\u306E\u6311\u6226\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSFOOTBALL, 0, + NULL, ssideki3RomInfo, ssideki3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The King of Fighters '95 (NGM-084) + +static struct BurnRomInfo kof95RomDesc[] = { + { "084-p1.p1", 0x200000, 0x2cba2716, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "084-s1.s1", 0x020000, 0xde716f8a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "084-c1.c1", 0x400000, 0xfe087e32, 3 | BRF_GRA }, // 2 Sprite data + { "084-c2.c2", 0x400000, 0x07864e09, 3 | BRF_GRA }, // 3 + { "084-c3.c3", 0x400000, 0xa4e65d1b, 3 | BRF_GRA }, // 4 + { "084-c4.c4", 0x400000, 0xc1ace468, 3 | BRF_GRA }, // 5 + { "084-c5.c5", 0x200000, 0x8a2c1edc, 3 | BRF_GRA }, // 6 + { "084-c6.c6", 0x200000, 0xf593ac35, 3 | BRF_GRA }, // 7 + { "084-c7.c7", 0x100000, 0x9904025f, 3 | BRF_GRA }, // 8 + { "084-c8.c8", 0x100000, 0x78eb0f9b, 3 | BRF_GRA }, // 9 + + { "084-m1.m1", 0x020000, 0x6f2d7429, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "084-v1.v1", 0x400000, 0x84861b56, 5 | BRF_SND }, // 11 Sound data + { "084-v2.v2", 0x200000, 0xb38a2803, 5 | BRF_SND }, // 12 + { "084-v3.v3", 0x100000, 0xd683a338, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof95, kof95, neogeo) +STD_ROM_FN(kof95) + +struct BurnDriver BurnDrvKof95 = { + "kof95", NULL, "neogeo", NULL, "1995", + "The King of Fighters '95 (NGM-084)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, FBF_KOF, + NULL, kof95RomInfo, kof95RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '95 (NGH-084) + +static struct BurnRomInfo kof95hRomDesc[] = { + { "084-pg1.p1", 0x200000, 0x5e54cf95, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "084-s1.s1", 0x020000, 0xde716f8a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "084-c1.c1", 0x400000, 0xfe087e32, 3 | BRF_GRA }, // 2 Sprite data + { "084-c2.c2", 0x400000, 0x07864e09, 3 | BRF_GRA }, // 3 + { "084-c3.c3", 0x400000, 0xa4e65d1b, 3 | BRF_GRA }, // 4 + { "084-c4.c4", 0x400000, 0xc1ace468, 3 | BRF_GRA }, // 5 + { "084-c5.c5", 0x200000, 0x8a2c1edc, 3 | BRF_GRA }, // 6 + { "084-c6.c6", 0x200000, 0xf593ac35, 3 | BRF_GRA }, // 7 + { "084-c7.c7", 0x100000, 0x9904025f, 3 | BRF_GRA }, // 8 + { "084-c8.c8", 0x100000, 0x78eb0f9b, 3 | BRF_GRA }, // 9 + + { "084-m1.m1", 0x020000, 0x6f2d7429, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "084-v1.v1", 0x400000, 0x84861b56, 5 | BRF_SND }, // 11 Sound data + { "084-v2.v2", 0x200000, 0xb38a2803, 5 | BRF_SND }, // 12 + { "084-v3.v3", 0x100000, 0xd683a338, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof95h, kof95h, neogeo) +STD_ROM_FN(kof95h) + +struct BurnDriver BurnDrvKof95h = { + "kof95h", "kof95", "neogeo", NULL, "1995", + "The King of Fighters '95 (NGH-084)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, FBF_KOF, + NULL, kof95hRomInfo, kof95hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown III / Samurai Spirits - Zankurou Musouken (NGM-087) + +static struct BurnRomInfo samsho3RomDesc[] = { + { "087-epr.ep1", 0x080000, 0x23e09bb8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "087-epr.ep2", 0x080000, 0x256f5302, 1 | BRF_ESS | BRF_PRG }, // 1 + { "087-epr.ep3", 0x080000, 0xbf2db5dd, 1 | BRF_ESS | BRF_PRG }, // 2 + { "087-epr.ep4", 0x080000, 0x53e60c58, 1 | BRF_ESS | BRF_PRG }, // 3 + { "087-p5.p5", 0x100000, 0xe86ca4af, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "087-s1.s1", 0x020000, 0x74ec7d9f, 2 | BRF_GRA }, // 5 Text layer tiles + + { "087-c1.c1", 0x400000, 0x07a233bc, 3 | BRF_GRA }, // 6 Sprite data + { "087-c2.c2", 0x400000, 0x7a413592, 3 | BRF_GRA }, // 7 + { "087-c3.c3", 0x400000, 0x8b793796, 3 | BRF_GRA }, // 8 + { "087-c4.c4", 0x400000, 0x728fbf11, 3 | BRF_GRA }, // 9 + { "087-c5.c5", 0x400000, 0x172ab180, 3 | BRF_GRA }, // 10 + { "087-c6.c6", 0x400000, 0x002ff8f3, 3 | BRF_GRA }, // 11 + { "087-c7.c7", 0x100000, 0xae450e3d, 3 | BRF_GRA }, // 12 + { "087-c8.c8", 0x100000, 0xa9e82717, 3 | BRF_GRA }, // 13 + + { "087-m1.m1", 0x020000, 0x8e6440eb, 4 | BRF_ESS | BRF_PRG }, // 14 Z80 code + + { "087-v1.v1", 0x400000, 0x84bdd9a0, 5 | BRF_SND }, // 15 Sound data + { "087-v2.v2", 0x200000, 0xac0f261a, 5 | BRF_SND }, // 16 +}; + +STDROMPICKEXT(samsho3, samsho3, neogeo) +STD_ROM_FN(samsho3) + +struct BurnDriver BurnDrvSamSho3 = { + "samsho3", NULL, "neogeo", NULL, "1995", + "Samurai Shodown III / Samurai Spirits - Zankurou Musouken (NGM-087)\0", NULL, "SNK", "Neo Geo MVS", + L"Samurai Shodown III\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4 - \u65AC\u7D05\u90CE\u7121\u53CC\u5263 (NGM-087)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho3RomInfo, samsho3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown III / Samurai Spirits - Zankurou Musouken (NGH-087) + +static struct BurnRomInfo samsho3hRomDesc[] = { + { "087-pg1.p1", 0x100000, 0x282a336e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "087-p2.sp2", 0x200000, 0x9bbe27e0, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "087-s1.s1", 0x020000, 0x74ec7d9f, 2 | BRF_GRA }, // 2 Text layer tiles + + { "087-c1.c1", 0x400000, 0x07a233bc, 3 | BRF_GRA }, // 3 Sprite data + { "087-c2.c2", 0x400000, 0x7a413592, 3 | BRF_GRA }, // 4 + { "087-c3.c3", 0x400000, 0x8b793796, 3 | BRF_GRA }, // 5 + { "087-c4.c4", 0x400000, 0x728fbf11, 3 | BRF_GRA }, // 6 + { "087-c5.c5", 0x400000, 0x172ab180, 3 | BRF_GRA }, // 7 + { "087-c6.c6", 0x400000, 0x002ff8f3, 3 | BRF_GRA }, // 8 + { "087-c7.c7", 0x100000, 0xae450e3d, 3 | BRF_GRA }, // 9 + { "087-c8.c8", 0x100000, 0xa9e82717, 3 | BRF_GRA }, // 10 + + { "087-m1.m1", 0x020000, 0x8e6440eb, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "087-v1.v1", 0x400000, 0x84bdd9a0, 5 | BRF_SND }, // 12 Sound data + { "087-v2.v2", 0x200000, 0xac0f261a, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(samsho3h, samsho3h, neogeo) +STD_ROM_FN(samsho3h) + +struct BurnDriver BurnDrvSamSho3h = { + "samsho3h", "samsho3", "neogeo", NULL, "1995", + "Samurai Shodown III / Samurai Spirits - Zankurou Musouken (NGH-087)\0", NULL, "SNK", "Neo Geo MVS", + L"Samurai Shodown III\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4 - \u65AC\u7D05\u90CE\u7121\u53CC\u5263 (NGH-087)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho3hRomInfo, samsho3hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Fighters Swords (Korean release of Samurai Shodown III) + +static struct BurnRomInfo fswordsRomDesc[] = { + { "187-p1k.p1", 0x100000, 0xc8e7c075, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "087-p2.sp2", 0x200000, 0x9bbe27e0, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "087-s1.s1", 0x020000, 0x74ec7d9f, 2 | BRF_GRA }, // 2 Text layer tiles + + { "087-c1.c1", 0x400000, 0x07a233bc, 3 | BRF_GRA }, // 3 Sprite data + { "087-c2.c2", 0x400000, 0x7a413592, 3 | BRF_GRA }, // 4 + { "087-c3.c3", 0x400000, 0x8b793796, 3 | BRF_GRA }, // 5 + { "087-c4.c4", 0x400000, 0x728fbf11, 3 | BRF_GRA }, // 6 + { "087-c5.c5", 0x400000, 0x172ab180, 3 | BRF_GRA }, // 7 + { "087-c6.c6", 0x400000, 0x002ff8f3, 3 | BRF_GRA }, // 8 + { "087-c7.c7", 0x100000, 0xae450e3d, 3 | BRF_GRA }, // 9 + { "087-c8.c8", 0x100000, 0xa9e82717, 3 | BRF_GRA }, // 10 + + { "087-m1.m1", 0x020000, 0x8e6440eb, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "087-v1.v1", 0x400000, 0x84bdd9a0, 5 | BRF_SND }, // 12 Sound data + { "087-v2.v2", 0x200000, 0xac0f261a, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(fswords, fswords, neogeo) +STD_ROM_FN(fswords) + +struct BurnDriver BurnDrvfswords = { + "fswords", "samsho3", "neogeo", NULL, "1995", + "Fighters Swords (Korean release of Samurai Shodown III)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, fswordsRomInfo, fswordsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Real Bout Fatal Fury / Real Bout Garou Densetsu (NGM-095)(NGH-095) + +static struct BurnRomInfo rbff1RomDesc[] = { + { "095-p1.p1", 0x100000, 0x63b4d8ae, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "095-p2.sp2", 0x200000, 0xcc15826e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "095-s1.s1", 0x020000, 0xb6bf5e08, 2 | BRF_GRA }, // 2 Text layer tiles + + { "069-c1.c1", 0x400000, 0xe302f93c, 3 | BRF_GRA }, // 3 Sprite data + { "069-c2.c2", 0x400000, 0x1053a455, 3 | BRF_GRA }, // 4 + { "069-c3.c3", 0x400000, 0x1c0fde2f, 3 | BRF_GRA }, // 5 + { "069-c4.c4", 0x400000, 0xa25fc3d0, 3 | BRF_GRA }, // 6 + { "095-c5.c5", 0x400000, 0x8b9b65df, 3 | BRF_GRA }, // 7 + { "095-c6.c6", 0x400000, 0x3e164718, 3 | BRF_GRA }, // 8 + { "095-c7.c7", 0x200000, 0xca605e12, 3 | BRF_GRA }, // 9 + { "095-c8.c8", 0x200000, 0x4e6beb6c, 3 | BRF_GRA }, // 10 + + { "095-m1.m1", 0x020000, 0x653492a7, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "069-v1.v1", 0x400000, 0x2bdbd4db, 5 | BRF_SND }, // 12 Sound data + { "069-v2.v2", 0x400000, 0xa698a487, 5 | BRF_SND }, // 13 + { "095-v3.v3", 0x400000, 0x189d1c6c, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(rbff1, rbff1, neogeo) +STD_ROM_FN(rbff1) + +struct BurnDriver BurnDrvrbff1 = { + "rbff1", NULL, "neogeo", NULL, "1995", + "Real Bout Fatal Fury / Real Bout Garou Densetsu (NGM-095)(NGH-095)\0", NULL, "SNK", "Neo Geo MVS", + L"Real Bout Fatal Fury\0Real Bout \u9913\u72FC\u4F1D\u8AAC (NGM-095)(NGH-095)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbff1RomInfo, rbff1RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Real Bout Fatal Fury / Real Bout Garou Densetsu (bug fix revision) + +static struct BurnRomInfo rbff1aRomDesc[] = { + { "095-p1.p1", 0x100000, 0x63b4d8ae, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "095-p2.sp2", 0x200000, 0xcc15826e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "095-s1.s1", 0x020000, 0xb6bf5e08, 2 | BRF_GRA }, // 2 Text layer tiles + + { "069-c1.c1", 0x400000, 0xe302f93c, 3 | BRF_GRA }, // 3 Sprite data + { "069-c2.c2", 0x400000, 0x1053a455, 3 | BRF_GRA }, // 4 + { "069-c3.c3", 0x400000, 0x1c0fde2f, 3 | BRF_GRA }, // 5 + { "069-c4.c4", 0x400000, 0xa25fc3d0, 3 | BRF_GRA }, // 6 + { "095-c5.c5", 0x400000, 0x8b9b65df, 3 | BRF_GRA }, // 7 + { "095-c6.c6", 0x400000, 0x3e164718, 3 | BRF_GRA }, // 8 + { "095-c7.c7", 0x200000, 0xca605e12, 3 | BRF_GRA }, // 9 + { "095-c8.c8", 0x200000, 0x4e6beb6c, 3 | BRF_GRA }, // 10 + + { "095-m1.m1", 0x020000, 0x653492a7, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "069-v1.v1", 0x400000, 0x2bdbd4db, 5 | BRF_SND }, // 12 Sound data + { "069-v2.v2", 0x400000, 0xa698a487, 5 | BRF_SND }, // 13 + { "095-v3.v3", 0x400000, 0x189d1c6c, 5 | BRF_SND }, // 14 + + { "095-epr.ep1", 0x080000, 0xbe0060a3, 0 | BRF_ESS | BRF_PRG }, // 15 68k code +}; + +STDROMPICKEXT(rbff1a, rbff1a, neogeo) +STD_ROM_FN(rbff1a) + +static void rbff1aCallback() +{ + BurnLoadRom(Neo68KROMActive, 15, 1); +} + +static INT32 rbff1aInit() +{ + NeoCallbackActive->pInitialise = rbff1aCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvrbff1a = { + "rbff1a", "rbff1", "neogeo", NULL, "1995", + "Real Bout Fatal Fury / Real Bout Garou Densetsu (bug fix revision)\0", NULL, "SNK", "Neo Geo MVS", + L"Real Bout Fatal Fury\0Real Bout \u9913\u72FC\u4F1D\u8AAC (bug fix revision)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbff1aRomInfo, rbff1aRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + rbff1aInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Art of Fighting 3 - The Path of the Warrior / Art of Fighting - Ryuuko no Ken Gaiden + +static struct BurnRomInfo aof3RomDesc[] = { + { "096-p1.p1", 0x100000, 0x9edb420d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "096-p2.sp2", 0x200000, 0x4d5a2602, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "096-s1.s1", 0x020000, 0xcc7fd344, 2 | BRF_GRA }, // 2 Text layer tiles + + { "096-c1.c1", 0x400000, 0xf17b8d89, 3 | BRF_GRA }, // 3 Sprite data + { "096-c2.c2", 0x400000, 0x3840c508, 3 | BRF_GRA }, // 4 + { "096-c3.c3", 0x400000, 0x55f9ee1e, 3 | BRF_GRA }, // 5 + { "096-c4.c4", 0x400000, 0x585b7e47, 3 | BRF_GRA }, // 6 + { "096-c5.c5", 0x400000, 0xc75a753c, 3 | BRF_GRA }, // 7 + { "096-c6.c6", 0x400000, 0x9a9d2f7a, 3 | BRF_GRA }, // 8 + { "096-c7.c7", 0x200000, 0x51bd8ab2, 3 | BRF_GRA }, // 9 + { "096-c8.c8", 0x200000, 0x9a34f99c, 3 | BRF_GRA }, // 10 + + { "096-m1.m1", 0x020000, 0xcb07b659, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "096-v1.v1", 0x200000, 0xe2c32074, 5 | BRF_SND }, // 12 Sound data + { "096-v2.v2", 0x200000, 0xa290eee7, 5 | BRF_SND }, // 13 + { "096-v3.v3", 0x200000, 0x199d12ea, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(aof3, aof3, neogeo) +STD_ROM_FN(aof3) + +struct BurnDriver BurnDrvAof3 = { + "aof3", NULL, "neogeo", NULL, "1996", + "Art of Fighting 3 - The Path of the Warrior / Art of Fighting - Ryuuko no Ken Gaiden\0", NULL, "SNK", "Neo Geo MVS", + L"Art of Fighting 3 - The Path of the Warrior\0Art of Fighting - \u9F8D\u864E\u306E\u62F3\u5916\u4F1D\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, aof3RomInfo, aof3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Art of Fighting 3 - The Path of the Warrior (Korean release) + +static struct BurnRomInfo aof3kRomDesc[] = { + { "196-p1k.p1", 0x100000, 0xa0780789, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "096-p2.sp2", 0x200000, 0x4d5a2602, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "096-s1.s1", 0x020000, 0xcc7fd344, 2 | BRF_GRA }, // 2 Text layer tiles + + { "096-c1.c1", 0x400000, 0xf17b8d89, 3 | BRF_GRA }, // 3 Sprite data + { "096-c2.c2", 0x400000, 0x3840c508, 3 | BRF_GRA }, // 4 + { "096-c3.c3", 0x400000, 0x55f9ee1e, 3 | BRF_GRA }, // 5 + { "096-c4.c4", 0x400000, 0x585b7e47, 3 | BRF_GRA }, // 6 + { "096-c5.c5", 0x400000, 0xc75a753c, 3 | BRF_GRA }, // 7 + { "096-c6.c6", 0x400000, 0x9a9d2f7a, 3 | BRF_GRA }, // 8 + { "096-c7.c7", 0x200000, 0x51bd8ab2, 3 | BRF_GRA }, // 9 + { "096-c8.c8", 0x200000, 0x9a34f99c, 3 | BRF_GRA }, // 10 + + { "096-m1.m1", 0x020000, 0xcb07b659, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "096-v1.v1", 0x200000, 0xe2c32074, 5 | BRF_SND }, // 12 Sound data + { "096-v2.v2", 0x200000, 0xa290eee7, 5 | BRF_SND }, // 13 + { "096-v3.v3", 0x200000, 0x199d12ea, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(aof3k, aof3k, neogeo) +STD_ROM_FN(aof3k) + +struct BurnDriver BurnDrvAof3k = { + "aof3k", "aof3", "neogeo", NULL, "1996", + "Art of Fighting 3 - The Path of the Warrior (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, aof3kRomInfo, aof3kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '96 (NGM-214) + +static struct BurnRomInfo kof96RomDesc[] = { + { "214-p1.p1", 0x100000, 0x52755d74, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "214-p2.sp2", 0x200000, 0x002ccb73, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "214-s1.s1", 0x020000, 0x1254cbdb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "214-c1.c1", 0x400000, 0x7ecf4aa2, 3 | BRF_GRA }, // 3 Sprite data + { "214-c2.c2", 0x400000, 0x05b54f37, 3 | BRF_GRA }, // 4 + { "214-c3.c3", 0x400000, 0x64989a65, 3 | BRF_GRA }, // 5 + { "214-c4.c4", 0x400000, 0xafbea515, 3 | BRF_GRA }, // 6 + { "214-c5.c5", 0x400000, 0x2a3bbd26, 3 | BRF_GRA }, // 7 + { "214-c6.c6", 0x400000, 0x44d30dc7, 3 | BRF_GRA }, // 8 + { "214-c7.c7", 0x400000, 0x3687331b, 3 | BRF_GRA }, // 9 + { "214-c8.c8", 0x400000, 0xfa1461ad, 3 | BRF_GRA }, // 10 + + { "214-m1.m1", 0x020000, 0xdabc427c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "214-v1.v1", 0x400000, 0x63f7b045, 5 | BRF_SND }, // 12 Sound data + { "214-v2.v2", 0x400000, 0x25929059, 5 | BRF_SND }, // 13 + { "214-v3.v3", 0x200000, 0x92a2257d, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof96, kof96, neogeo) +STD_ROM_FN(kof96) + +struct BurnDriver BurnDrvKof96 = { + "kof96", NULL, "neogeo", NULL, "1996", + "The King of Fighters '96 (NGM-214)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof96RomInfo, kof96RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '96 (NGH-214) + +static struct BurnRomInfo kof96hRomDesc[] = { + { "214-pg1.p1", 0x100000, 0xbd3757c9, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "214-p2.sp2", 0x200000, 0x002ccb73, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "214-s1.s1", 0x020000, 0x1254cbdb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "214-c1.c1", 0x400000, 0x7ecf4aa2, 3 | BRF_GRA }, // 3 Sprite data + { "214-c2.c2", 0x400000, 0x05b54f37, 3 | BRF_GRA }, // 4 + { "214-c3.c3", 0x400000, 0x64989a65, 3 | BRF_GRA }, // 5 + { "214-c4.c4", 0x400000, 0xafbea515, 3 | BRF_GRA }, // 6 + { "214-c5.c5", 0x400000, 0x2a3bbd26, 3 | BRF_GRA }, // 7 + { "214-c6.c6", 0x400000, 0x44d30dc7, 3 | BRF_GRA }, // 8 + { "214-c7.c7", 0x400000, 0x3687331b, 3 | BRF_GRA }, // 9 + { "214-c8.c8", 0x400000, 0xfa1461ad, 3 | BRF_GRA }, // 10 + + { "214-m1.m1", 0x020000, 0xdabc427c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "214-v1.v1", 0x400000, 0x63f7b045, 5 | BRF_SND }, // 12 Sound data + { "214-v2.v2", 0x400000, 0x25929059, 5 | BRF_SND }, // 13 + { "214-v3.v3", 0x200000, 0x92a2257d, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof96h, kof96h, neogeo) +STD_ROM_FN(kof96h) + +struct BurnDriver BurnDrvKof96h = { + "kof96h", "kof96", "neogeo", NULL, "1996", + "The King of Fighters '96 (NGH-214)\0", NULL, "SNK", "Neo Geo AES", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof96hRomInfo, kof96hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The Ultimate 11 - The SNK Football Championship / Tokuten Ou - Honoo no Libero + +static struct BurnRomInfo ssideki4RomDesc[] = { + { "215-p1.p1", 0x200000, 0x519b4ba3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "215-s1.s1", 0x020000, 0xf0fe5c36, 2 | BRF_GRA }, // 1 Text layer tiles + + { "215-c1.c1", 0x400000, 0x8ff444f5, 3 | BRF_GRA }, // 2 Sprite data + { "215-c2.c2", 0x400000, 0x5b155037, 3 | BRF_GRA }, // 3 + { "215-c3.c3", 0x400000, 0x456a073a, 3 | BRF_GRA }, // 4 + { "215-c4.c4", 0x400000, 0x43c182e1, 3 | BRF_GRA }, // 5 + { "215-c5.c5", 0x200000, 0x0c6f97ec, 3 | BRF_GRA }, // 6 + { "215-c6.c6", 0x200000, 0x329c5e1b, 3 | BRF_GRA }, // 7 + + { "215-m1.m1", 0x020000, 0xa932081d, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "215-v1.v1", 0x400000, 0x877d1409, 5 | BRF_SND }, // 9 Sound data + { "215-v2.v2", 0x200000, 0x1bfa218b, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(ssideki4, ssideki4, neogeo) +STD_ROM_FN(ssideki4) + +struct BurnDriver BurnDrvSsideki4 = { + "ssideki4", NULL, "neogeo", NULL, "1996", + "The Ultimate 11 - The SNK Football Championship / Tokuten Ou - Honoo no Libero\0", NULL, "SNK", "Neo Geo MVS", + L"The Ultimate 11 - SNK Football Championship\0\u5F97\u70B9\u738B - \u708E\u306E\u30EA\u30D9\u30ED\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSFOOTBALL, 0, + NULL, ssideki4RomInfo, ssideki4RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Kizuna Encounter - Super Tag Battle / Fu'un Super Tag Battle + +static struct BurnRomInfo kizunaRomDesc[] = { + { "216-p1.p1", 0x200000, 0x75d2b3de, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "216-s1.s1", 0x020000, 0xefdc72d7, 2 | BRF_GRA }, // 1 Text layer tiles + + { "059-c1.c1", 0x200000, 0x763ba611, 3 | BRF_GRA }, // 2 Sprite data + { "059-c2.c2", 0x200000, 0xe05e8ca6, 3 | BRF_GRA }, // 3 + { "216-c3.c3", 0x400000, 0x665c9f16, 3 | BRF_GRA }, // 4 + { "216-c4.c4", 0x400000, 0x7f5d03db, 3 | BRF_GRA }, // 5 + { "059-c5.c5", 0x200000, 0x59013f9e, 3 | BRF_GRA }, // 6 + { "059-c6.c6", 0x200000, 0x1c8d5def, 3 | BRF_GRA }, // 7 + { "059-c7.c7", 0x200000, 0xc88f7035, 3 | BRF_GRA }, // 8 + { "059-c8.c8", 0x200000, 0x484ce3ba, 3 | BRF_GRA }, // 9 + + { "216-m1.m1", 0x020000, 0x1b096820, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "059-v1.v1", 0x200000, 0x530c50fd, 5 | BRF_SND }, // 11 Sound data + { "216-v2.v2", 0x200000, 0x03667a8d, 5 | BRF_SND }, // 12 + { "059-v3.v3", 0x200000, 0x7038c2f9, 5 | BRF_SND }, // 13 + { "216-v4.v4", 0x200000, 0x31b99bd6, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kizuna, kizuna, neogeo) +STD_ROM_FN(kizuna) + +struct BurnDriver BurnDrvKizuna = { + "kizuna", NULL, "neogeo", NULL, "1996", + "Kizuna Encounter - Super Tag Battle / Fu'un Super Tag Battle\0", NULL, "SNK", "Neo Geo MVS", + L"Kizuna Encounter - Super Tag Battle\0\u98A8\u96F2 Super Tag Battle\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, kizunaRomInfo, kizunaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown IV - Amakusa's Revenge / Samurai Spirits - Amakusa Kourin (NGM-222)(NGH-222) + +static struct BurnRomInfo samsho4RomDesc[] = { + { "222-p1.p1", 0x100000, 0x1a5cb56d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "222-p2.sp2", 0x400000, 0xb023cd8b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "222-s1.s1", 0x020000, 0x8d3d3bf9, 2 | BRF_GRA }, // 2 Text layer tiles + + { "222-c1.c1", 0x400000, 0x68f2ed95, 3 | BRF_GRA }, // 3 Sprite data + { "222-c2.c2", 0x400000, 0xa6e9aff0, 3 | BRF_GRA }, // 4 + { "222-c3.c3", 0x400000, 0xc91b40f4, 3 | BRF_GRA }, // 5 + { "222-c4.c4", 0x400000, 0x359510a4, 3 | BRF_GRA }, // 6 + { "222-c5.c5", 0x400000, 0x9cfbb22d, 3 | BRF_GRA }, // 7 + { "222-c6.c6", 0x400000, 0x685efc32, 3 | BRF_GRA }, // 8 + { "222-c7.c7", 0x400000, 0xd0f86f0d, 3 | BRF_GRA }, // 9 + { "222-c8.c8", 0x400000, 0xadfc50e3, 3 | BRF_GRA }, // 10 + + { "222-m1.m1", 0x020000, 0x7615bc1b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "222-v1.v1", 0x400000, 0x7d6ba95f, 5 | BRF_SND }, // 12 Sound data + { "222-v2.v2", 0x400000, 0x6c33bb5d, 5 | BRF_SND }, // 13 + { "222-v3.v3", 0x200000, 0x831ea8c0, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(samsho4, samsho4, neogeo) +STD_ROM_FN(samsho4) + +struct BurnDriver BurnDrvSamSho4 = { + "samsho4", NULL, "neogeo", NULL, "1996", + "Samurai Shodown IV - Amakusa's Revenge / Samurai Spirits - Amakusa Kourin (NGM-222)(NGH-222)\0", NULL, "SNK", "Neo Geo MVS", + L"Samurai Shodown IV - Amakusa's Revenge\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4 - \u5929\u8349\u964D\u81E8 (NGM-222)(NGH-222)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho4RomInfo, samsho4RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Pae Wang Jeon Seol / Legend of a Warrior (Korean censored Samurai Shodown IV) + +static struct BurnRomInfo samsho4kRomDesc[] = { + { "222-p1k.p1", 0x100000, 0x06e0a25d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "222-p2.sp2", 0x400000, 0xb023cd8b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "222-s1k.s1", 0x020000, 0xd313687d, 2 | BRF_GRA }, // 2 Text layer tiles + + { "222-c1.c1", 0x400000, 0x68f2ed95, 3 | BRF_GRA }, // 3 Sprite data + { "222-c2.c2", 0x400000, 0xa6e9aff0, 3 | BRF_GRA }, // 4 + { "222-c3.c3", 0x400000, 0xc91b40f4, 3 | BRF_GRA }, // 5 + { "222-c4.c4", 0x400000, 0x359510a4, 3 | BRF_GRA }, // 6 + { "222-c5.c5", 0x400000, 0x9cfbb22d, 3 | BRF_GRA }, // 7 + { "222-c6.c6", 0x400000, 0x685efc32, 3 | BRF_GRA }, // 8 + { "222-c7.c7", 0x400000, 0xd0f86f0d, 3 | BRF_GRA }, // 9 + { "222-c8.c8", 0x400000, 0xadfc50e3, 3 | BRF_GRA }, // 10 + + { "222-m1.m1", 0x020000, 0x7615bc1b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "222-v1.v1", 0x400000, 0x7d6ba95f, 5 | BRF_SND }, // 12 Sound data + { "222-v2.v2", 0x400000, 0x6c33bb5d, 5 | BRF_SND }, // 13 + { "222-v3.v3", 0x200000, 0x831ea8c0, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(samsho4k, samsho4k, neogeo) +STD_ROM_FN(samsho4k) + +struct BurnDriver BurnDrvSamSho4k = { + "samsho4k", "samsho4", "neogeo", NULL, "1996", + "Pae Wang Jeon Seol / Legend of a Warrior (Korean censored Samurai Shodown IV)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho4kRomInfo, samsho4kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Real Bout Fatal Fury Special / Real Bout Garou Densetsu Special + +static struct BurnRomInfo rbffspecRomDesc[] = { + { "223-p1.p1", 0x100000, 0xf84a2d1d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "223-p2.sp2", 0x400000, 0xaddd8f08, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "223-s1.s1", 0x020000, 0x7ecd6e8c, 2 | BRF_GRA }, // 2 Text layer tiles + + { "223-c1.c1", 0x400000, 0xebab05e2, 3 | BRF_GRA }, // 3 Sprite data + { "223-c2.c2", 0x400000, 0x641868c3, 3 | BRF_GRA }, // 4 + { "223-c3.c3", 0x400000, 0xca00191f, 3 | BRF_GRA }, // 5 + { "223-c4.c4", 0x400000, 0x1f23d860, 3 | BRF_GRA }, // 6 + { "223-c5.c5", 0x400000, 0x321e362c, 3 | BRF_GRA }, // 7 + { "223-c6.c6", 0x400000, 0xd8fcef90, 3 | BRF_GRA }, // 8 + { "223-c7.c7", 0x400000, 0xbc80dd2d, 3 | BRF_GRA }, // 9 + { "223-c8.c8", 0x400000, 0x5ad62102, 3 | BRF_GRA }, // 10 + + { "223-m1.m1", 0x020000, 0x3fee46bf, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "223-v1.v1", 0x400000, 0x76673869, 5 | BRF_SND }, // 12 Sound data + { "223-v2.v2", 0x400000, 0x7a275acd, 5 | BRF_SND }, // 13 + { "223-v3.v3", 0x400000, 0x5a797fd2, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(rbffspec, rbffspec, neogeo) +STD_ROM_FN(rbffspec) + +struct BurnDriver BurnDrvrbffspec = { + "rbffspec", NULL, "neogeo", NULL, "1996", + "Real Bout Fatal Fury Special / Real Bout Garou Densetsu Special\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbffspecRomInfo, rbffspecRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Real Bout Fatal Fury Special / Real Bout Garou Densetsu Special (Korean release) + +static struct BurnRomInfo rbffspeckRomDesc[] = { + { "223-p1k.p1", 0x100000, 0xb78c8391, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "223-p2.sp2", 0x400000, 0xaddd8f08, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "223-s1.s1", 0x020000, 0x7ecd6e8c, 2 | BRF_GRA }, // 2 Text layer tiles + + { "223-c1.c1", 0x400000, 0xebab05e2, 3 | BRF_GRA }, // 3 Sprite data + { "223-c2.c2", 0x400000, 0x641868c3, 3 | BRF_GRA }, // 4 + { "223-c3.c3", 0x400000, 0xca00191f, 3 | BRF_GRA }, // 5 + { "223-c4.c4", 0x400000, 0x1f23d860, 3 | BRF_GRA }, // 6 + { "223-c5.c5", 0x400000, 0x321e362c, 3 | BRF_GRA }, // 7 + { "223-c6.c6", 0x400000, 0xd8fcef90, 3 | BRF_GRA }, // 8 + { "223-c7.c7", 0x400000, 0xbc80dd2d, 3 | BRF_GRA }, // 9 + { "223-c8.c8", 0x400000, 0x5ad62102, 3 | BRF_GRA }, // 10 + + { "223-m1.m1", 0x020000, 0x3fee46bf, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "223-v1.v1", 0x400000, 0x76673869, 5 | BRF_SND }, // 12 Sound data + { "223-v2.v2", 0x400000, 0x7a275acd, 5 | BRF_SND }, // 13 + { "223-v3.v3", 0x400000, 0x5a797fd2, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(rbffspeck, rbffspeck, neogeo) +STD_ROM_FN(rbffspeck) + +struct BurnDriver BurnDrvrbffspeck = { + "rbffspeck", "rbffspec", "neogeo", NULL, "1996", + "Real Bout Fatal Fury Special / Real Bout Garou Densetsu Special (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbffspeckRomInfo, rbffspeckRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The King of Fighters '97 (NGM-2320) + +static struct BurnRomInfo kof97RomDesc[] = { + { "232-p1.p1", 0x100000, 0x7db81ad9, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232-p2.sp2", 0x400000, 0x158b23f6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "232-s1.s1", 0x020000, 0x8514ecf5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232-c1.c1", 0x800000, 0x5f8bf0a1, 3 | BRF_GRA }, // 3 Sprite data + { "232-c2.c2", 0x800000, 0xe4d45c81, 3 | BRF_GRA }, // 4 + { "232-c3.c3", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.c4", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.c5", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.c6", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1.m1", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.v1", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.v2", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.v3", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97, kof97, neogeo) +STD_ROM_FN(kof97) + +struct BurnDriver BurnDrvKof97 = { + "kof97", NULL, "neogeo", NULL, "1997", + "The King of Fighters '97 (NGM-2320)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97RomInfo, kof97RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 (NGH-2320) + +static struct BurnRomInfo kof97hRomDesc[] = { + { "232-pg1.p1", 0x100000, 0x5c2400b7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232-p2.sp2", 0x400000, 0x158b23f6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "232-s1.s1", 0x020000, 0x8514ecf5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232-c1.c1", 0x800000, 0x5f8bf0a1, 3 | BRF_GRA }, // 3 Sprite data + { "232-c2.c2", 0x800000, 0xe4d45c81, 3 | BRF_GRA }, // 4 + { "232-c3.c3", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.c4", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.c5", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.c6", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1.m1", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.v1", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.v2", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.v3", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97h, kof97h, neogeo) +STD_ROM_FN(kof97h) + +struct BurnDriver BurnDrvKof97h = { + "kof97h", "kof97", "neogeo", NULL, "1997", + "The King of Fighters '97 (NGH-2320)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97hRomInfo, kof97hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 (Korean release) + +static struct BurnRomInfo kof97kRomDesc[] = { + { "232-p1.p1", 0x100000, 0x7db81ad9, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232-p2.sp2", 0x400000, 0x158b23f6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "232-s1.s1", 0x020000, 0x8514ecf5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232-c1.c1", 0x800000, 0x5f8bf0a1, 3 | BRF_GRA }, // 3 Sprite data + { "232-c2.c2", 0x800000, 0xe4d45c81, 3 | BRF_GRA }, // 4 + { "232-c3.c3", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.c4", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.c5", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.c6", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1k.m1", 0x020000, 0xbbea9070, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.v1", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.v2", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.v3", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97k, kof97k, neogeo) +STD_ROM_FN(kof97k) + +struct BurnDriver BurnDrvKof97k = { + "kof97k", "kof97", "neogeo", NULL, "1997", + "The King of Fighters '97 (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97kRomInfo, kof97kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 Plus (bootleg) + +static struct BurnRomInfo kof97plsRomDesc[] = { + { "kf97-p1p.bin", 0x100000, 0xc01fda46, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "kf97-p2p.bin", 0x400000, 0x5502b020, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "kf97-s1p.bin", 0x020000, 0x73254270, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232-c1.c1", 0x800000, 0x5f8bf0a1, 3 | BRF_GRA }, // 3 Sprite data + { "232-c2.c2", 0x800000, 0xe4d45c81, 3 | BRF_GRA }, // 4 + { "232-c3.c3", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.c4", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.c5", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.c6", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1.m1", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.v1", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.v2", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.v3", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97pls, kof97pls, neogeo) +STD_ROM_FN(kof97pls) + +struct BurnDriver BurnDrvKof97pls = { + "kof97pls", "kof97", "neogeo", NULL, "1997", + "The King of Fighters '97 Plus (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97plsRomInfo, kof97plsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// King of Gladiator (The King of Fighters '97 bootleg) + +static struct BurnRomInfo kogRomDesc[] = { + { "5232-p1.bin", 0x200000, 0xd2413ec6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232-p2.sp2", 0x400000, 0x158b23f6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5232-s1.bin", 0x020000, 0x0bef69da, 2 | BRF_GRA }, // 2 Text layer tiles + + { "5232-c1a.bin", 0x800000, 0x4eab9b0a, 3 | BRF_GRA }, // 3 Sprite data + { "5232-c2a.bin", 0x800000, 0x697f8fd0, 3 | BRF_GRA }, // 4 + { "5232-c1b.bin", 0x800000, 0x1143fdf3, 3 | BRF_GRA }, // 5 + { "5232-c2b.bin", 0x800000, 0xea82cf8f, 3 | BRF_GRA }, // 6 + { "5232-c3.bin", 0x400000, 0xabd1be07, 3 | BRF_GRA }, // 7 + { "5232-c4.bin", 0x400000, 0xd2bd967b, 3 | BRF_GRA }, // 8 + + { "232-m1.m1", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.v1", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.v2", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.v3", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kog, kog, neogeo) +STD_ROM_FN(kog) + +// This is actually set by a jumper on the PCB +UINT16 __fastcall KogReadWord(UINT32) +{ + extern INT32 nBIOS; + if (nBIOS == 5 || nBIOS == 6 || nBIOS == 7 || nBIOS == 8 || nBIOS == 10 || nBIOS == 11) { + return 0xff00; + } else { + return 0xff01; + } +} + +static void kogCallback() +{ + INT32 i; + UINT8 *dst = (UINT8 *)malloc( 0x100000 ); + + if (dst) + { + static const INT32 sec[] = { 0x3, 0x8, 0x7, 0xc, 0x1, 0xa, 0x6, 0xd }; + + for (i = 0; i < 0x100000 / 0x020000; i++) + memcpy (dst + i * 0x020000, Neo68KROMActive + sec[i] * 0x020000, 0x020000); + + memcpy (dst + 0x090000, Neo68KROMActive + 0x040000, 0x004000); + memcpy (Neo68KROMActive, dst, 0x100000); + free (dst); + dst = NULL; + } + + for (i = 0x90000; i < 0x94000; i+=2) { + if ((*((UINT16 *)(Neo68KROMActive + i + 0)) & 0xf2bf) == 0x42b9 && *((UINT16 *)(Neo68KROMActive + i + 2)) == 0) + *((UINT16 *)(Neo68KROMActive + i + 2)) = 0x0009; + + if (*((UINT16 *)(Neo68KROMActive + i + 0)) == 0x4eb8) { + *((UINT16 *)(Neo68KROMActive + i + 0)) = 0x6100; + *((UINT16 *)(Neo68KROMActive + i + 2)) += 0xfffe - (i & 0xfffe); + } + } + + memcpy (Neo68KROMActive + 0x0007a6, Neo68KROMActive + 0x0907a6, 0x000006); + memcpy (Neo68KROMActive + 0x0007c6, Neo68KROMActive + 0x0907c6, 0x000006); + memcpy (Neo68KROMActive + 0x0007e6, Neo68KROMActive + 0x0907e6, 0x000006); + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive + 0x200000, 0x400000); + + *((UINT16 *)(Neo68KROMActive + 0x924ac)) = 0x0009; + *((UINT16 *)(Neo68KROMActive + 0x9251c)) = 0x0009; + + lans2004_sx_decode(); + lans2004_cx_decode(0x800000 * 5); +} + +static void kogInstallHandlers() +{ + // Install jumper that controls title screen language + SekMapHandler(6, 0x0FFFFE, 0x0FFFFF, SM_READ); + SekSetReadWordHandler(6, KogReadWord); +} + +static INT32 kogInit() +{ + INT32 nRet; + + nBurnCPUSpeedAdjust = 0x010a; // fix garbage on intro + NeoCallbackActive->pInitialise = kogCallback; + NeoCallbackActive->pInstallHandlers = kogInstallHandlers; + + nRet = NeoInit(); + + return nRet; +} + +struct BurnDriver BurnDrvKog = { + "kog", "kof97", "neogeo", NULL, "1997", + "King of Gladiator (The King of Fighters '97 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kogRomInfo, kogRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kogInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The Last Blade / Bakumatsu Roman - Gekka no Kenshi (NGM-2340) + +static struct BurnRomInfo lastbladRomDesc[] = { + { "234-p1.p1", 0x100000, 0xe123a5a3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "234-p2.sp2", 0x400000, 0x0fdc289e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "234-s1.s1", 0x020000, 0x95561412, 2 | BRF_GRA }, // 2 Text layer tiles + + { "234-c1.c1", 0x800000, 0x9f7e2bd3, 3 | BRF_GRA }, // 3 Sprite data + { "234-c2.c2", 0x800000, 0x80623d3c, 3 | BRF_GRA }, // 4 + { "234-c3.c3", 0x800000, 0x91ab1a30, 3 | BRF_GRA }, // 5 + { "234-c4.c4", 0x800000, 0x3d60b037, 3 | BRF_GRA }, // 6 + { "234-c5.c5", 0x400000, 0x1ba80cee, 3 | BRF_GRA }, // 7 + { "234-c6.c6", 0x400000, 0xbeafd091, 3 | BRF_GRA }, // 8 + + { "234-m1.m1", 0x020000, 0x087628ea, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "234-v1.v1", 0x400000, 0xed66b76f, 5 | BRF_SND }, // 10 Sound data + { "234-v2.v2", 0x400000, 0xa0e7f6e2, 5 | BRF_SND }, // 11 + { "234-v3.v3", 0x400000, 0xa506e1e2, 5 | BRF_SND }, // 12 + { "234-v4.v4", 0x400000, 0x0e34157f, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(lastblad, lastblad, neogeo) +STD_ROM_FN(lastblad) + +struct BurnDriver BurnDrvlastblad = { + "lastblad", NULL, "neogeo", NULL, "1997", + "The Last Blade / Bakumatsu Roman - Gekka no Kenshi (NGM-2340)\0", NULL, "SNK", "Neo Geo MVS", + L"The Last Blade\0\u5E55\u672B\u6D6A\u6F2B \u6708\u83EF\u306E\u5263\u58EB (NGM-2340)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, lastbladRomInfo, lastbladRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The Last Blade / Bakumatsu Roman - Gekka no Kenshi (NGH-2340) + +static struct BurnRomInfo lastbladhRomDesc[] = { + { "234-pg1.p1", 0x100000, 0xcd01c06d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "234-p2.sp2", 0x400000, 0x0fdc289e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "234-s1.s1", 0x020000, 0x95561412, 2 | BRF_GRA }, // 2 Text layer tiles + + { "234-c1.c1", 0x800000, 0x9f7e2bd3, 3 | BRF_GRA }, // 3 Sprite data + { "234-c2.c2", 0x800000, 0x80623d3c, 3 | BRF_GRA }, // 4 + { "234-c3.c3", 0x800000, 0x91ab1a30, 3 | BRF_GRA }, // 5 + { "234-c4.c4", 0x800000, 0x3d60b037, 3 | BRF_GRA }, // 6 + { "234-c5.c5", 0x400000, 0x1ba80cee, 3 | BRF_GRA }, // 7 + { "234-c6.c6", 0x400000, 0xbeafd091, 3 | BRF_GRA }, // 8 + + { "234-m1.m1", 0x020000, 0x087628ea, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "234-v1.v1", 0x400000, 0xed66b76f, 5 | BRF_SND }, // 10 Sound data + { "234-v2.v2", 0x400000, 0xa0e7f6e2, 5 | BRF_SND }, // 11 + { "234-v3.v3", 0x400000, 0xa506e1e2, 5 | BRF_SND }, // 12 + { "234-v4.v4", 0x400000, 0x0e34157f, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(lastbladh, lastbladh, neogeo) +STD_ROM_FN(lastbladh) + +struct BurnDriver BurnDrvlastbladh = { + "lastbladh", "lastblad", "neogeo", NULL, "1997", + "The Last Blade / Bakumatsu Roman - Gekka no Kenshi (NGH-2340)\0", NULL, "SNK", "Neo Geo AES", + L"The Last Blade\0\u5E55\u672B\u6D6A\u6F2B \u6708\u83EF\u306E\u5263\u58EB (NGH-2340)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, lastbladhRomInfo, lastbladhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The Last Soldier (Korean release of The Last Blade) + +static struct BurnRomInfo lastsoldRomDesc[] = { + { "134-p1k.p1", 0x100000, 0x906f3065, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "234-p2.sp2", 0x400000, 0x0fdc289e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "234-s1.s1", 0x020000, 0x95561412, 2 | BRF_GRA }, // 2 Text layer tiles + + { "234-c1.c1", 0x800000, 0x9f7e2bd3, 3 | BRF_GRA }, // 3 Sprite data + { "234-c2.c2", 0x800000, 0x80623d3c, 3 | BRF_GRA }, // 4 + { "234-c3.c3", 0x800000, 0x91ab1a30, 3 | BRF_GRA }, // 5 + { "234-c4.c4", 0x800000, 0x3d60b037, 3 | BRF_GRA }, // 6 + { "234-c5.c5", 0x400000, 0x1ba80cee, 3 | BRF_GRA }, // 7 + { "234-c6.c6", 0x400000, 0xbeafd091, 3 | BRF_GRA }, // 8 + + { "234-m1.m1", 0x020000, 0x087628ea, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "234-v1.v1", 0x400000, 0xed66b76f, 5 | BRF_SND }, // 10 Sound data + { "234-v2.v2", 0x400000, 0xa0e7f6e2, 5 | BRF_SND }, // 11 + { "234-v3.v3", 0x400000, 0xa506e1e2, 5 | BRF_SND }, // 12 + { "234-v4.v4", 0x400000, 0x0e34157f, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(lastsold, lastsold, neogeo) +STD_ROM_FN(lastsold) + +struct BurnDriver BurnDrvlastsold = { + "lastsold", "lastblad", "neogeo", NULL, "1997", + "The Last Soldier (Korean release of The Last Blade)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, lastsoldRomInfo, lastsoldRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The Irritating Maze / Ultra Denryu Iraira Bou + +static struct BurnRomInfo irrmazeRomDesc[] = { + { "236-p1.p1", 0x200000, 0x4c2ff660, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "236-s1.s1", 0x020000, 0x5d1ca640, 2 | BRF_GRA }, // 1 Text layer tiles + + { "236-c1.c1", 0x400000, 0xc1d47902, 3 | BRF_GRA }, // 2 Sprite data + { "236-c2.c2", 0x400000, 0xe15f972e, 3 | BRF_GRA }, // 3 + + { "236-m1.m1", 0x020000, 0x880a1abd, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "236-v1.v1", 0x200000, 0x5f89c3b4, 5 | BRF_SND }, // 5 Sound data + { "236-v2.v2", 0x100000, 0x1e843567, 6 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(irrmaze, irrmaze, neotrackball) +STD_ROM_FN(irrmaze) + +struct BurnDriver BurnDrvIrrmaze = { + "irrmaze", NULL, "neogeo", NULL, "1997", + "The Irritating Maze / Ultra Denryu Iraira Bou\0", NULL, "SNK / Saurus", "Neo Geo MVS", + L"The Irritating Maze\0\u30A6\u30EB\u30C8\u30E9\u96FB\u6D41\u30A4\u30E9\u30A4\u30E9\u68D2\0", NULL, NULL, NULL, + BDF_GAME_WORKING /*| BDF_TRACKBALL*/, 1, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_TRACKBALL | HARDWARE_SNK_SWAPP, GBF_MISC, 0, + NULL, irrmazeRomInfo, irrmazeRomName, NULL, NULL, neotrackballInputInfo, neotrackballDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Real Bout Fatal Fury 2 - The Newcomers / Real Bout Garou Densetsu 2 - the newcomers (NGM-2400) + +static struct BurnRomInfo rbff2RomDesc[] = { + { "240-p1.p1", 0x100000, 0x80e41205, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "240-p2.sp2", 0x400000, 0x960aa88d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "240-s1.s1", 0x020000, 0xda3b40de, 2 | BRF_GRA }, // 2 Text layer tiles + + { "240-c1.c1", 0x800000, 0xeffac504, 3 | BRF_GRA }, // 3 Sprite data + { "240-c2.c2", 0x800000, 0xed182d44, 3 | BRF_GRA }, // 4 + { "240-c3.c3", 0x800000, 0x22e0330a, 3 | BRF_GRA }, // 5 + { "240-c4.c4", 0x800000, 0xc19a07eb, 3 | BRF_GRA }, // 6 + { "240-c5.c5", 0x800000, 0x244dff5a, 3 | BRF_GRA }, // 7 + { "240-c6.c6", 0x800000, 0x4609e507, 3 | BRF_GRA }, // 8 + + { "240-m1.m1", 0x040000, 0xed482791, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "240-v1.v1", 0x400000, 0xf796265a, 5 | BRF_SND }, // 10 Sound data + { "240-v2.v2", 0x400000, 0x2cb3f3bb, 5 | BRF_SND }, // 11 + { "240-v3.v3", 0x400000, 0x8fe1367a, 5 | BRF_SND }, // 12 + { "240-v4.v4", 0x200000, 0x996704d8, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(rbff2, rbff2, neogeo) +STD_ROM_FN(rbff2) + +struct BurnDriver BurnDrvrbff2 = { + "rbff2", NULL, "neogeo", NULL, "1998", + "Real Bout Fatal Fury 2 - The Newcomers / Real Bout Garou Densetsu 2 - the newcomers (NGM-2400)\0", NULL, "SNK", "Neo Geo MVS", + L"Real Bout Fatal Fury 2 - The Newcomers\0Real Bout \u9913\u72FC\u4F1D\u8AAC\uFF12 (NGM-2400)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbff2RomInfo, rbff2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Real Bout Fatal Fury 2 - The Newcomers / Real Bout Garou Densetsu 2 - the newcomers (NGH-2400) + +static struct BurnRomInfo rbff2hRomDesc[] = { + { "240-pg1.p1", 0x100000, 0xb6969780, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "240-p2.sp2", 0x400000, 0x960aa88d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "240-s1.s1", 0x020000, 0xda3b40de, 2 | BRF_GRA }, // 2 Text layer tiles + + { "240-c1.c1", 0x800000, 0xeffac504, 3 | BRF_GRA }, // 3 Sprite data + { "240-c2.c2", 0x800000, 0xed182d44, 3 | BRF_GRA }, // 4 + { "240-c3.c3", 0x800000, 0x22e0330a, 3 | BRF_GRA }, // 5 + { "240-c4.c4", 0x800000, 0xc19a07eb, 3 | BRF_GRA }, // 6 + { "240-c5.c5", 0x800000, 0x244dff5a, 3 | BRF_GRA }, // 7 + { "240-c6.c6", 0x800000, 0x4609e507, 3 | BRF_GRA }, // 8 + + { "240-m1.m1", 0x040000, 0xed482791, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "240-v1.v1", 0x400000, 0xf796265a, 5 | BRF_SND }, // 10 Sound data + { "240-v2.v2", 0x400000, 0x2cb3f3bb, 5 | BRF_SND }, // 11 + { "240-v3.v3", 0x400000, 0x8fe1367a, 5 | BRF_SND }, // 12 + { "240-v4.v4", 0x200000, 0x996704d8, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(rbff2h, rbff2h, neogeo) +STD_ROM_FN(rbff2h) + +struct BurnDriver BurnDrvrbff2h = { + "rbff2h", "rbff2", "neogeo", NULL, "1998", + "Real Bout Fatal Fury 2 - The Newcomers / Real Bout Garou Densetsu 2 - the newcomers (NGH-2400)\0", NULL, "SNK", "Neo Geo MVS", + L"Real Bout Fatal Fury 2 - The Newcomers\0Real Bout \u9913\u72FC\u4F1D\u8AAC\uFF12 (NGH-2400)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbff2hRomInfo, rbff2hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Real Bout Fatal Fury 2 - The Newcomers (Korean release) + +static struct BurnRomInfo rbff2kRomDesc[] = { + { "140-p1k.p1", 0x100000, 0x965edee1, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "240-p2.sp2", 0x400000, 0x960aa88d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "240-s1.s1", 0x020000, 0xda3b40de, 2 | BRF_GRA }, // 2 Text layer tiles + + { "240-c1.c1", 0x800000, 0xeffac504, 3 | BRF_GRA }, // 3 Sprite data + { "240-c2.c2", 0x800000, 0xed182d44, 3 | BRF_GRA }, // 4 + { "240-c3.c3", 0x800000, 0x22e0330a, 3 | BRF_GRA }, // 5 + { "240-c4.c4", 0x800000, 0xc19a07eb, 3 | BRF_GRA }, // 6 + { "240-c5.c5", 0x800000, 0x244dff5a, 3 | BRF_GRA }, // 7 + { "240-c6.c6", 0x800000, 0x4609e507, 3 | BRF_GRA }, // 8 + + { "240-m1.m1", 0x040000, 0xed482791, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "240-v1.v1", 0x400000, 0xf796265a, 5 | BRF_SND }, // 10 Sound data + { "240-v2.v2", 0x400000, 0x2cb3f3bb, 5 | BRF_SND }, // 11 + { "240-v3.v3", 0x400000, 0x8fe1367a, 5 | BRF_SND }, // 12 + { "240-v4.v4", 0x200000, 0x996704d8, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(rbff2k, rbff2k, neogeo) +STD_ROM_FN(rbff2k) + +struct BurnDriver BurnDrvrbff2k = { + "rbff2k", "rbff2", "neogeo", NULL, "1998", + "Real Bout Fatal Fury 2 - The Newcomers (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_FATFURY, + NULL, rbff2kRomInfo, rbff2kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Metal Slug 2 - Super Vehicle-001/II + +static struct BurnRomInfo mslug2RomDesc[] = { + { "241-p1.p1", 0x100000, 0x2a53c5da, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "241-p2.sp2", 0x200000, 0x38883f44, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "241-s1.s1", 0x020000, 0xf3d32f0f, 2 | BRF_GRA }, // 2 Text layer tiles + + { "241-c1.c1", 0x800000, 0x394b5e0d, 3 | BRF_GRA }, // 3 Sprite data + { "241-c2.c2", 0x800000, 0xe5806221, 3 | BRF_GRA }, // 4 + { "241-c3.c3", 0x800000, 0x9f6bfa6f, 3 | BRF_GRA }, // 5 + { "241-c4.c4", 0x800000, 0x7d3e306f, 3 | BRF_GRA }, // 6 + + { "241-m1.m1", 0x020000, 0x94520ebd, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "241-v1.v1", 0x400000, 0x99ec20e8, 5 | BRF_SND }, // 8 Sound data + { "241-v2.v2", 0x400000, 0xecb16799, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(mslug2, mslug2, neogeo) +STD_ROM_FN(mslug2) + +struct BurnDriver BurnDrvMSlug2 = { + "mslug2", NULL, "neogeo", NULL, "1998", + "Metal Slug 2 - Super Vehicle-001/II\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug2RomInfo, mslug2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (NGM-2420) + +static struct BurnRomInfo kof98RomDesc[] = { + { "242-p1.p1", 0x200000, 0x8893df89, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "242-p2.sp2", 0x400000, 0x980aba4c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "242-s1.s1", 0x020000, 0x7f7b4805, 2 | BRF_GRA }, // 2 Text layer tiles + + { "242-c1.c1", 0x800000, 0xe564ecd6, 3 | BRF_GRA }, // 3 Sprite data + { "242-c2.c2", 0x800000, 0xbd959b60, 3 | BRF_GRA }, // 4 + { "242-c3.c3", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5 + { "242-c4.c4", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6 + { "242-c5.c5", 0x800000, 0x9d10bed3, 3 | BRF_GRA }, // 7 + { "242-c6.c6", 0x800000, 0xda07b6a2, 3 | BRF_GRA }, // 8 + { "242-c7.c7", 0x800000, 0xf6d7a38a, 3 | BRF_GRA }, // 9 + { "242-c8.c8", 0x800000, 0xc823e045, 3 | BRF_GRA }, // 10 + + { "242-m1.m1", 0x040000, 0x4ef7016b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "242-v1.v1", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 12 Sound data + { "242-v2.v2", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 13 + { "242-v3.v3", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 14 + { "242-v4.v4", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof98, kof98, neogeo) +STD_ROM_FN(kof98) + +static void kof98Decrypt() +{ + INT32 sec[] = {0x000000, 0x100000, 0x000004, 0x100004, 0x10000a, 0x00000a, 0x10000e, 0x00000e}; + INT32 pos[] = {0x000, 0x004, 0x00a, 0x00e}; + + UINT8* pTemp = (UINT8*)malloc(0x200000); + + if (pTemp == NULL) { + return; + } + + memcpy(pTemp, Neo68KROMActive, 0x200000); + + for (INT32 i = 0x0800; i < 0x100000; i += 0x0200) { + for (INT32 j = 0; j < 0x0100; j += 0x10) { + for (INT32 k = 0; k < 8; k++) { + memcpy(&Neo68KROMActive[i + j + k * 2 + 0], &pTemp[i + j + sec[k] + 0x0100], 2); + memcpy(&Neo68KROMActive[i + j + k * 2 + 0x0100], &pTemp[i + j + sec[k] + 0], 2); + } + if (i >= 0x080000 && i < 0x0c0000) { + for (INT32 k = 0; k < 4; k++) { + memcpy(&Neo68KROMActive[i + j + pos[k] + 0], &pTemp[i + j + pos[k] + 0], 2); + memcpy(&Neo68KROMActive[i + j + pos[k] + 0x0100], &pTemp[i + j + pos[k] + 0x0100], 2); + } + } + if (i >= 0x0c0000) { + for (INT32 k = 0; k < 4; k++) { + memcpy(&Neo68KROMActive[i + j + pos[k] + 0], &pTemp[i + j + pos[k] + 0x0100], 2); + memcpy(&Neo68KROMActive[i + j + pos[k] + 0x0100], &pTemp[i + j + pos[k] + 0], 2); + } + } + } + + memcpy(&Neo68KROMActive[i + 0x000000], &pTemp[i + 0x000000], 2); + memcpy(&Neo68KROMActive[i + 0x000002], &pTemp[i + 0x100000], 2); + memcpy(&Neo68KROMActive[i + 0x000100], &pTemp[i + 0x000100], 2); + memcpy(&Neo68KROMActive[i + 0x000102], &pTemp[i + 0x100100], 2); + } + + memcpy(&Neo68KROMActive[0x100000], &Neo68KROMActive[0x200000], 0x400000); + + if (pTemp) { + free(pTemp); + pTemp = NULL; + } +} + +static UINT16 nkof98Protection; + +static void kof98Protection() +{ + // We need two writes because the BIOS vector block is actually 1024 bytes large + switch (nkof98Protection) { + case 0x0090: + *((UINT32*)Neo68KROMActive + 0x0100) = 0x00C200FD; + SekWriteLongROM(0x000100, 0x00C200FD); + break; + case 0x00F0: + *((UINT32*)Neo68KROMActive + 0x0100) = 0x4E454F2D; + SekWriteLongROM(0x000100, 0x4E454F2D); + break; + } +} + +void __fastcall kof98WriteByteProtection(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x20AAAA: { + nkof98Protection &= 0x00FF; + nkof98Protection |= byteValue << 8; + kof98Protection(); + } + case 0x20AAAB: { + nkof98Protection &= 0xFF00; + nkof98Protection |= byteValue; + kof98Protection(); + } + } +} + +void __fastcall kof98WriteWordProtection(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x20AAAA: { + nkof98Protection = wordValue; + kof98Protection(); + } + } +} + +static void kof98InstallHandler() +{ + SekMapHandler(6, 0x200000, 0x2FFBFF, SM_WRITE); + SekSetWriteWordHandler(6, kof98WriteWordProtection); + SekSetWriteByteHandler(6, kof98WriteByteProtection); + + nkof98Protection = 0; +} + +static INT32 kof98Init() +{ + NeoCallbackActive->pInitialise = kof98Decrypt; + NeoCallbackActive->pInstallHandlers = kof98InstallHandler; +// NeoCallbackActive->pScan = kof98Scan; + + return NeoInit(); + +} + +struct BurnDriver BurnDrvKof98 = { + "kof98", NULL, "neogeo", NULL, "1998", + "The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (NGM-2420)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof98RomInfo, kof98RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof98Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (Korean board) + +static struct BurnRomInfo kof98kRomDesc[] = { + { "242-p1.p1", 0x200000, 0x8893df89, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "242-p2.sp2", 0x400000, 0x980aba4c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "242-s1.s1", 0x020000, 0x7f7b4805, 2 | BRF_GRA }, // 2 Text layer tiles + + { "242-c1.c1", 0x800000, 0xe564ecd6, 3 | BRF_GRA }, // 3 Sprite data + { "242-c2.c2", 0x800000, 0xbd959b60, 3 | BRF_GRA }, // 4 + { "242-c3.c3", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5 + { "242-c4.c4", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6 + { "242-c5.c5", 0x800000, 0x9d10bed3, 3 | BRF_GRA }, // 7 + { "242-c6.c6", 0x800000, 0xda07b6a2, 3 | BRF_GRA }, // 8 + { "242-c7.c7", 0x800000, 0xf6d7a38a, 3 | BRF_GRA }, // 9 + { "242-c8.c8", 0x800000, 0xc823e045, 3 | BRF_GRA }, // 10 + + { "242-m1k.m1", 0x040000, 0xce12da0c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "242-v1.v1", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 12 Sound data + { "242-v2.v2", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 13 + { "242-v3.v3", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 14 + { "242-v4.v4", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof98k, kof98k, neogeo) +STD_ROM_FN(kof98k) + +struct BurnDriver BurnDrvKof98k = { + "kof98k", "kof98", "neogeo", NULL, "1998", + "The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (Korean board)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof98kRomInfo, kof98kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof98Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (Korean board 2) + +static struct BurnRomInfo kof98kaRomDesc[] = { + { "242-p1.p1", 0x200000, 0x8893df89, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "242-p2.sp2", 0x400000, 0x980aba4c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "242-s1.s1", 0x020000, 0x7f7b4805, 2 | BRF_GRA }, // 2 Text layer tiles + + { "242-c1.c1", 0x800000, 0xe564ecd6, 3 | BRF_GRA }, // 3 Sprite data + { "242-c2.c2", 0x800000, 0xbd959b60, 3 | BRF_GRA }, // 4 + { "242-c3.c3", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5 + { "242-c4.c4", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6 + { "242-c5.c5", 0x800000, 0x9d10bed3, 3 | BRF_GRA }, // 7 + { "242-c6.c6", 0x800000, 0xda07b6a2, 3 | BRF_GRA }, // 8 + { "242-c7.c7", 0x800000, 0xf6d7a38a, 3 | BRF_GRA }, // 9 + { "242-c8.c8", 0x800000, 0xc823e045, 3 | BRF_GRA }, // 10 + + { "242-mg1k.m1", 0x040000, 0xce9fb07c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "242-v1.v1", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 12 Sound data + { "242-v2.v2", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 13 + { "242-v3.v3", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 14 + { "242-v4.v4", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof98ka, kof98ka, neogeo) +STD_ROM_FN(kof98ka) + +struct BurnDriver BurnDrvKof98ka = { + "kof98ka", "kof98", "neogeo", NULL, "1998", + "The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (Korean board 2)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof98kaRomInfo, kof98kaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof98Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (NGH-2420) + +static struct BurnRomInfo kof98hRomDesc[] = { + { "242-pn1.p1", 0x100000, 0x61ac868a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "242-p2.sp2", 0x400000, 0x980aba4c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "242-s1.s1", 0x020000, 0x7f7b4805, 2 | BRF_GRA }, // 2 Text layer tiles + + { "242-c1.c1", 0x800000, 0xe564ecd6, 3 | BRF_GRA }, // 3 Sprite data + { "242-c2.c2", 0x800000, 0xbd959b60, 3 | BRF_GRA }, // 4 + { "242-c3.c3", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5 + { "242-c4.c4", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6 + { "242-c5.c5", 0x800000, 0x9d10bed3, 3 | BRF_GRA }, // 7 + { "242-c6.c6", 0x800000, 0xda07b6a2, 3 | BRF_GRA }, // 8 + { "242-c7.c7", 0x800000, 0xf6d7a38a, 3 | BRF_GRA }, // 9 + { "242-c8.c8", 0x800000, 0xc823e045, 3 | BRF_GRA }, // 10 + + { "242-mg1.m1", 0x040000, 0x4e7a6b1b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "242-v1.v1", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 12 Sound data + { "242-v2.v2", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 13 + { "242-v3.v3", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 14 + { "242-v4.v4", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof98h, kof98h, neogeo) +STD_ROM_FN(kof98h) + +struct BurnDriver BurnDrvKof98h = { + "kof98h", "kof98", "neogeo", NULL, "1998", + "The King of Fighters '98 - The Slugfest / King of Fighters '98 - dream match never ends (NGH-2420)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof98hRomInfo, kof98hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The Last Blade 2 / Bakumatsu Roman - Dai Ni Maku Gekka no Kenshi (NGM-2430)(NGH-2430) + +static struct BurnRomInfo lastbld2RomDesc[] = { + { "243-pg1.p1", 0x100000, 0xaf1e6554, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "243-pg2.sp2", 0x400000, 0xadd4a30b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "243-s1.s1", 0x020000, 0xc9cd2298, 2 | BRF_GRA }, // 2 Text layer tiles + + { "243-c1.c1", 0x800000, 0x5839444d, 3 | BRF_GRA }, // 3 Sprite data + { "243-c2.c2", 0x800000, 0xdd087428, 3 | BRF_GRA }, // 4 + { "243-c3.c3", 0x800000, 0x6054cbe0, 3 | BRF_GRA }, // 5 + { "243-c4.c4", 0x800000, 0x8bd2a9d2, 3 | BRF_GRA }, // 6 + { "243-c5.c5", 0x800000, 0x6a503dcf, 3 | BRF_GRA }, // 7 + { "243-c6.c6", 0x800000, 0xec9c36d0, 3 | BRF_GRA }, // 8 + + { "243-m1.m1", 0x020000, 0xacf12d10, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "243-v1.v1", 0x400000, 0xf7ee6fbb, 5 | BRF_SND }, // 10 Sound data + { "243-v2.v2", 0x400000, 0xaa9e4df6, 5 | BRF_SND }, // 11 + { "243-v3.v3", 0x400000, 0x4ac750b2, 5 | BRF_SND }, // 12 + { "243-v4.v4", 0x400000, 0xf5c64ba6, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(lastbld2, lastbld2, neogeo) +STD_ROM_FN(lastbld2) + +struct BurnDriver BurnDrvlastbld2 = { + "lastbld2", NULL, "neogeo", NULL, "1998", + "The Last Blade 2 / Bakumatsu Roman - Dai Ni Maku Gekka no Kenshi (NGM-2430)(NGH-2430)\0", NULL, "SNK", "Neo Geo MVS", + L"The Last Blade 2\0\u5E55\u672B\u6D6A\u6F2B\u7B2C\u4E8C\u5E55 - \u6708\u83EF\u306E\u5263\u58EB - \u6708\u306B\u54B2\u304F\u83EF\u3001\u6563\u308A\u3086\u304F\u82B1 (NGM-2430)(NGH-2430)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, lastbld2RomInfo, lastbld2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Neo-Geo Cup '98 - The Road to the Victory + +static struct BurnRomInfo neocup98RomDesc[] = { + { "244-p1.p1", 0x200000, 0xf8fdb7a5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "244-s1.s1", 0x020000, 0x9bddb697, 2 | BRF_GRA }, // 1 Text layer tiles + + { "244-c1.c1", 0x800000, 0xc7a62b23, 3 | BRF_GRA }, // 2 Sprite data + { "244-c2.c2", 0x800000, 0x33aa0f35, 3 | BRF_GRA }, // 3 + + { "244-m1.m1", 0x020000, 0xa701b276, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "244-v1.v1", 0x400000, 0x79def46d, 5 | BRF_SND }, // 5 Sound data + { "244-v2.v2", 0x200000, 0xb231902f, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(neocup98, neocup98, neogeo) +STD_ROM_FN(neocup98) + +struct BurnDriver BurnDrvNeocup98 = { + "neocup98", NULL, "neogeo", NULL, "1998", + "Neo-Geo Cup '98 - The Road to the Victory\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSFOOTBALL, 0, + NULL, neocup98RomInfo, neocup98RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Metal Slug X - Super Vehicle-001 + +static struct BurnRomInfo mslugxRomDesc[] = { + { "250-p1.p1", 0x100000, 0x81f1f60b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "250-p2.ep1", 0x400000, 0x1fda2e12, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "250-s1.s1", 0x020000, 0xfb6f441d, 2 | BRF_GRA }, // 2 Text layer tiles + + { "250-c1.c1", 0x800000, 0x09a52c6f, 3 | BRF_GRA }, // 3 Sprite data + { "250-c2.c2", 0x800000, 0x31679821, 3 | BRF_GRA }, // 4 + { "250-c3.c3", 0x800000, 0xfd602019, 3 | BRF_GRA }, // 5 + { "250-c4.c4", 0x800000, 0x31354513, 3 | BRF_GRA }, // 6 + { "250-c5.c5", 0x800000, 0xa4b56124, 3 | BRF_GRA }, // 7 + { "250-c6.c6", 0x800000, 0x83e3e69d, 3 | BRF_GRA }, // 8 + + { "250-m1.m1", 0x020000, 0xfd42a842, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "250-v1.v1", 0x400000, 0xc79ede73, 5 | BRF_SND }, // 10 Sound data + { "250-v2.v2", 0x400000, 0xea9aabe1, 5 | BRF_SND }, // 11 + { "250-v3.v3", 0x200000, 0x2ca65102, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(mslugx, mslugx, neogeo) +STD_ROM_FN(mslugx) + +static void mslugxPatch() +{ + for (INT32 i = 0; i < 0x100000 - 8; i += 2) { + if (*((UINT16*)(Neo68KROMActive + i + 0)) == 0x0243 && *((UINT16*)(Neo68KROMActive + i + 2)) == 0x0001 && *((UINT16*)(Neo68KROMActive + i + 4)) == 0x6600) { + *((UINT16*)(Neo68KROMActive + i + 4)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + i + 6)) = 0x4e71; + } + } + + *((UINT16*)(Neo68KROMActive + 0x3bdc)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + 0x3bde)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + 0x3be0)) = 0x4e71; + + *((UINT16*)(Neo68KROMActive + 0x3c0c)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + 0x3c0e)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + 0x3c10)) = 0x4e71; + + *((UINT16*)(Neo68KROMActive + 0x3c36)) = 0x4e71; + *((UINT16*)(Neo68KROMActive + 0x3c38)) = 0x4e71; +} + +static INT32 mslugxInit() +{ + NeoCallbackActive->pInitialise = mslugxPatch; + + return NeoInit(); +} + +struct BurnDriver BurnDrvMSlugX = { + "mslugx", NULL, "neogeo", NULL, "1999", + "Metal Slug X - Super Vehicle-001\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, FBF_MSLUG, + NULL, mslugxRomInfo, mslugxRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslugxInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '99 - Millennium Battle (set 1) + +static struct BurnRomInfo kof99RomDesc[] = { + { "ka.neo-sma", 0x040000, 0x7766d09e, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "251-p1.p1", 0x400000, 0x006e4532, 1 | BRF_ESS | BRF_PRG }, // 1 + { "251-p2.p2", 0x400000, 0x90175f15, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "251-c1.c1", 0x800000, 0x0f9e93fe, 3 | BRF_GRA }, // 3 Sprite data + { "251-c2.c2", 0x800000, 0xe71e2ea3, 3 | BRF_GRA }, // 4 + { "251-c3.c3", 0x800000, 0x238755d2, 3 | BRF_GRA }, // 5 + { "251-c4.c4", 0x800000, 0x438c8b22, 3 | BRF_GRA }, // 6 + { "251-c5.c5", 0x800000, 0x0b0abd0a, 3 | BRF_GRA }, // 7 + { "251-c6.c6", 0x800000, 0x65bbf281, 3 | BRF_GRA }, // 8 + { "251-c7.c7", 0x800000, 0xff65f62e, 3 | BRF_GRA }, // 9 + { "251-c8.c8", 0x800000, 0x8d921c68, 3 | BRF_GRA }, // 10 + + { "251-m1.m1", 0x020000, 0x5e74539c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "251-v1.v1", 0x400000, 0xef2eecc8, 5 | BRF_SND }, // 12 Sound data + { "251-v2.v2", 0x400000, 0x73e211ca, 5 | BRF_SND }, // 13 + { "251-v3.v3", 0x400000, 0x821901da, 5 | BRF_SND }, // 14 + { "251-v4.v4", 0x200000, 0xb49e6178, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof99, kof99, neogeo) +STD_ROM_FN(kof99) + +static void kof99SMADecrypt() +{ + for (INT32 i = 0; i < 0x800000 / 2; i++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i] = BITSWAP16(((UINT16*)(Neo68KROMActive + 0x100000))[i], 13, 7, 3, 0, 9, 4, 5, 6, 1, 12, 8, 14, 10, 11, 2, 15); + } + + for (INT32 i = 0; i < 0x0C0000 / 2; i++) { + ((UINT16*)Neo68KROMActive)[i] = ((UINT16*)Neo68KROMActive)[0x700000 / 2 + BITSWAP24(i, 23, 22, 21, 20, 19, 18, 11, 6, 14, 17, 16, 5, 8, 10, 12, 0, 4, 3, 2, 7, 9, 15, 13, 1)]; + } + + for (INT32 i = 0; i < 0x600000 / 2; i += 0x0800 / 2) { + UINT16 nBuffer[0x0800 / 2]; + memcpy(nBuffer, &((UINT16*)(Neo68KROMActive + 0x100000))[i], 0x0800); + for (INT32 j = 0; j < 0x0800 / 2; j++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i + j] = nBuffer[BITSWAP24(j, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 6, 2, 4, 9, 8, 3, 1, 7, 0, 5)]; + } + } +} + +void __fastcall kof99WriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2FFFF0) { + static UINT32 bankoffset[64] = { + 0x100000, 0x200000, 0x300000, 0x400000, + 0x4cc000, 0x5cc000, 0x4f2000, 0x5f2000, + 0x507800, 0x607800, 0x50d000, 0x60d000, + 0x517800, 0x617800, 0x520800, 0x620800, + 0x524800, 0x624800, 0x529000, 0x629000, + 0x52e800, 0x62e800, 0x531800, 0x631800, + 0x64d000, 0x651000, 0x667000, 0x692800, + 0x688800, 0x681800, 0x699800, 0x694800, + 0x698000, /* rest not used? */ + }; + + // Unscramble bank number + INT32 nBank = + (((wordValue >> 14) & 1) << 0) + + (((wordValue >> 6) & 1) << 1) + + (((wordValue >> 8) & 1) << 2) + + (((wordValue >> 10) & 1) << 3) + + (((wordValue >> 12) & 1) << 4) + + (((wordValue >> 5) & 1) << 5); + + if (bankoffset[nBank] != nNeo68KROMBank) { + nNeo68KROMBank = bankoffset[nBank]; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFBFF, SM_ROM); + } + } +} + +static INT32 kof99Init() +{ + nNeoProtectionXor = 0x00; + + return NeoSMAInit(kof99SMADecrypt, kof99WriteWordBankswitch, 0x2FFFF8, 0x2FFFFA); +} + +struct BurnDriver BurnDrvkof99 = { + "kof99", NULL, "neogeo", NULL, "1999", + "The King of Fighters '99 - Millennium Battle (set 1)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_VSFIGHT, FBF_KOF, + NULL, kof99RomInfo, kof99RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof99Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '99 - Millennium Battle (set 2) + +static struct BurnRomInfo kof99hRomDesc[] = { + { "kc.neo-sma", 0x040000, 0x6c9d0647, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "251-p1.p1", 0x400000, 0x006e4532, 1 | BRF_ESS | BRF_PRG }, // 1 + { "251-pg2.p2", 0x400000, 0xd9057f51, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "251-c1.c1", 0x800000, 0x0f9e93fe, 3 | BRF_GRA }, // 3 Sprite data + { "251-c2.c2", 0x800000, 0xe71e2ea3, 3 | BRF_GRA }, // 4 + { "251-c3.c3", 0x800000, 0x238755d2, 3 | BRF_GRA }, // 5 + { "251-c4.c4", 0x800000, 0x438c8b22, 3 | BRF_GRA }, // 6 + { "251-c5.c5", 0x800000, 0x0b0abd0a, 3 | BRF_GRA }, // 7 + { "251-c6.c6", 0x800000, 0x65bbf281, 3 | BRF_GRA }, // 8 + { "251-c7.c7", 0x800000, 0xff65f62e, 3 | BRF_GRA }, // 9 + { "251-c8.c8", 0x800000, 0x8d921c68, 3 | BRF_GRA }, // 10 + + { "251-m1.m1", 0x020000, 0x5e74539c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "251-v1.v1", 0x400000, 0xef2eecc8, 5 | BRF_SND }, // 12 Sound data + { "251-v2.v2", 0x400000, 0x73e211ca, 5 | BRF_SND }, // 13 + { "251-v3.v3", 0x400000, 0x821901da, 5 | BRF_SND }, // 14 + { "251-v4.v4", 0x200000, 0xb49e6178, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof99h, kof99h, neogeo) +STD_ROM_FN(kof99h) + +struct BurnDriver BurnDrvkof99h = { + "kof99h", "kof99", "neogeo", NULL, "1999", + "The King of Fighters '99 - Millennium Battle (set 2)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_VSFIGHT, FBF_KOF, + NULL, kof99hRomInfo, kof99hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof99Init, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '99 - Millennium Battle (earlier) + +static struct BurnRomInfo kof99eRomDesc[] = { + { "ka.neo-sma", 0x040000, 0x7766d09e, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "251-ep1.p1", 0x200000, 0x1e8d692d, 1 | BRF_ESS | BRF_PRG }, // 1 + { "251-ep2.p2", 0x200000, 0xd6206e5a, 1 | BRF_ESS | BRF_PRG }, // 2 + { "251-ep3.p3", 0x200000, 0xd58c3ef8, 1 | BRF_ESS | BRF_PRG }, // 3 + { "251-ep4.p4", 0x200000, 0x52de02ae, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "251-c1.c1", 0x800000, 0x0f9e93fe, 3 | BRF_GRA }, // 5 Sprite data + { "251-c2.c2", 0x800000, 0xe71e2ea3, 3 | BRF_GRA }, // 6 + { "251-c3.c3", 0x800000, 0x238755d2, 3 | BRF_GRA }, // 7 + { "251-c4.c4", 0x800000, 0x438c8b22, 3 | BRF_GRA }, // 8 + { "251-c5.c5", 0x800000, 0x0b0abd0a, 3 | BRF_GRA }, // 9 + { "251-c6.c6", 0x800000, 0x65bbf281, 3 | BRF_GRA }, // 10 + { "251-c7.c7", 0x800000, 0xff65f62e, 3 | BRF_GRA }, // 11 + { "251-c8.c8", 0x800000, 0x8d921c68, 3 | BRF_GRA }, // 12 + + { "251-m1.m1", 0x020000, 0x5e74539c, 4 | BRF_ESS | BRF_PRG }, // 13 Z80 code + + { "251-v1.v1", 0x400000, 0xef2eecc8, 5 | BRF_SND }, // 14 Sound data + { "251-v2.v2", 0x400000, 0x73e211ca, 5 | BRF_SND }, // 15 + { "251-v3.v3", 0x400000, 0x821901da, 5 | BRF_SND }, // 16 + { "251-v4.v4", 0x200000, 0xb49e6178, 5 | BRF_SND }, // 17 +}; + +STDROMPICKEXT(kof99e, kof99e, neogeo) +STD_ROM_FN(kof99e) + +struct BurnDriver BurnDrvkof99e = { + "kof99e", "kof99", "neogeo", NULL, "1999", + "The King of Fighters '99 - Millennium Battle (earlier)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_VSFIGHT, FBF_KOF, + NULL, kof99eRomInfo, kof99eRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof99Init, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '99 - Millennium Battle (Korean release) + +static struct BurnRomInfo kof99kRomDesc[] = { + { "152-p1.p1", 0x100000, 0xf2c7ddfa, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "152-p2.sp2", 0x400000, 0x274ef47a, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "251-c1.c1", 0x800000, 0x0f9e93fe, 3 | BRF_GRA }, // 2 Sprite data + { "251-c2.c2", 0x800000, 0xe71e2ea3, 3 | BRF_GRA }, // 3 + { "251-c3.c3", 0x800000, 0x238755d2, 3 | BRF_GRA }, // 4 + { "251-c4.c4", 0x800000, 0x438c8b22, 3 | BRF_GRA }, // 5 + { "251-c5.c5", 0x800000, 0x0b0abd0a, 3 | BRF_GRA }, // 6 + { "251-c6.c6", 0x800000, 0x65bbf281, 3 | BRF_GRA }, // 7 + { "251-c7.c7", 0x800000, 0xff65f62e, 3 | BRF_GRA }, // 8 + { "251-c8.c8", 0x800000, 0x8d921c68, 3 | BRF_GRA }, // 9 + + { "251-m1.m1", 0x020000, 0x5e74539c, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "251-v1.v1", 0x400000, 0xef2eecc8, 5 | BRF_SND }, // 11 Sound data + { "251-v2.v2", 0x400000, 0x73e211ca, 5 | BRF_SND }, // 12 + { "251-v3.v3", 0x400000, 0x821901da, 5 | BRF_SND }, // 13 + { "251-v4.v4", 0x200000, 0xb49e6178, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof99k, kof99k, neogeo) +STD_ROM_FN(kof99k) + +INT32 kof99kInit() +{ + nNeoProtectionXor = 0x00; + return NeoInit(); +} + +struct BurnDriver BurnDrvkof99k = { + "kof99k", "kof99", "neogeo", NULL, "1999", + "The King of Fighters '99 - Millennium Battle (Korean release)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_VSFIGHT, FBF_KOF, + NULL, kof99kRomInfo, kof99kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof99kInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '99 - Millennium Battle (prototype) + +static struct BurnRomInfo kof99pRomDesc[] = { + { "251-p1p.p1", 0x100000, 0xf37929c4, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "251-p2p.p2", 0x400000, 0x739742ad, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "251-s1p.s1", 0x020000, 0xfb1498ed, 2 | BRF_GRA }, // 2 Text layer tiles + + { "251-c1p.c1", 0x800000, 0xe5d8ffa4, 3 | BRF_GRA }, // 3 Sprite data + { "251-c2p.c2", 0x800000, 0xd822778f, 3 | BRF_GRA }, // 4 + { "251-c3p.c3", 0x800000, 0xf20959e8, 3 | BRF_GRA }, // 5 + { "251-c4p.c4", 0x800000, 0x54ffbe9f, 3 | BRF_GRA }, // 6 + { "251-c5p.c5", 0x800000, 0xd87a3bbc, 3 | BRF_GRA }, // 7 + { "251-c6p.c6", 0x800000, 0x4d40a691, 3 | BRF_GRA }, // 8 + { "251-c7p.c7", 0x800000, 0xa4479a58, 3 | BRF_GRA }, // 9 + { "251-c8p.c8", 0x800000, 0xead513ce, 3 | BRF_GRA }, // 10 + + { "251-m1.m1", 0x020000, 0x5e74539c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "251-v1.v1", 0x400000, 0xef2eecc8, 5 | BRF_SND }, // 12 Sound data + { "251-v2.v2", 0x400000, 0x73e211ca, 5 | BRF_SND }, // 13 + { "251-v3.v3", 0x400000, 0x821901da, 5 | BRF_SND }, // 14 + { "251-v4.v4", 0x200000, 0xb49e6178, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof99p, kof99p, neogeo) +STD_ROM_FN(kof99p) + +struct BurnDriver BurnDrvkof99p = { + "kof99p", "kof99", "neogeo", NULL, "1999", + "The King of Fighters '99 - Millennium Battle (prototype)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof99pRomInfo, kof99pRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Garou - Mark of the Wolves (set 1) + +static struct BurnRomInfo garouRomDesc[] = { + { "kf.neo-sma", 0x040000, 0x98bc93dc, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "253-ep1.p1", 0x200000, 0xea3171a4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "253-ep2.p2", 0x200000, 0x382f704b, 1 | BRF_ESS | BRF_PRG }, // 2 + { "253-ep3.p3", 0x200000, 0xe395bfdd, 1 | BRF_ESS | BRF_PRG }, // 3 + { "253-ep4.p4", 0x200000, 0xda92c08e, 1 | BRF_ESS | BRF_PRG }, // 4 + + { "253-c1.c1", 0x800000, 0x0603e046, 3 | BRF_GRA }, // 5 Sprite data + { "253-c2.c2", 0x800000, 0x0917d2a4, 3 | BRF_GRA }, // 6 + { "253-c3.c3", 0x800000, 0x6737c92d, 3 | BRF_GRA }, // 7 + { "253-c4.c4", 0x800000, 0x5ba92ec6, 3 | BRF_GRA }, // 8 + { "253-c5.c5", 0x800000, 0x3eab5557, 3 | BRF_GRA }, // 9 + { "253-c6.c6", 0x800000, 0x308d098b, 3 | BRF_GRA }, // 10 + { "253-c7.c7", 0x800000, 0xc0e995ae, 3 | BRF_GRA }, // 11 + { "253-c8.c8", 0x800000, 0x21a11303, 3 | BRF_GRA }, // 12 + + { "253-m1.m1", 0x040000, 0x36a806be, 4 | BRF_ESS | BRF_PRG }, // 13 Z80 code + + { "253-v1.v1", 0x400000, 0x263e388c, 5 | BRF_SND }, // 14 Sound data + { "253-v2.v2", 0x400000, 0x2c6bc7be, 5 | BRF_SND }, // 15 + { "253-v3.v3", 0x400000, 0x0425b27d, 5 | BRF_SND }, // 16 + { "253-v4.v4", 0x400000, 0xa54be8a9, 5 | BRF_SND }, // 17 +}; + +STDROMPICKEXT(garou, garou, neogeo) +STD_ROM_FN(garou) + +static void garouSMADecrypt() +{ + for (INT32 i = 0; i < 0x800000 / 2; i++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i] = BITSWAP16(((UINT16*)(Neo68KROMActive + 0x100000))[i], 13, 12, 14, 10, 8, 2, 3, 1, 5, 9, 11, 4, 15, 0, 6, 7); + } + + for (INT32 i = 0; i < 0x0C0000 / 2; i++) { + ((UINT16*)Neo68KROMActive)[i] = ((UINT16*)Neo68KROMActive)[0x710000 / 2 + BITSWAP24(i, 23, 22, 21, 20, 19, 18, 4, 5, 16, 14, 7, 9, 6, 13, 17, 15, 3, 1, 2, 12, 11, 8, 10, 0)]; + } + + for (INT32 i = 0; i < 0x800000 / 2; i += 0x8000 / 2) { + UINT16 nBuffer[0x8000 / 2]; + memcpy(nBuffer, &((UINT16*)(Neo68KROMActive + 0x100000))[i], 0x8000); + for (INT32 j = 0; j < 0x8000 / 2; j++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i + j] = nBuffer[BITSWAP24(j, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 9, 4, 8, 3, 13, 6, 2, 7, 0, 12, 1, 11, 10, 5)]; + } + } +} + +void __fastcall garouWriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2FFFC0) { + static UINT32 bankoffset[64] = { + 0x100000, 0x200000, 0x300000, 0x400000, // 00 + 0x380000, 0x480000, 0x3d0000, 0x4d0000, // 04 + 0x3f0000, 0x4f0000, 0x500000, 0x600000, // 08 + 0x520000, 0x620000, 0x540000, 0x640000, // 12 + 0x598000, 0x698000, 0x5a0000, 0x6a0000, // 16 + 0x5a8000, 0x6a8000, 0x5b0000, 0x6b0000, // 20 + 0x5b8000, 0x6b8000, 0x5c0000, 0x6c0000, // 24 + 0x5c8000, 0x6c8000, 0x5d0000, 0x6d0000, // 28 + 0x558000, 0x658000, 0x560000, 0x660000, // 32 + 0x568000, 0x668000, 0x570000, 0x670000, // 36 + 0x578000, 0x678000, 0x580000, 0x680000, // 40 + 0x588000, 0x688000, 0x590000, 0x690000, // 44 + 0x6d0000, 0x6d8000, 0x6e0000, 0x6e8000, // 48 + 0x6f0000, 0x6f8000, 0x700000, /* rest not used? */ + }; + + // Unscramble bank number + INT32 nBank = + (((wordValue >> 5) & 1) << 0) + + (((wordValue >> 9) & 1) << 1) + + (((wordValue >> 7) & 1) << 2) + + (((wordValue >> 6) & 1) << 3) + + (((wordValue >> 14) & 1) << 4) + + (((wordValue >> 12) & 1) << 5); + + if (bankoffset[nBank] != nNeo68KROMBank) { + nNeo68KROMBank = bankoffset[nBank]; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFBFF, SM_ROM); + } + } +} + +static INT32 garouInit() +{ + nNeoProtectionXor = 0x06; + + return NeoSMAInit(garouSMADecrypt, garouWriteWordBankswitch, 0x2FFFCC, 0x2FFFF0); +} + +struct BurnDriver BurnDrvGarou = { + "garou", NULL, "neogeo", NULL, "1999", + "Garou - Mark of the Wolves (set 1)\0", NULL, "SNK", "Neo Geo MVS", + L"Garou\0\u9913\u72FC - mark of the wolves (set 1)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_VSFIGHT, 0, + NULL, garouRomInfo, garouRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + garouInit, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Garou - Mark of the Wolves (set 2) + +static struct BurnRomInfo garouoRomDesc[] = { + { "ke.neo-sma", 0x040000, 0x96c72233, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "253-p1.p1", 0x400000, 0x18ae5d7e, 1 | BRF_ESS | BRF_PRG }, // 1 + { "253-p2.p2", 0x400000, 0xafffa779, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "253-c1.c1", 0x800000, 0x0603e046, 3 | BRF_GRA }, // 3 Sprite data + { "253-c2.c2", 0x800000, 0x0917d2a4, 3 | BRF_GRA }, // 4 + { "253-c3.c3", 0x800000, 0x6737c92d, 3 | BRF_GRA }, // 5 + { "253-c4.c4", 0x800000, 0x5ba92ec6, 3 | BRF_GRA }, // 6 + { "253-c5.c5", 0x800000, 0x3eab5557, 3 | BRF_GRA }, // 7 + { "253-c6.c6", 0x800000, 0x308d098b, 3 | BRF_GRA }, // 8 + { "253-c7.c7", 0x800000, 0xc0e995ae, 3 | BRF_GRA }, // 9 + { "253-c8.c8", 0x800000, 0x21a11303, 3 | BRF_GRA }, // 10 + + { "253-m1.m1", 0x040000, 0x36a806be, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "253-v1.v1", 0x400000, 0x263e388c, 5 | BRF_SND }, // 12 Sound data + { "253-v2.v2", 0x400000, 0x2c6bc7be, 5 | BRF_SND }, // 13 + { "253-v3.v3", 0x400000, 0x0425b27d, 5 | BRF_SND }, // 14 + { "253-v4.v4", 0x400000, 0xa54be8a9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(garouo, garouo, neogeo) +STD_ROM_FN(garouo) + +static void garouoSMADecrypt() +{ + for (INT32 i = 0; i < 0x800000 / 2; i++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i] = BITSWAP16(((UINT16*)(Neo68KROMActive + 0x100000))[i], 14, 5, 1, 11, 7, 4, 10, 15, 3, 12, 8, 13, 0, 2, 9, 6); + } + + for (INT32 i = 0; i < 0x0C0000 / 2; i++) { + ((UINT16*)Neo68KROMActive)[i] = ((UINT16*)Neo68KROMActive)[0x7F8000 / 2 + BITSWAP24(i, 23, 22, 21, 20, 19, 18, 5, 16, 11, 2, 6, 7, 17, 3, 12, 8, 14, 4, 0, 9, 1, 10, 15, 13)]; + } + + for (INT32 i = 0; i < 0x800000 / 2; i += 0x8000 / 2) { + UINT16 nBuffer[0x8000 / 2]; + memcpy(nBuffer, &((UINT16*)(Neo68KROMActive + 0x100000))[i], 0x8000); + for (INT32 j = 0; j < 0x8000 / 2; j++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i + j] = nBuffer[BITSWAP24(j, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 12, 8, 1, 7, 11, 3, 13, 10, 6, 9, 5, 4, 0, 2)]; + } + } +} + +void __fastcall garouoWriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2FFFC0) { + static UINT32 bankoffset[64] = { + 0x100000, 0x200000, 0x300000, 0x400000, // 00 + 0x380000, 0x480000, 0x3d0000, 0x4d0000, // 04 + 0x3c8000, 0x4c8000, 0x500000, 0x600000, // 08 + 0x520000, 0x620000, 0x540000, 0x640000, // 12 + 0x698000, 0x798000, 0x6a0000, 0x7a0000, // 16 + 0x6a8000, 0x7a8000, 0x6b0000, 0x7b0000, // 20 + 0x6b8000, 0x7b8000, 0x6c0000, 0x7c0000, // 24 + 0x6c8000, 0x7c8000, 0x6d0000, 0x7d0000, // 28 + 0x558000, 0x658000, 0x560000, 0x660000, // 32 + 0x568000, 0x668000, 0x570000, 0x670000, // 36 + 0x578000, 0x678000, 0x580000, 0x680000, // 40 + 0x588000, 0x688000, 0x590000, 0x690000, // 44 + 0x6d8000, 0x7d8000, 0x6e0000, 0x7e0000, // 48 + 0x6e8000, 0x7e8000, 0x7e8000, 0x100000, // 52 + 0x100000, 0x100000, 0x100000, 0x100000, // 56 + 0x100000, 0x100000, 0x100000, 0x100000, // 60 + }; + + // Unscramble bank number + INT32 nBank = + (((wordValue >> 4) & 1) << 0) + + (((wordValue >> 8) & 1) << 1) + + (((wordValue >> 14) & 1) << 2) + + (((wordValue >> 2) & 1) << 3) + + (((wordValue >> 11) & 1) << 4) + + (((wordValue >> 13) & 1) << 5); + + if (bankoffset[nBank] != nNeo68KROMBank) { + nNeo68KROMBank = bankoffset[nBank]; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFBFF, SM_ROM); + } + } +} + +static INT32 garouoInit() +{ + nNeoProtectionXor = 0x06; + + return NeoSMAInit(garouoSMADecrypt, garouoWriteWordBankswitch, 0x2FFFCC, 0x2FFFF0); +} + +struct BurnDriver BurnDrvGarouo = { + "garouo", "garou", "neogeo", NULL, "1999", + "Garou - Mark of the Wolves (set 2)\0", NULL, "SNK", "Neo Geo MVS", + L"Garou\0\u9913\u72FC - mark of the wolves (set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_VSFIGHT, 0, + NULL, garouoRomInfo, garouoRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + garouoInit, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Garou - Mark of the Wolves (prototype) + +static struct BurnRomInfo garoupRomDesc[] = { + { "253-p1p.p1", 0x100000, 0xc72f0c16, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "253-p2p.p2", 0x400000, 0xbf8de565, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "253-s1p.s1", 0x020000, 0x779989de, 2 | BRF_GRA }, // 2 Text layer tiles + + { "253-c1p.c1", 0x800000, 0x5bb5d137, 3 | BRF_GRA }, // 3 Sprite data + { "253-c2p.c2", 0x800000, 0x5c8d2960, 3 | BRF_GRA }, // 4 + { "253-c3p.c3", 0x800000, 0x234d16fc, 3 | BRF_GRA }, // 5 + { "253-c4p.c4", 0x800000, 0xb9b5b993, 3 | BRF_GRA }, // 6 + { "253-c5p.c5", 0x800000, 0x722615d2, 3 | BRF_GRA }, // 7 + { "253-c6p.c6", 0x800000, 0x0a6fab38, 3 | BRF_GRA }, // 8 + { "253-c7p.c7", 0x800000, 0xd68e806f, 3 | BRF_GRA }, // 9 + { "253-c8p.c8", 0x800000, 0xf778fe99, 3 | BRF_GRA }, // 10 + + { "253-m1p.m1", 0x040000, 0xbbe464f7, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "253-v1p.v1", 0x400000, 0x274f3923, 5 | BRF_SND }, // 12 Sound data + { "253-v2p.v2", 0x400000, 0x8f86dabe, 5 | BRF_SND }, // 13 + { "253-v3p.v3", 0x400000, 0x05fd06cd, 5 | BRF_SND }, // 14 + { "253-v4p.v4", 0x400000, 0x14984063, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(garoup, garoup, neogeo) +STD_ROM_FN(garoup) + +struct BurnDriver BurnDrvGaroup = { + "garoup", "garou", "neogeo", NULL, "1999", + "Garou - Mark of the Wolves (prototype)\0", NULL, "SNK", "Neo Geo MVS", + L"Garou\0\u9913\u72FC - mark of the wolves (prototype)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, garoupRomInfo, garoupRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Garou - Mark of the Wolves (bootleg) + +static struct BurnRomInfo garoublRomDesc[] = { + { "garou-p1.bin", 0x0100000, 0xfd446d59, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "garou-p2.bin", 0x0400000, 0x3fb10a84, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "garou-s1.bin", 0x0020000, 0xdf720e33, 2 | BRF_GRA }, // 2 Text layer tiles + + { "garou-c1.bin", 0x1000000, 0xe2ac83fa, 3 | BRF_GRA }, // 3 Sprite data + { "garou-c2.bin", 0x1000000, 0x7c344b24, 3 | BRF_GRA }, // 4 + { "garou-c3.bin", 0x1000000, 0xd3aec5a6, 3 | BRF_GRA }, // 5 + { "garou-c4.bin", 0x1000000, 0xe02a242d, 3 | BRF_GRA }, // 6 + + { "garou-m1.bin", 0x0080000, 0x7c51d002, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "garou-v1.bin", 0x0400000, 0x98d736e4, 5 | BRF_SND }, // 8 Sound data + { "garou-v2.bin", 0x0400000, 0xeb43c03f, 5 | BRF_SND }, // 9 + { "garou-v3.bin", 0x0400000, 0x10a0f814, 5 | BRF_SND }, // 10 + { "garou-v4.bin", 0x0400000, 0x8918fdd3, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(garoubl, garoubl, neogeo) +STD_ROM_FN(garoubl) + +static void garoubl_sx_decode() +{ + INT32 i; + for (i = 0; i < 0x020000; i++) + NeoTextROM[nNeoActiveSlot][i] = BITSWAP08(NeoTextROM[nNeoActiveSlot][i], 7, 6, 0, 4, 3, 2, 1, 5); +} + +static void garoublCallback() +{ + garoubl_sx_decode(); + lans2004_cx_decode(0x800000 * 8); +} + +static INT32 garoublInit() +{ + NeoCallbackActive->pInitialise = garoublCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvgaroubl = { + "garoubl", "garou", "neogeo", NULL, "1999", + "Garou - Mark of the Wolves (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + L"Garou\0\u9913\u72FC - mark of the wolves (bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, garoublRomInfo, garoublRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + garoublInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Metal Slug 3 (NGM-2560) + +static struct BurnRomInfo mslug3RomDesc[] = { + { "neo-sma", 0x040000, 0x9cd55736, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "256-pg1.p1", 0x400000, 0xb07edfd5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "256-pg2.p2", 0x400000, 0x6097c26b, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "256-c1.c1", 0x800000, 0x5a79c34e, 3 | BRF_GRA }, // 3 Sprite data + { "256-c2.c2", 0x800000, 0x944c362c, 3 | BRF_GRA }, // 4 + { "256-c3.c3", 0x800000, 0x6e69d36f, 3 | BRF_GRA }, // 5 + { "256-c4.c4", 0x800000, 0xb755b4eb, 3 | BRF_GRA }, // 6 + { "256-c5.c5", 0x800000, 0x7aacab47, 3 | BRF_GRA }, // 7 + { "256-c6.c6", 0x800000, 0xc698fd5d, 3 | BRF_GRA }, // 8 + { "256-c7.c7", 0x800000, 0xcfceddd2, 3 | BRF_GRA }, // 9 + { "256-c8.c8", 0x800000, 0x4d9be34c, 3 | BRF_GRA }, // 10 + + { "256-m1.m1", 0x080000, 0xeaeec116, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "256-v1.v1", 0x400000, 0xf2690241, 5 | BRF_SND }, // 12 Sound data + { "256-v2.v2", 0x400000, 0x7e2a10bd, 5 | BRF_SND }, // 13 + { "256-v3.v3", 0x400000, 0x0eaec17c, 5 | BRF_SND }, // 14 + { "256-v4.v4", 0x400000, 0x9b4b22d4, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(mslug3, mslug3, neogeo) +STD_ROM_FN(mslug3) + +static void mslug3SMADecrypt() +{ + for (INT32 i = 0; i < 0x800000 / 2; i++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i] = BITSWAP16(((UINT16*)(Neo68KROMActive + 0x100000))[i], 4, 11, 14, 3, 1, 13, 0, 7, 2, 8, 12, 15, 10, 9, 5, 6); + } + + for (INT32 i = 0; i < 0x0C0000 / 2; i++) { + ((UINT16*)Neo68KROMActive)[i] = ((UINT16*)Neo68KROMActive)[0x5D0000 / 2 + BITSWAP24(i, 23, 22, 21, 20, 19, 18, 15, 2, 1, 13, 3, 0, 9, 6, 16, 4, 11, 5, 7, 12, 17, 14, 10, 8)]; + } + + for (INT32 i = 0; i < 0x800000 / 2; i += 0x010000 / 2) { + UINT16 nBuffer[0x010000 / 2]; + memcpy(nBuffer, &((UINT16*)(Neo68KROMActive + 0x100000))[i], 0x010000); + for (INT32 j = 0; j < 0x010000 / 2; j++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i + j] = nBuffer[BITSWAP24(j, 23, 22, 21, 20, 19, 18, 17, 16, 15, 2, 11, 0, 14, 6, 4, 13, 8, 9, 3, 10, 7, 5, 12, 1)]; + } + } +} + +void __fastcall mslug3WriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + +// bprintf(PRINT_NORMAL, " -- bankswitch: 0x%08X -> 0x%04X\n", sekAddress, wordValue); + + if (sekAddress == 0x2FFFE4) { + static UINT32 bankoffset[64] = { + 0x100000, 0x120000, 0x140000, 0x160000, // 00 + 0x170000, 0x190000, 0x1b0000, 0x1d0000, // 04 + 0x1e0000, 0x1f0000, 0x220000, 0x230000, // 08 + 0x240000, 0x250000, 0x280000, 0x290000, // 12 + 0x2a0000, 0x2b0000, 0x2e0000, 0x2f0000, // 16 + 0x300000, 0x310000, 0x340000, 0x350000, // 20 + 0x360000, 0x370000, 0x3a0000, 0x3b0000, // 24 + 0x3c0000, 0x3d0000, 0x400000, 0x410000, // 28 + 0x420000, 0x430000, 0x460000, 0x470000, // 32 + 0x480000, 0x490000, 0x4c0000, 0x4d0000, // 36 + 0x500000, 0x510000, 0x540000, 0x550000, // 40 + 0x560000, 0x570000, 0x5a0000, 0x5b0000, // 44 + 0x5c0000, /* rest not used? */ + }; + + // Unscramble bank number + INT32 nBank = + (((wordValue >> 14) & 1) << 0) + + (((wordValue >> 12) & 1) << 1) + + (((wordValue >> 15) & 1) << 2) + + (((wordValue >> 6) & 1) << 3) + + (((wordValue >> 3) & 1) << 4) + + (((wordValue >> 9) & 1) << 5); + + if (bankoffset[nBank] != nNeo68KROMBank) { + nNeo68KROMBank = bankoffset[nBank]; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFFFF, SM_ROM); + } + } +} + +static INT32 mslug3Init() +{ + nNeoProtectionXor = 0xAD; + + return NeoSMAInit(mslug3SMADecrypt, mslug3WriteWordBankswitch, 0, 0); +} + +struct BurnDriver BurnDrvmslug3 = { + "mslug3", NULL, "neogeo", NULL, "2000", + "Metal Slug 3 (NGM-2560)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SMA_PROTECTION, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug3RomInfo, mslug3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug3Init, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 3 (NGH-2560) + +static struct BurnRomInfo mslug3hRomDesc[] = { + { "256-ph1.p1", 0x100000, 0x9c42ca85, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "256-ph2.sp2", 0x400000, 0x1f3d8ce8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "256-c1.c1", 0x800000, 0x5a79c34e, 3 | BRF_GRA }, // 2 Sprite data + { "256-c2.c2", 0x800000, 0x944c362c, 3 | BRF_GRA }, // 3 + { "256-c3.c3", 0x800000, 0x6e69d36f, 3 | BRF_GRA }, // 4 + { "256-c4.c4", 0x800000, 0xb755b4eb, 3 | BRF_GRA }, // 5 + { "256-c5.c5", 0x800000, 0x7aacab47, 3 | BRF_GRA }, // 6 + { "256-c6.c6", 0x800000, 0xc698fd5d, 3 | BRF_GRA }, // 7 + { "256-c7.c7", 0x800000, 0xcfceddd2, 3 | BRF_GRA }, // 8 + { "256-c8.c8", 0x800000, 0x4d9be34c, 3 | BRF_GRA }, // 9 + + { "256-m1.m1", 0x080000, 0xeaeec116, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "256-v1.v1", 0x400000, 0xf2690241, 5 | BRF_SND }, // 11 Sound data + { "256-v2.v2", 0x400000, 0x7e2a10bd, 5 | BRF_SND }, // 12 + { "256-v3.v3", 0x400000, 0x0eaec17c, 5 | BRF_SND }, // 13 + { "256-v4.v4", 0x400000, 0x9b4b22d4, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(mslug3h, mslug3h, neogeo) +STD_ROM_FN(mslug3h) + +static INT32 mslug3hInit() +{ + nNeoProtectionXor = 0xAD; + + return NeoInit(); +} + +struct BurnDriver BurnDrvmslug3h = { + "mslug3h", "mslug3", "neogeo", NULL, "2000", + "Metal Slug 3 (NGH-2560)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug3hRomInfo, mslug3hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug3hInit, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 6 (Metal Slug 3 bootleg) + +static struct BurnRomInfo mslug3b6RomDesc[] = { + { "299-p1.bin", 0x200000, 0x5f2fe228, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "299-p2.bin", 0x400000, 0x193fa835, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "299-s1.bin", 0x020000, 0x6f8b9635, 2 | BRF_GRA }, // 2 Text layer tiles + + { "256-c1.c1", 0x800000, 0x5a79c34e, 3 | BRF_GRA }, // 3 Sprite data + { "256-c2.c2", 0x800000, 0x944c362c, 3 | BRF_GRA }, // 4 + { "256-c3.c3", 0x800000, 0x6e69d36f, 3 | BRF_GRA }, // 5 + { "256-c4.c4", 0x800000, 0xb755b4eb, 3 | BRF_GRA }, // 6 + { "256-c5.c5", 0x800000, 0x7aacab47, 3 | BRF_GRA }, // 7 + { "256-c6.c6", 0x800000, 0xc698fd5d, 3 | BRF_GRA }, // 8 + { "256-c7.c7", 0x800000, 0xcfceddd2, 3 | BRF_GRA }, // 9 + { "256-c8.c8", 0x800000, 0x4d9be34c, 3 | BRF_GRA }, // 10 + + { "256-m1.m1", 0x080000, 0xeaeec116, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "256-v1.v1", 0x400000, 0xf2690241, 5 | BRF_SND }, // 12 Sound data + { "256-v2.v2", 0x400000, 0x7e2a10bd, 5 | BRF_SND }, // 13 + { "256-v3.v3", 0x400000, 0x0eaec17c, 5 | BRF_SND }, // 14 + { "256-v4.v4", 0x400000, 0x9b4b22d4, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(mslug3b6, mslug3b6, neogeo) +STD_ROM_FN(mslug3b6) + +static void mslug3b6Callback() +{ + memcpy(Neo68KROMActive, Neo68KROMActive + 0x100000, 0x500000); + + garoubl_sx_decode(); +} + +static INT32 mslug3b6Init() +{ + NeoCallbackActive->pInitialise = mslug3b6Callback; + nNeoProtectionXor = 0xAD; + + return NeoInit(); +} + +struct BurnDriver BurnDrvmslug3b6 = { + "mslug3b6", "mslug3", "neogeo", NULL, "2000", + "Metal Slug 6 (Metal Slug 3 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug3b6RomInfo, mslug3b6RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug3b6Init, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2000 (NGM-2570) (NGH-2570) + +static struct BurnRomInfo kof2000RomDesc[] = { + { "neo-sma", 0x040000, 0x71c6e6bb, 9 | BRF_ESS | BRF_PRG }, // 0 68K code + { "257-p1.p1", 0x400000, 0x60947b4c, 1 | BRF_ESS | BRF_PRG }, // 1 + { "257-p2.p2", 0x400000, 0x1b7ec415, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "257-c1.c1", 0x800000, 0xcef1cdfa, 3 | BRF_GRA }, // 3 Sprite data + { "257-c2.c2", 0x800000, 0xf7bf0003, 3 | BRF_GRA }, // 4 + { "257-c3.c3", 0x800000, 0x101e6560, 3 | BRF_GRA }, // 5 + { "257-c4.c4", 0x800000, 0xbd2fc1b1, 3 | BRF_GRA }, // 6 + { "257-c5.c5", 0x800000, 0x89775412, 3 | BRF_GRA }, // 7 + { "257-c6.c6", 0x800000, 0xfa7200d5, 3 | BRF_GRA }, // 8 + { "257-c7.c7", 0x800000, 0x7da11fe4, 3 | BRF_GRA }, // 9 + { "257-c8.c8", 0x800000, 0xb1afa60b, 3 | BRF_GRA }, // 10 + + { "257-m1.m1", 0x040000, 0x4b749113, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "257-v1.v1", 0x400000, 0x17cde847, 5 | BRF_SND }, // 12 Sound data + { "257-v2.v2", 0x400000, 0x1afb20ff, 5 | BRF_SND }, // 13 + { "257-v3.v3", 0x400000, 0x4605036a, 5 | BRF_SND }, // 14 + { "257-v4.v4", 0x400000, 0x764bbd6b, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kof2000, kof2000, neogeo) +STD_ROM_FN(kof2000) + +static void kof2000SMADecrypt() +{ + for (INT32 i = 0; i < 0x800000 / 2; i++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i] = BITSWAP16(((UINT16*)(Neo68KROMActive + 0x100000))[i], 12, 8, 11, 3, 15, 14, 7, 0, 10, 13, 6, 5, 9, 2, 1, 4); + } + + for (INT32 i = 0; i < 0x0C0000 / 2; i++) { + ((UINT16*)Neo68KROMActive)[i] = ((UINT16*)Neo68KROMActive)[0x73A000 / 2 + BITSWAP24(i, 23, 22, 21, 20, 19, 18, 8, 4, 15, 13, 3, 14, 16, 2, 6, 17, 7, 12, 10, 0, 5, 11, 1, 9)]; + } + + for (INT32 i = 0; i < 0x63A000 / 2; i += 0x0800 / 2) { + UINT16 nBuffer[0x0800 / 2]; + memcpy(nBuffer, &((UINT16*)(Neo68KROMActive + 0x100000))[i], 0x0800); + for (INT32 j = 0; j < 0x0800 / 2; j++) { + ((UINT16*)(Neo68KROMActive + 0x100000))[i + j] = nBuffer[BITSWAP24(j, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 4, 1, 3, 8, 6, 2, 7, 0, 9, 5)]; + } + } +} + +void __fastcall kof2000WriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2FFFEC) { + static UINT32 bankoffset[64] = { + 0x100000, 0x200000, 0x300000, 0x400000, // 00 + 0x4f7800, 0x5f7800, 0x4ff800, 0x5ff800, // 04 + 0x507800, 0x607800, 0x50f800, 0x60f800, // 08 + 0x516800, 0x616800, 0x51d800, 0x61d800, // 12 + 0x524000, 0x624000, 0x623800, 0x723800, // 16 + 0x626000, 0x726000, 0x628000, 0x728000, // 20 + 0x62a000, 0x72a000, 0x62b800, 0x72b800, // 24 + 0x62d000, 0x72d000, 0x62e800, 0x72e800, // 28 + 0x718000, 0x719000, 0x71a000, 0x71a800, // 32 + }; + + // Unscramble bank number + INT32 nBank = + (((wordValue >> 15) & 1) << 0) + + (((wordValue >> 14) & 1) << 1) + + (((wordValue >> 7) & 1) << 2) + + (((wordValue >> 3) & 1) << 3) + + (((wordValue >> 10) & 1) << 4) + + (((wordValue >> 5) & 1) << 5); + + if (bankoffset[nBank] != nNeo68KROMBank) { + nNeo68KROMBank = bankoffset[nBank]; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FE3FF, SM_ROM); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank + 0x0FE800, 0x2FE800, 0x2FFBFF, SM_ROM); + } + } +} + +static INT32 kof2000Init() +{ + nNeoProtectionXor = 0x00; + + return NeoSMAInit(kof2000SMADecrypt, kof2000WriteWordBankswitch, 0x2FFFD8, 0x2FFFDA); +} + +struct BurnDriver BurnDrvkof2000 = { + "kof2000", NULL, "neogeo", NULL, "2000", + "The King of Fighters 2000 (NGM-2570) (NGH-2570)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_SMA_PROTECTION | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2000RomInfo, kof2000RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2000Init, NeoSMAExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2000 (not encrypted) + +static struct BurnRomInfo kof2000nRomDesc[] = { + { "257-pg1.p1", 0x100000, 0x5f809dbe, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "257-pg2.sp2", 0x400000, 0x693c2c5e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "257-c1.c1", 0x800000, 0xcef1cdfa, 3 | BRF_GRA }, // 2 Sprite data + { "257-c2.c2", 0x800000, 0xf7bf0003, 3 | BRF_GRA }, // 3 + { "257-c3.c3", 0x800000, 0x101e6560, 3 | BRF_GRA }, // 4 + { "257-c4.c4", 0x800000, 0xbd2fc1b1, 3 | BRF_GRA }, // 5 + { "257-c5.c5", 0x800000, 0x89775412, 3 | BRF_GRA }, // 6 + { "257-c6.c6", 0x800000, 0xfa7200d5, 3 | BRF_GRA }, // 7 + { "257-c7.c7", 0x800000, 0x7da11fe4, 3 | BRF_GRA }, // 8 + { "257-c8.c8", 0x800000, 0xb1afa60b, 3 | BRF_GRA }, // 9 + + { "257-m1.m1", 0x040000, 0x4b749113, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "257-v1.v1", 0x400000, 0x17cde847, 5 | BRF_SND }, // 11 Sound data + { "257-v2.v2", 0x400000, 0x1afb20ff, 5 | BRF_SND }, // 12 + { "257-v3.v3", 0x400000, 0x4605036a, 5 | BRF_SND }, // 13 + { "257-v4.v4", 0x400000, 0x764bbd6b, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof2000n, kof2000n, neogeo) +STD_ROM_FN(kof2000n) + +static INT32 kof2000nInit() +{ + nNeoProtectionXor = 0x00; + return NeoInit(); +} + +struct BurnDriver BurnDrvkof2000n = { + "kof2000n", "kof2000", "neogeo", NULL, "2000", + "The King of Fighters 2000 (not encrypted)\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2000nRomInfo, kof2000nRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2000nInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Zupapa! + +static struct BurnRomInfo zupapaRomDesc[] = { + { "070-p1.p1", 0x100000, 0x5a96203e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "070-c1.c1", 0x800000, 0xf8ad02d8, 3 | BRF_GRA }, // 1 Sprite data + { "070-c2.c2", 0x800000, 0x70156dde, 3 | BRF_GRA }, // 2 + + { "070-m1.m1", 0x020000, 0x5a3b3191, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "070-v1.v1", 0x200000, 0xd3a7e1ff, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(zupapa, zupapa, neogeo) +STD_ROM_FN(zupapa) + +static INT32 zupapaInit() +{ + nNeoProtectionXor = 0xBD; + return NeoInit(); +} + +struct BurnDriver BurnDrvZupapa = { + "zupapa", NULL, "neogeo", NULL, "2001", + "Zupapa!\0", NULL, "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_PLATFORM, 0, + NULL, zupapaRomInfo, zupapaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + zupapaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Sengoku 3 / Sengoku Densho 2001 + +static struct BurnRomInfo sengoku3RomDesc[] = { + { "261-ph1.p1", 0x200000, 0xe0d4bc0a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "261-c1.c1", 0x800000, 0xded84d9c, 3 | BRF_GRA }, // 1 Sprite data + { "261-c2.c2", 0x800000, 0xb8eb4348, 3 | BRF_GRA }, // 2 + { "261-c3.c3", 0x800000, 0x84e2034a, 3 | BRF_GRA }, // 3 + { "261-c4.c4", 0x800000, 0x0b45ae53, 3 | BRF_GRA }, // 4 + + { "261-m1.m1", 0x080000, 0x7d501c39, 4 | BRF_ESS | BRF_PRG }, // 5 Z80 code + + { "261-v1.v1", 0x400000, 0x64c30081, 5 | BRF_SND }, // 6 Sound data + { "261-v2.v2", 0x400000, 0x392a9c47, 5 | BRF_SND }, // 7 + { "261-v3.v3", 0x400000, 0xc1a7ebe3, 5 | BRF_SND }, // 8 + { "261-v4.v4", 0x200000, 0x9000d085, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(sengoku3, sengoku3, neogeo) +STD_ROM_FN(sengoku3) + +static INT32 sengoku3Init() +{ + nNeoProtectionXor = 0xFE; + return NeoInit(); +} + +struct BurnDriver BurnDrvSengoku3 = { + "sengoku3", NULL, "neogeo", NULL, "2001", + "Sengoku 3 / Sengoku Densho 2001\0", NULL, "SNK / Noise Factory", "Neo Geo MVS", + L"Sengoku 3\0\u6226\u56FD\u4F1D\u627F\uFF12\uFF10\uFF10\uFF11", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42 | HARDWARE_SNK_SWAPP, GBF_SCRFIGHT, 0, + NULL, sengoku3RomInfo, sengoku3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + sengoku3Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// The King of Fighters 2001 (NGM-262?) + +static struct BurnRomInfo kof2001RomDesc[] = { + { "262-p1-08-e0.p1", 0x100000, 0x9381750d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "262-p2-08-e0.sp2", 0x400000, 0x8e0d8329, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "262-c1-08-e0.c1", 0x800000, 0x99cc785a, 3 | BRF_GRA }, // 2 Sprite data + { "262-c2-08-e0.c2", 0x800000, 0x50368cbf, 3 | BRF_GRA }, // 3 + { "262-c3-08-e0.c3", 0x800000, 0xfb14ff87, 3 | BRF_GRA }, // 4 + { "262-c4-08-e0.c4", 0x800000, 0x4397faf8, 3 | BRF_GRA }, // 5 + { "262-c5-08-e0.c5", 0x800000, 0x91f24be4, 3 | BRF_GRA }, // 6 + { "262-c6-08-e0.c6", 0x800000, 0xa31e4403, 3 | BRF_GRA }, // 7 + { "262-c7-08-e0.c7", 0x800000, 0x54d9d1ec, 3 | BRF_GRA }, // 8 + { "262-c8-08-e0.c8", 0x800000, 0x59289a6b, 3 | BRF_GRA }, // 9 + + { "265-262-m1.m1", 0x040000, 0xa7f8119f, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "262-v1-08-e0.v1", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 11 Sound data + { "262-v2-08-e0.v2", 0x400000, 0x003f1843, 5 | BRF_SND }, // 12 + { "262-v3-08-e0.v3", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 13 + { "262-v4-08-e0.v4", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof2001, kof2001, neogeo) +STD_ROM_FN(kof2001) + +static INT32 kof2001Init() +{ + nNeoProtectionXor = 0x1E; + return NeoInit(); +} + +struct BurnDriver BurnDrvkof2001 = { + "kof2001", NULL, "neogeo", NULL, "2001", + "The King of Fighters 2001 (NGM-262?)\0", NULL, "SNK / Eolith", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2001RomInfo, kof2001RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2001Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2001 (NGH-2621) + +static struct BurnRomInfo kof2001hRomDesc[] = { + { "262-pg1.p1", 0x100000, 0x2af7e741, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "262-pg2.sp2", 0x400000, 0x91eea062, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "262-c1-08-e0.c1", 0x800000, 0x99cc785a, 3 | BRF_GRA }, // 2 Sprite data + { "262-c2-08-e0.c2", 0x800000, 0x50368cbf, 3 | BRF_GRA }, // 3 + { "262-c3-08-e0.c3", 0x800000, 0xfb14ff87, 3 | BRF_GRA }, // 4 + { "262-c4-08-e0.c4", 0x800000, 0x4397faf8, 3 | BRF_GRA }, // 5 + { "262-c5-08-e0.c5", 0x800000, 0x91f24be4, 3 | BRF_GRA }, // 6 + { "262-c6-08-e0.c6", 0x800000, 0xa31e4403, 3 | BRF_GRA }, // 7 + { "262-c7-08-e0.c7", 0x800000, 0x54d9d1ec, 3 | BRF_GRA }, // 8 + { "262-c8-08-e0.c8", 0x800000, 0x59289a6b, 3 | BRF_GRA }, // 9 + + { "265-262-m1.m1", 0x040000, 0xa7f8119f, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "262-v1-08-e0.v1", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 11 Sound data + { "262-v2-08-e0.v2", 0x400000, 0x003f1843, 5 | BRF_SND }, // 12 + { "262-v3-08-e0.v3", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 13 + { "262-v4-08-e0.v4", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof2001h, kof2001h, neogeo) +STD_ROM_FN(kof2001h) + +struct BurnDriver BurnDrvkof2001h = { + "kof2001h", "kof2001", "neogeo", NULL, "2001", + "The King of Fighters 2001 (NGH-2621)\0", NULL, "SNK / Eolith", "Neo Geo AES", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2001hRomInfo, kof2001hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2001Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Crouching Tiger Hidden Dragon 2003 (The King of Fighters 2001 bootleg) + +static struct BurnRomInfo cthd2003RomDesc[] = { + { "5003-p1.bin", 0x100000, 0xbb7602c1, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "5003-p2.bin", 0x400000, 0xadc1c22b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5003-s1.bin", 0x020000, 0x5ba29aab, 2 | BRF_GRA }, // 2 Text layer tiles + + { "5003-c1.bin", 0x800000, 0x68f54b67, 3 | BRF_GRA }, // 3 Sprite data + { "5003-c2.bin", 0x800000, 0x2f8849d5, 3 | BRF_GRA }, // 4 + { "5003-c3.bin", 0x800000, 0xac4aff71, 3 | BRF_GRA }, // 5 + { "5003-c4.bin", 0x800000, 0xafef5d66, 3 | BRF_GRA }, // 6 + { "5003-c5.bin", 0x800000, 0xc7c1ae50, 3 | BRF_GRA }, // 7 + { "5003-c6.bin", 0x800000, 0x613197f9, 3 | BRF_GRA }, // 8 + { "5003-c7.bin", 0x800000, 0x64ddfe0f, 3 | BRF_GRA }, // 9 + { "5003-c8.bin", 0x800000, 0x917a1439, 3 | BRF_GRA }, // 10 + + { "5003-m1.bin", 0x020000, 0x1a8c274b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.v1", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "262-v2-08-e0.v2", 0x400000, 0x003f1843, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.v3", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.v4", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(cthd2003, cthd2003, neogeo) +STD_ROM_FN(cthd2003) + +static void cthd2003Bankswitch(UINT32 nBank) +{ + static UINT32 cthd2003_banks[8] = { + 0x200000, 0x100000, 0x200000, 0x100000, 0x200000, 0x100000, 0x400000, 0x300000, + }; + + nBank = cthd2003_banks[nBank & 7]; + + if (nBank != nNeo68KROMBank) { + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fffff, SM_ROM); + } +} + +void __fastcall cthd2003WriteByteBankswitch(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress == 0x2ffff0) { + cthd2003Bankswitch(byteValue); + } +} + +void __fastcall cthd2003WriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2ffff0) { + cthd2003Bankswitch(wordValue); + } +} +static void cthd2003_decode() +{ + INT32 i, n; + + // fix garbage on s1 layer over everything + *((UINT16*)(Neo68KROMActive + 0xf415a)) = 0x4ef9; + *((UINT16*)(Neo68KROMActive + 0xf415c)) = 0x000f; + *((UINT16*)(Neo68KROMActive + 0xf415e)) = 0x4cf2; + + // Fix corruption in attract mode before title screen + for (i = 0x1ae290; i < 0x1ae8d0; i+=2) { + *((UINT16*)(Neo68KROMActive + i)) = 0x0000; + } + + // Fix for title page + for (i = 0x1f8ef0; i < 0x1fa1f0; i += 4) { + *((UINT16*)(Neo68KROMActive + i + 0)) -= 0x7000; + *((UINT16*)(Neo68KROMActive + i + 2)) -= 0x0010; + } + + // Fix for green dots on title page + for (i = 0xac500; i < 0xac520; i+=2) { + *((UINT16*)(Neo68KROMActive + i)) = 0xffff; + } + + // Fix for blanks as screen change level end clear + *((UINT16*)(Neo68KROMActive + 0x991d0)) = 0xdd03; + *((UINT16*)(Neo68KROMActive + 0x99306)) = 0xdd03; + *((UINT16*)(Neo68KROMActive + 0x99354)) = 0xdd03; + *((UINT16*)(Neo68KROMActive + 0x9943e)) = 0xdd03; + + // Swap bits 15 & 16 in the address of the Z80 ROM + for (i = 0; i < 0x10000 / 2; i++) { + n = NeoZ80ROMActive[0x08000 + i]; + NeoZ80ROMActive[0x08000 + i] = NeoZ80ROMActive[0x10000 + i]; + NeoZ80ROMActive[0x10000 + i] = n; + } + + DoPerm(0); +} + +static void cthd2003Callback() +{ + INT32 i, n; + for (i = 0; i < 0x8000; i++) + { + n = NeoTextROM[nNeoActiveSlot][0x08000 + i]; + NeoTextROM[nNeoActiveSlot][0x08000 + i] = NeoTextROM[nNeoActiveSlot][0x10000 + i]; + NeoTextROM[nNeoActiveSlot][0x10000 + i] = n; + } + + cthd2003_decode(); +} + +static void cthd2003InstallBankSwitchHandler() +{ + SekMapHandler(6, 0x200000, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(6, cthd2003WriteWordBankswitch); + SekSetWriteByteHandler(6, cthd2003WriteByteBankswitch); + + cthd2003Bankswitch(0); +} + +static INT32 cthd2003Init() +{ + nBurnCPUSpeedAdjust = 0x010a; + + NeoCallbackActive->pInitialise = cthd2003Callback; + NeoCallbackActive->pInstallHandlers = cthd2003InstallBankSwitchHandler; + NeoCallbackActive->pBankswitch = NeoMapBank; + + return NeoInit(); +} + +struct BurnDriver BurnDrvcthd2003 = { + "cthd2003", "kof2001", "neogeo", NULL, "2003", + "Crouching Tiger Hidden Dragon 2003 (The King of Fighters 2001 bootleg)\0", "Hack of \"The King of Fighters 2001\"", "Phenixsoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, cthd2003RomInfo, cthd2003RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + cthd2003Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Crouching Tiger Hidden Dragon 2003 Super Plus (The King of Fighters 2001 bootleg) + +static struct BurnRomInfo ct2k3spRomDesc[] = { + { "5003-p1sp.bin", 0x100000, 0xab5c4de0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "5003-p2.bin", 0x400000, 0xadc1c22b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5003-s1sp.bin", 0x040000, 0x6c355ab4, 2 | BRF_GRA }, // 2 Text layer tiles + + { "5003-c1.bin", 0x800000, 0x68f54b67, 3 | BRF_GRA }, // 3 Sprite data + { "5003-c2.bin", 0x800000, 0x2f8849d5, 3 | BRF_GRA }, // 4 + { "5003-c3.bin", 0x800000, 0xac4aff71, 3 | BRF_GRA }, // 5 + { "5003-c4.bin", 0x800000, 0xafef5d66, 3 | BRF_GRA }, // 6 + { "5003-c5.bin", 0x800000, 0xc7c1ae50, 3 | BRF_GRA }, // 7 + { "5003-c6.bin", 0x800000, 0x613197f9, 3 | BRF_GRA }, // 8 + { "5003-c7.bin", 0x800000, 0x64ddfe0f, 3 | BRF_GRA }, // 9 + { "5003-c8.bin", 0x800000, 0x917a1439, 3 | BRF_GRA }, // 10 + + { "5003-m1.bin", 0x020000, 0x1a8c274b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.v1", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "262-v2-08-e0.v2", 0x400000, 0x003f1843, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.v3", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.v4", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(ct2k3sp, ct2k3sp, neogeo) +STD_ROM_FN(ct2k3sp) + +static void ct2k3spCallback() +{ + INT32 i, j; + UINT8 *dst = (UINT8 *)malloc( 0x040000 ); + if (dst) + { + for (i = 0; i < 0x040000; i++) + { + j = BITSWAP24(i, 23,22,21,20,19,18,17,3,0,1,4,2,13,14,15,16,5,6,11,10,9,8,7,12); + dst[i] = NeoTextROM[nNeoActiveSlot][j]; + } + + memcpy (NeoTextROM[nNeoActiveSlot], dst, 0x040000 ); + + free (dst); + dst = NULL; + } + + cthd2003_decode(); +} + +static void ct2kspInstallBankSwitchHandler() +{ + SekMapHandler(6, 0x200000, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(6, cthd2003WriteWordBankswitch); + SekSetWriteByteHandler(6, cthd2003WriteByteBankswitch); + + cthd2003Bankswitch(0); +} + +static INT32 ct2k3spInit() +{ + nBurnCPUSpeedAdjust = 0x010a; + + NeoCallbackActive->pInitialise = ct2k3spCallback; + NeoCallbackActive->pInstallHandlers = ct2kspInstallBankSwitchHandler; + NeoCallbackActive->pBankswitch = NeoMapBank; + + return NeoInit(); +} + +struct BurnDriver BurnDrvct2k3sp = { + "ct2k3sp", "kof2001", "neogeo", NULL, "2003", + "Crouching Tiger Hidden Dragon 2003 Super Plus (The King of Fighters 2001 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + L"Crouching Tiger Hidden Dragon 2003 Super Plus (The King of Fighters 2001 bootleg)\0\u81E5\u864E\u85CF\u9F8D Crouching Tiger Hidden Dragon 2003 Super Plus\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, ct2k3spRomInfo, ct2k3spRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + ct2k3spInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Crouching Tiger Hidden Dragon 2003 Super Plus alternate (The King of Fighters 2001 bootleg) + +static struct BurnRomInfo ct2k3saRomDesc[] = { + { "5003-p1sa.bin", 0x100000, 0x013a509d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "5003-p2.bin", 0x400000, 0xadc1c22b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5003-s1sa.bin", 0x020000, 0x4e1f7eae, 2 | BRF_GRA }, // 2 Text layer tiles + + { "5003-c1.bin", 0x800000, 0x68f54b67, 3 | BRF_GRA }, // 3 Sprite data + { "5003-c2.bin", 0x800000, 0x2f8849d5, 3 | BRF_GRA }, // 4 + { "5003-c3.bin", 0x800000, 0xac4aff71, 3 | BRF_GRA }, // 5 + { "5003-c4.bin", 0x800000, 0xafef5d66, 3 | BRF_GRA }, // 6 + { "5003-c5.bin", 0x800000, 0xc7c1ae50, 3 | BRF_GRA }, // 7 + { "5003-c6.bin", 0x800000, 0x613197f9, 3 | BRF_GRA }, // 8 + { "5003-c7.bin", 0x800000, 0x64ddfe0f, 3 | BRF_GRA }, // 9 + { "5003-c8.bin", 0x800000, 0x917a1439, 3 | BRF_GRA }, // 10 + + { "5003-m1.bin", 0x020000, 0x1a8c274b, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.v1", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "262-v2-08-e0.v2", 0x400000, 0x003f1843, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.v3", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.v4", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(ct2k3sa, ct2k3sa, neogeo) +STD_ROM_FN(ct2k3sa) + +static INT32 ct2k3saInit() +{ + nBurnCPUSpeedAdjust = 0x010d; + NeoCallbackActive->pInitialise = cthd2003_decode; + return NeoInit(); +} + +struct BurnDriver BurnDrvct2k3sa = { + "ct2k3sa", "kof2001", "neogeo", NULL, "2003", + "Crouching Tiger Hidden Dragon 2003 Super Plus alternate (The King of Fighters 2001 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + L"Crouching Tiger Hidden Dragon 2003 Super Plus alternate (The King of Fighters 2001 bootleg)\0\u81E5\u864E\u85CF\u9F8D Crouching Tiger Hidden Dragon 2003 Super Plus\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, ct2k3saRomInfo, ct2k3saRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + ct2k3saInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 (NGM-2650)(NGH-2650) + +static struct BurnRomInfo kof2002RomDesc[] = { + { "265-p1.p1", 0x100000, 0x9ede7323, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265-p2.sp2", 0x400000, 0x327266b8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "265-c1.c1", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 2 Sprite data + { "265-c2.c2", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 3 + { "265-c3.c3", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 4 + { "265-c4.c4", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 5 + { "265-c5.c5", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 6 + { "265-c6.c6", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 7 + { "265-c7.c7", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 8 + { "265-c8.c8", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 9 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 11 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof2002, kof2002, neogeo) +STD_ROM_FN(kof2002) + +static INT32 kof2002Init() +{ + INT32 nRet; + + nNeoProtectionXor = 0xEC; + NeoCallbackActive->pInitialise = PCM2DecryptP; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkof2002 = { + "kof2002", NULL, "neogeo", NULL, "2002", + "The King of Fighters 2002 (NGM-2650)(NGH-2650)\0", NULL, "Eolith / Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2002RomInfo, kof2002RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2002Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 (bootleg) + +static struct BurnRomInfo kof2002bRomDesc[] = { + { "265-p1.p1", 0x100000, 0x9ede7323, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "2k2-p2.bin", 0x400000, 0x6dbee4df, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k2-s1.bin", 0x020000, 0x2255f5bf, 2 | BRF_GRA }, // 2 Text data + + { "2k2-c1.bin", 0x800000, 0xf25d3d66, 3 | BRF_GRA }, // 3 Sprite data + { "2k2-c2.bin", 0x800000, 0xe3e66f1d, 3 | BRF_GRA }, // 4 + { "2k2-c3.bin", 0x800000, 0x8732fa30, 3 | BRF_GRA }, // 5 + { "2k2-c4.bin", 0x800000, 0x0989fd40, 3 | BRF_GRA }, // 6 + { "2k2-c5.bin", 0x800000, 0x60635cd2, 3 | BRF_GRA }, // 7 + { "2k2-c6.bin", 0x800000, 0xbd736824, 3 | BRF_GRA }, // 8 + { "2k2-c7.bin", 0x800000, 0x2da8d8cf, 3 | BRF_GRA }, // 9 + { "2k2-c8.bin", 0x800000, 0x2048404a, 3 | BRF_GRA }, // 10 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof2002b, kof2002b, neogeo) +STD_ROM_FN(kof2002b) + +void kof2002b_gfx_decrypt(UINT8 *src, INT32 nLen) +{ + INT32 i, j, k, *m; + INT32 tbl[8][6] = { + { 1, 2, 6, 7, 8, 0 }, + { 2, 6, 7, 8, 0, 1 }, + { 6, 7, 8, 0, 1, 2 }, + { 7, 8, 0, 1, 2, 6 }, + { 8, 0, 1, 2, 6, 7 }, + { 8, 7, 6, 2, 1, 0 }, + { 8, 7, 6, 0, 1, 2 }, + { 1, 2, 6, 7, 0, 8 } + }; + + UINT8 dst[0x10000]; + + for (i = 0; i < nLen; i+= 0x10000) + { + memcpy (dst, src + i, 0x10000); + + for (j = 0; j < 0x10000 / 0x80; j++) + { + m = tbl[(j >> 3) & 7]; + k = BITSWAP16(j, 15, 14, 13, 12, 11, 10, 9, m[5], m[4], m[3], 5, 4, 3, m[2], m[1], m[0]); + memcpy (src + i + k * 0x80, dst + j * 0x80, 0x80); + } + } +} + +static void kof2002bCallback() +{ + PCM2DecryptP(); + kof2002b_gfx_decrypt(NeoSpriteROM[nNeoActiveSlot], 0x4000000); + kof2002b_gfx_decrypt(NeoTextROM[nNeoActiveSlot], 0x020000); +} + +static INT32 kof2002bInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = kof2002bCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkof2002b = { + "kof2002b", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2002bRomInfo, kof2002bRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2002bInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 Plus (bootleg set 1) + +static struct BurnRomInfo kf2k2plsRomDesc[] = { + { "2k2-p1p.bin", 0x100000, 0x3ab03781, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265-p2.sp2", 0x400000, 0x327266b8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k2-s1p.bin", 0x020000, 0x595e0006, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.c1", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.c2", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.c3", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.c4", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.c5", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.c6", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.c7", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.c8", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2pls, kf2k2pls, neogeo) +STD_ROM_FN(kf2k2pls) + +struct BurnDriver BurnDrvkf2k2pls = { + "kf2k2pls", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Plus (bootleg set 1)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2plsRomInfo, kf2k2plsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2002Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// The King of Fighters 2002 Plus (bootleg set 2) + +static struct BurnRomInfo kf2k2plaRomDesc[] = { + { "2k2-p1pa.bin", 0x100000, 0x6a3a02f3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265-p2.sp2", 0x400000, 0x327266b8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k2-s1pa.bin", 0x020000, 0x1a3ed064, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.c1", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.c2", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.c3", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.c4", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.c5", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.c6", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.c7", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.c8", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2pla, kf2k2pla, neogeo) +STD_ROM_FN(kf2k2pla) + +struct BurnDriver BurnDrvkf2k2pla = { + "kf2k2pla", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Plus (bootleg set 2)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2plaRomInfo, kf2k2plaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2002Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 Magic Plus (bootleg) + +static struct BurnRomInfo kf2k2mpRomDesc[] = { + { "kf02m-p1.bin", 0x400000, 0xff7c6ec0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "kf02m-p2.bin", 0x400000, 0x91584716, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "kf02m-s1.bin", 0x020000, 0x348d6f2c, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.c1", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.c2", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.c3", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.c4", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.c5", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.c6", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.c7", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.c8", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2mp, kf2k2mp, neogeo) +STD_ROM_FN(kf2k2mp) + +static void kf2k2mpCallback() +{ + INT32 i, j; + for (i = 0; i < 0x500000; i++) + { + j = (i & 0xffff00) + BITSWAP08(i, 7, 3, 4, 5, 6, 1, 2, 0); + Neo68KROMActive[i] = Neo68KROMActive[0x300000 + j]; + } + + garoubl_sx_decode(); +} + +static INT32 kf2k2mpInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0xEC; + NeoCallbackActive->pInitialise = kf2k2mpCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k2mp = { + "kf2k2mp", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Magic Plus (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2mpRomInfo, kf2k2mpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k2mpInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// The King of Fighters 2002 Magic Plus II (bootleg) + +static struct BurnRomInfo kf2k2mp2RomDesc[] = { + { "k2k2m2p1.bin", 0x200000, 0x1016806c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "k2k2m2p2.bin", 0x400000, 0x432fdf53, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "k2k2m2s1.bin", 0x020000, 0x446e74c5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.c1", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.c2", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.c3", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.c4", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.c5", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.c6", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.c7", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.c8", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.m1", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.v1", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.v2", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2mp2, kf2k2mp2, neogeo) +STD_ROM_FN(kf2k2mp2) + +static void kf2k2mp2Callback() +{ + memcpy (Neo68KROMActive + 0x000000, Neo68KROMActive + 0x1c0000, 0x040000); + memcpy (Neo68KROMActive + 0x0c0000, Neo68KROMActive + 0x100000, 0x040000); + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive + 0x200000, 0x400000); + + lans2004_sx_decode(); +} + +static INT32 kof2km2Init() +{ + INT32 nRet; + + nNeoProtectionXor = 0xEC; + NeoCallbackActive->pInitialise = kf2k2mp2Callback; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k2mp2 = { + "kf2k2mp2", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Magic Plus II (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2mp2RomInfo, kf2k2mp2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2km2Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 10th Anniversary (The King of Fighters 2002 bootleg) + +static struct BurnRomInfo kof10thRomDesc[] = { + { "kf10-p1.bin", 0x800000, 0xb1fd0c43, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "kf10-c1a.bin", 0x400000, 0x3bbc0364, 3 | BRF_GRA }, // 1 Sprite data + { "kf10-c2a.bin", 0x400000, 0x91230075, 3 | BRF_GRA }, // 2 + { "kf10-c1b.bin", 0x400000, 0xb5abfc28, 3 | BRF_GRA }, // 3 + { "kf10-c2b.bin", 0x400000, 0x6cc4c6e1, 3 | BRF_GRA }, // 4 + { "kf10-c3a.bin", 0x400000, 0x5b3d4a16, 3 | BRF_GRA }, // 5 + { "kf10-c4a.bin", 0x400000, 0xc6f3419b, 3 | BRF_GRA }, // 6 + { "kf10-c3b.bin", 0x400000, 0x9d2bba19, 3 | BRF_GRA }, // 7 + { "kf10-c4b.bin", 0x400000, 0x5a4050cb, 3 | BRF_GRA }, // 8 + { "kf10-c5a.bin", 0x400000, 0xa289d1e1, 3 | BRF_GRA }, // 9 + { "kf10-c6a.bin", 0x400000, 0xe6494b5d, 3 | BRF_GRA }, // 10 + { "kf10-c5b.bin", 0x400000, 0x404fff02, 3 | BRF_GRA }, // 11 + { "kf10-c6b.bin", 0x400000, 0xf2ccfc9e, 3 | BRF_GRA }, // 12 + { "kf10-c7a.bin", 0x400000, 0xbe79c5a8, 3 | BRF_GRA }, // 13 + { "kf10-c8a.bin", 0x400000, 0xa5952ca4, 3 | BRF_GRA }, // 14 + { "kf10-c7b.bin", 0x400000, 0x3fdb3542, 3 | BRF_GRA }, // 15 + { "kf10-c8b.bin", 0x400000, 0x661b7a52, 3 | BRF_GRA }, // 16 + + { "kf10-m1.bin", 0x020000, 0xf6fab859, 4 | BRF_ESS | BRF_PRG }, // 17 Z80 code + + { "kf10-v1.bin", 0x800000, 0x0fc9a58d, 5 | BRF_SND }, // 18 Sound data + { "kf10-v2.bin", 0x800000, 0xb8c475a4, 5 | BRF_SND }, // 19 +}; + +STDROMPICKEXT(kof10th, kof10th, neogeo) +STD_ROM_FN(kof10th) + +static UINT8* kof10thExtraRAMA, *kof10thExtraRAMB; + +static void kof10thBankswitch(UINT32 nBank) +{ + nBank = 0x100000 + ((nBank & 7) << 20); + if (nBank >= 0x700000) { + nBank = 0x100000; + } + + if (nBank != nNeo68KROMBank) { + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); + } +} + +// Text data extraction, game does this on the fly! +void __fastcall kof10thWriteWordCustom(UINT32 sekAddress, UINT16 wordValue) +{ + if (kof10thExtraRAMB[0x1ffc]) { + NeoUpdateTextOne(((sekAddress >> 1) & 0x1ffff), BITSWAP08(wordValue, 3, 2, 1, 5, 7, 6, 0, 4)); + } else { + *(UINT16*)(kof10thExtraRAMA + (sekAddress & 0x1fffe)) = wordValue; + } +} + +// 68K Bankswitch and RAM Handlers +void __fastcall kof10thWriteByteBankswitch(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress ^= 1; + if (sekAddress == 0x2ffff0) + kof10thBankswitch(byteValue); + + kof10thExtraRAMB[sekAddress & 0x1fff] = byteValue; +} + +void __fastcall kof10thWriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress == 0x2ffff0) + kof10thBankswitch(wordValue); + else if (sekAddress == 0x2ffff8 && *(UINT16*)(kof10thExtraRAMB + 0x1ff8) != wordValue) + SekMapMemory(Neo68KROMActive + ((wordValue & 1) ? 0x710000 : 0x010000) , 0x010000, 0x0dffff, SM_ROM); + + *(UINT16*)(kof10thExtraRAMB + (sekAddress & 0x01ffe)) = wordValue; +} + +static void kof10thCallback() +{ + INT32 i, j, k; + UINT8 *dst = (UINT8*)malloc(0x100000); + if (dst) + { + for (i = 0; i < 0x800000; i+=0x100000) + { + for (j = 0; j < 0x100000; j++) + { + k = BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,13,12,11,2,9,8,7,1,5,4,3,10,6,0); + dst[k] = Neo68KROMActive[i + j]; + } + memcpy (Neo68KROMActive + i, dst, 0x100000); + } + + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x700000); + memcpy (Neo68KROMActive, dst, 0x100000); + free (dst); + dst = NULL; + } + + // Altera protection chip patches these over P ROM + *((UINT16 *)(Neo68KROMActive + 0x0124)) = 0x000d; // Enables XOR for RAM moves, forces SoftDIPs, and USA region + *((UINT16 *)(Neo68KROMActive + 0x0126)) = 0xf7a8; + + *((UINT16 *)(Neo68KROMActive + 0x8bf4)) = 0x4ef9; // Run code to change "S" data + *((UINT16 *)(Neo68KROMActive + 0x8bf6)) = 0x000d; + *((UINT16 *)(Neo68KROMActive + 0x8bf8)) = 0xf980; +} + +static void kof10thMapBank() +{ + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); +} + +static INT32 kof10thScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029713; + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = kof10thExtraRAMA; + ba.nLen = 0x00020000; + ba.nAddress = 0; + ba.szName = "Extra RAM A"; + BurnAcb(&ba); + + ba.Data = kof10thExtraRAMB; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Extra RAM B"; + BurnAcb(&ba); + } + return 0; +} + +static void kof10thInstallHandlers() +{ + // Install RAM handlers + SekMapMemory(kof10thExtraRAMA, 0x0e0000, 0x0fffff, SM_ROM); // Text RAM on range 0x0e0000 - 0x0fffff + SekMapMemory(kof10thExtraRAMB, 0x2fe000, 0x2fffff, SM_ROM); // Extra 68K RAM + + // Install bankswitch and text handlers + SekMapHandler(6, 0x2fe000, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(6, kof10thWriteWordBankswitch); + SekSetWriteByteHandler(6, kof10thWriteByteBankswitch); + + SekMapHandler(7, 0x200000, 0x23ffff, SM_WRITE); + SekSetWriteWordHandler(7, kof10thWriteWordCustom); + + // Set bank + nNeo68KROMBank = 1; + kof10thBankswitch(0); +} + +static INT32 kof10thInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = kof10thCallback; + NeoCallbackActive->pInstallHandlers = kof10thInstallHandlers; + NeoCallbackActive->pBankswitch = kof10thMapBank; + NeoCallbackActive->pScan = kof10thScan; + + nNeoTextROMSize[nNeoActiveSlot] = 0x20000; + + nRet = NeoInit(); + + if (nRet == 0) { + kof10thExtraRAMA = Neo68KROMActive + 0x7e0000; + kof10thExtraRAMB = Neo68KROMActive + 0x1fe000; + memset(kof10thExtraRAMA, 0, 0x20000); + memset(kof10thExtraRAMB, 0, 0x02000); + } + + return nRet; +} + +struct BurnDriver BurnDrvkof10th = { + "kof10th", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 10th Anniversary (The King of Fighters 2002 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof10thRomInfo, kof10thRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof10thInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 10th Anniversary Extra Plus (The King of Fighters 2002 bootleg) + +static struct BurnRomInfo kf10thepRomDesc[] = { + { "5008-p1.bin", 0x200000, 0xbf5469ba, 1 | BRF_PRG | BRF_OPT }, // 0 68K code + { "5008-p2.bin", 0x400000, 0xa649ec38, 1 | BRF_ESS | BRF_PRG }, // 1 + { "5008-p3.bin", 0x200000, 0xe629e13c, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "5008-s1.bin", 0x020000, 0x92410064, 2 | BRF_GRA }, // 3 Text layer tiles + + { "kf10-c1a.bin", 0x400000, 0x3bbc0364, 3 | BRF_GRA }, // 4 Sprite data + { "kf10-c2a.bin", 0x400000, 0x91230075, 3 | BRF_GRA }, // 5 + { "kf10-c1b.bin", 0x400000, 0xb5abfc28, 3 | BRF_GRA }, // 6 + { "kf10-c2b.bin", 0x400000, 0x6cc4c6e1, 3 | BRF_GRA }, // 7 + { "kf10-c3a.bin", 0x400000, 0x5b3d4a16, 3 | BRF_GRA }, // 8 + { "kf10-c4a.bin", 0x400000, 0xc6f3419b, 3 | BRF_GRA }, // 9 + { "kf10-c3b.bin", 0x400000, 0x9d2bba19, 3 | BRF_GRA }, // 10 + { "kf10-c4b.bin", 0x400000, 0x5a4050cb, 3 | BRF_GRA }, // 11 + { "kf10-c5a.bin", 0x400000, 0xa289d1e1, 3 | BRF_GRA }, // 12 + { "kf10-c6a.bin", 0x400000, 0xe6494b5d, 3 | BRF_GRA }, // 13 + { "kf10-c5b.bin", 0x400000, 0x404fff02, 3 | BRF_GRA }, // 14 + { "kf10-c6b.bin", 0x400000, 0xf2ccfc9e, 3 | BRF_GRA }, // 15 + { "kf10-c7a.bin", 0x400000, 0xbe79c5a8, 3 | BRF_GRA }, // 16 + { "kf10-c8a.bin", 0x400000, 0xa5952ca4, 3 | BRF_GRA }, // 17 + { "5008-c7b.bin", 0x400000, 0x33604ef0, 3 | BRF_GRA }, // 18 + { "5008-c8b.bin", 0x400000, 0x51f6a8f8, 3 | BRF_GRA }, // 19 + + { "5008-m1.bin", 0x020000, 0x5a47d9ad, 4 | BRF_ESS | BRF_PRG }, // 20 Z80 code + + { "kf10-v1.bin", 0x800000, 0x0fc9a58d, 5 | BRF_SND }, // 21 Sound data + { "kf10-v2.bin", 0x800000, 0xb8c475a4, 5 | BRF_SND }, // 22 +}; + +STDROMPICKEXT(kf10thep, kf10thep, neogeo) +STD_ROM_FN(kf10thep) + +static void kf10thepCallback() +{ + INT32 i; + UINT8 *dst = (UINT8*)malloc(0x100000); + if (dst) + { + UINT32 sec[8] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD }; + + for (i = 0; i < 8; i++) + memcpy (dst + i * 0x20000, Neo68KROMActive + sec[i] * 0x20000, 0x20000); + + memcpy (dst + 0x0002e0, Neo68KROMActive + 0x0402e0, 0x06a); + memcpy (dst + 0x0f92bc, Neo68KROMActive + 0x0492bc, 0xb9e); + memcpy (Neo68KROMActive, dst, 0x100000); + free (dst); + dst = NULL; + } + + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive + 0x200000, 0x600000); + + for (i = 0xf92bc; i < 0xf9e58; i += 2) + { + if ((*((UINT16*)(Neo68KROMActive + i + 0)) & 0xffbf) == 0x4eb9 && *((UINT16*)(Neo68KROMActive + i + 2)) == 0x0000) + { + *((UINT16*)(Neo68KROMActive + i + 2)) = 0x000f; + } + } + + *((UINT16 *)(Neo68KROMActive + 0x00342)) = 0x000f; + + lans2004_sx_decode(); +} + +static INT32 kf10thepInit() +{ + NeoCallbackActive->pInitialise = kf10thepCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkf10thep = { + "kf10thep", "kof2002", "neogeo", NULL, "2005", + "The King of Fighters 10th Anniversary Extra Plus (The King of Fighters 2002 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kf10thepRomInfo, kf10thepRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf10thepInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 10th Anniversary 2005 Unique (The King of Fighters 2002 bootleg) + +static struct BurnRomInfo kf2k5uniRomDesc[] = { + { "5006-p2a.bin", 0x400000, 0xced883a2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "5006-p1.bin", 0x400000, 0x72c39c46, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5006-s1.bin", 0x020000, 0x91f8c544, 2 | BRF_GRA }, // 2 Text layer tiles + + { "kf10-c1a.bin", 0x400000, 0x3bbc0364, 3 | BRF_GRA }, // 3 Sprite data + { "kf10-c2a.bin", 0x400000, 0x91230075, 3 | BRF_GRA }, // 4 + { "kf10-c1b.bin", 0x400000, 0xb5abfc28, 3 | BRF_GRA }, // 5 + { "kf10-c2b.bin", 0x400000, 0x6cc4c6e1, 3 | BRF_GRA }, // 6 + { "kf10-c3a.bin", 0x400000, 0x5b3d4a16, 3 | BRF_GRA }, // 7 + { "kf10-c4a.bin", 0x400000, 0xc6f3419b, 3 | BRF_GRA }, // 8 + { "kf10-c3b.bin", 0x400000, 0x9d2bba19, 3 | BRF_GRA }, // 9 + { "kf10-c4b.bin", 0x400000, 0x5a4050cb, 3 | BRF_GRA }, // 10 + { "kf10-c5a.bin", 0x400000, 0xa289d1e1, 3 | BRF_GRA }, // 11 + { "kf10-c6a.bin", 0x400000, 0xe6494b5d, 3 | BRF_GRA }, // 12 + { "kf10-c5b.bin", 0x400000, 0x404fff02, 3 | BRF_GRA }, // 13 + { "kf10-c6b.bin", 0x400000, 0xf2ccfc9e, 3 | BRF_GRA }, // 14 + { "kf10-c7a.bin", 0x400000, 0xbe79c5a8, 3 | BRF_GRA }, // 15 + { "kf10-c8a.bin", 0x400000, 0xa5952ca4, 3 | BRF_GRA }, // 16 + { "kf10-c7b.bin", 0x400000, 0x3fdb3542, 3 | BRF_GRA }, // 17 + { "kf10-c8b.bin", 0x400000, 0x661b7a52, 3 | BRF_GRA }, // 18 + + { "5006-m1.bin", 0x020000, 0x9050bfe7, 4 | BRF_ESS | BRF_PRG }, // 19 Z80 code + + { "kf10-v1.bin", 0x800000, 0x0fc9a58d, 5 | BRF_SND }, // 20 Sound data + { "kf10-v2.bin", 0x800000, 0xb8c475a4, 5 | BRF_SND }, // 21 +}; + +STDROMPICKEXT(kf2k5uni, kf2k5uni, neogeo) +STD_ROM_FN(kf2k5uni) + +static void kf2k5uniCallback() +{ + INT32 i, j, k; + UINT8 dst[0x80]; + + for (i = 0; i < 0x800000; i+=0x80) + { + for (j = 0; j < 0x80; j++) + { + k = BITSWAP08(j, 7, 3, 4, 5, 6, 1, 2, 0); + dst[j] = Neo68KROMActive[i + k]; + } + memcpy (Neo68KROMActive + i, dst, 0x80); + } + + memcpy(Neo68KROMActive, Neo68KROMActive + 0x600000, 0x100000); + + for (i = 0; i < 0x30000; i++) + NeoZ80ROMActive[i] = BITSWAP08(NeoZ80ROMActive[i], 4, 5, 6, 7, 0, 1, 2, 3); + + for (i = 0; i < 0x20000; i++) + NeoTextROM[nNeoActiveSlot][i] = BITSWAP08(NeoTextROM[nNeoActiveSlot][i], 4, 5, 6, 7, 0, 1, 2, 3); +} + +static INT32 kf2k5uniInit() +{ + NeoCallbackActive->pInitialise = kf2k5uniCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkf2k5uni = { + "kf2k5uni", "kof2002", "neogeo", NULL, "2004", + "The King of Fighters 10th Anniversary 2005 Unique (The King of Fighters 2002 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k5uniRomInfo, kf2k5uniRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k5uniInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters Special Edition 2004 (The King of Fighters 2002 bootleg) + +static struct BurnRomInfo kof2k4seRomDesc[] = { + { "k2k4s-p1.bin", 0x400000, 0xe6c50566, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "k2k4s-p2.bin", 0x080000, 0x21a84084, 1 | BRF_ESS | BRF_PRG }, // 1 + { "k2k4s-p3.bin", 0x080000, 0xfebb484e, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "k2k4s-s1.bin", 0x020000, 0xa3c9b2d8, 2 | BRF_GRA }, // 3 Text layer tiles + + { "k2k4s-c4.bin", 0x800000, 0x7a050288, 3 | BRF_GRA }, // 4 Sprite data + { "k2k4s-c8.bin", 0x800000, 0xe924afcf, 3 | BRF_GRA }, // 5 + { "k2k4s-c3.bin", 0x800000, 0x959fad0b, 3 | BRF_GRA }, // 6 + { "k2k4s-c7.bin", 0x800000, 0xefe6a468, 3 | BRF_GRA }, // 7 + { "k2k4s-c2.bin", 0x800000, 0x74bba7c6, 3 | BRF_GRA }, // 8 + { "k2k4s-c6.bin", 0x800000, 0xe20d2216, 3 | BRF_GRA }, // 9 + { "k2k4s-c1.bin", 0x800000, 0xfa705b2b, 3 | BRF_GRA }, // 10 + { "k2k4s-c5.bin", 0x800000, 0x2c912ff9, 3 | BRF_GRA }, // 11 + + { "k2k4s-m1.bin", 0x020000, 0x5a47d9ad, 4 | BRF_ESS | BRF_PRG }, // 12 Z80 code + + { "k2k4s-v2.bin", 0x800000, 0xe4ddfb3f, 5 | BRF_SND }, // 13 Sound data + { "k2k4s-v1.bin", 0x800000, 0xb887d287, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(kof2k4se, kof2k4se, neogeo) +STD_ROM_FN(kof2k4se) + +static void kof2k4seCallback() +{ + UINT8 *dst = (UINT8*)malloc(0x100000); + + if (dst) + { + memcpy (dst, Neo68KROMActive + 0x000000, 0x100000); + memcpy (Neo68KROMActive + 0x000000, Neo68KROMActive + 0x400000, 0x100000); + memcpy (Neo68KROMActive + 0x400000, dst, 0x100000); + memcpy (dst, Neo68KROMActive + 0x100000, 0x100000); + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive + 0x300000, 0x100000); + memcpy (Neo68KROMActive + 0x300000, dst, 0x100000); + + free (dst); + dst = NULL; + } +} + +static INT32 kof2k4seInit() +{ + NeoCallbackActive->pInitialise = kof2k4seCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkof2k4se = { + "kof2k4se", "kof2002", "neogeo", NULL, "2004", + "The King of Fighters Special Edition 2004 (The King of Fighters 2002 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof2k4seRomInfo, kof2k4seRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2k4seInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 5 (NGM-2680) + +static struct BurnRomInfo mslug5RomDesc[] = { + { "268-p1cr.p1", 0x400000, 0xd0466792, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "268-p2cr.p2", 0x400000, 0xfbf6b61e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "268-c1c.c1", 0x800000, 0xab7c389a, 3 | BRF_GRA }, // 2 Sprite data + { "268-c2c.c2", 0x800000, 0x3560881b, 3 | BRF_GRA }, // 3 + { "268-c3c.c3", 0x800000, 0x3af955ea, 3 | BRF_GRA }, // 4 + { "268-c4c.c4", 0x800000, 0xc329c373, 3 | BRF_GRA }, // 5 + { "268-c5c.c5", 0x800000, 0x959c8177, 3 | BRF_GRA }, // 6 + { "268-c6c.c6", 0x800000, 0x010a831b, 3 | BRF_GRA }, // 7 + { "268-c7c.c7", 0x800000, 0x6d72a969, 3 | BRF_GRA }, // 8 + { "268-c8c.c8", 0x800000, 0x551d720e, 3 | BRF_GRA }, // 9 + + { "268-m1.m1", 0x080000, 0x4a5a6e0e, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "268-v1c.v1", 0x800000, 0xae31d60c, 5 | BRF_SND }, // 11 Sound data + { "268-v2c.v2", 0x800000, 0xc40613ed, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(mslug5, mslug5, neogeo) +STD_ROM_FN(mslug5) + +static void mslug5Callback() +{ + INT32 i, j, k; + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[i] ^= Neo68KROMActive[0x0fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x700000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x7fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x0500000; i += 4) + { + UINT16 rom16 = *((UINT16 *)(Neo68KROMActive + i + 1)); + rom16 = BITSWAP16(rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0); + *((UINT16 *)(Neo68KROMActive + i + 1)) = rom16; + } + + memcpy (Neo68KROMActive + 0x700000, Neo68KROMActive, 0x100000); + + for (i = 0; i < 0x100000 / 0x010000; i++) + { + j = BITSWAP08(i, 7, 6, 5, 4, 1, 0, 3, 2) * 0x010000; + memcpy (Neo68KROMActive + i * 0x010000, Neo68KROMActive + 0x700000 + j, 0x010000); + } + + for (i = 0x100000; i < 0x700000; i += 0x100000) + { + for (j = 0; j < 0x100000; j+=0x100) + { + k = ((j & 0xf00) ^ 0x700) + (BITSWAP08((j >> 12), 5, 4, 7, 6, 1, 0, 3, 2 ) << 12); + memcpy (Neo68KROMActive + 0x700000 + j, Neo68KROMActive + i + k, 0x100); + } + + memcpy (Neo68KROMActive + i, Neo68KROMActive + 0x700000, 0x100000); + } +} + +static INT32 mslug5Init() +{ + INT32 nRet; + + nNeoProtectionXor = 0x19; + NeoCallbackActive->pInitialise = mslug5Callback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0x4e001, 0xfe2cf6, { 0xc3, 0xfd, 0x81, 0xac, 0x6d, 0xe7, 0xbf, 0x9e } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvmslug5 = { + "mslug5", NULL, "neogeo", NULL, "2003", + "Metal Slug 5 (NGM-2680)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug5RomInfo, mslug5RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug5Init, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Metal Slug 5 (NGH-2680) + +static struct BurnRomInfo mslug5hRomDesc[] = { + { "268-p1c.p1", 0x400000, 0x3636690a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "268-p2c.p2", 0x400000, 0x8dfc47a2, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "268-c1c.c1", 0x800000, 0xab7c389a, 3 | BRF_GRA }, // 2 Sprite data + { "268-c2c.c2", 0x800000, 0x3560881b, 3 | BRF_GRA }, // 3 + { "268-c3c.c3", 0x800000, 0x3af955ea, 3 | BRF_GRA }, // 4 + { "268-c4c.c4", 0x800000, 0xc329c373, 3 | BRF_GRA }, // 5 + { "268-c5c.c5", 0x800000, 0x959c8177, 3 | BRF_GRA }, // 6 + { "268-c6c.c6", 0x800000, 0x010a831b, 3 | BRF_GRA }, // 7 + { "268-c7c.c7", 0x800000, 0x6d72a969, 3 | BRF_GRA }, // 8 + { "268-c8c.c8", 0x800000, 0x551d720e, 3 | BRF_GRA }, // 9 + + { "268-m1.m1", 0x080000, 0x4a5a6e0e, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "268-v1c.v1", 0x800000, 0xae31d60c, 5 | BRF_SND }, // 11 Sound data + { "268-v2c.v2", 0x800000, 0xc40613ed, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(mslug5h, mslug5h, neogeo) +STD_ROM_FN(mslug5h) + +struct BurnDriver BurnDrvmslug5h = { + "mslug5h", "mslug5", "neogeo", NULL, "2003", + "Metal Slug 5 (NGH-2680)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug5hRomInfo, mslug5hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug5Init, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 5 (JAMMA PCB) + +static struct BurnRomInfo ms5pcbRomDesc[] = { +#if !defined (ROM_VERIFY) + { "268-p1.p1", 0x400000, 0xd0466792, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "268-p2.p2", 0x400000, 0xfbf6b61e, 1 | BRF_ESS | BRF_PRG }, // 1 +#else + { "268-p1r.p1", 0x400000, 0x00000000, 1 | BRF_ESS | BRF_PRG | BRF_NODUMP }, // 0 68K code + { "268-p2r.p2", 0x400000, 0x00000000, 1 | BRF_ESS | BRF_PRG | BRF_NODUMP }, // 1 +#endif + + { "268-c1.c1", 0x1000000, 0x802042e8, 3 | BRF_GRA }, // 2 Sprite data + { "268-c2.c2", 0x1000000, 0x3b89fb9f, 3 | BRF_GRA }, // 3 + { "268-c3.c3", 0x1000000, 0x0f3f59e3, 3 | BRF_GRA }, // 4 + { "268-c4.c4", 0x1000000, 0x3ad8435a, 3 | BRF_GRA }, // 5 + + { "268-m1.m1", 0x080000, 0x4a5a6e0e, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "268-v1.v1", 0x1000000, 0x8458afe5, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(ms5pcb, ms5pcb, ms5pcbBIOS) +STD_ROM_FN(ms5pcb) + +struct BurnDriver BurnDrvms5pcb = { + "ms5pcb", NULL, NULL, NULL, "2003", + "Metal Slug 5 (JAMMA PCB)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SNK_DEDICATED_PCB | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, ms5pcbRomInfo, ms5pcbRomName, NULL, NULL, neogeoInputInfo, ms5pcbDIPInfo, + mslug5Init, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 5 Plus (bootleg) + +static struct BurnRomInfo ms5plusRomDesc[] = { + { "ms5-p1p.bin", 0x100000, 0x106b276f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "ms5-p2p.bin", 0x200000, 0xd6a458e8, 1 | BRF_ESS | BRF_PRG }, // 1 + { "ms5-p3p.bin", 0x200000, 0x439ec031, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "ms5-s1p.bin", 0x020000, 0x21e04432, 2 | BRF_GRA }, // 3 Text layer tiles + + { "268-c1c.c1", 0x800000, 0xab7c389a, 3 | BRF_GRA }, // 4 Sprite data + { "268-c2c.c2", 0x800000, 0x3560881b, 3 | BRF_GRA }, // 5 + { "268-c3c.c3", 0x800000, 0x3af955ea, 3 | BRF_GRA }, // 6 + { "268-c4c.c4", 0x800000, 0xc329c373, 3 | BRF_GRA }, // 7 + { "268-c5c.c5", 0x800000, 0x959c8177, 3 | BRF_GRA }, // 8 + { "268-c6c.c6", 0x800000, 0x010a831b, 3 | BRF_GRA }, // 9 + { "268-c7c.c7", 0x800000, 0x6d72a969, 3 | BRF_GRA }, // 10 + { "268-c8c.c8", 0x800000, 0x551d720e, 3 | BRF_GRA }, // 11 + + { "268-m1.m1", 0x080000, 0x4a5a6e0e, 4 | BRF_ESS | BRF_PRG }, // 12 Z80 code + + { "268-v1c.v1", 0x800000, 0xae31d60c, 5 | BRF_SND }, // 13 Sound data + { "268-v2c.v2", 0x800000, 0xc40613ed, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(ms5plus, ms5plus, neogeo) +STD_ROM_FN(ms5plus) + +void __fastcall ms5plusWriteWordBankSwitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress==0x2ffff4) + { + UINT32 nBank = wordValue << 16; + if (nNeo68KROMBank != nBank) + { + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); + } + }; +} + +static void ms5plusInstallHandlers() +{ + SekMapHandler(6, 0x2fe000, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(6, ms5plusWriteWordBankSwitch); +} + +static INT32 ms5plusInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = lans2004_sx_decode; + NeoCallbackActive->pInstallHandlers = ms5plusInstallHandlers; + NeoCallbackActive->pBankswitch = NeoPVCMapBank; + nNeoProtectionXor = 0x19; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0x4e001, 0xfe2cf6, { 0xc3, 0xfd, 0x81, 0xac, 0x6d, 0xe7, 0xbf, 0x9e } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvms5plus = { + "ms5plus", "mslug5", "neogeo", NULL, "2003", + "Metal Slug 5 Plus (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, ms5plusRomInfo, ms5plusRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + ms5plusInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos (JAMMA PCB, set 1) + +static struct BurnRomInfo svcpcbRomDesc[] = { + { "269-p1.p1", 0x2000000, 0x432cfdfc, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "269-c1.c1", 0x2000000, 0x1b608f9c, 3 | BRF_GRA }, // 1 Sprite data + { "269-c2.c1", 0x2000000, 0x5a95f294, 3 | BRF_GRA }, // 2 + + { "269-m1.m1", 0x080000, 0xf6819d00, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "269-v1.v1", 0x800000, 0xc659b34c, 5 | BRF_SND }, // 5 Sound data + { "269-v2.v1", 0x800000, 0xdd903835, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(svcpcb, svcpcb, svcpcbBIOS) +STD_ROM_FN(svcpcb) + +static void svcCallback() +{ + INT32 i, j, k; + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x0fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x800000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x7fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x0600000; i+=4) + { + UINT16 rom16 = *((UINT16 *)(Neo68KROMActive + i + 1)); + rom16 = BITSWAP16(rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0); + *((UINT16 *)(Neo68KROMActive + i + 1)) = rom16; + } + + memcpy (Neo68KROMActive + 0x700000, Neo68KROMActive, 0x100000); + + for (i = 0; i < 0x0100000 / 0x10000; i++) + { + j = BITSWAP08(i, 7, 6, 5, 4, 2, 3, 0, 1); + memcpy (Neo68KROMActive + i * 0x010000, Neo68KROMActive + 0x700000 + j * 0x010000, 0x010000); + } + + for (i = 0x100000; i < 0x700000; i += 0x100000) + { + for (j = 0; j < 0x100000; j+= 0x100) + { + k = BITSWAP08(j >> 12, 4, 5, 6, 7, 1, 0, 3, 2 ) << 12; + k |= (j & 0x00f00) ^ 0x00a00; + + memcpy (Neo68KROMActive + 0x700000 + j, Neo68KROMActive + i + k, 0x100); + } + + memcpy (Neo68KROMActive + i, Neo68KROMActive + 0x700000, 0x100000); + } +} + +static INT32 svcpcbInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x57; + NeoCallbackActive->pInitialise = svcCallback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xC2000, 0xFFAC28, { 0xC3, 0xFD, 0x81, 0xAC, 0x6D, 0xE7, 0xBF, 0x9E } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvsvcpcb = { + "svcpcb", NULL, NULL, NULL, "2003", + "SNK vs. Capcom - SVC Chaos (JAMMA PCB, set 1)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SNK_DEDICATED_PCB | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcpcbRomInfo, svcpcbRomName, NULL, NULL, neogeoInputInfo, svcpcbDIPInfo, + svcpcbInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos (JAMMA PCB, set 2) + +static struct BurnRomInfo svcpcbaRomDesc[] = { + { "269-p1a.p1", 0x400000, 0x38e2005e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "269-p2a.p1", 0x400000, 0x6d13797c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "269-c1a.c1", 0x1000000, 0xe64d2b0c, 3 | BRF_GRA }, // 2 Sprite data + { "269-c2a.c2", 0x1000000, 0x249089c2, 3 | BRF_GRA }, // 3 + { "269-c3a.c3", 0x1000000, 0xd32f2fab, 3 | BRF_GRA }, // 4 + { "269-c4a.c4", 0x1000000, 0xbf77e878, 3 | BRF_GRA }, // 5 + + { "269-m1.m1", 0x080000, 0xf6819d00, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "269-v1a.v1", 0x1000000, 0xa6af4753, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(svcpcba, svcpcba, svcpcbBIOS) +STD_ROM_FN(svcpcba) + +struct BurnDriver BurnDrvsvcpcba = { + "svcpcba", "svcpcb", NULL, NULL, "2003", + "SNK vs. Capcom - SVC Chaos (JAMMA PCB, set 2)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SNK_DEDICATED_PCB | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcpcbaRomInfo, svcpcbaRomName, NULL, NULL, neogeoInputInfo, svcpcbDIPInfo, + svcpcbInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos (NGM-2690)(NGH-2690) + +static struct BurnRomInfo svcRomDesc[] = { + { "269-p1.p1", 0x400000, 0x38e2005e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "269-p2.p2", 0x400000, 0x6d13797c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "269-c1r.c1", 0x800000, 0x887b4068, 3 | BRF_GRA }, // 2 Sprite data + { "269-c2r.c2", 0x800000, 0x4e8903e4, 3 | BRF_GRA }, // 3 + { "269-c3r.c3", 0x800000, 0x7d9c55b0, 3 | BRF_GRA }, // 4 + { "269-c4r.c4", 0x800000, 0x8acb5bb6, 3 | BRF_GRA }, // 5 + { "269-c5r.c5", 0x800000, 0x097a4157, 3 | BRF_GRA }, // 6 + { "269-c6r.c6", 0x800000, 0xe19df344, 3 | BRF_GRA }, // 7 + { "269-c7r.c7", 0x800000, 0xd8f0340b, 3 | BRF_GRA }, // 8 + { "269-c8r.c8", 0x800000, 0x2570b71b, 3 | BRF_GRA }, // 9 + + { "269-m1.m1", 0x080000, 0xf6819d00, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "269-v1.v1", 0x800000, 0xc659b34c, 5 | BRF_SND }, // 11 Sound data + { "269-v2.v2", 0x800000, 0xdd903835, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(svc, svc, neogeo) +STD_ROM_FN(svc) + +struct BurnDriver BurnDrvsvc = { + "svc", NULL, "neogeo", NULL, "2003", + "SNK vs. Capcom - SVC Chaos (NGM-2690)(NGH-2690)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcRomInfo, svcRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + svcpcbInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos (bootleg) + +static struct BurnRomInfo svcbootRomDesc[] = { + { "svc-p1.bin", 0x800000, 0x0348f162, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "svc-s1.bin", 0x020000, 0x70b44df1, 2 | BRF_GRA }, // 1 Text layer tiles + + { "svc-c1.bin", 0x800000, 0xa7826b89, 3 | BRF_GRA }, // 2 Sprite data + { "svc-c2.bin", 0x800000, 0xed3c2089, 3 | BRF_GRA }, // 3 + { "svc-c3.bin", 0x800000, 0x71ed8063, 3 | BRF_GRA }, // 4 + { "svc-c4.bin", 0x800000, 0x250bde2d, 3 | BRF_GRA }, // 5 + { "svc-c5.bin", 0x800000, 0x9817c082, 3 | BRF_GRA }, // 6 + { "svc-c6.bin", 0x800000, 0x2bc0307f, 3 | BRF_GRA }, // 7 + { "svc-c7.bin", 0x800000, 0x4358d7b9, 3 | BRF_GRA }, // 8 + { "svc-c8.bin", 0x800000, 0x366deee5, 3 | BRF_GRA }, // 9 + + { "svc-m1.bin", 0x020000, 0x804328c3, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "svc-v2.bin", 0x400000, 0xb5097287, 5 | BRF_SND }, // 11 Sound data + { "svc-v1.bin", 0x400000, 0xbd3a391f, 5 | BRF_SND }, // 12 + { "svc-v4.bin", 0x400000, 0x33fc0b37, 5 | BRF_SND }, // 13 + { "svc-v3.bin", 0x400000, 0xaa9849a0, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(svcboot, svcboot, neogeo) +STD_ROM_FN(svcboot) + +static void svcboot_sx_decode() +{ + for (INT32 i = 0; i < 0x20000 / 2; i++) { + INT32 n = NeoTextROM[nNeoActiveSlot][i]; + NeoTextROM[nNeoActiveSlot][i] = NeoTextROM[nNeoActiveSlot][0x10000 + i]; + NeoTextROM[nNeoActiveSlot][0x10000 + i] = n; + } +} + +static void svcboot_decode() +{ + DoPerm(1); + + for (INT32 i = 0; i < 0x20000 / 2; i++) { + INT32 n = NeoZ80ROMActive[i]; + NeoZ80ROMActive[i] = NeoZ80ROMActive[0x10000 + i]; + NeoZ80ROMActive[0x10000 + i] = n; + } +} + +static void svcbootCallback() +{ + INT32 i, j, k; + for (i = 0x100000; i < 0x800000; i+=0x100000) + { + memcpy (Neo68KROMActive, Neo68KROMActive + i, 0x100000); + + for (j = 0; j < 0x100000; j++) + { + k = (j & 0xfff00) + BITSWAP08(j, 7, 2, 1, 4, 3, 6, 5, 0); + Neo68KROMActive[i + j] = Neo68KROMActive[k]; + } + } + + memcpy (Neo68KROMActive, Neo68KROMActive + 0x700000, 0x100000); + + svcboot_sx_decode(); + svcboot_decode(); +} + + +static INT32 svcbootInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = svcbootCallback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot], 0x1000000); + } + + return nRet; +} + +struct BurnDriver BurnDrvsvcboot = { + "svcboot", "svc", "neogeo", NULL, "2003", + "SNK vs. Capcom - SVC Chaos (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcbootRomInfo, svcbootRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + svcbootInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos Plus (bootleg set 1) + +static struct BurnRomInfo svcplusRomDesc[] = { + { "svc-p2p.bin", 0x200000, 0x50c0e2b7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "svc-p3p.bin", 0x200000, 0x58cdc293, 1 | BRF_ESS | BRF_PRG }, // 1 + { "svc-p1p.bin", 0x200000, 0xa194d842, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "svc-s1p.bin", 0x020000, 0x73344711, 2 | BRF_GRA }, // 3 Text layer tiles + + { "svc-c1.bin", 0x800000, 0xa7826b89, 3 | BRF_GRA }, // 4 Sprite data + { "svc-c2.bin", 0x800000, 0xed3c2089, 3 | BRF_GRA }, // 5 + { "svc-c3.bin", 0x800000, 0x71ed8063, 3 | BRF_GRA }, // 6 + { "svc-c4.bin", 0x800000, 0x250bde2d, 3 | BRF_GRA }, // 7 + { "svc-c5.bin", 0x800000, 0x9817c082, 3 | BRF_GRA }, // 8 + { "svc-c6.bin", 0x800000, 0x2bc0307f, 3 | BRF_GRA }, // 9 + { "svc-c7.bin", 0x800000, 0x4358d7b9, 3 | BRF_GRA }, // 10 + { "svc-c8.bin", 0x800000, 0x366deee5, 3 | BRF_GRA }, // 11 + + { "svc-m1.bin", 0x020000, 0x804328c3, 4 | BRF_ESS | BRF_PRG }, // 12 Z80 code + + { "svc-v2.bin", 0x400000, 0xb5097287, 5 | BRF_SND }, // 13 Sound data + { "svc-v1.bin", 0x400000, 0xbd3a391f, 5 | BRF_SND }, // 14 + { "svc-v4.bin", 0x400000, 0x33fc0b37, 5 | BRF_SND }, // 15 + { "svc-v3.bin", 0x400000, 0xaa9849a0, 5 | BRF_SND }, // 16 +}; + +STDROMPICKEXT(svcplus, svcplus, neogeo) +STD_ROM_FN(svcplus) + +static void svcplusCallback() +{ + INT32 i, j, k; + UINT8 *dst = (UINT8*)malloc(0x100000); + + if (dst) + { + for (i = 0; i < 0x600000; i+= 0x100000) + { + for (j = 0; j < 0x100000; j++) + { + k = BITSWAP24(j, 23,22,21,20,1,2,3,16,15,14,13,12,11,10,9,8,7,6,5,4,17,18,19,0); + k ^= 0x0e000e; + + dst[j] = Neo68KROMActive[i + k]; + } + + memcpy (Neo68KROMActive + i, dst, 0x100000); + } + + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x500000); + memcpy (Neo68KROMActive, dst, 0x100000); + + free (dst); + dst = NULL; + } + + *((UINT16*)(Neo68KROMActive + 0xf8016)) = 0x33c1; // Patch protected address + + lans2004_sx_decode(); + svcboot_decode(); +} + +static INT32 svcplusInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = svcplusCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot], 0x1000000); + } + + return nRet; +} + +struct BurnDriver BurnDrvsvcplus = { + "svcplus", "svc", "neogeo", NULL, "2003", + "SNK vs. Capcom - SVC Chaos Plus (bootleg set 1)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcplusRomInfo, svcplusRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + svcplusInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos Plus (bootleg set 2) + +static struct BurnRomInfo svcplusaRomDesc[] = { + { "svc-p2pl.bin", 0x400000, 0x7231ace2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "svc-p1pl.bin", 0x200000, 0x16b44144, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "svc-s1pl.bin", 0x020000, 0xca3c735e, 2 | BRF_GRA }, // 2 Text layer tiles + + { "svc-c1.bin", 0x800000, 0xa7826b89, 3 | BRF_GRA }, // 3 Sprite data + { "svc-c2.bin", 0x800000, 0xed3c2089, 3 | BRF_GRA }, // 4 + { "svc-c3.bin", 0x800000, 0x71ed8063, 3 | BRF_GRA }, // 5 + { "svc-c4.bin", 0x800000, 0x250bde2d, 3 | BRF_GRA }, // 6 + { "svc-c5.bin", 0x800000, 0x9817c082, 3 | BRF_GRA }, // 7 + { "svc-c6.bin", 0x800000, 0x2bc0307f, 3 | BRF_GRA }, // 8 + { "svc-c7.bin", 0x800000, 0x4358d7b9, 3 | BRF_GRA }, // 9 + { "svc-c8.bin", 0x800000, 0x366deee5, 3 | BRF_GRA }, // 10 + + { "svc-m1.bin", 0x020000, 0x804328c3, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "svc-v2.bin", 0x400000, 0xb5097287, 5 | BRF_SND }, // 12 Sound data + { "svc-v1.bin", 0x400000, 0xbd3a391f, 5 | BRF_SND }, // 13 + { "svc-v4.bin", 0x400000, 0x33fc0b37, 5 | BRF_SND }, // 14 + { "svc-v3.bin", 0x400000, 0xaa9849a0, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(svcplusa, svcplusa, neogeo) +STD_ROM_FN(svcplusa) + +static void svcplusaCallback() +{ + UINT8 *dst = (UINT8*)malloc(0x100000); + if (dst) + { + memcpy (dst, Neo68KROMActive + 0x500000, 0x100000); + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x500000); + memcpy (Neo68KROMActive, dst, 0x100000); + free (dst); + dst = NULL; + } + + *((UINT16*)(Neo68KROMActive + 0xf8016)) = 0x33c1; // Patch protected address + + svcboot_sx_decode(); + svcboot_decode(); +} + +static INT32 svcplusaInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = svcplusaCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot], 0x1000000); + } + + return nRet; +} + +struct BurnDriver BurnDrvsvcplusa = { + "svcplusa", "svc", "neogeo", NULL, "2003", + "SNK vs. Capcom - SVC Chaos Plus (bootleg set 2)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcplusaRomInfo, svcplusaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + svcplusaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// SNK vs. Capcom - SVC Chaos Super Plus (bootleg) + +static struct BurnRomInfo svcsplusRomDesc[] = { + { "svc-p1sp.bin", 0x400000, 0x2601902f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "svc-p2sp.bin", 0x400000, 0x0ca13305, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "svc-s1sp.bin", 0x020000, 0x233d6439, 2 | BRF_GRA }, // 2 Text layer tiles + + { "svc-c1.bin", 0x800000, 0xa7826b89, 3 | BRF_GRA }, // 3 Sprite data + { "svc-c2.bin", 0x800000, 0xed3c2089, 3 | BRF_GRA }, // 4 + { "svc-c3.bin", 0x800000, 0x71ed8063, 3 | BRF_GRA }, // 5 + { "svc-c4.bin", 0x800000, 0x250bde2d, 3 | BRF_GRA }, // 6 + { "svc-c5.bin", 0x800000, 0x9817c082, 3 | BRF_GRA }, // 7 + { "svc-c6.bin", 0x800000, 0x2bc0307f, 3 | BRF_GRA }, // 8 + { "svc-c7.bin", 0x800000, 0x4358d7b9, 3 | BRF_GRA }, // 9 + { "svc-c8.bin", 0x800000, 0x366deee5, 3 | BRF_GRA }, // 10 + + { "svc-m1.bin", 0x020000, 0x804328c3, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "svc-v2.bin", 0x400000, 0xb5097287, 5 | BRF_SND }, // 12 Sound data + { "svc-v1.bin", 0x400000, 0xbd3a391f, 5 | BRF_SND }, // 13 + { "svc-v4.bin", 0x400000, 0x33fc0b37, 5 | BRF_SND }, // 14 + { "svc-v3.bin", 0x400000, 0xaa9849a0, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(svcsplus, svcsplus, neogeo) +STD_ROM_FN(svcsplus) + +static void svcsplus_sx_decode() +{ + for (INT32 i = 0; i < 0x20000; i++) + NeoTextROM[nNeoActiveSlot][i] = BITSWAP08(NeoTextROM[nNeoActiveSlot][i], 7, 6, 0, 4, 3, 2, 1, 5); +} + +static void svcsplusCallback() +{ + INT32 i, j, k; + for (i = 0x100000; i < 0x800000; i+=0x10000) + { + memcpy (Neo68KROMActive, Neo68KROMActive + i, 0x10000); + + for (j = 0; j < 0x10000; j++) + { + k = BITSWAP16(j, 1, 9, 10, 12, 11, 13, 14, 5, 4, 2, 8, 7, 3, 6, 15, 0); + Neo68KROMActive[i + j] = Neo68KROMActive[k]; + } + } + + memcpy (Neo68KROMActive, Neo68KROMActive + 0x600000, 0x100000); + + *((UINT16*)(Neo68KROMActive + 0x9e90)) = 0x000f; // Enable S. Plus + *((UINT16*)(Neo68KROMActive + 0x9e92)) = 0xc9c0; + *((UINT16*)(Neo68KROMActive + 0xa10c)) = 0x4eb9; // Enable boss icons + *((UINT16*)(Neo68KROMActive + 0xa10e)) = 0x000e; + *((UINT16*)(Neo68KROMActive + 0xa110)) = 0x9750; + + svcsplus_sx_decode(); + svcboot_decode(); +} + +static INT32 svcsplusInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = svcsplusCallback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot], 0x1000000); + } + + return nRet; +} + +struct BurnDriver BurnDrvsvcsplus = { + "svcsplus", "svc", "neogeo", NULL, "2003", + "SNK vs. Capcom - SVC Chaos Super Plus (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF | FBF_SF, + NULL, svcsplusRomInfo, svcsplusRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + svcsplusInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown V / Samurai Spirits Zero (NGM-2700) + +static struct BurnRomInfo samsho5RomDesc[] = { + { "270-p1.p1", 0x400000, 0x4a2a09e6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "270-p2.sp2", 0x400000, 0xe0c74c85, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "270-c1.c1", 0x800000, 0x14ffffac, 3 | BRF_GRA }, // 2 Sprite data + { "270-c2.c2", 0x800000, 0x401f7299, 3 | BRF_GRA }, // 3 + { "270-c3.c3", 0x800000, 0x838f0260, 3 | BRF_GRA }, // 4 + { "270-c4.c4", 0x800000, 0x041560a5, 3 | BRF_GRA }, // 5 + { "270-c5.c5", 0x800000, 0xbd30b52d, 3 | BRF_GRA }, // 6 + { "270-c6.c6", 0x800000, 0x86a69c70, 3 | BRF_GRA }, // 7 + { "270-c7.c7", 0x800000, 0xd28fbc3c, 3 | BRF_GRA }, // 8 + { "270-c8.c8", 0x800000, 0x02c530a6, 3 | BRF_GRA }, // 9 + + { "270-m1.m1", 0x080000, 0x49c9901a, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "270-v1.v1", 0x800000, 0x62e434eb, 5 | BRF_SND }, // 11 Sound data + { "270-v2.v2", 0x800000, 0x180f3c9a, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(samsho5, samsho5, neogeo) +STD_ROM_FN(samsho5) + +static void samsho5Callback() +{ + PCM2DecryptP2Info Info = { 0x000000, 0x080000, 0x700000, 0x680000, 0x500000, 0x180000, 0x200000, 0x480000, 0x300000, 0x780000, 0x600000, 0x280000, 0x100000, 0x580000, 0x400000, 0x380000 }; + + PCM2DecryptP2(&Info); +} + +static INT32 samsho5Init() +{ + nNeoProtectionXor = 0x0F; + + NeoCallbackActive->pInitialise = samsho5Callback; + + INT32 nRet = NeoInit(); + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0x0A000, 0xFEB2C0, { 0xCB, 0x29, 0x7D, 0x43, 0xD2, 0x3A, 0xC2, 0xB4 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvsamsho5 = { + "samsho5", NULL, "neogeo", NULL, "2003", + "Samurai Shodown V / Samurai Spirits Zero (NGM-2700)\0", NULL, "Yuki Enterprise / SNK Playmore", "Neo Geo MVS", + L"Samurai Shodown V\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 (NGM-2700)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho5RomInfo, samsho5RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsho5Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown V / Samurai Spirits Zero (NGH-2700) + +static struct BurnRomInfo samsho5hRomDesc[] = { + { "270-p1c.p1", 0x400000, 0xbf956089, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "270-p2c.sp2", 0x400000, 0x943a6b1d, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "270-c1.c1", 0x800000, 0x14ffffac, 3 | BRF_GRA }, // 2 Sprite data + { "270-c2.c2", 0x800000, 0x401f7299, 3 | BRF_GRA }, // 3 + { "270-c3.c3", 0x800000, 0x838f0260, 3 | BRF_GRA }, // 4 + { "270-c4.c4", 0x800000, 0x041560a5, 3 | BRF_GRA }, // 5 + { "270-c5.c5", 0x800000, 0xbd30b52d, 3 | BRF_GRA }, // 6 + { "270-c6.c6", 0x800000, 0x86a69c70, 3 | BRF_GRA }, // 7 + { "270-c7.c7", 0x800000, 0xd28fbc3c, 3 | BRF_GRA }, // 8 + { "270-c8.c8", 0x800000, 0x02c530a6, 3 | BRF_GRA }, // 9 + + { "270-m1.m1", 0x080000, 0x49c9901a, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "270-v1.v1", 0x800000, 0x62e434eb, 5 | BRF_SND }, // 11 Sound data + { "270-v2.v2", 0x800000, 0x180f3c9a, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(samsho5h, samsho5h, neogeo) +STD_ROM_FN(samsho5h) + +struct BurnDriver BurnDrvsamsho5h = { + "samsho5h", "samsho5", "neogeo", NULL, "2003", + "Samurai Shodown V / Samurai Spirits Zero (NGH-2700)\0", NULL, "Yuki Enterprise / SNK Playmore", "Neo Geo MVS", + L"Samurai Shodown V\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 (NGH-2700)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho5hRomInfo, samsho5hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsho5Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown V / Samurai Spirits Zero (bootleg) + +static struct BurnRomInfo samsho5bRomDesc[] = { + { "ssv-p2.bin", 0x400000, 0x5023067f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "ssv-p1.bin", 0x400000, 0xb6cbe386, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "ssv-s1.bin", 0x020000, 0x70f667d0, 2 | BRF_GRA }, // 2 Text layer tiles + + { "ssv-c1.bin", 0x1000000, 0x9c564a01, 3 | BRF_GRA }, // 3 Sprite data + { "ssv-c2.bin", 0x1000000, 0x4b73b8da, 3 | BRF_GRA }, // 4 + { "ssv-c3.bin", 0x1000000, 0x029f9bb5, 3 | BRF_GRA }, // 5 + { "ssv-c4.bin", 0x1000000, 0x75722430, 3 | BRF_GRA }, // 6 + + { "ssv-m1.bin", 0x020000, 0x18114fb1, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code (decrypted) + + { "ssv-v1.bin", 0x400000, 0xa3609761, 5 | BRF_SND }, // 8 Sound data + { "ssv-v2.bin", 0x400000, 0xcbd6ebd5, 5 | BRF_SND }, // 9 + { "ssv-v3.bin", 0x400000, 0x6f1c2703, 5 | BRF_SND }, // 10 + { "ssv-v4.bin", 0x400000, 0x5020c055, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(samsho5b, samsho5b, neogeo) +STD_ROM_FN(samsho5b) + +static void samsho5b_sx_decode() +{ + UINT8 *Buf = (UINT8*)malloc(0x20000); + if (Buf) { + memcpy(Buf, NeoTextROM[nNeoActiveSlot], 0x20000); + + for (INT32 i = 0; i < 0x20000; i += 0x10) { + memcpy(&NeoTextROM[nNeoActiveSlot][i + 0], &Buf[i + 8], 8); + memcpy(&NeoTextROM[nNeoActiveSlot][i + 8], &Buf[i + 0], 8); + } + + free(Buf); + Buf = NULL; + } +} + +static void samsho5b_vx_decode() +{ + for (INT32 i = 0; i < 0x400000 * 4; i++) + YM2610ADPCMAROM[nNeoActiveSlot][i] = BITSWAP08(YM2610ADPCMAROM[nNeoActiveSlot][i], 0, 1, 5, 4, 3, 2, 6, 7); +} + +static void samsho5bCallback() +{ + INT32 i, j, k; + UINT8 *dst = (UINT8 *)malloc(0x100000); + + if (dst) + { + for (i = 0; i < 0x800000; i+=0x100000) + { + for (j = 0; j < 0x100000; j++) + { + k = BITSWAP08((j & 0xff), 7, 6, 5, 4, 1, 2, 3, 0); + k += (j & 0xfffff00); + k ^= 0x0c000a; + + dst[j] = Neo68KROMActive[i + k]; + } + + memcpy (Neo68KROMActive + i, dst, 0x100000); + } + + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x700000); + memcpy (Neo68KROMActive, dst, 0x100000); + + free (dst); + dst = NULL; + } + + samsho5b_sx_decode(); + lans2004_cx_decode(0x1000000 * 4); + +} + +static INT32 samsho5bInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = samsho5bCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + samsho5b_vx_decode(); + } + + return nRet; +} + +struct BurnDriver BurnDrvsamsho5b = { + "samsho5b", "samsho5", "neogeo", NULL, "2003", + "Samurai Shodown V / Samurai Spirits Zero (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + L"Samurai Shodown V\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 (bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsho5bRomInfo, samsho5bRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsho5bInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2003 (dedicated PCB version) + +static struct BurnRomInfo kf2k3pcbRomDesc[] = { + { "271-p1.p1", 0x0400000, 0xb9da070c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "271-p2.p2", 0x0400000, 0xda3118c4, 1 | BRF_ESS | BRF_PRG }, // 1 + { "271-p3.p3", 0x0100000, 0x5cefd0d2, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "271-c1.c1", 0x1000000, 0xf5ebb327, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2.c2", 0x1000000, 0x2be21620, 3 | BRF_GRA }, // 4 + { "271-c3.c3", 0x1000000, 0xddded4ff, 3 | BRF_GRA }, // 5 + { "271-c4.c4", 0x1000000, 0xd85521e6, 3 | BRF_GRA }, // 6 + { "271-c5.c5", 0x1000000, 0x18aa3540, 3 | BRF_GRA }, // 7 + { "271-c6.c6", 0x1000000, 0x1c40de87, 3 | BRF_GRA }, // 8 + + { "271-m1.m1", 0x0080000, 0xd6bcf2bc, 4 | BRF_ESS | BRF_ESS }, // 9 Z80 code + + { "271-v1.v1", 0x1000000, 0x1d96154b, 5 | BRF_SND }, // 10 Sound data +}; + +STDROMPICKEXT(kf2k3pcb, kf2k3pcb, kf2k3pcbBIOS) +STD_ROM_FN(kf2k3pcb) + +void kf2k3pcb_bios_decode() +{ + INT32 i, j; + static const INT32 address[0x40] = { + 0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a, + 0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04, + 0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07, + 0x09,0x09,0x04,0x04,0x09,0x09,0x04,0x04, + 0x0b,0x0d,0x0b,0x0d,0x03,0x05,0x03,0x05, + 0x0e,0x0e,0x03,0x03,0x0e,0x0e,0x03,0x03, + 0x03,0x05,0x0b,0x0d,0x03,0x05,0x0b,0x0d, + 0x04,0x00,0x04,0x00,0x0e,0x0a,0x0e,0x0a + }; + + extern UINT8 *Neo68KBIOS; + UINT16 *src = (UINT16*)Neo68KBIOS; + UINT16 *dst = (UINT16*)malloc( 0x80000 ); + + for (i = 0; i < 0x80000 / 2; i++) { + j = i; + if ( i & 0x00020) j ^= 0x0010; + if (~i & 0x00010) j ^= 0x0040; + j ^= 0x00a0; + if ( i & 0x00004) j ^= 0x0080; + if ( i & 0x00200) j ^= 0x0100; + if (~i & 0x02000) j ^= 0x0400; + if (~i & 0x10000) j ^= 0x1000; + if ( i & 0x02000) j ^= 0x8000; + j ^= address[((i >> 1) & 0x38) | (i & 7)]; + + dst[i] = src[j]; + if (dst[i] & 0x0004) dst[i] ^= 0x0001; + if (dst[i] & 0x0010) dst[i] ^= 0x0002; + if (dst[i] & 0x0020) dst[i] ^= 0x0008; + } + + memcpy (src, dst, 0x80000); + + if (dst) { + free (dst); + dst = NULL; + } +} + +static void kf2k3pcbCallback() +{ + INT32 i, j, k; + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[0x800000 + i] ^= Neo68KROMActive[0x100002 | i]; + + for (i = 0x100000; i < 0x800000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x7fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x700000; i += 4) { + UINT16 rom16 = *((UINT16 *)(Neo68KROMActive + i + 1)); + rom16 = BITSWAP16(rom16, 15, 14, 13, 12, 4, 5, 6, 7, 8, 9, 10, 11, 3, 2, 1, 0); + *((UINT16 *)(Neo68KROMActive + i + 1)) = rom16; + } + + memcpy (Neo68KROMActive + 0x700000, Neo68KROMActive, 0x100000); + + for (i = 0; i < 0x0100000 / 0x10000; i++) { + j = BITSWAP08(i, 7, 6, 5, 4, 1, 0, 3, 2); + memcpy (Neo68KROMActive + i * 0x010000, Neo68KROMActive + 0x700000 + j * 0x010000, 0x010000); + } + + memcpy (Neo68KROMActive + 0x200000, Neo68KROMActive + 0x100000, 0x600000); + + for (i = 0x200000; i < 0x900000; i += 0x100000) + { + for (j = 0; j < 0x100000; j += 0x100) + { + k = (j & 0xf00) ^ 0x00300; + k |= BITSWAP08(j >> 12, 4, 5, 6, 7, 1, 0, 3, 2 ) << 12; + + memcpy (Neo68KROMActive + 0x100000 + j, Neo68KROMActive + i + k, 0x100); + } + + memcpy (Neo68KROMActive + i, Neo68KROMActive + 0x100000, 0x100000); + } +} + +static INT32 kf2k3pcbInit() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = kf2k3pcbCallback; + + nNeoTextROMSize[nNeoActiveSlot] = 0x100000; + nNeoProtectionXor = 0x9D; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + + // M1 has additional swap + for (INT32 i = 0; i < 0x80000; i++) { + NeoZ80ROMActive[i] = BITSWAP08(NeoZ80ROMActive[i], 5, 6, 1, 4, 3, 0, 7, 2); + } + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k3pcb = { + "kf2k3pcb", NULL, NULL, NULL, "2003", + "The King of Fighters 2003\0", "dedicated PCB version, Japan region", "Playmore / Capcom", "dedicated Neo Geo PCB", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SNK_DEDICATED_PCB | HARDWARE_SNK_CMC50 | HARDWARE_SNK_KOF2K3 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k3pcbRomInfo, kf2k3pcbRomName, NULL, NULL, neogeoInputInfo, kf2k3pcbDIPInfo, + kf2k3pcbInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2003 (NGM-2710) + +static struct BurnRomInfo kof2003RomDesc[] = { + { "271-p1c.p1", 0x400000, 0x530ecc14, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "271-p2c.p2", 0x400000, 0xfd568da9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "271-p3c.p3", 0x100000, 0xaec5b4a9, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "271-c1c.c1", 0x800000, 0xb1dc25d0, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2c.c2", 0x800000, 0xd5362437, 3 | BRF_GRA }, // 4 + { "271-c3c.c3", 0x800000, 0x0a1fbeab, 3 | BRF_GRA }, // 5 + { "271-c4c.c4", 0x800000, 0x87b19a0c, 3 | BRF_GRA }, // 6 + { "271-c5c.c5", 0x800000, 0x704ea371, 3 | BRF_GRA }, // 7 + { "271-c6c.c6", 0x800000, 0x20a1164c, 3 | BRF_GRA }, // 8 + { "271-c7c.c7", 0x800000, 0x189aba7f, 3 | BRF_GRA }, // 9 + { "271-c8c.c8", 0x800000, 0x20ec4fdc, 3 | BRF_GRA }, // 10 + + { "271-m1c.m1", 0x080000, 0xf5515629, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 12 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof2003, kof2003, neogeo) +STD_ROM_FN(kof2003) + +static void kof2003Callback() +{ + INT32 i, j, k; + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x0fffe0 + (i & 0x1f)]; + + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[0x800000 + i] ^= Neo68KROMActive[0x100002 | i]; + + for (i = 0x100000; i < 0x800000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x7fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x800000; i += 4) { + UINT16 rom16 = *((UINT16 *)(Neo68KROMActive + i + 1)); + rom16 = BITSWAP16(rom16, 15, 14, 13, 12, 5, 4, 7, 6, 9, 8, 11, 10, 3, 2, 1, 0); + *((UINT16 *)(Neo68KROMActive + i + 1)) = rom16; + } + + memcpy (Neo68KROMActive + 0x700000, Neo68KROMActive, 0x100000); + + for (i = 0; i < 0x0100000 / 0x10000; i++) { + j = BITSWAP08(i, 7, 6, 5, 4, 0, 1, 2, 3); + memcpy (Neo68KROMActive + i * 0x010000, Neo68KROMActive + 0x700000 + j * 0x010000, 0x010000); + } + + memcpy (Neo68KROMActive + 0x200000, Neo68KROMActive + 0x100000, 0x600000); + + for (i = 0x200000; i < 0x900000; i += 0x100000) + { + for (j = 0; j < 0x100000; j += 0x100) + { + k = (j & 0xf00) ^ 0x00800; + k |= BITSWAP08(j >> 12, 4, 5, 6, 7, 1, 0, 3, 2 ) << 12; + + memcpy (Neo68KROMActive + 0x100000 + j, Neo68KROMActive + i + k, 0x100); + } + + memcpy (Neo68KROMActive + i, Neo68KROMActive + 0x100000, 0x100000); + } +} + +static INT32 kof2003Init() +{ + INT32 nRet; + + nNeoProtectionXor = 0x9D; + NeoCallbackActive->pInitialise = kof2003Callback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkof2003 = { + "kof2003", NULL, "neogeo", NULL, "2003", + "The King of Fighters 2003 (NGM-2710)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2003RomInfo, kof2003RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2003Init, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2003 (NGH-2710) + +static struct BurnRomInfo kof2003hRomDesc[] = { + { "271-p1k.p1", 0x400000, 0xd0d0ae3e, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + { "271-p2k.p2", 0x400000, 0xfb3f79d9, 1 | BRF_ESS | BRF_PRG }, // 1 + { "271-p3k.p3", 0x100000, 0x232702ad, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "271-c1k.c1", 0x800000, 0xefb9dd24, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2k.c2", 0x800000, 0x3fb90447, 3 | BRF_GRA }, // 4 + { "271-c3k.c3", 0x800000, 0x27950f28, 3 | BRF_GRA }, // 5 + { "271-c4k.c4", 0x800000, 0x735177f8, 3 | BRF_GRA }, // 6 + { "271-c5k.c5", 0x800000, 0xa51b7c0f, 3 | BRF_GRA }, // 7 + { "271-c6k.c6", 0x800000, 0xd5cae4e0, 3 | BRF_GRA }, // 8 + { "271-c7k.c7", 0x800000, 0xe65ae2d0, 3 | BRF_GRA }, // 9 + { "271-c8k.c8", 0x800000, 0x312f528c, 3 | BRF_GRA }, // 10 + + { "271-m1k.m1", 0x080000, 0x48d9affe, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 12 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kof2003h, kof2003h, neogeo) +STD_ROM_FN(kof2003h) + +static void kof2003hCallback() +{ + INT32 i, j, k; + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x0fffe0 + (i & 0x1f)]; + + for (i = 0; i < 0x100000; i++) + Neo68KROMActive[0x800000 + i] ^= Neo68KROMActive[0x100002 | i]; + + for (i = 0x100000; i < 0x800000; i++) + Neo68KROMActive[i] ^= ~Neo68KROMActive[0x7fffe0 + (i & 0x1f)]; + + for (i = 0x100000; i < 0x800000; i += 4) { + UINT16 rom16 = *((UINT16 *)(Neo68KROMActive + i + 1)); + rom16 = BITSWAP16(rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0); + *((UINT16 *)(Neo68KROMActive + i + 1)) = rom16; + } + + memcpy (Neo68KROMActive + 0x700000, Neo68KROMActive, 0x100000); + + for (i = 0; i < 0x0100000 / 0x10000; i++) { + j = BITSWAP08(i, 7, 6, 5, 4, 1, 0, 3, 2); + memcpy (Neo68KROMActive + i * 0x010000, Neo68KROMActive + 0x700000 + j * 0x010000, 0x010000); + } + + memcpy (Neo68KROMActive + 0x200000, Neo68KROMActive + 0x100000, 0x600000); + + for (i = 0x200000; i < 0x900000; i += 0x100000) + { + for (j = 0; j < 0x100000; j += 0x100) + { + k = (j & 0xf00) ^ 0x00400; + k |= BITSWAP08(j >> 12, 6, 7, 4, 5, 0, 1, 2, 3) << 12; + + memcpy (Neo68KROMActive + 0x100000 + j, Neo68KROMActive + i + k, 0x100); + } + + memcpy (Neo68KROMActive + i, Neo68KROMActive + 0x100000, 0x100000); + } +} + +static INT32 kof2003hInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x9D; + NeoCallbackActive->pInitialise = kof2003hCallback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkof2003h = { + "kof2003h", "kof2003", "neogeo", NULL, "2003", + "The King of Fighters 2003 (NGH-2710)\0", NULL, "SNK Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_P32 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kof2003hRomInfo, kof2003hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2003hInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2003 (bootleg set 1) + +static struct BurnRomInfo kf2k3blRomDesc[] = { + { "2k3-p1.bin", 0x400000, 0x92ed6ee3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "2k3-p2.bin", 0x400000, 0x5d3d8bb3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k3-s1.bin", 0x020000, 0x482c48a5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "271-c1c.c1", 0x800000, 0xb1dc25d0, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2c.c2", 0x800000, 0xd5362437, 3 | BRF_GRA }, // 4 + { "271-c3c.c3", 0x800000, 0x0a1fbeab, 3 | BRF_GRA }, // 5 + { "271-c4c.c4", 0x800000, 0x87b19a0c, 3 | BRF_GRA }, // 6 + { "271-c5c.c5", 0x800000, 0x704ea371, 3 | BRF_GRA }, // 7 + { "271-c6c.c6", 0x800000, 0x20a1164c, 3 | BRF_GRA }, // 8 + { "271-c7c.c7", 0x800000, 0x189aba7f, 3 | BRF_GRA }, // 9 + { "271-c8c.c8", 0x800000, 0x20ec4fdc, 3 | BRF_GRA }, // 10 + + { "2k3-m1.bin", 0x020000, 0x3a4969ff, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 12 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k3bl, kf2k3bl, neogeo) +STD_ROM_FN(kf2k3bl) + +UINT8 __fastcall kf2k3blReadByteProtection(UINT32) +{ + return PVCRAM[0x1ff2]; +} + +UINT16 __fastcall kf2k3blReadWordProtection(UINT32) +{ + return PVCRAM[0x1ff2]; +} + +static void kf2k3blCallback() +{ + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x700000); + memcpy (Neo68KROMActive, Neo68KROMActive + 0x700000, 0x100000); + + lans2004_sx_decode(); +} + +static void kf2k3blInstallHandlers() +{ + NeoPVCInstallHandlers(); + + SekMapHandler(7, 0x058196, 0x058197, SM_READ); + SekSetReadByteHandler(7, kf2k3blReadByteProtection); +} + +static INT32 kf2k3blInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x9D; + NeoCallbackActive->pInitialise = kf2k3blCallback; + + nRet = NeoPVCInit(); + + NeoCallbackActive->pInstallHandlers = kf2k3blInstallHandlers; + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k3bl = { + "kf2k3bl", "kof2003", "neogeo", NULL, "2003", + "The King of Fighters 2003 (bootleg set 1)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k3blRomInfo, kf2k3blRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k3blInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2003 (bootleg set 2) + +static struct BurnRomInfo kf2k3blaRomDesc[] = { + { "2k3-p1bl.bin", 0x100000, 0x4ea414dd, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "2k3-p3bl.bin", 0x400000, 0x370acbff, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2k3-p2bl.bin", 0x200000, 0x9c04fc52, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "2k3-s1.bin", 0x020000, 0x482c48a5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "271-c1c.c1", 0x800000, 0xb1dc25d0, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2c.c2", 0x800000, 0xd5362437, 3 | BRF_GRA }, // 4 + { "271-c3c.c3", 0x800000, 0x0a1fbeab, 3 | BRF_GRA }, // 5 + { "271-c4c.c4", 0x800000, 0x87b19a0c, 3 | BRF_GRA }, // 6 + { "271-c5c.c5", 0x800000, 0x704ea371, 3 | BRF_GRA }, // 7 + { "271-c6c.c6", 0x800000, 0x20a1164c, 3 | BRF_GRA }, // 8 + { "271-c7c.c7", 0x800000, 0x189aba7f, 3 | BRF_GRA }, // 9 + { "271-c8c.c8", 0x800000, 0x20ec4fdc, 3 | BRF_GRA }, // 10 + + { "2k3-m1.bin", 0x020000, 0x3a4969ff, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 12 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k3bla, kf2k3bla, neogeo) +STD_ROM_FN(kf2k3bla) + +static void kf2k3blaCallback() +{ + INT32 i, j, k; + UINT8 *dst = (UINT8 *)malloc(0x100000); + if (dst) + { + for (i = 0; i < 0x700000; i += 0x100000) + { + memcpy(dst, Neo68KROMActive + i, 0x100000); + + for (j = 0; j < 0x100000; j++) + { + k = BITSWAP24(j, 23,22,21,20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,0); + Neo68KROMActive[i + j] = dst[k]; + } + } + + free (dst); + dst = NULL; + } + + // patched by Altera protection chip + *((UINT16*)(Neo68KROMActive + 0x0f38ac)) = 0x4e75; + + lans2004_sx_decode(); +} + +void __fastcall kf2k3blaWriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + *((UINT16*)(PVCRAM + (sekAddress & 0x1ffe))) = wordValue; + + if (sekAddress == 0x2ffff2) + { + UINT32 nBank = ((PVCRAM[0x1ff3] << 16) | (PVCRAM[0x1ff2] << 8) | PVCRAM[0x1ff0]) + 0x100000; + + if (nBank != nNeo68KROMBank) + { + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2fdfff, SM_ROM); + } + } +} + +static void kf2k3blaInstallHandlers() +{ + NeoPVCInstallHandlers(); + + SekMapHandler(7, 0x2ffff0, 0x2fffff, SM_WRITE); + SekSetWriteWordHandler(7, kf2k3blaWriteWordBankswitch); +} + +static INT32 kf2k3blaInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x9D; + + NeoCallbackActive->pInitialise = kf2k3blaCallback; + + nRet = NeoPVCInit(); + + NeoCallbackActive->pInstallHandlers = kf2k3blaInstallHandlers; + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k3bla = { + "kf2k3bla", "kof2003", "neogeo", NULL, "2003", + "The King of Fighters 2003 (bootleg set 2)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k3blaRomInfo, kf2k3blaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k3blaInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2004 Plus / Hero (The King of Fighters 2003 bootleg) + +static struct BurnRomInfo kf2k3plRomDesc[] = { + { "2k3-p1pl.bin", 0x100000, 0x07b84112, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "2k3-p3bl.bin", 0x400000, 0x370acbff, 1 | BRF_ESS | BRF_PRG }, // 1 + { "2k3-p2bl.bin", 0x200000, 0x9c04fc52, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "2k3-s1pl.bin", 0x020000, 0xad548a36, 2 | BRF_GRA }, // 3 Text layer tiles + + { "271-c1c.c1", 0x800000, 0xb1dc25d0, 3 | BRF_GRA }, // 3 Sprite data + { "271-c2c.c2", 0x800000, 0xd5362437, 3 | BRF_GRA }, // 4 + { "271-c3c.c3", 0x800000, 0x0a1fbeab, 3 | BRF_GRA }, // 5 + { "271-c4c.c4", 0x800000, 0x87b19a0c, 3 | BRF_GRA }, // 6 + { "271-c5c.c5", 0x800000, 0x704ea371, 3 | BRF_GRA }, // 7 + { "271-c6c.c6", 0x800000, 0x20a1164c, 3 | BRF_GRA }, // 8 + { "271-c7c.c7", 0x800000, 0x189aba7f, 3 | BRF_GRA }, // 9 + { "271-c8c.c8", 0x800000, 0x20ec4fdc, 3 | BRF_GRA }, // 10 + + { "2k3-m1.bin", 0x020000, 0x3a4969ff, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 12 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k3pl, kf2k3pl, neogeo) +STD_ROM_FN(kf2k3pl) + +struct BurnDriver BurnDrvkf2k3pl = { + "kf2k3pl", "kof2003", "neogeo", NULL, "2003", + "The King of Fighters 2004 Plus / Hero (The King of Fighters 2003 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k3plRomInfo, kf2k3plRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k3blaInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// The King of Fighters 2004 Ultra Plus (The King of Fighters 2003 bootleg) + +static struct BurnRomInfo kf2k3uplRomDesc[] = { + { "2k3-p1up.bin", 0x800000, 0x87294c01, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "2k3-s1up.bin", 0x020000, 0xe5708c0c, 2 | BRF_GRA }, // 1 Text layer tiles + + { "271-c1c.c1", 0x800000, 0xb1dc25d0, 3 | BRF_GRA }, // 2 Sprite data + { "271-c2c.c2", 0x800000, 0xd5362437, 3 | BRF_GRA }, // 3 + { "271-c3c.c3", 0x800000, 0x0a1fbeab, 3 | BRF_GRA }, // 4 + { "271-c4c.c4", 0x800000, 0x87b19a0c, 3 | BRF_GRA }, // 5 + { "271-c5c.c5", 0x800000, 0x704ea371, 3 | BRF_GRA }, // 6 + { "271-c6c.c6", 0x800000, 0x20a1164c, 3 | BRF_GRA }, // 7 + { "271-c7c.c7", 0x800000, 0x189aba7f, 3 | BRF_GRA }, // 8 + { "271-c8c.c8", 0x800000, 0x20ec4fdc, 3 | BRF_GRA }, // 9 + + { "2k3-m1.bin", 0x020000, 0x3a4969ff, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "271-v1c.v1", 0x800000, 0xffa3f8c7, 5 | BRF_SND }, // 11 Sound data + { "271-v2c.v2", 0x800000, 0x5382c7d1, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kf2k3upl, kf2k3upl, neogeo) +STD_ROM_FN(kf2k3upl) + +static void kf2k3uplCallback() +{ + INT32 i, j; + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive, 0x600000); + memcpy (Neo68KROMActive, Neo68KROMActive + 0x700000, 0x100000); + + for(i = 0; i < 0x2000; i++) { + j = (i & 0x1f00) | BITSWAP08(i & 0xff, 7, 1, 5, 4, 3, 2, 6, 0) ; + Neo68KROMActive[0xfe000 + i] = Neo68KROMActive[0xd0610 + j]; + } + + garoubl_sx_decode(); +} + +static INT32 kof2k3uplInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x9D; + NeoCallbackActive->pInitialise = kf2k3uplCallback; + + nRet = NeoPVCInit(); + + NeoCallbackActive->pInstallHandlers = kf2k3blInstallHandlers; + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0xa7001, 0xff14ea, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k3upl = { + "kf2k3upl", "kof2003", "neogeo", NULL, "2003", + "The King of Fighters 2004 Ultra Plus (The King of Fighters 2003 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k3uplRomInfo, kf2k3uplRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2k3uplInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Samurai Shodown V Special / Samurai Spirits Zero Special (NGM-2720) + +static struct BurnRomInfo samsh5spRomDesc[] = { + { "272-p1.p1", 0x400000, 0xfb7a6bba, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "272-p2.sp2", 0x400000, 0x63492ea6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "272-c1.c1", 0x800000, 0x4f97661a, 3 | BRF_GRA }, // 2 Sprite data + { "272-c2.c2", 0x800000, 0xa3afda4f, 3 | BRF_GRA }, // 3 + { "272-c3.c3", 0x800000, 0x8c3c7502, 3 | BRF_GRA }, // 4 + { "272-c4.c4", 0x800000, 0x32d5e2e2, 3 | BRF_GRA }, // 5 + { "272-c5.c5", 0x800000, 0x6ce085bc, 3 | BRF_GRA }, // 6 + { "272-c6.c6", 0x800000, 0x05c8dc8e, 3 | BRF_GRA }, // 7 + { "272-c7.c7", 0x800000, 0x1417b742, 3 | BRF_GRA }, // 8 + { "272-c8.c8", 0x800000, 0xd49773cd, 3 | BRF_GRA }, // 9 + + { "272-m1.m1", 0x080000, 0xadeebf40, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "272-v1.v1", 0x800000, 0x76a94127, 5 | BRF_SND }, // 11 Sound data + { "272-v2.v2", 0x800000, 0x4ba507f1, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(samsh5sp, samsh5sp, neogeo) +STD_ROM_FN(samsh5sp) + +static void samsh5spCallback() +{ + PCM2DecryptP2Info Info = { 0x000000, 0x080000, 0x500000, 0x480000, 0x600000, 0x580000, 0x700000, 0x280000, 0x100000, 0x680000, 0x400000, 0x780000, 0x200000, 0x380000, 0x300000, 0x180000 }; + + PCM2DecryptP2(&Info); +} + +static INT32 samsh5spInit() +{ + INT32 nRet; + +// nNeoTextROMSize = 0x20000; + nNeoProtectionXor = 0x0D; + NeoCallbackActive->pInitialise = samsh5spCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + PCM2DecryptV2Info Info = { 0x02000, 0xffb440, { 0x4b, 0xa4, 0x63, 0x46, 0xf0, 0x91, 0xea, 0x62 } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvsamsh5sp = { + "samsh5sp", NULL, "neogeo", NULL, "2003", + "Samurai Shodown V Special / Samurai Spirits Zero Special (NGM-2720)\0", NULL, "Yuki Enterprise / SNK Playmore", "Neo Geo MVS", + L"Samurai Shodown V Special\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 Special (NGM-2720)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsh5spRomInfo, samsh5spRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsh5spInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Samurai Shodown V Special / Samurai Spirits Zero Special (NGH-2720) (1st release, censored) + +static struct BurnRomInfo samsh5sphRomDesc[] = { + { "272-p1c.p1", 0x400000, 0x9291794d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "272-p2c.sp2", 0x400000, 0xfa1a7dd8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "272-c1.c1", 0x800000, 0x4f97661a, 3 | BRF_GRA }, // 2 Sprite data + { "272-c2.c2", 0x800000, 0xa3afda4f, 3 | BRF_GRA }, // 3 + { "272-c3.c3", 0x800000, 0x8c3c7502, 3 | BRF_GRA }, // 4 + { "272-c4.c4", 0x800000, 0x32d5e2e2, 3 | BRF_GRA }, // 5 + { "272-c5.c5", 0x800000, 0x6ce085bc, 3 | BRF_GRA }, // 6 + { "272-c6.c6", 0x800000, 0x05c8dc8e, 3 | BRF_GRA }, // 7 + { "272-c7.c7", 0x800000, 0x1417b742, 3 | BRF_GRA }, // 8 + { "272-c8.c8", 0x800000, 0xd49773cd, 3 | BRF_GRA }, // 9 + + { "272-m1.m1", 0x080000, 0xadeebf40, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "272-v1.v1", 0x800000, 0x76a94127, 5 | BRF_SND }, // 11 Sound data + { "272-v2.v2", 0x800000, 0x4ba507f1, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(samsh5sph, samsh5sph, neogeo) +STD_ROM_FN(samsh5sph) + +struct BurnDriver BurnDrvsamsh5sph = { + "samsh5sph", "samsh5sp", "neogeo", NULL, "2003", + "Samurai Shodown V Special / Samurai Spirits Zero Special (NGH-2720) (1st release, censored)\0", NULL, "Yuki Enterprise / SNK Playmore", "Neo Geo MVS", + L"Samurai Shodown V Special\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 Special (NGH-2720) (1st release, censored)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsh5sphRomInfo, samsh5sphRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsh5spInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Samurai Shodown V Special / Samurai Spirits Zero Special (NGH-2720) (2nd release, less censored) + +static struct BurnRomInfo samsh5spnRomDesc[] = { + { "272-p1ca.p1", 0x400000, 0xc30a08dd, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "272-p2ca.sp2", 0x400000, 0xbd64a518, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "272-c1.c1", 0x800000, 0x4f97661a, 3 | BRF_GRA }, // 2 Sprite data + { "272-c2.c2", 0x800000, 0xa3afda4f, 3 | BRF_GRA }, // 3 + { "272-c3.c3", 0x800000, 0x8c3c7502, 3 | BRF_GRA }, // 4 + { "272-c4.c4", 0x800000, 0x32d5e2e2, 3 | BRF_GRA }, // 5 + { "272-c5.c5", 0x800000, 0x6ce085bc, 3 | BRF_GRA }, // 6 + { "272-c6.c6", 0x800000, 0x05c8dc8e, 3 | BRF_GRA }, // 7 + { "272-c7.c7", 0x800000, 0x1417b742, 3 | BRF_GRA }, // 8 + { "272-c8.c8", 0x800000, 0xd49773cd, 3 | BRF_GRA }, // 9 + + { "272-m1.m1", 0x080000, 0xadeebf40, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "272-v1.v1", 0x800000, 0x76a94127, 5 | BRF_SND }, // 11 Sound data + { "272-v2.v2", 0x800000, 0x4ba507f1, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(samsh5spn, samsh5spn, neogeo) +STD_ROM_FN(samsh5spn) + +struct BurnDriver BurnDrvsamsh5spn = { + "samsh5spn", "samsh5sp", "neogeo", NULL, "2003", + "Samurai Shodown V Special / Samurai Spirits Zero Special (NGH-2720) (2nd release, less censored)\0", NULL, "Yuki Enterprise / SNK Playmore", "Neo Geo MVS", + L"Samurai Shodown V Special\0\u30B5\u30E0\u30E9\u30A4\u30B9\u30D4\u30EA\u30C3\u30C4\u96F6 Special (NGH-2720) (2nd release, less censored)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_SAMSHO, + NULL, samsh5spnRomInfo, samsh5spnRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + samsh5spInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Magician Lord (NGM-005) + +static struct BurnRomInfo maglordRomDesc[] = { + { "005-pg1.p1", 0x080000, 0xbd0a492d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "005-s1.s1", 0x020000, 0x1c5369a2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "005-c1.c1", 0x080000, 0x806aee34, 3 | BRF_GRA }, // 2 Sprite data + { "005-c2.c2", 0x080000, 0x34aa9a86, 3 | BRF_GRA }, // 3 + { "005-c3.c3", 0x080000, 0xc4c2b926, 3 | BRF_GRA }, // 4 + { "005-c4.c4", 0x080000, 0x9c46dcf4, 3 | BRF_GRA }, // 5 + { "005-c5.c5", 0x080000, 0x69086dec, 3 | BRF_GRA }, // 6 + { "005-c6.c6", 0x080000, 0xab7ac142, 3 | BRF_GRA }, // 7 + + { "005-m1.m1", 0x040000, 0x26259f0f, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "005-v11.v11", 0x080000, 0xcc0455fd, 5 | BRF_SND }, // 9 Sound data + { "005-v21.v21", 0x080000, 0xf94ab5b7, 6 | BRF_SND }, // 10 + { "005-v22.v22", 0x080000, 0x232cfd04, 6 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(maglord, maglord, neogeo) +STD_ROM_FN(maglord) + +struct BurnDriver BurnDrvmaglord = { + "maglord", NULL, "neogeo", NULL, "1990", + "Magician Lord (NGM-005)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, maglordRomInfo, maglordRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Magician Lord (NGH-005) + +static struct BurnRomInfo maglordhRomDesc[] = { + { "005-p1.p1", 0x080000, 0x599043c5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "005-s1.s1", 0x020000, 0x1c5369a2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "005-c1.c1", 0x080000, 0x806aee34, 3 | BRF_GRA }, // 2 Sprite data + { "005-c2.c2", 0x080000, 0x34aa9a86, 3 | BRF_GRA }, // 3 + { "005-c3.c3", 0x080000, 0xc4c2b926, 3 | BRF_GRA }, // 4 + { "005-c4.c4", 0x080000, 0x9c46dcf4, 3 | BRF_GRA }, // 5 + { "005-c5.c5", 0x080000, 0x69086dec, 3 | BRF_GRA }, // 6 + { "005-c6.c6", 0x080000, 0xab7ac142, 3 | BRF_GRA }, // 7 + + { "005-m1.m1", 0x040000, 0x26259f0f, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "005-v11.v11", 0x080000, 0xcc0455fd, 5 | BRF_SND }, // 9 Sound data + { "005-v21.v21", 0x080000, 0xf94ab5b7, 6 | BRF_SND }, // 10 + { "005-v22.v22", 0x080000, 0x232cfd04, 6 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(maglordh, maglordh, neogeo) +STD_ROM_FN(maglordh) + +struct BurnDriver BurnDrvmaglordh = { + "maglordh", "maglord", "neogeo", NULL, "1990", + "Magician Lord (NGH-005)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, maglordhRomInfo, maglordhRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Ninja Combat (NGM-009) + +static struct BurnRomInfo ncombatRomDesc[] = { + { "009-p1.p1", 0x080000, 0xb45fcfbf, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "009-s1.s1", 0x020000, 0xd49afee8, 2 | BRF_GRA }, // 1 Text layer tiles + + { "009-c1.c1", 0x080000, 0x33cc838e, 3 | BRF_GRA }, // 2 Sprite data + { "009-c2.c2", 0x080000, 0x26877feb, 3 | BRF_GRA }, // 3 + { "009-c3.c3", 0x080000, 0x3b60a05d, 3 | BRF_GRA }, // 4 + { "009-c4.c4", 0x080000, 0x39c2d039, 3 | BRF_GRA }, // 5 + { "009-c5.c5", 0x080000, 0x67a4344e, 3 | BRF_GRA }, // 6 + { "009-c6.c6", 0x080000, 0x2eca8b19, 3 | BRF_GRA }, // 7 + + { "009-m1.m1", 0x020000, 0xb5819863, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "009-v11.v11", 0x080000, 0xcf32a59c, 5 | BRF_SND }, // 9 Sound data + { "009-v12.v12", 0x080000, 0x7b3588b7, 5 | BRF_SND }, // 10 + { "009-v13.v13", 0x080000, 0x505a01b5, 5 | BRF_SND }, // 11 + { "009-v21.v21", 0x080000, 0x365f9011, 6 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(ncombat, ncombat, neogeo) +STD_ROM_FN(ncombat) + +struct BurnDriver BurnDrvncombat = { + "ncombat", NULL, "neogeo", NULL, "1990", + "Ninja Combat (NGM-009)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, ncombatRomInfo, ncombatRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Ninja Combat (NGH-009) + +static struct BurnRomInfo ncombathRomDesc[] = { + { "009-pg1.p1", 0x080000, 0x8e9f0add, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "009-s1.s1", 0x020000, 0xd49afee8, 2 | BRF_GRA }, // 1 Text layer tiles + + { "009-c1.c1", 0x080000, 0x33cc838e, 3 | BRF_GRA }, // 2 Sprite data + { "009-c2.c2", 0x080000, 0x26877feb, 3 | BRF_GRA }, // 3 + { "009-c3.c3", 0x080000, 0x3b60a05d, 3 | BRF_GRA }, // 4 + { "009-c4.c4", 0x080000, 0x39c2d039, 3 | BRF_GRA }, // 5 + { "009-c5.c5", 0x080000, 0x67a4344e, 3 | BRF_GRA }, // 6 + { "009-c6.c6", 0x080000, 0x2eca8b19, 3 | BRF_GRA }, // 7 + + { "009-m1.m1", 0x020000, 0xb5819863, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "009-v11.v11", 0x080000, 0xcf32a59c, 5 | BRF_SND }, // 9 Sound data + { "009-v12.v12", 0x080000, 0x7b3588b7, 5 | BRF_SND }, // 10 + { "009-v13.v13", 0x080000, 0x505a01b5, 5 | BRF_SND }, // 11 + { "009-v21.v21", 0x080000, 0x365f9011, 6 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(ncombath, ncombath, neogeo) +STD_ROM_FN(ncombath) + +struct BurnDriver BurnDrvncombath = { + "ncombath", "ncombat", "neogeo", NULL, "1990", + "Ninja Combat (NGH-009)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, ncombathRomInfo, ncombathRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Blue's Journey / Raguy (ALM-001)(ALH-001) + +static struct BurnRomInfo bjourneyRomDesc[] = { + { "022-p1.p1", 0x100000, 0x6a2f6d4a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "022-s1.s1", 0x020000, 0x843c3624, 2 | BRF_GRA }, // 1 Text layer tiles + + { "022-c1.c1", 0x100000, 0x4d47a48c, 3 | BRF_GRA }, // 2 Sprite data + { "022-c2.c2", 0x100000, 0xe8c1491a, 3 | BRF_GRA }, // 3 + { "022-c3.c3", 0x080000, 0x66e69753, 3 | BRF_GRA }, // 4 + { "022-c4.c4", 0x080000, 0x71bfd48a, 3 | BRF_GRA }, // 5 + + { "022-m1.m1", 0x020000, 0x8e1d4ab6, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "022-v11.v11", 0x100000, 0x2cb4ad91, 5 | BRF_SND }, // 7 Sound data + { "022-v22.v22", 0x100000, 0x65a54d13, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(bjourney, bjourney, neogeo) +STD_ROM_FN(bjourney) + +struct BurnDriver BurnDrvbjourney = { + "bjourney", NULL, "neogeo", NULL, "1990", + "Blue's Journey / Raguy (ALM-001)(ALH-001)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, bjourneyRomInfo, bjourneyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, 0x1000, + 320, 224, 4, 3 +}; + +// Crossed Swords (ALM-002)(ALH-002) + +static struct BurnRomInfo crswordRomDesc[] = { + { "037-p1.p1", 0x080000, 0xe7f2553c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "037-s1.s1", 0x020000, 0x74651f27, 2 | BRF_GRA }, // 1 Text layer tiles + + { "037-c1.c1", 0x100000, 0x09df6892, 3 | BRF_GRA }, // 2 Sprite data + { "037-c2.c2", 0x100000, 0xac122a78, 3 | BRF_GRA }, // 3 + { "037-c3.c3", 0x100000, 0x9d7ed1ca, 3 | BRF_GRA }, // 4 + { "037-c4.c4", 0x100000, 0x4a24395d, 3 | BRF_GRA }, // 5 + + { "037-m1.m1", 0x020000, 0x9504b2c6, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "037-v1.v1", 0x100000, 0x61fedf65, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(crsword, crsword, neogeo) +STD_ROM_FN(crsword) + +struct BurnDriver BurnDrvcrsword = { + "crsword", NULL, "neogeo", NULL, "1991", + "Crossed Swords (ALM-002)(ALH-002)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, crswordRomInfo, crswordRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Thrash Rally (ALM-003)(ALH-003) + +static struct BurnRomInfo trallyRomDesc[] = { + { "038-p1.p1", 0x080000, 0x1e52a576, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "038-p2.p2", 0x080000, 0xa5193e2f, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "038-s1.s1", 0x020000, 0xfff62ae3, 2 | BRF_GRA }, // 2 Text layer tiles + + { "038-c1.c1", 0x100000, 0xc58323d4, 3 | BRF_GRA }, // 3 Sprite data + { "038-c2.c2", 0x100000, 0xbba9c29e, 3 | BRF_GRA }, // 4 + { "038-c3.c3", 0x080000, 0x3bb7b9d6, 3 | BRF_GRA }, // 5 + { "038-c4.c4", 0x080000, 0xa4513ecf, 3 | BRF_GRA }, // 6 + + { "038-m1.m1", 0x020000, 0x0908707e, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "038-v1.v1", 0x100000, 0x5ccd9fd5, 5 | BRF_SND }, // 8 Sound data + { "038-v2.v2", 0x080000, 0xddd8d1e6, 5 | BRF_SND }, // 9 + + { "hd6301v1p.hd6301v1", 0x001000, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + +STDROMPICKEXT(trally, trally, neogeo) +STD_ROM_FN(trally) + +struct BurnDriver BurnDrvtrally = { + "trally", NULL, "neogeo", NULL, "1991", + "Thrash Rally (ALM-003)(ALH-003)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_RACING, 0, + NULL, trallyRomInfo, trallyRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Ninja Commando + +static struct BurnRomInfo ncommandRomDesc[] = { + { "050-p1.p1", 0x100000, 0x4e097c40, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "050-s1.s1", 0x020000, 0xdb8f9c8e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "050-c1.c1", 0x100000, 0x87421a0a, 3 | BRF_GRA }, // 2 Sprite data + { "050-c2.c2", 0x100000, 0xc4cf5548, 3 | BRF_GRA }, // 3 + { "050-c3.c3", 0x100000, 0x03422c1e, 3 | BRF_GRA }, // 4 + { "050-c4.c4", 0x100000, 0x0845eadb, 3 | BRF_GRA }, // 5 + + { "050-m1.m1", 0x020000, 0x6fcf07d3, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "050-v1.v1", 0x100000, 0x23c3ab42, 5 | BRF_SND }, // 7 Sound data + { "050-v2.v2", 0x080000, 0x80b8a984, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(ncommand, ncommand, neogeo) +STD_ROM_FN(ncommand) + +struct BurnDriver BurnDrvncommand = { + "ncommand", NULL, "neogeo", NULL, "1992", + "Ninja Commando\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, ncommandRomInfo, ncommandRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// World Heroes (ALM-005) + +static struct BurnRomInfo wh1RomDesc[] = { + { "053-epr.p1", 0x080000, 0xd42e1e9a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "053-epr.p2", 0x080000, 0x0e33e8a3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "053-s1.s1", 0x020000, 0x8c2c2d6b, 2 | BRF_GRA }, // 2 Text layer tiles + + { "053-c1.c1", 0x200000, 0x85eb5bce, 3 | BRF_GRA }, // 3 Sprite data + { "053-c2.c2", 0x200000, 0xec93b048, 3 | BRF_GRA }, // 4 + { "053-c3.c3", 0x100000, 0x0dd64965, 3 | BRF_GRA }, // 5 + { "053-c4.c4", 0x100000, 0x9270d954, 3 | BRF_GRA }, // 6 + + { "053-m1.m1", 0x020000, 0x1bd9d04b, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "053-v2.v2", 0x200000, 0xa68df485, 5 | BRF_SND }, // 8 Sound data + { "053-v4.v4", 0x100000, 0x7bea8f66, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(wh1, wh1, neogeo) +STD_ROM_FN(wh1) + +struct BurnDriver BurnDrvwh1 = { + "wh1", NULL, "neogeo", NULL, "1992", + "World Heroes (ALM-005)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, wh1RomInfo, wh1RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + + +// World Heroes (ALH-005 + +static struct BurnRomInfo wh1hRomDesc[] = { + { "053-p1.p1", 0x080000, 0x95b574cb, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "053-p2.p2", 0x080000, 0xf198ed45, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "053-s1.s1", 0x020000, 0x8c2c2d6b, 2 | BRF_GRA }, // 2 Text layer tiles + + { "053-c1.c1", 0x200000, 0x85eb5bce, 3 | BRF_GRA }, // 3 Sprite data + { "053-c2.c2", 0x200000, 0xec93b048, 3 | BRF_GRA }, // 4 + { "053-c3.c3", 0x100000, 0x0dd64965, 3 | BRF_GRA }, // 5 + { "053-c4.c4", 0x100000, 0x9270d954, 3 | BRF_GRA }, // 6 + + { "053-m1.m1", 0x020000, 0x1bd9d04b, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "053-v2.v2", 0x200000, 0xa68df485, 5 | BRF_SND }, // 8 Sound data + { "053-v4.v4", 0x100000, 0x7bea8f66, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(wh1h, wh1h, neogeo) +STD_ROM_FN(wh1h) + +struct BurnDriver BurnDrvwh1h = { + "wh1h", "wh1", "neogeo", NULL, "1992", + "World Heroes (ALH-005\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, wh1hRomInfo, wh1hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + + +// World Heroes (set 3) + +static struct BurnRomInfo wh1haRomDesc[] = { + { "053-p1_a.p1", 0x080000, 0xed29fde2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "053-p2_a.p2", 0x080000, 0x98f2b158, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "053-s1.s1", 0x020000, 0x8c2c2d6b, 2 | BRF_GRA }, // 2 Text layer tiles + + { "053-c1.c1", 0x200000, 0x85eb5bce, 3 | BRF_GRA }, // 3 Sprite data + { "053-c2.c2", 0x200000, 0xec93b048, 3 | BRF_GRA }, // 4 + { "053-c3.c3", 0x100000, 0x0dd64965, 3 | BRF_GRA }, // 5 + { "053-c4.c4", 0x100000, 0x9270d954, 3 | BRF_GRA }, // 6 + + { "053-m1.m1", 0x020000, 0x1bd9d04b, 4 | BRF_ESS | BRF_PRG }, // 7 Z80 code + + { "053-v2.v2", 0x200000, 0xa68df485, 5 | BRF_SND }, // 8 Sound data + { "053-v4.v4", 0x100000, 0x7bea8f66, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(wh1ha, wh1ha, neogeo) +STD_ROM_FN(wh1ha) + +struct BurnDriver BurnDrvwh1ha = { + "wh1ha", "wh1", "neogeo", NULL, "1992", + "World Heroes (set 3)\0", NULL, "Alpha Denshi Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_VSFIGHT, 0, + NULL, wh1haRomInfo, wh1haRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// World Heroes 2 (ALM-006)(ALH-006) + +static struct BurnRomInfo wh2RomDesc[] = { + { "057-p1.p1", 0x200000, 0x65a891d9, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "057-s1.s1", 0x020000, 0xfcaeb3a4, 2 | BRF_GRA }, // 1 Text layer tiles + + { "057-c1.c1", 0x200000, 0x21c6bb91, 3 | BRF_GRA }, // 2 Sprite data + { "057-c2.c2", 0x200000, 0xa3999925, 3 | BRF_GRA }, // 3 + { "057-c3.c3", 0x200000, 0xb725a219, 3 | BRF_GRA }, // 4 + { "057-c4.c4", 0x200000, 0x8d96425e, 3 | BRF_GRA }, // 5 + { "057-c5.c5", 0x200000, 0xb20354af, 3 | BRF_GRA }, // 6 + { "057-c6.c6", 0x200000, 0xb13d1de3, 3 | BRF_GRA }, // 7 + + { "057-m1.m1", 0x020000, 0x8fa3bc77, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "057-v1.v1", 0x200000, 0x8877e301, 5 | BRF_SND }, // 9 Sound data + { "057-v2.v2", 0x200000, 0xc1317ff4, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(wh2, wh2, neogeo) +STD_ROM_FN(wh2) + +struct BurnDriver BurnDrvwh2 = { + "wh2", NULL, "neogeo", NULL, "1993", + "World Heroes 2 (ALM-006)(ALH-006)\0", NULL, "ADK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, wh2RomInfo, wh2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// World Heroes 2 Jet (ADM-007)(ADH-007) + +static struct BurnRomInfo wh2jRomDesc[] = { + { "064-p1.p1", 0x200000, 0x385a2e86, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "064-s1.s1", 0x020000, 0x2a03998a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "064-c1.c1", 0x200000, 0x2ec87cea, 3 | BRF_GRA }, // 2 Sprite data + { "064-c2.c2", 0x200000, 0x526b81ab, 3 | BRF_GRA }, // 3 + { "064-c3.c3", 0x200000, 0x436d1b31, 3 | BRF_GRA }, // 4 + { "064-c4.c4", 0x200000, 0xf9c8dd26, 3 | BRF_GRA }, // 5 + { "064-c5.c5", 0x200000, 0x8e34a9f4, 3 | BRF_GRA }, // 6 + { "064-c6.c6", 0x200000, 0xa43e4766, 3 | BRF_GRA }, // 7 + { "064-c7.c7", 0x200000, 0x59d97215, 3 | BRF_GRA }, // 8 + { "064-c8.c8", 0x200000, 0xfc092367, 3 | BRF_GRA }, // 9 + + { "064-m1.m1", 0x020000, 0xd2eec9d3, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "064-v1.v1", 0x200000, 0xaa277109, 5 | BRF_SND }, // 7 Sound data + { "064-v2.v2", 0x200000, 0xb6527edd, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(wh2j, wh2j, neogeo) +STD_ROM_FN(wh2j) + +struct BurnDriver BurnDrvwh2j = { + "wh2j", NULL, "neogeo", NULL, "1994", + "World Heroes 2 Jet (ADM-007)(ADH-007)\0", NULL, "ADK / SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, wh2jRomInfo, wh2jRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Aggressors of Dark Kombat / Tsuukai GANGAN Koushinkyoku (ADM-008)(ADH-008) + +static struct BurnRomInfo aodkRomDesc[] = { + { "074-p1.p1", 0x200000, 0x62369553, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "074-s1.s1", 0x020000, 0x96148d2b, 2 | BRF_GRA }, // 1 Text layer tiles + + { "074-c1.c1", 0x200000, 0xa0b39344, 3 | BRF_GRA }, // 2 Sprite data + { "074-c2.c2", 0x200000, 0x203f6074, 3 | BRF_GRA }, // 3 + { "074-c3.c3", 0x200000, 0x7fff4d41, 3 | BRF_GRA }, // 4 + { "074-c4.c4", 0x200000, 0x48db3e0a, 3 | BRF_GRA }, // 5 + { "074-c5.c5", 0x200000, 0xc74c5e51, 3 | BRF_GRA }, // 6 + { "074-c6.c6", 0x200000, 0x73e8e7e0, 3 | BRF_GRA }, // 7 + { "074-c7.c7", 0x200000, 0xac7daa01, 3 | BRF_GRA }, // 8 + { "074-c8.c8", 0x200000, 0x14e7ad71, 3 | BRF_GRA }, // 9 + + { "074-m1.m1", 0x020000, 0x5a52a9d1, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "074-v1.v1", 0x200000, 0x7675b8fa, 5 | BRF_SND }, // 11 Sound data + { "074-v2.v2", 0x200000, 0xa9da86e9, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(aodk, aodk, neogeo) +STD_ROM_FN(aodk) + +struct BurnDriver BurnDrvaodk = { + "aodk", NULL, "neogeo", NULL, "1994", + "Aggressors of Dark Kombat / Tsuukai GANGAN Koushinkyoku (ADM-008)(ADH-008)\0", NULL, "ADK / SNK", "Neo Geo MVS", + L"Aggressors of Dark Kombat\0\u75DB\u5FEB\uFF27\uFF41\uFF4E\uFF47\uFF41\uFF4E\u884C\u9032\u66F2 (ADM-008)(ADH-008)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, aodkRomInfo, aodkRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// World Heroes Perfect + +static struct BurnRomInfo whpRomDesc[] = { + { "090-p1.p1", 0x200000, 0xafaa4702, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "090-s1.s1", 0x020000, 0x174a880f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "090-c1.c1", 0x400000, 0xcd30ed9b, 3 | BRF_GRA }, // 2 Sprite data + { "090-c2.c2", 0x400000, 0x10eed5ee, 3 | BRF_GRA }, // 3 + { "064-c3.c3", 0x200000, 0x436d1b31, 3 | BRF_GRA }, // 4 + { "064-c4.c4", 0x200000, 0xf9c8dd26, 3 | BRF_GRA }, // 5 + { "064-c5.c5", 0x200000, 0x8e34a9f4, 3 | BRF_GRA }, // 6 + { "064-c6.c6", 0x200000, 0xa43e4766, 3 | BRF_GRA }, // 7 + { "064-c7.c7", 0x200000, 0x59d97215, 3 | BRF_GRA }, // 8 + { "064-c8.c8", 0x200000, 0xfc092367, 3 | BRF_GRA }, // 9 + + { "090-m1.m1", 0x020000, 0x28065668, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "090-v1.v1", 0x200000, 0x30cf2709, 5 | BRF_SND }, // 11 Sound data + { "064-v2.v2", 0x200000, 0xb6527edd, 5 | BRF_SND }, // 12 + { "090-v3.v3", 0x200000, 0x1908a7ce, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(whp, whp, neogeo) +STD_ROM_FN(whp) + +struct BurnDriver BurnDrvwhp = { + "whp", NULL, "neogeo", NULL, "1995", + "World Heroes Perfect\0", NULL, "ADK / SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, whpRomInfo, whpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Syougi No Tatsujin - Master of Syougi + +static struct BurnRomInfo mosyougiRomDesc[] = { + { "203-p1.p1", 0x100000, 0x7ba70e2d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "203-s1.s1", 0x020000, 0xbfdc8309, 2 | BRF_GRA }, // 1 Text layer tiles + + { "203-c1.c1", 0x200000, 0xbba9e8c0, 3 | BRF_GRA }, // 2 Sprite data + { "203-c2.c2", 0x200000, 0x2574be03, 3 | BRF_GRA }, // 3 + + { "203-m1.m1", 0x020000, 0xa602c2c2, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "203-v1.v1", 0x200000, 0xbaa2b9a5, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(mosyougi, mosyougi, neogeo) +STD_ROM_FN(mosyougi) + +struct BurnDriver BurnDrvmosyougi = { + "mosyougi", NULL, "neogeo", NULL, "1995", + "Syougi No Tatsujin - Master of Syougi\0", NULL, "ADK / SNK", "Neo Geo MVS", + L"\u5C06\u68CB\u306E\u9054\u4EBA\0Master of Syougi\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, mosyougiRomInfo, mosyougiRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Over Top + +static struct BurnRomInfo overtopRomDesc[] = { + { "212-p1.p1", 0x200000, 0x16c063a9, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "212-s1.s1", 0x020000, 0x481d3ddc, 2 | BRF_GRA }, // 1 Text layer tiles + + { "212-c1.c1", 0x400000, 0x50f43087, 3 | BRF_GRA }, // 2 Sprite data + { "212-c2.c2", 0x400000, 0xa5b39807, 3 | BRF_GRA }, // 3 + { "212-c3.c3", 0x400000, 0x9252ea02, 3 | BRF_GRA }, // 4 + { "212-c4.c4", 0x400000, 0x5f41a699, 3 | BRF_GRA }, // 5 + { "212-c5.c5", 0x200000, 0xfc858bef, 3 | BRF_GRA }, // 6 + { "212-c6.c6", 0x200000, 0x0589c15e, 3 | BRF_GRA }, // 7 + + { "212-m1.m1", 0x020000, 0xfcab6191, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "212-v1.v1", 0x400000, 0x013d4ef9, 5 | BRF_SND }, // 9 Sound data +}; + +STDROMPICKEXT(overtop, overtop, neogeo) +STD_ROM_FN(overtop) + +struct BurnDriver BurnDrvovertop = { + "overtop", NULL, "neogeo", NULL, "1996", + "Over Top\0", NULL, "ADK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_RACING, 0, + NULL, overtopRomInfo, overtopRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ninja Master's - haoh-ninpo-cho + +static struct BurnRomInfo ninjamasRomDesc[] = { + { "217-p1.p1", 0x100000, 0x3e97ed69, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "217-p2.sp2", 0x200000, 0x191fca88, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "217-s1.s1", 0x020000, 0x8ff782f0, 2 | BRF_GRA }, // 2 Text layer tiles + + { "217-c1.c1", 0x400000, 0x5fe97bc4, 3 | BRF_GRA }, // 3 Sprite data + { "217-c2.c2", 0x400000, 0x886e0d66, 3 | BRF_GRA }, // 4 + { "217-c3.c3", 0x400000, 0x59e8525f, 3 | BRF_GRA }, // 5 + { "217-c4.c4", 0x400000, 0x8521add2, 3 | BRF_GRA }, // 6 + { "217-c5.c5", 0x400000, 0xfb1896e5, 3 | BRF_GRA }, // 7 + { "217-c6.c6", 0x400000, 0x1c98c54b, 3 | BRF_GRA }, // 8 + { "217-c7.c7", 0x400000, 0x8b0ede2e, 3 | BRF_GRA }, // 9 + { "217-c8.c8", 0x400000, 0xa085bb61, 3 | BRF_GRA }, // 10 + + { "217-m1.m1", 0x020000, 0xd00fb2af, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "217-v1.v1", 0x400000, 0x1c34e013, 5 | BRF_SND }, // 12 Sound data + { "217-v2.v2", 0x200000, 0x22f1c681, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(ninjamas, ninjamas, neogeo) +STD_ROM_FN(ninjamas) + +struct BurnDriver BurnDrvninjamas = { + "ninjamas", NULL, "neogeo", NULL, "1996", + "Ninja Master's - haoh-ninpo-cho\0", NULL, "ADK / SNK", "Neo Geo MVS", + L"Ninja master's \u8987\u738B\u5FCD\u6CD5\u5E16\0Ninja Master's haoh ninpo cho\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, ninjamasRomInfo, ninjamasRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Twinkle Star Sprites + +static struct BurnRomInfo twinspriRomDesc[] = { + { "224-p1.p1", 0x200000, 0x7697e445, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "224-s1.s1", 0x020000, 0xeeed5758, 2 | BRF_GRA }, // 1 Text layer tiles + + { "224-c1.c1", 0x400000, 0xf7da64ab, 3 | BRF_GRA }, // 2 Sprite data + { "224-c2.c2", 0x400000, 0x4c09bbfb, 3 | BRF_GRA }, // 3 + { "224-c3.c3", 0x100000, 0xc59e4129, 3 | BRF_GRA }, // 4 + { "224-c4.c4", 0x100000, 0xb5532e53, 3 | BRF_GRA }, // 5 + + { "224-m1.m1", 0x020000, 0x364d6f96, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "224-v1.v1", 0x400000, 0xff57f088, 5 | BRF_SND }, // 7 Sound data + { "224-v2.v2", 0x200000, 0x7ad26599, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(twinspri, twinspri, neogeo) +STD_ROM_FN(twinspri) + +struct BurnDriver BurnDrvtwinspri = { + "twinspri", NULL, "neogeo", NULL, "1996", + "Twinkle Star Sprites\0", NULL, "ADK", "Neo Geo MVS", + L"TwinkleStar Sprites\0\u30C6\u30A3\u30F3\u30AF\u30EB\u30B9\u30BF\u30FC\u30B9\u30D7\u30E9\u30A4\u30C4\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VERSHOOT, 0, + NULL, twinspriRomInfo, twinspriRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Zintrick / Oshidashi Zentrix (hack / bootleg) + +static struct BurnRomInfo zintrckbRomDesc[] = { + { "zin-p1.bin", 0x100000, 0x06c8fca7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "zin-s1.bin", 0x020000, 0xa7ab0e81, 2 | BRF_GRA }, // 1 Text layer tiles + + { "zin-c1.bin", 0x200000, 0x76aee189, 3 | BRF_GRA }, // 2 Sprite data + { "zin-c2.bin", 0x200000, 0x844ed4b3, 3 | BRF_GRA }, // 3 + + { "zin-m1.bin", 0x020000, 0xfd9627ca, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "zin-v1.bin", 0x200000, 0xc09f74f1, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(zintrckb, zintrckb, neogeo) +STD_ROM_FN(zintrckb) + +struct BurnDriver BurnDrvzintrckb = { + "zintrckb", NULL, "neogeo", NULL, "1996", + "Zintrick / Oshidashi Zentrix (hack / bootleg)\0", NULL, "hack / bootleg", "Neo Geo MVS", + L"Zintrick\0\u62BC\u3057\u51FA\u3057\u30B8\u30F3\u30C8\u30EA\u30C3\u30AF (hack / bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, zintrckbRomInfo, zintrckbRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Viewpoint + +static struct BurnRomInfo viewpoinRomDesc[] = { + { "051-p1.p1", 0x100000, 0x17aa899d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "051-s1.s1", 0x020000, 0x9fea5758, 2 | BRF_GRA }, // 1 Text layer tiles + + { "051-c1.c1", 0x200000, 0xd624c132, 3 | BRF_GRA }, // 2 Sprite data + { "051-c2.c2", 0x200000, 0x40d69f1e, 3 | BRF_GRA }, // 3 + + { "051-m1.m1", 0x020000, 0x8e69f29a, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "051-v2.v2", 0x200000, 0x019978b6, 5 | BRF_SND }, // 5 Sound data + { "051-v4.v4", 0x200000, 0x5758f38c, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(viewpoin, viewpoin, neogeo) +STD_ROM_FN(viewpoin) + +struct BurnDriver BurnDrvviewpoin = { + "viewpoin", NULL, "neogeo", NULL, "1992", + "Viewpoint\0", NULL, "Sammy / Aicom", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPC, GBF_SHOOT, 0, + NULL, viewpoinRomInfo, viewpoinRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Jyanshin Densetsu - Quest of Jongmaster + +static struct BurnRomInfo janshinRomDesc[] = { + { "048-p1.p1", 0x100000, 0xfa818cbb, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "048-s1.s1", 0x020000, 0x8285b25a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "048-c1.c1", 0x200000, 0x3fa890e9, 3 | BRF_GRA }, // 2 Sprite data + { "048-c2.c1", 0x200000, 0x59c48ad8, 3 | BRF_GRA }, // 3 + + { "048-m1.m1", 0x020000, 0x310467c7, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "048-v1.v1", 0x200000, 0xf1947d2b, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(janshin, janshin, neogeo) +STD_ROM_FN(janshin) + +struct BurnDriver BurnDrvjanshin = { + "janshin", NULL, "neogeo", NULL, "1994", + "Jyanshin Densetsu - Quest of Jongmaster\0", NULL, "Aicom", "Neo Geo MVS", + L"\u96C0\u795E\u4F1D\u8AAC - quest of jongmaster\0Jyanshin Densetsu\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_MAHJONG, GBF_MAHJONG, 0, + NULL, janshinRomInfo, janshinRomName, NULL, NULL, neomahjongInputInfo, neomahjongDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Pulstar + +static struct BurnRomInfo pulstarRomDesc[] = { + { "089-p1.p1", 0x100000, 0x5e5847a2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "089-p2.sp2", 0x200000, 0x028b774c, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "089-s1.s1", 0x020000, 0xc79fc2c8, 2 | BRF_GRA }, // 2 Text layer tiles + + { "089-c1.c1", 0x400000, 0xf4e97332, 3 | BRF_GRA }, // 3 Sprite data + { "089-c2.c2", 0x400000, 0x836d14da, 3 | BRF_GRA }, // 4 + { "089-c3.c3", 0x400000, 0x913611c4, 3 | BRF_GRA }, // 5 + { "089-c4.c4", 0x400000, 0x44cef0e3, 3 | BRF_GRA }, // 6 + { "089-c5.c5", 0x400000, 0x89baa1d7, 3 | BRF_GRA }, // 7 + { "089-c6.c6", 0x400000, 0xb2594d56, 3 | BRF_GRA }, // 8 + { "089-c7.c7", 0x200000, 0x6a5618ca, 3 | BRF_GRA }, // 9 + { "089-c8.c8", 0x200000, 0xa223572d, 3 | BRF_GRA }, // 10 + + { "089-m1.m1", 0x020000, 0xff3df7c7, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "089-v1.v1", 0x400000, 0x6f726ecb, 5 | BRF_SND }, // 12 Sound data + { "089-v2.v2", 0x400000, 0x9d2db551, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(pulstar, pulstar, neogeo) +STD_ROM_FN(pulstar) + +struct BurnDriver BurnDrvpulstar = { + "pulstar", NULL, "neogeo", NULL, "1995", + "Pulstar\0", NULL, "Aicom", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0, + NULL, pulstarRomInfo, pulstarRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Blazing Star + +static struct BurnRomInfo blazstarRomDesc[] = { + { "239-p1.p1", 0x100000, 0x183682f8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "239-p2.sp2", 0x200000, 0x9a9f4154, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "239-s1.s1", 0x020000, 0xd56cb498, 2 | BRF_GRA }, // 2 Text layer tiles + + { "239-c1.c1", 0x400000, 0x84f6d584, 3 | BRF_GRA }, // 3 Sprite data + { "239-c2.c2", 0x400000, 0x05a0cb22, 3 | BRF_GRA }, // 4 + { "239-c3.c3", 0x400000, 0x5fb69c9e, 3 | BRF_GRA }, // 5 + { "239-c4.c4", 0x400000, 0x0be028c4, 3 | BRF_GRA }, // 6 + { "239-c5.c5", 0x400000, 0x74bae5f8, 3 | BRF_GRA }, // 7 + { "239-c6.c6", 0x400000, 0x4e0700d2, 3 | BRF_GRA }, // 8 + { "239-c7.c7", 0x400000, 0x010ff4fd, 3 | BRF_GRA }, // 9 + { "239-c8.c8", 0x400000, 0xdb60460e, 3 | BRF_GRA }, // 10 + + { "239-m1.m1", 0x020000, 0xd31a3aea, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "239-v1.v1", 0x400000, 0x1b8d5bf7, 5 | BRF_SND }, // 12 Sound data + { "239-v2.v2", 0x400000, 0x74cf0a70, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(blazstar, blazstar, neogeo) +STD_ROM_FN(blazstar) + +struct BurnDriver BurnDrvblazstar = { + "blazstar", NULL, "neogeo", NULL, "1998", + "Blazing Star\0", NULL, "Yumekobo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0, + NULL, blazstarRomInfo, blazstarRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Prehistoric Isle 2 + +static struct BurnRomInfo preisle2RomDesc[] = { + { "255-p1.p1", 0x100000, 0xdfa3c0f3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "255-p2.sp2", 0x400000, 0x42050b80, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "255-c1.c1", 0x800000, 0xea06000b, 3 | BRF_GRA }, // 2 Sprite data + { "255-c2.c2", 0x800000, 0x04e67d79, 3 | BRF_GRA }, // 3 + { "255-c3.c3", 0x800000, 0x60e31e08, 3 | BRF_GRA }, // 4 + { "255-c4.c4", 0x800000, 0x40371d69, 3 | BRF_GRA }, // 5 + { "255-c5.c5", 0x800000, 0x0b2e6adf, 3 | BRF_GRA }, // 6 + { "255-c6.c6", 0x800000, 0xb001bdd3, 3 | BRF_GRA }, // 7 + + { "255-m1.m1", 0x020000, 0x8efd4014, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "255-v1.v1", 0x400000, 0x5a14543d, 5 | BRF_SND }, // 9 Sound data + { "255-v2.v2", 0x200000, 0x6610d91a, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(preisle2, preisle2, neogeo) +STD_ROM_FN(preisle2) + +INT32 preisle2Init() +{ + nNeoProtectionXor = 0x9F; + return NeoInit(); +} + +struct BurnDriver BurnDrvpreisle2 = { + "preisle2", NULL, "neogeo", NULL, "1999", + "Prehistoric Isle 2\0", NULL, "Yumekobo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_HORSHOOT, 0, + NULL, preisle2RomInfo, preisle2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + preisle2Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Spin Master / Miracle Adventure + +static struct BurnRomInfo spinmastRomDesc[] = { + { "062-p1.p1", 0x100000, 0x37aba1aa, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "062-p2.sp2", 0x100000, 0xf025ab77, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "062-s1.s1", 0x020000, 0x289e2bbe, 2 | BRF_GRA }, // 2 Text layer tiles + + { "062-c1.c1", 0x100000, 0xa9375aa2, 3 | BRF_GRA }, // 3 Sprite data + { "062-c2.c2", 0x100000, 0x0e73b758, 3 | BRF_GRA }, // 4 + { "062-c3.c3", 0x100000, 0xdf51e465, 3 | BRF_GRA }, // 5 + { "062-c4.c4", 0x100000, 0x38517e90, 3 | BRF_GRA }, // 6 + { "062-c5.c5", 0x100000, 0x7babd692, 3 | BRF_GRA }, // 7 + { "062-c6.c6", 0x100000, 0xcde5ade5, 3 | BRF_GRA }, // 8 + { "062-c7.c7", 0x100000, 0xbb2fd7c0, 3 | BRF_GRA }, // 9 + { "062-c8.c8", 0x100000, 0x8d7be933, 3 | BRF_GRA }, // 10 + + { "062-m1.m1", 0x020000, 0x76108b2f, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "062-v1.v1", 0x100000, 0xcc281aef, 5 | BRF_SND }, // 12 Sound data +}; + +STDROMPICKEXT(spinmast, spinmast, neogeo) +STD_ROM_FN(spinmast) + +struct BurnDriver BurnDrvspinmast = { + "spinmast", NULL, "neogeo", NULL, "1993", + "Spin Master / Miracle Adventure\0", NULL, "Data East Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, spinmastRomInfo, spinmastRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Windjammers / Flying Power Disc + +static struct BurnRomInfo wjammersRomDesc[] = { + { "065-p1.p1", 0x100000, 0x6692c140, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "065-s1.s1", 0x020000, 0x074b5723, 2 | BRF_GRA }, // 1 Text layer tiles + + { "065-c1.c1", 0x100000, 0xc7650204, 3 | BRF_GRA }, // 2 Sprite data + { "065-c2.c2", 0x100000, 0xd9f3e71d, 3 | BRF_GRA }, // 3 + { "065-c3.c3", 0x100000, 0x40986386, 3 | BRF_GRA }, // 4 + { "065-c4.c4", 0x100000, 0x715e15ff, 3 | BRF_GRA }, // 5 + + { "065-m1.m1", 0x020000, 0x52c23cfc, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "065-v1.v1", 0x100000, 0xce8b3698, 5 | BRF_SND }, // 7 Sound data + { "065-v2.v2", 0x100000, 0x659f9b96, 5 | BRF_SND }, // 8 + { "065-v3.v3", 0x100000, 0x39f73061, 5 | BRF_SND }, // 9 + { "065-v4.v4", 0x100000, 0x5dee7963, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(wjammers, wjammers, neogeo) +STD_ROM_FN(wjammers) + +struct BurnDriver BurnDrvwjammers = { + "wjammers", NULL, "neogeo", NULL, "1994", + "Windjammers / Flying Power Disc\0", NULL, "Data East Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, wjammersRomInfo, wjammersRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Karnov's Revenge / Fighter's History Dynamite + +static struct BurnRomInfo karnovrRomDesc[] = { + { "066-p1.p1", 0x100000, 0x8c86fd22, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "066-s1.s1", 0x020000, 0xbae5d5e5, 2 | BRF_GRA }, // 1 Text layer tiles + + { "066-c1.c1", 0x200000, 0x09dfe061, 3 | BRF_GRA }, // 2 Sprite data + { "066-c2.c2", 0x200000, 0xe0f6682a, 3 | BRF_GRA }, // 3 + { "066-c3.c3", 0x200000, 0xa673b4f7, 3 | BRF_GRA }, // 4 + { "066-c4.c4", 0x200000, 0xcb3dc5f4, 3 | BRF_GRA }, // 5 + { "066-c5.c5", 0x200000, 0x9a28785d, 3 | BRF_GRA }, // 6 + { "066-c6.c6", 0x200000, 0xc15c01ed, 3 | BRF_GRA }, // 7 + + { "066-m1.m1", 0x020000, 0x030beae4, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "066-v1.v1", 0x200000, 0x0b7ea37a, 5 | BRF_SND }, // 9 Sound data +}; + +STDROMPICKEXT(karnovr, karnovr, neogeo) +STD_ROM_FN(karnovr) + +struct BurnDriver BurnDrvkarnovr = { + "karnovr", NULL, "neogeo", NULL, "1994", + "Karnov's Revenge / Fighter's History Dynamite\0", NULL, "Data East Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, karnovrRomInfo, karnovrRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Street Hoop / Street Slam / Dunk Dream (DEM-004) (DEH-004) + +static struct BurnRomInfo strhoopRomDesc[] = { + { "079-p1.p1", 0x100000, 0x5e78328e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "079-s1.s1", 0x020000, 0x3ac06665, 2 | BRF_GRA }, // 1 Text layer tiles + + { "079-c1.c1", 0x200000, 0x0581c72a, 3 | BRF_GRA }, // 2 Sprite data + { "079-c2.c2", 0x200000, 0x5b9b8fb6, 3 | BRF_GRA }, // 3 + { "079-c3.c3", 0x200000, 0xcd65bb62, 3 | BRF_GRA }, // 4 + { "079-c4.c4", 0x200000, 0xa4c90213, 3 | BRF_GRA }, // 5 + + { "079-m1.m1", 0x020000, 0xbee3455a, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "079-v1.v1", 0x200000, 0x718a2400, 5 | BRF_SND }, // 7 Sound data + { "079-v2.v2", 0x100000, 0x720774eb, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(strhoop, strhoop, neogeo) +STD_ROM_FN(strhoop) + +struct BurnDriver BurnDrvstrhoop = { + "strhoop", NULL, "neogeo", NULL, "1994", + "Street Hoop / Street Slam / Dunk Dream (DEM-004) (DEH-004)\0", NULL, "Data East Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, strhoopRomInfo, strhoopRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ghostlop (prototype) + +static struct BurnRomInfo ghostlopRomDesc[] = { + { "228-p1p.p1", 0x100000, 0x6033172e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "228-s1p.s1", 0x020000, 0x83c24e81, 2 | BRF_GRA }, // 1 Text layer tiles + + { "228-c1p.c1", 0x400000, 0xbfc99efe, 3 | BRF_GRA }, // 2 Sprite data + { "228-c2p.c2", 0x400000, 0x69788082, 3 | BRF_GRA }, // 3 + + { "228-m1p.m1", 0x020000, 0xfd833b33, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "228-v1p.v1", 0x200000, 0xc603fce6, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(ghostlop, ghostlop, neogeo) +STD_ROM_FN(ghostlop) + +struct BurnDriver BurnDrvghostlop = { + "ghostlop", NULL, "neogeo", NULL, "1996", + "Ghostlop (prototype)\0", NULL, "Data East Corporation", "Neo Geo MVS", + L"Ghostlop \u30B4\u30FC\u30B9\u30C8\u30ED\u30C3\u30D7 (prototype)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, ghostlopRomInfo, ghostlopRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Magical Drop II + +static struct BurnRomInfo magdrop2RomDesc[] = { + { "221-p1.p1", 0x080000, 0x7be82353, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "221-s1.s1", 0x020000, 0x2a4063a3, 2 | BRF_GRA }, // 1 Text layer tiles + + { "221-c1.c1", 0x400000, 0x1f862a14, 3 | BRF_GRA }, // 2 Sprite data + { "221-c2.c2", 0x400000, 0x14b90536, 3 | BRF_GRA }, // 3 + + { "221-m1.m1", 0x020000, 0xbddae628, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "221-v1.v1", 0x200000, 0x7e5e53e4, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(magdrop2, magdrop2, neogeo) +STD_ROM_FN(magdrop2) + +struct BurnDriver BurnDrvmagdrop2 = { + "magdrop2", NULL, "neogeo", NULL, "1996", + "Magical Drop II\0", NULL, "Data East Corporation", "Neo Geo MVS", + L"Magical Drop II\0\u30DE\u30B8\u30AB\u30EB\u30C9\u30ED\u30C3\u30D7\uFF12\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, magdrop2RomInfo, magdrop2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Magical Drop III + +static struct BurnRomInfo magdrop3RomDesc[] = { + { "233-p1.p1", 0x100000, 0x931e17fa, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "233-s1.s1", 0x020000, 0x7399e68a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "233-c1.c1", 0x400000, 0x65e3f4c4, 3 | BRF_GRA }, // 2 Sprite data + { "233-c2.c2", 0x400000, 0x35dea6c9, 3 | BRF_GRA }, // 3 + { "233-c3.c3", 0x400000, 0x0ba2c502, 3 | BRF_GRA }, // 4 + { "233-c4.c4", 0x400000, 0x70dbbd6d, 3 | BRF_GRA }, // 5 + + { "233-m1.m1", 0x020000, 0x5beaf34e, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "233-v1.v1", 0x400000, 0x58839298, 5 | BRF_SND }, // 7 Sound data + { "233-v2.v2", 0x080000, 0xd5e30df4, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(magdrop3, magdrop3, neogeo) +STD_ROM_FN(magdrop3) + +struct BurnDriver BurnDrvmagdrop3 = { + "magdrop3", NULL, "neogeo", NULL, "1997", + "Magical Drop III\0", NULL, "Data East Corporation", "Neo Geo MVS", + L"Magical Drop III\0\u30DE\u30B8\u30AB\u30EB\u30C9\u30ED\u30C3\u30D7III\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, magdrop3RomInfo, magdrop3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Nightmare in the Dark + +static struct BurnRomInfo nitdRomDesc[] = { + { "260-p1.p1", 0x080000, 0x61361082, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "260-c1.c1", 0x800000, 0x147b0c7f, 3 | BRF_GRA }, // 1 Sprite data + { "260-c2.c2", 0x800000, 0xd2b04b0d, 3 | BRF_GRA }, // 2 + + { "260-m1.m1", 0x080000, 0x6407c5e5, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "260-v1.v1", 0x400000, 0x24b0480c, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(nitd, nitd, neogeo) +STD_ROM_FN(nitd) + +INT32 nitdInit() +{ + nNeoProtectionXor = 0xFF; + return NeoInit(); +} + +struct BurnDriver BurnDrvnitd = { + "nitd", NULL, "neogeo", NULL, "2000", + "Nightmare in the Dark\0", NULL, "Eleven / Gavaking", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_PLATFORM, 0, + NULL, nitdRomInfo, nitdRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + nitdInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + + +// Nightmare in the Dark (bootleg) + +static struct BurnRomInfo nitdblRomDesc[] = { + { "nitd-p1.bin", 0x080000, 0x1a05bd1b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "nitd-s1.bin", 0x020000, 0xdd3bf47c, 2 | BRF_GRA }, // 1 Text layer tiles + + { "nitd-c1.bin", 0x200000, 0xb4353190, 3 | BRF_GRA }, // 2 Sprite data + { "nitd-c2.bin", 0x200000, 0x6e27511f, 3 | BRF_GRA }, // 3 + { "nitd-c3.bin", 0x200000, 0x472cf075, 3 | BRF_GRA }, // 4 + { "nitd-c4.bin", 0x200000, 0x4c3926e6, 3 | BRF_GRA }, // 5 + + { "260-m1.m1", 0x080000, 0x6407c5e5, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "nitd-v1.bin", 0x200000, 0x79008868, 5 | BRF_SND }, // 7 Sound data + { "nitd-v2.bin", 0x200000, 0x728558f9, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(nitdbl, nitdbl, neogeo) +STD_ROM_FN(nitdbl) + +struct BurnDriver BurnDrvnitdbl = { + "nitdbl", "nitd", "neogeo", NULL, "2001", + "Nightmare in the Dark (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, nitdblRomInfo, nitdblRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Gururin + +static struct BurnRomInfo gururinRomDesc[] = { + { "067-p1.p1", 0x080000, 0x4cea8a49, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "067-s1.s1", 0x020000, 0xb119e1eb, 2 | BRF_GRA }, // 1 Text layer tiles + + { "067-c1.c1", 0x200000, 0x35866126, 3 | BRF_GRA }, // 2 Sprite data + { "067-c2.c2", 0x200000, 0x9db64084, 3 | BRF_GRA }, // 3 + + { "067-m1.m1", 0x020000, 0x9e3c6328, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "067-v1.v1", 0x080000, 0xcf23afd0, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(gururin, gururin, neogeo) +STD_ROM_FN(gururin) + +struct BurnDriver BurnDrvgururin = { + "gururin", NULL, "neogeo", NULL, "1994", + "Gururin\0", NULL, "Face", "Neo Geo MVS", + L"\u3050\u308B\u308A\u3093\0Gururin\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, gururinRomInfo, gururinRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Money Puzzle Exchanger / Money Idol Exchanger + +static struct BurnRomInfo miexchngRomDesc[] = { + { "231-p1.p1", 0x080000, 0x61be1810, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "231-s1.s1", 0x020000, 0xfe0c0c53, 2 | BRF_GRA }, // 1 Text layer tiles + + { "231-c1.c1", 0x200000, 0x6c403ba3, 3 | BRF_GRA }, // 2 Sprite data + { "231-c2.c2", 0x200000, 0x554bcd9b, 3 | BRF_GRA }, // 3 + { "231-c3.c3", 0x100000, 0x4f6f7a63, 3 | BRF_GRA }, // 4 + { "231-c4.c4", 0x100000, 0x2e35e71b, 3 | BRF_GRA }, // 5 + + { "231-m1.m1", 0x020000, 0xde41301b, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "231-v1.v1", 0x400000, 0x113fb898, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(miexchng, miexchng, neogeo) +STD_ROM_FN(miexchng) + +struct BurnDriver BurnDrvmiexchng = { + "miexchng", NULL, "neogeo", NULL, "1997", + "Money Puzzle Exchanger / Money Idol Exchanger\0", NULL, "Face", "Neo Geo MVS", + L"Money Puzzle Exchanger\0\u30DE\u30CD\u30FC\u30A2\u30A4\u30C9\u30EB\u30A8\u30AF\u30B9\u30C1\u30A7\u30F3\u30B8\u30E3\u30FC\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, miexchngRomInfo, miexchngRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Panic Bomber + +static struct BurnRomInfo panicbomRomDesc[] = { + { "073-p1.p1", 0x080000, 0xadc356ad, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "073-s1.s1", 0x020000, 0xb876de7e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "073-c1.c1", 0x100000, 0x8582e1b5, 3 | BRF_GRA }, // 2 Sprite data + { "073-c2.c2", 0x100000, 0xe15a093b, 3 | BRF_GRA }, // 3 + + { "073-m1.m1", 0x020000, 0x3cdf5d88, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "073-v1.v1", 0x200000, 0x7fc86d2f, 5 | BRF_SND }, // 5 Sound data + { "073-v2.v2", 0x100000, 0x082adfc7, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(panicbom, panicbom, neogeo) +STD_ROM_FN(panicbom) + +struct BurnDriver BurnDrvpanicbom = { + "panicbom", NULL, "neogeo", NULL, "1994", + "Panic Bomber\0", NULL, "Eighting / Hudson", "Neo Geo MVS", + L"Panic Bomber\0\u3071\u306B\u3063\u304F\u30DC\u30F3\u30D0\u30FC \u30DC\u30F3\u30D0\u30FC\u30DE\u30F3\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, panicbomRomInfo, panicbomRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Far East of Eden - Kabuki Klash / Tengai Makyou - Shin Den + +static struct BurnRomInfo kabukiklRomDesc[] = { + { "092-p1.p1", 0x200000, 0x28ec9b77, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "092-s1.s1", 0x020000, 0xa3d68ee2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "092-c1.c1", 0x400000, 0x2a9fab01, 3 | BRF_GRA }, // 2 Sprite data + { "092-c2.c2", 0x400000, 0x6d2bac02, 3 | BRF_GRA }, // 3 + { "092-c3.c3", 0x400000, 0x5da735d6, 3 | BRF_GRA }, // 4 + { "092-c4.c4", 0x400000, 0xde07f997, 3 | BRF_GRA }, // 5 + + { "092-m1.m1", 0x020000, 0x91957ef6, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "092-v1.v1", 0x200000, 0x69e90596, 5 | BRF_SND }, // 7 Sound data + { "092-v2.v2", 0x200000, 0x7abdb75d, 5 | BRF_SND }, // 8 + { "092-v3.v3", 0x200000, 0xeccc98d3, 5 | BRF_SND }, // 9 + { "092-v4.v4", 0x100000, 0xa7c9c949, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(kabukikl, kabukikl, neogeo) +STD_ROM_FN(kabukikl) + +struct BurnDriver BurnDrvkabukikl = { + "kabukikl", NULL, "neogeo", NULL, "1995", + "Far East of Eden - Kabuki Klash / Tengai Makyou - Shin Den\0", NULL, "Hudson", "Neo Geo MVS", + L"Kabuki Klash - far east of eden\0\u5929\u5916\u9B54\u5883 - \u771F\u4F1D\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, kabukiklRomInfo, kabukiklRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Neo Bomberman + +static struct BurnRomInfo neobombeRomDesc[] = { + { "093-p1.p1", 0x100000, 0xa1a71d0d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "093-s1.s1", 0x020000, 0x4b3fa119, 2 | BRF_GRA }, // 1 Text layer tiles + + { "093-c1.c1", 0x400000, 0xd1f328f8, 3 | BRF_GRA }, // 2 Sprite data + { "093-c2.c2", 0x400000, 0x82c49540, 3 | BRF_GRA }, // 3 + { "093-c3.c3", 0x080000, 0xe37578c5, 3 | BRF_GRA }, // 4 + { "093-c4.c4", 0x080000, 0x59826783, 3 | BRF_GRA }, // 5 + + { "093-m1.m1", 0x020000, 0xe81e780b, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "093-v1.v1", 0x400000, 0x02abd4b0, 5 | BRF_SND }, // 7 Sound data + { "093-v2.v2", 0x200000, 0xa92b8b3d, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(neobombe, neobombe, neogeo) +STD_ROM_FN(neobombe) + +struct BurnDriver BurnDrvneobombe = { + "neobombe", NULL, "neogeo", NULL, "1997", + "Neo Bomberman\0", NULL, "Hudson", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MAZE, 0, + NULL, neobombeRomInfo, neobombeRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Minasanno Okagesamadesu! Daisugorokutaikai (MOM-001)(MOH-001) + +static struct BurnRomInfo minasanRomDesc[] = { + { "027-p1.p1", 0x080000, 0xc8381327, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "027-s1.s1", 0x020000, 0xe5824baa, 2 | BRF_GRA }, // 1 Text layer tiles + + { "027-c1.c1", 0x100000, 0xd0086f94, 3 | BRF_GRA }, // 2 Sprite data + { "027-c2.c2", 0x100000, 0xda61f5a6, 3 | BRF_GRA }, // 3 + { "027-c3.c3", 0x100000, 0x08df1228, 3 | BRF_GRA }, // 4 + { "027-c4.c4", 0x100000, 0x54e87696, 3 | BRF_GRA }, // 5 + + { "027-m1.m1", 0x020000, 0xadd5a226, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "027-v11.v11", 0x100000, 0x59ad4459, 5 | BRF_SND }, // 7 Sound data + { "027-v21.v21", 0x100000, 0xdf5b4eeb, 6 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(minasan, minasan, neogeo) +STD_ROM_FN(minasan) + +struct BurnDriver BurnDrvminasan = { + "minasan", NULL, "neogeo", NULL, "1990", + "Minasanno Okagesamadesu! Daisugorokutaikai (MOM-001)(MOH-001)\0", NULL, "Monolith Corp.", "Neo Geo MVS", + L"\u307F\u306A\u3055\u3093\u306E\u304A\u304B\u3052\u3055\u307E\u3067\u3059\uFF01\0Minnasanno Okagesamadesu (MOM-001)(MOH-001)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_MAHJONG, GBF_MAHJONG, 0, + NULL, minasanRomInfo, minasanRomName, NULL, NULL, neomahjongInputInfo, neomahjongDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Bakatonosama Mahjong Manyuuki (MOM-002)(MOH-002) + +static struct BurnRomInfo bakatonoRomDesc[] = { + { "036-p1.p1", 0x080000, 0x1c66b6fa, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "036-s1.s1", 0x020000, 0xf3ef4485, 2 | BRF_GRA }, // 1 Text layer tiles + + { "036-c1.c1", 0x100000, 0xfe7f1010, 3 | BRF_GRA }, // 2 Sprite data + { "036-c2.c2", 0x100000, 0xbbf003f5, 3 | BRF_GRA }, // 3 + { "036-c3.c3", 0x100000, 0x9ac0708e, 3 | BRF_GRA }, // 4 + { "036-c4.c4", 0x100000, 0xf2577d22, 3 | BRF_GRA }, // 5 + + { "036-m1.m1", 0x020000, 0xf1385b96, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "036-v1.v1", 0x100000, 0x1c335dce, 5 | BRF_SND }, // 7 Sound data + { "036-v2.v2", 0x100000, 0xbbf79342, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(bakatono, bakatono, neogeo) +STD_ROM_FN(bakatono) + +struct BurnDriver BurnDrvbakatono = { + "bakatono", NULL, "neogeo", NULL, "1991", + "Bakatonosama Mahjong Manyuuki (MOM-002)(MOH-002)\0", NULL, "Monolith Corp.", "Neo Geo MVS", + L"\u30D0\u30AB\u6BBF\u69D8 \u9EBB\u96C0\u6F2B\u904A\u8A18\0Bakatonosama Mahjong Manyuki (MOM-002)(MOH-002)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_MAHJONG, GBF_MAHJONG, 0, + NULL, bakatonoRomInfo, bakatonoRomName, NULL, NULL, neomahjongInputInfo, neomahjongDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Turf Masters / Big Tournament Golf + +static struct BurnRomInfo turfmastRomDesc[] = { + { "200-p1.p1", 0x200000, 0x28c83048, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "200-s1.s1", 0x020000, 0x9a5402b2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "200-c1.c1", 0x400000, 0x8e7bf41a, 3 | BRF_GRA }, // 2 Sprite data + { "200-c2.c2", 0x400000, 0x5a65a8ce, 3 | BRF_GRA }, // 3 + + { "200-m1.m1", 0x020000, 0x9994ac00, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "200-v1.v1", 0x200000, 0x00fd48d2, 5 | BRF_SND }, // 5 Sound data + { "200-v2.v2", 0x200000, 0x082acb31, 5 | BRF_SND }, // 6 + { "200-v3.v3", 0x200000, 0x7abca053, 5 | BRF_SND }, // 7 + { "200-v4.v4", 0x200000, 0x6c7b4902, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(turfmast, turfmast, neogeo) +STD_ROM_FN(turfmast) + +struct BurnDriver BurnDrvturfmast = { + "turfmast", NULL, "neogeo", NULL, "1996", + "Neo Turf Masters / Big Tournament Golf\0", NULL, "Nazca", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSMISC, 0, + NULL, turfmastRomInfo, turfmastRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug - Super Vehicle-001 + +static struct BurnRomInfo mslugRomDesc[] = { + { "201-p1.p1", 0x200000, 0x08d8daa5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "201-s1.s1", 0x020000, 0x2f55958d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "201-c1.c1", 0x400000, 0x72813676, 3 | BRF_GRA }, // 2 Sprite data + { "201-c2.c2", 0x400000, 0x96f62574, 3 | BRF_GRA }, // 3 + { "201-c3.c3", 0x400000, 0x5121456a, 3 | BRF_GRA }, // 4 + { "201-c4.c4", 0x400000, 0xf4ad59a3, 3 | BRF_GRA }, // 5 + + { "201-m1.m1", 0x020000, 0xc28b3253, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "201-v1.v1", 0x400000, 0x23d22ed1, 5 | BRF_SND }, // 7 Sound data + { "201-v2.v2", 0x400000, 0x472cf9db, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(mslug, mslug, neogeo) +STD_ROM_FN(mslug) + +struct BurnDriver BurnDrvmslug = { + "mslug", NULL, "neogeo", NULL, "1996", + "Metal Slug - Super Vehicle-001\0", NULL, "Nazca", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_PLATFORM, FBF_MSLUG, + NULL, mslugRomInfo, mslugRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Zed Blade / Operation Ragnarok + +static struct BurnRomInfo zedbladeRomDesc[] = { + { "076-p1.p1", 0x080000, 0xd7c1effd, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "076-s1.s1", 0x020000, 0xf4c25dd5, 2 | BRF_GRA }, // 1 Text layer tiles + + { "076-c1.c1", 0x200000, 0x4d9cb038, 3 | BRF_GRA }, // 2 Sprite data + { "076-c2.c2", 0x200000, 0x09233884, 3 | BRF_GRA }, // 3 + { "076-c3.c3", 0x200000, 0xd06431e3, 3 | BRF_GRA }, // 4 + { "076-c4.c4", 0x200000, 0x4b1c089b, 3 | BRF_GRA }, // 5 + + { "076-m1.m1", 0x020000, 0x7b5f3d0a, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "076-v1.v1", 0x200000, 0x1a21d90c, 5 | BRF_SND }, // 7 Sound data + { "076-v2.v2", 0x200000, 0xb61686c3, 5 | BRF_SND }, // 8 + { "076-v3.v3", 0x100000, 0xb90658fa, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(zedblade, zedblade, neogeo) +STD_ROM_FN(zedblade) + +struct BurnDriver BurnDrvzedblade = { + "zedblade", NULL, "neogeo", NULL, "1994", + "Zed Blade / Operation Ragnarok\0", NULL, "NMK", "Neo Geo MVS", + L"Zed Blade\0Operation Ragnarok\0\u4F5C\u6226\u540D\uFF02\u30E9\u30B0\u30CA\u30ED\u30AF\uFF02\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0, + NULL, zedbladeRomInfo, zedbladeRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, + &NeoRecalcPalette, 0x1000, 304, 224, 4, 3 +}; + +// Strikers 1945 Plus + +static struct BurnRomInfo s1945pRomDesc[] = { + { "254-p1.p1", 0x100000, 0xff8efcff, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "254-p2.sp2", 0x400000, 0xefdfd4dd, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "254-c1.c1", 0x800000, 0xae6fc8ef, 3 | BRF_GRA }, // 2 Sprite data + { "254-c2.c2", 0x800000, 0x436fa176, 3 | BRF_GRA }, // 3 + { "254-c3.c3", 0x800000, 0xe53ff2dc, 3 | BRF_GRA }, // 4 + { "254-c4.c4", 0x800000, 0x818672f0, 3 | BRF_GRA }, // 5 + { "254-c5.c5", 0x800000, 0x4580eacd, 3 | BRF_GRA }, // 6 + { "254-c6.c6", 0x800000, 0xe34970fc, 3 | BRF_GRA }, // 7 + { "254-c7.c7", 0x800000, 0xf2323239, 3 | BRF_GRA }, // 8 + { "254-c8.c8", 0x800000, 0x66848c7d, 3 | BRF_GRA }, // 9 + + { "254-m1.m1", 0x020000, 0x994b4487, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "254-v1.v1", 0x400000, 0x844f58fb, 5 | BRF_SND }, // 11 Sound data + { "254-v2.v2", 0x400000, 0xd9a248f0, 5 | BRF_SND }, // 12 + { "254-v3.v3", 0x400000, 0x0b0d2d33, 5 | BRF_SND }, // 13 + { "254-v4.v4", 0x400000, 0x6d13dc91, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(s1945p, s1945p, neogeo) +STD_ROM_FN(s1945p) + +static INT32 s1945pInit() +{ + nNeoProtectionXor = 0x05; + return NeoInit(); +} + +struct BurnDriver BurnDrvs1945p = { + "s1945p", NULL, "neogeo", NULL, "1999", + "Strikers 1945 Plus\0", NULL, "Psikyo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC42, GBF_VERSHOOT, 0, + NULL, s1945pRomInfo, s1945pRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + s1945pInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Quiz King of Fighters (SAM-080)(SAH-080) + +static struct BurnRomInfo quizkofRomDesc[] = { + { "080-p1.p1", 0x100000, 0x4440315e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "080-s1.s1", 0x020000, 0xd7b86102, 2 | BRF_GRA }, // 1 Text layer tiles + + { "080-c1.c1", 0x200000, 0xea1d764a, 3 | BRF_GRA }, // 2 Sprite data + { "080-c2.c2", 0x200000, 0xd331d4a4, 3 | BRF_GRA }, // 3 + { "080-c3.c3", 0x200000, 0xb4851bfe, 3 | BRF_GRA }, // 4 + { "080-c4.c4", 0x200000, 0xca6f5460, 3 | BRF_GRA }, // 5 + + { "080-m1.m1", 0x020000, 0xf5f44172, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "080-v1.v1", 0x200000, 0x0be18f60, 5 | BRF_SND }, // 7 Sound data + { "080-v2.v2", 0x200000, 0x4abde3ff, 5 | BRF_SND }, // 8 + { "080-v3.v3", 0x200000, 0xf02844e2, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(quizkof, quizkof, neogeo) +STD_ROM_FN(quizkof) + +struct BurnDriver BurnDrvquizkof = { + "quizkof", NULL, "neogeo", NULL, "1995", + "Quiz King of Fighters (SAM-080)(SAH-080)\0", NULL, "Saurus", "Neo Geo MVS", + L"\u30AF\u30A4\u30BA\u30AD\u30F3\u30B0\u30AA\u30D6\u30D5\u30A1\u30A4\u30BF\u30FC\u30BA\0Quiz King of Fighters (SAM-080)(SAH-080)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, quizkofRomInfo, quizkofRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Quiz King of Fighters (Korean release) + +static struct BurnRomInfo quizkofkRomDesc[] = { + { "vic-080-p1.p1", 0x100000, 0x2589488e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "vic-080-s1.s1", 0x020000, 0xaf72c30f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "vic-080-c1.c1", 0x200000, 0x94d90170, 3 | BRF_GRA }, // 2 Sprite data + { "vic-080-c2.c2", 0x200000, 0x297f25a1, 3 | BRF_GRA }, // 3 + { "vic-080-c3.c3", 0x200000, 0xcf484c4f, 3 | BRF_GRA }, // 4 + { "vic-080-c4.c4", 0x200000, 0x36e5d997, 3 | BRF_GRA }, // 5 + + { "vic-080-m1.m1", 0x020000, 0x4f157e9a, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "080-v1.v1", 0x200000, 0x0be18f60, 5 | BRF_SND }, // 7 Sound data + { "vic-080-v2.v2", 0x200000, 0x719fee5b, 5 | BRF_SND }, // 8 + { "vic-080-v3.v3", 0x200000, 0x64b7efde, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(quizkofk, quizkofk, neogeo) +STD_ROM_FN(quizkofk) + +struct BurnDriver BurnDrvquizkofk = { + "quizkofk", "quizkof", "neogeo", NULL, "1995", + "Quiz King of Fighters (Korean release)\0", NULL, "Saurus", "Neo Geo MVS", + L"\u30AF\u30A4\u30BA\u30AD\u30F3\u30B0\u30AA\u30D6\u30D5\u30A1\u30A4\u30BF\u30FC\u30BA (Korea)\0Quiz King of Fighters (Korean release)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, quizkofkRomInfo, quizkofkRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Stakes Winner / Stakes Winner - GI kinzen seihae no michi + +static struct BurnRomInfo stakwinRomDesc[] = { + { "088-p1.p1", 0x200000, 0xbd5814f6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "088-s1.s1", 0x020000, 0x073cb208, 2 | BRF_GRA }, // 1 Text layer tiles + + { "088-c1.c1", 0x200000, 0x6e733421, 3 | BRF_GRA }, // 2 Sprite data + { "088-c2.c2", 0x200000, 0x4d865347, 3 | BRF_GRA }, // 3 + { "088-c3.c3", 0x200000, 0x8fa5a9eb, 3 | BRF_GRA }, // 4 + { "088-c4.c4", 0x200000, 0x4604f0dc, 3 | BRF_GRA }, // 5 + + { "088-m1.m1", 0x020000, 0x2fe1f499, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "088-v1.v1", 0x200000, 0xb7785023, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(stakwin, stakwin, neogeo) +STD_ROM_FN(stakwin) + +struct BurnDriver BurnDrvstakwin = { + "stakwin", NULL, "neogeo", NULL, "1995", + "Stakes Winner / Stakes Winner - GI kinzen seihae no michi\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_MISC, 0, + NULL, stakwinRomInfo, stakwinRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Ragnagard / Shin-Oh-Ken + +static struct BurnRomInfo ragnagrdRomDesc[] = { + { "218-p1.p1", 0x200000, 0xca372303, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "218-s1.s1", 0x020000, 0x7d402f9a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "218-c1.c1", 0x400000, 0xc31500a4, 3 | BRF_GRA }, // 2 Sprite data + { "218-c2.c2", 0x400000, 0x98aba1f9, 3 | BRF_GRA }, // 3 + { "218-c3.c3", 0x400000, 0x833c163a, 3 | BRF_GRA }, // 4 + { "218-c4.c4", 0x400000, 0xc1a30f69, 3 | BRF_GRA }, // 5 + { "218-c5.c5", 0x400000, 0x6b6de0ff, 3 | BRF_GRA }, // 6 + { "218-c6.c6", 0x400000, 0x94beefcf, 3 | BRF_GRA }, // 7 + { "218-c7.c7", 0x400000, 0xde6f9b28, 3 | BRF_GRA }, // 8 + { "218-c8.c8", 0x400000, 0xd9b311f6, 3 | BRF_GRA }, // 9 + + { "218-m1.m1", 0x020000, 0x17028bcf, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "218-v1.v1", 0x400000, 0x61eee7f4, 5 | BRF_SND }, // 11 Sound data + { "218-v2.v2", 0x400000, 0x6104e20b, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(ragnagrd, ragnagrd, neogeo) +STD_ROM_FN(ragnagrd) + +struct BurnDriver BurnDrvragnagrd = { + "ragnagrd", NULL, "neogeo", NULL, "1996", + "Ragnagard / Shin-Oh-Ken\0", NULL, "Saurus", "Neo Geo MVS", + L"Operation Ragnagard\0\u795E\u51F0\u62F3\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, ragnagrdRomInfo, ragnagrdRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Pleasure Goal / Futsal - 5 on 5 Mini Soccer (NGM-219) + +static struct BurnRomInfo pgoalRomDesc[] = { + { "219-p1.p1", 0x200000, 0x6af0e574, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "219-s1.s1", 0x020000, 0x002f3c88, 2 | BRF_GRA }, // 1 Text layer tiles + + { "219-c1.c1", 0x400000, 0x67fec4dc, 3 | BRF_GRA }, // 2 Sprite data + { "219-c2.c2", 0x400000, 0x86ed01f2, 3 | BRF_GRA }, // 3 + { "219-c3.c3", 0x200000, 0x5fdad0a5, 3 | BRF_GRA }, // 4 + { "219-c4.c4", 0x200000, 0xf57b4a1c, 3 | BRF_GRA }, // 5 + + { "219-m1.m1", 0x020000, 0x958efdc8, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "219-v1.v1", 0x400000, 0xd0ae33d9, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(pgoal, pgoal, neogeo) +STD_ROM_FN(pgoal) + +struct BurnDriver BurnDrvpgoal = { + "pgoal", NULL, "neogeo", NULL, "1996", + "Pleasure Goal / Futsal - 5 on 5 Mini Soccer (NGM-219)\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSFOOTBALL, 0, + NULL, pgoalRomInfo, pgoalRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Stakes Winner 2 + +static struct BurnRomInfo stakwin2RomDesc[] = { + { "227-p1.p1", 0x200000, 0xdaf101d2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "227-s1.s1", 0x020000, 0x2a8c4462, 2 | BRF_GRA }, // 1 Text layer tiles + + { "227-c1.c1", 0x400000, 0x7d6c2af4, 3 | BRF_GRA }, // 2 Sprite data + { "227-c2.c2", 0x400000, 0x7e402d39, 3 | BRF_GRA }, // 3 + { "227-c3.c3", 0x200000, 0x93dfd660, 3 | BRF_GRA }, // 4 + { "227-c4.c4", 0x200000, 0x7efea43a, 3 | BRF_GRA }, // 5 + + { "227-m1.m1", 0x020000, 0xc8e5e0f9, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "227-v1.v1", 0x400000, 0xb8f24181, 5 | BRF_SND }, // 7 Sound data + { "227-v2.v2", 0x400000, 0xee39e260, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(stakwin2, stakwin2, neogeo) +STD_ROM_FN(stakwin2) + +struct BurnDriver BurnDrvstakwin2 = { + "stakwin2", NULL, "neogeo", NULL, "1996", + "Stakes Winner 2\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_MISC, 0, + NULL, stakwin2RomInfo, stakwin2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Shock Troopers (set 1) + +static struct BurnRomInfo shocktroRomDesc[] = { + { "238-p1.p1", 0x100000, 0x5677456f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "238-p2.sp2", 0x400000, 0x5b4a09c5, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "238-s1.s1", 0x020000, 0x1f95cedb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "238-c1.c1", 0x400000, 0x90c6a181, 3 | BRF_GRA }, // 3 Sprite data + { "238-c2.c2", 0x400000, 0x888720f0, 3 | BRF_GRA }, // 4 + { "238-c3.c3", 0x400000, 0x2c393aa3, 3 | BRF_GRA }, // 5 + { "238-c4.c4", 0x400000, 0xb9e909eb, 3 | BRF_GRA }, // 6 + { "238-c5.c5", 0x400000, 0xc22c68eb, 3 | BRF_GRA }, // 7 + { "238-c6.c6", 0x400000, 0x119323cd, 3 | BRF_GRA }, // 8 + { "238-c7.c7", 0x400000, 0xa72ce7ed, 3 | BRF_GRA }, // 9 + { "238-c8.c8", 0x400000, 0x1c7c2efb, 3 | BRF_GRA }, // 10 + + { "238-m1.m1", 0x020000, 0x075b9518, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "238-v1.v1", 0x400000, 0x260c0bef, 5 | BRF_SND }, // 12 Sound data + { "238-v2.v2", 0x200000, 0x4ad7d59e, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(shocktro, shocktro, neogeo) +STD_ROM_FN(shocktro) + +struct BurnDriver BurnDrvshocktro = { + "shocktro", NULL, "neogeo", NULL, "1997", + "Shock Troopers (set 1)\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, shocktroRomInfo, shocktroRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Shock Troopers (set 2) + +static struct BurnRomInfo shocktroaRomDesc[] = { + { "238-pg1.p1", 0x100000, 0xefedf8dc, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "238-p2.sp2", 0x400000, 0x5b4a09c5, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "238-s1.s1", 0x020000, 0x1f95cedb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "238-c1.c1", 0x400000, 0x90c6a181, 3 | BRF_GRA }, // 3 Sprite data + { "238-c2.c2", 0x400000, 0x888720f0, 3 | BRF_GRA }, // 4 + { "238-c3.c3", 0x400000, 0x2c393aa3, 3 | BRF_GRA }, // 5 + { "238-c4.c4", 0x400000, 0xb9e909eb, 3 | BRF_GRA }, // 6 + { "238-c5.c5", 0x400000, 0xc22c68eb, 3 | BRF_GRA }, // 7 + { "238-c6.c6", 0x400000, 0x119323cd, 3 | BRF_GRA }, // 8 + { "238-c7.c7", 0x400000, 0xa72ce7ed, 3 | BRF_GRA }, // 9 + { "238-c8.c8", 0x400000, 0x1c7c2efb, 3 | BRF_GRA }, // 10 + + { "238-m1.m1", 0x020000, 0x075b9518, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "238-v1.v1", 0x400000, 0x260c0bef, 5 | BRF_SND }, // 12 Sound data + { "238-v2.v2", 0x200000, 0x4ad7d59e, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(shocktroa, shocktroa, neogeo) +STD_ROM_FN(shocktroa) + +struct BurnDriver BurnDrvshocktroa = { + "shocktroa", "shocktro", "neogeo", NULL, "1997", + "Shock Troopers (set 2)\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, shocktroaRomInfo, shocktroaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Shock Troopers - 2nd Squad + +static struct BurnRomInfo shocktr2RomDesc[] = { + { "246-p1.p1", 0x100000, 0x6d4b7781, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "246-p2.sp2", 0x400000, 0x72ea04c3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "246-s1.s1", 0x020000, 0x2a360637, 2 | BRF_GRA }, // 2 Text layer tiles + + { "246-c1.c1", 0x800000, 0x47ac9ec5, 3 | BRF_GRA }, // 3 Sprite data + { "246-c2.c2", 0x800000, 0x7bcab64f, 3 | BRF_GRA }, // 4 + { "246-c3.c3", 0x800000, 0xdb2f73e8, 3 | BRF_GRA }, // 5 + { "246-c4.c4", 0x800000, 0x5503854e, 3 | BRF_GRA }, // 6 + { "246-c5.c5", 0x800000, 0x055b3701, 3 | BRF_GRA }, // 7 + { "246-c6.c6", 0x800000, 0x7e2caae1, 3 | BRF_GRA }, // 8 + + { "246-m1.m1", 0x020000, 0xd0604ad1, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "246-v1.v1", 0x400000, 0x16986fc6, 5 | BRF_SND }, // 10 Sound data + { "246-v2.v2", 0x400000, 0xada41e83, 5 | BRF_SND }, // 11 + { "246-v3.v3", 0x200000, 0xa05ba5db, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(shocktr2, shocktr2, neogeo) +STD_ROM_FN(shocktr2) + +struct BurnDriver BurnDrvshocktr2 = { + "shocktr2", NULL, "neogeo", NULL, "1998", + "Shock Troopers - 2nd Squad\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, shocktr2RomInfo, shocktr2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Lansquenet 2004 (Shock Troopers - 2nd Squad bootleg) + +static struct BurnRomInfo lans2004RomDesc[] = { + { "lnsq-p1.bin", 0x200000, 0xb40a879a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "lnsq-p21.bin", 0x200000, 0xecdb2d42, 1 | BRF_ESS | BRF_PRG }, // 1 + { "lnsq-p22.bin", 0x200000, 0xfac5e2e7, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "lnsq-s1.bin", 0x020000, 0x39e82897, 2 | BRF_GRA }, // 3 Text layer tiles + + { "lnsq-c1.bin", 0x800000, 0xb83de59f, 3 | BRF_GRA }, // 4 Sprite data + { "lnsq-c2.bin", 0x800000, 0xe08969fd, 3 | BRF_GRA }, // 5 + { "lnsq-c3.bin", 0x800000, 0x013f2cda, 3 | BRF_GRA }, // 6 + { "lnsq-c4.bin", 0x800000, 0xd8c3a758, 3 | BRF_GRA }, // 7 + { "lnsq-c5.bin", 0x800000, 0x75500b82, 3 | BRF_GRA }, // 8 + { "lnsq-c6.bin", 0x800000, 0x670ac13b, 3 | BRF_GRA }, // 9 + + { "246-m1.bin", 0x020000, 0xd0604ad1, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "lnsq-v1.bin", 0x400000, 0x4408ebc3, 5 | BRF_SND }, // 11 Sound data + { "lnsq-v2.bin", 0x400000, 0x3d953975, 5 | BRF_SND }, // 12 + { "lnsq-v3.bin", 0x200000, 0x437d1d8e, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(lans2004, lans2004, neogeo) +STD_ROM_FN(lans2004) + +static void lans2004Callback() +{ + INT32 i; + UINT8 *dst = (UINT8*)malloc(0x100000); + if (dst) + { + static const INT32 sec[] = { 0x3, 0x8, 0x7, 0xc, 0x1, 0xa, 0x6, 0xd }; + + for (i = 0; i < 8; i++) + memcpy (dst + i * 0x20000, Neo68KROMActive + sec[i] * 0x20000, 0x20000); + + memcpy (dst + 0x0bbb00, Neo68KROMActive + 0x045b00, 0x001710); + memcpy (dst + 0x02fff0, Neo68KROMActive + 0x1a92be, 0x000010); + memcpy (Neo68KROMActive, dst, 0x100000); + free (dst); + dst = NULL; + } + + memcpy (Neo68KROMActive + 0x100000, Neo68KROMActive + 0x200000, 0x400000); + + for (i = 0xbbb00; i < 0xbe000; i+=2) { + if ((*((UINT16 *)(Neo68KROMActive + i + 0)) & 0xf2bf) == 0x42b9 && + *((UINT16 *)(Neo68KROMActive + i + 2)) == 0x0000) + { + *((UINT16 *)(Neo68KROMActive + i + 2)) = 0x000b; + *((UINT16 *)(Neo68KROMActive + i + 4)) += 0x6000; + } + } + + *((UINT16 *)(Neo68KROMActive + 0x2d15c)) = 0x000b; + *((UINT16 *)(Neo68KROMActive + 0x2d15e)) = 0xbb00; + *((UINT16 *)(Neo68KROMActive + 0x2d1e4)) = 0x6002; + *((UINT16 *)(Neo68KROMActive + 0x2ea7e)) = 0x6002; + *((UINT16 *)(Neo68KROMActive + 0xbbcd0)) = 0x6002; + *((UINT16 *)(Neo68KROMActive + 0xbbdf2)) = 0x6002; + *((UINT16 *)(Neo68KROMActive + 0xbbe42)) = 0x6002; + + lans2004_sx_decode(); + lans2004_cx_decode(0x800000 * 6); +} + +static INT32 lans2004Init() +{ + INT32 nRet; + + NeoCallbackActive->pInitialise = lans2004Callback; + + nRet = NeoInit(); + + if (nRet == 0) { + for (INT32 i = 0; i < 0xa00000; i++) + YM2610ADPCMAROM[nNeoActiveSlot][i] = BITSWAP08(YM2610ADPCMAROM[nNeoActiveSlot][i], 0, 1, 5, 4, 3, 2, 6, 7); + } + + return nRet; +} + +struct BurnDriver BurnDrvlans2004 = { + "lans2004", "shocktr2", "neogeo", NULL, "1998", + "Lansquenet 2004 (Shock Troopers - 2nd Squad bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, lans2004RomInfo, lans2004RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + lans2004Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Galaxy Fight - Universal Warriors + +static struct BurnRomInfo galaxyfgRomDesc[] = { + { "078-p1.p1", 0x200000, 0x45906309, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "078-s1.s1", 0x020000, 0x72f8923e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "078-c1.c1", 0x200000, 0xc890c7c0, 3 | BRF_GRA }, // 2 Sprite data + { "078-c2.c2", 0x200000, 0xb6d25419, 3 | BRF_GRA }, // 3 + { "078-c3.c3", 0x200000, 0x9d87e761, 3 | BRF_GRA }, // 4 + { "078-c4.c4", 0x200000, 0x765d7cb8, 3 | BRF_GRA }, // 5 + { "078-c5.c5", 0x200000, 0xe6b77e6a, 3 | BRF_GRA }, // 6 + { "078-c6.c6", 0x200000, 0xd779a181, 3 | BRF_GRA }, // 7 + { "078-c7.c7", 0x100000, 0x4f27d580, 3 | BRF_GRA }, // 8 + { "078-c8.c8", 0x100000, 0x0a7cc0d8, 3 | BRF_GRA }, // 9 + + { "078-m1.m1", 0x020000, 0x8e9e3b10, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "078-v1.v1", 0x200000, 0xe3b735ac, 5 | BRF_SND }, // 11 Sound data + { "078-v2.v2", 0x200000, 0x6a8e78c2, 5 | BRF_SND }, // 12 + { "078-v3.v3", 0x100000, 0x70bca656, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(galaxyfg, galaxyfg, neogeo) +STD_ROM_FN(galaxyfg) + +struct BurnDriver BurnDrvgalaxyfg = { + "galaxyfg", NULL, "neogeo", NULL, "1995", + "Galaxy Fight - Universal Warriors\0", NULL, "Sunsoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, galaxyfgRomInfo, galaxyfgRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Waku Waku 7 + +static struct BurnRomInfo wakuwak7RomDesc[] = { + { "225-p1.p1", 0x100000, 0xb14da766, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "225-p2.sp2", 0x200000, 0xfe190665, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "225-s1.s1", 0x020000, 0x71c4b4b5, 2 | BRF_GRA }, // 2 Text layer tiles + + { "225-c1.c1", 0x400000, 0xee4fea54, 3 | BRF_GRA }, // 3 Sprite data + { "225-c2.c2", 0x400000, 0x0c549e2d, 3 | BRF_GRA }, // 4 + { "225-c3.c3", 0x400000, 0xaf0897c0, 3 | BRF_GRA }, // 5 + { "225-c4.c4", 0x400000, 0x4c66527a, 3 | BRF_GRA }, // 6 + { "225-c5.c5", 0x400000, 0x8ecea2b5, 3 | BRF_GRA }, // 7 + { "225-c6.c6", 0x400000, 0x0eb11a6d, 3 | BRF_GRA }, // 8 + + { "225-m1.m1", 0x020000, 0x0634bba6, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "225-v1.v1", 0x400000, 0x6195c6b4, 5 | BRF_SND }, // 10 Sound data + { "225-v2.v2", 0x400000, 0x6159c5fe, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(wakuwak7, wakuwak7, neogeo) +STD_ROM_FN(wakuwak7) + +struct BurnDriver BurnDrvwakuwak7 = { + "wakuwak7", NULL, "neogeo", NULL, "1996", + "Waku Waku 7\0", NULL, "Sunsoft", "Neo Geo MVS", + L"Waku Waku 7\0\u308F\u304F\u308F\u304F\uFF17\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, 0, + NULL, wakuwak7RomInfo, wakuwak7RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Puzzle Bobble / Bust-A-Move (Neo-Geo) (NGM-083) + +static struct BurnRomInfo pbobblenRomDesc[] = { + { "d96-07.ep1", 0x080000, 0x6102ca14, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "d96-04.s1", 0x020000, 0x9caae538, 2 | BRF_GRA }, // 1 Text layer tiles + + { "068-c1.c1", 0x100000, 0x7f250f76, 3 | BRF_GRA }, // 2 Sprite data + { "068-c2.c2", 0x100000, 0x20912873, 3 | BRF_GRA }, // 3 + { "068-c3.c3", 0x100000, 0x4b641ba1, 3 | BRF_GRA }, // 4 + { "068-c4.c4", 0x100000, 0x35072596, 3 | BRF_GRA }, // 5 + { "d96-02.c5", 0x080000, 0xe89ad494, 3 | BRF_GRA }, // 6 Sprite data + { "d96-03.c6", 0x080000, 0x4b42d7eb, 3 | BRF_GRA }, // 7 + + { "d96-06.m1", 0x020000, 0xf424368a, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "068-v1.v1", 0x100000, 0x2ced86df, 5 | BRF_SND }, // 9 Sound data + { "068-v2.v2", 0x100000, 0x970851ab, 5 | BRF_SND }, // 10 + { "d96-01.v3", 0x100000, 0x0840cbc4, 5 | BRF_SND }, // 11 + { "d96-05.v4", 0x080000, 0x0a548948, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(pbobblen, pbobblen, neogeo) +STD_ROM_FN(pbobblen) + +struct BurnDriver BurnDrvpbobblen = { + "pbobblen", NULL, "neogeo", NULL, "1994", + "Puzzle Bobble / Bust-A-Move (Neo-Geo) (NGM-083)\0", NULL, "Taito", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, pbobblenRomInfo, pbobblenRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + + +// Puzzle Bobble / Bust-A-Move (Neo-Geo) (bootleg) + +static struct BurnRomInfo pbobblenbRomDesc[] = { + { "u7", 0x080000, 0xac1e9ef3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "us1", 0x020000, 0x9caae538, 2 | BRF_GRA }, // 1 Text layer tiles + + { "uc5", 0x080000, 0xe89ad494, 3 | BRF_GRA }, // 2 Sprite data + { "uc6", 0x080000, 0x4b42d7eb, 3 | BRF_GRA }, // 3 + + { "um1", 0x020000, 0xf424368a, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "u8", 0x100000, 0x0840cbc4, 5 | BRF_SND }, // 5 Sound data + { "u9", 0x080000, 0x0a548948, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(pbobblenb, pbobblenb, neogeo) +STD_ROM_FN(pbobblenb) + +struct BurnDriver BurnDrvpbobblenb = { + "pbobblenb", "pbobblen", "neogeo", NULL, "1994", + "Puzzle Bobble / Bust-A-Move (Neo-Geo) (bootleg)\0", NULL, "Taito", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, pbobblenbRomInfo, pbobblenbRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Puzzle Bobble 2 / Bust-A-Move Again (Neo-Geo) + +static struct BurnRomInfo pbobbl2nRomDesc[] = { + { "248-p1.p1", 0x100000, 0x9d6c0754, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "248-s1.s1", 0x020000, 0x0a3fee41, 2 | BRF_GRA }, // 1 Text layer tiles + + { "248-c1.c1", 0x400000, 0xd9115327, 3 | BRF_GRA }, // 2 Sprite data + { "248-c2.c2", 0x400000, 0x77f9fdac, 3 | BRF_GRA }, // 3 + { "248-c3.c3", 0x100000, 0x8890bf7c, 3 | BRF_GRA }, // 4 + { "248-c4.c4", 0x100000, 0x8efead3f, 3 | BRF_GRA }, // 5 + + { "248-m1.m1", 0x020000, 0x883097a9, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "248-v1.v1", 0x400000, 0x57fde1fa, 5 | BRF_SND }, // 7 Sound data + { "248-v2.v2", 0x400000, 0x4b966ef3, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(pbobbl2n, pbobbl2n, neogeo) +STD_ROM_FN(pbobbl2n) + +struct BurnDriver BurnDrvpbobbl2n = { + "pbobbl2n", NULL, "neogeo", NULL, "1999", + "Puzzle Bobble 2 / Bust-A-Move Again (Neo-Geo)\0", NULL, "Taito (SNK license)", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, pbobbl2nRomInfo, pbobbl2nRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Pochi and Nyaa + +static struct BurnRomInfo pnyaaRomDesc[] = { + { "267-p1.p1", 0x100000, 0x112fe2c0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "267-c1.c1", 0x800000, 0x5eebee65, 3 | BRF_GRA }, // 1 Sprite data + { "267-c2.c2", 0x800000, 0x2b67187b, 3 | BRF_GRA }, // 2 + + { "267-m1.m1", 0x080000, 0xc7853ccd, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "267-v1.v1", 0x400000, 0xe2e8e917, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(pnyaa, pnyaa, neogeo) +STD_ROM_FN(pnyaa) + +INT32 pnyaaInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x2E; + + nRet = NeoInit(); + + if (nRet == 0) { + PCM2DecryptV(0x400000, 0); + } + + return nRet; +} + +struct BurnDriver BurnDrvpnyaa = { + "pnyaa", NULL, "neogeo", NULL, "2003", + "Pochi and Nyaa\0", NULL, "Aiky / Taito", "Neo Geo MVS", + L"Pochi and Nyaa\0\u30DD\u30C1\u30C3\u3068\u306B\u3083\uFF5E\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PUZZLE, 0, + NULL, pnyaaRomInfo, pnyaaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + pnyaaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Chibi Marukochan Deluxe Quiz + +static struct BurnRomInfo marukodqRomDesc[] = { + { "206-p1.p1", 0x100000, 0xc33ed21e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "206-s1.s1", 0x020000, 0xf0b68780, 2 | BRF_GRA }, // 1 Text layer tiles + + { "206-c1.c1", 0x400000, 0x846e4e8e, 3 | BRF_GRA }, // 2 Sprite data + { "206-c2.c2", 0x400000, 0x1cba876d, 3 | BRF_GRA }, // 3 + { "206-c3.c3", 0x100000, 0x79aa2b48, 3 | BRF_GRA }, // 4 + { "206-c4.c4", 0x100000, 0x55e1314d, 3 | BRF_GRA }, // 5 + + { "206-m1.m1", 0x020000, 0x0e22902e, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "206-v1.v1", 0x200000, 0x5385eca8, 5 | BRF_SND }, // 7 Sound data + { "206-v2.v2", 0x200000, 0xf8c55404, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(marukodq, marukodq, neogeo) +STD_ROM_FN(marukodq) + +struct BurnDriver BurnDrvmarukodq = { + "marukodq", NULL, "neogeo", NULL, "1995", + "Chibi Marukochan Deluxe Quiz\0", NULL, "Takara", "Neo Geo MVS", + L"\u3061\u3073\u307E\u308B\u5B50\u3061\u3083\u3093 \u307E\u308B\u5B50\u30C7\u30E9\u30C3\u30AF\u30B9\u30AF\u30A4\u30BA\0Chibi Marukochan Deluxe Quiz\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_QUIZ, 0, + NULL, marukodqRomInfo, marukodqRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Double Dragon (Neo-Geo) + +static struct BurnRomInfo doubledrRomDesc[] = { + { "082-p1.p1", 0x200000, 0x34ab832a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "082-s1.s1", 0x020000, 0xbef995c5, 2 | BRF_GRA }, // 1 Text layer tiles + + { "082-c1.c1", 0x200000, 0xb478c725, 3 | BRF_GRA }, // 2 Sprite data + { "082-c2.c2", 0x200000, 0x2857da32, 3 | BRF_GRA }, // 3 + { "082-c3.c3", 0x200000, 0x8b0d378e, 3 | BRF_GRA }, // 4 + { "082-c4.c4", 0x200000, 0xc7d2f596, 3 | BRF_GRA }, // 5 + { "082-c5.c5", 0x200000, 0xec87bff6, 3 | BRF_GRA }, // 6 + { "082-c6.c6", 0x200000, 0x844a8a11, 3 | BRF_GRA }, // 7 + { "082-c7.c7", 0x100000, 0x727c4d02, 3 | BRF_GRA }, // 8 + { "082-c8.c8", 0x100000, 0x69a5fa37, 3 | BRF_GRA }, // 9 + + { "082-m1.m1", 0x020000, 0x10b144de, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "082-v1.v1", 0x200000, 0xcc1128e4, 5 | BRF_SND }, // 11 Sound data + { "082-v2.v2", 0x200000, 0xc3ff5554, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(doubledr, doubledr, neogeo) +STD_ROM_FN(doubledr) + +struct BurnDriver BurnDrvdoubledr = { + "doubledr", NULL, "neogeo", NULL, "1995", + "Double Dragon (Neo-Geo)\0", NULL, "Technos", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, doubledrRomInfo, doubledrRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Voltage Fighter - Gowcaizer / Choujin Gakuen Gowcaizer + +static struct BurnRomInfo gowcaizrRomDesc[] = { + { "094-p1.p1", 0x200000, 0x33019545, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "094-s1.s1", 0x020000, 0x2f8748a2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "094-c1.c1", 0x200000, 0x042f6af5, 3 | BRF_GRA }, // 2 Sprite data + { "094-c2.c2", 0x200000, 0x0fbcd046, 3 | BRF_GRA }, // 3 + { "094-c3.c3", 0x200000, 0x58bfbaa1, 3 | BRF_GRA }, // 4 + { "094-c4.c4", 0x200000, 0x9451ee73, 3 | BRF_GRA }, // 5 + { "094-c5.c5", 0x200000, 0xff9cf48c, 3 | BRF_GRA }, // 6 + { "094-c6.c6", 0x200000, 0x31bbd918, 3 | BRF_GRA }, // 7 + { "094-c7.c7", 0x200000, 0x2091ec04, 3 | BRF_GRA }, // 8 + { "094-c8.c8", 0x200000, 0xd80dd241, 3 | BRF_GRA }, // 9 + + { "094-m1.m1", 0x020000, 0x78c851cb, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "094-v1.v1", 0x200000, 0x6c31223c, 5 | BRF_SND }, // 11 Sound data + { "094-v2.v2", 0x200000, 0x8edb776c, 5 | BRF_SND }, // 12 + { "094-v3.v3", 0x100000, 0xc63b9285, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(gowcaizr, gowcaizr, neogeo) +STD_ROM_FN(gowcaizr) + +struct BurnDriver BurnDrvgowcaizr = { + "gowcaizr", NULL, "neogeo", NULL, "1995", + "Voltage Fighter - Gowcaizer / Choujin Gakuen Gowcaizer\0", NULL, "Technos", "Neo Geo MVS", + L"Voltage Fighter - Gowcaizer\0\u8D85\u4EBA\u5B66\u5712\u30B4\u30A6\u30AB\u30A4\u30B6\u30FC\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, gowcaizrRomInfo, gowcaizrRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Super Dodge Ball / Kunio no Nekketsu Toukyuu Densetsu + +static struct BurnRomInfo sdodgebRomDesc[] = { + { "208-p1.p1", 0x200000, 0x127f3d32, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "208-s1.s1", 0x020000, 0x64abd6b3, 2 | BRF_GRA }, // 1 Text layer tiles + + { "208-c1.c1", 0x400000, 0x93d8619b, 3 | BRF_GRA }, // 2 Sprite data + { "208-c2.c2", 0x400000, 0x1c737bb6, 3 | BRF_GRA }, // 3 + { "208-c3.c3", 0x200000, 0x14cb1703, 3 | BRF_GRA }, // 4 + { "208-c4.c4", 0x200000, 0xc7165f19, 3 | BRF_GRA }, // 5 + + { "208-m1.m1", 0x020000, 0x0a5f3325, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "208-v1.v1", 0x400000, 0xe7899a24, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(sdodgeb, sdodgeb, neogeo) +STD_ROM_FN(sdodgeb) + +struct BurnDriver BurnDrvsdodgeb = { + "sdodgeb", NULL, "neogeo", NULL, "1996", + "Super Dodge Ball / Kunio no Nekketsu Toukyuu Densetsu\0", NULL, "Technos", "Neo Geo MVS", + L"Super Dodge Ball\0\u304F\u306B\u304A\u306E\u71B1\u8840\u95D8\u7403\u4F1D\u8AAC\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSMISC, 0, + NULL, sdodgebRomInfo, sdodgebRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Tecmo World Soccer '96 + +static struct BurnRomInfo tws96RomDesc[] = { + { "086-p1.p1", 0x100000, 0x03e20ab6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "086-s1.s1", 0x020000, 0x6f5e2b3a, 2 | BRF_GRA }, // 1 Text layer tiles + + { "086-c1.c1", 0x400000, 0x2611bc2a, 3 | BRF_GRA }, // 2 Sprite data + { "086-c2.c2", 0x400000, 0x6b0d6827, 3 | BRF_GRA }, // 3 + { "086-c3.c3", 0x100000, 0x750ddc0c, 3 | BRF_GRA }, // 4 + { "086-c4.c4", 0x100000, 0x7a6e7d82, 3 | BRF_GRA }, // 5 + + { "086-m1.m1", 0x020000, 0xcb82bc5d, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "086-v1.v1", 0x200000, 0x97bf1986, 5 | BRF_SND }, // 7 Sound data + { "086-v2.v2", 0x200000, 0xb7eb05df, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(tws96, tws96, neogeo) +STD_ROM_FN(tws96) + +struct BurnDriver BurnDrvtws96 = { + "tws96", NULL, "neogeo", NULL, "1996", + "Tecmo World Soccer '96\0", NULL, "Tecmo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSFOOTBALL, 0, + NULL, tws96RomInfo, tws96RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Fight Fever (set 1) + +static struct BurnRomInfo fightfevRomDesc[] = { + { "060-p1.p1", 0x100000, 0x2a104b50, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "060-s1.s1", 0x020000, 0x7f012104, 2 | BRF_GRA }, // 2 Text layer tiles + + { "060-c1.c1", 0x200000, 0x8908fff9, 3 | BRF_GRA }, // 2 Sprite data + { "060-c2.c2", 0x200000, 0xc6649492, 3 | BRF_GRA }, // 3 + { "060-c3.c3", 0x200000, 0x0956b437, 3 | BRF_GRA }, // 4 + { "060-c4.c4", 0x200000, 0x026f3b62, 3 | BRF_GRA }, // 5 + + { "060-m1.m1", 0x020000, 0x0b7c4e65, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "060-v1.v1", 0x200000, 0xf417c215, 5 | BRF_SND }, // 7 Sound data + { "060-v2.v2", 0x100000, 0xefcff7cf, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(fightfev, fightfev, neogeo) +STD_ROM_FN(fightfev) + +struct BurnDriver BurnDrvfightfev = { + "fightfev", NULL, "neogeo", NULL, "1994", + "Fight Fever (set 1)\0", NULL, "Viccom", "Neo Geo MVS", + L"Fight Fever\0\uC655\uC911\uC655 (set 1)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, fightfevRomInfo, fightfevRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Fight Fever (set 2) + +static struct BurnRomInfo fightfevaRomDesc[] = { + { "060-p1.p1", 0x100000, 0x2a104b50, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "060-s1.s1", 0x020000, 0x7f012104, 2 | BRF_GRA }, // 2 Text layer tiles + + { "060-c1.c1", 0x200000, 0x8908fff9, 3 | BRF_GRA }, // 2 Sprite data + { "060-c2.c2", 0x200000, 0xc6649492, 3 | BRF_GRA }, // 3 + { "060-c3.c3", 0x200000, 0x0956b437, 3 | BRF_GRA }, // 4 + { "060-c4.c4", 0x200000, 0x026f3b62, 3 | BRF_GRA }, // 5 + + { "060-m1.m1", 0x020000, 0x0b7c4e65, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "060-v1.v1", 0x200000, 0xf417c215, 5 | BRF_SND }, // 7 Sound data + { "060-v2.v2", 0x100000, 0xefcff7cf, 5 | BRF_SND }, // 8 + + { "060-epr.sp2", 0x080000, 0x3032041b, 0 | BRF_ESS | BRF_PRG }, // 9 68K code +}; + +STDROMPICKEXT(fightfeva, fightfeva, neogeo) +STD_ROM_FN(fightfeva) + +static void fightfevaCallback() +{ + BurnLoadRom(Neo68KROMActive, 9, 1); +} + +static INT32 fightfevaInit() +{ + NeoCallbackActive->pInitialise = fightfevaCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvfightfeva = { + "fightfeva", "fightfev", "neogeo", NULL, "1994", + "Fight Fever (set 2)\0", NULL, "Viccom", "Neo Geo MVS", + L"Fight Fever\0\uC655\uC911\uC655 (set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SCRFIGHT, 0, + NULL, fightfevaRomInfo, fightfevaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + fightfevaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Power Spikes II (NGM-068) + +static struct BurnRomInfo pspikes2RomDesc[] = { + { "068-pg1.p1", 0x100000, 0x105a408f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "068-sg1.s1", 0x020000, 0x18082299, 2 | BRF_GRA }, // 1 Text layer tiles + + { "068-c1.c1", 0x100000, 0x7f250f76, 3 | BRF_GRA }, // 2 Sprite data + { "068-c2.c2", 0x100000, 0x20912873, 3 | BRF_GRA }, // 3 + { "068-c3.c3", 0x100000, 0x4b641ba1, 3 | BRF_GRA }, // 4 + { "068-c4.c4", 0x100000, 0x35072596, 3 | BRF_GRA }, // 5 + { "068-c5.c5", 0x100000, 0x151dd624, 3 | BRF_GRA }, // 6 + { "068-c6.c6", 0x100000, 0xa6722604, 3 | BRF_GRA }, // 7 + + { "068-mg1.m1", 0x020000, 0xb1c7911e, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "068-v1.v1", 0x100000, 0x2ced86df, 5 | BRF_SND }, // 9 Sound data + { "068-v2.v2", 0x100000, 0x970851ab, 5 | BRF_SND }, // 10 + { "068-v3.v3", 0x100000, 0x81ff05aa, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(pspikes2, pspikes2, neogeo) +STD_ROM_FN(pspikes2) + +struct BurnDriver BurnDrvpspikes2 = { + "pspikes2", NULL, "neogeo", NULL, "1994", + "Power Spikes II (NGM-068)\0", NULL, "Video System Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0, + NULL, pspikes2RomInfo, pspikes2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Aero Fighters 2 / Sonic Wings 2 + +static struct BurnRomInfo sonicwi2RomDesc[] = { + { "075-p1.p1", 0x200000, 0x92871738, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "075-s1.s1", 0x020000, 0xc9eec367, 2 | BRF_GRA }, // 1 Text layer tiles + + { "075-c1.c1", 0x200000, 0x3278e73e, 3 | BRF_GRA }, // 2 Sprite data + { "075-c2.c2", 0x200000, 0xfe6355d6, 3 | BRF_GRA }, // 3 + { "075-c3.c3", 0x200000, 0xc1b438f1, 3 | BRF_GRA }, // 4 + { "075-c4.c4", 0x200000, 0x1f777206, 3 | BRF_GRA }, // 5 + + { "075-m1.m1", 0x020000, 0xbb828df1, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "075-v1.v1", 0x200000, 0x7577e949, 5 | BRF_SND }, // 7 Sound data + { "075-v2.v2", 0x100000, 0x021760cd, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(sonicwi2, sonicwi2, neogeo) +STD_ROM_FN(sonicwi2) + +struct BurnDriver BurnDrvsonicwi2 = { + "sonicwi2", NULL, "neogeo", NULL, "1994", + "Aero Fighters 2 / Sonic Wings 2\0", NULL, "Video System Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VERSHOOT, FBF_SONICWI, + NULL, sonicwi2RomInfo, sonicwi2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Aero Fighters 3 / Sonic Wings 3 + +static struct BurnRomInfo sonicwi3RomDesc[] = { + { "097-p1.p1", 0x200000, 0x0547121d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "097-s1.s1", 0x020000, 0x8dd66743, 2 | BRF_GRA }, // 1 Text layer tiles + + { "097-c1.c1", 0x400000, 0x33d0d589, 3 | BRF_GRA }, // 2 Sprite data + { "097-c2.c2", 0x400000, 0x186f8b43, 3 | BRF_GRA }, // 3 + { "097-c3.c3", 0x200000, 0xc339fff5, 3 | BRF_GRA }, // 4 + { "097-c4.c4", 0x200000, 0x84a40c6e, 3 | BRF_GRA }, // 5 + + { "097-m1.m1", 0x020000, 0xb20e4291, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "097-v1.v1", 0x400000, 0x6f885152, 5 | BRF_SND }, // 7 Sound data + { "097-v2.v2", 0x200000, 0x3359e868, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(sonicwi3, sonicwi3, neogeo) +STD_ROM_FN(sonicwi3) + +struct BurnDriver BurnDrvsonicwi3 = { + "sonicwi3", NULL, "neogeo", NULL, "1995", + "Aero Fighters 3 / Sonic Wings 3\0", NULL, "Video System Co.", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VERSHOOT, FBF_SONICWI, + NULL, sonicwi3RomInfo, sonicwi3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Pop 'n Bounce / Gapporin + +static struct BurnRomInfo popbouncRomDesc[] = { + { "237-p1.p1", 0x100000, 0xbe96e44f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "237-s1.s1", 0x020000, 0xb61cf595, 2 | BRF_GRA }, // 1 Text layer tiles + + { "237-c1.c1", 0x200000, 0xeda42d66, 3 | BRF_GRA }, // 2 Sprite data + { "237-c2.c2", 0x200000, 0x5e633c65, 3 | BRF_GRA }, // 3 + + { "237-m1.m1", 0x020000, 0xd4c946dd, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "237-v1.v1", 0x200000, 0xedcb1beb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(popbounc, popbounc, neogeo) +STD_ROM_FN(popbounc) + +struct BurnDriver BurnDrvpopbounc = { + "popbounc", NULL, "neogeo", NULL, "1997", + "Pop 'n Bounce / Gapporin\0", NULL, "Video System Co.", "Neo Geo MVS", + L"Pop 'n Bounce\0\u30AC\u30C3\u30DD\u30EA\u30F3\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_PADDLE, GBF_PUZZLE, 0, + NULL, popbouncRomInfo, popbouncRomName, NULL, NULL, neopaddleInputInfo, neopaddleDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Andro Dunos (NGM-049)(NGH-049) + +static struct BurnRomInfo androdunRomDesc[] = { + { "049-p1.p1", 0x080000, 0x3b857da2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "049-p2.p2", 0x080000, 0x2f062209, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "049-s1.s1", 0x020000, 0x6349de5d, 2 | BRF_GRA }, // 2 Text layer tiles + + { "049-c1.c1", 0x100000, 0x7ace6db3, 3 | BRF_GRA }, // 3 Sprite data + { "049-c2.c2", 0x100000, 0xb17024f7, 3 | BRF_GRA }, // 4 + + { "049-m1.m1", 0x020000, 0xedd2acf4, 4 | BRF_ESS | BRF_PRG }, // 5 Z80 code + + { "049-v1.v1", 0x100000, 0xce43cb89, 5 | BRF_SND }, // 6 Sound data +}; + +STDROMPICKEXT(androdun, androdun, neogeo) +STD_ROM_FN(androdun) + +struct BurnDriver BurnDrvandrodun = { + "androdun", NULL, "neogeo", NULL, "1992", + "Andro Dunos (NGM-049)(NGH-049)\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0, + NULL, androdunRomInfo, androdunRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Puzzle De Pon! + +static struct BurnRomInfo puzzledpRomDesc[] = { + { "202-p1.p1", 0x080000, 0x2b61415b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "202-s1.s1", 0x020000, 0xcd19264f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "202-c1.c1", 0x100000, 0xcc0095ef, 3 | BRF_GRA }, // 2 Sprite data + { "202-c2.c2", 0x100000, 0x42371307, 3 | BRF_GRA }, // 3 + + { "202-m1.m1", 0x020000, 0x9c0291ea, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "202-v1.v1", 0x080000, 0xdebeb8fb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(puzzledp, puzzledp, neogeo) +STD_ROM_FN(puzzledp) + +struct BurnDriver BurnDrvpuzzledp = { + "puzzledp", NULL, "neogeo", NULL, "1995", + "Puzzle De Pon!\0", NULL, "Taito (Visco license)", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, puzzledpRomInfo, puzzledpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Mr. Do! + +static struct BurnRomInfo neomrdoRomDesc[] = { + { "207-p1.p1", 0x100000, 0x334ea51e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "207-s1.s1", 0x020000, 0x6aebafce, 2 | BRF_GRA }, // 1 Text layer tiles + + { "207-c1.c1", 0x200000, 0xc7541b9d, 3 | BRF_GRA }, // 2 Sprite data + { "207-c2.c2", 0x200000, 0xf57166d2, 3 | BRF_GRA }, // 3 + + { "207-m1.m1", 0x020000, 0xb5b74a95, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "207-v1.v1", 0x200000, 0x4143c052, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neomrdo, neomrdo, neogeo) +STD_ROM_FN(neomrdo) + +struct BurnDriver BurnDrvneomrdo = { + "neomrdo", NULL, "neogeo", NULL, "1996", + "Neo Mr. Do!\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MAZE, 0, + NULL, neomrdoRomInfo, neomrdoRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Goal! Goal! Goal! + +static struct BurnRomInfo goalx3RomDesc[] = { + { "209-p1.p1", 0x200000, 0x2a019a79, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "209-s1.s1", 0x020000, 0xc0eaad86, 2 | BRF_GRA }, // 1 Text layer tiles + + { "209-c1.c1", 0x400000, 0xb49d980e, 3 | BRF_GRA }, // 2 Sprite data + { "209-c2.c2", 0x400000, 0x5649b015, 3 | BRF_GRA }, // 3 + { "209-c3.c3", 0x100000, 0x5f91bace, 3 | BRF_GRA }, // 4 + { "209-c4.c4", 0x100000, 0x1e9f76f2, 3 | BRF_GRA }, // 5 + + { "209-m1.m1", 0x020000, 0xcd758325, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "209-v1.v1", 0x200000, 0xef214212, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(goalx3, goalx3, neogeo) +STD_ROM_FN(goalx3) + +struct BurnDriver BurnDrvgoalx3 = { + "goalx3", NULL, "neogeo", NULL, "1995", + "Goal! Goal! Goal!\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_SPORTSFOOTBALL, 0, + NULL, goalx3RomInfo, goalx3RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Drift Out - New Technology + +static struct BurnRomInfo neodriftRomDesc[] = { + { "213-p1.p1", 0x200000, 0xe397d798, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "213-s1.s1", 0x020000, 0xb76b61bc, 2 | BRF_GRA }, // 1 Text layer tiles + + { "213-c1.c1", 0x400000, 0x3edc8bd3, 3 | BRF_GRA }, // 2 Sprite data + { "213-c2.c2", 0x400000, 0x46ae5f16, 3 | BRF_GRA }, // 3 + + { "213-m1.m1", 0x020000, 0x200045f1, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "213-v1.v1", 0x200000, 0xa421c076, 5 | BRF_SND }, // 5 Sound data + { "213-v2.v2", 0x200000, 0x233c7dd9, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(neodrift, neodrift, neogeo) +STD_ROM_FN(neodrift) + +struct BurnDriver BurnDrvneodrift = { + "neodrift", NULL, "neogeo", NULL, "1996", + "Neo Drift Out - New Technology\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_RACING, 0, + NULL, neodriftRomInfo, neodriftRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Breakers + +static struct BurnRomInfo breakersRomDesc[] = { + { "230-p1.p1", 0x200000, 0xed24a6e6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "230-s1.s1", 0x020000, 0x076fb64c, 2 | BRF_GRA }, // 1 Text layer tiles + + { "230-c1.c1", 0x400000, 0x68d4ae76, 3 | BRF_GRA }, // 2 Sprite data + { "230-c2.c2", 0x400000, 0xfdee05cd, 3 | BRF_GRA }, // 3 + { "230-c3.c3", 0x400000, 0x645077f3, 3 | BRF_GRA }, // 4 + { "230-c4.c4", 0x400000, 0x63aeb74c, 3 | BRF_GRA }, // 5 + + { "230-m1.m1", 0x020000, 0x3951a1c1, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "230-v1.v1", 0x400000, 0x7f9ed279, 5 | BRF_SND }, // 7 Sound data + { "230-v2.v2", 0x400000, 0x1d43e420, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(breakers, breakers, neogeo) +STD_ROM_FN(breakers) + +struct BurnDriver BurnDrvbreakers = { + "breakers", NULL, "neogeo", NULL, "1996", + "Breakers\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, breakersRomInfo, breakersRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Puzzle De Pon! R! + +static struct BurnRomInfo puzzldprRomDesc[] = { + { "235-p1.p1", 0x080000, 0xafed5de2, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "235-s1.s1", 0x010000, 0x5a68d91e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "202-c1.c1", 0x100000, 0xcc0095ef, 3 | BRF_GRA }, // 2 Sprite data + { "202-c2.c2", 0x100000, 0x42371307, 3 | BRF_GRA }, // 3 + + { "202-m1.m1", 0x020000, 0x9c0291ea, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "202-v1.v1", 0x080000, 0xdebeb8fb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(puzzldpr, puzzldpr, neogeo) +STD_ROM_FN(puzzldpr) + +struct BurnDriver BurnDrvpuzzldpr = { + "puzzldpr", "puzzledp", "neogeo", NULL, "1997", + "Puzzle De Pon! R!\0", NULL, "Taito (Visco license)", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, puzzldprRomInfo, puzzldprRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Breakers Revenge + +static struct BurnRomInfo breakrevRomDesc[] = { + { "245-p1.p1", 0x200000, 0xc828876d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "245-s1.s1", 0x020000, 0xe7660a5d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "245-c1.c1", 0x400000, 0x68d4ae76, 3 | BRF_GRA }, // 2 Sprite data + { "245-c2.c2", 0x400000, 0xfdee05cd, 3 | BRF_GRA }, // 3 + { "245-c3.c3", 0x400000, 0x645077f3, 3 | BRF_GRA }, // 4 + { "245-c4.c4", 0x400000, 0x63aeb74c, 3 | BRF_GRA }, // 5 + { "245-c5.c5", 0x400000, 0xb5f40e7f, 3 | BRF_GRA }, // 6 + { "245-c6.c6", 0x400000, 0xd0337328, 3 | BRF_GRA }, // 7 + + { "245-m1.m1", 0x020000, 0x00f31c66, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "245-v1.v1", 0x400000, 0xe255446c, 5 | BRF_SND }, // 9 Sound data + { "245-v2.v2", 0x400000, 0x9068198a, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(breakrev, breakrev, neogeo) +STD_ROM_FN(breakrev) + +struct BurnDriver BurnDrvbreakrev = { + "breakrev", NULL, "neogeo", NULL, "1998", + "Breakers Revenge\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VSFIGHT, 0, + NULL, breakrevRomInfo, breakrevRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Battle Flip Shot + +static struct BurnRomInfo flipshotRomDesc[] = { + { "247-p1.p1", 0x100000, 0x95779094, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "247-s1.s1", 0x020000, 0x6300185c, 2 | BRF_GRA }, // 1 Text layer tiles + + { "247-c1.c1", 0x200000, 0xc9eedcb2, 3 | BRF_GRA }, // 2 Sprite data + { "247-c2.c2", 0x200000, 0x7d6d6e87, 3 | BRF_GRA }, // 3 + + { "247-m1.m1", 0x020000, 0xa9fe0144, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "247-v1.v1", 0x200000, 0x42ec743d, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(flipshot, flipshot, neogeo) +STD_ROM_FN(flipshot) + +struct BurnDriver BurnDrvflipshot = { + "flipshot", NULL, "neogeo", NULL, "1998", + "Battle Flip Shot\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_BALLPADDLE, 0, + NULL, flipshotRomInfo, flipshotRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Captain Tomaday + +static struct BurnRomInfo ctomadayRomDesc[] = { + { "249-p1.p1", 0x200000, 0xc9386118, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "249-s1.s1", 0x020000, 0xdc9eb372, 2 | BRF_GRA }, // 1 Text layer tiles + + { "249-c1.c1", 0x400000, 0x041fb8ee, 3 | BRF_GRA }, // 2 Sprite data + { "249-c2.c2", 0x400000, 0x74f3cdf4, 3 | BRF_GRA }, // 3 + + { "249-m1.m1", 0x020000, 0x80328a47, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "249-v1.v1", 0x400000, 0xde7c8f27, 5 | BRF_SND }, // 5 Sound data + { "249-v2.v2", 0x100000, 0xc8e40119, 5 | BRF_SND }, // 6 +}; + +STDROMPICKEXT(ctomaday, ctomaday, neogeo) +STD_ROM_FN(ctomaday) + +struct BurnDriver BurnDrvctomaday = { + "ctomaday", NULL, "neogeo", NULL, "1999", + "Captain Tomaday\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_VERSHOOT, 0, + NULL, ctomadayRomInfo, ctomadayRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ganryu / Musashi Ganryuki + +static struct BurnRomInfo ganryuRomDesc[] = { + { "252-p1.p1", 0x200000, 0x4b8ac4fb, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "252-c1.c1", 0x800000, 0x50ee7882, 3 | BRF_GRA }, // 1 Sprite data + { "252-c2.c2", 0x800000, 0x62585474, 3 | BRF_GRA }, // 2 + + { "252-m1.m1", 0x020000, 0x30cc4099, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "252-v1.v1", 0x400000, 0xe5946733, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(ganryu, ganryu, neogeo) +STD_ROM_FN(ganryu) + +static INT32 ganryuInit() +{ + nNeoProtectionXor = 0x07; + return NeoInit(); +} + +struct BurnDriver BurnDrvganryu = { + "ganryu", NULL, "neogeo", NULL, "1999", + "Ganryu / Musashi Ganryuki\0", NULL, "Visco", "Neo Geo MVS", + L"Ganryu\0\u6B66\u8535\u5DCC\u6D41\u8A18\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP | HARDWARE_SNK_CMC42, GBF_PLATFORM, 0, + NULL, ganryuRomInfo, ganryuRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + ganryuInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Bang Bead + +static struct BurnRomInfo bangbeadRomDesc[] = { + { "259-p1.p1", 0x200000, 0x88a37f8b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "259-c1.c1", 0x800000, 0x1f537f74, 3 | BRF_GRA }, // 1 Sprite data + { "259-c2.c2", 0x800000, 0x0efd98ff, 3 | BRF_GRA }, // 2 + + { "259-m1.m1", 0x020000, 0x85668ee9, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "259-v1.v1", 0x400000, 0x088eb8ab, 5 | BRF_SND }, // 4 Sound data + { "259-v2.v2", 0x100000, 0x97528fe9, 5 | BRF_SND }, // 5 +}; + +STDROMPICKEXT(bangbead, bangbead, neogeo) +STD_ROM_FN(bangbead) + +static INT32 bangbeadInit() +{ + nNeoProtectionXor = 0xF8; + return NeoInit(); +} + +struct BurnDriver BurnDrvbangbead = { + "bangbead", NULL, "neogeo", NULL, "2000", + "Bang Bead\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP | HARDWARE_SNK_CMC42, GBF_BALLPADDLE, 0, + NULL, bangbeadRomInfo, bangbeadRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + bangbeadInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 4 (NGM-2630) + +static struct BurnRomInfo mslug4RomDesc[] = { + { "263-p1.p1", 0x100000, 0x27e4def3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "263-p2.sp2", 0x400000, 0xfdb7aed8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "263-c1.c1", 0x800000, 0x84865f8a, 3 | BRF_GRA }, // 2 Sprite data + { "263-c2.c2", 0x800000, 0x81df97f2, 3 | BRF_GRA }, // 3 + { "263-c3.c3", 0x800000, 0x1a343323, 3 | BRF_GRA }, // 4 + { "263-c4.c4", 0x800000, 0x942cfb44, 3 | BRF_GRA }, // 5 + { "263-c5.c5", 0x800000, 0xa748854f, 3 | BRF_GRA }, // 6 + { "263-c6.c6", 0x800000, 0x5c8ba116, 3 | BRF_GRA }, // 7 + + { "263-m1.m1", 0x020000, 0x46ac8228, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "263-v1.v1", 0x800000, 0x01e9b9cd, 5 | BRF_SND }, // 9 Sound data + { "263-v2.v2", 0x800000, 0x4ab2bf81, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(mslug4, mslug4, neogeo) +STD_ROM_FN(mslug4) + +static INT32 mslug4Init() +{ + INT32 nRet; + +// nNeoTextROMSize = 0x080000; + nNeoProtectionXor = 0x31; + + nRet = NeoInit(); + + if (nRet == 0) { + PCM2DecryptV(0x1000000, 1); + } + + return nRet; +} + +struct BurnDriver BurnDrvmslug4 = { + "mslug4", NULL, "neogeo", NULL, "2002", + "Metal Slug 4 (NGM-2630)\0", NULL, "Mega", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug4RomInfo, mslug4RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug4Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Metal Slug 4 (NGH-2630) + +static struct BurnRomInfo mslug4hRomDesc[] = { + { "263-ph1.p1", 0x100000, 0xc67f5c8d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "263-ph2.sp2", 0x400000, 0xbc3ec89e, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "263-c1.c1", 0x800000, 0x84865f8a, 3 | BRF_GRA }, // 2 Sprite data + { "263-c2.c2", 0x800000, 0x81df97f2, 3 | BRF_GRA }, // 3 + { "263-c3.c3", 0x800000, 0x1a343323, 3 | BRF_GRA }, // 4 + { "263-c4.c4", 0x800000, 0x942cfb44, 3 | BRF_GRA }, // 5 + { "263-c5.c5", 0x800000, 0xa748854f, 3 | BRF_GRA }, // 6 + { "263-c6.c6", 0x800000, 0x5c8ba116, 3 | BRF_GRA }, // 7 + + { "263-m1.m1", 0x020000, 0x46ac8228, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "263-v1.v1", 0x800000, 0x01e9b9cd, 5 | BRF_SND }, // 9 Sound data + { "263-v2.v2", 0x800000, 0x4ab2bf81, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(mslug4h, mslug4h, neogeo) +STD_ROM_FN(mslug4h) + +struct BurnDriver BurnDrvmslug4h = { + "mslug4h", "mslug4", "neogeo", NULL, "2002", + "Metal Slug 4 (NGH-2630)\0", NULL, "Mega", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug4hRomInfo, mslug4hRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug4Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Metal Slug 4 Plus (bootleg) + +static struct BurnRomInfo ms4plusRomDesc[] = { + { "ms4-p1p.bin", 0x100000, 0x806a6e04, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "263-p2.sp2", 0x400000, 0xfdb7aed8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "ms4-s1p.bin", 0x020000, 0x07ff87ce, 2 | BRF_GRA }, // 2 Text layer tiles + + { "263-c1.c1", 0x800000, 0x84865f8a, 3 | BRF_GRA }, // 3 Sprite data + { "263-c2.c2", 0x800000, 0x81df97f2, 3 | BRF_GRA }, // 4 + { "263-c3.c3", 0x800000, 0x1a343323, 3 | BRF_GRA }, // 5 + { "263-c4.c4", 0x800000, 0x942cfb44, 3 | BRF_GRA }, // 6 + { "263-c5.c5", 0x800000, 0xa748854f, 3 | BRF_GRA }, // 7 + { "263-c6.c6", 0x800000, 0x5c8ba116, 3 | BRF_GRA }, // 8 + + { "263-m1.m1", 0x020000, 0x46ac8228, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "263-v1.v1", 0x800000, 0x01e9b9cd, 5 | BRF_SND }, // 9 Sound data + { "263-v2.v2", 0x800000, 0x4ab2bf81, 5 | BRF_SND }, // 10 +}; + +STDROMPICKEXT(ms4plus, ms4plus, neogeo) +STD_ROM_FN(ms4plus) + +struct BurnDriver BurnDrvms4plus = { + "ms4plus", "mslug4", "neogeo", NULL, "2002", + "Metal Slug 4 Plus (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, ms4plusRomInfo, ms4plusRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug4Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Rage of the Dragons (NGM-264?) + +static struct BurnRomInfo rotdRomDesc[] = { + { "264-p1.p1", 0x800000, 0xb8cc969d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "264-c1.c1", 0x800000, 0x4f148fee, 3 | BRF_GRA }, // 1 Sprite data + { "264-c2.c2", 0x800000, 0x7cf5ff72, 3 | BRF_GRA }, // 2 + { "264-c3.c3", 0x800000, 0x64d84c98, 3 | BRF_GRA }, // 3 + { "264-c4.c4", 0x800000, 0x2f394a95, 3 | BRF_GRA }, // 4 + { "264-c5.c5", 0x800000, 0x6b99b978, 3 | BRF_GRA }, // 5 + { "264-c6.c6", 0x800000, 0x847d5c7d, 3 | BRF_GRA }, // 6 + { "264-c7.c7", 0x800000, 0x231d681e, 3 | BRF_GRA }, // 7 + { "264-c8.c8", 0x800000, 0xc5edb5c4, 3 | BRF_GRA }, // 8 + + { "264-m1.m1", 0x020000, 0x4dbd7b43, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "264-v1.v1", 0x800000, 0xfa005812, 5 | BRF_SND }, // 10 Sound data + { "264-v2.v2", 0x800000, 0xc3dc8bf0, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(rotd, rotd, neogeo) +STD_ROM_FN(rotd) + +static INT32 rotdInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x3F; + + nRet = NeoInit(); + + if (nRet == 0) { + PCM2DecryptV(0x1000000, 2); + } + + return nRet; +} + +struct BurnDriver BurnDrvrotd = { + "rotd", NULL, "neogeo", NULL, "2002", + "Rage of the Dragons (NGM-264?)\0", NULL, "Evoga / Playmore", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, 0, + NULL, rotdRomInfo, rotdRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + rotdInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Matrimelee / Shin Gouketsuji Ichizoku Toukon (NGM-2660) (NGH-2660) + +static struct BurnRomInfo matrimRomDesc[] = { + { "266-p1.p1", 0x100000, 0x5d4c2dc7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "266-p2.sp2", 0x400000, 0xa14b1906, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "266-c1.c1", 0x800000, 0x505f4e30, 3 | BRF_GRA }, // 2 Sprite data + { "266-c2.c2", 0x800000, 0x3cb57482, 3 | BRF_GRA }, // 3 + { "266-c3.c3", 0x800000, 0xf1cc6ad0, 3 | BRF_GRA }, // 4 + { "266-c4.c4", 0x800000, 0x45b806b7, 3 | BRF_GRA }, // 5 + { "266-c5.c5", 0x800000, 0x9a15dd6b, 3 | BRF_GRA }, // 6 + { "266-c6.c6", 0x800000, 0x281cb939, 3 | BRF_GRA }, // 7 + { "266-c7.c7", 0x800000, 0x4b71f780, 3 | BRF_GRA }, // 8 + { "266-c8.c8", 0x800000, 0x29873d33, 3 | BRF_GRA }, // 9 + + { "266-m1.m1", 0x020000, 0x456c3e6c, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "266-v1.v1", 0x800000, 0xa4f83690, 5 | BRF_SND }, // 11 Sound data + { "266-v2.v2", 0x800000, 0xd0f69eda, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(matrim, matrim, neogeo) +STD_ROM_FN(matrim) + +static INT32 matrimInit() +{ + INT32 nRet; + +// nNeoTextROMSize = 0x080000; + nNeoProtectionXor = 0x6A; + NeoCallbackActive->pInitialise = PCM2DecryptP; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0x01000, 0xffce20, { 0xc4, 0x83, 0xa8, 0x5f, 0x21, 0x27, 0x64, 0xaf } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvmatrim = { + "matrim", NULL, "neogeo", NULL, "2002", + "Matrimelee / Shin Gouketsuji Ichizoku Toukon (NGM-2660) (NGH-2660)\0", NULL, "Noise Factory / Atlus", "Neo Geo MVS", + L"\u65B0\u8C6A\u8840\u5BFA\u4E00\u65CF - \u95D8\u5A5A\0Matrimelee (NGM-2660) (NGH-2660)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_PWRINST, + NULL, matrimRomInfo, matrimRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + matrimInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Matrimelee / Shin Gouketsuji Ichizoku Toukon (bootleg) + +static struct BurnRomInfo matrimblRomDesc[] = { + { "266-p1.p1", 0x100000, 0x5d4c2dc7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "266-p2.sp2", 0x400000, 0xa14b1906, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "mart-c1.bin", 0x800000, 0xa5595656, 3 | BRF_GRA }, // 2 Sprite data + { "mart-c2.bin", 0x800000, 0xc5f7c300, 3 | BRF_GRA }, // 3 + { "mart-c3.bin", 0x800000, 0x574efd7d, 3 | BRF_GRA }, // 4 + { "mart-c4.bin", 0x800000, 0x109d54d9, 3 | BRF_GRA }, // 5 + { "mart-c5.bin", 0x800000, 0x15c9e882, 3 | BRF_GRA }, // 6 + { "mart-c6.bin", 0x800000, 0x77497b97, 3 | BRF_GRA }, // 7 + { "mart-c7.bin", 0x800000, 0xab481bb6, 3 | BRF_GRA }, // 8 + { "mart-c8.bin", 0x800000, 0x906cf267, 3 | BRF_GRA }, // 9 + + { "mart-m1.bin", 0x020000, 0x3ea96ab1, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "mart-v1.bin", 0x400000, 0x352b0a07, 5 | BRF_SND }, // 11 Sound data + { "mart-v2.bin", 0x400000, 0x1e9bd59e, 5 | BRF_SND }, // 12 + { "mart-v3.bin", 0x400000, 0xe8362fcc, 5 | BRF_SND }, // 13 + { "mart-v4.bin", 0x400000, 0xc8c79b19, 5 | BRF_SND }, // 14 +}; + +STDROMPICKEXT(matrimbl, matrimbl, neogeo) +STD_ROM_FN(matrimbl) + +static void matrimblCallback() +{ + INT32 i, j; + UINT8 *dst = (UINT8 *)malloc( 0x020000 ); + + if (dst) + { + memcpy(dst, NeoZ80ROMActive, 0x020000); + + for(i = 0; i < 0x020000; i++) { + j = i; + if (i & 0x00001) j ^= 0x00800; + if (i & 0x00002) j ^= 0x02000; + if (i & 0x00800) j ^= 0x10800; + if (i & 0x10000) j ^= 0x00800; + NeoZ80ROMActive[j] = dst[i]; + } + free (dst); + dst = NULL; + } + + PCM2DecryptP(); + DoPerm(0); + NeoCMCExtractSData(NeoSpriteROM[nNeoActiveSlot], NeoTextROM[nNeoActiveSlot], 0x4000000, 0x080000); +} + +static INT32 matrimblInit() +{ + INT32 nRet; + +// nNeoTextROMSize = 0x080000; + NeoCallbackActive->pInitialise = matrimblCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot] + 0x400000, 0x400000); + BurnByteswap(YM2610ADPCMAROM[nNeoActiveSlot] + 0xc00000, 0x400000); + } + + return nRet; +} + +struct BurnDriver BurnDrvmatrimbl = { + "matrimbl", "matrim", "neogeo", NULL, "2002", + "Matrimelee / Shin Gouketsuji Ichizoku Toukon (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + L"\u65B0\u8C6A\u8840\u5BFA\u4E00\u65CF - \u95D8\u5A5A\0Matrimelee (bootleg)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_ALTERNATE_TEXT, GBF_VSFIGHT, FBF_PWRINST, + NULL, matrimblRomInfo, matrimblRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + matrimblInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 320, 224, 4, 3 +}; + +// Jockey Grand Prix (set 1) + +static struct BurnRomInfo jockeygpRomDesc[] = { + { "008-epr.p1", 0x100000, 0x2fb7f388, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "008-c1.c1", 0x800000, 0xa9acbf18, 3 | BRF_GRA }, // 1 Sprite data + { "008-c2.c2", 0x800000, 0x6289eef9, 3 | BRF_GRA }, // 2 + + { "008-mg1.m1", 0x080000, 0xd163c690, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "008-v1.v1", 0x200000, 0x443eadba, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(jockeygp, jockeygp, neogeo) +STD_ROM_FN(jockeygp) + +INT32 jockeygpInit() +{ + nNeoProtectionXor = 0xAC; + return NeoInit(); +} + +struct BurnDriver BurnDrvjockeygp = { + "jockeygp", NULL, "neogeo", NULL, "2001", + "Jockey Grand Prix (set 1)\0", NULL, "Sun Amusement / BrezzaSoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_GAMBLING | HARDWARE_SNK_ENCRYPTED_M1, GBF_MISC, 0, + NULL, jockeygpRomInfo, jockeygpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + jockeygpInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Jockey Grand Prix (set 2) + +static struct BurnRomInfo jockeygpaRomDesc[] = { + { "008-epr_a.p1", 0x100000, 0xb8f35532, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "008-c1.c1", 0x800000, 0xa9acbf18, 3 | BRF_GRA }, // 1 Sprite data + { "008-c2.c2", 0x800000, 0x6289eef9, 3 | BRF_GRA }, // 2 + + { "008-mg1.m1", 0x080000, 0xd163c690, 4 | BRF_ESS | BRF_PRG }, // 3 Z80 code + + { "008-v1.v1", 0x200000, 0x443eadba, 5 | BRF_SND }, // 4 Sound data +}; + +STDROMPICKEXT(jockeygpa, jockeygpa, neogeo) +STD_ROM_FN(jockeygpa) + +struct BurnDriver BurnDrvjockeygpa = { + "jockeygpa", "jockeygp", "neogeo", NULL, "2001", + "Jockey Grand Prix (set 2)\0", NULL, "Sun Amusement / BrezzaSoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_GAMBLING | HARDWARE_SNK_ENCRYPTED_M1, GBF_MISC, 0, + NULL, jockeygpaRomInfo, jockeygpaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + jockeygpInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// V-Liner (set 1) + +static struct BurnRomInfo vlinerRomDesc[] = { + { "epr.p1", 0x080000, 0x72a2c043, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "s-1.s1", 0x020000, 0x972d8c31, 2 | BRF_GRA }, // 1 Text layer tiles + + { "c-1.c1", 0x080000, 0x5118f7c0, 3 | BRF_GRA }, // 2 Sprite data + { "c-2.c2", 0x080000, 0xefe9b33e, 3 | BRF_GRA }, // 3 + + { "m-1.m1", 0x010000, 0x9b92b7d1, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code +}; + +STDROMPICKEXT(vliner, vliner, neogeo) +STD_ROM_FN(vliner) + +struct BurnDriver BurnDrvvliner = { + "vliner", NULL, "neogeo", NULL, "2001", + "V-Liner (set 1)\0", NULL, "Dyna / BreezaSoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_GAMBLING, GBF_CASINO, 0, + NULL, vlinerRomInfo, vlinerRomName, NULL, NULL, vlinerInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// V-Liner (set 2) + +static struct BurnRomInfo vlineroRomDesc[] = { + { "epr_54.p1", 0x080000, 0x172efc18, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "s-1.s1", 0x020000, 0x972d8c31, 2 | BRF_GRA }, // 1 Text layer tiles + + { "c-1.c1", 0x080000, 0x5118f7c0, 3 | BRF_GRA }, // 2 Sprite data + { "c-2.c2", 0x080000, 0xefe9b33e, 3 | BRF_GRA }, // 3 + + { "m-1.m1", 0x010000, 0x9b92b7d1, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code +}; + +STDROMPICKEXT(vlinero, vlinero, neogeo) +STD_ROM_FN(vlinero) + +struct BurnDriver BurnDrvvlinero = { + "vlinero", "vliner", "neogeo", NULL, "2001", + "V-Liner (set 2)\0", NULL, "Dyna / BreezaSoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_GAMBLING, GBF_CASINO, 0, + NULL, vlineroRomInfo, vlineroRomName, NULL, NULL, vlinerInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Digger Man + +static struct BurnRomInfo diggermaRomDesc[] = { + { "dig-p1.bin", 0x080000, 0xeda433d7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "dig-s1.bin", 0x010000, 0x75a88c1f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "dig-c1.bin", 0x080000, 0x3db0a4ed, 3 | BRF_GRA }, // 2 Sprite data + { "dig-c2.bin", 0x080000, 0x3e632161, 3 | BRF_GRA }, // 3 + + { "dig-m1.bin", 0x010000, 0x833cdf1b, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "dig-v1.bin", 0x080000, 0xee15bda4, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(diggerma, diggerma, neogeo) +STD_ROM_FN(diggerma) + +struct BurnDriver BurnDrvdiggerma = { + "diggerma", NULL, "neogeo", NULL, "2000", + "Digger Man\0", NULL, "Kyle Hodgetts", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_MAZE, 0, + NULL, diggermaRomInfo, diggermaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// ----------------------------------------------------------------------------- +// Games not in MAME + +// Bang Bead (Prototype?) + +static struct BurnRomInfo bangbedpRomDesc[] = { + { "259-p1.bin", 0x200000, 0x88a37f8b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "259-s1p.bin", 0x020000, 0xbb50fb2d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "259-c1p.bin", 0x200000, 0xe3919e44, 3 | BRF_GRA }, // 2 Sprite data + { "259-c2p.bin", 0x200000, 0xbaf5a320, 3 | BRF_GRA }, // 3 + { "259-c3p.bin", 0x100000, 0xc8e52157, 3 | BRF_GRA }, // 4 + { "259-c4p.bin", 0x100000, 0x69fa8e60, 3 | BRF_GRA }, // 5 + + { "259-m1.bin", 0x020000, 0x85668ee9, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "259-v1p.bin", 0x200000, 0xe97b9385, 5 | BRF_SND }, // 7 Sound data + { "259-v2p.bin", 0x200000, 0xb0cbd70a, 5 | BRF_SND }, // 8 + { "259-v3p.bin", 0x100000, 0x97528fe9, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(bangbedp, bangbedp, neogeo) +STD_ROM_FN(bangbedp) + +struct BurnDriver BurnDrvbangbedp = { + "bangbedp", "bangbead", "neogeo", NULL, "2000", + "Bang Bead (Prototype?)\0", NULL, "Visco", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_BALLPADDLE, 0, + NULL, bangbedpRomInfo, bangbedpRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Crouching Tiger Hidden Dragon 2003 (The King of Fighters 2001 bootleg set 2) + +static struct BurnRomInfo cthd2k3aRomDesc[] = { + { "5003-p1a.bin", 0x100000, 0x1185fe39, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "5003-p2a.bin", 0x400000, 0xea71faf7, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "5003-s1a.bin", 0x020000, 0x174ccffd, 2 | BRF_GRA }, // 2 Text layer tiles + + { "5003-c1a.bin", 0x800000, 0xdc90c563, 3 | BRF_GRA }, // 3 Sprite data + { "5003-c2a.bin", 0x800000, 0x7b08d331, 3 | BRF_GRA }, // 4 + { "5003-c3.bin", 0x800000, 0xac4aff71, 3 | BRF_GRA }, // 5 + { "5003-c4.bin", 0x800000, 0xafef5d66, 3 | BRF_GRA }, // 6 + { "5003-c5.bin", 0x800000, 0xc7c1ae50, 3 | BRF_GRA }, // 7 + { "5003-c6.bin", 0x800000, 0x613197f9, 3 | BRF_GRA }, // 8 + { "5003-c7a.bin", 0x800000, 0xad2d72b3, 3 | BRF_GRA }, // 9 + { "5003-c8a.bin", 0x800000, 0x8c3fc1b5, 3 | BRF_GRA }, // 10 + + { "5003-m1a.bin", 0x020000, 0xa37cc447, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.bin", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "5003-v2a.bin", 0x400000, 0x2b498449, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.bin", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.bin", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(cthd2k3a, cthd2k3a, neogeo) +STD_ROM_FN(cthd2k3a) + +static void cthd2k3aCallback() +{ + INT32 i, n; + + // P-ROM Encryption + UINT8 nBank[] = { 0x06, 0x02, 0x04, 0x05, 0x01, 0x03, 0x00, 0x07, 0x27, 0x0E, 0x1C, 0x15, 0x1B, 0x17, 0x0A, 0x0F, 0x16, 0x14, 0x23, 0x0B, 0x22, 0x26, 0x08, 0x24, 0x21, 0x13, 0x1A, 0x0C, 0x19, 0x1D, 0x25, 0x10, 0x09, 0x20, 0x18, 0x1F, 0x1E, 0x12, 0x0D, 0x11 }; + + UINT8 *pTemp = (UINT8*)malloc(0x500000); + if (pTemp) { + for (i = 0; i < 0x500000 / 0x20000; i++) { + memcpy(pTemp + (i * 0x20000), Neo68KROMActive + (nBank[i] * 0x20000), 0x20000); + } + memcpy(Neo68KROMActive, pTemp, 0x500000); + free(pTemp); + pTemp = NULL; + } + + UINT16 *Rom = (UINT16*)Neo68KROMActive; + Rom[0xed00e / 2] = 0x4e71; + Rom[0xed394 / 2] = 0x4e71; + Rom[0xa2b7e / 2] = 0x4e71; + + // Text ROM + for (i = 0; i < 0x8000; i++) { + n = NeoTextROM[nNeoActiveSlot][0x08000 + i]; + NeoTextROM[nNeoActiveSlot][0x08000 + i] = NeoTextROM[nNeoActiveSlot][0x10000 + i]; + NeoTextROM[nNeoActiveSlot][0x10000 + i] = n; + } + + // Swap bits 15 & 16 in the address of the Z80 ROM + for (i = 0; i < 0x10000 / 2; i++) { + n = NeoZ80ROMActive[0x08000 + i]; + NeoZ80ROMActive[0x08000 + i] = NeoZ80ROMActive[0x10000 + i]; + NeoZ80ROMActive[0x10000 + i] = n; + } + + DoPerm(0); +} + +static INT32 cthd2k3aInit() +{ + NeoCallbackActive->pInitialise = cthd2k3aCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvcthd2k3a = { + "cthd2k3a", "kof2001", "neogeo", NULL, "2003", + "Crouching Tiger Hidden Dragon 2003 (The King of Fighters 2001 bootleg set 2)\0", NULL, "bootleg", "Neo Geo MVS", + L"Crouching Tiger Hidden Dragon 2003\0\u81E5\u864E\u85CF\u9F8D Crouching Tiger Hidden Dragon 2003 (The King of Fighters 2001 bootleg set 2)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, cthd2k3aRomInfo, cthd2k3aRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + cthd2k3aInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Idol Mahjong - final romance 2 (CD to MVS Conversion) + +static struct BurnRomInfo fr2chRomDesc[] = { + { "098-p1ch.bin", 0x080000, 0x9aa8cee0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "098-s1ch.bin", 0x020000, 0x764ac7aa, 2 | BRF_GRA }, // 1 Text layer tiles + + { "098-c1ch.bin", 0x100000, 0x6158cf4a, 3 | BRF_GRA }, // 2 Sprite data + { "098-c2ch.bin", 0x100000, 0x93a809a3, 3 | BRF_GRA }, // 3 + { "098-c3ch.bin", 0x100000, 0xfafa3381, 3 | BRF_GRA }, // 4 + { "098-c4ch.bin", 0x100000, 0x9895e23f, 3 | BRF_GRA }, // 5 + { "098-c5ch.bin", 0x100000, 0xeeaaa818, 3 | BRF_GRA }, // 6 + { "098-c6ch.bin", 0x100000, 0xf3d9a190, 3 | BRF_GRA }, // 7 + + { "098-m1ch.bin", 0x010000, 0xa455fa31, 4 | BRF_ESS | BRF_PRG }, // 8 Z80 code + + { "098-v1ch.bin", 0x100000, 0x92e175f0, 5 | BRF_SND }, // 9 Sound data +}; + +STDROMPICKEXT(fr2ch, fr2ch, neogeo) +STD_ROM_FN(fr2ch) + +static void fr2chCallback() +{ + UINT16 *src = (UINT16*)Neo68KROMActive; + UINT8 *rom = Neo68KROMActive; + + INT32 i; + UINT8 data[16] = { + 0x49, 0x46, 0x41, 0x4E, 0x20, 0x4C, 0x4F, 0x52, + 0x41, 0x4D, 0x43, 0x4E, 0x20, 0x45, 0x20, 0x32 + }; + + // change jsr to C004DA + src[0x01AF8 >> 1] = 0x04DA; // C00552 (Not used?) + src[0x01BF6 >> 1] = 0x04DA; // C0056A (fixes crash) + src[0x01ED8 >> 1] = 0x04DA; // C00570 (Not used?) + src[0x1C384 >> 1] = 0x04DA; // C00552 (fixes crash) + + // 0x001C06 - this routine can cause a loop/freeze + src[0x01C06 >> 1] = 0x4E75; + + // can cause bugs + // Move text for credit + coin info (Thanks to Kanyero) + memcpy (NeoTextROM + 0x20000, NeoTextROM + 0x20600, 0x140); + + // optional + // Hack in the proper identification (see setup menu [F2]) + for (i = 0; i < 0x10; i++) + { + rom[0x3A6 + i] = rom[0x61E + i] = rom[0x896 + i] = data[i]; + } + for (i = 0; i < 0x20; i += 4) + { + src[(0x40 + i + 2) >> 1] = 0x0426; + } + + // Album Fix + src[0x1C382 >> 1] = 0x0008; // C00552 + src[0x1C384 >> 1] = 0x0000; + src[0x80000 >> 1] = 0x33FC; + src[0x80002 >> 1] = 0x0001; + src[0x80004 >> 1] = 0x0020; + src[0x80006 >> 1] = 0x0002; + src[0x80008 >> 1] = 0x4E75; +} + +static INT32 fr2chInit() +{ + NeoCallbackActive->pInitialise = fr2chCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvfr2ch = { + "fr2ch", NULL, "neogeo", NULL, "1995", + "Idol Mahjong - final romance 2 (CD to MVS Conversion)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HACK, 2, HARDWARE_SNK_NEOGEO, GBF_MAHJONG, 0, + NULL, fr2chRomInfo, fr2chRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + fr2chInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Choutetsu Brikin'ger - Iron clad (Prototype) + +static struct BurnRomInfo ironcladRomDesc[] = { + { "220-p1p.p1", 0x200000, 0x62a942c6, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "220-s1p.s1", 0x020000, 0x372fe217, 2 | BRF_GRA }, // 1 Text layer tiles + + { "220-c1p.c1", 0x400000, 0x9aa2b7dc, 3 | BRF_GRA }, // 2 Sprite data + { "220-c2p.c2", 0x400000, 0x8a2ad708, 3 | BRF_GRA }, // 3 + { "220-c3p.c3", 0x400000, 0xd67fb15a, 3 | BRF_GRA }, // 4 + { "220-c4p.c4", 0x400000, 0xe73ea38b, 3 | BRF_GRA }, // 5 + + { "220-m1p.m1", 0x020000, 0x3a08bb63, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "220-v1p.v1", 0x400000, 0x8f30a215, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(ironclad, ironclad, neogeo) +STD_ROM_FN(ironclad) + +struct BurnDriver BurnDrvironclad = { + "ironclad", NULL, "neogeo", NULL, "1996", + "Choutetsu Brikin'ger - Iron clad (Prototype)\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_HORSHOOT, 0, + NULL, ironcladRomInfo, ironcladRomName, NULL, NULL, neogeoInputInfo, neogeousaDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + + +// Choutetsu Brikin'ger - Iron clad (Prototype, older) + +static struct BurnRomInfo ironcladoRomDesc[] = { + { "220-p1po.p1", 0x200000, 0xce37e3a0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "220-s1p.s1", 0x020000, 0x372fe217, 2 | BRF_GRA }, // 1 Text layer tiles + + { "220-c1p.c1", 0x400000, 0x9aa2b7dc, 3 | BRF_GRA }, // 2 Sprite data + { "220-c2p.c2", 0x400000, 0x8a2ad708, 3 | BRF_GRA }, // 3 + { "220-c3p.c3", 0x400000, 0xd67fb15a, 3 | BRF_GRA }, // 4 + { "220-c4p.c4", 0x400000, 0xe73ea38b, 3 | BRF_GRA }, // 5 + + { "220-m1p.m1", 0x020000, 0x3a08bb63, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "220-v1p.v1", 0x400000, 0x8f30a215, 5 | BRF_SND }, // 7 Sound data +}; + +STDROMPICKEXT(ironclado, ironclado, neogeo) +STD_ROM_FN(ironclado) + +struct BurnDriver BurnDrvironclado = { + "ironclado", "ironclad", "neogeo", NULL, "1996", + "Choutetsu Brikin'ger - Iron clad (Prototype, older)\0", NULL, "Saurus", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_PROTOTYPE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP, GBF_HORSHOOT, 0, + NULL, ironcladoRomInfo, ironcladoRomName, NULL, NULL, neogeoInputInfo, neogeousaDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2001 Plus (set 2, bootleg / hack) + +static struct BurnRomInfo kf2k1paRomDesc[] = { + { "2k1-p1a.bin", 0x100000, 0xf8a71b6f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "262-pg2.bin", 0x400000, 0x91eea062, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k1-s1a.bin", 0x020000, 0x50986eeb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "262-c1-08-e0.bin", 0x800000, 0x99cc785a, 3 | BRF_GRA }, // 3 Sprite data + { "262-c2-08-e0.bin", 0x800000, 0x50368cbf, 3 | BRF_GRA }, // 4 + { "262-c3-08-e0.bin", 0x800000, 0xfb14ff87, 3 | BRF_GRA }, // 5 + { "262-c4-08-e0.bin", 0x800000, 0x4397faf8, 3 | BRF_GRA }, // 6 + { "262-c5-08-e0.bin", 0x800000, 0x91f24be4, 3 | BRF_GRA }, // 7 + { "262-c6-08-e0.bin", 0x800000, 0xa31e4403, 3 | BRF_GRA }, // 8 + { "262-c7-08-e0.bin", 0x800000, 0x54d9d1ec, 3 | BRF_GRA }, // 9 + { "262-c8-08-e0.bin", 0x800000, 0x59289a6b, 3 | BRF_GRA }, // 10 + + { "265-262-m1.bin", 0x040000, 0xa7f8119f, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.bin", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "262-v2-08-e0.bin", 0x400000, 0x003f1843, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.bin", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.bin", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kf2k1pa, kf2k1pa, neogeo) +STD_ROM_FN(kf2k1pa) + +static void kf2k1paCallback() +{ + for (INT32 i = 0; i < 0x20000; i++) { + NeoTextROM[nNeoActiveSlot][i] = BITSWAP08(NeoTextROM[nNeoActiveSlot][i], 3, 2, 4, 5, 1, 6, 0, 7); + } +} + +static INT32 kf2k1paInit() +{ + nNeoProtectionXor = 0x1e; + NeoCallbackActive->pInitialise = kf2k1paCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkf2k1pa = { + "kf2k1pa", "kof2001", "neogeo", NULL, "2002", + "The King of Fighters 2001 Plus (set 2, bootleg / hack)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k1paRomInfo, kf2k1paRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k1paInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2001 Plus (set 1, bootleg / hack) + +static struct BurnRomInfo kf2k1plsRomDesc[] = { + { "2k1-p1p.bin", 0x100000, 0x758529a7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "262-pg2.bin", 0x400000, 0x91eea062, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k1-s1p.bin", 0x020000, 0x088657e6, 2 | BRF_GRA }, // 2 Text layer tiles + + { "262-c1-08-e0.bin", 0x800000, 0x99cc785a, 3 | BRF_GRA }, // 3 Sprite data + { "262-c2-08-e0.bin", 0x800000, 0x50368cbf, 3 | BRF_GRA }, // 4 + { "262-c3-08-e0.bin", 0x800000, 0xfb14ff87, 3 | BRF_GRA }, // 5 + { "262-c4-08-e0.bin", 0x800000, 0x4397faf8, 3 | BRF_GRA }, // 6 + { "262-c5-08-e0.bin", 0x800000, 0x91f24be4, 3 | BRF_GRA }, // 7 + { "262-c6-08-e0.bin", 0x800000, 0xa31e4403, 3 | BRF_GRA }, // 8 + { "262-c7-08-e0.bin", 0x800000, 0x54d9d1ec, 3 | BRF_GRA }, // 9 + { "262-c8-08-e0.bin", 0x800000, 0x59289a6b, 3 | BRF_GRA }, // 10 + + { "265-262-m1.bin", 0x040000, 0xa7f8119f, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "262-v1-08-e0.bin", 0x400000, 0x83d49ecf, 5 | BRF_SND }, // 12 Sound data + { "262-v2-08-e0.bin", 0x400000, 0x003f1843, 5 | BRF_SND }, // 13 + { "262-v3-08-e0.bin", 0x400000, 0x2ae38dbe, 5 | BRF_SND }, // 14 + { "262-v4-08-e0.bin", 0x400000, 0x26ec4dd9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kf2k1pls, kf2k1pls, neogeo) +STD_ROM_FN(kf2k1pls) + +static INT32 kf2k1plsInit() +{ + nNeoProtectionXor = 0x1e; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkf2k1pls = { + "kf2k1pls", "kof2001", "neogeo", NULL, "2002", + "The King of Fighters 2001 Plus (set 1, bootleg / hack)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k1plsRomInfo, kf2k1plsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k1plsInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 Plus (bootleg set 3) + +static struct BurnRomInfo kf2k2plbRomDesc[] = { + { "2k2-p1p.bin", 0x100000, 0x3ab03781, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265-p2.bin", 0x400000, 0x327266b8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k2-s1pb.bin", 0x020000, 0x2072d5e9, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.bin", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.bin", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.bin", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.bin", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.bin", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.bin", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.bin", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.bin", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.bin", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.bin", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.bin", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2plb, kf2k2plb, neogeo) +STD_ROM_FN(kf2k2plb) + +struct BurnDriver BurnDrvkf2k2plb = { + "kf2k2plb", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Plus (bootleg set 3)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2plbRomInfo, kf2k2plbRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof2002Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 Super (bootleg) + +static struct BurnRomInfo kf2k2plcRomDesc[] = { + { "2k2-p1pc.bin", 0x100000, 0xebedae17, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265-p2.bin", 0x400000, 0x327266b8, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "2k2-s1pc.bin", 0x020000, 0xfecbb589, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1.bin", 0x800000, 0x2b65a656, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2.bin", 0x800000, 0xadf18983, 3 | BRF_GRA }, // 4 + { "265-c3.bin", 0x800000, 0x875e9fd7, 3 | BRF_GRA }, // 5 + { "265-c4.bin", 0x800000, 0x2da13947, 3 | BRF_GRA }, // 6 + { "265-c5.bin", 0x800000, 0x61bd165d, 3 | BRF_GRA }, // 7 + { "265-c6.bin", 0x800000, 0x03fdd1eb, 3 | BRF_GRA }, // 8 + { "265-c7.bin", 0x800000, 0x1a2749d8, 3 | BRF_GRA }, // 9 + { "265-c8.bin", 0x800000, 0xab0bb549, 3 | BRF_GRA }, // 10 + + { "265-m1.bin", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "265-v1.bin", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 12 Sound data + { "265-v2.bin", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k2plc, kf2k2plc, neogeo) +STD_ROM_FN(kf2k2plc) + +static void kf2k2plcCallback() +{ + PCM2DecryptP(); + + garoubl_sx_decode(); +} + +static INT32 kf2k2plcInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0xEC; + NeoCallbackActive->pInitialise = kf2k2plcCallback; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k2plc = { + "kf2k2plc", "kof2002", "neogeo", NULL, "2002", + "The King of Fighters 2002 Super (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2plcRomInfo, kf2k2plcRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k2plcInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters 2002 (PlayStation 2 ver 0.4, EGHT hack) + +static struct BurnRomInfo kf2k2ps2RomDesc[] = { + { "265ps2-p1.bin", 0x100000, 0x336c4ca8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "265ps2-p2.bin", 0x500000, 0xcb0032bf, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "265ps2-s1.bin", 0x020000, 0x714ade47, 2 | BRF_GRA }, // 2 Text layer tiles + + { "265-c1_decrypted.bin", 0x800000, 0x7efa6ef7, 3 | BRF_GRA }, // 3 Sprite data + { "265-c2_decrypted.bin", 0x800000, 0xaa82948b, 3 | BRF_GRA }, // 4 + { "265-c3_decrypted.bin", 0x800000, 0x959fad0b, 3 | BRF_GRA }, // 5 + { "265-c4_decrypted.bin", 0x800000, 0xefe6a468, 3 | BRF_GRA }, // 6 + { "265-c5_decrypted.bin", 0x800000, 0x74bba7c6, 3 | BRF_GRA }, // 7 + { "265-c6_decrypted.bin", 0x800000, 0xe20d2216, 3 | BRF_GRA }, // 8 + { "265ps2-c7.bin", 0x800000, 0x1b1d35fb, 3 | BRF_GRA }, // 9 + { "265ps2-c8.bin", 0x800000, 0xa5e35d11, 3 | BRF_GRA }, // 10 + { "265ps2-c9.bin", 0x800000, 0xaa8bbc97, 3 | BRF_GRA }, // 11 + { "265ps2-c10.bin", 0x800000, 0x9832713d, 3 | BRF_GRA }, // 12 + + { "265-m1.bin", 0x020000, 0x85aaa632, 4 | BRF_ESS | BRF_PRG }, // 13 Z80 code + + { "265-v1.bin", 0x800000, 0x15e8f3f5, 5 | BRF_SND }, // 14 Sound data + { "265-v2.bin", 0x800000, 0xda41d6f9, 5 | BRF_SND }, // 15 +}; + +STDROMPICKEXT(kf2k2ps2, kf2k2ps2, neogeo) +STD_ROM_FN(kf2k2ps2) + +static INT32 kf2k2ps2Init() +{ + INT32 nRet; + + nRet = NeoInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0xa5000, 0x000000, { 0xf9, 0xe0, 0x5d, 0xf3, 0xea, 0x92, 0xbe, 0xef } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvkf2k2ps2 = { + "kf2k2ps2", "kof2002", "neogeo", NULL, "2007", + "The King of Fighters 2002 (PlayStation 2 ver 0.4, EGHT hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_ENCRYPTED_M1, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k2ps2RomInfo, kf2k2ps2RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k2ps2Init, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters Special Edition 2004 Plus (The King of Fighters 2002 bootleg) + +static struct BurnRomInfo kf2k4plsRomDesc[] = { + { "k2k4s-p1p.bin", 0x200000, 0xed97c684, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "k2k4s-p1.bin", 0x400000, 0xe6c50566, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "k2k4s-s1p.bin", 0x020000, 0xcc0ab564, 2 | BRF_GRA }, // 2 Text layer tiles + + { "k2k4s-c4.bin", 0x800000, 0x7a050288, 3 | BRF_GRA }, // 3 Sprite data + { "k2k4s-c8.bin", 0x800000, 0xe924afcf, 3 | BRF_GRA }, // 4 + { "k2k4s-c3.bin", 0x800000, 0x959fad0b, 3 | BRF_GRA }, // 5 + { "k2k4s-c7.bin", 0x800000, 0xefe6a468, 3 | BRF_GRA }, // 6 + { "k2k4s-c2.bin", 0x800000, 0x74bba7c6, 3 | BRF_GRA }, // 7 + { "k2k4s-c6.bin", 0x800000, 0xe20d2216, 3 | BRF_GRA }, // 8 + { "k2k4s-c1.bin", 0x800000, 0xfa705b2b, 3 | BRF_GRA }, // 9 + { "k2k4s-c5.bin", 0x800000, 0x2c912ff9, 3 | BRF_GRA }, // 10 + + { "k2k4s-m1.bin", 0x020000, 0x5a47d9ad, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "k2k4s-v2.bin", 0x800000, 0xe4ddfb3f, 5 | BRF_SND }, // 12 Sound data + { "k2k4s-v1.bin", 0x800000, 0xb887d287, 5 | BRF_SND }, // 13 +}; + +STDROMPICKEXT(kf2k4pls, kf2k4pls, neogeo) +STD_ROM_FN(kf2k4pls) + +static void kf2k4plsCallback() +{ + UINT8 *pTemp = (UINT8*)malloc(0x600000); + + if (pTemp) { + memcpy(pTemp, Neo68KROMActive, 0x600000); + memcpy(Neo68KROMActive + 0x000000, pTemp + 0x000000, 0x100000); + memcpy(Neo68KROMActive + 0x500000, pTemp + 0x100000, 0x100000); + memcpy(Neo68KROMActive + 0x400000, pTemp + 0x200000, 0x100000); + memcpy(Neo68KROMActive + 0x300000, pTemp + 0x300000, 0x100000); + memcpy(Neo68KROMActive + 0x200000, pTemp + 0x400000, 0x100000); + memcpy(Neo68KROMActive + 0x100000, pTemp + 0x500000, 0x100000); + + memset(pTemp, 0, 0x600000); + memcpy(pTemp + 0x000000, Neo68KROMActive + 0x000000, 0x100000); + memcpy(pTemp + 0x100000, Neo68KROMActive + 0x500000, 0x100000); + memcpy(Neo68KROMActive + 0x000000, pTemp + 0x1a0000, 0x020000); + memcpy(Neo68KROMActive + 0x020000, pTemp + 0x080000, 0x020000); + memcpy(Neo68KROMActive + 0x040000, pTemp + 0x140000, 0x020000); + memcpy(Neo68KROMActive + 0x060000, pTemp + 0x000000, 0x020000); + memcpy(Neo68KROMActive + 0x080000, pTemp + 0x180000, 0x020000); + memcpy(Neo68KROMActive + 0x0a0000, pTemp + 0x0a0000, 0x020000); + memcpy(Neo68KROMActive + 0x0c0000, pTemp + 0x100000, 0x020000); + memcpy(Neo68KROMActive + 0x0e0000, pTemp + 0x040000, 0x020000); + + free(pTemp); + pTemp = NULL; + } + + lans2004_sx_decode(); +} + +static INT32 kf2k4plsInit() +{ + NeoCallbackActive->pInitialise = kf2k4plsCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkf2k4pls = { + "kf2k4pls", "kof2002", "neogeo", NULL, "2004", + "The King of Fighters Special Edition 2004 Plus (The King of Fighters 2002 bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kf2k4plsRomInfo, kf2k4plsRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kf2k4plsInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '96 (Anniversary Edition, EGHT hack) + +static struct BurnRomInfo kof96aeRomDesc[] = { + { "214ae-p1.bin", 0x100000, 0x47660e7c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "214ae-p2.bin", 0x400000, 0x824ff3eb, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "214ae-s1.bin", 0x020000, 0x203b3aaf, 2 | BRF_GRA }, // 2 Text layer tiles + + { "214ae-c1.bin", 0x400000, 0xb308c1f9, 3 | BRF_GRA }, // 3 Sprite data + { "214ae-c2.bin", 0x400000, 0x220a92b2, 3 | BRF_GRA }, // 4 + { "214-c3.bin", 0x400000, 0x64989a65, 3 | BRF_GRA }, // 5 + { "214-c4.bin", 0x400000, 0xafbea515, 3 | BRF_GRA }, // 6 + { "214ae-c5.bin", 0x400000, 0x6e03cb0c, 3 | BRF_GRA }, // 7 + { "214ae-c6.bin", 0x400000, 0xa90bc55d, 3 | BRF_GRA }, // 8 + { "214ae-c7.bin", 0x400000, 0x08021fd6, 3 | BRF_GRA }, // 9 + { "214ae-c8.bin", 0x400000, 0xbbd21b08, 3 | BRF_GRA }, // 10 + { "214ae-c9.bin", 0x400000, 0x57e5bf80, 3 | BRF_GRA }, // 11 + { "214ae-c10.bin",0x400000, 0xcbe44c81, 3 | BRF_GRA }, // 12 + { "214ae-c11.bin",0x400000, 0x5c7ddc8b, 3 | BRF_GRA }, // 13 + { "214ae-c12.bin",0x400000, 0x48d8b574, 3 | BRF_GRA }, // 14 + + { "214ae-m1.bin", 0x020000, 0xc9dd0348, 4 | BRF_ESS | BRF_PRG }, // 15 Z80 code + + { "214-v1.bin", 0x400000, 0x63f7b045, 5 | BRF_SND }, // 16 Sound data + { "214-v2.bin", 0x400000, 0x25929059, 5 | BRF_SND }, // 17 + { "214ae-v3.bin", 0x400000, 0x143923a7, 5 | BRF_SND }, // 18 +}; + +STDROMPICKEXT(kof96ae, kof96ae, neogeo) +STD_ROM_FN(kof96ae) + +struct BurnDriver BurnDrvkof96ae = { + "kof96ae", "kof96", "neogeo", NULL, "2007", + "The King of Fighters '96 (Anniversary Edition, EGHT hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof96aeRomInfo, kof96aeRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '96 (Chinese Edition ver 1.0, hack) + +static struct BurnRomInfo kof96cnRomDesc[] = { + { "214cn-p1.bin", 0x100000, 0xa8c25f0a, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "214cn-p2.bin", 0x200000, 0x0edface5, 1 | BRF_ESS | BRF_PRG }, // 1 + { "214cn-p3.bin", 0x500000, 0x8724a441, 1 | BRF_ESS | BRF_PRG }, // 2 + + { "214cn-s1.bin", 0x020000, 0xf917527a, 2 | BRF_GRA }, // 3 Text layer tiles + + { "214-c1.bin", 0x400000, 0x7ecf4aa2, 3 | BRF_GRA }, // 4 Sprite data + { "214-c2.bin", 0x400000, 0x05b54f37, 3 | BRF_GRA }, // 5 + { "214-c3.bin", 0x400000, 0x64989a65, 3 | BRF_GRA }, // 6 + { "214-c4.bin", 0x400000, 0xafbea515, 3 | BRF_GRA }, // 7 + { "214-c5.bin", 0x400000, 0x2a3bbd26, 3 | BRF_GRA }, // 8 + { "214-c6.bin", 0x400000, 0x44d30dc7, 3 | BRF_GRA }, // 9 + { "214-c7.bin", 0x400000, 0x3687331b, 3 | BRF_GRA }, // 10 + { "214-c8.bin", 0x400000, 0xfa1461ad, 3 | BRF_GRA }, // 11 + { "214cn-c9.bin", 0x400000, 0xa9f811d2, 3 | BRF_GRA }, // 12 + { "214cn-c10.bin",0x400000, 0x1147406a, 3 | BRF_GRA }, // 13 + + { "214-m1.bin", 0x020000, 0xdabc427c, 4 | BRF_ESS | BRF_PRG }, // 14 Z80 code + + { "214-v1.bin", 0x400000, 0x63f7b045, 5 | BRF_SND }, // 15 Sound data + { "214-v2.bin", 0x400000, 0x25929059, 5 | BRF_SND }, // 16 + { "214-v3.bin", 0x200000, 0x92a2257d, 5 | BRF_SND }, // 17 +}; + +STDROMPICKEXT(kof96cn, kof96cn, neogeo) +STD_ROM_FN(kof96cn) + +struct BurnDriver BurnDrvkof96cn = { + "kof96cn", "kof96", "neogeo", NULL, "200?", + "The King of Fighters '96 (Chinese Edition ver 1.0, hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof96cnRomInfo, kof96cnRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +static struct BurnRomInfo kof96epRomDesc[] = { + { "214-p1.bin", 0x100000, 0x52755d74, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "214-p2.bin", 0x200000, 0x002ccb73, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "214-s1.bin", 0x020000, 0x1254cbdb, 2 | BRF_GRA }, // 2 Text layer tiles + + { "214-c1.bin", 0x400000, 0x7ecf4aa2, 3 | BRF_GRA }, // 3 Sprite data + { "214-c2.bin", 0x400000, 0x05b54f37, 3 | BRF_GRA }, // 4 + { "214-c3.bin", 0x400000, 0x64989a65, 3 | BRF_GRA }, // 5 + { "214-c4.bin", 0x400000, 0xafbea515, 3 | BRF_GRA }, // 6 + { "214-c5.bin", 0x400000, 0x2a3bbd26, 3 | BRF_GRA }, // 7 + { "214-c6.bin", 0x400000, 0x44d30dc7, 3 | BRF_GRA }, // 8 + { "214-c7.bin", 0x400000, 0x3687331b, 3 | BRF_GRA }, // 9 + { "214-c8.bin", 0x400000, 0xfa1461ad, 3 | BRF_GRA }, // 10 + + { "214-m1.bin", 0x020000, 0xdabc427c, 4 | BRF_ESS | BRF_PRG }, // 11 Z80 code + + { "214-v1.bin", 0x400000, 0x63f7b045, 5 | BRF_SND }, // 12 Sound data + { "214-v2.bin", 0x400000, 0x25929059, 5 | BRF_SND }, // 13 + { "214-v3.bin", 0x200000, 0x92a2257d, 5 | BRF_SND }, // 14 + + { "kof96m_ep1.rom",0x080000, 0xe5f2fb43, 0 | BRF_ESS | BRF_PRG }, // 15 +}; + +STDROMPICKEXT(kof96ep, kof96ep, neogeo) +STD_ROM_FN(kof96ep) + +static void kof96epCallback() +{ + UINT8 *pTemp = (UINT8*)malloc(0x80000); + + if (pTemp) { + BurnLoadRom(pTemp, 15, 1); + + for (UINT32 i = 0; i < 0x80000; i++) { + if (pTemp[i] - Neo68KROMActive[i] == 8) pTemp[i] = Neo68KROMActive[i]; + } + + memcpy(Neo68KROMActive, pTemp, 0x80000); + + free(pTemp); + pTemp = NULL; + } +} + +static INT32 kof96epInit() +{ + NeoCallbackActive->pInitialise = kof96epCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkof96ep = { + "kof96ep", "kof96", "neogeo", NULL, "1996", + "The King of Fighters '96 (bootleg / hack)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof96epRomInfo, kof96epRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof96epInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 (10th Anniversary Chinese Edition, EGHT hack) + +static struct BurnRomInfo kof97cnRomDesc[] = { + { "232cn-p1.bin", 0x100000, 0x082933c8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232cn-p2.bin", 0x600000, 0xd22d3ca3, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "232cn-s1.bin", 0x020000, 0xde5ad278, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232cn-c1.bin", 0x800000, 0x8c3d2c0c, 3 | BRF_GRA }, // 3 Sprite data + { "232cn-c2.bin", 0x800000, 0x43ce69ae, 3 | BRF_GRA }, // 4 + { "232-c3.bin", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.bin", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.bin", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.bin", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1.bin", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.bin", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.bin", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.bin", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97cn, kof97cn, neogeo) +STD_ROM_FN(kof97cn) + +struct BurnDriver BurnDrvkof97cn = { + "kof97cn", "kof97", "neogeo", NULL, "2007", + "The King of Fighters '97 (10th Anniversary Chinese Edition, EGHT hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97cnRomInfo, kof97cnRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 Plus 2003 (bootleg / hack) + +static struct BurnRomInfo kof97plaRomDesc[] = { + { "kf97-p1a.bin", 0x100000, 0x035911c5, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232-p2.bin", 0x400000, 0x158b23f6, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "kf97-s1a.bin", 0x020000, 0x4ee2149a, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232-c1.bin", 0x800000, 0x5f8bf0a1, 3 | BRF_GRA }, // 3 Sprite data + { "232-c2.bin", 0x800000, 0xe4d45c81, 3 | BRF_GRA }, // 4 + { "232-c3.bin", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.bin", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232-c5.bin", 0x400000, 0x34fc4e51, 3 | BRF_GRA }, // 7 + { "232-c6.bin", 0x400000, 0x4ff4d47b, 3 | BRF_GRA }, // 8 + + { "232-m1.bin", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.bin", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.bin", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.bin", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97pla, kof97pla, neogeo) +STD_ROM_FN(kof97pla) + +static void kof97plaCallback() +{ + lans2004_sx_decode(); +} + +static INT32 kof97plaInit() +{ + NeoCallbackActive->pInitialise = kof97plaCallback; + + return NeoInit(); +} + +struct BurnDriver BurnDrvkof97pla = { + "kof97pla", "kof97", "neogeo", NULL, "2003", + "The King of Fighters '97 Plus 2003 (bootleg / hack)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97plaRomInfo, kof97plaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + kof97plaInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '97 - Final Battle (hack) + +static struct BurnRomInfo kof97xtRomDesc[] = { + { "232xt-p1.bin", 0x100000, 0x2e4f4e3b, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "232xt-p2.bin", 0x400000, 0x6d4503ce, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "232xt-s1.bin", 0x020000, 0xd6fe166f, 2 | BRF_GRA }, // 2 Text layer tiles + + { "232xt-c1.bin", 0x800000, 0xd504bf4a, 3 | BRF_GRA }, // 3 Sprite data + { "232xt-c2.bin", 0x800000, 0x942ea708, 3 | BRF_GRA }, // 4 + { "232-c3.bin", 0x800000, 0x581d6618, 3 | BRF_GRA }, // 5 + { "232-c4.bin", 0x800000, 0x49bb1e68, 3 | BRF_GRA }, // 6 + { "232xt-c5.bin", 0x800000, 0xc1bd2375, 3 | BRF_GRA }, // 7 + { "232xt-c6.bin", 0x800000, 0xa7c8506a, 3 | BRF_GRA }, // 8 + + { "232-m1.bin", 0x020000, 0x45348747, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "232-v1.bin", 0x400000, 0x22a2b5b5, 5 | BRF_SND }, // 10 Sound data + { "232-v2.bin", 0x400000, 0x2304e744, 5 | BRF_SND }, // 11 + { "232-v3.bin", 0x400000, 0x759eb954, 5 | BRF_SND }, // 12 +}; + +STDROMPICKEXT(kof97xt, kof97xt, neogeo) +STD_ROM_FN(kof97xt) + +struct BurnDriver BurnDrvkof97xt = { + "kof97xt", "kof97", "neogeo", NULL, "2007", + "The King of Fighters '97 - Final Battle (hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof97xtRomInfo, kof97xtRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// The King of Fighters '98 (Anniversary Edition, EGHT hack) + +static struct BurnRomInfo kof98aeRomDesc[] = { + { "242-p1ae.bin", 0x100000, 0xc9188c66, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "242-p2ae.bin", 0x600000, 0x609fac6b, 1 | BRF_ESS | BRF_PRG }, // 1 + + { "242-s1ae.bin", 0x020000, 0xf1fee5c0, 2 | BRF_GRA }, // 2 Text layer tiles + + { "242-c1ae.bin", 0x800000, 0x0319cfc9, 3 | BRF_GRA }, // 3 Sprite data + { "242-c2ae.bin", 0x800000, 0x553f6714, 3 | BRF_GRA }, // 4 + { "242-c3.bin", 0x800000, 0x22127b4f, 3 | BRF_GRA }, // 5 + { "242-c4.bin", 0x800000, 0x0b4fa044, 3 | BRF_GRA }, // 6 + { "242-c5ae.bin", 0x800000, 0x71641718, 3 | BRF_GRA }, // 7 + { "242-c6ae.bin", 0x800000, 0x982ba2b3, 3 | BRF_GRA }, // 8 + { "242-c7ae.bin", 0x800000, 0x8d495552, 3 | BRF_GRA }, // 9 + { "242-c8ae.bin", 0x800000, 0x8bfc3417, 3 | BRF_GRA }, // 10 + { "242-c9ae.bin", 0x800000, 0x128256d1, 3 | BRF_GRA }, // 11 + { "242-c91ae.bin",0x800000, 0x4bd8412d, 3 | BRF_GRA }, // 12 + { "242-c92ae.bin",0x800000, 0xe893277f, 3 | BRF_GRA }, // 13 + { "242-c93ae.bin",0x800000, 0xf165589e, 3 | BRF_GRA }, // 14 + + { "242-m1ae.bin", 0x040000, 0x9ade0528, 4 | BRF_ESS | BRF_PRG }, // 15 Z80 code + + { "242-v1.bin", 0x400000, 0xb9ea8051, 5 | BRF_SND }, // 16 Sound data + { "242-v2.bin", 0x400000, 0xcc11106e, 5 | BRF_SND }, // 17 + { "242-v3.bin", 0x400000, 0x044ea4e1, 5 | BRF_SND }, // 18 + { "242-v4.bin", 0x400000, 0x7985ea30, 5 | BRF_SND }, // 19 + { "242-v5ae.bin", 0x400000, 0xafdd9660, 5 | BRF_SND }, // 20 +}; + +STDROMPICKEXT(kof98ae, kof98ae, neogeo) +STD_ROM_FN(kof98ae) + +struct BurnDriver BurnDrvkof98ae = { + "kof98ae", "kof98", "neogeo", NULL, "2007", + "The King of Fighters '98 (Anniversary Edition, EGHT hack)\0", NULL, "hack", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_VSFIGHT, FBF_KOF, + NULL, kof98aeRomInfo, kof98aeRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Last Hope (Neo CD conversion) + +static struct BurnRomInfo lhcdbRomDesc[] = { + { "300-p1ch.bin", 0x100000, 0x0f7405d7, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "300-s1ch.bin", 0x020000, 0x298495d6, 2 | BRF_GRA }, // 1 Text data + + { "300-c1ch.bin", 0x400000, 0x554e6b73, 3 | BRF_GRA }, // 2 Sprite data + { "300-c2ch.bin", 0x400000, 0x7c84b0fc, 3 | BRF_GRA }, // 3 + { "300-c3ch.bin", 0x400000, 0x28ec7555, 3 | BRF_GRA }, // 4 + { "300-c4ch.bin", 0x400000, 0x8b7c236b, 3 | BRF_GRA }, // 5 + + { "300-m1ch.bin", 0x020000, 0xd9f6c153, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "300-v1ch.bin", 0x400000, 0xde563ec3, 5 | BRF_SND }, // 7 Sound data + { "300-v2ch.bin", 0x400000, 0x93478033, 5 | BRF_SND }, // 8 + { "300-v3ch.bin", 0x400000, 0xe0fc99ca, 5 | BRF_SND }, // 9 +}; + +STDROMPICKEXT(lhcdb, lhcdb, neogeo) +STD_ROM_FN(lhcdb) + +struct BurnDriver BurnDrvlhcdb = { + "lhcdb", NULL, "neogeo", NULL, "2007", + "Last Hope CD Beta (Neo CD conversion)\0", "Imperfect graphics", "NG:Dev.Team", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HACK, 2, HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, lhcdbRomInfo, lhcdbRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Metal Slug 5 (bootleg) + +static struct BurnRomInfo mslug5bRomDesc[] = { + { "ms5-p1b.bin", 0x500000, 0xd05853ea, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "268-c1c.bin", 0x800000, 0xab7c389a, 3 | BRF_GRA }, // 1 Sprite data + { "268-c2c.bin", 0x800000, 0x3560881b, 3 | BRF_GRA }, // 2 + { "268-c3c.bin", 0x800000, 0x3af955ea, 3 | BRF_GRA }, // 3 + { "268-c4c.bin", 0x800000, 0xc329c373, 3 | BRF_GRA }, // 4 + { "268-c5c.bin", 0x800000, 0x959c8177, 3 | BRF_GRA }, // 5 + { "268-c6c.bin", 0x800000, 0x010a831b, 3 | BRF_GRA }, // 6 + { "268-c7c.bin", 0x800000, 0x6d72a969, 3 | BRF_GRA }, // 7 + { "268-c8c.bin", 0x800000, 0x551d720e, 3 | BRF_GRA }, // 8 + + { "268-m1h.bin", 0x080000, 0x4a5a6e0e, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "268-v1c.bin", 0x800000, 0xae31d60c, 5 | BRF_SND }, // 10 Sound data + { "268-v2c.bin", 0x800000, 0xc40613ed, 5 | BRF_SND }, // 11 +}; + +STDROMPICKEXT(mslug5b, mslug5b, neogeo) +STD_ROM_FN(mslug5b) + +static void mslug5bCallback() +{ + UINT8 *pTemp = (UINT8*)malloc(0x500000); + + if (pTemp) { + memcpy(pTemp, Neo68KROMActive, 0x500000); + memset(Neo68KROMActive, 0, 0x500000); + memcpy(Neo68KROMActive + 0x000000, pTemp + 0x000000, 0x100000); + memcpy(Neo68KROMActive + 0x100000, pTemp + 0x100000, 0x100000); + memcpy(Neo68KROMActive + 0x300000, pTemp + 0x200000, 0x100000); + memcpy(Neo68KROMActive + 0x200000, pTemp + 0x300000, 0x100000); + memcpy(Neo68KROMActive + 0x400000, pTemp + 0x400000, 0x100000); + + free(pTemp); + pTemp = NULL; + } +} + +static INT32 mslug5bInit() +{ + INT32 nRet; + + nNeoProtectionXor = 0x19; + NeoCallbackActive->pInitialise = mslug5bCallback; + + nRet = NeoPVCInit(); + + if (nRet == 0) { + const PCM2DecryptV2Info Info = { 0x4e001, 0xfe2cf6, { 0xc3, 0xfd, 0x81, 0xac, 0x6d, 0xe7, 0xbf, 0x9e } }; + + PCM2DecryptV2(&Info); + } + + return nRet; +} + +struct BurnDriver BurnDrvmslug5b = { + "mslug5b", "mslug5", "neogeo", NULL, "2003", + "Metal Slug 5 (bootleg)\0", NULL, "bootleg", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO | HARDWARE_SNK_CMC50 | HARDWARE_SNK_ALTERNATE_TEXT | HARDWARE_SNK_ENCRYPTED_M1, GBF_PLATFORM, FBF_MSLUG, + NULL, mslug5bRomInfo, mslug5bRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + mslug5bInit, NeoPVCExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Zintrick / Oshidashi Zentrix (Neo CD conversion) + +static struct BurnRomInfo zintrkcdRomDesc[] = { + { "211-p1.bin", 0x100000, 0x9a0bfe0a, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "211-s1.bin", 0x020000, 0x56d16afa, 2 | BRF_GRA }, // 1 Text data + + { "zin-c1.bin", 0x200000, 0x76aee189, 3 | BRF_GRA }, // 2 Sprite data + { "zin-c2.bin", 0x200000, 0x844ed4b3, 3 | BRF_GRA }, // 3 + + { "211-m1.bin", 0x010000, 0xfcae1407, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "211-v1.bin", 0x100000, 0x781439da, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(zintrkcd, zintrkcd, neogeo) +STD_ROM_FN(zintrkcd) + +struct BurnDriver BurnDrvzintrkcd = { + "zintrkcd", "zintrckb", "neogeo", NULL, "1996", + "Zintrick / Oshidashi Zentrix (Neo CD conversion)\0", NULL, "hack", "Neo Geo MVS", + L"Zintrick\0\u62BC\u3057\u51FA\u3057\u30B8\u30F3\u30C8\u30EA\u30C3\u30AF (Neo CD conversion)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, zintrkcdRomInfo, zintrkcdRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// ----------------------------------------------------------------------------- +// Diagnostic Cartridges + +// Neo Geo 4 player test cartridge + +static struct BurnRomInfo fourplayRomDesc[] = { + { "4play_p1.rom", 0x100000, 0x3C3D741B, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "4play_s1.rom", 0x020000, 0xDE828076, 2 | BRF_GRA }, // 1 Text data + + { "4play_c1.rom", 0x020000, 0x7EE8CDCD, 3 | BRF_GRA }, // 2 Sprite data + { "4play_c2.rom", 0x020000, 0x7EE8CDCD, 3 | BRF_GRA }, // 3 + + { "4play_m1.rom", 0x020000, 0x5132580E, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "4play_v1.rom", 0x020000, 0x7EE8CDCD, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(fourplay, fourplay, neogeo) +STD_ROM_FN(fourplay) + +struct BurnDriver BurnDrv4play = { + "4play", NULL, "neogeo", NULL, "???", + "4 player input test\0", "4 player input test cartridge", "SNK", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 4, HARDWARE_SNK_NEOGEO | HARDWARE_SNK_4_JOYSTICKS, GBF_MISC, 0, + NULL, fourplayRomInfo, fourplayRomName, NULL, NULL, neodualInputInfo, neodualDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// ----------------------------------------------------------------------------- +// Demos and Homebrew + +// Shadow of the Beast (Neo Geo demo) + +static struct BurnRomInfo beastRomDesc[] = { + { "2002-p1.bin", 0x080000, 0x1f9e62a4, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "2002-s1.bin", 0x020000, 0x05a417f5, 2 | BRF_GRA }, // 1 Text layer tiles + + { "2002-c1.bin", 0x080000, 0xe1974741, 3 | BRF_GRA }, // 2 Sprite data + { "2002-c2.bin", 0x080000, 0x9f5b9cf6, 3 | BRF_GRA }, // 3 + + { "nnp-m1.rom", 0x010000, 0x7669de64, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "nnp-v1.rom", 0x080000, 0x504bf849, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(beast, beast, neogeo) +STD_ROM_FN(beast) + +struct BurnDriver BurnDrvbeast = { + "beast", NULL, "neogeo", NULL, "????", + "Shadow of the Beast (Neo Geo demo)\0", NULL, "Jeff Kurtz", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, beastRomInfo, beastRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Codename - Blut Engel (2006-01-19) + +static struct BurnRomInfo cnbeRomDesc[] = { + { "cnbe-p1.bin", 0x080000, 0x7ece4186, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "cnbe-s1.bin", 0x010000, 0x40a4698f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "cnbe-c1.bin", 0x100000, 0x0f4fea6f, 3 | BRF_GRA }, // 2 Sprite data + { "cnbe-c2.bin", 0x100000, 0x3d5fc36f, 3 | BRF_GRA }, // 3 + + { "cnbe-m1.bin", 0x020000, 0xa5821c9c, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "cnbe-v1.bin", 0x080000, 0x70191764, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(cnbe, cnbe, neogeo) +STD_ROM_FN(cnbe) + +struct BurnDriver BurnDrvcnbe = { + "cnbe", NULL, "neogeo", NULL, "2006", + "Codename - Blut Engel (2006-01-19)\0", NULL, "blastar@gmx.net", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_VERSHOOT, 0, + NULL, cnbeRomInfo, cnbeRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Columns (Neo Geo) + +static struct BurnRomInfo columnsnRomDesc[] = { + { "2000-p1.bin", 0x080000, 0xc6c9888d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "2000-s1.bin", 0x020000, 0x089a28a8, 2 | BRF_GRA }, // 1 Text layer tiles + + { "2000-c1.bin", 0x080000, 0x9a579cab, 3 | BRF_GRA }, // 2 Sprite data + { "2000-c2.bin", 0x080000, 0x91d14043, 3 | BRF_GRA }, // 3 + + { "nnp-m1.rom", 0x010000, 0x7669de64, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "nnp-v1.rom", 0x080000, 0x504bf849, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(columnsn, columnsn, neogeo) +STD_ROM_FN(columnsn) + +struct BurnDriver BurnDrvcolumnsn = { + "columnsn", NULL, "neogeo", NULL, "????", + "Columns (Neo Geo)\0", NULL, "homebrew", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, columnsnRomInfo, columnsnRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Jonas Indiana and the Lost Temple of RA (20050717) + +static struct BurnRomInfo ltorb1RomDesc[] = { + { "nnp-p1.rom", 0x040000, 0x353f6b05, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "nnp-s1.rom", 0x010000, 0x8224d8b7, 2 | BRF_GRA }, // 1 Text layer tiles + + { "nnp-c1.rom", 0x080000, 0x8b607198, 3 | BRF_GRA }, // 2 Sprite data + { "nnp-c2.rom", 0x080000, 0x6b96b59c, 3 | BRF_GRA }, // 3 + + { "nnp-m1.rom", 0x010000, 0x6847fd52, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "nnp-v1.rom", 0x080000, 0x0329c2e7, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(ltorb1, ltorb1, neogeo) +STD_ROM_FN(ltorb1) + +struct BurnDriver BurnDrvltorb1 = { + "ltorb1", NULL, "neogeo", NULL, "2005", + "Jonas Indiana and the Lost Temple of RA (20050717)\0", NULL, "blastar@gmx.net", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_PLATFORM, 0, + NULL, ltorb1RomInfo, ltorb1RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo 2500 Demo + +static struct BurnRomInfo neo2500RomDesc[] = { + { "2500-p1.bin", 0x080000, 0x2321c0d8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "2500-s1.bin", 0x010000, 0x1a37925c, 2 | BRF_GRA }, // 1 Text layer tiles + + { "2500-c1.bin", 0x080000, 0x8c304b56, 3 | BRF_GRA }, // 2 Sprite data + { "2500-c2.bin", 0x080000, 0x9a0758d6, 3 | BRF_GRA }, // 3 + + { "202-m1.bin", 0x020000, 0x9c0291ea, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "202-v1.bin", 0x080000, 0xdebeb8fb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neo2500, neo2500, neogeo) +STD_ROM_FN(neo2500) + +struct BurnDriver BurnDrvneo2500 = { + "neo2500", NULL, "neogeo", NULL, "2004", + "Neo 2500 Demo\0", NULL, "blastar@gmx.net", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, neo2500RomInfo, neo2500RomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Demo +static struct BurnRomInfo neodemoRomDesc[] = { + { "demo-p1.bin", 0x080000, 0xfbfce2a4, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "demo-s1.bin", 0x020000, 0xcd19264f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "demo-c1.bin", 0x100000, 0x870b28ea, 3 | BRF_GRA }, // 2 Sprite data + { "demo-c2.bin", 0x100000, 0x1ecf8128, 3 | BRF_GRA }, // 3 + + { "202-m1.bin", 0x020000, 0x9c0291ea, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "202-v1.bin", 0x080000, 0xdebeb8fb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neodemo, neodemo, neogeo) +STD_ROM_FN(neodemo) + +struct BurnDriver BurnDrvneodemo = { + "neodemo", NULL, "neogeo", NULL, "2002", + "Chaos Demo (Neo Geo)\0", NULL, "Chaos", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, neodemoRomInfo, neodemoRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo No Panepon (beta) + +static struct BurnRomInfo neonoponRomDesc[] = { + { "nnp-p1.rom", 0x080000, 0x8a792271, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "nnp-s1.rom", 0x010000, 0x93e6fe7d, 2 | BRF_GRA }, // 1 Text layer tiles + + { "nnp-c1.rom", 0x100000, 0x4a718ae3, 3 | BRF_GRA }, // 2 Sprite data + { "nnp-c2.rom", 0x100000, 0x0e2cbc25, 3 | BRF_GRA }, // 3 + + { "nnp-m1.rom", 0x010000, 0x7669de64, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "nnp-v1.rom", 0x080000, 0x504bf849, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neonopon, neonopon, neogeo) +STD_ROM_FN(neonopon) + +struct BurnDriver BurnDrvneonopon = { + "neonopon", NULL, "neogeo", NULL, "????", + "Neo No Panepon (beta)\0", NULL, "blastar@gmx.net", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, neonoponRomInfo, neonoponRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Pong + +static struct BurnRomInfo neopongRomDesc[] = { + { "pong_p1.rom", 0x020000, 0x9f35e29d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "pong_s1.rom", 0x020000, 0xcd19264f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "pong_c1.rom", 0x100000, 0xf5a57d1a, 3 | BRF_GRA }, // 2 Sprite data + { "pong_c2.rom", 0x100000, 0xaffde64e, 3 | BRF_GRA }, // 3 + + { "pong_m1.rom", 0x020000, 0x78c851cb, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "pong_v1.rom", 0x200000, 0x6c31223c, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neopong, neopong, neogeo) +STD_ROM_FN(neopong) + +struct BurnDriver BurnDrvneopong = { + "neopong", NULL, "neogeo", NULL, "2002", + "Neo Pong (ver 1.1)\0", NULL, "Neo Dev Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_BALLPADDLE, 0, + NULL, neopongRomInfo, neopongRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Pong (v1.0) + +static struct BurnRomInfo neopongaRomDesc[] = { + { "np10_p1.rom", 0x020000, 0x31b724d7, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "pong_s1.rom", 0x020000, 0xcd19264f, 2 | BRF_GRA }, // 1 Text layer tiles + + { "np10_c1.rom", 0x100000, 0xd7587282, 3 | BRF_GRA }, // 2 Sprite data + { "np10_c2.rom", 0x100000, 0xfefc9d06, 3 | BRF_GRA }, // 3 + + { "np10_m1.rom", 0x020000, 0x9c0291ea, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "np10_v1.rom", 0x080000, 0xdebeb8fb, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(neoponga, neoponga, neogeo) +STD_ROM_FN(neoponga) + +struct BurnDriverD BurnDrvneoponga = { + "neoponga", "neopong", "neogeo", NULL, "2002", + "Neo Pong (ver 1.0)\0", NULL, "Neo Dev Corporation", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_BALLPADDLE, 0, + NULL, neopongaRomInfo, neopongaRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// NGEM2K (beta 2006-01-18) + +static struct BurnRomInfo ngem2kRomDesc[] = { + { "ngem-p1.bin", 0x080000, 0xf2c42fe3, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "ngem-s1.bin", 0x010000, 0xfb3c02d2, 2 | BRF_GRA }, // 1 Text layer tiles + + { "ngem-c1.bin", 0x100000, 0xa8e2ab47, 3 | BRF_GRA }, // 2 Sprite data + { "ngem-c2.bin", 0x100000, 0xa738ea1c, 3 | BRF_GRA }, // 3 + + { "ngem-m1.bin", 0x020000, 0xb1f44a15, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "ngem-v1.bin", 0x080000, 0xc32199f0, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(ngem2k, ngem2k, neogeo) +STD_ROM_FN(ngem2k) + +struct BurnDriver BurnDrvngem2k = { + "ngem2k", NULL, "neogeo", NULL, "2006", + "NGEM2K (beta 2006-01-18)\0", NULL, "homebrew", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_PUZZLE, 0, + NULL, ngem2kRomInfo, ngem2kRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo Frog Feast + +static struct BurnRomInfo ngfrogRomDesc[] = { + { "frg-p1.bin", 0x080000, 0xc26848da, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "frg-s1.bin", 0x020000, 0x88f4cd13, 2 | BRF_GRA }, // 1 Text layer tiles + + { "frg-c1.bin", 0x100000, 0x7b2f9fb3, 3 | BRF_GRA }, // 2 Sprite data + { "frg-c2.bin", 0x100000, 0xa7f18a6f, 3 | BRF_GRA }, // 3 + { "frg-c3.bin", 0x100000, 0x956bac74, 3 | BRF_GRA }, // 4 + { "frg-c4.bin", 0x100000, 0x956bac74, 3 | BRF_GRA }, // 5 + + { "frg-m1.bin", 0x020000, 0xc825b484, 4 | BRF_ESS | BRF_PRG }, // 6 Z80 code + + { "frg-v1.bin", 0x100000, 0x2639da11, 5 | BRF_SND }, // 7 Sound data + { "frg-v2.bin", 0x100000, 0xe5eda58b, 5 | BRF_SND }, // 8 +}; + +STDROMPICKEXT(ngfrog, ngfrog, neogeo) +STD_ROM_FN(ngfrog) + +struct BurnDriver BurnDrvngfrog = { + "ngfrog", NULL, "neogeo", NULL, "2006", + "Frog Feast (Neo Geo)\0", NULL, "Rastersoft", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, ngfrogRomInfo, ngfrogRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Poker Night + +static struct BurnRomInfo poknightRomDesc[] = { + { "2003-p1.bin", 0x080000, 0x750421ee, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "2003-s1.bin", 0x020000, 0xa26d2f09, 2 | BRF_GRA }, // 1 Text layer tiles + + { "2003-c1.bin", 0x080000, 0x5fb2b761, 3 | BRF_GRA }, // 2 Sprite data + { "2003-c2.bin", 0x080000, 0xf2b570e3, 3 | BRF_GRA }, // 3 + + { "nnp-m1.rom", 0x010000, 0x7669de64, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "nnp-v1.rom", 0x080000, 0x504bf849, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(poknight, poknight, neogeo) +STD_ROM_FN(poknight) + +struct BurnDriver BurnDrvpoknight = { + "poknight", NULL, "neogeo", NULL, "????", + "Poker Night\0", NULL, "Jeff Kurtz", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NEOGEO, GBF_CASINO, 0, + NULL, poknightRomInfo, poknightRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Neo System Check (ver 1.0b) + +static struct BurnRomInfo syscheckRomDesc[] = { + { "sys-p1.rom", 0x080000, 0xa4adbe1e, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "sys-s1.rom", 0x010000, 0x4774f28e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "sys-c1.rom", 0x080000, 0x75660aac, 3 | BRF_GRA }, // 2 Sprite data + { "sys-c2.rom", 0x080000, 0x75660aac, 3 | BRF_GRA }, // 3 + + { "sys-m1.rom", 0x010000, 0x7669de64, 4 | BRF_ESS | BRF_PRG }, // 4 Z80 code + + { "sys-v1.rom", 0x080000, 0x504bf849, 5 | BRF_SND }, // 5 Sound data +}; + +STDROMPICKEXT(syscheck, syscheck, neogeo) +STD_ROM_FN(syscheck) + +struct BurnDriver BurnDrvsyscheck = { + "syscheck", NULL, "neogeo", NULL, "????", + "Neo System Check (ver 1.0b)\0", NULL, "blastar@gmx.net", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, syscheckRomInfo, syscheckRomName, NULL, NULL, neogeoInputInfo, neogeoDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Chip n Dale (Intro demo) + +static struct BurnRomInfo cndiRomDesc[] = { + { "cnd-p1.bin", 0x800000, 0x2df9a41d, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "cnd-s1.bin", 0x010000, 0x63b8b25e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "cnd-c1.bin", 0x400000, 0x55bd32fc, 3 | BRF_GRA }, // 2 Sprite data + { "cnd-c2.bin", 0x400000, 0xbbb43733, 3 | BRF_GRA }, // 3 + { "cnd-c3.bin", 0x400000, 0x715e0318, 3 | BRF_GRA }, // 4 + { "cnd-c4.bin", 0x400000, 0x016f3c7e, 3 | BRF_GRA }, // 5 + { "cnd-c5.bin", 0x400000, 0x28c6cb8c, 3 | BRF_GRA }, // 6 + { "cnd-c6.bin", 0x400000, 0x9c89503f, 3 | BRF_GRA }, // 7 + { "cnd-c7.bin", 0x400000, 0x074dd407, 3 | BRF_GRA }, // 8 + { "cnd-c8.bin", 0x400000, 0x5ddb7db5, 3 | BRF_GRA }, // 9 + + { "cnd-m1.bin", 0x002000, 0xae120a59, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "cnd-v1.bin", 0x092000, 0x91d45537, 5 | BRF_SND }, // 11 Sound data +}; + +STDROMPICKEXT(cndi, cndi, neogeo) +STD_ROM_FN(cndi) + +struct BurnDriver BurnDrvcndi = { + "cndi", NULL, "neogeo", NULL, "2009", + "Chip n Dale (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, cndiRomInfo, cndiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// DarkWing Duck (Intro demo) + +static struct BurnRomInfo dwiRomDesc[] = { + { "dwi-p1.bin", 0x800000, 0x8e3f2ea8, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "dwi-s1.bin", 0x010000, 0x3dc5c1ef, 2 | BRF_GRA }, // 1 Text layer tiles + + { "dwi-c1.bin", 0x400000, 0x2b8bda94, 3 | BRF_GRA }, // 2 Sprite data + { "dwi-c2.bin", 0x400000, 0x5345e4de, 3 | BRF_GRA }, // 3 + { "dwi-c3.bin", 0x400000, 0xc6185f14, 3 | BRF_GRA }, // 4 + { "dwi-c4.bin", 0x400000, 0xc9e59701, 3 | BRF_GRA }, // 5 + { "dwi-c5.bin", 0x400000, 0x42dd1c90, 3 | BRF_GRA }, // 6 + { "dwi-c6.bin", 0x400000, 0x9fa6d651, 3 | BRF_GRA }, // 7 + { "dwi-c7.bin", 0x400000, 0x5cfa6886, 3 | BRF_GRA }, // 8 + { "dwi-c8.bin", 0x400000, 0x59c37871, 3 | BRF_GRA }, // 9 + + { "dwi-m1.bin", 0x002000, 0x2249e065, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "dwi-v1.bin", 0x09b000, 0x13bb4ce4, 5 | BRF_SND }, // 11 Sound data +}; + +STDROMPICKEXT(dwi, dwi, neogeo) +STD_ROM_FN(dwi) + +struct BurnDriver BurnDrvdwi = { + "dwi", NULL, "neogeo", NULL, "2009", + "DarkWing Duck (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, dwiRomInfo, dwiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Duck Tales (Intro demo) + +static struct BurnRomInfo duckiRomDesc[] = { + { "duck-p1.bin", 0x800000, 0xf975711c, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "duck-s1.bin", 0x010000, 0x63b8b25e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "duck-c1.bin", 0x400000, 0x02adabba, 3 | BRF_GRA }, // 2 Sprite data + { "duck-c2.bin", 0x400000, 0x00bd87ac, 3 | BRF_GRA }, // 3 + { "duck-c3.bin", 0x400000, 0x263307c8, 3 | BRF_GRA }, // 4 + { "duck-c4.bin", 0x400000, 0xb8330c1e, 3 | BRF_GRA }, // 5 + { "duck-c5.bin", 0x400000, 0xce99fcb8, 3 | BRF_GRA }, // 6 + { "duck-c6.bin", 0x400000, 0xa6d30781, 3 | BRF_GRA }, // 7 + { "duck-c7.bin", 0x400000, 0xeda15323, 3 | BRF_GRA }, // 8 + { "duck-c8.bin", 0x400000, 0x400fd4cd, 3 | BRF_GRA }, // 9 + + { "duck-m1.bin", 0x002000, 0x7761d993, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "duck-v1.bin", 0x090200, 0x24b716ee, 5 | BRF_SND }, // 11 Sound data +}; + +STDROMPICKEXT(ducki, ducki, neogeo) +STD_ROM_FN(ducki) + +struct BurnDriver BurnDrvducki = { + "ducki", NULL, "neogeo", NULL, "2009", + "Duck Tales (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, duckiRomInfo, duckiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Ghost Busters (Intro demo) + +static struct BurnRomInfo ghostbiRomDesc[] = { + { "ghostb-p1.bin", 0x100000, 0xaf69ef5f, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + { "ghostb-p2.bin", 0x400000, 0xf57e393f, 1 | BRF_ESS | BRF_PRG }, // 1 68K code + + { "ghostb-s1.bin", 0x010000, 0x63b8b25e, 2 | BRF_GRA }, // 2 Text layer tiles + + { "ghostb-c1.bin", 0x400000, 0x4281fecd, 3 | BRF_GRA }, // 3 Sprite data + { "ghostb-c2.bin", 0x400000, 0x0f07018c, 3 | BRF_GRA }, // 4 + { "ghostb-c3.bin", 0x400000, 0xa4589b2a, 3 | BRF_GRA }, // 5 + { "ghostb-c4.bin", 0x400000, 0x2a72bd04, 3 | BRF_GRA }, // 6 + { "ghostb-c5.bin", 0x400000, 0xad3b72f9, 3 | BRF_GRA }, // 7 + { "ghostb-c6.bin", 0x400000, 0x963e0941, 3 | BRF_GRA }, // 8 + + { "ghostb-m1.bin", 0x002000, 0x6624e642, 4 | BRF_ESS | BRF_PRG }, // 9 Z80 code + + { "ghostb-v1.bin", 0x094a00, 0x44864761, 5 | BRF_SND }, // 10 Sound data +}; + +STDROMPICKEXT(ghostbi, ghostbi, neogeo) +STD_ROM_FN(ghostbi) + +struct BurnDriver BurnDrvghostbi = { + "ghostbi", NULL, "neogeo", NULL, "2009", + "Ghost Busters (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, ghostbiRomInfo, ghostbiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Robocop (Intro demo) + +static struct BurnRomInfo robocopiRomDesc[] = { + { "robo-p1.bin", 0x800000, 0xadcb4fe0, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "robo-s1.bin", 0x010000, 0x63b8b25e, 2 | BRF_GRA }, // 1 Text layer tiles + + { "robo-c1.bin", 0x400000, 0x8cf565a0, 3 | BRF_GRA }, // 2 Sprite data + { "robo-c2.bin", 0x400000, 0x76ef561d, 3 | BRF_GRA }, // 3 + { "robo-c3.bin", 0x400000, 0x7166790c, 3 | BRF_GRA }, // 4 + { "robo-c4.bin", 0x400000, 0xc0cdcbfc, 3 | BRF_GRA }, // 5 + { "robo-c5.bin", 0x400000, 0xa5ddc363, 3 | BRF_GRA }, // 6 + { "robo-c6.bin", 0x400000, 0x1fcc8fce, 3 | BRF_GRA }, // 7 + { "robo-c7.bin", 0x400000, 0xbe9f9da2, 3 | BRF_GRA }, // 8 + { "robo-c8.bin", 0x400000, 0x7cff633a, 3 | BRF_GRA }, // 9 + + { "robo-m1.bin", 0x002000, 0xc4d35e83, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "robo-v1.bin", 0x096000, 0xecb284a9, 5 | BRF_SND }, // 11 Sound data +}; + +STDROMPICKEXT(robocopi, robocopi, neogeo) +STD_ROM_FN(robocopi) + +struct BurnDriver BurnDrvrobocopi = { + "robocopi", NULL, "neogeo", NULL, "2009", + "Robocop (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, robocopiRomInfo, robocopiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; + +// Teenage Mutant Ninja Turtles (Intro demo) + +static struct BurnRomInfo tmntiRomDesc[] = { + { "tmnt-p1.bin", 0x800000, 0x2d5066ff, 1 | BRF_ESS | BRF_PRG }, // 0 68K code + + { "tmnt-s1.bin", 0x010000, 0x3dc5c1ef, 2 | BRF_GRA }, // 1 Text layer tiles + + { "tmnt-c1.bin", 0x400000, 0xae1735c1, 3 | BRF_GRA }, // 2 Sprite data + { "tmnt-c2.bin", 0x400000, 0x344281b5, 3 | BRF_GRA }, // 3 + { "tmnt-c3.bin", 0x400000, 0x1058a648, 3 | BRF_GRA }, // 4 + { "tmnt-c4.bin", 0x400000, 0x1c6ba1b0, 3 | BRF_GRA }, // 5 + { "tmnt-c5.bin", 0x400000, 0x73a89fb0, 3 | BRF_GRA }, // 6 + { "tmnt-c6.bin", 0x400000, 0xa139246a, 3 | BRF_GRA }, // 7 + { "tmnt-c7.bin", 0x400000, 0xed957842, 3 | BRF_GRA }, // 8 + { "tmnt-c8.bin", 0x400000, 0x8c15d91b, 3 | BRF_GRA }, // 9 + + { "tmnt-m1.bin", 0x002000, 0x953542ef, 4 | BRF_ESS | BRF_PRG }, // 10 Z80 code + + { "tmnt-v1.bin", 0x094900, 0x273640c3, 5 | BRF_SND }, // 11 Sound data +}; + +STDROMPICKEXT(tmnti, tmnti, neogeo) +STD_ROM_FN(tmnti) + +struct BurnDriver BurnDrvtmnti = { + "tmnti", NULL, "neogeo", NULL, "2009", + "Teenage Mutant Ninja Turtles (Intro demo)\0", "You must use the Universe BIOS and set region to Japan AES", "Demo", "Neo Geo MVS", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 2, HARDWARE_SNK_NEOGEO, GBF_MISC, 0, + NULL, tmntiRomInfo, tmntiRomName, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo, + NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette, + 0x1000, 304, 224, 4, 3 +}; diff --git a/src/burn/drivers/neogeo/neo_decrypt.cpp b/src/burn/drivers/neogeo/neo_decrypt.cpp new file mode 100644 index 00000000..ba06969d --- /dev/null +++ b/src/burn/drivers/neogeo/neo_decrypt.cpp @@ -0,0 +1,675 @@ +// This file is based on the MAME source code (see http://www.mame.net/) + +/*************************************************************************** + +NeoGeo 'C' ROM encryption + +Starting with KOF99, all NeoGeo games have encrypted graphics. Additionally +to that, the data for the front text layer, which was previously stored in +a separate ROM, is stored at the end of the tile data. + +The encryption is one of the nastiest implementation of a XOR scheme ever +seen, involving 9 seemingly uncorrelated 256-byte tables. All known games use +the same tables except KOF2000 and MS4 which use a different set. + +The 32 data bits of every longword are decrypted in a single step (one byte at +a time), but the values to use for the xor are determined in a convoluted way. +It's actually so convoluted that it's too difficult to describe - please refer +to the source below. +Suffice to say that bytes are handled in couples (0&3 and 1&2), and the two xor +values are taken from three tables, the indexes inside the tables depending on +bits 0-7 and 8-15 of the address, in one case further xored through the table +used in step 5) below. Additionally, the bytes in a couple can be swapped, +depending either on bit 8 of the address, or on bit 16 xored with the table +used in step 4) below. + +The 24 address bits are encrypted in five steps. Each step xors 8 bits with a +value taken from a different table; the index inside the table depends on 8 +other bits. +0) xor bits 0-7 with a fixed value that changes from game to game +1) xor bits 8-15 depending on bits 16-23 +2) xor bits 8-15 depending on bits 0-7 +3) xor bits 16-23 depending on bits 0-7 +4) xor bits 16-23 depending on bits 8-15 +5) xor bits 0-7 depending on bits 8-15 + +Each step acts on the current value, so e.g. step 4) uses bits 8-15 as modified +by step 2). + +[Note: the table used in step 1) is currently incomplete due to lack of data to +analyze] + + +There are two major weaknesses in this encryption algorithm, that exposed it to +a known plaintext attack. + +The first weakness is that the data xor depends on the address inside the +encrypted ROM instead that on the decrypted address; together with the high +concentration of 0x00 and 0xFF in the decrypted data (more than 60% of the +total), this exposed easily recognizable patterns in the encrypted data, which +could be exploited with some simple statistical checks. The deviousness of the +xor scheme was the major difficulty. + +The second weakness is that the address scrambling works on 32-bit words. Since +there are a large number of 32-bit values that appear only once in the whole +encrypted ROM space, this means that once the xor layer was broken, a large +table of encrypted-decrypted address correspondencies could be built and +analyzed, quickly leading to the algorithm. + +***************************************************************************/ + +#include "neogeo.h" +#include "bitswap.h" + + +const UINT8 *type0_t03; +const UINT8 *type0_t12; +const UINT8 *type1_t03; +const UINT8 *type1_t12; +const UINT8 *address_8_15_xor1; +const UINT8 *address_8_15_xor2; +const UINT8 *address_16_23_xor1; +const UINT8 *address_16_23_xor2; +const UINT8 *address_0_7_xor; + + +const UINT8 kof99_type0_t03[256] = +{ + 0xfb, 0x86, 0x9d, 0xf1, 0xbf, 0x80, 0xd5, 0x43, 0xab, 0xb3, 0x9f, 0x6a, 0x33, 0xd9, 0xdb, 0xb6, + 0x66, 0x08, 0x69, 0x88, 0xcc, 0xb7, 0xde, 0x49, 0x97, 0x64, 0x1f, 0xa6, 0xc0, 0x2f, 0x52, 0x42, + 0x44, 0x5a, 0xf2, 0x28, 0x98, 0x87, 0x96, 0x8a, 0x83, 0x0b, 0x03, 0x61, 0x71, 0x99, 0x6b, 0xb5, + 0x1a, 0x8e, 0xfe, 0x04, 0xe1, 0xf7, 0x7d, 0xdd, 0xed, 0xca, 0x37, 0xfc, 0xef, 0x39, 0x72, 0xda, + 0xb8, 0xbe, 0xee, 0x7f, 0xe5, 0x31, 0x78, 0xf3, 0x91, 0x9a, 0xd2, 0x11, 0x19, 0xb9, 0x09, 0x4c, + 0xfd, 0x6d, 0x2a, 0x4d, 0x65, 0xa1, 0x89, 0xc7, 0x75, 0x50, 0x21, 0xfa, 0x16, 0x00, 0xe9, 0x12, + 0x74, 0x2b, 0x1e, 0x4f, 0x14, 0x01, 0x70, 0x3a, 0x4e, 0x3f, 0xf5, 0xf4, 0x1d, 0x3d, 0x15, 0x27, + 0xa7, 0xff, 0x45, 0xe0, 0x6e, 0xf9, 0x54, 0xc8, 0x48, 0xad, 0xa5, 0x0a, 0xf6, 0x2d, 0x2c, 0xe2, + 0x68, 0x67, 0xd6, 0x85, 0xb4, 0xc3, 0x34, 0xbc, 0x62, 0xd3, 0x5f, 0x84, 0x06, 0x5b, 0x0d, 0x95, + 0xea, 0x5e, 0x9e, 0xd4, 0xeb, 0x90, 0x7a, 0x05, 0x81, 0x57, 0xe8, 0x60, 0x2e, 0x20, 0x25, 0x7c, + 0x46, 0x0c, 0x93, 0xcb, 0xbd, 0x17, 0x7e, 0xec, 0x79, 0xb2, 0xc2, 0x22, 0x41, 0xb1, 0x10, 0xac, + 0xa8, 0xbb, 0x9b, 0x82, 0x4b, 0x9c, 0x8b, 0x07, 0x47, 0x35, 0x24, 0x56, 0x8d, 0xaf, 0xe6, 0x26, + 0x40, 0x38, 0xc4, 0x5d, 0x1b, 0xc5, 0xd1, 0x0f, 0x6c, 0x7b, 0xb0, 0xe3, 0xa3, 0x23, 0x6f, 0x58, + 0xc1, 0xba, 0xcf, 0xd7, 0xa2, 0xe7, 0xd0, 0x63, 0x5c, 0xf8, 0x73, 0xa0, 0x13, 0xdc, 0x29, 0xcd, + 0xc9, 0x76, 0xae, 0x8f, 0xe4, 0x59, 0x30, 0xaa, 0x94, 0x1c, 0x3c, 0x0e, 0x55, 0x92, 0x77, 0x32, + 0xc6, 0xce, 0x18, 0x36, 0xdf, 0xa9, 0x8c, 0xd8, 0xa4, 0xf0, 0x3b, 0x51, 0x4a, 0x02, 0x3e, 0x53, +}; + +const UINT8 kof99_type0_t12[256] = +{ + 0x1f, 0xac, 0x4d, 0xcd, 0xca, 0x70, 0x02, 0x6b, 0x18, 0x40, 0x62, 0xb2, 0x3f, 0x9b, 0x5b, 0xef, + 0x69, 0x68, 0x71, 0x3b, 0xcb, 0xd4, 0x30, 0xbc, 0x47, 0x72, 0x74, 0x5e, 0x84, 0x4c, 0x1b, 0xdb, + 0x6a, 0x35, 0x1d, 0xf5, 0xa1, 0xb3, 0x87, 0x5d, 0x57, 0x28, 0x2f, 0xc4, 0xfd, 0x24, 0x26, 0x36, + 0xad, 0xbe, 0x61, 0x63, 0x73, 0xaa, 0x82, 0xee, 0x29, 0xd0, 0xdf, 0x8c, 0x15, 0xb5, 0x96, 0xf3, + 0xdd, 0x7e, 0x3a, 0x37, 0x58, 0x7f, 0x0c, 0xfc, 0x0b, 0x07, 0xe8, 0xf7, 0xf4, 0x14, 0xb8, 0x81, + 0xb6, 0xd7, 0x1e, 0xc8, 0x85, 0xe6, 0x9d, 0x33, 0x60, 0xc5, 0x95, 0xd5, 0x55, 0x00, 0xa3, 0xb7, + 0x7d, 0x50, 0x0d, 0xd2, 0xc1, 0x12, 0xe5, 0xed, 0xd8, 0xa4, 0x9c, 0x8f, 0x2a, 0x4f, 0xa8, 0x01, + 0x52, 0x83, 0x65, 0xea, 0x9a, 0x6c, 0x44, 0x4a, 0xe2, 0xa5, 0x2b, 0x46, 0xe1, 0x34, 0x25, 0xf8, + 0xc3, 0xda, 0xc7, 0x6e, 0x48, 0x38, 0x7c, 0x78, 0x06, 0x53, 0x64, 0x16, 0x98, 0x3c, 0x91, 0x42, + 0x39, 0xcc, 0xb0, 0xf1, 0xeb, 0x13, 0xbb, 0x05, 0x32, 0x86, 0x0e, 0xa2, 0x0a, 0x9e, 0xfa, 0x66, + 0x54, 0x8e, 0xd3, 0xe7, 0x19, 0x20, 0x77, 0xec, 0xff, 0xbd, 0x6d, 0x43, 0x23, 0x03, 0xab, 0x75, + 0x3d, 0xcf, 0xd1, 0xde, 0x92, 0x31, 0xa7, 0x45, 0x4b, 0xc2, 0x97, 0xf9, 0x7a, 0x88, 0xd9, 0x1c, + 0xe9, 0xe4, 0x10, 0xc9, 0x22, 0x2d, 0x90, 0x76, 0x17, 0x79, 0x04, 0x51, 0x1a, 0x5a, 0x5f, 0x2c, + 0x21, 0x6f, 0x3e, 0xe0, 0xf0, 0xbf, 0xd6, 0x94, 0x0f, 0x80, 0x11, 0xa0, 0x5c, 0xa9, 0x49, 0x2e, + 0xce, 0xaf, 0xa6, 0x9f, 0x7b, 0x99, 0xb9, 0xb4, 0xe3, 0xfb, 0xf6, 0x27, 0xf2, 0x93, 0xfe, 0x08, + 0x67, 0xae, 0x09, 0x89, 0xdc, 0x4e, 0xc6, 0xc0, 0x8a, 0xb1, 0x59, 0x8b, 0x41, 0x56, 0x8d, 0xba, +}; + +const UINT8 kof99_type1_t03[256] = +{ + 0xa9, 0x17, 0xaf, 0x0d, 0x34, 0x6e, 0x53, 0xb6, 0x7f, 0x58, 0xe9, 0x14, 0x5f, 0x55, 0xdb, 0xd4, + 0x42, 0x80, 0x99, 0x59, 0xa8, 0x3a, 0x57, 0x5d, 0xd5, 0x6f, 0x4c, 0x68, 0x35, 0x46, 0xa6, 0xe7, + 0x7b, 0x71, 0xe0, 0x93, 0xa2, 0x1f, 0x64, 0x21, 0xe3, 0xb1, 0x98, 0x26, 0xab, 0xad, 0xee, 0xe5, + 0xbb, 0xd9, 0x1e, 0x2e, 0x95, 0x36, 0xef, 0x23, 0x79, 0x45, 0x04, 0xed, 0x13, 0x1d, 0xf4, 0x85, + 0x96, 0xec, 0xc2, 0x32, 0xaa, 0x7c, 0x15, 0xd8, 0xda, 0x92, 0x90, 0x9d, 0xb7, 0x56, 0x6a, 0x66, + 0x41, 0xfc, 0x00, 0xf6, 0x50, 0x24, 0xcf, 0xfb, 0x11, 0xfe, 0x82, 0x48, 0x9b, 0x27, 0x1b, 0x67, + 0x4e, 0x84, 0x69, 0x97, 0x6d, 0x8c, 0xd2, 0xba, 0x74, 0xf9, 0x8f, 0xa5, 0x54, 0x5c, 0xcd, 0x73, + 0x07, 0xd1, 0x01, 0x09, 0xf1, 0x19, 0x3b, 0x5e, 0x87, 0x30, 0x76, 0xcc, 0xc0, 0x5a, 0xa7, 0x49, + 0x22, 0xfa, 0x16, 0x02, 0xdf, 0xa4, 0xff, 0xb3, 0x75, 0x33, 0xbd, 0x88, 0x2f, 0xcb, 0x2a, 0x44, + 0xb8, 0xbf, 0x1c, 0x0f, 0x81, 0x10, 0x43, 0xb4, 0xc8, 0x7e, 0x9a, 0x25, 0xea, 0x83, 0x4b, 0x38, + 0x7a, 0xd7, 0x3d, 0x1a, 0x4f, 0x62, 0x51, 0xc9, 0x47, 0x0e, 0xce, 0x3f, 0xc7, 0x4d, 0x2c, 0xa1, + 0x86, 0xb9, 0xc5, 0xca, 0xdd, 0x6b, 0x70, 0x6c, 0x91, 0x9c, 0xbe, 0x0a, 0x9f, 0xf5, 0x94, 0xbc, + 0x18, 0x2b, 0x60, 0x20, 0x29, 0xf7, 0xf2, 0x28, 0xc4, 0xa0, 0x0b, 0x65, 0xde, 0x8d, 0x78, 0x12, + 0x3e, 0xd0, 0x77, 0x08, 0x8b, 0xae, 0x05, 0x31, 0x3c, 0xd6, 0xa3, 0x89, 0x06, 0xdc, 0x52, 0x72, + 0xb0, 0xb5, 0x37, 0xd3, 0xc3, 0x8a, 0xc6, 0xf0, 0xc1, 0x61, 0xfd, 0x4a, 0x5b, 0x7d, 0x9e, 0xf3, + 0x63, 0x40, 0x2d, 0xe8, 0xb2, 0xe6, 0x39, 0x03, 0xeb, 0x8e, 0xe1, 0x0c, 0xe4, 0xe2, 0xf8, 0xac, +}; + +const UINT8 kof99_type1_t12[256] = +{ + 0xea, 0xe6, 0x5e, 0xa7, 0x8e, 0xac, 0x34, 0x03, 0x30, 0x97, 0x52, 0x53, 0x76, 0xf2, 0x62, 0x0b, + 0x0a, 0xfc, 0x94, 0xb8, 0x67, 0x36, 0x11, 0xbc, 0xae, 0xca, 0xfa, 0x15, 0x04, 0x2b, 0x17, 0xc4, + 0x3e, 0x5b, 0x59, 0x01, 0x57, 0xe2, 0xba, 0xb7, 0xd1, 0x3f, 0xf0, 0x6a, 0x9c, 0x2a, 0xcb, 0xa9, + 0xe3, 0x2c, 0xc0, 0x0f, 0x46, 0x91, 0x8a, 0xd0, 0x98, 0xc5, 0xa6, 0x1b, 0x96, 0x29, 0x12, 0x09, + 0x63, 0xed, 0xe0, 0xa2, 0x86, 0x77, 0xbe, 0xe5, 0x65, 0xdb, 0xbd, 0x50, 0xb3, 0x9d, 0x1a, 0x4e, + 0x79, 0x0c, 0x00, 0x43, 0xdf, 0x3d, 0x54, 0x33, 0x8f, 0x89, 0xa8, 0x7b, 0xf9, 0xd5, 0x27, 0x82, + 0xbb, 0xc2, 0x8c, 0x47, 0x88, 0x6b, 0xb4, 0xc3, 0xf8, 0xaa, 0x06, 0x1e, 0x83, 0x7d, 0x05, 0x78, + 0x85, 0xf6, 0x6e, 0x2e, 0xec, 0x5a, 0x31, 0x45, 0x38, 0x14, 0x16, 0x8b, 0x02, 0xe4, 0x4f, 0xb0, + 0xbf, 0xab, 0xa4, 0x9e, 0x48, 0x60, 0x19, 0x35, 0x08, 0xde, 0xdd, 0x66, 0x90, 0x51, 0xcc, 0xa3, + 0xaf, 0x70, 0x9b, 0x75, 0x95, 0x49, 0x6c, 0x64, 0x72, 0x7e, 0x44, 0xa0, 0x73, 0x25, 0x68, 0x55, + 0x1f, 0x40, 0x7a, 0x74, 0x0e, 0x8d, 0xdc, 0x1c, 0x71, 0xc8, 0xcf, 0xd7, 0xe8, 0xce, 0xeb, 0x32, + 0x3a, 0xee, 0x07, 0x61, 0x4d, 0xfe, 0x5c, 0x7c, 0x56, 0x2f, 0x2d, 0x5f, 0x6f, 0x9f, 0x81, 0x22, + 0x58, 0x4b, 0xad, 0xda, 0xb9, 0x10, 0x18, 0x23, 0xe1, 0xf3, 0x6d, 0xe7, 0xe9, 0x28, 0xd6, 0xd8, + 0xf4, 0x4c, 0x39, 0x21, 0xb2, 0x84, 0xc1, 0x24, 0x26, 0xf1, 0x93, 0x37, 0xc6, 0x4a, 0xcd, 0x20, + 0xc9, 0xd9, 0xc7, 0xb1, 0xff, 0x99, 0xd4, 0x5d, 0xb5, 0xa1, 0x87, 0x0d, 0x69, 0x92, 0x13, 0x80, + 0xd2, 0xd3, 0xfd, 0x1d, 0xf5, 0x3b, 0xa5, 0x7f, 0xef, 0x9a, 0xb6, 0x42, 0xfb, 0x3c, 0xf7, 0x41, +}; + + + +/* underlined values are wrong (not enough evidence, FF fill in kof99 and garou) */ +/* they correspond to tiles 7d000-7efff */ +const UINT8 kof99_address_8_15_xor1[256] = +{ + 0x00, 0xb1, 0x1e, 0xc5, 0x3d, 0x40, 0x45, 0x5e, 0xf2, 0xf8, 0x04, 0x63, 0x36, 0x87, 0x88, 0xbf, + 0xab, 0xcc, 0x78, 0x08, 0xdd, 0x20, 0xd4, 0x35, 0x09, 0x8e, 0x44, 0xae, 0x33, 0xa9, 0x9e, 0xcd, + 0xb3, 0xe5, 0xad, 0x41, 0xda, 0xbe, 0xf4, 0x16, 0x57, 0x2e, 0x53, 0x67, 0xaf, 0xdb, 0x8a, 0xd8, + 0x34, 0x17, 0x3c, 0x01, 0x55, 0x73, 0xcf, 0xe3, 0xe8, 0xc7, 0x0d, 0xe9, 0xa3, 0x13, 0x0c, 0xf6, + 0x90, 0x4e, 0xfb, 0x97, 0x6d, 0x5f, 0xa8, 0x71, 0x11, 0xfc, 0xd1, 0x95, 0x81, 0xba, 0x8c, 0x1b, + 0x39, 0xfe, 0xa2, 0x15, 0xa6, 0x52, 0x4d, 0x5b, 0x59, 0xa5, 0xe0, 0x96, 0xd9, 0x8f, 0x7b, 0xed, + 0x29, 0xd3, 0x1f, 0x0e, 0xec, 0x23, 0x0f, 0xb8, 0x6c, 0x6f, 0x7d, 0x18, 0x46, 0xd6, 0xe4, 0xb5, + 0x9a, 0x79, 0x02, 0xf5, 0x03, 0xc0, 0x60, 0x66, 0x5c, 0x2f, 0x76, 0x85, 0x9d, 0x54, 0x1a, 0x6a, + 0x28, 0xce, 0x7f, 0x7c, 0x91, 0x99, 0x4c, 0x83, 0x3e, 0xb4, 0x1d, 0x05, 0xc1, 0xc3, 0xd7, 0x47, + 0xde, 0xbc, 0x62, 0x6e, 0x86, 0x14, 0x80, 0x77, 0xeb, 0xf3, 0x07, 0x31, 0x56, 0xd2, 0xc2, 0xc6, + 0x6b, 0xdc, 0xfd, 0x22, 0x92, 0xf0, 0x06, 0x51, 0x2d, 0x38, 0xe6, 0xa0, 0x25, 0xdf, 0xd5, 0x2c, + 0x1c, 0x94, 0x12, 0x9c, 0xb0, 0x9b, 0xc4, 0x0b, 0xc8, 0xd0, 0xf7, 0x30, 0xcb, 0x27, 0xfa, 0x7a, + 0x10, 0x61, 0xaa, 0xa4, 0x70, 0xb7, 0x2a, 0x5a, 0xc9, 0xf1, 0x0a, 0x49, 0x65, 0xee, 0x69, 0x4b, + 0x3a, 0x8d, 0x32, 0x5d, 0x68, 0xb9, 0x9f, 0x75, 0x19, 0x3f, 0xac, 0x37, 0x4f, 0xe7, 0x93, 0x89, + 0x7e, 0x4a, 0x3b, 0xea, 0x74, 0x72, 0x43, 0xbd, 0x24, 0xef, 0xb6, 0xff, 0x64, 0x58, 0x84, 0x8b, + 0xa7, 0xbb, 0xb2, 0xe1, 0x26, 0x2b, 0x50, 0xca, 0x21, 0xf9, 0x98, 0xa1, 0xe2, 0x42, 0x82, 0x48, +// ^^^^ ^^^^ ^^^^ ^^^^ +}; + +const UINT8 kof99_address_8_15_xor2[256] = +{ + 0x9b, 0x9d, 0xc1, 0x3d, 0xa9, 0xb8, 0xf4, 0x6f, 0xf6, 0x25, 0xc7, 0x47, 0xd5, 0x97, 0xdf, 0x6b, + 0xeb, 0x90, 0xa4, 0xb2, 0x5d, 0xf5, 0x66, 0xb0, 0xb9, 0x8b, 0x93, 0x64, 0xec, 0x7b, 0x65, 0x8c, + 0xf1, 0x43, 0x42, 0x6e, 0x45, 0x9f, 0xb3, 0x35, 0x06, 0x71, 0x96, 0xdb, 0xa0, 0xfb, 0x0b, 0x3a, + 0x1f, 0xf8, 0x8e, 0x69, 0xcd, 0x26, 0xab, 0x86, 0xa2, 0x0c, 0xbd, 0x63, 0xa5, 0x7a, 0xe7, 0x6a, + 0x5f, 0x18, 0x9e, 0xbf, 0xad, 0x55, 0xb1, 0x1c, 0x5c, 0x03, 0x30, 0xc6, 0x37, 0x20, 0xe3, 0xc9, + 0x52, 0xe8, 0xee, 0x4f, 0x01, 0x70, 0xc4, 0x77, 0x29, 0x2a, 0xba, 0x53, 0x12, 0x04, 0x7d, 0xaf, + 0x33, 0x8f, 0xa8, 0x4d, 0xaa, 0x5b, 0xb4, 0x0f, 0x92, 0xbb, 0xed, 0xe1, 0x2f, 0x50, 0x6c, 0xd2, + 0x2c, 0x95, 0xd9, 0xf9, 0x98, 0xc3, 0x76, 0x4c, 0xf2, 0xe4, 0xe5, 0x2b, 0xef, 0x9c, 0x49, 0xb6, + 0x31, 0x3b, 0xbc, 0xa1, 0xca, 0xde, 0x62, 0x74, 0xea, 0x81, 0x00, 0xdd, 0xa6, 0x46, 0x88, 0x3f, + 0x39, 0xd6, 0x23, 0x54, 0x24, 0x4a, 0xd8, 0xdc, 0xd7, 0xd1, 0xcc, 0xbe, 0x57, 0x7c, 0xda, 0x44, + 0x61, 0xce, 0xd3, 0xd4, 0xe9, 0x28, 0x80, 0xe0, 0x56, 0x8a, 0x09, 0x05, 0x9a, 0x89, 0x1b, 0xf7, + 0xf3, 0x99, 0x6d, 0x5e, 0x48, 0x91, 0xc0, 0xd0, 0xc5, 0x79, 0x78, 0x41, 0x59, 0x21, 0x2e, 0xff, + 0xc2, 0x4b, 0x38, 0x83, 0x32, 0xe6, 0xe2, 0x7f, 0x1e, 0x17, 0x58, 0x1d, 0x1a, 0xfa, 0x85, 0x82, + 0x94, 0xc8, 0x72, 0x7e, 0xb7, 0xac, 0x0e, 0xfc, 0xfd, 0x16, 0x27, 0x75, 0x8d, 0xcb, 0x08, 0xfe, + 0x0a, 0x02, 0x0d, 0x36, 0x11, 0x22, 0x84, 0x40, 0x34, 0x3e, 0x2d, 0x68, 0x5a, 0xa7, 0x67, 0xae, + 0x87, 0x07, 0x10, 0x60, 0x14, 0x73, 0x3c, 0x51, 0x19, 0xa3, 0xb5, 0xcf, 0x13, 0xf0, 0x15, 0x4e, +}; + +const UINT8 kof99_address_16_23_xor1[256] = +{ + 0x00, 0x5f, 0x03, 0x52, 0xce, 0xe3, 0x7d, 0x8f, 0x6b, 0xf8, 0x20, 0xde, 0x7b, 0x7e, 0x39, 0xbe, + 0xf5, 0x94, 0x18, 0x78, 0x80, 0xc9, 0x7f, 0x7a, 0x3e, 0x63, 0xf2, 0xe0, 0x4e, 0xf7, 0x87, 0x27, + 0x69, 0x6c, 0xa4, 0x1d, 0x85, 0x5b, 0xe6, 0x44, 0x25, 0x0c, 0x98, 0xc7, 0x01, 0x02, 0xa3, 0x26, + 0x09, 0x38, 0xdb, 0xc3, 0x1e, 0xcf, 0x23, 0x45, 0x68, 0x76, 0xd6, 0x22, 0x5d, 0x5a, 0xae, 0x16, + 0x9f, 0xa2, 0xb5, 0xcd, 0x81, 0xea, 0x5e, 0xb8, 0xb9, 0x9d, 0x9c, 0x1a, 0x0f, 0xff, 0xe1, 0xe7, + 0x74, 0xaa, 0xd4, 0xaf, 0xfc, 0xc6, 0x33, 0x29, 0x5c, 0xab, 0x95, 0xf0, 0x19, 0x47, 0x59, 0x67, + 0xf3, 0x96, 0x60, 0x1f, 0x62, 0x92, 0xbd, 0x89, 0xee, 0x28, 0x13, 0x06, 0xfe, 0xfa, 0x32, 0x6d, + 0x57, 0x3c, 0x54, 0x50, 0x2c, 0x58, 0x49, 0xfb, 0x17, 0xcc, 0xef, 0xb2, 0xb4, 0xf9, 0x07, 0x70, + 0xc5, 0xa9, 0xdf, 0xd5, 0x3b, 0x86, 0x2b, 0x0d, 0x6e, 0x4d, 0x0a, 0x90, 0x43, 0x31, 0xc1, 0xf6, + 0x88, 0x0b, 0xda, 0x53, 0x14, 0xdc, 0x75, 0x8e, 0xb0, 0xeb, 0x99, 0x46, 0xa1, 0x15, 0x71, 0xc8, + 0xe9, 0x3f, 0x4a, 0xd9, 0x73, 0xe5, 0x7c, 0x30, 0x77, 0xd3, 0xb3, 0x4b, 0x37, 0x72, 0xc2, 0x04, + 0x97, 0x08, 0x36, 0xb1, 0x3a, 0x61, 0xec, 0xe2, 0x1c, 0x9a, 0x8b, 0xd1, 0x1b, 0x2e, 0x9e, 0x8a, + 0xd8, 0x41, 0xe4, 0xc4, 0x40, 0x2f, 0xad, 0xc0, 0xb6, 0x84, 0x51, 0x66, 0xbb, 0x12, 0xe8, 0xdd, + 0xcb, 0xbc, 0x6f, 0xd0, 0x11, 0x83, 0x56, 0x4c, 0xca, 0xbf, 0x05, 0x10, 0xd7, 0xba, 0xfd, 0xed, + 0x8c, 0x0e, 0x4f, 0x3d, 0x35, 0x91, 0xb7, 0xac, 0x34, 0x64, 0x2a, 0xf1, 0x79, 0x6a, 0x9b, 0x2d, + 0x65, 0xf4, 0x42, 0xa0, 0x8d, 0xa7, 0x48, 0x55, 0x21, 0x93, 0x24, 0xd2, 0xa6, 0xa5, 0xa8, 0x82, +}; + +const UINT8 kof99_address_16_23_xor2[256] = +{ + 0x29, 0x97, 0x1a, 0x2c, 0x0b, 0x94, 0x3e, 0x75, 0x01, 0x0d, 0x1b, 0xe1, 0x4d, 0x38, 0x39, 0x8f, + 0xe7, 0xd0, 0x60, 0x90, 0xb2, 0x0f, 0xbb, 0x70, 0x1f, 0xe6, 0x5b, 0x87, 0xb4, 0x43, 0xfd, 0xf5, + 0xf6, 0xf9, 0xad, 0xc0, 0x98, 0x17, 0x9f, 0x91, 0x15, 0x51, 0x55, 0x64, 0x6c, 0x18, 0x61, 0x0e, + 0xd9, 0x93, 0xab, 0xd6, 0x24, 0x2f, 0x6a, 0x3a, 0x22, 0xb1, 0x4f, 0xaa, 0x23, 0x48, 0xed, 0xb9, + 0x88, 0x8b, 0xa3, 0x6b, 0x26, 0x4c, 0xe8, 0x2d, 0x1c, 0x99, 0xbd, 0x5c, 0x58, 0x08, 0x50, 0xf2, + 0x2a, 0x62, 0xc1, 0x72, 0x66, 0x04, 0x10, 0x37, 0x6e, 0xfc, 0x44, 0xa9, 0xdf, 0xd4, 0x20, 0xdd, + 0xee, 0x41, 0xdb, 0x73, 0xde, 0x54, 0xec, 0xc9, 0xf3, 0x4b, 0x2e, 0xae, 0x5a, 0x4a, 0x5e, 0x47, + 0x07, 0x2b, 0x76, 0xa4, 0xe3, 0x28, 0xfe, 0xb0, 0xf0, 0x02, 0x06, 0xd1, 0xaf, 0x42, 0xc2, 0xa5, + 0xe0, 0x67, 0xbf, 0x16, 0x8e, 0x35, 0xce, 0x8a, 0xe5, 0x3d, 0x7b, 0x96, 0xd7, 0x79, 0x52, 0x1e, + 0xa1, 0xfb, 0x9b, 0xbe, 0x21, 0x9c, 0xe9, 0x56, 0x14, 0x7f, 0xa0, 0xe4, 0xc3, 0xc4, 0x46, 0xea, + 0xf7, 0xd2, 0x1d, 0x31, 0x0a, 0x5f, 0xeb, 0xa2, 0x68, 0x8d, 0xb5, 0xc5, 0x74, 0x0c, 0xdc, 0x82, + 0x80, 0x09, 0x19, 0x95, 0x71, 0x9a, 0x11, 0x57, 0x77, 0x4e, 0xc6, 0xff, 0x12, 0x03, 0xa7, 0xc7, + 0xf4, 0xc8, 0xb6, 0x7a, 0x59, 0x36, 0x3c, 0x53, 0xe2, 0x69, 0x8c, 0x25, 0x05, 0x45, 0x63, 0xf8, + 0x34, 0x89, 0x33, 0x3f, 0x85, 0x27, 0xbc, 0x65, 0xfa, 0xa8, 0x6d, 0x84, 0x5d, 0xba, 0x40, 0x32, + 0x30, 0xef, 0x83, 0x13, 0xa6, 0x78, 0xcc, 0x81, 0x9e, 0xda, 0xca, 0xd3, 0x7e, 0x9d, 0x6f, 0xcd, + 0xb7, 0xb3, 0xd8, 0xcf, 0x3b, 0x00, 0x92, 0xb8, 0x86, 0xac, 0x49, 0x7c, 0xf1, 0xd5, 0xcb, 0x7d, +}; + +const UINT8 kof99_address_0_7_xor[256] = +{ + 0x74, 0xad, 0x5d, 0x1d, 0x9e, 0xc3, 0xfa, 0x4e, 0xf7, 0xdb, 0xca, 0xa2, 0x64, 0x36, 0x56, 0x0c, + 0x4f, 0xcf, 0x43, 0x66, 0x1e, 0x91, 0xe3, 0xa5, 0x58, 0xc2, 0xc1, 0xd4, 0xb9, 0xdd, 0x76, 0x16, + 0xce, 0x61, 0x75, 0x01, 0x2b, 0x22, 0x38, 0x55, 0x50, 0xef, 0x6c, 0x99, 0x05, 0xe9, 0xe8, 0xe0, + 0x2d, 0xa4, 0x4b, 0x4a, 0x42, 0xae, 0xba, 0x8c, 0x6f, 0x93, 0x14, 0xbd, 0x71, 0x21, 0xb0, 0x02, + 0x15, 0xc4, 0xe6, 0x60, 0xd7, 0x44, 0xfd, 0x85, 0x7e, 0x78, 0x8f, 0x00, 0x81, 0xf1, 0xa7, 0x3b, + 0xa0, 0x10, 0xf4, 0x9f, 0x39, 0x88, 0x35, 0x62, 0xcb, 0x19, 0x31, 0x11, 0x51, 0xfb, 0x2a, 0x20, + 0x45, 0xd3, 0x7d, 0x92, 0x1b, 0xf2, 0x09, 0x0d, 0x97, 0xa9, 0xb5, 0x3c, 0xee, 0x5c, 0xaf, 0x7b, + 0xd2, 0x3a, 0x49, 0x8e, 0xb6, 0xcd, 0xd9, 0xde, 0x8a, 0x29, 0x6e, 0xd8, 0x0b, 0xe1, 0x69, 0x87, + 0x1a, 0x96, 0x18, 0xcc, 0xdf, 0xe7, 0xc5, 0xc7, 0xf8, 0x52, 0xc9, 0xf0, 0xb7, 0xe5, 0x33, 0xda, + 0x67, 0x9d, 0xa3, 0x03, 0x0e, 0x72, 0x26, 0x79, 0xe2, 0xb8, 0xfc, 0xaa, 0xfe, 0xb4, 0x86, 0xc8, + 0xd1, 0xbc, 0x12, 0x08, 0x77, 0xeb, 0x40, 0x8d, 0x04, 0x25, 0x4d, 0x5a, 0x6a, 0x7a, 0x2e, 0x41, + 0x65, 0x1c, 0x13, 0x94, 0xb2, 0x63, 0x28, 0x59, 0x5e, 0x9a, 0x30, 0x07, 0xc6, 0xbf, 0x17, 0xf5, + 0x0f, 0x89, 0xf3, 0x1f, 0xea, 0x6d, 0xb3, 0xc0, 0x70, 0x47, 0xf9, 0x53, 0xf6, 0xd6, 0x54, 0xed, + 0x6b, 0x4c, 0xe4, 0x8b, 0x83, 0x24, 0x90, 0xb1, 0x7c, 0xbb, 0x73, 0xab, 0xd5, 0x2f, 0x5f, 0xec, + 0x9c, 0x2c, 0xa8, 0x34, 0x46, 0x37, 0x27, 0xa1, 0x0a, 0x06, 0x80, 0x68, 0x82, 0x32, 0x84, 0xff, + 0x48, 0xac, 0x7f, 0x3f, 0x95, 0xdc, 0x98, 0x9b, 0xbe, 0x23, 0x57, 0x3e, 0x5b, 0xd0, 0x3d, 0xa6, +}; + + + + + + +const UINT8 kof2000_type0_t03[256] = +{ + 0x10, 0x61, 0xf1, 0x78, 0x85, 0x52, 0x68, 0xe3, 0x12, 0x0d, 0xfa, 0xf0, 0xc9, 0x36, 0x5e, 0x3d, + 0xf9, 0xa6, 0x01, 0x2e, 0xc7, 0x84, 0xea, 0x2b, 0x6d, 0x14, 0x38, 0x4f, 0x55, 0x1c, 0x9d, 0xa7, + 0x7a, 0xc6, 0xf8, 0x9a, 0xe6, 0x42, 0xb5, 0xed, 0x7d, 0x3a, 0xb1, 0x05, 0x43, 0x4a, 0x22, 0xfd, + 0xac, 0xa4, 0x31, 0xc3, 0x32, 0x76, 0x95, 0x9e, 0x7e, 0x88, 0x8e, 0xa2, 0x97, 0x18, 0xbe, 0x2a, + 0xf5, 0xd6, 0xca, 0xcc, 0x72, 0x3b, 0x87, 0x6c, 0xde, 0x75, 0xd7, 0x21, 0xcb, 0x0b, 0xdd, 0xe7, + 0xe1, 0x65, 0xaa, 0xb9, 0x44, 0xfb, 0x66, 0x15, 0x1a, 0x3c, 0x98, 0xcf, 0x8a, 0xdf, 0x37, 0xa5, + 0x2f, 0x67, 0xd2, 0x83, 0xb6, 0x6b, 0xfc, 0xe0, 0xb4, 0x7c, 0x08, 0xdc, 0x93, 0x30, 0xab, 0xe4, + 0x19, 0xc2, 0x8b, 0xeb, 0xa0, 0x0a, 0xc8, 0x03, 0xc0, 0x4b, 0x64, 0x71, 0x86, 0x9c, 0x9b, 0x16, + 0x79, 0xff, 0x70, 0x09, 0x8c, 0xd0, 0xf6, 0x53, 0x07, 0x73, 0xd4, 0x89, 0xb3, 0x00, 0xe9, 0xfe, + 0xec, 0x8f, 0xbc, 0xb2, 0x1e, 0x5d, 0x11, 0x35, 0xa9, 0x06, 0x59, 0x9f, 0xc1, 0xd3, 0x7b, 0xf2, + 0xc5, 0x77, 0x4e, 0x39, 0x20, 0xd5, 0x6a, 0x82, 0xda, 0x45, 0xf3, 0x33, 0x81, 0x23, 0xba, 0xe2, + 0x1d, 0x5f, 0x5c, 0x51, 0x49, 0xae, 0x8d, 0xc4, 0xa8, 0xf7, 0x1f, 0x0f, 0x34, 0x28, 0xa1, 0xd9, + 0x27, 0xd8, 0x4c, 0x2c, 0xbf, 0x91, 0x3e, 0x69, 0x57, 0x41, 0x25, 0x0c, 0x5a, 0x90, 0x92, 0xb0, + 0x63, 0x6f, 0x40, 0xaf, 0x74, 0xb8, 0x2d, 0x80, 0xbb, 0x46, 0x94, 0xe5, 0x29, 0xee, 0xb7, 0x1b, + 0x96, 0xad, 0x13, 0x0e, 0x58, 0x99, 0x60, 0x4d, 0x17, 0x26, 0xce, 0xe8, 0xdb, 0xef, 0x24, 0xa3, + 0x6e, 0x7f, 0x54, 0x3f, 0x02, 0xd1, 0x5b, 0x50, 0x56, 0x48, 0xf4, 0xbd, 0x62, 0x47, 0x04, 0xcd, +}; + +const UINT8 kof2000_type0_t12[256] = +{ + 0xf4, 0x28, 0xb4, 0x8f, 0xfa, 0xeb, 0x8e, 0x54, 0x2b, 0x49, 0xd1, 0x76, 0x71, 0x47, 0x8b, 0x57, + 0x92, 0x85, 0x7c, 0xb8, 0x5c, 0x22, 0xf9, 0x26, 0xbc, 0x5b, 0x6d, 0x67, 0xae, 0x5f, 0x6f, 0xf5, + 0x9f, 0x48, 0x66, 0x40, 0x0d, 0x11, 0x4e, 0xb2, 0x6b, 0x35, 0x15, 0x0f, 0x18, 0x25, 0x1d, 0xba, + 0xd3, 0x69, 0x79, 0xec, 0xa8, 0x8c, 0xc9, 0x7f, 0x4b, 0xdb, 0x51, 0xaf, 0xca, 0xe2, 0xb3, 0x81, + 0x12, 0x5e, 0x7e, 0x38, 0xc8, 0x95, 0x01, 0xff, 0xfd, 0xfb, 0xf2, 0x74, 0x62, 0x14, 0xa5, 0x98, + 0xa6, 0xda, 0x80, 0x53, 0xe8, 0x56, 0xac, 0x1b, 0x52, 0xd0, 0xf1, 0x45, 0x42, 0xb6, 0x1a, 0x4a, + 0x3a, 0x99, 0xfc, 0xd2, 0x9c, 0xcf, 0x31, 0x2d, 0xdd, 0x86, 0x2f, 0x29, 0xe1, 0x03, 0x19, 0xa2, + 0x41, 0x33, 0x83, 0x90, 0xc1, 0xbf, 0x0b, 0x08, 0x3d, 0xd8, 0x8d, 0x6c, 0x39, 0xa0, 0xe3, 0x55, + 0x02, 0x50, 0x46, 0xe6, 0xc3, 0x82, 0x36, 0x13, 0x75, 0xab, 0x27, 0xd7, 0x1f, 0x0a, 0xd4, 0x89, + 0x59, 0x4f, 0xc0, 0x5d, 0xc6, 0xf7, 0x88, 0xbd, 0x3c, 0x00, 0xef, 0xcd, 0x05, 0x1c, 0xaa, 0x9b, + 0xed, 0x7a, 0x61, 0x17, 0x93, 0xfe, 0x23, 0xb9, 0xf3, 0x68, 0x78, 0xf6, 0x5a, 0x7b, 0xe0, 0xe4, + 0xa3, 0xee, 0x16, 0x72, 0xc7, 0x3b, 0x8a, 0x37, 0x2a, 0x70, 0xa9, 0x2c, 0x21, 0xf8, 0x24, 0x09, + 0xce, 0x20, 0x9e, 0x06, 0x87, 0xc5, 0x04, 0x64, 0x43, 0x7d, 0x4d, 0x10, 0xd6, 0xa4, 0x94, 0x4c, + 0x60, 0xde, 0xdf, 0x58, 0xb1, 0x44, 0x3f, 0xb0, 0xd9, 0xe5, 0xcb, 0xbb, 0xbe, 0xea, 0x07, 0x34, + 0x73, 0x6a, 0x77, 0xf0, 0x9d, 0x0c, 0x2e, 0x0e, 0x91, 0x9a, 0xcc, 0xc2, 0xb7, 0x63, 0x97, 0xd5, + 0xdc, 0xc4, 0x32, 0xe7, 0x84, 0x3e, 0x30, 0xa1, 0x1e, 0xb5, 0x6e, 0x65, 0xe9, 0xad, 0xa7, 0x96, +}; + +const UINT8 kof2000_type1_t03[256] = +{ + 0x9a, 0x2f, 0xcc, 0x4e, 0x40, 0x69, 0xac, 0xca, 0xa5, 0x7b, 0x0a, 0x61, 0x91, 0x0d, 0x55, 0x74, + 0xcd, 0x8b, 0x0b, 0x80, 0x09, 0x5e, 0x38, 0xc7, 0xda, 0xbf, 0xf5, 0x37, 0x23, 0x31, 0x33, 0xe9, + 0xae, 0x87, 0xe5, 0xfa, 0x6e, 0x5c, 0xad, 0xf4, 0x76, 0x62, 0x9f, 0x2e, 0x01, 0xe2, 0xf6, 0x47, + 0x8c, 0x7c, 0xaa, 0x98, 0xb5, 0x92, 0x51, 0xec, 0x5f, 0x07, 0x5d, 0x6f, 0x16, 0xa1, 0x1d, 0xa9, + 0x48, 0x45, 0xf0, 0x6a, 0x9c, 0x1e, 0x11, 0xa0, 0x06, 0x46, 0xd5, 0xf1, 0x73, 0xed, 0x94, 0xf7, + 0xc3, 0x57, 0x1b, 0xe0, 0x97, 0xb1, 0xa4, 0xa7, 0x24, 0xe7, 0x2b, 0x05, 0x5b, 0x34, 0x0c, 0xb8, + 0x0f, 0x9b, 0xc8, 0x4d, 0x5a, 0xa6, 0x86, 0x3e, 0x14, 0x29, 0x84, 0x58, 0x90, 0xdb, 0x2d, 0x54, + 0x9d, 0x82, 0xd4, 0x7d, 0xc6, 0x67, 0x41, 0x89, 0xc1, 0x13, 0xb0, 0x9e, 0x81, 0x6d, 0xa8, 0x59, + 0xbd, 0x39, 0x8e, 0xe6, 0x25, 0x8f, 0xd9, 0xa2, 0xe4, 0x53, 0xc5, 0x72, 0x7e, 0x36, 0x4a, 0x4f, + 0x52, 0xc2, 0x22, 0x2a, 0xce, 0x3c, 0x21, 0x2c, 0x00, 0xd7, 0x75, 0x8a, 0x27, 0xee, 0x43, 0xfe, + 0xcb, 0x6b, 0xb9, 0xa3, 0x78, 0xb7, 0x85, 0x02, 0x20, 0xd0, 0x83, 0xc4, 0x12, 0xf9, 0xfd, 0xd8, + 0x79, 0x64, 0x3a, 0x49, 0x03, 0xb4, 0xc0, 0xf2, 0xdf, 0x15, 0x93, 0x08, 0x35, 0xff, 0x70, 0xdd, + 0x28, 0x6c, 0x0e, 0x04, 0xde, 0x7a, 0x65, 0xd2, 0xab, 0x42, 0x95, 0xe1, 0x3f, 0x3b, 0x7f, 0x66, + 0xd1, 0x8d, 0xe3, 0xbb, 0x1c, 0xfc, 0x77, 0x1a, 0x88, 0x18, 0x19, 0x68, 0x1f, 0x56, 0xd6, 0xe8, + 0xb6, 0xbc, 0xd3, 0xea, 0x3d, 0x26, 0xb3, 0xc9, 0x44, 0xdc, 0xf3, 0x32, 0x30, 0xef, 0x96, 0x4c, + 0xaf, 0x17, 0xf8, 0xfb, 0x60, 0x50, 0xeb, 0x4b, 0x99, 0x63, 0xba, 0xb2, 0x71, 0xcf, 0x10, 0xbe, +}; + +const UINT8 kof2000_type1_t12[256] = +{ + 0xda, 0xa7, 0xd6, 0x6e, 0x2f, 0x5e, 0xf0, 0x3f, 0xa4, 0xce, 0xd3, 0xfd, 0x46, 0x2a, 0xac, 0xc9, + 0xbe, 0xeb, 0x9f, 0xd5, 0x3c, 0x61, 0x96, 0x11, 0xd0, 0x38, 0xca, 0x06, 0xed, 0x1b, 0x65, 0xe7, + 0x23, 0xdd, 0xd9, 0x05, 0xbf, 0x5b, 0x5d, 0xa5, 0x95, 0x00, 0xec, 0xf1, 0x01, 0xa9, 0xa6, 0xfc, + 0xbb, 0x54, 0xe3, 0x2e, 0x92, 0x58, 0x0a, 0x7b, 0xb6, 0xcc, 0xb1, 0x5f, 0x14, 0x35, 0x72, 0xff, + 0xe6, 0x52, 0xd7, 0x8c, 0xf3, 0x43, 0xaf, 0x9c, 0xc0, 0x4f, 0x0c, 0x42, 0x8e, 0xef, 0x80, 0xcd, + 0x1d, 0x7e, 0x88, 0x3b, 0x98, 0xa1, 0xad, 0xe4, 0x9d, 0x8d, 0x2b, 0x56, 0xb5, 0x50, 0xdf, 0x66, + 0x6d, 0xd4, 0x60, 0x09, 0xe1, 0xee, 0x4a, 0x47, 0xf9, 0xfe, 0x73, 0x07, 0x89, 0xa8, 0x39, 0xea, + 0x82, 0x9e, 0xcf, 0x26, 0xb2, 0x4e, 0xc3, 0x59, 0xf2, 0x3d, 0x9a, 0xb0, 0x69, 0xf7, 0xbc, 0x34, + 0xe5, 0x36, 0x22, 0xfb, 0x57, 0x71, 0x99, 0x6c, 0x83, 0x30, 0x55, 0xc2, 0xbd, 0xf4, 0x77, 0xe9, + 0x76, 0x97, 0xa0, 0xe0, 0xb9, 0x86, 0x6b, 0xa3, 0x84, 0x67, 0x1a, 0x70, 0x02, 0x5a, 0x41, 0x5c, + 0x25, 0x81, 0xaa, 0x28, 0x78, 0x4b, 0xc6, 0x64, 0x53, 0x16, 0x4d, 0x8b, 0x20, 0x93, 0xae, 0x0f, + 0x94, 0x2c, 0x3a, 0xc7, 0x62, 0xe8, 0xc4, 0xdb, 0x04, 0xc5, 0xfa, 0x29, 0x48, 0xd1, 0x08, 0x24, + 0x0d, 0xe2, 0xd8, 0x10, 0xb4, 0x91, 0x8a, 0x13, 0x0e, 0xdc, 0xd2, 0x79, 0xb8, 0xf8, 0xba, 0x2d, + 0xcb, 0xf5, 0x7d, 0x37, 0x51, 0x40, 0x31, 0xa2, 0x0b, 0x18, 0x63, 0x7f, 0xb3, 0xab, 0x9b, 0x87, + 0xf6, 0x90, 0xde, 0xc8, 0x27, 0x45, 0x7c, 0x1c, 0x85, 0x68, 0x33, 0x19, 0x03, 0x75, 0x15, 0x7a, + 0x1f, 0x49, 0x8f, 0x4c, 0xc1, 0x44, 0x17, 0x12, 0x6f, 0x32, 0xb7, 0x3e, 0x74, 0x1e, 0x21, 0x6a, +}; + + + +const UINT8 kof2000_address_8_15_xor1[256] = +{ + 0xfc, 0x9b, 0x1c, 0x35, 0x72, 0x53, 0xd6, 0x7d, 0x84, 0xa4, 0xc5, 0x93, 0x7b, 0xe7, 0x47, 0xd5, + 0x24, 0xa2, 0xfa, 0x19, 0x0c, 0xb1, 0x8c, 0xb9, 0x9d, 0xd8, 0x59, 0x4f, 0x3c, 0xb2, 0x78, 0x4a, + 0x2a, 0x96, 0x9a, 0xf1, 0x1f, 0x22, 0xa8, 0x5b, 0x67, 0xa3, 0x0f, 0x00, 0xfb, 0xdf, 0xeb, 0x0a, + 0x57, 0xb8, 0x25, 0xd7, 0xf0, 0x6b, 0x0b, 0x31, 0x95, 0x23, 0x2d, 0x5c, 0x27, 0xc7, 0xf4, 0x55, + 0x1a, 0xf7, 0x74, 0xbe, 0xd3, 0xac, 0x3d, 0xc1, 0x7f, 0xbd, 0x28, 0x01, 0x10, 0xe5, 0x09, 0x37, + 0x1e, 0x58, 0xaf, 0x17, 0xf2, 0x16, 0x30, 0x92, 0x36, 0x68, 0xe6, 0xd4, 0xea, 0xb7, 0x75, 0x54, + 0x77, 0x41, 0xb4, 0x8d, 0xe0, 0xf3, 0x51, 0x03, 0xa9, 0xe8, 0x66, 0xab, 0x29, 0xa5, 0xed, 0xcb, + 0xd1, 0xaa, 0xf5, 0xdb, 0x4c, 0x42, 0x97, 0x8a, 0xae, 0xc9, 0x6e, 0x04, 0x33, 0x85, 0xdd, 0x2b, + 0x6f, 0xef, 0x12, 0x21, 0x7a, 0xa1, 0x5a, 0x91, 0xc8, 0xcc, 0xc0, 0xa7, 0x60, 0x3e, 0x56, 0x2f, + 0xe4, 0x71, 0x99, 0xc2, 0xa0, 0x45, 0x80, 0x65, 0xbb, 0x87, 0x69, 0x81, 0x73, 0xca, 0xf6, 0x46, + 0x43, 0xda, 0x26, 0x7e, 0x8f, 0xe1, 0x8b, 0xfd, 0x50, 0x79, 0xba, 0xc6, 0x63, 0x4b, 0xb3, 0x8e, + 0x34, 0xe2, 0x48, 0x14, 0xcd, 0xe3, 0xc4, 0x05, 0x13, 0x40, 0x06, 0x6c, 0x88, 0xb0, 0xe9, 0x1b, + 0x4d, 0xf8, 0x76, 0x02, 0x44, 0x94, 0xcf, 0x32, 0xfe, 0xce, 0x3b, 0x5d, 0x2c, 0x89, 0x5f, 0xdc, + 0xd2, 0x9c, 0x6a, 0xec, 0x18, 0x6d, 0x0e, 0x86, 0xff, 0x5e, 0x9e, 0xee, 0x11, 0xd0, 0x49, 0x52, + 0x4e, 0x61, 0x90, 0x0d, 0xc3, 0x39, 0x15, 0x83, 0xb5, 0x62, 0x3f, 0x70, 0x7c, 0xad, 0x20, 0xbf, + 0x2e, 0x08, 0x1d, 0xf9, 0xb6, 0xa6, 0x64, 0x07, 0x82, 0x38, 0x98, 0x3a, 0x9f, 0xde, 0xbc, 0xd9, +}; + +const UINT8 kof2000_address_8_15_xor2[256] = +{ + 0x00, 0xbe, 0x06, 0x5a, 0xfa, 0x42, 0x15, 0xf2, 0x3f, 0x0a, 0x84, 0x93, 0x4e, 0x78, 0x3b, 0x89, + 0x32, 0x98, 0xa2, 0x87, 0x73, 0xdd, 0x26, 0xe5, 0x05, 0x71, 0x08, 0x6e, 0x9b, 0xe0, 0xdf, 0x9e, + 0xfc, 0x83, 0x81, 0xef, 0xb2, 0xc0, 0xc3, 0xbf, 0xa7, 0x6d, 0x1b, 0x95, 0xed, 0xb9, 0x3e, 0x13, + 0xb0, 0x47, 0x9c, 0x7a, 0x24, 0x41, 0x68, 0xd0, 0x36, 0x0b, 0xb5, 0xc2, 0x67, 0xf7, 0x54, 0x92, + 0x1e, 0x44, 0x86, 0x2b, 0x94, 0xcc, 0xba, 0x23, 0x0d, 0xca, 0x6b, 0x4c, 0x2a, 0x9a, 0x2d, 0x8b, + 0xe3, 0x52, 0x29, 0xf0, 0x21, 0xbd, 0xbb, 0x1f, 0xa3, 0xab, 0xf8, 0x46, 0xb7, 0x45, 0x82, 0x5e, + 0xdb, 0x07, 0x5d, 0xe9, 0x9d, 0x1a, 0x48, 0xce, 0x91, 0x12, 0xd4, 0xee, 0xa9, 0x39, 0xf1, 0x18, + 0x2c, 0x22, 0x8a, 0x7e, 0x34, 0x4a, 0x8c, 0xc1, 0x14, 0xf3, 0x20, 0x35, 0xd9, 0x96, 0x33, 0x77, + 0x9f, 0x76, 0x7c, 0x90, 0xc6, 0xd5, 0xa1, 0x5b, 0xac, 0x75, 0xc7, 0x0c, 0xb3, 0x17, 0xd6, 0x99, + 0x56, 0xa6, 0x3d, 0x1d, 0xb1, 0x2e, 0xd8, 0xbc, 0x2f, 0xde, 0x60, 0x55, 0x6c, 0x40, 0xcd, 0x43, + 0xff, 0xad, 0x38, 0x79, 0x51, 0xc8, 0x0e, 0x5f, 0xc4, 0x66, 0xcb, 0xa8, 0x7d, 0xa4, 0x3a, 0xea, + 0x27, 0x7b, 0x70, 0x8e, 0x5c, 0x19, 0x0f, 0x80, 0x6f, 0x8f, 0x10, 0xf9, 0x49, 0x85, 0x69, 0x7f, + 0xeb, 0x1c, 0x01, 0x65, 0x37, 0xa5, 0x28, 0xe4, 0x6a, 0x03, 0x04, 0xd1, 0x31, 0x11, 0x30, 0xfb, + 0x88, 0x97, 0xd3, 0xf6, 0xc5, 0x4d, 0xf5, 0x3c, 0xe8, 0x61, 0xdc, 0xd2, 0xb4, 0xb8, 0xa0, 0xae, + 0x16, 0x25, 0x02, 0x09, 0xfe, 0xcf, 0x53, 0x63, 0xaf, 0x59, 0xf4, 0xe1, 0xec, 0xd7, 0xe7, 0x50, + 0xe2, 0xc9, 0xaa, 0x4b, 0x8d, 0x4f, 0xe6, 0x64, 0xda, 0x74, 0xb6, 0x72, 0x57, 0x62, 0xfd, 0x58, +}; + +const UINT8 kof2000_address_16_23_xor1[256] = +{ + 0x45, 0x9f, 0x6e, 0x2f, 0x28, 0xbc, 0x5e, 0x6d, 0xda, 0xb5, 0x0d, 0xb8, 0xc0, 0x8e, 0xa2, 0x32, + 0xee, 0xcd, 0x8d, 0x48, 0x8c, 0x27, 0x14, 0xeb, 0x65, 0xd7, 0xf2, 0x93, 0x99, 0x90, 0x91, 0xfc, + 0x5f, 0xcb, 0xfa, 0x75, 0x3f, 0x26, 0xde, 0x72, 0x33, 0x39, 0xc7, 0x1f, 0x88, 0x79, 0x73, 0xab, + 0x4e, 0x36, 0x5d, 0x44, 0xd2, 0x41, 0xa0, 0x7e, 0xa7, 0x8b, 0xa6, 0xbf, 0x03, 0xd8, 0x86, 0xdc, + 0x2c, 0xaa, 0x70, 0x3d, 0x46, 0x07, 0x80, 0x58, 0x0b, 0x2b, 0xe2, 0xf0, 0xb1, 0xfe, 0x42, 0xf3, + 0xe9, 0xa3, 0x85, 0x78, 0xc3, 0xd0, 0x5a, 0xdb, 0x1a, 0xfb, 0x9d, 0x8a, 0xa5, 0x12, 0x0e, 0x54, + 0x8f, 0xc5, 0x6c, 0xae, 0x25, 0x5b, 0x4b, 0x17, 0x02, 0x9c, 0x4a, 0x24, 0x40, 0xe5, 0x9e, 0x22, + 0xc6, 0x49, 0x62, 0xb6, 0x6b, 0xbb, 0xa8, 0xcc, 0xe8, 0x81, 0x50, 0x47, 0xc8, 0xbe, 0x5c, 0xa4, + 0xd6, 0x94, 0x4f, 0x7b, 0x9a, 0xcf, 0xe4, 0x59, 0x7a, 0xa1, 0xea, 0x31, 0x37, 0x13, 0x2d, 0xaf, + 0x21, 0x69, 0x19, 0x1d, 0x6f, 0x16, 0x98, 0x1e, 0x08, 0xe3, 0xb2, 0x4d, 0x9b, 0x7f, 0xa9, 0x77, + 0xed, 0xbd, 0xd4, 0xd9, 0x34, 0xd3, 0xca, 0x09, 0x18, 0x60, 0xc9, 0x6a, 0x01, 0xf4, 0xf6, 0x64, + 0xb4, 0x3a, 0x15, 0xac, 0x89, 0x52, 0x68, 0x71, 0xe7, 0x82, 0xc1, 0x0c, 0x92, 0xf7, 0x30, 0xe6, + 0x1c, 0x3e, 0x0f, 0x0a, 0x67, 0x35, 0xba, 0x61, 0xdd, 0x29, 0xc2, 0xf8, 0x97, 0x95, 0xb7, 0x3b, + 0xe0, 0xce, 0xf9, 0xd5, 0x06, 0x76, 0xb3, 0x05, 0x4c, 0x04, 0x84, 0x3c, 0x87, 0x23, 0x63, 0x7c, + 0x53, 0x56, 0xe1, 0x7d, 0x96, 0x1b, 0xd1, 0xec, 0x2a, 0x66, 0xf1, 0x11, 0x10, 0xff, 0x43, 0x2e, + 0xdf, 0x83, 0x74, 0xf5, 0x38, 0x20, 0xfd, 0xad, 0xc4, 0xb9, 0x55, 0x51, 0xb0, 0xef, 0x00, 0x57, +}; + +const UINT8 kof2000_address_16_23_xor2[256] = +{ + 0x00, 0xb8, 0xf0, 0x34, 0xca, 0x21, 0x3c, 0xf9, 0x01, 0x8e, 0x75, 0x70, 0xec, 0x13, 0x27, 0x96, + 0xf4, 0x5b, 0x88, 0x1f, 0xeb, 0x4a, 0x7d, 0x9d, 0xbe, 0x02, 0x14, 0xaf, 0xa2, 0x06, 0xc6, 0xdb, + 0x35, 0x6b, 0x74, 0x45, 0x7b, 0x29, 0xd2, 0xfe, 0xb6, 0x15, 0xd0, 0x8a, 0xa9, 0x2d, 0x19, 0xf6, + 0x5e, 0x5a, 0x90, 0xe9, 0x11, 0x33, 0xc2, 0x47, 0x37, 0x4c, 0x4f, 0x59, 0xc3, 0x04, 0x57, 0x1d, + 0xf2, 0x63, 0x6d, 0x6e, 0x31, 0x95, 0xcb, 0x3e, 0x67, 0xb2, 0xe3, 0x98, 0xed, 0x8d, 0xe6, 0xfb, + 0xf8, 0xba, 0x5d, 0xd4, 0x2a, 0xf5, 0x3b, 0x82, 0x05, 0x16, 0x44, 0xef, 0x4d, 0xe7, 0x93, 0xda, + 0x9f, 0xbb, 0x61, 0xc9, 0x53, 0xbd, 0x76, 0x78, 0x52, 0x36, 0x0c, 0x66, 0xc1, 0x10, 0xdd, 0x7a, + 0x84, 0x69, 0xcd, 0xfd, 0x58, 0x0d, 0x6c, 0x89, 0x68, 0xad, 0x3a, 0xb0, 0x4b, 0x46, 0xc5, 0x03, + 0xb4, 0xf7, 0x30, 0x8c, 0x4e, 0x60, 0x73, 0xa1, 0x8b, 0xb1, 0x62, 0xcc, 0xd1, 0x08, 0xfc, 0x77, + 0x7e, 0xcf, 0x56, 0x51, 0x07, 0xa6, 0x80, 0x92, 0xdc, 0x0b, 0xa4, 0xc7, 0xe8, 0xe1, 0xb5, 0x71, + 0xea, 0xb3, 0x2f, 0x94, 0x18, 0xe2, 0x3d, 0x49, 0x65, 0xaa, 0xf1, 0x91, 0xc8, 0x99, 0x55, 0x79, + 0x86, 0xa7, 0x26, 0xa0, 0xac, 0x5f, 0xce, 0x6a, 0x5c, 0xf3, 0x87, 0x8f, 0x12, 0x1c, 0xd8, 0xe4, + 0x9b, 0x64, 0x2e, 0x1e, 0xd7, 0xc0, 0x17, 0xbc, 0xa3, 0xa8, 0x9a, 0x0e, 0x25, 0x40, 0x41, 0x50, + 0xb9, 0xbf, 0x28, 0xdf, 0x32, 0x54, 0x9e, 0x48, 0xd5, 0x2b, 0x42, 0xfa, 0x9c, 0x7f, 0xd3, 0x85, + 0x43, 0xde, 0x81, 0x0f, 0x24, 0xc4, 0x38, 0xae, 0x83, 0x1b, 0x6f, 0x7c, 0xe5, 0xff, 0x1a, 0xd9, + 0x3f, 0xb7, 0x22, 0x97, 0x09, 0xe0, 0xa5, 0x20, 0x23, 0x2c, 0x72, 0xd6, 0x39, 0xab, 0x0a, 0xee, +}; + +const UINT8 kof2000_address_0_7_xor[256] = +{ + 0x26, 0x48, 0x06, 0x9b, 0x21, 0xa9, 0x1b, 0x76, 0xc9, 0xf8, 0xb4, 0x67, 0xe4, 0xff, 0x99, 0xf7, + 0x15, 0x9e, 0x62, 0x00, 0x72, 0x4d, 0xa0, 0x4f, 0x02, 0xf1, 0xea, 0xef, 0x0b, 0xf3, 0xeb, 0xa6, + 0x93, 0x78, 0x6f, 0x7c, 0xda, 0xd4, 0x7b, 0x05, 0xe9, 0xc6, 0xd6, 0xdb, 0x50, 0xce, 0xd2, 0x01, + 0xb5, 0xe8, 0xe0, 0x2a, 0x08, 0x1a, 0xb8, 0xe3, 0xf9, 0xb1, 0xf4, 0x8b, 0x39, 0x2d, 0x85, 0x9c, + 0x55, 0x73, 0x63, 0x40, 0x38, 0x96, 0xdc, 0xa3, 0xa2, 0xa1, 0x25, 0x66, 0x6d, 0x56, 0x8e, 0x10, + 0x0f, 0x31, 0x1c, 0xf5, 0x28, 0x77, 0x0a, 0xd1, 0x75, 0x34, 0xa4, 0xfe, 0x7d, 0x07, 0x51, 0x79, + 0x41, 0x90, 0x22, 0x35, 0x12, 0xbb, 0xc4, 0xca, 0xb2, 0x1f, 0xcb, 0xc8, 0xac, 0xdd, 0xd0, 0x0d, + 0xfc, 0xc5, 0x9d, 0x14, 0xbc, 0x83, 0xd9, 0x58, 0xc2, 0x30, 0x9a, 0x6a, 0xc0, 0x0c, 0xad, 0xf6, + 0x5d, 0x74, 0x7f, 0x2f, 0xbd, 0x1d, 0x47, 0xd5, 0xe6, 0x89, 0xcf, 0xb7, 0xd3, 0x59, 0x36, 0x98, + 0xf0, 0xfb, 0x3c, 0xf2, 0x3f, 0xa7, 0x18, 0x82, 0x42, 0x5c, 0xab, 0xba, 0xde, 0x52, 0x09, 0x91, + 0xaa, 0x61, 0xec, 0xd7, 0x95, 0x23, 0xcd, 0x80, 0xa5, 0x68, 0x60, 0x27, 0x71, 0xe1, 0x2c, 0x2e, + 0x8d, 0x2b, 0x57, 0x65, 0xbf, 0xc1, 0x19, 0xc7, 0x49, 0x64, 0x88, 0x4a, 0xcc, 0x20, 0x4e, 0xd8, + 0x3b, 0x4c, 0x13, 0x5f, 0x9f, 0xbe, 0x5e, 0x6e, 0xfd, 0xe2, 0xfa, 0x54, 0x37, 0x0e, 0x16, 0x7a, + 0x6c, 0x33, 0xb3, 0x70, 0x84, 0x7e, 0xc3, 0x04, 0xb0, 0xae, 0xb9, 0x81, 0x03, 0x29, 0xdf, 0x46, + 0xe5, 0x69, 0xe7, 0x24, 0x92, 0x5a, 0x4b, 0x5b, 0x94, 0x11, 0x3a, 0x3d, 0x87, 0xed, 0x97, 0xb6, + 0x32, 0x3e, 0x45, 0xaf, 0x1e, 0x43, 0x44, 0x8c, 0x53, 0x86, 0x6b, 0xee, 0xa8, 0x8a, 0x8f, 0x17, +}; + + + + + +void NeoCMCExtractSData(UINT8* rom, UINT8* sdata, INT32 rom_size, INT32 sdata_size) +{ +#if 0 + /* the S data comes from the end fo the C data */ + rom += rom_size - sdata_size; + + for (INT32 i = 0; i < sdata_size; i++) { + sdata[i] = rom[(i & ~0x1F) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4)]; + } +#endif + INT32 i; + // the S data comes from the end fo the C data + if (sdata_size == 0x100000) { + // 1 MB of data, special for kf2k3pcb + rom += rom_size - sdata_size /2; + for (i = 0; i < sdata_size / 2; i++) { + sdata[i + 0] = rom[(i & ~0x1F) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4) - 0x1000000 ]; + sdata[i + sdata_size / 2] = rom[(i & ~0x1F) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4)]; + } + } else { + // Normal data extraction + rom += rom_size - sdata_size; + for (i = 0; i < sdata_size; i++) { + sdata[i] = rom[(i & ~0x1F) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4)]; + } + } +} + +inline static void cmc_xor(UINT8 *r0, UINT8 *r1, + const UINT8 *table0hi, + const UINT8 *table0lo, + const UINT8 *table1, + INT32 base, + INT32 invert) + +{ + UINT8 c0, c1, tmp, xor0, xor1; + + tmp = table1[(base & 0xff) ^ address_0_7_xor[(base >> 8) & 0xff]]; + xor0 = (table0hi[(base >> 8) & 0xff] & 0xfe) | (tmp & 0x01); + xor1 = (tmp & 0xfe) | (table0lo[(base >> 8) & 0xff] & 0x01); + + c0 = *r0; + c1 = *r1; + + if (invert) { + *r0 = c1 ^ xor0; + *r1 = c0 ^ xor1; + } else { + *r0 = c0 ^ xor0; + *r1 = c1 ^ xor1; + } +} + +void NeoCMCDecrypt(INT32 extra_xor, UINT8* rom, UINT8* buf, INT32 offset, INT32 block_size, INT32 rom_size) +{ + INT32 clamp_size, rpos; + + if (rom_size > 0x04000000) rom_size = 0x04000000; + + // Adjust variables for addressing 32bit words + rom_size >>= 2; + block_size >>= 2; + offset >>= 2; + + // special handling for games with 6 C ROMs + for (clamp_size = 1 << 30; clamp_size > rom_size; clamp_size >>= 1) { } + + // Data xor + for (rpos = 0; rpos < block_size; rpos++) + { + cmc_xor(buf+4*rpos+0, buf+4*rpos+3, type0_t03, type0_t12, type1_t03, rpos, (rpos>>8) & 1); + cmc_xor(buf+4*rpos+1, buf+4*rpos+2, type0_t12, type0_t03, type1_t12, rpos, (((rpos + offset)>>16) ^ address_16_23_xor2[(rpos>>8) & 0xff]) & 1); + } + + // Address xor + for (rpos = 0; rpos < block_size; rpos++) + { + INT32 baser = rpos + offset; + + baser ^= address_0_7_xor[(baser >> 8) & 0xff]; + baser ^= address_16_23_xor2[(baser >> 8) & 0xff] << 16; + baser ^= address_16_23_xor1[baser & 0xff] << 16; + + if (rpos + offset < clamp_size) + baser &= clamp_size - 1; + else + baser = clamp_size + (baser & ((clamp_size >> 1) - 1)); + + baser ^= address_8_15_xor2[baser & 0xff] << 8; + baser ^= address_8_15_xor1[(baser >> 16) & 0xff] << 8; + + baser ^= extra_xor; + + ((UINT32*)rom)[baser] = ((UINT32*)buf)[rpos]; + } +} + +/* CMC42 protection chip */ +void NeoCMC42Init() +{ + type0_t03 = kof99_type0_t03; + type0_t12 = kof99_type0_t12; + type1_t03 = kof99_type1_t03; + type1_t12 = kof99_type1_t12; + address_8_15_xor1 = kof99_address_8_15_xor1; + address_8_15_xor2 = kof99_address_8_15_xor2; + address_16_23_xor1 = kof99_address_16_23_xor1; + address_16_23_xor2 = kof99_address_16_23_xor2; + address_0_7_xor = kof99_address_0_7_xor; +} + +/* CMC50 protection chip */ +void NeoCMC50Init() +{ + type0_t03 = kof2000_type0_t03; + type0_t12 = kof2000_type0_t12; + type1_t03 = kof2000_type1_t03; + type1_t12 = kof2000_type1_t12; + address_8_15_xor1 = kof2000_address_8_15_xor1; + address_8_15_xor2 = kof2000_address_8_15_xor2; + address_16_23_xor1 = kof2000_address_16_23_xor1; + address_16_23_xor2 = kof2000_address_16_23_xor2; + address_0_7_xor = kof2000_address_0_7_xor; +} + +// M1 Decryption +static const UINT8 m1_address_8_15_xor[256] = { + 0x0a, 0x72, 0xb7, 0xaf, 0x67, 0xde, 0x1d, 0xb1, 0x78, 0xc4, 0x4f, 0xb5, 0x4b, 0x18, 0x76, 0xdd, + 0x11, 0xe2, 0x36, 0xa1, 0x82, 0x03, 0x98, 0xa0, 0x10, 0x5f, 0x3f, 0xd6, 0x1f, 0x90, 0x6a, 0x0b, + 0x70, 0xe0, 0x64, 0xcb, 0x9f, 0x38, 0x8b, 0x53, 0x04, 0xca, 0xf8, 0xd0, 0x07, 0x68, 0x56, 0x32, + 0xae, 0x1c, 0x2e, 0x48, 0x63, 0x92, 0x9a, 0x9c, 0x44, 0x85, 0x41, 0x40, 0x09, 0xc0, 0xc8, 0xbf, + 0xea, 0xbb, 0xf7, 0x2d, 0x99, 0x21, 0xf6, 0xba, 0x15, 0xce, 0xab, 0xb0, 0x2a, 0x60, 0xbc, 0xf1, + 0xf0, 0x9e, 0xd5, 0x97, 0xd8, 0x4e, 0x14, 0x9d, 0x42, 0x4d, 0x2c, 0x5c, 0x2b, 0xa6, 0xe1, 0xa7, + 0xef, 0x25, 0x33, 0x7a, 0xeb, 0xe7, 0x1b, 0x6d, 0x4c, 0x52, 0x26, 0x62, 0xb6, 0x35, 0xbe, 0x80, + 0x01, 0xbd, 0xfd, 0x37, 0xf9, 0x47, 0x55, 0x71, 0xb4, 0xf2, 0xff, 0x27, 0xfa, 0x23, 0xc9, 0x83, + 0x17, 0x39, 0x13, 0x0d, 0xc7, 0x86, 0x16, 0xec, 0x49, 0x6f, 0xfe, 0x34, 0x05, 0x8f, 0x00, 0xe6, + 0xa4, 0xda, 0x7b, 0xc1, 0xf3, 0xf4, 0xd9, 0x75, 0x28, 0x66, 0x87, 0xa8, 0x45, 0x6c, 0x20, 0xe9, + 0x77, 0x93, 0x7e, 0x3c, 0x1e, 0x74, 0xf5, 0x8c, 0x3e, 0x94, 0xd4, 0xc2, 0x5a, 0x06, 0x0e, 0xe8, + 0x3d, 0xa9, 0xb2, 0xe3, 0xe4, 0x22, 0xcf, 0x24, 0x8e, 0x6b, 0x8a, 0x8d, 0x84, 0x4a, 0xd2, 0x91, + 0x88, 0x79, 0x57, 0xa5, 0x0f, 0xcd, 0xb9, 0xac, 0x3b, 0xaa, 0xb3, 0xd1, 0xee, 0x31, 0x81, 0x7c, + 0xd7, 0x89, 0xd3, 0x96, 0x43, 0xc5, 0xc6, 0xc3, 0x69, 0x7f, 0x46, 0xdf, 0x30, 0x5b, 0x6e, 0xe5, + 0x08, 0x95, 0x9b, 0xfb, 0xb8, 0x58, 0x0c, 0x61, 0x50, 0x5d, 0x3a, 0xa2, 0x29, 0x12, 0xfc, 0x51, + 0x7d, 0x1a, 0x02, 0x65, 0x54, 0x5e, 0x19, 0xcc, 0xdc, 0xdb, 0x73, 0xed, 0xad, 0x59, 0x2f, 0xa3, +}; + +static const UINT8 m1_address_0_7_xor[256] = { + 0xf4, 0xbc, 0x02, 0xf7, 0x2c, 0x3d, 0xe8, 0xd9, 0x50, 0x62, 0xec, 0xbd, 0x53, 0x73, 0x79, 0x61, + 0x00, 0x34, 0xcf, 0xa2, 0x63, 0x28, 0x90, 0xaf, 0x44, 0x3b, 0xc5, 0x8d, 0x3a, 0x46, 0x07, 0x70, + 0x66, 0xbe, 0xd8, 0x8b, 0xe9, 0xa0, 0x4b, 0x98, 0xdc, 0xdf, 0xe2, 0x16, 0x74, 0xf1, 0x37, 0xf5, + 0xb7, 0x21, 0x81, 0x01, 0x1c, 0x1b, 0x94, 0x36, 0x09, 0xa1, 0x4a, 0x91, 0x30, 0x92, 0x9b, 0x9a, + 0x29, 0xb1, 0x38, 0x4d, 0x55, 0xf2, 0x56, 0x18, 0x24, 0x47, 0x9d, 0x3f, 0x80, 0x1f, 0x22, 0xa4, + 0x11, 0x54, 0x84, 0x0d, 0x25, 0x48, 0xee, 0xc6, 0x59, 0x15, 0x03, 0x7a, 0xfd, 0x6c, 0xc3, 0x33, + 0x5b, 0xc4, 0x7b, 0x5a, 0x05, 0x7f, 0xa6, 0x40, 0xa9, 0x5d, 0x41, 0x8a, 0x96, 0x52, 0xd3, 0xf0, + 0xab, 0x72, 0x10, 0x88, 0x6f, 0x95, 0x7c, 0xa8, 0xcd, 0x9c, 0x5f, 0x32, 0xae, 0x85, 0x39, 0xac, + 0xe5, 0xd7, 0xfb, 0xd4, 0x08, 0x23, 0x19, 0x65, 0x6b, 0xa7, 0x93, 0xbb, 0x2b, 0xbf, 0xb8, 0x35, + 0xd0, 0x06, 0x26, 0x68, 0x3e, 0xdd, 0xb9, 0x69, 0x2a, 0xb2, 0xde, 0x87, 0x45, 0x58, 0xff, 0x3c, + 0x9e, 0x7d, 0xda, 0xed, 0x49, 0x8c, 0x14, 0x8e, 0x75, 0x2f, 0xe0, 0x6e, 0x78, 0x6d, 0x20, 0xd2, + 0xfa, 0x2d, 0x51, 0xcc, 0xc7, 0xe7, 0x1d, 0x27, 0x97, 0xfc, 0x31, 0xdb, 0xf8, 0x42, 0xe3, 0x99, + 0x5e, 0x83, 0x0e, 0xb4, 0x2e, 0xf6, 0xc0, 0x0c, 0x4c, 0x57, 0xb6, 0x64, 0x0a, 0x17, 0xa3, 0xc1, + 0x77, 0x12, 0xfe, 0xe6, 0x8f, 0x13, 0x71, 0xe4, 0xf9, 0xad, 0x9f, 0xce, 0xd5, 0x89, 0x7e, 0x0f, + 0xc2, 0x86, 0xf3, 0x67, 0xba, 0x60, 0x43, 0xc9, 0x04, 0xb3, 0xb0, 0x1e, 0xb5, 0xc8, 0xeb, 0xa5, + 0x76, 0xea, 0x5c, 0x82, 0x1a, 0x4f, 0xaa, 0xca, 0xe1, 0x0b, 0x4e, 0xcb, 0x6a, 0xef, 0xd1, 0xd6, +}; + +static UINT16 generate_cs16(UINT8 *rom, INT32 size) +{ + UINT16 cs16; + cs16 = 0x0000; + for (INT32 i = 0; i < size; i++) { + cs16 += rom[i]; + } + return cs16 & 0xffff; +} + +static INT32 m1_address_scramble(INT32 address, UINT16 key) +{ + INT32 block; + INT32 aux; + + const INT32 p1[8][16] = { + {15, 14, 10, 7, 1, 2, 3, 8, 0, 12, 11, 13, 6, 9, 5, 4}, + { 7, 1, 8, 11, 15, 9, 2, 3, 5, 13, 4, 14, 10, 0, 6, 12}, + { 8, 6, 14, 3, 10, 7, 15, 1, 4, 0, 2, 5, 13, 11, 12, 9}, + { 2, 8, 15, 9, 3, 4, 11, 7, 13, 6, 0, 10, 1, 12, 14, 5}, + { 1, 13, 6, 15, 14, 3, 8, 10, 9, 4, 7, 12, 5, 2, 0, 11}, + {11, 15, 3, 4, 7, 0, 9, 2, 6, 14, 12, 1, 8, 5, 10, 13}, + {10, 5, 13, 8, 6, 15, 1, 14, 11, 9, 3, 0, 12, 7, 4, 2}, + { 9, 3, 7, 0, 2, 12, 4, 11, 14, 10, 5, 8, 15, 13, 1, 6}, + }; + + block = (address >> 16) & 7; + aux = address & 0xffff; + + aux ^= BITSWAP16(key, 12, 0, 2, 4, 8, 15, 7, 13, 10, 1, 3, 6, 11, 9, 14, 5); + aux = BITSWAP16(aux, + p1[block][15], p1[block][14], p1[block][13], p1[block][12], + p1[block][11], p1[block][10], p1[block][9] , p1[block][8], + p1[block][7] , p1[block][6] , p1[block][5] , p1[block][4], + p1[block][3] , p1[block][2] , p1[block][1] , p1[block][0]); + aux ^= m1_address_0_7_xor[(aux >> 8) & 0xff]; + aux ^= m1_address_8_15_xor[aux & 0xff] << 8; + aux = BITSWAP16(aux, 7, 15, 14, 6, 5, 13, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0); + + return (block << 16) | aux; +} + +void neogeo_cmc50_m1_decrypt() +{ + UINT8 *rom = NeoZ80ROMActive; + UINT8 *buffer = (UINT8*)malloc(0x80000); + + UINT16 key = generate_cs16(rom, 0x10000); + + for (INT32 i = 0; i < 0x80000; i++) { + buffer[i] = rom[m1_address_scramble(i, key)]; + } + + memcpy(rom, buffer, 0x80000); + if (buffer) { + free(buffer); + buffer = NULL; + } +} diff --git a/src/burn/drivers/neogeo/neo_palette.cpp b/src/burn/drivers/neogeo/neo_palette.cpp new file mode 100644 index 00000000..ae42f0da --- /dev/null +++ b/src/burn/drivers/neogeo/neo_palette.cpp @@ -0,0 +1,117 @@ +#include "neogeo.h" +// Neo Geo -- palette functions + +UINT8* NeoPalSrc[2]; // Pointer to input palettes +UINT32* NeoPalette; +INT32 nNeoPaletteBank; // Selected palette bank + +static UINT32* NeoPaletteData[2] = {NULL, NULL}; +static UINT16* NeoPaletteCopy[2] = {NULL, NULL}; + +UINT8 NeoRecalcPalette; + +INT32 NeoInitPalette() +{ + for (INT32 i = 0; i < 2; i++) { + if (NeoPaletteData[i]) { + free(NeoPaletteData[i]); + NeoPaletteData[i] = NULL; + } + if (NeoPaletteCopy[i]) { + free(NeoPaletteCopy[i]); + NeoPaletteCopy[i] = NULL; + } + NeoPaletteData[i] = (UINT32*)malloc(4096 * sizeof(UINT32)); + NeoPaletteCopy[i] = (UINT16*)malloc(4096 * sizeof(UINT16)); + } + + NeoRecalcPalette = 1; + + return 0; +} + +void NeoExitPalette() +{ + for (INT32 i = 0; i < 2; i++) { + if (NeoPaletteData[i]) { + free(NeoPaletteData[i]); + NeoPaletteData[i] = NULL; + } + if (NeoPaletteCopy[i]) { + free(NeoPaletteCopy[i]); + NeoPaletteCopy[i] = NULL; + } + } +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r = (nColour & 0x0F00) >> 4; // Red + r |= (nColour >> 11) & 8; + INT32 g = (nColour & 0x00F0); // Green + g |= (nColour >> 10) & 8; + INT32 b = (nColour & 0x000F) << 4; // Blue + b |= (nColour >> 9) & 8; + + r |= r >> 5; + g |= g >> 5; + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +INT32 NeoUpdatePalette() +{ + if (NeoRecalcPalette) { + INT32 i; + UINT16* ps; + UINT16* pc; + UINT32* pd; + + // Update both palette banks + for (INT32 j = 0; j < 2; j++) { + for (i = 0, ps = (UINT16*)NeoPalSrc[j], pc = NeoPaletteCopy[j], pd = NeoPaletteData[j]; i < 4096; i++, ps++, pc++, pd++) { + *pc = *ps; + *pd = CalcCol(*ps); + } + } + + NeoRecalcPalette = 0; + + } + + return 0; +} + +void NeoSetPalette() +{ + NeoPalette = NeoPaletteData[nNeoPaletteBank]; +} + +// Update the PC copy of the palette on writes to the palette memory +void __fastcall NeoPalWriteByte(UINT32 nAddress, UINT8 byteValue) +{ + nAddress &= 0x1FFF; + nAddress ^= 1; + + NeoPalSrc[nNeoPaletteBank][nAddress] = byteValue; // write byte + + if (*((UINT8*)(NeoPaletteCopy[nNeoPaletteBank] + nAddress)) != byteValue) { + *((UINT8*)(NeoPaletteCopy[nNeoPaletteBank] + nAddress)) = byteValue; + NeoPaletteData[nNeoPaletteBank][nAddress >> 1] = CalcCol(*(UINT16*)(NeoPalSrc[nNeoPaletteBank] + (nAddress & ~0x01))); + } +} + +void __fastcall NeoPalWriteWord(UINT32 nAddress, UINT16 wordValue) +{ + nAddress &= 0x1FFF; + nAddress >>= 1; + + ((UINT16*)NeoPalSrc[nNeoPaletteBank])[nAddress] = wordValue; // write word + + if (NeoPaletteCopy[nNeoPaletteBank][nAddress] != wordValue) { + NeoPaletteCopy[nNeoPaletteBank][nAddress] = wordValue; + NeoPaletteData[nNeoPaletteBank][nAddress] = CalcCol(wordValue); + } +} + diff --git a/src/burn/drivers/neogeo/neo_run.cpp b/src/burn/drivers/neogeo/neo_run.cpp new file mode 100644 index 00000000..fcf22927 --- /dev/null +++ b/src/burn/drivers/neogeo/neo_run.cpp @@ -0,0 +1,4876 @@ +/* + +struct NeoMediaInfo { + UINT8* p68KROM; + UINT8* pVector; + UINT8* pZ80ROM; + UINT8* pSpriteROM; + UINT8* pTextROM; + UINT8* pADPCMROM; + UINT8* pDeltaTROM; + + INT32 n68KBankOffset; + INT32 nVectorOffset; + + INT32 n68KROMSize; + INT32 nZ80ROMSize; + INT32 nSpriteROMSize; + INT32 nTextROMSize; + INT32 nADPCMROMSize; + INT32 nADeltaROMSize; + + // Function callbacks + + void (*pLoadCallback)(); + void (*pUnloadCallback)(); + void (*pInstallCallback)(); + void (*pUnnstallCallback)(); + void (*pBankswitchCallback)(); + INT32 (*pScan)(int, int*); + + // Private data + + INT32 nSRAMProtectionOffset; + + void* pCustomData; + void* pTextData; +}; + +*/ + +/* + * FB Alpha Neo Geo module + * + * The video frequencies of MVS hardware are: + * hsync: 15625 Hz + * vsync: ~59.18 Hz (264 scanlines make up a single frame) + * The image occupies 224 scanlines, spanning scanlines 24 to 248. + * + * The memory card interface occupies 128KB of memory. There are 2 kinds of + * memory cards that can be used -- 16bit or 8bit. For games, a maximum of 16kB + * data is stored on either, but 16bit cards can be used to transfer bookkeeping + * information. For 8bit cards, only odd bytes are used to address memory and + * the BIOS tests the size of the inserted card by writing to the first byte of + * each 2kB block. The interface used is JEIDA 3.0. + * + * bit 6 of memory location 0x300081 = 0 -> 1/2 slot MVS + * = 1 + bit 5 of 0x320001 = 0 -> 4 slot MVS + * = 1 -> 6 slot MVS + * + * On MVS hardware with multiple slots, address 0x380021 is used to select the + * active slot. + * + * The watchdog timer will reset the system after ~0.13 seconds + * + * On an MV-1F system, the following code was used to test: + * 000100 203C 0001 4F51 MOVE.L #0x14F51,D0 + * 000106 13C0 0030 0001 MOVE.B D0,0x300001 + * 00010C 5380 SUBQ.L #1,D0 + * 00010E 64FC BCC.S *-0x2 [0x10C] + * 000110 13C0 0030 0001 MOVE.B D0,0x300001 + * 000116 60F8 BRA.S *-0x6 [0x110] + * This code loops long enough to sometimes cause a reset, sometimes not. + * The move takes 16 cycles, subq 8, bcc 10 if taken and 8 if not taken, so: + * (0x14F51 * 18 + 14) cycles / 12000000 cycles per second = 0.12876 seconds + * + * Newer games force a reset using the following code (this from kof99): + * 009CDA 203C 0003 0D40 MOVE.L #0x30D40,D0 + * 009CE0 5380 SUBQ.L #1,D0 + * 009CE2 64FC BCC.S *-0x2 [0x9CE0] + * Note however that there is a valid code path after this loop, and indeed + * there are many games that employ the watchdog as a protection device, by + * writing a value to SRAM (usually to 0xD00100) when the watchdog doesn't + * trigger a reset. Later on, the presence of this value can trigger various + * actions, usually a text screen indicating the game is an unlicensed copy. + * + * On AES hardware, reading unmapped memory returns the last value that was on + * the data-bus. + * + * Raster interrupts can be generated by specifying an offset, in pixels. + * This offset can be added to the following (depending on a control register): + * - the position of the electron beam, when setting the offset + * - the position of the electron beam, when interrupt 2 is triggered + * - the position of the electron beam, when interrupt 4 (vblank) is triggered + * + * Note that the offset is *always* relative; when setting the offset from the + * vblank (scanline 248), to trigger an interrupt at scanline 24, you would + * poINT32 the offset to 24 scanlines past the screen end at line 264, and set it + * to 15360 (40 scanlines * 384 pixels per scanline). + * + */ + +#include "neogeo.h" +#include "cd_interface.h" +#include "burn_ym2610.h" +#include "bitswap.h" +#include "neocdlist.h" + +// #undef USE_SPEEDHACKS + +// #define LOG_IRQ +// #define LOG_DRAW + +#define NEO_HREFRESH (15625.0) +#define NEO_VREFRESH (NEO_HREFRESH / 264.0) +// #define NEO_VREFRESH (NEO_HREFRESH / 312.0) + +// If defined, enable emulation of the watchdog timer (timing doesn't match real hardware 100%) +#define EMULATE_WATCHDOG + +// If defined, reset the Z80 when switching between the Z80 BIOS/cartridge ROM +//#define Z80_RESET_ON_BANKSWITCH + +// If defined, adjust the Z80 speed along with the 68000 when overclocking +#define Z80_SPEED_ADJUST + +// If defined, use kludges to better align raster effects in some games (e.g. mosyougi) +#define RASTER_KLUDGE + +// If defined, use the bAllowRasters variable to enable/disable raster effects +// #define RASTERS_OPTIONAL + +#if defined Z80_SPEED_ADJUST + static INT32 nZ80Clockspeed; +#else + static const INT32 nZ80Clockspeed = 4000000; +#endif + +#if defined RASTER_KLUDGE + static UINT16 nScanlineOffset; +#else + // 0xF8 is correct as verified on MVS hardware + static const UINT16 nScanlineOffset = 0xF8; +#endif + +#if defined RASTERS_OPTIONAL + static bool bAllowRasters = false; +#endif + +// The number of cartridge slots on the emulated MVS hardware (can be 1, 2, 4, or 6) +UINT8 nNeoNumSlots = 1; + +UINT32 nNeoActiveSlot = 0; + +UINT8 NeoButton1[32] = { 0, }; +UINT8 NeoButton2[8] = { 0, }; +UINT8 NeoButton3[8] = { 0, }; +UINT8 NeoButton4[8] = { 0, }; +UINT8 NeoJoy1[8] = { 0, }; +UINT8 NeoJoy2[8] = { 0, }; +UINT8 NeoJoy3[8] = { 0, }; +UINT8 NeoJoy4[8] = { 0, }; +UINT16 NeoAxis[2] = { 0, }; +UINT8 NeoInput[32] = { 0, }; +UINT8 NeoDiag[2] = { 0, }; +UINT8 NeoDebugDip[2] = { 0, }; +UINT8 NeoReset = 0, NeoSystem = 0; + +static UINT8 OldDebugDip[2]; + +// Which 68K BIOS to use +INT32 nBIOS; + +// Joyports are multiplexed +static INT32 nJoyport0[8] = { 0, }; +static INT32 nJoyport1[8] = { 0, }; + +// Ports always mirror the joystick, except when other controllers are hooked up: +// +// input no. corresponds to +// +// Joyport0: 0x00 : trackball X in irrmaze / p1 paddle in popbounc +// 0x01 : trackball Y in irrmaze +// 0x09 : mahjong controller +// 0x12 : mahjong controller (BIOS controls) +// 0x1B : Always has p1 joystick & buttons +// 0x24 : mahjong controller +// 0x20 & 0x21 : selected by irrmaze instead of 0x00 & 0x01 when you lose a life +// (activates air-jets) +// Joyport1: 0x00 : p2 paddle in popbounc +// 0x1B : Always has p2 joystick & buttons + +// ---------------------------------------------------------------------------- +// Variables that need to be included in savestates + +static INT32 nCyclesExtra[2]; +static INT32 nPrevBurnCPUSpeedAdjust; + +bool bNeoEnableGraphics; + +UINT32 nNeo68KROMBank; + +static INT32 nIRQAcknowledge; + +static INT32 nIRQControl; +static bool bSRAMWritable; + +static bool b68KBoardROMBankedIn; +static bool bZ80BoardROMBankedIn; +static INT32 nZ80Bank0, nZ80Bank1, nZ80Bank2, nZ80Bank3; + +static UINT8* NeoGraphicsRAMBank; +static UINT16 NeoGraphicsRAMPointer; +static INT32 nNeoGraphicsModulo; + +INT32 nNeoSpriteFrame; + +static INT32 nSpriteFrameSpeed; +static INT32 nSpriteFrameTimer; + +static UINT8 nSoundLatch; +static UINT8 nSoundReply; +static UINT32 nSoundStatus; + +#if 1 && defined USE_SPEEDHACKS +static INT32 nSoundPrevReply; +#endif + +static INT32 nInputSelect; +static UINT8* NeoInputBank; +static UINT32 nAnalogAxis[2]; + +static UINT32 nuPD4990ATicks; + +static UINT32 nIRQOffset; + +#define NO_IRQ_PENDING (0x7FFFFFFF) +static INT32 nIRQCycles; + +#if defined EMULATE_WATCHDOG +static INT32 nNeoWatchdog; +#endif + +static INT32 nNeoCDIRQVector; +static INT32 nNeoCDIRQVectorAck; + +static INT32 nNeoCDZ80ProgWriteWordCancelHack = 0; + +INT32 nNeoScreenWidth; + +UINT8 nLEDLatch, nLED[3]; + +// ---------------------------------------------------------------------------- + +static bool bMemoryCardInserted, bMemoryCardWritable; + +NEO_CALLBACK NeoCallback[MAX_SLOT] = { { NULL, NULL, NULL, NULL, NULL }, }; +NEO_CALLBACK* NeoCallbackActive = &NeoCallback[0]; + +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; +static INT32 nCyclesVBlank; +static INT32 nCycles68KSync; + +UINT8 *Neo68KROM[MAX_SLOT] = { NULL, }, *Neo68KROMActive = NULL; +UINT8 *NeoVector[MAX_SLOT] = { NULL, }, *NeoVectorActive = NULL; +UINT8 *Neo68KFix[MAX_SLOT] = { NULL, }; +UINT8 *NeoZ80ROM[MAX_SLOT] = { NULL, }, *NeoZ80ROMActive = NULL; + +static UINT8 *AllRAM = NULL, *RAMEnd = NULL, *AllROM = NULL, *ROMEnd = NULL; + +UINT8 *NeoSpriteRAM, *NeoTextRAM; + +UINT8 *Neo68KBIOS, *NeoZ80BIOS; +static UINT8 *Neo68KRAM, *NeoZ80RAM, *NeoNVRAM, *NeoNVRAM2, *NeoMemoryCard; + +static UINT32 nSpriteSize[MAX_SLOT] = { 0, }; +static UINT32 nCodeSize[MAX_SLOT] = { 0, }; + +UINT8* NeoGraphicsRAM; + +UINT8* YM2610ADPCMAROM[MAX_SLOT] = { NULL, }; +UINT8* YM2610ADPCMBROM[MAX_SLOT] = { NULL, }; + +static INT32 nYM2610ADPCMASize[MAX_SLOT] = { 0, }; +static INT32 nYM2610ADPCMBSize[MAX_SLOT] = { 0, }; + +static bool bIRQEnabled; +static INT32 nVBLankIRQ; +static INT32 nScanlineIRQ; + +static bool bRenderImage; + +static bool bRenderLineByLine; + +static bool bForcePartialRender; +static bool bForceUpdateOnStatusRead; + +static INT32 nNeoControlConfig; + +static INT32 nNeoSystemType; +static bool bZ80BIOS; + +static INT32 /*nNeoCDCyclesIRQ = 0,*/ nNeoCDCyclesIRQPeriod = 0; + +static bool bUseAsm68KCoreOldValue = false; + +bool IsNeoGeoCD() { + return (nNeoSystemType & NEO_SYS_CD); +} + +// This function is called once to determine how much memory is needed (RAMEnd-(UINT8 *)0), +// then a second time after the memory is allocated to set up all the pointers. +static INT32 RAMIndex() +{ + UINT8* Next = AllRAM; + + NeoPalSrc[0] = Next; Next += 0x002000; // Palette RAM Bank 0 + NeoPalSrc[1] = Next; Next += 0x002000; // Palette RAM Bank 1 + + NeoGraphicsRAM = Next; Next += 0x020000; // Graphics controller RAM (2 64KB banks) + + if (nNeoSystemType & NEO_SYS_CART) { + Neo68KRAM = Next; Next += 0x010000; // 68K work RAM + NeoZ80RAM = Next; Next += 0x000800; // Z80 RAM + + NeoNVRAM = Next; Next += 0x010000; // Battery backed SRAM + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) == HARDWARE_SNK_GAMBLING) { + NeoNVRAM2 = Next; Next += 0x002000; // Extra SRAM for vliner/jockeygp + } + NeoMemoryCard = Next; Next += 0x020000; // Memory card + + if (nNeoSystemType & NEO_SYS_CD) { + NeoSpriteRAM = Next; Next += nSpriteSize[0]; + NeoTextRAM = Next; Next += nNeoTextROMSize[0]; + } + + RAMEnd = Next; + + return 0; +} + +// This function is called once to determine how much memory is needed (ROMEnd-(UINT8*)0), +// then a second time after the memory is allocated to set up all the pointers. +static INT32 ROMIndex() +{ + UINT8* Next = AllROM; + + NeoZ80BIOS = Next; Next += 0x020000; // Z80 boardROM + NeoZoomROM = Next; Next += 0x020000; // Y Zoom table + NeoTextROMBIOS = Next; Next += 0x020000; + + if (nNeoSystemType & NEO_SYS_CART) { + Neo68KBIOS = Next; Next += 0x080000; // 68K boardROM + } else { + Neo68KROM[0] = Next; Next += nCodeSize[0]; + NeoVector[0] = Next; Next += 0x000400; // Copy of 68K cartridge ROM with boardROM vector table + Neo68KBIOS = Next; Next += 0x080000; // 68K boardROM + + NeoZ80ROM[0] = Next; Next += 0x080000; + NeoSpriteROM[0] = Next; Next += nSpriteSize[0]; + NeoTextROM[0] = Next; Next += nNeoTextROMSize[0]; + YM2610ADPCMAROM[0] = Next; Next += nYM2610ADPCMASize[0]; + YM2610ADPCMBROM[0] = Next; Next += nYM2610ADPCMBSize[0]; + } + + ROMEnd = Next; + + return 0; +} + +// ----------------------------------------------------------------------------- +// ROM loading + +static void NeoSetSystemType() +{ + // Neo CD + if (nNeoSystemType & NEO_SYS_CD) { + return; + } + // Dedicated JAMMA PCB + if (nNeoSystemType & NEO_SYS_PCB) { + return; + } + + // See if we're emulating MVS or AES hardware + if (nBIOS == -1 || nBIOS == 10 || nBIOS == 11 || nBIOS == 12 || ((NeoSystem & 0x74) == 0x20)) { + nNeoSystemType = NEO_SYS_CART | NEO_SYS_AES; + return; + } + + nNeoSystemType = NEO_SYS_CART | NEO_SYS_MVS; +} + +static INT32 NeoLoad68KBIOS(INT32 nNewBIOS) +{ + // Neo CD + if (nNeoSystemType & NEO_SYS_CD) { + return 0; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) == HARDWARE_SNK_TRACKBALL) { + nNewBIOS = 25; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + nNewBIOS = 26; + } + + // The most recent MVS models doesn't have a Z80 BIOS + bZ80BIOS = (nNewBIOS != 0) ? true : false; + + // Check if we need to load a new BIOS + if (nNewBIOS == nBIOS) { + return 0; + } + + nBIOS = nNewBIOS; + + // Load the BIOS ROMs + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + // Load the BIOS ROMs + BurnLoadRom(Neo68KBIOS, 0x00000 + nBIOS, 1); + } else { + if (nBIOS >= 0) { + BurnLoadRom(Neo68KBIOS, 0x00080 + nBIOS, 1); + } else { + BurnLoadRom(Neo68KBIOS, 0x00080 + 0, 1); + } + } + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "kf2k3pcb") || !strcmp(BurnDrvGetTextA(DRV_NAME), "k2k3pcbd")) kf2k3pcb_bios_decode(); + + NeoUpdateVector(); + + return 0; +} + +static INT32 FindType(const char* pName) +{ + INT32 i = 0; + + while (pName[i] && pName[i] != '-' && pName[i] != '_') { + i++; + } + + return i + 1; +} + +static INT32 FindROMs(UINT32 nType, INT32* pOffset, INT32* pNum) +{ + INT32 nOffset = -1; + INT32 nNum = -1; + + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + + // Invalidate indices + if (pOffset) { + *pOffset = -1; + } + if (pNum) { + *pNum = 0; + } + + do { + if (BurnDrvGetRomInfo(&ri, ++nOffset)) { + return 1; + } + } while ((ri.nType & 7) != nType && nOffset < 0x80); + + if (nOffset >= 0x7F) { + return 1; + } + + do { + if (BurnDrvGetRomInfo(&ri, nOffset + ++nNum)) { + break; + } + } while ((ri.nType & 7) == nType && nOffset < 0x80); + + if (pOffset) { + *pOffset = nOffset; + } + if (pNum) { + *pNum = nNum >= 0 ? nNum : 0; + } + + return 0; +} + +static INT32 LoadRoms() +{ + NeoGameInfo info; + NeoGameInfo* pInfo = &info; + + { + struct BurnRomInfo ri; + + ri.nType = 0; + ri.nLen = 0; + + // Find 'P' ROMs + FindROMs(1, &pInfo->nCodeOffset, &pInfo->nCodeNum); + // Find 'S' ROM + FindROMs(2, &pInfo->nTextOffset, NULL); + // Find 'C' ROMs + FindROMs(3, &pInfo->nSpriteOffset, &pInfo->nSpriteNum); + // Find 'M' ROM + FindROMs(4, &pInfo->nSoundOffset, NULL); + // Find 'V' ROMs + FindROMs(5, &pInfo->nADPCMOffset, &pInfo->nADPCMANum); + FindROMs(6, NULL, &pInfo->nADPCMBNum); + + if (pInfo->nADPCMBNum < 0) { + pInfo->nADPCMBNum = 0; + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T(" - P: %i (%i);"), pInfo->nCodeOffset, pInfo->nCodeNum); + if (pInfo->nTextOffset >= 0) { + bprintf(PRINT_IMPORTANT, _T(" S: %i;"), pInfo->nTextOffset); + } else { + bprintf(PRINT_IMPORTANT, _T(" S: unused;")); + } + bprintf(PRINT_IMPORTANT, _T(" C: %i (%i); M: %i"), pInfo->nSpriteOffset, pInfo->nSpriteNum, pInfo->nSoundOffset); + if (pInfo->nADPCMOffset >= 0) { + bprintf(PRINT_IMPORTANT, _T(" V: %i (%i, %i)"), pInfo->nADPCMOffset, pInfo->nADPCMANum, pInfo->nADPCMBNum); + } else { + bprintf(PRINT_IMPORTANT, _T(" V: unused")); + } + bprintf(PRINT_IMPORTANT,_T("\n")); +#endif + + nCodeSize[nNeoActiveSlot] = 0; + for (INT32 i = 0; i < pInfo->nCodeNum; i++) { + BurnDrvGetRomInfo(&ri, pInfo->nCodeOffset + i); + nCodeSize[nNeoActiveSlot] += ri.nLen; + } + nCodeSize[nNeoActiveSlot] = (nCodeSize[nNeoActiveSlot] + 0x0FFFFF) & ~0x0FFFFF; + + nSpriteSize[nNeoActiveSlot] = 0; + + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_SWAPC) { + BurnDrvGetRomInfo(&ri, pInfo->nSpriteOffset); + // for viewpoin, aof, ssideki + if (pInfo->nSpriteNum == 2) { + nSpriteSize[nNeoActiveSlot] = 0x600000; + } + // for kotm2 + if (pInfo->nSpriteNum == 4) { + BurnDrvGetRomInfo(&ri, pInfo->nSpriteOffset + 2); + if (ri.nLen == 0x080000) { + nSpriteSize[nNeoActiveSlot] = 0x600000; + } + } + } + + if (nSpriteSize[nNeoActiveSlot] == 0) { + + // Compute correct size taking gaps into account (kizuna) + for (INT32 i = 0; i < pInfo->nSpriteNum - 2; i += 2) { + BurnDrvGetRomInfo(&ri, pInfo->nSpriteOffset + i); + if (ri.nLen > nSpriteSize[nNeoActiveSlot]) { + nSpriteSize[nNeoActiveSlot] = ri.nLen; + } + } + nSpriteSize[nNeoActiveSlot] *= pInfo->nSpriteNum - 2; + + // The final 2 ROMs may have a different size + BurnDrvGetRomInfo(&ri, pInfo->nSpriteOffset + pInfo->nSpriteNum - 2); + nSpriteSize[nNeoActiveSlot] += ri.nLen * 2; + } + + { + UINT32 nSize = nSpriteSize[nNeoActiveSlot]; +// if (nSize > 0x4000000) { +// nSize = 0x4000000; +// } + + for (nNeoTileMask[nNeoActiveSlot] = 1; nNeoTileMask[nNeoActiveSlot] < nSize; nNeoTileMask[nNeoActiveSlot] <<= 1) { } + nNeoTileMask[nNeoActiveSlot] = (nNeoTileMask[nNeoActiveSlot] >> 7) - 1; + nNeoMaxTile[nNeoActiveSlot] = nSize >> 7; + } + + if (nNeoTextROMSize[nNeoActiveSlot] == 0) { + if (pInfo->nTextOffset > 0) { + BurnDrvGetRomInfo(&ri, pInfo->nTextOffset); + nNeoTextROMSize[nNeoActiveSlot] = ri.nLen; + } else { + nNeoTextROMSize[nNeoActiveSlot] = 0x080000; + } + } + + nYM2610ADPCMASize[nNeoActiveSlot] = nYM2610ADPCMBSize[nNeoActiveSlot] = 0; + if (pInfo->nADPCMOffset >= 0) { + char* pName; + BurnDrvGetRomInfo(&ri, pInfo->nADPCMOffset); + BurnDrvGetRomName(&pName, pInfo->nADPCMOffset, 0); + nYM2610ADPCMASize[nNeoActiveSlot] = ri.nLen; + + if (pInfo->nADPCMANum > 1) { + BurnDrvGetRomInfo(&ri, pInfo->nADPCMOffset + pInfo->nADPCMANum - 1); + BurnDrvGetRomName(&pName, pInfo->nADPCMOffset + pInfo->nADPCMANum - 1, 0); + if (pInfo->nADPCMBNum == 0) { + nYM2610ADPCMASize[nNeoActiveSlot] *= pName[FindType(pName) + 1] - '1'; + } else { + nYM2610ADPCMASize[nNeoActiveSlot] *= pName[FindType(pName) + 2] - '1'; + } + nYM2610ADPCMASize[nNeoActiveSlot] += ri.nLen; + } + + if (pInfo->nADPCMBNum) { + BurnDrvGetRomInfo(&ri, pInfo->nADPCMOffset + pInfo->nADPCMANum); + nYM2610ADPCMBSize[nNeoActiveSlot] = ri.nLen * (pInfo->nADPCMBNum - 1); + BurnDrvGetRomInfo(&ri, pInfo->nADPCMOffset + pInfo->nADPCMANum + pInfo->nADPCMBNum - 1); + nYM2610ADPCMBSize[nNeoActiveSlot] += ri.nLen; + } + } + } + + if (!strcmp("kof2k4se", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x800000; + if (!strcmp("kf2k4pls", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x800000; + if (!strcmp("svcboot", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x400000; + if (!strcmp("svcplus", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x400000; + if (!strcmp("svcplusa", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x400000; + if (!strcmp("svcsplus", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] += 0x400000; + if (!strcmp("pbobblenb", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] = 0x180000; + if (!strcmp("alpham2p", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] = 0x200000; + if (!strcmp("burningfp", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] = 0x180000; + if (!strcmp("kotm2p", BurnDrvGetTextA(DRV_NAME))) nYM2610ADPCMASize[nNeoActiveSlot] = 0x300000; + +// bprintf(PRINT_NORMAL, _T("%x\n"), nYM2610ADPCMASize[nNeoActiveSlot]); + + // The kof2k3 PCB has 96MB of graphics ROM, however the last 16MB are unused, and the protection/decryption hardware does not see them +// if (nSpriteSize[nNeoActiveSlot] > 0x4000000) { +// nSpriteSize[nNeoActiveSlot] = 0x5000000; +// } + + NeoSpriteROM[nNeoActiveSlot] = (UINT8*)malloc(nSpriteSize[nNeoActiveSlot] < (nNeoTileMask[nNeoActiveSlot] << 7) ? ((nNeoTileMask[nNeoActiveSlot] + 1) << 7) : nSpriteSize[nNeoActiveSlot]); + if (NeoSpriteROM[nNeoActiveSlot] == NULL) { + return 1; + } + +/* if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + BurnSetProgressRange(1.0 / ((double)nSpriteSize[nNeoActiveSlot] / 0x800000 / 12)); + } else if (BurnDrvGetHardwareCode() & (HARDWARE_SNK_CMC42 | HARDWARE_SNK_CMC50)) { + BurnSetProgressRange(1.0 / ((double)nSpriteSize[nNeoActiveSlot] / 0x800000 / 9)); + } else { + BurnSetProgressRange(1.0 / ((double)nSpriteSize[nNeoActiveSlot] / 0x800000 / 3)); + }*/ + + if (BurnDrvGetHardwareCode() & (HARDWARE_SNK_CMC42 | HARDWARE_SNK_CMC50)) { + double fRange = (double)pInfo->nSpriteNum / 4.0; + if (fRange < 1.5) { + fRange = 1.5; + } + BurnSetProgressRange(1.0 / fRange); + } else { + BurnSetProgressRange(1.0 / pInfo->nSpriteNum); + } + + // Load sprite data + NeoLoadSprites(pInfo->nSpriteOffset, pInfo->nSpriteNum, NeoSpriteROM[nNeoActiveSlot], nSpriteSize[nNeoActiveSlot]); + + NeoTextROM[nNeoActiveSlot] = (UINT8*)malloc(nNeoTextROMSize[nNeoActiveSlot]); + if (NeoTextROM[nNeoActiveSlot] == NULL) { + return 1; + } + + // Load Text layer tiledata + { + if (pInfo->nTextOffset != -1) { + // Load S ROM data + BurnLoadRom(NeoTextROM[nNeoActiveSlot], pInfo->nTextOffset, 1); + } else { + // Extract data from the end of C ROMS + BurnUpdateProgress(0.0, _T("Decrypting text layer graphics...")/*, BST_DECRYPT_TXT*/, 0); + NeoCMCExtractSData(NeoSpriteROM[nNeoActiveSlot], NeoTextROM[nNeoActiveSlot], nSpriteSize[nNeoActiveSlot], nNeoTextROMSize[nNeoActiveSlot]); + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + for (INT32 i = 0; i < nNeoTextROMSize[nNeoActiveSlot]; i++) { + NeoTextROM[nNeoActiveSlot][i] = BITSWAP08(NeoTextROM[nNeoActiveSlot][i] ^ 0xd2, 4, 0, 7, 2, 5, 1, 6, 3); + } + } + } + } + + Neo68KROM[nNeoActiveSlot] = (UINT8*)malloc(nCodeSize[nNeoActiveSlot]); // 68K cartridge ROM + if (Neo68KROM[nNeoActiveSlot] == NULL) { + return 1; + } + Neo68KROMActive = Neo68KROM[nNeoActiveSlot]; + Neo68KFix[nNeoActiveSlot] = Neo68KROM[nNeoActiveSlot]; + + // Load the roms into memory + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_SMA_PROTECTION) { + BurnLoadRom(Neo68KROMActive + 0x0C0000, 0, 1); + NeoLoadCode(pInfo->nCodeOffset + 1, pInfo->nCodeNum - 1, Neo68KROMActive + 0x100000); + } else { + NeoLoadCode(pInfo->nCodeOffset, pInfo->nCodeNum, Neo68KROMActive); + } + + NeoZ80ROM[nNeoActiveSlot] = (UINT8*)malloc(0x080000); // Z80 cartridge ROM + if (NeoZ80ROM[nNeoActiveSlot] == NULL) { + return 1; + } + NeoZ80ROMActive = NeoZ80ROM[nNeoActiveSlot]; + + BurnLoadRom(NeoZ80ROMActive, pInfo->nSoundOffset, 1); + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_ENCRYPTED_M1) { + neogeo_cmc50_m1_decrypt(); + } + + if (NeoCallbackActive && NeoCallbackActive->pInitialise) { + NeoCallbackActive->pInitialise(); + } + + // Decode text data + BurnUpdateProgress(0.0, _T("Preprocessing text layer graphics...")/*, BST_PROCESS_TXT*/, 0); + NeoDecodeText(0, nNeoTextROMSize[nNeoActiveSlot], NeoTextROM[nNeoActiveSlot], NeoTextROM[nNeoActiveSlot]); + + // Decode sprite data + NeoDecodeSprites(NeoSpriteROM[nNeoActiveSlot], nSpriteSize[nNeoActiveSlot]); + + if (pInfo->nADPCMANum) { + char* pName; + struct BurnRomInfo ri; + UINT8* pADPCMData; + + YM2610ADPCMAROM[nNeoActiveSlot] = (UINT8*)malloc(nYM2610ADPCMASize[nNeoActiveSlot]); + if (YM2610ADPCMAROM[nNeoActiveSlot] == NULL) { + return 1; + } + + ri.nType = 0; + ri.nLen = 0; + BurnDrvGetRomInfo(&ri, pInfo->nADPCMOffset); + BurnDrvGetRomName(&pName, pInfo->nADPCMOffset, 0); + + pADPCMData = YM2610ADPCMAROM[nNeoActiveSlot]; + + // pbobblen needs this (V ROMs are v3 & v4), note aof/wh1/wh1h/kotm2 (V ROMs are v2 & v4) + if (pInfo->nADPCMANum == 2 && pName[FindType(pName) + 1] == '3') { + pADPCMData += ri.nLen * 2; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "pbobblenb")) { + YM2610ADPCMAROM[nNeoActiveSlot] = (UINT8*)realloc(YM2610ADPCMAROM[nNeoActiveSlot], 0x380000); + nYM2610ADPCMASize[nNeoActiveSlot] += 0x200000; + pADPCMData = YM2610ADPCMAROM[nNeoActiveSlot] + 0x200000; + } + + NeoLoadADPCM(pInfo->nADPCMOffset, pInfo->nADPCMANum, pADPCMData); + + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_SWAPV) { + for (INT32 i = 0; i < 0x00200000; i++) { + UINT8 n = YM2610ADPCMAROM[nNeoActiveSlot][i]; + YM2610ADPCMAROM[nNeoActiveSlot][i] = YM2610ADPCMAROM[nNeoActiveSlot][0x00200000 + i]; + YM2610ADPCMAROM[nNeoActiveSlot][0x00200000 + i] = n; + } + } + } + + if (pInfo->nADPCMBNum) { + YM2610ADPCMBROM[nNeoActiveSlot] = (UINT8*)malloc(nYM2610ADPCMBSize[nNeoActiveSlot]); + if (YM2610ADPCMBROM[nNeoActiveSlot] == NULL) { + return 1; + } + + NeoLoadADPCM(pInfo->nADPCMOffset + pInfo->nADPCMANum, pInfo->nADPCMBNum, YM2610ADPCMBROM[nNeoActiveSlot]); + } else { + YM2610ADPCMBROM[nNeoActiveSlot] = YM2610ADPCMAROM[nNeoActiveSlot]; + nYM2610ADPCMBSize[nNeoActiveSlot] = nYM2610ADPCMASize[nNeoActiveSlot]; + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Bankswitch / memory map functions + +static void NeoZ80SetBank0(INT32 nBank) +{ + nBank &= 0x0F; + if (nBank != nZ80Bank0) { + UINT8* nStartAddress = NeoZ80ROMActive + (nBank << 14); + ZetMapArea(0x8000, 0xBFFF, 0, nStartAddress); + ZetMapArea(0x8000, 0xBFFF, 2, nStartAddress); + + nZ80Bank0 = nBank; + } + + return; +} + +static void NeoZ80SetBank1(INT32 nBank) +{ + nBank &= 0x1F; + if (nBank != nZ80Bank1) { + UINT8* nStartAddress = NeoZ80ROMActive + (nBank << 13); + ZetMapArea(0xC000, 0xDFFF, 0, nStartAddress); + ZetMapArea(0xC000, 0xDFFF, 2, nStartAddress); + + nZ80Bank1 = nBank; + } + + return; +} + +static void NeoZ80SetBank2(INT32 nBank) +{ + nBank &= 0x3F; + if (nBank != nZ80Bank2) { + UINT8* nStartAddress = NeoZ80ROMActive + (nBank << 12); + ZetMapArea(0xE000, 0xEFFF, 0, nStartAddress); + ZetMapArea(0xE000, 0xEFFF, 2, nStartAddress); + + nZ80Bank2 = nBank; + } + + return; +} + +static void NeoZ80SetBank3(INT32 nBank) +{ + nBank &= 0x7F; + if (nBank != nZ80Bank3) { + UINT8* nStartAddress = NeoZ80ROMActive + (nBank << 11); + ZetMapArea(0xF000, 0xF7FF, 0, nStartAddress); + ZetMapArea(0xF000, 0xF7FF, 2, nStartAddress); + + nZ80Bank3 = nBank; + } + + return; +} + +static void NeoZ80MapROM(bool bMapBoardROM) +{ + if (nNeoSystemType & NEO_SYS_CART) { + if (bMapBoardROM && bZ80BIOS) { + // Bank in the Z80 boardROM + ZetMapArea(0x0000, 0x7FFF, 0, NeoZ80BIOS); + ZetMapArea(0x0000, 0x7FFF, 2, NeoZ80BIOS); + } else { + // Bank in the Z80 cartridge ROM + ZetMapArea(0x0000, 0x7FFF, 0, NeoZ80ROMActive); + ZetMapArea(0x0000, 0x7FFF, 2, NeoZ80ROMActive); + } + } +} + +static void MapVectorTable(bool bMapBoardROM) +{ + if (!bMapBoardROM && Neo68KROMActive) { + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x000000, 0x0003FF, SM_ROM); + } else { + SekMapMemory(NeoVectorActive, 0x000000, 0x0003FF, SM_ROM); + } +} + +inline static void MapPalette(INT32 nBank) +{ + if (nNeoPaletteBank != nBank) { + nNeoPaletteBank = nBank; + SekMapMemory(NeoPalSrc[nBank], 0x400000, 0x401FFF, SM_ROM); + + NeoSetPalette(); + } +} + +static void Bankswitch(UINT32 nBank) +{ + nBank = 0x100000 + ((nBank & 7) << 20); + if (nBank >= nCodeSize[nNeoActiveSlot]) { + nBank = 0x100000; + } + + if (nBank != nNeo68KROMBank) { +// bprintf(PRINT_NORMAL, "Bankswitched main ROM, new address is 0x%08X.\n", nBank); + nNeo68KROMBank = nBank; + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FFFFF, SM_ROM); + } +} + +void NeoMapBank() +{ + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FFFFF, SM_ROM); +} + +void NeoMap68KFix() +{ + if ((nNeoSystemType & NEO_SYS_CART) && (nCodeSize[nNeoActiveSlot] > 0x100000)) { + + SekMapMemory(Neo68KFix[nNeoActiveSlot] + 0x0400, 0x000400, 0x0FFFFF, SM_ROM); + + if (Neo68KROM[nNeoActiveSlot]) { + memcpy(NeoVector[nNeoActiveSlot] + 0x80, Neo68KFix[nNeoActiveSlot] + 0x80, 0x0380); + } + } + + MapVectorTable(b68KBoardROMBankedIn); +} + +void NeoUpdateVector() +{ + // Create copy of 68K with BIOS vector table + for (INT32 i = 0; i < MAX_SLOT; i++) { + if (NeoVector[i]) { + memcpy(NeoVector[i] + 0x00, Neo68KBIOS, 0x0080); + if (Neo68KROM[i]) { + memcpy(NeoVector[i] + 0x80, Neo68KFix[i] + 0x80, 0x0380); + } + } + } +} + +// ---------------------------------------------------------------------------- +// 68K bankswitch for most games without SMA/PVC protection + +void __fastcall neogeoWriteByteBankswitch(UINT32 sekAddress, UINT8 byteValue) +{ + if (sekAddress >= 0x2FFFF0) { + +// bprintf(PRINT_NORMAL, _T(" - Bankswitch: 0x%06X -> 0x%02X\n"), sekAddress, byteValue); + + Bankswitch(byteValue); + return; + } +} + +void __fastcall neogeoWriteWordBankswitch(UINT32 sekAddress, UINT16 wordValue) +{ + if (sekAddress >= 0x2FFFF0) { + +// bprintf(PRINT_NORMAL, _T(" - Bankswitch: 0x%06X -> 0x%04X\n"), sekAddress, wordValue); + + Bankswitch(wordValue); + return; + } +} + +// ---------------------------------------------------------------------------- +// CPU synchronisation + +static inline void neogeoSynchroniseZ80(INT32 nExtraCycles) +{ +#if defined Z80_SPEED_ADJUST + INT32 nCycles = SekTotalCycles() / 3 + nExtraCycles; +#else + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; +#endif + + if (nCycles <= ZetTotalCycles()) { + return; + } + + nCycles68KSync = nCycles - nExtraCycles; + + BurnTimerUpdate(nCycles); +} + +// Callbacks for the FM chip + +static void neogeoFMIRQHandler(INT32, INT32 nStatus) +{ +// bprintf(PRINT_NORMAL, _T(" YM2610 IRQ status: 0x%02X (%6i cycles)\n"), nStatus, ZetTotalCycles()); + + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 neogeoSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / nZ80Clockspeed; +} + +static double neogeoGetTime() +{ + return (double)ZetTotalCycles() / nZ80Clockspeed; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall neogeoReadByteGambling(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x280001: { + return 0xff - NeoInput[3]; + } + + case 0x2c0001: { + return 0x03; + } + } + +// bprintf(PRINT_NORMAL, _T("Read Byte 0x%08X.\n"), sekAddress); + + return 0xff; +} + +UINT16 __fastcall neogeoReadWordGambling(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x280000: { + return 0xff - NeoInput[3]; + } + + case 0x2c0000: { + return 0x0003; + } + } + +// bprintf(PRINT_NORMAL, _T("Read Word 0x%08X.\n"), sekAddress); + + return 0xffff; +} + +UINT8 __fastcall vliner_timing(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x320000: { + INT32 nReply = nSoundReply; + +#if 1 && defined USE_SPEEDHACKS + // nSoundStatus: &1 = sound latch read, &2 = response written + if (nSoundStatus != 3) { + neogeoSynchroniseZ80(0x0100); + } +#endif + + if (nSoundStatus & 1) { +// bprintf(PRINT_NORMAL, _T(" - Sound reply read (0x%02X).\n"), nSoundReply); + + return nReply; + } else { +// bprintf(PRINT_NORMAL, _T(" - Sound reply read while sound pending (0x%02X).\n"), nSoundReply); + + return nReply & 0x7F; + } + } + + case 0x320001: { +// if (!bAESBIOS) { + if (nBIOS != 10 && nBIOS != 11 && nBIOS != 12) { + UINT8 nuPD4990AOutput = uPD4990ARead(SekTotalCycles() - nuPD4990ATicks); + nuPD4990ATicks = SekTotalCycles(); + return 0x3F | (nuPD4990AOutput << 6); + } + + return (0x3f) & 0xE7; + } + } + +// bprintf(PRINT_NORMAL, _T("Read Byte 0x%08X.\n"), sekAddress); + return 0xff; +} + +// ----------------------------------------------------------------------------- + +static void NeoMapActiveCartridge() +{ + if (!(nNeoSystemType & NEO_SYS_CART)) { + nNeoActiveSlot = 0; + return; + } + + neogeoSynchroniseZ80(0); + + if (NeoCallbackActive && NeoCallbackActive->pRemoveHandlers) { + NeoCallbackActive->pRemoveHandlers(); + } + + NeoVectorActive = NeoVector[nNeoActiveSlot]; + + if (Neo68KROM[nNeoActiveSlot] == NULL) { + + // If an empty slot is selected, only the vector table is valid + + Neo68KROMActive = NULL; + + SekMapHandler(0, 0x000000, 0x0FFFFF, SM_RAM); + SekMapHandler(0, 0x200000, 0x2FFFFF, SM_RAM); + + b68KBoardROMBankedIn = true; + MapVectorTable(b68KBoardROMBankedIn); + + NeoCallbackActive = NULL; + + ZetSetBUSREQLine(1); + + NeoSetSpriteSlot(nNeoActiveSlot); + NeoSetTextSlot(nNeoActiveSlot); + + return; + } + + Neo68KROMActive = Neo68KROM[nNeoActiveSlot]; + NeoZ80ROMActive = NeoZ80ROM[nNeoActiveSlot]; + NeoCallbackActive = &NeoCallback[nNeoActiveSlot]; + + SekSetReadWordHandler(6, NULL); + SekSetWriteWordHandler(6, NULL); + SekSetReadByteHandler(6, NULL); + SekSetWriteByteHandler(6, NULL); + SekSetReadWordHandler(7, NULL); + SekSetWriteWordHandler(7, NULL); + SekSetReadByteHandler(7, NULL); + SekSetWriteByteHandler(7, NULL); + + SekMapHandler(0, 0x000000, 0x0FFFFF, SM_WRITE); + + if (nCodeSize[nNeoActiveSlot] <= 0x080000) { + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x000000, 0x07FFFF, SM_ROM); + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x080000, 0x0FFFFF, SM_ROM); + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x200000, 0x27FFFF, SM_ROM); + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x280000, 0x2FFFFF, SM_ROM); + } + + if (nCodeSize[nNeoActiveSlot] <= 0x100000) { + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x000000, 0x0FFFFF, SM_ROM); + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x200000, 0x2FFFFF, SM_ROM); + } + + if (nCodeSize[nNeoActiveSlot] > 0x100000) { + SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x000000, 0x0FFFFF, SM_ROM); + + SekMapHandler(4, 0x200000, 0x2FFFFF, SM_WRITE); + + SekSetWriteWordHandler(4, neogeoWriteWordBankswitch); + SekSetWriteByteHandler(4, neogeoWriteByteBankswitch); + } + + if (NeoCallbackActive->pInstallHandlers) { + NeoCallbackActive->pInstallHandlers(); + } + + if (nCodeSize[nNeoActiveSlot] > 0x100000) { + nNeo68KROMBank = 0x100000; + + if (NeoCallbackActive->pBankswitch) { + NeoCallbackActive->pBankswitch(); + } else { + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) != HARDWARE_SNK_GAMBLING) { + NeoMapBank(); + } + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) == HARDWARE_SNK_GAMBLING) { + SekMapMemory(NeoNVRAM2, 0x200000, 0x201FFF, SM_RAM); // 68K RAM + + SekMapHandler(6, 0x202000, 0x2FFFFF, SM_READ); + SekSetReadByteHandler(6, neogeoReadByteGambling); + SekSetReadWordHandler(6, neogeoReadWordGambling); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "vliner") || !strcmp(BurnDrvGetTextA(DRV_NAME), "vlinero")) { + SekMapHandler(7, 0x320000, 0x320001, SM_READ); + SekSetReadByteHandler(7, vliner_timing); + } + } + + if (NeoZ80ROMActive) { + ZetSetBUSREQLine(0); + + nZ80Bank0 = nZ80Bank1 = nZ80Bank2 = nZ80Bank3 = -1; + NeoZ80SetBank0(0x02); + NeoZ80SetBank1(0x06); + NeoZ80SetBank2(0x0E); + NeoZ80SetBank3(0x1E); + } else { + ZetSetBUSREQLine(1); + } + + MapVectorTable(b68KBoardROMBankedIn); + NeoZ80MapROM(bZ80BoardROMBankedIn); + + NeoSetSpriteSlot(nNeoActiveSlot); + NeoSetTextSlot(nNeoActiveSlot); + + // the text rendering code will get confused if we don't do this + memset(NeoGraphicsRAM + 0xEA00, 0, 0x0200); + + BurnYM2610MapADPCMROM(YM2610ADPCMAROM[nNeoActiveSlot], nYM2610ADPCMASize[nNeoActiveSlot], YM2610ADPCMBROM[nNeoActiveSlot], nYM2610ADPCMBSize[nNeoActiveSlot]); + + return; +} + +// ----------------------------------------------------------------------------- +// Savestate support + +INT32 NeoScan(INT32 nAction, INT32* pnMin) +{ + INT32 nOldBIOS = nBIOS; + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029713; + } + + // Make sure we have the correct value for nBIOS + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nBIOS); + // Update the system type immediately + NeoSetSystemType(); + } + + if (nAction & ACB_MEMORY_ROM) { + + if (nNeoSystemType & NEO_SYS_CART) { + ba.Data = Neo68KBIOS; + ba.nLen = 0x80000;//(nNeoSystemType & NEO_SYS_PCB) ? 0x00080000 : 0x00020000; + ba.nAddress = 0; + ba.szName = "68K BIOS"; + BurnAcb(&ba); + + ba.Data = Neo68KROMActive; + ba.nLen = nCodeSize[nNeoActiveSlot]; + ba.nAddress = 0; + ba.szName = "68K ROM"; + BurnAcb(&ba); + + ba.Data = NeoZ80BIOS; + ba.nLen = 0x00020000; + ba.nAddress = 0; + ba.szName = "Z80 BIOS"; + BurnAcb(&ba); + + ba.Data = NeoZ80ROMActive; + ba.nLen = 0x00080000; + ba.nAddress = 0; + ba.szName = "Z80 ROM"; + BurnAcb(&ba); + + ba.Data = YM2610ADPCMAROM[nNeoActiveSlot]; + ba.nLen = nYM2610ADPCMASize[nNeoActiveSlot]; + ba.nAddress = 0; + ba.szName = "ADPCM ROM"; + BurnAcb(&ba); + + ba.Data = YM2610ADPCMBROM[nNeoActiveSlot]; + ba.nLen = nYM2610ADPCMBSize[nNeoActiveSlot]; + ba.nAddress = 0; + ba.szName = "Delta-T ROM"; + BurnAcb(&ba); + } else { + ba.Data = Neo68KBIOS; + ba.nLen = 0x00080000; + ba.nAddress = 0; + ba.szName = "68K BIOS"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_MEMCARD) { + if ((nNeoSystemType & NEO_SYS_CART) && !(nNeoSystemType & NEO_SYS_PCB)) { // Scan memory card + + if (pnMin && (nAction & ACB_TYPEMASK) == ACB_MEMCARD) { // Return minimum compatible version + *pnMin = 0x029713; + } + + ba.Data = NeoMemoryCard; + ba.nLen = 0x020000; + ba.nAddress = 0; + ba.szName = "Memory card"; + + if ((nAction & ACB_TYPEMASK) == ACB_MEMCARD) { + if (nAction & ACB_WRITE) { + bMemoryCardInserted = true; + } + if (nAction & ACB_READ) { + bMemoryCardInserted = false; + + // If a card is inserted, determine the size + if (*((UINT16*)NeoMemoryCard) != 0x8000) { + INT32 nSize = (NeoMemoryCard[21] << 8) | NeoMemoryCard[23]; + if (nSize >= 0x1000) { + ba.nLen = nSize; + } + } + } + } + + BurnAcb(&ba); + } + } + + if ((nNeoSystemType & NEO_SYS_CD) && (nAction & ACB_NVRAM)) { // Scan non-volatile memory (built-in memory card) + + if (pnMin && (nAction & ACB_TYPEMASK) == ACB_NVRAM) { // Return minimum compatible version + *pnMin = 0x029713; + } + + ba.Data = NeoMemoryCard; + ba.nLen = 0x004000; + ba.nAddress = 0; + ba.szName = "Memory card"; + BurnAcb(&ba); + } + + if ((nNeoSystemType & NEO_SYS_MVS) && (nAction & ACB_NVRAM)) { // Scan non-volatile memory + + if (pnMin && (nAction & ACB_TYPEMASK) == ACB_NVRAM) { // Return minimum compatible version + *pnMin = 0x029713; + } + + ba.Data = NeoNVRAM; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "NVRAM"; + BurnAcb(&ba); + } + + if (((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) == HARDWARE_SNK_GAMBLING) && (nAction & ACB_NVRAM)) { + ba.Data = NeoNVRAM2; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Extra NVRAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { // Scan RAM + + if (nNeoSystemType & NEO_SYS_CART) { + ba.Data = Neo68KRAM; + ba.nLen = 0x00010000; + ba.nAddress = 0; + ba.szName = "68K RAM"; + BurnAcb(&ba); + + ba.Data = NeoZ80RAM; + ba.nLen = 0x00000800; + ba.nAddress = 0; + ba.szName = "Z80 RAM"; + BurnAcb(&ba); + } + + if (nNeoSystemType & NEO_SYS_CD) { + ba.Data = Neo68KROMActive; + ba.nLen = nCodeSize[0]; + ba.nAddress = 0; + ba.szName = "68K program RAM"; + BurnAcb(&ba); + + ba.Data = NeoZ80ROMActive; + ba.nLen = 0x00080000; + ba.nAddress = 0; + ba.szName = "Z80 program RAM"; + BurnAcb(&ba); + } + + ba.Data = NeoPalSrc[0]; + ba.nLen = 0x000002000; + ba.nAddress = 0; + ba.szName = "Palette 0"; + BurnAcb(&ba); + ba.Data = NeoPalSrc[1]; + ba.nLen = 0x000002000; + ba.nAddress = 0; + ba.szName = "Palette 1"; + BurnAcb(&ba); + + ba.Data = NeoGraphicsRAM; + ba.nLen = 0x00020000; + ba.nAddress = 0; + ba.szName = "Graphics RAM"; + BurnAcb(&ba); + + if (nNeoSystemType & NEO_SYS_CD) { + ba.Data = NeoSpriteRAM; + ba.nLen = nSpriteSize[0]; + ba.nAddress = 0; + ba.szName = "Sprite layer tile RAM"; + BurnAcb(&ba); + + ba.Data = NeoTextRAM; + ba.nLen = nNeoTextROMSize[0]; + ba.nAddress = 0; + ba.szName = "Text layer tile RAM"; + BurnAcb(&ba); + + ba.Data = YM2610ADPCMBROM[0]; + ba.nLen = nYM2610ADPCMBSize[0]; + ba.nAddress = 0; + ba.szName = "ADPCM sample RAM"; + BurnAcb(&ba); + } + + if (NeoCallbackActive && NeoCallbackActive->pScan) { + NeoCallbackActive->pScan(nAction, pnMin); + } + } + + if (nAction & ACB_DRIVER_DATA) { // Scan driver data + + SekScan(nAction); // Scan 68000 state + ZetScan(nAction); // Scan Z80 state + + BurnYM2610Scan(nAction, pnMin); + + if (nNeoSystemType & NEO_SYS_MVS) { + uPD4990AScan(nAction, pnMin); + } + + if (NeoCallbackActive && NeoCallbackActive->pScan) { + NeoCallbackActive->pScan(nAction, pnMin); + } + + SCAN_VAR(nCyclesExtra); + + SCAN_VAR(bNeoEnableGraphics); + SCAN_VAR(nIRQAcknowledge); + + SCAN_VAR(nIRQControl); SCAN_VAR(nIRQOffset); SCAN_VAR(nIRQCycles); + SCAN_VAR(bSRAMWritable); + +#if defined EMULATE_WATCHDOG + SCAN_VAR(nNeoWatchdog); +#endif + + SCAN_VAR(b68KBoardROMBankedIn); + if (nNeoSystemType & NEO_SYS_CART) { + SCAN_VAR(bBIOSTextROMEnabled); + SCAN_VAR(nZ80Bank0); SCAN_VAR(nZ80Bank1); SCAN_VAR(nZ80Bank2); SCAN_VAR(nZ80Bank3); + SCAN_VAR(nNeo68KROMBank); + } + + SCAN_OFF(NeoGraphicsRAMBank, NeoGraphicsRAM, nAction); + + SCAN_VAR(nNeoSpriteFrame); SCAN_VAR(nSpriteFrameSpeed); SCAN_VAR(nSpriteFrameTimer); + + SCAN_VAR(nNeoPaletteBank); + + SCAN_VAR(nSoundLatch); + SCAN_VAR(nSoundReply); + SCAN_VAR(nSoundStatus); + +#if 1 && defined USE_SPEEDHACKS + SCAN_VAR(nSoundPrevReply); +#endif + + SCAN_VAR(nInputSelect); + + SCAN_OFF(NeoInputBank, NeoInput, nAction); + + SCAN_VAR(nAnalogAxis); + + SCAN_VAR(nuPD4990ATicks); + + SCAN_OFF(Neo68KFix[nNeoActiveSlot], Neo68KROM[nNeoActiveSlot], nAction); + + if (nAction & ACB_WRITE) { + INT32 nNewBIOS = nBIOS; + INT32 nBank; + + SekOpen(0); + NeoMap68KFix(); + SekClose(); + + if (nNeoSystemType & NEO_SYS_CART) { + ZetOpen(0); + NeoZ80MapROM(bZ80BoardROMBankedIn); + + nBank = nZ80Bank0; nZ80Bank0 = -1; + NeoZ80SetBank0(nBank); + nBank = nZ80Bank1; nZ80Bank1 = -1; + NeoZ80SetBank1(nBank); + nBank = nZ80Bank2; nZ80Bank2 = -1; + NeoZ80SetBank2(nBank); + nBank = nZ80Bank3; nZ80Bank3 = -1; + NeoZ80SetBank3(nBank); + ZetClose(); + + if (NeoCallbackActive && NeoCallbackActive->pBankswitch) { + NeoCallbackActive->pBankswitch(); + } else { + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) != HARDWARE_SNK_GAMBLING) { + SekOpen(0); + SekMapMemory(Neo68KROMActive + nNeo68KROMBank, 0x200000, 0x2FFFFF, SM_ROM); + SekClose(); + } + } + } + + nBank = nNeoPaletteBank; nNeoPaletteBank = -1; + SekOpen(0); + MapPalette(nBank); + SekClose(); + + NeoRecalcPalette = 1; + + if (nNeoSystemType & NEO_SYS_CART) { + nBIOS = nOldBIOS; + NeoLoad68KBIOS(nNewBIOS); + + NeoSetSystemType(); + } + + nPrevBurnCPUSpeedAdjust = -1; + + SCAN_VAR(nLEDLatch); + SCAN_VAR(nLED[3]); + +// BurnGameFeedback(sizeof(nLED), nLED); + } + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// Z80 handlers + +UINT8 __fastcall neogeoZ80In(UINT16 nAddress) +{ + switch (nAddress & 0xFF) { + case 0x00: // Read sound command +// bprintf(PRINT_NORMAL, _T(" - Sound command received (0x%02X).\n"), nSoundLatch); + nSoundStatus = 1; +#if 1 && defined USE_SPEEDHACKS + nSoundPrevReply = -1; +#endif + return nSoundLatch; + + case 0x04: + return BurnYM2610Read(0); + case 0x05: + return BurnYM2610Read(1); + case 0x06: + return BurnYM2610Read(2); + + case 0x08: +// bprintf(PRINT_NORMAL, " - Z80 bank 3 -> 0x%02X\n", nAddress >> 8); + NeoZ80SetBank3(nAddress >> 8); + break; + case 0x09: +// bprintf(PRINT_NORMAL, " - Z80 bank 2 -> 0x%02X\n", nAddress >> 8); + NeoZ80SetBank2(nAddress >> 8); + break; + case 0x0A: +// bprintf(PRINT_NORMAL, " - Z80 bank 1 -> 0x%02X\n", nAddress >> 8); + NeoZ80SetBank1(nAddress >> 8); + break; + case 0x0B: +// bprintf(PRINT_NORMAL, " - Z80 bank 0 -> 0x%02X\n", nAddress >> 8); + NeoZ80SetBank0(nAddress >> 8); + break; + +// default: { +// bprintf(PRINT_NORMAL, _T)" - Z80 read port 0x%04X.\n"), nAddress); +// } + } + + return 0; +} + +UINT8 __fastcall neogeoZ80InCD(UINT16 nAddress) +{ + switch (nAddress & 0xFF) { + case 0x00: // Read sound command +// bprintf(PRINT_NORMAL, _T(" - Sound command received (0x%02X).\n"), nSoundLatch); + nSoundStatus = 1; +#if 1 && defined USE_SPEEDHACKS + nSoundPrevReply = -1; +#endif + return nSoundLatch; + + case 0x04: + return BurnYM2610Read(0); + case 0x05: + return BurnYM2610Read(1); + case 0x06: + return BurnYM2610Read(2); + + // banskswitch on MVS/AES + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + break; + + default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 read port 0x%04X.\n"), nAddress); + } + } + + return 0; +} + +void __fastcall neogeoZ80Out(UINT16 nAddress, UINT8 nValue) +{ + switch (nAddress & 0x0FF) { + case 0x00: +// bprintf(PRINT_NORMAL, _T(" - Z80 port 0x00 -> 0x%02X.\n"), nValue); + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: + BurnYM2610Write(nAddress & 3, nValue); + break; + + case 0x0C: // Write reply to sound commands +// bprintf(PRINT_NORMAL, _T(" - Sound reply sent (0x%02X).\n"), nValue); + nSoundReply = nValue; + +#if 1 && defined USE_SPEEDHACKS + if (nSoundPrevReply != nValue) { + nSoundPrevReply = nValue; + + // s1945p replies a 0x00, then an 0xFF; + // the 68K loops until it has read both + if (nSoundReply == 0) { + nSoundStatus &= ~2; + } else { + nSoundStatus |= 2; + } + } else { + nSoundStatus |= 2; + } + + if (ZetTotalCycles() > nCycles68KSync) { + +// bprintf(PRINT_NORMAL, _T(" %i\n"), ZetTotalCycles()); + BurnTimerUpdateEnd(); +// bprintf(PRINT_NORMAL, _T(" %i - %i\n"), ZetTotalCycles(), nCycles68KSync); + } +#endif + + break; + + case 0x80: + bprintf(PRINT_ERROR, _T(" - Z80 port 0x%04X -> 0x%02X.\n"), nAddress, nValue); + break; + + default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 port 0x%04X -> 0x%02X.\n"), nAddress, nValue); + } + } +} + +// ----------------------------------------------------------------------------- +// 68K handlers + +INT32 __fastcall NeoCDIRQCallback(INT32 /* nIRQ */) +{ +// bprintf(PRINT_NORMAL, _T(" - IRQ Callback %i %2X.\n"), nIRQ, nNeoCDIRQVector); + if (nNeoCDIRQVectorAck) { + nNeoCDIRQVectorAck = 0; + return nNeoCDIRQVector; + } + return M68K_INT_ACK_AUTOVECTOR; +} + +static inline INT32 NeoConvertIRQPosition(INT32 nOffset) +{ + UINT64 nNewPosition = ((UINT64)nOffset * nBurnCPUSpeedAdjust) >> 7; + + return (nNewPosition < NO_IRQ_PENDING) ? nNewPosition : NO_IRQ_PENDING; +} + +static inline void NeoIRQUpdate(UINT16 wordValue) +{ + nIRQAcknowledge |= (wordValue & 7); + +// bprintf(PRINT_NORMAL, _T(" - IRQ Ack -> %02X (at line %3i).\n"), nIRQAcknowledge, SekCurrentScanline()); + + if ((nIRQAcknowledge & 7) == 7) { + SekSetIRQLine(7, SEK_IRQSTATUS_NONE); + } else { + if ((nIRQAcknowledge & 1) == 0) { + SekSetIRQLine(3, SEK_IRQSTATUS_ACK); + } + if ((nIRQAcknowledge & 2) == 0) { + SekSetIRQLine(nScanlineIRQ, SEK_IRQSTATUS_ACK); + } + if ((nIRQAcknowledge & 4) == 0) { + SekSetIRQLine(nVBLankIRQ, SEK_IRQSTATUS_ACK); + } + } +} + +static inline void NeoCDIRQUpdate(UINT8 byteValue) +{ + nIRQAcknowledge |= (byteValue & 0x38); + +// bprintf(PRINT_NORMAL, _T(" - IRQ Ack -> %02X (CD, at line %3i).\n"), nIRQAcknowledge, SekCurrentScanline()); + + if ((nIRQAcknowledge & 0x3F) == 0x3F) { + SekSetIRQLine(7, SEK_IRQSTATUS_NONE); + } else { + if ((nIRQAcknowledge & 0x07) != 7) { + NeoIRQUpdate(0); + return; + } + if ((nIRQAcknowledge & 0x08) == 0) { + nNeoCDIRQVector = 0x17; + nNeoCDIRQVectorAck = 1; + SekSetIRQLine(4, SEK_IRQSTATUS_ACK /*| SEK_IRQSTATUS_CALLBACK*/); + return; + } + if ((nIRQAcknowledge & 0x10) == 0) { + nNeoCDIRQVector = 0x16; + nNeoCDIRQVectorAck = 1; + SekSetIRQLine(4, SEK_IRQSTATUS_ACK /*| SEK_IRQSTATUS_CALLBACK*/); + return; + } + if ((nIRQAcknowledge & 0x20) == 0) { + nNeoCDIRQVector = 0x15; + nNeoCDIRQVectorAck = 1; + SekSetIRQLine(4, SEK_IRQSTATUS_ACK /*| SEK_IRQSTATUS_CALLBACK*/); + return; + } + } +} + +static inline void SendSoundCommand(const UINT8 nCommand) +{ +// bprintf(PRINT_NORMAL, _T(" - Sound command sent (0x%02X).\n"), nCommand); + + neogeoSynchroniseZ80(0); + + nSoundStatus &= ~1; + nSoundLatch = nCommand; + + ZetNmi(); + +#if 1 && defined USE_SPEEDHACKS + neogeoSynchroniseZ80(0x0200); +#endif +} + +static UINT8 ReadInput1(INT32 nOffset) +{ + switch (nOffset) { + case 0x00: +// bprintf(PRINT_NORMAL, _T(" -- bank %d inputP0[0x%02X] read (%i).\n"), 0, nInputSelect, SekTotalCycles()); + return ~NeoInputBank[nJoyport0[nInputSelect & 0x07]]; + + case 0x01: +// bprintf(PRINT_NORMAL, _T(" - 0x%06X read (byte).\n"), sekAddress); + if (nNeoSystemType & NEO_SYS_MVS) { + return ~NeoInputBank[4]; + } + return ~0; + + case 0x81: +// bprintf(PRINT_NORMAL, _T(" - 0x%06X read (byte).\n"), sekAddress); + if (nNeoSystemType & NEO_SYS_MVS) { + return ~NeoInputBank[5]; + } + return ~0; + } + + return ~0; +} + +static UINT8 ReadInput2(INT32 nOffset) +{ + if ((nOffset & 1) == 0) { +// bprintf(PRINT_NORMAL, _T(" -- bank %d inputP1[0x%02X] read.\n"), 0, nInputSelect); + return ~NeoInputBank[nJoyport1[(nInputSelect >> 3) & 0x07]]; + } + + return ~0; +} + +static UINT8 ReadInput3(INT32 nOffset) +{ + if ((nOffset & 1) == 0) { +// bprintf(PRINT_NORMAL, " -- input 2 read.\n"); + return ~NeoInputBank[2]; + } + + return ~0; +} + +UINT8 __fastcall neogeoReadByte(UINT32 sekAddress) +{ + switch (sekAddress & 0xFE0000) { + case 0x300000: + return ReadInput1(sekAddress & 0xFF); + + case 0x320000: { + if ((sekAddress & 1) == 0) { + INT32 nReply = nSoundReply; + +#if 1 && defined USE_SPEEDHACKS + // nSoundStatus: &1 = sound latch read, &2 = response written + if (nSoundStatus != 3) { + neogeoSynchroniseZ80(0x0100); + } +#else + neogeoSynchroniseZ80(0); +#endif + + if ((nSoundStatus & 1) == 0) { +// bprintf(PRINT_NORMAL, _T(" - Sound reply read while sound pending (0x%02X).\n"), nSoundReply); + + return nReply & 0x7F; + } + +// bprintf(PRINT_NORMAL, _T(" - Sound reply read (0x%02X).\n"), nSoundReply); + return nReply; + } + + if (nNeoSystemType & NEO_SYS_MVS) { + UINT8 nuPD4990AOutput = uPD4990ARead(SekTotalCycles() - nuPD4990ATicks); + nuPD4990ATicks = SekTotalCycles(); + return (~NeoInputBank[3] & 0x3F) | (nuPD4990AOutput << 6); + } + + return (~NeoInputBank[3] & 0x7F) & 0xE7; + } + + case 0x340000: + return ReadInput2(sekAddress & 0xFF); + + case 0x380000: + return ReadInput3(sekAddress & 0xFF); + + default: + bprintf(PRINT_NORMAL, _T(" - 0x%08X read (byte, PC: %08X)\n"), sekAddress, SekGetPC(-1)); + } + + return ~0; +} + +UINT16 __fastcall neogeoReadWord(UINT32 sekAddress) +{ + switch (sekAddress & 0xFE0000) { + case 0x300000: + return (ReadInput1(sekAddress & 0xFE) << 8) | ReadInput1((sekAddress & 0xFE) | 1); + + case 0x320000: + SEK_DEF_READ_WORD(0, sekAddress); + + case 0x340000: + return (ReadInput2(sekAddress & 0xFE) << 8) | ReadInput2((sekAddress & 0xFE) | 1); + + case 0x380000: + return (ReadInput3(sekAddress & 0xFE) << 8) | ReadInput3((sekAddress & 0xFE) | 1); + + default: + bprintf(PRINT_NORMAL, _T(" - 0x%08X read (word, PC: %08X)\n"), sekAddress, SekGetPC(-1)); + } + + return ~0; +} + +static void WriteIO1(INT32 nOffset, UINT8 byteValue) +{ + switch (nOffset) { + case 0x01: // Select the input returned at 0x300000 +// bprintf(PRINT_NORMAL, _T(" - InputP0/P1 0x%02X selected (%i).\n"), byteValue, SekTotalCycles()); + nInputSelect = byteValue; + break; + + case 0x21: // Select the active cartridge slot +// bprintf(PRINT_NORMAL, _T(" - Cartridge slot 0x%02X activated.\n"), byteValue); + nNeoActiveSlot = byteValue; + if (nNeoActiveSlot >= nNeoNumSlots) { + nNeoActiveSlot = 0; + } + + NeoMapActiveCartridge(); + break; + + case 0x31: // Send latched output to LEDs (bits 5/4 - numeric displays, bit 3 - marquee lights, one per slot) +// bprintf(PRINT_NORMAL, _T(" - 0x%06X -> 0x%02X.\n"), sekAddress, byteValue); +// if (byteValue != 255) { +// bprintf(PRINT_NORMAL, _T(" - LED %02X -> %02X\n"), ~byteValue & 255, nLEDLatch & 255); +// } + +/* if ((byteValue & 0x20) == 0) { + nLED[0] = nLEDLatch; + } + if ((byteValue & 0x10) == 0) { + nLED[1] = nLEDLatch; + } + if ((byteValue & 0x08) == 0) { + nLED[2] = nLEDLatch; + } + + BurnGameFeedback(sizeof(nLED), nLED);*/ + + break; + + case 0x41: // Latch LED output + // for numeric displays - digits displayed = ~bytevalue + // for start buttons - highlighted marquee = ~bytevalue +// bprintf(PRINT_NORMAL, _T(" - LED output -> 0x%02X.\n"), byteValue); + nLEDLatch = ~byteValue; + break; + + case 0x51: // Send command to RTC +// bprintf(PRINT_NORMAL, _T(" - RTC -> 0x%02X.\n"), byteValue); + if (nNeoSystemType & NEO_SYS_MVS) { + uPD4990AWrite(byteValue & 2, byteValue & 4, byteValue & 1); + } + break; + + case 0x61: // Coin lockout chute 1 & input bank select +// bprintf(PRINT_NORMAL, _T(" - %sInput bank 0 selected (0x%02X).\n"), byteValue ? _T("Chute 1 coin lockout -> High / ") : _T(""), byteValue); + NeoInputBank = NeoInput + 0; + break; + case 0x63: // Coin lockout chute 2 +// bprintf(PRINT_NORMAL, _T(" - Chute 2 coin lockout -> High (0x%02X).\n"), byteValue); + break; + + case 0x65: // Coin counter chute 1 -> High + break; +// bprintf(PRINT_NORMAL, _T(" - Chute 1 coin counter -> High (0x%02X).\n"), byteValue); + case 0x67: // Coin counter chute 2 -> High +// bprintf(PRINT_NORMAL, _T(" - Chute 2 coin counter -> High (0x%02X).\n"), byteValue); + break; + + case 0xD1: // Send command to RTC +// bprintf(PRINT_NORMAL, _T(" - RTC -> 0x%02X.\n"), byteValue); + if (nNeoSystemType & NEO_SYS_MVS) { + uPD4990AWrite(byteValue & 2, byteValue & 4, byteValue & 1); + } + break; + + case 0xE1: +// bprintf(PRINT_NORMAL, _T(" - Chute 2 coin lockout -> Low / Input bank 1 selected (0x%02X).\n"), byteValue); + NeoInputBank = NeoInput + 8; + break; + case 0xE3: +// bprintf(PRINT_NORMAL, _T(" - Chute 2 coin lockout -> Low (0x%02X).\n"), byteValue); + break; + + case 0xE5: // Coin counter chute 1 -> Low +// bprintf(PRINT_NORMAL, _T(" - Chute 1 coin counter -> Low (0x%02X).\n"), byteValue); + break; + case 0xE7: // Coin counter chute 2 -> Low +// bprintf(PRINT_NORMAL, _T(" - Chute 2 coin counter -> Low (0x%02X).\n"), byteValue); + break; + } + + return; +} + +static void WriteIO2(INT32 nOffset, UINT8 /*byteValue*/) +{ + switch (nOffset) { + case 0x01: // Enable display + if (nNeoSystemType & NEO_SYS_CART) { + bNeoEnableGraphics = true; +// bprintf(PRINT_NORMAL, _T(" - Display enabled (0x%02X, at scanline %i).\n"), byteValue, SekCurrentScanline()); + break; + } + + case 0x03: // Select BIOS vector table + if (nNeoSystemType & NEO_SYS_CART) { + if (!b68KBoardROMBankedIn) { + MapVectorTable(true); + b68KBoardROMBankedIn = true; + } +// bprintf(PRINT_NORMAL, _T(" - BIOS vector table banked in (0x%02X).\n"), byteValue); + } + break; + + case 0x0B: // Select BIOS text ROM +// bprintf(PRINT_NORMAL, _T(" - BIOS text/Z80 ROM banked in (0x%02X).\n"), byteValue); + + bBIOSTextROMEnabled = !(nNeoSystemType & (NEO_SYS_PCB | NEO_SYS_AES)); + + if (bZ80BIOS) { + if (!bZ80BoardROMBankedIn) { + bZ80BoardROMBankedIn = true; + NeoZ80MapROM(true); + } + +#if defined Z80_RESET_ON_BANKSWITCH + nSoundStatus |= 1; + ZetReset(); +#endif + } + + break; + + case 0x0D: // Write-protect SRAM + bSRAMWritable = false; +// bprintf(PRINT_NORMAL, _T(" - SRAM write-protected (0x%02X).\n"), byteValue); + break; + + case 0x0F: // Select palette bank 1 +// bprintf(PRINT_NORMAL, _T(" - Palette 1 banked in (0x%02X).\n"), byteValue); + MapPalette(1); + break; + + case 0x11: // Disable display + if (nNeoSystemType & NEO_SYS_CART) { + bNeoEnableGraphics = false; +// bprintf(PRINT_NORMAL, _T(" - Display disabled (0x%02X, at scanline %i).\n"), byteValue, SekCurrentScanline()); + break; + } + + case 0x13: // Select game vector table + if (nNeoSystemType & NEO_SYS_CART) { + if (b68KBoardROMBankedIn) { + MapVectorTable(false); + b68KBoardROMBankedIn = false; + } +// bprintf(PRINT_NORMAL, _T(" - ROM vector table banked in (0x%02X).\n"), byteValue); + } + break; + + case 0x1B: // Select game text ROM +// bprintf(PRINT_NORMAL, _T(" - Cartridge text/Z80 ROM banked in (0x%02X).\n"), byteValue); + + bBIOSTextROMEnabled = false; + + if (bZ80BIOS) { + if (bZ80BoardROMBankedIn) { + bZ80BoardROMBankedIn = false; + NeoZ80MapROM(false); + } + +#if defined Z80_RESET_ON_BANKSWITCH + nSoundStatus |= 1; + ZetReset(); +#endif + } + + break; + + case 0x1D: // Write-enable SRAM + bSRAMWritable = true; +// bprintf(PRINT_NORMAL, _T(" - SRAM writable (0x%02X).\n"), byteValue); + break; + + case 0x1F: // Select palette bank 0 +// bprintf(PRINT_NORMAL, _T(" - Palette 0 banked in (0x%02X).\n"), byteValue); + MapPalette(0); + break; + } + + return; +} + +void __fastcall neogeoWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress & 0xFF0000) { + case 0x300000: + if ((sekAddress & 1) == 1) { +// bprintf(PRINT_NORMAL, " - Watchdog timer reset (%02X, at scanline %i)\n", byteValue, SekCurrentScanline()); + +#if defined EMULATE_WATCHDOG + nNeoWatchdog = -SekTotalCycles(); +#endif + + } + return; + + case 0x320000: + if ((sekAddress & 1) == 0) { + SendSoundCommand(byteValue); + } + return; + + case 0x380000: + WriteIO1(sekAddress & 0xFF, byteValue); + return; + + case 0x3A0000: + WriteIO2(sekAddress & 0x1F, byteValue); + return; + } + +// bprintf(PRINT_NORMAL, _T(" - Attempt to write byte 0x%06X -> 0x%02X\n"), sekAddress, byteValue); + + return; +} + +void __fastcall neogeoWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ +// neogeoWriteByte(sekAddress | 1, wordValue); + + SEK_DEF_WRITE_WORD(0, sekAddress, wordValue); + +// bprintf(PRINT_NORMAL, _T(" - Attempt to write word 0x%06X -> 0x%04X\n"), sekAddress, wordValue); +} + +// ---------------------------------------------------------------------------- +// Video controller reads + +UINT16 __fastcall neogeoReadWordVideo(UINT32 sekAddress) +{ + switch (sekAddress & 6) { + case 0x00: + case 0x02: +// bprintf(PRINT_NORMAL, " - Graphics RAM read (Bank %i, address 0x%04X).\n", NeoGraphicsRAMPointer > 0xFFFF ? 1 : 0, NeoGraphicsRAMPointer & 0xFFFF); + return *((UINT16*)(NeoGraphicsRAMBank + NeoGraphicsRAMPointer)); + + case 0x04: +// bprintf(PRINT_NORMAL, " - Graphics RAM modulo read.\n"); + return (UINT16)(nNeoGraphicsModulo >> 1); + + case 0x06: // Display status +// bprintf(PRINT_NORMAL, " - Display status read, line: %3i, anim: %i\n", SekCurrentScanline(), nNeoSpriteFrame); + +#if 1 && !defined USE_SPEEDHACKS + bForcePartialRender |= bForceUpdateOnStatusRead; +#endif + + return ((SekCurrentScanline() + nScanlineOffset) << 7) | 0 | (nNeoSpriteFrame & 7); + } + + return 0; +} + +UINT8 __fastcall neogeoReadByteVideo(UINT32 sekAddress) +{ + if (sekAddress & 1) { + return 0x0FF; + } else { + return neogeoReadWordVideo(sekAddress) >> 8; + } +} + +void __fastcall neogeoWriteWordVideo(UINT32 sekAddress, UINT16 wordValue) +{ +// if (sekAddress >= 0x3C0010) +// bprintf(PRINT_NORMAL, _T(" - Attempt to write word 0x%06X -> 0x%04X\n"), sekAddress, wordValue); + + switch (sekAddress & 14) { + case 0x00: { + NeoGraphicsRAMPointer = wordValue << 1; + NeoGraphicsRAMBank = NeoGraphicsRAM; + if (wordValue & 0x8000) { + NeoGraphicsRAMBank += 0x00010000; + } + break; + } + case 0x02: { + *((UINT16*)(NeoGraphicsRAMBank + NeoGraphicsRAMPointer)) = wordValue; + NeoGraphicsRAMPointer += nNeoGraphicsModulo; + +#if 0 + if ((NeoGraphicsRAMBank == NeoGraphicsRAM) && NeoGraphicsRAMPointer >= 0xC000 && NeoGraphicsRAMPointer < 0xE000) { + bprintf(PRINT_NORMAL, _T("VRAM bank 0 + 0x%04X -> %04X\n"), NeoGraphicsRAMPointer, wordValue); + } + if ((NeoGraphicsRAMBank != NeoGraphicsRAM) && NeoGraphicsRAMPointer >= 0x0C00) { + bprintf(PRINT_NORMAL, _T("VRAM bank 1 + 0x%04X -> %04X\n"), NeoGraphicsRAMPointer, wordValue); + } +#endif + +#if 1 && defined USE_SPEEDHACKS + bForcePartialRender |= bForceUpdateOnStatusRead; +#endif + break; + } + case 0x04: { + nNeoGraphicsModulo = ((INT16)wordValue) << 1; + break; + } + + case 0x06: { + nSpriteFrameSpeed = (wordValue >> 8); + + if ((nIRQControl & 0x10) == 0 && wordValue & 0x10) { + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ enabled (at line %3i, IRQControl: 0x%02X).\n"), SekCurrentScanline(), wordValue & 0xFF); +#endif + + if (nIRQCycles < nCyclesSegment) { + SekRunAdjust(nIRQCycles - nCyclesSegment); + } + } + +#if 0 || defined LOG_IRQ + if (nIRQControl & 0x10 && (wordValue & 0x10) == 0) { + bprintf(PRINT_NORMAL, _T(" - IRQ disabled (at line %3i, IRQControl: 0x%02X).\n"), SekCurrentScanline(), wordValue & 0xFF); + } +#endif + + nIRQControl = wordValue; +// bprintf(PRINT_NORMAL, _T(" - Autoanim speed -> 0x%02X\n"), wordValue >> 8); +// bprintf(PRINT_NORMAL, _T(" - IRQ control register -> 0x%02X (at line %3i)\n"), wordValue & 0xFF, SekCurrentScanline()); + break; + } + + case 0x08: { +// bprintf(PRINT_NORMAL, "0x%06X -> 0x%04X\n", sekAddress, wordValue); + // Bit 15 seems to be ignored + nIRQOffset = (nIRQOffset & 0x0000FFFF) | ((wordValue & 0x7FFF) << 16); + break; + } + case 0x0A: { +// bprintf(PRINT_NORMAL, "0x%06X -> 0x%04X\n", sekAddress, wordValue); + nIRQOffset = (nIRQOffset & 0xFFFF0000) | wordValue; + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ offs -> 0x%08X (at line %3i, IRQControl: 0x%02X).\n"), nIRQOffset, SekCurrentScanline(), nIRQControl); +#endif + + if (nIRQControl & 0x20) { + +#if 0 +// nIRQCycles = SekTotalCycles() - 64 + NeoConvertIRQPosition(nIRQOffset); + nIRQCycles = SekTotalCycles() + NeoConvertIRQPosition(nIRQOffset); +#else + // Turfmast uses this to set the timing of the raster interrupts. Using the code below, + // all raster effects in turfmast are correctly aligned and exhibit no flicker. + // (this sets the offset of the IRQ to the start of the current scanline instead of the actual beam position) + + // ssideki2 has some problems with this + nIRQCycles = SekCurrentScanline() * nSekCyclesScanline + NeoConvertIRQPosition(nIRQOffset + 8); +// bprintf(PRINT_NORMAL, _T(" %i - %i\n"), SekCurrentScanline(), SekTotalCycles() % SekCyclesScanline()); +#endif + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" IRQ Line -> %3i (at line %3i, relative).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + if (nIRQCycles < 0) { + nIRQCycles = NO_IRQ_PENDING; + } + if (nIRQCycles < nCyclesSegment) { + SekRunAdjust(nIRQCycles - nCyclesSegment); + } + } + + break; + } + + case 0x0C: { + NeoIRQUpdate(wordValue); + break; + } + } +} + +void __fastcall neogeoWriteByteVideo(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" - Attempt to write byte 0x%06X -> 0x%02X\n"), sekAddress, byteValue); + +#if 1 + if ((sekAddress & 1) == 0) { + neogeoWriteWordVideo(sekAddress, byteValue); + } +#else + if (sekAddress & 1) { + neogeoWriteWordVideo(sekAddress, byteValue); + } else { + neogeoWriteWordVideo(sekAddress, (byteValue << 8)); + } +#endif + +#if 1 && defined USE_SPEEDHACKS + bForcePartialRender |= bForceUpdateOnStatusRead; +#endif +} + +// ---------------------------------------------------------------------------- +// Backup RAM on MVS hardware + +void __fastcall neogeoWriteByteSRAM(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress &= 0xFFFF; + + if (bSRAMWritable) { + NeoNVRAM[sekAddress ^ 1] = byteValue; + } +} + +void __fastcall neogeoWriteWordSRAM(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress &= 0xFFFF; + + if (bSRAMWritable) { + *((UINT16*)(NeoNVRAM + sekAddress)) = wordValue; + } +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall neogeoReadByteMemoryCard(UINT32 sekAddress) +{ +// if (sekAddress < 0x800100) +// bprintf(PRINT_NORMAL, _T(" - Memcard 0x%04X read (PC: 0x%06X).\n"), sekAddress & 0x7FFF, SekGetPC(-1)); + + if (bMemoryCardInserted) { + if ((NeoSystem & 0x40) || (sekAddress & 1)) { + return NeoMemoryCard[sekAddress & 0x01FFFF]; + } + } + + return 0xFF; +} + +void __fastcall neogeoWriteByteMemoryCard(UINT32 sekAddress, UINT8 byteValue) +{ +// if (sekAddress < 0x800100) +// bprintf(PRINT_NORMAL, _T(" - Memcard 0x%04X -> 0x%02X (PC: 0x%06X).\n"), sekAddress & 0x7FFF, byteValue, SekGetPC(-1)); + + if (bMemoryCardInserted && bMemoryCardWritable) { + if ((NeoSystem & 0x40) || (sekAddress & 1)) { + NeoMemoryCard[sekAddress & 0x01FFFF] = byteValue; + } + } +} + +UINT8 __fastcall neoCDReadByteMemoryCard(UINT32 sekAddress) +{ + sekAddress &= 0x01FFFF; + if (sekAddress < 0x4000 && sekAddress & 1) { + return NeoMemoryCard[sekAddress]; + } + + return 0xFF; +} + +void __fastcall neoCDWriteByteMemoryCard(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress &= 0x01FFFF; + if (sekAddress < 0x4000 && sekAddress & 1) { + NeoMemoryCard[sekAddress] = byteValue; + } +} + +// ---------------------------------------------------------------------------- +// NeoCD CD-ROM controller handlers + +#define CD_FRAMES_MINUTE (60 * 75) +#define CD_FRAMES_SECOND ( 75) +#define CD_FRAMES_PREGAP ( 2 * 75) + +static INT32 nLC8951Register = 0; +static INT32 LC8951RegistersR[16]; +static INT32 LC8951RegistersW[16]; + +static INT32 nActiveTransferArea; +static INT32 nSpriteTransferBank; +static INT32 nADPCMTransferBank; + +static UINT8 nTransferWriteEnable; + +static bool NeoCDOBJBankUpdate[4]; + +static bool bNeoCDCommsClock, bNeoCDCommsSend; + +static UINT8 NeoCDCommsCommandFIFO[10] = { 0, }; +static UINT8 NeoCDCommsStatusFIFO[10] = { 0, }; + +static INT32 NeoCDCommsWordCount = 0; + +static INT32 NeoCDAssyStatus = 0; + +static INT32 NeoCDTrack = 0; + +static INT32 NeoCDSectorMin = 0; +static INT32 NeoCDSectorSec = 0; +static INT32 NeoCDSectorFrm = 0; +static INT32 NeoCDSectorLBA = 0; + +static char NeoCDSectorData[2352]; + +static bool bNeoCDLoadSector = false; + +static INT32 NeoCDDMAAddress1 = 0; +static INT32 NeoCDDMAAddress2 = 0; +static INT32 NeoCDDMAValue1 = 0; +static INT32 NeoCDDMAValue2 = 0; +static INT32 NeoCDDMACount = 0; + +static INT32 NeoCDDMAMode = 0; + +// hax0r +static INT32 nNeoCDMode = 0; +static INT32 nff0002 = 0; + +static void NeoCDLBAToMSF(const INT32 LBA) +{ + NeoCDSectorMin = (LBA + CD_FRAMES_PREGAP) / CD_FRAMES_MINUTE; + NeoCDSectorSec = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_MINUTE / CD_FRAMES_SECOND; + NeoCDSectorFrm = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_SECOND; +} + +static void NeoCDCommsWrite(UINT8 data) +{ + if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) { + NeoCDCommsCommandFIFO[NeoCDCommsWordCount] = data & 0x0F; + } +} + +static UINT8 NeoCDCommsread() +{ + UINT8 ret = 0; + + if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) { + ret = NeoCDCommsStatusFIFO[NeoCDCommsWordCount] & 0x0F; + } + + if (bNeoCDCommsClock) { + ret |= 0x10; + } + + return ret; +} + +static void NeoCDCommsReset() +{ + bNeoCDCommsSend = false; + bNeoCDCommsClock = true; + + memset(NeoCDCommsCommandFIFO, 0, sizeof(NeoCDCommsCommandFIFO)); + memset(NeoCDCommsStatusFIFO, 0, sizeof(NeoCDCommsStatusFIFO)); + + NeoCDCommsWordCount = 0; + + NeoCDAssyStatus = 9; + + memset(NeoCDSectorData, 0, sizeof(NeoCDSectorData)); + + bNeoCDLoadSector = false; + + nNeoCDMode = 0; +} + +static void LC8951UpdateHeader() +{ + NeoCDLBAToMSF(NeoCDSectorLBA); + + if (LC8951RegistersW[11] & 1) { + + // HEAD registers have sub-header + + LC8951RegistersR[4] = 0; // HEAD0 + LC8951RegistersR[5] = 0; // HEAD1 + LC8951RegistersR[6] = 0; // HEAD2 + LC8951RegistersR[7] = 0; // HEAD3 + + } else { + + // HEAD registers have header + + LC8951RegistersR[4] = ((NeoCDSectorMin / 10) << 4) | (NeoCDSectorMin % 10); // HEAD0 + LC8951RegistersR[5] = ((NeoCDSectorSec / 10) << 4) | (NeoCDSectorSec % 10); // HEAD1 + LC8951RegistersR[6] = ((NeoCDSectorFrm / 10) << 4) | (NeoCDSectorFrm % 10); // HEAD2 + LC8951RegistersR[7] = 1; // HEAD3 + } +} + +static char* LC8915InitTransfer() +{ + if (!LC8951RegistersW[6]) { + bprintf(PRINT_ERROR, _T(" LC8951 DTTRG status invalid\n")); + return NULL; + } + if (!(LC8951RegistersW[1] & 0x02)) { + bprintf(PRINT_ERROR, _T(" LC8951 DOUTEN status invalid\n")); + return NULL; + } + if (((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]) + (NeoCDDMACount << 1) > 2352) { + bprintf(PRINT_ERROR, _T(" DMA transfer exceeds current sector in LC8951 external buffer\n")); + return NULL; + } + + return NeoCDSectorData + ((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]); +} + +static void LC8915EndTransfer() +{ + LC8951RegistersW[6] = 0x00; // reset DTTRG + + LC8951RegistersR[1] |= 0x48; // set DTEI & DTBSY + if (LC8951RegistersW[1] & 0x40) { + + // trigger DTE interrupt + + // the Neo Geo CD doesn't use the DTE interrupt + // nIRQAcknowledge &= ~0x20; + // NeoCDIRQUpdate(0); + + } +} + +static void LC8951Reset() +{ + memset(LC8951RegistersR, 0, sizeof(LC8951RegistersR)); + memset(LC8951RegistersW, 0, sizeof(LC8951RegistersW)); + LC8951RegistersR[0x01] = 0xFF; + LC8951RegistersR[0x0F] = 0x80; + + LC8951UpdateHeader(); +} + +static void NeoCDProcessCommand() +{ + memset(NeoCDCommsStatusFIFO, 0, sizeof(NeoCDCommsStatusFIFO)); + + if (NeoCDCommsCommandFIFO[0]) { + NeoCDCommsStatusFIFO[1] = 15; + } + + switch (NeoCDCommsCommandFIFO[0]) { + case 0: + break; + case 1: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + CDEmuStop(); + + NeoCDAssyStatus = 0x0E; + bNeoCDLoadSector = false; + break; + case 2: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + NeoCDCommsStatusFIFO[1] = NeoCDCommsCommandFIFO[3]; + switch (NeoCDCommsCommandFIFO[3]) { + + case 0: { + UINT8* ChannelData = CDEmuReadQChannel(); + + NeoCDCommsStatusFIFO[2] = ChannelData[1] / 10; + NeoCDCommsStatusFIFO[3] = ChannelData[1] % 10; + + NeoCDCommsStatusFIFO[4] = ChannelData[2] / 10; + NeoCDCommsStatusFIFO[5] = ChannelData[2] % 10; + + NeoCDCommsStatusFIFO[6] = ChannelData[3] / 10; + NeoCDCommsStatusFIFO[7] = ChannelData[3] % 10; + + NeoCDCommsStatusFIFO[8] = ChannelData[7]; + +// bprintf(PRINT_ERROR, _T(" %02i %02i:%02i:%02i %02i:%02i:%02i %02i\n"), ChannelData[0], ChannelData[1], ChannelData[2], ChannelData[3], ChannelData[4], ChannelData[5], ChannelData[6], ChannelData[7]); + + break; + } + case 1: { + UINT8* ChannelData = CDEmuReadQChannel(); + + NeoCDCommsStatusFIFO[2] = ChannelData[4] / 10; + NeoCDCommsStatusFIFO[3] = ChannelData[4] % 10; + + NeoCDCommsStatusFIFO[4] = ChannelData[5] / 10; + NeoCDCommsStatusFIFO[5] = ChannelData[5] % 10; + + NeoCDCommsStatusFIFO[6] = ChannelData[6] / 10; + NeoCDCommsStatusFIFO[7] = ChannelData[6] % 10; + + NeoCDCommsStatusFIFO[8] = ChannelData[7]; + + break; + } + case 2: { + + UINT8* ChannelData = CDEmuReadQChannel(); + + NeoCDCommsStatusFIFO[2] = ChannelData[0] / 10; + NeoCDCommsStatusFIFO[3] = ChannelData[0] % 10; + + + NeoCDCommsStatusFIFO[8] = ChannelData[7]; + + break; + } + case 3: { + UINT8* TOCEntry = CDEmuReadTOC(-2); + + NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10; + NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10; + + NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10; + NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10; + + NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10; + NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10; + + break; + } + case 4: { + UINT8* TOCEntry = CDEmuReadTOC(-1); + + NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10; + NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10; + + NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10; + NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10; + + break; + } + case 5: { + NeoCDTrack = NeoCDCommsCommandFIFO[4] * 10 + NeoCDCommsCommandFIFO[5]; + + UINT8* TOCEntry = CDEmuReadTOC(NeoCDTrack); + + NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10; + NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10; + + NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10; + NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10; + + NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10; + NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10; + + // bit 3 of the 1st minutes digit indicates a data track + if (TOCEntry[3] & 4) { + NeoCDCommsStatusFIFO[6] |= 8; + } + + NeoCDCommsStatusFIFO[8] = NeoCDTrack % 10; + + break; + } + + case 6: { + + UINT8* ChannelData = CDEmuReadQChannel(); + + NeoCDCommsStatusFIFO[8] = ChannelData[7]; + + break; + } + + case 7: { + + // must be 02, 0E, 0F, or 05 + NeoCDCommsStatusFIFO[2] = 0; + NeoCDCommsStatusFIFO[3] = 5; + + NeoCDCommsStatusFIFO[4] = 0; + NeoCDCommsStatusFIFO[5] = 0; + + NeoCDCommsStatusFIFO[6] = 0; + NeoCDCommsStatusFIFO[7] = 0; + break; + } + } + break; + + case 3: { + + if (LC8951RegistersW[10] & 4) { + + if (CDEmuGetStatus() == playing) { + bprintf(PRINT_ERROR, _T("*** Switching CD mode to CD-ROM while in audio mode!(PC: 0x%06X)\n"), SekGetPC(-1)); + } + + NeoCDSectorLBA = NeoCDCommsCommandFIFO[2] * (10 * CD_FRAMES_MINUTE); + NeoCDSectorLBA += NeoCDCommsCommandFIFO[3] * ( 1 * CD_FRAMES_MINUTE); + NeoCDSectorLBA += NeoCDCommsCommandFIFO[4] * (10 * CD_FRAMES_SECOND); + NeoCDSectorLBA += NeoCDCommsCommandFIFO[5] * ( 1 * CD_FRAMES_SECOND); + NeoCDSectorLBA += NeoCDCommsCommandFIFO[6] * (10 ); + NeoCDSectorLBA += NeoCDCommsCommandFIFO[7] * ( 1 ); + + NeoCDSectorLBA -= CD_FRAMES_PREGAP; + + CDEmuStartRead(); +// LC8951RegistersR[1] |= 0x20; + } else { + + if (CDEmuGetStatus() == reading) { + bprintf(PRINT_ERROR, _T("*** Switching CD mode to audio while in CD-ROM mode!(PC: 0x%06X)\n"), SekGetPC(-1)); + } + + CDEmuPlay((NeoCDCommsCommandFIFO[2] * 10) + NeoCDCommsCommandFIFO[3], (NeoCDCommsCommandFIFO[4] * 10) + NeoCDCommsCommandFIFO[5], (NeoCDCommsCommandFIFO[6] * 10) + NeoCDCommsCommandFIFO[7]); + } + + NeoCDAssyStatus = 1; + bNeoCDLoadSector = true; + + break; + } + case 4: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + CDEmuPause(); + break; + case 5: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); +// NeoCDAssyStatus = 9; +// bNeoCDLoadSector = false; + break; + + case 6: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + NeoCDAssyStatus = 4; + bNeoCDLoadSector = false; + break; + case 7: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + NeoCDAssyStatus = 1; + bNeoCDLoadSector = true; + break; + + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: +// bprintf(PRINT_ERROR, _T(" CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]); + NeoCDAssyStatus = 9; + bNeoCDLoadSector = false; + break; + } +} + +static void NeoCDDoDMA() +{ + + // The LC8953 chip has a programmable DMA controller, which is not properly emulated. + // Since the software only uses it in a limited way, we can apply a simple heuristic + // to determnine the requested operation. + + // Additionally, we don't know how many cycles DMA operations take. + // Here, only bus access is used to get a rough approximation -- + // each read/write takes a single cycle, setup and everything else is ignored. + +// bprintf(PRINT_IMPORTANT, _T(" - DMA controller transfer started (PC: 0x%06X)\n"), SekGetPC(-1)); + + switch (NeoCDDMAMode) { + + case 0xCFFD: { +// bprintf(PRINT_NORMAL, _T(" adr : 0x%08X - 0x%08X <- address, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 8); + + // - DMA controller 0x7E -> 0xCFFD (PC: 0xC07CE2) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8) + // - DMA controller program[02] -> 0xE8DA (PC: 0xC07CEE) + // - DMA controller program[04] -> 0x92DA (PC: 0xC07CF4) + // - DMA controller program[06] -> 0x92DB (PC: 0xC07CFA) + // - DMA controller program[08] -> 0x96DB (PC: 0xC07D00) + // - DMA controller program[10] -> 0x96F6 (PC: 0xC07D06) + // - DMA controller program[12] -> 0x2E02 (PC: 0xC07D0C) + // - DMA controller program[14] -> 0xFDFF (PC: 0xC07D12) + + SekIdle(NeoCDDMACount * 4); + + while (NeoCDDMACount--) { + SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 24); + SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >> 16); + SekWriteWord(NeoCDDMAAddress1 + 4, NeoCDDMAAddress1 >> 8); + SekWriteWord(NeoCDDMAAddress1 + 6, NeoCDDMAAddress1 >> 0); + NeoCDDMAAddress1 += 8; + } + + break; + } + + case 0xE2DD: { +// bprintf(PRINT_NORMAL, _T(" copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X, skip odd bytes\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4); + + // - DMA controller 0x7E -> 0xE2DD (PC: 0xC0A190) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192) + // - DMA controller program[02] -> 0x82BE (PC: 0xC0A194) + // - DMA controller program[04] -> 0x93DA (PC: 0xC0A196) + // - DMA controller program[06] -> 0xBE93 (PC: 0xC0A198) + // - DMA controller program[08] -> 0xDABE (PC: 0xC0A19A) + // - DMA controller program[10] -> 0xF62D (PC: 0xC0A19C) + // - DMA controller program[12] -> 0x02FD (PC: 0xC0A19E) + // - DMA controller program[14] -> 0xFFFF (PC: 0xC0A1A0) + + SekIdle(NeoCDDMACount * 1); + + while (NeoCDDMACount--) { + SekWriteWord(NeoCDDMAAddress2 + 0, SekReadByte(NeoCDDMAAddress1 + 0)); + SekWriteWord(NeoCDDMAAddress2 + 2, SekReadByte(NeoCDDMAAddress1 + 1)); + NeoCDDMAAddress1 += 2; + NeoCDDMAAddress2 += 4; + } + + break; + } + + case 0xFC2D: { +// bprintf(PRINT_NORMAL, _T(" copy: 0x%08X - 0x%08X <- LC8951 external buffer, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4); + + // - DMA controller 0x7E -> 0xFC2D (PC: 0xC0A190) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192) + // - DMA controller program[02] -> 0x8492 (PC: 0xC0A194) + // - DMA controller program[04] -> 0xDA92 (PC: 0xC0A196) + // - DMA controller program[06] -> 0xDAF6 (PC: 0xC0A198) + // - DMA controller program[08] -> 0x2A02 (PC: 0xC0A19A) + // - DMA controller program[10] -> 0xFDFF (PC: 0xC0A19C) + // - DMA controller program[12] -> 0x48E7 (PC: 0xC0A19E) + // - DMA controller program[14] -> 0xFFFE (PC: 0xC0A1A0) + + char* data = LC8915InitTransfer(); + if (data == NULL) { + break; + } + + SekIdle(NeoCDDMACount * 4); + + while (NeoCDDMACount--) { + SekWriteByte(NeoCDDMAAddress1 + 0, data[0]); + SekWriteByte(NeoCDDMAAddress1 + 2, data[1]); + NeoCDDMAAddress1 += 4; + data += 2; + } + + LC8915EndTransfer(); + + break; + } + + case 0xFE3D: + + // - DMA controller 0x7E -> 0xFE3D (PC: 0xC0A190) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192) + // - DMA controller program[02] -> 0x82BF (PC: 0xC0A194) + // - DMA controller program[04] -> 0x93BF (PC: 0xC0A196) + // - DMA controller program[06] -> 0xF629 (PC: 0xC0A198) + // - DMA controller program[08] -> 0x02FD (PC: 0xC0A19A) + // - DMA controller program[10] -> 0xFFFF (PC: 0xC0A19C) + // - DMA controller program[12] -> 0xF17D (PC: 0xC0A19E) + // - DMA controller program[14] -> 0xFCF5 (PC: 0xC0A1A0) + + case 0xFE6D: { +// bprintf(PRINT_NORMAL, _T(" copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2); + + // - DMA controller 0x7E -> 0xFE6D (PC: 0xC0FD7A) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0FD7C) + // - DMA controller program[02] -> 0x82BF (PC: 0xC0FD7E) + // - DMA controller program[04] -> 0xF693 (PC: 0xC0FD80) + // - DMA controller program[06] -> 0xBF29 (PC: 0xC0FD82) + // - DMA controller program[08] -> 0x02FD (PC: 0xC0FD84) + // - DMA controller program[10] -> 0xFFFF (PC: 0xC0FD86) + // - DMA controller program[12] -> 0xC515 (PC: 0xC0FD88) + // - DMA controller program[14] -> 0xFCF5 (PC: 0xC0FD8A) + + SekIdle(NeoCDDMACount * 1); + + while (NeoCDDMACount--) { + SekWriteWord(NeoCDDMAAddress2, SekReadWord(NeoCDDMAAddress1)); + NeoCDDMAAddress1 += 2; + NeoCDDMAAddress2 += 2; + } + +if (NeoCDDMAAddress2 == 0x0800) { +// MapVectorTable(false); +// bprintf(PRINT_ERROR, _T(" RAM vectors mapped (PC = 0x%08X\n"), SekGetPC(0)); +// extern INT32 bRunPause; +// bRunPause = 1; +} + break; + } + + case 0xFEF5: { +// bprintf(PRINT_NORMAL, _T(" adr : 0x%08X - 0x%08X <- address\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4); + + // - DMA controller 0x7E -> 0xFEF5 (PC: 0xC07CE2) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8) + // - DMA controller program[02] -> 0x92E8 (PC: 0xC07CEE) + // - DMA controller program[04] -> 0xBE96 (PC: 0xC07CF4) + // - DMA controller program[06] -> 0xF629 (PC: 0xC07CFA) + // - DMA controller program[08] -> 0x02FD (PC: 0xC07D00) + // - DMA controller program[10] -> 0xFFFF (PC: 0xC07D06) + // - DMA controller program[12] -> 0xFC3D (PC: 0xC07D0C) + // - DMA controller program[14] -> 0xFCF5 (PC: 0xC07D12) + + SekIdle(NeoCDDMACount * 2); + + while (NeoCDDMACount--) { + SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 16); + SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >> 0); + NeoCDDMAAddress1 += 4; + } + + break; + } + + case 0xFFC5: { +// bprintf(PRINT_NORMAL, _T(" copy: 0x%08X - 0x%08X <- LC8951 external buffer\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2); + + // - DMA controller 0x7E -> 0xFFC5 (PC: 0xC0A190) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192) + // - DMA controller program[02] -> 0xA6F6 (PC: 0xC0A194) + // - DMA controller program[04] -> 0x2602 (PC: 0xC0A196) + // - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198) + // - DMA controller program[08] -> 0xFC2D (PC: 0xC0A19A) + // - DMA controller program[10] -> 0xFCF5 (PC: 0xC0A19C) + // - DMA controller program[12] -> 0x8492 (PC: 0xC0A19E) + // - DMA controller program[14] -> 0xDA92 (PC: 0xC0A1A0) + + char* data = LC8915InitTransfer(); + if (data == NULL) { + break; + } + + SekIdle(NeoCDDMACount * 4); + + while (NeoCDDMACount--) { + SekWriteByte(NeoCDDMAAddress1 + 0, data[0]); + SekWriteByte(NeoCDDMAAddress1 + 1, data[1]); + NeoCDDMAAddress1 += 2; + data += 2; + } + + LC8915EndTransfer(); + + break; + } + + case 0xFFCD: + + // - DMA controller 0x7E -> 0xFFCD (PC: 0xC0A190) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192) + // - DMA controller program[02] -> 0x92F6 (PC: 0xC0A194) + // - DMA controller program[04] -> 0x2602 (PC: 0xC0A196) + // - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198) + // - DMA controller program[08] -> 0x7006 (PC: 0xC0A19A) + // - DMA controller program[10] -> 0x6100 (PC: 0xC0A19C) + // - DMA controller program[12] -> 0x2412 (PC: 0xC0A19E) + // - DMA controller program[14] -> 0x13FC (PC: 0xC0A1A0) + + case 0xFFDD: { +// bprintf(PRINT_NORMAL, _T(" Fill: 0x%08X - 0x%08X <- 0x%04X\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2, NeoCDDMAValue1); + + // - DMA controller 0x7E -> 0xFFDD (PC: 0xC07CE2) + // - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8) + // - DMA controller program[02] -> 0x92F6 (PC: 0xC07CEE) + // - DMA controller program[04] -> 0x2602 (PC: 0xC07CF4) + // - DMA controller program[06] -> 0xFDFF (PC: 0xC07CFA) + // - DMA controller program[08] -> 0xFFFF (PC: 0xC07D00) + // - DMA controller program[10] -> 0xFCF5 (PC: 0xC07D06) + // - DMA controller program[12] -> 0x8AF0 (PC: 0xC07D0C) + // - DMA controller program[14] -> 0x1609 (PC: 0xC07D12) + + SekIdle(NeoCDDMACount * 1); + + while (NeoCDDMACount--) { + SekWriteWord(NeoCDDMAAddress1, NeoCDDMAValue1); + NeoCDDMAAddress1 += 2; + } + + break; + } + default: { + bprintf(PRINT_ERROR, _T(" Unknown transfer type 0x%04X (PC: 0x%06X)\n"), NeoCDDMAMode, SekGetPC(-1)); + bprintf(PRINT_NORMAL, _T(" ??? : 0x%08X 0x%08X 0x%04X 0x%04X 0x%08X\n"), NeoCDDMAAddress1, NeoCDDMAAddress2, NeoCDDMAValue1, NeoCDDMAValue2, NeoCDDMACount); + +extern INT32 bRunPause; +bRunPause = 1; + + } + } +} + +static void NeoCDCommsControl(UINT8 clock, UINT8 send) +{ + if (clock && !bNeoCDCommsClock) { + NeoCDCommsWordCount++; + if (NeoCDCommsWordCount >= 10) { + NeoCDCommsWordCount = 0; + + if (send) { + + // command receive complete + + if (NeoCDCommsCommandFIFO[0]) { + INT32 sum = 0; + +// bprintf(PRINT_NORMAL, _T(" - CD mechanism command receive completed : 0x")); + for (INT32 i = 0; i < 9; i++) { +// bprintf(PRINT_NORMAL, _T("%X"), NeoCDCommsCommandFIFO[i]); + sum += NeoCDCommsCommandFIFO[i]; + } + sum = ~(sum + 5) & 0x0F; +// bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), NeoCDCommsCommandFIFO[9], (sum == NeoCDCommsCommandFIFO[9]) ? _T("OK") : _T("NG")); + if (sum == NeoCDCommsCommandFIFO[9]) { + + NeoCDProcessCommand(); + + if (NeoCDCommsCommandFIFO[0]) { + + if (NeoCDAssyStatus == 1) { + if (CDEmuGetStatus() == idle) { + NeoCDAssyStatus = 0x0E; + bNeoCDLoadSector = false; + } + } + + NeoCDCommsStatusFIFO[0] = NeoCDAssyStatus; + +#if 0 + extern INT32 counter; + if (counter) { + NeoCDCommsStatusFIFO[0] = counter & 0x0F; + } +#endif + + // compute checksum + + sum = 0; + + for (INT32 i = 0; i < 9; i++) { + sum += NeoCDCommsStatusFIFO[i]; + } + NeoCDCommsStatusFIFO[9] = ~(sum + 5) & 0x0F; + } + } + } + } else { + + // status send complete + +// if (NeoCDCommsStatusFIFO[0] || NeoCDCommsStatusFIFO[1]) { +// INT32 sum = 0; +// +// bprintf(PRINT_NORMAL, _T(" - CD mechanism status send completed : 0x")); +// for (INT32 i = 0; i < 9; i++) { +// bprintf(PRINT_NORMAL, _T("%X"), NeoCDCommsStatusFIFO[i]); +// sum += NeoCDCommsStatusFIFO[i]; +// } +// sum = ~(sum + 5) & 0x0F; +// bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), NeoCDCommsStatusFIFO[9], (sum == NeoCDCommsStatusFIFO[9]) ? _T("OK") : _T("NG")); +// } + +// if (NeoCDAssyStatus == 0xE) { +// NeoCDAssyStatus = 9; +// } + } + + } + bNeoCDCommsSend = send; + } + bNeoCDCommsClock = clock; +} + +void NeoCDReadSector() +{ + if ((nff0002 & 0x0500)) { + if (NeoCDAssyStatus == 1 && bNeoCDLoadSector) { + +// if (LC8951RegistersW[10] & 0x80) { + NeoCDSectorLBA++; + NeoCDSectorLBA = CDEmuLoadSector(NeoCDSectorLBA, NeoCDSectorData + 4) - 1; +// } + + if (LC8951RegistersW[10] & 0x80) { + LC8951UpdateHeader(); + + LC8951RegistersR[12] = 0x80; // STAT0 + LC8951RegistersR[13] = 0; // STAT1 + LC8951RegistersR[14] = 0x10; // STAT2 + LC8951RegistersR[15] = 0; // STAT3 + +// bprintf(PRINT_IMPORTANT, _T(" Sector %08i (%02i:%02i:%02i) read\n"), NeoCDSectorLBA, NeoCDSectorMin, NeoCDSectorSec, NeoCDSectorFrm); + +#if 1 + if (NeoCDSectorData[4 + 64] == 'g' && !strncmp(NeoCDSectorData + 4, "Copyright by SNK", 16)) { +// printf(PRINT_ERROR, _T(" simulated CDZ protection error\n")); +// bprintf(PRINT_ERROR, _T(" %.70hs\n"), NeoCDSectorData + 4); + + NeoCDSectorData[4 + 64] = 'f'; + + // LC8951RegistersR[12] = 0x00; // STAT0 + } +#endif + + nIRQAcknowledge &= ~0x20; + NeoCDIRQUpdate(0); + + LC8951RegistersR[1] &= ~0x20; + +// bprintf(PRINT_IMPORTANT, _T(" DECI interrupt triggered\n")); + } + } + + bNeoCDLoadSector = true; +// bNeoCDLoadSector = false; + } +} + +UINT8 __fastcall neogeoReadByteCDROM(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" - CDROM: 0x%06X read (byte, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + switch (sekAddress & 0xFFFF) { + + case 0x0017: + return nNeoCDMode; + + // LC8951 registers + case 0x0101: +// bprintf(PRINT_NORMAL, _T(" - LC8951 register read (PC: 0x%06X)\n"), SekGetPC(-1)); + return nLC8951Register; + case 0x0103: { +// bprintf(PRINT_NORMAL, _T(" - LC8951 register 0x%X read (PC: 0x%06X)\n"), nLC8951Register, SekGetPC(-1)); + + INT32 reg = LC8951RegistersR[nLC8951Register]; + + switch (nLC8951Register) { + case 0x03: // DBCH + LC8951RegistersR[3] &= 0x0F; + LC8951RegistersR[3] |= (LC8951RegistersR[1] & 0x40) ? 0x00 : 0xF0; + break; + case 0x0D: // STAT3 + LC8951RegistersR[1] |= 0x20; // reset DECI + // bprintf(PRINT_ERROR, _T(" - DECI (PC: 0x%06X)\n"), SekGetPC(-1)); + break; + } + + nLC8951Register = (nLC8951Register + 1) & 0x0F; + return reg; + } + + // CD mechanism communication + case 0x0161: + return NeoCDCommsread(); + + default: { +// bprintf(PRINT_NORMAL, _T(" - NGCD port 0x%06X read (byte, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + } + } + + return ~0; +} + +UINT16 __fastcall neogeoReadWordCDROM(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" - CDROM: 0x%06X read (word, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + +#if 1 + switch (sekAddress & 0xFFFF) { + case 0x011C: + return ~((0x10 | (NeoSystem & 3)) << 8); + } +#endif + +// bprintf(PRINT_NORMAL, _T(" - NGCD port 0x%06X read (word, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + return ~0; +} + +void __fastcall neogeoWriteByteCDROM(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" - Neo Geo CD: 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + + switch (sekAddress & 0xFFFF) { + case 0x000F: + NeoCDIRQUpdate(byteValue); + break; + + case 0x0017: + nNeoCDMode = byteValue; + break; + + case 0x0061: + if (byteValue & 0x40) { + NeoCDDoDMA(); + } + break; + + // LC8951 registers + case 0x0101: + nLC8951Register = byteValue & 0x0F; +// bprintf(PRINT_NORMAL, _T(" - LC8951 register -> 0x%02X (PC: 0x%06X)\n"), nLC8951Register, SekGetPC(-1)); + break; + case 0x0103: +// bprintf(PRINT_NORMAL, _T(" - LC8951 register 0x%X -> 0x%02X (PC: 0x%06X)\n"), nLC8951Register, byteValue, SekGetPC(-1)); + switch (nLC8951Register) { + case 3: // DBCH + LC8951RegistersW[ 3] = byteValue & 0x0F; + break; + case 6: // DTTRG + LC8951RegistersW[ 6] = ~0x00; + LC8951RegistersR[ 1] &= ~0x08; + break; + case 7: // DTACK + LC8951RegistersW[ 7] = ~0x00; + LC8951RegistersR[ 1] &= ~0x40; + break; +// case 10: +// LC8951RegistersW[nLC8951Register] = byteValue; +// bprintf(PRINT_NORMAL, _T(" - CTRL0 -> %02X (PC: 0x%06X)\n"), LC8951RegistersW[nLC8951Register], byteValue, SekGetPC(-1)); +// break; + case 11: + LC8951RegistersW[11] = byteValue; // CTRL1 + LC8951UpdateHeader(); + break; + case 15: + LC8951Reset(); + break; + default: + LC8951RegistersW[nLC8951Register] = byteValue; + } + nLC8951Register = (nLC8951Register + 1) & 0x0F; + break; + + case 0x0105: +// bprintf(PRINT_NORMAL, _T(" - NGCD 0xE00000 area -> 0x%02X (PC: 0x%06X)\n"), byteValue, SekGetPC(-1)); + nActiveTransferArea = byteValue; + break; + + case 0x0121: +// bprintf(PRINT_NORMAL, _T(" - NGCD OBJ BUSREQ -> 1 (PC: 0x%06X)\n"), SekGetPC(-1)); + NeoSetSpriteSlot(1); + memset(NeoCDOBJBankUpdate, 0, sizeof(NeoCDOBJBankUpdate)); + break; + case 0x0123: +// bprintf(PRINT_NORMAL, _T(" - NGCD PCM BUSREQ -> 1 (PC: 0x%06X) %x\n"), SekGetPC(-1), byteValue); + break; + case 0x0127: +// bprintf(PRINT_NORMAL, _T(" - NGCD Z80 BUSREQ -> 1 (PC: 0x%06X)\n"), SekGetPC(-1)); + neogeoSynchroniseZ80(0); + ZetSetBUSREQLine(1); + break; + case 0x0129: +// bprintf(PRINT_NORMAL, _T(" - NGCD FIX BUSREQ -> 1 (PC: 0x%06X)\n"), SekGetPC(-1)); + NeoSetTextSlot(1); + break; + + case 0x0141: +// bprintf(PRINT_NORMAL, _T(" - NGCD OBJ BUSREQ -> 0 (PC: 0x%06X)\n"), SekGetPC(-1)); + NeoSetSpriteSlot(0); + for (INT32 i = 0; i < 4; i++) { + if (NeoCDOBJBankUpdate[i]) { + NeoDecodeSpritesCD(NeoSpriteRAM + (i << 20), NeoSpriteROM[0] + (i << 20), 0x100000); + NeoUpdateSprites((i << 20), 0x100000); + } + } + + break; + case 0x0143: +// bprintf(PRINT_NORMAL, _T(" - NGCD PCM BUSREQ -> 0 (PC: 0x%06X)\n"), SekGetPC(-1)); + break; + case 0x0147: +// bprintf(PRINT_NORMAL, _T(" - NGCD Z80 BUSREQ -> 0 (PC: 0x%06X)\n"), SekGetPC(-1)); + neogeoSynchroniseZ80(0); + ZetSetBUSREQLine(0); + break; + case 0x0149: +// bprintf(PRINT_NORMAL, _T(" - NGCD FIX BUSREQ -> 0 (PC: 0x%06X)\n"), SekGetPC(-1)); + NeoSetTextSlot(0); + NeoUpdateText(0, 0x020000, NeoTextRAM, NeoTextROM[0]); + break; + + // CD mechanism communication + case 0x0163: + NeoCDCommsWrite(byteValue); + break; + case 0x0165: + NeoCDCommsControl(byteValue & 1, byteValue & 2); + break; + + case 0x016D: +// bprintf(PRINT_ERROR, _T(" - NGCD port 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + + MapVectorTable(!(byteValue == 0xFF)); + +//extern INT32 bRunPause; +//bRunPause = 1; + break; + + case 0x016F: +// bprintf(PRINT_IMPORTANT, _T(" - NGCD 0xE00000 area write access %s (0x%02X, PC: 0x%06X)\n"), byteValue ? _T("enabled") : _T("disabled"), byteValue, SekGetPC(-1)); + + nTransferWriteEnable = byteValue; + break; + + case 0x0181: { + static UINT8 clara = 0; + if (!byteValue && clara) { +// bprintf(PRINT_IMPORTANT, _T(" - NGCD CD communication reset (PC: 0x%06X)\n"), SekGetPC(-1)); +// NeoCDCommsReset(); + } + clara = byteValue; + break; + } + case 0x0183: { + static UINT8 clara = 0; + if (!byteValue && clara) { +// bprintf(PRINT_IMPORTANT, _T(" - NGCD Z80 reset (PC: 0x%06X)\n"), SekGetPC(-1)); + //ZetReset(); + } + clara = byteValue; + break; + } + case 0x01A1: + nSpriteTransferBank = (byteValue & 3) << 20; + break; + case 0x01A3: + nADPCMTransferBank = (byteValue & 1) << 19; + break; + + default: { +// bprintf(PRINT_NORMAL, _T(" - NGCD port 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + } + } +} + +void __fastcall neogeoWriteWordCDROM(UINT32 sekAddress, UINT16 wordValue) +{ +// bprintf(PRINT_NORMAL, _T(" - NGCD port 0x%06X -> 0x%04X (PC: 0x%06X)\n"), sekAddress, wordValue, SekGetPC(-1)); + + switch (sekAddress & 0xFFFE) { + case 0x0002: +// bprintf(PRINT_IMPORTANT, _T(" - NGCD Interrupt mask -> 0x%04X (PC: 0x%06X)\n"), wordValue, SekGetPC(-1)); + nff0002 = wordValue; + +// LC8951RegistersR[1] |= 0x20; + + if (nff0002 & 0x0500) + nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 75.0)); + else + nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 75.0)); + + break; + + case 0x000E: + NeoCDIRQUpdate(wordValue); + break; + + // DMA controller + + case 0x0064: + NeoCDDMAAddress1 &= 0x0000FFFF; + NeoCDDMAAddress1 |= wordValue << 16; + break; + case 0x0066: + NeoCDDMAAddress1 &= 0xFFFF0000; + NeoCDDMAAddress1 |= wordValue; + break; + case 0x0068: + NeoCDDMAAddress2 &= 0x0000FFFF; + NeoCDDMAAddress2 |= wordValue << 16; + break; + case 0x006A: + NeoCDDMAAddress2 &= 0xFFFF0000; + NeoCDDMAAddress2 |= wordValue; + break; + case 0x006C: + NeoCDDMAValue1 = wordValue; + break; + case 0x006E: + NeoCDDMAValue2 = wordValue; + break; + case 0x0070: + NeoCDDMACount &= 0x0000FFFF; + NeoCDDMACount |= wordValue << 16; + break; + case 0x0072: + NeoCDDMACount &= 0xFFFF0000; + NeoCDDMACount |= wordValue; + break; + + case 0x007E: + NeoCDDMAMode = wordValue; +// bprintf(PRINT_NORMAL, _T(" - DMA controller 0x%2X -> 0x%04X (PC: 0x%06X)\n"), sekAddress & 0xFF, wordValue, SekGetPC(-1)); + break; + + // upload DMA controller program + + case 0x0080: + case 0x0082: + case 0x0084: + case 0x0086: + case 0x0088: + case 0x008A: + case 0x008C: + case 0x008E: +// bprintf(PRINT_NORMAL, _T(" - DMA controller program[%02i] -> 0x%04X (PC: 0x%06X)\n"), sekAddress & 0x0F, wordValue, SekGetPC(-1)); + break; + + default: { +// bprintf(PRINT_NORMAL, _T(" - NGCD port 0x%06X -> 0x%04X (PC: 0x%06X)\n"), sekAddress, wordValue, SekGetPC(-1)); + } + } + +} + +// Reads from / writes to the transfer area + +UINT8 __fastcall neogeoReadByteTransfer(UINT32 sekAddress) +{ +// if ((sekAddress & 0x0FFFFF) < 16) +// printf(PRINT_NORMAL, _T(" - NGCD port 0x%06X read (byte, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + sekAddress ^= 1; + + switch (nActiveTransferArea) { + case 0: // Sprites + return NeoSpriteRAM[nSpriteTransferBank + (sekAddress & 0x0FFFFF)]; + break; + case 1: // ADPCM + return YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)]; + break; + case 4: // Z80 + if ((sekAddress & 0xfffff) >= 0x20000) break; + return NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1]; + break; + case 5: // Text + return NeoTextRAM[(sekAddress & 0x3FFFF) >> 1]; + break; + } + + return ~0; +} + +UINT16 __fastcall neogeoReadWordTransfer(UINT32 sekAddress) +{ +// if ((sekAddress & 0x0FFFFF) < 16) +// bprintf(PRINT_NORMAL, _T(" - Transfer: 0x%06X read (word, PC: 0x%06X)\n"), sekAddress, SekGetPC(-1)); + + switch (nActiveTransferArea) { + case 0: // Sprites + return *((UINT16*)(NeoSpriteRAM + nSpriteTransferBank + (sekAddress & 0xFFFFF))); + break; + case 1: // ADPCM + return 0xFF00 | YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)]; + break; + case 4: // Z80 + if ((sekAddress & 0xfffff) >= 0x20000) break; + return 0xFF00 | NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1]; + break; + case 5: // Text + return 0xFF00 | NeoTextRAM[(sekAddress & 0x3FFFF) >> 1]; + break; + } + + return ~0; +} + +void __fastcall neogeoWriteByteTransfer(UINT32 sekAddress, UINT8 byteValue) +{ +// if ((sekAddress & 0x0FFFFF) < 16) +// bprintf(PRINT_NORMAL, _T(" - Transfer: 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + + if (!nTransferWriteEnable) { +// return; + } + + sekAddress ^= 1; + + switch (nActiveTransferArea) { + case 0: // Sprites + NeoSpriteRAM[nSpriteTransferBank + (sekAddress & 0x0FFFFF)] = byteValue; + NeoCDOBJBankUpdate[nSpriteTransferBank >> 20] = true; + break; + case 1: // ADPCM + YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = byteValue; + break; + case 4: // Z80 + if ((sekAddress & 0xfffff) >= 0x20000) break; + NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1] = byteValue; + break; + case 5: // Text + NeoTextRAM[(sekAddress & 0x3FFFF) >> 1] = byteValue; +// NeoUpdateTextOne((sekAddress & 0x3FFFF) >> 1, byteValue); + break; + } +} + +void __fastcall neogeoWriteWordTransfer(UINT32 sekAddress, UINT16 wordValue) +{ +// if ((sekAddress & 0x0FFFFF) < 16) +// bprintf(PRINT_NORMAL, _T(" - Transfer: 0x%06X -> 0x%04X (PC: 0x%06X)\n"), sekAddress, wordValue, SekGetPC(-1)); + + if (!nTransferWriteEnable) { +// return; + } + + switch (nActiveTransferArea) { + case 0: // Sprites + *((UINT16*)(NeoSpriteRAM + nSpriteTransferBank + (sekAddress & 0xFFFFF))) = wordValue; + NeoCDOBJBankUpdate[nSpriteTransferBank >> 20] = true; + break; + case 1: // ADPCM + YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = wordValue; + break; + case 4: // Z80 + // The games that write here, seem to write crap, however the BIOS writes the Z80 code here, and not in the byte area + // So basically, we are allowing writes to here, until the BIOS has finished writing the program, then not allowing any further writes + if (((sekAddress & 0xfffff) >= 0x20000) || nNeoCDZ80ProgWriteWordCancelHack) break; + if (sekAddress == 0xe1fdf2) nNeoCDZ80ProgWriteWordCancelHack = 1; + NeoZ80ROMActive[(sekAddress & 0x1FFFF) >> 1] = wordValue; + break; + case 5: // Text + NeoTextRAM[(sekAddress & 0x3FFFF) >> 1] = wordValue; +// NeoUpdateTextOne((sekAddress & 0x3FFFF) >> 1, wordValue); + break; + } +} + +// 68K memory + +void __fastcall neogeoWriteWord68KProgram(UINT32 sekAddress, UINT16 wordValue) +{ +// if (sekAddress < 16) +// bprintf(PRINT_NORMAL, _T(" - 68K: 0x%06X -> 0x%04X (PC: 0x%06X)\n"), sekAddress, wordValue, SekGetPC(-1)); + + *((UINT16*)(Neo68KROMActive + sekAddress)) = wordValue; + if (sekAddress >= 0x0100) { + *((UINT16*)(NeoVectorActive + sekAddress)) = wordValue; + } +} + +void __fastcall neogeoWriteByte68KProgram(UINT32 sekAddress, UINT8 byteValue) +{ +// if (sekAddress < 16) +// bprintf(PRINT_NORMAL, _T(" - 68K: 0x%06X -> 0x%02X (PC: 0x%06X)\n"), sekAddress, byteValue, SekGetPC(-1)); + + Neo68KROMActive[sekAddress ^ 1] = byteValue; + if (sekAddress >= 0x0100) { + NeoVectorActive[sekAddress ^ 1] = byteValue; + } +} + +// ---------------------------------------------------------------------------- + +// for NeoGeo CD (WAV playback) +void wav_exit(); + +static INT32 neogeoReset() +{ + if (nNeoSystemType & NEO_SYS_CART) { + NeoLoad68KBIOS(NeoSystem & 0x1f); + + if (nBIOS == -1 || nBIOS == 23) { + // Write system type & region code into BIOS ROM + *((UINT16*)(Neo68KBIOS + 0x000400)) = ((NeoSystem & 4) << 13) | (NeoSystem & 0x03); + } + +#if 1 && defined FBA_DEBUG + if (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SNK_DEDICATED_PCB) && (BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) != HARDWARE_SNK_TRACKBALL) { + switch (NeoSystem & 0x1f) { + case 0x00: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Asia/Europe ver. 6 (1 slot) BIOS\n")); break; } + case 0x01: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Asia/Europe ver. 5 (1 slot) BIOS\n")); break; } + case 0x02: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Asia/Europe ver. 3 (4 slot) BIOS\n")); break; } + case 0x03: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS USA ver. 5 (2 slot) BIOS\n")); break; } + case 0x04: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS USA ver. 5 (6 slot) BIOS\n")); break; } + case 0x05: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Japan ver. 6 (? slot) BIOS\n")); break; } + case 0x06: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Japan ver. 5 (? slot) BIOS\n")); break; } + case 0x07: { bprintf(PRINT_IMPORTANT, _T("Emulating using MVS Japan ver. 3 (4 slot) BIOS\n")); break; } + case 0x08: { bprintf(PRINT_IMPORTANT, _T("Emulating using NEO-MVH MV1C BIOS\n")); break; } + case 0x09: { bprintf(PRINT_IMPORTANT, _T("MVS Japan (J3)\n")); break; } + case 0x0a: { bprintf(PRINT_IMPORTANT, _T("Emulating using AES Japan BIOS\n")); break; } + case 0x0b: { bprintf(PRINT_IMPORTANT, _T("Emulating using AES Asia BIOS\n")); break; } + case 0x0c: { bprintf(PRINT_IMPORTANT, _T("Emulating using Development Kit BIOS\n")); break; } + case 0x0d: { bprintf(PRINT_IMPORTANT, _T("Emulating using Deck ver. 6 (Git Ver 1.3) BIOS\n")); break; } + case 0x0e: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 2.3 BIOS\n")); break; } + case 0x0f: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 2.3 (alt) BIOS\n")); break; } + case 0x10: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 2.2 BIOS\n")); break; } + case 0x11: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 2.1 BIOS\n")); break; } + case 0x12: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 2.0 BIOS\n")); break; } + case 0x13: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 1.3 BIOS\n")); break; } + case 0x14: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 1.2 BIOS\n")); break; } + case 0x15: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 1.2 (alt) BIOS\n")); break; } + case 0x16: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 1.1 BIOS\n")); break; } + case 0x17: { bprintf(PRINT_IMPORTANT, _T("Emulating using Universe BIOS ver. 1.0 BIOS\n")); break; } + case 0x18: { bprintf(PRINT_IMPORTANT, _T("Emulating using NeoOpen BIOS v0.1 beta BIOS\n")); break; } + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK) == HARDWARE_SNK_TRACKBALL) { + bprintf(PRINT_IMPORTANT, _T("Emulating using custom Trackball BIOS\n")); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + bprintf(PRINT_IMPORTANT, _T("Emulating using custom PCB BIOS\n")); + } +#endif + + OldDebugDip[0] = NeoDebugDip[0] = 0; + OldDebugDip[1] = NeoDebugDip[1] = 0; + } + +#if 1 && defined FBA_DEBUG + if (nNeoSystemType & NEO_SYS_CD) { + bprintf(PRINT_IMPORTANT, _T(" - Emulating Neo CD system.\n")); + + // exit WAV object if needed + wav_exit(); + + nNeoCDZ80ProgWriteWordCancelHack = 0; + } +#endif + + NeoSetSystemType(); + + bSRAMWritable = false; + + bNeoEnableGraphics = true; + + bBIOSTextROMEnabled = false; + bZ80BoardROMBankedIn = false; + b68KBoardROMBankedIn = true; + + nNeoPaletteBank = -1; + + nSpriteFrameSpeed = 4; + nSpriteFrameTimer = 0; + nNeoSpriteFrame = 0; + + nIRQAcknowledge = ~0; + bIRQEnabled = false; + + nSoundLatch = 0x00; + nSoundReply = 0x00; + nSoundStatus = 1; + +#if 1 && defined USE_SPEEDHACKS + nSoundPrevReply = -1; +#endif + + nIRQOffset = 0; + nIRQControl = 0; + + nInputSelect = 0; + NeoInputBank = NeoInput; + + nCyclesExtra[0] = nCyclesExtra[1] = 0; + + { + SekOpen(0); + ZetOpen(0); + + if (nNeoSystemType & NEO_SYS_MVS) { + for (INT32 a = 0xD00000; a < 0xE00000; a += 0x010000) { + SekMapMemory(NeoNVRAM, a, a + 0xFFFF, SM_RAM); // 68K RAM + } + SekMapHandler(1, 0xD00000, 0xDFFFFF, SM_WRITE); // + } else { + SekMapHandler(0, 0xD00000, 0xDFFFFF, SM_RAM); // AES/NeoCD don't have the SRAM + } + + if (nNeoSystemType & NEO_SYS_CART) { + NeoMapActiveCartridge(); + } + + if (nNeoSystemType & NEO_SYS_PCB) { + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_KOF2K3) { + SekMapMemory(Neo68KBIOS, 0xC00000, 0xC7FFFF, SM_ROM); + SekMapMemory(Neo68KBIOS, 0xC80000, 0xCFFFFF, SM_ROM); + } else { + for (INT32 a = 0xC00000; a < 0xD00000; a += 0x020000) { + SekMapMemory(Neo68KBIOS + (NeoSystem & 0x03) * 0x020000, a, a + 0x01FFFF, SM_ROM); + } + } + } + + // Set by a switch on the PCB + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "svcpcb") || !strcmp(BurnDrvGetTextA(DRV_NAME), "svcpcba") || !strcmp(BurnDrvGetTextA(DRV_NAME), "svcpcbnd") || !strcmp(BurnDrvGetTextA(DRV_NAME), "ms5pcb") || !strcmp(BurnDrvGetTextA(DRV_NAME), "ms5pcbnd")) { + SekMapMemory(Neo68KBIOS + 0x20000 * (~NeoSystem & 1), 0xc00000, 0xc1ffff, SM_ROM); + } + + MapVectorTable(true); + + if (nNeoSystemType & NEO_SYS_CD) { + nActiveTransferArea = -1; + nSpriteTransferBank = -1; + nADPCMTransferBank = -1; + + NeoCDCommsReset(); + + nTransferWriteEnable = 0; + + NeoSetTextSlot(0); + NeoSetSpriteSlot(0); + + memset(NeoCDOBJBankUpdate, 0, sizeof(NeoCDOBJBankUpdate)); + + LC8951Reset(); + } + + ZetSetBUSREQLine(0); + + SekReset(); + ZetReset(); + + MapPalette(0); + + ZetClose(); + SekClose(); + } + + BurnYM2610Reset(); + +#if defined EMULATE_WATCHDOG + nNeoWatchdog = 0; +#endif + + nIRQCycles = NO_IRQ_PENDING; + + nNeoCDIRQVector = 0; + nNeoCDIRQVectorAck = 0; + nff0002 = 0; + + return 0; +} + +static void SwitchToMusashi() +{ + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } +} + +static INT32 NeoInitCommon() +{ + BurnSetRefreshRate(NEO_VREFRESH); + INT32 nNeoScreenHeight; // not used + BurnDrvGetFullSize(&nNeoScreenWidth, &nNeoScreenHeight); + + if (nNeoSystemType & NEO_SYS_CART) { + nVBLankIRQ = 1; + nScanlineIRQ = 2; + } else { + nVBLankIRQ = 2; + nScanlineIRQ = 1; + } + + // Allocate all memory is needed for RAM + { + INT32 nLen; + + RAMIndex(); // Get amount of memory needed + nLen = RAMEnd - (UINT8*)0; + if ((AllRAM = (UINT8*)malloc(nLen)) == NULL) { // Allocate memory + return 1; + } + memset(AllRAM, 0, nLen); // Initialise memory + RAMIndex(); // Index the allocated memory + } + + if (nNeoSystemType & NEO_SYS_CD) { + SwitchToMusashi(); + } + + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + ZetInit(1); + ZetOpen(0); + + { + if (nNeoSystemType & NEO_SYS_CD) { + SekSetIrqCallback(NeoCDIRQCallback); + } + + SekSetCyclesScanline((INT32)(12000000.0 / NEO_HREFRESH)); + + // Map 68000 memory: + + if (nNeoSystemType & NEO_SYS_CART) { + + for (INT32 a = 0x100000; a < 0x200000; a += 0x010000) { + SekMapMemory(Neo68KRAM, a, a + 0xFFFF, SM_RAM); // 68K RAM + } + + if (!(nNeoSystemType & NEO_SYS_PCB)) { +// for (INT32 a = 0xC00000; a < 0xD00000; a += 0x020000) { +// SekMapMemory(Neo68KBIOS, a, a + 0x01FFFF, SM_ROM); // MVS/AES BIOS ROM +// } + SekMapMemory(Neo68KBIOS, 0xC00000, 0xC7FFFF, SM_ROM); // BIOS ROM + } + + } else { + SekMapMemory(Neo68KFix[0], 0x000000, 0x1FFFFF, SM_RAM); // Main 68K RAM + SekMapMemory(Neo68KBIOS, 0xC00000, 0xC7FFFF, SM_ROM); // NeoCD BIOS ROM + SekMapMemory(Neo68KBIOS, 0xC80000, 0xCFFFFF, SM_ROM); // + } + + SekSetReadWordHandler(0, neogeoReadWord); + SekSetReadByteHandler(0, neogeoReadByte); + SekSetWriteWordHandler(0, neogeoWriteWord); + SekSetWriteByteHandler(0, neogeoWriteByte); + + SekSetWriteWordHandler(1, neogeoWriteWordSRAM); + SekSetWriteByteHandler(1, neogeoWriteByteSRAM); + + if (!(nNeoSystemType & NEO_SYS_PCB)) { + SekMapHandler(2, 0x800000, 0xBFFFFF, SM_ROM); // Memory card + SekMapHandler(2, 0x800000, 0xBFFFFF, SM_WRITE); // + + SekSetReadByteHandler(2, neogeoReadByteMemoryCard); + SekSetWriteByteHandler(2, neogeoWriteByteMemoryCard); + } + + SekMapHandler(3, 0x400000, 0x7FFFFF, SM_WRITE); // Palette + + SekSetWriteWordHandler(3, NeoPalWriteWord); + SekSetWriteByteHandler(3, NeoPalWriteByte); + + // Set up mirrors + for (INT32 a = 0x420000; a < 0x800000; a += 0x2000) { + SekMapMemory(NeoPalSrc[0], a, a + 0x1FFF, SM_ROM); + } + + SekMapHandler(5, 0x3C0000, 0x3DFFFF, SM_RAM); // Read Video Controller + SekSetReadWordHandler(5, neogeoReadWordVideo); + SekSetReadByteHandler(5, neogeoReadByteVideo); + SekSetWriteWordHandler(5, neogeoWriteWordVideo); + SekSetWriteByteHandler(5, neogeoWriteByteVideo); + + if (nNeoSystemType & NEO_SYS_CD) { + SekMapHandler(4, 0x000000, 0x0003FF, SM_WRITE); + + SekSetWriteWordHandler(4, neogeoWriteWord68KProgram); + SekSetWriteByteHandler(4, neogeoWriteByte68KProgram); + + SekMapHandler(6, 0xE00000, 0xEFFFFF, SM_RAM); + + SekSetReadWordHandler(6, neogeoReadWordTransfer); + SekSetReadByteHandler(6, neogeoReadByteTransfer); + SekSetWriteWordHandler(6, neogeoWriteWordTransfer); + SekSetWriteByteHandler(6, neogeoWriteByteTransfer); + + SekMapHandler(7, 0xF00000, 0xFFFFFF, SM_RAM); + + SekSetReadWordHandler(7, neogeoReadWordCDROM); + SekSetReadByteHandler(7, neogeoReadByteCDROM); + SekSetWriteWordHandler(7, neogeoWriteWordCDROM); + SekSetWriteByteHandler(7, neogeoWriteByteCDROM); + + SekSetReadByteHandler(2, neoCDReadByteMemoryCard); + SekSetWriteByteHandler(2, neoCDWriteByteMemoryCard); + + } + } + + { + // Z80 setup + + if (nNeoSystemType & NEO_SYS_CART) { + // Work RAM + ZetMapArea(0xF800, 0xFFFF, 0, NeoZ80RAM); + ZetMapArea(0xF800, 0xFFFF, 1, NeoZ80RAM); + ZetMapArea(0xF800, 0xFFFF, 2, NeoZ80RAM); + + ZetMemEnd(); + + ZetSetInHandler(neogeoZ80In); + ZetSetOutHandler(neogeoZ80Out); + } + + if (nNeoSystemType & NEO_SYS_CD) { + // Main Z80 RAM + ZetMapArea(0x0000, 0xFFFF, 0, NeoZ80ROMActive); + ZetMapArea(0x0000, 0xFFFF, 1, NeoZ80ROMActive); + ZetMapArea(0x0000, 0xFFFF, 2, NeoZ80ROMActive); + + ZetMemEnd(); + + ZetSetInHandler(neogeoZ80InCD); + ZetSetOutHandler(neogeoZ80Out); + } + } + + ZetClose(); + SekClose(); + +#if defined USE_SPEEDHACKS + bRenderLineByLine = false; +#else + bRenderLineByLine = false; +#endif + +#if defined RASTER_KLUDGE + nScanlineOffset = 0xF8; // correct as verified on MVS hardware +#endif + + // These games rely on reading the line counter for synchronising raster effects + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "mosyougi")) { + bRenderLineByLine = true; + +#if defined RASTER_KLUDGE + nScanlineOffset = 0xFB; +#endif + + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "neodrift")) { + bRenderLineByLine = true; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "zedblade")) { + bRenderLineByLine = true; + } +// if (!strcmp(BurnDrvGetTextA(DRV_NAME), "ssideki2")) { +// bRenderLineByLine = true; +// } + + nNeoControlConfig = BurnDrvGetHardwareCode() & HARDWARE_SNK_CONTROLMASK; + + // Hook up standard joysticks to all ports + for (INT32 i = 0; i < 8; i++) { + nJoyport0[i] = 0; + nJoyport1[i] = 1; + } + + if (nNeoSystemType & NEO_SYS_CD) { + nJoyport0[4] = 16; + nJoyport1[4] = 17; + } else { + // Override for special controllers + switch (nNeoControlConfig) { + case HARDWARE_SNK_PADDLE: // Two Paddles + joysticks + nJoyport0[0] = 6; + nJoyport1[0] = 7; + break; + case HARDWARE_SNK_TRACKBALL: // Trackball controller + nJoyport0[0] = 6; + nJoyport0[1] = 7; + break; + case HARDWARE_SNK_MAHJONG: // Mahjong controller + nJoyport0[1] = 16; + nJoyport0[2] = 17; + nJoyport0[4] = 18; + break; + } + } + +#if defined Z80_SPEED_ADJUST + nZ80Clockspeed = 4000000; +#endif + + if (nNeoSystemType & NEO_SYS_CART) { + BurnYM2610Init(8000000, YM2610ADPCMAROM[0], &nYM2610ADPCMASize[0], YM2610ADPCMBROM[0], &nYM2610ADPCMBSize[0], &neogeoFMIRQHandler, neogeoSynchroniseStream, neogeoGetTime, 0); + } else { + BurnYM2610Init(8000000, YM2610ADPCMBROM[0], &nYM2610ADPCMBSize[0], YM2610ADPCMBROM[0], &nYM2610ADPCMBSize[0], &neogeoFMIRQHandler, neogeoSynchroniseStream, neogeoGetTime, 0); + } + + BurnTimerAttachZet(nZ80Clockspeed); + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + for (nNeoActiveSlot = 0; nNeoActiveSlot < MAX_SLOT; nNeoActiveSlot++) { + if (nBurnDrvSelect[nNeoActiveSlot] < nBurnDrvCount) { +// NeoInitText(nNeoActiveSlot); +// NeoInitSprites(nNeoActiveSlot); + } + } + + NeoInitText(-1); + + } else { + NeoInitText(0); + NeoInitText(-1); + NeoInitSprites(0); + } + + if (nNeoSystemType & NEO_SYS_CART) { + ZetOpen(0); + nZ80Bank0 = nZ80Bank1 = nZ80Bank2 = nZ80Bank3 = -1; + NeoZ80SetBank0(0x02); + NeoZ80SetBank1(0x06); + NeoZ80SetBank2(0x0E); + NeoZ80SetBank3(0x1E); + + NeoZ80MapROM(false); + ZetClose(); + } + + NeoInitPalette(); + + uPD4990AInit(12000000); + nPrevBurnCPUSpeedAdjust = -1; + + if (nNeoSystemType & NEO_SYS_CD) { + bMemoryCardInserted = true; + bMemoryCardWritable = true; + } else { + bMemoryCardInserted = false; + bMemoryCardWritable = false; + } + + nNeoActiveSlot = 0; + neogeoReset(); // Reset machine + + return 0; +} + +static bool recursing = false; + +INT32 NeoInit() +{ + if (recursing) { + if (LoadRoms()) { + return 1; + } + return 0; + } + + recursing = true; + + nNeoSystemType = NEO_SYS_CART; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + nNeoSystemType |= NEO_SYS_MVS | NEO_SYS_PCB; + } + + nNeoActiveSlot = 0; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + UINT32 nDriver = nBurnDrvActive; + +// memset(NeoCallback, 0, sizeof(NeoCallback)); + + for (nNeoActiveSlot = 0; nNeoActiveSlot < MAX_SLOT; nNeoActiveSlot++) { + + if (nBurnDrvSelect[nNeoActiveSlot] < nBurnDrvCount) { + + nBurnDrvActive = nBurnDrvSelect[nNeoActiveSlot]; + NeoCallbackActive = &NeoCallback[nNeoActiveSlot]; + + if (BurnDrvCartridgeSetup(CART_INIT_START)) { + return 1; + } + + NeoInitText(nNeoActiveSlot); + NeoInitSprites(nNeoActiveSlot); + } + } + + for (nNeoNumSlots = 5; nNeoNumSlots > 0 && nBurnDrvSelect[nNeoNumSlots] >= nBurnDrvCount; nNeoNumSlots--) { } + + switch (nNeoNumSlots) { + case 0: + nNeoNumSlots = 1; + break; + case 1: + nNeoNumSlots = 2; + break; + case 2: + case 3: + nNeoNumSlots = 4; + break; + case 4: + case 5: + nNeoNumSlots = 6; + break; + } + + nBurnDrvActive = nDriver; + + if (BurnDrvCartridgeSetup(CART_INIT_END)) { + return 1; + } + + } else { + if (LoadRoms()) { + return 1; + } + } + + recursing = false; + + for (nNeoActiveSlot = 0; nNeoActiveSlot < nNeoNumSlots; nNeoActiveSlot++) { + NeoVector[nNeoActiveSlot] = (UINT8*)malloc(0x0400); + if (NeoVector[nNeoActiveSlot] == NULL) { + return 1; + } + memset(NeoVector[nNeoActiveSlot], 0, 0x0400); + } + + // Allocate all memory needed for ROM + { + INT32 nLen; + + ROMIndex(); // Get amount of memory needed + nLen = ROMEnd - (UINT8*)0; + if ((AllROM = (UINT8*)malloc(nLen)) == NULL) { // Allocate memory + return 1; + } + memset(AllROM, 0, nLen); // Initialise memory + ROMIndex(); // Index the allocated memory + } + + if (nNeoSystemType & NEO_SYS_PCB) { + BurnLoadRom(Neo68KBIOS, 0x00080 + 26, 1); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + BurnLoadRom(NeoZ80BIOS, 0x00000 + 27, 1); + BurnLoadRom(NeoTextROMBIOS, 0x00000 + 28, 1); + BurnLoadRom(NeoZoomROM, 0x00000 + 29, 1); + } else { + + // Still load the Z80 BIOS & text layer data for AES systems, since it might be switched to MVS later + + if (nNeoSystemType & NEO_SYS_PCB) { + bZ80BIOS = false; + BurnLoadRom(NeoTextROMBIOS, 0x00080 + 28, 1); + BurnLoadRom(NeoZoomROM, 0x00080 + 29, 1); + } else { + BurnLoadRom(NeoZ80BIOS, 0x00080 + 27, 1); + BurnLoadRom(NeoTextROMBIOS, 0x00080 + 28, 1); + BurnLoadRom(NeoZoomROM, 0x00080 + 29, 1); + } + } + BurnUpdateProgress(0.0, _T("Preprocessing text layer graphics...")/*, BST_PROCESS_TXT*/, 0); + NeoDecodeTextBIOS(0, 0x020000, NeoTextROMBIOS); + + nBIOS = 9999; + if (NeoLoad68KBIOS(NeoSystem & 0x1f)) { + return 1; + } + + return NeoInitCommon(); +} + +INT32 NeoCDInit() +{ + recursing = false; + + nNeoSystemType = NEO_SYS_CD; + + nCodeSize[0] = 0x200000; + nSpriteSize[0] = 0x400000; + nNeoTextROMSize[0] = 0x020000; + nYM2610ADPCMASize[0] = 0; + nYM2610ADPCMBSize[0] = 0x100000; + + // Allocate all memory is needed for ROM + { + INT32 nLen; + + ROMIndex(); // Get amount of memory needed + nLen = ROMEnd - (UINT8*)0; + if ((AllROM = (UINT8*)malloc(nLen)) == NULL) { // Allocate memory + return 1; + } + memset(AllROM, 0, nLen); // Initialise memory + ROMIndex(); // Index the allocated memory + } + + Neo68KROMActive = Neo68KROM[0]; + NeoVectorActive = NeoVector[0]; + NeoZ80ROMActive = NeoZ80ROM[0]; + + Neo68KFix[0] = Neo68KROM[0]; + + BurnLoadRom(Neo68KBIOS, 0, 1); + BurnLoadRom(NeoZoomROM, 1, 1); + + // Create copy of 68K with BIOS vector table + memcpy(NeoVectorActive + 0x00, Neo68KBIOS, 0x0100); + + // Create a default program for the Z80 + NeoZ80ROMActive[0] = 0xC3; // JP 0 + NeoZ80ROMActive[1] = 0x00; // + NeoZ80ROMActive[2] = 0x00; // + + bZ80BIOS = false; + + for (nNeoTileMask[0] = 1; nNeoTileMask[0] < nSpriteSize[0]; nNeoTileMask[0] <<= 1) { } + nNeoTileMask[0] = (nNeoTileMask[0] >> 7) - 1; + nNeoMaxTile[0] = nSpriteSize[0] >> 7; + + return NeoInitCommon(); +} + +INT32 NeoExit() +{ + if (recursing) { + return 0; + } + + recursing = true; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + UINT32 nDriver = nBurnDrvActive; + + for (nNeoActiveSlot = 0; nNeoActiveSlot < MAX_SLOT; nNeoActiveSlot++) { + + if (nBurnDrvSelect[nNeoActiveSlot] < nBurnDrvCount) { + + nBurnDrvActive = nBurnDrvSelect[nNeoActiveSlot]; + + if (BurnDrvCartridgeSetup(CART_EXIT)) { + return 1; + } + } + } + + nBurnDrvActive = nDriver; + } + + uPD4990AExit(); + + NeoExitPalette(); + + BurnYM2610Exit(); + + ZetExit(); // Deallocate Z80 + SekExit(); // Deallocate 68000 + + if (nNeoSystemType & NEO_SYS_CART) { + + // Deallocate all used memory + + for (nNeoActiveSlot = 0; nNeoActiveSlot < MAX_SLOT; nNeoActiveSlot++) { + + NeoExitSprites(nNeoActiveSlot); + NeoExitText(nNeoActiveSlot); + + if (NeoTextROM[nNeoActiveSlot]) { + free(NeoTextROM[nNeoActiveSlot]); // Text ROM + NeoTextROM[nNeoActiveSlot] = NULL; + } + nNeoTextROMSize[nNeoActiveSlot] = 0; + + if (NeoSpriteROM[nNeoActiveSlot]) { + free(NeoSpriteROM[nNeoActiveSlot]); // Sprite ROM + NeoSpriteROM[nNeoActiveSlot] = NULL; + } + + if (Neo68KROM[nNeoActiveSlot]) { + free(Neo68KROM[nNeoActiveSlot]); // 68K ROM + Neo68KROM[nNeoActiveSlot] = NULL; + } + if (NeoVector[nNeoActiveSlot]) { + free(NeoVector[nNeoActiveSlot]); // 68K vectors + NeoVector[nNeoActiveSlot] = NULL; + } + + if (NeoZ80ROM[nNeoActiveSlot]) { + free(NeoZ80ROM[nNeoActiveSlot]); // Z80 ROM + NeoZ80ROM[nNeoActiveSlot] = NULL; + } + + if (YM2610ADPCMAROM[nNeoActiveSlot]) { // ADPCM data + free(YM2610ADPCMAROM[nNeoActiveSlot]); + YM2610ADPCMAROM[nNeoActiveSlot] = NULL; + } + if (YM2610ADPCMAROM[nNeoActiveSlot]) { + free(YM2610ADPCMBROM[nNeoActiveSlot]); + YM2610ADPCMBROM[nNeoActiveSlot] = NULL; + } + } + } + + if (AllROM) { + free(AllROM); // Misc ROM + AllROM = NULL; + } + + if (AllRAM) { + free(AllRAM); // Misc RAM + AllRAM = NULL; + } + + memset(NeoCallback, 0, sizeof(NeoCallback)); + NeoCallbackActive = &NeoCallback[0]; + + nNeoTextROMSize[0] = 0; + + nBIOS = 9999; + + nNeoActiveSlot = 0; + NeoVectorActive = NULL; + Neo68KROMActive = NULL; + NeoZ80ROMActive = NULL; + + nCodeSize[0] = 0; + + nNeoCDZ80ProgWriteWordCancelHack = 0; + + // Switch back CPU core if needed + if (nNeoSystemType & NEO_SYS_CD) { + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + } + + recursing = false; + + // release the NeoGeo CD information object if needed + NeoCDInfo_Exit(); + + return 0; +} + +INT32 NeoRender() +{ + NeoUpdatePalette(); // Update the palette + NeoClearScreen(); + + if (bNeoEnableGraphics) { + nSliceStart = 0x10; nSliceEnd = 0xF0; + nSliceSize = nSliceEnd - nSliceStart; + +#if 0 || defined LOG_DRAW + bprintf(PRINT_NORMAL, _T(" -- Drawing slice: %3i - %3i.\n"), nSliceStart, nSliceEnd); +#endif + + NeoRenderSprites(); // Render sprites + NeoRenderText(); // Render text layer + } + + return 0; +} + +inline static void NeoClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0C) == 0x0C) { + *nJoystickInputs &= ~0x0C; + } +} + +static void NeoStandardInputs(INT32 nBank) +{ + if (nBank) { + NeoInput[ 8] = 0x00; // Player 1 + NeoInput[ 9] = 0x00; // Player 2 + NeoInput[10] = 0x00; // Buttons + NeoInput[11] = 0x00; // + for (INT32 i = 0; i < 8; i++) { + NeoInput[ 8] |= (NeoJoy3[i] & 1) << i; + NeoInput[ 9] |= (NeoJoy4[i] & 1) << i; + NeoInput[10] |= (NeoButton3[i] & 1) << i; + NeoInput[11] |= (NeoButton4[i] & 1) << i; + } + NeoClearOpposites(&NeoInput[ 8]); + NeoClearOpposites(&NeoInput[ 9]); + + if (NeoDiag[1]) { + NeoInput[13] |= 0x80; + } + } else { + NeoInput[ 0] = 0x00; // Player 1 + NeoInput[ 1] = 0x00; // Player 2 + NeoInput[ 2] = 0x00; // Buttons + NeoInput[ 3] = 0x00; // + for (INT32 i = 0; i < 8; i++) { + NeoInput[ 0] |= (NeoJoy1[i] & 1) << i; + NeoInput[ 1] |= (NeoJoy2[i] & 1) << i; + NeoInput[ 2] |= (NeoButton1[i] & 1) << i; + NeoInput[ 3] |= (NeoButton2[i] & 1) << i; + } + NeoClearOpposites(&NeoInput[ 0]); + NeoClearOpposites(&NeoInput[ 1]); + + if (NeoDiag[0]) { + NeoInput[ 5] |= 0x80; + } + } +} + +#if 1 +#define NeoSekRun SekRun +#else +static INT32 NeoSekRun(const INT32 nCycles) +{ + INT32 nCyclesExecutedTotal = 0, nOldCyclesSegment = nCyclesSegment; + + if (!(nNeoSystemType & NEO_SYS_CD) || !(nff0002 & 0x0050)) + return SekRun(nCycles); + +//bprintf(PRINT_NORMAL, _T("***\n")); + + while (nCyclesExecutedTotal < nCycles) { + + INT32 nCyclesExecuted; + + if (nNeoCDCyclesIRQ <= 0) { + nNeoCDCyclesIRQ += nNeoCDCyclesIRQPeriod; + + // Trigger CD mechanism communication interrupt +//bprintf(PRINT_NORMAL, _T(" DECI status %i\n"), (LC8951RegistersR[1] & 0x20) >> 5); + + nIRQAcknowledge &= ~0x10; + NeoCDIRQUpdate(0); + + if ((nff0002 & 0x0500) && (LC8951RegistersR[1] & 0x20)) + NeoCDReadSector(); + } + + nCyclesSegment = (nNeoCDCyclesIRQ < (nCycles - nCyclesExecutedTotal)) ? nNeoCDCyclesIRQ : (nCycles - nCyclesExecutedTotal); + nCyclesExecuted = SekRun(nCyclesSegment); + +//bprintf(PRINT_NORMAL, _T("%010i %010i %010i %010i\n"), nCycles, nCyclesExecutedTotal, nCyclesExecuted, nNeoCDCyclesIRQ); + + nCyclesExecutedTotal += nCyclesExecuted; + nNeoCDCyclesIRQ -= nCyclesExecuted; + + } + + nCyclesSegment = nOldCyclesSegment; + + return nCyclesExecutedTotal; +} +#endif + +INT32 NeoFrame() +{ + if (NeoReset) { // Reset machine + if (nNeoSystemType & NEO_SYS_CART) { + memset(Neo68KRAM, 0, 0x010000); + } + + neogeoReset(); + } + + NeoInput[ 5] &= 0x1F; // Clear ports + NeoInput[13] = 0x00; // + + switch (nNeoControlConfig) { + case HARDWARE_SNK_PADDLE: { // Two Paddles + joysticks + + NeoStandardInputs(0); + + // Handle analog controls + nAnalogAxis[0] -= NeoAxis[0]; + nAnalogAxis[1] -= NeoAxis[1]; + NeoInput[6] = (nAnalogAxis[0] >> 8) & 0xFF; + NeoInput[7] = (nAnalogAxis[1] >> 8) & 0xFF; + + break; + } + + case HARDWARE_SNK_TRACKBALL: { // Trackball controller + NeoInput[1] = 0x00; // Buttons + NeoInput[2] = 0x00; // + NeoInput[3] = 0x00; // + for (INT32 i = 0; i < 8; i++) { + NeoInput[1] |= (NeoJoy2[i] & 1) << i; + NeoInput[2] |= (NeoButton1[i] & 1) << i; + NeoInput[3] |= (NeoButton2[i] & 1) << i; + } + // Handle analog controls + nAnalogAxis[0] += NeoAxis[0]; + nAnalogAxis[1] += NeoAxis[1]; + NeoInput[6] = (nAnalogAxis[0] >> 8) & 0xFF; + NeoInput[7] = (nAnalogAxis[1] >> 8) & 0xFF; + + if (NeoDiag[0]) { + NeoInput[5] |= 0x80; + } + + break; + } + + case HARDWARE_SNK_4_JOYSTICKS: { // Four joystick controllers + + NeoStandardInputs(0); + NeoStandardInputs(1); + + break; + } + + case HARDWARE_SNK_MAHJONG: { // Mahjong controller + + NeoStandardInputs(0); + + NeoInput[16] = 0x00; + NeoInput[17] = 0x00; + NeoInput[18] = 0x00; + for (INT32 i = 0; i < 7; i++) { + NeoInput[16] |= (NeoButton1[i + 8] & 1) << i; + NeoInput[17] |= (NeoButton1[i + 16] & 1) << i; + NeoInput[18] |= (NeoButton1[i + 24] & 1) << i; + } + + break; + } + + case HARDWARE_SNK_GAMBLING: { // Gambling configuration + + NeoStandardInputs(0); + +/* NeoInput[16] = 0x00; + for (INT32 i = 0; i < 7; i++) { + NeoInput[16] |= (NeoButton1[i + 16] & 1) << i; + }*/ + + break; + } + + default: { // Two joystick controllers + NeoStandardInputs(0); + } + } + + if (nNeoSystemType & NEO_SYS_CART) { + + bMemoryCardWritable = (NeoSystem & 0x80); + + if (bMemoryCardInserted) { + NeoInput[2] |= 0x30; // JEIDA connector pen /CD1, /READY + if (bMemoryCardWritable) { + NeoInput[2] |= 0x40; // JEIDA connector pen /WP + } + } + + if (nNeoSystemType & NEO_SYS_AES) { // Report the type of hardware + NeoInput[2] |= 0x80; + } + + if (nNeoControlConfig != HARDWARE_SNK_GAMBLING) { + if (nNeoSystemType & NEO_SYS_MVS) { // Report the appropriate number of slots on MVS hardware + switch (nNeoNumSlots) { + case 4: + NeoInput[ 5] &= ~0x40; + NeoInput[ 3] |= 0x20; + break; + case 6: + NeoInput[ 5] &= ~0x40; + NeoInput[ 3] &= ~0x20; + break; + default: + + // Default to 1/2 slot hardware + + NeoInput[ 5] |= 0x40; + NeoInput[ 3] |= 0x20; + } + } + } + + if (OldDebugDip[0] != NeoDebugDip[0]) { + SekOpen(0); + SekWriteByte(SekReadLong(0x010E) + 0, NeoDebugDip[0]); + SekClose(); + OldDebugDip[0] = NeoDebugDip[0]; + } + if (OldDebugDip[1] != NeoDebugDip[1]) { + SekOpen(0); + SekWriteByte(SekReadLong(0x010E) + 1, NeoDebugDip[1]); + SekClose(); + OldDebugDip[1] = NeoDebugDip[1]; + } + } else { + NeoInput[2] |= 0x70; + + NeoInput[16] = 0x00; + NeoInput[17] = 0x00; + + if (NeoDiag[0]) { + NeoInput[16] = (UINT8)~0xDA; + } + } + + if (nPrevBurnCPUSpeedAdjust != nBurnCPUSpeedAdjust) { + // 68K CPU clock is 12MHz, modified by nBurnCPUSpeedAdjust + nCyclesTotal[0] = (INT32)((INT64)12000000 * nBurnCPUSpeedAdjust / (256.0 * NEO_VREFRESH)); + +#if defined Z80_SPEED_ADJUST + // Z80 CPU clock always 68K / 3 + nCyclesTotal[1] = nCyclesTotal[0] / 3; + nZ80Clockspeed = (INT32)((INT64)4000000 * nBurnCPUSpeedAdjust / 256); + BurnTimerAttachZet(nZ80Clockspeed); +#else + // Z80 CPU clock is always 4MHz + nCyclesTotal[1] = 4000000.0 / NEO_VREFRESH; +#endif + // 68K cycles executed each scanline + SekSetCyclesScanline((INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * NEO_HREFRESH))); + + // uPD499A ticks per second (same as 68K clock) + uPD499ASetTicks((INT64)12000000 * nBurnCPUSpeedAdjust / 256); + + nPrevBurnCPUSpeedAdjust = nBurnCPUSpeedAdjust; + } + +#if defined EMULATE_WATCHDOG + // If the watchdog isn't reset every 8 frames, reset the system + // This can't be 100% accurate, as the 68000 instruction timings are not 100% + if ((nNeoSystemType & NEO_SYS_CART) && nNeoWatchdog > nCyclesTotal[0] * 8) { + bprintf(PRINT_IMPORTANT, _T(" ** Watchdog triggered system reset (PC: 0x%06X)\n"), SekGetPC(-1)); + neogeoReset(); + } +#endif +//bprintf(PRINT_NORMAL, _T("***\n")); + + bRenderImage = false; + bForceUpdateOnStatusRead = false; + + if (pBurnDraw) { + NeoUpdatePalette(); // Update the palette + NeoClearScreen(); + } + nSliceEnd = 0x10; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + // Compensate for extra cycles executed + SekIdle(nCyclesExtra[0]); + ZetIdle(nCyclesExtra[1]); + + nuPD4990ATicks = nCyclesExtra[0]; + + // Run 68000 + + + if ((nNeoSystemType & NEO_SYS_CD) && (nff0002 & 0x0050)) { + nIRQAcknowledge &= ~0x10; + NeoCDIRQUpdate(0); + + if (nff0002 & 0x0500) { + NeoCDReadSector(); + } + } + + + nCyclesSegment = nSekCyclesScanline * 24; + while (SekTotalCycles() < nCyclesSegment) { + + if ((nIRQControl & 0x10) && (nIRQCycles < NO_IRQ_PENDING) && (SekTotalCycles() >= nIRQCycles)) { + + nIRQAcknowledge &= ~2; + SekSetIRQLine(nScanlineIRQ, SEK_IRQSTATUS_ACK); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ triggered (line %3i + %3i cycles).\n"), SekCurrentScanline(), SekTotalCycles() - SekCurrentScanline() * SekCyclesScanline()); +#endif + + if (nIRQControl & 0x80) { + nIRQCycles += NeoConvertIRQPosition(nIRQOffset + 1); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ Line -> %3i (at line %3i, autoload).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + } + } + + if (nCyclesSegment < nIRQCycles || SekTotalCycles() >= nIRQCycles) { + NeoSekRun(nCyclesSegment - SekTotalCycles()); + } else { + NeoSekRun(nIRQCycles - SekTotalCycles()); + } + } + + bRenderImage = pBurnDraw != NULL && bNeoEnableGraphics; + bForceUpdateOnStatusRead = bRenderImage && bRenderLineByLine; + bForcePartialRender = false; + + // Display starts here + + nCyclesVBlank = nSekCyclesScanline * 248; + if (bRenderLineByLine) { + INT32 nLastIRQ = nIRQCycles - 1; + while (SekTotalCycles() < nCyclesVBlank) { + + if ((nIRQControl & 0x10) && (nIRQCycles < NO_IRQ_PENDING) && (nLastIRQ < nIRQCycles) && (SekTotalCycles() >= nIRQCycles)) { + nLastIRQ = nIRQCycles; + nIRQAcknowledge &= ~2; + SekSetIRQLine(nScanlineIRQ, SEK_IRQSTATUS_ACK); +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ triggered (line %3i + %3i cycles).\n"), SekCurrentScanline(), SekTotalCycles() - SekCurrentScanline() * SekCyclesScanline()); +#endif + + if (nIRQControl & 0x80) { + nIRQCycles += NeoConvertIRQPosition(nIRQOffset + 1); +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ Line -> %3i (at line %3i, autoload).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + } + + bForcePartialRender = bRenderImage; + if (bForcePartialRender) { + nSliceStart = nSliceEnd; + nSliceEnd = SekCurrentScanline() - 5; + } + } else { + if (bForcePartialRender) { + nSliceStart = nSliceEnd; + nSliceEnd = SekCurrentScanline() - 6; + } + } + + if (bForcePartialRender) { + + if (nSliceEnd > 240) { + nSliceEnd = 240; + } + nSliceSize = nSliceEnd - nSliceStart; + if (nSliceSize > 0) { + +#if 0 || defined LOG_DRAW + bprintf(PRINT_NORMAL, _T(" -- Drawing slice: %3i - %3i.\n"), nSliceStart, nSliceEnd); +#endif + + NeoRenderSprites(); // Render sprites + } + } + + bForcePartialRender = false; + + if (SekTotalCycles() >= nCyclesSegment) { + nCyclesSegment += nSekCyclesScanline; + } + if (nCyclesSegment < nIRQCycles || SekTotalCycles() >= nIRQCycles) { + NeoSekRun(nCyclesSegment - SekTotalCycles()); + } else { + NeoSekRun(nIRQCycles - SekTotalCycles()); + } + } + } else { + nCyclesSegment = nCyclesVBlank; + while (SekTotalCycles() < nCyclesVBlank) { + + if ((nIRQControl & 0x10) && (nIRQCycles < NO_IRQ_PENDING) && (SekTotalCycles() >= nIRQCycles)) { + nIRQAcknowledge &= ~2; + SekSetIRQLine(nScanlineIRQ, SEK_IRQSTATUS_ACK); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ triggered (line %3i + %3i cycles).\n"), SekCurrentScanline(), SekTotalCycles() - SekCurrentScanline() * SekCyclesScanline()); +#endif + + if (nIRQControl & 0x80) { + nIRQCycles += NeoConvertIRQPosition(nIRQOffset + 1); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ Line -> %3i (at line %3i, autoload).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + } + + bForcePartialRender = bRenderImage; + } + +#if defined RASTERS_OPTIONAL + if (bAllowRasters) { +#endif + if (bForcePartialRender) { + + nSliceStart = nSliceEnd; + nSliceEnd = SekCurrentScanline() - 5; + + if (nSliceEnd > 240) { + nSliceEnd = 240; + } + nSliceSize = nSliceEnd - nSliceStart; + if (nSliceSize > 0) { + +#if 0 || defined LOG_DRAW + bprintf(PRINT_NORMAL, _T(" -- Drawing slice: %3i - %3i.\n"), nSliceStart, nSliceEnd); +#endif + + NeoRenderSprites(); // Render sprites + } + } + +#if defined RASTERS_OPTIONAL + } +#endif + + bForcePartialRender = false; + + if (nCyclesSegment < nIRQCycles || SekTotalCycles() >= nIRQCycles) { + NeoSekRun(nCyclesSegment - SekTotalCycles()); + } else { + NeoSekRun(nIRQCycles - SekTotalCycles()); + } + } + } + + if (bRenderImage) { + if (nSliceEnd < 240) { + nSliceStart = nSliceEnd; + nSliceEnd = 240; + nSliceSize = nSliceEnd - nSliceStart; + +#if 0 || defined LOG_DRAW + bprintf(PRINT_NORMAL, _T(" -- Drawing slice: %3i - %3i.\n"), nSliceStart, nSliceEnd); +#endif + + NeoRenderSprites(); // Render sprites + } + NeoRenderText(); // Render text layer + } + + nIRQAcknowledge &= ~4; + SekSetIRQLine(nVBLankIRQ, SEK_IRQSTATUS_ACK); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - VBLank.\n")); +#endif + + // set IRQ scanline at line 248 + if (nIRQControl & 0x40) { + if (NeoConvertIRQPosition(nIRQOffset) < NO_IRQ_PENDING) { + nIRQCycles = nCyclesSegment + NeoConvertIRQPosition(nIRQOffset); + } + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ Line -> %3i (at line %3i, VBlank).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + } + + nCyclesSegment = nCyclesTotal[0]; + while (SekTotalCycles() < nCyclesSegment) { + + if ((nIRQControl & 0x10) && (nIRQCycles < NO_IRQ_PENDING) && (SekTotalCycles() >= nIRQCycles)) { + nIRQAcknowledge &= ~2; + SekSetIRQLine(nScanlineIRQ, SEK_IRQSTATUS_ACK); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ triggered (line %3i + %3i cycles).\n"), SekCurrentScanline(), SekTotalCycles() - SekCurrentScanline() * SekCyclesScanline()); +#endif + + if (nIRQControl & 0x80) { + nIRQCycles += NeoConvertIRQPosition(nIRQOffset + 1); + +#if 0 || defined LOG_IRQ + bprintf(PRINT_NORMAL, _T(" - IRQ Line -> %3i (at line %3i, autoload).\n"), nIRQCycles / SekCyclesScanline(), SekCurrentScanline()); +#endif + + } + } + + if (nCyclesSegment < nIRQCycles || SekTotalCycles() >= nIRQCycles) { + NeoSekRun(nCyclesSegment - SekTotalCycles()); + } else { + NeoSekRun(nIRQCycles - SekTotalCycles()); + } + } + + if (nIRQCycles < NO_IRQ_PENDING) { + nIRQCycles -= nCyclesTotal[0]; + if (nIRQCycles < 0) { + nIRQCycles = NO_IRQ_PENDING; + +#if 0 || defined LOG_IRQ + } else { + bprintf(PRINT_NORMAL, _T(" - IRQ Line past screen end (IRQControl: %02X, line -> %3i).\n"), nIRQControl, nIRQCycles / SekCyclesScanline()); +#endif + + } + } +// bprintf(PRINT_NORMAL, " -- IRQControl: %02X, nIRQCycles / SekCyclesScanline(): %3i.\n", nIRQControl, nIRQCycles / SekCyclesScanline()); + + // Update the sound until the end of the frame + + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + + // Update the uPD4990 until the end of the frame + uPD4990AUpdate(SekTotalCycles() - nuPD4990ATicks); + +#if defined EMULATE_WATCHDOG + // Handle the watchdog + nNeoWatchdog += SekTotalCycles(); +#endif + + // Remember extra cycles executed + nCyclesExtra[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesExtra[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T(" Z80 PC 0x%04X\n"), Doze.pc); +// bprintf(PRINT_NORMAL, _T(" - %i\n"), SekTotalCycles()); + + ZetClose(); + SekClose(); + + if ((nIRQControl & 8) == 0) { + if (++nSpriteFrameTimer > nSpriteFrameSpeed) { + nSpriteFrameTimer = 0; + nNeoSpriteFrame++; + } + } + + CDEmuGetSoundBuffer(pBurnSoundOut, nBurnSoundLen); + + return 0; +} diff --git a/src/burn/drivers/neogeo/neo_sprite.cpp b/src/burn/drivers/neogeo/neo_sprite.cpp new file mode 100644 index 00000000..ad1247eb --- /dev/null +++ b/src/burn/drivers/neogeo/neo_sprite.cpp @@ -0,0 +1,181 @@ +#include "neogeo.h" + +UINT8* NeoZoomROM; + +UINT8* NeoSpriteROM[MAX_SLOT] = { NULL, }; + +UINT32 nNeoTileMask[MAX_SLOT]; +INT32 nNeoMaxTile[MAX_SLOT]; + +static UINT8* NeoSpriteROMActive; +static UINT32 nNeoTileMaskActive; +static INT32 nNeoMaxTileActive; + +static UINT8* NeoTileAttrib[MAX_SLOT] = { NULL, }; +static UINT8* NeoTileAttribActive; + +INT32 nSliceStart, nSliceEnd, nSliceSize; + +static UINT32* pTileData; +static UINT32* pTilePalette; + +static UINT16* pBank; + +static INT32 nBankSize; +static INT32 nBankXPos, nBankYPos; +static INT32 nBankXZoom, nBankYZoom; + +static INT32 nNeoSpriteFrame04, nNeoSpriteFrame08; + +static INT32 nLastBPP = -1; + +typedef void (*RenderBankFunction)(); +static RenderBankFunction* RenderBank; + +static UINT16 BankAttrib01, BankAttrib02, BankAttrib03; + + +// Include the tile rendering functions +#include "neo_sprite_func.h" + +INT32 NeoRenderSprites() +{ + if (nLastBPP != nBurnBpp ) { + nLastBPP = nBurnBpp; + + RenderBank = RenderBankNormal[nBurnBpp - 2]; + } + + if (!NeoSpriteROMActive || !(nBurnLayer & 1)) { + return 0; + } + +// UINT16 BankAttrib01, BankAttrib02, BankAttrib03; + + nNeoSpriteFrame04 = nNeoSpriteFrame & 3; + nNeoSpriteFrame08 = nNeoSpriteFrame & 7; + + // ssrpg hack! - NeoCD/SDL + INT32 nStart = 0; + if (SekReadWord(0x108) == 0x0085) { + UINT16 *vidram = (UINT16*)NeoGraphicsRAM; + + if ((vidram[0x8202] & 0x40) == 0 && (vidram[0x8203] & 0x40) != 0) { + nStart = 3; + + while ((vidram[0x8200 + nStart] & 0x40) != 0) nStart++; + + if (nStart == 3) nStart = 0; + } + } + + for (INT32 nBank = 0; nBank < 0x17D; nBank++) { + INT32 zBank = (nBank + nStart) % 0x17d; + BankAttrib01 = *((UINT16*)(NeoGraphicsRAM + 0x010000 + (zBank << 1))); + BankAttrib02 = *((UINT16*)(NeoGraphicsRAM + 0x010400 + (zBank << 1))); + BankAttrib03 = *((UINT16*)(NeoGraphicsRAM + 0x010800 + (zBank << 1))); + + pBank = (UINT16*)(NeoGraphicsRAM + (zBank << 7)); + + if (BankAttrib02 & 0x40) { + nBankXPos += nBankXZoom + 1; + } else { + nBankYPos = (0x0200 - (BankAttrib02 >> 7)) & 0x01FF; + nBankXPos = (BankAttrib03 >> 7); + if (nNeoScreenWidth == 304) { + nBankXPos -= 8; + } + + nBankYZoom = BankAttrib01 & 0xFF; + nBankSize = BankAttrib02 & 0x3F; + +// if (nBankSize > 0x10 && nSliceStart == 0x10) bprintf(PRINT_NORMAL, _T("bank: %04X, x: %04X, y: %04X, zoom: %02X, size: %02X.\n"), zBank, nBankXPos, nBankYPos, nBankYZoom, nBankSize); + } + + if (nBankSize) { + + nBankXZoom = (BankAttrib01 >> 8) & 0x0F; + if (nBankXPos >= 0x01E0) { + nBankXPos -= 0x200; + } + + if (nBankXPos >= 0 && nBankXPos < (nNeoScreenWidth - nBankXZoom - 1)) { + RenderBank[nBankXZoom](); + } else { + if (nBankXPos >= -nBankXZoom && nBankXPos < nNeoScreenWidth) { + RenderBank[nBankXZoom + 16](); + } + } + } + } + +// bprintf(PRINT_NORMAL, _T("\n")); + + return 0; +} + +void NeoUpdateSprites(INT32 nOffset, INT32 nSize) +{ + for (INT32 i = nOffset & ~127; i < nOffset + nSize; i += 128) { + bool bTransparent = true; + for (INT32 j = i; j < i + 128; j++) { + if (NeoSpriteROMActive[j]) { + bTransparent = false; + break; + } + } + if (bTransparent) { + NeoTileAttribActive[i >> 7] = 1; + } else { + NeoTileAttribActive[i >> 7] = 0; + } + } +} + +void NeoSetSpriteSlot(INT32 nSlot) +{ + NeoTileAttribActive = NeoTileAttrib[nSlot]; + NeoSpriteROMActive = NeoSpriteROM[nSlot]; + nNeoTileMaskActive = nNeoTileMask[nSlot]; + nNeoMaxTileActive = nNeoMaxTile[nSlot]; +} + +INT32 NeoInitSprites(INT32 nSlot) +{ + // Create a table that indicates if a tile is transparent + NeoTileAttrib[nSlot] = (UINT8*)malloc(nNeoTileMask[nSlot] + 1); + + for (INT32 i = 0; i < nNeoMaxTile[nSlot]; i++) { + bool bTransparent = true; + for (INT32 j = i << 7; j < (i + 1) << 7; j++) { + if (NeoSpriteROM[nSlot][j]) { + bTransparent = false; + break; + } + } + if (bTransparent) { + NeoTileAttrib[nSlot][i] = 1; + } else { + NeoTileAttrib[nSlot][i] = 0; + } + } + for (UINT32 i = nNeoMaxTile[nSlot]; i < nNeoTileMask[nSlot] + 1; i++) { + NeoTileAttrib[nSlot][i] = 1; + } + + NeoTileAttribActive = NeoTileAttrib[nSlot]; + NeoSpriteROMActive = NeoSpriteROM[nSlot]; + nNeoTileMaskActive = nNeoTileMask[nSlot]; + nNeoMaxTileActive = nNeoMaxTile[nSlot]; + + return 0; +} + +void NeoExitSprites(INT32 nSlot) +{ + if (NeoTileAttrib[nSlot]) { + free(NeoTileAttrib[nSlot]); + NeoTileAttrib[nSlot] = NULL; + } + NeoTileAttribActive = NULL; +} diff --git a/src/burn/drivers/neogeo/neo_sprite_render.h b/src/burn/drivers/neogeo/neo_sprite_render.h new file mode 100644 index 00000000..266514bb --- /dev/null +++ b/src/burn/drivers/neogeo/neo_sprite_render.h @@ -0,0 +1,656 @@ +// Create a unique name for each of the functions +#define FN(a,b,c,d) RenderBank ## a ## _ZOOM ## b ## c ## d +#define FUNCTIONNAME(a,b,c,d) FN(a,b,c,d) + +#if DOCLIP == 0 + #define CLIP _NOCLIP + #define TESTCLIP(x) 1 +#elif DOCLIP == 1 + #define CLIP _CLIP + #define TESTCLIP(x) (nBankXPos + x) >= 0 && (nBankXPos + x) < nNeoScreenWidth +#else + #error illegal doclip value. +#endif + +#if ISOPAQUE == 0 + #define OPACITY _TRANS + #define TESTCOLOUR(x) x +#else + #error illegal isopaque value +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT16*)pPixel) = (UINT16)pTilePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + UINT32 nRGB = pTilePalette[b]; \ + pPixel[0] = (UINT8)nRGB; \ + pPixel[1] = (UINT8)(nRGB >> 8); \ + pPixel[2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT32*)pPixel) = (UINT32)pTilePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +#if XZOOM == 0 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); +#elif XZOOM == 1 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); +#elif XZOOM == 2 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); +#elif XZOOM == 3 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); +#elif XZOOM == 4 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); +#elif XZOOM == 5 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 16; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); +#elif XZOOM == 6 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); +#elif XZOOM == 7 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); +#elif XZOOM == 8 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); +#elif XZOOM == 9 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); +#elif XZOOM == 10 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); +#elif XZOOM == 11 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(11),nColour & 0x0F); +#elif XZOOM == 12 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(11),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(12),nColour & 0x0F); +#elif XZOOM == 13 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(11),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(12),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(13),nColour & 0x0F); +#elif XZOOM == 14 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 8; \ + PLOTPIXEL(OFFSET(5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(11),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(12),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(13),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(14),nColour & 0x0F); +#elif XZOOM == 15 + #define PLOTLINE(OFFSET,ADVANCECOLUMN) \ + nColour = pTileData[nLine]; \ + PLOTPIXEL(OFFSET( 0),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 1),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 2),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 3),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 4),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 5),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 6),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 7),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour = pTileData[nLine + 1]; \ + PLOTPIXEL(OFFSET( 8),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET( 9),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(10),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(11),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(12),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(13),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(14),nColour & 0x0F); \ + ADVANCECOLUMN; \ + nColour >>= 4; \ + PLOTPIXEL(OFFSET(15),nColour & 0x0F); +#else + #error unsupported zoom factor specified. +#endif + +#define NORMALOFFSET(x) (x) +#define MIRROROFFSET(x) (XZOOM - x) + +// #undef USE_SPEEDHACKS + +static void FUNCTIONNAME(BPP,XZOOM,CLIP,OPACITY)() +{ + UINT8 *pTileRow, *pPixel; + INT32 nColour = 0, nTransparent = 0; + INT32 nTileNumber, nTileAttrib = 0; + INT32 nTile, nLine; + INT32 nPrevTile; + INT32 nYPos; + + UINT8* pZoomValue = NeoZoomROM + (nBankYZoom << 8); + + INT32 nLinesTotal = (nBankSize >= 0x20) ? 0x01FF : ((nBankSize << 4) - 1); + INT32 nLinesDone = 0; + + while (nLinesDone <= nLinesTotal) { + nLine = (nBankYPos + nLinesDone) & 0x01FF; + nYPos = nLine; + +// bprintf(PRINT_NORMAL, _T(" - s:%i l:%i y:%i %i z:%i\n"), nLinesTotal, nLinesDone, nYPos, nBankYPos, nBankYZoom); + + // Skip everything above the part of the display we need to render + if (nYPos < nSliceStart) { + nLinesDone += nSliceStart - nYPos; + continue; + } + // Skip everything below the part of the display we need to render + if (nYPos >= nSliceEnd) { + nLinesDone += nSliceStart + 512 - nYPos; + continue; + } + + // This part of the sprite strip is in the part of the display we need to render + { + INT32 nStartTile = (nLinesDone >= 0x0100) ? 0x10 : 0; + INT32 nStartLine = nLinesDone & 0xFF; + INT32 nEndLine = (nLinesDone < 0x0100 && nLinesTotal >= 0x0100) ? 0xFF : nLinesTotal & 0xFF; + + INT32 nThisLine; + + // Handle wraparound for full-size sprite strips + if (nBankSize > 0x10 && nBankYZoom != 0xFF) { + + if (nBankSize <= 0x20) { + + // normal wrap + + if (nLinesDone >= 0x0100) { + if (nLinesDone < (0x01FF - nBankYZoom)) { + nLinesDone = (0x01FF - nBankYZoom); + + continue; + } + + nStartLine -= 0xFF - nBankYZoom; + nEndLine -= 0xFF - nBankYZoom; + } + + } else { + + // Full strip, full wrap + + if (nLinesDone >= 0x0100) { + nStartLine -= 0xFF - nBankYZoom; + if (nStartLine < 0) { + +#if 1 && defined USE_SPEEDHACKS + nStartLine += nBankYZoom + 1; + if (nStartLine < 0) { + nLinesDone = 0x200; + continue; + } +#else + nStartLine = nBankYZoom - (-nStartLine - 1) % (nBankYZoom + 1); +#endif + + nStartTile = 0; + } + } else { + if (nStartLine > nBankYZoom) { + +#if 1 && defined USE_SPEEDHACKS + nStartLine -= nBankYZoom + 1; + if (nStartLine > nBankYZoom) { + nLinesDone = 0x0100; + continue; + } +#else + nStartLine %= nBankYZoom + 1; +#endif + + nStartTile = 0x10; + } + } + + nEndLine = nBankYZoom; + } + } + + nLinesDone += nEndLine - nStartLine + 1; + +#if 1 && defined USE_SPEEDHACKS + if (nBankSize <= 0x20 && nEndLine > nBankYZoom) { + nEndLine = nBankYZoom; +// nLinesDone |= 0x00FF; + } +#endif + + // Clip to the part of the screen we need to render + if (nEndLine - nStartLine > nSliceEnd - nYPos - 1) { + nEndLine = nStartLine + nSliceEnd - nYPos - 1; + } + + pTileRow = pBurnDraw + (nYPos - 0x10) * (BPP >> 3) * nNeoScreenWidth + nBankXPos * (BPP >> 3); + nThisLine = nStartLine; + + nPrevTile = ~0; + + while (nThisLine <= nEndLine) { + + nTile = nStartTile + (pZoomValue[nThisLine] >> 4); + + if (nTile != nPrevTile) { + nPrevTile = nTile; + + nTileNumber = pBank[nTile << 1]; + nTileAttrib = pBank[(nTile << 1) + 1]; + + nTileNumber += (nTileAttrib & 0xF0) << 12; + nTileNumber &= nNeoTileMaskActive; + + if (nTileAttrib & 8) { + nTileNumber &= ~7; + nTileNumber |= nNeoSpriteFrame08; + } else { + if (nTileAttrib & 4) { + nTileNumber &= ~3; + nTileNumber |= nNeoSpriteFrame04; + } + } + + nTransparent = NeoTileAttribActive[nTileNumber]; + + if (nTransparent == 0) { + pTileData = (UINT32*)(NeoSpriteROMActive + (nTileNumber << 7)); + pTilePalette = &NeoPalette[(nTileAttrib & 0xFF00) >> 4]; + } + } + + if (nTransparent == 0) { + nLine = (pZoomValue[nThisLine] & 0x0F) << 1; + if (nTileAttrib & 2) { // Flip Y + nLine ^= 0x1E; + } + + if (nTileAttrib & 1) { // Flip X + pPixel = pTileRow + XZOOM * (BPP >> 3); + PLOTLINE(MIRROROFFSET,pPixel -= (BPP >> 3)); + } else { + pPixel = pTileRow; + PLOTLINE(NORMALOFFSET,pPixel += (BPP >> 3)); + } + } + + pTileRow += ((BPP >> 3) * nNeoScreenWidth); + + nThisLine++; + } + } + } +} + +#undef PLOTLINE +#undef OPACITY +#undef PLOTPIXEL +#undef TESTCOLOUR +#undef TESTCLIP +#undef CLIP diff --git a/src/burn/drivers/neogeo/neo_text.cpp b/src/burn/drivers/neogeo/neo_text.cpp new file mode 100644 index 00000000..9dd0d45d --- /dev/null +++ b/src/burn/drivers/neogeo/neo_text.cpp @@ -0,0 +1,334 @@ +#include "neogeo.h" + +UINT8* NeoTextROMBIOS; +UINT8* NeoTextROM[MAX_SLOT]; + +INT32 nNeoTextROMSize[MAX_SLOT] = { 0, }; +bool bBIOSTextROMEnabled; + +static UINT8* NeoTextROMCurrent; + +static INT8* NeoTextTileAttrib[MAX_SLOT] = { NULL, }; +static INT8* NeoTextTileAttribBIOS = NULL; +static INT8* NeoTextTileAttribActive = NULL; +static INT32 nBankswitch[MAX_SLOT] = { 0, }; + +static INT32 nBankLookupAddress[40]; +static INT32 nBankLookupShift[40]; + +static UINT8* pTile; +static UINT8* pTileData; +static UINT32* pTilePalette; + +typedef void (*RenderTileFunction)(); +static RenderTileFunction RenderTile; + +static INT32 nLastBPP = 0; + +static INT32 nMinX, nMaxX; + +#define BPP 16 + #include "neo_text_render.h" +#undef BPP + +#define BPP 24 + #include "neo_text_render.h" +#undef BPP + +#define BPP 32 + #include "neo_text_render.h" +#undef BPP + +INT32 NeoRenderText() +{ + INT32 x, y; + UINT8* pTextROM; + INT8* pTileAttrib; + UINT8* pCurrentRow = pBurnDraw; + UINT32* pTextPalette = NeoPalette; + UINT32 nTileDown = nBurnPitch << 3; + UINT32 nTileLeft = nBurnBpp << 3; + UINT16* pTileRow = (UINT16*)(NeoGraphicsRAM + 0xE000); + + if (!(nBurnLayer & 2)) { + return 0; + } + + if (nLastBPP != nBurnBpp ) { + nLastBPP = nBurnBpp; + + switch (nBurnBpp) { + case 2: + RenderTile = *RenderTile16; + break; + case 3: + RenderTile = *RenderTile24; + break; + case 4: + RenderTile = *RenderTile32; + break; + default: + return 1; + } + } + + if (!bBIOSTextROMEnabled && nBankswitch[nNeoActiveSlot]) { + + if (!NeoTextROMCurrent) { + return 0; + } + + if (nBankswitch[nNeoActiveSlot] == 1) { + + // Garou, Metal Slug 3, Metal Slug 4 + + INT32 nOffset[32]; + INT32 nBank = (3 << 12); + INT32 z = 0; + + y = 0; + while (y < 32) { + if (*((UINT16*)(NeoGraphicsRAM + 0xEA00 + z)) == 0x0200 && (*((UINT16*)(NeoGraphicsRAM + 0xEB00 + z)) & 0xFF00) == 0xFF00) { + nBank = ((*((UINT16*)(NeoGraphicsRAM + 0xEB00 + z)) & 3) ^ 3) << 12; + nOffset[y++] = nBank; + } + nOffset[y++] = nBank; + z += 4; + } + + for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++) { + pTextROM = NeoTextROMCurrent + (nOffset[y - 2] << 5); + pTileAttrib = NeoTextTileAttribActive + nOffset[y - 2]; + for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[x << 5]; + INT32 nPalette = nTile & 0xF000; + nTile &= 0x0FFF; + if (pTileAttrib[nTile] == 0) { + pTileData = pTextROM + (nTile << 5); + pTilePalette = &pTextPalette[nPalette >> 8]; + RenderTile(); + } + } + } + } else { + + // KOF2000 + + UINT16* pBankInfo = (UINT16*)(NeoGraphicsRAM + 0xEA00) + 1; + pTextROM = NeoTextROMCurrent; + pTileAttrib = NeoTextTileAttribActive; + + for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++, pBankInfo++) { + for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[x << 5]; + INT32 nPalette = nTile & 0xF000; + nTile &= 0x0FFF; + nTile += (((pBankInfo[nBankLookupAddress[x]] >> nBankLookupShift[x]) & 3) ^ 3) << 12; + if (pTileAttrib[nTile] == 0) { + pTileData = pTextROM + (nTile << 5); + pTilePalette = &pTextPalette[nPalette >> 8]; + RenderTile(); + } + } + } + } + } else { + if (bBIOSTextROMEnabled) { + pTextROM = NeoTextROMBIOS; + pTileAttrib = NeoTextTileAttribBIOS; + } else { + pTextROM = NeoTextROMCurrent; + pTileAttrib = NeoTextTileAttribActive; + } + if (!pTextROM) { + return 0; + } + + for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++) { + for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[x << 5]; + INT32 nPalette = nTile & 0xF000; + nTile &= 0xFFF; + if (pTileAttrib[nTile] == 0) { + pTileData = pTextROM + (nTile << 5); + pTilePalette = &pTextPalette[nPalette >> 8]; + RenderTile(); + } + } + } + } + + return 0; +} + +void NeoExitText(INT32 nSlot) +{ + if (NeoTextTileAttribBIOS) { + free(NeoTextTileAttribBIOS); + NeoTextTileAttribBIOS = NULL; + } + + if (NeoTextTileAttrib[nSlot]) { + free(NeoTextTileAttrib[nSlot]); + NeoTextTileAttrib[nSlot] = NULL; + } + NeoTextTileAttribActive = NULL; +} + +static void NeoUpdateTextAttribBIOS(INT32 nOffset, INT32 nSize) +{ + for (INT32 i = nOffset & ~31; i < nOffset + nSize; i += 32) { + NeoTextTileAttribBIOS[i >> 5] = (((INT64*)NeoTextROMBIOS)[(i >> 3) + 0] || + ((INT64*)NeoTextROMBIOS)[(i >> 3) + 1] || + ((INT64*)NeoTextROMBIOS)[(i >> 3) + 2] || + ((INT64*)NeoTextROMBIOS)[(i >> 3) + 3]) + ? 0 : 1; + } +} + +static inline void NeoUpdateTextAttribOne(const INT32 nOffset) +{ + NeoTextTileAttribActive[nOffset >> 5] = 1; + + for (INT32 i = nOffset; i < nOffset + 32; i += 4) { + if (*((UINT32*)(NeoTextROMCurrent + i))) { + NeoTextTileAttribActive[nOffset >> 5] = 0; + break; + } + } +} + +static void NeoUpdateTextAttrib(INT32 nOffset, INT32 nSize) +{ + nOffset &= ~0x1F; + + for (INT32 i = nOffset; i < nOffset + nSize; i += 32) { + NeoUpdateTextAttribOne(i); + } +} + +void NeoUpdateTextOne(INT32 nOffset, const UINT8 byteValue) +{ + nOffset = (nOffset & ~0x1F) | (((nOffset ^ 0x10) & 0x18) >> 3) | ((nOffset & 0x07) << 2); + + if (byteValue) { + NeoTextTileAttribActive[nOffset >> 5] = 0; + } else { + if (NeoTextTileAttribActive[nOffset >> 5] == 0 && NeoTextROMCurrent[nOffset]) { + NeoTextTileAttribActive[nOffset >> 5] = 1; + NeoUpdateTextAttribOne(nOffset); + } + } + + NeoTextROMCurrent[nOffset] = byteValue; +} + +static inline void NeoTextDecodeTile(const UINT8* pData, UINT8* pDest) +{ + UINT8 nBuffer[32]; + + for (INT32 i = 0; i < 8; i++) { + nBuffer[0 + i * 4] = pData[16 + i]; + nBuffer[1 + i * 4] = pData[24 + i]; + nBuffer[2 + i * 4] = pData[ 0 + i]; + nBuffer[3 + i * 4] = pData[ 8 + i]; + } + + for (INT32 i = 0; i < 32; i++) { + pDest[i] = nBuffer[i] << 4; + pDest[i] |= nBuffer[i] >> 4; + } +} + +void NeoDecodeTextBIOS(INT32 nOffset, const INT32 nSize, UINT8* pData) +{ + UINT8* pEnd = pData + nSize; + + for (UINT8* pDest = NeoTextROMBIOS + (nOffset & ~0x1F); pData < pEnd; pData += 32, pDest += 32) { + NeoTextDecodeTile(pData, pDest); + } + +// if (NeoTextTileAttribBIOS) { +// NeoUpdateTextAttribBIOS(0, nSize); +// } +} + +void NeoDecodeText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest) +{ + UINT8* pEnd = pData + nSize; + + for (pData += (nOffset & ~0x1F); pData < pEnd; pData += 32, pDest += 32) { + NeoTextDecodeTile(pData, pDest); + } +} + +void NeoUpdateText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest) +{ + NeoDecodeText(nOffset, nSize, pData, pDest); + if (NeoTextTileAttribActive) { + NeoUpdateTextAttrib((nOffset & ~0x1F), nSize); + } +} + +void NeoSetTextSlot(INT32 nSlot) +{ + NeoTextROMCurrent = NeoTextROM[nSlot]; + NeoTextTileAttribActive = NeoTextTileAttrib[nSlot]; +} + +INT32 NeoInitText(INT32 nSlot) +{ + if (nSlot < 0) { + NeoTextTileAttribBIOS = (INT8*)malloc(0x1000); + for (INT32 i = 0; i < 0x1000; i++) { + NeoTextTileAttribBIOS[i] = 1; + } + NeoUpdateTextAttribBIOS(0, 0x020000); + + return 0; + } + + INT32 nTileNum = nNeoTextROMSize[nSlot] >> 5; + +// NeoExitText(nSlot); + + NeoTextTileAttrib[nSlot] = (INT8*)malloc((nTileNum < 0x1000) ? 0x1000 : nTileNum); + + if (nNeoScreenWidth == 304) { + nMinX = 1; + nMaxX = 39; + } else { + nMinX = 0; + nMaxX = 40; + } + + // Set up tile attributes + + NeoTextROMCurrent = NeoTextROM[nSlot]; + NeoTextTileAttribActive = NeoTextTileAttrib[nSlot]; + for (INT32 i = 0; i < ((nTileNum < 0x1000) ? 0x1000 : nTileNum); i++) { + NeoTextTileAttribActive[i] = 1; + } + NeoUpdateTextAttrib(0, nNeoTextROMSize[nSlot]); + + // Set up tile bankswitching + + nBankswitch[nSlot] = 0; + if (nNeoTextROMSize[nSlot] > 0x040000) { +// if (BurnDrvGetHardwareCode() & HARDWARE_SNK_CMC50) { + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_ALTERNATE_TEXT) { + nBankswitch[nSlot] = 2; + + // Precompute lookup-tables + for (INT32 x = nMinX; x < nMaxX; x++) { + nBankLookupAddress[x] = (x / 6) << 5; + nBankLookupShift[x] = (5 - (x % 6)) << 1; + } + + } else { + nBankswitch[nSlot] = 1; + } + } + + return 0; +} diff --git a/src/burn/drivers/neogeo/neo_text_render.h b/src/burn/drivers/neogeo/neo_text_render.h new file mode 100644 index 00000000..7f8e8e30 --- /dev/null +++ b/src/burn/drivers/neogeo/neo_text_render.h @@ -0,0 +1,79 @@ +#define FN(a) RenderTile ## a +#define FUNCTIONNAME(a) FN(a) + +#define ISOPAQUE 0 + +#define ADVANCECOLUMN pPixel += (BPP >> 3) + +#define ADVANCEROW pTileRow += ((BPP >> 3) * nNeoScreenWidth) + +#if ISOPAQUE == 0 + #define OPACITY _TRANS + #define TESTCOLOUR(x) x +#elif ISOPAQUE == 1 + #define OPACITY _OPAQUE + #define TESTCOLOUR(x) 1 +#else + #error illegal isopaque value +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b)) { \ + *((UINT16*)pPixel) = (UINT16)pTilePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b)) { \ + UINT32 nRGB = pTilePalette[b]; \ + pPixel[0] = (UINT8)nRGB; \ + pPixel[1] = (UINT8)(nRGB >> 8); \ + pPixel[2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b)) { \ + *((UINT32*)pPixel) = (UINT32)pTilePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +static void FUNCTIONNAME(BPP)() +{ + UINT8 *pTileRow, *pPixel; + INT32 y, nColour; + + for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) { + pPixel = pTileRow; + + nColour = *pTileData++; + PLOTPIXEL(0,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(1,nColour & 0x0F); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(2,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(3,nColour & 0x0F); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(4,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(5,nColour & 0x0F); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(6,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(7,nColour & 0x0F); + } +} + +#undef PLOTPIXEL +#undef TESTCLIP +#undef TESTCOLOUR +#undef ADVANCEROW +#undef ADVANCECOLUMN +#undef CLIP +#undef FUNCTIONNAME +#undef FN diff --git a/src/burn/drivers/neogeo/neo_upd4990a.cpp b/src/burn/drivers/neogeo/neo_upd4990a.cpp new file mode 100644 index 00000000..6c38d5de --- /dev/null +++ b/src/burn/drivers/neogeo/neo_upd4990a.cpp @@ -0,0 +1,285 @@ +// NEC uPD4990A module (real-time clock/calendar) + +#include "neogeo.h" + +static struct { + // The current time + UINT32 nSeconds; UINT32 nMinutes; UINT32 nHours; + UINT32 nDay; UINT32 nMonth; UINT32 nYear; + UINT32 nWeekDay; + + // Modes for both outputs + INT32 nMode; INT32 nTPMode; + + // Shift register and command + UINT32 nRegister[2]; UINT32 nCommand; + + // Counters + UINT32 nCount; UINT32 nTPCount; UINT32 nInterval; + + // Outputs + UINT8 TP; UINT8 nPrevCLK; UINT8 nPrevSTB; +} uPD4990A; + +static UINT32 nOneSecond; + +INT32 uPD4990AInit(UINT32 nTicksPerSecond) +{ + nOneSecond = nTicksPerSecond; + + uPD4990A.nRegister[0] = uPD4990A.nRegister[1] = 0; + + uPD4990A.nCommand = 0; + uPD4990A.nMode = uPD4990A.nTPMode = 0; + + uPD4990A.nCount = uPD4990A.nTPCount = 0; + uPD4990A.nInterval = nOneSecond / 64; + + uPD4990A.nPrevCLK = uPD4990A.nPrevSTB = 0; + + uPD4990A.TP = 0; + + // Set the time of the uPD4990A to the current local time + time_t nLocalTime = time(NULL); + tm* tmLocalTime = localtime(&nLocalTime); + + uPD4990A.nSeconds = tmLocalTime->tm_sec; + uPD4990A.nMinutes = tmLocalTime->tm_min; + uPD4990A.nHours = tmLocalTime->tm_hour; + uPD4990A.nDay = tmLocalTime->tm_mday; + uPD4990A.nWeekDay = tmLocalTime->tm_wday; + uPD4990A.nMonth = tmLocalTime->tm_mon + 1; + uPD4990A.nYear = tmLocalTime->tm_year % 100; + + return 0; +} + +void uPD499ASetTicks(UINT32 nTicksPerSecond) +{ + uPD4990A.nCount = (UINT32)((INT64)uPD4990A.nCount * nTicksPerSecond / nOneSecond); + uPD4990A.nTPCount = (UINT32)((INT64)uPD4990A.nTPCount * nTicksPerSecond / nOneSecond); + uPD4990A.nInterval = (UINT32)((INT64)uPD4990A.nInterval * nTicksPerSecond / nOneSecond); + + nOneSecond = nTicksPerSecond; +} + +void uPD4990AExit() +{ +} + +void uPD4990AUpdate(UINT32 nTicks) +{ + if (uPD4990A.nTPMode != 2) { + uPD4990A.nTPCount += nTicks; + + if (uPD4990A.nTPMode == 1) { + if (uPD4990A.nTPCount >= uPD4990A.nInterval) { + uPD4990A.nTPMode = 0; + uPD4990A.nTPCount %= uPD4990A.nInterval; + uPD4990A.TP = (uPD4990A.nTPCount >= (uPD4990A.nInterval >> 1)); + } + } else { + if (uPD4990A.nTPCount >= uPD4990A.nInterval) { + uPD4990A.nTPCount %= uPD4990A.nInterval; + } + uPD4990A.TP = (uPD4990A.nTPCount >= (uPD4990A.nInterval >> 1)); + } + } + + uPD4990A.nCount += nTicks; + if (uPD4990A.nCount >= nOneSecond) { + uPD4990A.nCount %= uPD4990A.nInterval; + + uPD4990A.nSeconds++; + if (uPD4990A.nSeconds >= 60) { + uPD4990A.nSeconds = 0; + + uPD4990A.nMinutes++; + if (uPD4990A.nMinutes >= 60) { + uPD4990A.nMinutes = 0; + + uPD4990A.nHours++; + if (uPD4990A.nHours >= 24) { + uPD4990A.nHours = 0; + + uPD4990A.nWeekDay++; + if (uPD4990A.nWeekDay >= 7) { + uPD4990A.nWeekDay = 0; + } + + UINT32 nMonthLength[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + if ((uPD4990A.nYear & 3) == 0) { + nMonthLength[2]++; + } + + uPD4990A.nDay++; + if (uPD4990A.nDay > nMonthLength[uPD4990A.nMonth]) { + uPD4990A.nDay = 1; + + uPD4990A.nMonth++; + if (uPD4990A.nMonth > 12) { + uPD4990A.nMonth = 1; + + uPD4990A.nYear++; + if (uPD4990A.nYear >= 100) { + uPD4990A.nYear = 0; + } + } + } + } + } + } + } +} + +void uPD4990AScan(INT32 nAction, INT32* pnMin) +{ + if (nAction & ACB_DRIVER_DATA) { // Scan variables + + if (pnMin && *pnMin < 0x020902) { // Return minimum compatible version + *pnMin = 0x020902; + } + + SCAN_VAR(uPD4990A); + } +} + +void uPD4990AWrite(UINT8 CLK, UINT8 STB, UINT8 DATA) +{ +// bprintf(PRINT_NORMAL, _T(" - uPD4990A written: CLK: %i, STB: %i DATA IN: %i (PC: %06X).\n"), CLK ? 1 : 0, STB ? 1 : 0, DATA ? 1 : 0, SekGetPC(-1)); + + if (STB && uPD4990A.nPrevSTB == 0) { // Process command + +// bprintf(PRINT_NORMAL, _T(" - Command sent: %02X.\n"), nCommand & 0x0F); + + switch (uPD4990A.nCommand & 0x0F) { + case 0x00: // Register hold + uPD4990A.nMode = 0; + + uPD4990A.nTPMode = 0; + uPD4990A.nInterval = nOneSecond / 64; + uPD4990A.nTPCount %= uPD4990A.nInterval; + break; + case 0x01: // Register shift + uPD4990A.nMode = 1; + break; + case 0x02: // Time set & counter hold + uPD4990A.nMode = 2; + +// bprintf(PRINT_NORMAL, _T("Time set: %08X %08X.\n"), nRegister[0], nRegister[1]); + + // Convert BCD values to normal numbers + uPD4990A.nSeconds = ((uPD4990A.nRegister[0] >> 0) & 0x0F); + uPD4990A.nSeconds += ((uPD4990A.nRegister[0] >> 4) & 0x0F) * 10; + uPD4990A.nMinutes = ((uPD4990A.nRegister[0] >> 8) & 0x0F); + uPD4990A.nMinutes += ((uPD4990A.nRegister[0] >> 12) & 0x0F) * 10; + uPD4990A.nHours = ((uPD4990A.nRegister[0] >> 16) & 0x0F); + uPD4990A.nHours += ((uPD4990A.nRegister[0] >> 20) & 0x0F) * 10; + uPD4990A.nDay = ((uPD4990A.nRegister[0] >> 24) & 0x0F); + uPD4990A.nDay += ((uPD4990A.nRegister[0] >> 28) & 0x0F) * 10; + uPD4990A.nWeekDay = ((uPD4990A.nRegister[1] >> 0) & 0x0F); + uPD4990A.nMonth = ((uPD4990A.nRegister[1] >> 4) & 0x0F); + uPD4990A.nYear = ((uPD4990A.nRegister[1] >> 8) & 0x0F); + uPD4990A.nYear += ((uPD4990A.nRegister[1] >> 12) & 0x0F) * 10; + break; + case 0x03: // Time read + uPD4990A.nMode = 0; + + // Convert normal numbers to BCD values + uPD4990A.nRegister[0] = (uPD4990A.nSeconds % 10) << 0; + uPD4990A.nRegister[0] |= (uPD4990A.nSeconds / 10) << 4; + uPD4990A.nRegister[0] |= (uPD4990A.nMinutes % 10) << 8; + uPD4990A.nRegister[0] |= (uPD4990A.nMinutes / 10) << 12; + uPD4990A.nRegister[0] |= (uPD4990A.nHours % 10) << 16; + uPD4990A.nRegister[0] |= (uPD4990A.nHours / 10) << 20; + uPD4990A.nRegister[0] |= (uPD4990A.nDay % 10) << 24; + uPD4990A.nRegister[0] |= (uPD4990A.nDay / 10) << 28; + uPD4990A.nRegister[1] = (uPD4990A.nWeekDay ) << 0; + uPD4990A.nRegister[1] |= (uPD4990A.nMonth ) << 4; + uPD4990A.nRegister[1] |= (uPD4990A.nYear % 10) << 8; + uPD4990A.nRegister[1] |= (uPD4990A.nYear / 10) << 12; + break; + + case 0x04: + case 0x05: + case 0x06: + case 0x07: { // TP = nn Hz + INT32 n[4] = { 64, 256, 2048, 4096 }; + + uPD4990A.nTPMode = 0; + uPD4990A.nInterval = nOneSecond / n[uPD4990A.nCommand & 3]; + uPD4990A.nTPCount %= uPD4990A.nInterval; + break; + } + + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: { // TP = nn s interval set (counter reset & start) + INT32 n[4] = { 1, 10, 30, 60 }; + + uPD4990A.nTPMode = 0; + uPD4990A.nInterval = n[uPD4990A.nCommand & 3] * nOneSecond; + uPD4990A.nTPCount = 0; + break; + } + case 0x0C: // Interval reset + uPD4990A.nTPMode = 1; + uPD4990A.TP = 1; + break; + case 0x0D: // interval start + uPD4990A.nTPMode = 0; + break; + case 0x0E: // Interval stop + uPD4990A.nTPMode = 2; + break; + + case 0x0F: // Test mode set (not implemented) + break; + } + } + + if (STB == 0 && CLK && uPD4990A.nPrevCLK == 0) { + + // Shift a new bit into the register + if (uPD4990A.nMode == 1) { + uPD4990A.nRegister[0] >>= 1; + if (uPD4990A.nRegister[1] & 1) { + uPD4990A.nRegister[0] |= (1 << 31); + } + uPD4990A.nRegister[1] >>= 1; + uPD4990A.nRegister[1] &= 0x7FFF; + if (uPD4990A.nCommand & 1) { + uPD4990A.nRegister[1] |= (1 << 15); + } + } + + // Shift a new bit into the command + uPD4990A.nCommand >>= 1; + uPD4990A.nCommand &= 7; + if (DATA) { + uPD4990A.nCommand |= 8; + } + } + + uPD4990A.nPrevCLK = CLK; + uPD4990A.nPrevSTB = STB; +} + +UINT8 uPD4990ARead(UINT32 nTicks) +{ + UINT8 OUT; + + uPD4990AUpdate(nTicks); + + if (uPD4990A.nMode == 0) { // 1Hz pulse appears at output + OUT = (uPD4990A.nCount >= (nOneSecond >> 1)); + } else { // LSB of the shift register appears at output + OUT = uPD4990A.nRegister[0] & 1; + } + +// bprintf(PRINT_NORMAL, _T(" - uPD4990A read: OUT %i, TP %i.\n"), OUT, uPD4990A.TP); + + return (OUT << 1) | uPD4990A.TP; +} + diff --git a/src/burn/drivers/neogeo/neogeo.cpp b/src/burn/drivers/neogeo/neogeo.cpp new file mode 100644 index 00000000..270ca0f3 --- /dev/null +++ b/src/burn/drivers/neogeo/neogeo.cpp @@ -0,0 +1,433 @@ +// Neo Geo -- misc. support functions + +#include "neogeo.h" +#include "bitswap.h" + +UINT8 nNeoProtectionXor; + +// This function loads the 68K ROMs +INT32 NeoLoadCode(INT32 nOffset, INT32 nNum, UINT8* pDest) +{ + struct BurnRomInfo ri; + + for (INT32 i = 0; i < nNum; i++) { + ri.nLen = 0; + BurnDrvGetRomInfo(&ri, nOffset + i); + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_P32) && (i == 0)) + { + if (BurnLoadRom(pDest + 0, nOffset + i + 0, 2)) return 1; + if (BurnLoadRom(pDest + 1, nOffset + i + 1, 2)) return 1; + + for (UINT32 j = 0; j < ri.nLen << 1; j+=4) + BurnByteswap(pDest + j + 1, 2); + + i++; + pDest += ri.nLen << 1; + continue; + } + + if (BurnLoadRom(pDest, nOffset + i, 1)) { + return 1; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SNK_SWAPP) && (i == 0)) { + for (UINT32 j = 0; j < (ri.nLen / 2); j++) { + INT32 k = pDest[j]; + pDest[j] = pDest[j + (ri.nLen / 2)]; + pDest[j + (ri.nLen / 2)] = k; + } + } + + pDest += ri.nLen; + } + + return 0; +} + +static void NeoSVCAddressDecrypt(UINT8* src, UINT8* dst, INT32 start, INT32 end) +{ + for (INT32 i = start / 4; i < end / 4; i++) { + ((UINT32*)dst)[i] = ((UINT32*)src)[(i & 0xFFE00000) | (0x0C8923 ^ BITSWAP24((i & 0x1FFFFF), 0x17, 0x16, 0x15, 0x04, 0x0B, 0x0E, 0x08, 0x0C, 0x10, 0x00, 0x0a, 0x13, 0x03, 0x06, 0x02, 0x07, 0x0D, 0x01, 0x11, 0x09, 0x14, 0x0f, 0x12, 0x05))]; + } +} + +static void NeoKOFAddressDecrypt(UINT8* src, UINT8* dst, INT32 start, INT32 end) +{ + for (INT32 i = start; i < end; i += 0x100) { + memcpy(dst + i, src + ((i & 0xFF800000) | (BITSWAP16((i >> 8) & 0x7FFF, 0x0F, 0x0A, 0x0E, 0x0C, 0x0B, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x0D, 0x01, 0x00) << 8)), 0x100); + } +} + +static void NeoPCBDataDecrypt(UINT8* dst, INT32 size) +{ + for (INT32 i = 0; i < size / 4; i++) { + ((UINT32*)dst)[i] = BITSWAP32(0xE9C42134 ^ ((UINT32*)dst)[i], 0x09, 0x0D, 0x13, 0x00, 0x17, 0x0F, 0x03, 0x05, 0x04, 0x0C, 0x11, 0x1E, 0x12, 0x15, 0x0B, 0x06, 0x1B, 0x0A, 0x1A, 0x1C, 0x14, 0x02, 0x0e, 0x1D, 0x18, 0x08, 0x01, 0x10, 0x19, 0x1F, 0x07, 0x16); + } +} + +// This function loads and pre-processes the sprite data +INT32 NeoLoadSprites(INT32 nOffset, INT32 nNum, UINT8* pDest, UINT32 nSpriteSize) +{ + struct BurnRomInfo ri; + + UINT32 nRomSize = 0; + + if (BurnDrvGetHardwareCode() & (HARDWARE_SNK_CMC42 | HARDWARE_SNK_CMC50)) { + + UINT8* pBuf1 = NULL; + UINT8* pBuf2 = NULL; + +// double dProgress = 1.0 / ((double)((nSpriteSize > 0x04000000) ? 0x05000000 : nSpriteSize) / 0x400000 * 1.5); + + BurnDrvGetRomInfo(&ri, nOffset); + nRomSize = ri.nLen; + + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_CMC42) { + NeoCMC42Init(); + } else { + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_CMC50) { + NeoCMC50Init(); + } + } + + pBuf1 = (UINT8*)malloc(nRomSize * 2); + if (pBuf1 == NULL) { + return 1; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { +// dProgress *= 0.75; + + pBuf2 = (UINT8*)malloc(nRomSize * 2); + if (pBuf2 == NULL) { + return 1; + } + } + + for (INT32 i = 0; i < (nNum >> 1); i++) { + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + if (nRomSize == 0x02000000) { + + // The ROM chips are 32-bit + + BurnLoadRom(pBuf2 + 0 * nRomSize, nOffset + (i << 1), 1); + BurnLoadRom(pBuf2 + 1 * nRomSize, nOffset + 1 + (i << 1), 1); + } else { + + // The ROM chips are 16-bit and need to be interleaved + + BurnLoadRom(pBuf1, nOffset + (i << 1), 1); + for (UINT32 j = 0; j < nRomSize / 2; j++) { + ((UINT16*)pBuf2)[(j << 1) + 0] = ((UINT16*)pBuf1)[j]; + } + BurnLoadRom(pBuf1, nOffset + 1 + (i << 1), 1); + for (UINT32 j = 0; j < nRomSize / 2; j++) { + ((UINT16*)pBuf2)[(j << 1) + 1] = ((UINT16*)pBuf1)[j]; + } + } + } else { + BurnLoadRom(pBuf1 + 0, nOffset + (i << 1), 2); + BurnLoadRom(pBuf1 + 1, nOffset + 1 + (i << 1), 2); + } + +// BurnUpdateProgress(0.0, _T("Decrypting graphics...")/*, BST_DECRYPT_GRA*/ , 0); + BurnUpdateProgress(1.0 / ((double)(nSpriteSize/0x800000) * 8.0 / (nRomSize / 0x400000) / 3.0), _T("Decrypting graphics..."), 0); + + if ((i * nRomSize * 2) < 0x04000000) { + for (UINT32 j = 0; j < nRomSize * 2; j += 0x400000) { + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { +// BurnUpdateProgress(dProgress / 2.0, NULL/*, 0*/, 0); + (BurnDrvGetHardwareCode() & HARDWARE_SNK_KOF2K3) ? NeoKOFAddressDecrypt(pBuf2, pBuf1, j, j + 0x400000) : NeoSVCAddressDecrypt(pBuf2, pBuf1, j, j + 0x400000); + NeoPCBDataDecrypt(pBuf1 + j, 0x400000); + } +// BurnUpdateProgress(dProgress, NULL/*, 0*/, 0); + NeoCMCDecrypt(nNeoProtectionXor, pDest, pBuf1 + j, i * (nRomSize * 2) + j, 0x400000, nSpriteSize); + } + } else { + // The kof2k3 PCB has 96MB of graphics ROM, however the last 16MB are unused, and the protection/decryption hardware does not see them + + for (UINT32 j = 0; j < nRomSize; j += 0x400000) { +// BurnUpdateProgress(dProgress / 2.0, NULL/*, 0*/, 0); + NeoKOFAddressDecrypt(pBuf2, pBuf1, j, j + 0x400000); + NeoPCBDataDecrypt(pBuf1 + j, 0x400000); +// BurnUpdateProgress(dProgress, NULL, /*0,*/ 0); + NeoCMCDecrypt(nNeoProtectionXor, pDest + 0x4000000, pBuf1 + j, j, 0x400000, 0x1000000); + } + } + } + + if (pBuf2) { + free(pBuf2); + pBuf2 = NULL; + } + if (pBuf1) { + free(pBuf1); + pBuf1 = NULL; + } + + } else { + nSpriteSize = 0; + + // Compute correct size to gaps into account (Kizuna) + for (INT32 i = 0; i < nNum - 2; i++) { + BurnDrvGetRomInfo(&ri, nOffset + i); + if (ri.nLen > nRomSize) { + nRomSize = ri.nLen; + } + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_SPRITE32) { + for (INT32 i = 0; i < (nNum >> 2); i++) { + BurnLoadRom(pDest + nSpriteSize + 0, nOffset + 0 + (i << 2), 4); + BurnLoadRom(pDest + nSpriteSize + 2, nOffset + 1 + (i << 2), 4); + BurnLoadRom(pDest + nSpriteSize + 1, nOffset + 2 + (i << 2), 4); + BurnLoadRom(pDest + nSpriteSize + 3, nOffset + 3 + (i << 2), 4); + + BurnDrvGetRomInfo(&ri, nOffset + (i << 2)); + + if (i < (nNum >> 2) - 1) { + nSpriteSize += nRomSize << 2; + } else { + nSpriteSize += ri.nLen << 2; + } + } + } else { + for (INT32 i = 0; i < (nNum >> 1); i++) { + BurnLoadRom(pDest + nSpriteSize + 0, nOffset + (i << 1), 2); + BurnLoadRom(pDest + nSpriteSize + 1, nOffset + 1 + (i << 1), 2); + + BurnDrvGetRomInfo(&ri, nOffset + (i << 1)); + + if (i < (nNum >> 1) - 1) { + nSpriteSize += nRomSize << 1; + } else { + nSpriteSize += ri.nLen << 1; + } + } + } + } + + // Swap data for viewpoin, aof, ssideki, kotm2, more + if (BurnDrvGetHardwareCode() & HARDWARE_SNK_SWAPC) { + UINT8* pBuf = (UINT8*)malloc(0x600000); + + if (pBuf) { + for (INT32 i = 0x200000; i < 0x600000; i++) { + pBuf[i] = pDest[i]; + } + for (INT32 i = 0; i < 0x100000; i++) { + ((INT16*)(pDest + 0x200000))[i] = ((INT16*)(pBuf + 0x400000))[i]; + ((INT16*)(pDest + 0x400000))[i] = ((INT16*)(pBuf + 0x200000))[i]; + } + + free(pBuf); + pBuf = NULL; + } else { + return 1; + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Graphics decoding for MVS/AES + +void NeoDecodeSprites(UINT8* pDest, INT32 nSize) +{ +// double dProgress = 0.0; + +// if (nSize > 0x04000000) { +// nSize = 0x04000000; +// } + +/* if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_DEDICATED_PCB) { + dProgress = 1.0 / 32.0; + } else if (BurnDrvGetHardwareCode() & (HARDWARE_SNK_CMC42 | HARDWARE_SNK_CMC50)) { + dProgress = 1.0 / 24.0; + } else { + dProgress = 1.0 / 8.0; + }*/ + + for (INT32 i = 0; i < 8; i++) { + + UINT8* pStart = pDest + i * (nSize >> 3); + UINT8* pEnd = pStart + (nSize >> 3); + +// BurnUpdateProgress(dProgress, i ? NULL : _T("Preprocessing graphics...")/*, BST_PROCESS_GRA*/, 0); + + INT32 nStep = 8; + if (BurnDrvGetHardwareCode() & (HARDWARE_SNK_CMC42 | HARDWARE_SNK_CMC50)) { + nStep *= 4; + } + BurnUpdateProgress(1.0 / nStep, i ? NULL : _T("Preprocessing graphics..."), 0); + + // Pre-process the sprite graphics + for (UINT8* pTile = pStart; pTile < pEnd; pTile += 128) { + UINT32 data[32]; + + for (INT32 y = 0; y < 16; y++) { + UINT32 n = 0; + for (INT32 x = 0; x < 8; x++) { + UINT32 m = ((pTile[67 + (y << 2)] >> x) & 1) << 3; + m |= ((pTile[65 + (y << 2)] >> x) & 1) << 2; + m |= ((pTile[66 + (y << 2)] >> x) & 1) << 1; + m |= ((pTile[64 + (y << 2)] >> x) & 1) << 0; + + n |= m << (x << 2); + } + data[(y << 1) + 0] = n; + + n = 0; + for (INT32 x = 0; x < 8; x++) { + UINT32 m = ((pTile[3 + (y << 2)] >> x) & 1) << 3; + m |= ((pTile[1 + (y << 2)] >> x) & 1) << 2; + m |= ((pTile[2 + (y << 2)] >> x) & 1) << 1; + m |= ((pTile[0 + (y << 2)] >> x) & 1) << 0; + + n |= m << (x << 2); + } + data[(y << 1) + 1] = n; + } + for (INT32 n = 0; n < 32; n++) { + ((UINT32*)pTile)[n] = data[n]; + } + } + } +} + +/* +void NeoDecodeText(UINT8* pDest, INT32 nSize) +{ + // Pre-process the text layer graphics + for (UINT8* pTile = pDest; pTile < (pDest + nSize); pTile += 32) { + UINT8 data[32]; + for (INT32 n = 0; n < 8; n++) { + data[0 + n * 4] = pTile[16 + n]; + data[1 + n * 4] = pTile[24 + n]; + data[2 + n * 4] = pTile[ 0 + n]; + data[3 + n * 4] = pTile[ 8 + n]; + } + + for (INT32 n = 0; n < 32; n++) { + pTile[n] = data[n] << 4; + pTile[n] |= data[n] >> 4; + } + } +} +*/ + +// ---------------------------------------------------------------------------- +// Graphics decoding for Neo CD + +void NeoDecodeSpritesCD(UINT8* pData, UINT8* pDest, INT32 nSize) +{ + UINT8* pEnd = pData + nSize; + + for (UINT8* pTile = pData; pTile < pEnd; pTile += 128, pDest += 128) { + UINT32 data[32]; + + for (INT32 y = 0; y < 16; y++) { + UINT32 n = 0; + + for (INT32 x = 0; x < 8; x++) { + UINT32 m = ((pTile[67 + (y << 2)] >> x) & 1) << 3; + m |= ((pTile[66 + (y << 2)] >> x) & 1) << 2; + m |= ((pTile[65 + (y << 2)] >> x) & 1) << 1; + m |= ((pTile[64 + (y << 2)] >> x) & 1) << 0; + + n |= m << (x << 2); + } + data[(y << 1) + 0] = n; + + n = 0; + for (INT32 x = 0; x < 8; x++) { + UINT32 m = ((pTile[3 + (y << 2)] >> x) & 1) << 3; + m |= ((pTile[2 + (y << 2)] >> x) & 1) << 2; + m |= ((pTile[1 + (y << 2)] >> x) & 1) << 1; + m |= ((pTile[0 + (y << 2)] >> x) & 1) << 0; + + n |= m << (x << 2); + } + data[(y << 1) + 1] = n; + } + + for (INT32 n = 0; n < 32; n++) { + ((UINT32*)pDest)[n] = data[n]; + } + } +} + +// ---------------------------------------------------------------------------- + +INT32 NeoLoadADPCM(INT32 nOffset, INT32 nNum, UINT8* pDest) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + + BurnDrvGetRomInfo(&ri, nOffset); + + for (INT32 i = 0; i < nNum; i++) { + BurnLoadRom(pDest + ri.nLen * i, nOffset + i, 1); + } + + return 0; +} + +// This function fills the screen with the first palette entry +void NeoClearScreen() +{ + UINT32 nColour = NeoPalette[0x0FFF]; + + if (nColour) { + switch (nBurnBpp) { + case 4: { + UINT32* pClear = (UINT32*)pBurnDraw; + for (INT32 i = 0; i < nNeoScreenWidth * 224 / 8; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + + case 3: { + UINT8* pClear = pBurnDraw; + UINT8 r = nColour; + UINT8 g = (nColour >> 8) & 0xFF; + UINT8 b = (nColour >> 16) & 0xFF; + for (INT32 i = 0; i < nNeoScreenWidth * 224; i++) { + *pClear++ = r; + *pClear++ = g; + *pClear++ = b; + } + break; + } + + case 2: { + UINT32* pClear = (UINT32*)pBurnDraw; + nColour |= nColour << 16; + for (INT32 i = 0; i < nNeoScreenWidth * 224 / 16; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + } + } else { + memset(pBurnDraw, 0, nNeoScreenWidth * 224 * nBurnBpp); + } +} diff --git a/src/burn/drivers/neogeo/neogeo.h b/src/burn/drivers/neogeo/neogeo.h new file mode 100644 index 00000000..96fec9a5 --- /dev/null +++ b/src/burn/drivers/neogeo/neogeo.h @@ -0,0 +1,160 @@ +#include "burnint.h" + +// Uncomment the following line to make the display the full 320 pixels wide +#define NEO_DISPLAY_OVERSCAN + +#if defined NEO_DISPLAY_OVERSCAN + extern INT32 nNeoScreenWidth;// = 320; +#else + extern INT32 nNeoScreenWidth;// = 304; +#endif + +#define MAX_SLOT (8) + +#define NEO_SYS_CD (1 << 4) +#define NEO_SYS_PCB (1 << 3) +#define NEO_SYS_CART (1 << 2) +#define NEO_SYS_AES (1 << 1) +#define NEO_SYS_MVS (1 << 0) + +struct NeoGameInfo { + INT32 nCodeOffset; INT32 nCodeNum; + INT32 nTextOffset; + INT32 nSpriteOffset; INT32 nSpriteNum; + INT32 nSoundOffset; + INT32 nADPCMOffset; INT32 nADPCMANum; INT32 nADPCMBNum; + INT32 nNeoSRAMProtection; +}; + +struct NEO_CALLBACK { + void (*pInitialise)(); + void (*pInstallHandlers)(); + void (*pRemoveHandlers)(); + void (*pBankswitch)(); + INT32 (*pScan)(INT32, INT32*); +}; + +extern NEO_CALLBACK NeoCallback[MAX_SLOT]; +extern NEO_CALLBACK* NeoCallbackActive; + +// neogeo.cpp +void NeoClearScreen(); +INT32 NeoLoadCode(INT32 nOffset, INT32 nNum, UINT8* pDest); +INT32 NeoLoadSprites(INT32 nOffset, INT32 nNum, UINT8* pDest, UINT32 nSpriteSize); +INT32 NeoLoadADPCM(INT32 nOffset, INT32 nNum, UINT8* pDest); + +void NeoDecodeSprites(UINT8* pDest, INT32 nSize); +void NeoDecodeSpritesCD(UINT8* pData, UINT8* pDest, INT32 nSize); + +// neo_run.cpp +extern UINT8* NeoGraphicsRAM; + +extern UINT8 nNeoNumSlots; +extern UINT32 nNeoActiveSlot; + +extern UINT8 NeoButton1[]; +extern UINT8 NeoButton2[]; +extern UINT8 NeoButton3[]; +extern UINT8 NeoButton4[]; +extern UINT8 NeoJoy1[]; +extern UINT8 NeoJoy2[]; +extern UINT8 NeoJoy3[]; +extern UINT8 NeoJoy4[]; +extern UINT16 NeoAxis[]; +extern UINT8 NeoInput[]; +extern UINT8 NeoDiag[]; +extern UINT8 NeoDebugDip[]; +extern UINT8 NeoReset, NeoSystem; + +extern UINT8* Neo68KROMActive; +extern UINT8* NeoVectorActive; +extern UINT8* NeoZ80ROMActive; + +extern UINT8* YM2610ADPCMAROM[MAX_SLOT]; +extern UINT8* Neo68KFix[MAX_SLOT]; + +extern UINT32 nNeo68KROMBank; + +extern UINT8 *NeoSpriteRAM, *NeoTextRAM; + +extern bool bNeoEnableGraphics; + +INT32 NeoInit(); +INT32 NeoCDInit(); +INT32 NeoExit(); +INT32 NeoScan(INT32 nAction, INT32* pnMin); +INT32 NeoRender(); +INT32 NeoFrame(); + +void NeoMapBank(); +void NeoMap68KFix(); +void NeoUpdateVector(); + +// neo_palette.cpp +extern UINT8* NeoPalSrc[2]; +extern INT32 nNeoPaletteBank; +extern UINT32* NeoPalette; + +extern UINT8 NeoRecalcPalette; + +INT32 NeoInitPalette(); +void NeoExitPalette(); +INT32 NeoUpdatePalette(); +void NeoSetPalette(); + +void __fastcall NeoPalWriteByte(UINT32 nAddress, UINT8 byteValue); +void __fastcall NeoPalWriteWord(UINT32 nAddress, UINT16 wordValue); + +// neo_text.cpp +extern UINT8* NeoTextROMBIOS; +extern UINT8* NeoTextROM[MAX_SLOT]; +extern INT32 nNeoTextROMSize[MAX_SLOT]; +extern bool bBIOSTextROMEnabled; + +INT32 NeoInitText(INT32 nSlot); +void NeoSetTextSlot(INT32 nSlot); +void NeoExitText(INT32 nSlot); +INT32 NeoRenderText(); + +void NeoDecodeTextBIOS(INT32 nOffset, const INT32 nSize, UINT8* pData); +void NeoDecodeText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest); +void NeoUpdateTextOne(INT32 nOffset, const UINT8 byteValue); +void NeoUpdateText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest); + +// neo_sprite.cpp +extern UINT8* NeoSpriteROM[MAX_SLOT]; +extern UINT8* NeoZoomROM; + +extern INT32 nNeoSpriteFrame; +extern UINT32 nNeoTileMask[MAX_SLOT]; +extern INT32 nNeoMaxTile[MAX_SLOT]; + +extern INT32 nSliceStart, nSliceEnd, nSliceSize; + +void NeoUpdateSprites(INT32 nOffset, INT32 nSize); +void NeoSetSpriteSlot(INT32 nSlot); +INT32 NeoInitSprites(INT32 nSlot); +void NeoExitSprites(INT32 nSlot); +INT32 NeoRenderSprites(); + +// neo_decrypt.cpp +extern UINT8 nNeoProtectionXor; + +void NeoCMC42Init(); +void NeoCMC50Init(); +void NeoCMCDecrypt(INT32 extra_xor, UINT8* rom, UINT8* buf, INT32 offset, INT32 block_size, INT32 rom_size); +void NeoCMCExtractSData(UINT8* rom, UINT8* sdata, INT32 rom_size, INT32 sdata_size); + +void neogeo_cmc50_m1_decrypt(); + +// neo_upd4990a.cpp +void uPD4990AExit(); +void uPD499ASetTicks(UINT32 nTicksPerSecond); +INT32 uPD4990AInit(UINT32 nTicksPerSecond); +void uPD4990AScan(INT32 nAction, INT32* pnMin); +void uPD4990AUpdate(UINT32 nTicks); +void uPD4990AWrite(UINT8 CLK, UINT8 STB, UINT8 DATA); +UINT8 uPD4990ARead(UINT32 nTicks); + +// d_neogeo.cpp +void kf2k3pcb_bios_decode(); diff --git a/src/burn/drivers/pgm/changes.txt b/src/burn/drivers/pgm/changes.txt new file mode 100644 index 00000000..086ff4ba --- /dev/null +++ b/src/burn/drivers/pgm/changes.txt @@ -0,0 +1,221 @@ + * Changes + * + * 12-23-2010 + * Added ICS2115 timer changes from MAME + * + * 12-21-2010 + * Sped up sprite routines a bit + * Added custom bios from thegladpcb and ddp3 for use with regular cart games + * + * 12-19-2010 + * Documented coin counter functionality + * Added another ddp3 set (JackC) + * Added some .NV files to match mame + * Removed dw2001 decrypt routine - it uses the same routine as martmast + * Changed palette size + * Fixed FBA crash on olds & clones after high score screen + * Fixed olds intro (didn't affect olds100 & olds100a) + * Updated dumps for Ketsui and Espgaluda (redumped graphics) + * Changed protection routine names + * Fixed a bug with palette writes + * Sped up character tile decoding + * + * 12-17-2010 + * Added Espgaluda graphics and sound rom information + * Fixed date for kov2p + * Added Japanese title for Ketsui, Espgaluda, and DDP3 + * Fixed olds & Clones (Lantus) + * Fixed kov & Clones (Lantus) + * Fixed sprite zoom bug (Thanks JackC :)) + * + * 12-13-2010 + * Changed frames per second to 59.17 (causes some sound crackling on emulation start) + * + * 12-11-2010 + * Matched some sets to MAME (JackC [the man]) + * Added Cave sets + * Changed dips to "Off" and "On" instead of "Yes" or "No" + * Added Haze's ketsui/espgaluda/ddp3 protection simulation + * Simplified this and added savestate functionality + * Added Haze's video mirroring changes (ddp3) + * Changed some variable names to ensure no future conflicts + * Cleaned drawing routines a bit + * + * 11-07-2010 + * Matched sets to MAME (thanks to JackC for the help) + * Hopefully fixed a rare crash (drawing) + * Added missing IRQ4 for many games. I'm not sure if it affects anything, + * but emulation should be a bit more accurate now. + * Added PCB version of theglad + * Added decryption for several sets + * Added kludgy protection sim for ddp2 (mame 0.103) + * Added killing blade protection simulation + * Simplified hooking up protection simulations + * Fixed crashes for games without proper ARM7 dumps + * Disabled ARM7 protection simulation for these games + * Disabled loading of ARM7 roms (external) for these games + * Renamed some sets to be more consistent + * Renamed some protection routines to reflect which asic emulated/simulated + * Cleaned up decryption routines a bit + * Moved bootleg decryption routines to pgm_crypt.cpp + * Finally fixed the svg-type asic protection routines + * This makes killbldp show something (still not working though) + * Added idle loop skipping for killbldp (speedup) + * Fixed save state for kov and puzzle star asic simulation + * + * 02-27-2010 + * Added kov2a and kov2b (kov2b is disabled) partially dumped sets + * Thanks to JackC for helping sort a few sets. + * + * 12-05-2009 + * Added Happy6in1 (XingXing) + * Added newer 68k bios (XingXing) + * Added fake dip switch to switch beween 68k bios versions + * Added kovsh103 (XingXing) + * Added martmastc102 (XingXing) + * Added region dips for martmastc102 + * Added proper dump for demon front (alt) (XingXing) + * Added several pgm bootleg/hacks from MAME Plus + * Added proper dump for orlegendc + * Labeled region dips as "fake" as they are really hacks since PGM games + * usually have their regions supplied by the protection devices. + * + * 10-19-2009 + * Fixed kov2106 thanks to the FBA Shuffle team :) + * Added a few small speedups + * - Only recalculate the whole palette when needed now rather than every frame + * - Clear all video buffers in one loop + * Fixed a crash when doing line scroll (see kovsh intro - fire stage background) + * Fixed sound after save state load + * + * 04-24-2009 + * Updated a set few names + * + * 03-26-2009 + * Added protection emulation for kovsh & photoy2k (asic28) [XingXing] + * - Hooked up the arm7 cpu + * - Added speed hacks + * - Added region hacks + * Added crc information for svg, theglada, killbldp, kovh, ddp2/ddp2a, etc + * + * 03-19-2009 + * Added missing rom for olds100 + * Hooked up protection to olds and olds100 + * Updated some game information thanks to JackC + * + * 03-10-2009 + * Added another speed hack + * - detects idle loops (cpu loops, waiting for something to do) and skips them + * - Massive speedup! Helps kov2 (and clones) more than martmast though... + * Added a function to the arm7 core to enable idle loop skip + * - Must manually find address where loop starts + * Added region hack for kov2p & kov2p205 + * Added Creamymami Olds100a stage fix + * Removed olds100a.h -- just modifying the ram_dump instead (much smaller) + * Fixed loading bug with small games + * Removed previous speed hack - caused choppy sound + * + * 03-09-2009 + * Reduced amount of ram used by tiles + * - Also a tiny speedup for background tile drawing + * Added speed hack (not a lot faster) + * - burns 66 cycles from 68k or arm7 whenever triggered + * Greatly sped up the sprite drawing routine + * - cpu usage drops 20-40% depending on the game + * Added transparency table for background tiles + * - Small speedup for background drawing + * Added different routine for drawing background tiles without row scroll + * - Small speedup for background drawing + * Added transparency table for text tiles + * - Small speedup + * + * 03-08-2009 + * Added XingXing's Oriental Legends Special/Super protection simulation + * Fixed a crash if tile accessed is outside available tiles + * Fixed a crash if sample is accessed outside of available + * Added input opposite clearing + * Cleaned pgm_run.cpp a bit + * Renamed protection & reset routines + * + * 03-07-2009 + * Added hack/patch for kov2p & clones + * + * 03-03-2009 + * Added theglad's decryption (still missing internal arm7 rom, so not working) + * Put decryption code in order of style (68k + no table, 68k + table, arm7 + table) + * Fixed line in oriental legends background (improper alignment with sprites flipped) + * Fixed line in dragon world 2's background + * Added some unicode titles (thanks JackC) + * Fixed sprite priorities + * + * 02-28-2009 + * Improved sprite drawing routine, should be much faster + * - Non-zoomed sprites drawn by seperate routine + * - Still very slow... + * Cleaned up pgm_run.cpp, removed all protection read/writes + * - Moved protection read/writes to pgm_prot.cpp + * - Added callback for resetting protection routines + * Sped up Arm7/68k syncing slightly + * - Only sync on 68k reads + * Reduced memory allocated for 8x8 tiles (only actually need 4mb) + * + * 02-26-2009 + * Added decryption for kov2p + * Added kov2p205 (seems to be a valid dump) + * Cleaned up d_pgm.cpp + * Added region switch for asic27a games + * + * 02-22-2009 + * Added sprite zooming - slow!! + * Added sprite buffering + * Rewrote text drawing routine + * - Slightly faster + * - Supports X & Y flipping + * Added layer disabling (shots factory) + * + * 02-21-2009 + * Added Arm7 cpu support + * Added color independant transfer (high color support) + * Rewrote background drawing routine + * - Slightly faster + * - Fixed scrolling in kov2 + * - Added line scrolling (check fire level of kov) + * Fixed rom loading for kov2 + * Added Martial Masters (China) + * + * 07-09-2007 + * Sound available + * + * 07-06-2007 + * Change sceen scale 2:1 back to 4:3 ( sprites seems been stove ) + * Add nPgmPalRecalc, support color depth change while gamming + * fix Save states + * + * 07-04-2007 ( IQ_132's release ) + * Added all of BisonSAS's changes + * - Save State support + * - pgmPalUpdate() + * - Diagnostics Inputs + * - Dipswitches "Music and Voice" + * - Dipswitch "Disable Ba-Chieh" in sets orlegend, orlegnde and orlegndc + * - Removed chinese title in orlegend, orlegnde and orld105k + * - Save game configurations. (NVRAM) + * Drawing, protection, decrypt, sound, drivers, etc are all in seperate files + * All drivers for PGM games in MAME are added (though most, as in MAME, are not working) + * - Killing Blade, The (Chinese) is working (though glitchy) + * - Photoy2k & Real and Fake are working perfectly + * - Puzzle Star is working (though glitchy, freezes after second stage) + * - Dragon World 2 boots and runs, though the controls do not work (needs another irq?) + * - PGM Homebrew (PGM Frog Feast, PGM Demo) are supported (in the source) and work Perfectly + * All games have a shared loading routine (like CPS-2 and NeoGeo) + * All games have a shared memory map (like CPS-2 and NeoGeo) + * Improved Save states a little + * Removed code meant for low-ram environment + * Shortened and cleaned some code, removed a lot of 'printf's' + * Added all decrypt routines + * + * 06-09-2007 + * rows scrolls not emulated + * sprite zoom not emulated + * no sound (z80 and ics2115 not emulated) + * \ No newline at end of file diff --git a/src/burn/drivers/pgm/d_pgm.cpp b/src/burn/drivers/pgm/d_pgm.cpp new file mode 100644 index 00000000..7cd6882d --- /dev/null +++ b/src/burn/drivers/pgm/d_pgm.cpp @@ -0,0 +1,3506 @@ +// FB Alpha IGS PolyGameMaster driver module +// Original FB Alpha port by OopsWare +// Based on MAME driver by ElSemi + +#include "pgm.h" + +/* + IGS PolyGame Master game IDs + + ID# Year Game + 01 1997 Oriental Legend + 02 1997 Dragon World 2 + 03 1998 The Killing Blade + 04 1998 Dragon World 3 + 05 1999 Oriental Legend Super + 06 1999 Knights of Valour / Knights of Valour Plus / Knights of Valour Superheroes + 07 1999 Photo Y2k + 08 1999 Puzzle Star + 09 2001 Puzzli 2 Super + 10 2001 Martial Masters + 11 2001 Photo Y2k2 + 12 2000 Knights of Valour 2 / Knights of Valour 2 Plus + 13 2001 DoDonPachi 2 - Bee Storm + 14? 2001 Dragon World 2001 + + 44 2002 DoDonPachi Dai-Ou-Jou / DoDonPachi Dai-Ou-Jou Black Label + 45 2002 Demon Front + 46 2003 The Gladiator + 47 2002 Ketsui Kizuna Jigoku Tachi + 48 2003 Espgaluda + + 52? 2004 Happy 6in1 + 53 2004 Oriental Legend Special Plus + 54 2004 Knights of Valour Super Heroes Plus + 56 2005 S.V.G. - Spectral vs Generation + 57 2005 The Killing Blade Plus +*/ + +static struct BurnRomInfo emptyRomDesc[] = { + { "", 0, 0, 0 }, +}; + +static struct BurnInputInfo pgmInputList[] = { + {"P1 Coin", BIT_DIGITAL, PgmBtn1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, PgmJoy1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, PgmJoy1 + 1, "p1 up" }, + {"P1 Down", BIT_DIGITAL, PgmJoy1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, PgmJoy1 + 3, "p1 left" }, + {"P1 Right", BIT_DIGITAL, PgmJoy1 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, PgmJoy1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, PgmJoy1 + 6, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, PgmJoy1 + 7, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, PgmBtn2 + 0, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, PgmBtn1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, PgmJoy2 + 0, "p2 start" }, + {"P2 Up", BIT_DIGITAL, PgmJoy2 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, PgmJoy2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, PgmJoy2 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, PgmJoy2 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, PgmJoy2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, PgmJoy2 + 6, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, PgmJoy2 + 7, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, PgmBtn2 + 1, "p2 fire 4" }, + + {"P3 Coin", BIT_DIGITAL, PgmBtn1 + 2, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, PgmJoy3 + 0, "p3 start" }, + {"P3 Up", BIT_DIGITAL, PgmJoy3 + 1, "p3 up" }, + {"P3 Down", BIT_DIGITAL, PgmJoy3 + 2, "p3 down" }, + {"P3 Left", BIT_DIGITAL, PgmJoy3 + 3, "p3 left" }, + {"P3 Right", BIT_DIGITAL, PgmJoy3 + 4, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, PgmJoy3 + 5, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, PgmJoy3 + 6, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, PgmJoy3 + 7, "p3 fire 3" }, + {"P3 Button 4", BIT_DIGITAL, PgmBtn2 + 2, "p3 fire 4" }, + + {"P4 Coin", BIT_DIGITAL, PgmBtn1 + 3, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, PgmJoy4 + 0, "p4 start" }, + {"P4 Up", BIT_DIGITAL, PgmJoy4 + 1, "p4 up" }, + {"P4 Down", BIT_DIGITAL, PgmJoy4 + 2, "p4 down" }, + {"P4 Left", BIT_DIGITAL, PgmJoy4 + 3, "p4 left" }, + {"P4 Right", BIT_DIGITAL, PgmJoy4 + 4, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, PgmJoy4 + 5, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, PgmJoy4 + 6, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, PgmJoy4 + 7, "p4 fire 3" }, + {"P4 Button 4", BIT_DIGITAL, PgmBtn2 + 3, "p4 fire 4" }, + + {"Reset", BIT_DIGITAL, &PgmReset, "reset" }, + {"Diagnostics 1", BIT_DIGITAL, PgmBtn1 + 4, "diag" }, + {"Diagnostics 2", BIT_DIGITAL, PgmBtn1 + 6, "" }, + {"Service 1", BIT_DIGITAL, PgmBtn1 + 5, "service" }, + {"Service 2", BIT_DIGITAL, PgmBtn1 + 7, "service2" }, + + {"Dip A", BIT_DIPSWITCH, PgmInput + 6, "dip" }, + {"Dip B", BIT_DIPSWITCH, PgmInput + 7, "dip" }, + {"Dip C", BIT_DIPSWITCH, PgmInput + 8, "dip" }, +}; + +STDINPUTINFO(pgm) + +static struct BurnDIPInfo pgmDIPList[] = { + {0x2D, 0xFF, 0xFF, 0x00, NULL }, + {0x2F, 0xFF, 0x01, 0x01, NULL }, + + {0, 0xFE, 0, 2, "Test mode" }, + {0x2D, 0x01, 0x01, 0x00, "Off" }, + {0x2D, 0x01, 0x01, 0x01, "On" }, + + {0, 0xFE, 0, 2, "Music" }, + {0x2D, 0x01, 0x02, 0x02, "Off" }, + {0x2D, 0x01, 0x02, 0x00, "On" }, + + {0, 0xFE, 0, 2, "Voice" }, + {0x2D, 0x01, 0x04, 0x04, "Off" }, + {0x2D, 0x01, 0x04, 0x00, "On" }, + + {0, 0xFE, 0, 2, "Free play" }, + {0x2D, 0x01, 0x08, 0x00, "Off" }, + {0x2D, 0x01, 0x08, 0x08, "On" }, + + {0, 0xFE, 0, 2, "Stop mode" }, + {0x2D, 0x01, 0x10, 0x00, "Off" }, + {0x2D, 0x01, 0x10, 0x10, "On" }, + + {0, 0xFE, 0, 4, "Bios select (Fake)" }, + {0x2F, 0x01, 0x0f, 0x00, "Older" }, + {0x2F, 0x01, 0x0f, 0x01, "Newer" }, + {0x2F, 0x01, 0x0f, 0x02, "Newer (no intro, calendar)" }, + {0x2F, 0x01, 0x0f, 0x03, "Newer (no intro)" }, +}; + +STDDIPINFO(pgm) + +static struct BurnDIPInfo jammaDIPList[] = { + {0x2D, 0xFF, 0xFF, 0x00, NULL }, + {0x2F, 0xFF, 0x01, 0x00, NULL }, + + {0, 0xFE, 0, 2, "Test mode" }, + {0x2D, 0x01, 0x01, 0x00, "Off" }, + {0x2D, 0x01, 0x01, 0x01, "On" }, + + {0, 0xFE, 0, 2, "Music" }, + {0x2D, 0x01, 0x02, 0x02, "Off" }, + {0x2D, 0x01, 0x02, 0x00, "On" }, + + {0, 0xFE, 0, 2, "Voice" }, + {0x2D, 0x01, 0x04, 0x04, "Off" }, + {0x2D, 0x01, 0x04, 0x00, "On" }, + + {0, 0xFE, 0, 2, "Free play" }, + {0x2D, 0x01, 0x08, 0x00, "Off" }, + {0x2D, 0x01, 0x08, 0x08, "On" }, + + {0, 0xFE, 0, 2, "Stop mode" }, + {0x2D, 0x01, 0x10, 0x00, "Off" }, + {0x2D, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(jamma) + +static struct BurnDIPInfo orlegendDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x00, NULL }, + + {0, 0xFE, 0, 2, "Disable Ba-Chieh" }, + {0x2E, 0x02, 0x01, 0x00, "Off" }, + {0x2E, 0x02, 0x01, 0x01, "On" }, + + {0, 0xFE, 0, 3, "Region (Fake)" }, + {0x2E, 0x01, 0x03, 0x00, "World" }, + {0x2E, 0x01, 0x03, 0x02, "Korea" }, + {0x2E, 0x01, 0x03, 0x03, "China" }, +}; + +static struct BurnDIPInfo orlegend112cDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x03, NULL }, + + {0, 0xFE, 0, 2, "Disable Ba-Chieh" }, + {0x2E, 0x02, 0x01, 0x00, "Off" }, + {0x2E, 0x02, 0x01, 0x01, "On" }, + + {0, 0xFE, 0, 3, "Region (Fake)" }, + {0x2E, 0x01, 0x03, 0x00, "World" }, + {0x2E, 0x01, 0x03, 0x02, "Korea" }, + {0x2E, 0x01, 0x03, 0x03, "China" }, +}; + +static struct BurnDIPInfo orld111cDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x02, NULL }, + + {0, 0xFE, 0, 2, "Region (Fake)" }, + {0x2E, 0x01, 0x03, 0x00, "Hong Kong" }, + {0x2E, 0x01, 0x03, 0x02, "China" }, +}; + +static struct BurnDIPInfo orld105kDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x02, NULL }, +}; + +static struct BurnDIPInfo sangoDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x05, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x00, "China" }, + {0x2E, 0x01, 0x0F, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x02, "Japan" }, + {0x2E, 0x01, 0x0F, 0x03, "Korea" }, + {0x2E, 0x01, 0x0F, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x05, "World" }, +}; + +static struct BurnDIPInfo oldsDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x04, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x02, "China" }, + {0x2E, 0x01, 0x0F, 0x03, "Japan" }, + {0x2E, 0x01, 0x0F, 0x04, "Korea" }, + {0x2E, 0x01, 0x0F, 0x05, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x06, "World" }, +}; + +static struct BurnDIPInfo olds100DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x05, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x02, "China" }, + {0x2E, 0x01, 0x0F, 0x03, "Japan" }, + {0x2E, 0x01, 0x0F, 0x04, "Korea" }, + {0x2E, 0x01, 0x0F, 0x05, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x06, "World" }, +}; + +static struct BurnDIPInfo kov100DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x02, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x00, "China" }, + {0x2E, 0x01, 0x0F, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x02, "Japan" }, + {0x2E, 0x01, 0x0F, 0x03, "Korea" }, + {0x2E, 0x01, 0x0F, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x05, "World" }, +}; + +static struct BurnDIPInfo killbldDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x21, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0xFF, 0x16, "Taiwan" }, + {0x2E, 0x01, 0xFF, 0x17, "China" }, + {0x2E, 0x01, 0xFF, 0x18, "Hong Kong" }, + {0x2E, 0x01, 0xFF, 0x19, "Japan" }, + {0x2E, 0x01, 0xFF, 0x20, "Korea" }, + {0x2E, 0x01, 0xFF, 0x21, "World" }, +}; + +static struct BurnDIPInfo photoy2kDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x03, NULL }, + + {0, 0xFE, 0, 7, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x00, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x01, "China" }, + {0x2E, 0x01, 0x0F, 0x02, "Japan" }, + {0x2E, 0x01, 0x0F, 0x03, "World" }, + {0x2E, 0x01, 0x0F, 0x04, "Korea" }, + {0x2E, 0x01, 0x0F, 0x05, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x06, "Singapore / Malaysia" }, +}; + +static struct BurnDIPInfo raf102jDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x02, NULL }, + + {0, 0xFE, 0, 7, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x00, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x01, "China" }, + {0x2E, 0x01, 0x0F, 0x02, "Japan" }, + {0x2E, 0x01, 0x0F, 0x03, "World" }, + {0x2E, 0x01, 0x0F, 0x04, "Korea" }, + {0x2E, 0x01, 0x0F, 0x05, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x06, "Singapore / Malaysia" }, +}; + +static struct BurnDIPInfo puzzli2DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x05, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x0F, 0x00, "Taiwan" }, + {0x2E, 0x01, 0x0F, 0x01, "China" }, + {0x2E, 0x01, 0x0F, 0x02, "Japan" }, + {0x2E, 0x01, 0x0F, 0x03, "Korea" }, + {0x2E, 0x01, 0x0F, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x0F, 0x05, "World" }, +}; + +static struct BurnDIPInfo kov2DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x04, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x07, 0x00, "China" }, + {0x2E, 0x01, 0x07, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x07, 0x02, "Japan" }, + {0x2E, 0x01, 0x07, 0x03, "Korea" }, + {0x2E, 0x01, 0x07, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x07, 0x05, "World" }, +}; + +static struct BurnDIPInfo martmastDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x06, NULL }, + + {0, 0xFE, 0, 7, "Region (Fake)" }, + {0x2E, 0x01, 0x07, 0x00, "China" }, + {0x2E, 0x01, 0x07, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x07, 0x02, "China" }, + {0x2E, 0x01, 0x07, 0x03, "Korea" }, + {0x2E, 0x01, 0x07, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x07, 0x05, "World" }, + {0x2E, 0x01, 0x07, 0x06, "USA" }, +}; + +static struct BurnDIPInfo martmastcDIPList[] = { + {0x2E, 0xFF, 0xFF, 0x00, NULL }, + + {0, 0xFE, 0, 7, "Region (Fake)" }, + {0x2E, 0x01, 0x07, 0x00, "China" }, + {0x2E, 0x01, 0x07, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x07, 0x02, "China" }, + {0x2E, 0x01, 0x07, 0x03, "Korea" }, + {0x2E, 0x01, 0x07, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x07, 0x05, "World" }, + {0x2E, 0x01, 0x07, 0x06, "USA" }, +}; + +static struct BurnDIPInfo martmastc102DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x00, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x07, 0x00, "China" }, + {0x2E, 0x01, 0x07, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x07, 0x02, "Japan" }, + {0x2E, 0x01, 0x07, 0x03, "Korea" }, + {0x2E, 0x01, 0x07, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x07, 0x05, "World" }, +}; + +static struct BurnDIPInfo ddp2DIPList[] = { + {0x2E, 0xFF, 0xFF, 0x00, NULL }, + + {0, 0xFE, 0, 6, "Region (Fake)" }, + {0x2E, 0x01, 0x07, 0x00, "China" }, + {0x2E, 0x01, 0x07, 0x01, "Taiwan" }, + {0x2E, 0x01, 0x07, 0x02, "Japan (Cave License)" }, + {0x2E, 0x01, 0x07, 0x03, "Korea" }, + {0x2E, 0x01, 0x07, 0x04, "Hong Kong" }, + {0x2E, 0x01, 0x07, 0x05, "World" }, +}; + +STDDIPINFOEXT(orlegend, pgm, orlegend ) +STDDIPINFOEXT(orlegend112c, pgm, orlegend112c ) +STDDIPINFOEXT(orld111c, pgm, orld111c ) +STDDIPINFOEXT(orld105k, pgm, orld105k ) +STDDIPINFOEXT(sango, pgm, sango ) +STDDIPINFOEXT(kov100, pgm, kov100 ) +STDDIPINFOEXT(killbld, pgm, killbld ) +STDDIPINFOEXT(photoy2k, pgm, photoy2k ) +STDDIPINFOEXT(raf102j, pgm, raf102j ) +STDDIPINFOEXT(puzzli2, pgm, puzzli2 ) +STDDIPINFOEXT(kov2, pgm, kov2 ) +STDDIPINFOEXT(martmast, pgm, martmast ) +STDDIPINFOEXT(martmastc, pgm, martmastc ) +STDDIPINFOEXT(martmastc102, pgm, martmastc102 ) +STDDIPINFOEXT(olds, pgm, olds ) +STDDIPINFOEXT(olds100, pgm, olds100 ) +STDDIPINFOEXT(ddp2, pgm, ddp2 ) + +// ----------------------------------------------------------------------------- +// BIOS + + +// PGM (Polygame Master) System BIOS + +static struct BurnRomInfo pgmRomDesc[] = { + { "pgm_t01s.rom", 0x200000, 0x1a7123a0, BRF_GRA | BRF_BIOS }, // 0x80 - 8x8 Text Layer Tiles + { "pgm_m01s.rom", 0x200000, 0x45ae7159, BRF_SND | BRF_BIOS }, // 0x81 - Samples + + { "pgm_p01s.u20", 0x020000, 0xe42b166e, BRF_PRG | BRF_BIOS }, // 0x82 - 68K BIOS (V0001, older - 02/26/97 - 11:14:09) + { "pgm_p02s.u20", 0x020000, 0x78C15FA2, BRF_PRG | BRF_BIOS }, // 0x83 - 68K BIOS (V0001, newer - 07/10/97 - 16:36:08) +#if !defined (ROM_VERIFY) + { "ddp3_bios.u37",0x080000, 0xB3CC5C8F, BRF_PRG | BRF_BIOS }, // 0x84 - 68K BIOS (V0001, custom - 07/17/97 - 19:44:59) + { "bios.u42", 0x020000, 0x517CF7A2, BRF_PRG | BRF_BIOS }, // 0x85 - 68K BIOS (V0001-01J, custom - 02/25/03 - 17:51:01) +#else + { "", 0x000000, 0x00000000, 0 }, // 0x84 + { "", 0x000000, 0x00000000, 0 }, // 0x85 +#endif +}; + +STD_ROM_PICK(pgm) +STD_ROM_FN(pgm) + +struct BurnDriver BurnDrvPgm = { + "pgm", NULL, NULL, NULL, "1997", + "PGM (Polygame Master) System BIOS\0", "BIOS only", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_BOARDROM, 0, HARDWARE_IGS_PGM, GBF_BIOS, 0, + NULL, pgmRomInfo, pgmRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + pgmInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +static struct BurnRomInfo thegladBIOSRomDesc[] = { + { "pgm_t01s.rom", 0x200000, 0x1a7123a0, BRF_GRA | BRF_BIOS }, // 0x80 - 8x8 Text Layer Tiles + + { "pgm_m01s.rom", 0x200000, 0x45ae7159, BRF_SND | BRF_BIOS }, // 0x81 - Samples + + { "bios.u42", 0x020000, 0x517CF7A2, BRF_PRG | BRF_BIOS }, // 0x82 - 68K BIOS (V0001-01J, custom? 02/25/03 17:51:01) + + { "wave.u29", 0x200000, 0x51ACB395, BRF_SND | BRF_BIOS }, // 0x83 - More samples +}; + + +static struct BurnRomInfo ketsuiBiosRomDesc[] = { + { "pgm_t01s.rom", 0x200000, 0x1a7123a0, BRF_GRA | BRF_BIOS }, // 0x80 - 8x8 Text Layer Tiles + { "", 0, 0, 0 }, // 0x81 - Samples + + { "", 0, 0, 0 }, // 0x82 - 68K BIOS + { "", 0, 0, 0 }, // 0x83 - 68K BIOS +}; + + +static struct BurnRomInfo espgalBiosRomDesc[] = { + { "t01s.u18", 0x200000, 0x1a7123a0, BRF_GRA | BRF_BIOS }, // 0x80 - 8x8 Text Layer Tiles + { "", 0, 0, 0 }, // 0x81 - Samples + + { "", 0, 0, 0 }, // 0x82 - 68K BIOS + { "", 0, 0, 0 }, // 0x83 - 68K BIOS +}; + + +static struct BurnRomInfo ddp3BiosRomDesc[] = { + { "pgm_t01s.rom", 0x200000, 0x1a7123a0, BRF_GRA | BRF_BIOS }, // 0x80 - 8x8 Text Layer Tiles + + { "pgm_m01s.rom", 0x200000, 0x45ae7159, BRF_SND | BRF_BIOS }, // 0x81 - Samples + + { "ddp3_bios.u37",0x080000, 0xB3CC5C8F, BRF_PRG | BRF_BIOS }, // 0x82 - 68K BIOS (V0001, custom? 07/17/97 19:44:59) +}; + + +// ----------------------------------------------------------------------------- +// Normal Games + + +// Oriental Legend / Xi Yo Gi Shi Re Zuang (V126) + +static struct BurnRomInfo orlegendRomDesc[] = { + { "p0103.rom", 0x200000, 0xd5e93543, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend, orlegend, pgm) +STD_ROM_FN(orlegend) + +static INT32 orlegendInit() +{ + pPgmProtCallback = install_protection_asic3_orlegend; + + return pgmInit(); +} + +struct BurnDriver BurnDrvOrlegend = { + "orlegend", NULL, "pgm", NULL, "1997", + "Oriental Legend - Xi Yo Gi Shi Re Zuang (V126)\0", NULL, "IGS", "PolyGameMaster", + L"Oriental Legend\0\u897F\u6E38\u91CA\u5384\u4F20 (V126)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegendRomInfo, orlegendRomName, NULL, NULL, pgmInputInfo, orlegendDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend / Xi Yo Gi Shi Re Zuang (V112) + +static struct BurnRomInfo orlegend112eRomDesc[] = { + { "p0102.rom", 0x200000, 0x4d0f6cc5, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend112e, orlegend112e, pgm) +STD_ROM_FN(orlegend112e) + +struct BurnDriver BurnDrvOrlegend112e = { + "orlegende", "orlegend", "pgm", NULL, "1997", + "Oriental Legend - Xi Yo Gi Shi Re Zuang (V112)\0", NULL, "IGS", "PolyGameMaster", + L"Oriental Legend\0\u897F\u6E38\u91CA\u5384\u4F20 (V112)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegend112eRomInfo, orlegend112eRomName, NULL, NULL, pgmInputInfo, orlegendDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend / Xi Yo Gi Shi Re Zuang (V112, China) + +static struct BurnRomInfo orlegend112cRomDesc[] = { + { "p0101.160", 0x200000, 0xb24f0c1e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend112c, orlegend112c, pgm) +STD_ROM_FN(orlegend112c) + +struct BurnDriver BurnDrvOrlegend112c = { + "orlegendc", "orlegend", "pgm", NULL, "1997", + "Oriental Legend - Xi Yo Gi Shi Re Zuang (V112, China)\0", NULL, "IGS", "PolyGameMaster", + L"Oriental Legend\0\u897F\u6E38\u91CA\u5384\u4F20 (V112, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegend112cRomInfo, orlegend112cRomName, NULL, NULL, pgmInputInfo, orlegend112cDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend / Xi Yo Gi Shi Re Zuang (V112 alt,China) + +static struct BurnRomInfo orlegend112caRomDesc[] = { + { "p0101.102", 0x200000, 0x7a22e1cb, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend112ca, orlegend112ca, pgm) +STD_ROM_FN(orlegend112ca) + +struct BurnDriver BurnDrvOrlegend112ca = { + "orlegendca", "orlegend", "pgm", NULL, "1997", + "Oriental Legend - Xi Yo Gi Shi Re Zuang (V112 alt, China)\0", NULL, "IGS", "PolyGameMaster", + L"Oriental Legend\0\u897F\u6E38\u91CA\u5384\u4F20 (V112 alt, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegend112caRomInfo, orlegend112caRomName, NULL, NULL, pgmInputInfo, orlegend112cDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend / Xi Yo Gi Shi Re Zuang (V111, China) + +static struct BurnRomInfo orlegend111cRomDesc[] = { + { "olv111ch.u6", 0x080000, 0x5fb86373, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "olv111ch.u9", 0x080000, 0x83cf09c8, 1 | BRF_PRG | BRF_ESS }, // 1 + { "olv111ch.u7", 0x080000, 0x6ee79faf, 1 | BRF_PRG | BRF_ESS }, // 2 + { "olv111ch.u11", 0x080000, 0xb80ddd3c, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend111c, orlegend111c, pgm) +STD_ROM_FN(orlegend111c) + +struct BurnDriver BurnDrvOrlegend111c = { + "orlegend111c", "orlegend", "pgm", NULL, "1997", + "Oriental Legend - Xi Yo Gi Shi Re Zuang (V111, China)\0", NULL, "IGS", "PolyGameMaster", + L"Oriental Legend\0\u897F\u6E38\u91CA\u5384\u4F20 (V111, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegend111cRomInfo, orlegend111cRomName, NULL, NULL, pgmInputInfo, orld111cDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend (V105, Korea) + +static struct BurnRomInfo orlegend105kRomDesc[] = { + { "olv105ko.u6", 0x080000, 0xb86703fe, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "olv105ko.u9", 0x080000, 0x5a108e39, 1 | BRF_PRG | BRF_ESS }, // 1 + { "olv105ko.u7", 0x080000, 0x5712facc, 1 | BRF_PRG | BRF_ESS }, // 2 + { "olv105ko.u11", 0x080000, 0x40ae4d9e, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "t0100.rom", 0x400000, 0x61425e1e, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x8b3bd88a, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0101.rom", 0x400000, 0x3b9e9644, 3 | BRF_GRA }, // 3 + { "a0102.rom", 0x400000, 0x069e2c38, 3 | BRF_GRA }, // 4 + { "a0103.rom", 0x400000, 0x4460a3fd, 3 | BRF_GRA }, // 5 + { "a0104.rom", 0x400000, 0x5f8abb56, 3 | BRF_GRA }, // 6 + { "a0105.rom", 0x400000, 0xa17a7147, 3 | BRF_GRA }, // 7 + + { "b0100.rom", 0x400000, 0x69d2e48c, 4 | BRF_GRA }, // 8 Sprite Masks & Color Indexes + { "b0101.rom", 0x400000, 0x0d587bf3, 4 | BRF_GRA }, // 9 + { "b0102.rom", 0x400000, 0x43823c1e, 4 | BRF_GRA }, // 10 + + { "m0100.rom", 0x200000, 0xe5c36c83, 5 | BRF_SND }, // 11 Samples +}; + +STDROMPICKEXT(orlegend105k, orlegend105k, pgm) +STD_ROM_FN(orlegend105k) + +struct BurnDriver BurnDrvOrlegend105k = { + "orlegend105k", "orlegend", "pgm", NULL, "1997", + "Oriental Legend (V105, Korea)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, orlegend105kRomInfo, orlegend105kRomName, NULL, NULL, pgmInputInfo, orld105kDIPInfo, + orlegendInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Dragon World II (V110X, World) + +static struct BurnRomInfo drgw2RomDesc[] = { + { "v-110x.u2", 0x080000, 0x1978106b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "pgmt0200.u7", 0x400000, 0xb0f6534d, 2 | BRF_GRA }, // 1 Tile data + + { "pgma0200.u5", 0x400000, 0x13b95069, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "pgmb0200.u9", 0x400000, 0x932d0f13, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes +}; + +STDROMPICKEXT(drgw2, drgw2, pgm) +STD_ROM_FN(drgw2) + +static void drgw2_patch() +{ + pgm_decrypt_dw2(); + + *((UINT16*)(PGM68KROM + 0x031098)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x03113e)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x0311ce)) = SWAP_WORD_LSB(0x4e93); +} + +static INT32 drgw2Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = drgw2_patch; + pPgmProtCallback = install_protection_asic25_asic12_dw2; + + return pgmInit(); +} + +struct BurnDriver BurnDrvDrgw2 = { + "drgw2", NULL, "pgm", NULL, "1997", + "Dragon World II (V110X, World)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw2RomInfo, drgw2RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Zhong Guo Long II (V100C, China) + +static struct BurnRomInfo drgw2cRomDesc[] = { + { "v-100c.u2", 0x080000, 0x67467981, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "pgmt0200.u7", 0x400000, 0xb0f6534d, 2 | BRF_GRA }, // 1 Tile data + + { "pgma0200.u5", 0x400000, 0x13b95069, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "pgmb0200.u9", 0x400000, 0x932d0f13, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes +}; + +STDROMPICKEXT(drgw2c, drgw2c, pgm) +STD_ROM_FN(drgw2c) + +static void drgw2100c_patch() +{ + pgm_decrypt_dw2(); + + *((UINT16*)(PGM68KROM + 0x0303bc)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x030462)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x0304F2)) = SWAP_WORD_LSB(0x4e93); +} + +static INT32 drgw2100cInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = drgw2100c_patch; + pPgmProtCallback = install_protection_asic25_asic12_dw2; + + return pgmInit(); +} + +struct BurnDriver BurnDrvDrgw2c = { + "drgw2c", "drgw2", "pgm", NULL, "1997", + "Zhong Guo Long II (V100C, China)\0", NULL, "IGS", "PolyGameMaster", + L"\u4E2D\u570B\u9F8D II (V100C, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw2cRomInfo, drgw2cRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw2100cInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 448, 224, 4, 3 +}; + + +// Chuugokuryuu II (V100J, Japan) + +static struct BurnRomInfo drgw2jRomDesc[] = { + { "v-100j.u2", 0x080000, 0xf8f8393e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "pgmt0200.u7", 0x400000, 0xb0f6534d, 2 | BRF_GRA }, // 1 Tile data + + { "pgma0200.u5", 0x400000, 0x13b95069, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "pgmb0200.u9", 0x400000, 0x932d0f13, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes +}; + +STDROMPICKEXT(drgw2j, drgw2j, pgm) +STD_ROM_FN(drgw2j) + +static void drgw2100j_patch() +{ + pgm_decrypt_dw2(); + + *((UINT16*)(PGM68KROM + 0x0302C0)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x030366)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x0303F6)) = SWAP_WORD_LSB(0x4e93); +} + +static INT32 drgw2100jInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = drgw2100j_patch; + pPgmProtCallback = install_protection_asic25_asic12_dw2; + + return pgmInit(); +} + +struct BurnDriver BurnDrvDrgw2j = { + "drgw2j", "drgw2", "pgm", NULL, "1997", + "Chuugokuryuu II (V100J, Japan)\0", NULL, "IGS", "PolyGameMaster", + L"\u4E2D\u570B\u9F8D II (V100J, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw2jRomInfo, drgw2jRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw2100jInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 448, 224, 4, 3 +}; + + +// Dragon World II (V100X, World) + +static struct BurnRomInfo drgw2xRomDesc[] = { + { "dragonv100x.bin", 0x080000, 0x5e71851d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "pgmt0200.u7", 0x400000, 0xb0f6534d, 2 | BRF_GRA }, // 1 Tile data + + { "pgma0200.u5", 0x400000, 0x13b95069, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "pgmb0200.u9", 0x400000, 0x932d0f13, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes +}; + +STDROMPICKEXT(drgw2x, drgw2x, pgm) +STD_ROM_FN(drgw2x) + +static void drgw2100x_patch() +{ + pgm_decrypt_dw2(); + + *((UINT16*)(PGM68KROM + 0x031084)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x03112A)) = SWAP_WORD_LSB(0x4e93); + *((UINT16*)(PGM68KROM + 0x0311BA)) = SWAP_WORD_LSB(0x4e93); +} + +static INT32 drgw2100xInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = drgw2100x_patch; + pPgmProtCallback = install_protection_asic25_asic12_dw2; + + return pgmInit(); +} + +struct BurnDriver BurnDrvDrgw2x = { + "dw2v100x", "drgw2", "pgm", NULL, "1997", + "Dragon World II (V100X, World)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw2xRomInfo, drgw2xRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw2100xInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 448, 224, 4, 3 +}; + + +// The Killing Blade (V109, China) + +static struct BurnRomInfo killbldRomDesc[] = { + { "p0300_v109.u9", 0x200000, 0x2fcee215, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0300.u14", 0x400000, 0x0922f7d9, 2 | BRF_GRA }, // 1 Tile data + + { "a0300.u9", 0x400000, 0x3f9455d3, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0301.u10", 0x400000, 0x92776889, 3 | BRF_GRA }, // 3 + { "a0303.u11", 0x400000, 0x33f5cc69, 3 | BRF_GRA }, // 4 + { "a0306.u12", 0x400000, 0xcc018a8e, 3 | BRF_GRA }, // 5 + { "a0307.u2", 0x400000, 0xbc772e39, 3 | BRF_GRA }, // 6 + + { "b0300.u13", 0x400000, 0x7f876981, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b0302.u14", 0x400000, 0xeea9c502, 4 | BRF_GRA }, // 8 + { "b0303.u15", 0x200000, 0x77a9652e, 4 | BRF_GRA }, // 9 + + { "m0300.u1", 0x400000, 0x93159695, 5 | BRF_SND }, // 10 Samples + + { "kb_u2.rom", 0x010000, 0xde3eae63, 0 | BRF_PRG | BRF_ESS }, // 11 Protection Data +}; + +STDROMPICKEXT(killbld, killbld, pgm) +STD_ROM_FN(killbld) + +static INT32 killbldInit() +{ + pPgmInitCallback = pgm_decrypt_killbld; + pPgmProtCallback = install_protection_asic25_asic22_killbld; + + return pgmInit(); +} + +struct BurnDriver BurnDrvKillbld = { + "killbld", NULL, "pgm", NULL, "1998", + "The Killing Blade (V109, China)\0", NULL, "IGS", "PolyGameMaster", + L"The Killing Blade\0\u50B2\u5251\u72C2\u5200\0\u50B2\u528D\u72C2\u5200 (V109, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM, GBF_VSFIGHT, 0, + NULL, killbldRomInfo, killbldRomName, NULL, NULL, pgmInputInfo, killbldDIPInfo, + killbldInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// The Killing Blade (V104) + +static struct BurnRomInfo killbld104RomDesc[] = { + { "kb_u3_v104.u3", 0x080000, 0x6db1d719, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "kb_u6_v104.u6", 0x080000, 0x31ecc978, 1 | BRF_PRG | BRF_ESS }, // 1 + { "kb_u4_v104.u4", 0x080000, 0x1ed8b2e7, 1 | BRF_PRG | BRF_ESS }, // 2 + { "kb_u5_v104.u5", 0x080000, 0xa0bafc29, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "t0300.u14", 0x400000, 0x0922f7d9, 2 | BRF_GRA }, // 4 Tile data + + { "a0300.u9", 0x400000, 0x3f9455d3, 3 | BRF_GRA }, // 5 Sprite Color Data + { "a0301.u10", 0x400000, 0x92776889, 3 | BRF_GRA }, // 6 + { "a0303.u11", 0x400000, 0x33f5cc69, 3 | BRF_GRA }, // 7 + { "a0306.u12", 0x400000, 0xcc018a8e, 3 | BRF_GRA }, // 8 + { "a0307.u2", 0x400000, 0xbc772e39, 3 | BRF_GRA }, // 9 + + { "b0300.u13", 0x400000, 0x7f876981, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0302.u14", 0x400000, 0xeea9c502, 4 | BRF_GRA }, // 11 + { "b0303.u15", 0x200000, 0x77a9652e, 4 | BRF_GRA }, // 12 + + { "m0300.u1", 0x400000, 0x93159695, 5 | BRF_SND }, // 13 Samples + + { "kb_u2_v104.u2", 0x010000, 0xc970f6d5, 0 | BRF_PRG | BRF_ESS }, // 14 Protection Data +}; + +STDROMPICKEXT(killbld104, killbld104, pgm) +STD_ROM_FN(killbld104) + +struct BurnDriver BurnDrvKillbld104 = { + "killbld104", "killbld", "pgm", NULL, "1998", + "The Killing Blade (V104)\0", NULL, "IGS", "PolyGameMaster", + L"The Killing Blade\0\u50B2\u5251\u72C2\u5200\0\u50B2\u528D\u72C2\u5200 (V104)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_VSFIGHT, 0, + NULL, killbld104RomInfo, killbld104RomName, NULL, NULL, pgmInputInfo, killbldDIPInfo, + killbldInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Dragon World 3 (V106, Korea) + +static struct BurnRomInfo drgw3RomDesc[] = { + { "dw3_v106.u12", 0x080000, 0xc3f6838b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "dw3_v106.u13", 0x080000, 0x28284e22, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "dw3t0400.u18", 0x400000, 0xb70f3357, 2 | BRF_GRA }, // 2 Tile data + + { "dw3a0400.u9", 0x400000, 0xdd7bfd40, 3 | BRF_GRA }, // 3 Sprite Color Data + { "dw3a0401.u10", 0x400000, 0xcab6557f, 3 | BRF_GRA }, // 4 + + { "dw3b0400.u13", 0x400000, 0x4bb87cc0, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "dw3m0400.u1", 0x400000, 0x031eb9ce, 5 | BRF_SND }, // 6 Samples + + { "dw3_v100.u15", 0x010000, 0x03dc4fdf, 0 | BRF_PRG | BRF_ESS }, // 7 Protection data +}; + +STDROMPICKEXT(drgw3, drgw3, pgm) +STD_ROM_FN(drgw3) + +static INT32 drgw3Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_dw3; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvDrgw3 = { + "drgw3", NULL, "pgm", NULL, "1998", + "Dragon World 3 (V106, Korea)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw3RomInfo, drgw3RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Dragon World 3 (ver. 105) + +static struct BurnRomInfo drgw3105RomDesc[] = { + { "dw3_v105.u12", 0x080000, 0xc5e24318, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "dw3_v105.u13", 0x080000, 0x8d6c9d39, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "dw3t0400.u18", 0x400000, 0xb70f3357, 2 | BRF_GRA }, // 2 Tile data + + { "dw3a0400.u9", 0x400000, 0xdd7bfd40, 3 | BRF_GRA }, // 3 Sprite Color Data + { "dw3a0401.u10", 0x400000, 0xcab6557f, 3 | BRF_GRA }, // 4 + + { "dw3b0400.u13", 0x400000, 0x4bb87cc0, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "dw3m0400.u1", 0x400000, 0x031eb9ce, 5 | BRF_SND }, // 6 Samples + + { "dw3_v100.u15", 0x010000, 0x03dc4fdf, 0 | BRF_PRG | BRF_ESS }, // 7 Protection data +}; + +STDROMPICKEXT(drgw3105, drgw3105, pgm) +STD_ROM_FN(drgw3105) + +struct BurnDriverD BurnDrvDrgw3105 = { + "drgw3105", "drgw3", "pgm", NULL, "1998", + "Dragon World 3 (ver. 105)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw3105RomInfo, drgw3105RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Dragon World 3 (ver. 100) + +static struct BurnRomInfo drgw3100RomDesc[] = { + { "dw3_v100.u12", 0x080000, 0x47243906, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "dw3_v100.u13", 0x080000, 0xb7cded21, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "dw3t0400.u18", 0x400000, 0xb70f3357, 2 | BRF_GRA }, // 2 Tile data + + { "dw3a0400.u9", 0x400000, 0xdd7bfd40, 3 | BRF_GRA }, // 3 Sprite Color Data + { "dw3a0401.u10", 0x400000, 0xcab6557f, 3 | BRF_GRA }, // 4 + + { "dw3b0400.u13", 0x400000, 0x4bb87cc0, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "dw3m0400.u1", 0x400000, 0x031eb9ce, 5 | BRF_SND }, // 6 Samples + + { "dw3_v100.u15", 0x010000, 0x03dc4fdf, 0 | BRF_PRG | BRF_ESS }, // 7 Protection data +}; + +STDROMPICKEXT(drgw3100, drgw3100, pgm) +STD_ROM_FN(drgw3100) + +struct BurnDriverD BurnDrvDrgw3100 = { + "drgw3100", "drgw3", "pgm", NULL, "1998", + "Dragon World 3 (ver. 100)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, drgw3100RomInfo, drgw3100RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Dragon World 3 EX (ver. 100) + +static struct BurnRomInfo dwexRomDesc[] = { + { "ex_v100.u12", 0x080000, 0xbc171799, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "ex_v100.u13", 0x080000, 0x7afe6322, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "ex_t0400.u18", 0x200000, 0x9ecc950d, 2 | BRF_GRA }, // 2 Tile data + + { "ex_a0400.u9", 0x400000, 0xdd7bfd40, 3 | BRF_GRA }, // 3 Sprite Color Data + { "ex_a0401.u10", 0x200000, 0xd36c06a4, 3 | BRF_GRA }, // 4 + + { "ex_b0400.u13", 0x400000, 0x4bb87cc0, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "ex_m0400.u1", 0x200000, 0x42d54fd5, 5 | BRF_SND }, // 6 Samples + + { "ex_data.u15", 0x010000, 0x03dc4fdf, 0 | BRF_PRG | BRF_ESS }, // 7 Protection data +}; + +STDROMPICKEXT(dwex, dwex, pgm) +STD_ROM_FN(dwex) + +struct BurnDriverD BurnDrvDwex = { + "dwex", NULL, "pgm", NULL, "1998", + "Dragon World 3 EX (ver. 100)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, dwexRomInfo, dwexRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + drgw3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend Super (V101, Korea) + +static struct BurnRomInfo oldsRomDesc[] = { + { "sp_v101.u2", 0x080000, 0x08eb9661, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "sp_v101.u3", 0x080000, 0x0a358c1e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sp_v101.u4", 0x080000, 0x766570e0, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sp_v101.u5", 0x080000, 0x58662e12, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sp_v101.u1", 0x080000, 0x2b2f4f1e, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "t0500.rom", 0x400000, 0xd881726c, 2 | BRF_GRA }, // 5 Tile data + { "t0501.rom", 0x200000, 0xd2106864, 2 | BRF_GRA }, // 6 + + { "a0500.rom", 0x400000, 0x80a59197, 3 | BRF_GRA }, // 7 Sprite Color Data + { "a0501.rom", 0x400000, 0x98c931b1, 3 | BRF_GRA }, // 8 + { "a0502.rom", 0x400000, 0xc3fcdf1d, 3 | BRF_GRA }, // 9 + { "a0503.rom", 0x400000, 0x066dffec, 3 | BRF_GRA }, // 10 + { "a0504.rom", 0x400000, 0x45337583, 3 | BRF_GRA }, // 11 + { "a0505.rom", 0x400000, 0x5b8cf3a5, 3 | BRF_GRA }, // 12 + { "a0506.rom", 0x400000, 0x087ac60c, 3 | BRF_GRA }, // 13 + + { "b0500.rom", 0x400000, 0xcde07f74, 4 | BRF_GRA }, // 14 Sprite Masks & Color Indexes + { "b0501.rom", 0x400000, 0x1546c2e9, 4 | BRF_GRA }, // 15 + { "b0502.rom", 0x400000, 0xe97b31c3, 4 | BRF_GRA }, // 16 + { "b0503.u16", 0x400000, 0xe41d98e4, 4 | BRF_GRA }, // 17 + + { "m0500.rom", 0x200000, 0x37928cdd, 5 | BRF_SND }, // 18 Samples + + { "sp_v101.u6", 0x010000, 0x097046bc, 0 | BRF_PRG | BRF_ESS }, // 19 Protection Rom + + { "ram_dump", 0x004000, 0x280cfb4e, 0 | BRF_PRG | BRF_ESS }, // 20 ram dump +}; + +STDROMPICKEXT(olds, olds, pgm) +STD_ROM_FN(olds) + +static INT32 oldsInit() +{ + pPgmProtCallback = install_protection_asic25_asic28_olds; + + return pgmInit(); +} + +struct BurnDriver BurnDrvOlds = { + "olds", NULL, "pgm", NULL, "1999", + "Oriental Legend Super (V101, Korea)\0", "Imperfect Protection Emulation", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, oldsRomInfo, oldsRomName, NULL, NULL, pgmInputInfo, oldsDIPInfo, + oldsInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend Special / Xi Yo Gi Shi Re Zuang Super (V100) + +static struct BurnRomInfo olds100RomDesc[] = { + { "v100-u2.040", 0x080000, 0x517c2a06, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "v100-u3.040", 0x080000, 0xd0e2b741, 1 | BRF_PRG | BRF_ESS }, // 1 + { "v100-u4.040", 0x080000, 0x32a6bdbd, 1 | BRF_PRG | BRF_ESS }, // 2 + { "v100-u5.040", 0x080000, 0xb4a1cafb, 1 | BRF_PRG | BRF_ESS }, // 3 + { "v100-u1.040", 0x080000, 0x37ea4e75, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "t0500.rom", 0x400000, 0xd881726c, 2 | BRF_GRA }, // 5 Tile data + { "t0501.rom", 0x200000, 0xd2106864, 2 | BRF_GRA }, // 6 + + { "a0500.rom", 0x400000, 0x80a59197, 3 | BRF_GRA }, // 7 Sprite Color Data + { "a0501.rom", 0x400000, 0x98c931b1, 3 | BRF_GRA }, // 8 + { "a0502.rom", 0x400000, 0xc3fcdf1d, 3 | BRF_GRA }, // 9 + { "a0503.rom", 0x400000, 0x066dffec, 3 | BRF_GRA }, // 10 + { "a0504.rom", 0x400000, 0x45337583, 3 | BRF_GRA }, // 11 + { "a0505.rom", 0x400000, 0x5b8cf3a5, 3 | BRF_GRA }, // 12 + { "a0506.rom", 0x400000, 0x087ac60c, 3 | BRF_GRA }, // 13 + + { "b0500.rom", 0x400000, 0xcde07f74, 4 | BRF_GRA }, // 14 Sprite Masks & Color Indexes + { "b0501.rom", 0x400000, 0x1546c2e9, 4 | BRF_GRA }, // 15 + { "b0502.rom", 0x400000, 0xe97b31c3, 4 | BRF_GRA }, // 16 + { "b0503.u16", 0x400000, 0xe41d98e4, 4 | BRF_GRA }, // 17 + + { "m0500.rom", 0x200000, 0x37928cdd, 5 | BRF_SND }, // 18 Samples + + { "kd-u6.512", 0x010000, 0xe7613dda, 0 | BRF_PRG | BRF_ESS }, // 19 Protection Rom + + { "ram_dump", 0x004000, 0x280cfb4e, 0 | BRF_PRG | BRF_ESS }, // 20 ram dump +}; + +STDROMPICKEXT(olds100, olds100, pgm) +STD_ROM_FN(olds100) + +struct BurnDriver BurnDrvOlds100 = { + "olds100", "olds", "pgm", NULL, "1998", + "Oriental Legend Special - Xi Yo Gi Shi Re Zuang Super (V100)\0", "Imperfect Protection Emulation", "IGS", "PolyGameMaster", + L"Oriental Legend Super\0\u897F\u6E38\u91CA\u5384\u4F20 Super (V100)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, olds100RomInfo, olds100RomName, NULL, NULL, pgmInputInfo, olds100DIPInfo, + oldsInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend Special / Xi Yo Gi Shi Re Zuang Super (V100 alt) + +static struct BurnRomInfo olds100aRomDesc[] = { + { "p0500.v10", 0x400000, 0x8981fc87, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0500.rom", 0x400000, 0xd881726c, 2 | BRF_GRA }, // 1 Tile data + { "t0501.rom", 0x200000, 0xd2106864, 2 | BRF_GRA }, // 2 + + { "a0500.rom", 0x400000, 0x80a59197, 3 | BRF_GRA }, // 3 Sprite Color Data + { "a0501.rom", 0x400000, 0x98c931b1, 3 | BRF_GRA }, // 4 + { "a0502.rom", 0x400000, 0xc3fcdf1d, 3 | BRF_GRA }, // 5 + { "a0503.rom", 0x400000, 0x066dffec, 3 | BRF_GRA }, // 6 + { "a0504.rom", 0x400000, 0x45337583, 3 | BRF_GRA }, // 7 + { "a0505.rom", 0x400000, 0x5b8cf3a5, 3 | BRF_GRA }, // 8 + { "a0506.rom", 0x400000, 0x087ac60c, 3 | BRF_GRA }, // 9 + + { "b0500.rom", 0x400000, 0xcde07f74, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0501.rom", 0x400000, 0x1546c2e9, 4 | BRF_GRA }, // 11 + { "b0502.rom", 0x400000, 0xe97b31c3, 4 | BRF_GRA }, // 12 + { "b0503.u16", 0x400000, 0xe41d98e4, 4 | BRF_GRA }, // 13 + + { "m0500.rom", 0x200000, 0x37928cdd, 5 | BRF_SND }, // 14 Samples + +#if !defined (ROM_VERIFY) + { "protection_data.u6", 0x010000, 0, 0 | BRF_PRG | BRF_NODUMP }, // 15 Protection Rom +#else + { "", 0x000000, 0, 0 }, // 15 +#endif + + { "ram_dump", 0x004000, 0x280cfb4e, 0 | BRF_PRG | BRF_ESS }, // 16 ram dump +}; + +STDROMPICKEXT(olds100a, olds100a, pgm) +STD_ROM_FN(olds100a) + +struct BurnDriver BurnDrvOlds100a = { + "olds100a", "olds", "pgm", NULL, "1998", + "Oriental Legend Special - Xi Yo Gi Shi Re Zuang Super (V100 alt)\0", "Imperfect Protection Emulation", "IGS", "PolyGameMaster", + L"Oriental Legend Super\0\u897F\u6E38\u91CA\u5384\u4F20 Super (V100 alt)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM, GBF_SCRFIGHT, 0, + NULL, olds100aRomInfo, olds100aRomName, NULL, NULL, pgmInputInfo, olds100DIPInfo, + oldsInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour / Sangoku Senki (V117) + +static struct BurnRomInfo kovRomDesc[] = { + { "p0600.117", 0x400000, 0xc4d19fe6, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 7 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 8 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(kov, kov, pgm) +STD_ROM_FN(kov) + +static INT32 kovInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_kov; + pPgmProtCallback = install_protection_asic27_kov; // simulation + + return pgmInit(); +} + +struct BurnDriver BurnDrvKov = { + "kov", NULL, "pgm", NULL, "1999", + "Knights of Valour - Sangoku Senki (V117)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour\0\u4E09\u56FD\u6226\u7D00\0\u4E09\u56FD\u6218\u7EAA (V117)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovRomInfo, kovRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour / Sangoku Senki (V115) + +static struct BurnRomInfo kov115RomDesc[] = { + { "p0600.115", 0x400000, 0x527a2924, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 7 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 8 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(kov115, kov115, pgm) +STD_ROM_FN(kov115) + +struct BurnDriver BurnDrvKov115 = { + "kov115", "kov", "pgm", NULL, "1999", + "Knights of Valour - Sangoku Senki (V115)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour\0\u4E09\u56FD\u6226\u7D00\0\u4E09\u56FD\u6218\u7EAA (V115)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kov115RomInfo, kov115RomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour Plus / Sangoku Senki (V100, Japan) + +static struct BurnRomInfo kov100RomDesc[] = { + { "sav111.u4", 0x080000, 0xae2f1b4e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "sav111.u7", 0x080000, 0x95eedf0e, 1 | BRF_PRG | BRF_ESS }, // 1 + { "sav111.u5", 0x080000, 0x5fdd4aa8, 1 | BRF_PRG | BRF_ESS }, // 2 + { "sav111.u8", 0x080000, 0x003cbf49, 1 | BRF_PRG | BRF_ESS }, // 3 + { "sav111.u10", 0x080000, 0xd5536107, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 5 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 6 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 7 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 8 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 9 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 11 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 12 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 13 Internal ARM7 Rom +}; + +STDROMPICKEXT(kov100, kov100, pgm) +STD_ROM_FN(kov100) + +struct BurnDriver BurnDrvKov100 = { + "kov100", "kov", "pgm", NULL, "1999", + "Knights of Valour - Sangoku Senki (V100, Japan)\0", NULL, "IGS (Alta Co., LTD License)", "PolyGameMaster", + L"Knights of Valour\0\u4E09\u56FD\u6226\u7D00\0\u4E09\u56FD\u6218\u7EAA (V100, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kov100RomInfo, kov100RomName, NULL, NULL, pgmInputInfo, kov100DIPInfo, + kovInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour Plus / Sangoku Senki Plus (V119) + +static struct BurnRomInfo kovplusRomDesc[] = { + { "p0600.119", 0x400000, 0xe4b0875d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 7 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 8 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovplus, kovplus, pgm) +STD_ROM_FN(kovplus) + +struct BurnDriver BurnDrvKovplus = { + "kovplus", NULL, "pgm", NULL, "1999", + "Knights of Valour Plus - Sangoku Senki Plus (V119)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour Plus\0\u4E09\u56FD\u6226\u7D00 Plus\0\u4E09\u56FD\u6218\u7EAA Plus (V119)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovplusRomInfo, kovplusRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour Plus / Sangoku Senki Plus (V119 alt) + +static struct BurnRomInfo kovplusaRomDesc[] = { + { "v119.u3", 0x080000, 0x6750388f, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "v119.u5", 0x080000, 0xd4101ffd, 1 | BRF_PRG | BRF_ESS }, // 1 + { "v119.u4", 0x080000, 0x8200ece6, 1 | BRF_PRG | BRF_ESS }, // 2 + { "v119.u6", 0x080000, 0x71e28f27, 1 | BRF_PRG | BRF_ESS }, // 3 + { "v119.u2", 0x080000, 0x29588ef2, 1 | BRF_PRG | BRF_ESS }, // 4 + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 5 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 6 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 7 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 8 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 9 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 11 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 12 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 13 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovplusa, kovplusa, pgm) +STD_ROM_FN(kovplusa) + +struct BurnDriver BurnDrvKovplusa = { + "kovplusa", "kovplus", "pgm", NULL, "1999", + "Knights of Valour Plus - Sangoku Senki Plus (V119 alt)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour Plus\0\u4E09\u56FD\u6226\u7D00 Plus\0\u4E09\u56FD\u6218\u7EAA Plus (V119 alt)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovplusaRomInfo, kovplusaRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour Superheroes / Sangoku Senki Superheroes (V104, China) + +static struct BurnRomInfo kovshRomDesc[] = { + { "p0600.322", 0x400000, 0x7c78e5f3, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 + { "a0604.rom", 0x400000, 0x26b59fd3, 3 | BRF_GRA }, // 6 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 8 + { "b0602.rom", 0x100000, 0x9df77934, 4 | BRF_GRA }, // 9 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 10 Samples + + { "kovsh_v100_china.asic", 0x04000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 11 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovsh, kovsh, pgm) +STD_ROM_FN(kovsh) + +static INT32 kovshInit() +{ + pPgmInitCallback = pgm_decrypt_kovsh; + pPgmProtCallback = install_protection_asic27a_kovsh; + + Arm7SetIdleLoopAddress(0x00000260); + + return pgmInit(); +} + +struct BurnDriver BurnDrvKovsh = { + "kovsh", NULL, "pgm", NULL, "1999", + "Knights of Valour Superheroes / Sangoku Senki Superheroes (V104, China)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kovshRomInfo, kovshRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovshInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour Superheroes / Sangoku Senki Superheroes (V103) + +static struct BurnRomInfo kovsh103RomDesc[] = { + { "p0600.103", 0x400000, 0xf0b3da82, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 + { "a0604.rom", 0x400000, 0x26b59fd3, 3 | BRF_GRA }, // 6 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 8 + { "b0602.rom", 0x100000, 0x9df77934, 4 | BRF_GRA }, // 9 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 10 Samples + + { "kovsh_v100_china.asic", 0x04000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 11 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovsh103, kovsh103, pgm) +STD_ROM_FN(kovsh103) + +struct BurnDriver BurnDrvKovsh103 = { + "kovsh103", "kovsh", "pgm", NULL, "1999", + "Knights of Valour Superheroes / Sangoku Senki Superheroes (V103)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kovsh103RomInfo, kovsh103RomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovshInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Photo Y2K (ver. 105) + +static struct BurnRomInfo photoy2kRomDesc[] = { + { "p0701_v105.u2", 0x200000, 0xfab142e0, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0700.rom", 0x080000, 0x93943b4d, 2 | BRF_GRA }, // 1 Tile data + + { "a0700.l", 0x400000, 0x26a9ae9c, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0700.h", 0x400000, 0x79bc1fc1, 3 | BRF_GRA }, // 3 + { "a0701.l", 0x400000, 0x23607f81, 3 | BRF_GRA }, // 4 + { "a0701.h", 0x400000, 0x5f2efd37, 3 | BRF_GRA }, // 5 + { "a0702.rom", 0x080000, 0x42239e1b, 3 | BRF_GRA }, // 6 + + { "b0700.l", 0x400000, 0xaf096904, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b0700.h", 0x400000, 0x6d53de26, 4 | BRF_GRA }, // 8 + { "cgv101.rom", 0x020000, 0xda02ec3e, 4 | BRF_GRA }, // 9 + + { "m0700.rom", 0x080000, 0xacc7afce, 5 | BRF_SND }, // 10 Samples + + { "igs027a_photoy2k_v100_china.asic", 0x004000, 0x1a0b68f6, 7 | BRF_PRG | BRF_ESS }, // 11 Internal ARM7 Rom +}; + +STDROMPICKEXT(photoy2k, photoy2k, pgm) +STD_ROM_FN(photoy2k) + +static INT32 photoy2kInit() +{ + pPgmInitCallback = pgm_decrypt_photoy2k; + pPgmProtCallback = install_protection_asic27a_kovsh; + + Arm7SetIdleLoopAddress(0x000001f4); + + return pgmInit(); +} + +struct BurnDriver BurnDrvPhotoy2k = { + "photoy2k", NULL, "pgm", NULL, "1999", + "Photo Y2K / Real and Fake (V105)\0", NULL, "IGS", "PolyGameMaster", + L"Photo Y2K\0\u30EA\u30A2\u30EB\u30A2\u30F3\u30C9 \u30D5\u30A7\u30A4\u30AF\0\u5927\u5BB6\u6765 \u627E\u78B4\0\u8D85\u7EA7 \u6BD4\u4E00\u6BD4 (V105)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_PUZZLE, 0, + NULL, photoy2kRomInfo, photoy2kRomName, NULL, NULL, pgmInputInfo, photoy2kDIPInfo, + photoy2kInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Photo Y2K / Real and Fake (V104) + +static struct BurnRomInfo photoy2k104RomDesc[] = { + { "v104.16m", 0x200000, 0xe051070f, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0700.rom", 0x080000, 0x93943b4d, 2 | BRF_GRA }, // 1 Tile data + + { "a0700.l", 0x400000, 0x26a9ae9c, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0700.h", 0x400000, 0x79bc1fc1, 3 | BRF_GRA }, // 3 + { "a0701.l", 0x400000, 0x23607f81, 3 | BRF_GRA }, // 4 + { "a0701.h", 0x400000, 0x5f2efd37, 3 | BRF_GRA }, // 5 + { "a0702.rom", 0x080000, 0x42239e1b, 3 | BRF_GRA }, // 6 + + { "b0700.l", 0x400000, 0xaf096904, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b0700.h", 0x400000, 0x6d53de26, 4 | BRF_GRA }, // 8 + { "cgv101.rom", 0x020000, 0xda02ec3e, 4 | BRF_GRA }, // 9 + + { "m0700.rom", 0x080000, 0xacc7afce, 5 | BRF_SND }, // 10 Samples + + { "igs027a_photoy2k_v100_china_alt.asic", 0x004000, 0x6dd7f257, 7 | BRF_PRG | BRF_ESS }, // 11 Internal ARM7 Rom +}; + +STDROMPICKEXT(photoy2k104, photoy2k104, pgm) +STD_ROM_FN(photoy2k104) + +struct BurnDriver BurnDrvPhotoy2k104 = { + "photoy2k104", "photoy2k", "pgm", NULL, "1999", + "Photo Y2K / Real and Fake (V104)\0", NULL, "IGS", "PolyGameMaster", + L"Photo Y2K\0\u30EA\u30A2\u30EB\u30A2\u30F3\u30C9 \u30D5\u30A7\u30A4\u30AF\0\u5927\u5BB6\u6765 \u627E\u78B4\0\u8D85\u7EA7 \u6BD4\u4E00\u6BD4 (V104)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_PUZZLE, 0, + NULL, photoy2k104RomInfo, photoy2k104RomName, NULL, NULL, pgmInputInfo, photoy2kDIPInfo, + photoy2kInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Real and Fake / Photo Y2K (V102, Japan) + +static struct BurnRomInfo photoy2k102RomDesc[] = { + { "v102.u4", 0x080000, 0xa65eda9f, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "v102.u6", 0x080000, 0xb9ca5504, 1 | BRF_PRG | BRF_ESS }, // 1 + { "v102.u5", 0x080000, 0x9201621b, 1 | BRF_PRG | BRF_ESS }, // 2 + { "v102.u8", 0x080000, 0x3be22b8f, 1 | BRF_PRG | BRF_ESS }, // 3 + + { "t0700.rom", 0x080000, 0x93943b4d, 2 | BRF_GRA }, // 4 Tile data + + { "a0700.l", 0x400000, 0x26a9ae9c, 3 | BRF_GRA }, // 5 Sprite Color Data + { "a0700.h", 0x400000, 0x79bc1fc1, 3 | BRF_GRA }, // 6 + { "a0701.l", 0x400000, 0x23607f81, 3 | BRF_GRA }, // 7 + { "a0701.h", 0x400000, 0x5f2efd37, 3 | BRF_GRA }, // 8 + { "a0702.rom", 0x080000, 0x42239e1b, 3 | BRF_GRA }, // 9 + + { "b0700.l", 0x400000, 0xaf096904, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0700.h", 0x400000, 0x6d53de26, 4 | BRF_GRA }, // 11 + { "cgv101.rom", 0x020000, 0xda02ec3e, 4 | BRF_GRA }, // 12 + + { "m0700.rom", 0x080000, 0xacc7afce, 5 | BRF_SND }, // 13 Samples + + { "igs027a_photoy2k_v100_china_alt.asic", 0x0004000, 0x6dd7f257, 7 | BRF_PRG | BRF_ESS }, // 14 Internal ARM7 Rom +}; + +STDROMPICKEXT(photoy2k102, photoy2k102, pgm) +STD_ROM_FN(photoy2k102) + +struct BurnDriver BurnDrvphotoy2k102 = { + "photoy2k102", "photoy2k", "pgm", NULL, "1999", + "Real and Fake\0Photo Y2K (V102, Japan)\0", NULL, "IGS", "PolyGameMaster", + L"\u30EA\u30A2\u30EB\u30A2\u30F3\u30C9 \u30D5\u30A7\u30A4\u30AF\0Photo Y2K\0\u5927\u5BB6\u6765 \u627E\u78B4\0\u8D85\u7EA7 \u6BD4\u4E00\u6BD4 (V102, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_PUZZLE, 0, + NULL, photoy2k102RomInfo, photoy2k102RomName, NULL, NULL, pgmInputInfo, raf102jDIPInfo, + photoy2kInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Puzzle Star (V100MG) + +static struct BurnRomInfo puzlstarRomDesc[] = { + { "v100mg.u2", 0x080000, 0x4c79d979, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "v100mg.u1", 0x080000, 0x5788b77d, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "t0800.u5", 0x200000, 0xf9d84e59, 2 | BRF_GRA }, // 2 Tile data + + { "a0800.u1", 0x400000, 0xe1e6ec40, 3 | BRF_GRA }, // 3 Sprite Color Data + + { "b0800.u3", 0x200000, 0x52e7bef5, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m0800.u2", 0x400000, 0xe1a46541, 5 | BRF_SND }, // 5 Samples + + { "puzlstar_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom +}; + +STDROMPICKEXT(puzlstar, puzlstar, pgm) +STD_ROM_FN(puzlstar) + +static INT32 puzlstarInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_puzlstar; + pPgmProtCallback = install_protection_asic27a_puzlstar; // simulation +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriver BurnDrvPuzlstar = { + "puzlstar", NULL, "pgm", NULL, "1999", + "Puzzle Star (V100MG)\0", "Incomplete Protection Emulation", "IGS", "PolyGameMaster", + L"Puzzle Star\0\u30D1\u30BA\u30EB\u30B9\u30BF\u30FC\0\u9B54\u5E7B\u661F\u5EA7 (V100MG)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PUZZLE, 0, + NULL, puzlstarRomInfo, puzlstarRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + puzlstarInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Puzzli 2 Super (V200) + +static struct BurnRomInfo puzzli2RomDesc[] = { + { "2sp_v200.u4", 0x080000, 0xfa5c86c1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + { "2sp_v200.u3", 0x080000, 0x2a5ba8a6, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "t0900.u9", 0x200000, 0x70615611, 2 | BRF_GRA }, // 2 Tile data + + { "a0900.u3", 0x400000, 0x14911251, 3 | BRF_GRA }, // 3 Sprite Color Data + + { "b0900.u4", 0x200000, 0x6f0638b6, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m0900.u2", 0x400000, 0x9ea7af2e, 5 | BRF_SND }, // 5 Samples + + { "puzzli2_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom +}; + +STDROMPICKEXT(puzzli2, puzzli2, pgm) +STD_ROM_FN(puzzli2) + +static void puzzli2_decrypt() +{ + pgm_decrypt_puzzli2(); + + *((UINT16*)(PGM68KROM + 0x0268c0)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x0268c2)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x0268c4)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x03877a)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x04cee0)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x0548ec)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x0548fc)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x054948)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x05496A)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x0549FA)) = SWAP_WORD_LSB(0x4e71); + *((UINT16*)(PGM68KROM + 0x054A0A)) = SWAP_WORD_LSB(0x4e71); +} + +static INT32 puzzli2Init() +{ + pPgmInitCallback = puzzli2_decrypt; + pPgmProtCallback = install_protection_asic27_kov; // simulation +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvPuzzli2 = { + "puzzli2", NULL, "pgm", NULL, "2001", + "Puzzli 2 Super (V200)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PUZZLE, 0, + NULL, puzzli2RomInfo, puzzli2RomName, NULL, NULL, pgmInputInfo, puzzli2DIPInfo, + puzzli2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Martial Masters / Xing Yi (V104, 102, 102, USA) + +static struct BurnRomInfo martmastRomDesc[] = { + { "v104_32m.u9", 0x400000, 0xcfd9dff4, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1000.u3", 0x800000, 0xbbf879b5, 2 | BRF_GRA }, // 1 Tile data + + { "a1000.u3", 0x800000, 0x43577ac8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1001.u4", 0x800000, 0xfe7a476f, 3 | BRF_GRA }, // 3 + { "a1002.u6", 0x800000, 0x62e33d38, 3 | BRF_GRA }, // 4 + { "a1003.u8", 0x800000, 0xb2c4945a, 3 | BRF_GRA }, // 5 + { "a1004.u10", 0x400000, 0x9fd3f5fd, 3 | BRF_GRA }, // 6 + + { "b1000.u9", 0x800000, 0xc5961f6f, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1001.u11", 0x800000, 0x0b7e1c06, 4 | BRF_GRA }, // 8 + + { "m1000.u5", 0x800000, 0xed407ae8, 5 | BRF_SND }, // 9 Samples + { "m1001.u7", 0x400000, 0x662d2d48, 5 | BRF_SND }, // 10 + + { "martial_masters_v102_usa.asic", 0x4000, 0xa6c0828c, 7 | BRF_PRG | BRF_ESS }, // 11 Internal ARM7 Rom + + { "v102_16m.u10", 0x200000, 0x18b745e6, 8 | BRF_PRG | BRF_ESS }, // 12 External ARM7 Rom +}; + +STDROMPICKEXT(martmast, martmast, pgm) +STD_ROM_FN(martmast) + +static INT32 martmastInit() +{ + Arm7SetIdleLoopAddress(0x800039e); + + pPgmInitCallback = pgm_decrypt_martmast; + pPgmProtCallback = install_protection_asic27a_martmast; + + return pgmInit(); +} + +struct BurnDriver BurnDrvMartmast = { + "martmast", NULL, "pgm", NULL, "2001", + "Martial Masters (V104, 102, 102, USA)\0", NULL, "IGS", "PolyGameMaster", + L"Martial Masters\0\u5f62\u610f\u62f3 (V104, 102, 102, USA)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_VSFIGHT, 0, + NULL, martmastRomInfo, martmastRomName, NULL, NULL, pgmInputInfo, martmastDIPInfo, + martmastInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Martial Masters / Xing Yi (V104, 102, 101, China) + +static struct BurnRomInfo martmastcRomDesc[] = { + { "v104_32m.u9", 0x400000, 0xcfd9dff4, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1000.u3", 0x800000, 0xbbf879b5, 2 | BRF_GRA }, // 1 Tile data + + { "a1000.u3", 0x800000, 0x43577ac8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1001.u4", 0x800000, 0xfe7a476f, 3 | BRF_GRA }, // 3 + { "a1002.u6", 0x800000, 0x62e33d38, 3 | BRF_GRA }, // 4 + { "a1003.u8", 0x800000, 0xb2c4945a, 3 | BRF_GRA }, // 5 + { "a1004.u10", 0x400000, 0x9fd3f5fd, 3 | BRF_GRA }, // 6 + + { "b1000.u9", 0x800000, 0xc5961f6f, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1001.u11", 0x800000, 0x0b7e1c06, 4 | BRF_GRA }, // 8 + + { "m1000.u5", 0x800000, 0xed407ae8, 5 | BRF_SND }, // 9 Samples + { "m1001.u7", 0x400000, 0x662d2d48, 5 | BRF_SND }, // 10 + + { "martial_masters_v101_cn.asic", 0x4000, 0xb3e25b7d, 7 | BRF_PRG | BRF_ESS }, // 11 Internal ARM7 Rom + + { "v102_16m.u10", 0x200000, 0x18b745e6, 8 | BRF_PRG | BRF_ESS }, // 12 External ARM7 Rom +}; + +STDROMPICKEXT(martmastc, martmastc, pgm) +STD_ROM_FN(martmastc) + +struct BurnDriver BurnDrvmartmastc = { + "martmastc", "martmast", "pgm", NULL, "2001", + "Martial Masters (V104, 102, 101, China)\0", NULL, "IGS", "PolyGameMaster", + L"Martial Masters\0\u5f62\u610f\u62f3 (V104, 102, 101, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_VSFIGHT, 0, + NULL, martmastcRomInfo, martmastcRomName, NULL, NULL, pgmInputInfo, martmastcDIPInfo, + martmastInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Martial Masters / Xing Yi (V102, 101, 101, China) + +static struct BurnRomInfo martmastc102RomDesc[] = { + { "martmast_u9-v102.322", 0x400000, 0xBB24B92A, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1000.u3", 0x800000, 0xbbf879b5, 2 | BRF_GRA }, // 1 Tile data + + { "a1000.u3", 0x800000, 0x43577ac8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1001.u4", 0x800000, 0xfe7a476f, 3 | BRF_GRA }, // 3 + { "a1002.u6", 0x800000, 0x62e33d38, 3 | BRF_GRA }, // 4 + { "a1003.u8", 0x800000, 0xb2c4945a, 3 | BRF_GRA }, // 5 + { "a1004.u10", 0x400000, 0x9fd3f5fd, 3 | BRF_GRA }, // 6 + + { "b1000.u9", 0x800000, 0xc5961f6f, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1001.u11", 0x800000, 0x0b7e1c06, 4 | BRF_GRA }, // 8 + + { "m1000.u5", 0x800000, 0xed407ae8, 5 | BRF_SND }, // 9 Samples + { "m1001.u7", 0x400000, 0x662d2d48, 5 | BRF_SND }, // 10 + + { "martial_masters_v101_cn.asic", 0x004000, 0xb3e25b7d, 7 | BRF_PRG | BRF_ESS }, // 11 Internal ARM7 Rom + + { "martmast_u10-v101.160", 0x200000, 0xD5D93294, 8 | BRF_PRG | BRF_ESS }, // 12 External ARM7 Rom +}; + +STDROMPICKEXT(martmastc102, martmastc102, pgm) +STD_ROM_FN(martmastc102) + +struct BurnDriver BurnDrvmartmastc102 = { + "martmastc102", "martmast", "pgm", NULL, "2001", + "Martial Masters (V102, 101, 101, China)\0", NULL, "IGS", "PolyGameMaster", + L"Martial Masters\0\u5f62\u610f\u62f3 (V102, 101, 101, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_VSFIGHT, 0, + NULL, martmastc102RomInfo, martmastc102RomName, NULL, NULL, pgmInputInfo, martmastc102DIPInfo, + martmastInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Photo Y2K 2 + +static struct BurnRomInfo py2k2RomDesc[] = { + { "y2k2_m-101xx.u1",0x200000, 0xc47795f1, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "y2k2_a1100.u6", 0x800000, 0xe32ce499, 3 | BRF_GRA }, // 1 Sprite Color Data + { "y2k2_a1101.u7", 0x800000, 0x4e7568bc, 3 | BRF_GRA }, // 2 + { "y2k2_a1102.u8", 0x800000, 0x6da7c143, 3 | BRF_GRA }, // 3 + { "y2k2_a1103.u9", 0x800000, 0x0ebebfdc, 3 | BRF_GRA }, // 4 + + { "y2k2_b1100.u4", 0x800000, 0xfa53d6f6, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "y2k2_b1101.u5", 0x800000, 0x001e4c81, 4 | BRF_GRA }, // 6 + + { "y2k2_m1100.u3", 0x200000, 0xfb1515f8, 5 | BRF_SND }, // 7 Samples + + { "igs027a_photoy2k2.asic", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_ESS| BRF_NODUMP }, // 8 Internal ARM7 Rom +}; + +STDROMPICKEXT(py2k2, py2k2, pgm) +STD_ROM_FN(py2k2) + +static INT32 py2k2Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_py2k2; +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvPy2k2 = { + "py2k2", NULL, "pgm", NULL, "2001", + "Photo Y2K 2\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PUZZLE, 0, + NULL, py2k2RomInfo, py2k2RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + py2k2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 (V107, 102, 100, Hong Kong) + +static struct BurnRomInfo kov2RomDesc[] = { + { "u18.107", 0x400000, 0x661a5b2c, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom", 0x800000, 0x82f0a878, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom", 0x800000, 0x27527099, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + + { "kov2_v100_hongkong.asic", 0x4000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom + + { "u19.102", 0x200000, 0x462e2980, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2, kov2, pgm) +STD_ROM_FN(kov2) + +static INT32 kov2Init() +{ + Arm7SetIdleLoopAddress(0x80000ae); + + pPgmInitCallback = pgm_decrypt_kov2; + pPgmProtCallback = install_protection_asic27a_martmast; + + return pgmInit(); +} + +struct BurnDriver BurnDrvKov2 = { + "kov2", NULL, "pgm", NULL, "2000", + "Knights of Valour 2 (V107, 102, 100, Hong Kong)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour 2\0\u4e09\u56fd\u6218\u7eaa 2 (V107, 102, 100, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2RomInfo, kov2RomName, NULL, NULL, pgmInputInfo, kov2DIPInfo, + kov2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 (V106, 102, 100 Hong Kong) + +static struct BurnRomInfo kov2106RomDesc[] = { + { "u18.106", 0x400000, 0x40051ad9, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom", 0x800000, 0x82f0a878, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom", 0x800000, 0x27527099, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + + { "kov2_v100_hongkong.asic", 0x4000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom + + { "u19.102", 0x200000, 0x462e2980, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2106, kov2106, pgm) +STD_ROM_FN(kov2106) + +struct BurnDriver BurnDrvKov2106 = { + "kov2106", "kov2", "pgm", NULL, "2000", + "Knights of Valour 2 (V106, 102, 100 Hong Kong)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour 2\0\u4e09\u56fd\u6218\u7eaa 2 (V106, 102, 100 Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2106RomInfo, kov2106RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + kov2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 (V103, 101, 100, Hong Kong) + +static struct BurnRomInfo kov2103RomDesc[] = { + { "u18.103", 0x400000, 0x98c32f76, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom", 0x800000, 0x82f0a878, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom", 0x800000, 0x27527099, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + + { "kov2_v100_hongkong.asic", 0x004000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom + + { "u19.101", 0x200000, 0x8c35f2fe, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2103, kov2103, pgm) +STD_ROM_FN(kov2103) + +struct BurnDriver BurnDrvKov2103 = { + "kov2103", "kov2", "pgm", NULL, "2000", + "Knights of Valour 2 (V103, 101, 100, Hong Kong)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour 2\0\u4e09\u56fd\u6218\u7eaa 2 (V103, 101, 100, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2103RomInfo, kov2103RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + kov2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 (V102, 101, 100, Hong Kong) + +static struct BurnRomInfo kov2102RomDesc[] = { + { "u18.102", 0x400000, 0xa2489c37, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom", 0x800000, 0x82f0a878, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom", 0x800000, 0x27527099, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + + { "kov2_v100_hongkong.asic", 0x004000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom + + { "u19.101", 0x200000, 0x8c35f2fe, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2102, kov2102, pgm) +STD_ROM_FN(kov2102) + +struct BurnDriver BurnDrvKov2102 = { + "kov2102", "kov2", "pgm", NULL, "2000", + "Knights of Valour 2 (V102, 101, 100, Hong Kong)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour 2\0\u4e09\u56fd\u6218\u7eaa 2 (V102, 101, 100, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2102RomInfo, kov2102RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + kov2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 (V100, 100, 100, Hong Kong) + +static struct BurnRomInfo kov2100RomDesc[] = { + { "igs_u18.rom", 0x400000, 0x86205879, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom", 0x800000, 0x82f0a878, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom", 0x800000, 0x27527099, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + + { "kov2_v100_hongkong.asic", 0x004000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom + + { "u19.100", 0x200000, 0xedd59922, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2100, kov2100, pgm) +STD_ROM_FN(kov2100) + +struct BurnDriver BurnDrvKov2100 = { + "kov2100", "kov2", "pgm", NULL, "2000", + "Knights of Valour 2 (V100, 100, 100, Hong Kong)\0", NULL, "IGS", "PolyGameMaster", + L"Knights of Valour 2\0\u4e09\u56fd\u6218\u7eaa 2 (V100, 100, 100, Hong Kong)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2100RomInfo, kov2100RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + kov2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 Plus - Nine Dragons (VM204XX) + +static struct BurnRomInfo kov2pRomDesc[] = { + { "v204-32m.rom", 0x400000, 0x583e0650, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom_p", 0x800000, 0x21063ca7, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom_p", 0x200000, 0x14b4b5bb, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + +#if !defined (ROM_VERIFY) + { "kov2p_igs027a.bin", 0x004000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom +#else + { "kov2p_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_ESS | BRF_NODUMP }, // 10 Internal ARM7 Rom +#endif + + { "v200-16.rom", 0x200000, 0x16a0c11f, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2p, kov2p, pgm) +STD_ROM_FN(kov2p) + +static void kov2pCallback() +{ + pgm_decrypt_kov2p(); + + *((UINT16*)(PGMUSER0 + 0x0000de)) = SWAP_WORD_LSB(0x46c0); + *((UINT16*)(PGMUSER0 + 0x1ffffc)) = SWAP_WORD_LSB(0x9933); + + for (INT32 i = 0x4ed8; i <= 0x4f0c; i+=4) { + PGMUSER0[i] -= 0x08; + } +} + +static INT32 kov2pInit() +{ + Arm7SetIdleLoopAddress(0x80000a6); + + pPgmInitCallback = kov2pCallback; + pPgmProtCallback = install_protection_asic27a_martmast; + + return pgmInit(); +} + +struct BurnDriver BurnDrvKov2p = { + "kov2p", NULL, "pgm", NULL, "2001", + "Knights of Valour 2 Plus - Nine Dragons (VM204XX)\0", "Incorrect Asic dump", "IGS", "PolyGameMaster", + L"Knights of Valour 2 Plus\0\u4e09\u56fd\u6218\u7eaa 2 - \u7fa4\u96c4\u4e89\u9738 (VM204XX)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2pRomInfo, kov2pRomName, NULL, NULL, pgmInputInfo, kov2DIPInfo, + kov2pInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour 2 Plus - Nine Dragons (VM205XX, China) + +static struct BurnRomInfo kov2p205RomDesc[] = { + { "u8-27322.rom", 0x400000, 0x3a2cc0de, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1200.rom", 0x800000, 0xd7e26609, 2 | BRF_GRA }, // 1 Tile data + + { "a1200.rom", 0x800000, 0xceeb81d8, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1201.rom_p", 0x800000, 0x21063ca7, 3 | BRF_GRA }, // 3 + { "a1202.rom", 0x800000, 0x4bb92fae, 3 | BRF_GRA }, // 4 + { "a1203.rom", 0x800000, 0xe73cb627, 3 | BRF_GRA }, // 5 + { "a1204.rom_p", 0x200000, 0x14b4b5bb, 3 | BRF_GRA }, // 6 + + { "b1200.rom", 0x800000, 0xbed7d994, 4 | BRF_GRA }, // 7 Sprite Masks & Color Indexes + { "b1201.rom", 0x800000, 0xf251eb57, 4 | BRF_GRA }, // 8 + + { "m1200.rom", 0x800000, 0xb0d88720, 5 | BRF_SND }, // 9 Samples + +#if !defined (ROM_VERIFY) + { "kov2p_igs027a.bin", 0x004000, 0xe0d7679f, 7 | BRF_PRG | BRF_ESS }, // 10 Internal ARM7 Rom +#else + { "kov2p_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_ESS | BRF_NODUMP }, // 10 Internal ARM7 Rom +#endif + + { "v200-16.rom", 0x200000, 0x16a0c11f, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom +}; + +STDROMPICKEXT(kov2p205, kov2p205, pgm) +STD_ROM_FN(kov2p205) + +struct BurnDriver BurnDrvKov2p205 = { + "kov2p205", "kov2p", "pgm", NULL, "2001", + "Knights of Valour 2 Plus - Nine Dragons (VM205XX, China)\0", "Incorrect Asic dump", "IGS", "PolyGameMaster", + L"Knights of Valour 2 Plus\0\u4e09\u56fd\u6218\u7eaa 2 - \u7fa4\u96c4\u4e89\u9738 (VM205XX, China)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kov2p205RomInfo, kov2p205RomName, NULL, NULL, pgmInputInfo, kov2DIPInfo, + kov2pInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Bee Storm - DoDonPachi II (V102) + +static struct BurnRomInfo ddp2RomDesc[] = { + { "v102.u8", 0x200000, 0x5a9ea040, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1300.u21", 0x800000, 0xe748f0cb, 2 | BRF_GRA }, // 1 Tile data + + { "a1300.u1", 0x800000, 0xfc87a405, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1301.u2", 0x800000, 0x0c8520da, 3 | BRF_GRA }, // 3 + + { "b1300.u7", 0x800000, 0xef646604, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m1300.u5", 0x400000, 0x82d4015d, 5 | BRF_SND }, // 5 Samples + + { "ddp2_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP },// 6 Internal ARM7 Rom + + { "v100.u23", 0x020000, 0x06c3dd29, 8 | BRF_PRG | BRF_ESS }, // 7 External ARM7 Rom +}; + +STDROMPICKEXT(ddp2, ddp2, pgm) +STD_ROM_FN(ddp2) + +static INT32 ddp2Init() +{ + pPgmInitCallback = pgm_decrypt_ddp2; + pPgmProtCallback = install_protection_asic27a_ddp2; // simulation +// pPgmProtCallback = install_protection_asic27a_martmast; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvDdp2 = { + "ddp2", NULL, "pgm", NULL, "2001", + "Bee Storm - DoDonPachi II (V102)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Bee Storm - DoDonPatchi II\0\u6012\u9996\u9886\u8702\uff0d\u8702\u66b4 (V102)\0", NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU */, GBF_VERSHOOT, 0, + NULL, ddp2RomInfo, ddp2RomName, NULL, NULL, pgmInputInfo, ddp2DIPInfo, + ddp2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224,448,3,4 +}; + +// Bee Storm - DoDonPachi II (V100) + +static struct BurnRomInfo ddp2100RomDesc[] = { + { "v100.u8", 0x200000, 0x0c8aa8ea, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1300.u21", 0x800000, 0xe748f0cb, 2 | BRF_GRA }, // 1 Tile data + + { "a1300.u1", 0x800000, 0xfc87a405, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1301.u2", 0x800000, 0x0c8520da, 3 | BRF_GRA }, // 3 + + { "b1300.u7", 0x800000, 0xef646604, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m1300.u5", 0x400000, 0x82d4015d, 5 | BRF_SND }, // 5 Samples + + { "ddp2_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP },// 6 Internal ARM7 Rom + + { "v100.u23", 0x020000, 0x06c3dd29, 8 | BRF_PRG | BRF_ESS }, // 7 External ARM7 Rom +}; + +STDROMPICKEXT(ddp2100, ddp2100, pgm) +STD_ROM_FN(ddp2100) + +struct BurnDriverD BurnDrvDdp2100 = { + "ddp2100", "ddp2", "pgm", NULL, "2001", + "Bee Storm - DoDonPachi II (V100)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Bee Storm - DoDonPatchi II\0\u6012\u9996\u9886\u8702\uff0d\u8702\u66b4 (V100)\0", NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_VERSHOOT, 0, + NULL, ddp2100RomInfo, ddp2100RomName, NULL, NULL, pgmInputInfo, ddp2DIPInfo, + ddp2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224,448,3,4 +}; + +// Bee Storm - DoDonPachi II (V101) + +static struct BurnRomInfo ddp2101RomDesc[] = { + { "v101_16m.u8", 0x200000, 0x5e5786fd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t1300.u21", 0x800000, 0xe748f0cb, 2 | BRF_GRA }, // 1 Tile data + + { "a1300.u1", 0x800000, 0xfc87a405, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a1301.u2", 0x800000, 0x0c8520da, 3 | BRF_GRA }, // 3 + + { "b1300.u7", 0x800000, 0xef646604, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m1300.u5", 0x400000, 0x82d4015d, 5 | BRF_SND }, // 5 Samples + + { "ddp2_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP },// 6 Internal ARM7 Rom + + { "v100.u23", 0x020000, 0x06c3dd29, 8 | BRF_PRG | BRF_ESS }, // 7 External ARM7 Rom +}; + +STDROMPICKEXT(ddp2101, ddp2101, pgm) +STD_ROM_FN(ddp2101) + +struct BurnDriverD BurnDrvDdp2101 = { + "ddp2101", "ddp2", "pgm", NULL, "2001", + "Bee Storm - DoDonPachi II (V101)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Bee Storm - DoDonPatchi II\0\u6012\u9996\u9886\u8702\uff0d\u8702\u66b4 (V101)\0", NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU */, GBF_VERSHOOT, 0, + NULL, ddp2101RomInfo, ddp2101RomName, NULL, NULL, pgmInputInfo, ddp2DIPInfo, + ddp2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224,448,3,4 +}; + + +// Dragon World 2001 (V100, Taiwan) + +static struct BurnRomInfo dw2001RomDesc[] = { + { "2001.u22", 0x080000, 0x5cabed92, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "2001.u11", 0x200000, 0x1dd8d1e9, 2 | BRF_GRA }, // 1 Tile data + + { "2001.u2", 0x200000, 0xd11c733c, 3 | BRF_GRA }, // 2 Sprite Color Data + { "2001.u3", 0x200000, 0x1435aef2, 3 | BRF_GRA }, // 4 + + { "2001.u9", 0x200000, 0xccbca572, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "2001.u7", 0x200000, 0x4ea62f21, 5 | BRF_SND }, // 6 Samples + + { "dw2001_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_ESS | BRF_NODUMP }, // 7 Internal ARM7 rom + + { "2001.u12", 0x080000, 0x973db1ab, 8 | BRF_PRG | BRF_ESS }, // 8 External ARM7 rom +}; + +STDROMPICKEXT(dw2001, dw2001, pgm) +STD_ROM_FN(dw2001) + +static INT32 dw2001Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_martmast; // the same +// pPgmProtCallback = install_protection_asic27a_martmast; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvDw2001 = { + "dw2001", NULL, "pgm", NULL, "2001", + "Dragon World 2001 (V100, Taiwan)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PUZZLE, 0, + NULL, dw2001RomInfo, dw2001RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + dw2001Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Demon Front (V102) + +static struct BurnRomInfo dmnfrntRomDesc[] = { + { "v102_16m.u5", 0x200000, 0x3d4d481a, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04501.u29", 0x800000, 0x900eaaac, 2 | BRF_GRA }, // 1 Tile data + + { "a04501.u3", 0x800000, 0x9741bea6, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04502.u4", 0x800000, 0xe104f405, 3 | BRF_GRA }, // 3 + { "a04503.u6", 0x800000, 0xbfd5cfe3, 3 | BRF_GRA }, // 4 + + { "b04501.u9", 0x800000, 0x29320b7d, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "b04502.u11", 0x200000, 0x578c00e9, 4 | BRF_GRA }, // 6 + + { "w04501.u5", 0x800000, 0x3ab58137, 5 | BRF_SND }, // 7 Samples + + { "dmnfrnt_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP }, // 8 Internal ARM7 Rom + + { "v101_32m.u26", 0x400000, 0x93965281, 8 | BRF_PRG | BRF_ESS }, // 9 External ARM7 Rom +}; + +STDROMPICKEXT(dmnfrnt, dmnfrnt, pgm) +STD_ROM_FN(dmnfrnt) + +static INT32 dmnfrntInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_dfront; +// pPgmProtCallback = install_protection_asic27a_svg; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvDmnfrnt = { + "dmnfrnt", NULL, "pgm", NULL, "2002", + "Demon Front (V102)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Demon Front\0\u9B54\u57DF\u6218\u7EBF\0\u9B54\u57DF\u6230\u7DDA (V102)\0", NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PLATFORM, 0, + NULL, dmnfrntRomInfo, dmnfrntRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + dmnfrntInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Demon Front (V105, China) + +static struct BurnRomInfo dmnfrnt105RomDesc[] = { + { "v105_16m.u5", 0x200000, 0xbda083bd, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04501.u29", 0x800000, 0x900eaaac, 2 | BRF_GRA }, // 1 Tile data + + { "a04501.u3", 0x800000, 0x9741bea6, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04502.u4", 0x800000, 0xe104f405, 3 | BRF_GRA }, // 3 + { "a04503.u6", 0x800000, 0xbfd5cfe3, 3 | BRF_GRA }, // 4 + + { "b04501.u9", 0x800000, 0x29320b7d, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "b04502.u11", 0x200000, 0x578c00e9, 4 | BRF_GRA }, // 6 + + { "w04501.u5", 0x800000, 0x3ab58137, 5 | BRF_SND }, // 7 Samples + + { "dmnfrnt_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP }, // 8 Internal ARM7 Rom + + { "v105_32m.u26", 0x400000, 0xc798c2ef, 8 | BRF_PRG | BRF_ESS }, // 9 External ARM7 Rom +}; + +STDROMPICKEXT(dmnfrnt105, dmnfrnt105, pgm) +STD_ROM_FN(dmnfrnt105) + +struct BurnDriverD BurnDrvDmnfrnt105 = { + "dmnfrnt105", "dmnfrnt", "pgm", NULL, "2002", + "Demon Front (V105, China)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Demon Front\0\u9B54\u57DF\u6218\u7EBF\0\u9B54\u57DF\u6230\u7DDA (V105, China)\0", NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_PLATFORM, 0, + NULL, dmnfrnt105RomInfo, dmnfrnt105RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + dmnfrntInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// The Gladiator / Shen Jian (V100) + +static struct BurnRomInfo thegladRomDesc[] = { + { "u6.rom", 0x080000, 0x14c85212, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04601.u33", 0x800000, 0xe5dab371, 2 | BRF_GRA }, // 1 Tile data + + { "a04601.u2", 0x800000, 0xd9b2e004, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04602.u4", 0x800000, 0x14f22308, 3 | BRF_GRA }, // 3 + { "a04603.u6", 0x800000, 0x8f621e17, 3 | BRF_GRA }, // 4 + + { "b04601.u11", 0x800000, 0xee72bccf, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "b04602.u12", 0x400000, 0x7dba9c38, 4 | BRF_GRA }, // 6 + + { "w04601.u1", 0x800000, 0x5f15ddb3, 5 | BRF_SND }, // 7 Samples + + { "theglad_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 8 Internal ARM7 Rom + + { "u2.rom", 0x200000, 0xc7bcf2ae, 8 | BRF_PRG | BRF_ESS }, // 9 External ARM7 Rom +}; + +STDROMPICKEXT(theglad, theglad, pgm) +STD_ROM_FN(theglad) + +static INT32 thegladInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_theglad; +// pPgmProtCallback = install_protection_asic27a_svg; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvTheglad = { + "theglad", NULL, "pgm", NULL, "2003", + "The Gladiator / Shen Jian (V100)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"The Gladiator (V100)\0\u795E\u5251\u98CE\u4E91\0\u795E\u528D\u98A8\u96F2\0", NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, thegladRomInfo, thegladRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + thegladInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// The Gladiator / Shen Jian (V101, Taiwan) + +static struct BurnRomInfo theglad101RomDesc[] = { + { "v101.u6", 0x080000, 0xf799e866, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04601.u33", 0x800000, 0xe5dab371, 2 | BRF_GRA }, // 1 Tile data + + { "a04601.u2", 0x800000, 0xd9b2e004, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04602.u4", 0x800000, 0x14f22308, 3 | BRF_GRA }, // 3 + { "a04603.u6", 0x800000, 0x8f621e17, 3 | BRF_GRA }, // 4 + + { "b04601.u11", 0x800000, 0xee72bccf, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "b04602.u12", 0x400000, 0x7dba9c38, 4 | BRF_GRA }, // 6 + + { "w04601.u1", 0x800000, 0x5f15ddb3, 5 | BRF_SND }, // 7 Samples + + { "theglad_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 8 Internal ARM7 Rom + + { "v107.u26", 0x200000, 0xf7c61357, 8 | BRF_PRG | BRF_ESS }, // 9 External ARM7 Rom +}; + +STDROMPICKEXT(theglad101, theglad101, pgm) +STD_ROM_FN(theglad101) + +struct BurnDriverD BurnDrvTheglad101 = { + "theglada", "theglad", "pgm", NULL, "2003", + "The Gladiator / Shen Jian (V101, Taiwan)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"The Gladiator (V101, Taiwan)\0\u795E\u5251\u98CE\u4E91\0\u795E\u528D\u98A8\u96F2\0", NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, theglad101RomInfo, theglad101RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + thegladInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Happy 6in1 (V100 - V100MK) + +static struct BurnRomInfo happy6RomDesc[] = { + { "happy6in1_v100cn.u5", 0x080000, 0xa25418e8, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t01w64m.u29", 0x800000, 0x2d3feb8b, 2 | BRF_GRA }, // 1 Tile data + + { "a01w64m.u5", 0x800000, 0xbbaa3df3, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a02w64m.u6", 0x800000, 0xf8c9cd36, 3 | BRF_GRA }, // 3 + + { "b01w64m.u19", 0x800000, 0x73f5f225, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "w01w64m.u17", 0x800000, 0x7e23e2be, 5 | BRF_SND }, // 5 Samples + + { "happy6_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "happy6in1_v101cn.u26", 0x400000, 0x4a48ca1c, 8 | BRF_PRG | BRF_ESS }, // 7 External ARM7 Rom +}; + +STDROMPICKEXT(happy6, happy6, pgm) +STD_ROM_FN(happy6) + +static INT32 happy6in1Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_happy6in1; +// pPgmProtCallback = install_protection_asic27a_svg; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvhappy6 = { + "happy6", NULL, "pgm", NULL, "2004", + "Happy 6in1 (V100 - V100MK)\0", "Missing Internal ARM7 Rom", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_MISC, 0, + NULL, happy6RomInfo, happy6RomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + happy6in1Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 448, 224, 4, 3 +}; + + +// Knights of Valour Super Heroes Plus / Sangoku Senki Super Heroes Plus (ver. 100) + +static struct BurnRomInfo kovshpRomDesc[] = { + { "p0600h.rom", 0x400000, 0xe251e8e4, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0540.rom", 0x800000, 0x4fd3413e, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b0540.rom", 0x800000, 0x60999757, 4 | BRF_GRA }, // 7 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 8 Samples + + { "kovshp_igs027a.bin", 0x004000, 0x00000000, 0 | BRF_ESS | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovshp, kovshp, pgm) +STD_ROM_FN(kovshp) + +static INT32 kovshpInit() +{ + pPgmInitCallback = pgm_decrypt_kovshp; + pPgmProtCallback = install_protection_asic27_kov; // simulation +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvkovshp = { + "kovshp", NULL, "pgm", NULL, "2004", + "Knights of Valour Super Heroes Plus / Sangoku Senki Super Heroes Plus (ver. 100)\0", "Incomplete dump", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovshpRomInfo, kovshpRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovshpInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Oriental Legend Special Plus / Xi You Shi E Zhuan Super Plus (ver. 205) + +static struct BurnRomInfo oldsplusRomDesc[] = { + { "p05301.rom", 0x400000, 0x923f7246, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t05301.rom", 0x800000, 0x8257bbb0, 2 | BRF_GRA }, // 1 Tile data + + { "a05301.rom", 0x800000, 0x57946fd2, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a05302.rom", 0x800000, 0x3459a0b8, 3 | BRF_GRA }, // 3 + { "a05303.rom", 0x800000, 0x13475d85, 3 | BRF_GRA }, // 4 + { "a05304.rom", 0x800000, 0xf03ef7a6, 3 | BRF_GRA }, // 5 + + { "b05301.rom", 0x800000, 0xfd98f503, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b05302.rom", 0x800000, 0x9f6094a8, 4 | BRF_GRA }, // 7 + + { "m05301.rom", 0x400000, 0x86ec83bc, 5 | BRF_SND }, // 8 Samples + + { "oldsplus_igs027a.bin", 0x004000, 0, 7 | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(oldsplus, oldsplus, pgm) +STD_ROM_FN(oldsplus) + +static INT32 oldsplusInit() +{ + pPgmInitCallback = pgm_decrypt_oldsplus; + pPgmProtCallback = install_protection_asic27a_oldsplus; +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriver BurnDrvoldsplus = { + "oldsplus", NULL, "pgm", NULL, "2004", + "Oriental Legend Special Plus / Xi You Shi E Zhuan Super Plus (ver. 205)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"Oriental Legend Special Plus\0\u897F\u6E38\u91CA\u5384\u4F20 Plus\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, oldsplusRomInfo, oldsplusRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + oldsplusInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// The Killing Blade Plus (V300) + +static struct BurnRomInfo killbldpRomDesc[] = { + { "v300x.u6", 0x080000, 0xb7fb8ec9, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t05701w032.bin", 0x400000, 0x567c714f, 2 | BRF_GRA }, // 1 Tile data + + { "a05701w064.bin", 0x800000, 0x8c0c992c, 3 | BRF_GRA }, // 3 Sprite Color Data + { "a05702w064.bin", 0x800000, 0x7e5b0f27, 3 | BRF_GRA }, // 4 + { "a05703w064.bin", 0x800000, 0xaccbdb44, 3 | BRF_GRA }, // 5 + + { "b05701w064.bin", 0x800000, 0xa20cdcef, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b05702w016.bin", 0x200000, 0xfe7457df, 4 | BRF_GRA }, // 7 + + { "w05701b032.bin", 0x400000, 0x2d3ae593, 5 | BRF_SND }, // 8 Samples + + { "killbldp_igs027a.bin", 0x004000, 0x9a73bf7d, 7 | BRF_PRG }, // 9 Internal ARM7 Rom + + { "v300x.u26", 0x200000, 0x144388c8, 8 | BRF_PRG | BRF_ESS }, // 10 External ARM7 Rom +}; + +STDROMPICKEXT(killbldp, killbldp, pgm) +STD_ROM_FN(killbldp) + +INT32 killbldpInit() +{ + Arm7SetIdleLoopAddress(0x00007c4); + + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_killbldp; + pPgmProtCallback = install_protection_asic27a_svg; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvKillbldp = { + "killbldp", NULL, "pgm", NULL, "2005", + "The Killing Blade Plus (V300)\0", NULL, "IGS", "PolyGameMaster", + L"The Killing Blade Plus \0\u50B2\u5251\u72C2\u5200\0\u50B2\u528D\u72C2\u5200 (V300)\0", NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_VSFIGHT, 0, + NULL, killbldpRomInfo, killbldpRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + killbldpInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// S.V.G. - Spectral vs Generation (V200, China) + +static struct BurnRomInfo svgRomDesc[] = { + { "u30.bin", 0x080000, 0x34c18f3f, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t05601w016.bin", 0x200000, 0x03e110dc, 2 | BRF_GRA }, // 1 Tile data + + { "a05601w064.bin", 0x800000, 0xea6453e4, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a05602w064.bin", 0x800000, 0x6d00621b, 3 | BRF_GRA }, // 3 + { "a05603w064.bin", 0x800000, 0x7b71c64f, 3 | BRF_GRA }, // 4 + { "a05604w032.bin", 0x400000, 0x9452a567, 3 | BRF_GRA }, // 5 + + { "b05601w064.bin", 0x800000, 0x35c0a489, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b05602w064.bin", 0x800000, 0x8aad3f85, 4 | BRF_GRA }, // 7 + + { "w05601b064.bin", 0x800000, 0xbfe61a71, 5 | BRF_SND }, // 8 Samples + { "w05602b032.bin", 0x400000, 0x0685166d, 5 | BRF_SND }, // 9 + + { "svg_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 10 Internal ARM7 Rom + + { "u26.bin", 0x400000, 0x46826ec8, 8 | BRF_PRG | BRF_ESS }, // 11 External ARM7 Rom + { "u29.bin", 0x400000, 0xfa5f3901, 8 | BRF_PRG | BRF_ESS }, // 12 +}; + +STDROMPICKEXT(svg, svg, pgm) +STD_ROM_FN(svg) + +static INT32 svgInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_svg; +// pPgmProtCallback = install_protection_asic27a_svg; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvSvg = { + "svg", NULL, "pgm", NULL, "2005", + "S.V.G. - Spectral vs Generation (V200, China)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, svgRomInfo, svgRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + svgInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// ----------------------------------------------------------------------------- +// PCB Versions! + + +// DoDonPachi Dai-Ou-Jou (V101, Japan) + +static struct BurnRomInfo ddp3RomDesc[] = { + { "ddp3_v101.u36", 0x200000, 0x195b5c1e, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04401w064.u19", 0x800000, 0x3a95f19c, 2 | BRF_GRA }, // 1 Tile data + + { "a04401w064.u7", 0x800000, 0xed229794, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04402w064.u8", 0x800000, 0x752167b0, 3 | BRF_GRA }, // 3 + + { "b04401w064.u1", 0x800000, 0x8cbff066, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04401b032.u17", 0x400000, 0x5a0dbd76, 5 | BRF_SND }, // 5 Samples + + { "ddp3_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ddp3_defaults.nv", 0x020000, 0x571e96c0, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(ddp3, ddp3, ddp3Bios) /* custom bios */ +STD_ROM_FN(ddp3) + +static INT32 ddp3Init() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_py2k2; // the same. + pPgmProtCallback = install_protection_asic27a_ddp3; // simulation + + return pgmInit(); +} + +struct BurnDriver BurnDrvDdp3 = { + "ddpdoj", NULL, NULL, NULL, "2002", + "DoDonPachi Dai-Ou-Jou (V101, Japan)\0", "Incomplete Protection Simulation", "Cave / AMI", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, ddp3RomInfo, ddp3RomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ddp3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224, 448, 3, 4 +}; + + +// DoDonPachi Dai-Ou-Jou (V100 (second version), Japan) + +static struct BurnRomInfo ddp3aRomDesc[] = { + { "ddp3_d_d_1_0.u36", 0x200000, 0x5D3F85BA, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04401w064.u19", 0x800000, 0x3a95f19c, 2 | BRF_GRA }, // 1 Tile data + + { "a04401w064.u7", 0x800000, 0xed229794, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04402w064.u8", 0x800000, 0x752167b0, 3 | BRF_GRA }, // 3 + + { "b04401w064.u1", 0x800000, 0x8cbff066, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04401b032.u17", 0x400000, 0x5a0dbd76, 5 | BRF_SND }, // 5 Samples + + { "ddp3_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ddp3_defaults.nv", 0x020000, 0x571e96c0, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(ddp3a, ddp3a, ddp3Bios) /* custom bios */ +STD_ROM_FN(ddp3a) + +struct BurnDriver BurnDrvDdp3a = { + "ddpdoja", "ddpdoj", NULL, NULL, "2002", + "DoDonPachi Dai-Ou-Jou (V100 (second version), Japan)\0", "Incomplete Protection Simulation", "Cave / AMI", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, ddp3aRomInfo, ddp3aRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ddp3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224, 448, 3, 4 +}; + + +// DoDonPachi Dai-Ou-Jou (V100 (first version), Japan) + +static struct BurnRomInfo ddp3bRomDesc[] = { + { "dd v100.bin", 0x200000, 0x7da0c1e4, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04401w064.u19", 0x800000, 0x3a95f19c, 2 | BRF_GRA }, // 1 Tile data + + { "a04401w064.u7", 0x800000, 0xed229794, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04402w064.u8", 0x800000, 0x752167b0, 3 | BRF_GRA }, // 3 + + { "b04401w064.u1", 0x800000, 0x8cbff066, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04401b032.u17", 0x400000, 0x5a0dbd76, 5 | BRF_SND }, // 5 Samples + + { "ddp3_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ddp3_defaults.nv", 0x020000, 0x571e96c0, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(ddp3b, ddp3b, ddp3Bios) /* custom bios */ +STD_ROM_FN(ddp3b) + +struct BurnDriver BurnDrvDdp3b = { + "ddpdojb", "ddpdoj", NULL, NULL, "2002", + "DoDonPachi Dai-Ou-Jou (V100 (first version), Japan)\0", "Incomplete Protection Simulation", "Cave / AMI", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, ddp3bRomInfo, ddp3bRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ddp3Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x1200, + 224, 448, 3, 4 +}; + + +// DoDonPachi Dai-Ou-Jou Black Label (V100, Japan) + +static struct BurnRomInfo ddp3blkRomDesc[] = { + { "ddb10.u45", 0x200000, 0x72b35510, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04401w064.u19", 0x800000, 0x3a95f19c, 2 | BRF_GRA }, // 1 Tile data + + { "a04401w064.u7", 0x800000, 0xed229794, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04402w064.u8", 0x800000, 0x752167b0, 3 | BRF_GRA }, // 3 + + { "b04401w064.u1", 0x800000, 0x8cbff066, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04401b032.u17", 0x400000, 0x5a0dbd76, 5 | BRF_SND }, // 5 Samples + + { "ddp3_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ddp3blk_defaults.nv", 0x020000, 0xa1651904, 0 | BRF_OPT }, // 7 NV RAM (patch below instead) +}; + +STDROMPICKEXT(ddp3blk, ddp3blk, ddp3Bios) /* custom bios */ +STD_ROM_FN(ddp3blk) + +/* + Black Label has some values set in the NV ram. If the battery dies, + the pcb must be sent back to Cave for repair. +*/ + +static void ddp3blkPatchRAM() +{ + SekOpen(0); + SekWriteLong(0x803800, 0x95804803); // cmpi.l #$95804803,($803800).l + SekWriteLong(0x803804, 0x23879065); // cmpi.l #$23879065,($803804).l + SekClose(); + + // enable asic test +// *((UINT16*)(PGM68KROM + 0x03c0f4)) = SWAP_WORD_LSB(0x0012); +} + +static INT32 ddp3blkInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_py2k2; // the same + pPgmProtCallback = install_protection_asic27a_ddp3; // simulation + + INT32 nRet = pgmInit(); + + if (nRet == 0) { + ddp3blkPatchRAM(); + } + + return nRet; +} + +struct BurnDriver BurnDrvDdp3blk = { + "ddpdojblk", "ddpdoj", NULL, NULL, "2002", + "DoDonPachi Dai-Ou-Jou Black Label (V100, Japan)\0", "Incomplete Protection Simulation", "Cave / AMI", "PolyGameMaster", + L"DoDonPachi Dai-Ou-Jou Black Label\0\u6012\u9996\u9818\u8702 \u5927\u5F80\u751F Black Label (V100, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, ddp3blkRomInfo, ddp3blkRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ddp3blkInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 224, 448, 3, 4 +}; + + +// Ketsui Kizuna Jigoku Tachi (Revision 2?, Japan) + +static struct BurnRomInfo ketRomDesc[] = { + { "ketsui_v100.u38", 0x200000, 0xdfe62f3b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04701w064.u19", 0x800000, 0x2665b041, 2 | BRF_GRA }, // 1 Tile data + + { "a04701w064.u7", 0x800000, 0x5ef1b94b, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04702w064.u8", 0x800000, 0x26d6da7f, 3 | BRF_GRA }, // 3 + + { "b04701w064.u1", 0x800000, 0x1bec008d, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04701b032.u17", 0x400000, 0xb46e22d1, 5 | BRF_SND }, // 5 Samples + + { "ket_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ket_defaults.nv", 0x020000, 0x3ca892d8, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(ket, ket, ketsuiBios) /* custom bios */ +STD_ROM_FN(ket) + +static INT32 ketsuiInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_ketsui; + pPgmProtCallback = install_protection_asic27a_ketsui; // simulation + + return pgmInit(); +} + +struct BurnDriver BurnDrvKet = { + "ket", NULL, NULL, NULL, "2002", + "Ketsui Kizuna Jigoku Tachi (Revision 2?, Japan)\0", NULL, "CAVE / AMI", "PolyGameMaster based", + L"Ketsui Kizuna Jigoku Tachi\0\u30B1\u30C4\u30A4~\u7D46\u5730\u7344\u305F\u3061 (Revision 2?, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_JAMMAPCB/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_VERSHOOT, 0, + NULL, ketRomInfo, ketRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ketsuiInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 224, 448, 3, 4 +}; + + +// Ketsui Kizuna Jigoku Tachi (Revision 1?, Japan) + +static struct BurnRomInfo ketaRomDesc[] = { + { "ketsui_prg_revised.bin", 0x200000, 0x69fcf5eb, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04701w064.u19", 0x800000, 0x2665b041, 2 | BRF_GRA }, // 1 Tile data + + { "a04701w064.u7", 0x800000, 0x5ef1b94b, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04702w064.u8", 0x800000, 0x26d6da7f, 3 | BRF_GRA }, // 3 + + { "b04701w064.u1", 0x800000, 0x1bec008d, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04701b032.u17", 0x400000, 0xb46e22d1, 5 | BRF_SND }, // 5 Samples + + { "ket_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ket_defaults.nv", 0x020000, 0x3ca892d8, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(keta, keta, ketsuiBios) /* custom bios */ +STD_ROM_FN(keta) + +struct BurnDriver BurnDrvKeta = { + "keta", "ket", NULL, NULL, "2002", + "Ketsui Kizuna Jigoku Tachi (Revision 1?, Japan)\0", NULL, "CAVE / AMI", "PolyGameMaster based", + L"Ketsui Kizuna Jigoku Tachi\0\u30B1\u30C4\u30A4~\u7D46\u5730\u7344\u305F\u3061 (Revision 1?, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_JAMMAPCB/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_VERSHOOT, 0, + NULL, ketaRomInfo, ketaRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ketsuiInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 224, 448, 3, 4 +}; + + +// Ketsui Kizuna Jigoku Tachi (Original?, Japan) + +static struct BurnRomInfo ketbRomDesc[] = { + { "ketsui_prg_original.bin", 0x200000, 0xcca5e153, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04701w064.u19", 0x800000, 0x2665b041, 2 | BRF_GRA }, // 1 Tile data + + { "a04701w064.u7", 0x800000, 0x5ef1b94b, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04702w064.u8", 0x800000, 0x26d6da7f, 3 | BRF_GRA }, // 3 + + { "b04701w064.u1", 0x800000, 0x1bec008d, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "m04701b032.u17", 0x400000, 0xb46e22d1, 5 | BRF_SND }, // 5 Samples + + { "ket_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom + + { "ket_defaults.nv", 0x020000, 0x3ca892d8, 0 | BRF_OPT }, // 7 NV RAM +}; + +STDROMPICKEXT(ketb, ketb, ketsuiBios) /* custom bios */ +STD_ROM_FN(ketb) + +struct BurnDriver BurnDrvKetb = { + "ketb", "ket", NULL, NULL, "2002", + "Ketsui Kizuna Jigoku Tachi (Original?, Japan)\0", NULL, "CAVE / AMI", "PolyGameMaster based", + L"Ketsui Kizuna Jigoku Tachi\0\u30B1\u30C4\u30A4~\u7D46\u5730\u7344\u305F\u3061 (Original?, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_JAMMAPCB/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_VERSHOOT, 0, + NULL, ketbRomInfo, ketbRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + ketsuiInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 224, 448, 3, 4 +}; + + +// Espgaluda (V100, Japan) + +static struct BurnRomInfo espgalRomDesc[] = { + { "espgaluda_v100.u38", 0x200000, 0x08ecec34, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t04801w064.u19", 0x800000, 0x6021c79e, 2 | BRF_GRA }, // 1 Tile data + + { "a04801w064.u7", 0x800000, 0x26dd4932, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04802w064.u8", 0x800000, 0x0e6bf7a9, 3 | BRF_GRA }, // 3 + + { "b04801w064.u1", 0x800000, 0x98dce13a, 4 | BRF_GRA }, // 4 Sprite Masks & Color Indexes + + { "w04801b032.u17", 0x400000, 0x60298536, 5 | BRF_SND }, // 5 Samples + + { "espgal_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 6 Internal ARM7 Rom +}; + +STDROMPICKEXT(espgal, espgal, espgalBios) /* custom bios */ +STD_ROM_FN(espgal) + +static INT32 espgalInit() +{ + nPGMEnableIRQ4 = 1; + pPgmInitCallback = pgm_decrypt_espgaluda; + pPgmProtCallback = install_protection_asic27a_ketsui; // simulation + + return pgmInit(); +} + +struct BurnDriver BurnDrvEspgal = { + "espgal", NULL, NULL, NULL, "2003", + "Espgaluda (V100, Japan)\0", NULL, "CAVE / AMI", "PolyGameMaster based", + L"Espgaluda\0\u30A8\u30B9\u30D7\u30AC\u30EB\u30FC\u30C0 (V100, Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_JAMMAPCB/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_VERSHOOT, 0, + NULL, espgalRomInfo, espgalRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + espgalInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 224, 448, 3, 4 +}; + + + +// The Gladiator / Shen Jian (V100, Japan, PCB Version) + +static struct BurnRomInfo thegladpcbRomDesc[] = { + { "v100.u43", 0x080000, 0xBCF3B172, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + // u71 on this board + { "t04601.u33", 0x800000, 0xe5dab371, 2 | BRF_GRA }, // 1 Tile data + + // u30, u31 & u32 + { "a04601.u2", 0x800000, 0xd9b2e004, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a04602.u4", 0x800000, 0x14f22308, 3 | BRF_GRA }, // 3 + { "a04603.u6", 0x800000, 0x8f621e17, 3 | BRF_GRA }, // 4 + + // u40 & u41 + { "b04601.u11", 0x800000, 0xee72bccf, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + { "b04602.u12", 0x400000, 0x7dba9c38, 4 | BRF_GRA }, // 6 + + { "w04601.u1", 0x800000, 0x5f15ddb3, 5 | BRF_SND }, // 7 Samples + + { "thegladpcb_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 8 Internal ARM7 Rom + + { "v100.u62", 0x200000, 0x0F3F511E, 8 | BRF_PRG | BRF_ESS }, // 9 External ARM7 Rom +}; + +STDROMPICKEXT(thegladpcb, thegladpcb, thegladBIOS) /* custom bios */ +STD_ROM_FN(thegladpcb) + +static INT32 thegladpcbInit() +{ + INT32 nRet = thegladInit(); + + if (nRet == 0) { + if (BurnLoadRom(ICSSNDROM + 0x200000, 0x83, 1)) return 1; // load extra 'wave' bios sample rom + } + + return nRet; +} + +struct BurnDriverD BurnDrvThegladpcb = { + "thegladpcb", NULL, NULL, NULL, "2003", + "The Gladiator / Shen Jian (V100, Japan, Single PCB Version)\0", "Incomplete Dump", "IGS", "PolyGameMaster", + L"The Gladiator (V100, Japan, PCB Version)\0\u795E\u5251\u98CE\u4E91\0\u795E\u528D\u98A8\u96F2\0", NULL, NULL, NULL, + 0, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, thegladpcbRomInfo, thegladpcbRomName, NULL, NULL, pgmInputInfo, jammaDIPInfo, + thegladpcbInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// ----------------------------------------------------------------------------- +// Homebrew + + +// Chaos (PGM Demo) + +static struct BurnRomInfo pgmdemoRomDesc[] = { + { "p0103.rom", 0x200000, 0xd3f6ec45, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x0596a59a, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x5d0e8fa1, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "b0100.rom", 0x400000, 0x15dd191f, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes + + { "m0100.rom", 0x200000, 0x8d89877e, 5 | BRF_SND }, // 4 Samples +}; + +STDROMPICKEXT(pgmdemo, pgmdemo, pgm) +STD_ROM_FN(pgmdemo) + +struct BurnDriver BurnDrvPgmdemo = { + "pgmdemo", NULL, "pgm", NULL, "2005", + "Chaos (PGM Demo)\0", "Demo Game", "Raster", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_DEMO, 4, HARDWARE_IGS_PGM, GBF_MISC, 0, + NULL, pgmdemoRomInfo, pgmdemoRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + pgmInit,pgmExit,pgmFrame,pgmDraw,NULL, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Frog Feast (PGM) + +static struct BurnRomInfo pgmfrogRomDesc[] = { + { "p0103.rom", 0x200000, 0xcdec9e8d, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x8f58b6d8, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0xdc1eafe6, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "b0100.rom", 0x400000, 0x3d44b66f, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes + + { "m0100.rom", 0x200000, 0x05e2f761, 5 | BRF_SND }, // 4 Samples +}; + +STDROMPICKEXT(pgmfrog, pgmfrog, pgm) +STD_ROM_FN(pgmfrog) + +struct BurnDriver BurnDrvPgmfrog = { + "pgmfrog", NULL, "pgm", NULL, "2006", + "Frog Feast (PGM)\0", NULL, "RasterSoft", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 4, HARDWARE_IGS_PGM, GBF_MISC, 0, + NULL, pgmfrogRomInfo, pgmfrogRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + pgmInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// P-GeMeni (060123) + +static struct BurnRomInfo pgemeniRomDesc[] = { + { "p0103.rom", 0x200000, 0x6cafa56b, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0100.rom", 0x400000, 0x42b979dd, 2 | BRF_GRA }, // 1 Tile data + + { "a0100.rom", 0x400000, 0x105d7cee, 3 | BRF_GRA }, // 2 Sprite Color Data + + { "b0100.rom", 0x400000, 0xb4127373, 4 | BRF_GRA }, // 3 Sprite Masks & Color Indexes + + { "m0100.rom", 0x200000, 0x8d89877e, 5 | BRF_SND }, // 4 Samples +}; + +STDROMPICKEXT(pgemeni, pgemeni, pgm) +STD_ROM_FN(pgemeni) + +struct BurnDriver BurnDrvPgemeni = { + "pgemeni", NULL, "pgm", NULL, "2006", + "P-GeMeni (060123)\0", NULL, "blastar@gmx.net", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HOMEBREW, 4, HARDWARE_IGS_PGM, GBF_PUZZLE, 0, + NULL, pgemeniRomInfo, pgemeniRomName, NULL, NULL, pgmInputInfo, pgmDIPInfo, + pgmInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +//----------------------------------------------------------------------------------------------------------------- +// Bootlegs + + +// Knights of Valour: Quan Huang San Guo Special / Sangoku Senki: Quan Huang San Guo Special (ver. 303CN) + +static struct BurnRomInfo kovqhsgsRomDesc[] = { + { "qhsg_c51.rom", 0x0400000, 0xe5cbac85, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "qhsg_prot.c51", 0x0004000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovqhsgs, kovqhsgs, pgm) +STD_ROM_FN(kovqhsgs) + +static INT32 kovqhsgsInit() +{ + Arm7SetIdleLoopAddress(0x00000260); + + pPgmInitCallback = pgm_decrypt_kovqhsgs; + pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriver BurnDrvkovqhsgs = { + "kovqhsgs", "kovsh", "pgm", NULL, "1999", + "Knights of Valour: Quan Huang San Guo Special / Sangoku Senki: Quan Huang San Guo Special (ver. 303CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM | HARDWARE_IGS_USE_ARM_CPU, GBF_SCRFIGHT, 0, + NULL, kovqhsgsRomInfo, kovqhsgsRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovqhsgsInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: Luan Shi Quan Huang 2 / Sangoku Senki: Luan Shi Quan Huang 2 (ver. 200CN) + +static struct BurnRomInfo kovlsqh2RomDesc[] = { + { "lsqh2_prg.rom", 0x0400000, 0xd71e3d50, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "qhsg_prot.c51", 0x0004000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovlsqh2, kovlsqh2, pgm) +STD_ROM_FN(kovlsqh2) + +static INT32 kovlsqh2Init() +{ + pPgmInitCallback = pgm_decrypt_kovlsqh2; +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvkovlsqh2 = { + "kovlsqh2", "kovshp", "pgm", NULL, "2009", + "Knights of Valour: Luan Shi Quan Huang 2 / Sangoku Senki: Luan Shi Quan Huang 2 (ver. 200CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, kovlsqh2RomInfo, kovlsqh2RomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovlsqh2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + +// Knights of Valour: Luan Shi Quan Huang 2 / Sangoku Senki: Luan Shi Quan Huang (ver. 200CN) + +static struct BurnRomInfo kovlsqhRomDesc[] = { + { "lsqh_v200cn.rom", 0x0400000, 0x9935a27a, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "qhsg_prot.c51", 0x0004000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovlsqh, kovlsqh, pgm) +STD_ROM_FN(kovlsqh) + +static INT32 kovlsqhInit() +{ + pPgmInitCallback = pgm_decrypt_kovlsqh2; +// pPgmProtCallback = install_protection_asic27a_kovsh; +// pPgmProtCallback = install_protection_asic27a_simulation_debug; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvkovlsqh = { + "kovlsqh", "kovshp", "pgm", NULL, "2009", + "Knights of Valour: Luan Shi Quan Huang / Sangoku Senki: Luan Shi Quan Huang (ver. 200CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, kovlsqhRomInfo, kovlsqhRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovlsqhInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN) + +static struct BurnRomInfo kovlsjbRomDesc[] = { + { "lsjb_prg.rom", 0x0400000, 0xadf06b37, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "qhsg_prot.c51", 0x0004000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovlsjb, kovlsjb, pgm) +STD_ROM_FN(kovlsjb) + +struct BurnDriverD BurnDrvkovlsjb = { + "kovlsjb", "kovshp", "pgm", NULL, "2009", + "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovlsjbRomInfo, kovlsjbRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovlsqh2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (alt ver. 200CN) + +static struct BurnRomInfo kovlsjbaRomDesc[] = { + { "lsjba_prg.rom", 0x0400000, 0x8b42f456, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "qhsg_prot.c51", 0x0004000, 0x0f09a5c1, 7 | BRF_ESS | BRF_PRG }, // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovlsjba, kovlsjba, pgm) +STD_ROM_FN(kovlsjba) + +struct BurnDriverD BurnDrvkovlsjba = { + "kovlsjba", "kovshp", "pgm", NULL, "2009", + "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (alt ver. 200CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovlsjbaRomInfo, kovlsjbaRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovlsqh2Init, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: Ao Shi San Guo / Sangoku Senki: Ao Shi San Guo (ver. 315CN) + +static struct BurnRomInfo kovassgRomDesc[] = { + { "assg_v315cn.rom", 0x0400000, 0xb9885d5c, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "lsqh2_t01.rom", 0x1000000, 0xd498d97f, 2 | BRF_GRA }, // 1 Tile data + + { "lsqh2_a01.rom", 0x1000000, 0x25ae3efd, 3 | BRF_GRA }, // 2 Sprite Color Data + { "lsqh2_a23.rom", 0x1000000, 0x7a779112, 3 | BRF_GRA }, // 3 + { "lsqh2_a45.rom", 0x1000000, 0x5d7de052, 3 | BRF_GRA }, // 4 + + { "lsqh2_b01.rom", 0x1000000, 0xdf7ca696, 4 | BRF_GRA }, // 5 Sprite Masks & Color Indexes + + { "lsqh2_m01.rom", 0x1000000, 0x01af1b65, 5 | BRF_SND }, // 6 Samples + + { "assg_prot.arm", 0x0010000, 0x00000000, 7 | BRF_ESS | BRF_PRG | BRF_NODUMP } // 7 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovassg, kovassg, pgm) +STD_ROM_FN(kovassg) + +static INT32 kovassgInit() +{ + pPgmInitCallback = pgm_decrypt_kovassg; +// pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvkovassg = { + "kovassg", "kovshp", "pgm", NULL, "2009", + "Knights of Valour: Ao Shi San Guo / Sangoku Senki: Ao Shi San Guo (ver. 315CN)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM /* | HARDWARE_IGS_USE_ARM_CPU */, GBF_SCRFIGHT, 0, + NULL, kovassgRomInfo, kovassgRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovassgInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: Aoshi Sanguo / Sangoku Senki: Aoshi Sanguo (ver. 202CN) + +static struct BurnRomInfo kovshxasRomDesc[] = { + { "de_p0609.322", 0x400000, 0x3b7b627f, 1 | BRF_ESS | BRF_PRG }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603xas.rom", 0x800000, 0x7057b37e, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 6 Sprite Masks & Color Indexes + { "b0601xas.rom", 0x800000, 0x3784fb49, 4 | BRF_GRA }, // 7 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 8 Samples + + { "kovshxas_v100_china.asic", 0x004000, 0x00000000, 0 | BRF_ESS | BRF_PRG | BRF_NODUMP }, // 9 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovshxas, kovshxas, pgm) +STD_ROM_FN(kovshxas) + +static INT32 kovshxasInit() +{ + pPgmProtCallback = install_protection_asic27a_kovsh; + + return pgmInit(); +} + +struct BurnDriverD BurnDrvkovshxas = { + "kovshxas", "kovshp", "pgm", NULL, "2004", + "Knights of Valour: Aoshi Sanguo / Sangoku Senki: Aoshi Sanguo (ver. 202CN)\0", "Incomplete dump", "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovshxasRomInfo, kovshxasRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovshxasInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan (set 1) + +static struct BurnRomInfo kovsgqyzRomDesc[] = { + { "pgm_sgqyz.rom", 0x400000, 0x18e1eed9, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 +// { "qyza0603.rom", 0x800000, 0xc8b92220, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 11 +// { "qyzb0601.rom", 0x800000, 0x64f55882, 4 | BRF_GRA }, // 11 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 12 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 13 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovsgqyz, kovsgqyz, pgm) +STD_ROM_FN(kovsgqyz) + +static INT32 kovsgqyzInit() +{ + nPGMEnableIRQ4 = 1; + pPgmProtCallback = install_protection_asic27_kov; // simulation + + return pgmInit(); +} + +struct BurnDriver BurnDrvKovsgqyz = { + "kovsgqyz", "kovplus", "pgm", NULL, "1999", + "Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan (set 1)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovsgqyzRomInfo, kovsgqyzRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovsgqyzInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; + + +// Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan (set 2) + +static struct BurnRomInfo kovsgqyzaRomDesc[] = { + { "pgm_sgqyza.rom",0x400000, 0x5a30dcb7, 1 | BRF_PRG | BRF_ESS }, // 0 68K Code + + { "t0600.rom", 0x800000, 0x4acc1ad6, 2 | BRF_GRA }, // 1 Tile data + + { "a0600.rom", 0x800000, 0xd8167834, 3 | BRF_GRA }, // 2 Sprite Color Data + { "a0601.rom", 0x800000, 0xff7a4373, 3 | BRF_GRA }, // 3 + { "a0602.rom", 0x800000, 0xe7a32959, 3 | BRF_GRA }, // 4 + { "a0603.rom", 0x400000, 0xec31abda, 3 | BRF_GRA }, // 5 +// { "qyza0603.rom", 0x800000, 0xc8b92220, 3 | BRF_GRA }, // 5 + + { "b0600.rom", 0x800000, 0x7d3cd059, 4 | BRF_GRA }, // 10 Sprite Masks & Color Indexes + { "b0601.rom", 0x400000, 0xa0bb1c2f, 4 | BRF_GRA }, // 11 +// { "qyzb0601.rom", 0x800000, 0x64f55882, 4 | BRF_GRA }, // 11 + + { "m0600.rom", 0x400000, 0x3ada4fd6, 5 | BRF_SND }, // 12 Samples + + { "kov_igs027a.bin", 0x004000, 0x00000000, 7 | BRF_PRG | BRF_NODUMP }, // 13 Internal ARM7 Rom +}; + +STDROMPICKEXT(kovsgqyza, kovsgqyza, pgm) +STD_ROM_FN(kovsgqyza) + +struct BurnDriver BurnDrvKovsgqyza = { + "kovsgqyza", "kovplus", "pgm", NULL, "1999", + "Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan (set 2)\0", NULL, "IGS", "PolyGameMaster", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_IGS_PGM/* | HARDWARE_IGS_USE_ARM_CPU*/, GBF_SCRFIGHT, 0, + NULL, kovsgqyzaRomInfo, kovsgqyzaRomName, NULL, NULL, pgmInputInfo, sangoDIPInfo, + kovsgqyzInit, pgmExit, pgmFrame, pgmDraw, pgmScan, &nPgmPalRecalc, 0x600, + 448, 224, 4, 3 +}; diff --git a/src/burn/drivers/pgm/pgm.h b/src/burn/drivers/pgm/pgm.h new file mode 100644 index 00000000..987f6a62 --- /dev/null +++ b/src/burn/drivers/pgm/pgm.h @@ -0,0 +1,113 @@ +#include "tiles_generic.h" +#include "arm7_intf.h" +#include "ics2115.h" + +#define HARDWARE_IGS_JAMMAPCB 0x0002 + +#ifdef LSB_FIRST +#define SWAP_WORD_LSB(x) (((x&0xff)<<8)|((x>>8)&0xff)) +#else +#define SWAP_WORD_LSB(x) (x) +#endif + +// pgm_run +extern INT32 nPGM68KROMLen; +extern INT32 nPGMSPRColMaskLen; +extern INT32 nPGMSPRMaskMaskLen; +extern INT32 nPGMTileROMLen; +extern INT32 nPGMExternalARMLen; + +extern UINT8 *PGM68KRAM; +extern UINT8 *PGM68KROM; +extern UINT8 *PGMTileROM; +extern UINT8 *PGMTileROMExp; +extern UINT8 *PGMSPRColROM; +extern UINT8 *PGMSPRMaskROM; +extern UINT8 *PGMARMROM; +extern UINT8 *PGMUSER0; +extern UINT8 *PGMARMRAM0; +extern UINT8 *PGMARMRAM1; +extern UINT8 *PGMARMRAM2; +extern UINT8 *PGMARMShareRAM; +extern UINT8 *PGMARMShareRAM2; +extern UINT16 *PGMRowRAM; +extern UINT16 *PGMPalRAM; +extern UINT16 *PGMVidReg; +extern UINT16 *PGMSprBuf; +extern UINT32 *PGMBgRAM; +extern UINT32 *PGMTxtRAM; +extern UINT32 *RamCurPal; +extern UINT8 nPgmPalRecalc; + +extern UINT8 PgmJoy1[]; +extern UINT8 PgmJoy2[]; +extern UINT8 PgmJoy3[]; +extern UINT8 PgmJoy4[]; +extern UINT8 PgmBtn1[]; +extern UINT8 PgmBtn2[]; +extern UINT8 PgmInput[]; +extern UINT8 PgmReset; + +extern void (*pPgmInitCallback)(); +extern void (*pPgmResetCallback)(); +extern INT32 (*pPgmScanCallback)(INT32, INT32*); +extern void (*pPgmProtCallback)(); + +extern INT32 nPGMEnableIRQ4; +extern INT32 nPGMArm7Type; + +INT32 pgmInit(); +INT32 pgmExit(); +INT32 pgmFrame(); +INT32 pgmScan(INT32 nAction, INT32 *pnMin); + +// pgm_draw +void pgmInitDraw(); +void pgmExitDraw(); +INT32 pgmDraw(); + +// pgm_prot +void install_protection_asic3_orlegend(); +void install_protection_asic25_asic12_dw2(); +void install_protection_asic25_asic22_killbld(); +void install_protection_asic25_asic28_olds(); +void install_protection_asic27_kov(); +void install_protection_asic27a_kovsh(); +void install_protection_asic27a_martmast(); +void install_protection_asic27a_oldsplus(); +void install_protection_asic27a_puzlstar(); +void install_protection_asic27a_ddp2(); +void install_protection_asic27a_svg(); +void install_protection_asic27a_ketsui(); +void install_protection_asic27a_ddp3(); + +// pgm_crypt +void pgm_decrypt_kov(); +void pgm_decrypt_kovsh(); +void pgm_decrypt_kovshp(); +void pgm_decrypt_puzzli2(); +void pgm_decrypt_dw2(); +void pgm_decrypt_photoy2k(); +void pgm_decrypt_puzlstar(); +void pgm_decrypt_dw3(); +void pgm_decrypt_killbld(); +void pgm_decrypt_dfront(); +void pgm_decrypt_ddp2(); +void pgm_decrypt_martmast(); +void pgm_decrypt_kov2(); +void pgm_decrypt_kov2p(); +void pgm_decrypt_theglad(); +void pgm_decrypt_killbldp(); +void pgm_decrypt_oldsplus(); +void pgm_decrypt_svg(); +void pgm_decrypt_happy6in1(); +void pgm_decrypt_dw2001(); +void pgm_decrypt_py2k2(); +void pgm_decrypt_espgaluda(); +void pgm_decrypt_ketsui(); + +void pgm_decode_kovqhsgs_gfx_block(UINT8 *src); +void pgm_decode_kovqhsgs_tile_data(UINT8 *source); +void pgm_decrypt_kovqhsgs(); +void pgm_decrypt_kovlsqh2(); +void pgm_decrypt_kovassg(); diff --git a/src/burn/drivers/pgm/pgm_crypt.cpp b/src/burn/drivers/pgm/pgm_crypt.cpp new file mode 100644 index 00000000..673c4c62 --- /dev/null +++ b/src/burn/drivers/pgm/pgm_crypt.cpp @@ -0,0 +1,975 @@ +/* IGS PGM System Encryptions */ + +#include "pgm.h" +#include "bitswap.h" + +/* + Some xor tables used to decrypt the program roms contain asci text + IGS #### RD ? YR MO DAY - GAME + IGS 0004 RD 1 02 10 15 - ketsui + IGS 0005 RD 1 02 12 03 - theglad + IGS 0007 RD 1 03 09 09 - espgaluda + IGS 0008 RD 1 03 12 15 - happy6in1 + IGS 0009 rd 1 04 02 19 - kovshp + IGS 0013 RD 1 04 07 27 - oldsplus + IGS 0024 RD 1 05 09 08 - killbldp + + IGS 0055 RD 4 02 06 21 - Sheng Dan Wu Xian (non-PGM, but uses asic27A) + + The later games (ones that use ASIC27/ASIC27A) have ram-based xor tables. The + internal ASIC program uploads the xor to the 0x50000000 - 0x500003ff region. +*/ + +void pgm_decrypt_dw2() +{ + UINT16 *src = (UINT16 *)PGM68KROM; + + for (INT32 i = 0; i> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static UINT8 ddp2_tab[256] = { + 0x2a, 0x4a, 0x39, 0x98, 0xac, 0x39, 0xb2, 0x55, 0x72, 0xf3, 0x7b, 0x3c, 0xee, 0x94, 0x6e, 0xd5, + 0xcd, 0xbc, 0x9a, 0xd0, 0x45, 0x7d, 0x49, 0x68, 0xb1, 0x61, 0x54, 0xef, 0xa2, 0x84, 0x29, 0x20, + 0x32, 0x52, 0x82, 0x04, 0x38, 0x69, 0x9f, 0x24, 0x46, 0xf4, 0x3f, 0xc2, 0xf1, 0x25, 0xac, 0x2d, + 0xdf, 0x2d, 0xb4, 0x51, 0xc7, 0xb5, 0xe5, 0x88, 0xbd, 0x3b, 0x5a, 0x25, 0x5b, 0xc7, 0xae, 0x5f, + 0x43, 0xcf, 0x89, 0xd9, 0xe2, 0x63, 0xc6, 0x76, 0x21, 0x2b, 0x77, 0xc0, 0x27, 0x98, 0xfd, 0x09, + 0xe1, 0x8c, 0x26, 0x2e, 0x92, 0x99, 0xbc, 0xbe, 0x0e, 0xba, 0xbf, 0x70, 0xe7, 0xb7, 0xe9, 0x37, + 0x5c, 0xd1, 0x5e, 0xad, 0x22, 0x17, 0xc5, 0x67, 0x9d, 0xc6, 0xfb, 0x53, 0xc7, 0x4d, 0x32, 0xb4, + 0xf2, 0x43, 0x53, 0x7c, 0x01, 0xfe, 0xd2, 0x91, 0x40, 0x85, 0xa3, 0xe8, 0xdf, 0xdb, 0xff, 0x6c, + 0x64, 0x15, 0xcd, 0x8e, 0x07, 0x82, 0x78, 0x8d, 0x4e, 0x2d, 0x66, 0x8a, 0x62, 0x6f, 0xd3, 0x6a, + 0xae, 0x16, 0x44, 0x1e, 0xed, 0xc4, 0x12, 0x7a, 0xbe, 0x05, 0x06, 0xce, 0x9b, 0x8a, 0xf7, 0xf8, + 0x74, 0x23, 0x73, 0x74, 0xb8, 0x13, 0xc2, 0x42, 0xea, 0xf9, 0x7f, 0xa9, 0xaf, 0x56, 0xd6, 0xb3, + 0xb7, 0xc4, 0x47, 0x31, 0x67, 0xaa, 0x58, 0x8b, 0x47, 0x1b, 0xf5, 0x75, 0x95, 0x8f, 0xf0, 0x3a, + 0x85, 0x76, 0x59, 0x24, 0x0c, 0xd7, 0x00, 0xb3, 0xdc, 0xfc, 0x65, 0x34, 0xde, 0xfa, 0xd8, 0xc3, + 0xc3, 0x5e, 0xe3, 0x9e, 0x02, 0x28, 0x50, 0x81, 0x95, 0x2f, 0xe4, 0xb5, 0xa0, 0x4d, 0xa1, 0x36, + 0x9d, 0x18, 0x6d, 0x79, 0x19, 0x3b, 0x1d, 0xb8, 0xe1, 0xcc, 0x61, 0x1a, 0xe2, 0x31, 0x4c, 0x3f, + 0xdc, 0xca, 0xd4, 0xda, 0xcd, 0xd2, 0x83, 0xca, 0xeb, 0x4f, 0xf2, 0x2f, 0x2d, 0x2a, 0xec, 0x1f +}; + +void pgm_decrypt_ddp2() +{ + UINT16 *src = (UINT16 *)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x0480) != 0x0080) x ^= 0x0001; + if ((i & 0x0042) != 0x0042) x ^= 0x0008; + if ((i & 0x8100) == 0x8000) x ^= 0x0010; + if ((i & 0x2004) != 0x0004) x ^= 0x0020; + if ((i & 0x1800) != 0x0000) x ^= 0x0040; + if ((i & 0x0820) == 0x0820) x ^= 0x0080; + + x ^= ddp2_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static UINT8 mm_tab[256] = { + 0xd0, 0x45, 0xbc, 0x84, 0x93, 0x60, 0x7d, 0x49, 0x68, 0xb1, 0x54, 0xa2, 0x05, 0x29, 0x41, 0x20, + 0x04, 0x08, 0x52, 0x25, 0x89, 0xf4, 0x69, 0x9f, 0x24, 0x46, 0x3d, 0xf1, 0xf9, 0xab, 0xa6, 0x2d, + 0x18, 0x19, 0x6d, 0x33, 0x79, 0x23, 0x3b, 0x1d, 0xe0, 0xb8, 0x61, 0x1a, 0xe1, 0x4c, 0x5d, 0x3f, + 0x5e, 0x02, 0xe3, 0x4d, 0x9e, 0x80, 0x28, 0x50, 0xa0, 0x81, 0xe4, 0xa5, 0x97, 0xa1, 0x86, 0x36, + 0x1e, 0xed, 0x16, 0x8a, 0x44, 0x06, 0x64, 0x12, 0x9a, 0x7e, 0xce, 0x9b, 0xef, 0xf7, 0x3e, 0xf8, + 0x15, 0x07, 0xcb, 0x6f, 0x8e, 0x3c, 0x82, 0x70, 0x62, 0x8d, 0x66, 0x7a, 0x4e, 0xd3, 0xb6, 0x6a, + 0x51, 0xa7, 0x2c, 0xc7, 0xa4, 0x0b, 0xb5, 0xe5, 0x88, 0xbd, 0x5a, 0x5b, 0x1b, 0xae, 0xe6, 0x5f, + 0x2e, 0x92, 0x8c, 0xb7, 0x96, 0xba, 0x99, 0xbb, 0xbe, 0x0e, 0xbf, 0xe7, 0x2f, 0xe9, 0x30, 0x37, + 0x98, 0xac, 0x4a, 0x94, 0x38, 0xf3, 0x39, 0xb2, 0x55, 0x72, 0x7b, 0xee, 0xdd, 0x6e, 0x11, 0xd5, + 0x26, 0xa8, 0x71, 0xd6, 0x74, 0x7f, 0x13, 0xc2, 0x56, 0xea, 0xa9, 0xaf, 0xc3, 0x42, 0x03, 0xb3, + 0xc4, 0x6b, 0x47, 0xf0, 0x31, 0xf5, 0xaa, 0x58, 0x8f, 0x48, 0x75, 0x95, 0x35, 0x8b, 0x57, 0x3a, + 0x73, 0x0c, 0x59, 0xd8, 0x14, 0x65, 0xd7, 0x00, 0xfa, 0xdc, 0x34, 0xde, 0xc0, 0xb0, 0x87, 0xc1, + 0xc8, 0xcd, 0xd4, 0x2a, 0xda, 0xe8, 0xd2, 0x83, 0x0d, 0xca, 0xf2, 0x0f, 0xeb, 0xec, 0x9c, 0x1f, + 0xad, 0x22, 0xd1, 0x4b, 0x5c, 0xf6, 0x17, 0xc5, 0x67, 0x9d, 0xfb, 0xc9, 0xcc, 0x32, 0x1c, 0xb4, + 0xd9, 0xe2, 0xcf, 0x90, 0xb9, 0x2b, 0x63, 0xc6, 0x76, 0x21, 0x77, 0x27, 0xfc, 0xfd, 0x0a, 0x09, + 0x7c, 0x01, 0x43, 0xdb, 0x53, 0x85, 0xfe, 0x78, 0x91, 0x40, 0xa3, 0xdf, 0x4f, 0xff, 0x10, 0x6c +}; + +void pgm_decrypt_martmast() // and dw2001 +{ + UINT16 *src = (UINT16 *)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x040480) != 0x000080) x ^= 0x0001; + if ((i & 0x004008) == 0x004008) x ^= 0x0002; + if ((i & 0x000030) == 0x000010) x ^= 0x0004; + if ((i & 0x000242) != 0x000042) x ^= 0x0008; + if ((i & 0x008100) == 0x008000) x ^= 0x0010; + if ((i & 0x022004) != 0x000004) x ^= 0x0020; + if ((i & 0x011800) != 0x010000) x ^= 0x0040; + if ((i & 0x000820) == 0x000820) x ^= 0x0080; + + x ^= mm_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static const UINT8 kov2_tab[256] = { + 0x11, 0x4a, 0x38, 0x98, 0xac, 0x39, 0xb2, 0x55, 0x72, 0xf3, 0x7b, 0x3c, 0xee, 0x94, 0x6e, 0xd5, + 0x41, 0xbc, 0x93, 0xd0, 0x45, 0x7d, 0x49, 0x68, 0xb1, 0x60, 0x54, 0xef, 0xa2, 0x84, 0x29, 0x20, + 0xa6, 0x52, 0x89, 0x04, 0x08, 0x69, 0x9f, 0x24, 0x46, 0xf4, 0x3d, 0xc3, 0xf1, 0x25, 0xab, 0x2d, + 0xe6, 0x2c, 0xa4, 0x51, 0xa7, 0xb5, 0xe5, 0x88, 0xbd, 0x0b, 0x5a, 0x35, 0x5b, 0xc7, 0xae, 0x5f, + 0x0a, 0xcf, 0xb9, 0xd9, 0xe2, 0x63, 0xc6, 0x76, 0x21, 0x2b, 0x77, 0xc0, 0x27, 0x90, 0xfd, 0x09, + 0x30, 0x8c, 0x96, 0x2e, 0x92, 0x99, 0xbb, 0xbe, 0x0e, 0xba, 0xbf, 0x80, 0xe7, 0xb7, 0xe9, 0x37, + 0x1c, 0xd1, 0x5c, 0xad, 0x22, 0x17, 0xc5, 0x67, 0x9d, 0xf6, 0xfb, 0x23, 0xc9, 0x4b, 0x32, 0xb4, + 0x10, 0x43, 0x53, 0x7c, 0x01, 0xfe, 0x78, 0x91, 0x40, 0x85, 0xa3, 0xe8, 0xdf, 0xdb, 0xff, 0x6c, + 0xb6, 0x15, 0xcb, 0x8e, 0x07, 0x82, 0x70, 0x8d, 0x4e, 0xdd, 0x66, 0x7a, 0x62, 0x6f, 0xd3, 0x6a, + 0x3e, 0x16, 0x44, 0x1e, 0xed, 0x64, 0x12, 0x9a, 0x7e, 0x05, 0x06, 0xce, 0x9b, 0x8a, 0xf7, 0xf8, + 0x03, 0x26, 0x71, 0x74, 0xa8, 0x13, 0xc2, 0x42, 0xea, 0xf9, 0x7f, 0xa9, 0xaf, 0x56, 0xd6, 0xb3, + 0x57, 0xc4, 0x47, 0x31, 0x6b, 0xaa, 0x58, 0x8b, 0x48, 0x1b, 0xf5, 0x75, 0x95, 0x8f, 0xf0, 0x3a, + 0x87, 0x73, 0x59, 0x14, 0x0c, 0xd7, 0x00, 0xb0, 0xdc, 0xfc, 0x65, 0x34, 0xde, 0xfa, 0xd8, 0xc1, + 0x86, 0x5e, 0xe3, 0x9e, 0x02, 0x28, 0x50, 0x81, 0x97, 0x2f, 0xe4, 0xa5, 0xa0, 0x4d, 0xa1, 0x36, + 0x5d, 0x18, 0x6d, 0x79, 0x19, 0x3b, 0x1d, 0xb8, 0xe1, 0xcc, 0x61, 0x1a, 0xe0, 0x33, 0x4c, 0x3f, + 0x9c, 0xc8, 0xd4, 0xda, 0xcd, 0xd2, 0x83, 0xca, 0xeb, 0x4f, 0xf2, 0x0f, 0x0d, 0x2a, 0xec, 0x1f +}; + +void pgm_decrypt_kov2() +{ + UINT16 *src = (UINT16 *)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x40080) != 0x00080) x ^= 0x0001; + if ((i & 0x80030) == 0x80010) x ^= 0x0004; + if ((i & 0x00042) != 0x00042) x ^= 0x0008; + if ((i & 0x48100) == 0x48000) x ^= 0x0010; + if ((i & 0x22004) != 0x00004) x ^= 0x0020; + if ((i & 0x01800) != 0x00000) x ^= 0x0040; + if ((i & 0x00820) == 0x00820) x ^= 0x0080; + + x ^= kov2_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static const UINT8 kov2p_tab[256] = { + 0x44, 0x47, 0xb8, 0x28, 0x03, 0xa2, 0x21, 0xbc, 0x17, 0x32, 0x4e, 0xe2, 0xdf, 0x69, 0x35, 0xc7, + 0xa2, 0x06, 0xec, 0x36, 0xd2, 0x44, 0x12, 0x6a, 0x8d, 0x51, 0x6b, 0x20, 0x69, 0x01, 0xca, 0xf0, + 0x71, 0xc4, 0x34, 0xdc, 0x6b, 0xd6, 0x42, 0x2a, 0x5d, 0xb5, 0xc7, 0x6f, 0x4f, 0xd8, 0xb3, 0xed, + 0x51, 0x9e, 0x37, 0x1e, 0xc0, 0x85, 0x2a, 0x91, 0xc6, 0x9c, 0xac, 0xf5, 0x20, 0x3b, 0x09, 0x74, + 0x24, 0xf1, 0xe0, 0x42, 0x02, 0xbe, 0x84, 0x75, 0x4a, 0x82, 0xa2, 0x17, 0xae, 0xb6, 0x24, 0x79, + 0x0a, 0x5a, 0x56, 0xcb, 0xa1, 0x2e, 0x47, 0xea, 0xa9, 0x25, 0x73, 0x79, 0x0b, 0x17, 0x9e, 0x33, + 0x64, 0xb6, 0x03, 0x7f, 0x4f, 0xc3, 0xae, 0x45, 0xe6, 0x82, 0x27, 0x01, 0x86, 0x6b, 0x50, 0x16, + 0xd3, 0x22, 0x90, 0x64, 0xfc, 0xa9, 0x31, 0x1c, 0x41, 0xd5, 0x07, 0xd3, 0xb2, 0xfe, 0x53, 0xd6, + 0x39, 0xfb, 0xe6, 0xbe, 0xda, 0x4d, 0x8a, 0x44, 0x3a, 0x9b, 0x9d, 0x56, 0x5e, 0x5f, 0xff, 0x6a, + 0xb6, 0xde, 0x2f, 0x12, 0x5a, 0x5d, 0xb0, 0xd0, 0x93, 0x92, 0xb2, 0x2c, 0x9d, 0x59, 0xee, 0x05, + 0xab, 0xa8, 0xd2, 0x25, 0x2c, 0xc5, 0xde, 0x18, 0x4d, 0xb6, 0x4e, 0x3d, 0xbf, 0xfa, 0xf9, 0x1d, + 0xba, 0x76, 0x79, 0xfc, 0x42, 0xb2, 0x8c, 0xae, 0xa9, 0x45, 0xba, 0xac, 0x55, 0x8e, 0x38, 0x67, + 0xc3, 0xa5, 0x0d, 0xdc, 0xcc, 0x91, 0x73, 0x69, 0x27, 0xbc, 0x80, 0xdf, 0x30, 0xa4, 0x05, 0xd8, + 0xe7, 0xd2, 0xb7, 0x4b, 0x3c, 0x10, 0x8c, 0x5d, 0x8a, 0xd7, 0x68, 0x7a, 0x61, 0x07, 0xf9, 0xa5, + 0x88, 0xda, 0xdf, 0x0c, 0x42, 0x1b, 0x11, 0xe0, 0xd1, 0x93, 0x7c, 0x63, 0x39, 0xc5, 0xed, 0x43, + 0x46, 0xdb, 0x30, 0x26, 0xd0, 0xdf, 0x7a, 0x86, 0x3e, 0x2e, 0x04, 0xbf, 0x49, 0x2a, 0xf9, 0x66 +}; + +void pgm_decrypt_kov2p() +{ + UINT16 *src = (UINT16*)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x040080) != 0x000080) x ^= 0x0001; + if ((i & 0x004008) == 0x004008) x ^= 0x0002; + if ((i & 0x080030) == 0x080010) x ^= 0x0004; + if ((i & 0x000242) != 0x000042) x ^= 0x0008; + if ((i & 0x008100) == 0x008000) x ^= 0x0010; + if ((i & 0x002004) != 0x000004) x ^= 0x0020; + if ((i & 0x011800) != 0x010000) x ^= 0x0040; + if ((i & 0x000820) == 0x000820) x ^= 0x0080; + + x ^= kov2p_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static const UINT8 theglad_tab[256] = { // IGS0005RD1021203 + 0x49, 0x47, 0x53, 0x30, 0x30, 0x30, 0x35, 0x52, 0x44, 0x31, 0x30, 0x32, 0x31, 0x32, 0x30, 0x33, + 0xc4, 0xa3, 0x46, 0x78, 0x30, 0xb3, 0x8b, 0xd5, 0x2f, 0xc4, 0x44, 0xbf, 0xdb, 0x76, 0xdb, 0xea, + 0xb4, 0xeb, 0x95, 0x4d, 0x15, 0x21, 0x99, 0xa1, 0xd7, 0x8c, 0x40, 0x1d, 0x43, 0xf3, 0x9f, 0x71, + 0x3d, 0x8c, 0x52, 0x01, 0xaf, 0x5b, 0x8b, 0x63, 0x34, 0xc8, 0x5c, 0x1b, 0x06, 0x7f, 0x41, 0x96, + 0x2a, 0x8d, 0xf1, 0x64, 0xda, 0xb8, 0x67, 0xba, 0x33, 0x1f, 0x2b, 0x28, 0x20, 0x13, 0xe6, 0x96, + 0x86, 0x34, 0x25, 0x85, 0xb0, 0xd0, 0x6d, 0x85, 0xfe, 0x78, 0x81, 0xf1, 0xca, 0xe4, 0xef, 0xf2, + 0x9b, 0x09, 0xe1, 0xb4, 0x8d, 0x79, 0x22, 0xe2, 0x00, 0xfb, 0x6f, 0x68, 0x80, 0x6a, 0x00, 0x69, + 0xf5, 0xd3, 0x57, 0x7e, 0x0c, 0xca, 0x48, 0x31, 0xe5, 0x0d, 0x4a, 0xb9, 0xfd, 0x5c, 0xfd, 0xf8, + 0x5f, 0x98, 0xfb, 0xb3, 0x07, 0x1a, 0xe3, 0x10, 0x96, 0x56, 0xa3, 0x56, 0x3d, 0xb1, 0x07, 0xe0, + 0xe3, 0x9f, 0x7f, 0x62, 0x99, 0x01, 0x35, 0x60, 0x40, 0xbe, 0x4f, 0xeb, 0x79, 0xa0, 0x82, 0x9f, + 0xcd, 0x71, 0xd8, 0xda, 0x1e, 0x56, 0xc2, 0x3e, 0x4e, 0x6b, 0x60, 0x69, 0x2d, 0x9f, 0x10, 0xf4, + 0xa9, 0xd3, 0x36, 0xaa, 0x31, 0x2e, 0x4c, 0x0a, 0x69, 0xc3, 0x2a, 0xff, 0x15, 0x67, 0x96, 0xde, + 0x3f, 0xcc, 0x0f, 0xa1, 0xac, 0xe2, 0xd6, 0x62, 0x7e, 0x6f, 0x3e, 0x1b, 0x2a, 0xed, 0x36, 0x9c, + 0x9d, 0xa4, 0x14, 0xcd, 0xaa, 0x08, 0xa4, 0x26, 0xb7, 0x55, 0x70, 0x6c, 0xa9, 0x69, 0x52, 0xae, + 0x0c, 0xe1, 0x38, 0x7f, 0x87, 0x78, 0x38, 0x75, 0x80, 0x9c, 0xd4, 0xe2, 0x0b, 0x52, 0x8f, 0xd2, + 0x19, 0x4c, 0xb0, 0x45, 0xde, 0x48, 0x55, 0xae, 0x82, 0xab, 0xbc, 0xab, 0x0c, 0x5e, 0xce, 0x07 +}; + +void pgm_decrypt_theglad() +{ + UINT16 *src = (UINT16*)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x040080) != 0x000080) x ^= 0x0001; + if ((i & 0x104008) == 0x104008) x ^= 0x0002; + if ((i & 0x080030) == 0x080010) x ^= 0x0004; + if ((i & 0x000042) != 0x000042) x ^= 0x0008; + if ((i & 0x008100) == 0x008000) x ^= 0x0010; + if ((i & 0x022004) != 0x000004) x ^= 0x0020; + if ((i & 0x011800) != 0x010000) x ^= 0x0040; + if ((i & 0x000820) == 0x000820) x ^= 0x0080; + + x ^= theglad_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static const UINT8 killbldp_tab[] = { // IGS0024RD1050908 + 0x49, 0x47, 0x53, 0x30, 0x30, 0x32, 0x34, 0x52, 0x44, 0x31, 0x30, 0x35, 0x30, 0x39, 0x30, 0x38, + 0x12, 0xa0, 0xd1, 0x9e, 0xb1, 0x8a, 0xfb, 0x1f, 0x50, 0x51, 0x4b, 0x81, 0x28, 0xda, 0x5f, 0x41, + 0x78, 0x6c, 0x7a, 0xf0, 0xcd, 0x6b, 0x69, 0x14, 0x94, 0x55, 0xb6, 0x42, 0xdf, 0xfe, 0x10, 0x79, + 0x74, 0x08, 0xfa, 0xc0, 0x1c, 0xa5, 0xb4, 0x03, 0x2a, 0x91, 0x67, 0x2b, 0x49, 0x4a, 0x94, 0x7d, + 0x8b, 0x92, 0xbe, 0x35, 0xaf, 0x28, 0x56, 0x63, 0xb3, 0xc2, 0xe8, 0x06, 0x9b, 0x4e, 0x85, 0x66, + 0x7f, 0x6b, 0x70, 0xb7, 0xdb, 0x22, 0x0c, 0xeb, 0x13, 0xe9, 0x06, 0xd7, 0x45, 0xda, 0xbe, 0x8b, + 0x54, 0x30, 0xfc, 0xeb, 0x32, 0x02, 0xd0, 0x92, 0x6d, 0x44, 0xca, 0xe8, 0xfd, 0xfb, 0x5b, 0x81, + 0x4c, 0xc0, 0x8b, 0xb9, 0x87, 0x78, 0xdd, 0x8e, 0x24, 0x52, 0x80, 0xbe, 0xb4, 0x01, 0xb7, 0x21, + 0xeb, 0x3c, 0x8a, 0x49, 0xed, 0x73, 0xae, 0x58, 0xdb, 0xd2, 0xb2, 0x21, 0x9e, 0x7c, 0x6c, 0x82, + 0xf3, 0x01, 0xa3, 0x00, 0xb7, 0x21, 0xfe, 0xa5, 0x75, 0xc4, 0x2d, 0x17, 0x2d, 0x39, 0x56, 0xf9, + 0x67, 0xae, 0xc2, 0x87, 0x79, 0xf1, 0xc8, 0x6d, 0x15, 0x66, 0xfa, 0xe8, 0x16, 0x48, 0x8f, 0x1f, + 0x8b, 0x24, 0x10, 0xc4, 0x04, 0x93, 0x47, 0xe6, 0x1d, 0x37, 0x65, 0x1a, 0x49, 0xf8, 0x72, 0xcb, + 0xe1, 0x80, 0xfa, 0xdd, 0x6d, 0xf5, 0xf6, 0x89, 0x32, 0xf6, 0xf8, 0x75, 0xfc, 0xd8, 0x9b, 0x12, + 0x2d, 0x22, 0x2a, 0x3b, 0x06, 0x46, 0x90, 0x0c, 0x35, 0xa2, 0x80, 0xff, 0xa0, 0xb7, 0xe5, 0x4d, + 0x71, 0xa9, 0x8c, 0x84, 0x62, 0xf7, 0x10, 0x65, 0x4a, 0x7b, 0x06, 0x00, 0xe8, 0xa4, 0x6a, 0x13, + 0xf0, 0xf3, 0x4a, 0x9f, 0x54, 0xb4, 0xb1, 0xcc, 0xd4, 0xff, 0xd6, 0xff, 0xc9, 0xee, 0x86, 0x39 +}; + +void pgm_decrypt_killbldp() +{ + UINT16 *src = (UINT16*)PGMUSER0; + + for (INT32 i = 0; i< nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x040480) != 0x000080) x ^= 0x0001; + if ((i & 0x104008) == 0x104008) x ^= 0x0002; + if ((i & 0x080030) == 0x080010) x ^= 0x0004; + if ((i & 0x000242) != 0x000042) x ^= 0x0008; + if ((i & 0x008100) == 0x008000) x ^= 0x0010; + if ((i & 0x002004) != 0x000004) x ^= 0x0020; + if ((i & 0x011800) != 0x010000) x ^= 0x0040; + if ((i & 0x000820) == 0x000820) x ^= 0x0080; + + x ^= killbldp_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +static const UINT8 happy6in1_tab[256] = { // IGS0008RD1031215 + 0x49, 0x47, 0x53, 0x30, 0x30, 0x30, 0x38, 0x52, 0x44, 0x31, 0x30, 0x33, 0x31, 0x32, 0x31, 0x35, + 0x14, 0xd6, 0x37, 0x5c, 0x5e, 0xc3, 0xd3, 0x62, 0x96, 0x3d, 0xfb, 0x47, 0xf0, 0xcb, 0xbf, 0xb0, + 0x60, 0xa1, 0xc2, 0x3d, 0x90, 0xd0, 0x58, 0x56, 0x22, 0xac, 0xdd, 0x39, 0x27, 0x7e, 0x58, 0x44, + 0xe0, 0x6b, 0x51, 0x80, 0xb4, 0xa4, 0xf0, 0x6f, 0x71, 0xd0, 0x57, 0x18, 0xc7, 0xb6, 0x41, 0x50, + 0x02, 0x2f, 0xdb, 0x4a, 0x08, 0x4b, 0xe3, 0x62, 0x92, 0xc3, 0xff, 0x26, 0xaf, 0x9f, 0x60, 0xa5, + 0x76, 0x28, 0x97, 0xfd, 0x0b, 0x10, 0xb7, 0x1f, 0xd5, 0xe0, 0xac, 0xe6, 0xfd, 0xa3, 0xdb, 0x58, + 0x2a, 0xd1, 0xfc, 0x3b, 0x7c, 0x7e, 0x34, 0xdc, 0xc7, 0xc4, 0x76, 0x1b, 0x11, 0x6d, 0x1b, 0xbb, + 0x4e, 0xe5, 0xc0, 0xe8, 0x5a, 0x60, 0x60, 0x0a, 0x38, 0x47, 0xb3, 0xc9, 0x89, 0xe9, 0xc6, 0x61, + 0x50, 0x5f, 0xdb, 0x28, 0xe5, 0xc0, 0x83, 0x5c, 0x37, 0x86, 0xfa, 0x32, 0x46, 0x40, 0xc3, 0x1d, + 0xdf, 0x7a, 0x85, 0x5c, 0x9a, 0xea, 0x24, 0xc7, 0x12, 0xdc, 0x23, 0xda, 0x65, 0xdf, 0x39, 0x02, + 0xeb, 0xb1, 0x32, 0x28, 0x3a, 0x69, 0x09, 0x7c, 0x5a, 0xe3, 0x44, 0x83, 0x45, 0x71, 0x8f, 0x64, + 0xa3, 0xbf, 0x9c, 0x6f, 0xc4, 0x07, 0x3a, 0xee, 0xdd, 0x77, 0xb4, 0x31, 0x87, 0xdf, 0x6d, 0xd4, + 0x75, 0x9f, 0xb9, 0x53, 0x75, 0xd0, 0xfe, 0xd1, 0xaa, 0xb2, 0x0b, 0x25, 0x08, 0x56, 0xb8, 0x27, + 0x10, 0x8c, 0xbf, 0x39, 0xce, 0x0f, 0xdb, 0x18, 0x10, 0xf0, 0x1f, 0xe5, 0xe8, 0x40, 0x98, 0x6f, + 0x64, 0x02, 0x27, 0xc3, 0x8c, 0x4f, 0x98, 0xf6, 0x9d, 0xcb, 0x07, 0x31, 0x85, 0x48, 0x75, 0xff, + 0x9f, 0xba, 0xa6, 0xd3, 0xb0, 0x5b, 0x3d, 0xdd, 0x22, 0x1f, 0x1b, 0x0e, 0x7f, 0x5a, 0xf4, 0x6a +}; + +void pgm_decrypt_happy6in1() +{ + UINT16 *src = (UINT16*)PGMUSER0; + + for (INT32 i = 0; i < nPGMExternalARMLen/2; i++) { + UINT16 x = src[i]; + + if ((i & 0x040480) != 0x000080) x ^= 0x0001; + if ((i & 0x104008) == 0x104008) x ^= 0x0002; + if ((i & 0x080030) == 0x080010) x ^= 0x0004; + if ((i & 0x000242) != 0x000042) x ^= 0x0008; + if ((i & 0x048100) == 0x048000) x ^= 0x0010; + if ((i & 0x002004) != 0x000004) x ^= 0x0020; + if ((i & 0x011800) != 0x010000) x ^= 0x0040; + if ((i & 0x000820) == 0x000820) x ^= 0x0080; + + x ^= happy6in1_tab[(i >> 1) & 0xff] << 8; + + src[i] = x; + } +} + +// ------------------------------------------------------------------------------------------------------------ +// Bootleg decryption routines + +void pgm_decode_kovqhsgs_gfx_block(UINT8 *src) +{ + INT32 i, j; + UINT8 *dec = (UINT8*)malloc(0x800000); + + for (i = 0; i < 0x800000; i++) + { + j = BITSWAP24(i, 23, 10, 9, 22, 19, 18, 20, 21, 17, 16, 15, 14, 13, 12, 11, 8, 7, 6, 5, 4, 3, 2, 1, 0); + + dec[j] = src[i]; + } + + memcpy (src, dec, 0x800000); + + if (dec) { + free (dec); + dec = NULL; + } +} + +void pgm_decode_kovqhsgs_tile_data(UINT8 *source) +{ + INT32 i, j; + UINT16 *src = (UINT16*)source; + UINT16 *dst = (UINT16*)malloc(0x800000); + + for (i = 0; i < 0x800000 / 2; i++) + { + j = BITSWAP24(i, 23, 22, 9, 8, 21, 18, 0, 1, 2, 3, 16, 15, 14, 13, 12, 11, 10, 19, 20, 17, 7, 6, 5, 4); + + dst[j] = BITSWAP16(src[i], 1, 14, 8, 7, 0, 15, 6, 9, 13, 2, 5, 10, 12, 3, 4, 11); + } + + memcpy (src, dst, 0x800000); + + if (dst) { + free (dst); + dst = NULL; + } +} + +static void pgm_decode_kovqhsgs_samples() +{ + INT32 i; + for (i = 0; i < 0x400000; i+=2) { + ICSSNDROM[i + 0x400001] = ICSSNDROM[i + 0xc00001]; + } +} + +static void pgm_decode_kovqhsgs_program() +{ + INT32 i, j; + UINT16 *src = (UINT16*)PGM68KROM; + UINT16 *dst = (UINT16*)malloc(0x400000); + + for (i = 0; i < 0x400000 / 2; i++) + { + j = BITSWAP24(i, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 5, 4, 3, 2, 1, 0); + + dst[j] = BITSWAP16(src[i], 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0); + } + + memcpy (src, dst, 0x400000); + + if (dst) { + free (dst); + dst = NULL; + } +} + +void pgm_decrypt_kovqhsgs() +{ + pgm_decode_kovqhsgs_program(); + + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x000000); + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x800000); + + // sprite colors are decoded in pgm_run + + pgm_decode_kovqhsgs_samples(); +} + +static void pgm_decode_kovlsqh2_program() +{ + INT32 i, j; + UINT16 *src = (UINT16*)PGM68KROM; + UINT16 *dst = (UINT16*)malloc(0x400000); + + for (i = 0; i < 0x400000 / 2; i++) + { + j = BITSWAP24(i, 23, 22, 21, 20, 19, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 18, 17, 7); + + dst[j] = src[i]; + } + + memcpy (src, dst, 0x400000); + + if (dst) { + free (dst); + dst = NULL; + } +} + +void pgm_decrypt_kovlsqh2() +{ + pgm_decode_kovlsqh2_program(); + + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x000000); + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x800000); + + // sprite colors are decoded in pgm_run.cpp + + pgm_decode_kovqhsgs_samples(); +} + +static void pgm_decode_kovassg_program() +{ + INT32 i, j; + UINT16 *src = (UINT16 *)PGM68KROM; + UINT16 *dst = (UINT16 *)malloc(0x400000); + + for (i = 0; i < 0x400000/2; i++) + { + j = (i & ~0xffff) | (BITSWAP16(i, 15, 14, 13, 12, 11, 10, 7, 3, 1, 9, 4, 8, 6, 0, 2, 5) ^ 0x019c); + + dst[i] = BITSWAP16(src[j], 13, 9, 10, 11, 2, 0, 12 ,5, 4, 1, 14, 8, 15, 6, 3, 7) ^ 0x9d05; + } + + memcpy (src, dst, 0x400000); + + if (src) { + free (src); + src = NULL; + } +} + +void pgm_decrypt_kovassg() +{ + pgm_decode_kovassg_program(); + + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x000000); + pgm_decode_kovqhsgs_gfx_block(PGMSPRMaskROM + 0x800000); + + // sprite colors are decoded in pgm_run.cpp + + pgm_decode_kovqhsgs_samples(); +} diff --git a/src/burn/drivers/pgm/pgm_draw.cpp b/src/burn/drivers/pgm/pgm_draw.cpp new file mode 100644 index 00000000..271ed732 --- /dev/null +++ b/src/burn/drivers/pgm/pgm_draw.cpp @@ -0,0 +1,854 @@ +#include "pgm.h" + +static INT32 nTileMask = 0; +static UINT8 sprmsktab[0x100]; +static UINT8 *SpritePrio; // sprite priorities +static UINT16 *pTempScreen; // sprites +static UINT16 *pTempDraw; // pre-zoomed sprites +static UINT8 *tiletrans; // tile transparency table +static UINT8 *texttrans; // text transparency table + +#define draw_pixel_nomask(n) \ + dest[xoff + n] = adata[aoffset] | palt; \ + pdest[xoff + n] = prio; \ + aoffset++ \ + +#define draw_pixel(n, mskno) \ + if (msk & mskno) { \ + draw_pixel_nomask(n); \ + } \ + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x7C00) >> 7; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +static void pgm_prepare_sprite(INT32 wide, INT32 high,INT32 palt, INT32 boffset) +{ + UINT8 * bdata = PGMSPRMaskROM; + UINT8 * adata = PGMSPRColROM; + UINT16* dest = pTempDraw; + INT32 bdatasize = nPGMSPRMaskMaskLen; + INT32 adatasize = nPGMSPRColMaskLen; + + wide *= 16; + palt *= 32; + + UINT32 aoffset = (bdata[(boffset+3) & bdatasize] << 24) | (bdata[(boffset+2) & bdatasize] << 16) | (bdata[(boffset+1) & bdatasize] << 8) | (bdata[(boffset) & bdatasize]); + aoffset = (aoffset >> 2) * 3; + + boffset += 4; + + for (INT32 ycnt = 0 ; ycnt < high; ycnt++) { + dest = pTempDraw + (ycnt * wide); + + for (INT32 xcnt = 0 ; xcnt < wide; xcnt+=16) { + UINT16 msk = (bdata[(boffset+1) & bdatasize] << 8) | bdata[boffset & bdatasize]; + + if (msk == 0xffff) { + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + *dest++ = 0x8000; + } + else if (msk == 0) + { + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + *dest++ = adata[aoffset++ & adatasize] | palt; + } + else + { + for (INT32 x = 0; x < 16; x++) + { + if (msk & 1) + { + dest[x] = 0x8000; + } + else + { + dest[x] = adata[aoffset++ & adatasize] | palt; + } + + msk >>= 1; + } + + dest += 16; + } + + boffset+=2; + } + } +} + +static inline void draw_sprite_line(INT32 wide, UINT16* dest, UINT8 *pdest, INT32 xzoom, INT32 xgrow, INT32 yoffset, INT32 flip, INT32 xpos, INT32 prio) +{ + INT32 xzoombit; + INT32 xoffset; + INT32 xcnt = 0, xcntdraw = 0; + INT32 xdrawpos = 0; + + wide *= 16; + flip &= 1; + + while (xcnt < wide) + { + if (flip) xoffset = wide - xcnt - 1; + else xoffset = xcnt; + + UINT32 srcdat = pTempDraw[yoffset + xoffset]; + xzoombit = (xzoom >> (xcnt & 0x1f)) & 1; + + if (xzoombit == 1 && xgrow == 1) + { + xdrawpos = xpos + xcntdraw; + + if (!(srcdat & 0x8000)) + { + if ((xdrawpos >= 0) && (xdrawpos < nScreenWidth)) { + dest[xdrawpos] = srcdat; + pdest[xdrawpos] = prio; + } + + xdrawpos = xpos + xcntdraw + 1; + + if ((xdrawpos >= 0) && (xdrawpos < nScreenWidth)) { + dest[xdrawpos] = srcdat; + pdest[xdrawpos] = prio; + } + } + + xcntdraw+=2; + } + else if (xzoombit == 1 && xgrow == 0) + { + /* skip this column */ + } + else //normal column + { + xdrawpos = xpos + xcntdraw; + + if (!(srcdat & 0x8000)) + { + if ((xdrawpos >= 0) && (xdrawpos < nScreenWidth)) { + dest[xdrawpos] = srcdat; + pdest[xdrawpos] = prio; + } + } + + xcntdraw++; + } + + xcnt++; + + if (xdrawpos == nScreenWidth) break; + } +} + +static void pgm_draw_sprite_nozoom(INT32 wide, INT32 high, INT32 palt, INT32 boffset, INT32 xpos, INT32 ypos, INT32 flipx, INT32 flipy, INT32 prio) +{ + UINT16 *dest = pTempScreen; + UINT8 *pdest = SpritePrio; + UINT8 * bdata = PGMSPRMaskROM; + UINT8 * adata = PGMSPRColROM; + INT32 bdatasize = nPGMSPRMaskMaskLen; + INT32 adatasize = nPGMSPRColMaskLen; + INT32 yoff, xoff; + + UINT16 msk; + + UINT32 aoffset = (bdata[(boffset+3) & bdatasize] << 24) | (bdata[(boffset+2) & bdatasize] << 16) | (bdata[(boffset+1) & bdatasize] << 8) | (bdata[boffset & bdatasize]); + aoffset = (aoffset >> 2) * 3; + aoffset &= adatasize; + + boffset += 4; + wide <<= 4; + + palt <<= 5; + + for (INT32 ycnt = 0; ycnt < high; ycnt++) { + if (flipy) { + yoff = ypos + ((high-1) - ycnt); + if (yoff < 0) break; + if (yoff < nScreenHeight) { + dest = pTempScreen + (yoff * nScreenWidth); + pdest = SpritePrio + (yoff * nScreenWidth); + } + } else { + yoff = ypos + ycnt; + if (yoff >= nScreenHeight) break; + if (yoff >= 0) { + dest = pTempScreen + (yoff * nScreenWidth); + pdest = SpritePrio + (yoff * nScreenWidth); + } + } + + if (yoff >= 0 && yoff < nScreenHeight && xpos >= 0 && (xpos + wide) < nScreenWidth) + { + for (INT32 xcnt = 0; xcnt < wide; xcnt+=8) + { + msk = bdata[boffset & bdatasize] ^ 0xff; + boffset++; + aoffset &= adatasize; // not 100% safe, but faster... + + if (msk == 0) { // transparent + aoffset += sprmsktab[msk]; + continue; + } + + if (flipx) { + xoff = xpos + (wide - xcnt); + if (msk == 0xff) { // opaque + draw_pixel_nomask( 0); + draw_pixel_nomask(-1); + draw_pixel_nomask(-2); + draw_pixel_nomask(-3); + draw_pixel_nomask(-4); + draw_pixel_nomask(-5); + draw_pixel_nomask(-6); + draw_pixel_nomask(-7); + } else { + draw_pixel( 0, 0x01); + draw_pixel(-1, 0x02); + draw_pixel(-2, 0x04); + draw_pixel(-3, 0x08); + draw_pixel(-4, 0x10); + draw_pixel(-5, 0x20); + draw_pixel(-6, 0x40); + draw_pixel(-7, 0x80); + } + } else { + xoff = xpos + xcnt; + if (msk == 0xff) { // opaque + draw_pixel_nomask( 0); + draw_pixel_nomask( 1); + draw_pixel_nomask( 2); + draw_pixel_nomask( 3); + draw_pixel_nomask( 4); + draw_pixel_nomask( 5); + draw_pixel_nomask( 6); + draw_pixel_nomask( 7); + } else { + draw_pixel( 0, 0x01); + draw_pixel( 1, 0x02); + draw_pixel( 2, 0x04); + draw_pixel( 3, 0x08); + draw_pixel( 4, 0x10); + draw_pixel( 5, 0x20); + draw_pixel( 6, 0x40); + draw_pixel( 7, 0x80); + } + } + } + } else { + for (INT32 xcnt = 0; xcnt < wide; xcnt+=8) + { + msk = bdata[boffset & bdatasize] ^ 0xff; + boffset++; + aoffset &= adatasize; + + if (yoff < 0 || yoff >= nScreenHeight || msk == 0) { + aoffset += sprmsktab[msk]; + + continue; + } + + if (flipx) { + xoff = xpos + (wide - xcnt); + + if (xoff < -7 || xoff >= nScreenWidth+8) { + aoffset += sprmsktab[msk]; + continue; + } + + for (INT32 x = 0; x < 8; x++, xoff--) + { + if (msk & 0x0001) + { + if (xoff >= 0 && xoff < nScreenWidth) { + dest[xoff] = adata[aoffset] | palt; + pdest[xoff] = prio; + } + + aoffset++; + } + + msk >>= 1; + if (!msk) break; + } + } else { + xoff = xpos + xcnt; + + if (xoff < -7 || xoff >= nScreenWidth) { + aoffset += sprmsktab[msk]; + continue; + } + + for (INT32 x = 0; x < 8; x++, xoff++) + { + if (msk & 0x0001) + { + if (xoff >= 0 && xoff < nScreenWidth) { + dest[xoff] = adata[aoffset] | palt; + pdest[xoff] = prio; + } + + aoffset++; + } + + msk >>= 1; + if (!msk) break; + } + } + } + } + } +} + +static void draw_sprite_new_zoomed(INT32 wide, INT32 high, INT32 xpos, INT32 ypos, INT32 palt, INT32 boffset, INT32 flip, UINT32 xzoom, INT32 xgrow, UINT32 yzoom, INT32 ygrow, INT32 prio ) +{ + if (!wide) return; + + if (yzoom == 0 && xzoom == 0) { + pgm_draw_sprite_nozoom(wide, high, palt, boffset, xpos, ypos, flip & 1, flip & 2, prio); + return; + } + + INT32 ycnt; + INT32 ydrawpos; + UINT16 *dest; + UINT8 *pdest; + INT32 yoffset; + INT32 ycntdraw; + INT32 yzoombit; + + pgm_prepare_sprite(wide, high, palt, boffset); + + ycnt = 0; + ycntdraw = 0; + while (ycnt < high) + { + yzoombit = (yzoom >> (ycnt&0x1f))&1; + + if (yzoombit == 1 && ygrow == 1) // double this line + { + ydrawpos = ypos + ycntdraw; + + if (!(flip&0x02)) yoffset = (ycnt*(wide*16)); + else yoffset = ( (high-ycnt-1)*(wide*16)); + if ((ydrawpos >= 0) && (ydrawpos < 224)) + { + dest = pTempScreen + ydrawpos * nScreenWidth; + pdest = SpritePrio + ydrawpos * nScreenWidth; + draw_sprite_line(wide, dest, pdest, xzoom, xgrow, yoffset, flip, xpos, prio); + } + ycntdraw++; + + ydrawpos = ypos + ycntdraw; + if (!(flip&0x02)) yoffset = (ycnt*(wide*16)); + else yoffset = ( (high-ycnt-1)*(wide*16)); + if ((ydrawpos >= 0) && (ydrawpos < 224)) + { + dest = pTempScreen + ydrawpos * nScreenWidth; + pdest = SpritePrio + ydrawpos * nScreenWidth; + draw_sprite_line(wide, dest, pdest, xzoom, xgrow, yoffset, flip, xpos, prio); + } + ycntdraw++; + + if (ydrawpos == 224) ycnt = high; + } + else if (yzoombit ==1 && ygrow == 0) + { + /* skip this line */ + /* we should process anyway if we don't do the pre-decode.. */ + } + else /* normal line */ + { + ydrawpos = ypos + ycntdraw; + + if (!(flip&0x02)) yoffset = (ycnt*(wide*16)); + else yoffset = ( (high-ycnt-1)*(wide*16)); + if ((ydrawpos >= 0) && (ydrawpos < 224)) + { + dest = pTempScreen + ydrawpos * nScreenWidth; + pdest = SpritePrio + ydrawpos * nScreenWidth; + draw_sprite_line(wide, dest, pdest, xzoom, xgrow, yoffset, flip, xpos, prio); + } + ycntdraw++; + + if (ydrawpos == 224) ycnt = high; + } + + ycnt++; + } +} + +static void pgm_drawsprites() +{ + UINT16 *source = PGMSprBuf; + UINT16 *finish = PGMSprBuf + 0xa00/2; + UINT16 *zoomtable = &PGMVidReg[0x1000/2]; + + while (finish > source) + { + if (source[4] == 0) break; // right? + + INT32 xpos = source[0] & 0x07ff; + INT32 ypos = source[1] & 0x03ff; + INT32 xzom = (source[0] & 0x7800) >> 11; + INT32 xgrow= (source[0] & 0x8000) >> 15; + INT32 yzom = (source[1] & 0x7800) >> 11; + INT32 ygrow= (source[1] & 0x8000) >> 15; + INT32 palt = (source[2] & 0x1f00) >> 8; + INT32 flip = (source[2] & 0x6000) >> 13; + INT32 boff =((source[2] & 0x007f) << 16) | (source[3] & 0xffff); + INT32 wide = (source[4] & 0x7e00) >> 9; + INT32 prio = (source[2] & 0x0080) >> 7; + INT32 high = source[4] & 0x01ff; + + if (xgrow) xzom = 0x10-xzom; + if (ygrow) yzom = 0x10-yzom; + + UINT32 xzoom = (zoomtable[xzom*2]<<16)|zoomtable[xzom*2+1]; + UINT32 yzoom = (zoomtable[yzom*2]<<16)|zoomtable[yzom*2+1]; + + if (xpos > 0x3ff) xpos -=0x800; + if (ypos > 0x1ff) ypos -=0x400; + + draw_sprite_new_zoomed(wide, high, xpos, ypos, palt, boff * 2, flip, xzoom, xgrow, yzoom, ygrow, prio); + + source += 5; + } +} + +static void copy_sprite_priority(INT32 prio) +{ + UINT16 *dest = pTransDraw; + UINT16 *src = pTempScreen; + UINT8 *pri = SpritePrio; + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) + { + if (pri[i] == prio) { + dest[i] = src[i]; + } + } +} + +static void draw_text() +{ + UINT16 *vram = (UINT16*)PGMTxtRAM; + + INT32 scrollx = ((INT16)PGMVidReg[0x6000 / 2]) & 0x1ff; + INT32 scrolly = ((INT16)PGMVidReg[0x5000 / 2]) & 0x0ff; + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 code = vram[offs * 2]; + if (texttrans[code] == 0) continue; // transparent + + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + sx -= scrollx; + if (sx < -7) sx += 512; + sy -= scrolly; + if (sy < -7) sy += 256; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 attr = vram[offs * 2 + 1]; + INT32 color = ((attr & 0x3e) >> 1) | 0x80; + INT32 flipx = (attr & 0x40); + INT32 flipy = (attr & 0x80); + + if (sx < 0 || sy < 0 || sx >= nScreenWidth - 8 || sy >= nScreenHeight - 8) + { + if (texttrans[code] & 2) { // opaque + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } else { + Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } + } else { + if (flipx) { + Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } else { + Render8x8Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } else { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } + } + } + } + else + { + if (texttrans[code] & 2) { // opaque + if (flipy) { + if (flipx) { + Render8x8Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } else { + Render8x8Tile_FlipY(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } + } else { + if (flipx) { + Render8x8Tile_FlipX(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } else { + Render8x8Tile(pTransDraw, code, sx, sy, color, 4, 0, PGMTileROM); + } + } + } else { + if (flipy) { + if (flipx) { + Render8x8Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } else { + Render8x8Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } + } else { + if (flipx) { + Render8x8Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } else { + Render8x8Tile_Mask(pTransDraw, code, sx, sy, color, 4, 15, 0, PGMTileROM); + } + } + } + } + } +} + +static void draw_background() +{ + UINT16 *vram = (UINT16*)PGMBgRAM; + UINT16 *dst = pTransDraw; + + UINT16 *rowscroll = PGMRowRAM; + INT32 yscroll = (INT16)PGMVidReg[0x2000 / 2]; + INT32 xscroll = (INT16)PGMVidReg[0x3000 / 2]; + + // check to see if we need to do line scroll + INT32 t = 0; + { + UINT16 *rs = rowscroll; + for (INT32 i = 0; i < 224; i++) { + if (rs[0] != rs[i]) { + t = 1; + break; + } + } + } + + // no line scroll (fast) + if (t == 0) + { + yscroll &= 0x1ff; + xscroll &= 0x7ff; + + for (INT32 offs = 0; offs < 64 * 16; offs++) + { + INT32 sx = (offs & 0x3f) << 5; + INT32 sy = (offs >> 6) << 5; + + sx -= xscroll; + if (sx < -31) sx += 2048; + sy -= yscroll; + if (sy < -31) sy += 512; + + if (sx >= nScreenWidth || sy >= nScreenHeight) continue; + + INT32 code = vram[offs * 2]; + if (code >= nTileMask) continue; + if (tiletrans[code] == 0) continue; // transparent + INT32 color = ((vram[offs*2+1] & 0x3e) >> 1) | 0x20; + INT32 flipy = vram[offs*2+1] & 0x80; + INT32 flipx = vram[offs*2+1] & 0x40; + + if (sx < 0 || sy < 0 || sx >= nScreenWidth - 32 || sy >= nScreenHeight - 32) + { + if (tiletrans[code] & 2) { // opaque + if (flipy) { + if (flipx) { + Render32x32Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } else { + Render32x32Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } + } else { + if (flipx) { + Render32x32Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } else { + Render32x32Tile_Clip(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } + } + } else { + if (flipy) { + if (flipx) { + Render32x32Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } else { + Render32x32Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } + } else { + if (flipx) { + Render32x32Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } else { + Render32x32Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } + } + } + } + else + { + if (tiletrans[code] & 2) { // opaque + if (flipy) { + if (flipx) { + Render32x32Tile_FlipXY(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } else { + Render32x32Tile_FlipY(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } + } else { + if (flipx) { + Render32x32Tile_FlipX(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } else { + Render32x32Tile(pTransDraw, code, sx, sy, color, 5, 0, PGMTileROMExp); + } + } + } else { + if (flipy) { + if (flipx) { + Render32x32Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } else { + Render32x32Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } + } else { + if (flipx) { + Render32x32Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } else { + Render32x32Tile_Mask(pTransDraw, code, sx, sy, color, 5, 0x1f, 0, PGMTileROMExp); + } + } + } + } + } + + return; + } + + // do line scroll (slow) + for (INT32 y = 0; y < 224; y++, dst += nScreenWidth) + { + INT32 scrollx = (xscroll + rowscroll[y]) & 0x7ff; + INT32 scrolly = (yscroll + y) & 0x7ff; + + for (INT32 x = 0; x < 480; x+=32) + { + INT32 sx = x - (scrollx & 0x1f); + if (sx >= nScreenWidth) break; + + INT32 offs = ((scrolly & 0x1e0) << 2) | (((scrollx + x) & 0x7e0) >> 4); + + INT32 code = vram[offs]; + if (code >= nTileMask) continue; + if (tiletrans[code] == 0) continue; + + INT32 attr = vram[offs + 1]; + INT32 color = ((attr & 0x3e) << 4) | 0x400; + INT32 flipx = ((attr & 0x40) >> 6) * 0x1f; + INT32 flipy = ((attr & 0x80) >> 7) * 0x1f; + + UINT8 *src = PGMTileROMExp + (code * 1024) + (((scrolly ^ flipy) & 0x1f) << 5); + + if (sx >= 0 && sx <= 415) { + for (INT32 xx = 0; xx < 32; xx++, sx++) { + INT32 pxl = src[xx^flipx]; + + if (pxl != 0x1f) { + dst[sx] = pxl | color; + } + } + } else { + for (INT32 xx = 0; xx < 32; xx++, sx++) { + if (sx < 0) continue; + if (sx >= nScreenWidth) break; + + INT32 pxl = src[xx^flipx]; + + if (pxl != 0x1f) { + dst[sx] = pxl | color; + } + } + } + } + } +} + +INT32 pgmDraw() +{ + if (nPgmPalRecalc) { + for (INT32 i = 0; i < 0x1200 / 2; i++) { + RamCurPal[i] = CalcCol(PGMPalRAM[i]); + } + nPgmPalRecalc = 0; + } + + { + // black / magenta + RamCurPal[0x1200/2] = (nBurnLayer & 1) ? 0 : BurnHighCol(0xff, 0, 0xff, 0); + } + + // Fill in background color (0x1200/2) + // also, clear buffers + { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + pTransDraw[i] = 0x900; + pTempScreen[i] = 0; + SpritePrio[i] = 0xff; + } + } + + pgm_drawsprites(); + if (nSpriteEnable & 1) copy_sprite_priority(1); + if (nBurnLayer & 1) draw_background(); + if (nSpriteEnable & 2) copy_sprite_priority(0); + if (nBurnLayer & 2) draw_text(); + + BurnTransferCopy(RamCurPal); + + return 0; +} + +void pgmInitDraw() // preprocess some things... +{ + GenericTilesInit(); + + pTempDraw = (UINT16*)malloc(0x400 * 0x200 * 2); + SpritePrio = (UINT8*)malloc(nScreenWidth * nScreenHeight); + pTempScreen = (UINT16*)malloc(nScreenWidth * nScreenHeight * sizeof(INT16)); + + // Find transparent tiles so we can skip them + { + nTileMask = ((nPGMTileROMLen / 5) * 8) / 0x400; // also used to set max. tile + + // background tiles + tiletrans = (UINT8*)malloc(nTileMask); + memset (tiletrans, 0, nTileMask); + + for (INT32 i = 0; i < nTileMask << 10; i += 0x400) + { + INT32 k = 0x1f; + for (INT32 j = 0; j < 0x400; j++) + { + if (PGMTileROMExp[i+j] != 0x1f) { + tiletrans[i/0x400] = 1; + } + k &= (PGMTileROMExp[i+j] ^ 0x1f); + } + if (k) tiletrans[i/0x400] |= 2; + } + + // character tiles + texttrans = (UINT8*)malloc(0x10000); + memset (texttrans, 0, 0x10000); + + for (INT32 i = 0; i < 0x400000; i += 0x40) + { + INT32 k = 0xf; + for (INT32 j = 0; j < 0x40; j++) + { + if (PGMTileROM[i+j] != 0xf) { + texttrans[i/0x40] = 1; + } + k &= (PGMTileROM[i+j] ^ 0xf); + } + if (k) texttrans[i/0x40] |= 2; + } + } + + // set up table to count bits in sprite mask data + // gives a good speedup in sprite drawing. ^^ + { + memset (sprmsktab, 0, 0x100); + for (INT32 i = 0; i < 0x100; i++) { + for (INT32 j = 0; j < 8; j++) { + if (i & (1 << j)) { + sprmsktab[i]++; + } + } + } + } +} + +void pgmExitDraw() +{ + nTileMask = 0; + + if (pTempDraw) { + free (pTempDraw); + pTempDraw = NULL; + } + + if (tiletrans) { + free (tiletrans); + tiletrans = NULL; + } + + if (texttrans) { + free (texttrans); + texttrans = NULL; + } + + if (pTempScreen) { + free (pTempScreen); + pTempScreen = NULL; + } + + if (SpritePrio) { + free (SpritePrio); + SpritePrio = NULL; + } + + GenericTilesExit(); +} diff --git a/src/burn/drivers/pgm/pgm_prot.cpp b/src/burn/drivers/pgm/pgm_prot.cpp new file mode 100644 index 00000000..2779aea7 --- /dev/null +++ b/src/burn/drivers/pgm/pgm_prot.cpp @@ -0,0 +1,2546 @@ + +#include "pgm.h" +#include "bitswap.h" + +static UINT8 *USER1; +static UINT16 *sharedprotram; + +static INT32 ptr; + +INT32 pstarsScan(INT32 nAction,INT32 */*pnMin*/); +INT32 killbldScan(INT32 nAction,INT32 */*pnMin*/); +INT32 kov_asic27Scan(INT32 nAction,INT32 */*pnMin*/); +INT32 asic3Scan(INT32 nAction,INT32 */*pnMin*/); +INT32 asic27aScan(INT32 nAction,INT32 *); +INT32 oldsScan(INT32 nAction, INT32 */*pnMin*/); +INT32 oldsplus_asic27aScan(INT32 nAction, INT32 */*pnMin*/); +INT32 kovsh_asic27aScan(INT32 nAction,INT32 *); +INT32 svg_asic27aScan(INT32 nAction,INT32 *); +INT32 ddp3Scan(INT32 nAction, INT32 */*pnMin*/); + +//----------------------------------------------------------------------------------------------------- +// ASIC3 - Oriental Legends + +static UINT8 asic3_reg, asic3_latch[3], asic3_x, asic3_y, asic3_z, asic3_h1, asic3_h2; +static UINT16 asic3_hold; + +static UINT32 bt(UINT32 v, INT32 bit) +{ + return (v & (1<= 0x80 && asic3_reg <= 0x87) { + asic3_y = asic3_reg & 7; + asic3_z = data; + asic3_compute_hold(); + } + } +} + +static void pgm_asic3_reg_w(UINT16 data) +{ + asic3_reg = data & 0xff; +} + +static void __fastcall asic3_write_word(UINT32 address, UINT16 data) +{ + if (address == 0xc04000) { + pgm_asic3_reg_w(data); + return; + } + + if (address == 0xc0400e) { + pgm_asic3_w(data); + return; + } +} + +static UINT16 __fastcall asic3_read_word(UINT32 address) +{ + if (address == 0xc0400e) { + return pgm_asic3_r(); + } + + return 0; +} + +static void reset_asic3() +{ + asic3_latch[0] = asic3_latch[1] = asic3_latch[2] = 0; + asic3_hold = asic3_reg = asic3_x = asic3_y, asic3_z = asic3_h1 = asic3_h2 = 0; +} + +void install_protection_asic3_orlegend() +{ + pPgmScanCallback = asic3Scan; + pPgmResetCallback = reset_asic3; + + SekOpen(0); + SekMapHandler(4, 0xc04000, 0xc0400f, SM_READ | SM_WRITE); + + SekSetReadWordHandler(4, asic3_read_word); + SekSetWriteWordHandler(4, asic3_write_word); + SekClose(); +} + + +//----------------------------------------------------------------------------------------------------- +// ASIC27 - Knights of Valour + +//Not sure if BATABLE is complete +static const UINT32 BATABLE[0x40]= { + 0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e, //0x00 + 0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d, //0x08 + 0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87, //0x10 + 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90, //0x18 + 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c, + 0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1 }; + +static const UINT32 B0TABLE[16]={2,0,1,4,3}; //maps char portraits to tables + +static UINT16 ASIC27KEY; +static UINT16 ASIC27REGS[10]; +static UINT16 ASICPARAMS[256]; +static UINT16 ASIC27RCNT=0; +static UINT32 E0REGS[16]; + +static UINT16 pgm_kov_asic27_r(UINT16 offset) +{ + UINT32 val=(ASIC27REGS[1]<<16)|(ASIC27REGS[0]); + + switch(ASIC27REGS[1]&0xff) { + case 0x67: + val=0x880000; + break; + + case 0x8e: + val=0x880000; + break; + + case 0x99: + val=0x880000; + break; + case 0x9d: // spr palette + val=0xa00000+((ASIC27REGS[0]&0x1f)<<6); + break; + case 0xb0: + val=B0TABLE[ASIC27REGS[0]&0xf]; + break; + case 0xb4: + { + INT32 v2=ASIC27REGS[0]&0x0f; + INT32 v1=(ASIC27REGS[0]&0x0f00)>>8; + if(ASIC27REGS[0]==0x102) + E0REGS[1]=E0REGS[0]; + else + E0REGS[v1]=E0REGS[v2]; + val=0x880000; + } + break; + case 0xba: + val=BATABLE[ASIC27REGS[0]&0x3f]; + if(ASIC27REGS[0]>0x2f) { + + } + break; + case 0xc0: + val=0x880000; + break; + case 0xc3: //TXT tile position Uses C0 to select column + val=0x904000+(ASICPARAMS[0xc0]+ASICPARAMS[0xc3]*64)*4; + break; + case 0xcb: + val=0x880000; + break; + case 0xcc: //BG + { + INT32 y=ASICPARAMS[0xcc]; + if(y&0x400) //y is signed (probably x too and it also applies to TXT, but I've never seen it used) + y=-(0x400-(y&0x3ff)); + val=0x900000+(((ASICPARAMS[0xcb]+(y)*64)*4)/*&0x1fff*/); + } + break; + case 0xd0: //txt palette + val=0xa01000+(ASIC27REGS[0]<<5); + break; + case 0xd6: //???? check it + { + INT32 v2=ASIC27REGS[0]&0xf; + E0REGS[0]=E0REGS[v2]; + //E0REGS[v2]=0; + val=0x880000; + } + break; + case 0xdc: //bg palette + val=0xa00800+(ASIC27REGS[0]<<6); + break; + case 0xe0: //spr palette + val=0xa00000+((ASIC27REGS[0]&0x1f)<<6); + break; + case 0xe5: + val=0x880000; + break; + case 0xe7: + val=0x880000; + break; + case 0xf0: + val=0x00C000; + break; + case 0xab: + case 0xf8: + val=E0REGS[ASIC27REGS[0]&0xf]&0xffffff; + break; + case 0xfc: //Adjust damage level to char experience level + val=(ASICPARAMS[0xfc]*ASICPARAMS[0xfe])>>6; + break; + case 0xfe: //todo + val=0x880000; + break; + default: + val=0x880000; + } + + if(offset==0) { + UINT16 d=val&0xffff; + UINT16 realkey; + realkey=ASIC27KEY>>8; + realkey|=ASIC27KEY; + d^=realkey; + return d; + } + else if(offset==2) { + UINT16 d=val>>16; + UINT16 realkey; + realkey=ASIC27KEY>>8; + realkey|=ASIC27KEY; + d^=realkey; + ASIC27RCNT++; + if(!(ASIC27RCNT&0x3)) { + ASIC27KEY+=0x100; + ASIC27KEY&=0xFF00; + } + return d; + } + return 0xff; +} + +static void pgm_kov_asic27_w(UINT16 offset, UINT16 data) +{ + if(offset==0) { + UINT16 realkey; + realkey=ASIC27KEY>>8; + realkey|=ASIC27KEY; + data^=realkey; + ASIC27REGS[0]=data; + return; + } + + if(offset==2) { + + ASIC27KEY = data & 0xff00; + + UINT16 realkey = (ASIC27KEY >> 8) | ASIC27KEY; + + ASIC27REGS[1] = data ^ realkey; + + ASICPARAMS[ASIC27REGS[1]&0xff]=ASIC27REGS[0]; + if (ASIC27REGS[1]==0xE7) { + UINT32 E0R=(ASICPARAMS[0xE7]>>12)&0xf; + E0REGS[E0R]&=0xffff; + E0REGS[E0R]|=ASIC27REGS[0]<<16; + } + if (ASIC27REGS[1]==0xE5) { + UINT32 E0R=(ASICPARAMS[0xE7]>>12)&0xf; + E0REGS[E0R]&=0xff0000; + E0REGS[E0R]|=ASIC27REGS[0]; + } + ASIC27RCNT=0; + } +} + +static void __fastcall kov_asic27_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffffc) == 0x500000) { + pgm_kov_asic27_w(address & 3, data); + } +} + +static UINT16 __fastcall kov_asic27_read_word(UINT32 address) +{ + if ((address & 0xfffffc) == 0x500000) { + return pgm_kov_asic27_r(address & 3); + } + + return 0; +} + +static void reset_kov_asic27() +{ + ASIC27KEY=0; + ASIC27RCNT=0; + memset(ASIC27REGS, 0, 10); + memset(ASICPARAMS, 0, 256); + memset(E0REGS, 0, 16); + + memset (PGMUSER0, 0, 0x400); + + *((UINT16*)(PGMUSER0 + 0x00008)) = PgmInput[7]; // region +} + +void install_protection_asic27_kov() +{ + pPgmScanCallback = kov_asic27Scan; + pPgmResetCallback = reset_kov_asic27; + + SekOpen(0); + SekMapMemory(PGMUSER0, 0x4f0000, 0x4f003f | 0x3ff, SM_READ); + + SekMapHandler(4, 0x500000, 0x500003, SM_READ | SM_WRITE); + + SekSetReadWordHandler(4, kov_asic27_read_word); + SekSetWriteWordHandler(4, kov_asic27_write_word); + SekClose(); +} + + +//----------------------------------------------------------------------------------------------------- +// Dragon World 2 + +#define DW2BITSWAP(s,d,bs,bd) d=((d&(~(1<>bs)&1)<>8)|(d<<8); + DW2BITSWAP(d,d2,7 ,0); + DW2BITSWAP(d,d2,4 ,1); + DW2BITSWAP(d,d2,5 ,2); + DW2BITSWAP(d,d2,2 ,3); + DW2BITSWAP(d,d2,15,4); + DW2BITSWAP(d,d2,1 ,5); + DW2BITSWAP(d,d2,10,6); + DW2BITSWAP(d,d2,13,7); + + // ... missing bitswaps here (8-15) there is not enough data to know them + // the code only checks the lowest 8 bits + + return d2; +} + +void install_protection_asic25_asic12_dw2() +{ + SekOpen(0); + SekMapHandler(4, 0xd80000, 0xd80003, SM_READ); + SekSetReadWordHandler(4, dw2_read_word); + SekClose(); +} + + +//----------------------------------------------------------------------------------------------------- +// Killing Blade + +static UINT16 kb_cmd; +static UINT16 kb_reg; +static UINT16 kb_ptr; +static UINT32 kb_regs[0x100]; //? + +static void IGS022_do_dma(UINT16 src, UINT16 dst, UINT16 size, UINT16 mode) +{ + UINT16 param = mode >> 8; + UINT16 *PROTROM = (UINT16*)USER1; + + mode &= 0x0f; + + switch (mode) + { + case 0: + case 1: + case 2: + case 3: + { + for (INT32 x = 0; x < size; x++) + { + UINT16 dat2 = PROTROM[src + x]; + + UINT8 extraoffset = param & 0xfe; + UINT8* dectable = (UINT8 *)PROTROM; + UINT16 extraxor = ((dectable[((x*2)+0+extraoffset)&0xff]) << 8) | (dectable[((x*2)+1+extraoffset)&0xff] << 0); + + dat2 = ((dat2 & 0x00ff)<<8) | ((dat2 & 0xff00)>>8); + + // mode==0 plain + if (mode==3) dat2 ^= extraxor; + if (mode==2) dat2 += extraxor; + if (mode==1) dat2 -= extraxor; + + sharedprotram[dst + x] = dat2; + } + + if ((mode==3) && (param==0x54) && (src*2==0x2120) && (dst*2==0x2600)) sharedprotram[0x2600 / 2] = 0x4e75; // hack + } + break; + + case 5: // copy + { + for (INT32 x = 0; x < size; x++) { + sharedprotram[dst + x] = PROTROM[src + x]; + } + } + break; + + case 6: // swap bytes and nibbles + { + for (INT32 x = 0; x < size; x++) + { + UINT16 dat = PROTROM[src + x]; + + dat = ((dat & 0xf000) >> 12) | ((dat & 0x0f00) >> 4) | ((dat & 0x00f0) << 4) | ((dat & 0x000f) << 12); + + sharedprotram[dst + x] = dat; + } + } + break; + + case 4: // fixed value xor? + case 7: // params left in memory? nop? + default: // ? + break; + } +} + +static void IGS022_handle_command() +{ + UINT16 cmd = sharedprotram[0x200/2]; + + if (cmd == 0x6d) // Store values to asic ram + { + UINT32 p1 = (sharedprotram[0x298/2] << 16) | sharedprotram[0x29a/2]; + UINT32 p2 = (sharedprotram[0x29c/2] << 16) | sharedprotram[0x29e/2]; + + if ((p2 & 0xffff) == 0x9) // Set value + { + INT32 reg = (p2 >> 16) & 0xffff; + if (reg & 0x200) kb_regs[reg & 0xff] = p1; + } + if ((p2 & 0xffff) == 0x6) // Add value + { + INT32 src1 = (p1 >> 16) & 0x00ff; + INT32 src2 = (p1 >> 0) & 0x00ff; + INT32 dst = (p2 >> 16) & 0x00ff; + kb_regs[dst] = kb_regs[src2] - kb_regs[src1]; + } + if ((p2 & 0xffff) == 0x1) // Add Imm? + { + INT32 reg = (p2 >> 16) & 0x00ff; + INT32 imm = (p1 >> 0) & 0xffff; + kb_regs[reg] += imm; + } + if ((p2 & 0xffff) == 0xa) // Get value + { + INT32 reg = (p1 >> 16) & 0x00ff; + sharedprotram[0x29c/2] = (kb_regs[reg] >> 16) & 0xffff; + sharedprotram[0x29e/2] = (kb_regs[reg] >> 0) & 0xffff; + } + } + + if (cmd == 0x4f) // memcpy with encryption / scrambling + { + UINT16 src = sharedprotram[0x290 / 2] >> 1; // ? + UINT16 dst = sharedprotram[0x292 / 2]; + UINT16 size = sharedprotram[0x294 / 2]; + UINT16 mode = sharedprotram[0x296 / 2]; + + IGS022_do_dma(src, dst, size, mode); + } +} + +static void killbld_igs025_prot_write(UINT32 offset, UINT16 data) +{ + offset &= 0xf; + + if (offset == 0) { + kb_cmd = data; + return; + } + + switch (kb_cmd) + { + case 0: + kb_reg = data; + break; + + case 2: + if (data == 1) { + IGS022_handle_command(); + kb_reg++; + } + break; + + case 4: + kb_ptr = data; + break; + + case 0x20: + kb_ptr++; + break; + + default: + break; + } +} + +static UINT16 killbld_igs025_prot_read(UINT32 offset) +{ + offset &= 0xf; + + if (offset == 1) + { + if (kb_cmd == 1) + { + return (kb_reg & 0x7f); + } + else if (kb_cmd == 5) + { + UINT32 protvalue = 0x89911400 | PgmInput[7]; + return (protvalue >> (8 * (kb_ptr - 1))) & 0xff; + } + } + + return 0; +} + +static void __fastcall killbld_write_word(UINT32 address, UINT16 data) +{ + killbld_igs025_prot_write(address / 2, data); +} + +static UINT16 __fastcall killbld_read_word(UINT32 address) +{ + return killbld_igs025_prot_read(address / 2); +} + +static void IGS022Reset() +{ + sharedprotram = (UINT16*)PGMUSER0; + USER1 = PGMUSER0 + 0x10000; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "killbld") == 0) { + BurnLoadRom(USER1, 11, 1); // load protection data + } else { + BurnLoadRom(USER1, 14, 1); // load protection data + } + + BurnByteswap(USER1, 0x10000); + + UINT16 *PROTROM = (UINT16*)USER1; + + for (INT32 i = 0; i < 0x4000/2; i++) + sharedprotram[i] = 0xa55a; + + UINT16 src = PROTROM[0x100 / 2]; + UINT16 dst = PROTROM[0x102 / 2]; + UINT16 size = PROTROM[0x104 / 2]; + UINT16 mode = PROTROM[0x106 / 2]; + UINT16 tmp = PROTROM[0x114 / 2]; + + src = (( src & 0xff00) >> 8) | (( src & 0x00ff) << 8); + dst = (( dst & 0xff00) >> 8) | (( dst & 0x00ff) << 8); + size = ((size & 0xff00) >> 8) | ((size & 0x00ff) << 8); + tmp = (( tmp & 0xff00) >> 8) | (( tmp & 0x00ff) << 8); + mode &= 0xff; + + src >>= 1; + + IGS022_do_dma(src, dst, size, mode); + + sharedprotram[0x2a2/2] = tmp; // crc check? + + kb_cmd = kb_reg = kb_ptr = 0; + memset (kb_regs, 0, 0x100 * sizeof(INT32)); +} + +void install_protection_asic25_asic22_killbld() +{ + pPgmScanCallback = killbldScan; + pPgmResetCallback = IGS022Reset; + + sharedprotram = (UINT16*)PGMUSER0; + + SekOpen(0); + SekMapMemory(PGMUSER0, 0x300000, 0x303fff, SM_RAM); + SekMapHandler(4, 0xd40000, 0xd40003, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, killbld_read_word); + SekSetWriteWordHandler(4, killbld_write_word); + SekClose(); +} + +//------------------------------------------------------------------------- +// Puzzle Stars + + +static UINT16 PSTARSKEY; +static UINT16 PSTARSINT[2]; +static UINT32 PSTARS_REGS[16]; +static UINT32 PSTARS_VAL; + +static UINT16 pstar_e7,pstar_b1,pstar_ce; +static UINT16 pstar_ram[3]; + +static INT32 Pstar_ba[0x1E]={ + 0x02,0x00,0x00,0x01,0x00,0x03,0x00,0x00, //0 + 0x02,0x00,0x06,0x00,0x22,0x04,0x00,0x03, //8 + 0x00,0x00,0x06,0x00,0x20,0x07,0x00,0x03, //10 + 0x00,0x21,0x01,0x00,0x00,0x63 +}; + +static INT32 Pstar_b0[0x10]={ + 0x09,0x0A,0x0B,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00 +}; + +static INT32 Pstar_ae[0x10]={ + 0x5D,0x86,0x8C ,0x8B,0xE0,0x8B,0x62,0xAF, + 0xB6,0xAF,0x10A,0xAF,0x00,0x00,0x00,0x00 +}; + +static INT32 Pstar_a0[0x10]={ + 0x02,0x03,0x04,0x05,0x06,0x01,0x0A,0x0B, + 0x0C,0x0D,0x0E,0x09,0x00,0x00,0x00,0x00, +}; + +static INT32 Pstar_9d[0x10]={ + 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +static INT32 Pstar_90[0x10]={ + 0x0C,0x10,0x0E,0x0C,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; +static INT32 Pstar_8c[0x23]={ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02, + 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04, + 0x03,0x03,0x03 +}; + +static INT32 Pstar_80[0x1a3]={ + 0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05, + 0x05,0x05,0x06,0x06,0x03,0x03,0x04,0x04, + 0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07, + 0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x05, + 0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06, + 0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07, + 0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07, + 0x07,0x07,0x08,0x08,0x05,0x05,0x05,0x05, + 0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07, + 0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08, + 0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07, + 0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09, + 0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08, + 0x08,0x08,0x09,0x09,0x05,0x05,0x06,0x06, + 0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09, + 0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08, + 0x08,0x09,0x09,0x09,0x06,0x06,0x07,0x03, + 0x07,0x06,0x07,0x07,0x08,0x07,0x05,0x04, + 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, + 0x06,0x06,0x06,0x06,0x03,0x04,0x04,0x04, + 0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07, + 0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06, + 0x06,0x07,0x07,0x08,0x05,0x05,0x06,0x07, + 0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07, + 0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09, + 0x09,0x09,0x03,0x04,0x04,0x05,0x05,0x05, + 0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08, + 0x08,0x09,0x09,0x09,0x03,0x04,0x05,0x05, + 0x04,0x03,0x04,0x04,0x04,0x05,0x05,0x04, + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04, + 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03, + 0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, + 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00 +}; + +static UINT16 PSTARS_protram_r(UINT32 offset) +{ + offset >>= 1; + + if (offset == 4) //region + return PgmInput[7]; + else if (offset >= 0x10) //timer + { + return pstar_ram[offset-0x10]--; + } + return 0x0000; +} + +static UINT16 PSTARS_r16(UINT32 offset) +{ + offset >>= 1; + + if(offset==0) + { + UINT16 d=PSTARS_VAL&0xffff; + UINT16 realkey; + realkey=PSTARSKEY>>8; + realkey|=PSTARSKEY; + d^=realkey; + return d; + } + else if(offset==1) + { + UINT16 d=PSTARS_VAL>>16; + UINT16 realkey; + realkey=PSTARSKEY>>8; + realkey|=PSTARSKEY; + d^=realkey; + return d; + + } + return 0xff; +} + +static void PSTARS_w16(UINT32 offset, UINT16 data) +{ + offset >>= 1; + + if(offset==0) + { + PSTARSINT[0]=data; + return; + } + + if(offset==1) + { + UINT16 realkey; + if((data>>8)==0xff) PSTARSKEY=0xff00; + realkey=PSTARSKEY>>8; + realkey|=PSTARSKEY; + { + PSTARSKEY+=0x100; + PSTARSKEY&=0xff00; + if(PSTARSKEY==0xff00)PSTARSKEY=0x100; + } + data^=realkey; + PSTARSINT[1]=data; + PSTARSINT[0]^=realkey; + + switch(PSTARSINT[1]&0xff) + { + case 0x99: + { + PSTARSKEY=0x100; + PSTARS_VAL=0x880000; + } + break; + + case 0xE0: + { + PSTARS_VAL=0xa00000+(PSTARSINT[0]<<6); + } + break; + case 0xDC: + { + PSTARS_VAL=0xa00800+(PSTARSINT[0]<<6); + } + break; + case 0xD0: + { + PSTARS_VAL=0xa01000+(PSTARSINT[0]<<5); + } + break; + + case 0xb1: + { + pstar_b1=PSTARSINT[0]; + PSTARS_VAL=0x890000; + } + break; + case 0xbf: + { + PSTARS_VAL=pstar_b1*PSTARSINT[0]; + } + break; + + case 0xc1: //TODO:TIMER 0,1,2,FIX TO 0 should be OK? + { + PSTARS_VAL=0; + } + break; + case 0xce: //TODO:TIMER 0,1,2 + { + pstar_ce=PSTARSINT[0]; + PSTARS_VAL=0x890000; + } + break; + case 0xcf: //TODO:TIMER 0,1,2 + { + pstar_ram[pstar_ce]=PSTARSINT[0]; + PSTARS_VAL=0x890000; + } + break; + + + case 0xe7: + { + pstar_e7=(PSTARSINT[0]>>12)&0xf; + PSTARS_REGS[pstar_e7]&=0xffff; + PSTARS_REGS[pstar_e7]|=(PSTARSINT[0]&0xff)<<16; + PSTARS_VAL=0x890000; + } + break; + case 0xe5: + { + + PSTARS_REGS[pstar_e7]&=0xff0000; + PSTARS_REGS[pstar_e7]|=PSTARSINT[0]; + PSTARS_VAL=0x890000; + } + break; + case 0xf8: //@73C + { + PSTARS_VAL=PSTARS_REGS[PSTARSINT[0]&0xf]&0xffffff; + } + break; + + + case 0xba: + { + PSTARS_VAL=Pstar_ba[PSTARSINT[0]]; + } + break; + case 0xb0: + { + PSTARS_VAL=Pstar_b0[PSTARSINT[0]]; + } + break; + case 0xae: + { + PSTARS_VAL=Pstar_ae[PSTARSINT[0]]; + } + break; + case 0xa0: + { + PSTARS_VAL=Pstar_a0[PSTARSINT[0]]; + } + break; + case 0x9d: + { + PSTARS_VAL=Pstar_9d[PSTARSINT[0]]; + } + break; + case 0x90: + { + PSTARS_VAL=Pstar_90[PSTARSINT[0]]; + } + break; + case 0x8c: + { + PSTARS_VAL=Pstar_8c[PSTARSINT[0]]; + } + break; + case 0x80: + { + PSTARS_VAL=Pstar_80[PSTARSINT[0]]; + } + break; + default: + PSTARS_VAL=0x890000; + } + } +} + +void __fastcall pstars_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffffc) == 0x500000) { + PSTARS_w16(address & 3, data); + } +} + +UINT8 __fastcall pstars_read_byte(UINT32 address) +{ + if ((address & 0xff0000) == 0x4f0000) { + return PSTARS_protram_r(address & 0xffff); + } + + if ((address & 0xfffffc) == 0x500000) { + return PSTARS_r16(address & 3); + } + + return 0; +} + +UINT16 __fastcall pstars_read_word(UINT32 address) +{ + if ((address & 0xff0000) == 0x4f0000) { + return PSTARS_protram_r(address & 0xffff); + } + + if ((address & 0xfffffc) == 0x500000) { + return PSTARS_r16(address & 3); + } + + return 0; +} + +static void reset_puzlstar() +{ + PSTARSKEY = 0; + PSTARS_VAL = 0; + PSTARSINT[0] = PSTARSINT[1] = 0; + pstar_e7 = pstar_b1 = pstar_ce = 0; + + memset(PSTARS_REGS, 0, 16); + memset(pstar_ram, 0, 3); +} + +void install_protection_asic27a_puzlstar() +{ + pPgmScanCallback = pstarsScan; + pPgmResetCallback = reset_puzlstar; + + SekOpen(0); + SekMapHandler(4, 0x4f0000, 0x500003, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, pstars_read_word); + SekSetReadByteHandler(4, pstars_read_byte); + SekSetWriteWordHandler(4, pstars_write_word); + SekClose(); +} + + +//----------------------------------------------------------------------------------------------------- +// ASIC27A - Kov2, Martmast, etc + +static UINT8 asic27a_to_arm = 0; +static UINT8 asic27a_to_68k = 0; + +static inline void pgm_cpu_sync() +{ + INT32 nCycles = SekTotalCycles() - Arm7TotalCycles(); + + if (nCycles > 0) { + Arm7Run(nCycles); + } +} + +static void __fastcall asic27a_write_byte(UINT32 /*address*/, UINT8 /*data*/) +{ + +} + +static void __fastcall asic27a_write_word(UINT32 address, UINT16 data) +{ + if ((address & 0xfffffe) == 0xd10000) { + // pgm_cpu_sync(); + asic27a_to_arm = data & 0xff; + Arm7SetIRQLine(ARM7_FIRQ_LINE, ARM7_HOLD_LINE); + return; + } +} + +static UINT8 __fastcall asic27a_read_byte(UINT32 address) +{ + if ((address & 0xff0000) == 0xd00000) { + pgm_cpu_sync(); + return PGMARMShareRAM[(address & 0xffff)^1]; + } + + if ((address & 0xfffffc) == 0xd10000) { + pgm_cpu_sync(); + return asic27a_to_68k; + } + + return 0; +} + +static UINT16 __fastcall asic27a_read_word(UINT32 address) +{ + if ((address & 0xff0000) == 0xd00000) { + pgm_cpu_sync(); + return *((UINT16*)(PGMARMShareRAM + (address & 0xfffe))); + } + + if ((address & 0xfffffc) == 0xd10000) { + pgm_cpu_sync(); + return asic27a_to_68k; + } + + return 0; +} + +static void asic27a_arm7_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x38000000: + asic27a_to_68k = data; + return; + } +} + +static UINT8 asic27a_arm7_read_byte(UINT32 address) +{ + switch (address) + { + case 0x38000000: + return asic27a_to_arm; + } + + return 0; +} + +void install_protection_asic27a_martmast() +{ + nPGMArm7Type = 2; + pPgmScanCallback = asic27aScan; + + SekOpen(0); + + SekMapMemory(PGMARMShareRAM, 0xd00000, 0xd0ffff, SM_FETCH | SM_WRITE); + + SekMapHandler(4, 0xd00000, 0xd10003, SM_READ); + SekMapHandler(5, 0xd10000, 0xd10003, SM_WRITE); + + SekSetReadWordHandler(4, asic27a_read_word); + SekSetReadByteHandler(4, asic27a_read_byte); + SekSetWriteWordHandler(5, asic27a_write_word); + SekSetWriteByteHandler(5, asic27a_write_byte); + SekClose(); + + Arm7Init(1); + Arm7Open(0); + Arm7MapMemory(PGMARMROM, 0x00000000, 0x00003fff, ARM7_ROM); + Arm7MapMemory(PGMUSER0, 0x08000000, 0x08000000+(nPGMExternalARMLen-1), ARM7_ROM); + Arm7MapMemory(PGMARMRAM0, 0x10000000, 0x100003ff, ARM7_RAM); + Arm7MapMemory(PGMARMRAM1, 0x18000000, 0x1800ffff, ARM7_RAM); + Arm7MapMemory(PGMARMShareRAM, 0x48000000, 0x4800ffff, ARM7_RAM); + Arm7MapMemory(PGMARMRAM2, 0x50000000, 0x500003ff, ARM7_RAM); + Arm7SetWriteByteHandler(asic27a_arm7_write_byte); + Arm7SetReadByteHandler(asic27a_arm7_read_byte); + Arm7Close(); +} + + +//---------------------------------------------------------------------------------------------------------- +// Kovsh/Photoy2k/Photoy2k2 asic27a emulation... (thanks to XingXing!) + +static UINT16 kovsh_highlatch_arm_w = 0; +static UINT16 kovsh_lowlatch_arm_w = 0; +static UINT16 kovsh_highlatch_68k_w = 0; +static UINT16 kovsh_lowlatch_68k_w = 0; +static UINT32 kovsh_counter = 1; + +static void __fastcall kovsh_asic27a_write_word(UINT32 address, UINT16 data) +{ + switch (address) + { + case 0x500000: + case 0x600000: + kovsh_lowlatch_68k_w = data; + return; + + case 0x500002: + case 0x600002: + kovsh_highlatch_68k_w = data; + return; + } +} + +static UINT16 __fastcall kovsh_asic27a_read_word(UINT32 address) +{ + if ((address & 0xffffc0) == 0x4f0000) { + return *((UINT16*)(PGMARMShareRAM + (address & 0x3e))); + } + + switch (address) + { + case 0x500000: + case 0x600000: + pgm_cpu_sync(); + return kovsh_lowlatch_arm_w; + + case 0x500002: + case 0x600002: + pgm_cpu_sync(); + return kovsh_highlatch_arm_w; + } + + return 0; +} + +static void kovsh_asic27a_arm7_write_word(UINT32 address, UINT16 data) +{ + // written... but never read? + if ((address & 0xffffff80) == 0x50800000) { + *((UINT16*)(PGMARMShareRAM + ((address>>1) & 0x3e))) = data; + return; + } +} + +static void kovsh_asic27a_arm7_write_long(UINT32 address, UINT32 data) +{ + switch (address) + { + case 0x40000000: + { + kovsh_highlatch_arm_w = data >> 16; + kovsh_lowlatch_arm_w = data; + + kovsh_highlatch_68k_w = 0; + kovsh_lowlatch_68k_w = 0; + } + return; + } +} + +static UINT32 kovsh_asic27a_arm7_read_long(UINT32 address) +{ + switch (address) + { + case 0x40000000: + return (kovsh_highlatch_68k_w << 16) | (kovsh_lowlatch_68k_w); + + case 0x4000000c: + return kovsh_counter++; + } + + return 0; +} + +void install_protection_asic27a_kovsh() +{ + nPGMArm7Type = 1; + pPgmScanCallback = kovsh_asic27aScan; + + SekOpen(0); + SekMapMemory(PGMARMShareRAM, 0x4f0000, 0x4f003f, SM_RAM); + + SekMapHandler(4, 0x500000, 0x600005, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, kovsh_asic27a_read_word); + SekSetWriteWordHandler(4, kovsh_asic27a_write_word); + SekClose(); + + Arm7Init(1); + Arm7Open(0); + Arm7MapMemory(PGMARMROM, 0x00000000, 0x00003fff, ARM7_ROM); + Arm7MapMemory(PGMARMRAM0, 0x10000000, 0x100003ff, ARM7_RAM); + Arm7MapMemory(PGMARMRAM2, 0x50000000, 0x500003ff, ARM7_RAM); + Arm7SetWriteWordHandler(kovsh_asic27a_arm7_write_word); + Arm7SetWriteLongHandler(kovsh_asic27a_arm7_write_long); + Arm7SetReadLongHandler(kovsh_asic27a_arm7_read_long); + Arm7Close(); +} + + +//---------------------------------------------------------------------------------------------------------- +// olds + +static INT32 rego; +static UINT16 olds_bs,olds_cmd3; + +static UINT32 olds_prot_addr( UINT16 addr ) +{ + UINT32 mode = addr & 0xff; + UINT32 offset = addr >> 8; + UINT32 realaddr; + + switch(mode) + { + case 0x0: + case 0x5: + case 0xa: + realaddr = 0x402a00 + (offset << 2); + break; + + case 0x2: + case 0x8: + realaddr = 0x402e00 + (offset << 2); + break; + + case 0x1: + realaddr = 0x40307e; + break; + + case 0x3: + realaddr = 0x403090; + break; + + case 0x4: + realaddr = 0x40309a; + break; + + case 0x6: + realaddr = 0x4030a4; + break; + + case 0x7: + realaddr = 0x403000; + break; + + case 0x9: + realaddr = 0x40306e; + break; + + default: + realaddr = 0; + } + return realaddr; +} + +static UINT32 olds_read_reg(UINT16 addr) +{ + UINT32 protaddr = (olds_prot_addr(addr) - 0x400000) / 2; + return sharedprotram[protaddr] << 16 | sharedprotram[protaddr + 1]; +} + +static void olds_write_reg(UINT16 addr, UINT32 val) +{ + sharedprotram[(olds_prot_addr(addr) - 0x400000) / 2] = val >> 16; + sharedprotram[(olds_prot_addr(addr) - 0x400000) / 2 + 1] = val & 0xffff; +} + +UINT16 __fastcall olds_protection_read(UINT32 address) +{ + UINT16 res = 0; + + if (address & 2) + { + if (kb_cmd == 1) + res = kb_reg & 0x7f; + if (kb_cmd == 2) + res = olds_bs | 0x80; + if (kb_cmd == 3) + res = olds_cmd3; + else if (kb_cmd == 5) + { + UINT32 protvalue = 0x900000 | PgmInput[7]; // region from protection device. + res = (protvalue >> (8 * (kb_ptr - 1))) & 0xff; // includes region 1 = taiwan , 2 = china, 3 = japan (title = orlegend special), 4 = korea, 5 = hongkong, 6 = world + + } + } + + return res; +} + +void __fastcall olds_protection_write(UINT32 address, UINT16 data) +{ + if ((address & 2) == 0) + kb_cmd = data; + else //offset==2 + { + if (kb_cmd == 0) + kb_reg = data; + else if(kb_cmd == 2) //a bitswap= + { + INT32 reg = 0; + if (data & 0x01) reg |= 0x40; + if (data & 0x02) reg |= 0x80; + if (data & 0x04) reg |= 0x20; + if (data & 0x08) reg |= 0x10; + olds_bs = reg; + } + else if (kb_cmd == 3) + { + UINT16 cmd = sharedprotram[0x3026 / 2]; + + switch (cmd) + { + case 0x11: + case 0x12: + break; + case 0x64: + { + UINT16 cmd0 = sharedprotram[0x3082 / 2]; + UINT16 val0 = sharedprotram[0x3050 / 2]; //CMD_FORMAT + { + if ((cmd0 & 0xff) == 0x2) + olds_write_reg(val0, olds_read_reg(val0) + 0x10000); + } + break; + } + + default: + break; + } + olds_cmd3 = ((data >> 4) + 1) & 0x3; + } + else if (kb_cmd == 4) + kb_ptr = data; + else if(kb_cmd == 0x20) + kb_ptr++; + } +} + +static UINT16 __fastcall olds_mainram_read_word(UINT32 address) +{ + if (SekGetPC(-1) >= 0x100000 && address != 0x8178d8) SekWriteWord(0x8178f4, SekReadWord(0x8178D8)); + + return *((UINT16*)(PGM68KRAM + (address & 0x1fffe))); +} + +static UINT8 __fastcall olds_mainram_read_byte(UINT32 address) +{ + return PGM68KRAM[(address & 0x1ffff)^1]; +} + +static void reset_olds() +{ + olds_bs = olds_cmd3 = kb_cmd = ptr = rego = 0; + memcpy (PGMUSER0, PGMUSER0 + 0x10000, 0x04000); +} + +void install_protection_asic25_asic28_olds() +{ + pPgmScanCallback = oldsScan; + pPgmResetCallback = reset_olds; + + sharedprotram = (UINT16*)PGMUSER0; + + // no protection rom and different offset for olds100a + if (strcmp(BurnDrvGetTextA(DRV_NAME), "olds100a") == 0) { + BurnLoadRom(PGMUSER0 + 0x10000, 16, 1); + } else { + BurnLoadRom(PGMUSER0 + 0x10000, 20, 1); + BurnLoadRom(PGMUSER0 + 0x20000, 19, 1); + BurnByteswap(PGMUSER0 + 0x20000, 0x10000); + + // copy in some 68k code from protection rom + memcpy (PGMUSER0 + 0x10200, PGMUSER0 + 0x20300, 0x6B4); + } + + { + UINT16 *gptr = (UINT16*)(PGMUSER0 + 0x10000); + + for(INT32 i = 0; i < 0x4000 / 2; i++) { + if (gptr[i] == (0xffff - i)) gptr[i] = 0x4e75; + } + } + + SekOpen(0); + + SekMapMemory(PGMUSER0, 0x400000, 0x403fff, SM_RAM); + + SekMapHandler(4, 0xdcb400, 0xdcb403, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, olds_protection_read); + SekSetWriteWordHandler(4, olds_protection_write); + + SekMapHandler(5, 0x8178f4, 0x8178f5, SM_READ | SM_FETCH); + SekSetReadWordHandler(5, olds_mainram_read_word); + SekSetReadByteHandler(5, olds_mainram_read_byte); + + SekClose(); +} + +//------------------------------------------------------------------------------------------- +// Oriental Legends Special Plus! (Creamy Mami) + +static UINT16 m_oldsplus_key; +static UINT16 m_oldsplus_int[2]; +static UINT32 m_oldsplus_val; +static UINT32 m_oldsplus_regs[0x100]; +static UINT32 m_oldsplus_ram[0x100]; + +static const INT32 oldsplus_80[0x5]={ + 0xbb8,0x1770,0x2328,0x2ee0,0xf4240 +}; + +static const UINT8 oldsplus_fc[0x20]={ + 0x00,0x00,0x0a,0x3a,0x4e,0x2e,0x03,0x40, + 0x33,0x43,0x26,0x2c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x44,0x4d,0x0b,0x27,0x3d,0x0f, + 0x37,0x2b,0x02,0x2f,0x15,0x45,0x0e,0x30 +}; + +static const UINT16 oldsplus_a0[0x20]={ + 0x000,0x023,0x046,0x069,0x08c,0x0af,0x0d2,0x0f5, + 0x118,0x13b,0x15e,0x181,0x1a4,0x1c7,0x1ea,0x20d, + 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d, + 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d, +}; + +static const UINT16 oldsplus_90[0x7]={ + 0x50,0xa0,0xc8,0xf0,0x190,0x1f4,0x258 +}; + +static const UINT8 oldsplus_5e[0x20]={ + 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03, + 0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static const UINT8 oldsplus_b0[0xe0]={ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + + 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, + + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + + 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, + 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, + 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f +}; + +static const UINT8 oldsplus_ae[0xe0]={ + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + + 0x1E,0x1F,0x20,0x21,0x22,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + + 0x1F,0x20,0x21,0x22,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + + 0x20,0x21,0x22,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + + 0x21,0x22,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23 +}; + +static const UINT16 oldsplus_ba[0x4]={ + 0x3138,0x2328,0x1C20,0x1518 +}; + +static const UINT16 oldsplus_9d[0x111]={ + 0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc, + 0x02f8,0x0334,0x0370,0x03ac,0x03e8,0x0424,0x0460,0x049c, + 0x04d8,0x0514,0x0550,0x058c,0x05c8,0x0604,0x0640,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000, + 0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0302, + 0x0348,0x038e,0x03d4,0x041a,0x0460,0x04a6,0x04ec,0x0532, + 0x0578,0x05be,0x0604,0x064a,0x0690,0x06d6,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064, + 0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0316,0x0370, + 0x03ca,0x0424,0x047e,0x04d8,0x0532,0x058c,0x05e6,0x0640, + 0x069a,0x06f4,0x074e,0x07a8,0x0802,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8, + 0x012c,0x0190,0x01f4,0x0258,0x02bc,0x032a,0x0398,0x0406, + 0x0474,0x04e2,0x0550,0x05be,0x062c,0x069a,0x0708,0x0776, + 0x07e4,0x0852,0x08c0,0x092e,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c, + 0x0190,0x01f4,0x0258,0x02bc,0x0348,0x03d4,0x0460,0x04ec, + 0x0578,0x0604,0x0690,0x071c,0x07a8,0x0834,0x08c0,0x094c, + 0x09d8,0x0a64,0x0af0,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190, + 0x01f4,0x0258,0x02bc,0x0384,0x044c,0x0514,0x05dc,0x06a4, + 0x076c,0x0834,0x08fc,0x09c4,0x0a8c,0x0b54,0x0c1c,0x0ce4, + 0x0dac,0x0e74,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4, + 0x0258,0x02bc,0x030c,0x035c,0x03ac,0x03fc,0x044c,0x049c, + 0x04ec,0x053c,0x058c,0x05dc,0x062c,0x067c,0x06cc,0x071c, + 0x076c,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc, + 0x06bc +}; + +static const UINT16 oldsplus_8c[0x20]={ + 0x0032,0x0032,0x0064,0x0096,0x0096,0x00fa,0x012c,0x015e, + 0x0032,0x0064,0x0096,0x00c8,0x00c8,0x012c,0x015e,0x0190, + 0x0064,0x0096,0x00c8,0x00fa,0x00fa,0x015e,0x0190,0x01c2, + 0x0096,0x00c8,0x00fa,0x012c,0x012c,0x0190,0x01c2,0x01f4 +}; + +UINT16 _fastcall oldsplus_prot_read(UINT32 address) +{ + if (address == 0x500000) + { + UINT16 d = m_oldsplus_val & 0xffff; + UINT16 realkey = m_oldsplus_key >> 8; + realkey |= m_oldsplus_key; + d ^= realkey; + return d; + } + else if (address == 0x500002) + { + UINT16 d = m_oldsplus_val >> 16; + UINT16 realkey = m_oldsplus_key >> 8; + realkey |= m_oldsplus_key; + d ^= realkey; + return d; + + } + return 0xff; +} + +void __fastcall oldsplus_prot_write(UINT32 address, UINT16 data) +{ + if (address == 0x500000) + { + m_oldsplus_int[0] = data; + return; + } + + if (address == 0x500002) + { + UINT16 realkey; + if ((data >> 8) == 0xff) m_oldsplus_key = 0xff00; + realkey = m_oldsplus_key >> 8; + realkey |= m_oldsplus_key; + { + m_oldsplus_key += 0x100; + m_oldsplus_key &= 0xff00; + if (m_oldsplus_key == 0xff00) m_oldsplus_key = 0x100; + } + data ^= realkey; + m_oldsplus_int[1] = data; + m_oldsplus_int[0] ^= realkey; + + switch (m_oldsplus_int[1] & 0xff) + { + case 0x88: + m_oldsplus_key = 0x100; + m_oldsplus_val = 0x990000; + break; + + case 0xd0: + m_oldsplus_val = 0xa01000 + (m_oldsplus_int[0] << 5); + break; + + case 0xc0: + m_oldsplus_val = 0xa00000 + (m_oldsplus_int[0] << 6); + break; + + case 0xc3: + m_oldsplus_val = 0xa00800 + (m_oldsplus_int[0] << 6); + break; + + case 0x36: + m_oldsplus_ram[0x36] = m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0x33: + m_oldsplus_ram[0x33] = m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0x35: + m_oldsplus_ram[0x36] += m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0x37: + m_oldsplus_ram[0x33] += m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0x34: + m_oldsplus_val = m_oldsplus_ram[0x36]; + break; + + case 0x38: + m_oldsplus_val = m_oldsplus_ram[0x33]; + break; + + case 0x80: + m_oldsplus_val = oldsplus_80[m_oldsplus_int[0]]; + break; + + case 0xe7: + m_oldsplus_ram[0xe7] = m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0xe5: + switch (m_oldsplus_ram[0xe7]) + { + case 0xb000: + m_oldsplus_regs[0xb] = m_oldsplus_int[0]; + m_oldsplus_regs[0xc] = 0; + break; + + case 0xc000: + m_oldsplus_regs[0xc] = m_oldsplus_int[0]; + break; + + case 0xd000: + m_oldsplus_regs[0xd] = m_oldsplus_int[0]; + break; + + case 0xf000: + m_oldsplus_regs[0xf] = m_oldsplus_int[0]; + break; + } + m_oldsplus_val = 0x990000; + break; + + case 0xf8: + m_oldsplus_val = m_oldsplus_regs[m_oldsplus_int[0]]; + break; + + case 0xfc: + m_oldsplus_val = oldsplus_fc[m_oldsplus_int[0]]; + break; + + case 0xc5: + m_oldsplus_regs[0xd] --; + m_oldsplus_val = 0x990000; + break; + + case 0xd6: + m_oldsplus_regs[0xb] ++; + m_oldsplus_val = 0x990000; + break; + + case 0x3a: + m_oldsplus_regs[0xf] = 0; + m_oldsplus_val = 0x990000; + break; + + case 0xf0: + m_oldsplus_ram[0xf0] = m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0xed: + m_oldsplus_val = m_oldsplus_int[0] << 0x6; + m_oldsplus_val += m_oldsplus_ram[0xf0]; + m_oldsplus_val = m_oldsplus_val << 0x2; + m_oldsplus_val += 0x900000; + break; + + case 0xe0: + m_oldsplus_ram[0xe0] = m_oldsplus_int[0]; + m_oldsplus_val = 0x990000; + break; + + case 0xdc: + m_oldsplus_val = m_oldsplus_int[0] << 0x6; + m_oldsplus_val += m_oldsplus_ram[0xe0]; + m_oldsplus_val = m_oldsplus_val << 2; + m_oldsplus_val += 0x904000; + break; + + case 0xcb: + m_oldsplus_val = 0xc000; + break; + + case 0xa0: + m_oldsplus_val = oldsplus_a0[m_oldsplus_int[0]]; + break; + + case 0xba: + m_oldsplus_val = oldsplus_ba[m_oldsplus_int[0]]; + break; + + case 0x5e: + m_oldsplus_val = oldsplus_5e[m_oldsplus_int[0]]; + break; + + case 0xb0: + m_oldsplus_val = oldsplus_b0[m_oldsplus_int[0]]; + break; + + case 0xae: + m_oldsplus_val = oldsplus_ae[m_oldsplus_int[0]]; + break; + + case 0x9d: + m_oldsplus_val = oldsplus_9d[m_oldsplus_int[0]]; + break; + + case 0x90: + m_oldsplus_val = oldsplus_90[m_oldsplus_int[0]]; + break; + + case 0x8c: + m_oldsplus_val = oldsplus_8c[m_oldsplus_int[0]]; + break; + + default: + m_oldsplus_val = 0x990000; + break; + } + } +} + +static void reset_asic27a_oldsplus() +{ + m_oldsplus_key = 0; + m_oldsplus_val = 0; + memset (m_oldsplus_int, 0, sizeof(INT16) * 2); + memset (m_oldsplus_regs, 0, sizeof(INT32) * 0x100); + memset (m_oldsplus_ram, 0, sizeof(INT32) * 0x100); + + memset (PGMUSER0, 0, 0x400); + + *((UINT16*)(PGMUSER0 + 0x00008)) = PgmInput[7]; // region +} + +void install_protection_asic27a_oldsplus() +{ + pPgmScanCallback = oldsplus_asic27aScan; + pPgmResetCallback = reset_asic27a_oldsplus; + + SekOpen(0); + SekMapMemory(PGMUSER0, 0x4f0000, 0x4f003f | 0x3ff, SM_READ); // ram + + SekMapHandler(4, 0x500000, 0x500003, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, oldsplus_prot_read); + SekSetWriteWordHandler(4, oldsplus_prot_write); + SekClose(); +} + + + +// add this to the bottom of pgm_prot.cpp (i added it after the oldsScan function) + + +INT32 oldsplus_asic27aScan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = (UINT8*)m_oldsplus_ram; + ba.nLen = 0x0000100 * sizeof(INT32); + ba.nAddress = 0xfffc00; + ba.szName = "Prot RAM"; + BurnAcb(&ba); + + ba.Data = (UINT8*)m_oldsplus_regs; + ba.nLen = 0x0000100 * sizeof(INT32); + ba.nAddress = 0xfff800; + ba.szName = "Prot REGs"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(m_oldsplus_key); + SCAN_VAR(m_oldsplus_val); + SCAN_VAR(m_oldsplus_int[0]); + SCAN_VAR(m_oldsplus_int[1]); + } + + return 0; +} + +//------------------------------------------------------------------------------------------- +// S.V.G. - Spectral vs Generation / Demon Front / The Gladiator / The Killing Blade EX / Happy 6in1 + +static UINT8 svg_ram_sel = 0; +static UINT8 *svg_ram[2]; + +static void svg_set_ram_bank(INT32 data) +{ + svg_ram_sel = data & 1; + Arm7MapMemory(svg_ram[svg_ram_sel], 0x38000000, 0x3801ffff, ARM7_RAM); + SekMapMemory(svg_ram[svg_ram_sel^1], 0x500000, 0x51ffff, SM_FETCH); +} + +static void __fastcall svg_write_byte(UINT32 address, UINT8 data) +{ + pgm_cpu_sync(); + + if ((address & 0xffe0000) == 0x0500000) { + svg_ram[svg_ram_sel^1][(address & 0x1ffff)^1] = data; + return; + } + + switch (address) + { + case 0x5c0000: + case 0x5c0001: + Arm7SetIRQLine(ARM7_FIRQ_LINE, ARM7_HOLD_LINE); + return; + } +} + +static void __fastcall svg_write_word(UINT32 address, UINT16 data) +{ + pgm_cpu_sync(); + + if ((address & 0xffe0000) == 0x0500000) { + *((UINT16*)(svg_ram[svg_ram_sel^1] + (address & 0x1fffe))) = data; + + return; + } + + switch (address) + { + case 0x5c0000: + Arm7SetIRQLine(ARM7_FIRQ_LINE, ARM7_HOLD_LINE); + return; + + case 0x5c0300: + asic27a_to_arm = data; + return; + } +} + +static UINT8 __fastcall svg_read_byte(UINT32 address) +{ + if ((address & 0xffe0000) == 0x0500000) { + pgm_cpu_sync(); + + INT32 d = svg_ram[svg_ram_sel^1][(address & 0x1ffff)^1]; + return d; + } + + switch (address) + { + case 0x5c0000: + case 0x5c0001: + return 0; + } + + return 0; +} + +static UINT16 __fastcall svg_read_word(UINT32 address) +{ + if ((address & 0xffe0000) == 0x0500000) { + pgm_cpu_sync(); + + return *((UINT16*)(svg_ram[svg_ram_sel^1] + (address & 0x1fffe))); + } + + switch (address) + { + case 0x5c0000: + case 0x5c0001: + return 0; + + case 0x5c0300: + pgm_cpu_sync(); + return asic27a_to_68k; + } + + return 0; +} + +static void svg_arm7_write_byte(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x40000018: + svg_set_ram_bank(data); + return; + + case 0x48000000: + asic27a_to_68k = data; + return; + } +} + +static void svg_arm7_write_word(UINT32 /*address*/, UINT16 /*data*/) +{ + +} + +static void svg_arm7_write_long(UINT32 address, UINT32 data) +{ + switch (address) + { + case 0x40000018: + svg_set_ram_bank(data); + return; + + case 0x48000000: + asic27a_to_68k = data; + return; + } +} + +static UINT8 svg_arm7_read_byte(UINT32 address) +{ + switch (address) + { + case 0x48000000: + case 0x48000001: + case 0x48000002: + case 0x48000003: + return asic27a_to_arm; + } + + return 0; +} + +static UINT16 svg_arm7_read_word(UINT32 address) +{ + switch (address) + { + case 0x48000000: + case 0x48000002: + return asic27a_to_arm; + } + + return 0; +} + +static UINT32 svg_arm7_read_long(UINT32 address) +{ + switch (address) + { + case 0x48000000: + return asic27a_to_arm; + } + + return 0; +} + +void install_protection_asic27a_svg() +{ + nPGMArm7Type = 3; + + pPgmScanCallback = svg_asic27aScan; + + svg_ram_sel = 0; + svg_ram[0] = PGMARMShareRAM; + svg_ram[1] = PGMARMShareRAM2; + + SekOpen(0); + SekMapHandler(5, 0x500000, 0x5fffff, SM_RAM); + SekSetReadWordHandler(5, svg_read_word); + SekSetReadByteHandler(5, svg_read_byte); + SekSetWriteWordHandler(5, svg_write_word); + SekSetWriteByteHandler(5, svg_write_byte); + SekClose(); + + Arm7Init(1); + Arm7Open(0); + Arm7MapMemory(PGMARMROM, 0x00000000, 0x00003fff, ARM7_ROM); + Arm7MapMemory(PGMUSER0, 0x08000000, 0x08000000 | (nPGMExternalARMLen-1), ARM7_ROM); + Arm7MapMemory(PGMARMRAM0, 0x10000000, 0x100003ff, ARM7_RAM); + Arm7MapMemory(PGMARMRAM1, 0x18000000, 0x1803ffff, ARM7_RAM); + Arm7MapMemory(svg_ram[1], 0x38000000, 0x3801ffff, ARM7_RAM); + Arm7MapMemory(PGMARMRAM2, 0x50000000, 0x500003ff, ARM7_RAM); + Arm7SetWriteByteHandler(svg_arm7_write_byte); + Arm7SetWriteWordHandler(svg_arm7_write_word); + Arm7SetWriteLongHandler(svg_arm7_write_long); + Arm7SetReadByteHandler(svg_arm7_read_byte); + Arm7SetReadWordHandler(svg_arm7_read_word); + Arm7SetReadLongHandler(svg_arm7_read_long); + Arm7Close(); +} + + +//------------------------------------------------------------------------------------------- +// ketsui / espgaluda / ddp3 + +static UINT16 ddp3value; +static UINT16 ddp3key; +static UINT32 ddp3response; +static UINT8 ddp3internal_slot; +static UINT32 ddp3slots[0x100]; + +void __fastcall ddp3_asic_write(UINT32 offset, UINT16 data) +{ + switch (offset & 0x06) + { + case 0: ddp3value = data; return; + + case 2: + { + if ((data >> 8) == 0xff) ddp3key = 0xffff; + + ddp3value ^= ddp3key; + ddp3response = 0x880000; + + switch ((data ^ ddp3key) & 0xff) + { + case 0x40: + ddp3slots[(ddp3value >> 10) & 0x1f] = (ddp3slots[(ddp3value >> 5) & 0x1f] + ddp3slots[(ddp3value >> 0) & 0x1f]) & 0xffffff; + break; + + case 0x67: + ddp3internal_slot = ddp3value >> 8; + ddp3slots[ddp3internal_slot] = (ddp3value & 0x00ff) << 16; + break; + + case 0xe5: + ddp3slots[ddp3internal_slot] |= ddp3value; + break; + + case 0x8e: + ddp3response = ddp3slots[ddp3value & 0xff]; + break; + + case 0x99: // reset? + ddp3key = 0; + break; + } + + ddp3key = (ddp3key + 0x0100) & 0xff00; + if (ddp3key == 0xff00) ddp3key = 0x0100; + ddp3key |= ddp3key >> 8; + } + return; + + case 4: return; + } +} + +static UINT16 __fastcall ddp3_asic_read(UINT32 offset) +{ + switch (offset & 0x02) + { + case 0: return (ddp3response >> 0) ^ ddp3key; + case 2: return (ddp3response >> 16) ^ ddp3key; + } + + return 0; +} + +static void reset_ddp3() +{ + ddp3value = 0; + ddp3key = 0; + ddp3response = 0; + ddp3internal_slot = 0; + + memset (ddp3slots, 0, 0x100 * sizeof(INT32)); +} + +void install_protection_asic27a_ketsui() +{ + pPgmResetCallback = reset_ddp3; + pPgmScanCallback = ddp3Scan; + + SekOpen(0); + SekMapHandler(4, 0x400000, 0x400005, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, ddp3_asic_read); + SekSetWriteWordHandler(4, ddp3_asic_write); + SekClose(); +} + +void install_protection_asic27a_ddp3() +{ + pPgmResetCallback = reset_ddp3; + pPgmScanCallback = ddp3Scan; + + SekOpen(0); + SekMapHandler(4, 0x500000, 0x500005, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, ddp3_asic_read); + SekSetWriteWordHandler(4, ddp3_asic_write); + SekClose(); +} + + +//----------------------------------------------------------------------------------------------------- +// Save states + +INT32 kov_asic27Scan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = (UINT8*)ASIC27REGS; + ba.nLen = 0x000000a * sizeof(INT16); + ba.nAddress = 0xff0000; + ba.szName = "Asic Registers"; + BurnAcb(&ba); + + ba.Data = (UINT8*)ASICPARAMS; + ba.nLen = 0x0000100 * sizeof(INT16); + ba.nAddress = 0xff1000; + ba.szName = "Asic Parameters"; + BurnAcb(&ba); + + ba.Data = (UINT8*)E0REGS; + ba.nLen = 0x0000010 * sizeof(INT16); + ba.nAddress = 0xff2000; + ba.szName = "Asic E0 Registers"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(ASIC27KEY); + SCAN_VAR(ASIC27RCNT); + } + + return 0; +} + +INT32 asic3Scan(INT32 nAction, INT32 */*pnMin*/) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(asic3_reg); + SCAN_VAR(asic3_latch[0]); + SCAN_VAR(asic3_latch[1]); + SCAN_VAR(asic3_latch[2]); + SCAN_VAR(asic3_x); + SCAN_VAR(asic3_y); + SCAN_VAR(asic3_z); + SCAN_VAR(asic3_h1); + SCAN_VAR(asic3_h2); + SCAN_VAR(asic3_hold); + } + + return 0; +} + +INT32 killbldScan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMUSER0 + 0x000000; + ba.nLen = 0x0004000; + ba.nAddress = 0x300000; + ba.szName = "ProtRAM"; + BurnAcb(&ba); + + ba.Data = (UINT8*)kb_regs; + ba.nLen = 0x00100 * sizeof(INT32); + ba.nAddress = 0xfffffc00; + ba.szName = "Protection Registers"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(kb_cmd); + SCAN_VAR(kb_reg); + SCAN_VAR(kb_ptr); + } + + return 0; +} + +INT32 pstarsScan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = (UINT8*)PSTARS_REGS; + ba.nLen = 0x0000010 * sizeof(INT32); + ba.nAddress = 0xff1000; + ba.szName = "Asic Register"; + BurnAcb(&ba); + + ba.Data = (UINT8*)pstar_ram; + ba.nLen = 0x0000003 * sizeof(INT16); + ba.nAddress = 0xff2000; + ba.szName = "Asic RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(PSTARSKEY); + SCAN_VAR(PSTARS_VAL); + SCAN_VAR(PSTARSINT[0]); + SCAN_VAR(PSTARSINT[1]); + SCAN_VAR(pstar_e7); + SCAN_VAR(pstar_b1); + SCAN_VAR(pstar_ce); + } + + return 0; +} + +INT32 asic27aScan(INT32 nAction,INT32 *) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMARMShareRAM; + ba.nLen = 0x0010000; + ba.nAddress = 0xd00000; + ba.szName = "ARM SHARE RAM"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM0; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 0"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM1; + ba.nLen = 0x0010000; + ba.nAddress = 0; + ba.szName = "ARM RAM 1"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM2; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 2"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + Arm7Scan(nAction); + + SCAN_VAR(asic27a_to_arm); + SCAN_VAR(asic27a_to_68k); + } + + return 0; +} + +INT32 oldsScan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMUSER0 + 0x000000; + ba.nLen = 0x0004000; + ba.nAddress = 0x400000; + ba.szName = "ProtRAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(olds_cmd3); + SCAN_VAR(rego); + SCAN_VAR(olds_bs); + SCAN_VAR(ptr); + SCAN_VAR(kb_cmd); + } + + return 0; +} + +INT32 kovsh_asic27aScan(INT32 nAction,INT32 *) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMARMShareRAM; + ba.nLen = 0x0000040; + ba.nAddress = 0x400000; + ba.szName = "ARM SHARE RAM"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM0; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 0"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM2; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 1"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + Arm7Scan(nAction); + + SCAN_VAR(kovsh_highlatch_arm_w); + SCAN_VAR(kovsh_lowlatch_arm_w); + SCAN_VAR(kovsh_highlatch_68k_w); + SCAN_VAR(kovsh_lowlatch_68k_w); + SCAN_VAR(kovsh_counter); + } + + return 0; +} + +INT32 svg_asic27aScan(INT32 nAction,INT32 *) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMARMShareRAM; + ba.nLen = 0x0020000; + ba.nAddress = 0x400000; + ba.szName = "ARM SHARE RAM #0 (address 500000)"; + BurnAcb(&ba); + + ba.Data = PGMARMShareRAM2; + ba.nLen = 0x0020000; + ba.nAddress = 0x500000; + ba.szName = "ARM SHARE RAM #1"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM0; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 0"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM1; + ba.nLen = 0x0040000; + ba.nAddress = 0; + ba.szName = "ARM RAM 1"; + BurnAcb(&ba); + + ba.Data = PGMARMRAM2; + ba.nLen = 0x0000400; + ba.nAddress = 0; + ba.szName = "ARM RAM 2"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + Arm7Scan(nAction); + SCAN_VAR(asic27a_to_arm); + SCAN_VAR(asic27a_to_68k); + + SCAN_VAR(svg_ram_sel); + svg_set_ram_bank(svg_ram_sel); + } + + return 0; +} + +INT32 ddp3Scan(INT32 nAction, INT32 */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = (UINT8*)ddp3slots; + ba.nLen = 0x0000100 * sizeof(INT32); + ba.nAddress = 0xff00000; + ba.szName = "ProtRAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(ddp3value); + SCAN_VAR(ddp3key); + SCAN_VAR(ddp3response); + SCAN_VAR(ddp3internal_slot); + } + + return 0; +} + +//------------------------------------------------------------------------------------------- +// ddp2 - preliminary (kludgy) + +static INT32 ddp2_asic27_0xd10000 = 0; + +static void __fastcall Ddp2WriteByte(UINT32 address, UINT8 data) +{ + if ((address & 0xffe000) == 0xd00000) { + PGMUSER0[(address & 0x1fff)^1] = data; + *((UINT16*)(PGMUSER0 + 0x0010)) = 0; + *((UINT16*)(PGMUSER0 + 0x0020)) = 1; + return; + } + + if ((address & 0xffffffe) == 0xd10000) { + ddp2_asic27_0xd10000=data; + return; + } +} + +static void __fastcall Ddp2WriteWord(UINT32 address, UINT16 data) +{ + if ((address & 0xffe000) == 0xd00000) { + *((UINT16*)(PGMUSER0 + (address & 0x1ffe))) = data; + *((UINT16*)(PGMUSER0 + 0x0010)) = 0; + *((UINT16*)(PGMUSER0 + 0x0020)) = 1; + return; + } + + if ((address & 0xffffffe) == 0xd10000) { + ddp2_asic27_0xd10000=data; + return; + } +} + +static UINT8 __fastcall Ddp2ReadByte(UINT32 address) +{ + if ((address & 0xfffffe) == 0xd10000) { + ddp2_asic27_0xd10000++; + ddp2_asic27_0xd10000&=0x7f; + return ddp2_asic27_0xd10000; + } + + if ((address & 0xffe000) == 0xd00000) { + *((UINT16*)(PGMUSER0 + 0x0002)) = PgmInput[7]; // region + *((UINT16*)(PGMUSER0 + 0x1f00)) = 0; + return PGMUSER0[(address & 0x1fff)^1]; + } + + return 0; +} + +static UINT16 __fastcall Ddp2ReadWord(UINT32 address) +{ + if ((address & 0xfffffe) == 0xd10000) { + ddp2_asic27_0xd10000++; + ddp2_asic27_0xd10000&=0x7f; + return ddp2_asic27_0xd10000; + } + + if ((address & 0xffe000) == 0xd00000) { + *((UINT16*)(PGMUSER0 + 0x0002)) = PgmInput[7]; // region + *((UINT16*)(PGMUSER0 + 0x1f00)) = 0; + return *((UINT16*)(PGMUSER0 + (address & 0x1ffe))); + } + + return 0; +} + +void install_protection_asic27a_ddp2() +{ + memset (PGMUSER0, 0, 0x2000); + + SekOpen(0); + SekMapHandler(4, 0xd00000, 0xd1ffff, SM_READ | SM_WRITE); + SekSetReadWordHandler(4, Ddp2ReadWord); + SekSetReadByteHandler(4, Ddp2ReadByte); + SekSetWriteWordHandler(4, Ddp2WriteWord); + SekSetWriteByteHandler(4, Ddp2WriteByte); + SekClose(); +} diff --git a/src/burn/drivers/pgm/pgm_run.cpp b/src/burn/drivers/pgm/pgm_run.cpp new file mode 100644 index 00000000..7db81e8b --- /dev/null +++ b/src/burn/drivers/pgm/pgm_run.cpp @@ -0,0 +1,1050 @@ + +#include "pgm.h" +#include "arm7_intf.h" + +UINT8 PgmJoy1[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmJoy2[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmJoy3[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmJoy4[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmBtn1[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmBtn2[8] = {0,0,0,0,0,0,0,0}; +UINT8 PgmInput[9] = {0,0,0,0,0,0,0,0, 0}; +UINT8 PgmReset = 0; + +INT32 nPGM68KROMLen = 0; +INT32 nPGMTileROMLen = 0; +INT32 nPGMSPRColROMLen = 0; +INT32 nPGMSPRMaskROMLen = 0; +INT32 nPGMSNDROMLen = 0; +INT32 nPGMSPRColMaskLen = 0; +INT32 nPGMSPRMaskMaskLen = 0; +INT32 nPGMExternalARMLen = 0; + +UINT32 *PGMBgRAM; +UINT32 *PGMTxtRAM; +UINT32 *RamCurPal; +UINT16 *PGMRowRAM; +UINT16 *PGMPalRAM; +UINT16 *PGMVidReg; +UINT16 *PGMSprBuf; +static UINT8 *RamZ80; +UINT8 *PGM68KRAM; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; + +UINT8 *PGM68KBIOS, *PGM68KROM, *PGMTileROM, *PGMTileROMExp, *PGMSPRColROM, *PGMSPRMaskROM, *PGMARMROM; +UINT8 *PGMARMRAM0, *PGMUSER0, *PGMARMRAM1, *PGMARMRAM2, *PGMARMShareRAM, *PGMARMShareRAM2; + +UINT8 nPgmPalRecalc = 0; +static UINT8 nPgmZ80Work = 0; +static INT32 nPgmCurrentBios = -1; + +void (*pPgmResetCallback)() = NULL; +void (*pPgmInitCallback)() = NULL; +void (*pPgmProtCallback)() = NULL; +INT32 (*pPgmScanCallback)(INT32, INT32*) = NULL; + +static INT32 nEnableArm7 = 0; +INT32 nPGMEnableIRQ4 = 0; +INT32 nPGMArm7Type = 0; + +#define M68K_CYCS_PER_FRAME ((20000000 * 100) / nBurnFPS) +#define Z80_CYCS_PER_FRAME (( 8468000 * 100) / nBurnFPS) +#define ARM7_CYCS_PER_FRAME ((20000000 * 100) / nBurnFPS) + +#define PGM_INTER_LEAVE 2 + +#define M68K_CYCS_PER_INTER (M68K_CYCS_PER_FRAME / PGM_INTER_LEAVE) +#define Z80_CYCS_PER_INTER (Z80_CYCS_PER_FRAME / PGM_INTER_LEAVE) +#define ARM7_CYCS_PER_INTER (ARM7_CYCS_PER_FRAME / PGM_INTER_LEAVE) + +static INT32 nCyclesDone[3]; + +static INT32 pgmMemIndex() +{ + UINT8 *Next; Next = Mem; + PGM68KBIOS = Next; Next += 0x0080000; + PGM68KROM = Next; Next += nPGM68KROMLen; + + PGMUSER0 = Next; Next += nPGMExternalARMLen; + + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_USE_ARM_CPU) { + PGMARMROM = Next; Next += 0x0004000; + } + + RamStart = Next; + + PGM68KRAM = Next; Next += 0x0020000; + RamZ80 = Next; Next += 0x0010000; + + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_USE_ARM_CPU) { + PGMARMShareRAM = Next; Next += 0x0020000; + PGMARMShareRAM2 = Next; Next += 0x0020000; + PGMARMRAM0 = Next; Next += 0x0001000; // minimum map is 0x1000 - should be 0x400 + PGMARMRAM1 = Next; Next += 0x0040000; + PGMARMRAM2 = Next; Next += 0x0001000; // minimum map is 0x1000 - should be 0x400 + } + + PGMBgRAM = (UINT32 *) Next; Next += 0x0001000; + PGMTxtRAM = (UINT32 *) Next; Next += 0x0002000; + + PGMRowRAM = (UINT16 *) Next; Next += 0x0001000; // Row Scroll + PGMPalRAM = (UINT16 *) Next; Next += 0x0001400; // Palette R5G5B5 + PGMVidReg = (UINT16 *) Next; Next += 0x0010000; // Video Regs inc. Zoom Table + PGMSprBuf = (UINT16 *) Next; Next += 0x0000a00; + + RamEnd = Next; + + RamCurPal = (UINT32 *) Next; Next += (0x0001202 / 2) * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 pgmGetRoms(bool bLoad) +{ + INT32 kov2 = (strncmp(BurnDrvGetTextA(DRV_NAME), "kov2", 4) == 0) ? 1 : 0; + + char* pRomName; + struct BurnRomInfo ri; + struct BurnRomInfo pi; + + UINT8 *PGMUSER0Load = PGMUSER0; + UINT8 *PGM68KROMLoad = PGM68KROM; + UINT8 *PGMTileROMLoad = PGMTileROM + 0x180000; + UINT8 *PGMSPRMaskROMLoad = PGMSPRMaskROM; + UINT8 *PGMSNDROMLoad = ICSSNDROM + 0x400000; + + if (kov2 && bLoad) { + PGMSNDROMLoad += 0x400000; + } + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & BRF_PRG) && (ri.nType & 0x0f) == 1) + { + if (bLoad) { + BurnDrvGetRomInfo(&pi, i+1); + + if (ri.nLen == 0x80000 && pi.nLen == 0x80000) + { + BurnLoadRom(PGM68KROMLoad + 0, i + 0, 2); + BurnLoadRom(PGM68KROMLoad + 1, i + 1, 2); + PGM68KROMLoad += pi.nLen; + i += 1; + } + else + { + BurnLoadRom(PGM68KROMLoad, i, 1); + } + PGM68KROMLoad += ri.nLen; + } else { + nPGM68KROMLen += ri.nLen; + } + continue; + } + + if ((ri.nType & BRF_GRA) && (ri.nType & 0x0f) == 2) + { + if (bLoad) { + BurnLoadRom(PGMTileROMLoad, i, 1); + PGMTileROMLoad += ri.nLen; + } else { + nPGMTileROMLen += ri.nLen; + } + continue; + } + + if ((ri.nType & BRF_GRA) && (ri.nType & 0x0f) == 3) + { + if (bLoad) { + } else { + nPGMSPRColROMLen += ri.nLen; + } + continue; + } + + if ((ri.nType & BRF_GRA) && (ri.nType & 0x0f) == 4) + { + if (bLoad) { + BurnLoadRom(PGMSPRMaskROMLoad, i, 1); + PGMSPRMaskROMLoad += ri.nLen; + } else { + nPGMSPRMaskROMLen += ri.nLen; + } + continue; + } + + if ((ri.nType & BRF_SND) && (ri.nType & 0x0f) == 5) + { + if (bLoad) { + BurnLoadRom(PGMSNDROMLoad, i, 1); + PGMSNDROMLoad += ri.nLen; + } else { + nPGMSNDROMLen += ri.nLen; + } + continue; + } + + if ((ri.nType & BRF_PRG) && (ri.nType & 0x0f) == 7) + { + if (bLoad) { + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_USE_ARM_CPU) { + BurnLoadRom(PGMARMROM, i, 1); + } + } + continue; + } + + if ((ri.nType & BRF_PRG) && (ri.nType & 0x0f) == 8) + { + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_USE_ARM_CPU) { + if (bLoad) { + BurnLoadRom(PGMUSER0, i, 1); + PGMUSER0Load += ri.nLen; + } else { + nPGMExternalARMLen += ri.nLen; + } + } + continue; + } + } + + if (!bLoad) { + nPGMTileROMLen += 0x180000; + if (nPGMTileROMLen < 0x400000) nPGMTileROMLen = 0x400000; + + nPGMSNDROMLen += 0x400000; + + if (kov2) nPGMSNDROMLen += 0x400000; + + nPGMSNDROMLen = ((nPGMSNDROMLen-1) | 0xfffff) + 1; + nICSSNDROMLen = (nPGMSNDROMLen-1) & 0xf00000; + + if (nPGMExternalARMLen == 0) nPGMExternalARMLen = 0x200000; + bprintf (0, _T("%5.5x, %d\n"), nPGMExternalARMLen, nBurnFPS); + } + + return 0; +} + +/* Calendar Emulation */ + +static UINT8 CalVal, CalMask, CalCom=0, CalCnt=0; + +static UINT8 bcd(UINT8 data) +{ + return ((data / 10) << 4) | (data % 10); +} + +static UINT8 pgm_calendar_r() +{ + UINT8 calr; + calr = (CalVal & CalMask) ? 1 : 0; + CalMask <<= 1; + return calr; +} + +static void pgm_calendar_w(UINT16 data) +{ + time_t nLocalTime = time(NULL); + tm* tmLocalTime = localtime(&nLocalTime); + + CalCom <<= 1; + CalCom |= data & 1; + ++CalCnt; + if(CalCnt==4) + { + CalMask = 1; + CalVal = 1; + CalCnt = 0; + + switch(CalCom & 0xf) + { + case 0x1: case 0x3: case 0x5: case 0x7: case 0x9: case 0xb: case 0xd: + CalVal++; + break; + + case 0x0: // Day + CalVal=bcd(tmLocalTime->tm_wday); + break; + + case 0x2: // Hours + CalVal=bcd(tmLocalTime->tm_hour); + break; + + case 0x4: // Seconds + CalVal=bcd(tmLocalTime->tm_sec); + break; + + case 0x6: // Month + CalVal=bcd(tmLocalTime->tm_mon + 1); // not bcd in MVS + break; + + case 0x8: // Milliseconds? + CalVal=0; + break; + + case 0xa: // Day + CalVal=bcd(tmLocalTime->tm_mday); + break; + + case 0xc: // Minute + CalVal=bcd(tmLocalTime->tm_min); + break; + + case 0xe: // Year + CalVal=bcd(tmLocalTime->tm_year % 100); + break; + + case 0xf: // Load Date + tmLocalTime = localtime(&nLocalTime); + break; + } + } +} + +UINT8 __fastcall PgmReadByte(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0xC00007: + return pgm_calendar_r(); + + case 0xC08007: // dipswitches - (ddp2) + return ~(PgmInput[6]) | 0xe0; + + // default: + // bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x (PC: %5.5x)\n"), sekAddress, SekGetPC(-1)); + } + + return 0; +} + +UINT16 __fastcall PgmReadWord(UINT32 sekAddress) +{ + switch (sekAddress) + { + case 0xC00004: + return ics2115_soundlatch_r(1); + + case 0xC00006: // ketsui wants this + return pgm_calendar_r(); + + case 0xC08000: // p1+p2 controls + return ~(PgmInput[0] | (PgmInput[1] << 8)); + + case 0xC08002: // p3+p4 controls + return ~(PgmInput[2] | (PgmInput[3] << 8)); + + case 0xC08004: // extra controls + return ~(PgmInput[4] | (PgmInput[5] << 8)); + + case 0xC08006: // dipswitches + return ~(PgmInput[6]) | 0xffe0; + + // default: + // bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x (PC: %5.5x)\n"), sekAddress, SekGetPC(-1)); + } + + return 0; +} + +void __fastcall PgmWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + byteValue=byteValue; // fix warning + + switch (sekAddress) + { + // default: + // bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x (PC: %5.5x)\n"), byteValue, sekAddress, SekGetPC(-1)); + } +} + +void __fastcall PgmWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + static INT32 coin_counter_previous; + + switch (sekAddress) + { + case 0x700006: // Watchdog? + break; + + case 0xC00002: + ics2115_soundlatch_w(0, wordValue); + if (nPgmZ80Work) ZetNmi(); + break; + + case 0xC00004: + ics2115_soundlatch_w(1, wordValue); + break; + + case 0xC00006: + pgm_calendar_w(wordValue); + break; + + case 0xC00008: + if (wordValue == 0x5050) { + ics2115_reset(); + nPgmZ80Work = 1; + + ZetReset(); + } else { + nPgmZ80Work = 0; + } + break; + + case 0xC0000A: // z80_ctrl_w + break; + + case 0xC0000C: + ics2115_soundlatch_w(2, wordValue); + break; + + case 0xC08006: // coin counter + if (coin_counter_previous == 0xf && wordValue == 0) { + // bprintf (0, _T("increment coin counter!\n")); + } + coin_counter_previous = wordValue & 0x0f; + break; + + // default: + // bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x (PC: %5.5x)\n"), wordValue, sekAddress, SekGetPC(-1)); + } +} + +UINT8 __fastcall PgmZ80ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) + { + // default: + // bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + + return 0; +} + +UINT16 __fastcall PgmZ80ReadWord(UINT32 sekAddress) +{ + sekAddress &= 0xffff; + return (RamZ80[sekAddress] << 8) | RamZ80[sekAddress+1]; +} + +void __fastcall PgmZ80WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress &= 0xffff; + RamZ80[sekAddress] = wordValue >> 8; + RamZ80[sekAddress+1] = wordValue & 0xFF; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x7C00) >> 7; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +void __fastcall PgmPaletteWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + sekAddress = (sekAddress - 0xa00000) >> 1; + PGMPalRAM[sekAddress] = wordValue; + RamCurPal[sekAddress] = CalcCol(wordValue); +} + +void __fastcall PgmPaletteWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + sekAddress -= 0xa00000; + UINT8 *pal = (UINT8*)PGMPalRAM; + pal[sekAddress ^ 1] = byteValue; + + RamCurPal[sekAddress >> 1] = CalcCol(PGMPalRAM[sekAddress >> 1]); +} + +UINT8 __fastcall PgmZ80PortRead(UINT16 port) +{ + switch (port >> 8) + { + case 0x80: + return ics2115read(port & 0xff); + + case 0x81: + return ics2115_soundlatch_r(2) & 0xff; + + case 0x82: + return ics2115_soundlatch_r(0) & 0xff; + + case 0x84: + return ics2115_soundlatch_r(1) & 0xff; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to read port %04x\n"), port); + } + return 0; +} + +void __fastcall PgmZ80PortWrite(UINT16 port, UINT8 data) +{ + switch (port >> 8) + { + case 0x80: + ics2115write(port & 0xff, data); + break; + + case 0x81: + ics2115_soundlatch_w(2, data); + break; + + case 0x82: + ics2115_soundlatch_w(0, data); + break; + + case 0x84: + ics2115_soundlatch_w(1, data); + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 Attempt to write %02x to port %04x\n"), data, port); + } +} + +INT32 PgmDoReset() +{ + if (nPgmCurrentBios != PgmInput[8]) { // Load the 68k bios + if (!(BurnDrvGetHardwareCode() & HARDWARE_IGS_JAMMAPCB)) { + nPgmCurrentBios = PgmInput[8]; + BurnLoadRom(PGM68KBIOS, 0x00082 + nPgmCurrentBios, 1); // 68k bios + } + } + + SekOpen(0); + SekReset(); + SekClose(); + + if (nEnableArm7) { + Arm7Open(0); + Arm7Reset(); + Arm7Close(); + } + + ZetOpen(0); + nPgmZ80Work = 0; + ZetReset(); + ZetClose(); + + ics2115_reset(); + + if (pPgmResetCallback) { + pPgmResetCallback(); + } + + return 0; +} + +static void expand_tile_gfx() +{ + UINT8 *src = PGMTileROM; + UINT8 *dst = PGMTileROMExp; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "kovqhsgs") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsqh2") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsjb") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsjba") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovassg") == 0) { + pgm_decode_kovqhsgs_tile_data(PGMTileROM + 0x180000); + } + + for (INT32 i = nPGMTileROMLen/5-1; i >= 0 ; i --) { + dst[0+8*i] = ((src[0+5*i] >> 0) & 0x1f); + dst[1+8*i] = ((src[0+5*i] >> 5) & 0x07) | ((src[1+5*i] << 3) & 0x18); + dst[2+8*i] = ((src[1+5*i] >> 2) & 0x1f ); + dst[3+8*i] = ((src[1+5*i] >> 7) & 0x01) | ((src[2+5*i] << 1) & 0x1e); + dst[4+8*i] = ((src[2+5*i] >> 4) & 0x0f) | ((src[3+5*i] << 4) & 0x10); + dst[5+8*i] = ((src[3+5*i] >> 1) & 0x1f ); + dst[6+8*i] = ((src[3+5*i] >> 6) & 0x03) | ((src[4+5*i] << 2) & 0x1c); + dst[7+8*i] = ((src[4+5*i] >> 3) & 0x1f ); + } + + for (INT32 i = 0x200000-1; i >= 0; i--) { + INT32 d = PGMTileROM[i]; + PGMTileROM[i * 2 + 0] = d & 0x0f; + PGMTileROM[i * 2 + 1] = d >> 4; + } + + PGMTileROM = (UINT8*)realloc(PGMTileROM, 0x400000); +} + +static void expand_colourdata() +{ + // allocate + { + INT32 needed = (nPGMSPRColROMLen / 2) * 3; + nPGMSPRColMaskLen = 1; + while (nPGMSPRColMaskLen < needed) + nPGMSPRColMaskLen <<= 1; + + needed = nPGMSPRMaskROMLen; + nPGMSPRMaskMaskLen = 1; + while (nPGMSPRMaskMaskLen < needed) + nPGMSPRMaskMaskLen <<= 1; + nPGMSPRMaskMaskLen-=1; + + PGMSPRColROM = (UINT8*)malloc(nPGMSPRColMaskLen); + nPGMSPRColMaskLen -= 1; + } + + UINT8 *tmp = (UINT8*)malloc(nPGMSPRColROMLen); + if (tmp == NULL) return; + + // load sprite color roms + { + char* pRomName; + struct BurnRomInfo ri; + + UINT8 *PGMSPRColROMLoad = tmp; + + for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++) { + + BurnDrvGetRomInfo(&ri, i); + + if ((ri.nType & BRF_GRA) && (ri.nType & 0x0f) == 3) + { + BurnLoadRom(PGMSPRColROMLoad, i, 1); + PGMSPRColROMLoad += ri.nLen; + + // fix for 2x size b0601 rom + if (strcmp(BurnDrvGetTextA(DRV_NAME), "kovsh") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovsh103") == 0) { + if (ri.nLen == 0x400000) { + PGMSPRColROMLoad -= 0x200000; + } + } + + continue; + } + } + } + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "kovqhsgs") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsqh2") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsjb") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovlsjba") == 0 || + strcmp(BurnDrvGetTextA(DRV_NAME), "kovassg") == 0) { + pgm_decode_kovqhsgs_gfx_block(tmp + 0x0000000); + pgm_decode_kovqhsgs_gfx_block(tmp + 0x0800000); + pgm_decode_kovqhsgs_gfx_block(tmp + 0x1000000); + pgm_decode_kovqhsgs_gfx_block(tmp + 0x1800000); + pgm_decode_kovqhsgs_gfx_block(tmp + 0x2000000); + pgm_decode_kovqhsgs_gfx_block(tmp + 0x2800000); + } + + // convert from 3bpp packed + for (INT32 cnt = 0; cnt < nPGMSPRColROMLen / 2; cnt++) + { + UINT16 colpack = ((tmp[cnt*2]) | (tmp[cnt*2+1] << 8)); + PGMSPRColROM[cnt*3+0] = (colpack >> 0 ) & 0x1f; + PGMSPRColROM[cnt*3+1] = (colpack >> 5 ) & 0x1f; + PGMSPRColROM[cnt*3+2] = (colpack >> 10) & 0x1f; + } + + if (tmp) { + free (tmp); + tmp = NULL; + } +} + +INT32 pgmInit() +{ + BurnSetRefreshRate((BurnDrvGetHardwareCode() & HARDWARE_IGS_JAMMAPCB) ? 59.17 : 60.00); // different? + + Mem = NULL; + + pgmGetRoms(false); + + expand_colourdata(); + + PGMTileROM = (UINT8*)malloc(nPGMTileROMLen); // 8x8 Text Tiles + 32x32 BG Tiles + PGMTileROMExp = (UINT8*)malloc((nPGMTileROMLen / 5) * 8); // Expanded 8x8 Text Tiles and 32x32 BG Tiles + PGMSPRMaskROM = (UINT8*)malloc(nPGMSPRMaskROMLen); + ICSSNDROM = (UINT8*)malloc(nPGMSNDROMLen); + + pgmMemIndex(); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + pgmMemIndex(); + + // load bios roms (68k bios loaded in reset routine) + if (BurnLoadRom(PGMTileROM, 0x80, 1)) return 1; // Bios Text and Tiles + BurnLoadRom(ICSSNDROM, 0x81, 1); // Bios Intro Sounds + + pgmGetRoms(true); + + expand_tile_gfx(); // expand graphics + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // ketsui and espgaluda + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_JAMMAPCB) + { + SekMapMemory(PGM68KROM, 0x000000, (nPGM68KROMLen-1), SM_ROM); // 68000 ROM (no bios) + } + else + { + SekMapMemory(PGM68KBIOS, 0x000000, 0x07ffff, SM_ROM); // 68000 BIOS + SekMapMemory(PGM68KROM, 0x100000, (nPGM68KROMLen-1)+0x100000, SM_ROM); // 68000 ROM + } + + for (INT32 i = 0; i < 0x100000; i+=0x20000) { // Main Ram + Mirrors... + SekMapMemory(PGM68KRAM, 0x800000 | i, 0x81ffff | i, SM_RAM); + } + + // Ripped from FBA Shuffle. + for (INT32 i = 0; i < 0x100000; i+=0x08000) { // Video Ram + Mirrors... + SekMapMemory((UINT8 *)PGMBgRAM, 0x900000 | i, 0x900fff | i, SM_RAM); + SekMapMemory((UINT8 *)PGMBgRAM, 0x901000 | i, 0x901fff | i, SM_RAM); // mirror + SekMapMemory((UINT8 *)PGMBgRAM, 0x902000 | i, 0x902fff | i, SM_RAM); // mirror + SekMapMemory((UINT8 *)PGMBgRAM, 0x903000 | i, 0x904fff | i, SM_RAM); // mirror + + SekMapMemory((UINT8 *)PGMTxtRAM, 0x904000 | i, 0x905fff | i, SM_RAM); + SekMapMemory((UINT8 *)PGMTxtRAM, 0x906000 | i, 0x906fff | i, SM_RAM); // mirror + + SekMapMemory((UINT8 *)PGMRowRAM, 0x907000 | i, 0x907fff | i, SM_RAM); + } + + SekMapMemory((UINT8 *)PGMPalRAM, 0xa00000, 0xa013ff, SM_ROM); // palette + SekMapMemory((UINT8 *)PGMVidReg, 0xb00000, 0xb0ffff, SM_RAM); // should be mirrored? + + SekMapHandler(1, 0xa00000, 0xa013ff, SM_WRITE); + SekMapHandler(2, 0xc10000, 0xc1ffff, SM_READ | SM_WRITE); + + SekSetReadWordHandler(0, PgmReadWord); + SekSetReadByteHandler(0, PgmReadByte); + SekSetWriteWordHandler(0, PgmWriteWord); + SekSetWriteByteHandler(0, PgmWriteByte); + + SekSetWriteByteHandler(1, PgmPaletteWriteByte); + SekSetWriteWordHandler(1, PgmPaletteWriteWord); + + SekSetReadWordHandler(2, PgmZ80ReadWord); + SekSetWriteWordHandler(2, PgmZ80WriteWord); + + SekClose(); + } + + { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xffff, 0, RamZ80); + ZetMapArea(0x0000, 0xffff, 1, RamZ80); + ZetMapArea(0x0000, 0xffff, 2, RamZ80); + ZetSetOutHandler(PgmZ80PortWrite); + ZetSetInHandler(PgmZ80PortRead); + ZetMemEnd(); + ZetClose(); + } + + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_USE_ARM_CPU) { + nEnableArm7 = 1; + } + + pgmInitDraw(); + + ics2115_init(); + + pBurnDrvPalette = (UINT32*)PGMPalRAM; + + if (pPgmInitCallback) { + pPgmInitCallback(); + } + + if (pPgmProtCallback) { + pPgmProtCallback(); + } + + PgmDoReset(); + + return 0; +} + +INT32 pgmExit() +{ + pgmExitDraw(); + + SekExit(); + ZetExit(); + + if (nEnableArm7) { + Arm7Exit(); + } + + if (Mem) { + free(Mem); + Mem = NULL; + } + + ics2115_exit(); // frees ICSSNDROM + + if (PGMTileROM) { + free (PGMTileROM); + PGMTileROM = NULL; + } + + if (PGMTileROMExp) { + free (PGMTileROMExp); + PGMTileROMExp = NULL; + } + + if (PGMSPRColROM) { + free (PGMSPRColROM); + PGMSPRColROM = NULL; + } + + if (PGMSPRMaskROM) { + free (PGMSPRMaskROM); + PGMSPRMaskROM = NULL; + } + + nPGM68KROMLen = 0; + nPGMTileROMLen = 0; + nPGMSPRColROMLen = 0; + nPGMSPRMaskROMLen = 0; + nPGMSNDROMLen = 0; + nPGMExternalARMLen = 0; + + pPgmInitCallback = NULL; + pPgmProtCallback = NULL; + pPgmScanCallback = NULL; + pPgmResetCallback = NULL; + + nEnableArm7 = 0; + nPGMEnableIRQ4 = 0; + nPGMArm7Type = 0; + + nPgmCurrentBios = -1; + + return 0; +} + +INT32 pgmFrame() +{ + if (PgmReset) { + PgmDoReset(); + } + + // compile inputs + { + memset (PgmInput, 0, 6); + for (INT32 i = 0; i < 8; i++) { + PgmInput[0] |= (PgmJoy1[i] & 1) << i; + PgmInput[1] |= (PgmJoy2[i] & 1) << i; + PgmInput[2] |= (PgmJoy3[i] & 1) << i; + PgmInput[3] |= (PgmJoy4[i] & 1) << i; + PgmInput[4] |= (PgmBtn1[i] & 1) << i; + PgmInput[5] |= (PgmBtn2[i] & 1) << i; + } + + // clear opposites + if ((PgmInput[0] & 0x06) == 0x06) PgmInput[0] &= 0xf9; // up/down + if ((PgmInput[0] & 0x18) == 0x18) PgmInput[0] &= 0xe7; // left/right + if ((PgmInput[1] & 0x06) == 0x06) PgmInput[1] &= 0xf9; + if ((PgmInput[1] & 0x18) == 0x18) PgmInput[1] &= 0xe7; + if ((PgmInput[2] & 0x06) == 0x06) PgmInput[2] &= 0xf9; + if ((PgmInput[2] & 0x18) == 0x18) PgmInput[2] &= 0xe7; + if ((PgmInput[3] & 0x06) == 0x06) PgmInput[3] &= 0xf9; + if ((PgmInput[3] & 0x18) == 0x18) PgmInput[3] &= 0xe7; + } + + INT32 nCyclesNext[3] = {0, 0, 0}; + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + nCyclesDone[2] = 0; + + SekNewFrame(); + ZetNewFrame(); + Arm7NewFrame(); + + if (nEnableArm7) // region hacks + { + switch (nPGMArm7Type) + { + case 1: // kov/kovsh/kovshp/photoy2k/puzlstar/puzzli2/oldsplus/py2k2 + PGMARMShareRAM[0x008] = PgmInput[7]; + break; + + case 2: // martmast/kov2/ddp2/dw2001 + PGMARMShareRAM[0x138] = PgmInput[7]; + break; + + case 3: // svg/killbldp/dmnfrnt/theglad/happy6in1 + // unknown... + break; + } + } + + SekOpen(0); + ZetOpen(0); + Arm7Open(0); + + for (INT32 i = 0; i < PGM_INTER_LEAVE; i++) + { + nCyclesNext[0] += M68K_CYCS_PER_INTER; + nCyclesNext[1] += Z80_CYCS_PER_INTER; + nCyclesNext[2] += ARM7_CYCS_PER_INTER; + + INT32 cycles = nCyclesNext[0] - nCyclesDone[0]; + + if (cycles > 0) { + nCyclesDone[0] += SekRun(cycles); + } + + cycles = nCyclesNext[2] - Arm7TotalCycles(); + + if (cycles > 0 && nEnableArm7) { + nCyclesDone[2] += Arm7Run(cycles); + } + + if (nPgmZ80Work) { + nCyclesDone[1] += ZetRun( nCyclesNext[1] - nCyclesDone[1] ); + } else + nCyclesDone[1] += nCyclesNext[1] - nCyclesDone[1]; + + if (i == ((PGM_INTER_LEAVE / 2)-1) && nPGMEnableIRQ4 != 0) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + + ics2115_frame(); + + Arm7Close(); + ZetClose(); + SekClose(); + + ics2115_update(nBurnSoundLen); + + if (pBurnDraw) { + pgmDraw(); + } + + memcpy (PGMSprBuf, PGM68KRAM /* Sprite RAM 0-bff */, 0xa00); // buffer sprites + + return 0; +} + +INT32 pgmScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029702; + } + + nPgmPalRecalc = 1; + + if (nAction & ACB_MEMORY_ROM) { + if (BurnDrvGetHardwareCode() & HARDWARE_IGS_JAMMAPCB) { + ba.Data = PGM68KROM; + ba.nLen = nPGM68KROMLen; + ba.nAddress = 0; + ba.szName = "68K ROM"; + BurnAcb(&ba); + } else { + ba.Data = PGM68KBIOS; + ba.nLen = 0x0020000; + ba.nAddress = 0; + ba.szName = "BIOS ROM"; + BurnAcb(&ba); + + ba.Data = PGM68KROM; + ba.nLen = nPGM68KROMLen; + ba.nAddress = 0x100000; + ba.szName = "68K ROM"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = PGMBgRAM; + ba.nLen = 0x0004000; + ba.nAddress = 0x900000; + ba.szName = "Bg RAM"; + BurnAcb(&ba); + + ba.Data = PGMTxtRAM; + ba.nLen = 0x0003000; + ba.nAddress = 0x904000; + ba.szName = "Tx RAM"; + BurnAcb(&ba); + + ba.Data = PGMRowRAM; + ba.nLen = 0x0001000; + ba.nAddress = 0x907000; + ba.szName = "Row Scroll"; + BurnAcb(&ba); + + ba.Data = PGMPalRAM; + ba.nLen = 0x0001400; + ba.nAddress = 0xA00000; + ba.szName = "Palette"; + BurnAcb(&ba); + + ba.Data = PGMVidReg; + ba.nLen = 0x0010000; + ba.nAddress = 0xB00000; + ba.szName = "Video Regs"; + BurnAcb(&ba); + + ba.Data = RamZ80; + ba.nLen = 0x0010000; + ba.nAddress = 0xC10000; + ba.szName = "Z80 RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_NVRAM) { + ba.Data = PGM68KRAM; + ba.nLen = 0x020000; + ba.nAddress = 0x800000; + ba.szName = "68K RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); + ZetScan(nAction); + + SCAN_VAR(PgmInput); + + SCAN_VAR(nPgmZ80Work); + + SCAN_VAR(nPgmCurrentBios); + + ics2115_scan(nAction, pnMin); + + SCAN_VAR(CalVal); + SCAN_VAR(CalMask); + SCAN_VAR(CalCom); + SCAN_VAR(CalCnt); + } + + if (pPgmScanCallback) { + pPgmScanCallback(nAction, pnMin); + } + + return 0; +} diff --git a/src/burn/drivers/psikyo/d_psikyo.cpp b/src/burn/drivers/psikyo/d_psikyo.cpp new file mode 100644 index 00000000..bc8ed57f --- /dev/null +++ b/src/burn/drivers/psikyo/d_psikyo.cpp @@ -0,0 +1,2588 @@ +// Psikyo MC68EC020 based hardware +#include "psikyo.h" +#include "burn_ym2610.h" +#include "burn_ymf278b.h" + +// #undef USE_SPEEDHACKS + +INT32 PsikyoHardwareVersion; + +static UINT8 DrvJoy1[8] = {0, }; +static UINT8 DrvJoy2[8] = {0, }; +static UINT8 DrvInp1[8] = {0, }; +static UINT8 DrvInp2[8] = {0, }; +static UINT16 DrvInput[4] = {0, }; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Psikyo68KROM, *PsikyoZ80ROM; +static UINT8 *Psikyo68KRAM, *PsikyoZ80RAM; +static UINT8 *PsikyoSampleROM01, *PsikyoSampleROM02; + +static INT32 PsikyoSampleROM01Size, PsikyoSampleROM02Size; +static INT32 PsikyoTileROMSize, PsikyoSpriteROMSize; + +static UINT8 DrvReset = 0; +static UINT16 bVBlank; + +static INT32 nPsikyoZ80Bank; + +static INT32 nSoundlatch, nSoundlatchAck; + +static INT32 nCyclesDone[2]; +static INT32 nCyclesTotal[2]; +static INT32 nCyclesSegment; +static INT32 nCycles68KSync; + +static INT32 nPrevBurnCPUSpeedAdjust; + +static INT32 (*CheckSleep)(INT32); + +// ---------------------------------------------------------------------------- +// Input definitions + +static struct BurnInputInfo gunbirdInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInp1 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 7, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 6, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 4, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 5, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvInp1 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 7, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 6, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 4, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 5, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Test", BIT_DIGITAL, DrvInp1 + 5, "diag"}, + {"Service", BIT_DIGITAL, DrvInp1 + 4, "service"}, +// {"Tilt", BIT_DIGITAL, DrvInp1 + 6, "tilt"}, + + {"Dip 1", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 2)) + 1, "dip"}, + {"Dip 2", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 2)) + 0, "dip"}, + {"Dip 3", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 3)) + 0, "dip"}, +}; + +STDINPUTINFO(gunbird) + +static struct BurnInputInfo btlkroadInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInp1 + 0, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 7, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 6, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 4, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 5, "p1 right"}, + {"P1 Weak punch", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1"}, + {"P1 Medium punch", BIT_DIGITAL, DrvJoy1 + 2, "p1 fire 2"}, + {"P1 Strong punch", BIT_DIGITAL, DrvJoy1 + 1, "p1 fire 3"}, + {"P1 Weak kick", BIT_DIGITAL, DrvInp2 + 7, "p1 fire 4"}, + {"P1 Medium kick", BIT_DIGITAL, DrvInp2 + 6, "p1 fire 5"}, + {"P1 Strong kick", BIT_DIGITAL, DrvInp2 + 5, "p1 fire 6"}, + + {"P2 Coin", BIT_DIGITAL, DrvInp1 + 1, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 7, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 6, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 4, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 5, "p2 right"}, + {"P2 Weak punch", BIT_DIGITAL, DrvJoy2 + 3, "p2 fire 1"}, + {"P2 Medium punch", BIT_DIGITAL, DrvJoy2 + 2, "p2 fire 2"}, + {"P2 Strong punch", BIT_DIGITAL, DrvJoy2 + 1, "p2 fire 3"}, + {"P2 Weak kick", BIT_DIGITAL, DrvInp2 + 3, "p2 fire 4"}, + {"P2 Medium kick", BIT_DIGITAL, DrvInp2 + 2, "p2 fire 5"}, + {"P2 Strong kick", BIT_DIGITAL, DrvInp2 + 1, "p2 fire 6"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Test", BIT_DIGITAL, DrvInp1 + 5, "diag"}, + {"Service", BIT_DIGITAL, DrvInp1 + 4, "service"}, +// {"Tilt", BIT_DIGITAL, DrvInp1 + 6, "tilt"}, + + {"Dip 1", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 2)) + 1, "dip"}, + {"Dip 2", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 2)) + 0, "dip"}, + {"Region", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 3)) + 0, "dip"}, + {"Debug Dip", BIT_DIPSWITCH, ((UINT8*)(DrvInput + 3)) + 1, "dip"}, +}; + +STDINPUTINFO(btlkroad) + +static struct BurnDIPInfo samuraiaDIPList[] = { + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin slot"}, + {0x15, 0x82, 0x01, 0x00, "Same"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x01, 0x01, "Individual"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 9, "Coin 1"}, + {0x15, 0x01, 0x0E, 0x00, "1 coin = 1 credit"}, + {0x15, 0x01, 0x0E, 0x02, "2 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x04, "3 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x08, "1 coin = 2 credits"}, + {0x15, 0x01, 0x0E, 0x06, "1 coin = 3 credits"}, + {0x15, 0x01, 0x0E, 0x0A, "1 coin = 4 credits"}, + {0x15, 0x01, 0x0E, 0x0C, "1 coin = 5 credits"}, + {0x15, 0x82, 0x0E, 0x0E, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x01, 0xFF, 0xFF, "Free play"}, + {0, 0xFE, 0, 9, "Coin 2"}, + {0x15, 0x82, 0x70, 0x00, "1 coin = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x10, "2 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x20, "3 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x40, "1 coin = 2 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x30, "1 coin = 3 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x50, "1 coin = 4 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x60, "1 coin = 5 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x70, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0xFF, 0xFF, "Free play"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 2, "Continue coin"}, + {0x15, 0x82, 0x80, 0x00, "Normal mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x80, 0x80, "Continue mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + // DIP 2 + {0, 0xFE, 0, 2, "Screen reverse"}, + {0x16, 0x01, 0x01, 0x00, "Invert"}, + {0x16, 0x01, 0x01, 0x01, "Normal"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x16, 0x01, 0x02, 0x00, "Off"}, + {0x16, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Easy"}, + {0x16, 0x01, 0x0C, 0x08, "Hard"}, + {0x16, 0x01, 0x0C, 0x0C, "Super hard"}, + {0, 0xFE, 0, 4, "Fighters"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "1"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Extend player"}, + {0x16, 0x01, 0x40, 0x00, "Every 400,000 points"}, + {0x16, 0x01, 0x40, 0x40, "Every 600,000 points"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x16, 0x01, 0x80, 0x00, "Off"}, + {0x16, 0x01, 0x80, 0x80, "On"}, +}; + +static struct BurnDIPInfo gunbirdDIPList[] = { + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin slot"}, + {0x15, 0x82, 0x01, 0x00, "Same"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x01, 0x01, "Individual"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 9, "Coin 1"}, + {0x15, 0x01, 0x0E, 0x00, "1 coin = 1 credit"}, + {0x15, 0x01, 0x0E, 0x02, "2 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x04, "3 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x08, "1 coin = 2 credits"}, + {0x15, 0x01, 0x0E, 0x06, "1 coin = 3 credits"}, + {0x15, 0x01, 0x0E, 0x0A, "1 coin = 4 credits"}, + {0x15, 0x01, 0x0E, 0x0C, "1 coin = 5 credits"}, + {0x15, 0x82, 0x0E, 0x0E, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x01, 0xFF, 0xFF, "Free play"}, + {0, 0xFE, 0, 9, "Coin 2"}, + {0x15, 0x82, 0x70, 0x00, "1 coin = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x10, "2 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x20, "3 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x40, "1 coin = 2 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x30, "1 coin = 3 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x50, "1 coin = 4 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x60, "1 coin = 5 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x70, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0xFF, 0xFF, "Free play"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 2, "Continue coin"}, + {0x15, 0x82, 0x80, 0x00, "Normal mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x80, 0x80, "Continue mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + // DIP 2 + {0, 0xFE, 0, 2, "Screen"}, + {0x16, 0x01, 0x01, 0x00, "Normal"}, + {0x16, 0x01, 0x01, 0x01, "Reverse"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x16, 0x01, 0x02, 0x00, "Off"}, + {0x16, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Easy"}, + {0x16, 0x01, 0x0C, 0x08, "Difficult"}, + {0x16, 0x01, 0x0C, 0x0C, "More Difficult"}, + {0, 0xFE, 0, 4, "Number of fighters"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "1"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Extend fighters"}, + {0x16, 0x01, 0x40, 0x00, "Every 400,000 points"}, + {0x16, 0x01, 0x40, 0x40, "Every 600,000 points"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x16, 0x01, 0x80, 0x00, "Off"}, + {0x16, 0x01, 0x80, 0x80, "On"}, +}; + +static struct BurnDIPInfo btlkroadDIPList[] = { + // Defaults + {0x1B, 0xFF, 0xFF, 0x00, NULL}, + {0x1C, 0xFF, 0xFF, 0x02, NULL}, + {0x1D, 0xFF, 0xFF, 0x0F, NULL}, + {0x1E, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin slot"}, + {0x1B, 0x82, 0x01, 0x00, "Same"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x01, 0x01, "Individual"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 9, "Coin 1"}, + {0x1B, 0x01, 0x0E, 0x00, "1 coin = 1 credit"}, + {0x1B, 0x01, 0x0E, 0x02, "2 coins = 1 credit"}, + {0x1B, 0x01, 0x0E, 0x04, "3 coins = 1 credit"}, + {0x1B, 0x01, 0x0E, 0x08, "1 coin = 2 credits"}, + {0x1B, 0x01, 0x0E, 0x06, "1 coin = 3 credits"}, + {0x1B, 0x01, 0x0E, 0x0A, "1 coin = 4 credits"}, + {0x1B, 0x01, 0x0E, 0x0C, "1 coin = 5 credits"}, + {0x1B, 0x82, 0x0E, 0x0E, "1 coin = 6 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x01, 0xFF, 0xFF, "Free play"}, + {0, 0xFE, 0, 9, "Coin 2"}, + {0x1B, 0x82, 0x70, 0x00, "1 coin = 1 credit"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x10, "2 coins = 1 credit"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x20, "3 coins = 1 credit"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x40, "1 coin = 2 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x30, "1 coin = 3 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x50, "1 coin = 4 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x60, "1 coin = 5 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x70, 0x70, "1 coin = 6 credits"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0xFF, 0xFF, "Free play"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 2, "Continue coin"}, + {0x1B, 0x82, 0x80, 0x00, "Normal mode"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + {0x1B, 0x82, 0x80, 0x80, "Continue mode"}, + {0x1B, 0x00, 0xFF, 0xFF, NULL}, + // DIP 2 + {0, 0xFE, 0, 2, NULL}, + {0x1C, 0x01, 0x01, 0x00, "Normal screen"}, + {0x1C, 0x01, 0x01, 0x01, "Invert screen"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x1C, 0x01, 0x02, 0x00, "Disabled"}, + {0x1C, 0x01, 0x02, 0x02, "Enabled"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x1C, 0x01, 0x0C, 0x00, "Normal"}, + {0x1C, 0x01, 0x0C, 0x04, "Easy"}, + {0x1C, 0x01, 0x0C, 0x08, "Hard"}, + {0x1C, 0x01, 0x0C, 0x0C, "Hardest"}, + {0, 0xFE, 0, 2, "Enable debug dip"}, + {0x1C, 0x01, 0x40, 0x00, "Off"}, + {0x1C, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x1C, 0x01, 0x80, 0x00, "Off"}, + {0x1C, 0x01, 0x80, 0x80, "On"}, + + // Region + {0, 0xFE, 0, 6, "Region"}, + {0x1D, 0x01, 0xFF, 0x00, "Japan"}, + {0x1D, 0x01, 0xFF, 0x01, "USA / Canada (Jaleco license)"}, + {0x1D, 0x01, 0xFF, 0x03, "Korea"}, + {0x1D, 0x01, 0xFF, 0x05, "Hong Kong"}, + {0x1D, 0x01, 0xFF, 0x09, "Taiwan"}, + {0x1D, 0x01, 0xFF, 0x0F, "World"}, + + // Debug Dip + {0, 0xFE, 0, 2, "Debug test menu"}, + {0x1E, 0x82, 0x80, 0x00, "Off"}, + {0x1C, 0x00, 0x40, 0x00, NULL}, + {0x1E, 0x82, 0x80, 0x80, "On"}, + {0x1C, 0x00, 0x40, 0x00, NULL}, +}; + +static struct BurnDIPInfo s1945DIPList[] = { + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Coin slot"}, + {0x15, 0x01, 0x01, 0x00, "Same"}, + {0x15, 0x01, 0x01, 0x01, "Individual"}, + {0, 0xFE, 0, 8, "Coin 1"}, + {0x15, 0x01, 0x0E, 0x00, "1 coin = 1 credit"}, + {0x15, 0x01, 0x0E, 0x02, "2 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x04, "3 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x08, "1 coin = 2 credits"}, + {0x15, 0x01, 0x0E, 0x06, "1 coin = 3 credits"}, + {0x15, 0x01, 0x0E, 0x0A, "1 coin = 4 credits"}, + {0x15, 0x01, 0x0E, 0x0C, "1 coin = 5 credits"}, + {0x15, 0x82, 0x0E, 0x0E, "1 coin = 6 credits"}, + {0, 0xFE, 0, 8, "Coin 2"}, + {0x15, 0x01, 0x70, 0x00, "1 coin = 1 credit"}, + {0x15, 0x01, 0x70, 0x10, "2 coins = 1 credit"}, + {0x15, 0x01, 0x70, 0x20, "3 coins = 1 credit"}, + {0x15, 0x01, 0x70, 0x40, "1 coin = 2 credits"}, + {0x15, 0x01, 0x70, 0x30, "1 coin = 3 credits"}, + {0x15, 0x01, 0x70, 0x50, "1 coin = 4 credits"}, + {0x15, 0x01, 0x70, 0x60, "1 coin = 5 credits"}, + {0x15, 0x01, 0x70, 0x70, "1 coin = 6 credits"}, + {0, 0xFE, 0, 2, "Continue coin"}, + {0x15, 0x01, 0x80, 0x00, "Normal mode"}, + {0x15, 0x01, 0x80, 0x80, "Continue mode"}, + // DIP 2 + {0, 0xFE, 0, 2, "Screen"}, + {0x16, 0x01, 0x01, 0x00, "Normal"}, + {0x16, 0x01, 0x01, 0x01, "Reverse"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x16, 0x01, 0x02, 0x00, "Off"}, + {0x16, 0x01, 0x02, 0x02, "On"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Easy"}, + {0x16, 0x01, 0x0C, 0x08, "Difficult"}, + {0x16, 0x01, 0x0C, 0x0C, "More Difficult"}, + {0, 0xFE, 0, 4, "Number of fighters"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "1"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Extend fighters"}, + {0x16, 0x01, 0x40, 0x00, "Every 600,000 points"}, + {0x16, 0x01, 0x40, 0x40, "Every 800,000 points"}, + {0, 0xFE, 0, 2, "Test mode"}, + {0x16, 0x01, 0x80, 0x00, "Off"}, + {0x16, 0x01, 0x80, 0x80, "On"}, +}; + +static struct BurnDIPInfo tengaiDIPList[] = { + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + {0x17, 0xFF, 0xFF, 0x0F, NULL}, + + {0, 0xFE, 0, 2, "Coin slot"}, + {0x15, 0x82, 0x01, 0x00, "Same"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x01, 0x01, "Individual"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 9, "Coin 1"}, + {0x15, 0x01, 0x0E, 0x00, "1 coin = 1 credit"}, + {0x15, 0x01, 0x0E, 0x02, "2 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x04, "3 coins = 1 credit"}, + {0x15, 0x01, 0x0E, 0x08, "1 coin = 2 credits"}, + {0x15, 0x01, 0x0E, 0x06, "1 coin = 3 credits"}, + {0x15, 0x01, 0x0E, 0x0A, "1 coin = 4 credits"}, + {0x15, 0x01, 0x0E, 0x0C, "1 coin = 5 credits"}, + {0x15, 0x82, 0x0E, 0x0E, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x01, 0xFF, 0xFF, "Free play"}, + {0, 0xFE, 0, 9, "Coin 2"}, + {0x15, 0x82, 0x70, 0x00, "1 coin = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x10, "2 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x20, "3 coins = 1 credit"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x40, "1 coin = 2 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x30, "1 coin = 3 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x50, "1 coin = 4 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x60, "1 coin = 5 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x70, 0x70, "1 coin = 6 credits"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0xFF, 0xFF, "Free play"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0, 0xFE, 0, 2, "Continue coin"}, + {0x15, 0x82, 0x80, 0x00, "Normal mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + {0x15, 0x82, 0x80, 0x80, "Continue mode"}, + {0x15, 0x00, 0xFF, 0xFF, NULL}, + // DIP 2 + {0, 0xFE, 0, 2, NULL}, + {0x16, 0x01, 0x01, 0x00, "Normal screen"}, + {0x16, 0x01, 0x01, 0x01, "Invert screen"}, + {0, 0xFE, 0, 2, "Demo sounds"}, + {0x16, 0x01, 0x02, 0x00, "Disabled"}, + {0x16, 0x01, 0x02, 0x02, "Enabled"}, + {0, 0xFE, 0, 4, "Difficulty"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Easy"}, + {0x16, 0x01, 0x0C, 0x08, "Hard"}, + {0x16, 0x01, 0x0C, 0x0C, "Hardest"}, + {0, 0xFE, 0, 4, "Lives"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "1"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "4"}, + {0, 0xFE, 0, 2, "Bonus life"}, + {0x16, 0x01, 0x40, 0x00, "600K"}, + {0x16, 0x01, 0x40, 0x40, "800K"}, +}; + +static struct BurnDIPInfo NoRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, +}; + +static struct BurnDIPInfo samuraiaRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 5, "Region"}, + {0x17, 0x01, 0xFF, 0x00, "World"}, + {0x17, 0x01, 0xFF, 0x10, "USA / Canada"}, + {0x17, 0x01, 0xFF, 0x20, "Korea"}, + {0x17, 0x01, 0xFF, 0x40, "Hong Kong"}, + {0x17, 0x01, 0xFF, 0x80, "Taiwan"}, +}; + +static struct BurnDIPInfo gunbirdRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 5, "Region"}, + {0x17, 0x01, 0xFF, 0x00, "World"}, + {0x17, 0x01, 0xFF, 0x01, "USA / Canada"}, + {0x17, 0x01, 0xFF, 0x02, "Korea"}, + {0x17, 0x01, 0xFF, 0x04, "Hong Kong"}, + {0x17, 0x01, 0xFF, 0x08, "Taiwan"}, +}; + +static struct BurnDIPInfo s1945aRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x01, NULL}, + + // Region + {0, 0xFE, 0, 2, "Region"}, + {0x17, 0x01, 0xFF, 0x00, "Japan"}, + {0x17, 0x01, 0xFF, 0x01, "World"}, +}; + +static struct BurnDIPInfo tengaiRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 5, "Region"}, + {0x17, 0x01, 0xFF, 0x01, "U.S.A. & Canada"}, + {0x17, 0x01, 0xFF, 0x02, "Korea"}, + {0x17, 0x01, 0xFF, 0x04, "Hong Kong"}, + {0x17, 0x01, 0xFF, 0x08, "Taiwan"}, + {0x17, 0x01, 0xFF, 0x00, "World"}, +}; + +static struct BurnDIPInfo tengaijRegionDIPList[] = { + // Defaults + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 2, "Region"}, + {0x17, 0x01, 0xFF, 0x00, "Japan"}, + {0x17, 0x01, 0xFF, 0x0F, "World"}, +}; + +STDDIPINFOEXT(samuraia, samuraia, samuraiaRegion) +STDDIPINFOEXT(sngkace, samuraia, NoRegion) + +STDDIPINFO(btlkroad) + +STDDIPINFOEXT(gunbirdWorld, gunbird, gunbirdRegion) +STDDIPINFOEXT(gunbird, gunbird, NoRegion) + +STDDIPINFOEXT(s1945World, s1945, gunbirdRegion) +STDDIPINFOEXT(s1945, s1945, NoRegion) +STDDIPINFOEXT(s1945a, s1945, s1945aRegion) + +//STDDIPINFO(tengai) +STDDIPINFOEXT(tengai, tengai, tengaiRegion) +STDDIPINFOEXT(tengaij, tengai, tengaijRegion) + +// ---------------------------------------------------------------------------- +// Z80 banswitch + +static void samuraiaZ80SetBank(INT32 nBank) +{ + nBank &= 0x03; + if (nBank != nPsikyoZ80Bank) { + UINT8* nStartAddress = PsikyoZ80ROM + (nBank << 15); + ZetMapArea(0x8000, 0xFFFF, 0, nStartAddress); + ZetMapArea(0x8000, 0xFFFF, 2, nStartAddress); + + nPsikyoZ80Bank = nBank; + } + + return; +} + +static void gunbirdZ80SetBank(INT32 nBank) +{ + nBank &= 0x03; + if (nBank != nPsikyoZ80Bank) { + UINT8* nStartAddress = PsikyoZ80ROM + 0x00200 + (nBank << 15); + ZetMapArea(0x8200, 0xFFFF, 0, nStartAddress); + ZetMapArea(0x8200, 0xFFFF, 2, nStartAddress); + + nPsikyoZ80Bank = nBank; + } + + return; +} + +// ---------------------------------------------------------------------------- +// CPU synchronisation + +static inline void PsikyoSynchroniseZ80(INT32 nExtraCycles) +{ + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; + + if (nCycles <= ZetTotalCycles()) { + return; + } + + nCycles68KSync = nCycles - nExtraCycles; + + BurnTimerUpdate(nCycles); +} + +// Callbacks for the FM chip + +static void PsikyoFMIRQHandler(INT32, INT32 nStatus) +{ +// bprintf(PRINT_NORMAL, _T(" - IRQ -> %i.\n"), nStatus); + + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 PsikyoSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double PsikyoGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +// ---------------------------------------------------------------------------- +// Z80 I/O handlers + +UINT8 __fastcall samuraiaZ80In(UINT16 nAddress) +{ + switch (nAddress & 0xFF) { + case 0x00: + return BurnYM2610Read(0); + case 0x02: + return BurnYM2610Read(2); + case 0x08: // Read sound command +// bprintf(PRINT_NORMAL, _T(" - Sound command received (0x%02X).\n"), nSoundlatch); + return nSoundlatch; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 read port 0x%04X.\n"), nAddress); +// } + } + + return 0; +} + +void __fastcall samuraiaZ80Out(UINT16 nAddress, UINT8 nValue) +{ + switch (nAddress & 0x0FF) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + BurnYM2610Write(nAddress & 3, nValue); + break; + + case 0x04: + samuraiaZ80SetBank(nValue); + break; + + case 0x0C: // Write reply to sound commands +// bprintf(PRINT_NORMAL, _T(" - Sound reply sent (0x%02X).\n"), nValue); + +#if 1 && defined USE_SPEEDHACKS + if (!nSoundlatchAck && ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEnd(); + } +#endif + + nSoundlatchAck = 1; + + break; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 port 0x%04X -> 0x%02X.\n"), nAddress, nValue); +// } + } +} + +UINT8 __fastcall gunbirdZ80In(UINT16 nAddress) +{ + switch (nAddress & 0xFF) { + case 0x04: +// bprintf(PRINT_NORMAL, _T(" read 0 %6i\n"), ZetTotalCycles()); + return BurnYM2610Read(0); + case 0x06: +// bprintf(PRINT_NORMAL, _T(" read 2 %6i\n"), ZetTotalCycles()); + return BurnYM2610Read(2); + case 0x08: // Read sound command +// bprintf(PRINT_NORMAL, _T(" - Sound command received (0x%02X).\n"), nSoundlatch); + return nSoundlatch; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 read port 0x%04X.\n"), nAddress); +// } + } + + return 0; +} + +void __fastcall gunbirdZ80Out(UINT16 nAddress, UINT8 nValue) +{ + switch (nAddress & 0x0FF) { + case 0x00: + gunbirdZ80SetBank(nValue >> 4); + break; + case 0x04: + case 0x05: + case 0x06: + case 0x07: { + BurnYM2610Write(nAddress & 3, nValue); + break; + } + case 0x0C: // Write reply to sound commands +// bprintf(PRINT_NORMAL, _T(" - Sound reply sent (0x%02X).\n"), nValue); + +#if 1 && defined USE_SPEEDHACKS + if (!nSoundlatchAck && ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEnd(); + } +#endif + + nSoundlatchAck = 1; + + break; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 port 0x%04X -> 0x%02X.\n"), nAddress, nValue); +// } + } +} + +UINT8 __fastcall tengaiZ80In(UINT16 nAddress) +{ + switch (nAddress & 0xFF) { + case 0x08: +// bprintf(PRINT_NORMAL, _T(" read 0 %6i\n"), ZetTotalCycles()); + return BurnYMF278BReadStatus(); + case 0x10: // Read sound command +// bprintf(PRINT_NORMAL, _T(" - Sound command received (0x%02X).\n"), nSoundlatch); + return nSoundlatch; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 read port 0x%04X.\n"), nAddress); +// } + } + + return 0; +} + +void __fastcall tengaiZ80Out(UINT16 nAddress, UINT8 nValue) +{ + switch (nAddress & 0x0FF) { + case 0x00: + gunbirdZ80SetBank(nValue >> 4); + break; + case 0x08: + case 0x0A: + case 0x0C: { + BurnYMF278BSelectRegister((nAddress >> 1) & 3, nValue); + break; + } + case 0x09: + case 0x0B: + case 0x0D: { + BurnYMF278BWriteRegister((nAddress >> 1) & 3, nValue); + break; + } + case 0x18: // Write reply to sound commands +// bprintf(PRINT_NORMAL, _T(" - Sound reply sent (0x%02X).\n"), nValue); + +#if 1 && defined USE_SPEEDHACKS + if (!nSoundlatchAck && ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEnd(); + } +#endif + + nSoundlatchAck = 1; + + break; + +// default: { +// bprintf(PRINT_NORMAL, _T(" - Z80 port 0x%04X -> 0x%02X.\n"), nAddress, nValue); +// } + } +} + +// ---------------------------------------------------------------------------- +// 68K memory handlers + +static inline void SendSoundCommand(const INT8 nCommand) +{ +// bprintf(PRINT_NORMAL, _T(" - Sound command sent (0x%02X).\n"), nCommand); + + PsikyoSynchroniseZ80(0); + + nSoundlatch = nCommand; + nSoundlatchAck = 0; + + ZetNmi(); +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall samuraiaReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0] >> 8; + case 0xC00001: + return ~DrvInput[0] & 0xFF; + case 0xC00004: // DIPs + return ~DrvInput[2] >> 8; + case 0xC00005: + return ~DrvInput[2] & 0xFF; + case 0xC00006: // Region + return ~DrvInput[3] >> 8; + case 0xC00007: + return ~DrvInput[3] & 0xFF; + case 0xC00008: { // Inputs / Sound CPU status + return ~DrvInput[1] >> 8; + case 0xC80009: +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0100); + if (!nSoundlatchAck) { + return ~DrvInput[1] & 0xFF; + } + } +#else +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~DrvInput[1] & 0xFF; + } +#endif + return ~(DrvInput[1] | 0x80) & 0xFF; + } + case 0xC0000B: // VBlank + return ~bVBlank; + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); +// } + } + return 0; +} + +UINT16 __fastcall samuraiaReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0]; + case 0xC00004: // DIPs + return ~DrvInput[2]; + case 0xC00006: // + return ~DrvInput[3]; + case 0xC00008: { // Inputs / Sound CPU status +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0100); + if (!nSoundlatchAck) { + return ~DrvInput[1]; + } + } +#else +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~DrvInput[1]; + } +#endif + return ~(DrvInput[1] | 0x80); + } + case 0xC0000A: // VBlank + return ~bVBlank; + + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); +// } + } + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall gunbirdReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0] >> 8; + case 0xC00001: + return ~DrvInput[0] & 0xFF; + case 0xC00002: // Inputs / Sound CPU status + return ~DrvInput[1] >> 8; + case 0xC00003: +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0100); + if (!nSoundlatchAck) { + return ~DrvInput[1] & 0xFF; + } + } +#else +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~DrvInput[1] & 0xFF; + } +#endif + return ~(DrvInput[1] | 0x80) & 0xFF; + case 0xC00004: // DIPs + return ~DrvInput[2] >> 8; + case 0xC00005: + return ~DrvInput[2] & 0xFF; + case 0xC00006: // Region / VBlank + return ~DrvInput[3] >> 8; + case 0xC00007: + return ~(DrvInput[3] | (bVBlank << 7)) & 0xFF; + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); +// } + } + return 0; +} + +UINT16 __fastcall gunbirdReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0]; + case 0xC00002: { // Inputs / Sound CPU status +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0100); + if (!nSoundlatchAck) { + return ~DrvInput[1]; + } + } +#else + bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~DrvInput[1]; + } +#endif + return ~(DrvInput[1] | 0x80); + } + case 0xC00004: // DIPs + return ~DrvInput[2]; + case 0xC00006: // Region / VBlank + return ~(DrvInput[3] | (bVBlank << 7)); + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); +// } + } + return 0; +} + +void __fastcall gunbirdWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0xC00011: // Sound latch + SendSoundCommand(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall gunbirdWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0xC00012: // Sound latch + SendSoundCommand(wordValue & 0xFF); + break; + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); +// } + } +} + +// ---------------------------------------------------------------------------- + +static UINT8 s1945_table[256] = { + 0x00, 0x00, 0x64, 0xae, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc, + 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc5, 0x1e, + 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xac, 0x5c, 0x00, 0x00, 0x2b, 0xc0 +}; + +static UINT8 s1945j_table[256] = { + 0x00, 0x00, 0x64, 0xb6, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc, + 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc5, 0x92, + 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xac, 0x64, 0x00, 0x00, 0x2b, 0xc0 +}; + +static UINT8 s1945a_table[256] = { + 0x00, 0x00, 0x64, 0xbe, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc, + 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc7, 0x2a, + 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xad, 0x4c, 0x00, 0x00, 0x2b, 0xc0 +}; + +static UINT8 s1945_mcu_direction, s1945_mcu_latch1, s1945_mcu_latch2, s1945_mcu_inlatch, s1945_mcu_index; +static UINT8 s1945_mcu_latching, s1945_mcu_mode, s1945_mcu_control, s1945_mcu_bctrl; +static const UINT8 *s1945_mcu_table; + +static INT32 TengaiMCUScan(INT32 nAction, INT32 *pnMin) +{ + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020998; + } + + SCAN_VAR(s1945_mcu_direction); + SCAN_VAR(s1945_mcu_latch1); + SCAN_VAR(s1945_mcu_latch2); + SCAN_VAR(s1945_mcu_inlatch); + SCAN_VAR(s1945_mcu_index); + SCAN_VAR(s1945_mcu_latching); + SCAN_VAR(s1945_mcu_mode); + SCAN_VAR(s1945_mcu_control); + SCAN_VAR(s1945_mcu_bctrl); + + if (nAction & ACB_WRITE) { + PsikyoSetTileBank(1, (s1945_mcu_bctrl >> 6) & 3); + PsikyoSetTileBank(0, (s1945_mcu_bctrl >> 4) & 3); + } + + return 0; +} + +static void TengaiMCUInit(const UINT8 *mcu_table) +{ + s1945_mcu_direction = 0x00; + s1945_mcu_inlatch = 0xff; + s1945_mcu_latch1 = 0xff; + s1945_mcu_latch2 = 0xff; + s1945_mcu_latching = 0x5; + s1945_mcu_control = 0xff; + s1945_mcu_index = 0; + s1945_mcu_mode = 0; + s1945_mcu_table = mcu_table; + s1945_mcu_bctrl = 0x00; +} + +void tengaiMCUWrite(UINT32 offset, UINT8 data) +{ + switch (offset) { + case 0x06: + s1945_mcu_inlatch = data; + break; + case 0x07: + PsikyoSetTileBank(1, (data >> 6) & 3); + PsikyoSetTileBank(0, (data >> 4) & 3); + s1945_mcu_bctrl = data; + break; + case 0x08: + s1945_mcu_control = data; + break; + case 0x09: + s1945_mcu_direction = data; + break; + case 0x0b: + switch (data | (s1945_mcu_direction ? 0x100 : 0)) { + case 0x11c: + s1945_mcu_latching = 5; + s1945_mcu_index = s1945_mcu_inlatch; + break; + case 0x013: +// logerror("MCU: Table read index %02x\n", s1945_mcu_index); + s1945_mcu_latching = 1; + s1945_mcu_latch1 = s1945_mcu_table[s1945_mcu_index]; + break; + case 0x113: + s1945_mcu_mode = s1945_mcu_inlatch; + if(s1945_mcu_mode == 1) { + s1945_mcu_latching &= ~1; + s1945_mcu_latch2 = 0x55; + } else { + // Go figure. + s1945_mcu_latching &= ~1; + s1945_mcu_latching |= 2; + } + s1945_mcu_latching &= ~4; + s1945_mcu_latch1 = s1945_mcu_inlatch; + break; + case 0x010: + case 0x110: + s1945_mcu_latching |= 4; + break; + default: +// logerror("MCU: function %02x, direction %02x, latch1 %02x, latch2 %02x (%x)\n", data, s1945_mcu_direction, s1945_mcu_latch1, s1945_mcu_latch2, activecpu_get_pc()); + break; + } + break; +// default: +// logerror("MCU.w %x, %02x (%x)\n", offset, data, activecpu_get_pc()); + } +} + +UINT16 tengaiMCURead(UINT32 offset) +{ + switch (offset) { + case 0: { + UINT16 res; + if (s1945_mcu_control & 16) { + res = s1945_mcu_latching & 4 ? 0xff00 : s1945_mcu_latch1 << 8; + s1945_mcu_latching |= 4; + } else { + res = s1945_mcu_latching & 1 ? 0xff00 : s1945_mcu_latch2 << 8; + s1945_mcu_latching |= 1; + } + res |= s1945_mcu_bctrl & 0x00f0; + return res; + } + case 1: + return (s1945_mcu_latching << 8) | 0x0800; + } + + return 0; +} + +UINT8 __fastcall tengaiReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0] >> 8; + case 0xC00001: + return ~DrvInput[0] & 0xFF; + case 0xC00002: // Inputs / Sound CPU status + return ~DrvInput[1] >> 8; + case 0xC00003: +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0200); + if (!nSoundlatchAck) { + return ~(DrvInput[1] | 0x04) & 0xFF; + } + } +#else +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~(DrvInput[1] | 0x04) & 0xFF; + } +#endif + return ~(DrvInput[1] | 0x84) & 0xFF; + case 0xC00004: // DIPs + return ~DrvInput[2] >> 8; + case 0xC00005: + return ~DrvInput[2] & 0xFF; + case 0xC00006: // Region / MCU + return tengaiMCURead(0) >> 8; + case 0xC00007: + return ((~DrvInput[3] & 0x0F) | tengaiMCURead(0)) & 0xFF; + case 0xC00008: // MCU + return tengaiMCURead(1) >> 8; + case 0xC00009: + return tengaiMCURead(1) & 0xFF; + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); +// } + } + return 0; +} + +UINT16 __fastcall tengaiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0xC00000: // Joysticks + return ~DrvInput[0]; + case 0xC00002: { // Inputs / Sound CPU status +#if 1 && defined USE_SPEEDHACKS +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + if (!nSoundlatchAck) { + PsikyoSynchroniseZ80(0x0200); + if (!nSoundlatchAck) { + return ~(DrvInput[1] | 0x04); + } + } +#else +// bprintf(PRINT_NORMAL, _T(" - Sound reply read.\n")); + PsikyoSynchroniseZ80(0); + if (!nSoundlatchAck) { + return ~(DrvInput[1] | 0x04); + } +#endif + return ~(DrvInput[1] | 0x84); + } + case 0xC00004: // DIPs + return ~DrvInput[2]; + case 0xC00006: // Region / MCU + return (~DrvInput[3] & 0x0F) | tengaiMCURead(0); + case 0xC00008: // MCU + return tengaiMCURead(1); + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); +// } + } + return 0; +} + +void __fastcall tengaiWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0xC00004: + case 0xC00005: + case 0xC00006: + case 0xC00007: + case 0xC00008: + case 0xC00009: + case 0xC0000A: + case 0xC0000B: + tengaiMCUWrite(sekAddress & 0x0F, byteValue); + break; + + case 0xC00011: // Sound latch + SendSoundCommand(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall tengaiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0xC00004: + case 0xC00005: + case 0xC00006: + case 0xC00007: + case 0xC00008: + case 0xC00009: + case 0xC0000A: + case 0xC0000B: + tengaiMCUWrite((sekAddress & 0x0F), wordValue >> 8); + tengaiMCUWrite((sekAddress & 0x0F) + 1, wordValue & 0xFF); + break; + + case 0xC00010: // Sound latch + SendSoundCommand(wordValue & 0xFF); + break; + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); +// } + } +} + +// ---------------------------------------------------------------------------- + +void __fastcall PsikyoWriteBytePalette(UINT32 sekAddress, UINT8 byteValue) +{ + PsikyoPalWriteByte(sekAddress & 0x1FFF, byteValue); +} + +void __fastcall PsikyoWriteWordPalette(UINT32 sekAddress, UINT16 wordValue) +{ + PsikyoPalWriteWord(sekAddress & 0x1FFF, wordValue); +} + +// ---------------------------------------------------------------------------- + +static INT32 DrvExit() +{ + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: + case PSIKYO_HW_GUNBIRD: { + BurnYM2610Exit(); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + BurnYMF278BExit(); + break; + } + } + + PsikyoSpriteExit(); + PsikyoTileExit(); + PsikyoPalExit(); + + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + { + SekOpen(0); + SekReset(); + SekClose(); + } + + { + ZetOpen(0); + + nPsikyoZ80Bank = -1; + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: { + samuraiaZ80SetBank(0); + break; + } + case PSIKYO_HW_GUNBIRD: + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + gunbirdZ80SetBank(0); + break; + } + } + + ZetReset(); + + ZetClose(); + } + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: + case PSIKYO_HW_GUNBIRD: { + BurnYM2610Reset(); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + BurnYMF278BReset(); + break; + } + } + + nSoundlatch = 0; + nSoundlatchAck = 1; + + nCyclesDone[0] = nCyclesDone[1] = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + PsikyoPalUpdate(); + PsikyoTileRender(); + + return 0; +} + +static INT32 samuraiaCheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (bVBlank && nCurrentPC >= 0x000462 && nCurrentPC <= 0x00046E) { + + // S1945's idle loop increases this location as it loops; ensure it's increased enough + *((UINT32*)(Psikyo68KRAM + 0x0218)) += 1000; + + return 1; + } +#endif + + return 0; +} + +static INT32 gunbirdCheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (bVBlank && nCurrentPC >= 0x015E68 && nCurrentPC <= 0x015E76) { + + // Gunbird's idle loop increases this location as it loops; ensure it's increased enough + *((UINT32*)(Psikyo68KRAM + 0x0214)) += 1000; + + return 1; + } +#endif + + return 0; +} + +static INT32 gunbirdjCheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (bVBlank && nCurrentPC >= 0x015EA6 && nCurrentPC <= 0x015EB4) { + + // Gunbird's idle loop increases this location as it loops; ensure it's increased enough + *((UINT32*)(Psikyo68KRAM + 0x0214)) += 1000; + + return 1; + } +#endif + + return 0; +} + +static INT32 gunbirdkCheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (bVBlank && nCurrentPC >= 0x015E70 && nCurrentPC <= 0x015E7E) { + + // Gunbird's idle loop increases this location as it loops; ensure it's increased enough + *((UINT32*)(Psikyo68KRAM + 0x0214)) += 1000; + + return 1; + } +#endif + + return 0; +} + +static INT32 s1945jnCheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (bVBlank && nCurrentPC >= 0x019646 && nCurrentPC <= 0x019654) { + + // S1945's idle loop increases this location as it loops; ensure it's increased enough + *((UINT32*)(Psikyo68KRAM + 0x71F8)) += 1000; + + return 1; + } +#endif + + return 0; +} + +static INT32 psikyoCheckSleep(INT32) +{ +// bprintf(PRINT_NORMAL, "0x%06X\n", SekGetPC(-1)); + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nCyclesVBlank; + INT32 nInterleave = 16; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x0000; // Joysticks + DrvInput[1] = 0x0000; + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << (i + 8); + DrvInput[0] |= (DrvJoy2[i] & 1) << (i + 0); + + DrvInput[1] |= (DrvInp1[i] & 1) << (i + 0); + DrvInput[1] |= (DrvInp2[i] & 1) << (i + 8); + } + + SekNewFrame(); + ZetNewFrame(); + + if (nPrevBurnCPUSpeedAdjust != nBurnCPUSpeedAdjust) { + // 68K CPU clock is 16MHz, modified by nBurnCPUSpeedAdjust + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (INT32)(256.0 * 15625.0 / 263.5)); + // Z80 CPU clock is always 4MHz + nCyclesTotal[1] = (INT32)(4000000.0 / (15625.0 / 263.5)); + + // 68K cycles executed each scanline + SekSetCyclesScanline((INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (256 * 15625))); + + nPrevBurnCPUSpeedAdjust = nBurnCPUSpeedAdjust; + } + + nCyclesVBlank = nCyclesTotal[0] * (INT32)(224.0 * 2.0) / (INT32)(263.5 * 2.0); + bVBlank = 0x01; + + SekOpen(0); + ZetOpen(0); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + for (INT32 i = 1; i <= nInterleave; i++) { + + // Run 68000 + INT32 nNext = i * nCyclesTotal[0] / nInterleave; + + // See if we need to trigger the VBlank interrupt + if (bVBlank && nNext >= nCyclesVBlank) { + if (nCyclesDone[0] < nCyclesVBlank) { + nCyclesSegment = nCyclesVBlank - nCyclesDone[0]; + if (!CheckSleep(0)) { // See if this CPU is busywaiting + nCyclesDone[0] += SekRun(nCyclesSegment); + } else { + nCyclesDone[0] += SekIdle(nCyclesSegment); + } + } + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + PsikyoSpriteBuffer(); + + SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); + bVBlank = 0x00; + } + + nCyclesSegment = nNext - nCyclesDone[0]; + if (!CheckSleep(0)) { // See if this CPU is busywaiting + nCyclesDone[0] += SekRun(nCyclesSegment); + } else { + nCyclesDone[0] += SekIdle(nCyclesSegment); + } + } + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: + case PSIKYO_HW_GUNBIRD: { + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrame(nCyclesTotal[1]); + BurnYMF278BUpdate(nBurnSoundLen); + break; + } + default: { + ZetIdle(nCyclesTotal[1] - ZetTotalCycles()); + } + } + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + + ZetClose(); + SekClose(); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Loading + +static void Nibbleswap(UINT8* pData, INT32 nLen) +{ + for (INT32 i = nLen -2 ; i >= 0; i -= 2) { + UINT16 c = ((pData[i + 0] >> 4) | (pData[i + 0] << 8)) & 0x0F0F; + ((UINT16*)pData)[i + 0] = ((pData[i + 1] >> 4) | (pData[i + 1] << 8)) & 0x0F0F; + ((UINT16*)pData)[i + 1] = c; + } + + return; +} + +static INT32 samuraiaLoadRoms() +{ + // Load 68000 ROM + UINT8* pTemp = (UINT8*)malloc(0x080000); + if (pTemp == NULL) { + return 1; + } + + BurnLoadRom(pTemp + 0x000000, 0, 1); + BurnLoadRom(pTemp + 0x040000, 1, 1); + + for (INT32 i = 0; i < 0x020000; i++) { + ((UINT16*)Psikyo68KROM)[2 * i + 0] = ((UINT16*)pTemp)[0x000000 + i]; + ((UINT16*)Psikyo68KROM)[2 * i + 1] = ((UINT16*)pTemp)[0x020000 + i]; + } + + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + BurnLoadRom(PsikyoSpriteROM + 0x000000, 2, 1); + Nibbleswap(PsikyoSpriteROM, 0x200000); + + BurnLoadRom(PsikyoSpriteLUT, 3, 1); + + BurnLoadRom(PsikyoTileROM + 0x000000, 4, 1); + BurnLoadRom(PsikyoTileROM + 0x100000, 5, 1); + Nibbleswap(PsikyoTileROM, 0x200000); + + BurnLoadRom(PsikyoZ80ROM, 6, 1); + + BurnLoadRom(PsikyoSampleROM02, 7, 1); + + for (INT32 i = 0; i < 0x100000; i++) { + PsikyoSampleROM02[i] = ((PsikyoSampleROM02[i] & 0x80) >> 1) | ((PsikyoSampleROM02[i] & 0x40) << 1) | (PsikyoSampleROM02[i] & 0x3F); + } + + return 0; +} + +static INT32 gunbirdLoadRoms() +{ + // Load 68000 ROM + UINT8* pTemp = (UINT8*)malloc(0x100000); + if (pTemp == NULL) { + return 1; + } + + BurnLoadRom(pTemp + 0x000000, 0, 1); + BurnLoadRom(pTemp + 0x080000, 1, 1); + + for (INT32 i = 0; i < 0x040000; i++) { + ((UINT16*)Psikyo68KROM)[2 * i + 0] = ((UINT16*)pTemp)[0x000000 + i]; + ((UINT16*)Psikyo68KROM)[2 * i + 1] = ((UINT16*)pTemp)[0x040000 + i]; + } + + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + BurnLoadRom(PsikyoSpriteROM + 0x000000, 2, 1); + BurnLoadRom(PsikyoSpriteROM + 0x200000, 3, 1); + BurnLoadRom(PsikyoSpriteROM + 0x400000, 4, 1); + if (PsikyoSpriteROMSize > 0x0C00000) { + BurnLoadRom(PsikyoSpriteROM + 0x600000, 5, 1); + } + Nibbleswap(PsikyoSpriteROM, PsikyoSpriteROMSize >> 1); + + BurnLoadRom(PsikyoSpriteLUT, 6, 1); + + BurnLoadRom(PsikyoTileROM, 7, 1); + Nibbleswap(PsikyoTileROM, 0x200000); + + BurnLoadRom(PsikyoZ80ROM, 8, 1); + + BurnLoadRom(PsikyoSampleROM01, 9, 1); + BurnLoadRom(PsikyoSampleROM02, 10, 1); + + return 0; +} + +static INT32 s1945LoadRoms() +{ + // Load 68000 ROM + UINT8* pTemp = (UINT8*)malloc(0x100000); + if (pTemp == NULL) { + return 1; + } + + BurnLoadRom(pTemp + 0x000000, 0, 1); + BurnLoadRom(pTemp + 0x080000, 1, 1); + + for (INT32 i = 0; i < 0x040000; i++) { + ((UINT16*)Psikyo68KROM)[2 * i + 0] = ((UINT16*)pTemp)[0x000000 + i]; + ((UINT16*)Psikyo68KROM)[2 * i + 1] = ((UINT16*)pTemp)[0x040000 + i]; + } + + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + BurnLoadRom(PsikyoSpriteROM + 0x000000, 2, 1); + BurnLoadRom(PsikyoSpriteROM + 0x200000, 3, 1); + BurnLoadRom(PsikyoSpriteROM + 0x400000, 4, 1); + BurnLoadRom(PsikyoSpriteROM + 0x600000, 5, 1); + Nibbleswap(PsikyoSpriteROM, 0x800000); + + BurnLoadRom(PsikyoSpriteLUT, 6, 1); + + BurnLoadRom(PsikyoTileROM, 7, 1); + Nibbleswap(PsikyoTileROM, 0x200000); + + BurnLoadRom(PsikyoZ80ROM, 8, 1); + + BurnLoadRom(PsikyoSampleROM02, 9, 1); + + return 0; +} + +static void tengaiNibbleswap(UINT8* pData, INT32 nLen) +{ + for (INT32 i = nLen - 1; i >= 0; i--) { + ((UINT16*)pData)[i] = ((pData[i] >> 4) | (pData[i] << 8)) & 0x0F0F; + } + + return; +} + +static INT32 tengaiLoadRoms() +{ + // Load 68000 ROM + UINT8* pTemp = (UINT8*)malloc(0x100000); + if (pTemp == NULL) { + return 1; + } + + BurnLoadRom(pTemp + 0x000000, 0, 1); + BurnLoadRom(pTemp + 0x080000, 1, 1); + + for (INT32 i = 0; i < 0x040000; i++) { + ((UINT16*)Psikyo68KROM)[2 * i + 0] = ((UINT16*)pTemp)[0x000000 + i]; + ((UINT16*)Psikyo68KROM)[2 * i + 1] = ((UINT16*)pTemp)[0x040000 + i]; + } + + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + BurnLoadRom(PsikyoSpriteROM + 0x000000, 2, 1); + BurnLoadRom(PsikyoSpriteROM + 0x200000, 3, 1); + BurnLoadRom(PsikyoSpriteROM + 0x400000, 4, 1); + tengaiNibbleswap(PsikyoSpriteROM, 0x600000); + + BurnLoadRom(PsikyoSpriteLUT, 5, 1); + + BurnLoadRom(PsikyoTileROM, 6, 1); + tengaiNibbleswap(PsikyoTileROM, 0x400000); + + BurnLoadRom(PsikyoZ80ROM, 7, 1); + + BurnLoadRom(PsikyoSampleROM02 + 0x000000, 8, 1); + BurnLoadRom(PsikyoSampleROM02 + 0x200000, 9, 1); + + return 0; +} + +// ---------------------------------------------------------------------------- + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers + +static INT32 MemIndex() +{ + UINT8* Next; Next = Mem; + + Psikyo68KROM = Next; Next += 0x100000; // 68K program + PsikyoZ80ROM = Next; Next += 0x020000; // Z80 program + PsikyoSpriteROM = Next; Next += PsikyoSpriteROMSize; + PsikyoSpriteLUT = Next; Next += 0x040000; + PsikyoTileROM = Next; Next += PsikyoTileROMSize; + PsikyoSampleROM01 = Next; Next += PsikyoSampleROM01Size; + PsikyoSampleROM02 = Next; Next += PsikyoSampleROM02Size; + RamStart = Next; + Psikyo68KRAM = Next; Next += 0x020000; // 68K work RAM + if (PsikyoHardwareVersion == PSIKYO_HW_SAMURAIA) { + PsikyoZ80RAM = Next; Next += 0x000800; // Z80 work RAM + } else { + PsikyoZ80RAM = Next; Next += 0x000200; // Z80 work RAM + } + PsikyoTileRAM[0] = Next; Next += 0x002000; // Tile layer 0 + PsikyoTileRAM[1] = Next; Next += 0x002000; // Tile layer 1 + PsikyoTileRAM[2] = Next; Next += 0x004000; // Tile attribute RAM + PsikyoSpriteRAM = Next; Next += 0x002000; + PsikyoPalSrc = Next; Next += 0x002000; // palette + RamEnd = Next; + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + BurnSetRefreshRate(15625.0 / 263.5); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "samuraia") || !strcmp(BurnDrvGetTextA(DRV_NAME), "sngkace")) { + PsikyoHardwareVersion = PSIKYO_HW_SAMURAIA; + + CheckSleep = samuraiaCheckSleep; + + PsikyoTileROMSize = 0x0400000; + PsikyoSpriteROMSize = 0x0400000; + + PsikyoSampleROM01Size = 0; + PsikyoSampleROM02Size = 0x100000; + + bPsikyoClearBackground = false; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gunbird") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gunbirdj") || !strcmp(BurnDrvGetTextA(DRV_NAME), "gunbirdk") || !strcmp(BurnDrvGetTextA(DRV_NAME), "btlkroad") || !strcmp(BurnDrvGetTextA(DRV_NAME), "s1945jn")) { + PsikyoHardwareVersion = PSIKYO_HW_GUNBIRD; + + CheckSleep = psikyoCheckSleep; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gunbird")) { + CheckSleep = gunbirdCheckSleep; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gunbirdj")) { + CheckSleep = gunbirdjCheckSleep; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "gunbirdk")) { + CheckSleep = gunbirdkCheckSleep; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945jn")) { + CheckSleep = s1945jnCheckSleep; + } + + PsikyoTileROMSize = 0x0400000; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "btlkroad")) { + PsikyoSpriteROMSize = 0x0C00000; + } else { + PsikyoSpriteROMSize = 0x1000000; + } + + PsikyoSampleROM01Size = 0x080000; + PsikyoSampleROM02Size = 0x100000; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945jn")) { + bPsikyoClearBackground = false; + } else { + bPsikyoClearBackground = true; + } + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945") || !strcmp(BurnDrvGetTextA(DRV_NAME), "s1945j") || !strcmp(BurnDrvGetTextA(DRV_NAME), "s1945k") || !strcmp(BurnDrvGetTextA(DRV_NAME), "s1945a")) { + PsikyoHardwareVersion = PSIKYO_HW_S1945; + + CheckSleep = psikyoCheckSleep; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945j")) TengaiMCUInit(s1945j_table); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945") || !strcmp(BurnDrvGetTextA(DRV_NAME), "s1945k")) TengaiMCUInit(s1945_table); + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "s1945a")) TengaiMCUInit(s1945a_table); + + PsikyoTileROMSize = 0x0400000; + PsikyoSpriteROMSize = 0x1000000; + + PsikyoSampleROM01Size = 0; + PsikyoSampleROM02Size = 0x200000; + + bPsikyoClearBackground = false; + } + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "tengai") || !strcmp(BurnDrvGetTextA(DRV_NAME), "tengaij")) { + PsikyoHardwareVersion = PSIKYO_HW_TENGAI; + + CheckSleep = psikyoCheckSleep; + + TengaiMCUInit(s1945_table); + + PsikyoTileROMSize = 0x0800000; + PsikyoSpriteROMSize = 0x0C00000; + + PsikyoSampleROM01Size = 0; + PsikyoSampleROM02Size = 0x400000; + + bPsikyoClearBackground = false; + } + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: { + if (samuraiaLoadRoms()) { + return 1; + } + break; + } + case PSIKYO_HW_GUNBIRD: { + if (gunbirdLoadRoms()) { + return 1; + } + break; + } + case PSIKYO_HW_S1945: { + if (s1945LoadRoms()) { + return 1; + } + break; + } + case PSIKYO_HW_TENGAI: { + if (tengaiLoadRoms()) { + return 1; + } + break; + } + } + + { + // 68EC020 setup + SekInit(0, 0x68EC020); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Psikyo68KROM, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(PsikyoSpriteRAM, 0x400000, 0x401FFF, SM_RAM); + SekMapMemory(PsikyoTileRAM[0], 0x800000, 0x801FFF, SM_RAM); + SekMapMemory(PsikyoTileRAM[1], 0x802000, 0x803FFF, SM_RAM); + SekMapMemory(PsikyoTileRAM[2], 0x804000, 0x807FFF, SM_RAM); + SekMapMemory(Psikyo68KRAM, 0xFE0000, 0xFFFFFF, SM_RAM); + + SekMapMemory(PsikyoPalSrc, 0x600000, 0x601FFF, SM_ROM); // Palette RAM (write goes through handler) + SekMapHandler(1, 0x600000, 0x601FFF, SM_WRITE); // + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: { + SekSetReadWordHandler(0, samuraiaReadWord); + SekSetReadByteHandler(0, samuraiaReadByte); + SekSetWriteWordHandler(0, gunbirdWriteWord); + SekSetWriteByteHandler(0, gunbirdWriteByte); + break; + } + case PSIKYO_HW_GUNBIRD: { + SekSetReadWordHandler(0, gunbirdReadWord); + SekSetReadByteHandler(0, gunbirdReadByte); + SekSetWriteWordHandler(0, gunbirdWriteWord); + SekSetWriteByteHandler(0, gunbirdWriteByte); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + SekSetReadWordHandler(0, tengaiReadWord); + SekSetReadByteHandler(0, tengaiReadByte); + SekSetWriteWordHandler(0, tengaiWriteWord); + SekSetWriteByteHandler(0, tengaiWriteByte); + break; + } + } + + SekSetWriteWordHandler(1, PsikyoWriteWordPalette); + SekSetWriteByteHandler(1, PsikyoWriteBytePalette); + + SekClose(); + } + + { + // Z80 setup + ZetInit(1); + ZetOpen(0); + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: { + // fixed ROM + ZetMapArea(0x0000, 0x77FF, 0, PsikyoZ80ROM); + ZetMapArea(0x0000, 0x77FF, 2, PsikyoZ80ROM); + // Work RAM + ZetMapArea(0x7800, 0x7FFF, 0, PsikyoZ80RAM); + ZetMapArea(0x7800, 0x7FFF, 1, PsikyoZ80RAM); + ZetMapArea(0x7800, 0x7FFF, 2, PsikyoZ80RAM); + + ZetMemEnd(); + + ZetSetInHandler(samuraiaZ80In); + ZetSetOutHandler(samuraiaZ80Out); + break; + } + case PSIKYO_HW_GUNBIRD: { + // fixed ROM + ZetMapArea(0x0000, 0x7FFF, 0, PsikyoZ80ROM); + ZetMapArea(0x0000, 0x7FFF, 2, PsikyoZ80ROM); + // Work RAM + ZetMapArea(0x8000, 0x81FF, 0, PsikyoZ80RAM); + ZetMapArea(0x8000, 0x81FF, 1, PsikyoZ80RAM); + ZetMapArea(0x8000, 0x81FF, 2, PsikyoZ80RAM); + + ZetMemEnd(); + + ZetSetInHandler(gunbirdZ80In); + ZetSetOutHandler(gunbirdZ80Out); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + // fixed ROM + ZetMapArea(0x0000, 0x7FFF, 0, PsikyoZ80ROM); + ZetMapArea(0x0000, 0x7FFF, 2, PsikyoZ80ROM); + // Work RAM + ZetMapArea(0x8000, 0x81FF, 0, PsikyoZ80RAM); + ZetMapArea(0x8000, 0x81FF, 1, PsikyoZ80RAM); + ZetMapArea(0x8000, 0x81FF, 2, PsikyoZ80RAM); + + ZetMemEnd(); + ZetSetInHandler(tengaiZ80In); + ZetSetOutHandler(tengaiZ80Out); + break; + } + } + + ZetClose(); + } + + PsikyoPalInit(); + + PsikyoTileInit(PsikyoTileROMSize); + PsikyoSpriteInit(PsikyoSpriteROMSize); + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: + case PSIKYO_HW_GUNBIRD: { + BurnYM2610Init(8000000, PsikyoSampleROM02, &PsikyoSampleROM02Size, PsikyoSampleROM01, &PsikyoSampleROM01Size, &PsikyoFMIRQHandler, PsikyoSynchroniseStream, PsikyoGetTime, 0); + BurnTimerAttachZet(4000000); + break; + } + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + BurnYMF278BInit(0, PsikyoSampleROM02, &PsikyoFMIRQHandler, PsikyoSynchroniseStream); + BurnTimerAttachZet(4000000); + break; + } + } + + nPrevBurnCPUSpeedAdjust = -1; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// ---------------------------------------------------------------------------- +// Savestates / scanning + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + if (nAction & ACB_MEMORY_ROM) { // Scan all memory, devices & variables + ba.Data = Psikyo68KROM; + ba.nLen = 0x00100000; + ba.nAddress = 0; + ba.szName = "68K ROM"; + BurnAcb(&ba); + + ba.Data = PsikyoZ80ROM; + ba.nLen = 0x00020000; + ba.nAddress = 0; + ba.szName = "Z80 ROM"; + BurnAcb(&ba); + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + ba.Data = Psikyo68KRAM; + ba.nLen = 0x00020000; + ba.nAddress = 0; + ba.szName = "68K RAM"; + BurnAcb(&ba); + + ba.Data = PsikyoZ80RAM; + if (PsikyoHardwareVersion == PSIKYO_HW_SAMURAIA) { + ba.nLen = 0x0000800; + } else { + ba.nLen = 0x0000200; + } + ba.nAddress = 0; + ba.szName = "Z80 RAM"; + BurnAcb(&ba); + + ba.Data = PsikyoTileRAM[0]; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Tilemap 0"; + BurnAcb(&ba); + + ba.Data = PsikyoTileRAM[1]; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Tilemap 1"; + BurnAcb(&ba); + + ba.Data = PsikyoTileRAM[2]; + ba.nLen = 0x00004000; + ba.nAddress = 0; + ba.szName = "Tilemap attributes"; + BurnAcb(&ba); + + ba.Data = PsikyoSpriteRAM; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Sprite tables"; + BurnAcb(&ba); + + ba.Data = PsikyoPalSrc; + ba.nLen = 0x00002000; + ba.nAddress = 0; + ba.szName = "Palette"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + + SekScan(nAction); // Scan 68000 state + + ZetOpen(0); + ZetScan(nAction); // Scan Z80 state + ZetClose(); + + SCAN_VAR(nCyclesDone); + + SCAN_VAR(bVBlank); + + BurnYM2610Scan(nAction, pnMin); + + SCAN_VAR(nSoundlatch); SCAN_VAR(nSoundlatchAck); + + SCAN_VAR(nPsikyoZ80Bank); + + TengaiMCUScan(nAction, pnMin); + + if (nAction & ACB_WRITE) { + int nBank = nPsikyoZ80Bank; + nPsikyoZ80Bank = -1; + + switch (PsikyoHardwareVersion) { + case PSIKYO_HW_SAMURAIA: { + samuraiaZ80SetBank(nBank); + break; + } + case PSIKYO_HW_GUNBIRD: + case PSIKYO_HW_S1945: + case PSIKYO_HW_TENGAI: { + gunbirdZ80SetBank(nBank); + break; + } + } + + PsikyoRecalcPalette = 1; + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Rom information + +// Samurai Aces / Sengoku Ace + +static struct BurnRomInfo samuraiaRomDesc[] = { + { "4-u127.bin", 0x040000, 0x8C9911CA, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "5-u126.bin", 0x040000, 0xD20C3EF0, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x00A546CB, BRF_GRA }, // 2 Sprite data + + { "u11.bin", 0x040000, 0x11A04D91, BRF_GRA }, // 3 Sprite LUT + + { "u34.bin", 0x100000, 0xE6A75BD8, BRF_GRA }, // 4 Tile data + { "u35.bin", 0x100000, 0xC4CA0164, BRF_GRA }, // 5 + + { "3-u58.bin", 0x020000, 0x310F5C76, BRF_ESS | BRF_PRG }, // 6 CPU #1 code + + { "u68.bin", 0x100000, 0x9A7F6C34, BRF_SND }, // 7 YM2610 (delta-t) ADPCM data +}; + +STD_ROM_PICK(samuraia) +STD_ROM_FN(samuraia) + +static struct BurnRomInfo sngkaceRomDesc[] = { + { "1-u127.bin", 0x040000, 0x6C45B2F8, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "2-u126.bin", 0x040000, 0x845A6760, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x00A546CB, BRF_GRA }, // 2 Sprite data + + { "u11.bin", 0x040000, 0x11A04D91, BRF_GRA }, // 3 Sprite LUT + + { "u34.bin", 0x100000, 0xE6A75BD8, BRF_GRA }, // 4 Tile data + { "u35.bin", 0x100000, 0xC4CA0164, BRF_GRA }, // 5 + + { "3-u58.bin", 0x020000, 0x310F5C76, BRF_ESS | BRF_PRG }, // 6 CPU #1 code + + { "u68.bin", 0x100000, 0x9A7F6C34, BRF_SND }, // 7 YM2610 (delta-t) ADPCM data +}; + +STD_ROM_PICK(sngkace) +STD_ROM_FN(sngkace) + +struct BurnDriver BurnDrvSamuraiA = { + "samuraia", NULL, NULL, NULL, "1993", + "Samurai Aces (World)\0", NULL, "Psikyo / Banpresto", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, samuraiaRomInfo, samuraiaRomName, NULL, NULL, gunbirdInputInfo, samuraiaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvSngkAce = { + "sngkace", "samuraia", NULL, NULL, "1993", + "Sengoku Ace (Japan)\0", NULL, "Psikyo / Banpresto", "Psikyo 68EC020", + L"\u6226\u56FD\u30A8\u30FC\u30B9 (Japan)\0Sengoku Ace\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, sngkaceRomInfo, sngkaceRomName, NULL, NULL, gunbirdInputInfo, sngkaceDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +// Gunbird + +static struct BurnRomInfo gunbirdRomDesc[] = { + { "4.u46", 0x040000, 0xB78EC99D, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "5.u39", 0x040000, 0x925F095D, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x7D7E8A00, BRF_GRA }, // 2 Sprite data + { "u24.bin", 0x200000, 0x5E3FFC9D, BRF_GRA }, // 3 + { "u15.bin", 0x200000, 0xA827BFB5, BRF_GRA }, // 4 + { "u25.bin", 0x100000, 0xEF652E0C, BRF_GRA }, // 5 + + { "u3.bin", 0x040000, 0x0905AEB2, BRF_GRA }, // 6 Sprite LUT + + { "u33.bin", 0x200000, 0x54494E6B, BRF_GRA }, // 7 Tile data + + { "3.u71", 0x020000, 0x2168E4BA, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u64.bin", 0x080000, 0xE187ED4F, BRF_SND }, // 9 YM2610 ADPCM (delta-t) data + { "u56.bin", 0x100000, 0x9E07104D, BRF_SND }, // 10 YM2610 ADPCM data + + { "3020.u19", 0x000001, 0x00000000, BRF_OPT | BRF_NODUMP },// 11 + { "3021.u69", 0x000001, 0x00000000, BRF_OPT | BRF_NODUMP },// 12 +}; + +STD_ROM_PICK(gunbird) +STD_ROM_FN(gunbird) + +static struct BurnRomInfo gunbirdjRomDesc[] = { + { "1.u46", 0x040000, 0x474ABD69, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "2.u39", 0x040000, 0x3E3E661F, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x7D7E8A00, BRF_GRA }, // 2 Sprite data + { "u24.bin", 0x200000, 0x5E3FFC9D, BRF_GRA }, // 3 + { "u15.bin", 0x200000, 0xA827BFB5, BRF_GRA }, // 4 + { "u25.bin", 0x100000, 0xEF652E0C, BRF_GRA }, // 5 + + { "u3.bin", 0x040000, 0x0905AEB2, BRF_GRA }, // 6 Sprite LUT + + { "u33.bin", 0x200000, 0x54494E6B, BRF_GRA }, // 7 Tile data + + { "3.u71", 0x020000, 0x2168E4BA, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u64.bin", 0x080000, 0xE187ED4F, BRF_SND }, // 9 YM2610 ADPCM (delta-t) data + { "u56.bin", 0x100000, 0x9E07104D, BRF_SND }, // 10 YM2610 ADPCM data +}; + +STD_ROM_PICK(gunbirdj) +STD_ROM_FN(gunbirdj) + +static struct BurnRomInfo gunbirdkRomDesc[] = { + { "1k.u46", 0x080000, 0x745CEE52, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "2k.u39", 0x080000, 0x669632FB, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x7D7E8A00, BRF_GRA }, // 2 Sprite data + { "u24.bin", 0x200000, 0x5E3FFC9D, BRF_GRA }, // 3 + { "u15.bin", 0x200000, 0xA827BFB5, BRF_GRA }, // 4 + { "u25.bin", 0x100000, 0xEF652E0C, BRF_GRA }, // 5 + + { "u3.bin", 0x040000, 0x0905AEB2, BRF_GRA }, // 6 Sprite LUT + + { "u33.bin", 0x200000, 0x54494E6B, BRF_GRA }, // 7 Tile data + + { "k3.u71", 0x020000, 0x11994055, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u64.bin", 0x080000, 0xE187ED4F, BRF_SND }, // 9 YM2610 ADPCM (delta-t) data + { "u56.bin", 0x100000, 0x9E07104D, BRF_SND }, // 10 YM2610 ADPCM data +}; + +STD_ROM_PICK(gunbirdk) +STD_ROM_FN(gunbirdk) + +struct BurnDriver BurnDrvGunbird = { + "gunbird", NULL, NULL, NULL, "1994", + "Gunbird (World)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, gunbirdRomInfo, gunbirdRomName, NULL, NULL, gunbirdInputInfo, gunbirdWorldDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvGunbirdj = { + "gunbirdj", "gunbird", NULL, NULL, "1994", + "Gunbird (Japan)\0", NULL, "Psikyo", "Psikyo 68EC020", + L"Gunbird (Japan)\0\u30AC\u30F3\u30D0\u30FC\u30C9\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, gunbirdjRomInfo, gunbirdjRomName, NULL, NULL, gunbirdInputInfo, gunbirdDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvGunbirdk = { + "gunbirdk", "gunbird", NULL, NULL, "1994", + "Gunbird (Korea)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, gunbirdkRomInfo, gunbirdkRomName, NULL, NULL, gunbirdInputInfo, gunbirdDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +// Battle K-Road + +static struct BurnRomInfo btlkroadRomDesc[] = { + { "4-u46.bin", 0x040000, 0x8a7a28b4, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "5-u39.bin", 0x040000, 0x933561fa, BRF_ESS | BRF_PRG }, // 1 + + { "u14.bin", 0x200000, 0x282D89C3, BRF_GRA }, // 2 Sprite data + { "u24.bin", 0x200000, 0xBBE9D3D1, BRF_GRA }, // 3 + { "u15.bin", 0x200000, 0xD4D1B07C, BRF_GRA }, // 4 + { "", 0, 0, 0 }, // 5 + + { "u3.bin", 0x040000, 0x30D541ED, BRF_GRA }, // 6 Sprite LUT + + { "u33.bin", 0x200000, 0x4C8577F1, BRF_GRA }, // 7 Tile data + + { "3-u71.bin", 0x020000, 0x22411FAB, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u64.bin", 0x080000, 0x0F33049F, BRF_SND }, // 9 YM2610 ADPCM (delta-t) data + { "u56.bin", 0x100000, 0x51D73682, BRF_SND }, // 10 YM2610 ADPCM data + + { "tibpal16l8.u69", 260, 0x00000000, BRF_NODUMP }, // NO DUMP + { "tibpal16l8.u19", 260, 0x00000000, BRF_NODUMP }, // NO DUMP +}; + +STD_ROM_PICK(btlkroad) +STD_ROM_FN(btlkroad) + +struct BurnDriver BurnDrvBtlKRoad = { + "btlkroad", NULL, NULL, NULL, "1994", + "Battle K-Road\0", NULL, "Psikyo", "Psikyo 68EC020", + L"Battle K-Road\0Battle K-Road \u30D0\u30C8\u30EB\u30AF\u30ED\u30FC\u30C9\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VSFIGHT, 0, + NULL, btlkroadRomInfo, btlkroadRomName, NULL, NULL, btlkroadInputInfo, btlkroadDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 320, 224, 4, 3 +}; + +// Strikers 1945 (gunbird hardware) + +static struct BurnRomInfo s1945jnRomDesc[] = { + { "1-u46.bin", 0x080000, 0x45FA8086, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "2-u39.bin", 0x080000, 0x0152AB8C, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0x28A27FEE, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0xCA152A32, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xC5d60EA9, BRF_GRA }, // 4 + { "u23.bin", 0x200000, 0x48710332, BRF_GRA }, // 5 + + { "u1.bin", 0x040000, 0xDEE22654, BRF_GRA }, // 6 Sprite LUT + + { "u34.bin", 0x200000, 0xAAF83E23, BRF_GRA }, // 7 Tile data + + { "3-u71.bin", 0x020000, 0xE3E366BD, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u64.bin", 0x080000, 0xA44A4A9b, BRF_SND }, // 9 YM2610 ADPCM (delta-t) data + { "u56.bin", 0x100000, 0xFE1312C2, BRF_SND }, // 10 YM2610 ADPCM data +}; + +STD_ROM_PICK(s1945jn) +STD_ROM_FN(s1945jn) + +struct BurnDriver BurnDrvS1945jn = { + "s1945jn", "s1945", NULL, NULL, "1995", + "Strikers 1945 (Japan, unprotected)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945jnRomInfo, s1945jnRomName, NULL, NULL, gunbirdInputInfo, s1945DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +// Strikers 1945 + +static struct BurnRomInfo s1945RomDesc[] = { + { "2s.u40", 0x040000, 0x9B10062A, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "3s.u41", 0x040000, 0xF87E871A, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0x28A27FEE, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0xCA152A32, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xC5d60EA9, BRF_GRA }, // 4 + { "u23.bin", 0x200000, 0x48710332, BRF_GRA }, // 5 + + { "u1.bin", 0x040000, 0xDEE22654, BRF_GRA }, // 6 Sprite LUT + + { "u34.bin", 0x200000, 0xAAF83E23, BRF_GRA }, // 7 Tile data + + { "3-u63.bin", 0x020000, 0x42D40AE1, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u61.bin", 0x200000, 0xA839CF47, BRF_SND }, // 9 PCM data + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(s1945) +STD_ROM_FN(s1945) + +static struct BurnRomInfo s1945jRomDesc[] = { + { "1-u40.bin", 0x040000, 0xC00EB012, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "2-u41.bin", 0x040000, 0x3F5A134B, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0x28A27FEE, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0xCA152A32, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xC5d60EA9, BRF_GRA }, // 4 + { "u23.bin", 0x200000, 0x48710332, BRF_GRA }, // 5 + + { "u1.bin", 0x040000, 0xDEE22654, BRF_GRA }, // 6 Sprite LUT + + { "u34.bin", 0x200000, 0xAAF83E23, BRF_GRA }, // 7 Tile data + + { "3-u63.bin", 0x020000, 0x42D40AE1, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u61.bin", 0x200000, 0xA839CF47, BRF_SND }, // 9 PCM data + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(s1945j) +STD_ROM_FN(s1945j) + +static struct BurnRomInfo s1945kRomDesc[] = { + { "10.u40", 0x040000, 0x5a32af36, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "9.u41", 0x040000, 0x29cc6d7d, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0x28A27FEE, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0xCA152A32, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xC5d60EA9, BRF_GRA }, // 4 + { "u23.bin", 0x200000, 0x48710332, BRF_GRA }, // 5 + + { "u1.bin", 0x040000, 0xDEE22654, BRF_GRA }, // 6 Sprite LUT + + { "u34.bin", 0x200000, 0xAAF83E23, BRF_GRA }, // 7 Tile data + + { "3-u63.bin", 0x020000, 0x42D40AE1, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u61.bin", 0x200000, 0xA839CF47, BRF_SND }, // 9 PCM data + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(s1945k) +STD_ROM_FN(s1945k) + +static struct BurnRomInfo s1945aRomDesc[] = { + { "4-u40.bin", 0x040000, 0x29ffc217, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "5-u41.bin", 0x040000, 0xc3d3fb64, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0x28A27FEE, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0xCA152A32, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xC5d60EA9, BRF_GRA }, // 4 + { "u23.bin", 0x200000, 0x48710332, BRF_GRA }, // 5 + + { "u1.bin", 0x040000, 0xDEE22654, BRF_GRA }, // 6 Sprite LUT + + { "u34.bin", 0x200000, 0xAAF83E23, BRF_GRA }, // 7 Tile data + + { "3-u63.bin", 0x020000, 0x42D40AE1, BRF_ESS | BRF_PRG }, // 8 CPU #1 code + + { "u61.bin", 0x200000, 0xA839CF47, BRF_SND }, // 9 PCM data + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(s1945a) +STD_ROM_FN(s1945a) + +struct BurnDriver BurnDrvS1945 = { + "s1945", NULL, NULL, NULL, "1995", + "Strikers 1945\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945RomInfo, s1945RomName, NULL, NULL, gunbirdInputInfo, s1945WorldDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvS1945j = { + "s1945j", "s1945", NULL, NULL, "1995", + "Strikers 1945 (Japan)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945jRomInfo, s1945jRomName, NULL, NULL, gunbirdInputInfo, s1945DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvS1945k = { + "s1945k", "s1945", NULL, NULL, "1995", + "Strikers 1945 (Korea)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945kRomInfo, s1945kRomName, NULL, NULL, gunbirdInputInfo, s1945DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvS1945a = { + "s1945a", "s1945", NULL, NULL, "1995", + "Strikers 1945 (Alt)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945aRomInfo, s1945aRomName, NULL, NULL, gunbirdInputInfo, s1945aDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 224, 320, 3, 4 +}; + +// Tengai + +static struct BurnRomInfo tengaiRomDesc[] = { + { "5-u40.bin", 0x080000, 0x90088195, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "4-u41.bin", 0x080000, 0x0d53196c, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0xED42EF73, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0x8D21CAEE, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xEFE34EED, BRF_GRA }, // 4 + + { "u1.bin", 0x040000, 0x681D7D55, BRF_GRA }, // 5 Sprite LUT + + { "u34.bin", 0x400000, 0x2A2E2EEB, BRF_GRA }, // 6 Tile data + + { "1-u63.bin", 0x020000, 0x2025E387, BRF_ESS | BRF_PRG }, // 7 CPU #1 code + + { "u61.bin", 0x200000, 0xA63633C5, BRF_SND }, // 8 PCM data + { "u62.bin", 0x200000, 0x3AD0C357, BRF_SND }, // 9 + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(tengai) +STD_ROM_FN(tengai) + +struct BurnDriver BurnDrvTengai = { + "tengai", NULL, NULL, NULL, "1996", + "Tengai (world)\0", NULL, "Psikyo", "Psikyo 68EC020", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_PSIKYO, GBF_HORSHOOT, 0, + NULL, tengaiRomInfo, tengaiRomName, NULL, NULL, gunbirdInputInfo, tengaiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 320, 224, 4, 3 +}; + +static struct BurnRomInfo tengaijRomDesc[] = { + { "2-u40.bin", 0x080000, 0xAB6FE58A, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "3-u41.bin", 0x080000, 0x02E42E39, BRF_ESS | BRF_PRG }, // 1 + + { "u20.bin", 0x200000, 0xED42EF73, BRF_GRA }, // 2 Sprite data + { "u22.bin", 0x200000, 0x8D21CAEE, BRF_GRA }, // 3 + { "u21.bin", 0x200000, 0xEFE34EED, BRF_GRA }, // 4 + + { "u1.bin", 0x040000, 0x681D7D55, BRF_GRA }, // 5 Sprite LUT + + { "u34.bin", 0x400000, 0x2A2E2EEB, BRF_GRA }, // 6 Tile data + + { "1-u63.bin", 0x020000, 0x2025E387, BRF_ESS | BRF_PRG }, // 7 CPU #1 code + + { "u61.bin", 0x200000, 0xA63633C5, BRF_SND }, // 8 PCM data + { "u62.bin", 0x200000, 0x3AD0C357, BRF_SND }, // 9 + + { "4-u59.bin", 256, 0x00000000, BRF_NODUMP }, +}; + +STD_ROM_PICK(tengaij) +STD_ROM_FN(tengaij) + +struct BurnDriver BurnDrvTengaij = { + "tengaij", "tengai", NULL, NULL, "1996", + "Tengai\0Sengoku Blade - sengoku ace episode II\0", NULL, "Psikyo", "Psikyo 68EC020", + L"Tengai\0\u6226\u56FD\u30D6\u30EC\u30FC\u30C9 - sengoku ace episode II\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_PSIKYO, GBF_HORSHOOT, 0, + NULL, tengaijRomInfo, tengaijRomName, NULL, NULL, gunbirdInputInfo, tengaijDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &PsikyoRecalcPalette, 0x1000, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/psikyo/d_psikyosh.cpp b/src/burn/drivers/psikyo/d_psikyosh.cpp new file mode 100644 index 00000000..7cfcb321 --- /dev/null +++ b/src/burn/drivers/psikyo/d_psikyosh.cpp @@ -0,0 +1,1570 @@ +// FB Alpha Psikyo Sh2-based hardware driver module +// Based on MAME driver by David Haywood + +// To do! +// implement background zooming update. + + +#include "tiles_generic.h" +#include "psikyosh_render.h" +#include "burn_ymf278b.h" +#include "eeprom.h" +#include "sh2.h" + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *DrvSh2ROM; +static UINT8 *DrvSndROM; +static UINT8 *DrvEEPROM; +static UINT8 *DrvSh2RAM; +static UINT8 *DrvZoomRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvBgRAM; +static UINT8 *DrvVidRegs; + +static INT32 sample_offs; + +static INT32 graphics_min_max[2]; +static INT32 previous_graphics_bank; + +static UINT32 speedhack_address = ~0; +static UINT32 speedhack_pc[4] = { 0, 0, 0, 0 }; + +static UINT8 DrvReset; +static UINT32 DrvInputs; +static UINT8 DrvDips[2]; +static UINT8 DrvJoy1[32]; + +static struct BurnInputInfo Common2ButtonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 24, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 31, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 30, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 28, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 29, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 27, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 26, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 16, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 23, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 22, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 20, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 21, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 19, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 18, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common2Button) + +static struct BurnInputInfo Common3ButtonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 24, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 31, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 30, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 28, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 29, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 27, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 26, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 25, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 16, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 23, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 22, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 20, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 21, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 19, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 18, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 17, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common3Button) + +static struct BurnInputInfo Common4ButtonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy1 + 24, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 31, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 30, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 28, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 29, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 27, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 26, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 15, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 14, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy1 + 16, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy1 + 23, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy1 + 22, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy1 + 20, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy1 + 21, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 19, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 18, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 11, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, DrvJoy1 + 10, "p2 fire 4" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy1 + 4, "service" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, +}; + +STDINPUTINFO(Common4Button) + +static struct BurnDIPInfo DarakuDIPList[]= +{ + {0x16, 0xff, 0xff, 0x60, NULL }, + {0x17, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x16, 0x01, 0x40, 0x40, "Off" }, + {0x16, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x17, 0x01, 0x01, 0x00, "Japan" }, + {0x17, 0x01, 0x01, 0x01, "World" }, +}; + +STDDIPINFO(Daraku) + +static struct BurnDIPInfo S1945iiDIPList[]= +{ + {0x12, 0xff, 0xff, 0x60, NULL }, + {0x13, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x12, 0x01, 0x20, 0x20, "Off" }, + {0x12, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x12, 0x01, 0x40, 0x40, "Off" }, + {0x12, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x13, 0x01, 0x01, 0x00, "Japan" }, + {0x13, 0x01, 0x01, 0x01, "World" }, +}; + +STDDIPINFO(S1945ii) + +static struct BurnDIPInfo DragnblzDIPList[]= +{ + {0x14, 0xff, 0xff, 0x20, NULL }, + {0x15, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + +// {0 , 0xfe, 0 , 2, "Debug" }, +// {0x14, 0x01, 0x40, 0x40, "Off" }, +// {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x01, 0x00, "Japan" }, + {0x15, 0x01, 0x01, 0x01, "World" }, +}; + +STDDIPINFO(Dragnblz) + +static struct BurnDIPInfo SoldividDIPList[]= +{ + {0x14, 0xff, 0xff, 0x60, NULL }, + {0x15, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x01, 0x00, "Japan" }, + {0x15, 0x01, 0x01, 0x01, "World" }, +}; + +STDDIPINFO(Soldivid) + +static struct BurnDIPInfo Gunbird2DIPList[]= +{ + {0x14, 0xff, 0xff, 0x60, NULL }, + {0x15, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x03, 0x00, "Japan" }, + {0x15, 0x01, 0x03, 0x01, "International Ver A." }, + {0x15, 0x01, 0x03, 0x02, "International Ver B." }, +}; + +STDDIPINFO(Gunbird2) + +static struct BurnDIPInfo S1945iiiDIPList[]= +{ + {0x14, 0xff, 0xff, 0x60, NULL }, + {0x15, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x03, 0x00, "Japan" }, + {0x15, 0x01, 0x03, 0x02, "International Ver A." }, + {0x15, 0x01, 0x03, 0x01, "International Ver B." }, +}; + +STDDIPINFO(S1945iii) + +static struct BurnDIPInfo Tgm2DIPList[]= +{ + {0x14, 0xff, 0xff, 0x60, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Debug" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Tgm2) + +//------------------------------------------------------------------------------------- + +static void graphics_bank() +{ + INT32 bank = (*((UINT32*)(DrvVidRegs + 0x10)) & 0x1ff) * 0x20000; + + if (bank != previous_graphics_bank) + { + previous_graphics_bank = bank; + + bank -= graphics_min_max[0]; + + if (bank < 0 || bank >= graphics_min_max[1]) + bank = graphics_min_max[1] - graphics_min_max[0]; + + Sh2MapMemory(pPsikyoshTiles + bank, 0x3060000, 0x307ffff, SM_ROM); + Sh2MapMemory(pPsikyoshTiles + bank, 0x4060000, 0x407ffff, SM_ROM); + } +} + +void __fastcall psx_write_long(UINT32 , UINT32) +{ + // Keep sh2 from crashing with Space Bomber +} + +void __fastcall ps3v1_write_word(UINT32 address, UINT16 data) +{ + address &= 0xc7ffffff; + address ^= 2; + + if ((address & 0xfffffe00) == 0x3050000) { + *((UINT16 *)(DrvZoomRAM + (address & 0x1fe))) = data; + return; + } +} + +void __fastcall ps3v1_write_byte(UINT32 address, UINT8 data) +{ + address &= 0xc7ffffff; + + if ((address & 0xfffffe00) == 0x3050000) { + address ^= 3; + DrvZoomRAM[address & 0x1ff] = data; + return; + } + + if ((address & 0xffffffe0) == 0x305ffe0) { + address ^= 3; + DrvVidRegs[address & 0x1f] = data; + DrvZoomRAM[address & 0xffff] = data; + + if ((address & 0x1c) == 0x10) { + graphics_bank(); + } + + return; + } + + switch (address) + { + case 0x305ffdd: + if (!(data & 0xc0)) Sh2SetIRQLine(4, SH2_IRQSTATUS_NONE); + return; + + case 0x5000000: + case 0x5000002: + case 0x5000004: + BurnYMF278BSelectRegister((address >> 1) & 3, data); + return; + + case 0x5000001: + case 0x5000003: + case 0x5000005: + BurnYMF278BWriteRegister((address >> 1) & 3, data); + return; + + case 0x5800004: + EEPROMWrite((data & 0x40), (data & 0x80), (data & 0x20)); + return; + } +} + +UINT8 __fastcall ps3v1_read_byte(UINT32 address) +{ + address &= 0xc7ffffff; + + switch (address) + { + case 0x5000000: + return BurnYMF278BReadStatus(); + + case 0x5800000: + case 0x5800001: + case 0x5800002: + case 0x5800003: + return DrvInputs >> ((~address & 3) << 3); + + case 0x5800004: + return DrvDips[1] | ((EEPROMRead() & 1) << 4); + + case 0x5000005: + return DrvSndROM[(sample_offs++) & 0x3fffff]; + } + + return 0; +} + +//----------------------------------------------------------------------------------------- + +void __fastcall ps5_write_word(UINT32 address, UINT16 data) +{ + address &= 0xc7ffffff; + address ^= 2; + + if ((address & 0xfffffe00) == 0x4050000) { + *((UINT16 *)(DrvZoomRAM + (address & 0x1fe))) = data; + return; + } +} + +void __fastcall ps5_write_byte(UINT32 address, UINT8 data) +{ + address &= 0xc7ffffff; + + if ((address & 0xfffffe00) == 0x4050000) { + address ^= 3; + DrvZoomRAM[address & 0x1ff] = data; + return; + } + + if ((address & 0xffffffe0) == 0x405ffe0) { + address ^= 3; + DrvVidRegs[address & 0x1f] = data; + DrvZoomRAM[address & 0xffff] = data; + + if ((address & 0x1c) == 0x10) { + graphics_bank(); + } + + return; + } + + switch (address) + { + case 0x405ffdd: + if (!(data & 0xc0)) Sh2SetIRQLine(4, SH2_IRQSTATUS_NONE); + return; + + case 0x3100000: + case 0x3100002: + case 0x3100004: + case 0x3100006: + BurnYMF278BSelectRegister((address >> 1) & 3, data); + return; + + case 0x3100001: + case 0x3100003: + case 0x3100005: + case 0x3100007: + BurnYMF278BWriteRegister((address >> 1) & 3, data); + return; + + case 0x3000004: + EEPROMWrite((data & 0x40), (data & 0x80), (data & 0x20)); + return; + } +} + +UINT8 __fastcall ps5_read_byte(UINT32 address) +{ + address &= 0xc7ffffff; + + switch (address) + { + case 0x3100000: + return BurnYMF278BReadStatus(); + + case 0x3000000: + case 0x3000001: + case 0x3000002: + case 0x3000003: + return DrvInputs >> ((~address & 3) << 3); + + case 0x3000004: + return DrvDips[1] | ((EEPROMRead() & 1) << 4); + + case 0x3100005: + return DrvSndROM[(sample_offs++) & 0x3fffff]; + } + + return 0; +} + +//------------------------------------------------------------------------------------- +// Some hackery to eat up some idle cycles. + +UINT32 __fastcall hack_read_long(UINT32 a) +{ + a &= 0xfffff; + + if (a == speedhack_address) { + UINT32 pc = Sh2GetPC(0); + + if (pc == speedhack_pc[0]) { + Sh2StopRun(); + } else if (pc == speedhack_pc[1]) { + Sh2StopRun(); + } else if (pc == speedhack_pc[2]) { + Sh2StopRun(); + } else if (pc == speedhack_pc[3]) { + Sh2StopRun(); + } + } + + return *((UINT32*)(DrvSh2RAM + a)); +} + +UINT16 __fastcall hack_read_word(UINT32 a) +{ + return *((UINT16 *)(DrvSh2RAM + ((a & 0xfffff) ^ 2))); +} + +UINT8 __fastcall hack_read_byte(UINT32 a) +{ + return DrvSh2RAM[(a & 0xfffff) ^ 3]; +} + +//------------------------------------------------------------------------------------- + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)Sh2TotalCycles() * nSoundRate / 28636350; +} + +static void DrvIRQCallback(INT32, INT32 nStatus) +{ + if (nStatus) + Sh2SetIRQLine(12, SH2_IRQSTATUS_AUTO); + else + Sh2SetIRQLine(12, SH2_IRQSTATUS_NONE); +} + +static INT32 DrvDoReset() +{ + Sh2Reset( *(UINT32 *)(DrvSh2ROM + 0), *(UINT32 *)(DrvSh2ROM + 4) ); + + memset (AllRam, 0, RamEnd - AllRam); + + if (EEPROMAvailable() == 0) { + EEPROMFill(DrvEEPROM, 0, 0x100); + } + + BurnYMF278BReset(); + + sample_offs = 0; + previous_graphics_bank = -1; + + return 0; +} + +static INT32 MemIndex(INT32 gfxsize) +{ + UINT8 *Next; Next = AllMem; + + DrvSh2ROM = Next; Next += 0x0200000; + + pPsikyoshTiles = Next; Next += gfxsize + 0x20000 /* empty banking */; + + DrvSndROM = Next; Next += 0x0400000; + + DrvEEPROM = Next; Next += 0x0000100; + + AllRam = Next; + + DrvZoomRAM = Next; Next += 0x0010000; + DrvPalRAM = Next; Next += 0x0010000; + DrvSprRAM = Next; Next += 0x0010000; + DrvVidRegs = Next; Next += 0x0000200; + DrvSh2RAM = Next; Next += 0x0100000; + DrvSprBuf = Next; Next += 0x0004000; + + RamEnd = Next; + + pBurnDrvPalette = (UINT32 *)Next; Next += 0x1400 * sizeof(UINT32); + + DrvBgRAM = DrvSprRAM + 0x004000; + + pPsikyoshPalRAM = (UINT32*)DrvPalRAM; + pPsikyoshSpriteBuffer = (UINT32*)DrvSprBuf; + pPsikyoshBgRAM = (UINT32*)DrvBgRAM; + pPsikyoshVidRegs = (UINT32*)DrvVidRegs; + pPsikyoshZoomRAM = (UINT32*)DrvZoomRAM; + + MemEnd = Next; + + return 0; +} + +static const eeprom_interface eeprom_interface_93C56 = +{ + 8, // address bits 8 + 8, // data bits 8 + "*110x", // read 110x aaaaaaaa + "*101x", // write 101x aaaaaaaa dddddddd + "*111x", // erase 111x aaaaaaaa + "*10000xxxxxxx", // lock 100x 00xxxx + "*10011xxxxxxx", // unlock 100x 11xxxx + 0, + 0 +}; + +static void BurnSwap32(UINT8 *src, INT32 len) +{ + for (INT32 i = 0; i < len; i+=4) { + INT32 t = src[i+1]; + src[i+1] = src[i+2]; + src[i+2] = t; + } +} + +static void BurnSwapEndian(INT32 len) +{ + BurnByteswap(DrvSh2ROM, 0x200000); + + for (INT32 i = 0; i < len; i+=4) { + INT32 t = DrvSh2ROM[i + 0]; + DrvSh2ROM[i + 0] = DrvSh2ROM[i+3]; + DrvSh2ROM[i + 3] = t; + t = DrvSh2ROM[i + 1]; + DrvSh2ROM[i + 1] = DrvSh2ROM[i + 2]; + DrvSh2ROM[i + 2] = t; + } +} + +static void DrvGfxDecode(INT32 size) +{ + BurnSwap32(pPsikyoshTiles, size); + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "soldivid") == 0) { + BurnByteswap(pPsikyoshTiles, size); + } +} + +static INT32 DrvInit(INT32 (*LoadCallback)(), INT32 type, INT32 gfx_max, INT32 gfx_min) +{ + AllMem = NULL; + MemIndex(gfx_max - gfx_min); + INT32 nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(AllMem, 0, nLen); + MemIndex(gfx_max - gfx_min); + + { + if (LoadCallback) { + if (LoadCallback()) return 1; + } + + BurnSwap32(DrvSh2ROM, 0x100000); + BurnSwapEndian(0x200000); + DrvGfxDecode(gfx_max - gfx_min); + graphics_min_max[0] = gfx_min; + graphics_min_max[1] = gfx_max; + } + + if (type == 0) + { + Sh2Init(1); + Sh2Open(0); + Sh2MapMemory(DrvSh2ROM, 0x00000000, 0x000fffff, SM_ROM); + Sh2MapMemory(DrvSh2ROM + 0x100000, 0x02000000, 0x020fffff, SM_ROM); + Sh2MapMemory(DrvSprRAM, 0x03000000, 0x0300ffff, SM_RAM); + Sh2MapMemory(DrvPalRAM, 0x03040000, 0x0304ffff, SM_RAM); + Sh2MapMemory(DrvZoomRAM, 0x03050000, 0x0305ffff, SM_ROM); + Sh2MapMemory(DrvSh2RAM, 0x06000000, 0x060fffff, SM_RAM); + Sh2SetReadByteHandler (0, ps3v1_read_byte); + Sh2SetWriteByteHandler(0, ps3v1_write_byte); + Sh2SetWriteWordHandler(0, ps3v1_write_word); + Sh2SetWriteLongHandler(0, psx_write_long); + } else { + Sh2Init(1); + Sh2Open(0); + Sh2MapMemory(DrvSh2ROM, 0x00000000, 0x000fffff, SM_ROM); + Sh2MapMemory(DrvSprRAM, 0x04000000, 0x0400ffff, SM_RAM); + Sh2MapMemory(DrvPalRAM, 0x04040000, 0x0404ffff, SM_RAM); + Sh2MapMemory(DrvZoomRAM, 0x04050000, 0x0405ffff, SM_ROM); + Sh2MapMemory(DrvSh2ROM + 0x100000, 0x05000000, 0x0507ffff, SM_ROM); + Sh2MapMemory(DrvSh2RAM, 0x06000000, 0x060fffff, SM_RAM); + Sh2SetReadByteHandler (0, ps5_read_byte); + Sh2SetWriteByteHandler(0, ps5_write_byte); + Sh2SetWriteWordHandler(0, ps5_write_word); + Sh2SetWriteLongHandler(0, psx_write_long); + } + + Sh2MapHandler(1, 0x06000000 | speedhack_address, 0x0600ffff | speedhack_address, SM_ROM); + Sh2SetReadByteHandler (1, hack_read_byte); + Sh2SetReadWordHandler (1, hack_read_word); + Sh2SetReadLongHandler (1, hack_read_long); + + BurnYMF278BInit(0, DrvSndROM, &DrvIRQCallback, DrvSynchroniseStream); + BurnTimerAttachSh2(28636350); + + EEPROMInit(&eeprom_interface_93C56); + + PsikyoshVideoInit(gfx_max, gfx_min); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + PsikyoshVideoExit(); + + Sh2Exit(); + BurnYMF278BExit(); + + EEPROMExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + speedhack_address = ~0; + memset (speedhack_pc, 0, 4 * sizeof(UINT32)); + + return 0; +} + +static INT32 DrvFrame() +{ + if (DrvReset) { + DrvDoReset(); + } + + Sh2NewFrame(); + + { + DrvInputs = ~0x60 | (DrvDips[0] & 0x60); + for (INT32 i = 0; i < 32; i++) { + DrvInputs ^= (DrvJoy1[i] & 1) << i; + } + } + + BurnTimerEndFrame(28636350 / 60); + + Sh2SetIRQLine(4, SH2_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + BurnYMF278BUpdate(nBurnSoundLen); + } + + if (pBurnDraw) { + PsikyoshDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x4000); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_MEMORY_RAM) { + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.nAddress = 0; + ba.szName = "All RAM"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + Sh2Scan(nAction); + BurnYMF278BScan(nAction, pnMin); + + SCAN_VAR(sample_offs); + } + + if (nAction & ACB_WRITE) { + previous_graphics_bank = -1; + graphics_bank(); + } + + return 0; +} + + +// Sol Divide - The Sword Of Darkness + +static struct BurnRomInfo soldividRomDesc[] = { + { "2-prog_l.u18", 0x080000, 0xcf179b04, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1-prog_h.u17", 0x080000, 0xf467d1c4, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "4l.u10", 0x400000, 0x9eb9f269, 2 | BRF_GRA }, // 2 Graphics + { "4h.u31", 0x400000, 0x7c76cfe7, 2 | BRF_GRA }, // 3 + { "5l.u9", 0x400000, 0xc59c6858, 2 | BRF_GRA }, // 4 + { "5h.u30", 0x400000, 0x73bc66d0, 2 | BRF_GRA }, // 5 + { "6l.u8", 0x400000, 0xf01b816e, 2 | BRF_GRA }, // 6 + { "6h.u37", 0x400000, 0xfdd57361, 2 | BRF_GRA }, // 7 + + { "sound.bin", 0x400000, 0xe98f8d45, 3 | BRF_SND }, // 8 Samples +}; + +STD_ROM_PICK(soldivid) +STD_ROM_FN(soldivid) + +static int SoldividLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x2000000 - 0x2000000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001 - 0x2000000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800000 - 0x2000000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800001 - 0x2000000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000000 - 0x2000000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000001 - 0x2000000, 7, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 8, 1)) return 1; + + return 0; +} + +static INT32 SoldividInit() +{ + speedhack_address = 0x00000c; + speedhack_pc[0] = 0x0001AFAC; + speedhack_pc[1] = 0x0001AE76; + + return DrvInit(SoldividLoadCallback, 0, 0x3800000, 0x2000000); +} + +struct BurnDriver BurnDrvSoldivid = { + "soldivid", NULL, NULL, NULL, "1997", + "Sol Divide - The Sword Of Darkness\0", NULL, "Psikyo", "PS3-V1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PSIKYO, GBF_HORSHOOT, 0, + NULL, soldividRomInfo, soldividRomName, NULL, NULL, Common3ButtonInputInfo, SoldividDIPInfo, + SoldividInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 320, 224, 4, 3 +}; + + +// Strikers 1945 II + +static struct BurnRomInfo s1945iiRomDesc[] = { + { "2_prog_l.u18", 0x080000, 0x20a911b8, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1_prog_h.u17", 0x080000, 0x4c0fe85e, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "0l.u4", 0x400000, 0xbfacf98d, 2 | BRF_GRA }, // 2 Graphics + { "0h.u13", 0x400000, 0x1266f67c, 2 | BRF_GRA }, // 3 + { "1l.u3", 0x400000, 0x2d3332c9, 2 | BRF_GRA }, // 4 + { "1h.u12", 0x400000, 0x27b32c3e, 2 | BRF_GRA }, // 5 + { "2l.u2", 0x400000, 0x91ba6d23, 2 | BRF_GRA }, // 6 + { "2h.u20", 0x400000, 0xfabf4334, 2 | BRF_GRA }, // 7 + { "3l.u1", 0x400000, 0xa6c3704e, 2 | BRF_GRA }, // 8 + { "3h.u19", 0x400000, 0x4cd3ca70, 2 | BRF_GRA }, // 9 + + { "sound.u32", 0x400000, 0xba680ca7, 3 | BRF_SND }, // 10 Samples + + { "eeprom-s1945ii.bin", 0x000100, 0x7ac38846, BRF_OPT }, +}; + +STD_ROM_PICK(s1945ii) +STD_ROM_FN(s1945ii) + +static const UINT8 factory_eeprom[16] = { + 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static INT32 S1945iiLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0000000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0000001, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800001, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 10, 1)) return 1; + + memcpy (DrvEEPROM, factory_eeprom, 0x10); + + return 0; +} + +static INT32 S1945iiInit() +{ + speedhack_address = 0x00000c; + speedhack_pc[0] = 0x0609fc6a; + speedhack_pc[1] = 0x0609fed4; + speedhack_pc[2] = 0x060A0172; + + return DrvInit(S1945iiLoadCallback, 0, 0x2000000, 0); +} + +struct BurnDriver BurnDrvS1945ii = { + "s1945ii", NULL, NULL, NULL, "1997", + "Strikers 1945 II\0", NULL, "Psikyo", "PS3-V1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945iiRomInfo, s1945iiRomName, NULL, NULL, Common2ButtonInputInfo, S1945iiDIPInfo, + S1945iiInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Daraku Tenshi - The Fallen Angels + +static struct BurnRomInfo darakuRomDesc[] = { + { "4_prog_l.u18", 0x080000, 0x660b4609, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "3_prog_h.u17", 0x080000, 0x7a9cf601, 1 | BRF_PRG | BRF_ESS }, // 1 + { "prog.u16", 0x100000, 0x3742e990, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "0l.u4", 0x400000, 0x565d8427, 2 | BRF_GRA }, // 3 Graphics + { "0h.u13", 0x400000, 0x9a602630, 2 | BRF_GRA }, // 4 + { "1l.u3", 0x400000, 0xac5ce8e1, 2 | BRF_GRA }, // 5 + { "1h.u12", 0x400000, 0xb0a59f7b, 2 | BRF_GRA }, // 6 + { "2l.u2", 0x400000, 0x2daa03b2, 2 | BRF_GRA }, // 7 + { "2h.u20", 0x400000, 0xe98e185a, 2 | BRF_GRA }, // 8 + { "3l.u1", 0x400000, 0x1d372aa1, 2 | BRF_GRA }, // 9 + { "3h.u19", 0x400000, 0x597f3f15, 2 | BRF_GRA }, // 10 + { "4l.u10", 0x400000, 0xe3d58cd8, 2 | BRF_GRA }, // 11 + { "4h.u31", 0x400000, 0xaebc9cd0, 2 | BRF_GRA }, // 12 + { "5l.u9", 0x400000, 0xeab5a50b, 2 | BRF_GRA }, // 13 + { "5h.u30", 0x400000, 0xf157474f, 2 | BRF_GRA }, // 14 + { "6l.u8", 0x200000, 0x9f008d1b, 2 | BRF_GRA }, // 15 + { "6h.u37", 0x200000, 0xacd2d0e3, 2 | BRF_GRA }, // 16 + + { "sound.u32", 0x400000, 0xef2c781d, 3 | BRF_SND }, // 17 Samples + + { "eeprom-daraku.bin", 0x000100, 0xa9715297, BRF_OPT }, +}; + +STD_ROM_PICK(daraku) +STD_ROM_FN(daraku) + +static const UINT8 daraku_eeprom[16] = { + 0x03, 0x02, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static INT32 DarakuLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0100000, 2, 1)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0000000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0000001, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800001, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800000, 9, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001, 10, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000, 11, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001, 12, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800000, 13, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800001, 14, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000000, 15, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000001, 16, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 17, 1)) return 1; + + memcpy (DrvEEPROM, daraku_eeprom, 0x10); + + return 0; +} + +static INT32 DarakuInit() +{ + speedhack_address = 0x00000c; + speedhack_pc[0] = 0x0004761c; + speedhack_pc[1] = 0x00047978; + + return DrvInit(DarakuLoadCallback, 0, 0x3400000, 0); +} + +struct BurnDriver BurnDrvDaraku = { + "daraku", NULL, NULL, NULL, "1998", + "Daraku Tenshi - The Fallen Angels\0", NULL, "Psikyo", "PS3-V1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PSIKYO, GBF_VSFIGHT, 0, + NULL, darakuRomInfo, darakuRomName, NULL, NULL, Common4ButtonInputInfo, DarakuDIPInfo, + DarakuInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 320, 224, 4, 3 +}; + + +// Space Bomber (ver. B) + +static struct BurnRomInfo sbomberRomDesc[] = { + { "1-b_pr_l.u18", 0x080000, 0x52d12225, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1-b_pr_h.u17", 0x080000, 0x1bbd0345, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "0l.u4", 0x400000, 0xb7e4ac51, 2 | BRF_GRA }, // 2 Graphics + { "0h.u13", 0x400000, 0x235e6c27, 2 | BRF_GRA }, // 3 + { "1l.u3", 0x400000, 0x3c88c48c, 2 | BRF_GRA }, // 4 + { "1h.u12", 0x400000, 0x15626a6e, 2 | BRF_GRA }, // 5 + { "2l.u2", 0x400000, 0x41e92f64, 2 | BRF_GRA }, // 6 + { "2h.u20", 0x400000, 0x4ae62e84, 2 | BRF_GRA }, // 7 + { "3l.u1", 0x400000, 0x43ba5f0f, 2 | BRF_GRA }, // 8 + { "3h.u19", 0x400000, 0xff01bb12, 2 | BRF_GRA }, // 9 + { "4l.u10", 0x400000, 0xe491d593, 2 | BRF_GRA }, // 10 + { "4h.u31", 0x400000, 0x7bdd377a, 2 | BRF_GRA }, // 11 + + { "sound.u32", 0x400000, 0x85cbff69, 3 | BRF_SND }, // 12 Samples + + { "eeprom-sbomber.bin", 0x000100, 0x7ac38846, BRF_OPT }, +}; + +STD_ROM_PICK(sbomber) +STD_ROM_FN(sbomber) + +static struct BurnRomInfo sbomberaRomDesc[] = { + { "2.u18", 0x080000, 0x57819a26, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1.u17", 0x080000, 0xc388e847, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "0l.u4", 0x400000, 0xb7e4ac51, 2 | BRF_GRA }, // 2 Graphics + { "0h.u13", 0x400000, 0x235e6c27, 2 | BRF_GRA }, // 3 + { "1l.u3", 0x400000, 0x3c88c48c, 2 | BRF_GRA }, // 4 + { "1h.u12", 0x400000, 0x15626a6e, 2 | BRF_GRA }, // 5 + { "2l.u2", 0x400000, 0x41e92f64, 2 | BRF_GRA }, // 6 + { "2h.u20", 0x400000, 0x4ae62e84, 2 | BRF_GRA }, // 7 + { "3l.u1", 0x400000, 0x43ba5f0f, 2 | BRF_GRA }, // 8 + { "3h.u19", 0x400000, 0xff01bb12, 2 | BRF_GRA }, // 9 + { "4l.u10", 0x400000, 0xe491d593, 2 | BRF_GRA }, // 10 + { "4h.u31", 0x400000, 0x7bdd377a, 2 | BRF_GRA }, // 11 + + { "sound.u32", 0x400000, 0x85cbff69, 3 | BRF_SND }, // 12 Samples + + { "eeprom-sbomber.bin", 0x000100, 0x7ac38846, BRF_OPT }, +}; + +STD_ROM_PICK(sbombera) +STD_ROM_FN(sbombera) + +static INT32 SbomberLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0000000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0000001, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800001, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001, 9, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000, 10, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001, 11, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 12, 1)) return 1; + + memcpy (DrvEEPROM, factory_eeprom, 0x10); + + return 0; +} + +static INT32 SbomberInit() +{ + speedhack_address = 0x00000c; + speedhack_pc[0] = 0x060A10EE; + speedhack_pc[1] = 0x060A165A; + speedhack_pc[2] = 0x060A1382; + + return DrvInit(SbomberLoadCallback, 0, 0x2800000, 0); +} + +struct BurnDriver BurnDrvSbomber = { + "sbomber", NULL, NULL, NULL, "1998", + "Space Bomber (ver. B)\0", NULL, "Psikyo", "PS3-V1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_SHOOT, 0, + NULL, sbomberRomInfo, sbomberRomName, NULL, NULL, Common2ButtonInputInfo, S1945iiDIPInfo, + SbomberInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvSbombera = { + "sbombera", "sbomber", NULL, NULL, "1998", + "Space Bomber\0", NULL, "Psikyo", "PS3-V1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_PSIKYO, GBF_SHOOT, 0, + NULL, sbomberaRomInfo, sbomberaRomName, NULL, NULL, Common2ButtonInputInfo, S1945iiDIPInfo, + SbomberInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Gunbird 2 + +static struct BurnRomInfo gunbird2RomDesc[] = { + { "2_prog_l.u16", 0x080000, 0x76f934f0, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1_prog_h.u17", 0x080000, 0x7328d8bf, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3_pdata.u1", 0x080000, 0xa5b697e6, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "0l.u3", 0x800000, 0x5c826bc8, 2 | BRF_GRA }, // 3 Graphics + { "0h.u10", 0x800000, 0x3df0cb6c, 2 | BRF_GRA }, // 4 + { "1l.u4", 0x800000, 0x1558358d, 2 | BRF_GRA }, // 5 + { "1h.u11", 0x800000, 0x4ee0103b, 2 | BRF_GRA }, // 6 + { "2l.u5", 0x800000, 0xe1c7a7b8, 2 | BRF_GRA }, // 7 + { "2h.u12", 0x800000, 0xbc8a41df, 2 | BRF_GRA }, // 8 + { "3l.u6", 0x400000, 0x0229d37f, 2 | BRF_GRA }, // 9 + { "3h.u13", 0x400000, 0xf41bbf2b, 2 | BRF_GRA }, // 10 + + { "sound.u9", 0x400000, 0xf19796ab, 3 | BRF_SND }, // 11 Samples + + { "eeprom-gunbird2.bin",0x000100, 0x7ac38846, BRF_OPT }, +}; + +STD_ROM_PICK(gunbird2) +STD_ROM_FN(gunbird2) + +static INT32 Gunbird2LoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0100000, 2, 1)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0000000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0000001, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000000, 9, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x3000001, 10, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 11, 1)) return 1; + + memcpy (DrvEEPROM, factory_eeprom, 0x10); + + return 0; +} + +static INT32 Gunbird2Init() +{ + speedhack_address = 0x004000c; + speedhack_pc[0] = 0x06028be6; + speedhack_pc[1] = 0x06028974; + speedhack_pc[2] = 0x06028e64; + + return DrvInit(Gunbird2LoadCallback, 1, 0x3800000, 0); +} + +struct BurnDriver BurnDrvGunbird2 = { + "gunbird2", NULL, NULL, NULL, "1998", + "Gunbird 2\0", NULL, "Psikyo", "PS5", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, gunbird2RomInfo, gunbird2RomName, NULL, NULL, Common3ButtonInputInfo, Gunbird2DIPInfo, + Gunbird2Init, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Strikers 1945 III (World) / Strikers 1999 (Japan) + +static struct BurnRomInfo s1945iiiRomDesc[] = { + { "2_progl.u16", 0x080000, 0x5d5d385f, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "1_progh.u17", 0x080000, 0x1b8a5a18, 1 | BRF_PRG | BRF_ESS }, // 1 + { "3_data.u1", 0x080000, 0x8ff5f7d3, 1 | BRF_PRG | BRF_ESS }, // 2 + + { "0l.u3", 0x800000, 0x70a0d52c, 2 | BRF_GRA }, // 3 Graphics + { "0h.u10", 0x800000, 0x4dcd22b4, 2 | BRF_GRA }, // 4 + { "1l.u4", 0x800000, 0xde1042ff, 2 | BRF_GRA }, // 5 + { "1h.u11", 0x800000, 0xb51a4430, 2 | BRF_GRA }, // 6 + { "2l.u5", 0x800000, 0x23b02dca, 2 | BRF_GRA }, // 7 + { "2h.u12", 0x800000, 0x9933ab04, 2 | BRF_GRA }, // 8 + { "3l.u6", 0x400000, 0xf693438c, 2 | BRF_GRA }, // 9 + { "3h.u13", 0x400000, 0x2d0c334f, 2 | BRF_GRA }, // 10 + + { "sound.u9", 0x400000, 0xc5374beb, 3 | BRF_SND }, // 11 Samples + + { "eeprom-s1945iii.bin",0x000100, 0xb39f3604, BRF_OPT }, +}; + +STD_ROM_PICK(s1945iii) +STD_ROM_FN(s1945iii) + +static const UINT8 s1945iii_eeprom[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x70, + 0x25, 0x25, 0x25, 0x00, 0x01, 0x00, 0x11, 0xe0 +}; + +static INT32 S1945iiiLoadCallback() +{ + INT32 nRet = Gunbird2LoadCallback(); + + memcpy (DrvEEPROM + 0x00, factory_eeprom, 0x10); + memcpy (DrvEEPROM + 0xf0, s1945iii_eeprom, 0x10); + + return nRet; +} + +static INT32 S1945iiiInit() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x0602b464; + speedhack_pc[1] = 0x0602b97c; + speedhack_pc[2] = 0x0602b6e2; + speedhack_pc[3] = 0x0602bc1e; + + return DrvInit(S1945iiiLoadCallback, 1, 0x3800000, 0); +} + +struct BurnDriver BurnDrvS1945iii = { + "s1945iii", NULL, NULL, NULL, "1999", + "Strikers 1945 III (World) / Strikers 1999 (Japan)\0", NULL, "Psikyo", "PS5", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, s1945iiiRomInfo, s1945iiiRomName, NULL, NULL, Common3ButtonInputInfo, S1945iiiDIPInfo, + S1945iiiInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Dragon Blaze + +static struct BurnRomInfo dragnblzRomDesc[] = { + { "1prog_l.u22", 0x080000, 0x95d6fd02, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "2prog_h.u21", 0x080000, 0xfc5eade8, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1l.u4", 0x200000, 0xc2eb565c, 2 | BRF_GRA }, // 2 Graphics + { "1h.u12", 0x200000, 0x23cb46b7, 2 | BRF_GRA }, // 3 + { "2l.u5", 0x200000, 0xbc256aea, 2 | BRF_GRA }, // 4 + { "2h.u13", 0x200000, 0xb75f59ec, 2 | BRF_GRA }, // 5 + { "3l.u6", 0x200000, 0x4284f008, 2 | BRF_GRA }, // 6 + { "3h.u14", 0x200000, 0xabe5cbbf, 2 | BRF_GRA }, // 7 + { "4l.u7", 0x200000, 0xc9fcf2e5, 2 | BRF_GRA }, // 8 + { "4h.u15", 0x200000, 0x0ab0a12a, 2 | BRF_GRA }, // 9 + { "5l.u8", 0x200000, 0x68d03ccf, 2 | BRF_GRA }, // 10 + { "5h.u16", 0x200000, 0x5450fbca, 2 | BRF_GRA }, // 11 + { "6l.u1", 0x200000, 0x8b52c90b, 2 | BRF_GRA }, // 12 + { "6h.u2", 0x200000, 0x7362f929, 2 | BRF_GRA }, // 13 + { "7l.u19", 0x200000, 0xb4f4d86e, 2 | BRF_GRA }, // 14 + { "7h.u20", 0x200000, 0x44b7b9cc, 2 | BRF_GRA }, // 15 + { "8l.u28", 0x200000, 0xcd079f89, 2 | BRF_GRA }, // 16 + { "8h.u29", 0x200000, 0x3edb508a, 2 | BRF_GRA }, // 17 + { "9l.u41", 0x200000, 0x0b53cd78, 2 | BRF_GRA }, // 18 + { "9h.u42", 0x200000, 0xbc61998a, 2 | BRF_GRA }, // 19 + { "10l.u58", 0x200000, 0xa3f5c7f8, 2 | BRF_GRA }, // 20 + { "10h.u59", 0x200000, 0x30e304c4, 2 | BRF_GRA }, // 21 + + { "snd0.u52", 0x200000, 0x7fd1b225, 3 | BRF_SND }, // 22 Samples + + { "eeprom-dragnblz.bin",0x000100, 0x70a8a3a6, BRF_OPT }, +}; + +STD_ROM_PICK(dragnblz) +STD_ROM_FN(dragnblz) + +static const UINT8 dragnblz_eeprom[16] = { + 0x00, 0x01, 0x11, 0x70, 0x25, 0x25, 0x25, 0x00, + 0x01, 0x00, 0x11, 0xe0, 0x00, 0x00, 0x00, 0x00 +}; + +static INT32 DragnblzLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0400000 - 0x0400000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0400001 - 0x0400000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800000 - 0x0400000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800001 - 0x0400000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0c00000 - 0x0400000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0c00001 - 0x0400000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000 - 0x0400000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001 - 0x0400000, 9, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1400000 - 0x0400000, 10, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1400001 - 0x0400000, 11, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800000 - 0x0400000, 12, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001 - 0x0400000, 13, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00000 - 0x0400000, 14, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00001 - 0x0400000, 15, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000 - 0x0400000, 16, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001 - 0x0400000, 17, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400000 - 0x0400000, 18, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400001 - 0x0400000, 19, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800000 - 0x0400000, 20, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800001 - 0x0400000, 21, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 22, 1)) return 1; + + memcpy (DrvEEPROM + 0x00, factory_eeprom, 0x10); + memcpy (DrvEEPROM + 0xf0, dragnblz_eeprom, 0x10); + + return 0; +} + +static INT32 DragnblzInit() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x06027440; + speedhack_pc[1] = 0x060276e6; + speedhack_pc[2] = 0x06027C74; + speedhack_pc[3] = 0x060279A8; + + return DrvInit(DragnblzLoadCallback, 1, 0x2c00000, 0x0400000); +} + +struct BurnDriver BurnDrvDragnblz = { + "dragnblz", NULL, NULL, NULL, "2000", + "Dragon Blaze\0", NULL, "Psikyo", "PS5V2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_VERSHOOT, 0, + NULL, dragnblzRomInfo, dragnblzRomName, NULL, NULL, Common3ButtonInputInfo, DragnblzDIPInfo, + DragnblzInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Gunbarich + +static struct BurnRomInfo gnbarichRomDesc[] = { + { "1-prog_h.u22", 0x080000, 0x6588fc96, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "2-prog_l.u21", 0x080000, 0xc136cd9c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "6l.u1", 0x200000, 0x0432e1a8, 2 | BRF_GRA }, // 2 Graphics + { "6h.u2", 0x200000, 0xf90fa3ea, 2 | BRF_GRA }, // 3 + { "7l.u19", 0x200000, 0x36bf9a58, 2 | BRF_GRA }, // 4 + { "7h.u20", 0x200000, 0x4b3eafd8, 2 | BRF_GRA }, // 5 + { "8l.u28", 0x200000, 0x026754da, 2 | BRF_GRA }, // 6 + { "8h.u29", 0x200000, 0x8cd7aaa0, 2 | BRF_GRA }, // 7 + { "9l.u41", 0x200000, 0x02c066fe, 2 | BRF_GRA }, // 8 + { "9h.u42", 0x200000, 0x5433385a, 2 | BRF_GRA }, // 9 + + { "snd0.u52", 0x200000, 0x7b10436b, 3 | BRF_SND }, // 10 Samples + + { "eeprom-gnbarich.bin",0x000100, 0x0f5bf42f, BRF_OPT }, +}; + +STD_ROM_PICK(gnbarich) +STD_ROM_FN(gnbarich) + +static const UINT8 gnbarich_eeprom[16] = { + 0x00, 0x0f, 0x42, 0x40, 0x08, 0x0a, 0x00, 0x00, + 0x01, 0x06, 0x42, 0x59, 0x00, 0x00, 0x00, 0x00 +}; + +static INT32 GnbarichLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x1800000 - 0x1800000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001 - 0x1800000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00000 - 0x1800000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00001 - 0x1800000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000 - 0x1800000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001 - 0x1800000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400000 - 0x1800000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400001 - 0x1800000, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 10, 1)) return 1; + + memcpy (DrvEEPROM + 0x00, factory_eeprom, 0x10); + memcpy (DrvEEPROM + 0xf0, gnbarich_eeprom, 0x10); + + return 0; +} + +static INT32 GnbarichInit() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x0602CAE8; + speedhack_pc[1] = 0x0602CD88; + speedhack_pc[2] = 0x0602D2F0; + speedhack_pc[3] = 0x0602D042; + + return DrvInit(GnbarichLoadCallback, 1, 0x2800000, 0x1800000); +} + +struct BurnDriver BurnDrvGnbarich = { + "gnbarich", NULL, NULL, NULL, "2001", + "Gunbarich\0", NULL, "Psikyo", "PS5V2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_PSIKYO, GBF_BREAKOUT, 0, + NULL, gnbarichRomInfo, gnbarichRomName, NULL, NULL, Common3ButtonInputInfo, S1945iiiDIPInfo, + GnbarichInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 224, 320, 3, 4 +}; + + +// Mahjong G-Taste + +static struct BurnRomInfo mjgtasteRomDesc[] = { + { "1.u22", 0x080000, 0xf5ff7876, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "2.u21", 0x080000, 0x5f2041dc, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1l.u4", 0x200000, 0x30da42b1, 2 | BRF_GRA }, // 2 Graphics + { "1h.u12", 0x200000, 0x629c1d44, 2 | BRF_GRA }, // 3 + { "2l.u5", 0x200000, 0x1f6126ab, 2 | BRF_GRA }, // 4 + { "2h.u13", 0x200000, 0xdba34e46, 2 | BRF_GRA }, // 5 + { "3l.u6", 0x200000, 0x1023e35e, 2 | BRF_GRA }, // 6 + { "3h.u14", 0x200000, 0x8aebec7f, 2 | BRF_GRA }, // 7 + { "4l.u7", 0x200000, 0x9acf018b, 2 | BRF_GRA }, // 8 + { "4h.u15", 0x200000, 0xf93e154c, 2 | BRF_GRA }, // 9 + + { "snd0.u52", 0x400000, 0x0179f018, 3 | BRF_SND }, // 10 Samples + + { "eeprom-mjgtaste.bin",0x000100, 0xbbf7cfae, BRF_OPT }, +}; + +STD_ROM_PICK(mjgtaste) +STD_ROM_FN(mjgtaste) + +static const UINT8 mjgtaste_eeprom[16] = { + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 +}; + +static INT32 MjgtasteLoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0400000 - 0x0400000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0400001 - 0x0400000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800000 - 0x0400000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0800001 - 0x0400000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0c00000 - 0x0400000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0c00001 - 0x0400000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000 - 0x0400000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001 - 0x0400000, 9, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 10, 1)) return 1; + + memcpy (DrvEEPROM + 0x00, mjgtaste_eeprom, 0x10); + memcpy (DrvEEPROM + 0xf0, mjgtaste_eeprom, 0x10); + + return 0; +} + +static INT32 MjgtasteInit() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x06031f04; + speedhack_pc[1] = 0x0603214c; + + return DrvInit(MjgtasteLoadCallback, 1, 0x1400000, 0x0400000); +} + +struct BurnDriver BurnDrvMjgtaste = { + "mjgtaste", NULL, NULL, NULL, "2002", + "Mahjong G-Taste\0", NULL, "Psikyo", "PS5V2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PSIKYO, GBF_MAHJONG, 0, + NULL, mjgtasteRomInfo, mjgtasteRomName, NULL, NULL, Common3ButtonInputInfo, Tgm2DIPInfo, + MjgtasteInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 320, 224, 4, 3 +}; + + +// Tetris the Absolute The Grand Master 2 + +static struct BurnRomInfo tgm2RomDesc[] = { + { "1.u22", 0x080000, 0xc521bf24, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "2.u21", 0x080000, 0xb19f6c31, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "81ts_3l.u6", 0x200000, 0xd77cff9c, 2 | BRF_GRA }, // 2 Graphics + { "82ts_3h.u14", 0x200000, 0xf012b583, 2 | BRF_GRA }, // 3 + { "83ts_4l.u7", 0x200000, 0x078cafc3, 2 | BRF_GRA }, // 4 + { "84ts_4h.u15", 0x200000, 0x1f91446b, 2 | BRF_GRA }, // 5 + { "85ts_5l.u8", 0x200000, 0x40fbd259, 2 | BRF_GRA }, // 6 + { "86ts_5h.u16", 0x200000, 0x186c935f, 2 | BRF_GRA }, // 7 + { "87ts_6l.u1", 0x200000, 0xc17dc48a, 2 | BRF_GRA }, // 8 + { "88ts_6h.u2", 0x200000, 0xe4dba5da, 2 | BRF_GRA }, // 9 + { "89ts_7l.u19", 0x200000, 0xdab1b2c5, 2 | BRF_GRA }, // 10 + { "90ts_7h.u20", 0x200000, 0xaae696b3, 2 | BRF_GRA }, // 11 + { "91ts_8l.u28", 0x200000, 0xe953ace1, 2 | BRF_GRA }, // 12 + { "92ts_8h.u29", 0x200000, 0x9da3b976, 2 | BRF_GRA }, // 13 + { "93ts_9l.u41", 0x200000, 0x233087fe, 2 | BRF_GRA }, // 14 + { "94ts_9h.u42", 0x200000, 0x9da831c7, 2 | BRF_GRA }, // 15 + { "95ts_10l.u58", 0x200000, 0x303a5240, 2 | BRF_GRA }, // 16 + { "96ts_10h.u59", 0x200000, 0x2240ebf6, 2 | BRF_GRA }, // 17 + + { "97ts_snd.u52", 0x400000, 0x9155eca6, 3 | BRF_SND }, // 18 Samples + + { "tgm2.default.nv", 0x000100, 0x50e2348c, 4 | BRF_PRG | BRF_ESS }, // 19 EEPROM data +}; + +STD_ROM_PICK(tgm2) +STD_ROM_FN(tgm2) + +static INT32 Tgm2LoadCallback() +{ + if (BurnLoadRom(DrvSh2ROM + 0x0000001, 0, 2)) return 1; + if (BurnLoadRom(DrvSh2ROM + 0x0000000, 1, 2)) return 1; + + if (BurnLoadRom(pPsikyoshTiles + 0x0c00000 - 0x0c00000, 2, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x0c00001 - 0x0c00000, 3, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000000 - 0x0c00000, 4, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1000001 - 0x0c00000, 5, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1400000 - 0x0c00000, 6, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1400001 - 0x0c00000, 7, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800000 - 0x0c00000, 8, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1800001 - 0x0c00000, 9, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00000 - 0x0c00000, 10, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x1c00001 - 0x0c00000, 11, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000000 - 0x0c00000, 12, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2000001 - 0x0c00000, 13, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400000 - 0x0c00000, 14, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2400001 - 0x0c00000, 15, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800000 - 0x0c00000, 16, 2)) return 1; + if (BurnLoadRom(pPsikyoshTiles + 0x2800001 - 0x0c00000, 17, 2)) return 1; + + if (BurnLoadRom(DrvSndROM + 0x0000000, 18, 1)) return 1; + + if (BurnLoadRom(DrvEEPROM + 0x0000000, 19, 1)) return 1; + + return 0; +} + +static INT32 Tgm2Init() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x0602895a; + speedhack_pc[1] = 0x06028cac; + speedhack_pc[2] = 0x06029272; + speedhack_pc[3] = 0x06028ef2; + + return DrvInit(Tgm2LoadCallback, 1, 0x2c00000, 0x0c00000); +} + +struct BurnDriver BurnDrvTgm2 = { + "tgm2", NULL, NULL, NULL, "2000", + "Tetris the Absolute The Grand Master 2\0", NULL, "Arika", "PS5V2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_PSIKYO, GBF_PUZZLE, 0, + NULL, tgm2RomInfo, tgm2RomName, NULL, NULL, Common3ButtonInputInfo, Tgm2DIPInfo, + Tgm2Init, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 320, 240, 4, 3 +}; + + +// Tetris the Absolute The Grand Master 2 Plus + +static struct BurnRomInfo tgm2pRomDesc[] = { + { "1b.u22", 0x080000, 0x7599fb19, 1 | BRF_PRG | BRF_ESS }, // 0 SH2 Code + { "2b.u21", 0x080000, 0x38bc626c, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "81ts_3l.u6", 0x200000, 0xd77cff9c, 2 | BRF_GRA }, // 2 Graphics + { "82ts_3h.u14", 0x200000, 0xf012b583, 2 | BRF_GRA }, // 3 + { "83ts_4l.u7", 0x200000, 0x078cafc3, 2 | BRF_GRA }, // 4 + { "84ts_4h.u15", 0x200000, 0x1f91446b, 2 | BRF_GRA }, // 5 + { "85ts_5l.u8", 0x200000, 0x40fbd259, 2 | BRF_GRA }, // 6 + { "86ts_5h.u16", 0x200000, 0x186c935f, 2 | BRF_GRA }, // 7 + { "87ts_6l.u1", 0x200000, 0xc17dc48a, 2 | BRF_GRA }, // 8 + { "88ts_6h.u2", 0x200000, 0xe4dba5da, 2 | BRF_GRA }, // 9 + { "89ts_7l.u19", 0x200000, 0xdab1b2c5, 2 | BRF_GRA }, // 10 + { "90ts_7h.u20", 0x200000, 0xaae696b3, 2 | BRF_GRA }, // 11 + { "91ts_8l.u28", 0x200000, 0xe953ace1, 2 | BRF_GRA }, // 12 + { "92ts_8h.u29", 0x200000, 0x9da3b976, 2 | BRF_GRA }, // 13 + { "93ts_9l.u41", 0x200000, 0x233087fe, 2 | BRF_GRA }, // 14 + { "94ts_9h.u42", 0x200000, 0x9da831c7, 2 | BRF_GRA }, // 15 + { "95ts_10l.u58", 0x200000, 0x303a5240, 2 | BRF_GRA }, // 16 + { "96ts_10h.u59", 0x200000, 0x2240ebf6, 2 | BRF_GRA }, // 17 + + { "97ts_snd.u52", 0x400000, 0x9155eca6, 3 | BRF_SND }, // 18 Samples + + { "tgm2p.default.nv", 0x000100, 0xb2328b40, 4 | BRF_PRG | BRF_ESS }, // 19 EEPROM data +}; + +STD_ROM_PICK(tgm2p) +STD_ROM_FN(tgm2p) + +static INT32 Tgm2pInit() +{ + speedhack_address = 0x6000c; + speedhack_pc[0] = 0x0602ae5a; + speedhack_pc[1] = 0x0602b1ac; + speedhack_pc[2] = 0x0602b772; + speedhack_pc[3] = 0x0602b3f2; + + return DrvInit(Tgm2LoadCallback, 1, 0x2c00000, 0x0c00000); +} + +struct BurnDriver BurnDrvTgm2p = { + "tgm2p", "tgm2", NULL, NULL, "2000", + "Tetris the Absolute The Grand Master 2 Plus\0", NULL, "Arika", "PS5V2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PSIKYO, GBF_PUZZLE, 0, + NULL, tgm2pRomInfo, tgm2pRomName, NULL, NULL, Common3ButtonInputInfo, Tgm2DIPInfo, + Tgm2pInit, DrvExit, DrvFrame, PsikyoshDraw, DrvScan, NULL, 0x1400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/psikyo/psikyo.h b/src/burn/drivers/psikyo/psikyo.h new file mode 100644 index 00000000..5049f6c0 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo.h @@ -0,0 +1,44 @@ +#include "burnint.h" + +// General +enum { + PSIKYO_HW_SAMURAIA, + PSIKYO_HW_GUNBIRD, + PSIKYO_HW_S1945, + PSIKYO_HW_TENGAI +}; + +extern INT32 PsikyoHardwareVersion; + +// palette +INT32 PsikyoPalInit(); +INT32 PsikyoPalExit(); +INT32 PsikyoPalUpdate(); + +void PsikyoPalWriteByte(UINT32 nAddress, UINT8 byteValue); +void PsikyoPalWriteWord(UINT32 nAddress, UINT16 wordValue); + +extern UINT8* PsikyoPalSrc; +extern UINT8 PsikyoRecalcPalette; +extern UINT32* PsikyoPalette; + +// Tile rendering +INT32 PsikyoTileRender(); +void PsikyoSetTileBank(INT32 nLayer, INT32 nBank); +INT32 PsikyoTileInit(UINT32 nROMSize); +void PsikyoTileExit(); + +extern UINT8* PsikyoTileROM; +extern UINT8* PsikyoTileRAM[3]; + +extern bool bPsikyoClearBackground; + +// Sprite rendering +INT32 PsikyoSpriteInit(INT32 nROMSize); +void PsikyoSpriteExit(); +INT32 PsikyoSpriteBuffer(); +INT32 PsikyoSpriteRender(INT32 nLowPriority, INT32 nHighPriority); + +extern UINT8* PsikyoSpriteROM; +extern UINT8* PsikyoSpriteRAM; +extern UINT8* PsikyoSpriteLUT; diff --git a/src/burn/drivers/psikyo/psikyo_palette.cpp b/src/burn/drivers/psikyo/psikyo_palette.cpp new file mode 100644 index 00000000..e0036374 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo_palette.cpp @@ -0,0 +1,89 @@ +#include "psikyo.h" + +UINT8* PsikyoPalSrc; +UINT8 PsikyoRecalcPalette; // Set to 1 to force recalculation of the entire palette + +UINT32* PsikyoPalette; +static UINT16* PsikyoPalCopy; + +INT32 PsikyoPalInit() +{ + PsikyoPalette = (UINT32*)malloc(0x1000 * sizeof(UINT32)); + memset(PsikyoPalette, 0, 0x1000 * sizeof(UINT32)); + + PsikyoPalCopy = (UINT16*)malloc(0x1000 * sizeof(UINT16)); + memset(PsikyoPalCopy, 0, 0x1000 * sizeof(UINT16)); + + pBurnDrvPalette = PsikyoPalette; + + return 0; +} + +INT32 PsikyoPalExit() +{ + if (PsikyoPalette) { + free(PsikyoPalette); + PsikyoPalette = NULL; + } + if (PsikyoPalCopy) { + free(PsikyoPalCopy); + PsikyoPalCopy = NULL; + } + + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x7C00) >> 7; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x001F) << 3; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +INT32 PsikyoPalUpdate() +{ + if (PsikyoRecalcPalette) { + UINT16 c; + + for (INT32 i = 0; i < 0x1000; i++) { + c = ((UINT16*)PsikyoPalSrc)[i]; + PsikyoPalCopy[i] = c; + PsikyoPalette[i] = CalcCol(c); + } + + PsikyoRecalcPalette = 0; + } + + return 0; +} + +// Update the PC copy of the palette on writes to the palette memory +void PsikyoPalWriteByte(UINT32 nAddress, UINT8 byteValue) +{ + nAddress ^= 1; + PsikyoPalSrc[nAddress] = byteValue; // write byte + + if (*((UINT8*)(PsikyoPalCopy + nAddress)) != byteValue) { + *((UINT8*)(PsikyoPalCopy + nAddress)) = byteValue; + PsikyoPalette[nAddress >> 1] = CalcCol(*(UINT16*)(PsikyoPalSrc + (nAddress & ~0x01))); + } +} + +void PsikyoPalWriteWord(UINT32 nAddress, UINT16 wordValue) +{ + nAddress >>= 1; + + ((UINT16*)PsikyoPalSrc)[nAddress] = wordValue; // write word + + if (PsikyoPalCopy[nAddress] != wordValue) { + PsikyoPalCopy[nAddress] = wordValue; + PsikyoPalette[nAddress] = CalcCol(wordValue); + } +} diff --git a/src/burn/drivers/psikyo/psikyo_render.h b/src/burn/drivers/psikyo/psikyo_render.h new file mode 100644 index 00000000..fddf8733 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo_render.h @@ -0,0 +1,284 @@ +// Graphics format: 16 × 16 pixel tiles, 4 bits/pixel. + +// Create a unique name for each of the functions +#define FN(a,b,c,d,e,f,g,h) RenderTile ## a ## b ## c ## _ROT ## d ## e ## f ## g ## h +#define FUNCTIONNAME(a,b,c,d,e,f,g,h) FN(a,b,c,d,e,f,g,h) + +#if FLIP == 0 + #define DOFLIP _NOFLIP + #define FLIPX 0 + #define FLIPY 0 +#elif FLIP == 1 + #define DOFLIP _FLIPX + #define FLIPX 1 + #define FLIPY 0 +#elif FLIP == 2 + #define DOFLIP _FLIPY + #define FLIPX 0 + #define FLIPY 1 +#elif FLIP == 3 + #define DOFLIP _FLIPXY + #define FLIPX 1 + #define FLIPY 1 +#else + #error unsupported flip mode specified. +#endif + +#if ZOOM == 0 + #define ZOOMMODE _NOZOOM + #define CHECKX(x) + #if FLIPX == 0 + #define OFFSET(x) (x) + #else + #define OFFSET(x) (15 - (x)) + #endif +#elif ZOOM == 1 + #define ZOOMMODE _ZOOM + #define CHECKX(x) if (x >= nTileXSize) { continue; } + #if FLIPX == 0 + #define OFFSET(x) (pXZoomInfo[x]) + #else + #define OFFSET(x) (15 - pXZoomInfo[x]) + #endif +#else + #error unsupported zoom mode specified. +#endif + +#if ROT == 0 + #if FLIPY == 0 + #define ADVANCEROW pTileRow += ((BPP >> 3) * 320) + #else + #define ADVANCEROW pTileRow -= ((BPP >> 3) * 320) + #endif +#else + #error unsupported rotation angle specified +#endif + +#if DOCLIP == 0 + #define CLIP _NOCLIP +#elif DOCLIP == 1 + #define CLIP _CLIP +#else + #error illegal doclip value. +#endif + +#if TRANS == 15 || TRANS == 0 + #define TESTCOLOUR(x) ((x) != TRANS) + #if TRANS == 0 + #define TRANSMODE _TRANS0 + #else + #define TRANSMODE _TRANS15 + #endif +#elif TRANS == -1 + #define TESTCOLOUR(x) 1 + #define TRANSMODE _SOLID +#else + #error unsupported transparency mode specified +#endif + +#if ZBUFFER == 0 + #define ZBUF _NOZBUFFER + #define ADVANCEZROW + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) +#elif ZBUFFER == 1 + #define ZBUF _RZBUFFER + #define TESTZBUF(a) (pZTileRow[a] <= nZPos) + #define WRITEZBUF(a) +#elif ZBUFFER == 2 + #define ZBUF _WZBUFFER + #define TESTZBUF(a) 1 + #define WRITEZBUF(a) pZTileRow[a] = nZPos +#elif ZBUFFER == 3 + #define ZBUF _RWZBUFFER + #define TESTZBUF(a) (pZTileRow[a] <= nZPos) + #define WRITEZBUF(a) pZTileRow[a] = nZPos +#else + #error unsupported zbuffer mode specified. +#endif + +#if ZBUFFER != 0 + #if FLIPY == 0 + #define ADVANCEZROW pZTileRow += 320 + #else + #define ADVANCEZROW pZTileRow -= 320 + #endif +#endif + +#if BPP == 16 + #define PLOTPIXEL(a, b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + ((UINT16*)pTileRow)[a] = (UINT16)pTilePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a, b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + UINT32 nRGB = pTilePalette[b]; \ + WRITEZBUF(a); \ + pTileRow[3 * a + 0] = (UINT8)nRGB; \ + pTileRow[3 * a + 1] = (UINT8)(nRGB >> 8); \ + pTileRow[3 * a + 2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a, b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \ + WRITEZBUF(a); \ + ((UINT32*)pTileRow)[a] = (UINT32)pTilePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +// For decorating the function name +#if ROWSCROLL == 0 + #define SCROLL _NOROWSCROLL +#elif ROWSCROLL == 1 + #define SCROLL _ROWSCROLL +#else + #error unsupported rowscroll mode specified. +#endif + +static void FUNCTIONNAME(BPP,TRANSMODE,DOFLIP,ROT,SCROLL,ZOOMMODE,ZBUF,CLIP)() +{ +// Create an empty function if unsupported features are requested +#if ROT == 0 + + UINT8* pTileRow; + #if ZBUFFER != 0 + UINT16* pZTileRow; + #endif + + #if ROWSCROLL == 1 + INT32 nRowOffset; + #endif + INT32 y; + + #if ZOOM == 1 + #if ZBUFFER == 0 + #if FLIPY == 0 + for (y = 0, pTileRow = pTile; y < nTileYSize; ADVANCEROW, pTileData += pYZoomInfo[y], y++) { + #else + for (y = nTileYSize - 1, pTileRow = pTile + ((BPP >> 3) * 320 * (nTileYSize - 1)); y >= 0; ADVANCEROW, pTileData += pYZoomInfo[nTileYSize - 1 - y], y--) { + #endif + #else + #if FLIPY == 0 + for (y = 0, pTileRow = pTile, pZTileRow = pZTile; y < nTileYSize; ADVANCEROW, ADVANCEZROW, pTileData += pYZoomInfo[y], y++) { + #else + for (y = nTileYSize - 1, pTileRow = pTile + ((BPP >> 3) * 320 * (nTileYSize - 1)), pZTileRow = pZTile + (320 * (nTileYSize - 1)); y >= 0; ADVANCEROW, ADVANCEZROW, pTileData += pYZoomInfo[nTileYSize - 1 - y], y--) { + #endif + #endif + #else + #if ZBUFFER == 0 + #if FLIPY == 0 + for (y = 0, pTileRow = pTile; y < 16; y++, ADVANCEROW, pTileData += 16) { + #else + for (y = 15, pTileRow = pTile + ((BPP >> 3) * 320 * 15); y >= 0; y--, ADVANCEROW, pTileData += 16) { + #endif + #else + #if FLIPY == 0 + for (y = 0, pTileRow = pTile, pZTileRow = pZTile; y < 16; y++, ADVANCEROW, ADVANCEZROW, pTileData += 16) { + #else + for (y = 15, pTileRow = pTile + ((BPP >> 3) * 320 * 15), pZTileRow = pZTile + (320 * 15); y >= 0; y--, ADVANCEROW, ADVANCEZROW, pTileData += 16) { + #endif + #endif + #endif + + #if DOCLIP == 1 + if (nTileYPos + y < 0) { + #if FLIPY == 0 + continue; + #else + return; + #endif + } + + if (nTileYPos + y >= 224) { + #if FLIPY == 0 + return; + #else + continue; + #endif + } + #endif + + #if ROWSCROLL == 1 + nRowOffset = (nTileXPos - pTileRowInfo[(nTileYPos + y) & 0xFF]) & nTilemapWith; + if (nRowOffset >= 320) { + nRowOffset -= nTilemapWith + 1; + } + if (nRowOffset <= -16) { + continue; + } + #endif + + #if ROWSCROLL == 1 + #define XPOS nRowOffset + #define ROWOFFSET nRowOffset + #else + #define XPOS nTileXPos + #define ROWOFFSET 0 + #endif + + #if DOCLIP == 1 || ROWSCROLL == 1 + #define CLIPPIXEL(a,b) if (XPOS >= 0 - (a) && XPOS < 320 - (a)) { PLOTPIXEL(ROWOFFSET + a,b); } + CLIPPIXEL( 0, pTileData[OFFSET( 0)]); + CLIPPIXEL( 1, pTileData[OFFSET( 1)]); + CLIPPIXEL( 2, pTileData[OFFSET( 2)]); + CLIPPIXEL( 3, pTileData[OFFSET( 3)]); + CLIPPIXEL( 4, pTileData[OFFSET( 4)]); + CLIPPIXEL( 5, pTileData[OFFSET( 5)]); + CLIPPIXEL( 6, pTileData[OFFSET( 6)]); + CLIPPIXEL( 7, pTileData[OFFSET( 7)]); CHECKX( 8); + CLIPPIXEL( 8, pTileData[OFFSET( 8)]); CHECKX( 9); + CLIPPIXEL( 9, pTileData[OFFSET( 9)]); CHECKX(10); + CLIPPIXEL(10, pTileData[OFFSET(10)]); CHECKX(11); + CLIPPIXEL(11, pTileData[OFFSET(11)]); CHECKX(12); + CLIPPIXEL(12, pTileData[OFFSET(12)]); CHECKX(13); + CLIPPIXEL(13, pTileData[OFFSET(13)]); CHECKX(14); + CLIPPIXEL(14, pTileData[OFFSET(14)]); CHECKX(15); + CLIPPIXEL(15, pTileData[OFFSET(15)]); + #undef CLIPPIXEL + #else + PLOTPIXEL( 0, pTileData[OFFSET( 0)]); + PLOTPIXEL( 1, pTileData[OFFSET( 1)]); + PLOTPIXEL( 2, pTileData[OFFSET( 2)]); + PLOTPIXEL( 3, pTileData[OFFSET( 3)]); + PLOTPIXEL( 4, pTileData[OFFSET( 4)]); + PLOTPIXEL( 5, pTileData[OFFSET( 5)]); + PLOTPIXEL( 6, pTileData[OFFSET( 6)]); + PLOTPIXEL( 7, pTileData[OFFSET( 7)]); CHECKX( 8); + PLOTPIXEL( 8, pTileData[OFFSET( 8)]); CHECKX( 9); + PLOTPIXEL( 9, pTileData[OFFSET( 9)]); CHECKX(10); + PLOTPIXEL(10, pTileData[OFFSET(10)]); CHECKX(11); + PLOTPIXEL(11, pTileData[OFFSET(11)]); CHECKX(12); + PLOTPIXEL(12, pTileData[OFFSET(12)]); CHECKX(13); + PLOTPIXEL(13, pTileData[OFFSET(13)]); CHECKX(14); + PLOTPIXEL(14, pTileData[OFFSET(14)]); CHECKX(15); + PLOTPIXEL(15, pTileData[OFFSET(15)]); + #endif + + #undef ROWOFFSET + #undef XPOS + } +#endif +} + +#undef DOFLIP +#undef FLIPX +#undef FLIPY +#undef OFFSET +#undef CHECKX +#undef ZOOMMODE +#undef ZBUF +#undef TRANSMODE +#undef CLIP +#undef WRITEZBUF +#undef PLOTPIXEL +#undef TESTCOLOUR +#undef TESTZBUF +#undef ADVANCEROW +#undef ADVANCEZROW +#undef SCROLL +#undef SELECT +#undef DEPTH +#undef FUNCTIONNAME +#undef FN + diff --git a/src/burn/drivers/psikyo/psikyo_sprite.cpp b/src/burn/drivers/psikyo/psikyo_sprite.cpp new file mode 100644 index 00000000..093dc407 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo_sprite.cpp @@ -0,0 +1,533 @@ +// Psikyo hardware sprites +#include "psikyo.h" + +UINT8* PsikyoSpriteROM = NULL; +UINT8* PsikyoSpriteRAM = NULL; +UINT8* PsikyoSpriteLUT = NULL; + +struct PsikyoSprite { + INT8 flip; + INT8 priority; + INT16 palette; + INT32 x; INT32 y; + INT32 xsize; INT32 ysize; + INT32 xzoom; INT32 yzoom; + INT32 address; +}; + +static INT32 nFrame; + +static INT8* PsikyoSpriteAttrib = NULL; +static INT32 nSpriteAddressMask; + +static PsikyoSprite* pSpriteLists = NULL; +static PsikyoSprite* pSpriteList = NULL; + +static INT32* PsikyoZoomXTable = NULL; +static INT32* PsikyoZoomYTable = NULL; + +static UINT8* pTile; +static UINT8* pTileData; +static UINT32* pTilePalette; + +static UINT16* pZBuffer = NULL; +static UINT16* pZTile; + +static INT32 *pXZoomInfo, *pYZoomInfo; + +static INT32 nTileXPos, nTileYPos, nZPos, nTileXSize, nTileYSize; +static INT32 nXSize, nYSize; + +static INT32 nFirstSprites[8], nLastSprites[8]; +static INT32 *nFirstSprite, *nLastSprite; + +static INT32 nTopSprite; +static INT32 nZOffset; + +typedef void (*RenderSpriteFunction)(); + +// Include the tile rendering functions +#include "psikyo_sprite_func.h" + +static void GetBuffers(INT32 nBuffer) +{ + pSpriteList = pSpriteLists + (nBuffer << 10); + nFirstSprite = nFirstSprites + (nBuffer << 2); + nLastSprite = nLastSprites + (nBuffer << 2); +} + +INT32 PsikyoSpriteRender(INT32 nLowPriority, INT32 nHighPriority) +{ + static INT32 nMaskLeft, nMaskRight, nMaskTop, nMaskBottom; + PsikyoSprite* pBuffer; + INT32 nRenderFunction; + + UINT8* pStart; + UINT16* pZStart = NULL; + + INT32 nAddress, nTransColour, nNextTileX, nNextTileY, nXZoom, nYZoom, nStartXPos; + INT32 nPriorityMask = 0; + INT32 nMaxZPos = -1; + INT32 nMinZPos = 0x00010000; + INT32 nUseBuffer = 0x00010000; + INT32 nCurrentZPos; + + if ((nBurnLayer & 1) == 0) { + return 0; + } + + if (nLowPriority == 0) { + nZPos = -1; + nTopSprite = -1; + + nMaskLeft = nMaskTop = 9999; + nMaskRight = nMaskBottom = -1; + + GetBuffers(nFrame ^ 1); + } + + if (nHighPriority < 3) { + for (INT32 i = nHighPriority + 1; i < 4; i++) { + if (nUseBuffer > nFirstSprite[i]) { + nUseBuffer = nFirstSprite[i]; + } + } + } + + nRenderFunction = (((UINT16*)PsikyoSpriteRAM)[0x0FFF] & 4) << 4; + nTransColour = (nRenderFunction & 64) ? 0 : 15; + + for (INT32 i = nLowPriority; i <= nHighPriority; i++) { + if (nMinZPos > nFirstSprite[i]) { + nMinZPos = nFirstSprite[i]; + } + if (nMaxZPos < nLastSprite[i]) { + nMaxZPos = nLastSprite[i]; + } + nPriorityMask |= 1 << i; + } + + nCurrentZPos = nMinZPos; + + nPriorityMask &= nSpriteEnable; + if (nPriorityMask == 0) { + return 0; + } + + for (pBuffer = pSpriteList + nCurrentZPos; nCurrentZPos <= nMaxZPos; pBuffer++, nCurrentZPos++) { + + if ((pBuffer->priority & nPriorityMask) == 0) { + continue; + } + + nTileXPos = pBuffer->x; + nTileYPos = pBuffer->y; + + pTilePalette = PsikyoPalette + pBuffer->palette; + + nXSize = pBuffer->xsize; + nYSize = pBuffer->ysize; + + nRenderFunction &= 64; + nRenderFunction |= pBuffer->flip << 3; + + nAddress = pBuffer->address; + + switch (pBuffer->flip) { + case 1: + nNextTileX = -1; + nNextTileY = nXSize << 1; + nAddress -= nXSize + 1; + break; + case 2: + nNextTileX = 1; + nNextTileY = -nXSize << 1; + nAddress += (nYSize + 1) * nXSize; + break; + case 3: + nNextTileX = -1; + nNextTileY = 0; + nAddress += nYSize * nXSize - 1; + break; + default: + nNextTileX = 1; + nNextTileY = 0; + } + + if (pBuffer->xzoom == 0 && pBuffer->yzoom == 0) { // This sprite doesn't use zooming + + if (nTopSprite > nCurrentZPos) { // Test ZBuffer + if (nTileXPos < nMaskRight && (nTileXPos + nXSize * 16) >= nMaskLeft && nTileYPos < nMaskBottom && (nTileYPos + nYSize * 16) >= nMaskTop) { + nRenderFunction |= 2; + } + } + + if (nUseBuffer < nCurrentZPos) { // Write ZBuffer + nRenderFunction |= 4; + + if (nTileXPos < nMaskLeft) { + nMaskLeft = nTileXPos; + } + if ((nTileXPos + nXSize) > nMaskRight) { + nMaskRight = nTileXPos + nXSize * 16; + } + if (nTileYPos < nMaskTop) { + nMaskTop = nTileYPos; + } + if ((nTileYPos + nYSize) > nMaskBottom) { + nMaskBottom = nTileYPos + nYSize * 16; + } + } + + if (nRenderFunction & 6) { + pZStart = pZBuffer + (nTileYPos * 320) + nTileXPos; + nZPos = nZOffset + nCurrentZPos; + } + + pStart = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + + for (INT32 y = 0; y < nYSize; y++, nTileYPos += 16, pStart += 16 * nBurnPitch, pZStart += 16 * 320) { + nTileXPos = pBuffer->x; + + pTile = pStart; + pZTile = pZStart; + + nAddress += nNextTileY; + + for (INT32 x = 0; x < nXSize; x++, nTileXPos += 16, nAddress += nNextTileX, pTile += nBurnBpp << 4, pZTile += 16) { + + if (PsikyoSpriteAttrib[((UINT16*)PsikyoSpriteLUT)[nAddress]] == nTransColour) { + continue; + } + + pTileData = PsikyoSpriteROM + ((((UINT16*)PsikyoSpriteLUT)[nAddress] << 8) & nSpriteAddressMask); + if (nTileYPos < 0 || nTileYPos > 208 || nTileXPos < 0 || nTileXPos > 304) { + if (nTileYPos > -16 && nTileYPos < 224 && nTileXPos > -16 && nTileXPos < 320) { + RenderSprite[nRenderFunction + 1](); + } + } else { + RenderSprite[nRenderFunction + 0](); + } + } + } + } else { // This sprite uses zooming + nXZoom = pBuffer->xzoom; + nYZoom = pBuffer->yzoom; + + nTileXPos += (nXSize * nXZoom + 3) >> 2; + nTileYPos += (nYSize * nYZoom + 3) >> 2; + + nXZoom = 32 - nXZoom; + nYZoom = 32 - nYZoom; + + if (nTopSprite > nCurrentZPos) { // Test ZBuffer + if (nTileXPos < nMaskRight && (nTileXPos + nXSize * nXZoom / 2) >= nMaskLeft && nTileYPos < nMaskBottom && (nTileYPos + nYSize * nXZoom / 2) >= nMaskTop) { + nRenderFunction |= 2; + } + } + + if (nUseBuffer < nCurrentZPos) { // Write ZBuffer + nRenderFunction |= 4; + + if (nTileXPos < nMaskLeft) { + nMaskLeft = nTileXPos; + } + if ((nTileXPos + nXSize) > nMaskRight) { + nMaskRight = nTileXPos + nXSize * nXZoom / 2; + } + if (nTileYPos < nMaskTop) { + nMaskTop = nTileYPos; + } + if ((nTileYPos + nYSize) > nMaskBottom) { + nMaskBottom = nTileYPos + nYSize * nYZoom / 2; + } + } + + if (nRenderFunction & 6) { + pZStart = pZBuffer + (nTileYPos * 320) + nTileXPos; + nZPos = nZOffset + nCurrentZPos; + } + + pStart = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + nStartXPos = nTileXPos; + + for (INT32 y = 0; y < nYSize; y++, nTileYPos += nTileYSize, pStart += nTileYSize * nBurnPitch, pZStart += nTileYSize * 320) { + nTileXPos = nStartXPos; + + pTile = pStart; + pZTile = pZStart; + + nAddress += nNextTileY; + + nTileYSize = (y + 1) * nYZoom / 2 - (y * nYZoom / 2); + pYZoomInfo = PsikyoZoomYTable + (nTileYSize << 4); + + for (INT32 x = 0; x < nXSize; x++, nTileXPos += nTileXSize, nAddress += nNextTileX, pTile += nBurnBpp * nTileXSize, pZTile += nTileXSize) { + + nTileXSize = (x + 1) * nXZoom / 2 - (x * nXZoom / 2); + + if (PsikyoSpriteAttrib[((UINT16*)PsikyoSpriteLUT)[nAddress]] == nTransColour) { + continue; + } + + pXZoomInfo = PsikyoZoomXTable + (nTileXSize << 4); + pTileData = PsikyoSpriteROM + ((((UINT16*)PsikyoSpriteLUT)[nAddress] << 8) & nSpriteAddressMask); + if (nTileYPos < 0 || nTileYPos > (224 - nTileYSize) || nTileXPos < 0 || nTileXPos > (320 - nTileXSize)) { + if (nTileYPos > -nTileYSize && nTileYPos < 224 && nTileXPos > -nTileXSize && nTileXPos < 320) { + RenderSprite[nRenderFunction + 33](); + } + } else { + RenderSprite[nRenderFunction + 32](); + } + } + } + } + } + + if (nMaxZPos > nTopSprite) { + nTopSprite = nMaxZPos; + } + + if (nHighPriority == 3) { + if (nZPos >= 0) { + nZOffset += nTopSprite; + if (nZOffset > 0xFC00) { + memset(pZBuffer, 0, 320 * 224 * sizeof(short)); + nZOffset = 0; + } + } + } + + return 0; +} + +INT32 PsikyoSpriteBuffer() +{ + UINT16* pSprite; + PsikyoSprite* pBuffer; + INT32 nPriority; + + UINT16 word; + INT32 x, y, xs, ys; + + nFrame ^= 1; + + GetBuffers(nFrame); + + pBuffer = pSpriteList; + + nFirstSprite[0] = 0x00010000; + nFirstSprite[1] = 0x00010000; + nFirstSprite[2] = 0x00010000; + nFirstSprite[3] = 0x00010000; + + nLastSprite[0] = -1; + nLastSprite[1] = -1; + nLastSprite[2] = -1; + nLastSprite[3] = -1; + + // Check if sprites are disabled + if (((UINT16*)PsikyoSpriteRAM)[0x0FFF] & 1) { + return 0; + } + + for (INT32 i = 0x0C00, z = 0; i < 0x0FFF; i++) { + + word = ((UINT16*)PsikyoSpriteRAM)[i]; + + // Check for end-marker + if (word == 0xFFFF) { + break; + } + + if (word >= 0x0300) { + continue; + } + + // Point to sprite + pSprite = &(((UINT16*)PsikyoSpriteRAM)[word * 4]); + + x = pSprite[1] & 0x01FF; + y = pSprite[0] & 0x01FF; + + xs = ((pSprite[1] >> 9) & 0x0007) + 1; + ys = ((pSprite[0] >> 9) & 0x0007) + 1; + + if (x >= 320) { + x -= 512; + if (x + (xs << 4) < 0) { + continue; + } + } + if (y >= 224) { + y -= 512; + if (y + (ys << 4) < 0) { + continue; + } + } + + // Sprite is active and most likely on screen, so add it to the buffer + + word = pSprite[2]; + + nPriority = 3 - ((word >> 6) & 0x03); + + if (nLastSprite[nPriority] == -1) { + nFirstSprite[nPriority] = z; + } + nLastSprite[nPriority] = z; + + pBuffer->priority = 1 << nPriority; + + pBuffer->xzoom = pSprite[1] >> 12; + pBuffer->yzoom = pSprite[0] >> 12; + + pBuffer->xsize = xs; + pBuffer->ysize = ys; + + pBuffer->x = x; + pBuffer->y = y; + + pBuffer->flip = (word >> 14) & 0x03; + pBuffer->palette = (word >> 4) & 0x01F0; + + pBuffer->address = pSprite[3] | ((word & 1) << 16); + + pBuffer++; + z++; + } + + return 0; +} + +void PsikyoSpriteExit() +{ + if (PsikyoZoomXTable) { + free(PsikyoZoomXTable); + PsikyoZoomXTable = NULL; + } + if (PsikyoZoomYTable) { + free(PsikyoZoomYTable); + PsikyoZoomYTable = NULL; + } + if (PsikyoSpriteAttrib) { + free(PsikyoSpriteAttrib); + PsikyoSpriteAttrib = NULL; + } + if (pSpriteLists) { + free(pSpriteLists); + pSpriteLists = NULL; + } + if (pZBuffer) { + free(pZBuffer); + pZBuffer = NULL; + } + + return; +} + +INT32 PsikyoSpriteInit(INT32 nROMSize) +{ + const INT32 nTileSize = 256; + INT32 nNumTiles = nROMSize / nTileSize; + + if (pSpriteLists) { + free(pSpriteLists); + pSpriteLists = NULL; + } + pSpriteLists = (PsikyoSprite*)malloc(0x0800 * sizeof(PsikyoSprite)); + if (pSpriteLists == NULL) { + PsikyoSpriteExit(); + return 1; + } + + for (INT32 i = 0; i < 8; i++) { + nFirstSprites[i] = 0x00010000; + nLastSprites[i] = -1; + } + + if (pZBuffer) { + free(pZBuffer); + pZBuffer = NULL; + } + pZBuffer = (UINT16*)malloc(320 * 224 * sizeof(UINT16)); + if (pZBuffer == NULL) { + PsikyoSpriteExit(); + return 1; + } + + memset(pZBuffer, 0, 320 * 224 * sizeof(UINT16)); + nZOffset = 0; + + for (nSpriteAddressMask = 1; nSpriteAddressMask < nROMSize; nSpriteAddressMask <<= 1) {} + nSpriteAddressMask--; + + if (PsikyoSpriteAttrib) { + free(PsikyoSpriteAttrib); + PsikyoSpriteAttrib = NULL; + } + PsikyoSpriteAttrib = (INT8*)malloc(nSpriteAddressMask + 1); + if (PsikyoSpriteAttrib == NULL) { + return 1; + } + + for (INT32 i = 0; i < nNumTiles; i++) { + bool bTransparent0 = true; + bool bTransparent15 = true; + for (INT32 j = i * nTileSize; j < (i + 1) * nTileSize; j++) { + if (PsikyoSpriteROM[j] != 0x00) { + bTransparent0 = false; + if (!bTransparent15) { + break; + } + } + if (PsikyoSpriteROM[j] != 0xFF) { + bTransparent15 = false; + if (!bTransparent0) { + break; + } + } + } + PsikyoSpriteAttrib[i] = (INT8)0xFF; + if (bTransparent0) { + PsikyoSpriteAttrib[i] = 0; + } + if (bTransparent15) { + PsikyoSpriteAttrib[i] = 15; + } + } + + for (INT32 i = nNumTiles; i <= nSpriteAddressMask; i++) { + PsikyoSpriteAttrib[i] = (INT8)0xFF; + } + + PsikyoZoomXTable = (INT32*)malloc(272 * sizeof(INT32)); + PsikyoZoomYTable = (INT32*)malloc(272 * sizeof(INT32)); + if (PsikyoZoomXTable == NULL || PsikyoZoomYTable == NULL) { + PsikyoSpriteExit(); + return 1; + } + + memset(PsikyoZoomXTable, 0, 272 * sizeof(INT32)); + memset(PsikyoZoomYTable, 0, 272 * sizeof(INT32)); + + for (INT32 z = 8; z < 16; z++) { + for (INT32 i = 0, x = 0; i < z; i++, x += 0x100000 / z) { + PsikyoZoomXTable[(z << 4) + i] = (x + 0x8000) >> 16; + } + for (INT32 i = 1; i < z; i++) { + PsikyoZoomYTable[(z << 4) + i - 1] = (PsikyoZoomXTable[(z << 4) + i] - PsikyoZoomXTable[(z << 4) + i - 1]) << 4; +// bprintf(PRINT_NORMAL, "%2i:%2i - ", PsikyoZoomXTable[(z << 4) + i - 1], PsikyoZoomYTable[(z << 4) + i - 1]); + } + PsikyoZoomYTable[(z << 4) + z - 1] = PsikyoZoomYTable[(z << 4)]; +// bprintf(PRINT_NORMAL, "%2i:%2i\n", PsikyoZoomXTable[(z << 4) + z - 1], PsikyoZoomYTable[(z << 4) + z - 1]); + } + for (INT32 i = 0; i < 16; i++) { + PsikyoZoomXTable[256 + i] = i; + PsikyoZoomYTable[256 + i] = 16; + } + + nFrame = 0; + + return 0; +} diff --git a/src/burn/drivers/psikyo/psikyo_sprite_func.h b/src/burn/drivers/psikyo/psikyo_sprite_func.h new file mode 100644 index 00000000..8192f263 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo_sprite_func.h @@ -0,0 +1,761 @@ +#define ROT 0 +#define BPP 16 +#define ROWSCROLL 0 + +#define TRANS 0 + +#define ZOOM 0 + +#define FLIP 0 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 1 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 2 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 3 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP + +#undef ZOOM +#define ZOOM 1 + +#define FLIP 0 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 1 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 2 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 3 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP + +#undef ZOOM + +#undef TRANS +#define TRANS 15 + +#define ZOOM 0 + +#define FLIP 0 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 1 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 2 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 3 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP + +#undef ZOOM +#define ZOOM 1 + +#define FLIP 0 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 1 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 2 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP +#define FLIP 3 + +#define ZBUFFER 0 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 1 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 2 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER +#define ZBUFFER 3 + +#define DOCLIP 0 +#include "psikyo_render.h" +#undef DOCLIP +#define DOCLIP 1 +#include "psikyo_render.h" +#undef DOCLIP + +#undef ZBUFFER + +#undef FLIP + +#undef ZOOM + +#undef TRANS + +#undef ROWSCROLL +#undef ROT +#undef BPP + +// no zbuffer/no clip, no zbuffer/clip, read zbuffer/no clip, read zbuffer/clip, write zbuffer/no clip, write zbuffer/clip, read/write zbuffer/no clip, read/write zbuffer/clip, +static RenderSpriteFunction RenderSprite[] = { + // Transparency 15, no zooming + &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + // Transparency 15, zooming + &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPX_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS15_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + + // Transparency 0, no zooming + &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_NOZOOM_RWZBUFFER_CLIP, + // Transparency 0, zooming + &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_NOFLIP_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPX_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, + &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_NOZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_WZBUFFER_CLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_NOCLIP, &RenderTile16_TRANS0_FLIPXY_ROT0_NOROWSCROLL_ZOOM_RWZBUFFER_CLIP, +}; diff --git a/src/burn/drivers/psikyo/psikyo_tile.cpp b/src/burn/drivers/psikyo/psikyo_tile.cpp new file mode 100644 index 00000000..ed938d06 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyo_tile.cpp @@ -0,0 +1,287 @@ +// Psikyo hardware tilemaps + +#include "psikyo.h" + +UINT8* PsikyoTileROM; +UINT8* PsikyoTileRAM[3] = { NULL, }; + +bool bPsikyoClearBackground; + +static UINT32 PsikyoLayerAttrib[3] = { 0, }; +static INT32 PsikyoLayerXOffset[2] = { 0, }; +static INT32 PsikyoLayerYOffset[2] = { 0, }; + +static INT8* PsikyoTileAttrib = { NULL, }; +static INT32 PsikyoTileMask; + +static UINT32 PsikyoTileBank[2]; + +static UINT8* pTile; +static UINT8* pTileData; +static UINT32* pTilePalette; +static INT16* pTileRowInfo; + +typedef void (*RenderTileFunction)(); + +static INT32 nTilemapWith, nTileXPos, nTileYPos; + +// Include the tile rendering functions +#include "psikyo_tile_func.h" + +static void PsikyoRenderLayer(INT32 nLayer) +{ + static INT32 nLayerXSize[] = { 0x0040, 0x0080, 0x0100, 0x0020 }; +// static INT32 nLayerYSize[] = { 0x0040, 0x0020, 0x0010, 0x0080 }; + + INT32 x, y; + INT32 ax, bx, ay, by, cx, cy, mx; + INT32 minx, maxx; + INT32 nTileColumn, nTileRow; + UINT32 nTileNumber, nTilePalette, nTileBank; + INT32 nRenderFunction, nTransColour; + bool bClip; + + UINT16* pTileRAM = (UINT16*)(PsikyoTileRAM[nLayer]); + + UINT32* LayerPalette = PsikyoPalette + (nLayer ? 0x0C00 : 0x0800); + + nTileBank = PsikyoTileBank[nLayer]; + + mx = nLayerXSize[(PsikyoLayerAttrib[nLayer] & 0xC0) >> 6]; + + pTileRowInfo = (INT16*)(PsikyoTileRAM[2] + (nLayer << 9)); + nTilemapWith = (mx << 4) - 1; + + nRenderFunction = 8; + nTransColour = 99; + if ((bPsikyoClearBackground || nLayer) && (PsikyoLayerAttrib[nLayer] & 0x02) == 0) { + if (PsikyoLayerAttrib[nLayer] & 0x08) { + nRenderFunction = 0; + nTransColour = 0; + } else { + nRenderFunction = 4; + nTransColour = 15; + } + } + + // Compute the tile offsets + ax = PsikyoLayerXOffset[nLayer]; + bx = 16 - (ax & 0x0F); + cx = (ax >> 4) + 1; + + ay = PsikyoLayerYOffset[nLayer]; + by = 16 - (ay & 0x0F); + cy = ((ay >> 4) + 1) * mx; + + for (nTileYPos = -16 + by, y = -mx; nTileYPos < 224; nTileYPos += 16, y += mx) { + + if (nTileYPos <= -16) { + continue; + } + + nTileRow = (cy + y) & 0x0FFF; + + bClip = (nTileYPos < 0 || nTileYPos > 208); + + if (PsikyoLayerAttrib[nLayer] & 0x0300) { + if (PsikyoLayerAttrib[nLayer] & 0x0200) { + + // per-tile rowscroll; each tilerow has it's own offset to the tilemap x offset + + minx = pTileRowInfo[(nTileYPos >> 4) & 0x0F]; + } else { + + // Rowscroll enabled + + minx = 32767; maxx = -32768; + + // Compute the min/max row offsets + for (int i = 0; i < 16; i++) { + if (pTileRowInfo[(nTileYPos + i) & 0xFF] > maxx) { + maxx = pTileRowInfo[(nTileYPos + i) & 0xFF]; + } + if (pTileRowInfo[(nTileYPos + i) & 0xFF] < minx) { + minx = pTileRowInfo[(nTileYPos + i) & 0xFF]; + } + } + + // If rowscroll is enabled, but each line of the tilerow has the + // same offset, we can use the normal tilemap rendering + // Otherwise, use specific rowscroll rendering + if (minx != maxx) { + + // Compute the tile offsets + ax = PsikyoLayerXOffset[nLayer]; + bx = 16 - (ax & 0x0F); + cx = (ax >> 4) + 1; + + maxx = 21 + (maxx >> 4); + minx = (minx - 16) >> 4; + + for (x = minx, nTileXPos = (minx << 4) + bx; x < maxx; x++, nTileXPos += 16) { + + nTileColumn = (cx + x) & (mx - 1); + nTileNumber = pTileRAM[nTileRow + nTileColumn]; + nTilePalette = nTileNumber >> 13; + nTileNumber = (nTileNumber & 0x1FFF) + nTileBank; + + if (PsikyoTileAttrib[nTileNumber] == nTransColour) { + continue; + } + + pTile = pBurnDraw + (nTileYPos * nBurnPitch); + pTileData = PsikyoTileROM + (nTileNumber << 8); + pTilePalette = LayerPalette + (nTilePalette << 4); + + if (bClip) { + RenderTile[nRenderFunction + 3](); + } else { + RenderTile[nRenderFunction + 2](); + } + } + + continue; + } + } + + // Compute the tile offsets + ax = PsikyoLayerXOffset[nLayer] + minx; + bx = 16 - (ax & 0x0F); + cx = (ax >> 4) + 1; + } + + for (nTileXPos = -16 + bx, x = -1; nTileXPos < 320; nTileXPos += 16, x++) { + + if (nTileXPos <= -16) { + continue; + } + + nTileColumn = (cx + x) & (mx - 1); + nTileNumber = pTileRAM[nTileRow + nTileColumn]; + nTilePalette = nTileNumber >> 13; + nTileNumber = (nTileNumber & 0x1FFF) + nTileBank; + + if (PsikyoTileAttrib[nTileNumber] == nTransColour) { + continue; + } + + pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp); + pTileData = PsikyoTileROM + (nTileNumber << 8); + pTilePalette = LayerPalette + (nTilePalette << 4); + + if (bClip || nTileXPos < 0 || nTileXPos > 304) { + RenderTile[nRenderFunction + 1](); + } else { + RenderTile[nRenderFunction + 0](); + } + } + } + + return; +} + +void PsikyoSetTileBank(INT32 nLayer, INT32 nBank) +{ + PsikyoTileBank[nLayer] = nBank << 13; +} + +INT32 PsikyoTileRender() +{ + INT32 nPriority, nLowPriority = 0; + + PsikyoLayerAttrib[0] = *((INT16*)(PsikyoTileRAM[2] + 0x0412)); + PsikyoLayerXOffset[0] = *((INT16*)(PsikyoTileRAM[2] + 0x0406)); + PsikyoLayerYOffset[0] = *((INT16*)(PsikyoTileRAM[2] + 0x0402)); + + PsikyoLayerAttrib[1] = *((INT16*)(PsikyoTileRAM[2] + 0x0416)); + PsikyoLayerXOffset[1] = *((INT16*)(PsikyoTileRAM[2] + 0x040E)); + PsikyoLayerYOffset[1] = *((INT16*)(PsikyoTileRAM[2] + 0x040A)); + + if (PsikyoHardwareVersion == PSIKYO_HW_GUNBIRD) { + PsikyoTileBank[0] = (PsikyoLayerAttrib[0] & 0x0400) << 3; + PsikyoTileBank[1] = (PsikyoLayerAttrib[1] & 0x0400) << 3; + } + + if (bPsikyoClearBackground || ((PsikyoLayerAttrib[0] & 0x01) && (PsikyoLayerAttrib[1] & 0x02)) || (nBurnLayer & 0x0C) != 0x0C) { + BurnClearScreen(); + } + + for (nPriority = 1; nPriority < 4; nPriority++) { + + INT32 nLayer = nPriority - 1; + + if ((PsikyoLayerAttrib[nLayer] & 1) == 0 || nPriority == 3) { + PsikyoSpriteRender(nLowPriority, nPriority); + nLowPriority = nPriority + 1; + } + + if (nLayer < 2 && (PsikyoLayerAttrib[nLayer] & 1) == 0 && (PsikyoLayerAttrib[nLayer + 1] & 0x02) == 0 && (nBurnLayer & (4 << nLayer))) { + PsikyoRenderLayer(nLayer); + } + } + + return 0; +} + +void PsikyoTileExit() +{ + if (PsikyoTileAttrib) { + free(PsikyoTileAttrib); + PsikyoTileAttrib = NULL; + } + + return; +} + +INT32 PsikyoTileInit(UINT32 nROMSize) +{ + const INT32 nTileSize = 256; + INT32 nNumTiles = nROMSize / nTileSize; + + for (PsikyoTileMask = 1; PsikyoTileMask < nNumTiles; PsikyoTileMask <<= 1) { } + PsikyoTileMask--; + + if (PsikyoTileAttrib) { + free(PsikyoTileAttrib); + PsikyoTileAttrib = NULL; + } + PsikyoTileAttrib = (INT8*)malloc(PsikyoTileMask + 1); + if (PsikyoTileAttrib == NULL) { + return 1; + } + + for (INT32 i = 0; i < nNumTiles; i++) { + bool bTransparent0 = true; + bool bTransparent15 = true; + for (INT32 j = i * nTileSize; j < (i + 1) * nTileSize; j++) { + if (PsikyoTileROM[j] != 0x00) { + bTransparent0 = false; + if (!bTransparent15) { + break; + } + } + if (PsikyoTileROM[j] != 0xFF) { + bTransparent15 = false; + if (!bTransparent0) { + break; + } + } + } + PsikyoTileAttrib[i] = (INT8)0xFF; + if (bTransparent0) { + PsikyoTileAttrib[i] = 0; + } + if (bTransparent15) { + PsikyoTileAttrib[i] = 15; + } + } + + for (INT32 i = nNumTiles; i <= PsikyoTileMask; i++) { + PsikyoTileAttrib[i] = (INT8)0xFF; + } + + PsikyoTileBank[0] = 0x0000; + PsikyoTileBank[1] = 0x2000; + + return 0; +} diff --git a/src/burn/drivers/psikyo/psikyosh_render.cpp b/src/burn/drivers/psikyo/psikyosh_render.cpp new file mode 100644 index 00000000..823d5fed --- /dev/null +++ b/src/burn/drivers/psikyo/psikyosh_render.cpp @@ -0,0 +1,743 @@ +// Video rendering module for Psikyo SH2 games +// Lots of code here and there ripped directly from MAME +// Thanks to David Haywood for the initial MAME driver +// as well as some other valuable pointers. + +#include "tiles_generic.h" // nScreenWidth & nScreenHeight +#include "psikyosh_render.h" // contains loads of macros + +UINT8 *pPsikyoshTiles; +UINT32 *pPsikyoshSpriteBuffer; +UINT32 *pPsikyoshBgRAM; +UINT32 *pPsikyoshVidRegs; +UINT32 *pPsikyoshPalRAM; +UINT32 *pPsikyoshZoomRAM; + +static UINT8 *DrvTransTab; +static UINT8 alphatable[0x100]; + +static UINT16 *DrvPriBmp; +static UINT8 *DrvZoomBmp; +static INT32 nDrvZoomPrev = -1; +static UINT32 *DrvTmpDraw; +static UINT32 *DrvTmpDraw_ptr; + +static INT32 nGraphicsMin0; // minimum tile number 4bpp +static INT32 nGraphicsMin1; // for 8bpp +static INT32 nGraphicsSize; // normal +static INT32 nGraphicsSize0; // for 4bpp +static INT32 nGraphicsSize1; // for 8bpp + +//-------------------------------------------------------------------------------- + +static inline UINT32 alpha_blend(UINT32 d, UINT32 s, UINT32 p) +{ + if (p == 0) return d; + + INT32 a = 256 - p; + + return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) | + ((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) >> 8; +} + +//-------------------------------------------------------------------------------- + +static void draw_blendy_tile(INT32 gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 alpha, INT32 z) +{ + color <<= 4; + UINT32 *pal = pBurnDrvPalette + color; + + if (gfx == 0) { + code &= 0x7ffff; + code -= nGraphicsMin0; + if (code < 0 || code > nGraphicsSize0) return; + + if (DrvTransTab[code >> 3] & (1 << (code & 7))) return; + + UINT8 *src = pPsikyoshTiles + (code << 7); + + INT32 inc = 8; + if (fy) { + inc = -8; + src += 0x78; + } + + if (sx >= 0 && sx < (nScreenWidth-15) && sy >= 0 && sy <= (nScreenHeight-15)) { + if (z > 0) { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX() + } else { + PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_PRIO() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_PRIO() + } else { + PUTPIXEL_4BPP_ALPHATAB_PRIO() + } + } + } else { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_FLIPX() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_FLIPX() + } else { + PUTPIXEL_4BPP_ALPHATAB_FLIPX() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA() + } else { + PUTPIXEL_4BPP_ALPHATAB() + } + } + } + } else { + if (z > 0) { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX_CLIP() + } else { + PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX_CLIP() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_PRIO_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_PRIO_CLIP() + } else { + PUTPIXEL_4BPP_ALPHATAB_PRIO_CLIP() + } + } + } else { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_FLIPX_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_FLIPX_CLIP() + } else { + PUTPIXEL_4BPP_ALPHATAB_FLIPX_CLIP() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_4BPP_NORMAL_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_4BPP_ALPHA_CLIP() + } else { + PUTPIXEL_4BPP_ALPHATAB_CLIP() + } + } + } + } + } else { + code &= 0x3ffff; + code -= nGraphicsMin1; + if (code < 0 || code > nGraphicsSize0) return; + + if (DrvTransTab[(code >> 3) + 0x10000] & (1 << (code & 7))) return; + + UINT8 *src = pPsikyoshTiles + (code << 8); + + INT32 inc = 16; + if (fy) { + inc = -16; + src += 0xf0; + } + + if (sx >= 0 && sx < (nScreenWidth-15) && sy >= 0 && sy < (nScreenHeight-15)) { + if (z > 0) { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX() + } else { + PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_PRIO() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_PRIO() + } else { + PUTPIXEL_8BPP_ALPHATAB_PRIO() + } + } + } else { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_FLIPX() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_FLIPX() + } else { + PUTPIXEL_8BPP_ALPHATAB_FLIPX() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA() + } else { + PUTPIXEL_8BPP_ALPHATAB() + } + } + } + } else { + if (z > 0) { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX_CLIP() + } else { + PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX_CLIP() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_PRIO_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_PRIO_CLIP() + } else { + PUTPIXEL_8BPP_ALPHATAB_PRIO_CLIP() + } + } + } else { + if (fx) { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_FLIPX_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_FLIPX_CLIP() + } else { + PUTPIXEL_8BPP_ALPHATAB_FLIPX_CLIP() + } + } else { + if (alpha == 0xff) { + PUTPIXEL_8BPP_NORMAL_CLIP() + } else if (alpha >= 0) { + PUTPIXEL_8BPP_ALPHA_CLIP() + } else { + PUTPIXEL_8BPP_ALPHATAB_CLIP() + } + } + } + + } + } +} + +static void draw_prezoom(INT32 gfx, INT32 code, INT32 high, INT32 wide) +{ + // these probably aren't the safest routines, but they should be pretty fast. + + if (gfx) { + INT32 tileno = (code & 0x3ffff) - nGraphicsMin1; + if (tileno < 0 || tileno > nGraphicsSize1) tileno = 0; + if (nDrvZoomPrev == tileno) return; + nDrvZoomPrev = tileno; + UINT32 *gfxptr = (UINT32*)(pPsikyoshTiles + (tileno << 8)); + + for (INT32 ytile = 0; ytile < high; ytile++) + { + for (INT32 xtile = 0; xtile < wide; xtile++) + { + UINT32 *dest = (UINT32*)(DrvZoomBmp + (ytile << 12) + (xtile << 4)); + + for (INT32 ypixel = 0; ypixel < 16; ypixel++, gfxptr += 4) { + + dest[0] = gfxptr[0]; + dest[1] = gfxptr[1]; + dest[2] = gfxptr[2]; + dest[3] = gfxptr[3]; + + dest += 64; + } + } + } + } else { + INT32 tileno = (code & 0x7ffff) - nGraphicsMin0; + if (tileno < 0 || tileno > nGraphicsSize0) tileno = 0; + if (nDrvZoomPrev == tileno) return; + nDrvZoomPrev = tileno; + UINT8 *gfxptr = pPsikyoshTiles + (tileno << 7); + for (INT32 ytile = 0; ytile < high; ytile++) + { + for (INT32 xtile = 0; xtile < wide; xtile++) + { + UINT8 *dest = DrvZoomBmp + (ytile << 12) + (xtile << 4); + + for (INT32 ypixel = 0; ypixel < 16; ypixel++, gfxptr += 8) + { + for (INT32 xpixel = 0; xpixel < 16; xpixel+=2) + { + INT32 c = gfxptr[xpixel>>1]; + dest[xpixel ] = c >> 4; + dest[xpixel + 1] = c & 0x0f; + } + + dest += 256; + } + } + } + } +} + +static void psikyosh_drawgfxzoom(INT32 gfx, UINT32 code, INT32 color, INT32 flipx, INT32 flipy, INT32 offsx, + INT32 offsy, INT32 alpha, INT32 zoomx, INT32 zoomy, INT32 wide, INT32 high, INT32 z) +{ + if (~nBurnLayer & 8) return; + if (!zoomx || !zoomy) return; + + if (zoomx == 0x400 && zoomy == 0x400) + { + INT32 xstart, ystart, xend, yend, xinc, yinc, code_offset = 0; + + if (flipx) { xstart = wide-1; xend = -1; xinc = -1; } + else { xstart = 0; xend = wide; xinc = +1; } + + if (flipy) { ystart = high-1; yend = -1; yinc = -1; } + else { ystart = 0; yend = high; yinc = +1; } + + for (INT32 ytile = ystart; ytile != yend; ytile += yinc ) + { + for (INT32 xtile = xstart; xtile != xend; xtile += xinc ) + { + INT32 sx = offsx + (xtile << 4); + INT32 sy = offsy + (ytile << 4); + + draw_blendy_tile(gfx, code + code_offset++, color, sx, sy, flipx, flipy, alpha, z); + } + } + } + else + { + draw_prezoom(gfx, code, high, wide); + + { + UINT32 *pal = pBurnDrvPalette + (color << 4); + + INT32 sprite_screen_height = ((high << 24) / zoomy + 0x200) >> 10; + INT32 sprite_screen_width = ((wide << 24) / zoomx + 0x200) >> 10; + + if (sprite_screen_width && sprite_screen_height) + { + INT32 sx = offsx; + INT32 sy = offsy; + INT32 ex = sx + sprite_screen_width; + INT32 ey = sy + sprite_screen_height; + + INT32 x_index_base; + INT32 y_index; + + INT32 dx, dy; + + if (flipx) { x_index_base = (sprite_screen_width-1)*zoomx; dx = -zoomx; } + else { x_index_base = 0; dx = zoomx; } + + if (flipy) { y_index = (sprite_screen_height-1)*zoomy; dy = -zoomy; } + else { y_index = 0; dy = zoomy; } + + { + if (sx < 0) { + INT32 pixels = 0-sx; + sx += pixels; + x_index_base += pixels*dx; + } + if (sy < 0 ) { + INT32 pixels = 0-sy; + sy += pixels; + y_index += pixels*dy; + } + if (ex > nScreenWidth) { + INT32 pixels = ex-(nScreenWidth-1)-1; + ex -= pixels; + } + if (ey > nScreenHeight) { + INT32 pixels = ey-(nScreenHeight-1)-1; + ey -= pixels; + } + } + + if (ex > sx) + { + if (alpha == 0xff) { + if (z > 0) { + PUTPIXEL_ZOOM_NORMAL_PRIO() + } else { + PUTPIXEL_ZOOM_NORMAL() + } + } else if (alpha >= 0) { + if (z > 0) { + PUTPIXEL_ZOOM_ALPHA_PRIO() + } else { + PUTPIXEL_ZOOM_ALPHA() + } + } else { + if (z > 0) { + PUTPIXEL_ZOOM_ALPHATAB_PRIO() + } else { + PUTPIXEL_ZOOM_ALPHATAB() + } + } + } + } + } + } +} + +static void draw_sprites(UINT8 req_pri) +{ + UINT32 *src = pPsikyoshSpriteBuffer; + UINT16 *list = (UINT16 *)src + 0x3800/2; + UINT16 listlen = 0x800/2; + UINT16 listcntr = 0; + UINT16 *zoom_table = (UINT16 *)pPsikyoshZoomRAM; + UINT8 *alpha_table = (UINT8 *)pPsikyoshVidRegs; + + while (listcntr < listlen) + { + UINT32 xpos, ypos, high, wide, flpx, flpy, zoomx, zoomy, tnum, colr, dpth, pri; + INT32 alpha; + + UINT32 listdat = list[listcntr ^ 1]; + UINT32 sprnum = (listdat & 0x03ff) << 2; + + pri = (src[sprnum+1] & 0x00003000) >> 12; + pri = (pPsikyoshVidRegs[2] << (pri << 2)) >> 28; + + if (pri == req_pri) + { + ypos = (src[sprnum+0] & 0x03ff0000) >> 16; + xpos = (src[sprnum+0] & 0x000003ff); + high =((src[sprnum+1] & 0x0f000000) >> 24) + 1; + wide =((src[sprnum+1] & 0x00000f00) >> 8) + 1; + flpy = (src[sprnum+1] & 0x80000000) >> 31; + flpx = (src[sprnum+1] & 0x00008000) >> 15; + zoomy = (src[sprnum+1] & 0x00ff0000) >> 16; + zoomx = (src[sprnum+1] & 0x000000ff); + tnum = (src[sprnum+2] & 0x0007ffff); + dpth = (src[sprnum+2] & 0x00800000) >> 23; + colr = (src[sprnum+2] & 0xff000000) >> 24; + alpha = (src[sprnum+2] & 0x00700000) >> 20; + + if (ypos & 0x200) ypos -= 0x400; + if (xpos & 0x200) xpos -= 0x400; + + alpha = alpha_table[alpha ^ 3]; + + if (alpha & 0x80) { + alpha = -1; + } else { + alpha = alphatable[alpha | 0xc0]; + } + + if (zoom_table[zoomy ^ 1] && zoom_table[zoomx ^ 1]) + { + psikyosh_drawgfxzoom(dpth, tnum, colr, flpx, flpy, xpos, ypos, alpha, + (UINT32)zoom_table[zoomx ^ 1],(UINT32)zoom_table[zoomy ^ 1], wide, high, listcntr); + } + } + + listcntr++; + if (listdat & 0x4000) break; + } +} + +static void draw_layer(INT32 layer, INT32 bank, INT32 alpha, INT32 scrollx, INT32 scrolly) +{ + if ((bank < 0x0c) || (bank > 0x1f)) return; + + if (alpha & 0x80) { + alpha = -1; + } else { + alpha = alphatable[alpha | 0xc0]; + } + + INT32 attr = pPsikyoshVidRegs[7] << (layer << 2); + INT32 gfx = attr & 0x00004000; + INT32 size =(attr & 0x00001000) ? 32 : 16; + INT32 wide = size * 16; + + for (INT32 offs = 0; offs < size * 32; offs++) { + INT32 sx = (offs & 0x1f) << 4; + INT32 sy = (offs >> 5) << 4; + + sx = (sx + scrollx) & 0x1ff; + sy = (sy + scrolly) & (wide-1); + if (sx >= nScreenWidth) sx -= 0x200; + if (sy >= nScreenHeight) sy -= wide; + if (sx < -15 || sy < -15) continue; + + UINT32 code = pPsikyoshBgRAM[(bank*0x800)/4 + offs - 0x4000/4]; + + draw_blendy_tile(gfx, code & 0x7ffff, (code >> 24), sx, sy, 0, 0, alpha, 0); + } +} + +static void draw_bglayer(INT32 layer) +{ + if (!(nBurnLayer & 1)) return; + + INT32 scrollx, scrolly, bank, alpha; + INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f; + INT32 offset = (scrollbank == 0x0b) ? 0x200 : 0; + + bank = (pPsikyoshBgRAM[0x17f0/4 + offset + layer] & 0x000000ff); + alpha = (pPsikyoshBgRAM[0x17f0/4 + offset + layer] & 0x0000bf00) >> 8; + scrollx = (pPsikyoshBgRAM[0x13f0/4 + offset + layer] & 0x000001ff); + scrolly = (pPsikyoshBgRAM[0x13f0/4 + offset + layer] & 0x03ff0000) >> 16; + + if (scrollbank == 0x0d) scrollx += 0x08; + + draw_layer(layer, bank, alpha, scrollx, scrolly); +} + +static void draw_bglayertext(INT32 layer) +{ + if (~nBurnLayer & 2) return; + + INT32 scrollx, scrolly, bank, alpha; + INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f; + + bank = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x000000ff); + alpha = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x0000bf00) >> 8; + scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 ] & 0x000001ff); + scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 ] & 0x03ff0000) >> 16; + + draw_layer(layer, bank, alpha, scrollx, scrolly); + + bank = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 + 0x20/4 - 0x4000/4] & 0x000000ff); + alpha = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 + 0x20/4 - 0x4000/4] & 0x0000bf00) >> 8; + scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 + 0x20/4 ] & 0x000001ff); + scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 + 0x20/4 ] & 0x03ff0000) >> 16; + + draw_layer(layer, bank, alpha, scrollx, scrolly); +} + +static void draw_bglayerscroll(INT32 layer) +{ + if (!(nBurnLayer & 4)) return; + + INT32 scrollx, bank, alpha; + INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f; + + bank = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x000000ff); + alpha = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x0000bf00) >> 8; + scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 ] & 0x000001ff); +// scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 ] & 0x03ff0000) >> 16; + + draw_layer(layer, bank, alpha, scrollx, 0); +} + +static void draw_background(UINT8 req_pri) +{ + for (INT32 i = 0; i < 3; i++) + { + if (!((pPsikyoshVidRegs[7] << (i << 2)) & 0x8000)) + continue; + + INT32 bgtype = ((pPsikyoshVidRegs[6] << (i << 3)) >> 24) & 0x7f; + + switch (bgtype) + { + case 0x0a: // Normal + if((pPsikyoshBgRAM[0x17f0/4 + (i*0x04)/4] >> 24) == req_pri) + draw_bglayer(i); + break; + + case 0x0b: // Alt / Normal + if((pPsikyoshBgRAM[0x1ff0/4 + (i*0x04)/4] >> 24) == req_pri) + draw_bglayer(i); + break; + + case 0x0c: // Using normal for now + case 0x0d: // Using normal for now + if((pPsikyoshBgRAM[(bgtype*0x800)/4 + 0x400/4 - 0x4000/4] >> 24) == req_pri) + draw_bglayertext(i); + break; + + case 0x0e: + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + if((pPsikyoshBgRAM[(bgtype*0x800)/4 + 0x400/4 - 0x4000/4] >> 24) == req_pri) + draw_bglayerscroll(i); + break; + } + } +} + +static void prelineblend() +{ + UINT32 *linefill = pPsikyoshBgRAM; + UINT32 *destline = DrvTmpDraw; + + for (INT32 y = 0; y < nScreenHeight; y++, destline+=nScreenWidth) { + if (linefill[y] & 0xff) { + for (INT32 x = 0; x < nScreenWidth; x++) { + destline[x] = linefill[y] >> 8; + } + } + } +} + +static void postlineblend() +{ + UINT32 *lineblend = pPsikyoshBgRAM + 0x0400/4; + UINT32 *destline = DrvTmpDraw; + + for (INT32 y = 0; y < nScreenHeight; y++, destline+=nScreenWidth) { + if (lineblend[y] & 0x80) { + for (INT32 x = 0; x < nScreenWidth; x++) { + destline[x] = lineblend[y] >> 8; + } + } + else if (lineblend[y] & 0x7f) { + for (INT32 x = 0; x < nScreenWidth; x++) { + destline[x] = alpha_blend(destline[x], lineblend[y] >> 8, (lineblend[y] & 0x7f) << 1); + } + } + } +} + +INT32 PsikyoshDraw() +{ + { + for (INT32 i = 0; i < 0x5000 / 4; i++) { + pBurnDrvPalette[i] = pPsikyoshPalRAM[i] >> 8; + } + } + + if (nBurnBpp == 4) { + DrvTmpDraw = (UINT32*)pBurnDraw; + } else { + DrvTmpDraw = DrvTmpDraw_ptr; + } + + memset (DrvTmpDraw, 0, nScreenWidth * nScreenHeight * sizeof(UINT32)); + memset (DrvPriBmp, 0, nScreenWidth * nScreenHeight * sizeof(INT16)); + + UINT32 *psikyosh_vidregs = pPsikyoshVidRegs; + + prelineblend(); + + for (UINT32 i = 0; i < 8; i++) { + draw_sprites(i); + draw_background(i); + if ((psikyosh_vidregs[2] & 0x0f) == i) postlineblend(); + } + + if (nBurnBpp < 4) { + for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) { + INT32 d = DrvTmpDraw[i]; + PutPix(pBurnDraw + i * nBurnBpp, BurnHighCol(d>>16, d>>8, d, 0)); + } + } + + return 0; +} + +static void fill_alphatable() +{ + for (INT32 i = 0; i < 0xc0; i++) + alphatable[i] = 0xff; + + for (INT32 i = 0; i < 0x40; i++) { + alphatable[i | 0xc0] = ((0x3f - i) * 0xff) / 0x3f; + } +} + +static void calculate_transtab() +{ + DrvTransTab = (UINT8*)malloc(0x18000); + + memset (DrvTransTab, 0xff, 0x18000); + + // first calculate all 4bpp tiles + for (INT32 i = 0; i < nGraphicsSize; i+= 0x80) { + for (INT32 j = 0; j < 0x80; j++) { + if (pPsikyoshTiles[i + j]) { + DrvTransTab[(i>>10) + 0x00000] &= ~(1 << ((i >> 7) & 7)); + break; + } + } + } + + // next, calculate all 8bpp tiles + for (INT32 i = 0; i < nGraphicsSize; i+= 0x100) { + for (INT32 j = 0; j < 0x100; j++) { + if (pPsikyoshTiles[i + j]) { + DrvTransTab[(i>>11) + 0x10000] &= ~(1 << ((i >> 8) & 7)); + break; + } + } + } +} + +void PsikyoshVideoInit(INT32 gfx_max, INT32 gfx_min) +{ + DrvZoomBmp = (UINT8 *)malloc(16 * 16 * 16 * 16); + DrvPriBmp = (UINT16*)malloc(320 * 240 * sizeof(INT16)); + DrvTmpDraw_ptr = (UINT32 *)malloc(320 * 240 * sizeof(UINT32)); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth); + } else { + BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight); + } + + nGraphicsSize = gfx_max - gfx_min; + nGraphicsMin0 = (gfx_min / 128); + nGraphicsMin1 = (gfx_min / 256); + nGraphicsSize0 = (nGraphicsSize / 128) - 1; + nGraphicsSize1 = (nGraphicsSize / 256) - 1; + + calculate_transtab(); + fill_alphatable(); +} + +void PsikyoshVideoExit() +{ + if (DrvZoomBmp) { + free (DrvZoomBmp); + DrvZoomBmp = NULL; + } + + if (DrvPriBmp) { + free (DrvPriBmp); + DrvPriBmp = NULL; + } + + if (DrvTmpDraw_ptr) { + free (DrvTmpDraw_ptr); + DrvTmpDraw_ptr = NULL; + } + + DrvTmpDraw = NULL; + + if (DrvTransTab) { + free (DrvTransTab); + DrvTransTab = NULL; + } + + nDrvZoomPrev = -1; + pPsikyoshTiles = NULL; + pPsikyoshSpriteBuffer = NULL; + pPsikyoshBgRAM = NULL; + pPsikyoshVidRegs = NULL; + pPsikyoshPalRAM = NULL; + pPsikyoshZoomRAM = NULL; + pBurnDrvPalette = NULL; + + nScreenWidth = nScreenHeight = 0; +} diff --git a/src/burn/drivers/psikyo/psikyosh_render.h b/src/burn/drivers/psikyo/psikyosh_render.h new file mode 100644 index 00000000..8d164938 --- /dev/null +++ b/src/burn/drivers/psikyo/psikyosh_render.h @@ -0,0 +1,270 @@ +extern UINT8 *pPsikyoshTiles; +extern UINT32 *pPsikyoshSpriteBuffer; +extern UINT32 *pPsikyoshBgRAM; +extern UINT32 *pPsikyoshVidRegs; +extern UINT32 *pPsikyoshPalRAM; +extern UINT32 *pPsikyoshZoomRAM; + +void PsikyoshVideoInit(INT32 gfx_max, INT32 gfx_min); +void PsikyoshVideoExit(); +INT32 PsikyoshDraw(); + + +//-------------------------------------------------------------------------------- +// Macro hell. + +// Standard tile drawing with full clipping. +//----------------------------------------------------------------------- +#define PUTPIXEL_CLIP(forloop, splitpixel, putpixel) \ + UINT32 *dest; \ + for (INT32 y = 0; y < 16; y++, sy++, src+=inc) { \ + if (sy < 0 || sy >= nScreenHeight) continue; \ + \ + dest = DrvTmpDraw + sy * nScreenWidth; \ + \ +forloop \ + { \ + if (sx < 0 || sx >= nScreenWidth) continue; \ + \ +splitpixel \ + \ + if (c) { \ +putpixel \ + } \ + } \ + \ + sx -= 16; \ + } + +// Tile drawing with clipping and priority +//----------------------------------------------------------------------- +#define PUTPIXEL_PRIO_CLIP(forloop, splitpixel, putpixel) \ + UINT32 *dest; \ + UINT16 *pri; \ + for (INT32 y = 0; y < 16; y++, sy++, src+=inc) { \ + if (sy < 0 || sy >= nScreenHeight) continue; \ + \ + dest = DrvTmpDraw + sy * nScreenWidth; \ + pri = DrvPriBmp + sy * nScreenWidth; \ + \ + forloop { \ + if (sx < 0 || sx >= nScreenWidth) continue; \ + \ + if (z >= pri[sx]) { \ +splitpixel \ + \ + if (c) { \ +putpixel \ + pri[sx] = z; \ + } \ + } \ + } \ + \ + sx -= 16; \ + } + +// Standard tile drawing with no clipping. +//----------------------------------------------------------------------- +#define PUTPIXEL(forloop, splitpixel, putpixel) \ + UINT32 *dest = DrvTmpDraw + sy * nScreenWidth; \ + for (INT32 y = 0; y < 16; y++, sy++, src+=inc) { \ +forloop \ + { \ + \ +splitpixel \ + \ + if (c) { \ +putpixel \ + } \ + } \ + \ + dest += nScreenWidth; \ + sx -= 16; \ + } + +// Tile drawing with no clipping and with priorities. +//----------------------------------------------------------------------- +#define PUTPIXEL_PRIO(forloop, splitpixel, putpixel) \ + UINT32 *dest = DrvTmpDraw + sy * nScreenWidth; \ + UINT16 *pri = DrvPriBmp + sy * nScreenWidth; \ + for (INT32 y = 0; y < 16; y++, sy++, src+=inc) { \ + forloop { \ + if (z >= pri[sx]) { \ +splitpixel \ + \ + if (c) { \ +putpixel \ + pri[sx] = z; \ + } \ + } \ + } \ + dest += nScreenWidth; \ + pri += nScreenWidth; \ + sx -= 16; \ + } + +// Zoom drawing with priorities. +//----------------------------------------------------------------------- +#define ZOOMPIXEL_PRIO(putpixel) \ + for (INT32 y = sy; y < ey; y++) \ + { \ + UINT8 *source = DrvZoomBmp + (y_index >> 10) * 256; \ + UINT32 *dest = DrvTmpDraw + y * nScreenWidth; \ + UINT16 *pri = DrvPriBmp + y * nScreenWidth; \ + \ + INT32 x_index = x_index_base; \ + for (INT32 x = sx; x < ex; x++) \ + { \ + if (z >= pri[x]) \ + { \ + INT32 c = source[x_index>>10]; \ + if (c) \ + { \ +putpixel \ + pri[x] = z; \ + } \ + } \ + x_index += dx; \ + } \ + y_index += dy; \ + } + +// Standard Zoom drawing +//----------------------------------------------------------------------- +#define ZOOMPIXEL_NORMAL(putpixel) \ + for (INT32 y = sy; y < ey; y++) \ + { \ + UINT8 *source = DrvZoomBmp + (y_index >> 10) * 256; \ + UINT32 *dest = DrvTmpDraw + y * nScreenWidth; \ + INT32 x_index = x_index_base; \ + \ + for (INT32 x = sx; x < ex; x++) \ + { \ + INT32 c = source[x_index>>10]; \ + if(c) { \ +putpixel \ + } \ + x_index += dx; \ + } \ + y_index += dy; \ + } + +//-------------------------------------------------------------------------------- + +// split up a 4bpp pixel +#define SPLITPIXEL \ + INT32 c = src[(x >> 1)]; \ + if (x & 1) { \ + c &= 0xf; \ + } else { \ + c >>= 4; \ + } + +// use 8bpp pixel +#define NORMALPIXEL INT32 c = src[x]; + +#define SETNORMALPIXEL dest[sx] = pal[c]; + +#define SETBLENDPIXEL dest[sx] = alpha_blend(dest[sx], pal[c], alpha); + +#define SETVARIABLEPIXEL \ + if (alphatable[c] == 0xff) { \ + dest[sx] = pal[c]; \ + } else { \ + dest[sx] = alpha_blend(dest[sx], pal[c], alphatable[c]); \ + } + +#define FORLOOP_NORMAL for (INT32 x = 0; x < 16; x++, sx++) + +#define FORLOOP_FLIPX for (INT32 x = 15; x >= 0; x--, sx++) + +// set pixels for zoom routines +#define ZSETNORMALPIXEL dest[x] = pal[c]; + +#define ZSETBLENDPIXEL dest[x] = alpha_blend(dest[x], pal[c], alpha); + +#define ZSETVARIABLEPIXEL \ + if (alphatable[c] == 0xff) { \ + dest[x] = pal[c]; \ + } else { \ + dest[x] = alpha_blend(dest[x], pal[c], alphatable[c]); \ + } + +//-------------------------------------------------------------------------------- + +// these aren't really necessary, they just help me keep track of what things do... + +#define PUTPIXEL_4BPP_NORMAL_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_CLIP() PUTPIXEL_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_PRIO_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_NORMAL, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX_CLIP()PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_FLIPX_CLIP() PUTPIXEL_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX_CLIP() PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX_CLIP()PUTPIXEL_PRIO_CLIP(FORLOOP_FLIPX, NORMALPIXEL, SETVARIABLEPIXEL) + + +#define PUTPIXEL_4BPP_NORMAL() PUTPIXEL(FORLOOP_NORMAL, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA() PUTPIXEL(FORLOOP_NORMAL, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB() PUTPIXEL(FORLOOP_NORMAL, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL() PUTPIXEL(FORLOOP_NORMAL, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA() PUTPIXEL(FORLOOP_NORMAL, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB() PUTPIXEL(FORLOOP_NORMAL, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_PRIO() PUTPIXEL_PRIO(FORLOOP_NORMAL, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_FLIPX() PUTPIXEL(FORLOOP_FLIPX, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_FLIPX() PUTPIXEL(FORLOOP_FLIPX, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_FLIPX() PUTPIXEL(FORLOOP_FLIPX, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX() PUTPIXEL_PRIO(FORLOOP_FLIPX, SPLITPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX() PUTPIXEL_PRIO(FORLOOP_FLIPX, SPLITPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX() PUTPIXEL_PRIO(FORLOOP_FLIPX, SPLITPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_FLIPX() PUTPIXEL(FORLOOP_FLIPX, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_FLIPX() PUTPIXEL(FORLOOP_FLIPX, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_FLIPX() PUTPIXEL(FORLOOP_FLIPX, NORMALPIXEL, SETVARIABLEPIXEL) + +#define PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX() PUTPIXEL_PRIO(FORLOOP_FLIPX, NORMALPIXEL, SETNORMALPIXEL) +#define PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX() PUTPIXEL_PRIO(FORLOOP_FLIPX, NORMALPIXEL, SETBLENDPIXEL) +#define PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX()PUTPIXEL_PRIO(FORLOOP_FLIPX, NORMALPIXEL, SETVARIABLEPIXEL) + + +#define PUTPIXEL_ZOOM_NORMAL_PRIO() ZOOMPIXEL_PRIO(ZSETNORMALPIXEL) +#define PUTPIXEL_ZOOM_NORMAL() ZOOMPIXEL_NORMAL(ZSETNORMALPIXEL) + +#define PUTPIXEL_ZOOM_ALPHA_PRIO() ZOOMPIXEL_PRIO(ZSETBLENDPIXEL) +#define PUTPIXEL_ZOOM_ALPHA() ZOOMPIXEL_NORMAL(ZSETBLENDPIXEL) + +#define PUTPIXEL_ZOOM_ALPHATAB_PRIO() ZOOMPIXEL_PRIO(ZSETVARIABLEPIXEL) +#define PUTPIXEL_ZOOM_ALPHATAB() ZOOMPIXEL_NORMAL(ZSETVARIABLEPIXEL) diff --git a/src/burn/drivers/sega/d_hangon.cpp b/src/burn/drivers/sega/d_hangon.cpp new file mode 100644 index 00000000..3ff18c0d --- /dev/null +++ b/src/burn/drivers/sega/d_hangon.cpp @@ -0,0 +1,1432 @@ +#include "sys16.h" + +/*==================================================== +Input Defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo EndurorInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Bank Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort3, "p1 fire 2" ), + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Enduror) + +static struct BurnInputInfo HangonInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Hangon) + +static struct BurnInputInfo ShangonrbInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Super Charger" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Shangonrb) + +static struct BurnInputInfo SharrierInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + {"Fire 1" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , System16InputPort0 + 6, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , System16InputPort0 + 7, "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Sharrier) + +#undef A + +/*==================================================== +Dip defs +====================================================*/ + +#define HANGON_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo EndurorDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x7e, NULL }, + + // Dip 1 + HANGON_COINAGE(0x0a) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + {0x0b, 0x01, 0x01, 0x01, "Wheelie" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x06, 0x04, "Easy" }, + {0x0b, 0x01, 0x06, 0x06, "Medium" }, + {0x0b, 0x01, 0x06, 0x02, "Hard" }, + {0x0b, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0b, 0x01, 0x18, 0x10, "Easy" }, + {0x0b, 0x01, 0x18, 0x18, "Medium" }, + {0x0b, 0x01, 0x18, 0x08, "Hard" }, + {0x0b, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Control" }, + {0x0b, 0x01, 0x60, 0x40, "Easy" }, + {0x0b, 0x01, 0x60, 0x60, "Medium" }, + {0x0b, 0x01, 0x60, 0x20, "Hard" }, + {0x0b, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x80, 0x80, "Off" }, + {0x0b, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Enduror) + +static struct BurnDIPInfo HangonDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + HANGON_COINAGE(0x09) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x01, 0x01, "Off" }, + {0x0a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0x06, 0x04, "Easy" }, + {0x0a, 0x01, 0x06, 0x06, "Medium" }, + {0x0a, 0x01, 0x06, 0x02, "Hard" }, + {0x0a, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0a, 0x01, 0x18, 0x18, "Normal" }, + {0x0a, 0x01, 0x18, 0x10, "Medium" }, + {0x0a, 0x01, 0x18, 0x08, "Hard" }, + {0x0a, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Play Music" }, + {0x0a, 0x01, 0x20, 0x00, "Off" }, + {0x0a, 0x01, 0x20, 0x20, "On" }, +}; + +STDDIPINFO(Hangon) + +static struct BurnDIPInfo ShangonrbDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x1e, NULL }, + + // Dip 1 + HANGON_COINAGE(0x0a) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x06, 0x04, "Easy" }, + {0x0b, 0x01, 0x06, 0x06, "Normal" }, + {0x0b, 0x01, 0x06, 0x02, "Hard" }, + {0x0b, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0b, 0x01, 0x18, 0x10, "Easy" }, + {0x0b, 0x01, 0x18, 0x18, "Normal" }, + {0x0b, 0x01, 0x18, 0x08, "Hard" }, + {0x0b, 0x01, 0x18, 0x00, "Hardest" }, +}; + +STDDIPINFO(Shangonrb) + +static struct BurnDIPInfo SharrierDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + HANGON_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x01, 0x00, "Upright" }, + {0x0c, 0x01, 0x01, 0x01, "Moving" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x02, "Off" }, + {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x0c, 0x08, "2" }, + {0x0c, 0x01, 0x0c, 0x0c, "3" }, + {0x0c, 0x01, 0x0c, 0x04, "4" }, + {0x0c, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x10, 0x10, "5000000" }, + {0x0c, 0x01, 0x10, 0x00, "7000000" }, + + {0 , 0xfe, 0 , 2 , "Trial Time" }, + {0x0c, 0x01, 0x20, 0x20, "Off" }, + {0x0c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Medium" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Sharrier) + +#undef HANGON_COINAGE + +/*==================================================== +Rom Defs +====================================================*/ + +static struct BurnRomInfo EndurorRomDesc[] = { + { "epr-7640a.ic97", 0x08000, 0x1d1dc5d4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7636a.ic84", 0x08000, 0x84131639, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7641.ic98", 0x08000, 0x2503ae7c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7637.ic85", 0x08000, 0x82a27a8c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7642.ic99", 0x08000, 0x1c453bea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7638.ic86", 0x08000, 0x70544779, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7634a.ic54", 0x08000, 0xaec83731, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-7635a.ic67", 0x08000, 0xb2fce96f, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-7644.ic31", 0x08000, 0xe7a4ff90, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7645.ic46", 0x08000, 0x4caa0095, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7646.ic60", 0x08000, 0x7e432683, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7678.ic36", 0x08000, 0x9fb5e656, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7670.ic28", 0x08000, 0xdbbe2f6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7662.ic18", 0x08000, 0xcb0c13c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7654.1c8", 0x08000, 0x2db6520d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7677.ic35", 0x08000, 0x7764765b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7669.ic27", 0x08000, 0xf9525faa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7661.ic17", 0x08000, 0xfe93a79b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7653.ic7", 0x08000, 0x46a52114, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7676.ic34", 0x08000, 0x2e42e0d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7668.ic26", 0x08000, 0xe115ce33, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7660.ic16", 0x08000, 0x86dfbb68, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7652.ic6", 0x08000, 0x2880cfdb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7675.ic33", 0x08000, 0x05cd2d61, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7667.ic25", 0x08000, 0x923bde9d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7659.ic15", 0x08000, 0x629dc8ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7651.ic5", 0x08000, 0xd7902bad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7674.ic32", 0x08000, 0x1a129acf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7666.ic24", 0x08000, 0x23697257, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7658.ic14", 0x08000, 0x1677f24f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7650.ic4", 0x08000, 0x642635ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7673.ic31", 0x08000, 0x82602394, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7665.ic23", 0x08000, 0x12d77607, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7657.ic13", 0x08000, 0x8158839c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7649.ic3", 0x08000, 0x4edba14c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7672.ic30", 0x08000, 0xd11452f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7664.ic22", 0x08000, 0x0df2cfad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7656.ic12", 0x08000, 0x6c741272, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7648.ic2", 0x08000, 0x983ea830, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7671.ic29", 0x08000, 0xb0c7fdc6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7663.ic21", 0x08000, 0x2b0b8f08, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7655.ic11", 0x08000, 0x3433fe7b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7647.ic1", 0x08000, 0x2e7fbec0, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7633.ic1", 0x08000, 0x6f146210, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-7682.rom", 0x08000, 0xc4efbf48, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-7681.rom", 0x08000, 0xbc0c4d12, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-7680.rom", 0x08000, 0x627b3c8c, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, + + { "317-0013a.key", 0x02000, 0x295e6737, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Enduror) +STD_ROM_FN(Enduror) + +static struct BurnRomInfo Enduror1RomDesc[] = { + { "epr-7630.ic97", 0x08000, 0xa1bdadab, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7629.ic84", 0x08000, 0xf50f4169, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7641.ic98", 0x08000, 0x2503ae7c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7637.ic85", 0x08000, 0x82a27a8c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7642.ic99", 0x08000, 0x1c453bea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7638.ic86", 0x08000, 0x70544779, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7634.ic54", 0x08000, 0x3e07fd32, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-7635.ic67", 0x08000, 0x22f762ab, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-7644.ic31", 0x08000, 0xe7a4ff90, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7645.ic46", 0x08000, 0x4caa0095, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7646.ic60", 0x08000, 0x7e432683, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7678.ic36", 0x08000, 0x9fb5e656, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7670.ic28", 0x08000, 0xdbbe2f6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7662.ic18", 0x08000, 0xcb0c13c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7654.1c8", 0x08000, 0x2db6520d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7677.ic35", 0x08000, 0x7764765b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7669.ic27", 0x08000, 0xf9525faa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7661.ic17", 0x08000, 0xfe93a79b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7653.ic7", 0x08000, 0x46a52114, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7676.ic34", 0x08000, 0x2e42e0d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7668.ic26", 0x08000, 0xe115ce33, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7660.ic16", 0x08000, 0x86dfbb68, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7652.ic6", 0x08000, 0x2880cfdb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7675.ic33", 0x08000, 0x05cd2d61, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7667.ic25", 0x08000, 0x923bde9d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7659.ic15", 0x08000, 0x629dc8ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7651.ic5", 0x08000, 0xd7902bad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7674.ic32", 0x08000, 0x1a129acf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7666.ic24", 0x08000, 0x23697257, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7658.ic14", 0x08000, 0x1677f24f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7650.ic4", 0x08000, 0x642635ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7673.ic31", 0x08000, 0x82602394, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7665.ic23", 0x08000, 0x12d77607, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7657.ic13", 0x08000, 0x8158839c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7649.ic3", 0x08000, 0x4edba14c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7672.ic30", 0x08000, 0xd11452f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7664.ic22", 0x08000, 0x0df2cfad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7656.ic12", 0x08000, 0x6c741272, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7648.ic2", 0x08000, 0x983ea830, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7671.ic29", 0x08000, 0xb0c7fdc6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7663.ic21", 0x08000, 0x2b0b8f08, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7655.ic11", 0x08000, 0x3433fe7b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7647.ic1", 0x08000, 0x2e7fbec0, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7633.ic1", 0x08000, 0x6f146210, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-7765.ic73", 0x04000, 0x81c82fc9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + { "epr-7764.ic72", 0x04000, 0x755bfdad, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-7762.ic5", 0x08000, 0xbc0c4d12, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-7763.ic6", 0x08000, 0x627b3c8c, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, + + { "317-0013a.key", 0x02000, 0x295e6737, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Enduror1) +STD_ROM_FN(Enduror1) + +static struct BurnRomInfo EnduroblRomDesc[] = { + { "7.13j", 0x10000, 0xf1d6b4b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "4.13h", 0x10000, 0x43bff873, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "8.14j", 0x08000, 0x2153154a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "5.14h", 0x08000, 0x0a97992c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "9.15j", 0x08000, 0xdb3bff1c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "6.15h", 0x08000, 0x54b1885a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7634.ic54", 0x08000, 0x3e07fd32, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-7635.ic67", 0x08000, 0x22f762ab, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-7644.ic31", 0x08000, 0xe7a4ff90, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7645.ic46", 0x08000, 0x4caa0095, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7646.ic60", 0x08000, 0x7e432683, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7678.ic36", 0x08000, 0x9fb5e656, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7670.ic28", 0x08000, 0xdbbe2f6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7662.ic18", 0x08000, 0xcb0c13c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7654.1c8", 0x08000, 0x2db6520d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7677.ic35", 0x08000, 0x7764765b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7669.ic27", 0x08000, 0xf9525faa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7661.ic17", 0x08000, 0xfe93a79b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7653.ic7", 0x08000, 0x46a52114, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7676.ic34", 0x08000, 0x2e42e0d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7668.ic26", 0x08000, 0xe115ce33, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7660.ic16", 0x08000, 0x86dfbb68, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7652.ic6", 0x08000, 0x2880cfdb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7675.ic33", 0x08000, 0x05cd2d61, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7667.ic25", 0x08000, 0x923bde9d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7659.ic15", 0x08000, 0x629dc8ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7651.ic5", 0x08000, 0xd7902bad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7674.ic32", 0x08000, 0x1a129acf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7666.ic24", 0x08000, 0x23697257, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7658.ic14", 0x08000, 0x1677f24f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7650.ic4", 0x08000, 0x642635ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7673.ic31", 0x08000, 0x82602394, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7665.ic23", 0x08000, 0x12d77607, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7657.ic13", 0x08000, 0x8158839c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7649.ic3", 0x08000, 0x4edba14c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7672.ic30", 0x08000, 0xd11452f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7664.ic22", 0x08000, 0x0df2cfad, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7656.ic12", 0x08000, 0x6c741272, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7648.ic2", 0x08000, 0x983ea830, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7671.ic29", 0x08000, 0xb0c7fdc6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7663.ic21", 0x08000, 0x2b0b8f08, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7655.ic11", 0x08000, 0x3433fe7b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7647.ic1", 0x08000, 0x2e7fbec0, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7633.ic1", 0x08000, 0x6f146210, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-7765.ic73", 0x04000, 0x81c82fc9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + { "epr-7764.ic72", 0x04000, 0x755bfdad, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-7762.ic5", 0x08000, 0xbc0c4d12, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-7763.ic6", 0x08000, 0x627b3c8c, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, +}; + + +STD_ROM_PICK(Endurobl) +STD_ROM_FN(Endurobl) + +static struct BurnRomInfo HangonRomDesc[] = { + { "epr-6918a.ic22", 0x08000, 0x20b1c2b0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6916a.ic8", 0x08000, 0x7d9db1bf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6917a.ic20", 0x08000, 0xfea12367, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6915a.ic6", 0x08000, 0xac883240, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-6920.ic63", 0x08000, 0x1c95013e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-6919.ic51", 0x08000, 0x6ca30d69, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-6841.ic38", 0x08000, 0x54d295dc, SYS16_ROM_TILES | BRF_GRA }, + { "epr-6842.ic23", 0x08000, 0xf677b568, SYS16_ROM_TILES | BRF_GRA }, + { "epr-6843.ic7", 0x08000, 0xa257f0da, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-6819.ic27", 0x08000, 0x469dad07, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6820.ic34", 0x08000, 0x87cbc6de, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6821.ic28", 0x08000, 0x15792969, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6822.ic35", 0x08000, 0xe9718de5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6823.ic29", 0x08000, 0x49422691, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6824.ic36", 0x08000, 0x701deaa4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6825.ic30", 0x08000, 0x6e23c8b4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6826.ic37", 0x08000, 0x77d0de2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6827.ic31", 0x08000, 0x7fa1bfb6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6828.ic38", 0x08000, 0x8e880c93, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6829.ic32", 0x08000, 0x7ca0952d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6830.ic39", 0x08000, 0xb1a63aef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6845.ic18", 0x08000, 0xba08c9b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6846.ic25", 0x08000, 0xf21e57a3, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-6840.ic108", 0x08000, 0x581230e3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-6833.ic73", 0x04000, 0x3b942f5f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-6831.ic5", 0x08000, 0xcfef5481, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-6832.ic6", 0x08000, 0x4165aea5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, +}; + + +STD_ROM_PICK(Hangon) +STD_ROM_FN(Hangon) + +static struct BurnRomInfo Hangon1RomDesc[] = { + { "epr-6918.ic22", 0x08000, 0x0bf4f2ac, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6916.ic8", 0x08000, 0x06c21c8a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6917.ic20", 0x08000, 0xf48a6cbc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-6915.ic6", 0x08000, 0x75d3b5ee, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-6920.ic63", 0x08000, 0x1c95013e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-6919.ic51", 0x08000, 0x6ca30d69, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-6841.ic38", 0x08000, 0x54d295dc, SYS16_ROM_TILES | BRF_GRA }, + { "epr-6842.ic23", 0x08000, 0xf677b568, SYS16_ROM_TILES | BRF_GRA }, + { "epr-6843.ic7", 0x08000, 0xa257f0da, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-6819.ic27", 0x08000, 0x469dad07, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6820.ic34", 0x08000, 0x87cbc6de, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6821.ic28", 0x08000, 0x15792969, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6822.ic35", 0x08000, 0xe9718de5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6823.ic29", 0x08000, 0x49422691, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6824.ic36", 0x08000, 0x701deaa4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6825.ic30", 0x08000, 0x6e23c8b4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6826.ic37", 0x08000, 0x77d0de2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6827.ic31", 0x08000, 0x7fa1bfb6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6828.ic38", 0x08000, 0x8e880c93, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6829.ic32", 0x08000, 0x7ca0952d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6830.ic39", 0x08000, 0xb1a63aef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6845.ic18", 0x08000, 0xba08c9b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-6846.ic25", 0x08000, 0xf21e57a3, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-6840.ic108", 0x08000, 0x581230e3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-6833.ic73", 0x04000, 0x3b942f5f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-6831.ic5", 0x08000, 0xcfef5481, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-6832.ic6", 0x08000, 0x4165aea5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, +}; + + +STD_ROM_PICK(Hangon1) +STD_ROM_FN(Hangon1) + +static struct BurnRomInfo ShangonroRomDesc[] = { + { "epr-10842.22", 0x08000, 0x24289138, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10839.8", 0x08000, 0x70f92d5e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10841.20", 0x08000, 0x3bb2186c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10838.6", 0x08000, 0x6aded05a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10840.18", 0x08000, 0x12ee8716, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10837.4", 0x08000, 0x155e0cfd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10831.25", 0x10000, 0x3a2de9eb, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10833.31", 0x10000, 0x13ba98bc, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10830.24", 0x10000, 0x2ae4e53a, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10832.30", 0x10000, 0x543cd7bb, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.38", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.23", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.7", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10675.22", 0x10000, 0xd6ac012b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10682.11", 0x10000, 0xd9d83250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10676.21", 0x10000, 0x25ebf2c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10683.12", 0x10000, 0x6365d2e9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10677.20", 0x10000, 0x8a57b8d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10684.11", 0x10000, 0x3aff8910, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10678.19", 0x10000, 0xaf473098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10685.10", 0x10000, 0x80bafeef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10679.18", 0x10000, 0x03bc4878, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10686.9", 0x10000, 0x274b734e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10680.17", 0x10000, 0x9f0677ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10687.8", 0x10000, 0x508a4701, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10681.16", 0x10000, 0xb176ea72, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10688.7", 0x10000, 0x42fcd51d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10866.108", 0x08000, 0x1bbe4fc8, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10834a.52", 0x08000, 0x83347dc0, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10835.55", 0x10000, 0xda08ca2b, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10836.56", 0x10000, 0x8b10e601, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.119", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, + + { "317-0038.key", 0x02000, 0x85943925, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shangonro) +STD_ROM_FN(Shangonro) + +static struct BurnRomInfo ShangonrbRomDesc[] = { + { "s-hangon.30", 0x10000, 0xd95e82fc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "s-hangon.32", 0x10000, 0x2ee4b4fb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "s-hangon.29", 0x08000, 0x12ee8716, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "s-hangon.31", 0x08000, 0x155e0cfd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "s-hangon.09", 0x10000, 0x070c8059, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "s-hangon.05", 0x10000, 0x9916c54b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "s-hangon.08", 0x10000, 0x000ad595, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "s-hangon.04", 0x10000, 0x8f8f4af0, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.38", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.23", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.7", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10675.22", 0x10000, 0xd6ac012b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10682.11", 0x10000, 0xd9d83250, SYS16_ROM_SPRITES | BRF_GRA }, + { "s-hangon.20", 0x10000, 0xeef23b3d, SYS16_ROM_SPRITES | BRF_GRA }, + { "s-hangon.14", 0x10000, 0x0f26d131, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10677.20", 0x10000, 0x8a57b8d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10684.11", 0x10000, 0x3aff8910, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10678.19", 0x10000, 0xaf473098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10685.10", 0x10000, 0x80bafeef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10679.18", 0x10000, 0x03bc4878, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10686.9", 0x10000, 0x274b734e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10680.17", 0x10000, 0x9f0677ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10687.8", 0x10000, 0x508a4701, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10681.16", 0x10000, 0xb176ea72, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10688.7", 0x10000, 0x42fcd51d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10866.108", 0x08000, 0x1bbe4fc8, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10834a.52", 0x08000, 0x83347dc0, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10835.55", 0x10000, 0xda08ca2b, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10836.56", 0x10000, 0x8b10e601, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.119", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, +}; + + +STD_ROM_PICK(Shangonrb) +STD_ROM_FN(Shangonrb) + +static struct BurnRomInfo SharrierRomDesc[] = { + { "epr-7188a.ic97", 0x08000, 0x45e173c3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7184a.ic84", 0x08000, 0xe1934a51, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7189.ic98", 0x08000, 0x40b1309f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7185.ic85", 0x08000, 0xce78045c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7190.ic99", 0x08000, 0xf6391091, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7186.ic86", 0x08000, 0x79b367d7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7191.ic100", 0x08000, 0x6171e9d3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7187.ic87", 0x08000, 0x70cb72ef, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7182.ic54", 0x08000, 0xd7c535b6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-7183.ic67", 0x08000, 0xa6153af8, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-7196.ic31", 0x08000, 0x347fa325, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7197.ic46", 0x08000, 0x39d98bd1, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7198.ic60", 0x08000, 0x3da3ea6b, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7230.ic36", 0x08000, 0x93e2d264, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7222.ic28", 0x08000, 0xedbf5fc3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7214.ic18", 0x08000, 0xe8c537d8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7206.ic8", 0x08000, 0x22844fa4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7229.ic35", 0x08000, 0xcd6e7500, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7221.ic27", 0x08000, 0x41f25a9c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7213.ic17", 0x08000, 0x5bb09a67, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7205.ic7", 0x08000, 0xdcaa2ebf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7228.ic34", 0x08000, 0xd5e15e66, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7220.ic26", 0x08000, 0xac62ae2e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7212.ic16", 0x08000, 0x9c782295, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7204.ic6", 0x08000, 0x3711105c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7227.ic33", 0x08000, 0x60d7c1bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7219.ic25", 0x08000, 0xf6330038, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7211.ic15", 0x08000, 0x60737b98, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7203.ic5", 0x08000, 0x70fb5ebb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7226.ic32", 0x08000, 0x6d7b5c97, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7218.ic24", 0x08000, 0xcebf797c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7210.ic14", 0x08000, 0x24596a8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7202.ic4", 0x08000, 0xb537d082, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7225.ic31", 0x08000, 0x5e784271, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7217.ic23", 0x08000, 0x510e5e10, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7209.ic13", 0x08000, 0x7a2dad15, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7201.ic3", 0x08000, 0xf5ba4e08, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7224.ic30", 0x08000, 0xec42c9ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7216.ic22", 0x08000, 0x6d4a7d7a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7208.ic12", 0x08000, 0x0f732717, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7200.ic2", 0x08000, 0xfc3bf8f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7223.ic29", 0x08000, 0xed51fdc4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7215.ic21", 0x08000, 0xdfe75f3d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7207.ic11", 0x08000, 0xa2c07741, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7199.ic1", 0x08000, 0xb191e22f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7181.ic2", 0x08000, 0xb4740419, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-7234.ic73", 0x04000, 0xd6397933, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + { "epr-7233.ic72", 0x04000, 0x504e76d9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-7231.ic5", 0x08000, 0x871c6b14, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-7232.ic6", 0x08000, 0x4b59340c, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, + + { "315-5163a.ic32", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Sharrier) +STD_ROM_FN(Sharrier) + +static struct BurnRomInfo Sharrier1RomDesc[] = { + { "epr-7188.ic97", 0x08000, 0x7c30a036, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7184.ic84", 0x08000, 0x16deaeb1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7189.ic98", 0x08000, 0x40b1309f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7185.ic85", 0x08000, 0xce78045c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7190.ic99", 0x08000, 0xf6391091, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7186.ic86", 0x08000, 0x79b367d7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7191.ic100", 0x08000, 0x6171e9d3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7187.ic87", 0x08000, 0x70cb72ef, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7182.ic54", 0x08000, 0xd7c535b6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-7183.ic67", 0x08000, 0xa6153af8, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-7196.ic31", 0x08000, 0x347fa325, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7197.ic46", 0x08000, 0x39d98bd1, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7198.ic60", 0x08000, 0x3da3ea6b, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7230.ic36", 0x08000, 0x93e2d264, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7222.ic28", 0x08000, 0xedbf5fc3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7214.ic18", 0x08000, 0xe8c537d8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7206.ic8", 0x08000, 0x22844fa4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7229.ic35", 0x08000, 0xcd6e7500, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7221.ic27", 0x08000, 0x41f25a9c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7213.ic17", 0x08000, 0x5bb09a67, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7205.ic7", 0x08000, 0xdcaa2ebf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7228.ic34", 0x08000, 0xd5e15e66, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7220.ic26", 0x08000, 0xac62ae2e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7212.ic16", 0x08000, 0x9c782295, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7204.ic6", 0x08000, 0x3711105c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7227.ic33", 0x08000, 0x60d7c1bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7219.ic25", 0x08000, 0xf6330038, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7211.ic15", 0x08000, 0x60737b98, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7203.ic5", 0x08000, 0x70fb5ebb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7226.ic32", 0x08000, 0x6d7b5c97, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7218.ic24", 0x08000, 0xcebf797c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7210.ic14", 0x08000, 0x24596a8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7202.ic4", 0x08000, 0xb537d082, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7225.ic31", 0x08000, 0x5e784271, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7217.ic23", 0x08000, 0x510e5e10, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7209.ic13", 0x08000, 0x7a2dad15, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7201.ic3", 0x08000, 0xf5ba4e08, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7224.ic30", 0x08000, 0xec42c9ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7216.ic22", 0x08000, 0x6d4a7d7a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7208.ic12", 0x08000, 0x0f732717, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7200.ic2", 0x08000, 0xfc3bf8f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7223.ic29", 0x08000, 0xed51fdc4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7215.ic21", 0x08000, 0xdfe75f3d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7207.ic11", 0x08000, 0xa2c07741, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7199.ic1", 0x08000, 0xb191e22f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7181.ic2", 0x08000, 0xb4740419, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-7234.ic73", 0x04000, 0xd6397933, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + { "epr-7233.ic72", 0x04000, 0x504e76d9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-7231.ic5", 0x08000, 0x871c6b14, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-7232.ic6", 0x08000, 0x4b59340c, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-6844.ic123", 0x02000, 0xe3ec7bd6, SYS16_ROM_PROM | BRF_GRA }, + + { "315-5163.ic32", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Sharrier1) +STD_ROM_FN(Sharrier1) + +/*==================================================== +Memory Handlers +====================================================*/ + +void HangonPPI0WritePortA(UINT8 data) +{ + System16SoundLatch = data & 0xff; +} + +void HangonPPI0WritePortB(UINT8 data) +{ + System16VideoEnable = data & 0x10; + System16SpriteShadow = ~data & 0x40; + System16ScreenFlip = data & 0x80; +} + +void HangonPPI0WritePortC(UINT8 data) +{ + System16ColScroll = ~data & 0x04; + System16RowScroll = ~data & 0x02; + + if (!(data & 0x80)) { + ZetOpen(0); + ZetNmi(); + nSystem16CyclesDone[2] += ZetRun(100); + ZetClose(); + } +} + +UINT8 HangonPPI1ReadPortC() +{ + return 0x00; +} + +void HangonPPI1WritePortA(UINT8 data) +{ + System16AnalogSelect = (data >> 2) & 3; + + if (!(data & 0x40)) { + INT32 nLastCPU = nSekActive; + SekClose(); + SekOpen(1); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + SekOpen(nLastCPU); + } + if (data & 0x20) { + INT32 nLastCPU = nSekActive; + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(nLastCPU); + } +} + +UINT16 __fastcall HangonReadWord(UINT32 a) +{ + switch (a) { + case 0xe00000: + case 0xe00002: + case 0xe00004: + case 0xe00006: { + return ppi8255_r(0, (a - 0xe00000) >> 1); + } + + case 0xe01000: { + return 0xff - System16Input[0]; + } + + case 0xe0100a: { + return System16Dip[0]; + } + + case 0xe0100c: { + return System16Dip[1]; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0; +} + +UINT8 __fastcall HangonReadByte(UINT32 a) +{ + switch (a) { + case 0xe00001: + case 0xe00003: + case 0xe00005: + case 0xe00007: { + return ppi8255_r(0, (a - 0xe00000) >> 1); + } + + case 0xe01001: { + return 0xff - System16Input[0]; + } + + case 0xe0100b: { + return System16Dip[0]; + } + + case 0xe0100d: { + return System16Dip[1]; + } + + case 0xe03001: + case 0xe03003: + case 0xe03005: + case 0xe03007: { + return ppi8255_r(1, (a - 0xe03000) >> 1); + } + + case 0xe03021: { + if (System16ProcessAnalogControlsDo) return System16ProcessAnalogControlsDo(System16AnalogSelect); + return 0xff; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0; +} + +void __fastcall HangonWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x403fff) { + System16ATileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0xe00001: + case 0xe00003: + case 0xe00005: + case 0xe00007: { + ppi8255_w(0, (a - 0xe00000) >> 1, d & 0xff); + return; + } + + case 0xe03001: + case 0xe03003: + case 0xe03005: + case 0xe03007: { + ppi8255_w(1, (a - 0xe03000) >> 1, d & 0xff); + return; + } + + case 0xe03021: { + return; + } + + + case 0xe00000: + case 0xe00002: { + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall HangonWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x403fff) { + System16ATileWordWrite(a - 0x400000, d); + return; + } + + switch (a) { + case 0xe00000: + case 0xe00002: + case 0xe00004: + case 0xe00006: { + ppi8255_w(0, (a - 0xe00000) >> 1, d & 0xff); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +UINT16 __fastcall SharrierReadWord(UINT32 a) +{ + switch (a) { + case 0x140010: { + return (UINT16)(0xff - System16Input[0]); + } + + case 0x140012: { + return 0xffff; + } + + case 0x140014: { + return (UINT16)System16Dip[0]; + } + + case 0x140016: { + return (UINT16)System16Dip[1]; + } + } + + return 0; +} + +UINT8 __fastcall SharrierReadByte(UINT32 a) +{ + switch (a) { + case 0x140001: + case 0x140003: + case 0x140005: + case 0x140007: { + return ppi8255_r(0, (a - 0x140000) >> 1); + } + + case 0x140011: { + return 0xff - System16Input[0]; + } + + case 0x140015: { + return System16Dip[0]; + } + + case 0x140021: + case 0x140023: + case 0x140025: + case 0x140027: { + return ppi8255_r(1, (a - 0x140020) >> 1); + } + + case 0x140031: { + if (System16ProcessAnalogControlsDo) return System16ProcessAnalogControlsDo(System16AnalogSelect); + return 0xff; + } + } + + return 0; +} + +void __fastcall SharrierWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x100000 && a <= 0x107fff) { + System16ATileByteWrite((a - 0x100000) ^ 1, d); + return; + } + + switch (a) { + case 0x140001: + case 0x140003: + case 0x140005: + case 0x140007: { + ppi8255_w(0, (a - 0x140000) >> 1, d & 0xff); + return; + } + + case 0x140021: + case 0x140023: + case 0x140025: + case 0x140027: { + ppi8255_w(1, (a - 0x140020) >> 1, d & 0xff); + return; + } + + case 0x140031: { + return; + } + } +} + +void __fastcall SharrierWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x100000 && a <= 0x107fff) { + System16ATileWordWrite(a - 0x100000, d); + return; + } +} + +/*==================================================== +Driver Inits +====================================================*/ + +UINT8 EndurorProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Accelerate + case 0: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + + // Brake + case 1: { + if (System16AnalogPort3 > 1) return 0xff; + return 0; + } + + // Bank Up / Down + case 2: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) > 0x7f && (System16AnalogPort1 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort1 >> 4); + } + + if (temp == 0x80) return 0x20; + if (temp > 0x80) return 0xff; + return 0; + } + + // Steering + case 3: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + return temp; + } + } + + return 0; +} + +UINT8 HangonProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Steering + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + + // Brake + case 2: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + } + + return 0; +} + +UINT8 SharrierProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + + // Up / Down + case 1: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) < 0xf82 && (System16AnalogPort1 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort1 >> 4); + } + + if (temp < 0x60) temp = 0x60; + if (temp > 0xa0) temp = 0xa0; + return temp; + } + } + + return 0; +} + +void SharrierMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x03ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x03ffff, SM_FETCH); + SekMapMemory(System16Ram , 0x040000, 0x043fff, SM_RAM); + SekMapMemory(System16TileRam , 0x100000, 0x107fff, SM_READ); + SekMapMemory(System16TextRam , 0x108000, 0x108fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(System16ExtraRam , 0x124000, 0x127fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x130000, 0x130fff, SM_RAM); + SekMapMemory(System16RoadRam , 0xc68000, 0xc68fff, SM_RAM); + + SekSetReadWordHandler(0, SharrierReadWord); + SekSetReadByteHandler(0, SharrierReadByte); + SekSetWriteByteHandler(0, SharrierWriteByte); + SekSetWriteWordHandler(0, SharrierWriteWord); + SekClose(); +} + +static INT32 EndurorInit() +{ + System16Map68KDo = SharrierMap68K; + + System16ProcessAnalogControlsDo = EndurorProcessAnalogControls; + + System16ClockSpeed = 10000000; + + System16PCMDataSizePreAllocate = 0x18000; + + INT32 nRet = System16Init(); + + UINT8 *pTemp = (UINT8*)malloc(0x10000); + memcpy(pTemp, System16PCMData, 0x10000); + memset(System16PCMData, 0, 0x18000); + memcpy(System16PCMData + 0x00000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x10000, pTemp + 0x08000, 0x8000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + return nRet; +} + +static INT32 Enduror1Init() +{ + System16Map68KDo = SharrierMap68K; + + System16ProcessAnalogControlsDo = EndurorProcessAnalogControls; + + System16ClockSpeed = 10000000; + + return System16Init(); +} + +INT32 EnduroblLoadRom() +{ + INT32 nRet = 1; + UINT8 *pTemp = (UINT8*)malloc(0x40000); + + if (pTemp) { + memcpy(pTemp, System16Rom, 0x40000); + memset(System16Rom, 0, 0x40000); + memcpy(System16Rom + 0x00000, pTemp + 0x10000, 0x10000); + memcpy(System16Rom + 0x10000, pTemp + 0x20000, 0x20000); + memcpy(System16Rom + 0x30000, pTemp + 0x00000, 0x10000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + nRet = 0; + } + + return nRet; +} + +static INT32 EnduroblDecryptOpCode() +{ + UINT16 *rom = (UINT16*)System16Rom; + UINT16 *decrypt = (UINT16*)System16Code; + memcpy(decrypt + 0x00000/2, rom + 0x30000/2, 0x10000); + memcpy(decrypt + 0x10000/2, rom + 0x10000/2, 0x20000); + + return 0; +} + +static INT32 EnduroblInit() +{ + System16CustomLoadRomDo = EnduroblLoadRom; + + System16CustomDecryptOpCodeDo = EnduroblDecryptOpCode; + + System16Map68KDo = SharrierMap68K; + + System16ProcessAnalogControlsDo = EndurorProcessAnalogControls; + + System16ClockSpeed = 10000000; + + return System16Init(); +} + +static INT32 HangonInit() +{ + System16ProcessAnalogControlsDo = HangonProcessAnalogControls; + + System16ClockSpeed = 25174800 / 4; + + INT32 nRet = System16Init(); + + if (!nRet) Hangon = true; + + return nRet; +} + +static INT32 ShangonrbInit() +{ + System16ProcessAnalogControlsDo = HangonProcessAnalogControls; + + System16ClockSpeed = 10000000; + + INT32 nRet = System16Init(); + + if (!nRet) Hangon = true; + + return nRet; +} + +void Sharrier_Sim8751() +{ + // Inputs + *((UINT16*)(System16Ram + 0x0492)) = (UINT16)((SharrierProcessAnalogControls(0) << 8) | SharrierProcessAnalogControls(1)); +} + +static INT32 SharrierInit() +{ + Simulate8751 = Sharrier_Sim8751; + + System16Map68KDo = SharrierMap68K; + + System16ClockSpeed = 10000000; + + return System16Init(); +} + +/*==================================================== +Driver defs +====================================================*/ + +struct BurnDriver BurnDrvEnduror = { + "enduror", NULL, NULL, NULL, "1986", + "Enduro Racer (YM2151, FD1089B 317-0013A)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_FD1089B_ENC | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, EndurorRomInfo, EndurorRomName, NULL, NULL, EndurorInputInfo, EndurorDIPInfo, + EndurorInit, System16Exit, HangonFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEnduror1 = { + "enduror1", "enduror", NULL, NULL, "1986", + "Enduro Racer (YM2203, FD1089B 317-0013A)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_FD1089B_ENC | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_YM2203, GBF_RACING, 0, + NULL, Enduror1RomInfo, Enduror1RomName, NULL, NULL, EndurorInputInfo, EndurorDIPInfo, + Enduror1Init, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEndurobl = { + "endurobl", "enduror", NULL, NULL, "1986", + "Enduro Racer (bootleg set 1)\0", NULL, "bootleg", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_YM2203, GBF_RACING, 0, + NULL, EnduroblRomInfo, EnduroblRomName, NULL, NULL, EndurorInputInfo, EndurorDIPInfo, + EnduroblInit, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHangon = { + "hangon", NULL, NULL, NULL, "1985", + "Hang-On (rev A)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_YM2203, GBF_RACING, 0, + NULL, HangonRomInfo, HangonRomName, NULL, NULL, HangonInputInfo, HangonDIPInfo, + HangonInit, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHangon1 = { + "hangon1", "hangon", NULL, NULL, "1985", + "Hang-On\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_YM2203, GBF_RACING, 0, + NULL, Hangon1RomInfo, Hangon1RomName, NULL, NULL, HangonInputInfo, HangonDIPInfo, + HangonInit, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvShangonro = { + "shangonro", "shangon", NULL, NULL, "1992", + "Super Hang-On (Japan, FD1094 317-0038)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_FD1094_ENC_CPU2, GBF_RACING, 0, + NULL, ShangonroRomInfo, ShangonroRomName, NULL, NULL, ShangonrbInputInfo, ShangonrbDIPInfo, + ShangonrbInit, System16Exit, HangonFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvShangonrb = { + "shangonrb", "shangon", NULL, NULL, "1992", + "Super Hang-On (bootleg)\0", NULL, "bootleg", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_HANGON, GBF_RACING, 0, + NULL, ShangonrbRomInfo, ShangonrbRomName, NULL, NULL, ShangonrbInputInfo, ShangonrbDIPInfo, + ShangonrbInit, System16Exit, HangonFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSharrier = { + "sharrier", NULL, NULL, NULL, "1985", + "Space Harrier (Rev A, 8751 315-5163A)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_YM2203, GBF_SHOOT, 0, + NULL, SharrierRomInfo, SharrierRomName, NULL, NULL, SharrierInputInfo, SharrierDIPInfo, + SharrierInit, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSharrier1 = { + "sharrier1", "sharrier", NULL, NULL, "1985", + "Space Harrier (8751 315-5163)\0", NULL, "Sega", "Hang-On", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_HANGON | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_YM2203, GBF_SHOOT, 0, + NULL, Sharrier1RomInfo, Sharrier1RomName, NULL, NULL, SharrierInputInfo, SharrierDIPInfo, + SharrierInit, System16Exit, HangonYM2203Frame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_outrun.cpp b/src/burn/drivers/sega/d_outrun.cpp new file mode 100644 index 00000000..ede5fe0f --- /dev/null +++ b/src/burn/drivers/sega/d_outrun.cpp @@ -0,0 +1,1686 @@ +#include "sys16.h" +#include "bitswap.h" + +/*==================================================== +Input Defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo OutrunInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Gear" , BIT_DIGITAL , &System16Gear , "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Outrun) + +static struct BurnInputInfo ShangonInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Super Charger" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Shangon) + +static struct BurnInputInfo ToutrunInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Gear" , BIT_DIGITAL , &System16Gear , "p1 fire 3" }, + {"Nitro" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Toutrun) + +#undef A + +/*==================================================== +Dip Defs +====================================================*/ + +#define OUTRUN_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo OutrunDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xf9, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0a) + + // Dip 2 + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0b, 0x01, 0x03, 0x03, "Moving" }, + {0x0b, 0x01, 0x03, 0x02, "Up Cockpit" }, + {0x0b, 0x01, 0x03, 0x01, "Mini Up" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0b, 0x01, 0x30, 0x20, "Easy" }, + {0x0b, 0x01, 0x30, 0x30, "Normal" }, + {0x0b, 0x01, 0x30, 0x10, "Hard" }, + {0x0b, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0xc0, 0x80, "Easy" }, + {0x0b, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0b, 0x01, 0xc0, 0x40, "Hard" }, + {0x0b, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Outrun) + +static struct BurnDIPInfo OutrundxDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0a) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x00, "Not Moving" }, + {0x0b, 0x01, 0x01, 0x01, "Moving" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0b, 0x01, 0x30, 0x20, "Easy" }, + {0x0b, 0x01, 0x30, 0x30, "Normal" }, + {0x0b, 0x01, 0x30, 0x10, "Hard" }, + {0x0b, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0xc0, 0x80, "Easy" }, + {0x0b, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0b, 0x01, 0xc0, 0x40, "Hard" }, + {0x0b, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Outrundx) + +static struct BurnDIPInfo ShangonDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x1e, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0a) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x06, 0x04, "Easy" }, + {0x0b, 0x01, 0x06, 0x06, "Normal" }, + {0x0b, 0x01, 0x06, 0x02, "Hard" }, + {0x0b, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0b, 0x01, 0x18, 0x10, "Easy" }, + {0x0b, 0x01, 0x18, 0x18, "Normal" }, + {0x0b, 0x01, 0x18, 0x08, "Hard" }, + {0x0b, 0x01, 0x18, 0x00, "Hardest" }, +}; + +STDDIPINFO(Shangon) + +static struct BurnDIPInfo ToutrunDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xd9, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0c, 0x01, 0x03, 0x03, "Moving" }, + {0x0c, 0x01, 0x03, 0x02, "Cockpit Conversion" }, + {0x0c, 0x01, 0x03, 0x01, "Mini Up" }, + {0x0c, 0x01, 0x03, 0x00, "Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Turbo" }, + {0x0c, 0x01, 0x08, 0x00, "Use start button" }, + {0x0c, 0x01, 0x08, 0x08, "Use turbo shifter" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0c, 0x01, 0x30, 0x20, "3 to start/2 to continue" }, + {0x0c, 0x01, 0x30, 0x30, "2 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x10, "1 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x00, "2 to start/2 to continue" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Toutrun) + +static struct BurnDIPInfo ToutruncDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xd8, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 1 , "Cabinet" }, + {0x0c, 0x01, 0x03, 0x00, "Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 1 , "Turbo" }, + {0x0c, 0x01, 0x08, 0x08, "Use turbo shifter" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0c, 0x01, 0x30, 0x20, "3 to start/2 to continue" }, + {0x0c, 0x01, 0x30, 0x30, "2 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x10, "1 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x00, "2 to start/2 to continue" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Toutrunc) + +static struct BurnDIPInfo ToutrunmDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xdb, NULL }, + + // Dip 1 + OUTRUN_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 1 , "Cabinet" }, + {0x0c, 0x01, 0x03, 0x03, "Moving" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Turbo" }, + {0x0c, 0x01, 0x08, 0x00, "Use start button" }, + {0x0c, 0x01, 0x08, 0x08, "Use turbo shifter" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0c, 0x01, 0x30, 0x20, "3 to start/2 to continue" }, + {0x0c, 0x01, 0x30, 0x30, "2 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x10, "1 to start/1 to continue" }, + {0x0c, 0x01, 0x30, 0x00, "2 to start/2 to continue" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Toutrunm) + +#undef OUTRUN_COINAGE + +/*==================================================== +Rom Defs +====================================================*/ + +static struct BurnRomInfo OutrunRomDesc[] = { + { "epr-10380b.133", 0x10000, 0x1f6cadad, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10382b.118", 0x10000, 0xc4c3fa1a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10381b.132", 0x10000, 0xbe8c412b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10383b.117", 0x10000, 0x10a2014a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10327a.76", 0x10000, 0xe28a5baf, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10329a.58", 0x10000, 0xda131c81, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10328a.75", 0x10000, 0xd5ec5e5d, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10330a.57", 0x10000, 0xba9ec82a, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-10268.99", 0x08000, 0x95344b04, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10232.102", 0x08000, 0x776ba1eb, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10267.100", 0x08000, 0xa85bb823, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10231.103", 0x08000, 0x8908bcbf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10266.101", 0x08000, 0x9f6f1a74, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10230.104", 0x08000, 0x686f5e50, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-10371.9", 0x20000, 0x7cc86208, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10373.10", 0x20000, 0xb0d26ac9, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10375.11", 0x20000, 0x59b60bd7, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10377.12", 0x20000, 0x17a1b04a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10372.13", 0x20000, 0xb557078c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10374.14", 0x20000, 0x8051e517, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10376.15", 0x20000, 0xf3b8f318, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10378.16", 0x20000, 0xa1062984, SYS16_ROM_SPRITES | BRF_GRA }, + + { "opr-10186.47", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + { "opr-10185.11", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10187.88", 0x08000, 0xa10abaa9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-10193.66", 0x08000, 0xbcd10dde, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10192.67", 0x08000, 0x770f1270, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10191.68", 0x08000, 0x20a284ab, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10190.69", 0x08000, 0x7cab70e2, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10189.70", 0x08000, 0x01366b54, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10188.71", 0x08000, 0xbad30ad9, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Outrun) +STD_ROM_FN(Outrun) + +static struct BurnRomInfo OutrunoRomDesc[] = { + { "epr-10380.133", 0x10000, 0xe339e87a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10382.118", 0x10000, 0x65248dd5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10381.132", 0x10000, 0xbe8c412b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10383.117", 0x10000, 0xdcc586e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10327.76", 0x10000, 0xda99d855, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10329.58", 0x10000, 0xfe0fa5e2, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10328.75", 0x10000, 0x3c0e9a7f, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10330.57", 0x10000, 0x59786e99, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-10268.99", 0x08000, 0x95344b04, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10232.102", 0x08000, 0x776ba1eb, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10267.100", 0x08000, 0xa85bb823, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10231.103", 0x08000, 0x8908bcbf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10266.101", 0x08000, 0x9f6f1a74, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10230.104", 0x08000, 0x686f5e50, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10194.26", 0x08000, 0xf0eda3bd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10203.38", 0x08000, 0x8445a622, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10212.52", 0x08000, 0xdee7e731, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10221.66", 0x08000, 0x43431387, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10195.27", 0x08000, 0x0de75cdd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10204.39", 0x08000, 0x5f4b5abb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10213.53", 0x08000, 0x1d1b22f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10222.67", 0x08000, 0xa254c706, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10196.28", 0x08000, 0x8688bb59, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10205.40", 0x08000, 0x74bd93ca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10214.54", 0x08000, 0x57527e18, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10223.68", 0x08000, 0x3850690e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10197.29", 0x08000, 0x009165a6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10206.41", 0x08000, 0x954542c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10215.55", 0x08000, 0x69be5a6c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10224.69", 0x08000, 0x5cffc346, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10198.30", 0x08000, 0xd894992e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10207.42", 0x08000, 0xca61cea4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10216.56", 0x08000, 0xd394134d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10225.70", 0x08000, 0x0a5d1f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10199.31", 0x08000, 0x86376af6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10208.43", 0x08000, 0x6830b7fa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10217.57", 0x08000, 0xbf2c9b76, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10226.71", 0x08000, 0x5a452474, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10200.32", 0x08000, 0x1e5d4f73, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10209.44", 0x08000, 0x5c15419e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10218.58", 0x08000, 0xdb4bdb39, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10227.72", 0x08000, 0xc7def392, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10201.33", 0x08000, 0x1d9d4b9c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10210.45", 0x08000, 0x39422931, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10219.59", 0x08000, 0xe73b9224, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10228.73", 0x08000, 0x25803978, SYS16_ROM_SPRITES | BRF_GRA }, + + { "opr-10186.47", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + { "opr-10185.11", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10187.88", 0x08000, 0xa10abaa9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-10193.66", 0x08000, 0xbcd10dde, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10192.67", 0x08000, 0x770f1270, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10191.68", 0x08000, 0x20a284ab, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10190.69", 0x08000, 0x7cab70e2, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10189.70", 0x08000, 0x01366b54, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10188.71", 0x08000, 0xbad30ad9, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Outruno) +STD_ROM_FN(Outruno) + +static struct BurnRomInfo OutrundxRomDesc[] = { + { "epr-10183.115", 0x08000, 0x3d992396, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10261.130", 0x08000, 0x1d034847, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10184.116", 0x08000, 0x1a73dc46, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10262.131", 0x08000, 0x5386b6b3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10258.117", 0x08000, 0x39408e4f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10263.132", 0x08000, 0xeda65fd6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10259.118", 0x08000, 0x95100b1a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10264.133", 0x08000, 0xcc94b102, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10173.66", 0x08000, 0x6c2775c0, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10178.86", 0x08000, 0x6d36be05, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10174.67", 0x08000, 0xaae7efad, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10179.87", 0x08000, 0x180fd041, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10175.68", 0x08000, 0x31c76063, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10180.88", 0x08000, 0x4713b264, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10176.69", 0x08000, 0xa7811f90, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10181.89", 0x08000, 0xe009a04d, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-10268.99", 0x08000, 0x95344b04, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10232.102", 0x08000, 0x776ba1eb, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10267.100", 0x08000, 0xa85bb823, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10231.103", 0x08000, 0x8908bcbf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10266.101", 0x08000, 0x9f6f1a74, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10230.104", 0x08000, 0x686f5e50, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10194.26", 0x08000, 0xf0eda3bd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10203.38", 0x08000, 0x8445a622, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10212.52", 0x08000, 0xdee7e731, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10221.66", 0x08000, 0x43431387, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10195.27", 0x08000, 0x0de75cdd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10204.39", 0x08000, 0x5f4b5abb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10213.53", 0x08000, 0x1d1b22f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10222.67", 0x08000, 0xa254c706, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10196.28", 0x08000, 0x8688bb59, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10205.40", 0x08000, 0x74bd93ca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10214.54", 0x08000, 0x57527e18, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10223.68", 0x08000, 0x3850690e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10197.29", 0x08000, 0x009165a6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10206.41", 0x08000, 0x954542c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10215.55", 0x08000, 0x69be5a6c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10224.69", 0x08000, 0x5cffc346, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10198.30", 0x08000, 0xd894992e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10207.42", 0x08000, 0xca61cea4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10216.56", 0x08000, 0xd394134d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10225.70", 0x08000, 0x0a5d1f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10199.31", 0x08000, 0x86376af6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10208.43", 0x08000, 0x6830b7fa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10217.57", 0x08000, 0xbf2c9b76, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10226.71", 0x08000, 0x5a452474, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10200.32", 0x08000, 0x1e5d4f73, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10209.44", 0x08000, 0x5c15419e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10218.58", 0x08000, 0xdb4bdb39, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10227.72", 0x08000, 0xc7def392, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10201.33", 0x08000, 0x1d9d4b9c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10210.45", 0x08000, 0x39422931, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10219.59", 0x08000, 0xe73b9224, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10228.73", 0x08000, 0x25803978, SYS16_ROM_SPRITES | BRF_GRA }, + + { "opr-10186.47", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + { "opr-10185.11", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10187.88", 0x08000, 0xa10abaa9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-10193.66", 0x08000, 0xbcd10dde, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10192.67", 0x08000, 0x770f1270, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10191.68", 0x08000, 0x20a284ab, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10190.69", 0x08000, 0x7cab70e2, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10189.70", 0x08000, 0x01366b54, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10188.71", 0x08000, 0xbad30ad9, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Outrundx) +STD_ROM_FN(Outrundx) + +static struct BurnRomInfo OutrunraRomDesc[] = { + { "epr-10380a.133", 0x10000, 0x434fadbc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10382a.118", 0x10000, 0x1ddcc04e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10381a.132", 0x10000, 0xbe8c412b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10383a.117", 0x10000, 0xdcc586e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10327a.76", 0x10000, 0xe28a5baf, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10329a.58", 0x10000, 0xda131c81, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10328a.75", 0x10000, 0xd5ec5e5d, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10330a.57", 0x10000, 0xba9ec82a, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-10268.99", 0x08000, 0x95344b04, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10232.102", 0x08000, 0x776ba1eb, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10267.100", 0x08000, 0xa85bb823, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10231.103", 0x08000, 0x8908bcbf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10266.101", 0x08000, 0x9f6f1a74, SYS16_ROM_TILES | BRF_GRA }, + { "opr-10230.104", 0x08000, 0x686f5e50, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-10371.9", 0x20000, 0x7cc86208, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10373.10", 0x20000, 0xb0d26ac9, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10375.11", 0x20000, 0x59b60bd7, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10377.12", 0x20000, 0x17a1b04a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10372.13", 0x20000, 0xb557078c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10374.14", 0x20000, 0x8051e517, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10376.15", 0x20000, 0xf3b8f318, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10378.16", 0x20000, 0xa1062984, SYS16_ROM_SPRITES | BRF_GRA }, + + { "opr-10186.47", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + { "opr-10185.11", 0x08000, 0x22794426, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10187.88", 0x08000, 0xa10abaa9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-10193.66", 0x08000, 0xbcd10dde, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10192.67", 0x08000, 0x770f1270, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10191.68", 0x08000, 0x20a284ab, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10190.69", 0x08000, 0x7cab70e2, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10189.70", 0x08000, 0x01366b54, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-10188.71", 0x08000, 0xbad30ad9, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Outrunra) +STD_ROM_FN(Outrunra) + +static struct BurnRomInfo OutrunbRomDesc[] = { + { "a-10.bin", 0x10000, 0xcddceea2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a-9.bin", 0x10000, 0x14e97a67, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a-14.bin", 0x10000, 0x3092d857, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a-13.bin", 0x10000, 0x30a1c496, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "a-8.bin", 0x10000, 0xd7f5aae0, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "a-7.bin", 0x10000, 0x88c2e78f, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "a-12.bin", 0x10000, 0xd5ec5e5d, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "a-11.bin", 0x10000, 0x74c5fbec, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "a-15.bin", 0x10000, 0x4c489133, SYS16_ROM_TILES | BRF_GRA }, + { "a-17.bin", 0x10000, 0x899c781d, SYS16_ROM_TILES | BRF_GRA }, + { "a-16.bin", 0x10000, 0x98dd4d15, SYS16_ROM_TILES | BRF_GRA }, + + { "a-18.bin", 0x10000, 0x77377e00, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-20.bin", 0x10000, 0x69ecc975, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-22.bin", 0x10000, 0xb6a8d0e2, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-24.bin", 0x10000, 0xd632d8a2, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-26.bin", 0x10000, 0x4f784236, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-28.bin", 0x10000, 0xee4f7154, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-30.bin", 0x10000, 0xe9880aa3, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-32.bin", 0x10000, 0xdc286dc2, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-19.bin", 0x10000, 0x2c0e7277, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-21.bin", 0x10000, 0x54761e57, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-23.bin", 0x10000, 0xa00d0676, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-25.bin", 0x10000, 0xda398368, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-27.bin", 0x10000, 0x8d459356, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-29.bin", 0x10000, 0xa8245727, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-31.bin", 0x10000, 0xef7d06fe, SYS16_ROM_SPRITES | BRF_GRA }, + { "a-33.bin", 0x10000, 0x1222af9f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "a-2.bin", 0x08000, 0xed5bda9c, SYS16_ROM_ROAD | BRF_GRA }, + { "a-3.bin", 0x08000, 0x666fe754, SYS16_ROM_ROAD | BRF_GRA }, + + { "a-1.bin", 0x08000, 0x209bb53a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "a-6.bin", 0x10000, 0x191f98f4, SYS16_ROM_PCMDATA | BRF_SND }, + { "a-5.bin", 0x10000, 0x374466d0, SYS16_ROM_PCMDATA | BRF_SND }, + { "a-4.bin", 0x10000, 0x2a27d0b0, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Outrunb) +STD_ROM_FN(Outrunb) + +static struct BurnRomInfo ShangonRomDesc[] = { + { "epr-10886.133", 0x10000, 0x8be3cd36, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10884.118", 0x10000, 0xcb06150d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10887.132", 0x10000, 0x8d248bb0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10885.117", 0x10000, 0x70795f26, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10792.76", 0x10000, 0x16299d25, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10790.58", 0x10000, 0x2246cbc1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10793.75", 0x10000, 0xd9525427, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10791.57", 0x10000, 0x5faf4cbe, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.54", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.55", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.56", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-10794.8", 0x20000, 0x7c958e63, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10798.16", 0x20000, 0x7d58f807, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10795.6", 0x20000, 0xd9d31f8c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10799.14", 0x20000, 0x96d90d3d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10796.4", 0x20000, 0xfb48957c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10800.12", 0x20000, 0xfeaff98e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10797.2", 0x20000, 0x27f2870d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10801.10", 0x20000, 0x12781795, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10642.47", 0x08000, 0x7836bcc3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10649c.88", 0x08000, 0xf6c1ce71, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10643.66", 0x08000, 0x06f55364, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10644.67", 0x08000, 0xb41d541d, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10645.68", 0x08000, 0xa60dabff, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10646.69", 0x08000, 0x473cc411, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shangon) +STD_ROM_FN(Shangon) + +static struct BurnRomInfo Shangon2RomDesc[] = { + { "epr-10636a.133", 0x10000, 0x74a64f4f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10634a.118", 0x10000, 0x1608cb4a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10637a.132", 0x10000, 0xad6c1308, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10635a.117", 0x10000, 0xa2415595, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10640.76", 0x10000, 0x02be68db, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10638.58", 0x10000, 0xf13e8bee, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10641.75", 0x10000, 0x38c3f808, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10639.57", 0x10000, 0x8cdbcde8, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.54", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.55", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.56", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10675.8", 0x10000, 0xd6ac012b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10682.16", 0x10000, 0xd9d83250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10676.7", 0x10000, 0x25ebf2c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10683.15", 0x10000, 0x6365d2e9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10677.6", 0x10000, 0x8a57b8d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10684.14", 0x10000, 0x3aff8910, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10678.5", 0x10000, 0xaf473098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10685.13", 0x10000, 0x80bafeef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10679.4", 0x10000, 0x03bc4878, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10686.12", 0x10000, 0x274b734e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10680.3", 0x10000, 0x9f0677ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10687.11", 0x10000, 0x508a4701, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10681.2", 0x10000, 0xb176ea72, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10688.10", 0x10000, 0x42fcd51d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10642.47", 0x08000, 0x7836bcc3, SYS16_ROM_ROAD | BRF_GRA }, + + { "ic88", 0x08000, 0x1254efa6, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10643.66", 0x08000, 0x06f55364, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10644.67", 0x08000, 0xb41d541d, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10645.68", 0x08000, 0xa60dabff, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10646.69", 0x08000, 0x473cc411, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0034.key", 0x02000, 0x263ca773, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shangon2) +STD_ROM_FN(Shangon2) + +static struct BurnRomInfo Shangon3RomDesc[] = { + { "epr-10789.133", 0x10000, 0x6092c5ce, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10788.118", 0x10000, 0xc3d8a1ea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10637a.132", 0x10000, 0xad6c1308, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10635a.117", 0x10000, 0xa2415595, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10792.76", 0x10000, 0x16299d25, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10790.58", 0x10000, 0x2246cbc1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10793.75", 0x10000, 0xd9525427, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10791.57", 0x10000, 0x5faf4cbe, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.54", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.55", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.56", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10675.8", 0x10000, 0xd6ac012b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10682.16", 0x10000, 0xd9d83250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10676.7", 0x10000, 0x25ebf2c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10683.15", 0x10000, 0x6365d2e9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10677.6", 0x10000, 0x8a57b8d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10684.14", 0x10000, 0x3aff8910, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10678.5", 0x10000, 0xaf473098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10685.13", 0x10000, 0x80bafeef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10679.4", 0x10000, 0x03bc4878, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10686.12", 0x10000, 0x274b734e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10680.3", 0x10000, 0x9f0677ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10687.11", 0x10000, 0x508a4701, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10681.2", 0x10000, 0xb176ea72, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10688.10", 0x10000, 0x42fcd51d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10642.47", 0x08000, 0x7836bcc3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10649a.88", 0x08000, 0xbf38330f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10643.66", 0x08000, 0x06f55364, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10644.67", 0x08000, 0xb41d541d, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10645.68", 0x08000, 0xa60dabff, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10646.69", 0x08000, 0x473cc411, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0034.key", 0x02000, 0x263ca773, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shangon3) +STD_ROM_FN(Shangon3) + +static struct BurnRomInfo ShangonleRomDesc[] = { + { "epr-13944.133", 0x10000, 0x989a80db, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13943.118", 0x10000, 0x426e3050, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10899.132", 0x10000, 0xbb3faa37, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10897.117", 0x10000, 0x5f087eb1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10640.76", 0x10000, 0x02be68db, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10638.58", 0x10000, 0xf13e8bee, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10641.75", 0x10000, 0x38c3f808, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10639.57", 0x10000, 0x8cdbcde8, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10652.54", 0x08000, 0x260286f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10651.55", 0x08000, 0xc609ee7b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10650.56", 0x08000, 0xb236a403, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10675.8", 0x10000, 0xd6ac012b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10682.16", 0x10000, 0xd9d83250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13945.7", 0x10000, 0xfbb1eef9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13946.15", 0x10000, 0x03144930, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10677.6", 0x10000, 0x8a57b8d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10684.14", 0x10000, 0x3aff8910, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10678.5", 0x10000, 0xaf473098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10685.13", 0x10000, 0x80bafeef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10679.4", 0x10000, 0x03bc4878, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10686.12", 0x10000, 0x274b734e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10680.3", 0x10000, 0x9f0677ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10687.11", 0x10000, 0x508a4701, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10681.2", 0x10000, 0xb176ea72, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10688.10", 0x10000, 0x42fcd51d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10642.47", 0x08000, 0x7836bcc3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10649c.88", 0x08000, 0xf6c1ce71, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10643.66", 0x08000, 0x06f55364, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10644.67", 0x08000, 0xb41d541d, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10645.68", 0x08000, 0xa60dabff, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-10646.69", 0x08000, 0x473cc411, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shangonle) +STD_ROM_FN(Shangonle) + +static struct BurnRomInfo ToutrunRomDesc[] = { + { "epr-12513.133", 0x10000, 0xae8835a5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12512.118", 0x10000, 0xf90372ad, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12515.132", 0x10000, 0x1f047df4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12514.117", 0x10000, 0x5539e9c3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12293.131", 0x10000, 0xf4321eea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12292.116", 0x10000, 0x51d98af0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12295.76", 0x10000, 0xd43a3a84, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12294.58", 0x10000, 0x27cdcfd3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12297.75", 0x10000, 0x1d9b5677, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12296.57", 0x10000, 0x0a513671, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12323.102", 0x10000, 0x4de43a6f, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12324.103", 0x10000, 0x24607a55, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12325.104", 0x10000, 0x1405137a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12336.9", 0x20000, 0xdda465c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12337.10", 0x20000, 0x828233d1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12338.11", 0x20000, 0x46b4b5f4, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12339.12", 0x20000, 0x0d7e3bab, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12364.13", 0x20000, 0xa4b83e65, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12365.14", 0x20000, 0x4a80b2a9, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12366.15", 0x20000, 0x385cb3ab, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12367.16", 0x20000, 0x4930254a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12299.47", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + { "epr-12298.11", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-12300.88", 0x10000, 0xe8ff7011, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-12301.66", 0x10000, 0x6e78ad15, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12302.67", 0x10000, 0xe72928af, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12303.68", 0x10000, 0x8384205c, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12304.69", 0x10000, 0xe1762ac3, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12305.70", 0x10000, 0xba9ce677, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12306.71", 0x10000, 0xe49249fd, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0118.key", 0x02000, 0x083d7d56, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Toutrun) +STD_ROM_FN(Toutrun) + +static struct BurnRomInfo Toutrun1RomDesc[] = { + { "epr-12289.133", 0x10000, 0x812fd035, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12288.118", 0x10000, 0x2f1151bb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12291.132", 0x10000, 0x8ca284d2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12290.117", 0x10000, 0x44dbf3cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12293.131", 0x10000, 0xf4321eea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12292.116", 0x10000, 0x51d98af0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12295.76", 0x10000, 0xd43a3a84, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12294.58", 0x10000, 0x27cdcfd3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12297.75", 0x10000, 0x1d9b5677, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12296.57", 0x10000, 0x0a513671, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12323.102", 0x10000, 0x4de43a6f, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12324.103", 0x10000, 0x24607a55, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12325.104", 0x10000, 0x1405137a, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12307.9", 0x10000, 0x437dcf09, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12308.10", 0x10000, 0x0de70cc2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12309.11", 0x10000, 0xdeb8c242, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12310.12", 0x10000, 0x45cf157e, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12311.13", 0x10000, 0xae2bd639, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12312.14", 0x10000, 0x626000e7, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12313.15", 0x10000, 0x52870c37, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12314.16", 0x10000, 0x40c461ea, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12315.17", 0x10000, 0x3ff9a3a3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12316.18", 0x10000, 0x8a1e6dc8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12317.19", 0x10000, 0x77e382d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12318.20", 0x10000, 0xd1afdea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12319.25", 0x10000, 0xdf23baf9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12320.22", 0x10000, 0x7931e446, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12321.23", 0x10000, 0x830bacd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12322.24", 0x10000, 0x8b812492, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12299.47", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + { "epr-12298.11", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-12300.88", 0x10000, 0xe8ff7011, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-12301.66", 0x10000, 0x6e78ad15, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12302.67", 0x10000, 0xe72928af, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12303.68", 0x10000, 0x8384205c, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12304.69", 0x10000, 0xe1762ac3, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12305.70", 0x10000, 0xba9ce677, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12306.71", 0x10000, 0xe49249fd, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0109.key", 0x02000, 0xe12a6e78, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Toutrun1) +STD_ROM_FN(Toutrun1) + +static struct BurnRomInfo Toutrun2RomDesc[] = { + { "epr-12397.133", 0x10000, 0xe4b57d7d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12396.118", 0x10000, 0x5e7115cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12399.132", 0x10000, 0x62c77b1b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12398.117", 0x10000, 0x18e34520, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12293.131", 0x10000, 0xf4321eea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12292.116", 0x10000, 0x51d98af0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12295.76", 0x10000, 0xd43a3a84, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12294.58", 0x10000, 0x27cdcfd3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12297.75", 0x10000, 0x1d9b5677, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12296.57", 0x10000, 0x0a513671, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12323.102", 0x10000, 0x4de43a6f, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12324.103", 0x10000, 0x24607a55, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12325.104", 0x10000, 0x1405137a, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12307.9", 0x10000, 0x437dcf09, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12308.10", 0x10000, 0x0de70cc2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12309.11", 0x10000, 0xdeb8c242, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12310.12", 0x10000, 0x45cf157e, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12311.13", 0x10000, 0xae2bd639, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12312.14", 0x10000, 0x626000e7, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12313.15", 0x10000, 0x52870c37, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12314.16", 0x10000, 0x40c461ea, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12315.17", 0x10000, 0x3ff9a3a3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12316.18", 0x10000, 0x8a1e6dc8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12317.19", 0x10000, 0x77e382d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12318.20", 0x10000, 0xd1afdea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12319.25", 0x10000, 0xdf23baf9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12320.22", 0x10000, 0x7931e446, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12321.23", 0x10000, 0x830bacd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12322.24", 0x10000, 0x8b812492, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12299.47", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + { "epr-12298.11", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-12300.88", 0x10000, 0xe8ff7011, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-12301.66", 0x10000, 0x6e78ad15, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12302.67", 0x10000, 0xe72928af, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12303.68", 0x10000, 0x8384205c, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12304.69", 0x10000, 0xe1762ac3, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12305.70", 0x10000, 0xba9ce677, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12306.71", 0x10000, 0xe49249fd, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-unknown-toutrun1.key", 0x02000, 0x00000000, SYS16_ROM_KEY | BRF_ESS | BRF_PRG | BRF_NODUMP }, +}; + + +STD_ROM_PICK(Toutrun2) +STD_ROM_FN(Toutrun2) + +static struct BurnRomInfo Toutrun3RomDesc[] = { + { "epr-12410.133", 0x10000, 0xaa74f3e9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12409.118", 0x10000, 0xc11c8ef7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12412.132", 0x10000, 0xb0534647, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12411.117", 0x10000, 0x12bb0d83, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12293.131", 0x10000, 0xf4321eea, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12292.116", 0x10000, 0x51d98af0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12295.76", 0x10000, 0xd43a3a84, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12294.58", 0x10000, 0x27cdcfd3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12297.75", 0x10000, 0x1d9b5677, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "opr-12296.57", 0x10000, 0x0a513671, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12323.102", 0x10000, 0x4de43a6f, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12324.103", 0x10000, 0x24607a55, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12325.104", 0x10000, 0x1405137a, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12307.9", 0x10000, 0x437dcf09, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12308.10", 0x10000, 0x0de70cc2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12309.11", 0x10000, 0xdeb8c242, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12310.12", 0x10000, 0x45cf157e, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12311.13", 0x10000, 0xae2bd639, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12312.14", 0x10000, 0x626000e7, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12313.15", 0x10000, 0x52870c37, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12314.16", 0x10000, 0x40c461ea, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12315.17", 0x10000, 0x3ff9a3a3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12316.18", 0x10000, 0x8a1e6dc8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12317.19", 0x10000, 0x77e382d4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12318.20", 0x10000, 0xd1afdea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12319.25", 0x10000, 0xdf23baf9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12320.22", 0x10000, 0x7931e446, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12321.23", 0x10000, 0x830bacd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12322.24", 0x10000, 0x8b812492, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12299.47", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + { "epr-12298.11", 0x08000, 0xfc9bc41b, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-12300.88", 0x10000, 0xe8ff7011, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-12301.66", 0x10000, 0x6e78ad15, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12302.67", 0x10000, 0xe72928af, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12303.68", 0x10000, 0x8384205c, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12304.69", 0x10000, 0xe1762ac3, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12305.70", 0x10000, 0xba9ce677, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-12306.71", 0x10000, 0xe49249fd, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-unknown.key", 0x02000, 0x33e632ae, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Toutrun3) +STD_ROM_FN(Toutrun3) + +/*==================================================== +Memory Handlers +====================================================*/ + +void OutrunPPI0WritePortC(UINT8 data) +{ + System16VideoEnable = data & 0x20; + + if (!(data & 0x01)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } +} + +UINT16 __fastcall OutrunReadWord(UINT32 a) +{ + switch (a) { + case 0x140060: { + // watchdog read + return 0; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall OutrunReadByte(UINT32 a) +{ + switch (a) { + case 0x140001: { + ppi8255_r(0, (a - 0x140000) >> 1); + } + + case 0x140011: { + return 0xff - System16Input[0]; + } + + case 0x140015: { + return System16Dip[0]; + } + + case 0x140017: { + return System16Dip[1]; + } + + case 0x140031: { + if (System16ProcessAnalogControlsDo) return System16ProcessAnalogControlsDo(System16AnalogSelect); + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall OutrunWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x100000 && a <= 0x10ffff) { + System16BTileWordWrite(a - 0x100000, d); + return; + } + + switch (a) { + case 0x140070: { + UINT32 *src = (UINT32 *)System16SpriteRam; + UINT32 *dst = (UINT32 *)System16SpriteRamBuff; + + /* swap the halves of the sprite RAM */ + for (UINT32 i = 0; i < System16SpriteRamSize/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + /* hack for thunderblade */ + memset(System16SpriteRam, 0xff, System16SpriteRamSize); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall OutrunWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x100000 && a <= 0x10ffff) { + System16BTileByteWrite((a - 0x100000) ^ 1, d); + return; + } + + switch (a) { + case 0x140003: + case 0x140005: + case 0x140007: { + ppi8255_w(0, (a - 0x140000) >> 1, d & 0xff); + } + + case 0x140031: { + System16AnalogSelect = d; + return; + } + + case 0x140071: { + UINT32 *src = (UINT32 *)System16SpriteRam; + UINT32 *dst = (UINT32 *)System16SpriteRamBuff; + + /* swap the halves of the sprite RAM */ + for (UINT32 i = 0; i < System16SpriteRamSize/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + /* hack for thunderblade */ + memset(System16SpriteRam, 0xff, System16SpriteRamSize); + return; + } + + case 0xffff07: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT8 __fastcall Outrun2ReadByte(UINT32 a) +{ + switch (a) { + case 0x090000: + case 0x090001: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Read Byte -> 0x%06X\n"), a); +#endif + + return 0; +} + +void __fastcall Outrun2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x090000: { + System16RoadControl = d & 3; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall Outrun2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x090001: { + System16RoadControl = d & 3; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT16 __fastcall ShangonReadWord(UINT32 a) +{ + switch (a) { + case 0x141002: { + return 0xff - System16Input[0]; + } + + case 0x141004: { + return System16Dip[0]; + } + + case 0x141006: { + return System16Dip[1]; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall ShangonReadByte(UINT32 a) +{ + switch (a) { + case 0x141003: { + return 0xff - System16Input[0]; + } + + case 0x141005: { + return System16Dip[0]; + } + + case 0x141007: { + return System16Dip[1]; + } + + case 0x143021: { + if (System16ProcessAnalogControlsDo) return System16ProcessAnalogControlsDo(System16AnalogSelect); + } + + case 0x290000: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + + case 0xffff05: { + return System16SoundLatch; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall ShangonWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x100000 && a <= 0x10ffff) { + System16BTileWordWrite(a - 0x100000, d); + return; + } + + switch (a) { + case 0x290000: { + System16RoadControl = d & 3; + return; + } + + case 0xffff06: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nSystem16CyclesDone[2] += ZetRun(200); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall ShangonWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x100000 && a <= 0x10ffff) { + System16BTileByteWrite((a - 0x100000) ^ 1, d); + return; + } + + switch (a) { + case 0x140001: { + System16AnalogSelect = (d >> 6) & 3; + System16VideoEnable = (d >> 5) & 1; + return; + } + + case 0x140021: { + if (!(d & 1)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + return; + + } + + case 0x143001: { + // watchdog write + return; + } + + case 0x143021: { + return; + } + + case 0xffff07: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nSystem16CyclesDone[2] += ZetRun(200); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +/*==================================================== +Driver Inits +====================================================*/ + +UINT8 OutrunProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Steering + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + + // Accelerate + case 4: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + + // Brake + case 8: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + } + + return 0; +} + +UINT8 ShangonProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Steering + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + + // Brake + case 2: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + } + + return 0; +} + +static INT32 OutrunInit() +{ + System16ProcessAnalogControlsDo = OutrunProcessAnalogControls; + + System16HasGears = true; + + System16PCMDataSizePreAllocate = 0x60000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0x30000); + memcpy(pTemp, System16PCMData, 0x30000); + memset(System16PCMData, 0, 0x60000); + memcpy(System16PCMData + 0x00000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x08000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x10000, pTemp + 0x08000, 0x8000); + memcpy(System16PCMData + 0x18000, pTemp + 0x08000, 0x8000); + memcpy(System16PCMData + 0x20000, pTemp + 0x10000, 0x8000); + memcpy(System16PCMData + 0x28000, pTemp + 0x10000, 0x8000); + memcpy(System16PCMData + 0x30000, pTemp + 0x18000, 0x8000); + memcpy(System16PCMData + 0x38000, pTemp + 0x18000, 0x8000); + memcpy(System16PCMData + 0x40000, pTemp + 0x20000, 0x8000); + memcpy(System16PCMData + 0x48000, pTemp + 0x20000, 0x8000); + memcpy(System16PCMData + 0x50000, pTemp + 0x28000, 0x8000); + memcpy(System16PCMData + 0x58000, pTemp + 0x28000, 0x8000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 OutrunbInit() +{ + System16ProcessAnalogControlsDo = OutrunProcessAnalogControls; + + System16HasGears = true; + + System16PCMDataSizePreAllocate = 0x60000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT16 *word; + UINT8 *byte; + INT32 i, length; + + /* main CPU: swap bits 11,12 and 6,7 */ + word = (UINT16 *)System16Rom; + length = System16RomSize / 2; + for (i = 0; i < length; i++) + word[i] = BITSWAP16(word[i], 15,14,11,12,13,10,9,8,6,7,5,4,3,2,1,0); + + memcpy(System16Code, System16Rom, System16RomSize); + + /* sub CPU: swap bits 14,15 and 2,3 */ + word = (UINT16 *)System16Rom2; + length = System16Rom2Size / 2; + for (i = 0; i < length; i++) + word[i] = BITSWAP16(word[i], 14,15,13,12,11,10,9,8,7,6,5,4,2,3,1,0); + + /* road gfx */ + /* rom a-2.bin: swap bits 6,7 */ + /* rom a-3.bin: swap bits 5,6 */ + byte = System16Roads; + length = 0x40000 / 2; + for (i = 0; i < length; i++) + { + byte[i] = BITSWAP08(byte[i], 6,7,5,4,3,2,1,0); + byte[i+length] = BITSWAP08(byte[i+length], 7,5,6,4,3,2,1,0); + } + + /* Z80 code: swap bits 5,6 */ + byte = System16Z80Rom; + length = System16Z80RomSize; + for (i = 0; i < length; i++) { + byte[i] = BITSWAP08(byte[i], 7,5,6,4,3,2,1,0); + } + + UINT8 *pTemp = (UINT8*)malloc(0x30000); + memcpy(pTemp, System16PCMData, 0x30000); + memset(System16PCMData, 0, 0x60000); + memcpy(System16PCMData + 0x00000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x10000, pTemp + 0x08000, 0x8000); + memcpy(System16PCMData + 0x20000, pTemp + 0x10000, 0x8000); + memcpy(System16PCMData + 0x30000, pTemp + 0x18000, 0x8000); + memcpy(System16PCMData + 0x40000, pTemp + 0x20000, 0x8000); + memcpy(System16PCMData + 0x50000, pTemp + 0x28000, 0x8000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 ShangonInit() +{ + System16ProcessAnalogControlsDo = ShangonProcessAnalogControls; + + Shangon = true; + + System16PCMDataSizePreAllocate = 0x40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadWordHandler(0, ShangonReadWord); + SekSetWriteWordHandler(0, ShangonWriteWord); + SekSetReadByteHandler(0, ShangonReadByte); + SekSetWriteByteHandler(0, ShangonWriteByte); + SekClose(); + + System16RoadColorOffset1 = 0x7f6; + System16RoadColorOffset2 = 0x7c0; + System16RoadColorOffset3 = 0x7c0; + + UINT8 *pTemp = (UINT8*)malloc(0x20000); + memcpy(pTemp, System16PCMData, 0x20000); + memset(System16PCMData, 0, 0x40000); + memcpy(System16PCMData + 0x00000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x08000, pTemp + 0x00000, 0x8000); + memcpy(System16PCMData + 0x10000, pTemp + 0x08000, 0x8000); + memcpy(System16PCMData + 0x18000, pTemp + 0x08000, 0x8000); + memcpy(System16PCMData + 0x20000, pTemp + 0x10000, 0x8000); + memcpy(System16PCMData + 0x28000, pTemp + 0x10000, 0x8000); + memcpy(System16PCMData + 0x30000, pTemp + 0x18000, 0x8000); + memcpy(System16PCMData + 0x38000, pTemp + 0x18000, 0x8000); + } + + return nRet; +} + +static INT32 Shangon2Init() +{ + System16ProcessAnalogControlsDo = ShangonProcessAnalogControls; + + System16PCMDataSizePreAllocate = 0x40000; + + return ShangonInit(); +} + +static INT32 ToutrunInit() +{ + System16ProcessAnalogControlsDo = OutrunProcessAnalogControls; + + System16HasGears = true; + + System16PCMDataSizePreAllocate = 0x60000; + + return System16Init(); +} + +/*==================================================== +Driver Defs +====================================================*/ + +struct BurnDriver BurnDrvOutrun = { + "outrun", NULL, NULL, NULL, "1986", + "Out Run (sitdown/upright, Rev B)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_HISCORE_SUPPORTED, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, OutrunRomInfo, OutrunRomName, NULL, NULL, OutrunInputInfo, OutrunDIPInfo, + OutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOutruno = { + "outruno", "outrun", NULL, NULL, "1986", + "Out Run (sitdown/upright)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, OutrunoRomInfo, OutrunoRomName, NULL, NULL, OutrunInputInfo, OutrundxDIPInfo, + OutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOutrundx = { + "outrundx", "outrun", NULL, NULL, "1986", + "Out Run (deluxe sitdown)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, OutrundxRomInfo, OutrundxRomName, NULL, NULL, OutrunInputInfo, OutrundxDIPInfo, + OutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOutrunra = { + "outrunra", "outrun", NULL, NULL, "1986", + "Out Run (sitdown/upright, Rev A)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, OutrunraRomInfo, OutrunraRomName, NULL, NULL, OutrunInputInfo, OutrunDIPInfo, + OutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOutrunb = { + "outrunb", "outrun", NULL, NULL, "1986", + "Out Run (bootleg)\0", NULL, "bootleg", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, OutrunbRomInfo, OutrunbRomName, NULL, NULL, OutrunInputInfo, OutrunDIPInfo, + OutrunbInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShangon = { + "shangon", NULL, NULL, NULL, "1987", + "Super Hang-On (sitdown/upright, unprotected)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_OUTRUN, GBF_RACING, 0, + NULL, ShangonRomInfo, ShangonRomName, NULL, NULL, ShangonInputInfo, ShangonDIPInfo, + ShangonInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShangon2 = { + "shangon2", "shangon", NULL, NULL, "1987", + "Super Hang-On (mini ride-on, Rev A, FD1089B 317-0034)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1089B_ENC, GBF_RACING, 0, + NULL, Shangon2RomInfo, Shangon2RomName, NULL, NULL, ShangonInputInfo, ShangonDIPInfo, + Shangon2Init, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShangon3 = { + "shangon3", "shangon", NULL, NULL, "1987", + "Super Hang-On (sitdown/upright, FD1089B 317-0034)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1089B_ENC, GBF_RACING, 0, + NULL, Shangon3RomInfo, Shangon3RomName, NULL, NULL, ShangonInputInfo, ShangonDIPInfo, + Shangon2Init, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShangonle = { + "shangonle", "shangon", NULL, NULL, "1991", + "Limited Edition Hang-On\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN, GBF_RACING, 0, + NULL, ShangonleRomInfo, ShangonleRomName, NULL, NULL, ShangonInputInfo, ShangonDIPInfo, + ShangonInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvToutrun = { + "toutrun", NULL, NULL, NULL, "1989", + "Turbo Out Run (Out Run upgrade, FD1094 317-0118)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, ToutrunRomInfo, ToutrunRomName, NULL, NULL, ToutrunInputInfo, ToutrunDIPInfo, + ToutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvToutrun1 = { + "toutrun1", "toutrun", NULL, NULL, "1989", + "Turbo Out Run (deluxe cockpit, FD1094 317-0109)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, Toutrun1RomInfo, Toutrun1RomName, NULL, NULL, ToutrunInputInfo, ToutrunmDIPInfo, + ToutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvToutrun2 = { + "toutrun2", "toutrun", NULL, NULL, "1989", + "Turbo Out Run (cockpit, FD1094 317-unknown)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, Toutrun2RomInfo, Toutrun2RomName, NULL, NULL, ToutrunInputInfo, ToutrunDIPInfo, + ToutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvToutrun3 = { + "toutrun3", "toutrun", NULL, NULL, "1989", + "Turbo Out Run (upright, FD1094 317-unknown)\0", NULL, "Sega", "Out Run", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_OUTRUN | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_SPRITE_LOAD32, GBF_RACING, 0, + NULL, Toutrun3RomInfo, Toutrun3RomName, NULL, NULL, ToutrunInputInfo, ToutruncDIPInfo, + ToutrunInit, System16Exit, OutrunFrame, NULL, System16Scan, + NULL, 0x3000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_sys1.cpp b/src/burn/drivers/sega/d_sys1.cpp new file mode 100644 index 00000000..f0c12753 --- /dev/null +++ b/src/burn/drivers/sega/d_sys1.cpp @@ -0,0 +1,5417 @@ +#include "tiles_generic.h" +#include "sn76496.h" +#include "bitswap.h" +#include "mc8123.h" + +static UINT8 System1InputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 System1InputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 System1InputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 System1Dip[2] = {0, 0}; +static UINT8 System1Input[3] = {0x00, 0x00, 0x00 }; +static UINT8 System1Reset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *System1Rom1 = NULL; +static UINT8 *System1Rom2 = NULL; +static UINT8 *System1PromRed = NULL; +static UINT8 *System1PromGreen = NULL; +static UINT8 *System1PromBlue = NULL; +static UINT8 *System1Ram1 = NULL; +static UINT8 *System1Ram2 = NULL; +static UINT8 *System1SpriteRam = NULL; +static UINT8 *System1PaletteRam = NULL; +static UINT8 *System1BgRam = NULL; +static UINT8 *System1VideoRam = NULL; +static UINT8 *System1BgCollisionRam = NULL; +static UINT8 *System1SprCollisionRam = NULL; +static UINT8 *System1deRam = NULL; +static UINT8 *System1efRam = NULL; +static UINT8 *System1f4Ram = NULL; +static UINT8 *System1fcRam = NULL; +static UINT32 *System1Palette = NULL; +static UINT8 *System1Tiles = NULL; +static UINT8 *System1Sprites = NULL; +static UINT8 *System1TempRom = NULL; +static UINT8 *SpriteOnScreenMap = NULL; +static UINT8 *System1Fetch1 = NULL; +static UINT8 *System1MC8123Key = NULL; +static UINT32 *System1TilesPenUsage = NULL; + +static UINT8 System1ScrollX[2]; +static UINT8 System1ScrollY; +static INT32 System1BgScrollX; +static INT32 System1BgScrollY; +static INT32 System1VideoMode; +static INT32 System1FlipScreen; +static INT32 System1SoundLatch; +static INT32 System1RomBank; +static INT32 NoboranbInp16Step; +static INT32 NoboranbInp17Step; +static INT32 NoboranbInp23Step; +static UINT8 BlockgalDial1; +static UINT8 BlockgalDial2; + +static INT32 System1SpriteRomSize; +static INT32 System1NumTiles; +static INT32 System1SpriteXOffset; +static INT32 System1ColourProms = 0; +static INT32 System1BankedRom = 0; + +typedef void (*Decode)(); +static Decode DecodeFunction; +static Decode TileDecodeFunction; + +typedef void (*Render)(); +static Render System1Draw; +static void System1Render(); +//static void WbmlRender(); + +typedef void (*MakeInputs)(); +static MakeInputs MakeInputsFunction; + +static INT32 nCyclesDone[2], nCyclesTotal[2]; +static INT32 nCyclesSegment; + +/*============================================================================================== +Input Definitions +===============================================================================================*/ + +static struct BurnInputInfo BlockgalInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort2 + 6, "p1 fire 1" }, + + {"P2 Left" , BIT_DIGITAL , System1InputPort0 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort0 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort2 + 7, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Blockgal) + +static struct BurnInputInfo FlickyInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 1" }, + + {"P2 Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Flicky) + +static struct BurnInputInfo MyheroInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System1InputPort0 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System1InputPort0 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort0 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System1InputPort1 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System1InputPort1 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort1 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Myhero) + +static struct BurnInputInfo SeganinjInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System1InputPort0 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System1InputPort0 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System1InputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , System1InputPort1 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System1InputPort1 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System1InputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Seganinj) + +static struct BurnInputInfo UpndownInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System1InputPort0 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System1InputPort0 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , System1InputPort1 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System1InputPort1 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Upndown) + +static struct BurnInputInfo WboyInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort0 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort1 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Wboy) + +static struct BurnInputInfo WmatchInputList[] = { + {"Coin 1" , BIT_DIGITAL , System1InputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System1InputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System1InputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System1InputPort2 + 5, "p2 start" }, + + {"P1 Left Up" , BIT_DIGITAL , System1InputPort0 + 5, "p1 up" }, + {"P1 Left Down" , BIT_DIGITAL , System1InputPort0 + 4, "p1 down" }, + {"P1 Left Left" , BIT_DIGITAL , System1InputPort0 + 7, "p1 left" }, + {"P1 Left Right" , BIT_DIGITAL , System1InputPort0 + 6, "p1 right" }, + {"P1 Right Up" , BIT_DIGITAL , System1InputPort0 + 1, "p1 fire 1" }, + {"P1 Right Down" , BIT_DIGITAL , System1InputPort0 + 0, "p1 fire 2" }, + {"P1 Right Left" , BIT_DIGITAL , System1InputPort0 + 3, "p1 fire 3" }, + {"P1 Right Right" , BIT_DIGITAL , System1InputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 1" , BIT_DIGITAL , System1InputPort2 + 6, "p1 fire 5" }, + + {"P2 Left Up" , BIT_DIGITAL , System1InputPort1 + 5, "p2 up" }, + {"P2 Left Down" , BIT_DIGITAL , System1InputPort1 + 4, "p2 down" }, + {"P2 Left Left" , BIT_DIGITAL , System1InputPort1 + 7, "p2 left" }, + {"P2 Left Right" , BIT_DIGITAL , System1InputPort1 + 6, "p2 right" }, + {"P2 Right Up" , BIT_DIGITAL , System1InputPort1 + 1, "p2 fire 1" }, + {"P2 Right Down" , BIT_DIGITAL , System1InputPort1 + 0, "p2 fire 2" }, + {"P2 Right Left" , BIT_DIGITAL , System1InputPort1 + 3, "p2 fire 3" }, + {"P2 Right Right" , BIT_DIGITAL , System1InputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 1" , BIT_DIGITAL , System1InputPort2 + 7, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &System1Reset , "reset" }, + {"Service" , BIT_DIGITAL , System1InputPort2 + 3, "service" }, + {"Test" , BIT_DIGITAL , System1InputPort2 + 2, "diag" }, + {"Dip 1" , BIT_DIPSWITCH, System1Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System1Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Wmatch) + +inline void System1ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x30) == 0x30) { + *nJoystickInputs &= ~0x30; + } + if ((*nJoystickInputs & 0xc0) == 0xc0) { + *nJoystickInputs &= ~0xc0; + } +} + +static inline void System1MakeInputs() +{ + // Reset Inputs + System1Input[0] = System1Input[1] = System1Input[2] = 0x00; + + // Compile Digital Inputs + for (int i = 0; i < 8; i++) { + System1Input[0] |= (System1InputPort0[i] & 1) << i; + System1Input[1] |= (System1InputPort1[i] & 1) << i; + System1Input[2] |= (System1InputPort2[i] & 1) << i; + } + + // Clear Opposites + System1ClearOpposites(&System1Input[0]); + System1ClearOpposites(&System1Input[1]); +} + +static inline void BlockgalMakeInputs() +{ + System1Input[2] = 0x00; + + for (int i = 0; i < 8; i++) { + System1Input[2] |= (System1InputPort2[i] & 1) << i; + } + + if (System1InputPort0[0]) BlockgalDial1 += 0x04; + if (System1InputPort0[1]) BlockgalDial1 -= 0x04; + + if (System1InputPort0[2]) BlockgalDial2 += 0x04; + if (System1InputPort0[3]) BlockgalDial2 -= 0x04;; +} + +#define SYSTEM1_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 4/2 5/3 6/4"}, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 4/2 5/3 6/4"}, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x00, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + +static struct BurnDIPInfo FourdwarrioDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x06, 0x06, "3" }, + {0x14, 0x01, 0x06, 0x04, "4" }, + {0x14, 0x01, 0x06, 0x02, "5" }, + {0x14, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x14, 0x01, 0x38, 0x38, "30k" }, + {0x14, 0x01, 0x38, 0x30, "40k" }, + {0x14, 0x01, 0x38, 0x28, "50k" }, + {0x14, 0x01, 0x38, 0x20, "60k" }, + {0x14, 0x01, 0x38, 0x18, "70k" }, + {0x14, 0x01, 0x38, 0x10, "80k" }, + {0x14, 0x01, 0x38, 0x08, "90k" }, + {0x14, 0x01, 0x38, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Fourdwarrio) + +static struct BurnDIPInfo BlockgalDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0xd7, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0c, 0x01, 0x01, 0x00, "Upright" }, + {0x0c, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x00, "Off" }, + {0x0c, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0c, 0x01, 0x08, 0x08, "2" }, + {0x0c, 0x01, 0x08, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0c, 0x01, 0x10, 0x10, "10k 30k 60k 100k 150k" }, + {0x0c, 0x01, 0x10, 0x00, "30k 50k 100k 200k 300k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x20, "Off" }, + {0x0c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x80, 0x80, "Off" }, + {0x0c, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + SYSTEM1_COINAGE(0x0d) +}; + +STDDIPINFO(Blockgal) + +static struct BurnDIPInfo BrainDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, +}; + +STDDIPINFO(Brain) + +static struct BurnDIPInfo BullfgtDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "30k" }, + {0x14, 0x01, 0x30, 0x20, "50k" }, + {0x14, 0x01, 0x30, 0x10, "70k" }, + {0x14, 0x01, 0x30, 0x00, "None" }, +}; + +STDDIPINFO(Bullfgt) + +static struct BurnDIPInfo FlickyDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x0d) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x01, 0x00, "Upright" }, + {0x0e, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0e, 0x01, 0x0c, 0x0c, "2" }, + {0x0e, 0x01, 0x0c, 0x08, "3" }, + {0x0e, 0x01, 0x0c, 0x04, "4" }, + {0x0e, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0e, 0x01, 0x30, 0x30, "30k 80k 160k" }, + {0x0e, 0x01, 0x30, 0x20, "30k 100k 200k" }, + {0x0e, 0x01, 0x30, 0x10, "40k 120k 240k" }, + {0x0e, 0x01, 0x30, 0x00, "40k 140k 280k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x0e, 0x01, 0x40, 0x40, "Easy" }, + {0x0e, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Flicky) + +static struct BurnDIPInfo GardiaDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7c, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, " 5k 20k 30k" }, + {0x14, 0x01, 0x30, 0x20, "10k 25k 50k" }, + {0x14, 0x01, 0x30, 0x10, "15k 30k 60k" }, + {0x14, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Gardia) + +static struct BurnDIPInfo ImsorryDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "30k" }, + {0x14, 0x01, 0x30, 0x20, "40k" }, + {0x14, 0x01, 0x30, 0x10, "50k" }, + {0x14, 0x01, 0x30, 0x00, "None" }, +}; + +STDDIPINFO(Imsorry) + +static struct BurnDIPInfo MrvikingDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7c, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Maximum Credit" }, + {0x14, 0x01, 0x02, 0x02, "9" }, + {0x14, 0x01, 0x02, 0x00, "99" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "10k, 30k then every 30k"}, + {0x14, 0x01, 0x30, 0x20, "20k, 40k then every 30k"}, + {0x14, 0x01, 0x30, 0x10, "30k, then every 30k" }, + {0x14, 0x01, 0x30, 0x00, "40k, then every 30k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Mrviking) + +static struct BurnDIPInfo MrvikngjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7c, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "10k, 30k then every 30k"}, + {0x14, 0x01, 0x30, 0x20, "20k, 40k then every 30k"}, + {0x14, 0x01, 0x30, 0x10, "30k, then every 30k" }, + {0x14, 0x01, 0x30, 0x00, "40k, then every 30k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Mrvikngj) + +static struct BurnDIPInfo MyheroDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "30k" }, + {0x14, 0x01, 0x30, 0x20, "50k" }, + {0x14, 0x01, 0x30, 0x10, "70k" }, + {0x14, 0x01, 0x30, 0x00, "90k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Myhero) + +static struct BurnDIPInfo NobbDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x2f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x03, 0x00, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0x0c, 0x00, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + {0x13, 0x01, 0x0c, 0x04, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x13, 0x01, 0x30, 0x20, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Medium" }, + {0x13, 0x01, 0x30, 0x10, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x40, 0x00, "Upright" }, + {0x13, 0x01, 0x40, 0x40, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x80, 0x00, "Off" }, + {0x13, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x03, 0x02, "2" }, + {0x14, 0x01, 0x03, 0x03, "3" }, + {0x14, 0x01, 0x03, 0x01, "5" }, + {0x14, 0x01, 0x03, 0x00, "99" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "40k, 80k, 120k, 160k" }, + {0x14, 0x01, 0x0c, 0x0c, "50k, 100k, 150k" }, + {0x14, 0x01, 0x0c, 0x04, "60k, 120k, 180k" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, +}; + +STDDIPINFO(Nobb) + +static struct BurnDIPInfo Pitfall2DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xdc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x14, 0x01, 0x10, 0x10, "20k 50k" }, + {0x14, 0x01, 0x10, 0x00, "30k 70k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x14, 0x01, 0x40, 0x00, "2 minutes" }, + {0x14, 0x01, 0x40, 0x40, "3 minutes" }, +}; + +STDDIPINFO(Pitfall2) + +static struct BurnDIPInfo PitfalluDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xde, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x06, 0x06, "3" }, + {0x14, 0x01, 0x06, 0x04, "4" }, + {0x14, 0x01, 0x06, 0x02, "5" }, + {0x14, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Starting Stage" }, + {0x14, 0x01, 0x18, 0x18, "1" }, + {0x14, 0x01, 0x18, 0x10, "2" }, + {0x14, 0x01, 0x18, 0x08, "3" }, + {0x14, 0x01, 0x18, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x20, 0x20, "Off" }, + {0x14, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x14, 0x01, 0x40, 0x00, "2 minutes" }, + {0x14, 0x01, 0x40, 0x40, "3 minutes" }, +}; + +STDDIPINFO(Pitfallu) + +static struct BurnDIPInfo RaflesiaDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "20k, 70k and 120k" }, + {0x14, 0x01, 0x30, 0x20, "30k, 80k and 150k" }, + {0x14, 0x01, 0x30, 0x10, "50k, 100k and 200k" }, + {0x14, 0x01, 0x30, 0x00, "None" }, +}; + +STDDIPINFO(Raflesia) + +static struct BurnDIPInfo RegulusDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x7e, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "Off" }, + {0x14, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Regulus) + +static struct BurnDIPInfo RegulusoDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Reguluso) + +static struct BurnDIPInfo SeganinjDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xdc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x15) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x16, 0x01, 0x01, 0x00, "Upright" }, + {0x16, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x0c, 0x08, "2" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x04, "4" }, + {0x16, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x16, 0x01, 0x10, 0x10, "20k 70k 120k 170k" }, + {0x16, 0x01, 0x10, 0x00, "50k 100k 150k 200k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x20, 0x20, "Off" }, + {0x16, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x16, 0x01, 0x40, 0x40, "Easy" }, + {0x16, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Seganinj) + +static struct BurnDIPInfo SpatterDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x08, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x04, "4" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "40k, 120k and 480k" }, + {0x14, 0x01, 0x30, 0x20, "50k and 200k" }, + {0x14, 0x01, 0x30, 0x10, "100k only" }, + {0x14, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Reset Timer/Objects on Life Loss" }, + {0x14, 0x01, 0x40, 0x40, "No" }, + {0x14, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Spatter) + +static struct BurnDIPInfo StarjackDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf6, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x06, 0x06, "3" }, + {0x14, 0x01, 0x06, 0x04, "4" }, + {0x14, 0x01, 0x06, 0x02, "5" }, + {0x14, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x14, 0x01, 0x38, 0x38, "Every 20k" }, + {0x14, 0x01, 0x38, 0x28, "Every 30k" }, + {0x14, 0x01, 0x38, 0x18, "Every 40k" }, + {0x14, 0x01, 0x38, 0x08, "Every 50k" }, + {0x14, 0x01, 0x38, 0x30, "20k, then every 30k" }, + {0x14, 0x01, 0x38, 0x20, "30k, then every 40k" }, + {0x14, 0x01, 0x38, 0x10, "40k, then every 50k" }, + {0x14, 0x01, 0x38, 0x00, "50k, then every 60k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0xc0, 0xc0, "Easy" }, + {0x14, 0x01, 0xc0, 0x80, "Medium" }, + {0x14, 0x01, 0xc0, 0x40, "Hard" }, + {0x14, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Starjack) + +static struct BurnDIPInfo StarjacsDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x06, 0x06, "3" }, + {0x14, 0x01, 0x06, 0x04, "4" }, + {0x14, 0x01, 0x06, 0x02, "5" }, + {0x14, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 2 , "Ship" }, + {0x14, 0x01, 0x08, 0x08, "Single" }, + {0x14, 0x01, 0x08, 0x00, "Multi" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "30k, then every 40k" }, + {0x14, 0x01, 0x30, 0x20, "40k, then every 50k" }, + {0x14, 0x01, 0x30, 0x10, "50k, then every 60k" }, + {0x14, 0x01, 0x30, 0x00, "60k, then every 70k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0xc0, 0xc0, "Easy" }, + {0x14, 0x01, 0xc0, 0x80, "Medium" }, + {0x14, 0x01, 0xc0, 0x40, "Hard" }, + {0x14, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Starjacs) + +static struct BurnDIPInfo SwatDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x06, 0x06, "3" }, + {0x14, 0x01, 0x06, 0x04, "4" }, + {0x14, 0x01, 0x06, 0x02, "5" }, + {0x14, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x14, 0x01, 0x38, 0x38, "30k" }, + {0x14, 0x01, 0x38, 0x30, "40k" }, + {0x14, 0x01, 0x38, 0x28, "50k" }, + {0x14, 0x01, 0x38, 0x20, "60k" }, + {0x14, 0x01, 0x38, 0x18, "70k" }, + {0x14, 0x01, 0x38, 0x10, "80k" }, + {0x14, 0x01, 0x38, 0x08, "90k" }, + {0x14, 0x01, 0x38, 0x00, "None" }, +}; + +STDDIPINFO(Swat) + +static struct BurnDIPInfo TeddybbDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x00, "Off" }, + {0x14, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x08, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x04, "4" }, + {0x14, 0x01, 0x0c, 0x00, "252" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "100k 400k" }, + {0x14, 0x01, 0x30, 0x20, "200k 600k" }, + {0x14, 0x01, 0x30, 0x10, "400k 800k" }, + {0x14, 0x01, 0x30, 0x00, "600k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Easy" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Teddybb) + +static struct BurnDIPInfo UpndownDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x11) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x12, 0x01, 0x01, 0x00, "Upright" }, + {0x12, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x06, 0x06, "3" }, + {0x12, 0x01, 0x06, 0x04, "4" }, + {0x12, 0x01, 0x06, 0x02, "5" }, + {0x12, 0x01, 0x06, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 8 , "Bonus Life" }, + {0x12, 0x01, 0x38, 0x38, "10k" }, + {0x12, 0x01, 0x38, 0x30, "20k" }, + {0x12, 0x01, 0x38, 0x28, "30k" }, + {0x12, 0x01, 0x38, 0x20, "40k" }, + {0x12, 0x01, 0x38, 0x18, "50k" }, + {0x12, 0x01, 0x38, 0x10, "60k" }, + {0x12, 0x01, 0x38, 0x08, "70k" }, + {0x12, 0x01, 0x38, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0xc0, 0xc0, "Easy" }, + {0x12, 0x01, 0xc0, 0x80, "Medium" }, + {0x12, 0x01, 0xc0, 0x40, "Hard" }, + {0x12, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Upndown) + +static struct BurnDIPInfo WboyDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xec, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x0f) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Upright" }, + {0x10, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x02, "Off" }, + {0x10, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "3" }, + {0x10, 0x01, 0x0c, 0x08, "4" }, + {0x10, 0x01, 0x0c, 0x04, "5" }, + {0x10, 0x01, 0x0c, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x10, 0x10, "30k 100k 170k 240k" }, + {0x10, 0x01, 0x10, 0x00, "30k 120k 210k 300k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x20, 0x00, "Off" }, + {0x10, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x40, 0x40, "Easy" }, + {0x10, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Wboy) + +static struct BurnDIPInfo Wboy3DIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xec, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x0f) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Upright" }, + {0x10, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x02, "Off" }, + {0x10, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "1" }, + {0x10, 0x01, 0x0c, 0x08, "2" }, + {0x10, 0x01, 0x0c, 0x04, "3" }, + {0x10, 0x01, 0x0c, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x10, 0x10, "30k 100k 170k 240k" }, + {0x10, 0x01, 0x10, 0x00, "30k 120k 210k 300k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x20, 0x00, "Off" }, + {0x10, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x40, 0x40, "Easy" }, + {0x10, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Wboy3) + +static struct BurnDIPInfo WboyuDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xbe, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x01, 0x00, "Upright" }, + {0x0f, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x06, 0x00, "2" }, + {0x0f, 0x01, 0x06, 0x06, "3" }, + {0x0f, 0x01, 0x06, 0x04, "4" }, + {0x0f, 0x01, 0x06, 0x02, "5" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Coinage" }, + {0x10, 0x01, 0x07, 0x04, "4 Coins 1 Credit" }, + {0x10, 0x01, 0x07, 0x05, "3 Coins 1 Credit" }, + {0x10, 0x01, 0x07, 0x00, "4 Coins 2 Credits" }, + {0x10, 0x01, 0x07, 0x06, "2 Coins 1 Credit" }, + {0x10, 0x01, 0x07, 0x01, "3 Coins 2 Credits" }, + {0x10, 0x01, 0x07, 0x02, "2 Coins 1 Credits" }, + {0x10, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x10, 0x01, 0x07, 0x03, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x10, 0x00, "Off" }, + {0x10, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4 , "Mode" }, + {0x10, 0x01, 0xc0, 0xc0, "Normal Game" }, + {0x10, 0x01, 0xc0, 0x80, "Free Play" }, + {0x10, 0x01, 0xc0, 0x40, "Test Mode" }, + {0x10, 0x01, 0xc0, 0x00, "Endless Game" }, +}; + +STDDIPINFO(Wboyu) + +static struct BurnDIPInfo WbdeluxeDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0x7c, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x0f) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x10, 0x01, 0x01, 0x00, "Upright" }, + {0x10, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x02, 0x02, "Off" }, + {0x10, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x0c, 0x0c, "3" }, + {0x10, 0x01, 0x0c, 0x08, "4" }, + {0x10, 0x01, 0x0c, 0x04, "5" }, + {0x10, 0x01, 0x0c, 0x00, "Freeplay" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x10, 0x10, "30k 100k 170k 240k" }, + {0x10, 0x01, 0x10, 0x00, "30k 120k 210k 300k" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x20, 0x00, "Off" }, + {0x10, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x10, 0x01, 0x40, 0x40, "Easy" }, + {0x10, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Energy Consumption" }, + {0x10, 0x01, 0x80, 0x00, "Slow" }, + {0x10, 0x01, 0x80, 0x80, "Fast" }, +}; + +STDDIPINFO(Wbdeluxe) + +static struct BurnDIPInfo WmatchDIPList[]= +{ + // Default Values + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM1_COINAGE(0x19) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x1a, 0x01, 0x01, 0x00, "Upright" }, + {0x1a, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1a, 0x01, 0x02, 0x02, "Off" }, + {0x1a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x1a, 0x01, 0x0c, 0x0c, "Normal" }, + {0x1a, 0x01, 0x0c, 0x08, "Fast" }, + {0x1a, 0x01, 0x0c, 0x04, "Faster" }, + {0x1a, 0x01, 0x0c, 0x00, "Fastest" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x1a, 0x01, 0x10, 0x10, "20k 50k" }, + {0x1a, 0x01, 0x10, 0x00, "30k 70k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x1a, 0x01, 0x40, 0x40, "Easy" }, + {0x1a, 0x01, 0x40, 0x00, "Hard" }, +}; + +STDDIPINFO(Wmatch) + +#undef SYSTEM1_COINAGE + +/*============================================================================================== +ROM Descriptions +===============================================================================================*/ + +static struct BurnRomInfo FourdwarrioRomDesc[] = { + { "4d.116", 0x004000, 0x546d1bc7, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "4d.109", 0x004000, 0xf1074ec3, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "4d.96", 0x004000, 0x387c1e8f, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "4d.120", 0x002000, 0x5241c009, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "4d.62", 0x002000, 0xf31b2e09, BRF_GRA }, // 4 Tiles + { "4d.61", 0x002000, 0x5430e925, BRF_GRA }, // 5 Tiles + { "4d.64", 0x002000, 0x9f442351, BRF_GRA }, // 6 Tiles + { "4d.63", 0x002000, 0x633232bd, BRF_GRA }, // 7 Tiles + { "4d.66", 0x002000, 0x52bfa2ed, BRF_GRA }, // 8 Tiles + { "4d.65", 0x002000, 0xe9ba4658, BRF_GRA }, // 9 Tiles + + { "4d.117", 0x004000, 0x436e4141, BRF_GRA }, // 10 Sprites + { "4d.04", 0x004000, 0x8b7cecef, BRF_GRA }, // 11 Sprites + { "4d.110", 0x004000, 0x6ec5990a, BRF_GRA }, // 12 Sprites + { "4d.05", 0x004000, 0xf31a1e6a, BRF_GRA }, // 13 Sprites + + { "pr5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Fourdwarrio) +STD_ROM_FN(Fourdwarrio) + +static struct BurnRomInfo BlockgalRomDesc[] = { + { "bg.116", 0x004000, 0xa99b231a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bg.109", 0x004000, 0xa6b573d5, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "bg.120", 0x002000, 0xd848faff, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + + { "bg.62", 0x002000, 0x7e3ea4eb, BRF_GRA }, // 3 Tiles + { "bg.61", 0x002000, 0x4dd3d39d, BRF_GRA }, // 4 Tiles + { "bg.64", 0x002000, 0x17368663, BRF_GRA }, // 5 Tiles + { "bg.63", 0x002000, 0x0c8bc404, BRF_GRA }, // 6 Tiles + { "bg.66", 0x002000, 0x2b7dc4fa, BRF_GRA }, // 7 Tiles + { "bg.65", 0x002000, 0xed121306, BRF_GRA }, // 8 Tiles + + { "bg.117", 0x004000, 0xe99cc920, BRF_GRA }, // 9 Sprites + { "bg.04", 0x004000, 0x213057f8, BRF_GRA }, // 10 Sprites + { "bg.110", 0x004000, 0x064c812c, BRF_GRA }, // 11 Sprites + { "bg.05", 0x004000, 0x02e0b040, BRF_GRA }, // 12 Sprites + + { "pr5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 13 Timing PROM + + { "317-0029.key", 0x002000, 0x350d7f93, BRF_ESS | BRF_PRG }, // 14 MC8123 Key +}; + +STD_ROM_PICK(Blockgal) +STD_ROM_FN(Blockgal) + +static struct BurnRomInfo BrainRomDesc[] = { + { "brain.1", 0x008000, 0x2d2aec31, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "brain.2", 0x008000, 0x810a8ab5, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "brain.3", 0x008000, 0x9a225634, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "brain.120", 0x008000, 0xc7e50278, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "brain.62", 0x004000, 0x7dce2302, BRF_GRA }, // 4 Tiles + { "brain.64", 0x004000, 0x7ce03fd3, BRF_GRA }, // 5 Tiles + { "brain.66", 0x004000, 0xea54323f, BRF_GRA }, // 6 Tiles + + { "brain.117", 0x008000, 0x92ff71a4, BRF_GRA }, // 7 Sprites + { "brain.110", 0x008000, 0xa1b847ec, BRF_GRA }, // 8 Sprites + { "brain.4", 0x008000, 0xfd2ea53b, BRF_GRA }, // 9 Sprites + + { "bprom.3", 0x000100, 0x8eee0f72, BRF_OPT }, // 10 Red PROM + { "bprom.2", 0x000100, 0x3e7babd7, BRF_OPT }, // 11 Green PROM + { "bprom.1", 0x000100, 0x371c44a6, BRF_OPT }, // 12 Blue PROM + { "pr5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 13 Timing PROM +}; + +STD_ROM_PICK(Brain) +STD_ROM_FN(Brain) + +static struct BurnRomInfo BullfgtRomDesc[] = { + { "epr-.129", 0x002000, 0x29f19156, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-.130", 0x002000, 0xe37d2b95, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-.131", 0x002000, 0xeaf5773d, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-.132", 0x002000, 0x72c3c712, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-.133", 0x002000, 0x7d9fa4cd, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-.134", 0x002000, 0x061f2797, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-6077.120", 0x002000, 0x02a37602, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-.82", 0x002000, 0xb71c349f, BRF_GRA }, // 7 Tiles + { "epr-.65", 0x002000, 0x86deafa8, BRF_GRA }, // 8 Tiles + { "epr-6087.81", 0x002000, 0x2677742c, BRF_GRA }, // 9 Tiles + { "epr-.64", 0x002000, 0x6f0a62be, BRF_GRA }, // 10 Tiles + { "epr-6085.80", 0x002000, 0x9c3ddc62, BRF_GRA }, // 11 Tiles + { "epr-.63", 0x002000, 0xc0fce57c, BRF_GRA }, // 12 Tiles + + { "epr-6069.86", 0x004000, 0xfe691e41, BRF_GRA }, // 13 Sprites + { "epr-6070.93", 0x004000, 0x34f080df, BRF_GRA }, // 14 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Bullfgt) +STD_ROM_FN(Bullfgt) + +static struct BurnRomInfo ThetogyuRomDesc[] = { + { "epr-6071.116", 0x004000, 0x96b57df9, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6072.109", 0x004000, 0xf7baadd0, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6073.96", 0x004000, 0x721af166, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6077.120", 0x002000, 0x02a37602, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-6089.62", 0x002000, 0xa183e5ff, BRF_GRA }, // 7 Tiles + { "epr-6088.61", 0x002000, 0xb919b4a6, BRF_GRA }, // 8 Tiles + { "epr-6087.64", 0x002000, 0x2677742c, BRF_GRA }, // 9 Tiles + { "epr-6086.63", 0x002000, 0x76b5a084, BRF_GRA }, // 10 Tiles + { "epr-6085.66", 0x002000, 0x9c3ddc62, BRF_GRA }, // 11 Tiles + { "epr-6084.65", 0x002000, 0x90e1fa5f, BRF_GRA }, // 12 Tiles + + { "epr-6069.117", 0x004000, 0xfe691e41, BRF_GRA }, // 13 Sprites + { "epr-6070.110", 0x004000, 0x34f080df, BRF_GRA }, // 14 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Thetogyu) +STD_ROM_FN(Thetogyu) + +static struct BurnRomInfo FlickyRomDesc[] = { + { "epr5978a.116", 0x004000, 0x296f1492, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr5979a.109", 0x004000, 0x64b03ef9, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "epr-5869.120", 0x002000, 0x6d220d4e, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + + { "epr-5868.62", 0x002000, 0x7402256b, BRF_GRA }, // 3 Tiles + { "epr-5867.61", 0x002000, 0x2f5ce930, BRF_GRA }, // 4 Tiles + { "epr-5866.64", 0x002000, 0x967f1d9a, BRF_GRA }, // 5 Tiles + { "epr-5865.63", 0x002000, 0x03d9a34c, BRF_GRA }, // 6 Tiles + { "epr-5864.66", 0x002000, 0xe659f358, BRF_GRA }, // 7 Tiles + { "epr-5863.65", 0x002000, 0xa496ca15, BRF_GRA }, // 8 Tiles + + { "epr-5855.117", 0x004000, 0xb5f894a1, BRF_GRA }, // 9 Sprites + { "epr-5856.110", 0x004000, 0x266af78f, BRF_GRA }, // 10 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 11 Timing PROM +}; + +STD_ROM_PICK(Flicky) +STD_ROM_FN(Flicky) + +static struct BurnRomInfo Flickys1RomDesc[] = { + { "ic129", 0x002000, 0x7011275c, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic130", 0x002000, 0xe7ed012d, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "ic131", 0x002000, 0xc5e98cd1, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "ic132", 0x002000, 0x0e5122c2, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + + { "epr-5869.120", 0x002000, 0x6d220d4e, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "epr-5868.62", 0x002000, 0x7402256b, BRF_GRA }, // 5 Tiles + { "epr-5867.61", 0x002000, 0x2f5ce930, BRF_GRA }, // 6 Tiles + { "epr-5866.64", 0x002000, 0x967f1d9a, BRF_GRA }, // 7 Tiles + { "epr-5865.63", 0x002000, 0x03d9a34c, BRF_GRA }, // 8 Tiles + { "epr-5864.66", 0x002000, 0xe659f358, BRF_GRA }, // 9 Tiles + { "epr-5863.65", 0x002000, 0xa496ca15, BRF_GRA }, // 10 Tiles + + { "epr-5855.117", 0x004000, 0xb5f894a1, BRF_GRA }, // 11 Sprites + { "epr-5856.110", 0x004000, 0x266af78f, BRF_GRA }, // 12 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 13 Timing PROM +}; + +STD_ROM_PICK(Flickys1) +STD_ROM_FN(Flickys1) + +static struct BurnRomInfo Flickys2RomDesc[] = { + { "epr-6621.bin", 0x004000, 0xb21ff546, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6622.bin", 0x004000, 0x133a8bf1, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "epr-5869.120", 0x002000, 0x6d220d4e, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + + { "epr-5868.62", 0x002000, 0x7402256b, BRF_GRA }, // 3 Tiles + { "epr-5867.61", 0x002000, 0x2f5ce930, BRF_GRA }, // 4 Tiles + { "epr-5866.64", 0x002000, 0x967f1d9a, BRF_GRA }, // 5 Tiles + { "epr-5865.63", 0x002000, 0x03d9a34c, BRF_GRA }, // 6 Tiles + { "epr-5864.66", 0x002000, 0xe659f358, BRF_GRA }, // 7 Tiles + { "epr-5863.65", 0x002000, 0xa496ca15, BRF_GRA }, // 8 Tiles + + { "epr-5855.117", 0x004000, 0xb5f894a1, BRF_GRA }, // 9 Sprites + { "epr-5856.110", 0x004000, 0x266af78f, BRF_GRA }, // 10 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 11 Timing PROM +}; + +STD_ROM_PICK(Flickys2) +STD_ROM_FN(Flickys2) + +static struct BurnRomInfo FlickyoRomDesc[] = { + { "epr-5857.bin", 0x002000, 0xa65ac88e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr5858a.bin", 0x002000, 0x18b412f4, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5859.bin", 0x002000, 0xa5558d7e, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5860.bin", 0x002000, 0x1b35fef1, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + + { "epr-5869.120", 0x002000, 0x6d220d4e, BRF_ESS | BRF_PRG }, // 4 Z80 #2 Program Code + + { "epr-5868.62", 0x002000, 0x7402256b, BRF_GRA }, // 5 Tiles + { "epr-5867.61", 0x002000, 0x2f5ce930, BRF_GRA }, // 6 Tiles + { "epr-5866.64", 0x002000, 0x967f1d9a, BRF_GRA }, // 7 Tiles + { "epr-5865.63", 0x002000, 0x03d9a34c, BRF_GRA }, // 8 Tiles + { "epr-5864.66", 0x002000, 0xe659f358, BRF_GRA }, // 9 Tiles + { "epr-5863.65", 0x002000, 0xa496ca15, BRF_GRA }, // 10 Tiles + + { "epr-5855.117", 0x004000, 0xb5f894a1, BRF_GRA }, // 11 Sprites + { "epr-5856.110", 0x004000, 0x266af78f, BRF_GRA }, // 12 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 13 Timing PROM +}; + +STD_ROM_PICK(Flickyo) +STD_ROM_FN(Flickyo) + +static struct BurnRomInfo GardiaRomDesc[] = { + { "epr10255.1", 0x008000, 0x89282a6b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr10254.2", 0x008000, 0x2826b6d8, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr10253.3", 0x008000, 0x7911260f, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr10243.120", 0x004000, 0x87220660, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr10249.61", 0x004000, 0x4e0ad0f2, BRF_GRA }, // 4 Tiles + { "epr10248.64", 0x004000, 0x3515d124, BRF_GRA }, // 5 Tiles + { "epr10247.66", 0x004000, 0x541e1555, BRF_GRA }, // 6 Tiles + + { "epr10234.117", 0x008000, 0x8a6aed33, BRF_GRA }, // 7 Sprites + { "epr10233.110", 0x008000, 0xc52784d3, BRF_GRA }, // 8 Sprites + { "epr10236.04", 0x008000, 0xb35ab227, BRF_GRA }, // 9 Sprites + { "epr10235.5", 0x008000, 0x006a3151, BRF_GRA }, // 10 Sprites + + { "bprom.3", 0x000100, 0x8eee0f72, BRF_OPT }, // 11 Red PROM + { "bprom.2", 0x000100, 0x3e7babd7, BRF_OPT }, // 12 Green PROM + { "bprom.1", 0x000100, 0x371c44a6, BRF_OPT }, // 13 Blue PROM + { "pr5317.4", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Gardia) +STD_ROM_FN(Gardia) + +static struct BurnRomInfo GardiabRomDesc[] = { + { "gardiabl.5", 0x008000, 0x207f9cbb, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "gardiabl.6", 0x008000, 0xb2ed05dc, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "gardiabl.7", 0x008000, 0x0a490588, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr10243.120", 0x004000, 0x87220660, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "gardiabl.8", 0x004000, 0x367c9a17, BRF_GRA }, // 4 Tiles + { "gardiabl.9", 0x004000, 0x1540fd30, BRF_GRA }, // 5 Tiles + { "gardiabl.10", 0x004000, 0xe5c9af10, BRF_GRA }, // 6 Tiles + + { "epr10234.117", 0x008000, 0x8a6aed33, BRF_GRA }, // 7 Sprites + { "epr10233.110", 0x008000, 0xc52784d3, BRF_GRA }, // 8 Sprites + { "epr10236.04", 0x008000, 0xb35ab227, BRF_GRA }, // 9 Sprites + { "epr10235.5", 0x008000, 0x006a3151, BRF_GRA }, // 10 Sprites + + { "bprom.3", 0x000100, 0x8eee0f72, BRF_OPT }, // 11 Red PROM + { "bprom.2", 0x000100, 0x3e7babd7, BRF_OPT }, // 12 Green PROM + { "bprom.1", 0x000100, 0x371c44a6, BRF_OPT }, // 13 Blue PROM + { "pr5317.4", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Gardiab) +STD_ROM_FN(Gardiab) + +static struct BurnRomInfo ImsorryRomDesc[] = { + { "epr-6676.116", 0x004000, 0xeb087d7f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6677.109", 0x004000, 0xbd244bee, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6678.96", 0x004000, 0x2e16b9fd, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6656.120", 0x002000, 0x25e3d685, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6684.62", 0x002000, 0x2c8df377, BRF_GRA }, // 4 Tiles + { "epr-6683.61", 0x002000, 0x89431c48, BRF_GRA }, // 5 Tiles + { "epr-6682.64", 0x002000, 0x256a9246, BRF_GRA }, // 6 Tiles + { "epr-6681.63", 0x002000, 0x6974d189, BRF_GRA }, // 7 Tiles + { "epr-6680.66", 0x002000, 0x10a629d6, BRF_GRA }, // 8 Tiles + { "epr-6674.65", 0x002000, 0x143d883c, BRF_GRA }, // 9 Tiles + + { "epr-6645.117", 0x004000, 0x1ba167ee, BRF_GRA }, // 10 Sprites + { "epr-6646.04", 0x004000, 0xedda7ad6, BRF_GRA }, // 11 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 12 Timing PROM +}; + +STD_ROM_PICK(Imsorry) +STD_ROM_FN(Imsorry) + +static struct BurnRomInfo ImsorryjRomDesc[] = { + { "epr-6647.116", 0x004000, 0xcc5d915d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6648.109", 0x004000, 0x37574d60, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6649.96", 0x004000, 0x5f59bdee, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6656.120", 0x002000, 0x25e3d685, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6655.62", 0x002000, 0xbe1f762f, BRF_GRA }, // 4 Tiles + { "epr-6654.61", 0x002000, 0xed5f7fc8, BRF_GRA }, // 5 Tiles + { "epr-6653.64", 0x002000, 0x8b4845a7, BRF_GRA }, // 6 Tiles + { "epr-6652.63", 0x002000, 0x001d68cb, BRF_GRA }, // 7 Tiles + { "epr-6651.66", 0x002000, 0x4ee9b5e6, BRF_GRA }, // 8 Tiles + { "epr-6650.65", 0x002000, 0x3fca4414, BRF_GRA }, // 9 Tiles + + { "epr-6645.117", 0x004000, 0x1ba167ee, BRF_GRA }, // 10 Sprites + { "epr-6646.04", 0x004000, 0xedda7ad6, BRF_GRA }, // 11 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 12 Timing PROM +}; + +STD_ROM_PICK(Imsorryj) +STD_ROM_FN(Imsorryj) + +static struct BurnRomInfo MrvikingRomDesc[] = { + { "epr-5873.129", 0x002000, 0x14d21624, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5874.130", 0x002000, 0x6df7de87, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5875.131", 0x002000, 0xac226100, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5876.132", 0x002000, 0xe77db1dc, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5755.133", 0x002000, 0xedd62ae1, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5756.134", 0x002000, 0x11974040, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5763.3", 0x002000, 0xd712280d, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5762.82", 0x002000, 0x4a91d08a, BRF_GRA }, // 7 Tiles + { "epr-5761.65", 0x002000, 0xf7d61b65, BRF_GRA }, // 8 Tiles + { "epr-5760.81", 0x002000, 0x95045820, BRF_GRA }, // 9 Tiles + { "epr-5759.64", 0x002000, 0x5f9bae4e, BRF_GRA }, // 10 Tiles + { "epr-5758.80", 0x002000, 0x808ee706, BRF_GRA }, // 11 Tiles + { "epr-5757.63", 0x002000, 0x480f7074, BRF_GRA }, // 12 Tiles + + { "epr-5749.86", 0x004000, 0xe24682cd, BRF_GRA }, // 13 Sprites + { "epr-5750.93", 0x004000, 0x6564d1ad, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Mrviking) +STD_ROM_FN(Mrviking) + +static struct BurnRomInfo MrvikingjRomDesc[] = { + { "epr-5751.129", 0x002000, 0xae97a4c5, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5752.130", 0x002000, 0xd48e6726, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5753.131", 0x002000, 0x28c60887, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5754.132", 0x002000, 0x1f47ed02, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5755.133", 0x002000, 0xedd62ae1, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5756.134", 0x002000, 0x11974040, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5763.3", 0x002000, 0xd712280d, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5762.82", 0x002000, 0x4a91d08a, BRF_GRA }, // 7 Tiles + { "epr-5761.65", 0x002000, 0xf7d61b65, BRF_GRA }, // 8 Tiles + { "epr-5760.81", 0x002000, 0x95045820, BRF_GRA }, // 9 Tiles + { "epr-5759.64", 0x002000, 0x5f9bae4e, BRF_GRA }, // 10 Tiles + { "epr-5758.80", 0x002000, 0x808ee706, BRF_GRA }, // 11 Tiles + { "epr-5757.63", 0x002000, 0x480f7074, BRF_GRA }, // 12 Tiles + + { "epr-5749.86", 0x004000, 0xe24682cd, BRF_GRA }, // 13 Sprites + { "epr-5750.93", 0x004000, 0x6564d1ad, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Mrvikingj) +STD_ROM_FN(Mrvikingj) + +static struct BurnRomInfo MyheroRomDesc[] = { + { "epr6963b.116", 0x004000, 0x4daf89d4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr6964a.109", 0x004000, 0xc26188e5, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6927.96", 0x004000, 0x3cbbaf64, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-69xx.120", 0x002000, 0x0039e1e9, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6966.62", 0x002000, 0x157f0401, BRF_GRA }, // 4 Tiles + { "epr-6961.61", 0x002000, 0xbe53ce47, BRF_GRA }, // 5 Tiles + { "epr-6960.64", 0x002000, 0xbd381baa, BRF_GRA }, // 6 Tiles + { "epr-6959.63", 0x002000, 0xbc04e79a, BRF_GRA }, // 7 Tiles + { "epr-6958.66", 0x002000, 0x714f2c26, BRF_GRA }, // 8 Tiles + { "epr-6957.65", 0x002000, 0x80920112, BRF_GRA }, // 9 Tiles + + { "epr-6921.117", 0x004000, 0xf19e05a1, BRF_GRA }, // 10 Sprites + { "epr-6923.04", 0x004000, 0x7988adc3, BRF_GRA }, // 11 Sprites + { "epr-6922.110", 0x004000, 0x37f77a78, BRF_GRA }, // 12 Sprites + { "epr-6924.05", 0x004000, 0x42bdc8f6, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Myhero) +STD_ROM_FN(Myhero) + +static struct BurnRomInfo SscandalRomDesc[] = { + { "epr6925b.116", 0x004000, 0xff54dcec, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr6926a.109", 0x004000, 0x5c41eea8, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6927.96", 0x004000, 0x3cbbaf64, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6934.120", 0x002000, 0xaf467223, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6933.62", 0x002000, 0xe7304036, BRF_GRA }, // 4 Tiles + { "epr-6932.61", 0x002000, 0xf5cfbfda, BRF_GRA }, // 5 Tiles + { "epr-6931.64", 0x002000, 0x599d7f87, BRF_GRA }, // 6 Tiles + { "epr-6930.63", 0x002000, 0xcb6616c2, BRF_GRA }, // 7 Tiles + { "epr-6929.66", 0x002000, 0x27a16856, BRF_GRA }, // 8 Tiles + { "epr-6928.65", 0x002000, 0xc0c9cfa4, BRF_GRA }, // 9 Tiles + + { "epr-6921.117", 0x004000, 0xf19e05a1, BRF_GRA }, // 10 Sprites + { "epr-6923.04", 0x004000, 0x7988adc3, BRF_GRA }, // 11 Sprites + { "epr-6922.110", 0x004000, 0x37f77a78, BRF_GRA }, // 12 Sprites + { "epr-6924.05", 0x004000, 0x42bdc8f6, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Sscandal) +STD_ROM_FN(Sscandal) + +static struct BurnRomInfo MyherokRomDesc[] = { + { "ry-11.rom", 0x004000, 0x6f4c8ee5, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ry-09.rom", 0x004000, 0x369302a1, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "ry-07.rom", 0x004000, 0xb8e9922e, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6934.120", 0x002000, 0xaf467223, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "ry-04.rom", 0x004000, 0xdfb75143, BRF_GRA }, // 4 Tiles + { "ry-03.rom", 0x004000, 0xcf68b4a2, BRF_GRA }, // 5 Tiles + { "ry-02.rom", 0x004000, 0xd100eaef, BRF_GRA }, // 6 Tiles + + { "epr-6921.117", 0x004000, 0xf19e05a1, BRF_GRA }, // 7 Sprites + { "epr-6923.04", 0x004000, 0x7988adc3, BRF_GRA }, // 8 Sprites + { "epr-6922.110", 0x004000, 0x37f77a78, BRF_GRA }, // 9 Sprites + { "epr-6924.05", 0x004000, 0x42bdc8f6, BRF_GRA }, // 10 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 11 Timing PROM +}; + +STD_ROM_PICK(Myherok) +STD_ROM_FN(Myherok) + +static struct BurnRomInfo NobRomDesc[] = { + { "dm08.1f", 0x008000, 0x98d602d6, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "dm10.1k", 0x008000, 0xe7c06663, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "dm09.1h", 0x008000, 0xdc4c872f, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "dm03.9h", 0x004000, 0x415adf76, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "dm01.12b", 0x008000, 0x446fbcdd, BRF_GRA }, // 4 Tiles + { "dm02.13b", 0x008000, 0xf12df039, BRF_GRA }, // 5 Tiles + { "dm00.10b", 0x008000, 0x35f396df, BRF_GRA }, // 6 Tiles + + { "dm04.5f", 0x008000, 0x2442b86d, BRF_GRA }, // 7 Sprites + { "dm06.5k", 0x008000, 0xe33743a6, BRF_GRA }, // 8 Sprites + { "dm05.5h", 0x008000, 0x7fbba01d, BRF_GRA }, // 9 Sprites + { "dm07.5l", 0x008000, 0x85e7a29f, BRF_GRA }, // 10 Sprites + + { "nobo_pr.16d", 0x000100, 0x95010ac2, BRF_OPT }, // 11 Red PROM + { "nobo_pr.15d", 0x000100, 0xc55aac0c, BRF_OPT }, // 12 Green PROM + { "dm-12.ic3", 0x000100, 0xde394cee, BRF_OPT }, // 13 Blue PROM + { "dc-11.6a", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM + + { "dm.bin", 0x001000, 0x6fde9dcb, BRF_PRG | BRF_OPT }, // 15 MCU +}; + +STD_ROM_PICK(Nob) +STD_ROM_FN(Nob) + +static struct BurnRomInfo NobbRomDesc[] = { + { "nobo-t.bin", 0x008000, 0x176fd168, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "nobo-r.bin", 0x008000, 0xd61cf3c9, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "nobo-s.bin", 0x008000, 0xb0e7697f, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "nobo-m.bin", 0x004000, 0x415adf76, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "nobo-k.bin", 0x008000, 0x446fbcdd, BRF_GRA }, // 4 Tiles + { "nobo-j.bin", 0x008000, 0xf12df039, BRF_GRA }, // 5 Tiles + { "nobo-l.bin", 0x008000, 0x35f396df, BRF_GRA }, // 6 Tiles + + { "nobo-q.bin", 0x008000, 0x2442b86d, BRF_GRA }, // 7 Sprites + { "nobo-o.bin", 0x008000, 0xe33743a6, BRF_GRA }, // 8 Sprites + { "nobo-p.bin", 0x008000, 0x7fbba01d, BRF_GRA }, // 9 Sprites + { "nobo-n.bin", 0x008000, 0x85e7a29f, BRF_GRA }, // 10 Sprites + + { "nobo_pr.16d", 0x000100, 0x95010ac2, BRF_OPT }, // 11 Red PROM + { "nobo_pr.15d", 0x000100, 0xc55aac0c, BRF_OPT }, // 12 Green PROM + { "nobo_pr.14d", 0x000100, 0xde394cee, BRF_OPT }, // 13 Blue PROM + { "nobo_pr.13a", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Nobb) +STD_ROM_FN(Nobb) + +static struct BurnRomInfo Pitfall2RomDesc[] = { + { "epr6456a.116", 0x004000, 0xbcc8406b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr6457a.109", 0x004000, 0xa016fd2a, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr6458a.96", 0x004000, 0x5c30b3e8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6462.120", 0x002000, 0x86bb9185, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr6474a.62", 0x002000, 0x9f1711b9, BRF_GRA }, // 4 Tiles + { "epr6473a.61", 0x002000, 0x8e53b8dd, BRF_GRA }, // 5 Tiles + { "epr6472a.64", 0x002000, 0xe0f34a11, BRF_GRA }, // 6 Tiles + { "epr6471a.63", 0x002000, 0xd5bc805c, BRF_GRA }, // 7 Tiles + { "epr6470a.66", 0x002000, 0x1439729f, BRF_GRA }, // 8 Tiles + { "epr6469a.65", 0x002000, 0xe4ac6921, BRF_GRA }, // 9 Tiles + + { "epr6454a.117", 0x004000, 0xa5d96780, BRF_GRA }, // 10 Sprites + { "epr-6455.05", 0x004000, 0x32ee64a1, BRF_GRA }, // 11 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 12 Timing PROM +}; + +STD_ROM_PICK(Pitfall2) +STD_ROM_FN(Pitfall2) + +static struct BurnRomInfo Pitfall2aRomDesc[] = { + { "epr-6505", 0x004000, 0xb6769739, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6506", 0x004000, 0x1ce6aec4, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr6458a.96", 0x004000, 0x5c30b3e8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6462.120", 0x002000, 0x86bb9185, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr6474a.62", 0x002000, 0x9f1711b9, BRF_GRA }, // 4 Tiles + { "epr6473a.61", 0x002000, 0x8e53b8dd, BRF_GRA }, // 5 Tiles + { "epr6472a.64", 0x002000, 0xe0f34a11, BRF_GRA }, // 6 Tiles + { "epr6471a.63", 0x002000, 0xd5bc805c, BRF_GRA }, // 7 Tiles + { "epr6470a.66", 0x002000, 0x1439729f, BRF_GRA }, // 8 Tiles + { "epr6469a.65", 0x002000, 0xe4ac6921, BRF_GRA }, // 9 Tiles + + { "epr6454a.117", 0x004000, 0xa5d96780, BRF_GRA }, // 10 Sprites + { "epr-6455.05", 0x004000, 0x32ee64a1, BRF_GRA }, // 11 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 12 Timing PROM +}; + +STD_ROM_PICK(Pitfall2a) +STD_ROM_FN(Pitfall2a) + +static struct BurnRomInfo Pitfall2uRomDesc[] = { + { "epr-6623.116", 0x004000, 0xbcb47ed6, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr6624a.109", 0x004000, 0x6e8b09c1, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6625.96", 0x004000, 0xdc5484ba, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6462.120", 0x002000, 0x86bb9185, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr6474a.62", 0x002000, 0x9f1711b9, BRF_GRA }, // 4 Tiles + { "epr6473a.61", 0x002000, 0x8e53b8dd, BRF_GRA }, // 5 Tiles + { "epr6472a.64", 0x002000, 0xe0f34a11, BRF_GRA }, // 6 Tiles + { "epr6471a.63", 0x002000, 0xd5bc805c, BRF_GRA }, // 7 Tiles + { "epr6470a.66", 0x002000, 0x1439729f, BRF_GRA }, // 8 Tiles + { "epr6469a.65", 0x002000, 0xe4ac6921, BRF_GRA }, // 9 Tiles + + { "epr6454a.117", 0x004000, 0xa5d96780, BRF_GRA }, // 10 Sprites + { "epr-6455.05", 0x004000, 0x32ee64a1, BRF_GRA }, // 11 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 12 Timing PROM +}; + +STD_ROM_PICK(Pitfall2u) +STD_ROM_FN(Pitfall2u) + +static struct BurnRomInfo RaflesiaRomDesc[] = { + { "epr-7411.116", 0x004000, 0x88a0c6c6, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7412.109", 0x004000, 0xd3b8cddf, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-7413.96", 0x004000, 0xb7e688b3, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-7420.120", 0x002000, 0x14387666, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-7419.62", 0x002000, 0xbfd5f34c, BRF_GRA }, // 4 Tiles + { "epr-7418.61", 0x002000, 0xf8cbc9b6, BRF_GRA }, // 5 Tiles + { "epr-7417.64", 0x002000, 0xe63501bc, BRF_GRA }, // 6 Tiles + { "epr-7416.63", 0x002000, 0x093e5693, BRF_GRA }, // 7 Tiles + { "epr-7415.66", 0x002000, 0x1a8d6bd6, BRF_GRA }, // 8 Tiles + { "epr-7414.65", 0x002000, 0x5d20f218, BRF_GRA }, // 9 Tiles + + { "epr-7407.117", 0x004000, 0xf09fc057, BRF_GRA }, // 10 Sprites + { "epr-7409.04", 0x004000, 0x819fedb8, BRF_GRA }, // 11 Sprites + { "epr-7408.110", 0x004000, 0x3189f33c, BRF_GRA }, // 12 Sprites + { "epr-7410.05", 0x004000, 0xced74789, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Raflesia) +STD_ROM_FN(Raflesia) + +static struct BurnRomInfo RegulusRomDesc[] = { + { "epr-5640a.129", 0x002000, 0xdafb1528, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5641a.130", 0x002000, 0x0fcc850e, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5642a.131", 0x002000, 0x4feffa17, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5643a.132", 0x002000, 0xb8ac7eb4, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5644.133", 0x002000, 0xffd05b7d, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5645a.134", 0x002000, 0x6b4bf77c, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5652.3", 0x002000, 0x74edcb98, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5651.82", 0x002000, 0xf07f3e82, BRF_GRA }, // 7 Tiles + { "epr-5650.65", 0x002000, 0x84c1baa2, BRF_GRA }, // 8 Tiles + { "epr-5649.81", 0x002000, 0x6774c895, BRF_GRA }, // 9 Tiles + { "epr-5648.64", 0x002000, 0x0c69e92a, BRF_GRA }, // 10 Tiles + { "epr-5647.80", 0x002000, 0x9330f7b5, BRF_GRA }, // 11 Tiles + { "epr-5646.63", 0x002000, 0x4dfacbbc, BRF_GRA }, // 12 Tiles + + { "epr-5638.86", 0x004000, 0x617363dd, BRF_GRA }, // 13 Sprites + { "epr-5639.93", 0x004000, 0xa4ec5131, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Regulus) +STD_ROM_FN(Regulus) + +static struct BurnRomInfo RegulusoRomDesc[] = { + { "epr-5640.129", 0x002000, 0x8324d0d4, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5641.130", 0x002000, 0x0a09f5c7, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5642.131", 0x002000, 0xff27b2f6, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5643.132", 0x002000, 0x0d867df0, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5644.133", 0x002000, 0xffd05b7d, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5645.134", 0x002000, 0x57a2b4b4, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5652.3", 0x002000, 0x74edcb98, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5651.82", 0x002000, 0xf07f3e82, BRF_GRA }, // 7 Tiles + { "epr-5650.65", 0x002000, 0x84c1baa2, BRF_GRA }, // 8 Tiles + { "epr-5649.81", 0x002000, 0x6774c895, BRF_GRA }, // 9 Tiles + { "epr-5648.64", 0x002000, 0x0c69e92a, BRF_GRA }, // 10 Tiles + { "epr-5647.80", 0x002000, 0x9330f7b5, BRF_GRA }, // 11 Tiles + { "epr-5646.63", 0x002000, 0x4dfacbbc, BRF_GRA }, // 12 Tiles + + { "epr-5638.86", 0x004000, 0x617363dd, BRF_GRA }, // 13 Sprites + { "epr-5639.93", 0x004000, 0xa4ec5131, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Reguluso) +STD_ROM_FN(Reguluso) + +static struct BurnRomInfo RegulusuRomDesc[] = { + { "epr-5950.129", 0x002000, 0x3b047b67, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5951.130", 0x002000, 0xd66453ab, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5952.131", 0x002000, 0xf3d0158a, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5953.132", 0x002000, 0xa9ad4f44, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5644.133", 0x002000, 0xffd05b7d, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5955.134", 0x002000, 0x65ddb2a3, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5652.3", 0x002000, 0x74edcb98, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5651.82", 0x002000, 0xf07f3e82, BRF_GRA }, // 7 Tiles + { "epr-5650.65", 0x002000, 0x84c1baa2, BRF_GRA }, // 8 Tiles + { "epr-5649.81", 0x002000, 0x6774c895, BRF_GRA }, // 9 Tiles + { "epr-5648.64", 0x002000, 0x0c69e92a, BRF_GRA }, // 10 Tiles + { "epr-5647.80", 0x002000, 0x9330f7b5, BRF_GRA }, // 11 Tiles + { "epr-5646.63", 0x002000, 0x4dfacbbc, BRF_GRA }, // 12 Tiles + + { "epr-5638.86", 0x004000, 0x617363dd, BRF_GRA }, // 13 Sprites + { "epr-5639.93", 0x004000, 0xa4ec5131, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Regulusu) +STD_ROM_FN(Regulusu) + +static struct BurnRomInfo SeganinjRomDesc[] = { + { "epr-.116", 0x004000, 0xa5d0c9d0, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-.109", 0x004000, 0xb9e6775c, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6552.96", 0x004000, 0xf2eeb0d8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 4 Tiles + { "epr-6592.61", 0x002000, 0x7804db86, BRF_GRA }, // 5 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 6 Tiles + { "epr-6590.63", 0x002000, 0xbf858cad, BRF_GRA }, // 7 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 8 Tiles + { "epr-6588.65", 0x002000, 0xdc931dbb, BRF_GRA }, // 9 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 10 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 11 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 12 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Seganinj) +STD_ROM_FN(Seganinj) + +static struct BurnRomInfo SeganinjuRomDesc[] = { + { "epr-7149.116", 0x004000, 0xcd9fade7, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7150.109", 0x004000, 0xc36351e2, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6552.96", 0x004000, 0xf2eeb0d8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 4 Tiles + { "epr-6592.61", 0x002000, 0x7804db86, BRF_GRA }, // 5 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 6 Tiles + { "epr-6590.63", 0x002000, 0xbf858cad, BRF_GRA }, // 7 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 8 Tiles + { "epr-6588.65", 0x002000, 0xdc931dbb, BRF_GRA }, // 9 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 10 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 11 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 12 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Seganinju) +STD_ROM_FN(Seganinju) + +static struct BurnRomInfo NinjaRomDesc[] = { + { "epr6594.bin", 0x004000, 0x3ef0e5fc, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr6595.bin", 0x004000, 0xb16f13cd, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6552.96", 0x004000, 0xf2eeb0d8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 4 Tiles + { "epr6592.bin", 0x002000, 0x88d0c7a1, BRF_GRA }, // 5 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 6 Tiles + { "epr6590.bin", 0x002000, 0x956e3b61, BRF_GRA }, // 7 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 8 Tiles + { "epr6588.bin", 0x002000, 0x023a14a3, BRF_GRA }, // 9 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 10 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 11 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 12 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Ninja) +STD_ROM_FN(Ninja) + +static struct BurnRomInfo NprincesRomDesc[] = { + { "epr-6612.129", 0x002000, 0x1b30976f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6613.130", 0x002000, 0x18281f27, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6614.131", 0x002000, 0x69fc3d73, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-6615.132", 0x002000, 0x1d0374c8, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-6577.133", 0x002000, 0x73616e03, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-6617.134", 0x002000, 0x20b6f895, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 7 Tiles + { "epr-6557.61", 0x002000, 0x6eb131d0, BRF_GRA }, // 8 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 9 Tiles + { "epr-6555.63", 0x002000, 0x7f669aac, BRF_GRA }, // 10 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 11 Tiles + { "epr-6553.65", 0x002000, 0xeb82a8fe, BRF_GRA }, // 12 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 13 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 14 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 15 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 16 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 17 Timing PROM +}; + +STD_ROM_PICK(Nprinces) +STD_ROM_FN(Nprinces) + +static struct BurnRomInfo NprincesoRomDesc[] = { + { "epr-6550.116", 0x004000, 0x5f6d59f1, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6551.109", 0x004000, 0x1af133b2, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6552.96", 0x004000, 0xf2eeb0d8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 4 Tiles + { "epr-6557.61", 0x002000, 0x6eb131d0, BRF_GRA }, // 5 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 6 Tiles + { "epr-6555.63", 0x002000, 0x7f669aac, BRF_GRA }, // 7 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 8 Tiles + { "epr-6553.65", 0x002000, 0xeb82a8fe, BRF_GRA }, // 9 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 10 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 11 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 12 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Nprinceso) +STD_ROM_FN(Nprinceso) + +static struct BurnRomInfo NprincesuRomDesc[] = { + { "epr-6573.129", 0x002000, 0xd2919c7d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6574.130", 0x002000, 0x5a132833, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6575.131", 0x002000, 0xa94b0bd4, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-6576.132", 0x002000, 0x27d3bbdb, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-6577.133", 0x002000, 0x73616e03, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-6578.134", 0x002000, 0xab68499f, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 7 Tiles + { "epr-6557.61", 0x002000, 0x6eb131d0, BRF_GRA }, // 8 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 9 Tiles + { "epr-6555.63", 0x002000, 0x7f669aac, BRF_GRA }, // 10 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 11 Tiles + { "epr-6553.65", 0x002000, 0xeb82a8fe, BRF_GRA }, // 12 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 13 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 14 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 15 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 16 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 17 Timing PROM +}; + +STD_ROM_PICK(Nprincesu) +STD_ROM_FN(Nprincesu) + +static struct BurnRomInfo NprincesbRomDesc[] = { + { "nprinces.001", 0x004000, 0xe0de073c, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "nprinces.002", 0x004000, 0x27219c7f, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6552.96", 0x004000, 0xf2eeb0d8, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6559.120", 0x002000, 0x5a1570ee, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6558.62", 0x002000, 0x2af9eaeb, BRF_GRA }, // 4 Tiles + { "epr-6557.61", 0x002000, 0x6eb131d0, BRF_GRA }, // 5 Tiles + { "epr-6556.64", 0x002000, 0x79fd26f7, BRF_GRA }, // 6 Tiles + { "epr-6555.63", 0x002000, 0x7f669aac, BRF_GRA }, // 7 Tiles + { "epr-6554.66", 0x002000, 0x5ac9d205, BRF_GRA }, // 8 Tiles + { "epr-6553.65", 0x002000, 0xeb82a8fe, BRF_GRA }, // 9 Tiles + + { "epr-6546.117", 0x004000, 0xa4785692, BRF_GRA }, // 10 Sprites + { "epr-6548.04", 0x004000, 0xbdf278c1, BRF_GRA }, // 11 Sprites + { "epr-6547.110", 0x004000, 0x34451b08, BRF_GRA }, // 12 Sprites + { "epr-6549.05", 0x004000, 0xd2057668, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM + { "nprinces.129", 0x000100, 0xae765f62, BRF_OPT }, // 15 Decryption Table + { "nprinces.123", 0x000020, 0xed5146e9, BRF_OPT }, // 15 Decryption Table +}; + +STD_ROM_PICK(Nprincesb) +STD_ROM_FN(Nprincesb) + +static struct BurnRomInfo SpatterRomDesc[] = { + { "epr-6392.116", 0x004000, 0x329b4506, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6393.109", 0x004000, 0x3b56e25f, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6394.96", 0x004000, 0x647c1301, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6316.120", 0x002000, 0x1df95511, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6328.62", 0x002000, 0xa2bf2832, BRF_GRA }, // 4 Tiles + { "epr-6397.61", 0x002000, 0xc60d4471, BRF_GRA }, // 5 Tiles + { "epr-6326.64", 0x002000, 0x269fbb4c, BRF_GRA }, // 6 Tiles + { "epr-6396.63", 0x002000, 0xc15ccf3b, BRF_GRA }, // 7 Tiles + { "epr-6324.66", 0x002000, 0x8ab3b563, BRF_GRA }, // 8 Tiles + { "epr-6395.65", 0x002000, 0x3f083065, BRF_GRA }, // 9 Tiles + + { "epr-6306.04", 0x004000, 0xe871e132, BRF_GRA }, // 10 Sprites + { "epr-6308.117", 0x004000, 0x99c2d90e, BRF_GRA }, // 11 Sprites + { "epr-6307.05", 0x004000, 0x0a5ad543, BRF_GRA }, // 12 Sprites + { "epr-6309.110", 0x004000, 0x7423ad98, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Spatter) +STD_ROM_FN(Spatter) + +static struct BurnRomInfo SsanchanRomDesc[] = { + { "epr-6310.116", 0x004000, 0x26b43701, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6311.109", 0x004000, 0xcb2bc620, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6312.96", 0x004000, 0x71b15b47, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6316.120", 0x002000, 0x1df95511, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6328.62", 0x002000, 0xa2bf2832, BRF_GRA }, // 4 Tiles + { "epr-6327.61", 0x002000, 0x53298109, BRF_GRA }, // 5 Tiles + { "epr-6326.64", 0x002000, 0x269fbb4c, BRF_GRA }, // 6 Tiles + { "epr-6325.63", 0x002000, 0xbf038745, BRF_GRA }, // 7 Tiles + { "epr-6324.66", 0x002000, 0x8ab3b563, BRF_GRA }, // 8 Tiles + { "epr-6323.65", 0x002000, 0x0394673c, BRF_GRA }, // 9 Tiles + + { "epr-6306.04", 0x004000, 0xe871e132, BRF_GRA }, // 10 Sprites + { "epr-6308.117", 0x004000, 0x99c2d90e, BRF_GRA }, // 11 Sprites + { "epr-6307.05", 0x004000, 0x0a5ad543, BRF_GRA }, // 12 Sprites + { "epr-6309.110", 0x004000, 0x7423ad98, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Ssanchan) +STD_ROM_FN(Ssanchan) + +static struct BurnRomInfo StarjackRomDesc[] = { + { "epr5320b.129", 0x002000, 0x7ab72ecd, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr5321a.130", 0x002000, 0x38b99050, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr5322a.131", 0x002000, 0x103a595b, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5323.132", 0x002000, 0x46af0d58, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5324.133", 0x002000, 0x1e89efe2, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5325.134", 0x002000, 0xd6e379a1, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5332.3", 0x002000, 0x7a72ab3d, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5331.82", 0x002000, 0x251d898f, BRF_GRA }, // 7 Tiles + { "epr-5330.65", 0x002000, 0xeb048745, BRF_GRA }, // 8 Tiles + { "epr-5329.81", 0x002000, 0x3e8bcaed, BRF_GRA }, // 9 Tiles + { "epr-5328.64", 0x002000, 0x9ed7849f, BRF_GRA }, // 10 Tiles + { "epr-5327.80", 0x002000, 0x79e92cb1, BRF_GRA }, // 11 Tiles + { "epr-5326.63", 0x002000, 0xba7e2b47, BRF_GRA }, // 12 Tiles + + { "epr-5318.86", 0x004000, 0x6f2e1fd3, BRF_GRA }, // 13 Sprites + { "epr-5319.93", 0x004000, 0xebee4999, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Starjack) +STD_ROM_FN(Starjack) + +static struct BurnRomInfo StarjacksRomDesc[] = { + { "a1_ic29.129", 0x002000, 0x59a22a1f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a1_ic30.130", 0x002000, 0x7f4597dc, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "a1_ic31.131", 0x002000, 0x6074c046, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "a1_ic32.132", 0x002000, 0x1c48a3fa, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "a1_ic33.133", 0x002000, 0x7598bd51, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "a1_ic34.134", 0x002000, 0xf66fa604, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5332.3", 0x002000, 0x7a72ab3d, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5331.82", 0x002000, 0x251d898f, BRF_GRA }, // 7 Tiles + { "a1_ic65.65", 0x002000, 0x0ab1893c, BRF_GRA }, // 8 Tiles + { "epr-5329.81", 0x002000, 0x3e8bcaed, BRF_GRA }, // 9 Tiles + { "a1_ic64.64", 0x002000, 0x7f628ae6, BRF_GRA }, // 10 Tiles + { "epr-5327.80", 0x002000, 0x79e92cb1, BRF_GRA }, // 11 Tiles + { "a1_ic63.63", 0x002000, 0x5bcb253e, BRF_GRA }, // 12 Tiles + + { "a1_ic86.86", 0x004000, 0x6f2e1fd3, BRF_GRA }, // 13 Sprites + { "a1_ic93.93", 0x004000, 0x07987244, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Starjacks) +STD_ROM_FN(Starjacks) + +static struct BurnRomInfo SwatRomDesc[] = { + { "epr5807b.129", 0x002000, 0x93db9c9f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5808.130", 0x002000, 0x67116665, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5809.131", 0x002000, 0xfd792fc9, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5810.132", 0x002000, 0xdc2b279d, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5811.133", 0x002000, 0x093e3ab1, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5812.134", 0x002000, 0x5bfd692f, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5819.3", 0x002000, 0xf6afd0fd, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5818.82", 0x002000, 0xb22033d9, BRF_GRA }, // 7 Tiles + { "epr-5817.65", 0x002000, 0xfd942797, BRF_GRA }, // 8 Tiles + { "epr-5816.81", 0x002000, 0x4384376d, BRF_GRA }, // 9 Tiles + { "epr-5815.64", 0x002000, 0x16ad046c, BRF_GRA }, // 10 Tiles + { "epr-5814.80", 0x002000, 0xbe721c99, BRF_GRA }, // 11 Tiles + { "epr-5813.63", 0x002000, 0x0d42c27e, BRF_GRA }, // 12 Tiles + + { "epr-5805.86", 0x004000, 0x5a732865, BRF_GRA }, // 13 Sprites + { "epr-5806.93", 0x004000, 0x26ac258c, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Swat) +STD_ROM_FN(Swat) + +static struct BurnRomInfo TeddybbRomDesc[] = { + { "epr-6768.116", 0x004000, 0x5939817e, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6769.109", 0x004000, 0x14a98ddd, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6770.96", 0x004000, 0x67b0c7c2, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr6748x.120", 0x002000, 0xc2a1b89d, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6747.62", 0x002000, 0xa0e5aca7, BRF_GRA }, // 4 Tiles + { "epr-6746.61", 0x002000, 0xcdb77e51, BRF_GRA }, // 5 Tiles + { "epr-6745.64", 0x002000, 0x0cab75c3, BRF_GRA }, // 6 Tiles + { "epr-6744.63", 0x002000, 0x0ef8d2cd, BRF_GRA }, // 7 Tiles + { "epr-6743.66", 0x002000, 0xc33062b5, BRF_GRA }, // 8 Tiles + { "epr-6742.65", 0x002000, 0xc457e8c5, BRF_GRA }, // 9 Tiles + + { "epr-6735.117", 0x004000, 0x1be35a97, BRF_GRA }, // 10 Sprites + { "epr-6737.04", 0x004000, 0x6b53aa7a, BRF_GRA }, // 11 Sprites + { "epr-6736.110", 0x004000, 0x565c25d0, BRF_GRA }, // 12 Sprites + { "epr-6738.05", 0x004000, 0xe116285f, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Teddybb) +STD_ROM_FN(Teddybb) + +static struct BurnRomInfo TeddybboRomDesc[] = { + { "epr-6739.116", 0x004000, 0x81a37e69, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-6740.109", 0x004000, 0x715388a9, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-6741.96", 0x004000, 0xe5a74f5f, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-6748.120", 0x002000, 0x9325a1cf, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-6747.62", 0x002000, 0xa0e5aca7, BRF_GRA }, // 4 Tiles + { "epr-6746.61", 0x002000, 0xcdb77e51, BRF_GRA }, // 5 Tiles + { "epr-6745.64", 0x002000, 0x0cab75c3, BRF_GRA }, // 6 Tiles + { "epr-6744.63", 0x002000, 0x0ef8d2cd, BRF_GRA }, // 7 Tiles + { "epr-6743.66", 0x002000, 0xc33062b5, BRF_GRA }, // 8 Tiles + { "epr-6742.65", 0x002000, 0xc457e8c5, BRF_GRA }, // 9 Tiles + + { "epr-6735.117", 0x004000, 0x1be35a97, BRF_GRA }, // 10 Sprites + { "epr-6737.04", 0x004000, 0x6b53aa7a, BRF_GRA }, // 11 Sprites + { "epr-6736.110", 0x004000, 0x565c25d0, BRF_GRA }, // 12 Sprites + { "epr-6738.05", 0x004000, 0xe116285f, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Teddybbo) +STD_ROM_FN(Teddybbo) + +static struct BurnRomInfo UpndownRomDesc[] = { + { "epr5516a.129", 0x002000, 0x038c82da, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr5517a.130", 0x002000, 0x6930e1de, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5518.131", 0x002000, 0x2a370c99, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5519.132", 0x002000, 0x9d664a58, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5520.133", 0x002000, 0x208dfbdf, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5521.134", 0x002000, 0xe7b8d87a, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5535.3", 0x002000, 0xcf4e4c45, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5527.82", 0x002000, 0xb2d616f1, BRF_GRA }, // 7 Tiles + { "epr-5526.65", 0x002000, 0x8a8b33c2, BRF_GRA }, // 8 Tiles + { "epr-5525.81", 0x002000, 0xe749c5ef, BRF_GRA }, // 9 Tiles + { "epr-5524.64", 0x002000, 0x8b886952, BRF_GRA }, // 10 Tiles + { "epr-5523.80", 0x002000, 0xdede35d9, BRF_GRA }, // 11 Tiles + { "epr-5522.63", 0x002000, 0x5e6d9dff, BRF_GRA }, // 12 Tiles + + { "epr-5514.86", 0x004000, 0xfcc0a88b, BRF_GRA }, // 13 Sprites + { "epr-5515.93", 0x004000, 0x60908838, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Upndown) +STD_ROM_FN(Upndown) + +static struct BurnRomInfo UpndownuRomDesc[] = { + { "epr-5679.129", 0x002000, 0xc4f2f9c2, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-5680.130", 0x002000, 0x837f021c, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-5681.131", 0x002000, 0xe1c7ff7e, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-5682.132", 0x002000, 0x4a5edc1e, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-5520.133", 0x002000, 0x208dfbdf, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-5684.133", 0x002000, 0x32fa95da, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-5528.3", 0x002000, 0x00cd44ab, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-5527.82", 0x002000, 0xb2d616f1, BRF_GRA }, // 7 Tiles + { "epr-5526.65", 0x002000, 0x8a8b33c2, BRF_GRA }, // 8 Tiles + { "epr-5525.81", 0x002000, 0xe749c5ef, BRF_GRA }, // 9 Tiles + { "epr-5524.64", 0x002000, 0x8b886952, BRF_GRA }, // 10 Tiles + { "epr-5523.80", 0x002000, 0xdede35d9, BRF_GRA }, // 11 Tiles + { "epr-5522.63", 0x002000, 0x5e6d9dff, BRF_GRA }, // 12 Tiles + + { "epr-5514.86", 0x004000, 0xfcc0a88b, BRF_GRA }, // 13 Sprites + { "epr-5515.93", 0x004000, 0x60908838, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Upndownu) +STD_ROM_FN(Upndownu) + +static struct BurnRomInfo WboyRomDesc[] = { + { "epr-7489.116", 0x004000, 0x130f4b70, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7490.109", 0x004000, 0x9e656733, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-7491.96", 0x004000, 0x1f7d0efe, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-7498.120", 0x002000, 0x78ae1e7b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 4 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 5 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 6 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 7 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 8 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 9 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 10 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 11 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 12 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Wboy) +STD_ROM_FN(Wboy) + +static struct BurnRomInfo WboyoRomDesc[] = { + { "epr-.116", 0x004000, 0x51d27534, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-.109", 0x004000, 0xe29d1cd1, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-7491.96", 0x004000, 0x1f7d0efe, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-7498.120", 0x002000, 0x78ae1e7b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 4 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 5 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 6 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 7 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 8 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 9 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 10 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 11 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 12 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Wboyo) +STD_ROM_FN(Wboyo) + +static struct BurnRomInfo Wboy2RomDesc[] = { + { "epr-7587.129", 0x002000, 0x1bbb7354, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "epr-7588.130", 0x002000, 0x21007413, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "epr-7589.131", 0x002000, 0x44b30433, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "epr-7590.132", 0x002000, 0xbb525a0b, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-7591.133", 0x002000, 0x8379aa23, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-7592.134", 0x002000, 0xc767a5d7, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr-7498.120", 0x002000, 0x78ae1e7b, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 7 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 8 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 9 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 10 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 11 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 12 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 13 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 14 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 15 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 16 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 17 Timing PROM +}; + +STD_ROM_PICK(Wboy2) +STD_ROM_FN(Wboy2) + +static struct BurnRomInfo Wboy2uRomDesc[] = { + { "ic129_02.bin", 0x002000, 0x32c4b709, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic130_03.bin", 0x002000, 0x56463ede, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "ic131_04.bin", 0x002000, 0x775ed392, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "ic132_05.bin", 0x002000, 0x7b922708, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "epr-7591.133", 0x002000, 0x8379aa23, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "epr-7592.134", 0x002000, 0xc767a5d7, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr7498a.3", 0x002000, 0xc198205c, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 7 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 8 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 9 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 10 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 11 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 12 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 13 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 14 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 15 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 16 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 17 Timing PROM +}; + +STD_ROM_PICK(Wboy2u) +STD_ROM_FN(Wboy2u) + +static struct BurnRomInfo Wboy3RomDesc[] = { + { "wb_1", 0x004000, 0xbd6fef49, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "wb_2", 0x004000, 0x4081b624, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "wb_3", 0x004000, 0xc48a0e36, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-7498.120", 0x002000, 0x78ae1e7b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 4 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 5 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 6 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 7 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 8 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 9 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 10 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 11 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 12 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Wboy3) +STD_ROM_FN(Wboy3) + +static struct BurnRomInfo Wboy4RomDesc[] = { + { "ic2.bin", 0x008000, 0x48b2c006, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic3.bin", 0x008000, 0x466cae31, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + + { "7583.126", 0x008000, 0x99334b3c, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program Code + + { "epr7610.ic62", 0x004000, 0x1685d26a, BRF_GRA }, // 3 Tiles + { "epr7609.ic64", 0x004000, 0x87ecba53, BRF_GRA }, // 4 Tiles + { "epr7608.ic66", 0x004000, 0xe812b3ec, BRF_GRA }, // 5 Tiles + + { "7578.87", 0x008000, 0x6ff1637f, BRF_GRA }, // 6 Sprites + { "7577.86", 0x008000, 0x58b3705e, BRF_GRA }, // 7 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 8 Timing PROM +}; + +STD_ROM_PICK(Wboy4) +STD_ROM_FN(Wboy4) + +static struct BurnRomInfo WboyuRomDesc[] = { + { "ic116_89.bin", 0x004000, 0x73d8cef0, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic109_90.bin", 0x004000, 0x29546828, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "ic096_91.bin", 0x004000, 0xc7145c2a, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + + { "epr-7498.120", 0x002000, 0x78ae1e7b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 4 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 5 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 6 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 7 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 8 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 9 Tiles + + { "ic117_85.bin", 0x004000, 0x1ee96ae8, BRF_GRA }, // 10 Sprites + { "ic004_87.bin", 0x004000, 0x119735bb, BRF_GRA }, // 11 Sprites + { "ic110_86.bin", 0x004000, 0x26d0fac4, BRF_GRA }, // 12 Sprites + { "ic005_88.bin", 0x004000, 0x2602e519, BRF_GRA }, // 13 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 14 Timing PROM +}; + +STD_ROM_PICK(Wboyu) +STD_ROM_FN(Wboyu) + +static struct BurnRomInfo WbdeluxeRomDesc[] = { + { "wbd1.bin", 0x002000, 0xa1bedbd7, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "ic130_03.bin", 0x002000, 0x56463ede, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "wbd3.bin", 0x002000, 0x6fcdbd4c, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "ic132_05.bin", 0x002000, 0x7b922708, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "wbd5.bin", 0x002000, 0xf6b02902, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "wbd6.bin", 0x002000, 0x43df21fe, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "epr7498a.3", 0x002000, 0xc198205c, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "epr-7497.62", 0x002000, 0x08d609ca, BRF_GRA }, // 7 Tiles + { "epr-7496.61", 0x002000, 0x6f61fdf1, BRF_GRA }, // 8 Tiles + { "epr-7495.64", 0x002000, 0x6a0d2c2d, BRF_GRA }, // 9 Tiles + { "epr-7494.63", 0x002000, 0xa8e281c7, BRF_GRA }, // 10 Tiles + { "epr-7493.66", 0x002000, 0x89305df4, BRF_GRA }, // 11 Tiles + { "epr-7492.65", 0x002000, 0x60f806b1, BRF_GRA }, // 12 Tiles + + { "epr-7485.117", 0x004000, 0xc2891722, BRF_GRA }, // 13 Sprites + { "epr-7487.04", 0x004000, 0x2d3a421b, BRF_GRA }, // 14 Sprites + { "epr-7486.110", 0x004000, 0x8d622c50, BRF_GRA }, // 15 Sprites + { "epr-7488.05", 0x004000, 0x007c2f1b, BRF_GRA }, // 16 Sprites + + { "pr-5317.76", 0x000100, 0x648350b8, BRF_OPT }, // 17 Timing PROM +}; + +STD_ROM_PICK(Wbdeluxe) +STD_ROM_FN(Wbdeluxe) + +static struct BurnRomInfo WmatchRomDesc[] = { + { "wm.129", 0x002000, 0xb6db4442, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "wm.130", 0x002000, 0x59a0a7a0, BRF_ESS | BRF_PRG }, // 1 Z80 #1 Program Code + { "wm.131", 0x002000, 0x4cb3856a, BRF_ESS | BRF_PRG }, // 2 Z80 #1 Program Code + { "wm.132", 0x002000, 0xe2e44b29, BRF_ESS | BRF_PRG }, // 3 Z80 #1 Program Code + { "wm.133", 0x002000, 0x43a36445, BRF_ESS | BRF_PRG }, // 4 Z80 #1 Program Code + { "wm.134", 0x002000, 0x5624794c, BRF_ESS | BRF_PRG }, // 5 Z80 #1 Program Code + + { "wm.3", 0x002000, 0x50d2afb7, BRF_ESS | BRF_PRG }, // 6 Z80 #2 Program Code + + { "wm.82", 0x002000, 0x540f0bf3, BRF_GRA }, // 7 Tiles + { "wm.65", 0x002000, 0x92c1e39e, BRF_GRA }, // 8 Tiles + { "wm.81", 0x002000, 0x6a01ff2a, BRF_GRA }, // 9 Tiles + { "wm.64", 0x002000, 0xaae6449b, BRF_GRA }, // 10 Tiles + { "wm.80", 0x002000, 0xfc3f0bd4, BRF_GRA }, // 11 Tiles + { "wm.63", 0x002000, 0xc2ce9b93, BRF_GRA }, // 12 Tiles + + { "wm.86", 0x004000, 0x238ae0e5, BRF_GRA }, // 13 Sprites + { "wm.93", 0x004000, 0xa2f19170, BRF_GRA }, // 14 Sprites + + { "pr-5317.106", 0x000100, 0x648350b8, BRF_OPT }, // 15 Timing PROM +}; + +STD_ROM_PICK(Wmatch) +STD_ROM_FN(Wmatch) + +/*============================================================================================== +Decode Functions +===============================================================================================*/ + +static void sega_decode(const UINT8 convtable[32][4]) +{ + INT32 A; + + INT32 length = 0x10000; + INT32 cryptlen = 0x8000; + UINT8 *rom = System1Rom1; + UINT8 *decrypted = System1Fetch1; + + for (A = 0x0000;A < cryptlen;A++) + { + INT32 xorval = 0; + + UINT8 src = rom[A]; + + /* pick the translation table from bits 0, 4, 8 and 12 of the address */ + INT32 row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3); + + /* pick the offset in the table from bits 3 and 5 of the source data */ + INT32 col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); + /* the bottom half of the translation table is the mirror image of the top */ + if (src & 0x80) + { + col = 3 - col; + xorval = 0xa8; + } + + /* decode the opcodes */ + decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xorval); + + /* decode the data */ + rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xorval); + + if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */ + decrypted[A] = 0xee; + if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */ + rom[A] = 0xee; + } + + /* this is a kludge to catch anyone who has code that crosses the encrypted/ */ + /* decrypted boundary. ssanchan does it */ + if (length > 0x8000) + { + INT32 bytes = 0x4000; + memcpy(&decrypted[0x8000], &rom[0x8000], bytes); + } +} + +void bullfgtj_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ + { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void flicky_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...1...0 */ + { 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...1...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...1...1...0 */ + { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 }, /* ...1...0...0...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void hvymetal_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...1...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void imsorry_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...1 */ + { 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ + { 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...1...0...0...0 */ + { 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...0...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 }, /* ...1...1...0...0 */ + { 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }, /* ...1...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void mrviking_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void myheroj_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void myherok_decode(void) +{ + UINT8 *rom = System1Rom1; + + for (INT32 A = 0; A < 0xc000; A++) + rom[A] = (rom[A] & 0xfc) | ((rom[A] & 1) << 1) | ((rom[A] & 2) >> 1); + + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void nprinces_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...0...0...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...1...0...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void pitfall2_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...1...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void regulus_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ + { 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ + { 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void seganinj_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...0...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...0...1 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...1...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void spatter_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 }, /* ...0...1...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 }, /* ...1...0...0...0 */ + { 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...0 */ + { 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ + { 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void swat_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...0 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...1 */ + { 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void teddybb_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...0...0...0 */ + { 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +void wmatch_decode(void) +{ + static const UINT8 convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...1 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */ + { 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...1...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...1...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 } /* ...1...1...1...1 */ + }; + + sega_decode(convtable); +} + +static void sega_decode_2(UINT8 *pDest, UINT8 *pDestDec, const UINT8 opcode_xor[64],const INT32 opcode_swap_select[64], + const UINT8 data_xor[64],const INT32 data_swap_select[64]) +{ + INT32 A; + static const UINT8 swaptable[24][4] = + { + { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 }, + { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 }, + { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 }, + { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 }, + { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 }, + { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 }, + }; + + + UINT8 *rom = pDest; + UINT8 *decrypted = pDestDec; + + for (A = 0x0000;A < 0x8000;A++) + { + INT32 row; + UINT8 src; + const UINT8 *tbl; + + + src = rom[A]; + + /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */ + row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2) + + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5); + + /* decode the opcodes */ + tbl = swaptable[opcode_swap_select[row]]; + decrypted[A] = BITSWAP08(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row]; + + /* decode the data */ + tbl = swaptable[data_swap_select[row]]; + rom[A] = BITSWAP08(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row]; + } + + memcpy(pDestDec + 0x8000, pDest + 0x8000, 0x4000); +} + +static void astrofl_decode(void) +{ + static const UINT8 opcode_xor[64] = + { + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50, + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, + 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50, + }; + + static const UINT8 data_xor[64] = + { + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14, + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, + 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14, + }; + + static const INT32 opcode_swap_select[64] = + { + 0,0,1,1,1,2,2,3,3,4,4,4,5,5,6,6, + 6,7,7,8,8,9,9,9,10,10,11,11,11,12,12,13, + + 8,8,9,9,9,10,10,11,11,12,12,12,13,13,14,14, + 14,15,15,16,16,17,17,17,18,18,19,19,19,20,20,21, + }; + + static const INT32 data_swap_select[64] = + { + 0,0,1,1,2,2,2,3,3,4,4,5,5,5,6,6, + 7,7,7,8,8,9,9,10,10,10,11,11,12,12,12,13, + + 8,8,9,9,10,10,10,11,11,12,12,13,13,13,14,14, + 15,15,15,16,16,17,17,18,18,18,19,19,20,20,20,21, + }; + + sega_decode_2(System1Rom1, System1Fetch1, opcode_xor,opcode_swap_select,data_xor,data_swap_select); +} + +void fdwarrio_decode(void) +{ + static const UINT8 opcode_xor[64] = + { + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, + }; + + static const UINT8 data_xor[64] = + { + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, + }; + + static const INT32 opcode_swap_select[64] = + { + 4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, + 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11, + }; + + static const INT32 data_swap_select[64] = + { + 4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, + 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11, + 12, + }; + + sega_decode_2(System1Rom1, System1Fetch1, opcode_xor,opcode_swap_select,data_xor,data_swap_select); +} + +static void wboy2_decode(void) +{ + static const UINT8 opcode_xor[64] = + { + 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51, + 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50, + 0x00,0x45,0x11,0x01, + 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51, + 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50, + 0x00,0x45,0x11,0x01, + }; + + static const UINT8 data_xor[64] = + { + 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11, + 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10, + 0x55,0x05,0x41,0x14, + 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11, + 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10, + 0x55,0x05,0x41,0x14, + }; + + static const INT32 opcode_swap_select[64] = + { + 2, + 5,1,5,1,5, + 0,4,0,4,0,4, + 7,3,7,3,7,3, + 6,2,6,2,6, + 1,5,1,5,1,5, + 0,4,0, + + 10, + 13,9,13,9,13, + 8,12,8,12,8,12, + 15,11,15,11,15,11, + 14,10,14,10,14, + 9,13,9,13,9,13, + 8,12,8, + }; + + static const INT32 data_swap_select[64] = + { + 3,7,3,7,3,7, + 2,6,2,6,2, + 5,1,5,1,5,1, + 4,0,4,0,4, + 8, + 3,7,3,7,3, + 6,2,6,2, + + 11,15,11,15,11,15, + 10,14,10,14,10, + 13,9,13,9,13,9, + 12,8,12,8,12, + 16, + 11,15,11,15,11, + 14,10,14,10, + }; + + sega_decode_2(System1Rom1, System1Fetch1, opcode_xor,opcode_swap_select,data_xor,data_swap_select); +} + +void sega_decode_317(UINT8 *pDest, UINT8 *pDestDec, INT32 order, INT32 opcode_shift, INT32 data_shift) +{ + static const UINT8 xor1_317[1+64] = + { + 0x54, + 0x14,0x15,0x41,0x14,0x50,0x55,0x05,0x41,0x01,0x10,0x51,0x05,0x11,0x05,0x14,0x55, + 0x41,0x05,0x04,0x41,0x14,0x10,0x45,0x50,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00, + 0x54,0x04,0x15,0x10,0x04,0x05,0x11,0x44,0x04,0x01,0x05,0x00,0x44,0x15,0x40,0x45, + 0x10,0x15,0x51,0x50,0x00,0x15,0x51,0x44,0x15,0x04,0x44,0x44,0x50,0x10,0x04,0x04, + }; + + static const UINT8 xor2_317[2+64] = + { + 0x04, + 0x44, + 0x15,0x51,0x41,0x10,0x15,0x54,0x04,0x51,0x05,0x55,0x05,0x54,0x45,0x04,0x10,0x01, + 0x51,0x55,0x45,0x55,0x45,0x04,0x55,0x40,0x11,0x15,0x01,0x40,0x01,0x11,0x45,0x44, + 0x40,0x05,0x15,0x15,0x01,0x50,0x00,0x44,0x04,0x50,0x51,0x45,0x50,0x54,0x41,0x40, + 0x14,0x40,0x50,0x45,0x10,0x05,0x50,0x01,0x40,0x01,0x50,0x50,0x50,0x44,0x40,0x10, + }; + + static const INT32 swap1_317[1+64] = + { + 7, + 1,11,23,17,23, 0,15,19, + 20,12,10, 0,18,18, 5,20, + 13, 0,18,14, 5, 6,10,21, + 1,11, 9, 3,21, 4, 1,17, + 5, 7,16,13,19,23,20, 2, + 10,23,23,15,10,12, 0,22, + 14, 6,15,11,17,15,21, 0, + 6, 1, 1,18, 5,15,15,20, + }; + + static const INT32 swap2_317[2+64] = + { + 7, + 12, + 18, 8,21, 0,22,21,13,21, + 20,13,20,14, 6, 3, 5,20, + 8,20, 4, 8,17,22, 0, 0, + 6,17,17, 9, 0,16,13,21, + 3, 2,18, 6,11, 3, 3,18, + 18,19, 3, 0, 5, 0,11, 8, + 8, 1, 7, 2,10, 8,10, 2, + 1, 3,12,16, 0,17,10, 1, + }; + + if (order) + sega_decode_2( pDest, pDestDec, xor2_317+opcode_shift, swap2_317+opcode_shift, xor1_317+data_shift, swap1_317+data_shift ); + else + sega_decode_2( pDest, pDestDec, xor1_317+opcode_shift, swap1_317+opcode_shift, xor2_317+data_shift, swap2_317+data_shift ); +} + +static void gardia_decode() +{ + sega_decode_317( System1Rom1, System1Fetch1, 1, 1, 1 ); +} + +static void gardiab_decode() +{ + sega_decode_317( System1Rom1, System1Fetch1, 0, 1, 2 ); +} + +static void blockgal_decode() +{ + mc8123_decrypt_rom(0, 0, System1Rom1, System1Fetch1, System1MC8123Key); +} + +static void myherok_tile_decode() +{ + INT32 A; + UINT8 *rom = System1TempRom; + + /* the first ROM has data lines D0 and D6 swapped. */ + for (A = 0x0000;A < 0x4000;A++) + rom[A] = (rom[A] & 0xbe) | ((rom[A] & 0x01) << 6) | ((rom[A] & 0x40) >> 6); + + /* the second ROM has data lines D1 and D5 swapped. */ + for (A = 0x4000;A < 0x8000;A++) + rom[A] = (rom[A] & 0xdd) | ((rom[A] & 0x02) << 4) | ((rom[A] & 0x20) >> 4); + + /* the third ROM has data lines D0 and D6 swapped. */ + for (A = 0x8000;A < 0xc000;A++) + rom[A] = (rom[A] & 0xbe) | ((rom[A] & 0x01) << 6) | ((rom[A] & 0x40) >> 6); + + /* also, all three ROMs have address lines A4 and A5 swapped. */ + for (A = 0;A < 0xc000;A++) + { + INT32 A1; + UINT8 temp; + + A1 = (A & 0xffcf) | ((A & 0x0010) << 1) | ((A & 0x0020) >> 1); + if (A < A1) + { + temp = rom[A]; + rom[A] = rom[A1]; + rom[A1] = temp; + } + } +} + +/*============================================================================================== +Allocate Memory +===============================================================================================*/ + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + System1Rom1 = Next; Next += 0x020000; + System1Fetch1 = Next; Next += 0x010000; + System1Rom2 = Next; Next += 0x008000; + System1PromRed = Next; Next += 0x000100; + System1PromGreen = Next; Next += 0x000100; + System1PromBlue = Next; Next += 0x000100; + + RamStart = Next; + + System1Ram1 = Next; Next += 0x0020fd; + System1Ram2 = Next; Next += 0x000800; + System1SpriteRam = Next; Next += 0x000200; + System1PaletteRam = Next; Next += 0x000600; + System1BgRam = Next; Next += 0x000800; + System1VideoRam = Next; Next += 0x000700; + System1BgCollisionRam = Next; Next += 0x000400; + System1SprCollisionRam = Next; Next += 0x000400; + System1deRam = Next; Next += 0x000200; + System1efRam = Next; Next += 0x000100; + System1f4Ram = Next; Next += 0x000400; + System1fcRam = Next; Next += 0x000400; + SpriteOnScreenMap = Next; Next += (256 * 256); + + RamEnd = Next; + + System1Sprites = Next; Next += System1SpriteRomSize; + System1Tiles = Next; Next += (System1NumTiles * 8 * 8); + System1TilesPenUsage = (UINT32*)Next; Next += System1NumTiles * sizeof(UINT32); + System1Palette = (UINT32*)Next; Next += 0x000600 * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +/*============================================================================================== +Reset Functions +===============================================================================================*/ + +static INT32 System1DoReset() +{ + ZetOpen(0); + ZetReset(); + ZetClose(); + + ZetOpen(1); + ZetReset(); + ZetClose(); + + System1ScrollX[0] = System1ScrollX[1] = System1ScrollY = 0; + System1BgScrollX = 0; + System1BgScrollY = 0; + System1VideoMode = 0; + System1FlipScreen = 0; + System1SoundLatch = 0; + System1RomBank = 0; + NoboranbInp16Step = 0; + NoboranbInp17Step = 0; + NoboranbInp23Step = 0; + BlockgalDial1 = 0; + BlockgalDial2 = 0; + + return 0; +} + +/*============================================================================================== +Memory Handlers +===============================================================================================*/ + +static void System1BankRom() +{ + INT32 BankAddress = (System1RomBank * 0x4000) + 0x10000; + ZetMapArea(0x8000, 0xbfff, 0, System1Rom1 + BankAddress); + if (DecodeFunction) { + ZetMapArea(0x8000, 0xbfff, 2, System1Fetch1 + BankAddress, System1Rom1 + BankAddress); + } else { + ZetMapArea(0x8000, 0xbfff, 2, System1Rom1 + BankAddress); + } +} + +UINT8 __fastcall System1Z801PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - System1Input[0]; + } + + case 0x04: { + return 0xff - System1Input[1]; + } + + case 0x08: { + return 0xff - System1Input[2]; + } + + case 0x0c: { + return System1Dip[0]; + } + + case 0x0d: { + return System1Dip[1]; + } + + case 0x10: { + return System1Dip[1]; + } + + case 0x11: { + return System1Dip[0]; + } + + case 0x15: { + return System1VideoMode; + } + + case 0x19: { + return System1VideoMode; + } + } + + bprintf(PRINT_NORMAL, _T("IO Read %x\n"), a); + return 0; +} + +UINT8 __fastcall BlockgalZ801PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return BlockgalDial1; + } + + case 0x04: { + return BlockgalDial2; + } + + case 0x08: { + return 0xff - System1Input[2]; + } + + case 0x0c: { + return System1Dip[0]; + } + + case 0x0d: { + return System1Dip[1]; + } + + case 0x10: { + return System1Dip[1]; + } + + case 0x11: { + return System1Dip[0]; + } + + case 0x15: { + return System1VideoMode; + } + + case 0x19: { + return System1VideoMode; + } + } + + bprintf(PRINT_NORMAL, _T("IO Read %x\n"), a); + return 0; +} + +UINT8 __fastcall NoboranbZ801PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return 0xff - System1Input[0]; + } + + case 0x04: { + return 0xff - System1Input[1]; + } + + case 0x08: { + return 0xff - System1Input[2]; + } + + case 0x0c: { + return System1Dip[0]; + } + + case 0x0d: { + return System1Dip[1]; + } + + case 0x15: { + return System1VideoMode; + } + + case 0x16: { + return NoboranbInp16Step; + } + + case 0x1c: { + return 0x80; + } + + case 0x22: { + return NoboranbInp17Step; + } + + case 0x23: { + return NoboranbInp23Step; + } + } + + bprintf(PRINT_NORMAL, _T("IO Read %x\n"), a); + return 0; +} + +void __fastcall System1Z801PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x14: + case 0x18: { + System1SoundLatch = d; + + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + + case 0x15: + case 0x19: { + System1VideoMode = d; + System1FlipScreen = d & 0x80; + return; + } + } + + bprintf(PRINT_NORMAL, _T("IO Write %x, %x\n"), a, d); +} + +void __fastcall BrainZ801PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x14: + case 0x18: { + System1SoundLatch = d; + + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + + case 0x15: + case 0x19: { + System1VideoMode = d; + System1FlipScreen = d & 0x80; + + System1RomBank = ((d & 0x04) >> 2) + ((d & 0x40) >> 5); + System1BankRom(); + return; + } + } + + bprintf(PRINT_NORMAL, _T("IO Write %x, %x\n"), a, d); +} + +void __fastcall NoboranbZ801PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x14: + case 0x18: { + System1SoundLatch = d; + + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + + case 0x15: { + System1VideoMode = d; + System1FlipScreen = d & 0x80; + + System1RomBank = ((d & 0x04) >> 2) + ((d & 0x40) >> 5); + System1BankRom(); + return; + } + + case 0x16: { + NoboranbInp16Step = d; + return; + } + + case 0x17: { + NoboranbInp17Step = d; + return; + } + + case 0x24: { + NoboranbInp23Step = d; + return; + } + } + + bprintf(PRINT_NORMAL, _T("IO Write %x, %x\n"), a, d); +} + +void __fastcall System1Z801ProgWrite(UINT16 a, UINT8 d) +{ + if (a >= 0xf000 && a <= 0xf3ff) { System1BgCollisionRam[a - 0xf000] = 0x7e; return; } + if (a >= 0xf800 && a <= 0xfbff) { System1SprCollisionRam[a - 0xf800] = 0x7e; return; } + + switch (a) { + case 0xefbd: { + System1ScrollY = d; + break; + } + + case 0xeffc: { + System1ScrollX[0] = d; + break; + } + + case 0xeffd: { + System1ScrollX[1] = d; + break; + } + } + + if (a >= 0xef00 && a <= 0xefff) { + System1efRam[a - 0xef00] = d; + return; + } + + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +void __fastcall NoboranbZ801ProgWrite(UINT16 a, UINT8 d) +{ + if (a >= 0xc000 && a <= 0xc3ff) { System1BgCollisionRam[a - 0xc000] = 0x7e; return; } + if (a >= 0xc800 && a <= 0xcbff) { System1SprCollisionRam[a - 0xc800] = 0x7e; return; } + + switch (a) { + case 0xefbd: { + System1ScrollY = d; + break; + } + + case 0xeffc: { + System1ScrollX[0] = d; + break; + } + + case 0xeffd: { + System1ScrollX[1] = d; + break; + } + } + + if (a >= 0xef00 && a <= 0xefff) { + System1efRam[a - 0xef00] = d; + return; + } + + bprintf(PRINT_NORMAL, _T("Prog Write %x, %x\n"), a, d); +} + +UINT8 __fastcall System1Z802ProgRead(UINT16 a) +{ + switch (a) { + case 0xe000: { + return System1SoundLatch; + } + + case 0xffff: { + return System1SoundLatch; + } + } + + bprintf(PRINT_NORMAL, _T("Z80 2 Prog Read %x\n"), a); + return 0; +} + +void __fastcall System1Z802ProgWrite(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xa000: + case 0xa001: + case 0xa002: + case 0xa003: { + SN76496Write(0, d); + return; + } + + case 0xc000: + case 0xc001: + case 0xc002: + case 0xc003: { + SN76496Write(1, d); + return; + } + } + + bprintf(PRINT_NORMAL, _T("Z80 2 Prog Write %x, %x\n"), a, d); +} + +/*============================================================================================== +Driver Inits +===============================================================================================*/ + +static void CalcPenUsage() +{ + INT32 i, x, y; + UINT32 Usage; + UINT8 *dp = NULL; + + for (i = 0; i < System1NumTiles; i++) { + dp = System1Tiles + (i * 64); + Usage = 0; + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + Usage |= 1 << dp[x]; + } + + dp += 8; + } + + System1TilesPenUsage[i] = Usage; + } +} + +static INT32 TilePlaneOffsets[3] = { 0, 0x20000, 0x40000 }; +static INT32 NoboranbTilePlaneOffsets[3] = { 0, 0x40000, 0x80000 }; +static INT32 TileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TileYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +static INT32 System1Init(INT32 nZ80Rom1Num, INT32 nZ80Rom1Size, INT32 nZ80Rom2Num, INT32 nZ80Rom2Size, INT32 nTileRomNum, INT32 nTileRomSize, INT32 nSpriteRomNum, INT32 nSpriteRomSize, bool bReset) +{ + INT32 nRet = 0, nLen, i, RomOffset; + + System1NumTiles = (nTileRomNum * nTileRomSize) / 24; + System1SpriteRomSize = nSpriteRomNum * nSpriteRomSize; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + System1TempRom = (UINT8*)malloc(0x18000); + + // Load Z80 #1 Program roms + RomOffset = 0; + for (i = 0; i < nZ80Rom1Num; i++) { + nRet = BurnLoadRom(System1Rom1 + (i * nZ80Rom1Size), i + RomOffset, 1); if (nRet != 0) return 1; + } + + if (System1BankedRom) { + memcpy(System1TempRom, System1Rom1, 0x18000); + memset(System1Rom1, 0, 0x18000); + memcpy(System1Rom1 + 0x00000, System1TempRom + 0x00000, 0x8000); + memcpy(System1Rom1 + 0x10000, System1TempRom + 0x08000, 0x8000); + memcpy(System1Rom1 + 0x08000, System1TempRom + 0x08000, 0x8000); + memcpy(System1Rom1 + 0x18000, System1TempRom + 0x10000, 0x8000); + } + + if (DecodeFunction) DecodeFunction(); + + // Load Z80 #2 Program roms + RomOffset += nZ80Rom1Num; + for (i = 0; i < nZ80Rom2Num; i++) { + nRet = BurnLoadRom(System1Rom2 + (i * nZ80Rom2Size), i + RomOffset, 1); if (nRet != 0) return 1; + } + + // Load and decode tiles + memset(System1TempRom, 0, 0x18000); + RomOffset += nZ80Rom2Num; + for (i = 0; i < nTileRomNum; i++) { + nRet = BurnLoadRom(System1TempRom + (i * nTileRomSize), i + RomOffset, 1); + } + if (TileDecodeFunction) TileDecodeFunction(); + if (System1NumTiles > 0x800) { + GfxDecode(System1NumTiles, 3, 8, 8, NoboranbTilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, System1TempRom, System1Tiles); + } else { + GfxDecode(System1NumTiles, 3, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x40, System1TempRom, System1Tiles); + } + CalcPenUsage(); + if (System1TempRom) { + free(System1TempRom); + System1TempRom = NULL; + } + + // Load Sprite roms + RomOffset += nTileRomNum; + for (i = 0; i < nSpriteRomNum; i++) { + nRet = BurnLoadRom(System1Sprites + (i * nSpriteRomSize), i + RomOffset, 1); + } + + // Load Colour proms + if (System1ColourProms) { + RomOffset += nSpriteRomNum; + nRet = BurnLoadRom(System1PromRed, 0 + RomOffset, 1); + nRet = BurnLoadRom(System1PromGreen, 1 + RomOffset, 1); + nRet = BurnLoadRom(System1PromBlue, 2 + RomOffset, 1); + } + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetWriteHandler(System1Z801ProgWrite); + ZetSetInHandler(System1Z801PortRead); + ZetSetOutHandler(System1Z801PortWrite); + ZetMapArea(0x0000, 0x7fff, 0, System1Rom1); + ZetMapArea(0x8000, 0xbfff, 0, System1Rom1 + 0x8000); + if (DecodeFunction) { + ZetMapArea(0x0000, 0x7fff, 2, System1Fetch1, System1Rom1); + ZetMapArea(0x8000, 0xbfff, 2, System1Fetch1 + 0x8000, System1Rom1 + 0x8000); + } else { + ZetMapArea(0x0000, 0x7fff, 2, System1Rom1); + ZetMapArea(0x8000, 0xbfff, 2, System1Rom1 + 0x8000); + } + ZetMapArea(0xc000, 0xcfff, 0, System1Ram1); + ZetMapArea(0xc000, 0xcfff, 1, System1Ram1); + ZetMapArea(0xc000, 0xcfff, 2, System1Ram1); + ZetMapArea(0xd000, 0xd1ff, 0, System1SpriteRam); + ZetMapArea(0xd000, 0xd1ff, 1, System1SpriteRam); + ZetMapArea(0xd000, 0xd1ff, 2, System1SpriteRam); + ZetMapArea(0xd200, 0xd7ff, 0, System1Ram1 + 0x1000); + ZetMapArea(0xd200, 0xd7ff, 1, System1Ram1 + 0x1000); + ZetMapArea(0xd200, 0xd7ff, 2, System1Ram1 + 0x1000); + ZetMapArea(0xd800, 0xddff, 0, System1PaletteRam); + ZetMapArea(0xd800, 0xddff, 1, System1PaletteRam); + ZetMapArea(0xd800, 0xddff, 2, System1PaletteRam); + ZetMapArea(0xde00, 0xdfff, 0, System1deRam); + ZetMapArea(0xde00, 0xdfff, 1, System1deRam); + ZetMapArea(0xde00, 0xdfff, 2, System1deRam); + ZetMapArea(0xe000, 0xe7ff, 0, System1BgRam); + ZetMapArea(0xe000, 0xe7ff, 1, System1BgRam); + ZetMapArea(0xe000, 0xe7ff, 2, System1BgRam); + ZetMapArea(0xe800, 0xeeff, 0, System1VideoRam); + ZetMapArea(0xe800, 0xeeff, 1, System1VideoRam); + ZetMapArea(0xe800, 0xeeff, 2, System1VideoRam); + ZetMapArea(0xef00, 0xefff, 0, System1efRam); + ZetMapArea(0xef00, 0xefff, 2, System1efRam); + ZetMapArea(0xf000, 0xf3ff, 0, System1BgCollisionRam); + ZetMapArea(0xf000, 0xf3ff, 2, System1BgCollisionRam); + ZetMapArea(0xf400, 0xf7ff, 0, System1f4Ram); + ZetMapArea(0xf400, 0xf7ff, 1, System1f4Ram); + ZetMapArea(0xf400, 0xf7ff, 2, System1f4Ram); + ZetMapArea(0xf800, 0xfbff, 0, System1SprCollisionRam); + ZetMapArea(0xf800, 0xfbff, 2, System1SprCollisionRam); + ZetMapArea(0xfc00, 0xffff, 0, System1fcRam); + ZetMapArea(0xfc00, 0xffff, 1, System1fcRam); + ZetMapArea(0xfc00, 0xffff, 2, System1fcRam); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(System1Z802ProgRead); + ZetSetWriteHandler(System1Z802ProgWrite); + ZetMapArea(0x0000, 0x7fff, 0, System1Rom2); + ZetMapArea(0x0000, 0x7fff, 2, System1Rom2); + ZetMapArea(0x8000, 0x87ff, 0, System1Ram2); + ZetMapArea(0x8000, 0x87ff, 1, System1Ram2); + ZetMapArea(0x8000, 0x87ff, 2, System1Ram2); + ZetMemEnd(); + ZetClose(); + + memset(SpriteOnScreenMap, 255, 256 * 256); + + System1SpriteXOffset = 1; + + nCyclesTotal[0] = 4000000 / 60; + nCyclesTotal[1] = 4000000 / 60; + + SN76489AInit(0, 2000000, 0); + SN76489AInit(1, 4000000, 1); + + GenericTilesInit(); + + MakeInputsFunction = System1MakeInputs; + System1Draw = System1Render; + + // Reset the driver + if (bReset) System1DoReset(); + + return 0; +} + +static INT32 FourdwarrioInit() +{ + DecodeFunction = fdwarrio_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 BlockgalInit() +{ + INT32 nRet; + + System1MC8123Key = (UINT8*)malloc(0x2000); + BurnLoadRom(System1MC8123Key, 14, 1); + + DecodeFunction = blockgal_decode; + + nRet = System1Init(2, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); + if (System1MC8123Key) { + free(System1MC8123Key); + System1MC8123Key = NULL; + } + + ZetOpen(0); + ZetSetInHandler(BlockgalZ801PortRead); + ZetClose(); + MakeInputsFunction = BlockgalMakeInputs; + + return nRet; +} + +static INT32 BrainInit() +{ + INT32 nRet; + + System1ColourProms = 1; + System1BankedRom = 1; + + nRet = System1Init(3, 0x8000, 1, 0x8000, 3, 0x4000, 3, 0x8000, 0); + + ZetOpen(0); + ZetSetOutHandler(BrainZ801PortWrite); + ZetClose(); + + System1DoReset(); + + return nRet; +} + +static INT32 BullfgtInit() +{ + DecodeFunction = bullfgtj_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 ThetogyuInit() +{ + DecodeFunction = bullfgtj_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 FlickyInit() +{ + DecodeFunction = flicky_decode; + + return System1Init(2, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 Flicks1Init() +{ + DecodeFunction = flicky_decode; + + return System1Init(4, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 Flicks2Init() +{ + return System1Init(2, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 GardiaInit() +{ + INT32 nRet; + + System1ColourProms = 1; + System1BankedRom = 1; + + DecodeFunction = gardia_decode; + + nRet = System1Init(3, 0x8000, 1, 0x4000, 3, 0x4000, 4, 0x8000, 0); + + ZetOpen(0); + ZetSetOutHandler(BrainZ801PortWrite); + ZetClose(); + + System1DoReset(); + + return nRet; +} + +static INT32 GardiabInit() +{ + INT32 nRet; + + System1ColourProms = 1; + System1BankedRom = 1; + + DecodeFunction = gardiab_decode; + + nRet = System1Init(3, 0x8000, 1, 0x4000, 3, 0x4000, 4, 0x8000, 0); + + ZetOpen(0); + ZetSetOutHandler(BrainZ801PortWrite); + ZetClose(); + + System1DoReset(); + + return nRet; +} + +static INT32 ImsorryInit() +{ + DecodeFunction = imsorry_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 MrvikingInit() +{ + DecodeFunction = mrviking_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 MyheroInit() +{ + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 SscandalInit() +{ + DecodeFunction = myheroj_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 MyherokInit() +{ + DecodeFunction = myherok_decode; + TileDecodeFunction = myherok_tile_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 3, 0x4000, 4, 0x4000, 1); +} + +static INT32 NobbInit() +{ + INT32 nRet; + + System1ColourProms = 1; + System1BankedRom = 1; + + nRet = System1Init(3, 0x8000, 1, 0x4000, 3, 0x8000, 4, 0x8000, 0); + nCyclesTotal[0] = 8000000 / 60; + System1Rom2[0x02f9] = 0x28; + + ZetOpen(0); + ZetSetWriteHandler(NoboranbZ801ProgWrite); + ZetSetInHandler(NoboranbZ801PortRead); + ZetSetOutHandler(NoboranbZ801PortWrite); + ZetMemCallback(0xc000, 0xffff, 0); + ZetMemCallback(0xc000, 0xffff, 1); + ZetMemCallback(0xc000, 0xffff, 2); + ZetMapArea(0xc000, 0xc3ff, 0, System1BgCollisionRam); + ZetMapArea(0xc000, 0xc3ff, 2, System1BgCollisionRam); + ZetMapArea(0xc400, 0xc7ff, 0, System1f4Ram); + ZetMapArea(0xc400, 0xc7ff, 1, System1f4Ram); + ZetMapArea(0xc400, 0xc7ff, 2, System1f4Ram); + ZetMapArea(0xc800, 0xcbff, 0, System1SprCollisionRam); + ZetMapArea(0xc800, 0xcbff, 2, System1SprCollisionRam); + ZetMapArea(0xcc00, 0xcfff, 0, System1fcRam); + ZetMapArea(0xcc00, 0xcfff, 1, System1fcRam); + ZetMapArea(0xcc00, 0xcfff, 2, System1fcRam); + ZetMapArea(0xd000, 0xd1ff, 0, System1SpriteRam); + ZetMapArea(0xd000, 0xd1ff, 1, System1SpriteRam); + ZetMapArea(0xd000, 0xd1ff, 2, System1SpriteRam); + ZetMapArea(0xd200, 0xd7ff, 0, System1Ram1 + 0x1000); + ZetMapArea(0xd200, 0xd7ff, 1, System1Ram1 + 0x1000); + ZetMapArea(0xd200, 0xd7ff, 2, System1Ram1 + 0x1000); + ZetMapArea(0xd800, 0xddff, 0, System1PaletteRam); + ZetMapArea(0xd800, 0xddff, 1, System1PaletteRam); + ZetMapArea(0xd800, 0xddff, 2, System1PaletteRam); + ZetMapArea(0xde00, 0xdfff, 0, System1deRam); + ZetMapArea(0xde00, 0xdfff, 1, System1deRam); + ZetMapArea(0xde00, 0xdfff, 2, System1deRam); + ZetMapArea(0xe000, 0xe7ff, 0, System1BgRam); + ZetMapArea(0xe000, 0xe7ff, 1, System1BgRam); + ZetMapArea(0xe000, 0xe7ff, 2, System1BgRam); + ZetMapArea(0xe800, 0xeeff, 0, System1VideoRam); + ZetMapArea(0xe800, 0xeeff, 1, System1VideoRam); + ZetMapArea(0xe800, 0xeeff, 2, System1VideoRam); + ZetMapArea(0xef00, 0xefff, 0, System1efRam); + ZetMapArea(0xef00, 0xefff, 2, System1efRam); + ZetMapArea(0xf000, 0xffff, 0, System1Ram1); + ZetMapArea(0xf000, 0xffff, 1, System1Ram1); + ZetMapArea(0xf000, 0xffff, 2, System1Ram1); + ZetClose(); + + System1DoReset(); + + return nRet; +} + +static INT32 Pitfall2Init() +{ + INT32 nRet; + + DecodeFunction = pitfall2_decode; + + nRet = System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); + nCyclesTotal[0] = 3600000 / 60; + + return nRet; +} + +static INT32 PitfalluInit() +{ + INT32 nRet; + + nRet = System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); + nCyclesTotal[0] = 3600000 / 60; + + return nRet; +} + +static INT32 RaflesiaInit() +{ + DecodeFunction = fdwarrio_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 RegulusInit() +{ + DecodeFunction = regulus_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 RegulusuInit() +{ + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 SeganinjInit() +{ + DecodeFunction = seganinj_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 SeganinuInit() +{ + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 NprincesInit() +{ + DecodeFunction = flicky_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 NprincsoInit() +{ + DecodeFunction = nprinces_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 NprincsuInit() +{ + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 NprincsbInit() +{ + DecodeFunction = flicky_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 SpatterInit() +{ + DecodeFunction = spatter_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 StarjackInit() +{ + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 SwatInit() +{ + DecodeFunction = swat_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 TeddybbInit() +{ + DecodeFunction = teddybb_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 UpndownInit() +{ + DecodeFunction = nprinces_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 UpndownuInit() +{ + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 WboyInit() +{ + DecodeFunction = astrofl_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 WboyoInit() +{ + DecodeFunction = hvymetal_decode; + + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 Wboy2Init() +{ + DecodeFunction = wboy2_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 Wboy2uInit() +{ + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 Wboy4Init() +{ + DecodeFunction = fdwarrio_decode; + + return System1Init(2, 0x8000, 1, 0x8000, 3, 0x4000, 2, 0x8000, 1); +} + +static INT32 WboyuInit() +{ + return System1Init(3, 0x4000, 1, 0x2000, 6, 0x2000, 4, 0x4000, 1); +} + +static INT32 WmatchInit() +{ + DecodeFunction = wmatch_decode; + + return System1Init(6, 0x2000, 1, 0x2000, 6, 0x2000, 2, 0x4000, 1); +} + +static INT32 System1Exit() +{ + ZetExit(); + + SN76496Exit(); + + GenericTilesExit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + System1SoundLatch = 0; + System1ScrollX[0] = System1ScrollX[1] = System1ScrollY = 0; + System1BgScrollX = 0; + System1BgScrollY = 0; + System1VideoMode = 0; + System1FlipScreen = 0; + System1RomBank = 0; + NoboranbInp16Step = 0; + NoboranbInp17Step = 0; + NoboranbInp23Step = 0; + BlockgalDial1 = 0; + BlockgalDial2 = 0; + + System1SpriteRomSize = 0; + System1NumTiles = 0; + System1SpriteXOffset = 0; + System1ColourProms = 0; + System1BankedRom = 0; + + DecodeFunction = NULL; + TileDecodeFunction = NULL; + MakeInputsFunction = NULL; + System1Draw = NULL; + + return 0; +} + +/*============================================================================================== +Graphics Rendering +===============================================================================================*/ + +static void DrawPixel(INT32 x, INT32 y, INT32 SpriteNum, INT32 Colour) +{ + INT32 xr, yr, SpriteOnScreen, dx, dy; + + dx = x; + dy = y; + if (nScreenWidth == 240) dx -= 8; + + if (x < 0 || x > 255 || y < 0 || y > 255) return; + + if (SpriteOnScreenMap[(y * 256) + x] != 255) { + SpriteOnScreen = SpriteOnScreenMap[(y * 256) + x]; + System1SprCollisionRam[SpriteOnScreen + (32 * SpriteNum)] = 0xff; + } + + SpriteOnScreenMap[(y * 256) + x] = SpriteNum; + + if (dx >= 0 && dx < nScreenWidth && dy >= 0 && dy < nScreenHeight) { + UINT16 *pPixel = pTransDraw + (dy * nScreenWidth); + pPixel[dx] = Colour; + } + + xr = ((x - System1BgScrollX) & 0xff) / 8; + yr = ((y - System1BgScrollY) & 0xff) / 8; + + if (System1BgRam[2 * (32 * yr + xr) + 1] & 0x10) { + System1BgCollisionRam[0x20 + SpriteNum] = 0xff; + } +} + +static void DrawSprite(INT32 Num) +{ + INT32 Src, Bank, Height, sy, Row; + INT16 Skip; + UINT8 *SpriteBase; + UINT32 *SpritePalette; + + SpriteBase = System1SpriteRam + (0x10 * Num); + Src = (SpriteBase[7] << 8) | SpriteBase[6]; + Bank = 0x8000 * (((SpriteBase[3] & 0x80) >> 7) + ((SpriteBase[3] & 0x40) >> 5)); + Bank &= (System1SpriteRomSize - 1); + Skip = (SpriteBase[5] << 8) | SpriteBase[4]; + + Height = SpriteBase[1] - SpriteBase[0]; + SpritePalette = System1Palette + (0x10 * Num); + + sy = SpriteBase[0] + 1; + + for (Row = 0; Row < Height; Row++) { + INT32 x, y, Src2; + + Src = Src2 = Src + Skip; + x = ((SpriteBase[3] & 0x01) << 8) + SpriteBase[2] + System1SpriteXOffset; + y = sy + Row; + + x /= 2; + + while(1) { + INT32 Colour1, Colour2, Data; + + Data = System1Sprites[Bank + (Src2 & 0x7fff)]; + + if (Src & 0x8000) { + Src2--; + Colour1 = Data & 0x0f; + Colour2 = Data >> 4; + } else { + Src2++; + Colour1 = Data >> 4; + Colour2 = Data & 0x0f; + } + + if (Colour1 == 0x0f) break; + if (Colour1) DrawPixel(x, y, Num, Colour1 + (0x10 * Num)); + x++; + + if (Colour2 == 0x0f) break; + if (Colour2) DrawPixel(x, y, Num, Colour2 + (0x10 * Num)); + x++; + } + } +} + +static void System1DrawSprites() +{ + INT32 i, SpriteBottomY, SpriteTopY; + UINT8 *SpriteBase; + + memset(SpriteOnScreenMap, 255, 256 * 256); + + for (i = 0; i < 32; i++) { + SpriteBase = System1SpriteRam + (0x10 * i); + SpriteTopY = SpriteBase[0]; + SpriteBottomY = SpriteBase[1]; + if (SpriteBottomY && (SpriteBottomY - SpriteTopY > 0)) { + DrawSprite(i); + } + } +} + +static void System1DrawBgLayer(INT32 PriorityDraw) +{ + INT32 Offs, sx, sy; + + System1BgScrollX = ((System1ScrollX[0] >> 1) + ((System1ScrollX[1] & 1) << 7) + 14) & 0xff; + System1BgScrollY = (-System1ScrollY & 0xff); + + if (PriorityDraw == -1) { + for (Offs = 0; Offs < 0x800; Offs += 2) { + INT32 Code, Colour; + + Code = (System1BgRam[Offs + 1] << 8) | System1BgRam[Offs + 0]; + Code = ((Code >> 4) & 0x800) | (Code & 0x7ff); + Colour = ((Code >> 5) & 0x3f); + + sx = (Offs >> 1) % 32; + sy = (Offs >> 1) / 32; + + sx = 8 * sx + System1BgScrollX; + sy = 8 * sy + System1BgScrollY; + + if (nScreenWidth == 240) sx -= 8; + + Code &= (System1NumTiles - 1); + + Render8x8Tile_Clip(pTransDraw, Code, sx , sy , Colour, 3, 512 * 2, System1Tiles); + Render8x8Tile_Clip(pTransDraw, Code, sx - 256, sy , Colour, 3, 512 * 2, System1Tiles); + Render8x8Tile_Clip(pTransDraw, Code, sx , sy - 256, Colour, 3, 512 * 2, System1Tiles); + Render8x8Tile_Clip(pTransDraw, Code, sx - 256, sy - 256, Colour, 3, 512 * 2, System1Tiles); + } + } else { + PriorityDraw <<= 3; + + for (Offs = 0; Offs < 0x800; Offs += 2) { + if ((System1BgRam[Offs + 1] & 0x08) == PriorityDraw) { + INT32 Code, Colour; + + Code = (System1BgRam[Offs + 1] << 8) | System1BgRam[Offs + 0]; + Code = ((Code >> 4) & 0x800) | (Code & 0x7ff); + Colour = ((Code >> 5) & 0x3f); + + INT32 ColourOffs = 0x40; + if (Colour >= 0x10 && Colour <= 0x1f) ColourOffs += 0x10; + if (Colour >= 0x20 && Colour <= 0x2f) ColourOffs += 0x20; + if (Colour >= 0x30 && Colour <= 0x3f) ColourOffs += 0x30; + + sx = (Offs >> 1) % 32; + sy = (Offs >> 1) / 32; + + sx = 8 * sx + System1BgScrollX; + sy = 8 * sy + System1BgScrollY; + + if (nScreenWidth == 240) sx -= 8; + + Code &= (System1NumTiles - 1); + + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx , sy , Colour, 3, 0, 512 * 2, System1Tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx - 256, sy , Colour, 3, 0, 512 * 2, System1Tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx , sy - 256, Colour, 3, 0, 512 * 2, System1Tiles); + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx - 256, sy - 256, Colour, 3, 0, 512 * 2, System1Tiles); + } + } + } +} + +static void System1DrawFgLayer(INT32 PriorityDraw) +{ + INT32 Offs, sx, sy; + + PriorityDraw <<= 3; + + for (Offs = 0; Offs < 0x700; Offs += 2) { + INT32 Code, Colour; + + if ((System1VideoRam[Offs + 1] & 0x08) == PriorityDraw) { + Code = (System1VideoRam[Offs + 1] << 8) | System1VideoRam[Offs + 0]; + Code = ((Code >> 4) & 0x800) | (Code & 0x7ff); + Colour = (Code >> 5) & 0x3f; + + sx = (Offs >> 1) % 32; + sy = (Offs >> 1) / 32; + + sx *= 8; + sy *= 8; + + if (nScreenWidth == 240) sx -= 8; + + Code %= System1NumTiles; + Code &= (System1NumTiles - 1); + + if (System1TilesPenUsage[Code] & ~1) { + Render8x8Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 3, 0, 512, System1Tiles); + } + } + } +} + +static inline UINT8 pal2bit(UINT8 bits) +{ + bits &= 3; + return (bits << 6) | (bits << 4) | (bits << 2) | bits; +} + +static inline UINT8 pal3bit(UINT8 bits) +{ + bits &= 7; + return (bits << 5) | (bits << 2) | (bits >> 1); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal3bit(nColour >> 0); + g = pal3bit(nColour >> 3); + b = pal2bit(nColour >> 6); + + return BurnHighCol(r, g, b, 0); +} + +static INT32 System1CalcPalette() +{ + if (System1ColourProms) { + INT32 i; + for (i = 0; i < 0x600; i++) { + INT32 bit0, bit1, bit2, bit3, r, g, b, val; + + val = System1PromRed[System1PaletteRam[i]]; + bit0 = (val >> 0) & 0x01; + bit1 = (val >> 1) & 0x01; + bit2 = (val >> 2) & 0x01; + bit3 = (val >> 3) & 0x01; + r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + val = System1PromGreen[System1PaletteRam[i]]; + bit0 = (val >> 0) & 0x01; + bit1 = (val >> 1) & 0x01; + bit2 = (val >> 2) & 0x01; + bit3 = (val >> 3) & 0x01; + g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + val = System1PromBlue[System1PaletteRam[i]]; + bit0 = (val >> 0) & 0x01; + bit1 = (val >> 1) & 0x01; + bit2 = (val >> 2) & 0x01; + bit3 = (val >> 3) & 0x01; + b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; + + System1Palette[i] = BurnHighCol(r, g, b, 0); + } + } else { + for (INT32 i = 0; i < 0x600; i++) { + System1Palette[i] = CalcCol(System1PaletteRam[i]); + } + } + + return 0; +} + +static void System1Render() +{ + BurnTransferClear(); + System1CalcPalette(); + System1DrawBgLayer(-1); + System1DrawFgLayer(0); + System1DrawBgLayer(0); + System1DrawSprites(); + System1DrawBgLayer(1); + System1DrawFgLayer(1); + if (System1VideoMode & 0x010) BurnTransferClear(); + BurnTransferCopy(System1Palette); +} +/* +static void WbmlRender() +{ + BurnTransferClear(); + System1CalcPalette(); + System1DrawSprites(); + if (System1VideoMode & 0x010) BurnTransferClear(); + BurnTransferCopy(System1Palette); +} +*/ +/*============================================================================================== +Frame functions +===============================================================================================*/ + +INT32 System1Frame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (System1Reset) System1DoReset(); + + MakeInputsFunction(); + + nCyclesDone[0] = nCyclesDone[1] = 0; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 9) ZetRaiseIrq(0); + ZetClose(); + + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 2 || i == 4 || i == 6 || i == 8) ZetRaiseIrq(0); + ZetClose(); + + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + SN76496Update(0, pSoundBuf, nSegmentLength); + SN76496Update(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + SN76496Update(0, pSoundBuf, nSegmentLength); + SN76496Update(1, pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) System1Draw(); + + return 0; +} + +/*============================================================================================== +Scan Driver +===============================================================================================*/ + +static INT32 System1Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029675; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); // Scan Z80 + SN76496Scan(nAction, pnMin); + + // Scan critical driver variables + SCAN_VAR(nCyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(System1Dip); + SCAN_VAR(System1Input); + SCAN_VAR(System1ScrollX); + SCAN_VAR(System1ScrollY); + SCAN_VAR(System1BgScrollX); + SCAN_VAR(System1BgScrollY); + SCAN_VAR(System1VideoMode); + SCAN_VAR(System1FlipScreen); + SCAN_VAR(System1SoundLatch); + SCAN_VAR(System1RomBank); + SCAN_VAR(NoboranbInp16Step); + SCAN_VAR(NoboranbInp17Step); + SCAN_VAR(NoboranbInp23Step); + } + + if (nAction & ACB_WRITE) { + if (System1BankedRom) { + ZetOpen(0); + System1BankRom(); + ZetClose(); + } + } + + return 0; +} + +/*============================================================================================== +Driver defs +===============================================================================================*/ + +struct BurnDriver BurnDrvFourdwarrio = { + "4dwarrio", NULL, NULL, NULL, "1985", + "4-D Warriors (315-5162)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_HORSHOOT, 0, + NULL, FourdwarrioRomInfo, FourdwarrioRomName, NULL, NULL, MyheroInputInfo, FourdwarrioDIPInfo, + FourdwarrioInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBlockgal = { + "blockgal", NULL, NULL, NULL, "1987", + "Block Gal (MC-8123B, 317-0029)\0", NULL, "Sega / Vic Tokai", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_SEGA_SYSTEM1, GBF_PUZZLE, 0, + NULL, BlockgalRomInfo, BlockgalRomName, NULL, NULL, BlockgalInputInfo, BlockgalDIPInfo, + BlockgalInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvBrain = { + "brain", NULL, NULL, NULL, "1986", + "Brain\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_HORSHOOT, 0, + NULL, BrainRomInfo, BrainRomName, NULL, NULL, MyheroInputInfo, BrainDIPInfo, + BrainInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBullfgt = { + "bullfgt", NULL, NULL, NULL, "1984", + "Bullfight (315-5065)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_MISC, 0, + NULL, BullfgtRomInfo, BullfgtRomName, NULL, NULL, MyheroInputInfo, BullfgtDIPInfo, + BullfgtInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThetogyu = { + "thetogyu", "bullfgt", NULL, NULL, "1984", + "The Togyu (315-5065, Japan)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_MISC, 0, + NULL, ThetogyuRomInfo, ThetogyuRomName, NULL, NULL, MyheroInputInfo, BullfgtDIPInfo, + ThetogyuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlicky = { + "flicky", NULL, NULL, NULL, "1984", + "Flicky (128k Version, System 2, 315-5051)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, FlickyRomInfo, FlickyRomName, NULL, NULL, FlickyInputInfo, FlickyDIPInfo, + FlickyInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlickys1 = { + "flickys1", "flicky", NULL, NULL, "1984", + "Flicky (64k Version, System 1, 315-5051, set 2)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Flickys1RomInfo, Flickys1RomName, NULL, NULL, FlickyInputInfo, FlickyDIPInfo, + Flicks1Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlickys2 = { + "flickys2", "flicky", NULL, NULL, "1984", + "Flicky (128k Version, System 2, not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Flickys2RomInfo, Flickys2RomName, NULL, NULL, FlickyInputInfo, FlickyDIPInfo, + Flicks2Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFlickyo = { + "flickyo", "flicky", NULL, NULL, "1984", + "Flicky (64k Version, System 1, 315-5051, set 1)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, FlickyoRomInfo, FlickyoRomName, NULL, NULL, FlickyInputInfo, FlickyDIPInfo, + Flicks1Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGardia = { + "gardia", NULL, NULL, NULL, "1986", + "Gardia (317-0006)\0", NULL, "Sega / Coreland", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, GardiaRomInfo, GardiaRomName, NULL, NULL, MyheroInputInfo, GardiaDIPInfo, + GardiaInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvGardiab = { + "gardiab", "gardia", NULL, NULL, "1986", + "Gardia (317-0007?, bootleg)\0", NULL, "Sega / Coreland", "System 1", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, GardiabRomInfo, GardiabRomName, NULL, NULL, MyheroInputInfo, GardiaDIPInfo, + GardiabInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvImsorry = { + "imsorry", NULL, NULL, NULL, "1985", + "I'm Sorry (315-5110, US)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_MAZE, 0, + NULL, ImsorryRomInfo, ImsorryRomName, NULL, NULL, MyheroInputInfo, ImsorryDIPInfo, + ImsorryInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvImsorryj = { + "imsorryj", "imsorry", NULL, NULL, "1985", + "Gonbee no I'm Sorry (315-5110, Japan)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_MAZE, 0, + NULL, ImsorryjRomInfo, ImsorryjRomName, NULL, NULL, MyheroInputInfo, ImsorryDIPInfo, + ImsorryInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMrviking = { + "mrviking", NULL, NULL, NULL, "1984", + "Mister Viking (315-5041)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, MrvikingRomInfo, MrvikingRomName, NULL, NULL, MyheroInputInfo, MrvikingDIPInfo, + MrvikingInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvMrvikingj = { + "mrvikingj", "mrviking", NULL, NULL, "1984", + "Mister Viking (315-5041, Japan)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, MrvikingjRomInfo, MrvikingjRomName, NULL, NULL, MyheroInputInfo, MrvikngjDIPInfo, + MrvikingInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvMyhero = { + "myhero", NULL, NULL, NULL, "1985", + "My Hero (US, not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, MyheroRomInfo, MyheroRomName, NULL, NULL, MyheroInputInfo, MyheroDIPInfo, + MyheroInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSscandal = { + "sscandal", "myhero", NULL, NULL, "1985", + "Seishun Scandal (315-5132, Japan)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, SscandalRomInfo, SscandalRomName, NULL, NULL, MyheroInputInfo, MyheroDIPInfo, + SscandalInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMyherok = { + "myherok", "myhero", NULL, NULL, "1985", + "My Hero (Korea)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, MyherokRomInfo, MyherokRomName, NULL, NULL, MyheroInputInfo, MyheroDIPInfo, + MyherokInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNob = { + "nob", NULL, NULL, NULL, "1986", + "Noboranka (Japan)\0", NULL, "Data East Corporation", "System 1", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NobRomInfo, NobRomName, NULL, NULL, MyheroInputInfo, NobbDIPInfo, + NobbInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvNobb = { + "nobb", "nob", NULL, NULL, "1986", + "Noboranka (Japan, bootleg)\0", NULL, "bootleg", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NobbRomInfo, NobbRomName, NULL, NULL, MyheroInputInfo, NobbDIPInfo, + NobbInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvPitfall2 = { + "pitfall2", NULL, NULL, NULL, "1985", + "Pitfall II (315-5093)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Pitfall2RomInfo, Pitfall2RomName, NULL, NULL, MyheroInputInfo, Pitfall2DIPInfo, + Pitfall2Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPitfall2a = { + "pitfall2a", "pitfall2", NULL, NULL, "1985", + "Pitfall II (315-5093, Flicky Conversion)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Pitfall2aRomInfo, Pitfall2aRomName, NULL, NULL, MyheroInputInfo, Pitfall2DIPInfo, + Pitfall2Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPitfall2u = { + "pitfall2u", "pitfall2", NULL, NULL, "1985", + "Pitfall II (not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Pitfall2uRomInfo, Pitfall2uRomName, NULL, NULL, MyheroInputInfo, PitfalluDIPInfo, + PitfalluInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRaflesia = { + "raflesia", NULL, NULL, NULL, "1986", + "Rafflesia (315-5162)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, RaflesiaRomInfo, RaflesiaRomName, NULL, NULL, MyheroInputInfo, RaflesiaDIPInfo, + RaflesiaInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvRegulus = { + "regulus", NULL, NULL, NULL, "1983", + "Regulus (315-5033, rev. A)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, RegulusRomInfo, RegulusRomName, NULL, NULL, MyheroInputInfo, RegulusDIPInfo, + RegulusInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvReguluso = { + "reguluso", "regulus", NULL, NULL, "1983", + "Regulus (315-5033)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, RegulusoRomInfo, RegulusoRomName, NULL, NULL, MyheroInputInfo, RegulusoDIPInfo, + RegulusInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvRegulusu = { + "regulusu", "regulus", NULL, NULL, "1983", + "Regulus (not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, RegulusuRomInfo, RegulusuRomName, NULL, NULL, MyheroInputInfo, RegulusDIPInfo, + RegulusuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvSeganinj = { + "seganinj", NULL, NULL, NULL, "1985", + "Sega Ninja (315-5102)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, SeganinjRomInfo, SeganinjRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + SeganinjInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSeganinju = { + "seganinju", "seganinj", NULL, NULL, "1985", + "Sega Ninja (not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, SeganinjuRomInfo, SeganinjuRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + SeganinuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNinja = { + "ninja", "seganinj", NULL, NULL, "1985", + "Ninja (315-5102)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NinjaRomInfo, NinjaRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + SeganinjInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNprinces = { + "nprinces", "seganinj", NULL, NULL, "1985", + "Ninja Princess (315-5051, 64k Ver. bootleg?)\0", NULL, "bootleg?", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NprincesRomInfo, NprincesRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + NprincesInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNprinceso = { + "nprinceso", "seganinj", NULL, NULL, "1985", + "Ninja Princess (315-5098, 128k Ver.)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NprincesoRomInfo, NprincesoRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + NprincsoInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNprincesu = { + "nprincesu", "seganinj", NULL, NULL, "1985", + "Ninja Princess (64k Ver. not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NprincesuRomInfo, NprincesuRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + NprincsuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNprincesb = { + "nprincesb", "seganinj", NULL, NULL, "1985", + "Ninja Princess (315-5051?, 128k Ver. bootleg?)\0", NULL, "bootleg?", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, NprincesbRomInfo, NprincesbRomName, NULL, NULL, SeganinjInputInfo, SeganinjDIPInfo, + NprincsbInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSpatter = { + "spatter", NULL, NULL, NULL, "1984", + "Spatter\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_MAZE, 0, + NULL, SpatterRomInfo, SpatterRomName, NULL, NULL, MyheroInputInfo, SpatterDIPInfo, + SpatterInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 240, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsanchan = { + "ssanchan", "spatter", NULL, NULL, "1984", + "Sanrin San Chan (Japan)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_MAZE, 0, + NULL, SsanchanRomInfo, SsanchanRomName, NULL, NULL, MyheroInputInfo, SpatterDIPInfo, + SpatterInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 240, 224, 4, 3 +}; + +struct BurnDriver BurnDrvStarjack = { + "starjack", NULL, NULL, NULL, "1983", + "Star Jacker (Sega)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, StarjackRomInfo, StarjackRomName, NULL, NULL, MyheroInputInfo, StarjackDIPInfo, + StarjackInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvStarjacks = { + "starjacks", "starjack", NULL, NULL, "1983", + "Star Jacker (Stern)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_VERSHOOT, 0, + NULL, StarjacksRomInfo, StarjacksRomName, NULL, NULL, MyheroInputInfo, StarjacsDIPInfo, + StarjackInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + +struct BurnDriver BurnDrvSwat = { + "swat", NULL, NULL, NULL, "1984", + "SWAT (315-5048)\0", NULL, "Coreland / Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_MISC, 0, + NULL, SwatRomInfo, SwatRomName, NULL, NULL, MyheroInputInfo, SwatDIPInfo, + SwatInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTeddybb = { + "teddybb", NULL, NULL, NULL, "1985", + "TeddyBoy Blues (315-5115, New Ver.)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, TeddybbRomInfo, TeddybbRomName, NULL, NULL, MyheroInputInfo, TeddybbDIPInfo, + TeddybbInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTeddybbo = { + "teddybbo", "teddybb", NULL, NULL, "1985", + "TeddyBoy Blues (315-5115, Old Ver.)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, TeddybboRomInfo, TeddybboRomName, NULL, NULL, MyheroInputInfo, TeddybbDIPInfo, + TeddybbInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvUpndown = { + "upndown", NULL, NULL, NULL, "1983", + "Up'n Down (315-5030)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_MISC, 0, + NULL, UpndownRomInfo, UpndownRomName, NULL, NULL, UpndownInputInfo, UpndownDIPInfo, + UpndownInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvUpndownu = { + "upndownu", "upndown", NULL, NULL, "1983", + "Up'n Down (not encrypted)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_MISC, 0, + NULL, UpndownuRomInfo, UpndownuRomName, NULL, NULL, UpndownInputInfo, UpndownDIPInfo, + UpndownuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvWboy = { + "wboy", NULL, NULL, NULL, "1986", + "Wonder Boy (set 1, 315-5177)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, WboyRomInfo, WboyRomName, NULL, NULL, WboyInputInfo, WboyDIPInfo, + WboyInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboyo = { + "wboyo", "wboy", NULL, NULL, "1986", + "Wonder Boy (set 1, 315-5135)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, WboyoRomInfo, WboyoRomName, NULL, NULL, WboyInputInfo, WboyDIPInfo, + WboyoInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboy2 = { + "wboy2", "wboy", NULL, NULL, "1986", + "Wonder Boy (set 2, 315-5178)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Wboy2RomInfo, Wboy2RomName, NULL, NULL, WboyInputInfo, WboyDIPInfo, + Wboy2Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboy2u = { + "wboy2u", "wboy", NULL, NULL, "1986", + "Wonder Boy (set 2, not encrypted)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Wboy2uRomInfo, Wboy2uRomName, NULL, NULL, WboyInputInfo, WboyDIPInfo, + Wboy2uInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboy3 = { + "wboy3", "wboy", NULL, NULL, "1986", + "Wonder Boy (set 3, 315-5135)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Wboy3RomInfo, Wboy3RomName, NULL, NULL, WboyInputInfo, Wboy3DIPInfo, + WboyoInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboy4 = { + "wboy4", "wboy", NULL, NULL, "1986", + "Wonder Boy (set 4, 315-5162)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, Wboy4RomInfo, Wboy4RomName, NULL, NULL, WboyInputInfo, WboyDIPInfo, + Wboy4Init, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWboyu = { + "wboyu", "wboy", NULL, NULL, "1986", + "Wonder Boy (not encrypted)\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, WboyuRomInfo, WboyuRomName, NULL, NULL, WboyInputInfo, WboyuDIPInfo, + WboyuInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWbdeluxe = { + "wbdeluxe", "wboy", NULL, NULL, "1986", + "Wonder Boy Deluxe\0", NULL, "Sega (Escape License)", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM1, GBF_PLATFORM, 0, + NULL, WbdeluxeRomInfo, WbdeluxeRomName, NULL, NULL, WboyInputInfo, WbdeluxeDIPInfo, + Wboy2uInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWmatch = { + "wmatch", NULL, NULL, NULL, "1984", + "Water Match (315-5064)\0", NULL, "Sega", "System 1", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM1, GBF_SPORTSMISC, 0, + NULL, WmatchRomInfo, WmatchRomName, NULL, NULL, WmatchInputInfo, WmatchDIPInfo, + WmatchInit, System1Exit, System1Frame, NULL, System1Scan, + NULL, 0x600, 224, 240, 3, 4 +}; + + + +// hvymetal +// shtngmst and clones +// chplft and clones +// wboysys2 +// blckgalb +// tokisens +// wbml and clones +// dakkochn +// ufosensi diff --git a/src/burn/drivers/sega/d_sys16a.cpp b/src/burn/drivers/sega/d_sys16a.cpp new file mode 100644 index 00000000..086e800a --- /dev/null +++ b/src/burn/drivers/sega/d_sys16a.cpp @@ -0,0 +1,3156 @@ +#include "sys16.h" + +/*==================================================== +Input defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo System16aInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16a) + +static struct BurnInputInfo System16afire1InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16afire1) + +static struct BurnInputInfo System16afire3InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16afire3) + +static struct BurnInputInfo System16aDip3InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, System16Dip + 2 , "dip" }, +}; + +STDINPUTINFO(System16aDip3) + +static struct BurnInputInfo AceattacaInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort3 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort3 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort3 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort3 + 1, "p1 right" }, + {"P1 Dial Left" , BIT_DIGITAL , System16InputPort4 + 0, "p1 fire 14"}, + {"P1 Dial Right" , BIT_DIGITAL , System16InputPort4 + 1, "p1 fire 15"}, + {"P1 Block" , BIT_DIGITAL , System16InputPort0 + 6, "p1 fire 1" }, + {"P1 Select" , BIT_DIGITAL , System16InputPort1 + 4, "p1 fire 2" }, + {"P1 Attack Dir0" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 3" }, + {"P1 Attack Dir1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 4" }, + {"P1 Attack Dir2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 5" }, + {"P1 Attack Dir3" , BIT_DIGITAL , System16InputPort1 + 3, "p1 fire 6" }, + {"P1 Attack Dir4" , BIT_DIGITAL , System16InputPort1 + 4, "p1 fire 7" }, + {"P1 Attack Dir5" , BIT_DIGITAL , System16InputPort1 + 5, "p1 fire 8" }, + {"P1 Attack Dir6" , BIT_DIGITAL , System16InputPort1 + 6, "p1 fire 9" }, + {"P1 Attack Dir7" , BIT_DIGITAL , System16InputPort1 + 7, "p1 fire 10"}, + {"P1 Attack Pow0" , BIT_DIGITAL , System16InputPort2 + 4, "p1 fire 11"}, + {"P1 Attack Pow1" , BIT_DIGITAL , System16InputPort2 + 5, "p1 fire 12"}, + {"P1 Attack Pow2" , BIT_DIGITAL , System16InputPort2 + 6, "p1 fire 13"}, + + {"P2 Up" , BIT_DIGITAL , System16InputPort3 + 6, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort3 + 7, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort3 + 4, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort3 + 5, "p2 right" }, + {"P2 Dial Left" , BIT_DIGITAL , System16InputPort4 + 2, "p2 fire 14"}, + {"P2 Dial Right" , BIT_DIGITAL , System16InputPort4 + 3, "p2 fire 15"}, + {"P2 Block" , BIT_DIGITAL , System16InputPort0 + 7, "p2 fire 1" }, + {"P2 Select" , BIT_DIGITAL , System16InputPort5 + 4, "p2 fire 2" }, + {"P2 Attack Dir0" , BIT_DIGITAL , System16InputPort5 + 0, "p2 fire 3" }, + {"P2 Attack Dir1" , BIT_DIGITAL , System16InputPort5 + 1, "p2 fire 4" }, + {"P2 Attack Dir2" , BIT_DIGITAL , System16InputPort5 + 2, "p2 fire 5" }, + {"P2 Attack Dir3" , BIT_DIGITAL , System16InputPort5 + 3, "p2 fire 6" }, + {"P2 Attack Dir4" , BIT_DIGITAL , System16InputPort5 + 4, "p2 fire 7" }, + {"P2 Attack Dir5" , BIT_DIGITAL , System16InputPort5 + 5, "p2 fire 8" }, + {"P2 Attack Dir6" , BIT_DIGITAL , System16InputPort5 + 6, "p2 fire 9" }, + {"P2 Attack Dir7" , BIT_DIGITAL , System16InputPort5 + 7, "p2 fire 10"}, + {"P2 Attack Pow0" , BIT_DIGITAL , System16InputPort6 + 4, "p2 fire 11"}, + {"P2 Attack Pow1" , BIT_DIGITAL , System16InputPort6 + 5, "p2 fire 12"}, + {"P2 Attack Pow2" , BIT_DIGITAL , System16InputPort6 + 6, "p2 fire 13"}, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Aceattaca) + +static struct BurnInputInfo MjleagueInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort3 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort3 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort3 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort3 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 7, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , System16InputPort1 + 3, "p1 fire 5" }, + A("P1 Bat Swing" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 z-axis" ), + + {"P1 Up" , BIT_DIGITAL , System16InputPort3 + 6, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort3 + 7, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort3 + 4, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort3 + 5, "p1 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 7, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , System16InputPort2 + 3, "p2 fire 5" }, + A("P2 Bat Swing" , BIT_ANALOG_REL, &System16AnalogPort1, "p2 z-axis" ), + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Mjleague) + +static struct BurnInputInfo Passsht16aInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 6, "p3 start" }, + {"Start 4" , BIT_DIGITAL , System16InputPort0 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 1, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 0, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 6, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , System16InputPort1 + 7, "p1 fire 4" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 1, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 0, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 2, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 6, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , System16InputPort2 + 7, "p2 fire 4" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 1, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 0, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 3, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 2, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 5, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , System16InputPort3 + 6, "p3 fire 3" }, + {"P3 Fire 4" , BIT_DIGITAL , System16InputPort3 + 7, "p3 fire 4" }, + + {"P4 Up" , BIT_DIGITAL , System16InputPort4 + 1, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , System16InputPort4 + 0, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , System16InputPort4 + 3, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , System16InputPort4 + 2, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , System16InputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , System16InputPort4 + 5, "p4 fire 2" }, + {"P4 Fire 3" , BIT_DIGITAL , System16InputPort4 + 6, "p4 fire 3" }, + {"P4 Fire 4" , BIT_DIGITAL , System16InputPort4 + 7, "p4 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Passsht16a) + +static struct BurnInputInfo QuartetInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort1 + 6, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort2 + 6, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , System16InputPort3 + 6, "p4 coin" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort0 + 1, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort0 + 0, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort0 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort0 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort1 + 1, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort1 + 0, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort1 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort1 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort2 + 1, "p1 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort2 + 0, "p1 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort2 + 3, "p1 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort2 + 2, "p1 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort2 + 4, "p1 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort2 + 5, "p1 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , System16InputPort3 + 1, "p2 up" }, + {"P4 Down" , BIT_DIGITAL , System16InputPort3 + 0, "p2 down" }, + {"P4 Left" , BIT_DIGITAL , System16InputPort3 + 3, "p2 left" }, + {"P4 Right" , BIT_DIGITAL , System16InputPort3 + 2, "p2 right" }, + {"P4 Fire 1" , BIT_DIGITAL , System16InputPort3 + 4, "p2 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , System16InputPort3 + 5, "p2 fire 2" }, + + {"Service 1" , BIT_DIGITAL , System16InputPort0 + 7 , "service" }, + {"Service 2" , BIT_DIGITAL , System16InputPort1 + 7 , "service2" }, + {"Service 3" , BIT_DIGITAL , System16InputPort2 + 7 , "service3" }, + {"Service 4" , BIT_DIGITAL , System16InputPort3 + 7 , "service4" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Quartet) + +static struct BurnInputInfo SdiInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 1, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 0, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + A("Target Left/Right", BIT_ANALOG_REL, &System16AnalogPort0, "mouse x-axis" ), + A("Target Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 6, "mouse button 1"}, + + {"P2 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p2 right" }, + A("Target Left/Right", BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("Target Up/Down" , BIT_ANALOG_REL, &System16AnalogPort3, "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort0 + 7, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Sdi) + +static struct BurnInputInfo Sjryuko1InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + {"Mahjong A" , BIT_DIGITAL , System16InputPort1 + 0, "mah a" }, + {"Mahjong B" , BIT_DIGITAL , System16InputPort1 + 1, "mah b" }, + {"Mahjong C" , BIT_DIGITAL , System16InputPort1 + 2, "mah c" }, + {"Mahjong D" , BIT_DIGITAL , System16InputPort1 + 3, "mah d" }, + {"Mahjong E" , BIT_DIGITAL , System16InputPort2 + 0, "mah e" }, + {"Mahjong F" , BIT_DIGITAL , System16InputPort2 + 1, "mah f" }, + {"Mahjong G" , BIT_DIGITAL , System16InputPort2 + 2, "mah g" }, + {"Mahjong H" , BIT_DIGITAL , System16InputPort2 + 3, "mah h" }, + {"Mahjong I" , BIT_DIGITAL , System16InputPort3 + 0, "mah i" }, + {"Mahjong J" , BIT_DIGITAL , System16InputPort3 + 1, "mah j" }, + {"Mahjong K" , BIT_DIGITAL , System16InputPort3 + 2, "mah k" }, + {"Mahjong L" , BIT_DIGITAL , System16InputPort3 + 3, "mah l" }, + {"Mahjong M" , BIT_DIGITAL , System16InputPort4 + 0, "mah m" }, + {"Mahjong N" , BIT_DIGITAL , System16InputPort4 + 1, "mah n" }, + {"Mahjong Kan" , BIT_DIGITAL , System16InputPort6 + 0, "mah kan" }, + {"Mahjong Pon" , BIT_DIGITAL , System16InputPort4 + 3, "mah pon" }, + {"Mahjong Chi" , BIT_DIGITAL , System16InputPort4 + 2, "mah chi" }, + {"Mahjong Reach" , BIT_DIGITAL , System16InputPort6 + 1, "mah reach" }, + {"Mahjong Ron" , BIT_DIGITAL , System16InputPort6 + 2, "mah ron" }, + {"Mahjong Bet" , BIT_DIGITAL , System16InputPort5 + 1, "mah bet" }, + {"Mahjong Last Chance", BIT_DIGITAL , System16InputPort1 + 4, "mah lc" }, + {"Mahjong Score" , BIT_DIGITAL , System16InputPort5 + 0, "mah score" }, + {"Mahjong Flip Flop" , BIT_DIGITAL , System16InputPort4 + 4, "mah ff" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Sjryuko1) + +#undef A + +/*==================================================== +Dip defs +====================================================*/ + +#define SYSTEM16A_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo AceattacaDIPList[]= +{ + // Default Values + {0x2d, 0xff, 0xff, 0xff, NULL }, + {0x2e, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x2d) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x2e, 0x01, 0x01, 0x01, "Off" }, + {0x2e, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Starting Points" }, + {0x2e, 0x01, 0x0e, 0x06, "2000" }, + {0x2e, 0x01, 0x0e, 0x0a, "3000" }, + {0x2e, 0x01, 0x0e, 0x0c, "4000" }, + {0x2e, 0x01, 0x0e, 0x0e, "5000" }, + {0x2e, 0x01, 0x0e, 0x08, "6000" }, + {0x2e, 0x01, 0x0e, 0x04, "7000" }, + {0x2e, 0x01, 0x0e, 0x02, "8000" }, + {0x2e, 0x01, 0x0e, 0x00, "9000" }, +}; + +STDDIPINFO(Aceattaca) + +static struct BurnDIPInfo AfighterDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x08, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x04, "4" }, + {0x14, 0x01, 0x0c, 0x00, "Infinite" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x30, "10000 - 20000" }, + {0x14, 0x01, 0x30, 0x20, "20000 - 40000" }, + {0x14, 0x01, 0x30, 0x10, "30000 - 60000" }, + {0x14, 0x01, 0x30, 0x00, "40000 - 80000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x40, 0x40, "Normal" }, + {0x14, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x80, 0x00, "No" }, + {0x14, 0x01, 0x80, 0x80, "Yes" }, +}; + +STDDIPINFO(Afighter) + +static struct BurnDIPInfo AlexkiddDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Continues" }, + {0x14, 0x01, 0x01, 0x01, "Only before level 5" }, + {0x14, 0x01, 0x01, 0x00, "Unlimited" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + {0x14, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x30, 0x20, "10000" }, + {0x14, 0x01, 0x30, 0x30, "20000" }, + {0x14, 0x01, 0x30, 0x10, "40000" }, + {0x14, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Timer Adjust" }, + {0x14, 0x01, 0xc0, 0x80, "70" }, + {0x14, 0x01, 0xc0, 0xc0, "60" }, + {0x14, 0x01, 0xc0, 0x40, "50" }, + {0x14, 0x01, 0xc0, 0x00, "40" }, +}; + +STDDIPINFO(Alexkidd) + +static struct BurnDIPInfo AliensynDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x11) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x0c, 0x08, "2" }, + {0x12, 0x01, 0x0c, 0x0c, "3" }, + {0x12, 0x01, 0x0c, 0x04, "4" }, + {0x12, 0x01, 0x0c, 0x00, "127" }, + + {0 , 0xfe, 0 , 4 , "Timer" }, + {0x12, 0x01, 0x30, 0x00, "150" }, + {0x12, 0x01, 0x30, 0x10, "160" }, + {0x12, 0x01, 0x30, 0x20, "170" }, + {0x12, 0x01, 0x30, 0x30, "180" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0xc0, 0x80, "Easy" }, + {0x12, 0x01, 0xc0, 0xc0, "Normal" }, + {0x12, 0x01, 0xc0, 0x40, "Hard" }, + {0x12, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Aliensyn) + +static struct BurnDIPInfo BodyslamDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, +}; + +STDDIPINFO(Bodyslam) + +static struct BurnDIPInfo FantzoneDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Upright" }, + {0x14, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x08, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x04, "4" }, + {0x14, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Extra Ship Cost" }, + {0x14, 0x01, 0x30, 0x30, "5000" }, + {0x14, 0x01, 0x30, 0x20, "10000" }, + {0x14, 0x01, 0x30, 0x10, "15000" }, + {0x14, 0x01, 0x30, 0x00, "20000" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0xc0, 0x80, "Easy" }, + {0x14, 0x01, 0xc0, 0xc0, "Normal" }, + {0x14, 0x01, 0xc0, 0x40, "Hard" }, + {0x14, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Fantzone) + +static struct BurnDIPInfo MjleagueDIPList[]= +{ + // Default Values + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xf0, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x1b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x1c, 0x01, 0x01, 0x00, "Upright" }, + {0x1c, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1c, 0x01, 0x02, 0x02, "Off" }, + {0x1c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Starting Points" }, + {0x1c, 0x01, 0x0c, 0x0c, "2000" }, + {0x1c, 0x01, 0x0c, 0x08, "3000" }, + {0x1c, 0x01, 0x0c, 0x04, "5000" }, + {0x1c, 0x01, 0x0c, 0x00, "10000" }, + + {0 , 0xfe, 0 , 2 , "Team Select" }, + {0x1c, 0x01, 0x10, 0x02, "Off" }, + {0x1c, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(Mjleague) + +static struct BurnDIPInfo Passsht16aDIPList[]= +{ + // Default Values + {0x29, 0xff, 0xff, 0xff, NULL }, + {0x2a, 0xff, 0xff, 0xf0, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x29) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x2a, 0x01, 0x01, 0x01, "Off" }, + {0x2a, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Initial Point" }, + {0x2a, 0x01, 0x0e, 0x06, "2000" }, + {0x2a, 0x01, 0x0e, 0x0a, "3000" }, + {0x2a, 0x01, 0x0e, 0x0c, "4000" }, + {0x2a, 0x01, 0x0e, 0x0e, "5000" }, + {0x2a, 0x01, 0x0e, 0x08, "6000" }, + {0x2a, 0x01, 0x0e, 0x04, "7000" }, + {0x2a, 0x01, 0x0e, 0x02, "8000" }, + {0x2a, 0x01, 0x0e, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Point Table" }, + {0x2a, 0x01, 0x30, 0x20, "Easy" }, + {0x2a, 0x01, 0x30, 0x30, "Normal" }, + {0x2a, 0x01, 0x30, 0x10, "Hard" }, + {0x2a, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x2a, 0x01, 0xc0, 0x80, "Easy" }, + {0x2a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x2a, 0x01, 0xc0, 0x40, "Hard" }, + {0x2a, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Passsht16a) + +static struct BurnDIPInfo QuartetDIPList[]= +{ + // Default Values + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x21) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x22, 0x01, 0x01, 0x01, "Off" }, + {0x22, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Credit Power" }, + {0x22, 0x01, 0x06, 0x04, "500" }, + {0x22, 0x01, 0x06, 0x06, "1000" }, + {0x22, 0x01, 0x06, 0x02, "2000" }, + {0x22, 0x01, 0x06, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x22, 0x01, 0x18, 0x10, "Easy" }, + {0x22, 0x01, 0x18, 0x18, "Normal" }, + {0x22, 0x01, 0x18, 0x08, "Hard" }, + {0x22, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Coin During Game" }, + {0x22, 0x01, 0x20, 0x20, "Power" }, + {0x22, 0x01, 0x20, 0x00, "Credit" }, + + {0 , 0xfe, 0 , 2 , "Free Play" }, + {0x22, 0x01, 0x40, 0x40, "Off" }, + {0x22, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x22, 0x01, 0x80, 0x80, "Off" }, + {0x22, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Quartet) + +static struct BurnDIPInfo Quart2DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x01, 0x01, "Off" }, + {0x14, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Credit Power" }, + {0x14, 0x01, 0x06, 0x04, "500" }, + {0x14, 0x01, 0x06, 0x06, "1000" }, + {0x14, 0x01, 0x06, 0x02, "2000" }, + {0x14, 0x01, 0x06, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x18, 0x10, "Easy" }, + {0x14, 0x01, 0x18, 0x18, "Normal" }, + {0x14, 0x01, 0x18, 0x08, "Hard" }, + {0x14, 0x01, 0x18, 0x00, "Hardest" }, +}; + +STDDIPINFO(Quart2) + +static struct BurnDIPInfo SdiDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x15) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x01, 0x01, "No" }, + {0x16, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x0c, 0x08, "2" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x04, "4" }, + {0x16, 0x01, 0x0c, 0x00, "Free" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x30, 0x20, "Easy" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x10, "Hard" }, + {0x16, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0xc0, 0x80, "Every 50000" }, + {0x16, 0x01, 0xc0, 0xc0, "50000" }, + {0x16, 0x01, 0xc0, 0x40, "100000" }, + {0x16, 0x01, 0xc0, 0x00, "None" }, +}; + +STDDIPINFO(Sdi) + +static struct BurnDIPInfo ShinobiDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x15) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x16, 0x01, 0x01, 0x00, "Upright" }, + {0x16, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x0c, 0x08, "2" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x04, "5" }, + {0x16, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x30, 0x20, "Easy" }, + {0x16, 0x01, 0x30, 0x30, "Normal" }, + {0x16, 0x01, 0x30, 0x10, "Hard" }, + {0x16, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Enemy Bullet Speed" }, + {0x16, 0x01, 0x40, 0x40, "Slow" }, + {0x16, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x16, 0x01, 0x80, 0x80, "Japanese" }, + {0x16, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Shinobi) + +static struct BurnDIPInfo Sjryuko1DIPList[]= +{ + // Default Values + {0x1c, 0xff, 0xff, 0xff, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x1c) + + // Dip 2 +}; + +STDDIPINFO(Sjryuko1) + +static struct BurnDIPInfo TetrisDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x11) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x30, 0x20, "Easy" }, + {0x12, 0x01, 0x30, 0x30, "Normal" }, + {0x12, 0x01, 0x30, 0x10, "Hard" }, + {0x12, 0x01, 0x30, 0x00, "Hardest" }, +}; + +STDDIPINFO(Tetris) + +static struct BurnDIPInfo TimescanDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf5, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x14, 0x01, 0x01, 0x00, "Cocktail" }, + {0x14, 0x01, 0x01, 0x01, "Upright" }, + + {0 , 0xfe, 0 , 16 , "Bonus" }, + {0x14, 0x01, 0x1e, 0x16, "Replay 1000000/2000000" }, + {0x14, 0x01, 0x1e, 0x14, "Replay 1200000/2500000" }, + {0x14, 0x01, 0x1e, 0x12, "Replay 1500000/3000000" }, + {0x14, 0x01, 0x1e, 0x10, "Replay 2000000/4000000" }, + {0x14, 0x01, 0x1e, 0x1c, "Replay 1000000" }, + {0x14, 0x01, 0x1e, 0x1e, "Replay 1200000" }, + {0x14, 0x01, 0x1e, 0x1a, "Replay 1500000" }, + {0x14, 0x01, 0x1e, 0x18, "Replay 1800000" }, + {0x14, 0x01, 0x1e, 0x0e, "Extra Ball 100000" }, + {0x14, 0x01, 0x1e, 0x0c, "Extra Ball 200000" }, + {0x14, 0x01, 0x1e, 0x0a, "Extra Ball 300000" }, + {0x14, 0x01, 0x1e, 0x08, "Extra Ball 400000" }, + {0x14, 0x01, 0x1e, 0x06, "Extra Ball 500000" }, + {0x14, 0x01, 0x1e, 0x04, "Extra Ball 600000" }, + {0x14, 0x01, 0x1e, 0x02, "Extra Ball 700000" }, + {0x14, 0x01, 0x1e, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Match" }, + {0x14, 0x01, 0x20, 0x00, "Off" }, + {0x14, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Pin Rebound" }, + {0x14, 0x01, 0x40, 0x40, "Well" }, + {0x14, 0x01, 0x40, 0x00, "A Little" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x80, 0x80, "3" }, + {0x14, 0x01, 0x80, 0x00, "5" }, + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Out Lane Pin" }, + {0x15, 0x01, 0x02, 0x02, "Near" }, + {0x15, 0x01, 0x02, 0x00, "Far" }, + + {0 , 0xfe, 0 , 4 , "Special" }, + {0x15, 0x01, 0x0c, 0x08, "7 Credits" }, + {0x15, 0x01, 0x0c, 0x0c, "3 Credits" }, + {0x15, 0x01, 0x0c, 0x04, "1 Credit" }, + {0x15, 0x01, 0x0c, 0x00, "2000000 Points" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x10, 0x00, "No" }, + {0x15, 0x01, 0x10, 0x10, "Yes" }, +}; + +STDDIPINFO(Timescan) + +static struct BurnDIPInfo Wb31DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + // Dip 1 + SYSTEM16A_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x0c, 0x00, "2" }, + {0x14, 0x01, 0x0c, 0x0c, "3" }, + {0x14, 0x01, 0x0c, 0x08, "4" }, + {0x14, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x14, 0x01, 0x10, 0x10, "5k, 10k, 18k, 30k" }, + {0x14, 0x01, 0x10, 0x00, "5k, 15k, 30k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x14, 0x01, 0x20, 0x20, "Normal" }, + {0x14, 0x01, 0x20, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Invincible Mode" }, + {0x14, 0x01, 0x40, 0x40, "No" }, + {0x14, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Wb31) + +#undef SYSTEM16A_COINAGE + +/*==================================================== +Rom defs +====================================================*/ + +static struct BurnRomInfo AceattacaRomDesc[] = { + { "epr-11573.43", 0x10000, 0xca116367, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11571.26", 0x10000, 0x5631d1d6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11574.42", 0x10000, 0x8d3ed7bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11572.25", 0x10000, 0x35c27c25, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11575.95", 0x10000, 0xbab9fbf3, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11576.94", 0x10000, 0x067ed682, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11577.93", 0x10000, 0xf67cf331, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11501.10", 0x10000, 0x09179ead, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11505.11", 0x10000, 0xb67f1ecf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11502.17", 0x10000, 0x7464bae4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11506.18", 0x10000, 0xb0104def, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11503.23", 0x10000, 0x344c0692, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11507.24", 0x10000, 0xa2af710a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11504.29", 0x10000, 0x42b4a5f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11508.30", 0x10000, 0x5cbb833c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11578.12", 0x08000, 0x3d58e39a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-11579.1", 0x08000, 0x1a994135, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11580.2", 0x08000, 0x961646ed, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11581.4", 0x08000, 0xd271a6e5, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11582.5", 0x08000, 0xbcbe3d8a, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0060.key", 0x02000, 0xf4ee940f, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aceattaca) +STD_ROM_FN(Aceattaca) + +static struct BurnRomInfo AfighterRomDesc[] = { + { "epr-10353", 0x08000, 0x5a757dc9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10350", 0x08000, 0xf2cd6b3f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10352", 0x08000, 0xf8abb143, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10349", 0x08000, 0x4b434c37, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10351", 0x08000, 0xede21d8d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10348", 0x08000, 0xe51e3012, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10281.95", 0x10000, 0x30e92cda, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10282.94", 0x10000, 0xb67b8910, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10283.93", 0x10000, 0xe7dbfd2d, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10285", 0x08000, 0x98aa3d04, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10289", 0x08000, 0xc59d1b98, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10286", 0x08000, 0x8da050cf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10290", 0x08000, 0x39354223, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10287", 0x08000, 0x7989b74a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10291", 0x08000, 0x6e4b245c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10288", 0x08000, 0xd3ce551a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10292", 0x08000, 0xcef289a3, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10284.12", 0x08000, 0x8ff09116, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0018.key", 0x02000, 0xfee04be8, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Afighter) +STD_ROM_FN(Afighter) + +static struct BurnRomInfo AlexkiddRomDesc[] = { + { "epr-10447.43", 0x10000, 0x29e87f71, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10445.26", 0x10000, 0x25ce5b6f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10448.42", 0x10000, 0x05baedb5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10446.25", 0x10000, 0xcd61d23c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10431.95", 0x08000, 0xa7962c39, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10432.94", 0x08000, 0xdb8cd24e, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10433.93", 0x08000, 0xe163c8c2, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10437.10", 0x08000, 0x522f7618, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10441.11", 0x08000, 0x74e3a35c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10438.17", 0x08000, 0x738a6362, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10442.18", 0x08000, 0x86cb9c14, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10439.23", 0x08000, 0xb391aca7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10443.24", 0x08000, 0x95d32635, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10440.29", 0x08000, 0x23939508, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10444.30", 0x08000, 0x82115823, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10434.12", 0x08000, 0x77141cce, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10435.1", 0x08000, 0xad89f6e3, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10436.2", 0x08000, 0x96c76613, SYS16_ROM_7751DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Alexkidd) +STD_ROM_FN(Alexkidd) + +static struct BurnRomInfo Alexkidd1RomDesc[] = { + { "epr-10429.43", 0x10000, 0xbdf49eca, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10427.26", 0x10000, 0xf6e3dd29, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10430.42", 0x10000, 0x89e3439f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10428.25", 0x10000, 0xdbed3210, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10431.95", 0x08000, 0xa7962c39, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10432.94", 0x08000, 0xdb8cd24e, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10433.93", 0x08000, 0xe163c8c2, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10437.10", 0x08000, 0x522f7618, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10441.11", 0x08000, 0x74e3a35c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10438.17", 0x08000, 0x738a6362, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10442.18", 0x08000, 0x86cb9c14, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10439.23", 0x08000, 0xb391aca7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10443.24", 0x08000, 0x95d32635, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10440.29", 0x08000, 0x23939508, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10444.30", 0x08000, 0x82115823, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10434.12", 0x08000, 0x77141cce, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10435.1", 0x08000, 0xad89f6e3, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10436.2", 0x08000, 0x96c76613, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0021.key", 0x02000, 0x85be8eac, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Alexkidd1) +STD_ROM_FN(Alexkidd1) + +static struct BurnRomInfo AliensynjoRomDesc[] = { + { "epr-10699.43", 0x08000, 0x3fd38d17, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10696.26", 0x08000, 0xd734f19f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10700.42", 0x08000, 0x3b04b252, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10697.25", 0x08000, 0xf2bc123d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10701.41", 0x08000, 0x92171751, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10698.24", 0x08000, 0xc1e4fdc0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10739.95", 0x10000, 0xa29ec207, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10740.94", 0x10000, 0x47f93015, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10741.93", 0x10000, 0x4970739c, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10709.10", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10713.11", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10710.17", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10714.18", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10711.23", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10715.24", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10712.29", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10716.30", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10705.12", 0x08000, 0x777b749e, SYS16_ROM_Z80PROG | BRF_ESS |BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10706.1", 0x08000, 0xaa114acc, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10707.2", 0x08000, 0x800c1d82, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10708.4", 0x08000, 0x5921ef52, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0033.key", 0x02000, 0x49e882e5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aliensynjo) +STD_ROM_FN(Aliensynjo) + +static struct BurnRomInfo Aliensyn2RomDesc[] = { + { "epr-10808", 0x08000, 0xe669929f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10806", 0x08000, 0x9f7f8fdd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10809", 0x08000, 0x9a424919, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10807", 0x08000, 0x3d2c3530, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10701", 0x08000, 0x92171751, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10698", 0x08000, 0xc1e4fdc0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "10739", 0x10000, 0xa29ec207, SYS16_ROM_TILES | BRF_GRA }, + { "10740", 0x10000, 0x47f93015, SYS16_ROM_TILES | BRF_GRA }, + { "10741", 0x10000, 0x4970739c, SYS16_ROM_TILES | BRF_GRA }, + + { "10709.b1", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "10713.b5", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "10710.b2", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "10714.b6", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "10711.b3", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "10715.b7", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "10712.b4", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "10716.b8", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "10705", 0x08000, 0x777b749e, SYS16_ROM_Z80PROG | BRF_ESS |BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "10706", 0x08000, 0xaa114acc, SYS16_ROM_7751DATA | BRF_SND }, + { "10707", 0x08000, 0x800c1d82, SYS16_ROM_7751DATA | BRF_SND }, + { "10708", 0x08000, 0x5921ef52, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0033.key", 0x02000, 0x49e882e5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aliensyn2) +STD_ROM_FN(Aliensyn2) + +static struct BurnRomInfo Aliensyn5RomDesc[] = { + { "epr-10804.43", 0x08000, 0x23f78b83, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10802.26", 0x08000, 0x996768bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10805.42", 0x08000, 0x53d7fe50, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10803.25", 0x08000, 0x0536dd33, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10732.41", 0x08000, 0xc5712bfc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10729.24", 0x08000, 0x3e520e30, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10739.95", 0x10000, 0xa29ec207, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10740.94", 0x10000, 0x47f93015, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10741.93", 0x10000, 0x4970739c, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10709.10", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10713.11", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10710.17", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10714.18", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10711.23", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10715.24", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10712.29", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10716.30", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10705.12", 0x08000, 0x777b749e, SYS16_ROM_Z80PROG | BRF_ESS |BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10706.1", 0x08000, 0xaa114acc, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10707.2", 0x08000, 0x800c1d82, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10708.4", 0x08000, 0x5921ef52, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0037.key", 0x02000, 0x49e882e5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aliensyn5) +STD_ROM_FN(Aliensyn5) + +static struct BurnRomInfo BodyslamRomDesc[] = { + { "epr-10066.b9", 0x08000, 0x6cd53290, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10063.b6", 0x08000, 0xdd849a16, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10067.b10", 0x08000, 0xdb22a5ce, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10064.b7", 0x08000, 0x53d6b7e0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10068.b11", 0x08000, 0x15ccc665, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10065.b8", 0x08000, 0x0e5fa314, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10321.c9", 0x08000, 0xcd3e7cba, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10322.c10", 0x08000, 0xb53d3217, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10323.c11", 0x08000, 0x915a3e61, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10012.c5", 0x08000, 0x990824e8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10016.b2", 0x08000, 0xaf5dc72f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10013.c6", 0x08000, 0x9a0919c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10017.b3", 0x08000, 0x62aafd95, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10027.c7", 0x08000, 0x3f1c57c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10028.b4", 0x08000, 0x80d4946d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10015.c8", 0x08000, 0x582d3b6a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10019.b5", 0x08000, 0xe020c38b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10026.b1", 0x08000, 0x123b69b8, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10029.c1", 0x08000, 0x7e4aca83, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10030.c2", 0x08000, 0xdcc1df0b, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10031.c3", 0x08000, 0xea3c4472, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-10032.c4", 0x08000, 0x0aabebce, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0015.bin", 0x01000, 0x833869e2, BRF_PRG | BRF_OPT }, +}; + + +STD_ROM_PICK(Bodyslam) +STD_ROM_FN(Bodyslam) + +static struct BurnRomInfo DumpmtmtRomDesc[] = { + { "epr-7704a.b9", 0x08000, 0x96de6c7b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7701a.b6", 0x08000, 0x786d1009, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7705a.b10", 0x08000, 0xfc584391, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7702a.b7", 0x08000, 0x2241a8fd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7706a.b11", 0x08000, 0x6bbcc9d0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7703a.b8", 0x08000, 0xfcb0cd40, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7707a.c9", 0x08000, 0x45318738, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7708a.c10", 0x08000, 0x411be9a4, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7709a.c11", 0x08000, 0x74ceb5a8, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7715.c5", 0x08000, 0xbf47e040, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7719.b2", 0x08000, 0xfa5c5d6c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10013.c6", 0x08000, 0x9a0919c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10017.b3", 0x08000, 0x62aafd95, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7717.c7", 0x08000, 0xfa64c86d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7721.b4", 0x08000, 0x62a9143e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10015.c8", 0x08000, 0x582d3b6a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10019.b5", 0x08000, 0xe020c38b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7710a.b1", 0x08000, 0xa19b8ba8, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7711.c1", 0x08000, 0xefa9aabd, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7712.c2", 0x08000, 0x7bcd85cf, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7713.c3", 0x08000, 0x33f292e7, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7714.c4", 0x08000, 0x8fd48c47, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0011a.mcu", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Dumpmtmt) +STD_ROM_FN(Dumpmtmt) + +static struct BurnRomInfo FantzoneRomDesc[] = { + { "epr-7385a.43", 0x08000, 0x4091af42, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7382a.26", 0x08000, 0x77d67bfd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7386a.42", 0x08000, 0xb0a67cd0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7383a.25", 0x08000, 0x5f79b2a9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7387.41", 0x08000, 0x0acd335d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7384.24", 0x08000, 0xfd909341, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7388.95", 0x08000, 0x8eb02f6b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7389.94", 0x08000, 0x2f4f71b8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7390.93", 0x08000, 0xd90609c6, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7392.10", 0x08000, 0x5bb7c8b6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7396.11", 0x08000, 0x74ae4b57, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7393.17", 0x08000, 0x14fc7e82, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7397.18", 0x08000, 0xe05a1e25, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7394.23", 0x08000, 0x531ca13f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7398.24", 0x08000, 0x68807b49, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7535a.12", 0x08000, 0xbc1374fa, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fantzone) +STD_ROM_FN(Fantzone) + +static struct BurnRomInfo Fantzone1RomDesc[] = { + { "epr-7385.43", 0x08000, 0x5cb64450, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7382.26", 0x08000, 0x3fda7416, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7386.42", 0x08000, 0x15810ace, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7383.25", 0x08000, 0xa001e10a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7387.41", 0x08000, 0x0acd335d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7384.24", 0x08000, 0xfd909341, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7388.95", 0x08000, 0x8eb02f6b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7389.94", 0x08000, 0x2f4f71b8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7390.93", 0x08000, 0xd90609c6, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7392.10", 0x08000, 0x5bb7c8b6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7396.11", 0x08000, 0x74ae4b57, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7393.17", 0x08000, 0x14fc7e82, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7397.18", 0x08000, 0xe05a1e25, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7394.23", 0x08000, 0x531ca13f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7398.24", 0x08000, 0x68807b49, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7535.12", 0x08000, 0x0cb2126a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fantzone1) +STD_ROM_FN(Fantzone1) + +static struct BurnRomInfo FantzonepRomDesc[] = { + { "epr-7385.43", 0x08000, 0x5cb64450, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7382.26", 0x08000, 0x3fda7416, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7386.42", 0x08000, 0x15810ace, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7383.25", 0x08000, 0xa001e10a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7387.41", 0x08000, 0x0acd335d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7384.24", 0x08000, 0xfd909341, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7388.95", 0x08000, 0x8eb02f6b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7389.94", 0x08000, 0x2f4f71b8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7390.93", 0x08000, 0xd90609c6, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7392.10", 0x08000, 0x5bb7c8b6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7396.11", 0x08000, 0x74ae4b57, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7393.17", 0x08000, 0x14fc7e82, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7397.18", 0x08000, 0xe05a1e25, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7394.23", 0x08000, 0x531ca13f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7398.24", 0x08000, 0x68807b49, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7391.12", 0x08000, 0xc03e155e, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fantzonep) +STD_ROM_FN(Fantzonep) + +static struct BurnRomInfo MjleagueRomDesc[] = { + { "epr-7404.9b", 0x08000, 0xec1655b5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7401.6b", 0x08000, 0x2befa5e0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7405.10b", 0x08000, 0x7a4f4e38, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7402.7b", 0x08000, 0xb7bef762, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7406a.11b", 0x08000, 0xbb743639, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7403a.8b", 0x08000, 0x0a39a4d0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7051.9a", 0x08000, 0x10ca255a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7052.10a", 0x08000, 0x2550db0e, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7053.11a", 0x08000, 0x5bfea038, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7055.5a", 0x08000, 0x1fb860bd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7059.2b", 0x08000, 0x3d14091d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7056.6a", 0x08000, 0xb35dd968, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7060.3b", 0x08000, 0x61bb3757, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7057.7a", 0x08000, 0x3e5a2b6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7061.4b", 0x08000, 0xc808dad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7058.8a", 0x08000, 0xb543675f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7062.5b", 0x08000, 0x9168eb47, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7054c.1b", 0x08000, 0x4443b744, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7063.1a", 0x08000, 0x45d8908a, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7065.2a", 0x08000, 0x8c8f8cff, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7064.3a", 0x08000, 0x159f6636, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7066.4a", 0x08000, 0xf5cfa91f, SYS16_ROM_7751DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Mjleague) +STD_ROM_FN(Mjleague) + +static struct BurnRomInfo Passsht16aRomDesc[] = { + { "epr-11833.43", 0x10000, 0x5eb1405c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11832.26", 0x10000, 0x718a3fe4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11834.95", 0x10000, 0xdf4e18ab, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11835.94", 0x10000, 0x6a07acc0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11836.93", 0x10000, 0x93c74928, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11842.10", 0x10000, 0xb6e94727, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11845.11", 0x10000, 0x17e8d5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11843.17", 0x10000, 0x3e670098, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11846.18", 0x10000, 0x50eb71cc, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11844.23", 0x10000, 0x05733ca8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11847.24", 0x10000, 0x81e49697, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11837.12", 0x08000, 0x74d11552, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-11838.1", 0x08000, 0xa465cd69, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11839.2", 0x08000, 0x99de6197, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11840.4", 0x08000, 0x9854e8b3, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-11841.5", 0x08000, 0x1e89877e, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0071.key", 0x02000, 0xc69949ec, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Passsht16a) +STD_ROM_FN(Passsht16a) + +static struct BurnRomInfo QuartetRomDesc[] = { + { "epr-7458a.9b", 0x08000, 0x42e7b23e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7455a.6b", 0x08000, 0x01631ab2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7459a.10b", 0x08000, 0x6b540637, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7456a.7b", 0x08000, 0x31ca583e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7460.11b", 0x08000, 0xa444ea13, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7457.8b", 0x08000, 0x3b282c23, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7461.9c", 0x08000, 0xf6af07f2, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7462.10c", 0x08000, 0x7914af28, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7463.11c", 0x08000, 0x827c5603, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7465.5c", 0x08000, 0x8a1ab7d7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7469.2b", 0x08000, 0xcb65ae4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7466.6c", 0x08000, 0xb2d3f4f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7470.3b", 0x08000, 0x16fc67b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7467.7c", 0x08000, 0x0af68de2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7471.4b", 0x08000, 0x13fad5ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7468.8c", 0x08000, 0xddfd40c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7472.5b", 0x08000, 0x8e2762ec, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7464.1b", 0x08000, 0x9f291306, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7473.1c", 0x08000, 0x06ec75fa, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7475.2c", 0x08000, 0x7abd1206, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7474.3c", 0x08000, 0xdbf853b8, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7476.4c", 0x08000, 0x5eba655a, SYS16_ROM_7751DATA | BRF_SND }, + + { "315-5194.mcu", 0x01000, 0x00000000, BRF_NODUMP }, + + { "pal16r6a.22g", 0x00104, 0x00000000, BRF_NODUMP }, // PLD + { "pal16r6a.23g", 0x00104, 0x00000000, BRF_NODUMP }, // PLD + { "pls153.8j", 0x000eb, 0x0fe1eefd, BRF_OPT }, // PLD +}; + + +STD_ROM_PICK(Quartet) +STD_ROM_FN(Quartet) + +static struct BurnRomInfo QuartetaRomDesc[] = { + { "epr-7458.9b", 0x08000, 0x0096499f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7455.6b", 0x08000, 0xda934390, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7459.10b", 0x08000, 0xd130cf61, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7456.7b", 0x08000, 0x7847149f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7460.11b", 0x08000, 0xa444ea13, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7457.8b", 0x08000, 0x3b282c23, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7461.9c", 0x08000, 0xf6af07f2, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7462.10c", 0x08000, 0x7914af28, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7463.11c", 0x08000, 0x827c5603, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7465.5c", 0x08000, 0x8a1ab7d7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7469.2b", 0x08000, 0xcb65ae4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7466.6c", 0x08000, 0xb2d3f4f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7470.3b", 0x08000, 0x16fc67b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7467.7c", 0x08000, 0x0af68de2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7471.4b", 0x08000, 0x13fad5ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7468.8c", 0x08000, 0xddfd40c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7472.5b", 0x08000, 0x8e2762ec, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7464.1b", 0x08000, 0x9f291306, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7473.1c", 0x08000, 0x06ec75fa, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7475.2c", 0x08000, 0x7abd1206, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7474.3c", 0x08000, 0xdbf853b8, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7476.4c", 0x08000, 0x5eba655a, SYS16_ROM_7751DATA | BRF_SND }, + + { "315-5194.mcu", 0x01000, 0x00000000, BRF_NODUMP }, + + { "pal16r6a.22g", 0x00104, 0x00000000, BRF_NODUMP }, // PLD + { "pal16r6a.23g", 0x00104, 0x00000000, BRF_NODUMP }, // PLD + { "pls153.8j", 0x000eb, 0x0fe1eefd, BRF_OPT }, // PLD +}; + + +STD_ROM_PICK(Quarteta) +STD_ROM_FN(Quarteta) + +static struct BurnRomInfo Quartet2RomDesc[] = { + { "epr-7695.b9", 0x08000, 0x67177cd8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7692.b6", 0x08000, 0x50f50b08, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7696.b10", 0x08000, 0x4273c3b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7693.b7", 0x08000, 0x0aa337bb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7697.b11", 0x08000, 0x3a6a375d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7694.b8", 0x08000, 0xd87b2ca2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7698.c9", 0x08000, 0x547a6058, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7699.c10", 0x08000, 0x77ec901d, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7700.c11", 0x08000, 0x7e348cce, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7465.5c", 0x08000, 0x8a1ab7d7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7469.2b", 0x08000, 0xcb65ae4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7466.6c", 0x08000, 0xb2d3f4f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7470.3b", 0x08000, 0x16fc67b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7467.7c", 0x08000, 0x0af68de2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7471.4b", 0x08000, 0x13fad5ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7468.8c", 0x08000, 0xddfd40c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7472.5b", 0x08000, 0x8e2762ec, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7464.1b", 0x08000, 0x9f291306, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7473.1c", 0x08000, 0x06ec75fa, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7475.2c", 0x08000, 0x7abd1206, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7474.3c", 0x08000, 0xdbf853b8, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7476.4c", 0x08000, 0x5eba655a, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0010.bin", 0x01000, 0x8c2033ea, BRF_PRG | BRF_OPT }, +}; + + +STD_ROM_PICK(Quartet2) +STD_ROM_FN(Quartet2) + +static struct BurnRomInfo Quartet2aRomDesc[] = { + { "epr-7728.b9", 0x08000, 0x56a8c88e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7725.b6", 0x08000, 0xee15fcc9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7729.b10", 0x08000, 0xbc242123, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7726.b7", 0x08000, 0x9d1c48e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7697.b11", 0x08000, 0x3a6a375d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-7694.b8", 0x08000, 0xd87b2ca2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-7698.c9", 0x08000, 0x547a6058, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7699.c10", 0x08000, 0x77ec901d, SYS16_ROM_TILES | BRF_GRA }, + { "epr-7700.c11", 0x08000, 0x7e348cce, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-7465.5c", 0x08000, 0x8a1ab7d7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7469.2b", 0x08000, 0xcb65ae4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7466.6c", 0x08000, 0xb2d3f4f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7470.3b", 0x08000, 0x16fc67b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7467.7c", 0x08000, 0x0af68de2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7471.4b", 0x08000, 0x13fad5ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7468.8c", 0x08000, 0xddfd40c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-7472.5b", 0x08000, 0x8e2762ec, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-7464.1b", 0x08000, 0x9f291306, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-7473.1c", 0x08000, 0x06ec75fa, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7475.2c", 0x08000, 0x7abd1206, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7474.3c", 0x08000, 0xdbf853b8, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-7476.4c", 0x08000, 0x5eba655a, SYS16_ROM_7751DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Quartet2a) +STD_ROM_FN(Quartet2a) + +static struct BurnRomInfo SdiRomDesc[] = { + { "epr-10970.43", 0x08000, 0xb8fa4a2c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10968.26", 0x08000, 0xa3f97793, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10971.42", 0x08000, 0xc44a0328, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10969.25", 0x08000, 0x455d15bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10755.41", 0x08000, 0x405e3969, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10752.24", 0x08000, 0x77453740, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10756.95", 0x10000, 0x44d8a506, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10757.94", 0x10000, 0x497e1740, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10758.93", 0x10000, 0x61d61486, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10760.10", 0x10000, 0x30e2c50a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10763.11", 0x10000, 0x794e3e8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10761.17", 0x10000, 0x6a8b3fd0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10764.18", 0x10000, 0x602da5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10762.23", 0x10000, 0xb9de3aeb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10765.24", 0x10000, 0x0a73a057, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10759.12", 0x08000, 0xd7f9649f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0027.key", 0x02000, 0x9a5307b2, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sdi) +STD_ROM_FN(Sdi) + +static struct BurnRomInfo ShinobiRomDesc[] = { + { "epr-12010.43", 0x10000, 0x7df7f4a2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12008.26", 0x10000, 0xf5ae64cd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12011.42", 0x10000, 0x9d46e707, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12009.25", 0x10000, 0x7961d07e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11264.95", 0x10000, 0x46627e7d, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11265.94", 0x10000, 0x87d0f321, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11266.93", 0x10000, 0xefb4af87, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11290.10", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11294.11", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11291.17", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11295.18", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11292.23", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11296.24", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11293.29", 0x10000, 0x41f41063, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11297.30", 0x10000, 0xb6e1fd72, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11267.12", 0x08000, 0xdd50b745, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-11268.1", 0x08000, 0x6d7966da, SYS16_ROM_7751DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shinobi) +STD_ROM_FN(Shinobi) + +static struct BurnRomInfo Shinobi1RomDesc[] = { + { "epr-11262.42", 0x10000, 0xd4b8df12, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11260.27", 0x10000, 0x2835c95d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11263.43", 0x10000, 0xa2a620bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11261.25", 0x10000, 0xa3ceda52, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11264.95", 0x10000, 0x46627e7d, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11265.94", 0x10000, 0x87d0f321, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11266.93", 0x10000, 0xefb4af87, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11290.10", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11294.11", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11291.17", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11295.18", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11292.23", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11296.24", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11293.29", 0x10000, 0x41f41063, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11297.30", 0x10000, 0xb6e1fd72, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11267.12", 0x08000, 0xdd50b745, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-11268.1", 0x08000, 0x6d7966da, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0050.key", 0x02000, 0x82c39ced, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shinobi1) +STD_ROM_FN(Shinobi1) + +static struct BurnRomInfo ShinoblsRomDesc[] = { + { "b3", 0x10000, 0x38e59646, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "b1", 0x10000, 0x8529d192, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "b4", 0x10000, 0xa2a620bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "b2", 0x10000, 0xa3ceda52, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "b5", 0x10000, 0x46627e7d, SYS16_ROM_TILES | BRF_GRA }, + { "b6", 0x10000, 0x87d0f321, SYS16_ROM_TILES | BRF_GRA }, + { "b7", 0x10000, 0xefb4af87, SYS16_ROM_TILES | BRF_GRA }, + + { "b10", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "b14", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "b11", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "b15", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "b12", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "b16", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "b13", 0x10000, 0x7e98bd36, SYS16_ROM_SPRITES | BRF_GRA }, + { "b17", 0x10000, 0x0315cf42, SYS16_ROM_SPRITES | BRF_GRA }, + + { "b8", 0x08000, 0xdd50b745, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "b9", 0x08000, 0x6d7966da, SYS16_ROM_7751DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shinobls) +STD_ROM_FN(Shinobls) + +static struct BurnRomInfo ShinoblbRomDesc[] = { + { "4.3k", 0x10000, 0xc178a39c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "2.3n", 0x10000, 0x5ad8ebf2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "5.2k", 0x10000, 0xa2a620bd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "3.2n", 0x10000, 0xa3ceda52, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "8.3b", 0x10000, 0x46627e7d, SYS16_ROM_TILES | BRF_GRA }, + { "7.4b", 0x10000, 0x87d0f321, SYS16_ROM_TILES | BRF_GRA }, + { "6.5b", 0x10000, 0xefb4af87, SYS16_ROM_TILES | BRF_GRA }, + + { "9.6r", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "13.8r", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "10.6q", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "14.8q", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "11.6p", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "15.8p", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "12.6n", 0x10000, 0x41f41063, SYS16_ROM_SPRITES | BRF_GRA }, + { "16.8n", 0x10000, 0xb6e1fd72, SYS16_ROM_SPRITES | BRF_GRA }, + + { "1.5s", 0x08000, 0xdd50b745, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "b9", 0x08000, 0x6d7966da, SYS16_ROM_7751DATA | BRF_SND }, + + { "17.6u", 0x08000, 0xb7a6890c, BRF_SND | BRF_OPT }, +}; + + +STD_ROM_PICK(Shinoblb) +STD_ROM_FN(Shinoblb) + +static struct BurnRomInfo Sjryuko1RomDesc[] = { + { "epr-12251.43", 0x08000, 0x1af3cd0b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12249.26", 0x08000, 0x743d467d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12252.42", 0x08000, 0x7ae309d6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12250.25", 0x08000, 0x52c40f19, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "12224-95.b9", 0x08000, 0xeac17ba1, SYS16_ROM_TILES | BRF_GRA }, + { "12225-94.b10", 0x08000, 0x2310fc98, SYS16_ROM_TILES | BRF_GRA }, + { "12226-93.b11", 0x08000, 0x210e6999, SYS16_ROM_TILES | BRF_GRA }, + + { "12232-10.b1", 0x10000, 0x0adec62b, SYS16_ROM_SPRITES | BRF_GRA }, + { "12236-11.b5", 0x10000, 0x286b9af8, SYS16_ROM_SPRITES | BRF_GRA }, + { "12233-17.b2", 0x10000, 0x3e45969c, SYS16_ROM_SPRITES | BRF_GRA }, + { "12237-18.b6", 0x10000, 0xe5058e96, SYS16_ROM_SPRITES | BRF_GRA }, + { "12234-23.b3", 0x10000, 0x8c8d54ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "12238-24.b7", 0x10000, 0x7ada3304, SYS16_ROM_SPRITES | BRF_GRA }, + { "12235-29.b4", 0x10000, 0xfa45d511, SYS16_ROM_SPRITES | BRF_GRA }, + { "12239-30.b8", 0x10000, 0x91f70c8b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12227.12", 0x08000, 0x5b12409d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-12228.1", 0x08000, 0x6b2e6aef, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-12229.2", 0x08000, 0xb7aa015c, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-12230.4", 0x08000, 0xd0f61fd4, SYS16_ROM_7751DATA | BRF_SND }, + { "epr-12231.5", 0x08000, 0x780bdc57, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-5021.key", 0x02000, 0x4a3422e4, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sjryuko1) +STD_ROM_FN(Sjryuko1) + +static struct BurnRomInfo TetrisRomDesc[] = { + { "epr-12201.rom", 0x08000, 0x338e9b51, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12200.rom", 0x08000, 0xfb058779, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12202.rom", 0x10000, 0x2f7da741, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12203.rom", 0x10000, 0xa6e58ec5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12204.rom", 0x10000, 0x0ae98e23, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12169.b1", 0x08000, 0xdacc6165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12170.b5", 0x08000, 0x87354e42, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12205.rom", 0x08000, 0x6695dc99, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0093.key", 0x02000, 0xe0064442, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Tetris) +STD_ROM_FN(Tetris) + +static struct BurnRomInfo Tetris3RomDesc[] = { + { "epr-12201a.43", 0x08000, 0x9250e5cf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12200a.26", 0x08000, 0x85d4b0ff, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12202.rom", 0x10000, 0x2f7da741, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12203.rom", 0x10000, 0xa6e58ec5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12204.rom", 0x10000, 0x0ae98e23, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12169.b1", 0x08000, 0xdacc6165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12170.b5", 0x08000, 0x87354e42, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12205.rom", 0x08000, 0x6695dc99, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0093a.key", 0x02000, 0x7ca4a8ee, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Tetris3) +STD_ROM_FN(Tetris3) + +static struct BurnRomInfo Timescan1RomDesc[] = { + { "epr-10540a.43", 0x08000, 0x76848b0b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10537a.26", 0x08000, 0x4ddc434a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10541.42", 0x08000, 0xcc6d945e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10538.25", 0x08000, 0x68379473, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10542.41", 0x08000, 0x10217dfa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10539.24", 0x08000, 0x10943b2e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10543.95", 0x08000, 0x07dccc37, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10544.94", 0x08000, 0x84fb9a3a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10545.93", 0x08000, 0xc8694bc0, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10548.10", 0x08000, 0xaa150735, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10552.11", 0x08000, 0x6fcbb9f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10549.17", 0x08000, 0x2f59f067, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10553.18", 0x08000, 0x8a220a9f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10550.23", 0x08000, 0xf05069ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10554.24", 0x08000, 0xdc64f809, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10551.29", 0x08000, 0x435d811f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10555.30", 0x08000, 0x2143c471, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10546.12", 0x08000, 0x1ebee5cc, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "7751.bin", 0x00400, 0x6a9534fc, SYS16_ROM_7751PROG | BRF_ESS | BRF_PRG }, + + { "epr-10547.1", 0x08000, 0xd24ffc4b, SYS16_ROM_7751DATA | BRF_SND }, + + { "317-0024.key", 0x02000, 0xee42ec18, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Timescan1) +STD_ROM_FN(Timescan1) + +static struct BurnRomInfo Wb31RomDesc[] = { + { "epr-12084.bin", 0x10000, 0xb6deb654, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12082.bin", 0x10000, 0x38dc5b15, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12085.bin", 0x10000, 0x0962098b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12083.bin", 0x10000, 0x3d631a8e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12086.bin", 0x10000, 0x45b949df, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12087.bin", 0x10000, 0x6f0396b7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12088.bin", 0x10000, 0xba8c0749, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12089.bin", 0x08000, 0x8321eb0b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0084.key", 0x02000, 0x2c58dafa, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wb31) +STD_ROM_FN(Wb31) + +/*==================================================== +Memory Handlers +====================================================*/ + +static bool Mjleague = false; + +void System16APPI0WritePortA(UINT8 data) +{ + System16SoundLatch = data & 0xff; +} + +void System16APPI0WritePortB(UINT8 data) +{ + System16VideoControl = data; + System16VideoEnable = data & 0x10; + if (Mjleague) System16ScreenFlip = data & 0x80; +} + +void System16APPI0WritePortC(UINT8 data) +{ + if (!(data & 0x80)) { + ZetOpen(0); + ZetNmi(); + ZetClose(); + } + System16ColScroll = ~data & 0x04; + System16RowScroll = ~data & 0x02; +} + +UINT16 __fastcall System16AReadWord(UINT32 a) +{ + switch (a) { + case 0xc40000: + case 0xc40002: + case 0xc40004: + case 0xc40006: + case 0xc41000: + case 0xc41002: + case 0xc41004: + case 0xc41006: + case 0xc42000: + case 0xc42002: + case 0xc42004: + case 0xc42006: { + SEK_DEF_READ_WORD(0, a); + } + + case 0xc60000: { + return 0; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall System16AReadByte(UINT32 a) +{ + switch (a) { + case 0xc40001: + case 0xc40003: + case 0xc40005: + case 0xc40007: { + return ppi8255_r(0, (a - 0xc40000) >> 1); + } + + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return System16Dip[2]; + } + + case 0xc41007: { + return 0xff - System16Input[2]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc60000: { + return 0; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall System16AWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16ATileWordWrite(a - 0x400000, d); + return; + } + + switch (a) { + case 0xc40000: + case 0xc40002: + case 0xc40004: + case 0xc40006: { + SEK_DEF_WRITE_WORD(0, a, d); + return; + } + + case 0xc60000: { + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall System16AWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16ATileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0xc40001: + case 0xc40003: + case 0xc40005: + case 0xc40007: { + ppi8255_w(0, (a - 0xc40000) >> 1, d & 0xff); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +static INT16 AceattacaTrack1X = 0; +static INT16 AceattacaTrack1Y = 0; +static INT16 AceattacaTrack2X = 0; +static INT16 AceattacaTrack2Y = 0; +static INT8 AceattacaDial1 = 0; +static INT8 AceattacaDial2 = 0; + +void AceattacaMakeAnalogInputs() +{ + if (System16InputPort3[0]) AceattacaTrack1X += 0x40; + if (System16InputPort3[1]) AceattacaTrack1X -= 0x40; + if (AceattacaTrack1X >= 0x100) AceattacaTrack1X = 0; + if (AceattacaTrack1X < 0) AceattacaTrack1X = 0xfd; + + if (System16InputPort3[2]) AceattacaTrack1Y -= 0x40; + if (System16InputPort3[3]) AceattacaTrack1Y += 0x40; + if (AceattacaTrack1Y >= 0x100) AceattacaTrack1Y = 0; + if (AceattacaTrack1Y < 0) AceattacaTrack1Y = 0xfd; + + if (System16InputPort4[0]) AceattacaDial1 += 0x01; + if (System16InputPort4[1]) AceattacaDial1 -= 0x01; + if (AceattacaDial1 >= 0x10) AceattacaDial1 = 0; + if (AceattacaDial1 < 0) AceattacaDial1 = 0x0f; + + if (System16InputPort3[4]) AceattacaTrack2X += 0x40; + if (System16InputPort3[5]) AceattacaTrack2X -= 0x40; + if (AceattacaTrack2X >= 0x100) AceattacaTrack2X = 0; + if (AceattacaTrack2X < 0) AceattacaTrack2X = 0xfd; + + if (System16InputPort3[6]) AceattacaTrack2Y -= 0x40; + if (System16InputPort3[7]) AceattacaTrack2Y += 0x40; + if (AceattacaTrack2Y >= 0x100) AceattacaTrack2Y = 0; + if (AceattacaTrack2Y < 0) AceattacaTrack2Y = 0xfd; + + if (System16InputPort4[2]) AceattacaDial2 += 0x01; + if (System16InputPort4[3]) AceattacaDial2 -= 0x01; + if (AceattacaDial2 >= 0x10) AceattacaDial2 = 0; + if (AceattacaDial2 < 0) AceattacaDial2 = 0x0f; +} + +UINT8 __fastcall AceattacaReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + if (System16VideoControl == 0x10) return 0xff - System16Input[1]; + if (System16VideoControl == 0x14) return AceattacaTrack1X; + if (System16VideoControl == 0x18) return AceattacaTrack1Y; + if (System16VideoControl == 0x1c) return System16Input[2]; + return 0xff; + } + + case 0xc41005: { + return AceattacaDial1 | (AceattacaDial2 << 4); + } + + case 0xc41007: { + if (System16VideoControl == 0x10) return 0xff - System16Input[5]; + if (System16VideoControl == 0x14) return AceattacaTrack2X; + if (System16VideoControl == 0x18) return AceattacaTrack2Y; + if (System16VideoControl == 0x1c) return System16Input[6]; + return 0xff; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc60000: { + return 0; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +static INT16 MjleagueTrack1X = 0; +static INT16 MjleagueTrack1Y = 0; +static INT16 MjleagueTrack2X = 0; +static INT16 MjleagueTrack2Y = 0; +static INT16 MjleagueBat1 = 0; +static INT16 MjleagueBat2 = 0; + +void MjleagueMakeAnalogInputs() +{ + if (System16InputPort3[0]) MjleagueTrack1X -= 0x04; + if (System16InputPort3[1]) MjleagueTrack1X += 0x04; + if (MjleagueTrack1X >= 0x100) MjleagueTrack1X = 0; + if (MjleagueTrack1X < 0) MjleagueTrack1X = 0xfc; + + if (System16InputPort3[2]) MjleagueTrack1Y -= 0x04; + if (System16InputPort3[3]) MjleagueTrack1Y += 0x04; + if (MjleagueTrack1Y >= 0x100) MjleagueTrack1Y = 0; + if (MjleagueTrack1Y < 0) MjleagueTrack1Y = 0xfc; + + if (System16InputPort3[4]) MjleagueTrack2X -= 0x04; + if (System16InputPort3[5]) MjleagueTrack2X += 0x04; + if (MjleagueTrack2X >= 0x100) MjleagueTrack2X = 0; + if (MjleagueTrack2X < 0) MjleagueTrack2X = 0xfc; + + if (System16InputPort3[6]) MjleagueTrack2Y -= 0x04; + if (System16InputPort3[7]) MjleagueTrack2Y += 0x04; + if (MjleagueTrack2Y >= 0x100) MjleagueTrack2Y = 0; + if (MjleagueTrack2Y < 0) MjleagueTrack2Y = 0xfc; + + MjleagueBat1 = 0x80 + (System16AnalogPort0 >> 4); + MjleagueBat2 = 0x80 + (System16AnalogPort1 >> 4); +} + +UINT8 __fastcall MjleagueReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + UINT8 buttons = 0x3f - System16Input[0]; + UINT8 analog1 = (System16VideoControl & 4) ? MjleagueTrack1Y : MjleagueTrack1X; + UINT8 analog2 = (System16VideoControl & 4) ? MjleagueTrack2Y : MjleagueTrack2X; + + buttons |= (analog1 & 0x80) >> 1; + buttons |= (analog2 & 0x80); + + return buttons; + } + + case 0xc41003: { + UINT8 analog = (System16VideoControl & 4) ? MjleagueTrack1Y : MjleagueTrack1X; + return ((0xff - System16Input[1]) & 0x80) | (analog & 0x7f); + } + + case 0xc41005: { + if (System16VideoControl & 4) { + return (MjleagueBat1 >> 4) | (MjleagueBat2 & 0xf0); + } else { + static UINT8 last_buttons1 = 0; + static UINT8 last_buttons2 = 0; + UINT8 buttons1 = 0xff - System16Input[1]; + UINT8 buttons2 = 0xff - System16Input[2]; + + if (!(buttons1 & 0x01)) + last_buttons1 = 0; + else if (!(buttons1 & 0x02)) + last_buttons1 = 1; + else if (!(buttons1 & 0x04)) + last_buttons1 = 2; + else if (!(buttons1 & 0x08)) + last_buttons1 = 3; + + if (!(buttons2 & 0x01)) + last_buttons2 = 0; + else if (!(buttons2 & 0x02)) + last_buttons2 = 1; + else if (!(buttons2 & 0x04)) + last_buttons2 = 2; + else if (!(buttons2 & 0x08)) + last_buttons2 = 3; + + return last_buttons1 | (last_buttons2 << 4); + } + } + + case 0xc41007: { + UINT8 analog = (System16VideoControl & 4) ? MjleagueTrack2Y : MjleagueTrack2X; + return ((0xff - System16Input[2]) & 0x80) | (analog & 0x7f); + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +UINT8 __fastcall Passsht16aReadByte(UINT32 a) +{ + static INT32 PortNum = 0; + + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + switch ((PortNum++) & 3) { + case 0: return 0xff - System16Input[1]; + case 1: return 0xff - System16Input[2]; + case 2: return 0xff - System16Input[3]; + case 3: return 0xff - System16Input[4]; + } + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc60000: { + return 0; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +UINT8 __fastcall QuartetReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return 0xff - System16Input[2]; + } + + case 0xc41007: { + return 0xff - System16Input[3]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc60000: { + return 0; + } + } + + return 0xff; +} + +static INT16 SdiTrack1X = 0; +static INT16 SdiTrack1Y = 0; +static INT16 SdiTrack2X = 0; +static INT16 SdiTrack2Y = 0; + +void SdiMakeAnalogInputs() +{ + SdiTrack1X += (System16AnalogPort0 >> 8) & 0xff; + SdiTrack1Y -= (System16AnalogPort1 >> 8) & 0xff; + + SdiTrack2X += (System16AnalogPort2 >> 8) & 0xff; + SdiTrack2Y -= (System16AnalogPort3 >> 8) & 0xff; +} + +UINT8 __fastcall SdiReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return (System16VideoControl & 4) ? SdiTrack1Y : SdiTrack1X; + } + + case 0xc41005: { + return 0xff - System16Input[1]; + } + + case 0xc41007: { + return (System16VideoControl & 4) ? SdiTrack2Y : SdiTrack2X; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc60000: { + return 0xff; + } + } + + return 0xff; +} + +static UINT8 MahjongInputNum; + +UINT16 __fastcall Sjryuko1ReadWord(UINT32 a) +{ + SEK_DEF_READ_WORD(0, a); + + return 0xffff; +} + +UINT8 __fastcall Sjryuko1ReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + if (System16Input[MahjongInputNum + 1] != 0xff) return 0xff & ~(1 << MahjongInputNum); + return 0xff; + } + + case 0xc41005: { + return 0xff - System16Input[MahjongInputNum + 1]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall Sjryuko1WriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16ATileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0xc40001: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + + case 0xc40003: { + if ((System16VideoControl ^ d) & 0xc) { + if (((System16VideoControl ^ d) & 4) && (d & 4)) MahjongInputNum = (MahjongInputNum + 1) % 6; + } + System16VideoControl = d; + System16VideoEnable = d & 0x10; + return; + } + } +} + +/*==================================================== +Driver Inits +====================================================*/ + +static INT32 AceattacaInit() +{ + System16MakeAnalogInputsDo = AceattacaMakeAnalogInputs; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, AceattacaReadByte); + SekClose(); + + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 AceattacaExit() +{ + AceattacaTrack1X = 0; + AceattacaTrack1Y = 0; + AceattacaTrack2X = 0; + AceattacaTrack2Y = 0; + AceattacaDial1 = 0; + AceattacaDial2 = 0; + + return System16Exit(); +} + +static INT32 AceattacaScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(AceattacaTrack1X); + SCAN_VAR(AceattacaTrack1Y); + SCAN_VAR(AceattacaTrack2X); + SCAN_VAR(AceattacaTrack2Y); + SCAN_VAR(AceattacaDial1); + SCAN_VAR(AceattacaDial2); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 AliensynjoInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Aliensyn5Init() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +void Bodyslam_Sim8751() +{ + UINT8 flag = ((System16Ram[0x200 + 1] << 8) | System16Ram[0x200 + 0]) >> 8; + UINT8 tick = ((System16Ram[0x200 + 1] << 8) | System16Ram[0x200 + 0]) & 0xff; + UINT8 sec = ((System16Ram[0x202 + 1] << 8) | System16Ram[0x202 + 0]) >> 8; + UINT8 min = ((System16Ram[0x202 + 1] << 8) | System16Ram[0x202 + 0]) & 0xff; + + /* out of time? set the flag */ + if (tick == 0 && sec == 0 && min == 0) + flag = 1; + else + { + if (tick != 0) + tick--; + else + { + /* the game counts 64 ticks per second */ + tick = 0x40; + + /* seconds are counted in BCD */ + if (sec != 0) + sec = (sec & 0xf) ? sec - 1 : (sec - 0x10) + 9; + else + { + sec = 0x59; + + /* minutes are counted normally */ + if (min != 0) + min--; + else + { + flag = 1; + tick = sec = min = 0; + } + } + } + } + + *((UINT16*)(System16Ram + 0x200)) = (flag << 8) + tick; + *((UINT16*)(System16Ram + 0x202)) = (sec << 8) + min; +} + +static INT32 BodyslamInit() +{ + Simulate8751 = Bodyslam_Sim8751; + + return System16Init(); +} + +static INT32 MjleagueInit() +{ + System16MakeAnalogInputsDo = MjleagueMakeAnalogInputs; + + Mjleague = true; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, MjleagueReadByte); + SekClose(); + } + + return nRet; +} + +static INT32 MjleagueExit() +{ + MjleagueTrack1X = 0; + MjleagueTrack1Y = 0; + MjleagueTrack2X = 0; + MjleagueTrack2Y = 0; + MjleagueBat1 = 0; + MjleagueBat2 = 0; + + Mjleague = false; + + return System16Exit(); +} + +static INT32 MjleagueScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(MjleagueTrack1X); + SCAN_VAR(MjleagueTrack1Y); + SCAN_VAR(MjleagueTrack2X); + SCAN_VAR(MjleagueTrack2Y); + SCAN_VAR(MjleagueBat1); + SCAN_VAR(MjleagueBat2); + } + + return System16Scan(nAction, pnMin);; +} + +void Quartet_Sim8751() +{ + // X-Scroll Values + *((UINT16*)(System16TextRam + 0xff8)) = ((System16Ram[0x0d14 + 1] << 8) | System16Ram[0x0d14 + 0]); + *((UINT16*)(System16TextRam + 0xffa)) = ((System16Ram[0x0d18 + 1] << 8) | System16Ram[0x0d18 + 0]); + + // Page Values + *((UINT16*)(System16TextRam + 0xe9e)) = ((System16Ram[0x0d1c + 1] << 8) | System16Ram[0x0d1c + 0]); + *((UINT16*)(System16TextRam + 0xe9c)) = ((System16Ram[0x0d1e + 1] << 8) | System16Ram[0x0d1e + 0]); +} + +static INT32 Passsht16aInit() +{ + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x70000 - 0x60000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, Passsht16aReadByte); + SekClose(); + + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 QuartetInit() +{ + Simulate8751 = Quartet_Sim8751; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, QuartetReadByte); + SekClose(); + } + + return nRet; +} + +static INT32 SdiInit() +{ + System16MakeAnalogInputsDo = SdiMakeAnalogInputs; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x70000 - 0x60000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, SdiReadByte); + SekClose(); + + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 SdiExit() +{ + SdiTrack1X = 0; + SdiTrack1Y = 0; + SdiTrack2X = 0; + SdiTrack2Y = 0; + + return System16Exit(); +} + +static INT32 SdiScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(SdiTrack1X); + SCAN_VAR(SdiTrack1Y); + SCAN_VAR(SdiTrack2X); + SCAN_VAR(SdiTrack2Y); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 ShinobiInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Sjryuko1Init() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetWriteByteHandler(0, Sjryuko1WriteByte); + SekSetReadByteHandler(0, Sjryuko1ReadByte); + SekSetReadWordHandler(0, Sjryuko1ReadWord); + SekClose(); + + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Sjryuko1Exit() +{ + MahjongInputNum = 0; + + return System16Exit(); +} + +static INT32 Sjryuko1Scan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(MahjongInputNum); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 Wb31Init() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + // Handle different sprite rom layout + UINT8 *pTemp = (UINT8*)malloc(System16SpriteRomSize); + if (pTemp) { + memcpy(pTemp, System16Sprites, System16SpriteRomSize); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x40000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x60000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x50000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x70000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +/*==================================================== +Driver defs +====================================================*/ + +struct BurnDriver BurnDrvAceattaca = { + "aceattaca", "aceattac", NULL, NULL, "1986", + "Ace Attacker (Japan, System 16A, FD1094 317-0060)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, AceattacaRomInfo, AceattacaRomName, NULL, NULL, AceattacaInputInfo, AceattacaDIPInfo, + AceattacaInit, AceattacaExit, System16AFrame, NULL, AceattacaScan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAFighter = { + "afighter", NULL, NULL, NULL, "1986", + "Action Fighter, FD1089A 317-0018\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089A_ENC, GBF_RACING, 0, + NULL, AfighterRomInfo, AfighterRomName, NULL, NULL, System16aInputInfo, AfighterDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAlexkidd = { + "alexkidd", NULL, NULL, NULL, "1986", + "Alex Kidd: The Lost Stars (set 2, unprotected)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, AlexkiddRomInfo, AlexkiddRomName, NULL, NULL, System16aInputInfo, AlexkiddDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAlexkidd1 = { + "alexkidd1", "alexkidd", NULL, NULL, "1986", + "Alex Kidd: The Lost Stars (set 1, FD1089A 317-unknown)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089A_ENC, GBF_PLATFORM, 0, + NULL, Alexkidd1RomInfo, Alexkidd1RomName, NULL, NULL, System16aInputInfo, AlexkiddDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAliensynjo = { + "aliensynjo", "aliensyn", NULL, NULL, "1987", + "Alien Syndrome (set 1, Japan, old, System 16A, FD1089A 317-0033)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089A_ENC, GBF_MAZE, 0, + NULL, AliensynjoRomInfo, AliensynjoRomName, NULL, NULL, System16afire1InputInfo, AliensynDIPInfo, + AliensynjoInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAliensyn2 = { + "aliensyn2", "aliensyn", NULL, NULL, "1987", + "Alien Syndrome (set 2, System 16A, FD1089A 317-0033)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089A_ENC, GBF_MAZE, 0, + NULL, Aliensyn2RomInfo, Aliensyn2RomName, NULL, NULL, System16afire1InputInfo, AliensynDIPInfo, + AliensynjoInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAliensyn5 = { + "aliensyn5", "aliensyn", NULL, NULL, "1987", + "Alien Syndrome (set 5, System 16A, FD1089B 317-0037)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089B_ENC, GBF_MAZE, 0, + NULL, Aliensyn5RomInfo, Aliensyn5RomName, NULL, NULL, System16afire1InputInfo, AliensynDIPInfo, + Aliensyn5Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBodyslam = { + "bodyslam", NULL, NULL, NULL, "1986", + "Body Slam (8751 317-0015)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A, GBF_VSFIGHT, 0, + NULL, BodyslamRomInfo, BodyslamRomName, NULL, NULL, System16aInputInfo, BodyslamDIPInfo, + BodyslamInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDumpmtmt = { + "dumpmtmt", "bodyslam", NULL, NULL, "1986", + "Dump Matsumoto (Japan, 8751 317-unknown)\0", NULL, "Sega", "System 16A", + L"Dump Matsumoto (Japan, 8751 317-unknown)\0\u30C0\u30F3\u30D7\u677E\u672C\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A, GBF_VSFIGHT, 0, + NULL, DumpmtmtRomInfo, DumpmtmtRomName, NULL, NULL, System16aInputInfo, BodyslamDIPInfo, + BodyslamInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantzone = { + "fantzone", NULL, NULL, NULL, "1986", + "Fantasy Zone (Rev A, unprotected)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A, GBF_HORSHOOT, 0, + NULL, FantzoneRomInfo, FantzoneRomName, NULL, NULL, System16aInputInfo, FantzoneDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantzone1 = { + "fantzone1", "fantzone", NULL, NULL, "1986", + "Fantasy Zone (unprotected)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A, GBF_HORSHOOT, 0, + NULL, Fantzone1RomInfo, Fantzone1RomName, NULL, NULL, System16aInputInfo, FantzoneDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantzonep = { + "fantzonep", "fantzone", NULL, NULL, "1986", + "Fantasy Zone (317-5000)\0", "No sound - encrypted Z80", "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A, GBF_HORSHOOT, 0, + NULL, FantzonepRomInfo, FantzonepRomName, NULL, NULL, System16aInputInfo, FantzoneDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMjleague = { + "mjleague", NULL, NULL, NULL, "1985", + "Major League\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16A, GBF_SPORTSMISC, 0, + NULL, MjleagueRomInfo, MjleagueRomName, NULL, NULL, MjleagueInputInfo, MjleagueDIPInfo, + MjleagueInit, MjleagueExit, System16AFrame, NULL, MjleagueScan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvPasssht16a = { + "passsht16a", "passsht", NULL, NULL, "1988", + "Passing Shot (Japan, 4 Players, System 16A, FD1094 317-0071)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 4, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, Passsht16aRomInfo, Passsht16aRomName, NULL, NULL, Passsht16aInputInfo, Passsht16aDIPInfo, + Passsht16aInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvQuartet = { + "quartet", NULL, NULL, NULL, "1986", + "Quartet (Rev A, 8751 317-unknown)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, QuartetRomInfo, QuartetRomName, NULL, NULL, QuartetInputInfo, QuartetDIPInfo, + QuartetInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQuarteta = { + "quarteta", "quartet", NULL, NULL, "1986", + "Quartet (8751 315-5194)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, QuartetaRomInfo, QuartetaRomName, NULL, NULL, QuartetInputInfo, QuartetDIPInfo, + QuartetInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQuartet2 = { + "quartet2", "quartet", NULL, NULL, "1986", + "Quartet 2 (8751 317-0010)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, Quartet2RomInfo, Quartet2RomName, NULL, NULL, System16aInputInfo, Quart2DIPInfo, + QuartetInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQuartet2a = { + "quartet2a", "quartet", NULL, NULL, "1986", + "Quartet 2 (unprotected)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, Quartet2aRomInfo, Quartet2aRomName, NULL, NULL, System16aInputInfo, Quart2DIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSdi = { + "sdi", NULL, NULL, NULL, "1987", + "SDI - Strategic Defense Initiative (Japan, old, System 16A, FD1089B 317-0027)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089B_ENC, GBF_SHOOT, 0, + NULL, SdiRomInfo, SdiRomName, NULL, NULL, SdiInputInfo, SdiDIPInfo, + SdiInit, SdiExit, System16AFrame, NULL, SdiScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi = { + "shinobi", NULL, NULL, NULL, "1987", + "Shinobi (set 6, System 16A, unprotected)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, ShinobiRomInfo, ShinobiRomName, NULL, NULL, System16afire3InputInfo, ShinobiDIPInfo, + ShinobiInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi1 = { + "shinobi1", "shinobi", NULL, NULL, "1987", + "Shinobi (set 1, System 16A, FD1094 317-0050)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Shinobi1RomInfo, Shinobi1RomName, NULL, NULL, System16afire3InputInfo, ShinobiDIPInfo, + ShinobiInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobls = { + "shinobls", "shinobi", NULL, NULL, "1987", + "Shinobi (Star bootleg, System 16A)\0", NULL, "bootleg", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, ShinoblsRomInfo, ShinoblsRomName, NULL, NULL, System16afire3InputInfo, ShinobiDIPInfo, + ShinobiInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinoblb = { + "shinoblb", "shinobi", NULL, NULL, "1987", + "Shinobi (beta bootleg, System 16A)\0", NULL, "bootleg", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16A, GBF_PLATFORM, 0, + NULL, ShinoblbRomInfo, ShinoblbRomName, NULL, NULL, System16afire3InputInfo, ShinobiDIPInfo, + ShinobiInit, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSjryuko1 = { + "sjryuko1", "sjryuko", NULL, NULL, "1987", + "Sukeban Jansi Ryuko (set 1, System 16A, FD1089B 317-5021)\0", NULL, "White Board", "System 16A", + L"Sukeban Jansi Ryuko (set 1, System 16A, FD1089B 317-5021)\0\u30B9\u30B1\u30D0\u30F3\u96C0\u58EB \u7ADC\u5B50\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089B_ENC, GBF_MAHJONG, 0, + NULL, Sjryuko1RomInfo, Sjryuko1RomName, NULL, NULL, Sjryuko1InputInfo, Sjryuko1DIPInfo, + Sjryuko1Init, Sjryuko1Exit, System16AFrame, NULL, Sjryuko1Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetris = { + "tetris", NULL, NULL, NULL, "1988", + "Tetris (set 4, Japan, System 16A, FD1094 317-0093)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, TetrisRomInfo, TetrisRomName, NULL, NULL, System16afire1InputInfo, TetrisDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetris3 = { + "tetris3", "tetris", NULL, NULL, "1988", + "Tetris (set 3, Japan, System 16A, FD1094 317-0093a)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, Tetris3RomInfo, Tetris3RomName, NULL, NULL, System16afire1InputInfo, TetrisDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTimescan1 = { + "timescan1", "timescan", NULL, NULL, "1987", + "Time Scanner (set 1, System 16A, FD1089B 317-0024)\0", NULL, "Sega", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1089B_ENC, GBF_PINBALL, 0, + NULL, Timescan1RomInfo, Timescan1RomName, NULL, NULL, System16aDip3InputInfo, TimescanDIPInfo, + System16Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvWb31 = { + "wb31", "wb3", NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (set 1, System 16A, FD1094 317-0084)\0", NULL, "Sega / Westone", "System 16A", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16A | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Wb31RomInfo, Wb31RomName, NULL, NULL, System16aInputInfo, Wb31DIPInfo, + Wb31Init, System16Exit, System16AFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_sys16b.cpp b/src/burn/drivers/sega/d_sys16b.cpp new file mode 100644 index 00000000..789d3f75 --- /dev/null +++ b/src/burn/drivers/sega/d_sys16b.cpp @@ -0,0 +1,9156 @@ +#include "sys16.h" + +/*==================================================== +Input defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo System16bInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16b) + +static struct BurnInputInfo System16bfire1InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16bfire1) + +static struct BurnInputInfo System16bfire3InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16bfire3) + +static struct BurnInputInfo System16bfire4InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , System16InputPort1 + 3, "p1 fire 4" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , System16InputPort2 + 3, "p2 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System16bfire4) + +static struct BurnInputInfo System16bDip3InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH, System16Dip + 2 , "dip" }, +}; + +STDINPUTINFO(System16bDip3) + +static struct BurnInputInfo AtomicpInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort1 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort1 + 6, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Atomicp) + +static struct BurnInputInfo BulletInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort0 + 7, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 6, "p3 start" }, + + {"P1 Up 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 up" }, + {"P1 Down 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 down" }, + {"P1 Left 1" , BIT_DIGITAL , System16InputPort1 + 3, "p1 left" }, + {"P1 Right 1" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + {"P1 Up 2" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up 2" }, + {"P1 Down 2" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down 2" }, + {"P1 Left 2" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left 2" }, + {"P1 Right 2" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right 2"}, + + {"P2 Up 1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 up" }, + {"P2 Down 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 down" }, + {"P2 Left 1" , BIT_DIGITAL , System16InputPort2 + 3, "p2 left" }, + {"P2 Right 1" , BIT_DIGITAL , System16InputPort2 + 2, "p2 right" }, + {"P2 Up 2" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up 2" }, + {"P2 Down 2" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down 2" }, + {"P2 Left 2" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left 2" }, + {"P2 Right 2" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right 2"}, + + {"P3 Up 1" , BIT_DIGITAL , System16InputPort3 + 1, "p3 up" }, + {"P3 Down 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 down" }, + {"P3 Left 1" , BIT_DIGITAL , System16InputPort3 + 3, "p3 left" }, + {"P3 Right 1" , BIT_DIGITAL , System16InputPort3 + 2, "p3 right" }, + {"P3 Up 2" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up 2" }, + {"P3 Down 2" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down 2" }, + {"P3 Left 2" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left 2" }, + {"P3 Right 2" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right 2"}, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Bullet) + +static struct BurnInputInfo DunkshotInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 6, "p3 start" }, + {"Start 4" , BIT_DIGITAL , System16InputPort0 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort2 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort2 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort2 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort2 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 6, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 7, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 4, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 5, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort1 + 2, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort1 + 3, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 2, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 3, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 0, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 1, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort1 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort1 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , System16InputPort3 + 6, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , System16InputPort3 + 7, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , System16InputPort3 + 4, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , System16InputPort3 + 5, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , System16InputPort1 + 6, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , System16InputPort1 + 7, "p4 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Dunkshot) + +static struct BurnInputInfo ExctleagInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort4 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort4 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort4 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort4 + 1, "p1 right" }, + {"P1 Bant0" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Bant1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Bant2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + {"P1 Swing0" , BIT_DIGITAL , System16InputPort1 + 3, "p1 fire 4" }, + {"P1 Swing1" , BIT_DIGITAL , System16InputPort1 + 4, "p1 fire 5" }, + {"P1 Low" , BIT_DIGITAL , System16InputPort1 + 5, "p1 fire 6" }, + {"P1 Mid" , BIT_DIGITAL , System16InputPort1 + 6, "p1 fire 7" }, + {"P1 Hi" , BIT_DIGITAL , System16InputPort1 + 7, "p1 fire 8" }, + {"P1 Change" , BIT_DIGITAL , System16InputPort3 + 1, "p1 fire 9" }, + {"P1 Select" , BIT_DIGITAL , System16InputPort3 + 2, "p1 fire 10" }, + {"P1 Chase" , BIT_DIGITAL , System16InputPort3 + 0, "p1 fire 11" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort4 + 6, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort4 + 7, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort4 + 4, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort4 + 5, "p2 right" }, + {"P2 Bant0" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Bant1" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Bant2" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + {"P2 Swing0" , BIT_DIGITAL , System16InputPort2 + 3, "p2 fire 4" }, + {"P2 Swing1" , BIT_DIGITAL , System16InputPort2 + 4, "p2 fire 5" }, + {"P2 Low" , BIT_DIGITAL , System16InputPort2 + 5, "p2 fire 6" }, + {"P2 Mid" , BIT_DIGITAL , System16InputPort2 + 6, "p2 fire 7" }, + {"P2 Hi" , BIT_DIGITAL , System16InputPort2 + 7, "p2 fire 8" }, + {"P2 Change" , BIT_DIGITAL , System16InputPort3 + 5, "p2 fire 9" }, + {"P2 Select" , BIT_DIGITAL , System16InputPort3 + 6, "p2 fire 10" }, + {"P2 Chase" , BIT_DIGITAL , System16InputPort3 + 4, "p2 fire 11" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Exctleag) + +static struct BurnInputInfo FpointblInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Fpointbl) + +static struct BurnInputInfo HwchampInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Left" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Right" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Hwchamp) + +static struct BurnInputInfo PassshtInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 6, "p3 start" }, + {"Start 4" , BIT_DIGITAL , System16InputPort0 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 1, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 0, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 6, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , System16InputPort1 + 7, "p1 fire 4" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 1, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 0, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 2, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 6, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , System16InputPort2 + 7, "p2 fire 4" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 1, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 0, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 3, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 2, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 5, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , System16InputPort3 + 6, "p3 fire 3" }, + {"P3 Fire 4" , BIT_DIGITAL , System16InputPort3 + 7, "p3 fire 4" }, + + {"P4 Up" , BIT_DIGITAL , System16InputPort4 + 1, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , System16InputPort4 + 0, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , System16InputPort4 + 3, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , System16InputPort4 + 2, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , System16InputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , System16InputPort4 + 5, "p4 fire 2" }, + {"P4 Fire 3" , BIT_DIGITAL , System16InputPort4 + 6, "p4 fire 3" }, + {"P4 Fire 4" , BIT_DIGITAL , System16InputPort4 + 7, "p4 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Passsht) + +static struct BurnInputInfo RyukyuInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Ryukyu) + +static struct BurnInputInfo SdiInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 1, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 0, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + A("Target Left/Right", BIT_ANALOG_REL, &System16AnalogPort0, "mouse x-axis" ), + A("Target Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 6, "mouse button 1"}, + + {"P2 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p2 right" }, + A("Target Left/Right", BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("Target Up/Down" , BIT_ANALOG_REL, &System16AnalogPort3, "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort0 + 7, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Sdi) + +static struct BurnInputInfo SjryukoInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + + {"Mahjong A" , BIT_DIGITAL , System16InputPort1 + 0, "mah a" }, + {"Mahjong B" , BIT_DIGITAL , System16InputPort1 + 1, "mah b" }, + {"Mahjong C" , BIT_DIGITAL , System16InputPort1 + 2, "mah c" }, + {"Mahjong D" , BIT_DIGITAL , System16InputPort1 + 3, "mah d" }, + {"Mahjong E" , BIT_DIGITAL , System16InputPort2 + 0, "mah e" }, + {"Mahjong F" , BIT_DIGITAL , System16InputPort2 + 1, "mah f" }, + {"Mahjong G" , BIT_DIGITAL , System16InputPort2 + 2, "mah g" }, + {"Mahjong H" , BIT_DIGITAL , System16InputPort2 + 3, "mah h" }, + {"Mahjong I" , BIT_DIGITAL , System16InputPort3 + 0, "mah i" }, + {"Mahjong J" , BIT_DIGITAL , System16InputPort3 + 1, "mah j" }, + {"Mahjong K" , BIT_DIGITAL , System16InputPort3 + 2, "mah k" }, + {"Mahjong L" , BIT_DIGITAL , System16InputPort3 + 3, "mah l" }, + {"Mahjong M" , BIT_DIGITAL , System16InputPort4 + 0, "mah m" }, + {"Mahjong N" , BIT_DIGITAL , System16InputPort4 + 1, "mah n" }, + {"Mahjong Kan" , BIT_DIGITAL , System16InputPort6 + 0, "mah kan" }, + {"Mahjong Pon" , BIT_DIGITAL , System16InputPort4 + 3, "mah pon" }, + {"Mahjong Chi" , BIT_DIGITAL , System16InputPort4 + 2, "mah chi" }, + {"Mahjong Reach" , BIT_DIGITAL , System16InputPort6 + 1, "mah reach" }, + {"Mahjong Ron" , BIT_DIGITAL , System16InputPort6 + 2, "mah ron" }, + {"Mahjong Bet" , BIT_DIGITAL , System16InputPort5 + 1, "mah bet" }, + {"Mahjong Last Chance", BIT_DIGITAL , System16InputPort1 + 4, "mah lc" }, + {"Mahjong Score" , BIT_DIGITAL , System16InputPort5 + 0, "mah score" }, + {"Mahjong Flip Flop" , BIT_DIGITAL , System16InputPort4 + 4, "mah ff" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Sjryuko) + +static struct BurnInputInfo SnapperInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort1 + 1, "p1 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort0 + 6, "p1 fire 3" }, + + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Snapper) + +#undef A + +/*==================================================== +Dip defs +====================================================*/ + +#define SYSTEM16B_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo AliensynDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfd, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x08, "2" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x00, "127" }, + + {0 , 0xfe, 0 , 4 , "Timer" }, + {0x11, 0x01, 0x30, 0x00, "120" }, + {0x11, 0x01, 0x30, 0x10, "130" }, + {0x11, 0x01, 0x30, 0x20, "140" }, + {0x11, 0x01, 0x30, 0x30, "150" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0xc0, 0x80, "Easy" }, + {0x11, 0x01, 0xc0, 0xc0, "Normal" }, + {0x11, 0x01, 0xc0, 0x40, "Hard" }, + {0x11, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x12) +}; + +STDDIPINFO(Aliensyn) + +static struct BurnDIPInfo AliensynjDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfd, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0x0c, 0x08, "2" }, + {0x11, 0x01, 0x0c, 0x0c, "3" }, + {0x11, 0x01, 0x0c, 0x04, "4" }, + {0x11, 0x01, 0x0c, 0x00, "127" }, + + {0 , 0xfe, 0 , 4 , "Timer" }, + {0x11, 0x01, 0x30, 0x00, "150" }, + {0x11, 0x01, 0x30, 0x10, "160" }, + {0x11, 0x01, 0x30, 0x20, "170" }, + {0x11, 0x01, 0x30, 0x30, "180" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0xc0, 0x80, "Easy" }, + {0x11, 0x01, 0xc0, 0xc0, "Normal" }, + {0x11, 0x01, 0xc0, 0x40, "Hard" }, + {0x11, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x12) +}; + +STDDIPINFO(Aliensynj) + +static struct BurnDIPInfo AltbeastDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Credits needed" }, + {0x15, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x15, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x08, "2" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x04, "4" }, + {0x15, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Energy Meter" }, + {0x15, 0x01, 0x30, 0x20, "2" }, + {0x15, 0x01, 0x30, 0x30, "3" }, + {0x15, 0x01, 0x30, 0x10, "4" }, + {0x15, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0xc0, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Altbeast) + +static struct BurnDIPInfo AtomicpDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0x2f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x11, 0x01, 0x38, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x38, 0x20, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x38, 0x18, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x38, 0x38, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x38, 0x10, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x38, 0x28, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x38, 0x08, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x38, 0x30, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 8 , "Coin B" }, + {0x11, 0x01, 0x07, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x07, 0x04, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x07, 0x03, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x07, 0x02, "1 Coin 2 Credits" }, + {0x11, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x11, 0x01, 0x07, 0x01, "1 Coin 4 Credits" }, + {0x11, 0x01, 0x07, 0x06, "1 Coin 5 Credits" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x11, 0x01, 0xc0, 0xc0, "1" }, + {0x11, 0x01, 0xc0, 0x80, "2" }, + {0x11, 0x01, 0xc0, 0x40, "3" }, + {0x11, 0x01, 0xc0, 0x00, "5" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x01, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Normal" }, + {0x12, 0x01, 0x03, 0x02, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Level Select" }, + {0x12, 0x01, 0x04, 0x04, "Off" }, + {0x12, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x12, 0x01, 0x08, 0x08, "Off" }, + {0x12, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x10, 0x10, "Off" }, + {0x12, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x20, 0x00, "Off" }, + {0x12, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Mode" }, + {0x12, 0x01, 0x40, 0x40, "Normal Tetris" }, + {0x12, 0x01, 0x40, 0x00, "Atomic Point" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x12, 0x01, 0x80, 0x00, "Off" }, + {0x12, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Atomicp) + +static struct BurnDIPInfo AurailDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x15, 0x01, 0x01, 0x01, "Upright" }, + {0x15, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x00, "2" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x08, "4" }, + {0x15, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x15, 0x01, 0x10, 0x10, "80k, 200k, 500k, 1000k" }, + {0x15, 0x01, 0x10, 0x00, "100k, 300k, 700k, 1000k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x15, 0x01, 0x20, 0x20, "Normal" }, + {0x15, 0x01, 0x20, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Controller Select" }, + {0x15, 0x01, 0x40, 0x40, "1 Player Side" }, + {0x15, 0x01, 0x40, 0x00, "2 Players Side" }, + + {0 , 0xfe, 0 , 2 , "Special Function Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Aurail) + +static struct BurnDIPInfo BayrouteDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x01, 0x00, "Off" }, + {0x15, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x04, "1" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x08, "5" }, + {0x15, 0x01, 0x0c, 0x00, "Unlimited" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x30, 0x30, "100000" }, + {0x15, 0x01, 0x30, 0x20, "150000" }, + {0x15, 0x01, 0x30, 0x10, "200000" }, + {0x15, 0x01, 0x30, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0xc0, "Easy" }, + {0x15, 0x01, 0xc0, 0x80, "Normal" }, + {0x15, 0x01, 0xc0, 0x40, "Hard" }, + {0x15, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Bayroute) + +static struct BurnDIPInfo Blox16bDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, +}; + +STDDIPINFO(Blox16b) + +static struct BurnDIPInfo BulletDIPList[]= +{ + // Default Values + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + + // Dip 2 + SYSTEM16B_COINAGE(0x22) +}; + +STDDIPINFO(Bullet) + +static struct BurnDIPInfo CottonDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x06, 0x04, "2" }, + {0x13, 0x01, 0x06, 0x06, "3" }, + {0x13, 0x01, 0x06, 0x02, "4" }, + {0x13, 0x01, 0x06, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x18, 0x10, "Easy" }, + {0x13, 0x01, 0x18, 0x18, "Normal" }, + {0x13, 0x01, 0x18, 0x08, "Hard" }, + {0x13, 0x01, 0x18, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Cotton) + +static struct BurnDIPInfo DduxDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0x06, 0x04, "Easy" }, + {0x13, 0x01, 0x06, 0x06, "Normal" }, + {0x13, 0x01, 0x06, 0x02, "Hard" }, + {0x13, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x18, 0x10, "2" }, + {0x13, 0x01, 0x18, 0x18, "3" }, + {0x13, 0x01, 0x18, 0x08, "4" }, + {0x13, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x60, 0x40, "150000" }, + {0x13, 0x01, 0x60, 0x60, "200000" }, + {0x13, 0x01, 0x60, 0x20, "300000" }, + {0x13, 0x01, 0x60, 0x00, "400000" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Ddux) + +static struct BurnDIPInfo DunkshotDIPList[]= +{ + // Default Values + {0x21, 0xff, 0xff, 0xfd, NULL }, + {0x22, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x21, 0x01, 0x02, 0x02, "Off" }, + {0x21, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "VS Time" }, + {0x21, 0x01, 0x0c, 0x08, "2P 1:30 | 3P 2:00 | 4P 2:30" }, + {0x21, 0x01, 0x0c, 0x0c, "2P 2:00 | 3P 2:30 | 4P 3:00" }, + {0x21, 0x01, 0x0c, 0x04, "2P 2:30 | 3P 3:00 | 4P 3:30" }, + {0x21, 0x01, 0x0c, 0x00, "2P 3:00 | 3P 3:30 | 4P 4:00" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x21, 0x01, 0x30, 0x20, "Easy" }, + {0x21, 0x01, 0x30, 0x30, "Normal" }, + {0x21, 0x01, 0x30, 0x10, "Hard" }, + {0x21, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "CPU starts with +6 pts" }, + {0x21, 0x01, 0x40, 0x40, "Off" }, + {0x21, 0x01, 0x40, 0x00, "On" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x22) +}; + +STDDIPINFO(Dunkshot) + +static struct BurnDIPInfo EswatDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x15, 0x01, 0x08, 0x08, "Normal" }, + {0x15, 0x01, 0x08, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x30, 0x20, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0xc0, 0x00, "1" }, + {0x15, 0x01, 0xc0, 0x40, "2" }, + {0x15, 0x01, 0xc0, 0xc0, "3" }, + {0x15, 0x01, 0xc0, 0x80, "4" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Eswat) + +static struct BurnDIPInfo ExctleagDIPList[]= +{ + // Default Values + {0x25, 0xff, 0xff, 0xfe, NULL }, + {0x26, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x25, 0x01, 0x01, 0x01, "Off" }, + {0x25, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Starting Points" }, + {0x25, 0x01, 0x0e, 0x06, "2000" }, + {0x25, 0x01, 0x0e, 0x0a, "3000" }, + {0x25, 0x01, 0x0e, 0x0c, "4000" }, + {0x25, 0x01, 0x0e, 0x0e, "5000" }, + {0x25, 0x01, 0x0e, 0x08, "6000" }, + {0x25, 0x01, 0x0e, 0x04, "7000" }, + {0x25, 0x01, 0x0e, 0x02, "8000" }, + {0x25, 0x01, 0x0e, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x25, 0x01, 0x30, 0x20, "Easy" }, + {0x25, 0x01, 0x30, 0x30, "Normal" }, + {0x25, 0x01, 0x30, 0x10, "Hard" }, + {0x25, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Point Table" }, + {0x25, 0x01, 0xc0, 0x80, "Easy" }, + {0x25, 0x01, 0xc0, 0xc0, "Normal" }, + {0x25, 0x01, 0xc0, 0x40, "Hard" }, + {0x25, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 1 + SYSTEM16B_COINAGE(0x26) +}; + +STDDIPINFO(Exctleag) + +static struct BurnDIPInfo Fantzn2xDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, +}; + +STDDIPINFO(Fantzn2x) + +static struct BurnDIPInfo FpointDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfd, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x30, 0x20, "Easy" }, + {0x11, 0x01, 0x30, 0x30, "Normal" }, + {0x11, 0x01, 0x30, 0x10, "Hard" }, + {0x11, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Clear Round Allowed" }, + {0x11, 0x01, 0x40, 0x00, "1" }, + {0x11, 0x01, 0x40, 0x40, "2" }, + + {0 , 0xfe, 0 , 2 , "Cell Move" }, + {0x11, 0x01, 0x80, 0x00, "Off" }, + {0x11, 0x01, 0x80, 0x80, "On" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x12) +}; + +STDDIPINFO(Fpoint) + +static struct BurnDIPInfo GoldnaxeDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Credits needed" }, + {0x15, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x15, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x08, "1" }, + {0x15, 0x01, 0x0c, 0x0c, "2" }, + {0x15, 0x01, 0x0c, 0x04, "3" }, + {0x15, 0x01, 0x0c, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Energy Meter" }, + {0x15, 0x01, 0x30, 0x20, "2" }, + {0x15, 0x01, 0x30, 0x30, "3" }, + {0x15, 0x01, 0x30, 0x10, "4" }, + {0x15, 0x01, 0x30, 0x00, "5" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Goldnaxe) + +static struct BurnDIPInfo HwchampDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xf9, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Start Level Select" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x08, 0x08, "Off" }, + {0x0a, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0x30, 0x20, "Easy" }, + {0x0a, 0x01, 0x30, 0x30, "Normal" }, + {0x0a, 0x01, 0x30, 0x10, "Hard" }, + {0x0a, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x0a, 0x01, 0xc0, 0x80, "Easy" }, + {0x0a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0a, 0x01, 0xc0, 0x40, "Hard" }, + {0x0a, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x0b) +}; + +STDDIPINFO(Hwchamp) + +static struct BurnDIPInfo MvpDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Credits Needed" }, + {0x15, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x15, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Innings" }, + {0x15, 0x01, 0x04, 0x04, "1 Credit 1 Inning Only" }, + {0x15, 0x01, 0x04, 0x0c, "+2 Credits 3 Innings" }, + + {0 , 0xfe, 0 , 8 , "Time Limits" }, + {0x15, 0x01, 0x38, 0x18, "Easy" }, + {0x15, 0x01, 0x38, 0x28, "Easy 2" }, + {0x15, 0x01, 0x38, 0x08, "Easy 3" }, + {0x15, 0x01, 0x38, 0x38, "Normal" }, + {0x15, 0x01, 0x38, 0x30, "Hard" }, + {0x15, 0x01, 0x38, 0x10, "Hard 2" }, + {0x15, 0x01, 0x38, 0x20, "Hard 3" }, + {0x15, 0x01, 0x38, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0xc0, 0x80, "Easy" }, + {0x15, 0x01, 0xc0, 0x40, "Easy 2" }, + {0x15, 0x01, 0xc0, 0xc0, "Normal" }, + {0x15, 0x01, 0xc0, 0x30, "Hard" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Mvp) + +static struct BurnDIPInfo PassshtDIPList[]= +{ + // Default Values + {0x17, 0xff, 0xff, 0xf0, NULL }, + {0x18, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Initial Point" }, + {0x17, 0x01, 0x0e, 0x06, "2000" }, + {0x17, 0x01, 0x0e, 0x0a, "3000" }, + {0x17, 0x01, 0x0e, 0x0c, "4000" }, + {0x17, 0x01, 0x0e, 0x0e, "5000" }, + {0x17, 0x01, 0x0e, 0x08, "6000" }, + {0x17, 0x01, 0x0e, 0x04, "7000" }, + {0x17, 0x01, 0x0e, 0x02, "8000" }, + {0x17, 0x01, 0x0e, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Point Table" }, + {0x17, 0x01, 0x30, 0x20, "Easy" }, + {0x17, 0x01, 0x30, 0x30, "Normal" }, + {0x17, 0x01, 0x30, 0x10, "Hard" }, + {0x17, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0xc0, 0x80, "Easy" }, + {0x17, 0x01, 0xc0, 0xc0, "Normal" }, + {0x17, 0x01, 0xc0, 0x40, "Hard" }, + {0x17, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x18) +}; + +STDDIPINFO(Passsht) + + +static struct BurnDIPInfo PassshtaDIPList[]= +{ + // Default Values + {0x29, 0xff, 0xff, 0xf0, NULL }, + {0x2a, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x29, 0x01, 0x01, 0x01, "Off" }, + {0x29, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Initial Point" }, + {0x29, 0x01, 0x0e, 0x06, "2000" }, + {0x29, 0x01, 0x0e, 0x0a, "3000" }, + {0x29, 0x01, 0x0e, 0x0c, "4000" }, + {0x29, 0x01, 0x0e, 0x0e, "5000" }, + {0x29, 0x01, 0x0e, 0x08, "6000" }, + {0x29, 0x01, 0x0e, 0x04, "7000" }, + {0x29, 0x01, 0x0e, 0x02, "8000" }, + {0x29, 0x01, 0x0e, 0x00, "9000" }, + + {0 , 0xfe, 0 , 4 , "Point Table" }, + {0x29, 0x01, 0x30, 0x20, "Easy" }, + {0x29, 0x01, 0x30, 0x30, "Normal" }, + {0x29, 0x01, 0x30, 0x10, "Hard" }, + {0x29, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x29, 0x01, 0xc0, 0x80, "Easy" }, + {0x29, 0x01, 0xc0, 0xc0, "Normal" }, + {0x29, 0x01, 0xc0, 0x40, "Hard" }, + {0x29, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x2a) +}; + +STDDIPINFO(Passshta) + +static struct BurnDIPInfo RiotcityDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x13, 0x01, 0x01, 0x01, "Off" }, + {0x13, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x0c, 0x00, "1" }, + {0x13, 0x01, 0x0c, 0x0c, "2" }, + {0x13, 0x01, 0x0c, 0x08, "3" }, + {0x13, 0x01, 0x0c, 0x04, "4" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x30, 0x20, "Easy" }, + {0x13, 0x01, 0x30, 0x30, "Normal" }, + {0x13, 0x01, 0x30, 0x10, "Hard" }, + {0x13, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x13, 0x01, 0x40, 0x40, "Normal" }, + {0x13, 0x01, 0x40, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Attack button to start" }, + {0x13, 0x01, 0x80, 0x80, "Off" }, + {0x13, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Riotcity) + +static struct BurnDIPInfo RyukyuDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xf8, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x01, 0x01, "Off" }, + {0x0d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Cancel per credit" }, + {0x0d, 0x01, 0x02, 0x00, "2" }, + {0x0d, 0x01, 0x02, 0x02, "3" }, + + {0 , 0xfe, 0 , 2 , "Timer Speed" }, + {0x0d, 0x01, 0x04, 0x04, "20 seconds" }, + {0x0d, 0x01, 0x04, 0x00, "30 seconds" }, + + {0 , 0xfe, 0 , 2 , "PCM Voice" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Omikuji Difficulty" }, + {0x0d, 0x01, 0x30, 0x20, "Easy" }, + {0x0d, 0x01, 0x30, 0x30, "Normal" }, + {0x0d, 0x01, 0x30, 0x10, "Hard" }, + {0x0d, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0d, 0x01, 0xc0, 0x80, "Easy" }, + {0x0d, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0d, 0x01, 0xc0, 0x40, "Hard" }, + {0x0d, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x0e) +}; + +STDDIPINFO(Ryukyu) + +static struct BurnDIPInfo SdibDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfd, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x01, 0x01, "No" }, + {0x15, 0x01, 0x01, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x08, "2" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x04, "4" }, + {0x15, 0x01, 0x0c, 0x00, "Free" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x30, 0x20, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0xc0, 0x80, "Every 50000" }, + {0x15, 0x01, 0xc0, 0xc0, "50000" }, + {0x15, 0x01, 0xc0, 0x40, "100000" }, + {0x15, 0x01, 0xc0, 0x00, "None" }, + + // Dip 1 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Sdib) + +static struct BurnDIPInfo ShinobiDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfc, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x15, 0x01, 0x01, 0x00, "Upright" }, + {0x15, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x0c, 0x08, "2" }, + {0x15, 0x01, 0x0c, 0x0c, "3" }, + {0x15, 0x01, 0x0c, 0x04, "5" }, + {0x15, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x30, 0x20, "Easy" }, + {0x15, 0x01, 0x30, 0x30, "Normal" }, + {0x15, 0x01, 0x30, 0x10, "Hard" }, + {0x15, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Enemy Bullet Speed" }, + {0x15, 0x01, 0x40, 0x40, "Slow" }, + {0x15, 0x01, 0x40, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x15, 0x01, 0x80, 0x80, "Japanese" }, + {0x15, 0x01, 0x80, 0x00, "English" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Shinobi) + +static struct BurnDIPInfo SonicbomDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0x7f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x13, 0x01, 0x07, 0x06, "Easy" }, + {0x13, 0x01, 0x07, 0x07, "Normal" }, + {0x13, 0x01, 0x07, 0x05, "Hard 1" }, + {0x13, 0x01, 0x07, 0x04, "Hard 2" }, + {0x13, 0x01, 0x07, 0x03, "Hard 3" }, + {0x13, 0x01, 0x07, 0x02, "Hard 4" }, + {0x13, 0x01, 0x07, 0x01, "Hard 5" }, + {0x13, 0x01, 0x07, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x18, 0x10, "2" }, + {0x13, 0x01, 0x18, 0x18, "3" }, + {0x13, 0x01, 0x18, 0x08, "4" }, + {0x13, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x13, 0x01, 0x60, 0x40, "30000" }, + {0x13, 0x01, 0x60, 0x60, "40000" }, + {0x13, 0x01, 0x60, 0x20, "50000" }, + {0x13, 0x01, 0x60, 0x00, "60000" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x80, 0x00, "Upright" }, + {0x13, 0x01, 0x80, 0x80, "Cocktail" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Sonicbom) + +static struct BurnDIPInfo SjryukoDIPList[]= +{ + // Default Values + {0x1c, 0xff, 0xff, 0xff, NULL }, + {0x1d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + + + // Dip 2 + SYSTEM16B_COINAGE(0x1d) +}; + +STDDIPINFO(Sjryuko) + +static struct BurnDIPInfo SnapperDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 8 , "Coin A" }, + {0x0a, 0x01, 0x07, 0x07, "1 Coin 1 Credit" }, + {0x0a, 0x01, 0x07, 0x06, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0x07, 0x05, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0x07, 0x04, "1 Coin 4 Credits" }, + {0x0a, 0x01, 0x07, 0x03, "1 Coin 5 Credits" }, + {0x0a, 0x01, 0x07, 0x02, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x07, 0x01, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x07, 0x00, "4 Coins 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0a, 0x01, 0x18, 0x10, "3" }, + {0x0a, 0x01, 0x18, 0x18, "4" }, + {0x0a, 0x01, 0x18, 0x08, "5" }, + {0x0a, 0x01, 0x18, 0x00, "6" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x10, 0x00, "Off" }, + {0x0b, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x80, 0x80, "Off" }, + {0x0b, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Snapper) + +static struct BurnDIPInfo TetrisDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfd, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x30, 0x20, "Easy" }, + {0x11, 0x01, 0x30, 0x30, "Normal" }, + {0x11, 0x01, 0x30, 0x10, "Hard" }, + {0x11, 0x01, 0x30, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x12) +}; + +STDDIPINFO(Tetris) + +static struct BurnDIPInfo TimescanDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xf5, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Cocktail" }, + {0x13, 0x01, 0x01, 0x01, "Upright" }, + + {0 , 0xfe, 0 , 16 , "Bonus" }, + {0x13, 0x01, 0x1e, 0x16, "Replay 1000000/2000000" }, + {0x13, 0x01, 0x1e, 0x14, "Replay 1200000/2500000" }, + {0x13, 0x01, 0x1e, 0x12, "Replay 1500000/3000000" }, + {0x13, 0x01, 0x1e, 0x10, "Replay 2000000/4000000" }, + {0x13, 0x01, 0x1e, 0x1c, "Replay 1000000" }, + {0x13, 0x01, 0x1e, 0x1e, "Replay 1200000" }, + {0x13, 0x01, 0x1e, 0x1a, "Replay 1500000" }, + {0x13, 0x01, 0x1e, 0x18, "Replay 1800000" }, + {0x13, 0x01, 0x1e, 0x0e, "Extra Ball 100000" }, + {0x13, 0x01, 0x1e, 0x0c, "Extra Ball 200000" }, + {0x13, 0x01, 0x1e, 0x0a, "Extra Ball 300000" }, + {0x13, 0x01, 0x1e, 0x08, "Extra Ball 400000" }, + {0x13, 0x01, 0x1e, 0x06, "Extra Ball 500000" }, + {0x13, 0x01, 0x1e, 0x04, "Extra Ball 600000" }, + {0x13, 0x01, 0x1e, 0x02, "Extra Ball 700000" }, + {0x13, 0x01, 0x1e, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Match" }, + {0x13, 0x01, 0x20, 0x00, "Off" }, + {0x13, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Pin Rebound" }, + {0x13, 0x01, 0x40, 0x40, "Well" }, + {0x13, 0x01, 0x40, 0x00, "A Little" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x13, 0x01, 0x80, 0x80, "3" }, + {0x13, 0x01, 0x80, 0x00, "5" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) + + // Dip 3 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Out Lane Pin" }, + {0x15, 0x01, 0x02, 0x02, "Near" }, + {0x15, 0x01, 0x02, 0x00, "Far" }, + + {0 , 0xfe, 0 , 4 , "Special" }, + {0x15, 0x01, 0x0c, 0x08, "7 Credits" }, + {0x15, 0x01, 0x0c, 0x0c, "3 Credits" }, + {0x15, 0x01, 0x0c, 0x04, "1 Credit" }, + {0x15, 0x01, 0x0c, 0x00, "2000000 Points" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x10, 0x00, "No" }, + {0x15, 0x01, 0x10, 0x10, "Yes" }, +}; + +STDDIPINFO(Timescan) + +static struct BurnDIPInfo ToryumonDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x01, 0x01, "Off" }, + {0x11, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "VS-Mode Battle" }, + {0x11, 0x01, 0x10, 0x10, "1" }, + {0x11, 0x01, 0x10, 0x00, "3" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x11, 0x01, 0xe0, 0xc0, "Easy" }, + {0x11, 0x01, 0xe0, 0xe0, "Normal" }, + {0x11, 0x01, 0xe0, 0xa0, "Hard" }, + {0x11, 0x01, 0xe0, 0x80, "Hard+1" }, + {0x11, 0x01, 0xe0, 0x60, "Hard+2" }, + {0x11, 0x01, 0xe0, 0x40, "Hard+3" }, + {0x11, 0x01, 0xe0, 0x20, "Hard+4" }, + {0x11, 0x01, 0xe0, 0x00, "Hard+5" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x12) +}; + +STDDIPINFO(Toryumon) + +static struct BurnDIPInfo TturfDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0x2c, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Continues" }, + {0x15, 0x01, 0x03, 0x00, "None" }, + {0x15, 0x01, 0x03, 0x01, "3" }, + {0x15, 0x01, 0x03, 0x02, "Unlimited" }, + {0x15, 0x01, 0x03, 0x03, "Unlimited" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x0c, 0x08, "Easy" }, + {0x15, 0x01, 0x0c, 0x0c, "Normal" }, + {0x15, 0x01, 0x0c, 0x04, "Hard" }, + {0x15, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Starting Energy" }, + {0x15, 0x01, 0x30, 0x00, "3" }, + {0x15, 0x01, 0x30, 0x10, "4" }, + {0x15, 0x01, 0x30, 0x20, "6" }, + {0x15, 0x01, 0x30, 0x30, "8" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Bonus Energy" }, + {0x15, 0x01, 0x80, 0x80, "1" }, + {0x15, 0x01, 0x80, 0x00, "2" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x16) +}; + +STDDIPINFO(Tturf) + +static struct BurnDIPInfo Wb3DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x0c, 0x00, "2" }, + {0x13, 0x01, 0x0c, 0x0c, "3" }, + {0x13, 0x01, 0x0c, 0x08, "4" }, + {0x13, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x13, 0x01, 0x10, 0x10, "5k, 10k, 18k, 30k" }, + {0x13, 0x01, 0x10, 0x00, "5k, 15k, 30k" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x13, 0x01, 0x20, 0x20, "Normal" }, + {0x13, 0x01, 0x20, 0x00, "Hard" }, + + {0 , 0xfe, 0 , 2 , "Invincible Mode" }, + {0x13, 0x01, 0x40, 0x40, "No" }, + {0x13, 0x01, 0x40, 0x00, "Yes" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Wb3) + +static struct BurnDIPInfo WrestwarDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfd, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Round Time" }, + {0x13, 0x01, 0x0c, 0x00, "100" }, + {0x13, 0x01, 0x0c, 0x0c, "110" }, + {0x13, 0x01, 0x0c, 0x08, "120" }, + {0x13, 0x01, 0x0c, 0x04, "130" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x13, 0x01, 0x20, 0x00, "No" }, + {0x13, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x13, 0x01, 0xc0, 0x80, "Easy" }, + {0x13, 0x01, 0xc0, 0xc0, "Normal" }, + {0x13, 0x01, 0xc0, 0x40, "Hard" }, + {0x13, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + SYSTEM16B_COINAGE(0x14) +}; + +STDDIPINFO(Wrestwar) + +#undef SYSTEM16B_COINAGE + +/*==================================================== +Rom defs +====================================================*/ + +static struct BurnRomInfo AceattacRomDesc[] = { + { "epr-11491.a4", 0x10000, 0xf3c19c36, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11489.a1", 0x10000, 0xbbe623c5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11492.a5", 0x10000, 0xd8bd3139, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11490.a2", 0x10000, 0x38cb3a41, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11493.b9", 0x10000, 0x654485d9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11494.b10", 0x10000, 0xb67971ab, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11495.b11", 0x10000, 0xb687ab61, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11501.b1", 0x10000, 0x09179ead, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11505.b5", 0x10000, 0xb67f1ecf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11502.b2", 0x10000, 0xa3ee36b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11506.b6", 0x10000, 0xb0104def, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11503.b3", 0x10000, 0x344c0692, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11507.b7", 0x10000, 0xa2af710a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11504.b4", 0x10000, 0x7cae7920, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11508.b8", 0x10000, 0x5cbb833c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11496.a7", 0x08000, 0x82cb40a9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11497.a8", 0x08000, 0xb04f62cc, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11498.a9", 0x08000, 0x97baf52b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11499.a10", 0x08000, 0xea332866, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11500.a11", 0x08000, 0x2ddf1c31, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0059.key", 0x02000, 0x00000000, SYS16_ROM_KEY | BRF_ESS | BRF_PRG | BRF_NODUMP }, +}; + + +STD_ROM_PICK(Aceattac) +STD_ROM_FN(Aceattac) + +static struct BurnRomInfo AliensynRomDesc[] = { + { "epr-11083.a4", 0x08000, 0xcb2ad9b3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11080.a1", 0x08000, 0xfe7378d9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11084.a5", 0x08000, 0x2e1ec7b1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11081.a2", 0x08000, 0x1308ee63, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11085.a6", 0x08000, 0xcff78f39, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11082.a3", 0x08000, 0x9cdc2a14, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10702.b9", 0x10000, 0x393bc813, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10703.b10", 0x10000, 0x6b6dd9f5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10704.b11", 0x10000, 0x911e7ebc, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10709.b1", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10713.b5", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10710.b2", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10714.b6", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10711.b3", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10715.b7", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10712.b4", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10716.b8", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10723.a7", 0x08000, 0x99953526, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10724.a8", 0x08000, 0xf971a817, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10725.a9", 0x08000, 0x6a50e08f, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10726.a10", 0x08000, 0xd50b7736, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Aliensyn) +STD_ROM_FN(Aliensyn) + +static struct BurnRomInfo Aliensyn3RomDesc[] = { + { "epr-10816.a4", 0x08000, 0x17bf5304, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10814.a1", 0x08000, 0x4cd134df, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10817.a5", 0x08000, 0xc8b791b0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10815.a2", 0x08000, 0xbdcf4a30, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10822a.a6", 0x08000, 0x1d0790aa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10819a.a3", 0x08000, 0x1e7586b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10702.b9", 0x10000, 0x393bc813, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10703.b10", 0x10000, 0x6b6dd9f5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10704.b11", 0x10000, 0x911e7ebc, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10709.b1", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10713.b5", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10710.b2", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10714.b6", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10711.b3", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10715.b7", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10712.b4", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10716.b8", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10723.a7", 0x08000, 0x99953526, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10724.a8", 0x08000, 0xf971a817, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10725.a9", 0x08000, 0x6a50e08f, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10726.a10", 0x08000, 0xd50b7736, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0033.key", 0x02000, 0x49e882e5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aliensyn3) +STD_ROM_FN(Aliensyn3) + +static struct BurnRomInfo AliensynjRomDesc[] = { + { "epr-10720a.a4", 0x08000, 0x1b920893, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10717a.a1", 0x08000, 0x972ae358, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10721a.a5", 0x08000, 0xf4d2d1c3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10718a.a2", 0x08000, 0xc79bf61b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10722a.a6", 0x08000, 0x1d0790aa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10719a.a3", 0x08000, 0x1e7586b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10702.b9", 0x10000, 0x393bc813, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10703.b10", 0x10000, 0x6b6dd9f5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10704.b11", 0x10000, 0x911e7ebc, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10709.b1", 0x10000, 0xaddf0a90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10713.b5", 0x10000, 0xececde3a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10710.b2", 0x10000, 0x992369eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10714.b6", 0x10000, 0x91bf42fb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10711.b3", 0x10000, 0x29166ef6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10715.b7", 0x10000, 0xa7c57384, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10712.b4", 0x10000, 0x876ad019, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10716.b8", 0x10000, 0x40ba1d48, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10723.a7", 0x08000, 0x99953526, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10724.a8", 0x08000, 0xf971a817, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10725.a9", 0x08000, 0x6a50e08f, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10726.a10", 0x08000, 0xd50b7736, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0033.key", 0x02000, 0x49e882e5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aliensynj) +STD_ROM_FN(Aliensynj) + +static struct BurnRomInfo AltbeastRomDesc[] = { + { "epr-11907.a7", 0x20000, 0x29e0c3ad, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11906.a5", 0x20000, 0x4c9e9cd8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11674.a14", 0x20000, 0xa57a66d5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11675.a15", 0x20000, 0x2ef2f144, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11676.a16", 0x20000, 0x0c04acac, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11677.b1", 0x20000, 0xa01425cd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11681.b5", 0x20000, 0xd9e03363, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11678.b2", 0x20000, 0x17a9fc53, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11682.b6", 0x20000, 0xe3f77c5e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11679.b3", 0x20000, 0x14dcc245, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11683.b7", 0x20000, 0xf9a60f06, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11680.b4", 0x20000, 0xf43dcdec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11684.b8", 0x20000, 0xb20c0edb, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11671.a10", 0x08000, 0x2b71343b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0078.mcu", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Altbeast) +STD_ROM_FN(Altbeast) + +static struct BurnRomInfo AltbeastjRomDesc[] = { + { "epr-11885.a7", 0x20000, 0x5bb715aa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11884.a5", 0x20000, 0xe1707090, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11722.a14", 0x10000, 0xadaa8db5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11736.b14", 0x10000, 0xe9ad5e89, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11723.a15", 0x10000, 0x131a3f9a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11737.b15", 0x10000, 0x2e420023, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11724.a16", 0x10000, 0x6f2ed50a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11738.b16", 0x10000, 0xde3d6d02, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11725.b1", 0x10000, 0xf8b3684e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11729.b5", 0x10000, 0xae3c2793, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11726.b2", 0x10000, 0x3cce5419, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11730.b6", 0x10000, 0x3af62b55, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11727.b3", 0x10000, 0xb0390078, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11731.b7", 0x10000, 0x2a87744a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11728.b4", 0x10000, 0xf3a43fd8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11732.b8", 0x10000, 0x2fb3e355, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11717.a1", 0x10000, 0x676be0cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11733.b10", 0x10000, 0x802cac94, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11718.a2", 0x10000, 0x882864c2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11734.b11", 0x10000, 0x76c704d2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11719.a3", 0x10000, 0x339987f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11735.b12", 0x10000, 0x4fe406aa, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11671.a10", 0x08000, 0x2b71343b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0077.mcu", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Altbeastj) +STD_ROM_FN(Altbeastj) + +static struct BurnRomInfo Altbeast2RomDesc[] = { + { "epr-11705.a7", 0x20000, 0x57dc5c7a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11704.a5", 0x20000, 0x33bbcf07, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11674.a14", 0x20000, 0xa57a66d5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11675.a15", 0x20000, 0x2ef2f144, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11676.a16", 0x20000, 0x0c04acac, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11677.b1", 0x20000, 0xa01425cd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11681.b5", 0x20000, 0xd9e03363, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11678.b2", 0x20000, 0x17a9fc53, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11682.b6", 0x20000, 0xe3f77c5e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11679.b3", 0x20000, 0x14dcc245, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11683.b7", 0x20000, 0xf9a60f06, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11680.b4", 0x20000, 0xf43dcdec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11684.b8", 0x20000, 0xb20c0edb, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11686.a10", 0x08000, 0x828a45b3, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0066.key", 0x02000, 0xed85a054, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Altbeast2) +STD_ROM_FN(Altbeast2) + +static struct BurnRomInfo Altbeastj3RomDesc[] = { + { "epr-11721.a7", 0x20000, 0x1c5d11de, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11720.a5", 0x20000, 0x735350cf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11722.a14", 0x10000, 0xadaa8db5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11736.b14", 0x10000, 0xe9ad5e89, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11723.a15", 0x10000, 0x131a3f9a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11737.b15", 0x10000, 0x2e420023, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11724.a16", 0x10000, 0x6f2ed50a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11738.b16", 0x10000, 0xde3d6d02, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11725.b1", 0x10000, 0xf8b3684e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11729.b5", 0x10000, 0xae3c2793, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11726.b2", 0x10000, 0x3cce5419, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11730.b6", 0x10000, 0x3af62b55, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11727.b3", 0x10000, 0xb0390078, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11731.b7", 0x10000, 0x2a87744a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11728.b4", 0x10000, 0xf3a43fd8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11732.b8", 0x10000, 0x2fb3e355, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11717.a1", 0x10000, 0x676be0cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11733.b10", 0x10000, 0x802cac94, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11718.a2", 0x10000, 0x882864c2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11734.b11", 0x10000, 0x76c704d2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11719.a3", 0x10000, 0x339987f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11735.b12", 0x10000, 0x4fe406aa, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11671.a10", 0x08000, 0x2b71343b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0068.key", 0x02000, 0xc1ed4310, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Altbeastj3) +STD_ROM_FN(Altbeastj3) + +static struct BurnRomInfo Altbeast4RomDesc[] = { + { "epr-11740.a7", 0x20000, 0xce227542, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11739.a5", 0x20000, 0xe466eb65, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11722.a14", 0x10000, 0xadaa8db5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11736.b14", 0x10000, 0xe9ad5e89, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11723.a15", 0x10000, 0x131a3f9a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11737.b15", 0x10000, 0x2e420023, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11724.a16", 0x10000, 0x6f2ed50a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11738.b16", 0x10000, 0xde3d6d02, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11725.b1", 0x10000, 0xf8b3684e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11729.b5", 0x10000, 0xae3c2793, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11726.b2", 0x10000, 0x3cce5419, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11730.b6", 0x10000, 0x3af62b55, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11727.b3", 0x10000, 0xb0390078, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11731.b7", 0x10000, 0x2a87744a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11728.b4", 0x10000, 0xf3a43fd8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11732.b8", 0x10000, 0x2fb3e355, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11717.a1", 0x10000, 0x676be0cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11733.b10", 0x10000, 0x802cac94, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11718.a2", 0x10000, 0x882864c2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11734.b11", 0x10000, 0x76c704d2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11719.a3", 0x10000, 0x339987f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11735.b12", 0x10000, 0x4fe406aa, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11686.a10", 0x08000, 0x828a45b3, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0066.key", 0x02000, 0xed85a054, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Altbeast4) +STD_ROM_FN(Altbeast4) + +static struct BurnRomInfo Altbeast5RomDesc[] = { + { "epr-11883.a7", 0x20000, 0xc5b3e8f7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11882.a5", 0x20000, 0x9c01170b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11722.a14", 0x10000, 0xadaa8db5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11736.b14", 0x10000, 0xe9ad5e89, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11723.a15", 0x10000, 0x131a3f9a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11737.b15", 0x10000, 0x2e420023, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11724.a16", 0x10000, 0x6f2ed50a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11738.b16", 0x10000, 0xde3d6d02, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11725.b1", 0x10000, 0xf8b3684e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11729.b5", 0x10000, 0xae3c2793, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11726.b2", 0x10000, 0x3cce5419, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11730.b6", 0x10000, 0x3af62b55, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11727.b3", 0x10000, 0xb0390078, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11731.b7", 0x10000, 0x2a87744a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11728.b4", 0x10000, 0xf3a43fd8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11732.b8", 0x10000, 0x2fb3e355, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11717.a1", 0x10000, 0x676be0cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11733.b10", 0x10000, 0x802cac94, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11718.a2", 0x10000, 0x882864c2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11734.b11", 0x10000, 0x76c704d2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11719.a3", 0x10000, 0x339987f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11735.b12", 0x10000, 0x4fe406aa, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11671.a10", 0x08000, 0x2b71343b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-11672.a11", 0x20000, 0xbbd7f460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "opr-11673.a12", 0x20000, 0x400c4a36, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0076.mcu", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Altbeast5) +STD_ROM_FN(Altbeast5) + +static struct BurnRomInfo AtomicpRomDesc[] = { + { "ap-t2.bin", 0x10000, 0x97421047, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ap-t1.bin", 0x10000, 0x5c65fe56, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "ap-t4.bin", 0x08000, 0x332e58f4, SYS16_ROM_TILES | BRF_GRA }, + { "ap-t3.bin", 0x08000, 0xdddc122c, SYS16_ROM_TILES | BRF_GRA }, + { "ap-t5.bin", 0x08000, 0xef5ecd6b, SYS16_ROM_TILES | BRF_GRA }, +}; + + +STD_ROM_PICK(Atomicp) +STD_ROM_FN(Atomicp) + +static struct BurnRomInfo AurailRomDesc[] = { + { "epr-13577.a7", 0x20000, 0x6701b686, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13576.a5", 0x20000, 0x1e428d94, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13447.a8", 0x20000, 0x70a52167, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13445.a6", 0x20000, 0x28dfc3dd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13450.a14", 0x20000, 0x0fc4a7a8, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13465.b14", 0x20000, 0xe08135e0, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13451.a15", 0x20000, 0x1c49852f, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13466.b15", 0x20000, 0xe14c6684, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13452.a16", 0x20000, 0x047bde5e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13467.b16", 0x20000, 0x6309fec4, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13453.b1", 0x20000, 0x5fa0a9f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13457.b5", 0x20000, 0x0d1b54da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13454.b2", 0x20000, 0x5f6b33b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13458.b6", 0x20000, 0xbad340c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13455.b3", 0x20000, 0x4e80520b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13459.b7", 0x20000, 0x7e9165ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13456.b4", 0x20000, 0x5733c428, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13460.b8", 0x20000, 0x66b8f9b3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13440.a1", 0x20000, 0x4f370b2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13461.b10", 0x20000, 0xf76014bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13441.a2", 0x20000, 0x37cf9cb4, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13462.b11", 0x20000, 0x1061e7da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13442.a3", 0x20000, 0x049698ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13463.b12", 0x20000, 0x7dbcfbf1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13443.a4", 0x20000, 0x77a8989e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13464.b13", 0x20000, 0x551df422, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13448.a10", 0x08000, 0xb5183fb9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13449.a11", 0x20000, 0xd3d9aaf9, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Aurail) +STD_ROM_FN(Aurail) + +static struct BurnRomInfo Aurail1RomDesc[] = { + { "epr-13469.a7", 0x20000, 0xc628b69d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13468.a5", 0x20000, 0xce092218, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13447.a8", 0x20000, 0x70a52167, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13445.a6", 0x20000, 0x28dfc3dd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13450.a14", 0x20000, 0x0fc4a7a8, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13465.b14", 0x20000, 0xe08135e0, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13451.a15", 0x20000, 0x1c49852f, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13466.b15", 0x20000, 0xe14c6684, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13452.a16", 0x20000, 0x047bde5e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13467.b16", 0x20000, 0x6309fec4, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13453.b1", 0x20000, 0x5fa0a9f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13457.b5", 0x20000, 0x0d1b54da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13454.b2", 0x20000, 0x5f6b33b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13458.b6", 0x20000, 0xbad340c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13455.b3", 0x20000, 0x4e80520b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13459.b7", 0x20000, 0x7e9165ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13456.b4", 0x20000, 0x5733c428, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13460.b8", 0x20000, 0x66b8f9b3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13440.a1", 0x20000, 0x4f370b2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13461.b10", 0x20000, 0xf76014bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13441.a2", 0x20000, 0x37cf9cb4, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13462.b11", 0x20000, 0x1061e7da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13442.a3", 0x20000, 0x049698ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13463.b12", 0x20000, 0x7dbcfbf1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13443.a4", 0x20000, 0x77a8989e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13464.b13", 0x20000, 0x551df422, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13448.a10", 0x08000, 0xb5183fb9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13449.a11", 0x20000, 0xd3d9aaf9, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0168.key", 0x02000, 0xbc2d1792, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aurail1) +STD_ROM_FN(Aurail1) + +static struct BurnRomInfo AurailjRomDesc[] = { + { "epr-13446.a7", 0x20000, 0xd1f57b2a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13444.a5", 0x20000, 0x7a2b045f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13447.a8", 0x20000, 0x70a52167, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13445.a6", 0x20000, 0x28dfc3dd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13450.a14", 0x20000, 0x0fc4a7a8, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13465.b14", 0x20000, 0xe08135e0, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13451.a15", 0x20000, 0x1c49852f, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13466.b15", 0x20000, 0xe14c6684, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13452.a16", 0x20000, 0x047bde5e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13467.b16", 0x20000, 0x6309fec4, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13453.b1", 0x20000, 0x5fa0a9f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13457.b5", 0x20000, 0x0d1b54da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13454.b2", 0x20000, 0x5f6b33b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13458.b6", 0x20000, 0xbad340c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13455.b3", 0x20000, 0x4e80520b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13459.b7", 0x20000, 0x7e9165ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13456.b4", 0x20000, 0x5733c428, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13460.b8", 0x20000, 0x66b8f9b3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13440.a1", 0x20000, 0x4f370b2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13461.b10", 0x20000, 0xf76014bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13441.a2", 0x20000, 0x37cf9cb4, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13462.b11", 0x20000, 0x1061e7da, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13442.a3", 0x20000, 0x049698ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13463.b12", 0x20000, 0x7dbcfbf1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13443.a4", 0x20000, 0x77a8989e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13464.b13", 0x20000, 0x551df422, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13448.a10", 0x08000, 0xb5183fb9, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13449.a11", 0x20000, 0xd3d9aaf9, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0167.key", 0x02000, 0xbc2d1792, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Aurailj) +STD_ROM_FN(Aurailj) + +static struct BurnRomInfo BayrouteRomDesc[] = { + { "epr-12517.a7", 0x20000, 0x436728a9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12516.a5", 0x20000, 0x4ff0353f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12458.a8", 0x20000, 0xe7c7476a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12456.a6", 0x20000, 0x25dc2eaf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12462.a14", 0x10000, 0xa19943b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12463.a15", 0x10000, 0x62f8200d, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12464.a16", 0x10000, 0xc8c59703, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12465.b1", 0x20000, 0x11d61b45, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12467.b5", 0x20000, 0xc3b4e4c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12466.b2", 0x20000, 0xa57f236f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12468.b6", 0x20000, 0xd89c77de, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12459.a10", 0x08000, 0x3e1d29d0, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12460.a11", 0x20000, 0x0bae570d, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-12461.a12", 0x20000, 0xb03b8b46, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0116.key", 0x02000, 0x8778ee49, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Bayroute) +STD_ROM_FN(Bayroute) + +static struct BurnRomInfo BayroutejRomDesc[] = { + { "epr-12457.a7", 0x20000, 0xbc726255, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12455.a5", 0x20000, 0xb6a722eb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12458.a8", 0x20000, 0xe7c7476a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12456.a6", 0x20000, 0x25dc2eaf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12462.a14", 0x10000, 0xa19943b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12463.a15", 0x10000, 0x62f8200d, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12464.a16", 0x10000, 0xc8c59703, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12465.b1", 0x20000, 0x11d61b45, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12467.b5", 0x20000, 0xc3b4e4c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12466.b2", 0x20000, 0xa57f236f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12468.b6", 0x20000, 0xd89c77de, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12459.a10", 0x08000, 0x3e1d29d0, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12460.a11", 0x20000, 0x0bae570d, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-12461.a12", 0x20000, 0xb03b8b46, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0115.key", 0x02000, 0x75a55614, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Bayroutej) +STD_ROM_FN(Bayroutej) + +static struct BurnRomInfo Bayroute1RomDesc[] = { + { "br.a4", 0x10000, 0x91c6424b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "br.a1", 0x10000, 0x76954bf3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "br.a5", 0x10000, 0x9d6fd183, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "br.a2", 0x10000, 0x5ca1e3d2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "br.a6", 0x10000, 0xed97ad4c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "br.a3", 0x10000, 0x0d362905, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12462.a14", 0x10000, 0xa19943b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12463.a15", 0x10000, 0x62f8200d, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12464.a16", 0x10000, 0xc8c59703, SYS16_ROM_TILES | BRF_GRA }, + + { "br_obj0o.b1", 0x10000, 0x098a5e82, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj0e.b5", 0x10000, 0x85238af9, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj1o.b2", 0x10000, 0xcc641da1, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj1e.b6", 0x10000, 0xd3123315, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj2o.b3", 0x10000, 0x84efac1f, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj2e.b7", 0x10000, 0xb73b12cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "br_obj3o.b4", 0x10000, 0xa2e238ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "br.b8", 0x10000, 0xd8de78ff, SYS16_ROM_SPRITES | BRF_GRA }, + + { "sound.a7", 0x08000, 0x00000000, SYS16_ROM_Z80PROG | BRF_NODUMP | BRF_PRG }, + + { "sound.a8", 0x10000, 0x00000000, SYS16_ROM_UPD7759DATA | BRF_NODUMP | BRF_SND }, + { "sound.a9", 0x10000, 0x00000000, SYS16_ROM_UPD7759DATA | BRF_NODUMP | BRF_SND }, + { "sound.a10", 0x10000, 0x00000000, SYS16_ROM_UPD7759DATA | BRF_NODUMP | BRF_SND }, + { "sound.a11", 0x10000, 0x00000000, SYS16_ROM_UPD7759DATA | BRF_NODUMP | BRF_SND }, +}; + + +STD_ROM_PICK(Bayroute1) +STD_ROM_FN(Bayroute1) + +static struct BurnRomInfo Blox16bRomDesc[] = { + { "bs16b.p00", 0x040000, 0xfd1978b9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "bs16b.scr", 0x040000, 0x1de4e95b, SYS16_ROM_TILES | BRF_GRA }, + + { "bs16b.obj", 0x020000, 0x05076220, SYS16_ROM_SPRITES | BRF_GRA }, + + { "bs16b.snd", 0x018000, 0x930c7e7b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Blox16b) +STD_ROM_FN(Blox16b) + +static struct BurnRomInfo BulletRomDesc[] = { + { "epr-11010.a4", 0x08000, 0xdd9001de, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11007.a1", 0x08000, 0xd9e08110, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11011.a5", 0x08000, 0x7f446b9f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11008.a2", 0x08000, 0x34824d3b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11012.a6", 0x08000, 0x3992f159, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11009.a3", 0x08000, 0xdf199999, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10994.b9", 0x10000, 0x3035468a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10995.b10", 0x10000, 0x6b97aff1, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10996.b11", 0x10000, 0x501bddd6, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10999.b1", 0x10000, 0x119f0008, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11003.b5", 0x10000, 0x2f429089, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11000.b2", 0x10000, 0xf5482bbe, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11004.b6", 0x10000, 0x8c886df0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11001.b3", 0x10000, 0x65ea71e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11005.b7", 0x10000, 0xea2f9d50, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11002.b4", 0x10000, 0x9e25042b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11006.b8", 0x10000, 0x6b7384f2, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10997.a7", 0x08000, 0x5dd9cab5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10998.a8", 0x08000, 0xf971a817, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0041.key", 0x02000, 0x4cd4861a, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Bullet) +STD_ROM_FN(Bullet) + +static struct BurnRomInfo CottonRomDesc[] = { + { "epr-13921a.a7", 0x20000, 0xf047a037, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13919a.a5", 0x20000, 0x651108b1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13922a.a8", 0x20000, 0x1ca248c5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13920a.a6", 0x20000, 0xfa3610f9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-13862.a14", 0x20000, 0xa47354b6, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13877.b14", 0x20000, 0xd38424b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13863.a15", 0x20000, 0x8c990026, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13878.b15", 0x20000, 0x21c15b8a, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13864.a16", 0x20000, 0xd2b175bf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13879.b16", 0x20000, 0xb9d62531, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-13865.b1", 0x20000, 0x7024f404, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13869.b5", 0x20000, 0xab4b3468, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13866.b2", 0x20000, 0x6169bba4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13870.b6", 0x20000, 0x69b41ac3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13867.b3", 0x20000, 0xb014f02d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13871.b7", 0x20000, 0x0801cf02, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13868.b4", 0x20000, 0xe62a7cd6, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13872.b8", 0x20000, 0xf066f315, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13852.a1", 0x20000, 0x943aba8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13873.b10", 0x20000, 0x1bd145f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13853.a2", 0x20000, 0x7ea93200, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13874.b11", 0x20000, 0x4fd59bff, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13891.a3", 0x20000, 0xc6b3c414, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13894.b12", 0x20000, 0xe3d0bee2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13855.a4", 0x20000, 0x856f3ee2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13876.b13", 0x20000, 0x1c5ffad8, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13892.a10", 0x08000, 0xfdfbe6ad, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-13893.a11", 0x20000, 0x384233df, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0181a.key", 0x02000, 0x5c419b36, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Cotton) +STD_ROM_FN(Cotton) + +static struct BurnRomInfo CottonuRomDesc[] = { + { "cotton.a7", 0x20000, 0xe7ef7d10, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "cotton.a5", 0x20000, 0xabe4f83e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "cotton.a8", 0x20000, 0xfc0f4401, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "cotton.a6", 0x20000, 0xf50f1ea2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-13862.a14", 0x20000, 0xa47354b6, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13877.b14", 0x20000, 0xd38424b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13863.a15", 0x20000, 0x8c990026, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13878.b15", 0x20000, 0x21c15b8a, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13864.a16", 0x20000, 0xd2b175bf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13879.b16", 0x20000, 0xb9d62531, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-13865.b1", 0x20000, 0x7024f404, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13869.b5", 0x20000, 0xab4b3468, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13866.b2", 0x20000, 0x6169bba4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13870.b6", 0x20000, 0x69b41ac3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13867.b3", 0x20000, 0xb014f02d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13871.b7", 0x20000, 0x0801cf02, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13868.b4", 0x20000, 0xe62a7cd6, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13872.b8", 0x20000, 0xf066f315, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13852.a1", 0x20000, 0x943aba8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13873.b10", 0x20000, 0x1bd145f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13853.a2", 0x20000, 0x7ea93200, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13874.b11", 0x20000, 0x4fd59bff, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13891.a3", 0x20000, 0xc6b3c414, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13894.b12", 0x20000, 0xe3d0bee2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13855.a4", 0x20000, 0x856f3ee2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13876.b13", 0x20000, 0x1c5ffad8, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13892.a10", 0x08000, 0xfdfbe6ad, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-13893.a11", 0x20000, 0x384233df, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0180.key", 0x02000, 0xa236b915, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Cottonu) +STD_ROM_FN(Cottonu) + +static struct BurnRomInfo CottonjRomDesc[] = { + { "epr-13858.a7", 0x20000, 0x276f42fe, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13856.a5", 0x20000, 0x14e6b5e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13859.a8", 0x20000, 0x4703ef9d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13857.a6", 0x20000, 0xde37e527, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-13862.a14", 0x20000, 0xa47354b6, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13877.b14", 0x20000, 0xd38424b5, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13863.a15", 0x20000, 0x8c990026, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13878.b15", 0x20000, 0x21c15b8a, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13864.a16", 0x20000, 0xd2b175bf, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13879.b16", 0x20000, 0xb9d62531, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-13865.b1", 0x20000, 0x7024f404, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13869.b5", 0x20000, 0xab4b3468, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13866.b2", 0x20000, 0x6169bba4, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13870.b6", 0x20000, 0x69b41ac3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13867.b3", 0x20000, 0xb014f02d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13871.b7", 0x20000, 0x0801cf02, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13868.b4", 0x20000, 0xe62a7cd6, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13872.b8", 0x20000, 0xf066f315, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13852.a1", 0x20000, 0x943aba8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13873.b10", 0x20000, 0x1bd145f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13853.a2", 0x20000, 0x7ea93200, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13874.b11", 0x20000, 0x4fd59bff, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13854.a3", 0x20000, 0x1c942190, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13875.b12", 0x20000, 0x6a66868d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13855.a4", 0x20000, 0x856f3ee2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13876.b13", 0x20000, 0x1c5ffad8, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13860.a10", 0x08000, 0x6a57b027, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-13061.a11", 0x20000, 0x4d21153f, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0179a.key", 0x02000, 0x488096d3, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Cottonj) +STD_ROM_FN(Cottonj) + +static struct BurnRomInfo DduxRomDesc[] = { + { "epr-11191.a7", 0x20000, 0x500e400a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11190.a5", 0x20000, 0x2a698308, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11915.a8", 0x20000, 0xd8ed3132, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11913.a6", 0x20000, 0x30c6cb92, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11917.a14", 0x10000, 0x6f772190, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11918.a15", 0x10000, 0xc731db95, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11919.a16", 0x10000, 0x64d5a491, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-11920.b1", 0x20000, 0xe5d1e3cd, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11922.b5", 0x20000, 0x70b0c4dd, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11921.b2", 0x20000, 0x61d2358c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11923.b6", 0x20000, 0xc9ffe47d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11916.a10", 0x08000, 0x7ab541cf, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0096.key", 0x02000, 0x6fd7d26e, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Ddux) +STD_ROM_FN(Ddux) + +static struct BurnRomInfo Ddux1RomDesc[] = { + { "epr-12189.a7", 0x20000, 0x558e9b5d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12188.a5", 0x20000, 0x802a240f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11915.a8", 0x20000, 0xd8ed3132, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11913.a6", 0x20000, 0x30c6cb92, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11917.a14", 0x10000, 0x6f772190, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11918.a15", 0x10000, 0xc731db95, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11919.a16", 0x10000, 0x64d5a491, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-11920.b1", 0x20000, 0xe5d1e3cd, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11922.b5", 0x20000, 0x70b0c4dd, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11921.b2", 0x20000, 0x61d2358c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11923.b6", 0x20000, 0xc9ffe47d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11916.a10", 0x08000, 0x7ab541cf, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0095.bin", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Ddux1) +STD_ROM_FN(Ddux1) + +static struct BurnRomInfo DduxblRomDesc[] = { + { "dduxb03.bin", 0x20000, 0xe7526012, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "dduxb05.bin", 0x20000, 0x459d1237, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "dduxb02.bin", 0x20000, 0xd8ed3132, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "dduxb04.bin", 0x20000, 0x30c6cb92, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "dduxb14.bin", 0x10000, 0x664bd135, SYS16_ROM_TILES | BRF_GRA }, + { "dduxb15.bin", 0x10000, 0xce0d2b30, SYS16_ROM_TILES | BRF_GRA }, + { "dduxb16.bin", 0x10000, 0x6de95434, SYS16_ROM_TILES | BRF_GRA }, + + { "dduxb10.bin", 0x10000, 0x0be3aee5, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb06.bin", 0x10000, 0xb0079e99, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb11.bin", 0x10000, 0xcfb2af18, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb07.bin", 0x10000, 0x0217369c, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb12.bin", 0x10000, 0x28ce9b15, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb08.bin", 0x10000, 0x8844f336, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb13.bin", 0x10000, 0xefe57759, SYS16_ROM_SPRITES | BRF_GRA }, + { "dduxb09.bin", 0x10000, 0x6b64f665, SYS16_ROM_SPRITES | BRF_GRA }, + + { "dduxb01.bin", 0x08000, 0x0dbef0d7, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Dduxbl) +STD_ROM_FN(Dduxbl) + +static struct BurnRomInfo DunkshotRomDesc[] = { + { "epr-10470.a4", 0x08000, 0x8c60761f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10467.a1", 0x08000, 0x29774114, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10471.a5", 0x08000, 0x22777314, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10468.a2", 0x08000, 0xe2d5f97a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10472.a6", 0x08000, 0x206027a6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10469.a3", 0x08000, 0xaa442b81, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10485.b9", 0x08000, 0xf16dda29, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10486.b10", 0x08000, 0x311d973c, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10487.b11", 0x08000, 0xa8fb179f, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10477.b1", 0x08000, 0xf9d3b2cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10481.b5", 0x08000, 0xfeb04bc9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10478.b2", 0x08000, 0x5b5c5c92, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10482.b6", 0x08000, 0x5bc07618, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10479.b3", 0x08000, 0xe84190a0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10483.b7", 0x08000, 0x7cab4f9e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10480.b4", 0x08000, 0x5dffd9dd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10484.b8", 0x08000, 0xbcb5fcc9, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10473.a7", 0x08000, 0x7f1f5a27, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10474.a8", 0x08000, 0x419a656e, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10475.a9", 0x08000, 0x17d55e85, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-10476.a10", 0x08000, 0xa6be0956, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0022.key", 0x02000, 0x4eedc66d, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Dunkshot) +STD_ROM_FN(Dunkshot) + +static struct BurnRomInfo EswatRomDesc[] = { + { "epr-12659.bin", 0x40000, 0xc5ab2db9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12658.bin", 0x40000, 0xaf40bd71, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12624.b11", 0x40000, 0x375a5ec4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12625.b12", 0x40000, 0x3b8c757e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12626.b13", 0x40000, 0x3efca25c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12618.b1", 0x40000, 0x0d1530bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12621.b4", 0x40000, 0x18ff0799, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12619.b2", 0x40000, 0x32069246, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12622.b5", 0x40000, 0xa3dfe436, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12620.b3", 0x40000, 0xf6b096e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12623.b6", 0x40000, 0x6773fef6, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12617.a13", 0x08000, 0x7efecf23, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12616.a11", 0x40000, 0x254347c2, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0130.key", 0x02000, 0xba7b717b, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Eswat) +STD_ROM_FN(Eswat) + +static struct BurnRomInfo EswatjRomDesc[] = { + { "epr-12615.a2", 0x40000, 0x388c2ea7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12614.a1", 0x40000, 0xd5f0fb47, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12624.b11", 0x40000, 0x375a5ec4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12625.b12", 0x40000, 0x3b8c757e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12626.b13", 0x40000, 0x3efca25c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12618.b1", 0x40000, 0x0d1530bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12621.b4", 0x40000, 0x18ff0799, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12619.b2", 0x40000, 0x32069246, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12622.b5", 0x40000, 0xa3dfe436, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12620.b3", 0x40000, 0xf6b096e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12623.b6", 0x40000, 0x6773fef6, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12617.a13", 0x08000, 0x7efecf23, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12616.a11", 0x40000, 0x254347c2, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0128.key", 0x02000, 0x95f96277, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Eswatj) +STD_ROM_FN(Eswatj) + +static struct BurnRomInfo EswatuRomDesc[] = { + { "epr-12657.a2", 0x40000, 0x43ca72aa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12656.a1", 0x40000, 0x5f018967, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12624.b11", 0x40000, 0x375a5ec4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12625.b12", 0x40000, 0x3b8c757e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12626.b13", 0x40000, 0x3efca25c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12618.b1", 0x40000, 0x0d1530bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12621.b4", 0x40000, 0x18ff0799, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12619.b2", 0x40000, 0x32069246, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12622.b5", 0x40000, 0xa3dfe436, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12620.b3", 0x40000, 0xf6b096e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12623.b6", 0x40000, 0x6773fef6, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12617.a13", 0x08000, 0x7efecf23, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12616.a11", 0x40000, 0x254347c2, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0129.key", 0x02000, 0x128302c7, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Eswatu) +STD_ROM_FN(Eswatu) + +static struct BurnRomInfo EswatblRomDesc[] = { + { "eswat_c.rom", 0x10000, 0x1028cc81, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "eswat_f.rom", 0x10000, 0xf7b2d388, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "eswat_b.rom", 0x10000, 0x87c6b1b5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "eswat_e.rom", 0x10000, 0x937ddf9a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "eswat_a.rom", 0x08000, 0x2af4fc62, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "eswat_d.rom", 0x08000, 0xb4751e19, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr12624.b11", 0x40000, 0x375a5ec4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr12625.b12", 0x40000, 0x3b8c757e, SYS16_ROM_TILES | BRF_GRA }, + { "mpr12626.b13", 0x40000, 0x3efca25c, SYS16_ROM_TILES | BRF_GRA }, + + { "ic9", 0x40000, 0x0d1530bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic12", 0x40000, 0x18ff0799, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic10", 0x40000, 0x32069246, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic13", 0x40000, 0xa3dfe436, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic11", 0x40000, 0xf6b096e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic14", 0x40000, 0x6773fef6, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr12617.a13", 0x08000, 0x7efecf23, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr12616.a11", 0x40000, 0x254347c2, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Eswatbl) +STD_ROM_FN(Eswatbl) + +static struct BurnRomInfo ExctleagRomDesc[] = { + { "epr-11939.a04", 0x10000, 0x117dd98f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11936.a01", 0x10000, 0x0863de60, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11940.a05", 0x10000, 0xdec83274, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11937.a02", 0x10000, 0x4ebda367, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11941.a06", 0x10000, 0x4df2d451, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11938.a03", 0x10000, 0x07c08d47, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11942.b09", 0x10000, 0xeb70e827, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11943.b10", 0x10000, 0xd97c8982, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11944.b11", 0x10000, 0xa75cae80, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11950.b01", 0x10000, 0xaf497849, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11954.b05", 0x10000, 0x5fa2106c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11951.b02", 0x10000, 0xc04fa974, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11955.b06", 0x10000, 0x86a0c368, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11952.b03", 0x10000, 0xe64a9761, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11956.b07", 0x10000, 0xaff5c2fa, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11953.b04", 0x10000, 0x4cae3999, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11957.b08", 0x10000, 0x218f835b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11945.a07", 0x08000, 0xc2a83012, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11140.a08", 0x08000, 0xb297371b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11141.a09", 0x08000, 0x19756aa6, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11142.a10", 0x08000, 0x25d26c66, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11143.a11", 0x08000, 0x848b7b77, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0079.key", 0x02000, 0xeffefa1c, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Exctleag) +STD_ROM_FN(Exctleag) + +static struct BurnRomInfo Fantzn2xRomDesc[] = { + { "fz2_s16c.p00", 0x040000, 0xb7d16c1d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "fz2_s16c.p01", 0x040000, 0x2c47487c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "fz2_s16c.scr", 0x080000, 0xed3b1ac0, SYS16_ROM_TILES | BRF_GRA }, + + { "fz2_s16c.spr", 0x200000, 0x14d06fee, SYS16_ROM_SPRITES | BRF_GRA }, + + { "fz2_s16c.snd", 0x030000, 0x0ed30ec1, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fantzn2x) +STD_ROM_FN(Fantzn2x) + +static struct BurnRomInfo FantzntaRomDesc[] = { + { "fz1_s16b_ta.p00",0x040000, 0xbad0537a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "fz1_s16b.scr", 0x040000, 0x10ecd8b9, SYS16_ROM_TILES | BRF_GRA }, + + { "fz1_s16b_ta.obj",0x200000, 0x51fd438f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "fz1_s16b.snd", 0x020000, 0xa00701fb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fantznta) +STD_ROM_FN(Fantznta) + +static struct BurnRomInfo FpointRomDesc[] = { + { "epr-12599b.a4", 0x10000, 0x26e3f354, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12598b.a1", 0x10000, 0xc0f2c97d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12593.a14", 0x10000, 0xcc0582d8, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12594.a15", 0x10000, 0x8bfc4815, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12595.a16", 0x10000, 0x5b18d60b, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12596.b1", 0x10000, 0x4a4041f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12597.b5", 0x10000, 0x6961e676, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12592.a10", 0x08000, 0x9a8c11bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0127a.key", 0x02000, 0x5adb0042, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fpoint) +STD_ROM_FN(Fpoint) + +static struct BurnRomInfo Fpoint1RomDesc[] = { + { "epr-12591b.a7", 0x10000, 0x248b3e1b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12590b.a5", 0x10000, 0x75256e3d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12593.a14", 0x10000, 0xcc0582d8, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12594.a15", 0x10000, 0x8bfc4815, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12595.a16", 0x10000, 0x5b18d60b, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12596.b1", 0x10000, 0x4a4041f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12597.b5", 0x10000, 0x6961e676, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12592.a10", 0x08000, 0x9a8c11bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0127a.key", 0x02000, 0x5adb0042, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fpoint1) +STD_ROM_FN(Fpoint1) + +static struct BurnRomInfo FpointblRomDesc[] = { + { "flpoint.003", 0x10000, 0x4d6df514, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "flpoint.002", 0x10000, 0x4dff2ee8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "flpoint.006", 0x10000, 0xc539727d, SYS16_ROM_TILES | BRF_GRA }, + { "flpoint.005", 0x10000, 0x82c0b8b0, SYS16_ROM_TILES | BRF_GRA }, + { "flpoint.004", 0x10000, 0x522426ae, SYS16_ROM_TILES | BRF_GRA }, + + { "12596.bin", 0x10000, 0x4a4041f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "12597.bin", 0x10000, 0x6961e676, SYS16_ROM_SPRITES | BRF_GRA }, + + { "flpoint.001", 0x08000, 0xc5b8e0fe, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Fpointbl) +STD_ROM_FN(Fpointbl) + +static struct BurnRomInfo FpointbjRomDesc[] = { + { "boot2.003", 0x10000, 0x6c00d1b0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "boot2.002", 0x10000, 0xc1fcd704, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "flpoint.006", 0x10000, 0xc539727d, SYS16_ROM_TILES | BRF_GRA }, + { "flpoint.005", 0x10000, 0x82c0b8b0, SYS16_ROM_TILES | BRF_GRA }, + { "flpoint.004", 0x10000, 0x522426ae, SYS16_ROM_TILES | BRF_GRA }, + + { "12596.bin", 0x10000, 0x4a4041f3, SYS16_ROM_SPRITES | BRF_GRA }, + { "12597.bin", 0x10000, 0x6961e676, SYS16_ROM_SPRITES | BRF_GRA }, + + { "flpoint.001", 0x08000, 0xc5b8e0fe, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "82s129.1", 0x00100, 0xa7c22d96, BRF_OPT }, + { "82s123.2", 0x00020, 0x58bcf8bd, BRF_OPT }, + { "fpointbj_gal16v8_1.bin", 0x00117, 0xba7f292c, BRF_OPT }, + { "fpointbj_gal16v8_3.bin", 0x00117, 0xce1ab1e1, BRF_OPT }, + { "fpointbj_gal20v8.bin", 0x00400, 0x00000000, BRF_OPT | BRF_NODUMP }, +}; + + +STD_ROM_PICK(Fpointbj) +STD_ROM_FN(Fpointbj) + +static struct BurnRomInfo GoldnaxeRomDesc[] = { + { "epr-12545.ic2", 0x40000, 0xa97c4e4d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12544.ic1", 0x40000, 0x5e38f668, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.ic19", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.ic20", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.ic21", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.ic9", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.ic12", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.ic10", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.ic13", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.ic11", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.ic14", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.ic8", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.ic6", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0123a.bin", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Goldnaxe) +STD_ROM_FN(Goldnaxe) + +static struct BurnRomInfo Goldnaxe1RomDesc[] = { + { "epr-12389.ic2", 0x40000, 0x35d5fa77, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12388.ic1", 0x40000, 0x72952a93, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.ic19", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.ic20", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.ic21", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.ic9", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.ic12", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.ic10", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.ic13", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.ic11", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.ic14", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.ic8", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.ic6", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0110.key", 0x02000, 0xcd517dc6, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Goldnaxe1) +STD_ROM_FN(Goldnaxe1) + +static struct BurnRomInfo Goldnaxe2RomDesc[] = { + { "epr-12523.a7", 0x20000, 0x8e6128d7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12522.a5", 0x20000, 0xb6c35160, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12521.a8", 0x20000, 0x5001d713, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12519.a6", 0x20000, 0x4438ca8e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.a14", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.a15", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.a16", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.b1", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.b5", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.b2", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.b6", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.b3", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.b7", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.a10", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.a11", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0112.bin", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Goldnaxe2) +STD_ROM_FN(Goldnaxe2) + +static struct BurnRomInfo Goldnaxe3RomDesc[] = { + { "epr-12525.a7", 0x20000, 0x48332c76, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12524.a5", 0x20000, 0x8e58f342, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12521.a8", 0x20000, 0x5001d713, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12519.a6", 0x20000, 0x4438ca8e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.a14", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.a15", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.a16", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.b1", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.b5", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.b2", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.b6", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.b3", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.b7", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.a10", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.a11", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0120.key", 0x02000, 0x946e9fa6, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Goldnaxe3) +STD_ROM_FN(Goldnaxe3) + +static struct BurnRomInfo GoldnaxejRomDesc[] = { + { "epr-12540.a7", 0x20000, 0x0c7ccc6d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12539.a5", 0x20000, 0x1f24f7d0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12521.a8", 0x20000, 0x5001d713, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12519.a6", 0x20000, 0x4438ca8e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.a14", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.a15", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.a16", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.b1", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.b5", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.b2", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.b6", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.b3", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.b7", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.a10", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.a11", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0121.key", 0x02000, 0x72afed01, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Goldnaxej) +STD_ROM_FN(Goldnaxej) + +static struct BurnRomInfo GoldnaxeuRomDesc[] = { + { "epr-12543.ic2", 0x40000, 0xb0df9ca4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12542.ic1", 0x40000, 0xb7994d3c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12385.ic19", 0x20000, 0xb8a4e7e0, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12386.ic20", 0x20000, 0x25d7d779, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12387.ic21", 0x20000, 0xc7fcadf3, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12378.ic9", 0x40000, 0x119e5a82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12379.ic12", 0x40000, 0x1a0e8c57, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12380.ic10", 0x40000, 0xbb2c0853, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12381.ic13", 0x40000, 0x81ba6ecc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12382.ic11", 0x40000, 0x81601c6f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12383.ic14", 0x40000, 0x5dbacf7a, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12390.ic8", 0x08000, 0x399fc5f5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12384.ic6", 0x20000, 0x6218d8e7, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0122.key", 0x02000, 0xf123c2fb, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Goldnaxeu) +STD_ROM_FN(Goldnaxeu) + +static struct BurnRomInfo HwchampRomDesc[] = { + { "epr-11239.a7", 0x20000, 0xe5abfed7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11238.a5", 0x20000, 0x25180124, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11241.a14", 0x20000, 0xfc586a86, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11166.b14", 0x20000, 0xaeaaa9d8, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11242.a15", 0x20000, 0x7715a742, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11167.b15", 0x20000, 0x63a82afa, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11243.a16", 0x20000, 0xf30cd5fd, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-11168.b16", 0x20000, 0x5b8494a8, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-11158.b1", 0x20000, 0xfc098a13, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11162.b5", 0x20000, 0x5db934a8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11159.b2", 0x20000, 0x1f27ee74, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11163.b6", 0x20000, 0x8a6a5cf1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11160.b3", 0x20000, 0xc0b2ba82, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11164.b7", 0x20000, 0xd6c7917b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11161.b4", 0x20000, 0x35c9e44b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11165.b8", 0x20000, 0x57e8f9d2, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11240.a10", 0x08000, 0x96a12d9d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11244.a11", 0x20000, 0x4191c03d, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-11245.a12", 0x20000, 0xa4d53f7b, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "pls153.bin", 0x000eb, 0x39b47212, BRF_OPT }, // PLD +}; + + +STD_ROM_PICK(Hwchamp) +STD_ROM_FN(Hwchamp) + +static struct BurnRomInfo HwchampjRomDesc[] = { + { "epr-11152.a7", 0x20000, 0x8ab0ce62, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11153.a5", 0x20000, 0x84a743de, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11202.a14", 0x20000, 0x7c94ede3, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11213.b14", 0x20000, 0xaeaaa9d8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11203.a15", 0x20000, 0x327754f7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11214.b15", 0x20000, 0x63a82afa, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11204.a16", 0x20000, 0xdfc4cd33, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11215.b16", 0x20000, 0x5b8494a8, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11205.b1", 0x20000, 0xfc098a13, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11209.b5", 0x20000, 0x5db934a8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11206.b2", 0x20000, 0x1f27ee74, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11210.b6", 0x20000, 0x8a6a5cf1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11207.b3", 0x20000, 0xc0b2ba82, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11211.b7", 0x20000, 0xd6c7917b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11208.b4", 0x20000, 0x35c9e44b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11212.b8", 0x20000, 0x57e8f9d2, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11154.a10", 0x08000, 0x65791275, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11200.a11", 0x20000, 0x5c41a68a, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11201.a12", 0x20000, 0x9a993120, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0046.key", 0x02000, 0x488b3f8b, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, + + { "pls153.bin", 0x000eb, 0x39b47212, BRF_OPT }, // PLD +}; + + +STD_ROM_PICK(Hwchampj) +STD_ROM_FN(Hwchampj) + +static struct BurnRomInfo MvpRomDesc[] = { + { "13000.rom", 0x40000, 0x2e0e21ec, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "12999.rom", 0x40000, 0xfd213d28, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "13011.rom", 0x40000, 0x1cb871fc, SYS16_ROM_TILES | BRF_GRA }, + { "13012.rom", 0x40000, 0xb75e6821, SYS16_ROM_TILES | BRF_GRA }, + { "13013.rom", 0x40000, 0xf1944a3c, SYS16_ROM_TILES | BRF_GRA }, + + { "13003.rom", 0x40000, 0x21424151, SYS16_ROM_SPRITES | BRF_GRA }, + { "13006.rom", 0x40000, 0x2e9afd2f, SYS16_ROM_SPRITES | BRF_GRA }, + { "13004.rom", 0x40000, 0x0aa09dd3, SYS16_ROM_SPRITES | BRF_GRA }, + { "13007.rom", 0x40000, 0x55c8605b, SYS16_ROM_SPRITES | BRF_GRA }, + { "13005.rom", 0x40000, 0xc899c810, SYS16_ROM_SPRITES | BRF_GRA }, + { "13008.rom", 0x40000, 0xb3d46dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "13009.rom", 0x40000, 0x126d2e37, SYS16_ROM_SPRITES | BRF_GRA }, + { "13010.rom", 0x40000, 0xdf37c567, SYS16_ROM_SPRITES | BRF_GRA }, + + { "13002.rom", 0x08000, 0x1b6e1515, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "13001.rom", 0x40000, 0xe8cace8c, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0143.key", 0x02000, 0xfba2e8da, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Mvp) +STD_ROM_FN(Mvp) + +static struct BurnRomInfo MvpjRomDesc[] = { + { "epr-12967.a7", 0x20000, 0xe53ac137, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12965.a5", 0x20000, 0x4266cb9e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12968.a8", 0x20000, 0x91c772ac, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12966.a6", 0x20000, 0x39365a79, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12971.a14", 0x20000, 0x245dcd1f, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12983.b14", 0x20000, 0xf3570fc9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12972.a15", 0x20000, 0xff7c4278, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12984.b15", 0x20000, 0xd37d1876, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12973.a16", 0x20000, 0x8dc9b9ea, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12985.b16", 0x20000, 0xe3f33a8a, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12974.b1", 0x20000, 0xe1da5597, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12977.b5", 0x20000, 0xb9eb9762, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12975.b2", 0x20000, 0x364d51d1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12978.b6", 0x20000, 0x014b5442, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12976.b3", 0x20000, 0x43b549c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12979.b7", 0x20000, 0x20f603f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12962.a1", 0x20000, 0x9b678da3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12980.b10", 0x20000, 0x883b792a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12963.a2", 0x20000, 0x8870f95a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12981.b11", 0x20000, 0x48636cb0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12964.a3", 0x20000, 0xf9148c5d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12982.b12", 0x20000, 0xc4453292, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12969.a10", 0x08000, 0xec621893, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12970.a11", 0x20000, 0x8f7d7657, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0142.key", 0x02000, 0x90468045, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Mvpj) +STD_ROM_FN(Mvpj) + +static struct BurnRomInfo PassshtRomDesc[] = { + { "epr-11871.a4", 0x10000, 0x0f9ccea5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11870.a1", 0x10000, 0xdf43ebcf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11854.b9", 0x10000, 0xd31c0b6c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11855.b10", 0x10000, 0xb78762b4, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11856.b11", 0x10000, 0xea49f666, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-11862.b1", 0x10000, 0xb6e94727, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11865.b5", 0x10000, 0x17e8d5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11863.b2", 0x10000, 0x3e670098, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11866.b6", 0x10000, 0x50eb71cc, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11864.b3", 0x10000, 0x05733ca8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11867.b7", 0x10000, 0x81e49697, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11857.a7", 0x08000, 0x789edc06, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11858.a8", 0x08000, 0x08ab0018, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11859.a9", 0x08000, 0x8673e01b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11860.a10", 0x08000, 0x10263746, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11861.a11", 0x08000, 0x38b54a71, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0080.key", 0x02000, 0x222d016f, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Passsht) +STD_ROM_FN(Passsht) + +static struct BurnRomInfo PassshtaRomDesc[] = { + { "8.4a", 0x10000, 0xb84dc139, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "5.1a", 0x10000, 0xeffe29df, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11854.b9", 0x10000, 0xd31c0b6c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11855.b10", 0x10000, 0xb78762b4, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11856.b11", 0x10000, 0xea49f666, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-11862.b1", 0x10000, 0xb6e94727, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11865.b5", 0x10000, 0x17e8d5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11863.b2", 0x10000, 0x3e670098, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11866.b6", 0x10000, 0x50eb71cc, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11864.b3", 0x10000, 0x05733ca8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11867.b7", 0x10000, 0x81e49697, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11857.a7", 0x08000, 0x789edc06, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11858.a8", 0x08000, 0x08ab0018, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11859.a9", 0x08000, 0x8673e01b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11860.a10", 0x08000, 0x10263746, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11861.a11", 0x08000, 0x38b54a71, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0074.key", 0x02000, 0x71bd232d, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Passshta) +STD_ROM_FN(Passshta) + +static struct BurnRomInfo PassshtjRomDesc[] = { + { "epr-11853.a4", 0x10000, 0xfab337e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11852.a1", 0x10000, 0x892a81fc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11854.b9", 0x10000, 0xd31c0b6c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11855.b10", 0x10000, 0xb78762b4, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11856.b11", 0x10000, 0xea49f666, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-11862.b1", 0x10000, 0xb6e94727, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11865.b5", 0x10000, 0x17e8d5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11863.b2", 0x10000, 0x3e670098, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11866.b6", 0x10000, 0x50eb71cc, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11864.b3", 0x10000, 0x05733ca8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11867.b7", 0x10000, 0x81e49697, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11857.a7", 0x08000, 0x789edc06, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11858.a8", 0x08000, 0x08ab0018, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11859.a9", 0x08000, 0x8673e01b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11860.a10", 0x08000, 0x10263746, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11861.a11", 0x08000, 0x38b54a71, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0070.key", 0x02000, 0x5d0308aa, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Passshtj) +STD_ROM_FN(Passshtj) + +static struct BurnRomInfo PassshtbRomDesc[] = { + { "pass3_2p.bin", 0x10000, 0x26bb9299, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "pass4_2p.bin", 0x10000, 0x06ac6d5d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr11854.b9", 0x10000, 0xd31c0b6c, SYS16_ROM_TILES | BRF_GRA }, + { "opr11855.b10", 0x10000, 0xb78762b4, SYS16_ROM_TILES | BRF_GRA }, + { "opr11856.b11", 0x10000, 0xea49f666, SYS16_ROM_TILES | BRF_GRA }, + + { "opr11862.b1", 0x10000, 0xb6e94727, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr11865.b5", 0x10000, 0x17e8d5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr11863.b2", 0x10000, 0x3e670098, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr11866.b6", 0x10000, 0x50eb71cc, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr11864.b3", 0x10000, 0x05733ca8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr11867.b7", 0x10000, 0x81e49697, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr11857.a7", 0x08000, 0x789edc06, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr11858.a8", 0x08000, 0x08ab0018, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr11859.a9", 0x08000, 0x8673e01b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr11860.a10", 0x08000, 0x10263746, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr11861.a11", 0x08000, 0x38b54a71, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Passshtb) +STD_ROM_FN(Passshtb) + +static struct BurnRomInfo RiotcityRomDesc[] = { + { "epr-14612.bin", 0x20000, 0xa1b331ec, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14610.bin", 0x20000, 0xcd4f2c50, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14613.bin", 0x20000, 0x0659df4c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14611.bin", 0x20000, 0xd9e6f80b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14616.bin", 0x20000, 0x46d30368, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14625.bin", 0x20000, 0xabfb80fe, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14617.bin", 0x20000, 0x884e40f9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14626.bin", 0x20000, 0x4ef55846, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14618.bin", 0x20000, 0x00eb260e, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14627.bin", 0x20000, 0x961e5f82, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-14619.bin", 0x40000, 0x6f2b5ef7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14622.bin", 0x40000, 0x7ca7e40d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14620.bin", 0x40000, 0x66183333, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14623.bin", 0x40000, 0x98630049, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14621.bin", 0x40000, 0xc0f2820e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14624.bin", 0x40000, 0xd1a68448, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14614.bin", 0x10000, 0xc65cc69a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-14615.bin", 0x20000, 0x46653db1, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Riotcity) +STD_ROM_FN(Riotcity) + +static struct BurnRomInfo RyukyuRomDesc[] = { + { "epr-13348.a7", 0x10000, 0x5f0e0c86, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13347.a5", 0x10000, 0x398031fa, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-13351.a14", 0x20000, 0xa68a4e6d, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13352.a15", 0x20000, 0x5e5531e4, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13353.a16", 0x20000, 0x6d23dfd8, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-13354.b1", 0x20000, 0xf07aad99, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13356.b5", 0x20000, 0x5498290b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13355.b2", 0x20000, 0x67890019, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13357.b6", 0x20000, 0xf9e7cf03, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13349.a10", 0x08000, 0xb83183f8, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-13350.a11", 0x20000, 0x3c59a658, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-5023.key", 0x02000, 0x43704331, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Ryukyu) +STD_ROM_FN(Ryukyu) + +static struct BurnRomInfo SdibRomDesc[] = { + { "epr-10986a.a4", 0x08000, 0x3e136215, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10984a.a1", 0x08000, 0x44bf3cf5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10987a.a5", 0x08000, 0xcfd79404, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10985a.a2", 0x08000, 0x1c21a03f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10829.a6", 0x08000, 0xa431ab08, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10826.a3", 0x08000, 0x2ed8e4b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10772.b9", 0x10000, 0x182b6301, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10773.b10", 0x10000, 0x8f7129a2, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10774.b11", 0x10000, 0x4409411f, SYS16_ROM_TILES | BRF_GRA }, + + { "10760.b1", 0x10000, 0x70de327b, SYS16_ROM_SPRITES | BRF_GRA }, + { "10763.b5", 0x10000, 0x99ec5cb5, SYS16_ROM_SPRITES | BRF_GRA }, + { "10761.b2", 0x10000, 0x4e80f80d, SYS16_ROM_SPRITES | BRF_GRA }, + { "10764.b6", 0x10000, 0x602da5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "10762.b3", 0x10000, 0x464b5f78, SYS16_ROM_SPRITES | BRF_GRA }, + { "10765.b7", 0x10000, 0x0a73a057, SYS16_ROM_SPRITES | BRF_GRA }, + + { "10775.a7", 0x08000, 0x4cbd55a8, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0028.key", 0x02000, 0x9a5307b2, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sdib) +STD_ROM_FN(Sdib) + +static struct BurnRomInfo SdiblRomDesc[] = { + { "a4.rom", 0x08000, 0xf2c41dd6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a1.rom", 0x08000, 0xa9f816ef, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a5.rom", 0x08000, 0x7952e27e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a2.rom", 0x08000, 0x369af326, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a6.rom", 0x08000, 0x8ee2c287, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "a3.rom", 0x08000, 0x193e4231, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10772.b9", 0x10000, 0x182b6301, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10773.b10", 0x10000, 0x8f7129a2, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10774.b11", 0x10000, 0x4409411f, SYS16_ROM_TILES | BRF_GRA }, + + { "b1.rom", 0x10000, 0x30e2c50a, SYS16_ROM_SPRITES | BRF_GRA }, + { "b5.rom", 0x10000, 0x794e3e8b, SYS16_ROM_SPRITES | BRF_GRA }, + { "b2.rom", 0x10000, 0x6a8b3fd0, SYS16_ROM_SPRITES | BRF_GRA }, + { "10764.b6", 0x10000, 0x602da5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "b3.rom", 0x10000, 0xb9de3aeb, SYS16_ROM_SPRITES | BRF_GRA }, + { "10765.b7", 0x10000, 0x0a73a057, SYS16_ROM_SPRITES | BRF_GRA }, + + { "a7.rom", 0x08000, 0x793f9f7f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sdibl) +STD_ROM_FN(Sdibl) + +static struct BurnRomInfo DefenseRomDesc[] = { + { "epr-10917a.a4", 0x08000, 0xd91ac47c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10915.a1", 0x08000, 0x7344c510, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10918a.a5", 0x08000, 0xe41befcd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10916a.a2", 0x08000, 0x7f58ba12, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10829.a6", 0x08000, 0xa431ab08, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10826.a3", 0x08000, 0x2ed8e4b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "10919.b9", 0x10000, 0x23b88f82, SYS16_ROM_TILES | BRF_GRA }, + { "10920.b10", 0x10000, 0x22b1fb4c, SYS16_ROM_TILES | BRF_GRA }, + { "10921.b11", 0x10000, 0x7788f55d, SYS16_ROM_TILES | BRF_GRA }, + + { "10760.b1", 0x10000, 0x70de327b, SYS16_ROM_SPRITES | BRF_GRA }, + { "10763.b5", 0x10000, 0x99ec5cb5, SYS16_ROM_SPRITES | BRF_GRA }, + { "10761.b2", 0x10000, 0x4e80f80d, SYS16_ROM_SPRITES | BRF_GRA }, + { "10764.b6", 0x10000, 0x602da5d5, SYS16_ROM_SPRITES | BRF_GRA }, + { "10762.b3", 0x10000, 0x464b5f78, SYS16_ROM_SPRITES | BRF_GRA }, + { "10765.b7", 0x10000, 0x0a73a057, SYS16_ROM_SPRITES | BRF_GRA }, + + { "10775.a7", 0x08000, 0x4cbd55a8, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0028.key", 0x02000, 0x9a5307b2, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Defense) +STD_ROM_FN(Defense) + +static struct BurnRomInfo Shinobi2RomDesc[] = { + { "epr-11282.a4", 0x10000, 0x5f2e5524, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11280.a1", 0x10000, 0xbdfe5c38, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11283.a5", 0x10000, 0x9d46e707, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11281.a2", 0x10000, 0x7961d07e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11284.b9", 0x10000, 0x5f62e163, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11285.b10", 0x10000, 0x75f8fbc9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11286.b11", 0x10000, 0x06508bb9, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11290.b1", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11294.b5", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11291.b2", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11295.b6", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11292.b3", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11296.b7", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11293.b4", 0x10000, 0x41f41063, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11297.b8", 0x10000, 0xb6e1fd72, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11287.a7", 0x08000, 0xe8cccd42, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11288.a8", 0x08000, 0xc8df8460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11289.a9", 0x08000, 0xe5a4cf30, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0049.key", 0x02000, 0x8fac824f, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shinobi2) +STD_ROM_FN(Shinobi2) + +static struct BurnRomInfo Shinobi3RomDesc[] = { + { "epr-11299.a4", 0x10000, 0xb930399d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11298.a1", 0x10000, 0x343f4c46, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11283.a5", 0x10000, 0x9d46e707, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11281.a2", 0x10000, 0x7961d07e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11284.b9", 0x10000, 0x5f62e163, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11285.b10", 0x10000, 0x75f8fbc9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11286.b11", 0x10000, 0x06508bb9, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11290.b1", 0x10000, 0x611f413a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11294.b5", 0x10000, 0x5eb00fc1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11291.b2", 0x10000, 0x3c0797c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11295.b6", 0x10000, 0x25307ef8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11292.b3", 0x10000, 0xc29ac34e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11296.b7", 0x10000, 0x04a437f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11293.b4", 0x10000, 0x41f41063, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11297.b8", 0x10000, 0xb6e1fd72, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11372.a7", 0x08000, 0x0824269a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11288.a8", 0x08000, 0xc8df8460, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11289.a9", 0x08000, 0xe5a4cf30, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0054.key", 0x02000, 0x39fd4535, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shinobi3) +STD_ROM_FN(Shinobi3) + +static struct BurnRomInfo Shinobi4RomDesc[] = { + { "epr-11360.a7", 0x20000, 0xb1f67ab9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11359.a5", 0x20000, 0x0f0306e1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11363.a14", 0x20000, 0x40914168, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11364.a15", 0x20000, 0xe63649a4, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11365.a16", 0x20000, 0x1ef55d20, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11366.b1", 0x20000, 0x319ede73, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11368.b5", 0x20000, 0x0377d7ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11367.b2", 0x20000, 0x1d06c5c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11369.b6", 0x20000, 0xd751d2a2, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11377.a10", 0x08000, 0x0fb6af34, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11362.a11", 0x20000, 0x256af749, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0054.key", 0x02000, 0x39fd4535, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Shinobi4) +STD_ROM_FN(Shinobi4) + +static struct BurnRomInfo Shinobi5RomDesc[] = { + { "epr-11360.a7", 0x20000, 0xb1f67ab9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11359.a5", 0x20000, 0x0f0306e1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11363.a14", 0x20000, 0x40914168, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11364.a15", 0x20000, 0xe63649a4, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11365.a16", 0x20000, 0x1ef55d20, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11366.b1", 0x20000, 0x319ede73, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11368.b5", 0x20000, 0x0377d7ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11367.b2", 0x20000, 0x1d06c5c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11369.b6", 0x20000, 0xd751d2a2, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11361.a10", 0x08000, 0x1f47ebcb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11362.a11", 0x20000, 0x256af749, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shinobi5) +STD_ROM_FN(Shinobi5) + +static struct BurnRomInfo SjryukoRomDesc[] = { + { "epr-12256.a4", 0x08000, 0x5987ee1b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12253.a1", 0x08000, 0x26a822df, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12257.a5", 0x08000, 0x3a2acc3f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12254.a2", 0x08000, 0x7e908217, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12224-95.b9", 0x08000, 0xeac17ba1, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12225-94.b10", 0x08000, 0x2310fc98, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12226-93.b11", 0x08000, 0x210e6999, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12232-10.b1", 0x10000, 0x0adec62b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12236-11.b5", 0x10000, 0x286b9af8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12233-17.b2", 0x10000, 0x3e45969c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12237-18.b6", 0x10000, 0xe5058e96, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12234-23.b3", 0x10000, 0x8c8d54ef, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12238-24.b7", 0x10000, 0x7ada3304, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12235-29.b4", 0x10000, 0xfa45d511, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12239-30.b8", 0x10000, 0x91f70c8b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12244.a7", 0x08000, 0xcb2a47e5, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12245.a8", 0x08000, 0x66164134, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12246.a9", 0x08000, 0xf1242582, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12247.a10", 0x08000, 0xef8a64c6, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12248.a11", 0x08000, 0xd1eabdab, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-5021.key", 0x02000, 0x4a3422e4, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sjryuko) +STD_ROM_FN(Sjryuko) + +static struct BurnRomInfo SnapperRomDesc[] = { + { "snap2.r01", 0x10000, 0x9a9e4ed3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "snap1.r02", 0x10000, 0xcd468d6a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "snap4.r03", 0x08000, 0x0f848e1e, SYS16_ROM_TILES | BRF_GRA }, + { "snap3.r04", 0x08000, 0xc7f8cf0e, SYS16_ROM_TILES | BRF_GRA }, + { "snap5.r05", 0x08000, 0x378e08eb, SYS16_ROM_TILES | BRF_GRA }, +}; + + +STD_ROM_PICK(Snapper) +STD_ROM_FN(Snapper) + +static struct BurnRomInfo SonicbomRomDesc[] = { + { "epr-11342.a4", 0x10000, 0x454693f1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11340.a1", 0x10000, 0x03ba3fed, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11343.a5", 0x10000, 0xedfeb7d4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11341.a2", 0x10000, 0x0338f771, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-11344.b9", 0x10000, 0x59a9f940, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11345.b10", 0x10000, 0xb44c068b, SYS16_ROM_TILES | BRF_GRA }, + { "opr-11346.b11", 0x10000, 0xe5ada66c, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-11350.b1", 0x10000, 0x525ba1df, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11354.b5", 0x10000, 0x793fa3ac, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11351.b2", 0x10000, 0x63b1f1ca, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11355.b6", 0x10000, 0xfe0fa332, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11352.b3", 0x10000, 0x047fa4b0, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11356.b7", 0x10000, 0xaea3c39d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11353.b4", 0x10000, 0x4e0791f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-11357.b8", 0x10000, 0xa7c5ea41, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11347.a7", 0x08000, 0xb41f0ced, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11348.a8", 0x08000, 0x89924588, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11349.a9", 0x08000, 0x8e4b6204, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0053.key", 0x02000, 0x91c80c88, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Sonicbom) +STD_ROM_FN(Sonicbom) + +static struct BurnRomInfo SuprleagRomDesc[] = { + { "epr-11133.a04", 0x10000, 0xeed72f37, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11130.a01", 0x10000, 0xe2451676, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11134.a05", 0x10000, 0xccd857f5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11131.a02", 0x10000, 0x9b78c2cc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11135.a06", 0x10000, 0x3735e0e1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11132.a03", 0x10000, 0xff199325, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11136.b09", 0x10000, 0xc3860ce4, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11137.b10", 0x10000, 0x92d96187, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11138.b11", 0x10000, 0xc01dc773, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11144.b01", 0x10000, 0xb31de51c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11148.b05", 0x10000, 0x126e1309, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11145.b02", 0x10000, 0x4223d2c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11149.b06", 0x10000, 0x694d3765, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11146.b03", 0x10000, 0xbf0359b6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11150.b07", 0x10000, 0x9fc0aded, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11147.b04", 0x10000, 0x3e592772, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11151.b08", 0x10000, 0x9de95169, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11139.a07", 0x08000, 0x9cbd99da, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11140.a08", 0x08000, 0xb297371b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11141.a09", 0x08000, 0x19756aa6, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11142.a10", 0x08000, 0x25d26c66, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-11143.a11", 0x08000, 0x848b7b77, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0045.key", 0x02000, 0x0594cc2e, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Suprleag) +STD_ROM_FN(Suprleag) + +static struct BurnRomInfo Tetris1RomDesc[] = { + { "epr-12164.a4", 0x08000, 0xb329cd6f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12163.a1", 0x08000, 0xd372d3f3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12165.b9", 0x10000, 0x62640221, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12166.b10", 0x10000, 0x9abd183b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12167.b11", 0x10000, 0x2495fd4e, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12169.b1", 0x08000, 0xdacc6165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12170.b5", 0x08000, 0x87354e42, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12168.a7", 0x08000, 0xbd9ba01b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0091.key", 0x02000, 0xa7937661, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Tetris1) +STD_ROM_FN(Tetris1) + +static struct BurnRomInfo Tetris2RomDesc[] = { + { "epr-12193.a7", 0x20000, 0x44466ed4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12192.a5", 0x20000, 0xa1c8af00, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12165.b9", 0x10000, 0x62640221, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12166.b10", 0x10000, 0x9abd183b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12167.b11", 0x10000, 0x2495fd4e, SYS16_ROM_TILES | BRF_GRA }, + + { "obj0-o.rom", 0x10000, 0x2fb38880, SYS16_ROM_SPRITES | BRF_GRA }, + { "obj0-e.rom", 0x10000, 0xd6a02cba, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12168.a7", 0x08000, 0xbd9ba01b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0092.key", 0x02000, 0xd10e1ad9, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Tetris2) +STD_ROM_FN(Tetris2) + +static struct BurnRomInfo TetrisblRomDesc[] = { + { "rom2.bin", 0x10000, 0x4d165c38, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "rom1.bin", 0x10000, 0x1e912131, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr12165.b9", 0x10000, 0x62640221, SYS16_ROM_TILES | BRF_GRA }, + { "epr12166.b10", 0x10000, 0x9abd183b, SYS16_ROM_TILES | BRF_GRA }, + { "epr12167.b11", 0x10000, 0x2495fd4e, SYS16_ROM_TILES | BRF_GRA }, + + { "obj0-o.rom", 0x10000, 0x2fb38880, SYS16_ROM_SPRITES | BRF_GRA }, + { "obj0-e.rom", 0x10000, 0xd6a02cba, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr12168.a7", 0x08000, 0xbd9ba01b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Tetrisbl) +STD_ROM_FN(Tetrisbl) + +static struct BurnRomInfo TimescanRomDesc[] = { + { "epr-10853.a4", 0x08000, 0x24d7c5fb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10850.a1", 0x08000, 0xf1575732, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10854.a5", 0x08000, 0x82d0b237, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10851.a2", 0x08000, 0xf5ce271b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10855.a6", 0x08000, 0x63e95a53, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10852.a3", 0x08000, 0x7cd1382b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10543.b9", 0x08000, 0x07dccc37, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10544.b10", 0x08000, 0x84fb9a3a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10545.b11", 0x08000, 0xc8694bc0, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-10548.b1", 0x08000, 0xaa150735, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10552.b5", 0x08000, 0x6fcbb9f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10549.b2", 0x08000, 0x2f59f067, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10553.b6", 0x08000, 0x8a220a9f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10550.b3", 0x08000, 0xf05069ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10554.b7", 0x08000, 0xdc64f809, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10551.b4", 0x08000, 0x435d811f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10555.b8", 0x08000, 0x2143c471, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10562.a7", 0x08000, 0x3f5028bf, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-10563.a8", 0x08000, 0x9db7eddf, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Timescan) +STD_ROM_FN(Timescan) + +static struct BurnRomInfo ToryumonRomDesc[] = { + { "epr-17689.a2", 0x20000, 0x4f0dee19, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-17688.a1", 0x20000, 0x717d81c7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-17700.b11", 0x40000, 0x8f288b37, SYS16_ROM_TILES | BRF_GRA }, + { "epr-17701.b12", 0x40000, 0x6dfb025b, SYS16_ROM_TILES | BRF_GRA }, + { "epr-17702.b13", 0x40000, 0xae0b7eab, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-17692.b1", 0x20000, 0x543c4327, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17695.b4", 0x20000, 0xee60f244, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17693.b2", 0x20000, 0x4a350b3e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17696.b5", 0x20000, 0x6edb54f1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17694.b3", 0x20000, 0xb296d71d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17697.b6", 0x20000, 0x6ccb7b28, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17698.b7", 0x20000, 0xcd4dfb82, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-17699.b8", 0x20000, 0x2694ecce, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-17691.a13", 0x08000, 0x14205388, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-17690.a11", 0x40000, 0x4f9ba4e4, SYS16_ROM_UPD7759DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Toryumon) +STD_ROM_FN(Toryumon) + +static struct BurnRomInfo TturfRomDesc[] = { + { "12327.a7", 0x20000, 0x0376c593, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "12326.a5", 0x20000, 0xf998862b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "12268.a14", 0x10000, 0xe0dac07f, SYS16_ROM_TILES | BRF_GRA }, + { "12269.a15", 0x10000, 0x457a8790, SYS16_ROM_TILES | BRF_GRA }, + { "12270.a16", 0x10000, 0x69fc025b, SYS16_ROM_TILES | BRF_GRA }, + + { "12279.b1", 0x10000, 0x7a169fb1, SYS16_ROM_SPRITES | BRF_GRA }, + { "12283.b5", 0x10000, 0xae0fa085, SYS16_ROM_SPRITES | BRF_GRA }, + { "12278.b2", 0x10000, 0x961d06b7, SYS16_ROM_SPRITES | BRF_GRA }, + { "12282.b6", 0x10000, 0xe8671ee1, SYS16_ROM_SPRITES | BRF_GRA }, + { "12277.b3", 0x10000, 0xf16b6ba2, SYS16_ROM_SPRITES | BRF_GRA }, + { "12281.b7", 0x10000, 0x1ef1077f, SYS16_ROM_SPRITES | BRF_GRA }, + { "12276.b4", 0x10000, 0x838bd71f, SYS16_ROM_SPRITES | BRF_GRA }, + { "12280.b8", 0x10000, 0x639a57cb, SYS16_ROM_SPRITES | BRF_GRA }, + + { "12328.a10", 0x08000, 0x00000000, SYS16_ROM_Z80PROG | BRF_NODUMP | BRF_PRG }, + + { "12329.a11", 0x10000, 0xed9a686d, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "12330.a12", 0x10000, 0xfb762bca, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0104.bin", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Tturf) +STD_ROM_FN(Tturf) + +static struct BurnRomInfo TturfuRomDesc[] = { + { "epr-12266.bin", 0x10000, 0xf549def8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12264.bin", 0x10000, 0xf7cdb289, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12267.bin", 0x10000, 0x3c3ce191, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12265.bin", 0x10000, 0x8cdadd9a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "12268.a14", 0x10000, 0xe0dac07f, SYS16_ROM_TILES | BRF_GRA }, + { "12269.a15", 0x10000, 0x457a8790, SYS16_ROM_TILES | BRF_GRA }, + { "12270.a16", 0x10000, 0x69fc025b, SYS16_ROM_TILES | BRF_GRA }, + + { "12276.b4", 0x10000, 0x838bd71f, SYS16_ROM_SPRITES | BRF_GRA }, + { "12280.b8", 0x10000, 0x639a57cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "12277.b3", 0x10000, 0xf16b6ba2, SYS16_ROM_SPRITES | BRF_GRA }, + { "12281.b7", 0x10000, 0x1ef1077f, SYS16_ROM_SPRITES | BRF_GRA }, + { "12278.b2", 0x10000, 0x961d06b7, SYS16_ROM_SPRITES | BRF_GRA }, + { "12282.b6", 0x10000, 0xe8671ee1, SYS16_ROM_SPRITES | BRF_GRA }, + { "12279.b1", 0x10000, 0x7a169fb1, SYS16_ROM_SPRITES | BRF_GRA }, + { "12283.b5", 0x10000, 0xae0fa085, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12271.a7", 0x08000, 0x99671e52, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12272.a8", 0x08000, 0x7cf7e69f, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12273.a9", 0x08000, 0x28f0bb8b, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12274.a10", 0x08000, 0x8207f0c4, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "epr-12275.a11", 0x08000, 0x182f3c3d, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0099.bin", 0x01000, 0xf676e3e4, BRF_OPT }, +}; + + +STD_ROM_PICK(Tturfu) +STD_ROM_FN(Tturfu) + +static struct BurnRomInfo Wb3RomDesc[] = { + { "epr-12259.a7", 0x20000, 0x54927c7e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12258.a5", 0x20000, 0x01f5898c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12124.a14", 0x10000, 0xdacefb6f, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12125.a15", 0x10000, 0x9fc36df7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12126.a16", 0x10000, 0xa693fd94, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12127.a10", 0x08000, 0x0bb901bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0098.bin", 0x01000, 0x00000000, BRF_NODUMP }, +}; + + +STD_ROM_PICK(Wb3) +STD_ROM_FN(Wb3) + +static struct BurnRomInfo Wb32RomDesc[] = { + { "epr-12100.a6", 0x10000, 0xf5ca4abc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12098.a1", 0x10000, 0xd998e5e5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12101.a5", 0x10000, 0x6146492b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12099.a2", 0x10000, 0x3e243b45, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12124.b9", 0x10000, 0xdacefb6f, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12125.b10", 0x10000, 0x9fc36df7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12126.b11", 0x10000, 0xa693fd94, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12127.a7", 0x08000, 0x0bb901bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0085.key", 0x02000, 0x8150f38d, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wb32) +STD_ROM_FN(Wb32) + +static struct BurnRomInfo Wb33RomDesc[] = { + { "epr-12137.a7", 0x20000, 0x6f81238e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12136.a5", 0x20000, 0x4cf05003, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12124.a14", 0x10000, 0xdacefb6f, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12125.a15", 0x10000, 0x9fc36df7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12126.a16", 0x10000, 0xa693fd94, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12127.a10", 0x08000, 0x0bb901bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0089.key", 0x02000, 0x597d30d3, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wb33) +STD_ROM_FN(Wb33) + +static struct BurnRomInfo Wb34RomDesc[] = { + { "epr-12131.a7", 0x20000, 0xb95ecf88, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12128.a5", 0x20000, 0xb711372b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12124.a14", 0x10000, 0xdacefb6f, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12125.a15", 0x10000, 0x9fc36df7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12126.a16", 0x10000, 0xa693fd94, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12127.a10", 0x08000, 0x0bb901bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0087.key", 0x02000, 0x162cb531, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wb34) +STD_ROM_FN(Wb34) + +static struct BurnRomInfo Wb3bblRomDesc[] = { + { "wb3_03", 0x10000, 0x0019ab3b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "wb3_05", 0x10000, 0x196e17ee, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "wb3_02", 0x10000, 0xc87350cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "wb3_04", 0x10000, 0x565d5035, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "wb3_14", 0x10000, 0xd3f20bca, SYS16_ROM_TILES | BRF_GRA }, + { "wb3_15", 0x10000, 0x96ff9d52, SYS16_ROM_TILES | BRF_GRA }, + { "wb3_16", 0x10000, 0xafaf0d31, SYS16_ROM_TILES | BRF_GRA }, + + { "epr12090.b1", 0x10000, 0xaeeecfca, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12094.b5", 0x10000, 0x615e4927, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12091.b2", 0x10000, 0x8409a243, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12095.b6", 0x10000, 0xe774ec2c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12092.b3", 0x10000, 0x5c2f0d90, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12096.b7", 0x10000, 0x0cd59d6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12093.b4", 0x10000, 0x4891e7bb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr12097.b8", 0x10000, 0xe645902c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr12127.a10", 0x08000, 0x0bb901bb, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wb3bbl) +STD_ROM_FN(Wb3bbl) + +static struct BurnRomInfo WrestwarRomDesc[] = { + { "epr-12372.a7", 0x20000, 0xeeaba126, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12371.a5", 0x20000, 0x6714600a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12146.a8", 0x20000, 0xb77ba665, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12144.a6", 0x20000, 0xddf075cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12150.a14", 0x20000, 0x6a821ab9, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12151.a15", 0x20000, 0x2b1a0751, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12152.a16", 0x20000, 0xf6e190fe, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12153.b1", 0x20000, 0xffa7d368, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12157.b5", 0x20000, 0x8d7794c1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12154.b2", 0x20000, 0x0ed343f2, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12158.b6", 0x20000, 0x99458d58, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12155.b3", 0x20000, 0x3087104d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12159.b7", 0x20000, 0xabcf9bed, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12156.b4", 0x20000, 0x41b6068b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12160.b8", 0x20000, 0x97eac164, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12141.a1", 0x20000, 0x260311c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12161.b10", 0x20000, 0x35a4b1b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12142.a2", 0x10000, 0x12e38a5c, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12162.b11", 0x10000, 0xfa06fd24, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12147.a10", 0x08000, 0xc3609607, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12148.a11", 0x20000, 0xfb9a7f29, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-12149.a12", 0x20000, 0xd6617b19, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0103.bin", 0x01000, 0xaa0710f5, BRF_OPT } +}; + + +STD_ROM_PICK(Wrestwar) +STD_ROM_FN(Wrestwar) + +static struct BurnRomInfo Wrestwar1RomDesc[] = { + { "epr-12145.a7", 0x20000, 0x2af51e2e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12143.a5", 0x20000, 0x4131e345, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12146.a8", 0x20000, 0xb77ba665, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12144.a6", 0x20000, 0xddf075cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12150.a14", 0x20000, 0x6a821ab9, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12151.a15", 0x20000, 0x2b1a0751, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12152.a16", 0x20000, 0xf6e190fe, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12153.b1", 0x20000, 0xffa7d368, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12157.b5", 0x20000, 0x8d7794c1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12154.b2", 0x20000, 0x0ed343f2, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12158.b6", 0x20000, 0x99458d58, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12155.b3", 0x20000, 0x3087104d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12159.b7", 0x20000, 0xabcf9bed, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12156.b4", 0x20000, 0x41b6068b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12160.b8", 0x20000, 0x97eac164, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12141.a1", 0x20000, 0x260311c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12161.b10", 0x20000, 0x35a4b1b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12142.a2", 0x10000, 0x12e38a5c, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12162.b11", 0x10000, 0xfa06fd24, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12147.a10", 0x08000, 0xc3609607, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12148.a11", 0x20000, 0xfb9a7f29, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-12149.a12", 0x20000, 0xd6617b19, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0090.key", 0x02000, 0xb7c24c4a, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wrestwar1) +STD_ROM_FN(Wrestwar1) + +static struct BurnRomInfo Wrestwar2RomDesc[] = { + { "epr-12370.a7", 0x20000, 0xcb5dbb76, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12369.a5", 0x20000, 0x6f47dd2f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12146.a8", 0x20000, 0xb77ba665, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12144.a6", 0x20000, 0xddf075cb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12150.a14", 0x20000, 0x6a821ab9, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12151.a15", 0x20000, 0x2b1a0751, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12152.a16", 0x20000, 0xf6e190fe, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12153.b1", 0x20000, 0xffa7d368, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12157.b5", 0x20000, 0x8d7794c1, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12154.b2", 0x20000, 0x0ed343f2, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12158.b6", 0x20000, 0x99458d58, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12155.b3", 0x20000, 0x3087104d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12159.b7", 0x20000, 0xabcf9bed, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12156.b4", 0x20000, 0x41b6068b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12160.b8", 0x20000, 0x97eac164, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12141.a1", 0x20000, 0x260311c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12161.b10", 0x20000, 0x35a4b1b1, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12142.a2", 0x10000, 0x12e38a5c, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12162.b11", 0x10000, 0xfa06fd24, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12147.a10", 0x08000, 0xc3609607, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12148.a11", 0x20000, 0xfb9a7f29, SYS16_ROM_UPD7759DATA | BRF_SND }, + { "mpr-12149.a12", 0x20000, 0xd6617b19, SYS16_ROM_UPD7759DATA | BRF_SND }, + + { "317-0102.key", 0x02000, 0x28ba1bf0, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Wrestwar2) +STD_ROM_FN(Wrestwar2) + +/*==================================================== +Bootleg Z80 Handling +====================================================*/ + +UINT8 __fastcall BootlegZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x01: { + return BurnYM2151ReadStatus(); + } + + case 0x40: + case 0xc0: { + return System16SoundLatch; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read Port -> %02X\n"), a); +#endif + + return 0; +} + +void __fastcall BootlegZ80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + d &= 0xff; + + switch (a) { + case 0x00: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x01: { + BurnYM2151WriteRegister(d); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write Port -> %02X, %02X\n"), a, d); +#endif +} + +UINT8 __fastcall BootlegZ80Read(UINT16 a) +{ + switch (a) { + case 0xe000: + case 0xe800: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return System16SoundLatch; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); +#endif + + return 0; +} + +#if 0 && defined FBA_DEBUG +void __fastcall BootlegZ80Write(UINT16 a, UINT8 d) +{ + + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02X\n"), a, d); +} +#endif + +void BootlegMapZ80() +{ + ZetMapArea(0x0000, 0x7fff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0x7fff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(BootlegZ80Read); +#if 0 && defined FBA_DEBUG + ZetSetWriteHandler(BootlegZ80Write); +#endif + ZetSetInHandler(BootlegZ80PortRead); + ZetSetOutHandler(BootlegZ80PortWrite); +} + +/*==================================================== +Memory Handlers +====================================================*/ + +UINT8 __fastcall System16BReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return System16Dip[2]; + } + + case 0xc41007: { + return 0xff - System16Input[2]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall System16BWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0xc40001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xfe0007: { + System16SoundLatch = d; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall System16BWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileWordWrite(a - 0x400000, d); + return; + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall AliensynWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc00007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT8 __fastcall AtomicpReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return System16Dip[0]; + } + + case 0xc41007: { + return System16Dip[1]; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall AtomicpWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0x123407: { + // ??? + return; + } + + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x080000: { + BurnYM2413Write(0, d); + return; + } + + case 0x080002: { + BurnYM2413Write(1, d); + return; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall AurailWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xfc0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0xfc0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +UINT8 __fastcall BayrouteReadByte(UINT32 a) +{ + switch (a) { + case 0x901001: { + return 0xff - System16Input[0]; + } + + case 0x901003: { + return 0xff - System16Input[1]; + } + + case 0x901007: { + return 0xff - System16Input[2]; + } + + case 0x902001: { + return System16Dip[0]; + } + + case 0x902003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall BayrouteWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x700000 && a <= 0x70ffff) { + System16BTileByteWrite((a - 0x700000) ^ 1, d); + return; + } + + switch (a) { + case 0x900001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xff0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall BayrouteWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x700000 && a <= 0x70ffff) { + System16BTileWordWrite(a - 0x700000, d); + return; + } +} + +UINT8 __fastcall BulletReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return 0xff - System16Input[3]; + } + + case 0xc41007: { + return 0xff - System16Input[2]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall BulletWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc00007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT8 __fastcall CottonReadByte(UINT32 a) +{ + switch (a) { + case 0x601001: { + return 0xff - System16Input[0]; + } + + case 0x601003: { + return 0xff - System16Input[1]; + } + + case 0x601005: { + return 0xff; + } + + case 0x601007: { + return 0xff - System16Input[2]; + } + + case 0x602001: { + return System16Dip[0]; + } + + case 0x602003: { + return System16Dip[1]; + } + + case 0x7038f7: { + return (System16Rom[SekGetPC(0) + 1] << 8) | System16Rom[SekGetPC(0) + 0]; + } + } + + return 0xff; +} + +void __fastcall CottonWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0x100001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x100003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x600001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xff0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall CottonWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileWordWrite(a - 0x400000, d); + return; + } +} + +void __fastcall DduxWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall DduxblGfxWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc46021: { + BootlegFgPage[1] = d & 0xf; + BootlegBgPage[1] = (d >> 4) & 0xf; + return; + } + + case 0xc46023: { + BootlegFgPage[0] = d & 0xf; + BootlegBgPage[0] = (d >> 4) & 0xf; + return; + } + + case 0xc46025: { + BootlegFgPage[3] = d & 0xf; + BootlegBgPage[3] = (d >> 4) & 0xf; + return; + } + + case 0xc46027: { + BootlegFgPage[2] = d & 0xf; + BootlegBgPage[2] = (d >> 4) & 0xf; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall DduxblGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc46000: { + System16ScrollY[1] = d; + return; + } + + case 0xc46008: { + System16ScrollX[1] = (d ^ 0xffff) & 0x1ff; + return; + } + + case 0xc46010: { + System16ScrollY[0] = d; + return; + } + + case 0xc46018: { + System16ScrollX[0] = (d ^ 0xffff) & 0x1ff; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall DduxblWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc40001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xc40007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +static INT16 DunkshotTrack1X = 0; +static INT16 DunkshotTrack1Y = 0; +static INT16 DunkshotTrack2X = 0; +static INT16 DunkshotTrack2Y = 0; +static INT16 DunkshotTrack3X = 0; +static INT16 DunkshotTrack3Y = 0; +static INT16 DunkshotTrack4X = 0; +static INT16 DunkshotTrack4Y = 0; + +void DunkshotMakeAnalogInputs() +{ + if (System16InputPort2[0]) DunkshotTrack1X += 0x40; + if (System16InputPort2[1]) DunkshotTrack1X -= 0x40; + if (DunkshotTrack1X >= 0x1000) DunkshotTrack1X = 0; + if (DunkshotTrack1X < 0) DunkshotTrack1X = 0xfc0; + + if (System16InputPort2[2]) DunkshotTrack1Y -= 0x40; + if (System16InputPort2[3]) DunkshotTrack1Y += 0x40; + if (DunkshotTrack1Y >= 0x1000) DunkshotTrack1Y = 0; + if (DunkshotTrack1Y < 0) DunkshotTrack1Y = 0xfc0; + + if (System16InputPort2[4]) DunkshotTrack2X += 0x40; + if (System16InputPort2[5]) DunkshotTrack2X -= 0x40; + if (DunkshotTrack2X >= 0x1000) DunkshotTrack2X = 0; + if (DunkshotTrack2X < 0) DunkshotTrack2X = 0xfc0; + + if (System16InputPort2[6]) DunkshotTrack2Y -= 0x40; + if (System16InputPort2[7]) DunkshotTrack2Y += 0x40; + if (DunkshotTrack2Y >= 0x1000) DunkshotTrack2Y = 0; + if (DunkshotTrack2Y < 0) DunkshotTrack2Y = 0xfc0; + + if (System16InputPort3[0]) DunkshotTrack3X += 0x40; + if (System16InputPort3[1]) DunkshotTrack3X -= 0x40; + if (DunkshotTrack3X >= 0x1000) DunkshotTrack3X = 0; + if (DunkshotTrack3X < 0) DunkshotTrack3X = 0xfc0; + + if (System16InputPort3[2]) DunkshotTrack3Y -= 0x40; + if (System16InputPort3[3]) DunkshotTrack3Y += 0x40; + if (DunkshotTrack3Y >= 0x1000) DunkshotTrack3Y = 0; + if (DunkshotTrack3Y < 0) DunkshotTrack3Y = 0xfc0; + + if (System16InputPort3[4]) DunkshotTrack4X += 0x40; + if (System16InputPort3[5]) DunkshotTrack4X -= 0x40; + if (DunkshotTrack4X >= 0x1000) DunkshotTrack4X = 0; + if (DunkshotTrack4X < 0) DunkshotTrack4X = 0xfc0; + + if (System16InputPort3[6]) DunkshotTrack4Y -= 0x40; + if (System16InputPort3[7]) DunkshotTrack4Y += 0x40; + if (DunkshotTrack4Y >= 0x1000) DunkshotTrack4Y = 0; + if (DunkshotTrack4Y < 0) DunkshotTrack4Y = 0xfc0; +} + +UINT8 __fastcall DunkshotReadByte(UINT32 a) +{ + switch (a) { + case 0xc43001: { + return DunkshotTrack1X & 0xff; + } + + case 0xc43003: { + return DunkshotTrack1X >> 8; + } + + case 0xc43005: { + return DunkshotTrack1Y & 0xff; + } + + case 0xc43007: { + return DunkshotTrack1Y >> 8; + } + + case 0xc43009: { + return DunkshotTrack2X & 0xff; + } + + case 0xc4300b: { + return DunkshotTrack2X >> 8; + } + + case 0xc4300d: { + return DunkshotTrack2Y & 0xff; + } + + case 0xc4300f: { + return DunkshotTrack2Y >> 8; + } + + case 0xc43011: { + return DunkshotTrack3X & 0xff; + } + + case 0xc43013: { + return DunkshotTrack3X >> 8; + } + + case 0xc43015: { + return DunkshotTrack3Y & 0xff; + } + + case 0xc43017: { + return DunkshotTrack3Y >> 8; + } + + case 0xc43019: { + return DunkshotTrack4X & 0xff; + } + + case 0xc4301b: { + return DunkshotTrack4X >> 8; + } + + case 0xc4301d: { + return DunkshotTrack4Y & 0xff; + } + + case 0xc4301f: { + return DunkshotTrack4Y >> 8; + } + } + + return 0xff; +} + +UINT16 __fastcall EswatMultiply0ReadWord(UINT32 a) +{ + return System16MultiplyChipRead(0, (a - 0x3e0000) >> 1); +} + +void __fastcall EswatMultiply0WriteWord(UINT32 a, UINT16 d) +{ + System16MultiplyChipWrite(0, (a - 0x3e0000) >> 1, d); +} + +UINT16 __fastcall EswatCompare0ReadWord(UINT32 a) +{ + return System16CompareTimerChipRead(0, (a - 0x3e1000) >> 1); +} + +void __fastcall EswatCompare0WriteWord(UINT32 a, UINT16 d) +{ + System16CompareTimerChipWrite(0, (a - 0x3e1000) >> 1, d); +} + +void __fastcall EswatSoundWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x123407: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall EswatWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3e2001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3e2003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall EswatblSoundWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc42007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall EswatblGfxWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x418031: { + System16TileBanks[1] = d & 7; + return; + } + } +} + +void __fastcall EswatblGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x418000: { + System16ScrollY[0] = d; + return; + } + + case 0x418008: { + System16ScrollX[0] = (d ^ 0xffff); + return; + } + + case 0x418010: { + System16ScrollY[1] = d; + return; + } + + case 0x418018: { + System16ScrollX[1] = (d ^ 0xffff); + return; + } + + case 0x418020: { + BootlegFgPage[3] = (d >> 12) & 0xf; + BootlegFgPage[2] = (d >> 8) & 0xf; + BootlegFgPage[1] = (d >> 4) & 0xf; + BootlegFgPage[0] = (d >> 0) & 0xf; + return; + } + + case 0x418028: { + BootlegBgPage[3] = (d >> 12) & 0xf; + BootlegBgPage[2] = (d >> 8) & 0xf; + BootlegBgPage[1] = (d >> 4) & 0xf; + BootlegBgPage[0] = (d >> 0) & 0xf; + return; + } + } +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +static INT16 ExctleagTrack1X = 0; +static INT16 ExctleagTrack1Y = 0; +static INT16 ExctleagTrack2X = 0; +static INT16 ExctleagTrack2Y = 0; + +void ExctleagMakeAnalogInputs() +{ + if (System16InputPort4[0]) ExctleagTrack1X += 0x1; + if (System16InputPort4[1]) ExctleagTrack1X -= 0x1; + if (ExctleagTrack1X >= 0x100) ExctleagTrack1X = 0; + if (ExctleagTrack1X < 0) ExctleagTrack1X = 0xff; + + if (System16InputPort4[2]) ExctleagTrack1Y -= 0x1; + if (System16InputPort4[3]) ExctleagTrack1Y += 0x1; + if (ExctleagTrack1Y >= 0x100) ExctleagTrack1Y = 0; + if (ExctleagTrack1Y < 0) ExctleagTrack1Y = 0xff; + + if (System16InputPort4[4]) ExctleagTrack2X += 0x4; + if (System16InputPort4[5]) ExctleagTrack2X -= 0x4; + if (ExctleagTrack2X >= 0x100) ExctleagTrack2X = 0; + if (ExctleagTrack2X < 0) ExctleagTrack2X = 0xfc; + + if (System16InputPort4[6]) ExctleagTrack2Y -= 0x4; + if (System16InputPort4[7]) ExctleagTrack2Y += 0x4; + if (ExctleagTrack2Y >= 0x100) ExctleagTrack2Y = 0; + if (ExctleagTrack2Y < 0) ExctleagTrack2Y = 0xfc; +} + +UINT8 __fastcall ExctleagReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return 0xff - System16Input[3]; + } + + case 0xc41007: { + return 0xff - System16Input[2]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc43001: + case 0xc43003: { + return ExctleagTrack1X; + } + + case 0xc43005: + case 0xc43007: { + return ExctleagTrack1Y; + } + + case 0xc43009: + case 0xc4300b: { + return ExctleagTrack2X; + } + + case 0xc4300d: + case 0xc4300f: { + return ExctleagTrack2Y; + } + } + + return 0xff; +} + +void __fastcall Fantzn2xWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT8 __fastcall FpointblReadByte(UINT32 a) +{ + switch (a) { + case 0x601001: { + return 0xff - System16Input[0]; + } + + case 0x601003: { + return 0xff - System16Input[1]; + } + + case 0x601005: { + return 0xff - System16Input[2]; + } + + case 0x600001: { + return System16Dip[0]; + } + + case 0x600003: { + return System16Dip[1]; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall FpointblWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x600007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + + } + + case 0x843001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall FpointblGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc46000: { + System16ScrollY[0] = d; + return; + } + + case 0xc46008: { + System16ScrollX[0] = (d ^ 0xffff); + return; + } + + case 0xc46010: { + System16ScrollY[1] = d + 2; + return; + } + + case 0xc46018: { + System16ScrollX[1] = (d ^ 0xffff); + return; + } + + case 0xc46022: { + BootlegFgPage[3] = (d >> 12) & 0xf; + BootlegFgPage[2] = (d >> 8) & 0xf; + BootlegFgPage[1] = (d >> 4) & 0xf; + BootlegFgPage[0] = (d >> 0) & 0xf; + return; + } + + case 0xc46026: { + BootlegBgPage[0] = (d >> 12) & 0xf; + BootlegBgPage[1] = (d >> 8) & 0xf; + BootlegBgPage[2] = (d >> 4) & 0xf; + BootlegBgPage[3] = (d >> 0) & 0xf; + return; + } + } +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X, 0x%04X\n"), a, d, d ^ 0xffff); +#endif +} + +void __fastcall GoldnaxeTileWriteByte(UINT32 a, UINT8 d) +{ + System16BTileByteWrite((a - 0x100000) ^ 1, d); +} + +void __fastcall GoldnaxeTileWriteWord(UINT32 a, UINT16 d) +{ + System16BTileWordWrite(a - 0x100000, d); +} + +UINT16 __fastcall GoldnaxeMultiply0ReadWord(UINT32 a) +{ + return System16MultiplyChipRead(0, (a - 0x1f0000) >> 1); +} + +void __fastcall GoldnaxeMultiply0WriteWord(UINT32 a, UINT16 d) +{ + System16MultiplyChipWrite(0, (a - 0x1f0000) >> 1, d); +} + +UINT16 __fastcall GoldnaxeCompare0ReadWord(UINT32 a) +{ + return System16CompareTimerChipRead(0, (a - 0x1f1000) >> 1); +} + +void __fastcall GoldnaxeCompare0WriteWord(UINT32 a, UINT16 d) +{ + System16CompareTimerChipWrite(0, (a - 0x1f1000) >> 1, d); +} + +UINT16 __fastcall GoldnaxeCompare1ReadWord(UINT32 a) +{ + return System16CompareTimerChipRead(1, (a - 0x1e0000) >> 1); +} + +void __fastcall GoldnaxeCompare1WriteWord(UINT32 a, UINT16 d) +{ + System16CompareTimerChipWrite(1, (a - 0x1e0000) >> 1, d); +} + +void __fastcall Goldnaxe1WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x1f2001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x1f2003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall Goldnaxe3WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x1f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x1f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +static UINT8 HwchampInputVal; + +UINT16 __fastcall HwchampCtrlReadWord(UINT32 a) +{ + UINT16 result; + + switch (a) { + case 0xc43020: + case 0xc43022: + case 0xc43024: { + result = (HwchampInputVal & 0x80) >> 7; + HwchampInputVal <<= 1; + return result; + } + } + + return 0xffff; +} + +void __fastcall HwchampCtrlWriteWord(UINT32 a, UINT16 /*d*/) +{ + UINT8 temp = 0; + + switch (a) { + case 0xc43020: { + temp = 0x80 + (System16AnalogPort0 >> 4); + if (temp < 0x01) temp = 0x01; + if (temp > 0xfe) temp = 0xfe; + HwchampInputVal = temp; + return; + } + + case 0xc43022: { + temp = 0x26; + if (System16AnalogPort2 > 1) temp = 0xfe; + HwchampInputVal = temp; + return; + } + + case 0xc43024: { + temp = 0x26; + if (System16AnalogPort1 > 1) temp = 0xfe; + HwchampInputVal = temp; + return; + } + } +} + +void __fastcall HwchampWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall MvpWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3f2001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f2003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall MvpjWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +void __fastcall PassshtWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc00007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT8 __fastcall PassshtaReadByte(UINT32 a) +{ + switch (a) { + case 0xc43001: { + return 0xff - System16Input[1]; + } + + case 0xc43003: { + return 0xff - System16Input[2]; + } + + case 0xc43005: { + return 0xff - System16Input[3]; + } + + case 0xc43007: { + return 0xff - System16Input[4]; + } + } + + return 0xff; +} + +void __fastcall PassshtbGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc46000: { + System16ScrollY[0] = d; + return; + } + + case 0xc46002: { + System16ScrollX[0] = (d ^ 0xffff) & 0x1ff; + return; + } + + case 0xc46004: { + System16ScrollY[1] = d; + return; + } + + case 0xc46006: { + System16ScrollX[1] = (d ^ 0xffff) & 0x1ff; + return; + } + +/* case 0xc46022: { + BootlegFgPage[3] = (d >> 12) & 0xf; + BootlegFgPage[2] = (d >> 8) & 0xf; + BootlegFgPage[1] = (d >> 4) & 0xf; + BootlegFgPage[0] = (d >> 0) & 0xf; + return; + } + + case 0xc46026: { + BootlegBgPage[0] = (d >> 12) & 0xf; + BootlegBgPage[1] = (d >> 8) & 0xf; + BootlegBgPage[2] = (d >> 4) & 0xf; + BootlegBgPage[3] = (d >> 0) & 0xf; + return; + }*/ + } +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X, 0x%04X\n"), a, d, (d ^ 0xffff) & 0x1ff); +#endif +} + +UINT8 __fastcall RiotcityReadByte(UINT32 a) +{ + switch (a) { + case 0xf81001: { + return 0xff - System16Input[0]; + } + + case 0xf81003: { + return 0xff - System16Input[1]; + } + + case 0xf81007: { + return 0xff - System16Input[2]; + } + + case 0xf82001: { + return System16Dip[0]; + } + + case 0xf82003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall RiotcityWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0xfa0000 && a <= 0xfaffff) { + System16BTileByteWrite((a - 0xfa0000) ^ 1, d); + return; + } + + switch (a) { + case 0xf00007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0xf20001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0xf20003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0xf80001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + } +} + +void __fastcall RiotcityWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0xfa0000 && a <= 0xfaffff) { + System16BTileWordWrite(a - 0xfa0000, d); + return; + } +} + +UINT16 __fastcall RyukyuReadWord(UINT32 a) +{ + switch (a) { + case 0x601000: { + return 0xff - System16Input[0]; + } + + case 0x601002: { + return 0xff - System16Input[1]; + } + + case 0x602000: { + return System16Dip[0]; + } + + case 0x602002: { + return System16Dip[1]; + } + } + + return 0xffff; +} + +void __fastcall RyukyuWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileWordWrite(a - 0x400000, d); + return; + } + + switch (a) { + case 0x100000: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x100002: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x600000: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + } +} + +void __fastcall RyukyuWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xff0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +static INT16 SdiTrack1X = 0; +static INT16 SdiTrack1Y = 0; +static INT16 SdiTrack2X = 0; +static INT16 SdiTrack2Y = 0; + +void SdibMakeAnalogInputs() +{ + SdiTrack1X -= (System16AnalogPort0 >> 8) & 0xff; + SdiTrack1Y += (System16AnalogPort1 >> 8) & 0xff; + + SdiTrack2X -= (System16AnalogPort2 >> 8) & 0xff; + SdiTrack2Y += (System16AnalogPort3 >> 8) & 0xff; +} + +UINT8 __fastcall SdibReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41005: { + return 0xff - System16Input[1]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xc42005: { + return System16Dip[0]; + } + + case 0xc43001: { + return SdiTrack1X; + } + + case 0xc43005: { + return SdiTrack1Y; + } + + case 0xc43009: { + return SdiTrack2X; + } + + case 0xc4300d: { + return SdiTrack2Y; + } + } + + return 0xff; +} + +void __fastcall SdibSoundWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x123407: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +static UINT8 MahjongInputNum; + +UINT16 __fastcall SjryukoReadWord(UINT32 a) +{ + SEK_DEF_READ_WORD(0, a); + + return 0xffff; +} + +UINT8 __fastcall SjryukoReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + if (System16Input[MahjongInputNum + 1] != 0xff) return 0xff & ~(1 << MahjongInputNum); + return 0xff; + } + + case 0xc41005: { + return 0xff - System16Input[MahjongInputNum + 1]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall SjryukoWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc40003: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + if (d & 4) MahjongInputNum = (MahjongInputNum + 1) % 6; + return; + } + + case 0xc00007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT16 __fastcall SonicbomReadWord(UINT32 a) +{ + switch (a) { + case 0xc42000: { + return (0xff << 8) | System16Dip[0]; + } + + case 0xc42002: { + return (0xff << 8) | System16Dip[1]; + } + } + + return 0xffff; +} + +void __fastcall SonicbomWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x123407: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall TetrisblGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x418000: { + System16ScrollY[0] = d; + return; + } + + case 0x418008: { + System16ScrollX[0] = (d ^ 0xffff) & 0x3ff; + return; + } + + case 0x418010: { + System16ScrollY[1] = d; + return; + } + + case 0x418018: { + System16ScrollX[1] = ((d ^ 0xffff) & 0x3ff) + 2; + return; + } + + case 0x418020: { + BootlegFgPage[3] = (d >> 12) & 0xf; + BootlegFgPage[2] = (d >> 8) & 0xf; + BootlegFgPage[1] = (d >> 4) & 0xf; + BootlegFgPage[0] = (d >> 0) & 0xf; + return; + } + + case 0x418028: { + BootlegBgPage[0] = (d >> 12) & 0xf; + BootlegBgPage[1] = (d >> 8) & 0xf; + BootlegBgPage[2] = (d >> 4) & 0xf; + BootlegBgPage[3] = (d >> 0) & 0xf; + return; + } + } +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X, 0x%04X\n"), a, d, (d ^ 0xffff) & 0x3ff); +#endif +} + +void __fastcall TetrisblSndWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc42007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT8 __fastcall ToryumonReadByte(UINT32 a) +{ + switch (a) { + case 0xe41001: { + return 0xff - System16Input[0]; + } + + case 0xe41003: { + return 0xff - System16Input[1]; + } + + case 0xe41005: { + return 0; + } + + case 0xe41007: { + return 0xff - System16Input[2]; + } + + case 0xe42001: { + return System16Dip[0]; + } + + case 0xe42003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall ToryumonWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3e2001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3e2003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0xe40001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xfe0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT8 __fastcall TturfReadByte(UINT32 a) +{ + switch (a) { + case 0x602001: { + return System16Dip[0]; + } + + case 0x602003: { + return System16Dip[1]; + } + } + + return 0xff; +} + +void __fastcall TturfWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0x600001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + } +} + +void __fastcall Wb3WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xdf0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +void __fastcall Wb3bblGfxWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc46000: { + System16ScrollY[0] = d; + return; + } + + case 0xc46002: { + System16ScrollX[0] = (d ^ 0xffff) & 0x3ff; + return; + } + + case 0xc46004: { + System16ScrollY[1] = d; + return; + } + + case 0xc46006: { + System16ScrollX[1] = (d ^ 0xffff) & 0x3ff; + return; + } + +/* case 0xc46022: { + BootlegFgPage[3] = (d >> 12) & 0xf; + BootlegFgPage[2] = (d >> 8) & 0xf; + BootlegFgPage[1] = (d >> 4) & 0xf; + BootlegFgPage[0] = (d >> 0) & 0xf; + return; + } + + case 0xc46026: { + BootlegBgPage[0] = (d >> 12) & 0xf; + BootlegBgPage[1] = (d >> 8) & 0xf; + BootlegBgPage[2] = (d >> 4) & 0xf; + BootlegBgPage[3] = (d >> 0) & 0xf; + return; + }*/ + } +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X, 0x%04X\n"), a, d, d ^ 0xffff); +#endif +} + +void __fastcall WrestwarTileWriteByte(UINT32 a, UINT8 d) +{ + System16BTileByteWrite((a - 0x100000) ^ 1, d); +} + +void __fastcall WrestwarTileWriteWord(UINT32 a, UINT16 d) +{ + System16BTileWordWrite(a - 0x100000, d); +} + +void __fastcall WrestwarWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x400001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x400003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + } +} + +/*==================================================== +Driver Inits +====================================================*/ + +static INT32 Fantzn2xPlaneOffsets[3] = { 1, 2, 3 }; +static INT32 Fantzn2xXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 Fantzn2xYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + +static INT32 AliensynInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc00006, 0xc00007, SM_WRITE); + SekSetWriteByteHandler(1, AliensynWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 Aliensyn3Init() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc00006, 0xc00007, SM_WRITE); + SekSetWriteByteHandler(1, AliensynWriteByte); + SekClose(); + } + + return nRet; +} + +void Altbeast_Sim8751() +{ + // System Inputs + *((UINT16*)(System16Ram + 0x30c2)) = (UINT16)(System16Input[0] << 8); + + // Tile Banking + System16TileBanks[1] = ((System16Ram[0x3094 + 1] << 8) | System16Ram[0x3094 + 0]) & 7; + + // Sound command + UINT16 temp = (System16Ram[0x30c4 + 1] << 8) | System16Ram[0x30c4 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x30c4)) = (UINT16)(temp & 0xff); + } +} + +void Altbeastj_Sim8751() +{ + // System Inputs + *((UINT16*)(System16Ram + 0x30d0)) = (UINT16)(System16Input[0] << 8); + + // Tile Banking + System16TileBanks[1] = ((System16Ram[0x3094 + 1] << 8) | System16Ram[0x3094 + 0]) & 7; + + // Sound command + UINT16 temp = (System16Ram[0x30d4 + 1] << 8) | System16Ram[0x30d4 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x30d4)) = (UINT16)(temp & 0xff); + } +} + +void Altbeast5_Sim8751() +{ + // System Inputs + *((UINT16*)(System16Ram + 0x3096)) = (UINT16)(System16Input[0] << 8); + + // Tile Banking + System16TileBanks[1] = ((System16Ram[0x3094 + 1] << 8) | System16Ram[0x3094 + 0]) & 7; + + // Sound command + UINT16 temp = (System16Ram[0x3098 + 1] << 8) | System16Ram[0x3098 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x3098)) = (UINT16)(temp & 0xff); + } +} + +static INT32 AltbeastInit() +{ + Simulate8751 = Altbeast_Sim8751; + + return System16Init(); +} + +static INT32 AltbeastjInit() +{ + Simulate8751 = Altbeastj_Sim8751; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1a0000 - 0xe0000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0xe0000); + memset(System16Sprites, 0, 0x1a0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + memcpy(System16Sprites + 0x100000, pTemp + 0x80000, 0x20000); + memcpy(System16Sprites + 0x140000, pTemp + 0xa0000, 0x20000); + memcpy(System16Sprites + 0x180000, pTemp + 0xc0000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Altbeast5Init() +{ + Simulate8751 = Altbeast5_Sim8751; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1a0000 - 0xe0000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0xe0000); + memset(System16Sprites, 0, 0x1a0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + memcpy(System16Sprites + 0x100000, pTemp + 0x80000, 0x20000); + memcpy(System16Sprites + 0x140000, pTemp + 0xa0000, 0x20000); + memcpy(System16Sprites + 0x180000, pTemp + 0xc0000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Altbeastj3Init() +{ + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1a0000 - 0xe0000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0xe0000); + memset(System16Sprites, 0, 0x1a0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + memcpy(System16Sprites + 0x100000, pTemp + 0x80000, 0x20000); + memcpy(System16Sprites + 0x140000, pTemp + 0xa0000, 0x20000); + memcpy(System16Sprites + 0x180000, pTemp + 0xc0000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Altbeast4Init() +{ + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1a0000 - 0xe0000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0xe0000); + memset(System16Sprites, 0, 0x1a0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + memcpy(System16Sprites + 0x100000, pTemp + 0x80000, 0x20000); + memcpy(System16Sprites + 0x140000, pTemp + 0xa0000, 0x20000); + memcpy(System16Sprites + 0x180000, pTemp + 0xc0000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +void AtomicpMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x01ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x01ffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, System16BWriteWord); + SekSetReadByteHandler(0, AtomicpReadByte); + SekSetWriteByteHandler(0, AtomicpWriteByte); + SekClose(); +} + +static INT32 AtomicpInit() +{ + System16Map68KDo = AtomicpMap68K; + + INT32 nRet = System16Init(); + + System16IgnoreVideoEnable = 1; + System16YM2413IRQInterval = 166; + + return nRet; +} + +static INT32 AurailInit() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xfc0000, 0xfc0003, SM_WRITE); + SekSetWriteByteHandler(1, AurailWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 Aurail1Init() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xfc0000, 0xfc0003, SM_WRITE); + SekSetWriteByteHandler(1, AurailWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 AurailjInit() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xfc0000, 0xfc0003, SM_WRITE); + SekSetWriteByteHandler(1, AurailWriteByte); + SekClose(); + } + + return nRet; +} + +void BayrouteMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16Ram , 0x500000, 0x503fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x600000, 0x6007ff, SM_RAM); + SekMapMemory(System16TileRam , 0x700000, 0x70ffff, SM_READ); + SekMapMemory(System16TextRam , 0x710000, 0x710fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x800000, 0x800fff, SM_RAM); + SekSetReadByteHandler(0, BayrouteReadByte); + SekSetWriteByteHandler(0, BayrouteWriteByte); + SekSetWriteWordHandler(0, BayrouteWriteWord); + SekClose(); +} + +static INT32 BayrouteInit() +{ + System16Map68KDo = BayrouteMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + return nRet; +} + +static INT32 Bayroute1Init() +{ + System16Map68KDo = BayrouteMap68K; + System16CustomLoadRomDo = CustomLoadRom20000; + + INT32 nRet = System16Init(); + + return nRet; +} + +void Blox16bMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, System16BWriteWord); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, Fantzn2xWriteByte); + SekClose(); +} + +static INT32 Blox16bLoadRom() +{ + if (BurnLoadRom(System16Rom + 0x00000, 0, 1)) return 1; + + System16TempGfx = (UINT8*)malloc(System16TileRomSize); + BurnLoadRom(System16TempGfx, 1, 1); + GfxDecode(0x2000, 3, 8, 8, Fantzn2xPlaneOffsets, Fantzn2xXOffsets, Fantzn2xYOffsets, 0x100, System16TempGfx, System16Tiles); + System16NumTiles = 0x2000; + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + + BurnLoadRom(System16Sprites, 2, 1); + BurnByteswap(System16Sprites, System16SpriteRomSize); + + if (BurnLoadRom(System16Z80Rom, 3, 1)) return 1; + memcpy(System16UPD7759Data, System16Z80Rom + 0x10000, 0x08000); + + return 0; +} + +static INT32 Blox16bInit() +{ + System16Map68KDo = Blox16bMap68K; + System16CustomLoadRomDo = Blox16bLoadRom; + System16UPD7759DataSize = 0x08000; + + INT32 nRet = System16Init(); + + return nRet; +} + +static INT32 BulletInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, BulletReadByte); + SekMapHandler(1, 0xc00006, 0xc00007, SM_WRITE); + SekSetWriteByteHandler(1, BulletWriteByte); + SekClose(); + } + return nRet; +} + +void CottonMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0fffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0fffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x300000, 0x3007ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(System16Ram , 0x200000, 0x203fff, SM_RAM); + SekSetReadByteHandler(0, CottonReadByte); + SekSetWriteByteHandler(0, CottonWriteByte); + SekSetWriteWordHandler(0, CottonWriteWord); + SekClose(); +} + +static INT32 CottonInit() +{ + System16Map68KDo = CottonMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + return nRet; +} + +void Ddux_Sim8751() +{ + // Sound command + UINT16 temp = (System16Ram[0x0bd0 + 1] << 8) | System16Ram[0x0bd0 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x0bd0)) = (UINT16)(temp & 0xff); + } +} + +static INT32 DduxInit() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, DduxWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 Ddux1Init() +{ + Simulate8751 = Ddux_Sim8751; + System16CustomLoadRomDo = CustomLoadRom40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, DduxWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 DduxblInit() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + System16SpriteXOffset = 112; + + System16MapZ80Do = BootlegMapZ80; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetWriteByteHandler(0, DduxblWriteByte); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, DduxWriteByte); + SekMapHandler(2, 0xc46000, 0xc46027, SM_WRITE); + SekSetWriteByteHandler(2, DduxblGfxWriteByte); + SekSetWriteWordHandler(2, DduxblGfxWriteWord); + SekClose(); + + bSystem16BootlegRender = true; + } + + return nRet; +} + +static INT32 DunkshotInit() +{ + System16MakeAnalogInputsDo = DunkshotMakeAnalogInputs; + + System16BTileAlt = true; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x80000 - 0x40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc43000, 0xc4301f, SM_READ); + SekSetReadByteHandler(1, DunkshotReadByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x80000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x80000); + memset(System16Sprites, 0, 0x80000); + memcpy(System16Sprites + 0x00000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x10000, pTemp + 0x00000, 0x10000); + memcpy(System16Sprites + 0x20000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x30000, pTemp + 0x10000, 0x10000); + memcpy(System16Sprites + 0x40000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x50000, pTemp + 0x20000, 0x10000); + memcpy(System16Sprites + 0x60000, pTemp + 0x30000, 0x10000); + memcpy(System16Sprites + 0x70000, pTemp + 0x30000, 0x10000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 DunkshotExit() +{ + DunkshotTrack1X = 0; + DunkshotTrack1Y = 0; + DunkshotTrack2X = 0; + DunkshotTrack2Y = 0; + DunkshotTrack3X = 0; + DunkshotTrack3Y = 0; + DunkshotTrack4X = 0; + DunkshotTrack4Y = 0; + + return System16Exit(); +} + +static INT32 DunkshotScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(DunkshotTrack1X); + SCAN_VAR(DunkshotTrack1Y); + SCAN_VAR(DunkshotTrack2X); + SCAN_VAR(DunkshotTrack2Y); + SCAN_VAR(DunkshotTrack3X); + SCAN_VAR(DunkshotTrack3Y); + SCAN_VAR(DunkshotTrack4X); + SCAN_VAR(DunkshotTrack4Y); + } + + return System16Scan(nAction, pnMin);; +} + +void EswatMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekSetWriteWordHandler(0, System16BWriteWord); + SekClose(); +} + +static INT32 EswatInit() +{ + System16Map68KDo = EswatMap68K; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x123406, 0x123407, SM_WRITE); + SekSetWriteByteHandler(1, EswatSoundWriteByte); + + SekMapHandler(2, 0x3e0000, 0x3e0fff, SM_RAM); + SekSetReadWordHandler(2, EswatMultiply0ReadWord); + SekSetWriteWordHandler(2, EswatMultiply0WriteWord); + + SekMapHandler(3, 0x3e1000, 0x3e1fff, SM_RAM); + SekSetReadWordHandler(3, EswatCompare0ReadWord); + SekSetWriteWordHandler(3, EswatCompare0WriteWord); + + SekMapHandler(4, 0x3e2000, 0x3e2003, SM_WRITE); + SekSetWriteByteHandler(4, EswatWriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 EswatblInit() +{ + System16Map68KDo = EswatMap68K; + + System16SpriteXOffset = 124; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x418000, 0x418031, SM_WRITE); + SekSetWriteWordHandler(1, EswatblGfxWriteWord); + SekSetWriteByteHandler(1, EswatblGfxWriteByte); + + SekMapHandler(2, 0xc42006, 0xc42007, SM_WRITE); + SekSetWriteByteHandler(2, EswatblSoundWriteByte); + + SekMapHandler(3, 0x3e2000, 0x3e2003, SM_WRITE); + SekSetWriteByteHandler(3, EswatWriteByte); + + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + bSystem16BootlegRender = true; + } + + return nRet; +} + +static INT32 ExctleagInit() +{ + System16MakeAnalogInputsDo = ExctleagMakeAnalogInputs; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, ExctleagReadByte); + SekClose(); + } + + return nRet; +} + +static INT32 ExctleagExit() +{ + ExctleagTrack1X = 0; + ExctleagTrack1Y = 0; + ExctleagTrack2X = 0; + ExctleagTrack2Y = 0; + + return System16Exit(); +} + +static INT32 ExctleagScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(ExctleagTrack1X); + SCAN_VAR(ExctleagTrack1Y); + SCAN_VAR(ExctleagTrack2X); + SCAN_VAR(ExctleagTrack2Y); + } + + return System16Scan(nAction, pnMin);; +} + +void Fantzn2xMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(System16Rom + 0x40000 , 0x080000, 0x0bffff, SM_ROM); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0x200000, 0x23ffff, SM_RAM); + SekSetWriteWordHandler(0, System16BWriteWord); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, Fantzn2xWriteByte); + SekClose(); +} + +static INT32 Fantzn2xLoadRom() +{ + if (BurnLoadRom(System16Rom + 0x00000, 0, 1)) return 1; + if (BurnLoadRom(System16Rom + 0x40000, 1, 1)) return 1; + + System16TempGfx = (UINT8*)malloc(System16TileRomSize); + BurnLoadRom(System16TempGfx, 2, 1); + GfxDecode(0x4000, 3, 8, 8, Fantzn2xPlaneOffsets, Fantzn2xXOffsets, Fantzn2xYOffsets, 0x100, System16TempGfx, System16Tiles); + System16NumTiles = 0x4000; + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + + BurnLoadRom(System16Sprites, 3, 1); + + if (BurnLoadRom(System16Z80Rom, 4, 1)) return 1; + memcpy(System16UPD7759Data, System16Z80Rom + 0x10000, 0x20000); + + return 0; +} + +static INT32 Fantzn2xInit() +{ + System16Map68KDo = Fantzn2xMap68K; + System16CustomLoadRomDo = Fantzn2xLoadRom; + System16UPD7759DataSize = 0x20000; + + INT32 nRet = System16Init(); + + return nRet; +} + +void FantzntaMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetWriteWordHandler(0, System16BWriteWord); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, Fantzn2xWriteByte); + SekClose(); +} + +static INT32 FantzntaLoadRom() +{ + if (BurnLoadRom(System16Rom + 0x00000, 0, 1)) return 1; + + System16TempGfx = (UINT8*)malloc(System16TileRomSize); + BurnLoadRom(System16TempGfx, 1, 1); + GfxDecode(0x2000, 3, 8, 8, Fantzn2xPlaneOffsets, Fantzn2xXOffsets, Fantzn2xYOffsets, 0x100, System16TempGfx, System16Tiles); + System16NumTiles = 0x2000; + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + + BurnLoadRom(System16Sprites, 2, 1); + BurnByteswap(System16Sprites, System16SpriteRomSize); + + if (BurnLoadRom(System16Z80Rom, 3, 1)) return 1; + memcpy(System16UPD7759Data, System16Z80Rom + 0x10000, 0x10000); + + return 0; +} + +static INT32 FantzntaInit() +{ + System16Map68KDo = FantzntaMap68K; + System16CustomLoadRomDo = FantzntaLoadRom; + System16UPD7759DataSize = 0x10000; + + INT32 nRet = System16Init(); + + return nRet; +} + +static INT32 FpointblInit() +{ + System16MapZ80Do = BootlegMapZ80; + + INT32 nRet = System16Init(); + + System16SpriteXOffset = 109; + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, FpointblReadByte); + SekSetWriteByteHandler(0, FpointblWriteByte); + + SekMapHandler(1, 0xc46000, 0xc46031, SM_WRITE); + SekSetWriteWordHandler(1, FpointblGfxWriteWord); + SekClose(); + + bSystem16BootlegRender = true; + } + + return nRet; +} + +void GoldnaxeMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x100000, 0x10ffff, SM_READ); + SekMapMemory(System16TextRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x200000, 0x2007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x300000, 0x3007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x400000, 0x4007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x500000, 0x5007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x700000, 0x7007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x800000, 0x8007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x900000, 0x9007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x600000, 0x6007ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x140000, 0x140fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + + SekMapHandler(1, 0x100000, 0x10ffff, SM_WRITE); + SekSetWriteByteHandler(1, GoldnaxeTileWriteByte); + SekSetWriteWordHandler(1, GoldnaxeTileWriteWord); + SekClose(); +} + +void Goldnaxe_Sim8751() +{ + // Protection MCU + UINT16 temp1 = (System16Ram[0x2cd8 + 1] << 8) | System16Ram[0x2cd8 + 0]; + UINT16 temp2 = (System16Ram[0x2cda + 1] << 8) | System16Ram[0x2cda + 0]; + UINT16 temp3 = (System16Ram[0x2cdc + 1] << 8) | System16Ram[0x2cdc + 0]; + UINT16 temp4 = (System16Ram[0x2cde + 1] << 8) | System16Ram[0x2cde + 0]; + if (temp1 == 0 && temp2 == 0 && temp3 == 0 && temp4 == 0) { + *((UINT16*)(System16Ram + 0x2cd8)) = 0x048c; + *((UINT16*)(System16Ram + 0x2cda)) = 0x159d; + *((UINT16*)(System16Ram + 0x2cdc)) = 0x26ae; + *((UINT16*)(System16Ram + 0x2cde)) = 0x37bf; + } + + // Sound command + UINT16 temp = (System16Ram[0x2cfc + 1] << 8) | System16Ram[0x2cfc + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x2cfc)) = (UINT16)(temp & 0xff); + } + + // Inputs + *((UINT16*)(System16Ram + 0x2cd0)) = (UINT16)(~((System16Input[1] << 8) | System16Input[2])); + *((UINT16*)(System16Ram + 0x2c96)) = (UINT16)(~System16Input[0] << 8); +} + +static INT32 GoldnaxeInit() +{ + Simulate8751 = Goldnaxe_Sim8751; + System16Map68KDo = GoldnaxeMap68K; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(2, 0x1e0000, 0x1e0fff, SM_RAM); + SekSetReadWordHandler(2, GoldnaxeCompare1ReadWord); + SekSetWriteWordHandler(2, GoldnaxeCompare1WriteWord); + + SekMapHandler(3, 0x1f0000, 0x1f0fff, SM_RAM); + SekSetReadWordHandler(3, GoldnaxeMultiply0ReadWord); + SekSetWriteWordHandler(3, GoldnaxeMultiply0WriteWord); + + SekMapHandler(4, 0x1f1000, 0x1f1fff, SM_RAM); + SekSetReadWordHandler(4, GoldnaxeCompare0ReadWord); + SekSetWriteWordHandler(4, GoldnaxeCompare0WriteWord); + + SekMapHandler(5, 0x1f2000, 0x1f2003, SM_WRITE); + SekSetWriteByteHandler(5, Goldnaxe1WriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Goldnaxe1Init() +{ + System16Map68KDo = GoldnaxeMap68K; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(2, 0x1e0000, 0x1e0fff, SM_RAM); + SekSetReadWordHandler(2, GoldnaxeCompare1ReadWord); + SekSetWriteWordHandler(2, GoldnaxeCompare1WriteWord); + + SekMapHandler(3, 0x1f0000, 0x1f0fff, SM_RAM); + SekSetReadWordHandler(3, GoldnaxeMultiply0ReadWord); + SekSetWriteWordHandler(3, GoldnaxeMultiply0WriteWord); + + SekMapHandler(4, 0x1f1000, 0x1f1fff, SM_RAM); + SekSetReadWordHandler(4, GoldnaxeCompare0ReadWord); + SekSetWriteWordHandler(4, GoldnaxeCompare0WriteWord); + + SekMapHandler(5, 0x1f2000, 0x1f2003, SM_WRITE); + SekSetWriteByteHandler(5, Goldnaxe1WriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Goldnaxe2Init() +{ + Simulate8751 = Goldnaxe_Sim8751; + System16Map68KDo = GoldnaxeMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(2, 0x1f0000, 0x1f0003, SM_WRITE); + SekSetWriteByteHandler(2, Goldnaxe3WriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Goldnaxe3Init() +{ + System16Map68KDo = GoldnaxeMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(2, 0x1f0000, 0x1f0003, SM_WRITE); + SekSetWriteByteHandler(2, Goldnaxe3WriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 HwchampInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, HwchampWriteByte); + + SekMapHandler(2, 0xc43020, 0xc43025, SM_RAM); + SekSetReadWordHandler(2, HwchampCtrlReadWord); + SekSetWriteWordHandler(2, HwchampCtrlWriteWord); + SekClose(); + } + + return nRet; +} + +static INT32 HwchampExit() +{ + HwchampInputVal = 0; + + return System16Exit(); +} + +static INT32 HwchampScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(HwchampInputVal); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 MvpInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x3f2000, 0x3f2003, SM_WRITE); + SekSetWriteByteHandler(1, MvpWriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x200000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x200000); + memset(System16Sprites, 0, 0x200000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x180000, 0x40000); + memcpy(System16Sprites + 0x1c0000, pTemp + 0x1c0000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 MvpjInit() +{ + System16CustomLoadRomDo = CustomLoadRom40000; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x200000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x3f0000, 0x3f0003, SM_WRITE); + SekSetWriteByteHandler(1, MvpjWriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x200000); + if (pTemp) { + memset(pTemp, 0, 0x200000); + memcpy(pTemp, System16Sprites, 0x200000); + memset(System16Sprites, 0, 0x200000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0xc0000); + memcpy(System16Sprites + 0x100000, pTemp + 0x0c0000, 0xc0000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 PassshtInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc00006, 0xc00007, SM_WRITE); + SekSetWriteByteHandler(1, PassshtWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 PassshtaInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc00006, 0xc00007, SM_WRITE); + SekSetWriteByteHandler(1, PassshtWriteByte); + SekMapHandler(2, 0xc43000, 0xc43007, SM_READ); + SekSetReadByteHandler(2, PassshtaReadByte); + SekClose(); + } + + return nRet; +} + +static INT32 PassshtbInit() +{ + INT32 nRet = System16Init(); + +// System16SpriteXOffset = 114; + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc46000, 0xc46031, SM_WRITE); + SekSetWriteWordHandler(1, PassshtbGfxWriteWord); + +// SekMapHandler(2, 0x842000, 0x842001, SM_READ); +// SekSetReadByteHandler(2, PassshtbReadByte); + +// SekMapHandler(2, 0xc42006, 0xc42007, SM_WRITE); +// SekSetWriteByteHandler(2, TetrisblSndWriteByte); + SekClose(); + + bSystem16BootlegRender = true; + } + + return nRet; +} + +void RiotcityMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0xfa0000, 0xfaffff, SM_READ); + SekMapMemory(System16TextRam , 0xfb0000, 0xfb0fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0xf40000, 0xf407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0xf60000, 0xf60fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, RiotcityReadByte); + SekSetWriteByteHandler(0, RiotcityWriteByte); + SekSetWriteWordHandler(0, RiotcityWriteWord); + SekClose(); +} + +static INT32 RiotcityInit() +{ + System16Map68KDo = RiotcityMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x1c0000 - 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0x1c0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x1c0000); + memset(System16Sprites, 0, 0x1c0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x40000); + memcpy(System16Sprites + 0x100000, pTemp + 0x040000, 0x40000); + memcpy(System16Sprites + 0x040000, pTemp + 0x080000, 0x40000); + memcpy(System16Sprites + 0x140000, pTemp + 0x0c0000, 0x40000); + memcpy(System16Sprites + 0x080000, pTemp + 0x100000, 0x40000); + memcpy(System16Sprites + 0x180000, pTemp + 0x140000, 0x40000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +void RyukyuMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x300000, 0x3007ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x300800, 0x300fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(System16Ram , 0x200000, 0x203fff, SM_RAM); + SekSetReadWordHandler(0, RyukyuReadWord); + SekSetWriteWordHandler(0, RyukyuWriteWord); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, RyukyuWriteByte); + SekClose(); +} + +static INT32 RyukyuInit() +{ + System16Map68KDo = RyukyuMap68K; + + INT32 nRet = System16Init(); + + return nRet; +} + +static INT32 SdibInit() +{ + System16MakeAnalogInputsDo = SdibMakeAnalogInputs; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, SdibReadByte); + SekMapHandler(1, 0x123406, 0x123407, SM_WRITE); + SekSetWriteByteHandler(1, SdibSoundWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 SdiblInit() +{ + System16MakeAnalogInputsDo = SdibMakeAnalogInputs; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, SdibReadByte); + SekMapHandler(1, 0x123406, 0x123407, SM_WRITE); + SekSetWriteByteHandler(1, SdibSoundWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 SdibExit() +{ + SdiTrack1X = 0; + SdiTrack1Y = 0; + SdiTrack2X = 0; + SdiTrack2Y = 0; + + return System16Exit(); +} + +static INT32 SdibScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(SdiTrack1X); + SCAN_VAR(SdiTrack1Y); + SCAN_VAR(SdiTrack2X); + SCAN_VAR(SdiTrack2Y); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 SjryukoInit() +{ + System16BTileAlt = true; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetWriteByteHandler(0, SjryukoWriteByte); + SekSetReadByteHandler(0, SjryukoReadByte); + SekSetReadWordHandler(0, SjryukoReadWord); + SekClose(); + } + + return nRet; +} + +static INT32 SjryukoExit() +{ + MahjongInputNum = 0; + + return System16Exit(); +} + +static INT32 SjryukoScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(MahjongInputNum); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 SnapperInit() +{ + System16Map68KDo = AtomicpMap68K; + + INT32 nRet = System16Init(); + + System16IgnoreVideoEnable = 1; + System16YM2413IRQInterval = 41; + + return nRet; +} + +static INT32 SonicbomInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x123406, 0x123407, SM_WRITE); + SekSetWriteByteHandler(1, SonicbomWriteByte); + SekMapHandler(2, 0xc42000, 0xc42003, SM_READ); + SekSetReadWordHandler(2, SonicbomReadWord); + SekClose(); + } + + return nRet; +} + +static INT32 TetrisblInit() +{ + INT32 nRet = System16Init(); + + System16SpriteXOffset = 114; + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0x418000, 0x418031, SM_WRITE); + SekSetWriteWordHandler(1, TetrisblGfxWriteWord); + + SekMapHandler(2, 0xc42006, 0xc42007, SM_WRITE); + SekSetWriteByteHandler(2, TetrisblSndWriteByte); + SekClose(); + + bSystem16BootlegRender = true; + } + + return nRet; +} + +static INT32 TimescanInit() +{ + System16BTileAlt = true; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0x80000 - 0x40000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0x80000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x40000); + memset(System16Sprites, 0, 0x80000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x020000, pTemp + 0x10000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x060000, pTemp + 0x30000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 ToryumonInit() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, ToryumonReadByte); + SekSetWriteByteHandler(0, ToryumonWriteByte); + SekMapMemory(System16Ram, 0xff0000, 0xff3fff, SM_RAM); + SekMapMemory(System16Ram, 0xff4000, 0xff7fff, SM_RAM); + SekMapMemory(System16Ram, 0xff8000, 0xffbfff, SM_RAM); + SekClose(); + } + + return nRet; +} + +void TturfMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x300000, 0x3007ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x500000, 0x500fff, SM_RAM); + SekMapMemory(System16Ram , 0x200000, 0x203fff, SM_RAM); + SekSetReadByteHandler(0, TturfReadByte); + SekSetWriteByteHandler(0, TturfWriteByte); + SekSetWriteWordHandler(0, System16BWriteWord); + SekClose(); +} + +void Tturf_Sim8751() +{ + // Inputs + *((UINT16*)(System16Ram + 0x01e6)) = (UINT16)(~System16Input[0] << 8); + *((UINT16*)(System16Ram + 0x01e8)) = (UINT16)(~System16Input[1] << 8); + *((UINT16*)(System16Ram + 0x01ea)) = (UINT16)(~System16Input[2] << 8); + + // Sound command + UINT16 temp = (System16Ram[0x01d0 + 1] << 8) | System16Ram[0x01d0 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x01d0)) = (UINT16)(temp & 0xff); + } +} + +static INT32 TturfInit() +{ + Simulate8751 = Tturf_Sim8751; + System16Map68KDo = TturfMap68K; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0xe0000 - 0x80000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x80000); + memset(System16Sprites, 0, 0xe0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 TturfuInit() +{ + Simulate8751 = Tturf_Sim8751; + System16Map68KDo = TturfMap68K; + + INT32 nRet = System16Init(); + + return nRet; +} + +void Wb3_Sim8751() +{ + // Sound command + UINT16 temp = (System16Ram[0x0008 + 1] << 8) | System16Ram[0x0008 + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp >> 8; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x0008)) = (UINT16)(temp & 0xff); + } +} + +static INT32 Wb3Init() +{ + Simulate8751 = Wb3_Sim8751; + + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0xe0000 - 0x80000; + + INT32 nRet = System16Init(); + + if (!nRet) { + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x80000); + memset(System16Sprites, 0, 0xe0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Wb32Init() +{ + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xdf0006, 0xdf0007, SM_WRITE); + SekSetWriteByteHandler(1, Wb3WriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 Wb33Init() +{ + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0xe0000 - 0x80000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xdf0006, 0xdf0007, SM_WRITE); + SekSetWriteByteHandler(1, Wb3WriteByte); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x80000); + memset(System16Sprites, 0, 0xe0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + } + + return nRet; +} + +static INT32 Wb3bblInit() +{ + // Start off with some sprite rom and let the load routine add on the rest + System16SpriteRomSize = 0xe0000 - 0x80000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc44000, 0xc46031, SM_WRITE); + SekSetWriteWordHandler(1, Wb3bblGfxWriteWord); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0xe0000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x80000); + memset(System16Sprites, 0, 0xe0000); + memcpy(System16Sprites + 0x000000, pTemp + 0x00000, 0x20000); + memcpy(System16Sprites + 0x040000, pTemp + 0x20000, 0x20000); + memcpy(System16Sprites + 0x080000, pTemp + 0x40000, 0x20000); + memcpy(System16Sprites + 0x0c0000, pTemp + 0x60000, 0x20000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + bSystem16BootlegRender = true; + } + + return nRet; +} + +void WrestwarMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x100000, 0x10ffff, SM_READ); + SekMapMemory(System16TextRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x200000, 0x2007ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x300000, 0x300fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekMapHandler(1, 0x400000, 0x400003, SM_WRITE); + SekSetWriteByteHandler(1, WrestwarWriteByte); + SekMapHandler(2, 0x100000, 0x10ffff, SM_WRITE); + SekSetWriteByteHandler(2, WrestwarTileWriteByte); + SekSetWriteWordHandler(2, WrestwarTileWriteWord); + SekClose(); +} + +void Wrestwar_Sim8751() +{ + // System Inputs + *((UINT16*)(System16Ram + 0x2082)) = (UINT16)~System16Input[0]; + + // Sound command + UINT16 temp = (System16Ram[0x208e + 1] << 8) | System16Ram[0x208e + 0]; + if ((temp & 0xff00) != 0x0000) { + System16SoundLatch = temp & 0xff; + ZetOpen(0); +// ZetRaiseIrq(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + *((UINT16*)(System16Ram + 0x208e)) = (UINT16)(temp & 0xff); + } +} + +static INT32 WrestwarInit() +{ + Simulate8751 = Wrestwar_Sim8751; + System16Map68KDo = WrestwarMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + return System16Init(); +} + +static INT32 Wrestwar1Init() +{ + System16Map68KDo = WrestwarMap68K; + System16CustomLoadRomDo = CustomLoadRom40000; + + return System16Init(); +} + +/*==================================================== +Driver defs +====================================================*/ + +struct BurnDriver BurnDrvAceattac = { + "aceattac", NULL, NULL, NULL, "1988", + "Ace Attacker (FD1094 317-0059)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, AceattacRomInfo, AceattacRomName, NULL, NULL, System16bDip3InputInfo, NULL, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvAliensyn = { + "aliensyn", NULL, NULL, NULL, "1987", + "Alien Syndrome (set 4, System 16B, unprotected)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_MAZE, 0, + NULL, AliensynRomInfo, AliensynRomName, NULL, NULL, System16bfire1InputInfo, AliensynDIPInfo, + AliensynInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAliensyn3 = { + "aliensyn3", "aliensyn", NULL, NULL, "1987", + "Alien Syndrome (set 3, System 16B, FD1089A 317-0033)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1089A_ENC, GBF_MAZE, 0, + NULL, Aliensyn3RomInfo, Aliensyn3RomName, NULL, NULL, System16bfire1InputInfo, AliensynDIPInfo, + Aliensyn3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAliensynj = { + "aliensynj", "aliensyn", NULL, NULL, "1987", + "Alien Syndrome (set 6, Japan, new, System 16B, FD1089A 317-0033)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1089A_ENC, GBF_MAZE, 0, + NULL, AliensynjRomInfo, AliensynjRomName, NULL, NULL, System16bfire1InputInfo, AliensynjDIPInfo, + Aliensyn3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeast = { + "altbeast", NULL, NULL, NULL, "1988", + "Altered Beast (set 7, 8751 317-0078)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, AltbeastRomInfo, AltbeastRomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + AltbeastInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeastj = { + "altbeastj", "altbeast", NULL, NULL, "1988", + "Juuouki (set 6, Japan, 8751 317-0077)\0", NULL, "Sega", "System 16B", + L"Juuoki (set 6, Japan, 8751 317-0077)\0\u7363\u738B\u8A18\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, AltbeastjRomInfo, AltbeastjRomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + AltbeastjInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeast2 = { + "altbeast2", "altbeast", NULL, NULL, "1988", + "Altered Beast (set 2, MC-8123B 317-0066)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_MC8123_ENC, GBF_SCRFIGHT, 0, + NULL, Altbeast2RomInfo, Altbeast2RomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeastj3 = { + "altbeastj3", "altbeast", NULL, NULL, "1988", + "Juuouki (set 3, Japan, FD1094 317-0068)\0", NULL, "Sega", "System 16B", + L"Juuoki (set 3, Japan, FD1094 317-0068)\0\u7363\u738B\u8A18\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, Altbeastj3RomInfo, Altbeastj3RomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + Altbeastj3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeast4 = { + "altbeast4", "altbeast", NULL, NULL, "1988", + "Altered Beast (set 4, MC-8123B 317-0066)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_MC8123_ENC, GBF_SCRFIGHT, 0, + NULL, Altbeast4RomInfo, Altbeast4RomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + Altbeast4Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAltbeast5 = { + "altbeast5", "altbeast", NULL, NULL, "1988", + "Altered Beast (set 5, 8751 317-0076)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, Altbeast5RomInfo, Altbeast5RomName, NULL, NULL, System16bfire3InputInfo, AltbeastDIPInfo, + Altbeast5Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAtomicp = { + "atomicp", NULL, NULL, NULL, "1990", + "Atomic Point (Korea)\0", NULL, "Philco", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_YM2413, GBF_MISC, 0, + NULL, AtomicpRomInfo, AtomicpRomName, NULL, NULL, AtomicpInputInfo, AtomicpDIPInfo, + AtomicpInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAurail = { + "aurail", NULL, NULL, NULL, "1990", + "Aurail (set 3, US, unprotected)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_VERSHOOT, 0, + NULL, AurailRomInfo, AurailRomName, NULL, NULL, System16bfire3InputInfo, AurailDIPInfo, + AurailInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAurail1 = { + "aurail1", "aurail", NULL, NULL, "1990", + "Aurail (set 2, World, FD1089B 317-0168)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1089B_ENC, GBF_VERSHOOT, 0, + NULL, Aurail1RomInfo, Aurail1RomName, NULL, NULL, System16bfire3InputInfo, AurailDIPInfo, + Aurail1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAurailj = { + "aurailj", "aurail", NULL, NULL, "1990", + "Aurail (set 1, Japan, FD1089A 317-0167)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1089A_ENC, GBF_VERSHOOT, 0, + NULL, AurailjRomInfo, AurailjRomName, NULL, NULL, System16bfire3InputInfo, AurailDIPInfo, + AurailjInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBayroute = { + "bayroute", NULL, NULL, NULL, "1989", + "Bay Route (set 3, World, FD1094 317-0116)\0", NULL, "Sunsoft / Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, BayrouteRomInfo, BayrouteRomName, NULL, NULL, System16bfire3InputInfo, BayrouteDIPInfo, + BayrouteInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBayroutej = { + "bayroutej", "bayroute", NULL, NULL, "1989", + "Bay Route (set 2, Japan, FD1094 317-0115)\0", NULL, "Sunsoft / Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, BayroutejRomInfo, BayroutejRomName, NULL, NULL, System16bfire3InputInfo, BayrouteDIPInfo, + BayrouteInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBayroute1 = { + "bayroute1", "bayroute", NULL, NULL, "1989", + "Bay Route (set 1, US, unprotected)\0", "No Sound, Missing Z80 Program ROM", "Sunsoft / Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_PLATFORM, 0, + NULL, Bayroute1RomInfo, Bayroute1RomName, NULL, NULL, System16bfire3InputInfo, BayrouteDIPInfo, + Bayroute1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBlox16b = { + "blox16b", "bloxeed", NULL, NULL, "2008", + "Bloxeed (System 16B, PS2 data file)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5704_PS2, GBF_PUZZLE, 0, + NULL, Blox16bRomInfo, Blox16bRomName, NULL, NULL, System16bfire3InputInfo, Blox16bDIPInfo, + Blox16bInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBullet = { + "bullet", NULL, NULL, NULL, "1987", + "Bullet (FD1094 317-0041)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_VERSHOOT, 0, + NULL, BulletRomInfo, BulletRomName, NULL, NULL, BulletInputInfo, BulletDIPInfo, + BulletInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCotton = { + "cotton", NULL, NULL, NULL, "1991", + "Cotton (set 3, World, FD1094 317-0181a)\0", NULL, "Sega / Success", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_HORSHOOT, 0, + NULL, CottonRomInfo, CottonRomName, NULL, NULL, System16bInputInfo, CottonDIPInfo, + CottonInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCottonu = { + "cottonu", "cotton", NULL, NULL, "1991", + "Cotton (set 2, US, FD1094 317-0180)\0", NULL, "Sega / Success", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_HORSHOOT, 0, + NULL, CottonuRomInfo, CottonuRomName, NULL, NULL, System16bInputInfo, CottonDIPInfo, + CottonInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCottonj = { + "cottonj", "cotton", NULL, NULL, "1991", + "Cotton (set 1, Japan, FD1094 317-0179a))\0", NULL, "Sega / Success", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_HORSHOOT, 0, + NULL, CottonjRomInfo, CottonjRomName, NULL, NULL, System16bInputInfo, CottonDIPInfo, + CottonInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdux = { + "ddux", NULL, NULL, NULL, "1989", + "Dynamite Dux (set 2, FD1094 317-0096)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, DduxRomInfo, DduxRomName, NULL, NULL, System16bInputInfo, DduxDIPInfo, + DduxInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdux1 = { + "ddux1", "ddux", NULL, NULL, "1989", + "Dynamite Dux (set 1, 8751 317-0095)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, Ddux1RomInfo, Ddux1RomName, NULL, NULL, System16bInputInfo, DduxDIPInfo, + Ddux1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDduxbl = { + "dduxbl", "ddux", NULL, NULL, "1989", + "Dynamite Dux (bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_INVERT_TILES | HARDWARE_SEGA_5358, GBF_SCRFIGHT, 0, + NULL, DduxblRomInfo, DduxblRomName, NULL, NULL, System16bInputInfo, DduxDIPInfo, + DduxblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDunkshot = { + "dunkshot", NULL, NULL, NULL, "1986", + "Dunk Shot (FD1089 317-0022)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1089A_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, DunkshotRomInfo, DunkshotRomName, NULL, NULL, DunkshotInputInfo, DunkshotDIPInfo, + DunkshotInit, DunkshotExit, System16BFrame, NULL, DunkshotScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEswat = { + "eswat", NULL, NULL, NULL, "1989", + "E-Swat - Cyber Police (set 3, World, FD1094 317-0130)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, EswatRomInfo, EswatRomName, NULL, NULL, System16bfire3InputInfo, EswatDIPInfo, + EswatInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEswatj = { + "eswatj", "eswat", NULL, NULL, "1989", + "E-Swat - Cyber Police (set 1, Japan, FD1094 317-0128)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, EswatjRomInfo, EswatjRomName, NULL, NULL, System16bfire3InputInfo, EswatDIPInfo, + EswatInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEswatu = { + "eswatu", "eswat", NULL, NULL, "1989", + "E-Swat - Cyber Police (set 2, US, FD1094 317-0129)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, EswatuRomInfo, EswatuRomName, NULL, NULL, System16bfire3InputInfo, EswatDIPInfo, + EswatInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEswatbl = { + "eswatbl", "eswat", NULL, NULL, "1989", + "E-Swat - Cyber Police (bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797, GBF_PLATFORM, 0, + NULL, EswatblRomInfo, EswatblRomName, NULL, NULL, System16bfire3InputInfo, EswatDIPInfo, + EswatblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvExctleag = { + "exctleag", NULL, NULL, NULL, "1989", + "Excite League (FD1094 317-0079)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, ExctleagRomInfo, ExctleagRomName, NULL, NULL, ExctleagInputInfo, ExctleagDIPInfo, + ExctleagInit, ExctleagExit, System16BFrame, NULL, ExctleagScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantzn2x = { + "fantzn2x", NULL, NULL, NULL, "2008", + "Fantasy Zone 2 (System 16C version, PS2 data file)\0", NULL, "Sega", "System 16C", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5704_PS2, GBF_HORSHOOT, 0, + NULL, Fantzn2xRomInfo, Fantzn2xRomName, NULL, NULL, System16bInputInfo, Fantzn2xDIPInfo, + Fantzn2xInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFantznta = { + "fantznta", "fantzn2x", NULL, NULL, "2008", + "Fantasy Zone Time Attack (System 16B, PS2 data file)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5704_PS2, GBF_HORSHOOT, 0, + NULL, FantzntaRomInfo, FantzntaRomName, NULL, NULL, System16bInputInfo, Fantzn2xDIPInfo, + FantzntaInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFpoint = { + "fpoint", NULL, NULL, NULL, "1989", + "Flash Point (set 2, Japan, FD1094 317-0127A)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_PUZZLE, 0, + NULL, FpointRomInfo, FpointRomName, NULL, NULL, System16bfire1InputInfo, FpointDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFpoint1 = { + "fpoint1", "fpoint", NULL, NULL, "1989", + "Flash Point (set 1, Japan, FD1094 317-0127A)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, Fpoint1RomInfo, Fpoint1RomName, NULL, NULL, System16bfire1InputInfo, FpointDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFpointbl = { + "fpointbl", "fpoint", NULL, NULL, "1989", + "Flash Point (World, bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_INVERT_TILES, GBF_PUZZLE, 0, + NULL, FpointblRomInfo, FpointblRomName, NULL, NULL, FpointblInputInfo, FpointDIPInfo, + FpointblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFpointbj = { + "fpointbj", "fpoint", NULL, NULL, "1989", + "Flash Point (Japan, bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_INVERT_TILES, GBF_PUZZLE, 0, + NULL, FpointbjRomInfo, FpointbjRomName, NULL, NULL, FpointblInputInfo, FpointDIPInfo, + FpointblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxe = { + "goldnaxe", NULL, NULL, NULL, "1989", + "Golden Axe (set 6, US, 8751 317-123A)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797, GBF_SCRFIGHT, 0, + NULL, GoldnaxeRomInfo, GoldnaxeRomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + GoldnaxeInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxe1 = { + "goldnaxe1", "goldnaxe", NULL, NULL, "1989", + "Golden Axe (set 1, World, FD1094 317-0110)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, Goldnaxe1RomInfo, Goldnaxe1RomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + Goldnaxe1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxe2 = { + "goldnaxe2", "goldnaxe", NULL, NULL, "1989", + "Golden Axe (set 2, US, 8751 317-0112)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, Goldnaxe2RomInfo, Goldnaxe2RomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + Goldnaxe2Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxe3 = { + "goldnaxe3", "goldnaxe", NULL, NULL, "1989", + "Golden Axe (set 3, World, FD1094 317-0120)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, Goldnaxe3RomInfo, Goldnaxe3RomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + Goldnaxe3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxej = { + "goldnaxej", "goldnaxe", NULL, NULL, "1989", + "Golden Axe (set 4, Japan, FD1094 317-0121)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, GoldnaxejRomInfo, GoldnaxejRomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + Goldnaxe3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGoldnaxeu = { + "goldnaxeu", "goldnaxe", NULL, NULL, "1989", + "Golden Axe (set 5, US, FD1094 317-0122)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, GoldnaxeuRomInfo, GoldnaxeuRomName, NULL, NULL, System16bfire3InputInfo, GoldnaxeDIPInfo, + Goldnaxe1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHwchamp = { + "hwchamp", NULL, NULL, NULL, "1987", + "Heavyweight Champ\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_VSFIGHT, 0, + NULL, HwchampRomInfo, HwchampRomName, NULL, NULL, HwchampInputInfo, HwchampDIPInfo, + HwchampInit, HwchampExit, System16BFrame, NULL, HwchampScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHwchampj = { + "hwchampj", "hwchamp", NULL, NULL, "1987", + "Heavyweight Champ (Japan, FD1094 317-0046)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_VSFIGHT, 0, + NULL, HwchampjRomInfo, HwchampjRomName, NULL, NULL, HwchampInputInfo, HwchampDIPInfo, + HwchampInit, HwchampExit, System16BFrame, NULL, HwchampScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMvp = { + "mvp", NULL, NULL, NULL, "1989", + "MVP (set 2, US, FD1094 317-0143)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797 | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, MvpRomInfo, MvpRomName, NULL, NULL, System16bfire3InputInfo, MvpDIPInfo, + MvpInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMvpj = { + "mvpj", "mvp", NULL, NULL, "1989", + "MVP (set 1, Japan, FD1094 317-0142)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, MvpjRomInfo, MvpjRomName, NULL, NULL, System16bfire3InputInfo, MvpDIPInfo, + MvpjInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPasssht = { + "passsht", NULL, NULL, NULL, "1988", + "Passing Shot (World, 2 Players, FD1094 317-0080)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, PassshtRomInfo, PassshtRomName, NULL, NULL, System16bfire4InputInfo, PassshtDIPInfo, + PassshtInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvPassshta = { + "passshta", "passsht", NULL, NULL, "1988", + "Passing Shot (World, 4 Players, FD1094 317-0074)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, PassshtaRomInfo, PassshtaRomName, NULL, NULL, PassshtInputInfo, PassshtaDIPInfo, + PassshtaInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvPassshtj = { + "passshtj", "passsht", NULL, NULL, "1988", + "Passing Shot (Japan, 4 Players, FD1094 317-0070)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE, 4, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, PassshtjRomInfo, PassshtjRomName, NULL, NULL, PassshtInputInfo, PassshtaDIPInfo, + PassshtaInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriverD BurnDrvPassshtb = { + "passshtb", "passsht", NULL, NULL, "1988", + "Passing Shot (bootleg, 2 Players)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, PassshtbRomInfo, PassshtbRomName, NULL, NULL, PassshtInputInfo, PassshtDIPInfo, + PassshtbInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvRiotcity = { + "riotcity", NULL, NULL, NULL, "1991", + "Riot City (Japan)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, RiotcityRomInfo, RiotcityRomName, NULL, NULL, System16bInputInfo, RiotcityDIPInfo, + RiotcityInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRyukyu = { + "ryukyu", NULL, NULL, NULL, "1990", + "RyuKyu (Japan, FD1094 317-5023)\0", NULL, "Success / Sega", "System 16B", + L"RyuKyu \u7409\u7403 (Japan, FD1094 317-5023)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, RyukyuRomInfo, RyukyuRomName, NULL, NULL, RyukyuInputInfo, RyukyuDIPInfo, + RyukyuInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSdib = { + "sdib", "sdi", NULL, NULL, "1987", + "SDI - Strategic Defense Initiative (System 16B, FD1089A 317-0028)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1089A_ENC | HARDWARE_SEGA_5358, GBF_SHOOT, 0, + NULL, SdibRomInfo, SdibRomName, NULL, NULL, SdiInputInfo, SdibDIPInfo, + SdibInit, SdibExit, System16BFrame, NULL, SdibScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSdibl = { + "sdibl", "sdi", NULL, NULL, "1987", + "SDI - Strategic Defense Initiative (bootleg)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_SHOOT, 0, + NULL, SdiblRomInfo, SdiblRomName, NULL, NULL, SdiInputInfo, SdibDIPInfo, + SdiblInit, SdibExit, System16BFrame, NULL, SdibScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDefense = { + "defense", "sdi", NULL, NULL, "1987", + "Defense (System 16B, FD1089A 317-0028)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1089A_ENC | HARDWARE_SEGA_5358, GBF_SHOOT, 0, + NULL, DefenseRomInfo, DefenseRomName, NULL, NULL, SdiInputInfo, SdibDIPInfo, + SdibInit, SdibExit, System16BFrame, NULL, SdibScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi2 = { + "shinobi2", "shinobi", NULL, NULL, "1987", + "Shinobi (set 2, System 16B, FD1094 317-0049)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Shinobi2RomInfo, Shinobi2RomName, NULL, NULL, System16bfire3InputInfo, ShinobiDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi3 = { + "shinobi3", "shinobi", NULL, NULL, "1987", + "Shinobi (set 3, System 16B, MC-8123B 317-0054)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_MC8123_ENC, GBF_PLATFORM, 0, + NULL, Shinobi3RomInfo, Shinobi3RomName, NULL, NULL, System16bfire3InputInfo, ShinobiDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi4 = { + "shinobi4", "shinobi", NULL, NULL, "1987", + "Shinobi (set 4, System 16B, MC-8123B 317-0054)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_MC8123_ENC, GBF_PLATFORM, 0, + NULL, Shinobi4RomInfo, Shinobi4RomName, NULL, NULL, System16bfire3InputInfo, ShinobiDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinobi5 = { + "shinobi5", "shinobi", NULL, NULL, "1987", + "Shinobi (set 5, System 16B, unprotected)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_PLATFORM, 0, + NULL, Shinobi5RomInfo, Shinobi5RomName, NULL, NULL, System16bfire3InputInfo, ShinobiDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSjryuko = { + "sjryuko", NULL, NULL, NULL, "1987", + "Sukeban Jansi Ryuko (set 2, System 16B, FD1089B 317-5021)\0", NULL, "White Board", "System 16B", + L"Sukeban Jansi Ryuko (set 2, System 16B, FD1089B 317-5021)\0\u30B9\u30B1\u30D0\u30F3\u96C0\u58EB \u7ADC\u5B50\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1089B_ENC | HARDWARE_SEGA_5358, GBF_MAHJONG, 0, + NULL, SjryukoRomInfo, SjryukoRomName, NULL, NULL, SjryukoInputInfo, SjryukoDIPInfo, + SjryukoInit, SjryukoExit, System16BFrame, NULL, SjryukoScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSnapper = { + "snapper", NULL, NULL, NULL, "1990", + "Snapper (Korea)\0", NULL, "Philko", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_YM2413, GBF_MISC, 0, + NULL, SnapperRomInfo, SnapperRomName, NULL, NULL, SnapperInputInfo, SnapperDIPInfo, + SnapperInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSonicbom = { + "sonicbom", NULL, NULL, NULL, "1987", + "Sonic Boom (FD1094 317-0053)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1094_ENC, GBF_VERSHOOT, 0, + NULL, SonicbomRomInfo, SonicbomRomName, NULL, NULL, System16bInputInfo, SonicbomDIPInfo, + SonicbomInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvSuprleag = { + "suprleag", NULL, NULL, NULL, "1987", + "Super League (FD1094 317-0045)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_FD1094_ENC | HARDWARE_SEGA_5358, GBF_SPORTSMISC, 0, + NULL, SuprleagRomInfo, SuprleagRomName, NULL, NULL, ExctleagInputInfo, ExctleagDIPInfo, + ExctleagInit, ExctleagExit, System16BFrame, NULL, ExctleagScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetris1 = { + "tetris1", "tetris", NULL, NULL, "1988", + "Tetris (set 1, Japan, System 16B, FD1094 317-0091)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, Tetris1RomInfo, Tetris1RomName, NULL, NULL, System16bfire1InputInfo, TetrisDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetris2 = { + "tetris2", "tetris", NULL, NULL, "1988", + "Tetris (set 2, Japan, System 16B, FD1094 317-0092)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, Tetris2RomInfo, Tetris2RomName, NULL, NULL, System16bfire1InputInfo, TetrisDIPInfo, + System16Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetrisbl = { + "tetrisbl", "tetris", NULL, NULL, "1988", + "Tetris (bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B, GBF_PUZZLE, 0, + NULL, TetrisblRomInfo, TetrisblRomName, NULL, NULL, System16bfire1InputInfo, TetrisDIPInfo, + TetrisblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTimescan = { + "timescan", NULL, NULL, NULL, "1987", + "Time Scanner (set 2, System 16B)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_PINBALL, 0, + NULL, TimescanRomInfo, TimescanRomName, NULL, NULL, System16bDip3InputInfo, TimescanDIPInfo, + TimescanInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvToryumon = { + "toryumon", NULL, NULL, NULL, "1994", + "Toryumon\0", NULL, "Sega / Westone", "System 16B", + L"Toryumon\0\u767B\u9F8D\u9580\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5797, GBF_PUZZLE, 0, + NULL, ToryumonRomInfo, ToryumonRomName, NULL, NULL, System16bfire1InputInfo, ToryumonDIPInfo, + ToryumonInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTturf = { + "tturf", NULL, NULL, NULL, "1989", + "Tough Turf (set 2, Japan, 8751 317-0104)\0", "No Sound, Missing Z80 Program", "Sega / Sunsoft", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, TturfRomInfo, TturfRomName, NULL, NULL, System16bfire3InputInfo, TturfDIPInfo, + TturfInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTturfu = { + "tturfu", "tturf", NULL, NULL, "1989", + "Tough Turf (set 1, US, 8751 317-0099)\0", NULL, "Sega / Sunsoft", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358, GBF_SCRFIGHT, 0, + NULL, TturfuRomInfo, TturfuRomName, NULL, NULL, System16bfire3InputInfo, TturfDIPInfo, + TturfuInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWb3 = { + "wb3", NULL, NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (set 5, World, System 16B, 8751 317-0098)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_PLATFORM, 0, + NULL, Wb3RomInfo, Wb3RomName, NULL, NULL, System16bInputInfo, Wb3DIPInfo, + Wb3Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWb32 = { + "wb32", "wb3", NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (set 2, Japan, System 16B, FD1094 317-0085)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5358 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Wb32RomInfo, Wb32RomName, NULL, NULL, System16bInputInfo, Wb3DIPInfo, + Wb32Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWb33 = { + "wb33", "wb3", NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (set 3, World, System 16B, FD1094 317-0089)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Wb33RomInfo, Wb33RomName, NULL, NULL, System16bInputInfo, Wb3DIPInfo, + Wb33Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWb34 = { + "wb34", "wb3", NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (set 4, Japan, System 16B, FD1094 317-0087)\0", NULL, "Sega / Westone", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Wb34RomInfo, Wb34RomName, NULL, NULL, System16bInputInfo, Wb3DIPInfo, + Wb33Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvWb3bbl = { + "wb3bbl", "wb3", NULL, NULL, "1988", + "Wonder Boy III - Monster Lair (bootleg)\0", NULL, "bootleg", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_INVERT_TILES, GBF_PLATFORM, 0, + NULL, Wb3bblRomInfo, Wb3bblRomName, NULL, NULL, System16bInputInfo, Wb3DIPInfo, + Wb3bblInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWrestwar = { + "wrestwar", NULL, NULL, NULL, "1988", + "Wrestle War (set 3, World, 8751 317-0103)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521, GBF_VSFIGHT, 0, + NULL, WrestwarRomInfo, WrestwarRomName, NULL, NULL, System16bInputInfo, WrestwarDIPInfo, + WrestwarInit, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvWrestwar1 = { + "wrestwar1", "wrestwar", NULL, NULL, "1988", + "Wrestle War (set 1, Japan, FD1094 317-0090)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_VSFIGHT, 0, + NULL, Wrestwar1RomInfo, Wrestwar1RomName, NULL, NULL, System16bInputInfo, WrestwarDIPInfo, + Wrestwar1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvWrestwar2 = { + "wrestwar2", "wrestwar", NULL, NULL, "1988", + "Wrestle War (set 2, World, FD1094 317-0102)\0", NULL, "Sega", "System 16B", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_5521 | HARDWARE_SEGA_FD1094_ENC, GBF_VSFIGHT, 0, + NULL, Wrestwar2RomInfo, Wrestwar2RomName, NULL, NULL, System16bInputInfo, WrestwarDIPInfo, + Wrestwar1Init, System16Exit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +// ISG Selection Master Type 2006 hardware + +static UINT16 IsgsmCartAddrLatch; +static UINT32 IsgsmCartAddr; +static INT32 IsgsmType = 0; +static UINT32 IsgsmAddr; +static UINT8 IsgsmMode; +static UINT16 IsgsmAddrLatch; +static UINT32 IsgsmSecurity; +static UINT16 IsgsmSecurityLatch; +static UINT8 IsgsmRleControlPosition = 8; +static UINT8 IsgsmRleControlByte; +static INT32 IsgsmRleLatched; +static UINT8 IsgsmRleByte; +static UINT8 IsgsmReadXor; +static UINT32 nCartSize; + +typedef UINT32 (*isgsm_security_callback)(UINT32 input); +isgsm_security_callback IsgsmSecurityCallback; + +static INT32 IsgsmTilePlaneOffsets[3] = { 0x200000, 0x100000, 0 }; +static INT32 IsgsmTileXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 IsgsmTileYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +static struct BurnDIPInfo ShinfzDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfc, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x13, 0x01, 0x0c, 0x08, "2" }, + {0x13, 0x01, 0x0c, 0x0c, "3" }, + {0x13, 0x01, 0x0c, 0x04, "4" }, + {0x13, 0x01, 0x0c, 0x00, "240" }, + + {0 , 0xfe, 0 , 4 , "Extra Ship Cost" }, + {0x13, 0x01, 0x30, 0x30, "5000" }, + {0x13, 0x01, 0x30, 0x20, "10000" }, + {0x13, 0x01, 0x30, 0x10, "15000" }, + {0x13, 0x01, 0x30, 0x00, "20000" }, + + {0 , 0xfe, 0 , 2 , "Difficulty" }, + {0x13, 0x01, 0xc0, 0x80, "Easy" }, + {0x13, 0x01, 0xc0, 0xc0, "Normal" }, + {0x13, 0x01, 0xc0, 0x40, "Hard" }, + {0x13, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 3 , "Game Select" }, + {0x15, 0x01, 0x03, 0x00, "Shinobi Ninja Game" }, + {0x15, 0x01, 0x03, 0x01, "FZ-2006 Game I" }, + {0x15, 0x01, 0x03, 0x02, "FZ-2006 Game II" }, +}; + +STDDIPINFO(Shinfz) + +static struct BurnDIPInfo TetrbxDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + // Dip 1 + + // Dip 2 + + // Dip 3 + {0 , 0xfe, 0 , 3 , "Game Select" }, + {0x15, 0x01, 0x03, 0x00, "Tetris" }, + {0x15, 0x01, 0x03, 0x01, "Tetris II (Blox)" }, + {0x15, 0x01, 0x03, 0x02, "Tetris Turbo" }, +}; + +STDDIPINFO(Tetrbx) + +static struct BurnRomInfo emptyRomDesc[] = { + { "", 0, 0, 0 }, +}; + +static struct BurnRomInfo IsgsmRomDesc[] = { + { "ism2006v00.u1", 0x020000, 0x2292585c, BRF_ESS | BRF_PRG | BRF_BIOS }, +}; + +STD_ROM_PICK(Isgsm) +STD_ROM_FN(Isgsm) + +static struct BurnRomInfo ShinfzRomDesc[] = { + { "shin06.u13", 0x200000, 0x39d773e9, BRF_ESS | BRF_PRG }, +}; + +STDROMPICKEXT(Shinfz, Shinfz, Isgsm) +STD_ROM_FN(Shinfz) + +static struct BurnRomInfo TetrbxRomDesc[] = { + { "tetr06.u13", 0x080000, 0x884dd693, BRF_ESS | BRF_PRG }, +}; + +STDROMPICKEXT(Tetrbx, Tetrbx, Isgsm) +STD_ROM_FN(Tetrbx) + +static UINT32 ShinfzSecurity(UINT32 input) +{ + return BITSWAP32(input, 19, 20, 25, 26, 15, 0, 16, 2, 8, 9, 13, 14, 31, 21, 7, 18, 11, 30, 22, 17, 3, 4, 12, 28, 29, 5, 27, 10, 23, 24, 1, 6); +} + +static UINT32 TetrbxSecurity(UINT32 input) +{ + return input; +} + +UINT8 __fastcall IsgsmReadByte(UINT32 a) +{ + switch (a) { + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41007: { + return 0xff - System16Input[2]; + } + + case 0xc42001: { + return System16Dip[0]; + } + + case 0xc42003: { + return System16Dip[1]; + } + + case 0xe80001: { + UINT32 Address; + UINT8 Data; + + IsgsmCartAddr++; + Address = (IsgsmCartAddr & (nCartSize - 1)); + Data = System16Rom[(0x100000 + Address) ^ 1] ^ IsgsmReadXor; + + return Data; + } + + case 0xe80003: { + return System16Dip[2]; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall IsgsmWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + switch (a) { + case 0x3f0001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f0003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f2001: { + if (System16TileBanks[0] != (d & 0x07)) { + System16TileBanks[0] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0x3f2003: { + if (System16TileBanks[1] != (d & 0x07)) { + System16TileBanks[1] = d & 0x07; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + return; + } + + case 0xc40001: { + System16VideoEnable = d & 0x20; + System16ScreenFlip = d & 0x40; + return; + } + + case 0xc43001: { + // ???? + return; + } + + case 0xe00001: { + UINT8 *pDest = 0; + int AddressMask = 0; + + switch (IsgsmType & 0x0f) { + case 0x00: { + pDest = System16Sprites; + AddressMask = 0x1fffff; + break; + } + + case 0x01: { + pDest = System16TempGfx; + AddressMask = 0xfffff; + break; + } + + case 0x02: { + pDest = System16Z80Rom; + AddressMask = 0x3ffff; + break; + } + + case 0x03: { + pDest = System16Rom + 0x300000; + AddressMask = 0xfffff; + break; + } + } + + if ((IsgsmType & 0x10) == 0x00) { + switch (IsgsmType & 0xe0) { + case 0x00: d = BITSWAP08(d, 0, 7, 6, 5, 4, 3, 2, 1); break; + case 0x20: d = BITSWAP08(d, 7, 6, 5, 4, 3, 2, 1, 0); break; + case 0x40: d = BITSWAP08(d, 6, 5, 4, 3, 2, 1, 0, 7); break; + case 0x60: d = BITSWAP08(d, 5, 4, 3, 2, 1, 0, 7, 6); break; + case 0x80: d = BITSWAP08(d, 4, 3, 2, 1, 0, 7, 6, 5); break; + case 0xa0: d = BITSWAP08(d, 3, 2, 1, 0, 7, 6, 5, 4); break; + case 0xc0: d = BITSWAP08(d, 2, 1, 0, 7, 6, 5, 4, 3); break; + case 0xe0: d = BITSWAP08(d, 1, 0, 7, 6, 5, 4, 3, 2); break; + } + } + + if (pDest) { + INT32 BytesToWrite; + BytesToWrite = 1; + + if (IsgsmMode & 0x04) { + if (!IsgsmRleLatched) { + if (IsgsmRleControlPosition == 8) { + IsgsmRleControlByte = d; + IsgsmRleControlPosition = 0; + BytesToWrite = 0; + } else { + if (((IsgsmRleControlByte << IsgsmRleControlPosition) & 0x80) == 0) { + IsgsmRleByte = d; + IsgsmRleLatched = 1; + } else { + BytesToWrite = 1; + } + + IsgsmRleControlPosition++; + } + } else { + IsgsmRleLatched = 0; + BytesToWrite = d + 2; + d = IsgsmRleByte; + } + } + + for (INT32 i = 0; i < BytesToWrite; i++) { + UINT8 Byte = 0; + + if (IsgsmMode & 0x08) { + IsgsmAddr++; + IsgsmAddr &= 0xfffffff; + } else { + IsgsmAddr--; + IsgsmAddr &= 0xfffffff; + } + + switch (IsgsmMode & 0x03) { + case 0x00: Byte = d; break; + case 0x01: Byte = pDest[IsgsmAddr & AddressMask] ^ d; break; + case 0x02: Byte = pDest[IsgsmAddr & AddressMask] | d; break; + case 0x03: Byte = pDest[IsgsmAddr & AddressMask] & d; break; + } + + if ((IsgsmType & 0x10) == 0x10) { + switch (IsgsmType & 0xe0) { + case 0x00: Byte = BITSWAP08(Byte, 0, 7, 6, 5, 4, 3, 2, 1); break; + case 0x20: Byte = BITSWAP08(Byte, 7, 6, 5, 4, 3, 2, 1, 0); break; + case 0x40: Byte = BITSWAP08(Byte, 6, 5, 4, 3, 2, 1, 0, 7); break; + case 0x60: Byte = BITSWAP08(Byte, 5, 4, 3, 2, 1, 0, 7, 6); break; + case 0x80: Byte = BITSWAP08(Byte, 4, 3, 2, 1, 0, 7, 6, 5); break; + case 0xa0: Byte = BITSWAP08(Byte, 3, 2, 1, 0, 7, 6, 5, 4); break; + case 0xc0: Byte = BITSWAP08(Byte, 2, 1, 0, 7, 6, 5, 4, 3); break; + case 0xe0: Byte = BITSWAP08(Byte, 1, 0, 7, 6, 5, 4, 3, 2); break; + } + } + + if ((IsgsmType & 0x0f) == 0x01) { + if (IsgsmAddr < System16TileRomSize) { + pDest[IsgsmAddr] = Byte; + GfxDecodeSingle((IsgsmAddr & 0x1ffff) / 8, 3, 8, 8, IsgsmTilePlaneOffsets, IsgsmTileXOffsets, IsgsmTileYOffsets, 0x40, System16TempGfx, System16Tiles); + } + } else { + pDest[IsgsmAddr & AddressMask] = Byte; + } + } + } + + return; + } + + case 0xe00003: { + IsgsmType = d; + return; + } + + case 0xfe0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + + case 0xfe0009: { + if (d == 0) { + ZetOpen(0); + ZetReset(); + ZetClose(); + System16Z80Enable = true; + } + + if (d == 1) { + ZetOpen(0); + ZetReset(); + ZetClose(); + System16Z80Enable = false; + } + + return; + } + + case 0xfe000b: { + SekMapMemory(System16Rom + 0x300000, 0x000000, 0x0fffff, SM_ROM); + return; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT16 __fastcall IsgsmReadWord(UINT32 a) +{ + switch (a) { + case 0xe80008: { + return (IsgsmSecurity >> 16) & 0xffff; + } + + case 0xe8000a: { + return IsgsmSecurity & 0xffff; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +void __fastcall IsgsmWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileWordWrite(a - 0x400000, d); + return; + } + + switch (a) { + case 0xe00004: { + IsgsmAddrLatch = d; + return; + } + + case 0xe00006: { + IsgsmMode = (IsgsmAddrLatch & 0xf000) >> 12; + IsgsmAddr = d | ((IsgsmAddrLatch & 0x0fff) << 16); + + IsgsmRleControlPosition = 8; + IsgsmRleControlByte = 0; + IsgsmRleLatched = 0; + return; + } + + case 0xe80004: { + IsgsmCartAddrLatch = d; + return; + } + + case 0xe80006: { + IsgsmCartAddr = d | IsgsmCartAddrLatch << 16; + return; + } + + case 0xe80008: { + IsgsmSecurityLatch = d; + return; + } + + case 0xe8000a: { + IsgsmSecurity = d | IsgsmSecurityLatch << 16; + if (IsgsmSecurityCallback) IsgsmSecurity = IsgsmSecurityCallback(IsgsmSecurity); + return; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void IsgsmMap68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(System16ExtraRam , 0x200000, 0x23ffff, SM_RAM); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Rom + 0x100000 , 0xee0000, 0xefffff, SM_ROM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, IsgsmReadWord); + SekSetWriteWordHandler(0, IsgsmWriteWord); + SekSetReadByteHandler(0, IsgsmReadByte); + SekSetWriteByteHandler(0, IsgsmWriteByte); + SekClose(); +} + +static INT32 IsgsmInit() +{ + System16RomSize = 0x400000; + System16TileRomSize = 0x60000; + System16SpriteRomSize = 0x200000; + System16UPD7759DataSize = 0x30000; + + System16Map68KDo = IsgsmMap68K; + + INT32 nRet = System16Init(); + + if (!nRet) { + memset(System16Rom, 0, 0x400000); + + // Load and Decrypt BIOS + UINT16 *pTemp = (UINT16*)malloc(0x20000); + memset(pTemp, 0, 0x20000); + UINT16 *Rom = (UINT16*)System16Rom; + + nRet = BurnLoadRom(System16Rom, 0x80, 1); if (nRet) return 1; + + for (UINT32 i = 0; i < 0x10000; i++) { + pTemp[i ^ 0x4127] = BITSWAP16(Rom[i], 6, 14, 4, 2, 12, 10, 8, 0, 1, 9, 11, 13, 3, 5, 7, 15); + } + + memcpy(Rom, pTemp, 0x20000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + // Load program ROM + nRet = BurnLoadRom(System16Rom + 0x100000, 0, 1); if (nRet) return 1; + + System16TempGfx = (UINT8*)malloc(System16TileRomSize); + memset(System16TempGfx, 0, System16TileRomSize); + memset(System16Tiles, 0, System16NumTiles * 8 * 8); + memset(System16Sprites, 0, System16TileRomSize); + + System16UPD7759Data = (UINT8*)(System16Z80Rom + 0x10000); + } + + System16ClockSpeed = 16000000; + + return nRet; +} + +static INT32 ShinfzInit() +{ + INT32 nRet = IsgsmInit(); + + if (!nRet) { + nCartSize = 0x200000; + UINT16 *pTemp = (UINT16*)malloc(0x200000); + memset(pTemp, 0, 0x200000); + UINT16 *Rom = (UINT16*)(System16Rom + 0x100000); + + for (UINT32 i = 0; i < 0x100000; i++) { + pTemp[i ^ 0x68956] = BITSWAP16(Rom[i], 8, 4, 12, 3, 6, 7, 1, 0, 15, 11, 5, 14, 10, 2, 9, 13); + } + + memcpy(Rom, pTemp, 0x200000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + IsgsmReadXor = 0x66; + IsgsmSecurityCallback = ShinfzSecurity; + } + + return nRet; +} + +static INT32 TetrbxInit() +{ + INT32 nRet = IsgsmInit(); + + if (!nRet) { + nCartSize = 0x80000; + UINT16 *pTemp = (UINT16*)malloc(nCartSize); + memset(pTemp, 0, nCartSize); + UINT16 *Rom = (UINT16*)(System16Rom + 0x100000); + + for (UINT32 i = 0; i < nCartSize >> 1; i++) { + pTemp[i ^ 0x2a6e6] = BITSWAP16(Rom[i], 4, 0, 12, 5, 7, 3, 1, 14, 10, 11, 9, 6, 15, 2, 13, 8); + } + + memcpy(Rom, pTemp, nCartSize); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + IsgsmReadXor = 0x73; + IsgsmSecurityCallback = TetrbxSecurity; + } + + return nRet; +} + +static INT32 IsgsmExit() +{ + INT32 nRet = System16Exit(); + + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + + IsgsmCartAddrLatch = 0; + IsgsmCartAddr = 0; + IsgsmType = 0; + IsgsmAddr = 0; + IsgsmMode = 0; + IsgsmAddrLatch = 0; + IsgsmSecurity = 0; + IsgsmSecurityLatch = 0; + IsgsmRleControlPosition = 0; + IsgsmRleControlByte = 0; + IsgsmRleLatched = 0; + IsgsmRleByte = 0; + IsgsmReadXor = 0; + nCartSize = 0; + IsgsmSecurityCallback = NULL; + + return nRet; +} + +struct BurnDriver BurnDrvIsgsm = { + "isgsm", NULL, NULL, NULL, "2006", + "ISG Selection Master Type 2006 System BIOS\0", "BIOS only", "ISG", "ISG Selection Master Type 2006", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_BOARDROM, 0, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_ISGSM | HARDWARE_SEGA_5521, GBF_BIOS, 0, + NULL, IsgsmRomInfo, IsgsmRomName, NULL, NULL, System16bDip3InputInfo, NULL, + IsgsmInit, IsgsmExit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShinfz = { + "shinfz", NULL, "isgsm", NULL, "2006", + "Shinobi / FZ-2006 (Korean System 16 bootleg) (ISG Selection Master Type 2006)\0", NULL, "ISG", "ISG Selection Master Type 2006", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_ISGSM | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, ShinfzRomInfo, ShinfzRomName, NULL, NULL, System16bDip3InputInfo, ShinfzDIPInfo, + ShinfzInit, IsgsmExit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTetrbx = { + "tetrbx", NULL, "isgsm", NULL, "2006", + "Tetris / Bloxeed (Korean System 16 bootleg) (ISG Selection Master Type 2006)\0", NULL, "ISG", "ISG Selection Master Type 2006", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM16B | HARDWARE_SEGA_ISGSM | HARDWARE_SEGA_5521, GBF_SCRFIGHT, 0, + NULL, TetrbxRomInfo, TetrbxRomName, NULL, NULL, System16bDip3InputInfo, TetrbxDIPInfo, + TetrbxInit, IsgsmExit, System16BFrame, NULL, System16Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_sys18.cpp b/src/burn/drivers/sega/d_sys18.cpp new file mode 100644 index 00000000..196eacbc --- /dev/null +++ b/src/burn/drivers/sega/d_sys18.cpp @@ -0,0 +1,2758 @@ +#include "sys16.h" + +/*==================================================== +Input defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo System18InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Service 2" , BIT_DIGITAL , System16InputPort0 + 6 , "service2" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(System18) + +static struct BurnInputInfo AstormInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort0 + 0, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 6, "p3 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + {"P1 Service" , BIT_DIGITAL , System16InputPort1 + 3, "p1 fire 4" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + {"P2 Service" , BIT_DIGITAL , System16InputPort2 + 3, "p2 fire 4" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 1, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , System16InputPort3 + 2, "p3 fire 3" }, + {"P3 Service" , BIT_DIGITAL , System16InputPort3 + 3, "p3 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Astorm) + +static struct BurnInputInfo DdcrewInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort0 + 7, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort3 + 3, "p3 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 1, "p3 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Ddcrew) + +static struct BurnInputInfo Ddcrew2InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Ddcrew2) + +static struct BurnInputInfo DdcrewuInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort5 + 2, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort5 + 0, "p3 start" }, + {"Coin 4" , BIT_DIGITAL , System16InputPort5 + 3, "p4 coin" }, + {"Start 4" , BIT_DIGITAL , System16InputPort5 + 1, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 1, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , System16InputPort4 + 5, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , System16InputPort4 + 4, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , System16InputPort4 + 7, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , System16InputPort4 + 6, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , System16InputPort4 + 0, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , System16InputPort4 + 1, "p4 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Ddcrewu) + +static struct BurnInputInfo DesertbrInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort3 + 3, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort0 + 7, "p3 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , System16InputPort1 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , System16InputPort2 + 2, "p2 fire 3" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 1, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , System16InputPort3 + 2, "p3 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Desertbr) + +static struct BurnInputInfo LghostInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort0 + 7, "p3 coin" }, + + A("P1 X-Axis" , BIT_ANALOG_REL, &System16AnalogPort0, "mouse x-axis" ), + A("P1 Y-Axis" , BIT_ANALOG_REL, &System16AnalogPort1, "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "mouse button 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "mouse button 2" }, + + A("P2 X-Axis" , BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("P2 Y-Axis" , BIT_ANALOG_REL, &System16AnalogPort3, "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort1 + 2, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort1 + 3, "p2 fire 2" }, + + A("P3 X-Axis" , BIT_ANALOG_REL, &System16AnalogPort4, "p3 x-axis" ), + A("P3 Y-Axis" , BIT_ANALOG_REL, &System16AnalogPort5, "p3 y-axis" ), + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort1 + 7, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort1 + 6, "p3 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 4 , "service" }, + {"Service 2" , BIT_DIGITAL , System16InputPort0 + 5 , "service2" }, + {"Service 3" , BIT_DIGITAL , System16InputPort0 + 6 , "service3" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Lghost) + +static struct BurnInputInfo MwalkInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , System16InputPort0 + 7, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , System16InputPort3 + 3, "p3 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 5, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 1, "p1 fire 2" }, + {"P1 Service" , BIT_DIGITAL , System16InputPort1 + 3, "service" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 5, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort2 + 1, "p2 fire 2" }, + {"P2 Service" , BIT_DIGITAL , System16InputPort2 + 3, "service2" }, + + {"P3 Up" , BIT_DIGITAL , System16InputPort3 + 5, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , System16InputPort3 + 4, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , System16InputPort3 + 7, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , System16InputPort3 + 6, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , System16InputPort3 + 0, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , System16InputPort3 + 1, "p3 fire 2" }, + {"P3 Service" , BIT_DIGITAL , System16InputPort0 + 6, "service3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH, System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Mwalk) + +static struct BurnInputInfo WwallyInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , System16InputPort1 + 3, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , System16InputPort1 + 4, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , System16InputPort1 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , System16InputPort1 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 0, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , System16InputPort2 + 3, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , System16InputPort2 + 4, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , System16InputPort2 + 1, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , System16InputPort2 + 2, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort2 + 0, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Wwally) + +#undef A + +/*==================================================== +Dip defs +====================================================*/ + +#define SYSTEM18_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo AstormDIPList[]= +{ + // Default Values + {0x21, 0xff, 0xff, 0xff, NULL }, + {0x22, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x21) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x22, 0x01, 0x01, 0x01, "Off" }, + {0x22, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x22, 0x01, 0x02, 0x02, "Off" }, + {0x22, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x22, 0x01, 0x1c, 0x04, "Easiest" }, + {0x22, 0x01, 0x1c, 0x08, "Easier" }, + {0x22, 0x01, 0x1c, 0x0c, "Easy" }, + {0x22, 0x01, 0x1c, 0x1c, "Normal" }, + {0x22, 0x01, 0x1c, 0x10, "Hard" }, + {0x22, 0x01, 0x1c, 0x14, "Harder" }, + {0x22, 0x01, 0x1c, 0x18, "Hardest" }, + {0x22, 0x01, 0x1c, 0x00, "Special" }, + + {0 , 0xfe, 0 , 2 , "Coin Chutes" }, + {0x22, 0x01, 0x20, 0x00, "1" }, + {0x22, 0x01, 0x20, 0x20, "3" }, +}; + +STDDIPINFO(Astorm) + +static struct BurnDIPInfo Astorm2pDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x16) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x17, 0x01, 0x1c, 0x04, "Easiest" }, + {0x17, 0x01, 0x1c, 0x08, "Easier" }, + {0x17, 0x01, 0x1c, 0x0c, "Easy" }, + {0x17, 0x01, 0x1c, 0x1c, "Normal" }, + {0x17, 0x01, 0x1c, 0x10, "Hard" }, + {0x17, 0x01, 0x1c, 0x14, "Harder" }, + {0x17, 0x01, 0x1c, 0x18, "Hardest" }, + {0x17, 0x01, 0x1c, 0x00, "Special" }, + + {0 , 0xfe, 0 , 2 , "Coin Chutes" }, + {0x17, 0x01, 0x20, 0x00, "1" }, + {0x17, 0x01, 0x20, 0x20, "2" }, +}; + +STDDIPINFO(Astorm2p) + +static struct BurnDIPInfo CltchitrDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x16) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Game Time P1" }, + {0x17, 0x01, 0x0c, 0x04, "2 Credits 18 Outcounts 14 Min" }, + {0x17, 0x01, 0x0c, 0x00, "1 Credit 6 Outcounts 7 Min" }, + {0x17, 0x01, 0x0c, 0x08, "1 Credit 12 Outcounts 12 Min" }, + {0x17, 0x01, 0x0c, 0x0c, "1C 6OC 8M / 2C 18OC 14M" }, + + {0 , 0xfe, 0 , 4 , "Game Time P2" }, + {0x17, 0x01, 0x30, 0x10, "4 Credits 18 Outcounts 16 Min" }, + {0x17, 0x01, 0x30, 0x00, "2 Credits 6 Outcounts 8 Min" }, + {0x17, 0x01, 0x30, 0x20, "2 Credits 12 Outcounts 14 Min" }, + {0x17, 0x01, 0x30, 0x30, "2C 6OC 8M / 4C 18OC 16M" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0xc0, 0x40, "Easiest" }, + {0x17, 0x01, 0xc0, 0x80, "Easy" }, + {0x17, 0x01, 0xc0, 0xc0, "Normal" }, + {0x17, 0x01, 0xc0, 0x00, "Hard" }, +}; + +STDDIPINFO(Cltchitr) + +static struct BurnDIPInfo DdcrewDIPList[]= +{ + // Default Values + {0x1b, 0xff, 0xff, 0xff, NULL }, + {0x1c, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x1b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Credits Needed" }, + {0x1c, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x1c, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Switch to Start" }, + {0x1c, 0x01, 0x02, 0x02, "Start" }, + {0x1c, 0x01, 0x02, 0x00, "Attack" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x1c, 0x01, 0x04, 0x04, "Common" }, + {0x1c, 0x01, 0x04, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1c, 0x01, 0x08, 0x08, "Off" }, + {0x1c, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Player Start/Continue" }, + {0x1c, 0x01, 0x30, 0x30, "3/3" }, + {0x1c, 0x01, 0x30, 0x20, "2/3" }, + {0x1c, 0x01, 0x30, 0x10, "2/2" }, + {0x1c, 0x01, 0x30, 0x00, "3/4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1c, 0x01, 0xc0, 0x80, "Easy" }, + {0x1c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x1c, 0x01, 0xc0, 0x40, "Hard" }, + {0x1c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ddcrew) + +static struct BurnDIPInfo Ddcrew2DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x13) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Credits Needed" }, + {0x14, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x14, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Switch to Start" }, + {0x14, 0x01, 0x02, 0x02, "Start" }, + {0x14, 0x01, 0x02, 0x00, "Attack" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x14, 0x01, 0x04, 0x04, "Common" }, + {0x14, 0x01, 0x04, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x08, "Off" }, + {0x14, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Player Start/Continue" }, + {0x14, 0x01, 0x30, 0x30, "3/3" }, + {0x14, 0x01, 0x30, 0x20, "2/3" }, + {0x14, 0x01, 0x30, 0x10, "2/2" }, + {0x14, 0x01, 0x30, 0x00, "3/4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0xc0, 0x80, "Easy" }, + {0x14, 0x01, 0xc0, 0xc0, "Normal" }, + {0x14, 0x01, 0xc0, 0x40, "Hard" }, + {0x14, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ddcrew2) + +static struct BurnDIPInfo DdcrewuDIPList[]= +{ + // Default Values + {0x23, 0xff, 0xff, 0xff, NULL }, + {0x24, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x23) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Credits Needed" }, + {0x24, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x24, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Switch to Start" }, + {0x24, 0x01, 0x02, 0x02, "Start" }, + {0x24, 0x01, 0x02, 0x00, "Attack" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x24, 0x01, 0x04, 0x04, "Common" }, + {0x24, 0x01, 0x04, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x24, 0x01, 0x08, 0x08, "Off" }, + {0x24, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Player Start/Continue" }, + {0x24, 0x01, 0x30, 0x30, "3/3" }, + {0x24, 0x01, 0x30, 0x20, "2/3" }, + {0x24, 0x01, 0x30, 0x10, "2/2" }, + {0x24, 0x01, 0x30, 0x00, "3/4" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x24, 0x01, 0xc0, 0x80, "Easy" }, + {0x24, 0x01, 0xc0, 0xc0, "Normal" }, + {0x24, 0x01, 0xc0, 0x40, "Hard" }, + {0x24, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ddcrewu) + +static struct BurnDIPInfo DesertbrDIPList[]= +{ + // Default Values + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x1e) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1f, 0x01, 0x02, 0x02, "Off" }, + {0x1f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1f, 0x01, 0x08, 0x00, "2 Players" }, + {0x1f, 0x01, 0x08, 0x08, "3 Players" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x15, 0x01, 0x10, 0x10, "Common" }, + {0x15, 0x01, 0x10, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 2 , "Start Button" }, + {0x15, 0x01, 0x20, 0x20, "Use" }, + {0x15, 0x01, 0x20, 0x00, "Unused" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1f, 0x01, 0xc0, 0x80, "Easy" }, + {0x1f, 0x01, 0xc0, 0xc0, "Normal" }, + {0x1f, 0x01, 0xc0, 0x40, "Hard" }, + {0x1f, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Desertbr) + +static struct BurnDIPInfo LghostDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x14) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x15, 0x01, 0x01, 0x01, "Off" }, + {0x15, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 8 , "Difficulty" }, + {0x15, 0x01, 0x1c, 0x18, "Easy" }, + {0x15, 0x01, 0x1c, 0x14, "Easier" }, + {0x15, 0x01, 0x1c, 0x0c, "Easiest" }, + {0x15, 0x01, 0x1c, 0x1c, "Normal" }, + {0x15, 0x01, 0x1c, 0x10, "Hard" }, + {0x15, 0x01, 0x1c, 0x04, "Harder" }, + {0x15, 0x01, 0x1c, 0x08, "Hardest" }, + {0x15, 0x01, 0x1c, 0x00, "Extra Hardest" }, + + {0 , 0xfe, 0 , 2 , "Continue Mode" }, + {0x15, 0x01, 0x20, 0x00, "Off" }, + {0x15, 0x01, 0x20, 0x20, "On" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x15, 0x01, 0x40, 0x00, "Common" }, + {0x15, 0x01, 0x40, 0x40, "Individual" }, +}; + +STDDIPINFO(Lghost) + +static struct BurnDIPInfo MwalkDIPList[]= +{ + // Default Values + {0x1e, 0xff, 0xff, 0xff, NULL }, + {0x1f, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x1e) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x1f, 0x01, 0x01, 0x01, "Off" }, + {0x1f, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x1f, 0x01, 0x02, 0x02, "Off" }, + {0x1f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x1f, 0x01, 0x04, 0x04, "2" }, + {0x1f, 0x01, 0x04, 0x00, "3" }, + + {0 , 0xfe, 0 , 2 , "Player Vitality" }, + {0x1f, 0x01, 0x08, 0x08, "Low" }, + {0x1f, 0x01, 0x08, 0x00, "High" }, + + {0 , 0xfe, 0 , 2 , "Play Mode" }, + {0x1f, 0x01, 0x10, 0x10, "2 Players" }, + {0x1f, 0x01, 0x10, 0x00, "3 Players" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x1f, 0x01, 0x20, 0x20, "Common" }, + {0x1f, 0x01, 0x20, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1f, 0x01, 0xc0, 0x80, "Easy" }, + {0x1f, 0x01, 0xc0, 0xc0, "Normal" }, + {0x1f, 0x01, 0xc0, 0x40, "Hard" }, + {0x1f, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Mwalk) + +static struct BurnDIPInfo ShdancerDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x16) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x17, 0x01, 0x01, 0x01, "Off" }, + {0x17, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x17, 0x01, 0x0c, 0x00, "2" }, + {0x17, 0x01, 0x0c, 0x0c, "3" }, + {0x17, 0x01, 0x0c, 0x08, "4" }, + {0x17, 0x01, 0x0C, 0x04, "5" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0x30, 0x20, "Easy" }, + {0x17, 0x01, 0x30, 0x30, "Normal" }, + {0x17, 0x01, 0x30, 0x10, "Hard" }, + {0x17, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time Adjust" }, + {0x17, 0x01, 0xc0, 0x00, "2:20" }, + {0x17, 0x01, 0xc0, 0x40, "2:40" }, + {0x17, 0x01, 0xc0, 0xc0, "3:00" }, + {0x17, 0x01, 0xc0, 0x80, "3:30" }, +}; + +STDDIPINFO(Shdancer) + +static struct BurnDIPInfo WwallyDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + SYSTEM18_COINAGE(0x11) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "2 Credits to Start" }, + {0x12, 0x01, 0x01, 0x01, "Off" }, + {0x12, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x12, 0x01, 0x02, 0x02, "Off" }, + {0x12, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x12, 0x01, 0x04, 0x04, "Common" }, + {0x12, 0x01, 0x04, 0x00, "Individual" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x60, 0x40, "Easy" }, + {0x12, 0x01, 0x60, 0x60, "Normal" }, + {0x12, 0x01, 0x60, 0x20, "Hard" }, + {0x12, 0x01, 0x60, 0x00, "Hardest" }, +}; + +STDDIPINFO(Wwally) + +#undef SYSTEM18_COINAGE + +/*==================================================== +Rom defs +====================================================*/ + +static struct BurnRomInfo AstormRomDesc[] = { + { "epr-13182.a6", 0x40000, 0xe31f2a1c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13181.a5", 0x40000, 0x78cd3b26, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13073.bin", 0x40000, 0xdf5d0a61, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13074.bin", 0x40000, 0x787afab8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13075.bin", 0x40000, 0x4e01b477, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13082.bin", 0x40000, 0xa782b704, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13089.bin", 0x40000, 0x2a4227f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13081.bin", 0x40000, 0xeb510228, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13088.bin", 0x40000, 0x3b6b4c55, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13080.bin", 0x40000, 0xe668eefb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13087.bin", 0x40000, 0x2293427d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13079.bin", 0x40000, 0xde9221ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13086.bin", 0x40000, 0x8c9a71c4, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13083a.bin", 0x20000, 0xe7528e06, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13076.bin", 0x40000, 0x94e6c76e, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13077.bin", 0x40000, 0xe2ec0d8d, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13078.bin", 0x40000, 0x15684dc5, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0154.key", 0x02000, 0xb86b6b8f, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Astorm) +STD_ROM_FN(Astorm) + +static struct BurnRomInfo Astorm3RomDesc[] = { + { "epr-13165.a6", 0x40000, 0x6efcd381, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13164.a5", 0x40000, 0x97d693c6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13073.bin", 0x40000, 0xdf5d0a61, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13074.bin", 0x40000, 0x787afab8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13075.bin", 0x40000, 0x4e01b477, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13082.bin", 0x40000, 0xa782b704, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13089.bin", 0x40000, 0x2a4227f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13081.bin", 0x40000, 0xeb510228, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13088.bin", 0x40000, 0x3b6b4c55, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13080.bin", 0x40000, 0xe668eefb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13087.bin", 0x40000, 0x2293427d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13079.bin", 0x40000, 0xde9221ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13086.bin", 0x40000, 0x8c9a71c4, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13083.bin", 0x20000, 0x5df3af20, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13076.bin", 0x40000, 0x94e6c76e, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13077.bin", 0x40000, 0xe2ec0d8d, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13078.bin", 0x40000, 0x15684dc5, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0148.key", 0x02000, 0x72e4b64a, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Astorm3) +STD_ROM_FN(Astorm3) + +static struct BurnRomInfo AstormjRomDesc[] = { + { "epr-13085.a6", 0x40000, 0x15f74e2d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13084.a5", 0x40000, 0x9687b38f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13073.bin", 0x40000, 0xdf5d0a61, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13074.bin", 0x40000, 0x787afab8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13075.bin", 0x40000, 0x4e01b477, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13082.bin", 0x40000, 0xa782b704, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13089.bin", 0x40000, 0x2a4227f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13081.bin", 0x40000, 0xeb510228, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13088.bin", 0x40000, 0x3b6b4c55, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13080.bin", 0x40000, 0xe668eefb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13087.bin", 0x40000, 0x2293427d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13079.bin", 0x40000, 0xde9221ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13086.bin", 0x40000, 0x8c9a71c4, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13083.bin", 0x20000, 0x5df3af20, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13076.bin", 0x40000, 0x94e6c76e, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13077.bin", 0x40000, 0xe2ec0d8d, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13078.bin", 0x40000, 0x15684dc5, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0146.key", 0x02000, 0xe94991c5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Astormj) +STD_ROM_FN(Astormj) + +static struct BurnRomInfo AstormjaRomDesc[] = { + { "epr-13085.a6", 0x40000, 0x15f74e2d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13084.a5", 0x40000, 0x9687b38f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13073.bin", 0x40000, 0xdf5d0a61, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13074.bin", 0x40000, 0x787afab8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13075.bin", 0x40000, 0x4e01b477, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13082.bin", 0x40000, 0xa782b704, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13089.bin", 0x40000, 0x2a4227f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13081.bin", 0x40000, 0xeb510228, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13088.bin", 0x40000, 0x3b6b4c55, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13080.bin", 0x40000, 0xe668eefb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13087.bin", 0x40000, 0x2293427d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13079.bin", 0x40000, 0xde9221ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13086.bin", 0x40000, 0x8c9a71c4, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13083b.bin", 0x20000, 0x169b4b5f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13076.bin", 0x40000, 0x94e6c76e, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13077.bin", 0x40000, 0xe2ec0d8d, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13078.bin", 0x40000, 0x15684dc5, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0146.key", 0x02000, 0xe94991c5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Astormja) +STD_ROM_FN(Astormja) + +static struct BurnRomInfo AstormuRomDesc[] = { + { "epr-13095.a6", 0x40000, 0x55d40742, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13094.a5", 0x40000, 0x92b305f9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13073.bin", 0x40000, 0xdf5d0a61, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13074.bin", 0x40000, 0x787afab8, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13075.bin", 0x40000, 0x4e01b477, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13082.bin", 0x40000, 0xa782b704, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13089.bin", 0x40000, 0x2a4227f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13081.bin", 0x40000, 0xeb510228, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13088.bin", 0x40000, 0x3b6b4c55, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13080.bin", 0x40000, 0xe668eefb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13087.bin", 0x40000, 0x2293427d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13079.bin", 0x40000, 0xde9221ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13086.bin", 0x40000, 0x8c9a71c4, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13083.bin", 0x20000, 0x5df3af20, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13076.bin", 0x40000, 0x94e6c76e, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13077.bin", 0x40000, 0xe2ec0d8d, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13078.bin", 0x40000, 0x15684dc5, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0147.key", 0x02000, 0x3fd54ba7, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Astormu) +STD_ROM_FN(Astormu) + +static struct BurnRomInfo BloxeedRomDesc[] = { + { "epr-12911.a6", 0x20000, 0xa481581a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12910.a5", 0x20000, 0xdd1bc3bf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "opr-12884.b1", 0x10000, 0xe024aa33, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12885.b2", 0x10000, 0x8041b814, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12886.b3", 0x10000, 0xde32285e, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-12887.b11", 0x10000, 0xf0c0f49d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-12891.a11", 0x10000, 0x90d31a8c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12888.a4", 0x20000, 0x6f2fc63c, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "317-0139.key", 0x02000, 0x9aae84cb, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Bloxeed) +STD_ROM_FN(Bloxeed) + +static struct BurnRomInfo CltchitrRomDesc[] = { + { "epr-13794.a4", 0x40000, 0xc8d80233, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13795.a6", 0x40000, 0xb0b60b67, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13784.a5", 0x40000, 0x80c8180d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13786.a7", 0x40000, 0x3095dac0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13773.c1", 0x80000, 0x3fc600e5, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13774.c2", 0x80000, 0x2411a824, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13775.c3", 0x80000, 0xcf527bf6, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13779.c10", 0x80000, 0xc707f416, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13787.a10", 0x80000, 0xf05c68c6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13780.c11", 0x80000, 0xa4c341e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13788.a11", 0x80000, 0x0106fea6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13781.c12", 0x80000, 0xf33b13af, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13789.a12", 0x80000, 0x09ba8835, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13793.c7", 0x80000, 0xa3d31944, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13792.c6", 0x80000, 0x808f9695, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13791.c5", 0x80000, 0x35c16d80, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0176.key", 0x02000, 0x9b072430, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Cltchitr) +STD_ROM_FN(Cltchitr) + +static struct BurnRomInfo CltchitrjRomDesc[] = { + { "epr-13783.a4", 0x40000, 0xe2a1d5af, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13796.a6", 0x40000, 0x06001c67, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13785.a5", 0x40000, 0x09714762, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13797.a7", 0x40000, 0x361ade9f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13773.c1", 0x80000, 0x3fc600e5, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13774.c2", 0x80000, 0x2411a824, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13775.c3", 0x80000, 0xcf527bf6, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13779.c10", 0x80000, 0xc707f416, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13787.a10", 0x80000, 0xf05c68c6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13780.c11", 0x80000, 0xa4c341e0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13788.a11", 0x80000, 0x0106fea6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13781.c12", 0x80000, 0xf33b13af, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13789.a12", 0x80000, 0x09ba8835, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13782.c13", 0x40000, 0x73790852, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13790.a13", 0x40000, 0x23849101, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13778.c7", 0x20000, 0x35e86146, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13777.c6", 0x80000, 0xd1524782, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-13776.c5", 0x80000, 0x282ac9fe, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0175.key", 0x02000, 0x70d9d283, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Cltchitrj) +STD_ROM_FN(Cltchitrj) + +static struct BurnRomInfo DdcrewRomDesc[] = { + { "epr-14160.a4", 0x40000, 0xb9f897b7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14161.a6", 0x40000, 0xbb03c1f0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14139.a5", 0x40000, 0x06c31531, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14141.a7", 0x40000, 0x080a494b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14127.c1", 0x40000, 0x2228cd88, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14128.c2", 0x40000, 0xedba8e10, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14129.c3", 0x40000, 0xe8ecc305, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14134.c10", 0x80000, 0x4fda6a4b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14142.a10", 0x80000, 0x3cbf1f2a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14135.c11", 0x80000, 0xe9c74876, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14143.a11", 0x80000, 0x59022c31, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14136.c12", 0x80000, 0x720d9858, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14144.a12", 0x80000, 0x7775fdd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14137.c13", 0x80000, 0x846c4265, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14145.a13", 0x80000, 0x0e76c797, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14133.c7", 0x20000, 0xcff96665, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14132.c6", 0x80000, 0x1fae0220, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14131.c5", 0x80000, 0xbe5a7d0b, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-14130.c4", 0x80000, 0x948f34a1, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0190.key", 0x02000, 0x2d502b11, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Ddcrew) +STD_ROM_FN(Ddcrew) + +static struct BurnRomInfo Ddcrew1RomDesc[] = { + { "epr-14154.a4", 0x40000, 0x9a0dadf0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14155.a6", 0x40000, 0xe74362f4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14139.a5", 0x40000, 0x06c31531, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14141.a7", 0x40000, 0x080a494b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14127.c1", 0x40000, 0x2228cd88, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14128.c2", 0x40000, 0xedba8e10, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14129.c3", 0x40000, 0xe8ecc305, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14134.c10", 0x80000, 0x4fda6a4b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14142.a10", 0x80000, 0x3cbf1f2a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14135.c11", 0x80000, 0xe9c74876, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14143.a11", 0x80000, 0x59022c31, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14136.c12", 0x80000, 0x720d9858, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14144.a12", 0x80000, 0x7775fdd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14137.c13", 0x80000, 0x846c4265, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14145.a13", 0x80000, 0x0e76c797, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14133.c7", 0x20000, 0xcff96665, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14132.c6", 0x80000, 0x1fae0220, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14131.c5", 0x80000, 0xbe5a7d0b, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-14130.c4", 0x80000, 0x948f34a1, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0187.key", 0x02000, 0x1dfb60be, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Ddcrew1) +STD_ROM_FN(Ddcrew1) + +static struct BurnRomInfo Ddcrew2RomDesc[] = { + { "epr-14148.a4", 0x40000, 0xdf4cb0cf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14149.a6", 0x40000, 0x380ff818, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14139.a5", 0x40000, 0x06c31531, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14141.a7", 0x40000, 0x080a494b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14127.c1", 0x40000, 0x2228cd88, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14128.c2", 0x40000, 0xedba8e10, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14129.c3", 0x40000, 0xe8ecc305, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14134.c10", 0x80000, 0x4fda6a4b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14142.a10", 0x80000, 0x3cbf1f2a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14135.c11", 0x80000, 0xe9c74876, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14143.a11", 0x80000, 0x59022c31, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14136.c12", 0x80000, 0x720d9858, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14144.a12", 0x80000, 0x7775fdd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14137.c13", 0x80000, 0x846c4265, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14145.a13", 0x80000, 0x0e76c797, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14133.c7", 0x20000, 0xcff96665, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14132.c6", 0x80000, 0x1fae0220, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14131.c5", 0x80000, 0xbe5a7d0b, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-14130.c4", 0x80000, 0x948f34a1, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0184.key", 0x02000, 0xcee06254, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Ddcrew2) +STD_ROM_FN(Ddcrew2) + +static struct BurnRomInfo DdcrewjRomDesc[] = { + { "epr-14138.a4", 0x40000, 0xdf280b1b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14140.a6", 0x40000, 0x48f223ee, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14139.a5", 0x40000, 0x06c31531, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14141.a7", 0x40000, 0x080a494b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14127.c1", 0x40000, 0x2228cd88, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14128.c2", 0x40000, 0xedba8e10, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14129.c3", 0x40000, 0xe8ecc305, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14134.c10", 0x80000, 0x4fda6a4b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14142.a10", 0x80000, 0x3cbf1f2a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14135.c11", 0x80000, 0xe9c74876, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14143.a11", 0x80000, 0x59022c31, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14136.c12", 0x80000, 0x720d9858, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14144.a12", 0x80000, 0x7775fdd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14137.c13", 0x80000, 0x846c4265, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14145.a13", 0x80000, 0x0e76c797, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14133.c7", 0x20000, 0xcff96665, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14132.c6", 0x80000, 0x1fae0220, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14131.c5", 0x80000, 0xbe5a7d0b, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-14130.c4", 0x80000, 0x948f34a1, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0182.key", 0x02000, 0x2e8a3601, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Ddcrewj) +STD_ROM_FN(Ddcrewj) + +static struct BurnRomInfo DdcrewuRomDesc[] = { + { "epr-14152.a4", 0x40000, 0x69c7b571, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14153.a6", 0x40000, 0xe01fae0c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14139.a5", 0x40000, 0x06c31531, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mpr-14141.a7", 0x40000, 0x080a494b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-14127.c1", 0x40000, 0x2228cd88, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14128.c2", 0x40000, 0xedba8e10, SYS16_ROM_TILES | BRF_GRA }, + { "epr-14129.c3", 0x40000, 0xe8ecc305, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14134.c10", 0x80000, 0x4fda6a4b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14142.a10", 0x80000, 0x3cbf1f2a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14135.c11", 0x80000, 0xe9c74876, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14143.a11", 0x80000, 0x59022c31, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14136.c12", 0x80000, 0x720d9858, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14144.a12", 0x80000, 0x7775fdd4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14137.c13", 0x80000, 0x846c4265, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-14145.a13", 0x80000, 0x0e76c797, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14133.c7", 0x20000, 0xcff96665, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14132.c6", 0x80000, 0x1fae0220, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14131.c5", 0x80000, 0xbe5a7d0b, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "epr-14130.c4", 0x80000, 0x948f34a1, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0186.key", 0x02000, 0x7acaf1fd, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Ddcrewu) +STD_ROM_FN(Ddcrewu) + +static struct BurnRomInfo DesertbrRomDesc[] = { + { "epr-14802.a4", 0x080000, 0x9ab93cbc, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14902.a6", 0x080000, 0x6724e7b1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14793.a5", 0x080000, 0xdc9d7af3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14795.a7", 0x080000, 0x7e5bf7d9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14781.c1", 0x100000, 0xc4f7d7aa, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14782.c2", 0x100000, 0xccc98d05, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14783.c3", 0x100000, 0xef202bec, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14788.c10", 0x100000, 0xb5b05536, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14796.a10", 0x100000, 0xc033220a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14789.c11", 0x100000, 0x0f9bcb97, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14797.a11", 0x100000, 0x4c301cc9, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14790.c12", 0x100000, 0x6a07ac27, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14798.a12", 0x100000, 0x50634625, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14791.c13", 0x100000, 0xa4ae352b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14799.a13", 0x100000, 0xaeb7b025, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14787.c7", 0x040000, 0xcc6feec7, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14786.c6", 0x080000, 0xcc8349f2, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14785.c5", 0x080000, 0x7babba13, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14784.c4", 0x080000, 0x073878e4, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0196.key", 0x002000, 0xcb942262, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Desertbr) +STD_ROM_FN(Desertbr) + +static struct BurnRomInfo DesertbrjRomDesc[] = { + { "epr-14792.a4", 0x080000, 0x453d9d02, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14794.a6", 0x080000, 0x4426758f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14793.a5", 0x080000, 0xdc9d7af3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14795.a7", 0x080000, 0x7e5bf7d9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14781.c1", 0x100000, 0xc4f7d7aa, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14782.c2", 0x100000, 0xccc98d05, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14783.c3", 0x100000, 0xef202bec, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14788.c10", 0x100000, 0xb5b05536, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14796.a10", 0x100000, 0xc033220a, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14789.c11", 0x100000, 0x0f9bcb97, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14797.a11", 0x100000, 0x4c301cc9, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14790.c12", 0x100000, 0x6a07ac27, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14798.a12", 0x100000, 0x50634625, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14791.c13", 0x100000, 0xa4ae352b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14799.a13", 0x100000, 0xaeb7b025, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14787.c7", 0x040000, 0xcc6feec7, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14786.c6", 0x080000, 0xcc8349f2, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14785.c5", 0x080000, 0x7babba13, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14784.c4", 0x080000, 0x073878e4, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0194.key", 0x002000, 0x40cbc4cb, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Desertbrj) +STD_ROM_FN(Desertbrj) + +static struct BurnRomInfo LghostRomDesc[] = { + { "epr-13429.a4", 0x40000, 0x09bd65c0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13430.a6", 0x40000, 0x51009fe0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13411.a5", 0x40000, 0x5160167b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13413.a7", 0x40000, 0x656b3bd8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13414.c1", 0x40000, 0xdada2419, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13415.c2", 0x40000, 0xbbb62c48, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13416.c3", 0x40000, 0x1d11dbae, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-13604.c10", 0x80000, 0x4009c8e5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13603.a10", 0x80000, 0x5350a94e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13424.c11", 0x80000, 0xfb98d920, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13421.a11", 0x80000, 0x2fc75890, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13425.c12", 0x80000, 0xf8252589, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13422.a12", 0x80000, 0x48a0754d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13426.c13", 0x80000, 0x5cfb1e25, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13423.a13", 0x80000, 0x335bbc9d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13417.c7", 0x20000, 0xcd7beb49, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13420.c6", 0x40000, 0x3de0dee4, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13419.c5", 0x40000, 0xe7021b0a, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13418.c4", 0x40000, 0x0732594d, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0166.key", 0x02000, 0x8379961f, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Lghost) +STD_ROM_FN(Lghost) + +static struct BurnRomInfo LghostuRomDesc[] = { + { "epr-13427.a4", 0x40000, 0x5bf8fb6b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13428.a6", 0x40000, 0x276775f5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13411.a5", 0x40000, 0x5160167b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13413.a7", 0x40000, 0x656b3bd8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13414.c1", 0x40000, 0xdada2419, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13415.c2", 0x40000, 0xbbb62c48, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13416.c3", 0x40000, 0x1d11dbae, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-13604.c10", 0x80000, 0x4009c8e5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13603.a10", 0x80000, 0x5350a94e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13424.c11", 0x80000, 0xfb98d920, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13421.a11", 0x80000, 0x2fc75890, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13425.c12", 0x80000, 0xf8252589, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13422.a12", 0x80000, 0x48a0754d, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13426.c13", 0x80000, 0x5cfb1e25, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13423.a13", 0x80000, 0x335bbc9d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13417.c7", 0x20000, 0xcd7beb49, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13420.c6", 0x40000, 0x3de0dee4, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13419.c5", 0x40000, 0xe7021b0a, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13418.c4", 0x40000, 0x0732594d, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0165.key", 0x02000, 0xa04267ab, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Lghostu) +STD_ROM_FN(Lghostu) + +static struct BurnRomInfo MwalkRomDesc[] = { + { "epr-13235.a6", 0x40000, 0x6983e129, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13234.a5", 0x40000, 0xc9fd20f2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13216.b1", 0x40000, 0x862d2c03, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13217.b2", 0x40000, 0x7d1ac3ec, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-13218.b3", 0x40000, 0x56d3393c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-13224.b11", 0x40000, 0xc59f107b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13231.a11", 0x40000, 0xa5e96346, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13223.b10", 0x40000, 0x364f60ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13230.a10", 0x40000, 0x9550091f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13222.b9", 0x40000, 0x523df3ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13229.a9", 0x40000, 0xf40dc45d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13221.b8", 0x40000, 0x9ae7546a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13228.a8", 0x40000, 0xde3786be, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13225.a4", 0x20000, 0x56c2e82b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13219.b4", 0x40000, 0x19e2061f, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13220.b5", 0x40000, 0x58d4d9ce, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-13249.b6", 0x40000, 0x623edc5d, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0159.key", 0x02000, 0x507838f0, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, + + { "315-5437.ic4", 0x01000, 0x4bf63bc1, SYS16_ROM_PROM | BRF_PRG}, +}; + + +STD_ROM_PICK(Mwalk) +STD_ROM_FN(Mwalk) + +static struct BurnRomInfo MwalkblRomDesc[] = { + { "mwalkbl.01", 0x10000, 0xf49cdb16, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.05", 0x10000, 0xc483f29f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.02", 0x10000, 0x0bde1896, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.06", 0x10000, 0x5b9fc688, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.03", 0x10000, 0x0c5fe15c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.07", 0x10000, 0x9e600704, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.04", 0x10000, 0x64692f79, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "mwalkbl.08", 0x10000, 0x546ca530, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr13216.b1", 0x40000, 0x862d2c03, SYS16_ROM_TILES | BRF_GRA }, + { "mpr13217.b2", 0x40000, 0x7d1ac3ec, SYS16_ROM_TILES | BRF_GRA }, + { "mpr13218.b3", 0x40000, 0x56d3393c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr13224.b11", 0x40000, 0xc59f107b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr13231.a11", 0x40000, 0xa5e96346, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr13223.b10", 0x40000, 0x364f60ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr13230.a10", 0x40000, 0x9550091f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr13222.b9", 0x40000, 0x523df3ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr13229.a9", 0x40000, 0xf40dc45d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr13221.b8", 0x40000, 0x9ae7546a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr13228.a8", 0x40000, 0xde3786be, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr13225.a4", 0x20000, 0x56c2e82b, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr13219.b4", 0x40000, 0x19e2061f, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr13220.b5", 0x40000, 0x58d4d9ce, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr13249.b6", 0x40000, 0x623edc5d, SYS16_ROM_RF5C68DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Mwalkbl) +STD_ROM_FN(Mwalkbl) + +static struct BurnRomInfo ShdancerRomDesc[] = { + { "shdancer.a6", 0x40000, 0x3d5b3fa9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "shdancer.a5", 0x40000, 0x2596004e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12712.b1", 0x40000, 0x9bdabe3d, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12713.b2", 0x40000, 0x852d2b1c, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12714.b3", 0x40000, 0x448226ce, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12719.b11", 0x40000, 0xd6888534, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12726.a11", 0x40000, 0xff344945, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12718.b10", 0x40000, 0xba2efc0c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12725.a10", 0x40000, 0x268a0c17, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12717.b9", 0x40000, 0xc81cc4f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12724.a9", 0x40000, 0x0f4903dc, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12716.b8", 0x40000, 0xa870e629, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12723.a8", 0x40000, 0xc606cf90, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12720.a4", 0x20000, 0x7a0d8de1, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12715.b4", 0x40000, 0x07051a52, SYS16_ROM_RF5C68DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shdancer) +STD_ROM_FN(Shdancer) + +static struct BurnRomInfo Shdancer1RomDesc[] = { + { "epr-12772b.a6", 0x40000, 0x6868a4d4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12771b.a5", 0x40000, 0x04e30c84, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12712.b1", 0x40000, 0x9bdabe3d, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12713.b2", 0x40000, 0x852d2b1c, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12714.b3", 0x40000, 0x448226ce, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12719.b11", 0x40000, 0xd6888534, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12726.a11", 0x40000, 0xff344945, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12718.b10", 0x40000, 0xba2efc0c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12725.a10", 0x40000, 0x268a0c17, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12717.b9", 0x40000, 0xc81cc4f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12724.a9", 0x40000, 0x0f4903dc, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12716.b8", 0x40000, 0xa870e629, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12723.a8", 0x40000, 0xc606cf90, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12720.a4", 0x20000, 0x7a0d8de1, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12715.b4", 0x40000, 0x07051a52, SYS16_ROM_RF5C68DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shdancer1) +STD_ROM_FN(Shdancer1) + +static struct BurnRomInfo ShdancerjRomDesc[] = { + { "epr-12722b.a6", 0x40000, 0xc00552a2, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12721b.a5", 0x40000, 0x653d351a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12712.b1", 0x40000, 0x9bdabe3d, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12713.b2", 0x40000, 0x852d2b1c, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-12714.b3", 0x40000, 0x448226ce, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12719.b11", 0x40000, 0xd6888534, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12726.a11", 0x40000, 0xff344945, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12718.b10", 0x40000, 0xba2efc0c, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12725.a10", 0x40000, 0x268a0c17, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12717.b9", 0x40000, 0xc81cc4f8, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12724.a9", 0x40000, 0x0f4903dc, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12716.b8", 0x40000, 0xa870e629, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12723.a8", 0x40000, 0xc606cf90, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12720.a4", 0x20000, 0x7a0d8de1, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-12715.b4", 0x40000, 0x07051a52, SYS16_ROM_RF5C68DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shdancerj) +STD_ROM_FN(Shdancerj) + +static struct BurnRomInfo ShdancblRomDesc[] = { + { "ic39", 0x10000, 0xadc1781c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic53", 0x10000, 0x1c1ac463, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic38", 0x10000, 0xcd6e155b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic52", 0x10000, 0xbb3c49a4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic37", 0x10000, 0x1bd8d5c3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic51", 0x10000, 0xce2e71b4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic36", 0x10000, 0xbb861290, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ic50", 0x10000, 0x7f7b82b1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "ic4", 0x20000, 0xf0a016fe, SYS16_ROM_TILES | BRF_GRA }, + { "ic18", 0x20000, 0xf6bee053, SYS16_ROM_TILES | BRF_GRA }, + { "ic3", 0x20000, 0xe07e6b5d, SYS16_ROM_TILES | BRF_GRA }, + { "ic17", 0x20000, 0xf59deba1, SYS16_ROM_TILES | BRF_GRA }, + { "ic2", 0x20000, 0x60095070, SYS16_ROM_TILES | BRF_GRA }, + { "ic16", 0x20000, 0x0f0d5dd3, SYS16_ROM_TILES | BRF_GRA }, + + { "ic73", 0x10000, 0x59e77c96, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic58", 0x10000, 0x9cd5c8c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic74", 0x10000, 0x90ea5407, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic59", 0x10000, 0xff40e872, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic75", 0x10000, 0x27d2fa61, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic60", 0x10000, 0x826d7245, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic76", 0x10000, 0xf36db688, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic61", 0x10000, 0xdcf8068b, SYS16_ROM_SPRITES | BRF_GRA }, + + { "ic77", 0x10000, 0xf93470b7, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic62", 0x10000, 0x50ca8065, SYS16_ROM_SPRITES | BRF_GRA }, + { "sdbl.78", 0x10000, 0xe533be5d, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic63", 0x10000, 0xd1866aa9, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic95", 0x10000, 0x828b8294, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic90", 0x10000, 0x3602b758, SYS16_ROM_SPRITES | BRF_GRA }, + { "sdbl.94", 0x10000, 0xe2fa2b41, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic89", 0x10000, 0x1ba4be93, SYS16_ROM_SPRITES | BRF_GRA }, + + { "ic79", 0x10000, 0xf22548ee, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic64", 0x10000, 0x7a8b7bcc, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic80", 0x10000, 0x6209f7f9, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic65", 0x10000, 0x90ffca14, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic81", 0x10000, 0x34692f23, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic66", 0x10000, 0x5d655517, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic82", 0x10000, 0x7ae40237, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic67", 0x10000, 0x0e5d0855, SYS16_ROM_SPRITES | BRF_GRA }, + + { "ic83", 0x10000, 0xa9040a32, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic68", 0x10000, 0x8d684e53, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic84", 0x10000, 0xd6810031, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic69", 0x10000, 0xc47d32e2, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic92", 0x10000, 0xb57d5cb5, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic88", 0x10000, 0x9de140e1, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic91", 0x10000, 0x49def6c8, SYS16_ROM_SPRITES | BRF_GRA }, + { "ic87", 0x10000, 0x8172a991, SYS16_ROM_SPRITES | BRF_GRA }, + + { "ic45", 0x10000, 0x576b3a81, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "ic46", 0x10000, 0xc84e8c84, SYS16_ROM_RF5C68DATA | BRF_SND }, +}; + + +STD_ROM_PICK(Shdancbl) +STD_ROM_FN(Shdancbl) + +static struct BurnRomInfo WwallyjRomDesc[] = { + { "epr-14730b.a4", 0x040000, 0xe72bc17a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14731b.a6", 0x040000, 0x6e3235b9, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14719.c1", 0x040000, 0x8b58c743, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14720.c2", 0x040000, 0xf96d19f4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14721.c3", 0x040000, 0xc4ced91d, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14726.c10", 0x100000, 0x7213d1d3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14732.a10", 0x100000, 0x04ced549, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14727.c11", 0x100000, 0x3b74e0f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14733.a11", 0x100000, 0x6da0444f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14728.c12", 0x080000, 0x5b921587, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14734.a12", 0x080000, 0x6f3f5ed9, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14725.c7", 0x020000, 0x2b29684f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14724.c6", 0x080000, 0x47cbea86, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14723.c5", 0x080000, 0xbc5adc27, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14722.c4", 0x080000, 0x1bd081f8, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0197b.key", 0x002000, 0xf5b7c5b4, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Wwallyj) +STD_ROM_FN(Wwallyj) + +static struct BurnRomInfo WwallyjaRomDesc[] = { + { "epr-14730a.a4", 0x040000, 0xdaa7880e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-14731a.a6", 0x040000, 0x5e36353b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14719.c1", 0x040000, 0x8b58c743, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14720.c2", 0x040000, 0xf96d19f4, SYS16_ROM_TILES | BRF_GRA }, + { "mpr-14721.c3", 0x040000, 0xc4ced91d, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-14726.c10", 0x100000, 0x7213d1d3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14732.a10", 0x100000, 0x04ced549, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14727.c11", 0x100000, 0x3b74e0f0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14733.a11", 0x100000, 0x6da0444f, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14728.c12", 0x080000, 0x5b921587, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-14734.a12", 0x080000, 0x6f3f5ed9, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-14725.c7", 0x020000, 0x2b29684f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-14724.c6", 0x080000, 0x47cbea86, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14723.c5", 0x080000, 0xbc5adc27, SYS16_ROM_RF5C68DATA | BRF_SND }, + { "mpr-14722.c4", 0x080000, 0x1bd081f8, SYS16_ROM_RF5C68DATA | BRF_SND }, + + { "317-0197a.key", 0x002000, 0x2fb6a9a1, SYS16_ROM_KEY | BRF_ESS | BRF_PRG}, +}; + + +STD_ROM_PICK(Wwallyja) +STD_ROM_FN(Wwallyja) + +/*==================================================== +Memory Handlers +====================================================*/ + +static UINT8 misc_io_data[0x10]; + +static UINT8 io_chip_r(UINT32 offset) +{ + switch (offset) { + case 0x03: + case 0x07: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff; + } + + case 0x00: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff - System16Input[1]; + } + + case 0x01: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff - System16Input[2]; + } + + case 0x02: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff - System16Input[3]; + } + + case 0x04: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff - System16Input[0]; + } + + case 0x05: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return System16Dip[0]; + } + + case 0x06: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return System16Dip[1]; + } + + case 0x08: { + return 'S'; + } + + case 0x09: { + return 'E'; + } + + case 0x0a: { + return 'G'; + } + + case 0x0b: { + return 'A'; + } + + case 0x0c: + case 0x0e: { + return misc_io_data[0x0e]; + } + + case 0x0d: + case 0x0f: { + return misc_io_data[0x0f]; + } + } + + return 0xff; +} + +static void io_chip_w(UINT32 offset, UINT16 d) +{ + UINT8 old; + + offset &= 0x1f/2; + + old = misc_io_data[offset]; + misc_io_data[offset] = d; + + switch (offset) { + case 0x00: + case 0x01: + case 0x02: + case 0x04: + case 0x05: + case 0x06: { + return; + } + + case 0x07: { + for (int i = 0; i < 4; i++) { + if (System16TileBanks[0 + i] != ((d & 0xf) * 4 + i)) { + System16TileBanks[0 + i] = (d & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + if (System16TileBanks[4 + i] != (((d >> 4) & 0xf) * 4 + i)) { + System16TileBanks[4 + i] = ((d >> 4) & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + } + return; + } + + case 0x0e: { + System16VideoEnable = d & 0x02; + if ((old ^ d) & 4) System18VdpEnable = d & 0x04; + return; + } + + } +} + +static void System18GfxBankWrite(UINT32 offset, UINT16 d) +{ + // Tile Banking + if (offset < 8) { + INT32 MaxBanks = System16NumTiles / 1024; + if (d >= MaxBanks) d %= MaxBanks; + if (System16TileBanks[offset] != d) { + System16TileBanks[offset] = d; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + } else { + // Sprite Banking + INT32 MaxBanks = System16SpriteRomSize / 0x40000; + if (d >= MaxBanks) d = 255; + System16SpriteBanks[(offset - 8) * 2 + 0] = d * 2 + 0; + System16SpriteBanks[(offset - 8) * 2 + 1] = d * 2 + 1; + } +} + +UINT16 __fastcall System18ReadWord(UINT32 a) +{ + if (a >= 0xc00000 && a <= 0xc0000f) { + return GenesisVDPRead((a - 0xc00000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall System18ReadByte(UINT32 a) +{ + if (a >= 0xa40000 && a <= 0xa4001f) { + return io_chip_r((a - 0xa40000) >> 1); + } + + if (a >= 0xe40000 && a <= 0xe4001f) { + return io_chip_r((a - 0xe40000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall System18WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileWordWrite(a - 0x400000, d); + return; + } + + if (a >= 0xc00000 && a <= 0xc0000f) { + GenesisVDPWrite((a - 0xc00000) >> 1, d); + return; + } + + switch (a) { + case 0xe42000: { + System18VdpMixing = d & 0xff; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall System18WriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x40ffff) { + System16BTileByteWrite((a - 0x400000) ^ 1, d); + return; + } + + if (a >= 0x3e0000 && a <= 0x3e001f) { + System18GfxBankWrite((a - 0x3e0000) >> 1, d); + return; + } + + if (a >= 0xa40000 && a <= 0xa41fff) { + io_chip_w((a - 0xa40000) >> 1, d); + return; + } + + if (a >= 0xc00000 && a <= 0xc0000f) { + GenesisVDPWrite((a - 0xc00000) >> 1, d); + return; + } + + if (a >= 0xe40000 && a <= 0xe41fff) { + io_chip_w((a - 0xe40000) >> 1, d); + return; + } + + switch (a) { + case 0xa42001: + case 0xe42001: { + System18VdpMixing = d & 0xff; + return; + } + + case 0xfe0007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT8 __fastcall Astorm3ReadByte(UINT32 a) +{ + if (a >= 0xa00000 && a <= 0xa0001f) { + return io_chip_r((a - 0xa00000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall Astorm3WriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0xa00000 && a <= 0xa01fff) { + io_chip_w((a - 0xa00000) >> 1, d); + return; + } + + switch (a) { + case 0xa02101: { + System18VdpMixing = d & 0xff; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT8 __fastcall DdcrewuReadByte(UINT32 a) +{ + switch (a) { + case 0xe43021: { + return 0xff - System16Input[3]; + } + + case 0xe43023: { + return 0xff - System16Input[4]; + } + + case 0xe43025: { + return 0xff - System16Input[5]; + } + } + + return 0xff; +} + +UINT8 LghostValue; + +UINT8 __fastcall LghostReadByte(UINT32 a) +{ + switch (a) { + case 0xe43011: + case 0xe43013: + case 0xe43015: + case 0xe43017: { + UINT8 result = LghostValue | 0x7f; + LghostValue <<= 1; + return result; + } + } + + return 0xff; +} + +void __fastcall LghostWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xe43011: { + LghostValue = ~BurnGunReturnY(0); + return; + } + + case 0xe43013: { + LghostValue = BurnGunReturnX(0); + return; + } + + case 0xe43015: { + LghostValue = (System16AnalogSelect) ? ~BurnGunReturnY(2) : ~BurnGunReturnY(1); + return; + } + + case 0xe43017: { + LghostValue = (System16AnalogSelect) ? BurnGunReturnX(2) : BurnGunReturnX(1); + return; + } + + case 0xe43021: { + System16AnalogSelect = d & 1; + return; + } + } +} + +UINT8 __fastcall MwalkblReadByte(UINT32 a) +{ + switch (a) { + case 0xc40001: { + return System16Dip[0]; + } + + case 0xc40003: { + return System16Dip[1]; + } + + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return 0xff - System16Input[2]; + } + + case 0xc41007: { + return 0xff - System16Input[3]; + } + } + + return 0xff; +} + +void __fastcall MwalkblWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc40007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + + case 0xc46601: { + System16VideoEnable = d & 0x02; + return; + } + + case 0xc46801: { + for (int i = 0; i < 4; i++) { + if (System16TileBanks[0 + i] != ((d & 0xf) * 4 + i)) { + System16TileBanks[0 + i] = (d & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + if (System16TileBanks[4 + i] != (((d >> 4) & 0xf) * 4 + i)) { + System16TileBanks[4 + i] = ((d >> 4) & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + } + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +void __fastcall MwalkblWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc46000: { + System16ScrollY[1] = d & 0xff; + return; + } + + case 0xc46200: { + System16ScrollY[0] = d & 0xff; + return; + } + + case 0xc46400: { + BootlegBgPage[0] = (d >> 8) & 0xf; + System16ScrollX[0] = d & 0xff; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +UINT8 __fastcall ShdancblReadByte(UINT32 a) +{ + switch (a) { + case 0xc40001: { + return System16Dip[0]; + } + + case 0xc40003: { + return System16Dip[1]; + } + + case 0xc41001: { + return 0xff - System16Input[0]; + } + + case 0xc41003: { + return 0xff - System16Input[1]; + } + + case 0xc41005: { + return 0xff - System16Input[2]; + } + + case 0xc41007: { + return 0xff - System16Input[3]; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall ShdancblWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xc40007: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetRaiseIrq(0); + ZetClose(); + return; + } + + case 0xe4001d: { + //System16VideoEnable = d & 0x02; + return; + } + + case 0xe4000f: { + for (int i = 0; i < 4; i++) { + if (System16TileBanks[0 + i] != ((d & 0xf) * 4 + i)) { + System16TileBanks[0 + i] = (d & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + if (System16TileBanks[4 + i] != (((d >> 4) & 0xf) * 4 + i)) { + System16TileBanks[4 + i] = ((d >> 4) & 0xf) * 4 + i; + System16RecalcBgTileMap = 1; + System16RecalcBgAltTileMap = 1; + System16RecalcFgTileMap = 1; + System16RecalcFgAltTileMap = 1; + } + } + return; + } + + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +static INT16 WwallyTrack1X = 0; +static INT16 WwallyTrack1Y = 0; +static INT16 WwallyTrack2X = 0; +static INT16 WwallyTrack2Y = 0; + +static UINT8 WwallyLastX[2]; +static UINT8 WwallyLastY[2]; + +UINT8 __fastcall WwallyReadByte(UINT32 a) +{ + switch (a) { + case 0xa43001: { + return (WwallyTrack1X - WwallyLastX[0]) & 0xff; + } + + case 0xa43005: { + return (WwallyTrack1Y - WwallyLastY[0]) & 0xff; + } + + case 0xa43009: { + return (WwallyTrack2X - WwallyLastX[1]) & 0xff; + } + + case 0xa4300d: { + return (WwallyTrack2Y - WwallyLastY[1]) & 0xff; + } + + } + + return 0xff; +} + +void __fastcall WwallyWriteWord(UINT32 a, UINT16 /*d*/) +{ + switch (a) { + case 0xa43000: { + WwallyLastX[0] = WwallyTrack1X; + WwallyLastY[0] = WwallyTrack1Y; + return; + } + + case 0xa43008: { + WwallyLastX[1] = WwallyTrack2X; + WwallyLastY[1] = WwallyTrack2Y; + return; + } + } +} + +/*==================================================== +Driver inits +====================================================*/ + +void WwallyMakeAnalogInputs() +{ + if (System16InputPort1[1]) WwallyTrack1X += 0x4; + if (System16InputPort1[2]) WwallyTrack1X -= 0x4; + if (WwallyTrack1X >= 0x100) WwallyTrack1X = 0; + if (WwallyTrack1X < 0) WwallyTrack1X = 0xfc; + + if (System16InputPort1[3]) WwallyTrack1Y -= 0x4; + if (System16InputPort1[4]) WwallyTrack1Y += 0x4; + if (WwallyTrack1Y >= 0x100) WwallyTrack1Y = 0; + if (WwallyTrack1Y < 0) WwallyTrack1Y = 0xfc; + + if (System16InputPort2[1]) WwallyTrack2X += 0x4; + if (System16InputPort2[2]) WwallyTrack2X -= 0x4; + if (WwallyTrack2X >= 0x100) WwallyTrack2X = 0; + if (WwallyTrack2X < 0) WwallyTrack2X = 0xfc; + + if (System16InputPort2[3]) WwallyTrack2Y -= 0x4; + if (System16InputPort2[4]) WwallyTrack2Y += 0x4; + if (WwallyTrack2Y >= 0x100) WwallyTrack2Y = 0; + if (WwallyTrack2Y < 0) WwallyTrack2Y = 0xfc; +} + +static INT32 System18BankRom40000() +{ + INT32 nRet = 1; + UINT8 *pTemp = (UINT8*)malloc(0x280000); + + if (pTemp) { + memcpy(pTemp, System16Rom, 0x280000); + memset(System16Rom, 0, 0x280000); + memcpy(System16Rom + 0x000000, pTemp + 0x00000, 0x80000); + memcpy(System16Rom + 0x200000, pTemp + 0x80000, 0x80000); + free(pTemp); + pTemp = NULL; + nRet = 0; + } + + return nRet; +} + +static INT32 System18BankRom80000() +{ + INT32 nRet = 1; + UINT8 *pTemp = (UINT8*)malloc(0x300000); + + if (pTemp) { + memcpy(pTemp, System16Rom, 0x300000); + memset(System16Rom, 0, 0x300000); + memcpy(System16Rom + 0x000000, pTemp + 0x000000, 0x100000); + memcpy(System16Rom + 0x200000, pTemp + 0x100000, 0x100000); + free(pTemp); + pTemp = NULL; + nRet = 0; + } + + return nRet; +} + +static INT32 System18Bank40000Init() +{ + System16RomSize = 0x180000; + + System16CustomLoadRomDo = System18BankRom40000; + + System16SpriteRomSize = 0x800000 - 0x400000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapMemory(System16Rom + 0x200000, 0x200000, 0x27ffff, SM_READ); + SekClose(); + + UINT8 *pTemp = (UINT8*)malloc(0x400000); + if (pTemp) { + memcpy(pTemp, System16Sprites, 0x400000); + memset(System16Sprites, 0, System16SpriteRomSize); + memcpy(System16Sprites + 0x000000, pTemp + 0x000000, 0x100000); + memcpy(System16Sprites + 0x200000, pTemp + 0x100000, 0x100000); + memcpy(System16Sprites + 0x400000, pTemp + 0x200000, 0x100000); + memcpy(System16Sprites + 0x600000, pTemp + 0x300000, 0x100000); + } else { + nRet = 1; + } + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + } + + return nRet; +} + +static INT32 System18Bank80000Init() +{ + System16RomSize = 0x100000; + + System16CustomLoadRomDo = System18BankRom80000; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapMemory(System16Rom + 0x200000, 0x200000, 0x27ffff, SM_READ); + SekClose(); + } + + return nRet; +} + +void Astorm3Map68K() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0bffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0bffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(System16TextRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x200000, 0x2007ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x140000, 0x140fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, System18ReadWord); + SekSetWriteWordHandler(0, System18WriteWord); + SekSetReadByteHandler(0, System18ReadByte); + SekSetWriteByteHandler(0, System18WriteByte); + SekMapHandler(1, 0xa00000, 0xa03fff, SM_RAM); + SekSetReadByteHandler(1, Astorm3ReadByte); + SekSetWriteByteHandler(1, Astorm3WriteByte); + SekClose(); +} + +static INT32 Astorm3Init() +{ + System16Map68KDo = Astorm3Map68K; + + INT32 nRet = System16Init(); + + return nRet; +} + +static INT32 DdcrewuInit() +{ + INT32 nRet = System18Bank40000Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xe43020, 0xe43025, SM_READ); + SekSetReadByteHandler(1, DdcrewuReadByte); + SekClose(); + } + + return nRet; +} + +static INT32 LghostInit() +{ + BurnGunInit(3, true); + + INT32 nRet = System18Bank40000Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xe43010, 0xe43021, SM_RAM); + SekSetReadByteHandler(1, LghostReadByte); + SekSetWriteByteHandler(1, LghostWriteByte); + SekClose(); + } + + return nRet; +} + +static INT32 MwalkblPatchRom() +{ + *((UINT16*)(System16Rom + 0x070212)) = 0x4e71; + *((UINT16*)(System16Rom + 0x070116)) = 0x4e71; + *((UINT16*)(System16Rom + 0x00314a)) = 0x4642; + System16Rom[0x00311a] = 0x3f; + System16Rom[0x070103] = 0x00; + System16Rom[0x070109] = 0x00; + System16Rom[0x007727] = 0x00; + System16Rom[0x007729] = 0x00; + System16Rom[0x00780d] = 0x00; + System16Rom[0x00780f] = 0x00; + System16Rom[0x007861] = 0x00; + System16Rom[0x007863] = 0x00; + System16Rom[0x007d47] = 0x00; + System16Rom[0x007863] = 0x00; + System16Rom[0x008533] = 0x00; + System16Rom[0x008535] = 0x00; + System16Rom[0x0085bd] = 0x00; + System16Rom[0x0085bf] = 0x00; + System16Rom[0x009a4b] = 0x00; + System16Rom[0x009a4d] = 0x00; + System16Rom[0x009b2f] = 0x00; + System16Rom[0x009b31] = 0x00; + System16Rom[0x00a05b] = 0x00; + System16Rom[0x00a05d] = 0x00; + System16Rom[0x00a23f] = 0x00; + System16Rom[0x00a241] = 0x00; + System16Rom[0x010159] = 0x00; + System16Rom[0x01015b] = 0x00; + System16Rom[0x0109fb] = 0x00; + System16Rom[0x0109fd] = 0x00; + + return 0; +} + +static INT32 MwalkblInit() +{ + System16CustomLoadRomDo = MwalkblPatchRom; + + System16SpriteXOffset = 128; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xc40000, 0xc41009, SM_READ); + SekSetReadByteHandler(1, MwalkblReadByte); + SekMapHandler(2, 0xc40006, 0xc46801, SM_WRITE); + SekSetWriteByteHandler(2, MwalkblWriteByte); + SekSetWriteWordHandler(2, MwalkblWriteWord); + SekClose(); + } + + return nRet; +} + +static INT32 ShdancblInit() +{ + System16SpriteXOffset = 112; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekSetReadByteHandler(0, ShdancblReadByte); + SekSetWriteByteHandler(0, ShdancblWriteByte); + SekClose(); + + System16VideoEnable = 1; + } + + return nRet; +} + +static INT32 WwallyInit() +{ + System16MakeAnalogInputsDo = WwallyMakeAnalogInputs; + + INT32 nRet = System16Init(); + + if (!nRet) { + SekOpen(0); + SekMapHandler(1, 0xa43000, 0xa4300e, SM_RAM); + SekSetReadByteHandler(1, WwallyReadByte); + SekSetWriteWordHandler(1, WwallyWriteWord); + SekClose(); + } + + return nRet; +} + +static INT32 System18Exit() +{ + memset(misc_io_data, 0, sizeof(misc_io_data)); + + GenesisVDPExit(); + + return System16Exit(); +} + +static INT32 System18Scan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(misc_io_data); + + GenesisVDPScan(); + } + + return System16Scan(nAction, pnMin);; +} + +static INT32 LghostExit() +{ + LghostValue = 0; + + return System18Exit(); +} + +static INT32 LghostScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(LghostValue); + } + + return System18Scan(nAction, pnMin);; +} + +static INT32 WwallyExit() +{ + WwallyTrack1X = 0; + WwallyTrack1Y = 0; + WwallyTrack2X = 0; + WwallyTrack2Y = 0; + + memset(WwallyLastX, 0, sizeof(WwallyLastX)); + memset(WwallyLastY, 0, sizeof(WwallyLastY)); + + return System18Exit(); +} + +static INT32 WwallyScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(WwallyTrack1X); + SCAN_VAR(WwallyTrack1Y); + SCAN_VAR(WwallyTrack2X); + SCAN_VAR(WwallyTrack2Y); + SCAN_VAR(WwallyLastX); + SCAN_VAR(WwallyLastY); + } + + return System18Scan(nAction, pnMin);; +} + +/*==================================================== +Driver defs +====================================================*/ + +struct BurnDriver BurnDrvAstorm = { + "astorm", NULL, NULL, NULL, "1990", + "Alien Storm (set 4, World, 2 Players, FD1094 317-0154)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, AstormRomInfo, AstormRomName, NULL, NULL, System18InputInfo, Astorm2pDIPInfo, + Astorm3Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAstorm3 = { + "astorm3", "astorm", NULL, NULL, "1990", + "Alien Storm (set 3, World, 3 Players, FD1094 317-0148)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, Astorm3RomInfo, Astorm3RomName, NULL, NULL, AstormInputInfo, AstormDIPInfo, + Astorm3Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAstormj = { + "astormj", "astorm", NULL, NULL, "1990", + "Alien Storm (set 1, Japan, 2 Players, FD1094 317-0146)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, AstormjRomInfo, AstormjRomName, NULL, NULL, System18InputInfo, Astorm2pDIPInfo, + Astorm3Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAstormja = { + "astormja", "astorm", NULL, NULL, "1990", + "Alien Storm (set 5, Japan Rev B, 2 Players, FD1094 317-0146)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, AstormjaRomInfo, AstormjaRomName, NULL, NULL, System18InputInfo, Astorm2pDIPInfo, + Astorm3Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAstormu = { + "astormu", "astorm", NULL, NULL, "1990", + "Alien Storm (set 2, US, 3 Players, FD1094 317-0147)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, AstormuRomInfo, AstormuRomName, NULL, NULL, AstormInputInfo, AstormDIPInfo, + Astorm3Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBloxeed = { + "bloxeed", NULL, NULL, NULL, "1990", + "Bloxeed (Japan, FD1094 317-0139)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, BloxeedRomInfo, BloxeedRomName, NULL, NULL, System18InputInfo, NULL, + System16Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCltchitr = { + "cltchitr", NULL, NULL, NULL, "1991", + "Clutch Hitter (set 2, US, FD1094 317-0176)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, CltchitrRomInfo, CltchitrRomName, NULL, NULL, System18InputInfo, CltchitrDIPInfo, + System18Bank40000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCltchitrj = { + "cltchitrj", "cltchitr", NULL, NULL, "1991", + "Clutch Hitter (set 1, Japan, FD1094 317-0175)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SPORTSMISC, 0, + NULL, CltchitrjRomInfo, CltchitrjRomName, NULL, NULL, System18InputInfo, CltchitrDIPInfo, + System18Bank40000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdcrew = { + "ddcrew", NULL, NULL, NULL, "1991", + "D. D. Crew (set 4, World, 3 Player, FD1094 317-0190)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, DdcrewRomInfo, DdcrewRomName, NULL, NULL, DdcrewInputInfo, DdcrewDIPInfo, + System18Bank40000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdcrew1 = { + "ddcrew1", "ddcrew", NULL, NULL, "1991", + "D. D. Crew (set 1, World, 4 Player, FD1094 317-?)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, Ddcrew1RomInfo, Ddcrew1RomName, NULL, NULL, DdcrewuInputInfo, DdcrewuDIPInfo, + DdcrewuInit, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdcrew2 = { + "ddcrew2", "ddcrew", NULL, NULL, "1991", + "D. D. Crew (set 2, World, 2 Player, FD1094 317-0184)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, Ddcrew2RomInfo, Ddcrew2RomName, NULL, NULL, Ddcrew2InputInfo, Ddcrew2DIPInfo, + System18Bank40000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdcrewj = { + "ddcrewj", "ddcrew", NULL, NULL, "1991", + "D. D. Crew (set 5, Japan, 2 Player, FD1094 317-0182)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, DdcrewjRomInfo, DdcrewjRomName, NULL, NULL, Ddcrew2InputInfo, Ddcrew2DIPInfo, + System18Bank40000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDdcrewu = { + "ddcrewu", "ddcrew", NULL, NULL, "1991", + "D. D. Crew (set 3, US, 4 Player, FD1094 317-0186)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SCRFIGHT, 0, + NULL, DdcrewuRomInfo, DdcrewuRomName, NULL, NULL, DdcrewuInputInfo, DdcrewuDIPInfo, + DdcrewuInit, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDesertbr = { + "desertbr", NULL, NULL, NULL, "1992", + "Desert Breaker (World, FD1094 317-0196)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_VERSHOOT, 0, + NULL, DesertbrRomInfo, DesertbrRomName, NULL, NULL, DesertbrInputInfo, DesertbrDIPInfo, + System18Bank80000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDesertbrj = { + "desertbrj", "desertbr", NULL, NULL, "1992", + "Desert Breaker (Japan, FD1094 317-0194)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_VERSHOOT, 0, + NULL, DesertbrjRomInfo, DesertbrjRomName, NULL, NULL, DesertbrInputInfo, DesertbrDIPInfo, + System18Bank80000Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvLghost = { + "lghost", NULL, NULL, NULL, "1990", + "Laser Ghost (set 2, World, 317-0166)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, LghostRomInfo, LghostRomName, NULL, NULL, LghostInputInfo, LghostDIPInfo, + LghostInit, LghostExit, System18Frame, NULL, LghostScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLghostu = { + "lghostu", "lghost", NULL, NULL, "1990", + "Laser Ghost (set 1, US, 317-0165)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, LghostuRomInfo, LghostuRomName, NULL, NULL, LghostInputInfo, LghostDIPInfo, + LghostInit, LghostExit, System18Frame, NULL, LghostScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMWalk = { + "mwalk", NULL, NULL, NULL, "1990", + "Michael Jackson's Moonwalker (set 3, World, FD1094/8751 317-0159)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + 0, 3, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PLATFORM, 0, + NULL, MwalkRomInfo, MwalkRomName, NULL, NULL, MwalkInputInfo, MwalkDIPInfo, + System16Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMWalkbl = { + "mwalkbl", "mwalk", NULL, NULL, "1990", + "Michael Jackson's Moonwalker (bootleg)\0", NULL, "bootleg", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 3, HARDWARE_SEGA_SYSTEM18, GBF_PLATFORM, 0, + NULL, MwalkblRomInfo, MwalkblRomName, NULL, NULL, MwalkInputInfo, MwalkDIPInfo, + MwalkblInit, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShdancer = { + "shdancer", NULL, NULL, NULL, "1989", + "Shadow Dancer (set 3, US)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM18, GBF_PLATFORM, 0, + NULL, ShdancerRomInfo, ShdancerRomName, NULL, NULL, System18InputInfo, ShdancerDIPInfo, + System16Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShdancer1 = { + "shdancer1", "shdancer", NULL, NULL, "1989", + "Shadow Dancer (set 1)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18, GBF_PLATFORM, 0, + NULL, Shdancer1RomInfo, Shdancer1RomName, NULL, NULL, System18InputInfo, ShdancerDIPInfo, + System16Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvShdancerj = { + "shdancerj", "shdancer", NULL, NULL, "1989", + "Shadow Dancer (set 2, Japan)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18, GBF_PLATFORM, 0, + NULL, ShdancerjRomInfo, ShdancerjRomName, NULL, NULL, System18InputInfo, ShdancerDIPInfo, + System16Init, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvShdancbl = { + "shdancbl", "shdancer", NULL, NULL, "1989", + "Shadow Dancer (bootleg)\0", NULL, "bootleg", "System 18", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_INVERT_TILES, GBF_PLATFORM, 0, + NULL, ShdancblRomInfo, ShdancblRomName, NULL, NULL, System18InputInfo, ShdancerDIPInfo, + ShdancblInit, System18Exit, System18Frame, NULL, System18Scan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWwallyj = { + "wwallyj", NULL, NULL, NULL, "1992", + "Wally wo Sagase! (rev B, Japan, FD1094 317-0197B)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, WwallyjRomInfo, WwallyjRomName, NULL, NULL, WwallyInputInfo, WwallyDIPInfo, + WwallyInit, WwallyExit, System18Frame, NULL, WwallyScan, + NULL, 0x1800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvWwallyja = { + "wwallyja", "wwallyj", NULL, NULL, "1992", + "Wally wo Sagase! (rev A, Japan, FD1094 317-0197A)\0", NULL, "Sega", "System 18", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEM18 | HARDWARE_SEGA_FD1094_ENC, GBF_PUZZLE, 0, + NULL, WwallyjaRomInfo, WwallyjaRomName, NULL, NULL, WwallyInputInfo, WwallyDIPInfo, + WwallyInit, WwallyExit, System18Frame, NULL, WwallyScan, + NULL, 0x1800, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_xbrd.cpp b/src/burn/drivers/sega/d_xbrd.cpp new file mode 100644 index 00000000..a77b62ad --- /dev/null +++ b/src/burn/drivers/sega/d_xbrd.cpp @@ -0,0 +1,2530 @@ +#include "sys16.h" + +/*==================================================== +Input defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo AbcopInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + {"Jump" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Abcop) + +static struct BurnInputInfo Aburner2InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Throttle" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 z-axis" ), + {"Vulcan" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"Missile" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Aburner2) + +static struct BurnInputInfo GpriderInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Shift Down" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 3" }, + {"Shift Up" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Gprider) + +static struct BurnInputInfo LoffireInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("P1 X-Axis" , BIT_ANALOG_REL, &System16AnalogPort0, "mouse x-axis" ), + A("P1 Y-Axis" , BIT_ANALOG_REL, &System16AnalogPort1, "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort1 + 7, "mouse button 1" }, + {"P1 Fire 2" , BIT_DIGITAL , System16InputPort1 + 6, "mouse button 2" }, + + A("P2 X-Axis" , BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("P2 Y-Axis" , BIT_ANALOG_REL, &System16AnalogPort3, "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort1 + 5, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , System16InputPort1 + 4, "p2 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Service 2" , BIT_DIGITAL , System16InputPort0 + 3 , "service2" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Loffire) + +static struct BurnInputInfo RacheroInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Move to centre" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 3" }, + {"Suicide" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Rachero) + +static struct BurnInputInfo SmgpInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Shift Down" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 3" }, + {"Shift Up" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 4" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Smgp) + +static struct BurnInputInfo ThndrbldInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Throttle" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 z-axis" ), + {"Cannon" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"Missile" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Thndrbld) + +#undef A + +/*==================================================== +Dip Defs +====================================================*/ + +#define BOARDX_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo AbcopDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xff, 0xf9, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x09) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Credits" }, + {0x0a, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x0a, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x04, 0x04, "No" }, + {0x0a, 0x01, 0x04, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x0a, 0x01, 0x30, 0x10, "Easy" }, + {0x0a, 0x01, 0x30, 0x30, "Normal" }, + {0x0a, 0x01, 0x30, 0x20, "Hard" }, + {0x0a, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0xc0, 0x40, "Easy" }, + {0x0a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0a, 0x01, 0xc0, 0x80, "Hard" }, + {0x0a, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Abcop) + +static struct BurnDIPInfo Aburner2DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xcd, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x0c, 0x01, 0x03, 0x03, "Moving Deluxe" }, + {0x0c, 0x01, 0x03, 0x02, "Moving Standard" }, + {0x0c, 0x01, 0x03, 0x01, "Upright 1" }, + {0x0c, 0x01, 0x03, 0x00, "Upright 2" }, + + {0 , 0xfe, 0 , 2 , "Throttle Lever" }, + {0x0c, 0x01, 0x04, 0x00, "No" }, + {0x0c, 0x01, 0x04, 0x04, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0c, 0x01, 0x08, 0x08, "3" }, + {0x0c, 0x01, 0x08, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Ship Increase" }, + {0x0c, 0x01, 0x10, 0x10, "No" }, + {0x0c, 0x01, 0x10, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x20, "No" }, + {0x0c, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Aburner2) + +static struct BurnDIPInfo AburnerDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xc1, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x0c, 0x01, 0x03, 0x03, "Moving Deluxe" }, + {0x0c, 0x01, 0x03, 0x02, "Moving Standard" }, + {0x0c, 0x01, 0x03, 0x01, "Upright 1" }, + {0x0c, 0x01, 0x03, 0x00, "Upright 2" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x0c, 0x01, 0x10, 0x10, "3" }, + {0x0c, 0x01, 0x10, 0x00, "3 x credits" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x20, "No" }, + {0x0c, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Aburner) + +static struct BurnDIPInfo GpriderDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xfe, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet Type" }, + {0x0c, 0x01, 0x03, 0x03, "Ride On" }, + {0x0c, 0x01, 0x03, 0x02, "Upright" }, + + {0 , 0xfe, 0 , 2 , "ID Number" }, + {0x0c, 0x01, 0x08, 0x08, "Main" }, + {0x0c, 0x01, 0x08, 0x00, "Slave" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x10, 0x00, "Off" }, + {0x0c, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x80, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x40, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Gprider) + +static struct BurnDIPInfo LoffireDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0x9c, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0e) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0f, 0x01, 0x01, 0x01, "Japanese" }, + {0x0f, 0x01, 0x01, 0x00, "English" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x02, 0x02, "Cockpit" }, + {0x0f, 0x01, 0x02, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "2 Credits to start" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0x18, 0x10, "Easy" }, + {0x0f, 0x01, 0x18, 0x18, "Normal" }, + {0x0f, 0x01, 0x18, 0x08, "Hard" }, + {0x0f, 0x01, 0x18, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0f, 0x01, 0x20, 0x20, "No" }, + {0x0f, 0x01, 0x20, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x40, 0x40, "Off" }, + {0x0f, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x0f, 0x01, 0x80, 0x80, "Single" }, + {0x0f, 0x01, 0x80, 0x00, "Twin" }, +}; + +STDDIPINFO(Loffire) + +static struct BurnDIPInfo RacheroDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xf9, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Credits" }, + {0x0c, 0x01, 0x01, 0x01, "1 to start, 1 to continue" }, + {0x0c, 0x01, 0x01, 0x00, "2 to start, 1 to continue" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x02, "Off" }, + {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x04, 0x04, "No" }, + {0x0c, 0x01, 0x04, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x0c, 0x01, 0x30, 0x10, "Easy" }, + {0x0c, 0x01, 0x30, 0x30, "Normal" }, + {0x0c, 0x01, 0x30, 0x20, "Hard" }, + {0x0c, 0x01, 0x30, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x40, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x80, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Very Hard" }, +}; + +STDDIPINFO(Rachero) + +static struct BurnDIPInfo SmgpDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 8 , "Machine ID" }, + {0x0c, 0x01, 0x07, 0x07, "1" }, + {0x0c, 0x01, 0x07, 0x06, "2" }, + {0x0c, 0x01, 0x07, 0x05, "3" }, + {0x0c, 0x01, 0x07, 0x04, "4" }, + {0x0c, 0x01, 0x07, 0x03, "5" }, + {0x0c, 0x01, 0x07, 0x02, "6" }, + {0x0c, 0x01, 0x07, 0x01, "7" }, + {0x0c, 0x01, 0x07, 0x00, "8" }, + + {0 , 0xfe, 0 , 8 , "Number of Machines" }, + {0x0c, 0x01, 0x38, 0x38, "1" }, + {0x0c, 0x01, 0x38, 0x30, "2" }, + {0x0c, 0x01, 0x38, 0x28, "3" }, + {0x0c, 0x01, 0x38, 0x20, "4" }, + {0x0c, 0x01, 0x38, 0x18, "5" }, + {0x0c, 0x01, 0x38, 0x10, "6" }, + {0x0c, 0x01, 0x38, 0x08, "7" }, + {0x0c, 0x01, 0x38, 0x00, "8" }, + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0c, 0x01, 0xc0, 0xc0, "Deluxe" }, + {0x0c, 0x01, 0xc0, 0x80, "Cockpit" }, + {0x0c, 0x01, 0xc0, 0x40, "Upright" }, +}; + +STDDIPINFO(Smgp) + +static struct BurnDIPInfo ThndrbldDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet Type" }, + {0x0c, 0x01, 0x01, 0x01, "Econ Upright" }, + {0x0c, 0x01, 0x01, 0x00, "Mini Upright" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x02, "Off" }, + {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x0c, 0x01, 0x04, 0x04, "30 sec" }, + {0x0c, 0x01, 0x04, 0x00, "0 sec" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x18, 0x08, "2" }, + {0x0c, 0x01, 0x18, 0x18, "3" }, + {0x0c, 0x01, 0x18, 0x10, "4" }, + {0x0c, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x00, "No" }, + {0x0c, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x40, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x80, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Thndrbld) + +static struct BurnDIPInfo Thndrbld1DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xfd, NULL }, + + // Dip 1 + BOARDX_COINAGE(0x0b) + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Cabinet Type" }, + {0x0c, 0x01, 0x01, 0x01, "Deluxe" }, + {0x0c, 0x01, 0x01, 0x00, "Standing" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x02, 0x02, "Off" }, + {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Time" }, + {0x0c, 0x01, 0x04, 0x04, "30 sec" }, + {0x0c, 0x01, 0x04, 0x00, "0 sec" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0c, 0x01, 0x18, 0x08, "2" }, + {0x0c, 0x01, 0x18, 0x18, "3" }, + {0x0c, 0x01, 0x18, 0x10, "4" }, + {0x0c, 0x01, 0x18, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x00, "No" }, + {0x0c, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0xc0, 0x40, "Easy" }, + {0x0c, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0c, 0x01, 0xc0, 0x80, "Hard" }, + {0x0c, 0x01, 0xc0, 0x00, "Hardest" }, +}; + +STDDIPINFO(Thndrbld1) + +#undef BOARDX_COINAGE + +/*==================================================== +Rom Defs +====================================================*/ + +static struct BurnRomInfo AbcopRomDesc[] = { + { "epr-13568b.ic58", 0x20000, 0xf88db35b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13556b.ic63", 0x20000, 0x337bf32e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13559.ic57", 0x20000, 0x4588bf19, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13558.ic62", 0x20000, 0x11259ed4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13566.ic20", 0x20000, 0x22e52f32, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13565.ic29", 0x20000, 0xa21784bd, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-13553.ic154", 0x10000, 0x8c418837, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13554.ic153", 0x10000, 0x4e3df9f0, SYS16_ROM_TILES | BRF_GRA }, + { "opr-13555.ic152", 0x10000, 0x6c4a1d42, SYS16_ROM_TILES | BRF_GRA }, + + { "opr-13552.ic90", 0x20000, 0xcc2cf706, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13551.ic94", 0x20000, 0xd6f276c1, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13550.ic98", 0x20000, 0xf16518dd, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13549.ic102", 0x20000, 0xcba407a7, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13548.ic91", 0x20000, 0x080fd805, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13547.ic95", 0x20000, 0x42d4dd68, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13546.ic99", 0x20000, 0xca6fbf3d, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13545.ic103", 0x20000, 0xc9e58dd2, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13544.ic92", 0x20000, 0x9c1436d9, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13543.ic96", 0x20000, 0x2c1c8f0e, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13542.ic100", 0x20000, 0x01fd52b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13541.ic104", 0x20000, 0xa45c547b, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13540.ic93", 0x20000, 0x84b42ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13539.ic97", 0x20000, 0xcd6e524f, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13538.ic101", 0x20000, 0xbf9a4586, SYS16_ROM_SPRITES | BRF_GRA }, + { "opr-13537.ic105", 0x20000, 0xfa14ed3e, SYS16_ROM_SPRITES | BRF_GRA }, + + { "opr-13564.ic40", 0x10000, 0xe70ba138, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-13560.ic17", 0x10000, 0x83050925, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "opr-13563.ic11", 0x20000, 0x4083e74f, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-13562.ic12", 0x20000, 0x3cc3968f, SYS16_ROM_PCMDATA | BRF_SND }, + { "opr-13561.ic13", 0x20000, 0x80a7c02a, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0169b.key", 0x02000, 0x058da36e, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Abcop) +STD_ROM_FN(Abcop) + +static struct BurnRomInfo Aburner2RomDesc[] = { + { "epr-11107.58", 0x20000, 0x6d87bab7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11108.63", 0x20000, 0x202a3e1d, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11109.20", 0x20000, 0x85a0fe07, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11110.29", 0x20000, 0xf3d6797c, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11115.154", 0x10000, 0xe8e32921, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11114.153", 0x10000, 0x2e97f633, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11113.152", 0x10000, 0x36058c8c, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-10932.90", 0x20000, 0xcc0821d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10934.94", 0x20000, 0x4a51b1fa, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10936.98", 0x20000, 0xada70d64, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10938.102", 0x20000, 0xe7675baf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10933.91", 0x20000, 0xc8efb2c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10935.95", 0x20000, 0xc1e23521, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10937.99", 0x20000, 0xf0199658, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10939.103", 0x20000, 0xa0d49480, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11103.92", 0x20000, 0xbdd60da2, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11104.96", 0x20000, 0x06a35fce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11105.100", 0x20000, 0x027b0689, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11106.104", 0x20000, 0x9e1fec09, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11116.93", 0x20000, 0x49b4c1ba, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11117.97", 0x20000, 0x821fbb71, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11118.101", 0x20000, 0x8f38540b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11119.105", 0x20000, 0xd0343a8e, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10922.40", 0x10000, 0xb49183d4, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-11112.17", 0x10000, 0xd777fc6d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-10931.11", 0x20000, 0x9209068f, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-10930.12", 0x20000, 0x6493368b, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11102.13", 0x20000, 0x6c07c78d, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Aburner2) +STD_ROM_FN(Aburner2) + +static struct BurnRomInfo AburnerRomDesc[] = { + { "epr-10940.58", 0x20000, 0x4d132c4e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-10941.63", 0x20000, 0x136ea264, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-10927.20", 0x20000, 0x66d36757, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-10928.29", 0x20000, 0x7c01d40b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-10926.154", 0x10000, 0xed8bd632, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10925.153", 0x10000, 0x4ef048cc, SYS16_ROM_TILES | BRF_GRA }, + { "epr-10924.152", 0x10000, 0x50c15a6d, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-10932.90", 0x20000, 0xcc0821d6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10934.94", 0x20000, 0x4a51b1fa, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10936.98", 0x20000, 0xada70d64, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10938.102", 0x20000, 0xe7675baf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10933.91", 0x20000, 0xc8efb2c3, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10935.95", 0x20000, 0xc1e23521, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10937.99", 0x20000, 0xf0199658, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-10939.103", 0x20000, 0xa0d49480, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10942.92", 0x20000, 0x5ce10b8c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10943.96", 0x20000, 0xb98294dc, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10944.100", 0x20000, 0x17be8f67, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10945.104", 0x20000, 0xdf4d4c4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10946.93", 0x20000, 0xd7d485f4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10947.97", 0x20000, 0x08838392, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10948.101", 0x20000, 0x64284761, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-10949.105", 0x20000, 0xd8437d92, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-10922.40", 0x10000, 0xb49183d4, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-10923.17", 0x10000, 0x6888eb8f, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-10931.11", 0x20000, 0x9209068f, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-10930.12", 0x20000, 0x6493368b, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11102.13", 0x20000, 0x6c07c78d, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Aburner) +STD_ROM_FN(Aburner) + +static struct BurnRomInfo GpriderRomDesc[] = { + { "epr-13409.ic58", 0x20000, 0x9abb81b6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13408.ic63", 0x20000, 0x8e410e97, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13395.ic20", 0x20000, 0xd6ccfac7, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13394.ic29", 0x20000, 0x914a55ec, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13393.ic21", 0x20000, 0x08d023cc, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13392.ic30", 0x20000, 0xf927cd42, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13383.ic154", 0x10000, 0x24f897a7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13384.ic153", 0x10000, 0xfe8238bd, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13385.ic152", 0x10000, 0x6df1b995, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-13382.ic90", 0x20000, 0x01dac209, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13381.ic94", 0x20000, 0x3a50d931, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13380.ic98", 0x20000, 0xad1024c8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13379.ic102", 0x20000, 0x1ac17625, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13378.ic91", 0x20000, 0x50c9b867, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13377.ic95", 0x20000, 0x9b12f5c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13376.ic99", 0x20000, 0x449ac518, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13375.ic103", 0x20000, 0x5489a9ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13374.ic92", 0x20000, 0x6a319e4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13373.ic96", 0x20000, 0xeca5588b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13372.ic100", 0x20000, 0x0b45a433, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13371.ic104", 0x20000, 0xb68f4cff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13370.ic93", 0x20000, 0x78276620, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13369.ic97", 0x20000, 0x8625bf0f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13368.ic101", 0x20000, 0x0f50716c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13367.ic105", 0x20000, 0x4b1bb51f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13388.ic17", 0x10000, 0x706581e4, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13391.ic11", 0x20000, 0x8c30c867, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13390.ic12", 0x20000, 0x8c93cd05, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13389.ic13", 0x20000, 0x4e4c758e, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0163.key", 0x02000, 0xc1d4d207, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Gprider) +STD_ROM_FN(Gprider) + +static struct BurnRomInfo Gprider1RomDesc[] = { + { "epr-13407.ic58", 0x20000, 0x03553ebd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13406.ic63", 0x20000, 0x122c711f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13395.ic20", 0x20000, 0xd6ccfac7, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13394.ic29", 0x20000, 0x914a55ec, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13393.ic21", 0x20000, 0x08d023cc, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13392.ic30", 0x20000, 0xf927cd42, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13383.ic154", 0x10000, 0x24f897a7, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13384.ic153", 0x10000, 0xfe8238bd, SYS16_ROM_TILES | BRF_GRA }, + { "epr-13385.ic152", 0x10000, 0x6df1b995, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-13382.ic90", 0x20000, 0x01dac209, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13381.ic94", 0x20000, 0x3a50d931, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13380.ic98", 0x20000, 0xad1024c8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13379.ic102", 0x20000, 0x1ac17625, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13378.ic91", 0x20000, 0x50c9b867, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13377.ic95", 0x20000, 0x9b12f5c0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13376.ic99", 0x20000, 0x449ac518, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13375.ic103", 0x20000, 0x5489a9ff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13374.ic92", 0x20000, 0x6a319e4f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13373.ic96", 0x20000, 0xeca5588b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13372.ic100", 0x20000, 0x0b45a433, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13371.ic104", 0x20000, 0xb68f4cff, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13370.ic93", 0x20000, 0x78276620, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13369.ic97", 0x20000, 0x8625bf0f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13368.ic101", 0x20000, 0x0f50716c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13367.ic105", 0x20000, 0x4b1bb51f, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13388.ic17", 0x10000, 0x706581e4, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13391.ic11", 0x20000, 0x8c30c867, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13390.ic12", 0x20000, 0x8c93cd05, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13389.ic13", 0x20000, 0x4e4c758e, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0162.key", 0x02000, 0x8067de53, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Gprider1) +STD_ROM_FN(Gprider1) + +static struct BurnRomInfo LoffireRomDesc[] = { + { "epr-12849.58", 0x20000, 0x61cfd2fe, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12850.63", 0x20000, 0x14598f2a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12804.20", 0x20000, 0xb853480e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12805.29", 0x20000, 0x4a7200c3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12802.21", 0x20000, 0xd746bb39, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12803.30", 0x20000, 0xc1d9e751, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12791.154", 0x10000, 0xacfa69ba, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12792.153", 0x10000, 0xe506723c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12793.152", 0x10000, 0x0ce8cce3, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12787.90", 0x20000, 0x6431a3a6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12788.94", 0x20000, 0x1982a0ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12789.98", 0x20000, 0x97d03274, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12790.102", 0x20000, 0x816e76e6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12783.91", 0x20000, 0xc13feea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12784.95", 0x20000, 0x39b94c65, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12785.99", 0x20000, 0x05ed0059, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12786.103", 0x20000, 0xa4123165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12779.92", 0x20000, 0xae58af7c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12780.96", 0x20000, 0xee670c1e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12781.100", 0x20000, 0x538f6bc5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12782.104", 0x20000, 0x5acc34f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12775.93", 0x20000, 0x693056ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12776.97", 0x20000, 0x61efbdfd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12777.101", 0x20000, 0x29d5b953, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12778.105", 0x20000, 0x2fb68e07, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12798.17", 0x10000, 0x0587738d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12799.11", 0x20000, 0xbc60181c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12800.12", 0x20000, 0x1158c1a3, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12801.13", 0x20000, 0x2d6567c4, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0136.key", 0x02000, 0x344bfe0c, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Loffire) +STD_ROM_FN(Loffire) + +static struct BurnRomInfo LoffirejRomDesc[] = { + { "epr-12794.58", 0x20000, 0x1e588992, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12795.63", 0x20000, 0xd43d7427, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12804.20", 0x20000, 0xb853480e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12805.29", 0x20000, 0x4a7200c3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12802.21", 0x20000, 0xd746bb39, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12803.30", 0x20000, 0xc1d9e751, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12791.154", 0x10000, 0xacfa69ba, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12792.153", 0x10000, 0xe506723c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12793.152", 0x10000, 0x0ce8cce3, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12787.90", 0x20000, 0x6431a3a6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12788.94", 0x20000, 0x1982a0ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12789.98", 0x20000, 0x97d03274, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12790.102", 0x20000, 0x816e76e6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12783.91", 0x20000, 0xc13feea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12784.95", 0x20000, 0x39b94c65, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12785.99", 0x20000, 0x05ed0059, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12786.103", 0x20000, 0xa4123165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12779.92", 0x20000, 0xae58af7c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12780.96", 0x20000, 0xee670c1e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12781.100", 0x20000, 0x538f6bc5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12782.104", 0x20000, 0x5acc34f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12775.93", 0x20000, 0x693056ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12776.97", 0x20000, 0x61efbdfd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12777.101", 0x20000, 0x29d5b953, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12778.105", 0x20000, 0x2fb68e07, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12798.17", 0x10000, 0x0587738d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12799.11", 0x20000, 0xbc60181c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12800.12", 0x20000, 0x1158c1a3, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12801.13", 0x20000, 0x2d6567c4, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0134.key", 0x02000, 0x732626d4, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Loffirej) +STD_ROM_FN(Loffirej) + +static struct BurnRomInfo LoffireuRomDesc[] = { + { "epr-12847a.58", 0x20000, 0xc50eb4ed, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12848a.63", 0x20000, 0xf8ff8640, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12804.20", 0x20000, 0xb853480e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12805.29", 0x20000, 0x4a7200c3, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12802.21", 0x20000, 0xd746bb39, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12803.30", 0x20000, 0xc1d9e751, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "opr-12791.154", 0x10000, 0xacfa69ba, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12792.153", 0x10000, 0xe506723c, SYS16_ROM_TILES | BRF_GRA }, + { "opr-12793.152", 0x10000, 0x0ce8cce3, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12787.90", 0x20000, 0x6431a3a6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12788.94", 0x20000, 0x1982a0ce, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12789.98", 0x20000, 0x97d03274, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12790.102", 0x20000, 0x816e76e6, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12783.91", 0x20000, 0xc13feea9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12784.95", 0x20000, 0x39b94c65, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12785.99", 0x20000, 0x05ed0059, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12786.103", 0x20000, 0xa4123165, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12779.92", 0x20000, 0xae58af7c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12780.96", 0x20000, 0xee670c1e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12781.100", 0x20000, 0x538f6bc5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12782.104", 0x20000, 0x5acc34f7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12775.93", 0x20000, 0x693056ec, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12776.97", 0x20000, 0x61efbdfd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12777.101", 0x20000, 0x29d5b953, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12778.105", 0x20000, 0x2fb68e07, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12798.17", 0x10000, 0x0587738d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12799.11", 0x20000, 0xbc60181c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12800.12", 0x20000, 0x1158c1a3, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12801.13", 0x20000, 0x2d6567c4, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0135.key", 0x02000, 0xc53ad019, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Loffireu) +STD_ROM_FN(Loffireu) + +static struct BurnRomInfo Rascot2RomDesc[] = { + { "ep13965a", 0x20000, 0x7eacdfb3, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "ep13694a", 0x20000, 0x15b86498, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr13967", 0x20000, 0x3b92e2b8, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr13966", 0x20000, 0xeaa644e1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr13961" , 0x10000, 0x68038629, SYS16_ROM_TILES | BRF_GRA }, + { "epr13962", 0x10000, 0x7d7605bc, SYS16_ROM_TILES | BRF_GRA }, + { "epr13963", 0x10000, 0xf3376b65, SYS16_ROM_TILES | BRF_GRA }, + + { "epr13957", 0x20000, 0x6d50fb54, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr13958", 0x20000, 0x7803a027, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr13959", 0x20000, 0xdb245b22, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr13960", 0x20000, 0xb974128d, SYS16_ROM_SPRITES | BRF_GRA }, + + { "ep13221a", 0x10000, 0x0d429ac4, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Rascot2) +STD_ROM_FN(Rascot2) + +static struct BurnRomInfo RacheroRomDesc[] = { + { "epr-13129.ic58", 0x20000, 0xad9f32e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13130.ic63", 0x20000, 0x6022777b, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12855.ic57", 0x20000, 0xcecf1e73, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12856.ic62", 0x20000, 0xda900ebb, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12857.ic20", 0x20000, 0x8a2328cc, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12858.ic29", 0x20000, 0x38a248b7, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12879.ic154", 0x10000, 0xc1a9de7a, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12880.ic153", 0x10000, 0x27ff04a5, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12881.ic152", 0x10000, 0x72f14491, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-12872.ic90", 0x20000, 0x68d56139, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12873.ic94", 0x20000, 0x3d3ec450, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12874.ic98", 0x20000, 0x7d6bde23, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12875.ic102", 0x20000, 0xe33092bf, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12868.ic91", 0x20000, 0x96289583, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12869.ic95", 0x20000, 0x2ef0de02, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12870.ic99", 0x20000, 0xc76630e1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12871.ic103", 0x20000, 0x23401b1a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12864.ic92", 0x20000, 0x77d6cff4, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12865.ic96", 0x20000, 0x1e7e685b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12866.ic100", 0x20000, 0xfdf31329, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12867.ic104", 0x20000, 0xb25e37fd, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12860.ic93", 0x20000, 0x86b64119, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12861.ic97", 0x20000, 0xbccff19b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12862.ic101", 0x20000, 0x7d4c3b05, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12863.ic105", 0x20000, 0x85095053, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12859.ic17", 0x10000, 0xd57881da, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12876.ic11", 0x20000, 0xf72a34a0, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12877.ic12", 0x20000, 0x18c1b6d2, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-12878.ic13", 0x20000, 0x7c212c15, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0144.key", 0x02000, 0x8740bbff, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Rachero) +STD_ROM_FN(Rachero) + +static struct BurnRomInfo SmgpRomDesc[] = { + { "epr-12563b.58", 0x20000, 0xbaf1f333, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12564b.63", 0x20000, 0xb5191af0, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12576a.20", 0x20000, 0x2c9599c1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12577a.29", 0x20000, 0xabf9a50b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0126a.key", 0x02000, 0x2abc1982, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgp) +STD_ROM_FN(Smgp) + +static struct BurnRomInfo Smgp5RomDesc[] = { + { "epr-12563.58", 0x20000, 0x6d7325ae, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12564.63", 0x20000, 0xadfbf921, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12576.20", 0x20000, 0x23266b26, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12577.29", 0x20000, 0xd5b53211, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12413.93", 0x20000, 0x2f1693df, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12414.97", 0x20000, 0xc78f3d45, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12415.101", 0x20000, 0x6080e9ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12416.105", 0x20000, 0x6f1f2769, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12535.8", 0x10000, 0x80453597, SYS16_ROM_Z80PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-12505.8", 0x08000, 0x5020788a, SYS16_ROM_Z80PROG4 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + + { "mpr-12437.20", 0x20000, 0xa1c7e712, SYS16_ROM_PCM2DATA | BRF_SND }, + { "mpr-12438.21", 0x20000, 0x6573d46b, SYS16_ROM_PCM2DATA | BRF_SND }, + { "mpr-12439.22", 0x20000, 0x13bf6de5, SYS16_ROM_PCM2DATA | BRF_SND }, + + { "317-0126.key", 0x02000, 0x4d917996, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgp5) +STD_ROM_FN(Smgp5) + +static struct BurnRomInfo Smgp6RomDesc[] = { + { "epr-12563a.58", 0x20000, 0x2e64b10e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12564a.63", 0x20000, 0x5baba3e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12576a.20", 0x20000, 0x2c9599c1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12577a.29", 0x20000, 0xabf9a50b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0126a.key", 0x02000, 0x2abc1982, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + +STD_ROM_PICK(Smgp6) +STD_ROM_FN(Smgp6) + +static struct BurnRomInfo SmgpjRomDesc[] = { + { "epr-12432b.58", 0x20000, 0xc1a29db1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12433b.63", 0x20000, 0x97199eb1, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12441a.20", 0x20000, 0x2c9599c1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12442a.29", 0x20000, 0x77a5ec16, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12413.93", 0x20000, 0x2f1693df, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12414.97", 0x20000, 0xc78f3d45, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12415.101", 0x20000, 0x6080e9ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12416.105", 0x20000, 0x6f1f2769, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0124a.key", 0x02000, 0x022a8a16, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpj) +STD_ROM_FN(Smgpj) + +static struct BurnRomInfo SmgpjaRomDesc[] = { + { "epr-12432a.58", 0x20000, 0x22517672, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12433a.63", 0x20000, 0xa46b5d13, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12441a.20", 0x20000, 0x2c9599c1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12442a.29", 0x20000, 0x77a5ec16, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12413.93", 0x20000, 0x2f1693df, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12414.97", 0x20000, 0xc78f3d45, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12415.101", 0x20000, 0x6080e9ed, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12416.105", 0x20000, 0x6f1f2769, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0124a.key", 0x02000, 0x022a8a16, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpja) +STD_ROM_FN(Smgpja) + +static struct BurnRomInfo SmgpuRomDesc[] = { + { "epr-12561c.58", 0x20000, 0xa5b0f3fe, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12562c.63", 0x20000, 0x799e55f4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12574a.20", 0x20000, 0xf8b5c38b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12575a.29", 0x20000, 0x248b1d17, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0125a.key", 0x02000, 0x3ecdb120, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpu) +STD_ROM_FN(Smgpu) + +static struct BurnRomInfo Smgpu1RomDesc[] = { + { "epr-12561b.58", 0x20000, 0x80a32655, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12562b.63", 0x20000, 0xd525f2a8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12574a.20", 0x20000, 0xf8b5c38b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12575a.29", 0x20000, 0x248b1d17, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0125a.key", 0x02000, 0x3ecdb120, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpu1) +STD_ROM_FN(Smgpu1) + +static struct BurnRomInfo Smgpu2RomDesc[] = { + { "epr-12561a.58", 0x20000, 0xe505eb89, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12562a.63", 0x20000, 0xc3af4215, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12574a.20", 0x20000, 0xf8b5c38b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12575a.29", 0x20000, 0x248b1d17, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0125a.key", 0x02000, 0x3ecdb120, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpu2) +STD_ROM_FN(Smgpu2) + +static struct BurnRomInfo Smgpu3RomDesc[] = { + { "epr-12561.58", 0x20000, 0x80a32655, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12562.63", 0x20000, 0xd525f2a8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-12574a.20", 0x20000, 0xf8b5c38b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-12575a.29", 0x20000, 0x248b1d17, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12429.154", 0x10000, 0x5851e614, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12430.153", 0x10000, 0x05e00134, SYS16_ROM_TILES | BRF_GRA }, + { "epr-12431.152", 0x10000, 0x35572f4a, SYS16_ROM_TILES | BRF_GRA }, + + { "mpr-12425.90", 0x20000, 0x14bf2a15, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12426.94", 0x20000, 0x28b60dc0, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12427.98", 0x20000, 0x0a367928, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12428.102", 0x20000, 0xefa80ad5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12421.91", 0x20000, 0x25f46140, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12422.95", 0x20000, 0xcb51c8f6, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12423.99", 0x20000, 0x0be9818e, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12424.103", 0x20000, 0x0ce00dfc, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12417.92", 0x20000, 0xa806eabf, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12418.96", 0x20000, 0xed1a0f2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12419.100", 0x20000, 0xce4568cb, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-12420.104", 0x20000, 0x679442eb, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12609.93", 0x20000, 0xa867812f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12610.97", 0x20000, 0x53b99417, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12611.101", 0x20000, 0xbd5c6ab0, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-12612.105", 0x20000, 0xac86e890, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-12436.17", 0x10000, 0x16ec5f0a, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-12587.14", 0x08000, 0x2afe648b, SYS16_ROM_Z80PROG2 | BRF_ESS | BRF_PRG }, + + { "mpr-12437.11", 0x20000, 0xa1c7e712, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12438.12", 0x20000, 0x6573d46b, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-12439.13", 0x20000, 0x13bf6de5, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0125a.key", 0x02000, 0x3ecdb120, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Smgpu3) +STD_ROM_FN(Smgpu3) + +static struct BurnRomInfo ThndrbldRomDesc[] = { + { "epr-11405.ic58", 0x20000, 0xe057dd5a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11406.ic63", 0x20000, 0xc6b994b8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11306.ic57", 0x20000, 0x4b95f2b4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11307.ic62", 0x20000, 0x2d6833e4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11390.ic20", 0x20000, 0xed988fdb, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11391.ic29", 0x20000, 0x12523bc1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11310.ic21", 0x20000, 0x5d9fa02c, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11311.ic30", 0x20000, 0x483de21b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11314.ic154", 0x10000, 0xd4f954a9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11315.ic153", 0x10000, 0x35813088, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11316.ic152", 0x10000, 0x84290dff, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11323.ic90", 0x20000, 0x27e40735, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11322.ic94", 0x20000, 0x10364d74, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11321.ic98", 0x20000, 0x8e738f58, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11320.ic102", 0x20000, 0xa95c76b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11327.ic91", 0x20000, 0xdeae90f1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11326.ic95", 0x20000, 0x29198403, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11325.ic99", 0x20000, 0xb9e98ae9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11324.ic103", 0x20000, 0x9742b552, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11331.ic92", 0x20000, 0x3a2c042e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11330.ic96", 0x20000, 0xaa7c70c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11329.ic100", 0x20000, 0x31b20257, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11328.ic104", 0x20000, 0xda39e89c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11395.ic93", 0x20000, 0x90775579, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11394.ic97", 0x20000, 0x5f2783be, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11393.ic101", 0x20000, 0x525e2e1d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11392.ic105", 0x20000, 0xb4a382f7, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11313.ic29", 0x10000, 0x6a56c4c3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-11396.ic17", 0x10000, 0xd37b54a4, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11317.ic11", 0x20000, 0xd4e7ac1f, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11318.ic12", 0x20000, 0x70d3f02c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11319.ic13", 0x20000, 0x50d9242e, SYS16_ROM_PCMDATA | BRF_SND }, + + { "317-0056.key", 0x02000, 0xb40cd2c5, SYS16_ROM_KEY | BRF_ESS | BRF_PRG }, +}; + + +STD_ROM_PICK(Thndrbld) +STD_ROM_FN(Thndrbld) + +static struct BurnRomInfo Thndrbld1RomDesc[] = { + { "epr-11304.ic58", 0x20000, 0xa90630ef, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11305.ic63", 0x20000, 0x9ba3ef61, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11306.ic57", 0x20000, 0x4b95f2b4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11307.ic62", 0x20000, 0x2d6833e4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11308.ic20", 0x20000, 0x7956c238, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11309.ic29", 0x20000, 0xc887f620, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11310.ic21", 0x20000, 0x5d9fa02c, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11311.ic30", 0x20000, 0x483de21b, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11314.ic154", 0x10000, 0xd4f954a9, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11315.ic153", 0x10000, 0x35813088, SYS16_ROM_TILES | BRF_GRA }, + { "epr-11316.ic152", 0x10000, 0x84290dff, SYS16_ROM_TILES | BRF_GRA }, + + { "epr-11323.ic90", 0x20000, 0x27e40735, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11322.ic94", 0x20000, 0x10364d74, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11321.ic98", 0x20000, 0x8e738f58, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11320.ic102", 0x20000, 0xa95c76b8, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11327.ic91", 0x20000, 0xdeae90f1, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11326.ic95", 0x20000, 0x29198403, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11325.ic99", 0x20000, 0xb9e98ae9, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11324.ic103", 0x20000, 0x9742b552, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11331.ic92", 0x20000, 0x3a2c042e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11330.ic96", 0x20000, 0xaa7c70c5, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11329.ic100", 0x20000, 0x31b20257, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11328.ic104", 0x20000, 0xda39e89c, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11335.ic93", 0x20000, 0xf19b3e86, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11334.ic97", 0x20000, 0x348f91c7, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11333.ic101", 0x20000, 0x05a2333f, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11332.ic105", 0x20000, 0xdc089ec6, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11313.ic29", 0x10000, 0x6a56c4c3, SYS16_ROM_ROAD | BRF_GRA }, + + { "epr-11312.ic17", 0x10000, 0x3b974ed2, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-11317.ic11", 0x20000, 0xd4e7ac1f, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11318.ic12", 0x20000, 0x70d3f02c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11319.ic13", 0x20000, 0x50d9242e, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Thndrbld1) +STD_ROM_FN(Thndrbld1) + +/*==================================================== +Memory Handlers +====================================================*/ + +static UINT8 iochip_regs[2][8]; +static UINT8 iochip_force_input; + +inline UINT16 iochip_r(INT32 which, INT32 port, INT32 inputval) +{ + UINT16 result = iochip_regs[which][port]; + + /* for ports 0-3, the direction is controlled 4 bits at a time by register 6 */ + if (port <= 3) + { + if (iochip_force_input || ((iochip_regs[which][6] >> (2*port+0)) & 1)) + result = (result & ~0x0f) | (inputval & 0x0f); + if (iochip_force_input || ((iochip_regs[which][6] >> (2*port+1)) & 1)) + result = (result & ~0xf0) | (inputval & 0xf0); + } + + /* for port 4, the direction is controlled 1 bit at a time by register 7 */ + else + { + if ((iochip_regs[which][7] >> 0) & 1) + result = (result & ~0x01) | (inputval & 0x01); + if ((iochip_regs[which][7] >> 1) & 1) + result = (result & ~0x02) | (inputval & 0x02); + if ((iochip_regs[which][7] >> 2) & 1) + result = (result & ~0x04) | (inputval & 0x04); + if ((iochip_regs[which][7] >> 3) & 1) + result = (result & ~0x08) | (inputval & 0x08); + result &= 0x0f; + } + return result; +} + +UINT16 __fastcall XBoardReadWord(UINT32 a) +{ + if (a >= 0x0e0000 && a <= 0x0e0007) { + return System16MultiplyChipRead(0, (a - 0x0e0000) >> 1); + } + + if (a >= 0x0e4000 && a <= 0x0e401f) { + return System16DivideChipRead(0, (a - 0x0e4000) >> 1); + } + + if (a >= 0x0e8000 && a <= 0x0e801f) { + return System16CompareTimerChipRead(0, (a - 0x0e8000) >> 1); + } + + if (a >= 0x2e0000 && a <= 0x2e0007) { + return System16MultiplyChipRead(1, (a - 0x2e0000) >> 1); + } + + if (a >= 0x2e4000 && a <= 0x2e401f) { + return System16DivideChipRead(1, (a - 0x2e4000) >> 1); + } + + if (a >= 0x2e8000 && a <= 0x2e800f) { + return System16CompareTimerChipRead(1, (a - 0x2e8000) >> 1); + } + + switch (a) { + case 0x2ee000: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall XBoardReadByte(UINT32 a) +{ + if (a >= 0x0e4000 && a <= 0x0e401f) { + return (UINT8)System16DivideChipRead(0, (a - 0x0e4000) >> 1); + } + + if (a >= 0x2e4000 && a <= 0x2e401f) { + return (UINT8)System16DivideChipRead(0, (a - 0x2e4000) >> 1); + } + + if (a >= 0x140000 && a <= 0x14ffff) { + int offset = ((a - 0x140000) >> 1) & 7; + switch (offset) { + case 0: { + return iochip_r(0, 0, 0xff); + } + + case 1: { + return iochip_r(0, 1, 0xff); + } + + case 2: { + return iochip_r(0, 2, 0); + } + + case 3: { + return iochip_r(0, 3, 0); + } + + case 4: { + return iochip_r(0, 4, 0); + } + } + return 0; + } + + if (a == 0x150001) return 0xff - System16Input[0]; + if (a == 0x150003) return 0xff - System16Input[1]; + if (a == 0x150005) return System16Dip[0]; + if (a == 0x150007) return System16Dip[1]; + + if (a >= 0x150008 && a <= 0x15ffff) { + INT32 offset = ((a - 0x150000) >> 1) & 7; + switch (offset) { + case 0: { + return iochip_r(1, 0, ~System16Input[0]); + } + + case 1: { + return iochip_r(1, 1, 0xff); + } + + case 2: { + return iochip_r(1, 2, System16Dip[0]); + } + + case 3: { + return iochip_r(1, 3, System16Dip[1]); + } + + case 4: { + return iochip_r(1, 4, 0); + } + } + return 0; + } + + switch (a) { + case 0x130001: { + if (System16ProcessAnalogControlsDo) return System16ProcessAnalogControlsDo((iochip_regs[0][2] >> 2) & 7); + } + + case 0x2ee000: + case 0x2ee001: + case 0x2ee002: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall XBoardWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x0c0000 && a <= 0x0cffff) { + System16BTileWordWrite(a - 0x0c0000, d); + return; + } + + if (a >= 0x0e0000 && a <= 0x0e0007) { + System16MultiplyChipWrite(0, (a - 0x0e0000) >> 1, d); + return; + } + + if (a >= 0x0e4000 && a <= 0x0e401f) { + System16DivideChipWrite(0, (a - 0x0e4000) >> 1, d); + return; + } + + if (a >= 0x0e8000 && a <= 0x0e801f) { + if (a == 0x0e8016) { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nSystem16CyclesDone[1] += ZetRun(100); + ZetClose(); + } + + System16CompareTimerChipWrite(0, (a - 0x0e8000) >> 1, d); + return; + } + + if (a >= 0x140000 && a <= 0x14ffff) { + INT32 offset = ((a - 0x140000) >> 1) & 7; + + iochip_regs[0][offset] = d; + + if (offset == 2) { + System16VideoEnable = d & 0x20; + if (!(d & 0x01)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + } + return; + } + + if (a >= 0x150000 && a <= 0x15ffff) { + INT32 offset = ((a - 0x150000) >> 1) & 7; + + iochip_regs[1][offset] = d; + return; + } + + if (a >= 0x2e0000 && a <= 0x2e0007) { + System16MultiplyChipWrite(1, (a - 0x2e0000) >> 1, d); + return; + } + + if (a >= 0x2e4000 && a <= 0x2e401f) { + System16DivideChipWrite(1, (a - 0x2e4000) >> 1, d); + return; + } + + if (a >= 0x2e8000 && a <= 0x2e800f) { + System16CompareTimerChipWrite(1, (a - 0x2e8000) >> 1, d); + return; + } + + switch (a) { + case 0x110000: { + UINT32 *src = (UINT32 *)System16SpriteRam; + UINT32 *dst = (UINT32 *)System16SpriteRamBuff; + + /* swap the halves of the sprite RAM */ + for (UINT32 i = 0; i < System16SpriteRamSize/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + /* hack for thunderblade */ + memset(System16SpriteRam, 0xff, System16SpriteRamSize); + + return; + } + + case 0x2ee000: { + System16RoadControl = d & 7; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall XBoardWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x0c0000 && a <= 0x0cffff) { + System16BTileByteWrite((a - 0x0c0000) ^ 1, d); + return; + } + + if (a >= 0x140000 && a <= 0x14ffff) { + INT32 offset = ((a - 0x140000) >> 1) & 7; + + iochip_regs[0][offset] = d; + + if (offset == 2) { + System16VideoEnable = d & 0x20; + if (!(d & 0x01)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + } + return; + } + + if (a >= 0x150000 && a <= 0x15ffff) { + INT32 offset = ((a - 0x150000) >> 1) & 7; + + iochip_regs[1][offset] = d; + return; + } + + switch (a) { + case 0x110000: + case 0x110001: { + UINT32 *src = (UINT32 *)System16SpriteRam; + UINT32 *dst = (UINT32 *)System16SpriteRamBuff; + + /* swap the halves of the sprite RAM */ + for (UINT32 i = 0; i < System16SpriteRamSize/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + /* hack for thunderblade */ + memset(System16SpriteRam, 0xff, System16SpriteRamSize); + return; + } + + case 0x130001: { + System16AnalogSelect = d; + return; + } + + case 0x0e8017: { + System16CompareTimerChipWrite(0, (a - 0x0e8000) >> 1, d); + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + nSystem16CyclesDone[1] += ZetRun(100); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT16 __fastcall XBoard2ReadWord(UINT32 a) +{ + if (a >= 0x0e0000 && a <= 0x0e0007) { + return System16MultiplyChipRead(1, (a - 0x0e0000) >> 1); + } + + if (a >= 0x0e4000 && a <= 0x0e401f) { + return System16DivideChipRead(1, (a - 0x0e4000) >> 1); + } + + if (a >= 0x0e8000 && a <= 0x0e800f) { + return System16CompareTimerChipRead(1, (a - 0x0e8000) >> 1); + } + + if (a >= 0x2e0000 && a <= 0x2e0007) { + return System16MultiplyChipRead(1, (a - 0x2e0000) >> 1); + } + + if (a >= 0x2e4000 && a <= 0x2e401f) { + return System16DivideChipRead(1, (a - 0x2e4000) >> 1); + } + + switch (a) { + case 0x0ee000: + case 0x2ee000: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Read Word -> 0x%06X\n"), a); +#endif + + return 0; +} + +UINT8 __fastcall XBoard2ReadByte(UINT32 a) +{ + switch (a) { + case 0x0ee000: + case 0x0ee001: { + // swap the halves of the road RAM + memcpy(System16RoadRamBuff, System16RoadRam, 0x1000); + UINT32 *src = (UINT32 *)System16RoadRamBuff; + UINT32 *dst = (UINT32 *)System16RoadRam; + for (INT32 i = 0; i < 0x1000/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + + return System16RoadControl; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Read Byte -> 0x%06X\n"), a); +#endif + + return 0; +} + +void __fastcall XBoard2WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x0e0000 && a <= 0x0e0007) { + System16MultiplyChipWrite(1, (a - 0x0e0000) >> 1, d); + return; + } + + if (a >= 0x0e4000 && a <= 0x0e401f) { + System16DivideChipWrite(1, (a - 0x0e4000) >> 1, d); + return; + } + + if (a >= 0x0e8000 && a <= 0x0e800f) { + System16CompareTimerChipWrite(1, (a - 0x0e8000) >> 1, d); + return; + } + + if (a >= 0x2e0000 && a <= 0x2e0007) { + System16MultiplyChipWrite(1, (a - 0x2e0000) >> 1, d); + return; + } + + if (a >= 0x2e4000 && a <= 0x2e401f) { + System16DivideChipWrite(1, (a - 0x2e4000) >> 1, d); + return; + } + + switch (a) { + case 0x0ee000: + case 0x2ee000: { + System16RoadControl = d & 7; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall XBoard2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x0ee001: + case 0x2ee000: { + System16RoadControl = d & 7; + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 # 2 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +/*==================================================== +Driver Inits +====================================================*/ + +UINT8 AbcopProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + //if (temp < 32) { + if (temp < 0x20) { + //bprintf(0, _T("(temp < 0x20) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + temp = 0x20; + return temp; + } + + // if (temp > 224) { + if (temp > 0xe0) { + //bprintf(0, _T("(temp > 0xe0) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + temp = 0xe0; + return temp; + } + + //bprintf(0, _T("(0x80 + (System16AnalogPort0 >> 4)) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + + return temp; + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + } + + return 0; +} + +UINT8 AburnerProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort0 >> 4); + } + + //if (temp < 32) { + if (temp < 0x20) { + //bprintf(0, _T("(temp < 0x20) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + temp = 0x20; + return temp; + } + + // if (temp > 224) { + if (temp > 0xe0) { + //bprintf(0, _T("(temp > 0xe0) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + temp = 0xe0; + return temp; + } + + //bprintf(0, _T("(0x80 + (System16AnalogPort0 >> 4)) int-> %i char-> %i\n"), 0x80 + (System16AnalogPort0 >> 4), temp); + return temp; + } + + // Up / Down + case 1: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) < 0xf82 && (System16AnalogPort1 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort1 >> 4); + } + + // if (temp < 64) { + if (temp < 0x40) { + //bprintf(0, _T("(temp < 0x40) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort1 >> 4), (System16AnalogPort1 >> 4), temp); + temp = 0x40; + return temp; + } + + // if (temp > 192) { + if (temp > 0xc0) { + //bprintf(0, _T("(temp > 0xc0) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort1 >> 4), (System16AnalogPort1 >> 4), temp); + temp = 0xc0; + return temp; + } + + //bprintf(0, _T("(0x80 - (System16AnalogPort1 >> 4)) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort1 >> 4), (System16AnalogPort1 >> 4), temp); + return temp; + } + + // Throttle + case 2: { + + // Prevent CHAR data overflow + if((System16AnalogPort2 >> 4) > 0x7f && (System16AnalogPort2 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort2 >> 4); + } + + // if (temp > 192) { + if (temp > 0xc0) { + //bprintf(0, _T("(temp > 0xc0) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort2 >> 4), (System16AnalogPort2 >> 4), temp); + temp = 0xff; + return temp; + } + + // if (temp < 64) { + if (temp < 0x40) { + //bprintf(0, _T("(temp < 0x40) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort2 >> 4), (System16AnalogPort2 >> 4), temp); + temp = 0; + return temp; + } + + temp = 0x80; + //bprintf(0, _T("(0x80 - (System16AnalogPort1 >> 4)) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort1 >> 4), (System16AnalogPort1 >> 4), temp); + return temp; + } + } + return 0; +} + +UINT8 GpriderProcessAnalogControls(UINT16 value) +{ + switch (value) { + + // Left / Right + case 0: { + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + return 0x80 + 0x7f; + } else { + return 0x80 + (System16AnalogPort0 >> 4); + } + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0x10; + return 0xef; + } + + // Brake + case 2: { + if (System16AnalogPort2 > 1) return 0x10; + return 0xef; + } + } + + return 0; +} + +UINT8 LoffireProcessAnalogControls(UINT16 value) +{ + switch (value) { + case 0: { return BurnGunReturnX(0); } + case 1: { return ~BurnGunReturnY(0); } + case 2: { return BurnGunReturnX(1); } + case 3: { return ~BurnGunReturnY(1); } + } + return 0; +} + +UINT8 RacheroProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + + // Brake + case 2: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + } + + return 0; +} + +UINT8 SmgpProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + return 0x80 + 0x7f; + } else { + return 0x80 + (System16AnalogPort0 >> 4); + } + + if (temp < 0x39) temp = 0x38; + if (temp > 0xc8) temp = 0xc8; + return temp; + } + + // Accelerate + case 1: { + if (System16AnalogPort1 > 1) return 0xb8; + return 0x38; + } + + // Brake + case 2: { + if (System16AnalogPort2 > 1) return 0xa8; + return 0x28; + } + } + + return 0; +} + +UINT8 ThndrbldProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left / Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) < 0xf82 && (System16AnalogPort0 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) { + temp = 0x20; + return temp; + } + + if (temp > 0xe0) { + temp = 0xe0; + return temp; + } + + return temp; + } + + // Throttle + case 1: { + + // Prevent CHAR data overflow + if((System16AnalogPort2 >> 4) > 0x7f && (System16AnalogPort2 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort2 >> 4); + } + + if (temp == 1) temp = 0; + return temp; + } + + // Up / Down + case 2: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) > 0x7f && (System16AnalogPort1 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort1 >> 4); + } + + if (temp < 0x20) { + temp = 0x20; + return temp; + } + + if (temp > 0xe0) { + temp = 0xe0; + return temp; + } + + return temp; + } + } + + return 0; +} + +static INT32 AbcopInit() +{ + System16ProcessAnalogControlsDo = AbcopProcessAnalogControls; + + return System16Init(); +} + +static INT32 Aburner2Init() +{ + System16ProcessAnalogControlsDo = AburnerProcessAnalogControls; + + INT32 nRet = System16Init(); + + if (!nRet) { + System16RoadPriority = 0; + } + + return nRet; +} + +static INT32 GpriderInit() +{ + System16ProcessAnalogControlsDo = GpriderProcessAnalogControls; + + return System16Init(); +} + +static INT32 LoffireInit() +{ + BurnGunInit(2, true); + + System16ProcessAnalogControlsDo = LoffireProcessAnalogControls; + + return System16Init(); +} + +static INT32 RacheroInit() +{ + System16ProcessAnalogControlsDo = RacheroProcessAnalogControls; + + return System16Init(); +} + +static INT32 SmgpInit() +{ + System16ProcessAnalogControlsDo = SmgpProcessAnalogControls; + + return System16Init(); +} + +static INT32 ThndrbldInit() +{ + System16ProcessAnalogControlsDo = ThndrbldProcessAnalogControls; + + return System16Init(); +} + +static INT32 XBoardExit() +{ + memset(iochip_regs, 0, sizeof(iochip_regs)); + iochip_force_input = 0; + + return System16Exit(); +} + +static INT32 XBoardScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(iochip_regs); + SCAN_VAR(iochip_force_input); + } + + return System16Scan(nAction, pnMin);; +} + +/*==================================================== +Driver Defs +====================================================*/ + +struct BurnDriver BurnDrvAbcop = { + "abcop", NULL, NULL, NULL, "1990", + "A.B. Cop (FD1094 317-0169b)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, AbcopRomInfo, AbcopRomName, NULL, NULL, AbcopInputInfo, AbcopDIPInfo, + AbcopInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAburner2 = { + "aburner2", NULL, NULL, NULL, "1987", + "After Burner II\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32, GBF_SHOOT, 0, + NULL, Aburner2RomInfo, Aburner2RomName, NULL, NULL, Aburner2InputInfo, Aburner2DIPInfo, + Aburner2Init, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvAburner = { + "aburner", "aburner2", NULL, NULL, "1987", + "After Burner (Japan)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32, GBF_SHOOT, 0, + NULL, AburnerRomInfo, AburnerRomName, NULL, NULL, Aburner2InputInfo, AburnerDIPInfo, + Aburner2Init, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGprider = { + "gprider", NULL, NULL, NULL, "1990", + "GP Rider (set 2, World, FD1094 317-0163)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, GpriderRomInfo, GpriderRomName, NULL, NULL, GpriderInputInfo, GpriderDIPInfo, + GpriderInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGprider1 = { + "gprider1", "gprider", NULL, NULL, "1990", + "GP Rider (set 1, US, FD1094 317-0162)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Gprider1RomInfo, Gprider1RomName, NULL, NULL, GpriderInputInfo, GpriderDIPInfo, + GpriderInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLoffire = { + "loffire", NULL, NULL, NULL, "1989", + "Line of Fire / Bakudan Yarou (World, FD1094 317-0136)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, LoffireRomInfo, LoffireRomName, NULL, NULL, LoffireInputInfo, LoffireDIPInfo, + LoffireInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLoffirej = { + "loffirej", "loffire", NULL, NULL, "1989", + "Line of Fire / Bakudan Yarou (Japan, FD1094 317-0134)\0", NULL, "Sega", "X-Board", + L"Line of Fire / Bakudan Yarou (Japan, FD1094 317-0134)\0\u7206\u5F3E\u91CE\u90CE\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, LoffirejRomInfo, LoffirejRomName, NULL, NULL, LoffireInputInfo, LoffireDIPInfo, + LoffireInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLoffireu = { + "loffireu", "loffire", NULL, NULL, "1989", + "Line of Fire / Bakudan Yarou (US, FD1094 317-0135)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, LoffireuRomInfo, LoffireuRomName, NULL, NULL, LoffireInputInfo, LoffireDIPInfo, + LoffireInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRachero = { + "rachero", NULL, NULL, NULL, "1989", + "Racing Hero (FD1094 317-0144)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, RacheroRomInfo, RacheroRomName, NULL, NULL, RacheroInputInfo, RacheroDIPInfo, + RacheroInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriverD BurnDrvRascot2 = { + "rascot2", NULL, NULL, NULL, "19??", + "Royal Ascot 2\0", NULL, "????", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32, GBF_MISC, 0, + NULL, Rascot2RomInfo, Rascot2RomName, NULL, NULL, Aburner2InputInfo, Aburner2DIPInfo, + Aburner2Init, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgp = { + "smgp", NULL, NULL, NULL, "1989", + "Super Monaco GP (World, Rev B, 'Twin', FD1094 317-0126a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, SmgpRomInfo, SmgpRomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgp5 = { + "smgp5", "smgp", NULL, NULL, "1989", + "Super Monaco GP (World, 'Air Drive Cabinet', FD1094 317-0126)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Smgp5RomInfo, Smgp5RomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgp6 = { + "smgp6", "smgp", NULL, NULL, "1989", + "Super Monaco GP (World, Rev A, FD1094 317-0126a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Smgp6RomInfo, Smgp6RomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpj = { + "smgpj", "smgp", NULL, NULL, "1989", + "Super Monaco GP (Japan, Rev B, FD1094 317-0124a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, SmgpjRomInfo, SmgpjRomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpja = { + "smgpja", "smgp", NULL, NULL, "1989", + "Super Monaco GP (Japan, Rev A, FD1094 317-0124a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, SmgpjaRomInfo, SmgpjaRomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpu = { + "smgpu", "smgp", NULL, NULL, "1989", + "Super Monaco GP (US, Rev C, FD1094 317-0125a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, SmgpuRomInfo, SmgpuRomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpu1 = { + "smgpu1", "smgp", NULL, NULL, "1989", + "Super Monaco GP (US, Rev B, FD1094 317-0125a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Smgpu1RomInfo, Smgpu1RomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpu2 = { + "smgpu2", "smgp", NULL, NULL, "1989", + "Super Monaco GP (US, Rev A, FD1094 317-0125a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Smgpu2RomInfo, Smgpu2RomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSmgpu3 = { + "smgpu3", "smgp", NULL, NULL, "1989", + "Super Monaco GP (set 3, US, FD1094 317-0125a)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_RACING, 0, + NULL, Smgpu3RomInfo, Smgpu3RomName, NULL, NULL, SmgpInputInfo, SmgpDIPInfo, + SmgpInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThndrbld = { + "thndrbld", NULL, NULL, NULL, "1987", + "Thunder Blade (upright, FD1094 317-0056)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32 | HARDWARE_SEGA_FD1094_ENC, GBF_SHOOT, 0, + NULL, ThndrbldRomInfo, ThndrbldRomName, NULL, NULL, ThndrbldInputInfo, ThndrbldDIPInfo, + ThndrbldInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThndrbld1 = { + "thndrbld1", "thndrbld", NULL, NULL, "1987", + "Thunder Blade (deluxe/standing, unprotected)\0", NULL, "Sega", "X-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMX | HARDWARE_SEGA_SPRITE_LOAD32, GBF_SHOOT, 0, + NULL, Thndrbld1RomInfo, Thndrbld1RomName, NULL, NULL, ThndrbldInputInfo, Thndrbld1DIPInfo, + ThndrbldInit, XBoardExit, XBoardFrame, NULL, XBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/d_ybrd.cpp b/src/burn/drivers/sega/d_ybrd.cpp new file mode 100644 index 00000000..45e47100 --- /dev/null +++ b/src/burn/drivers/sega/d_ybrd.cpp @@ -0,0 +1,2023 @@ +#include "sys16.h" + +/*==================================================== +Input Defs +====================================================*/ + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo Gforce2InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Throttle" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 z-axis" ), + {"Shoot" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"Missile" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Gforce2) + +static struct BurnInputInfo GlocInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Throttle" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 z-axis" ), + {"Fire 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + {"Fire 3" , BIT_DIGITAL , System16InputPort0 + 0, "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Gloc) + +static struct BurnInputInfo Glocr360InputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 y-axis" ), + A("Moving Roll" , BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("Moving Pitch" , BIT_ANALOG_REL, &System16AnalogPort3, "p3 x-axis" ), + {"Fire 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , System16InputPort0 + 5, "p1 fire 2" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Glocr360) + +static struct BurnInputInfo PdriftInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 6, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 7, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &System16AnalogPort0, "p1 x-axis" ), + A("Accelerate" , BIT_ANALOG_REL, &System16AnalogPort1, "p1 fire 1" ), + A("Brake" , BIT_ANALOG_REL, &System16AnalogPort2, "p1 fire 2" ), + {"Gear" , BIT_DIGITAL , &System16Gear , "p1 fire 3" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 2 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 1 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Pdrift) + +static struct BurnInputInfo RchaseInputList[] = { + {"Coin 1" , BIT_DIGITAL , System16InputPort0 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , System16InputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , System16InputPort0 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , System16InputPort0 + 6, "p2 start" }, + + A("P1 Left/Right" , BIT_ANALOG_REL, &System16AnalogPort0, "mouse x-axis" ), + A("P1 Up/Down" , BIT_ANALOG_REL, &System16AnalogPort1, "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , System16InputPort0 + 1, "mouse button 1" }, + + A("P2 Left/Right" , BIT_ANALOG_REL, &System16AnalogPort2, "p2 x-axis" ), + A("P2 Up/Down" , BIT_ANALOG_REL, &System16AnalogPort3, "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , System16InputPort0 + 0, "p2 fire 1" }, + + {"Service" , BIT_DIGITAL , System16InputPort0 + 3 , "service" }, + {"Diagnostics" , BIT_DIGITAL , System16InputPort0 + 2 , "diag" }, + {"Reset" , BIT_DIGITAL , &System16Reset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , System16Dip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , System16Dip + 1 , "dip" }, +}; + +STDINPUTINFO(Rchase) + +#undef A + +/*==================================================== +Dip Defs +====================================================*/ + +#define YBOARD_COINAGE(dipval) \ + {0 , 0xfe, 0 , 16 , "Coin A" }, \ + {dipval, 0x01, 0x0f, 0x07, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x08, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x09, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x05, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0x0f, 0x04, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0x0f, 0x01, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0x0f, 0x02, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0x0f, 0x03, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0x0f, 0x06, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, \ + \ + {0 , 0xfe, 0 , 16 , "Coin B" }, \ + {dipval, 0x01, 0xf0, 0x70, "4 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x80, "3 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x90, "2 Coins 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x50, "2 Coins 1 Credit 5/3 6/4" }, \ + {dipval, 0x01, 0xf0, 0x40, "2 Coins 1 Credit 4/3" }, \ + {dipval, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, \ + {dipval, 0x01, 0xf0, 0x10, "1 Coin 1 Credit 2/3" }, \ + {dipval, 0x01, 0xf0, 0x20, "1 Coin 1 Credit 4/5" }, \ + {dipval, 0x01, 0xf0, 0x30, "1 Coin 1 Credit 5/6" }, \ + {dipval, 0x01, 0xf0, 0x60, "2 Coins 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, \ + {dipval, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, \ + {dipval, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, \ + {dipval, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, \ + {dipval, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, \ + {dipval, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, + +static struct BurnDIPInfo Gforce2DIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0x7e, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Energy Timer" }, + {0x0b, 0x01, 0x06, 0x04, "Easy" }, + {0x0b, 0x01, 0x06, 0x06, "Normal" }, + {0x0b, 0x01, 0x06, 0x02, "Hard" }, + {0x0b, 0x01, 0x06, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Shield Strength" }, + {0x0b, 0x01, 0x08, 0x08, "Weak" }, + {0x0b, 0x01, 0x08, 0x00, "Strong" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x30, 0x20, "Easy" }, + {0x0b, 0x01, 0x30, 0x30, "Normal" }, + {0x0b, 0x01, 0x30, 0x10, "Hard" }, + {0x0b, 0x01, 0x30, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0b, 0x01, 0xc0, 0xc0, "Super Deluxe" }, + {0x0b, 0x01, 0xc0, 0x80, "Deluxe" }, + {0x0b, 0x01, 0xc0, 0x40, "Upright" }, + {0x0b, 0x01, 0xc0, 0x00, "City" }, + + // Dip 2 + YBOARD_COINAGE(0x0c) +}; + +STDDIPINFO(Gforce2) + +static struct BurnDIPInfo GlocDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x6b, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0c, 0x01, 0x18, 0x18, "Moving" }, + {0x0c, 0x01, 0x18, 0x10, "Cockpit" }, + {0x0c, 0x01, 0x18, 0x08, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x20, 0x00, "No" }, + {0x0c, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0c, 0x01, 0xc0, 0x40, "1 to start, 1 to continue" }, + {0x0c, 0x01, 0xc0, 0xc0, "2 to start, 1 to continue" }, + {0x0c, 0x01, 0xc0, 0x80, "3 to start, 2 to continue" }, + {0x0c, 0x01, 0xc0, 0x00, "4 to start, 3 to continue" }, + + // Dip 2 + YBOARD_COINAGE(0x0d) +}; + +STDDIPINFO(Gloc) + +static struct BurnDIPInfo Glocr360DIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0xf3, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 3 , "Game Type" }, + {0x0c, 0x01, 0x03, 0x02, "Fighting Only" }, + {0x0c, 0x01, 0x03, 0x03, "Fight/Experience" }, + {0x0c, 0x01, 0x03, 0x01, "Experience Only" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 9 , "Initial Credit" }, + {0x0c, 0x01, 0xf0, 0xf0, "1" }, + {0x0c, 0x01, 0xf0, 0xe0, "2" }, + {0x0c, 0x01, 0xf0, 0xd0, "3" }, + {0x0c, 0x01, 0xf0, 0xc0, "4" }, + {0x0c, 0x01, 0xf0, 0xb0, "5" }, + {0x0c, 0x01, 0xf0, 0xa0, "6" }, + {0x0c, 0x01, 0xf0, 0x90, "8" }, + {0x0c, 0x01, 0xf0, 0x80, "10" }, + {0x0c, 0x01, 0xf0, 0x70, "12" }, + + // Dip 2 + {0 , 0xfe, 0 , 16 , "Coin A" }, + {0x0d, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" }, + {0x0d, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" }, + {0x0d, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" }, + {0x0d, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" }, + {0x0d, 0x01, 0x0f, 0x08, "1 Coin 8 Credits" }, + {0x0d, 0x01, 0x0f, 0x00, "Free Play (if coin B too) or 1C/1C" }, + + {0 , 0xfe, 0 , 16 , "Coin B" }, + {0x0d, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" }, + {0x0d, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" }, + {0x0d, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" }, + {0x0d, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" }, + {0x0d, 0x01, 0xf0, 0x80, "1 Coin 8 Credits" }, + {0x0d, 0x01, 0xf0, 0x00, "Free Play (if coin A too) or 1C/1C" }, +}; + +STDDIPINFO(Glocr360) + +static struct BurnDIPInfo PdriftDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xea, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0a, 0x01, 0x03, 0x03, "Moving" }, + {0x0a, 0x01, 0x03, 0x02, "Upright/Sit Down" }, + {0x0a, 0x01, 0x03, 0x01, "Mini Upright" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0a, 0x01, 0x08, 0x08, "1 to start, 1 to continue" }, + {0x0a, 0x01, 0x08, 0x18, "2 to start, 1 to continue" }, + {0x0a, 0x01, 0x08, 0x00, "2 to start, 2 to continue" }, + {0x0a, 0x01, 0x08, 0x10, "3 to start, 2 to continue" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x20, 0x00, "No" }, + {0x0a, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0xc0, 0x80, "Easy" }, + {0x0a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0a, 0x01, 0xc0, 0x40, "Hard" }, + {0x0a, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + YBOARD_COINAGE(0x0b) +}; + +STDDIPINFO(Pdrift) + +static struct BurnDIPInfo PdrifteDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xea, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0a, 0x01, 0x03, 0x03, "Moving" }, + {0x0a, 0x01, 0x03, 0x02, "Upright" }, + {0x0a, 0x01, 0x03, 0x01, "Mini Upright" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Initial Credit" }, + {0x0a, 0x01, 0x10, 0x00, "1" }, + {0x0a, 0x01, 0x10, 0x10, "2" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x20, 0x00, "No" }, + {0x0a, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0xc0, 0x80, "Easy" }, + {0x0a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0a, 0x01, 0xc0, 0x40, "Hard" }, + {0x0a, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + YBOARD_COINAGE(0x0b) +}; + +STDDIPINFO(Pdrifte) + +static struct BurnDIPInfo PdriftjDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xea, NULL }, + {0x0b, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0a, 0x01, 0x03, 0x03, "Moving" }, + {0x0a, 0x01, 0x03, 0x02, "Upright/Sit Down" }, + {0x0a, 0x01, 0x03, 0x01, "Mini Upright" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Initial Credit" }, + {0x0a, 0x01, 0x10, 0x00, "1" }, + {0x0a, 0x01, 0x10, 0x10, "2" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x20, 0x00, "No" }, + {0x0a, 0x01, 0x20, 0x20, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0xc0, 0x80, "Easy" }, + {0x0a, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0a, 0x01, 0xc0, 0x40, "Hard" }, + {0x0a, 0x01, 0xc0, 0x00, "Hardest" }, + + // Dip 2 + YBOARD_COINAGE(0x0b) +}; + +STDDIPINFO(Pdriftj) + +static struct BurnDIPInfo RchaseDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0x63, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0d, 0x01, 0x03, 0x03, "1 to start, 1 to continue" }, + {0x0d, 0x01, 0x03, 0x02, "2 to start, 1 to continue" }, + {0x0d, 0x01, 0x03, 0x01, "3 to start, 2 to continue" }, + {0x0d, 0x01, 0x03, 0x00, "4 to start, 3 to continue" }, + + {0 , 0xfe, 0 , 2 , "Coin Chute" }, + {0x0d, 0x01, 0x04, 0x04, "Single" }, + {0x0d, 0x01, 0x04, 0x00, "Twin" }, + + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x08, 0x08, "Moving" }, + {0x0d, 0x01, 0x08, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0d, 0x01, 0x60, 0x40, "Easy" }, + {0x0d, 0x01, 0x60, 0x60, "Normal" }, + {0x0d, 0x01, 0x60, 0x20, "Hard" }, + {0x0d, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x80, 0x80, "Off" }, + {0x0d, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Coin to Credit" }, + {0x0e, 0x01, 0x03, 0x00, "4 Coins 1 Credit" }, + {0x0e, 0x01, 0x03, 0x01, "3 Coins 1 Credit" }, + {0x0e, 0x01, 0x03, 0x02, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coins 1 Credit" }, + + {0 , 0xfe, 0 , 2 , "Coin #1 mulitplier" }, + {0x0e, 0x01, 0x04, 0x04, "x1" }, + {0x0e, 0x01, 0x04, 0x00, "x2" }, + + {0 , 0xfe, 0 , 4 , "Coin #2 mulitplier" }, + {0x0e, 0x01, 0x18, 0x18, "x1" }, + {0x0e, 0x01, 0x18, 0x10, "x4" }, + {0x0e, 0x01, 0x18, 0x08, "x5" }, + {0x0e, 0x01, 0x18, 0x00, "x6" }, + + {0 , 0xfe, 0 , 8 , "Bonus Adder" }, + {0x0e, 0x01, 0xe0, 0xe0, "None" }, + {0x0e, 0x01, 0xe0, 0xc0, "2 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0xa0, "3 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0x80, "4 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0x60, "5 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0x40, "6 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0x20, "7 gives 1 more" }, + {0x0e, 0x01, 0xe0, 0x00, "Error" }, +}; + +STDDIPINFO(Rchase) + +static struct BurnDIPInfo StrkfgtrDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0x5b, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x08, 0x00, "No" }, + {0x0c, 0x01, 0x08, 0x08, "Yes" }, + + {0 , 0xfe, 0 , 4 , "Credits" }, + {0x0c, 0x01, 0x30, 0x10, "1 to start, 1 to continue" }, + {0x0c, 0x01, 0x30, 0x30, "2 to start, 1 to continue" }, + {0x0c, 0x01, 0x30, 0x20, "3 to start, 2 to continue" }, + {0x0c, 0x01, 0x30, 0x00, "4 to start, 3 to continue" }, + + {0 , 0xfe, 0 , 3 , "Cabinet" }, + {0x0c, 0x01, 0xc0, 0xc0, "Moving" }, + {0x0c, 0x01, 0xc0, 0x80, "Cockpit" }, + {0x0c, 0x01, 0xc0, 0x40, "Upright" }, + + // Dip 2 + YBOARD_COINAGE(0x0d) +}; + +STDDIPINFO(Strkfgtr) + +#undef YBOARD_COINAGE + +/*==================================================== +Rom Defs +====================================================*/ + +static struct BurnRomInfo Gforce2RomDesc[] = { + { "epr-11688.25", 0x20000, 0xc845f2df, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11687.24", 0x20000, 0x1cbefbbf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11875.81", 0x20000, 0xc81701c6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11874.80", 0x20000, 0x5301fd79, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11816b.54", 0x20000, 0x317dd0c2, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-11815b.53", 0x20000, 0xf1fb22f1, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "mpr-11468.14", 0x20000, 0x74ca9ca5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11467.16", 0x20000, 0x6e60e736, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11695.15", 0x20000, 0x38a864be, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11694.17", 0x20000, 0x7e297b84, SYS16_ROM_SPRITES | BRF_GRA }, + + { "mpr-11469.67", 0x20000, 0xed7a2299, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11470.75", 0x20000, 0x34dea550, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11477.63", 0x20000, 0xa2784653, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11478.71", 0x20000, 0x8b778993, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11471.86", 0x20000, 0xf1974069, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11472.114", 0x20000, 0x0d24409a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11479.82", 0x20000, 0xecd6138a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11480.110", 0x20000, 0x64ad66c5, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-11473.66", 0x20000, 0x0538c6ec, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11474.74", 0x20000, 0xeb923c50, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11481.62", 0x20000, 0x78e652b6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11482.70", 0x20000, 0x2f879766, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11475.85", 0x20000, 0x69cfec89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11476.113", 0x20000, 0xa60b9b79, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11483.81", 0x20000, 0xd5d3a505, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11484.109", 0x20000, 0xb8a56a50, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11696.65", 0x20000, 0x99e8e49e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11697.73", 0x20000, 0x7545c52e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11700.61", 0x20000, 0xe13839c1, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11701.69", 0x20000, 0x9fb3d365, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11698.84", 0x20000, 0xcfeba3e2, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11699.112", 0x20000, 0x4a00534a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11702.80", 0x20000, 0x2a09c627, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11703.108", 0x20000, 0x43bb7d9f, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11524.64", 0x20000, 0x5d35849f, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11525.72", 0x20000, 0x9ae47552, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11532.60", 0x20000, 0xb3565ddb, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11533.68", 0x20000, 0xf5d16e8a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11526.83", 0x20000, 0x094cb3f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11527.111", 0x20000, 0xe821a144, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11534.79", 0x20000, 0xb7f0ad7c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11535.107", 0x20000, 0x95da7a46, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11693.102", 0x10000, 0x0497785c, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11465.107", 0x80000, 0xe1436dab, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11516.106", 0x20000, 0x19d0e17f, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11814.105", 0x20000, 0x0b05d376, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Gforce2) +STD_ROM_FN(Gforce2) + +static struct BurnRomInfo Gforce2jRomDesc[] = { + { "epr-11511.25", 0x20000, 0xd80a86d6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11510.24", 0x20000, 0xd2b1bef4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11515.81", 0x20000, 0xd85875cf, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11514.80", 0x20000, 0x3dcc6919, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11513.54", 0x20000, 0xe18bc177, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-11512.53", 0x20000, 0x6010e63e, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "mpr-11468.14", 0x20000, 0x74ca9ca5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11467.16", 0x20000, 0x6e60e736, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11695.15", 0x20000, 0x38a864be, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11694.17", 0x20000, 0x7e297b84, SYS16_ROM_SPRITES | BRF_GRA }, + + { "mpr-11469.67", 0x20000, 0xed7a2299, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11470.75", 0x20000, 0x34dea550, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11477.63", 0x20000, 0xa2784653, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11478.71", 0x20000, 0x8b778993, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11471.86", 0x20000, 0xf1974069, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11472.114", 0x20000, 0x0d24409a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11479.82", 0x20000, 0xecd6138a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11480.110", 0x20000, 0x64ad66c5, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-11473.66", 0x20000, 0x0538c6ec, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11474.74", 0x20000, 0xeb923c50, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11481.62", 0x20000, 0x78e652b6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11482.70", 0x20000, 0x2f879766, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11475.85", 0x20000, 0x69cfec89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11476.113", 0x20000, 0xa60b9b79, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11483.81", 0x20000, 0xd5d3a505, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11484.109", 0x20000, 0xb8a56a50, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11696.65", 0x20000, 0x99e8e49e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11697.73", 0x20000, 0x7545c52e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11700.61", 0x20000, 0xe13839c1, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11701.69", 0x20000, 0x9fb3d365, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11698.84", 0x20000, 0xcfeba3e2, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11699.112", 0x20000, 0x4a00534a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11702.80", 0x20000, 0x2a09c627, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11703.108", 0x20000, 0x43bb7d9f, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11524.64", 0x20000, 0x5d35849f, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11525.72", 0x20000, 0x9ae47552, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11532.60", 0x20000, 0xb3565ddb, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11533.68", 0x20000, 0xf5d16e8a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11526.83", 0x20000, 0x094cb3f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11527.111", 0x20000, 0xe821a144, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11534.79", 0x20000, 0xb7f0ad7c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11535.107", 0x20000, 0x95da7a46, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11693.102", 0x10000, 0x0497785c, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11465.107", 0x80000, 0xe1436dab, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11516.106", 0x20000, 0x19d0e17f, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11814.105", 0x20000, 0x0b05d376, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Gforce2j) +STD_ROM_FN(Gforce2j) + +static struct BurnRomInfo Gforce2jaRomDesc[] = { + { "epr-11688.25", 0x20000, 0xc845f2df, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11687.24", 0x20000, 0x1cbefbbf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11875.81", 0x20000, 0xc81701c6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11874.80", 0x20000, 0x5301fd79, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11690a.54", 0x20000, 0xe18bc177, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-11689a.53", 0x20000, 0x6010e63e, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "mpr-11468.14", 0x20000, 0x74ca9ca5, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-11467.16", 0x20000, 0x6e60e736, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11695.15", 0x20000, 0x38a864be, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11694.17", 0x20000, 0x7e297b84, SYS16_ROM_SPRITES | BRF_GRA }, + + { "mpr-11469.67", 0x20000, 0xed7a2299, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11470.75", 0x20000, 0x34dea550, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11477.63", 0x20000, 0xa2784653, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11478.71", 0x20000, 0x8b778993, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11471.86", 0x20000, 0xf1974069, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11472.114", 0x20000, 0x0d24409a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11479.82", 0x20000, 0xecd6138a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11480.110", 0x20000, 0x64ad66c5, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-11473.66", 0x20000, 0x0538c6ec, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11474.74", 0x20000, 0xeb923c50, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11481.62", 0x20000, 0x78e652b6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11482.70", 0x20000, 0x2f879766, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11475.85", 0x20000, 0x69cfec89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11476.113", 0x20000, 0xa60b9b79, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11483.81", 0x20000, 0xd5d3a505, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-11484.109", 0x20000, 0xb8a56a50, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11696.65", 0x20000, 0x99e8e49e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11697.73", 0x20000, 0x7545c52e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11700.61", 0x20000, 0xe13839c1, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11701.69", 0x20000, 0x9fb3d365, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11698.84", 0x20000, 0xcfeba3e2, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11699.112", 0x20000, 0x4a00534a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11702.80", 0x20000, 0x2a09c627, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11703.108", 0x20000, 0x43bb7d9f, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11524.64", 0x20000, 0x5d35849f, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11525.72", 0x20000, 0x9ae47552, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11532.60", 0x20000, 0xb3565ddb, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11533.68", 0x20000, 0xf5d16e8a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11526.83", 0x20000, 0x094cb3f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11527.111", 0x20000, 0xe821a144, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11534.79", 0x20000, 0xb7f0ad7c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11535.107", 0x20000, 0x95da7a46, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11693.102", 0x10000, 0x0497785c, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11465.107", 0x80000, 0xe1436dab, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11516.106", 0x20000, 0x19d0e17f, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11814.105", 0x20000, 0x0b05d376, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Gforce2ja) +STD_ROM_FN(Gforce2ja) + +static struct BurnRomInfo GlocRomDesc[] = { + { "epr-13170.25", 0x20000, 0x45189229, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13169.24", 0x20000, 0x1b47cd6e, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13028.27", 0x20000, 0xb6aa2edf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13027.26", 0x20000, 0x6463c87a, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13032.81", 0x20000, 0x7da09c4e, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13031.80", 0x20000, 0xf3c7e3f4, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13030.54", 0x20000, 0x81abcabf, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-13029.53", 0x20000, 0xf3638efb, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-13037.14", 0x80000, 0xb801a250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13039.16", 0x80000, 0xd7e1266d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13038.15", 0x80000, 0x0b2edb6d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13040.17", 0x80000, 0x4aeb3a85, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13048.67", 0x80000, 0xfe1eb0dd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13056.75", 0x80000, 0x5904f8e6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13044.63", 0x80000, 0x4d931f89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13052.71", 0x80000, 0x0291f040, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13064.86", 0x80000, 0x5f8e651b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13072.114", 0x80000, 0x6b85641a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13060.82", 0x80000, 0xee16ad97, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13068.110", 0x80000, 0x64d52bbb, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13047.66", 0x80000, 0x53340832, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13055.74", 0x80000, 0x39b6b665, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13043.62", 0x80000, 0x208f16fd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13051.70", 0x80000, 0xad62cbd4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13063.85", 0x80000, 0xc580bf6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13071.113", 0x80000, 0xdf99ef99, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13059.81", 0x80000, 0x4c982558, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13067.109", 0x80000, 0xf97f6119, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13046.65", 0x80000, 0xc75a86e9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13054.73", 0x80000, 0x2934549a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13042.61", 0x80000, 0x53ed97af, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13050.69", 0x80000, 0x04429068, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13062.84", 0x80000, 0x4fdb4ee3, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13070.112", 0x80000, 0x52ea130e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13058.80", 0x80000, 0x19ff1626, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13066.108", 0x80000, 0xbc70a250, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13045.64", 0x80000, 0x54d5bc6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13053.72", 0x80000, 0x9502af13, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13041.60", 0x80000, 0xd0a7402c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13049.68", 0x80000, 0x5b9c0b6c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13061.83", 0x80000, 0x7b95ec3b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13069.111", 0x80000, 0xe1f538f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13057.79", 0x80000, 0x73baefee, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13065.107", 0x80000, 0x8937a655, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13033.102", 0x10000, 0x6df5e827, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13036.107", 0x80000, 0x7890c26c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13035.106", 0x80000, 0x009fa13e, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13034.105", 0x80000, 0xcd22d95d, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Gloc) +STD_ROM_FN(Gloc) + +static struct BurnRomInfo Glocr360RomDesc[] = { + { "epr-13623.25", 0x20000, 0x58ad10e7, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13622.24", 0x20000, 0xc4e68dbf, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13323a.27", 0x20000, 0x02e24a33, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13322a.26", 0x20000, 0x94f67740, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13327.81", 0x20000, 0x627036f9, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13326.80", 0x20000, 0x162ac233, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13325a.54", 0x20000, 0xaba307e5, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-13324a.53", 0x20000, 0xeb1b19e5, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-13037.14", 0x80000, 0xb801a250, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13039.16", 0x80000, 0xd7e1266d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13038.15", 0x80000, 0x0b2edb6d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13040.17", 0x80000, 0x4aeb3a85, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13048.67", 0x80000, 0xfe1eb0dd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13056.75", 0x80000, 0x5904f8e6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13044.63", 0x80000, 0x4d931f89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13052.71", 0x80000, 0x0291f040, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13064.86", 0x80000, 0x5f8e651b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13072.114", 0x80000, 0x6b85641a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13060.82", 0x80000, 0xee16ad97, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13068.110", 0x80000, 0x64d52bbb, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13047.66", 0x80000, 0x53340832, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13055.74", 0x80000, 0x39b6b665, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13043.62", 0x80000, 0x208f16fd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13051.70", 0x80000, 0xad62cbd4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13063.85", 0x80000, 0xc580bf6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13071.113", 0x80000, 0xdf99ef99, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13059.81", 0x80000, 0x4c982558, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13067.109", 0x80000, 0xf97f6119, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13331.65", 0x80000, 0x8ea8febe, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13333.73", 0x80000, 0x5bcd37d4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13330.61", 0x80000, 0x1e325d52, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13332.69", 0x80000, 0x8fd8067e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13335.84", 0x80000, 0x98ea420b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13337.112", 0x80000, 0xf55f00a4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13334.80", 0x80000, 0x72725060, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13336.108", 0x80000, 0xe2d4d477, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13045.64", 0x80000, 0x54d5bc6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13053.72", 0x80000, 0x9502af13, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13041.60", 0x80000, 0xd0a7402c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13049.68", 0x80000, 0x5b9c0b6c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13061.83", 0x80000, 0x7b95ec3b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13069.111", 0x80000, 0xe1f538f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13057.79", 0x80000, 0x73baefee, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13065.107", 0x80000, 0x8937a655, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13624.102", 0x10000, 0xeff33f2d, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "epr-13036.107", 0x80000, 0x7890c26c, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13035.106", 0x80000, 0x009fa13e, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-13625.105", 0x80000, 0xfae71fd2, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Glocr360) +STD_ROM_FN(Glocr360) + +static struct BurnRomInfo PdriftRomDesc[] = { + { "epr-12017.25", 0x20000, 0x31190322, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12016.24", 0x20000, 0x499f64a6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11748.27", 0x20000, 0x82a76cab, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11747.26", 0x20000, 0x9796ece5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11905.81", 0x20000, 0x1cf68109, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11904.80", 0x20000, 0xbb993681, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12019a.54", 0x20000, 0x11188a30, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-12018a.53", 0x20000, 0x1c582e1f, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-11791.14", 0x20000, 0x36b2910a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11789.16", 0x20000, 0xb86f8d2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11792.15", 0x20000, 0xc85caf6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11790.17", 0x20000, 0x2a564e66, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11757.67", 0x20000, 0xe46dc478, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11758.75", 0x20000, 0x5b435c87, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11773.63", 0x20000, 0x1b5d5758, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11774.71", 0x20000, 0x2ca0c170, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11759.86", 0x20000, 0xac8111f6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11760.114", 0x20000, 0x91282af9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11775.82", 0x20000, 0x48225793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11776.110", 0x20000, 0x78c46198, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11761.66", 0x20000, 0xbaa5d065, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11762.74", 0x20000, 0x1d1af7a5, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11777.62", 0x20000, 0x9662dd32, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11778.70", 0x20000, 0x2dfb7494, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11763.85", 0x20000, 0x1ee23407, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11764.113", 0x20000, 0xe859305e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11779.81", 0x20000, 0xa49cd793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11780.109", 0x20000, 0xd514ed81, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11765.65", 0x20000, 0x649e2dff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11766.73", 0x20000, 0xd92fb7fc, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11781.61", 0x20000, 0x9692d4cd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11782.69", 0x20000, 0xc913bb43, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11767.84", 0x20000, 0x1f8ad054, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11768.112", 0x20000, 0xdb2c4053, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11783.80", 0x20000, 0x6d189007, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11784.108", 0x20000, 0x57f5fd64, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11769.64", 0x20000, 0x28f0ab51, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11770.72", 0x20000, 0xd7557ea9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11785.60", 0x20000, 0xe6ef32c4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11786.68", 0x20000, 0x2066b49d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11771.83", 0x20000, 0x67635618, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11772.111", 0x20000, 0x0f798d3a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11787.79", 0x20000, 0xe631dc12, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11788.107", 0x20000, 0x8464c66e, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11899.102", 0x10000, 0xed9fa889, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11754.107", 0x80000, 0xebeb8484, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11756.105", 0x20000, 0x12e43f8a, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11755.106", 0x20000, 0xc2db1244, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-11895.ic1", 0x20000, 0xee99a6fd, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11896.ic2", 0x20000, 0x4bebc015, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11897.ic3", 0x20000, 0x4463cb95, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11898.ic4", 0x20000, 0x5d19d767, SYS16_ROM_PROM | BRF_OPT }, +}; + + +STD_ROM_PICK(Pdrift) +STD_ROM_FN(Pdrift) + +static struct BurnRomInfo PdriftaRomDesc[] = { + { "epr-12017.25", 0x20000, 0x31190322, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-12016.24", 0x20000, 0x499f64a6, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11748.27", 0x20000, 0x82a76cab, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11747.26", 0x20000, 0x9796ece5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11905.81", 0x20000, 0x1cf68109, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11904.80", 0x20000, 0xbb993681, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-12019.54", 0x20000, 0xe514d7b6, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-12018.53", 0x20000, 0x0a3f7faf, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-11791.14", 0x20000, 0x36b2910a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11789.16", 0x20000, 0xb86f8d2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11792.15", 0x20000, 0xc85caf6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11790.17", 0x20000, 0x2a564e66, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11757.67", 0x20000, 0xe46dc478, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11758.75", 0x20000, 0x5b435c87, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11773.63", 0x20000, 0x1b5d5758, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11774.71", 0x20000, 0x2ca0c170, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11759.86", 0x20000, 0xac8111f6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11760.114", 0x20000, 0x91282af9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11775.82", 0x20000, 0x48225793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11776.110", 0x20000, 0x78c46198, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11761.66", 0x20000, 0xbaa5d065, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11762.74", 0x20000, 0x1d1af7a5, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11777.62", 0x20000, 0x9662dd32, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11778.70", 0x20000, 0x2dfb7494, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11763.85", 0x20000, 0x1ee23407, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11764.113", 0x20000, 0xe859305e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11779.81", 0x20000, 0xa49cd793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11780.109", 0x20000, 0xd514ed81, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11765.65", 0x20000, 0x649e2dff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11766.73", 0x20000, 0xd92fb7fc, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11781.61", 0x20000, 0x9692d4cd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11782.69", 0x20000, 0xc913bb43, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11767.84", 0x20000, 0x1f8ad054, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11768.112", 0x20000, 0xdb2c4053, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11783.80", 0x20000, 0x6d189007, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11784.108", 0x20000, 0x57f5fd64, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11769.64", 0x20000, 0x28f0ab51, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11770.72", 0x20000, 0xd7557ea9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11785.60", 0x20000, 0xe6ef32c4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11786.68", 0x20000, 0x2066b49d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11771.83", 0x20000, 0x67635618, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11772.111", 0x20000, 0x0f798d3a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11787.79", 0x20000, 0xe631dc12, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11788.107", 0x20000, 0x8464c66e, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11899.102", 0x10000, 0xed9fa889, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11754.107", 0x80000, 0xebeb8484, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11756.105", 0x20000, 0x12e43f8a, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11755.106", 0x20000, 0xc2db1244, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-11895.ic1", 0x20000, 0xee99a6fd, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11896.ic2", 0x20000, 0x4bebc015, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11897.ic3", 0x20000, 0x4463cb95, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11898.ic4", 0x20000, 0x5d19d767, SYS16_ROM_PROM | BRF_OPT }, +}; + + +STD_ROM_PICK(Pdrifta) +STD_ROM_FN(Pdrifta) + +static struct BurnRomInfo PdrifteRomDesc[] = { + { "epr-11901.25", 0x20000, 0x16744be8, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11900.24", 0x20000, 0x0a170d06, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11748.27", 0x20000, 0x82a76cab, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11747.26", 0x20000, 0x9796ece5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11905.81", 0x20000, 0x1cf68109, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11904.80", 0x20000, 0xbb993681, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11903.54", 0x20000, 0xd004f411, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-11902.53", 0x20000, 0xe8028e08, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-11791.14", 0x20000, 0x36b2910a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11789.16", 0x20000, 0xb86f8d2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11792.15", 0x20000, 0xc85caf6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11790.17", 0x20000, 0x2a564e66, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11757.67", 0x20000, 0xe46dc478, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11758.75", 0x20000, 0x5b435c87, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11773.63", 0x20000, 0x1b5d5758, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11774.71", 0x20000, 0x2ca0c170, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11759.86", 0x20000, 0xac8111f6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11760.114", 0x20000, 0x91282af9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11775.82", 0x20000, 0x48225793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11776.110", 0x20000, 0x78c46198, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11761.66", 0x20000, 0xbaa5d065, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11762.74", 0x20000, 0x1d1af7a5, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11777.62", 0x20000, 0x9662dd32, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11778.70", 0x20000, 0x2dfb7494, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11763.85", 0x20000, 0x1ee23407, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11764.113", 0x20000, 0xe859305e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11779.81", 0x20000, 0xa49cd793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11780.109", 0x20000, 0xd514ed81, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11765.65", 0x20000, 0x649e2dff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11766.73", 0x20000, 0xd92fb7fc, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11781.61", 0x20000, 0x9692d4cd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11782.69", 0x20000, 0xc913bb43, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11767.84", 0x20000, 0x1f8ad054, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11768.112", 0x20000, 0xdb2c4053, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11783.80", 0x20000, 0x6d189007, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11784.108", 0x20000, 0x57f5fd64, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11769.64", 0x20000, 0x28f0ab51, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11770.72", 0x20000, 0xd7557ea9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11785.60", 0x20000, 0xe6ef32c4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11786.68", 0x20000, 0x2066b49d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11771.83", 0x20000, 0x67635618, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11772.111", 0x20000, 0x0f798d3a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11787.79", 0x20000, 0xe631dc12, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11788.107", 0x20000, 0x8464c66e, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11899.102", 0x10000, 0xed9fa889, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11754.107", 0x80000, 0xebeb8484, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11756.105", 0x20000, 0x12e43f8a, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11755.106", 0x20000, 0xc2db1244, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-11895.ic1", 0x20000, 0xee99a6fd, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11896.ic2", 0x20000, 0x4bebc015, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11897.ic3", 0x20000, 0x4463cb95, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11898.ic4", 0x20000, 0x5d19d767, SYS16_ROM_PROM | BRF_OPT }, +}; + + +STD_ROM_PICK(Pdrifte) +STD_ROM_FN(Pdrifte) + +static struct BurnRomInfo PdriftjRomDesc[] = { + { "epr-11746a.25", 0x20000, 0xb0f1caf4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11745a.24", 0x20000, 0xa89720cd, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11748.27", 0x20000, 0x82a76cab, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-11747.26", 0x20000, 0x9796ece5, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-11752.81", 0x20000, 0xb6bb8111, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-11751.80", 0x20000, 0x7f0d0311, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-11750b.54", 0x20000, 0xbc14ce30, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-11749b.53", 0x20000, 0x9e385568, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-11791.14", 0x20000, 0x36b2910a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11789.16", 0x20000, 0xb86f8d2b, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11792.15", 0x20000, 0xc85caf6e, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-11790.17", 0x20000, 0x2a564e66, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-11757.67", 0x20000, 0xe46dc478, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11758.75", 0x20000, 0x5b435c87, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11773.63", 0x20000, 0x1b5d5758, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11774.71", 0x20000, 0x2ca0c170, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11759.86", 0x20000, 0xac8111f6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11760.114", 0x20000, 0x91282af9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11775.82", 0x20000, 0x48225793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11776.110", 0x20000, 0x78c46198, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11761.66", 0x20000, 0xbaa5d065, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11762.74", 0x20000, 0x1d1af7a5, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11777.62", 0x20000, 0x9662dd32, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11778.70", 0x20000, 0x2dfb7494, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11763.85", 0x20000, 0x1ee23407, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11764.113", 0x20000, 0xe859305e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11779.81", 0x20000, 0xa49cd793, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11780.109", 0x20000, 0xd514ed81, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11765.65", 0x20000, 0x649e2dff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11766.73", 0x20000, 0xd92fb7fc, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11781.61", 0x20000, 0x9692d4cd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11782.69", 0x20000, 0xc913bb43, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11767.84", 0x20000, 0x1f8ad054, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11768.112", 0x20000, 0xdb2c4053, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11783.80", 0x20000, 0x6d189007, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11784.108", 0x20000, 0x57f5fd64, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11769.64", 0x20000, 0x28f0ab51, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11770.72", 0x20000, 0xd7557ea9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11785.60", 0x20000, 0xe6ef32c4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11786.68", 0x20000, 0x2066b49d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11771.83", 0x20000, 0x67635618, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11772.111", 0x20000, 0x0f798d3a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11787.79", 0x20000, 0xe631dc12, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-11788.107", 0x20000, 0x8464c66e, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-11899.102", 0x10000, 0xed9fa889, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-11754.107", 0x80000, 0xebeb8484, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11756.105", 0x20000, 0x12e43f8a, SYS16_ROM_PCMDATA | BRF_SND }, + { "epr-11755.106", 0x20000, 0xc2db1244, SYS16_ROM_PCMDATA | BRF_SND }, + + { "epr-11895.ic1", 0x20000, 0xee99a6fd, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11896.ic2", 0x20000, 0x4bebc015, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11897.ic3", 0x20000, 0x4463cb95, SYS16_ROM_PROM | BRF_OPT }, + { "epr-11898.ic4", 0x20000, 0x5d19d767, SYS16_ROM_PROM | BRF_OPT }, +}; + + +STD_ROM_PICK(Pdriftj) +STD_ROM_FN(Pdriftj) + +static struct BurnRomInfo RchaseRomDesc[] = { + { "epr-13986.25", 0x20000, 0x388b2365, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13985.24", 0x20000, 0x14dba5d4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13988.27", 0x20000, 0xdc1cd5a4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13987.26", 0x20000, 0x43be9e60, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13992a.81", 0x20000, 0xc5d525b6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13991a.80", 0x20000, 0x299e3c7c, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-14092.54", 0x20000, 0x18eb23c5, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-14091.53", 0x20000, 0x72a56f71, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "mpr-13997.14", 0x40000, 0x1fdf1b87, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13999.16", 0x40000, 0x9a1dd53c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "mpr-14021.67", 0x80000, 0x9fa88781, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14022.75", 0x80000, 0x49e824bb, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14009.63", 0x80000, 0x35b5187e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14010.71", 0x80000, 0x9a538b9b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14023.86", 0x80000, 0xe11c6c67, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14024.114", 0x80000, 0x16344535, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14011.82", 0x80000, 0x78e9983b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14012.110", 0x80000, 0xe9daa1a4, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-14017.66", 0x80000, 0xb83df159, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14018.74", 0x80000, 0x76dbe9ce, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14005.62", 0x80000, 0x9e998209, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14006.70", 0x80000, 0x2caddf1a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14019.85", 0x80000, 0xb15e19ff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14020.113", 0x80000, 0x84c7008f, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14007.81", 0x80000, 0xc3cf5faa, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14008.109", 0x80000, 0x7e91beb2, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-14013.65", 0x80000, 0x31dbb2c3, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14014.73", 0x80000, 0x7e68257d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14001.61", 0x80000, 0x71031ad0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14002.69", 0x80000, 0x27e70a5e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14015.84", 0x80000, 0x7540bf85, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14016.112", 0x80000, 0x7d87b94d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14003.80", 0x80000, 0x87725d74, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14004.108", 0x80000, 0x73477291, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13993.102", 0x10000, 0x7cc3b543, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13996.107", 0x80000, 0x345f5a41, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13995.106", 0x80000, 0xf604c270, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13994.105", 0x80000, 0x76095538, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Rchase) +STD_ROM_FN(Rchase) + +static struct BurnRomInfo RchasejRomDesc[] = { + { "epr-13986.25", 0x20000, 0x388b2365, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13985.24", 0x20000, 0x14dba5d4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13988.27", 0x20000, 0xdc1cd5a4, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13987.26", 0x20000, 0x43be9e60, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13992a.81", 0x20000, 0xc5d525b6, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13991a.80", 0x20000, 0x299e3c7c, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13990.54.verify",0x20000, 0x18eb23c5, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-13989.53.verify",0x20000, 0x8f4f824e, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "mpr-13997.14", 0x40000, 0x1fdf1b87, SYS16_ROM_SPRITES | BRF_GRA }, + { "mpr-13999.16", 0x40000, 0x9a1dd53c, SYS16_ROM_SPRITES | BRF_GRA }, + + { "mpr-14021.67", 0x80000, 0x9fa88781, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14022.75", 0x80000, 0x49e824bb, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14009.63", 0x80000, 0x35b5187e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14010.71", 0x80000, 0x9a538b9b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14023.86", 0x80000, 0xe11c6c67, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14024.114", 0x80000, 0x16344535, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14011.82", 0x80000, 0x78e9983b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14012.110", 0x80000, 0xe9daa1a4, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-14017.66", 0x80000, 0xb83df159, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14018.74", 0x80000, 0x76dbe9ce, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14005.62", 0x80000, 0x9e998209, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14006.70", 0x80000, 0x2caddf1a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14019.85", 0x80000, 0xb15e19ff, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14020.113", 0x80000, 0x84c7008f, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14007.81", 0x80000, 0xc3cf5faa, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14008.109", 0x80000, 0x7e91beb2, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "mpr-14013.65", 0x80000, 0x31dbb2c3, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14014.73", 0x80000, 0x7e68257d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14001.61", 0x80000, 0x71031ad0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14002.69", 0x80000, 0x27e70a5e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14015.84", 0x80000, 0x7540bf85, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14016.112", 0x80000, 0x7d87b94d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14003.80", 0x80000, 0x87725d74, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "mpr-14004.108", 0x80000, 0x73477291, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13993.102", 0x10000, 0x7cc3b543, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13996.107", 0x80000, 0x345f5a41, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13995.106", 0x80000, 0xf604c270, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13994.105", 0x80000, 0x76095538, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Rchasej) +STD_ROM_FN(Rchasej) + +static struct BurnRomInfo StrkfgtrRomDesc[] = { + { "epr-13824.25", 0x20000, 0x2cf2610c, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13823.24", 0x20000, 0x2c98242f, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13826.27", 0x20000, 0x3d34ea55, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + { "epr-13825.26", 0x20000, 0xfe218d83, SYS16_ROM_PROG | BRF_ESS | BRF_PRG }, + + { "epr-13830.81", 0x20000, 0xf9adc9d1, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + { "epr-13829.80", 0x20000, 0xc5cd85dd, SYS16_ROM_PROG2 | BRF_ESS | BRF_PRG }, + + { "epr-13828.54", 0x20000, 0x2470cf5f, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + { "epr-13827.53", 0x20000, 0xa9d0cf7d, SYS16_ROM_PROG3 | BRF_ESS | BRF_PRG }, + + { "epr-13832.14", 0x80000, 0x41679754, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13833.16", 0x80000, 0x6148e11a, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13038.15", 0x80000, 0x0b2edb6d, SYS16_ROM_SPRITES | BRF_GRA }, + { "epr-13040.17", 0x80000, 0x4aeb3a85, SYS16_ROM_SPRITES | BRF_GRA }, + + { "epr-13048.67", 0x80000, 0xfe1eb0dd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13056.75", 0x80000, 0x5904f8e6, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13044.63", 0x80000, 0x4d931f89, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13052.71", 0x80000, 0x0291f040, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13064.86", 0x80000, 0x5f8e651b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13072.114", 0x80000, 0x6b85641a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13060.82", 0x80000, 0xee16ad97, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13068.110", 0x80000, 0x64d52bbb, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13047.66", 0x80000, 0x53340832, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13055.74", 0x80000, 0x39b6b665, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13043.62", 0x80000, 0x208f16fd, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13051.70", 0x80000, 0xad62cbd4, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13063.85", 0x80000, 0xc580bf6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13071.113", 0x80000, 0xdf99ef99, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13059.81", 0x80000, 0x4c982558, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13067.109", 0x80000, 0xf97f6119, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13046.65", 0x80000, 0xc75a86e9, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13054.73", 0x80000, 0x2934549a, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13042.61", 0x80000, 0x53ed97af, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13050.69", 0x80000, 0x04429068, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13062.84", 0x80000, 0x4fdb4ee3, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13070.112", 0x80000, 0x52ea130e, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13058.80", 0x80000, 0x19ff1626, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13066.108", 0x80000, 0xbc70a250, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13045.64", 0x80000, 0x54d5bc6d, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13053.72", 0x80000, 0x9502af13, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13041.60", 0x80000, 0xd0a7402c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13049.68", 0x80000, 0x5b9c0b6c, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13061.83", 0x80000, 0x7b95ec3b, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13069.111", 0x80000, 0xe1f538f0, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13057.79", 0x80000, 0x73baefee, SYS16_ROM_SPRITES2 | BRF_GRA }, + { "epr-13065.107", 0x80000, 0x8937a655, SYS16_ROM_SPRITES2 | BRF_GRA }, + + { "epr-13831.102", 0x10000, 0xdabbcea1, SYS16_ROM_Z80PROG | BRF_ESS | BRF_PRG }, + + { "mpr-13036.107", 0x80000, 0x7890c26c, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13035.106", 0x80000, 0x009fa13e, SYS16_ROM_PCMDATA | BRF_SND }, + { "mpr-13034.105", 0x80000, 0xcd22d95d, SYS16_ROM_PCMDATA | BRF_SND }, +}; + + +STD_ROM_PICK(Strkfgtr) +STD_ROM_FN(Strkfgtr) + +/*==================================================== +Memory Handlers +====================================================*/ + +static UINT8 misc_io_data[0x10]; +static UINT8 analog_data[4]; + +static UINT8 io_chip_r(UINT32 offset) +{ + switch (offset) { + case 0x00: + case 0x02: + case 0x03: + case 0x04: + case 0x07: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff; + } + + case 0x01: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return 0xff - System16Input[0]; + } + + case 0x05: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return System16Dip[0]; + } + + case 0x06: { + if (misc_io_data[0x1e/2] & (1 << offset)) return misc_io_data[offset]; + return System16Dip[1]; + } + + case 0x08: { + return 'S'; + } + + case 0x09: { + return 'E'; + } + + case 0x0a: { + return 'G'; + } + + case 0x0b: { + return 'A'; + } + + case 0x0c: + case 0x0e: { + return misc_io_data[0x0e]; + } + + case 0x0d: + case 0x0f: { + return misc_io_data[0x0f]; + } + } + + return 0xff; +} + +static void io_chip_w(UINT32 offset, UINT16 d) +{ + misc_io_data[offset] = d; + + switch (offset) { + case 0x04: { + System16VideoEnable = d & 0x80; + + if (d & 0x04) { + INT32 nLastCPU = nSekActive; + SekClose(); + SekOpen(2); + SekReset(); + SekClose(); + SekOpen(nLastCPU); + } + + if (d & 0x08) { + INT32 nLastCPU = nSekActive; + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(nLastCPU); + } + + if (!(d & 0x10)) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + return; + } + } +} + +static UINT8 analog_r(UINT32 offset) +{ + INT32 result = analog_data[offset] & 0x80; + analog_data[offset] <<= 1; + return result; +} + +static void analog_w(UINT32 offset, UINT16 /*d*/) +{ + if (offset == 3) { + if (System16ProcessAnalogControlsDo) analog_data[offset] = System16ProcessAnalogControlsDo(3 + (misc_io_data[0x08/2] & 3)); + } else { + if (System16ProcessAnalogControlsDo) analog_data[offset] = System16ProcessAnalogControlsDo(offset & 3); + } +} + +UINT16 __fastcall YBoardReadWord(UINT32 a) +{ + if (a >= 0x080000 && a <= 0x080007) { + return System16MultiplyChipRead(0, (a - 0x080000) >> 1); + } + + if (a >= 0x084000 && a <= 0x08401f) { + return System16DivideChipRead(0, (a - 0x084000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall YBoardReadByte(UINT32 a) +{ + if (a >= 0x100000 && a <= 0x10001f) { + return io_chip_r((a - 0x100000) >> 1); + } + + if (a >= 0x100040 && a <= 0x100047) { + return analog_r((a - 0x100040) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall YBoardWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x100000 && a <= 0x10001f) { + io_chip_w((a - 0x100000) >> 1, d); + return; + } + + if (a >= 0x080000 && a <= 0x080007) { + System16MultiplyChipWrite(0, (a - 0x080000) >> 1, d); + return; + } + + if (a >= 0x084000 && a <= 0x08401f) { + System16DivideChipWrite(0, (a - 0x084000) >> 1, d); + return; + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +void __fastcall YBoardWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x100000 && a <= 0x10001f) { + io_chip_w((a - 0x100000) >> 1, d); + return; + } + + if (a >= 0x100040 && a <= 0x100047) { + analog_w((a - 0x100040) >> 1, d); + return; + } + + switch (a) { + case 0x082001: { + System16SoundLatch = d & 0xff; + ZetOpen(0); + ZetNmi(); + ZetClose(); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 Write Byte -> 0x%06X, 0x%02X\n"), a, d); +#endif +} + +UINT16 __fastcall YBoard2ReadWord(UINT32 a) +{ + if (a >= 0x080000 && a <= 0x080007) { + return System16MultiplyChipRead(1, (a - 0x080000) >> 1); + } + + if (a >= 0x084000 && a <= 0x08401f) { + return System16DivideChipRead(1, (a - 0x084000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 #2 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +void __fastcall YBoard2WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x080000 && a <= 0x080007) { + System16MultiplyChipWrite(1, (a - 0x080000) >> 1, d); + return; + } + + if (a >= 0x084000 && a <= 0x08401f) { + System16DivideChipWrite(1, (a - 0x084000) >> 1, d); + return; + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 #2 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +UINT16 __fastcall YBoard3ReadWord(UINT32 a) +{ + if (a >= 0x080000 && a <= 0x080007) { + return System16MultiplyChipRead(2, (a - 0x080000) >> 1); + } + + if (a >= 0x084000 && a <= 0x08401f) { + return System16DivideChipRead(2, (a - 0x084000) >> 1); + } + + switch (a) { + case 0x198000: { + /* swap the halves of the rotation RAM */ + UINT32 *src = (UINT32 *)System16RotateRam; + UINT32 *dst = (UINT32 *)System16RotateRamBuff; + + for (UINT32 i = 0; i < System16RotateRamSize/4; i++) { + UINT32 temp = *src; + *src++ = *dst; + *dst++ = temp; + } + return 0xffff; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 #3 Read Word -> 0x%06X\n"), a); +#endif + + return 0xffff; +} + +UINT8 __fastcall YBoard3ReadByte(UINT32 a) +{ + if (a >= 0x084000 && a <= 0x08401f) { + return System16DivideChipRead(2, (a - 0x084000) >> 1); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 #3 Read Byte -> 0x%06X\n"), a); +#endif + + return 0xff; +} + +void __fastcall YBoard3WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x080000 && a <= 0x080007) { + System16MultiplyChipWrite(2, (a - 0x080000) >> 1, d); + return; + } + + if (a >= 0x084000 && a <= 0x08401f) { + System16DivideChipWrite(2, (a - 0x084000) >> 1, d); + return; + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68000 #3 Write Word -> 0x%06X, 0x%04X\n"), a, d); +#endif +} + +/*==================================================== +Driver Inits +====================================================*/ + +UINT8 Gforce2ProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Left/Right + case 0: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort0 >> 4); + } + + return temp; + } + + // Up/Down + case 1: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) < 0xf82 && (System16AnalogPort1 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort1 >> 4); + } + + return temp; + } + + // Throttle + case 2: { + + // Prevent CHAR data overflow + if((System16AnalogPort2 >> 4) > 0x7f && (System16AnalogPort2 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort2 >> 4); + } + + // full throttle + if(temp == 0) { + temp = 1; + return temp; + } + + // throttle range + if(temp > 0 && temp < 128) { + return temp; + } + + // normal speed + temp = 0; + + //bprintf(0, _T("(0x80 - (System16AnalogPort1 >> 4)) int-> %d port-> %d char-> %d\n"), 0x80 - (System16AnalogPort1 >> 4), (System16AnalogPort1 >> 4), temp); + + return temp; + } + } + + return 0; +} + +UINT8 GlocProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Up/Down + case 3: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) < 0xf82 && (System16AnalogPort1 >> 4) > 0x80) { + temp = (UINT8)(0x80 - 0xf82); + } else { + temp = 0x80 - (System16AnalogPort1 >> 4); + } + + if (temp < 0x40) temp = 0x40; + if (temp > 0xc0) temp = 0xc0; + return temp; + } + + // Throttle [?] + case 4: { + temp = 0x80 + (System16AnalogPort2 >> 4); + if (temp > 0xc0) return 0xff; + if (temp < 0x40) return 0; + return 0x80; + } + + // Left/Right + case 5: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + } + + return 0; +} + +UINT8 Glocr360ProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Moving Pitch + case 1: { + + // Prevent CHAR data overflow + if((System16AnalogPort3 >> 4) > 0x7f && (System16AnalogPort3 >> 4) <= 0x80) { + temp = 0x7f + 0x7f; + } else { + temp = 0x7f + (System16AnalogPort3 >> 4); + } + + if (temp == 0xfe) temp = 0xff; + return temp; + } + + // Moving Roll + case 2: { + + // Prevent CHAR data overflow + if((System16AnalogPort2 >> 4) > 0x7f && (System16AnalogPort2 >> 4) <= 0x80) { + temp = 0x7f + 0x7f; + } else { + temp = 0x7f + (System16AnalogPort2 >> 4); + } + + if (temp == 0xfe) temp = 0xff; + return temp; + } + + // Up/Down + case 3: { + + // Prevent CHAR data overflow + if((System16AnalogPort1 >> 4) < 0xf82 && (System16AnalogPort1 >> 4) > 0x80) { + temp = (UINT8)(0x7f - 0xf82); + } else { + temp = 0x7f - (System16AnalogPort1 >> 4); + } + + if (temp == 0xfe) temp = 0xff; + return temp; + } + + // Left/Right + case 5: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x7f + 0x7f; + } else { + temp = 0x7f + (System16AnalogPort0 >> 4); + } + + if (temp == 0xfe) temp = 0xff; + return temp; + } + } + + return 0; +} + +UINT8 PdriftProcessAnalogControls(UINT16 value) +{ + UINT8 temp = 0; + + switch (value) { + + // Brake + case 3: { + if (System16AnalogPort2 > 1) return 0xff; + return 0; + } + + // Accelerate + case 4: { + if (System16AnalogPort1 > 1) return 0xff; + return 0; + } + + // Steering + case 5: { + + // Prevent CHAR data overflow + if((System16AnalogPort0 >> 4) > 0x7f && (System16AnalogPort0 >> 4) <= 0x80) { + temp = 0x80 + 0x7f; + } else { + temp = 0x80 + (System16AnalogPort0 >> 4); + } + + if (temp < 0x20) temp = 0x20; + if (temp > 0xe0) temp = 0xe0; + return temp; + } + } + + return 0; +} + +UINT8 RchaseProcessAnalogControls(UINT16 value) +{ + switch (value) { + case 0: { + return BurnGunReturnX(0); + } + + case 1: { + return BurnGunReturnY(0); + } + + case 2: { + return BurnGunReturnX(1); + } + + case 3: { + return BurnGunReturnY(1); + } + } + + return 0; +} + +static INT32 Gforce2Init() +{ + System16ProcessAnalogControlsDo = Gforce2ProcessAnalogControls; + + System16PCMDataSizePreAllocate = 0x180000; + + INT32 nRet = System16Init(); + + UINT8 *pTemp = (UINT8*)malloc(0x0c0000); + memcpy(pTemp, System16PCMData, 0x0c0000); + memset(System16PCMData, 0, 0x180000); + memcpy(System16PCMData + 0x000000, pTemp + 0x000000, 0x80000); + memcpy(System16PCMData + 0x080000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0a0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0c0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0e0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x100000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x120000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x140000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x160000, pTemp + 0x0a0000, 0x20000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + return nRet; +} + +static INT32 GlocInit() +{ + System16ProcessAnalogControlsDo = GlocProcessAnalogControls; + + return System16Init(); +} + +static INT32 Glocr360Init() +{ + System16ProcessAnalogControlsDo = Glocr360ProcessAnalogControls; + + return System16Init(); +} + +static INT32 PdriftInit() +{ + System16ProcessAnalogControlsDo = PdriftProcessAnalogControls; + + System16HasGears = true; + + System16PCMDataSizePreAllocate = 0x180000; + + INT32 nRet = System16Init(); + + if (!nRet) YBoardIrq2Scanline = 0; + + UINT8 *pTemp = (UINT8*)malloc(0x0c0000); + memcpy(pTemp, System16PCMData, 0x0c0000); + memset(System16PCMData, 0, 0x180000); + memcpy(System16PCMData + 0x000000, pTemp + 0x000000, 0x80000); + memcpy(System16PCMData + 0x080000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0a0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0c0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x0e0000, pTemp + 0x080000, 0x20000); + memcpy(System16PCMData + 0x100000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x120000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x140000, pTemp + 0x0a0000, 0x20000); + memcpy(System16PCMData + 0x160000, pTemp + 0x0a0000, 0x20000); + if (pTemp) { + free(pTemp); + pTemp = NULL; + } + + return nRet; +} + +static INT32 RchaseInit() +{ + BurnGunInit(2, false); + + System16ProcessAnalogControlsDo = RchaseProcessAnalogControls; + + return System16Init(); +} + +static INT32 YBoardExit() +{ + memset(misc_io_data, 0, sizeof(misc_io_data)); + memset(analog_data, 0, sizeof(analog_data)); + + return System16Exit(); +} + +static INT32 YBoardScan(INT32 nAction,INT32 *pnMin) +{ + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(misc_io_data); + SCAN_VAR(analog_data); + } + + return System16Scan(nAction, pnMin);; +} + +struct BurnDriver BurnDrvGforce2 = { + "gforce2", NULL, NULL, NULL, "1988", + "Galaxy Force 2\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, Gforce2RomInfo, Gforce2RomName, NULL, NULL, Gforce2InputInfo, Gforce2DIPInfo, + Gforce2Init, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGforce2j = { + "gforce2j", "gforce2", NULL, NULL, "1988", + "Galaxy Force 2 (Japan)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, Gforce2jRomInfo, Gforce2jRomName, NULL, NULL, Gforce2InputInfo, Gforce2DIPInfo, + Gforce2Init, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGforce2ja = { + "gforce2ja", "gforce2", NULL, NULL, "1988", + "Galaxy Force 2 (Japan, Rev A)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, Gforce2jaRomInfo, Gforce2jaRomName, NULL, NULL, Gforce2InputInfo, Gforce2DIPInfo, + Gforce2Init, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGloc = { + "gloc", NULL, NULL, NULL, "1990", + "G-LOC Air Battle (US)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, GlocRomInfo, GlocRomName, NULL, NULL, GlocInputInfo, GlocDIPInfo, + GlocInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGlocr360 = { + "glocr360", "gloc", NULL, NULL, "1990", + "G-LOC R360\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, Glocr360RomInfo, Glocr360RomName, NULL, NULL, Glocr360InputInfo, Glocr360DIPInfo, + Glocr360Init, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPdrift = { + "pdrift", NULL, NULL, NULL, "1988", + "Power Drift (World, Rev A)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMY, GBF_RACING, 0, + NULL, PdriftRomInfo, PdriftRomName, NULL, NULL, PdriftInputInfo, PdriftDIPInfo, + PdriftInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPdrifta = { + "pdrifta", "pdrift", NULL, NULL, "1988", + "Power Drift (World)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_RACING, 0, + NULL, PdriftaRomInfo, PdriftaRomName, NULL, NULL, PdriftInputInfo, PdriftDIPInfo, + PdriftInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPdrifte = { + "pdrifte", "pdrift", NULL, NULL, "1988", + "Power Drift (World, Earlier)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_RACING, 0, + NULL, PdrifteRomInfo, PdrifteRomName, NULL, NULL, PdriftInputInfo, PdrifteDIPInfo, + PdriftInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPdriftj = { + "pdriftj", "pdrift", NULL, NULL, "1988", + "Power Drift (Japan)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_RACING, 0, + NULL, PdriftjRomInfo, PdriftjRomName, NULL, NULL, PdriftInputInfo, PdriftjDIPInfo, + PdriftInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRchase = { + "rchase", NULL, NULL, NULL, "1991", + "Rail Chase (World)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, RchaseRomInfo, RchaseRomName, NULL, NULL, RchaseInputInfo, RchaseDIPInfo, + RchaseInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRchasej = { + "rchasej", "rchase", NULL, NULL, "1991", + "Rail Chase (Japan)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, RchasejRomInfo, RchasejRomName, NULL, NULL, RchaseInputInfo, RchaseDIPInfo, + RchaseInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvStrkfgtr = { + "strkfgtr", NULL, NULL, NULL, "1991", + "Strike Fighter (Japan)\0", NULL, "Sega", "Y-Board", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_SEGA_SYSTEMY, GBF_SHOOT, 0, + NULL, StrkfgtrRomInfo, StrkfgtrRomName, NULL, NULL, GlocInputInfo, StrkfgtrDIPInfo, + GlocInit, YBoardExit, YBoardFrame, NULL, YBoardScan, + NULL, 0x6000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/sega/fd1089.cpp b/src/burn/drivers/sega/fd1089.cpp new file mode 100644 index 00000000..467332ed --- /dev/null +++ b/src/burn/drivers/sega/fd1089.cpp @@ -0,0 +1,280 @@ +#include "sys16.h" +#include "bitswap.h" + +struct parameters +{ + INT32 xor1; + INT32 s7,s6,s5,s4,s3,s2,s1,s0; +}; + +static UINT8 basetable_fd1089[0x100] = +{ + 0x00,0x1c,0x76,0x6a,0x5e,0x42,0x24,0x38,0x4b,0x67,0xad,0x81,0xe9,0xc5,0x03,0x2f, + 0x45,0x69,0xaf,0x83,0xe7,0xcb,0x01,0x2d,0x02,0x1e,0x78,0x64,0x5c,0x40,0x2a,0x36, + 0x32,0x2e,0x44,0x58,0xe4,0xf8,0x9e,0x82,0x29,0x05,0xcf,0xe3,0x93,0xbf,0x79,0x55, + 0x3f,0x13,0xd5,0xf9,0x85,0xa9,0x63,0x4f,0xb8,0xa4,0xc2,0xde,0x6e,0x72,0x18,0x04, + 0x0c,0x10,0x7a,0x66,0xfc,0xe0,0x86,0x9a,0x47,0x6b,0xa1,0x8d,0xbb,0x97,0x51,0x7d, + 0x17,0x3b,0xfd,0xd1,0xeb,0xc7,0x0d,0x21,0xa0,0xbc,0xda,0xc6,0x50,0x4c,0x26,0x3a, + 0x3e,0x22,0x48,0x54,0x46,0x5a,0x3c,0x20,0x25,0x09,0xc3,0xef,0xc1,0xed,0x2b,0x07, + 0x6d,0x41,0x87,0xab,0x89,0xa5,0x6f,0x43,0x1a,0x06,0x60,0x7c,0x62,0x7e,0x14,0x08, + 0x0a,0x16,0x70,0x6c,0xdc,0xc0,0xaa,0xb6,0x4d,0x61,0xa7,0x8b,0xf7,0xdb,0x11,0x3d, + 0x5b,0x77,0xbd,0x91,0xe1,0xcd,0x0b,0x27,0x80,0x9c,0xf6,0xea,0x56,0x4a,0x2c,0x30, + 0xb0,0xac,0xca,0xd6,0xee,0xf2,0x98,0x84,0x37,0x1b,0xdd,0xf1,0x95,0xb9,0x73,0x5f, + 0x39,0x15,0xdf,0xf3,0x9b,0xb7,0x71,0x5d,0xb2,0xae,0xc4,0xd8,0xec,0xf0,0x96,0x8a, + 0xa8,0xb4,0xd2,0xce,0xd0,0xcc,0xa6,0xba,0x1f,0x33,0xf5,0xd9,0xfb,0xd7,0x1d,0x31, + 0x57,0x7b,0xb1,0x9d,0xb3,0x9f,0x59,0x75,0x8c,0x90,0xfa,0xe6,0xf4,0xe8,0x8e,0x92, + 0x12,0x0e,0x68,0x74,0xe2,0xfe,0x94,0x88,0x65,0x49,0x8f,0xa3,0x99,0xb5,0x7f,0x53, + 0x35,0x19,0xd3,0xff,0xc9,0xe5,0x23,0x0f,0xbe,0xa2,0xc8,0xd4,0x4e,0x52,0x34,0x28, +}; + + +/* common to FD1089A and FD1089B */ +static const struct parameters addr_params[16] = +{ + { 0x23, 6,4,5,7,3,0,1,2 }, + { 0x92, 2,5,3,6,7,1,0,4 }, + { 0xb8, 6,7,4,2,0,5,1,3 }, + { 0x74, 5,3,7,1,4,6,0,2 }, + { 0xcf, 7,4,1,0,6,2,3,5 }, + { 0xc4, 3,1,6,4,5,0,2,7 }, + { 0x51, 5,7,2,4,3,1,6,0 }, + { 0x14, 7,2,0,6,1,3,4,5 }, + { 0x7f, 3,5,6,0,2,1,7,4 }, + { 0x03, 2,3,4,0,6,7,5,1 }, + { 0x96, 3,1,7,5,2,4,6,0 }, + { 0x30, 7,6,2,3,0,4,5,1 }, + { 0xe2, 1,0,3,7,4,5,2,6 }, + { 0x72, 1,6,0,5,7,2,4,3 }, + { 0xf5, 0,4,1,2,6,5,7,3 }, + { 0x5b, 0,7,5,3,1,4,2,6 }, +}; + +static UINT8 rearrange_key(UINT8 table, INT32 opcode) +{ + if (opcode == 0) { + table ^= (1<<4); + table ^= (1<<5); + table ^= (1<<6); + + if (BIT(~table,3)) + table ^= (1<<1); + + if (BIT(table,6)) + table ^= (1<<7); + + table = BITSWAP08(table,1,0,6,4,3,5,2,7); + + if (BIT(table,6)) + table = BITSWAP08(table,7,6,2,4,5,3,1,0); + } else { + table ^= (1<<2); + table ^= (1<<3); + table ^= (1<<4); + + if (BIT(~table,3)) + table ^= (1<<5); + + if (BIT(~table,7)) + table ^= (1<<6); + + table = BITSWAP08(table,5,6,7,4,2,3,1,0); + + if (BIT(table,6)) + table = BITSWAP08(table,7,6,5,3,2,4,1,0); + } + + if (BIT(table,6)) { + if (BIT(table,5)) + table ^= (1<<4); + } else { + if (BIT(~table,4)) + table ^= (1<<5); + } + + return table; +} + +static INT32 decode_fd1089a(INT32 val,INT32 key,INT32 opcode) +{ + INT32 table; + + static const struct parameters data_params[16] = + { + { 0x55, 6,5,1,0,7,4,2,3 }, + { 0x94, 7,6,4,2,0,5,1,3 }, + { 0x8d, 1,4,2,3,0,6,7,5 }, + { 0x9a, 4,3,5,6,0,2,1,7 }, + { 0x72, 4,3,7,0,5,6,1,2 }, + { 0xff, 1,7,2,3,6,4,5,0 }, + { 0x06, 6,5,3,2,4,1,0,7 }, + { 0xc5, 3,5,1,4,2,7,0,6 }, + { 0xec, 4,7,5,1,6,0,2,3 }, + { 0x89, 3,5,0,6,1,2,7,4 }, + { 0x5c, 1,3,0,7,5,2,4,6 }, + { 0x3f, 7,3,0,2,4,6,1,5 }, + { 0x57, 6,4,7,2,1,5,3,0 }, + { 0xf7, 6,3,7,0,5,4,2,1 }, + { 0x3a, 6,1,3,2,7,4,5,0 }, + { 0xac, 1,6,3,5,0,7,4,2 }, + }; + const struct parameters *p; + const struct parameters *q; + INT32 family; + + /* special case - don't decrypt */ + if (key == 0x40) + return val; + + table = rearrange_key(key, opcode); + + p = &addr_params[table >> 4]; + val = BITSWAP08(val, p->s7,p->s6,p->s5,p->s4,p->s3,p->s2,p->s1,p->s0) ^ p->xor1; + + if (BIT(table,3)) val ^= 0x01; + if (BIT(table,0)) val ^= 0xb1; + if (opcode) val ^= 0x34; + if (opcode == 0) + if (BIT(table,6)) + val ^= 0x01; + + val = basetable_fd1089[val]; + + family = table & 0x07; + if (opcode == 0) + { + if (BIT(~table,6) & BIT(table,2)) family ^= 8; + if (BIT(table,4)) family ^= 8; + } + else + { + if (BIT(table,6) & BIT(table,2)) family ^= 8; + if (BIT(table,5)) family ^= 8; + } + + if (BIT(table,0)) + { + if (BIT(val,0)) val ^= 0xc0; + if (BIT(~val,6) ^ BIT(val,4)) + val = BITSWAP08(val, 7,6,5,4,1,0,2,3); + } + else + { + if (BIT(~val,6) ^ BIT(val,4)) + val = BITSWAP08(val, 7,6,5,4,0,1,3,2); + } + if (BIT(~val,6)) + val = BITSWAP08(val, 7,6,5,4,2,3,0,1); + + q = &data_params[family]; + + val ^= q->xor1; + val = BITSWAP08(val, q->s7,q->s6,q->s5,q->s4,q->s3,q->s2,q->s1,q->s0); + + return val; +} + +static INT32 decode_fd1089b(INT32 val,INT32 key,INT32 opcode) +{ + INT32 table; + INT32 xor1; + + const struct parameters *p; + + /* special case - don't decrypt */ + if (key == 0x40) + return val; + + table = rearrange_key(key, opcode); + + p = &addr_params[table >> 4]; + val = BITSWAP08(val, p->s7,p->s6,p->s5,p->s4,p->s3,p->s2,p->s1,p->s0) ^ p->xor1; + + if (BIT(table,3)) val ^= 0x01; + if (BIT(table,0)) val ^= 0xb1; + if (opcode) val ^= 0x34; + if (opcode == 0) + if (BIT(table,6)) + val ^= 0x01; + + val = basetable_fd1089[val]; + + xor1 = 0; + if (opcode == 0) + { + if (BIT(~table,6) & BIT(table,2)) xor1 ^= 0x01; + if (BIT(table,4)) xor1 ^= 0x01; + } + else + { + if (BIT(table,6) & BIT(table,2)) xor1 ^= 0x01; + if (BIT(table,5)) xor1 ^= 0x01; + } + + val ^= xor1; + + if (BIT(table,2)) + { + val = BITSWAP08(val, 7,6,5,4,1,0,3,2); + + if (BIT(table,0) ^ BIT(table,1)) + val = BITSWAP08(val, 7,6,5,4,0,1,3,2); + } + else + { + val = BITSWAP08(val, 7,6,5,4,3,2,0,1); + + if (BIT(table,0) ^ BIT(table,1)) + val = BITSWAP08(val, 7,6,5,4,1,0,2,3); + } + + return val; +} + +static UINT16 fd1089_decrypt(/*offs_t*/INT32 addr,UINT16 val,const UINT8 *key,INT32 opcode) +{ + INT32 tbl_num,src; + + /* pick the translation table from bits ff022a of the address */ + tbl_num = ((addr & 0x000002) >> 1) | + ((addr & 0x000008) >> 2) | + ((addr & 0x000020) >> 3) | + ((addr & 0x000200) >> 6) | + ((addr & 0xff0000) >> 12); + + src = ((val & 0x0008) >> 3) | + ((val & 0x0040) >> 5) | + ((val & 0xfc00) >> 8); + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1089A_ENC) src = decode_fd1089a(src,key[tbl_num + (1^opcode) * 0x1000],opcode); + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1089B_ENC) src = decode_fd1089b(src,key[tbl_num + (1^opcode) * 0x1000],opcode); + + src = ((src & 0x01) << 3) | + ((src & 0x02) << 5) | + ((src & 0xfc) << 8); + + return (val & ~0xfc48) | src; +} + +static void sys16_decrypt(const UINT8 *key) +{ + UINT16 *rom = (UINT16 *)System16Rom; + INT32 size = 0x100000; + INT32 A; + UINT16 *decrypted = (UINT16 *)System16Code; + + for (A = 0;A < size;A+=2) + { + UINT16 src = rom[A / 2]; + + /* decode the opcodes */ + decrypted[A/2] = fd1089_decrypt(A,src,key,1); + + /* decode the data */ + rom[A/2] = fd1089_decrypt(A,src,key,0); + } +} + +void FD1089Decrypt() +{ + sys16_decrypt(System16Key); +} diff --git a/src/burn/drivers/sega/fd1094.cpp b/src/burn/drivers/sega/fd1094.cpp new file mode 100644 index 00000000..7492e2d3 --- /dev/null +++ b/src/burn/drivers/sega/fd1094.cpp @@ -0,0 +1,531 @@ +/***************************************************************************** + +FD1094 encryption + + +The FD1094 is a custom CPU based on the 68000, which runs encrypted code. +The decryption key is stored in 8KB of battery-backed RAM; when the battery +dies, the CPU can no longer decrypt the program code and the game stops +working (though the CPU itself still works - it just uses a wrong decryption +key). + +Being a 68000, the encryption works on 16-bit words. Only words fetched from +program space are decrypted; words fetched from data space are not affected. + +The decryption can logically be split in two parts. The first part consists +of a series of conditional XORs and bitswaps, controlled by the decryption +key, which will be described in the next paragraph. The second part does a +couple more XORs which don't depend on the key, followed by the replacement +of several values with FFFF. This last step is done to prevent usage of any +PC-relative opcode, which would easily allow an intruder to dump decrypted +values from program space. The FFFF replacement may affect either ~300 values +or ~5000, depending on the decryption key. + +The main part of the decryption can itself be subdivided in four consecutive +steps. The first one is executed only if bit 15 of the encrypted value is 1; +the second one only if bit 14 of the _current_ value is 1; the third one only +if bit 13 of the current value is 1; the fourth one is always executed. The +first three steps consist of a few conditional XORs and a final conditional +bitswap; the fourth one consists of a fixed XOR and a few conditional +bitswaps. There is, however, a special case: if bits 15, 14 and 13 of the +encrypted value are all 0, none of the above steps are executed, replaced by +a single fixed bitswap. + +In the end, the decryption of a value at a given address is controlled by 32 +boolean variables; 8 of them change at every address (repeating after 0x2000 +words), and constitute the main key which is stored in the battery-backed +RAM; the other 24 don't change with the address, and depend solely on bytes +1, 2, and 3 of the battery-backed RAM, modified by the "state" which the CPU +is in. + +The CPU can be in one of 256 possible states. The 8 bits of the state modify +the 24 bits of the global key in a fixed way, which isn't affected by the +battery-backed RAM. +On reset, the CPU goes in state 0x00. The state can then be modified by the +program, executing the instruction +CMPI.L #$00xxFFFF, D0 +where xx is the state. +When an interrupt happens, the CPU enters "irq mode", forcing a specific +state, which is stored in byte 0 of the battery-backed RAM. Irq mode can also +be selected by the program with the instruction +CMPI.L #$0200FFFF, D0 +When RTE is executed, the CPU leaves irq mode, restoring the previous state. +This can also be done by the program with the instruction +CMPI.L #$0300FFFF, D0 + +Since bytes 0-3 of the battery-backed RAM are used to store the irq state and +the global key, they have a double use: this one, and the normal 8-bit key +that changes at every address. To prevent that double use, the CPU fetches +the 8-bit key from a different place when decrypting words 0-3, but this only +happens after wrapping around at least once; when decrypting the first four +words of memory, which correspond the the initial SP and initial PC vectors, +the 8-bit key is taken from bytes 0-3 of RAM. Instead, when fetching the +vectors, the global key is handled differently, to prevent double use of +those bytes. But this special handling of the global key doesn't apply to +normal operations: reading words 1-3 from program space results in bytes 1-3 +of RAM being used both for the 8-bit key and for the 24-bit global key. + + + +There is still uncertainty about the assignment of two global key bits. + +key[1] +------ +key_0b invert; \ bits 7,5 always 1 for now (but 0 in a bad CPU) +global_xor0; / +key_5b invert; bit 6 +key_2b invert; bit 4 +key_1b invert; bit 3 always 1 for now (but 0 in a bad CPU) +global_xor1; bit 2 +key_0c invert; bit 1 +global_swap2; bit 0 + +key[2] +------ +key_1a invert; bit 7 always 1 for now (but 0 in a bad CPU) +key_6b invert; bit 6 always 1 for now (but 0 in a bad CPU) +global_swap0a; bit 5 +key_7a invert; bit 4 +key_4a invert; bit 3 +global_swap0b; bit 2 +key_6a invert; bit 1 +key_3a invert; bit 0 + +key[3] +------ +key_2a invert; bit 7 always 1 for now (but 0 in a bad CPU) +global_swap3; bit 6 always 1 for now (but 0 in a bad CPU) +key_5a_invert; bit 5 +global_swap1; bit 4 +key_3b invert; bit 3 +global_swap4; bit 2 +key_0a invert; bit 1 +key_4b invert; bit 0 + + +summary of global keys: +----------------------- + ..... .. .. +0049 10101000 11110101 11100011 +0050 10101000 11110101 11100011 +0053 11111111 11111111 11111111 +0056 10101111 11111110 11101000 +0058-02C 10101111 11110101 11111000 +0058-03D 10101111 11110100 11100100 +0058-05C 10101110 11111001 11110010 +0058-09D 10101100 11111001 11100101 +0068 10101111 11111001 11110101 +0070 10101111 11110111 11111001 +0080 10101111 11110111 11100101 +0084 10101111 11110101 11100000 +0085 10101111 11110100 11110111 +0087 10101111 11110100 11110111 +0089 10101111 11110100 11100010 +0090 10101111 11111110 11100100 +0091 10101111 11110100 11100100 +0092 10101111 11110100 11100011 +0093 10101111 11110100 11100010 +0093A 11111101 11110110 11101110 +0096 10101111 11110100 11101010 +0102 10101111 11111101 11111100 +0110 10101110 11111100 11100010 +0115 11111011 11111010 11110100 +0116 11111100 11100001 11110110 +0118 10101110 11111100 11111000 +0120 10101110 11111100 11100010 +0121 10101110 11111100 11100010 +0122 10101110 11111011 11111011 +0124A 11111001 11101010 11110100 +0125A 11111001 11110000 11101111 +0126 11111010 11100011 11111110 +0126A 11111001 11101111 11110000 +0127A 10101110 11111000 11111001 +0128 11111111 11100011 11101011 +0129 11111111 11100011 11101011 +0130 11111111 11100011 11101100 +0134 10101110 11110100 11100001 +0136 10101110 11110100 11100010 +0139 11111100 11100110 11110000 +0142 11111110 11100111 11101110 +0143 11111101 11111101 11101101 +0144 11111101 11101000 11101101 +0146 11111011 11100101 11101110 +0147 11111011 11110001 11110001 +0148 11111011 11100101 11110000 +0153 11111011 11110101 11110001 +0157 11111000 11101011 11110101 +0158 11111000 11110000 11110000 +0159 11111000 11101011 11110101 +0162 11111110 11110001 11110000 +0163 11111110 11110010 11110000 +0165 10101101 11110100 11100110 +0166 10101101 11110100 11101110 +0169B 11111001 11011100 11011111 +0175 10101100 11111100 11101001 +0176 10101100 11111100 11110001 +0179A 11111001 11001000 11101110 +0180 11111100 11001010 11111111 +0181A 11111001 11001000 11101110 +0184 11111000 11110011 11101111 +0186 10101100 11111000 11111110 +0196 11101011 11110011 11101001 +0197A 10101011 11111001 11101100 +5023 11111011 11101101 11111010 + ..... .. .. +unknown 11111111 11110110 10111110 (Shinobi 16A, part no. unreadable, could be dead) +dead 00001111 00001111 00001111 (Alien Storm CPU with no battery) +bad 11100000 10101011 10111001 (flaky 317-0049) + +*****************************************************************************/ + +#include "driver.h" +#include "fd1094.h" +#include "bitswap.h" + +#define BIT(x,n) (((x)>>(n))&1) +#define FALSE 0 +#define TRUE 1 +#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) + +/* +317-0162 CPU also needs to mask: +0x107a, +0x127a, +0x147a, +0x167a, +0x187a, +0x1a7a, +0x1c7a, +0x1e7a, +this only happens with 317-0162 so far; I assume it is a fault in the CPU. +*/ +static const UINT16 masked_opcodes[] = +{ + 0x013a,0x033a,0x053a,0x073a,0x083a,0x093a,0x0b3a,0x0d3a,0x0f3a, + + 0x103a, 0x10ba,0x10fa, 0x113a,0x117a,0x11ba,0x11fa, + 0x123a, 0x12ba,0x12fa, 0x133a,0x137a,0x13ba,0x13fa, + 0x143a, 0x14ba,0x14fa, 0x153a,0x157a,0x15ba, + 0x163a, 0x16ba,0x16fa, 0x173a,0x177a,0x17ba, + 0x183a, 0x18ba,0x18fa, 0x193a,0x197a,0x19ba, + 0x1a3a, 0x1aba,0x1afa, 0x1b3a,0x1b7a,0x1bba, + 0x1c3a, 0x1cba,0x1cfa, 0x1d3a,0x1d7a,0x1dba, + 0x1e3a, 0x1eba,0x1efa, 0x1f3a,0x1f7a,0x1fba, + + 0x203a,0x207a,0x20ba,0x20fa, 0x213a,0x217a,0x21ba,0x21fa, + 0x223a,0x227a,0x22ba,0x22fa, 0x233a,0x237a,0x23ba,0x23fa, + 0x243a,0x247a,0x24ba,0x24fa, 0x253a,0x257a,0x25ba, + 0x263a,0x267a,0x26ba,0x26fa, 0x273a,0x277a,0x27ba, + 0x283a,0x287a,0x28ba,0x28fa, 0x293a,0x297a,0x29ba, + 0x2a3a,0x2a7a,0x2aba,0x2afa, 0x2b3a,0x2b7a,0x2bba, + 0x2c3a,0x2c7a,0x2cba,0x2cfa, 0x2d3a,0x2d7a,0x2dba, + 0x2e3a,0x2e7a,0x2eba,0x2efa, 0x2f3a,0x2f7a,0x2fba, + + 0x303a,0x307a,0x30ba,0x30fa, 0x313a,0x317a,0x31ba,0x31fa, + 0x323a,0x327a,0x32ba,0x32fa, 0x333a,0x337a,0x33ba,0x33fa, + 0x343a,0x347a,0x34ba,0x34fa, 0x353a,0x357a,0x35ba, + 0x363a,0x367a,0x36ba,0x36fa, 0x373a,0x377a,0x37ba, + 0x383a,0x387a,0x38ba,0x38fa, 0x393a,0x397a,0x39ba, + 0x3a3a,0x3a7a,0x3aba,0x3afa, 0x3b3a,0x3b7a,0x3bba, + 0x3c3a,0x3c7a,0x3cba,0x3cfa, 0x3d3a,0x3d7a,0x3dba, + 0x3e3a,0x3e7a,0x3eba,0x3efa, 0x3f3a,0x3f7a,0x3fba, + + 0x41ba,0x43ba,0x44fa,0x45ba,0x46fa,0x47ba,0x49ba,0x4bba,0x4cba,0x4cfa,0x4dba,0x4fba, + + 0x803a,0x807a,0x80ba,0x80fa, 0x81fa, + 0x823a,0x827a,0x82ba,0x82fa, 0x83fa, + 0x843a,0x847a,0x84ba,0x84fa, 0x85fa, + 0x863a,0x867a,0x86ba,0x86fa, 0x87fa, + 0x883a,0x887a,0x88ba,0x88fa, 0x89fa, + 0x8a3a,0x8a7a,0x8aba,0x8afa, 0x8bfa, + 0x8c3a,0x8c7a,0x8cba,0x8cfa, 0x8dfa, + 0x8e3a,0x8e7a,0x8eba,0x8efa, 0x8ffa, + + 0x903a,0x907a,0x90ba,0x90fa, 0x91fa, + 0x923a,0x927a,0x92ba,0x92fa, 0x93fa, + 0x943a,0x947a,0x94ba,0x94fa, 0x95fa, + 0x963a,0x967a,0x96ba,0x96fa, 0x97fa, + 0x983a,0x987a,0x98ba,0x98fa, 0x99fa, + 0x9a3a,0x9a7a,0x9aba,0x9afa, 0x9bfa, + 0x9c3a,0x9c7a,0x9cba,0x9cfa, 0x9dfa, + 0x9e3a,0x9e7a,0x9eba,0x9efa, 0x9ffa, + + 0xb03a,0xb07a,0xb0ba,0xb0fa, 0xb1fa, + 0xb23a,0xb27a,0xb2ba,0xb2fa, 0xb3fa, + 0xb43a,0xb47a,0xb4ba,0xb4fa, 0xb5fa, + 0xb63a,0xb67a,0xb6ba,0xb6fa, 0xb7fa, + 0xb83a,0xb87a,0xb8ba,0xb8fa, 0xb9fa, + 0xba3a,0xba7a,0xbaba,0xbafa, 0xbbfa, + 0xbc3a,0xbc7a,0xbcba,0xbcfa, 0xbdfa, + 0xbe3a,0xbe7a,0xbeba,0xbefa, 0xbffa, + + 0xc03a,0xc07a,0xc0ba,0xc0fa, 0xc1fa, + 0xc23a,0xc27a,0xc2ba,0xc2fa, 0xc3fa, + 0xc43a,0xc47a,0xc4ba,0xc4fa, 0xc5fa, + 0xc63a,0xc67a,0xc6ba,0xc6fa, 0xc7fa, + 0xc83a,0xc87a,0xc8ba,0xc8fa, 0xc9fa, + 0xca3a,0xca7a,0xcaba,0xcafa, 0xcbfa, + 0xcc3a,0xcc7a,0xccba,0xccfa, 0xcdfa, + 0xce3a,0xce7a,0xceba,0xcefa, 0xcffa, + + 0xd03a,0xd07a,0xd0ba,0xd0fa, 0xd1fa, + 0xd23a,0xd27a,0xd2ba,0xd2fa, 0xd3fa, + 0xd43a,0xd47a,0xd4ba,0xd4fa, 0xd5fa, + 0xd63a,0xd67a,0xd6ba,0xd6fa, 0xd7fa, + 0xd83a,0xd87a,0xd8ba,0xd8fa, 0xd9fa, + 0xda3a,0xda7a,0xdaba,0xdafa, 0xdbfa, + 0xdc3a,0xdc7a,0xdcba,0xdcfa, 0xddfa, + 0xde3a,0xde7a,0xdeba,0xdefa, 0xdffa +}; + +static UINT8 masked_opcodes_lookup[2][65536/8/2]; +static UINT8 masked_opcodes_created = FALSE; + +static INT32 final_decrypt(INT32 i,INT32 moreffff) +{ + UINT32 j; + + /* final "obfuscation": invert bits 7 and 14 following a fixed pattern */ + INT32 dec = i; + if ((i & 0xf080) == 0x8000) dec ^= 0x0080; + if ((i & 0xf080) == 0xc080) dec ^= 0x0080; + if ((i & 0xb080) == 0x8000) dec ^= 0x4000; + if ((i & 0xb100) == 0x0000) dec ^= 0x4000; + + /* mask out opcodes doing PC-relative addressing, replace them with FFFF */ + if (!masked_opcodes_created) + { + masked_opcodes_created = TRUE; + for (j = 0; j < ARRAY_LENGTH(masked_opcodes); j++) + { + UINT16 opcode = masked_opcodes[j]; + masked_opcodes_lookup[0][opcode >> 4] |= 1 << ((opcode >> 1) & 7); + masked_opcodes_lookup[1][opcode >> 4] |= 1 << ((opcode >> 1) & 7); + } + for (j = 0; j < 65536; j += 2) + { + if ((j & 0xff80) == 0x4e80 || (j & 0xf0f8) == 0x50c8 || (j & 0xf000) == 0x6000) + masked_opcodes_lookup[1][j >> 4] |= 1 << ((j >> 1) & 7); + } + } + + if ((masked_opcodes_lookup[moreffff][dec >> 4] >> ((dec >> 1) & 7)) & 1) + dec = 0xffff; + + return dec; +} + + +/* note: address is the word offset (physical address / 2) */ +static INT32 decode(INT32 address,INT32 val,UINT8 *main_key,INT32 gkey1,INT32 gkey2,INT32 gkey3,INT32 vector_fetch) +{ + INT32 mainkey,key_F,key_6a,key_7a,key_6b; + INT32 key_0a,key_0b,key_0c; + INT32 key_1a,key_1b,key_2a,key_2b,key_3a,key_3b,key_4a,key_4b,key_5a,key_5b; + INT32 global_xor0,global_xor1; + INT32 global_swap0a,global_swap1,global_swap2,global_swap3,global_swap4; + INT32 global_swap0b; + + + /* for address xx0000-xx0006 (but only if >= 000008), use key xx2000-xx2006 */ + if ((address & 0x0ffc) == 0 && address >= 4) + mainkey = main_key[(address & 0x1fff) | 0x1000]; + else + mainkey = main_key[address & 0x1fff]; + + if (address & 0x1000) key_F = BIT(mainkey,7); + else key_F = BIT(mainkey,6); + + /* the CPU has been verified to produce different results when fetching opcodes + from 0000-0006 than when fetching the inital SP and PC on reset. */ + if (vector_fetch) + { + if (address <= 3) gkey3 = 0x00; // supposed to always be the case + if (address <= 2) gkey2 = 0x00; + if (address <= 1) gkey1 = 0x00; + if (address <= 1) key_F = 0; + } + + global_xor0 = 1^BIT(gkey1,5); // could be bit 7 + global_xor1 = 1^BIT(gkey1,2); + global_swap2 = 1^BIT(gkey1,0); + + global_swap0a = 1^BIT(gkey2,5); + global_swap0b = 1^BIT(gkey2,2); + + global_swap3 = 1^BIT(gkey3,6); + global_swap1 = 1^BIT(gkey3,4); + global_swap4 = 1^BIT(gkey3,2); + + key_0a = BIT(mainkey,0) ^ BIT(gkey3,1); + key_0b = BIT(mainkey,0) ^ BIT(gkey1,7); // could be bit 5 + key_0c = BIT(mainkey,0) ^ BIT(gkey1,1); + + key_1a = BIT(mainkey,1) ^ BIT(gkey2,7); + key_1b = BIT(mainkey,1) ^ BIT(gkey1,3); + + key_2a = BIT(mainkey,2) ^ BIT(gkey3,7); + key_2b = BIT(mainkey,2) ^ BIT(gkey1,4); + + key_3a = BIT(mainkey,3) ^ BIT(gkey2,0); + key_3b = BIT(mainkey,3) ^ BIT(gkey3,3); + + key_4a = BIT(mainkey,4) ^ BIT(gkey2,3); + key_4b = BIT(mainkey,4) ^ BIT(gkey3,0); + + key_5a = BIT(mainkey,5) ^ BIT(gkey3,5); + key_5b = BIT(mainkey,5) ^ BIT(gkey1,6); + + key_6a = BIT(mainkey,6) ^ BIT(gkey2,1); + key_6b = BIT(mainkey,6) ^ BIT(gkey2,6); + + key_7a = BIT(mainkey,7) ^ BIT(gkey2,4); + + + if ((val & 0xe000) == 0x0000) + val = BITSWAP16(val, 12,15,14,13,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + else + { + if (val & 0x8000) + { + if (!global_xor1) if (~val & 0x0008) val ^= 0x2410; // 13,10,4 + if (~val & 0x0004) val ^= 0x0022; // 5,1 + if (!key_1b) if (~val & 0x1000) val ^= 0x0848; // 11,6,3 + if (!global_swap2) if (!key_0c) val ^= 0x4101; // 14,8,0 + if (!key_2b) val = BITSWAP16(val, 15,14,13, 9,11,10,12, 8, 2, 6, 5, 4, 3, 7, 1, 0); // 12,9,7,2 + + val = 0x6561 ^ BITSWAP16(val, 15, 9,10,13, 3,12, 0,14, 6, 5, 2,11, 8, 1, 4, 7); + } + if (val & 0x4000) + { + if (!global_xor0) if (val & 0x0800) val ^= 0x9048; // 15,12,6,3 + if (!key_3a) if (val & 0x0004) val ^= 0x0202; // 9,1 + if (!key_6a) if (val & 0x0400) val ^= 0x0004; // 2 + if (!key_5b) if (!key_0b) val ^= 0x08a1; // 11,7,5,0 + if (!global_swap0b) val = BITSWAP16(val, 15,14,10,12,11,13, 9, 4, 7, 6, 5, 8, 3, 2, 1, 0); // 13,10,8,4 + + val = 0x3523 ^ BITSWAP16(val, 13,14, 7, 0, 8, 6, 4, 2, 1,15, 3,11,12,10, 5, 9); + } + if (val & 0x2000) + { + if (!key_4a) if (val & 0x0100) val ^= 0x4210; // 14,9,4 + if (!key_1a) if (val & 0x0040) val ^= 0x0080; // 7 + if (!key_7a) if (val & 0x0001) val ^= 0x110a; // 12,8,3,1 + if (!key_4b) if (!key_0a) val ^= 0x0040; // 6 + if (!global_swap0a) if (!key_6b) val ^= 0x0404; // 10,2 + if (!key_5b) val = BITSWAP16(val, 0,14,13,12,15,10, 9, 8, 7, 6,11, 4, 3, 2, 1, 5); // 15,11,5,0 + + val = 0x99a5 ^ BITSWAP16(val, 10, 2,13, 7, 8, 0, 3,14, 6,15, 1,11, 9, 4, 5,12); + } + + val = 0x87ff ^ BITSWAP16(val, 5,15,13,14, 6, 0, 9,10, 4,11, 1, 2,12, 3, 7, 8); + + if (!global_swap4) val = BITSWAP16(val, 6,14,13,12,11,10, 9, 5, 7,15, 8, 4, 3, 2, 1, 0); // 15-6, 8-5 + if (!global_swap3) val = BITSWAP16(val, 15,12,14,13,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 12-13-14 + if (!global_swap2) val = BITSWAP16(val, 15,14,13,12,11, 2, 9, 8,10, 6, 5, 4, 3, 0, 1, 7); // 10-2-0-7 + if (!key_3b) val = BITSWAP16(val, 15,14,13,12,11,10, 4, 8, 7, 6, 5, 9, 1, 2, 3, 0); // 9-4, 3-1 + + if (!key_2a) val = BITSWAP16(val, 15,12,13,14,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 14-12 + if (!global_swap1) val = BITSWAP16(val, 15,14,13,12, 9, 8,11,10, 7, 6, 5, 4, 3, 2, 1, 0); // 11...8 + if (!key_5a) val = BITSWAP16(val, 15,14,13,12,11,10, 9, 8, 4, 5, 7, 6, 3, 2, 1, 0); // 7...4 + if (!global_swap0a) val = BITSWAP16(val, 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 0, 3, 2, 1); // 3...0 + } + + return final_decrypt(val,key_F); +} + + +static INT32 global_key1,global_key2,global_key3; + +INT32 fd1094_decode(INT32 address,INT32 val,UINT8 *key,INT32 vector_fetch) +{ + if (!key) return 0; + + return decode(address,val,key,global_key1,global_key2,global_key3,vector_fetch); +} + +INT32 fd1094_set_state(UINT8 *key,INT32 state) +{ + static INT32 selected_state,irq_mode; + + if (!key) return 0; + + switch (state & 0x300) + { + case 0x0000: // 0x00xx: select state xx + selected_state = state & 0xff; + break; + + case FD1094_STATE_RESET: // 0x01xx: select state xx and exit irq mode + selected_state = state & 0xff; + irq_mode = 0; + break; + + case FD1094_STATE_IRQ: // 0x02xx: enter irq mode + irq_mode = 1; + break; + + case FD1094_STATE_RTE: // 0x03xx: exit irq mode + irq_mode = 0; + break; + } + + if (irq_mode) + state = key[0]; + else + state = selected_state; + + global_key1 = key[1]; + global_key2 = key[2]; + global_key3 = key[3]; + + if (state & 0x0001) + { + global_key1 ^= 0x04; // global_xor1 + global_key2 ^= 0x80; // key_1a invert + global_key3 ^= 0x80; // key_2a invert + } + if (state & 0x0002) + { + global_key1 ^= 0x01; // global_swap2 + global_key2 ^= 0x10; // key_7a invert + global_key3 ^= 0x01; // key_4b invert + } + if (state & 0x0004) + { + global_key1 ^= 0x80; // key_0b invert - could be 0x20 + global_key2 ^= 0x40; // key_6b invert + global_key3 ^= 0x04; // global_swap4 + } + if (state & 0x0008) + { + global_key1 ^= 0x20; // global_xor0 - could be 0x80 + global_key2 ^= 0x02; // key_6a invert + global_key3 ^= 0x20; // key_5a invert + } + if (state & 0x0010) + { + global_key1 ^= 0x02; // key_0c invert + global_key1 ^= 0x40; // key_5b invert + global_key2 ^= 0x08; // key_4a invert + } + if (state & 0x0020) + { + global_key1 ^= 0x08; // key_1b invert + global_key3 ^= 0x08; // key_3b invert + global_key3 ^= 0x10; // global_swap1 + } + if (state & 0x0040) + { + global_key1 ^= 0x10; // key_2b invert + global_key2 ^= 0x20; // global_swap0a + global_key2 ^= 0x04; // global_swap0b + } + if (state & 0x0080) + { + global_key2 ^= 0x01; // key_3a invert + global_key3 ^= 0x02; // key_0a invert + global_key3 ^= 0x40; // global_swap3 + } + return state & 0xff; +} diff --git a/src/burn/drivers/sega/fd1094.h b/src/burn/drivers/sega/fd1094.h new file mode 100644 index 00000000..6a4f1ae1 --- /dev/null +++ b/src/burn/drivers/sega/fd1094.h @@ -0,0 +1,6 @@ +#define FD1094_STATE_RESET 0x0100 +#define FD1094_STATE_IRQ 0x0200 +#define FD1094_STATE_RTE 0x0300 + +INT32 fd1094_set_state(UINT8 *key, INT32 state); +INT32 fd1094_decode(INT32 address, INT32 val, UINT8 *key, INT32 vector_fetch); diff --git a/src/burn/drivers/sega/genesis_vid.cpp b/src/burn/drivers/sega/genesis_vid.cpp new file mode 100644 index 00000000..fffa915a --- /dev/null +++ b/src/burn/drivers/sega/genesis_vid.cpp @@ -0,0 +1,907 @@ +#include "genesis_vid.h" +#include "burnint.h" + +INT32 GenesisScreenNumber; +UINT32 *GenesisPalette = NULL; +UINT16 GenesisPaletteBase; +UINT8 VdpBgColour; + +UINT8 *VdpVRAM = NULL; +UINT8 *VdpVSRAM = NULL; +UINT16 *VdpTransLookup = NULL; +UINT8 GenesisVdpRegs[32]; +UINT16 GenesisBgPalLookup[4]; +UINT16 GenesisSpPalLookup[4]; +UINT32 VdpScrollABase; +UINT32 VdpScrollBBase; +UINT32 VdpWindowBase; +UINT32 VdpSpriteBase; + +INT32 VdpHScrollMask; +UINT32 VdpHScrollSize; +UINT32 VdpHScrollBase; +UINT8 VdpVScrollMode; + +UINT8 VdpWindowWidth; +UINT8 VdpScrollWidth; +UINT8 VdpScrollHeight; +UINT8 VdpWindowRight; +UINT8 VdpWindowDown; +UINT32 VdpWindowHPos; +UINT32 VdpWindowVPos; + +UINT8 VdpCmdPart; +UINT8 VdpCode; +UINT32 VdpAddress; + +#define VRAM_SIZE 0x10000 +#define VRAM_MASK (VRAM_SIZE - 1) +#define VSRAM_SIZE 0x80 +#define VSRAM_MASK (VSRAM_SIZE - 1) +#define CRAM_SIZE 0x40 + +#define VDP_VRAM_BYTE(x) (VdpVRAM[(x) & VRAM_MASK]) +#define VDP_VSRAM_BYTE(x) (VdpVSRAM[(x) & VSRAM_MASK]) +#define VDP_VRAM_WORD(x) ((VDP_VRAM_BYTE(x) << 8) | VDP_VRAM_BYTE((x) + 1)) +#define VDP_VSRAM_WORD(x) ((VDP_VSRAM_BYTE(x) << 8) | VDP_VSRAM_BYTE((x) + 1)) + +#define EXTRACT_PIXEL(x,i) (((x) >> (((i) ^ 1) * 4)) & 0x0f) + +static void VdpRegisterWrite(INT32 d, INT32 /*vBlank*/) +{ + UINT8 RegNum = (d & 0x1f00) >> 8; + UINT8 RegDat = d & 0x00ff; + + GenesisVdpRegs[RegNum] = RegDat; + + switch (RegNum) { + case 0x01: { + // Video Modes + return; + } + + case 0x02: { + // Scroll A Name Table Base + VdpScrollABase = (RegDat & 0x38) << 10; + return; + } + + case 0x03: { + // Window Name Table Base + VdpWindowBase = (RegDat & 0x3e) << 10; + return; + } + + case 0x04: { + // Scroll B Name Table Base + VdpScrollBBase = (RegDat & 0x07) << 13; + return; + } + + case 0x05: { + // Sprite Table Base + VdpSpriteBase = (RegDat & 0x7e) << 9; + return; + } + + case 0x07: { + // BG Colour + VdpBgColour = RegDat & 0x3f; + return; + } + + case 0x0b: { + // Scroll Modes + static const UINT16 MaskTable[4] = { 0x000, 0x007, 0xff8, 0xfff }; + VdpVScrollMode = (RegDat & 0x04) >> 2; + VdpHScrollMask = MaskTable[RegDat & 3]; + VdpHScrollSize = 4 * ((VdpHScrollMask < 224) ? (VdpHScrollMask + 1) : 224); + return; + } + + case 0x0c: { + // Video Modes + switch (RegDat & 0x81) { + case 0x00: { + // 32 cell + VdpWindowWidth = 32; + return; + } + + case 0x01: { + // 40 cell corrupted + VdpWindowWidth = 64; + return; + } + + case 0x80: { + // illegal + VdpWindowWidth = 64; + return; + } + + case 0x81: { + // 40 cell + VdpWindowWidth = 64; + return; + } + } + return; + } + + case 0x0d: { + // H Scroll Base + VdpHScrollBase = (RegDat & 0x3f) << 10; + return; + } + + case 0x10: { + // Scroll Size + static const UINT8 SizeTable[4] = { 32, 64, 128, 128 }; + VdpScrollWidth = SizeTable[RegDat & 0x03]; + VdpScrollHeight = SizeTable[(RegDat & 0x30) >> 4]; + return; + } + + case 0x11: { + // Window H Pos + VdpWindowRight = RegDat & 0x80; + VdpWindowHPos = (RegDat & 0x1f) << 4; + return; + } + + case 012: { + // Window V Pos + VdpWindowDown = RegDat & 0x80; + VdpWindowVPos = (RegDat & 0x1f) << 3; + return; + } + } +} + +static UINT16 VDPDataRead() +{ + INT32 read = 0; + + VdpCmdPart = 0; + + switch (VdpCode & 0xf) { + case 0x00: { + read = VDP_VRAM_WORD(VdpAddress & ~1); + break; + } + + case 0x04: { + read = VDP_VSRAM_WORD(VdpAddress & ~1); + break; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Genesis VDP Data Read %x\n"), VdpCode); +// } + } + + VdpAddress += GenesisVdpRegs[15]; + return read; +} + +static UINT16 VDPControlRead() +{ + INT32 status = 0x3600; + + VdpCmdPart = 0; + + // If Vblank status |= 0x8 + // if Hblank status |= 0x4 + + return status; +} + +UINT16 GenesisVDPRead(UINT32 offset) +{ + switch(offset) { + case 0x00: + case 0x01: { + return VDPDataRead(); + } + + case 0x02: + case 0x03: { + return VDPControlRead(); + } + } + +// bprintf(PRINT_NORMAL, _T("Genesis VDP Read %x\n"), offset); + + return 0; +} + +static void VDPControlWrite(UINT16 data) +{ + if (!VdpCmdPart) { + if ((data & 0xc000) == 0x8000) { + VdpRegisterWrite(data, 0); + } else { + VdpCode = (VdpCode & 0x3c) | ((data >> 14) & 0x03); + VdpAddress = (VdpAddress & 0xc000) | (data & 0x3fff); + VdpCmdPart = 1; + } + } else { + VdpCode = (VdpCode & 0x03) | ((data >> 2) & 0x3c); + VdpAddress = (VdpAddress & 0x3fff) | ((data << 14) & 0xc000); + VdpCmdPart = 0; + // DMA Stuff here + } +} + +inline static UINT8 pal3bit(UINT8 bits) +{ + bits &= 7; + return (bits << 5) | (bits << 2) | (bits >> 1); +} + +static void VDPDataWrite(UINT16 data) +{ + VdpCmdPart = 0; + + // DMA Stuff here + + switch (VdpCode & 0xf) { + case 0x01: { + if (VdpAddress & 1) data = ((data & 0xff) << 8) | ((data >> 8) & 0xff); + VDP_VRAM_BYTE(VdpAddress & ~1) = data >> 8; + VDP_VRAM_BYTE(VdpAddress | 1 ) = data; + break; + } + + case 0x03: { + int offset = (VdpAddress >> 1) % CRAM_SIZE; + //palette_set_color(Machine, offset + genesis_palette_base, pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9)); + //System16Palette[offset + 0x1800 /*GenesisPaletteBase*/] = BurnHighCol(pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9), 0); + GenesisPalette[offset + GenesisPaletteBase] = BurnHighCol(pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9), 0); + break; + } + + case 0x05: { + if (VdpAddress & 1) data = ((data & 0xff) << 8) | ((data >> 8) & 0xff); + VDP_VSRAM_BYTE(VdpAddress & ~1) = data >> 8; + VDP_VSRAM_BYTE(VdpAddress | 1) = data; + break; + } + +// default: { +// bprintf(PRINT_NORMAL, _T("Genesis VDP Data Write %x\n"), VdpCode); +// } + } + + VdpAddress += GenesisVdpRegs[15]; +} + +void GenesisVDPWrite(UINT32 offset, UINT16 data) +{ + switch (offset) { + case 0x00: + case 0x01: { + VDPDataWrite(data); + return; + } + + case 0x02: + case 0x03: { + VDPControlWrite(data); + return; + } + } + +// bprintf(PRINT_NORMAL, _T("Genesis VDP Write %x\n"), data); +} + +INT32 StartGenesisVDP(INT32 ScreenNum, UINT32* pal) +{ + INT32 i; + static const UINT8 VdpInit[24] = + { + 0x04, 0x44, 0x30, 0x3C, 0x07, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x01, 0x37, 0x00, 0x02, + 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x80, + }; + + GenesisScreenNumber = ScreenNum; + + GenesisPalette = pal; + + VdpVRAM = (UINT8*)malloc(VRAM_SIZE); + VdpVSRAM = (UINT8*)malloc(VSRAM_SIZE); + VdpTransLookup = (UINT16*)malloc(0x1000 * sizeof(UINT16)); + + memset(VdpVRAM, 0, VRAM_SIZE); + memset(VdpVSRAM, 0, VSRAM_SIZE); + + // Init the transparency lookup table + for (i = 0; i < 0x1000; i++) { + INT32 OriginalColour = i & 0x7ff; + INT32 HalfBright = i & 0x800; + + if (OriginalColour & 0x100) + VdpTransLookup[i] = OriginalColour; + else if (HalfBright) + VdpTransLookup[i] = OriginalColour | 0x800; + else + VdpTransLookup[i] = OriginalColour | 0x1000; + } + + // Reset Palettes + GenesisPaletteBase = 0; + GenesisBgPalLookup[0] = GenesisSpPalLookup[0] = 0x00; + GenesisBgPalLookup[1] = GenesisSpPalLookup[1] = 0x10; + GenesisBgPalLookup[2] = GenesisSpPalLookup[2] = 0x20; + GenesisBgPalLookup[3] = GenesisSpPalLookup[3] = 0x30; + + // Reset VDP + for (i = 0; i < 24; i++) { + VdpRegisterWrite(0x8000 | (i << 8) | VdpInit[i], 1); + } + VdpCmdPart = 0; + VdpCode = 0; + VdpAddress = 0; + + return 0; +} + +void GenesisVDPExit() +{ + if (VdpVRAM) { + free(VdpVRAM); + VdpVRAM = NULL; + } + if (VdpVSRAM) { + free(VdpVSRAM); + VdpVSRAM = NULL; + } + if (VdpTransLookup) { + free(VdpTransLookup); + VdpTransLookup = NULL; + } + + memset(GenesisVdpRegs, 0, sizeof(GenesisVdpRegs)); + memset(GenesisBgPalLookup, 0, sizeof(GenesisBgPalLookup)); + memset(GenesisSpPalLookup, 0, sizeof(GenesisSpPalLookup)); + + GenesisPalette = NULL; + + GenesisScreenNumber = 0; + GenesisPaletteBase = 0; + VdpBgColour = 0; + VdpScrollABase = 0; + VdpScrollBBase = 0; + VdpWindowBase = 0; + VdpSpriteBase = 0; + VdpHScrollMask = 0; + VdpHScrollSize = 0; + VdpHScrollBase = 0; + VdpVScrollMode = 0; + VdpWindowWidth = 0; + VdpScrollWidth = 0; + VdpScrollHeight = 0; + VdpWindowRight = 0; + VdpWindowDown = 0; + VdpWindowHPos = 0; + VdpWindowVPos = 0; + VdpCmdPart = 0; + VdpCode = 0; + VdpAddress = 0; +} + +void GenesisVDPScan() +{ + SCAN_VAR(VdpVRAM); + SCAN_VAR(VdpVSRAM); + SCAN_VAR(GenesisVdpRegs); + SCAN_VAR(GenesisBgPalLookup); + SCAN_VAR(GenesisSpPalLookup); + SCAN_VAR(VdpBgColour); + SCAN_VAR(VdpScrollABase); + SCAN_VAR(VdpScrollBBase); + SCAN_VAR(VdpWindowBase); + SCAN_VAR(VdpSpriteBase); + SCAN_VAR(VdpHScrollMask); + SCAN_VAR(VdpHScrollSize); + SCAN_VAR(VdpHScrollBase); + SCAN_VAR(VdpVScrollMode); + SCAN_VAR(VdpWindowWidth); + SCAN_VAR(VdpScrollWidth); + SCAN_VAR(VdpScrollHeight); + SCAN_VAR(VdpWindowRight); + SCAN_VAR(VdpWindowDown); + SCAN_VAR(VdpWindowHPos); + SCAN_VAR(VdpWindowVPos); + SCAN_VAR(VdpCmdPart); + SCAN_VAR(VdpCode); + SCAN_VAR(VdpAddress); +} + +inline INT32 vdp_gethscroll(INT32 plane, INT32 line) +{ + line &= VdpHScrollMask; + return 0x400 - (VDP_VRAM_WORD(VdpHScrollBase + (4 * line) + plane) & 0x3ff); +} + + +/* Note: We expect plane = 0 for Scroll A, plane = 2 for Scroll B + A Column is 8 Pixels Wide */ +static INT32 vdp_getvscroll(INT32 plane, INT32 column) +{ + UINT32 vsramoffset; + + switch (VdpVScrollMode) + { + case 0x00: /* Overall Scroll */ + return VDP_VSRAM_WORD(plane) & 0x7ff; + + case 0x01: /* Column Scroll */ + if (column == 40) column = 39; /* Fix Minor Innacuracy Only affects PotoPoto */ + vsramoffset = (4 * (column >> 1)) + plane; + return VDP_VSRAM_WORD(vsramoffset) & 0x7ff; + } + return 0; +} + +static void get_scroll_tiles(UINT32 line, INT32 scrollnum, UINT32 scrollbase, UINT32 *tiles, INT32 *offset) +{ + INT32 linehscroll = vdp_gethscroll(scrollnum, line); + INT32 column; + + /* adjust for partial tiles and then pre-divide hscroll to get the tile offset */ + *offset = -(linehscroll % 8); + linehscroll /= 8; + + /* loop over columns */ + for (column = 0; column < 41; column++) + { + INT32 columnvscroll = vdp_getvscroll(scrollnum, (column - (linehscroll & 1)) & 0x3f) + line; + + /* determine the base of the tilemap row */ + INT32 temp = ((columnvscroll / 8) & (VdpScrollHeight - 1)) * VdpScrollWidth; + INT32 tilebase = scrollbase + 2 * temp; + + /* offset into the tilemap based on the column */ + temp = (linehscroll + column) & (VdpScrollWidth - 1); + tilebase += 2 * temp; + + /* get the tile info */ + *tiles++ = ((columnvscroll % 8) << 16) | VDP_VRAM_WORD(tilebase); + } +} + +static void get_window_tiles(UINT32 line, UINT32 scrollbase, UINT32 *tiles) +{ + INT32 column; + + /* loop over columns */ + for (column = 0; column < 40; column++) + { + /* determine the base of the tilemap row */ + INT32 temp = (line / 8) * VdpWindowWidth + column; + INT32 tilebase = scrollbase + 2 * temp; + + /* get the tile info */ + *tiles++ = ((line % 8) << 16) | VDP_VRAM_WORD(tilebase); + } +} + +static void drawline_tiles(UINT32 *tiles, UINT16 *bmap, UINT32 pri, INT32 offset, INT32 lclip, INT32 rclip) +{ + /* adjust for the 8-pixel slop */ + bmap += offset; + if (lclip > rclip) + return; + + /* loop over columns */ + for ( ; offset < 320; offset += 8, bmap += 8) + { + UINT32 tile = *tiles++; + + /* if the tile is the correct priority, draw it */ + if (((tile >> 15) & 1) == pri && offset < 320) + { + INT32 colbase = GenesisBgPalLookup[(tile & 0x6000) >> 13]; + UINT32 *tp = (UINT32 *)&VDP_VRAM_BYTE((tile & 0x7ff) * 32); + UINT32 mytile; + INT32 col; + + /* vertical flipping */ + if (!(tile & 0x1000)) + mytile = tp[tile >> 16]; + else + mytile = tp[(tile >> 16) ^ 7]; + + /* skip if all-transparent */ + if (!mytile) + continue; + + /* non-clipped */ + if (offset >= lclip && offset <= rclip - 7) + { + /* non-flipped */ + if (!(tile & 0x0800)) + { + col = EXTRACT_PIXEL(mytile, 0); if (col) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(mytile, 1); if (col) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(mytile, 2); if (col) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(mytile, 3); if (col) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(mytile, 4); if (col) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(mytile, 5); if (col) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(mytile, 6); if (col) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(mytile, 7); if (col) bmap[7] = colbase + col; + } + + /* horizontal flip */ + else + { + col = EXTRACT_PIXEL(mytile, 7); if (col) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(mytile, 6); if (col) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(mytile, 5); if (col) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(mytile, 4); if (col) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(mytile, 3); if (col) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(mytile, 2); if (col) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(mytile, 1); if (col) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(mytile, 0); if (col) bmap[7] = colbase + col; + } + } + + /* clipped */ + else if (offset >= lclip - 8 && offset <= rclip) + { + /* non-flipped */ + if (!(tile & 0x0800)) + { + col = EXTRACT_PIXEL(mytile, 0); if (col && (offset + 0) >= lclip && (offset + 0) <= rclip) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(mytile, 1); if (col && (offset + 1) >= lclip && (offset + 1) <= rclip) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(mytile, 2); if (col && (offset + 2) >= lclip && (offset + 2) <= rclip) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(mytile, 3); if (col && (offset + 3) >= lclip && (offset + 3) <= rclip) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(mytile, 4); if (col && (offset + 4) >= lclip && (offset + 4) <= rclip) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(mytile, 5); if (col && (offset + 5) >= lclip && (offset + 5) <= rclip) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(mytile, 6); if (col && (offset + 6) >= lclip && (offset + 6) <= rclip) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(mytile, 7); if (col && (offset + 7) >= lclip && (offset + 7) <= rclip) bmap[7] = colbase + col; + } + + /* horizontal flip */ + else + { + col = EXTRACT_PIXEL(mytile, 7); if (col && (offset + 0) >= lclip && (offset + 0) <= rclip) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(mytile, 6); if (col && (offset + 1) >= lclip && (offset + 1) <= rclip) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(mytile, 5); if (col && (offset + 2) >= lclip && (offset + 2) <= rclip) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(mytile, 4); if (col && (offset + 3) >= lclip && (offset + 3) <= rclip) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(mytile, 3); if (col && (offset + 4) >= lclip && (offset + 4) <= rclip) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(mytile, 2); if (col && (offset + 5) >= lclip && (offset + 5) <= rclip) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(mytile, 1); if (col && (offset + 6) >= lclip && (offset + 6) <= rclip) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(mytile, 0); if (col && (offset + 7) >= lclip && (offset + 7) <= rclip) bmap[7] = colbase + col; + } + } + } + } +} + +static void draw8pixs(UINT16 *bmap, INT32 patno, INT32 /*priority*/, INT32 colbase, INT32 patline) +{ + UINT32 tile = *(UINT32 *)&VDP_VRAM_BYTE(patno * 32 + 4 * patline); + INT32 col; + + /* skip if all-transparent */ + if (!tile) + return; + + /* non-transparent */ + if ((colbase & 0x30) != 0x30 || !(GenesisVdpRegs[12] & 0x08)) + { + col = EXTRACT_PIXEL(tile, 0); if (col) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(tile, 1); if (col) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(tile, 2); if (col) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(tile, 3); if (col) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(tile, 4); if (col) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(tile, 5); if (col) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(tile, 6); if (col) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(tile, 7); if (col) bmap[7] = colbase + col; + } + + /* transparent */ + else + { + col = EXTRACT_PIXEL(tile, 0); + if (col) + { + if (col < 0x0e) bmap[0] = colbase + col; + else bmap[0] = VdpTransLookup[((col & 1) << 11) | (bmap[0] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 1); + if (col) + { + if (col < 0x0e) bmap[1] = colbase + col; + else bmap[1] = VdpTransLookup[((col & 1) << 11) | (bmap[1] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 2); + if (col) + { + if (col < 0x0e) bmap[2] = colbase + col; + else bmap[2] = VdpTransLookup[((col & 1) << 11) | (bmap[2] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 3); + if (col) + { + if (col < 0x0e) bmap[3] = colbase + col; + else bmap[3] = VdpTransLookup[((col & 1) << 11) | (bmap[3] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 4); + if (col) + { + if (col < 0x0e) bmap[4] = colbase + col; + else bmap[4] = VdpTransLookup[((col & 1) << 11) | (bmap[4] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 5); + if (col) + { + if (col < 0x0e) bmap[5] = colbase + col; + else bmap[5] = VdpTransLookup[((col & 1) << 11) | (bmap[5] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 6); + if (col) + { + if (col < 0x0e) bmap[6] = colbase + col; + else bmap[6] = VdpTransLookup[((col & 1) << 11) | (bmap[6] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 7); + if (col) + { + if (col < 0x0e) bmap[7] = colbase + col; + else bmap[7] = VdpTransLookup[((col & 1) << 11) | (bmap[7] & 0x7ff)]; + } + } +} + + +/* draw a horizontally-flipped section of a sprite */ +static void draw8pixs_hflip(UINT16 *bmap, INT32 patno, INT32 /*priority*/, INT32 colbase, INT32 patline) +{ + UINT32 tile = *(UINT32 *)&VDP_VRAM_BYTE(patno * 32 + 4 * patline); + INT32 col; + + /* skip if all-transparent */ + if (!tile) + return; + + /* non-transparent */ + if ((colbase & 0x30) != 0x30 || !(GenesisVdpRegs[12] & 0x08)) + { + col = EXTRACT_PIXEL(tile, 7); if (col) bmap[0] = colbase + col; + col = EXTRACT_PIXEL(tile, 6); if (col) bmap[1] = colbase + col; + col = EXTRACT_PIXEL(tile, 5); if (col) bmap[2] = colbase + col; + col = EXTRACT_PIXEL(tile, 4); if (col) bmap[3] = colbase + col; + col = EXTRACT_PIXEL(tile, 3); if (col) bmap[4] = colbase + col; + col = EXTRACT_PIXEL(tile, 2); if (col) bmap[5] = colbase + col; + col = EXTRACT_PIXEL(tile, 1); if (col) bmap[6] = colbase + col; + col = EXTRACT_PIXEL(tile, 0); if (col) bmap[7] = colbase + col; + } + + /* transparent */ + else + { + col = EXTRACT_PIXEL(tile, 7); + if (col) + { + if (col < 0x0e) bmap[0] = colbase + col; + else bmap[0] = VdpTransLookup[((col & 1) << 11) | (bmap[0] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 6); + if (col) + { + if (col < 0x0e) bmap[1] = colbase + col; + else bmap[1] = VdpTransLookup[((col & 1) << 11) | (bmap[1] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 5); + if (col) + { + if (col < 0x0e) bmap[2] = colbase + col; + else bmap[2] = VdpTransLookup[((col & 1) << 11) | (bmap[2] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 4); + if (col) + { + if (col < 0x0e) bmap[3] = colbase + col; + else bmap[3] = VdpTransLookup[((col & 1) << 11) | (bmap[3] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 3); + if (col) + { + if (col < 0x0e) bmap[4] = colbase + col; + else bmap[4] = VdpTransLookup[((col & 1) << 11) | (bmap[4] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 2); + if (col) + { + if (col < 0x0e) bmap[5] = colbase + col; + else bmap[5] = VdpTransLookup[((col & 1) << 11) | (bmap[5] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 1); + if (col) + { + if (col < 0x0e) bmap[6] = colbase + col; + else bmap[6] = VdpTransLookup[((col & 1) << 11) | (bmap[6] & 0x7ff)]; + } + col = EXTRACT_PIXEL(tile, 0); + if (col) + { + if (col < 0x0e) bmap[7] = colbase + col; + else bmap[7] = VdpTransLookup[((col & 1) << 11) | (bmap[7] & 0x7ff)]; + } + } +} + +static void drawline_sprite(INT32 line, UINT16 *bmap, INT32 priority, UINT8 *spritebase) +{ + INT32 spriteypos = (((spritebase[0] & 0x01) << 8) | spritebase[1]) - 0x80; + INT32 spritexpos = (((spritebase[6] & 0x01) << 8) | spritebase[7]) - 0x80; + INT32 spriteheight = ((spritebase[2] & 0x03) + 1) * 8; + INT32 spritewidth = (((spritebase[2] & 0x0c) >> 2) + 1) * 8; + INT32 spriteattr, patno, patflip, patline, colbase, x; + + /* skip if out of range */ + if (line < spriteypos || line >= spriteypos + spriteheight) + return; + if (spritexpos + spritewidth < 0 || spritexpos >= 320) + return; + + /* extract the remaining data */ + spriteattr = (spritebase[4] << 8) | spritebase[5]; + patno = spriteattr & 0x07FF; + patflip = (spriteattr & 0x1800) >> 11; + patline = line - spriteypos; + + /* determine the color base */ + colbase = GenesisSpPalLookup[(spriteattr & 0x6000) >> 13]; + + /* adjust for the X position */ + spritewidth >>= 3; + spriteheight >>= 3; + + /* switch off the flip mode */ + bmap += spritexpos; + switch (patflip) + { + case 0x00: /* No Flip */ + for (x = 0; x < spritewidth; x++, bmap += 8) + { + if (spritexpos >= -7 && spritexpos < 320) + draw8pixs(bmap, patno, priority, colbase, patline); + spritexpos += 8; + patno += spriteheight; + } + break; + + case 0x01: /* Horizontal Flip */ + patno += spriteheight * (spritewidth - 1); + for (x = 0; x < spritewidth; x++, bmap += 8) + { + if (spritexpos >= -7 && spritexpos < 320) + draw8pixs_hflip(bmap, patno, priority, colbase, patline); + spritexpos += 8; + patno -= spriteheight; + } + break; + + case 0x02: /* Vertical Flip */ + patline = 8 * spriteheight - patline - 1; + for (x = 0; x < spritewidth; x++, bmap += 8) + { + if (spritexpos >= -7 && spritexpos < 320) + draw8pixs(bmap, patno, priority, colbase, patline); + spritexpos += 8; + patno += spriteheight; + } + break; + + case 0x03: /* Both Flip */ + patno += spriteheight * (spritewidth - 1); + patline = 8 * spriteheight - patline - 1; + for (x = 0; x < spritewidth; x++, bmap += 8) + { + if (spritexpos >= -7 && spritexpos < 320) + draw8pixs_hflip(bmap, patno, priority, colbase, patline); + spritexpos += 8; + patno -= spriteheight; + } + break; + } +} + +void vdp_drawline(UINT16 *bitmap, UINT32 line, INT32 bgfill) +{ + INT32 lowsprites, highsprites, link; + UINT32 scrolla_tiles[41], scrollb_tiles[41], window_tiles[41]; + INT32 scrolla_offset, scrollb_offset; + UINT8 *lowlist[81], *highlist[81]; + INT32 bgcolor = bgfill ? bgfill : GenesisBgPalLookup[0]; + INT32 window_lclip, window_rclip; + INT32 scrolla_lclip, scrolla_rclip; + INT32 column, sprite; + + /* clear to the background color */ + for (column = 0; column < 320; column++) + bitmap[column] = bgcolor; + + /* if display is disabled, stop */ + if (!(GenesisVdpRegs[1] & 0x40)) + return; + + /* Sprites need to be Drawn in Reverse order .. may as well sort them here */ + link = lowsprites = highsprites = 0; + for (sprite = 0; sprite < 80; sprite++) + { + UINT8 *spritebase = &VDP_VRAM_BYTE(VdpSpriteBase + 8 * link); + + /* sort into high/low priorities */ + if (spritebase[4] & 0x0080) + highlist[++highsprites] = spritebase; + else + lowlist[++lowsprites] = spritebase; + + /* get the link; if 0, stop processing */ + link = spritebase[3] & 0x7F; + if (!link) + break; + } + + /* get tiles for the B scroll layer */ + get_scroll_tiles(line, 2, VdpScrollBBase, scrollb_tiles, &scrollb_offset); + + /* get tiles for the A scroll layer */ + get_scroll_tiles(line, 0, VdpScrollABase, scrolla_tiles, &scrolla_offset); + + /* get tiles for the window layer */ + get_window_tiles(line, VdpWindowBase, window_tiles); + + /* compute the windowing for this line */ + if ((VdpWindowDown && line >= VdpWindowVPos) || (!VdpWindowDown && line < VdpWindowVPos)) + window_lclip = 0, window_rclip = 320 - 1; + else if (VdpWindowRight) + window_lclip = VdpWindowHPos, window_rclip = 320 - 1; + else + window_lclip = 0, window_rclip = VdpWindowHPos - 1; + + /* compute the clipping of the scroll A layer */ + if (window_lclip == 0) + { + scrolla_lclip = window_rclip + 1; + scrolla_rclip = 320 - 1; + } + else + { + scrolla_lclip = 0; + scrolla_rclip = window_lclip - 1; + } + + /* Scroll B Low */ + drawline_tiles(scrollb_tiles, bitmap, 0, scrollb_offset, 0, 320 - 1); + + /* Scroll A Low */ + drawline_tiles(scrolla_tiles, bitmap, 0, scrolla_offset, scrolla_lclip, scrolla_rclip); + + /* Window Low */ + drawline_tiles(window_tiles, bitmap, 0, 0, window_lclip, window_rclip); + + /* Sprites Low */ + for (sprite = lowsprites; sprite > 0; sprite--) + drawline_sprite(line, bitmap, 0, lowlist[sprite]); + + /* Scroll B High */ + drawline_tiles(scrollb_tiles, bitmap, 1, scrollb_offset, 0, 320 - 1); + + /* Scroll A High */ + drawline_tiles(scrolla_tiles, bitmap, 1, scrolla_offset, scrolla_lclip, scrolla_rclip); + + /* Window High */ + drawline_tiles(window_tiles, bitmap, 1, 0, window_lclip, window_rclip); + + /* Sprites High */ + for (sprite = highsprites; sprite > 0; sprite--) + drawline_sprite(line, bitmap, 1, highlist[sprite]); +} diff --git a/src/burn/drivers/sega/genesis_vid.h b/src/burn/drivers/sega/genesis_vid.h new file mode 100644 index 00000000..e81ccea6 --- /dev/null +++ b/src/burn/drivers/sega/genesis_vid.h @@ -0,0 +1,12 @@ +#include "driver.h" + +extern UINT16 GenesisPaletteBase; +extern UINT16 GenesisBgPalLookup[4]; +extern UINT16 GenesisSpPalLookup[4]; + +INT32 StartGenesisVDP(INT32 ScreenNum, UINT32* pal); +void GenesisVDPExit(); +void GenesisVDPScan(); +UINT16 GenesisVDPRead(UINT32 offset); +void GenesisVDPWrite(UINT32 offset, UINT16 data); +void vdp_drawline(UINT16 *bitmap, UINT32 line, INT32 bgfill); diff --git a/src/burn/drivers/sega/mc8123.cpp b/src/burn/drivers/sega/mc8123.cpp new file mode 100644 index 00000000..ed3eda1c --- /dev/null +++ b/src/burn/drivers/sega/mc8123.cpp @@ -0,0 +1,333 @@ +#include "burnint.h" +#include "bitswap.h" + +static INT32 decrypt_type0(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,7,5,3,1,2,0,6,4); + if (swap == 1) val = BITSWAP08(val,5,3,7,2,1,0,4,6); + if (swap == 2) val = BITSWAP08(val,0,3,4,6,7,1,5,2); + if (swap == 3) val = BITSWAP08(val,0,7,3,2,6,4,1,5); + + if (BIT(param,3) && BIT(val,7)) + val ^= (1<<5)|(1<<3)|(1<<0); + + if (BIT(param,2) && BIT(val,6)) + val ^= (1<<7)|(1<<2)|(1<<1); + + if (BIT(val,6)) val ^= (1<<7); + + if (BIT(param,1) && BIT(val,7)) + val ^= (1<<6); + + if (BIT(val,2)) val ^= (1<<5)|(1<<0); + + val ^= (1<<4)|(1<<3)|(1<<1); + + if (BIT(param,2)) val ^= (1<<5)|(1<<2)|(1<<0); + if (BIT(param,1)) val ^= (1<<7)|(1<<6); + if (BIT(param,0)) val ^= (1<<5)|(1<<0); + + if (BIT(param,0)) val = BITSWAP08(val,7,6,5,1,4,3,2,0); + + return val; +} + + +static INT32 decrypt_type1a(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,4,2,6,5,3,7,1,0); + if (swap == 1) val = BITSWAP08(val,6,0,5,4,3,2,1,7); + if (swap == 2) val = BITSWAP08(val,2,3,6,1,4,0,7,5); + if (swap == 3) val = BITSWAP08(val,6,5,1,3,2,7,0,4); + + if (BIT(param,2)) val = BITSWAP08(val,7,6,1,5,3,2,4,0); + + if (BIT(val,1)) val ^= (1<<0); + if (BIT(val,6)) val ^= (1<<3); + if (BIT(val,7)) val ^= (1<<6)|(1<<3); + if (BIT(val,2)) val ^= (1<<6)|(1<<3)|(1<<1); + if (BIT(val,4)) val ^= (1<<7)|(1<<6)|(1<<2); + + if (BIT(val,7) ^ BIT(val,2)) + val ^= (1<<4); + + val ^= (1<<6)|(1<<3)|(1<<1)|(1<<0); + + if (BIT(param,3)) val ^= (1<<7)|(1<<2); + if (BIT(param,1)) val ^= (1<<6)|(1<<3); + + if (BIT(param,0)) val = BITSWAP08(val,7,6,1,4,3,2,5,0); + + return val; +} + +static INT32 decrypt_type1b(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,1,0,3,2,5,6,4,7); + if (swap == 1) val = BITSWAP08(val,2,0,5,1,7,4,6,3); + if (swap == 2) val = BITSWAP08(val,6,4,7,2,0,5,1,3); + if (swap == 3) val = BITSWAP08(val,7,1,3,6,0,2,5,4); + + if (BIT(val,2) && BIT(val,0)) + val ^= (1<<7)|(1<<4); + + if (BIT(val,7)) val ^= (1<<2); + if (BIT(val,5)) val ^= (1<<7)|(1<<2); + if (BIT(val,1)) val ^= (1<<5); + if (BIT(val,6)) val ^= (1<<1); + if (BIT(val,4)) val ^= (1<<6)|(1<<5); + if (BIT(val,0)) val ^= (1<<6)|(1<<2)|(1<<1); + if (BIT(val,3)) val ^= (1<<7)|(1<<6)|(1<<2)|(1<<1)|(1<<0); + + val ^= (1<<6)|(1<<4)|(1<<0); + + if (BIT(param,3)) val ^= (1<<4)|(1<<1); + if (BIT(param,2)) val ^= (1<<7)|(1<<6)|(1<<3)|(1<<0); + if (BIT(param,1)) val ^= (1<<4)|(1<<3); + if (BIT(param,0)) val ^= (1<<6)|(1<<2)|(1<<1)|(1<<0); + + return val; +} + +static INT32 decrypt_type2a(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,0,1,4,3,5,6,2,7); + if (swap == 1) val = BITSWAP08(val,6,3,0,5,7,4,1,2); + if (swap == 2) val = BITSWAP08(val,1,6,4,5,0,3,7,2); + if (swap == 3) val = BITSWAP08(val,4,6,7,5,2,3,1,0); + + if (BIT(val,3) || (BIT(param,1) && BIT(val,2))) + val = BITSWAP08(val,6,0,7,4,3,2,1,5); + + if (BIT(val,5)) val ^= (1<<7); + if (BIT(val,6)) val ^= (1<<5); + if (BIT(val,0)) val ^= (1<<6); + if (BIT(val,4)) val ^= (1<<3)|(1<<0); + if (BIT(val,1)) val ^= (1<<2); + + val ^= (1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<1); + + if (BIT(param,2)) val ^= (1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0); + + if (BIT(param,3)) + { + if (BIT(param,0)) + val = BITSWAP08(val,7,6,5,3,4,1,2,0); + else + val = BITSWAP08(val,7,6,5,1,2,4,3,0); + } + else + { + if (BIT(param,0)) + val = BITSWAP08(val,7,6,5,2,1,3,4,0); + } + + return val; +} + +static INT32 decrypt_type2b(INT32 val,INT32 param,INT32 swap) +{ + // only 0x20 possible encryptions for this method - all others have 0x40 + // this happens because BIT(param,2) cancels the other three + + if (swap == 0) val = BITSWAP08(val,1,3,4,6,5,7,0,2); + if (swap == 1) val = BITSWAP08(val,0,1,5,4,7,3,2,6); + if (swap == 2) val = BITSWAP08(val,3,5,4,1,6,2,0,7); + if (swap == 3) val = BITSWAP08(val,5,2,3,0,4,7,6,1); + + if (BIT(val,7) && BIT(val,3)) + val ^= (1<<6)|(1<<4)|(1<<0); + + if (BIT(val,7)) val ^= (1<<2); + if (BIT(val,5)) val ^= (1<<7)|(1<<3); + if (BIT(val,1)) val ^= (1<<5); + if (BIT(val,4)) val ^= (1<<7)|(1<<5)|(1<<3)|(1<<1); + + if (BIT(val,7) && BIT(val,5)) + val ^= (1<<4)|(1<<0); + + if (BIT(val,5) && BIT(val,1)) + val ^= (1<<4)|(1<<0); + + if (BIT(val,6)) val ^= (1<<7)|(1<<5); + if (BIT(val,3)) val ^= (1<<7)|(1<<6)|(1<<5)|(1<<1); + if (BIT(val,2)) val ^= (1<<3)|(1<<1); + + val ^= (1<<7)|(1<<3)|(1<<2)|(1<<1); + + if (BIT(param,3)) val ^= (1<<6)|(1<<3)|(1<<1); + if (BIT(param,2)) val ^= (1<<7)|(1<<6)|(1<<5)|(1<<3)|(1<<2)|(1<<1); // same as the other three combined + if (BIT(param,1)) val ^= (1<<7); + if (BIT(param,0)) val ^= (1<<5)|(1<<2); + + return val; +} + +static INT32 decrypt_type3a(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,5,3,1,7,0,2,6,4); + if (swap == 1) val = BITSWAP08(val,3,1,2,5,4,7,0,6); + if (swap == 2) val = BITSWAP08(val,5,6,1,2,7,0,4,3); + if (swap == 3) val = BITSWAP08(val,5,6,7,0,4,2,1,3); + + if (BIT(val,2)) val ^= (1<<7)|(1<<5)|(1<<4); + if (BIT(val,3)) val ^= (1<<0); + + if (BIT(param,0)) val = BITSWAP08(val,7,2,5,4,3,1,0,6); + + if (BIT(val,1)) val ^= (1<<6)|(1<<0); + if (BIT(val,3)) val ^= (1<<4)|(1<<2)|(1<<1); + + if (BIT(param,3)) val ^= (1<<4)|(1<<3); + + if (BIT(val,3)) val = BITSWAP08(val,5,6,7,4,3,2,1,0); + + if (BIT(val,5)) val ^= (1<<2)|(1<<1); + + val ^= (1<<6)|(1<<5)|(1<<4)|(1<<3); + + if (BIT(param,2)) val ^= (1<<7); + if (BIT(param,1)) val ^= (1<<4); + if (BIT(param,0)) val ^= (1<<0); + + return val; +} + +static INT32 decrypt_type3b(INT32 val,INT32 param,INT32 swap) +{ + if (swap == 0) val = BITSWAP08(val,3,7,5,4,0,6,2,1); + if (swap == 1) val = BITSWAP08(val,7,5,4,6,1,2,0,3); + if (swap == 2) val = BITSWAP08(val,7,4,3,0,5,1,6,2); + if (swap == 3) val = BITSWAP08(val,2,6,4,1,3,7,0,5); + + if (BIT(val,2)) val ^= (1<<7); + + if (BIT(val,7)) val = BITSWAP08(val,7,6,3,4,5,2,1,0); + + if (BIT(param,3)) val ^= (1<<7); + + if (BIT(val,4)) val ^= (1<<6); + if (BIT(val,1)) val ^= (1<<6)|(1<<4)|(1<<2); + + if (BIT(val,7) && BIT(val,6)) + val ^= (1<<1); + + if (BIT(val,7)) val ^= (1<<1); + + if (BIT(param,3)) val ^= (1<<7); + if (BIT(param,2)) val ^= (1<<0); + + if (BIT(param,3)) val = BITSWAP08(val,4,6,3,2,5,0,1,7); + + if (BIT(val,4)) val ^= (1<<1); + if (BIT(val,5)) val ^= (1<<4); + if (BIT(val,7)) val ^= (1<<2); + + val ^= (1<<5)|(1<<3)|(1<<2); + + if (BIT(param,1)) val ^= (1<<7); + if (BIT(param,0)) val ^= (1<<3); + + return val; +} + +static INT32 decrypt(INT32 val, INT32 key, INT32 opcode) +{ + INT32 type = 0; + INT32 swap = 0; + INT32 param = 0; + + key ^= 0xff; + + // no encryption + if (key == 0x00) + return val; + + type ^= BIT(key,0) << 0; + type ^= BIT(key,2) << 0; + type ^= BIT(key,0) << 1; + type ^= BIT(key,1) << 1; + type ^= BIT(key,2) << 1; + type ^= BIT(key,4) << 1; + type ^= BIT(key,4) << 2; + type ^= BIT(key,5) << 2; + + swap ^= BIT(key,0) << 0; + swap ^= BIT(key,1) << 0; + swap ^= BIT(key,2) << 1; + swap ^= BIT(key,3) << 1; + + param ^= BIT(key,0) << 0; + param ^= BIT(key,0) << 1; + param ^= BIT(key,2) << 1; + param ^= BIT(key,3) << 1; + param ^= BIT(key,0) << 2; + param ^= BIT(key,1) << 2; + param ^= BIT(key,6) << 2; + param ^= BIT(key,1) << 3; + param ^= BIT(key,6) << 3; + param ^= BIT(key,7) << 3; + + if (!opcode) + { + param ^= 1 << 0; + type ^= 1 << 0; + } + + switch (type) + { + default: + case 0: return decrypt_type0(val,param,swap); + case 1: return decrypt_type0(val,param,swap); + case 2: return decrypt_type1a(val,param,swap); + case 3: return decrypt_type1b(val,param,swap); + case 4: return decrypt_type2a(val,param,swap); + case 5: return decrypt_type2b(val,param,swap); + case 6: return decrypt_type3a(val,param,swap); + case 7: return decrypt_type3b(val,param,swap); + } +} + +static UINT8 mc8123_decrypt(INT32 addr,UINT8 val,const UINT8 *key,INT32 opcode) +{ + INT32 tbl_num; + + /* pick the translation table from bits fd57 of the address */ + tbl_num = (addr & 7) + ((addr & 0x10)>>1) + ((addr & 0x40)>>2) + ((addr & 0x100)>>3) + ((addr & 0xc00)>>4) + ((addr & 0xf000)>>4) ; + + return decrypt(val,key[tbl_num + (opcode ? 0 : 0x1000)],opcode); +} + +void mc8123_decrypt_rom(INT32 /*banknum*/, INT32 numbanks, UINT8 *pRom, UINT8 *pFetch, UINT8 *pKey) +{ + UINT8 *decrypted1 = pFetch; +// UINT8 *decrypted2 = numbanks > 1 ? auto_malloc(0x4000 * numbanks) : decrypted1 + 0x8000; + UINT8 *rom = pRom; + UINT8 *key = pKey; + INT32 A, bank; + + for (A = 0x0000;A < 0x8000;A++) + { + UINT8 src = rom[A]; + + /* decode the opcodes */ + decrypted1[A] = mc8123_decrypt(A,src,key,1); + + /* decode the data */ + rom[A] = mc8123_decrypt(A,src,key,0); + } + + for (bank = 0; bank < numbanks; ++bank) + { + for (A = 0x8000;A < 0xc000;A++) + { + UINT8 src = rom[0x8000 + 0x4000*bank + A]; + + /* decode the opcodes */ +// decrypted2[0x4000 * bank + (A-0x8000)] = mc8123_decrypt(A,src,key,1); + + /* decode the data */ + rom[0x8000 + 0x4000*bank + A] = mc8123_decrypt(A,src,key,0); + } + } +} diff --git a/src/burn/drivers/sega/mc8123.h b/src/burn/drivers/sega/mc8123.h new file mode 100644 index 00000000..6418dcfa --- /dev/null +++ b/src/burn/drivers/sega/mc8123.h @@ -0,0 +1 @@ +void mc8123_decrypt_rom(INT32 banknum, INT32 numbanks, UINT8 *pRom, UINT8 *pFetch, UINT8 *pKey); diff --git a/src/burn/drivers/sega/sys16.h b/src/burn/drivers/sega/sys16.h new file mode 100644 index 00000000..ed1bd97e --- /dev/null +++ b/src/burn/drivers/sega/sys16.h @@ -0,0 +1,284 @@ +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "burn_ym2413.h" +#include "burn_ym2612.h" +#include "rf5c68.h" +#include "burn_gun.h" +#include "bitswap.h" +#include "genesis_vid.h" +#include "8255ppi.h" + +#define SYS16_ROM_PROG 1 +#define SYS16_ROM_TILES 2 +#define SYS16_ROM_SPRITES 3 +#define SYS16_ROM_Z80PROG 4 +#define SYS16_ROM_KEY 5 +#define SYS16_ROM_7751PROG 6 +#define SYS16_ROM_7751DATA 7 +#define SYS16_ROM_UPD7759DATA 8 +#define SYS16_ROM_PROG2 9 +#define SYS16_ROM_ROAD 10 +#define SYS16_ROM_PCMDATA 11 +#define SYS16_ROM_Z80PROG2 12 +#define SYS16_ROM_Z80PROG3 13 +#define SYS16_ROM_Z80PROG4 14 +#define SYS16_ROM_PCM2DATA 15 +#define SYS16_ROM_PROM 16 +#define SYS16_ROM_PROG3 17 +#define SYS16_ROM_SPRITES2 18 +#define SYS16_ROM_RF5C68DATA 19 + +// sys16_run.cpp +extern UINT8 System16InputPort0[8]; +extern UINT8 System16InputPort1[8]; +extern UINT8 System16InputPort2[8]; +extern UINT8 System16InputPort3[8]; +extern UINT8 System16InputPort4[8]; +extern UINT8 System16InputPort5[8]; +extern UINT8 System16InputPort6[8]; +extern UINT8 System16Gear; +extern INT32 System16AnalogPort0; +extern INT32 System16AnalogPort1; +extern INT32 System16AnalogPort2; +extern INT32 System16AnalogPort3; +extern INT32 System16AnalogPort4; +extern INT32 System16AnalogPort5; +extern INT32 System16AnalogSelect; +extern UINT8 System16Dip[3]; +extern UINT8 System16Input[7]; +extern UINT8 System16Reset; +extern UINT8 *System16Rom; +extern UINT8 *System16Code; +extern UINT8 *System16Rom2; +extern UINT8 *System16Z80Rom; +extern UINT8 *System16UPD7759Data; +extern UINT8 *System16PCMData; +extern UINT8 *System16RF5C68Data; +extern UINT8 *System16Prom; +extern UINT8 *System16Key; +extern UINT8 *System16Ram; +extern UINT8 *System16ExtraRam; +extern UINT8 *System16Z80Ram; +extern UINT8 *System16TempGfx; +extern UINT8 *System16TileRam; +extern UINT8 *System16TextRam; +extern UINT8 *System16TextRam; +extern UINT8 *System16SpriteRam; +extern UINT8 *System16SpriteRamBuff; +extern UINT8 *System16SpriteRam2; +extern UINT8 *System16RotateRam; +extern UINT8 *System16RotateRamBuff; +extern UINT8 *System16PaletteRam; +extern UINT8 *System16RoadRam; +extern UINT8 *System16RoadRamBuff; +extern UINT32 *System16Palette; +extern UINT8 *System16Tiles; +extern UINT8 *System16Sprites; +extern UINT8 *System16Sprites2; +extern UINT8 *System16Roads; +extern UINT32 System16NumTiles; +extern UINT32 System16RomSize; +extern UINT32 System16Rom2Size; +extern UINT32 System16TileRomSize; +extern UINT32 System16SpriteRomSize; +extern UINT32 System16Sprite2RomSize; +extern UINT32 System16RoadRomSize; +extern UINT32 System16Z80RomSize; +extern UINT32 System16PCMDataSize; +extern UINT32 System16PCMDataSizePreAllocate; +extern UINT32 System16ExtraRamSize; +extern UINT32 System16SpriteRamSize; +extern UINT32 System16SpriteRam2Size; +extern UINT32 System16RotateRamSize; +extern UINT32 System16UPD7759DataSize; + +extern UINT8 System16VideoControl; +extern INT32 System16SoundLatch; +extern bool System16BTileAlt; +extern bool Shangon; +extern bool Hangon; +extern bool System16Z80Enable; + +extern INT32 YBoardIrq2Scanline; +extern INT32 System16YM2413IRQInterval; + +extern bool System16HasGears; + +extern INT32 nSystem16CyclesDone[4]; +extern UINT32 System16ClockSpeed; + +typedef void (*Sim8751)(); +extern Sim8751 Simulate8751; + +typedef void (*System16Map68K)(); +extern System16Map68K System16Map68KDo; + +typedef void (*System16MapZ80)(); +extern System16MapZ80 System16MapZ80Do; + +typedef INT32 (*System16CustomLoadRom)(); +extern System16CustomLoadRom System16CustomLoadRomDo; + +typedef INT32 (*System16CustomDecryptOpCode)(); +extern System16CustomDecryptOpCode System16CustomDecryptOpCodeDo; + +typedef UINT8 (*System16ProcessAnalogControls)(UINT16 value); +extern System16ProcessAnalogControls System16ProcessAnalogControlsDo; + +typedef void (*System16MakeAnalogInputs)(); +extern System16MakeAnalogInputs System16MakeAnalogInputsDo; + +INT32 CustomLoadRom20000(); +INT32 CustomLoadRom40000(); + +UINT16 System16MultiplyChipRead(INT32 which, INT32 offset); +void System16MultiplyChipWrite(INT32 which, INT32 offset, UINT16 data); +UINT16 System16CompareTimerChipRead(INT32 which, INT32 offset); +void System16CompareTimerChipWrite(INT32 which, INT32 offset, UINT16 data); +UINT16 System16DivideChipRead(INT32 which, INT32 offset); +void System16DivideChipWrite(INT32 which, INT32 offset, UINT16 data); + +INT32 System16Init(); +INT32 System16Exit(); +INT32 System16AFrame(); +INT32 System16BFrame(); +INT32 System18Frame(); +INT32 HangonFrame(); +INT32 HangonYM2203Frame(); +INT32 OutrunFrame(); +INT32 XBoardFrame(); +INT32 YBoardFrame(); +INT32 System16Scan(INT32 nAction, INT32 *pnMin); + +// d_sys16a.cpp +void System16APPI0WritePortA(UINT8 data); +void System16APPI0WritePortB(UINT8 data); +void System16APPI0WritePortC(UINT8 data); +extern UINT16 __fastcall System16AReadWord(UINT32 a); +extern UINT8 __fastcall System16AReadByte(UINT32 a); +void __fastcall System16AWriteWord(UINT32 a, UINT16 d); +void __fastcall System16AWriteByte(UINT32 a, UINT8 d); + +// d_sys16b.cpp +extern UINT8 __fastcall System16BReadByte(UINT32 a); +void __fastcall System16BWriteByte(UINT32 a, UINT8 d); +void __fastcall System16BWriteWord(UINT32 a, UINT16 d); + +// d_sys18.cpp +extern UINT16 __fastcall System18ReadWord(UINT32 a); +extern UINT8 __fastcall System18ReadByte(UINT32 a); +void __fastcall System18WriteWord(UINT32 a, UINT16 d); +void __fastcall System18WriteByte(UINT32 a, UINT8 d); + +// d_hangon.cpp +void HangonPPI0WritePortA(UINT8 data); +void HangonPPI0WritePortB(UINT8 data); +void HangonPPI0WritePortC(UINT8 data); +UINT8 HangonPPI1ReadPortC(); +void HangonPPI1WritePortA(UINT8 data); +extern UINT16 __fastcall HangonReadWord(UINT32 a); +extern UINT8 __fastcall HangonReadByte(UINT32 a); +void __fastcall HangonWriteWord(UINT32 a, UINT16 d); +void __fastcall HangonWriteByte(UINT32 a, UINT8 d); + +// d_outrun.cpp +void OutrunPPI0WritePortC(UINT8 data); +extern UINT16 __fastcall OutrunReadWord(UINT32 a); +extern UINT8 __fastcall OutrunReadByte(UINT32 a); +void __fastcall OutrunWriteWord(UINT32 a, UINT16 d); +void __fastcall OutrunWriteByte(UINT32 a, UINT8 d); +extern UINT8 __fastcall Outrun2ReadByte(UINT32 a); +void __fastcall Outrun2WriteWord(UINT32 a, UINT16 d); +void __fastcall Outrun2WriteByte(UINT32 a, UINT8 d); + +// d_xbrd.cpp +extern UINT16 __fastcall XBoardReadWord(UINT32 a); +extern UINT8 __fastcall XBoardReadByte(UINT32 a); +void __fastcall XBoardWriteWord(UINT32 a, UINT16 d); +void __fastcall XBoardWriteByte(UINT32 a, UINT8 d); +extern UINT16 __fastcall XBoard2ReadWord(UINT32 a); +extern UINT8 __fastcall XBoard2ReadByte(UINT32 a); +void __fastcall XBoard2WriteWord(UINT32 a, UINT16 d); +void __fastcall XBoard2WriteByte(UINT32 a, UINT8 d); + +// d_ybrd.cpp +extern UINT16 __fastcall YBoardReadWord(UINT32 a); +extern UINT8 __fastcall YBoardReadByte(UINT32 a); +void __fastcall YBoardWriteWord(UINT32 a, UINT16 d); +void __fastcall YBoardWriteByte(UINT32 a, UINT8 d); +extern UINT16 __fastcall YBoard2ReadWord(UINT32 a); +void __fastcall YBoard2WriteWord(UINT32 a, UINT16 d); +extern UINT16 __fastcall YBoard3ReadWord(UINT32 a); +extern UINT8 __fastcall YBoard3ReadByte(UINT32 a); +void __fastcall YBoard3WriteWord(UINT32 a, UINT16 d); + +// sys16_gfx.cpp +extern INT32 System16VideoEnable; +extern INT32 System18VdpEnable; +extern INT32 System18VdpMixing; +extern INT32 System16ScreenFlip; +extern INT32 System16SpriteShadow; +extern INT32 System16SpriteXOffset; +extern INT32 System16SpriteBanks[16]; +extern INT32 System16TileBanks[8]; +extern INT32 System16OldTileBanks[8]; +extern INT32 System16Page[4]; +extern INT32 System16OldPage[4]; +extern UINT8 BootlegFgPage[4]; +extern UINT8 BootlegBgPage[4]; +extern INT32 System16ScrollX[4]; +extern INT32 System16ScrollY[4]; +extern INT32 System16ColScroll; +extern INT32 System16RowScroll; +extern INT32 System16RoadControl; +extern INT32 System16RoadColorOffset1; +extern INT32 System16RoadColorOffset2; +extern INT32 System16RoadColorOffset3; +extern INT32 System16RoadXOffset; +extern INT32 System16RoadPriority; +extern INT32 System16PaletteEntries; +extern INT32 System16TilemapColorOffset; +extern INT32 System16TileBankSize; +extern INT32 System16RecalcBgTileMap; +extern INT32 System16RecalcBgAltTileMap; +extern INT32 System16RecalcFgTileMap; +extern INT32 System16RecalcFgAltTileMap; +extern INT32 System16CreateOpaqueTileMaps; +extern INT32 System16IgnoreVideoEnable; + +extern bool bSystem16BootlegRender; + +extern UINT16 *pTempDraw; + +void System16Decode8x8Tiles(UINT8 *pTile, INT32 Num, INT32 offs1, INT32 offs2, INT32 offs3); +void OutrunDecodeRoad(); +void HangonDecodeRoad(); +void System16ATileMapsInit(INT32 bOpaque); +void System16BTileMapsInit(INT32 bOpaque); +void System16TileMapsExit(); +void System16ARender(); +void System16BRender(); +void System16BootlegRender(); +void System16BAltRender(); +void System16ATileByteWrite(UINT32 Offset, UINT8 d); +void System16ATileWordWrite(UINT32 Offset, UINT16 d); +void System16BTileByteWrite(UINT32 Offset, UINT8 d); +void System16BTileWordWrite(UINT32 Offset, UINT16 d); +void System18Render(); +void HangonRender(); +void HangonAltRender(); +void OutrunRender(); +void ShangonRender(); +void XBoardRender(); +void YBoardRender(); + +// fd1089.cpp +void FD1089Decrypt(); + +// sys16_fd1094.cpp +void fd1094_driver_init(INT32 nCPU); +void fd1094_machine_init(); +void fd1094_exit(); + +// genesis_vid.cpp diff --git a/src/burn/drivers/sega/sys16_fd1094.cpp b/src/burn/drivers/sega/sys16_fd1094.cpp new file mode 100644 index 00000000..01c68829 --- /dev/null +++ b/src/burn/drivers/sega/sys16_fd1094.cpp @@ -0,0 +1,191 @@ +#include "sys16.h" +#include "fd1094.h" + +#define S16_NUMCACHE 8 + +static UINT8 *fd1094_key; // the memory region containing key +static UINT16 *fd1094_cpuregion; // the CPU region with encrypted code +static UINT32 fd1094_cpuregionsize; // the size of this region in bytes + +static UINT16* fd1094_userregion; // a user region where the current decrypted state is put and executed from +static UINT16* fd1094_cacheregion[S16_NUMCACHE]; // a cache region where S16_NUMCACHE states are stored to improve performance +static INT32 fd1094_cached_states[S16_NUMCACHE]; // array of cached state numbers +static INT32 fd1094_current_cacheposition; // current position in cache array + +static INT32 nFD1094CPU = 0; + +bool System18Banking; +/* +static void *fd1094_get_decrypted_base(void) +{ + if (!fd1094_key) + return NULL; + return fd1094_userregion; +}*/ + +/* this function checks the cache to see if the current state is cached, + if it is then it copies the cached data to the user region where code is + executed from, if its not cached then it gets decrypted to the current + cache position using the functions in fd1094.c */ +static void fd1094_setstate_and_decrypt(INT32 state) +{ + INT32 i; + UINT32 addr; + + // force a flush of the prefetch cache + m68k_set_reg(M68K_REG_PREF_ADDR, 0x1000); + + /* set the FD1094 state ready to decrypt.. */ + state = fd1094_set_state(fd1094_key,state); + + /* first check the cache, if its cached we don't need to decrypt it, just copy */ + for (i=0;i=S16_NUMCACHE) + { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("out of cache, performance may suffer, increase S16_NUMCACHE!\n")); +#endif + fd1094_current_cacheposition=0; + } +} + +/* Callback for CMP.L instructions (state change) */ +INT32 __fastcall fd1094_cmp_callback(UINT32 val, INT32 reg) +{ + if (reg == 0 && (val & 0x0000ffff) == 0x0000ffff) // ? + { + fd1094_setstate_and_decrypt((val & 0xffff0000) >> 16); + } + + return 0; +} + +/* Callback when the FD1094 enters interrupt code */ +INT32 __fastcall fd1094_int_callback (INT32 irq) +{ + fd1094_setstate_and_decrypt(FD1094_STATE_IRQ); + return (0x60+irq*4)/4; // vector address +} + +INT32 __fastcall fd1094_rte_callback (void) +{ + fd1094_setstate_and_decrypt(FD1094_STATE_RTE); + + return 0; +} + +void fd1094_kludge_reset_values(void) +{ + INT32 i; + + for (i = 0;i < 4;i++) { + fd1094_userregion[i] = fd1094_decode(i,fd1094_cpuregion[i],fd1094_key,1); + } + + SekOpen(nFD1094CPU); + SekMapMemory((UINT8*)fd1094_userregion, 0x000000, 0x0fffff, SM_FETCH); + if (System18Banking) SekMapMemory((UINT8*)fd1094_userregion + 0x200000, 0x200000, 0x27ffff, SM_FETCH); + SekClose(); +} + + +/* function, to be called from MACHINE_RESET (every reset) */ +void fd1094_machine_init(void) +{ + fd1094_setstate_and_decrypt(FD1094_STATE_RESET); + fd1094_kludge_reset_values(); + + SekOpen(nFD1094CPU); + SekSetCmpCallback(fd1094_cmp_callback); + SekSetRTECallback(fd1094_rte_callback); + SekSetIrqCallback(fd1094_int_callback); + SekClose(); +} + +/* startup function, to be called from DRIVER_INIT (once on startup) */ +void fd1094_driver_init(INT32 nCPU) +{ + INT32 i; + + nFD1094CPU = nCPU; + + if (nFD1094CPU == 0) { + fd1094_cpuregion = (UINT16*)System16Rom; + fd1094_cpuregionsize = System16RomSize; + } + + if (nFD1094CPU == 1) { + fd1094_cpuregion = (UINT16*)System16Rom2; + fd1094_cpuregionsize = System16Rom2Size; + } + + if (nFD1094CPU >= 2) { + bprintf(PRINT_ERROR, _T("Invalid CPU called for FD1094 Driver Init\n")); + } + + fd1094_key = System16Key; + + /* punt if no key; this allows us to be called even for non-FD1094 games */ + if (!fd1094_key) + return; + + for (i=0;i 0x0fffff) System18Banking = true; +} + +void fd1094_exit() +{ + System18Banking = false; + nFD1094CPU = 0; + + for (INT32 i = 0; i < S16_NUMCACHE; i++) { + if (fd1094_cacheregion[i]) { + free(fd1094_cacheregion[i]); + fd1094_cacheregion[i] = NULL; + } + } + + fd1094_current_cacheposition = 0; +} diff --git a/src/burn/drivers/sega/sys16_gfx.cpp b/src/burn/drivers/sega/sys16_gfx.cpp new file mode 100644 index 00000000..064315a1 --- /dev/null +++ b/src/burn/drivers/sega/sys16_gfx.cpp @@ -0,0 +1,3338 @@ +#include "sys16.h" + +INT32 System16SpriteBanks[16]; +INT32 System16TileBanks[8]; +INT32 System16OldTileBanks[8]; +INT32 System16Page[4]; +INT32 System16OldPage[4]; +UINT8 BootlegFgPage[4]; +UINT8 BootlegBgPage[4]; +INT32 System16ScrollX[4] = {0, 0, 0, 0}; +INT32 System16ScrollY[4] = {0, 0, 0, 0}; +INT32 System16VideoEnable; +INT32 System18VdpEnable; +INT32 System18VdpMixing; +INT32 System16ScreenFlip; +INT32 System16SpriteShadow; +INT32 System16SpriteXOffset = 0; +INT32 System16ColScroll = 0; +INT32 System16RowScroll = 0; +INT32 System16RoadControl = 0; +INT32 System16RoadColorOffset1 = 0; +INT32 System16RoadColorOffset2 = 0; +INT32 System16RoadColorOffset3 = 0; +INT32 System16RoadXOffset = 0; +INT32 System16RoadPriority = 0; +INT32 System16PaletteEntries = 0; +INT32 System16TilemapColorOffset = 0; +INT32 System16TileBankSize = 0; +INT32 System16RecalcBgTileMap = 0; +INT32 System16RecalcBgAltTileMap = 0; +INT32 System16RecalcFgTileMap = 0; +INT32 System16RecalcFgAltTileMap = 0; +INT32 System16CreateOpaqueTileMaps = 0; +INT32 System16IgnoreVideoEnable = 0; + +bool bSystem16BootlegRender; + +UINT16 *pTempDraw = NULL; +static UINT16 *pSys16BgTileMapOpaque = NULL; +static UINT16 *pSys16BgAltTileMapOpaque = NULL; +static UINT16 *pSys16BgTileMapPri0 = NULL; +static UINT16 *pSys16BgTileMapPri1 = NULL; +static UINT16 *pSys16FgTileMapPri0 = NULL; +static UINT16 *pSys16FgTileMapPri1 = NULL; +static UINT16 *pSys16BgAltTileMapPri0 = NULL; +static UINT16 *pSys16BgAltTileMapPri1 = NULL; +static UINT16 *pSys16FgAltTileMapPri0 = NULL; +static UINT16 *pSys16FgAltTileMapPri1 = NULL; + +/*==================================================== +Decode Functions +====================================================*/ + +void System16Decode8x8Tiles(UINT8 *pTile, INT32 Num, INT32 offs1, INT32 offs2, INT32 offs3) +{ + INT32 c, y, x, Dat1, Dat2, Dat3, Col; + + for (c = 0; c < Num; c++) { + for (y = 0; y < 8; y++) { + Dat1 = System16TempGfx[offs1 + (c * 8) + y]; + Dat2 = System16TempGfx[offs2 + (c * 8) + y]; + Dat3 = System16TempGfx[offs3 + (c * 8) + y]; + for (x = 0; x < 8; x++) { + Col = 0; + if (Dat1 & 1) { Col |= 4;} + if (Dat2 & 1) { Col |= 2;} + if (Dat3 & 1) { Col |= 1;} + pTile[(c * 64) + (y * 8) + (7 - x)] = Col; + Dat1 >>= 1; + Dat2 >>= 1; + Dat3 >>= 1; + } + } + } +} + +void OutrunDecodeRoad() +{ + for (INT32 y = 0; y < 256 * 2; y++) { + UINT8 *src = System16TempGfx + ((y & 0xff) * 0x40 + (y >> 8) * 0x8000) % System16RoadRomSize; + UINT8 *dst = System16Roads + y * 512; + + /* loop over columns */ + for (INT32 x = 0; x < 512; x++) + { + dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1); + + /* pre-mark road data in the "stripe" area with a high bit */ + if (x >= 256-8 && x < 256 && dst[x] == 3) + dst[x] |= 4; + } + } + + /* set up a dummy road in the last entry */ + memset(System16Roads + 256 * 2 * 512, 3, 512); +} + +void HangonDecodeRoad() +{ + INT32 x, y; + + /* loop over rows */ + for (y = 0; y < 256; y++) + { + UINT8 *src = System16TempGfx + ((y & 0xff) * 0x40) % System16RoadRomSize; + UINT8 *dst = System16Roads + y * 512; + + /* loop over columns */ + for (x = 0; x < 512; x++) + dst[x] = (((src[x/8] >> (~x & 7)) & 1) << 0) | (((src[x/8 + 0x4000] >> (~x & 7)) & 1) << 1); + } +} + +/*==================================================== +Tile Layer Rendering +====================================================*/ + +#define PLOTPIXEL(x, po) pPixel[x] = nPalette | pTileData[x] | po; +#define PLOTPIXEL_MASK(x, mc, po) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x] | po;} + +static inline void RenderTile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * 1024) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += 1024, pTileData += 8) { + PLOTPIXEL(0, nPaletteOffset); + PLOTPIXEL(1, nPaletteOffset); + PLOTPIXEL(2, nPaletteOffset); + PLOTPIXEL(3, nPaletteOffset); + PLOTPIXEL(4, nPaletteOffset); + PLOTPIXEL(5, nPaletteOffset); + PLOTPIXEL(6, nPaletteOffset); + PLOTPIXEL(7, nPaletteOffset); + } +} + +static void RenderTile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * 1024) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += 1024, pTileData += 8) { + PLOTPIXEL_MASK(0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(7, nMaskColour, nPaletteOffset); + } +} + +#undef PLOTPIXEL +#undef PLOTPIXEL_MASK + +void System16ATileMapsInit(INT32 bOpaque) +{ + if (bOpaque) { + pSys16BgTileMapOpaque = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + } + + pSys16BgTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16BgTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); +} + +void System16BTileMapsInit(INT32 bOpaque) +{ + if (bOpaque) { + pSys16BgTileMapOpaque = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16BgAltTileMapOpaque = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + } + + pSys16BgTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16BgTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + + pSys16BgAltTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16BgAltTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgAltTileMapPri0 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + pSys16FgAltTileMapPri1 = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); +} + +void System16TileMapsExit() +{ + if (pSys16BgTileMapOpaque) { + free(pSys16BgTileMapOpaque); + pSys16BgTileMapOpaque = NULL; + } + if (pSys16BgAltTileMapOpaque) { + free(pSys16BgAltTileMapOpaque); + pSys16BgAltTileMapOpaque = NULL; + } + if (pSys16BgTileMapPri0) { + free(pSys16BgTileMapPri0); + pSys16BgTileMapPri0 = NULL; + } + if (pSys16BgTileMapPri1) { + free(pSys16BgTileMapPri1); + pSys16BgTileMapPri1 = NULL; + } + if (pSys16FgTileMapPri0) { + free(pSys16FgTileMapPri0); + pSys16FgTileMapPri0 = NULL; + } + if (pSys16FgTileMapPri1) { + free(pSys16FgTileMapPri1); + pSys16FgTileMapPri1 = NULL; + } + if (pSys16BgAltTileMapPri0) { + free(pSys16BgAltTileMapPri0); + pSys16BgAltTileMapPri0 = NULL; + } + if (pSys16BgAltTileMapPri1) { + free(pSys16BgAltTileMapPri1); + pSys16BgAltTileMapPri1 = NULL; + } + if (pSys16FgAltTileMapPri0) { + free(pSys16FgAltTileMapPri0); + pSys16FgAltTileMapPri0 = NULL; + } + if (pSys16FgAltTileMapPri1) { + free(pSys16FgAltTileMapPri1); + pSys16FgAltTileMapPri1 = NULL; + } +} + +static void System16ACreateBgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, i, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + UINT16 *pDest = NULL; + + if (System16CreateOpaqueTileMaps) memset(pSys16BgTileMapOpaque, 0, 1024 * 512 * sizeof(UINT16)); + EffPage = System16Page[1]; + EffPage = ((EffPage >> 4) & 0x0707) | ((EffPage << 4) & 0x7070); + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON) EffPage &= 0x3333; + for (i = 0; i < 2; i++) { + if (i == 0) pDest = pSys16BgTileMapPri0; + if (i == 1) pDest = pSys16BgTileMapPri1; + memset(pDest, 0, 1024 * 512 * sizeof(UINT16)); + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 12) & 1; + + if (Priority != i) continue; + + x = 8 * mx; + x += xOffs; + + Code = ((Attr >> 1) & 0x1000) | (Attr & 0xfff); + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (System16CreateOpaqueTileMaps) RenderTile(pSys16BgTileMapOpaque, Code, x, y, Colour, 3, ColourOff, System16Tiles); + RenderTile_Mask(pDest, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } + } +} + +static void System16ACreateFgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + + memset(pSys16FgTileMapPri0, 0, 1024 * 512 * sizeof(UINT16)); + memset(pSys16FgTileMapPri1, 0, 1024 * 512 * sizeof(UINT16)); + + EffPage = System16Page[0]; + EffPage = ((EffPage >> 4) & 0x0707) | ((EffPage << 4) & 0x7070); + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON) EffPage &= 0x3333; + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 12) & 1; + + x = 8 * mx; + x += xOffs; + + Code = ((Attr >> 1) & 0x1000) | (Attr & 0xfff); + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Priority == 0) RenderTile_Mask(pSys16FgTileMapPri0, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + if (Priority == 1) RenderTile_Mask(pSys16FgTileMapPri1, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } +} + +static void System16BCreateBgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, i, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + UINT16 *pDest = NULL; + + if (System16CreateOpaqueTileMaps) memset(pSys16BgTileMapOpaque, 0, 1024 * 512 * sizeof(UINT16)); + EffPage = System16Page[1]; + for (i = 0; i < 2; i++) { + if (i == 0) pDest = pSys16BgTileMapPri0; + if (i == 1) pDest = pSys16BgTileMapPri1; + memset(pDest, 0, 1024 * 512 * sizeof(UINT16)); + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + if (Priority != i) continue; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (System16CreateOpaqueTileMaps) RenderTile(pSys16BgTileMapOpaque, Code, x, y, Colour, 3, ColourOff, System16Tiles); + RenderTile_Mask(pDest, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } + } +} + +static void System16BCreateBgAltTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, i, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + UINT16 *pDest = NULL; + + if (System16CreateOpaqueTileMaps) memset(pSys16BgAltTileMapOpaque, 0, 1024 * 512 * sizeof(UINT16)); + EffPage = System16Page[3]; + for (i = 0; i < 2; i++) { + if (i == 0) pDest = pSys16BgAltTileMapPri0; + if (i == 1) pDest = pSys16BgAltTileMapPri1; + if (System16RecalcBgAltTileMap) memset(pDest, 0,1024 * 512 * sizeof(UINT16)); + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + if (Priority != i) continue; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (System16CreateOpaqueTileMaps) RenderTile(pSys16BgAltTileMapOpaque, Code, x, y, Colour, 3, ColourOff, System16Tiles); + if (System16RecalcBgAltTileMap) RenderTile_Mask(pDest, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } + } +} + +static void System16BCreateFgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + + memset(pSys16FgTileMapPri0, 0, 1024 * 512 * sizeof(UINT16)); + memset(pSys16FgTileMapPri1, 0, 1024 * 512 * sizeof(UINT16)); + + EffPage = System16Page[0]; + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Priority == 0) RenderTile_Mask(pSys16FgTileMapPri0, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + if (Priority == 1) RenderTile_Mask(pSys16FgTileMapPri1, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } +} + +static void System16BCreateFgAltTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + + memset(pSys16FgAltTileMapPri0, 0, 1024 * 512 * sizeof(UINT16)); + memset(pSys16FgAltTileMapPri1, 0, 1024 * 512 * sizeof(UINT16)); + + EffPage = System16Page[2]; + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Priority == 0) RenderTile_Mask(pSys16FgAltTileMapPri0, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + if (Priority == 1) RenderTile_Mask(pSys16FgAltTileMapPri1, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } +} + +static void System16BAltCreateBgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, i, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + UINT16 *pDest = NULL; + + if (System16CreateOpaqueTileMaps) memset(pSys16BgTileMapOpaque, 0, 1024 * 512 * sizeof(UINT16)); + EffPage = System16Page[1]; + for (i = 0; i < 2; i++) { + if (i == 0) pDest = pSys16BgTileMapPri0; + if (i == 1) pDest = pSys16BgTileMapPri1; + memset(pDest, 0, 1024 * 512 * sizeof(UINT16)); + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + if (Priority != i) continue; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (System16CreateOpaqueTileMaps) RenderTile(pSys16BgTileMapOpaque, Code, x, y, Colour, 3, ColourOff, System16Tiles); + RenderTile_Mask(pDest, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } + } +} + +static void System16BAltCreateBgAltTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, i, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + UINT16 *pDest = NULL; + + if (System16CreateOpaqueTileMaps) memset(pSys16BgAltTileMapOpaque, 0, 1024 * 512 * sizeof(UINT16)); + EffPage = System16Page[3]; + for (i = 0; i < 2; i++) { + if (i == 0) pDest = pSys16BgAltTileMapPri0; + if (i == 1) pDest = pSys16BgAltTileMapPri1; + if (System16RecalcBgAltTileMap) memset(pDest, 0,1024 * 512 * sizeof(UINT16)); + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + if (Priority != i) continue; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (System16CreateOpaqueTileMaps) RenderTile(pSys16BgAltTileMapOpaque, Code, x, y, Colour, 3, ColourOff, System16Tiles); + if (System16RecalcBgAltTileMap) RenderTile_Mask(pDest, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } + } +} + +static void System16BAltCreateFgTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + + memset(pSys16FgTileMapPri0, 0, 1024 * 512 * sizeof(UINT16)); + memset(pSys16FgTileMapPri1, 0, 1024 * 512 * sizeof(UINT16)); + + EffPage = System16Page[0]; + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Priority == 0) RenderTile_Mask(pSys16FgTileMapPri0, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + if (Priority == 1) RenderTile_Mask(pSys16FgTileMapPri1, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } +} + +static void System16BAltCreateFgAltTileMaps() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex, Priority, ColourOff, TilePage, xOffs, yOffs; + UINT16 *VideoRam = (UINT16*)System16TileRam; + UINT16 EffPage, ActPage; + + memset(pSys16FgAltTileMapPri0, 0, 1024 * 512 * sizeof(UINT16)); + memset(pSys16FgAltTileMapPri1, 0, 1024 * 512 * sizeof(UINT16)); + + EffPage = System16Page[2]; + for (TilePage = 0; TilePage < 4; TilePage++) { + ActPage = (EffPage >> 0) & 0x0f; + xOffs = 0; + yOffs = 0; + if (TilePage == 1) { ActPage = (EffPage >> 4) & 0x0f; xOffs = 512; } + if (TilePage == 2) { ActPage = (EffPage >> 8) & 0x0f; yOffs = 256; } + if (TilePage == 3) { ActPage = (EffPage >> 12) & 0x0f; xOffs = 512; yOffs = 256; } + for (my = 0; my < 32; my++) { + y = 8 * my; + y += yOffs; + for (mx = 0; mx < 64; mx++) { + TileIndex = (ActPage * 64 * 32) + (my * 64) + mx; + + Attr = VideoRam[TileIndex]; + Priority = (Attr >> 15) & 1; + + x = 8 * mx; + x += xOffs; + + Code = Attr & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Attr >> 5) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Priority == 0) RenderTile_Mask(pSys16FgAltTileMapPri0, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + if (Priority == 1) RenderTile_Mask(pSys16FgAltTileMapPri1, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } + } +} + +static void System16ACreateTileMaps() +{ + if (System16RecalcBgTileMap) { + System16ACreateBgTileMaps(); + System16RecalcBgTileMap = 0; + } + + if (System16RecalcFgTileMap) { + System16ACreateFgTileMaps(); + System16RecalcFgTileMap = 0; + } +} + +static void System16BCreateTileMaps() +{ + UINT16 *TextRam = (UINT16*)System16TextRam; + INT32 i; + + // Check if we need the alt tilemaps + if (System16RecalcFgAltTileMap) { + System16RecalcFgAltTileMap = 0; + for (i = 0xf80/2 + 0 * 0x40/2; i < 0xf80/2 + 0 * 0x40/2 + 224/8; i++) { + if (TextRam[i] & 0x8000) System16RecalcFgAltTileMap = 1; + } + } + + if (System16RecalcBgAltTileMap) { + System16RecalcBgAltTileMap = 0; + for (i = 0xf80/2 + 1 * 0x40/2; i < 0xf80/2 + 1 * 0x40/2 + 224/8; i++) { + if (TextRam[i] & 0x8000) System16RecalcBgAltTileMap = 1; + } + } + + if (System16RecalcBgTileMap) { + System16BCreateBgTileMaps(); + System16RecalcBgTileMap = 0; + } + + if (System16RecalcBgAltTileMap) { + System16BCreateBgAltTileMaps(); + System16RecalcBgAltTileMap = 0; + } + + if (System16RecalcFgTileMap) { + System16BCreateFgTileMaps(); + System16RecalcFgTileMap = 0; + } + + if (System16RecalcFgAltTileMap) { + System16BCreateFgAltTileMaps(); + System16RecalcFgAltTileMap = 0; + } +} + +static void System16BAltCreateTileMaps() +{ + UINT16 *TextRam = (UINT16*)System16TextRam; + INT32 i; + + // Check if we need the alt tilemaps + if (System16RecalcFgAltTileMap) { + System16RecalcFgAltTileMap = 0; + for (i = 0xf80/2 + 0 * 0x40/2; i < 0xf80/2 + 0 * 0x40/2 + 224/8; i++) { + if (TextRam[i] & 0x8000) System16RecalcFgAltTileMap = 1; + } + } + + if (System16RecalcBgAltTileMap) { + System16RecalcBgAltTileMap = 0; + for (i = 0xf80/2 + 1 * 0x40/2; i < 0xf80/2 + 1 * 0x40/2 + 224/8; i++) { + if (TextRam[i] & 0x8000) System16RecalcBgAltTileMap = 1; + } + } + + if (System16RecalcBgTileMap) { + System16BAltCreateBgTileMaps(); + System16RecalcBgTileMap = 0; + } + + if (System16RecalcBgAltTileMap) { + System16BAltCreateBgAltTileMaps(); + System16RecalcBgAltTileMap = 0; + } + + if (System16RecalcFgTileMap) { + System16BAltCreateFgTileMaps(); + System16RecalcFgTileMap = 0; + } + + if (System16RecalcFgAltTileMap) { + System16BAltCreateFgAltTileMaps(); + System16RecalcFgAltTileMap = 0; + } +} + +void System16ATileWordWrite(UINT32 Offset, UINT16 d) +{ + UINT16 *TileRam = (UINT16*)System16TileRam; + + UINT32 FgPage1Addr = (((System16Page[0] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage2Addr = (((System16Page[0] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage3Addr = (((System16Page[0] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage4Addr = (((System16Page[0] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgPage1Addr = (((System16Page[1] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage2Addr = (((System16Page[1] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage3Addr = (((System16Page[1] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage4Addr = (((System16Page[1] >> 12) & 0xf) * (32 * 64)) << 1; + + if ((Offset >= FgPage1Addr && Offset <= (FgPage1Addr + 0xfff)) || (Offset >= FgPage2Addr && Offset <= (FgPage2Addr + 0xfff)) || (Offset >= FgPage3Addr && Offset <= (FgPage3Addr + 0xfff)) || (Offset >= FgPage4Addr && Offset <= (FgPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcFgTileMap = 1; + } + + if ((Offset >= BgPage1Addr && Offset <= (BgPage1Addr + 0xfff)) || (Offset >= BgPage2Addr && Offset <= (BgPage2Addr + 0xfff)) || (Offset >= BgPage3Addr && Offset <= (BgPage3Addr + 0xfff)) || (Offset >= BgPage4Addr && Offset <= (BgPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcBgTileMap = 1; + } + + TileRam[Offset >> 1] = d; +} + +void System16ATileByteWrite(UINT32 Offset, UINT8 d) +{ + UINT32 FgPage1Addr = (((System16Page[0] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage2Addr = (((System16Page[0] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage3Addr = (((System16Page[0] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage4Addr = (((System16Page[0] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgPage1Addr = (((System16Page[1] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage2Addr = (((System16Page[1] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage3Addr = (((System16Page[1] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage4Addr = (((System16Page[1] >> 12) & 0xf) * (32 * 64)) << 1; + + if ((Offset >= FgPage1Addr && Offset <= (FgPage1Addr + 0xfff)) || (Offset >= FgPage2Addr && Offset <= (FgPage2Addr + 0xfff)) || (Offset >= FgPage3Addr && Offset <= (FgPage3Addr + 0xfff)) || (Offset >= FgPage4Addr && Offset <= (FgPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcFgTileMap = 1; + } + + if ((Offset >= BgPage1Addr && Offset <= (BgPage1Addr + 0xfff)) || (Offset >= BgPage2Addr && Offset <= (BgPage2Addr + 0xfff)) || (Offset >= BgPage3Addr && Offset <= (BgPage3Addr + 0xfff)) || (Offset >= BgPage4Addr && Offset <= (BgPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcBgTileMap = 1; + } + + System16TileRam[Offset] = d; +} + +void System16BTileWordWrite(UINT32 Offset, UINT16 d) +{ + UINT16 *TileRam = (UINT16*)System16TileRam; + + UINT32 FgPage1Addr = (((System16Page[0] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage2Addr = (((System16Page[0] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage3Addr = (((System16Page[0] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage4Addr = (((System16Page[0] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgPage1Addr = (((System16Page[1] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage2Addr = (((System16Page[1] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage3Addr = (((System16Page[1] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage4Addr = (((System16Page[1] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 FgAltPage1Addr = (((System16Page[2] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage2Addr = (((System16Page[2] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage3Addr = (((System16Page[2] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage4Addr = (((System16Page[2] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgAltPage1Addr = (((System16Page[3] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage2Addr = (((System16Page[3] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage3Addr = (((System16Page[3] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage4Addr = (((System16Page[3] >> 12) & 0xf) * (32 * 64)) << 1; + + if ((Offset >= FgPage1Addr && Offset <= (FgPage1Addr + 0xfff)) || (Offset >= FgPage2Addr && Offset <= (FgPage2Addr + 0xfff)) || (Offset >= FgPage3Addr && Offset <= (FgPage3Addr + 0xfff)) || (Offset >= FgPage4Addr && Offset <= (FgPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcFgTileMap = 1; + } + + if ((Offset >= BgPage1Addr && Offset <= (BgPage1Addr + 0xfff)) || (Offset >= BgPage2Addr && Offset <= (BgPage2Addr + 0xfff)) || (Offset >= BgPage3Addr && Offset <= (BgPage3Addr + 0xfff)) || (Offset >= BgPage4Addr && Offset <= (BgPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcBgTileMap = 1; + } + + if ((Offset >= FgAltPage1Addr && Offset <= (FgAltPage1Addr + 0xfff)) || (Offset >= FgAltPage2Addr && Offset <= (FgAltPage2Addr + 0xfff)) || (Offset >= FgAltPage3Addr && Offset <= (FgAltPage3Addr + 0xfff)) || (Offset >= FgAltPage4Addr && Offset <= (FgAltPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcFgAltTileMap = 1; + } + + if ((Offset >= BgAltPage1Addr && Offset <= (BgAltPage1Addr + 0xfff)) || (Offset >= BgAltPage2Addr && Offset <= (BgAltPage2Addr + 0xfff)) || (Offset >= BgAltPage3Addr && Offset <= (BgAltPage3Addr + 0xfff)) || (Offset >= BgAltPage4Addr && Offset <= (BgAltPage4Addr + 0xfff))) { + if (TileRam[Offset >> 1] != d) System16RecalcBgAltTileMap = 1; + } + + TileRam[Offset >> 1] = d; +} + +void System16BTileByteWrite(UINT32 Offset, UINT8 d) +{ + UINT32 FgPage1Addr = (((System16Page[0] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage2Addr = (((System16Page[0] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage3Addr = (((System16Page[0] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgPage4Addr = (((System16Page[0] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgPage1Addr = (((System16Page[1] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage2Addr = (((System16Page[1] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage3Addr = (((System16Page[1] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgPage4Addr = (((System16Page[1] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 FgAltPage1Addr = (((System16Page[2] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage2Addr = (((System16Page[2] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage3Addr = (((System16Page[2] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 FgAltPage4Addr = (((System16Page[2] >> 12) & 0xf) * (32 * 64)) << 1; + + UINT32 BgAltPage1Addr = (((System16Page[3] >> 0) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage2Addr = (((System16Page[3] >> 4) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage3Addr = (((System16Page[3] >> 8) & 0xf) * (32 * 64)) << 1; + UINT32 BgAltPage4Addr = (((System16Page[3] >> 12) & 0xf) * (32 * 64)) << 1; + + if ((Offset >= FgPage1Addr && Offset <= (FgPage1Addr + 0xfff)) || (Offset >= FgPage2Addr && Offset <= (FgPage2Addr + 0xfff)) || (Offset >= FgPage3Addr && Offset <= (FgPage3Addr + 0xfff)) || (Offset >= FgPage4Addr && Offset <= (FgPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcFgTileMap = 1; + } + + if ((Offset >= BgPage1Addr && Offset <= (BgPage1Addr + 0xfff)) || (Offset >= BgPage2Addr && Offset <= (BgPage2Addr + 0xfff)) || (Offset >= BgPage3Addr && Offset <= (BgPage3Addr + 0xfff)) || (Offset >= BgPage4Addr && Offset <= (BgPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcBgTileMap = 1; + } + + if ((Offset >= FgAltPage1Addr && Offset <= (FgAltPage1Addr + 0xfff)) || (Offset >= FgAltPage2Addr && Offset <= (FgAltPage2Addr + 0xfff)) || (Offset >= FgAltPage3Addr && Offset <= (FgAltPage3Addr + 0xfff)) || (Offset >= FgAltPage4Addr && Offset <= (FgAltPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcFgAltTileMap = 1; + } + + if ((Offset >= BgAltPage1Addr && Offset <= (BgAltPage1Addr + 0xfff)) || (Offset >= BgAltPage2Addr && Offset <= (BgAltPage2Addr + 0xfff)) || (Offset >= BgAltPage3Addr && Offset <= (BgAltPage3Addr + 0xfff)) || (Offset >= BgAltPage4Addr && Offset <= (BgAltPage4Addr + 0xfff))) { + if (System16TileRam[Offset] != d) System16RecalcBgAltTileMap = 1; + } + + System16TileRam[Offset] = d; +} + +static void System16ARenderTileLayer(INT32 Page, INT32 PriorityDraw, INT32 Transparent) +{ + INT32 xScroll, yScroll, x, y; + UINT16 *TextRam = (UINT16*)System16TextRam; + + xScroll = System16ScrollX[Page]; + yScroll = System16ScrollY[Page]; + UINT16 Pix; + + UINT16 *pTileMapSrc = NULL; + UINT16 *pTileMapDest = NULL; + INT32 xSrcOff, ySrcOff, RowScrollIndex, xEffScroll, yEffScroll; + + if (System16ColScroll && System16RowScroll) { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + RowScrollIndex = y / 8; + + xEffScroll = TextRam[0xf80/2 + RowScrollIndex * 2 + Page] & 0x1ff; + + for (x = 0; x < nScreenWidth; x++) { + yEffScroll = TextRam[0xf30/2 + (x/16) * 2 + Page] & 0xff; + + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + + xSrcOff = (x - xEffScroll + 200) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } else { + if (System16ColScroll) { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + xEffScroll = xScroll; + + for (x = 0; x < nScreenWidth; x++) { + yEffScroll = TextRam[0xf30/2 + (x/16) * 2 + Page] & 0xff; + + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + + xSrcOff = (x - xEffScroll + 200) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } else { + if (System16RowScroll) { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + RowScrollIndex = y / 8; + + xEffScroll = TextRam[0xf80/2 + RowScrollIndex * 2 + Page] & 0x1ff; + + for (x = 0; x < nScreenWidth; x++) { + yEffScroll = yScroll; + + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + + xSrcOff = (x - xEffScroll + 200) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } else { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + ySrcOff = (y + yScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + + for (x = 0; x < nScreenWidth; x++) { + xSrcOff = (x - xScroll + 200) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } + } + } +} + +static void System16BRenderTileLayer(INT32 Page, INT32 PriorityDraw, INT32 Transparent) +{ + INT32 xScroll, yScroll, x, y; + UINT16 *TextRam = (UINT16*)System16TextRam; + + xScroll = System16ScrollX[Page]; + yScroll = System16ScrollY[Page]; + UINT16 Pix; + + UINT16 *pTileMapSrc = NULL; + UINT16 *pTileMapDest = NULL; + INT32 xSrcOff, ySrcOff, RowScrollIndex, RowScroll, xEffScroll, yEffScroll; + + if (yScroll & 0x8000) { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + RowScrollIndex = y / 8; + + RowScroll = TextRam[0xf80/2 + 0x40/2 * Page + RowScrollIndex]; + xEffScroll = (xScroll & 0x8000) ? RowScroll : xScroll; + + for (x = 0; x < nScreenWidth; x++) { + yEffScroll = TextRam[0xf16/2 + 0x40/2 * Page + (x+9)/16]; + + if (RowScroll & 0x8000) { + xEffScroll = System16ScrollX[Page + 2]; + yEffScroll = System16ScrollY[Page + 2]; + + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgAltTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgAltTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0) pTileMapSrc = pSys16BgAltTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1) pTileMapSrc = pSys16BgAltTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgAltTileMapOpaque + (ySrcOff * 1024); + } else { + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1 && Transparent == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + } + + xSrcOff = (x - xEffScroll + 192) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } else { + for (y = 0; y < nScreenHeight; y++) { + pTileMapDest = pTransDraw + (y * nScreenWidth); + + RowScrollIndex = y / 8; + + RowScroll = TextRam[0xf80/2 + 0x40/2 * Page + RowScrollIndex]; + xEffScroll = (xScroll & 0x8000) ? RowScroll : xScroll; + yEffScroll = yScroll; + + if (RowScroll & 0x8000) { + xEffScroll = System16ScrollX[Page + 2]; + yEffScroll = System16ScrollY[Page + 2]; + + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgAltTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgAltTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0) pTileMapSrc = pSys16BgAltTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1) pTileMapSrc = pSys16BgAltTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgAltTileMapOpaque + (ySrcOff * 1024); + } else { + ySrcOff = (y + yEffScroll) & 0x1ff; + if (Page == 0 && PriorityDraw == 0) pTileMapSrc = pSys16FgTileMapPri0 + (ySrcOff * 1024); + if (Page == 0 && PriorityDraw == 1) pTileMapSrc = pSys16FgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 0) pTileMapSrc = pSys16BgTileMapPri0 + (ySrcOff * 1024); + if (Page == 1 && PriorityDraw == 1) pTileMapSrc = pSys16BgTileMapPri1 + (ySrcOff * 1024); + if (Page == 1 && Transparent == 0) pTileMapSrc = pSys16BgTileMapOpaque + (ySrcOff * 1024); + } + + for (x = 0; x < nScreenWidth; x++) { + xSrcOff = (x - xEffScroll + 192) & 0x3ff; + Pix = pTileMapSrc[xSrcOff]; + + if (Transparent) { + if (Pix) pTileMapDest[x] = Pix; + } else { + pTileMapDest[x] = Pix; + } + } + } + } +} + +static void BootlegRenderTileLayer(INT32 Page, INT32 PriorityDraw, INT32 Transparent) +{ + INT32 mx, my, Code, Colour, x, y, Priority, TileIndex, ColourOff; + + UINT16 EffPage, ActPage = 0, xScroll, yScroll; + + EffPage = System16Page[Page]; + xScroll = System16ScrollX[Page]; + yScroll = System16ScrollY[Page]; + + INT32 yStartPosArray[28 * 21]; + + float yPos = float(yScroll % 8); + INT32 yStartPos = INT32(yPos) * -1; + + if (yScroll & 0x8000) { + for (y = 0; y < 224; y += 8) { + for (x = -8; x < 320; x += 16) { + INT32 yColScrollTemp = (System16TextRam[0xf16 + (0x40 * Page) + (2 * (x + 8) / 16) + 1] << 8) | System16TextRam[0xf16 + (0x40 * Page) + (2 * (x + 8) / 16) + 0]; + float yTempPos = float(yColScrollTemp % 8); + INT32 yTempStartPos = INT32(yTempPos) * -1; + yStartPosArray[(y / 8) + (28 * ((x + 8) / 16))] = yTempStartPos + y; + } + } + + for (INT32 ny = 0; ny < 28; ny++) { + INT32 RowScrollIndex = ny; + + INT32 RowScroll = (System16TextRam[0xf80 + (0x40 * Page) + (2 * RowScrollIndex) + 1] << 8) | System16TextRam[0xf80 + (0x40 * Page) + (2 * RowScrollIndex) + 0]; + + INT32 xScrollRow = ((xScroll & 0x8000) ? RowScroll : xScroll); + + INT32 yScrollCol; + + if (RowScroll & 0x8000) { + EffPage = System16Page[Page + 2]; + xScrollRow = System16ScrollX[Page + 2]; + yScrollCol = System16ScrollY[Page + 2]; + } + + float xPos = float(xScrollRow % 8); + INT32 xStartPos = (INT32)xPos; + + if (xStartPos == 1) xStartPos = -7; + if (xStartPos == 2) xStartPos = -6; + if (xStartPos == 3) xStartPos = -5; + if (xStartPos == 4) xStartPos = -4; + if (xStartPos == 5) xStartPos = -3; + if (xStartPos == 6) xStartPos = -2; + if (xStartPos == 7) xStartPos = -1; + if (xStartPos == 0) xStartPos = 0; + + for (x = -8; x < 320; x += 16) { + INT32 x2 = xStartPos + x; + + yScrollCol = (System16TextRam[0xf16 + (0x40 * Page) + (2 * (x + 8) / 16) + 1] << 8) | System16TextRam[0xf16 + (0x40 * Page) + (2 * (x + 8) / 16) + 0]; + + my = ((ny * 8) + (yScrollCol & 0x1ff)) / 8; + + if (my > 63) my -= 64; + + y = yStartPosArray[ny + (28 * ((x + 8) / 16))]; + + mx = (x2 - (xScrollRow & 0x3ff) + 192) / 8; + if (mx < 0) mx += 128; + if (Page == 1) { + if (my < 32 && mx < 64) ActPage = BootlegBgPage[0]; + if (my < 32 && mx >= 64) ActPage = BootlegBgPage[1]; + if (my >= 32 && mx < 64) ActPage = BootlegBgPage[2]; + if (my >= 32 && mx >= 64) ActPage = BootlegBgPage[3]; + } + if (Page == 0) { + if (my < 32 && mx < 64) ActPage = BootlegFgPage[0]; + if (my < 32 && mx >= 64) ActPage = BootlegFgPage[1]; + if (my >= 32 && mx < 64) ActPage = BootlegFgPage[2]; + if (my >= 32 && mx >= 64) ActPage = BootlegFgPage[3]; + } + + TileIndex = 64 * 32 * 2 * ActPage + ((2 * 64 * my) & 0xfff) + ((2 * mx) & 0x7f); + INT32 Data = (System16TileRam[TileIndex + 1] << 8) | System16TileRam[TileIndex + 0]; + INT32 Data2 = (System16TileRam[TileIndex + 3] << 8) | System16TileRam[TileIndex + 2]; + + Priority = (Data >> 15) & 1; + + if (Priority == PriorityDraw) { + Code = Data & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Data >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Transparent) { + if (x2 > 7 && x2 < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x2, y, Colour, 3, 0, ColourOff, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x2, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } else { + if (x2 > 7 && x2 < 312 && y > 7 && y < 216) { + Render8x8Tile(pTransDraw, Code, x2, y, Colour, 3, ColourOff, System16Tiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x2, y, Colour, 3, ColourOff, System16Tiles); + } + } + + Code = Data2 & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Data2 >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + INT32 x1 = x2 + 8; + + if (Transparent) { + if (x1 > 7 && x1 < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x1, y, Colour, 3, 0, ColourOff, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x1, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } else { + if (x1 > 7 && x1 < 312 && y > 7 && y < 216) { + Render8x8Tile(pTransDraw, Code, x1, y, Colour, 3, ColourOff, System16Tiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x1, y, Colour, 3, ColourOff, System16Tiles); + } + } + } + } + } + } else { + for (y = yStartPos; y < 224; y += 8) { + INT32 RowScrollIndex = y / 8; + INT32 RowScroll = (System16TextRam[0xf80 + (0x40 * Page) + (2 * RowScrollIndex) + 1] << 8) | System16TextRam[0xf80 + (0x40 * Page) + (2 * RowScrollIndex) + 0]; + + INT32 xScrollRow = ((xScroll & 0x8000) ? RowScroll : xScroll); + + if (RowScroll & 0x8000) { + EffPage = System16Page[Page + 2]; + xScrollRow = System16ScrollX[Page + 2]; + yScroll = System16ScrollY[Page + 2]; + } + + float xPos = float(xScrollRow % 8); + INT32 xStartPos = (INT32)xPos; + + if (xStartPos == 1) xStartPos = -7; + if (xStartPos == 2) xStartPos = -6; + if (xStartPos == 3) xStartPos = -5; + if (xStartPos == 4) xStartPos = -4; + if (xStartPos == 5) xStartPos = -3; + if (xStartPos == 6) xStartPos = -2; + if (xStartPos == 7) xStartPos = -1; + + my = (y + (yScroll & 0x1ff)) / 8; + + if (my > 63) my -= 64; + + for (x = xStartPos; x < 320; x += 8) { + mx = (x - (xScrollRow & 0x3ff) + 192) / 8; + if (mx < 0) mx += 128; + if (Page == 1) { + if (my < 32 && mx < 64) ActPage = BootlegBgPage[0]; + if (my < 32 && mx >= 64) ActPage = BootlegBgPage[1]; + if (my >= 32 && mx < 64) ActPage = BootlegBgPage[2]; + if (my >= 32 && mx >= 64) ActPage = BootlegBgPage[3]; + } + if (Page == 0) { + if (my < 32 && mx < 64) ActPage = BootlegFgPage[0]; + if (my < 32 && mx >= 64) ActPage = BootlegFgPage[1]; + if (my >= 32 && mx < 64) ActPage = BootlegFgPage[2]; + if (my >= 32 && mx >= 64) ActPage = BootlegFgPage[3]; + } + + TileIndex = 64 * 32 * 2 * ActPage + ((2 * 64 * my) & 0xfff) + ((2 * mx) & 0x7f); + INT32 Data = (System16TileRam[TileIndex + 1] << 8) | System16TileRam[TileIndex + 0]; + + Priority = (Data >> 15) & 1; + + if (Priority == PriorityDraw) { + Code = Data & 0x1fff; + Code = System16TileBanks[Code / System16TileBankSize] * System16TileBankSize + Code % System16TileBankSize; + Code &= (System16NumTiles - 1); + Colour = (Data >> 6) & 0x7f; + + ColourOff = System16TilemapColorOffset; + if (Colour >= 0x20) ColourOff = 0x100 | System16TilemapColorOffset; + if (Colour >= 0x40) ColourOff = 0x200 | System16TilemapColorOffset; + if (Colour >= 0x60) ColourOff = 0x300 | System16TilemapColorOffset; + + if (Transparent) { + if (x > 7 && x < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, ColourOff, System16Tiles); + } + } else { + if (x > 7 && x < 312 && y > 7 && y < 216) { + Render8x8Tile(pTransDraw, Code, x, y, Colour, 3, ColourOff, System16Tiles); + } else { + Render8x8Tile_Clip(pTransDraw, Code, x, y, Colour, 3, ColourOff, System16Tiles); + } + } + } + } + } + } +} + +static void System16ARenderTextLayer(INT32 PriorityDraw) +{ + INT32 mx, my, Code, Colour, x, y, Priority, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = (System16TextRam[TileIndex + 1] << 8) | System16TextRam[TileIndex + 0]; + + Priority = (Code >> 11) & 1; + + if (Priority == PriorityDraw) { + Colour = (Code >> 8) & 0x07; + Code &= 0xff; + + x = 8 * mx; + y = 8 * my; + + x -= 192; + + if (x > 7 && x < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } + } + + TileIndex +=2; + } + } +} + +static void System16BRenderTextLayer(INT32 PriorityDraw) +{ + INT32 mx, my, Code, Colour, x, y, Priority, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = (System16TextRam[TileIndex + 1] << 8) | System16TextRam[TileIndex + 0]; + Priority = (Code >> 15) & 1; + + if (Priority == PriorityDraw) { + Colour = (Code >> 9) & 0x07; + Code &= 0x1ff; + + Code += System16TileBanks[0] * 0x1000; + + Code &= (System16NumTiles - 1); + + x = 8 * mx; + y = 8 * my; + + x -= 192; + + if (x > 7 && x < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } + } + + TileIndex +=2 ; + } + } +} + +static void System16BAltRenderTextLayer(INT32 PriorityDraw) +{ + INT32 mx, my, Code, Colour, x, y, Priority, TileIndex = 0; + + for (my = 0; my < 32; my++) { + for (mx = 0; mx < 64; mx++) { + Code = (System16TextRam[TileIndex + 1] << 8) | System16TextRam[TileIndex + 0]; + Priority = (Code >> 15) & 1; + + if (Priority == PriorityDraw) { + Colour = (Code >> 8) & 0x07; + Code &= 0xff; + + Code += System16TileBanks[0] * 0x1000; + + Code &= (System16NumTiles - 1); + + x = 8 * mx; + y = 8 * my; + + x -= 192; + + if (x > 7 && x < 312 && y > 7 && y < 216) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, System16TilemapColorOffset, System16Tiles); + } + } + + TileIndex +=2 ; + } + } +} + +/*==================================================== +Sprite Rendering +====================================================*/ + +static void System16DrawPixel(INT32 x, INT32 pix, INT32 colour, UINT16* pPixel) +{ + x += System16SpriteXOffset; + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (colour == (0x3f << 4)) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((((System16PaletteRam[pPixel[x] + 1] << 8) | System16PaletteRam[pPixel[x] + 0]) & 0x8000) ? (System16PaletteEntries * 2) : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour | 0x400) & (System16PaletteEntries - 1); + } + } +} + +static void System16ARenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks = System16SpriteRomSize / 0x10000; + + const UINT16 *spritebase = (const UINT16*)System16Sprites; + UINT16 *data; + + for (data = (UINT16*)System16SpriteRam; data < (UINT16*)System16SpriteRam + System16SpriteRamSize / 2; data += 8) { + if ((data[0] >> 8) > 0xf0) break; + INT32 sprpri = 1 << ((data[4] >> 0) & 0x3); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + + if (sprpri != Priority) continue; + + INT32 bottom = (data[0] >> 8) + 1; + INT32 top = (data[0] & 0xff) + 1; + INT32 xpos = (data[1] & 0x1ff) - 0xbd; + INT32 pitch = (INT16)data[2]; + UINT16 addr = data[3]; + INT32 color = ((data[4] >> 8) & 0x3f) << 4; + INT32 bank = System16SpriteBanks[(data[4] >> 4) & 0x7]; + const UINT16 *spritedata; + INT32 x, y, pix, xdelta = 1; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if ((top >= bottom) || bank == 255) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x8000 * bank; + + if (!System16ScreenFlip) { + for (y = top; y < bottom; y++) { + addr += pitch; + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + if (!(addr & 0x8000)) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[++data[7] & 0x7fff]; + + pix = (pixels >> 12) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 8) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 4) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 0) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + + if (pix == 15) break; + } + } else { + data[7] = addr + 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[--data[7] & 0x7fff]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 4) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 8) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 12) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + } else { + for (y = bottom - 3; y > top - 3; y--) { + addr += pitch; + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + if (!(addr & 0x8000)) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[++data[7] & 0x7fff]; + + pix = (pixels >> 12) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 8) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 4) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 0) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + + if (pix == 15) break; + } + } else { + data[7] = addr + 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[--data[7] & 0x7fff]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 4) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 8) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + pix = (pixels >> 12) & 0xf; System16DrawPixel(x, pix, color, pPixel); x += xdelta; + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + } + } +} + +static void System16BRenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks; + const UINT16 *spritebase; + UINT16 *data; + + spritebase = (const UINT16 *)System16Sprites; + numbanks = System16SpriteRomSize / 0x20000; + + for (data = (UINT16*)System16SpriteRam; data < (UINT16*)System16SpriteRam + System16SpriteRamSize / 2; data += 8) { + if (data[2] & 0x8000) break; + INT32 sprpri = 1 << ((data[4] >> 6) & 0x3); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + + if (sprpri != Priority) continue; + + INT32 bottom = data[0] >> 8; + INT32 top = data[0] & 0xff; + INT32 xpos = (data[1] & 0x1ff) - 0xb8; + INT32 hide = data[2] & 0x4000; + INT32 flip = data[2] & 0x100; + INT32 pitch = (INT8)(data[2] & 0xff); + UINT16 addr = data[3]; + INT32 bank = System16SpriteBanks[(data[4] >> 8) & 0xf]; + INT32 color = ((data[4] & 0x3f) << 4); + INT32 vzoom = (data[5] >> 5) & 0x1f; + INT32 hzoom = data[5] & 0x1f; + const UINT16 *spritedata; + INT32 x, y, pix, xdelta = 1; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if (hide || (top >= bottom) || bank == 255) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x10000 * bank; + + /* reset the yzoom counter */ + data[5] &= 0x03ff; + + if (!System16ScreenFlip) { + /* loop from top to bottom */ + for (y = top; y < bottom; y++) { + /* advance a row */ + addr += pitch; + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + data[5] += vzoom << 10; + if (data[5] & 0x8000) { + addr += pitch; + data[5] &= ~0x8000; + } + + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + int xacc; + + /* compute the initial X zoom accumulator; this is verified on the real PCB */ + xacc = 4 * hzoom; + + /* non-flipped case */ + if (!flip) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[++data[7]]; + + /* draw four pixels */ + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } else { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[--data[7]]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + } else { + /* loop from top to bottom */ + for (y = bottom; y > top; y--) { + /* advance a row */ + addr += pitch; + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + data[5] += vzoom << 10; + if (data[5] & 0x8000) { + addr += pitch; + data[5] &= ~0x8000; + } + + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + int xacc; + + /* compute the initial X zoom accumulator; this is verified on the real PCB */ + xacc = 4 * hzoom; + + /* non-flipped case */ + if (!flip) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[++data[7]]; + + /* draw four pixels */ + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } else { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[--data[7]]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { System16DrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + + } + } +} + +inline static void OutrunDrawPixel(INT32 x, INT32 pix, INT32 colour, INT32 shadow, UINT16* pPixel) +{ + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (shadow && pix == 0xa) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((((System16PaletteRam[pPixel[x] + 1] << 8) | System16PaletteRam[pPixel[x] + 0]) & 0x8000) ? System16PaletteEntries * 2 : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour | 0x800) & (System16PaletteEntries - 1); + } + } +} + +static void OutrunRenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks = System16SpriteRomSize / 0x40000; + const UINT32 *spritebase = (const UINT32 *)System16Sprites; + UINT16 *data; + + for (data = (UINT16*)System16SpriteRamBuff; data < (UINT16*)System16SpriteRamBuff + System16SpriteRamSize / 2; data += 8) { + if (data[0] & 0x8000) break; + INT32 sprpri = 1 << ((data[3] >> 12) & 3); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + if (sprpri != Priority) continue; + + INT32 hide = (data[0] & 0x5000); + INT32 bank = (data[0] >> 9) & 7; + INT32 top = (data[0] & 0x1ff) - 0x100; + UINT16 addr = data[1]; + INT32 pitch = (INT16)((data[2] >> 1) | ((data[4] & 0x1000) << 3)) >> 8; + INT32 xpos = data[2] & 0x1ff; + INT32 shadow = (data[3] >> 14) & 1; + INT32 vzoom = data[3] & 0x7ff; + INT32 ydelta = (data[4] & 0x8000) ? 1 : -1; + INT32 flip = (~data[4] >> 14) & 1; + INT32 xdelta = (data[4] & 0x2000) ? 1 : -1; + INT32 hzoom = data[4] & 0x7ff; + INT32 height = (data[5] >> 8) + 1; + INT32 color = (data[5] & 0x7f) << 4; + INT32 x, y, ytarget, yacc = 0, pix; + const UINT32 *spritedata; + + /* adjust X coordinate */ + /* note: the threshhold below is a guess. If it is too high, rachero will draw garbage */ + /* If it is too low, smgp won't draw the bottom part of the road */ + if (xpos < 0x80 && xdelta < 0) + xpos += 0x200; + xpos -= 0xbe; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if (hide || height == 0) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x10000 * bank; + + /* clamp to a maximum of 8x (not 100% confirmed) */ + if (vzoom < 0x40) vzoom = 0x40; + if (hzoom < 0x40) hzoom = 0x40; + + /* loop from top to bottom */ + ytarget = top + ydelta * height; + for (y = top; y != ytarget; y += ydelta) + { + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + int xacc = 0; + + /* non-flipped case */ + if (!flip) + { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; (xdelta > 0 && x <= 319) || (xdelta < 0 && x >= 0); ) + { + UINT32 pixels = spritedata[++data[7]]; + + /* draw four pixels */ + pix = (pixels >> 28) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 0) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if ((pixels & 0x000000f0) == 0x000000f0) + break; + } + } + + /* flipped case */ + else + { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; (xdelta > 0 && x <= 319) || (xdelta < 0 && x >= 0); ) + { + UINT32 pixels = spritedata[--data[7]]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 28) & 0xf; while (xacc < 0x200) { OutrunDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if ((pixels & 0x0f000000) == 0x0f000000) + break; + } + } + } + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + yacc += vzoom; + addr += pitch * (yacc >> 9); + yacc &= 0x1ff; + } + } +} + +inline static void HangonDrawPixel(INT32 x, INT32 pix, INT32 colour, INT32 shadow, UINT16* pPixel) +{ + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (shadow && pix == 0xa) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((((System16PaletteRam[pPixel[x] + 1] << 8) | System16PaletteRam[pPixel[x] + 0]) & 0x8000) ? System16PaletteEntries * 2 : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour | 0x400) & (System16PaletteEntries - 1); + } + } +} + +static void HangonRenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks = System16SpriteRomSize / 0x20000; + const UINT32 *spritebase = (UINT32*)System16Sprites; + const UINT8 *zoom = System16Prom; + UINT16 *data; + + for (data = (UINT16*)System16SpriteRam; data < (UINT16*)System16SpriteRam + System16SpriteRamSize / 2; data += 8) { + if ((data[0] >> 8) > 0xf0) break; + INT32 sprpri = ((data[2] >> 14) & 1) ? (1<<3) : (1<<1); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + + if (sprpri != Priority) continue; + + INT32 bottom = (data[0] >> 8) + 1; + INT32 top = (data[0] & 0xff) + 1; + INT32 bank = System16SpriteBanks[(data[1] >> 12) & 0x7]; + INT32 xpos = (data[1] & 0x1ff) - 0xbd; + INT32 shadow = (~data[2] >> 15) & 1; + INT32 color = (((data[2] >> 8) & 0x3f) << 4); + INT32 pitch = (INT16)(data[2] << 9) >> 9; + UINT16 addr = data[3]; + INT32 hzoom = ((data[4] >> 8) & 0x3f) << 1; + INT32 vzoom = (data[4] >> 0) & 0x3f; + INT32 x, y, pix, zaddr, zmask; + const UINT32 *spritedata; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if ((top >= bottom) || bank == 255) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x8000 * bank; + + /* determine the starting zoom address and mask */ + zaddr = (vzoom & 0x38) << 5; + zmask = 1 << (vzoom & 7); + + for (y = top; y < bottom; y++) { + addr += pitch; + + /* if the zoom bit says so, add pitch a second time */ + if (zoom[zaddr++] & zmask) + addr += pitch; + + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + INT32 xacc = 0x00; + + if (!(addr & 0x8000)) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; x <= 319; ) { + UINT32 pixels = spritedata[++data[7] & 0x7fff]; + + pix = (pixels >> 28) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 24) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 20) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 16) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + + if (pix == 15) break; + } + } else { + data[7] = addr + 1; + for (x = xpos; x <= 319; ) { + UINT32 pixels = spritedata[--data[7] & 0x7fff]; + + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 16) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 20) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 24) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + pix = (pixels >> 28) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonDrawPixel(x, pix, color, shadow, pPixel); x++; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + } +} + +inline static void HangonAltDrawPixel(INT32 x, INT32 pix, INT32 colour, UINT16* pPixel) +{ + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (colour == (0x3f << 4)) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((System16SpriteShadow) ? System16PaletteEntries * 2 : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour | 0x400) & (System16PaletteEntries - 1); + } + } +} + +static void HangonAltRenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks = System16SpriteRomSize / 0x10000; + const UINT16 *spritebase = (UINT16*)System16Sprites; + const UINT8 *zoom = System16Prom; + UINT16 *data; + + for (data = (UINT16*)System16SpriteRam; data < (UINT16*)System16SpriteRam + System16SpriteRamSize / 2; data += 8) { + if ((data[0] >> 8) > 0xf0) break; + INT32 sprpri = 1 << ((data[4] >> 0) & 0x3); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + + if (sprpri != Priority) continue; + + INT32 bottom = (data[0] >> 8) + 1; + INT32 top = (data[0] & 0xff) + 1; + INT32 bank = System16SpriteBanks[(data[1] >> 12) & 0xf]; + INT32 xpos = (data[1] & 0x1ff) - 0xbd; + INT32 pitch = (INT16)data[2]; + UINT16 addr = data[3]; + INT32 color = (((data[4] >> 8) & 0x3f) << 4); + INT32 vzoom = (data[4] >> 2) & 0x3f; + INT32 hzoom = vzoom << 1; + + INT32 x, y, pix, zaddr, zmask; + const UINT16 *spritedata; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if ((top >= bottom) || bank == 255) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x8000 * bank; + + /* determine the starting zoom address and mask */ + zaddr = (vzoom & 0x38) << 5; + zmask = 1 << (vzoom & 7); + + /* loop from top to bottom */ + for (y = top; y < bottom; y++) + { + /* advance a row */ + addr += pitch; + + /* if the zoom bit says so, add pitch a second time */ + if (zoom[zaddr++] & zmask) + addr += pitch; + + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) + { + UINT16* pPixel = pTransDraw + (y * 320); + INT32 xacc = 0x00; + + /* note that the System 16A sprites have a design flaw that allows the address */ + /* to carry into the flip flag, which is the topmost bit -- it is very important */ + /* to emulate this as the games compensate for it */ + + /* non-flipped case */ + if (!(addr & 0x8000)) + { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; x <= 319; ) + { + UINT16 pixels = spritedata[++data[7] & 0x7fff]; + + /* draw four pixels */ + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) + break; + } + } + + /* flipped case */ + else + { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; x <= 319; ) + { + UINT16 pixels = spritedata[--data[7] & 0x7fff]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0xff) + hzoom; if (xacc < 0x100) { if (x >= 0) HangonAltDrawPixel(x, pix, color, pPixel); x++; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) + break; + } + } + } + } + } +} + +inline static void BoardXDrawPixel(INT32 x, INT32 pix, INT32 colour, INT32 shadow, UINT16* pPixel) +{ + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (shadow && pix == 0xa) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((((System16PaletteRam[pPixel[x] + 1] << 8) | System16PaletteRam[pPixel[x] + 0]) & 0x8000) ? System16PaletteEntries * 2 : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour) & (System16PaletteEntries - 1); + } + } +} + +static void XBoardRenderSpriteLayer(INT32 Priority) +{ + UINT8 numbanks = System16SpriteRomSize / 0x40000; + const UINT32 *spritebase = (const UINT32 *)System16Sprites; + UINT16 *data; + + for (data = (UINT16*)System16SpriteRamBuff; data < (UINT16*)System16SpriteRamBuff + System16SpriteRamSize / 2; data += 8) { + if (data[0] & 0x8000) break; + INT32 sprpri = 1 << ((data[3] >> 12) & 3); + +#if 1 && defined FBA_DEBUG + if (sprpri != 1 && sprpri != 2 && sprpri != 4 && sprpri != 8) bprintf(PRINT_IMPORTANT, _T("Unknown Sprite Priority - %x\n"), sprpri); +#endif + if (sprpri != Priority) continue; + + INT32 hide = (data[0] & 0x5000); + INT32 bank = (data[0] >> 9) & 7; + INT32 top = (data[0] & 0x1ff) - 0x100; + UINT16 addr = data[1]; + INT32 pitch = (INT16)((data[2] >> 1) | ((data[4] & 0x1000) << 3)) >> 8; + INT32 xpos = data[2] & 0x1ff; + INT32 shadow = (data[3] >> 14) & 1; + INT32 vzoom = data[3] & 0x7ff; + INT32 ydelta = (data[4] & 0x8000) ? 1 : -1; + INT32 flip = (~data[4] >> 14) & 1; + INT32 xdelta = (data[4] & 0x2000) ? 1 : -1; + INT32 hzoom = data[4] & 0x7ff; + INT32 height = (data[5] & 0xfff) + 1; + INT32 color = (data[6] & 0xff) << 4; + INT32 x, y, ytarget, yacc = 0, pix; + const UINT32 *spritedata; + + /* adjust X coordinate */ + /* note: the threshhold below is a guess. If it is too high, rachero will draw garbage */ + /* If it is too low, smgp won't draw the bottom part of the road */ + if (xpos < 0x80 && xdelta < 0) + xpos += 0x200; + xpos -= 0xbe; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if (hide || height == 0) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x10000 * bank; + + /* clamp to a maximum of 8x (not 100% confirmed) */ + if (vzoom < 0x40) vzoom = 0x40; + if (hzoom < 0x40) hzoom = 0x40; + + /* loop from top to bottom */ + ytarget = top + ydelta * height; + for (y = top; y != ytarget; y += ydelta) + { + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + INT32 xacc = 0; + + /* non-flipped case */ + if (!flip) + { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; (xdelta > 0 && x <= 319) || (xdelta < 0 && x >= 0); ) + { + UINT32 pixels = spritedata[++data[7]]; + + /* draw four pixels */ + pix = (pixels >> 28) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 0) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if ((pixels & 0x000000f0) == 0x000000f0) + break; + } + } + + /* flipped case */ + else + { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; (xdelta > 0 && x <= 319) || (xdelta < 0 && x >= 0); ) + { + UINT32 pixels = spritedata[--data[7]]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + pix = (pixels >> 28) & 0xf; while (xacc < 0x200) { BoardXDrawPixel(x, pix, color, shadow, pPixel); x += xdelta; xacc += hzoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if ((pixels & 0x0f000000) == 0x0f000000) + break; + } + } + } + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + yacc += vzoom; + addr += pitch * (yacc >> 9); + yacc &= 0x1ff; + } + } +} + +inline static void YBoardSystem16BDrawPixel(INT32 x, INT32 pix, INT32 colour, UINT16* pPixel) +{ + if (x >= 0 && x <= 319 && pix != 0 && pix != 15) { + if (pix == 14) { + pPixel[x] &= (System16PaletteEntries - 1); + pPixel[x] += ((((System16PaletteRam[pPixel[x] + 1] << 8) | System16PaletteRam[pPixel[x] + 0]) & 0x8000) ? (System16PaletteEntries * 2) : System16PaletteEntries); + } else { + pPixel[x] = (pix | colour | 0x800) & (System16PaletteEntries - 1); + } + } +} + +static void YBoardSystem16BRenderSpriteLayer() +{ + UINT8 numbanks; + const UINT16 *spritebase; + UINT16 *data; + + spritebase = (const UINT16 *)System16Sprites; + numbanks = System16SpriteRomSize / 0x20000; + + for (data = (UINT16*)System16SpriteRam; data < (UINT16*)System16SpriteRam + System16SpriteRamSize / 2; data += 8) { + if (data[2] & 0x8000) break; + //INT32 sprpri = (data[1] >> 8) & 0x1e; + + INT32 bottom = data[0] >> 8; + INT32 top = data[0] & 0xff; + INT32 xpos = (data[1] & 0x1ff) - 0xb8; + INT32 hide = data[2] & 0x4000; + INT32 flip = data[2] & 0x100; + INT32 pitch = (INT8)(data[2] & 0xff); + UINT16 addr = data[3]; + INT32 bank = System16SpriteBanks[(data[4] >> 8) & 0xf]; + INT32 color = ((data[4] & 0x7f) << 4); + INT32 vzoom = (data[5] >> 5) & 0x1f; + INT32 hzoom = data[5] & 0x1f; + const UINT16 *spritedata; + INT32 x, y, pix, xdelta = 1; + + /* initialize the end address to the start address */ + data[7] = addr; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if (hide || (top >= bottom) || bank == 255) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x10000 * bank; + + /* reset the yzoom counter */ + data[5] &= 0x03ff; + + /* loop from top to bottom */ + for (y = top; y < bottom; y++) { + /* advance a row */ + addr += pitch; + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + data[5] += vzoom << 10; + if (data[5] & 0x8000) { + addr += pitch; + data[5] &= ~0x8000; + } + + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 223) { + UINT16* pPixel = pTransDraw + (y * 320); + int xacc; + + /* compute the initial X zoom accumulator; this is verified on the real PCB */ + xacc = 4 * hzoom; + + /* non-flipped case */ + if (!flip) { + /* start at the word before because we preincrement below */ + data[7] = addr - 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[++data[7]]; + + /* draw four pixels */ + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } else { + /* start at the word after because we predecrement below */ + data[7] = addr + 1; + for (x = xpos; ((xpos - x) & 0x1ff) != 1; ) { + UINT16 pixels = spritedata[--data[7]]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 4) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 8) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + pix = (pixels >> 12) & 0xf; xacc = (xacc & 0x3f) + hzoom; if (xacc < 0x40) { YBoardSystem16BDrawPixel(x, pix, color, pPixel); x += xdelta; } + + /* stop if the last pixel in the group was 0xf */ + if (pix == 15) break; + } + } + } + } + } +} + +inline static void YBoardDrawPixel(INT32 x, UINT32 ind, UINT32 colourpri, UINT16* pPixel) +{ + if (x >= 0 && x <= 511 && ind < 0x1fe) { + pPixel[x] = (ind | colourpri | 0x1000)/* & (System16PaletteEntries - 1)*/; + } +} + +static void YBoardRenderSpriteLayer() +{ + UINT8 numbanks = System16Sprite2RomSize / 0x80000; + const UINT64 *spritebase = (const UINT64 *)System16Sprites2; + const UINT16 *rotatebase = (UINT16*)System16RotateRamBuff; + UINT8 visited[0x1000]; + UINT16 *data; + INT32 next = 0; + + /* reset the visited list */ + memset(visited, 0, sizeof(visited)); + + for (INT32 y = 0; y <= 511; y++) + if (!(rotatebase[y & ~1] & 0xc000)) + memset(pTempDraw + (y * 512), 0xff, 512 * sizeof(UINT16)); + + for (data = (UINT16*)System16SpriteRam2; !(data[0] & 0x8000) && !visited[next]; data = (UINT16*)System16SpriteRam2 + next * 8) + { + INT32 hide = (data[0] & 0x5000); + UINT16 *indirect = (UINT16*)System16SpriteRam2 + ((data[0] & 0x7ff) << 4); + INT32 bank = ((data[1] >> 8) & 0x10) | ((data[2] >> 12) & 0x0f); + INT32 xpos = (data[1] & 0xfff) - 0x600; + INT32 top = (data[2] & 0xfff) - 0x600; + UINT16 addr = data[3]; + INT32 height = data[4]; + INT32 ydelta = (data[5] & 0x4000) ? 1 : -1; + INT32 flip = (~data[5] >> 13) & 1; + INT32 xdelta = (data[5] & 0x1000) ? 1 : -1; + INT32 zoom = data[5] & 0x7ff; + INT32 colorpri= (data[6] << 1) & 0xfe00; + INT32 pitch = (INT8)data[6]; + INT32 x, y, ytarget, yacc = 0, pix, ind; + const UINT64 *spritedata; + UINT16 offs; + + /* note that we've visited this entry and get the offset of the next one */ + visited[next] = 1; + next = data[7] & 0xfff; + + /* if hidden, or top greater than/equal to bottom, or invalid bank, punt */ + if (hide || height == 0) + continue; + + /* clamp to within the memory region size */ + if (numbanks) + bank %= numbanks; + spritedata = spritebase + 0x10000 * bank; + + /* clamp to a maximum of 8x (not 100% confirmed) */ + if (zoom == 0) zoom = 1; + + /* loop from top to bottom */ + ytarget = top + ydelta * height; + for (y = top; y != ytarget; y += ydelta) + { + /* skip drawing if not within the cliprect */ + if (y >= 0 && y <= 511) + { + //UINT16* pPixel = pTransDraw + (y * 320); + UINT16* pPixel = pTempDraw + (y * 512); + INT32 minx = rotatebase[y & ~1]; + INT32 maxx = rotatebase[y | 1]; + INT32 xacc = 0; + + /* bit 0x8000 from rotate RAM means that Y is above the top of the screen */ + if ((minx & 0x8000) && ydelta < 0) + break; + + /* bit 0x4000 from rotate RAM means that Y is below the bottom of the screen */ + if ((minx & 0x4000) && ydelta > 0) + break; + + /* if either bit is set, skip the rest for this scanline */ + if (!(minx & 0xc000)) + { + /* clamp min/max to the cliprect */ + minx -= 0x600; + maxx -= 0x600; + if (minx < 0) + minx = 0; + if (maxx > 511) + maxx = 511; + + /* non-flipped case */ + if (!flip) + { + /* start at the word before because we preincrement below */ + offs = addr - 1; + for (x = xpos; (xdelta > 0 && x <= maxx) || (xdelta < 0 && x >= minx); ) + { + UINT64 pixels = spritedata[++offs]; + + /* draw four pixels */ + pix = (pixels >> 60) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 56) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 52) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 48) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 44) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 40) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 36) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 32) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 28) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 0) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if (pix == 0x0f) + break; + } + } + + /* flipped case */ + else + { + /* start at the word after because we predecrement below */ + offs = addr + 1; + for (x = xpos; (xdelta > 0 && x <= maxx) || (xdelta < 0 && x >= minx); ) + { + UINT64 pixels = spritedata[--offs]; + + /* draw four pixels */ + pix = (pixels >> 0) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 4) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 8) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 12) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 16) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 20) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 24) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 28) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 32) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 36) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 40) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 44) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 48) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 52) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 56) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + pix = (pixels >> 60) & 0xf; ind = indirect[pix]; while (xacc < 0x200) { YBoardDrawPixel(x, ind, colorpri, pPixel); x += xdelta; xacc += zoom; } xacc -= 0x200; + + /* stop if the second-to-last pixel in the group was 0xf */ + if (pix == 0x0f) + break; + } + } + } + } + + /* accumulate zoom factors; if we carry into the high bit, skip an extra row */ + yacc += zoom; + addr += pitch * (yacc >> 9); + yacc &= 0x1ff; + } + } +} + +/*==================================================== +Road Rendering +====================================================*/ + +static void OutrunRenderRoadBackgroundLayer() +{ + UINT16 *roadram = (UINT16*)System16RoadRam; + INT32 x, y; + + for (y = 0; y < 224; y++) { + UINT16* pPixel = pTransDraw + (y * 320); + INT32 data0 = roadram[0x000 + y]; + INT32 data1 = roadram[0x100 + y]; + + INT32 color = -1; + + switch (System16RoadControl & 3) { + case 0: { + if (data0 & 0x800) color = data0 & 0x7f; + break; + } + + case 1: { + if (data0 & 0x800) color = data0 & 0x7f; + else if (data1 & 0x800) color = data1 & 0x7f; + break; + } + + case 2: { + if (data1 & 0x800) color = data1 & 0x7f; + else if (data0 & 0x800) color = data0 & 0x7f; + break; + } + + case 3: { + if (data1 & 0x800) color = data1 & 0x7f; + break; + } + } + + if (color != -1) { + for (x = 0; x < 320; x++) { + pPixel[x] = color | System16RoadColorOffset3; + } + } + } +} + +static void OutrunRenderRoadForegroundLayer() +{ + UINT16 *roadram = (UINT16*)System16RoadRam; + INT32 x, y; + + for (y = 0; y < 224; y++) { + static const UINT8 priority_map[2][8] = { + { 0x80,0x81,0x81,0x87,0,0,0,0x00 }, + { 0x81,0x81,0x81,0x8f,0,0,0,0x80 } + }; + + UINT16* pPixel = pTransDraw + (y * 320); + INT32 data0 = roadram[0x000 + y]; + INT32 data1 = roadram[0x100 + y]; + + /* if both roads are low priority, skip */ + if ((data0 & 0x800) && (data1 & 0x800)) continue; + + INT32 hpos0, hpos1, color0, color1; + INT32 control = System16RoadControl & 3; + UINT16 color_table[32]; + UINT8 *src0, *src1; + UINT8 bgcolor; + + /* get road 0 data */ + src0 = (data0 & 0x800) ? System16Roads + 256 * 2 * 512 : (System16Roads + (0x000 + ((data0 >> 1) & 0xff)) * 512); + hpos0 = (roadram[0x200 + ((System16RoadControl & 4) ? y : (data0 & 0x1ff))]) & 0xfff; + color0 = roadram[0x600 + ((System16RoadControl & 4) ? y : (data0 & 0x1ff))]; + + /* get road 1 data */ + src1 = (data1 & 0x800) ? System16Roads + 256 * 2 * 512 : (System16Roads + (0x100 + ((data1 >> 1) & 0xff)) * 512); + hpos1 = (roadram[0x400 + ((System16RoadControl & 4) ? (0x100 + y) : (data1 & 0x1ff))]) & 0xfff; + color1 = roadram[0x600 + ((System16RoadControl & 4) ? (0x100 + y) : (data1 & 0x1ff))]; + + /* determine the 5 colors for road 0 */ + color_table[0x00] = System16RoadColorOffset1 ^ 0x00 ^ ((color0 >> 0) & 1); + color_table[0x01] = System16RoadColorOffset1 ^ 0x02 ^ ((color0 >> 1) & 1); + color_table[0x02] = System16RoadColorOffset1 ^ 0x04 ^ ((color0 >> 2) & 1); + bgcolor = (color0 >> 8) & 0xf; + color_table[0x03] = (data0 & 0x200) ? color_table[0x00] : (System16RoadColorOffset2 ^ 0x00 ^ bgcolor); + color_table[0x07] = System16RoadColorOffset1 ^ 0x06 ^ ((color0 >> 3) & 1); + + /* determine the 5 colors for road 1 */ + color_table[0x10] = System16RoadColorOffset1 ^ 0x08 ^ ((color1 >> 4) & 1); + color_table[0x11] = System16RoadColorOffset1 ^ 0x0a ^ ((color1 >> 5) & 1); + color_table[0x12] = System16RoadColorOffset1 ^ 0x0c ^ ((color1 >> 6) & 1); + bgcolor = (color1 >> 8) & 0xf; + color_table[0x13] = (data1 & 0x200) ? color_table[0x10] : (System16RoadColorOffset2 ^ 0x10 ^ bgcolor); + color_table[0x17] = System16RoadColorOffset1 ^ 0x0e ^ ((color1 >> 7) & 1); + + /* draw the road */ + switch (control) { + case 0: { + if (data0 & 0x800) continue; + hpos0 = (hpos0 - (0x5f8 + System16RoadXOffset)) & 0xfff; + for (x = 0; x < 320; x++) { + INT32 pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3; + pPixel[x] = color_table[0x00 + pix0]; + hpos0 = (hpos0 + 1) & 0xfff; + } + break; + } + + case 1: { + hpos0 = (hpos0 - (0x5f8 + System16RoadXOffset)) & 0xfff; + hpos1 = (hpos1 - (0x5f8 + System16RoadXOffset)) & 0xfff; + for (x = 0; x < 320; x++) { + INT32 pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3; + INT32 pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3; + if ((priority_map[0][pix0] >> pix1) & 1) { + pPixel[x] = color_table[0x10 + pix1]; + } else { + pPixel[x] = color_table[0x00 + pix0]; + } + hpos0 = (hpos0 + 1) & 0xfff; + hpos1 = (hpos1 + 1) & 0xfff; + } + break; + } + + case 2: { + hpos0 = (hpos0 - (0x5f8 + System16RoadXOffset)) & 0xfff; + hpos1 = (hpos1 - (0x5f8 + System16RoadXOffset)) & 0xfff; + for (x = 0; x < 320; x++) { + INT32 pix0 = (hpos0 < 0x200) ? src0[hpos0] : 3; + INT32 pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3; + if ((priority_map[1][pix0] >> pix1) & 1) { + pPixel[x] = color_table[0x10 + pix1]; + } else { + pPixel[x] = color_table[0x00 + pix0]; + } + hpos0 = (hpos0 + 1) & 0xfff; + hpos1 = (hpos1 + 1) & 0xfff; + } + break; + } + + case 3: { + if (data1 & 0x800) continue; + hpos1 = (hpos1 - (0x5f8 + System16RoadXOffset)) & 0xfff; + for (x = 0; x < 320; x++) { + INT32 pix1 = (hpos1 < 0x200) ? src1[hpos1] : 3; + pPixel[x] = color_table[0x10 + pix1]; + hpos1 = (hpos1 + 1) & 0xfff; + } + break; + } + } + } +} + +static void HangonRenderRoadLayer(INT32 priority) +{ + UINT16 *roadram = (UINT16*)System16RoadRam; + INT32 x, y; + + for (y = 0; y <= 223; y++) + { + UINT16* pPixel = pTransDraw + (y * 320); + INT32 control = roadram[0x000 + y]; + INT32 ff9j1 = 0, ff9j2 = 0, ctr9m = 0, ctr9n9p = 0, ctr9n9p_ena = 0, ss8j = 0, plycont = 0; + + /* the PLYCONT signal controls the road layering */ + plycont = (control >> 10) & 3; + + if (plycont != priority) continue; + + INT32 hpos = roadram[0x100 + (control & 0xff)]; + INT32 color0 = roadram[0x200 + (control & 0xff)]; + INT32 color1 = roadram[0x300 + (control & 0xff)]; + UINT8 *src; + + /* compute the offset of the road graphics for this line */ + src = System16Roads + (0x000 + (control & 0xff)) * 512; + + /* initialize the 4-bit counter at 9M, which counts bits within each road byte */ + ctr9m = hpos & 7; + + /* initialize the two 4-bit counters at 9P (low) and 9N (high), which count road data bytes */ + ctr9n9p = (hpos >> 3) & 0xff; + + /* initialize the flip-flop at 9J (lower half), which controls the counting direction */ + ff9j1 = (hpos >> 11) & 1; + + /* initialize the flip-flop at 9J (upper half), which controls the background color */ + ff9j2 = 1; + + /* initialize the serial shifter at 8S, which delays several signals after we flip */ + ss8j = 0; + + /* draw this scanline from the beginning */ + for (x = -24; x <= 319; x++) + { + INT32 md, color, select; + + /* ---- the following logic all happens constantly ---- */ + + /* the enable is controlled by the value in the counter at 9M */ + ctr9n9p_ena = (ctr9m == 7); + + /* if we carried out of the 9P/9N counters, we will forcibly clear the flip-flop at 9J (lower half) */ + if ((ctr9n9p & 0xff) == 0xff) + ff9j1 = 0; + + /* if the control word bit 8 is clear, we will forcibly set the flip-flop at 9J (lower half) */ + if (!(control & 0x100)) + ff9j1 = 1; + + /* for the Hang On/Super Hang On case only: if the control word bit 9 is clear, we will forcibly */ + /* set the flip-flip at 9J (upper half) */ + if (Hangon && !(control & 0x200)) + ff9j2 = 1; + + /* ---- now process the pixel ---- */ + md = 3; + + /* the Space Harrier/Enduro Racer hardware has a tweak that maps the control word bit 9 to the */ + /* /CE line on the road ROM; use this to effectively disable the road data */ + if (Hangon || !(control & 0x200)) + + /* the /OE line on the road ROM is linked to the AND of bits 2 & 3 of the counter at 9N */ + if ((ctr9n9p & 0xc0) == 0xc0) + { + /* note that the pixel logic is hidden in a custom at 9S; this is just a guess */ + if (ss8j & 1) + md = src[((ctr9n9p & 0x3f) << 3) | ctr9m]; + else + md = src[((ctr9n9p & 0x3f) << 3) | (ctr9m ^ 7)]; + } + + /* "select" is a made-up signal that comes from bit 3 of the serial shifter and is */ + /* used in several places for color selection */ + select = (ss8j >> 3) & 1; + + /* check the flip-flop at 9J (upper half) to determine if we should use the background color; */ + /* the output of this is ANDed with M0 and M1 so it only affects pixels with a value of 3; */ + /* this is done by the AND gates at 9L and 7K */ + if (ff9j2 && md == 3) + { + /* in this case, the "select" signal is used to select which background color to use */ + /* since the color0 control word contains two selections */ + color = (color0 >> (select ? 0 : 8)) & 0x3f; + color |= 0x7c0; + } + + /* if we're not using the background color, we select pixel data from an alternate path */ + else + { + /* the AND gates at 7L, 9K, and 7K clamp the pixel value to 0 if bit 7 of the color 1 */ + /* signal is 1 and if the pixel value is 3 (both M0 and M1 == 1) */ + if ((color1 & 0x80) && md == 3) + md = 0; + + /* the pixel value plus the "select" line combine to form a mux into the low 8 bits of color1 */ + color = (color1 >> ((md << 1) | select)) & 1; + + /* this value becomes the low bit of the final color; the "select" line itself and the pixel */ + /* value form the other bits */ + color |= select << 3; + color |= md << 1; + color |= 0x038; + } + + /* write the pixel if we're past the minimum clip */ + if (x >= 0) + pPixel[x] = color; + + /* ---- the following logic all happens on the 6M clock ---- */ + + /* clock the counter at 9M */ + ctr9m = (ctr9m + 1) & 7; + + /* if enabled, clock on the two cascaded 4-bit counters at 9P and 9N */ + if (ctr9n9p_ena) + { + if (ff9j1) + ctr9n9p++; + else + ctr9n9p--; + } + + /* clock the flip-flop at 9J (upper half) */ + ff9j2 = !(!ff9j1 && (ss8j & 0x80)); + + /* clock the serial shift register at 8J */ + ss8j = (ss8j << 1) | ff9j1; + } + } +} + +/*==================================================== +Rotation Layer Rendering +====================================================*/ + +void System16RotateDraw() +{ + UINT16 *pRotateBuff = (UINT16*)System16RotateRamBuff; + + INT32 currx = (pRotateBuff[0x3f0] << 16) | pRotateBuff[0x3f1]; + INT32 curry = (pRotateBuff[0x3f2] << 16) | pRotateBuff[0x3f3]; + INT32 dyy = (pRotateBuff[0x3f4] << 16) | pRotateBuff[0x3f5]; + INT32 dxx = (pRotateBuff[0x3f6] << 16) | pRotateBuff[0x3f7]; + INT32 dxy = (pRotateBuff[0x3f8] << 16) | pRotateBuff[0x3f9]; + INT32 dyx = (pRotateBuff[0x3fa] << 16) | pRotateBuff[0x3fb]; + INT32 x, y; + + /* advance forward based on the clip rect */ + currx += dxx * (0 + 27) + dxy * 0; + curry += dyx * (0 + 27) + dyy * 0; + + /* loop over screen Y coordinates */ + for (y = 0; y <= 223; y++) + { + UINT16* pPixel = pTransDraw + (y * 320); + UINT16* pSrc = pTempDraw; + INT32 tx = currx; + INT32 ty = curry; + + /* loop over screen X coordinates */ + for (x = 0; x <= 319; x++) + { + /* fetch the pixel from the source bitmap */ + INT32 sx = (tx >> 14) & 0x1ff; + INT32 sy = (ty >> 14) & 0x1ff; + INT32 pix = pSrc[sy * 512 + (sx & 0x1ff)]; + + /* non-zero pixels get written; everything else is the scanline color */ + if (pix != 0xffff) + { + *pPixel++ = ((pix & 0x1ff) | ((pix >> 6) & 0x200) | ((pix >> 3) & 0xc00) | 0x1000) & (System16PaletteEntries - 1); + } + else + { + *pPixel++ = /*info->colorbase +*/ sy; + } + + /* advance the source X/Y pointers */ + tx += dxx; + ty += dyx; + } + + /* advance the source X/Y pointers */ + currx += dxy; + curry += dyy; + } +} + +/*==================================================== +Genesis VDP Rendering +====================================================*/ + +static void System18DrawVDP() +{ + INT32 x, y; + + for (y = 0; y < 224; y++) + { + UINT16 *src = pTempDraw + (y * 320); + UINT16 *dst = pTransDraw + (y * 320); + + for (x = 0; x < 320; x++) + { + UINT16 pix = src[x]; + if (pix != 0xffff) + { + dst[x] = pix; + } + } + } +} + +void UpdateSystem18VDP() +{ + for (INT32 y = 0; y < 224; y++) { + UINT16* pPixel = pTempDraw + (y * 320); + vdp_drawline(pPixel, y, 0xffff); + } +} + +/*==================================================== +Palette Generation +====================================================*/ + +static INT32 System16CalcPalette() +{ + INT32 i; + + for (i = 0; i < System16PaletteEntries * 2; i +=2) { + INT32 r, g, b; + INT32 nColour = (System16PaletteRam[i + 1] << 8) | System16PaletteRam[i + 0]; + + r = (nColour & 0x00f) << 1; + g = (nColour & 0x0f0) >> 2; + b = (nColour & 0xf00) >> 7; + + if (nColour & 0x1000) r |= 1; + if (nColour & 0x2000) g |= 2; + if (nColour & 0x8000) g |= 1; + if (nColour & 0x4000) b |= 1; + + r = (r << 3) | (r >> 2); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + + System16Palette[i / 2] = BurnHighCol(r, g, b, 0); + + r = r * 160 / 256; + g = g * 160 / 256; + b = b * 160 / 256; + + System16Palette[(i / 2) + System16PaletteEntries] = BurnHighCol(r, g, b, 0); + System16Palette[(i / 2) + (System16PaletteEntries * 2)] = BurnHighCol(r, g, b, 0); + } + + return 0; +} + +/*==================================================== +Frame Rendering +====================================================*/ + +inline static void System16AUpdateTileValues() +{ + UINT16 *TextRam = (UINT16*)System16TextRam; + INT32 i; + + for (i = 0; i < 2; i++) { + System16OldPage[i] = System16Page[i]; + System16Page[i] = (System16ScreenFlip) ? TextRam[0xe8e/2 - i] : TextRam[0xe9e/2 - i]; + System16ScrollX[i] = TextRam[0xff8/2 + i] & 0x1ff; + System16ScrollY[i] = TextRam[0xf24/2 + i] & 0x0ff; + } + + if (System16OldPage[0] != System16Page[0]) { + System16RecalcFgTileMap = 1; + } + + if (System16OldPage[1] != System16Page[1]) { + System16RecalcBgTileMap = 1; + } +} + +void System16ARender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16AUpdateTileValues(); + System16ACreateTileMaps(); + + System16CalcPalette(); + System16ARenderTileLayer(1, 0, 0); + System16ARenderSpriteLayer(1); + System16ARenderTileLayer(1, 0, 1); + System16ARenderSpriteLayer(2); + System16ARenderTileLayer(1, 1, 1); + System16ARenderTileLayer(0, 0, 1); + System16ARenderSpriteLayer(4); + System16ARenderTileLayer(0, 1, 1); + System16ARenderTextLayer(0); + System16ARenderSpriteLayer(8); + System16ARenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void System16BootlegRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16CalcPalette(); + BootlegRenderTileLayer(1, 0, 0); + BootlegRenderTileLayer(1, 1, 0); + System16BRenderSpriteLayer(1); + BootlegRenderTileLayer(1, 0, 1); + System16BRenderSpriteLayer(2); + BootlegRenderTileLayer(1, 1, 1); + BootlegRenderTileLayer(0, 0, 1); + System16BRenderSpriteLayer(4); + BootlegRenderTileLayer(0, 1, 1); + System16BRenderTextLayer(0); + System16BRenderSpriteLayer(8); + System16BRenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +inline static void System16BUpdateTileValues() +{ + UINT16 *TextRam = (UINT16*)System16TextRam; + + for (INT32 i = 0; i < 4; i++) { + System16OldPage[i] = System16Page[i]; + System16Page[i] = TextRam[(0xe80 >> 1) + i]; + System16ScrollX[i] = TextRam[(0xe98 >> 1) + i]; + System16ScrollY[i] = TextRam[(0xe90 >> 1) + i]; + } + + if (System16OldPage[0] != System16Page[0]) { + System16RecalcFgTileMap = 1; + } + + if (System16OldPage[1] != System16Page[1]) { + System16RecalcBgTileMap = 1; + } + + if (System16OldPage[2] != System16Page[2]) { + System16RecalcFgAltTileMap = 1; + } + + if (System16OldPage[3] != System16Page[3]) { + System16RecalcBgAltTileMap = 1; + } +} + +void System16BRender() +{ + if (!System16IgnoreVideoEnable) { + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + } + + System16BUpdateTileValues(); + System16BCreateTileMaps(); + + System16CalcPalette(); + System16BRenderTileLayer(1, 0, 0); + System16BRenderSpriteLayer(1); + System16BRenderTileLayer(1, 0, 1); + System16BRenderSpriteLayer(2); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + System16BRenderSpriteLayer(4); + System16BRenderTileLayer(0, 1, 1); + System16BRenderTextLayer(0); + System16BRenderSpriteLayer(8); + System16BRenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void System16BAltRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16BUpdateTileValues(); + System16BAltCreateTileMaps(); + + System16CalcPalette(); + System16BRenderTileLayer(1, 0, 0); + System16BRenderSpriteLayer(1); + System16BRenderTileLayer(1, 0, 1); + System16BRenderSpriteLayer(2); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + System16BRenderSpriteLayer(4); + System16BRenderTileLayer(0, 1, 1); + System16BAltRenderTextLayer(0); + System16BRenderSpriteLayer(8); + System16BAltRenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void System18Render() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + INT32 VDPLayer = (System18VdpMixing >> 1) & 3; + INT32 VDPPri = (System18VdpMixing & 1) ? (1 << VDPLayer) : 0; + + System16BUpdateTileValues(); + System16BCreateTileMaps(); + + System16CalcPalette(); + + if (System18VdpEnable) UpdateSystem18VDP(); + + System16BRenderTileLayer(1, 0, 0); + if (System18VdpEnable && VDPLayer == 0 && !VDPPri) System18DrawVDP(); + System16BRenderSpriteLayer(1); + if (System18VdpEnable && VDPLayer == 0 && VDPPri) System18DrawVDP(); + System16BRenderTileLayer(1, 0, 1); + if (System18VdpEnable && VDPLayer == 1 && !VDPPri) System18DrawVDP(); + System16BRenderSpriteLayer(2); + if (System18VdpEnable && VDPLayer == 1 && VDPPri) System18DrawVDP(); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + if (System18VdpEnable && VDPLayer == 2 && !VDPPri) System18DrawVDP(); + System16BRenderSpriteLayer(4); + if (System18VdpEnable && VDPLayer == 2 && VDPPri) System18DrawVDP(); + System16BRenderTileLayer(0, 1, 1); + System16BRenderTextLayer(0); + if (System18VdpEnable && VDPLayer == 3 && !VDPPri) System18DrawVDP(); + System16BRenderSpriteLayer(8); + if (System18VdpEnable && VDPLayer == 3 && VDPPri) System18DrawVDP(); + System16BRenderTextLayer(1); + BurnTransferCopy(System16Palette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +void HangonRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16CalcPalette(); + + System16AUpdateTileValues(); + System16ACreateTileMaps(); + + HangonRenderRoadLayer(0); + HangonRenderSpriteLayer(1); + System16ARenderTileLayer(1, 0, 1); + HangonRenderSpriteLayer(2); + System16ARenderTileLayer(1, 1, 1); + System16ARenderTileLayer(0, 0, 1); + HangonRenderSpriteLayer(4); + System16ARenderTileLayer(0, 1, 1); + HangonRenderRoadLayer(1); + HangonRenderSpriteLayer(8); + System16ARenderTextLayer(0); + System16ARenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void HangonAltRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16CalcPalette(); + + System16AUpdateTileValues(); + System16ACreateTileMaps(); + + HangonRenderRoadLayer(0); + HangonAltRenderSpriteLayer(1); + System16ARenderTileLayer(1, 0, 1); + HangonAltRenderSpriteLayer(2); + System16ARenderTileLayer(1, 1, 1); + System16ARenderTileLayer(0, 0, 1); + HangonAltRenderSpriteLayer(4); + System16ARenderTileLayer(0, 1, 1); + HangonRenderRoadLayer(1); + HangonAltRenderSpriteLayer(8); + System16ARenderTextLayer(0); + System16ARenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void OutrunRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16BUpdateTileValues(); + System16BCreateTileMaps(); + + System16CalcPalette(); + OutrunRenderRoadBackgroundLayer(); + OutrunRenderSpriteLayer(1); + System16BRenderTileLayer(1, 0, 1); + OutrunRenderSpriteLayer(2); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + OutrunRenderSpriteLayer(4); + System16BRenderTileLayer(0, 1, 1); + OutrunRenderRoadForegroundLayer(); + System16BRenderTextLayer(0); + OutrunRenderSpriteLayer(8); + System16BRenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void ShangonRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16BUpdateTileValues(); + System16BAltCreateTileMaps(); + + System16CalcPalette(); + OutrunRenderRoadBackgroundLayer(); + System16BRenderSpriteLayer(1); + System16BRenderTileLayer(1, 0, 1); + System16BRenderSpriteLayer(2); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + System16BRenderSpriteLayer(4); + System16BRenderTileLayer(0, 1, 1); + OutrunRenderRoadForegroundLayer(); + System16BRenderSpriteLayer(8); + System16BAltRenderTextLayer(0); + System16BAltRenderTextLayer(1); + BurnTransferCopy(System16Palette); +} + +void XBoardRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16BUpdateTileValues(); + System16BCreateTileMaps(); + + System16CalcPalette(); + OutrunRenderRoadBackgroundLayer(); + if (!System16RoadPriority) OutrunRenderRoadForegroundLayer(); + XBoardRenderSpriteLayer(1); + System16BRenderTileLayer(1, 0, 1); + XBoardRenderSpriteLayer(2); + System16BRenderTileLayer(1, 1, 1); + System16BRenderTileLayer(0, 0, 1); + XBoardRenderSpriteLayer(4); + System16BRenderTileLayer(0, 1, 1); + if (System16RoadPriority) OutrunRenderRoadForegroundLayer(); + System16BRenderTextLayer(0); + XBoardRenderSpriteLayer(8); + System16BRenderTextLayer(1); + BurnTransferCopy(System16Palette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +void YBoardRender() +{ + if (!System16VideoEnable) { + BurnTransferClear(); + return; + } + + System16CalcPalette(); + YBoardRenderSpriteLayer(); + System16RotateDraw(); + YBoardSystem16BRenderSpriteLayer(); + BurnTransferCopy(System16Palette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} diff --git a/src/burn/drivers/sega/sys16_run.cpp b/src/burn/drivers/sega/sys16_run.cpp new file mode 100644 index 00000000..0f1dce73 --- /dev/null +++ b/src/burn/drivers/sega/sys16_run.cpp @@ -0,0 +1,3304 @@ +#include "sys16.h" +#include "dac.h" +#include "i8039.h" +#include "mc8123.h" +#include "upd7759.h" +#include "segapcm.h" + +UINT8 System16InputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort5[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16InputPort6[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +UINT8 System16Gear = 0; +INT32 System16AnalogPort0 = 0; +INT32 System16AnalogPort1 = 0; +INT32 System16AnalogPort2 = 0; +INT32 System16AnalogPort3 = 0; +INT32 System16AnalogPort4 = 0; +INT32 System16AnalogPort5 = 0; +INT32 System16AnalogSelect = 0; +UINT8 System16Dip[3] = {0, 0, 0}; +UINT8 System16Input[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +UINT8 System16Reset = 0; + +UINT8 *Mem = NULL; +UINT8 *MemEnd = NULL; +UINT8 *RamStart = NULL; +UINT8 *RamEnd = NULL; +UINT8 *System16Rom = NULL; +UINT8 *System16Code = NULL; +UINT8 *System16Rom2 = NULL; +UINT8 *System16Rom3 = NULL; +UINT8 *System16Z80Rom = NULL; +UINT8 *System16Z80Code = NULL; +UINT8 *System16Z80Rom2 = NULL; +UINT8 *System16Z80Rom3 = NULL; +UINT8 *System16Z80Rom4 = NULL; +UINT8 *System167751Prog = NULL; +UINT8 *System167751Data = NULL; +UINT8 *System16UPD7759Data = NULL; +UINT8 *System16PCMData = NULL; +UINT8 *System16PCM2Data = NULL; +UINT8 *System16RF5C68Data = NULL; +UINT8 *System16Prom = NULL; +UINT8 *System16Key = NULL; +UINT8 *System16Ram = NULL; +UINT8 *System16ExtraRam = NULL; +UINT8 *System16ExtraRam2 = NULL; +UINT8 *System16ExtraRam3 = NULL; +UINT8 *System16BackupRam = NULL; +UINT8 *System16BackupRam2 = NULL; +UINT8 *System16Z80Ram = NULL; +UINT8 *System16TileRam = NULL; +UINT8 *System16TextRam = NULL; +UINT8 *System16SpriteRam = NULL; +UINT8 *System16SpriteRamBuff = NULL; +UINT8 *System16SpriteRam2 = NULL; +UINT8 *System16RotateRam = NULL; +UINT8 *System16RotateRamBuff = NULL; +UINT8 *System16PaletteRam = NULL; +UINT8 *System16RoadRam = NULL; +UINT8 *System16RoadRamBuff = NULL; +UINT8 *System16Tiles = NULL; +UINT8 *System16Sprites = NULL; +UINT8 *System16Sprites2 = NULL; +UINT8 *System16Roads = NULL; +UINT32 *System16Palette = NULL; +UINT8 *System16TempGfx = NULL; + +UINT32 System16RomSize = 0; +UINT32 System16RomNum = 0; +UINT32 System16Rom2Size = 0; +UINT32 System16Rom2Num = 0; +UINT32 System16Rom3Size = 0; +UINT32 System16Rom3Num = 0; +UINT32 System16TileRomSize = 0; +UINT32 System16TileRomNum = 0; +UINT32 System16NumTiles = 0; +UINT32 System16SpriteRomSize = 0; +UINT32 System16SpriteRomNum = 0; +UINT32 System16Sprite2RomSize = 0; +UINT32 System16Sprite2RomNum = 0; +UINT32 System16RoadRomSize = 0; +UINT32 System16RoadRomNum = 0; +UINT32 System16Z80RomSize = 0; +UINT32 System16Z80RomNum = 0; +UINT32 System16Z80Rom2Size = 0; +UINT32 System16Z80Rom2Num = 0; +UINT32 System16Z80Rom3Size = 0; +UINT32 System16Z80Rom3Num = 0; +UINT32 System16Z80Rom4Size = 0; +UINT32 System16Z80Rom4Num = 0; +UINT32 System167751ProgSize = 0; +UINT32 System167751ProgNum = 0; +UINT32 System167751DataSize = 0; +UINT32 System167751DataNum = 0; +UINT32 System16UPD7759DataSize = 0; +UINT32 System16UPD7759DataNum = 0; +UINT32 System16PCMDataSize = 0; +UINT32 System16PCMDataNum = 0; +UINT32 System16PCMDataSizePreAllocate = 0; +UINT32 System16PCM2DataSize = 0; +UINT32 System16PCM2DataNum = 0; +UINT32 System16RF5C68DataSize = 0; +UINT32 System16RF5C68DataNum = 0; +UINT32 System16PromSize = 0; +UINT32 System16PromNum = 0; +UINT32 System16KeySize = 0; +UINT32 System16RamSize = 0; +UINT32 System16ExtraRamSize = 0; +UINT32 System16ExtraRam2Size = 0; +UINT32 System16ExtraRam3Size = 0; +UINT32 System16SpriteRamSize = 0; +UINT32 System16SpriteRam2Size = 0; +UINT32 System16RotateRamSize = 0; +UINT32 System16BackupRamSize = 0; +UINT32 System16BackupRam2Size = 0; + +static INT32 System16LastGear; +bool System16HasGears = false; + +UINT8 System16VideoControl; +INT32 System16SoundLatch; +bool System16BTileAlt = false; +bool Shangon = false; +bool Hangon = false; +bool System16Z80Enable = true; + +INT32 nSystem16CyclesDone[4]; +static INT32 nCyclesTotal[4]; +static INT32 nCyclesSegment; +UINT32 System16ClockSpeed = 0; + +INT32 YBoardIrq2Scanline = 0; + +INT32 System16YM2413IRQInterval; + +static bool bUseAsm68KCoreOldValue = false; + +static UINT8 N7751Command; +static UINT32 N7751RomAddress; +static UINT32 UPD7759BankAddress; + +Sim8751 Simulate8751; +System16Map68K System16Map68KDo; +System16MapZ80 System16MapZ80Do; +System16CustomLoadRom System16CustomLoadRomDo; +System16CustomDecryptOpCode System16CustomDecryptOpCodeDo; +System16ProcessAnalogControls System16ProcessAnalogControlsDo; +System16MakeAnalogInputs System16MakeAnalogInputsDo; + +/*==================================================== +Inputs +====================================================*/ + +inline static void System16ClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x30) == 0x30) { + *nJoystickInputs &= ~0x30; + } + if ((*nJoystickInputs & 0xc0) == 0xc0) { + *nJoystickInputs &= ~0xc0; + } +} + +inline static void System16MakeInputs() +{ + // Reset Inputs + System16Input[0] = System16Input[1] = System16Input[2] = System16Input[3] = System16Input[4] = System16Input[5] = System16Input[6] = 0; + + // Compile Digital Inputs + for (int i = 0; i < 8; i++) { + System16Input[0] |= (System16InputPort0[i] & 1) << i; + System16Input[1] |= (System16InputPort1[i] & 1) << i; + System16Input[2] |= (System16InputPort2[i] & 1) << i; + System16Input[3] |= (System16InputPort3[i] & 1) << i; + System16Input[4] |= (System16InputPort4[i] & 1) << i; + System16Input[5] |= (System16InputPort5[i] & 1) << i; + System16Input[6] |= (System16InputPort6[i] & 1) << i; + } + + if (System16MakeAnalogInputsDo) System16MakeAnalogInputsDo(); +} + +inline static void OutrunMakeInputs() +{ + // Reset Inputs + System16Input[0] = 0; + + if (System16Gear && System16LastGear == 0) System16InputPort0[4] ^= 1; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + System16Input[0] |= (System16InputPort0[i] & 1) << i; + } + + System16LastGear = System16Gear; +} + +inline static void PdriftMakeInputs() +{ + // Reset Inputs + System16Input[0] = 0; + + if (System16Gear && System16LastGear == 0) System16InputPort0[5] ^= 1; + + // Compile Digital Inputs + for (INT32 i = 0; i < 8; i++) { + System16Input[0] |= (System16InputPort0[i] & 1) << i; + } + + System16LastGear = System16Gear; +} + +static void System16GunMakeInputs() +{ + if (nBurnGunNumPlayers) BurnGunMakeInputs(0, (INT16)System16AnalogPort0, (INT16)System16AnalogPort1); + if (nBurnGunNumPlayers >= 1) BurnGunMakeInputs(1, (INT16)System16AnalogPort2, (INT16)System16AnalogPort3); + if (nBurnGunNumPlayers >= 2) BurnGunMakeInputs(2, (INT16)System16AnalogPort4, (INT16)System16AnalogPort5); +} + +/*==================================================== +Reset Driver +====================================================*/ + +static INT32 System16DoReset() +{ + INT32 i; + + if ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC_CPU2)) { + fd1094_machine_init(); + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_ISGSM) { + SekOpen(0); + SekMapMemory(System16Rom, 0x000000, 0x0fffff, SM_ROM); + SekClose(); + } + + SekOpen(0); + SekReset(); + SekClose(); + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMY) { + SekOpen(1); + SekReset(); + SekClose(); + + System16LastGear = 0; + System16RoadControl = 0; + System16AnalogSelect = 0; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN) { + // Start in low gear + if (System16HasGears) System16InputPort0[4] = 1; + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMY) { + SekOpen(2); + SekReset(); + SekClose(); + + // Start in low gear + if (System16HasGears) System16InputPort0[5] = 1; + } + + if (System16Z80RomNum) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + + if (System167751ProgSize) { + N7751Reset(); + DACReset(); + N7751Command = 0; + N7751RomAddress = 0; + } + + if (System16UPD7759DataSize) { + UPD7759Reset(); + UPD7759BankAddress = 0; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) { + BurnYM3438Reset(); + RF5C68PCMReset(); + } else { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) { + BurnYM2203Reset(); + } else { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) { + BurnYM2413Reset(); + } else { + BurnYM2151Reset(); + } + } + } + + // Reset Variables + for (i = 0; i < 4; i++) { + System16Page[i] = 0; + System16OldPage[i] = 0; + System16ScrollX[i] = 0; + System16ScrollY[i] = 0; + BootlegBgPage[i] = 0; + BootlegFgPage[i] = 0; + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_5358) { + System16SpriteBanks[ 0] = 0; + System16SpriteBanks[ 1] = 255; + System16SpriteBanks[ 2] = 255; + System16SpriteBanks[ 3] = 255; + System16SpriteBanks[ 4] = 255; + System16SpriteBanks[ 5] = 255; + System16SpriteBanks[ 6] = 255; + System16SpriteBanks[ 7] = 3; + System16SpriteBanks[ 8] = 255; + System16SpriteBanks[ 9] = 255; + System16SpriteBanks[10] = 255; + System16SpriteBanks[11] = 2; + System16SpriteBanks[12] = 255; + System16SpriteBanks[13] = 1; + System16SpriteBanks[14] = 0; + System16SpriteBanks[15] = 255; + } else { + for (i = 0; i < 16; i++) { + System16SpriteBanks[i] = i; + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM16B || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18 || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX) { + for (i = 0; i < 8; i++) { + System16TileBanks[i] = i; + System16OldTileBanks[i] = i; + } + } + + System16VideoEnable = 0; + System18VdpEnable = 0; + System18VdpMixing = 0; + System16VideoControl = 0; + System16ScreenFlip = 0; + System16SoundLatch = 0; + System16ColScroll = 0; + System16RowScroll = 0;; + + return 0; +} + +INT32 __fastcall OutrunResetCallback() +{ + INT32 nLastCPU = nSekActive; + SekClose(); + + SekOpen(1); + SekReset(); + SekClose(); + + SekOpen(nLastCPU); + + return 0; +} + +/*==================================================== +Z80 Memory Handlers +====================================================*/ + +UINT8 __fastcall System16Z80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x01: { + return BurnYM2151ReadStatus(); + } + + case 0x40: + case 0xc0: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return System16SoundLatch; + } + + case 0x80: { + if (System16UPD7759DataSize) { + return UPD7759BusyRead(0) << 7; + } + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read Port -> %02X\n"), a); +#endif + + return 0; +} + +UINT8 __fastcall System16PPIZ80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x01: { + return BurnYM2151ReadStatus(); + } + + case 0x40: + case 0xc0: { + ppi8255_set_portC(0, 0x00); + return System16SoundLatch; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read Port -> %02X\n"), a); +#endif + + return 0; +} + +void __fastcall System16Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + d &= 0xff; + + switch (a) { + case 0x00: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x01: { + BurnYM2151WriteRegister(d); + return; + } + + case 0x40: { + if (System16UPD7759DataSize) { + UPD7759StartWrite(0,d & 0x80); + UPD7759ResetWrite(0,d & 0x40); + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_5358) { + if (!(d & 0x04)) UPD7759BankAddress = 0x00000; + if (!(d & 0x08)) UPD7759BankAddress = 0x10000; + if (!(d & 0x10)) UPD7759BankAddress = 0x20000; + if (!(d & 0x20)) UPD7759BankAddress = 0x30000; + UPD7759BankAddress += (d & 0x03) * 0x4000; + + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_5521) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_5704_PS2)) { + UPD7759BankAddress = ((d & 0x08) >> 3) * 0x20000; + UPD7759BankAddress += (d & 0x07) * 0x4000; + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_5797) { + UPD7759BankAddress = ((d & 0x08) >> 3) * 0x40000; + UPD7759BankAddress += ((d & 0x10) >> 4) * 0x20000; + UPD7759BankAddress += (d & 0x07) * 0x04000; + } + + UPD7759BankAddress %= System16UPD7759DataSize; + + ZetMapArea(0x8000, 0xdfff, 0, System16UPD7759Data + UPD7759BankAddress); + ZetMapArea(0x8000, 0xdfff, 2, System16UPD7759Data + UPD7759BankAddress); + return; + } + } + + case 0x80: { + if (System167751ProgSize) { + N7751RomAddress &= 0x3fff; + N7751RomAddress |= (d & 0x01) << 14; + if (!(d & 0x02) && System167751DataNum >= 1) N7751RomAddress |= 0x00000; + if (!(d & 0x04) && System167751DataNum >= 2) N7751RomAddress |= 0x08000; + if (!(d & 0x08) && System167751DataNum >= 3) N7751RomAddress |= 0x10000; + if (!(d & 0x10) && System167751DataNum >= 4) N7751RomAddress |= 0x18000; + N7751Command = d >> 5; + return; + } + + if (System16UPD7759DataSize) { + UPD7759PortWrite(0,d); + return; + } + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write Port -> %02X, %02X\n"), a, d); +#endif +} + +#if 1 && defined FBA_DEBUG +UINT8 __fastcall System16Z80Read(UINT16 a) +{ + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); + + return 0; +} +#endif + +#if 1 && defined FBA_DEBUG +void __fastcall System16Z80Write(UINT16 a, UINT8 d) +{ + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02X\n"), a, d); +} +#endif + +UINT8 __fastcall System16Z80PCMRead(UINT16 a) +{ + if (a >= 0xf000 && a <= 0xf0ff) { + return SegaPCMRead(a - 0xf000); + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); +#endif + + return 0; +} + +void __fastcall System16Z80PCMWrite(UINT16 a, UINT8 d) +{ + if (a >= 0xf000 && a <= 0xf0ff) { + SegaPCMWrite(a - 0xf000, d); + return; + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02X\n"), a, d); +#endif +} + +UINT8 __fastcall System16Z802203PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x40: { + ppi8255_set_portC(0, 0x00); + return System16SoundLatch; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read Port -> %02X\n"), a); +#endif + + return 0; +} + +UINT8 __fastcall System16Z802203Read(UINT16 a) +{ + if (a >= 0xe000 && a <= 0xe0ff) { + return SegaPCMRead(a - 0xe000); + } + + switch (a) { + case 0xd000: { + return BurnYM2203Read(0, 0); + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); +#endif + + return 0; +} + +void __fastcall System16Z802203Write(UINT16 a, UINT8 d) +{ + if (a >= 0xe000 && a <= 0xe0ff) { + SegaPCMWrite(a - 0xe000, d); + return; + } + + switch (a) { + case 0xd000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xd001: { + BurnYM2203Write(0, 1, d); + return; + } + } + +#if 0 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02X\n"), a, d); +#endif +} + +UINT8 __fastcall System18Z80PortRead(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x80: { + return BurnYM3438Read(0, 0); + } + + case 0xc0: { + return System16SoundLatch; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read Port -> %02X\n"), a); +#endif + + return 0; +} + +void __fastcall System18Z80PortWrite(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x80: { + BurnYM3438Write(0, 0, d); + return; + } + + case 0x81: { + BurnYM3438Write(0, 1, d); + return; + } + + case 0x82: { + BurnYM3438Write(0, 2, d); + return; + } + + case 0x83: { + BurnYM3438Write(0, 3, d); + return; + } + + case 0x90: { + BurnYM3438Write(1, 0, d); + return; + } + + case 0x91: { + BurnYM3438Write(1, 1, d); + return; + } + + case 0x92: { + BurnYM3438Write(1, 2, d); + return; + } + + case 0x93: { + BurnYM3438Write(1, 3, d); + return; + } + + case 0xa0: { + UINT32 BankAddress = d * 0x2000; + ZetMapArea(0xa000, 0xbfff, 0, System16Z80Rom + 0x10000 + BankAddress); + ZetMapArea(0xa000, 0xbfff, 2, System16Z80Rom + 0x10000 + BankAddress); + return; + } + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write Port -> %02X, %02X\n"), a, d); +#endif +} + +UINT8 __fastcall System18Z80Read(UINT16 a) +{ + if (a >= 0xd000 && a <= 0xdfff) { + return RF5C68PCMRead(a - 0xd000); + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Read -> %04X\n"), a); +#endif + + return 0; +} + +void __fastcall System18Z80Write(UINT16 a, UINT8 d) +{ + if (a >= 0xc000 && a <= 0xc00f) { + RF5C68PCMRegWrite(a - 0xc000, d); + return; + } + + if (a >= 0xd000 && a <= 0xdfff) { + RF5C68PCMWrite(a - 0xd000, d); + return; + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Z80 Write -> %04X, %02X\n"), a, d); +#endif +} + +void System16N7751ControlWrite(UINT32 Port, UINT32 Data) +{ + if (!(Data & 0x01)) { + N7751Reset(); + return; + } + + if (!(Data & 0x02)) { + N7751SetIrqState(1); + return; + } + + if (Data & 0x02) { + N7751SetIrqState(0); + return; + } + + bprintf(PRINT_NORMAL, _T("YM2151 Write Port %x, %02X\n"), Port, Data); +} + +UINT8 __fastcall N7751ReadIo(UINT32 Port) +{ + switch (Port) { + case 0x102: { + return 0x80 | ((N7751Command & 0x07) << 4); + } + + case 0x120: { + return System167751Data[N7751RomAddress]; + } + } + + return 0; +} + +void __fastcall N7751WriteIo(UINT32 Port, UINT8 Value) +{ + switch (Port) { + case 0x101: { + DACWrite(0, Value); + return; + } + + case 0x102: { + return; + } + + case 0x104: + case 0x105: + case 0x106: + case 0x107: { + INT32 Offset = Port - 0x104; + INT32 Mask = (0xf << (4 * Offset)) & 0x3fff; + INT32 NewData = (Value << (4 * Offset)) & Mask; + N7751RomAddress = (N7751RomAddress & ~Mask) | NewData; + return; + } + } +} + +UINT8 __fastcall N7751Read(UINT32 Address) +{ + if (Address < 0x400) return System167751Prog[Address]; + return 0; +} + +/*==================================================== +Allocate Memory +====================================================*/ + +static INT32 System16MemIndex() +{ + UINT8 *Next; Next = Mem; + + System16PaletteEntries = 0x800; + System16RamSize = 0x4000; + System16ExtraRamSize = 0; + System16ExtraRam2Size = 0; + System16ExtraRam3Size = 0; + System16SpriteRamSize = 0x800; + System16SpriteRam2Size = 0; + System16RotateRamSize = 0; + System16BackupRamSize = 0; + System16BackupRam2Size = 0; + bool SpriteBuffer = false; + bool HasRoad = false; + bool UseTempDraw = false; + INT32 Z80RomSize = 0x10000; + INT32 Z80RamSize = 0x00800; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) { + Z80RomSize = 0x210000; + Z80RamSize = 0x2000; + UseTempDraw = true; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON) { + System16ExtraRamSize = 0x4000; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "hangon") || !strcmp(BurnDrvGetTextA(DRV_NAME), "shangupb")) { + System16RamSize = 0x10000; + } else { + System16SpriteRamSize = 0x1000; + } + HasRoad = true; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN) { + System16PaletteEntries = 0x1000; + System16RamSize = 0x8000; + System16ExtraRamSize = 0x8000; + System16SpriteRamSize = 0x1000; + SpriteBuffer = true; + HasRoad = true; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX) { + System16PaletteEntries = 0x2000; + System16RamSize = 0x8000; + System16SpriteRamSize = 0x1000; + System16BackupRamSize = 0x4000; + System16BackupRam2Size = 0x4000; + SpriteBuffer = true; + HasRoad = true; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMY) { + System16PaletteEntries = 0x2000; + System16RamSize = 0x10000; + System16ExtraRamSize = 0x10000; + System16ExtraRam2Size = 0x10000; + System16ExtraRam3Size = 0x10000; + System16SpriteRamSize = 0x1000; + System16BackupRamSize = 0x4000; + System16SpriteRam2Size = 0x10000; + System16RotateRamSize = 0x800; + UseTempDraw = true; + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_ISGSM) { + System16ExtraRamSize = 0x40000; + Z80RomSize = 0x40000; + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_5704_PS2) { + System16RamSize = 0x40000; + } + + System16Rom = Next; Next += (System16RomSize > 0x100000) ? System16RomSize : 0x100000; + System16Code = Next; Next += (System16RomSize > 0x100000) ? System16RomSize : 0x100000; + System16Rom2 = Next; (System16Rom2Size) ? Next += 0x080000 : Next += 0; + System16Rom3 = Next; (System16Rom3Size) ? Next += 0x080000 : Next += 0; + System16Z80Rom = Next; Next += Z80RomSize; + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MC8123_ENC) { + System16Z80Code = Next; Next += Z80RomSize; + } + System16Z80Rom2 = Next; Next += System16Z80Rom2Size; + System16Z80Rom3 = Next; Next += System16Z80Rom3Size; + System16Z80Rom4 = Next; Next += System16Z80Rom4Size; + System167751Prog = Next; Next += System167751ProgSize; + System167751Data = Next; Next += System167751DataSize; + System16UPD7759Data = Next; Next += System16UPD7759DataSize; + System16PCMData = Next; Next += System16PCMDataSize; + System16PCM2Data = Next; Next += System16PCM2DataSize; + System16RF5C68Data = Next; Next += System16RF5C68DataSize; + System16Key = Next; Next += System16KeySize; + System16Prom = Next; Next += System16PromSize; + + RamStart = Next; + + System16Ram = Next; Next += System16RamSize; + System16ExtraRam = Next; Next += System16ExtraRamSize; + System16ExtraRam2 = Next; Next += System16ExtraRam2Size; + System16ExtraRam3 = Next; Next += System16ExtraRam3Size; + System16TileRam = Next; (System16TileRomSize) ? Next += 0x10000 : Next += 0; + System16TextRam = Next; (System16TileRomSize) ? Next += 0x01000 : Next += 0; + System16SpriteRam = Next; Next += System16SpriteRamSize; + System16SpriteRam2 = Next; Next += System16SpriteRam2Size; + System16RotateRam = Next; Next += System16RotateRamSize; + System16RotateRamBuff= Next; Next += System16RotateRamSize; + if (SpriteBuffer) System16SpriteRamBuff = Next; Next += System16SpriteRamSize; + System16PaletteRam = Next; Next += System16PaletteEntries * 2; + + if (HasRoad) { + System16RoadRam = Next; Next += 0x01000; + System16RoadRamBuff = Next; Next += 0x01000; + } + + System16BackupRam = Next; Next += System16BackupRamSize; + System16BackupRam2 = Next; Next += System16BackupRam2Size; + + System16Z80Ram = Next; Next += Z80RamSize; + + RamEnd = Next; + + System16Tiles = Next; Next += (System16NumTiles * 8 * 8); + System16Sprites = Next; Next += System16SpriteRomSize; + System16Sprites2 = Next; Next += System16Sprite2RomSize; + + if (HasRoad) { + System16Roads = Next; Next += 0x40000; + } + + System16Palette = (UINT32*)Next; Next += System16PaletteEntries * 3 * sizeof(UINT32) + (((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) ? (0x40 * sizeof(UINT32)) : 0); + + if (UseTempDraw) pTempDraw = (UINT16*)Next; Next += (512 * 512 * sizeof(UINT16)); + + MemEnd = Next; + + return 0; +} + +/*==================================================== +Rom Loading +====================================================*/ + +static INT32 System16LoadRoms(bool bLoad) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + INT32 nOffset = -1; + UINT32 i; + INT32 nRet = 0; + + if (!bLoad) { + do { + ri.nLen = 0; + ri.nType = 0; + BurnDrvGetRomInfo(&ri, ++nOffset); + if ((ri.nType & 0xff) == SYS16_ROM_PROG) { + System16RomSize += ri.nLen; + System16RomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_PROG2) { + System16Rom2Size += ri.nLen; + System16Rom2Num++; + } + if ((ri.nType & 0xff) == SYS16_ROM_PROG3) { + System16Rom3Size += ri.nLen; + System16Rom3Num++; + } + if ((ri.nType & 0xff) == SYS16_ROM_TILES) { + System16TileRomSize += ri.nLen; + System16TileRomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_SPRITES) { + System16SpriteRomSize += ri.nLen; + System16SpriteRomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_SPRITES2) { + System16Sprite2RomSize += ri.nLen; + System16Sprite2RomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_ROAD) { + System16RoadRomSize += ri.nLen; + System16RoadRomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_Z80PROG) { + System16Z80RomSize += ri.nLen; + System16Z80RomNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_Z80PROG2) { + System16Z80Rom2Size += ri.nLen; + System16Z80Rom2Num++; + } + if ((ri.nType & 0xff) == SYS16_ROM_Z80PROG3) { + System16Z80Rom3Size += ri.nLen; + System16Z80Rom3Num++; + } + if ((ri.nType & 0xff) == SYS16_ROM_Z80PROG4) { + System16Z80Rom4Size += ri.nLen; + System16Z80Rom4Num++; + } + if ((ri.nType & 0xff) == SYS16_ROM_7751PROG) { + System167751ProgSize += ri.nLen; + System167751ProgNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_7751DATA) { + System167751DataSize += ri.nLen; + System167751DataNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_UPD7759DATA) { + if (ri.nLen < 0x10000) { + System16UPD7759DataSize += 0x10000; + } else { + System16UPD7759DataSize += ri.nLen; + } + System16UPD7759DataNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_PCMDATA) { + if (System16PCMDataSizePreAllocate) { + System16PCMDataSize = System16PCMDataSizePreAllocate; + } else { + System16PCMDataSize += ri.nLen; + } + + System16PCMDataNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_PCM2DATA) { + System16PCM2DataSize += ri.nLen; + System16PCM2DataNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_RF5C68DATA) { + System16RF5C68DataNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_PROM) { + System16PromSize += ri.nLen; + System16PromNum++; + } + if ((ri.nType & 0xff) == SYS16_ROM_KEY) { + System16KeySize += ri.nLen; + } + } while (ri.nLen); + + System16NumTiles = System16TileRomSize / 24; + if (System16RF5C68DataNum) { + System16Z80RomNum += System16RF5C68DataNum; + System16Z80RomSize = 0x210000; + } + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("68K Rom Size: 0x%X (%i roms)\n"), System16RomSize, System16RomNum); + if (System16Rom2Size) bprintf(PRINT_NORMAL, _T("68K #2 Rom Size: 0x%X (%i roms)\n"), System16Rom2Size, System16Rom2Num); + if (System16Rom3Size) bprintf(PRINT_NORMAL, _T("68K #3 Rom Size: 0x%X (%i roms)\n"), System16Rom3Size, System16Rom3Num); + bprintf(PRINT_NORMAL, _T("Tile Rom Size: 0x%X (%i roms, 0x%X Tiles)\n"), System16TileRomSize, System16TileRomNum, System16NumTiles); + bprintf(PRINT_NORMAL, _T("Sprite Rom Size: 0x%X (%i roms)\n"), System16SpriteRomSize, System16SpriteRomNum); + if (System16Sprite2RomSize) bprintf(PRINT_NORMAL, _T("Sprite Rom 2 Size: 0x%X (%i roms)\n"), System16Sprite2RomSize, System16Sprite2RomNum); + bprintf(PRINT_NORMAL, _T("Z80 Rom Size: 0x%X (%i roms)\n"), System16Z80RomSize, System16Z80RomNum); + if (System16Z80Rom2Size) bprintf(PRINT_NORMAL, _T("Z80 #2 Rom Size: 0x%X (%i roms)\n"), System16Z80Rom2Size, System16Z80Rom2Num); + if (System16Z80Rom3Size) bprintf(PRINT_NORMAL, _T("Z80 #3 Rom Size: 0x%X (%i roms)\n"), System16Z80Rom3Size, System16Z80Rom3Num); + if (System16Z80Rom4Size) bprintf(PRINT_NORMAL, _T("Z80 #4 Rom Size: 0x%X (%i roms)\n"), System16Z80Rom4Size, System16Z80Rom4Num); + if (System16RoadRomSize) bprintf(PRINT_NORMAL, _T("Road Rom Size: 0x%X (%i roms)\n"), System16RoadRomSize, System16RoadRomNum); + if (System167751ProgSize) bprintf(PRINT_NORMAL, _T("7751 Prog Size: 0x%X (%i roms)\n"), System167751ProgSize, System167751ProgNum); + if (System167751DataSize) bprintf(PRINT_NORMAL, _T("7751 Data Size: 0x%X (%i roms)\n"), System167751DataSize, System167751DataNum); + if (System16UPD7759DataSize) bprintf(PRINT_NORMAL, _T("UPD7759 Data Size: 0x%X (%i roms)\n"), System16UPD7759DataSize, System16UPD7759DataNum); + if (System16PCMDataSize) bprintf(PRINT_NORMAL, _T("PCM Data Size: 0x%X (%i roms)\n"), System16PCMDataSize, System16PCMDataNum); + if (System16PCM2DataSize) bprintf(PRINT_NORMAL, _T("PCM Data #2 Size: 0x%X (%i roms)\n"), System16PCM2DataSize, System16PCM2DataNum); + if (System16PromSize) bprintf(PRINT_NORMAL, _T("PROM Rom Size: 0x%X (%i roms)\n"), System16PromSize, System16PromNum); + if (System16KeySize) bprintf(PRINT_NORMAL, _T("Encryption Key Size: 0x%X\n"), System16KeySize); +#endif + } + + if (bLoad) { + INT32 Offset; + + // 68000 Program Roms + Offset = 0; + for (i = 0; i < System16RomNum; i += 2) { + nRet = BurnLoadRom(System16Rom + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(System16Rom + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + } + + // 68000 #2 Program Roms + if (System16Rom2Size) { + Offset = 0; + for (i = System16RomNum; i < System16RomNum + System16Rom2Num; i += 2) { + nRet = BurnLoadRom(System16Rom2 + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(System16Rom2 + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + } + } + + // 68000 #3 Program Roms + if (System16Rom3Size) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num; i < System16RomNum + System16Rom2Num + System16Rom3Num; i += 2) { + nRet = BurnLoadRom(System16Rom3 + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(System16Rom3 + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + } + } + + // Tile Roms + Offset = 0; + System16TempGfx = (UINT8*)malloc(System16TileRomSize); + for (i = System16RomNum + System16Rom2Num + System16Rom3Num; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum; i++) { + nRet = BurnLoadRom(System16TempGfx + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_INVERT_TILES) { + for (i = 0; i < System16TileRomSize; i++) { + System16TempGfx[i] ^= 0xff; + } + } + System16Decode8x8Tiles(System16Tiles, System16NumTiles, System16TileRomSize * 2 / 3, System16TileRomSize * 1 / 3, 0); + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + + // Sprite Roms + Offset = 0; + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_SPRITE_LOAD32) { + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum; i += 4) { + nRet = BurnLoadRom(System16Sprites + Offset + 0, i + 0, 4); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites + Offset + 1, i + 1, 4); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites + Offset + 2, i + 2, 4); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites + Offset + 3, i + 3, 4); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + } + } else { + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum; i += 2) { + nRet = BurnLoadRom(System16Sprites + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + } + } + + // Sprite 2 Roms + if (System16Sprite2RomSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum; i += 8) { + nRet = BurnLoadRom(System16Sprites2 + Offset + 7, i + 0, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 6, i + 1, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 5, i + 2, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 4, i + 3, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 3, i + 4, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 2, i + 5, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 1, i + 6, 8); if (nRet) return 1; + nRet = BurnLoadRom(System16Sprites2 + Offset + 0, i + 7, 8); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 4); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 5); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 6); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 7); + Offset += ri.nLen; + } + } + + // Road Roms + if (System16RoadRomSize) { + Offset = 0; + System16TempGfx = (UINT8*)malloc(System16RoadRomSize); + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum; i++) { + nRet = BurnLoadRom(System16TempGfx + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX) OutrunDecodeRoad(); + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON) HangonDecodeRoad(); + if (System16TempGfx) { + free(System16TempGfx); + System16TempGfx = NULL; + } + } + + // Z80 Program Roms + Offset = 0; + if (System16RF5C68DataNum) Offset = 0x10000; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum; i++) { + nRet = BurnLoadRom(System16Z80Rom + Offset, i, 1); + if (nRet) { + // Fill with 0xff + memset(System16Z80Rom, 0xff, System16Z80RomSize); + + nRet = 0; + } + + BurnDrvGetRomInfo(&ri, i + 0); + if (System16RF5C68DataNum) { + Offset += 0x80000; + } else { + Offset += ri.nLen; + } + } + if (System16RF5C68DataNum) { + memcpy(System16Z80Rom, System16Z80Rom + 0x10000, 0x10000); + System16RF5C68DataNum = 0; + } + + // Z80 #2 Program Roms + if (System16Z80Rom2Size) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum+ System16Z80RomNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num; i++) { + nRet = BurnLoadRom(System16Z80Rom2 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // Z80 #3 Program Roms + if (System16Z80Rom3Size) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num; i++) { + nRet = BurnLoadRom(System16Z80Rom3 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // Z80 #4 Program Roms + if (System16Z80Rom4Size) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num; i++) { + nRet = BurnLoadRom(System16Z80Rom4 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // 7751 Program Roms + if (System167751ProgSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum; i++) { + nRet = BurnLoadRom(System167751Prog + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // 7751 Data Roms + if (System167751DataSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum; i++) { + nRet = BurnLoadRom(System167751Data + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // UPD7759 Data Roms + if (System16UPD7759DataSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum; i++) { + nRet = BurnLoadRom(System16UPD7759Data + Offset, i, 1); + + if (nRet) { + memset(System16UPD7759Data, 0xff, System16UPD7759DataSize); + + nRet = 0; + } + + BurnDrvGetRomInfo(&ri, i + 0); + if (ri.nLen < 0x10000) { + Offset += 0x10000; + } else { + Offset += ri.nLen; + } + } + } + + // PCM Data Roms + if (System16PCMDataSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum; i++) { + nRet = BurnLoadRom(System16PCMData + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // PCM2 Data Roms + if (System16PCM2DataSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum + System16PCM2DataNum; i++) { + nRet = BurnLoadRom(System16PCM2Data + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // PROMs + if (System16PromSize) { + Offset = 0; + for (i = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum + System16PCM2DataNum + System16RF5C68DataNum; i < System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum + System16PCM2DataNum + System16RF5C68DataNum + System16PromNum; i++) { + nRet = BurnLoadRom(System16Prom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + } + } + + // Encryption Key + if (System16KeySize) { + Offset = System16RomNum + System16Rom2Num + System16Rom3Num + System16TileRomNum + System16SpriteRomNum + System16Sprite2RomNum + System16RoadRomNum + System16Z80RomNum + System16Z80Rom2Num + System16Z80Rom3Num + System16Z80Rom4Num + System167751ProgNum + System167751DataNum + System16UPD7759DataNum + System16PCMDataNum + System16PCM2DataNum + System16RF5C68DataNum + System16PromNum; + nRet = BurnLoadRom(System16Key, Offset, 1); if (nRet) return 1; + } + } + + return nRet; +} + +INT32 CustomLoadRom20000() +{ + INT32 nRet = 1; + UINT8 *pTemp = (UINT8*)malloc(0xc0000); + + if (pTemp) { + memcpy(pTemp, System16Rom, 0xc0000); + memset(System16Rom, 0, 0xc0000); + memcpy(System16Rom + 0x00000, pTemp + 0x00000, 0x20000); + memcpy(System16Rom + 0x80000, pTemp + 0x20000, 0x40000); + free(pTemp); + pTemp = NULL; + nRet = 0; + } + + return nRet; +} + +INT32 CustomLoadRom40000() +{ + INT32 nRet = 1; + UINT8 *pTemp = (UINT8*)malloc(0xc0000); + + if (pTemp) { + memcpy(pTemp, System16Rom, 0xc0000); + memset(System16Rom, 0, 0xc0000); + memcpy(System16Rom + 0x00000, pTemp + 0x00000, 0x40000); + memcpy(System16Rom + 0x80000, pTemp + 0x40000, 0x40000); + free(pTemp); + pTemp = NULL; + nRet = 0; + } + + return nRet; +} + +/*==================================================== +Sound Support Functions +====================================================*/ + +inline static INT32 System16SndGetBank(INT32 Reg86) +{ + return (Reg86>>4)&7; +} + +inline static INT32 PdriftSndGetBank(INT32 Reg86) +{ + return (Reg86>>3)&0x1f; +} + +inline void System16YM2151IRQHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static void System16YM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 System16SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +inline static double System16GetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +inline static INT32 System18SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 8000000; +} + +inline static double System18GetTime() +{ + return (double)ZetTotalCycles() / 8000000; +} + +static void System16UPD7759DrqCallback(INT32 state) +{ + if (state) ZetNmi(); +} + +/*==================================================== +Multiply Protection Chip Emulation +====================================================*/ + +struct multiply_chip +{ + UINT16 regs[4]; +}; + +static struct multiply_chip multiply[3]; + +UINT16 System16MultiplyChipRead(INT32 which, INT32 offset) +{ + offset &= 3; + switch (offset) { + case 0: { + return multiply[which].regs[0]; + } + + case 1: { + return multiply[which].regs[1]; + } + + case 2: { + return ((INT16)multiply[which].regs[0] * (INT16)multiply[which].regs[1]) >> 16; + } + + case 3: { + return ((INT16)multiply[which].regs[0] * (INT16)multiply[which].regs[1]) & 0xffff; + } + } + + return 0xffff; +} + +void System16MultiplyChipWrite(INT32 which, INT32 offset, UINT16 data) +{ + offset &= 3; + switch (offset) { + case 0: { + multiply[which].regs[0] = data; + return; + } + + case 1: { + multiply[which].regs[1] = data; + return; + } + + case 2: { + multiply[which].regs[0] = data; + return; + } + + case 3: { + multiply[which].regs[1] = data; + return; + } + } +} + +/*==================================================== +Divide Protection Chip Emulation +====================================================*/ + +struct divide_chip +{ + UINT16 regs[8]; +}; + +static struct divide_chip divide[3]; + +static void update_divide(INT32 which, INT32 mode) +{ + /* clear the flags by default */ + divide[which].regs[6] = 0; + + /* if mode 0, store quotient/remainder */ + if (mode == 0) + { + INT32 dividend = (INT32)((divide[which].regs[0] << 16) | divide[which].regs[1]); + INT32 divisor = (INT16)divide[which].regs[2]; + INT32 quotient, remainder; + + /* perform signed divide */ + if (divisor == 0) + { + quotient = dividend;//((INT32)(dividend ^ divisor) < 0) ? 0x8000 : 0x7fff; + divide[which].regs[6] |= 0x4000; + } + else + quotient = dividend / divisor; + remainder = dividend - quotient * divisor; + + /* clamp to 16-bit signed */ + if (quotient < -32768) + { + quotient = -32768; + divide[which].regs[6] |= 0x8000; + } + else if (quotient > 32767) + { + quotient = 32767; + divide[which].regs[6] |= 0x8000; + } + + /* store quotient and remainder */ + divide[which].regs[4] = quotient; + divide[which].regs[5] = remainder; + } + + /* if mode 1, store 32-bit quotient */ + else + { + UINT32 dividend = (UINT32)((divide[which].regs[0] << 16) | divide[which].regs[1]); + UINT32 divisor = (UINT16)divide[which].regs[2]; + UINT32 quotient; + + /* perform unsigned divide */ + if (divisor == 0) + { + quotient = dividend;//0x7fffffff; + divide[which].regs[6] |= 0x4000; + } + else + quotient = dividend / divisor; + + /* store 32-bit quotient */ + divide[which].regs[4] = quotient >> 16; + divide[which].regs[5] = quotient & 0xffff; + } +} + +UINT16 System16DivideChipRead(INT32 which, INT32 offset) +{ + offset &= 7; + switch (offset) { + case 0: { + return divide[which].regs[0]; + } + + case 1: { + return divide[which].regs[1]; + } + + case 2: { + return divide[which].regs[2]; + } + + case 4: { + return divide[which].regs[4]; + } + + case 5: { + return divide[which].regs[5]; + } + + case 6: { + return divide[which].regs[6]; + } + } + + return 0xffff; +} + +void System16DivideChipWrite(INT32 which, INT32 offset, UINT16 data) +{ + INT32 a4 = offset & 8; + INT32 a3 = offset & 4; + + offset &= 3; + switch (offset) { + case 0: { + divide[which].regs[0] = data; + break; + } + + case 1: { + divide[which].regs[1] = data; + break; + } + + case 2: { + divide[which].regs[2] = data; + break; + } + + case 3: { + break; + } + } + + if (a4) update_divide(which, a3); +} + +/*==================================================== +Compare Timer Protection Chip Emulation +====================================================*/ + +struct compare_timer_chip +{ + UINT16 regs[16]; + UINT16 counter; + UINT8 bit; +}; + +static struct compare_timer_chip compare_timer[2]; + +inline static INT32 segaic16_compare_timer_clock(INT32 which) +{ + INT32 old_counter = compare_timer[which].counter; + INT32 result = 0; + + /* if we're enabled, clock the upcounter */ + if (compare_timer[which].regs[10] & 1) + compare_timer[which].counter++; + + /* regardless of the enable, a value of 0xfff will generate the IRQ */ + if (old_counter == 0xfff) + { + result = 1; + compare_timer[which].counter = compare_timer[which].regs[8] & 0xfff; + } + return result; +} + +inline static void update_compare(INT32 which, INT32 update_history) +{ + INT32 bound1 = (INT16)compare_timer[which].regs[0]; + INT32 bound2 = (INT16)compare_timer[which].regs[1]; + INT32 value = (INT16)compare_timer[which].regs[2]; + INT32 min = (bound1 < bound2) ? bound1 : bound2; + INT32 max = (bound1 > bound2) ? bound1 : bound2; + + if (value < min) + { + compare_timer[which].regs[7] = min; + compare_timer[which].regs[3] = 0x8000; + } + else if (value > max) + { + compare_timer[which].regs[7] = max; + compare_timer[which].regs[3] = 0x4000; + } + else + { + compare_timer[which].regs[7] = value; + compare_timer[which].regs[3] = 0x0000; + } + + if (update_history) + compare_timer[which].regs[4] |= (compare_timer[which].regs[3] == 0) << compare_timer[which].bit++; +} + +UINT16 System16CompareTimerChipRead(INT32 which, INT32 offset) +{ + offset &= 0xf; + switch (offset) { + case 0x0: return compare_timer[which].regs[0]; + case 0x1: return compare_timer[which].regs[1]; + case 0x2: return compare_timer[which].regs[2]; + case 0x3: return compare_timer[which].regs[3]; + case 0x4: return compare_timer[which].regs[4]; + case 0x5: return compare_timer[which].regs[1]; + case 0x6: return compare_timer[which].regs[2]; + case 0x7: return compare_timer[which].regs[7]; + } + + return 0xffff; +} + +void System16CompareTimerChipWrite(INT32 which, INT32 offset, UINT16 data) +{ + offset &= 0xf; + switch (offset) { + case 0x0: compare_timer[which].regs[0] = data; update_compare(which, 0); break; + case 0x1: compare_timer[which].regs[1] = data; update_compare(which, 0); break; + case 0x2: compare_timer[which].regs[2] = data; update_compare(which, 1); break; + case 0x4: compare_timer[which].regs[4] = 0; compare_timer[which].bit = 0; break; + case 0x6: compare_timer[which].regs[2] = data; update_compare(which, 0); break; + case 0x8: + case 0xc: compare_timer[which].regs[8] = data; break; + case 0xa: + case 0xe: compare_timer[which].regs[10] = data; break; + case 0xb: + case 0xf: + compare_timer[which].regs[11] = data; + break; + } +} + +/*==================================================== +Main Driver Init function +====================================================*/ + +INT32 System16Init() +{ + INT32 nRet = 0, nLen; + + // Allocate and Blank all required memory + Mem = NULL; + System16LoadRoms(0); // Get required rom sizes + System16MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + System16MemIndex(); + + // Load Roms + if (!(BurnDrvGetHardwareCode() & HARDWARE_SEGA_5704_PS2)) { + nRet = System16LoadRoms(1); if (nRet) return 1; + } + if (System16CustomLoadRomDo) { nRet = System16CustomLoadRomDo(); if (nRet) return 1; } + + // Copy the first 68000 rom to code (FETCH) + memcpy(System16Code, System16Rom, System16RomSize); + + // Handle any op-code decryption + if (System16CustomDecryptOpCodeDo) { nRet = System16CustomDecryptOpCodeDo(); if (nRet) return 1; } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1089A_ENC || BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1089B_ENC) { + FD1089Decrypt(); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC_CPU2)) { + // Make sure we use Musashi + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC) fd1094_driver_init(0); + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC_CPU2) fd1094_driver_init(1); + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MC8123_ENC) { + mc8123_decrypt_rom(0, 0, System16Z80Rom, System16Z80Code, System16Key); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM16A) { + if (System16Map68KDo) { + System16Map68KDo(); + } else { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0fffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0fffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + + SekSetReadWordHandler(0, System16AReadWord); + SekSetWriteWordHandler(0, System16AWriteWord); + SekSetReadByteHandler(0, System16AReadByte); + SekSetWriteByteHandler(0, System16AWriteByte); + SekClose(); + } + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + +#if 1 && defined FBA_DEBUG + ZetSetReadHandler(System16Z80Read); + ZetSetWriteHandler(System16Z80Write); +#endif + ZetSetInHandler(System16PPIZ80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + + if (PPI0PortWriteA == NULL) PPI0PortWriteA = System16APPI0WritePortA; + if (PPI0PortWriteB == NULL) PPI0PortWriteB = System16APPI0WritePortB; + if (PPI0PortWriteC == NULL) PPI0PortWriteC = System16APPI0WritePortC; + ppi8255_init(1); + + BurnYM2151Init(4000000, 25.0); + + if (System167751ProgSize) { + N7751Init(NULL); + + N7751SetIOReadHandler(N7751ReadIo); + N7751SetIOWriteHandler(N7751WriteIo); + N7751SetProgramReadHandler(N7751Read); + N7751SetCPUOpReadHandler(N7751Read); + N7751SetCPUOpReadArgHandler(N7751Read); + + YM2151SetPortWriteHandler(0, &System16N7751ControlWrite); + DACInit(0, 0, 1); + } + + System16TileBankSize = 0x1000; + System16CreateOpaqueTileMaps = 1; + System16ATileMapsInit(1); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM16B) { + if (System16Map68KDo) { + System16Map68KDo(); + } else { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0fffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0fffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + + SekSetReadByteHandler(0, System16BReadByte); + SekSetWriteByteHandler(0, System16BWriteByte); + SekSetWriteWordHandler(0, System16BWriteWord); + SekClose(); + } + + if (System16Z80RomNum || ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_ISGSM) && System16Z80Enable)) { + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_MC8123_ENC) { + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Code, System16Z80Rom); + } else { + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + } + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + +#if 1 && defined FBA_DEBUG + ZetSetReadHandler(System16Z80Read); + ZetSetWriteHandler(System16Z80Write); +#endif + ZetSetInHandler(System16Z80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + } + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) { + BurnYM2413Init(5000000, 25.0); + BurnYM2413IncreaseVolume(4); + } else { + BurnYM2151Init(4000000, 25.0); + } + + if (System16UPD7759DataSize) { + UPD7759Init(0,UPD7759_STANDARD_CLOCK, NULL); + UPD7759SetDrqCallback(0,System16UPD7759DrqCallback); + } + + System16TileBankSize = 0x1000; + System16CreateOpaqueTileMaps = 1; + System16BTileMapsInit(1); + System16ClockSpeed = 10000000; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) { + if (System16Map68KDo) { + System16Map68KDo(); + } else { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x0fffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x0fffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x840000, 0x840fff, SM_RAM); + SekMapMemory(System16Ram , 0xffc000, 0xffffff, SM_RAM); + + SekSetReadWordHandler(0, System18ReadWord); + SekSetWriteWordHandler(0, System18WriteWord); + SekSetReadByteHandler(0, System18ReadByte); + SekSetWriteByteHandler(0, System18WriteByte); + SekClose(); + } + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x9fff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0x9fff, 2, System16Z80Rom); + + ZetMapArea(0xa000, 0xbfff, 0, System16Z80Rom + 0xa000); + ZetMapArea(0xa000, 0xbfff, 2, System16Z80Rom + 0xa000); + + ZetMapArea(0xe000, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xe000, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xe000, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System18Z80Read); + ZetSetWriteHandler(System18Z80Write); + ZetSetInHandler(System18Z80PortRead); + ZetSetOutHandler(System18Z80PortWrite); + ZetClose(); + } + + BurnYM3438Init(2, 8000000, NULL, System18SynchroniseStream, System18GetTime, 1); + BurnTimerAttachZet(8000000); + + RF5C68PCMInit(10000000); + + System16TileBankSize = 0x400; + System16CreateOpaqueTileMaps = 1; + System16BTileMapsInit(1); + + StartGenesisVDP(0, System16Palette); + GenesisPaletteBase = 0x1800; + GenesisBgPalLookup[0] = GenesisSpPalLookup[0] = 0x1800; + GenesisBgPalLookup[1] = GenesisSpPalLookup[1] = 0x1810; + GenesisBgPalLookup[2] = GenesisSpPalLookup[2] = 0x1820; + GenesisBgPalLookup[3] = GenesisSpPalLookup[3] = 0x1830; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_HANGON) { + if (System16Map68KDo) { + System16Map68KDo(); + } else { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x03ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x03ffff, SM_FETCH); + SekMapMemory(System16Ram , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(System16TileRam , 0x400000, 0x403fff, SM_READ); + SekMapMemory(System16TextRam , 0x410000, 0x410fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x600000, 0x607fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0xa00000, 0xa00fff, SM_RAM); + SekMapMemory(System16Rom2 , 0xc00000, 0xc3ffff, SM_READ); + SekMapMemory(System16RoadRam , 0xc68000, 0xc68fff, SM_RAM); + SekMapMemory(System16ExtraRam , 0xc7c000, 0xc7ffff, SM_RAM); + + SekSetReadWordHandler(0, HangonReadWord); + SekSetReadByteHandler(0, HangonReadByte); + SekSetWriteByteHandler(0, HangonWriteByte); + SekSetWriteWordHandler(0, HangonWriteWord); + SekClose(); + } + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(System16Rom2 , 0x000000, 0x03ffff, SM_READ); + SekMapMemory(System16Rom2 , 0x000000, 0x03ffff, SM_FETCH); + SekMapMemory(System16RoadRam , 0xc68000, 0xc68fff, SM_RAM); + SekMapMemory(System16ExtraRam , 0xc7c000, 0xc7ffff, SM_RAM); + SekClose(); + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0x7fff, 2, System16Z80Rom); + + ZetMapArea(0xc000, 0xc7ff, 0, System16Z80Ram); + ZetMapArea(0xc000, 0xc7ff, 1, System16Z80Ram); + ZetMapArea(0xc000, 0xc7ff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System16Z802203Read); + ZetSetWriteHandler(System16Z802203Write); + ZetSetInHandler(System16Z802203PortRead); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System16Z80PCMRead); + ZetSetWriteHandler(System16Z80PCMWrite); + ZetSetInHandler(System16PPIZ80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + } + + if (PPI0PortWriteA == NULL) PPI0PortWriteA = HangonPPI0WritePortA; + if (PPI0PortWriteB == NULL) PPI0PortWriteB = HangonPPI0WritePortB; + if (PPI0PortWriteC == NULL) PPI0PortWriteC = HangonPPI0WritePortC; + if (PPI1PortReadC == NULL) PPI1PortReadC = HangonPPI1ReadPortC; + if (PPI1PortWriteA == NULL) PPI1PortWriteA = HangonPPI1WritePortA; + ppi8255_init(2); + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) { + BurnYM2203Init(1, 4000000, &System16YM2203IRQHandler, System16SynchroniseStream, System16GetTime, 0); + BurnTimerAttachZet(4000000); + } else { + BurnYM2151Init(4000000, 25.0); + BurnYM2151SetIrqHandler(&System16YM2151IRQHandler); + } + + if (System16PCMDataSize) { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) { + SegaPCMInit(8000000, BANK_512, System16PCMData, System16PCMDataSize); + } else { + SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize); + } + } + + System16TileBankSize = 0x1000; + System16ATileMapsInit(0); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN) { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x05ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x05ffff, SM_FETCH); + SekMapMemory(System16ExtraRam , 0x060000, 0x067fff, SM_RAM); + SekMapMemory(System16TileRam , 0x100000, 0x10ffff, SM_READ); + SekMapMemory(System16TextRam , 0x110000, 0x110fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x120000, 0x121fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x130000, 0x130fff, SM_RAM); + SekMapMemory(System16Rom2 , 0x200000, 0x23ffff, SM_READ); + SekMapMemory(System16Ram , 0x260000, 0x267fff, SM_RAM); + SekMapMemory(System16RoadRam , 0x280000, 0x280fff, SM_RAM); + SekSetResetCallback(OutrunResetCallback); + SekSetReadWordHandler(0, OutrunReadWord); + SekSetWriteWordHandler(0, OutrunWriteWord); + SekSetReadByteHandler(0, OutrunReadByte); + SekSetWriteByteHandler(0, OutrunWriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(System16Rom2 , 0x000000, 0x03ffff, SM_READ); + SekMapMemory(System16Rom2 , 0x000000, 0x03ffff, SM_FETCH); + SekMapMemory(System16Ram , 0x060000, 0x067fff, SM_RAM); + SekMapMemory(System16RoadRam , 0x080000, 0x080fff, SM_RAM); + SekSetWriteWordHandler(0, Outrun2WriteWord); + SekSetReadByteHandler(0, Outrun2ReadByte); + SekSetWriteByteHandler(0, Outrun2WriteByte); + SekClose(); + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System16Z80PCMRead); + ZetSetWriteHandler(System16Z80PCMWrite); + ZetSetInHandler(System16PPIZ80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + + if (PPI0PortWriteC == NULL) PPI0PortWriteC = OutrunPPI0WritePortC; + ppi8255_init(1); + + BurnYM2151Init(4000000, 25.0); + + if (System16PCMDataSize) { + SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize); + } + + System16RoadColorOffset1 = 0x400; + System16RoadColorOffset2 = 0x420; + System16RoadColorOffset3 = 0x780; + + System16TileBankSize = 0x1000; + System16BTileMapsInit(0); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX) { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x07ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x07ffff, SM_FETCH); + SekMapMemory(System16TileRam , 0x0c0000, 0x0cffff, SM_READ); + SekMapMemory(System16TextRam , 0x0d0000, 0x0d0fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x100000, 0x100fff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x101000, 0x101fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x102000, 0x102fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x103000, 0x103fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x104000, 0x104fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x105000, 0x105fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x106000, 0x106fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x107000, 0x107fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x108000, 0x108fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x109000, 0x109fff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10a000, 0x10afff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10b000, 0x10bfff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10c000, 0x10cfff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10d000, 0x10dfff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10e000, 0x10efff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16SpriteRam , 0x10f000, 0x10ffff, SM_RAM); // Tests past Sprite RAM in mem tests (mirror?) + SekMapMemory(System16PaletteRam , 0x120000, 0x123fff, SM_RAM); + SekMapMemory(System16Rom2 , 0x200000, 0x27ffff, SM_READ); + SekMapMemory(System16Ram , 0x29c000, 0x2a3fff, SM_RAM); + SekMapMemory(System16RoadRam , 0x2ec000, 0x2ecfff, SM_RAM); + SekMapMemory(System16RoadRam , 0x2ed000, 0x2edfff, SM_RAM); // Tests past Road RAM in mem tests (mirror?) + SekMapMemory(System16BackupRam2 , 0xff4000, 0xff7fff, SM_RAM); + SekMapMemory(System16BackupRam , 0xff8000, 0xffffff, SM_RAM); + SekMapMemory(System16BackupRam2 , 0xffc000, 0xffffff, SM_RAM); + SekSetResetCallback(OutrunResetCallback); + SekSetReadWordHandler(0, XBoardReadWord); + SekSetWriteWordHandler(0, XBoardWriteWord); + SekSetReadByteHandler(0, XBoardReadByte); + SekSetWriteByteHandler(0, XBoardWriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(System16Rom2 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(System16Ram , 0x09c000, 0x0a3fff, SM_RAM); + SekMapMemory(System16RoadRam , 0x0ec000, 0x0ecfff, SM_RAM); + SekMapMemory(System16Rom2 , 0x200000, 0x27ffff, SM_ROM); + SekMapMemory(System16Ram , 0x29c000, 0x2a3fff, SM_RAM); + SekMapMemory(System16RoadRam , 0x2ec000, 0x2ecfff, SM_RAM); + SekSetReadWordHandler(0, XBoard2ReadWord); + SekSetWriteWordHandler(0, XBoard2WriteWord); + SekSetReadByteHandler(0, XBoard2ReadByte); + SekSetWriteByteHandler(0, XBoard2WriteByte); + SekClose(); + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System16Z80PCMRead); + ZetSetWriteHandler(System16Z80PCMWrite); + ZetSetInHandler(System16PPIZ80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + + BurnYM2151Init(4000000, 25.0); + BurnYM2151SetIrqHandler(&System16YM2151IRQHandler); + + if (System16PCMDataSize) { + SegaPCMInit(4000000, BANK_512, System16PCMData, System16PCMDataSize); + } + + System16RoadColorOffset1 = 0x1700; + System16RoadColorOffset2 = 0x1720; + System16RoadColorOffset3 = 0x1780; + System16RoadXOffset = -166; + System16RoadPriority = 1; + System16TilemapColorOffset = 0x1c00; + + System16TileBankSize = 0x1000; + System16BTileMapsInit(0); + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMY) { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(System16Rom , 0x000000, 0x07ffff, SM_READ); + SekMapMemory(System16Code , 0x000000, 0x07ffff, SM_FETCH); + SekMapMemory(System16Ram , 0x0c0000, 0x0cffff, SM_RAM); + SekMapMemory(System16ExtraRam , 0xff0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, YBoardReadWord); + SekSetWriteWordHandler(0, YBoardWriteWord); + SekSetReadByteHandler(0, YBoardReadByte); + SekSetWriteByteHandler(0, YBoardWriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(System16Rom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(System16Ram , 0x0c0000, 0x0cffff, SM_RAM); + SekMapMemory(System16SpriteRam2 , 0x180000, 0x18ffff, SM_RAM); + SekMapMemory(System16ExtraRam2 , 0xff0000, 0xffbfff, SM_RAM); + SekMapMemory(System16BackupRam , 0xffc000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, YBoard2ReadWord); + SekSetWriteWordHandler(0, YBoard2WriteWord); + SekClose(); + + SekInit(2, 0x68000); + SekOpen(2); + SekMapMemory(System16Rom3 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(System16Ram , 0x0c0000, 0x0cffff, SM_RAM); + SekMapMemory(System16RotateRam , 0x180000, 0x1807ff, SM_RAM); + SekMapMemory(System16SpriteRam , 0x188000, 0x188fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x190000, 0x193fff, SM_RAM); + SekMapMemory(System16PaletteRam , 0x194000, 0x197fff, SM_RAM); + SekMapMemory(System16ExtraRam3 , 0xff0000, 0xffffff, SM_RAM); + SekSetReadWordHandler(0, YBoard3ReadWord); + SekSetWriteWordHandler(0, YBoard3WriteWord); + SekSetReadByteHandler(0, YBoard3ReadByte); + SekClose(); + + if (System16MapZ80Do) { + ZetInit(1); + ZetOpen(0); + System16MapZ80Do(); + ZetClose(); + } else { + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0xdfff, 0, System16Z80Rom); + ZetMapArea(0x0000, 0xdfff, 2, System16Z80Rom); + + ZetMapArea(0xf800, 0xffff, 0, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 1, System16Z80Ram); + ZetMapArea(0xf800, 0xffff, 2, System16Z80Ram); + ZetMemEnd(); + + ZetSetReadHandler(System16Z80PCMRead); + ZetSetWriteHandler(System16Z80PCMWrite); + ZetSetInHandler(System16PPIZ80PortRead); + ZetSetOutHandler(System16Z80PortWrite); + ZetClose(); + } + + BurnYM2151Init(32215900 / 8, 25.0); + BurnYM2151SetIrqHandler(&System16YM2151IRQHandler); + + if (System16PCMDataSize) { + SegaPCMInit(32215900 / 8, BANK_12M | BANK_MASKF8, System16PCMData, System16PCMDataSize); + } + + YBoardIrq2Scanline = 170; + } + + GenericTilesInit(); + bSystem16BootlegRender = false; + + // Reset the driver + System16DoReset(); + + return 0; +} + +/*==================================================== +Exit Function +====================================================*/ + +INT32 System16Exit() +{ + INT32 i; + + SekExit(); + ZetExit(); + N7751Exit(); + + BurnYM3438Exit(); + BurnYM2203Exit(); + BurnYM2413Exit(); + BurnYM2151Exit(); + + SegaPCMExit(); + DACExit(); + UPD7759Exit(); + + ppi8255_exit(); + + BurnGunExit(); + + GenericTilesExit(); + System16TileMapsExit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + // Reset Variables + for (i = 0; i < 4; i++) { + System16Page[i] = 0; + System16OldPage[i] = 0; + System16ScrollX[i] = 0; + System16ScrollY[i] = 0; + BootlegBgPage[i] = 0; + BootlegFgPage[i] = 0; + } + + for (i = 0; i < 16; i++) { + System16SpriteBanks[i] = 0; + } + + for (i = 0; i < 8; i++) { + System16TileBanks[i] = 0; + System16OldTileBanks[i] = 0; + } + + System16VideoEnable = 0; + System18VdpEnable = 0; + System18VdpMixing = 0; + System16ScreenFlip = 0; + System16SpriteShadow = 0; + System16SpriteXOffset = 0; + System16VideoControl = 0; + System16SoundLatch = 0; + System16ColScroll = 0; + System16RowScroll = 0; + System16IgnoreVideoEnable = 0; + + System16LastGear = 0; + System16HasGears = false; + + System16RoadControl = 0; + System16RoadColorOffset1 = 0; + System16RoadColorOffset2 = 0; + System16RoadColorOffset3 = 0; + System16RoadXOffset = 0; + System16RoadPriority = 0; + System16AnalogSelect = 0; + + System16ClockSpeed = 0; + + System16PaletteEntries = 0; + System16RamSize = 0; + System16ExtraRamSize = 0; + System16ExtraRam2Size = 0; + System16ExtraRam3Size = 0; + System16SpriteRamSize = 0; + System16SpriteRam2Size = 0; + System16RotateRamSize = 0; + System16TilemapColorOffset = 0; + System16TileBankSize = 0; + System16RecalcBgTileMap = 0; + System16RecalcBgAltTileMap = 0; + System16RecalcFgTileMap = 0; + System16RecalcFgAltTileMap = 0; + System16CreateOpaqueTileMaps = 0; + + System16BTileAlt = false; + Shangon = false; + Hangon = false; + bSystem16BootlegRender = false; + + YBoardIrq2Scanline = 0; + + System16YM2413IRQInterval = 0; + + UPD7759BankAddress = 0; + N7751Command = 0; + N7751RomAddress = 0; + + System16RomSize = 0; + System16RomNum = 0; + System16Rom2Size = 0; + System16Rom2Num = 0; + System16Rom3Size = 0; + System16Rom3Num = 0; + System16TileRomSize = 0; + System16TileRomNum = 0; + System16NumTiles = 0; + System16SpriteRomSize = 0; + System16SpriteRomNum = 0; + System16Sprite2RomSize = 0; + System16Sprite2RomNum = 0; + System16RoadRomSize = 0; + System16RoadRomNum = 0; + System16Z80RomSize = 0; + System16Z80RomNum = 0; + System16Z80Rom2Size = 0; + System16Z80Rom2Num = 0; + System16Z80Rom3Size = 0; + System16Z80Rom3Num = 0; + System16Z80Rom4Size = 0; + System16Z80Rom4Num = 0; + System167751ProgSize = 0; + System167751ProgNum = 0; + System167751DataSize = 0; + System167751DataNum = 0; + System16UPD7759DataSize = 0; + System16UPD7759DataNum = 0; + System16PCMDataSizePreAllocate = 0; + System16PCMDataSize = 0; + System16PCMDataNum = 0; + System16PCM2DataSize = 0; + System16PCM2DataNum = 0; + System16RF5C68DataSize = 0; + System16RF5C68DataNum = 0; + System16PromSize = 0; + System16PromNum = 0; + System16KeySize = 0; + + Simulate8751 = NULL; + System16Map68KDo = NULL; + System16MapZ80Do = NULL; + System16CustomLoadRomDo = NULL; + System16CustomDecryptOpCodeDo = NULL; + System16ProcessAnalogControlsDo = NULL; + System16MakeAnalogInputsDo = NULL; + + memset(multiply, 0, sizeof(multiply)); + memset(divide, 0, sizeof(divide)); + memset(compare_timer, 0, sizeof(compare_timer)); + + if ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC) || (BurnDrvGetHardwareCode() & HARDWARE_SEGA_FD1094_ENC_CPU2)) { + fd1094_exit(); + + // Switch back CPU core if needed + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + } + + return 0; +} + +/*==================================================== +Frame Functions +====================================================*/ + +INT32 System16AFrame() +{ + INT32 nInterleave = nBurnSoundLen; // for the DAC + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = 4000000 / 60; + nCyclesTotal[2] = (6000000 / 15) / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (System167751ProgSize) { + nCurrentCPU = 2; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = N7751Run(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + if (System167751ProgSize) DACUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (Simulate8751) Simulate8751(); + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + if (System167751ProgSize) DACUpdate(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) System16ARender(); + + return 0; +} + +INT32 System16BFrame() +{ + INT32 nInterleave = (nBurnSoundRate <= 44100) ? 183 : 200; // For the UPD7759 + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) nInterleave = System16YM2413IRQInterval; + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)System16ClockSpeed * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = 5000000 / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) { + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + // Run Z80 + if (System16Z80RomNum || ((BurnDrvGetHardwareCode() & HARDWARE_SEGA_ISGSM) && System16Z80Enable)) { + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) { + BurnYM2413Render(pSoundBuf, nSegmentLength); + } else { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + if (System16UPD7759DataSize) UPD7759Update(0,pSoundBuf, nSegmentLength); + ZetClose(); + } + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2413) { + BurnYM2413Render(pSoundBuf, nSegmentLength); + } else { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + if (System16UPD7759DataSize) UPD7759Update(0,pSoundBuf, nSegmentLength); + ZetClose(); + } + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (Simulate8751) Simulate8751(); + + if (pBurnDraw) { + if (System16BTileAlt) { + System16BAltRender(); + } else { + if (bSystem16BootlegRender) { + System16BootlegRender(); + } else { + System16BRender(); + } + } + } + + return 0; +} + +INT32 System18Frame() +{ + INT32 nInterleave = nBurnSoundLen; + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + if (nBurnGunNumPlayers) System16GunMakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = 8000000 / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + + nCurrentCPU = 1; + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + RF5C68PCMUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[1]); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + RF5C68PCMUpdate(pSoundBuf, nSegmentLength); + } + } + + ZetOpen(0); + BurnYM3438Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) { + System18Render(); + } + + return 0; +} + +INT32 HangonFrame() +{ + INT32 nInterleave = 10, i; + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)System16ClockSpeed * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)System16ClockSpeed * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = 4000000 / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + SekClose(); + + // Run 68000 #2 + nCurrentCPU = 1; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + SekClose(); + + // Run Z80 + nCurrentCPU = 2; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + } + } + + SekOpen(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (Simulate8751) Simulate8751(); + + if (pBurnDraw) { + HangonRender(); + } + + return 0; +} + +INT32 HangonYM2203Frame() +{ + INT32 nInterleave = 100, i; + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)System16ClockSpeed * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)System16ClockSpeed * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = 4000000 / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + SekClose(); + + // Run 68000 #2 + nCurrentCPU = 1; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + SekClose(); + + ZetOpen(0); + BurnTimerUpdate(i * (nCyclesTotal[2] / nInterleave)); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2203Update(pSoundBuf, nSegmentLength); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + SekOpen(0); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerEndFrame(nCyclesTotal[2]); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(0); + BurnYM2203Update(pSoundBuf, nSegmentLength); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (Simulate8751) Simulate8751(); + + if (pBurnDraw) { + if (Hangon) { + HangonAltRender(); + } else { + HangonRender(); + } + } + + return 0; +} + +INT32 OutrunFrame() +{ + INT32 nInterleave = 10, i; + + if (System16Reset) System16DoReset(); + + if (System16HasGears) { + OutrunMakeInputs(); + } else { + System16MakeInputs(); + } + + nCyclesTotal[0] = (INT32)((INT64)(40000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)(40000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = (16000000 / 4) / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 2 || i == 6 || i == 8) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 #2 + nCurrentCPU = 1; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + SekClose(); + + // Run Z80 + nCurrentCPU = 2; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + } + } + + for (i = 0; i < 2; i++) { + SekOpen(i); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + if (pBurnDraw) { + if (!Shangon) { + OutrunRender(); + } else { + ShangonRender(); + } + } + + return 0; +} + +INT32 XBoardFrame() +{ + INT32 nInterleave = 100, i; + + if (System16Reset) System16DoReset(); + + System16MakeInputs(); + + if (nBurnGunNumPlayers) System16GunMakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)(50000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)(50000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = (16000000 / 4) / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == 20 || i == 40 || i == 60 || i == 80) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + if (i == 99) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 #2 + nCurrentCPU = 1; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 99) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 2; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + if (System16PCMDataSize) SegaPCMUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + if (System16PCMDataSize) SegaPCMUpdate(pSoundBuf, nSegmentLength); + } + } + + if (pBurnDraw) { + XBoardRender(); + } + + return 0; +} + +INT32 YBoardFrame() +{ + INT32 nInterleave = 224, i; + + if (System16Reset) System16DoReset(); + + if (System16HasGears) { + PdriftMakeInputs(); + } else { + System16MakeInputs(); + } + + if (nBurnGunNumPlayers) System16GunMakeInputs(); + + nCyclesTotal[0] = (INT32)((INT64)(50000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)(50000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[2] = (INT32)((INT64)(50000000 / 4) * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[3] = (32215900 / 8) / 60; + nSystem16CyclesDone[0] = nSystem16CyclesDone[1] = nSystem16CyclesDone[2] = nSystem16CyclesDone[3] = 0; + + INT32 nSoundBufferPos = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nSystem16CyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + if (i == YBoardIrq2Scanline) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 #2 + nCurrentCPU = 1; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == YBoardIrq2Scanline) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 #3 + nCurrentCPU = 2; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = SekRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == YBoardIrq2Scanline) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 3; + ZetOpen(0); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nSystem16CyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nSystem16CyclesDone[nCurrentCPU] += nCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + SegaPCMUpdate(pSoundBuf, nSegmentLength); + } + } + + for (i = 0; i < 3; i++) { + SekOpen(i); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + if (pBurnDraw) { + YBoardRender(); + } + + return 0; +} + +/*==================================================== +Driver Scan +====================================================*/ + +INT32 System16Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029660; + } + + if (nAction & ACB_NVRAM) { + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMX || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEMY) { + if (System16BackupRamSize) { + memset(&ba, 0, sizeof(ba)); + ba.Data = System16BackupRam; + ba.nLen = System16BackupRamSize; + ba.szName = "Backup Ram 1"; + BurnAcb(&ba); + } + + if (System16BackupRam2Size) { + memset(&ba, 0, sizeof(ba)); + ba.Data = System16BackupRam2; + ba.nLen = System16BackupRam2Size; + ba.szName = "Backup Ram 2"; + BurnAcb(&ba); + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_OUTRUN || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM16B || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM16A || (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) { + memset(&ba, 0, sizeof(ba)); + ba.Data = System16Ram; + ba.nLen = System16RamSize; + ba.szName = "Work Ram"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + ppi8255_scan(); + BurnGunScan(); + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SEGA_SYSTEM18) { + BurnYM3438Scan(nAction, pnMin); + } else { + if (BurnDrvGetHardwareCode() & HARDWARE_SEGA_YM2203) { + BurnYM2203Scan(nAction, pnMin); + } else { + BurnYM2151Scan(nAction); + } + } + + if (System16UPD7759DataSize) { + UPD7759Scan(0,nAction, pnMin); + } + + if (System167751ProgSize) { + N7751Scan(nAction, pnMin); + DACScan(nAction, pnMin); + } + + if (System16PCMData) { + SegaPCMScan(nAction, pnMin); + } + + // Scan critical driver variables + SCAN_VAR(System16SoundLatch); + SCAN_VAR(System16Input); + SCAN_VAR(System16Dip); + SCAN_VAR(System16VideoEnable); + SCAN_VAR(System16ScreenFlip); + SCAN_VAR(System16ScrollX); + SCAN_VAR(System16ScrollY); + SCAN_VAR(System16ColScroll); + SCAN_VAR(System16RowScroll); + SCAN_VAR(System16SpriteBanks); + SCAN_VAR(System16TileBanks); + SCAN_VAR(System16Page); + SCAN_VAR(BootlegBgPage); + SCAN_VAR(BootlegFgPage); + SCAN_VAR(System16AnalogSelect); + SCAN_VAR(System16LastGear); + SCAN_VAR(nSystem16CyclesDone); + SCAN_VAR(nCyclesSegment); + SCAN_VAR(System16RoadControl); + SCAN_VAR(multiply); + SCAN_VAR(divide); + SCAN_VAR(compare_timer); + SCAN_VAR(N7751Command); + SCAN_VAR(N7751RomAddress); + SCAN_VAR(UPD7759BankAddress); + } + + return 0; +} diff --git a/src/burn/drivers/taito/cchip.cpp b/src/burn/drivers/taito/cchip.cpp new file mode 100644 index 00000000..c72457ba --- /dev/null +++ b/src/burn/drivers/taito/cchip.cpp @@ -0,0 +1,2612 @@ +#include "burnint.h" +#include "taito_ic.h" +#include "taito.h" + +static UINT8 CurrentBank; + +// Superman C-Chip +static UINT8 SupermanPort = 0; + +static const UINT8 superman_code[40] = +{ + 0x48, 0xe7, 0x80, 0x80, /* MOVEM.L D0/A0,-(A7) ( Preserve Regs ) */ + 0x20, 0x6d, 0x1c, 0x40, /* MOVEA.L ($1C40,A5),A0 ( Load sound pointer in A0 ) */ + 0x30, 0x2f, 0x00, 0x0c, /* MOVE.W ($0C,A7),D0 ( Fetch sound number ) */ + 0x10, 0x80, /* MOVE.B D0,(A0) ( Store it on sound pointer ) */ + 0x52, 0x88, /* ADDQ.W #1,A0 ( Increment sound pointer ) */ + 0x20, 0x3c, 0x00, 0xf0, 0x1c, 0x40, /* MOVE.L #$F01C40,D0 ( Load top of buffer in D0 ) */ + 0xb1, 0xc0, /* CMPA.L D0,A0 ( Are we there yet? ) */ + 0x66, 0x04, /* BNE.S *+$6 ( No, we arent, skip next line ) */ + 0x41, 0xed, 0x1c, 0x20, /* LEA ($1C20,A5),A0 ( Point to the start of the buffer ) */ + 0x2b, 0x48, 0x1c, 0x40, /* MOVE.L A0,($1C40,A5) ( Store new sound pointer ) */ + 0x4c, 0xdf, 0x01, 0x01, /* MOVEM.L (A7)+, D0/A0 ( Restore Regs ) */ + 0x4e, 0x75 /* RTS ( Return ) */ +}; + +UINT16 SupermanCChipCtrlRead() +{ + return 0x01; +} + +UINT16 SupermanCChipRamRead(UINT32 Offset, UINT8 Input1, UINT8 Input2, UINT8 Input3) +{ + if (CurrentBank == 0) { + switch (Offset) { + case 0x00: return Input1; + case 0x01: return Input2; + case 0x02: return Input3; + case 0x03: return SupermanPort; + } + } + + if (CurrentBank == 1 && Offset <= 0xff) { + if (Offset < 40) { + return superman_code[Offset]; + } else { + return 0; + } + } + + if (CurrentBank == 2) { + switch (Offset) { + case 0x000: return 0x47; + case 0x001: return 0x57; + case 0x002: return 0x4b; + } + } + + return 0; +} + +void SupermanCChipCtrlWrite() +{ + +} + +void SupermanCChipBankWrite(UINT16 Data) +{ + CurrentBank = Data & 7; +} + +void SupermanCChipRamWrite(UINT32 Offset, UINT16 Data) +{ + if (CurrentBank == 0 && Offset == 0x03) { + SupermanPort = Data; + } +} + +void SupermanCChipReset() +{ + CurrentBank = 0; + SupermanPort = 0; +} + +void SupermanCChipInit() +{ + CurrentBank = 0; + SupermanPort = 0; + + TaitoIC_SupermanCChipInUse = 1; +} + +void SupermanCChipExit() +{ + CurrentBank = 0; + SupermanPort = 0; +} + +void SupermanCChipScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(CurrentBank); + SCAN_VAR(SupermanPort); + } +} + +// Mega Blast + +static UINT8 *MegabCChipRam; + +UINT16 MegabCChipRead(UINT32 Offset) +{ + if (Offset == 0x401) { + return 0x01; + } + + return MegabCChipRam[Offset]; +} + +void MegabCChipWrite(UINT32 Offset, UINT16 Data) +{ + MegabCChipRam[Offset] = Data; +} + +void MegabCChipReset() +{ + memset(MegabCChipRam, 0, 0x800); +} + +void MegabCChipInit() +{ + MegabCChipRam = (UINT8*)malloc(0x800); + memset(MegabCChipRam, 0, 0x800); + + TaitoIC_MegabCChipInUse = 1; +} + +void MegabCChipExit() +{ + if (MegabCChipRam) { + free(MegabCChipRam); + MegabCChipRam = NULL; + } +} + +void MegabCChipScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = MegabCChipRam; + ba.nLen = 0x800; + ba.szName = "CChip Ram"; + BurnAcb(&ba); + } +} + +// Rainbow Islands C-Chip + +static UINT8 *CRAM[8]; +static INT32 ExtraVersion; + +struct CBANK +{ + const UINT8* data; + size_t size; +}; + +static const UINT8 CROM_BANK1[] = +{ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x0A, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x0A, 0x0B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x05, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, + 0x08, 0x08, 0x0A, 0x0C, 0x0C, 0x0E, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, + 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, + 0x32, 0x58, 0x5A, 0x5C, 0x5E, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, + 0x6E, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E, 0x7E, 0x7E, 0x80, + 0x82, 0x86, 0x86, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A +}; + +static const UINT8 CROM_BANK2[] = +{ + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, + 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x10, 0x10, 0x12, 0x12, + 0x14, 0x14, 0x16, 0x20, 0x22, 0x16, 0x20, 0x22, 0x16, 0x16, 0x20, 0x20, + 0x22, 0x22 +}; + +static const UINT8 CROM_BANK4_WORLD0[] = +{ + 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, + 0x40, 0x00, 0x44, 0x00, 0x48, 0x00, 0x54, 0x00, 0x58, 0x00, 0x5C, 0x00, + 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x74, 0x00, 0x78, 0x00, 0x7C, 0x00, + 0x80, 0x00, 0x84, 0x00, 0x32, 0x00, 0x34, 0x00, 0x56, 0x00, 0x58, 0x00, + 0x98, 0x00, 0x96, 0x00, 0x7A, 0x00, 0x7C, 0x00, 0x56, 0x00, 0x58, 0x00, + 0x98, 0x00, 0x96, 0x00, 0x12, 0x01, 0x13, 0x01, 0x1C, 0x01, 0x1D, 0x01, + 0x29, 0x01, 0x28, 0x01, 0x26, 0x01, 0x27, 0x01, 0x2A, 0x01, 0x2B, 0x01, + 0xFA, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x10, + 0xD6, 0x00, 0xD8, 0x00, 0xD2, 0x00, 0xD4, 0x00, 0xDE, 0x00, 0xE0, 0x00, + 0xDA, 0x00, 0xDC, 0x00, 0xF4, 0x00, 0xF2, 0x00, 0x36, 0x01, 0x37, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3A, 0x01, 0x34, 0x01, 0x35, 0x01, + 0xC9, 0x02, 0xC8, 0x02 +}; + +static const UINT8 CROM_BANK4_WORLD1[] = +{ + 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, + 0x3C, 0x00, 0x42, 0x00, 0x48, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00, + 0x58, 0x00, 0x5A, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x62, 0x00, 0x64, 0x00, + 0xAA, 0x01, 0xAC, 0x01, 0xCE, 0x01, 0xD0, 0x01, 0x6E, 0x02, 0x70, 0x02, + 0x62, 0x01, 0x64, 0x01, 0x86, 0x01, 0x88, 0x01, 0x6A, 0x02, 0x6C, 0x02, + 0x02, 0x02, 0x04, 0x02, 0x06, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0C, 0x02, + 0x82, 0x02, 0x84, 0x02, 0x0E, 0x02, 0x10, 0x02, 0x22, 0x02, 0x24, 0x02, + 0x86, 0x02, 0x88, 0x02, 0x26, 0x02, 0x2E, 0x02, 0x8A, 0x02, 0x8C, 0x02, + 0x28, 0x10, 0x28, 0x10, 0x8E, 0x02, 0x90, 0x02 +}; + +static const UINT8 CROM_BANK4_WORLD2[] = +{ + 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00, + 0x52, 0x00, 0x56, 0x00, 0x5A, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x62, 0x00, + 0x66, 0x00, 0x68, 0x00, 0x6A, 0x00, 0x6E, 0x00, 0x76, 0x00, 0x7E, 0x00, + 0x82, 0x00, 0x86, 0x00, 0x8A, 0x00, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03, + 0x07, 0x03, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03, 0x07, 0x03, 0x23, 0x03, + 0x21, 0x03, 0x25, 0x03, 0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x25, 0x03, + 0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x47, 0x03, 0x23, 0x03, 0x61, 0x03, + 0x63, 0x03, 0x61, 0x03, 0x63, 0x03, 0x67, 0x03, 0x65, 0x03, 0x49, 0x03, + 0x49, 0x03, 0x67, 0x03, 0x65, 0x03, 0x69, 0x03, 0x69, 0x03, 0xC9, 0x03, + 0xC7, 0x03, 0x85, 0x03, 0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0x85, 0x03, + 0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0xC9, 0x03, 0xC7, 0x03, 0xAB, 0x03, + 0xAD, 0x03, 0xAF, 0x03, 0xC1, 0x03, 0xC5, 0x03, 0xC3, 0x03 +}; + +static const UINT8 CROM_BANK4_WORLD3[] = +{ + 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00, + 0x48, 0x00, 0x4A, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00, 0x58, 0x00, + 0x5C, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, 0x6C, 0x00, + 0x70, 0x00, 0x7A, 0x00, 0x84, 0x00, 0x88, 0x00, 0xA2, 0x00, 0xBC, 0x00, + 0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x51, 0x04, + 0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x55, 0x04, + 0x59, 0x04, 0x59, 0x04, 0x59, 0x04, 0x9F, 0x04, 0x5D, 0x04, 0x5B, 0x04, + 0x5D, 0x04, 0x5B, 0x04, 0x95, 0x04, 0x93, 0x04, 0x5F, 0x04, 0x5F, 0x04, + 0x99, 0x04, 0x97, 0x04, 0x75, 0x04, 0x77, 0x04, 0x7F, 0x04, 0x91, 0x04, + 0x9D, 0x04, 0x9B, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04, + 0xB9, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04, 0xB9, 0x04, + 0xBD, 0x04, 0xBB, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04, 0xD9, 0x04, + 0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04, 0xDF, 0x04, + 0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04, + 0xD9, 0x04, 0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04, + 0xDF, 0x04, 0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0x12, 0x05, 0x11, 0x05 +}; + +static const UINT8 CROM_BANK4_WORLD4[] = +{ + 0x24, 0x00, 0x24, 0x00, 0x34, 0x00, 0x38, 0x00, 0x38, 0x00, 0x60, 0x00, + 0x64, 0x00, 0x64, 0x00, 0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x90, 0x00, + 0x94, 0x00, 0x94, 0x00, 0x96, 0x00, 0x9A, 0x00, 0x9A, 0x00, 0xB2, 0x00, + 0x56, 0x05, 0x57, 0x05, 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, + 0x5C, 0x05, 0x5D, 0x05, 0x87, 0x05, 0x86, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x64, 0x05, 0x65, 0x05, + 0x66, 0x05, 0x67, 0x05, 0x66, 0x05, 0x65, 0x05, 0x64, 0x05, 0x63, 0x05, + 0x85, 0x05, 0x84, 0x05, 0x68, 0x05, 0x69, 0x05, 0x6A, 0x05, 0x6B, 0x05, + 0x6C, 0x05, 0x6D, 0x05, 0x6E, 0x05, 0x6F, 0x05, 0x70, 0x05, 0x71, 0x05, + 0x72, 0x05, 0x6D, 0x05, 0x89, 0x05, 0x88, 0x05, 0x73, 0x05, 0x74, 0x05, + 0x75, 0x05, 0x76, 0x05, 0x77, 0x05, 0x78, 0x05, 0x79, 0x05, 0x7A, 0x05, + 0x8B, 0x05, 0x8A, 0x05, 0x7B, 0x05, 0x8C, 0x05, 0x8C, 0x05, 0x4A, 0x05, + 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, 0x50, 0x05, + 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x83, 0x05, + 0x82, 0x05 +}; + +static const UINT8 CROM_BANK4_WORLD5[] = +{ + 0x24, 0x00, 0x2C, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, + 0x4C, 0x00, 0x54, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, + 0x6C, 0x00, 0x78, 0x00, 0x84, 0x00, 0x88, 0x00, 0x8C, 0x00, 0x90, 0x00, + 0x43, 0x06, 0x45, 0x06, 0x47, 0x06, 0x49, 0x06, 0x43, 0x06, 0x45, 0x06, + 0x47, 0x06, 0x49, 0x06, 0x65, 0x06, 0x63, 0x06, 0x6D, 0x06, 0x6F, 0x06, + 0x71, 0x06, 0x83, 0x06, 0x6D, 0x06, 0x6F, 0x06, 0x71, 0x06, 0x83, 0x06, + 0x6F, 0x06, 0x83, 0x06, 0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06, + 0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06, 0x8F, 0x06, 0x8D, 0x06, + 0xAD, 0x06, 0xAF, 0x06, 0xAD, 0x06, 0xAF, 0x06, 0xC3, 0x06, 0xB1, 0x06, + 0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06, + 0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06, + 0xCB, 0x06, 0xC5, 0x06, 0xE3, 0x06, 0xD1, 0x06, 0xE3, 0x06, 0xD1, 0x06, + 0xE5, 0x06, 0xE3, 0x06 +}; + +static const UINT8 CROM_BANK4_WORLD6[] = +{ + 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00, + 0x52, 0x00, 0x5A, 0x00, 0x62, 0x00, 0x66, 0x00, 0x6A, 0x00, 0x6E, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00, 0x82, 0x00, 0x86, 0x00, + 0x8A, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08, + 0x61, 0x08, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08, 0x61, 0x08, 0x65, 0x08, + 0x63, 0x08, 0x67, 0x08, 0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x67, 0x08, + 0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x81, 0x08, 0x7F, 0x08, 0x83, 0x08, + 0x85, 0x08, 0x87, 0x08, 0x89, 0x08, 0x83, 0x08, 0x85, 0x08, 0x87, 0x08, + 0x89, 0x08, 0x9D, 0x08, 0x9B, 0x08, 0x9F, 0x08, 0xA1, 0x08, 0x9F, 0x08, + 0xA1, 0x08, 0xA5, 0x08, 0xA3, 0x08, 0xA7, 0x08, 0xA9, 0x08, 0xA7, 0x08, + 0xA9, 0x08, 0xBD, 0x08, 0xBB, 0x08, 0xBF, 0x08, 0xC1, 0x08, 0xBF, 0x08, + 0xC1, 0x08, 0xC5, 0x08, 0xC3, 0x08, 0xDD, 0x08, 0xDF, 0x08, 0xDD, 0x08, + 0xDF, 0x08, 0xE1, 0x08, 0xC7, 0x08, 0xC7, 0x08 +}; + +static const UINT8 CROM_BANK4_WORLD7[] = +{ + 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x42, 0x00, 0x46, 0x00, + 0x4A, 0x00, 0x4E, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5E, 0x00, 0x66, 0x00, + 0x6A, 0x00, 0x6E, 0x00, 0x72, 0x00, 0x76, 0x00, 0x78, 0x00, 0x7A, 0x00, + 0x7E, 0x00, 0x82, 0x00, 0x86, 0x00, 0xA1, 0x05, 0xA3, 0x05, 0xA5, 0x05, + 0xA7, 0x05, 0xA9, 0x05, 0xAB, 0x05, 0xAD, 0x05, 0xAF, 0x05, 0xC1, 0x05, + 0xC3, 0x05, 0xC5, 0x05, 0xC7, 0x05, 0xC5, 0x05, 0xC7, 0x05, 0xE3, 0x05, + 0xE5, 0x05, 0xE7, 0x05, 0xE9, 0x05, 0xED, 0x05, 0xEF, 0x05, 0x03, 0x06, + 0x05, 0x06, 0x58, 0x10, 0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x58, 0x10, + 0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x62, 0x10, 0x64, 0x10, 0x25, 0x06, + 0x27, 0x06, 0x25, 0x06, 0x27, 0x06, 0x29, 0x06, 0x2B, 0x06, 0x2F, 0x06, + 0x2F, 0x06, 0x2D, 0x06, 0x2F, 0x06, 0x9C, 0x05, 0x9D, 0x05, 0x9C, 0x05, + 0x9D, 0x05, 0x78, 0x10, 0x9D, 0x05 +}; + +static const UINT8 CROM_BANK4_WORLD8[] = +{ + 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x40, 0x00, + 0x42, 0x00, 0x46, 0x00, 0x4A, 0x00, 0x4E, 0x00, 0x5C, 0x00, 0x6A, 0x00, + 0x6E, 0x00, 0x70, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00, + 0x82, 0x00, 0x88, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x96, 0x00, 0x9A, 0x00, + 0xB0, 0x09, 0xB2, 0x09, 0xB0, 0x09, 0xB2, 0x09, 0xB4, 0x09, 0xB0, 0x09, + 0xB6, 0x09, 0xB6, 0x09, 0xB6, 0x09, 0xB8, 0x09, 0xBA, 0x09, 0xB8, 0x09, + 0xBA, 0x09, 0xBC, 0x09, 0xB8, 0x09, 0xBE, 0x09, 0xD0, 0x09, 0xD2, 0x09, + 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xBE, 0x09, 0xD0, 0x09, + 0xD2, 0x09, 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xDC, 0x09, + 0xD4, 0x09, 0xDE, 0x09, 0xDE, 0x09, 0xF4, 0x09, 0xDE, 0x09, 0xF6, 0x09, + 0xF8, 0x09, 0xF6, 0x09, 0xF8, 0x09, 0x1A, 0x0A, 0xF6, 0x09, 0x1C, 0x0A, + 0x1E, 0x0A, 0x30, 0x0A, 0x1C, 0x0A, 0x1E, 0x0A, 0x30, 0x0A, 0x32, 0x0A, + 0x1C, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x38, 0x0A, + 0x36, 0x0A +}; + +static const UINT8 CROM_BANK4_WORLD9[] = +{ + 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0x00, + 0x58, 0x00, 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00, + 0x88, 0x00, 0x90, 0x00, 0x98, 0x00, 0xA0, 0x00, 0xA6, 0x00, 0xAC, 0x00, + 0xB4, 0x00, 0xBC, 0x00, 0xC4, 0x00, 0xCC, 0x00, 0xD0, 0x00, 0xD4, 0x00, + 0xAF, 0x0B, 0xB1, 0x0B, 0xAF, 0x0B, 0xB1, 0x0B, 0xB3, 0x0B, 0xB5, 0x0B, + 0xEF, 0x0F, 0xF0, 0x0F, 0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B, + 0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B, 0xCF, 0x0B, 0xD1, 0x0B, + 0xF1, 0x0F, 0xF2, 0x0F, 0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11, + 0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11, 0x4F, 0x11, 0x51, 0x11, + 0xFD, 0x0F, 0xFE, 0x0F, 0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B, + 0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B, 0xF7, 0x0B, 0xF9, 0x0B, + 0xF3, 0x0F, 0xF4, 0x0F, 0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C, + 0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C, 0x13, 0x0C, 0x15, 0x0C, + 0xF5, 0x0F, 0xF6, 0x0F, 0x6B, 0x11, 0x6D, 0x11, 0x6F, 0x11, 0x6B, 0x11, + 0x6D, 0x11, 0x6F, 0x11, 0x1D, 0x0C, 0x2F, 0x0C, 0xF7, 0x0F, 0xF8, 0x0F, + 0x31, 0x0C, 0x33, 0x0C, 0x35, 0x0C, 0x37, 0x0C, 0x31, 0x0C, 0x33, 0x0C, + 0x35, 0x0C, 0x37, 0x0C, 0x39, 0x0C, 0x3B, 0x0C, 0xF9, 0x0F, 0xFA, 0x0F, + 0x3D, 0x0C, 0x4F, 0x0C, 0x3D, 0x0C, 0x4F, 0x0C, 0x51, 0x0C, 0x53, 0x0C, + 0xFB, 0x0F, 0xFC, 0x0F, 0xDC, 0x02, 0xDD, 0x02 +}; + +static const UINT8 CROM_BANK5_WORLD0[] = +{ + 0x1C, 0x00, 0x1C, 0x00, 0x32, 0x00, 0x32, 0x00, 0x48, 0x00, 0x48, 0x00, + 0xB6, 0x00, 0x5E, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x74, 0x00, 0x74, 0x00, + 0x8A, 0x00, 0x8A, 0x00, 0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19, + 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, + 0xFF, 0xFF, 0xC9, 0x08, 0xD3, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x45, 0x09, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x09, 0xC5, 0x19, 0xC8, 0x09, 0xC3, 0x19, 0x04, 0x0A, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, + 0xC7, 0x29, 0x89, 0x0A, 0xC7, 0x29, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x29, + 0x49, 0x0B, 0x43, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x49, 0x0B, 0x47, 0x29, 0x49, 0x0B, + 0x47, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, + 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x0B, 0xC1, 0x18, 0x08, 0x0C, 0xC1, 0x18, + 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x04, 0xC0, 0x39, 0x80, 0x0C, 0xC3, 0x39, 0xC4, 0x0C, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x3C, 0x00, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD1[] = +{ + 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00, + 0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19, 0x84, 0x08, 0xC7, 0x18, + 0xE6, 0x5A, 0xBF, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x08, + 0xC4, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x44, 0x09, 0xC7, 0x18, 0xEB, 0x5A, + 0xC1, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x45, 0x1A, + 0x89, 0x0A, 0x43, 0x1A, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x11, 0xC1, 0x29, 0xC9, 0x11, + 0xC1, 0x29, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, + 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0xC0, 0x19, 0x49, 0x03, 0xC0, 0x19, + 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01, + 0xFF, 0xFF, 0xC9, 0x03, 0xC0, 0x39, 0x09, 0x04, 0xC0, 0x39, 0x44, 0x0C, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD2[] = +{ + 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00, + 0x92, 0x00, 0x01, 0x18, 0xC7, 0x39, 0x49, 0x18, 0xC5, 0x39, 0x84, 0x08, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, + 0xC1, 0x08, 0xC7, 0x39, 0x09, 0x09, 0xC5, 0x39, 0x44, 0x09, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09, + 0x47, 0x49, 0xC9, 0x09, 0x45, 0x49, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x02, 0xC7, 0x49, + 0x89, 0x02, 0xC5, 0x49, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x43, 0x29, 0x49, 0x03, + 0x42, 0x29, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, + 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x1B, 0x43, 0x29, 0x09, 0x1C, 0x42, 0x29, + 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0x81, 0x0C, 0x43, 0x39, 0xC9, 0x0C, 0x41, 0x39, 0x04, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD3[] = +{ + 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00, + 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0xC1, 0x39, 0x49, 0x08, 0xC1, 0x39, + 0x84, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0xC1, 0x08, 0xC1, 0x39, 0x09, 0x09, 0xC1, 0x39, 0x44, 0x09, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, + 0x81, 0x01, 0x40, 0x39, 0xC9, 0x01, 0x40, 0x39, 0x04, 0x0A, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, + 0xC3, 0x39, 0x89, 0x0A, 0xC3, 0x39, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x40, 0x19, + 0x49, 0x03, 0x40, 0x19, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xD3, 0x49, 0x09, 0x0C, + 0xC9, 0x49, 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x78, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x24, 0xC7, 0x1B, 0xC9, 0x24, 0xC7, 0x1B, + 0x04, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0x40, 0x65, 0x41, 0x29, 0x88, 0x65, 0x40, 0x29, 0xC4, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD4[] = +{ + 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00, + 0x00, 0x38, 0xC6, 0x18, 0x48, 0x38, 0xC6, 0x18, 0x84, 0x08, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x98, + 0xC9, 0x18, 0x08, 0x99, 0xC9, 0x18, 0x44, 0x09, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x59, 0xC9, 0x18, + 0xC8, 0x59, 0xC9, 0x18, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x40, 0x3A, 0xC4, 0x18, 0x88, 0x3A, + 0xC4, 0x18, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0x80, 0x18, 0x48, 0x03, 0x80, 0x18, + 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0xC0, 0x5B, 0x85, 0x31, 0x08, 0x5C, 0x85, 0x31, 0x44, 0x0C, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD5[] = +{ + 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00, + 0x01, 0x18, 0x43, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x18, + 0xC3, 0x39, 0x09, 0x19, 0xC3, 0x39, 0x45, 0x09, 0xC3, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19, 0x43, 0x39, + 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x43, 0x19, 0x89, 0x0A, + 0x43, 0x19, 0xC5, 0x0A, 0x47, 0x19, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, + 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x2B, 0xC3, 0x19, 0x49, 0x2B, 0xC2, 0x19, + 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x18, 0x09, 0x0C, 0xC3, 0x18, 0x45, 0x0C, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD6[] = +{ + 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00, + 0x92, 0x00, 0x01, 0x18, 0x45, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, + 0xC1, 0x18, 0x45, 0x39, 0x09, 0x19, 0x43, 0x39, 0x45, 0x09, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19, + 0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0xC7, 0x39, + 0x89, 0x0A, 0xC5, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x05, 0x42, 0x49, 0x0B, + 0x03, 0x42, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, + 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC5, 0x39, 0x09, 0x0C, 0xC3, 0x39, + 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0x81, 0x0C, 0x4D, 0x0A, 0xC9, 0x0C, 0x4B, 0x0A, 0x05, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD7[] = +{ + 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00, + 0x92, 0x00, 0x01, 0x18, 0xC5, 0x41, 0x49, 0x18, 0xC3, 0x41, 0x85, 0x08, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, + 0xC1, 0x08, 0xC5, 0x41, 0x09, 0x09, 0xC3, 0x41, 0x45, 0x09, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09, + 0x45, 0x4A, 0xC9, 0x09, 0x43, 0x4A, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A, 0xC5, 0x39, + 0x81, 0x1A, 0xC3, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0xE0, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x5A, 0x49, 0x0B, + 0x43, 0x5A, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, + 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x03, 0xC5, 0x59, 0x09, 0x04, 0xC3, 0x59, + 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x0C, 0x45, 0x29, 0xC8, 0x0C, 0x43, 0x29, 0x04, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD8[] = +{ + 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00, + 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x43, 0x49, 0x49, 0x08, 0x43, 0x49, + 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0xC1, 0x00, 0x43, 0x39, 0x09, 0x01, 0x43, 0x49, 0x45, 0x01, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, + 0x81, 0x09, 0xC3, 0x59, 0xC9, 0x09, 0xC3, 0x59, 0x05, 0x0A, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x32, + 0xC3, 0x5B, 0x89, 0x32, 0xC3, 0x5B, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x03, 0xC3, 0x49, + 0x49, 0x03, 0xC3, 0x49, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x19, 0x09, 0x0C, + 0xC3, 0x19, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, + 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x14, 0xC5, 0x39, 0xC9, 0x14, 0xC3, 0x39, + 0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, + 0xFF, 0xFF, 0x41, 0x0D, 0xC7, 0x39, 0x89, 0x0D, 0xC5, 0x39, 0xC5, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK5_WORLD9[] = +{ + 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00, + 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x03, 0x1A, 0x49, 0x08, 0x03, 0x1A, + 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, + 0xFF, 0xFF, 0xC1, 0x18, 0xC3, 0x18, 0x09, 0x19, 0x03, 0x1A, 0x45, 0x09, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, + 0x81, 0x19, 0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, + 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A, + 0x45, 0x18, 0x89, 0x1A, 0x43, 0x18, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, + 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x1B, 0xC5, 0x18, + 0x49, 0x1B, 0xC3, 0x18, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, + 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x13, 0x47, 0x39, 0x09, 0x14, + 0x45, 0x39, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, + 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x1C, 0x45, 0x19, 0xC9, 0x1C, 0x43, 0x19, + 0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, + 0xFF, 0xFF, 0x41, 0x0D, 0xC5, 0x18, 0x89, 0x0D, 0xC3, 0x18, 0xC5, 0x0D, + 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF +}; + +static const UINT8 CROM_BANK6[] = +{ + 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x04, + 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x30, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x42, 0x00, 0x00, 0x33, 0x04, 0x00, 0x54, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x20, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x33, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x23, 0x02, 0x03, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x22, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x12, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x21, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x22, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00 +}; + +static const UINT8 CROM_BANK6_EXTRA[] = +{ + 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x02, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x34, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x05, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, + 0x50, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x01, 0x50, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x21, + 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x12, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x31, 0x12, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00 +}; + +static const UINT8 CROM_BANK7_WORLD0[] = { 0x03, 0x03, 0x03, 0x03, 0x0C, 0x0C, 0x0A, 0x07, 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x08 }; +static const UINT8 CROM_BANK7_WORLD1[] = { 0x03, 0x05, 0x01, 0x02, 0x04, 0x04 }; +static const UINT8 CROM_BANK7_WORLD2[] = { 0x03, 0x05, 0x07, 0x07, 0x08, 0x08, 0x01 }; +static const UINT8 CROM_BANK7_WORLD3[] = { 0x07, 0x07, 0x07, 0x08, 0x05, 0x08, 0x07, 0x0B }; +static const UINT8 CROM_BANK7_WORLD4[] = { 0x0A, 0x0B, 0x0A, 0x0A, 0x10, 0x10 }; +static const UINT8 CROM_BANK7_WORLD5[] = { 0x05, 0x08, 0x04, 0x08, 0x08, 0x07 }; +static const UINT8 CROM_BANK7_WORLD6[] = { 0x04, 0x07, 0x05, 0x08, 0x06, 0x08, 0x03 }; +static const UINT8 CROM_BANK7_WORLD7[] = { 0x07, 0x06, 0x06, 0x05, 0x08, 0x07, 0x0A }; +static const UINT8 CROM_BANK7_WORLD8[] = { 0x06, 0x05, 0x01, 0x08, 0x05, 0x05, 0x06, 0x08 }; +static const UINT8 CROM_BANK7_WORLD9[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + +static const struct CBANK CROM_BANK4[] = +{ + { CROM_BANK4_WORLD0, sizeof CROM_BANK4_WORLD0 }, + { CROM_BANK4_WORLD1, sizeof CROM_BANK4_WORLD1 }, + { CROM_BANK4_WORLD2, sizeof CROM_BANK4_WORLD2 }, + { CROM_BANK4_WORLD3, sizeof CROM_BANK4_WORLD3 }, + { CROM_BANK4_WORLD4, sizeof CROM_BANK4_WORLD4 }, + { CROM_BANK4_WORLD5, sizeof CROM_BANK4_WORLD5 }, + { CROM_BANK4_WORLD6, sizeof CROM_BANK4_WORLD6 }, + { CROM_BANK4_WORLD7, sizeof CROM_BANK4_WORLD7 }, + { CROM_BANK4_WORLD8, sizeof CROM_BANK4_WORLD8 }, + { CROM_BANK4_WORLD9, sizeof CROM_BANK4_WORLD9 }, +}; + +static const struct CBANK CROM_BANK5[] = +{ + { CROM_BANK5_WORLD0, sizeof CROM_BANK5_WORLD0 }, + { CROM_BANK5_WORLD1, sizeof CROM_BANK5_WORLD1 }, + { CROM_BANK5_WORLD2, sizeof CROM_BANK5_WORLD2 }, + { CROM_BANK5_WORLD3, sizeof CROM_BANK5_WORLD3 }, + { CROM_BANK5_WORLD4, sizeof CROM_BANK5_WORLD4 }, + { CROM_BANK5_WORLD5, sizeof CROM_BANK5_WORLD5 }, + { CROM_BANK5_WORLD6, sizeof CROM_BANK5_WORLD6 }, + { CROM_BANK5_WORLD7, sizeof CROM_BANK5_WORLD7 }, + { CROM_BANK5_WORLD8, sizeof CROM_BANK5_WORLD8 }, + { CROM_BANK5_WORLD9, sizeof CROM_BANK5_WORLD9 }, +}; + +static const struct CBANK CROM_BANK7[] = +{ + { CROM_BANK7_WORLD0, sizeof CROM_BANK7_WORLD0 }, + { CROM_BANK7_WORLD1, sizeof CROM_BANK7_WORLD1 }, + { CROM_BANK7_WORLD2, sizeof CROM_BANK7_WORLD2 }, + { CROM_BANK7_WORLD3, sizeof CROM_BANK7_WORLD3 }, + { CROM_BANK7_WORLD4, sizeof CROM_BANK7_WORLD4 }, + { CROM_BANK7_WORLD5, sizeof CROM_BANK7_WORLD5 }, + { CROM_BANK7_WORLD6, sizeof CROM_BANK7_WORLD6 }, + { CROM_BANK7_WORLD7, sizeof CROM_BANK7_WORLD7 }, + { CROM_BANK7_WORLD8, sizeof CROM_BANK7_WORLD8 }, + { CROM_BANK7_WORLD9, sizeof CROM_BANK7_WORLD9 }, +}; + +static const UINT16 cchip_extra_patch[][8] = +{ + { 0x0168, 0x0078, 0x0168, 0x0168, 0x0168, 0x02D0, 0x0168, 0x003C }, + { 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0000, 0x0000 }, + { 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 }, + { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x001E, 0x0168, 0x0168 }, + { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 }, + { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 }, + { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000 }, + { 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 }, + { 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4 }, + { 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500 } +}; + +static const UINT8 cchip_goalin[15][6] = +{ + { 0x00, 0x00, 0x28, 0x28, 0x50, 0x50 }, + { 0x00, 0x00, 0x00, 0x00, 0x50, 0x50 }, + { 0x00, 0x10, 0x20, 0x30, 0x00, 0x10 }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50 }, + { 0x00, 0x18, 0x30, 0x00, 0x18, 0x30 }, + { 0x00, 0x18, 0x30, 0x30, 0x18, 0x00 }, + { 0x00, 0x28, 0x50, 0x00, 0x28, 0x50 }, + { 0x00, 0x30, 0x20, 0x50, 0x10, 0x20 }, + { 0x00, 0x50, 0x00, 0x50, 0x00, 0x50 }, + { 0x30, 0x18, 0x00, 0x30, 0x18, 0x00 }, + { 0x30, 0x18, 0x00, 0x00, 0x18, 0x30 }, + { 0x30, 0x00, 0x10, 0x40, 0x50, 0x20 }, + { 0x30, 0x20, 0x10, 0x00, 0x10, 0x00 }, + { 0x50, 0x40, 0x30, 0x20, 0x10, 0x00 }, + { 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 } +}; + +static const UINT16 cchip_round_height[] = +{ + 0x02DC, 0x03B4, 0x0444, 0x04BC, 0x03B4, 0x0444, 0x05DC, 0x050C, + 0x0594, 0x06B4, 0x06B4, 0x0894, 0x065C, 0x06CC, 0x07BC, 0x08BC, + 0x0704, 0x059C, 0x030C, 0x0504, 0x0504, 0x0564, 0x05CC, 0x0644, + 0x080C, 0x086C, 0x08E4, 0x0954, 0x065C, 0x06D4, 0x0754, 0x07C4, + 0x06D4, 0x0754, 0x0824, 0x0884, 0x080C, 0x086C, 0x08E4, 0x096C, + 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, + 0x0999, 0x0999 +}; + +static const UINT32 cchip_round_address[] = +{ + 0x030000, 0x030360, 0x030798, 0x030CA8, 0x0311B8, 0x0315F0, 0x031B00, 0x0321C0, + 0x032880, 0x032E68, 0x033600, 0x033D98, 0x0347B8, 0x034E78, 0x035610, 0x035E80, + 0x0368A0, 0x037038, 0x037620, 0x037A58, 0x038118, 0x038700, 0x038CE8, 0x0393A8, + 0x039A68, 0x03A2D8, 0x03AC20, 0x03B568, 0x03BF88, 0x03C648, 0x03CDE0, 0x03D650, + 0x03DEC0, 0x03E658, 0x03EEC8, 0x03F738, 0x040080, 0x0408F0, 0x041238, 0x041B80, + 0x0425A0, 0x042678, 0x042750, 0x042828, 0x042900, 0x0429D8, 0x042AB0, 0x042B88, + 0x042C60, 0x042D38 +}; + +static void RequestRoundData(void) +{ + INT32 round = CRAM[1][0x141]; /* 0...49 */ + + memcpy(CRAM[1], CROM_BANK1, sizeof CROM_BANK1); + memcpy(CRAM[2], CROM_BANK2, sizeof CROM_BANK2); + + CRAM[1][1] = cchip_round_height[round] >> 0; + CRAM[1][2] = cchip_round_height[round] >> 8; + + CRAM[1][0x142] = cchip_round_address[round] >> 24; + CRAM[1][0x143] = cchip_round_address[round] >> 16; + CRAM[1][0x144] = cchip_round_address[round] >> 8; + CRAM[1][0x145] = cchip_round_address[round] >> 0; + + /* set the secret room or boss flag */ + + CRAM[1][0x148] = (round >= 40 || round % 4 == 3); +} + +static void RequestWorldData(void) +{ + INT32 world = CRAM[0][0x00D] / 4; /* 0...9 */ + + /* the extra version has the world data swapped around */ + + if (ExtraVersion) + { + static const UINT8 world_swap[] = + { + 8, 7, 6, 4, 0, 2, 3, 5, 1, 9 + }; + + world = world_swap[world]; + } + + /* first two bytes in each bank are left unchanged */ + + memcpy(CRAM[4] + 2, CROM_BANK4[world].data, CROM_BANK4[world].size); + memcpy(CRAM[5] + 2, CROM_BANK5[world].data, CROM_BANK5[world].size); + memcpy(CRAM[7] + 2, CROM_BANK7[world].data, CROM_BANK7[world].size); + + /* banks 5 and 6 are different in the extra version */ + + if (ExtraVersion) + { + INT32 i; + + for (i = 0; i < 8; i++) + { + UINT16 patch = cchip_extra_patch[world][i]; + + if (patch != 0) + { + CRAM[5][CRAM[5][2] + 22 * i + 18] = patch >> 0; + CRAM[5][CRAM[5][2] + 22 * i + 19] = patch >> 8; + } + } + + memcpy(CRAM[6] + 2, CROM_BANK6_EXTRA, sizeof CROM_BANK6_EXTRA); + } + else + { + memcpy(CRAM[6] + 2, CROM_BANK6, sizeof CROM_BANK6); + } +} + +static void RequestGoalinData(void) +{ + INT32 n = rand() % 15; + + CRAM[1][0x14B] = 0x00; /* x coordinates */ + CRAM[1][0x14D] = 0x10; + CRAM[1][0x14F] = 0x20; + CRAM[1][0x151] = 0x38; + CRAM[1][0x153] = 0x50; + CRAM[1][0x155] = 0x60; + + CRAM[1][0x14A] = cchip_goalin[n][0]; /* y coordinates */ + CRAM[1][0x14C] = cchip_goalin[n][1]; + CRAM[1][0x14E] = cchip_goalin[n][2]; + CRAM[1][0x150] = cchip_goalin[n][3]; + CRAM[1][0x152] = cchip_goalin[n][4]; + CRAM[1][0x154] = cchip_goalin[n][5]; +} + +void RainbowCChipUpdate(UINT8 Input1, UINT8 Input2, UINT8 Input3, UINT8 Input4) +{ + if (CRAM[1][0x100] == 1) { + RequestRoundData(); + + CRAM[1][0x100] = 0xFF; + } + + if (CRAM[5][0x000] == 1) { + RequestWorldData(); + + CRAM[5][0x000] = 0xFF; + } + + if (CRAM[1][0x149] == 1) { + RequestGoalinData(); + + CRAM[1][0x149] = 0xFF; + } + + CRAM[0][3] = Input1; + CRAM[0][4] = Input2; + CRAM[0][5] = Input3; + CRAM[0][6] = Input4; +} + +UINT16 RainbowCChipCtrlRead() +{ + return 0x01; +} + +UINT16 RainbowCChipRamRead(UINT32 Offset) +{ + return CRAM[CurrentBank][Offset]; +} + +void RainbowCChipCtrlWrite(UINT16) +{ + +} + +void RainbowCChipBankWrite(UINT16 Data) +{ + CurrentBank = Data & 7; +} + +void RainbowCChipRamWrite(UINT32 Offset, UINT16 Data) +{ + CRAM[CurrentBank][Offset] = Data; +} + +void RainbowCChipReset() +{ + for (INT32 i = 0; i < 8; i++) { + memset(CRAM[i], 0, 0x400); + } + + ExtraVersion = 0; + CurrentBank = 0; +} + +void RainbowCChipInit(INT32 Version) +{ + ExtraVersion = Version; + + for (INT32 i = 0; i < 8; i++) { + CRAM[i] = (UINT8*)malloc(0x400); + memset(CRAM[i], 0, 0x400); + } + + TaitoIC_RainbowCChipInUse = 1; +} + +void RainbowCChipExit() +{ + for (INT32 i = 0; i < 8; i++) { + if (CRAM[i]) { + free(CRAM[i]); + CRAM[i] = NULL; + } + } + + ExtraVersion = 0; + CurrentBank = 0; +} + +void RainbowCChipScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + for (INT32 i = 0; i < 8; i++) { + memset(&ba, 0, sizeof(ba)); + ba.Data = CRAM[i]; + ba.nLen = 0x400; + ba.szName = "CChip Ram"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(CurrentBank); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// Operation Wolf C-Chip + +#define OPWOLF_REGION_JAPAN 1 +#define OPWOLF_REGION_US 2 +#define OPWOLF_REGION_WORLD 3 +#define OPWOLF_REGION_OTHER 4 + +static INT32 CChipRegion; + +static UINT8 CurrentCmd=0; +static UINT8* CChipRam=0; +static UINT8 CChipLast_7a=0; +static UINT8 CChipLast_04=0; +static UINT8 CChipLast_05=0; +static UINT8 CChipCoinsForCredit[2]={1,1}; +static UINT8 CChipCreditsForCoin[2]={1,1}; +static UINT8 CChipCoins[2]={0,0}; +static UINT8 c588=0, c589=0, c58a=0; + +static const UINT16 level_data_00[0xcc] = +{ + 0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008, + 0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01, + 0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030, + 0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309, + 0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01, + 0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028, + 0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b, + 0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401, + 0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015, + 0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b, + 0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401, + 0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d, + 0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a, + 0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001, + 0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e, + 0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a, + 0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001, + 0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045, + 0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b, + 0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101, + 0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042, + 0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b, + 0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301, + 0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028, + 0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b, + 0x0000,0xf501,0x0008,0x8026 +}; + +static const UINT16 level_data_01[0xcc] = +{ + 0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209, + 0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01, + 0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040, + 0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309, + 0x0300,0x4d01,0xc003,0x0028,0x0b80,0x000b,0x0000,0x0b02, + 0x8009,0x0029,0x0b80,0x0409,0x0000,0x0f02,0x8008,0x8028, + 0x0b80,0x040a,0x0000,0x3502,0x000a,0x8028,0x0b80,0x050a, + 0x0000,0x1002,0x8006,0x8028,0x0b80,0x120a,0x0000,0x3602, + 0x0008,0x004d,0x0b80,0x120a,0x0000,0x3602,0x0008,0x004f, + 0x0b80,0x120a,0x0000,0x3602,0x0008,0x0001,0x0b80,0x120a, + 0x0000,0x3602,0x0008,0x0003,0x0b80,0x130a,0x0000,0x3a02, + 0x0007,0x0023,0x0b80,0x130a,0x0000,0x3a02,0x0007,0x8025, + 0x0b80,0x130a,0x0000,0x3a02,0x8009,0x0023,0x0b80,0x130a, + 0x0000,0x3a02,0x8009,0x8025,0x0b80,0x140a,0x0000,0x3e02, + 0x0007,0x000d,0x0b80,0x140a,0x0000,0x3e02,0x0007,0x800f, + 0x0b80,0x000b,0x0000,0x0102,0x0007,0x804e,0x0b80,0xd24b, + 0x0000,0x0302,0x0007,0x000e,0x0b80,0x000b,0x0000,0x0402, + 0x8006,0x0020,0x0b80,0xd34b,0x0000,0x0502,0x8006,0x0024, + 0x0b80,0x000b,0x0000,0x0602,0x8009,0x0001,0x0b80,0xd44b, + 0x0000,0x0702,0x800b,0x800b,0x0b80,0xd54b,0x0000,0x0802, + 0x800b,0x000e,0x0b80,0x000b,0x0000,0x0902,0x800b,0x0010, + 0x0b80,0x000b,0x0000,0x0a02,0x0009,0x0024,0x0b80,0xd64b, + 0x0000,0x0c02,0x000c,0x8021,0x0b80,0x000b,0x0000,0x0d02, + 0x000c,0x0025,0x0b80,0x000b,0x0000,0x0e02,0x8009,0x004e, + 0x0b80,0x0609,0x0300,0x4e01,0x8006,0x8012,0x0b80,0x0609, + 0x0300,0x4e01,0x0007,0x8007 +}; + +static const UINT16 level_data_02[0xcc] = +{ + 0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b, + 0x0300,0x4501,0x2001,0x0030,0x0780,0x1208,0x0300,0x5d01, + 0x0004,0x0010,0x0780,0x1208,0x0300,0x5d01,0x2004,0x001c, + 0x0780,0x1208,0x0300,0x5d01,0xe003,0x0026,0x0780,0x1208, + 0x0300,0x5d01,0x8003,0x0034,0x0780,0x1208,0x0300,0x5d01, + 0x3004,0x0040,0x0780,0x010c,0x0300,0x4601,0x4004,0x0022, + 0x0780,0x010c,0x0300,0x4601,0x6004,0x0042,0x0780,0x000c, + 0x0500,0x7b01,0x800b,0x0008,0x0780,0x010c,0x0300,0x4601, + 0x2004,0x0008,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000, + 0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000, + 0x0000,0xf001,0x0000,0x0000,0x0b80,0x000b,0x0000,0x1902, + 0x000b,0x0004,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8003, + 0x0b80,0x000b,0x0000,0x1902,0x000b,0x000c,0x0b80,0x000b, + 0x0000,0x1a02,0x0009,0x800b,0x0b80,0x000b,0x0000,0x1902, + 0x000b,0x001c,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x801b, + 0x0b80,0x000b,0x0000,0x1902,0x000b,0x002c,0x0b80,0x000b, + 0x0000,0x1a02,0x0009,0x802b,0x0b80,0x000b,0x0000,0x1902, + 0x000b,0x0044,0x0b80,0x000b,0x0000,0x1a02,0x0009,0x8043, + 0x0b80,0x000b,0x0000,0x1902,0x000b,0x004c,0x0b80,0x000b, + 0x0000,0x1a02,0x0009,0x804b,0x0b80,0x020c,0x0300,0x4801, + 0xa009,0x0010,0x0b80,0x020c,0x0300,0x4801,0xa009,0x0028, + 0x0b80,0x020c,0x0300,0x4801,0xa009,0x0036,0x0000,0x0000, + 0x0000,0xf001,0x0000,0x0000,0x0000,0x0000,0x0000,0xf001, + 0x0000,0x0000,0x0000,0x0000,0x0000,0xf001,0x0000,0x0000, + 0x0000,0x0000,0x0000,0xf001,0x0000,0x0000,0x0000,0x0000, + 0x0000,0xf001,0x0000,0x0000 +}; + +static const UINT16 level_data_03[0xcc] = +{ + 0x0480,0x000b,0x0300,0x4501,0x0001,0x0018,0x0480,0x000b, + 0x0300,0x4501,0x2001,0x002b,0x0780,0x010c,0x0300,0x4601, + 0x0004,0x000d,0x0780,0x000c,0x0500,0x7b01,0x800b,0x0020, + 0x0780,0x010c,0x0300,0x4601,0x2004,0x0020,0x0780,0x010c, + 0x0300,0x4601,0x8003,0x0033,0x0780,0x010c,0x0300,0x4601, + 0x0004,0x003c,0x0780,0x010c,0x0300,0x4601,0xd003,0x0045, + 0x0780,0x000c,0x0500,0x7b01,0x900b,0x0041,0x0780,0x010c, + 0x0300,0x4601,0x3004,0x0041,0x0b80,0x020c,0x0300,0x4801, + 0x0007,0x0000,0x0b80,0x410a,0x0000,0x2b02,0xe006,0x4049, + 0x0b80,0x020c,0x0300,0x4801,0x8007,0x000b,0x0b80,0x000b, + 0x0000,0x2702,0x800a,0x8005,0x0b80,0x000b,0x0000,0x1e02, + 0x0008,0x800e,0x0b80,0x000b,0x0000,0x1f02,0x8007,0x0011, + 0x0b80,0x000b,0x0000,0x2802,0x000b,0x0012,0x0b80,0x000b, + 0x0000,0x2002,0x0007,0x8015,0x0b80,0x000b,0x0000,0x2102, + 0x0007,0x801b,0x0b80,0x000b,0x0000,0x2902,0x800a,0x001a, + 0x0b80,0x000b,0x0000,0x2202,0x8007,0x001e,0x0b80,0x000b, + 0x0000,0x1e02,0x0008,0x0025,0x0b80,0x000b,0x0000,0x2302, + 0x8007,0x802c,0x0b80,0x000b,0x0000,0x2802,0x000b,0x8028, + 0x0b80,0x020c,0x0300,0x4801,0x0007,0x0030,0x0b80,0x400a, + 0x0000,0x2e02,0x4007,0x002d,0x0b80,0x000b,0x0000,0x2702, + 0x800a,0x8035,0x0b80,0x020c,0x0300,0x4801,0x8007,0x0022, + 0x0b80,0x000b,0x0000,0x2402,0x8007,0x0047,0x0b80,0x000b, + 0x0000,0x2a02,0x800a,0x004b,0x0b80,0x000b,0x0000,0x2502, + 0x0007,0x804b,0x0b80,0x000b,0x0000,0x2602,0x0007,0x004e, + 0x0b80,0x020c,0x0300,0x4801,0x0007,0x8043,0x0b80,0x020c, + 0x0300,0x4801,0x8007,0x803d +}; + +static const UINT16 level_data_04[0xcc] = +{ + 0x0780,0x0209,0x0300,0x4c01,0x0004,0x0010,0x0780,0x0209, + 0x0300,0x4c01,0x4004,0x0020,0x0780,0x0309,0x0300,0x4d01, + 0xe003,0x0030,0x0780,0x0309,0x0300,0x4d01,0x8003,0x0040, + 0x0780,0x0209,0x0300,0x4c01,0x8004,0x0018,0x0780,0x0309, + 0x0300,0x4d01,0xc003,0x0028,0x0780,0x000b,0x0300,0x5601, + 0x8004,0x0008,0x0780,0x000b,0x0300,0x5601,0x8004,0x0038, + 0x0780,0x000b,0x0300,0x5501,0x8004,0x0048,0x0980,0x0509, + 0x0f00,0x0f01,0x4005,0x4007,0x0980,0x0509,0x0f00,0x0f01, + 0x4005,0x4037,0x0b80,0x030a,0x0000,0x1302,0x8006,0x0040, + 0x0b80,0x110a,0x0000,0x1502,0x8008,0x8048,0x0b80,0x110a, + 0x0000,0x1502,0x8008,0x8049,0x0b80,0x000b,0x0000,0xf601, + 0x0007,0x8003,0x0b80,0x000b,0x0000,0xf701,0x0007,0x0005, + 0x0b80,0x000b,0x0000,0xf901,0x0007,0x8008,0x0b80,0x000b, + 0x0000,0xf901,0x0007,0x0010,0x0b80,0x000b,0x0000,0xfa01, + 0x0007,0x8013,0x0b80,0x000b,0x0000,0xf801,0x800b,0x800b, + 0x0b80,0x000b,0x0000,0x0002,0x800b,0x801a,0x0b80,0x000b, + 0x0000,0xf901,0x0007,0x8017,0x0b80,0x000b,0x0000,0xfa01, + 0x0007,0x001b,0x0b80,0x000b,0x0000,0xf801,0x800b,0x0013, + 0x0b80,0x000b,0x0000,0x4202,0x800b,0x0016,0x0b80,0x000b, + 0x0000,0xfb01,0x8007,0x8020,0x0b80,0x000b,0x0000,0xf601, + 0x0007,0x8023,0x0b80,0x000b,0x0000,0x4202,0x800b,0x800e, + 0x0b80,0x000b,0x0000,0x4302,0x800b,0x801d,0x0b80,0x000b, + 0x0000,0xf701,0x0007,0x0025,0x0b80,0x000b,0x0000,0xfd01, + 0x8006,0x003f,0x0b80,0x000b,0x0000,0xfe01,0x0007,0x0046, + 0x0b80,0x000b,0x0000,0xff01,0x8007,0x8049,0x0b80,0x000b, + 0x0000,0xfc01,0x8009,0x0042 +}; + +static const UINT16 level_data_05[0xcc] = +{ + 0x0480,0x1008,0x0300,0x5701,0x0001,0x0010,0x0480,0x1008, + 0x0300,0x5701,0x0001,0x002b,0x0780,0x0009,0x0300,0x4a01, + 0x0004,0x0020,0x0780,0x1208,0x0300,0x5d01,0x0004,0x0030, + 0x0780,0x0209,0x0300,0x4c01,0x0004,0x0038,0x0780,0x0309, + 0x0300,0x4d01,0x0004,0x0048,0x0980,0x1108,0x0300,0x5a01, + 0xc005,0x0018,0x0980,0x0109,0x0300,0x4b01,0xc005,0x0028, + 0x0b80,0x020a,0x0000,0x6401,0x8006,0x0004,0x0c80,0x010b, + 0x0000,0xf201,0x8006,0x8002,0x0b80,0x020a,0x0000,0x6401, + 0x8006,0x0017,0x0c80,0x010b,0x0000,0xf201,0x8006,0x8015, + 0x0b80,0x020a,0x0000,0x6401,0x0007,0x0034,0x0c80,0x010b, + 0x0000,0xf201,0x0007,0x8032,0x0b80,0x020a,0x0000,0x6401, + 0x8006,0x803e,0x0c80,0x010b,0x0000,0xf201,0x8006,0x803d, + 0x0b80,0x100a,0x0000,0x6001,0x0007,0x0008,0x0b80,0x100a, + 0x0000,0x6001,0x0007,0x000b,0x0b80,0x100a,0x0000,0x6001, + 0x0007,0x001b,0x0b80,0x100a,0x0000,0x6001,0x0007,0x001e, + 0x0b80,0x100a,0x0000,0x6001,0x8007,0x0038,0x0b80,0x100a, + 0x0000,0x6001,0x8007,0x003b,0x0b80,0x100a,0x0000,0x6001, + 0x0007,0x8042,0x0b80,0x100a,0x0000,0x6001,0x0007,0x8045, + 0x0c80,0x000b,0x0000,0xf101,0x800b,0x8007,0x0c80,0x000b, + 0x0000,0xf101,0x800b,0x801a,0x0c80,0x000b,0x0000,0xf101, + 0x000c,0x8037,0x0c80,0x000b,0x0000,0xf101,0x800b,0x0042, + 0x0c80,0xd04b,0x0000,0xf301,0x8006,0x8009,0x0c80,0xd04b, + 0x0000,0xf301,0x8006,0x801c,0x0c80,0xd04b,0x0000,0xf301, + 0x8006,0x0044,0x0c80,0x030b,0x0000,0xf401,0x0008,0x0028, + 0x0c80,0x030b,0x0000,0xf401,0x0008,0x804b,0x0c00,0x040b, + 0x0000,0xf501,0x0008,0x8026 +}; + +static const UINT16 level_data_06[0xcc] = +{ + 0x0000,0x1008,0x0300,0x5701,0x0001,0x0010,0x0000,0x1008, + 0x0300,0x5701,0x0001,0x002b,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0700,0x0009,0x0300,0x4a01,0x0004,0x0020, + 0x0700,0x1208,0x0300,0x5d01,0x0004,0x0030,0x0700,0x0209, + 0x0300,0x4c01,0x0004,0x0038,0x0700,0x0309,0x0300,0x4d01, + 0x0004,0x0048,0x0900,0x1108,0x0300,0x5a01,0xc005,0x0018, + 0x0900,0x0109,0x0300,0x4b01,0xc005,0x0028,0x0000,0x000b, + 0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000, + 0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000, + 0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b, + 0x0000,0x0000,0x0018,0x0000,0x0000,0x000b,0x0000,0x0000, + 0x0018,0x0000,0x0000,0x000b,0x0000,0x0000,0x0018,0x0000, + 0x0000,0x000b,0x0000,0x0000,0x0018,0x0000,0x0000,0x000b, + 0x0000,0x0000,0x0018,0x0000,0x0980,0xdb4c,0x0000,0x3202, + 0x0006,0x0004,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8002, + 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8003,0x0b80,0x0609, + 0x0300,0x4e01,0x5006,0x8004,0x0b80,0x0609,0x0300,0x4e01, + 0x5006,0x0008,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0010, + 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0012,0x0b80,0x0609, + 0x0300,0x4e01,0x5006,0x0014,0x0b80,0x0609,0x0300,0x4e01, + 0x5006,0x0016,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0018, + 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0020,0x0b80,0x0609, + 0x0300,0x4e01,0x5006,0x0023,0x0b80,0x0609,0x0300,0x4e01, + 0x5006,0x0030,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0038, + 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0040,0x0b80,0x0609, + 0x0300,0x4e01,0x5006,0x0042 +}; + +static const UINT16 *const level_data_lookup[] = +{ + level_data_00, + level_data_01, + level_data_02, + level_data_03, + level_data_04, + level_data_05, + level_data_06, +}; + +static void AccessLevelDataCommand() +{ + // Level data command + if (CurrentCmd==0xf5) + { + INT32 level=CChipRam[0x1b]; + const UINT16* level_data=level_data_lookup[level]; + INT32 i=0; + for (i=0; i<0xcc; i++) + { + CChipRam[0x200 + i*2 + 0]=level_data[i]>>8; + CChipRam[0x200 + i*2 + 1]=level_data[i]&0xff; + } + + // The bootleg cchip writes 0 to these locations - hard to tell what the real one writes + CChipRam[0x0]=0; + CChipRam[0x76]=0; + CChipRam[0x75]=0; + CChipRam[0x74]=0; + CChipRam[0x72]=0; + CChipRam[0x71]=0; + CChipRam[0x70]=0; + CChipRam[0x66]=0; + CChipRam[0x2b]=0; + CChipRam[0x30]=0; + CChipRam[0x31]=0; + CChipRam[0x32]=0; + CChipRam[0x27]=0; + c588=0; + c589=0; + c58a=0; + + CChipRam[0x1a]=0; + CChipRam[0x7a]=1; // Signal command complete + } + + CurrentCmd=0; +} + +static void updateDifficulty(INT32 Mode) +{ + // The game is made up of 6 rounds, when you complete the + // sixth you return to the start but with harder difficulty. + if (Mode == 0) + { + switch (CChipRam[0x15]&3) // Dipswitch B + { + case 3: + CChipRam[0x2c]=0x31; + CChipRam[0x77]=0x05; + CChipRam[0x25]=0x0f; + CChipRam[0x26]=0x0b; + break; + case 0: + CChipRam[0x2c]=0x20; + CChipRam[0x77]=0x06; + CChipRam[0x25]=0x07; + CChipRam[0x26]=0x03; + break; + case 1: + CChipRam[0x2c]=0x31; + CChipRam[0x77]=0x05; + CChipRam[0x25]=0x0f; + CChipRam[0x26]=0x0b; + break; + case 2: + CChipRam[0x2c]=0x3c; + CChipRam[0x77]=0x04; + CChipRam[0x25]=0x13; + CChipRam[0x26]=0x0f; + break; + } + } + else + { + switch (CChipRam[0x15]&3) // Dipswitch B + { + case 3: + CChipRam[0x2c]=0x46; + CChipRam[0x77]=0x05; + CChipRam[0x25]=0x11; + CChipRam[0x26]=0x0e; + break; + case 0: + CChipRam[0x2c]=0x30; + CChipRam[0x77]=0x06; + CChipRam[0x25]=0x0b; + CChipRam[0x26]=0x03; + break; + case 1: + CChipRam[0x2c]=0x3a; + CChipRam[0x77]=0x05; + CChipRam[0x25]=0x0f; + CChipRam[0x26]=0x09; + break; + case 2: + CChipRam[0x2c]=0x4c; + CChipRam[0x77]=0x04; + CChipRam[0x25]=0x19; + CChipRam[0x26]=0x11; + break; + }; + } +} + +void OpwolfCChipUpdate(UINT8 Input1, UINT8 Input2) +{ + // Update input ports, these are used by both the 68k directly and by the c-chip + CChipRam[0x4] = Input1; + CChipRam[0x5] = Input2; + + // Coin slots + if (CChipRam[0x4]!=CChipLast_04) + { + INT32 slot=-1; + + if (CChipRam[0x4]&1) slot=0; + if (CChipRam[0x4]&2) slot=1; + + if (slot != -1) + { + CChipCoins[slot]++; + if (CChipCoins[slot] >= CChipCoinsForCredit[slot]) + { + CChipRam[0x53]+=CChipCreditsForCoin[slot]; + CChipRam[0x51]=0x55; + CChipRam[0x52]=0x55; + CChipCoins[slot]-=CChipCoinsForCredit[slot]; + } + } + + if (CChipRam[0x53]>9) + CChipRam[0x53]=9; + } + CChipLast_04=CChipRam[0x4]; + + // Service switch + if (CChipRam[0x5]!=CChipLast_05) + { + if ((CChipRam[0x5]&4)==0) + { + CChipRam[0x53]++; + CChipRam[0x51]=0x55; + CChipRam[0x52]=0x55; + } + } + CChipLast_05=CChipRam[0x5]; + + // Special handling for last level + if (CChipRam[0x1b]==0x6) + { + // Check for triggering final helicopter (end boss) + if (c58a==0) + { + if ((CChipRam[0x72]&0x7f) >= 8 && CChipRam[0x74]==0 && CChipRam[0x1c]==0 && CChipRam[0x1d]==0 && CChipRam[0x1f]==0) + { + CChipRam[0x30]=1; + CChipRam[0x74]=1; + c58a=1; + } + } + + if (CChipRam[0x1a]==0x90) + CChipRam[0x74]=0; + + if (c58a!=0) + { + if (c589==0 && CChipRam[0x27]==0 && CChipRam[0x75]==0 && CChipRam[0x1c]==0 && CChipRam[0x1d]==0 && CChipRam[0x1e]==0 && CChipRam[0x1f]==0) + { + CChipRam[0x31]=1; + CChipRam[0x75]=1; + c589=1; + } + } + + if (CChipRam[0x2b]==0x1) + { + CChipRam[0x2b]=0; + + if (CChipRam[0x30]==0x1) + { + if (CChipRam[0x1a]!=0x90) + CChipRam[0x1a]--; + } + + if (CChipRam[0x72]==0x9) + { + if (CChipRam[0x76]!=0x4) + { + CChipRam[0x76]=3; + } + } + else + { + // This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it + c588|=0x80; + + CChipRam[0x72]=c588; + c588++; + + CChipRam[0x1a]--; + CChipRam[0x1a]--; + CChipRam[0x1a]--; + } + } + + // Update difficulty settings + if (CChipRam[0x76]==0) + { + CChipRam[0x76]=1; + updateDifficulty(1); + } + } + + // These variables are cleared every frame during attract mode and the intro. + if (CChipRam[0x34] < 2) + { + updateDifficulty(0); + CChipRam[0x76]=0; + CChipRam[0x75]=0; + CChipRam[0x74]=0; + CChipRam[0x72]=0; + CChipRam[0x71]=0; + CChipRam[0x70]=0; + CChipRam[0x66]=0; + CChipRam[0x2b]=0; + CChipRam[0x30]=0; + CChipRam[0x31]=0; + CChipRam[0x32]=0; + CChipRam[0x27]=0; + c588=0; + c589=0; + c58a=0; + } + + // Check for level completion (all enemies destroyed) + if (CChipRam[0x1c] == 0 && CChipRam[0x1d] == 0 && CChipRam[0x1e] == 0 && CChipRam[0x1f] == 0 && CChipRam[0x20] == 0) + { + // Special handling for end of level 6 + if (CChipRam[0x1b]==0x6) + { + // Don't signal end of level until final boss is destroyed + if (CChipRam[0x27]==0x1) + CChipRam[0x32]=1; + } + else + { + // Signal end of level + CChipRam[0x32]=1; + } + } + + if (CChipRam[0xe] == 1) + { + CChipRam[0xe]=0xfd; + CChipRam[0x61]=0x04; + } + + // Access level data command (address 0xf5 goes from 1 -> 0) + if (CChipRam[0x7a]==0 && CChipLast_7a!=0 && CurrentCmd!=0xf5) + { + // Simulate time for command to execute (exact timing unknown, this is close) + CurrentCmd=0xf5; + bprintf(PRINT_NORMAL, _T("Accessing Level Data Command\n")); + AccessLevelDataCommand(); +// timer_set(ATTOTIME_IN_CYCLES(80000,0), NULL, 0, opwolf_timer_callback); + } + CChipLast_7a=CChipRam[0x7a]; + + // This seems to some kind of periodic counter - results are expected + // by the 68k when the counter reaches 0xa + if (CChipRam[0x7f]==0xa) + { + CChipRam[0xfe]=0xf7; + CChipRam[0xff]=0x6e; + } + + // These are set every frame + CChipRam[0x64]=0; + CChipRam[0x66]=0; +} + +UINT16 OpwolfCChipStatusRead() +{ + return 0x01; +} + +UINT16 OpwolfCChipDataRead(UINT32 Offset) +{ + return CChipRam[(CurrentBank * 0x400) + Offset]; +} + +void OpwolfCChipStatusWrite() +{ + CChipRam[0x3d] = 1; + CChipRam[0x7a] = 1; + updateDifficulty(0); +} + +void OpwolfCChipBankWrite(UINT16 Data) +{ + CurrentBank = Data & 7; +} + +void OpwolfCChipDataWrite(UINT8 *p68kRom, UINT32 Offset, UINT16 Data ) +{ + CChipRam[(CurrentBank * 0x400) + Offset] = Data & 0xff; + + if (CurrentBank == 0) { + if (Offset == 0x14) + { + UINT16* rom = (UINT16*)p68kRom; + UINT32 CoinTable[2]= { 0, 0}; + UINT8 CoinOffset[2]; + INT32 Slot; + + if ((CChipRegion == OPWOLF_REGION_JAPAN) || (CChipRegion == OPWOLF_REGION_US)) { + CoinTable[0] = 0x03ffce; + CoinTable[1] = 0x03ffce; + } + if ((CChipRegion == OPWOLF_REGION_WORLD) || (CChipRegion == OPWOLF_REGION_OTHER)) { + CoinTable[0] = 0x03ffde; + CoinTable[1] = 0x03ffee; + } + + CoinOffset[0] = 12 - (4 * ((Data & 0x30) >> 4)); + CoinOffset[1] = 12 - (4 * ((Data & 0xc0) >> 6)); + + for (Slot = 0; Slot < 2; Slot++) { + if (CoinTable[Slot]) { + CChipCoinsForCredit[Slot] = rom[(CoinTable[Slot] + CoinOffset[Slot] + 0) / 2] & 0xff; + CChipCreditsForCoin[Slot] = rom[(CoinTable[Slot] + CoinOffset[Slot] + 2) / 2] & 0xff; + } + } + } + + // Dip switch B + if (Offset == 0x15) { + updateDifficulty(0); + } + } +} + +void OpwolfCChipReset() +{ + memset(CChipRam, 0, 0x400 * 8); + + CChipLast_7a = 0; + CChipLast_04 = 0xfc; + CChipLast_05 = 0xff; + CChipCoins[0] = 0; + CChipCoins[1] = 0; + CChipCoinsForCredit[0] = 1; + CChipCreditsForCoin[0] = 1; + CChipCoinsForCredit[1] = 1; + CChipCreditsForCoin[1] = 1; + CurrentBank = 0; + CurrentCmd = 0; + c588 = 0; + c589 = 0; + c58a = 0; + +} + +void OpwolfCChipInit(INT32 Region) +{ + CChipRegion = Region; + + CChipRam = (UINT8*)malloc(0x400 * 8); + memset(CChipRam, 0, 0x400 * 8); + + CChipLast_7a = 0; + CChipLast_04 = 0xfc; + CChipLast_05 = 0xff; + CChipCoins[0] = 0; + CChipCoins[1] = 0; + CChipCoinsForCredit[0] = 1; + CChipCreditsForCoin[0] = 1; + CChipCoinsForCredit[1] = 1; + CChipCreditsForCoin[1] = 1; + + TaitoIC_OpwolfCChipInUse = 1; +} + +void OpwolfCChipExit() +{ + if (CChipRam) { + free(CChipRam); + CChipRam = NULL; + } + + CChipRegion = 0; + + CChipLast_7a = 0; + CChipLast_04 = 0; + CChipLast_05 = 0; + CChipCoins[0] = 0; + CChipCoins[1] = 0; + CChipCoinsForCredit[0] = 0; + CChipCreditsForCoin[0] = 0; + CChipCoinsForCredit[1] = 0; + CChipCreditsForCoin[1] = 0; + CurrentBank = 0; + CurrentCmd = 0; + c588 = 0; + c589 = 0; + c58a = 0; + +} + +void OpwolfCChipScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = CChipRam; + ba.nLen = 0x400 * 8; + ba.szName = "C-Chip Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(CurrentBank); + SCAN_VAR(CurrentCmd); + SCAN_VAR(CChipLast_7a); + SCAN_VAR(CChipLast_04); + SCAN_VAR(CChipLast_05); + SCAN_VAR(CChipCoinsForCredit); + SCAN_VAR(CChipCreditsForCoin); + SCAN_VAR(CChipCoins); + SCAN_VAR(c588); + SCAN_VAR(c589); + SCAN_VAR(c58a); + } +} + +#undef OPWOLF_REGION_JAPAN +#undef OPWOLF_REGION_US +#undef OPWOLF_REGION_WORLD +#undef OPWOLF_REGION_OTHER + + +/************************************************************************* + + Bonze Adventure C-Chip + ====================== + + Based on RAINE. Improvements with a lot of help from Ruben Panossian. + Additional thanks to Robert Gallagher and stephh. + + Verification on real hardware by Bryan McPhail, Feb 2006: + The restart positions on real hardware are affected by the level + variable, as well as scroll & player position. The old implementation + did not account for this and so overlapping map positions between + levels reported the wrong data. + + Restart data is confirmed correct & complete. Previously many + restart points were missed. + + Mapping of restart positions now accurate to the real hardware - + previously these values were approximated by hand (and many + missing). + + Taken from MAME 0.136 Jan 11, 2010 + +*************************************************************************/ + + +static INT32 current_round = 0; +static INT32 current_bank = 0; +static INT32 coin_lockout = 0; + +static UINT8 cval[26]; +static UINT8 cc_port; +static UINT8 restart_status; + +struct cchip_mapping +{ + UINT16 xmin; + UINT16 xmax; + UINT16 ymin; + UINT16 ymax; + UINT16 sx; + UINT16 sy; + UINT16 px; + UINT16 py; +}; + +static const UINT16 CLEV[][13] = +{ +/* map start player start player y-range player x-range map y-range map x-range time */ + { 0x0000, 0x0018, 0x0020, 0x0030, 0x0028, 0x00D0, 0x0050, 0x0090, 0x0000, 0x0118, 0x0000, 0x0C90, 0x3800 }, + { 0x0000, 0x0100, 0x0048, 0x0028, 0x0028, 0x0090, 0x0070, 0x00B0, 0x0000, 0x02C0, 0x0000, 0x0CA0, 0x3000 }, + { 0x0000, 0x0518, 0x0068, 0x00B8, 0x0028, 0x00D0, 0x0068, 0x00B0, 0x02F8, 0x0518, 0x0000, 0x0EF8, 0x3000 }, + { 0x0978, 0x0608, 0x00C8, 0x00B0, 0x0028, 0x00D0, 0x0098, 0x00C8, 0x0608, 0x06E8, 0x0000, 0x0A48, 0x2000 }, + { 0x0410, 0x0708, 0x0070, 0x0030, 0x0028, 0x00D0, 0x0060, 0x0090, 0x0708, 0x0708, 0x0410, 0x1070, 0x3800 }, + { 0x1288, 0x0808, 0x0099, 0x00CE, 0x0028, 0x00D0, 0x0060, 0x00C0, 0x0000, 0x0808, 0x1288, 0x1770, 0x3000 }, + { 0x11B0, 0x0908, 0x0118, 0x0040, 0x0028, 0x00D0, 0x00B0, 0x00C0, 0x0900, 0x0910, 0x0050, 0x11B0, 0x3800 }, + { 0x0000, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x0000, 0x0398, 0x1000 }, + { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0x8800 }, + { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff }, + { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff }, +}; + +static const struct cchip_mapping level00[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x0200, 0x0000, 0x0100, 0x0000, 0x0018, 0x0020, 0x00a8 }, + { 0x0200, 0x0380, 0x0000, 0x0100, 0x01e0, 0x0018, 0x0070, 0x0098 }, + { 0x0380, 0x0620, 0x0000, 0x0100, 0x04a0, 0x0018, 0x0070, 0x0090 }, + { 0x0620, 0x08f0, 0x0000, 0x0100, 0x06b8, 0x0018, 0x0078, 0x0078 }, + { 0x08f0, 0x0a20, 0x0000, 0x0100, 0x08c8, 0x0018, 0x0070, 0x0028 }, + { 0x0a20, 0x0c80, 0x0000, 0x0100, 0x0a68, 0x0018, 0x0070, 0x0058 }, + { 0x0c80, 0x0e00, 0x0000, 0x0100, 0x0c40, 0x0018, 0x0070, 0x0040 }, + + { 0x0380, 0x07c0, 0x0100, 0x0200, 0x0038, 0x0418, 0x0070, 0x00a8 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level01[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x0120, 0x0100, 0x0200, 0x0000, 0x0208, 0x0040, 0x0070 }, + + { 0x0000, 0x0120, 0x0200, 0x0300, 0x0000, 0x0208, 0x0040, 0x0070 }, + { 0x0120, 0x0460, 0x0200, 0x0300, 0x0080, 0x0218, 0x00b0, 0x0080 }, + { 0x0460, 0x0690, 0x0200, 0x0278, 0x0450, 0x01f8, 0x0090, 0x0030 }, + { 0x0460, 0x0690, 0x0278, 0x0300, 0x0450, 0x0218, 0x00a0, 0x00a0 }, + { 0x0690, 0x07d0, 0x0200, 0x0278, 0x0618, 0x01f8, 0x00a0, 0x0040 }, + { 0x0690, 0x07d0, 0x0278, 0x0300, 0x0628, 0x0218, 0x00a8, 0x00b0 }, + { 0x07d0, 0x08b0, 0x0200, 0x0300, 0x07a8, 0x0218, 0x0090, 0x0060 }, + { 0x08b0, 0x09d0, 0x0200, 0x0300, 0x0840, 0x0218, 0x0088, 0x0060 }, + { 0x09d0, 0x0b00, 0x0200, 0x0300, 0x0958, 0x0218, 0x00a0, 0x0070 }, + { 0x0b00, 0x0c90, 0x0200, 0x0300, 0x0a98, 0x0218, 0x0088, 0x0050 }, + { 0x0c90, 0x0e00, 0x0200, 0x0300, 0x0c20, 0x0200, 0x00a0, 0x0028 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level02[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x01c0, 0x04f4, 0x05f8, 0x0000, 0x0518, 0x0068, 0x00b0 }, + { 0x01c0, 0x03c0, 0x04f4, 0x05f8, 0x00d0, 0x0518, 0x0078, 0x0060 }, + { 0x03c0, 0x06e0, 0x04f4, 0x05f8, 0x02f0, 0x0518, 0x0078, 0x0048 }, + { 0x06e0, 0x0840, 0x04f4, 0x05f8, 0x0670, 0x0518, 0x0078, 0x0048 }, + { 0x0840, 0x0a10, 0x04f4, 0x05f8, 0x07d8, 0x0518, 0x0070, 0x0060 }, + { 0x0a10, 0x0b80, 0x04f4, 0x05f8, 0x09e8, 0x0500, 0x0080, 0x0080 }, + { 0x0b80, 0x1090, 0x04f4, 0x05f8, 0x0b20, 0x0418, 0x0070, 0x0080 }, + + { 0x0230, 0x03a0, 0x040c, 0x04f4, 0x02e8, 0x04b0, 0x0080, 0x0090 }, + { 0x03a0, 0x03b0, 0x040c, 0x04f4, 0x0278, 0x0318, 0x0078, 0x00a8 }, + { 0x0520, 0x08e0, 0x040c, 0x04f4, 0x0608, 0x0318, 0x0080, 0x0058 }, + { 0x08e0, 0x0a00, 0x040c, 0x04f4, 0x0878, 0x0318, 0x0078, 0x0098 }, + + { 0x0230, 0x03b0, 0x02f8, 0x040c, 0x0278, 0x0318, 0x0078, 0x00a8 }, + { 0x03b0, 0x0520, 0x02f8, 0x040c, 0x0390, 0x0318, 0x0070, 0x00b8 }, + { 0x0520, 0x08e0, 0x02f8, 0x040c, 0x0608, 0x0318, 0x0080, 0x0058 }, + { 0x08e0, 0x0a00, 0x02f8, 0x040c, 0x0878, 0x0318, 0x0078, 0x0098 } +}; + +static const struct cchip_mapping level03[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x0280, 0x0618, 0x06f8, 0x00d8, 0x0608, 0x00b8, 0x00a0 }, + { 0x0280, 0x0380, 0x0618, 0x06f8, 0x02b0, 0x0608, 0x00b8, 0x0090 }, + { 0x0380, 0x0620, 0x0618, 0x06f8, 0x02c8, 0x0608, 0x00c0, 0x0090 }, + { 0x0620, 0x0760, 0x0618, 0x06f8, 0x0630, 0x0608, 0x00c0, 0x0028 }, + { 0x0760, 0x0910, 0x0618, 0x06f8, 0x07e8, 0x0608, 0x00b8, 0x0078 }, + { 0x0910, 0x0a30, 0x0618, 0x06f8, 0x0930, 0x0608, 0x00b8, 0x0080 }, + { 0x0a30, 0x0b60, 0x0618, 0x06f8, 0x0a48, 0x0608, 0x00c0, 0x0068 }, + + { 0x0090, 0x01d0, 0x06f8, 0x07f8, 0x0020, 0x0610, 0x00b8, 0x00a8 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level04[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0390, 0x06a0, 0x0704, 0x0804, 0x0560, 0x0708, 0x0068, 0x0090 }, + { 0x06a0, 0x0850, 0x0704, 0x0804, 0x0600, 0x0708, 0x0080, 0x0070 }, + { 0x0850, 0x09e0, 0x0704, 0x0804, 0x0860, 0x0708, 0x0060, 0x0090 }, + { 0x09e0, 0x0c00, 0x0704, 0x0804, 0x09c0, 0x0708, 0x0068, 0x0080 }, + { 0x0c00, 0x0da0, 0x0704, 0x0804, 0x0c58, 0x0708, 0x0068, 0x0070 }, + { 0x0da0, 0x0f80, 0x0704, 0x0804, 0x0d80, 0x0708, 0x0070, 0x00b0 }, + { 0x0f80, 0x1080, 0x0704, 0x0804, 0x0ea8, 0x0708, 0x0070, 0x00b0 }, + { 0x1080, 0x1230, 0x0704, 0x0804, 0x0fc0, 0x0708, 0x0080, 0x0030 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level05[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x1280, 0x1370, 0x800, 0x900, 0x1288, 0x0808, 0x0099, 0x00ce }, + { 0x1370, 0x14e0, 0x800, 0x900, 0x12f0, 0x0808, 0x0078, 0x0028 }, + { 0x14e0, 0x1660, 0x800, 0x900, 0x1488, 0x0808, 0x0080, 0x0070 }, + { 0x1660, 0x18f0, 0x800, 0x900, 0x1600, 0x0808, 0x0080, 0x0090 }, + + { 0x1480, 0x1640, 0x6f8, 0x800, 0x1508, 0x0708, 0x0080, 0x0090 }, + { 0x1640, 0x1760, 0x6f8, 0x800, 0x16e8, 0x06f0, 0x0080, 0x0058 }, + { 0x1760, 0x1900, 0x6f8, 0x800, 0x1770, 0x0728, 0x0080, 0x0080 }, + + { 0x14e0, 0x1570, 0x6a0, 0x6f8, 0x1508, 0x05e8, 0x0040, 0x0088 }, + { 0x1570, 0x1680, 0x6a0, 0x6f8, 0x1568, 0x0608, 0x0080, 0x0090 }, + { 0x1680, 0x1770, 0x6a0, 0x6f8, 0x1640, 0x05e8, 0x0088, 0x0088 }, + { 0x1770, 0x18d0, 0x6a0, 0x6f8, 0x1770, 0x0650, 0x00d8, 0x0070 }, + + { 0x14e0, 0x1570, 0x664, 0x6a0, 0x1508, 0x05e8, 0x0040, 0x0088 }, + { 0x1570, 0x1680, 0x664, 0x6a0, 0x1578, 0x05d0, 0x0098, 0x0060 }, + { 0x1680, 0x1770, 0x664, 0x6a0, 0x1640, 0x05e8, 0x0088, 0x0088 }, + { 0x1770, 0x18d0, 0x664, 0x6a0, 0x1770, 0x0650, 0x00d8, 0x0070 }, + + { 0x14e0, 0x1570, 0x624, 0x664, 0x1508, 0x05e8, 0x0040, 0x0088 }, + { 0x1570, 0x1680, 0x624, 0x664, 0x1578, 0x05d0, 0x0098, 0x0060 }, + { 0x1680, 0x1770, 0x624, 0x664, 0x1640, 0x05e8, 0x0088, 0x0088 }, + { 0x1770, 0x18d0, 0x624, 0x664, 0x1770, 0x0588, 0x0090, 0x0088 }, + + { 0x14e0, 0x1570, 0x5d4, 0x624, 0x1508, 0x05e8, 0x0040, 0x0088 }, + { 0x1570, 0x1680, 0x5d4, 0x624, 0x1578, 0x05d0, 0x0098, 0x0060 }, + { 0x1680, 0x16a0, 0x5d4, 0x624, 0x1630, 0x0528, 0x0088, 0x0088 }, + { 0x16a0, 0x1770, 0x5d4, 0x624, 0x1658, 0x0528, 0x0088, 0x0088 }, + { 0x1770, 0x18d0, 0x5d4, 0x624, 0x1770, 0x0588, 0x0090, 0x0088 }, + + { 0x14e0, 0x15d0, 0x5a4, 0x5d4, 0x1508, 0x0580, 0x0040, 0x0080 }, + { 0x15d0, 0x15f0, 0x5a4, 0x5d4, 0x1508, 0x04f8, 0x0080, 0x0060 }, + { 0x15f0, 0x1630, 0x5a4, 0x5d4, 0x1580, 0x04f8, 0x0068, 0x0080 }, + { 0x1630, 0x16a0, 0x5a4, 0x5d4, 0x1630, 0x0530, 0x0088, 0x0080 }, + { 0x16a0, 0x17b0, 0x5a4, 0x5d4, 0x1658, 0x0528, 0x0088, 0x0088 }, + { 0x17b0, 0x18c0, 0x5a4, 0x5d4, 0x1770, 0x0508, 0x0098, 0x0088 }, + + { 0x14e0, 0x15f0, 0x4f8, 0x5a4, 0x1508, 0x04f8, 0x0080, 0x0060 }, + { 0x15f0, 0x1670, 0x4f8, 0x5a4, 0x15c8, 0x0548, 0x00a8, 0x0070 }, + { 0x1670, 0x1750, 0x4f8, 0x5a4, 0x1680, 0x0528, 0x00a8, 0x0070 }, + { 0x1750, 0x18d0, 0x4f8, 0x5a4, 0x1770, 0x04a0, 0x00a8, 0x0078 }, + + { 0x14e0, 0x1630, 0x478, 0x4f8, 0x1508, 0x04f8, 0x0080, 0x0060 }, + { 0x1630, 0x16b0, 0x478, 0x4f8, 0x15d0, 0x0440, 0x00b8, 0x0078 }, + { 0x16b0, 0x1760, 0x478, 0x4f8, 0x1660, 0x0460, 0x0080, 0x0060 }, + { 0x1760, 0x17f0, 0x478, 0x4f8, 0x1738, 0x0420, 0x0090, 0x0070 }, + { 0x17f0, 0x18d0, 0x478, 0x4f8, 0x1770, 0x0450, 0x00d8, 0x0060 }, + + { 0x14e0, 0x16d0, 0x3f8, 0x478, 0x1500, 0x03e8, 0x0090, 0x0058 }, + { 0x16d0, 0x17f0, 0x3f8, 0x478, 0x16e0, 0x0398, 0x0068, 0x0068 }, + { 0x17f0, 0x18d0, 0x3f8, 0x478, 0x1770, 0x0450, 0x00d8, 0x0060 }, + + { 0x14e0, 0x1610, 0x35c, 0x3f8, 0x1518, 0x0368, 0x0090, 0x0058 }, + { 0x1610, 0x16b0, 0x35c, 0x3f8, 0x15b0, 0x0340, 0x0098, 0x0058 }, + { 0x16b0, 0x17e0, 0x35c, 0x3f8, 0x1728, 0x0320, 0x0068, 0x0068 }, + { 0x17e0, 0x18d0, 0x35c, 0x3f8, 0x1770, 0x0330, 0x00c0, 0x0080 }, + + { 0x14e0, 0x1650, 0x2f8, 0x35c, 0x1518, 0x0368, 0x0090, 0x0058 }, + { 0x1650, 0x17d0, 0x2f8, 0x35c, 0x1630, 0x02b0, 0x0088, 0x0060 }, + { 0x17d0, 0x18d0, 0x2f8, 0x35c, 0x1740, 0x02a8, 0x0090, 0x0058 }, + + { 0x14e0, 0x1650, 0x268, 0x2f8, 0x15a8, 0x0268, 0x0080, 0x0058 }, + { 0x1650, 0x17b0, 0x268, 0x2f8, 0x1650, 0x0250, 0x0080, 0x0058 }, + { 0x17b0, 0x18d0, 0x268, 0x2f8, 0x1740, 0x02a8, 0x0090, 0x0058 }, + + { 0x14e0, 0x15f0, 0x1d8, 0x268, 0x1508, 0x0208, 0x0078, 0x0060 }, + { 0x15f0, 0x17b0, 0x1d8, 0x268, 0x16c8, 0x0178, 0x0080, 0x0060 }, + { 0x17b0, 0x18d0, 0x1d8, 0x268, 0x1740, 0x02a8, 0x0090, 0x0058 }, + + { 0x14e0, 0x18d0, 0x158, 0x1d8, 0x1610, 0x0110, 0x0078, 0x0068 }, + { 0x14e0, 0x18d0, 0x158, 0x1d8, 0x1610, 0x0110, 0x0078, 0x0068 }, + + { 0x14d0, 0x18d0, 0x15c, 0x19c, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x14d0, 0x15b0, 0x19c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x15b0, 0x1670, 0x19c, 0x1bc, 0x1580, 0x0128, 0x0070, 0x0080 }, + { 0x1670, 0x18d0, 0x19c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x14d0, 0x14f0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x14f0, 0x15f0, 0x1bc, 0x1dc, 0x1508, 0x0208, 0x0078, 0x0060 }, + { 0x15f0, 0x1670, 0x1bc, 0x1dc, 0x1580, 0x0128, 0x0070, 0x0080 }, + { 0x1670, 0x18d0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 }, + + { 0x14d0, 0x14f0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x14f0, 0x1670, 0x18c, 0x1bc, 0x1508, 0x0208, 0x0078, 0x0060 }, + + { 0x14d0, 0x15b0, 0x18c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 }, + { 0x15b0, 0x1670, 0x18c, 0x1bc, 0x1580, 0x0128, 0x0070, 0x0080 }, + { 0x1670, 0x18d0, 0x18c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 }, + + { 0x14d0, 0x18d0, 0x15c, 0x18c, 0x1618, 0x0110, 0x0078, 0x0068 }, + + { 0x14e0, 0x1840, 0x098, 0x15c, 0x16b0, 0x00b0, 0x0088, 0x0060 }, + { 0x1840, 0x18d0, 0x088, 0x15c, 0x1770, 0x0118, 0x00c0, 0x0060 }, + + { 0x1250, 0x15a0, 0x000, 0x108, 0x1500, 0x0000, 0x0080, 0x0048 }, + { 0x15a0, 0x16f0, 0x000, 0x098, 0x1698, 0x0000, 0x0080, 0x0050 }, + { 0x16f0, 0x18d0, 0x000, 0x088, 0x1770, 0x0000, 0x00b8, 0x0060 }, + + { 0x1250, 0x14e0, 0x000, 0x10c, 0x1500, 0x0000, 0x0080, 0x0048 }, + { 0x14e0, 0x15a0, 0x000, 0x09c, 0x1500, 0x0000, 0x0080, 0x0048 }, + { 0x15a0, 0x16f0, 0x000, 0x09c, 0x1698, 0x0000, 0x0080, 0x0050 }, + { 0x16f0, 0x1830, 0x000, 0x09c, 0x1770, 0x0000, 0x00b8, 0x0060 }, + { 0x1830, 0x18d0, 0x000, 0x09c, 0x1770, 0x0118, 0x00c0, 0x0060 }, + + { 0x14e0, 0x1830, 0x09c, 0x158, 0x16b0, 0x00b0, 0x0088, 0x0060 }, + { 0x1830, 0x18d0, 0x09c, 0x158, 0x1770, 0x0118, 0x00c0, 0x0060 }, + + //-------------------------- + { 0x14e0, 0x1650, 0x29c, 0x2f0, 0x15a8, 0x0268, 0x0080, 0x0058 }, + { 0x14e0, 0x1610, 0x2f0, 0x3fc, 0x1518, 0x0368, 0x0090, 0x0058 }, + { 0x14e0, 0x1630, 0x3fc, 0x46c, 0x1500, 0x03e8, 0x0090, 0x0058 }, + { 0x14e0, 0x1630, 0x46c, 0x51c, 0x1508, 0x04f8, 0x0080, 0x0060 }, + { 0x14e0, 0x15f0, 0x51c, 0x59c, 0x1508, 0x04f8, 0x0080, 0x0060 }, + { 0x14e0, 0x15f0, 0x59c, 0x5d8, 0x1508, 0x0580, 0x0040, 0x0080 }, + { 0x14e0, 0x1570, 0x5d8, 0x700, 0x1508, 0x05e8, 0x0040, 0x0088 }, + { 0x1480, 0x1640, 0x700, 0x808, 0x1508, 0x0708, 0x0080, 0x0090 }, + + { 0x0000, 0x18d0, 0x000, 0x900, 0x1288, 0x0808, 0x0099, 0x00ce }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level06[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x01a0, 0x0904, 0x0a04, 0x00d0, 0x0908, 0x00b0, 0x0090 }, + { 0x01a0, 0x04e0, 0x0904, 0x0a04, 0x03d0, 0x0908, 0x00b0, 0x0038 }, + { 0x04e0, 0x0740, 0x0904, 0x0a04, 0x0660, 0x0908, 0x00b0, 0x0098 }, + { 0x0740, 0x0950, 0x0904, 0x0a04, 0x07e8, 0x0908, 0x00b8, 0x00b8 }, + { 0x0950, 0x0a80, 0x0904, 0x0a04, 0x08f8, 0x0908, 0x00b0, 0x0080 }, + { 0x0a80, 0x0da0, 0x0904, 0x0a04, 0x0cd0, 0x0908, 0x00b8, 0x00b0 }, + { 0x0da0, 0x0f40, 0x0904, 0x0a04, 0x0e08, 0x0908, 0x00b8, 0x0070 }, + { 0x0f40, 0x10c0, 0x0904, 0x0a04, 0x0fe8, 0x0908, 0x00b8, 0x0098 }, + { 0x10c0, 0x1370, 0x0904, 0x0a04, 0x1140, 0x0908, 0x00b8, 0x0068 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level07[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0x0570, 0x0804, 0x0904, 0x0000, 0x0808, 0x0028, 0x00b8 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping level08[] = +{ + /* X1 X2 Y1 Y2 => SX SY PX PY */ + { 0x0000, 0xf000, 0x0000, 0xf000, 0x06f8, 0x0808, 0x0028, 0x00b8 }, + { 0xff, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const struct cchip_mapping *const levelData[]= +{ + level00, + level01, + level02, + level03, + level04, + level05, + level06, + level07, + level08 +}; + +static void WriteLevelData(void) +{ + for (INT32 i = 0; i < 13; i++) + { + UINT16 v = CLEV[current_round][i]; + + cval[2 * i + 0] = v & 0xff; + cval[2 * i + 1] = v >> 8; + } +} + +static void WriteRestartPos(INT32 level) +{ + /* + Cval0/1 = scroll x position + Cval4/5 = player x screen position + Cval2/3 = scroll y position + Cval6/7 = player y screen position + + These are combined to find the absolute player position + on the map, which is then given to the C-Chip in order + for the restart position to be returned. + */ + + INT32 x = cval[0] + 256 * cval[1] + cval[4] + 256 * cval[5]; + INT32 y = cval[2] + 256 * cval[3] + cval[6] + 256 * cval[7]; + + const struct cchip_mapping* thisLevel=levelData[level]; + + while (thisLevel->xmin!=0xff) + { + if (x >= thisLevel->xmin && x < thisLevel->xmax && + y >= thisLevel->ymin && y < thisLevel->ymax) + { + cval[0] = thisLevel->sx & 0xff; + cval[1] = thisLevel->sx >> 8; + cval[2] = thisLevel->sy & 0xff; + cval[3] = thisLevel->sy >> 8; + cval[4] = thisLevel->px & 0xff; + cval[5] = thisLevel->px >> 8; + cval[6] = thisLevel->py & 0xff; + cval[7] = thisLevel->py >> 8; + + // Restart position found ok + restart_status=0; + + return; + } + + thisLevel++; + } + + // No restart position found for this position (cval0-7 confirmed unchanged in this case) + restart_status=0xff; +} + +void BonzeWriteCChipBank(INT32 data) +{ + current_bank = data & 7; +} + +void BonzeWriteCChipRam(INT32 offset, INT32 data) +{ + offset = (offset & 0xfff) / 2; + + if (current_bank == 0) + { + if (offset == 0x08) + { + cc_port = data; + coin_lockout = ~data >> 6; // data & 0xc0 + // coin_counter = data & 0x30; + } + + if (offset == 0x0e && data != 0x00) + { + WriteRestartPos(current_round); + } + + if (offset == 0x0f && data != 0x00) + { + WriteLevelData(); + } + + if (offset == 0x10) + { + current_round = data; + } + + if (offset >= 0x11 && offset <= 0x2a) + { + cval[offset - 0x11] = data; + } + } +} + +UINT16 BonzeReadCChipRam(INT32 offset) +{ + offset = (offset & 0xfff) / 2; + + if (current_bank == 0) + { + switch (offset) + { + case 0x03: return TaitoInput[0]; /* STARTn + SERVICE1 */ + case 0x04: return TaitoInput[1] & coin_lockout; /* COINn */ + case 0x05: return TaitoInput[2]; /* Player controls + TILT */ + case 0x06: return TaitoInput[3]; /* Player controls (cocktail) */ + case 0x08: return cc_port; + } + + if (offset == 0x0e) + { + return restart_status; /* 0xff signals error, 0 signals ok */ + } + + if (offset >= 0x11 && offset <= 0x2a) + { + return cval[offset - 0x11]; + } + } + + return 0; +} + +void BonzeCChipReset() +{ + current_round = 0; + current_bank = 0; + coin_lockout = 0; + + memset (cval, 0, 26); + cc_port = 0; + restart_status = 0; +} + +void BonzeCChipScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = cval; + ba.nLen = 26; + ba.szName = "C-Chip Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(current_round); + SCAN_VAR(current_bank); + SCAN_VAR(coin_lockout); + SCAN_VAR(cc_port); + SCAN_VAR(restart_status); + } +} + +/************************************************************************* + + Volfied C-Chip Protection + ========================= + + The C-Chip (Taito TC0030CMD) is an unidentified mask programmed + microcontroller of some sort with 64 pins. It probably has + about 2k of ROM and 8k of RAM. + + Cheat: + volfied:0:100191:00:001:Complete level with 99.9% Now! + volfied:0:100192:99:501:Complete level with 99.9% Now! (2/3) + volfied:0:100193:09:501:Complete level with 99.9% Now! (3/3) + +*************************************************************************/ + +UINT8 volfied_current_bank; +UINT8 volfied_current_flag; +UINT8 volfied_cc_port; +UINT8 volfied_current_cmd; +UINT8 * volfied_cchip_ram; + +static const UINT16 palette_data_01[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000, + 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000, + 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000, + 0x0000, 0xd62a, 0x1002, 0xce01, 0x5a3b, 0xde7b, 0x4a31, 0x0000, + 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0038, 0x0e38, 0x0000 +}; + +static const UINT16 palette_data_02[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x4008, 0x0029, 0xc641, 0x4c52, 0x5473, 0xde7b, 0x1863, + 0x524a, 0xce39, 0x0821, 0x9c01, 0x1200, 0x8001, 0xc002, 0xce39, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003, + 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600, + 0x0000, 0x4208, 0x0c39, 0xd061, 0x547a, 0x1472, 0xde7b, 0xde7b, + 0x187b, 0x947a, 0x0821, 0x9e79, 0x1040, 0x8079, 0xc07a, 0x0000 +}; + +static const UINT16 palette_data_03[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821, + 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003, + 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600, + 0x0000, 0xc001, 0x4002, 0x8002, 0xc002, 0xc002, 0x0001, 0xc001, + 0x9201, 0xc002, 0xc003, 0x0003, 0x8002, 0x4001, 0xc002, 0x4003 +}; + +static const UINT16 palette_data_04[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000, + 0x1e00, 0x1000, 0x8c21, 0xce29, 0x0039, 0x0038, 0x0e38, 0x0038, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x1002, 0xce01, 0x8c01, 0x5202, 0xd602, 0x4a01, 0x0000, + 0x1e00, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const UINT16 palette_data_05[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1200, 0x1600, 0x1a00, 0x9e01, 0x8021, 0xc029, 0x0032, + 0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x5202, 0xd602, 0x5a03, 0xde03, 0x8021, 0xc029, 0x0032, + 0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02 +}; + +static const UINT16 palette_data_06[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x9e52, 0x9028, 0x9428, 0x9828, 0x9e28, 0x4208, 0xde7b, + 0xde03, 0x9c02, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x5e31, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0263, 0x9e52, 0x8058, 0x0879, 0x8c79, 0x107a, 0x4208, 0xde7b, + 0xde01, 0x1e01, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x527a +}; + +static const UINT16 palette_data_07[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821, + 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003, + 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600, + 0x0000, 0x8001, 0x0002, 0x8002, 0x0003, 0x8003, 0x4208, 0x0821, + 0x8c31, 0x1042, 0x9c73, 0x1e00, 0x5c02, 0x0c00, 0x1860, 0x1e78 +}; + +static const UINT16 palette_data_08[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000, + 0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x5202, 0x1002, 0xce19, 0x9432, 0x1843, 0x8c11, 0x0000, + 0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000 +}; + +static const UINT16 palette_data_09[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1048, 0x1250, 0x1458, 0x1660, 0xd418, 0x9e02, 0xc203, + 0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e78, 0x166b, 0x0c38, 0x1868, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x1600, 0x1a21, 0x5c29, 0xde39, 0xd418, 0x9e02, 0xc203, + 0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e42, 0x186b, 0x9210, 0x9e31 +}; + +static const UINT16 palette_data_0a[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b, + 0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x0000, 0x0038, 0x4a29, 0x5401, 0x9c02, 0x9218, 0xde7b, + 0x0003, 0xc003, 0x5e02, 0xde01, 0x5201, 0xd200, 0x0668, 0x4672 +}; + +static const UINT16 palette_data_0b[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0050, 0x8001, 0xc001, 0x0002, 0xc002, 0xd043, 0x9c73, 0x524a, + 0xce39, 0x8c31, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x8c01, 0xce01, 0x1002, 0xd62a, 0xde4b, 0x9c73, 0x5202, + 0xce01, 0x8c01, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000 +}; + +static const UINT16 palette_data_0c[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0x9e52, + 0xc001, 0xc003, 0x1e00, 0x1400, 0x0c00, 0x4a01, 0x0668, 0x4672, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b, + 0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672 +}; + +static const UINT16 palette_data_0d[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863, + 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863, + 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42, + 0x0000, 0x4208, 0x5029, 0x9431, 0xd839, 0x5a4a, 0x9e52, 0x5862, + 0xde4b, 0x8e39, 0x0821, 0x1600, 0x1000, 0xd201, 0x1e00, 0x0a42 +}; + +static const UINT16 palette_data_0e[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0e01, 0x5001, 0x9201, 0xd401, 0x1602, 0x1200, 0x1600, + 0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x9a02, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003, + 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600, + 0x0000, 0x8a21, 0x0a32, 0x4c3a, 0x8e4a, 0x504b, 0xd203, 0xc003, + 0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x545b +}; + +static const UINT16 palette_data_0f[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x0000, 0x0821, + 0x9c31, 0x1042, 0x9c73, 0x1e02, 0x1a02, 0x0c00, 0x4002, 0xc001, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a, + 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003, + 0x0000, 0xce00, 0x5201, 0xd601, 0x5a02, 0xde02, 0x0000, 0x0821, + 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x9e01, 0x0e00 +}; + +static const UINT16 palette_data_10[0x50] = +{ + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0601, 0x8a09, 0x0e1a, 0x922a, 0x163b, 0xde7b, 0xd65a, + 0xce39, 0x0821, 0x0000, 0x0c00, 0x5208, 0x1a02, 0x9e03, 0xce39, + 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b, + 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1400, 0x8002, 0x0068, 0x0000, 0x5e01, 0x5e02, 0x1e03, + 0xde03, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, + 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863, + 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42 +}; + +static const UINT16 palette_data_11[0x50] = +{ + 0x0000, 0x4a29, 0x8c31, 0xce39, 0x1042, 0x524a, 0x9452, 0xd65a, + 0x1863, 0x0000, 0xde39, 0xde7b, 0xc001, 0x8002, 0x1800, 0x1e00, + 0x0000, 0xde7b, 0x1e00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, + 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, + 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, + 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, + 0xde03, 0x0e00, 0x9e4a, 0x0000, 0x1042, 0xde7b, 0x9452, 0x4a29, + 0xce39, 0x1c02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const UINT16 *const palette_data_lookup[] = +{ + 0, + palette_data_01, + palette_data_02, + palette_data_03, + palette_data_04, + palette_data_05, + palette_data_06, + palette_data_07, + palette_data_08, + palette_data_09, + palette_data_0a, + palette_data_0b, + palette_data_0c, + palette_data_0d, + palette_data_0e, + palette_data_0f, + palette_data_10, + palette_data_11 +}; + + +static void volfied_timer_callback() +{ + // Palette commands - palette data written to bank 0: $10 - $af + if (volfied_current_cmd >= 0x1 && volfied_current_cmd < 0x12) + { + const UINT16* palette_data = palette_data_lookup[volfied_current_cmd]; + INT32 i; + for (i = 0; i < 0x50; i++) + { + volfied_cchip_ram[0x10 + i * 2 + 0] = palette_data[i] >> 8; + volfied_cchip_ram[0x10 + i * 2 + 1] = palette_data[i] & 0xff; + } + } + + // Unknown command - result written to bank 0: $23 + if (volfied_current_cmd >= 0x81 && volfied_current_cmd < 0x92) + { + switch (volfied_current_cmd) + { + case 0x81: volfied_cchip_ram[0x23] = 0xf; break; + case 0x82: volfied_cchip_ram[0x23] = 0x1; break; + case 0x83: volfied_cchip_ram[0x23] = 0x6; break; + case 0x84: volfied_cchip_ram[0x23] = 0xf; break; + case 0x85: volfied_cchip_ram[0x23] = 0x9; break; + case 0x86: volfied_cchip_ram[0x23] = 0x6; break; + case 0x87: volfied_cchip_ram[0x23] = 0x6; break; + case 0x88: volfied_cchip_ram[0x23] = 0xf; break; + case 0x89: volfied_cchip_ram[0x23] = 0x8; break; + case 0x8a: volfied_cchip_ram[0x23] = 0x1; break; + case 0x8b: volfied_cchip_ram[0x23] = 0xa; break; + case 0x8c: volfied_cchip_ram[0x23] = 0x1; break; + case 0x8d: volfied_cchip_ram[0x23] = 0x1; break; + case 0x8e: volfied_cchip_ram[0x23] = 0x8; break; + case 0x8f: volfied_cchip_ram[0x23] = 0x6; break; + case 0x90: volfied_cchip_ram[0x23] = 0xa; break; + case 0x91: volfied_cchip_ram[0x23] = 0x0; break; + } + } + + volfied_current_cmd = 0; +} + +/************************************* + * + * Writes to C-Chip - Important Bits + * + *************************************/ + +void VolfiedCChipBankWrite(UINT16 data) +{ + volfied_current_bank = data & 7; +} + +void VolfiedCChipRamWrite(INT32 offset, UINT8 data) +{ + volfied_cchip_ram[(volfied_current_bank * 0x400) + offset] = data; + +// if (offset != 0x8) +// logerror("%08x: volfied c write %04x %04x\n", cpu_get_pc(space->cpu), offset, data); + + if (volfied_current_bank == 0) + { + if (offset == 0x008) + { + volfied_cc_port = data; + +// coin_lockout_w(space->machine, 1, data & 0x80); +// coin_lockout_w(space->machine, 0, data & 0x40); +// coin_counter_w(space->machine, 1, data & 0x20); +// coin_counter_w(space->machine, 0, data & 0x10); + } + + if (offset == 0x3fe) + { + /******************* + (This table stored in ROM at $146a8) + (Level number stored at $100198.b, from $100118.b, from $100098.b) + (Level number at $b34 stored to $100098.b) + + round 01 => data $0A + round 02 => data $01 + round 03 => data $03 + round 04 => data $08 + round 05 => data $05 + round 06 => data $04 + round 07 => data $0B + round 08 => data $09 + round 09 => data $07 + round 10 => data $06 + round 11 => data $0E + round 12 => data $0D + round 13 => data $02 + round 14 => data $0C + round 15 => data $0F + round 16 => data $10 + final => data $11 + + ********************/ + + volfied_current_cmd = data; + + // Palette request cmd - verified to take around 122242 68000 cycles to complete + if (volfied_current_cmd >= 0x1 && volfied_current_cmd < 0x12) + { + //space->machine->scheduler().timer_set(downcast(space->cpu)->cycles_to_attotime(122242), FUNC(volfied_timer_callback)); +// nTaitoCyclesDone[0] += SekRun(122242); + volfied_timer_callback(); + } + // Unknown cmd - verified to take around 105500 68000 cycles to complete + else if (volfied_current_cmd >= 0x81 && volfied_current_cmd < 0x92) + { + //space->machine->scheduler().timer_set(downcast(space->cpu)->cycles_to_attotime(105500), FUNC(volfied_timer_callback)); +// nTaitoCyclesDone[0] += SekRun(105500); + volfied_timer_callback(); + } + else + { +// logerror("unknown cchip cmd %02x\n", data); + volfied_current_cmd = 0; + } + } + + // Some kind of timer command + if (offset == 0x3ff) + { + volfied_current_flag = data; + } + } +} + + +/************************************* + * + * Reads from C-Chip + * + *************************************/ + +UINT8 VolfiedCChipCtrlRead() +{ + return 0x01; +} + +UINT8 VolfiedCChipRamRead(INT32 offset) +{ + /* Check for input ports */ + if (volfied_current_bank == 0) + { + switch (offset) + { + case 0x03: return TaitoInput[0];//input_port_read(space->machine, "F00007"); /* STARTn + SERVICE1 */ + case 0x04: return TaitoInput[1];//input_port_read(space->machine, "F00009"); /* COINn */ + case 0x05: return TaitoInput[2];//input_port_read(space->machine, "F0000B"); /* Player controls + TILT */ + case 0x06: return TaitoInput[3];//input_port_read(space->machine, "F0000D"); /* Player controls (cocktail) */ + case 0x08: return volfied_cc_port; + } + } + +// if (cpu_get_pc(space->cpu)!=0x15ca8 && cpu_get_pc(space->cpu)!=0x15cd8 && cpu_get_pc(space->cpu)!=0x15cde) +// logerror("%08x: volfied c read %04x (bank %04x)\n", cpu_get_pc(space->cpu), offset, volfied_current_bank); + + /* Unknown */ + if (volfied_current_bank == 2 && offset == 0x005) + { + /* Not fully understood - Game writes: + 0001a0c2: volfied c write 0005 00aa + 0001a0ca: volfied c write 0006 0055 + 0001a0d2: volfied c write 0004 0065 + + Then expects 0x7c to replace the 0xaa some time later. + */ + return 0x7c; /* makes worm in round 1 appear */ + } + + /* Unknown - some kind of timer */ + if (volfied_current_bank == 0 && offset == 0x3ff) + { + return 2 * volfied_current_flag; /* fixes freeze after shield runs out */ + } + + /* Current command status */ + if (volfied_current_bank == 0 && offset == 0x3fe) + { + return volfied_current_cmd; + } + + return volfied_cchip_ram[(volfied_current_bank * 0x400) + offset]; +} + + +/************************************* + * + * C-Chip State Saving + * + *************************************/ + +void VolfiedCChipInit() +{ + volfied_cchip_ram = (UINT8*)malloc(0x400 * 8); + + TaitoIC_VolfiedCChipInUse = 1; + +// state->save_item(NAME(state->volfied_current_bank)); +// state->save_item(NAME(state->volfied_current_cmd)); +// state->save_item(NAME(state->volfied_current_flag)); +// state->save_item(NAME(state->volfied_cc_port)); +// state->save_pointer(NAME(state->volfied_cchip_ram), 0x400 * 8); +} + +void VolfiedCChipReset() +{ + volfied_current_bank = 0; + volfied_current_flag = 0; + volfied_cc_port = 0; + volfied_current_cmd = 0; +} + +void VolfiedCChipExit() +{ + if (volfied_cchip_ram) { + free(volfied_cchip_ram); + volfied_cchip_ram = NULL; + } +} + +void VolfiedCChipScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = volfied_cchip_ram; + ba.nLen = 0x400 * 8; + ba.szName = "CChip Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(volfied_current_bank); + SCAN_VAR(volfied_current_flag); + SCAN_VAR(volfied_cc_port); + SCAN_VAR(volfied_current_cmd); + } +} diff --git a/src/burn/drivers/taito/d_asuka.cpp b/src/burn/drivers/taito/d_asuka.cpp new file mode 100644 index 00000000..9d539058 --- /dev/null +++ b/src/burn/drivers/taito/d_asuka.cpp @@ -0,0 +1,2135 @@ +// FB Alpha Asuka & Asuka driver module +// Based on MAME driver by David Graves, Brian Troha, and + +#include "tiles_generic.h" +#include "burn_ym2151.h" +#include "burn_ym2610.h" +#include "msm5205.h" +#include "taito_ic.h" +#include "taito.h" + +static UINT8 TaitoInputConfig; +static INT32 AsukaADPCMPos; +static INT32 AsukaADPCMData; + +static struct BurnInputInfo CadashInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 7, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 6, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort1 + 7, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort1 + 6, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Cadash) + +static struct BurnInputInfo AsukaInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset"}, + {"Service", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Asuka) + +static struct BurnInputInfo BonzeadvInputList[] = { + {"P1 Coin", BIT_DIGITAL, TaitoInputPort1 + 0, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TaitoInputPort0 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TaitoInputPort2 + 2, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TaitoInputPort2 + 3, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TaitoInputPort2 + 4, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TaitoInputPort2 + 5, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TaitoInputPort2 + 6, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TaitoInputPort2 + 7, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, TaitoInputPort1 + 1, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TaitoInputPort0 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TaitoInputPort3 + 1, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TaitoInputPort3 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TaitoInputPort3 + 3, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TaitoInputPort3 + 4, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TaitoInputPort3 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TaitoInputPort3 + 6, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TaitoInputPort0 + 7, "service" }, + {"Tilt", BIT_DIGITAL, TaitoInputPort2 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TaitoDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TaitoDip + 1, "dip" }, +}; + +STDINPUTINFO(Bonzeadv) + +static struct BurnDIPInfo CadashDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Starting Time" }, + {0x14, 0x01, 0x0c, 0x00, "5:00" }, + {0x14, 0x01, 0x0c, 0x04, "6:00" }, + {0x14, 0x01, 0x0c, 0x0c, "7:00" }, + {0x14, 0x01, 0x0c, 0x08, "8:00" }, + + {0 , 0xfe, 0 , 4, "Add Time" }, + {0x14, 0x01, 0x30, 0x00, "Default - 2:00" }, + {0x14, 0x01, 0x30, 0x10, "Default - 1:00" }, + {0x14, 0x01, 0x30, 0x30, "Default" }, + {0x14, 0x01, 0x30, 0x20, "Default + 1:00" }, + + {0 , 0xfe, 0 , 3, "Communication Mode" }, + {0x14, 0x01, 0xc0, 0xc0, "Stand alone" }, + {0x14, 0x01, 0xc0, 0x80, "Master" }, + {0x14, 0x01, 0xc0, 0x00, "Slave" }, +}; + +STDDIPINFO(Cadash) + +static struct BurnDIPInfo CadashjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coins 2 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "2 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 3 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Starting Time" }, + {0x14, 0x01, 0x0c, 0x00, "5:00" }, + {0x14, 0x01, 0x0c, 0x04, "6:00" }, + {0x14, 0x01, 0x0c, 0x0c, "7:00" }, + {0x14, 0x01, 0x0c, 0x08, "8:00" }, + + {0 , 0xfe, 0 , 4, "Add Time" }, + {0x14, 0x01, 0x30, 0x00, "Default - 2:00" }, + {0x14, 0x01, 0x30, 0x10, "Default - 1:00" }, + {0x14, 0x01, 0x30, 0x30, "Default" }, + {0x14, 0x01, 0x30, 0x20, "Default + 1:00" }, + + {0 , 0xfe, 0 , 3, "Communication Mode" }, + {0x14, 0x01, 0xc0, 0xc0, "Stand alone" }, + {0x14, 0x01, 0xc0, 0x80, "Master" }, + {0x14, 0x01, 0xc0, 0x00, "Slave" }, +}; + +STDDIPINFO(Cadashj) + +static struct BurnDIPInfo CadashuDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Price to Continue" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as Start" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Starting Time" }, + {0x14, 0x01, 0x0c, 0x00, "5:00" }, + {0x14, 0x01, 0x0c, 0x04, "6:00" }, + {0x14, 0x01, 0x0c, 0x0c, "7:00" }, + {0x14, 0x01, 0x0c, 0x08, "8:00" }, + + {0 , 0xfe, 0 , 4, "Add Time (after clear)"}, + {0x14, 0x01, 0x30, 0x00, "Default - 2:00" }, + {0x14, 0x01, 0x30, 0x10, "Default - 1:00" }, + {0x14, 0x01, 0x30, 0x30, "Default" }, + {0x14, 0x01, 0x30, 0x20, "Default + 1:00" }, + + {0 , 0xfe, 0 , 3, "Communication Mode" }, + {0x14, 0x01, 0xc0, 0xc0, "Stand alone" }, + {0x14, 0x01, 0xc0, 0x80, "Master" }, + {0x14, 0x01, 0xc0, 0x00, "Slave" }, +}; + +STDDIPINFO(Cadashu) + + +static struct BurnDIPInfo EtoDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0x03, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Eto) + +static struct BurnDIPInfo AsukaDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Points" }, + {0x14, 0x01, 0x0c, 0x0c, "500" }, + {0x14, 0x01, 0x0c, 0x08, "1500" }, + {0x14, 0x01, 0x0c, 0x04, "2000" }, + {0x14, 0x01, 0x0c, 0x00, "2500" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0xc0, 0x00, "No" }, + {0x14, 0x01, 0xc0, 0xc0, "Up To Level 2" }, + {0x14, 0x01, 0xc0, 0x80, "Up To Level 3" }, + {0x14, 0x01, 0xc0, 0x40, "Yes" }, +}; + +STDDIPINFO(Asuka) + +static struct BurnDIPInfo MofflottDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "20k And Every 50k" }, + {0x14, 0x01, 0x0c, 0x08, "50k And Every 100k" }, + {0x14, 0x01, 0x0c, 0x04, "100k Only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x40, "Off" }, + {0x14, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Number Of Keys" }, + {0x14, 0x01, 0x80, 0x00, "B 14" }, + {0x14, 0x01, 0x80, 0x80, "A 16" }, +}; + +STDDIPINFO(Mofflott) + +static struct BurnDIPInfo GalmedesDIPList[]= +{ + {0x13, 0xff, 0xff, 0xf7, NULL }, + {0x14, 0xff, 0xff, 0xfb, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 8, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "Every 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "100k And Every 200k" }, + {0x14, 0x01, 0x0c, 0x04, "150k And Every 200k" }, + {0x14, 0x01, 0x0c, 0x00, "Every 200k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 2, "Coin Mode" }, + {0x14, 0x01, 0x80, 0x80, "Mode A (Japan)" }, + {0x14, 0x01, 0x80, 0x00, "Mode B (World)" }, +}; + +STDDIPINFO(Galmedes) + +static struct BurnDIPInfo EarthjkrDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xf3, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x00, "100k and 300k" }, + {0x14, 0x01, 0x0c, 0x08, "100k only" }, + {0x14, 0x01, 0x0c, 0x04, "200k only" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x30, "2" }, + {0x14, 0x01, 0x30, 0x20, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + + {0 , 0xfe, 0 , 2, "Copyright" }, + {0x14, 0x01, 0x40, 0x40, "Visco" }, + {0x14, 0x01, 0x40, 0x00, "Visco (Romstar)" }, +}; + +STDDIPINFO(Earthjkr) + +static struct BurnDIPInfo BonzeadvDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xbc, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "40k 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "50k 150k" }, + {0x14, 0x01, 0x0c, 0x04, "60k 200k" }, + {0x14, 0x01, 0x0c, 0x00, "80k 250k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x40, "No" }, + {0x14, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Bonzeadv) + +static struct BurnDIPInfo JigkmgriDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xbc, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "40k 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "50k 150k" }, + {0x14, 0x01, 0x0c, 0x04, "60k 200k" }, + {0x14, 0x01, 0x0c, 0x00, "80k 250k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x40, "No" }, + {0x14, 0x01, 0x40, 0x00, "Yes" }, +}; + +STDDIPINFO(Jigkmgri) + +//-------------------------------------------------------------------------------------------------------------------------- + +void __fastcall cadash_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x900000) + TC0100SCN0ByteWrite_Map(0xc00000, 0xc0ffff) +} + +void __fastcall cadash_write_word(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x900000) + TC0100SCN0WordWrite_Map(0xc00000, 0xc0ffff) + TC0100SCN0CtrlWordWrite_Map(0xc20000) + + switch (a) + { + case 0x080000: + case 0x080002: + PC090OJSpriteCtrl = (d & 0x3c) >> 2; + return; + + case 0xa00000: + case 0xa00002: + case 0xa00004: + TC0110PCRStep14rbgWordWrite(0, (a & 0x0f) / 2, d); + return; + + case 0x0c0000: + TC0140SYTPortWrite(d); + return; + + case 0x0c0002: + ZetClose(); + TC0140SYTCommWrite(d); + ZetOpen(0); + return; + } +} + +UINT8 __fastcall cadash_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x900000) + + return 0; +} + +UINT16 __fastcall cadash_read_word(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x900000) + if ((a & 0xffffff0) == 0xc20000) return TC0100SCNCtrl[0][(a & 0x0f)/2]; + + switch (a) + { + case 0xa00002: + return TC0110PCRWordRead(0); + + case 0x0c0002: + return TC0140SYTCommRead(); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +void __fastcall asuka_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0ByteWrite_Map(0xc00000, 0xc0ffff) + + switch (a) + { + case 0x3a0001: + PC090OJSpriteCtrl = ((d & 0x3c) >> 2) | ((d & 0x01) << 15); + return; + + case 0x3e0001: + TC0140SYTPortWrite(d); + return; + + case 0x3e0002: + case 0x3e0003: + ZetClose(); + TC0140SYTCommWrite(d); + ZetOpen(0); + return; + } +} + +void __fastcall asuka_write_word(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0WordWrite_Map(0xc00000, 0xc0ffff) + TC0100SCN0CtrlWordWrite_Map(0xc20000) + + switch (a) + { + case 0x3a0000: + PC090OJSpriteCtrl = ((d & 0x3c) >> 2) | ((d & 0x01) << 15); + return; + + case 0x200000: + case 0x200002: + case 0x200004: + TC0110PCRStep1WordWrite(0, (a & 0x0f) / 2, d); + return; + + case 0x3e0000: // galmedes + TC0140SYTPortWrite(d); + return; + + case 0x3e0002: + ZetClose(); + TC0140SYTCommWrite(d); + ZetOpen(0); + return; + } +} + +UINT8 __fastcall asuka_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x3e0002: + case 0x3e0003: + return TC0140SYTCommRead(); + } + + return 0; +} + +UINT16 __fastcall asuka_read_word(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x400000) + if ((a & 0xffffff0) == 0xc20000) return TC0100SCNCtrl[0][(a & 0x0f)/2]; + + switch (a) + { + case 0x1076f0: + return 0; // maze of flott + + case 0x200002: + return TC0110PCRWordRead(0); + + case 0x3e0002: + return TC0140SYTCommRead(); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +void __fastcall eto_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0ByteWrite_Map(0xd00000, 0xd0ffff) + + if (a >= 0xc04000 && a <= 0xc0ffff) { + INT32 Offset = (a - 0xc00000) ^ 1; + if (TC0100SCNRam[0][Offset] != d) { + TC0100SCNBgLayerUpdate[0] = 1; + TC0100SCNFgLayerUpdate[0] = 1; + } + TC0100SCNRam[0][Offset] = d; + return; + } + + switch (a) + { + case 0x4a0000: + case 0x4a0001: + PC090OJSpriteCtrl = ((d & 0x3c) >> 2) | ((d & 0x01) << 15); + return; + } +} + +void __fastcall eto_write_word(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0WordWrite_Map(0xd00000, 0xd0ffff) + TC0100SCN0CtrlWordWrite_Map(0xd20000) + + if (a >= 0xc04000 && a <= 0xc0ffff) { + UINT16 *Ram = (UINT16*)TC0100SCNRam[0]; + INT32 Offset = (a - 0xc00000) >> 1; + if (Ram[Offset] != d) { + TC0100SCNBgLayerUpdate[0] = 1; + TC0100SCNFgLayerUpdate[0] = 1; + } + Ram[Offset] = d; + return; + } + + switch (a) + { + case 0x100000: + case 0x100002: + case 0x100004: + TC0110PCRStep1WordWrite(0, (a & 0x0f) / 2, d); + return; + + case 0x4e0000: + TC0140SYTPortWrite(d); + return; + + case 0x4e0002: + ZetClose(); + TC0140SYTCommWrite(d); + ZetOpen(0); + return; + } +} + +UINT8 __fastcall eto_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + TC0220IOCHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x4e0002: + case 0x4e0003: + return TC0140SYTCommRead(); + } + + return 0; +} + +UINT16 __fastcall eto_read_word(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + TC0220IOCHalfWordRead_Map(0x400000) + if ((a & 0xffffff0) == 0xd20000) return TC0100SCNCtrl[0][(a & 0x0f)/2]; + + switch (a) + { + case 0x100002: + return TC0110PCRWordRead(0); + + case 0x4e0002: + return TC0140SYTCommRead(); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +void __fastcall bonze_write_byte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0xc00000, 0xc0ffff) + + switch (a) + { + case 0x3a0001: + PC090OJSpriteCtrl = (d & 0x3c) >> 2; + return; + + case 0x3e0001: + TC0140SYTPortWrite(d); + return; + + case 0x3e0003: + ZetClose(); + TC0140SYTCommWrite(d); + ZetOpen(0); + return; + + case 0x800803: // CChip Ctrl + return; + + case 0x800c01: + BonzeWriteCChipBank(d); + return; + } + + if ((a & 0xffff800) == 0x800000) { + BonzeWriteCChipRam(a, d); + return; + } +} + +void __fastcall bonze_write_word(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0xc00000, 0xc0ffff) + TC0100SCN0CtrlWordWrite_Map(0xc20000) + + switch (a) + { + case 0x200000: + case 0x200002: + case 0x200004: + TC0110PCRStep1WordWrite(0, (a & 0x0f) / 2, d); + return; + + case 0x3c0000: + TaitoWatchdog = 0; + return; + } + + if ((a & 0xffffc00) == 0xc10000) return; // nop +} + +UINT8 __fastcall bonze_read_byte(UINT32 a) +{ + switch (a) + { + case 0x3e0003: + return TC0140SYTCommRead(); + + case 0x800803: + return 1; // CChip Status + } + + if ((a & 0xfffff800) == 0x800000) { + return BonzeReadCChipRam(a); + } + + return 0; +} + +UINT16 __fastcall bonze_read_word(UINT32 a) +{ + if ((a & 0xffffff0) == 0xc20000) return TC0100SCNCtrl[0][(a & 0x0f)/2]; + + switch (a) + { + case 0x200002: + return TC0110PCRWordRead(0); + + case 0x390000: + return TaitoDip[0]; + + case 0x3b0000: + return TaitoDip[1]; + + case 0x3d0000: + return 0; // nop + } + + if ((a & 0xfffff800) == 0x800000) { + return BonzeReadCChipRam(a); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +void __fastcall cadash_sound_write(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0x9000: + BurnYM2151SelectRegister(d); + return; + + case 0x9001: + BurnYM2151WriteRegister(d); + return; + + case 0xa000: + TC0140SYTSlavePortWrite(d); + return; + + case 0xa001: + TC0140SYTSlaveCommWrite(d); + return; + + case 0xb000: { + if (TaitoNumMSM5205) AsukaADPCMPos = (AsukaADPCMPos & 0x00ff) | (d << 8); + return; + } + + case 0xc000: { + if (TaitoNumMSM5205) MSM5205ResetWrite(0, 0); + return; + } + + case 0xd000: { + if (TaitoNumMSM5205) { + MSM5205ResetWrite(0, 1); + AsukaADPCMPos &= 0xff00; + } + return; + } + } +} + +UINT8 __fastcall cadash_sound_read(UINT16 a) +{ + switch (a) + { + case 0x9000: + case 0x9001: + return BurnYM2151ReadStatus(); + + case 0xa001: + return TC0140SYTSlaveCommRead(); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +static void DrvSoundBankSwitch(UINT32, UINT32 bank) +{ + TaitoZ80Bank = bank & 0x03; + + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + TaitoZ80Bank * 0x4000); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + TaitoZ80Bank * 0x4000); +} + +void __fastcall bonze_sound_write(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + BurnYM2610Write(a & 3, d); + return; + + case 0xe200: + TC0140SYTSlavePortWrite(d); + return; + + case 0xe201: + TC0140SYTSlaveCommWrite(d); + return; + + case 0xf200: + DrvSoundBankSwitch(0, d); + return; + } +} + +UINT8 __fastcall bonze_sound_read(UINT16 a) +{ + switch (a) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + return BurnYM2610Read(a & 3); + + case 0xe201: + return TC0140SYTSlaveCommRead(); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------------------------------- + +static void DrvMakeInputs() +{ + memset (TC0220IOCInput, 0xff, 3); + + TC0220IOCInput[2] &= ~TaitoInputConfig; // asuka + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[0] ^= (TC0220IOCInputPort0[i] & 1) << i; + TC0220IOCInput[1] ^= (TC0220IOCInputPort1[i] & 1) << i; + TC0220IOCInput[2] ^= (TC0220IOCInputPort2[i] & 1) << i; + } +} + +static void CadashYM2151IRQHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 4000000.0; +} + +static void AsukaMSM5205Vck() +{ + if (AsukaADPCMData != -1) { + MSM5205DataWrite(0, AsukaADPCMData & 0x0f); + AsukaADPCMData = -1; + } else { + AsukaADPCMData = TaitoMSM5205Rom[AsukaADPCMPos]; + AsukaADPCMPos = (AsukaADPCMPos + 1) & 0xffff; + MSM5205DataWrite(0, AsukaADPCMData >> 4); + } +} + +static INT32 DrvDoReset() +{ + memset (TaitoRamStart, 0, TaitoRamEnd - TaitoRamStart); + + TaitoDoReset(); + + ZetOpen(0); + DrvSoundBankSwitch(0, 1); + ZetClose(); + + BonzeCChipReset(); + + AsukaADPCMPos = 0; + AsukaADPCMData = -1; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += 0x100000; + TaitoZ80Rom1 = Next; Next += 0x010000; + + TaitoChars = Next; Next += TaitoCharRomSize * 2; + TaitoSpritesA = Next; Next += TaitoSpriteARomSize * 2; + + TaitoMSM5205Rom = Next; Next += TaitoMSM5205RomSize; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x008000; + Taito68KRam2 = Next; Next += 0x001000; + + TaitoZ80Ram1 = Next; Next += 0x002000; + + TaitoRamEnd = Next; + TaitoMemEnd = Next; + + return 0; +} + +static void expand_graphics(UINT8 *src, INT32 len) +{ + for (INT32 i = (len * 2) - 2; i >= 0; i -= 2) { + src[i + 0] = src[(i / 2) ^ 1] >> 4; + src[i + 1] = src[(i / 2) ^ 1] & 0x0f; + } +} + +static void Cadash68KSetup() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x100000, 0x107fff, SM_RAM); + SekMapMemory(Taito68KRam2, 0x800000, 0x800fff, SM_RAM); // Network RAM + SekMapMemory(PC090OJRam, 0xb00000, 0xb03fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0], 0xc00000, 0xc0ffff, SM_READ); + SekSetWriteByteHandler(0, cadash_write_byte); + SekSetWriteWordHandler(0, cadash_write_word); + SekSetReadByteHandler(0, cadash_read_byte); + SekSetReadWordHandler(0, cadash_read_word); + SekClose(); +} + +static void Eto68KSetup() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000, 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x200000, 0x203fff, SM_RAM); + SekMapMemory(PC090OJRam, 0xc00000, 0xc03fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] + 0x4000, 0xc04000, 0xc0ffff, SM_READ); // mirror + SekMapMemory(TC0100SCNRam[0], 0xd00000, 0xd0ffff, SM_READ); + SekSetWriteByteHandler(0, eto_write_byte); + SekSetWriteWordHandler(0, eto_write_word); + SekSetReadByteHandler(0, eto_read_byte); + SekSetReadWordHandler(0, eto_read_word); + SekClose(); +} + +static void Asuka68KSetup() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000, 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0], 0xc00000, 0xc0ffff, SM_READ); + SekMapMemory(PC090OJRam, 0xd00000, 0xd03fff, SM_RAM); + SekSetWriteByteHandler(0, asuka_write_byte); + SekSetWriteWordHandler(0, asuka_write_word); + SekSetReadByteHandler(0, asuka_read_byte); + SekSetReadWordHandler(0, asuka_read_word); + SekClose(); +} + +static void Bonze68KSetup() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000, 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x10c000, 0x10ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0], 0xc00000, 0xc0ffff, SM_READ); + SekMapMemory(PC090OJRam, 0xd00000, 0xd03fff, SM_RAM); + SekSetWriteByteHandler(0, bonze_write_byte); + SekSetWriteWordHandler(0, bonze_write_word); + SekSetReadByteHandler(0, bonze_read_byte); + SekSetReadWordHandler(0, bonze_read_word); + SekClose(); +} + +static void CadashZ80Setup() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1); + ZetSetWriteHandler(cadash_sound_write); + ZetSetReadHandler(cadash_sound_read); + ZetMemEnd(); + ZetClose(); +} + +static void BonzeZ80Setup() +{ + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1); + ZetSetWriteHandler(bonze_sound_write); + ZetSetReadHandler(bonze_sound_read); + ZetMemEnd(); + ZetClose(); +} + +static void CadashSoundSetup() +{ + BurnYM2151Init(4000000, 50.0); + BurnYM2151SetIrqHandler(&CadashYM2151IRQHandler); + BurnYM2151SetPortHandler(&DrvSoundBankSwitch); + + TaitoNumYM2151 = 1; + TaitoNumYM2610 = 0; + TaitoNumMSM5205 = 0; +} + +static void AsukaSoundSetup() +{ + BurnYM2151Init(4000000, 50.0); + BurnYM2151SetIrqHandler(&CadashYM2151IRQHandler); + BurnYM2151SetPortHandler(&DrvSoundBankSwitch); + + MSM5205Init(0, DrvSynchroniseStream, 384000, AsukaMSM5205Vck, MSM5205_S48_4B, 100, 1); + + TaitoNumYM2151 = 1; + TaitoNumMSM5205 = 1; + TaitoNumYM2610 = 0; +} + +static void BonzeSoundSetup() +{ + INT32 DrvSndROMLen = 0x80000; + BurnYM2610Init(8000000, TaitoYM2610ARom, &DrvSndROMLen, TaitoYM2610ARom, &DrvSndROMLen, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(4000000); + BurnYM2610SetSoundMixMode(1); + + TaitoNumYM2151 = 0; + TaitoNumYM2610 = 1; + TaitoNumMSM5205 = 0; +} + +static INT32 CommonInit(void (*Cpu68KSetup)(), void (*CpuZ80Setup)(), void (*SoundSetup)(), INT32 buffer_sprites) +{ + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoInputConfig = 0; + + TaitoLoadRoms(false); + + TaitoMem = NULL; + MemIndex(); + INT32 nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + TaitoLoadRoms(true); + + expand_graphics(TaitoChars, 0x80000); + expand_graphics(TaitoSpritesA, TaitoSpriteARomSize); + + GenericTilesInit(); + + PC090OJInit((TaitoSpriteARomSize * 2) / 0x100, 0, (256 - nScreenHeight) / 2, buffer_sprites); + TC0100SCNInit(0, (0x80000 * 2) / 0x40, 0, (256 - nScreenHeight) / 2, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0220IOCInit(); + TaitoMakeInputsFunction = DrvMakeInputs; + TC0140SYTInit(); + + Cpu68KSetup(); + CpuZ80Setup(); + SoundSetup(); + + DrvDoReset(); + + return 0; +} + +static INT32 DrvDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + if ((PC090OJSpriteCtrl & 0x8000)) PC090OJDrawSprites(TaitoSpritesA); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + if ((PC090OJSpriteCtrl & 0x8000)) PC090OJDrawSprites(TaitoSpritesA); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + if (!(PC090OJSpriteCtrl & 0x8000)) PC090OJDrawSprites(TaitoSpritesA); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + + BurnTransferCopy(TC0110PCRPalette); + + return 0; +} + +static INT32 CadashFrame() +{ + if (TaitoReset) { + DrvDoReset(); + } + + TaitoMakeInputsFunction(); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 16000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCycleSegment; + + nCycleSegment = (nCyclesTotal[0] / nInterleave) * (i+1); + if (i == (nInterleave - 1)) nCycleSegment -= 500; //? + nCyclesDone[0] += SekRun(nCycleSegment - SekTotalCycles()); + + nCycleSegment = (nCyclesTotal[1] / nInterleave) * (i+1); + nCyclesDone[1] += ZetRun(nCycleSegment - ZetTotalCycles()); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekRun(500); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 EtoFrame() // Using for asuka too, but needs msm5205 +{ + if (TaitoReset) { + DrvDoReset(); + } + + TaitoMakeInputsFunction(); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + INT32 nInterleave = 100; + if (TaitoNumMSM5205) nInterleave = MSM5205CalcInterleave(0, 4000000); + INT32 nSoundBufferPos = 0; + INT32 nCyclesTotal[2] = { 8000000 / 60, 4000000 / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) + { + INT32 nCycleSegment; + + nCycleSegment = (nCyclesTotal[0] / nInterleave) * (i+1); + nCyclesDone[0] += SekRun(nCycleSegment - SekTotalCycles()); + + nCycleSegment = (nCyclesTotal[1] / nInterleave) * (i+1); + nCyclesDone[1] += ZetRun(nCycleSegment - ZetTotalCycles()); + if (TaitoNumMSM5205) MSM5205Update(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + if (TaitoNumMSM5205) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 BonzeFrame() +{ + TaitoWatchdog++; + if (TaitoReset || TaitoWatchdog >= 180) { + DrvDoReset(); + } + + { + memset (TaitoInput, 0xff, 4); + TaitoInput[1] = 0; + + for (INT32 i = 0; i < 8; i++) { + TaitoInput[0] ^= (TaitoInputPort0[i] & 1) << i; + TaitoInput[1] ^= (TaitoInputPort1[i] & 1) << i; + TaitoInput[2] ^= (TaitoInputPort2[i] & 1) << i; + TaitoInput[3] ^= (TaitoInputPort3[i] & 1) << i; + } + } + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekRun(8000000 / 60); + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + BurnTimerEndFrame(4000000 / 60); + + if (pBurnSoundOut) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029707; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd - TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + TaitoICScan(nAction); + BonzeCChipScan(nAction); + + if (TaitoNumYM2151) BurnYM2151Scan(nAction); + if (TaitoNumYM2610) BurnYM2610Scan(nAction, pnMin); + if (TaitoNumMSM5205) MSM5205Scan(nAction, pnMin); + + SCAN_VAR(TaitoZ80Bank); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + DrvSoundBankSwitch(0, TaitoZ80Bank); + ZetClose(); + } + + return 0; +} + + +// Cadash (World) + +static struct BurnRomInfo cadashRomDesc[] = { + { "c21-14", 0x20000, 0x5daf13fb, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-16", 0x20000, 0xcbaa2e75, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-13", 0x20000, 0x6b9e0ee9, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-17", 0x20000, 0xbf9a578a, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? + + { "pal16l8b-c21-09.ic34", 0x00104, 0x4b296700, BRF_OPT }, // 8 plds + { "pal16l8b-c21-10.ic45", 0x00104, 0x35642f00, BRF_OPT }, // 9 + { "pal16l8b-c21-11-1.ic46", 0x00104, 0xf4791e24, BRF_OPT }, // 10 + { "pal20l8b-c21-12.ic47", 0x00144, 0xbbc2cc97, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(cadash) +STD_ROM_FN(cadash) + +static INT32 CadashInit() +{ + return CommonInit(Cadash68KSetup, CadashZ80Setup, CadashSoundSetup, 1); +} + +struct BurnDriver BurnDrvCadash = { + "cadash", NULL, NULL, NULL, "1989", + "Cadash (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashRomInfo, cadashRomName, NULL, NULL, CadashInputInfo, CadashDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Cadash (Japan) + +static struct BurnRomInfo cadashjRomDesc[] = { + { "c21-04.11", 0x20000, 0xcc22ebe5, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-06.15", 0x20000, 0x26e03304, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-03.10", 0x20000, 0xc54888ed, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-05.14", 0x20000, 0x834018d2, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? +}; + +STD_ROM_PICK(cadashj) +STD_ROM_FN(cadashj) + +struct BurnDriver BurnDrvCadashj = { + "cadashj", "cadash", NULL, NULL, "1989", + "Cadash (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashjRomInfo, cadashjRomName, NULL, NULL, CadashInputInfo, CadashjDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Cadash (US) + +static struct BurnRomInfo cadashuRomDesc[] = { + { "c21-14-2.11", 0x20000, 0xf823d418, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-16-2.15", 0x20000, 0x90165577, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-13-2.10", 0x20000, 0x92dcc3ae, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-15-2.14", 0x20000, 0xf915d26a, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? +}; + +STD_ROM_PICK(cadashu) +STD_ROM_FN(cadashu) + +struct BurnDriver BurnDrvCadashu = { + "cadashu", "cadash", NULL, NULL, "1989", + "Cadash (US)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashuRomInfo, cadashuRomName, NULL, NULL, CadashInputInfo, CadashuDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Cadash (Italy) + +static struct BurnRomInfo cadashiRomDesc[] = { + { "c21-14it", 0x20000, 0xd1d9e613, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-16it", 0x20000, 0x142256ef, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-13it", 0x20000, 0xc9cf6e30, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-17it", 0x20000, 0x641fc9dd, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? +}; + +STD_ROM_PICK(cadashi) +STD_ROM_FN(cadashi) + +struct BurnDriver BurnDrvCadashi = { + "cadashi", "cadash", NULL, NULL, "1989", + "Cadash (Italy)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashiRomInfo, cadashiRomName, NULL, NULL, CadashInputInfo, CadashDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Cadash (France) + +static struct BurnRomInfo cadashfRomDesc[] = { + { "c21-19", 0x20000, 0x4d70543b, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-21", 0x20000, 0x0e5b9950, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-18", 0x20000, 0x8a19e59b, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-20", 0x20000, 0xb96acfd9, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? +}; + +STD_ROM_PICK(cadashf) +STD_ROM_FN(cadashf) + +struct BurnDriver BurnDrvCadashf = { + "cadashf", "cadash", NULL, NULL, "1989", + "Cadash (France)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashfRomInfo, cadashfRomName, NULL, NULL, CadashInputInfo, CadashDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Cadash (Germany) + +static struct BurnRomInfo cadashgRomDesc[] = { + { "c21-23-1.12", 0x20000, 0x30ddbabe, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c21-25-1.16", 0x20000, 0x24e10611, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c21-22-1.11", 0x20000, 0xdaf58b2d, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "c21-24-1.15", 0x20000, 0x2359b93e, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + + { "c21-08.38", 0x10000, 0xdca495a0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c21-02.9", 0x80000, 0x205883b9, BRF_GRA | TAITO_CHARS }, // 5 Characters + + { "c21-01.1", 0x80000, 0x1ff6f39c, BRF_GRA | TAITO_SPRITESA }, // 6 Sprites + + { "c21-07.57", 0x08000, 0xf02292bd, BRF_PRG | BRF_OPT }, // 7 Z180 Code? +}; + +STD_ROM_PICK(cadashg) +STD_ROM_FN(cadashg) + +struct BurnDriver BurnDrvCadashg = { + "cadashg", "cadash", NULL, NULL, "1989", + "Cadash (Germany)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SCRFIGHT, 0, + NULL, cadashgRomInfo, cadashgRomName, NULL, NULL, CadashInputInfo, CadashDIPInfo, + CadashInit, TaitoExit, CadashFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Kokontouzai Eto Monogatari (Japan) + +static struct BurnRomInfo etoRomDesc[] = { + { "eto-1.23", 0x20000, 0x44286597, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "eto-0.8", 0x20000, 0x57b79370, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "eto-2.30", 0x80000, 0x12f46fb5, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "eto-5.27", 0x10000, 0xb3689da0, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "eto-4.3", 0x80000, 0xa8768939, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "eto-3.6", 0x80000, 0xdd247397, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites +}; + +STD_ROM_PICK(eto) +STD_ROM_FN(eto) + +static INT32 EtoInit() +{ + INT32 nRet = CommonInit(Eto68KSetup, CadashZ80Setup, CadashSoundSetup, 0); + + if (nRet == 0) { + BurnByteswap(Taito68KRom1 + 0x40000, 0x80000); + } + + return nRet; +} + +struct BurnDriver BurnDrvEto = { + "eto", NULL, NULL, NULL, "1994", + "Kokontouzai Eto Monogatari (Japan)\0", NULL, "Visco", "Taito Misc", + L"\u53E4\u4ECA\u6771\u897F\u5E72\u652F\u7269\u8A9E (Japan)\0Kokontouzai Eto Monogatari (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PUZZLE, 0, + NULL, etoRomInfo, etoRomName, NULL, NULL, AsukaInputInfo, EtoDIPInfo, + EtoInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 240, 4, 3 +}; + + +// Asuka & Asuka (World) + +static struct BurnRomInfo asukaRomDesc[] = { + { "b68-13.bin", 0x20000, 0x855efb3e, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b68-12.bin", 0x20000, 0x271eeee9, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b68-03.bin", 0x80000, 0xd3a59b10, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "b68-11.bin", 0x10000, 0xc378b508, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "b68-01.bin", 0x80000, 0x89f32c94, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "b68-02.bin", 0x80000, 0xf5018cd3, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites + { "b68-07.bin", 0x10000, 0xc113acc8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 6 + { "b68-06.bin", 0x10000, 0xf517e64d, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 7 + + { "b68-10.bin", 0x10000, 0x387aaf40, BRF_SND | TAITO_MSM5205 }, // 8 MSM5205 Samples +}; + +STD_ROM_PICK(asuka) +STD_ROM_FN(asuka) + +static INT32 AsukaInit() +{ + INT32 nRet = CommonInit(Asuka68KSetup, CadashZ80Setup, AsukaSoundSetup, 0); + + if (nRet == 0) { + BurnByteswap(Taito68KRom1 + 0x40000, 0x80000); + } + + TaitoInputConfig = 0x30; + + return nRet; +} + +struct BurnDriver BurnDrvAsuka = { + "asuka", NULL, NULL, NULL, "1988", + "Asuka & Asuka (World)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, asukaRomInfo, asukaRomName, NULL, NULL, AsukaInputInfo, AsukaDIPInfo, + AsukaInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 240, 320, 3, 4 +}; + + +// Asuka & Asuka (Japan) + +static struct BurnRomInfo asukajRomDesc[] = { + { "b68-09.bin", 0x20000, 0x1eaa1bbb, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b68-08.bin", 0x20000, 0x8cc96e60, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b68-03.bin", 0x80000, 0xd3a59b10, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "b68-11.bin", 0x10000, 0xc378b508, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "b68-01.bin", 0x80000, 0x89f32c94, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "b68-02.bin", 0x80000, 0xf5018cd3, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites + { "b68-07.bin", 0x10000, 0xc113acc8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 6 + { "b68-06.bin", 0x10000, 0xf517e64d, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 7 + + { "b68-10.bin", 0x10000, 0x387aaf40, BRF_SND | TAITO_MSM5205 }, // 8 MSM5205 Samples +}; + +STD_ROM_PICK(asukaj) +STD_ROM_FN(asukaj) + +struct BurnDriver BurnDrvAsukaj = { + "asukaj", "asuka", NULL, NULL, "1988", + "Asuka & Asuka (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, asukajRomInfo, asukajRomName, NULL, NULL, AsukaInputInfo, AsukaDIPInfo, + AsukaInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 240, 320, 3, 4 +}; + + +// Maze of Flott (Japan) + +static struct BurnRomInfo mofflottRomDesc[] = { + { "c17-09.bin", 0x20000, 0x05ee110f, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "c17-08.bin", 0x20000, 0xd0aacffd, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "c17-03.bin", 0x80000, 0x27047fc3, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "c17-07.bin", 0x10000, 0xcdb7bc2c, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "c17-01.bin", 0x80000, 0xe9466d42, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "c17-02.bin", 0x80000, 0x8860a8db, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites + { "c17-05.bin", 0x10000, 0x57ac4741, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 6 + { "c17-04.bin", 0x10000, 0xf4250410, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 7 + + { "c17-06.bin", 0x10000, 0x5c332125, BRF_SND | TAITO_MSM5205 }, // 8 MSM5205 Samples +}; + +STD_ROM_PICK(mofflott) +STD_ROM_FN(mofflott) + +struct BurnDriver BurnDrvMofflott = { + "mofflott", NULL, NULL, NULL, "1989", + "Maze of Flott (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_MAZE, 0, + NULL, mofflottRomInfo, mofflottRomName, NULL, NULL, AsukaInputInfo, MofflottDIPInfo, + AsukaInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 240, 320, 3, 4 +}; + + +// Galmedes (Japan) + +static struct BurnRomInfo galmedesRomDesc[] = { + { "gm-prg1.bin", 0x20000, 0x32a70753, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "gm-prg0.bin", 0x20000, 0xfae546a4, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "gm-30.rom", 0x80000, 0x4da2a407, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "gm-snd.bin", 0x10000, 0xd6f56c21, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "gm-scn.bin", 0x80000, 0x3bab0581, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "gm-obj.bin", 0x80000, 0x7a4a1315, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites +}; + +STD_ROM_PICK(galmedes) +STD_ROM_FN(galmedes) + +static INT32 GalmedesInit() +{ + INT32 nRet = CommonInit(Asuka68KSetup, CadashZ80Setup, CadashSoundSetup, 0); + + if (nRet == 0) { + BurnByteswap(Taito68KRom1 + 0x40000, 0x80000); + } + + return nRet; +} + +struct BurnDriver BurnDrvGalmedes = { + "galmedes", NULL, NULL, NULL, "1992", + "Galmedes (Japan)\0", NULL, "Visco", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, galmedesRomInfo, galmedesRomName, NULL, NULL, AsukaInputInfo, GalmedesDIPInfo, + GalmedesInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 240, 320, 3, 4 +}; + + +// U.N. Defense Force: Earth Joker + +static struct BurnRomInfo earthjkrRomDesc[] = { + { "ej_3b.rom", 0x20000, 0xbdd86fc2, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "ej_3a.rom", 0x20000, 0x9c8050c6, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "ej_30e.rom", 0x80000, 0x49d1f77f, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 2 + + { "ej_2.rom", 0x10000, 0x42ba2566, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 3 Z80 Code + + { "ej_chr.rom", 0x80000, 0xac675297, BRF_GRA | TAITO_CHARS }, // 4 Characters + + { "ej_obj.rom", 0x80000, 0x5f21ac47, BRF_GRA | TAITO_SPRITESA }, // 5 Sprites + { "ej_1.rom", 0x10000, 0xcb4891db, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 6 + { "ej_0.rom", 0x10000, 0xb612086f, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, // 7 +}; + +STD_ROM_PICK(earthjkr) +STD_ROM_FN(earthjkr) + +struct BurnDriver BurnDrvEarthjkr = { + "earthjkr", NULL, NULL, NULL, "1993", + "U.N. Defense Force: Earth Joker\0", NULL, "Visco", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, earthjkrRomInfo, earthjkrRomName, NULL, NULL, AsukaInputInfo, EarthjkrDIPInfo, + GalmedesInit, TaitoExit, EtoFrame, DrvDraw, DrvScan, NULL, 0x1000, + 240, 320, 3, 4 +}; + + +// Bonze Adventure (World, Newer) + +static struct BurnRomInfo bonzeadvRomDesc[] = { + { "b41-09-1.17", 0x10000, 0xaf821fbc, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b41-11-1.26", 0x10000, 0x823fff00, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b41-10.16", 0x10000, 0x4ca94d77, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "b41-15.25", 0x10000, 0xaed7a0d0, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + { "b41-01.15", 0x80000, 0x5d072fa4, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 4 + + { "b41-13.20", 0x10000, 0x9e464254, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 5 Z80 Code + + { "b41-03.1", 0x80000, 0x736d35d0, BRF_GRA | TAITO_CHARS }, // 6 Characters + + { "b41-02.7", 0x80000, 0x29f205d9, BRF_GRA | TAITO_SPRITESA }, // 7 Sprites + + { "b41-04.48", 0x80000, 0xc668638f, BRF_SND | TAITO_YM2610A }, // 8 YM2610 Samples +}; + +STD_ROM_PICK(bonzeadv) +STD_ROM_FN(bonzeadv) + +static INT32 BonzeInit() +{ + return CommonInit(Bonze68KSetup, BonzeZ80Setup, BonzeSoundSetup, 0); +} + +struct BurnDriver BurnDrvBonzeadv = { + "bonzeadv", NULL, NULL, NULL, "1988", + "Bonze Adventure (World, Newer)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, bonzeadvRomInfo, bonzeadvRomName, NULL, NULL, BonzeadvInputInfo, BonzeadvDIPInfo, + BonzeInit, TaitoExit, BonzeFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Bonze Adventure (World, Older) + +static struct BurnRomInfo bonzeadvoRomDesc[] = { + { "b41-09.17", 0x10000, 0x06818710, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b41-11.26", 0x10000, 0x33c4c2f4, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b41-10.16", 0x10000, 0x4ca94d77, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "b41-15.25", 0x10000, 0xaed7a0d0, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + { "b41-01.15", 0x80000, 0x5d072fa4, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 4 + + { "b41-13.20", 0x10000, 0x9e464254, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 5 Z80 Code + + { "b41-03.1", 0x80000, 0x736d35d0, BRF_GRA | TAITO_CHARS }, // 6 Characters + + { "b41-02.7", 0x80000, 0x29f205d9, BRF_GRA | TAITO_SPRITESA }, // 7 Sprites + + { "b41-04.48", 0x80000, 0xc668638f, BRF_SND | TAITO_YM2610A }, // 8 YM2610 Samples +}; + +STD_ROM_PICK(bonzeadvo) +STD_ROM_FN(bonzeadvo) + +struct BurnDriver BurnDrvBonzeadvo = { + "bonzeadvo", "bonzeadv", NULL, NULL, "1988", + "Bonze Adventure (World, Older)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, bonzeadvoRomInfo, bonzeadvoRomName, NULL, NULL, BonzeadvInputInfo, BonzeadvDIPInfo, + BonzeInit, TaitoExit, BonzeFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Bonze Adventure (US) + +static struct BurnRomInfo bonzeadvuRomDesc[] = { + { "b41-09-1.17", 0x10000, 0xaf821fbc, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b41-11-1.26", 0x10000, 0x823fff00, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b41-10.16", 0x10000, 0x4ca94d77, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "b41-14.25", 0x10000, 0x37def16a, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + { "b41-01.15", 0x80000, 0x5d072fa4, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 4 + + { "b41-13.20", 0x10000, 0x9e464254, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 5 Z80 Code + + { "b41-03.1", 0x80000, 0x736d35d0, BRF_GRA | TAITO_CHARS }, // 6 Characters + + { "b41-02.7", 0x80000, 0x29f205d9, BRF_GRA | TAITO_SPRITESA }, // 7 Sprites + + { "b41-04.48", 0x80000, 0xc668638f, BRF_SND | TAITO_YM2610A }, // 8 YM2610 Samples +}; + +STD_ROM_PICK(bonzeadvu) +STD_ROM_FN(bonzeadvu) + +struct BurnDriver BurnDrvBonzeadvu = { + "bonzeadvu", "bonzeadv", NULL, NULL, "1988", + "Bonze Adventure (US)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, bonzeadvuRomInfo, bonzeadvuRomName, NULL, NULL, BonzeadvInputInfo, JigkmgriDIPInfo, + BonzeInit, TaitoExit, BonzeFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Jigoku Meguri (Japan) + +static struct BurnRomInfo jigkmgriRomDesc[] = { + { "b41-09-1.17", 0x10000, 0xaf821fbc, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 0 68K Code + { "b41-11-1.26", 0x10000, 0x823fff00, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 1 + { "b41-10.16", 0x10000, 0x4ca94d77, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 2 + { "b41-12.25", 0x10000, 0x40d9c1fc, BRF_PRG | BRF_ESS | TAITO_68KROM1_BYTESWAP }, // 3 + { "b41-01.15", 0x80000, 0x5d072fa4, BRF_PRG | BRF_ESS | TAITO_68KROM1 }, // 4 + + { "b41-13.20", 0x10000, 0x9e464254, BRF_PRG | BRF_ESS | TAITO_Z80ROM1 }, // 5 Z80 Code + + { "b41-03.1", 0x80000, 0x736d35d0, BRF_GRA | TAITO_CHARS }, // 6 Characters + + { "b41-02.7", 0x80000, 0x29f205d9, BRF_GRA | TAITO_SPRITESA }, // 7 Sprites + + { "b41-04.48", 0x80000, 0xc668638f, BRF_SND | TAITO_YM2610A }, // 8 YM2610 Samples +}; + +STD_ROM_PICK(jigkmgri) +STD_ROM_FN(jigkmgri) + +struct BurnDriver BurnDrvJigkmgri = { + "jigkmgri", "bonzeadv", NULL, NULL, "1988", + "Jigoku Meguri (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + L"\u5730\u7344\u3081\u3050\u308A (Japan)\0Jigoku Meguri (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, jigkmgriRomInfo, jigkmgriRomName, NULL, NULL, BonzeadvInputInfo, JigkmgriDIPInfo, + BonzeInit, TaitoExit, BonzeFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_bublbobl.cpp b/src/burn/drivers/taito/d_bublbobl.cpp new file mode 100644 index 00000000..abe5d295 --- /dev/null +++ b/src/burn/drivers/taito/d_bublbobl.cpp @@ -0,0 +1,2648 @@ +#include "tiles_generic.h" +#include "m6800_intf.h" +#include "taito_m68705.h" +#include "burn_ym2203.h" +#include "burn_ym3526.h" +#include "bitswap.h" + +static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvDip[2] = {0, 0}; +static UINT8 DrvInput[3] = {0x00, 0x00, 0x00}; +static UINT8 DrvReset = 0; + +static UINT8 *Mem = NULL; +static UINT8 *MemEnd = NULL; +static UINT8 *RamStart = NULL; +static UINT8 *RamEnd = NULL; +static UINT8 *DrvZ80Rom1 = NULL; +static UINT8 *DrvZ80Rom2 = NULL; +static UINT8 *DrvZ80Rom3 = NULL; +static UINT8 *DrvMcuRom = NULL; +static UINT8 *DrvProm = NULL; +static UINT8 *DrvZ80Ram1 = NULL; +static UINT8 *DrvZ80Ram3 = NULL; +static UINT8 *DrvSharedRam = NULL; +static UINT8 *DrvMcuRam = NULL; +static UINT8 *DrvVideoRam = NULL; +static UINT8 *DrvSpriteRam = NULL; +static UINT8 *DrvPaletteRam = NULL; +static UINT8 *DrvTiles = NULL; +static UINT8 *DrvTempRom = NULL; +static UINT32 *DrvPalette = NULL; + +static UINT8 DrvRomBank; +static UINT8 DrvSlaveCPUActive; +static UINT8 DrvSoundCPUActive; +static UINT8 DrvMCUActive; +static UINT8 DrvVideoEnable; +static UINT8 DrvFlipScreen; +static INT32 IC43A; +static INT32 IC43B; +static INT32 DrvSoundStatus; +static INT32 DrvSoundNmiEnable; +static INT32 DrvSoundNmiPending; +static INT32 DrvSoundLatch; + +static INT32 nCyclesDone[4], nCyclesTotal[4]; +static INT32 nCyclesSegment; + +typedef INT32 (*BublboblCallbackFunc)(); +static BublboblCallbackFunc BublboblCallbackFunction; + +static UINT8 DrvMCUInUse; + +static INT32 mcu_address, mcu_latch; +static UINT8 ddr1, ddr2, ddr3, ddr4; +static UINT8 port1_in, port2_in, port3_in, port4_in; +static UINT8 port1_out, port2_out, port3_out, port4_out; + +static struct BurnInputInfo BublboblInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort2 + 6, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 5, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 4, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , DrvInputPort2 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort2 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort2 + 5, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort2 + 4, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort0 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , DrvInputPort0 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Bublbobl) + +static struct BurnInputInfo BoblboblInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 2, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 6, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &DrvReset , "reset" }, + {"Service" , BIT_DIGITAL , DrvInputPort1 + 3, "service" }, + {"Tilt" , BIT_DIGITAL , DrvInputPort1 + 2, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" }, +}; + +STDINPUTINFO(Boblbobl) + +static inline void BublboblMakeInputs() +{ + DrvInput[0] = 0xf3; + if (DrvInputPort0[0]) DrvInput[0] -= 0x01; + if (DrvInputPort0[1]) DrvInput[0] -= 0x02; + if (DrvInputPort0[2]) DrvInput[0] |= 0x04; + if (DrvInputPort0[3]) DrvInput[0] |= 0x08; + if (DrvInputPort0[4]) DrvInput[0] -= 0x10; + if (DrvInputPort0[5]) DrvInput[0] -= 0x20; + if (DrvInputPort0[6]) DrvInput[0] -= 0x40; + if (DrvInputPort0[7]) DrvInput[0] -= 0x80; + + DrvInput[1] = 0xff; + DrvInput[2] = 0xff; + for (INT32 i = 0; i < 8; i++) { + DrvInput[1] -= (DrvInputPort1[i] & 1) << i; + DrvInput[2] -= (DrvInputPort2[i] & 1) << i; + } +} + +static struct BurnDIPInfo BublboblDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xfe, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Mode" }, + {0x0f, 0x01, 0x05, 0x04, "Game, English" }, + {0x0f, 0x01, 0x05, 0x05, "Game, Japanese" }, + {0x0f, 0x01, 0x05, 0x01, "Test (Grid and Inputs)" }, + {0x0f, 0x01, 0x05, 0x00, "Test (RAM and Sound)/Pause"}, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Normal" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x0c, 0x08, "20k 80k 300k" }, + {0x10, 0x01, 0x0c, 0x0c, "30k 100k 400k" }, + {0x10, 0x01, 0x0c, 0x04, "40k 200k 500k" }, + {0x10, 0x01, 0x0c, 0x00, "50k 250k 500k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "ROM Type" }, + {0x10, 0x01, 0x80, 0x80, "IC52=512kb, IC53=none" }, + {0x10, 0x01, 0x80, 0x00, "IC52=256kb, IC53=256kb" }, +}; + +STDDIPINFO(Bublbobl) + +static struct BurnDIPInfo BoblboblDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xfe, NULL }, + {0x10, 0xff, 0xff, 0x3f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Mode" }, + {0x0f, 0x01, 0x05, 0x04, "Game, English" }, + {0x0f, 0x01, 0x05, 0x05, "Game, Japanese" }, + {0x0f, 0x01, 0x05, 0x01, "Test (Grid and Inputs)" }, + {0x0f, 0x01, 0x05, 0x00, "Test (RAM and Sound)" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Normal" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x0c, 0x08, "20k 80k 300k" }, + {0x10, 0x01, 0x0c, 0x0c, "30k 100k 400k" }, + {0x10, 0x01, 0x0c, 0x04, "40k 200k 500k" }, + {0x10, 0x01, 0x0c, 0x00, "50k 250k 500k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4 , "Monster Speed" }, + {0x10, 0x01, 0xc0, 0x00, "Normal" }, + {0x10, 0x01, 0xc0, 0x40, "Medium" }, + {0x10, 0x01, 0xc0, 0x80, "High" }, + {0x10, 0x01, 0xc0, 0xc0, "Very High" }, +}; + +STDDIPINFO(Boblbobl) + +static struct BurnDIPInfo SboblbobDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xfe, NULL }, + {0x10, 0xff, 0xff, 0x3f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Game" }, + {0x0f, 0x01, 0x01, 0x01, "Bobble Bobble" }, + {0x0f, 0x01, 0x01, 0x00, "Super Bobble Bobble" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Normal" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x0c, 0x08, "20k 80k 300k" }, + {0x10, 0x01, 0x0c, 0x0c, "30k 100k 400k" }, + {0x10, 0x01, 0x0c, 0x04, "40k 200k 500k" }, + {0x10, 0x01, 0x0c, 0x00, "50k 250k 500k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 4 , "Monster Speed" }, + {0x10, 0x01, 0xc0, 0x00, "Normal" }, + {0x10, 0x01, 0xc0, 0x40, "Medium" }, + {0x10, 0x01, 0xc0, 0x80, "High" }, + {0x10, 0x01, 0xc0, 0xc0, "Very High" }, +}; + +STDDIPINFO(Sboblbob) + +static struct BurnDIPInfo DlandDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0x3f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Game" }, + {0x0f, 0x01, 0x01, 0x01, "Dream Land" }, + {0x0f, 0x01, 0x01, 0x00, "Super Dream Land" }, + + {0 , 0xfe, 0 , 4 , "Mode" }, + {0x0f, 0x01, 0x05, 0x04, "Game, English" }, + {0x0f, 0x01, 0x05, 0x05, "Game, Japanese" }, + {0x0f, 0x01, 0x05, 0x01, "Test (Grid and Inputs)" }, + {0x0f, 0x01, 0x05, 0x00, "Test (RAM and Sound)" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x00, "Off" }, + {0x0f, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Play" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Play" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Plays" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Play" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Play" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Plays" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Plays" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Normal" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Very Hard" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x10, 0x01, 0x0c, 0x08, "20k 80k 300k" }, + {0x10, 0x01, 0x0c, 0x0c, "30k 100k 400k" }, + {0x10, 0x01, 0x0c, 0x04, "40k 200k 500k" }, + {0x10, 0x01, 0x0c, 0x00, "50k 250k 500k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "100 (Cheat)" }, + + {0 , 0xfe, 0 , 4 , "Monster Speed" }, + {0x10, 0x01, 0xc0, 0x00, "Normal" }, + {0x10, 0x01, 0xc0, 0x40, "Medium" }, + {0x10, 0x01, 0xc0, 0x80, "High" }, + {0x10, 0x01, 0xc0, 0xc0, "Very High" }, +}; + +STDDIPINFO(Dland) + +static struct BurnInputInfo TokioInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvInputPort0 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvInputPort1 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvInputPort1 + 3, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvInputPort1 + 2, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvInputPort1 + 0, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvInputPort1 + 1, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvInputPort1 + 5, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvInputPort1 + 4, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvInputPort0 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvInputPort2 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvInputPort2 + 3, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvInputPort2 + 2, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvInputPort2 + 0, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvInputPort2 + 1, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvInputPort2 + 5, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvInputPort2 + 4, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvInputPort0 + 1, "service" }, + {"Tilt", BIT_DIGITAL, DrvInputPort0 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" }, +}; + +STDINPUTINFO(Tokio) + +static struct BurnDIPInfo TokioDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0x7e, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 2, "Enemies" }, + {0x14, 0x01, 0x01, 0x01, "Few (Easy)" }, + {0x14, 0x01, 0x01, 0x00, "Many (Hard)" }, + + {0 , 0xfe, 0 , 2, "Enemy Shots" }, + {0x14, 0x01, 0x02, 0x02, "Few (Easy)" }, + {0x14, 0x01, 0x02, 0x00, "Many (Hard)" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100K 400K" }, + {0x14, 0x01, 0x0c, 0x08, "200K 400K" }, + {0x14, 0x01, 0x0c, 0x04, "300K 400K" }, + {0x14, 0x01, 0x0c, 0x00, "400K 400K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "99 (Cheat)" }, + + {0 , 0xfe, 0 , 0, "Language" }, + {0x14, 0x01, 0x80, 0x00, "English" }, + {0x14, 0x01, 0x80, 0x80, "Japanese" }, +}; + +STDDIPINFO(Tokio) + +static struct BurnRomInfo BublboblRomDesc[] = { + { "a78-06-1.51", 0x08000, 0x567934b6, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a78-05-1.52", 0x10000, 0x9f8ee242, BRF_ESS | BRF_PRG }, // 1 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 3 Z80 #3 Program + + { "a78-01.17", 0x01000, 0xb1bfb53d, BRF_ESS | BRF_PRG }, // 4 MCU Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 18 PLDs + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 19 + { "pal16r4.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(Bublbobl) +STD_ROM_FN(Bublbobl) + +static struct BurnRomInfo Bublbob1RomDesc[] = { + { "a78-06.51", 0x08000, 0x32c8305b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a78-05.52", 0x10000, 0x53f4bc6e, BRF_ESS | BRF_PRG }, // 1 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 3 Z80 #3 Program + + { "a78-01.17", 0x01000, 0xb1bfb53d, BRF_ESS | BRF_PRG }, // 4 MCU Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 18 PLDs + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 19 + { "pal16r4.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(Bublbob1) +STD_ROM_FN(Bublbob1) + +static struct BurnRomInfo BublbobrRomDesc[] = { + { "a78-25.51", 0x08000, 0x2d901c9d, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a78-24.52", 0x10000, 0xb7afedc4, BRF_ESS | BRF_PRG }, // 1 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 3 Z80 #3 Program + + { "a78-01.17", 0x01000, 0xb1bfb53d, BRF_ESS | BRF_PRG }, // 4 MCU Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 18 PLDs + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 19 + { "pal16r4.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(Bublbobr) +STD_ROM_FN(Bublbobr) + +static struct BurnRomInfo Bubbobr1RomDesc[] = { + { "a78-06.51", 0x08000, 0x32c8305b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a78-21.52", 0x10000, 0x2844033d, BRF_ESS | BRF_PRG }, // 1 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 2 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 3 Z80 #3 Program + + { "a78-01.17", 0x01000, 0xb1bfb53d, BRF_ESS | BRF_PRG }, // 4 MCU Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 18 PLDs + { "pal16l8.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 19 + { "pal16r4.bin", 0x00001, 0x00000000, BRF_OPT | BRF_NODUMP }, // 20 +}; + +STD_ROM_PICK(Bubbobr1) +STD_ROM_FN(Bubbobr1) + +static struct BurnRomInfo BoblboblRomDesc[] = { + { "bb3", 0x08000, 0x01f81936, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bb5", 0x08000, 0x13118eb1, BRF_ESS | BRF_PRG }, // 1 + { "bb4", 0x08000, 0xafda99d8, BRF_ESS | BRF_PRG }, // 2 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "pal16r4.u36", 0x00104, 0x22fe26ac, BRF_OPT }, // 18 PLDs + { "pal16l8.u38", 0x00104, 0xc02d9663, BRF_OPT }, // 19 + { "pal16l8.u4", 0x00104, 0x077d20a8, BRF_OPT }, // 20 +}; + +STD_ROM_PICK(Boblbobl) +STD_ROM_FN(Boblbobl) + +static struct BurnRomInfo SboblboaRomDesc[] = { + { "1c.bin", 0x08000, 0xf304152a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "1a.bin", 0x08000, 0x0865209c, BRF_ESS | BRF_PRG }, // 1 + { "1b.bin", 0x08000, 0x1f29b5c0, BRF_ESS | BRF_PRG }, // 2 + + { "1e.rom", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "1d.rom", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program + + { "1l.rom", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "1m.rom", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "1n.rom", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "1o.rom", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "1p.rom", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "1q.rom", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "1f.rom", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "1g.rom", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "1h.rom", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "1i.rom", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "1j.rom", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "1k.rom", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs +}; + +STD_ROM_PICK(Sboblboa) +STD_ROM_FN(Sboblboa) + +static struct BurnRomInfo SboblbobRomDesc[] = { + { "bbb-3.rom", 0x08000, 0xf304152a, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "bb5", 0x08000, 0x13118eb1, BRF_ESS | BRF_PRG }, // 1 + { "bbb-4.rom", 0x08000, 0x94c75591, BRF_ESS | BRF_PRG }, // 2 + + { "a78-08.37", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "a78-07.46", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs +}; + +STD_ROM_PICK(Sboblbob) +STD_ROM_FN(Sboblbob) + +static struct BurnRomInfo Bub68705RomDesc[] = { + { "2.bin", 0x08000, 0x32c8305b, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "3-1.bin", 0x08000, 0x980c2615, BRF_ESS | BRF_PRG }, // 1 + { "3.bin", 0x08000, 0xe6c698f2, BRF_ESS | BRF_PRG }, // 2 + + { "4.bin", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "1.bin", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program + + { "a78-09.12", 0x08000, 0x20358c22, BRF_GRA }, // 5 Tiles + { "a78-10.13", 0x08000, 0x930168a9, BRF_GRA }, // 6 + { "a78-11.14", 0x08000, 0x9773e512, BRF_GRA }, // 7 + { "a78-12.15", 0x08000, 0xd045549b, BRF_GRA }, // 8 + { "a78-13.16", 0x08000, 0xd0af35c5, BRF_GRA }, // 9 + { "a78-14.17", 0x08000, 0x7b5369a8, BRF_GRA }, // 10 + { "a78-15.30", 0x08000, 0x6b61a413, BRF_GRA }, // 11 + { "a78-16.31", 0x08000, 0xb5492d97, BRF_GRA }, // 12 + { "a78-17.32", 0x08000, 0xd69762d5, BRF_GRA }, // 13 + { "a78-18.33", 0x08000, 0x9f243b68, BRF_GRA }, // 14 + { "a78-19.34", 0x08000, 0x66e9438c, BRF_GRA }, // 15 + { "a78-20.35", 0x08000, 0x9ef863ad, BRF_GRA }, // 16 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 17 PROMs + + { "68705.bin", 0x00800, 0x78caa635, BRF_ESS | BRF_PRG }, // 18 68705 Program Code +}; + +STD_ROM_PICK(Bub68705) +STD_ROM_FN(Bub68705) + + + +static struct BurnRomInfo DlandRomDesc[] = { + { "dl_3.u69", 0x08000, 0x01eb3e4f, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "dl_5.u67", 0x08000, 0x75740b61, BRF_ESS | BRF_PRG }, // 1 + { "dl_4.u68", 0x08000, 0xc6a3776f, BRF_ESS | BRF_PRG }, // 2 + + { "dl_1.u42", 0x08000, 0xae11a07b, BRF_ESS | BRF_PRG }, // 3 Z80 #2 Program + + { "dl_2.u74", 0x08000, 0x4f9a26e8, BRF_ESS | BRF_PRG }, // 4 Z80 #3 Program + + { "dl_6.58", 0x10000, 0x6352d3fa, BRF_GRA }, // 5 Tiles + { "dl_7.59", 0x10000, 0x37a38b69, BRF_GRA }, // 6 + { "dl_8.60", 0x10000, 0x509ee5b1, BRF_GRA }, // 7 + { "dl_9.61", 0x10000, 0xae8514d7, BRF_GRA }, // 8 + { "dl_10.62", 0x10000, 0x6d406fb7, BRF_GRA }, // 9 + { "dl_11.63", 0x10000, 0xbdf9c0ab, BRF_GRA }, // 10 + + { "a71-25.41", 0x00100, 0x2d0f8545, BRF_GRA }, // 11 PROMs +}; + +STD_ROM_PICK(Dland) +STD_ROM_FN(Dland) + + +static struct BurnRomInfo tokioRomDesc[] = { + { "a71-02-1.ic4", 0x8000, 0xBB8DABD7, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program + { "a71-03-1.ic5", 0x8000, 0xEE49B383, BRF_ESS | BRF_PRG }, // 1 + { "a71-04.ic6", 0x8000, 0xa0a4ce0e, BRF_ESS | BRF_PRG }, // 2 + { "a71-05.ic7", 0x8000, 0x6da0b945, BRF_ESS | BRF_PRG }, // 3 + { "a71-06-1.ic8", 0x8000, 0x56927b3f, BRF_ESS | BRF_PRG }, // 4 + + { "a71-01.ic1", 0x8000, 0x0867c707, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "a71-07.ic10", 0x8000, 0xf298cc7b, BRF_ESS | BRF_PRG }, // 6 Z80 #3 Program + + { "a71-08.ic12", 0x8000, 0x0439ab13, BRF_GRA }, // 7 Tiles + { "a71-09.ic13", 0x8000, 0xedb3d2ff, BRF_GRA }, // 8 + { "a71-10.ic14", 0x8000, 0x69f0888c, BRF_GRA }, // 9 + { "a71-11.ic15", 0x8000, 0x4ae07c31, BRF_GRA }, // 10 + { "a71-12.ic16", 0x8000, 0x3f6bd706, BRF_GRA }, // 11 + { "a71-13.ic17", 0x8000, 0xf2c92aaa, BRF_GRA }, // 12 + { "a71-14.ic18", 0x8000, 0xc574b7b2, BRF_GRA }, // 13 + { "a71-15.ic19", 0x8000, 0x12d87e7f, BRF_GRA }, // 14 + { "a71-16.ic30", 0x8000, 0x0bce35b6, BRF_GRA }, // 15 + { "a71-17.ic31", 0x8000, 0xdeda6387, BRF_GRA }, // 16 + { "a71-18.ic32", 0x8000, 0x330cd9d7, BRF_GRA }, // 17 + { "a71-19.ic33", 0x8000, 0xfc4b29e0, BRF_GRA }, // 18 + { "a71-20.ic34", 0x8000, 0x65acb265, BRF_GRA }, // 19 + { "a71-21.ic35", 0x8000, 0x33cde9b2, BRF_GRA }, // 20 + { "a71-22.ic36", 0x8000, 0xfb98eac0, BRF_GRA }, // 21 + { "a71-23.ic37", 0x8000, 0x30bd46ad, BRF_GRA }, // 22 + + { "a71-25.ic41", 0x0100, 0x2d0f8545, BRF_GRA }, // 23 PROMs + + { "a71-24.ic57", 0x0800, 0x00000000, 6 | BRF_NODUMP }, // 24 Mcu Code + + { "a71-26.ic19", 0x0117, 0x4e1f119c, 7 | BRF_OPT }, // 25 PLDs +}; + +STD_ROM_PICK(tokio) +STD_ROM_FN(tokio) + +static struct BurnRomInfo tokiooRomDesc[] = { + { "a71-02.ic4", 0x8000, 0xd556c908, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program + { "a71-03.ic5", 0x8000, 0x69dacf44, BRF_ESS | BRF_PRG }, // 1 + { "a71-04.ic6", 0x8000, 0xa0a4ce0e, BRF_ESS | BRF_PRG }, // 2 + { "a71-05.ic7", 0x8000, 0x6da0b945, BRF_ESS | BRF_PRG }, // 3 + { "a71-06.ic8", 0x8000, 0x447d6779, BRF_ESS | BRF_PRG }, // 4 + + { "a71-01.ic1", 0x8000, 0x0867c707, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "a71-07.ic10", 0x8000, 0xf298cc7b, BRF_ESS | BRF_PRG }, // 6 Z80 #3 Program + + { "a71-08.ic12", 0x8000, 0x0439ab13, BRF_GRA }, // 7 Tiles + { "a71-09.ic13", 0x8000, 0xedb3d2ff, BRF_GRA }, // 8 + { "a71-10.ic14", 0x8000, 0x69f0888c, BRF_GRA }, // 9 + { "a71-11.ic15", 0x8000, 0x4ae07c31, BRF_GRA }, // 10 + { "a71-12.ic16", 0x8000, 0x3f6bd706, BRF_GRA }, // 11 + { "a71-13.ic17", 0x8000, 0xf2c92aaa, BRF_GRA }, // 12 + { "a71-14.ic18", 0x8000, 0xc574b7b2, BRF_GRA }, // 13 + { "a71-15.ic19", 0x8000, 0x12d87e7f, BRF_GRA }, // 14 + { "a71-16.ic30", 0x8000, 0x0bce35b6, BRF_GRA }, // 15 + { "a71-17.ic31", 0x8000, 0xdeda6387, BRF_GRA }, // 16 + { "a71-18.ic32", 0x8000, 0x330cd9d7, BRF_GRA }, // 17 + { "a71-19.ic33", 0x8000, 0xfc4b29e0, BRF_GRA }, // 18 + { "a71-20.ic34", 0x8000, 0x65acb265, BRF_GRA }, // 19 + { "a71-21.ic35", 0x8000, 0x33cde9b2, BRF_GRA }, // 20 + { "a71-22.ic36", 0x8000, 0xfb98eac0, BRF_GRA }, // 21 + { "a71-23.ic37", 0x8000, 0x30bd46ad, BRF_GRA }, // 22 + + { "a71-25.ic41", 0x0100, 0x2d0f8545, BRF_GRA }, // 23 PROMs + + { "a71-24.ic57", 0x0800, 0x00000000, 6 | BRF_NODUMP }, // 24 Mcu Code + + { "a71-26.ic19", 0x0117, 0x4e1f119c, 7 | BRF_OPT }, // 25 PLDs +}; + +STD_ROM_PICK(tokioo) +STD_ROM_FN(tokioo) + +static struct BurnRomInfo tokiouRomDesc[] = { + { "a71-27-1.ic4", 0x8000, 0x8c180896, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a71-28-1.ic5", 0x8000, 0x1b447527, BRF_ESS | BRF_PRG }, // 1 + { "a71-04.ic6", 0x8000, 0xa0a4ce0e, BRF_ESS | BRF_PRG }, // 2 + { "a71-05.ic7", 0x8000, 0x6da0b945, BRF_ESS | BRF_PRG }, // 3 + { "a71-06-1.ic8", 0x8000, 0x56927b3f, BRF_ESS | BRF_PRG }, // 4 + + { "a71-01.ic1", 0x8000, 0x0867c707, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "a71-07.ic10", 0x8000, 0xf298cc7b, BRF_ESS | BRF_PRG }, // 6 Z80 #3 Program + + { "a71-08.ic12", 0x8000, 0x0439ab13, BRF_GRA }, // 7 Tiles + { "a71-09.ic13", 0x8000, 0xedb3d2ff, BRF_GRA }, // 8 + { "a71-10.ic14", 0x8000, 0x69f0888c, BRF_GRA }, // 9 + { "a71-11.ic15", 0x8000, 0x4ae07c31, BRF_GRA }, // 10 + { "a71-12.ic16", 0x8000, 0x3f6bd706, BRF_GRA }, // 11 + { "a71-13.ic17", 0x8000, 0xf2c92aaa, BRF_GRA }, // 12 + { "a71-14.ic18", 0x8000, 0xc574b7b2, BRF_GRA }, // 13 + { "a71-15.ic19", 0x8000, 0x12d87e7f, BRF_GRA }, // 14 + { "a71-16.ic30", 0x8000, 0x0bce35b6, BRF_GRA }, // 15 + { "a71-17.ic31", 0x8000, 0xdeda6387, BRF_GRA }, // 16 + { "a71-18.ic32", 0x8000, 0x330cd9d7, BRF_GRA }, // 17 + { "a71-19.ic33", 0x8000, 0xfc4b29e0, BRF_GRA }, // 18 + { "a71-20.ic34", 0x8000, 0x65acb265, BRF_GRA }, // 19 + { "a71-21.ic35", 0x8000, 0x33cde9b2, BRF_GRA }, // 20 + { "a71-22.ic36", 0x8000, 0xfb98eac0, BRF_GRA }, // 21 + { "a71-23.ic37", 0x8000, 0x30bd46ad, BRF_GRA }, // 22 + + { "a71-25.ic41", 0x0100, 0x2d0f8545, BRF_GRA }, // 23 PROMs + + { "a71-24.ic57", 0x0800, 0x00000000, 6 | BRF_NODUMP }, // 24 Mcu Code + + { "a71-26.ic19", 0x0117, 0x4e1f119c, 7 | BRF_OPT }, // 25 PLDs +}; + +STD_ROM_PICK(tokiou) +STD_ROM_FN(tokiou) + +static struct BurnRomInfo tokiobRomDesc[] = { + { "2.ic4", 0x8000, 0xf583b1ef, BRF_ESS | BRF_PRG }, // 0 Z80 #1 Program Code + { "a71-03.ic5", 0x8000, 0x69dacf44, BRF_ESS | BRF_PRG }, // 1 + { "a71-04.ic6", 0x8000, 0xa0a4ce0e, BRF_ESS | BRF_PRG }, // 2 + { "a71-05.ic7", 0x8000, 0x6da0b945, BRF_ESS | BRF_PRG }, // 3 + { "6.ic8", 0x8000, 0x1490e95b, BRF_ESS | BRF_PRG }, // 4 + + { "a71-01.ic1", 0x8000, 0x0867c707, BRF_ESS | BRF_PRG }, // 5 Z80 #2 Program + + { "a71-07.ic10", 0x8000, 0xf298cc7b, BRF_ESS | BRF_PRG }, // 6 Z80 #3 Program + + { "a71-08.ic12", 0x8000, 0x0439ab13, BRF_GRA }, // 7 Tiles + { "a71-09.ic13", 0x8000, 0xedb3d2ff, BRF_GRA }, // 8 + { "a71-10.ic14", 0x8000, 0x69f0888c, BRF_GRA }, // 9 + { "a71-11.ic15", 0x8000, 0x4ae07c31, BRF_GRA }, // 10 + { "a71-12.ic16", 0x8000, 0x3f6bd706, BRF_GRA }, // 11 + { "a71-13.ic17", 0x8000, 0xf2c92aaa, BRF_GRA }, // 12 + { "a71-14.ic18", 0x8000, 0xc574b7b2, BRF_GRA }, // 13 + { "a71-15.ic19", 0x8000, 0x12d87e7f, BRF_GRA }, // 14 + { "a71-16.ic30", 0x8000, 0x0bce35b6, BRF_GRA }, // 15 + { "a71-17.ic31", 0x8000, 0xdeda6387, BRF_GRA }, // 16 + { "a71-18.ic32", 0x8000, 0x330cd9d7, BRF_GRA }, // 17 + { "a71-19.ic33", 0x8000, 0xfc4b29e0, BRF_GRA }, // 18 + { "a71-20.ic34", 0x8000, 0x65acb265, BRF_GRA }, // 19 + { "a71-21.ic35", 0x8000, 0x33cde9b2, BRF_GRA }, // 20 + { "a71-22.ic36", 0x8000, 0xfb98eac0, BRF_GRA }, // 21 + { "a71-23.ic37", 0x8000, 0x30bd46ad, BRF_GRA }, // 22 + + { "a71-25.ic41", 0x0100, 0x2d0f8545, BRF_GRA }, // 23 PROMs +}; + +STD_ROM_PICK(tokiob) +STD_ROM_FN(tokiob) + + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + + DrvZ80Rom1 = Next; Next += 0x30000; + DrvZ80Rom2 = Next; Next += 0x08000; + DrvZ80Rom3 = Next; Next += 0x0a000; + DrvProm = Next; Next += 0x00100; + if (DrvMCUInUse) { + DrvMcuRom = Next; Next += 0x01000; + } + + RamStart = Next; + + DrvPaletteRam = Next; Next += 0x00200; + DrvVideoRam = Next; Next += 0x01d00; + DrvZ80Ram1 = Next; Next += 0x00400; + DrvZ80Ram3 = Next; Next += 0x01000; + DrvSharedRam = Next; Next += 0x01800; + DrvMcuRam = Next; Next += 0x000c0; + DrvSpriteRam = Next; Next += 0x00300; + + RamEnd = Next; + + DrvTiles = Next; Next += 0x4000 * 8 * 8; + DrvPalette = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvDoReset() +{ + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + if (DrvMCUInUse == 1) { + M6801Reset(); + } else if (DrvMCUInUse == 2) { + m67805_taito_reset(); + } + + BurnYM3526Reset(); + BurnYM2203Reset(); + + DrvRomBank = 0; + DrvSlaveCPUActive = 0; + DrvSoundCPUActive = 0; + DrvMCUActive = 0; + DrvVideoEnable = 0; + DrvFlipScreen = 0; + IC43A = 0; + IC43B = 0; + DrvSoundStatus = 0; + DrvSoundNmiEnable = 0; + DrvSoundNmiPending = 0; + DrvSoundLatch = 0; + mcu_latch = 0; + mcu_address = 0; + + return 0; +} + +static INT32 TokioDoReset() +{ + for (INT32 i = 0; i < 3; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + BurnYM2203Reset(); + + DrvRomBank = 0; + DrvVideoEnable = 1; + DrvFlipScreen = 0; + DrvSoundStatus = 0; + DrvSoundNmiEnable = 0; + DrvSoundNmiPending = 0; + DrvSoundLatch = 0; + + return 0; +} + +UINT8 __fastcall BublboblRead1(UINT16 a) +{ + switch (a) { + case 0xfa00: { + return DrvSoundStatus; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall BublboblWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfa00: { + DrvSoundLatch = d; + DrvSoundNmiPending = 1; + return; + } + + case 0xfa03: { + if (d) { + ZetClose(); + ZetOpen(2); + ZetReset(); + ZetClose(); + ZetOpen(0); + DrvSoundCPUActive = 0; + } else { + DrvSoundCPUActive = 1; + } + return; + } + + case 0xfa80: { + // watchdog reset + return; + } + case 0xfb40: { + DrvRomBank = (d ^ 0x04) & 0x07; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + + if (!(d & 0x10)) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + DrvSlaveCPUActive = 0; + } else { + DrvSlaveCPUActive = 1; + } + + if (!(d & 0x20)) { + if (DrvMCUInUse == 2) { + m67805_taito_reset(); + } else { + M6801Reset(); + } + DrvMCUActive = 0; + } else { + DrvMCUActive = 1; + } + + DrvVideoEnable = d & 0x40; + DrvFlipScreen = d & 0x80; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall BoblboblRead1(UINT16 a) +{ + switch (a) { + case 0xfe00: { + return IC43A << 4; + } + + case 0xfe01: + case 0xfe02: + case 0xfe03: { + return rand() & 0xff; + } + + case 0xfe80: { + return IC43B << 4; + } + + case 0xfe81: + case 0xfe82: + case 0xfe83: { + return 0xff; + } + + case 0xff00: { + return DrvDip[0]; + } + + case 0xff01: { + return DrvDip[1]; + } + + case 0xff02: { + return DrvInput[0]; + } + + case 0xff03: { + return DrvInput[1]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall BoblboblWrite1(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xfa00: { + DrvSoundLatch = d; + DrvSoundNmiPending = 1; + return; + } + + case 0xfa03: { + if (d) { + ZetClose(); + ZetOpen(2); + ZetReset(); + ZetClose(); + ZetOpen(0); + DrvSoundCPUActive = 0; + } else { + DrvSoundCPUActive = 1; + } + return; + } + + case 0xfa80: { + // nop + return; + } + + case 0xfb40: { + DrvRomBank = (d ^ 0x04) & 0x07; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + + if (!(d & 0x10)) { + ZetClose(); + ZetOpen(1); + ZetReset(); + ZetClose(); + ZetOpen(0); + DrvSlaveCPUActive = 0; + } else { + DrvSlaveCPUActive = 1; + } + + DrvVideoEnable = d & 0x40; + DrvFlipScreen = d & 0x80; + return; + } + + case 0xfe00: + case 0xfe01: + case 0xfe02: + case 0xfe03: { + INT32 Res = 0; + INT32 Offset = a - 0xfe00; + + switch (Offset) { + case 0x00: { + if (~IC43A & 8) Res ^= 1; + if (~IC43A & 1) Res ^= 2; + if (~IC43A & 1) Res ^= 4; + if (~IC43A & 2) Res ^= 4; + if (~IC43A & 4) Res ^= 8; + break; + } + + case 0x01: { + if (~IC43A & 8) Res ^= 1; + if (~IC43A & 2) Res ^= 1; + if (~IC43A & 8) Res ^= 2; + if (~IC43A & 1) Res ^= 4; + if (~IC43A & 4) Res ^= 8; + break; + } + + case 0x02: { + if (~IC43A & 4) Res ^= 1; + if (~IC43A & 8) Res ^= 2; + if (~IC43A & 2) Res ^= 4; + if (~IC43A & 1) Res ^= 8; + if (~IC43A & 4) Res ^= 8; + break; + } + + case 0x03: { + if (~IC43A & 2) Res ^= 1; + if (~IC43A & 4) Res ^= 2; + if (~IC43A & 8) Res ^= 2; + if (~IC43A & 8) Res ^= 4; + if (~IC43A & 1) Res ^= 8; + break; + } + } + + IC43A = Res; + return; + } + + case 0xfe80: + case 0xfe81: + case 0xfe82: + case 0xfe83: { + INT32 Offset = a - 0xfe80; + static const INT32 XorVal[4] = { 4, 1, 8, 2 }; + + IC43B = (d >> 4) ^ XorVal[Offset]; + return; + } + + case 0xff94: + case 0xff98: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #1 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall DrvSoundRead3(UINT16 a) +{ + switch (a) { + case 0x9000: { + return BurnYM2203Read(0, 0); + } + + case 0x9001: { + return BurnYM2203Read(0, 1); + } + + case 0xa000: { + return BurnYM3526Read(0); + } + + case 0xb000: { + return DrvSoundLatch; + } + + case 0xb001: { + // nop + return 0; + } + + case 0xe000: { + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall DrvSoundWrite3(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x9001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xa000: { + BurnYM3526Write(0, d); + return; + } + + case 0xa001: { + BurnYM3526Write(1, d); + return; + } + + case 0xb000: { + DrvSoundStatus = d; + return; + } + + case 0xb001: { + DrvSoundNmiEnable = 1; + if (DrvSoundNmiPending) { + ZetNmi(); + DrvSoundNmiPending = 0; + } + return; + } + + case 0xb002: { + DrvSoundNmiEnable = 0; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #3 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 BublboblMcuReadByte(UINT16 Address) +{ + if (Address >= 0x0040 && Address <= 0x00ff) { + return DrvMcuRam[Address - 0x0040]; + } + + switch (Address) { + case 0x00: { + return ddr1; + } + + case 0x01: { + return ddr2; + } + + case 0x02: { + port1_in = DrvInput[0]; + return (port1_out & ddr1) | (port1_in & ~ddr1); + } + + case 0x03: { + return (port2_out & ddr2) | (port2_in & ~ddr2); + } + + case 0x04: { + return ddr3; + } + + case 0x05: { + return ddr4; + } + + case 0x06: { + return (port3_out & ddr3) | (port3_in & ~ddr3); + } + + case 0x07: { + return (port4_out & ddr4) | (port4_in & ~ddr4); + } + } + + bprintf(PRINT_NORMAL, _T("M6801 Read Byte -> %04X\n"), Address); + + return 0; +} + +void BublboblMcuWriteByte(UINT16 Address, UINT8 Data) +{ + if (Address >= 0x0040 && Address <= 0x00ff) { + DrvMcuRam[Address - 0x0040] = Data; + return; + } + + if (Address > 7 && Address <= 0x001f) { + m6803_internal_registers_w(Address, Data); + if (Address > 7) return; + } + + switch (Address) { + case 0x00: { + ddr1 = Data; + return; + } + + case 0x01: { + ddr2 = Data; + return; + } + + case 0x02: { + if ((port1_out & 0x40) && (~Data & 0x40)) { + ZetOpen(0); + ZetSetVector(DrvZ80Ram1[0]); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + } + + port1_out = Data; + return; + } + + case 0x03: { + if ((~port2_out & 0x10) && (Data & 0x10)) { + INT32 nAddress = port4_out | ((Data & 0x0f) << 8); + + if (port1_out & 0x80) { + if (nAddress == 0x0000) port3_in = DrvDip[0]; + if (nAddress == 0x0001) port3_in = DrvDip[1]; + if (nAddress == 0x0002) port3_in = DrvInput[1]; + if (nAddress == 0x0003) port3_in = DrvInput[2]; + + if (nAddress >= 0x0c00 && nAddress <= 0x0fff) port3_in = DrvZ80Ram1[nAddress - 0x0c00]; + } else { + if (nAddress >= 0x0c00 && nAddress <= 0x0fff) DrvZ80Ram1[nAddress - 0x0c00] = port3_out; + } + } + + port2_out = Data; + return; + } + + case 0x04: { + ddr3 = Data; + return; + } + + case 0x05: { + ddr4 = Data; + return; + } + + case 0x06: { + port3_out = Data; + return; + } + + case 0x07: { + port4_out = Data; + return; + } + } + + bprintf(PRINT_NORMAL, _T("M6801 Write Byte -> %04X, %02X\n"), Address, Data); +} + +void bublbobl_68705_portB_out(UINT8 *bytevalue) +{ + INT32 data = *bytevalue;//lazy + + if ((ddrB & 0x01) && (~data & 0x01) && (portB_out & 0x01)) + { + portA_in = mcu_latch; + } + if ((ddrB & 0x02) && (data & 0x02) && (~portB_out & 0x02)) + { + mcu_address = (mcu_address & 0xff00) | portA_out; + } + if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04)) + { + mcu_address = (mcu_address & 0x00ff) | ((portA_out & 0x0f) << 8); + } + if ((ddrB & 0x10) && (~data & 0x10) && (portB_out & 0x10)) + { + if (data & 0x08) /* read */ + { + if ((mcu_address & 0x0800) == 0x0000) + { + switch (mcu_address & 3) { + case 0: mcu_latch = DrvDip[0]; break; + case 1: mcu_latch = DrvDip[1]; break; + case 2: mcu_latch = DrvInput[1]; break; + case 3: mcu_latch = DrvInput[2]; break; + } + } + else if ((mcu_address & 0x0c00) == 0x0c00) + { + mcu_latch = DrvZ80Ram1[mcu_address & 0x03ff]; + } + } + else + { + if ((mcu_address & 0x0c00) == 0x0c00) + { + DrvZ80Ram1[mcu_address & 0x03ff] = portA_out; + } + } + } + if ((ddrB & 0x20) && (~data & 0x20) && (portB_out & 0x20)) + { + ZetOpen(0); + + /* hack to get random EXTEND letters (who is supposed to do this? 68705? PAL?) */ + DrvZ80Ram1[0x7c] = (ZetTotalCycles() ^ ZetPc(-1)) % 6; + + ZetSetVector(DrvZ80Ram1[0]); + ZetSetIRQLine(0, ZET_IRQSTATUS_AUTO); + ZetClose(); + } +} + +static void bublbobl_68705_portC_in() +{ + portC_out = DrvInput[0]; + ddrC = 0xff; +} + +static m68705_interface bub68705_m68705_interface = { + NULL, bublbobl_68705_portB_out, NULL, + NULL, NULL, NULL, + NULL, NULL, bublbobl_68705_portC_in +}; + + +void __fastcall TokioWrite1(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0xfa80: { + DrvRomBank = d & 0x07; + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + return; + } + + case 0xfb00: { + DrvFlipScreen = d & 0x80; + return; + } + + case 0xfb80: { + ZetClose(); + ZetOpen(1); + ZetNmi(); + ZetClose(); + ZetOpen(0); + return; + } + + case 0xfc00: { + DrvSoundLatch = d; + DrvSoundNmiPending = 1; + return; + } + } +} + +UINT8 __fastcall TokioRead1(UINT16 a) +{ + switch (a) + { + case 0xfa03: { + return DrvDip[0]; + } + + case 0xfa04: { + return DrvDip[1]; + } + + case 0xfa05: { + return DrvInput[0] & ~0x20; + } + + case 0xfa06: { + return DrvInput[1]; + } + + case 0xfa07: { + return DrvInput[2]; + } + + case 0xfc00: { + return DrvSoundStatus; + } + + case 0xfe00: { + return 0xbf; // Mcu read... + } + } + + return 0; +} + +void __fastcall TokioSoundWrite3(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0x9000: { + DrvSoundStatus = d; + return; + } + + case 0xa000: { + DrvSoundNmiEnable = 0; + return; + } + + case 0xa800: { + DrvSoundNmiEnable = 1; + if (DrvSoundNmiPending) { + ZetNmi(); + DrvSoundNmiPending = 0; + } + return; + } + + case 0xb000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xb001: { + BurnYM2203Write(0, 1, d); + return; + } + } +} + +UINT8 __fastcall TokioSoundRead3(UINT16 a) +{ + switch (a) + { + case 0x9000: { + return DrvSoundLatch; + } + + case 0xb000: { + return BurnYM2203Read(0, 0); + } + + case 0xb001: { + return BurnYM2203Read(0, 1); + } + } + + return 0; +} + +inline static void DrvYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3000000; +} + +inline static INT32 DrvYM3526SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 6000000; +} + +inline static double DrvGetTime() +{ + return (double)ZetTotalCycles() / 3000000; +} + +static INT32 TilePlaneOffsets[4] = { 0, 4, 0x200000, 0x200004 }; +static INT32 TileXOffsets[8] = { 3, 2, 1, 0, 11, 10, 9, 8 }; +static INT32 TileYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; + +static INT32 MachineInit() +{ + INT32 nLen; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + // Setup the Z80 emulation + ZetInit(3); + ZetOpen(0); + ZetSetReadHandler(BublboblRead1); + ZetSetWriteHandler(BublboblWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xc000, 0xdcff, 0, DrvVideoRam ); + ZetMapArea(0xc000, 0xdcff, 1, DrvVideoRam ); + ZetMapArea(0xc000, 0xdcff, 2, DrvVideoRam ); + ZetMapArea(0xdd00, 0xdfff, 0, DrvSpriteRam ); + ZetMapArea(0xdd00, 0xdfff, 1, DrvSpriteRam ); + ZetMapArea(0xdd00, 0xdfff, 2, DrvSpriteRam ); + ZetMapArea(0xe000, 0xf7ff, 0, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 1, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 2, DrvSharedRam ); + ZetMapArea(0xf800, 0xf9ff, 0, DrvPaletteRam ); + ZetMapArea(0xf800, 0xf9ff, 1, DrvPaletteRam ); + ZetMapArea(0xf800, 0xf9ff, 2, DrvPaletteRam ); + ZetMapArea(0xfc00, 0xffff, 0, DrvZ80Ram1 ); + ZetMapArea(0xfc00, 0xffff, 1, DrvZ80Ram1 ); + ZetMapArea(0xfc00, 0xffff, 2, DrvZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom2 ); + ZetMapArea(0xe000, 0xf7ff, 0, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 1, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 2, DrvSharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(DrvSoundRead3); + ZetSetWriteHandler(DrvSoundWrite3); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom3 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom3 ); + ZetMapArea(0x8000, 0x8fff, 0, DrvZ80Ram3 ); + ZetMapArea(0x8000, 0x8fff, 1, DrvZ80Ram3 ); + ZetMapArea(0x8000, 0x8fff, 2, DrvZ80Ram3 ); + ZetMemEnd(); + ZetClose(); + + if (DrvMCUInUse == 1) { + M6801Init(1); + M6801MapMemory(DrvMcuRom, 0xf000, 0xffff, M6801_ROM); + M6801SetReadByteHandler(BublboblMcuReadByte); + M6801SetWriteByteHandler(BublboblMcuWriteByte); + } else if (DrvMCUInUse == 2) { + + m67805_taito_init(DrvMcuRom, DrvMcuRam, &bub68705_m68705_interface); + } + + BurnYM2203Init(1, 3000000, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + + BurnYM3526Init(3000000, NULL, &DrvYM3526SynchroniseStream, 1); + BurnTimerAttachZetYM3526(6000000); + + if (BublboblCallbackFunction()) return 1; + + GenericTilesInit(); + + // Reset the driver + DrvDoReset(); + + return 0; +} + +static INT32 BublboblCallback() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)malloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load MCU Rom + nRet = BurnLoadRom(DrvMcuRom + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x68000, 16, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x80000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x80, DrvTempRom, DrvTiles); + + // Load the PROM + nRet = BurnLoadRom(DrvProm + 0x00000, 17, 1); if (nRet != 0) return 1; + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + return 0; +} + +static INT32 BublboblInit() +{ + BublboblCallbackFunction = BublboblCallback; + + DrvMCUInUse = 1; + + return MachineInit(); +} + +static INT32 BoblboblCallback() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)malloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x18000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x68000, 16, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x80000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x80, DrvTempRom, DrvTiles); + + // Load the PROM + nRet = BurnLoadRom(DrvProm + 0x00000, 17, 1); if (nRet != 0) return 1; + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + ZetOpen(0); + ZetSetReadHandler(BoblboblRead1); + ZetSetWriteHandler(BoblboblWrite1); + ZetMemCallback(0xfe00, 0xffff, 0); + ZetMemCallback(0xfe00, 0xffff, 1); + ZetMemCallback(0xfe00, 0xffff, 2); + ZetMemEnd(); + ZetClose(); + + return 0; +} + +static INT32 BoblboblInit() +{ + BublboblCallbackFunction = BoblboblCallback; + + return MachineInit(); +} + +static INT32 Bub68705Callback() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)malloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x18000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x68000, 16, 1); if (nRet != 0) return 1; + + for (INT32 i = 0x00000; i < 0x80000; i++) + DrvTempRom[i] ^= 0xff; + + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x80, DrvTempRom, DrvTiles); + + // Load the PROM + nRet = BurnLoadRom(DrvProm + 0x00000, 17, 1); if (nRet != 0) return 1; + + // Load the 68705 Rom + nRet = BurnLoadRom(DrvMcuRom + 0x00000, 18, 1); if (nRet != 0) return 1; + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + return 0; +} + +static INT32 Bub68705Init() +{ + BublboblCallbackFunction = Bub68705Callback; + + DrvMCUInUse = 2; + + return MachineInit(); +} + +static INT32 DlandCallback() +{ + INT32 nRet = 0; + + DrvTempRom = (UINT8 *)malloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x18000, 2, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 3, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 4, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x00000, 5, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 10, 1); if (nRet != 0) return 1; + + for (INT32 i = 0x00000; i < 0x40000; i++) + DrvTempRom[i] = BITSWAP08(DrvTempRom[i],7,6,5,4,0,1,2,3) ^ 0xff; + + for (INT32 i = 0x40000; i < 0x80000; i++) + DrvTempRom[i] = BITSWAP08(DrvTempRom[i],7,4,5,6,3,0,1,2) ^ 0xff; + + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x80, DrvTempRom, DrvTiles); + + // Load the PROM + nRet = BurnLoadRom(DrvProm + 0x00000, 11, 1); if (nRet != 0) return 1; + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + + ZetOpen(0); + ZetSetReadHandler(BoblboblRead1); + ZetSetWriteHandler(BoblboblWrite1); + ZetMemCallback(0xfe00, 0xffff, 0); + ZetMemCallback(0xfe00, 0xffff, 1); + ZetMemCallback(0xfe00, 0xffff, 2); + ZetMemEnd(); + ZetClose(); + + return 0; +} + +static INT32 DlandInit() +{ + BublboblCallbackFunction = DlandCallback; + + return MachineInit(); +} + +static INT32 TokioInit() +{ + INT32 nLen, nRet; + + // Allocate and Blank all required memory + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(Mem, 0, nLen); + MemIndex(); + + { + DrvTempRom = (UINT8 *)malloc(0x80000); + + // Load Z80 #1 Program Roms + nRet = BurnLoadRom(DrvZ80Rom1 + 0x00000, 0, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x10000, 1, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x18000, 2, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x20000, 3, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvZ80Rom1 + 0x28000, 4, 1); if (nRet != 0) return 1; + + // Load Z80 #2 Program Roms + nRet = BurnLoadRom(DrvZ80Rom2 + 0x00000, 5, 1); if (nRet != 0) return 1; + + // Load Z80 #3 Program Roms + nRet = BurnLoadRom(DrvZ80Rom3 + 0x00000, 6, 1); if (nRet != 0) return 1; + + // Load and decode the tiles + nRet = BurnLoadRom(DrvTempRom + 0x00000, 7, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x08000, 8, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x10000, 9, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x18000, 10, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x20000, 11, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x28000, 12, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x30000, 13, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x38000, 14, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x40000, 15, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x48000, 16, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x50000, 17, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x58000, 18, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x60000, 19, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x68000, 20, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x70000, 21, 1); if (nRet != 0) return 1; + nRet = BurnLoadRom(DrvTempRom + 0x78000, 22, 1); if (nRet != 0) return 1; + for (INT32 i = 0; i < 0x80000; i++) DrvTempRom[i] ^= 0xff; + GfxDecode(0x4000, 4, 8, 8, TilePlaneOffsets, TileXOffsets, TileYOffsets, 0x80, DrvTempRom, DrvTiles); + + // Load the PROM + nRet = BurnLoadRom(DrvProm + 0x00000, 23, 1); if (nRet != 0) return 1; + + // Load MCU Rom + //BurnLoadRom(DrvMcuRom + 0x00000, 24, 1); + + if (DrvTempRom) { + free(DrvTempRom); + DrvTempRom = NULL; + } + } + + // Setup the Z80 emulation + ZetInit(3); + ZetOpen(0); + ZetSetReadHandler(TokioRead1); + ZetSetWriteHandler(TokioWrite1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom1 ); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 ); + ZetMapArea(0xc000, 0xdcff, 0, DrvVideoRam ); + ZetMapArea(0xc000, 0xdcff, 1, DrvVideoRam ); + ZetMapArea(0xc000, 0xdcff, 2, DrvVideoRam ); + ZetMapArea(0xdd00, 0xdfff, 0, DrvSpriteRam ); + ZetMapArea(0xdd00, 0xdfff, 1, DrvSpriteRam ); + ZetMapArea(0xdd00, 0xdfff, 2, DrvSpriteRam ); + ZetMapArea(0xe000, 0xf7ff, 0, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 1, DrvSharedRam ); + ZetMapArea(0xe000, 0xf7ff, 2, DrvSharedRam ); + ZetMapArea(0xf800, 0xf9ff, 0, DrvPaletteRam ); + ZetMapArea(0xf800, 0xf9ff, 1, DrvPaletteRam ); + ZetMapArea(0xf800, 0xf9ff, 2, DrvPaletteRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom2 ); + ZetMapArea(0x8000, 0x97ff, 0, DrvSharedRam ); + ZetMapArea(0x8000, 0x97ff, 1, DrvSharedRam ); + ZetMapArea(0x8000, 0x97ff, 2, DrvSharedRam ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(2); + ZetSetReadHandler(TokioSoundRead3); + ZetSetWriteHandler(TokioSoundWrite3); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80Rom3 ); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80Rom3 ); + ZetMapArea(0x8000, 0x8fff, 0, DrvZ80Ram3 ); + ZetMapArea(0x8000, 0x8fff, 1, DrvZ80Ram3 ); + ZetMapArea(0x8000, 0x8fff, 2, DrvZ80Ram3 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 3000000, &DrvYM2203IRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(3000000); + + GenericTilesInit(); + + DrvVideoEnable = 1; + DrvMCUInUse = 0; + + // Reset the driver + TokioDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + ZetExit(); + BurnYM2203Exit(); + BurnYM3526Exit(); + + GenericTilesExit(); + + if (Mem) { + free(Mem); + Mem = NULL; + } + + DrvRomBank = 0; + DrvSlaveCPUActive = 0; + DrvSoundCPUActive = 0; + DrvMCUActive = 0; + DrvVideoEnable = 0; + DrvFlipScreen = 0; + IC43A = 0; + IC43B = 0; + DrvSoundStatus = 0; + DrvSoundNmiEnable = 0; + DrvSoundNmiPending = 0; + DrvSoundLatch = 0; + DrvMCUInUse = 0; + + mcu_latch = 0; + mcu_address = 0; + + BublboblCallbackFunction = NULL; + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +inline static INT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 12); + g = pal4bit(nColour >> 8); + b = pal4bit(nColour >> 4); + + return BurnHighCol(r, g, b, 0); +} + +static void DrvCalcPalette() +{ + for (INT32 i = 0; i < 0x200; i += 2) { + DrvPalette[i / 2] = CalcCol(DrvPaletteRam[i | 1] | (DrvPaletteRam[i & ~1] << 8)); + } +} + +static void DrvVideoUpdate() +{ + INT32 sx, sy, xc, yc; + INT32 GfxNum, GfxAttr, GfxOffset; + const UINT8 *Prom; + const UINT8 *PromLine; + + if (!DrvVideoEnable) return; + + sx = 0; + + Prom = DrvProm; + + for (INT32 Offset = 0; Offset < 0x300; Offset += 4) { + if (*(UINT32 *)(&DrvSpriteRam[Offset]) == 0) continue; + + GfxNum = DrvSpriteRam[Offset + 1]; + GfxAttr = DrvSpriteRam[Offset + 3]; + PromLine = Prom + 0x80 + ((GfxNum & 0xe0) >> 1); + + GfxOffset = ((GfxNum & 0x1f) * 0x80); + if ((GfxNum & 0xa0) == 0xa0) GfxOffset |= 0x1000; + + sy = -DrvSpriteRam[Offset + 0]; + + for (yc = 0; yc < 32; yc++) { + if (PromLine[yc / 2] & 0x08) continue; + + if (!(PromLine[yc / 2] & 0x04)) { + sx = DrvSpriteRam[Offset + 2]; + if (GfxAttr & 0x40) sx -= 256; + } + + for (xc = 0; xc < 2; xc++) { + INT32 gOffs, Code, Colour, xFlip, yFlip, x, y, yPos; + + gOffs = GfxOffset + xc * 0x40 + (yc & 7) * 0x02 + (PromLine[yc / 2] & 0x03) * 0x10; + Code = DrvVideoRam[gOffs] + 256 * (DrvVideoRam[gOffs + 1] & 0x03) + 1024 * (GfxAttr & 0x0f); + Colour = (DrvVideoRam[gOffs + 1] & 0x3c) >> 2; + xFlip = DrvVideoRam[gOffs + 1] & 0x40; + yFlip = DrvVideoRam[gOffs + 1] & 0x80; + x = sx + xc * 8; + y = (sy + yc * 8) & 0xff; + + if (DrvFlipScreen) { + x = 248 - x; + y = 248 - y; + xFlip = !xFlip; + yFlip = !yFlip; + } + + yPos = y - 16; + + if (x > 8 && x < (nScreenWidth - 8) && yPos > 8 && yPos < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, yPos, Colour, 4, 15, 0, DrvTiles); + } + } + } + } + } + + sx += 16; + } +} + +static void DrvDraw() +{ + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x00ff; + } + + DrvCalcPalette(); + DrvVideoUpdate(); + BurnTransferCopy(DrvPalette); +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + if (DrvReset) DrvDoReset(); + + BublboblMakeInputs(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesTotal[2] = 3000000 / 60; + nCyclesTotal[3] = (DrvMCUInUse == 2) ? (4000000 / 60) : (1000000 / 60); + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = nCyclesDone[3] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + BurnTimerUpdateYM3526(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if (i == 98 && !DrvMCUInUse) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 99 && !DrvMCUInUse) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #2 + if (DrvSlaveCPUActive) { + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 98) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 99) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + } + + // Run Z80 #3 + if (DrvSoundCPUActive) { + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if (DrvSoundNmiPending) { + if (DrvSoundNmiEnable) { + ZetNmi(); + DrvSoundNmiPending = 0; + } + } + ZetClose(); + } + + if (DrvMCUInUse) { + if (DrvMCUActive) { + nCurrentCPU = 3; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (DrvMCUInUse == 2) { + nCyclesSegment = m6805Run(nCyclesSegment); + if (i == 49) m68705SetIrqLine(0, 1 /*ASSERT_LINE*/); + if (i == 99) m68705SetIrqLine(0, 0 /*CLEAR_LINE*/); + } else { + nCyclesSegment = M6801Run(nCyclesSegment); + if (i == 98) M6801SetIRQ(0, M6801_IRQSTATUS_ACK); + if (i == 99) M6801SetIRQ(0, M6801_IRQSTATUS_NONE); + } + + nCyclesDone[nCurrentCPU] += nCyclesSegment; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(2); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + ZetOpen(0); + BurnYM3526Update(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + ZetOpen(0); + BurnTimerEndFrameYM3526(nCyclesTotal[0]); + ZetClose(); + + if (DrvSoundCPUActive) { + ZetOpen(2); + BurnTimerEndFrame(nCyclesTotal[2]); + ZetClose(); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(2); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + ZetOpen(0); + BurnYM3526Update(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 TokioFrame() +{ + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + if (DrvReset) TokioDoReset(); + + BublboblMakeInputs(); + + nCyclesTotal[0] = 6000000 / 60; + nCyclesTotal[1] = 6000000 / 60; + nCyclesTotal[2] = 3000000 / 60; + nCyclesDone[0] = nCyclesDone[1] = nCyclesDone[2] = 0; + + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run Z80 #1 + nCurrentCPU = 0; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 98) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 99) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #2 + nCurrentCPU = 1; + ZetOpen(nCurrentCPU); + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesSegment = ZetRun(nCyclesSegment); + nCyclesDone[nCurrentCPU] += nCyclesSegment; + if (i == 98) ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + if (i == 99) ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + ZetClose(); + + // Run Z80 #3 + nCurrentCPU = 2; + ZetOpen(nCurrentCPU); + BurnTimerUpdate(i * (nCyclesTotal[nCurrentCPU] / nInterleave)); + if (DrvSoundNmiPending) { + if (DrvSoundNmiEnable) { + ZetNmi(); + DrvSoundNmiPending = 0; + } + } + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(2); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + ZetOpen(2); + BurnTimerEndFrame(nCyclesTotal[2]); + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(2); + BurnYM2203Update(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (pBurnDraw) DrvDraw(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029706; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + ZetScan(nAction); + if (DrvMCUInUse == 1) M6801Scan(nAction); + if (DrvMCUInUse == 2) m68705_taito_scan(nAction); + + BurnYM2203Scan(nAction, pnMin); + + if (strncmp(BurnDrvGetTextA(DRV_NAME), "tokio", 5) != 0) { + BurnYM3526Scan(nAction, pnMin); + } + + SCAN_VAR(DrvRomBank); + SCAN_VAR(DrvSlaveCPUActive); + SCAN_VAR(DrvSoundCPUActive); + SCAN_VAR(DrvMCUActive); + SCAN_VAR(DrvVideoEnable); + SCAN_VAR(DrvFlipScreen); + SCAN_VAR(IC43A); + SCAN_VAR(IC43B); + SCAN_VAR(DrvSoundStatus); + SCAN_VAR(DrvSoundNmiEnable); + SCAN_VAR(DrvSoundNmiPending); + SCAN_VAR(DrvSoundLatch); + SCAN_VAR(ddr1); + SCAN_VAR(ddr2); + SCAN_VAR(ddr3); + SCAN_VAR(ddr4); + SCAN_VAR(port1_in); + SCAN_VAR(port2_in); + SCAN_VAR(port3_in); + SCAN_VAR(port4_in); + SCAN_VAR(port1_out); + SCAN_VAR(port2_out); + SCAN_VAR(port3_out); + SCAN_VAR(port4_out); + SCAN_VAR(mcu_latch); + SCAN_VAR(mcu_address); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x8000, 0xbfff, 0, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetMapArea(0x8000, 0xbfff, 2, DrvZ80Rom1 + 0x10000 + (DrvRomBank * 0x4000)); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvBublbobl = { + "bublbobl", NULL, NULL, NULL, "1986", + "Bubble Bobble\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, BublboblRomInfo, BublboblRomName, NULL, NULL, BublboblInputInfo, BublboblDIPInfo, + BublboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBublbob1 = { + "bublbobl1", "bublbobl", NULL, NULL, "1986", + "Bubble Bobble (older)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, Bublbob1RomInfo, Bublbob1RomName, NULL, NULL, BublboblInputInfo, BublboblDIPInfo, + BublboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBublbobr = { + "bublboblr", "bublbobl", NULL, NULL, "1986", + "Bubble Bobble (US with mode select)\0", NULL, "Taito America Corporation (Romstar license)", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, BublbobrRomInfo, BublbobrRomName, NULL, NULL, BublboblInputInfo, BublboblDIPInfo, + BublboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBubbobr1 = { + "bublboblr1", "bublbobl", NULL, NULL, "1986", + "Bubble Bobble (US)\0", NULL, "Taito America Corporation (Romstar license)", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, Bubbobr1RomInfo, Bubbobr1RomName, NULL, NULL, BublboblInputInfo, BublboblDIPInfo, + BublboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBoblbobl = { + "boblbobl", "bublbobl", NULL, NULL, "1986", + "Bobble Bobble\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, BoblboblRomInfo, BoblboblRomName, NULL, NULL, BoblboblInputInfo, BoblboblDIPInfo, + BoblboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSboblboa = { + "sboblboa", "bublbobl", NULL, NULL, "1986", + "Super Bobble Bobble (set 1)\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, SboblboaRomInfo, SboblboaRomName, NULL, NULL, BoblboblInputInfo, BoblboblDIPInfo, + BoblboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSboblbob = { + "sboblbob", "bublbobl", NULL, NULL, "1986", + "Super Bobble Bobble (set 2)\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, SboblbobRomInfo, SboblbobRomName, NULL, NULL, BoblboblInputInfo, SboblbobDIPInfo, + BoblboblInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvBub68705 = { + "bub68705", "bublbobl", NULL, NULL, "1986", + "Bubble Bobble (boolteg with 68705)\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, Bub68705RomInfo, Bub68705RomName, NULL, NULL, BublboblInputInfo, BublboblDIPInfo, + Bub68705Init, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDland = { + "dland", "bublbobl", NULL, NULL, "1987", + "Dream Land / Super Dream Land (bootleg of Bubble Bobble)\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, DlandRomInfo, DlandRomName, NULL, NULL, BublboblInputInfo, DlandDIPInfo, + DlandInit, DrvExit, DrvFrame, NULL, DrvScan, + NULL, 0x100, 256, 224, 4, 3 +}; + +struct BurnDriver BurnDrvTokio = { + "tokio", NULL, NULL, NULL, "1986", + "Tokio / Scramble Formation (newer)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, tokioRomInfo, tokioRomName, NULL, NULL, TokioInputInfo, TokioDIPInfo, + TokioInit, DrvExit, TokioFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvTokioo = { + "tokioo", "tokio", NULL, NULL, "1986", + "Tokio / Scramble Formation (older)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, tokiooRomInfo, tokiooRomName, NULL, NULL, TokioInputInfo, TokioDIPInfo, + TokioInit, DrvExit, TokioFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriverD BurnDrvTokiou = { + "tokiou", "tokio", NULL, NULL, "1986", + "Tokio / Scramble Formation (US)\0", NULL, "Taito America Corporation (Romstar license)", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, tokiouRomInfo, tokiouRomName, NULL, NULL, TokioInputInfo, TokioDIPInfo, + TokioInit, DrvExit, TokioFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; + +struct BurnDriver BurnDrvTokiob = { + "tokiob", "tokio", NULL, NULL, "1986", + "Tokio / Scramble Formation (bootleg)\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_TAITO_MISC, GBF_VERSHOOT, 0, + NULL, tokiobRomInfo, tokiobRomName, NULL, NULL, TokioInputInfo, TokioDIPInfo, + TokioInit, DrvExit, TokioFrame, NULL, DrvScan, + NULL, 0x100, 224, 256, 3, 4 +}; diff --git a/src/burn/drivers/taito/d_darius2.cpp b/src/burn/drivers/taito/d_darius2.cpp new file mode 100644 index 00000000..72a137ed --- /dev/null +++ b/src/burn/drivers/taito/d_darius2.cpp @@ -0,0 +1,2048 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" + +static INT32 Ninjaw; + +static void Darius2Draw(); +static void Darius2dDraw(); +static void WarriorbDraw(); + +static struct BurnInputInfo Darius2InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "tilt" }, + {"Freeze" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "freeze" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Darius2) + +static struct BurnInputInfo Darius2dInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "tilt" }, + {"Freeze" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "freeze" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Darius2d) + +static struct BurnInputInfo WarriorbInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 6, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 6, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 7, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "tilt" }, + {"Freeze" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "freeze" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Warriorb) + +static void Darius2MakeInputs() +{ + TC0220IOCInput[0] = 0xe2; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] |= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] |= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] |= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] |= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[1] -= (TC0220IOCInputPort1[i] & 1) << i; + TC0220IOCInput[2] -= (TC0220IOCInputPort2[i] & 1) << i; + } +} + +static void Darius2dMakeInputs() +{ + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xf7; + + if (TC0220IOCInputPort2[0]) TC0220IOCInput[2] -= 0x01; + if (TC0220IOCInputPort2[1]) TC0220IOCInput[2] -= 0x02; + if (TC0220IOCInputPort2[2]) TC0220IOCInput[2] -= 0x04; + if (TC0220IOCInputPort2[3]) TC0220IOCInput[2] |= 0x08; + if (TC0220IOCInputPort2[4]) TC0220IOCInput[2] -= 0x10; + if (TC0220IOCInputPort2[5]) TC0220IOCInput[2] -= 0x20; + if (TC0220IOCInputPort2[6]) TC0220IOCInput[2] -= 0x40; + if (TC0220IOCInputPort2[7]) TC0220IOCInput[2] -= 0x80; + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[0] -= (TC0220IOCInputPort0[i] & 1) << i; + TC0220IOCInput[1] -= (TC0220IOCInputPort1[i] & 1) << i; + } +} + +static void WarriorbMakeInputs() +{ + TC0510NIOInput[0] = 0xff; + TC0510NIOInput[1] = 0xff; + TC0510NIOInput[2] = 0xf7; + + if (TC0510NIOInputPort2[0]) TC0510NIOInput[2] -= 0x01; + if (TC0510NIOInputPort2[1]) TC0510NIOInput[2] -= 0x02; + if (TC0510NIOInputPort2[2]) TC0510NIOInput[2] -= 0x04; + if (TC0510NIOInputPort2[3]) TC0510NIOInput[2] |= 0x08; + if (TC0510NIOInputPort2[4]) TC0510NIOInput[2] -= 0x10; + if (TC0510NIOInputPort2[5]) TC0510NIOInput[2] -= 0x20; + if (TC0510NIOInputPort2[6]) TC0510NIOInput[2] -= 0x40; + if (TC0510NIOInputPort2[7]) TC0510NIOInput[2] -= 0x80; + + for (INT32 i = 0; i < 8; i++) { + TC0510NIOInput[0] -= (TC0510NIOInputPort0[i] & 1) << i; + TC0510NIOInput[1] -= (TC0510NIOInputPort1[i] & 1) << i; + } +} + +static struct BurnDIPInfo Darius2DIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xfe, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x14, 0x01, 0x02, 0x02, "Normal" }, + {0x14, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "every 700k" }, + {0x15, 0x01, 0x0c, 0x08, "every 800k" }, + {0x15, 0x01, 0x0c, 0x04, "every 900k" }, + {0x15, 0x01, 0x0c, 0x00, "every 1000K" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x30, 0x30, "3" }, + {0x15, 0x01, 0x30, 0x20, "4" }, + {0x15, 0x01, 0x30, 0x10, "5" }, + {0x15, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Invulnerability" }, + {0x15, 0x01, 0x40, 0x40, "Off" }, + {0x15, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Darius2) + +static struct BurnDIPInfo Darius2dDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xfe, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x14, 0x01, 0x02, 0x02, "Normal" }, + {0x14, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x15, 0x01, 0x0c, 0x0c, "every 700k" }, + {0x15, 0x01, 0x0c, 0x08, "every 800k" }, + {0x15, 0x01, 0x0c, 0x04, "every 900k" }, + {0x15, 0x01, 0x0c, 0x00, "every 1000K" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x15, 0x01, 0x30, 0x30, "3" }, + {0x15, 0x01, 0x30, 0x20, "4" }, + {0x15, 0x01, 0x30, 0x10, "5" }, + {0x15, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x15, 0x01, 0x80, 0x00, "Off" }, + {0x15, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Darius2d) + +static struct BurnDIPInfo NinjawDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x14, 0x01, 0x02, 0x02, "Normal" }, + {0x14, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x14, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x14, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ninjaw) + +static struct BurnDIPInfo NinjawjDIPList[]= +{ + // Default Values + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x01, 0x00, "Off" }, + {0x14, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x14, 0x01, 0x02, 0x02, "Normal" }, + {0x14, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x14, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Ninjawj) + +static struct BurnDIPInfo WarriorbDIPList[]= +{ + // Default Values + {0x16, 0xff, 0xff, 0xff, NULL }, + {0x17, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Vitality Recovery" }, + {0x16, 0x01, 0x03, 0x02, "Less" }, + {0x16, 0x01, 0x03, 0x03, "Normal" }, + {0x16, 0x01, 0x03, 0x01, "More" }, + {0x16, 0x01, 0x03, 0x00, "Most" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x08, 0x00, "Off" }, + {0x16, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x16, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x16, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x16, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x16, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x16, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x16, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x16, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x16, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x17, 0x01, 0x03, 0x02, "Easy" }, + {0x17, 0x01, 0x03, 0x03, "Medium" }, + {0x17, 0x01, 0x03, 0x01, "Hard" }, + {0x17, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Gold Sheep at" }, + {0x17, 0x01, 0x04, 0x04, "50k only" }, + {0x17, 0x01, 0x04, 0x00, "50k, then every 70k" }, + + {0 , 0xfe, 0 , 2 , "Magic Energy Loss" }, + {0x17, 0x01, 0x08, 0x08, "Always Player" }, + {0x17, 0x01, 0x08, 0x00, "Player or Magician" }, + + {0 , 0xfe, 0 , 2 , "Player Starting Strength" }, + {0x17, 0x01, 0x10, 0x10, "Normal" }, + {0x17, 0x01, 0x10, 0x00, "Full" }, + + {0 , 0xfe, 0 , 2 , "Magician appears" }, + {0x17, 0x01, 0x20, 0x20, "When you get a crystal" }, + {0x17, 0x01, 0x20, 0x00, "Always" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x17, 0x01, 0x40, 0x00, "Off" }, + {0x17, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Rounds" }, + {0x17, 0x01, 0x80, 0x80, "Normal (10-14, depends on skill"}, + {0x17, 0x01, 0x80, 0x00, "Long (14)" }, +}; + +STDDIPINFO(Warriorb) + +static struct BurnRomInfo Darius2RomDesc[] = { + { "c07-32-1", 0x10000, 0x216c8f6a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-29-1", 0x10000, 0x48de567f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-31-1", 0x10000, 0x8279d2f8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-30-1", 0x10000, 0x6122e400, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-27", 0x20000, 0x0a6f7b6c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-25", 0x20000, 0x059f40ce, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-26", 0x20000, 0x1f411242, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-24", 0x20000, 0x486c9c20, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c07-35-1", 0x10000, 0xdd8c4723, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c07-38-1", 0x10000, 0x46afb85c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c07-34-1", 0x10000, 0x296984b8, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c07-37-1", 0x10000, 0x8b7d461f, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c07-33-1", 0x10000, 0x2da03a3f, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c07-36-1", 0x10000, 0x02cf2b1c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c07-28", 0x20000, 0xda304bc5, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c07-03.12", 0x80000, 0x189bafce, BRF_GRA | TAITO_CHARS }, + { "c07-04.11", 0x80000, 0x50421e81, BRF_GRA | TAITO_CHARS }, + + { "c07-01", 0x80000, 0x3cf0f050, BRF_GRA | TAITO_SPRITESA }, + { "c07-02", 0x80000, 0x75d16d4b, BRF_GRA | TAITO_SPRITESA }, + + { "c07-10.95", 0x80000, 0x4bbe0ed9, BRF_SND | TAITO_YM2610A }, + { "c07-11.96", 0x80000, 0x3c815699, BRF_SND | TAITO_YM2610A }, + + { "c07-12.107", 0x80000, 0xe0b71258, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Darius2) +STD_ROM_FN(Darius2) + +static struct BurnRomInfo Darius2dRomDesc[] = { + { "c07_20-2.74", 0x20000, 0xa0f345b8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_19-2.73", 0x20000, 0x925412c6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_21-2.76", 0x20000, 0xbdd60e37, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_18-2.71", 0x20000, 0x23fcd89b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-09.75", 0x80000, 0xcc69c2ce, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c07_17.69", 0x20000, 0xae16c905, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c07-03.12", 0x80000, 0x189bafce, BRF_GRA | TAITO_CHARS }, + { "c07-04.11", 0x80000, 0x50421e81, BRF_GRA | TAITO_CHARS }, + + { "c07-06.27", 0x80000, 0x5eebbcd6, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-05.24", 0x80000, 0xfb6d0550, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-08.25", 0x80000, 0xa07dc846, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-07.26", 0x80000, 0xfd9f9e74, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c07-10.95", 0x80000, 0x4bbe0ed9, BRF_SND | TAITO_YM2610A }, + { "c07-11.96", 0x80000, 0x3c815699, BRF_SND | TAITO_YM2610A }, + + { "c07-12.107", 0x80000, 0xe0b71258, BRF_SND | TAITO_YM2610B }, + + { "c07-13.37", 0x00400, 0x3ca18eb3, BRF_OPT }, + { "c07-14.38", 0x00400, 0xbaf2a193, BRF_OPT }, +}; + +STD_ROM_PICK(Darius2d) +STD_ROM_FN(Darius2d) + +static struct BurnRomInfo Darius2doRomDesc[] = { + { "c07_20-1.74", 0x20000, 0x48b0804a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_19-1.73", 0x20000, 0x1f9a4f83, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_21-1.76", 0x20000, 0xb491b0ca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07_18-1.71", 0x20000, 0xc552e42f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c07-09.75", 0x80000, 0xcc69c2ce, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c07_17.69", 0x20000, 0xae16c905, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c07-03.12", 0x80000, 0x189bafce, BRF_GRA | TAITO_CHARS }, + { "c07-04.11", 0x80000, 0x50421e81, BRF_GRA | TAITO_CHARS }, + + { "c07-06.27", 0x80000, 0x5eebbcd6, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-05.24", 0x80000, 0xfb6d0550, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-08.25", 0x80000, 0xa07dc846, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c07-07.26", 0x80000, 0xfd9f9e74, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c07-10.95", 0x80000, 0x4bbe0ed9, BRF_SND | TAITO_YM2610A }, + { "c07-11.96", 0x80000, 0x3c815699, BRF_SND | TAITO_YM2610A }, + + { "c07-12.107", 0x80000, 0xe0b71258, BRF_SND | TAITO_YM2610B }, + + { "c07-13.37", 0x00400, 0x3ca18eb3, BRF_OPT }, + { "c07-14.38", 0x00400, 0xbaf2a193, BRF_OPT }, +}; + +STD_ROM_PICK(Darius2do) +STD_ROM_FN(Darius2do) + +static struct BurnRomInfo NinjawRomDesc[] = { + { "b31_45.35", 0x10000, 0x107902c3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_47.32", 0x10000, 0xbd536b1e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_29.34", 0x10000, 0xf2941a37, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_27.31", 0x10000, 0x2f3ff642, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_41.5", 0x20000, 0x0daef28a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_39.2", 0x20000, 0xe9197c3c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_40.6", 0x20000, 0x2ce0f24e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_38.3", 0x20000, 0xbc68cd99, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b31_33.87", 0x10000, 0x6ce9af44, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_36.97", 0x10000, 0xba20b0d4, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_32.86", 0x10000, 0xe6025fec, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_35.96", 0x10000, 0x70d9a89f, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_31.85", 0x10000, 0x837f47e2, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_34.95", 0x10000, 0xd6b5fb2a, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b31_37.11", 0x20000, 0x0ca5799d, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b31-01.23", 0x80000, 0x8e8237a7, BRF_GRA | TAITO_CHARS }, + { "b31-02.24", 0x80000, 0x4c3b4e33, BRF_GRA | TAITO_CHARS }, + + { "b31-07.176", 0x80000, 0x33568cdb, BRF_GRA | TAITO_SPRITESA }, + { "b31-06.175", 0x80000, 0x0d59439e, BRF_GRA | TAITO_SPRITESA }, + { "b31-05.174", 0x80000, 0x0a1fc9fb, BRF_GRA | TAITO_SPRITESA }, + { "b31-04.173", 0x80000, 0x2e1e4cb5, BRF_GRA | TAITO_SPRITESA }, + + { "b31-09.18", 0x80000, 0x60a73382, BRF_SND | TAITO_YM2610A }, + { "b31-10.17", 0x80000, 0xc6434aef, BRF_SND | TAITO_YM2610A }, + { "b31-11.16", 0x80000, 0x8da531d4, BRF_SND | TAITO_YM2610A }, + + { "b31-08.19", 0x80000, 0xa0a1f87d, BRF_SND | TAITO_YM2610B }, + + { "b31-25.38", 0x00200, 0xa0b4ba48, BRF_OPT }, + { "b31-26.58", 0x00200, 0x13e5fe15, BRF_OPT }, +}; + +STD_ROM_PICK(Ninjaw) +STD_ROM_FN(Ninjaw) + +static struct BurnRomInfo NinjawjRomDesc[] = { + { "b31_30.35", 0x10000, 0x056edd9f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_28.32", 0x10000, 0xcfa7661c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_29.34", 0x10000, 0xf2941a37, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_27.31", 0x10000, 0x2f3ff642, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_41.5", 0x20000, 0x0daef28a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_39.2", 0x20000, 0xe9197c3c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_40.6", 0x20000, 0x2ce0f24e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_38.3", 0x20000, 0xbc68cd99, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b31_33.87", 0x10000, 0x6ce9af44, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_36.97", 0x10000, 0xba20b0d4, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_32.86", 0x10000, 0xe6025fec, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_35.96", 0x10000, 0x70d9a89f, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_31.85", 0x10000, 0x837f47e2, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_34.95", 0x10000, 0xd6b5fb2a, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b31_37.11", 0x20000, 0x0ca5799d, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b31-01.23", 0x80000, 0x8e8237a7, BRF_GRA | TAITO_CHARS }, + { "b31-02.24", 0x80000, 0x4c3b4e33, BRF_GRA | TAITO_CHARS }, + + { "b31-07.176", 0x80000, 0x33568cdb, BRF_GRA | TAITO_SPRITESA }, + { "b31-06.175", 0x80000, 0x0d59439e, BRF_GRA | TAITO_SPRITESA }, + { "b31-05.174", 0x80000, 0x0a1fc9fb, BRF_GRA | TAITO_SPRITESA }, + { "b31-04.173", 0x80000, 0x2e1e4cb5, BRF_GRA | TAITO_SPRITESA }, + + { "b31-09.18", 0x80000, 0x60a73382, BRF_SND | TAITO_YM2610A }, + { "b31-10.17", 0x80000, 0xc6434aef, BRF_SND | TAITO_YM2610A }, + { "b31-11.16", 0x80000, 0x8da531d4, BRF_SND | TAITO_YM2610A }, + + { "b31-08.19", 0x80000, 0xa0a1f87d, BRF_SND | TAITO_YM2610B }, + + { "b31-25.38", 0x00200, 0xa0b4ba48, BRF_OPT }, + { "b31-26.58", 0x00200, 0x13e5fe15, BRF_OPT }, +}; + +STD_ROM_PICK(Ninjawj) +STD_ROM_FN(Ninjawj) + +static struct BurnRomInfo NinjawuRomDesc[] = { + { "b31_49.35", 0x10000, 0xd38b6391, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_48.32", 0x10000, 0x4b5bb3d8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_29.34", 0x10000, 0xf2941a37, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_27.31", 0x10000, 0x2f3ff642, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_41.5", 0x20000, 0x0daef28a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_39.2", 0x20000, 0xe9197c3c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_40.6", 0x20000, 0x2ce0f24e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b31_38.3", 0x20000, 0xbc68cd99, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b31_33.87", 0x10000, 0x6ce9af44, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_36.97", 0x10000, 0xba20b0d4, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_32.86", 0x10000, 0xe6025fec, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_35.96", 0x10000, 0x70d9a89f, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_31.85", 0x10000, 0x837f47e2, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b31_34.95", 0x10000, 0xd6b5fb2a, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b31_37.11", 0x20000, 0x0ca5799d, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b31-01.23", 0x80000, 0x8e8237a7, BRF_GRA | TAITO_CHARS }, + { "b31-02.24", 0x80000, 0x4c3b4e33, BRF_GRA | TAITO_CHARS }, + + { "b31-07.176", 0x80000, 0x33568cdb, BRF_GRA | TAITO_SPRITESA }, + { "b31-06.175", 0x80000, 0x0d59439e, BRF_GRA | TAITO_SPRITESA }, + { "b31-05.174", 0x80000, 0x0a1fc9fb, BRF_GRA | TAITO_SPRITESA }, + { "b31-04.173", 0x80000, 0x2e1e4cb5, BRF_GRA | TAITO_SPRITESA }, + + { "b31-09.18", 0x80000, 0x60a73382, BRF_SND | TAITO_YM2610A }, + { "b31-10.17", 0x80000, 0xc6434aef, BRF_SND | TAITO_YM2610A }, + { "b31-11.16", 0x80000, 0x8da531d4, BRF_SND | TAITO_YM2610A }, + + { "b31-08.19", 0x80000, 0xa0a1f87d, BRF_SND | TAITO_YM2610B }, + + { "b31-25.38", 0x00200, 0xa0b4ba48, BRF_OPT }, + { "b31-26.58", 0x00200, 0x13e5fe15, BRF_OPT }, +}; + +STD_ROM_PICK(Ninjawu) +STD_ROM_FN(Ninjawu) + +static struct BurnRomInfo WarriorbRomDesc[] = { + { "d24_20-1.74", 0x040000, 0x4452dc25, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d24_19-1.73", 0x040000, 0x15c16016, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d24_21-1.76", 0x040000, 0x783ef8e1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d24_18-1.71", 0x040000, 0x4502db60, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d24-09.75", 0x100000, 0xece5cc59, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d24_17.69", 0x020000, 0xe41e4aae, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d24-02.12", 0x100000, 0x9f50c271, BRF_GRA | TAITO_CHARS }, + { "d24-01.11", 0x100000, 0x326dcca9, BRF_GRA | TAITO_CHARS }, + + { "d24-07.47", 0x100000, 0x9f50c271, BRF_GRA | TAITO_CHARSB }, + { "d24-08.48", 0x100000, 0x1e6d1528, BRF_GRA | TAITO_CHARSB }, + + { "d24-06.27", 0x100000, 0x918486fe, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d24-03.24", 0x100000, 0x46db9fd7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d24-04.25", 0x100000, 0x148e0493, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d24-05.26", 0x100000, 0x9f414317, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "d24-12.107", 0x100000, 0x279203a1, BRF_SND | TAITO_YM2610A }, + { "d24-10.95", 0x100000, 0x0e0c716d, BRF_SND | TAITO_YM2610A }, + { "d24-11.118", 0x100000, 0x15362573, BRF_SND | TAITO_YM2610A }, + + { "d24-13.37", 0x000400, 0x3ca18eb3, BRF_OPT }, + { "d24-14.38", 0x000400, 0xbaf2a193, BRF_OPT }, +}; + +STD_ROM_PICK(Warriorb) +STD_ROM_FN(Warriorb) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + Taito68KRom2 = Next; Next += Taito68KRom2Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x010000; + Taito68KRam2 = Next; Next += 0x010000; + TaitoZ80Ram1 = Next; Next += 0x002000; + TaitoSharedRam = Next; Next += 0x010000; + TaitoSpriteRam = Next; Next += 0x004000; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 Darius2dMemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x010000; + TaitoZ80Ram1 = Next; Next += 0x002000; + TaitoSpriteRam = Next; Next += 0x001400; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 WarriorbMemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x014000; + TaitoZ80Ram1 = Next; Next += 0x002000; + TaitoSpriteRam = Next; Next += 0x001400; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoCharsB = Next; Next += TaitoNumCharB * TaitoCharBWidth * TaitoCharBHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + + TaitoMemEnd = Next; + + return 0; +} + +static void Darius2CpuAReset(UINT16 d) +{ + TaitoCpuACtrl = d; + if (!(TaitoCpuACtrl & 1)) { + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(0); + } +} + +UINT8 __fastcall Darius268K1ReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius268K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCNTripleScreenByteWrite_Map(0x280000, 0x293fff) + TC0100SCN1ByteWrite_Map(0x2c0000, 0x2d3fff) + TC0100SCN2ByteWrite_Map(0x300000, 0x313fff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Darius268K1ReadWord(UINT32 a) +{ + switch (a) { + case 0x200000: { + return TC0220IOCPortRegRead(); + } + + case 0x200002: { + return TC0220IOCHalfWordPortRead(); + } + + case 0x220002: { + return TC0140SYTCommRead(); + } + + case 0x340002: { + return TC0110PCRWordRead(0); + } + + case 0x350002: { + return TC0110PCRWordRead(1); + } + + case 0x360002: { + return TC0110PCRWordRead(2); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius268K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0CtrlWordWrite_Map(0x2a0000) + TC0100SCN1CtrlWordWrite_Map(0x2e0000) + TC0100SCN2CtrlWordWrite_Map(0x320000) + TC0100SCNTripleScreenWordWrite_Map(0x280000, 0x293fff) + TC0100SCN1WordWrite_Map(0x2c0000, 0x2d3fff) + TC0100SCN2WordWrite_Map(0x300000, 0x313fff) + + switch (a) { + case 0x200000: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x200002: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + case 0x210000: { + Darius2CpuAReset(d); + return; + } + + case 0x220000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x220002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x340000: + case 0x340002: { + TC0110PCRStep1WordWrite(0, (a - 0x340000) >> 1, d); + return; + } + + case 0x350000: + case 0x350002: { + TC0110PCRStep1WordWrite(1, (a - 0x350000) >> 1, d); + return; + } + + case 0x360000: + case 0x360002: { + TC0110PCRStep1WordWrite(2, (a - 0x360000) >> 1, d); + return; + } + + case 0x340004: + case 0x350004: + case 0x360004: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Darius268K2ReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius268K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Darius268K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x200000: { + return TC0220IOCPortRegRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius268K2WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCNTripleScreenWordWrite_Map(0x280000, 0x293fff) + + switch (a) { + case 0x210000: { + //??? + return; + } + + case 0x340000: + case 0x340002: { + TC0110PCRStep1WordWrite(0, (a - 0x340000) >> 1, d); + return; + } + + case 0x350000: + case 0x350002: { + TC0110PCRStep1WordWrite(1, (a - 0x350000) >> 1, d); + return; + } + + case 0x360000: + case 0x360002: { + TC0110PCRStep1WordWrite(2, (a - 0x360000) >> 1, d); + return; + } + + case 0x340004: + case 0x350004: + case 0x360004: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Darius2d68KReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius2d68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCNDualScreenByteWrite_Map(0x200000, 0x213fff) + TC0100SCN1ByteWrite_Map(0x240000, 0x25ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Darius2d68KReadWord(UINT32 a) +{ + switch (a) { + case 0x400002: { + return TC0110PCRWordRead(0); + } + + case 0x420002: { + return TC0110PCRWordRead(1); + } + + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: + case 0x800008: + case 0x80000a: + case 0x80000c: + case 0x80000e: { + return TC0220IOCRead((a - 0x800000) >> 1); + } + + case 0x830002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius2d68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCNDualScreenWordWrite_Map(0x200000, 0x213fff) + + if (a >= 0x214000 && a <= 0x2141ff) return; + + TC0100SCN0CtrlWordWrite_Map(0x220000) + TC0100SCN1CtrlWordWrite_Map(0x260000) + TC0100SCN1WordWrite_Map(0x240000, 0x25ffff) + + switch (a) { + case 0x400000: + case 0x400002: + case 0x400004: { + TC0110PCRStep1WordWrite(0, (a - 0x400000) >> 1, d); + return; + } + + case 0x420000: + case 0x420002: + case 0x420004: { + TC0110PCRStep1WordWrite(1, (a - 0x420000) >> 1, d); + return; + } + + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: + case 0x800008: + case 0x80000a: + case 0x80000c: + case 0x80000e: { + TC0220IOCWrite((a - 0x800000) >> 1, d); + return; + } + + case 0x820000: { + // nop + return; + } + + case 0x830000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x830002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Warriorb68KReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Warriorb68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCNDualScreenByteWrite_Map(0x300000, 0x313fff) + TC0100SCN1ByteWrite_Map(0x340000, 0x35ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Warriorb68KReadWord(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x800000) + + switch (a) { + case 0x400002: { + return TC0110PCRWordRead(0); + } + + case 0x420002: { + return TC0110PCRWordRead(1); + } + + case 0x830002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Warriorb68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCNDualScreenWordWrite_Map(0x300000, 0x313fff) + TC0100SCN1WordWrite_Map(0x340000, 0x35ffff) + + TC0100SCN0CtrlWordWrite_Map(0x320000) + TC0100SCN1CtrlWordWrite_Map(0x360000) + + TC0510NIOHalfWordWrite_Map(0x800000) + + switch (a) { + case 0x400000: + case 0x400002: + case 0x400004: { + TC0110PCRStep1WordWrite(0, (a - 0x400000) >> 1, d); + return; + } + + case 0x420000: + case 0x420002: + case 0x420004: { + TC0110PCRStep1WordWrite(1, (a - 0x420000) >> 1, d); + return; + } + + case 0x820000: { + // nop + return; + } + + case 0x830000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x830002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Darius2Z80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe002: { + return BurnYM2610Read(2); + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + case 0xea00: { + // NOP + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius2Z80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xe400: + case 0xe401: + case 0xe402: + case 0xe403: { + //pan control + return; + } + + case 0xe600: { + //??? + return; + } + + case 0xee00: { + //nop + return; + } + + case 0xf000: { + //nop + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 7; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 8, 12, 0, 4 }; +static INT32 SpriteXOffsets[16] = { 3, 2, 1, 0, 19, 18, 17, 16, 259, 258, 257, 256, 275, 274, 273, 272 }; +static INT32 SpriteYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 Darius2dSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 Darius2dSpriteXOffsets[16] = { 12, 8, 44, 40, 4, 0, 36, 32, 28, 24, 60, 56, 20, 16, 52, 48 }; +static INT32 Darius2dSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + +static void Darius2FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 Darius2SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (16000000 / 4); +} + +static double Darius2GetTime() +{ + return (double)ZetTotalCycles() / (16000000 / 4); +} + +static INT32 Darius2Init() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x8000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x2000; + + if (Ninjaw) TaitoNumSpriteA = 0x4000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 22, 16, 0, NULL); + TC0100SCNSetClipArea(0, 288, nScreenHeight, 0); + TC0100SCNInit(1, TaitoNumChar, 24, 16, 0, NULL); + TC0100SCNSetClipArea(1, 288, nScreenHeight, 288); + TC0100SCNSetPaletteOffset(1, 0x1000); + TC0100SCNInit(2, TaitoNumChar, 26, 16, 0, NULL); + TC0100SCNSetClipArea(2, 288, nScreenHeight, 576); + TC0100SCNSetPaletteOffset(2, 0x2000); + TC0110PCRInit(3, 0x3000); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x0c0000, 0x0cffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x240000, 0x24ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x260000, 0x263fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x280000, 0x293fff, SM_READ); + SekMapMemory(TC0100SCNRam[1] , 0x2c0000, 0x2d3fff, SM_READ); + SekMapMemory(TC0100SCNRam[2] , 0x300000, 0x313fff, SM_READ); + SekSetReadByteHandler(0, Darius268K1ReadByte); + SekSetWriteByteHandler(0, Darius268K1WriteByte); + SekSetReadWordHandler(0, Darius268K1ReadWord); + SekSetWriteWordHandler(0, Darius268K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x080000, 0x08ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x240000, 0x24ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x260000, 0x263fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x280000, 0x293fff, SM_READ); + SekSetReadByteHandler(0, Darius268K2ReadByte); + SekSetWriteByteHandler(0, Darius268K2WriteByte); + SekSetReadWordHandler(0, Darius268K2ReadWord); + SekSetWriteWordHandler(0, Darius268K2WriteWord); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Darius2Z80Read); + ZetSetWriteHandler(Darius2Z80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &Darius2FMIRQHandler, Darius2SynchroniseStream, Darius2GetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoDrawFunction = Darius2Draw; + TaitoMakeInputsFunction = Darius2MakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = (16000000 / 2) / 60; + nTaitoCyclesTotal[1] = (16000000 / 2) / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + TaitoResetFunction = TaitoDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 Darius2dInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x8000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = Darius2dSpritePlaneOffsets; + TaitoSpriteAXOffsets = Darius2dSpriteXOffsets; + TaitoSpriteAYOffsets = Darius2dSpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + Darius2dMemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + Darius2dMemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 4, 24, 0, NULL); + TC0100SCNSetClipArea(0, 320, nScreenHeight, 0); + TC0100SCNInit(1, TaitoNumChar, 4, 24, 0, NULL); + TC0100SCNSetClipArea(1, 320, nScreenHeight, 320); + TC0100SCNSetPaletteOffset(1, 0x1000); + TC0110PCRInit(2, 0x2000); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x200000, 0x213fff, SM_READ); + SekMapMemory(TC0100SCNRam[1] , 0x240000, 0x253fff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x6013ff, SM_RAM); + SekSetReadByteHandler(0, Darius2d68KReadByte); + SekSetWriteByteHandler(0, Darius2d68KWriteByte); + SekSetReadWordHandler(0, Darius2d68KReadWord); + SekSetWriteWordHandler(0, Darius2d68KWriteWord); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Darius2Z80Read); + ZetSetWriteHandler(Darius2Z80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &Darius2FMIRQHandler, Darius2SynchroniseStream, Darius2GetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoDrawFunction = Darius2dDraw; + TaitoMakeInputsFunction = Darius2dMakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = (16000000 / 4) / 60; + + TaitoResetFunction = TaitoDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 NinjawInit() +{ + Ninjaw = 1; + return Darius2Init(); +} + +static INT32 WarriorbInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x10000; + + TaitoCharBModulo = 0x100; + TaitoCharBNumPlanes = 4; + TaitoCharBWidth = 8; + TaitoCharBHeight = 8; + TaitoCharBPlaneOffsets = CharPlaneOffsets; + TaitoCharBXOffsets = CharXOffsets; + TaitoCharBYOffsets = CharYOffsets; + TaitoNumCharB = 0x10000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = Darius2dSpritePlaneOffsets; + TaitoSpriteAXOffsets = Darius2dSpriteXOffsets; + TaitoSpriteAYOffsets = Darius2dSpriteYOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + WarriorbMemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + WarriorbMemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 4, 8, 0, NULL); + TC0100SCNSetClipArea(0, 320, nScreenHeight, 0); + TC0100SCNInit(1, TaitoNumCharB, 5, 8, 0, NULL); + TC0100SCNSetClipArea(1, 320, nScreenHeight, 320); + TC0100SCNSetPaletteOffset(1, 0x1000); + TC0110PCRInit(2, 0x2000); + TC0140SYTInit(); + TC0510NIOInit(); + + if (TaitoLoadRoms(1)) return 1; + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x1fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x213fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x300000, 0x313fff, SM_READ); + SekMapMemory(TC0100SCNRam[1] , 0x340000, 0x353fff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x6013ff, SM_RAM); + SekSetReadByteHandler(0, Warriorb68KReadByte); + SekSetWriteByteHandler(0, Warriorb68KWriteByte); + SekSetReadWordHandler(0, Warriorb68KReadWord); + SekSetWriteWordHandler(0, Warriorb68KWriteWord); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(Darius2Z80Read); + ZetSetWriteHandler(Darius2Z80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &Darius2FMIRQHandler, Darius2SynchroniseStream, Darius2GetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoDrawFunction = WarriorbDraw; + TaitoMakeInputsFunction = WarriorbMakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = 16000000 / 60; + nTaitoCyclesTotal[1] = (16000000 / 4) / 60; + + TaitoResetFunction = TaitoDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 Darius2Exit() +{ + Ninjaw = 0; + + BurnYM2610SetSoundMixMode(0); + + return TaitoExit(); +} + +static void Darius2RenderSprites(INT32 PriorityDraw) +{ + INT32 Offset, Data, Code, Colour, xFlip, yFlip; + INT32 x, y, Priority; + + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + + for (Offset = 0x2000 - 4; Offset >=0; Offset -= 4) { + Data = SpriteRam[Offset + 2]; + Code = Data & (TaitoNumSpriteA - 1); + + if (!Code) continue; + + Data = SpriteRam[Offset + 0]; + x = (Data - 32) & 0x3ff; + + Data = SpriteRam[Offset + 1]; + y = (Data - 0) & 0x1ff; + + Data = SpriteRam[Offset + 3]; + xFlip = (Data & 0x1); + yFlip = (Data & 0x2) >> 1; + Priority = (Data & 0x4) >> 2; + + if (Priority != PriorityDraw) continue; + + Colour = (Data & 0x7f00) >> 8; + + y -= 16; + + if (x > 0x3c0) x -= 0x400; + if (y > 0x180) y -= 0x200; + + if (x > 16 && x < (nScreenWidth - 16) && y > 16 && y < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } + } +} + +static void Darius2dRenderSprites(INT32 PriorityDraw) +{ + INT32 Offset, Data, Code, Colour, xFlip, yFlip; + INT32 x, y, Priority; + + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + +// for (Offset = 0; Offset < 0x001400 / 2; Offset += 4) { + for (Offset = (0x1400 / 2) - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 1]; + Code = Data & (TaitoNumSpriteA - 1); + + Data = SpriteRam[Offset + 0]; + y = (-(Data & 0x1ff) - 24) & 0x1ff; + yFlip = (Data & 0x200) >> 9; + + Data = SpriteRam[Offset + 2]; + Priority = (Data & 0x100) >> 8; + Colour = Data & 0x7f; + + Data = SpriteRam[Offset + 3]; + x = Data & 0x3ff; + xFlip = (Data & 0x400) >> 10; + + if (Priority != PriorityDraw) continue; + + y -= 16; + + if (x > 0x3c0) x -= 0x400; + if (y > 0x180) y -= 0x200; + + if (x > 16 && x < (nScreenWidth - 16) && y > 16 && y < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } + } +} + +static void Darius2Draw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 Disable2 = TC0100SCNCtrl[1][6] & 0xf7; + INT32 Disable3 = TC0100SCNCtrl[2][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoChars); + if (!(Disable3 & 0x02)) TC0100SCNRenderFgLayer(2, 0, TaitoChars); + Darius2RenderSprites(1); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoChars); + if (!(Disable3 & 0x01)) TC0100SCNRenderBgLayer(2, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoChars); + if (!(Disable3 & 0x01)) TC0100SCNRenderBgLayer(2, 0, TaitoChars); + Darius2RenderSprites(1); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoChars); + if (!(Disable3 & 0x02)) TC0100SCNRenderFgLayer(2, 0, TaitoChars); + } + + Darius2RenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + if (!(Disable2 & 0x04)) TC0100SCNRenderCharLayer(1); + if (!(Disable3 & 0x04)) TC0100SCNRenderCharLayer(2); + BurnTransferCopy(TC0110PCRPalette); +} + +static void Darius2dDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 Disable2 = TC0100SCNCtrl[1][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoChars); + Darius2dRenderSprites(1); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoChars); + Darius2dRenderSprites(1); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoChars); + } + + Darius2dRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + if (!(Disable2 & 0x04)) TC0100SCNRenderCharLayer(1); + BurnTransferCopy(TC0110PCRPalette); +} + +static void WarriorbDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 Disable2 = TC0100SCNCtrl[1][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoCharsB); + Darius2dRenderSprites(1); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoCharsB); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoCharsB); + Darius2dRenderSprites(1); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoCharsB); + } + + Darius2dRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + if (!(Disable2 & 0x04)) TC0100SCNRenderCharLayer(1); + BurnTransferCopy(TC0110PCRPalette); +} + +static INT32 Darius2Frame() +{ + INT32 nInterleave = 100; + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == nInterleave - 1) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 # 2 + if ((TaitoCpuACtrl & 0x01)) { + nCurrentCPU = 1; + SekOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == nInterleave - 1) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[2] - nTaitoCyclesDone[2]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 Darius2dFrame() +{ + INT32 nInterleave = 100; + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == nInterleave - 1) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1] - nTaitoCyclesDone[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 Darius2Scan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029684; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + if (TaitoNumYM2610) BurnYM2610Scan(nAction, pnMin); + + SCAN_VAR(TaitoInput); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + } + + if (nAction & ACB_WRITE && TaitoZ80Bank) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvDarius2 = { + "darius2", NULL, NULL, NULL, "1989", + "Darius II (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, Darius2RomInfo, Darius2RomName, NULL, NULL, Darius2InputInfo, Darius2DIPInfo, + Darius2Init, Darius2Exit, Darius2Frame, NULL, Darius2Scan, + NULL, 0x3000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvDarius2d = { + "darius2d", "darius2", NULL, NULL, "1989", + "Darius II (dual screen) (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, Darius2dRomInfo, Darius2dRomName, NULL, NULL, Darius2dInputInfo, Darius2dDIPInfo, + Darius2dInit, Darius2Exit, Darius2dFrame, NULL, Darius2Scan, + NULL, 0x2000, 640, 224, 8, 3 +}; + +struct BurnDriver BurnDrvDarius2do = { + "darius2do", "darius2", NULL, NULL, "1989", + "Darius II (dual screen) (Japan old version)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, Darius2doRomInfo, Darius2doRomName, NULL, NULL, Darius2dInputInfo, Darius2dDIPInfo, + Darius2dInit, Darius2Exit, Darius2dFrame, NULL, Darius2Scan, + NULL, 0x2000, 640, 224, 8, 3 +}; + +struct BurnDriver BurnDrvNinjaw = { + "ninjaw", NULL, NULL, NULL, "1987", + "The Ninja Warriors (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, NinjawRomInfo, NinjawRomName, NULL, NULL, Darius2InputInfo, NinjawDIPInfo, + NinjawInit, Darius2Exit, Darius2Frame, NULL, Darius2Scan, + NULL, 0x3000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvNinjawj = { + "ninjawj", "ninjaw", NULL, NULL, "1987", + "The Ninja Warriors (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, NinjawjRomInfo, NinjawjRomName, NULL, NULL, Darius2InputInfo, NinjawjDIPInfo, + NinjawInit, Darius2Exit, Darius2Frame, NULL, Darius2Scan, + NULL, 0x3000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvNinjawu = { + "ninjawu", "ninjaw", NULL, NULL, "1987", + "The Ninja Warriors (US)\0", NULL, "Taito Corporation America (licensed to Romstar)", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, NinjawuRomInfo, NinjawuRomName, NULL, NULL, Darius2InputInfo, NinjawjDIPInfo, + NinjawInit, Darius2Exit, Darius2Frame, NULL, Darius2Scan, + NULL, 0x3000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvWarriorb = { + "warriorb", NULL, NULL, NULL, "1991", + "Warrior Blade - Rastan Saga Episode III (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, WarriorbRomInfo, WarriorbRomName, NULL, NULL, WarriorbInputInfo, WarriorbDIPInfo, + WarriorbInit, Darius2Exit, Darius2dFrame, NULL, Darius2Scan, + NULL, 0x2000, 640, 240, 8, 3 +}; diff --git a/src/burn/drivers/taito/d_othunder.cpp b/src/burn/drivers/taito/d_othunder.cpp new file mode 100644 index 00000000..8a16e7b6 --- /dev/null +++ b/src/burn/drivers/taito/d_othunder.cpp @@ -0,0 +1,1160 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" +#include "eeprom.h" +#include "burn_gun.h" + +static void OthunderDraw(); + +static bool bUseAsm68KCoreOldValue = false; + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo OthunderInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p2 start" }, + + A("P1 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "mouse x-axis" ), + A("P1 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "mouse button 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "mouse button 2" }, + + A("P2 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort2 , "p2 x-axis" ), + A("P2 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort3 , "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, + {"Dip 3" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, +}; + +STDINPUTINFO(Othunder) + +#undef A + +static void TC0220IOCMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[0] -= (TC0220IOCInputPort0[i] & 1) << i; + TC0220IOCInput[1] -= (TC0220IOCInputPort1[i] & 1) << i; + TC0220IOCInput[2] -= (TC0220IOCInputPort2[i] & 1) << i; + } +} + +static void OthunderMakeInputs() +{ + TC0220IOCMakeInputs(); + + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); + BurnGunMakeInputs(1, (INT16)TaitoAnalogPort2, (INT16)TaitoAnalogPort3); +} + +static struct BurnDIPInfo OthunderDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0x7f, NULL }, + {0x10, 0xff, 0xff, 0x07, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0e, 0x01, 0x02, 0x00, "Off" }, + {0x0e, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x08, 0x00, "Off" }, + {0x0e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0e, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0x03, 0x02, "Easy" }, + {0x0f, 0x01, 0x03, 0x03, "Medium" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Magazines/Rockets" }, + {0x0f, 0x01, 0x0c, 0x0c, "5/3" }, + {0x0f, 0x01, 0x0c, 0x08, "6/4" }, + {0x0f, 0x01, 0x0c, 0x04, "7/5" }, + {0x0f, 0x01, 0x0c, 0x00, "8/6" }, + + {0 , 0xfe, 0 , 4 , "Bullets per Magazine" }, + {0x0f, 0x01, 0x30, 0x00, "30" }, + {0x0f, 0x01, 0x30, 0x10, "35" }, + {0x0f, 0x01, 0x30, 0x30, "40" }, + {0x0f, 0x01, 0x30, 0x20, "50" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x80, 0x00, "English" }, + {0x0f, 0x01, 0x80, 0x80, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Stereo Seperation" }, + {0x10, 0x01, 0x07, 0x07, "Maximum" }, + {0x10, 0x01, 0x07, 0x03, "High" }, + {0x10, 0x01, 0x07, 0x01, "Medium" }, + {0x10, 0x01, 0x07, 0x00, "Low" }, +}; + +STDDIPINFO(Othunder) + +static struct BurnDIPInfo OthunderjDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0x7f, NULL }, + {0x10, 0xff, 0xff, 0x07, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0e, 0x01, 0x02, 0x00, "Off" }, + {0x0e, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x08, 0x00, "Off" }, + {0x0e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0x03, 0x02, "Easy" }, + {0x0f, 0x01, 0x03, 0x03, "Medium" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Magazines/Rockets" }, + {0x0f, 0x01, 0x0c, 0x0c, "5/3" }, + {0x0f, 0x01, 0x0c, 0x08, "6/4" }, + {0x0f, 0x01, 0x0c, 0x04, "7/5" }, + {0x0f, 0x01, 0x0c, 0x00, "8/6" }, + + {0 , 0xfe, 0 , 4 , "Bullets per Magazine" }, + {0x0f, 0x01, 0x30, 0x00, "30" }, + {0x0f, 0x01, 0x30, 0x10, "35" }, + {0x0f, 0x01, 0x30, 0x30, "40" }, + {0x0f, 0x01, 0x30, 0x20, "50" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x80, 0x00, "English" }, + {0x0f, 0x01, 0x80, 0x80, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Stereo Seperation" }, + {0x10, 0x01, 0x07, 0x07, "Maximum" }, + {0x10, 0x01, 0x07, 0x03, "High" }, + {0x10, 0x01, 0x07, 0x01, "Medium" }, + {0x10, 0x01, 0x07, 0x00, "Low" }, +}; + +STDDIPINFO(Othunderj) + +static struct BurnDIPInfo OthunderuDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0x7f, NULL }, + {0x10, 0xff, 0xff, 0x07, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0e, 0x01, 0x02, 0x00, "Off" }, + {0x0e, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x08, 0x00, "Off" }, + {0x0e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0x03, 0x02, "Easy" }, + {0x0f, 0x01, 0x03, 0x03, "Medium" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Magazines/Rockets" }, + {0x0f, 0x01, 0x0c, 0x0c, "5/3" }, + {0x0f, 0x01, 0x0c, 0x08, "6/4" }, + {0x0f, 0x01, 0x0c, 0x04, "7/5" }, + {0x0f, 0x01, 0x0c, 0x00, "8/6" }, + + {0 , 0xfe, 0 , 4 , "Bullets per Magazine" }, + {0x0f, 0x01, 0x30, 0x00, "30" }, + {0x0f, 0x01, 0x30, 0x10, "35" }, + {0x0f, 0x01, 0x30, 0x30, "40" }, + {0x0f, 0x01, 0x30, 0x20, "50" }, + + {0 , 0xfe, 0 , 2 , "Continue Price" }, + {0x0f, 0x01, 0x40, 0x00, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0x40, 0x40, "Same as Start" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x80, 0x00, "English" }, + {0x0f, 0x01, 0x80, 0x80, "Japanese" }, + + // Dip 3 + {0 , 0xfe, 0 , 4 , "Stereo Seperation" }, + {0x10, 0x01, 0x07, 0x07, "Maximum" }, + {0x10, 0x01, 0x07, 0x03, "High" }, + {0x10, 0x01, 0x07, 0x01, "Medium" }, + {0x10, 0x01, 0x07, 0x00, "Low" }, +}; + +STDDIPINFO(Othunderu) + +static struct BurnRomInfo OthunderRomDesc[] = { + { "b67-20.63", 0x20000, 0x21439ea2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-23.64", 0x20000, 0x789e9daa, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-14.61", 0x20000, 0x7f3dd724, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-15.62", 0x20000, 0xe84f62d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b67-13.40", 0x10000, 0x2936b4b1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b67-06.66", 0x80000, 0xb9a38d64, BRF_GRA | TAITO_CHARS}, + + { "b67-01", 0x80000, 0x81ad9acb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-02", 0x80000, 0xc20cd2fb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-03", 0x80000, 0xbc9019ed, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-04", 0x80000, 0x2af4c8af, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b67-05.43", 0x80000, 0x9593e42b, BRF_GRA | TAITO_SPRITEMAP }, + + { "b67-08", 0x80000, 0x458f41fb, BRF_SND | TAITO_YM2610A }, + + { "b67-07", 0x80000, 0x4f834357, BRF_SND | TAITO_YM2610B }, + + { "eeprom-othunder.bin", 0x00080, 0x3729b844, BRF_PRG | TAITO_DEFAULT_EEPROM }, + + { "plhs18p8b-b67-09.ic15", 0x00149, 0x62035487, BRF_OPT }, + { "pal16l8a-b67-11.ic36", 0x00104, 0x3177fb06, BRF_OPT }, + { "pal20l8b-b67-12.ic37", 0x00144, 0xa47c2798, BRF_OPT }, + { "pal20l8b-b67-10.ic33", 0x00144, 0x4ced09c7, BRF_OPT }, +}; + +STD_ROM_PICK(Othunder) +STD_ROM_FN(Othunder) + +static struct BurnRomInfo OthunderuRomDesc[] = { + { "b67-20-1.63", 0x20000, 0x851a453b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-22-1.64", 0x20000, 0x19480dc0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-14.61", 0x20000, 0x7f3dd724, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-15.62", 0x20000, 0xe84f62d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b67-13.40", 0x10000, 0x2936b4b1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b67-06.66", 0x80000, 0xb9a38d64, BRF_GRA | TAITO_CHARS}, + + { "b67-01", 0x80000, 0x81ad9acb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-02", 0x80000, 0xc20cd2fb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-03", 0x80000, 0xbc9019ed, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-04", 0x80000, 0x2af4c8af, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b67-05.43", 0x80000, 0x9593e42b, BRF_GRA | TAITO_SPRITEMAP }, + + { "b67-08", 0x80000, 0x458f41fb, BRF_SND | TAITO_YM2610A }, + + { "b67-07", 0x80000, 0x4f834357, BRF_SND | TAITO_YM2610B }, + + { "eeprom-othunder.bin", 0x00080, 0x3729b844, BRF_PRG | TAITO_DEFAULT_EEPROM }, + + { "plhs18p8b-b67-09.ic15", 0x00149, 0x62035487, BRF_OPT }, + { "pal16l8a-b67-11.ic36", 0x00104, 0x3177fb06, BRF_OPT }, + { "pal20l8b-b67-12.ic37", 0x00144, 0xa47c2798, BRF_OPT }, + { "pal20l8b-b67-10.ic33", 0x00144, 0x4ced09c7, BRF_OPT }, +}; + +STD_ROM_PICK(Othunderu) +STD_ROM_FN(Othunderu) + +static struct BurnRomInfo OthunderuoRomDesc[] = { + { "b67-20.63", 0x20000, 0x21439ea2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-22.64", 0x20000, 0x0f99ad3c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-14.61", 0x20000, 0x7f3dd724, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-15.62", 0x20000, 0xe84f62d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b67-13.40", 0x10000, 0x2936b4b1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b67-06.66", 0x80000, 0xb9a38d64, BRF_GRA | TAITO_CHARS}, + + { "b67-01", 0x80000, 0x81ad9acb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-02", 0x80000, 0xc20cd2fb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-03", 0x80000, 0xbc9019ed, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-04", 0x80000, 0x2af4c8af, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b67-05.43", 0x80000, 0x9593e42b, BRF_GRA | TAITO_SPRITEMAP }, + + { "b67-08", 0x80000, 0x458f41fb, BRF_SND | TAITO_YM2610A }, + + { "b67-07", 0x80000, 0x4f834357, BRF_SND | TAITO_YM2610B }, + + { "eeprom-othunder.bin", 0x00080, 0x3729b844, BRF_PRG | TAITO_DEFAULT_EEPROM }, + + { "plhs18p8b-b67-09.ic15", 0x00149, 0x62035487, BRF_OPT }, + { "pal16l8a-b67-11.ic36", 0x00104, 0x3177fb06, BRF_OPT }, + { "pal20l8b-b67-12.ic37", 0x00144, 0xa47c2798, BRF_OPT }, + { "pal20l8b-b67-10.ic33", 0x00144, 0x4ced09c7, BRF_OPT }, +}; + +STD_ROM_PICK(Othunderuo) +STD_ROM_FN(Othunderuo) + +static struct BurnRomInfo OthunderjRomDesc[] = { + { "b67-20.63", 0x20000, 0x21439ea2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-21.64", 0x20000, 0x9690fc86, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-14.61", 0x20000, 0x7f3dd724, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b67-15.62", 0x20000, 0xe84f62d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b67-13.40", 0x10000, 0x2936b4b1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b67-06.66", 0x80000, 0xb9a38d64, BRF_GRA | TAITO_CHARS}, + + { "b67-01", 0x80000, 0x81ad9acb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-02", 0x80000, 0xc20cd2fb, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-03", 0x80000, 0xbc9019ed, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b67-04", 0x80000, 0x2af4c8af, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b67-05.43", 0x80000, 0x9593e42b, BRF_GRA | TAITO_SPRITEMAP }, + + { "b67-08", 0x80000, 0x458f41fb, BRF_SND | TAITO_YM2610A }, + + { "b67-07", 0x80000, 0x4f834357, BRF_SND | TAITO_YM2610B }, + + { "eeprom-othunder.bin", 0x00080, 0x3729b844, BRF_PRG | TAITO_DEFAULT_EEPROM }, + + { "plhs18p8b-b67-09.ic15", 0x00149, 0x62035487, BRF_OPT }, + { "pal16l8a-b67-11.ic36", 0x00104, 0x3177fb06, BRF_OPT }, + { "pal20l8b-b67-12.ic37", 0x00144, 0xa47c2798, BRF_OPT }, + { "pal20l8b-b67-10.ic33", 0x00144, 0x4ced09c7, BRF_OPT }, +}; + +STD_ROM_PICK(Othunderj) +STD_ROM_FN(Othunderj) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoSpriteMapRom = Next; Next += TaitoSpriteMapRomSize; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + TaitoDefaultEEProm = Next; Next += TaitoDefaultEEPromSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x10000; + TaitoZ80Ram1 = Next; Next += 0x02000; + TaitoSpriteRam = Next; Next += 0x00600; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 OthunderDoReset() +{ + TaitoDoReset(); + + return 0; +} + +static UINT8 OthunderInputBypassRead(INT32 Offset) +{ + switch (Offset) { + case 0x03: { + return (EEPROMRead() & 1) << 7; + } + + default: { + return TC0220IOCRead(Offset); + } + } + + return 0; +} + +static void OthunderInputBypassWrite(INT32 Offset, UINT16 Data) +{ + switch (Offset) { + case 0x03: { + EEPROMWrite(Data & 0x20, Data & 0x10, Data & 0x40); + return; + } + + default: { + TC0220IOCWrite(Offset, Data & 0xff); + } + } +} + +UINT8 __fastcall Othunder68KReadByte(UINT32 a) +{ + switch (a) { + case 0x500001: { + return ~BurnGunReturnX(0); + } + + case 0x500003: { + return BurnGunReturnY(0); + } + + case 0x500005: { + return ~BurnGunReturnX(1); + } + + case 0x500007: { + return BurnGunReturnY(1); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Othunder68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x200000, 0x20ffff) + + switch (a) { + case 0x500001: + case 0x500003: + case 0x500005: + case 0x500007: { + nTaitoCyclesDone[0] += SekRun(10); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Othunder68KReadWord(UINT32 a) +{ + switch (a) { + case 0x090000: + case 0x090002: + case 0x090004: + case 0x090006: + case 0x090008: + case 0x09000a: + case 0x09000c: + case 0x09000e: { + return OthunderInputBypassRead((a - 0x090000) >> 1); + } + + case 0x100002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Othunder68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x200000, 0x20ffff) + TC0100SCN0CtrlWordWrite_Map(0x220000) + + switch (a) { + case 0x090000: + case 0x090002: + case 0x090004: + case 0x090006: + case 0x090008: + case 0x09000a: + case 0x09000c: + case 0x09000e: { + OthunderInputBypassWrite((a - 0x090000) >> 1, d); + return; + } + + case 0x100000: + case 0x100002: + case 0x100004: { + TC0110PCRStep1RBSwapWordWrite(0, (a - 0x100000) >> 1, d); + return; + } + + case 0x300000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0x300002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0x500000: + case 0x500002: + case 0x500004: + case 0x500006: { + nTaitoCyclesDone[0] += SekRun(10); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + return; + } + + case 0x600000: + case 0x600002: { + // irq ack + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall OthunderZ80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe002: { + return BurnYM2610Read(2); + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + case 0xea00: { + return TaitoDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall OthunderZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xe400: + case 0xe401: + case 0xe402: + case 0xe403: { + return; + } + + case 0xe600: { + // nop + return; + } + + case 0xee00: { + // nop + return; + } + + case 0xf000: { + // nop + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 7; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static const eeprom_interface othunder_eeprom_interface = { + 6, /* address bits */ + 16, /* data bits */ + "0110", /* read command */ + "0101", /* write command */ + "0111", /* erase command */ + "0100000000", /* lock command */ + "0100111111", /* unlock command */ + 0, + 0 +}; + +static const UINT8 othunder_default_eeprom[128] = { + 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x41, 0x41, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0xf0, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x41, 0x41, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0xf0, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x01, 0x42, 0x85, 0x00, 0x00, 0xf1, 0xe3, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x01, 0x42, 0x85, 0x00, 0x00, 0xf1, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static void OthunderFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 OthunderSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (16000000 / 4); +} + +static double OthunderGetTime() +{ + return (double)ZetTotalCycles() / (16000000 / 4); +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 SpritePlaneOffsets[4] = { 0, 8, 16, 24 }; +static INT32 SpriteXOffsets[16] = { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 SpriteYOffsets[8] = { 0, 64, 128, 192, 256, 320, 384, 448 }; + +static void SwitchToMusashi() +{ + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } +} + +static INT32 OthunderInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + TaitoNumEEPROM = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 4, 8, 1, NULL); + TC0110PCRInit(1, 0x1000); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x080000, 0x08ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x200000, 0x20ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x400000, 0x4005ff, SM_RAM); + SekSetReadWordHandler(0, Othunder68KReadWord); + SekSetWriteWordHandler(0, Othunder68KWriteWord); + SekSetReadByteHandler(0, Othunder68KReadByte); + SekSetWriteByteHandler(0, Othunder68KWriteByte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(OthunderZ80Read); + ZetSetWriteHandler(OthunderZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &OthunderFMIRQHandler, OthunderSynchroniseStream, OthunderGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + EEPROMInit(&othunder_eeprom_interface); + if (!EEPROMAvailable()) EEPROMFill(TaitoDefaultEEProm, 0, 128); + + TaitoMakeInputsFunction = OthunderMakeInputs; + TaitoDrawFunction = OthunderDraw; + TaitoIrqLine = 5; + TaitoFrameInterleave = 100; + TaitoFlipScreenX = 1; + + nTaitoCyclesTotal[0] = 13000000 / 60; + nTaitoCyclesTotal[1] = (16000000 / 4) / 60; + + BurnGunInit(2, true); + + // Reset the driver + OthunderDoReset(); + + return 0; +} + +static INT32 OthunderExit() +{ + TaitoExit(); + + BurnGunExit(); + + BurnYM2610SetSoundMixMode(0); + + // Switch back CPU core if needed + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + return 0; +} + +static void RenderSpriteZoom(INT32 Code, INT32 sx, INT32 sy, INT32 Colour, INT32 xFlip, INT32 yFlip, INT32 xScale, INT32 yScale, UINT8* pSource) +{ + // We can use sprite A for sizes, etc. as only Chase HQ uses sprite B and it has the same sizes and count + + UINT8 *SourceBase = pSource + ((Code % TaitoNumSpriteA) * TaitoSpriteAWidth * TaitoSpriteAHeight); + + INT32 SpriteScreenHeight = (yScale * TaitoSpriteAHeight + 0x8000) >> 16; + INT32 SpriteScreenWidth = (xScale * TaitoSpriteAWidth + 0x8000) >> 16; + + Colour = 0x10 * (Colour % 0x100); + + if (TaitoFlipScreenX) { + xFlip = !xFlip; + sx = 320 - sx - (xScale >> 12); + } + + if (SpriteScreenWidth && SpriteScreenHeight) { + INT32 dx = (TaitoSpriteAWidth << 16) / SpriteScreenWidth; + INT32 dy = (TaitoSpriteAHeight << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (xFlip) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (yFlip) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth) { + INT32 Pixels = ex - nScreenWidth; + ex -= Pixels; + } + + if (ey > nScreenHeight) { + INT32 Pixels = ey - nScreenHeight; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * TaitoSpriteAWidth); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + INT32 x, xIndex = xIndexBase; + for (x = sx; x < ex; x++) { + INT32 c = Source[xIndex >> 16]; + if (c != 0) { + pPixel[x] = c | Colour; + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +static void OthunderRenderSprites(INT32 PriorityDraw) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + INT32 BadChunks; + + for (Offset = 0x300 - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + Data = SpriteRam[Offset + 3]; + yFlip = (Data & 0x8000) >> 15; + Tile = Data & 0x1fff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0xfe00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + Colour = (Data & 0xff00) >> 8; + xZoom = (Data & 0x7f); + + MapOffset = Tile << 5; + + xZoom += 1; + yZoom += 1; + + y += 3; + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + BadChunks = 0; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + k = SpriteChunk % 4; + j = SpriteChunk / 4; + + px = xFlip ? (3 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteA - 1); + + if (Code == 0xffff) { + BadChunks += 1; + continue; + } + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + + } +} + +static void OthunderDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + OthunderRenderSprites(1); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + OthunderRenderSprites(1); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + OthunderRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static INT32 OthunderFrame() +{ + INT32 nInterleave = TaitoFrameInterleave; + + if (TaitoReset) OthunderDoReset(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (TaitoFrameInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 OthunderScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029709; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + + BurnGunScan(); + + SCAN_VAR(TaitoInput); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + } + + if (nAction & ACB_WRITE) { + if (TaitoZ80Bank) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + } + + return 0; +} + +struct BurnDriver BurnDrvOthunder = { + "othunder", NULL, NULL, NULL, "1988", + "Operation Thunderbolt (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OthunderRomInfo, OthunderRomName, NULL, NULL, OthunderInputInfo, OthunderDIPInfo, + OthunderInit, OthunderExit, OthunderFrame, NULL, OthunderScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOthunderu = { + "othunderu", "othunder", NULL, NULL, "1988", + "Operation Thunderbolt (US)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OthunderuRomInfo, OthunderuRomName, NULL, NULL, OthunderInputInfo, OthunderuDIPInfo, + OthunderInit, OthunderExit, OthunderFrame, NULL, OthunderScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOthunderuo = { + "othunderuo", "othunder", NULL, NULL, "1988", + "Operation Thunderbolt (US, older)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OthunderuoRomInfo, OthunderuoRomName, NULL, NULL, OthunderInputInfo, OthunderuDIPInfo, + OthunderInit, OthunderExit, OthunderFrame, NULL, OthunderScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOthunderj = { + "othunderj", "othunder", NULL, NULL, "1988", + "Operation Thunderbolt (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OthunderjRomInfo, OthunderjRomName, NULL, NULL, OthunderInputInfo, OthunderjDIPInfo, + OthunderInit, OthunderExit, OthunderFrame, NULL, OthunderScan, + NULL, 0x1000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_slapshot.cpp b/src/burn/drivers/taito/d_slapshot.cpp new file mode 100644 index 00000000..da4b9b82 --- /dev/null +++ b/src/burn/drivers/taito/d_slapshot.cpp @@ -0,0 +1,930 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" +#include "eeprom.h" +#include "burn_gun.h" +#include "timekpr.h" + +static void SlapshotDraw(); +static void Opwolf3Draw(); +static TaitoF2SpriteBufferUpdate TaitoF2SpriteBufferFunction; + +static bool bUseAsm68KCoreOldValue = false; + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo SlapshotInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0640FIOInputPort1 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0640FIOInputPort3 + 4, "p1 start" }, + {"Start 2" , BIT_DIGITAL , TC0640FIOInputPort3 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0640FIOInputPort4 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0640FIOInputPort4 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0640FIOInputPort4 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0640FIOInputPort4 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0640FIOInputPort2 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0640FIOInputPort2 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0640FIOInputPort2 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0640FIOInputPort4 + 4, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0640FIOInputPort4 + 5, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0640FIOInputPort4 + 6, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0640FIOInputPort4 + 7, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0640FIOInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0640FIOInputPort2 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0640FIOInputPort2 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0640FIOInputPort3 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TC0640FIOInputPort1 + 1, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, +}; + +STDINPUTINFO(Slapshot) + +static struct BurnInputInfo Opwolf3InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0640FIOInputPort1 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0640FIOInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0640FIOInputPort1 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0640FIOInputPort2 + 6, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , TC0640FIOInputPort1 + 6, "p3 coin" }, + {"Coin 4" , BIT_DIGITAL , TC0640FIOInputPort1 + 7, "p4 coin" }, + + A("P1 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "mouse x-axis" ), + A("P1 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TC0640FIOInputPort2 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0640FIOInputPort2 + 1, "p1 fire 2" }, + + A("P2 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort2 , "p2 x-axis" ), + A("P2 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort3 , "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , TC0640FIOInputPort2 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0640FIOInputPort2 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0640FIOInputPort3 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TC0640FIOInputPort1 + 1, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, +}; + +STDINPUTINFO(Opwolf3) + +#undef A + +static void TC0640FIOMakeInputs() +{ + TC0640FIOInput[0] = 0xff; + TC0640FIOInput[1] = 0xff; + TC0640FIOInput[2] = 0xff; + TC0640FIOInput[3] = 0xff; + TC0640FIOInput[4] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TC0640FIOInput[0] -= (TC0640FIOInputPort0[i] & 1) << i; + TC0640FIOInput[1] -= (TC0640FIOInputPort1[i] & 1) << i; + TC0640FIOInput[2] -= (TC0640FIOInputPort2[i] & 1) << i; + TC0640FIOInput[3] -= (TC0640FIOInputPort3[i] & 1) << i; + TC0640FIOInput[4] -= (TC0640FIOInputPort4[i] & 1) << i; + } +} + +static void Opwolf3MakeInputs() +{ + TC0640FIOMakeInputs(); + + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); + BurnGunMakeInputs(1, (INT16)TaitoAnalogPort2, (INT16)TaitoAnalogPort3); +} + +static struct BurnDIPInfo SlapshotDIPList[]= +{ + {0x14, 0xff, 0xff, 0x10, NULL }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x14, 0x01, 0x10, 0x10, "Off" }, + {0x14, 0x01, 0x10, 0x00, "On" }, +}; + +STDDIPINFO(Slapshot) + +static struct BurnDIPInfo Opwolf3DIPList[]= +{ + {0x11, 0xff, 0xff, 0x10, NULL }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x10, 0x10, "Off" }, + {0x11, 0x01, 0x10, 0x00, "On" }, +}; + +STDDIPINFO(Opwolf3) + +static struct BurnRomInfo SlapshotRomDesc[] = { + { "d71-15.3", 0x080000, 0x1470153f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d71-16.1", 0x080000, 0xf13666e0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d71-07.77", 0x010000, 0xdd5f670c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d71-04.79", 0x080000, 0xb727b81c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d71-05.80", 0x080000, 0x7b0f5d6d, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d71-06.37", 0x080000, 0xf3324188, BRF_SND | TAITO_YM2610A }, + + // Sprites - handled manually + { "d71-01.23", 0x100000, 0x0b1e8c27, BRF_GRA }, + { "d71-02.24", 0x100000, 0xccaaea2d, BRF_GRA }, + { "d71-03.25", 0x100000, 0xdccef9ec, BRF_GRA }, +}; + +STD_ROM_PICK(Slapshot) +STD_ROM_FN(Slapshot) + +static struct BurnRomInfo Opwolf3RomDesc[] = { + { "d74_16.3", 0x080000, 0x198ff1f6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_21.1", 0x080000, 0xc61c558b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_18.18", 0x080000, 0xbd5d7cdb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_17.17", 0x080000, 0xac35a672, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d74_22.77", 0x010000, 0x118374a6, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d74_05.80", 0x200000, 0x85ea64cc, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d74_06.81", 0x200000, 0x2fa1e08d, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d74_01.37", 0x200000, 0x115313e0, BRF_SND | TAITO_YM2610A }, + + // Sprites - handled manually + { "d74_02.23", 0x200000, 0xaab86332, BRF_GRA }, + { "d74_03.24", 0x200000, 0x3f398916, BRF_GRA }, + { "d74_04.25", 0x200000, 0x2f385638, BRF_GRA }, +}; + +STD_ROM_PICK(Opwolf3) +STD_ROM_FN(Opwolf3) + +static struct BurnRomInfo Opwolf3uRomDesc[] = { + { "d74_16.3", 0x080000, 0x198ff1f6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_20.1", 0x080000, 0x960fd892, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_18.18", 0x080000, 0xbd5d7cdb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d74_17.17", 0x080000, 0xac35a672, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d74_19.77", 0x010000, 0x05d53f06, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d74_05.80", 0x200000, 0x85ea64cc, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d74_06.81", 0x200000, 0x2fa1e08d, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d74_01.37", 0x200000, 0x115313e0, BRF_SND | TAITO_YM2610A }, + + // Sprites - handled manually + { "d74_02.23", 0x200000, 0xaab86332, BRF_GRA }, + { "d74_03.24", 0x200000, 0x3f398916, BRF_GRA }, + { "d74_04.25", 0x200000, 0x2f385638, BRF_GRA }, +}; + +STD_ROM_PICK(Opwolf3u) +STD_ROM_FN(Opwolf3u) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x10000; + TaitoZ80Ram1 = Next; Next += 0x02000; + TaitoSpriteRam = Next; Next += 0x10000; + TaitoSpriteRamBuffered = Next; Next += 0x10000; + TaitoSpriteExtension = Next; Next += 0x02000; + TaitoPaletteRam = Next; Next += 0x08000; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + TaitoF2SpriteList = (TaitoF2SpriteEntry*)Next; Next += 0x400 * sizeof(TaitoF2SpriteEntry); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 SlapshotDoReset() +{ + TaitoDoReset(); + + return 0; +} + +UINT8 __fastcall Slapshot68KReadByte(UINT32 a) +{ + if (a >= 0xa00000 && a <= 0xa03fff) { + return TimeKeeperRead((a - 0xa00000) >> 1); + } + + if (a >= 0xc00000 && a <= 0xc0000f) { + return TC0640FIORead((a - 0xc00000) >> 1); + } + + if (a >= 0xc00020 && a <= 0xc0002f) { + if (a == 0xc00027) bprintf(PRINT_IMPORTANT, _T("%x\n"), a); + + if (a == 0xc00026) return (TC0640FIOInput[2] & 0xef) | (TaitoDip[0] & 0x10); + + return TC0640FIORead((a - 0xc00020) >> 1); + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Slapshot68KWriteByte(UINT32 a, UINT8 d) +{ + if (a <= 0x0fffff) return; + + if (a >= 0xa00000 && a <= 0xa03fff) { + TimeKeeperWrite((a - 0xa00000) >> 1, d); + return; + } + + TC0360PRIHalfWordWrite_Map(0xb00000) + + if (a >= 0xc00000 && a <= 0xc0000f) { + TC0640FIOWrite((a - 0xc00000) >> 1, d); + return; + } + + if (a >= 0xc00010 && a <= 0xc0002f) { + return; + } + + switch (a) { + case 0xd00000: { + TC0140SYTPortWrite(d); + return; + } + + case 0xd00002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Slapshot68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Slapshot68KWriteWord(UINT32 a, UINT16 d) +{ + TC0480SCPCtrlWordWrite_Map(0x830000) + + if (a >= 0xc00000 && a <= 0xc0000f) { + TC0640FIOWrite((a - 0xc00000) >> 1, d); + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Opwolf3Gun68KReadByte(UINT32 a) +{ + switch (a) { + case 0xe00000: { + float Temp = (float)~BurnGunReturnX(0) / 256.0; + Temp *= 160.0; + return ((UINT8)Temp - 0x5b) & 0xff; + } + + case 0xe00002: { + float Temp = (float)BurnGunReturnY(0) / 256.0; + Temp *= 112; + return ((UINT8)Temp + 0x08) & 0xff; + } + + case 0xe00004: { + float Temp = (float)~BurnGunReturnX(1) / 256.0; + Temp *= 160.0; + return ((UINT8)Temp - 0x5b) & 0xff; + } + + case 0xe00006: { + float Temp = (float)BurnGunReturnY(1) / 256.0; + Temp *= 112; + return ((UINT8)Temp + 0x08) & 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Opwolf3Gun68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xe00000: + case 0xe00002: + case 0xe00004: + case 0xe00006: { + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Opwolf3Gun68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Opwolf3Gun68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall SlapshotZ80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall SlapshotZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 7; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static void SlapshotFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 SlapshotSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double SlapshotGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[16] = { 4, 0, 20, 16, 12, 8, 28, 24, 36, 32, 52, 48, 44, 40, 60, 56 }; +static INT32 CharYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 SpritePlaneOffsets[6] = { 0x1000000, 0x1000001, 0, 1, 2, 3 }; +static INT32 SpriteXOffsets[16] = { 4, 0, 12, 8, 20, 16, 28, 24, 36, 32, 44, 40, 52, 48, 60, 56 }; +static INT32 SpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 Opwolf3SpritePlaneOffsets[6] = { 0x2000000, 0x2000001, 0, 1, 2, 3 }; + +static void SwitchToMusashi() +{ + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } +} + +static INT32 MachineInit() +{ + INT32 nLen; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0480SCPInit(TaitoNumChar, 3, 30, 9, -1, 1, -2); + TC0480SCPSetColourBase(256); + TC0140SYTInit(); + TC0360PRIInit(); + TC0640FIOInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, Taito68KRom1Size - 1, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x500000, 0x50ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x60ffff, SM_RAM); + SekMapMemory(TaitoSpriteExtension , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x900000, 0x907fff, SM_RAM); + SekSetReadWordHandler(0, Slapshot68KReadWord); + SekSetWriteWordHandler(0, Slapshot68KWriteWord); + SekSetReadByteHandler(0, Slapshot68KReadByte); + SekSetWriteByteHandler(0, Slapshot68KWriteByte); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(SlapshotZ80Read); + ZetSetWriteHandler(SlapshotZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(8000000, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &SlapshotFMIRQHandler, SlapshotSynchroniseStream, SlapshotGetTime, 0); + BurnTimerAttachZet(4000000); + + TaitoMakeInputsFunction = TC0640FIOMakeInputs; + TaitoDrawFunction = SlapshotDraw; + + nTaitoCyclesTotal[0] = 14364000 / 60; + nTaitoCyclesTotal[1] = 4000000 / 60; + + TimeKeeperInit(TIMEKEEPER_MK48T08, NULL); + + TaitoF2SpritesDisabled = 1; + TaitoF2SpritesActiveArea = 0; + TaitoF2SpriteType = 2; + TaitoXOffset = 3; + + TaitoF2SpriteBufferFunction = TaitoF2NoBuffer; + + for (INT32 i = 0; i < 8; i++) { + TaitoF2SpriteBankBuffered[i] = 0x400 * i; + TaitoF2SpriteBank[i] = TaitoF2SpriteBankBuffered[i]; + } + + return 0; +} + +static INT32 SlapshotInit() +{ + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 6; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + if (MachineInit()) return 1; + + INT32 nRet; + UINT8 *TempRom = (UINT8*)malloc(0x400000); + memset(TempRom, 0, 0x400000); + nRet = BurnLoadRom(TempRom + 0x000000, 6, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000001, 7, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x300000, 8, 1); if (nRet) return 1; + INT32 Data; + INT32 Offset = 0x400000 / 2; + for (INT32 i = 0x400000 / 2 + 0x400000 / 4; i < 0x400000; i++) { + INT32 d1, d2, d3, d4; + + Data = TempRom[i]; + d1 = (Data >> 0) & 3; + d2 = (Data >> 2) & 3; + d3 = (Data >> 4) & 3; + d4 = (Data >> 6) & 3; + + TempRom[Offset] = (d1 << 2) | (d2 << 6); + Offset++; + + TempRom[Offset] = (d3 << 2) | (d4 << 6); + Offset++; + } + GfxDecode(TaitoNumSpriteA, TaitoSpriteANumPlanes, TaitoSpriteAWidth, TaitoSpriteAHeight, TaitoSpriteAPlaneOffsets, TaitoSpriteAXOffsets, TaitoSpriteAYOffsets, TaitoSpriteAModulo, TempRom, TaitoSpritesA); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + SlapshotDoReset(); + + return 0; +} + +static INT32 Opwolf3Init() +{ + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x8000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 6; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = Opwolf3SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x8000; + + if (MachineInit()) return 1; + + INT32 nRet; + UINT8 *TempRom = (UINT8*)malloc(0x800000); + memset(TempRom, 0, 0x400000); + nRet = BurnLoadRom(TempRom + 0x000000, 8, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000001, 9, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x600000, 10, 1); if (nRet) return 1; + INT32 Data; + INT32 Offset = 0x800000 / 2; + for (INT32 i = 0x800000 / 2 + 0x800000 / 4; i < 0x800000; i++) { + INT32 d1, d2, d3, d4; + + Data = TempRom[i]; + d1 = (Data >> 0) & 3; + d2 = (Data >> 2) & 3; + d3 = (Data >> 4) & 3; + d4 = (Data >> 6) & 3; + + TempRom[Offset] = (d1 << 2) | (d2 << 6); + Offset++; + + TempRom[Offset] = (d3 << 2) | (d4 << 6); + Offset++; + } + GfxDecode(TaitoNumSpriteA, TaitoSpriteANumPlanes, TaitoSpriteAWidth, TaitoSpriteAHeight, TaitoSpriteAPlaneOffsets, TaitoSpriteAXOffsets, TaitoSpriteAYOffsets, TaitoSpriteAModulo, TempRom, TaitoSpritesA); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + SekOpen(0); + SekMapHandler(1, 0xe00000, 0xe00007, SM_RAM); + SekSetReadWordHandler(1, Opwolf3Gun68KReadWord); + SekSetWriteWordHandler(1, Opwolf3Gun68KWriteWord); + SekSetReadByteHandler(1, Opwolf3Gun68KReadByte); + SekSetWriteByteHandler(1, Opwolf3Gun68KWriteByte); + SekClose(); + + TaitoMakeInputsFunction = Opwolf3MakeInputs; + TaitoDrawFunction = Opwolf3Draw; + + BurnGunInit(2, true); + + SlapshotDoReset(); + + return 0; +} + +static INT32 SlapshotExit() +{ + TaitoExit(); + + // Switch back CPU core if needed + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + TimeKeeperExit(); + + return 0; +} + +static INT32 Opwolf3Exit() +{ + INT32 nRet = SlapshotExit(); + + BurnGunExit(); + + return nRet; +} + +inline static INT32 CalcCol(INT32 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x000000ff) >> 0; + g = (nColour & 0xff000000) >> 24; + b = (nColour & 0x00ff0000) >> 16; + + return BurnHighCol(r, g, b, 0); +} + +static void SlapshotCalcPalette() +{ + INT32 i; + UINT32* ps; + UINT32* pd; + + for (i = 0, ps = (UINT32*)TaitoPaletteRam, pd = TaitoPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void SlapshotDraw() +{ + UINT8 Layer[4]; + UINT16 Priority = TC0480SCPGetBgPriority(); + + Layer[0] = (Priority & 0xf000) >> 12; + Layer[1] = (Priority & 0x0f00) >> 8; + Layer[2] = (Priority & 0x00f0) >> 4; + Layer[3] = (Priority & 0x000f) >> 0; + + TaitoF2TilePriority[Layer[0]] = TC0360PRIRegs[4] & 0x0f; + TaitoF2TilePriority[Layer[1]] = TC0360PRIRegs[4] >> 4; + TaitoF2TilePriority[Layer[2]] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[Layer[3]] = TC0360PRIRegs[5] >> 4; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + SlapshotCalcPalette(); + BurnTransferClear(); + + TaitoF2MakeSpriteList(); + + for (INT32 i = 0; i < 16; i++) { + if (TaitoF2TilePriority[0] == i) TC0480SCPTilemapRender(Layer[0], 0, TaitoChars); + if (TaitoF2TilePriority[1] == i) TC0480SCPTilemapRender(Layer[1], 0, TaitoChars); + if (TaitoF2TilePriority[2] == i) TC0480SCPTilemapRender(Layer[2], 0, TaitoChars); + if (TaitoF2TilePriority[3] == i) TC0480SCPTilemapRender(Layer[3], 0, TaitoChars); + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + } + + TC0480SCPRenderCharLayer(); + + BurnTransferCopy(TaitoPalette); +} + +static void Opwolf3Draw() +{ + SlapshotDraw(); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static INT32 SlapshotFrame() +{ + INT32 nInterleave = 100; + + if (TaitoReset) SlapshotDoReset(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + if ((GetCurrentFrame() % 60) == 0) TimeKeeperTick(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 10) { SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); nTaitoCyclesDone[0] += SekRun(200000 - 500); } + if (i == (nInterleave - 1)) SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + SekClose(); + + ZetOpen(0); + BurnTimerUpdate(i * (nTaitoCyclesTotal[1] / nInterleave)); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + TaitoF2HandleSpriteBuffering(); + + if (pBurnDraw) TaitoDrawFunction(); + + TaitoF2SpriteBufferFunction(); + + return 0; +} + +static INT32 SlapshotScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029709; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + TimeKeeperScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + + SCAN_VAR(TC0640FIOInput); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + SCAN_VAR(TaitoF2SpriteBank); + SCAN_VAR(TaitoF2SpriteBankBuffered); + } + + if (nAction & ACB_WRITE) { + if (TaitoZ80Bank) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + } + + return 0; +} + +static INT32 Opwolf3Scan(INT32 nAction, INT32 *pnMin) +{ + INT32 nRet = SlapshotScan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + BurnGunScan(); + } + + return nRet; +} + +struct BurnDriver BurnDrvSlapshot = { + "slapshot", NULL, NULL, NULL, "1994", + "Slap Shot (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_SPORTSMISC, 0, + NULL, SlapshotRomInfo, SlapshotRomName, NULL, NULL, SlapshotInputInfo, SlapshotDIPInfo, + SlapshotInit, SlapshotExit, SlapshotFrame, NULL, SlapshotScan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolf3 = { + "opwolf3", NULL, NULL, NULL, "1994", + "Operation Wolf 3 (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, Opwolf3RomInfo, Opwolf3RomName, NULL, NULL, Opwolf3InputInfo, Opwolf3DIPInfo, + Opwolf3Init, Opwolf3Exit, SlapshotFrame, NULL, Opwolf3Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolf3u = { + "opwolf3u", "opwolf3", NULL, NULL, "1994", + "Operation Wolf 3 (US)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, Opwolf3uRomInfo, Opwolf3uRomName, NULL, NULL, Opwolf3InputInfo, Opwolf3DIPInfo, + Opwolf3Init, Opwolf3Exit, SlapshotFrame, NULL, Opwolf3Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_superchs.cpp b/src/burn/drivers/taito/d_superchs.cpp new file mode 100644 index 00000000..ee922086 --- /dev/null +++ b/src/burn/drivers/taito/d_superchs.cpp @@ -0,0 +1,1151 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "eeprom.h" +#include "es5506.h" + + +static UINT8 *TaitoF3SoundRam = NULL; +static UINT8 *TaitoF3SharedRam = NULL; +static UINT8 *TaitoES5510DSPRam = NULL; +static INT32 TaitoF3Counter; +static INT32 TaitoF3VectorReg; +static INT32 M68681IMR; +static INT32 IMRStatus; +static UINT32 TaitoES5510GPRLatch; +static UINT32 *TaitoES5510GPR = NULL; + +static UINT32 TaitoF3SoundTriggerIRQCycles = 0; +static UINT32 TaitoF3SoundTriggerIRQPulseCycles = 0; +static UINT32 TaitoF3SoundTriggerIRQCycleCounter = 0; +static UINT32 TaitoF3SoundTriggerIRQPulseCycleCounter = 0; +#define IRQ_TRIGGER_OFF 0 +#define IRQ_TRIGGER_ONCE 1 +#define IRQ_TRIGGER_PULSE 2 +static INT32 TaitoF3SoundTriggerIRQCyclesMode = 0; + +static INT32 __fastcall TaitoF3SoundIRQCallback(INT32 /*irq*/) +{ + return TaitoF3VectorReg; +} + +static void TaitoF3SoundReset() +{ + UINT16 *Ram = (UINT16*)TaitoF3SoundRam; + UINT16 *Rom = (UINT16*)Taito68KRom3; + + Ram[0x00] = Rom[0x00]; + Ram[0x01] = Rom[0x01]; + Ram[0x02] = Rom[0x02]; + Ram[0x03] = Rom[0x03]; + + SekOpen(2); + SekReset(); + SekClose(); +} + +UINT8 __fastcall TaitoF3Sound68KReadByte(UINT32 a) +{ + if (a >= 0x140000 && a <= 0x140fff) { + INT32 Offset = (a - 0x140000) >> 1; + UINT32 *Ram = (UINT32*)TaitoF3SharedRam; + if ((Offset&3)==0) return (Ram[Offset/4]&0xff000000)>>16; + if ((Offset&3)==1) return (Ram[Offset/4]&0x00ff0000)>>8; + if ((Offset&3)==2) return (Ram[Offset/4]&0x0000ff00)>>0; + return (Ram[Offset/4]&0x000000ff)<<8; + } + + if (a >= 0x260000 && a <= 0x2601ff) { + INT32 Offset = (a - 0x260000) >> 1; + UINT16 *Ram = (UINT16*)TaitoES5510DSPRam; + + if (Offset == 0x12) return 0; + if (Offset == 0x16) return 0x27; + + return Ram[Offset]; + } + + if (a >= 0x280000 && a <= 0x28001f) { + INT32 Offset = (a - 0x280000) >> 1; + + if (Offset == 0x05) { + INT32 Ret = IMRStatus; + IMRStatus = 0; + return Ret; + } + + if (Offset == 0x0e) return 0x01; + + if (Offset == 0x0f) { + SekSetIRQLine(6, SEK_IRQSTATUS_NONE); + return 0x00; + } + + return 0xff; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Sound 68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoF3Sound68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x260000 && a <= 0x2601ff) { + INT32 Offset = (a - 0x260000) >> 1; + UINT16 *Ram = (UINT16*)TaitoES5510DSPRam; + Ram[Offset] = d; + + switch (Offset) { + case 0x00: { + TaitoES5510GPRLatch = (TaitoES5510GPRLatch & 0x00ffff) | ((d & 0xff) << 16); + return; + } + + case 0x01: { + TaitoES5510GPRLatch = (TaitoES5510GPRLatch & 0xff00ff) | ((d & 0xff) << 8); + return; + } + + case 0x02: { + TaitoES5510GPRLatch= (TaitoES5510GPRLatch & 0xffff00) | ((d & 0xff) << 0); + return; + } + + case 0x03: { + return; + } + + case 0x80: { + if (d < 0xc0) { + TaitoES5510GPRLatch = TaitoES5510GPR[d]; + } + return; + } + + case 0xa0: { + if (d < 0xc0) { + TaitoES5510GPR[d] = TaitoES5505Rom[(TaitoES5510GPRLatch >> 8) & (TaitoES5505RomSize - 1)]; + } + return; + } + + case 0xc0: { + return; + } + + case 0xe0: { + return; + } + + default: { +// bprintf(PRINT_NORMAL,_T("es5510_dsp_w byte %x -> %x\n"), Offset, d); + return; + } + } + } + + if (a >= 0x280000 && a <= 0x28001f) { + INT32 Offset = (a - 0x280000) >> 1; + + switch (Offset) { + case 0x04: { + switch ((d >> 4) & 0x07) { + case 0x0: { + return; + } + + case 0x01: { + return; + } + + case 0x02: { + return; + } + + case 0x03: { +// bprintf(PRINT_NORMAL, _T("divided by 16, counter is %04x, so interrupt every %d cycles\n"), TaitoF3Counter, (16000000 / 2000000) * TaitoF3Counter * 16); + TaitoF3SoundTriggerIRQCyclesMode = IRQ_TRIGGER_ONCE; + TaitoF3SoundTriggerIRQCycleCounter = 0; + TaitoF3SoundTriggerIRQCycles = (16000000 / 2000000) * TaitoF3Counter * 16; +// timer_mode=TIMER_SINGLESHOT; +// timer_device_adjust_oneshot(devtag_get_device(space->machine, "timer_68681"), cpu_clocks_to_attotime(space->cpu, (M68000_CLOCK/M68681_CLOCK)*counter*16), 0); + return; + } + + case 0x04: { + return; + } + + case 0x05: { + return; + } + + case 0x06: { +// bprintf(PRINT_NORMAL, _T("counter is %04x, so interrupt every %d cycles\n"), TaitoF3Counter, (16000000 / 2000000) * TaitoF3Counter); + TaitoF3SoundTriggerIRQCyclesMode = IRQ_TRIGGER_PULSE; + TaitoF3SoundTriggerIRQPulseCycleCounter = 0; + TaitoF3SoundTriggerIRQPulseCycles = (16000000 / 2000000) * TaitoF3Counter; +// timer_mode=TIMER_PULSE; +// timer_device_adjust_periodic(devtag_get_device(space->machine, "timer_68681"), cpu_clocks_to_attotime(space->cpu, (M68000_CLOCK/M68681_CLOCK)*counter), 0, cpu_clocks_to_attotime(space->cpu, (M68000_CLOCK/M68681_CLOCK)*counter)); + return; + } + + case 0x07: { + return; + } + } + } + + case 0x05: { + M68681IMR = d & 0xff; + return; + } + + case 0x06: { + TaitoF3Counter = ((d & 0xff) << 8) | (TaitoF3Counter & 0xff); + return; + } + + case 0x07: { + TaitoF3Counter = (TaitoF3Counter & 0xff00) | (d & 0xff); + return; + } + + case 0x08: return; + case 0x09: return; + case 0x0a: return; + case 0x0b: return; + + case 0x0c: { + TaitoF3VectorReg = d & 0xff; + return; + } + + default: { +// bprintf(PRINT_NORMAL,_T("f3_68681_w byte %x -> %x\n"), Offset, d); + return; + } + } + } + + if (a >= 0x300000 && a <= 0x30003f) { + UINT32 MaxBanks = (TaitoES5505RomSize / 0x200000) - 1; + INT32 Offset = (a - 0x300000) >> 1; + + d &= MaxBanks; + es5505_voice_bank_w(Offset, d << 20); + // es5505_voice_bank_w(offset, data << 20); + return; + } + + switch (a) { + case 0x340000: + case 0x340002: { + // f3_volume_w + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Sound 68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall TaitoF3Sound68KReadWord(UINT32 a) +{ + if (a >= 0x200000 && a <= 0x20001f) { + INT32 Offset = (a - 0x200000) >> 1; + // es5505_r + return ES5505Read(Offset); + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Sound 68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoF3Sound68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x200000 && a <= 0x20001f) { + INT32 Offset = (a - 0x200000) >> 1; + // es5505_w + ES5505Write(Offset, d); + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("Sound 68K Write word => %06X, %04X\n"), a, d); + } + } +} + + + + + + +struct SpriteEntry { + INT32 Code; + INT32 x; + INT32 y; + INT32 Colour; + INT32 xFlip; + INT32 yFlip; + INT32 xZoom; + INT32 yZoom; + INT32 Priority; +}; + +static struct SpriteEntry *SpriteList; + +static UINT8 SuperchsCoinWord; +static UINT16 SuperchsCpuACtrl; +static UINT32 SuperchsSteer = 0; + +static struct BurnInputInfo SuperchsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 7, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort1 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 6, "p2 coin" }, + + {"P1 Left" , BIT_DIGITAL , TaitoInputPort3 + 1, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort3 + 2, "p1 right" }, + {"P1 Accelerate" , BIT_DIGITAL , TaitoInputPort3 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 6, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TaitoInputPort1 + 4, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TaitoInputPort1 + 5, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TaitoInputPort1 + 0, "p1 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 5, "service" }, + {"Diagnosics" , BIT_DIGITAL , TaitoInputPort2 + 4, "diag" }, +}; + +STDINPUTINFO(Superchs) + +static void SuperchsMakeInputs() +{ + TaitoInput[0] = 0x7f;// bit 8 is eeprom read + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xe7; + + for (INT32 i = 0; i < 8; i++) { + TaitoInput[0] -= (TaitoInputPort0[i] & 1) << i; + TaitoInput[1] -= (TaitoInputPort1[i] & 1) << i; + TaitoInput[2] -= (TaitoInputPort2[i] & 1) << i; + } +} + +static struct BurnRomInfo SuperchsRomDesc[] = { + { "d46-35.27", 0x040000, 0x1575c9a7, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP32 }, + { "d46-34.25", 0x040000, 0xc72a4d2b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP32 }, + { "d46-33.23", 0x040000, 0x3094bcd0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP32 }, + { "d46-31.21", 0x040000, 0x38b983a3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP32 }, + + { "d46-24.127", 0x020000, 0xa006baa1, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "d46-23.112", 0x020000, 0x9a69dbd0, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "d46-37.8up", 0x020000, 0x60b51b91, BRF_ESS | BRF_PRG | TAITO_68KROM3_BYTESWAP }, + { "d46-36.7lo", 0x020000, 0x8f7aa276, BRF_ESS | BRF_PRG | TAITO_68KROM3_BYTESWAP }, + + { "d46-05.87", 0x100000, 0x150d0e4c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d46-06.88", 0x100000, 0x321308be, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d46-04.67", 0x200000, 0x832769a9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d46-03.66", 0x200000, 0xe0e9cbfd, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d46-02.65", 0x200000, 0xa83ca82e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "d46-01.64", 0x200000, 0x5c2ae92d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "d46-07.34", 0x080000, 0xc3b8b093, BRF_GRA | TAITO_SPRITEMAP }, + + { "d46-10.2", 0x200000, 0x306256be, BRF_SND | TAITO_ES5505_BYTESWAP }, + { "d46-12.4", 0x200000, 0xa24a53a8, BRF_SND | TAITO_ES5505_BYTESWAP }, + { "d46-11.5", 0x200000, 0xd4ea0f56, BRF_SND | TAITO_ES5505_BYTESWAP }, + + { "eeprom-superchs.bin",0x000080, 0x230f0753, BRF_PRG | TAITO_DEFAULT_EEPROM }, +}; + +STD_ROM_PICK(Superchs) +STD_ROM_FN(Superchs) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + Taito68KRom2 = Next; Next += Taito68KRom2Size; + Taito68KRom3 = Next; Next += Taito68KRom3Size; + TaitoSpriteMapRom = Next; Next += TaitoSpriteMapRomSize; + TaitoES5505Rom = Next; Next += TaitoES5505RomSize; + TaitoDefaultEEProm = Next; Next += TaitoDefaultEEPromSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x020000; + Taito68KRam2 = Next; Next += 0x010200; + TaitoSpriteRam = Next; Next += 0x002000; + TaitoPaletteRam = Next; Next += 0x008000; + TaitoSharedRam = Next; Next += 0x010000; + TaitoF3SoundRam = Next; Next += 0x010000; + TaitoF3SharedRam = Next; Next += 0x000800; + TaitoES5510DSPRam = Next; Next += 0x000200; + TaitoES5510GPR = (UINT32*)Next; Next += 0x0000c0 * sizeof(UINT32); + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + SpriteList = (SpriteEntry*)Next; Next += 0x4000 * sizeof(SpriteEntry); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 SuperchsDoReset() +{ + TaitoDoReset(); + + SuperchsCoinWord = 0; + SuperchsCpuACtrl = 0; + SuperchsSteer = 0; + + TaitoF3SoundReset(); + + return 0; +} + +UINT8 __fastcall Superchs68K1ReadByte(UINT32 a) +{ + switch (a) { + case 0x300000: { + return 0xff; + } + + case 0x300001: { + return TaitoInput[2] | TaitoDip[0]; + } + + case 0x300002: { + return TaitoInput[1]; + } + + case 0x300003: { + return TaitoInput[0] | ((EEPROMRead() & 1) ? 0x80 : 0x00); + } + + case 0x300004: { + return SuperchsCoinWord; + } + + case 0x340000: { + INT32 Delta; + UINT32 Goal = 0x80; + if (TaitoInputPort3[1]) Goal = 0xff; + if (TaitoInputPort3[2]) Goal = 0x0; + + if (SuperchsSteer != Goal) { + Delta = Goal - SuperchsSteer; + if (SuperchsSteer < Goal) { + if (Delta > 2) Delta = 2; + } else { + if (Delta < -2) Delta = -2; + } + SuperchsSteer += Delta; + } + return SuperchsSteer; + } + + case 0x340001: { + if (TaitoInputPort3[0]) return 0x00; + return 0xff; + } + + case 0x340002: { + return 0x7f; + } + + case 0x340003: { + return 0x7f; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0xff; +} + +void __fastcall Superchs68K1WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x300000: { + // watchdog write + return; + } + + case 0x300003: { + EEPROMWrite(d & 0x20, d & 0x10, d & 0x40); + return; + } + + case 0x300005: + case 0x300006: { + // superchs_input_w + return; + } + + case 0x300004: { + SuperchsCoinWord = d; + return; + } + + case 0x340000: + case 0x340001: + case 0x340002: { + SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); + return; + } + + case 0x340003: { + // irq ack? + return; + } + + case 0x380000: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Superchs68K1ReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Superchs68K1WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x140000 && a <= 0x141fff) { + UINT16 *Ram = (UINT16*)TaitoSpriteRam; + INT32 Offset = (a - 0x140000) >> 1; + + Ram[Offset] = d; + return; + } + + TC0480SCPCtrlWordWrite_Map(0x1b0000) + + switch (a) { + case 0x240000: { + return; + } + + case 0x240002: { + SuperchsCpuACtrl = d; + if (!(SuperchsCpuACtrl & 0x200)) { + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(0); + } +// if (d & 0x8000) { +// SekSetIRQLine(3, SEK_IRQSTATUS_AUTO); +// } + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT32 __fastcall Superchs68K1ReadLong(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read long => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Superchs68K1WriteLong(UINT32 a, UINT32 d) +{ + if (a >= 0x140000 && a <= 0x141fff) { + UINT16 *Ram = (UINT16*)TaitoSpriteRam; + INT32 Offset = (a - 0x140000) >> 1; + + Ram[Offset + 0] = d & 0xffff; + Ram[Offset + 1] = d >> 16; + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write long => %06X, %08X\n"), a, d); + } + } +} + +UINT8 __fastcall Superchs68K2ReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Superchs68K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Superchs68K2ReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Superchs68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[16] = { 4, 0, 20, 16, 12, 8, 28, 24, 36, 32, 52, 48, 44, 40, 60, 56 }; +static INT32 CharYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 SpritePlaneOffsets[4] = { 0, 8, 16, 24 }; +static INT32 SpriteXOffsets[16] = { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 SpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + +static const eeprom_interface superchs_eeprom_interface = +{ + 6, /* address bits */ + 16, /* data bits */ + "0110", /* read command */ + "0101", /* write command */ + "0111", /* erase command */ + "0100000000", /* unlock command */ + "0100110000", /* lock command */ + 0, + 0, +}; + +static INT32 SuperchsInit() +{ + INT32 nLen; + + GenericTilesInit(); + + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x10000; + + TaitoES5505RomSize = 0x1000000 - 0x600000; + + TaitoNum68Ks = 3; + TaitoNumES5505 = 1; + TaitoNumEEPROM = 1; + + nTaitoCyclesTotal[0] = 16000000 / 60; + nTaitoCyclesTotal[1] = 16000000 / 60; + nTaitoCyclesTotal[2] = 16000000 / 60; + + TaitoLoadRoms(0); + + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0480SCPInit(TaitoNumChar, 0, 0x20, 8, -1, 0, 0); + + UINT8 *pTemp; + pTemp = (UINT8*)malloc(0xc00000); + memcpy(pTemp, TaitoES5505Rom, 0xc00000); + memset(TaitoES5505Rom, 0, TaitoES5505RomSize); + memcpy(TaitoES5505Rom + 0xc00000, pTemp + 0x000000, 0x400000); + memcpy(TaitoES5505Rom + 0x000000, pTemp + 0x400000, 0x400000); + memcpy(TaitoES5505Rom + 0x400000, pTemp + 0x400000, 0x400000); + memcpy(TaitoES5505Rom + 0x800000, pTemp + 0x800000, 0x400000); + + SekInit(0, 0x68EC020); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x11ffff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x180000, 0x18ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoF3SharedRam , 0x2c0000, 0x2c07ff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x280000, 0x287fff, SM_RAM); + SekSetReadByteHandler(0, Superchs68K1ReadByte); + SekSetWriteByteHandler(0, Superchs68K1WriteByte); + SekSetReadWordHandler(0, Superchs68K1ReadWord); + SekSetWriteWordHandler(0, Superchs68K1WriteWord); + SekSetReadLongHandler(0, Superchs68K1ReadLong); + SekSetWriteLongHandler(0, Superchs68K1WriteLong); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(Taito68KRam2 + 0x10000 , 0xa00000, 0xa001ff, SM_RAM); + SekSetReadByteHandler(0, Superchs68K2ReadByte); + SekSetWriteByteHandler(0, Superchs68K2WriteByte); + SekSetReadWordHandler(0, Superchs68K2ReadWord); + SekSetWriteWordHandler(0, Superchs68K2WriteWord); + SekClose(); + + SekInit(2, 0x68000); + SekOpen(2); + SekMapMemory(TaitoF3SoundRam , 0x000000, 0x00ffff, SM_RAM); + SekMapMemory(TaitoF3SoundRam , 0x010000, 0x01ffff, SM_RAM); + SekMapMemory(TaitoF3SoundRam , 0x020000, 0x02ffff, SM_RAM); + SekMapMemory(TaitoF3SoundRam , 0x030000, 0x03ffff, SM_RAM); + SekMapMemory(Taito68KRom3 , 0xc00000, 0xc1ffff, SM_ROM); + SekMapMemory(Taito68KRom3 + 0x20000 , 0xc20000, 0xc3ffff, SM_ROM); + SekMapMemory(TaitoF3SoundRam , 0xff0000, 0xffffff, SM_RAM); + SekSetReadByteHandler(0, TaitoF3Sound68KReadByte); + SekSetWriteByteHandler(0, TaitoF3Sound68KWriteByte); + SekSetReadWordHandler(0, TaitoF3Sound68KReadWord); + SekSetWriteWordHandler(0, TaitoF3Sound68KWriteWord); + SekSetIrqCallback(TaitoF3SoundIRQCallback); + SekClose(); + + EEPROMInit(&superchs_eeprom_interface); + if (!EEPROMAvailable()) EEPROMFill(TaitoDefaultEEProm, 0, 128); + + ES5505Init(30476100/2, TaitoES5505Rom, TaitoES5505Rom, NULL); + + SuperchsDoReset(); + + return 0; +} + +static int SuperchsExit() +{ + TaitoExit(); + + SuperchsCoinWord = 0; + SuperchsCpuACtrl = 0; + SuperchsSteer = 0; + + return 0; +} + +inline static UINT32 CalcCol(UINT32 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x000000ff) >> 0; + b = (nColour & 0x00ff0000) >> 16; + g = (nColour & 0xff000000) >> 24; + + return BurnHighCol(r, g, b, 0); +} + +static void SuperchsCalcPalette() +{ + INT32 i; + UINT32* ps; + UINT32* pd; + + for (i = 0, ps = (UINT32*)TaitoPaletteRam, pd = TaitoPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void RenderSpriteZoom(INT32 Code, INT32 sx, INT32 sy, INT32 Colour, INT32 xFlip, INT32 yFlip, INT32 xScale, INT32 yScale, UINT8* pSource) +{ + UINT8 *SourceBase = pSource + ((Code % TaitoNumSpriteA) * TaitoSpriteAWidth * TaitoSpriteAHeight); + + INT32 SpriteScreenHeight = (yScale * TaitoSpriteAHeight + 0x8000) >> 16; + INT32 SpriteScreenWidth = (xScale * TaitoSpriteAWidth + 0x8000) >> 16; + + Colour = 0x10 * (Colour % 0x200); + + if (TaitoFlipScreenX) { + xFlip = !xFlip; + sx = 320 - sx - (xScale >> 12); + } + + if (SpriteScreenWidth && SpriteScreenHeight) { + INT32 dx = (TaitoSpriteAWidth << 16) / SpriteScreenWidth; + INT32 dy = (TaitoSpriteAHeight << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (xFlip) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (yFlip) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth) { + INT32 Pixels = ex - nScreenWidth; + ex -= Pixels; + } + + if (ey > nScreenHeight) { + INT32 Pixels = ey - nScreenHeight; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * TaitoSpriteAWidth); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + INT32 x, xIndex = xIndexBase; + for (x = sx; x < ex; x++) { + INT32 c = Source[xIndex >> 16]; + if (c != 0) { + pPixel[x] = c | Colour; + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +static void SuperchsMakeSpriteList(INT32 xOffset, INT32 yOffset) +{ + UINT32 *SpriteRam = (UINT32*)TaitoSpriteRam; + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + INT32 Offset, Data, TileNum, Colour, xFlip, yFlip; + INT32 x, y, Priority, DblSize, xCur, yCur; + INT32 SpritesFlipscreen = 0; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + INT32 Dimension, TotalChunks, BadChunks; + + struct SpriteEntry *SpritePtr = SpriteList; + + memset(SpriteList, 0, 0x4000 * sizeof(SpriteEntry)); + + for (Offset = ((0x2000 / 4) - 4); Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 0]; + xFlip = (Data & 0x00800000) >> 23; + xZoom = (Data & 0x007f0000) >> 16; + TileNum = (Data & 0x00007fff); + + Data = SpriteRam[Offset + 2]; + Priority = (Data & 0x000c0000) >> 18; + Colour = (Data & 0x0003fc00) >> 10; + x = (Data & 0x000003ff); + + Data = SpriteRam[Offset + 3]; + DblSize = (Data & 0x00040000) >> 18; + yFlip = (Data & 0x00020000) >> 17; + yZoom = (Data & 0x0001fc00) >> 10; + y = (Data & 0x000003ff); + + Colour |= 0x100; + + if (!TileNum) continue; + + yFlip = !yFlip; + xZoom += 1; + yZoom += 1; + + y += yOffset; + + if (x > 0x340) x -= 0x400; + if (y > 0x340) y -= 0x400; + + x -= xOffset; + + BadChunks = 0; + Dimension = ((DblSize * 2) + 2); + TotalChunks = ((DblSize * 3) + 1) << 2; + MapOffset = TileNum << 2; + + for (SpriteChunk = 0; SpriteChunk < TotalChunks; SpriteChunk++) { + j = SpriteChunk / Dimension; + k = SpriteChunk % Dimension; + + px = k; + py = j; + + if (xFlip) px = Dimension - 1 - k; + if (yFlip) py = Dimension - 1 - j; + + Code = SpriteMap[MapOffset + px + (py << (DblSize + 1))]; + + if (Code == 0xffff) { + BadChunks += 1; + continue; + } + + xCur = x + ((k * xZoom) / Dimension); + yCur = y + ((j * yZoom) / Dimension); + + zx = x + (((k + 1) * xZoom) / Dimension) - xCur; + zy = y + (((j + 1) * yZoom) / Dimension) - yCur; + + if (SpritesFlipscreen) { + xCur = 320 - xCur - zx; + yCur = 256 - yCur - zy; + xFlip = !xFlip; + yFlip = !yFlip; + } + + SpritePtr->Code = Code; + SpritePtr->Colour = Colour; + SpritePtr->xFlip = !xFlip; + SpritePtr->yFlip = yFlip; + SpritePtr->x = xCur; + SpritePtr->y = yCur; + SpritePtr->xZoom = zx << 12; + SpritePtr->yZoom = zy << 12; + SpritePtr->Priority = Priority; + + SpritePtr++; + } + } +} + +static void SuperchsRenderSpriteList(INT32 SpritePriorityLevel) +{ + for (INT32 i = 0; i < 0x4000; i++) { + if (SpriteList[i].Priority == SpritePriorityLevel) RenderSpriteZoom(SpriteList[i].Code, SpriteList[i].x, SpriteList[i].y, SpriteList[i].Colour, SpriteList[i].xFlip, SpriteList[i].yFlip, SpriteList[i].xZoom, SpriteList[i].yZoom, TaitoSpritesA); + } +} + +static void SuperchsDraw() +{ + UINT8 Layer[4]; + UINT16 Priority = TC0480SCPGetBgPriority(); + + Layer[0] = (Priority & 0xf000) >> 12; + Layer[1] = (Priority & 0x0f00) >> 8; + Layer[2] = (Priority & 0x00f0) >> 4; + Layer[3] = (Priority & 0x000f) >> 0; + + SuperchsCalcPalette(); + BurnTransferClear(); + + SuperchsMakeSpriteList(48, -116 - 16); + + TC0480SCPTilemapRender(Layer[0], 1, TaitoChars); + TC0480SCPTilemapRender(Layer[1], 0, TaitoChars); + SuperchsRenderSpriteList(0); + TC0480SCPTilemapRender(Layer[2], 0, TaitoChars); + TC0480SCPTilemapRender(Layer[3], 0, TaitoChars); + SuperchsRenderSpriteList(1); + SuperchsRenderSpriteList(2); + TC0480SCPRenderCharLayer(); + SuperchsRenderSpriteList(3); + BurnTransferCopy(TaitoPalette); +} + +static INT32 SuperchsFrame() +{ + INT32 nInterleave = 100; + INT32 nSoundBufferPos = 0; + + if (TaitoReset) SuperchsDoReset(); + + SuperchsMakeInputs(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + if (SuperchsCpuACtrl & 0x200) { + nCurrentCPU = 1; + SekOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + nCurrentCPU = 2; + SekOpen(2); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (TaitoF3SoundTriggerIRQCyclesMode == IRQ_TRIGGER_ONCE) { + TaitoF3SoundTriggerIRQCycleCounter += nTaitoCyclesSegment; + if (TaitoF3SoundTriggerIRQCycleCounter >= TaitoF3SoundTriggerIRQCycles) { + TaitoF3SoundTriggerIRQCyclesMode = IRQ_TRIGGER_OFF; + if (M68681IMR & 0x08) { +// bprintf(PRINT_NORMAL, _T("%x\n"), TaitoF3VectorReg); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + IMRStatus |= 0x08; + } + } + } + if (TaitoF3SoundTriggerIRQCyclesMode == IRQ_TRIGGER_PULSE) { + TaitoF3SoundTriggerIRQPulseCycleCounter += nTaitoCyclesSegment; + if (TaitoF3SoundTriggerIRQPulseCycleCounter >= TaitoF3SoundTriggerIRQPulseCycles) { +// TaitoF3SoundTriggerIRQCyclesMode = IRQ_TRIGGER_OFF; + if (M68681IMR & 0x08) { +// bprintf(PRINT_NORMAL, _T("%x\n"), TaitoF3VectorReg); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + IMRStatus |= 0x08; + } + TaitoF3SoundTriggerIRQPulseCycleCounter = 0; + } + } + SekClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ES5505Update(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ES5505Update(pSoundBuf, nSegmentLength); + } + } + +// if (pBurnSoundOut) ES5505Update(pBurnSoundOut, nBurnSoundLen); + + if (pBurnDraw) SuperchsDraw(); + + return 0; +} + +static INT32 SuperchsScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029709; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + } + + return 0; +} + +struct BurnDriver BurnDrvSuperchs = { + "superchs", NULL, NULL, NULL, "1992", + "Super Chase - Criminal Termintation (US)\0", "No Sound", "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_RACING, 0, + NULL, SuperchsRomInfo, SuperchsRomName, NULL, NULL, SuperchsInputInfo, NULL, + SuperchsInit, SuperchsExit, SuperchsFrame, NULL, SuperchsScan, + NULL, 0x2000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_taitob.cpp b/src/burn/drivers/taito/d_taitob.cpp new file mode 100644 index 00000000..f02b1f31 --- /dev/null +++ b/src/burn/drivers/taito/d_taitob.cpp @@ -0,0 +1,4141 @@ +// FB Alpha Taito B System driver module +// Based on MAME driver by Jarek Burczynski and various others + +// to do: +// fix rambo alt sets inputs +// master of weapon title screen is incorrect + +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" +#include "msm6295.h" +#include "burn_ym2203.h" +#include "burn_gun.h" +#include "eeprom.h" + +static UINT8 *DrvPxlRAM = NULL; +static UINT16 *DrvPxlScroll = NULL; +static UINT8 *DrvFramebuffer = NULL; + +static INT32 eeprom_latch = 0; +static INT32 coin_control = 0; + +static UINT8 color_config[4]; +static INT32 irq_config[2]; +static INT32 sound_config = 0; +static INT32 cpu_speed[2]; +static UINT8 nTaitoInputConfig[5] = { 0, 0, 0, 0, 0 }; + +static struct BurnInputInfo CommonInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Common) + +static struct BurnInputInfo PbobbleInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TaitoInputPort3 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TaitoInputPort3 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TaitoInputPort3 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TaitoInputPort3 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TaitoInputPort3 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TaitoInputPort3 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TaitoInputPort3 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TaitoInputPort3 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 6, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 6, "p3 start" }, + {"P3 Up", BIT_DIGITAL, TaitoInputPort5 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, TaitoInputPort5 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, TaitoInputPort5 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, TaitoInputPort5 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, TaitoInputPort4 + 0, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, TaitoInputPort4 + 1, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, TaitoInputPort4 + 2, "p3 fire 3" }, + + {"P4 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 7, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, TaitoInputPort5 + 4, "p4 up" }, + {"P4 Down", BIT_DIGITAL, TaitoInputPort5 + 5, "p4 down" }, + {"P4 Left", BIT_DIGITAL, TaitoInputPort5 + 6, "p4 left" }, + {"P4 Right", BIT_DIGITAL, TaitoInputPort5 + 7, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, TaitoInputPort4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, TaitoInputPort4 + 5, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, TaitoInputPort4 + 6, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "service" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, +}; + +STDINPUTINFO(Pbobble) + +static struct BurnInputInfo QzshowbyInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 start" }, + {"P1 Button 1", BIT_DIGITAL, TaitoInputPort3 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TaitoInputPort3 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TaitoInputPort3 + 3, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, TaitoInputPort3 + 2, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 start" }, + {"P2 Button 1", BIT_DIGITAL, TaitoInputPort3 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TaitoInputPort3 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TaitoInputPort3 + 7, "p2 fire 3" }, + {"P2 Button 4", BIT_DIGITAL, TaitoInputPort3 + 6, "p2 fire 4" }, + + {"P3 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 6, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 6, "p3 start" }, + {"P3 Button 1", BIT_DIGITAL, TaitoInputPort5 + 8, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, TaitoInputPort5 + 9, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, TaitoInputPort5 + 11, "p3 fire 3" }, + {"P3 Button 4", BIT_DIGITAL, TaitoInputPort5 + 10, "p3 fire 4" }, + + {"P4 Coin", BIT_DIGITAL, TC0220IOCInputPort0 + 7, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 7, "p4 start" }, + {"P4 Button 1", BIT_DIGITAL, TaitoInputPort5 + 12, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, TaitoInputPort5 + 13, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, TaitoInputPort5 + 15, "p4 fire 3" }, + {"P4 Button 4", BIT_DIGITAL, TaitoInputPort5 + 14, "p4 fire 4" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "service" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, +}; + +STDINPUTINFO(Qzshowby) + +static struct BurnInputInfo SpacedxoInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, TaitoInputPort5 + 0, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, TaitoInputPort3 + 0, "p3 start" }, + {"P3 Up", BIT_DIGITAL, TaitoInputPort3 + 3, "p3 up" }, + {"P3 Down", BIT_DIGITAL, TaitoInputPort3 + 4, "p3 down" }, + {"P3 Left", BIT_DIGITAL, TaitoInputPort3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, TaitoInputPort3 + 2, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, TaitoInputPort3 + 5, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, TaitoInputPort3 + 6, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, TaitoInputPort3 + 7, "p3 fire 3" }, + + {"P4 Coin", BIT_DIGITAL, TaitoInputPort5 + 2, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, TaitoInputPort4 + 0, "p4 start" }, + {"P4 Up", BIT_DIGITAL, TaitoInputPort4 + 3, "p4 up" }, + {"P4 Down", BIT_DIGITAL, TaitoInputPort4 + 4, "p4 down" }, + {"P4 Left", BIT_DIGITAL, TaitoInputPort4 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, TaitoInputPort4 + 2, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, TaitoInputPort4 + 5, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, TaitoInputPort4 + 6, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, TaitoInputPort4 + 7, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Service", BIT_DIGITAL, TaitoInputPort5 + 1, "service" }, + {"Service", BIT_DIGITAL, TaitoInputPort5 + 3, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Spacedxo) + +static struct BurnInputInfo SelfeenaInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset"}, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Selfeena) + +static struct BurnInputInfo SbmInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p1 fire 3" }, + {"P1 Button 4", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p1 fire 4" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 7, "p2 right" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Sbm) + +static struct BurnInputInfo SilentdInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 fire 3" }, + + {"P3 Coin", BIT_DIGITAL, TaitoInputPort5 + 0, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, TaitoInputPort3 + 0, "p3 start" }, + {"P3 Up", BIT_DIGITAL, TaitoInputPort3 + 3, "p3 up" }, + {"P3 Down", BIT_DIGITAL, TaitoInputPort3 + 4, "p3 down" }, + {"P3 Left", BIT_DIGITAL, TaitoInputPort3 + 1, "p3 left" }, + {"P3 Right", BIT_DIGITAL, TaitoInputPort3 + 2, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, TaitoInputPort3 + 5, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, TaitoInputPort3 + 6, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, TaitoInputPort3 + 7, "p3 fire 3" }, + + {"P4 Coin", BIT_DIGITAL, TaitoInputPort5 + 2, "p4 coin" }, + {"P4 Start", BIT_DIGITAL, TaitoInputPort4 + 0, "p4 start" }, + {"P4 Up", BIT_DIGITAL, TaitoInputPort4 + 3, "p4 up" }, + {"P4 Down", BIT_DIGITAL, TaitoInputPort4 + 4, "p4 down" }, + {"P4 Left", BIT_DIGITAL, TaitoInputPort4 + 1, "p4 left" }, + {"P4 Right", BIT_DIGITAL, TaitoInputPort4 + 2, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, TaitoInputPort4 + 5, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, TaitoInputPort4 + 6, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, TaitoInputPort4 + 7, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Silentd) + +static struct BurnInputInfo ViofightInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset"}, + {"Service", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Viofight) + +static struct BurnInputInfo HiticeInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 2, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, TC0220IOCInputPort0 + 5, "p2 fire 3" }, + + {"P3 Start", BIT_DIGITAL, TaitoInputPort3 + 7, "p3 start" }, + {"P3 Up", BIT_DIGITAL, TaitoInputPort3 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, TaitoInputPort3 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, TaitoInputPort3 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, TaitoInputPort3 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, TaitoInputPort3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, TaitoInputPort3 + 5, "p3 fire 2" }, + {"P3 Button 3", BIT_DIGITAL, TaitoInputPort3 + 6, "p3 fire 3" }, + + {"P4 Start", BIT_DIGITAL, TaitoInputPort4 + 7, "p4 start" }, + {"P4 Up", BIT_DIGITAL, TaitoInputPort4 + 0, "p4 up" }, + {"P4 Down", BIT_DIGITAL, TaitoInputPort4 + 1, "p4 down" }, + {"P4 Left", BIT_DIGITAL, TaitoInputPort4 + 2, "p4 left" }, + {"P4 Right", BIT_DIGITAL, TaitoInputPort4 + 3, "p4 right" }, + {"P4 Button 1", BIT_DIGITAL, TaitoInputPort4 + 4, "p4 fire 1" }, + {"P4 Button 2", BIT_DIGITAL, TaitoInputPort4 + 5, "p4 fire 2" }, + {"P4 Button 3", BIT_DIGITAL, TaitoInputPort4 + 6, "p4 fire 3" }, + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset" }, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Hitice) + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo Rambo3uInputList[] = { + {"P1 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 4, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 2, "p1 start" }, + {"P1 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 1, "p1 fire 2" }, + + A("P1 Trackball X", BIT_ANALOG_REL, &TaitoAnalogPort0, "p1 x-axis" ), + A("P1 Trackball Y", BIT_ANALOG_REL, &TaitoAnalogPort1, "p1 y-axis" ), + + {"P2 Coin", BIT_DIGITAL, TC0220IOCInputPort1 + 5, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, TC0220IOCInputPort1 + 3, "p2 start" }, + {"P2 Up", BIT_DIGITAL, TC0220IOCInputPort2 + 4, "p2 up" }, + {"P2 Down", BIT_DIGITAL, TC0220IOCInputPort2 + 5, "p2 down" }, + {"P2 Left", BIT_DIGITAL, TC0220IOCInputPort2 + 6, "p2 left" }, + {"P2 Right", BIT_DIGITAL, TC0220IOCInputPort2 + 7, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, TC0220IOCInputPort0 + 3, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, TC0220IOCInputPort0 + 4, "p2 fire 2" }, + + A("P2 Trackball X", BIT_ANALOG_REL, &TaitoAnalogPort2, "p2 x-axis" ), + A("P2 Trackball Y", BIT_ANALOG_REL, &TaitoAnalogPort3, "p2 y-axis" ), + + {"Reset", BIT_DIGITAL, &TaitoReset, "reset"}, + {"Service", BIT_DIGITAL, TC0220IOCInputPort1 + 1, "service" }, + {"Tilt", BIT_DIGITAL, TC0220IOCInputPort1 + 0, "tilt" }, + {"Dip A", BIT_DIPSWITCH, TC0220IOCDip + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, TC0220IOCDip + 1, "dip" }, +}; + +STDINPUTINFO(Rambo3u) + +#undef A + +static struct BurnDIPInfo NastarDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x08, "150k only" }, + {0x14, 0x01, 0x0c, 0x04, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "250k only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Nastar) + +static struct BurnDIPInfo Rastsag2DIPList[]= +{ + {0x13, 0xff, 0xff, 0x3f, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x08, "150k only" }, + {0x14, 0x01, 0x0c, 0x04, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "250k only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Rastsag2) + +static struct BurnDIPInfo NastarwDIPList[]= +{ + {0x13, 0xff, 0xff, 0x3e, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x08, "150k only" }, + {0x14, 0x01, 0x0c, 0x04, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "250k only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Nastarw) + +static struct BurnDIPInfo AshuraDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "every 150k" }, + {0x14, 0x01, 0x0c, 0x04, "every 200k" }, + {0x14, 0x01, 0x0c, 0x00, "every 250k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Ashura) + +static struct BurnDIPInfo AshurajDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "every 150k" }, + {0x14, 0x01, 0x0c, 0x04, "every 200k" }, + {0x14, 0x01, 0x0c, 0x00, "every 250k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Ashuraj) + +static struct BurnDIPInfo AshurauDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Continue Price" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as Start" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 100k" }, + {0x14, 0x01, 0x0c, 0x0c, "every 150k" }, + {0x14, 0x01, 0x0c, 0x04, "every 200k" }, + {0x14, 0x01, 0x0c, 0x00, "every 250k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x00, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Ashurau) + +static struct BurnDIPInfo CrimecDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Hi Score" }, + {0x13, 0x01, 0x01, 0x01, "Scribble" }, + {0x13, 0x01, 0x01, 0x00, "3 Characters" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 80k" }, + {0x14, 0x01, 0x0c, 0x0c, "80k only" }, + {0x14, 0x01, 0x0c, 0x04, "160k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0xc0, 0x00, "Off" }, + {0x14, 0x01, 0xc0, 0x40, "5 Times" }, + {0x14, 0x01, 0xc0, 0x80, "8 Times" }, + {0x14, 0x01, 0xc0, 0xc0, "On" }, +}; + +STDDIPINFO(Crimec) + +static struct BurnDIPInfo CrimecjDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Hi Score" }, + {0x13, 0x01, 0x01, 0x01, "Scribble" }, + {0x13, 0x01, 0x01, 0x00, "3 Characters" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 80k" }, + {0x14, 0x01, 0x0c, 0x0c, "80k only" }, + {0x14, 0x01, 0x0c, 0x04, "160k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0xc0, 0x00, "Off" }, + {0x14, 0x01, 0xc0, 0x40, "5 Times" }, + {0x14, 0x01, 0xc0, 0x80, "8 Times" }, + {0x14, 0x01, 0xc0, 0xc0, "On" }, +}; + +STDDIPINFO(Crimecj) + +static struct BurnDIPInfo CrimecuDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Hi Score" }, + {0x13, 0x01, 0x01, 0x01, "Scribble" }, + {0x13, 0x01, 0x01, 0x00, "3 Characters" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Price to Continue" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as Start" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "every 80k" }, + {0x14, 0x01, 0x0c, 0x0c, "80k only" }, + {0x14, 0x01, 0x0c, 0x04, "160k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 4, "Allow Continue" }, + {0x14, 0x01, 0xc0, 0x00, "Off" }, + {0x14, 0x01, 0xc0, 0x40, "5 Times" }, + {0x14, 0x01, 0xc0, 0x80, "8 Times" }, + {0x14, 0x01, 0xc0, 0xc0, "On" }, +}; + +STDDIPINFO(Crimecu) + +static struct BurnDIPInfo TetristDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, +}; + +STDDIPINFO(Tetrist) + +static struct BurnDIPInfo Rambo3DIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x10, 0x00, "Off" }, + {0x14, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(Rambo3) + +static struct BurnDIPInfo MasterwDIPList[]= +{ + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "500k, 1000k and 1500k"}, + {0x14, 0x01, 0x0c, 0x0c, "500k and 1000k" }, + {0x14, 0x01, 0x0c, 0x04, "500k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "Ship Type" }, + {0x14, 0x01, 0x80, 0x80, "Space Ship" }, + {0x14, 0x01, 0x80, 0x00, "Hover Cycle" }, +}; + +STDDIPINFO(Masterw) + +static struct BurnDIPInfo PbobbleDIPList[]= +{ + {0x29, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x29, 0x01, 0x80, 0x80, "Off" }, + {0x29, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Pbobble) + +static struct BurnDIPInfo QzshowbyDIPList[]= +{ + {0x1d, 0xff, 0xff, 0x80, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode " }, + {0x1d, 0x01, 0x80, 0x80, "Off" }, + {0x1d, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Qzshowby) + +static struct BurnDIPInfo SpacedxoDIPList[]= +{ + {0x29, 0xff, 0xff, 0xfe, NULL }, + {0x2a, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x29, 0x01, 0x01, 0x00, "Upright" }, + {0x29, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x29, 0x01, 0x02, 0x02, "Off" }, + {0x29, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x29, 0x01, 0x04, 0x04, "Off" }, + {0x29, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x29, 0x01, 0x08, 0x00, "Off" }, + {0x29, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x29, 0x01, 0x30, 0x00, "3 Coins 1 Credits" }, + {0x29, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x29, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x29, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x29, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x29, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x29, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x29, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x2a, 0x01, 0x03, 0x02, "Easy" }, + {0x2a, 0x01, 0x03, 0x03, "Medium" }, + {0x2a, 0x01, 0x03, 0x01, "Hard" }, + {0x2a, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Match Point" }, + {0x2a, 0x01, 0x0c, 0x08, "4" }, + {0x2a, 0x01, 0x0c, 0x0c, "3" }, + {0x2a, 0x01, 0x0c, 0x04, "5" }, + {0x2a, 0x01, 0x0c, 0x00, "2" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x2a, 0x01, 0x30, 0x30, "3" }, + {0x2a, 0x01, 0x30, 0x20, "4" }, + {0x2a, 0x01, 0x30, 0x10, "5" }, + {0x2a, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2, "Bonus Life" }, + {0x2a, 0x01, 0x40, 0x40, "1500 Points" }, + {0x2a, 0x01, 0x40, 0x00, "1000 Points" }, + + {0 , 0xfe, 0 , 2, "Game Type" }, + {0x2a, 0x01, 0x80, 0x80, "Double Company" }, + {0x2a, 0x01, 0x80, 0x00, "Single Company" }, +}; + +STDDIPINFO(Spacedxo) + +static struct BurnDIPInfo SelfeenaDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "100k only" }, + {0x16, 0x01, 0x0c, 0x08, "200k only" }, + {0x16, 0x01, 0x0c, 0x04, "300k only" }, + {0x16, 0x01, 0x0c, 0x00, "400k only" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x00, "1" }, + {0x16, 0x01, 0x30, 0x10, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x20, "4" }, +}; + +STDDIPINFO(Selfeena) + +static struct BurnDIPInfo RyujinDIPList[]= +{ + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x0c, 0x00, "1" }, + {0x16, 0x01, 0x0c, 0x04, "2" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x08, "4" }, +}; + +STDDIPINFO(Ryujin) + +static struct BurnDIPInfo SbmDIPList[]= +{ + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xfc, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Sbm) + +static struct BurnDIPInfo SilentdDIPList[]= +{ + {0x27, 0xff, 0xff, 0xff, NULL }, + {0x28, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x27, 0x01, 0x02, 0x02, "Off" }, + {0x27, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x27, 0x01, 0x04, 0x04, "Off" }, + {0x27, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x27, 0x01, 0x08, 0x00, "Off" }, + {0x27, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x27, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x27, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x27, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x27, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 2, "Difficulty" }, + {0x28, 0x01, 0x03, 0x02, "Easy" }, + {0x28, 0x01, 0x03, 0x03, "Medium" }, + {0x28, 0x01, 0x03, 0x01, "Hard" }, + {0x28, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Invulnerability" }, + {0x28, 0x01, 0x04, 0x04, "Off" }, + {0x28, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Power-Up Bonus" }, + {0x28, 0x01, 0x08, 0x08, "Off" }, + {0x28, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Regain Power" }, + {0x28, 0x01, 0x10, 0x10, "Off" }, + {0x28, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Credits" }, + {0x28, 0x01, 0x20, 0x20, "Combined" }, + {0x28, 0x01, 0x20, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Cabinet Style" }, + {0x28, 0x01, 0xc0, 0xc0, "3 Players" }, + {0x28, 0x01, 0xc0, 0x80, "2 Players" }, + {0x28, 0x01, 0xc0, 0x40, "4 Players/1 Machine" }, + {0x28, 0x01, 0xc0, 0x00, "4 Players/2 Machines" }, +}; + +STDDIPINFO(Silentd) + +static struct BurnDIPInfo SilentdjDIPList[]= +{ + {0x27, 0xff, 0xff, 0xff, NULL }, + {0x28, 0xff, 0xff, 0xbf, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x27, 0x01, 0x02, 0x02, "Off" }, + {0x27, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 0, "Service Mode" }, + {0x27, 0x01, 0x04, 0x04, "Off" }, + {0x27, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x27, 0x01, 0x08, 0x00, "Off" }, + {0x27, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x27, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x27, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x27, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x27, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x27, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x27, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x27, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x27, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x28, 0x01, 0x03, 0x02, "Easy" }, + {0x28, 0x01, 0x03, 0x03, "Medium" }, + {0x28, 0x01, 0x03, 0x01, "Hard" }, + {0x28, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Invulnerability" }, + {0x28, 0x01, 0x04, 0x04, "Off" }, + {0x28, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Power-Up Bonus" }, + {0x28, 0x01, 0x08, 0x08, "Off" }, + {0x28, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Regain Power" }, + {0x28, 0x01, 0x10, 0x10, "Off" }, + {0x28, 0x01, 0x10, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Credits" }, + {0x28, 0x01, 0x20, 0x20, "Combined" }, + {0x28, 0x01, 0x20, 0x00, "Separate" }, + + {0 , 0xfe, 0 , 2, "Cabinet Style" }, + {0x28, 0x01, 0xc0, 0xc0, "3 Players" }, + {0x28, 0x01, 0xc0, 0x80, "2 Players" }, + {0x28, 0x01, 0xc0, 0x40, "4 Players/1 Machine" }, + {0x28, 0x01, 0xc0, 0x00, "4 Players/2 Machines" }, +}; + +STDDIPINFO(Silentdj) + +static struct BurnDIPInfo ViofightDIPList[]= +{ + {0x14, 0xff, 0xff, 0xff, NULL }, + {0x15, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x14, 0x01, 0x02, 0x02, "Off" }, + {0x14, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x14, 0x01, 0x04, 0x04, "Off" }, + {0x14, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x14, 0x01, 0x08, 0x00, "Off" }, + {0x14, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coin A" }, + {0x14, 0x01, 0x30, 0x00, "4 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x14, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x14, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x14, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x14, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x14, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x15, 0x01, 0x03, 0x02, "Easy" }, + {0x15, 0x01, 0x03, 0x03, "Medium" }, + {0x15, 0x01, 0x03, 0x01, "Hard" }, + {0x15, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Viofight) + +static struct BurnDIPInfo HiticeDIPList[]= +{ + {0x25, 0xff, 0xff, 0xff, NULL }, + {0x26, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet Style" }, + {0x25, 0x01, 0x01, 0x01, "4 Players" }, + {0x25, 0x01, 0x01, 0x00, "2 Players" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x25, 0x01, 0x04, 0x04, "Off" }, + {0x25, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x25, 0x01, 0x08, 0x00, "Off" }, + {0x25, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x25, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x25, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + {0x25, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x25, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x25, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x25, 0x01, 0xc0, 0xc0, "1 Coin 1 Credits" }, + {0x25, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x25, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x26, 0x01, 0x03, 0x02, "Easy" }, + {0x26, 0x01, 0x03, 0x03, "Medium" }, + {0x26, 0x01, 0x03, 0x01, "Hard" }, + {0x26, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Timer count" }, + {0x26, 0x01, 0x0c, 0x0c, "1 sec = 58/60" }, + {0x26, 0x01, 0x0c, 0x04, "1 sec = 56/60" }, + {0x26, 0x01, 0x0c, 0x08, "1 sec = 62/60" }, + {0x26, 0x01, 0x0c, 0x00, "1 sec = 45/60" }, + + {0 , 0xfe, 0 , 2, "Maximum credits" }, + {0x26, 0x01, 0x80, 0x00, "99" }, + {0x26, 0x01, 0x80, 0x80, "9" }, +}; + +STDDIPINFO(Hitice) + +static struct BurnDIPInfo Rambo3uDIPList[]= +{ + {0x17, 0xff, 0xff, 0xff, NULL }, + {0x18, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 0, "Flip Screen" }, + {0x17, 0x01, 0x02, 0x02, "Off" }, + {0x17, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x17, 0x01, 0x04, 0x04, "Off" }, + {0x17, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x17, 0x01, 0x08, 0x00, "Off" }, + {0x17, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 2, "Coinage" }, + {0x17, 0x01, 0x30, 0x10, "3 Coins 1 Credits" }, + {0x17, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x17, 0x01, 0x30, 0x00, "4 Coins 3 Credits" }, + {0x17, 0x01, 0x30, 0x30, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Price to Continue" }, + {0x17, 0x01, 0xc0, 0x40, "2 Coins 1 Credits" }, + {0x17, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" }, + {0x17, 0x01, 0xc0, 0xc0, "Same as Start" }, + {0x17, 0x01, 0xc0, 0x00, "Same as Start or 1C/1C (if Coinage 4C/3C)" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x18, 0x01, 0x03, 0x02, "Easy" }, + {0x18, 0x01, 0x03, 0x03, "Medium" }, + {0x18, 0x01, 0x03, 0x01, "Hard" }, + {0x18, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 1, "Control" }, + {0x18, 0x01, 0x08, 0x08, "8 way Joystick" }, +// {0x18, 0x01, 0x08, 0x00, "Trackball" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x18, 0x01, 0x10, 0x00, "Off" }, + {0x18, 0x01, 0x10, 0x10, "On" }, +}; + +STDDIPINFO(Rambo3u) + +static const eeprom_interface taitob_eeprom_intf = +{ + 6, // address bits + 16, // data bits + "0110", // read command + "0101", // write command + "0111", // erase command + "0100000000", // lock command + "0100110000", // unlock command + 0, + 0 +}; + +static void bankswitch(UINT32, UINT32 data) +{ + TaitoZ80Bank = data & 0x03; + + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + TaitoZ80Bank * 0x4000); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + TaitoZ80Bank * 0x4000); +} + +void __fastcall taitob_sound_write_ym2610(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + BurnYM2610Write(a & 3, d); + return; + + case 0xe200: + TC0140SYTSlavePortWrite(d); + return; + + case 0xe201: + TC0140SYTSlaveCommWrite(d); + return; + + case 0xf200: + bankswitch(0, d); + return; + } +} + +UINT8 __fastcall taitob_sound_read_ym2610(UINT16 a) +{ + switch (a) + { + case 0xe000: + case 0xe001: + case 0xe002: + case 0xe003: + return BurnYM2610Read(a & 3); + + case 0xe201: + return TC0140SYTSlaveCommRead(); + } + + return 0; +} + +void __fastcall taitob_sound_write_ym2203(UINT16 a, UINT8 d) +{ + switch (a) + { + case 0x9000: + case 0x9001: + BurnYM2203Write(0, a & 1, d); + return; + + case 0xb000: + case 0xb001: + MSM6295Command(0, d); + return; + + case 0xa000: + TC0140SYTSlavePortWrite(d); + return; + + case 0xa001: + TC0140SYTSlaveCommWrite(d); + return; + } +} + +UINT8 __fastcall taitob_sound_read_ym2203(UINT16 a) +{ + switch (a) + { + case 0x9000: + case 0x9001: + return BurnYM2203Read(0, a & 1); + + case 0xb000: + case 0xb001: + return MSM6295ReadStatus(0); + + case 0xa001: + return TC0140SYTSlaveCommRead(); + } + + return 0; +} + +static void DrvMakeInputs() +{ + memset (TC0220IOCInput, 0xff, 3); + memset (TaitoInput + 3, 0xff, 3); + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[0] ^= (TC0220IOCInputPort0[i] & 1) << i; + TC0220IOCInput[1] ^= (TC0220IOCInputPort1[i] & 1) << i; + TC0220IOCInput[2] ^= (TC0220IOCInputPort2[i] & 1) << i; + TaitoInput[3] ^= (TaitoInputPort3[i] & 1) << i; + TaitoInput[4] ^= (TaitoInputPort4[i] & 1) << i; + TaitoInput[5] ^= (TaitoInputPort5[i] & 1) << i; + } + + // normal coin state is active low, but some games have + // active high buttons or coin inputs + TC0220IOCInput[0] ^= nTaitoInputConfig[0]; + TC0220IOCInput[1] ^= nTaitoInputConfig[1]; + TC0220IOCInput[2] ^= nTaitoInputConfig[2]; + TaitoInput[3] ^= nTaitoInputConfig[3]; + + // set up coin lockout + switch (nTaitoInputConfig[4]) { + case 0: // viofight, sbm, common + if (TaitoCoinLockout[0]) TC0220IOCInput[2] |= (1 << 2); + if (TaitoCoinLockout[1]) TC0220IOCInput[2] |= (1 << 3); + break; + + case 1: // rambo3a, hitice, selfeena + if (TaitoCoinLockout[0]) TC0220IOCInput[1] |= (1 << 4); + if (TaitoCoinLockout[1]) TC0220IOCInput[1] |= (1 << 5); + break; + + case 2: // silentd, spacedxo + if (TaitoCoinLockout[0]) TC0220IOCInput[1] |= (1 << 4); + if (TaitoCoinLockout[1]) TC0220IOCInput[1] |= (1 << 5); + if (TaitoCoinLockout[2]) TaitoInput[5] |= (1 << 0); + if (TaitoCoinLockout[3]) TaitoInput[5] |= (1 << 2); + break; + + case 3: // qzshowby, pbobble + if (TaitoCoinLockout[0]) TC0220IOCInput[0] |= (1 << 4); + if (TaitoCoinLockout[1]) TC0220IOCInput[0] |= (1 << 5); + if (TaitoCoinLockout[2]) TC0220IOCInput[0] |= (1 << 6); + if (TaitoCoinLockout[3]) TC0220IOCInput[0] |= (1 << 7); + break; + } + + // for rambo3a's trackball + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); + BurnGunMakeInputs(1, (INT16)TaitoAnalogPort2, (INT16)TaitoAnalogPort3); +} + +static void DrvFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 DrvSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / cpu_speed[1]; +} + +static double DrvGetTime() +{ + return (double)ZetTotalCycles() / (cpu_speed[1] * 1.0); +} + +static INT32 DrvDoReset(INT32 reset_ram) +{ + if (reset_ram) { + memset (TaitoRamStart, 0, TaitoRamEnd - TaitoRamStart); + } + + if (DrvFramebuffer) { + memset (DrvFramebuffer, 0, 1024 * 512); + } + + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + if (sound_config == 0) { + BurnYM2610Reset(); + } else { + BurnYM2203Reset(); + MSM6295Reset(0); + } + + TaitoICReset(); + + EEPROMReset(); + + coin_control = 0; + eeprom_latch = 0; + TaitoZ80Bank = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += ((Taito68KRom1Size - 1) | 0x7ffff) + 1; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + + TaitoChars = Next; Next += (TaitoCharRomSize * 8) / 4; + TaitoSpritesA = Next; Next += (TaitoCharRomSize * 8) / 4; + + TaitoMSM6295Rom = Next; Next += TaitoMSM6295RomSize; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + if (!(TaitoMSM6295RomSize | TaitoYM2610ARomSize | TaitoYM2610ARomSize)) { + Next += 0x040000; // games without samples... + } + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x010000; + TaitoPaletteRam = Next; Next += 0x002000; + TaitoSpriteRam = Next; Next += 0x002000; + + // hit the ice + DrvPxlRAM = Next; Next += 0x080000; + DrvPxlScroll = (UINT16*)Next; Next += 2 * sizeof(UINT16); + + TaitoZ80Ram1 = Next; Next += 0x002000; + + TaitoRamEnd = Next; + + TaitoPalette = (UINT32*)Next; Next += 0x1000 * sizeof(UINT32); + + TaitoMemEnd = Next; + + return 0; +} + +static void DrvGfxDecode(INT32 len, INT32 *tilemask0, INT32 *tilemask1) +{ + if (len == 0) return; // tetrist + + INT32 Planes[4] = { 0, 8, (len * 8) / 2 + 0, (len * 8) / 2 + 8 }; + INT32 XOffs[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x080, 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087 }; + INT32 YOffs[16] = { 0x000, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170 }; + + UINT8 *tmp = (UINT8*)malloc(len); + if (tmp == NULL) { + return; + } + + memcpy (tmp, TaitoChars, len); + + GfxDecode(((len * 8) / 4) / ( 8 * 8), 4, 8, 8, Planes, XOffs, YOffs, 0x080, tmp, TaitoChars); + GfxDecode(((len * 8) / 4) / (16 * 16), 4, 16, 16, Planes, XOffs, YOffs, 0x200, tmp, TaitoSpritesA); + + *tilemask0 = (((len * 8) / 4) / ( 8 * 8)) - 1; + *tilemask1 = (((len * 8) / 4) / (16 * 16)) - 1; + + if (tmp) { + free (tmp); + tmp = NULL; + } +} + +static void common_ym2610_init() +{ + sound_config = 0; + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1); + ZetSetWriteHandler(taitob_sound_write_ym2610); + ZetSetReadHandler(taitob_sound_read_ym2610); + ZetMemEnd(); + ZetClose(); + + TC0140SYTInit(); + + INT32 len0 = TaitoYM2610ARomSize; + INT32 len1 = TaitoYM2610BRomSize; + + BurnYM2610Init(8000000, TaitoYM2610ARom, &len0, TaitoYM2610BRom, &len1, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnTimerAttachZet(cpu_speed[1]); + BurnYM2610SetSoundMixMode(1); +} + +static void common_ym2203_init() +{ + sound_config = 1; + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1); + ZetSetWriteHandler(taitob_sound_write_ym2203); + ZetSetReadHandler(taitob_sound_read_ym2203); + ZetMemEnd(); + ZetClose(); + + TC0140SYTInit(); + + BurnYM2203Init(1, 3000000, DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0); + BurnYM2203SetPorts(0, NULL, NULL, &bankswitch, NULL); + BurnTimerAttachZet(cpu_speed[1]); + + MSM6295ROM = TaitoMSM6295Rom; + + MSM6295Init(0, 1056000 / 132, 80, 1); +} + +static INT32 CommonInit(void (*pInitCallback)(), INT32 sound_type, INT32 color_select, INT32 input_type, INT32 irq0, INT32 irq1) +{ + static const UINT8 color_types[3][4] = { + { 0xc0, 0x80, 0x00, 0x40 }, + { 0x00, 0x40, 0xc0, 0x80 }, + { 0x30, 0x20, 0x00, 0x10 } + }; + + TaitoLoadRoms(false); + + TaitoMem = NULL; + MemIndex(); + INT32 nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(true)) return 1; + + INT32 tilemaskChars = 0, tilemaskSprites = 0; + DrvGfxDecode(TaitoCharRomSize, &tilemaskChars, &tilemaskSprites); + + memcpy (color_config, color_types[color_select], 4); + + irq_config[0] = irq0; + irq_config[1] = irq1; + + cpu_speed[0] = 12000000; + cpu_speed[1] = 4000000; + + nTaitoInputConfig[4] = input_type; + + TC0220IOCInit(); + TaitoMakeInputsFunction = DrvMakeInputs; + + TC0180VCUInit(TaitoChars, tilemaskChars, TaitoSpritesA, tilemaskSprites, 0, 16); + + EEPROMInit(&taitob_eeprom_intf); + + if (pInitCallback) { + pInitCallback(); + } + + if (sound_type) { + common_ym2203_init(); + } else { + common_ym2610_init(); + } + + GenericTilesInit(); + + DrvDoReset(1); + + return 0; +} + +static INT32 DrvExit() +{ + EEPROMExit(); + + TaitoICExit(); + GenericTilesExit(); + + SekExit(); + ZetExit(); + + BurnYM2610SetSoundMixMode(0); + + if (sound_config == 0) { + BurnYM2610Exit(); + } else { + BurnYM2203Exit(); + MSM6295Exit(0); + MSM6295ROM = NULL; + } + + if (TaitoMem) { + free (TaitoMem); + TaitoMem = NULL; + } + + if (DrvFramebuffer) { + free (DrvFramebuffer); + DrvFramebuffer = NULL; + } + + memset (nTaitoInputConfig, 0, 5); + + TaitoExit(); + + return 0; +} + +static void DrvPaletteUpdate() +{ + UINT16 *p = (UINT16*)TaitoPaletteRam; + + for (INT32 i = 0; i < 0x2000 / 2; i++) + { + INT32 r = (p[i] >> 12) & 0x0f; + INT32 g = (p[i] >> 8) & 0x0f; + INT32 b = (p[i] >> 4) & 0x0f; + + r |= r << 4; + g |= g << 4; + b |= b << 4; + + TaitoPalette[i] = BurnHighCol(r, g, b, 0); + } +} + +static void draw_hitice_framebuffer() +{ + if (DrvFramebuffer == NULL) return; + + INT32 scrollx = -((2 * DrvPxlScroll[0] + 0) & 0x3ff); + INT32 scrolly = -((1 * DrvPxlScroll[1] + 16) & 0x1ff); + + for (INT32 sy = 0; sy < nScreenHeight; sy++) + { + UINT16 *dst = pTransDraw + sy * nScreenWidth; + UINT8 *src = DrvFramebuffer + ((sy + scrolly) & 0x1ff) * 1024; + + for (INT32 sx = 0; sx < nScreenWidth; sx++) { + INT32 pxl = src[(sx + scrollx) & 0x3ff]; + + if (pxl) { + dst[sx] = pxl | 0x800; + } + } + } +} + +static INT32 DrvDraw() +{ + DrvPaletteUpdate(); + + INT32 ctrl = TC0180VCUReadControl(); + + if (~ctrl & 0x20) { + BurnTransferClear(); + BurnTransferCopy(TaitoPalette); + return 0; + } + + if (~nBurnLayer & 1) BurnTransferClear(); + + if (nBurnLayer & 1) TC0180VCUDrawLayer(color_config[0], 1, -1); + + if (nSpriteEnable & 1) TC0180VCUFramebufferDraw(1, color_config[3] << 4); + + if (nBurnLayer & 2) TC0180VCUDrawLayer(color_config[1], 0, 0); + + draw_hitice_framebuffer(); + + if (nSpriteEnable & 2) TC0180VCUFramebufferDraw(0, color_config[3] << 4); + + if (nBurnLayer & 4) TC0180VCUDrawCharLayer(color_config[2]); + + BurnTransferCopy(TaitoPalette); + + TC0180VCUBufferSprites(); + + return 0; +} + +static INT32 DrvFrame() +{ + if (TaitoReset) { + DrvDoReset(1); + } + + SekNewFrame(); + ZetNewFrame(); + + TaitoWatchdog++; + if (TaitoWatchdog > 180) { + DrvDoReset(0); +// bprintf (0, _T("watchdog triggered!\n")); + } + + TaitoMakeInputsFunction(); + + SekOpen(0); + ZetOpen(0); + + INT32 SekSpeed = (INT32)((INT64)cpu_speed[0] * nBurnCPUSpeedAdjust / 0x100); + INT32 ZetSpeed = (INT32)((INT64)cpu_speed[1] * nBurnCPUSpeedAdjust / 0x100); + + INT32 nInterleave = 200; // high so that ym2203 sounds are good, 200 is perfect for irq #0 + INT32 nCyclesTotal[2] = { SekSpeed / 60, ZetSpeed / 60 }; + INT32 nCyclesDone[2] = { 0, 0 }; + INT32 nNext[2] = { 0, 0 }; + + for (INT32 i = 0; i < nInterleave; i++) { + nNext[0] += nCyclesTotal[0] / nInterleave; + nCyclesDone[0] += SekRun(nNext[0] - nCyclesDone[0]); + if (i == 4) SekSetIRQLine(irq_config[0], SEK_IRQSTATUS_AUTO); // Start of frame + 5000 cycles + if (i == (nInterleave / 1) - 1) SekSetIRQLine(irq_config[1], SEK_IRQSTATUS_AUTO); // End of frame + nNext[1] += nCyclesTotal[1] / nInterleave; + BurnTimerUpdate(nNext[1]); + nCyclesDone[1] += nNext[1]; + } + + BurnTimerEndFrame(nCyclesTotal[1]); + + if (pBurnSoundOut) { + if (sound_config == 0) { + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + } else { + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + } + + ZetClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); + } + + return 0; +} + +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { + *pnMin = 0x029708; + } + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd - TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + TaitoICScan(nAction); + + if (sound_config == 0) { + BurnYM2610Scan(nAction, pnMin); + } else { + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + } + + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(TaitoWatchdog); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + bankswitch(0, TaitoZ80Bank); + ZetClose(); + } + + return 0; +} + + +//---------------------------------------------------------------------------------------------------------- +// Rastan Saga 2 / Ashura Blaster + +UINT8 __fastcall rastsag2_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + TC0220IOCHalfWordRead_Map(0xa00000) + + switch (a) + { + case 0x800002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall rastsag2_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0xa00000) + + switch (a) + { + case 0x800000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x800002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall rastsag2_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) +} + +static void NastarInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TaitoPaletteRam, 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x600000, 0x607fff, SM_RAM); + SekSetWriteByteHandler(0, rastsag2_write_byte); + SekSetWriteWordHandler(0, rastsag2_write_word); + SekSetReadByteHandler(0, rastsag2_read_byte); +// SekSetReadWordHandler(0, rastsag2_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Crime City + +UINT8 __fastcall crimec_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + TC0180VCUHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x600002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall crimec_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0180VCUHalfWordWrite_Map(0x400000) + + switch (a) + { + case 0x600000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x600002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall crimec_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) +} + +static void CrimecInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x800000, 0x801fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0xa00000, 0xa0ffff, SM_RAM); + SekSetWriteByteHandler(0, crimec_write_byte); + SekSetWriteWordHandler(0, crimec_write_word); + SekSetReadByteHandler(0, crimec_read_byte); +// SekSetReadWordHandler(0, crimec_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Tetris (ym2610) + +UINT8 __fastcall tetrist_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + TC0220IOCHalfWordRead_Map(0x600000) + + switch (a) + { + case 0x200002: // not used? + return TC0140SYTCommRead(); + + case 0x600010: { // tracky1_lo_r + INT32 ret = (( TaitoAnalogPort1 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x600014: {// trackx1_lo_r + INT32 ret = ((~TaitoAnalogPort0 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x600018: {// tracky2_lo_r + INT32 ret = (( TaitoAnalogPort3 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x60001c: {// trackx2_lo_r + INT32 ret = ((~TaitoAnalogPort2 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + } + + return 0; +} + +UINT16 __fastcall tetrist_read_word(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x600000) + + switch (a) + { + case 0x600012: {// tracky1_hi_r + INT32 ret = (( TaitoAnalogPort1 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x600016: {// trackx1_hi_r + INT32 ret = ((~TaitoAnalogPort0 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x60001a: {// tracky2_hi_r + INT32 ret = (( TaitoAnalogPort3 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + + case 0x60001e: {// trackx2_hi_r + INT32 ret = ((~TaitoAnalogPort2 >> 4) & 0xffff); + if (ret == 0xffff) return 0; + return (ret+1); + } + } + + return 0; +} + +void __fastcall tetrist_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x600000) + + switch (a) + { + case 0x200000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x200002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall tetrist_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x600000) +} + +static void TetristInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x800000, 0x807fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0xa00000, 0xa01fff, SM_RAM); + SekSetWriteByteHandler(0, tetrist_write_byte); + SekSetWriteWordHandler(0, tetrist_write_word); + SekSetReadByteHandler(0, tetrist_read_byte); + SekSetReadWordHandler(0, tetrist_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Puzzle Bobble / Space Invaders Dx (v2.1) + +UINT8 __fastcall pbobble_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x500000: + return TC0220IOCDip[0]; + + case 0x500002: + return ((TC0220IOCInput[0] & 0xfe) | (EEPROMRead() & 1)); + + case 0x500004: + return TC0220IOCInput[1]; + + case 0x500006: + return TC0220IOCInput[2]; + + case 0x500008: + return TC0220IOCRead(0x08 / 2); + + case 0x50000e: + return TaitoInput[3]; + + case 0x500024: + return TaitoInput[4]; + + case 0x500026: + return eeprom_latch; + + case 0x50002e: + return TaitoInput[5]; + + case 0x700002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall pbobble_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x500000) + + switch (a) + { + case 0x500026: + eeprom_latch = d; + EEPROMWrite((d & 0x08), (d & 0x10), (d & 0x04)); + return; + + case 0x500028: + coin_control = d; + TaitoCoinLockout[2] = ~d & 0x01; + TaitoCoinLockout[3] = ~d & 0x02; + // coin counter d & 0x04, d & 0x08 + return; + + case 0x600000: + case 0x600002: // gain + return; + + case 0x700000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x700002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall pbobble_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x500000) +} + +static void PbobbleInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x800000, 0x801fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x900000, 0x90ffff, SM_RAM); + SekSetWriteByteHandler(0, pbobble_write_byte); + SekSetWriteWordHandler(0, pbobble_write_word); + SekSetReadByteHandler(0, pbobble_read_byte); +// SekSetReadWordHandler(0, pbobble_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Sel Feena / Ryu Jin + +UINT8 __fastcall selfeena_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x400000) + TC0220IOCHalfWordRead_Map(0x410000) + + if (a >= 0x218000 && a <= 0x21801f) { + return TC0180VCUReadRegs(a); + } + + switch (a) + { + case 0x500002: // not used? + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall selfeena_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x200000) + TC0220IOCHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x410000) + + switch (a) + { + case 0x500000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x500002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall selfeena_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x200000) +} + +static void SelfeenaInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x210000, 0x2137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x213800, 0x213fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x300000, 0x301fff, SM_RAM); + SekSetWriteByteHandler(0, selfeena_write_byte); + SekSetWriteWordHandler(0, selfeena_write_word); + SekSetReadByteHandler(0, selfeena_read_byte); +// SekSetReadWordHandler(0, selfeena_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Sonic Blast Man + +UINT8 __fastcall sbm_read_byte(UINT32 a) +{ + if ((a & 0xffffff0) == 0x300000) a ^= 2; + TC0220IOCHalfWordRead_Map(0x300000) + TC0180VCUHalfWordRead_Map(0x900000) + + switch (a) + { + case 0x320002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall sbm_write_byte(UINT32 a, UINT8 d) +{ + if ((a & 0xffffff0) == 0x300000) a ^= 2; + TC0220IOCHalfWordWrite_Map(0x300000) + TC0180VCUHalfWordWrite_Map(0x900000) + + switch (a) + { + case 0x320000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x320002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall sbm_write_word(UINT32 a, UINT16 d) +{ + if ((a & 0xffffff0) == 0x0300000) a ^= 2; + TC0220IOCHalfWordWrite_Map(0x300000) + TC0180VCUWordWrite_Map(0x900000) +} + +static void SbmInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x910000, 0x9137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x913800, 0x913fff, SM_RAM); + SekSetWriteByteHandler(0, sbm_write_byte); + SekSetWriteWordHandler(0, sbm_write_word); + SekSetReadByteHandler(0, sbm_read_byte); +// SekSetReadWordHandler(0, sbm_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Silent Dragon + +UINT8 __fastcall silentd_read_byte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + TC0180VCUHalfWordRead_Map(0x500000) + + switch (a) + { + case 0x100003: // not used? + return TC0140SYTCommRead(); + + case 0x210001: + return TaitoInput[3]; + + case 0x220001: + return TaitoInput[4]; + + case 0x230001: + return TaitoInput[5]; + } + + return 0; +} + +void __fastcall silentd_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0180VCUHalfWordWrite_Map(0x500000) + + switch (a) + { + case 0x100000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x100002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall silentd_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x500000) +} + +static void SilentdInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TaitoPaletteRam, 0x300000, 0x301fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x400000, 0x403fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x500000, 0x50ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x510000, 0x5137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x513800, 0x513fff, SM_RAM); + SekSetWriteByteHandler(0, silentd_write_byte); + SekSetWriteWordHandler(0, silentd_write_word); + SekSetReadByteHandler(0, silentd_read_byte); +// SekSetReadWordHandler(0, silentd_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Violence Fight + +UINT8 __fastcall viofight_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + TC0220IOCHalfWordRead_Map(0x800000) + + switch (a) + { + case 0x200002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall viofight_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x800000) + + switch (a) + { + case 0x200000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x200002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall viofight_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x800000) +} + +static void ViofightInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x600000, 0x601fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0xa00000, 0xa03fff, SM_RAM); + SekSetWriteByteHandler(0, viofight_write_byte); + SekSetWriteWordHandler(0, viofight_write_word); + SekSetReadByteHandler(0, viofight_read_byte); +// SekSetReadWordHandler(0, viofight_read_word); + SekClose(); + + memcpy (Taito68KRom1 + 0x40000, Taito68KRom1 + 0x20000, 0x40000); + + cpu_speed[1] = 6000000; // 6mhz +} + +//---------------------------------------------------------------------------------------------------------- +// Hit the Ice + +UINT8 __fastcall hitice_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + TC0220IOCHalfWordRead_Map(0x600000) + + switch (a) + { + case 0x610000: + return TC0220IOCInput[4]; + + case 0x610001: + return TC0220IOCInput[3]; + + case 0x700002: + return TC0140SYTCommRead(); + } + + return 0; +} + +static void hiticeFramebufferUpdate(UINT32 offset) +{ + offset &= 0x7fffe; + DrvFramebuffer[offset + 0] = DrvPxlRAM[offset]; + DrvFramebuffer[offset + 1] = DrvPxlRAM[offset]; +} + +void __fastcall hitice_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x600000) + + if (a >= 0xb00000 && a <= 0xb7ffff) { + DrvPxlRAM[(a & 0x7ffff)^1] = d; + hiticeFramebufferUpdate(a); + return; + } + + switch (a) + { + case 0x700000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x700002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall hitice_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x600000) + + if (a >= 0xb00000 && a <= 0xb7ffff) { + *((UINT16*)(DrvPxlRAM + (a & 0x7fffe))) = d; + hiticeFramebufferUpdate(a); + return; + } + + switch (a) + { + case 0xbffff2: + DrvPxlScroll[0] = d; + return; + + case 0xbffff4: + DrvPxlScroll[1] = d; + return; + } +} + +static void HiticeInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x800000, 0x803fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0xa00000, 0xa01fff, SM_RAM); + SekMapMemory(DrvPxlRAM, 0xb00000, 0xb7ffff, SM_ROM); + SekSetWriteByteHandler(0, hitice_write_byte); + SekSetWriteWordHandler(0, hitice_write_word); + SekSetReadByteHandler(0, hitice_read_byte); +// SekSetReadWordHandler(0, hitice_read_word); + SekClose(); + + DrvFramebuffer = (UINT8*)malloc(1024 * 512); +} + +//---------------------------------------------------------------------------------------------------------- +// Tetris (ym2203) + +UINT8 __fastcall tetrista_read_byte(UINT32 a) +{ + TC0180VCUHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x600000: + case 0x800000: + return TC0220IOCPortRegRead(); + + case 0x600002: + case 0x800002: + return TC0220IOCPortRead(); + + case 0xa00002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall tetrista_write_byte(UINT32 a, UINT8 d) +{ + TC0180VCUHalfWordWrite_Map(0x400000) + + switch (a) + { + case 0x600000: + case 0x800000: + TaitoWatchdog = 0; + TC0220IOCHalfWordPortRegWrite(d); + return; + + case 0x600002: + case 0x800002: + TC0220IOCHalfWordPortWrite(d); + return; + + case 0xa00000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0xa00002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + } +} + +void __fastcall tetrista_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) +} + +static void TetristaInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TaitoPaletteRam, 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x800000, 0x803fff, SM_RAM); + SekSetWriteByteHandler(0, tetrista_write_byte); + SekSetWriteWordHandler(0, tetrista_write_word); + SekSetReadByteHandler(0, tetrista_read_byte); +// SekSetReadWordHandler(0, tetrista_read_word); + SekClose(); +} + +static void MasterwInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1, 0x200000, 0x203fff, SM_RAM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x600000, 0x601fff, SM_RAM); + SekSetWriteByteHandler(0, tetrista_write_byte); + SekSetWriteWordHandler(0, tetrista_write_word); + SekSetReadByteHandler(0, tetrista_read_byte); +// SekSetReadWordHandler(0, tetrista_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- +// Quiz Sekai Wa Show by shobai + + +UINT8 __fastcall qzshowby_read_byte(UINT32 a) +{ + if (a != 0x200002) { + TC0220IOCHalfWordRead_Map(0x200000) + } + + TC0180VCUHalfWordRead_Map(0x400000) + + switch (a) + { + case 0x200002: + return ((TC0220IOCInput[0] & 0xfe) | (EEPROMRead() & 1)); + + case 0x200024: + return TC0220IOCInput[4]; + + case 0x200028: + return coin_control; + + case 0x20002e: + return TC0220IOCInput[5]; + + case 0x600002: + return TC0140SYTCommRead(); + } + + return 0; +} + +void __fastcall qzshowby_write_byte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0180VCUHalfWordWrite_Map(0x400000) + + switch (a) + { + case 0x200026: + EEPROMWrite((d & 0x08), (d & 0x10), (d & 0x04)); + return; + + case 0x200028: + coin_control = d; + TaitoCoinLockout[2] = ~d & 0x01; + TaitoCoinLockout[3] = ~d & 0x02; + // coin counter d & 0x04, d & 0x08 + return; + + case 0x600000: + TC0140SYTPortWrite(d & 0xff); + return; + + case 0x600002: + ZetClose(); + TC0140SYTCommWrite(d & 0xff); + ZetOpen(0); + return; + + case 0x700000: + case 0x700002: + // gain + return; + } +} + +void __fastcall qzshowby_write_word(UINT32 a, UINT16 d) +{ + TC0180VCUWordWrite_Map(0x400000) + TC0220IOCHalfWordWrite_Map(0x200000) +} + +static void QzshowbyInitCallback() +{ + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1, 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(TC0180VCURAM, 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam, 0x410000, 0x4137ff, SM_RAM); + SekMapMemory(TC0180VCUScrollRAM, 0x413800, 0x413fff, SM_RAM); + SekMapMemory(TaitoPaletteRam, 0x800000, 0x801fff, SM_RAM); + SekMapMemory(Taito68KRam1, 0x900000, 0x90ffff, SM_RAM); + SekSetWriteByteHandler(0, qzshowby_write_byte); + SekSetWriteWordHandler(0, qzshowby_write_word); + SekSetReadByteHandler(0, qzshowby_read_byte); +// SekSetReadWordHandler(0, qzshowby_read_word); + SekClose(); +} + +//---------------------------------------------------------------------------------------------------------- + + +// Master of Weapon (World) + +static struct BurnRomInfo masterwRomDesc[] = { + { "b72_06.33", 0x020000, 0xae848eff, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b72_12.24", 0x020000, 0x7176ce70, TAITO_68KROM1_BYTESWAP }, // 1 + { "b72_04.34", 0x020000, 0x141e964c, TAITO_68KROM1_BYTESWAP }, // 2 + { "b72_03.25", 0x020000, 0xf4523496, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b72_07.30", 0x010000, 0x2b1a946f, TAITO_Z80ROM1 }, // 4 Z80 code + + { "b72-02.rom", 0x080000, 0xc519f65a, TAITO_CHARS }, // 5 Graphics Tiles + { "b72-01.5", 0x080000, 0xa24ac26e, TAITO_CHARS }, // 6 +}; + +STD_ROM_PICK(masterw) +STD_ROM_FN(masterw) + +static INT32 MasterwInit() +{ + return CommonInit(MasterwInitCallback, 1, 2, 0, 4, 5); +} + +struct BurnDriver BurnDrvMasterw = { + "masterw", NULL, NULL, NULL, "1989", + "Master of Weapon (World)\0", "Imperfect graphics", "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, masterwRomInfo, masterwRomName, NULL, NULL, CommonInputInfo, MasterwDIPInfo, + MasterwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Master of Weapon (US) + +static struct BurnRomInfo masterwuRomDesc[] = { + { "b72_06.33", 0x020000, 0xae848eff, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b72_11.24", 0x020000, 0x0671fee6, TAITO_68KROM1_BYTESWAP }, // 1 + { "b72_04.34", 0x020000, 0x141e964c, TAITO_68KROM1_BYTESWAP }, // 2 + { "b72_03.25", 0x020000, 0xf4523496, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b72_07.30", 0x010000, 0x2b1a946f, TAITO_Z80ROM1 }, // 4 Z80 code + + { "b72-02.rom", 0x080000, 0xc519f65a, TAITO_CHARS }, // 5 Graphics Tiles + { "b72-01.5", 0x080000, 0xa24ac26e, TAITO_CHARS }, // 6 +}; + +STD_ROM_PICK(masterwu) +STD_ROM_FN(masterwu) + +struct BurnDriver BurnDrvMasterwu = { + "masterwu", "masterw", NULL, NULL, "1989", + "Master of Weapon (US)\0", "Imperfect graphics", "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, masterwuRomInfo, masterwuRomName, NULL, NULL, CommonInputInfo, MasterwDIPInfo, + MasterwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Master of Weapon (Japan) + +static struct BurnRomInfo masterwjRomDesc[] = { + { "b72_06.33", 0x020000, 0xae848eff, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b72_05.24", 0x020000, 0x9f78af5c, TAITO_68KROM1_BYTESWAP }, // 1 + { "b72_04.34", 0x020000, 0x141e964c, TAITO_68KROM1_BYTESWAP }, // 2 + { "b72_03.25", 0x020000, 0xf4523496, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b72_07.30", 0x010000, 0x2b1a946f, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b72-02.6", 0x080000, 0x843444eb, TAITO_CHARS }, // 5 Graphics Tiles + { "b72-01.5", 0x080000, 0xa24ac26e, TAITO_CHARS }, // 6 +}; + +STD_ROM_PICK(masterwj) +STD_ROM_FN(masterwj) + +struct BurnDriver BurnDrvMasterwj = { + "masterwj", "masterw", NULL, NULL, "1989", + "Master of Weapon (Japan)\0", "Imperfect graphics", "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, masterwjRomInfo, masterwjRomName, NULL, NULL, CommonInputInfo, MasterwDIPInfo, + MasterwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Nastar (World) + +static struct BurnRomInfo nastarRomDesc[] = { + { "b81-08.50", 0x020000, 0xd6da9169, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b81-13.31", 0x020000, 0x60d176fb, TAITO_68KROM1_BYTESWAP }, // 1 + { "b81-10.49", 0x020000, 0x53f34344, TAITO_68KROM1_BYTESWAP }, // 2 + { "b81-09.30", 0x020000, 0x630d34af, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b81-11.37", 0x010000, 0x3704bf09, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b81-03.14", 0x080000, 0x551b75e6, TAITO_CHARS }, // 5 Graphics Tiles + { "b81-04.15", 0x080000, 0xcf734e12, TAITO_CHARS }, // 6 + + { "b81-02.2", 0x080000, 0x20ec3b86, TAITO_YM2610A }, // 7 YM2610 A Samples + + { "b81-01.1", 0x080000, 0xb33f796b, TAITO_YM2610B }, // 8 YM2610 B Samples + + { "ampal16l8-b81-05.21", 0x000104, 0x922fd368, BRF_OPT }, // 9 PLDs + { "ampal16l8-b81-06a.22", 0x000104, 0xbb1cec84, BRF_OPT }, // 10 +}; + +STD_ROM_PICK(nastar) +STD_ROM_FN(nastar) + +static INT32 NastarInit() +{ + return CommonInit(NastarInitCallback, 0, 0, 0, 2, 4); +} + +struct BurnDriver BurnDrvNastar = { + "nastar", NULL, NULL, NULL, "1988", + "Nastar (World)\0", NULL, "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, nastarRomInfo, nastarRomName, NULL, NULL, CommonInputInfo, NastarDIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Rastan Saga 2 (Japan) + +static struct BurnRomInfo rastsag2RomDesc[] = { + { "b81-08.50", 0x020000, 0xd6da9169, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b81-07.31", 0x020000, 0x8edf17d7, TAITO_68KROM1_BYTESWAP }, // 1 + { "b81-10.49", 0x020000, 0x53f34344, TAITO_68KROM1_BYTESWAP }, // 2 + { "b81-09.30", 0x020000, 0x630d34af, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b81-11.37", 0x010000, 0x3704bf09, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b81-03.14", 0x080000, 0x551b75e6, TAITO_CHARS }, // 5 Graphics Tiles + { "b81-04.15", 0x080000, 0xcf734e12, TAITO_CHARS }, // 6 + + { "b81-02.2", 0x080000, 0x20ec3b86, TAITO_YM2610A }, // 7 YM2610 A Samples + + { "b81-01.1", 0x080000, 0xb33f796b, TAITO_YM2610B }, // 8 YM2610 B Samples +}; + +STD_ROM_PICK(rastsag2) +STD_ROM_FN(rastsag2) + +struct BurnDriver BurnDrvRastsag2 = { + "rastsag2", "nastar", NULL, NULL, "1988", + "Rastan Saga 2 (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, rastsag2RomInfo, rastsag2RomName, NULL, NULL, CommonInputInfo, Rastsag2DIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Nastar Warrior (US) + +static struct BurnRomInfo nastarwRomDesc[] = { + { "b81-08.50", 0x020000, 0xd6da9169, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b81-12.31", 0x020000, 0xf9d82741, TAITO_68KROM1_BYTESWAP }, // 1 + { "b81-10.49", 0x020000, 0x53f34344, TAITO_68KROM1_BYTESWAP }, // 2 + { "b81-09.30", 0x020000, 0x630d34af, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b81-11.37", 0x010000, 0x3704bf09, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b81-03.14", 0x080000, 0x551b75e6, TAITO_CHARS }, // 5 Graphics Tiles + { "b81-04.15", 0x080000, 0xcf734e12, TAITO_CHARS }, // 6 + + { "b81-02.2", 0x080000, 0x20ec3b86, TAITO_YM2610A }, // 7 YM2610 A Samples + + { "b81-01.1", 0x080000, 0xb33f796b, TAITO_YM2610B }, // 8 YM2610 B Samples +}; + +STD_ROM_PICK(nastarw) +STD_ROM_FN(nastarw) + +struct BurnDriver BurnDrvNastarw = { + "nastarw", "nastar", NULL, NULL, "1988", + "Nastar Warrior (US)\0", NULL, "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, nastarwRomInfo, nastarwRomName, NULL, NULL, CommonInputInfo, NastarwDIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Rambo III (Europe set 1) + +static struct BurnRomInfo rambo3RomDesc[] = { + { "ramb3-11.bin", 0x020000, 0x1cc42247, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "ramb3-14.bin", 0x020000, 0x7d917c21, TAITO_68KROM1_BYTESWAP }, // 1 + { "ramb3-07.bin", 0x020000, 0xc973ff6f, TAITO_68KROM1_BYTESWAP }, // 2 + { "ramb3-06.bin", 0x020000, 0xa83d3fd5, TAITO_68KROM1_BYTESWAP }, // 3 + + { "ramb3-10.bin", 0x010000, 0xb18bc020, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "ramb3-03.bin", 0x080000, 0xf5808c41, TAITO_CHARS }, // 5 Graphics Tiles + { "ramb3-04.bin", 0x080000, 0xc57831ce, TAITO_CHARS }, // 6 + { "ramb3-01.bin", 0x080000, 0xc55fcf54, TAITO_CHARS }, // 7 + { "ramb3-02.bin", 0x080000, 0x9dd014c6, TAITO_CHARS }, // 8 + + { "ramb3-05.bin", 0x080000, 0x0179dc40, TAITO_YM2610A }, // 9 YM2610 A Samples +}; + +STD_ROM_PICK(rambo3) +STD_ROM_FN(rambo3) + +static INT32 Rambo3Init() +{ + INT32 nRet = CommonInit(TetristInitCallback, 0, 0, 0, 1, 6); + + if (nRet == 0) { + memmove (Taito68KRom1 + 0x40000, Taito68KRom1 + 0x20000, 0x40000); + } + + return nRet; +} + +struct BurnDriver BurnDrvRambo3 = { + "rambo3", NULL, NULL, NULL, "1989", + "Rambo III (Europe)\0", NULL, "Taito Europe Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, rambo3RomInfo, rambo3RomName, NULL, NULL, CommonInputInfo, Rambo3DIPInfo, + Rambo3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Rambo III (US) + +static struct BurnRomInfo rambo3uRomDesc[] = { + { "ramb3-11.bin", 0x020000, 0x1cc42247, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "ramb3-13.bin", 0x020000, 0x0a964cb7, TAITO_68KROM1_BYTESWAP }, // 1 + { "ramb3-07.bin", 0x020000, 0xc973ff6f, TAITO_68KROM1_BYTESWAP }, // 2 + { "ramb3-06.bin", 0x020000, 0xa83d3fd5, TAITO_68KROM1_BYTESWAP }, // 3 + + { "ramb3-10.bin", 0x010000, 0xb18bc020, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "ramb3-03.bin", 0x080000, 0xf5808c41, TAITO_CHARS }, // 5 Graphics Tiles + { "ramb3-04.bin", 0x080000, 0xc57831ce, TAITO_CHARS }, // 6 + { "ramb3-01.bin", 0x080000, 0xc55fcf54, TAITO_CHARS }, // 7 + { "ramb3-02.bin", 0x080000, 0x9dd014c6, TAITO_CHARS }, // 8 + + { "ramb3-05.bin", 0x080000, 0x0179dc40, TAITO_YM2610A }, // 9 YM2610 A Samples +}; + +STD_ROM_PICK(rambo3u) +STD_ROM_FN(rambo3u) + +static INT32 Rambo3uInit() +{ + nTaitoInputConfig[1] = 0x30; + + return CommonInit(TetristInitCallback, 0, 2, 0, 1, 6); +} + +struct BurnDriver BurnDrvRambo3u = { + "rambo3u", "rambo3", NULL, NULL, "1989", + "Rambo III (US)\0", NULL, "Taito Europe Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, rambo3uRomInfo, rambo3uRomName, NULL, NULL, Rambo3uInputInfo, Rambo3uDIPInfo, + Rambo3uInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Rambo III (Europe, Proto?) + +static struct BurnRomInfo rambo3pRomDesc[] = { + { "r3-0e.rom", 0x010000, 0x3efa4177, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "r3-0o.rom", 0x010000, 0x55c38d92, TAITO_68KROM1_BYTESWAP }, // 1 + { "r3-1e.rom", 0x020000, 0x40e363c7, TAITO_68KROM1_BYTESWAP }, // 2 + { "r3-1o.rom", 0x020000, 0x7f1fe6ab, TAITO_68KROM1_BYTESWAP }, // 3 + + { "r3-00.rom", 0x010000, 0xdf7a6ed6, TAITO_Z80ROM1 }, // 4 Z80 Code + +// This order is different than that of MAME! This allows use of standard gfx decode. + { "r3-ch1ll.rom", 0x020000, 0xc86ea5fc, TAITO_CHARS_BYTESWAP }, // 5 Graphics Tiles + { "r3-ch1lh.rom", 0x020000, 0x75568cf0, TAITO_CHARS_BYTESWAP }, // 6 + { "r3-ch1hl.rom", 0x020000, 0x7525eb92, TAITO_CHARS_BYTESWAP }, // 7 + { "r3-ch1hh.rom", 0x020000, 0xe39cff37, TAITO_CHARS_BYTESWAP }, // 8 + { "r3-ch3ll.rom", 0x020000, 0xabe54b1e, TAITO_CHARS_BYTESWAP }, // 9 + { "r3-ch3lh.rom", 0x020000, 0x5a155c04, TAITO_CHARS_BYTESWAP }, // 10 + { "r3-ch3hl.rom", 0x020000, 0x80e5647e, TAITO_CHARS_BYTESWAP }, // 11 + { "r3-ch3hh.rom", 0x020000, 0xabe58fdb, TAITO_CHARS_BYTESWAP }, // 12 + { "r3-ch0ll.rom", 0x020000, 0xb416f1bf, TAITO_CHARS_BYTESWAP }, // 13 + { "r3-ch0lh.rom", 0x020000, 0x76a330a2, TAITO_CHARS_BYTESWAP }, // 14 + { "r3-ch0hl.rom", 0x020000, 0xa4cad36d, TAITO_CHARS_BYTESWAP }, // 15 + { "r3-ch0hh.rom", 0x020000, 0x4dc69751, TAITO_CHARS_BYTESWAP }, // 16 + { "r3-ch2ll.rom", 0x020000, 0xd0ce3051, TAITO_CHARS_BYTESWAP }, // 17 + { "r3-ch2lh.rom", 0x020000, 0xdf3bc48f, TAITO_CHARS_BYTESWAP }, // 18 + { "r3-ch2hl.rom", 0x020000, 0x837d8677, TAITO_CHARS_BYTESWAP }, // 19 + { "r3-ch2hh.rom", 0x020000, 0xbf37dfac, TAITO_CHARS_BYTESWAP }, // 20 + + { "r3-a1.rom", 0x020000, 0x4396fa19, TAITO_YM2610A }, // 21 YM2610 A Samples + { "r3-a2.rom", 0x020000, 0x41fe53a8, TAITO_YM2610A }, // 22 + { "r3-a3.rom", 0x020000, 0xe89249ba, TAITO_YM2610A }, // 23 + { "r3-a4.rom", 0x020000, 0x9cf4c21b, TAITO_YM2610A }, // 24 +}; + +STD_ROM_PICK(rambo3p) +STD_ROM_FN(rambo3p) + +struct BurnDriver BurnDrvRambo3p = { + "rambo3p", "rambo3", NULL, NULL, "1989", + "Rambo III (Europe, Proti?)\0", NULL, "Taito Europe Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SHOOT, 0, + NULL, rambo3pRomInfo, rambo3pRomName, NULL, NULL, Rambo3uInputInfo, Rambo3uDIPInfo, + Rambo3uInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Crime City (World) + +static struct BurnRomInfo crimecRomDesc[] = { + { "b99-07.40", 0x020000, 0x26e886e6, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b99-05.29", 0x020000, 0xff7f9a9d, TAITO_68KROM1_BYTESWAP }, // 1 + { "b99-06.39", 0x020000, 0x1f26aa92, TAITO_68KROM1_BYTESWAP }, // 2 + { "b99-14.28", 0x020000, 0x71c8b4d7, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b99-08.45", 0x010000, 0x26135451, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b99-02.18", 0x080000, 0x2a5d4a26, TAITO_CHARS }, // 5 Graphics Tiles + { "b99-01.19", 0x080000, 0xa19e373a, TAITO_CHARS }, // 6 + + { "b99-03.37", 0x080000, 0xdda10df7, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(crimec) +STD_ROM_FN(crimec) + +static INT32 CrimecInit() +{ + return CommonInit(CrimecInitCallback, 0, 1, 0, 3, 5); +} + +struct BurnDriver BurnDrvCrimec = { + "crimec", NULL, NULL, NULL, "1989", + "Crime City (World)\0", NULL, "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_PLATFORM, 0, + NULL, crimecRomInfo, crimecRomName, NULL, NULL, CommonInputInfo, CrimecDIPInfo, + CrimecInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Crime City (US) + +static struct BurnRomInfo crimecuRomDesc[] = { + { "b99-07.40", 0x020000, 0x26e886e6, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b99-05.29", 0x020000, 0xff7f9a9d, TAITO_68KROM1_BYTESWAP }, // 1 + { "b99-06.39", 0x020000, 0x1f26aa92, TAITO_68KROM1_BYTESWAP }, // 2 + { "b99-13.28", 0x020000, 0x06cf8441, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b99-08.45", 0x010000, 0x26135451, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b99-02.18", 0x080000, 0x2a5d4a26, TAITO_CHARS }, // 5 Graphics Tiles + { "b99-01.19", 0x080000, 0xa19e373a, TAITO_CHARS }, // 6 + + { "b99-03.37", 0x080000, 0xdda10df7, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(crimecu) +STD_ROM_FN(crimecu) + +struct BurnDriver BurnDrvCrimecu = { + "crimecu", "crimec", NULL, NULL, "1989", + "Crime City (US)\0", NULL, "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_PLATFORM, 0, + NULL, crimecuRomInfo, crimecuRomName, NULL, NULL, CommonInputInfo, CrimecuDIPInfo, + CrimecInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Crime City (Japan) + +static struct BurnRomInfo crimecjRomDesc[] = { + { "b99-07.40", 0x020000, 0x26e886e6, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "b99-05.29", 0x020000, 0xff7f9a9d, TAITO_68KROM1_BYTESWAP }, // 1 + { "b99-06.39", 0x020000, 0x1f26aa92, TAITO_68KROM1_BYTESWAP }, // 2 + { "b99-15.28", 0x020000, 0xe8c1e56d, TAITO_68KROM1_BYTESWAP }, // 3 + + { "b99-08.45", 0x010000, 0x26135451, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b99-02.18", 0x080000, 0x2a5d4a26, TAITO_CHARS }, // 5 Graphics Tiles + { "b99-01.19", 0x080000, 0xa19e373a, TAITO_CHARS }, // 6 + + { "b99-03.37", 0x080000, 0xdda10df7, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(crimecj) +STD_ROM_FN(crimecj) + +struct BurnDriver BurnDrvCrimecj = { + "crimecj", "crimec", NULL, NULL, "1989", + "Crime City (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_PLATFORM, 0, + NULL, crimecjRomInfo, crimecjRomName, NULL, NULL, CommonInputInfo, CrimecjDIPInfo, + CrimecInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Tetris (Japan, B-System, YM2610) + +static struct BurnRomInfo tetristRomDesc[] = { + { "c12-03.bin", 0x020000, 0x38f1ed41, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c12-02.bin", 0x020000, 0xed9530bc, TAITO_68KROM1_BYTESWAP }, // 1 + { "c12-05.bin", 0x020000, 0x128e9927, TAITO_68KROM1_BYTESWAP }, // 2 + { "c12-04.bin", 0x020000, 0x5da7a319, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c12-06.bin", 0x010000, 0xf2814b38, TAITO_Z80ROM1 }, // 4 Z80 Code +}; + +STD_ROM_PICK(tetrist) +STD_ROM_FN(tetrist) + +static INT32 TetristInit() +{ + return CommonInit(TetristInitCallback, 0, 0, 0, 2, 4); +} + +struct BurnDriver BurnDrvTetrist = { + "tetrist", "tetris", NULL, NULL, "1989", + "Tetris (Japan, B-System, YM2610)\0", NULL, "Sega", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_PUZZLE, 0, + NULL, tetristRomInfo, tetristRomName, NULL, NULL, CommonInputInfo, TetristDIPInfo, + TetristInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Tetris (Japan, B-System, YM2203) + +static struct BurnRomInfo tetristaRomDesc[] = { + { "c35-04.bin", 0x020000, 0xfa6e42ff, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c35-03.bin", 0x020000, 0xaebd8539, TAITO_68KROM1_BYTESWAP }, // 1 + { "c35-02.bin", 0x020000, 0x128e9927, TAITO_68KROM1_BYTESWAP }, // 2 + { "c35-01.bin", 0x020000, 0x5da7a319, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c35-05.bin", 0x010000, 0x785c63fb, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "b72-02.rom", 0x080000, 0x843444eb, BRF_OPT }, // 5 Graphics Tiles (not used) + { "b72-01.rom", 0x080000, 0xa24ac26e, BRF_OPT }, // 6 +}; + +STD_ROM_PICK(tetrista) +STD_ROM_FN(tetrista) + +static INT32 TetristaInit() +{ + return CommonInit(TetristaInitCallback, 1, 2, 0, 4, 5); +} + +struct BurnDriver BurnDrvTetrista = { + "tetrista", "tetris", NULL, NULL, "1989", + "Tetris (Japan, B-System, YM2203)\0", NULL, "Sega", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_PUZZLE, 0, + NULL, tetristaRomInfo, tetristaRomName, NULL, NULL, CommonInputInfo, TetristDIPInfo, + TetristaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Violence Fight (World) + +static struct BurnRomInfo viofightRomDesc[] = { + { "c16-11.42", 0x010000, 0x23dbd388, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c16-14.23", 0x010000, 0xdc934f6a, TAITO_68KROM1_BYTESWAP }, // 1 + { "c16-07.41", 0x020000, 0x64d1d059, TAITO_68KROM1_BYTESWAP }, // 2 + { "c16-06.22", 0x020000, 0x043761d8, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c16-12.32", 0x010000, 0x6fb028c7, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c16-01.1", 0x080000, 0x7059ce83, TAITO_CHARS }, // 5 Graphics Tiles + { "c16-02.2", 0x080000, 0xb458e905, TAITO_CHARS }, // 6 + { "c16-03.3", 0x080000, 0x515a9431, TAITO_CHARS }, // 7 + { "c16-04.4", 0x080000, 0xebf285e2, TAITO_CHARS }, // 8 + + { "c16-05.47", 0x080000, 0xa49d064a, TAITO_MSM6295 }, // 9 MSM6295 Samples + + { "pal16l8b-c16-08.ic34", 0x000104, 0x9456d278, BRF_OPT }, // 10 PLDs + { "pal16l8b-c16-09.ic35", 0x000104, 0x0965baab, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(viofight) +STD_ROM_FN(viofight) + +static INT32 ViofightInit() +{ + return CommonInit(ViofightInitCallback, 1, 2, 0, 1, 4); +} + +struct BurnDriver BurnDrvViofight = { + "viofight", NULL, NULL, NULL, "1989", + "Violence Fight (World)\0", NULL, "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_VSFIGHT, 0, + NULL, viofightRomInfo, viofightRomName, NULL, NULL, ViofightInputInfo, ViofightDIPInfo, + ViofightInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Violence Fight (US) + +static struct BurnRomInfo viofightuRomDesc[] = { + { "c16-11.42", 0x010000, 0x23dbd388, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c16-13.23", 0x010000, 0xab947ffc, TAITO_68KROM1_BYTESWAP }, // 1 + { "c16-07.41", 0x020000, 0x64d1d059, TAITO_68KROM1_BYTESWAP }, // 2 + { "c16-06.22", 0x020000, 0x043761d8, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c16-12.32", 0x010000, 0x6fb028c7, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c16-01.1", 0x080000, 0x7059ce83, TAITO_CHARS }, // 5 Graphics Tiles + { "c16-02.2", 0x080000, 0xb458e905, TAITO_CHARS }, // 6 + { "c16-03.3", 0x080000, 0x515a9431, TAITO_CHARS }, // 7 + { "c16-04.4", 0x080000, 0xebf285e2, TAITO_CHARS }, // 8 + + { "c16-05.47", 0x080000, 0xa49d064a, TAITO_MSM6295 }, // 9 MSM6295 Samples + + { "pal16l8b-c16-08.ic34", 0x000104, 0x9456d278, BRF_OPT }, // 10 PLDs + { "pal16l8b-c16-09.ic35", 0x000104, 0x0965baab, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(viofightu) +STD_ROM_FN(viofightu) + +struct BurnDriver BurnDrvViofightu = { + "viofightu", "viofight", NULL, NULL, "1989", + "Violence Fight (US)\0", NULL, "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_VSFIGHT, 0, + NULL, viofightuRomInfo, viofightuRomName, NULL, NULL, ViofightInputInfo, ViofightDIPInfo, + ViofightInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Violence Fight (Japan) + +static struct BurnRomInfo viofightjRomDesc[] = { + { "c16-11.42", 0x010000, 0x23dbd388, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c16-10.23", 0x010000, 0x329d2e46, TAITO_68KROM1_BYTESWAP }, // 1 + { "c16-07.41", 0x020000, 0x64d1d059, TAITO_68KROM1_BYTESWAP }, // 2 + { "c16-06.22", 0x020000, 0x043761d8, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c16-12.32", 0x010000, 0x6fb028c7, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c16-01.1", 0x080000, 0x7059ce83, TAITO_CHARS }, // 5 Graphics Tiles + { "c16-02.2", 0x080000, 0xb458e905, TAITO_CHARS }, // 6 + { "c16-03.3", 0x080000, 0x515a9431, TAITO_CHARS }, // 7 + { "c16-04.4", 0x080000, 0xebf285e2, TAITO_CHARS }, // 8 + + { "c16-05.47", 0x080000, 0xa49d064a, TAITO_MSM6295 }, // 9 MSM6295 Samples + + { "pal16l8b-c16-08.ic34", 0x000104, 0x9456d278, BRF_OPT }, // 10 PLDs + { "pal16l8b-c16-09.ic35", 0x000104, 0x0965baab, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(viofightj) +STD_ROM_FN(viofightj) + +struct BurnDriver BurnDrvViofightj = { + "viofightj", "viofight", NULL, NULL, "1989", + "Violence Fight (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_VSFIGHT, 0, + NULL, viofightjRomInfo, viofightjRomName, NULL, NULL, ViofightInputInfo, ViofightDIPInfo, + ViofightInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Ashura Blaster (World) + +static struct BurnRomInfo ashuraRomDesc[] = { + { "c43-15.50", 0x020000, 0x5d05d6c6, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c43-13.31", 0x020000, 0x75b7d877, TAITO_68KROM1_BYTESWAP }, // 1 + { "c43-14.49", 0x020000, 0xede7f37d, TAITO_68KROM1_BYTESWAP }, // 2 + { "c43-12.30", 0x020000, 0xb08a4ba0, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c43-16", 0x010000, 0xcb26fce1, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c43-02", 0x080000, 0x105722ae, TAITO_CHARS }, // 5 Graphics Tiles + { "c43-03", 0x080000, 0x426606ba, TAITO_CHARS }, // 6 + + { "c43-01", 0x080000, 0xdb953f37, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(ashura) +STD_ROM_FN(ashura) + +struct BurnDriver BurnDrvAshura = { + "ashura", NULL, NULL, NULL, "1990", + "Ashura Blaster (World)\0", NULL, "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, ashuraRomInfo, ashuraRomName, NULL, NULL, CommonInputInfo, AshuraDIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Ashura Blaster (Japan) + +static struct BurnRomInfo ashurajRomDesc[] = { + { "c43-07-1.50", 0x020000, 0xd5ceb20f, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c43-05-1.31", 0x020000, 0xa6f3bb37, TAITO_68KROM1_BYTESWAP }, // 1 + { "c43-06-1.49", 0x020000, 0x0f331802, TAITO_68KROM1_BYTESWAP }, // 2 + { "c43-04-1.30", 0x020000, 0xe06a2414, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c43-16", 0x010000, 0xcb26fce1, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c43-02", 0x080000, 0x105722ae, TAITO_CHARS }, // 5 Graphics Tiles + { "c43-03", 0x080000, 0x426606ba, TAITO_CHARS }, // 6 + + { "c43-01", 0x080000, 0xdb953f37, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(ashuraj) +STD_ROM_FN(ashuraj) + +struct BurnDriver BurnDrvAshuraj = { + "ashuraj", "ashura", NULL, NULL, "1990", + "Ashura Blaster (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, ashurajRomInfo, ashurajRomName, NULL, NULL, CommonInputInfo, AshurajDIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Ashura Blaster (US) + +static struct BurnRomInfo ashurauRomDesc[] = { + { "c43-11.50", 0x020000, 0xd5aefc9b, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c43-09.31", 0x020000, 0xe91d0ab1, TAITO_68KROM1_BYTESWAP }, // 1 + { "c43-10.49", 0x020000, 0xc218e7ea, TAITO_68KROM1_BYTESWAP }, // 2 + { "c43-08.30", 0x020000, 0x5ef4f19f, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c43-16", 0x010000, 0xcb26fce1, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c43-02", 0x080000, 0x105722ae, TAITO_CHARS }, // 5 Graphics Tiles + { "c43-03", 0x080000, 0x426606ba, TAITO_CHARS }, // 6 + + { "c43-01", 0x080000, 0xdb953f37, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(ashurau) +STD_ROM_FN(ashurau) + +struct BurnDriver BurnDrvAshurau = { + "ashurau", "ashura", NULL, NULL, "1990", + "Ashura Blaster (US)\0", NULL, "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, ashurauRomInfo, ashurauRomName, NULL, NULL, CommonInputInfo, AshurauDIPInfo, + NastarInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Hit the Ice (US) + +static struct BurnRomInfo hiticeRomDesc[] = { + { "c59-10.42", 0x020000, 0xe4ffad15, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c59-12.64", 0x020000, 0xa080d7af, TAITO_68KROM1_BYTESWAP }, // 1 + { "c59-09.41", 0x010000, 0xe243e3b0, TAITO_68KROM1_BYTESWAP }, // 2 + { "c59-11.63", 0x010000, 0x4d4dfa52, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c59-08.50", 0x010000, 0xd3cbc10b, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c59-03.12", 0x080000, 0x9e513048, TAITO_CHARS }, // 5 Graphics Tiles + { "c59-02.13", 0x080000, 0xaffb5e07, TAITO_CHARS }, // 6 + + { "c59-01.30", 0x020000, 0x46ae291d, TAITO_MSM6295 }, // 7 MSM6295 Samples + + { "pal20l8b-c59-04.25", 0x000144, 0x2ebcf07c, BRF_OPT }, // 8 PLDs + { "pal16l8b-c59-05.26", 0x000104, 0x37b67c5c, BRF_OPT }, // 9 + { "pal20l8b-c59-06.53", 0x000144, 0xbf176875, BRF_OPT }, // 10 + { "pal16r4b-c59-07.61", 0x000104, 0xcf64bd95, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(hitice) +STD_ROM_FN(hitice) + +static INT32 HiticeInit() +{ + return CommonInit(HiticeInitCallback, 1, 0, 1, 6, 4); +} + +struct BurnDriver BurnDrvHitice = { + "hitice", NULL, NULL, NULL, "1990", + "Hit the Ice (US)\0", "Imperfect graphics", "Williams", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_SPORTSMISC, 0, + NULL, hiticeRomInfo, hiticeRomName, NULL, NULL, HiticeInputInfo, HiticeDIPInfo, + HiticeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Hit the Ice (Japan) + +static struct BurnRomInfo hiticejRomDesc[] = { + { "c59-23.42", 0x020000, 0x01958fcc, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c59-25.64", 0x020000, 0x71984c76, TAITO_68KROM1_BYTESWAP }, // 1 + { "c59-22.41", 0x010000, 0xc2c86140, TAITO_68KROM1_BYTESWAP }, // 2 + { "c59-24.63", 0x010000, 0x26c8f409, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c59-08.50", 0x010000, 0xd3cbc10b, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "c59-03.12", 0x080000, 0x9e513048, TAITO_CHARS }, // 5 Graphics Tiles + { "c59-02.13", 0x080000, 0xaffb5e07, TAITO_CHARS }, // 6 + + { "c59-01.30", 0x020000, 0x46ae291d, TAITO_MSM6295 }, // 7 MSM6295 Samples + + { "pal20l8b-c59-04.25", 0x000144, 0x2ebcf07c, BRF_OPT }, // 8 PLDs + { "pal16l8b-c59-05.26", 0x000104, 0x37b67c5c, BRF_OPT }, // 9 + { "pal20l8b-c59-06.53", 0x000144, 0xbf176875, BRF_OPT }, // 10 + { "pal16r4b-c59-07.61", 0x000104, 0xcf64bd95, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(hiticej) +STD_ROM_FN(hiticej) + +struct BurnDriver BurnDrvHiticej = { + "hiticej", "hitice", NULL, NULL, "1990", + "Hit the Ice (Japan)\0", "Imperfect graphics", "Midway/Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SPORTSMISC, 0, + NULL, hiticejRomInfo, hiticejRomName, NULL, NULL, HiticeInputInfo, HiticeDIPInfo, + HiticeInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Sel Feena + +static struct BurnRomInfo selfeenaRomDesc[] = { + { "se-02.27", 0x020000, 0x08f0c8e3, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "se-01.26", 0x020000, 0xa06ca64b, TAITO_68KROM1_BYTESWAP }, // 1 + + { "se-03.39", 0x010000, 0x675998be, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "se-04.2", 0x080000, 0x920ad100, TAITO_CHARS }, // 3 Graphics Tiles + { "se-05.1", 0x080000, 0xd297c995, TAITO_CHARS }, // 4 + + { "se-06.11", 0x080000, 0x80d5e772, TAITO_YM2610A }, // 5 YM2610 A Samples +}; + +STD_ROM_PICK(selfeena) +STD_ROM_FN(selfeena) + +static INT32 SelfeenaInit() +{ + return CommonInit(SelfeenaInitCallback, 0, 2, 1, 4, 6); +} + +struct BurnDriver BurnDrvSelfeena = { + "selfeena", NULL, NULL, NULL, "1991", + "Sel Feena\0", NULL, "East Technology", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_MAZE, 0, + NULL, selfeenaRomInfo, selfeenaRomName, NULL, NULL, SelfeenaInputInfo, SelfeenaDIPInfo, + SelfeenaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Silent Dragon (World) + +static struct BurnRomInfo silentdRomDesc[] = { + { "east-12-1.ic32", 0x020000, 0x5883d362, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "east-15-1.ic10", 0x020000, 0x8c0a72ae, TAITO_68KROM1_BYTESWAP }, // 1 + { "east-11.ic31", 0x020000, 0x35da4428, TAITO_68KROM1_BYTESWAP }, // 2 + { "east-09.ic9", 0x020000, 0x2f05b14a, TAITO_68KROM1_BYTESWAP }, // 3 + + { "east-13.ic15", 0x010000, 0x651861ab, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "east-04.ic28", 0x100000, 0x53237217, TAITO_CHARS }, // 5 Graphics Tiles + { "east-06.ic29", 0x100000, 0xe6e6dfa7, TAITO_CHARS }, // 6 + { "east-03.ic39", 0x100000, 0x1b9b2846, TAITO_CHARS }, // 7 + { "east-05.ic40", 0x100000, 0xe02472c5, TAITO_CHARS }, // 8 + + { "east-01.ic1", 0x080000, 0xb41fff1a, TAITO_YM2610A }, // 9 YM2610 A Samples + + { "east-02.ic3", 0x080000, 0xe0de5c39, TAITO_YM2610B }, // 10 YM2610 B Samples +}; + +STD_ROM_PICK(silentd) +STD_ROM_FN(silentd) + +static INT32 SilentdInit() +{ + INT32 nRet = CommonInit(SilentdInitCallback, 0, 2, 2, 4, 6); + + if (nRet == 0) { + cpu_speed[0] = 16000000; // 16mhz + } + + return nRet; +} + +struct BurnDriver BurnDrvSilentd = { + "silentd", NULL, NULL, NULL, "1992", + "Silent Dragon (World)\0", NULL, "Taito Corporation Japan", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, silentdRomInfo, silentdRomName, NULL, NULL, SilentdInputInfo, SilentdDIPInfo, + SilentdInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Silent Dragon (Japan) + +static struct BurnRomInfo silentdjRomDesc[] = { + { "east-12-1.ic32", 0x020000, 0x5883d362, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "east-10-1.ic10", 0x020000, 0x584306fc, TAITO_68KROM1_BYTESWAP }, // 1 + { "east-11.ic31", 0x020000, 0x35da4428, TAITO_68KROM1_BYTESWAP }, // 2 + { "east-09.ic9", 0x020000, 0x2f05b14a, TAITO_68KROM1_BYTESWAP }, // 3 + + { "east-13.ic15", 0x010000, 0x651861ab, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "east-04.ic28", 0x100000, 0x53237217, TAITO_CHARS }, // 5 Graphics Tiles + { "east-06.ic29", 0x100000, 0xe6e6dfa7, TAITO_CHARS }, // 6 + { "east-03.ic39", 0x100000, 0x1b9b2846, TAITO_CHARS }, // 7 + { "east-05.ic40", 0x100000, 0xe02472c5, TAITO_CHARS }, // 8 + + { "east-01.ic1", 0x080000, 0xb41fff1a, TAITO_YM2610A }, // 9 YM2610 A Samples + + { "east-02.ic3", 0x080000, 0xe0de5c39, TAITO_YM2610B }, // 10 YM2610 B Samples +}; + +STD_ROM_PICK(silentdj) +STD_ROM_FN(silentdj) + +struct BurnDriver BurnDrvSilentdj = { + "silentdj", "silentd", NULL, NULL, "1992", + "Silent Dragon (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, silentdjRomInfo, silentdjRomName, NULL, NULL, SilentdInputInfo, SilentdjDIPInfo, + SilentdInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Silent Dragon (US) + +static struct BurnRomInfo silentduRomDesc[] = { + { "east-12-1.ic32", 0x020000, 0x5883d362, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "east-14-1.ic10", 0x020000, 0x3267bcd5, TAITO_68KROM1_BYTESWAP }, // 1 + { "east-11.ic31", 0x020000, 0x35da4428, TAITO_68KROM1_BYTESWAP }, // 2 + { "east-09.ic9", 0x020000, 0x2f05b14a, TAITO_68KROM1_BYTESWAP }, // 3 + + { "east-13.ic15", 0x010000, 0x651861ab, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "east-04.ic28", 0x100000, 0x53237217, TAITO_CHARS }, // 5 Graphics Tiles + { "east-06.ic29", 0x100000, 0xe6e6dfa7, TAITO_CHARS }, // 6 + { "east-03.ic39", 0x100000, 0x1b9b2846, TAITO_CHARS }, // 7 + { "east-05.ic40", 0x100000, 0xe02472c5, TAITO_CHARS }, // 8 + + { "east-01.ic1", 0x080000, 0xb41fff1a, TAITO_YM2610A }, // 9 YM2610 A Samples + + { "east-02.ic3", 0x080000, 0xe0de5c39, TAITO_YM2610B }, // 10 YM2610 B Samples +}; + +STD_ROM_PICK(silentdu) +STD_ROM_FN(silentdu) + +struct BurnDriver BurnDrvSilentdu = { + "silentdu", "silentd", NULL, NULL, "1992", + "Silent Dragon (US)\0", NULL, "Taito America Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_SCRFIGHT, 0, + NULL, silentduRomInfo, silentduRomName, NULL, NULL, SilentdInputInfo, SilentdjDIPInfo, + SilentdInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Ryu Jin (Japan) + +static struct BurnRomInfo ryujinRomDesc[] = { + { "ruj02.27", 0x020000, 0x0d223aee, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "ruj01.26", 0x020000, 0xc6bcdd1e, TAITO_68KROM1_BYTESWAP }, // 1 + { "ruj04.29", 0x020000, 0x0c153cab, TAITO_68KROM1_BYTESWAP }, // 2 + { "ruj03.28", 0x020000, 0x7695f89c, TAITO_68KROM1_BYTESWAP }, // 3 + + { "ruj05.39", 0x010000, 0x95270b16, TAITO_Z80ROM1 }, // 4 Z80 Code + + { "ryujin07.2", 0x100000, 0x34f50980, TAITO_CHARS }, // 5 Graphics Tiles + { "ryujin06.1", 0x100000, 0x1b85ff34, TAITO_CHARS }, // 6 + + { "ryujin08.11", 0x080000, 0x480d040d, TAITO_YM2610A }, // 7 YM2610 A Samples +}; + +STD_ROM_PICK(ryujin) +STD_ROM_FN(ryujin) + +struct BurnDriver BurnDrvRyujin = { + "ryujin", NULL, NULL, NULL, "1993", + "Ryu Jin (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOB, GBF_VERSHOOT, 0, + NULL, ryujinRomInfo, ryujinRomName, NULL, NULL, SelfeenaInputInfo, RyujinDIPInfo, + SelfeenaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 224, 320, 3, 4 +}; + + +// Quiz Sekai wa SHOW by shobai (Japan) + +static struct BurnRomInfo qzshowbyRomDesc[] = { + { "d72-13.bin", 0x080000, 0xa867759f, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "d72-12.bin", 0x080000, 0x522c09a7, TAITO_68KROM1_BYTESWAP }, // 1 + + { "d72-11.bin", 0x020000, 0x2ca046e2, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "d72-03.bin", 0x200000, 0x1de257d0, TAITO_CHARS }, // 3 Graphics Tiles + { "d72-02.bin", 0x200000, 0xbf0da640, TAITO_CHARS }, // 4 + + { "d72-01.bin", 0x200000, 0xb82b8830, TAITO_YM2610A }, // 5 YM2610 A Samples + + { "pal16l8-d72-05.bin", 0x0104, 0xc3d4cb7e, BRF_OPT }, // 6 PLDs + { "pal16l8-d72-06.bin", 0x0104, 0x27580efc, BRF_OPT }, // 7 + { "palce20v8-d72-07.bin", 0x0157, 0x6359e64c, BRF_OPT }, // 8 + { "palce20v8-d72-08.bin", 0x0157, 0x746a6474, BRF_OPT }, // 9 + { "palce20v8-d72-09.bin", 0x0157, 0x9f680800, BRF_OPT }, // 10 + { "palce16v8-d72-10.bin", 0x0117, 0xa5181ba2, BRF_OPT }, // 11 +}; + +STD_ROM_PICK(qzshowby) +STD_ROM_FN(qzshowby) + +static INT32 QzshowbyInit() +{ + return CommonInit(QzshowbyInitCallback, 0, 1, 3, 5, 3); +} + +struct BurnDriver BurnDrvQzshowby = { + "qzshowby", NULL, NULL, NULL, "1993", + "Quiz Sekai wa SHOW by shobai (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_QUIZ, 0, + NULL, qzshowbyRomInfo, qzshowbyRomName, NULL, NULL, QzshowbyInputInfo, QzshowbyDIPInfo, + QzshowbyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Puzzle Bobble (Japan, B-System) + +static struct BurnRomInfo pbobbleRomDesc[] = { + { "pb-1c18.bin", 0x040000, 0x5de14f49, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "pb-ic2.bin", 0x040000, 0x2abe07d1, TAITO_68KROM1_BYTESWAP }, // 1 + + { "pb-ic27.bin", 0x020000, 0x26efa4c4, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "pb-ic14.bin", 0x080000, 0x55f90ea4, TAITO_CHARS }, // 3 Graphics Tiles + { "pb-ic9.bin", 0x080000, 0x3253aac9, TAITO_CHARS }, // 4 + + { "pb-ic15.bin", 0x100000, 0x0840cbc4, TAITO_YM2610A }, // 5 YM2610 A Samples +}; + +STD_ROM_PICK(pbobble) +STD_ROM_FN(pbobble) + +static INT32 PbobbleInit() +{ + return CommonInit(PbobbleInitCallback, 0, 1, 3, 5, 3); +} + +struct BurnDriver BurnDrvPbobble = { + "pbobble", NULL, NULL, NULL, "1994", + "Puzzle Bobble (Japan, B-System)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, pbobbleRomInfo, pbobbleRomName, NULL, NULL, PbobbleInputInfo, PbobbleDIPInfo, + PbobbleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Space Invaders DX (US, v2.1) + +static struct BurnRomInfo spacedxRomDesc[] = { + { "d89-06", 0x040000, 0x7122751e, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "d89-xx.ic2", 0x040000, 0x56b0be6c, TAITO_68KROM1_BYTESWAP }, // 1 + + { "d89-07.27", 0x010000, 0xbd743401, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "d89-02.14", 0x080000, 0xc36544b9, TAITO_CHARS }, // 3 Graphics Tiles + { "d89-01.9", 0x080000, 0xfffa0660, TAITO_CHARS }, // 4 + + { "d89-03.15", 0x080000, 0x218f31a4, TAITO_YM2610A }, // 5 YM2610 A Samples + + { "pal16l8-d72-05.ic37", 0x0104, 0xc3d4cb7e, BRF_OPT }, // 6 PLDs + { "pal16l8-d72-06.ic50", 0x0104, 0xe96b7f37, BRF_OPT }, // 7 + { "palce20v8-d72-07.ic28", 0x0157, 0x6359e64c, BRF_OPT }, // 8 + { "palce20v8-d72-09.ic47", 0x0157, 0xde1760fd, BRF_OPT }, // 9 + { "palce16v8-d72-10.ic12", 0x0117, 0xa5181ba2, BRF_OPT }, // 10 + { "pal20l8b-d89-04.ic40", 0x0144, 0x00000000, BRF_OPT | BRF_NODUMP }, // 12 +}; + +STD_ROM_PICK(spacedx) +STD_ROM_FN(spacedx) + +struct BurnDriver BurnDrvSpacedx = { + "spacedx", NULL, NULL, NULL, "1994", + "Space Invaders DX (US, v2.1)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, spacedxRomInfo, spacedxRomName, NULL, NULL, PbobbleInputInfo, PbobbleDIPInfo, + PbobbleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Space Invaders DX (Japan, v2.1) + +static struct BurnRomInfo spacedxjRomDesc[] = { + { "d89-06", 0x040000, 0x7122751e, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "d89-05", 0x040000, 0xbe1638af, TAITO_68KROM1_BYTESWAP }, // 1 + + { "d89-07.27", 0x010000, 0xbd743401, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "d89-02.14", 0x080000, 0xc36544b9, TAITO_CHARS }, // 3 Graphics Tiles + { "d89-01.9", 0x080000, 0xfffa0660, TAITO_CHARS }, // 4 + + { "d89-03.15", 0x080000, 0x218f31a4, TAITO_YM2610A }, // 5 YM2610 A Samples + + { "pal16l8-d72-05.ic37", 0x0104, 0xc3d4cb7e, BRF_OPT }, // 6 PLDs + { "pal16l8-d72-06.ic50", 0x0104, 0xe96b7f37, BRF_OPT }, // 7 + { "palce20v8-d72-07.ic28", 0x0157, 0x6359e64c, BRF_OPT }, // 8 + { "palce20v8-d72-09.ic47", 0x0157, 0xde1760fd, BRF_OPT }, // 9 + { "palce16v8-d72-10.ic12", 0x0117, 0xa5181ba2, BRF_OPT }, // 10 + { "pal20l8b-d89-04.ic40", 0x0144, 0x00000000, BRF_OPT | BRF_NODUMP }, // 12 +}; + +STD_ROM_PICK(spacedxj) +STD_ROM_FN(spacedxj) + +struct BurnDriver BurnDrvSpacedxj = { + "spacedxj", "spacedx", NULL, NULL, "1994", + "Space Invaders DX (Japan, v2.1)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, spacedxjRomInfo, spacedxjRomName, NULL, NULL, PbobbleInputInfo, PbobbleDIPInfo, + PbobbleInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Space Invaders DX (Japan, v2.0) + +static struct BurnRomInfo spacedxoRomDesc[] = { + { "d89-08.bin", 0x020000, 0x0c2fe7f9, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "d89-09.bin", 0x020000, 0x7f0a0ba4, TAITO_68KROM1_BYTESWAP }, // 1 + + { "d89-07.27", 0x010000, 0xbd743401, TAITO_Z80ROM1 }, // 2 Z80 Code + + { "d89-12.bin", 0x080000, 0x53df86f1, TAITO_CHARS }, // 3 Graphics Tiles + { "d89-13.bin", 0x080000, 0xc44c1352, TAITO_CHARS }, // 4 + + { "d89-03.15", 0x080000, 0x218f31a4, TAITO_YM2610A }, // 5 YM2610 A Samples +}; + +STD_ROM_PICK(spacedxo) +STD_ROM_FN(spacedxo) + +static INT32 SpacedxoInit() +{ + return CommonInit(SilentdInitCallback, 0, 2, 3, 4, 6); +} + +struct BurnDriver BurnDrvSpacedxo = { + "spacedxo", "spacedx", NULL, NULL, "1994", + "Space Invaders DX (Japan, v2.0)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, spacedxoRomInfo, spacedxoRomName, NULL, NULL, SpacedxoInputInfo, SpacedxoDIPInfo, + SpacedxoInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; + + +// Sonic Blast Man (Japan) + +static struct BurnRomInfo sbmRomDesc[] = { + { "c69-20-1.10", 0x020000, 0xb40e4910, TAITO_68KROM1_BYTESWAP }, // 0 68k Code + { "c69-22-1.12", 0x020000, 0xecbcf830, TAITO_68KROM1_BYTESWAP }, // 1 + { "c69-19-1.9", 0x020000, 0x5719c158, TAITO_68KROM1_BYTESWAP }, // 2 + { "c69-21-1.11", 0x020000, 0x73562394, TAITO_68KROM1_BYTESWAP }, // 3 + + { "c69-23.28", 0x010000, 0xb2fce13e, TAITO_Z80ROM1 }, // 4 Z80 Code + + // Some roms are repeated to compensate for the way the taito rom loading system in fba works. + { "c69-01.ic5", 0x100000, 0x521fabe3, TAITO_CHARS }, // 5 Graphics Tiles + { "c69-13.ic2", 0x020000, 0xd1550884, TAITO_CHARS_BYTESWAP }, // 6 + { "c69-12.ic1", 0x020000, 0xeb56582c, TAITO_CHARS_BYTESWAP }, // 7 + { "c69-13.ic2", 0x020000, 0xd1550884, TAITO_CHARS_BYTESWAP }, // 8 + { "c69-12.ic1", 0x020000, 0xeb56582c, TAITO_CHARS_BYTESWAP }, // 9 + { "c69-13.ic2", 0x020000, 0xd1550884, TAITO_CHARS_BYTESWAP }, // 10 + { "c69-12.ic1", 0x020000, 0xeb56582c, TAITO_CHARS_BYTESWAP }, // 11 + { "c69-13.ic2", 0x020000, 0xd1550884, TAITO_CHARS_BYTESWAP }, // 12 + { "c69-12.ic1", 0x020000, 0xeb56582c, TAITO_CHARS_BYTESWAP }, // 13 + { "c69-02.ic6", 0x100000, 0xf0e20d35, TAITO_CHARS }, // 14 + { "c69-15.ic4", 0x020000, 0x9761d316, TAITO_CHARS_BYTESWAP }, // 15 + { "c69-14.ic3", 0x020000, 0x0ed0272a, TAITO_CHARS_BYTESWAP }, // 16 + { "c69-15.ic4", 0x020000, 0x9761d316, TAITO_CHARS_BYTESWAP }, // 17 + { "c69-14.ic3", 0x020000, 0x0ed0272a, TAITO_CHARS_BYTESWAP }, // 18 + { "c69-15.ic4", 0x020000, 0x9761d316, TAITO_CHARS_BYTESWAP }, // 19 + { "c69-14.ic3", 0x020000, 0x0ed0272a, TAITO_CHARS_BYTESWAP }, // 20 + { "c69-15.ic4", 0x020000, 0x9761d316, TAITO_CHARS_BYTESWAP }, // 21 + { "c69-14.ic3", 0x020000, 0x0ed0272a, TAITO_CHARS_BYTESWAP }, // 22 + + { "c69-03.36", 0x080000, 0x63e6b6e7, TAITO_YM2610A }, // 23 ymsnd +}; + +STD_ROM_PICK(sbm) +STD_ROM_FN(sbm) + +static INT32 SbmInit() +{ + nTaitoInputConfig[2] = 0x60; + + return CommonInit(SbmInitCallback, 0, 0, 0, 5, 4); +} + +struct BurnDriver BurnDrvSbm = { + "sbm", NULL, NULL, NULL, "1990", + "Sonic Blast Man (Japan)\0", NULL, "Taito Corporation", "Taito B System", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOB, GBF_MISC, 0, + NULL, sbmRomInfo, sbmRomName, NULL, NULL, SbmInputInfo, SbmDIPInfo, + SbmInit, DrvExit, DrvFrame, DrvDraw, DrvScan, NULL, 0x1000, + 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_taitof2.cpp b/src/burn/drivers/taito/d_taitof2.cpp new file mode 100644 index 00000000..b27c03be --- /dev/null +++ b/src/burn/drivers/taito/d_taitof2.cpp @@ -0,0 +1,11259 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" +#include "burn_ym2203.h" +#include "msm6295.h" + +static INT32 Footchmp; +static INT32 YesnoDip; +static INT32 MjnquestInput; +static INT32 DriveoutSoundNibble; +static INT32 DriveoutOkiBank; + +INT32 TaitoF2SpriteType; +INT32 TaitoF2SpritesFlipScreen; +INT32 TaitoF2PrepareSprites; +INT32 TaitoF2SpritesDisabled, TaitoF2SpritesActiveArea, TaitoF2SpritesMasterScrollX, TaitoF2SpritesMasterScrollY; +INT32 TaitoF2SpriteBlendMode; +UINT16 TaitoF2SpriteBank[8]; +UINT16 TaitoF2SpriteBankBuffered[8]; +UINT8 TaitoF2TilePriority[5]; +UINT8 TaitoF2SpritePriority[4]; +struct TaitoF2SpriteEntry *TaitoF2SpriteList; +static TaitoF2SpriteBufferUpdate TaitoF2SpriteBufferFunction; + +static void TaitoF2Draw(); +static void TaitoF2PivotDraw(); +static void CameltryDraw(); +static void DriftoutDraw(); +static void FinalbDraw(); +static void FootchmpDraw(); +static void MetalbDraw(); +static void PulirulaDraw(); +static void QtorimonDraw(); +static void QzquestDraw(); +static void SsiDraw(); +static void ThundfoxDraw(); +static void YuyugogoDraw(); + +static bool bUseAsm68KCoreOldValue = false; + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo CameltryInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + A("P1 Paddle" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + + A("P2 Paddle" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "p2 x-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Cameltry) + +static struct BurnInputInfo DeadconxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , TaitoInputPort2 + 5, "service 2" }, + {"Service 3" , BIT_DIGITAL , TaitoInputPort2 + 6, "service 3" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 7, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Deadconx) + +static struct BurnInputInfo DinorexInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Dinorex) + +static struct BurnInputInfo DondokodInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Dondokod) + +static struct BurnInputInfo DriftoutInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Driftout) + +static struct BurnInputInfo FinalbInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0220IOCInputPort2 + 4, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0220IOCInputPort2 + 5, "p1 fire 5" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Finalb) + +static struct BurnInputInfo FootchmpInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , TaitoInputPort2 + 2, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , TaitoInputPort3 + 7, "p3 start" }, + {"Coin 4" , BIT_DIGITAL , TaitoInputPort2 + 3, "p4 coin" }, + {"Start 4" , BIT_DIGITAL , TaitoInputPort4 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , TaitoInputPort3 + 0, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , TaitoInputPort3 + 1, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , TaitoInputPort3 + 2, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , TaitoInputPort3 + 3, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , TaitoInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , TaitoInputPort3 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , TaitoInputPort4 + 0, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , TaitoInputPort4 + 1, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , TaitoInputPort4 + 2, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , TaitoInputPort4 + 3, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , TaitoInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , TaitoInputPort4 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 4, "service" }, + {"Service 2" , BIT_DIGITAL , TaitoInputPort2 + 5, "service 2" }, + {"Service 3" , BIT_DIGITAL , TaitoInputPort2 + 6, "service 3" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 7, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Footchmp) + +static struct BurnInputInfo GrowlInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , TaitoInputPort5 + 0, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , TaitoInputPort3 + 7, "p3 start" }, + {"Coin 4" , BIT_DIGITAL , TaitoInputPort5 + 1, "p4 coin" }, + {"Start 4" , BIT_DIGITAL , TaitoInputPort4 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TaitoInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TaitoInputPort1 + 6, "p2 fire 3" }, + + {"P3 Up" , BIT_DIGITAL , TaitoInputPort3 + 0, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , TaitoInputPort3 + 1, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , TaitoInputPort3 + 2, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , TaitoInputPort3 + 3, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , TaitoInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , TaitoInputPort3 + 5, "p3 fire 2" }, + {"P3 Fire 3" , BIT_DIGITAL , TaitoInputPort3 + 6, "p3 fire 3" }, + + {"P4 Up" , BIT_DIGITAL , TaitoInputPort4 + 0, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , TaitoInputPort4 + 1, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , TaitoInputPort4 + 2, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , TaitoInputPort4 + 3, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , TaitoInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , TaitoInputPort4 + 5, "p4 fire 2" }, + {"P4 Fire 3" , BIT_DIGITAL , TaitoInputPort4 + 6, "p4 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 1, "service" }, + {"Service 2" , BIT_DIGITAL , TaitoInputPort5 + 2, "service 2" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Growl) + +static struct BurnInputInfo GunfrontInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Gunfront) + +static struct BurnInputInfo KoshienInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort2 + 4, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort2 + 5, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort2 + 6, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort2 + 7, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Koshien) + +static struct BurnInputInfo LiquidkInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Liquidk) + +static struct BurnInputInfo MegablstInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Megablst) + +static struct BurnInputInfo MetalbInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Metalb) + +static struct BurnInputInfo MjnquestInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort5 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort4 + 1, "p2 coin" }, + + {"Mahjong A" , BIT_DIGITAL , TaitoInputPort0 + 0, "mah a" }, + {"Mahjong B" , BIT_DIGITAL , TaitoInputPort1 + 0, "mah b" }, + {"Mahjong C" , BIT_DIGITAL , TaitoInputPort2 + 0, "mah c" }, + {"Mahjong D" , BIT_DIGITAL , TaitoInputPort3 + 0, "mah d" }, + {"Mahjong E" , BIT_DIGITAL , TaitoInputPort0 + 1, "mah e" }, + {"Mahjong F" , BIT_DIGITAL , TaitoInputPort1 + 1, "mah f" }, + {"Mahjong G" , BIT_DIGITAL , TaitoInputPort2 + 1, "mah g" }, + {"Mahjong H" , BIT_DIGITAL , TaitoInputPort3 + 1, "mah h" }, + {"Mahjong I" , BIT_DIGITAL , TaitoInputPort0 + 2, "mah i" }, + {"Mahjong J" , BIT_DIGITAL , TaitoInputPort1 + 2, "mah j" }, + {"Mahjong K" , BIT_DIGITAL , TaitoInputPort2 + 2, "mah k" }, + {"Mahjong L" , BIT_DIGITAL , TaitoInputPort3 + 2, "mah l" }, + {"Mahjong M" , BIT_DIGITAL , TaitoInputPort0 + 3, "mah m" }, + {"Mahjong N" , BIT_DIGITAL , TaitoInputPort1 + 3, "mah n" }, + {"Mahjong Kan" , BIT_DIGITAL , TaitoInputPort0 + 4, "mah kan" }, + {"Mahjong Pon" , BIT_DIGITAL , TaitoInputPort3 + 3, "mah pon" }, + {"Mahjong Chi" , BIT_DIGITAL , TaitoInputPort2 + 3, "mah chi" }, + {"Mahjong Reach" , BIT_DIGITAL , TaitoInputPort1 + 4, "mah reach" }, + {"Mahjong Ron" , BIT_DIGITAL , TaitoInputPort2 + 4, "mah ron" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort5 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort4 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Mjnquest) + +static struct BurnInputInfo NinjakInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 4, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 5, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + {"Coin 3" , BIT_DIGITAL , TaitoInputPort2 + 6, "p3 coin" }, + {"Start 3" , BIT_DIGITAL , TaitoInputPort3 + 7, "p3 start" }, + {"Coin 4" , BIT_DIGITAL , TaitoInputPort2 + 7, "p4 coin" }, + {"Start 4" , BIT_DIGITAL , TaitoInputPort4 + 7, "p4 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + + {"P3 Up" , BIT_DIGITAL , TaitoInputPort3 + 0, "p3 up" }, + {"P3 Down" , BIT_DIGITAL , TaitoInputPort3 + 1, "p3 down" }, + {"P3 Left" , BIT_DIGITAL , TaitoInputPort3 + 2, "p3 left" }, + {"P3 Right" , BIT_DIGITAL , TaitoInputPort3 + 3, "p3 right" }, + {"P3 Fire 1" , BIT_DIGITAL , TaitoInputPort3 + 4, "p3 fire 1" }, + {"P3 Fire 2" , BIT_DIGITAL , TaitoInputPort3 + 5, "p3 fire 2" }, + + {"P4 Up" , BIT_DIGITAL , TaitoInputPort4 + 0, "p4 up" }, + {"P4 Down" , BIT_DIGITAL , TaitoInputPort4 + 1, "p4 down" }, + {"P4 Left" , BIT_DIGITAL , TaitoInputPort4 + 2, "p4 left" }, + {"P4 Right" , BIT_DIGITAL , TaitoInputPort4 + 3, "p4 right" }, + {"P4 Fire 1" , BIT_DIGITAL , TaitoInputPort4 + 4, "p4 fire 1" }, + {"P4 Fire 2" , BIT_DIGITAL , TaitoInputPort4 + 5, "p4 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 1, "service" }, + {"Service 2" , BIT_DIGITAL , TaitoInputPort2 + 2, "service 2" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Ninjak) + +static struct BurnInputInfo PulirulaInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Pulirula) + +static struct BurnInputInfo QcrayonInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Qcrayon) + +static struct BurnInputInfo Qcrayon2InputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Qcrayon2) + +static struct BurnInputInfo QjinseiInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Qjinsei) + +static struct BurnInputInfo QtorimonInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 fire 4" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 fire 4" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Qtorimon) + +static struct BurnInputInfo QuizhqInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Quizhq) + +static struct BurnInputInfo QzchikyuInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Qzchikyu) + +static struct BurnInputInfo QzquestInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Qzquest) + +static struct BurnInputInfo SolfigtrInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TaitoInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TaitoInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Solfigtr) + +static struct BurnInputInfo SsiInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Ssi) + +static struct BurnInputInfo ThundfoxInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 fire 3" }, + + {"P2 Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Thundfox) + +static struct BurnInputInfo YesnojInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort1 + 2, "p1 coin" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 coin" }, + + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 fire 2" }, + + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 2, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 3, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort1 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort1 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Yesnoj) + +static struct BurnInputInfo YuyugogoInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort2 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort2 + 3, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 7, "p2 start" }, + + {"P1 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 0, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "p1 fire 5" }, + + {"P2 Fire 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p2 fire 3" }, + {"P2 Fire 4" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p2 fire 4" }, + {"P2 Fire 5" , BIT_DIGITAL , TC0510NIOInputPort1 + 4, "p2 fire 5" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort2 + 1, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Yuyugogo) + +#undef A + +static void TC0220IOCMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TC0220IOCInput[0] -= (TC0220IOCInputPort0[i] & 1) << i; + TC0220IOCInput[1] -= (TC0220IOCInputPort1[i] & 1) << i; + TC0220IOCInput[2] -= (TC0220IOCInputPort2[i] & 1) << i; + } +} + +static void TC0510NIOMakeInputs() +{ + // Reset Inputs + TC0510NIOInput[0] = 0xff; + TC0510NIOInput[1] = 0xff; + TC0510NIOInput[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TC0510NIOInput[0] -= (TC0510NIOInputPort0[i] & 1) << i; + TC0510NIOInput[1] -= (TC0510NIOInputPort1[i] & 1) << i; + TC0510NIOInput[2] -= (TC0510NIOInputPort2[i] & 1) << i; + } +} + +static void TaitoF2MakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + TaitoInput[4] = 0xff; + TaitoInput[5] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TaitoInput[0] -= (TaitoInputPort0[i] & 1) << i; + TaitoInput[1] -= (TaitoInputPort1[i] & 1) << i; + TaitoInput[2] -= (TaitoInputPort2[i] & 1) << i; + TaitoInput[3] -= (TaitoInputPort3[i] & 1) << i; + TaitoInput[4] -= (TaitoInputPort4[i] & 1) << i; + TaitoInput[5] -= (TaitoInputPort5[i] & 1) << i; + } +} + +static struct BurnDIPInfo CameltryDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + {0x0b, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x0b, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Medium" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Start remain time" }, + {0x0c, 0x01, 0x0c, 0x00, "35" }, + {0x0c, 0x01, 0x0c, 0x04, "40" }, + {0x0c, 0x01, 0x0c, 0x0c, "50" }, + {0x0c, 0x01, 0x0c, 0x08, "60" }, + + {0 , 0xfe, 0 , 4 , "Continue play time" }, + {0x0c, 0x01, 0x30, 0x00, "+20" }, + {0x0c, 0x01, 0x30, 0x10, "+25" }, + {0x0c, 0x01, 0x30, 0x30, "+30" }, + {0x0c, 0x01, 0x30, 0x20, "+40" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x0c, 0x01, 0x80, 0x80, "Single" }, + {0x0c, 0x01, 0x80, 0x00, "Dual" }, +}; + +STDDIPINFO(Cameltry) + +static struct BurnDIPInfo CameltrjDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + {0x0b, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0b, 0x01, 0x02, 0x02, "Off" }, + {0x0b, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Medium" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Start remain time" }, + {0x0c, 0x01, 0x0c, 0x00, "35" }, + {0x0c, 0x01, 0x0c, 0x04, "40" }, + {0x0c, 0x01, 0x0c, 0x0c, "50" }, + {0x0c, 0x01, 0x0c, 0x08, "60" }, + + {0 , 0xfe, 0 , 4 , "Continue play time" }, + {0x0c, 0x01, 0x30, 0x00, "+20" }, + {0x0c, 0x01, 0x30, 0x10, "+25" }, + {0x0c, 0x01, 0x30, 0x30, "+30" }, + {0x0c, 0x01, 0x30, 0x20, "+40" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x0c, 0x01, 0x80, 0x80, "Single" }, + {0x0c, 0x01, 0x80, 0x00, "Dual" }, +}; + +STDDIPINFO(Cameltrj) + +static struct BurnDIPInfo DeadconxDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x15, 0x01, 0x01, 0x00, "Upright" }, + {0x15, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Damage" }, + {0x16, 0x01, 0x18, 0x10, "Small" }, + {0x16, 0x01, 0x18, 0x18, "Normal" }, + {0x16, 0x01, 0x18, 0x08, "Big" }, + {0x16, 0x01, 0x18, 0x00, "Biggest" }, + + {0 , 0xfe, 0 , 2 , "Game Type" }, + {0x16, 0x01, 0x80, 0x00, "1 Player Only" }, + {0x16, 0x01, 0x80, 0x80, "Multiplayer" }, +}; + +STDDIPINFO(Deadconx) + +static struct BurnDIPInfo DeadconxjDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x15, 0x01, 0x01, 0x00, "Upright" }, + {0x15, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x0c, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0c, 0x04, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x02, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x03, 0x01, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Damage" }, + {0x16, 0x01, 0x18, 0x10, "Small" }, + {0x16, 0x01, 0x18, 0x18, "Normal" }, + {0x16, 0x01, 0x18, 0x08, "Big" }, + {0x16, 0x01, 0x18, 0x00, "Biggest" }, + + {0 , 0xfe, 0 , 2 , "Game Type" }, + {0x16, 0x01, 0x80, 0x00, "1 Player Only" }, + {0x16, 0x01, 0x80, 0x80, "Multiplayer" }, +}; + +STDDIPINFO(Deadconxj) + +static struct BurnDIPInfo DinorexDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Damage" }, + {0x16, 0x01, 0x0c, 0x08, "Small" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Big" }, + {0x16, 0x01, 0x0c, 0x00, "Biggest" }, + + {0 , 0xfe, 0 , 2 , "Timer Speed" }, + {0x16, 0x01, 0x10, 0x10, "Normal" }, + {0x16, 0x01, 0x10, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Match Type" }, + {0x16, 0x01, 0x20, 0x20, "Best of 3" }, + {0x16, 0x01, 0x20, 0x00, "Single" }, + + {0 , 0xfe, 0 , 2 , "2 Player Mode" }, + {0x16, 0x01, 0x40, 0x40, "Upright" }, + {0x16, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Dinorex) + +static struct BurnDIPInfo DinorexjDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x0c, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0c, 0x04, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x02, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x03, 0x01, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Damage" }, + {0x16, 0x01, 0x0c, 0x08, "Small" }, + {0x16, 0x01, 0x0c, 0x0c, "Normal" }, + {0x16, 0x01, 0x0c, 0x04, "Big" }, + {0x16, 0x01, 0x0c, 0x00, "Biggest" }, + + {0 , 0xfe, 0 , 2 , "Timer Speed" }, + {0x16, 0x01, 0x10, 0x10, "Normal" }, + {0x16, 0x01, 0x10, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Match Type" }, + {0x16, 0x01, 0x20, 0x20, "Best of 3" }, + {0x16, 0x01, 0x20, 0x00, "Single" }, + + {0 , 0xfe, 0 , 2 , "2 Player Mode" }, + {0x16, 0x01, 0x40, 0x40, "Upright" }, + {0x16, 0x01, 0x40, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Dinorexj) + +static struct BurnDIPInfo DondokodDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "10k and 100k" }, + {0x14, 0x01, 0x0c, 0x08, "10k and 150k" }, + {0x14, 0x01, 0x0c, 0x04, "10k and 250k" }, + {0x14, 0x01, 0x0c, 0x00, "10k and 350k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, +}; + +STDDIPINFO(Dondokod) + +static struct BurnDIPInfo DondokodjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "10k and 100k" }, + {0x14, 0x01, 0x0c, 0x08, "10k and 150k" }, + {0x14, 0x01, 0x0c, 0x04, "10k and 250k" }, + {0x14, 0x01, 0x0c, 0x00, "10k and 350k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, +}; + +STDDIPINFO(Dondokodj) + +static struct BurnDIPInfo DondokoduDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "10k and 100k" }, + {0x14, 0x01, 0x0c, 0x08, "10k and 150k" }, + {0x14, 0x01, 0x0c, 0x04, "10k and 250k" }, + {0x14, 0x01, 0x0c, 0x00, "10k and 350k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, +}; + +STDDIPINFO(Dondokodu) + +static struct BurnDIPInfo DriftoutDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0xff, NULL }, + {0x0d, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0c, 0x01, 0x02, 0x02, "Off" }, + {0x0c, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x08, 0x00, "Off" }, + {0x0c, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0c, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x0c, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0c, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0c, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0c, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0c, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0c, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0c, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0d, 0x01, 0x03, 0x02, "Easy" }, + {0x0d, 0x01, 0x03, 0x03, "Medium" }, + {0x0d, 0x01, 0x03, 0x01, "Hard" }, + {0x0d, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Control" }, + {0x0d, 0x01, 0x0c, 0x0c, "Joystick" }, + {0x0d, 0x01, 0x0c, 0x08, "Paddle" }, + {0x0d, 0x01, 0x0c, 0x04, "Joystick" }, + {0x0d, 0x01, 0x0c, 0x00, "Steering Wheel" }, +}; + +STDDIPINFO(Driftout) + +static struct BurnDIPInfo FinalbDIPList[]= +{ + // Default Values + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Alternate Controls" }, + {0x19, 0x01, 0x01, 0x01, "Off" }, + {0x19, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x19, 0x01, 0x02, 0x02, "Off" }, + {0x19, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x19, 0x01, 0x04, 0x04, "Off" }, + {0x19, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x19, 0x01, 0x08, 0x00, "Off" }, + {0x19, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x19, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x19, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x19, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x19, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x19, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1a, 0x01, 0x03, 0x02, "Easy" }, + {0x1a, 0x01, 0x03, 0x03, "Medium" }, + {0x1a, 0x01, 0x03, 0x01, "Hard" }, + {0x1a, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Finalb) + +static struct BurnDIPInfo FinalbjDIPList[]= +{ + // Default Values + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Alternate Controls" }, + {0x19, 0x01, 0x01, 0x01, "Off" }, + {0x19, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x19, 0x01, 0x02, 0x02, "Off" }, + {0x19, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x19, 0x01, 0x04, 0x04, "Off" }, + {0x19, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x19, 0x01, 0x08, 0x00, "Off" }, + {0x19, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x19, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x19, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x19, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x19, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x19, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x19, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x19, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1a, 0x01, 0x03, 0x02, "Easy" }, + {0x1a, 0x01, 0x03, 0x03, "Medium" }, + {0x1a, 0x01, 0x03, 0x01, "Hard" }, + {0x1a, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Finalbj) + +static struct BurnDIPInfo FootchmpDIPList[]= +{ + // Default Values + {0x25, 0xff, 0xff, 0xfe, NULL }, + {0x26, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Game Over Type" }, + {0x25, 0x01, 0x01, 0x01, "Both Teams' Games Over" }, + {0x25, 0x01, 0x01, 0x00, "Losing Team's Game is Over" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x25, 0x01, 0x02, 0x02, "Off" }, + {0x25, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x25, 0x01, 0x04, 0x04, "Off" }, + {0x25, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x25, 0x01, 0x08, 0x00, "Off" }, + {0x25, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x25, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x25, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x25, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x25, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x25, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x25, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x25, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x25, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x26, 0x01, 0x03, 0x02, "Easy" }, + {0x26, 0x01, 0x03, 0x03, "Normal" }, + {0x26, 0x01, 0x03, 0x01, "Hard" }, + {0x26, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Game Time" }, + {0x26, 0x01, 0x0c, 0x00, "1 minute 30 seconds" }, + {0x26, 0x01, 0x0c, 0x0c, "2 minutes" }, + {0x26, 0x01, 0x0c, 0x04, "2 minutes 30 seconds" }, + {0x26, 0x01, 0x0c, 0x08, "3 minutes" }, + + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x26, 0x01, 0x30, 0x30, "2 Players" }, + {0x26, 0x01, 0x30, 0x20, "4 Players / 4 Coin Slots" }, + {0x26, 0x01, 0x30, 0x10, "4 Players / 2 Cabinets Combined"}, + {0x26, 0x01, 0x30, 0x00, "4 Players / 2 Coin Slots" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x26, 0x01, 0x40, 0x00, "Off" }, + {0x26, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Version" }, + {0x26, 0x01, 0x80, 0x00, "Normal" }, + {0x26, 0x01, 0x80, 0x80, "European" }, + +}; + +STDDIPINFO(Footchmp) + +static struct BurnDIPInfo HtheroDIPList[]= +{ + // Default Values + {0x25, 0xff, 0xff, 0x7f, NULL }, + {0x26, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Game Over Type" }, + {0x25, 0x01, 0x80, 0x80, "Both Teams' Games Over" }, + {0x25, 0x01, 0x80, 0x00, "Losing Team's Game is Over" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x25, 0x01, 0x40, 0x40, "Off" }, + {0x25, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x25, 0x01, 0x20, 0x20, "Off" }, + {0x25, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x25, 0x01, 0x10, 0x00, "Off" }, + {0x25, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x25, 0x01, 0x0c, 0x00, "3 Coins 1 Credit" }, + {0x25, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x25, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x25, 0x01, 0x0c, 0x04, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x25, 0x01, 0x03, 0x00, "3 Coins 1 Credit" }, + {0x25, 0x01, 0x03, 0x02, "2 Coins 1 Credit" }, + {0x25, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x25, 0x01, 0x03, 0x01, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x26, 0x01, 0xc0, 0x40, "Easy" }, + {0x26, 0x01, 0xc0, 0xc0, "Normal" }, + {0x26, 0x01, 0xc0, 0x80, "Hard" }, + {0x26, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Game Time" }, + {0x26, 0x01, 0x30, 0x00, "1 minute 30 seconds" }, + {0x26, 0x01, 0x30, 0x30, "2 minutes" }, + {0x26, 0x01, 0x30, 0x20, "2 minutes 30 seconds" }, + {0x26, 0x01, 0x30, 0x10, "3 minutes" }, + + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x26, 0x01, 0x0c, 0x0c, "2 Players" }, + {0x26, 0x01, 0x0c, 0x04, "4 Players / 4 Coin Slots" }, + {0x26, 0x01, 0x0c, 0x08, "4 Players / 2 Cabinets Combined"}, + {0x26, 0x01, 0x0c, 0x00, "4 Players / 2 Coin Slots" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x26, 0x01, 0x02, 0x00, "Off" }, + {0x26, 0x01, 0x02, 0x02, "On" }, +}; + +STDDIPINFO(Hthero) + +static struct BurnDIPInfo GrowlDIPList[]= +{ + // Default Values + {0x28, 0xff, 0xff, 0xff, NULL }, + {0x29, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x28, 0x01, 0x02, 0x02, "Off" }, + {0x28, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x28, 0x01, 0x04, 0x04, "Off" }, + {0x28, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x28, 0x01, 0x08, 0x00, "Off" }, + {0x28, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x28, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x28, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x28, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x28, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x28, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x29, 0x01, 0x03, 0x02, "Easy" }, + {0x29, 0x01, 0x03, 0x03, "Normal" }, + {0x29, 0x01, 0x03, 0x01, "Hard" }, + {0x29, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x29, 0x01, 0x30, 0x30, "2 Players" }, + {0x29, 0x01, 0x30, 0x20, "4 Players / 4 Coin Slots" }, + {0x29, 0x01, 0x30, 0x10, "4 Players / 2 Cabinets Combined"}, + {0x29, 0x01, 0x30, 0x00, "4 Players / 2 Coin Slots" }, + + {0 , 0xfe, 0 , 2 , "Final Boss Continue" }, + {0x29, 0x01, 0x40, 0x00, "Off" }, + {0x29, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Growl) + +static struct BurnDIPInfo GrowluDIPList[]= +{ + // Default Values + {0x28, 0xff, 0xff, 0xff, NULL }, + {0x29, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x28, 0x01, 0x02, 0x02, "Off" }, + {0x28, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x28, 0x01, 0x04, 0x04, "Off" }, + {0x28, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x28, 0x01, 0x08, 0x00, "Off" }, + {0x28, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x28, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x28, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x28, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x28, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x28, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x29, 0x01, 0x03, 0x02, "Easy" }, + {0x29, 0x01, 0x03, 0x03, "Normal" }, + {0x29, 0x01, 0x03, 0x01, "Hard" }, + {0x29, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x29, 0x01, 0x30, 0x30, "2 Players" }, + {0x29, 0x01, 0x30, 0x20, "4 Players / 4 Coin Slots" }, + {0x29, 0x01, 0x30, 0x10, "4 Players / 2 Cabinets Combined"}, + {0x29, 0x01, 0x30, 0x00, "4 Players / 2 Coin Slots" }, + + {0 , 0xfe, 0 , 2 , "Final Boss Continue" }, + {0x29, 0x01, 0x40, 0x00, "Off" }, + {0x29, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Growlu) + +static struct BurnDIPInfo RunarkDIPList[]= +{ + // Default Values + {0x28, 0xff, 0xff, 0xff, NULL }, + {0x29, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x28, 0x01, 0x02, 0x02, "Off" }, + {0x28, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x28, 0x01, 0x04, 0x04, "Off" }, + {0x28, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x28, 0x01, 0x08, 0x00, "Off" }, + {0x28, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x28, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x28, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x28, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x28, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x28, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x28, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x28, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x29, 0x01, 0x03, 0x02, "Easy" }, + {0x29, 0x01, 0x03, 0x03, "Normal" }, + {0x29, 0x01, 0x03, 0x01, "Hard" }, + {0x29, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x29, 0x01, 0x30, 0x30, "2 Players" }, + {0x29, 0x01, 0x30, 0x20, "4 Players / 4 Coin Slots" }, + {0x29, 0x01, 0x30, 0x10, "4 Players / 2 Cabinets Combined"}, + {0x29, 0x01, 0x30, 0x00, "4 Players / 2 Coin Slots" }, + + {0 , 0xfe, 0 , 2 , "Final Boss Continue" }, + {0x29, 0x01, 0x40, 0x00, "Off" }, + {0x29, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Runark) + +static struct BurnDIPInfo GunfrontDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "10k and every 80k" }, + {0x14, 0x01, 0x0c, 0x0c, "20k and every 80k" }, + {0x14, 0x01, 0x0c, 0x04, "30k and every 80k" }, + {0x14, 0x01, 0x0c, 0x00, "60k and every 80k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x80, 0x00, "Single" }, + {0x14, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Gunfront) + +static struct BurnDIPInfo GunfrontjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "10k and every 80k" }, + {0x14, 0x01, 0x0c, 0x0c, "20k and every 80k" }, + {0x14, 0x01, 0x0c, 0x04, "30k and every 80k" }, + {0x14, 0x01, 0x0c, 0x00, "60k and every 80k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "1" }, + {0x14, 0x01, 0x30, 0x10, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x80, 0x00, "Single" }, + {0x14, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Gunfrontj) + +static struct BurnDIPInfo KoshienDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Koshien) + +static struct BurnDIPInfo LiquidkDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "30k and 100k" }, + {0x14, 0x01, 0x0c, 0x08, "30k and 150k" }, + {0x14, 0x01, 0x0c, 0x04, "50k and 250k" }, + {0x14, 0x01, 0x0c, 0x00, "50k and 350k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x80, 0x80, "Single" }, + {0x14, 0x01, 0x80, 0x00, "Dual" }, +}; + +STDDIPINFO(Liquidk) + +static struct BurnDIPInfo LiquidkuDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "30k and 100k" }, + {0x14, 0x01, 0x0c, 0x08, "30k and 150k" }, + {0x14, 0x01, 0x0c, 0x04, "50k and 250k" }, + {0x14, 0x01, 0x0c, 0x00, "50k and 350k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x00, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x80, 0x80, "Single" }, + {0x14, 0x01, 0x80, 0x00, "Dual" }, +}; + +STDDIPINFO(Liquidku) + +static struct BurnDIPInfo MegablstDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x04, "150k only" }, + {0x14, 0x01, 0x0c, 0x08, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x40, 0x00, "Single" }, + {0x14, 0x01, 0x40, 0x40, "Dual" }, +}; + +STDDIPINFO(Megablst) + +static struct BurnDIPInfo MegablstjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x04, "150k only" }, + {0x14, 0x01, 0x0c, 0x08, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x40, 0x00, "Single" }, + {0x14, 0x01, 0x40, 0x40, "Dual" }, +}; + +STDDIPINFO(Megablstj) + +static struct BurnDIPInfo MegablstuDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k only" }, + {0x14, 0x01, 0x0c, 0x04, "150k only" }, + {0x14, 0x01, 0x0c, 0x08, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x10, "1" }, + {0x14, 0x01, 0x30, 0x00, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x14, 0x01, 0x40, 0x00, "Single" }, + {0x14, 0x01, 0x40, 0x40, "Dual" }, +}; + +STDDIPINFO(Megablstu) + +static struct BurnDIPInfo MetalbDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x08, "50k and every 120k" }, + {0x16, 0x01, 0x0c, 0x0c, "70k and every 150k" }, + {0x16, 0x01, 0x0c, 0x04, "80k and every 160k" }, + {0x16, 0x01, 0x0c, 0x00, "100k and every 200k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x00, "1" }, + {0x16, 0x01, 0x30, 0x10, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Metalb) + +static struct BurnDIPInfo MetalbjDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x08, "50k and every 120k" }, + {0x16, 0x01, 0x0c, 0x0c, "70k and every 150k" }, + {0x16, 0x01, 0x0c, 0x04, "80k and every 160k" }, + {0x16, 0x01, 0x0c, 0x00, "100k and every 200k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x00, "1" }, + {0x16, 0x01, 0x30, 0x10, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Metalbj) + +static struct BurnDIPInfo MjnquestDIPList[]= +{ + // Default Values + {0x19, 0xff, 0xff, 0xff, NULL }, + {0x1a, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x19, 0x01, 0x02, 0x02, "Off" }, + {0x19, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x19, 0x01, 0x04, 0x04, "Off" }, + {0x19, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x19, 0x01, 0x08, 0x00, "Off" }, + {0x19, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x19, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x19, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x19, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x19, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x19, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x19, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x19, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x1a, 0x01, 0x03, 0x02, "Easy" }, + {0x1a, 0x01, 0x03, 0x03, "Medium" }, + {0x1a, 0x01, 0x03, 0x01, "Hard" }, + {0x1a, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Mjnquest) + +static struct BurnDIPInfo NinjakDIPList[]= +{ + // Default Values + {0x24, 0xff, 0xff, 0xff, NULL }, + {0x25, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x24, 0x01, 0x02, 0x02, "Off" }, + {0x24, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x24, 0x01, 0x04, 0x04, "Off" }, + {0x24, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x24, 0x01, 0x08, 0x00, "Off" }, + {0x24, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x24, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x24, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x24, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x24, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x24, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x25, 0x01, 0x03, 0x02, "Easy" }, + {0x25, 0x01, 0x03, 0x03, "Medium" }, + {0x25, 0x01, 0x03, 0x01, "Hard" }, + {0x25, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x25, 0x01, 0x0c, 0x0c, "2 Players" }, + {0x25, 0x01, 0x0c, 0x08, "TROG (4 Players / 2 Coin Slots" }, + {0x25, 0x01, 0x0c, 0x04, "MTX2 (4 Players / 2 Cabinets" }, + {0x25, 0x01, 0x0c, 0x00, "YMNT (4 Players / 4 Coin Slots" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x25, 0x01, 0x30, 0x20, "2" }, + {0x25, 0x01, 0x30, 0x30, "3" }, + {0x25, 0x01, 0x30, 0x10, "4" }, + {0x25, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x25, 0x01, 0x40, 0x00, "Off" }, + {0x25, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Type" }, + {0x25, 0x01, 0x80, 0x00, "1 Player Only" }, + {0x25, 0x01, 0x80, 0x80, "Multiplayer" }, +}; + +STDDIPINFO(Ninjak) + +static struct BurnDIPInfo NinjakjDIPList[]= +{ + // Default Values + {0x24, 0xff, 0xff, 0xff, NULL }, + {0x25, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x24, 0x01, 0x02, 0x02, "Off" }, + {0x24, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x24, 0x01, 0x04, 0x04, "Off" }, + {0x24, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x24, 0x01, 0x08, 0x00, "Off" }, + {0x24, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x24, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x24, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x24, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x24, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x24, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x24, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x25, 0x01, 0x03, 0x02, "Easy" }, + {0x25, 0x01, 0x03, 0x03, "Medium" }, + {0x25, 0x01, 0x03, 0x01, "Hard" }, + {0x25, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x25, 0x01, 0x0c, 0x0c, "2 Players" }, + {0x25, 0x01, 0x0c, 0x08, "TROG (4 Players / 2 Coin Slots" }, + {0x25, 0x01, 0x0c, 0x04, "MTX2 (4 Players / 2 Cabinets" }, + {0x25, 0x01, 0x0c, 0x00, "YMNT (4 Players / 4 Coin Slots" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x25, 0x01, 0x30, 0x20, "2" }, + {0x25, 0x01, 0x30, 0x30, "3" }, + {0x25, 0x01, 0x30, 0x10, "4" }, + {0x25, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x25, 0x01, 0x40, 0x00, "Off" }, + {0x25, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Type" }, + {0x25, 0x01, 0x80, 0x00, "1 Player Only" }, + {0x25, 0x01, 0x80, 0x80, "Multiplayer" }, +}; + +STDDIPINFO(Ninjakj) + +static struct BurnDIPInfo NinjakuDIPList[]= +{ + // Default Values + {0x24, 0xff, 0xff, 0xff, NULL }, + {0x25, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x24, 0x01, 0x02, 0x02, "Off" }, + {0x24, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x24, 0x01, 0x04, 0x04, "Off" }, + {0x24, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x24, 0x01, 0x08, 0x00, "Off" }, + {0x24, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x24, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x24, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x24, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x24, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x24, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x24, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x25, 0x01, 0x03, 0x02, "Easy" }, + {0x25, 0x01, 0x03, 0x03, "Medium" }, + {0x25, 0x01, 0x03, 0x01, "Hard" }, + {0x25, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Cabinet Type" }, + {0x25, 0x01, 0x0c, 0x0c, "2 Players" }, + {0x25, 0x01, 0x0c, 0x08, "TROG (4 Players / 2 Coin Slots" }, + {0x25, 0x01, 0x0c, 0x04, "MTX2 (4 Players / 2 Cabinets" }, + {0x25, 0x01, 0x0c, 0x00, "YMNT (4 Players / 4 Coin Slots" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x25, 0x01, 0x30, 0x20, "2" }, + {0x25, 0x01, 0x30, 0x30, "3" }, + {0x25, 0x01, 0x30, 0x10, "4" }, + {0x25, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x25, 0x01, 0x40, 0x00, "Off" }, + {0x25, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Game Type" }, + {0x25, 0x01, 0x80, 0x00, "1 Player Only" }, + {0x25, 0x01, 0x80, 0x80, "Multiplayer" }, +}; + +STDDIPINFO(Ninjaku) + +static struct BurnDIPInfo PulirulaDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3 , "Magic" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x08, "4" }, + {0x16, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Pulirula) + +static struct BurnDIPInfo PulirulajDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 3 , "Magic" }, + {0x16, 0x01, 0x0c, 0x0c, "3" }, + {0x16, 0x01, 0x0c, 0x08, "4" }, + {0x16, 0x01, 0x0c, 0x04, "5" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Pulirulaj) + +static struct BurnDIPInfo QcrayonDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Default Time" }, + {0x12, 0x01, 0x0c, 0x00, "6 seconds" }, + {0x12, 0x01, 0x0c, 0x04, "7 seconds" }, + {0x12, 0x01, 0x0c, 0x08, "8 seconds" }, + {0x12, 0x01, 0x0c, 0x0c, "10 seconds" }, +}; + +STDDIPINFO(Qcrayon) + +static struct BurnDIPInfo Qcrayon2DIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Game Control" }, + {0x12, 0x01, 0x80, 0x80, "Joystick" }, + {0x12, 0x01, 0x80, 0x00, "4 Buttons" }, +}; + +STDDIPINFO(Qcrayon2) + +static struct BurnDIPInfo QjinseiDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Qjinsei) + +static struct BurnDIPInfo QtorimonDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Medium" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x20, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Show Correct Answer" }, + {0x10, 0x01, 0x40, 0x40, "Off" }, + {0x10, 0x01, 0x40, 0x00, "On" }, +}; + +STDDIPINFO(Qtorimon) + +static struct BurnDIPInfo QuizhqDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Time" }, + {0x12, 0x01, 0x0c, 0x0c, "5 seconds" }, + {0x12, 0x01, 0x0c, 0x08, "10 seconds" }, + {0x12, 0x01, 0x0c, 0x04, "15 seconds" }, + {0x12, 0x01, 0x0c, 0x00, "20 seconds" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x12, 0x01, 0x30, 0x20, "1" }, + {0x12, 0x01, 0x30, 0x30, "2" }, + {0x12, 0x01, 0x30, 0x10, "3" }, + {0x12, 0x01, 0x30, 0x00, "4" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x12, 0x01, 0x80, 0x00, "Single" }, + {0x12, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Quizhq) + +static struct BurnDIPInfo QzchikyuDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Qzchikyu) + +static struct BurnDIPInfo QzquestDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Qzquest) + +static struct BurnDIPInfo SolfigtrDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, +}; + +STDDIPINFO(Solfigtr) + +static struct BurnDIPInfo SsiDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Shields" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + {0x14, 0x01, 0x0c, 0x0c, "1" }, + {0x14, 0x01, 0x0c, 0x04, "2" }, + {0x14, 0x01, 0x0c, 0x08, "3" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x10, 0x00, "2" }, + {0x14, 0x01, 0x10, 0x10, "3" }, + + {0 , 0xfe, 0 , 4 , "2 Player Mode" }, + {0x14, 0x01, 0xa0, 0xa0, "Simultaneous" }, + {0x14, 0x01, 0xa0, 0x80, "Alternate, Single" }, + {0x14, 0x01, 0xa0, 0x00, "Alternate, Dual" }, + {0x14, 0x01, 0xa0, 0x20, "Not Allowed" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Ssi) + +static struct BurnDIPInfo Majest12DIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Shields" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + {0x14, 0x01, 0x0c, 0x0c, "1" }, + {0x14, 0x01, 0x0c, 0x04, "2" }, + {0x14, 0x01, 0x0c, 0x08, "3" }, + + {0 , 0xfe, 0 , 2 , "Lives" }, + {0x14, 0x01, 0x10, 0x00, "2" }, + {0x14, 0x01, 0x10, 0x10, "3" }, + + {0 , 0xfe, 0 , 4 , "2 Player Mode" }, + {0x14, 0x01, 0xa0, 0xa0, "Simultaneous" }, + {0x14, 0x01, 0xa0, 0x80, "Alternate, Single" }, + {0x14, 0x01, 0xa0, 0x00, "Alternate, Dual" }, + {0x14, 0x01, 0xa0, 0x20, "Not Allowed" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Majest12) + +static struct BurnDIPInfo ThundfoxDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Thundfox) + +static struct BurnDIPInfo ThundfoxjDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Thundfoxj) + +static struct BurnDIPInfo ThundfoxuDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x15, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "Same as start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Timer" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Upright Controls" }, + {0x16, 0x01, 0x80, 0x00, "Single" }, + {0x16, 0x01, 0x80, 0x80, "Dual" }, +}; + +STDDIPINFO(Thundfoxu) + +static struct BurnDIPInfo YesnojDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xff, NULL }, + {0x0a, 0xff, 0xfe, 0xff, NULL }, + + // Dip 1 + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Results Printer" }, + {0x0a, 0x01, 0x01, 0x00, "Off" }, + {0x0a, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x02, 0x00, "Off" }, + {0x0a, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0a, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, +}; + +STDDIPINFO(Yesnoj) + +static struct BurnDIPInfo YuyugogoDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xff, NULL }, + {0x12, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x03, 0x02, "Easy" }, + {0x12, 0x01, 0x03, 0x03, "Medium" }, + {0x12, 0x01, 0x03, 0x01, "Hard" }, + {0x12, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x12, 0x01, 0x40, 0x00, "Off" }, + {0x12, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Yuyugogo) + +static struct BurnRomInfo CameltryRomDesc[] = { + { "c38-11", 0x020000, 0xbe172da0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c38-14", 0x020000, 0xffa430de, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c38-08.bin", 0x010000, 0x7ff78873, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c38-01.bin", 0x080000, 0xc170ff36, BRF_GRA | TAITO_SPRITESA }, + + { "c38-03.bin", 0x020000, 0x59fa59a7, BRF_SND | TAITO_YM2610A }, + + { "c38-02.bin", 0x020000, 0x1a11714b, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Cameltry) +STD_ROM_FN(Cameltry) + +static struct BurnRomInfo CameltryauRomDesc[] = { + { "c38-11", 0x020000, 0xbe172da0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c38-14", 0x020000, 0xffa430de, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c38-15.bin", 0x010000, 0x0e60faac, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c38-01.bin", 0x080000, 0xc170ff36, BRF_GRA | TAITO_SPRITESA }, + + { "c38-02.bin", 0x020000, 0x1a11714b, BRF_GRA | TAITO_CHARS_PIVOT }, + + { "c38-04.bin", 0x020000, 0x53d330bb, BRF_SND | TAITO_MSM6295 }, +}; + +STD_ROM_PICK(Cameltryau) +STD_ROM_FN(Cameltryau) + +static struct BurnRomInfo CameltryaRomDesc[] = { + { "c38-11", 0x020000, 0xbe172da0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c38-16", 0x020000, 0x66ad6164, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c38-15.bin", 0x010000, 0x0e60faac, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c38-01.bin", 0x080000, 0xc170ff36, BRF_GRA | TAITO_SPRITESA }, + + { "c38-02.bin", 0x020000, 0x1a11714b, BRF_GRA | TAITO_CHARS_PIVOT }, + + { "c38-04.bin", 0x020000, 0x53d330bb, BRF_SND | TAITO_MSM6295 }, +}; + +STD_ROM_PICK(Cameltrya) +STD_ROM_FN(Cameltrya) + +static struct BurnRomInfo CameltryjRomDesc[] = { + { "c38-09.bin", 0x020000, 0x2ae01120, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c38-10.bin", 0x020000, 0x48d8ff56, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c38-08.bin", 0x010000, 0x7ff78873, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c38-01.bin", 0x080000, 0xc170ff36, BRF_GRA | TAITO_SPRITESA }, + + { "c38-03.bin", 0x020000, 0x59fa59a7, BRF_SND | TAITO_YM2610A }, + + { "c38-02.bin", 0x020000, 0x1a11714b, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Cameltryj) +STD_ROM_FN(Cameltryj) + +static struct BurnRomInfo DeadconxRomDesc[] = { + { "d28-06.3", 0x040000, 0x5b4bff51, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-12.5", 0x040000, 0x9b74e631, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-09.2", 0x040000, 0x143a0cc1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-08.4", 0x040000, 0x4c872bd9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d28-10.6", 0x010000, 0x40805d74, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d28-04.16", 0x080000, 0xdcabc26b, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d28-05.17", 0x080000, 0x862f9665, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d28-01.8", 0x100000, 0x181d7b69, BRF_GRA | TAITO_SPRITESA }, + { "d28-02.9", 0x100000, 0xd301771c, BRF_GRA | TAITO_SPRITESA }, + + { "d28-03.10", 0x100000, 0xa1804b52, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Deadconx) +STD_ROM_FN(Deadconx) + +static struct BurnRomInfo DeadconxjRomDesc[] = { + { "d28-06.3", 0x040000, 0x5b4bff51, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-07.5", 0x040000, 0x3fb8954c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-09.2", 0x040000, 0x143a0cc1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d28-08.4", 0x040000, 0x4c872bd9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d28-10.6", 0x010000, 0x40805d74, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d28-04.16", 0x080000, 0xdcabc26b, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d28-05.17", 0x080000, 0x862f9665, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d28-01.8", 0x100000, 0x181d7b69, BRF_GRA | TAITO_SPRITESA }, + { "d28-02.9", 0x100000, 0xd301771c, BRF_GRA | TAITO_SPRITESA }, + + { "d28-03.10", 0x100000, 0xa1804b52, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Deadconxj) +STD_ROM_FN(Deadconxj) + +static struct BurnRomInfo DinorexRomDesc[] = { + { "d39-14.9", 0x080000, 0xe6aafdac, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-16.8", 0x080000, 0xcedc8537, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-04.6", 0x100000, 0x3800506d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + { "d39-05.7", 0x100000, 0xe2ec3b5d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d39-12.5", 0x010000, 0x8292c7c1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d39-06.2", 0x100000, 0x52f62835, BRF_GRA | TAITO_CHARS }, + + { "d39-01.29", 0x200000, 0xd10e9c7d, BRF_GRA | TAITO_SPRITESA }, + { "d39-02.28", 0x200000, 0x6c304403, BRF_GRA | TAITO_SPRITESA }, + { "d39-03.27", 0x200000, 0xfc9cdab4, BRF_GRA | TAITO_SPRITESA }, + + { "d39-07.10", 0x100000, 0x28262816, BRF_SND | TAITO_YM2610A }, + { "d39-08.4", 0x080000, 0x377b8b7b, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Dinorex) +STD_ROM_FN(Dinorex) + +static struct BurnRomInfo DinorexjRomDesc[] = { + { "d39-14.9", 0x080000, 0xe6aafdac, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-13.8", 0x080000, 0xae496b2f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-04.6", 0x100000, 0x3800506d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + { "d39-05.7", 0x100000, 0xe2ec3b5d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d39-12.5", 0x010000, 0x8292c7c1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d39-06.2", 0x100000, 0x52f62835, BRF_GRA | TAITO_CHARS }, + + { "d39-01.29", 0x200000, 0xd10e9c7d, BRF_GRA | TAITO_SPRITESA }, + { "d39-02.28", 0x200000, 0x6c304403, BRF_GRA | TAITO_SPRITESA }, + { "d39-03.27", 0x200000, 0xfc9cdab4, BRF_GRA | TAITO_SPRITESA }, + + { "d39-07.10", 0x100000, 0x28262816, BRF_SND | TAITO_YM2610A }, + { "d39-08.4", 0x080000, 0x377b8b7b, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Dinorexj) +STD_ROM_FN(Dinorexj) + +static struct BurnRomInfo DinorexuRomDesc[] = { + { "d39-14.9", 0x080000, 0xe6aafdac, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-15.8", 0x080000, 0xfe96723b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d39-04.6", 0x100000, 0x3800506d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + { "d39-05.7", 0x100000, 0xe2ec3b5d, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d39-12.5", 0x010000, 0x8292c7c1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d39-06.2", 0x100000, 0x52f62835, BRF_GRA | TAITO_CHARS }, + + { "d39-01.29", 0x200000, 0xd10e9c7d, BRF_GRA | TAITO_SPRITESA }, + { "d39-02.28", 0x200000, 0x6c304403, BRF_GRA | TAITO_SPRITESA }, + { "d39-03.27", 0x200000, 0xfc9cdab4, BRF_GRA | TAITO_SPRITESA }, + + { "d39-07.10", 0x100000, 0x28262816, BRF_SND | TAITO_YM2610A }, + { "d39-08.4", 0x080000, 0x377b8b7b, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Dinorexu) +STD_ROM_FN(Dinorexu) + +static struct BurnRomInfo DondokodRomDesc[] = { + { "b95-12.bin", 0x020000, 0xd0fce87a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-11-1.bin", 0x020000, 0xdad40cd3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-10.bin", 0x020000, 0xa46e1f0b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-14.bin", 0x020000, 0x6e4e1351, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b95-08.bin", 0x010000, 0xb5aa49e1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b95-02.bin", 0x080000, 0x67b4e979, BRF_GRA | TAITO_CHARS }, + + { "b95-01.bin", 0x080000, 0x51c176ce, BRF_GRA | TAITO_SPRITESA }, + + { "b95-04.bin", 0x080000, 0xac4c1716, BRF_SND | TAITO_YM2610A }, + + { "b95-03.bin", 0x080000, 0x543aa0d1, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Dondokod) +STD_ROM_FN(Dondokod) + +static struct BurnRomInfo DondokodjRomDesc[] = { + { "b95-12.bin", 0x020000, 0xd0fce87a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-11-1.bin", 0x020000, 0xdad40cd3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-10.bin", 0x020000, 0xa46e1f0b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-09.bin", 0x020000, 0xd8c86d39, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b95-08.bin", 0x010000, 0xb5aa49e1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b95-02.bin", 0x080000, 0x67b4e979, BRF_GRA | TAITO_CHARS }, + + { "b95-01.bin", 0x080000, 0x51c176ce, BRF_GRA | TAITO_SPRITESA }, + + { "b95-04.bin", 0x080000, 0xac4c1716, BRF_SND | TAITO_YM2610A }, + + { "b95-03.bin", 0x080000, 0x543aa0d1, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Dondokodj) +STD_ROM_FN(Dondokodj) + +static struct BurnRomInfo DondokoduRomDesc[] = { + { "b95-12.bin", 0x020000, 0xd0fce87a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-11-1.bin", 0x020000, 0xdad40cd3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-10.bin", 0x020000, 0xa46e1f0b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b95-13.bin", 0x020000, 0x350d2c65, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b95-08.bin", 0x010000, 0xb5aa49e1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b95-02.bin", 0x080000, 0x67b4e979, BRF_GRA | TAITO_CHARS }, + + { "b95-01.bin", 0x080000, 0x51c176ce, BRF_GRA | TAITO_SPRITESA }, + + { "b95-04.bin", 0x080000, 0xac4c1716, BRF_SND | TAITO_YM2610A }, + + { "b95-03.bin", 0x080000, 0x543aa0d1, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Dondokodu) +STD_ROM_FN(Dondokodu) + +static struct BurnRomInfo DriftoutRomDesc[] = { + { "do_46.rom", 0x080000, 0xf960363e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "do_45.rom", 0x080000, 0xe3fe66b9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "do_50.rom", 0x010000, 0xffe10124, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "do_obj.rom", 0x080000, 0x5491f1c4, BRF_GRA | TAITO_SPRITESA }, + + { "do_snd.rom", 0x080000, 0xf2deb82b, BRF_SND | TAITO_YM2610A }, + + { "do_piv.rom", 0x080000, 0xc4f012f7, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Driftout) +STD_ROM_FN(Driftout) + +static struct BurnRomInfo DriveoutRomDesc[] = { + { "driveout.003", 0x080000, 0xdc431e4e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "driveout.002", 0x080000, 0x6f9063f4, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "driveout.020", 0x008000, 0x99aaeb2e, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "driveout.084", 0x040000, 0x530ac420, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "driveout.081", 0x040000, 0x0e9a3e9e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "do_piv.rom", 0x080000, 0xc4f012f7, BRF_GRA | TAITO_CHARS_PIVOT }, + + { "driveout.028", 0x080000, 0xcbde0b66, BRF_SND | TAITO_MSM6295 }, + { "driveout.029", 0x020000, 0x0aba2026, BRF_SND | TAITO_MSM6295 }, +}; + +STD_ROM_PICK(Driveout) +STD_ROM_FN(Driveout) + +static struct BurnRomInfo FinalbRomDesc[] = { + { "b82-09.10", 0x20000, 0x632f1ecd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b82-17.11", 0x20000, 0xe91b2ec9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b82_10.16", 0x10000, 0xa38aaaed, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b82-06.19", 0x20000, 0xfc450a25, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b82-07.18", 0x20000, 0xec3df577, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b82-04.4", 0x80000, 0x6346f98e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-03.5", 0x80000, 0xdaa11561, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-05.3", 0x80000, 0xaa90b93a, BRF_GRA | TAITO_SPRITESA }, + + { "b82-02.1", 0x80000, 0x5dd06bdd, BRF_SND | TAITO_YM2610A }, + + { "b82-01.2", 0x80000, 0xf0eb6846, BRF_SND | TAITO_YM2610B }, + + { "tibpal16l8.ic41", 0x00104, 0x11a0a19a, BRF_OPT }, + { "tibpal16l8.ic42", 0x00104, 0xcc53deb8, BRF_OPT }, + { "tibpal16l8.ic51", 0x00104, 0xf2878537, BRF_OPT }, + { "gal16v8.ic13", 0x00117, 0xa4f75fd0, BRF_OPT }, + { "gal16v8.ic35", 0x00117, 0xca4eb3e1, BRF_OPT }, +}; + +STD_ROM_PICK(Finalb) +STD_ROM_FN(Finalb) + +static struct BurnRomInfo FinalbjRomDesc[] = { + { "b82-09.10", 0x20000, 0x632f1ecd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b82-08.11", 0x20000, 0x07154fe5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b82_10.16", 0x10000, 0xa38aaaed, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b82-06.19", 0x20000, 0xfc450a25, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b82-07.18", 0x20000, 0xec3df577, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b82-04.4", 0x80000, 0x6346f98e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-03.5", 0x80000, 0xdaa11561, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-05.3", 0x80000, 0xaa90b93a, BRF_GRA | TAITO_SPRITESA }, + + { "b82-02.1", 0x80000, 0x5dd06bdd, BRF_SND | TAITO_YM2610A }, + + { "b82-01.2", 0x80000, 0xf0eb6846, BRF_SND | TAITO_YM2610B }, + + { "tibpal16l8.ic41", 0x00104, 0x11a0a19a, BRF_OPT }, + { "tibpal16l8.ic42", 0x00104, 0xcc53deb8, BRF_OPT }, + { "tibpal16l8.ic51", 0x00104, 0xf2878537, BRF_OPT }, + { "gal16v8.ic13", 0x00117, 0xa4f75fd0, BRF_OPT }, + { "gal16v8.ic35", 0x00117, 0xca4eb3e1, BRF_OPT }, +}; + +STD_ROM_PICK(Finalbj) +STD_ROM_FN(Finalbj) + +static struct BurnRomInfo FinalbuRomDesc[] = { + { "b82-09-1", 0x20000, 0x66729cb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b82-6-14", 0x20000, 0x879387fa, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b82_10.16", 0x10000, 0xa38aaaed, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b82-06.19", 0x20000, 0xfc450a25, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b82-07.18", 0x20000, 0xec3df577, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b82-04.4", 0x80000, 0x6346f98e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-03.5", 0x80000, 0xdaa11561, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b82-05.3", 0x80000, 0xaa90b93a, BRF_GRA | TAITO_SPRITESA }, + + { "b82-02.1", 0x80000, 0x5dd06bdd, BRF_SND | TAITO_YM2610A }, + + { "b82-01.2", 0x80000, 0xf0eb6846, BRF_SND | TAITO_YM2610B }, + + { "tibpal16l8.ic41", 0x00104, 0x11a0a19a, BRF_OPT }, + { "tibpal16l8.ic42", 0x00104, 0xcc53deb8, BRF_OPT }, + { "tibpal16l8.ic51", 0x00104, 0xf2878537, BRF_OPT }, + { "gal16v8.ic13", 0x00117, 0xa4f75fd0, BRF_OPT }, + { "gal16v8.ic35", 0x00117, 0xca4eb3e1, BRF_OPT }, +}; + +STD_ROM_PICK(Finalbu) +STD_ROM_FN(Finalbu) + +static struct BurnRomInfo FootchmpRomDesc[] = { + { "c80-11.6", 0x020000, 0xf78630fb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-10.4", 0x020000, 0x32c109cb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-12.7", 0x020000, 0x80d46fef, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-14.5", 0x020000, 0x40ac4828, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c80-15.70", 0x010000, 0x05aa7fd7, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c80-04.1", 0x080000, 0x9a17fe8c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "c80-05.2", 0x080000, 0xacde7071, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "c80-01.9", 0x100000, 0xf43782e6, BRF_GRA | TAITO_SPRITESA }, + { "c80-02.10", 0x100000, 0x060a8b61, BRF_GRA | TAITO_SPRITESA }, + + { "c80-03.57", 0x100000, 0x609938d5, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Footchmp) +STD_ROM_FN(Footchmp) + +static struct BurnRomInfo HtheroRomDesc[] = { + { "c80-16.6", 0x020000, 0x4e795b52, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-17.4", 0x020000, 0x42c0a838, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-12.7", 0x020000, 0x80d46fef, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c80-18.5", 0x020000, 0xaea22904, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c80-15.70", 0x010000, 0x05aa7fd7, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c80-04.1", 0x080000, 0x9a17fe8c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "c80-05.2", 0x080000, 0xacde7071, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "c80-01.9", 0x100000, 0xf43782e6, BRF_GRA | TAITO_SPRITESA }, + { "c80-02.10", 0x100000, 0x060a8b61, BRF_GRA | TAITO_SPRITESA }, + + { "c80-03.57", 0x100000, 0x609938d5, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Hthero) +STD_ROM_FN(Hthero) + +static struct BurnRomInfo Euroch92RomDesc[] = { + { "ec92_25.rom", 0x020000, 0x98482202, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ec92_23.rom", 0x020000, 0xae5e75e9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ec92_26.rom", 0x020000, 0xb986ccb2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ec92_24.rom", 0x020000, 0xb31d94ac, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "ec92_27.rom", 0x010000, 0x2db48e65, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "ec92_21.rom", 0x080000, 0x5759ed37, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "ec92_22.rom", 0x080000, 0xd9a0d38e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "ec92_19.rom", 0x100000, 0x219141a5, BRF_GRA | TAITO_SPRITESA }, + { "c80-02.10", 0x100000, 0x060a8b61, BRF_GRA | TAITO_SPRITESA }, + + { "c80-03.57", 0x100000, 0x609938d5, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Euroch92) +STD_ROM_FN(Euroch92) + +static struct BurnRomInfo GrowlRomDesc[] = { + { "c74-10.ic59", 0x040000, 0xca81a20b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-08.ic61", 0x040000, 0xaa35dd9e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-11.ic58", 0x040000, 0xee3bd6d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-14.ic60", 0x040000, 0xb6c24ec7, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c74-12.ic62", 0x010000, 0xbb6ed668, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c74-01.ic34", 0x100000, 0x3434ce80, BRF_GRA | TAITO_CHARS }, + + { "c74-03.ic12", 0x100000, 0x1a0d8951, BRF_GRA | TAITO_SPRITESA }, + { "c74-02.ic11", 0x100000, 0x15a21506, BRF_GRA | TAITO_SPRITESA }, + + { "c74-04.ic28", 0x100000, 0x2d97edf2, BRF_SND | TAITO_YM2610A }, + { "c74-05.ic29", 0x080000, 0xe29c0828, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Growl) +STD_ROM_FN(Growl) + +static struct BurnRomInfo GrowluRomDesc[] = { + { "c74-10.ic59", 0x040000, 0xca81a20b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-08.ic61", 0x040000, 0xaa35dd9e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-11.ic58", 0x040000, 0xee3bd6d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-13.ic60", 0x040000, 0xc1c57e51, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c74-12.ic62", 0x010000, 0xbb6ed668, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c74-01.ic34", 0x100000, 0x3434ce80, BRF_GRA | TAITO_CHARS }, + + { "c74-03.ic12", 0x100000, 0x1a0d8951, BRF_GRA | TAITO_SPRITESA }, + { "c74-02.ic11", 0x100000, 0x15a21506, BRF_GRA | TAITO_SPRITESA }, + + { "c74-04.ic28", 0x100000, 0x2d97edf2, BRF_SND | TAITO_YM2610A }, + { "c74-05.ic29", 0x080000, 0xe29c0828, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Growlu) +STD_ROM_FN(Growlu) + +static struct BurnRomInfo RunarkRomDesc[] = { + { "c74-10.ic59", 0x040000, 0xca81a20b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-08.ic61", 0x040000, 0xaa35dd9e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-11.ic58", 0x040000, 0xee3bd6d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c74-09.ic14", 0x040000, 0x58cc2feb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c74-12.ic62", 0x010000, 0xbb6ed668, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c74-01.ic34", 0x100000, 0x3434ce80, BRF_GRA | TAITO_CHARS }, + + { "c74-03.ic12", 0x100000, 0x1a0d8951, BRF_GRA | TAITO_SPRITESA }, + { "c74-02.ic11", 0x100000, 0x15a21506, BRF_GRA | TAITO_SPRITESA }, + + { "c74-04.ic28", 0x100000, 0x2d97edf2, BRF_SND | TAITO_YM2610A }, + { "c74-05.ic29", 0x080000, 0xe29c0828, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Runark) +STD_ROM_FN(Runark) + +static struct BurnRomInfo GunfrontRomDesc[] = { + { "c71-09.ic42", 0x020000, 0x10a544a2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-08.ic41", 0x020000, 0xc17dc0a0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-10.ic40", 0x020000, 0xf39c0a06, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-14.ic39", 0x020000, 0x312da036, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-16.ic38", 0x020000, 0x1bbcc2d4, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-15.ic37", 0x020000, 0xdf3e00bb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c71-12.ic49", 0x010000, 0x0038c7f8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c71-02.ic59", 0x100000, 0x2a600c92, BRF_GRA | TAITO_CHARS }, + + { "c71-03.ic19", 0x100000, 0x9133c605, BRF_GRA | TAITO_SPRITESA }, + + { "c71-01.ic29", 0x100000, 0x0e73105a, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Gunfront) +STD_ROM_FN(Gunfront) + +static struct BurnRomInfo GunfrontjRomDesc[] = { + { "c71-09.ic42", 0x020000, 0x10a544a2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-08.ic41", 0x020000, 0xc17dc0a0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-10.ic40", 0x020000, 0xf39c0a06, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-11.ic39", 0x020000, 0xdf23c11a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-16.ic38", 0x020000, 0x1bbcc2d4, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c71-15.ic37", 0x020000, 0xdf3e00bb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c71-12.ic49", 0x010000, 0x0038c7f8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c71-02.ic59", 0x100000, 0x2a600c92, BRF_GRA | TAITO_CHARS }, + + { "c71-03.ic19", 0x100000, 0x9133c605, BRF_GRA | TAITO_SPRITESA }, + + { "c71-01.ic29", 0x100000, 0x0e73105a, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Gunfrontj) +STD_ROM_FN(Gunfrontj) + +static struct BurnRomInfo KoshienRomDesc[] = { + { "c81-11.bin", 0x020000, 0xb44ea8c9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c81-10.bin", 0x020000, 0x8f98c40a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c81-04.bin", 0x080000, 0x1592b460, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c81-12.bin", 0x010000, 0x6e8625b6, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c81-03.bin", 0x100000, 0x29bbf492, BRF_GRA | TAITO_CHARS }, + + { "c81-01.bin", 0x100000, 0x64b15d2a, BRF_GRA | TAITO_SPRITESA }, + { "c81-02.bin", 0x100000, 0x962461e8, BRF_GRA | TAITO_SPRITESA }, + + { "c81-05.bin", 0x080000, 0x9c3d71be, BRF_SND | TAITO_YM2610A }, + { "c81-06.bin", 0x080000, 0x927833b4, BRF_SND | TAITO_YM2610B }, + + { "pal16l8b-c81-07.bin",0x000104, 0x46341732, BRF_OPT }, + { "pal16l8b-c81-08.bin",0x000104, 0xe7d2d300, BRF_OPT }, + { "pal16l8b-c81-09.bin",0x000104, 0xe4c012a1, BRF_OPT }, +}; + +STD_ROM_PICK(Koshien) +STD_ROM_FN(Koshien) + +static struct BurnRomInfo LiquidkRomDesc[] = { + { "c49-09.ic47", 0x20000, 0x6ae09eb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-11.ic48", 0x20000, 0x42d2be6e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-10.ic45", 0x20000, 0x50bef2e0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-12.ic46", 0x20000, 0xcb16bad5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c49-08.ic32", 0x10000, 0x413c310c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c49-03.ic76", 0x80000, 0xc3364f9b, BRF_GRA | TAITO_CHARS }, + + { "c49-01.ic54", 0x80000, 0x67cc3163, BRF_GRA | TAITO_SPRITESA }, + { "c49-02.ic53", 0x80000, 0xd2400710, BRF_GRA | TAITO_SPRITESA }, + + { "c49-04.ic33", 0x80000, 0x474d45a4, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Liquidk) +STD_ROM_FN(Liquidk) + +static struct BurnRomInfo LiquidkuRomDesc[] = { + { "c49-09.ic47", 0x20000, 0x6ae09eb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-11.ic48", 0x20000, 0x42d2be6e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-10.ic45", 0x20000, 0x50bef2e0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-14.ic46", 0x20000, 0xbc118a43, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c49-08.ic32", 0x10000, 0x413c310c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c49-03.ic76", 0x80000, 0xc3364f9b, BRF_GRA | TAITO_CHARS }, + + { "c49-01.ic54", 0x80000, 0x67cc3163, BRF_GRA | TAITO_SPRITESA }, + { "c49-02.ic53", 0x80000, 0xd2400710, BRF_GRA | TAITO_SPRITESA }, + + { "c49-04.ic33", 0x80000, 0x474d45a4, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Liquidku) +STD_ROM_FN(Liquidku) + +static struct BurnRomInfo MizubakuRomDesc[] = { + { "c49-09.ic47", 0x20000, 0x6ae09eb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-11.ic48", 0x20000, 0x42d2be6e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-10.ic45", 0x20000, 0x50bef2e0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c49-13.ic46", 0x20000, 0x2518dbf9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c49-08.ic32", 0x10000, 0x413c310c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c49-03.ic76", 0x80000, 0xc3364f9b, BRF_GRA | TAITO_CHARS }, + + { "c49-01.ic54", 0x80000, 0x67cc3163, BRF_GRA | TAITO_SPRITESA }, + { "c49-02.ic53", 0x80000, 0xd2400710, BRF_GRA | TAITO_SPRITESA }, + + { "c49-04.ic33", 0x80000, 0x474d45a4, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Mizubaku) +STD_ROM_FN(Mizubaku) + +static struct BurnRomInfo MegablstRomDesc[] = { + { "c11-07.55", 0x020000, 0x11d228b6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-08.39", 0x020000, 0xa79d4dca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-06.54", 0x020000, 0x7c249894, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-11.38", 0x020000, 0x263ecbf9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c11-12.3", 0x010000, 0xb11094f1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c11-05.58", 0x080000, 0x733e6d8e, BRF_GRA | TAITO_CHARS }, + + { "c11-03.32", 0x080000, 0x46718c7a, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c11-04.31", 0x080000, 0x663f33cc, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c11-01.29", 0x080000, 0xfd1ea532, BRF_SND | TAITO_YM2610A }, + { "c11-02.30", 0x080000, 0x451cc187, BRF_SND | TAITO_YM2610B }, + + { "pal16l8b-b89-01.ic8", 0x000104, 0x4095b97a, BRF_OPT }, + { "pal16l8b-b89-02.ic28", 0x000104, 0x6430b559, BRF_OPT }, + { "pal16l8b-b89-03.bin", 0x000104, 0x634592e2, BRF_OPT }, + { "palce16v8-b89-04.ic27", 0x000117, 0xfc136ae2, BRF_OPT }, + { "pal16l8b-c11-13.ic13", 0x000104, 0x421d7ea8, BRF_OPT }, + { "pal16l8b-c11-14.ic23", 0x000104, 0x5c740aee, BRF_OPT }, +}; + +STD_ROM_PICK(Megablst) +STD_ROM_FN(Megablst) + +static struct BurnRomInfo MegablstjRomDesc[] = { + { "c11-07.55", 0x020000, 0x11d228b6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-08.39", 0x020000, 0xa79d4dca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-06.54", 0x020000, 0x7c249894, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-09.38", 0x020000, 0xc830aad5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c11-12.3", 0x010000, 0xb11094f1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c11-05.58", 0x080000, 0x733e6d8e, BRF_GRA | TAITO_CHARS }, + + { "c11-03.32", 0x080000, 0x46718c7a, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c11-04.31", 0x080000, 0x663f33cc, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c11-01.29", 0x080000, 0xfd1ea532, BRF_SND | TAITO_YM2610A }, + { "c11-02.30", 0x080000, 0x451cc187, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Megablstj) +STD_ROM_FN(Megablstj) + +static struct BurnRomInfo MegablstuRomDesc[] = { + { "c11-07.55", 0x020000, 0x11d228b6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-08.39", 0x020000, 0xa79d4dca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-06.54", 0x020000, 0x7c249894, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c11-10.38", 0x020000, 0xbf379a43, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c11-12.3", 0x010000, 0xb11094f1, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c11-05.58", 0x080000, 0x733e6d8e, BRF_GRA | TAITO_CHARS }, + + { "c11-03.32", 0x080000, 0x46718c7a, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c11-04.31", 0x080000, 0x663f33cc, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c11-01.29", 0x080000, 0xfd1ea532, BRF_SND | TAITO_YM2610A }, + { "c11-02.30", 0x080000, 0x451cc187, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Megablstu) +STD_ROM_FN(Megablstu) + +static struct BurnRomInfo MetalbRomDesc[] = { + { "d16-16.8", 0x040000, 0x3150be61, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d16-18.7", 0x040000, 0x5216d092, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d12-07.9", 0x020000, 0xe07f5136, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d12-06.6", 0x020000, 0x131df731, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d12-13.5", 0x020000, 0xbcca2649, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d12-03.14", 0x080000, 0x46b498c0, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d12-04.13", 0x080000, 0xab66d141, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d12-01.20", 0x100000, 0xb81523b9, BRF_GRA | TAITO_SPRITESA }, + + { "d12-02.10", 0x100000, 0x79263e74, BRF_SND | TAITO_YM2610A }, + { "d12-05.16", 0x080000, 0x7fd036c5, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Metalb) +STD_ROM_FN(Metalb) + +static struct BurnRomInfo MetalbjRomDesc[] = { + { "d12-12.8", 0x040000, 0x556f82b2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d12-11.7", 0x040000, 0xaf9ee28d, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d12-07.9", 0x020000, 0xe07f5136, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d12-06.6", 0x020000, 0x131df731, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d12-13.5", 0x020000, 0xbcca2649, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d12-03.14", 0x080000, 0x46b498c0, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "d12-04.13", 0x080000, 0xab66d141, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "d12-01.20", 0x100000, 0xb81523b9, BRF_GRA | TAITO_SPRITESA }, + + { "d12-02.10", 0x100000, 0x79263e74, BRF_SND | TAITO_YM2610A }, + { "d12-05.16", 0x080000, 0x7fd036c5, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Metalbj) +STD_ROM_FN(Metalbj) + +static struct BurnRomInfo MjnquestRomDesc[] = { + { "c77-09", 0x020000, 0x0a005d01, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c77-08", 0x020000, 0x4244f775, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c77-04", 0x080000, 0xc2e7e038, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c77-10", 0x010000, 0xf16b2c1e, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c77-01", 0x100000, 0x5ba51205, BRF_GRA | TAITO_CHARS }, + { "c77-02", 0x100000, 0x6a6f3040, BRF_GRA | TAITO_CHARS }, + + { "c77-05", 0x080000, 0xc5a54678, BRF_GRA | TAITO_SPRITESA }, + + { "c77-03", 0x080000, 0x312f17b1, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Mjnquest) +STD_ROM_FN(Mjnquest) + +static struct BurnRomInfo MjnquestbRomDesc[] = { + { "c77-09a", 0x020000, 0xfc17f1c2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c77-08", 0x020000, 0x4244f775, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c77-04", 0x080000, 0xc2e7e038, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c77-10", 0x010000, 0xf16b2c1e, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c77-01", 0x100000, 0x5ba51205, BRF_GRA | TAITO_CHARS }, + { "c77-02", 0x100000, 0x6a6f3040, BRF_GRA | TAITO_CHARS }, + + { "c77-05", 0x080000, 0xc5a54678, BRF_GRA | TAITO_SPRITESA }, + + { "c77-03", 0x080000, 0x312f17b1, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Mjnquestb) +STD_ROM_FN(Mjnquestb) + +static struct BurnRomInfo NinjakRomDesc[] = { + { "c85-10x.ic50", 0x020000, 0xba7e6e74, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-13x.ic49", 0x020000, 0x0ac2cba2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-07.ic48", 0x020000, 0x3eccfd0a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-06.ic47", 0x020000, 0xd126ded1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c85-14.ic54", 0x010000, 0xf2a52a51, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c85-03.ic65", 0x080000, 0x4cc7b9df, BRF_GRA | TAITO_CHARS }, + + { "c85-01.ic19", 0x100000, 0xa711977c, BRF_GRA | TAITO_SPRITESA }, + { "c85-02.ic17", 0x100000, 0xa6ad0f3d, BRF_GRA | TAITO_SPRITESA }, + + { "c85-04.ic31", 0x080000, 0x5afb747e, BRF_SND | TAITO_YM2610A }, + { "c85-05.ic33", 0x080000, 0x3c1b0ed0, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Ninjak) +STD_ROM_FN(Ninjak) + +static struct BurnRomInfo NinjakjRomDesc[] = { + { "c85-10x.ic50", 0x020000, 0xba7e6e74, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-11x.ic49", 0x020000, 0xe4ccaa8e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-07.ic48", 0x020000, 0x3eccfd0a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-06.ic47", 0x020000, 0xd126ded1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c85-14.ic54", 0x010000, 0xf2a52a51, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c85-03.ic65", 0x080000, 0x4cc7b9df, BRF_GRA | TAITO_CHARS }, + + { "c85-01.ic19", 0x100000, 0xa711977c, BRF_GRA | TAITO_SPRITESA }, + { "c85-02.ic17", 0x100000, 0xa6ad0f3d, BRF_GRA | TAITO_SPRITESA }, + + { "c85-04.ic31", 0x080000, 0x5afb747e, BRF_SND | TAITO_YM2610A }, + { "c85-05.ic33", 0x080000, 0x3c1b0ed0, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Ninjakj) +STD_ROM_FN(Ninjakj) + +static struct BurnRomInfo NinjakuRomDesc[] = { + { "c85-15x.ic50", 0x020000, 0x719a481b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-12x.ic49", 0x020000, 0x6c3f7e1e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-07.ic48", 0x020000, 0x3eccfd0a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c85-06.ic47", 0x020000, 0xd126ded1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c85-14.ic54", 0x010000, 0xf2a52a51, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c85-03.ic65", 0x080000, 0x4cc7b9df, BRF_GRA | TAITO_CHARS }, + + { "c85-01.ic19", 0x100000, 0xa711977c, BRF_GRA | TAITO_SPRITESA }, + { "c85-02.ic17", 0x100000, 0xa6ad0f3d, BRF_GRA | TAITO_SPRITESA }, + + { "c85-04.ic31", 0x080000, 0x5afb747e, BRF_SND | TAITO_YM2610A }, + { "c85-05.ic33", 0x080000, 0x3c1b0ed0, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Ninjaku) +STD_ROM_FN(Ninjaku) + +static struct BurnRomInfo PulirulaRomDesc[] = { + { "c98-12.rom", 0x040000, 0x816d6cde, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-16.rom", 0x040000, 0x59df5c77, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-06.rom", 0x020000, 0x64a71b45, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-07.rom", 0x020000, 0x90195bc0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c98-14.rom", 0x020000, 0xa858e17c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c98-04.rom", 0x100000, 0x0e1fe3b2, BRF_GRA | TAITO_CHARS }, + + { "c98-02.rom", 0x100000, 0x4a2ad2b3, BRF_GRA | TAITO_SPRITESA }, + { "c98-03.rom", 0x100000, 0x589a678f, BRF_GRA | TAITO_SPRITESA }, + + { "c98-01.rom", 0x100000, 0x197f66f5, BRF_SND | TAITO_YM2610A }, + + { "c98-05.rom", 0x080000, 0x9ddd9c39, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Pulirula) +STD_ROM_FN(Pulirula) + +static struct BurnRomInfo PulirulajRomDesc[] = { + { "c98-12.rom", 0x040000, 0x816d6cde, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-13.rom", 0x040000, 0xb7d13d5b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-06.rom", 0x020000, 0x64a71b45, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c98-07.rom", 0x020000, 0x90195bc0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c98-14.rom", 0x020000, 0xa858e17c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c98-04.rom", 0x100000, 0x0e1fe3b2, BRF_GRA | TAITO_CHARS }, + + { "c98-02.rom", 0x100000, 0x4a2ad2b3, BRF_GRA | TAITO_SPRITESA }, + { "c98-03.rom", 0x100000, 0x589a678f, BRF_GRA | TAITO_SPRITESA }, + + { "c98-01.rom", 0x100000, 0x197f66f5, BRF_SND | TAITO_YM2610A }, + + { "c98-05.rom", 0x080000, 0x9ddd9c39, BRF_GRA | TAITO_CHARS_PIVOT }, +}; + +STD_ROM_PICK(Pulirulaj) +STD_ROM_FN(Pulirulaj) + +static struct BurnRomInfo QcrayonRomDesc[] = { + { "d55-13", 0x040000, 0x16afbfc7, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d55-14", 0x040000, 0x2fb3057f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d55-03", 0x100000, 0x4d161e76, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d55-15", 0x010000, 0xba782eff, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d55-02", 0x100000, 0xf3db2f1c, BRF_GRA | TAITO_CHARS }, + + { "d55-05", 0x100000, 0xf0e59902, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "d55-04", 0x100000, 0x412975ce, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "d55-01", 0x100000, 0xa8309af4, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Qcrayon) +STD_ROM_FN(Qcrayon) + +static struct BurnRomInfo Qcrayon2RomDesc[] = { + { "d63-12", 0x040000, 0x0f445a38, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d63-13", 0x040000, 0x74455752, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d63-01", 0x080000, 0x872e38b4, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d63-11", 0x010000, 0x2c7ac9e5, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d63-03", 0x100000, 0xd24843af, BRF_GRA | TAITO_CHARS }, + + { "d63-06", 0x200000, 0x58b1e4a8, BRF_GRA | TAITO_SPRITESA }, + + { "d63-02", 0x100000, 0x162ae165, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Qcrayon2) +STD_ROM_FN(Qcrayon2) + +static struct BurnRomInfo QjinseiRomDesc[] = { + { "d48-09", 0x040000, 0xa573b68d, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d48-10", 0x040000, 0x37143a5b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d48-03", 0x100000, 0xfb5ea8dc, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d48-11", 0x010000, 0x656c5b54, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d48-04", 0x100000, 0x61e4b078, BRF_GRA | TAITO_CHARS }, + + { "d48-02", 0x100000, 0xa7b68e63, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "d48-01", 0x100000, 0x72a94b73, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "d48-05", 0x080000, 0x3fefd058, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Qjinsei) +STD_ROM_FN(Qjinsei) + +static struct BurnRomInfo QtorimonRomDesc[] = { + { "c41-04.bin", 0x020000, 0x0fbf5223, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c41-05.bin", 0x020000, 0x174bd5db, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "mask-51.bin", 0x020000, 0x12e14aca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "mask-52.bin", 0x020000, 0xb3ef66f3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c41-06.bin", 0x010000, 0x753a98d8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c41-02.bin", 0x020000, 0x05dcd36d, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c41-01.bin", 0x020000, 0x39ff043c, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c41-03.bin", 0x020000, 0xb2c18e89, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Qtorimon) +STD_ROM_FN(Qtorimon) + +static struct BurnRomInfo QuizhqRomDesc[] = { + { "c53-05.bin", 0x020000, 0xc798fc20, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c53-01.bin", 0x020000, 0xbf44c93e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c53-52.bin", 0x020000, 0x12e14aca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c53-51.bin", 0x020000, 0xb3ef66f3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c53-08.bin", 0x010000, 0x25187e81, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c53-03.bin", 0x020000, 0x47596e70, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c53-07.bin", 0x020000, 0x4f9fa82f, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c53-02.bin", 0x020000, 0xd704c6f4, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c53-06.bin", 0x020000, 0xf77f63fc, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c53-04.bin", 0x020000, 0x99890ad4, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Quizhq) +STD_ROM_FN(Quizhq) + +static struct BurnRomInfo QzchikyuRomDesc[] = { + { "d19-06.8", 0x020000, 0xde8c8e55, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d19-05.7", 0x020000, 0xc6d099d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d19-03.6", 0x080000, 0x5c1b92c0, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "d19-07.5", 0x010000, 0xa8935f84, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d19-02.10", 0x100000, 0xf2dce2f2, BRF_GRA | TAITO_CHARS }, + + { "d19-01.21", 0x100000, 0x6c4342d0, BRF_GRA | TAITO_SPRITESA }, + + { "d19-04.9", 0x080000, 0xd3c44905, BRF_SND | TAITO_YM2610A }, + + { "pal16l8b-d19-08.bin",0x000104, 0xc6240d10, BRF_OPT }, + { "pal16l8b-d19-09.bin",0x000104, 0x576f5db9, BRF_OPT }, + { "pal16l8b-d19-10.bin",0x000104, 0xea1232a5, BRF_OPT }, +}; + +STD_ROM_PICK(Qzchikyu) +STD_ROM_FN(Qzchikyu) + +static struct BurnRomInfo QzquestRomDesc[] = { + { "c92-06.8", 0x020000, 0x424be722, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c92-05.7", 0x020000, 0xda470f93, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c92-03.6", 0x080000, 0x1d697606, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c92-07.5", 0x010000, 0x3e313db9, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c92-02.10", 0x100000, 0x2daccecf, BRF_GRA | TAITO_CHARS }, + + { "c92-01.21", 0x100000, 0x9976a285, BRF_GRA | TAITO_SPRITESA }, + + { "c92-04.9", 0x080000, 0xe421bb43, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Qzquest) +STD_ROM_FN(Qzquest) + +static struct BurnRomInfo SsiRomDesc[] = { + { "c64_15-1.ic9", 0x040000, 0xce9308a6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c64_16-1.ic8", 0x040000, 0x470a483a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c64-09.13", 0x010000, 0x88d7f65c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c64-01.1", 0x100000, 0xa1b4f486, BRF_GRA | TAITO_SPRITESA }, + + { "c64-02.2", 0x020000, 0x3cb0b907, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Ssi) +STD_ROM_FN(Ssi) + +static struct BurnRomInfo Majest12RomDesc[] = { + { "c64-07.10", 0x020000, 0xf29ed5c9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c64-08.11", 0x020000, 0xddfd33d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c64-06.4", 0x020000, 0x18dc71ac, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c64-05.5", 0x020000, 0xb61866c0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c64-09.13", 0x010000, 0x88d7f65c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c64-01.1", 0x100000, 0xa1b4f486, BRF_GRA | TAITO_SPRITESA }, + + { "c64-02.2", 0x020000, 0x3cb0b907, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Majest12) +STD_ROM_FN(Majest12) + +static struct BurnRomInfo SolfigtrRomDesc[] = { + { "c91-05.59", 0x040000, 0xc1260e7c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c91-09.61", 0x040000, 0xd82b5266, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c91-07.62", 0x010000, 0xe471a05a, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c91-03.34", 0x100000, 0x8965da12, BRF_GRA | TAITO_CHARS }, + + { "c91-01.12", 0x100000, 0x0f3f4e00, BRF_GRA | TAITO_SPRITESA }, + { "c91-02.11", 0x100000, 0xe14ab98e, BRF_GRA | TAITO_SPRITESA }, + + { "c91-04.28", 0x080000, 0x390b1065, BRF_SND | TAITO_YM2610A }, + + { "pal16l8b-c74-06.ic48",0x000104, 0xc868dc16, BRF_OPT }, +}; + +STD_ROM_PICK(Solfigtr) +STD_ROM_FN(Solfigtr) + +static struct BurnRomInfo ThundfoxRomDesc[] = { + { "c28-13-1.51", 0x020000, 0xacb07013, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-16-1.40", 0x020000, 0x1e43d55b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-08.50", 0x020000, 0x38e038f1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-07.39", 0x020000, 0x24419abb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c28-14.3", 0x010000, 0x45ef3616, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c28-02.61", 0x080000, 0x6230a09d, BRF_GRA | TAITO_CHARS }, + + { "c28-01.63", 0x080000, 0x44552b25, BRF_GRA | TAITO_CHARSB }, + + { "c28-03.29", 0x080000, 0x51bdc7af, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c28-04.28", 0x080000, 0xba7ed535, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c28-06.41", 0x080000, 0xdb6983db, BRF_SND | TAITO_YM2610A }, + { "c28-05.42", 0x080000, 0xd3b238fa, BRF_SND | TAITO_YM2610B }, + + { "pal16l8b-b89-01.ic19",0x000104, 0x4095b97a, BRF_OPT }, + { "pal16l8b-b89-03.ic37",0x000104, 0x634592e2, BRF_OPT }, + { "pal16v8b-b89-04.ic33",0x000117, 0xfc136ae2, BRF_OPT }, + { "pal16l8b-c28-09.ic25",0x000104, 0x383e7305, BRF_OPT }, + { "pal16l8b-c28-10.ic26",0x000104, 0x47fccc07, BRF_OPT }, + { "pal16l8b-c28-11.ic35",0x000104, 0x33414fe8, BRF_OPT }, +}; + +STD_ROM_PICK(Thundfox) +STD_ROM_FN(Thundfox) + +static struct BurnRomInfo ThundfoxjRomDesc[] = { + { "c28-13-1.51", 0x020000, 0xacb07013, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-12-1.40", 0x020000, 0xf04db477, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-08.50", 0x020000, 0x38e038f1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-07.39", 0x020000, 0x24419abb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c28-14.3", 0x010000, 0x45ef3616, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c28-02.61", 0x080000, 0x6230a09d, BRF_GRA | TAITO_CHARS }, + + { "c28-01.63", 0x080000, 0x44552b25, BRF_GRA | TAITO_CHARSB }, + + { "c28-03.29", 0x080000, 0x51bdc7af, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c28-04.28", 0x080000, 0xba7ed535, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c28-06.41", 0x080000, 0xdb6983db, BRF_SND | TAITO_YM2610A }, + { "c28-05.42", 0x080000, 0xd3b238fa, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Thundfoxj) +STD_ROM_FN(Thundfoxj) + +static struct BurnRomInfo ThundfoxuRomDesc[] = { + { "c28-13-1.51", 0x020000, 0xacb07013, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-15-1.40", 0x020000, 0x874a84e1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-08.50", 0x020000, 0x38e038f1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c28-07.39", 0x020000, 0x24419abb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c28-14.3", 0x010000, 0x45ef3616, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c28-02.61", 0x080000, 0x6230a09d, BRF_GRA | TAITO_CHARS }, + + { "c28-01.63", 0x080000, 0x44552b25, BRF_GRA | TAITO_CHARSB }, + + { "c28-03.29", 0x080000, 0x51bdc7af, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c28-04.28", 0x080000, 0xba7ed535, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c28-06.41", 0x080000, 0xdb6983db, BRF_SND | TAITO_YM2610A }, + { "c28-05.42", 0x080000, 0xd3b238fa, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Thundfoxu) +STD_ROM_FN(Thundfoxu) + +static struct BurnRomInfo YesnojRomDesc[] = { + { "d20-05-2.2", 0x040000, 0x68adb929, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "d20-04-2.4", 0x040000, 0xa84762f8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d20-06.5", 0x010000, 0x3eb537dc, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "d20-01.11", 0x080000, 0x9d8a4d57, BRF_GRA | TAITO_CHARS }, + + { "d20-02.12", 0x080000, 0xe71a8e40, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "d20-03.13", 0x080000, 0x6a51a1b4, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, +}; + +STD_ROM_PICK(Yesnoj) +STD_ROM_FN(Yesnoj) + +static struct BurnRomInfo YuyugogoRomDesc[] = { + { "c83-10.3", 0x020000, 0x4d185d03, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c83-09.2", 0x020000, 0xf9892792, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c83-03.10", 0x100000, 0xeed9acc2, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "c83-11.1", 0x010000, 0x461e702a, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c83-05.21", 0x020000, 0xeca57fb1, BRF_GRA | TAITO_CHARS }, + + { "c83-01.12", 0x100000, 0x8bf0d416, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c83-02.11", 0x100000, 0x20bb1c15, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c83-04.5", 0x100000, 0x2600093a, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Yuyugogo) +STD_ROM_FN(Yuyugogo) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + if (TaitoNumMSM6295) MSM6295ROM = Next; Next += 0x40000; + TaitoMSM6295Rom = Next; Next += TaitoMSM6295RomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x020000; + TaitoZ80Ram1 = Next; Next += 0x002000; + TaitoSpriteRam = Next; Next += 0x010000; + TaitoSpriteRamBuffered = Next; Next += 0x010000; + TaitoSpriteRamDelayed = Next; Next += 0x010000; + TaitoSpriteExtension = Next; Next += 0x004000; + TaitoPaletteRam = Next; Next += 0x004000; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + if (TaitoNumCharB) TaitoCharsB = Next; Next += TaitoNumCharB * TaitoCharBWidth * TaitoCharBHeight; + TaitoCharsPivot = Next; Next += TaitoNumCharPivot * TaitoCharPivotWidth * TaitoCharPivotHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + TaitoPriorityMap = Next; Next += nScreenWidth * nScreenHeight; + TaitoF2SpriteList = (TaitoF2SpriteEntry*)Next; Next += 0x400 * sizeof(TaitoF2SpriteEntry); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 TaitoF2DoReset() +{ + TaitoDoReset(); + + YesnoDip = 0; + MjnquestInput = 0; + DriveoutSoundNibble = 0; + DriveoutOkiBank = 0; + + TaitoF2SpritesFlipScreen = 0; + TaitoF2SpriteBlendMode = 0; + TaitoF2TilePriority[0] = TaitoF2TilePriority[1] = TaitoF2TilePriority[2] = TaitoF2TilePriority[3] = TaitoF2TilePriority[4] = 0; + TaitoF2SpritePriority[0] = TaitoF2SpritePriority[1] = TaitoF2SpritePriority[2] = TaitoF2SpritePriority[3] = 0; + + return 0; +} + +static void TaitoF2SpriteBankWrite(INT32 Offset, UINT16 Data) +{ + INT32 i, j; + + if (Offset < 2) return; + if (Offset < 4) { + j = (Offset & 1) << 1; + i = Data << 11; + TaitoF2SpriteBankBuffered[j + 0] = i; + TaitoF2SpriteBankBuffered[j + 1] = i + 0x400; + } else { + i = Data << 10; + TaitoF2SpriteBankBuffered[Offset] = i; + } +} + +UINT8 __fastcall Cameltry68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Cameltry68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x813fff) + + switch (a) { + case 0x320000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Cameltry68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + case 0x300018: { + INT32 Temp = TaitoAnalogPort0 >> 6; + if (Temp >= 0x14 && Temp < 0x80) Temp = 0x14; + if (Temp <= 0x3ec && Temp > 0x80) Temp = 0x3ec; + return Temp; + } + + case 0x30001c: { + INT32 Temp = TaitoAnalogPort1 >> 6; + if (Temp >= 0x14 && Temp < 0x80) Temp = 0x14; + if (Temp <= 0x3ec && Temp > 0x80) Temp = 0x3ec; + return Temp; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Cameltry68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x813fff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0280GRDCtrlWordWrite_Map(0xa02000) + TC0360PRIHalfWordWrite_Map(0xd00000) + + if (a >= 0x814000 && a <= 0x814fff) return; //??? + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Deadconx68KReadByte(UINT32 a) +{ + switch (a) { + case 0x700001: { + return TaitoDip[0]; + } + + case 0x700003: { + return TaitoDip[1]; + } + + case 0x700005: { + return TaitoInput[2]; + } + + case 0x700007: { + return 0xff; + } + + case 0x70000b: { + return TaitoInput[0]; + } + + case 0x70000d: { + return TaitoInput[1]; + } + + case 0x70000f: { + return 0xff; + } + + case 0x700011: { + return 0xff; + } + + case 0xa00002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Deadconx68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x700007: { + // coin write + return; + } + + case 0xa00000: { + TC0140SYTPortWrite(d); + return; + } + + case 0xa00002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Deadconx68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Deadconx68KWriteWord(UINT32 a, UINT16 d) +{ + TC0480SCPCtrlWordWrite_Map(0x430000) + TC0360PRIHalfWordWrite_Map(0x500000) + + switch (a) { + case 0x300000: + case 0x300002: + case 0x300004: + case 0x300006: + case 0x300008: + case 0x30000a: + case 0x30000c: + case 0x30000e: { + TaitoF2SpriteBankWrite((a - 0x300000) >> 1, d); + return; + } + + case 0x700006: { + // coin write + return; + } + + case 0x700008: + case 0x700012: + case 0x700014: + case 0x700016: + case 0x700018: { + // ??? + return; + } + + case 0x800000: { + // watchdog + return; + } + + case 0x900000: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Dinorex68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x300000) + + switch (a) { + case 0xa00002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dinorex68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x900000, 0x90ffff) + + switch (a) { + case 0xa00000: { + TC0140SYTPortWrite(d); + return; + } + + case 0xa00002: { + TC0140SYTCommWrite(d); + return; + } + + case 0xb00000: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Dinorex68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dinorex68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x300000) + TC0360PRIHalfWordWrite_Map(0x700000) + TC0100SCN0WordWrite_Map(0x900000, 0x90ffff) + TC0100SCN0CtrlWordWrite_Map(0x920000) + + switch (a) { + case 0xb00000: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Dondokod68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + case 0x320002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dondokod68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x320000: + case 0x320001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320002: + case 0x320003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Dondokod68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dondokod68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0280GRDCtrlWordWrite_Map(0xa02000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x360000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Driftout68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0xb00000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Driftout68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x200000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x200002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Driftout68KReadWord(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0xb00000) + + switch (a) { + case 0x200000: { + return 0; + } + + case 0xb00018: + case 0xb0001a: { + //driftout_paddle_r + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Driftout68KWriteWord(UINT32 a, UINT16 d) +{ + TC0430GRWCtrlWordWrite_Map(0x402000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordSwapWrite_Map(0xa00000) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0xa00000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +void __fastcall Driveout68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x200000: { + DriveoutSoundNibble = d & 1; + return; + } + + case 0x200002: { + if (!DriveoutSoundNibble) { + TaitoSoundLatch = (d & 0x0f) | (TaitoSoundLatch & 0xf0); + } else { + TaitoSoundLatch = ((d << 4) & 0xf0) | (TaitoSoundLatch & 0x0f); + ZetOpen(0); + ZetRaiseIrq(0); + ZetClose(); + } + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall Finalb68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Finalb68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x320001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Finalb68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + case 0x200002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Finalb68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + + if (a >= 0x810000 && a <= 0x81ffff) return; // NOP + + switch (a) { + case 0x200000: + case 0x200002: { + TC0110PCRWordWrite(0, (a - 0x200000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Footchmp68KReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Footchmp68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0xa00001: { + TC0140SYTPortWrite(d); + return; + } + + case 0xa00003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Footchmp68KReadWord(UINT32 a) +{ + switch (a) { + case 0x700000: { + return TaitoDip[0]; + } + + case 0x700002: { + return TaitoDip[1]; + } + + case 0x700004: { + return TaitoInput[2]; + } + + case 0x70000a: { + return TaitoInput[0]; + } + + case 0x70000c: { + return TaitoInput[1]; + } + + case 0x70000e: { + return TaitoInput[3]; + } + + case 0x700010: { + return TaitoInput[4]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0xffff; +} + +void __fastcall Footchmp68KWriteWord(UINT32 a, UINT16 d) +{ + TC0480SCPCtrlWordWrite_Map(0x430000) + TC0360PRIHalfWordWrite_Map(0x500000) + + switch (a) { + case 0x300000: + case 0x300002: + case 0x300004: + case 0x300006: + case 0x300008: + case 0x30000a: + case 0x30000c: + case 0x30000e: { + TaitoF2SpriteBankWrite((a - 0x300000) >> 1, d); + return; + } + + case 0x700006: + case 0x700008: + case 0x700012: + case 0x700014: + case 0x700016: + case 0x700018: { + return; + } + + case 0x800000: { + // watchdog + return; + } + + case 0x900000: { + // ???? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Growl68KReadByte(UINT32 a) +{ + switch (a) { + case 0x320001: { + return TaitoInput[0]; + } + + case 0x320003: { + return TaitoInput[1]; + } + + case 0x400002: { + return TC0140SYTCommRead(); + } + + case 0x508000: { + return TaitoInput[4]; + } + + case 0x508001: { + return TaitoInput[3]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Growl68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x400000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x400002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Growl68KReadWord(UINT32 a) +{ + switch (a) { + case 0x300000: { + return TaitoDip[0]; + } + + case 0x300002: { + return TaitoDip[1]; + } + + case 0x320000: { + return TaitoInput[0]; + } + + case 0x320004: { + return TaitoInput[2]; + } + + case 0x50c000: { + return TaitoInput[5]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Growl68KWriteWord(UINT32 a, UINT16 d) +{ + TC0360PRIHalfWordWrite_Map(0xb00000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + + switch (a) { + case 0x300004: { + // coin write + return; + } + + case 0x340000: { + // watchdog + return; + } + + case 0x500000: + case 0x500002: + case 0x500004: + case 0x500006: + case 0x500008: + case 0x50000a: + case 0x50000c: + case 0x50000e: { + TaitoF2SpriteBankWrite((a - 0x500000) >> 1, d); + return; + } + + case 0x504000: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Gunfront68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordSwapRead_Map(0x300000) + + switch (a) { + case 0x320002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Gunfront68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordSwapWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x320000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320002: { + TC0140SYTCommWrite(d); + return; + } + + case 0xa00000: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Gunfront68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Gunfront68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordSwapWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Koshien68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Koshien68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x320000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x340000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Koshien68KReadWord(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Koshien68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0xa20000: { + TaitoF2SpriteBankBuffered[0] = 0x0000; + TaitoF2SpriteBankBuffered[1] = 0x0400; + TaitoF2SpriteBankBuffered[2] = ((d & 0x00f) + 1) * 0x800; + TaitoF2SpriteBankBuffered[4] = (((d & 0x0f0) >> 4) + 1) * 0x800; + TaitoF2SpriteBankBuffered[6] = (((d & 0xf00) >> 8) + 1) * 0x800; + TaitoF2SpriteBankBuffered[3] = TaitoF2SpriteBankBuffered[2] + 0x400; + TaitoF2SpriteBankBuffered[5] = TaitoF2SpriteBankBuffered[4] + 0x400; + TaitoF2SpriteBankBuffered[7] = TaitoF2SpriteBankBuffered[6] + 0x400; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Liquidk68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Liquidk68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x320001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x320003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Liquidk68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x300000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Liquidk68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x300000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Megablst68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x120000) + + if (a >= 0x180000 && a <= 0x180fff) { + return MegabCChipRead((a - 0x180000) >> 1); + } + + switch (a) { + case 0x100002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Megablst68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x120000) + TC0360PRIHalfWordWrite_Map(0x400000) + TC0100SCN0ByteWrite_Map(0x600000, 0x60ffff) + + if (a >= 0x180000 && a <= 0x180fff) { + MegabCChipWrite((a - 0x180000) >> 1, d); + return; + } + + switch (a) { + case 0x100000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x100002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Megablst68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x120000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Megablst68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x120000) + TC0360PRIHalfWordWrite_Map(0x400000) + TC0100SCN0WordWrite_Map(0x600000, 0x60ffff) + TC0100SCN0CtrlWordWrite_Map(0x620000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Metalb68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordSwapRead_Map(0x800000) + + switch (a) { + case 0x900002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Metalb68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordSwapWrite_Map(0x800000) + + switch (a) { + case 0x900000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x900002: { + TC0140SYTCommWrite(d); + return; + } + + case 0xa00000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Metalb68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Metalb68KWriteWord(UINT32 a, UINT16 d) +{ + TC0480SCPCtrlWordWrite_Map(0x530000) + TC0360PRIHalfWordWrite_Map(0x600000) + TC0510NIOHalfWordSwapWrite_Map(0x800000) + + switch (a) { + case 0x42000c: + case 0x42000e: { + //??? + return; + } + + case 0xa00000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Mjnquest68KReadByte(UINT32 a) +{ + switch (a) { + case 0x300000: { + return TaitoInput[4]; + } + + case 0x300001: { + return TaitoDip[0]; + } + + case 0x300002: { + return TaitoInput[5]; + } + + case 0x300003: { + return TaitoDip[1]; + } + + case 0x360002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Mjnquest68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x400000, 0x40ffff) + + switch (a) { + case 0x330000: + case 0x330001: { + //nop + return; + } + + case 0x360000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x360002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x360005: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Mjnquest68KReadWord(UINT32 a) +{ + switch (a) { + case 0x310000: { + switch (MjnquestInput) { + case 0x01: return TaitoInput[0]; + case 0x02: return TaitoInput[1]; + case 0x04: return TaitoInput[2]; + case 0x08: return TaitoInput[3]; + case 0x10: return 0xff; + } + return 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Mjnquest68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x400000, 0x40ffff) + TC0100SCN0CtrlWordWrite_Map(0x420000) + + switch (a) { + case 0x200000: + case 0x200002: { + TC0110PCRWordWrite(0, (a - 0x200000) >> 1, d); + return; + } + + case 0x200004: { + //nop + return; + } + + case 0x300000: { + //??? + return; + } + + case 0x320000: { + MjnquestInput = d >> 6; + return; + } + + case 0x350000: { + //nop + return; + } + + case 0x380000: { + TC0100SCNSetGfxBank(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Ninjak68KReadByte(UINT32 a) +{ + switch (a) { + case 0x300000: { + return TaitoDip[0]; + } + + case 0x300002: { + return TaitoDip[1]; + } + + case 0x300004: { + return TaitoInput[0]; + } + + case 0x300006: { + return TaitoInput[1]; + } + + case 0x300008: { + return TaitoInput[3]; + } + + case 0x30000a: { + return TaitoInput[4]; + } + + case 0x30000c: { + return TaitoInput[2]; + } + + case 0x400002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ninjak68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x30000e: { + //coin write + return; + } + + case 0x300010: { + //??? + return; + } + + case 0x400000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x400002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ninjak68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ninjak68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x300000: + case 0x300012: + case 0x300014: + case 0x300016: + case 0x300018: { + //??? + return; + } + + case 0x380000: { + //watchdog + return; + } + + case 0x600000: + case 0x600002: + case 0x600004: + case 0x600006: + case 0x600008: + case 0x60000a: + case 0x60000c: + case 0x60000e: { + TaitoF2SpriteBankWrite((a - 0x600000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Pulirula68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0xb00000) + + switch (a) { + case 0x200002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Pulirula68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x200000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x200002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Pulirula68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Pulirula68KWriteWord(UINT32 a, UINT16 d) +{ + TC0430GRWCtrlWordWrite_Map(0x402000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordSwapWrite_Map(0xa00000) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x500000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qcrayon68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0xa00000) + + switch (a) { + case 0x500002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qcrayon68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x900000, 0x90ffff) + TC0510NIOHalfWordWrite_Map(0xa00000) + + switch (a) { + case 0x200000: { + //??? + return; + } + + case 0x500000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x500002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qcrayon68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qcrayon68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x900000, 0x90ffff) + TC0100SCN0CtrlWordWrite_Map(0x920000) + TC0510NIOHalfWordWrite_Map(0xa00000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qcrayon268KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x700000) + + switch (a) { + case 0xa00002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qcrayon268KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x500000, 0x50ffff) + TC0510NIOHalfWordWrite_Map(0x700000) + + switch (a) { + case 0x800000: { + //??? + return; + } + + case 0xa00000: { + TC0140SYTPortWrite(d); + return; + } + + case 0xa00002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qcrayon268KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qcrayon268KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x500000, 0x50ffff) + TC0100SCN0CtrlWordWrite_Map(0x520000) + TC0510NIOHalfWordWrite_Map(0x700000) + TC0360PRIHalfWordWrite_Map(0x900000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qjinsei68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0xb00000) + + switch (a) { + case 0x200002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qjinsei68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x200000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x200002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qjinsei68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qjinsei68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xa00000) + TC0510NIOHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x500000: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qtorimon68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x500000) + + switch (a) { + case 0x600002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qtorimon68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x500000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x600000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x600002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qtorimon68KReadWord(UINT32 a) +{ + switch (a) { + case 0x200002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qtorimon68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x500000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + + if (a >= 0x810000 && a <= 0x81ffff) return; // NOP + + switch (a) { + case 0x200000: + case 0x200002: { + TC0110PCRWordWrite(0, (a - 0x200000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Quizhq68KReadByte(UINT32 a) +{ + switch (a) { + case 0x500001: { + return TaitoDip[1]; + } + + case 0x500003: { + return TaitoInput[0]; + } + + case 0x580001: { + return TaitoDip[0]; + } + + case 0x580003: { + return TaitoInput[1]; + } + + case 0x580005: { + return TaitoInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Quizhq68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x500005: { + //coin write + return; + } + + case 0x500007: { + //??? + return; + } + + case 0x580007: { + //nop + return; + } + + case 0x600001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x600003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Quizhq68KReadWord(UINT32 a) +{ + switch (a) { + case 0x500000: { + return TaitoDip[1]; + } + + case 0x500002: { + return TaitoInput[0]; + } + + case 0x580000: { + return TaitoDip[0]; + } + + case 0x580002: { + return TaitoInput[1]; + } + + case 0x580004: { + return TaitoInput[2]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Quizhq68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + + if (a >= 0x810000 && a <= 0x81ffff) return; // NOP + + switch (a) { + case 0x200000: + case 0x200002: { + TC0110PCRWordWrite(0, (a - 0x200000) >> 1, d); + return; + } + + case 0x680000: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qzchikyu68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x200000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qzchikyu68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0ByteWrite_Map(0x700000, 0x70ffff) + + switch (a) { + case 0x300001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x300003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qzchikyu68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qzchikyu68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0WordWrite_Map(0x700000, 0x70ffff) + TC0100SCN0CtrlWordWrite_Map(0x720000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Qzquest68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x200000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qzquest68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0ByteWrite_Map(0x700000, 0x70ffff) + + switch (a) { + case 0x300001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x300003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Qzquest68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Qzquest68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0WordWrite_Map(0x700000, 0x70ffff) + TC0100SCN0CtrlWordWrite_Map(0x720000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Solfigtr68KReadByte(UINT32 a) +{ + switch (a) { + case 0x300001: { + return TaitoDip[0]; + } + + case 0x300003: { + return TaitoDip[1]; + } + + case 0x320001: { + return TaitoInput[0]; + } + + case 0x320003: { + return TaitoInput[1]; + } + + case 0x320005: { + return TaitoInput[2]; + } + + case 0x400002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Solfigtr68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x300005: { + //coin write + return; + } + + case 0x400000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x400002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x504000: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Solfigtr68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Solfigtr68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + TC0360PRIHalfWordWrite_Map(0xb00000) + + switch (a) { + case 0x300006: { + //??? + return; + } + + case 0x320006: { + //??? + return; + } + + case 0x340000: { + //watchdog + return; + } + + case 0x500000: + case 0x500002: + case 0x500004: + case 0x500006: + case 0x500008: + case 0x50000a: + case 0x50000c: + case 0x50000e: { + TaitoF2SpriteBankWrite((a - 0x500000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Ssi68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x100000) + + switch (a) { + case 0x400002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ssi68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x100000) + TC0100SCN0ByteWrite_Map(0x600000, 0x60ffff) + + switch (a) { + case 0x400000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x400002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x500000: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Ssi68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Ssi68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x100000) + TC0100SCN0ByteWrite_Map(0x600000, 0x60ffff) + TC0100SCN0CtrlWordWrite_Map(0x620000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Thundfox68KReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Thundfox68KWriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0100SCN0ByteWrite_Map(0x400000, 0x40ffff) + TC0360PRIHalfWordWrite_Map(0x800000) + + switch (a) { + case 0x220000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x220002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Thundfox68KReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Thundfox68KWriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0100SCN0WordWrite_Map(0x400000, 0x40ffff) + TC0100SCN0CtrlWordWrite_Map(0x420000) + TC0100SCN1WordWrite_Map(0x500000, 0x50ffff) + TC0100SCN1CtrlWordWrite_Map(0x520000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Yesnoj68KReadByte(UINT32 a) +{ + if (a >= 0x700000 && a <= 0x70001f) return 0; + + switch (a) { + case 0x800002: { + return TC0140SYTCommRead(); + } + + case 0xa00001: { + return TaitoInput[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Yesnoj68KWriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x500000, 0x50ffff) + + switch (a) { + case 0x700015: + case 0x70001b: + case 0x70001d: + case 0x70001f: { + //??? + return; + } + + case 0x800000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x800002: { + TC0140SYTCommWrite(d); + return; + } + + case 0x900003: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Yesnoj68KReadWord(UINT32 a) +{ + switch (a) { + case 0xa00004: { + return TaitoInput[1]; + } + + case 0xb00000: { + YesnoDip = 1 - YesnoDip; + + if (YesnoDip) { + return TaitoDip[0]; + } else { + return TaitoDip[1]; + } + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Yesnoj68KWriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x500000, 0x50ffff) + TC0100SCN0CtrlWordWrite_Map(0x520000) + + switch (a) { + case 0x900002: + case 0x900006: + case 0xa00006: + case 0xc00000: + case 0xd00000: { + //nop + return; + } + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Yuyugogo68KReadByte(UINT32 a) +{ + TC0510NIOHalfWordRead_Map(0x200000) + + switch (a) { + case 0x400002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Yuyugogo68KWriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0ByteWrite_Map(0x800000, 0x80ffff) + + switch (a) { + case 0x400000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x400002: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Yuyugogo68KReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Yuyugogo68KWriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordWrite_Map(0x200000) + TC0100SCN0WordWrite_Map(0x800000, 0x80ffff) + TC0100SCN0CtrlWordWrite_Map(0x820000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall TaitoF2Z80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe002: { + return BurnYM2610Read(2); + } + + case 0xe200: { + // NOP + return 0; + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + case 0xea00: { + // NOP + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoF2Z80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xe400: + case 0xe401: + case 0xe402: + case 0xe403: { + return; + } + + case 0xe600: { + return; + } + + case 0xee00: { + return; + } + + case 0xf000: { + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 7; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall CamltryaZ80Read(UINT16 a) +{ + switch (a) { + case 0x9000: { + return BurnYM2203Read(0, 0); + } + + case 0xa001: { + return TC0140SYTSlaveCommRead(); + } + + case 0xb000: { + return MSM6295ReadStatus(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall CamltryaZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x9001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xa000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xa001: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xb000: + case 0xb001: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall DriveoutZ80Read(UINT16 a) +{ + switch (a) { + case 0x9800: { + return MSM6295ReadStatus(0); + } + + case 0xa000: { + return TaitoSoundLatch; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall DriveoutZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + if ((d & 4)) { + DriveoutOkiBank = (d & 3); + memcpy(MSM6295ROM, TaitoMSM6295Rom + (DriveoutOkiBank * 0x40000), 0x40000); + } + return; + } + + case 0x9800: { + MSM6295Command(0, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 PivotPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 PivotXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 PivotYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 YuyugogoCharPlaneOffsets[1] = { 0 }; +static INT32 YuyugogoCharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 YuyugogoCharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 TC0480SCPCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TC0480SCPCharXOffsets[16] = { 4, 0, 20, 16, 12, 8, 28, 24, 36, 32, 52, 48, 44, 40, 60, 56 }; +static INT32 TC0480SCPCharYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 SpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 SpriteXOffsets[16] = { 4, 0, 12, 8, 20, 16, 28, 24, 36, 32, 44, 40, 52, 48, 60, 56 }; +static INT32 SpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 FinalbSpritePlaneOffsets[6] = { 0x800000, 0x800001, 0, 1, 2, 3 }; +static INT32 FinalbSpriteXOffsets[16] = { 12, 8, 4, 0, 28, 24, 20, 16, 44, 40, 36, 32, 60, 56, 52, 48 }; +static INT32 FinalbSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + +static void TaitoF2FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 TaitoF2SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (24000000 / 6); +} + +static double TaitoF2GetTime() +{ + return (double)ZetTotalCycles() / (24000000 / 6); +} + +static INT32 CamltryaSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (24000000 / 4); +} + +static double CamltryaGetTime() +{ + return (double)ZetTotalCycles() / (24000000 / 4); +} + +static void TaitoF2SoundInit() +{ + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(TaitoF2Z80Read); + ZetSetWriteHandler(TaitoF2Z80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2610Init(24000000 / 3, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoF2FMIRQHandler, TaitoF2SynchroniseStream, TaitoF2GetTime, 0); + BurnTimerAttachZet(24000000 / 6); +} + +static void SwitchToMusashi() +{ + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } +} + +static void TaitoF2Init() +{ + GenericTilesInit(); + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoF2SpritesDisabled = 1; + TaitoF2SpritesActiveArea = 0; + TaitoXOffset = 0; + TaitoF2SpriteType = 0; + + TaitoF2SpriteBufferFunction = TaitoF2NoBuffer; + TaitoDrawFunction = TaitoF2Draw; + + for (INT32 i = 0; i < 8; i++) { + TaitoF2SpriteBankBuffered[i] = 0x400 * i; + TaitoF2SpriteBank[i] = TaitoF2SpriteBankBuffered[i]; + } + + nTaitoCyclesTotal[0] = (24000000 / 2) / 60; + nTaitoCyclesTotal[1] = (24000000 / 6) / 60; +} + +static INT32 CameltryInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x1000; + + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0140SYTInit(); + TC0220IOCInit(); + TC0280GRDInit(-16, -16, TaitoCharsPivot); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x813fff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TC0280GRDRam , 0xa00000, 0xa01fff, SM_RAM); + SekSetReadByteHandler(0, Cameltry68KReadByte); + SekSetWriteByteHandler(0, Cameltry68KWriteByte); + SekSetReadWordHandler(0, Cameltry68KReadWord); + SekSetWriteWordHandler(0, Cameltry68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoDrawFunction = CameltryDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 CamltryaInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumYM2610 = 0; + TaitoNumYM2203 = 1; + TaitoNumMSM6295 = 1; + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x1000; + + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0140SYTInit(); + TC0220IOCInit(); + TC0280GRDInit(-16, -16, TaitoCharsPivot); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x813fff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TC0280GRDRam , 0xa00000, 0xa01fff, SM_RAM); + SekSetReadByteHandler(0, Cameltry68KReadByte); + SekSetWriteByteHandler(0, Cameltry68KWriteByte); + SekSetReadWordHandler(0, Cameltry68KReadWord); + SekSetWriteWordHandler(0, Cameltry68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(CamltryaZ80Read); + ZetSetWriteHandler(CamltryaZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 24000000 / 8, &TaitoF2FMIRQHandler, CamltryaSynchroniseStream, CamltryaGetTime, 0); + BurnTimerAttachZet(24000000 / 4); + + MSM6295Init(0, (4224000 / 4) / 132 , 100.0, 1); + + nTaitoCyclesTotal[1] = (24000000 / 4) / 60; + + TaitoXOffset = 3; + TaitoDrawFunction = CameltryDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 DeadconxInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = TC0480SCPCharPlaneOffsets; + TaitoCharXOffsets = TC0480SCPCharXOffsets; + TaitoCharYOffsets = TC0480SCPCharYOffsets; + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "deadconxj")) { + TC0480SCPInit(TaitoNumChar, 3, 0x34, -5, -1, 0, 26); + } else { + TC0480SCPInit(TaitoNumChar, 3, 0x1e, 8, -1, 0, 0); + } + + TC0140SYTInit(); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x600000, 0x601fff, SM_RAM); + SekSetReadByteHandler(0, Deadconx68KReadByte); + SekSetWriteByteHandler(0, Deadconx68KWriteByte); + SekSetReadWordHandler(0, Deadconx68KReadWord); + SekSetWriteWordHandler(0, Deadconx68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoDrawFunction = FootchmpDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 DinorexInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0xc000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x2fffff, SM_ROM); + SekMapMemory(TaitoSpriteExtension , 0x400000, 0x400fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x500000, 0x501fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0x600000, 0x60ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x900000, 0x90ffff, SM_READ); + SekSetReadByteHandler(0, Dinorex68KReadByte); + SekSetWriteByteHandler(0, Dinorex68KWriteByte); + SekSetReadWordHandler(0, Dinorex68KReadWord); + SekSetWriteWordHandler(0, Dinorex68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteType = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 DondokodInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x4000; + + TaitoNumChar = 0x4000; + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0220IOCInit(); + TC0280GRDInit(-16, -16, TaitoCharsPivot); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TC0280GRDRam , 0xa00000, 0xa01fff, SM_RAM); + SekSetReadByteHandler(0, Dondokod68KReadByte); + SekSetWriteByteHandler(0, Dondokod68KWriteByte); + SekSetReadWordHandler(0, Dondokod68KReadWord); + SekSetWriteWordHandler(0, Dondokod68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + TaitoDrawFunction = TaitoF2PivotDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 DriftoutInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x4000; + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0140SYTInit(); + TC0360PRIInit(); + TC0430GRWInit(-16, 0, TaitoCharsPivot); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TC0430GRWRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Driftout68KReadByte); + SekSetWriteByteHandler(0, Driftout68KWriteByte); + SekSetReadWordHandler(0, Driftout68KReadWord); + SekSetWriteWordHandler(0, Driftout68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoDrawFunction = DriftoutDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 DriveoutInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumYM2610 = 0; + TaitoNumMSM6295 = 1; + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x4000; + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + TaitoMSM6295RomSize = 0x100000; + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + UINT8 *TempRom = (UINT8*)malloc(0x100000); + memcpy(TempRom, TaitoMSM6295Rom, 0x100000); + memset(TaitoMSM6295Rom, 0, 0x100000); + memcpy(TaitoMSM6295Rom + 0x00000, TempRom + 0x00000, 0x20000); + memcpy(TaitoMSM6295Rom + 0x20000, TempRom + 0x80000, 0x20000); + memcpy(TaitoMSM6295Rom + 0x40000, TempRom + 0x20000, 0x20000); + memcpy(TaitoMSM6295Rom + 0x60000, TempRom + 0x80000, 0x20000); + memcpy(TaitoMSM6295Rom + 0x80000, TempRom + 0x40000, 0x20000); + memcpy(TaitoMSM6295Rom + 0xa0000, TempRom + 0x80000, 0x20000); + memcpy(TaitoMSM6295Rom + 0xc0000, TempRom + 0x60000, 0x20000); + memcpy(TaitoMSM6295Rom + 0xe0000, TempRom + 0x80000, 0x20000); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0360PRIInit(); + TC0430GRWInit(-16, 0, TaitoCharsPivot); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TC0430GRWRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Driftout68KReadByte); + SekSetWriteByteHandler(0, Driveout68KWriteByte); + SekSetReadWordHandler(0, Driftout68KReadWord); + SekSetWriteWordHandler(0, Driftout68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(DriveoutZ80Read); + ZetSetWriteHandler(DriveoutZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x87ff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x87ff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x87ff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + MSM6295Init(0, 1056000 / 132 , 100.0, 0); + + TaitoXOffset = 3; + TaitoDrawFunction = DriftoutDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 FinalbInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 6; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = FinalbSpritePlaneOffsets; + TaitoSpriteAXOffsets = FinalbSpriteXOffsets; + TaitoSpriteAYOffsets = FinalbSpriteYOffsets; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + TaitoNumSpriteA = 0x0000; // Need to load these outside of the usual routine + + if (TaitoLoadRoms(1)) return 1; + + TC0110PCRInit(1, 0x1000); + TC0100SCNInit(0, TaitoNumChar, 1, 8, 0, NULL); + TC0140SYTInit(); + TC0220IOCInit(); + + // Load and decode Sprites + INT32 nRet; + TaitoNumSpriteA = 0x2000; + UINT8 *TempRom = (UINT8*)malloc(0x200000); + memset(TempRom, 0, 0x200000); + nRet = BurnLoadRom(TempRom + 0x000000 , 5, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(TempRom + 0x000001 , 6, 2); if (nRet != 0) return 1; + nRet = BurnLoadRom(TempRom + 0x180000 , 7, 1); if (nRet != 0) return 1; + + INT32 Offset = 0x100000; + UINT8 Data, d1, d2, d3, d4; + for (INT32 i = 0x180000; i < 0x200000; i++) { + Data = TempRom[i]; + d1 = (Data >> 0) & 3; + d2 = (Data >> 2) & 3; + d3 = (Data >> 4) & 3; + d4 = (Data >> 6) & 3; + + TempRom[Offset] = (d3 << 2) | (d4 << 6); + Offset++; + + TempRom[Offset] = (d1 << 2) | (d2 << 6); + Offset++; + } + GfxDecode(TaitoNumSpriteA, TaitoSpriteANumPlanes, TaitoSpriteAWidth, TaitoSpriteAHeight, FinalbSpritePlaneOffsets, FinalbSpriteXOffsets, FinalbSpriteYOffsets, TaitoSpriteAModulo, TempRom, TaitoSpritesA); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Finalb68KReadByte); + SekSetWriteByteHandler(0, Finalb68KWriteByte); + SekSetReadWordHandler(0, Finalb68KReadWord); + SekSetWriteWordHandler(0, Finalb68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 1; + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + TaitoDrawFunction = FinalbDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 FootchmpInit() +{ + INT32 nLen; + + TaitoF2Init(); + + Footchmp = 1; + + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = TC0480SCPCharPlaneOffsets; + TaitoCharXOffsets = TC0480SCPCharXOffsets; + TaitoCharYOffsets = TC0480SCPCharYOffsets; + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "hthero")) { + TC0480SCPInit(TaitoNumChar, 3, 0x33, -4, -1, 0, 24); + } else { + TC0480SCPInit(TaitoNumChar, 3, 0x1d, 8, -1, 0, 0); + } + TC0140SYTInit(); + TC0360PRIInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x600000, 0x601fff, SM_RAM); + SekSetReadByteHandler(0, Footchmp68KReadByte); + SekSetWriteByteHandler(0, Footchmp68KWriteByte); + SekSetReadWordHandler(0, Footchmp68KReadWord); + SekSetWriteWordHandler(0, Footchmp68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteBufferFunction = TaitoF2FullBufferDelayed; + TaitoDrawFunction = FootchmpDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 GrowlInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Growl68KReadByte); + SekSetWriteByteHandler(0, Growl68KWriteByte); + SekSetReadWordHandler(0, Growl68KReadWord); + SekSetWriteWordHandler(0, Growl68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 GunfrontInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Gunfront68KReadByte); + SekSetWriteByteHandler(0, Gunfront68KWriteByte); + SekSetReadWordHandler(0, Gunfront68KReadWord); + SekSetWriteWordHandler(0, Gunfront68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 KoshienInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 1, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Koshien68KReadByte); + SekSetWriteByteHandler(0, Koshien68KWriteByte); + SekSetReadWordHandler(0, Koshien68KReadWord); + SekSetWriteWordHandler(0, Koshien68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 1; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 LiquidkInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x4000; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0220IOCInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Liquidk68KReadByte); + SekSetWriteByteHandler(0, Liquidk68KWriteByte); + SekSetReadWordHandler(0, Liquidk68KReadWord); + SekSetWriteWordHandler(0, Liquidk68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 MegablstInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x4000; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0220IOCInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x300000, 0x301fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x600000, 0x60ffff, SM_READ); + SekMapMemory(Taito68KRam1 + 0x10000 , 0x610000, 0x61ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x800000, 0x80ffff, SM_RAM); + SekSetReadByteHandler(0, Megablst68KReadByte); + SekSetWriteByteHandler(0, Megablst68KWriteByte); + SekSetReadWordHandler(0, Megablst68KReadWord); + SekSetWriteWordHandler(0, Megablst68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + MegabCChipInit(); + + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 MetalbInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = TC0480SCPCharPlaneOffsets; + TaitoCharXOffsets = TC0480SCPCharXOffsets; + TaitoCharYOffsets = TC0480SCPCharYOffsets; + TaitoNumChar = 0x2000; + + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0480SCPInit(TaitoNumChar, 3, 0x32, -4, 1, 0, 24); + TC0480SCPSetColourBase(256); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x500000, 0x50ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x703fff, SM_RAM); + SekSetReadByteHandler(0, Metalb68KReadByte); + SekSetWriteByteHandler(0, Metalb68KWriteByte); + SekSetReadWordHandler(0, Metalb68KReadWord); + SekSetWriteWordHandler(0, Metalb68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoDrawFunction = MetalbDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 MjnquestInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x10000; + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + // Load and decode Sprites + INT32 nRet; + UINT8 *TempRom = (UINT8*)malloc(TaitoSpriteARomSize); + memset(TempRom, 0, TaitoSpriteARomSize); + nRet = BurnLoadRom(TempRom + 0x000000 , 6, 1); if (nRet != 0) return 1; + for (UINT32 i = 0; i < TaitoSpriteARomSize; i += 2) { + INT32 Temp = TempRom[i]; + TempRom[i + 0] = (TempRom[i + 1] >> 4) | (TempRom[i + 1] << 4); + TempRom[i + 1] = (Temp >> 4) | (Temp << 4); + } + GfxDecode(TaitoNumSpriteA, TaitoSpriteANumPlanes, TaitoSpriteAWidth, TaitoSpriteAHeight, TaitoSpriteAPlaneOffsets, TaitoSpriteAXOffsets, TaitoSpriteAYOffsets, TaitoSpriteAModulo, TempRom, TaitoSpritesA); + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + + TC0110PCRInit(1, 0x1000); + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0100SCNSetGfxMask(0, 0x7fff); + TC0140SYTInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x110000, 0x12ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x500000, 0x50ffff, SM_RAM); + SekSetReadByteHandler(0, Mjnquest68KReadByte); + SekSetWriteByteHandler(0, Mjnquest68KWriteByte); + SekSetReadWordHandler(0, Mjnquest68KReadWord); + SekSetWriteWordHandler(0, Mjnquest68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoDrawFunction = FinalbDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 NinjakInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x4000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Ninjak68KReadByte); + SekSetWriteByteHandler(0, Ninjak68KWriteByte); + SekSetReadWordHandler(0, Ninjak68KReadWord); + SekSetWriteWordHandler(0, Ninjak68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 PulirulaInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharPivotModulo = 0x100; + TaitoCharPivotNumPlanes = 4; + TaitoCharPivotWidth = 8; + TaitoCharPivotHeight = 8; + TaitoCharPivotPlaneOffsets = PivotPlaneOffsets; + TaitoCharPivotXOffsets = PivotXOffsets; + TaitoCharPivotYOffsets = PivotYOffsets; + TaitoNumCharPivot = 0x4000; + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0430GRWInit(-10, 0, TaitoCharsPivot); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TC0430GRWRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteExtension , 0x600000, 0x603fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Pulirula68KReadByte); + SekSetWriteByteHandler(0, Pulirula68KWriteByte); + SekSetReadWordHandler(0, Pulirula68KReadWord); + SekSetWriteWordHandler(0, Pulirula68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteType = 2; + TaitoDrawFunction = PulirulaDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QcrayonInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(Taito68KRom1 + 0x80000 , 0x300000, 0x3fffff, SM_ROM); + SekMapMemory(TaitoSpriteExtension , 0x600000, 0x603fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x900000, 0x90ffff, SM_READ); + SekSetReadByteHandler(0, Qcrayon68KReadByte); + SekSetWriteByteHandler(0, Qcrayon68KWriteByte); + SekSetReadWordHandler(0, Qcrayon68KReadWord); + SekSetWriteWordHandler(0, Qcrayon68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteType = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 Qcrayon2Init() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x300000, 0x301fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x500000, 0x50ffff, SM_READ); + SekMapMemory(Taito68KRom1 + 0x80000 , 0x600000, 0x6fffff, SM_ROM); + SekMapMemory(TaitoSpriteExtension , 0xb00000, 0xb017ff, SM_RAM); + SekSetReadByteHandler(0, Qcrayon268KReadByte); + SekSetWriteByteHandler(0, Qcrayon268KWriteByte); + SekSetReadWordHandler(0, Qcrayon268KReadWord); + SekSetWriteWordHandler(0, Qcrayon268KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteType = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QjinseiInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x80000 , 0x100000, 0x1fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TaitoSpriteExtension , 0x600000, 0x603fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x700000, 0x701fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Qjinsei68KReadByte); + SekSetWriteByteHandler(0, Qjinsei68KWriteByte); + SekSetReadWordHandler(0, Qjinsei68KReadWord); + SekSetWriteWordHandler(0, Qjinsei68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteType = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QtorimonInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumSpriteA = 0x0800; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0110PCRInit(1, 0x1000); + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0140SYTInit(); + TC0220IOCInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Qtorimon68KReadByte); + SekSetWriteByteHandler(0, Qtorimon68KWriteByte); + SekSetReadWordHandler(0, Qtorimon68KReadWord); + SekSetWriteWordHandler(0, Qtorimon68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + TaitoDrawFunction = QtorimonDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QuizhqInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumSpriteA = 0x1000; + + TaitoLoadRoms(0); + + Taito68KRom1Size = 0xc0000; + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + memcpy(Taito68KRom1 + 0x80000, Taito68KRom1 + 0x40000, 0x40000); + memset(Taito68KRom1 + 0x40000, 0, 0x40000); + + TC0110PCRInit(1, 0x1000); + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0140SYTInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x0bffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Quizhq68KReadByte); + SekSetWriteByteHandler(0, Quizhq68KWriteByte); + SekSetReadWordHandler(0, Quizhq68KReadWord); + SekSetWriteWordHandler(0, Quizhq68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + TaitoDrawFunction = QtorimonDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QzchikyuInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0140SYTInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0x100000, 0x17ffff, SM_ROM); + SekMapMemory(TaitoPaletteRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0x500000, 0x50ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x60ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x700000, 0x70ffff, SM_READ); + SekSetReadByteHandler(0, Qzchikyu68KReadByte); + SekSetWriteByteHandler(0, Qzchikyu68KWriteByte); + SekSetReadWordHandler(0, Qzchikyu68KReadWord); + SekSetWriteWordHandler(0, Qzchikyu68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayedQzchikyu; + TaitoDrawFunction = QzquestDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 QzquestInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0140SYTInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0x100000, 0x1fffff, SM_ROM); + SekMapMemory(TaitoPaletteRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0x500000, 0x50ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x60ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x700000, 0x70ffff, SM_READ); + SekSetReadByteHandler(0, Qzquest68KReadByte); + SekSetWriteByteHandler(0, Qzquest68KWriteByte); + SekSetReadWordHandler(0, Qzquest68KReadWord); + SekSetWriteWordHandler(0, Qzquest68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayed; + TaitoDrawFunction = QzquestDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 SolfigtrInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x8000; + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, TaitoPriorityMap); + TC0140SYTInit(); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x201fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekSetReadByteHandler(0, Solfigtr68KReadByte); + SekSetWriteByteHandler(0, Solfigtr68KWriteByte); + SekSetReadWordHandler(0, Solfigtr68KReadWord); + SekSetWriteWordHandler(0, Solfigtr68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 SsiInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 0, 0, 0, NULL); + TC0140SYTInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x300000, 0x301fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x600000, 0x60ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x800000, 0x80ffff, SM_RAM); + SekSetReadByteHandler(0, Ssi68KReadByte); + SekSetWriteByteHandler(0, Ssi68KWriteByte); + SekSetReadWordHandler(0, Ssi68KReadWord); + SekSetWriteWordHandler(0, Ssi68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayedThundfox; + TaitoDrawFunction = SsiDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 ThundfoxInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoNumChar = 0x4000; + + TaitoCharBModulo = 0x100; + TaitoCharBNumPlanes = 4; + TaitoCharBWidth = 8; + TaitoCharBHeight = 8; + TaitoCharBPlaneOffsets = CharPlaneOffsets; + TaitoCharBXOffsets = CharXOffsets; + TaitoCharBYOffsets = CharYOffsets; + TaitoNumCharB = 0x4000; + + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0100SCNSetClipArea(0, nScreenWidth, nScreenHeight, 0); + TC0100SCNInit(1, TaitoNumCharB, 3, 16, 0, NULL); + TC0100SCNSetClipArea(1, nScreenWidth, nScreenHeight, 0); + TC0140SYTInit(); + TC0220IOCInit(); + TC0360PRIInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(TaitoPaletteRam , 0x100000, 0x101fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0x300000, 0x30ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x400000, 0x40ffff, SM_READ); + SekMapMemory(TC0100SCNRam[1] , 0x500000, 0x50ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x600000, 0x60ffff, SM_RAM); + SekSetReadByteHandler(0, Thundfox68KReadByte); + SekSetWriteByteHandler(0, Thundfox68KWriteByte); + SekSetReadWordHandler(0, Thundfox68KReadWord); + SekSetWriteWordHandler(0, Thundfox68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoXOffset = 3; + TaitoF2SpriteBufferFunction = TaitoF2PartialBufferDelayedThundfox; + TaitoDrawFunction = ThundfoxDraw; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 YesnojInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharModulo = 0x40; + TaitoCharNumPlanes = 1; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = YuyugogoCharPlaneOffsets; + TaitoCharXOffsets = YuyugogoCharXOffsets; + TaitoCharYOffsets = YuyugogoCharYOffsets; + TaitoNumChar = 0x10000; + + TaitoNumSpriteA = 0x2000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0140SYTInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x500000, 0x50ffff, SM_READ); + SekMapMemory(TaitoPaletteRam , 0x600000, 0x601fff, SM_RAM); + SekSetReadByteHandler(0, Yesnoj68KReadByte); + SekSetWriteByteHandler(0, Yesnoj68KWriteByte); + SekSetReadWordHandler(0, Yesnoj68KReadWord); + SekSetWriteWordHandler(0, Yesnoj68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoDrawFunction = YuyugogoDraw; + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 YuyugogoInit() +{ + INT32 nLen; + + TaitoF2Init(); + + TaitoCharModulo = 0x40; + TaitoCharNumPlanes = 1; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = YuyugogoCharPlaneOffsets; + TaitoCharXOffsets = YuyugogoCharXOffsets; + TaitoCharYOffsets = YuyugogoCharYOffsets; + TaitoNumChar = 0x4000; + + TaitoNumSpriteA = 0x4000; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0100SCNInit(0, TaitoNumChar, 3, 8, 0, NULL); + TC0140SYTInit(); + TC0510NIOInit(); + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(TC0100SCNRam[0] , 0x800000, 0x80ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0xa00000, 0xa01fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0xb00000, 0xb10fff, SM_RAM); + SekMapMemory(TaitoSpriteExtension , 0xc00000, 0xc01fff, SM_RAM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0xd00000, 0xdfffff, SM_ROM); + SekSetReadByteHandler(0, Yuyugogo68KReadByte); + SekSetWriteByteHandler(0, Yuyugogo68KWriteByte); + SekSetReadWordHandler(0, Yuyugogo68KReadWord); + SekSetWriteWordHandler(0, Yuyugogo68KWriteWord); + SekClose(); + + TaitoF2SoundInit(); + + TaitoDrawFunction = YuyugogoDraw; + TaitoF2SpriteType = 1; + TaitoXOffset = 3; + + // Reset the driver + TaitoF2DoReset(); + + return 0; +} + +static INT32 TaitoF2Exit() +{ + TaitoExit(); + + TaitoF2SpritesFlipScreen = 0; + TaitoF2SpriteBlendMode = 0; + TaitoF2TilePriority[0] = TaitoF2TilePriority[1] = TaitoF2TilePriority[2] = TaitoF2TilePriority[3] = TaitoF2TilePriority[4] = 0; + TaitoF2SpritePriority[0] = TaitoF2SpritePriority[1] = TaitoF2SpritePriority[2] = TaitoF2SpritePriority[3] = 0; + + TaitoF2SpriteType = 0; + Footchmp = 0; + YesnoDip = 0; + MjnquestInput = 0; + DriveoutSoundNibble = 0; + DriveoutOkiBank = 0; + + TaitoF2SpriteBufferFunction = NULL; + + // Switch back CPU core if needed + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + + return 0; +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + + +inline static INT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 12); + g = pal4bit(nColour >> 8); + b = pal4bit(nColour >> 4); + + return BurnHighCol(r, g, b, 0); +} + +inline static INT32 QzquestCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 10); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +static void TaitoF2CalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x1000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void MetalbCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void QzquestCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x1000; i++, ps++, pd++) { + *pd = QzquestCalcCol(*ps); + } +} + +static void UpdateTaitoF2SpriteBanks() +{ + INT32 i; + + for (i = 0; i < 8; i++) { + TaitoF2SpriteBank[i] = TaitoF2SpriteBankBuffered[i]; + } +} + +void TaitoF2HandleSpriteBuffering() +{ + if (TaitoF2PrepareSprites) { + memcpy(TaitoSpriteRamBuffered, TaitoSpriteRam, 0x10000); + TaitoF2PrepareSprites = 0; + } +} + +static void TaitoF2UpdateSpritesActiveArea() +{ + INT32 Off; + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + + UpdateTaitoF2SpriteBanks(); + + TaitoF2HandleSpriteBuffering(); + + if (TaitoF2SpritesActiveArea == 0x8000 && SpriteRamBuffered[(0x8000 + 6) / 2] == 0 && SpriteRamBuffered[(0x8000 + 10) / 2] == 0) TaitoF2SpritesActiveArea = 0; + + for (Off = 0; Off < 0x4000; Off += 16) { + INT32 Offs = Off + TaitoF2SpritesActiveArea; + + if (SpriteRamBuffered[(Offs + 6) / 2] & 0x8000) { + TaitoF2SpritesDisabled = SpriteRamBuffered[(Offs + 10) / 2] & 0x1000; + if (Footchmp) { + TaitoF2SpritesActiveArea = 0x8000 * (SpriteRamBuffered[(Offs + 6) / 2] & 0x0001); + } else { + TaitoF2SpritesActiveArea = 0x8000 * (SpriteRamBuffered[(Offs + 10) / 2] & 0x0001); + } + } + + if ((SpriteRamBuffered[(Offs + 4) / 2] & 0xf000) == 0xa000) { + TaitoF2SpritesMasterScrollX = SpriteRamBuffered[(Offs + 4) / 2] & 0xfff; + if (TaitoF2SpritesMasterScrollX >= 0x800) TaitoF2SpritesMasterScrollX -= 0x1000; + + TaitoF2SpritesMasterScrollY = SpriteRamBuffered[(Offs + 6) / 2] & 0xfff; + if (TaitoF2SpritesMasterScrollY >= 0x800) TaitoF2SpritesMasterScrollY -= 0x1000; + } + } +} + +static void RenderSpriteZoom(INT32 Code, INT32 sx, INT32 sy, INT32 Colour, INT32 xFlip, INT32 yFlip, INT32 xScale, INT32 yScale, INT32 Priority, UINT8* pSource) +{ + UINT8 *SourceBase = pSource + ((Code % TaitoNumSpriteA) * TaitoSpriteAWidth * TaitoSpriteAHeight); + + INT32 SpriteScreenHeight = (yScale * TaitoSpriteAHeight + 0x8000) >> 16; + INT32 SpriteScreenWidth = (xScale * TaitoSpriteAWidth + 0x8000) >> 16; + + Colour = 0x10 * (Colour % 0x100); + + if (TaitoF2SpritesFlipScreen) { + xFlip = !xFlip; + sx = 320 - sx - (xScale >> 12); + yFlip = !yFlip; + sy = 256 - sy - (yScale >> 12); + } + + if (SpriteScreenWidth && SpriteScreenHeight) { + INT32 dx = (TaitoSpriteAWidth << 16) / SpriteScreenWidth; + INT32 dy = (TaitoSpriteAHeight << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (xFlip) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (yFlip) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth) { + INT32 Pixels = ex - nScreenWidth; + ex -= Pixels; + } + + if (ey > nScreenHeight) { + INT32 Pixels = ey - nScreenHeight; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * TaitoSpriteAWidth); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + INT32 x, xIndex = xIndexBase; + for (x = sx; x < ex; x++) { + INT32 c = Source[xIndex >> 16]; + if (c != 0) { + if (TaitoF2SpriteBlendMode) { + INT32 Pri = TaitoPriorityMap[(y * nScreenWidth) + x]; + INT32 TilePri = 0; + + if (TaitoIC_TC0100SCNInUse) { + if (Pri == 1) TilePri = TaitoF2TilePriority[0]; + if (Pri == 2) TilePri = TaitoF2TilePriority[1]; + if (Pri == 4) TilePri = TaitoF2TilePriority[2]; + } + + if (((TaitoF2SpriteBlendMode & 0xc0) == 0xc0) && (Priority == (TilePri - 1))) { + pPixel[x] = ((c | Colour) & 0xfff0) | (pPixel[x] & 0x0f); + } else { + if (((TaitoF2SpriteBlendMode & 0xc0) == 0xc0) && (Priority == (TilePri + 1))) { + if (pPixel[x] & 0x0f) { + pPixel[x] = (pPixel[x] & 0xfff0) | ((c | Colour) & 0x0f); + } else { + pPixel[x] = c | Colour; + } + } else { + if (((TaitoF2SpriteBlendMode & 0xc0) == 0x80) && (Priority == (TilePri - 1))) { + pPixel[x] = pPixel[x] & 0xffef; + } else { + if (((TaitoF2SpriteBlendMode & 0xc0) == 0x80) && (Priority == (TilePri + 1))) { + pPixel[x] = (c | Colour) & 0xffef; + } else { + pPixel[x] = c | Colour; + } + } + } + } + } else { + pPixel[x] = c | Colour; + } + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +void TaitoF2MakeSpriteList() +{ + INT32 i, x, y, Off, ExtOffs; + INT32 Code, Colour, SpriteData, SpriteCont, xFlip, yFlip; + INT32 xCurrent, yCurrent, BigSprite = 0; + INT32 yNum = 0, xNum = 0, xLatch = 0, yLatch = 0, LastContinuationTile = 0; + UINT32 ZoomWord, xZoom, yZoom, zx = 0, zy = 0, xZoomLatch = 0, yZoomLatch = 0; + INT32 xScroll1, yScroll1; + INT32 xScroll = 0, yScroll = 0; + INT32 xCur, yCur; + INT32 xOffset = 0; + + INT32 Disabled = TaitoF2SpritesDisabled; + INT32 MasterScrollX = TaitoF2SpritesMasterScrollX; + INT32 MasterScrollY = TaitoF2SpritesMasterScrollY; + INT32 Area = TaitoF2SpritesActiveArea; + + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + UINT16 *SpriteExtension = (UINT16*)TaitoSpriteExtension; + struct TaitoF2SpriteEntry *SpritePtr = TaitoF2SpriteList; + + memset(TaitoF2SpriteList, 0, 0x400 * sizeof(TaitoF2SpriteEntry)); + + xScroll1 = 0; + yScroll1 = 0; + x = y = 0; + xCurrent = yCurrent = 0; + Colour = 0; + + xOffset = TaitoXOffset; + if (TaitoF2SpritesFlipScreen) xOffset = -TaitoXOffset; + + if (Area == 0x8000 && SpriteRamBuffered[(0x8000 + 6) / 2] == 0 && SpriteRamBuffered[(0x8000 + 10) / 2] == 0) Area = 0; + + for (Off = 0; Off < 0x4000; Off += 16) { + INT32 Offs = Off + Area; + + if (SpriteRamBuffered[(Offs + 6) / 2] & 0x8000) { + Disabled = SpriteRamBuffered[(Offs + 10) / 2] & 0x1000; + TaitoF2SpritesFlipScreen = SpriteRamBuffered[(Offs + 10) / 2] & 0x2000; + + xOffset = TaitoXOffset; + if (TaitoF2SpritesFlipScreen) xOffset = -TaitoXOffset; + + if (Footchmp) { + Area = 0x8000 * (SpriteRamBuffered[(Offs + 6) / 2] & 0x0001); + } else { + Area = 0x8000 * (SpriteRamBuffered[(Offs + 10) / 2] & 0x0001); + } + } + + if ((SpriteRamBuffered[(Offs + 4) / 2] & 0xf000) == 0xa000) { + MasterScrollX = SpriteRamBuffered[(Offs + 4) / 2] & 0xfff; + if (MasterScrollX >= 0x800) MasterScrollX -= 0x1000; + + MasterScrollY = SpriteRamBuffered[(Offs + 6) / 2] & 0xfff; + if (MasterScrollY >= 0x800) MasterScrollY -= 0x1000; + } + + if ((SpriteRamBuffered[(Offs + 4) / 2] & 0xf000) == 0x5000) { + xScroll1 = SpriteRamBuffered[(Offs + 4) / 2] & 0xfff; + if (xScroll1 >= 0x800) xScroll1 -= 0x1000; + + yScroll1 = SpriteRamBuffered[(Offs + 6) / 2] & 0xfff; + if (yScroll1 >= 0x800) yScroll1 -= 0x1000; + } + + if (Disabled) + continue; + + SpriteData = SpriteRamBuffered[(Offs + 8) / 2]; + + SpriteCont = (SpriteData & 0xff00) >> 8; + + if ((SpriteCont & 0x08) != 0) { + if (BigSprite == 0) { + xLatch = SpriteRamBuffered[(Offs + 4) / 2] & 0xfff; + yLatch = SpriteRamBuffered[(Offs + 6) / 2] & 0xfff; + xNum = 0; + yNum = 0; + ZoomWord = SpriteRamBuffered[(Offs + 2) / 2]; + yZoomLatch = (ZoomWord >> 8) & 0xff; + xZoomLatch = (ZoomWord) & 0xff; + BigSprite = 1; + } + } else if (BigSprite) { + LastContinuationTile = 1; + } + + if ((SpriteCont & 0x04) == 0) Colour = SpriteData & 0xff; + + if (BigSprite == 0 || (SpriteCont & 0xf0) == 0) { + x = SpriteRamBuffered[(Offs + 4) / 2]; + + if (x & 0x8000) { + xScroll = -xOffset - 0x60; + yScroll = 0; + } else if (x & 0x4000) { + xScroll = MasterScrollX - xOffset - 0x60; + yScroll = MasterScrollY; + } else { + xScroll = xScroll1 + MasterScrollX - xOffset - 0x60; + yScroll = yScroll1 + MasterScrollY; + } + + x &= 0xfff; + y = SpriteRamBuffered[(Offs + 6) / 2] & 0xfff; + + xCurrent = x; + yCurrent = y; + } else { + if ((SpriteCont & 0x10) == 0) { + y = yCurrent; + } else if ((SpriteCont & 0x20) != 0) { + y += 16; + yNum++; + } + + if ((SpriteCont & 0x40) == 0) { + x = xCurrent; + } else if ((SpriteCont & 0x80) != 0){ + x += 16; + yNum=0; + xNum++; + } + } + + if (BigSprite) { + xZoom = xZoomLatch; + yZoom = yZoomLatch; + zx = 0x10; + zy = 0x10; + + if (xZoom || yZoom) { + x = xLatch + (xNum * (0x100 - xZoom) + 12) / 16; + y = yLatch + (yNum * (0x100 - yZoom) + 12) / 16; + zx = xLatch + ((xNum + 1) * (0x100 - xZoom) + 12) / 16 - x; + zy = yLatch + ((yNum + 1) * (0x100 - yZoom) + 12) / 16 - y; + } + } else { + ZoomWord = SpriteRamBuffered[(Offs + 2) / 2]; + yZoom = (ZoomWord >> 8) & 0xff; + xZoom = (ZoomWord) & 0xff; + zx = (0x100 - xZoom) / 16; + zy = (0x100 - yZoom) / 16; + } + + if (LastContinuationTile) { + BigSprite = 0; + LastContinuationTile = 0; + } + + Code = 0; + ExtOffs = Offs; + if (ExtOffs >= 0x8000) ExtOffs -= 0x4000; + + if (TaitoF2SpriteType == 0) { + Code = SpriteRamBuffered[Offs / 2] & 0x1fff; + i = (Code & 0x1c00) >> 10; + Code = TaitoF2SpriteBank[i] + (Code & 0x3ff); + } + + if (TaitoF2SpriteType == 1) { + Code = SpriteRamBuffered[Offs / 2] & 0x3ff; + i = (SpriteExtension[(ExtOffs >> 4)] & 0x3f) << 10; + Code = (i | Code); + } + + if (TaitoF2SpriteType == 2) { + Code = SpriteRamBuffered[Offs / 2] & 0xff; + i = (SpriteExtension[(ExtOffs >> 4)] & 0xff00); + Code = (i | Code); + } + + if (TaitoF2SpriteType == 3) { + Code = SpriteRamBuffered[Offs / 2] & 0xff; + i = (SpriteExtension[ExtOffs >> 4] & 0xff) << 8; + Code = (i | Code); + } + + if (Code == 0) continue; + + xFlip = SpriteCont & 0x01; + yFlip = SpriteCont & 0x02; + + xCur = (x + xScroll) & 0xfff; + if (xCur >= 0x800) xCur -= 0x1000; + + yCur = (y + yScroll) & 0xfff; + if (yCur >= 0x800) yCur -= 0x1000; + + if (TaitoF2SpritesFlipScreen) { + yCur += 16; + } else { + yCur -= 16; + } + + INT32 Priority = (Colour & 0xc0) >> 6; + + SpritePtr->Code = Code; + SpritePtr->x = xCur; + SpritePtr->y = yCur; + SpritePtr->Colour = Colour; + SpritePtr->xFlip = xFlip; + SpritePtr->yFlip = yFlip; + SpritePtr->xZoom = zx << 12; + SpritePtr->yZoom = zy << 12; + SpritePtr->Priority = TaitoF2SpritePriority[Priority]; + SpritePtr++; + } +} + +void TaitoF2RenderSpriteList(INT32 TaitoF2SpritePriorityLevel) +{ + for (INT32 i = 0; i < 0x400; i++) { + if (TaitoF2SpriteList[i].Priority == TaitoF2SpritePriorityLevel) RenderSpriteZoom(TaitoF2SpriteList[i].Code, TaitoF2SpriteList[i].x, TaitoF2SpriteList[i].y, TaitoF2SpriteList[i].Colour, TaitoF2SpriteList[i].xFlip, TaitoF2SpriteList[i].yFlip, TaitoF2SpriteList[i].xZoom, TaitoF2SpriteList[i].yZoom, TaitoF2SpritePriorityLevel, TaitoSpritesA); + } +} + +void TaitoF2NoBuffer() +{ + TaitoF2UpdateSpritesActiveArea(); + TaitoF2PrepareSprites = 1; +} + +void TaitoF2PartialBufferDelayed() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + + TaitoF2UpdateSpritesActiveArea(); + TaitoF2PrepareSprites = 0; + memcpy(TaitoSpriteRamBuffered, TaitoSpriteRamDelayed, 0x10000); + for (INT32 i = 0; i < 0x10000 / 2; i += 4) SpriteRamBuffered[i] = SpriteRam[i]; + memcpy(TaitoSpriteRamDelayed, TaitoSpriteRam, 0x10000); +} + +void TaitoF2PartialBufferDelayedQzchikyu() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + + TaitoF2UpdateSpritesActiveArea(); + TaitoF2PrepareSprites = 0; + memcpy(TaitoSpriteRamBuffered, TaitoSpriteRamDelayed, 0x10000); + for (INT32 i = 0; i < 0x10000 / 2; i += 8) { + SpriteRamBuffered[i + 0] = SpriteRam[i + 0]; + SpriteRamBuffered[i + 1] = SpriteRam[i + 1]; + SpriteRamBuffered[i + 4] = SpriteRam[i + 4]; + SpriteRamBuffered[i + 5] = SpriteRam[i + 5]; + SpriteRamBuffered[i + 6] = SpriteRam[i + 6]; + SpriteRamBuffered[i + 7] = SpriteRam[i + 7]; + } + memcpy(TaitoSpriteRamDelayed, TaitoSpriteRam, 0x10000); +} + +void TaitoF2PartialBufferDelayedThundfox() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + + TaitoF2UpdateSpritesActiveArea(); + TaitoF2PrepareSprites = 0; + memcpy(TaitoSpriteRamBuffered, TaitoSpriteRamDelayed, 0x10000); + for (INT32 i = 0; i < 0x10000 / 2; i += 8) { + SpriteRamBuffered[i + 0] = SpriteRam[i + 0]; + SpriteRamBuffered[i + 1] = SpriteRam[i + 1]; + SpriteRamBuffered[i + 4] = SpriteRam[i + 4]; + } + memcpy(TaitoSpriteRamDelayed, TaitoSpriteRam, 0x10000); +} + +void TaitoF2FullBufferDelayed() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRamBuffered = (UINT16*)TaitoSpriteRamBuffered; + + TaitoF2UpdateSpritesActiveArea(); + TaitoF2PrepareSprites = 0; + memcpy(TaitoSpriteRamBuffered, TaitoSpriteRamDelayed, 0x10000); + for (INT32 i = 0;i < 0x10000 / 2; i++) SpriteRamBuffered[i] = SpriteRam[i]; + memcpy(TaitoSpriteRamDelayed, TaitoSpriteRam, 0x10000); +} + +static void TaitoF2Draw() +{ + INT32 i; + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 DrawLayer0 = 1; + INT32 DrawLayer1 = 1; + INT32 DrawLayer2 = 1; + + if (TC0100SCNBottomLayer(0)) { + TaitoF2TilePriority[1] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[0] = TC0360PRIRegs[5] >> 4; + } else { + TaitoF2TilePriority[0] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[1] = TC0360PRIRegs[5] >> 4; + } + TaitoF2TilePriority[2] = TC0360PRIRegs[4] >> 4; + + if (TaitoF2TilePriority[1] < TaitoF2TilePriority[0]) TaitoF2TilePriority[1] = TaitoF2TilePriority[0]; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + TaitoF2SpriteBlendMode = TC0360PRIRegs[0] & 0xc0; + + BurnTransferClear(); + TaitoF2CalcPalette(); + + // Detect when we are using sprite blending with the sprite under the tile layer + UINT8 TileAltPriority[3] = { 0xff, 0xff, 0xff }; + if (TaitoF2SpriteBlendMode) { + for (i = 0; i < 4; i++) { + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[0] - 1) { + TileAltPriority[0] = TaitoF2SpritePriority[i]; + DrawLayer0 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[1] - 1) { + TileAltPriority[1] = TaitoF2SpritePriority[i]; + DrawLayer1 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[2] - 1) { + TileAltPriority[2] = TaitoF2SpritePriority[i]; + DrawLayer2 = 0; + } + } + } + + TaitoF2MakeSpriteList(); + + if (TC0100SCNBottomLayer(0)) { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } else { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } + + BurnTransferCopy(TaitoPalette); +} + +static void TaitoF2PivotDraw() +{ + INT32 i; + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 DrawLayer0 = 1; + INT32 DrawLayer1 = 1; + INT32 DrawLayer2 = 1; + INT32 RozPriority; + + if (TC0100SCNBottomLayer(0)) { + TaitoF2TilePriority[1] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[0] = TC0360PRIRegs[5] >> 4; + } else { + TaitoF2TilePriority[0] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[1] = TC0360PRIRegs[5] >> 4; + } + TaitoF2TilePriority[2] = TC0360PRIRegs[4] >> 4; + + if (TaitoF2TilePriority[1] < TaitoF2TilePriority[0]) TaitoF2TilePriority[1] = TaitoF2TilePriority[0]; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + TaitoF2SpriteBlendMode = TC0360PRIRegs[0] & 0xc0; + + RozPriority = (TC0360PRIRegs[1] & 0xc0) >> 6; + RozPriority = (TC0360PRIRegs[8 + (RozPriority / 2)] >> 4 * (RozPriority & 1)) & 0x0f; + TC0280GRDBaseColour = (TC0360PRIRegs[1] & 0x3f) << 2; + +// bprintf(PRINT_NORMAL, _T("TCBL %x, Blend %x, Roz %x, RozBase %x, T0 %x, T1 %x, T2 %x, S0 %x, S1 %x, S2 %x, S3 %x\n"), TC0100SCNBottomLayer(0), TaitoF2SpriteBlendMode, RozPriority, TaitoRozBaseColour, TaitoF2TilePriority[0], TaitoF2TilePriority[1], TaitoF2TilePriority[2], TaitoF2SpritePriority[0], TaitoF2SpritePriority[1], TaitoF2SpritePriority[2], TaitoF2SpritePriority[3]); + + BurnTransferClear(); + TaitoF2CalcPalette(); + + // Detect when we are using sprite blending with the sprite under the tile layer + UINT8 TileAltPriority[3] = { 0xff, 0xff, 0xff }; + if (TaitoF2SpriteBlendMode) { + for (i = 0; i < 4; i++) { + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[0] - 1) { + TileAltPriority[0] = TaitoF2SpritePriority[i]; + DrawLayer0 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[1] - 1) { + TileAltPriority[1] = TaitoF2SpritePriority[i]; + DrawLayer1 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[2] - 1) { + TileAltPriority[2] = TaitoF2SpritePriority[i]; + DrawLayer2 = 0; + } + } + } + + TaitoF2MakeSpriteList(); + + if (TC0100SCNBottomLayer(0)) { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0280GRDRenderLayer(); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } else { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0280GRDRenderLayer(); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } + + BurnTransferCopy(TaitoPalette); +} + +static void CameltryDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 i; + + INT32 RozPriority; + + TaitoF2TilePriority[2] = TC0360PRIRegs[4] >> 4; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + RozPriority = (TC0360PRIRegs[1] & 0xc0) >> 6; + RozPriority = (TC0360PRIRegs[8 + (RozPriority / 2)] >> 4 * (RozPriority & 1)) & 0x0f; + TC0280GRDBaseColour = (TC0360PRIRegs[1] & 0x3f) << 2; + + BurnTransferClear(); + TaitoF2CalcPalette(); + + TaitoF2MakeSpriteList(); + + for (i = 0; i < 16; i++) { + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0280GRDRenderLayer(); + if (TaitoF2TilePriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + + BurnTransferCopy(TaitoPalette); +} + +static void DriftoutDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 i; + + INT32 RozPriority; + + TaitoF2TilePriority[2] = TC0360PRIRegs[4] >> 4; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + RozPriority = (TC0360PRIRegs[1] & 0xc0) >> 6; + RozPriority = (TC0360PRIRegs[8 + (RozPriority / 2)] >> 4 * (RozPriority & 1)) & 0x0f; + TC0280GRDBaseColour = (TC0360PRIRegs[1] & 0x3f) << 2; + + BurnTransferClear(); + QzquestCalcPalette(); + + TaitoF2MakeSpriteList(); + + for (i = 0; i < 16; i++) { + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0430GRWRenderLayer(); + if (TaitoF2TilePriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + + BurnTransferCopy(TaitoPalette); +} + +static void FinalbDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + TaitoF2SpritePriority[0] = 0; + TaitoF2SpritePriority[1] = 0; + TaitoF2SpritePriority[2] = 0; + TaitoF2SpritePriority[3] = 0; + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + TaitoF2MakeSpriteList(); + + TaitoF2RenderSpriteList(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void FootchmpDraw() +{ + UINT8 Layer[4]; + UINT16 Priority = TC0480SCPGetBgPriority(); + + Layer[0] = (Priority & 0xf000) >> 12; + Layer[1] = (Priority & 0x0f00) >> 8; + Layer[2] = (Priority & 0x00f0) >> 4; + Layer[3] = (Priority & 0x000f) >> 0; + + TaitoF2TilePriority[0] = TC0360PRIRegs[4] >> 4; + TaitoF2TilePriority[1] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[2] = TC0360PRIRegs[5] >> 4; + TaitoF2TilePriority[3] = TC0360PRIRegs[4] & 0x0f; + TaitoF2TilePriority[4] = TC0360PRIRegs[7] >> 4; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + BurnTransferClear(); + TaitoF2CalcPalette(); + + TaitoF2MakeSpriteList(); + + for (INT32 i = 0; i < 16; i++) { + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (TaitoF2TilePriority[0] == i) TC0480SCPTilemapRender(Layer[0], 0, TaitoChars); + if (TaitoF2TilePriority[1] == i) TC0480SCPTilemapRender(Layer[1], 0, TaitoChars); + if (TaitoF2TilePriority[2] == i) TC0480SCPTilemapRender(Layer[2], 0, TaitoChars); + if (TaitoF2TilePriority[3] == i) TC0480SCPTilemapRender(Layer[3], 0, TaitoChars); + } + + TC0480SCPRenderCharLayer(); + + BurnTransferCopy(TaitoPalette); +} + +static void MetalbDraw() +{ + UINT8 Layer[4]; + UINT16 Priority = TC0480SCPGetBgPriority(); + + Layer[0] = (Priority & 0xf000) >> 12; + Layer[1] = (Priority & 0x0f00) >> 8; + Layer[2] = (Priority & 0x00f0) >> 4; + Layer[3] = (Priority & 0x000f) >> 0; + + TaitoF2TilePriority[Layer[0]] = TC0360PRIRegs[4] & 0x0f; + TaitoF2TilePriority[Layer[1]] = TC0360PRIRegs[4] >> 4; + TaitoF2TilePriority[Layer[2]] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[Layer[3]] = TC0360PRIRegs[5] >> 4; + TaitoF2TilePriority[4] = TC0360PRIRegs[9] & 0x0f; + + if (TaitoF2TilePriority[1] < TaitoF2TilePriority[0]) TaitoF2TilePriority[1] = TaitoF2TilePriority[0]; + if (TaitoF2TilePriority[2] < TaitoF2TilePriority[1]) TaitoF2TilePriority[2] = TaitoF2TilePriority[1]; + if (TaitoF2TilePriority[3] < TaitoF2TilePriority[2]) TaitoF2TilePriority[3] = TaitoF2TilePriority[2]; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + TaitoF2SpriteBlendMode = TC0360PRIRegs[0] & 0xc0; + +// bprintf(PRINT_IMPORTANT, _T("SPR Bl %x, T0 %x, T1 %x, T2 %x, T3 %x, T4 %x, S0 %x, S1 %x, S2 %x, S3 %x\n"), TaitoF2SpriteBlendMode, TaitoF2TilePriority[0], TaitoF2TilePriority[1], TaitoF2TilePriority[2], TaitoF2TilePriority[3], TaitoF2TilePriority[4], TaitoF2SpritePriority[0], TaitoF2SpritePriority[1], TaitoF2SpritePriority[2], TaitoF2SpritePriority[3]); +// bprintf(PRINT_NORMAL, _T("L0 %x %x, L1 %x %x, L2 %x %x, L3 %x %x\n"), Layer[0], TaitoF2TilePriority[0], Layer[1], TaitoF2TilePriority[1], Layer[2], TaitoF2TilePriority[2], Layer[3], TaitoF2TilePriority[3]); + + BurnTransferClear(); + MetalbCalcPalette(); + + TaitoF2MakeSpriteList(); + + for (INT32 i = 0; i < 16; i++) { + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (TaitoF2TilePriority[0] == i) TC0480SCPTilemapRender(Layer[0], 0, TaitoChars); + if (TaitoF2TilePriority[1] == i) TC0480SCPTilemapRender(Layer[1], 0, TaitoChars); + if (TaitoF2TilePriority[2] == i) TC0480SCPTilemapRender(Layer[2], 0, TaitoChars); + if (TaitoF2TilePriority[3] == i) TC0480SCPTilemapRender(Layer[3], 0, TaitoChars); + } + + TC0480SCPRenderCharLayer(); + + BurnTransferCopy(TaitoPalette); +} + +static void PulirulaDraw() +{ + INT32 i; + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + INT32 DrawLayer0 = 1; + INT32 DrawLayer1 = 1; + INT32 DrawLayer2 = 1; + INT32 RozPriority; + + if (TC0100SCNBottomLayer(0)) { + TaitoF2TilePriority[1] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[0] = TC0360PRIRegs[5] >> 4; + } else { + TaitoF2TilePriority[0] = TC0360PRIRegs[5] & 0x0f; + TaitoF2TilePriority[1] = TC0360PRIRegs[5] >> 4; + } + TaitoF2TilePriority[2] = TC0360PRIRegs[4] >> 4; + + if (TaitoF2TilePriority[1] < TaitoF2TilePriority[0]) TaitoF2TilePriority[1] = TaitoF2TilePriority[0]; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + + TaitoF2SpriteBlendMode = TC0360PRIRegs[0] & 0xc0; + + RozPriority = (TC0360PRIRegs[1] & 0xc0) >> 6; + RozPriority = (TC0360PRIRegs[8 + (RozPriority / 2)] >> 4 * (RozPriority & 1)) & 0x0f; + TC0280GRDBaseColour = (TC0360PRIRegs[1] & 0x3f) << 2; + + bprintf(PRINT_NORMAL, _T("TCBL %x, Blend %x, Roz %x, RozBase %x, T0 %x, T1 %x, T2 %x, S0 %x, S1 %x, S2 %x, S3 %x\n"), TC0100SCNBottomLayer(0), TaitoF2SpriteBlendMode, RozPriority, TC0280GRDBaseColour, TaitoF2TilePriority[0], TaitoF2TilePriority[1], TaitoF2TilePriority[2], TaitoF2SpritePriority[0], TaitoF2SpritePriority[1], TaitoF2SpritePriority[2], TaitoF2SpritePriority[3]); + + BurnTransferClear(); + QzquestCalcPalette(); + + // Detect when we are using sprite blending with the sprite under the tile layer + UINT8 TileAltPriority[3] = { 0xff, 0xff, 0xff }; + if (TaitoF2SpriteBlendMode) { + for (i = 0; i < 4; i++) { + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[0] - 1) { + TileAltPriority[0] = TaitoF2SpritePriority[i]; + DrawLayer0 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[1] - 1) { + TileAltPriority[1] = TaitoF2SpritePriority[i]; + DrawLayer1 = 0; + } + + if (TaitoF2SpritePriority[i] == TaitoF2TilePriority[2] - 1) { + TileAltPriority[2] = TaitoF2SpritePriority[i]; + DrawLayer2 = 0; + } + } + } + + TaitoF2MakeSpriteList(); + + if (TC0100SCNBottomLayer(0)) { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0430GRWRenderLayer(); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } else { + for (i = 0; i < 16; i++) { + if (TileAltPriority[0] == i) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TileAltPriority[1] == i) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TileAltPriority[2] == i) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (RozPriority == i) TC0430GRWRenderLayer(); + if (TaitoF2TilePriority[0] == i && DrawLayer0) { if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[1] == i && DrawLayer1) { if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); } + if (TaitoF2TilePriority[2] == i && DrawLayer2) { if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); } + } + } + + BurnTransferCopy(TaitoPalette); +} + +static void QtorimonDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + TaitoF2SpritePriority[0] = 0; + TaitoF2SpritePriority[1] = 0; + TaitoF2SpritePriority[2] = 0; + TaitoF2SpritePriority[3] = 0; + + TaitoF2MakeSpriteList(); + + TaitoF2RenderSpriteList(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void QzquestDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + QzquestCalcPalette(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + TaitoF2SpritePriority[0] = 0; + TaitoF2SpritePriority[1] = 0; + TaitoF2SpritePriority[2] = 0; + TaitoF2SpritePriority[3] = 0; + + TaitoF2MakeSpriteList(); + + TaitoF2RenderSpriteList(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TaitoPalette); +} + +static void SsiDraw() +{ + BurnTransferClear(); + TaitoF2CalcPalette(); + + TaitoF2SpritePriority[0] = 0; + TaitoF2SpritePriority[1] = 0; + TaitoF2SpritePriority[2] = 0; + TaitoF2SpritePriority[3] = 0; + + TaitoF2MakeSpriteList(); + + TaitoF2RenderSpriteList(0); + + BurnTransferCopy(TaitoPalette); +} + +static void ThundfoxDraw() +{ + INT32 Disable1 = TC0100SCNCtrl[0][6] & 0xf7; + INT32 Disable2 = TC0100SCNCtrl[1][6] & 0xf7; + + BurnTransferClear(); + TaitoF2CalcPalette(); + + INT32 TilePri[2][3]; + INT32 Layer[2][3]; + + TaitoF2MakeSpriteList(); + + Layer[0][0] = TC0100SCNBottomLayer(0); + Layer[0][1] = Layer[0][0] ^ 1; + Layer[0][2] = 2; + TilePri[0][Layer[0][0]] = TC0360PRIRegs[5] & 0x0f; + TilePri[0][Layer[0][1]] = TC0360PRIRegs[5] >> 4; + TilePri[0][Layer[0][2]] = TC0360PRIRegs[4] >> 4; + + Layer[1][0] = TC0100SCNBottomLayer(1); + Layer[1][1] = Layer[1][0] ^ 1; + Layer[1][2] = 2; + TilePri[1][Layer[1][0]] = TC0360PRIRegs[9] & 0x0f; + TilePri[1][Layer[1][1]] = TC0360PRIRegs[9] >> 4; + TilePri[1][Layer[1][2]] = TC0360PRIRegs[8] >> 4; + + TaitoF2SpritePriority[0] = TC0360PRIRegs[6] & 0x0f; + TaitoF2SpritePriority[1] = TC0360PRIRegs[6] >> 4; + TaitoF2SpritePriority[2] = TC0360PRIRegs[7] & 0x0f; + TaitoF2SpritePriority[3] = TC0360PRIRegs[7] >> 4; + +// bprintf(PRINT_NORMAL, _T("Layer0-0 %x, Layer 0-1 %x, Layer 0-2 %x, Layer1-0 %x, Layer 1-1 %x, Layer 1-2 %x, Sprite 0 %x, Sprite 1 %x, Sprite 2 %x, Sprite 3 %x\n"), TilePri[0][0], TilePri[0][1], TilePri[0][2], TilePri[1][0], TilePri[1][1], TilePri[1][2], TaitoF2SpritePriority[0], TaitoF2SpritePriority[1], TaitoF2SpritePriority[2], TaitoF2SpritePriority[3]); + + for (INT32 i = 0; i < 16; i++) { + if (TilePri[1][0] == i) { + if (TC0100SCNBottomLayer(1)) { + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoCharsB); + } else { + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoCharsB); + } + } + if (TilePri[0][0] == i) { + if (TC0100SCNBottomLayer(0)) { + if (!(Disable1 & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } else { + if (!(Disable1 & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } + } + if (TilePri[1][1] == i) { + if (!TC0100SCNBottomLayer(1)) { + if (!(Disable2 & 0x02)) TC0100SCNRenderFgLayer(1, 0, TaitoCharsB); + } else { + if (!(Disable2 & 0x01)) TC0100SCNRenderBgLayer(1, 0, TaitoCharsB); + } + } + if (TilePri[0][1] == i) { + if (!TC0100SCNBottomLayer(0)) { + if (!(Disable1 & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } else { + if (!(Disable1 & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } + } + if (TaitoF2SpritePriority[3] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[3]); + if (TaitoF2SpritePriority[2] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[2]); + if (TaitoF2SpritePriority[1] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[1]); + if (TaitoF2SpritePriority[0] == i) TaitoF2RenderSpriteList(TaitoF2SpritePriority[0]); + if (TilePri[1][2] == i) { if (!(Disable2 & 0x04)) TC0100SCNRenderCharLayer(1); } + if (TilePri[0][2] == i) { if (!(Disable1 & 0x04)) TC0100SCNRenderCharLayer(0); } + } + + BurnTransferCopy(TaitoPalette); +} + +static void YuyugogoDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + TaitoF2CalcPalette(); + + TaitoF2SpritePriority[0] = 0; + TaitoF2SpritePriority[1] = 0; + TaitoF2SpritePriority[2] = 0; + TaitoF2SpritePriority[3] = 0; + + TaitoF2MakeSpriteList(); + + TaitoF2RenderSpriteList(0); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TaitoPalette); +} + +static INT32 TaitoF2Frame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoF2DoReset(); + + if (TaitoIC_TC0220IOCInUse) { + TC0220IOCMakeInputs(); + } else { + if (TaitoIC_TC0510NIOInUse) { + TC0510NIOMakeInputs(); + } else { + TaitoF2MakeInputs(); + } + } + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + if (i == 9) nTaitoCyclesSegment -= 500; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 9) { + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + nTaitoCyclesDone[nCurrentCPU] += SekRun(500); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + } + SekClose(); + + nCurrentCPU = 1; + ZetOpen(0); + BurnTimerUpdate(i * (nTaitoCyclesTotal[1] / nInterleave)); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (TaitoNumYM2610) BurnYM2610Update(pSoundBuf, nSegmentLength); + if (TaitoNumYM2203) BurnYM2203Update(pSoundBuf, nSegmentLength); + if (TaitoNumMSM6295) MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1]); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + if (TaitoNumYM2610) BurnYM2610Update(pSoundBuf, nSegmentLength); + if (TaitoNumYM2203) BurnYM2203Update(pSoundBuf, nSegmentLength); + if (TaitoNumMSM6295) MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + ZetClose(); + + TaitoF2HandleSpriteBuffering(); + + if (pBurnDraw) TaitoDrawFunction(); + + TaitoF2SpriteBufferFunction(); + + return 0; +} + +static INT32 DriveoutFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoF2DoReset(); + + if (TaitoIC_TC0220IOCInUse) { + TC0220IOCMakeInputs(); + } else { + if (TaitoIC_TC0510NIOInUse) { + TC0510NIOMakeInputs(); + } else { + TaitoF2MakeInputs(); + } + } + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + if (i == 9) nTaitoCyclesSegment -= 500; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 9) { + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + nTaitoCyclesDone[nCurrentCPU] += SekRun(500); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + } + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + ZetClose(); + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + + if (nSegmentLength) { + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + TaitoF2HandleSpriteBuffering(); + + if (pBurnDraw) TaitoDrawFunction(); + + TaitoF2SpriteBufferFunction(); + + return 0; +} + +static INT32 TaitoF2Scan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029682; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + + SCAN_VAR(TaitoInput); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(TaitoF2SpriteBank); + SCAN_VAR(TaitoF2SpriteBankBuffered); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + SCAN_VAR(YesnoDip); + SCAN_VAR(MjnquestInput); + SCAN_VAR(DriveoutSoundNibble); + SCAN_VAR(DriveoutOkiBank); + } + + if (nAction & ACB_WRITE) { + if (TaitoZ80Bank) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + + if (DriveoutOkiBank) { + memcpy(MSM6295ROM, TaitoMSM6295Rom + (DriveoutOkiBank * 0x40000), 0x40000); + } + + TaitoF2SpriteBufferFunction(); + TaitoF2HandleSpriteBuffering(); + } + + return 0; +} + +struct BurnDriver BurnDrvCameltry = { + "cameltry", NULL, NULL, NULL, "1989", + "Cameltry (US, YM2610)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_MAZE, 0, + NULL, CameltryRomInfo, CameltryRomName, NULL, NULL, CameltryInputInfo, CameltryDIPInfo, + CameltryInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCameltryau = { + "cameltryau", "cameltry", NULL, NULL, "1989", + "Cameltry (World, YM2203 + M6295)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_MAZE, 0, + NULL, CameltryauRomInfo, CameltryauRomName, NULL, NULL, CameltryInputInfo, CameltryDIPInfo, + CamltryaInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCameltrya = { + "cameltrya", "cameltry", NULL, NULL, "1989", + "Cameltry (US, YM2203 + M6295)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_MAZE, 0, + NULL, CameltryaRomInfo, CameltryaRomName, NULL, NULL, CameltryInputInfo, CameltryDIPInfo, + CamltryaInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvCameltryj = { + "cameltryj", "cameltry", NULL, NULL, "1989", + "Cameltry (Japan, YM2610)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_MAZE, 0, + NULL, CameltryjRomInfo, CameltryjRomName, NULL, NULL, CameltryInputInfo, CameltrjDIPInfo, + CameltryInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDeadconx = { + "deadconx", NULL, NULL, NULL, "1992", + "Dead Connection (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_SHOOT, 0, + NULL, DeadconxRomInfo, DeadconxRomName, NULL, NULL, DeadconxInputInfo, DeadconxDIPInfo, + DeadconxInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDeadconxj = { + "deadconxj", "deadconx", NULL, NULL, "1992", + "Dead Connection (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_SHOOT, 0, + NULL, DeadconxjRomInfo, DeadconxjRomName, NULL, NULL, DeadconxInputInfo, DeadconxjDIPInfo, + DeadconxInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDinorex = { + "dinorex", NULL, NULL, NULL, "1992", + "Dino Rex (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, DinorexRomInfo, DinorexRomName, NULL, NULL, DinorexInputInfo, DinorexDIPInfo, + DinorexInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDinorexj = { + "dinorexj", "dinorex", NULL, NULL, "1992", + "Dino Rex (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, DinorexjRomInfo, DinorexjRomName, NULL, NULL, DinorexInputInfo, DinorexjDIPInfo, + DinorexInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDinorexu = { + "dinorexu", "dinorex", NULL, NULL, "1992", + "Dino Rex (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, DinorexuRomInfo, DinorexuRomName, NULL, NULL, DinorexInputInfo, DinorexDIPInfo, + DinorexInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDondokod = { + "dondokod", NULL, NULL, NULL, "1989", + "Don Doko Don (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, DondokodRomInfo, DondokodRomName, NULL, NULL, DondokodInputInfo, DondokodDIPInfo, + DondokodInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDondokodj = { + "dondokodj", "dondokod", NULL, NULL, "1989", + "Don Doko Don (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, DondokodjRomInfo, DondokodjRomName, NULL, NULL, DondokodInputInfo, DondokodjDIPInfo, + DondokodInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDondokodu = { + "dondokodu", "dondokod", NULL, NULL, "1989", + "Don Doko Don (US)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, DondokoduRomInfo, DondokoduRomName, NULL, NULL, DondokodInputInfo, DondokoduDIPInfo, + DondokodInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDriftout = { + "driftout", NULL, NULL, NULL, "1991", + "Drift Out (Japan)\0", NULL, "Visco", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOF2, GBF_RACING, 0, + NULL, DriftoutRomInfo, DriftoutRomName, NULL, NULL, DriftoutInputInfo, DriftoutDIPInfo, + DriftoutInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDriveout = { + "driveout", "driftout", NULL, NULL, "1991", + "Drive Out\0", NULL, "bootleg", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_TAITOF2, GBF_RACING, 0, + NULL, DriveoutRomInfo, DriveoutRomName, NULL, NULL, DriftoutInputInfo, DriftoutDIPInfo, + DriveoutInit, TaitoF2Exit, DriveoutFrame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvFinalb = { + "finalb", NULL, NULL, NULL, "1988", + "Final Blow (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, FinalbRomInfo, FinalbRomName, NULL, NULL, FinalbInputInfo, FinalbDIPInfo, + FinalbInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFinalbj = { + "finalbj", "finalb", NULL, NULL, "1988", + "Final Blow (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, FinalbjRomInfo, FinalbjRomName, NULL, NULL, FinalbInputInfo, FinalbjDIPInfo, + FinalbInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFinalbu = { + "finalbu", "finalb", NULL, NULL, "1988", + "Final Blow (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, FinalbuRomInfo, FinalbuRomName, NULL, NULL, FinalbInputInfo, FinalbjDIPInfo, + FinalbInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvFootchmp = { + "footchmp", NULL, NULL, NULL, "1990", + "Football Champ (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_TAITO_TAITOF2, GBF_SPORTSFOOTBALL, 0, + NULL, FootchmpRomInfo, FootchmpRomName, NULL, NULL, FootchmpInputInfo, FootchmpDIPInfo, + FootchmpInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvHthero = { + "hthero", "footchmp", NULL, NULL, "1990", + "Hat Trick Hero (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SPORTSFOOTBALL, 0, + NULL, HtheroRomInfo, HtheroRomName, NULL, NULL, FootchmpInputInfo, HtheroDIPInfo, + FootchmpInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvEuroch92 = { + "euroch92", "footchmp", NULL, NULL, "1992", + "Euro Champ '92 (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SPORTSFOOTBALL, 0, + NULL, Euroch92RomInfo, Euroch92RomName, NULL, NULL, FootchmpInputInfo, FootchmpDIPInfo, + FootchmpInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGrowl = { + "growl", NULL, NULL, NULL, "1990", + "Growl (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, GrowlRomInfo, GrowlRomName, NULL, NULL, GrowlInputInfo, GrowlDIPInfo, + GrowlInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGrowlu = { + "growlu", "growl", NULL, NULL, "1990", + "Growl (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, GrowluRomInfo, GrowluRomName, NULL, NULL, GrowlInputInfo, GrowluDIPInfo, + GrowlInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRunark = { + "runark", "growl", NULL, NULL, "1990", + "Runark (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, RunarkRomInfo, RunarkRomName, NULL, NULL, GrowlInputInfo, RunarkDIPInfo, + GrowlInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvGunfront = { + "gunfront", NULL, NULL, NULL, "1990", + "Gun & Frontier (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOF2, GBF_VERSHOOT, 0, + NULL, GunfrontRomInfo, GunfrontRomName, NULL, NULL, GunfrontInputInfo, GunfrontDIPInfo, + GunfrontInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvGunfrontj = { + "gunfrontj", "gunfront", NULL, NULL, "1990", + "Gun Frontier (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOF2, GBF_VERSHOOT, 0, + NULL, GunfrontjRomInfo, GunfrontjRomName, NULL, NULL, GunfrontInputInfo, GunfrontjDIPInfo, + GunfrontInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvKoshien = { + "koshien", NULL, NULL, NULL, "1990", + "Ah Eikou no Koshien (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u7532\u5B50\u5712 \u6804\u5149\u306E \u55DA\u547C (Japan)\0Ah Eikou no Koshien\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_SPORTSMISC, 0, + NULL, KoshienRomInfo, KoshienRomName, NULL, NULL, KoshienInputInfo, KoshienDIPInfo, + KoshienInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLiquidk = { + "liquidk", NULL, NULL, NULL, "1990", + "Liquid Kids (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, LiquidkRomInfo, LiquidkRomName, NULL, NULL, LiquidkInputInfo, LiquidkDIPInfo, + LiquidkInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvLiquidku = { + "liquidku", "liquidk", NULL, NULL, "1990", + "Liquid Kids (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, LiquidkuRomInfo, LiquidkuRomName, NULL, NULL, LiquidkInputInfo, LiquidkuDIPInfo, + LiquidkInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMizubaku = { + "mizubaku", "liquidk", NULL, NULL, "1990", + "Mizubaku Daibouken (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30DF\u30BA\u30D0\u30AF \u5927\u5192\u967A \u30A2\u30C9\u30D9\u30F3\u30C1\u30E3\u30FC (Japan)\0Mizubaku Daibouken\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_PLATFORM, 0, + NULL, MizubakuRomInfo, MizubakuRomName, NULL, NULL, LiquidkInputInfo, LiquidkuDIPInfo, + LiquidkInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMegablst = { + "megablst", NULL, NULL, NULL, "1989", + "Mega Blast (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_HORSHOOT, 0, + NULL, MegablstRomInfo, MegablstRomName, NULL, NULL, MegablstInputInfo, MegablstDIPInfo, + MegablstInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMegablstj = { + "megablstj", "megablst", NULL, NULL, "1989", + "Mega Blast (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_HORSHOOT, 0, + NULL, MegablstjRomInfo, MegablstjRomName, NULL, NULL, MegablstInputInfo, MegablstjDIPInfo, + MegablstInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMegablstu = { + "megablstu", "megablst", NULL, NULL, "1989", + "Mega Blast (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_HORSHOOT, 0, + NULL, MegablstuRomInfo, MegablstuRomName, NULL, NULL, MegablstInputInfo, MegablstuDIPInfo, + MegablstInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMetalb = { + "metalb", NULL, NULL, NULL, "1991", + "Metal Black (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_HORSHOOT, 0, + NULL, MetalbRomInfo, MetalbRomName, NULL, NULL, MetalbInputInfo, MetalbDIPInfo, + MetalbInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMetalbj = { + "metalbj", "metalb", NULL, NULL, "1991", + "Metal Black (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_HORSHOOT, 0, + NULL, MetalbjRomInfo, MetalbjRomName, NULL, NULL, MetalbInputInfo, MetalbjDIPInfo, + MetalbInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMjnquest = { + "mjnquest", NULL, NULL, NULL, "1990", + "Mahjong Quest (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_MAHJONG, 0, + NULL, MjnquestRomInfo, MjnquestRomName, NULL, NULL, MjnquestInputInfo, MjnquestDIPInfo, + MjnquestInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvMjnquestb = { + "mjnquestb", "mjnquest", NULL, NULL, "1990", + "Mahjong Quest (No Nudity)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_MAHJONG, 0, + NULL, MjnquestbRomInfo, MjnquestbRomName, NULL, NULL, MjnquestInputInfo, MjnquestDIPInfo, + MjnquestInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNinjak = { + "ninjak", NULL, NULL, NULL, "1990", + "The Ninja Kids (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, NinjakRomInfo, NinjakRomName, NULL, NULL, NinjakInputInfo, NinjakDIPInfo, + NinjakInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNinjakj = { + "ninjakj", "ninjak", NULL, NULL, "1990", + "The Ninja Kids (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, NinjakjRomInfo, NinjakjRomName, NULL, NULL, NinjakInputInfo, NinjakjDIPInfo, + NinjakInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNinjaku = { + "ninjaku", "ninjak", NULL, NULL, "1990", + "The Ninja Kids (US)\0", NULL, "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, NinjakuRomInfo, NinjakuRomName, NULL, NULL, NinjakInputInfo, NinjakuDIPInfo, + NinjakInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPulirula = { + "pulirula", NULL, NULL, NULL, "1991", + "PuLiRuLa (World)\0", "Some priority problems", "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, PulirulaRomInfo, PulirulaRomName, NULL, NULL, PulirulaInputInfo, PulirulaDIPInfo, + PulirulaInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvPulirulaj = { + "pulirulaj", "pulirula", NULL, NULL, "1991", + "PuLiRuLa (Japan)\0", "Some priority problems", "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, PulirulajRomInfo, PulirulajRomName, NULL, NULL, PulirulaInputInfo, PulirulajDIPInfo, + PulirulaInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQcrayon = { + "qcrayon", NULL, NULL, NULL, "1993", + "Quiz Crayon Shinchan (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30AF\u30A4\u30BA \u30AF\u30EC\u30E8\u30F3\u3057\u3093\u3061\u3083\u3093 (Japan)\0Quiz Crayon Shinchan\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QcrayonRomInfo, QcrayonRomName, NULL, NULL, QcrayonInputInfo, QcrayonDIPInfo, + QcrayonInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQcrayon2 = { + "qcrayon2", NULL, NULL, NULL, "1993", + "Crayon Shinchan Orato Asobo (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30AF\u30EC\u30E8\u30F3\u3057\u3093\u3061\u3083\u3093 \u30AA\u30E9\u3068\u904A\u307C (Japan)\0Crayon Shinchan Orato Asobo\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, Qcrayon2RomInfo, Qcrayon2RomName, NULL, NULL, Qcrayon2InputInfo, Qcrayon2DIPInfo, + Qcrayon2Init, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQjinsei = { + "qjinsei", NULL, NULL, NULL, "1992", + "Quiz Jinsei Gekijoh (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30AF\u30A4\u30BA \u4EBA\u751F\u5287\u5834 (Japan)\0Quiz Jinsei Gekijoh\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QjinseiRomInfo, QjinseiRomName, NULL, NULL, QjinseiInputInfo, QjinseiDIPInfo, + QjinseiInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQtorimon = { + "qtorimon", NULL, NULL, NULL, "1990", + "Quiz Torimonochou (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u304F\u3044\u305A \u82E6\u80C3\u982D \u6355\u7269\u5E33 (Japan)\0Quiz Torimonochou\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QtorimonRomInfo, QtorimonRomName, NULL, NULL, QtorimonInputInfo, QtorimonDIPInfo, + QtorimonInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x800, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQuizhq = { + "quizhq", NULL, NULL, NULL, "1990", + "Quiz H.Q. (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QuizhqRomInfo, QuizhqRomName, NULL, NULL, QuizhqInputInfo, QuizhqDIPInfo, + QuizhqInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQzchikyu = { + "qzchikyu", NULL, NULL, NULL, "1991", + "Quiz Chikyu Bouei Gun (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30AF\u30A4\u30BA \u5730\u7403\u9632\u885B\u8ECD (Japan)\0Quiz Chikyu Bouei Gun\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QzchikyuRomInfo, QzchikyuRomName, NULL, NULL, QzchikyuInputInfo, QzchikyuDIPInfo, + QzchikyuInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvQzquest = { + "qzquest", NULL, NULL, NULL, "1991", + "Quiz Quest - Hime to Yuusha no Monogatari (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u30AF\u30A4\u30BA \u30AF\u30A8\u30B9\u30C8 \uFF0D\u59EB\u3068\u52C7\u8005\u306E\u7269\u8A9E\uFF0D (Japan)\0Quiz Quest - Hime to Yuusha no Monogatari\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, QzquestRomInfo, QzquestRomName, NULL, NULL, QzquestInputInfo, QzquestDIPInfo, + QzquestInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSolfigtr = { + "solfigtr", NULL, NULL, NULL, "1991", + "Solitary Fighter (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_VSFIGHT, 0, + NULL, SolfigtrRomInfo, SolfigtrRomName, NULL, NULL, SolfigtrInputInfo, SolfigtrDIPInfo, + SolfigtrInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvSsi = { + "ssi", NULL, NULL, NULL, "1990", + "Super Space Invaders '91 (World)\0", NULL, "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOF2, GBF_SHOOT, 0, + NULL, SsiRomInfo, SsiRomName, NULL, NULL, SsiInputInfo, SsiDIPInfo, + SsiInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvMajest12 = { + "majest12", "ssi", NULL, NULL, "1990", + "Majestic Twelve - The Space Invaders Part IV (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOF2, GBF_SHOOT, 0, + NULL, Majest12RomInfo, Majest12RomName, NULL, NULL, SsiInputInfo, Majest12DIPInfo, + SsiInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 224, 320, 3, 4 +}; + +struct BurnDriver BurnDrvThundfox = { + "thundfox", NULL, NULL, NULL, "1990", + "Thunder Fox (World)\0", "NULL", "Taito Corporation Japan", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, ThundfoxRomInfo, ThundfoxRomName, NULL, NULL, ThundfoxInputInfo, ThundfoxDIPInfo, + ThundfoxInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThundfoxj = { + "thundfoxj", "thundfox", NULL, NULL, "1990", + "Thunder Fox (Japan)\0", "NULL", "Taito Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, ThundfoxjRomInfo, ThundfoxjRomName, NULL, NULL, ThundfoxInputInfo, ThundfoxjDIPInfo, + ThundfoxInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvThundfoxu = { + "thundfoxu", "thundfox", NULL, NULL, "1990", + "Thunder Fox (US)\0", "NULL", "Taito America Corporation", "Taito-F2", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOF2, GBF_SCRFIGHT, 0, + NULL, ThundfoxuRomInfo, ThundfoxuRomName, NULL, NULL, ThundfoxInputInfo, ThundfoxuDIPInfo, + ThundfoxInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvYesnoj = { + "yesnoj", NULL, NULL, NULL, "1992", + "Yes/No Sinri Tokimeki Chart\0", NULL, "Taito Corporation", "Taito-F2", + L"\uFF39\uFF45\uFF53.\uFF2E\uFF4F \u5FC3\u7406 \u30C8\u30AD\u30E1\u30AD\u30C1\u30E3\u30FC\u30C8\0Yes/No Sinri Tokimeki Chart\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, YesnojRomInfo, YesnojRomName, NULL, NULL, YesnojInputInfo, YesnojDIPInfo, + YesnojInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvYuyugogo = { + "yuyugogo", NULL, NULL, NULL, "1990", + "Yuuyu no Quiz de GO!GO! (Japan)\0", NULL, "Taito Corporation", "Taito-F2", + L"\u3086\u3046\u3086 \u306E\u30AF\u30A4\u30BA\u3067 \uFF27\uFF4F!\uFF27\uFF4F! (Japan)\0Yuuyu no Quiz de GO!GO!\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOF2, GBF_QUIZ, 0, + NULL, YuyugogoRomInfo, YuyugogoRomName, NULL, NULL, YuyugogoInputInfo, YuyugogoDIPInfo, + YuyugogoInit, TaitoF2Exit, TaitoF2Frame, NULL, TaitoF2Scan, + NULL, 0x2000, 320, 224, 4, 3 +}; diff --git a/src/burn/drivers/taito/d_taitomisc.cpp b/src/burn/drivers/taito/d_taitomisc.cpp new file mode 100644 index 00000000..e390f2ad --- /dev/null +++ b/src/burn/drivers/taito/d_taitomisc.cpp @@ -0,0 +1,5873 @@ +// PC080SN & PC090OJ based games + +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "msm5205.h" +#include "burn_ym2151.h" +#include "burn_ym2203.h" +#include "burn_gun.h" + +static UINT32 RastanADPCMPos; +static INT32 RastanADPCMData; +static UINT8 OpwolfADPCM_B[0x08]; +static UINT8 OpwolfADPCM_C[0x08]; +static UINT32 OpwolfADPCMPos[2]; +static UINT32 OpwolfADPCMEnd[2]; +static INT32 OpwolfADPCMData[2]; +static INT32 OpWolfGunXOffset; +static INT32 OpWolfGunYOffset; + +static UINT8 DariusADPCMCommand; +static INT32 DariusNmiEnable; +static UINT16 DariusCoinWord; + +static UINT16 VolfiedVidCtrl; +static UINT16 VolfiedVidMask; + +static UINT16 *pTopspeedTempDraw = NULL; + +static void DariusDraw(); +static void OpwolfDraw(); +static void RainbowDraw(); +static void JumpingDraw(); +static void RastanDraw(); +static void TopspeedDraw(); +static void VolfiedDraw(); + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo DariusInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort2 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort2 + 2, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort2 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort2 + 3, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort2 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Darius) + +static struct BurnInputInfo OpwolfInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort0 + 1, "p2 coin" }, + + A("P1 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "mouse x-axis" ), + A("P1 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 0, "mouse button 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 1, "mouse button 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort1 + 2, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort1 + 3, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Opwolf) + +static struct BurnInputInfo RainbowInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort1 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , TaitoInputPort2 + 4, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort2 + 5, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort2 + 6, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort2 + 7, "p1 fire 2" }, + + {"P2 Left" , BIT_DIGITAL , TaitoInputPort3 + 4, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort3 + 5, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort3 + 6, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort3 + 7, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort0 + 7, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Rainbow) + +static struct BurnInputInfo JumpingInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort0 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p2 start" }, + + {"P1 Left" , BIT_DIGITAL , TaitoInputPort1 + 7, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort1 + 6, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 1, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 2, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Jumping) + +static struct BurnInputInfo RastanInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort3 + 5, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort3 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort3 + 6, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort3 + 4, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort0 + 3, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort1 + 3, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TaitoInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort3 + 0, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort3 + 2, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Rastan) + +static struct BurnInputInfo TopspeedInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p2 coin" }, + + A("P1 Steering" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p1 fire 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 fire 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 fire 3" }, + {"P1 Fire 4" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p1 fire 4" }, + {"P1 Fire 5" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p1 fire 5" }, + {"P1 Fire 6" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 6" }, + {"P1 Fire 7" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p1 fire 7" }, + {"P1 Fire 8" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 fire 8" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Topspeed) + +static struct BurnInputInfo VolfiedInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TaitoInputPort1 + 0, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TaitoInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TaitoInputPort1 + 1, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TaitoInputPort0 + 5, "p2 start" }, + + {"P1 Up" , BIT_DIGITAL , TaitoInputPort2 + 2, "p1 up" }, + {"P1 Down" , BIT_DIGITAL , TaitoInputPort2 + 3, "p1 down" }, + {"P1 Left" , BIT_DIGITAL , TaitoInputPort2 + 4, "p1 left" }, + {"P1 Right" , BIT_DIGITAL , TaitoInputPort2 + 5, "p1 right" }, + {"P1 Fire 1" , BIT_DIGITAL , TaitoInputPort2 + 6, "p1 fire 1" }, + + {"P2 Up" , BIT_DIGITAL , TaitoInputPort3 + 1, "p2 up" }, + {"P2 Down" , BIT_DIGITAL , TaitoInputPort3 + 2, "p2 down" }, + {"P2 Left" , BIT_DIGITAL , TaitoInputPort3 + 3, "p2 left" }, + {"P2 Right" , BIT_DIGITAL , TaitoInputPort3 + 4, "p2 right" }, + {"P2 Fire 1" , BIT_DIGITAL , TaitoInputPort3 + 5, "p2 fire 1" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TaitoInputPort0 + 7, "service" }, + {"Tilt" , BIT_DIGITAL , TaitoInputPort2 + 0, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Volfied) + +#undef A + +static void DariusMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xfc; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] -= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] -= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] -= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] -= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + if (TaitoInputPort2[0]) TaitoInput[2] |= 0x01; + if (TaitoInputPort2[1]) TaitoInput[2] |= 0x02; + if (TaitoInputPort2[2]) TaitoInput[2] -= 0x04; + if (TaitoInputPort2[3]) TaitoInput[2] -= 0x08; + if (TaitoInputPort2[4]) TaitoInput[2] -= 0x10; + if (TaitoInputPort2[5]) TaitoInput[2] -= 0x20; + if (TaitoInputPort2[6]) TaitoInput[2] -= 0x40; + if (TaitoInputPort2[7]) TaitoInput[2] -= 0x80; +} + +static void OpwolfMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xfc; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] |= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] |= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] -= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] -= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); + + OpwolfCChipUpdate(TaitoInput[0], TaitoInput[1]); +} + +static void OpwolfbMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xfc; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] |= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] |= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] -= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] -= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); +} + +static void RainbowMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xfc; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] -= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] -= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] |= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] |= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + if (TaitoInputPort2[0]) TaitoInput[2] -= 0x01; + if (TaitoInputPort2[1]) TaitoInput[2] -= 0x02; + if (TaitoInputPort2[2]) TaitoInput[2] -= 0x04; + if (TaitoInputPort2[3]) TaitoInput[2] -= 0x08; + if (TaitoInputPort2[4]) TaitoInput[2] -= 0x10; + if (TaitoInputPort2[5]) TaitoInput[2] -= 0x20; + if (TaitoInputPort2[6]) TaitoInput[2] -= 0x40; + if (TaitoInputPort2[7]) TaitoInput[2] -= 0x80; + + if (TaitoInputPort3[0]) TaitoInput[3] -= 0x01; + if (TaitoInputPort3[1]) TaitoInput[3] -= 0x02; + if (TaitoInputPort3[2]) TaitoInput[3] -= 0x04; + if (TaitoInputPort3[3]) TaitoInput[3] -= 0x08; + if (TaitoInputPort3[4]) TaitoInput[3] -= 0x10; + if (TaitoInputPort3[5]) TaitoInput[3] -= 0x20; + if (TaitoInputPort3[6]) TaitoInput[3] -= 0x40; + if (TaitoInputPort3[7]) TaitoInput[3] -= 0x80; + + RainbowCChipUpdate(TaitoInput[0], TaitoInput[1], TaitoInput[2], TaitoInput[3]); +} + +static void JumpingMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] -= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] -= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] -= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] -= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; +} + +static void RastanMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xff; + TaitoInput[2] = 0x8f; + TaitoInput[3] = 0x1f; + + if (TaitoInputPort0[0]) TaitoInput[0] -= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] -= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] -= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] -= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + if (TaitoInputPort3[0]) TaitoInput[3] -= 0x01; + if (TaitoInputPort3[1]) TaitoInput[3] -= 0x02; + if (TaitoInputPort3[2]) TaitoInput[3] -= 0x04; + if (TaitoInputPort3[3]) TaitoInput[3] -= 0x08; + if (TaitoInputPort3[4]) TaitoInput[3] -= 0x10; + if (TaitoInputPort3[5]) TaitoInput[3] |= 0x20; + if (TaitoInputPort3[6]) TaitoInput[3] |= 0x40; + if (TaitoInputPort3[7]) TaitoInput[3] |= 0x80; +} + +static void TopspeedMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0x13; + TC0220IOCInput[1] = 0x0f; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] |= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] |= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] |= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] |= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] |= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] |= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] |= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] |= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] |= 0x80; + + if (TC0220IOCInputPort2[0]) TC0220IOCInput[2] -= 0x01; + if (TC0220IOCInputPort2[1]) TC0220IOCInput[2] -= 0x02; + if (TC0220IOCInputPort2[2]) TC0220IOCInput[2] -= 0x04; + if (TC0220IOCInputPort2[3]) TC0220IOCInput[2] -= 0x08; + if (TC0220IOCInputPort2[4]) TC0220IOCInput[2] -= 0x10; + if (TC0220IOCInputPort2[5]) TC0220IOCInput[2] -= 0x20; + if (TC0220IOCInputPort2[6]) TC0220IOCInput[2] -= 0x40; + if (TC0220IOCInputPort2[7]) TC0220IOCInput[2] -= 0x80; +} + +static void VolfiedMakeInputs() +{ + // Reset Inputs + TaitoInput[0] = 0xff; + TaitoInput[1] = 0xfc; + TaitoInput[2] = 0xff; + TaitoInput[3] = 0xff; + + if (TaitoInputPort0[0]) TaitoInput[0] -= 0x01; + if (TaitoInputPort0[1]) TaitoInput[0] -= 0x02; + if (TaitoInputPort0[2]) TaitoInput[0] -= 0x04; + if (TaitoInputPort0[3]) TaitoInput[0] -= 0x08; + if (TaitoInputPort0[4]) TaitoInput[0] -= 0x10; + if (TaitoInputPort0[5]) TaitoInput[0] -= 0x20; + if (TaitoInputPort0[6]) TaitoInput[0] -= 0x40; + if (TaitoInputPort0[7]) TaitoInput[0] -= 0x80; + + if (TaitoInputPort1[0]) TaitoInput[1] |= 0x01; + if (TaitoInputPort1[1]) TaitoInput[1] |= 0x02; + if (TaitoInputPort1[2]) TaitoInput[1] -= 0x04; + if (TaitoInputPort1[3]) TaitoInput[1] -= 0x08; + if (TaitoInputPort1[4]) TaitoInput[1] -= 0x10; + if (TaitoInputPort1[5]) TaitoInput[1] -= 0x20; + if (TaitoInputPort1[6]) TaitoInput[1] -= 0x40; + if (TaitoInputPort1[7]) TaitoInput[1] -= 0x80; + + if (TaitoInputPort2[0]) TaitoInput[2] -= 0x01; + if (TaitoInputPort2[1]) TaitoInput[2] -= 0x02; + if (TaitoInputPort2[2]) TaitoInput[2] -= 0x04; + if (TaitoInputPort2[3]) TaitoInput[2] -= 0x08; + if (TaitoInputPort2[4]) TaitoInput[2] -= 0x10; + if (TaitoInputPort2[5]) TaitoInput[2] -= 0x20; + if (TaitoInputPort2[6]) TaitoInput[2] -= 0x40; + if (TaitoInputPort2[7]) TaitoInput[2] -= 0x80; + + if (TaitoInputPort3[0]) TaitoInput[3] -= 0x01; + if (TaitoInputPort3[1]) TaitoInput[3] -= 0x02; + if (TaitoInputPort3[2]) TaitoInput[3] -= 0x04; + if (TaitoInputPort3[3]) TaitoInput[3] -= 0x08; + if (TaitoInputPort3[4]) TaitoInput[3] -= 0x10; + if (TaitoInputPort3[5]) TaitoInput[3] -= 0x20; + if (TaitoInputPort3[6]) TaitoInput[3] -= 0x40; + if (TaitoInputPort3[7]) TaitoInput[3] -= 0x80; +} + +static struct BurnDIPInfo DariusDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x13, 0x01, 0x02, 0x02, "Normal" }, + {0x13, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "Every 600k" }, + {0x14, 0x01, 0x0c, 0x0c, "600k only" }, + {0x14, 0x01, 0x0c, 0x04, "800k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Darius) + +static struct BurnDIPInfo DariuseDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x13, 0x01, 0x02, 0x02, "Normal" }, + {0x13, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "Every 600k" }, + {0x14, 0x01, 0x0c, 0x0c, "600k only" }, + {0x14, 0x01, 0x0c, 0x04, "800k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Dariuse) + +static struct BurnDIPInfo DariusjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Auto Fire" }, + {0x13, 0x01, 0x02, 0x02, "Normal" }, + {0x13, 0x01, 0x02, 0x00, "Fast" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x08, "Every 600k" }, + {0x14, 0x01, 0x0c, 0x0c, "600k only" }, + {0x14, 0x01, 0x0c, 0x04, "800k only" }, + {0x14, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, +}; + +STDDIPINFO(Dariusj) + +static struct BurnDIPInfo OpwolfDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x08, 0x00, "Off" }, + {0x0a, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0a, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0a, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0a, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x03, 0x02, "Easy" }, + {0x0b, 0x01, 0x03, 0x03, "Medium" }, + {0x0b, 0x01, 0x03, 0x01, "Hard" }, + {0x0b, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Ammo Magazines at Start" }, + {0x0b, 0x01, 0x0c, 0x00, "4" }, + {0x0b, 0x01, 0x0c, 0x04, "5" }, + {0x0b, 0x01, 0x0c, 0x0c, "6" }, + {0x0b, 0x01, 0x0c, 0x08, "7" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0b, 0x01, 0x80, 0x80, "Japanese" }, + {0x0b, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Opwolf) + +static struct BurnDIPInfo OpwolfuDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x08, 0x00, "Off" }, + {0x0a, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0a, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0a, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0a, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0a, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0a, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0a, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x03, 0x02, "Easy" }, + {0x0b, 0x01, 0x03, 0x03, "Medium" }, + {0x0b, 0x01, 0x03, 0x01, "Hard" }, + {0x0b, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Ammo Magazines at Start" }, + {0x0b, 0x01, 0x0c, 0x00, "4" }, + {0x0b, 0x01, 0x0c, 0x04, "5" }, + {0x0b, 0x01, 0x0c, 0x0c, "6" }, + {0x0b, 0x01, 0x0c, 0x08, "7" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x0b, 0x01, 0x80, 0x80, "Japanese" }, + {0x0b, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Opwolfu) + +static struct BurnDIPInfo OpwolfbDIPList[]= +{ + // Default Values + {0x0a, 0xff, 0xff, 0xff, NULL }, + {0x0b, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0a, 0x01, 0x02, 0x02, "Off" }, + {0x0a, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0a, 0x01, 0x04, 0x04, "Off" }, + {0x0a, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0a, 0x01, 0x08, 0x00, "Off" }, + {0x0a, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0a, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0a, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0a, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0a, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0a, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0a, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0b, 0x01, 0x03, 0x02, "Easy" }, + {0x0b, 0x01, 0x03, 0x03, "Medium" }, + {0x0b, 0x01, 0x03, 0x01, "Hard" }, + {0x0b, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Ammo Magazines at Start" }, + {0x0b, 0x01, 0x0c, 0x00, "4" }, + {0x0b, 0x01, 0x0c, 0x04, "5" }, + {0x0b, 0x01, 0x0c, 0x0c, "6" }, + {0x0b, 0x01, 0x0c, 0x08, "7" }, +}; + +STDDIPINFO(Opwolfb) + +static struct BurnDIPInfo RainbowDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xfe, NULL }, + {0x10, 0xff, 0xff, 0xbf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0f, 0x01, 0x01, 0x00, "Upright" }, + {0x0f, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x0f, 0x01, 0x02, 0x02, "Off" }, + {0x0f, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x10, 0x01, 0x03, 0x02, "Easy" }, + {0x10, 0x01, 0x03, 0x03, "Medium" }, + {0x10, 0x01, 0x03, 0x01, "Hard" }, + {0x10, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x10, 0x01, 0x04, 0x04, "100k, 1000k" }, + {0x10, 0x01, 0x04, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Complete Bonus" }, + {0x10, 0x01, 0x08, 0x08, "1 Up" }, + {0x10, 0x01, 0x08, 0x00, "100k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x10, 0x01, 0x30, 0x10, "1" }, + {0x10, 0x01, 0x30, 0x00, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x20, "4" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x10, 0x01, 0x40, 0x00, "English" }, + {0x10, 0x01, 0x40, 0x40, "Japanese" }, +}; + +STDDIPINFO(Rainbow) + +static struct BurnDIPInfo JumpingDIPList[]= +{ + // Default Values + {0x09, 0xff, 0xff, 0xfe, NULL }, + {0x0a, 0xff, 0xff, 0xbf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x09, 0x01, 0x08, 0x00, "Off" }, + {0x09, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x09, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x09, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x09, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x09, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x09, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x09, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x09, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x09, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0a, 0x01, 0x03, 0x02, "Easy" }, + {0x0a, 0x01, 0x03, 0x03, "Medium" }, + {0x0a, 0x01, 0x03, 0x01, "Hard" }, + {0x0a, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Bonus Life" }, + {0x0a, 0x01, 0x04, 0x04, "100k, 1000k" }, + {0x0a, 0x01, 0x04, 0x00, "None" }, + + {0 , 0xfe, 0 , 2 , "Complete Bonus" }, + {0x0a, 0x01, 0x08, 0x08, "1 Up" }, + {0x0a, 0x01, 0x08, 0x00, "100k" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0a, 0x01, 0x30, 0x10, "1" }, + {0x0a, 0x01, 0x30, 0x00, "2" }, + {0x0a, 0x01, 0x30, 0x30, "3" }, + {0x0a, 0x01, 0x30, 0x20, "4" }, +}; + +STDDIPINFO(Jumping) + +static struct BurnDIPInfo RastanDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k, 200k, 400k, 600k, 800k"}, + {0x14, 0x01, 0x0c, 0x08, "150k, 300k, 600k, 900k, 1200k"}, + {0x14, 0x01, 0x0c, 0x04, "200k, 400k, 800k, 1200k, 1600k"}, + {0x14, 0x01, 0x0c, 0x00, "250k, 500k, 1000k, 1500k, 2000k"}, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Rastan) + +static struct BurnDIPInfo RastsagaDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xfe, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x13, 0x01, 0x01, 0x00, "Upright" }, + {0x13, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "100k, 200k, 400k, 600k, 800k"}, + {0x14, 0x01, 0x0c, 0x08, "150k, 300k, 600k, 900k, 1200k"}, + {0x14, 0x01, 0x0c, 0x04, "200k, 400k, 800k, 1200k, 1600k"}, + {0x14, 0x01, 0x0c, 0x00, "250k, 500k, 1000k, 1500k, 2000k"}, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + {0x14, 0x01, 0x30, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, +}; + +STDDIPINFO(Rastsaga) + +static struct BurnDIPInfo TopspeedDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0f, 0x01, 0x03, 0x03, "Deluxe Motorized Cabinet" }, + {0x0f, 0x01, 0x03, 0x02, "Upright" }, + {0x0f, 0x01, 0x03, 0x01, "Upright (alt)" }, + {0x0f, 0x01, 0x03, 0x00, "Standard Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0f, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0f, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Initial Time" }, + {0x10, 0x01, 0x0c, 0x00, "40 seconds" }, + {0x10, 0x01, 0x0c, 0x04, "50 seconds" }, + {0x10, 0x01, 0x0c, 0x0c, "60 seconds" }, + {0x10, 0x01, 0x0c, 0x08, "70 seconds" }, + + {0 , 0xfe, 0 , 4 , "Nitros" }, + {0x10, 0x01, 0x30, 0x20, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x10, "4" }, + {0x10, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x40, 0x40, "Off" }, + {0x10, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Continue Price" }, + {0x10, 0x01, 0x80, 0x00, "1 Coin 1 Credit" }, + {0x10, 0x01, 0x80, 0x80, "Same as start" }, +}; + +STDDIPINFO(Topspeed) + +static struct BurnDIPInfo FullthrlDIPList[]= +{ + // Default Values + {0x0f, 0xff, 0xff, 0xff, NULL }, + {0x10, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0f, 0x01, 0x03, 0x03, "Deluxe Motorized Cabinet" }, + {0x0f, 0x01, 0x03, 0x02, "Upright" }, + {0x0f, 0x01, 0x03, 0x01, "Upright (alt)" }, + {0x0f, 0x01, 0x03, 0x00, "Standard Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0f, 0x01, 0x04, 0x04, "Off" }, + {0x0f, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0f, 0x01, 0x08, 0x00, "Off" }, + {0x0f, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0f, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0f, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0f, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0f, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0f, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Initial Time" }, + {0x10, 0x01, 0x0c, 0x00, "40 seconds" }, + {0x10, 0x01, 0x0c, 0x04, "50 seconds" }, + {0x10, 0x01, 0x0c, 0x0c, "60 seconds" }, + {0x10, 0x01, 0x0c, 0x08, "70 seconds" }, + + {0 , 0xfe, 0 , 4 , "Nitros" }, + {0x10, 0x01, 0x30, 0x20, "2" }, + {0x10, 0x01, 0x30, 0x30, "3" }, + {0x10, 0x01, 0x30, 0x10, "4" }, + {0x10, 0x01, 0x30, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x10, 0x01, 0x40, 0x40, "Off" }, + {0x10, 0x01, 0x40, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Continue Price" }, + {0x10, 0x01, 0x80, 0x00, "1 Coin 1 Credit" }, + {0x10, 0x01, 0x80, 0x80, "Same as start" }, +}; + +STDDIPINFO(Fullthrl) + +static struct BurnDIPInfo VolfiedDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x11, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x11, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x03, 0x02, "20k 40k 120k 480k 2400k" }, + {0x12, 0x01, 0x03, 0x03, "50k 150k 600k 3000k" }, + {0x12, 0x01, 0x03, 0x01, "70k 280k 1400k" }, + {0x12, 0x01, 0x03, 0x00, "100k 500k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x12, 0x01, 0x70, 0x70, "3" }, + {0x12, 0x01, 0x70, 0x60, "4" }, + {0x12, 0x01, 0x70, 0x50, "5" }, + {0x12, 0x01, 0x70, 0x40, "6" }, + {0x12, 0x01, 0x70, 0x00, "32768" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x80, 0x80, "Japanese" }, + {0x12, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Volfied) + +static struct BurnDIPInfo VolfiedjDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x11, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x11, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x11, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x11, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x11, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x03, 0x02, "20k 40k 120k 480k 2400k" }, + {0x12, 0x01, 0x03, 0x03, "50k 150k 600k 3000k" }, + {0x12, 0x01, 0x03, 0x01, "70k 280k 1400k" }, + {0x12, 0x01, 0x03, 0x00, "100k 500k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x12, 0x01, 0x70, 0x70, "3" }, + {0x12, 0x01, 0x70, 0x60, "4" }, + {0x12, 0x01, 0x70, 0x50, "5" }, + {0x12, 0x01, 0x70, 0x40, "6" }, + {0x12, 0x01, 0x70, 0x00, "32768" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x80, 0x80, "Japanese" }, + {0x12, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Volfiedj) + +static struct BurnDIPInfo VolfieduDIPList[]= +{ + // Default Values + {0x11, 0xff, 0xff, 0xfe, NULL }, + {0x12, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x11, 0x01, 0x01, 0x00, "Upright" }, + {0x11, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x11, 0x01, 0x02, 0x02, "Off" }, + {0x11, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x11, 0x01, 0x04, 0x04, "Off" }, + {0x11, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x11, 0x01, 0x08, 0x00, "Off" }, + {0x11, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x11, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x11, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x12, 0x01, 0x03, 0x02, "20k 40k 120k 480k 2400k" }, + {0x12, 0x01, 0x03, 0x03, "50k 150k 600k 3000k" }, + {0x12, 0x01, 0x03, 0x01, "70k 280k 1400k" }, + {0x12, 0x01, 0x03, 0x00, "100k 500k" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x12, 0x01, 0x0c, 0x08, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Medium" }, + {0x12, 0x01, 0x0c, 0x04, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 5 , "Lives" }, + {0x12, 0x01, 0x70, 0x70, "3" }, + {0x12, 0x01, 0x70, 0x60, "4" }, + {0x12, 0x01, 0x70, 0x50, "5" }, + {0x12, 0x01, 0x70, 0x40, "6" }, + {0x12, 0x01, 0x70, 0x00, "32768" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x12, 0x01, 0x80, 0x80, "Japanese" }, + {0x12, 0x01, 0x80, 0x00, "English" }, +}; + +STDDIPINFO(Volfiedu) + +static struct BurnRomInfo DariusRomDesc[] = { + { "da-59.bin", 0x10000, 0x11aab4eb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "da-58.bin", 0x10000, 0x5f71e697, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "da-61.bin", 0x10000, 0x4736aa9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "da-66.bin", 0x10000, 0x4ede5f56, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_31.187", 0x10000, 0xe9bb5d89, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_30.154", 0x10000, 0x9eb5e127, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "a96_33-1.190", 0x10000, 0xff186048, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_32-1.157", 0x10000, 0xd9719de8, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_35-1.191", 0x10000, 0xb3280193, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_34-1.158", 0x10000, 0xca3b2573, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "a96_57.33", 0x10000, 0x33ceb730, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "a96_56.18", 0x10000, 0x292ef55c, BRF_ESS | BRF_PRG | TAITO_Z80ROM2 }, + + { "a96_48.24", 0x10000, 0x39c9b3aa, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_51.47", 0x10000, 0x1bf8f0d3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_49.25", 0x10000, 0x37a7d88a, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_52.48", 0x10000, 0x2d9b2128, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_50.26", 0x10000, 0x75d738e4, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_53.49", 0x10000, 0x0173484c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "a96_54.143", 0x04000, 0x51c02ae2, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + { "a96_55.144", 0x04000, 0x771e4d98, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + + { "a96_44.179", 0x10000, 0xbbc18878, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_45.200", 0x10000, 0x616cdd8b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_46.180", 0x10000, 0xfec35418, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_47.201", 0x10000, 0x8df9286a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_40.177", 0x10000, 0xb699a51e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_41.198", 0x10000, 0x97128a3a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_42.178", 0x10000, 0x7f55ee0f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_43.199", 0x10000, 0xc7cad469, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "da-62.bin", 0x10000, 0x9179862c, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "da-63.bin", 0x10000, 0xfa19cfff, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "da-64.bin", 0x10000, 0x814c676f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "da-65.bin", 0x10000, 0x14eee326, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "a96-24.163", 0x00400, 0x0fa8be7f, BRF_OPT }, + { "a96-25.164", 0x00400, 0x265508a6, BRF_OPT }, + { "a96-26.165", 0x00400, 0x4891b9c0, BRF_OPT }, +}; + +STD_ROM_PICK(Darius) +STD_ROM_FN(Darius) + +static struct BurnRomInfo DariusjRomDesc[] = { + { "a96_29-1.185", 0x10000, 0x75486f62, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_28-1.152", 0x10000, 0xfb34d400, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_31.187", 0x10000, 0xe9bb5d89, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_30.154", 0x10000, 0x9eb5e127, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "a96_33-1.190", 0x10000, 0xff186048, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_32-1.157", 0x10000, 0xd9719de8, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_35-1.191", 0x10000, 0xb3280193, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96_34-1.158", 0x10000, 0xca3b2573, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "a96_57.33", 0x10000, 0x33ceb730, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "a96_56.18", 0x10000, 0x292ef55c, BRF_ESS | BRF_PRG | TAITO_Z80ROM2 }, + + { "a96_48.24", 0x10000, 0x39c9b3aa, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_51.47", 0x10000, 0x1bf8f0d3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_49.25", 0x10000, 0x37a7d88a, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_52.48", 0x10000, 0x2d9b2128, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_50.26", 0x10000, 0x75d738e4, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_53.49", 0x10000, 0x0173484c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "a96_54.143", 0x04000, 0x51c02ae2, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + { "a96_55.144", 0x04000, 0x771e4d98, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + + { "a96_44.179", 0x10000, 0xbbc18878, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_45.200", 0x10000, 0x616cdd8b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_46.180", 0x10000, 0xfec35418, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_47.201", 0x10000, 0x8df9286a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_40.177", 0x10000, 0xb699a51e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_41.198", 0x10000, 0x97128a3a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_42.178", 0x10000, 0x7f55ee0f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_43.199", 0x10000, 0xc7cad469, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_36.175", 0x10000, 0xaf598141, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_37.196", 0x10000, 0xb48137c8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_38.176", 0x10000, 0xe4f3e3a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_39.197", 0x10000, 0xea30920f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "a96-24.163", 0x00400, 0x0fa8be7f, BRF_OPT }, + { "a96-25.164", 0x00400, 0x265508a6, BRF_OPT }, + { "a96-26.165", 0x00400, 0x4891b9c0, BRF_OPT }, +}; + +STD_ROM_PICK(Dariusj) +STD_ROM_FN(Dariusj) + +static struct BurnRomInfo DariusoRomDesc[] = { + { "a96-29.185", 0x10000, 0xf775162b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96-28.152", 0x10000, 0x4721d667, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_31.187", 0x10000, 0xe9bb5d89, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_30.154", 0x10000, 0x9eb5e127, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "a96-33.190", 0x10000, 0xd2f340d2, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96-32.157", 0x10000, 0x044c9848, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96-35.191", 0x10000, 0xb8ed718b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "a96-34.158", 0x10000, 0x7556a660, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "a96_57.33", 0x10000, 0x33ceb730, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "a96_56.18", 0x10000, 0x292ef55c, BRF_ESS | BRF_PRG | TAITO_Z80ROM2 }, + + { "a96_48.24", 0x10000, 0x39c9b3aa, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_51.47", 0x10000, 0x1bf8f0d3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_49.25", 0x10000, 0x37a7d88a, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_52.48", 0x10000, 0x2d9b2128, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_50.26", 0x10000, 0x75d738e4, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_53.49", 0x10000, 0x0173484c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "a96_54.143", 0x04000, 0x51c02ae2, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + { "a96_55.144", 0x04000, 0x771e4d98, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + + { "a96_44.179", 0x10000, 0xbbc18878, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_45.200", 0x10000, 0x616cdd8b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_46.180", 0x10000, 0xfec35418, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_47.201", 0x10000, 0x8df9286a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_40.177", 0x10000, 0xb699a51e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_41.198", 0x10000, 0x97128a3a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_42.178", 0x10000, 0x7f55ee0f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_43.199", 0x10000, 0xc7cad469, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_36.175", 0x10000, 0xaf598141, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_37.196", 0x10000, 0xb48137c8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_38.176", 0x10000, 0xe4f3e3a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_39.197", 0x10000, 0xea30920f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "a96-24.163", 0x00400, 0x0fa8be7f, BRF_OPT }, + { "a96-25.164", 0x00400, 0x265508a6, BRF_OPT }, + { "a96-26.165", 0x00400, 0x4891b9c0, BRF_OPT }, +}; + +STD_ROM_PICK(Dariuso) +STD_ROM_FN(Dariuso) + +static struct BurnRomInfo DariuseRomDesc[] = { + { "dae-68.bin", 0x10000, 0xed721127, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "dae-67.bin", 0x10000, 0xb99aea8c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "dae-70.bin", 0x10000, 0x54590b31, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a96_30.154", 0x10000, 0x9eb5e127, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "dae-72.bin", 0x10000, 0x248ca2cc, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "dae-71.bin", 0x10000, 0x65dd0403, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "dae-74.bin", 0x10000, 0x0ea31f60, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "dae-73.bin", 0x10000, 0x27036a4d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "a96_57.33", 0x10000, 0x33ceb730, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "a96_56.18", 0x10000, 0x292ef55c, BRF_ESS | BRF_PRG | TAITO_Z80ROM2 }, + + { "a96_48.24", 0x10000, 0x39c9b3aa, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_51.47", 0x10000, 0x1bf8f0d3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_49.25", 0x10000, 0x37a7d88a, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_52.48", 0x10000, 0x2d9b2128, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_50.26", 0x10000, 0x75d738e4, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "a96_53.49", 0x10000, 0x0173484c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "a96_54.143", 0x04000, 0x51c02ae2, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + { "a96_55.144", 0x04000, 0x771e4d98, BRF_GRA | TAITO_CHARSB_BYTESWAP }, + + { "a96_44.179", 0x10000, 0xbbc18878, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_45.200", 0x10000, 0x616cdd8b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_46.180", 0x10000, 0xfec35418, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_47.201", 0x10000, 0x8df9286a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_40.177", 0x10000, 0xb699a51e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_41.198", 0x10000, 0x97128a3a, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_42.178", 0x10000, 0x7f55ee0f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_43.199", 0x10000, 0xc7cad469, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_36.175", 0x10000, 0xaf598141, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_37.196", 0x10000, 0xb48137c8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_38.176", 0x10000, 0xe4f3e3a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "a96_39.197", 0x10000, 0xea30920f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "a96-24.163", 0x00400, 0x0fa8be7f, BRF_OPT }, + { "a96-25.164", 0x00400, 0x265508a6, BRF_OPT }, + { "a96-26.165", 0x00400, 0x4891b9c0, BRF_OPT }, +}; + +STD_ROM_PICK(Dariuse) +STD_ROM_FN(Dariuse) + +static struct BurnRomInfo OpwolfRomDesc[] = { + { "b20-05-02.40", 0x10000, 0x3ffbfe3a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-03-02.30", 0x10000, 0xfdabd8a5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-04.39", 0x10000, 0x216b4838, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-20.29", 0x10000, 0xd244431a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b20-07.10", 0x10000, 0x45c7ace3, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b20-13.13", 0x80000, 0xf6acdab1, BRF_GRA | TAITO_CHARS }, + + { "b20-14.72", 0x80000, 0x89f889e5, BRF_GRA | TAITO_SPRITESA }, + + { "b20-08.21", 0x80000, 0xf3e19c64, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Opwolf) +STD_ROM_FN(Opwolf) + +static struct BurnRomInfo OpwolfaRomDesc[] = { + { "b20-05-02.40", 0x10000, 0x3ffbfe3a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-03-02.30", 0x10000, 0xfdabd8a5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-04.39", 0x10000, 0x216b4838, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-17.29", 0x10000, 0x6043188e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b20-07.10", 0x10000, 0x45c7ace3, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b20-13.13", 0x80000, 0xf6acdab1, BRF_GRA | TAITO_CHARS }, + + { "b20-14.72", 0x80000, 0x89f889e5, BRF_GRA | TAITO_SPRITESA }, + + { "b20-08.21", 0x80000, 0xf3e19c64, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Opwolfa) +STD_ROM_FN(Opwolfa) + +static struct BurnRomInfo OpwolfjRomDesc[] = { + { "b20-05-02.40", 0x10000, 0x3ffbfe3a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-03-02.30", 0x10000, 0xfdabd8a5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-04.39", 0x10000, 0x216b4838, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-18.29", 0x10000, 0xfd202470, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b20-07.10", 0x10000, 0x45c7ace3, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b20-13.13", 0x80000, 0xf6acdab1, BRF_GRA | TAITO_CHARS }, + + { "b20-14.72", 0x80000, 0x89f889e5, BRF_GRA | TAITO_SPRITESA }, + + { "b20-08.21", 0x80000, 0xf3e19c64, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Opwolfj) +STD_ROM_FN(Opwolfj) + +static struct BurnRomInfo OpwolfuRomDesc[] = { + { "b20-05-02.40", 0x10000, 0x3ffbfe3a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-03-02.30", 0x10000, 0xfdabd8a5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-04.39", 0x10000, 0x216b4838, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b20-19.29", 0x10000, 0xb71bc44c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b20-07.10", 0x10000, 0x45c7ace3, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b20-13.13", 0x80000, 0xf6acdab1, BRF_GRA | TAITO_CHARS }, + + { "b20-14.72", 0x80000, 0x89f889e5, BRF_GRA | TAITO_SPRITESA }, + + { "b20-08.21", 0x80000, 0xf3e19c64, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Opwolfu) +STD_ROM_FN(Opwolfu) + +static struct BurnRomInfo OpwolfbRomDesc[] = { + { "opwlfb.12", 0x10000, 0xd87e4405, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "opwlfb.10", 0x10000, 0x9ab6f75c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "opwlfb.13", 0x10000, 0x61230c6e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "opwlfb.11", 0x10000, 0x342e318d, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "opwlfb.30", 0x08000, 0x0669b94c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "opwlfb.09", 0x08000, 0xab27a3dd, BRF_ESS | BRF_PRG | TAITO_Z80ROM2 }, + + { "opwlfb.08", 0x10000, 0x134d294e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.04", 0x10000, 0xde0ca98d, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.06", 0x10000, 0x317d0e66, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.02", 0x10000, 0x6231fdd0, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.07", 0x10000, 0xe1c4095e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.03", 0x10000, 0xccf8ba80, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.05", 0x10000, 0xfd9e72c8, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "opwlfb.01", 0x10000, 0x0a65f256, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "opwlfb.14", 0x10000, 0x663786eb, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.18", 0x10000, 0xde9ab08e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.15", 0x10000, 0x315b8aa9, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.19", 0x10000, 0x645cf85e, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.16", 0x10000, 0xe01099e3, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.20", 0x10000, 0xd80b9cc6, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.17", 0x10000, 0x56fbe61d, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "opwlfb.21", 0x10000, 0x97d25157, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "opwlfb.29", 0x10000, 0x05a9eac0, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.25", 0x10000, 0x85b87f58, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.28", 0x10000, 0x281b2175, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.24", 0x10000, 0x8efc5d4d, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.27", 0x10000, 0x441211a6, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.23", 0x10000, 0xa874c703, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.26", 0x10000, 0x86d1d42d, BRF_SND | TAITO_MSM5205_BYTESWAP }, + { "opwlfb.22", 0x10000, 0x9228481f, BRF_SND | TAITO_MSM5205_BYTESWAP }, + +}; + +STD_ROM_PICK(Opwolfb) +STD_ROM_FN(Opwolfb) + +static struct BurnRomInfo RainbowRomDesc[] = { + { "b22-10-1.19", 0x10000, 0xe34a50ca, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-11-1.20", 0x10000, 0x6a31a093, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-08-1.21", 0x10000, 0x15d6e17a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-09-1.22", 0x10000, 0x454e66bc, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-03.23", 0x20000, 0x3ebb0fb8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-04.24", 0x20000, 0x91625e7f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b22-14.43", 0x10000, 0x113c1a5b, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b22-01.2", 0x80000, 0xb76c9168, BRF_GRA | TAITO_CHARS }, + + { "b22-02.5", 0x80000, 0x1b87ecf0, BRF_GRA | TAITO_SPRITESA }, + { "b22-12.7", 0x10000, 0x67a76dc6, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b22-13.6", 0x10000, 0x2fda099f, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, +}; + +STD_ROM_PICK(Rainbow) +STD_ROM_FN(Rainbow) + +static struct BurnRomInfo RainbowoRomDesc[] = { + { "b22-10.19", 0x10000, 0x3b013495, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-11.20", 0x10000, 0x80041a3d, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-08.21", 0x10000, 0x962fb845, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-09.22", 0x10000, 0xf43efa27, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-03.23", 0x20000, 0x3ebb0fb8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-04.24", 0x20000, 0x91625e7f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b22-14.43", 0x10000, 0x113c1a5b, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b22-01.2", 0x80000, 0xb76c9168, BRF_GRA | TAITO_CHARS }, + + { "b22-02.5", 0x80000, 0x1b87ecf0, BRF_GRA | TAITO_SPRITESA }, + { "b22-12.7", 0x10000, 0x67a76dc6, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b22-13.6", 0x10000, 0x2fda099f, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, +}; + +STD_ROM_PICK(Rainbowo) +STD_ROM_FN(Rainbowo) + +static struct BurnRomInfo RainboweRomDesc[] = { + { "b39-01.19", 0x10000, 0x50690880, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b39-02.20", 0x10000, 0x4dead71f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b39-03.21", 0x10000, 0x4a4cb785, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b39-04.22", 0x10000, 0x4caa53bd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-03.23", 0x20000, 0x3ebb0fb8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-04.24", 0x20000, 0x91625e7f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b22-14.43", 0x10000, 0x113c1a5b, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b22-01.2", 0x80000, 0xb76c9168, BRF_GRA | TAITO_CHARS }, + + { "b22-02.5", 0x80000, 0x1b87ecf0, BRF_GRA | TAITO_SPRITESA }, + { "b22-12.7", 0x10000, 0x67a76dc6, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "b22-13.6", 0x10000, 0x2fda099f, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, +}; + +STD_ROM_PICK(Rainbowe) +STD_ROM_FN(Rainbowe) + +static struct BurnRomInfo JumpingRomDesc[] = { + { "jb1_h4", 0x10000, 0x3fab6b31, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "jb1_h8", 0x10000, 0x8c878827, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "jb1_i4", 0x10000, 0x443492cf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "jb1_i8", 0x10000, 0xed33bae1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-03.23", 0x20000, 0x3ebb0fb8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b22-04.24", 0x20000, 0x91625e7f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "jb1_f89", 0x10000, 0x0810d327, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP_JUMPING }, + + { "jb1_cd67", 0x10000, 0x8527c00e, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "jb2_ic8", 0x10000, 0x65b76309, BRF_GRA | TAITO_CHARS }, + { "jb2_ic7", 0x10000, 0x43a94283, BRF_GRA | TAITO_CHARS }, + { "jb2_ic10", 0x10000, 0xe61933fb, BRF_GRA | TAITO_CHARS }, + { "jb2_ic9", 0x10000, 0xed031eb2, BRF_GRA | TAITO_CHARS }, + { "jb2_ic12", 0x10000, 0x312700ca, BRF_GRA | TAITO_CHARS }, + { "jb2_ic11", 0x10000, 0xde3b0b88, BRF_GRA | TAITO_CHARS }, + { "jb2_ic14", 0x10000, 0x9fdc6c8e, BRF_GRA | TAITO_CHARS }, + { "jb2_ic13", 0x10000, 0x06226492, BRF_GRA | TAITO_CHARS }, + + { "jb2_ic62", 0x10000, 0x8548db6c, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic61", 0x10000, 0x37c5923b, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic60", 0x08000, 0x662a2f1e, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic78", 0x10000, 0x925865e1, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic77", 0x10000, 0xb09695d1, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic76", 0x08000, 0x41937743, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic93", 0x10000, 0xf644eeab, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic92", 0x10000, 0x3fbccd33, BRF_GRA | TAITO_SPRITESA }, + { "jb2_ic91", 0x08000, 0xd886c014, BRF_GRA | TAITO_SPRITESA }, + { "jb2_i121", 0x10000, 0x93df1e4d, BRF_GRA | TAITO_SPRITESA }, + { "jb2_i120", 0x10000, 0x7c4e893b, BRF_GRA | TAITO_SPRITESA }, + { "jb2_i119", 0x08000, 0x7e1d58d8, BRF_GRA | TAITO_SPRITESA }, +}; + +STD_ROM_PICK(Jumping) +STD_ROM_FN(Jumping) + +static struct BurnRomInfo RastanRomDesc[] = { + { "b04-35.19", 0x10000, 0x1c91dbb1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-37.07", 0x10000, 0xecf20bdd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-40.20", 0x10000, 0x0930d4b3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-39.08", 0x10000, 0xd95ade5e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-42.21", 0x10000, 0x1857a7cb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-43.09", 0x10000, 0xc34b9152, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b04-19.49", 0x10000, 0xee81fdd8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b04-01.40", 0x20000, 0xcd30de19, BRF_GRA | TAITO_CHARS }, + { "b04-03.39", 0x20000, 0xab67e064, BRF_GRA | TAITO_CHARS }, + { "b04-02.67", 0x20000, 0x54040fec, BRF_GRA | TAITO_CHARS }, + { "b04-04.66", 0x20000, 0x94737e93, BRF_GRA | TAITO_CHARS }, + + { "b04-05.15", 0x20000, 0xc22d94ac, BRF_GRA | TAITO_SPRITESA }, + { "b04-07.14", 0x20000, 0xb5632a51, BRF_GRA | TAITO_SPRITESA }, + { "b04-06.28", 0x20000, 0x002ccf39, BRF_GRA | TAITO_SPRITESA }, + { "b04-08.27", 0x20000, 0xfeafca05, BRF_GRA | TAITO_SPRITESA }, + + { "b04-20.76", 0x10000, 0xfd1a34cc, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Rastan) +STD_ROM_FN(Rastan) + +static struct BurnRomInfo RastanuRomDesc[] = { + { "b04-35.19", 0x10000, 0x1c91dbb1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-37.07", 0x10000, 0xecf20bdd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-45.20", 0x10000, 0x362812dd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-44.08", 0x10000, 0x51cc5508, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-42.21", 0x10000, 0x1857a7cb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-41-1.09", 0x10000, 0xbd403269, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b04-19.49", 0x10000, 0xee81fdd8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b04-01.40", 0x20000, 0xcd30de19, BRF_GRA | TAITO_CHARS }, + { "b04-03.39", 0x20000, 0xab67e064, BRF_GRA | TAITO_CHARS }, + { "b04-02.67", 0x20000, 0x54040fec, BRF_GRA | TAITO_CHARS }, + { "b04-04.66", 0x20000, 0x94737e93, BRF_GRA | TAITO_CHARS }, + + { "b04-05.15", 0x20000, 0xc22d94ac, BRF_GRA | TAITO_SPRITESA }, + { "b04-07.14", 0x20000, 0xb5632a51, BRF_GRA | TAITO_SPRITESA }, + { "b04-06.28", 0x20000, 0x002ccf39, BRF_GRA | TAITO_SPRITESA }, + { "b04-08.27", 0x20000, 0xfeafca05, BRF_GRA | TAITO_SPRITESA }, + + { "b04-20.76", 0x10000, 0xfd1a34cc, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Rastanu) +STD_ROM_FN(Rastanu) + +static struct BurnRomInfo Rastanu2RomDesc[] = { + { "rs19_38.bin", 0x10000, 0xa38ac909, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-21.7", 0x10000, 0x7c8dde9a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-23.20", 0x10000, 0x254b3dce, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-22.8", 0x10000, 0x98e8edcf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-25.21", 0x10000, 0xd1e5adee, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-24.9", 0x10000, 0xa3dcc106, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b04-19.49", 0x10000, 0xee81fdd8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b04-01.40", 0x20000, 0xcd30de19, BRF_GRA | TAITO_CHARS }, + { "b04-03.39", 0x20000, 0xab67e064, BRF_GRA | TAITO_CHARS }, + { "b04-02.67", 0x20000, 0x54040fec, BRF_GRA | TAITO_CHARS }, + { "b04-04.66", 0x20000, 0x94737e93, BRF_GRA | TAITO_CHARS }, + + { "b04-05.15", 0x20000, 0xc22d94ac, BRF_GRA | TAITO_SPRITESA }, + { "b04-07.14", 0x20000, 0xb5632a51, BRF_GRA | TAITO_SPRITESA }, + { "b04-06.28", 0x20000, 0x002ccf39, BRF_GRA | TAITO_SPRITESA }, + { "b04-08.27", 0x20000, 0xfeafca05, BRF_GRA | TAITO_SPRITESA }, + + { "b04-20.76", 0x10000, 0xfd1a34cc, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Rastanu2) +STD_ROM_FN(Rastanu2) + +static struct BurnRomInfo RastsagaRomDesc[] = { + { "b04-38.19", 0x10000, 0xa38ac909, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-37.7", 0x10000, 0xbad60872, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-40.20", 0x10000, 0x6bcf70dc, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-39.8", 0x10000, 0x8838ecc5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-42.21", 0x10000, 0xb626c439, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-43.9", 0x10000, 0xc928a516, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b04-19.49", 0x10000, 0xee81fdd8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b04-01.40", 0x20000, 0xcd30de19, BRF_GRA | TAITO_CHARS }, + { "b04-03.39", 0x20000, 0xab67e064, BRF_GRA | TAITO_CHARS }, + { "b04-02.67", 0x20000, 0x54040fec, BRF_GRA | TAITO_CHARS }, + { "b04-04.66", 0x20000, 0x94737e93, BRF_GRA | TAITO_CHARS }, + + { "b04-05.15", 0x20000, 0xc22d94ac, BRF_GRA | TAITO_SPRITESA }, + { "b04-07.14", 0x20000, 0xb5632a51, BRF_GRA | TAITO_SPRITESA }, + { "b04-06.28", 0x20000, 0x002ccf39, BRF_GRA | TAITO_SPRITESA }, + { "b04-08.27", 0x20000, 0xfeafca05, BRF_GRA | TAITO_SPRITESA }, + + { "b04-20.76", 0x10000, 0xfd1a34cc, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Rastsaga) +STD_ROM_FN(Rastsaga) + +static struct BurnRomInfo Rastsaga1RomDesc[] = { + { "b04-14.19", 0x10000, 0xa38ac909, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-13.7", 0x10000, 0xbad60872, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-16-1.20", 0x10000, 0x00b59e60, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-15-1.8", 0x10000, 0xff9e018a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-18-1.21", 0x10000, 0xb626c439, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b04-17-1.9", 0x10000, 0xc928a516, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b04-19.49", 0x10000, 0xee81fdd8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b04-01.40", 0x20000, 0xcd30de19, BRF_GRA | TAITO_CHARS }, + { "b04-03.39", 0x20000, 0xab67e064, BRF_GRA | TAITO_CHARS }, + { "b04-02.67", 0x20000, 0x54040fec, BRF_GRA | TAITO_CHARS }, + { "b04-04.66", 0x20000, 0x94737e93, BRF_GRA | TAITO_CHARS }, + + { "b04-05.15", 0x20000, 0xc22d94ac, BRF_GRA | TAITO_SPRITESA }, + { "b04-07.14", 0x20000, 0xb5632a51, BRF_GRA | TAITO_SPRITESA }, + { "b04-06.28", 0x20000, 0x002ccf39, BRF_GRA | TAITO_SPRITESA }, + { "b04-08.27", 0x20000, 0xfeafca05, BRF_GRA | TAITO_SPRITESA }, + + { "b04-20.76", 0x10000, 0xfd1a34cc, BRF_SND | TAITO_MSM5205 }, +}; + +STD_ROM_PICK(Rastsaga1) +STD_ROM_FN(Rastsaga1) + +static struct BurnRomInfo TopspeedRomDesc[] = { + { "b14-67-1.11", 0x10000, 0x23f17616, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-68-1.9", 0x10000, 0x835659d9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-54.24", 0x20000, 0x172924d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-52.26", 0x20000, 0xe1b5b2a1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-55.23", 0x20000, 0xa1f15499, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-53.25", 0x20000, 0x04a04f5f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b14-69.80", 0x10000, 0xd652e300, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b14-70.81", 0x10000, 0xb720592b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b14-25.67", 0x10000, 0x9eab28ef, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b14-07.54", 0x20000, 0xc6025fff, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b14-06.52", 0x20000, 0xb4e2536e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b14-48.16", 0x20000, 0x30c7f265, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-49.12", 0x20000, 0x32ba4265, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-50.8", 0x20000, 0xec1ef311, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-51.4", 0x20000, 0x35041c5f, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-44.15", 0x20000, 0x9f6c030e, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-45.11", 0x20000, 0x63e4ce03, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-46.7", 0x20000, 0xd489adf2, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-47.3", 0x20000, 0xb3a1f75b, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-40.14", 0x20000, 0xfa2a3cb3, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-41.10", 0x20000, 0x09455a14, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-42.6", 0x20000, 0xab51f53c, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-43.2", 0x20000, 0x1e6d2b38, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-36.13", 0x20000, 0x20a7c1b8, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-37.9", 0x20000, 0x801b703b, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-38.5", 0x20000, 0xde0c213e, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + { "b14-39.1", 0x20000, 0x798c28c5, BRF_GRA | TAITO_SPRITESA_TOPSPEED }, + + { "b14-30.88" , 0x10000, 0xdccb0c7f, BRF_GRA | TAITO_SPRITEMAP }, + + { "b14-28.103", 0x10000, 0xdf11d0ae, BRF_SND | TAITO_MSM5205 }, + { "b14-29.109", 0x10000, 0x7ad983e7, BRF_SND | TAITO_MSM5205 }, + + { "b14-31.90", 0x02000, 0x5c6b013d, BRF_OPT }, +}; + +STD_ROM_PICK(Topspeed) +STD_ROM_FN(Topspeed) + +static struct BurnRomInfo TopspeeduRomDesc[] = { + { "b14-23", 0x10000, 0xdd0307fd, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-24", 0x10000, 0xacdf08d4, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-05", 0x80000, 0x6557e9d8, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "b14-26", 0x10000, 0x659dc872, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b14-56", 0x10000, 0xd165cf1b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b14-25.67", 0x10000, 0x9eab28ef, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b14-07.54", 0x20000, 0xc6025fff, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b14-06.52", 0x20000, 0xb4e2536e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b14-01", 0x80000, 0x84a56f37, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-02", 0x80000, 0x6889186b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-03", 0x80000, 0xd1ed9e71, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-04", 0x80000, 0xb63f0519, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b14-30.88" , 0x10000, 0xdccb0c7f, BRF_GRA | TAITO_SPRITEMAP }, + + { "b14-28.103", 0x10000, 0xdf11d0ae, BRF_SND | TAITO_MSM5205 }, + { "b14-29.109", 0x10000, 0x7ad983e7, BRF_SND | TAITO_MSM5205 }, + + { "b14-31.90", 0x02000, 0x5c6b013d, BRF_OPT }, +}; + +STD_ROM_PICK(Topspeedu) +STD_ROM_FN(Topspeedu) + +static struct BurnRomInfo FullthrlRomDesc[] = { + { "b14-67", 0x10000, 0x284c943f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-68", 0x10000, 0x54cf6196, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b14-05", 0x80000, 0x6557e9d8, BRF_ESS | BRF_PRG | TAITO_68KROM1 }, + + { "b14-69.80", 0x10000, 0xd652e300, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b14-71", 0x10000, 0xf7081727, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b14-25.67", 0x10000, 0x9eab28ef, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b14-07.54", 0x20000, 0xc6025fff, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "b14-06.52", 0x20000, 0xb4e2536e, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "b14-01", 0x80000, 0x84a56f37, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-02", 0x80000, 0x6889186b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-03", 0x80000, 0xd1ed9e71, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b14-04", 0x80000, 0xb63f0519, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b14-30.88" , 0x10000, 0xdccb0c7f, BRF_GRA | TAITO_SPRITEMAP }, + + { "b14-28.103", 0x10000, 0xdf11d0ae, BRF_SND | TAITO_MSM5205 }, + { "b14-29.109", 0x10000, 0x7ad983e7, BRF_SND | TAITO_MSM5205 }, + + { "b14-31.90", 0x02000, 0x5c6b013d, BRF_OPT }, +}; + +STD_ROM_PICK(Fullthrl) +STD_ROM_FN(Fullthrl) + +static struct BurnRomInfo VolfiedRomDesc[] = { + { "c04-12-1.30", 0x10000, 0xafb6a058, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-08-1.10", 0x10000, 0x19f7e66b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-11-1.29", 0x10000, 0x1aaf6e9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-25-1.9", 0x10000, 0xb39e04f9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-20.7", 0x20000, 0x0aea651f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-22.9", 0x20000, 0xf405d465, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-19.6", 0x20000, 0x231493ae, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-21.8", 0x20000, 0x8598d38e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c04-06.71", 0x08000, 0xb70106b2, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c04-16.2", 0x20000, 0x8c2476ef, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-18.4", 0x20000, 0x7665212c, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-15.1", 0x20000, 0x7c50b978, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-17.3", 0x20000, 0xc62fdeb8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c04-4-1.3", 0x00200, 0xab9fae65, BRF_OPT }, + { "c04-5.75", 0x00200, 0x2763ec89, BRF_OPT }, +}; + +STD_ROM_PICK(Volfied) +STD_ROM_FN(Volfied) + +static struct BurnRomInfo VolfiedjRomDesc[] = { + { "c04-12-1.30", 0x10000, 0xafb6a058, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-08-1.10", 0x10000, 0x19f7e66b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-11-1.29", 0x10000, 0x1aaf6e9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-07-1.9", 0x10000, 0x5d9065d5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-20.7", 0x20000, 0x0aea651f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-22.9", 0x20000, 0xf405d465, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-19.6", 0x20000, 0x231493ae, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-21.8", 0x20000, 0x8598d38e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c04-06.71", 0x08000, 0xb70106b2, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c04-16.2", 0x20000, 0x8c2476ef, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-18.4", 0x20000, 0x7665212c, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-15.1", 0x20000, 0x7c50b978, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-17.3", 0x20000, 0xc62fdeb8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c04-4-1.3", 0x00200, 0xab9fae65, BRF_OPT }, + { "c04-5.75", 0x00200, 0x2763ec89, BRF_OPT }, +}; + +STD_ROM_PICK(Volfiedj) +STD_ROM_FN(Volfiedj) + +static struct BurnRomInfo VolfiedjoRomDesc[] = { + { "c04-12.30", 0x10000, 0xe319c7ec, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-08.10", 0x10000, 0x81c6f755, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-11.29", 0x10000, 0xf05696a6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-07.9", 0x10000, 0x4eeda184, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-20.7", 0x20000, 0x0aea651f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-22.9", 0x20000, 0xf405d465, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-19.6", 0x20000, 0x231493ae, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-21.8", 0x20000, 0x8598d38e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c04-06.71", 0x08000, 0xb70106b2, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c04-16.2", 0x20000, 0x8c2476ef, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-18.4", 0x20000, 0x7665212c, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-15.1", 0x20000, 0x7c50b978, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-17.3", 0x20000, 0xc62fdeb8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c04-4-1.3", 0x00200, 0xab9fae65, BRF_OPT }, + { "c04-5.75", 0x00200, 0x2763ec89, BRF_OPT }, +}; + +STD_ROM_PICK(Volfiedjo) +STD_ROM_FN(Volfiedjo) + +static struct BurnRomInfo VolfieduRomDesc[] = { + { "c04-12-1.30", 0x10000, 0xafb6a058, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-08-1.10", 0x10000, 0x19f7e66b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-11-1.29", 0x10000, 0x1aaf6e9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-24-1.9", 0x10000, 0xc499346f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-20.7", 0x20000, 0x0aea651f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-22.9", 0x20000, 0xf405d465, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-19.6", 0x20000, 0x231493ae, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c04-21.8", 0x20000, 0x8598d38e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c04-06.71", 0x08000, 0xb70106b2, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c04-16.2", 0x20000, 0x8c2476ef, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-18.4", 0x20000, 0x7665212c, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-15.1", 0x20000, 0x7c50b978, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-17.3", 0x20000, 0xc62fdeb8, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-10.15", 0x10000, 0x429b6b49, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + { "c04-09.14", 0x10000, 0xc78cf057, BRF_GRA | TAITO_SPRITESA_BYTESWAP }, + + { "c04-4-1.3", 0x00200, 0xab9fae65, BRF_OPT }, + { "c04-5.75", 0x00200, 0x2763ec89, BRF_OPT }, +}; + +STD_ROM_PICK(Volfiedu) +STD_ROM_FN(Volfiedu) + +static int MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + Taito68KRom2 = Next; Next += Taito68KRom2Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoZ80Rom2 = Next; Next += TaitoZ80Rom2Size; + TaitoMSM5205Rom = Next; Next += TaitoMSM5205RomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x018000; + TaitoZ80Ram1 = Next; Next += 0x001000; + if (TaitoNumZ80s == 2) TaitoZ80Ram2 = Next; Next += 0x000800; + TaitoPaletteRam = Next; Next += 0x004000; + TaitoSpriteRam = Next; Next += 0x00f000; + TaitoSharedRam = Next; Next += 0x010000; + TaitoVideoRam = Next; Next += 0x080000; + Taito68KRam2 = Next; Next += 0x010000; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoCharsB = Next; Next += TaitoNumCharB * TaitoCharBWidth * TaitoCharBHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x02000 * sizeof(UINT32); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 DariusDoReset() +{ + TaitoDoReset(); + + DariusADPCMCommand = 0; + DariusNmiEnable = 0; + DariusCoinWord = 0; + + return 0; +} + +static INT32 OpwolfDoReset() +{ + TaitoDoReset(); + + memset(OpwolfADPCM_B, 0, 8); + memset(OpwolfADPCM_C, 0, 8); + OpwolfADPCMPos[0] = OpwolfADPCMPos[1] = 0; + OpwolfADPCMEnd[0] = OpwolfADPCMEnd[1] = 0; + OpwolfADPCMData[0] = OpwolfADPCMData[1] = -1; + + MSM5205ResetWrite(0, 1); + MSM5205ResetWrite(1, 1); + + return 0; +} + +static INT32 RastanDoReset() +{ + TaitoDoReset(); + + RastanADPCMPos = 0; + RastanADPCMData = -1; + + return 0; +} + +static INT32 VolfiedDoReset() +{ + TaitoDoReset(); + + VolfiedVidCtrl = 0; + VolfiedVidMask = 0; + + return 0; +} + +static INT32 TopspeedDoReset() +{ + TaitoDoReset(); + + RastanADPCMPos = 0; + RastanADPCMData = -1; + + return 0; +} + +static void TaitoMiscCpuAReset(UINT16 d) +{ + TaitoCpuACtrl = d; + if (!(TaitoCpuACtrl & 1)) { + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(0); + } +} + +UINT8 __fastcall Darius68K1ReadByte(UINT32 a) +{ + switch (a) { + case 0xc00010: { + return TaitoDip[1]; + } + + case 0xc00011: { + return TaitoDip[0]; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius68K1WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Darius68K1ReadWord(UINT32 a) +{ + switch (a) { + case 0xc00002: { + return TC0140SYTCommRead(); + } + + case 0xc00008: { + return TaitoInput[0]; + } + + case 0xc0000a: { + return TaitoInput[1]; + } + + case 0xc0000c: { + return TaitoInput[2]; + } + + case 0xc0000e: { + return DariusCoinWord; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius68K1WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x0a0000: { + TaitoMiscCpuAReset(d); + return; + } + + case 0x0b0000: { + //watchdog + return; + } + + case 0xc00000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0xc00002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0xc00020: + case 0xc00022: + case 0xc00024: + case 0xc00030: + case 0xc00032: + case 0xc00034: { + //misc io writes + return; + } + + case 0xc00050: { + //nop + return; + } + + case 0xc00060: { + DariusCoinWord = d; + return; + } + + case 0xd20000: + case 0xd20002: { + PC080SNSetScrollY(0, (a - 0xd20000) >> 1, d); + return; + } + + case 0xd40000: + case 0xd40002: { + PC080SNSetScrollX(0, (a - 0xd40000) >> 1, d); + return; + } + + case 0xd50000: { + PC080SNCtrlWrite(0, (a - 0xd50000) >> 1, d); + return; + } + + case 0xdc0000: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Darius68K2ReadByte(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius68K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Darius68K2ReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Darius68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0xc00050: { + //nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Opwolf68KReadByte(UINT32 a) +{ + if (a >= 0x0ff000 && a <= 0x0ff7ff) { + return OpwolfCChipDataRead((a - 0x0ff000) >> 1); + } + + switch (a) { + case 0x3e0002: { + return TC0140SYTCommRead(); + } + } + + return 0; +} + +void __fastcall Opwolf68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x0ff000 && a <= 0x0ff7ff) { + OpwolfCChipDataWrite(Taito68KRom1, (a - 0x0ff000) >> 1, d); + return; + } + + switch (a) { + case 0x3e0000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x3e0002: { + TC0140SYTCommWrite(d); + return; + } + } +} + +UINT16 __fastcall Opwolf68KReadWord(UINT32 a) +{ + if (a >= 0x0f0000 && a <= 0x0f07ff) { + return OpwolfCChipDataRead((a - 0x0f0000) >> 1); + } + + if (a >= 0x0ff000 && a <= 0x0ff7ff) { + return OpwolfCChipDataRead((a - 0x0ff000) >> 1); + } + + switch (a) { + case 0x3a0000: { + INT32 scaled = (BurnGunReturnX(0) * 320) / 256; + return scaled + 0x15 + OpWolfGunXOffset; + } + + case 0x3a0002: { + return BurnGunReturnY(0) - 0x24 + OpWolfGunYOffset; + } + + case 0x0ff802: { + return OpwolfCChipStatusRead(); + } + + case 0x380000: { + return TaitoDip[0]; + } + + case 0x380002: { + return TaitoDip[1]; + } + } + + return 0; +} + +void __fastcall Opwolf68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x0ff000 && a <= 0x0ff7ff) { + OpwolfCChipDataWrite(Taito68KRom1, (a - 0x0ff000) >> 1, d); + return; + } + + switch (a) { + case 0x0ff802: { + OpwolfCChipStatusWrite(); + return; + } + + case 0x0ffc00: { + OpwolfCChipBankWrite(d); + return; + } + + case 0x380000: { + PC090OJSpriteCtrl = (d & 0xe0) >> 5; + return; + } + + case 0x3c0000: { + // nop + return; + } + + case 0xc20000: + case 0xc20002: { + PC080SNSetScrollY(0, (a - 0xc20000) >> 1, d); + return; + } + + case 0xc40000: + case 0xc40002: { + PC080SNSetScrollX(0, (a - 0xc40000) >> 1, d); + return; + } + + case 0xc50000: { + PC080SNCtrlWrite(0, (a - 0xc50000) >> 1, d); + return; + } + } +} + +UINT8 __fastcall Opwolfb68KReadByte(UINT32 a) +{ + if (a >= 0x0ff000 && a <= 0x0fffff) { + return TaitoZ80Ram2[(a - 0x0ff000) >> 1]; + } + + switch (a) { + case 0x3e0002: { + return TC0140SYTCommRead(); + } + } + + return 0; +} + +void __fastcall Opwolfb68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x0ff000 && a <= 0x0fffff) { + TaitoZ80Ram2[(a - 0x0ff000) >> 1] = d ; + return; + } + + switch (a) { + case 0x3e0000: { + TC0140SYTPortWrite(d); + return; + } + + case 0x3e0002: { + TC0140SYTCommWrite(d); + return; + } + } +} + +UINT16 __fastcall Opwolfb68KReadWord(UINT32 a) +{ + if (a >= 0x0ff000 && a <= 0x0fffff) { + return TaitoZ80Ram2[(a - 0x0ff000) >> 1]; + } + + switch (a) { + case 0x0f0008: { + return TaitoInput[0]; + } + + case 0x0f000a: { + return TaitoInput[1]; + } + + case 0x380000: { + return TaitoDip[0]; + } + + case 0x380002: { + return TaitoDip[1]; + } + + case 0x3a0000: { + INT32 scaled = (BurnGunReturnX(0) * 320) / 256; + return scaled + 0x15 + OpWolfGunXOffset; + } + + case 0x3a0002: { + return BurnGunReturnY(0) - 0x24 + OpWolfGunYOffset; + } + } + + return 0; +} + +void __fastcall Opwolfb68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x0ff000 && a <= 0x0fffff) { + TaitoZ80Ram2[(a - 0x0ff000) >> 1] = d & 0xff; + return; + } + + switch (a) { + case 0x380000: { + PC090OJSpriteCtrl = (d & 0xe0) >> 5; + return; + } + + case 0x3c0000: { + // nop + return; + } + + case 0xc20000: + case 0xc20002: { + PC080SNSetScrollY(0, (a - 0xc20000) >> 1, d); + return; + } + + case 0xc40000: + case 0xc40002: { + PC080SNSetScrollX(0, (a - 0xc40000) >> 1, d); + return; + } + + case 0xc50000: { + PC080SNCtrlWrite(0, (a - 0xc50000) >> 1, d); + return; + } + } +} + +UINT8 __fastcall Rainbow68KReadByte(UINT32 a) +{ + if (a >= 0x800000 && a <= 0x8007ff) { + return RainbowCChipRamRead((a - 0x800000) >> 1); + } + + switch (a) { + case 0x800803: { + return RainbowCChipCtrlRead(); + } + } + + return 0; +} + +void __fastcall Rainbow68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x800000 && a <= 0x8007ff) { + RainbowCChipRamWrite((a - 0x800000) >> 1, d); + return; + } + + switch (a) { + case 0x3a0001: { + PC090OJSpriteCtrl = (d & 0xe0) >> 5; + return; + } + + case 0x3e0001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x3e0003: { + TC0140SYTCommWrite(d); + return; + } + + case 0x800803: { + RainbowCChipCtrlWrite(d); + return; + } + + case 0x800c01: { + RainbowCChipBankWrite(d); + return; + } + } +} + +UINT16 __fastcall Rainbow68KReadWord(UINT32 a) +{ + if (a >= 0x800000 && a <= 0x8007ff) { + return RainbowCChipRamRead((a - 0x800000) >> 1); + } + + switch (a) { + case 0x390000: { + return TaitoDip[0]; + } + + case 0x3b0000: { + return TaitoDip[1]; + } + } + + return 0; +} + +void __fastcall Rainbow68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x3c0000: { + // nop + return; + } + + case 0xc20000: + case 0xc20002: { + PC080SNSetScrollY(0, (a - 0xc20000) >> 1, d); + return; + } + + case 0xc40000: + case 0xc40002: { + PC080SNSetScrollX(0, (a - 0xc40000) >> 1, d); + return; + } + + case 0xc50000: { + PC080SNCtrlWrite(0, (a - 0xc50000) >> 1, d); + return; + } + } +} + +UINT8 __fastcall Jumping68KReadByte(UINT32 a) +{ + switch (a) { + case 0x401001: { + return TaitoInput[0]; + } + + case 0x401003: { + return TaitoInput[1]; + } + + case 0x420000: { + // nop + return 0; + } + } + + return 0; +} + +void __fastcall Jumping68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x800000 && a <= 0x80ffff) return; + + switch (a) { + case 0x3a0001: { + PC090OJSpriteCtrl = d; + return; + } + + case 0x400007: { + TaitoSoundLatch = d; + ZetOpen(0); + ZetSetIRQLine(0, ZET_IRQSTATUS_ACK); + ZetClose(); + return; + } + } +} + +UINT16 __fastcall Jumping68KReadWord(UINT32 a) +{ + switch (a) { + case 0x400000: { + return TaitoDip[0]; + } + + case 0x400002: { + return TaitoDip[0]; + } + } + + return 0; +} + +void __fastcall Jumping68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x3c0000: { + // nop + return; + } + + case 0x430000: + case 0x430002: { + PC080SNSetScrollY(0, (a - 0x430000) >> 1, d); + return; + } + + case 0xc20000: { + //nop + return; + } + + case 0xc50000: { + //??? + return; + } + } +} + +UINT8 __fastcall Rastan68KReadByte(UINT32 a) +{ + switch (a) { + case 0x390001: { + return TaitoInput[0]; + } + + case 0x390003: { + return TaitoInput[1]; + } + + case 0x390005: { + return TaitoInput[2]; + } + + case 0x390007: { + return TaitoInput[3]; + } + + case 0x390009: { + return TaitoDip[0]; + } + + case 0x39000b: { + return TaitoDip[1]; + } + + case 0x3e0003: { + return TC0140SYTCommRead(); + } + } + + return 0; +} + +void __fastcall Rastan68KWriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x3e0001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x3e0003: { + TC0140SYTCommWrite(d); + return; + } + } +} + +void __fastcall Rastan68KWriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x350008: { + // nop + return; + } + + case 0x380000: { + PC090OJSpriteCtrl = (d & 0xe0) >> 5; + return; + } + + case 0x3c0000: { + // watchdog + return; + } + + case 0xc20000: + case 0xc20002: { + PC080SNSetScrollY(0, (a - 0xc20000) >> 1, d); + return; + } + + case 0xc40000: + case 0xc40002: { + PC080SNSetScrollX(0, (a - 0xc40000) >> 1, d); + return; + } + + case 0xc50000: { + PC080SNCtrlWrite(0, (a - 0xc50000) >> 1, d); + return; + } + } +} + +static UINT8 TopspeedInputBypassRead() +{ + UINT8 Port = TC0220IOCPortRead(); + + INT32 Steer = (TaitoAnalogPort0 >> 4); + + switch (Port) { + case 0x0c: { + return Steer & 0xff; + } + + case 0x0d: { + return Steer >> 8; + } + + default: { + return TC0220IOCPortRegRead(); + } + } +} + +UINT8 __fastcall Topspeed68K1ReadByte(UINT32 a) +{ + switch (a) { + case 0x7e0003: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Topspeed68K1WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x7e0001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x7e0003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Topspeed68K1ReadWord(UINT32 a) +{ + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Topspeed68K1WriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0xe10000 && a <= 0xe1ffff) { + // ??? + return; + } + + switch (a) { + case 0x600002: { + TaitoMiscCpuAReset(d); + return; + } + + case 0x880002: + case 0x880004: + case 0x880006: { + // ??? + return; + } + + case 0xa20000: + case 0xa20002: { + PC080SNSetScrollY(0, (a - 0xa20000) >> 1, d); + return; + } + + case 0xa40000: + case 0xa40002: { + PC080SNSetScrollX(0, (a - 0xa40000) >> 1, d); + return; + } + + case 0xa50000: { + PC080SNCtrlWrite(0, (a - 0xa50000) >> 1, d); + return; + } + + case 0xb20000: + case 0xb20002: { + PC080SNSetScrollY(1, (a - 0xb20000) >> 1, d); + return; + } + + case 0xb40000: + case 0xb40002: { + PC080SNSetScrollX(1, (a - 0xb40000) >> 1, d); + return; + } + + case 0xb50000: { + PC080SNCtrlWrite(1, (a - 0xb50000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Topspeed68K2ReadByte(UINT32 a) +{ + if (a >= 0x900000 && a <= 0x9003ff) { + INT32 Offset = (a - 0x900000) >> 1; + + switch (Offset) { + case 0x000: return rand() & 0xff; + case 0x101: return 0x55; + } + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Topspeed68K2WriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x900000 && a <= 0x9003ff) { + return; + } + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Topspeed68K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x880000: { + return TopspeedInputBypassRead(); + } + + case 0x880002: { + return TC0220IOCHalfWordPortRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Topspeed68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x810000: { + // ??? + return; + } + + case 0x880000: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x880002: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Volfied68KReadByte(UINT32 a) +{ + if (a >= 0xf00000 && a <= 0xf007ff) { + INT32 Offset = (a - 0xf00000) >> 1; + return VolfiedCChipRamRead(Offset); + } + + switch (a) { + case 0xd00001: { + return 0x60; + } + + case 0xe00003: { + return TC0140SYTCommRead(); + } + + case 0xf00803: { + return VolfiedCChipCtrlRead() & 0xff; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Volfied68KWriteByte(UINT32 a, UINT8 d) +{ + if (a >= 0x400000 && a <= 0x47ffff) { + INT32 Offset = (a - 0x400000); + INT32 Mask; + if (Offset & 1) { + Mask = VolfiedVidMask >> 8; + } else { + Mask = VolfiedVidMask & 0xff; + } + TaitoVideoRam[Offset ^ 1] = (TaitoVideoRam[Offset ^ 1] & ~Mask) | (d & Mask); + return; + } + + if (a >= 0xf00000 && a <= 0xf007ff) { + INT32 Offset = (a - 0xf00000) >> 1; + VolfiedCChipRamWrite(Offset, d); + return; + } + + switch (a) { + case 0x700001: { + PC090OJSpriteCtrl = (d & 0x3c) >> 2; + return; + } + + case 0xd00001: { + VolfiedVidCtrl = d; + return; + } + + case 0xf00803: { + // cchip ctrl write - ignored + return; + } + + case 0xf00c01: { + VolfiedCChipBankWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Volfied68KReadWord(UINT32 a) +{ + if (a >= 0xf00000 && a <= 0xf007ff) { + INT32 Offset = (a - 0xf00000) >> 1; + return VolfiedCChipRamRead(Offset); + } + + switch (a) { + case 0xd00000: { + return 0x60; + } + + case 0xe00002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Volfied68KWriteWord(UINT32 a, UINT16 d) +{ + if (a >= 0x400000 && a <= 0x47ffff) { + UINT16 *Ram = (UINT16*)TaitoVideoRam; + INT32 Offset = (a - 0x400000) >> 1; + Ram[Offset] = (Ram[Offset] & ~VolfiedVidMask) | (d & VolfiedVidMask); + return; + } + + if (a >= 0xf00000 && a <= 0xf007ff) { + INT32 Offset = (a - 0xf00000) >> 1; + VolfiedCChipRamWrite(Offset, d & 0xff); + return; + } + + switch (a) { + case 0x600000: { + VolfiedVidMask = d; + return; + } + + case 0xd00000: { + VolfiedVidCtrl = d; + return; + } + + case 0xe00000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0xe00002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0xf00c00: { + VolfiedCChipBankWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall DariusZ80Read(UINT16 a) +{ + switch (a) { + case 0x9000: { + return BurnYM2203Read(0, 0); + } + + case 0x9001: { + return BurnYM2203Read(0, 1); + } + + case 0xa000: { + return BurnYM2203Read(1, 0); + } + + case 0xa001: { + return BurnYM2203Read(1, 1); + } + + case 0xb001: { + return TC0140SYTSlaveCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04X\n"), a); + } + } + + return 0; +} + +void __fastcall DariusZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x9001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xa000: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xa001: { + BurnYM2203Write(1, 1, d); + return; + } + + case 0xb000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xb001: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xc000: { + //darius_fm0_pan + return; + } + + case 0xc400: { + //darius_fm1_pan + return; + } + + case 0xc800: { + //darius_psg0_pan + return; + } + + case 0xcc00: { + //darius_psg1_pan + return; + } + + case 0xd000: { + //darius_da_pan + return; + } + + case 0xd400: { + DariusADPCMCommand = d; + return; + } + + case 0xd800: { + //??? + return; + } + + case 0xdc00: { + TaitoZ80Bank = d & 0x03; + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 + 0x10000 + (TaitoZ80Bank * 0x8000)); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 + 0x10000 + (TaitoZ80Bank * 0x8000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall DariusZ802ReadPort(UINT16 a) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + return DariusADPCMCommand; + } + + case 0x02: { + //??? + return 0; + } + + case 0x03: { + //??? + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Read => %02X\n"), a); + } + } + + return 0; +} + +void __fastcall DariusZ802WritePort(UINT16 a, UINT8 d) +{ + a &= 0xff; + + switch (a) { + case 0x00: { + DariusNmiEnable = 0; + return; + } + + case 0x01: { + DariusNmiEnable = 1; + return; + } + + case 0x02: { + MSM5205DataWrite(0, d); + MSM5205ResetWrite(0, !(d & 0x20)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 #2 Port Write => %02X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall OpwolfZ80Read(UINT16 a) +{ + switch (a) { + case 0x9001: { + return BurnYM2151ReadStatus(); + } + + case 0xa001: { + return TC0140SYTSlaveCommRead(); + } + } + + return 0; +} + +void __fastcall OpwolfZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x9001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xa000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xa001: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xb000: + case 0xb001: + case 0xb002: + case 0xb003: + case 0xb004: + case 0xb005: + case 0xb006: { + INT32 nStart; + INT32 nEnd; + INT32 Offset = a - 0xb000; + + OpwolfADPCM_B[Offset] = d; + if (Offset == 0x04) { + nStart = OpwolfADPCM_B[0] + (OpwolfADPCM_B[1] << 8); + nEnd = OpwolfADPCM_B[2] + (OpwolfADPCM_B[3] << 8); + nStart *= 16; + nEnd *= 16; + OpwolfADPCMPos[0] = nStart; + OpwolfADPCMEnd[0] = nEnd; + MSM5205ResetWrite(0, 0); + } + return; + } + + case 0xc000: + case 0xc001: + case 0xc002: + case 0xc003: + case 0xc004: + case 0xc005: + case 0xc006: { + INT32 nStart; + INT32 nEnd; + INT32 Offset = a - 0xc000; + + OpwolfADPCM_C[Offset] = d; + if (Offset == 0x04) { + nStart = OpwolfADPCM_C[0] + (OpwolfADPCM_C[1] << 8); + nEnd = OpwolfADPCM_C[2] + (OpwolfADPCM_C[3] << 8); + nStart *= 16; + nEnd *= 16; + OpwolfADPCMPos[1] = nStart; + OpwolfADPCMEnd[1] = nEnd; + MSM5205ResetWrite(1, 0); + } + return; + } + + case 0xd000: + case 0xe000: { + return; + } + } +} + +UINT8 __fastcall RainbowZ80Read(UINT16 a) +{ + switch (a) { + case 0x9001: { + return BurnYM2151ReadStatus(); + } + + case 0xa001: { + return TC0140SYTSlaveCommRead(); + } + } + + return 0; +} + +void __fastcall RainbowZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x9001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xa000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xa001: { + TC0140SYTSlaveCommWrite(d); + return; + } + } +} + +UINT8 __fastcall JumpingZ80Read(UINT16 a) +{ + switch (a) { + case 0xb000: { + return BurnYM2203Read(0, 0); + } + + case 0xb400: { + return BurnYM2203Read(1, 0); + } + + case 0xb800: { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + return TaitoSoundLatch; + } + } + + return 0; +} + +void __fastcall JumpingZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xb000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0xb001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0xb400: { + BurnYM2203Write(1, 0, d); + return; + } + + case 0xb401: { + BurnYM2203Write(1, 1, d); + return; + } + + case 0xbc00: { + //nop + return; + } + } +} + +UINT8 __fastcall RastanZ80Read(UINT16 a) +{ + switch (a) { + case 0x9001: { + return BurnYM2151ReadStatus(); + } + + case 0xa001: { + return TC0140SYTSlaveCommRead(); + } + } + + return 0; +} + +void __fastcall RastanZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x9001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xa000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xa001: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xb000: { + RastanADPCMPos = (RastanADPCMPos & 0x00ff) | (d << 8); + return; + } + + case 0xc000: { + MSM5205ResetWrite(0, 0); + return; + } + + case 0xd000: { + MSM5205ResetWrite(0, 1); + RastanADPCMPos &= 0xff00; + return; + } + } +} + +UINT8 __fastcall TopspeedZ80Read(UINT16 a) +{ + switch (a) { + case 0x9001: { + return BurnYM2151ReadStatus(); + } + + case 0xa001: { + return TC0140SYTSlaveCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TopspeedZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x9000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0x9001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xa000: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xa001: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xb000: { + RastanADPCMPos = (RastanADPCMPos & 0x00ff) | (d << 8); + MSM5205ResetWrite(0, 0); + return; + } + + case 0xb800: { + MSM5205ResetWrite(0, 1); + RastanADPCMPos &= 0xff00; + return; + } + + case 0xc000: + case 0xc400: + case 0xc800: + case 0xcc00: + case 0xd000: + case 0xd200: + case 0xd400: + case 0xd600: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall VolfiedZ80Read(UINT16 a) +{ + switch (a) { + case 0x8801: { + return TC0140SYTSlaveCommRead(); + } + + case 0x9000: { + return BurnYM2203Read(0, 0); + } + + case 0x9001: { + return BurnYM2203Read(0, 1); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read %04X\n"), a); + } + } + + return 0; +} + +void __fastcall VolfiedZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0x8800: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0x8801: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0x9000: { + BurnYM2203Write(0, 0, d); + return; + } + + case 0x9001: { + BurnYM2203Write(0, 1, d); + return; + } + + case 0x9800: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall OpwolfbCChipSubZ80Read(UINT16 a) +{ + switch (a) { + case 0x8800: { + return TaitoInput[0]; + } + + case 0x9800: { + return TaitoInput[0]; + } + } + + return 0; +} + +void __fastcall OpwolfbCChipSubZ80Write(UINT16 a, UINT8) +{ + switch (a) { + case 0x9000: + case 0xa000: { + //nop + return; + } + } +} + +static void TaitoYM2151IRQHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static void TaitoYM2203IRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +inline static INT32 TaitoSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)(ZetTotalCycles() * nSoundRate / 4000000); +} + +inline static double TaitoGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static void RainbowBankSwitch(UINT32, UINT32 Data) +{ + TaitoZ80Bank = (Data - 1) & 3; + + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); +} + +static void RastanBankSwitch(UINT32, UINT32 Data) +{ + Data &= 3; + if (Data != 0) { + TaitoZ80Bank = Data - 1; + + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + } +} + +static void DariusAdpcmInt() +{ + if (DariusNmiEnable) ZetNmi(); +} + +static void OpwolfMSM5205Vck0() +{ + if (OpwolfADPCMData[0] != -1) { + MSM5205DataWrite(0, OpwolfADPCMData[0] & 0x0f); + OpwolfADPCMData[0] = -1; + if (OpwolfADPCMPos[0] == OpwolfADPCMEnd[0]) MSM5205ResetWrite(0, 1); + } else { + OpwolfADPCMData[0] = TaitoMSM5205Rom[OpwolfADPCMPos[0]]; + OpwolfADPCMPos[0] = (OpwolfADPCMPos[0] + 1) & 0x7ffff; + MSM5205DataWrite(0, OpwolfADPCMData[0] >> 4); + } +} + +static void OpwolfMSM5205Vck1() +{ + if (OpwolfADPCMData[1] != -1) { + MSM5205DataWrite(1, OpwolfADPCMData[1] & 0x0f); + OpwolfADPCMData[1] = -1; + if (OpwolfADPCMPos[1] == OpwolfADPCMEnd[1]) MSM5205ResetWrite(1, 1); + } else { + OpwolfADPCMData[1] = TaitoMSM5205Rom[OpwolfADPCMPos[1]]; + OpwolfADPCMPos[1] = (OpwolfADPCMPos[1] + 1) & 0x7ffff; + MSM5205DataWrite(1, OpwolfADPCMData[1] >> 4); + } +} + +static void RastanMSM5205Vck() +{ + if (RastanADPCMData != -1) { + MSM5205DataWrite(0, RastanADPCMData & 0x0f); + RastanADPCMData = -1; + } else { + RastanADPCMData = TaitoMSM5205Rom[RastanADPCMPos]; + RastanADPCMPos = (RastanADPCMPos + 1) & 0xffff; + MSM5205DataWrite(0, RastanADPCMData >> 4); + } +} + +static void TopspeedBankSwitch(UINT32, UINT32 Data) +{ + Data &= 3; + if (Data != 0) { + TaitoZ80Bank = Data - 1; + + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + } +} + +static void TopspeedMSM5205Vck() +{ + if (RastanADPCMData != -1) { + MSM5205DataWrite(0, RastanADPCMData & 0x0f); + RastanADPCMData = -1; + } else { + RastanADPCMData = TaitoMSM5205Rom[RastanADPCMPos]; + RastanADPCMPos = (RastanADPCMPos + 1) & 0x1ffff; + MSM5205DataWrite(0, RastanADPCMData >> 4); + } +} + +static UINT8 VolfiedDip1Read(UINT32) +{ + return TaitoDip[0]; +} + +static UINT8 VolfiedDip2Read(UINT32) +{ + return TaitoDip[1]; +} + +static INT32 DariusCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 DariusCharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 DariusCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 DariusCharBPlaneOffsets[2] = { 0, 8 }; +static INT32 DariusCharBXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 DariusCharBYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 DariusSpritePlaneOffsets[4] = { 24, 8, 16, 0 }; +static INT32 DariusSpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 256, 257, 258, 259, 260, 261, 262, 263 }; +static INT32 DariusSpriteYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 512, 544, 576, 608, 640, 672, 704, 736 }; +static INT32 OpwolfbCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 OpwolfbCharXOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 }; +static INT32 OpwolfbCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 OpwolfbSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 OpwolfbSpriteXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 }; +static INT32 OpwolfbSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 RainbowCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 RainbowCharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 RainbowCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 RainbowSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 RainbowSpriteXOffsets[16] = { 8, 12, 0, 4, 24, 28, 16, 20, 40, 44, 32, 36, 56, 60, 48, 52 }; +static INT32 RainbowSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 JumpingCharPlaneOffsets[4] = { 0, 0x20000*8, 0x40000*8, 0x60000*8 }; +static INT32 JumpingCharXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 JumpingCharYOffsets[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; +static INT32 JumpingSpritePlaneOffsets[4] = { 0x78000*8, 0x50000*8, 0x28000*8, 0 }; +static INT32 JumpingSpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 JumpingSpriteYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 }; +static INT32 RastanCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 RastanCharXOffsets[8] = { 0, 4, 0x200000, 0x200004, 8, 12, 0x200008, 0x20000c }; +static INT32 RastanCharYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; +static INT32 RastanSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 RastanSpriteXOffsets[16] = { 0, 4, 0x200000, 0x200004, 8, 12, 0x200008, 0x20000c, 16, 20, 0x200010, 0x200014, 24, 28, 0x200018, 0x20001c }; +static INT32 RastanSpriteYOffsets[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 }; +static INT32 TopspeedCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TopspeedCharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 TopspeedCharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 TopspeedSpritePlaneOffsets[4] = { 0, 8, 16, 24 }; +static INT32 TopspeedSpriteXOffsets[16] = { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TopspeedSpriteYOffsets[8] = { 0, 64, 128, 192, 256, 320, 384, 448 }; +static INT32 VolfiedSpritePlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 VolfiedSpriteXOffsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 }; +static INT32 VolfiedSpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; + +static INT32 DariusInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = DariusCharPlaneOffsets; + TaitoCharXOffsets = DariusCharXOffsets; + TaitoCharYOffsets = DariusCharYOffsets; + TaitoNumChar = 0x3000; + + TaitoCharBModulo = 0x80; + TaitoCharBNumPlanes = 2; + TaitoCharBWidth = 8; + TaitoCharBHeight = 8; + TaitoCharBPlaneOffsets = DariusCharBPlaneOffsets; + TaitoCharBXOffsets = DariusCharBXOffsets; + TaitoCharBYOffsets = DariusCharBYOffsets; + TaitoNumCharB = 0x800; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = DariusSpritePlaneOffsets; + TaitoSpriteAXOffsets = DariusSpriteXOffsets; + TaitoSpriteAYOffsets = DariusSpriteYOffsets; + TaitoNumSpriteA = 0x1800; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 2; + TaitoNumYM2203 = 2; + TaitoNumMSM5205 = 1; + + TaitoLoadRoms(0); + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "darius") != 0) Taito68KRom1Size = 0x60000; + TaitoZ80Rom1Size = 0x30000; + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + if (strcmp(BurnDrvGetTextA(DRV_NAME), "darius") != 0) { + memcpy(Taito68KRom1 + 0x40000, Taito68KRom1 + 0x20000, 0x20000); + memset(Taito68KRom1 + 0x20000, 0xff, 0x20000); + } + + for (INT32 i = 3; i >= 0; i--) { + memcpy(TaitoZ80Rom1 + 0x8000 * i + 0x10000, TaitoZ80Rom1 , 0x4000); + memcpy(TaitoZ80Rom1 + 0x8000 * i + 0x14000, TaitoZ80Rom1 + 0x4000 * i, 0x4000); + } + + PC080SNInit(0, TaitoNumChar, -16, 0, 0, 1); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x080000, 0x08ffff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xd00000, 0xd0ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0xd80000, 0xd80fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xe00100, 0xe00fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0xe01000, 0xe02fff, SM_RAM); + SekMapMemory(TaitoVideoRam , 0xe08000, 0xe0ffff, SM_RAM); + SekMapMemory(Taito68KRam1 + 0x10000 , 0xe10000, 0xe10fff, SM_RAM); + SekSetReadByteHandler(0, Darius68K1ReadByte); + SekSetWriteByteHandler(0, Darius68K1WriteByte); + SekSetReadWordHandler(0, Darius68K1ReadWord); + SekSetWriteWordHandler(0, Darius68K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x040000, 0x04ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0xd80000, 0xd80fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xe00100, 0xe00fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0xe01000, 0xe02fff, SM_RAM); + SekMapMemory(TaitoVideoRam , 0xe08000, 0xe0ffff, SM_RAM); + SekSetReadByteHandler(0, Darius68K2ReadByte); + SekSetWriteByteHandler(0, Darius68K2WriteByte); + SekSetReadWordHandler(0, Darius68K2ReadWord); + SekSetWriteWordHandler(0, Darius68K2WriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(DariusZ80Read); + ZetSetWriteHandler(DariusZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetInHandler(DariusZ802ReadPort); + ZetSetOutHandler(DariusZ802WritePort); + ZetMapArea(0x0000, 0xffff, 0, TaitoZ80Rom2 ); + ZetMapArea(0x0000, 0xffff, 2, TaitoZ80Rom2 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 4000000, TaitoYM2203IRQHandler, TaitoSynchroniseStream, TaitoGetTime, 0); + BurnTimerAttachZet(8000000 / 2); + + MSM5205Init(0, TaitoSynchroniseStream, 384000, DariusAdpcmInt, MSM5205_S48_4B, 100, 1); + + GenericTilesInit(); + + TaitoDrawFunction = DariusDraw; + TaitoMakeInputsFunction = DariusMakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = (16000000 / 2) / 60; + nTaitoCyclesTotal[1] = (16000000 / 2) / 60; + nTaitoCyclesTotal[2] = (8000000 / 2) / 60; + nTaitoCyclesTotal[3] = (8000000 / 2) / 60; + + // Reset the driver + TaitoResetFunction = DariusDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 OpwolfInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = RainbowCharPlaneOffsets; + TaitoCharXOffsets = RainbowCharXOffsets; + TaitoCharYOffsets = RainbowCharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = RainbowSpritePlaneOffsets; + TaitoSpriteAXOffsets = RainbowSpriteXOffsets; + TaitoSpriteAYOffsets = RainbowSpriteYOffsets; + TaitoNumSpriteA = 0x1000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2151 = 1; + TaitoNumMSM5205 = 2; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 8, 0, 0); + PC090OJInit(TaitoNumSpriteA, 0, 8, 0); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x107fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(Taito68KRam1 + 0x8000 , 0xc10000, 0xc1ffff, SM_RAM); + SekMapMemory(PC090OJRam , 0xd00000, 0xd03fff, SM_RAM); + SekSetReadByteHandler(0, Opwolf68KReadByte); + SekSetWriteByteHandler(0, Opwolf68KWriteByte); + SekSetReadWordHandler(0, Opwolf68KReadWord); + SekSetWriteWordHandler(0, Opwolf68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(OpwolfZ80Read); + ZetSetWriteHandler(OpwolfZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(4000000, 50.0); + BurnYM2151SetIrqHandler(&TaitoYM2151IRQHandler); + BurnYM2151SetPortHandler(&RainbowBankSwitch); + + MSM5205Init(0, TaitoSynchroniseStream, 384000, OpwolfMSM5205Vck0, MSM5205_S48_4B, 60, 1); + MSM5205Init(1, TaitoSynchroniseStream, 384000, OpwolfMSM5205Vck1, MSM5205_S48_4B, 60, 1); + + GenericTilesInit(); + + BurnGunInit(1, true); + + TaitoDrawFunction = OpwolfDraw; + TaitoMakeInputsFunction = OpwolfMakeInputs; + TaitoIrqLine = 5; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 4000000 / 60; + + UINT16 *Rom = (UINT16*)Taito68KRom1; + OpWolfGunXOffset = 0xec - (Rom[0x03ffb0 / 2] & 0xff); + OpWolfGunYOffset = 0x1c - (Rom[0x03ffae / 2] & 0xff); + INT32 Region = Rom[0x03fffe / 2] & 0xff; + OpwolfCChipInit(Region); + + // Reset the driver + TaitoResetFunction = OpwolfDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 OpwolfbInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = OpwolfbCharPlaneOffsets; + TaitoCharXOffsets = OpwolfbCharXOffsets; + TaitoCharYOffsets = OpwolfbCharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = OpwolfbSpritePlaneOffsets; + TaitoSpriteAXOffsets = OpwolfbSpriteXOffsets; + TaitoSpriteAYOffsets = OpwolfbSpriteYOffsets; + TaitoNumSpriteA = 0x1000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 2; + TaitoNumYM2151 = 1; + TaitoNumMSM5205 = 2; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 8, 0, 0); + PC090OJInit(TaitoNumSpriteA, 0, 8, 0); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x107fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(Taito68KRam1 + 0x8000 , 0xc10000, 0xc1ffff, SM_RAM); + SekMapMemory(PC090OJRam , 0xd00000, 0xd03fff, SM_RAM); + SekSetReadByteHandler(0, Opwolfb68KReadByte); + SekSetWriteByteHandler(0, Opwolfb68KWriteByte); + SekSetReadWordHandler(0, Opwolfb68KReadWord); + SekSetWriteWordHandler(0, Opwolfb68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(2); + ZetOpen(0); + ZetSetReadHandler(OpwolfZ80Read); + ZetSetWriteHandler(OpwolfZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + ZetOpen(1); + ZetSetReadHandler(OpwolfbCChipSubZ80Read); + ZetSetWriteHandler(OpwolfbCChipSubZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom2 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom2 ); + ZetMapArea(0xc000, 0xc7ff, 0, TaitoZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 1, TaitoZ80Ram2 ); + ZetMapArea(0xc000, 0xc7ff, 2, TaitoZ80Ram2 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(4000000, 50.0); + BurnYM2151SetIrqHandler(&TaitoYM2151IRQHandler); + BurnYM2151SetPortHandler(&RainbowBankSwitch); + + MSM5205Init(0, TaitoSynchroniseStream, 384000, OpwolfMSM5205Vck0, MSM5205_S48_4B, 60, 1); + MSM5205Init(1, TaitoSynchroniseStream, 384000, OpwolfMSM5205Vck1, MSM5205_S48_4B, 60, 1); + + GenericTilesInit(); + + BurnGunInit(1, true); + + TaitoDrawFunction = OpwolfDraw; + TaitoMakeInputsFunction = OpwolfbMakeInputs; + TaitoIrqLine = 5; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 4000000 / 60; + nTaitoCyclesTotal[2] = 4000000 / 60; + + OpWolfGunXOffset = -2; + OpWolfGunYOffset = 17; + + // Reset the driver + TaitoResetFunction = OpwolfDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 RainbowInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = RainbowCharPlaneOffsets; + TaitoCharXOffsets = RainbowCharXOffsets; + TaitoCharYOffsets = RainbowCharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = RainbowSpritePlaneOffsets; + TaitoSpriteAXOffsets = RainbowSpriteXOffsets; + TaitoSpriteAYOffsets = RainbowSpriteYOffsets; + TaitoNumSpriteA = 0x1400; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2151 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 16, 0, 0); + PC090OJInit(TaitoNumSpriteA, 0, 16, 0); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x10c000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekMapMemory(Taito68KRam1 + 0x4000 , 0x201000, 0x203fff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(PC090OJRam , 0xd00000, 0xd03fff, SM_RAM); + SekSetReadByteHandler(0, Rainbow68KReadByte); + SekSetWriteByteHandler(0, Rainbow68KWriteByte); + SekSetReadWordHandler(0, Rainbow68KReadWord); + SekSetWriteWordHandler(0, Rainbow68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(RainbowZ80Read); + ZetSetWriteHandler(RainbowZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(16000000 / 4, 50.0); + BurnYM2151SetIrqHandler(&TaitoYM2151IRQHandler); + BurnYM2151SetPortHandler(&RainbowBankSwitch); + + GenericTilesInit(); + + TaitoDrawFunction = RainbowDraw; + TaitoMakeInputsFunction = RainbowMakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = (16000000 / 2) / 60; + nTaitoCyclesTotal[1] = (16000000 / 4) / 60; + + INT32 CChipVer = 0; + if (!strcmp(BurnDrvGetTextA(DRV_NAME), "rainbowe")) CChipVer = 1; + RainbowCChipInit(CChipVer); + + // Reset the driver + TaitoResetFunction = TaitoDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 JumpingInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x40; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = JumpingCharPlaneOffsets; + TaitoCharXOffsets = JumpingCharXOffsets; + TaitoCharYOffsets = JumpingCharYOffsets; + TaitoNumChar = 16384; + + TaitoSpriteAModulo = 0x100; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = JumpingSpritePlaneOffsets; + TaitoSpriteAXOffsets = JumpingSpriteXOffsets; + TaitoSpriteAYOffsets = JumpingSpriteYOffsets; + TaitoSpriteAInvertRom = 1; + TaitoNumSpriteA = 5120; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2203 = 2; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 16, 1, 0); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x09ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x10c000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekMapMemory(Taito68KRam1 + 0x4000 , 0x201000, 0x203fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x440000, 0x4407ff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam + 0x800 , 0xd00000, 0xd01fff, SM_RAM); + SekSetReadByteHandler(0, Jumping68KReadByte); + SekSetWriteByteHandler(0, Jumping68KWriteByte); + SekSetReadWordHandler(0, Jumping68KReadWord); + SekSetWriteWordHandler(0, Jumping68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(JumpingZ80Read); + ZetSetWriteHandler(JumpingZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xffff, 0, TaitoZ80Rom1 + 0xc000 ); + ZetMapArea(0xc000, 0xffff, 2, TaitoZ80Rom1 + 0xc000 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(2, 3579545, NULL, TaitoSynchroniseStream, TaitoGetTime, 0); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + TaitoDrawFunction = JumpingDraw; + TaitoMakeInputsFunction = JumpingMakeInputs; + TaitoIrqLine = 4; + PC080SNSetFgTransparentPen(0, 0x0f); + + nTaitoCyclesTotal[0] = 8000000 / 60; + nTaitoCyclesTotal[1] = 4000000 / 60; + + // Reset the driver + TaitoResetFunction = TaitoDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 RastanInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x80; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = RastanCharPlaneOffsets; + TaitoCharXOffsets = RastanCharXOffsets; + TaitoCharYOffsets = RastanCharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = RastanSpritePlaneOffsets; + TaitoSpriteAXOffsets = RastanSpriteXOffsets; + TaitoSpriteAYOffsets = RastanSpriteYOffsets; + TaitoNumSpriteA = 0x1000; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2151 = 1; + TaitoNumMSM5205 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 8, 0, 0); + PC090OJInit(TaitoNumSpriteA, 0, 8, 0); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x05ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x10c000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x200000, 0x200fff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xc00000, 0xc0ffff, SM_RAM); + SekMapMemory(PC090OJRam , 0xd00000, 0xd03fff, SM_RAM); + SekSetReadByteHandler(0, Rastan68KReadByte); + SekSetWriteByteHandler(0, Rastan68KWriteByte); + SekSetWriteWordHandler(0, Rastan68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(RastanZ80Read); + ZetSetWriteHandler(RastanZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(16000000 / 4, 50.0); + BurnYM2151SetIrqHandler(&TaitoYM2151IRQHandler); + BurnYM2151SetPortHandler(&RastanBankSwitch); + + MSM5205Init(0, TaitoSynchroniseStream, 384000, RastanMSM5205Vck, MSM5205_S48_4B, 60, 1); + + GenericTilesInit(); + + TaitoDrawFunction = RastanDraw; + TaitoMakeInputsFunction = RastanMakeInputs; + TaitoIrqLine = 5; + + nTaitoCyclesTotal[0] = (16000000 / 2) / 60; + nTaitoCyclesTotal[1] = (16000000 / 4) / 60; + + // Reset the driver + TaitoResetFunction = RastanDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 TopspeedInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = TopspeedCharPlaneOffsets; + TaitoCharXOffsets = TopspeedCharXOffsets; + TaitoCharYOffsets = TopspeedCharYOffsets; + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = TopspeedSpritePlaneOffsets; + TaitoSpriteAXOffsets = TopspeedSpriteXOffsets; + TaitoSpriteAYOffsets = TopspeedSpriteYOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2151 = 1; + TaitoNumMSM5205 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC080SNInit(0, TaitoNumChar, 0, 8, 0, 0); + PC080SNInit(1, TaitoNumChar, 0, 8, 0, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x20000 , 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(TaitoSharedRam , 0x400000, 0x40ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x500000, 0x503fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0x800000, 0x80ffff, SM_RAM); + SekMapMemory(PC080SNRam[0] , 0xa00000, 0xa0ffff, SM_RAM); + SekMapMemory(PC080SNRam[1] , 0xb00000, 0xb0ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xd00000, 0xd00fff, SM_RAM); + SekMapMemory(TaitoVideoRam , 0xe00000, 0xe0ffff, SM_RAM); + SekSetReadByteHandler(0, Topspeed68K1ReadByte); + SekSetWriteByteHandler(0, Topspeed68K1WriteByte); + SekSetReadWordHandler(0, Topspeed68K1ReadWord); + SekSetWriteWordHandler(0, Topspeed68K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(TaitoSharedRam , 0x400000, 0x40ffff, SM_RAM); + SekSetReadByteHandler(0, Topspeed68K2ReadByte); + SekSetWriteByteHandler(0, Topspeed68K2WriteByte); + SekSetReadWordHandler(0, Topspeed68K2ReadWord); + SekSetWriteWordHandler(0, Topspeed68K2WriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(TopspeedZ80Read); + ZetSetWriteHandler(TopspeedZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x8fff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x8fff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2151Init(16000000 / 4, 50.0); + BurnYM2151SetIrqHandler(&TaitoYM2151IRQHandler); + BurnYM2151SetPortHandler(&TopspeedBankSwitch); + + MSM5205Init(0, TaitoSynchroniseStream, 384000, TopspeedMSM5205Vck, MSM5205_S48_4B, 60, 1); + + GenericTilesInit(); + + TaitoDrawFunction = TopspeedDraw; + TaitoMakeInputsFunction = TopspeedMakeInputs; + TaitoIrqLine = 5; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = 4000000 / 60; + + pTopspeedTempDraw = (UINT16*)malloc(512 * 512 * sizeof(UINT16)); + + // Reset the driver + TaitoResetFunction = TopspeedDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 VolfiedInit() +{ + INT32 nLen; + + TaitoNumChar = 0; + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = VolfiedSpritePlaneOffsets; + TaitoSpriteAXOffsets = VolfiedSpriteXOffsets; + TaitoSpriteAYOffsets = VolfiedSpriteYOffsets; + TaitoNumSpriteA = 0x1800; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + TaitoNumYM2203 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + PC090OJInit(TaitoNumSpriteA, 0, 8, 0); + PC090OJSetPaletteOffset(256); + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRom1 + 0x40000 , 0x080000, 0x0fffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(PC090OJRam , 0x200000, 0x203fff, SM_RAM); + SekMapMemory(TaitoVideoRam , 0x400000, 0x47ffff, SM_READ); + SekMapMemory(TaitoPaletteRam , 0x500000, 0x503fff, SM_RAM); + SekSetReadByteHandler(0, Volfied68KReadByte); + SekSetWriteByteHandler(0, Volfied68KWriteByte); + SekSetReadWordHandler(0, Volfied68KReadWord); + SekSetWriteWordHandler(0, Volfied68KWriteWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(VolfiedZ80Read); + ZetSetWriteHandler(VolfiedZ80Write); + ZetMapArea(0x0000, 0x7fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x7fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x8000, 0x87ff, 0, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x87ff, 1, TaitoZ80Ram1 ); + ZetMapArea(0x8000, 0x87ff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + BurnYM2203Init(1, 4000000, TaitoYM2203IRQHandler, TaitoSynchroniseStream, TaitoGetTime, 0); + BurnYM2203SetPorts(0, &VolfiedDip1Read, &VolfiedDip2Read, NULL, NULL); + BurnTimerAttachZet(4000000); + + GenericTilesInit(); + + TaitoDrawFunction = VolfiedDraw; + TaitoMakeInputsFunction = VolfiedMakeInputs; + TaitoIrqLine = 4; + + nTaitoCyclesTotal[0] = 8000000 / 60; + nTaitoCyclesTotal[1] = 4000000 / 60; + + VolfiedCChipInit(); + + // Reset the driver + TaitoResetFunction = VolfiedDoReset; + TaitoResetFunction(); + + return 0; +} + +static INT32 TaitoMiscExit() +{ + RastanADPCMPos = 0; + RastanADPCMData = 0; + memset(OpwolfADPCM_B, 0, 8); + memset(OpwolfADPCM_C, 0, 8); + OpwolfADPCMPos[0] = OpwolfADPCMPos[1] = 0; + OpwolfADPCMEnd[0] = OpwolfADPCMEnd[1] = 0; + OpwolfADPCMData[0] = OpwolfADPCMData[1] = 0; + + OpWolfGunXOffset = 0; + OpWolfGunYOffset = 0; + + DariusADPCMCommand = 0; + DariusNmiEnable = 0; + DariusCoinWord = 0; + + VolfiedVidCtrl = 0; + VolfiedVidMask = 0; + + if (pTopspeedTempDraw) { + free(pTopspeedTempDraw); + pTopspeedTempDraw = NULL; + } + + return TaitoExit(); +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | bits; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 0); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 10); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 OpwolfCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 8); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +inline static UINT32 JumpingCalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal4bit(nColour >> 0); + g = pal4bit(nColour >> 4); + b = pal4bit(nColour >> 8); + + return BurnHighCol(r, g, b, 0); +} + +static void TaitoMiscCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x2000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void OpwolfCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x0800; i++, ps++, pd++) { + *pd = OpwolfCalcCol(*ps); + } +} + +static void JumpingCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x0800; i++, ps++, pd++) { + *pd = JumpingCalcCol(*ps); + } +} + +static void DariusDrawSprites(INT32 PriorityDraw) +{ + INT32 Offset, sx, sy; + UINT16 Code, Data; + UINT8 xFlip, yFlip, Colour, Priority; + + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + + for (Offset = 0xf000 / 2 - 4; Offset >= 0; Offset -= 4) + { + Code = SpriteRam[Offset+ 2 ] &0x1fff; + + if (Code) { + Data = SpriteRam[Offset + 0]; + sy = (256 - Data) & 0x1ff; + + Data = SpriteRam[Offset + 1]; + sx = Data & 0x3ff; + + Data = SpriteRam[Offset + 2]; + xFlip = ((Data & 0x4000) >> 14); + yFlip = ((Data & 0x8000) >> 15); + + Data = SpriteRam[Offset + 3]; + Priority = (Data & 0x80) >> 7; + if (Priority != PriorityDraw) continue; + + Colour = (Data & 0x7f); + + if (sx > 900) sx -= 1024; + if (sy > 400) sy -= 512; + + sy -= 16; + + if (sx > 16 && sx < (nScreenWidth < 16) && sy > 16 && sy < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } + } + } +} + +static void DariusDrawCharLayer() +{ + INT32 mx, my, Code, Attr, Colour, x, y, Flip, xFlip, yFlip, TileIndex = 0; + + UINT16 *VideoRam = (UINT16*)TaitoVideoRam; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 128; mx++) { + Code = VideoRam[TileIndex + 0x2000] & (TaitoNumCharB - 1); + Attr = VideoRam[TileIndex + 0x0000]; + + Colour = (Attr & 0xff) << 2; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 2, 0, 0, TaitoCharsB); + } + } + } + + TileIndex++; + } + } +} + +static void JumpingDrawSprites() +{ + INT32 SpriteColBank = (PC090OJSpriteCtrl & 0xe0) >> 1; + + for (INT32 Offs = 0x400 - 8; Offs >= 0; Offs -= 8) { + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Tile = SpriteRam[Offs]; + if (Tile < 5120) { + INT32 sx, sy, Colour, Data1, xFlip, yFlip; + + sy = ((SpriteRam[Offs + 1] - 0xfff1) ^ 0xffff) & 0x1ff; + if (sy > 400) sy = sy - 512; + sx = (SpriteRam[Offs + 2] - 0x38) & 0x1ff; + if (sx > 400) sx = sx - 512; + + Data1 = SpriteRam[Offs + 3]; + Colour = (SpriteRam[Offs + 4] & 0x0f) | SpriteColBank; + xFlip = Data1 & 0x40; + yFlip = Data1 & 0x80; + + sy += 1; + sy -= 16; + + if (sx > 16 && sx < (nScreenWidth - 16) && sy > 16 && sy < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Tile, sx, sy, Colour, 4, 15, 0, TaitoSpritesA); + } + } + } + } + } +} + +static void RenderSpriteZoom(INT32 Code, INT32 sx, INT32 sy, INT32 Colour, INT32 xFlip, INT32 yFlip, INT32 xScale, INT32 yScale, UINT8* pSource) +{ + UINT8 *SourceBase = pSource + ((Code % TaitoNumSpriteA) * TaitoSpriteAWidth * TaitoSpriteAHeight); + + INT32 SpriteScreenHeight = (yScale * TaitoSpriteAHeight + 0x8000) >> 16; + INT32 SpriteScreenWidth = (xScale * TaitoSpriteAWidth + 0x8000) >> 16; + + Colour = 0x10 * (Colour % 0x100); + + if (TaitoFlipScreenX) { + xFlip = !xFlip; + sx = 320 - sx - (xScale >> 12); + } + + if (SpriteScreenWidth && SpriteScreenHeight) { + INT32 dx = (TaitoSpriteAWidth << 16) / SpriteScreenWidth; + INT32 dy = (TaitoSpriteAHeight << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (xFlip) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (yFlip) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth) { + INT32 Pixels = ex - nScreenWidth; + ex -= Pixels; + } + + if (ey > nScreenHeight) { + INT32 Pixels = ey - nScreenHeight; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * TaitoSpriteAWidth); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + INT32 x, xIndex = xIndexBase; + for (x = sx; x < ex; x++) { + INT32 c = Source[xIndex >> 16]; + if (c != 0) { + pPixel[x] = c | Colour; + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +static void TopspeedDrawSprites(INT32 PriorityDraw) +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, MapOffset, x, y, xCur, yCur, SpriteChunk; + UINT16 *SpriteMap = (UINT16*)TaitoVideoRam; + UINT16 Data, TileNum, Code, Colour; + UINT8 xFlip, yFlip, Priority, BadChunks; + UINT8 j, k, px, py, zx, zy, xZoom, yZoom; + + for (Offset = (0x2c0 / 2) - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 2]; + + TileNum = SpriteRam[Offset + 3] & 0xff; + Colour = (SpriteRam[Offset + 3] & 0xff00) >> 8; + xFlip = (Data & 0x4000) >> 14; + yFlip = (SpriteRam[Offset + 1] & 0x8000) >> 15; + x = Data & 0x1ff; + y = SpriteRam[Offset] & 0x1ff; + xZoom = (SpriteRam[Offset + 1] & 0x7f); + yZoom = (SpriteRam[Offset] & 0xfe00) >> 9; + Priority = (Data & 0x8000) >> 15; + + if (Priority != PriorityDraw) continue; + + if (y == 0x180) continue; + + MapOffset = TileNum << 7; + + xZoom += 1; + yZoom += 1; + + y += 3 + (128 - yZoom); + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + BadChunks = 0; + + for (SpriteChunk = 0; SpriteChunk < 128; SpriteChunk++) { + k = SpriteChunk % 8; + j = SpriteChunk / 8; + + px = (xFlip) ? (7 - k) : (k); + py = (yFlip) ? (15 - j) : (j); + + Code = SpriteMap[MapOffset + (py << 3) + px]; + + if (Code & 0x8000) { + BadChunks += 1; + continue; + } + + xCur = x + ((k * xZoom) / 8); + yCur = y + ((j * yZoom) / 16); + + zx = x + (((k + 1) * xZoom) / 8) - xCur; + zy = y + (((j + 1) * yZoom) / 16) - yCur; + + RenderSpriteZoom(Code, xCur, yCur - 16, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + } +} + +static void DariusDraw() +{ + BurnTransferClear(); + TaitoMiscCalcPalette(); + PC080SNDrawBgLayer(0, 1, TaitoChars, pTransDraw); + DariusDrawSprites(0); + PC080SNDrawFgLayer(0, 0, TaitoChars, pTransDraw); + DariusDrawSprites(1); + DariusDrawCharLayer(); + BurnTransferCopy(TaitoPalette); +} + +static void OpwolfDraw() +{ + BurnTransferClear(); + OpwolfCalcPalette(); + PC080SNDrawBgLayer(0, 1, TaitoChars, pTransDraw); + PC090OJDrawSprites(TaitoSpritesA); + PC080SNDrawFgLayer(0, 0, TaitoChars, pTransDraw); + BurnTransferCopy(TaitoPalette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static void RainbowDraw() +{ + BurnTransferClear(); + TaitoMiscCalcPalette(); + PC080SNDrawBgLayer(0, 1, TaitoChars, pTransDraw); + PC090OJDrawSprites(TaitoSpritesA); + PC080SNDrawFgLayer(0, 0, TaitoChars, pTransDraw); + BurnTransferCopy(TaitoPalette); +} + +static void JumpingDraw() +{ + BurnTransferClear(); + JumpingCalcPalette(); + PC080SNOverrideFgScroll(0, 16, 0); + PC080SNDrawBgLayer(0, 1, TaitoChars, pTransDraw); + JumpingDrawSprites(); + PC080SNDrawFgLayer(0, 0, TaitoChars, pTransDraw); + BurnTransferCopy(TaitoPalette); +} + +static void RastanDraw() +{ + BurnTransferClear(); + TaitoMiscCalcPalette(); + PC080SNDrawBgLayer(0, 1, TaitoChars, pTransDraw); + PC080SNDrawFgLayer(0, 0, TaitoChars, pTransDraw); + PC090OJDrawSprites(TaitoSpritesA); + BurnTransferCopy(TaitoPalette); +} + +static void TopspeedDraw() +{ + BurnTransferClear(); + TaitoMiscCalcPalette(); + PC080SNDrawFgLayer(1, 1, TaitoChars, pTransDraw); + TopspeedDrawSprites(1); + TopspeedDrawBgLayer(1, TaitoChars, pTopspeedTempDraw, (UINT16*)Taito68KRam1); + TopspeedDrawFgLayer(0, TaitoChars, pTopspeedTempDraw, (UINT16*)(Taito68KRam1 + 0x200)); + TopspeedDrawSprites(0); + PC080SNDrawBgLayer(0, 0, TaitoChars, pTransDraw); + BurnTransferCopy(TaitoPalette); +} + +static void VolfiedDraw() +{ + BurnTransferClear(); + TaitoMiscCalcPalette(); + + UINT16* p = (UINT16*)TaitoVideoRam; + if (VolfiedVidCtrl & 0x01) p += 0x20000; + for (INT32 y = 0; y < nScreenHeight + 8; y++) { + for (INT32 x = 1; x < nScreenWidth + 1; x++) { + INT32 Colour = (p[x] << 2) & 0x700; + + if (p[x] & 0x8000) { + Colour |= 0x800 | ((p[x] >> 9) & 0xf); + + if (p[x] & 0x2000) Colour &= ~0xf; + } else { + Colour |= p[x] & 0xf; + } + + if ((y - 8) >= 0 && (y - 8) < nScreenHeight) { + pTransDraw[((y - 8) * nScreenWidth) + x - 1] = Colour; + } + } + + p += 512; + } + + PC090OJDrawSprites(TaitoSpritesA); + BurnTransferCopy(TaitoPalette); +} + +static INT32 TaitoMiscFrame() +{ + INT32 nInterleave = 10; + if (TaitoNumMSM5205) nInterleave = MSM5205CalcInterleave(0, 8000000 / 2); + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 9) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + if (TaitoNumZ80s >= 1) { + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + if (TaitoNumMSM5205) MSM5205Update(); + ZetClose(); + } + + if (TaitoNumZ80s == 2) { + nCurrentCPU = 2; + ZetOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + if (i == 9) ZetRaiseIrq(0); + ZetClose(); + } + + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumYM2151) BurnYM2151Render(pSoundBuf, nSegmentLength); + if (TaitoNumZ80s >= 1) ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumYM2151) BurnYM2151Render(pSoundBuf, nSegmentLength); + if (TaitoNumZ80s >= 1) ZetClose(); + } + } + + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumMSM5205) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + if (TaitoNumMSM5205 >= 2) MSM5205Render(1, pBurnSoundOut, nBurnSoundLen); + if (TaitoNumZ80s >= 1) ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 DariusFrame() +{ + INT32 nInterleave = MSM5205CalcInterleave(0, 8000000 / 2); + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = nTaitoCyclesDone[3] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == nInterleave - 1) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 # 2 + if ((TaitoCpuACtrl & 0x01)) { + nCurrentCPU = 1; + SekOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == nInterleave - 1) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + ZetOpen(0); + BurnTimerUpdate(i * (nTaitoCyclesTotal[2] / nInterleave)); + ZetClose(); + + nCurrentCPU = 3; + ZetOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + MSM5205Update(); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[2]); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + // Reduce the YM2203 volume + for (INT32 j = 0; j < nBurnSoundLen * 2; j += 2) { + pBurnSoundOut[j + 0] /= 10; + pBurnSoundOut[j + 1] /= 10; + } + + ZetOpen(1); + ZetRun(nTaitoCyclesTotal[3] - nTaitoCyclesDone[3]); + MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 JumpingFrame() +{ + INT32 nInterleave = 100; + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + ZetOpen(0); + BurnTimerUpdate(i * (nTaitoCyclesTotal[1] / nInterleave)); + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1]); + BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 TopspeedFrame() +{ + INT32 nInterleave = 10; + if (TaitoNumMSM5205) nInterleave = MSM5205CalcInterleave(0, 4000000); + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoResetFunction(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 # 1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave / 2) && (GetCurrentFrame > 0)) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 # 2 + if ((TaitoCpuACtrl & 0x01)) { + nCurrentCPU = 1; + SekOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave / 2) && (GetCurrentFrame > 0)) SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + if (i == (nInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + // Run Z80 + if (TaitoNumZ80s >= 1) { + nCurrentCPU = 2; + ZetOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + if (TaitoNumMSM5205) MSM5205Update(); + ZetClose(); + } + + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumYM2151) BurnYM2151Render(pSoundBuf, nSegmentLength); + if (TaitoNumZ80s >= 1) ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumYM2151) BurnYM2151Render(pSoundBuf, nSegmentLength); + if (TaitoNumZ80s >= 1) ZetClose(); + } + } + + if (TaitoNumZ80s >= 1) ZetOpen(0); + if (TaitoNumMSM5205) MSM5205Render(0, pBurnSoundOut, nBurnSoundLen); + if (TaitoNumZ80s >= 1) ZetClose(); + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 TaitoMiscScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029683; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + if (TaitoNumYM2151) BurnYM2151Scan(nAction); + if (TaitoNumYM2203) BurnYM2203Scan(nAction, pnMin); + if (TaitoNumMSM5205) MSM5205Scan(nAction, pnMin); + + BurnGunScan(); + + SCAN_VAR(TaitoInput); + SCAN_VAR(TaitoAnalogPort0); + SCAN_VAR(TaitoAnalogPort1); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(TaitoSoundLatch); + SCAN_VAR(RastanADPCMPos); + SCAN_VAR(RastanADPCMData); + SCAN_VAR(OpwolfADPCM_B); + SCAN_VAR(OpwolfADPCM_C); + SCAN_VAR(OpwolfADPCMPos); + SCAN_VAR(OpwolfADPCMEnd);; + SCAN_VAR(OpwolfADPCMData); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + SCAN_VAR(DariusADPCMCommand); + SCAN_VAR(DariusNmiEnable); + SCAN_VAR(DariusCoinWord); + SCAN_VAR(PC090OJSpriteCtrl); // for jumping + } + + if (nAction & ACB_WRITE && TaitoZ80Bank) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvDarius = { + "darius", NULL, NULL, NULL, "1986", + "Darius (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, DariusRomInfo, DariusRomName, NULL, NULL, DariusInputInfo, DariusDIPInfo, + DariusInit, TaitoMiscExit, DariusFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvDariusj = { + "dariusj", "darius", NULL, NULL, "1986", + "Darius (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, DariusjRomInfo, DariusjRomName, NULL, NULL, DariusInputInfo, DariusjDIPInfo, + DariusInit, TaitoMiscExit, DariusFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvDariuso = { + "dariuso", "darius", NULL, NULL, "1986", + "Darius (Japan old version)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, DariusoRomInfo, DariusoRomName, NULL, NULL, DariusInputInfo, DariusjDIPInfo, + DariusInit, TaitoMiscExit, DariusFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvDariuse = { + "dariuse", "darius", NULL, NULL, "1986", + "Darius (Extra) (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_HORSHOOT, 0, + NULL, DariuseRomInfo, DariuseRomName, NULL, NULL, DariusInputInfo, DariuseDIPInfo, + DariusInit, TaitoMiscExit, DariusFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 864, 224, 12, 3 +}; + +struct BurnDriver BurnDrvOpwolf = { + "opwolf", NULL, NULL, NULL, "1987", + "Operation Wolf (World, set 1)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OpwolfRomInfo, OpwolfRomName, NULL, NULL, OpwolfInputInfo, OpwolfDIPInfo, + OpwolfInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolfa = { + "opwolfa", "opwolf", NULL, NULL, "1987", + "Operation Wolf (World, set 2)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OpwolfaRomInfo, OpwolfaRomName, NULL, NULL, OpwolfInputInfo, OpwolfDIPInfo, + OpwolfInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolfj = { + "opwolfj", "opwolf", NULL, NULL, "1987", + "Operation Wolf (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OpwolfjRomInfo, OpwolfjRomName, NULL, NULL, OpwolfInputInfo, OpwolfDIPInfo, + OpwolfInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolfu = { + "opwolfu", "opwolf", NULL, NULL, "1987", + "Operation Wolf (US)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OpwolfuRomInfo, OpwolfuRomName, NULL, NULL, OpwolfInputInfo, OpwolfuDIPInfo, + OpwolfInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvOpwolfb = { + "opwolfb", "opwolf", NULL, NULL, "1987", + "Operation Bear\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_SHOOT, 0, + NULL, OpwolfbRomInfo, OpwolfbRomName, NULL, NULL, OpwolfInputInfo, OpwolfbDIPInfo, + OpwolfbInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRainbow = { + "rainbow", NULL, NULL, NULL, "1987", + "Rainbow Islands (new version)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RainbowRomInfo, RainbowRomName, NULL, NULL, RainbowInputInfo, RainbowDIPInfo, + RainbowInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRainbowo = { + "rainbowo", "rainbow", NULL, NULL, "1987", + "Rainbow Islands (old version)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RainbowoRomInfo, RainbowoRomName, NULL, NULL, RainbowInputInfo, RainbowDIPInfo, + RainbowInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRainbowe = { + "rainbowe", "rainbow", NULL, NULL, "1988", + "Rainbow Islands (Extra)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RainboweRomInfo, RainboweRomName, NULL, NULL, RainbowInputInfo, RainbowDIPInfo, + RainbowInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvJumping = { + "jumping", "rainbow", NULL, NULL, "1989", + "Jumping\0", NULL, "bootleg", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, JumpingRomInfo, JumpingRomName, NULL, NULL, JumpingInputInfo, JumpingDIPInfo, + JumpingInit, TaitoMiscExit, JumpingFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvRastan = { + "rastan", NULL, NULL, NULL, "1987", + "Rastan (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RastanRomInfo, RastanRomName, NULL, NULL, RastanInputInfo, RastanDIPInfo, + RastanInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRastanu = { + "rastanu", "rastan", NULL, NULL, "1987", + "Rastan (US set 1)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RastanuRomInfo, RastanuRomName, NULL, NULL, RastanInputInfo, RastsagaDIPInfo, + RastanInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRastanu2 = { + "rastanu2", "rastan", NULL, NULL, "1987", + "Rastan (US set 2)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, Rastanu2RomInfo, Rastanu2RomName, NULL, NULL, RastanInputInfo, RastsagaDIPInfo, + RastanInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRastsaga = { + "rastsaga", "rastan", NULL, NULL, "1987", + "Rastan Saga (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, RastsagaRomInfo, RastsagaRomName, NULL, NULL, RastanInputInfo, RastsagaDIPInfo, + RastanInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvRastsaga1 = { + "rastsaga1", "rastan", NULL, NULL, "1987", + "Rastan Saga (Japan Rev 1)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_PLATFORM, 0, + NULL, Rastsaga1RomInfo, Rastsaga1RomName, NULL, NULL, RastanInputInfo, RastsagaDIPInfo, + RastanInit, TaitoMiscExit, TaitoMiscFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTopspeed = { + "topspeed", NULL, NULL, NULL, "1987", + "Top Speed (World)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_MISC, GBF_RACING, 0, + NULL, TopspeedRomInfo, TopspeedRomName, NULL, NULL, TopspeedInputInfo, TopspeedDIPInfo, + TopspeedInit, TaitoMiscExit, TopspeedFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTopspeedu = { + "topspeedu", "topspeed", NULL, NULL, "1987", + "Top Speed (US)\0", NULL, "Taito America Corporation (Romstar license)", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_RACING, 0, + NULL, TopspeeduRomInfo, TopspeeduRomName, NULL, NULL, TopspeedInputInfo, FullthrlDIPInfo, + TopspeedInit, TaitoMiscExit, TopspeedFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvFullthrl = { + "fullthrl", "topspeed", NULL, NULL, "1987", + "Full Throttle (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_MISC, GBF_RACING, 0, + NULL, FullthrlRomInfo, FullthrlRomName, NULL, NULL, TopspeedInputInfo, FullthrlDIPInfo, + TopspeedInit, TaitoMiscExit, TopspeedFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvVolfied = { + "volfied", NULL, NULL, NULL, "1989", + "Volfied (World, revision 1)\0", NULL, "Taito Corporation Japan", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_PUZZLE, 0, + NULL, VolfiedRomInfo, VolfiedRomName, NULL, NULL, VolfiedInputInfo, VolfiedDIPInfo, + VolfiedInit, TaitoMiscExit, JumpingFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvVolfiedj = { + "volfiedj", "volfied", NULL, NULL, "1989", + "Volfied (Japan, revision 1)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_PUZZLE, 0, + NULL, VolfiedjRomInfo, VolfiedjRomName, NULL, NULL, VolfiedInputInfo, VolfiedjDIPInfo, + VolfiedInit, TaitoMiscExit, JumpingFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvVolfiedjo = { + "volfiedjo", "volfied", NULL, NULL, "1989", + "Volfied (Japan)\0", NULL, "Taito Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_PUZZLE, 0, + NULL, VolfiedjoRomInfo, VolfiedjoRomName, NULL, NULL, VolfiedInputInfo, VolfiedjDIPInfo, + VolfiedInit, TaitoMiscExit, JumpingFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvVolfiedu = { + "volfiedu", "volfied", NULL, NULL, "1989", + "Volfied (US, revision 1)\0", NULL, "Taito America Corporation", "Taito Misc", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_MISC, GBF_PUZZLE, 0, + NULL, VolfieduRomInfo, VolfieduRomName, NULL, NULL, VolfiedInputInfo, VolfieduDIPInfo, + VolfiedInit, TaitoMiscExit, JumpingFrame, NULL, TaitoMiscScan, + NULL, 0x2000, 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/taito/d_taitox.cpp b/src/burn/drivers/taito/d_taitox.cpp new file mode 100644 index 00000000..6f0d344d --- /dev/null +++ b/src/burn/drivers/taito/d_taitox.cpp @@ -0,0 +1,1656 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2151.h" +#include "burn_ym2610.h" + +static struct BurnInputInfo SupermanInputList[]= +{ + {"P1 Coin" , BIT_DIGITAL, TaitoInputPort2 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL, TaitoInputPort0 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL, TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL, TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL, TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL, TaitoInputPort0 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL, TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL, TaitoInputPort0 + 5, "p1 fire 2" }, + + {"P2 Coin" , BIT_DIGITAL, TaitoInputPort2 + 1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL, TaitoInputPort1 + 7, "p2 start" }, + {"P2 Up" , BIT_DIGITAL, TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL, TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL, TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL, TaitoInputPort1 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL, TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Button 2" , BIT_DIGITAL, TaitoInputPort1 + 5, "p2 fire 2" }, + + {"Reset" , BIT_DIGITAL, &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL, TaitoInputPort2 + 2, "service" }, + {"Tilt" , BIT_DIGITAL, TaitoInputPort2 + 3, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Superman) + +static struct BurnInputInfo TwinhawkInputList[]= +{ + {"P1 Coin" , BIT_DIGITAL, TaitoInputPort2 + 0, "p1 coin" }, + {"P1 Start" , BIT_DIGITAL, TaitoInputPort0 + 7, "p1 start" }, + {"P1 Up" , BIT_DIGITAL, TaitoInputPort0 + 0, "p1 up" }, + {"P1 Down" , BIT_DIGITAL, TaitoInputPort0 + 1, "p1 down" }, + {"P1 Left" , BIT_DIGITAL, TaitoInputPort0 + 2, "p1 left" }, + {"P1 Right" , BIT_DIGITAL, TaitoInputPort0 + 3, "p1 right" }, + {"P1 Button 1" , BIT_DIGITAL, TaitoInputPort0 + 4, "p1 fire 1" }, + {"P1 Button 2" , BIT_DIGITAL, TaitoInputPort0 + 5, "p1 fire 2" }, + {"P1 Button 3" , BIT_DIGITAL, TaitoInputPort0 + 6, "p1 fire 3" }, + + {"P2 Coin" , BIT_DIGITAL, TaitoInputPort2 + 1, "p2 coin" }, + {"P2 Start" , BIT_DIGITAL, TaitoInputPort1 + 7, "p2 start" }, + {"P2 Up" , BIT_DIGITAL, TaitoInputPort1 + 0, "p2 up" }, + {"P2 Down" , BIT_DIGITAL, TaitoInputPort1 + 1, "p2 down" }, + {"P2 Left" , BIT_DIGITAL, TaitoInputPort1 + 2, "p2 left" }, + {"P2 Right" , BIT_DIGITAL, TaitoInputPort1 + 3, "p2 right" }, + {"P2 Button 1" , BIT_DIGITAL, TaitoInputPort1 + 4, "p2 fire 1" }, + {"P2 Button 2" , BIT_DIGITAL, TaitoInputPort1 + 5, "p2 fire 2" }, + {"P2 Button 3" , BIT_DIGITAL, TaitoInputPort1 + 6, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL, &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL, TaitoInputPort2 + 2, "service" }, + {"Tilt" , BIT_DIGITAL, TaitoInputPort2 + 3, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH, TaitoDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH, TaitoDip + 1 , "dip" }, +}; + +STDINPUTINFO(Twinhawk) + +static void TaitoXMakeInputs() +{ + TaitoInput[0] = TaitoInput[1] = TaitoInput[2] = 0xff; + + for (INT32 i = 0; i < 8; i++) { + TaitoInput[0] -= (TaitoInputPort0[i] & 1) << i; + TaitoInput[1] -= (TaitoInputPort1[i] & 1) << i; + TaitoInput[2] -= (TaitoInputPort2[i] & 1) << i; + + } +} + +static struct BurnDIPInfo BallbrosDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xdf, NULL }, + {0x16, 0xff, 0xff, 0x86, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x03, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0x0c, 0x04, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Medium" }, + {0x15, 0x01, 0x60, 0x20, "Hard" }, + {0x15, 0x01, 0x60, 0x00, "Hardest" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x02, 0x02, "Off" }, + {0x16, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x04, 0x00, "Off" }, + {0x16, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x16, 0x01, 0x20, 0x00, "English" }, + {0x16, 0x01, 0x20, 0x20, "Japanese" }, + + {0 , 0xfe, 0 , 2 , "Colour Change" }, + {0x16, 0x01, 0x40, 0x00, "Less" }, + {0x16, 0x01, 0x40, 0x40, "More" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Ballbros) + +static struct BurnDIPInfo GigandesDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xdf, NULL }, + {0x16, 0xff, 0xff, 0x98, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x03, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0x0c, 0x04, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Medium" }, + {0x15, 0x01, 0x60, 0x20, "Hard" }, + {0x15, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Debug Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x02, 0x00, "Off" }, + {0x16, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x18, 0x18, "3" }, + {0x16, 0x01, 0x18, 0x10, "4" }, + {0x16, 0x01, 0x18, 0x08, "5" }, + {0x16, 0x01, 0x18, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Controls" }, + {0x16, 0x01, 0x20, 0x20, "Single" }, + {0x16, 0x01, 0x20, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x16, 0x01, 0x40, 0x00, "English" }, + {0x16, 0x01, 0x40, 0x40, "Japanese" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Gigandes) + +static struct BurnDIPInfo KyustrkrDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xdf, NULL }, + {0x16, 0xff, 0xff, 0x80, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x03, 0x01, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x03, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x03, 0x02, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0x0c, 0x04, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x0c, 0x08, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x15, 0x01, 0x60, 0x60, "Easy" }, + {0x15, 0x01, 0x60, 0x40, "Medium" }, + {0x15, 0x01, 0x60, 0x20, "Hard" }, + {0x15, 0x01, 0x60, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Debug Mode" }, + {0x15, 0x01, 0x80, 0x80, "Off" }, + {0x15, 0x01, 0x80, 0x00, "On" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x16, 0x01, 0x01, 0x01, "Off" }, + {0x16, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x16, 0x01, 0x02, 0x00, "Off" }, + {0x16, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x04, 0x04, "Off" }, + {0x16, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x18, 0x18, "3" }, + {0x16, 0x01, 0x18, 0x10, "4" }, + {0x16, 0x01, 0x18, 0x08, "5" }, + {0x16, 0x01, 0x18, 0x00, "6" }, + + {0 , 0xfe, 0 , 2 , "Controls" }, + {0x16, 0x01, 0x20, 0x20, "Single" }, + {0x16, 0x01, 0x20, 0x00, "Dual" }, + + {0 , 0xfe, 0 , 2 , "Language" }, + {0x16, 0x01, 0x40, 0x00, "English" }, + {0x16, 0x01, 0x40, 0x40, "Japanese" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Kyustrkr) + +static struct BurnDIPInfo SupermanDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x00, "5" }, +}; + +STDDIPINFO(Superman) + +static struct BurnDIPInfo SupermanjDIPList[]= +{ + // Default Values + {0x13, 0xff, 0xff, 0xff, NULL }, + {0x14, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x13, 0x01, 0x02, 0x02, "Off" }, + {0x13, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x13, 0x01, 0x04, 0x04, "Off" }, + {0x13, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x00, "Off" }, + {0x13, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x13, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x13, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x13, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x13, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x14, 0x01, 0x03, 0x02, "Easy" }, + {0x14, 0x01, 0x03, 0x03, "Medium" }, + {0x14, 0x01, 0x03, 0x01, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x30, "3" }, + {0x14, 0x01, 0x30, 0x10, "4" }, + {0x14, 0x01, 0x30, 0x00, "5" }, +}; + +STDDIPINFO(Supermanj) + + +static struct BurnDIPInfo TwinhawkDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "50k and every 150k" }, + {0x16, 0x01, 0x0c, 0x08, "70k and every 200k" }, + {0x16, 0x01, 0x0c, 0x04, "50k only" }, + {0x16, 0x01, 0x0c, 0x00, "100k only" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x00, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Twinhawk) + +static struct BurnDIPInfo TwinhawkuDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xff, NULL }, + {0x16, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "4 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x40, "3 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0x80, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "50k and every 150k" }, + {0x16, 0x01, 0x0c, 0x08, "70k and every 200k" }, + {0x16, 0x01, 0x0c, 0x04, "50k only" }, + {0x16, 0x01, 0x0c, 0x00, "100k only" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x00, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Twinhawku) + +static struct BurnDIPInfo DaisenpuDIPList[]= +{ + // Default Values + {0x15, 0xff, 0xff, 0xfe, NULL }, + {0x16, 0xff, 0xff, 0x7f, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x15, 0x01, 0x01, 0x00, "Upright" }, + {0x15, 0x01, 0x01, 0x01, "Cocktail" }, + + {0 , 0xfe, 0 , 2 , "Flip Screen" }, + {0x15, 0x01, 0x02, 0x02, "Off" }, + {0x15, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x15, 0x01, 0x04, 0x04, "Off" }, + {0x15, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x00, "Off" }, + {0x15, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x15, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x15, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x15, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x15, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x16, 0x01, 0x03, 0x02, "Easy" }, + {0x16, 0x01, 0x03, 0x03, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x08, "50k and every 150k" }, + {0x16, 0x01, 0x0c, 0x0c, "70k and every 200k" }, + {0x16, 0x01, 0x0c, 0x04, "100k only" }, + {0x16, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x16, 0x01, 0x30, 0x00, "2" }, + {0x16, 0x01, 0x30, 0x30, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + {0x16, 0x01, 0x30, 0x20, "5" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "Off" }, + {0x16, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Daisenpu) + +static struct BurnRomInfo BallbrosRomDesc[] = { + { "10a", 0x20000, 0x4af0e858, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "5a", 0x20000, 0x0b983a69, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "8d", 0x10000, 0xd1c515af, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "3", 0x20000, 0xec3e0537, BRF_GRA | TAITO_SPRITESA }, + { "2", 0x20000, 0xbb441717, BRF_GRA | TAITO_SPRITESA }, + { "1", 0x20000, 0x8196d624, BRF_GRA | TAITO_SPRITESA }, + { "0", 0x20000, 0x1cc584e5, BRF_GRA | TAITO_SPRITESA }, + + { "east-11", 0x80000, 0x92111f96, BRF_SND | TAITO_YM2610A }, + { "east-10", 0x80000, 0xca0ac419, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Ballbros) +STD_ROM_FN(Ballbros) + +static struct BurnRomInfo GigandesRomDesc[] = { + { "1.10a", 0x20000, 0x290c50e0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "3.5a", 0x20000, 0x9cef82af, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "east_2.8a", 0x20000, 0xdd94b4d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "east_4.3a", 0x20000, 0xa647310a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "east_5.17d", 0x10000, 0xb24ab5f4, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "east_8.3f", 0x80000, 0x75eece28, BRF_GRA | TAITO_SPRITESA }, + { "east_7.3h", 0x80000, 0xb179a76a, BRF_GRA | TAITO_SPRITESA }, + { "east_9.3j", 0x80000, 0x5c5e6898, BRF_GRA | TAITO_SPRITESA }, + { "east_6.3k", 0x80000, 0x52db30e9, BRF_GRA | TAITO_SPRITESA }, + + { "east-11.16f", 0x80000, 0x92111f96, BRF_SND | TAITO_YM2610A }, + { "east-10.16e", 0x80000, 0xca0ac419, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Gigandes) +STD_ROM_FN(Gigandes) + +static struct BurnRomInfo GigandesjRomDesc[] = { + { "east_1.10a", 0x20000, 0xae74e4e5, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "east_3.5a", 0x20000, 0x8bcf2116, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "east_2.8a", 0x20000, 0xdd94b4d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "east_4.3a", 0x20000, 0xa647310a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "east_5.17d", 0x10000, 0xb24ab5f4, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "east_8.3f", 0x80000, 0x75eece28, BRF_GRA | TAITO_SPRITESA }, + { "east_7.3h", 0x80000, 0xb179a76a, BRF_GRA | TAITO_SPRITESA }, + { "east_9.3j", 0x80000, 0x5c5e6898, BRF_GRA | TAITO_SPRITESA }, + { "east_6.3k", 0x80000, 0x52db30e9, BRF_GRA | TAITO_SPRITESA }, + + { "east-11.16f", 0x80000, 0x92111f96, BRF_SND | TAITO_YM2610A }, + { "east-10.16e", 0x80000, 0xca0ac419, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Gigandesj) +STD_ROM_FN(Gigandesj) + +static struct BurnRomInfo KyustrkrRomDesc[] = { + { "pe.9a", 0x20000, 0x082b5f96, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "po.4a", 0x20000, 0x0100361e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "ic.18d", 0x10000, 0x92cfb788, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "m-8-3.u3", 0x20000, 0x1c4084e6, BRF_GRA | TAITO_SPRITESA }, + { "m-8-2.u4", 0x20000, 0xada21c4d, BRF_GRA | TAITO_SPRITESA }, + { "m-8-1.u5", 0x20000, 0x9d95aad6, BRF_GRA | TAITO_SPRITESA }, + { "m-8-0.u6", 0x20000, 0x0dfb6ed3, BRF_GRA | TAITO_SPRITESA }, + + { "m-8-5.u2", 0x20000, 0xd9d90e0a, BRF_SND | TAITO_YM2610A }, + { "m-8-4.u1", 0x20000, 0xd3f6047a, BRF_SND | TAITO_YM2610B }, +}; + +STD_ROM_PICK(Kyustrkr) +STD_ROM_FN(Kyustrkr) + +static struct BurnRomInfo SupermanRomDesc[] = { + { "a10_09.bin", 0x20000, 0x640f1d58, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a05_07.bin", 0x20000, 0xfddb9953, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a08_08.bin", 0x20000, 0x79fc028e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a03_13.bin", 0x20000, 0x9f446a44, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d18_10.bin", 0x10000, 0x6efe79e8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "f01_14.bin", 0x80000, 0x89368c3e, BRF_GRA | TAITO_SPRITESA }, + { "h01_15.bin", 0x80000, 0x910cc4f9, BRF_GRA | TAITO_SPRITESA }, + { "j01_16.bin", 0x80000, 0x3622ed2f, BRF_GRA | TAITO_SPRITESA }, + { "k01_17.bin", 0x80000, 0xc34f27e0, BRF_GRA | TAITO_SPRITESA }, + + { "e18_01.bin", 0x80000, 0x3cf99786, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Superman) +STD_ROM_FN(Superman) + +static struct BurnRomInfo SupermanjRomDesc[] = { + { "a10_09.bin", 0x20000, 0x640f1d58, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a05_07.bin", 0x20000, 0xfddb9953, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "a08_08.bin", 0x20000, 0x79fc028e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b61-06.a3", 0x20000, 0x714a0b68, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "d18_10.bin", 0x10000, 0x6efe79e8, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "f01_14.bin", 0x80000, 0x89368c3e, BRF_GRA | TAITO_SPRITESA }, + { "h01_15.bin", 0x80000, 0x910cc4f9, BRF_GRA | TAITO_SPRITESA }, + { "j01_16.bin", 0x80000, 0x3622ed2f, BRF_GRA | TAITO_SPRITESA }, + { "k01_17.bin", 0x80000, 0xc34f27e0, BRF_GRA | TAITO_SPRITESA }, + + { "e18_01.bin", 0x80000, 0x3cf99786, BRF_SND | TAITO_YM2610A }, +}; + +STD_ROM_PICK(Supermanj) +STD_ROM_FN(Supermanj) + +static struct BurnRomInfo TwinhawkRomDesc[] = { + { "b87-11.u7", 0x20000, 0xfc84a399, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b87-10.u5", 0x20000, 0x17181706, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b87-07.13e", 0x08000, 0xe2e0efa0, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b87-02.3h", 0x80000, 0x89ad43a0, BRF_GRA | TAITO_SPRITESA }, + { "b87-01.3f", 0x80000, 0x81e82ae1, BRF_GRA | TAITO_SPRITESA }, + { "b87-04.3k", 0x80000, 0x958434b6, BRF_GRA | TAITO_SPRITESA }, + { "b87-03.3j", 0x80000, 0xce155ae0, BRF_GRA | TAITO_SPRITESA }, + +}; + +STD_ROM_PICK(Twinhawk) +STD_ROM_FN(Twinhawk) + +static struct BurnRomInfo TwinhawkuRomDesc[] = { + { "b87-09.u7", 0x20000, 0x7e6267c7, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b87-08.u5", 0x20000, 0x31d9916f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b87-07.13e", 0x08000, 0xe2e0efa0, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b87-02.3h", 0x80000, 0x89ad43a0, BRF_GRA | TAITO_SPRITESA }, + { "b87-01.3f", 0x80000, 0x81e82ae1, BRF_GRA | TAITO_SPRITESA }, + { "b87-04.3k", 0x80000, 0x958434b6, BRF_GRA | TAITO_SPRITESA }, + { "b87-03.3j", 0x80000, 0xce155ae0, BRF_GRA | TAITO_SPRITESA }, + +}; + +STD_ROM_PICK(Twinhawku) +STD_ROM_FN(Twinhawku) + +static struct BurnRomInfo DaisenpuRomDesc[] = { + { "b87-06.u7", 0x20000, 0xcf236100, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b87-05.u5", 0x20000, 0x7f15edc7, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b87-07.13e", 0x08000, 0xe2e0efa0, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b87-02.3h", 0x80000, 0x89ad43a0, BRF_GRA | TAITO_SPRITESA }, + { "b87-01.3f", 0x80000, 0x81e82ae1, BRF_GRA | TAITO_SPRITESA }, + { "b87-04.3k", 0x80000, 0x958434b6, BRF_GRA | TAITO_SPRITESA }, + { "b87-03.3j", 0x80000, 0xce155ae0, BRF_GRA | TAITO_SPRITESA }, + +}; + +STD_ROM_PICK(Daisenpu) +STD_ROM_FN(Daisenpu) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x004000; + TaitoZ80Ram1 = Next; Next += 0x002000; + TaitoPaletteRam = Next; Next += 0x001000; + TaitoSpriteRam = Next; Next += 0x000800; + TaitoSpriteRam2 = Next; Next += 0x004000; + + TaitoRamEnd = Next; + + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoPalette = (UINT32*)Next; Next += 0x00800 * sizeof(UINT32); + + TaitoMemEnd = Next; + + return 0; +} + +UINT8 __fastcall TaitoX68KReadByte(UINT32 a) +{ + if (TaitoIC_SupermanCChipInUse) { + if (a >= 0x900000 && a <= 0x9007ff) { + return SupermanCChipRamRead((a - 0x900000) >> 1, TaitoInput[0], TaitoInput[1], TaitoInput[2]); + } + } + + switch (a) { + case 0x500001: { + return TaitoDip[0] & 0x0f; + } + + case 0x500003: { + return (TaitoDip[0] & 0xf0) >> 4; + } + + case 0x500005: { + return TaitoDip[1] & 0x0f; + } + + case 0x500007: { + return (TaitoDip[1] & 0xf0) >> 4; + } + + case 0x800003: { + return TC0140SYTCommRead(); + } + + case 0x900001: { + return TaitoInput[0]; + } + + case 0x900003: { + return TaitoInput[1]; + } + + case 0x900005: { + return TaitoInput[2]; + } + + case 0x900803: { + if (TaitoIC_SupermanCChipInUse) return SupermanCChipCtrlRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoX68KWriteByte(UINT32 a, UINT8 d) +{ + if (TaitoIC_SupermanCChipInUse) { + if (a >= 0x900000 && a <= 0x9007ff) { + SupermanCChipRamWrite((a - 0x900000) >> 1, d); + return; + } + } + + switch (a) { + case 0x300000: + case 0x300001: { + //??? + return; + } + + case 0x400000: + case 0x400001: { + //nop + return; + } + + case 0x600000: + case 0x600001: { + //nop + return; + } + + case 0x700000: + case 0x700001: { + //nop + return; + } + + case 0x800001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x800003: { + TC0140SYTCommWrite(d); + return; + } + + case 0x900009: { + // coin write + return; + } + + case 0x900803: { + if (TaitoIC_SupermanCChipInUse) { + SupermanCChipCtrlWrite(); + return; + } + } + + case 0x900c01: { + if (TaitoIC_SupermanCChipInUse) { + SupermanCChipBankWrite(d); + return; + } + } + + case 0xc00000: + case 0xc00001: { + //??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall TaitoX68KReadWord(UINT32 a) +{ + switch (a) { + case 0x500000: { + return TaitoDip[0] & 0x0f; + } + + case 0x500002: { + return (TaitoDip[0] & 0xf0) >> 4; + } + + case 0x500004: { + return TaitoDip[1] & 0x0f; + } + + case 0x500006: { + return (TaitoDip[1] & 0xf0) >> 4; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +UINT8 __fastcall TaitoXZ80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe001: { + return BurnYM2610Read(1); + } + + case 0xe002: { + return BurnYM2610Read(2); + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoXZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xe400: + case 0xe401: + case 0xe402: + case 0xe403: { + //nop + return; + } + + case 0xe600: { + //??? + return; + } + + case 0xee00: { + //nop + return; + } + + case 0xf000: { + //nop + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 3; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +UINT8 __fastcall TwinhawkZ80Read(UINT16 a) +{ + switch (a) { + case 0xe001: { + return BurnYM2151ReadStatus(); + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TwinhawkZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2151SelectRegister(d); + return; + } + + case 0xe001: { + BurnYM2151WriteRegister(d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 3; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static void TaitoXFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 TaitoXSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 4000000; +} + +static double TaitoXGetTime() +{ + return (double)ZetTotalCycles() / 4000000; +} + +static void TaitoXYM2151IRQHandler(INT32 Irq) +{ + if (Irq) { + ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 SpritePlaneOffsets[4] = { 0x800008, 0x800000, 8, 0 }; +static INT32 SpriteXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 }; +static INT32 SpriteYOffsets[16] = { 0, 16, 32, 48, 64, 80, 96, 112, 256, 272, 288, 304, 320, 336, 352, 368 }; +static INT32 BallbrosPlaneOffsets[4] = { 0x300000, 0x200000, 0x100000, 0 }; +static INT32 BallbrosXOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 64, 65, 66, 67, 68, 69, 70, 71 }; +static INT32 BallbrosYOffsets[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 128, 136, 144, 152, 160, 168, 176, 184 }; + +static INT32 TaitoXInit(INT32 nSoundType) +{ + INT32 nLen; + + TaitoNum68Ks = 1; + TaitoNumZ80s = 1; + if (nSoundType == 1) { + TaitoNumYM2151 = 1; + } else { + TaitoNumYM2610 = 1; + } + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + if (TaitoLoadRoms(1)) return 1; + + TC0140SYTInit(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, Taito68KRom1Size - 1, SM_ROM); + SekMapMemory(TaitoPaletteRam , 0xb00000, 0xb00fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xd00000, 0xd007ff, SM_RAM); + SekMapMemory(TaitoSpriteRam2 , 0xe00000, 0xe03fff, SM_RAM); + SekMapMemory(Taito68KRam1 , 0xf00000, 0xf03fff, SM_RAM); + SekSetReadByteHandler(0, TaitoX68KReadByte); + SekSetWriteByteHandler(0, TaitoX68KWriteByte); + SekSetReadWordHandler(0, TaitoX68KReadWord); + SekClose(); + + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + if (nSoundType == 1) { + ZetSetReadHandler(TwinhawkZ80Read); + ZetSetWriteHandler(TwinhawkZ80Write); + } else { + ZetSetReadHandler(TaitoXZ80Read); + ZetSetWriteHandler(TaitoXZ80Write); + } + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + if (nSoundType == 1) { + BurnYM2151Init(4000000, 50.0); + BurnYM2151SetIrqHandler(&TaitoXYM2151IRQHandler); + } else { + if (nSoundType == 2) { + BurnYM2610Init(8000000, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, NULL, TaitoXSynchroniseStream, TaitoXGetTime, 0); + } else { + BurnYM2610Init(8000000, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, &TaitoXFMIRQHandler, TaitoXSynchroniseStream, TaitoXGetTime, 0); + } + BurnTimerAttachZet(4000000); + } + + GenericTilesInit(); + + nTaitoCyclesTotal[0] = (8000000) / 60; + nTaitoCyclesTotal[1] = (4000000) / 60; + + if (nScreenHeight == 224) TaitoYOffset = 16; + if (nScreenHeight == 240) TaitoYOffset = 8; + TaitoIrqLine = 2; + + TaitoDoReset(); + + return 0; +} + +static INT32 BallbrosInit() +{ + TaitoSpriteAModulo = 0x100; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = BallbrosPlaneOffsets; + TaitoSpriteAXOffsets = BallbrosXOffsets; + TaitoSpriteAYOffsets = BallbrosYOffsets; + TaitoNumSpriteA = 0x1000; + + return TaitoXInit(2); +} + +static INT32 GigandesInit() +{ + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + return TaitoXInit(2); +} + +static INT32 SupermanInit() +{ + INT32 nRet; + + SupermanCChipInit(); + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + nRet = TaitoXInit(0); + + TaitoIrqLine = 6; + + return nRet; +} + +static INT32 TwinhawkInit() +{ + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + return TaitoXInit(1); +} + +static INT32 TaitoXExit() +{ + return TaitoExit(); +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 10); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 0); + + return BurnHighCol(r, g, b, 0); +} + +static void TaitoXCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x0800; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void TaitoXDrawBgSprites() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRam2 = (UINT16*)TaitoSpriteRam2; + + INT32 Offs, Col, x, y, Code, Colour, xFlip, yFlip, sx, sy, yOffs; + + INT32 Ctrl = SpriteRam[0x300]; + INT32 Ctrl2 = SpriteRam[0x301]; + + INT32 Flip = Ctrl & 0x40; + INT32 NumCol = Ctrl2 & 0x000f; + + UINT16 *src = SpriteRam2 + (((Ctrl2 ^ (~Ctrl2 << 1)) & 0x40) ? 0x1000 : 0 ); + + INT32 Upper = (SpriteRam[0x302] & 0xff) + (SpriteRam[0x303] & 0xff) * 256; + INT32 Col0; + switch (Ctrl & 0x0f) { + case 0x01: Col0 = 0x4; break; + case 0x06: Col0 = 0x8; break; + + default: Col0 = 0x0; + } + + yOffs = Flip ? 1 : -1; + + if (NumCol == 1) NumCol = 16; + + for (Col = 0; Col < NumCol; Col++) { + x = SpriteRam[(Col * 0x20 + 0x08 + 0x400) / 2] & 0xff; + y = SpriteRam[(Col * 0x20 + 0x00 + 0x400) / 2] & 0xff; + + for (Offs = 0; Offs < 0x20; Offs++) { + Code = src[((Col + Col0) & 0x0f) * 0x20 + Offs + 0x400]; + Colour = src[((Col + Col0) & 0x0f) * 0x20 + Offs + 0x600]; + + xFlip = Code & 0x8000; + yFlip = Code & 0x4000; + + sx = x + (Offs & 1) * 16; + sy = -(y + yOffs) + (Offs / 2) * 16; + + if (Upper & (1 << Col)) sx += 256; + + if (Flip) { + sy = 0xf0 - sy; + xFlip = !xFlip; + yFlip = !yFlip; + } + + Colour = (Colour >> (16 - 5)) % 0x100; + Code &= (TaitoNumSpriteA - 1); + + sx = ((sx + 16) & 0x1ff) - 16; + sy = ((sy + 8) & 0xff) - 8; + + sy -= TaitoYOffset; + + if (sx > 16 && sx < (nScreenWidth - 16) && sy > 16 && sy < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } + } + } +} + +static void TaitoXDrawSprites() +{ + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + UINT16 *SpriteRam2 = (UINT16*)TaitoSpriteRam2; + + INT32 Offset, Code, x, y, xFlip, yFlip, Colour; + INT32 Ctrl = SpriteRam[0x300]; + INT32 Ctrl2 = SpriteRam[0x301]; + INT32 Flip = Ctrl & 0x40; + UINT16 *src = SpriteRam2 + (((Ctrl2 ^ (~Ctrl2 << 1)) & 0x40) ? 0x1000 : 0); + + for (Offset = (0x400 - 2) / 2; Offset >= 0; Offset-- ) { + Code = src[Offset]; + x = src[Offset + 0x200]; + y = SpriteRam[Offset] & 0xff; + xFlip = Code & 0x8000; + yFlip = Code & 0x4000; + + Colour = (x >> (16 - 5) ) % 0x100; + + Code &= (TaitoNumSpriteA - 1); + + if (Flip) { + y = 0xf0 - y; + xFlip = !xFlip; + yFlip = !yFlip; + } + + y = 0xf0 - y; + x = ((x + 16) & 0x1ff) - 16; + y = ((y + 8) & 0xff) - 8; + + y -= TaitoYOffset - 2; + + if (x > 16 && x < (nScreenWidth - 16) && y > 16 && y < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TaitoSpritesA); + } + } + } + } + +} + +static void TaitoXDraw() +{ + TaitoXCalcPalette(); + + for (INT32 i = 0; i < nScreenHeight * nScreenWidth; i++) { + pTransDraw[i] = 0x1f0; + } + + TaitoXDrawBgSprites(); + TaitoXDrawSprites(); + BurnTransferCopy(TaitoPalette); +} + +static INT32 TaitoXFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoDoReset(); + + TaitoXMakeInputs(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + nCurrentCPU = 0; + SekOpen(nCurrentCPU); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (nInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + nCurrentCPU = 1; + ZetOpen(0); + BurnTimerUpdate(i * (nTaitoCyclesTotal[1] / nInterleave)); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2610Update(pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + ZetClose(); + } + + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[1]); + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2610Update(pSoundBuf, nSegmentLength); + } + } + ZetClose(); + + if (pBurnDraw) TaitoXDraw(); + + return 0; +} + +static INT32 TwinhawkFrame() +{ + INT32 nInterleave = 10; + INT32 nSoundBufferPos = 0; + + if (TaitoReset) TaitoDoReset(); + + TaitoXMakeInputs(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = 0; + + SekNewFrame(); + ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 9) SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run Z80 + nCurrentCPU = 1; + ZetOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesSegment = ZetRun(nTaitoCyclesSegment); + nTaitoCyclesDone[nCurrentCPU] += nTaitoCyclesSegment; + ZetClose(); + + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + nSoundBufferPos += nSegmentLength; + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + ZetOpen(0); + BurnYM2151Render(pSoundBuf, nSegmentLength); + ZetClose(); + } + } + + if (pBurnDraw) TaitoXDraw(); + + return 0; +} + +static INT32 TaitoXScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029683; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + ZetScan(nAction); + + if (TaitoNumYM2610) BurnYM2610Scan(nAction, pnMin); + if (TaitoNumYM2151) BurnYM2151Scan(nAction); + + SCAN_VAR(TaitoInput); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(TaitoSoundLatch); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + } + + if (nAction & ACB_WRITE) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + + return 0; +} + +struct BurnDriver BurnDrvBallbros = { + "ballbros", NULL, NULL, NULL, "1992", + "Balloon Brothers\0", NULL, "East Technology", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOX, GBF_PUZZLE, 0, + NULL, BallbrosRomInfo, BallbrosRomName, NULL, NULL, TwinhawkInputInfo, BallbrosDIPInfo, + BallbrosInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGigandes = { + "gigandes", NULL, NULL, NULL, "1989", + "Gigandes\0", NULL, "East Technology", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOX, GBF_HORSHOOT, 0, + NULL, GigandesRomInfo, GigandesRomName, NULL, NULL, TwinhawkInputInfo, GigandesDIPInfo, + GigandesInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvGigandesj = { + "gigandesj", "gigandes", NULL, NULL, "1989", + "Gigandes (Japan)\0", NULL, "East Technology", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOX, GBF_HORSHOOT, 0, + NULL, GigandesjRomInfo, GigandesjRomName, NULL, NULL, TwinhawkInputInfo, GigandesDIPInfo, + GigandesInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvKyustrkr = { + "kyustrkr", NULL, NULL, NULL, "1989", + "Last Striker / Kyuukyoku no Striker\0", NULL, "East Technology", "Taito-X", + L"Last Striker\0Final \u7A76\u6975 \u306E Striker\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_TAITO_TAITOX, GBF_SPORTSFOOTBALL, 0, + NULL, KyustrkrRomInfo, KyustrkrRomName, NULL, NULL, TwinhawkInputInfo, KyustrkrDIPInfo, + BallbrosInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSuperman = { + "superman", NULL, NULL, NULL, "1988", + "Superman\0", NULL, "Taito Corporation", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOX, GBF_SCRFIGHT, 0, + NULL, SupermanRomInfo, SupermanRomName, NULL, NULL, SupermanInputInfo, SupermanDIPInfo, + SupermanInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSupermanj = { + "supermanj", "superman", NULL, NULL, "1988", + "Superman (Japan)\0", NULL, "Taito Corporation", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOX, GBF_SCRFIGHT, 0, + NULL, SupermanjRomInfo, SupermanjRomName, NULL, NULL, SupermanInputInfo, SupermanjDIPInfo, + SupermanInit, TaitoXExit, TaitoXFrame, NULL, TaitoXScan, + NULL, 0x800, 384, 240, 4, 3 +}; + +struct BurnDriver BurnDrvTwinhawk = { + "twinhawk", NULL, NULL, NULL, "1989", + "Twin Hawk (World)\0", NULL, "Taito Corporation Japan", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOX, GBF_VERSHOOT, 0, + NULL, TwinhawkRomInfo, TwinhawkRomName, NULL, NULL, TwinhawkInputInfo, TwinhawkDIPInfo, + TwinhawkInit, TaitoXExit, TwinhawkFrame, NULL, TaitoXScan, + NULL, 0x800, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvTwinhawku = { + "twinhawku", "twinhawk", NULL, NULL, "1989", + "Twin Hawk (US)\0", NULL, "Taito America Corporation", "Taito-X", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOX, GBF_VERSHOOT, 0, + NULL, TwinhawkuRomInfo, TwinhawkuRomName, NULL, NULL, TwinhawkInputInfo, TwinhawkuDIPInfo, + TwinhawkInit, TaitoXExit, TwinhawkFrame, NULL, TaitoXScan, + NULL, 0x800, 224, 384, 3, 4 +}; + +struct BurnDriver BurnDrvDaisenpu = { + "daisenpu", "twinhawk", NULL, NULL, "1989", + "Daisenpu (Japan)\0", NULL, "Taito Corporation", "Taito-X", + L"\u5927\u65CB\u98A8 (Japan)\0Daisenpu\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TAITO_TAITOX, GBF_VERSHOOT, 0, + NULL, DaisenpuRomInfo, DaisenpuRomName, NULL, NULL, TwinhawkInputInfo, DaisenpuDIPInfo, + TwinhawkInit, TaitoXExit, TwinhawkFrame, NULL, TaitoXScan, + NULL, 0x800, 224, 384, 3, 4 +}; diff --git a/src/burn/drivers/taito/d_taitoz.cpp b/src/burn/drivers/taito/d_taitoz.cpp new file mode 100644 index 00000000..3d56b760 --- /dev/null +++ b/src/burn/drivers/taito/d_taitoz.cpp @@ -0,0 +1,6045 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2610.h" +#include "eeprom.h" +#include "burn_gun.h" + +static INT32 Sci; +static INT32 Dblaxle; +static INT32 OldSteer; // Hack to centre the steering in SCI +static INT32 SciSpriteFrame; + +static void AquajackDraw(); +static void BsharkDraw(); +static void ChasehqDraw(); +static void ContcircDraw(); +static void EnforceDraw(); +static void DblaxleDraw(); +static void SciDraw(); +static void SpacegunDraw(); + +static bool bUseAsm68KCoreOldValue = false; + +#define A(a, b, c, d) {a, b, (UINT8*)(c), d} + +static struct BurnInputInfo AquajackInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p2 coin" }, + + {"Up" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 up" }, + {"Down" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p1 left" }, + {"Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p1 right" }, + {"Jump" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p1 fire 1" }, + {"Accelerate" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 fire 2" }, + {"Vulcan" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p1 fire 3" }, + {"Missile" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p1 fire 4" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Aquajack) + +static struct BurnInputInfo BsharkInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "p2 start" }, + + A("Crosshair X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + A("Crosshair Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "p1 y-axis" ), + {"Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Bshark) + +static struct BurnInputInfo BsharkjjsInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "p2 start" }, + + {"Up" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "p1 up" }, + {"Down" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p1 down" }, + {"Left" , BIT_DIGITAL , TC0220IOCInputPort2 + 5, "p1 left" }, + {"Right" , BIT_DIGITAL , TC0220IOCInputPort2 + 4, "p1 right" }, + {"Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Bsharkjjs) + +static struct BurnInputInfo ChasehqInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"Brake" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 1" }, + {"Accelerate" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p1 fire 2" }, + {"Turbo" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 fire 3" }, + {"Gear" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p1 fire 4" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Chasehq) + +static struct BurnInputInfo ContcircInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"Brake" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p1 fire 1" }, + {"Accelerate" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 fire 2" }, + {"Gear" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p1 fire 3" }, + {"Brake 2" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p1 fire 4" }, + {"Brake 3" , BIT_DIGITAL , TC0220IOCInputPort1 + 6, "p1 fire 5" }, + {"Accelerate 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 6" }, + {"Accelerate 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 fire 7" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Contcirc) + +static struct BurnInputInfo DblaxleInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0510NIOInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0510NIOInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0510NIOInputPort0 + 3, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"Brake" , BIT_DIGITAL , TC0510NIOInputPort0 + 5, "p1 fire 1" }, + {"Accelerate" , BIT_DIGITAL , TC0510NIOInputPort1 + 5, "p1 fire 2" }, + {"Nitro" , BIT_DIGITAL , TC0510NIOInputPort1 + 0, "p1 fire 3" }, + {"Gear" , BIT_DIGITAL , TC0510NIOInputPort0 + 1, "p1 fire 4" }, + {"Reverse" , BIT_DIGITAL , TC0510NIOInputPort0 + 7, "p1 fire 5" }, + {"Centre" , BIT_DIGITAL , TC0510NIOInputPort1 + 2, "p1 fire 6" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0510NIOInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0510NIOInputPort1 + 1, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0510NIODip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0510NIODip + 1 , "dip" }, +}; + +STDINPUTINFO(Dblaxle) + +static struct BurnInputInfo EnforceInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p2 coin" }, + + {"Up" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 up" }, + {"Down" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 down" }, + {"Left" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p1 left" }, + {"Right" , BIT_DIGITAL , TC0220IOCInputPort1 + 7, "p1 right" }, + {"Laser" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 fire 1" }, + {"Bomb" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Enforce) + +static struct BurnInputInfo NightstrInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "p2 start" }, + + A("Stick X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + A("Stick Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "p1 y-axis" ), + {"Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 6, "p1 fire 1" }, + {"Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 7, "p1 fire 2" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Nightstr) + +static struct BurnInputInfo SciInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort1 + 3, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p2 coin" }, + + A("Steering" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "p1 x-axis" ), + {"Brake" , BIT_DIGITAL , TC0220IOCInputPort0 + 5, "p1 fire 1" }, + {"Accelerate" , BIT_DIGITAL , TC0220IOCInputPort1 + 5, "p1 fire 2" }, + {"Fire" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p1 fire 3" }, + {"Turbo" , BIT_DIGITAL , TC0220IOCInputPort1 + 0, "p1 fire 4" }, + {"Gear" , BIT_DIGITAL , TC0220IOCInputPort1 + 4, "p1 fire 5" }, + {"Centre" , BIT_DIGITAL , TC0220IOCInputPort1 + 2, "p1 fire 6" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Tilt" , BIT_DIGITAL , TC0220IOCInputPort1 + 1, "tilt" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Sci) + +static struct BurnInputInfo SpacegunInputList[] = +{ + {"Coin 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 3, "p1 coin" }, + {"Start 1" , BIT_DIGITAL , TC0220IOCInputPort0 + 6, "p1 start" }, + {"Coin 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 2, "p2 coin" }, + {"Start 2" , BIT_DIGITAL , TC0220IOCInputPort0 + 7, "p2 start" }, + + A("P1 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort0 , "mouse x-axis" ), + A("P1 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort1 , "mouse y-axis" ), + {"P1 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 0, "mouse button 1" }, + {"P1 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 2, "mouse button 2" }, + {"P1 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 0, "p1 fire 1" }, + + A("P2 Gun X" , BIT_ANALOG_REL, &TaitoAnalogPort2 , "p2 x-axis" ), + A("P2 Gun Y" , BIT_ANALOG_REL, &TaitoAnalogPort3 , "p2 y-axis" ), + {"P2 Fire 1" , BIT_DIGITAL , TC0220IOCInputPort2 + 1, "p2 fire 1" }, + {"P2 Fire 2" , BIT_DIGITAL , TC0220IOCInputPort2 + 3, "p2 fire 2" }, + {"P2 Fire 3" , BIT_DIGITAL , TC0220IOCInputPort0 + 1, "p2 fire 3" }, + + {"Reset" , BIT_DIGITAL , &TaitoReset , "reset" }, + {"Service" , BIT_DIGITAL , TC0220IOCInputPort0 + 4, "service" }, + {"Dip 1" , BIT_DIPSWITCH , TC0220IOCDip + 0 , "dip" }, + {"Dip 2" , BIT_DIPSWITCH , TC0220IOCDip + 1 , "dip" }, +}; + +STDINPUTINFO(Spacegun) + +#undef A + +static void AquajackMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] -= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] -= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] -= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] -= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] -= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] -= 0x80; +} + +static void BsharkMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] -= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] -= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort2[0]) TC0220IOCInput[2] -= 0x01; + if (TC0220IOCInputPort2[1]) TC0220IOCInput[2] -= 0x02; + if (TC0220IOCInputPort2[2]) TC0220IOCInput[2] -= 0x04; + if (TC0220IOCInputPort2[3]) TC0220IOCInput[2] -= 0x08; + if (TC0220IOCInputPort2[4]) TC0220IOCInput[2] -= 0x10; + if (TC0220IOCInputPort2[5]) TC0220IOCInput[2] -= 0x20; + if (TC0220IOCInputPort2[6]) TC0220IOCInput[2] -= 0x40; + if (TC0220IOCInputPort2[7]) TC0220IOCInput[2] -= 0x80; +} + +static void ChasehqMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xf3; + TC0220IOCInput[1] = 0xef; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] |= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] |= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] |= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] -= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] -= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] -= 0x80; +} + +static void ContcircMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0x13; + TC0220IOCInput[1] = 0x0f; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] |= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] |= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] |= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] |= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] |= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] |= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] |= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] |= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] |= 0x80; +} + +static void DblaxleMakeInputs() +{ + // Reset Inputs + TC0510NIOInput[0] = 0xff; + TC0510NIOInput[1] = 0xff; + TC0510NIOInput[2] = 0xff; + + if (TC0510NIOInputPort0[0]) TC0510NIOInput[0] -= 0x01; + if (TC0510NIOInputPort0[1]) TC0510NIOInput[0] -= 0x02; + if (TC0510NIOInputPort0[2]) TC0510NIOInput[0] -= 0x04; + if (TC0510NIOInputPort0[3]) TC0510NIOInput[0] -= 0x08; + if (TC0510NIOInputPort0[4]) TC0510NIOInput[0] -= 0x10; + if (TC0510NIOInputPort0[5]) TC0510NIOInput[0] -= 0x20; + if (TC0510NIOInputPort0[6]) TC0510NIOInput[0] -= 0x40; + if (TC0510NIOInputPort0[7]) TC0510NIOInput[0] -= 0x80; + + if (TC0510NIOInputPort1[0]) TC0510NIOInput[1] -= 0x01; + if (TC0510NIOInputPort1[1]) TC0510NIOInput[1] -= 0x02; + if (TC0510NIOInputPort1[2]) TC0510NIOInput[1] -= 0x04; + if (TC0510NIOInputPort1[3]) TC0510NIOInput[1] -= 0x08; + if (TC0510NIOInputPort1[4]) TC0510NIOInput[1] -= 0x10; + if (TC0510NIOInputPort1[5]) TC0510NIOInput[1] -= 0x20; + if (TC0510NIOInputPort1[6]) TC0510NIOInput[1] -= 0x40; + if (TC0510NIOInputPort1[7]) TC0510NIOInput[1] -= 0x80; +} + +static void EnforceMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xf3; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] |= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] |= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] -= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] -= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] -= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] -= 0x80; +} + +static void NightstrMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] -= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] -= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort2[0]) TC0220IOCInput[2] -= 0x01; + if (TC0220IOCInputPort2[1]) TC0220IOCInput[2] -= 0x02; + if (TC0220IOCInputPort2[2]) TC0220IOCInput[2] -= 0x04; + if (TC0220IOCInputPort2[3]) TC0220IOCInput[2] -= 0x08; + if (TC0220IOCInputPort2[4]) TC0220IOCInput[2] -= 0x10; + if (TC0220IOCInputPort2[5]) TC0220IOCInput[2] -= 0x20; + if (TC0220IOCInputPort2[6]) TC0220IOCInput[2] -= 0x40; + if (TC0220IOCInputPort2[7]) TC0220IOCInput[2] -= 0x80; +} + +static void SciMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xef; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] -= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] -= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort1[0]) TC0220IOCInput[1] -= 0x01; + if (TC0220IOCInputPort1[1]) TC0220IOCInput[1] -= 0x02; + if (TC0220IOCInputPort1[2]) TC0220IOCInput[1] -= 0x04; + if (TC0220IOCInputPort1[3]) TC0220IOCInput[1] -= 0x08; + if (TC0220IOCInputPort1[4]) TC0220IOCInput[1] |= 0x10; + if (TC0220IOCInputPort1[5]) TC0220IOCInput[1] -= 0x20; + if (TC0220IOCInputPort1[6]) TC0220IOCInput[1] -= 0x40; + if (TC0220IOCInputPort1[7]) TC0220IOCInput[1] -= 0x80; +} + +static void SpacegunMakeInputs() +{ + // Reset Inputs + TC0220IOCInput[0] = 0xff; + TC0220IOCInput[1] = 0xff; + TC0220IOCInput[2] = 0xff; + + if (TC0220IOCInputPort0[0]) TC0220IOCInput[0] -= 0x01; + if (TC0220IOCInputPort0[1]) TC0220IOCInput[0] -= 0x02; + if (TC0220IOCInputPort0[2]) TC0220IOCInput[0] -= 0x04; + if (TC0220IOCInputPort0[3]) TC0220IOCInput[0] -= 0x08; + if (TC0220IOCInputPort0[4]) TC0220IOCInput[0] -= 0x10; + if (TC0220IOCInputPort0[5]) TC0220IOCInput[0] -= 0x20; + if (TC0220IOCInputPort0[6]) TC0220IOCInput[0] -= 0x40; + if (TC0220IOCInputPort0[7]) TC0220IOCInput[0] -= 0x80; + + if (TC0220IOCInputPort2[0]) TC0220IOCInput[2] -= 0x01; + if (TC0220IOCInputPort2[1]) TC0220IOCInput[2] -= 0x02; + if (TC0220IOCInputPort2[2]) TC0220IOCInput[2] -= 0x04; + if (TC0220IOCInputPort2[3]) TC0220IOCInput[2] -= 0x08; + if (TC0220IOCInputPort2[4]) TC0220IOCInput[2] -= 0x10; + if (TC0220IOCInputPort2[5]) TC0220IOCInput[2] -= 0x20; + if (TC0220IOCInputPort2[6]) TC0220IOCInput[2] -= 0x40; + if (TC0220IOCInputPort2[7]) TC0220IOCInput[2] -= 0x80; + + BurnGunMakeInputs(0, (INT16)TaitoAnalogPort0, (INT16)TaitoAnalogPort1); + BurnGunMakeInputs(1, (INT16)TaitoAnalogPort2, (INT16)TaitoAnalogPort3); +} + +static struct BurnDIPInfo AquajackDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x7f, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x80, 0x80, "Cockpit" }, + {0x0e, 0x01, 0x80, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x10, 0x00, "Off" }, + {0x0e, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x0c, 0x00, "4 Coins 1 Credit" }, + {0x0e, 0x01, 0x0c, 0x08, "3 Coins 1 Credit" }, + {0x0e, 0x01, 0x0c, 0x04, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0x03, 0x01, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0x03, 0x02, "1 Coin 4 Credits" }, + {0x0e, 0x01, 0x03, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0xc0, 0x40, "Easy" }, + {0x0f, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0f, 0x01, 0xc0, 0x80, "Hard" }, + {0x0f, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0f, 0x01, 0x30, 0x00, "30000" }, + {0x0f, 0x01, 0x30, 0x30, "50000" }, + {0x0f, 0x01, 0x30, 0x10, "80000" }, + {0x0f, 0x01, 0x30, 0x20, "100000" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x0c, 0x08, "1" }, + {0x0f, 0x01, 0x0c, 0x04, "2" }, + {0x0f, 0x01, 0x0c, 0x0c, "3" }, + {0x0f, 0x01, 0x0c, 0x00, "5" }, +}; + +STDDIPINFO(Aquajack) + +static struct BurnDIPInfo AquajackjDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0x7f, NULL }, + {0x0f, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x80, 0x80, "Cockpit" }, + {0x0e, 0x01, 0x80, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x20, 0x20, "Off" }, + {0x0e, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x10, 0x00, "Off" }, + {0x0e, 0x01, 0x10, 0x10, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x0c, 0x08, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x0c, 0x0c, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0x0c, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x0c, 0x04, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0x03, 0x02, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x03, 0x03, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0x03, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x03, 0x01, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0f, 0x01, 0xc0, 0x40, "Easy" }, + {0x0f, 0x01, 0xc0, 0xc0, "Normal" }, + {0x0f, 0x01, 0xc0, 0x80, "Hard" }, + {0x0f, 0x01, 0xc0, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Life" }, + {0x0f, 0x01, 0x30, 0x00, "30000" }, + {0x0f, 0x01, 0x30, 0x30, "50000" }, + {0x0f, 0x01, 0x30, 0x10, "80000" }, + {0x0f, 0x01, 0x30, 0x20, "100000" }, + + {0 , 0xfe, 0 , 4 , "Lives" }, + {0x0f, 0x01, 0x0c, 0x08, "1" }, + {0x0f, 0x01, 0x0c, 0x04, "2" }, + {0x0f, 0x01, 0x0c, 0x0c, "3" }, + {0x0f, 0x01, 0x0c, 0x00, "5" }, +}; + +STDDIPINFO(Aquajackj) + +static struct BurnDIPInfo BsharkDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Mirror Screen" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Speed of Sight" }, + {0x0c, 0x01, 0x0c, 0x0c, "Slow" }, + {0x0c, 0x01, 0x0c, 0x08, "Medium" }, + {0x0c, 0x01, 0x0c, 0x04, "Fast" }, + {0x0c, 0x01, 0x0c, 0x00, "Fastest" }, +}; + +STDDIPINFO(Bshark) + +static struct BurnDIPInfo BsharkjDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Mirror Screen" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Speed of Sight" }, + {0x0c, 0x01, 0x0c, 0x0c, "Slow" }, + {0x0c, 0x01, 0x0c, 0x08, "Medium" }, + {0x0c, 0x01, 0x0c, 0x04, "Fast" }, + {0x0c, 0x01, 0x0c, 0x00, "Fastest" }, +}; + +STDDIPINFO(Bsharkj) + +static struct BurnDIPInfo BsharkjjsDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Mirror Screen" }, + {0x0d, 0x01, 0x01, 0x01, "Off" }, + {0x0d, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Speed of Sight" }, + {0x0e, 0x01, 0x0c, 0x0c, "Slow" }, + {0x0e, 0x01, 0x0c, 0x08, "Medium" }, + {0x0e, 0x01, 0x0c, 0x04, "Fast" }, + {0x0e, 0x01, 0x0c, 0x00, "Fastest" }, +}; + +STDDIPINFO(Bsharkjjs) + +static struct BurnDIPInfo BsharkuDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xf7, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Mirror Screen" }, + {0x0b, 0x01, 0x01, 0x01, "Off" }, + {0x0b, 0x01, 0x01, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x0b, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "Same as Start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Speed of Sight" }, + {0x0c, 0x01, 0x0c, 0x0c, "Slow" }, + {0x0c, 0x01, 0x0c, 0x08, "Medium" }, + {0x0c, 0x01, 0x0c, 0x04, "Fast" }, + {0x0c, 0x01, 0x0c, 0x00, "Fastest" }, +}; + +STDDIPINFO(Bsharku) + +static struct BurnDIPInfo ChasehqDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0b, 0x01, 0x03, 0x03, "Upright / Steering Lock" }, + {0x0b, 0x01, 0x03, 0x02, "Upright / No Steering Lock" }, + {0x0b, 0x01, 0x03, 0x01, "Full Throttle Convert, Cockpit" }, + {0x0b, 0x01, 0x03, 0x00, "Full Throttle Convert, Deluxe" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer Setting" }, + {0x0c, 0x01, 0x0c, 0x08, "70 Seconds" }, + {0x0c, 0x01, 0x0c, 0x04, "65 Seconds" }, + {0x0c, 0x01, 0x0c, 0x0c, "60 Seconds" }, + {0x0c, 0x01, 0x0c, 0x00, "55 Seconds" }, + + {0 , 0xfe, 0 , 2 , "Turbos Stocked" }, + {0x0c, 0x01, 0x10, 0x10, "3" }, + {0x0c, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Discounted Continue Play" }, + {0x0c, 0x01, 0x20, 0x20, "Off" }, + {0x0c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Damage Cleared at Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x80, 0x00, "Off" }, + {0x0c, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Chasehq) + +static struct BurnDIPInfo ChasehqjDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xff, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 4 , "Cabinet" }, + {0x0b, 0x01, 0x03, 0x03, "Upright / Steering Lock" }, + {0x0b, 0x01, 0x03, 0x02, "Upright / No Steering Lock" }, + {0x0b, 0x01, 0x03, 0x01, "Full Throttle Convert, Cockpit" }, + {0x0b, 0x01, 0x03, 0x00, "Full Throttle Convert, Deluxe" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer Setting" }, + {0x0c, 0x01, 0x0c, 0x08, "70 Seconds" }, + {0x0c, 0x01, 0x0c, 0x04, "65 Seconds" }, + {0x0c, 0x01, 0x0c, 0x0c, "60 Seconds" }, + {0x0c, 0x01, 0x0c, 0x00, "55 Seconds" }, + + {0 , 0xfe, 0 , 2 , "Turbos Stocked" }, + {0x0c, 0x01, 0x10, 0x10, "3" }, + {0x0c, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Discounted Continue Play" }, + {0x0c, 0x01, 0x20, 0x20, "Off" }, + {0x0c, 0x01, 0x20, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Damage Cleared at Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x80, 0x00, "Off" }, + {0x0c, 0x01, 0x80, 0x80, "On" }, +}; + +STDDIPINFO(Chasehqj) + +static struct BurnDIPInfo ContcircDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x01, 0x01, "Upright" }, + {0x0e, 0x01, 0x01, 0x00, "Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x08, 0x00, "Off" }, + {0x0e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0e, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0e, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0e, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Time Difficulty" }, + {0x0f, 0x01, 0x03, 0x02, "Easy" }, + {0x0f, 0x01, 0x03, 0x03, "Normal" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Opponent Difficulty" }, + {0x0f, 0x01, 0x0c, 0x08, "Easy" }, + {0x0f, 0x01, 0x0c, 0x0c, "Normal" }, + {0x0f, 0x01, 0x0c, 0x04, "Hard" }, + {0x0f, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Steering Wheel" }, + {0x0f, 0x01, 0x10, 0x10, "Free" }, + {0x0f, 0x01, 0x10, 0x00, "Locked" }, + + {0 , 0xfe, 0 , 2 , "Enable 3D Alternate Frames" }, + {0x0f, 0x01, 0x20, 0x00, "Off" }, + {0x0f, 0x01, 0x20, 0x20, "On" }, +}; + +STDDIPINFO(Contcirc) + +static struct BurnDIPInfo ContcircuDIPList[]= +{ + // Default Values + {0x0e, 0xff, 0xff, 0xff, NULL }, + {0x0f, 0xff, 0xff, 0xdf, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0e, 0x01, 0x01, 0x01, "Upright" }, + {0x0e, 0x01, 0x01, 0x00, "Cockpit" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0e, 0x01, 0x04, 0x04, "Off" }, + {0x0e, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0e, 0x01, 0x08, 0x00, "Off" }, + {0x0e, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0e, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0e, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0e, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0e, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0e, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Time Difficulty" }, + {0x0f, 0x01, 0x03, 0x02, "Easy" }, + {0x0f, 0x01, 0x03, 0x03, "Normal" }, + {0x0f, 0x01, 0x03, 0x01, "Hard" }, + {0x0f, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Opponent Difficulty" }, + {0x0f, 0x01, 0x0c, 0x08, "Easy" }, + {0x0f, 0x01, 0x0c, 0x0c, "Normal" }, + {0x0f, 0x01, 0x0c, 0x04, "Hard" }, + {0x0f, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Steering Wheel" }, + {0x0f, 0x01, 0x10, 0x10, "Free" }, + {0x0f, 0x01, 0x10, 0x00, "Locked" }, + + {0 , 0xfe, 0 , 2 , "Enable 3D Alternate Frames" }, + {0x0f, 0x01, 0x20, 0x00, "Off" }, + {0x0f, 0x01, 0x20, 0x20, "On" }, +}; + +STDDIPINFO(Contcircu) + +static struct BurnDIPInfo DblaxleDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xfb, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Gear Shift" }, + {0x0d, 0x01, 0x02, 0x02, "Normal" }, + {0x0d, 0x01, 0x02, 0x00, "Inverted" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Multi-machine hookup" }, + {0x0e, 0x01, 0x04, 0x00, "Off" }, + {0x0e, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Player Truck" }, + {0x0e, 0x01, 0x08, 0x08, "Red" }, + {0x0e, 0x01, 0x08, 0x00, "Blue" }, + + {0 , 0xfe, 0 , 2 , "Reverse" }, + {0x0e, 0x01, 0x10, 0x10, "Normal" }, + {0x0e, 0x01, 0x10, 0x00, "Inverted" }, +}; + +STDDIPINFO(Dblaxle) + +static struct BurnDIPInfo PwheelsjDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xff, NULL }, + {0x0e, 0xff, 0xff, 0xfb, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Gear Shift" }, + {0x0d, 0x01, 0x02, 0x02, "Normal" }, + {0x0d, 0x01, 0x02, 0x00, "Inverted" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Multi-machine hookup" }, + {0x0e, 0x01, 0x04, 0x00, "Off" }, + {0x0e, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2 , "Player Truck" }, + {0x0e, 0x01, 0x08, 0x08, "Red" }, + {0x0e, 0x01, 0x08, 0x00, "Blue" }, + + {0 , 0xfe, 0 , 2 , "Reverse" }, + {0x0e, 0x01, 0x10, 0x10, "Normal" }, + {0x0e, 0x01, 0x10, 0x00, "Inverted" }, +}; + +STDDIPINFO(Pwheelsj) + +static struct BurnDIPInfo EnforceDIPList[]= +{ + // Default Values + {0x0c, 0xff, 0xff, 0xff, NULL }, + {0x0d, 0xff, 0xff, 0xef, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0c, 0x01, 0x04, 0x04, "Off" }, + {0x0c, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0c, 0x01, 0x08, 0x00, "Off" }, + {0x0c, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0c, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0c, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0c, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0c, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0c, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0c, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0c, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0c, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 2 , "Background Scenery" }, + {0x0d, 0x01, 0x10, 0x10, "Crazy Scolling" }, + {0x0d, 0x01, 0x10, 0x00, "Normal" }, +}; + +STDDIPINFO(Enforce) + +static struct BurnDIPInfo NightstrDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0b, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Shields" }, + {0x0c, 0x01, 0x0c, 0x08, "3" }, + {0x0c, 0x01, 0x0c, 0x04, "2" }, + {0x0c, 0x01, 0x0c, 0x0c, "1" }, + {0x0c, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Shields" }, + {0x0c, 0x01, 0x30, 0x00, "3" }, + {0x0c, 0x01, 0x30, 0x10, "4" }, + {0x0c, 0x01, 0x30, 0x30, "5" }, + {0x0c, 0x01, 0x30, 0x20, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Trigger Turbo" }, + {0x0c, 0x01, 0x80, 0x80, "7 shots / seconds" }, + {0x0c, 0x01, 0x80, 0x00, "10 shots / seconds" }, +}; + +STDDIPINFO(Nightstr) + +static struct BurnDIPInfo NightstrjDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0b, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Shields" }, + {0x0c, 0x01, 0x0c, 0x08, "3" }, + {0x0c, 0x01, 0x0c, 0x04, "2" }, + {0x0c, 0x01, 0x0c, 0x0c, "1" }, + {0x0c, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Shields" }, + {0x0c, 0x01, 0x30, 0x00, "3" }, + {0x0c, 0x01, 0x30, 0x10, "4" }, + {0x0c, 0x01, 0x30, 0x30, "5" }, + {0x0c, 0x01, 0x30, 0x20, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Trigger Turbo" }, + {0x0c, 0x01, 0x80, 0x80, "7 shots / seconds" }, + {0x0c, 0x01, 0x80, 0x00, "10 shots / seconds" }, +}; + +STDDIPINFO(Nightstrj) + + +static struct BurnDIPInfo NightstruDIPList[]= +{ + // Default Values + {0x0b, 0xff, 0xff, 0xfe, NULL }, + {0x0c, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0b, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0b, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0b, 0x01, 0x04, 0x04, "Off" }, + {0x0b, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0b, 0x01, 0x08, 0x00, "Off" }, + {0x0b, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0b, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x0b, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0b, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x0b, 0x01, 0xc0, 0xc0, "Same as Start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0c, 0x01, 0x03, 0x02, "Easy" }, + {0x0c, 0x01, 0x03, 0x03, "Normal" }, + {0x0c, 0x01, 0x03, 0x01, "Hard" }, + {0x0c, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Bonus Shields" }, + {0x0c, 0x01, 0x0c, 0x08, "3" }, + {0x0c, 0x01, 0x0c, 0x04, "2" }, + {0x0c, 0x01, 0x0c, 0x0c, "1" }, + {0x0c, 0x01, 0x0c, 0x00, "None" }, + + {0 , 0xfe, 0 , 4 , "Shields" }, + {0x0c, 0x01, 0x30, 0x00, "3" }, + {0x0c, 0x01, 0x30, 0x10, "4" }, + {0x0c, 0x01, 0x30, 0x30, "5" }, + {0x0c, 0x01, 0x30, 0x20, "6" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x0c, 0x01, 0x40, 0x00, "Off" }, + {0x0c, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Trigger Turbo" }, + {0x0c, 0x01, 0x80, 0x80, "7 shots / seconds" }, + {0x0c, 0x01, 0x80, 0x00, "10 shots / seconds" }, +}; + +STDDIPINFO(Nightstru) + +static struct BurnDIPInfo SciDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xfe, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0d, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x0d, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer Setting" }, + {0x0e, 0x01, 0x0c, 0x08, "70 Seconds" }, + {0x0e, 0x01, 0x0c, 0x04, "65 Seconds" }, + {0x0e, 0x01, 0x0c, 0x0c, "60 Seconds" }, + {0x0e, 0x01, 0x0c, 0x00, "55 Seconds" }, + + {0 , 0xfe, 0 , 2 , "Turbos Stocked" }, + {0x0e, 0x01, 0x10, 0x10, "3" }, + {0x0e, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Steering Radius" }, + {0x0e, 0x01, 0x20, 0x00, "270 Degree" }, + {0x0e, 0x01, 0x20, 0x20, "360 Degree" }, + + {0 , 0xfe, 0 , 2 , "Damage Cleared at Continue" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Siren Volume" }, + {0x0e, 0x01, 0x80, 0x80, "Normal" }, + {0x0e, 0x01, 0x80, 0x00, "Low" }, +}; + +STDDIPINFO(Sci) + +static struct BurnDIPInfo ScijDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xfe, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0d, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x0d, 0x01, 0x30, 0x10, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0x30, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0x30, 0x20, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0xc0, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x00, "2 Coins 3 Credits" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 2 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer Setting" }, + {0x0e, 0x01, 0x0c, 0x08, "70 Seconds" }, + {0x0e, 0x01, 0x0c, 0x04, "65 Seconds" }, + {0x0e, 0x01, 0x0c, 0x0c, "60 Seconds" }, + {0x0e, 0x01, 0x0c, 0x00, "55 Seconds" }, + + {0 , 0xfe, 0 , 2 , "Turbos Stocked" }, + {0x0e, 0x01, 0x10, 0x10, "3" }, + {0x0e, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Steering Radius" }, + {0x0e, 0x01, 0x20, 0x00, "270 Degree" }, + {0x0e, 0x01, 0x20, 0x20, "360 Degree" }, + + {0 , 0xfe, 0 , 2 , "Damage Cleared at Continue" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Siren Volume" }, + {0x0e, 0x01, 0x80, 0x80, "Normal" }, + {0x0e, 0x01, 0x80, 0x00, "Low" }, +}; + +STDDIPINFO(Scij) + +static struct BurnDIPInfo SciuDIPList[]= +{ + // Default Values + {0x0d, 0xff, 0xff, 0xfe, NULL }, + {0x0e, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Cabinet" }, + {0x0d, 0x01, 0x01, 0x01, "Cockpit" }, + {0x0d, 0x01, 0x01, 0x00, "Upright" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x0d, 0x01, 0x04, 0x04, "Off" }, + {0x0d, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x0d, 0x01, 0x08, 0x00, "Off" }, + {0x0d, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coinage" }, + {0x0d, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Price to Continue" }, + {0x0d, 0x01, 0xc0, 0x00, "3 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x40, "2 Coins 1 Credit" }, + {0x0d, 0x01, 0xc0, 0x80, "1 Coin 1 Credit" }, + {0x0d, 0x01, 0xc0, 0xc0, "Same as Start" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x0e, 0x01, 0x03, 0x02, "Easy" }, + {0x0e, 0x01, 0x03, 0x03, "Normal" }, + {0x0e, 0x01, 0x03, 0x01, "Hard" }, + {0x0e, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4 , "Timer Setting" }, + {0x0e, 0x01, 0x0c, 0x08, "70 Seconds" }, + {0x0e, 0x01, 0x0c, 0x04, "65 Seconds" }, + {0x0e, 0x01, 0x0c, 0x0c, "60 Seconds" }, + {0x0e, 0x01, 0x0c, 0x00, "55 Seconds" }, + + {0 , 0xfe, 0 , 2 , "Turbos Stocked" }, + {0x0e, 0x01, 0x10, 0x10, "3" }, + {0x0e, 0x01, 0x10, 0x00, "5" }, + + {0 , 0xfe, 0 , 2 , "Steering Radius" }, + {0x0e, 0x01, 0x20, 0x00, "270 Degree" }, + {0x0e, 0x01, 0x20, 0x20, "360 Degree" }, + + {0 , 0xfe, 0 , 2 , "Damage Cleared at Continue" }, + {0x0e, 0x01, 0x40, 0x00, "Off" }, + {0x0e, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Siren Volume" }, + {0x0e, 0x01, 0x80, 0x80, "Normal" }, + {0x0e, 0x01, 0x80, 0x00, "Low" }, +}; + +STDDIPINFO(Sciu) + +static struct BurnDIPInfo SpacegunDIPList[]= +{ + // Default Values + {0x10, 0xff, 0xff, 0xff, NULL }, + {0x11, 0xff, 0xff, 0xff, NULL }, + + // Dip 1 + {0 , 0xfe, 0 , 2 , "Always have gunsight power up" }, + {0x10, 0x01, 0x02, 0x02, "Off" }, + {0x10, 0x01, 0x02, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Service Mode" }, + {0x10, 0x01, 0x04, 0x04, "Off" }, + {0x10, 0x01, 0x04, 0x00, "On" }, + + {0 , 0xfe, 0 , 2 , "Demo Sounds" }, + {0x10, 0x01, 0x08, 0x00, "Off" }, + {0x10, 0x01, 0x08, 0x08, "On" }, + + {0 , 0xfe, 0 , 4 , "Coin A" }, + {0x10, 0x01, 0x30, 0x00, "4 Coins 1 Credit" }, + {0x10, 0x01, 0x30, 0x10, "3 Coins 1 Credit" }, + {0x10, 0x01, 0x30, 0x20, "2 Coins 1 Credit" }, + {0x10, 0x01, 0x30, 0x30, "1 Coin 1 Credit" }, + + {0 , 0xfe, 0 , 4 , "Coin B" }, + {0x10, 0x01, 0xc0, 0xc0, "1 Coin 2 Credits" }, + {0x10, 0x01, 0xc0, 0x80, "1 Coin 3 Credits" }, + {0x10, 0x01, 0xc0, 0x40, "1 Coin 4 Credits" }, + {0x10, 0x01, 0xc0, 0x00, "1 Coin 6 Credits" }, + + // Dip 2 + {0 , 0xfe, 0 , 4 , "Difficulty" }, + {0x11, 0x01, 0x03, 0x02, "Easy" }, + {0x11, 0x01, 0x03, 0x03, "Normal" }, + {0x11, 0x01, 0x03, 0x01, "Hard" }, + {0x11, 0x01, 0x03, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 2 , "Allow Continue" }, + {0x11, 0x01, 0x40, 0x00, "Off" }, + {0x11, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2 , "Disable Pedal" }, + {0x11, 0x01, 0x80, 0x80, "Off" }, + {0x11, 0x01, 0x80, 0x00, "On" }, +}; + +STDDIPINFO(Spacegun) + +static struct BurnRomInfo AquajackRomDesc[] = { + { "b77-22.ic31", 0x20000, 0x67400dde, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b77-26.ic17", 0x20000, 0xcd4d0969, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b77-24.ic69", 0x20000, 0x95e643ed, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b77-23.ic67", 0x20000, 0x395a7d1c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b77-20.ic54", 0x10000, 0x84ba54b7, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b77-05.ic105", 0x80000, 0x7238f0ff, BRF_GRA | TAITO_CHARS }, + + { "b77-04.ic16", 0x80000, 0xbed0be6c, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-03.ic15", 0x80000, 0x9a3030a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-02.ic14", 0x80000, 0xdaea0d2e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-01.ic13", 0x80000, 0xcdab000d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b77-07.ic33", 0x80000, 0x7db1fc5e, BRF_GRA | TAITO_ROAD }, + + { "b77-06.ic39", 0x80000, 0xce2aed00, BRF_GRA | TAITO_SPRITEMAP }, + + { "b77-09.ic58", 0x80000, 0x948e5ad9, BRF_SND | TAITO_YM2610A }, + + { "b77-08.ic57", 0x80000, 0x119b9485, BRF_SND | TAITO_YM2610B }, + + { "b77-17.ic1", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b77-18.ic37", 0x00100, 0x7b7d8ff4, BRF_OPT }, +}; + +STD_ROM_PICK(Aquajack) +STD_ROM_FN(Aquajack) + +static struct BurnRomInfo AquajackuRomDesc[] = { + { "b77-22.ic31", 0x20000, 0x67400dde, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b77-25.ic17", 0x20000, 0xba4a39ff, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b77-24.ic69", 0x20000, 0x95e643ed, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b77-23.ic67", 0x20000, 0x395a7d1c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b77-20.ic54", 0x10000, 0x84ba54b7, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b77-05.ic105", 0x80000, 0x7238f0ff, BRF_GRA | TAITO_CHARS }, + + { "b77-04.ic16", 0x80000, 0xbed0be6c, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-03.ic15", 0x80000, 0x9a3030a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-02.ic14", 0x80000, 0xdaea0d2e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-01.ic13", 0x80000, 0xcdab000d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b77-07.ic33", 0x80000, 0x7db1fc5e, BRF_GRA | TAITO_ROAD }, + + { "b77-06.ic39", 0x80000, 0xce2aed00, BRF_GRA | TAITO_SPRITEMAP }, + + { "b77-09.ic58", 0x80000, 0x948e5ad9, BRF_SND | TAITO_YM2610A }, + + { "b77-08.ic57", 0x80000, 0x119b9485, BRF_SND | TAITO_YM2610B }, + + { "b77-17.ic1", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b77-18.ic37", 0x00100, 0x7b7d8ff4, BRF_OPT }, +}; + +STD_ROM_PICK(Aquajacku) +STD_ROM_FN(Aquajacku) + +static struct BurnRomInfo AquajackjRomDesc[] = { + { "b77-22.ic31", 0x20000, 0x67400dde, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b77-21.ic17", 0x20000, 0x23436845, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b77-24.ic69", 0x20000, 0x95e643ed, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b77-23.ic67", 0x20000, 0x395a7d1c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b77-20.ic54", 0x10000, 0x84ba54b7, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b77-05.ic105", 0x80000, 0x7238f0ff, BRF_GRA | TAITO_CHARS }, + + { "b77-04.ic16", 0x80000, 0xbed0be6c, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-03.ic15", 0x80000, 0x9a3030a7, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-02.ic14", 0x80000, 0xdaea0d2e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b77-01.ic13", 0x80000, 0xcdab000d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b77-07.ic33", 0x80000, 0x7db1fc5e, BRF_GRA | TAITO_ROAD }, + + { "b77-06.ic39", 0x80000, 0xce2aed00, BRF_GRA | TAITO_SPRITEMAP }, + + { "b77-09.ic58", 0x80000, 0x948e5ad9, BRF_SND | TAITO_YM2610A }, + + { "b77-08.ic57", 0x80000, 0x119b9485, BRF_SND | TAITO_YM2610B }, + + { "b77-17.ic1", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b77-18.ic37", 0x00100, 0x7b7d8ff4, BRF_OPT }, +}; + +STD_ROM_PICK(Aquajackj) +STD_ROM_FN(Aquajackj) + +static struct BurnRomInfo BsharkRomDesc[] = { + { "c34_71.98", 0x20000, 0xdf1fa629, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_69.75", 0x20000, 0xa54c137a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_70.97", 0x20000, 0xd77d81e2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_68.74", 0x20000, 0x4e374ce2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c34_74.128", 0x20000, 0x6869fa99, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_72.112", 0x20000, 0xc09c0f91, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_75.129", 0x20000, 0x6ba65542, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_73.113", 0x20000, 0xf2fe62b5, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c34_05.3", 0x80000, 0x596b83da, BRF_GRA | TAITO_CHARS }, + + { "c34_04.17", 0x80000, 0x2446b0da, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_03.16", 0x80000, 0xa18eab78, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_02.15", 0x80000, 0x8488ba10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_01.14", 0x80000, 0x3ebe8c63, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c34_07.42", 0x80000, 0xedb07808, BRF_GRA | TAITO_ROAD }, + + { "c34_06.12", 0x80000, 0xd200b6eb, BRF_GRA | TAITO_SPRITEMAP }, + + { "c34_08.127", 0x80000, 0x89a30450, BRF_SND | TAITO_YM2610A }, + + { "c34_09.126", 0x80000, 0x39d12b50, BRF_SND | TAITO_YM2610B }, + + { "c34_18.22", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c34_19.72", 0x00100, 0x2ee9c404, BRF_OPT }, + { "c34_20.89", 0x00100, 0xfbf81f30, BRF_OPT }, + { "c34_21.7", 0x00400, 0x10728853, BRF_OPT }, + { "c34_22.8", 0x00400, 0x643e8bfc, BRF_OPT }, +}; + +STD_ROM_PICK(Bshark) +STD_ROM_FN(Bshark) + +static struct BurnRomInfo BsharkjRomDesc[] = { + { "c34_71.98", 0x20000, 0xdf1fa629, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_69.75", 0x20000, 0xa54c137a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_70.97", 0x20000, 0xd77d81e2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_66.74", 0x20000, 0xa0392dce, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c34_74.128", 0x20000, 0x6869fa99, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_72.112", 0x20000, 0xc09c0f91, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_75.129", 0x20000, 0x6ba65542, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_73.113", 0x20000, 0xf2fe62b5, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c34_05.3", 0x80000, 0x596b83da, BRF_GRA | TAITO_CHARS }, + + { "c34_04.17", 0x80000, 0x2446b0da, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_03.16", 0x80000, 0xa18eab78, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_02.15", 0x80000, 0x8488ba10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_01.14", 0x80000, 0x3ebe8c63, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c34_07.42", 0x80000, 0xedb07808, BRF_GRA | TAITO_ROAD }, + + { "c34_06.12", 0x80000, 0xd200b6eb, BRF_GRA | TAITO_SPRITEMAP }, + + { "c34_08.127", 0x80000, 0x89a30450, BRF_SND | TAITO_YM2610A }, + + { "c34_09.126", 0x80000, 0x39d12b50, BRF_SND | TAITO_YM2610B }, + + { "c34_18.22", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c34_19.72", 0x00100, 0x2ee9c404, BRF_OPT }, + { "c34_20.89", 0x00100, 0xfbf81f30, BRF_OPT }, + { "c34_21.7", 0x00400, 0x10728853, BRF_OPT }, + { "c34_22.8", 0x00400, 0x643e8bfc, BRF_OPT }, +}; + +STD_ROM_PICK(Bsharkj) +STD_ROM_FN(Bsharkj) + +static struct BurnRomInfo BsharkjjsRomDesc[] = { + { "c34_79.98", 0x20000, 0xbc3f2e93, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_77.75", 0x20000, 0x917916d0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_78.97", 0x20000, 0xf2fcc880, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_76.74", 0x20000, 0xde97fac0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c34_82.128", 0x20000, 0x6869fa99, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_80.112", 0x20000, 0xe1783eb4, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_83.129", 0x20000, 0xeec0b364, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_81.113", 0x20000, 0x23ce6bcf, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c34_05.3", 0x80000, 0x596b83da, BRF_GRA | TAITO_CHARS }, + + { "c34_04.17", 0x80000, 0x2446b0da, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_03.16", 0x80000, 0xa18eab78, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_02.15", 0x80000, 0x8488ba10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_01.14", 0x80000, 0x3ebe8c63, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c34_07.42", 0x80000, 0xedb07808, BRF_GRA | TAITO_ROAD }, + + { "c34_06.12", 0x80000, 0xd200b6eb, BRF_GRA | TAITO_SPRITEMAP }, + + { "c34_08.127", 0x80000, 0x89a30450, BRF_SND | TAITO_YM2610A }, + + { "c34_09.126", 0x80000, 0x39d12b50, BRF_SND | TAITO_YM2610B }, + + { "c34_18.22", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c34_19.72", 0x00100, 0x2ee9c404, BRF_OPT }, + { "c34_20.89", 0x00100, 0xfbf81f30, BRF_OPT }, + { "c34_21.7", 0x00400, 0x10728853, BRF_OPT }, + { "c34_22.8", 0x00400, 0x643e8bfc, BRF_OPT }, +}; + +STD_ROM_PICK(Bsharkjjs) +STD_ROM_FN(Bsharkjjs) + +static struct BurnRomInfo BsharkuRomDesc[] = { + { "c34_71.98", 0x20000, 0xdf1fa629, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_69.75", 0x20000, 0xa54c137a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_70.97", 0x20000, 0xd77d81e2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c34_67.74", 0x20000, 0x39307c74, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c34_74.128", 0x20000, 0x6869fa99, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_72.112", 0x20000, 0xc09c0f91, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_75.129", 0x20000, 0x6ba65542, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c34_73.113", 0x20000, 0xf2fe62b5, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c34_05.3", 0x80000, 0x596b83da, BRF_GRA | TAITO_CHARS }, + + { "c34_04.17", 0x80000, 0x2446b0da, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_03.16", 0x80000, 0xa18eab78, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_02.15", 0x80000, 0x8488ba10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c34_01.14", 0x80000, 0x3ebe8c63, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c34_07.42", 0x80000, 0xedb07808, BRF_GRA | TAITO_ROAD }, + + { "c34_06.12", 0x80000, 0xd200b6eb, BRF_GRA | TAITO_SPRITEMAP }, + + { "c34_08.127", 0x80000, 0x89a30450, BRF_SND | TAITO_YM2610A }, + + { "c34_09.126", 0x80000, 0x39d12b50, BRF_SND | TAITO_YM2610B }, + + { "c34_18.22", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c34_19.72", 0x00100, 0x2ee9c404, BRF_OPT }, + { "c34_20.89", 0x00100, 0xfbf81f30, BRF_OPT }, + { "c34_21.7", 0x00400, 0x10728853, BRF_OPT }, + { "c34_22.8", 0x00400, 0x643e8bfc, BRF_OPT }, +}; + +STD_ROM_PICK(Bsharku) +STD_ROM_FN(Bsharku) + +static struct BurnRomInfo ChasehqRomDesc[] = { + { "b52-130.36", 0x20000, 0x4e7beb46, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-136.29", 0x20000, 0x2f414df0, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-131.37", 0x20000, 0xaa945d83, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-129.30", 0x20000, 0x0eaebc08, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b52-132.39", 0x10000, 0xa2f54789, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b52-133.55", 0x10000, 0x12232f95, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b52-137.51", 0x10000, 0x37abb74a, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b52-29.27", 0x80000, 0x8366d27c, BRF_GRA | TAITO_CHARS}, + + { "b52-34.5", 0x80000, 0x7d8dce36, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-35.7", 0x80000, 0x78eeec0d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-36.9", 0x80000, 0x61e89e91, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-37.11", 0x80000, 0xf02e47b9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b52-30.4", 0x80000, 0x1b8cc647, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-31.6", 0x80000, 0xf1998e20, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-32.8", 0x80000, 0x8620780c, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-33.10", 0x80000, 0xe6f4b8c4, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b52-28.4", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "b52-38.34", 0x80000, 0x5b5bf7f6, BRF_GRA | TAITO_SPRITEMAP }, + + { "b52-115.71", 0x80000, 0x4e117e93, BRF_SND | TAITO_YM2610A }, + { "b52-114.72", 0x80000, 0x3a73d6b1, BRF_SND | TAITO_YM2610A }, + { "b52-113.73", 0x80000, 0x2c6a3a05, BRF_SND | TAITO_YM2610A }, + + { "b52-116.70", 0x80000, 0xad46983c, BRF_SND | TAITO_YM2610B }, + + { "b52-01.7", 0x00100, 0x89719d17, BRF_OPT }, + { "b52-03.135", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b52-06.24", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b52-18.93", 0x00100, 0x60bdaf1a, BRF_OPT }, + { "b52-18a", 0x00100, 0x6271be0d, BRF_OPT }, + { "b52-49.68", 0x02000, 0x60dd2ed1, BRF_OPT }, + { "b52-50.66", 0x10000, 0xc189781c, BRF_OPT }, + { "b52-51.65", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b52-126.136", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b52-127.156", 0x00400, 0x77682a4f, BRF_OPT }, + + { "pal20l8b-b52-17.ic18", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic16", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic53", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic55", 0x00144, 0x4851316d, BRF_OPT }, + { "pal16l8b-b52-19.ic33", 0x00104, 0x3ba292dc, BRF_OPT }, + { "pal16l8b-b52-20.ic35", 0x00104, 0xbd39ad73, BRF_OPT }, + { "pal16l8b-b52-21.ic51", 0x00104, 0x2fe76aa4, BRF_OPT }, + { "pal20l8b-b52-25.ic123", 0x00144, 0x372b632d, BRF_OPT }, + { "pal20l8b-b52-26.ic15", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic18", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic52", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic54", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-27.ic64", 0x00144, 0x61c2ab26, BRF_OPT }, + { "pal20l8b-b52-118.ic20", 0x00144, 0x9c5fe4af, BRF_OPT }, + { "pal20l8b-b52-119.ic21", 0x00144, 0x8b8e2106, BRF_OPT }, + { "pal16l8b-b52-120.ic56", 0x00104, 0x3e7effa0, BRF_OPT }, + { "pal20l8b-b52-121.ic57", 0x00144, 0x7056fd1d, BRF_OPT }, + { "pal16l8b-b52-122.ic124", 0x00104, 0x04c0fb04, BRF_OPT }, + { "pal16l8b-b52-123.ic125", 0x00104, 0x3865d1c8, BRF_OPT }, + { "pal16l8b-b52-124.ic180", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "pal16l8b-b52-125.ic112", 0x00104, 0x7628c557, BRF_OPT }, +}; + +STD_ROM_PICK(Chasehq) +STD_ROM_FN(Chasehq) + +static struct BurnRomInfo ChasehqjRomDesc[] = { + { "b52-140.36", 0x20000, 0xc1298a4b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-139.29", 0x20000, 0x997f732e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-131.37", 0x20000, 0xaa945d83, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-129.30", 0x20000, 0x0eaebc08, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b52-132.39", 0x10000, 0xa2f54789, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b52-133.55", 0x10000, 0x12232f95, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b52-134.51", 0x10000, 0x91faac7f, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b52-29.27", 0x80000, 0x8366d27c, BRF_GRA | TAITO_CHARS }, + + { "b52-34.5", 0x80000, 0x7d8dce36, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-35.7", 0x80000, 0x78eeec0d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-36.9", 0x80000, 0x61e89e91, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-37.11", 0x80000, 0xf02e47b9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b52-30.4", 0x80000, 0x1b8cc647, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-31.6", 0x80000, 0xf1998e20, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-32.8", 0x80000, 0x8620780c, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-33.10", 0x80000, 0xe6f4b8c4, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b52-28.4", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "b52-38.34", 0x80000, 0x5b5bf7f6, BRF_GRA | TAITO_SPRITEMAP }, + + { "b52-41.71", 0x80000, 0x8204880c, BRF_SND | TAITO_YM2610A }, + { "b52-40.72", 0x80000, 0xf0551055, BRF_SND | TAITO_YM2610A }, + { "b52-39.73", 0x80000, 0xac9cbbd3, BRF_SND | TAITO_YM2610A }, + + { "b52-42.70", 0x80000, 0x6e617df1, BRF_SND | TAITO_YM2610B }, + + { "b52-01.7", 0x00100, 0x89719d17, BRF_OPT }, + { "b52-03.135", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b52-06.24", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b52-18.93", 0x00100, 0x60bdaf1a, BRF_OPT }, + { "b52-18a", 0x00100, 0x6271be0d, BRF_OPT }, + { "b52-49.68", 0x02000, 0x60dd2ed1, BRF_OPT }, + { "b52-50.66", 0x10000, 0xc189781c, BRF_OPT }, + { "b52-51.65", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b52-126.136", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b52-127.156", 0x00400, 0x77682a4f, BRF_OPT }, + + { "pal20l8b-b52-17.ic18", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic16", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic53", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic55", 0x00144, 0x4851316d, BRF_OPT }, + { "pal16l8b-b52-19.ic33", 0x00104, 0x3ba292dc, BRF_OPT }, + { "pal16l8b-b52-20.ic35", 0x00104, 0xbd39ad73, BRF_OPT }, + { "pal16l8b-b52-21.ic51", 0x00104, 0x2fe76aa4, BRF_OPT }, + { "pal20l8b-b52-25.ic123", 0x00144, 0x372b632d, BRF_OPT }, + { "pal20l8b-b52-26.ic15", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic18", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic52", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic54", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-27.ic64", 0x00144, 0x61c2ab26, BRF_OPT }, + { "pal20l8b-b52-118.ic20", 0x00144, 0x9c5fe4af, BRF_OPT }, + { "pal20l8b-b52-119.ic21", 0x00144, 0x8b8e2106, BRF_OPT }, + { "pal16l8b-b52-120.ic56", 0x00104, 0x3e7effa0, BRF_OPT }, + { "pal20l8b-b52-121.ic57", 0x00144, 0x7056fd1d, BRF_OPT }, + { "pal16l8b-b52-122.ic124", 0x00104, 0x04c0fb04, BRF_OPT }, + { "pal16l8b-b52-123.ic125", 0x00104, 0x3865d1c8, BRF_OPT }, + { "pal16l8b-b52-124.ic180", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "pal16l8b-b52-125.ic112", 0x00104, 0x7628c557, BRF_OPT }, +}; + +STD_ROM_PICK(Chasehqj) +STD_ROM_FN(Chasehqj) + +static struct BurnRomInfo ChasehquRomDesc[] = { + { "b52-138.36", 0x20000, 0x8b71fe51, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-135.29", 0x20000, 0x5ba56a7c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-131.37", 0x20000, 0xaa945d83, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b52-129.30", 0x20000, 0x0eaebc08, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b52-132.39", 0x10000, 0xa2f54789, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b52-133.55", 0x10000, 0x12232f95, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b52-137.51", 0x10000, 0x37abb74a, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b52-29.27", 0x80000, 0x8366d27c, BRF_GRA | TAITO_CHARS}, + + { "b52-34.5", 0x80000, 0x7d8dce36, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-35.7", 0x80000, 0x78eeec0d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-36.9", 0x80000, 0x61e89e91, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b52-37.11", 0x80000, 0xf02e47b9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b52-30.4", 0x80000, 0x1b8cc647, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-31.6", 0x80000, 0xf1998e20, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-32.8", 0x80000, 0x8620780c, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b52-33.10", 0x80000, 0xe6f4b8c4, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b52-28.4", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "b52-38.34", 0x80000, 0x5b5bf7f6, BRF_GRA | TAITO_SPRITEMAP }, + + { "b52-115.71", 0x80000, 0x4e117e93, BRF_SND | TAITO_YM2610A }, + { "b52-114.72", 0x80000, 0x3a73d6b1, BRF_SND | TAITO_YM2610A }, + { "b52-113.73", 0x80000, 0x2c6a3a05, BRF_SND | TAITO_YM2610A }, + + { "b52-116.70", 0x80000, 0xad46983c, BRF_SND | TAITO_YM2610B }, + + { "b52-01.7", 0x00100, 0x89719d17, BRF_OPT }, + { "b52-03.135", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b52-06.24", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b52-18.93", 0x00100, 0x60bdaf1a, BRF_OPT }, + { "b52-18a", 0x00100, 0x6271be0d, BRF_OPT }, + { "b52-49.68", 0x02000, 0x60dd2ed1, BRF_OPT }, + { "b52-50.66", 0x10000, 0xc189781c, BRF_OPT }, + { "b52-51.65", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b52-126.136", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b52-127.156", 0x00400, 0x77682a4f, BRF_OPT }, + + { "pal20l8b-b52-17.ic18", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic16", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic53", 0x00144, 0x4851316d, BRF_OPT }, + { "pal20l8b-b52-17.ic55", 0x00144, 0x4851316d, BRF_OPT }, + { "pal16l8b-b52-19.ic33", 0x00104, 0x3ba292dc, BRF_OPT }, + { "pal16l8b-b52-20.ic35", 0x00104, 0xbd39ad73, BRF_OPT }, + { "pal16l8b-b52-21.ic51", 0x00104, 0x2fe76aa4, BRF_OPT }, + { "pal20l8b-b52-25.ic123", 0x00144, 0x372b632d, BRF_OPT }, + { "pal20l8b-b52-26.ic15", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic18", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic52", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-26.ic54", 0x00144, 0xd94f2bc2, BRF_OPT }, + { "pal20l8b-b52-27.ic64", 0x00144, 0x61c2ab26, BRF_OPT }, + { "pal20l8b-b52-118.ic20", 0x00144, 0x9c5fe4af, BRF_OPT }, + { "pal20l8b-b52-119.ic21", 0x00144, 0x8b8e2106, BRF_OPT }, + { "pal16l8b-b52-120.ic56", 0x00104, 0x3e7effa0, BRF_OPT }, + { "pal20l8b-b52-121.ic57", 0x00144, 0x7056fd1d, BRF_OPT }, + { "pal16l8b-b52-122.ic124", 0x00104, 0x04c0fb04, BRF_OPT }, + { "pal16l8b-b52-123.ic125", 0x00104, 0x3865d1c8, BRF_OPT }, + { "pal16l8b-b52-124.ic180", 0x00104, 0x00000000, BRF_OPT | BRF_NODUMP }, + { "pal16l8b-b52-125.ic112", 0x00104, 0x7628c557, BRF_OPT }, +}; + +STD_ROM_PICK(Chasehqu) +STD_ROM_FN(Chasehqu) + +static struct BurnRomInfo ContcircRomDesc[] = { + { "ic25", 0x20000, 0xf5c92e42, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ic26", 0x20000, 0xe7c1d1fa, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "ic35", 0x20000, 0x16522f2d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "cc_36.bin", 0x20000, 0xa1732ea5, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b33-30.11", 0x10000, 0xd8746234, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b33-02.57", 0x80000, 0xf6fb3ba2, BRF_GRA | TAITO_CHARS }, + + { "b33-06", 0x80000, 0x2cb40599, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-05", 0x80000, 0xbddf9eea, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-04", 0x80000, 0x8df866a2, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-03", 0x80000, 0x4f6c36d9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b33-01.3", 0x80000, 0xf11f2be8, BRF_GRA | TAITO_ROAD }, + + { "b33-07.64", 0x80000, 0x151e1f52, BRF_GRA | TAITO_SPRITEMAP }, + + { "b33-09.18", 0x80000, 0x1e6724b5, BRF_SND | TAITO_YM2610A }, + { "b33-10.17", 0x80000, 0xe9ce03ab, BRF_SND | TAITO_YM2610A }, + + { "b33-08.19", 0x80000, 0xcaa1c4c8, BRF_SND | TAITO_YM2610B }, + + { "b14-30.97", 0x10000, 0xdccb0c7f, BRF_OPT }, + { "b14-31.50", 0x02000, 0x5c6b013d, BRF_OPT }, + { "b33-17.16", 0x00100, 0x7b7d8ff4, BRF_OPT }, + { "b33-18.17", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Contcirc) +STD_ROM_FN(Contcirc) + +static struct BurnRomInfo ContcircuRomDesc[] = { + { "ic25", 0x20000, 0xf5c92e42, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ic26", 0x20000, 0xe7c1d1fa, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "ic35", 0x20000, 0x16522f2d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "ic36", 0x20000, 0xd6741e33, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b33-30.11", 0x10000, 0xd8746234, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b33-02.57", 0x80000, 0xf6fb3ba2, BRF_GRA | TAITO_CHARS }, + + { "b33-06", 0x80000, 0x2cb40599, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-05", 0x80000, 0xbddf9eea, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-04", 0x80000, 0x8df866a2, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-03", 0x80000, 0x4f6c36d9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b33-01.3", 0x80000, 0xf11f2be8, BRF_GRA | TAITO_ROAD }, + + { "b33-07.64", 0x80000, 0x151e1f52, BRF_GRA | TAITO_SPRITEMAP }, + + { "b33-09.18", 0x80000, 0x1e6724b5, BRF_SND | TAITO_YM2610A }, + { "b33-10.17", 0x80000, 0xe9ce03ab, BRF_SND | TAITO_YM2610A }, + + { "b33-08.19", 0x80000, 0xcaa1c4c8, BRF_SND | TAITO_YM2610B }, + + { "b14-30.97", 0x10000, 0xdccb0c7f, BRF_OPT }, + { "b14-31.50", 0x02000, 0x5c6b013d, BRF_OPT }, + { "b33-17.16", 0x00100, 0x7b7d8ff4, BRF_OPT }, + { "b33-18.17", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Contcircu) +STD_ROM_FN(Contcircu) + +static struct BurnRomInfo ContcircuaRomDesc[] = { + { "b33-34.ic25", 0x20000, 0xe1e016c1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b33-33.ic26", 0x20000, 0xf539d44b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "21-2.ic35", 0x20000, 0x2723f9e3, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "31-1.ic36", 0x20000, 0x438431f7, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b33-30.11", 0x10000, 0xd8746234, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b33-02.57", 0x80000, 0xf6fb3ba2, BRF_GRA | TAITO_CHARS }, + + { "b33-06", 0x80000, 0x2cb40599, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-05", 0x80000, 0xbddf9eea, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-04", 0x80000, 0x8df866a2, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b33-03", 0x80000, 0x4f6c36d9, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b33-01.3", 0x80000, 0xf11f2be8, BRF_GRA | TAITO_ROAD }, + + { "b33-07.64", 0x80000, 0x151e1f52, BRF_GRA | TAITO_SPRITEMAP }, + + { "b33-09.18", 0x80000, 0x1e6724b5, BRF_SND | TAITO_YM2610A }, + { "b33-10.17", 0x80000, 0xe9ce03ab, BRF_SND | TAITO_YM2610A }, + + { "b33-08.19", 0x80000, 0xcaa1c4c8, BRF_SND | TAITO_YM2610B }, + + { "b14-30.97", 0x10000, 0xdccb0c7f, BRF_OPT }, + { "b14-31.50", 0x02000, 0x5c6b013d, BRF_OPT }, + { "b33-17.16", 0x00100, 0x7b7d8ff4, BRF_OPT }, + { "b33-18.17", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Contcircua) +STD_ROM_FN(Contcircua) + +static struct BurnRomInfo DblaxleRomDesc[] = { + { "c78-41-1.2", 0x020000, 0xcf297fe4, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-43-1.4", 0x020000, 0x38a8bad6, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-42-1.3", 0x020000, 0x4124ab2b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-44-1.5", 0x020000, 0x50a55b6e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c78-30-1.35", 0x020000, 0x026aac18, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c78-31-1.36", 0x020000, 0x67ce23e8, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c78-34.c42", 0x020000, 0xf2186943, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c78-10.12", 0x080000, 0x44b1897c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "c78-11.11", 0x080000, 0x7db3d4a3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "c78-08.25", 0x100000, 0x6c725211, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-07.33", 0x100000, 0x9da00d5b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-06.23", 0x100000, 0x8309e91b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-05.31", 0x100000, 0x90001f68, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c78-09.12", 0x080000, 0x0dbde6f5, BRF_GRA | TAITO_ROAD }, + + { "c78-04.3", 0x080000, 0xcc1aa37c, BRF_GRA | TAITO_SPRITEMAP }, + + { "c78-12.33", 0x100000, 0xb0267404, BRF_SND | TAITO_YM2610A }, + { "c78-13.46", 0x080000, 0x1b363aa2, BRF_SND | TAITO_YM2610A }, + + { "c78-14.31", 0x080000, 0x9cad4dfb, BRF_SND | TAITO_YM2610B }, + + { "c78-25.15", 0x010000, 0x7245a6f6, BRF_OPT }, + { "c78-15.22", 0x000100, 0xfbf81f30, BRF_OPT }, + { "c78-21.74", 0x000100, 0x2926bf27, BRF_OPT }, + { "c84-10.16", 0x000400, 0x643e8bfc, BRF_OPT }, + { "c84-11.17", 0x000400, 0x10728853, BRF_OPT }, +}; + +STD_ROM_PICK(Dblaxle) +STD_ROM_FN(Dblaxle) + +static struct BurnRomInfo PwheelsjRomDesc[] = { + { "c78-26-2.2", 0x020000, 0x25c8eb2e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-28-2.4", 0x020000, 0xa9500eb1, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-27-2.3", 0x020000, 0x08d2cffb, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c78-29-2.5", 0x020000, 0xe1608004, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c78-30-1.35", 0x020000, 0x026aac18, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c78-31-1.36", 0x020000, 0x67ce23e8, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c78-32.42", 0x020000, 0x1494199c, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c78-10.12", 0x080000, 0x44b1897c, BRF_GRA | TAITO_CHARS_BYTESWAP }, + { "c78-11.11", 0x080000, 0x7db3d4a3, BRF_GRA | TAITO_CHARS_BYTESWAP }, + + { "c78-08.25", 0x100000, 0x6c725211, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-07.33", 0x100000, 0x9da00d5b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-06.23", 0x100000, 0x8309e91b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c78-05.31", 0x100000, 0x90001f68, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c78-09.12", 0x080000, 0x0dbde6f5, BRF_GRA | TAITO_ROAD }, + + { "c78-04.3", 0x080000, 0xcc1aa37c, BRF_GRA | TAITO_SPRITEMAP }, + + { "c78-01.33", 0x100000, 0x90ff1e72, BRF_SND | TAITO_YM2610A }, + { "c78-02.46", 0x080000, 0x8882d2b7, BRF_SND | TAITO_YM2610A }, + + { "c78-03.31", 0x080000, 0x9b926a2f, BRF_SND | TAITO_YM2610B }, + + { "c78-25.15", 0x010000, 0x7245a6f6, BRF_OPT }, + { "c78-15.22", 0x000100, 0xfbf81f30, BRF_OPT }, + { "c78-21.74", 0x000100, 0x2926bf27, BRF_OPT }, + { "c84-10.16", 0x000400, 0x643e8bfc, BRF_OPT }, + { "c84-11.17", 0x000400, 0x10728853, BRF_OPT }, +}; + +STD_ROM_PICK(Pwheelsj) +STD_ROM_FN(Pwheelsj) + +static struct BurnRomInfo EnforceRomDesc[] = { + { "b58-27.27", 0x20000, 0xa1aa0191, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b58-19.19", 0x20000, 0x40f43da3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b58-26.26", 0x20000, 0xe823c85c, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b58-18.18", 0x20000, 0x65328a3e, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b58-32.41", 0x10000, 0xf3fd8eca, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b58-09.13", 0x80000, 0x9ffd5b31, BRF_GRA | TAITO_CHARS }, + + { "b58-04.7", 0x80000, 0x9482f08d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b58-03.6", 0x80000, 0x158bc440, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b58-02.2", 0x80000, 0x6a6e307c, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b58-01.1", 0x80000, 0x01e9f0a8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b58-06.116", 0x80000, 0xb3495d70, BRF_GRA | TAITO_ROAD }, + + { "b58-05.71", 0x80000, 0xd1f4991b, BRF_GRA | TAITO_SPRITEMAP }, + + { "b58-07.11", 0x80000, 0xeeb5ba08, BRF_SND | TAITO_YM2610A }, + { "b58-08.12", 0x80000, 0x049243cf, BRF_SND | TAITO_YM2610A }, + + { "b58-10.14", 0x80000, 0xedce0cc1, BRF_SND | TAITO_YM2610B }, + + { "b58-26a.104", 0x10000, 0xdccb0c7f, BRF_OPT }, + { "b58-27.56", 0x02000, 0x5c6b013d, BRF_OPT }, + { "b58-23.52", 0x00100, 0x7b7d8ff4, BRF_OPT }, + { "b58-24.51", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b58-25.75", 0x00100, 0xde547342, BRF_OPT }, +}; + +STD_ROM_PICK(Enforce) +STD_ROM_FN(Enforce) + +static struct BurnRomInfo NightstrRomDesc[] = { + { "b91-45.bin", 0x20000, 0x7ad63421, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-44.bin", 0x20000, 0x4bc30adf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-43.bin", 0x20000, 0x3e6f727a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-47.bin", 0x20000, 0x9f778e03, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b91-39.bin", 0x20000, 0x725b23ae, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b91-40.bin", 0x20000, 0x81fb364d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b91-41.bin", 0x20000, 0x2694bb42, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b91-11.bin", 0x80000, 0xfff8ce31, BRF_GRA | TAITO_CHARS }, + + { "b91-04.bin", 0x80000, 0x8ca1970d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-03.bin", 0x80000, 0xcd5fed39, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-02.bin", 0x80000, 0x457c64b8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-01.bin", 0x80000, 0x3731d94f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b91-08.bin", 0x80000, 0x66f35c34, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-07.bin", 0x80000, 0x4d8ec6cf, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-06.bin", 0x80000, 0xa34dc839, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-05.bin", 0x80000, 0x5e72ac90, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b91-10.bin", 0x80000, 0x1d8f05b4, BRF_GRA | TAITO_ROAD }, + + { "b91-09.bin", 0x80000, 0x5f247ca2, BRF_GRA | TAITO_SPRITEMAP }, + + { "b91-13.bin", 0x80000, 0x8c7bf0f5, BRF_SND | TAITO_YM2610A }, + { "b91-12.bin", 0x80000, 0xda77c7af, BRF_SND | TAITO_YM2610A }, + + { "b91-14.bin", 0x80000, 0x6bc314d3, BRF_SND | TAITO_YM2610B }, + + { "b91-26.bin", 0x00400, 0x77682a4f, BRF_OPT }, + { "b91-27.bin", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b91-28.bin", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b91-29.bin", 0x02000, 0xad685be8, BRF_OPT }, + { "b91-30.bin", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b91-31.bin", 0x10000, 0xc189781c, BRF_OPT }, + { "b91-32.bin", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b91-33.bin", 0x00100, 0x89719d17, BRF_OPT }, +}; + +STD_ROM_PICK(Nightstr) +STD_ROM_FN(Nightstr) + +static struct BurnRomInfo NightstrjRomDesc[] = { + { "b91-45.bin", 0x20000, 0x7ad63421, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-44.bin", 0x20000, 0x4bc30adf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-43.bin", 0x20000, 0x3e6f727a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-42.bin", 0x20000, 0x7179ef2f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b91-39.bin", 0x20000, 0x725b23ae, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b91-40.bin", 0x20000, 0x81fb364d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b91-41.bin", 0x20000, 0x2694bb42, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b91-11.bin", 0x80000, 0xfff8ce31, BRF_GRA | TAITO_CHARS }, + + { "b91-04.bin", 0x80000, 0x8ca1970d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-03.bin", 0x80000, 0xcd5fed39, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-02.bin", 0x80000, 0x457c64b8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-01.bin", 0x80000, 0x3731d94f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b91-08.bin", 0x80000, 0x66f35c34, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-07.bin", 0x80000, 0x4d8ec6cf, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-06.bin", 0x80000, 0xa34dc839, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-05.bin", 0x80000, 0x5e72ac90, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b91-10.bin", 0x80000, 0x1d8f05b4, BRF_GRA | TAITO_ROAD }, + + { "b91-09.bin", 0x80000, 0x5f247ca2, BRF_GRA | TAITO_SPRITEMAP }, + + { "b91-13.bin", 0x80000, 0x8c7bf0f5, BRF_SND | TAITO_YM2610A }, + { "b91-12.bin", 0x80000, 0xda77c7af, BRF_SND | TAITO_YM2610A }, + + { "b91-14.bin", 0x80000, 0x6bc314d3, BRF_SND | TAITO_YM2610B }, + + { "b91-26.bin", 0x00400, 0x77682a4f, BRF_OPT }, + { "b91-27.bin", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b91-28.bin", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b91-29.bin", 0x02000, 0xad685be8, BRF_OPT }, + { "b91-30.bin", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b91-31.bin", 0x10000, 0xc189781c, BRF_OPT }, + { "b91-32.bin", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b91-33.bin", 0x00100, 0x89719d17, BRF_OPT }, +}; + +STD_ROM_PICK(Nightstrj) +STD_ROM_FN(Nightstrj) + +static struct BurnRomInfo NightstruRomDesc[] = { + { "b91-45.bin", 0x20000, 0x7ad63421, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-44.bin", 0x20000, 0x4bc30adf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-43.bin", 0x20000, 0x3e6f727a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "b91-46.bin", 0x20000, 0xe870be95, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "b91-39.bin", 0x20000, 0x725b23ae, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "b91-40.bin", 0x20000, 0x81fb364d, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "b91-41.bin", 0x20000, 0x2694bb42, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "b91-11.bin", 0x80000, 0xfff8ce31, BRF_GRA | TAITO_CHARS }, + + { "b91-04.bin", 0x80000, 0x8ca1970d, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-03.bin", 0x80000, 0xcd5fed39, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-02.bin", 0x80000, 0x457c64b8, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "b91-01.bin", 0x80000, 0x3731d94f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "b91-08.bin", 0x80000, 0x66f35c34, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-07.bin", 0x80000, 0x4d8ec6cf, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-06.bin", 0x80000, 0xa34dc839, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + { "b91-05.bin", 0x80000, 0x5e72ac90, BRF_GRA | TAITO_SPRITESB_BYTESWAP32 }, + + { "b91-10.bin", 0x80000, 0x1d8f05b4, BRF_GRA | TAITO_ROAD }, + + { "b91-09.bin", 0x80000, 0x5f247ca2, BRF_GRA | TAITO_SPRITEMAP }, + + { "b91-13.bin", 0x80000, 0x8c7bf0f5, BRF_SND | TAITO_YM2610A }, + { "b91-12.bin", 0x80000, 0xda77c7af, BRF_SND | TAITO_YM2610A }, + + { "b91-14.bin", 0x80000, 0x6bc314d3, BRF_SND | TAITO_YM2610B }, + + { "b91-26.bin", 0x00400, 0x77682a4f, BRF_OPT }, + { "b91-27.bin", 0x00400, 0xa3f8490d, BRF_OPT }, + { "b91-28.bin", 0x00400, 0xfa2f840e, BRF_OPT }, + { "b91-29.bin", 0x02000, 0xad685be8, BRF_OPT }, + { "b91-30.bin", 0x10000, 0x30cc1f79, BRF_OPT }, + { "b91-31.bin", 0x10000, 0xc189781c, BRF_OPT }, + { "b91-32.bin", 0x00100, 0xfbf81f30, BRF_OPT }, + { "b91-33.bin", 0x00100, 0x89719d17, BRF_OPT }, +}; + +STD_ROM_PICK(Nightstru) +STD_ROM_FN(Nightstru) + +static struct BurnRomInfo SciRomDesc[] = { + { "c09-37.43", 0x20000, 0x0fecea17, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-38.40", 0x20000, 0xe46ebd9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-42.38", 0x20000, 0xf4404f87, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-39.41", 0x20000, 0xde87bcb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c09-33.6", 0x10000, 0xcf4e6c5b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c09-32.5", 0x10000, 0xa4713719, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c09-34.31", 0x20000, 0xa21b3151, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c09-05.16", 0x80000, 0x890b38f0, BRF_GRA | TAITO_CHARS }, + + { "c09-04.52", 0x80000, 0x2cbb3c9b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-02.53", 0x80000, 0xa83a0389, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-03.54", 0x80000, 0xa31d0e80, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-01.55", 0x80000, 0x64bfea10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c09-07.15", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "c09-06.37", 0x80000, 0x12df6d7b, BRF_GRA | TAITO_SPRITEMAP }, + + { "c09-14.42", 0x80000, 0xad78bf46, BRF_SND | TAITO_YM2610A }, + { "c09-13.43", 0x80000, 0xd57c41d3, BRF_SND | TAITO_YM2610A }, + { "c09-12.44", 0x80000, 0x56c99fa5, BRF_SND | TAITO_YM2610A }, + + { "c09-15.29", 0x80000, 0xe63b9095, BRF_SND | TAITO_YM2610B }, + + { "c09-16.17", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c09-20.71", 0x00100, 0xcd8ffd80, BRF_OPT }, + { "c09-23.14", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Sci) +STD_ROM_FN(Sci) + +static struct BurnRomInfo SciaRomDesc[] = { + { "c09-28.43", 0x20000, 0x630dbaad, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-30.40", 0x20000, 0x68b1a97d, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-36.38", 0x20000, 0x59e47cba, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-31.41", 0x20000, 0x962b1fbf, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c09-33.6", 0x10000, 0xcf4e6c5b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c09-32.5", 0x10000, 0xa4713719, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c09-34.31", 0x20000, 0xa21b3151, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c09-05.16", 0x80000, 0x890b38f0, BRF_GRA | TAITO_CHARS }, + + { "c09-04.52", 0x80000, 0x2cbb3c9b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-02.53", 0x80000, 0xa83a0389, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-03.54", 0x80000, 0xa31d0e80, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-01.55", 0x80000, 0x64bfea10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c09-07.15", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "c09-06.37", 0x80000, 0x12df6d7b, BRF_GRA | TAITO_SPRITEMAP }, + + { "c09-14.42", 0x80000, 0xad78bf46, BRF_SND | TAITO_YM2610A }, + { "c09-13.43", 0x80000, 0xd57c41d3, BRF_SND | TAITO_YM2610A }, + { "c09-12.44", 0x80000, 0x56c99fa5, BRF_SND | TAITO_YM2610A }, + + { "c09-15.29", 0x80000, 0xe63b9095, BRF_SND | TAITO_YM2610B }, + + { "c09-16.17", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c09-20.71", 0x00100, 0xcd8ffd80, BRF_OPT }, + { "c09-23.14", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Scia) +STD_ROM_FN(Scia) + +static struct BurnRomInfo ScijRomDesc[] = { + { "c09-37.43", 0x20000, 0x0fecea17, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-38.40", 0x20000, 0xe46ebd9b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-40.38", 0x20000, 0x1a4e2eab, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-39.41", 0x20000, 0xde87bcb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c09-33.6", 0x10000, 0xcf4e6c5b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c09-32.5", 0x10000, 0xa4713719, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c09-27.31", 0x20000, 0xcd161dca, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c09-05.16", 0x80000, 0x890b38f0, BRF_GRA | TAITO_CHARS }, + + { "c09-04.52", 0x80000, 0x2cbb3c9b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-02.53", 0x80000, 0xa83a0389, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-03.54", 0x80000, 0xa31d0e80, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-01.55", 0x80000, 0x64bfea10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c09-07.15", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "c09-06.37", 0x80000, 0x12df6d7b, BRF_GRA | TAITO_SPRITEMAP }, + + { "c09-10.42", 0x80000, 0xad78bf46, BRF_SND | TAITO_YM2610A }, + { "c09-09.43", 0x80000, 0x6a655c00, BRF_SND | TAITO_YM2610A }, + { "c09-08.44", 0x80000, 0x7ddfc316, BRF_SND | TAITO_YM2610A }, + + { "c09-11.29", 0x80000, 0x6b1a11e1, BRF_SND | TAITO_YM2610B }, + + { "c09-16.17", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c09-20.71", 0x00100, 0xcd8ffd80, BRF_OPT }, + { "c09-23.14", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Scij) +STD_ROM_FN(Scij) + +static struct BurnRomInfo SciuRomDesc[] = { + { "c09-43.43", 0x20000, 0x20a9343e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-44.40", 0x20000, 0x7524338a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-41.38", 0x20000, 0x83477f11, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c09-39.41", 0x20000, 0xde87bcb9, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c09-33.6", 0x10000, 0xcf4e6c5b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c09-32.5", 0x10000, 0xa4713719, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c09-34.31", 0x20000, 0xa21b3151, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c09-05.16", 0x80000, 0x890b38f0, BRF_GRA | TAITO_CHARS }, + + { "c09-04.52", 0x80000, 0x2cbb3c9b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-02.53", 0x80000, 0xa83a0389, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-03.54", 0x80000, 0xa31d0e80, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-01.55", 0x80000, 0x64bfea10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c09-07.15", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "c09-06.37", 0x80000, 0x12df6d7b, BRF_GRA | TAITO_SPRITEMAP }, + + { "c09-14.42", 0x80000, 0xad78bf46, BRF_SND | TAITO_YM2610A }, + { "c09-13.43", 0x80000, 0xd57c41d3, BRF_SND | TAITO_YM2610A }, + { "c09-12.44", 0x80000, 0x56c99fa5, BRF_SND | TAITO_YM2610A }, + + { "c09-15.29", 0x80000, 0xe63b9095, BRF_SND | TAITO_YM2610B }, + + { "c09-16.17", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c09-20.71", 0x00100, 0xcd8ffd80, BRF_OPT }, + { "c09-23.14", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Sciu) +STD_ROM_FN(Sciu) + +static struct BurnRomInfo ScinegroRomDesc[] = { + { "ic37.37", 0x20000, 0x33fb159c, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ic40.38", 0x20000, 0x657df3f2, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ic38.42", 0x20000, 0x0a09b90b, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "ic41.39", 0x20000, 0x43167b2a, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c09-33.6", 0x10000, 0xcf4e6c5b, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c09-32.5", 0x10000, 0xa4713719, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c09-27.31", 0x20000, 0xcd161dca, BRF_ESS | BRF_PRG | TAITO_Z80ROM1 }, + + { "c09-05.16", 0x80000, 0x890b38f0, BRF_GRA | TAITO_CHARS }, + + { "c09-04.52", 0x80000, 0x2cbb3c9b, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-02.53", 0x80000, 0xa83a0389, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-03.54", 0x80000, 0xa31d0e80, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c09-01.55", 0x80000, 0x64bfea10, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c09-07.15", 0x80000, 0x963bc82b, BRF_GRA | TAITO_ROAD }, + + { "c09-06.37", 0x80000, 0x12df6d7b, BRF_GRA | TAITO_SPRITEMAP }, + + { "c09-10.42", 0x80000, 0xad78bf46, BRF_SND | TAITO_YM2610A }, + { "c09-09.43", 0x80000, 0x6a655c00, BRF_SND | TAITO_YM2610A }, + { "c09-08.44", 0x80000, 0x7ddfc316, BRF_SND | TAITO_YM2610A }, + + { "c09-11.29", 0x80000, 0x6b1a11e1, BRF_SND | TAITO_YM2610B }, + + { "c09-16.17", 0x10000, 0x7245a6f6, BRF_OPT }, + { "c09-20.71", 0x00100, 0xcd8ffd80, BRF_OPT }, + { "c09-23.14", 0x00100, 0xfbf81f30, BRF_OPT }, +}; + +STD_ROM_PICK(Scinegro) +STD_ROM_FN(Scinegro) + +static struct BurnRomInfo SpacegunRomDesc[] = { + { "c57-18.62", 0x020000, 0x19d7d52e, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c57-20.74", 0x020000, 0x2e58253f, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c57-17.59", 0x020000, 0xe197edb8, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + { "c57-22.73", 0x020000, 0x5855fde3, BRF_ESS | BRF_PRG | TAITO_68KROM1_BYTESWAP }, + + { "c57-15.27", 0x020000, 0xb36eb8f1, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + { "c57-16.29", 0x020000, 0xbfb5d1e7, BRF_ESS | BRF_PRG | TAITO_68KROM2_BYTESWAP }, + + { "c57-06.52", 0x080000, 0x4ebadd5b, BRF_GRA | TAITO_CHARS }, + + { "c57-01.25", 0x100000, 0xf901b04e, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c57-02.24", 0x100000, 0x21ee4633, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c57-03.12", 0x100000, 0xfafca86f, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + { "c57-04.11", 0x100000, 0xa9787090, BRF_GRA | TAITO_SPRITESA_BYTESWAP32 }, + + { "c57-05.36", 0x080000, 0x6a70eb2e, BRF_GRA | TAITO_SPRITEMAP }, + + { "c57-07.76", 0x080000, 0xad653dc1, BRF_SND | TAITO_YM2610A }, + + { "c57-08.75", 0x080000, 0x22593550, BRF_SND | TAITO_YM2610B }, + + { "pal16l8-c57-09.9", 0x000104, 0xea93161e, BRF_OPT }, + { "pal20l8-c57-10.47", 0x000144, 0x3ee56888, BRF_OPT }, + { "pal16l8-c57-11.48", 0x000104, 0x6bb4372e, BRF_OPT }, + { "pal20l8-c57-12.61", 0x000144, 0xdebddb13, BRF_OPT }, + { "pal16l8-c57-13.72", 0x000104, 0x1369f23e, BRF_OPT }, + { "pal16r4-c57-14.96", 0x000104, 0x75e1bf61, BRF_OPT }, + +}; + +STD_ROM_PICK(Spacegun) +STD_ROM_FN(Spacegun) + +static INT32 MemIndex() +{ + UINT8 *Next; Next = TaitoMem; + + Taito68KRom1 = Next; Next += Taito68KRom1Size; + Taito68KRom2 = Next; Next += Taito68KRom2Size; + TaitoZ80Rom1 = Next; Next += TaitoZ80Rom1Size; + TaitoSpriteMapRom = Next; Next += TaitoSpriteMapRomSize; + TaitoYM2610ARom = Next; Next += TaitoYM2610ARomSize; + TaitoYM2610BRom = Next; Next += TaitoYM2610BRomSize; + + TaitoRamStart = Next; + + Taito68KRam1 = Next; Next += 0x10000; + Taito68KRam2 = Next; Next += 0x08000; + TaitoSharedRam = Next; Next += 0x10000; + TaitoZ80Ram1 = Next; Next += 0x02000; + TaitoSpriteRam = Next; Next += 0x04000; + TaitoPaletteRam = Next; Next += 0x02000; + + TaitoRamEnd = Next; + + TaitoChars = Next; Next += TaitoNumChar * TaitoCharWidth * TaitoCharHeight; + TaitoSpritesA = Next; Next += TaitoNumSpriteA * TaitoSpriteAWidth * TaitoSpriteAHeight; + TaitoSpritesB = Next; Next += TaitoNumSpriteB * TaitoSpriteBWidth * TaitoSpriteBHeight; + TaitoPalette = (UINT32*)Next; Next += 0x01000 * sizeof(UINT32); + + TaitoMemEnd = Next; + + return 0; +} + +static INT32 TaitoZDoReset() +{ + TaitoDoReset(); + + SciSpriteFrame = 0; + OldSteer = 0; + + return 0; +} + +static void TaitoZCpuAReset(UINT16 d) +{ + TaitoCpuACtrl = d; + if (!(TaitoCpuACtrl & 1)) { + SekClose(); + SekOpen(1); + SekReset(); + SekClose(); + SekOpen(0); + } +} + +void __fastcall Aquajack68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0xa00000, 0xa0ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +void __fastcall Aquajack68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0xa00000, 0xa0ffff) + TC0100SCN0CtrlWordWrite_Map(0xa20000) + + switch (a) { + case 0x200000: { + TaitoZCpuAReset(d); + return; + } + + case 0x300000: + case 0x300002: { + TC0110PCRStep1WordWrite(0, (a - 0x300000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Aquajack68K2ReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + + switch (a) { + case 0x300003: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +UINT16 __fastcall Aquajack68K2ReadWord(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + + switch (a) { + case 0x900000: + case 0x900002: + case 0x900004: + case 0x900006: { + // nop + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Aquajack68K2WriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + + switch (a) { + case 0x300000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0x300002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0x900000: + case 0x900002: + case 0x900004: + case 0x900006: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +static UINT8 BsharkStickRead(INT32 Offset) +{ + switch (Offset) { + case 0x00: { + INT32 Temp = (TaitoAnalogPort0 >> 4) & 0xfff; + Temp = 0xfff - Temp; + Temp += 1; + if (Temp == 0x1000) Temp = 0; + return Temp; + } + + case 0x01: { + return 0xff; + } + + case 0x02: { + return TaitoAnalogPort1 >> 4; + } + + case 0x03: { + return 0xff; + } + } + + return 0; +} + +UINT8 __fastcall Bshark68K1ReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x400000) + + switch (a) { + case 0x800001: + case 0x800003: + case 0x800005: + case 0x800007: { + return BsharkStickRead((a - 0x800000) >> 1); + } + + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Bshark68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0ByteWrite_Map(0xd00000, 0xd0ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +void __fastcall Bshark68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0WordWrite_Map(0xd00000, 0xd0ffff) + TC0100SCN0CtrlWordWrite_Map(0xd20000) + + switch (a) { + case 0x600000: { + TaitoZCpuAReset(d); + return; + } + + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: { + nTaitoCyclesDone[0] += SekRun(10000); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT16 __fastcall Bshark68K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x40000a: { + // ??? + return 0; + } + + case 0x600000: { + return BurnYM2610Read(0); + } + + case 0x600004: { + return BurnYM2610Read(2); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Bshark68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x400000: + case 0x400002: + case 0x400004: + case 0x400006: + case 0x400008: { + // nop + return; + } + + case 0x600000: { + BurnYM2610Write(0, d & 0xff); + return; + } + + case 0x600002: { + BurnYM2610Write(1, d & 0xff); + return; + } + + case 0x600004: { + BurnYM2610Write(2, d & 0xff); + return; + } + + case 0x600006: { + BurnYM2610Write(3, d & 0xff); + return; + } + + case 0x60000c: + case 0x60000e: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +static UINT8 ChasehqInputBypassRead() +{ + UINT8 Port = TC0220IOCPortRead(); + + INT32 Steer = (TaitoAnalogPort0 >> 4); + + switch (Port) { + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: { + return 0xff; + } + + case 0x0c: { + return Steer & 0xff; + } + + case 0x0d: { + return Steer >> 8; + } + + default: { + return TC0220IOCPortRegRead(); + } + } +} + +UINT8 __fastcall Chasehq68K1ReadByte(UINT32 a) +{ + switch (a) { + case 0x400001: { + return ChasehqInputBypassRead(); + } + + case 0x820003: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Chasehq68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0xc00000, 0xc0ffff) + + switch (a) { + case 0x400001: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x400003: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + case 0x800001: { + TaitoZCpuAReset(d); + return; + } + + case 0x820001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x820003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Chasehq68K1ReadWord(UINT32 a) +{ + switch (a) { + case 0x400002: { + return TC0220IOCHalfWordPortRead(); + } + + case 0xa00002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Chasehq68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0xc00000, 0xc0ffff) + TC0100SCN0CtrlWordWrite_Map(0xc20000) + + switch (a) { + case 0x400000: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x400002: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + case 0xa00000: + case 0xa00002: { + TC0110PCRStep1WordWrite(0, (a - 0xa00000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +static UINT8 ContcircInputBypassRead() +{ + UINT8 Port = TC0220IOCPortRead(); + + INT32 Steer = (TaitoAnalogPort0 >> 4) & 0xfff; + Steer = 0xfff - Steer; + if (Steer == 0xfff) Steer = 0; + if (Steer > 0x5f && Steer < 0x80) Steer = 0x5f; + if (Steer > 0xf7f && Steer < 0xfa0) Steer = 0xfa0; + if (Steer > 0xf7f) Steer |= 0xf000; + + switch (Port) { + case 0x08: { + return Steer & 0xff; + } + + case 0x09: { + return Steer >> 8; + } + + default: { + return TC0220IOCPortRegRead(); + } + } +} + +void __fastcall Contcirc68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x200000, 0x20ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +void __fastcall Contcirc68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x200000, 0x20ffff) + TC0100SCN0CtrlWordWrite_Map(0x220000) + + switch (a) { + case 0x090000: { + TaitoRoadPalBank = (d & 0xc0) >> 6; + TaitoZCpuAReset(d); + return; + } + + case 0x100000: + case 0x100002: { + TC0110PCRStep1RBSwapWordWrite(0, (a - 0x100000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Contcirc68K2ReadByte(UINT32 a) +{ + switch (a) { + case 0x100001: { + return ContcircInputBypassRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Contcirc68K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x100001: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Contcirc68K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x100000: { + return ContcircInputBypassRead(); + } + + case 0x100002: { + return TC0220IOCHalfWordPortRead(); + } + + case 0x200002: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Contcirc68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x100000: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x100002: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + case 0x200000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0x200002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +static UINT16 DblaxleSteerRead(INT32 Offset) +{ + int Steer = TaitoAnalogPort0 >> 5; + if (Steer > 0x3f) Steer |= 0xf800; + + switch (Offset) { + case 0x04: { + return Steer >> 8; + } + + case 0x05: { + return Steer & 0xff; + } + } + + return 0x00; +} + +UINT8 __fastcall Dblaxle68K1ReadByte(UINT32 a) +{ + TC0510NIOHalfWordSwapRead_Map(0x400000) + + switch (a) { + case 0x620003: { + return TC0140SYTCommRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dblaxle68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0510NIOHalfWordSwapWrite_Map(0x400000) + + switch (a) { + case 0x600001: { + TaitoZCpuAReset(d); + return; + } + + case 0x620001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x620003: { + TC0140SYTCommWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Dblaxle68K1ReadWord(UINT32 a) +{ + TC0510NIOHalfWordSwapRead_Map(0x400000) + + switch (a) { + case 0x400018: + case 0x40001a: { + return DblaxleSteerRead((a - 0x400010) >> 1); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Dblaxle68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0510NIOHalfWordSwapWrite_Map(0x400000) + TC0480SCPCtrlWordWrite_Map(0xa30000) + + switch (a) { + case 0xc08000: { + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +void __fastcall Enforce68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x600000, 0x60ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Enforce68K1ReadWord(UINT32 a) +{ + switch (a) { + case 0x500002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Enforce68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x600000, 0x60ffff) + TC0100SCN0CtrlWordWrite_Map(0x620000) + + switch (a) { + case 0x200000: { + TaitoZCpuAReset(d); + return; + } + + case 0x500000: + case 0x500002: { + TC0110PCRStep1RBSwapWordWrite(0, (a - 0x500000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Enforce68K2ReadByte(UINT32 a) +{ + switch (a) { + case 0x300001: { + return TC0220IOCPortRegRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Enforce68K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x300001: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Enforce68K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x200002: { + return TC0140SYTCommRead(); + } + + case 0x300000: { + return TC0220IOCPortRegRead(); + } + + case 0x300002: { + return TC0220IOCHalfWordPortRead(); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Enforce68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x200000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0x200002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0x300000: { + TC0220IOCHalfWordPortRegWrite(d); + return; + } + + case 0x300002: { + TC0220IOCHalfWordPortWrite(d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +static const UINT8 nightstr_stick[128]= +{ + 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, + 0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, + 0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7, + 0xe8,0x00,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25, + 0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35, + 0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45, + 0x46,0x47,0x48,0x49,0xb8 +}; + +static UINT8 NightstrStickRead(INT32 Offset) +{ + switch (Offset) { + case 0x00: { + UINT8 Temp = 0x7f + (TaitoAnalogPort0 >> 4); + if (Temp < 0x01) Temp = 0x01; + if (Temp > 0xfe) Temp = 0xfe; + return nightstr_stick[(Temp * 0x64) / 0x100]; + } + + case 0x01: { + UINT8 Temp = 0x7f - (TaitoAnalogPort1 >> 4); + if (Temp < 0x01) Temp = 0x01; + if (Temp > 0xfe) Temp = 0xfe; + return nightstr_stick[(Temp * 0x64) / 0x100]; + } + + case 0x02: { + return 0xff; + } + + case 0x03: { + return 0xff; + } + } + + return 0xff; +} + +UINT8 __fastcall Nightstr68K1ReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x400000) + + switch (a) { + case 0xe40001: + case 0xe40003: + case 0xe40005: + case 0xe40007: { + return NightstrStickRead((a - 0xe40000) >> 1); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Nightstr68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0ByteWrite_Map(0xc00000, 0xc0ffff) + + switch (a) { + case 0xe00000: + case 0xe00008: + case 0xe00010: { + // nop + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Nightstr68K1ReadWord(UINT32 a) +{ + switch (a) { + case 0x820002: { + return TC0140SYTCommRead(); + } + + case 0xa00002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Nightstr68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0220IOCHalfWordWrite_Map(0x400000) + TC0100SCN0WordWrite_Map(0xc00000, 0xc0ffff) + TC0100SCN0CtrlWordWrite_Map(0xc20000) + + switch (a) { + case 0x800000: { + TaitoZCpuAReset(d); + return; + } + + case 0x820000: { + TC0140SYTPortWrite(d & 0xff); + return; + } + + case 0x820002: { + TC0140SYTCommWrite(d & 0xff); + return; + } + + case 0xa00000: + case 0xa00002: { + TC0110PCRStep1WordWrite(0, (a - 0xa00000) >> 1, d); + return; + } + + case 0xe00000: + case 0xe00008: + case 0xe00010: { + // nop + return; + } + + case 0xe40000: + case 0xe40002: + case 0xe40004: + case 0xe40006: + case 0xe40008: + case 0xe4000a: + case 0xe4000c: + case 0xe4000e: { + nTaitoCyclesDone[0] += SekRun(10000); + SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +static UINT8 SciSteerRead(INT32 Offset) +{ + INT32 Steer = TaitoAnalogPort0 >> 4; + if (Steer > 0x5f && Steer < 0x80) Steer = 0x5f; + if (Steer > 0xf80 && Steer < 0xfa0) Steer = 0xfa0; + if ((OldSteer < Steer) && (Steer > 0xfc0)) Steer = 0; + OldSteer = Steer; + + switch (Offset) { + case 0x04: { + return Steer & 0xff; + } + + case 0x05: { + return (Steer & 0xff00) >> 8; + } + } + + return 0xff; +} + +UINT8 __fastcall Sci68K1ReadByte(UINT32 a) +{ + TC0220IOCHalfWordRead_Map(0x200000) + + switch (a) { + case 0x200019: + case 0x20001b: { + return SciSteerRead((a - 0x200010) >> 1); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Sci68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0220IOCHalfWordWrite_Map(0x200000) + TC0100SCN0ByteWrite_Map(0xa00000, 0xa0ffff) + + switch (a) { + case 0x400001: { + TaitoZCpuAReset(d); + return; + } + + case 0x420001: { + TC0140SYTPortWrite(d); + return; + } + + case 0x420003: { + TC0140SYTCommWrite(d); + return; + } + + case 0xc08000: { + SciSpriteFrame = d; + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +void __fastcall Sci68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0xa00000, 0xa0ffff) + TC0100SCN0CtrlWordWrite_Map(0xa20000) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +static const UINT8 spacegun_default_eeprom[128]= +{ + 0x00,0x00,0x00,0xff,0x00,0x01,0x41,0x41,0x00,0x00,0x00,0xff,0x00,0x00,0xf0,0xf0, + 0x00,0x00,0x00,0xff,0x00,0x01,0x41,0x41,0x00,0x00,0x00,0xff,0x00,0x00,0xf0,0xf0, + 0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x01,0x40,0x00,0x00,0x00,0xf0,0x00, + 0x00,0x01,0x42,0x85,0x00,0x00,0xf1,0xe3,0x00,0x01,0x40,0x00,0x00,0x00,0xf0,0x00, + 0x00,0x01,0x42,0x85,0x00,0x00,0xf1,0xe3,0xcc,0xcb,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +static const eeprom_interface spacegun_eeprom_intf = +{ + 6, /* address bits */ + 16, /* data bits */ + "0110", /* read command */ + "0101", /* write command */ + "0111", /* erase command */ + "0100000000", /* lock command */ + "0100111111", /* unlock command */ + 0, /* multi-read disabled */ + 1 /* reset delay */ +}; + +static UINT8 SpacegunInputBypassRead(INT32 Offset) +{ + switch (Offset) { + case 0x03: { + return (EEPROMRead() & 1) << 7; + } + + default: { + return TC0220IOCRead(Offset); + } + } + + return 0; +} + +static void SpacegunInputBypassWrite(INT32 Offset, UINT16 Data) +{ + switch (Offset) { + case 0x03: { + EEPROMWrite(Data & 0x20, Data & 0x10, Data & 0x40); + return; + } + + default: { + TC0220IOCWrite(Offset, Data & 0xff); + } + } +} + +void __fastcall Spacegun68K1WriteByte(UINT32 a, UINT8 d) +{ + TC0100SCN0ByteWrite_Map(0x900000, 0x90ffff) + + switch (a) { + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Spacegun68K1ReadWord(UINT32 a) +{ + switch (a) { + case 0xb00002: { + return TC0110PCRWordRead(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Spacegun68K1WriteWord(UINT32 a, UINT16 d) +{ + TC0100SCN0WordWrite_Map(0x900000, 0x90ffff) + TC0100SCN0CtrlWordWrite_Map(0x920000) + + switch (a) { + case 0xb00000: + case 0xb00002: { + TC0110PCRStep1RBSwapWordWrite(0, (a - 0xb00000) >> 1, d); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #1 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall Spacegun68K2ReadByte(UINT32 a) +{ + switch (a) { + case 0xc0000d: { + // nop + return 0; + } + + case 0xf00001: { + return ~BurnGunReturnX(0); + } + + case 0xf00003: { + return BurnGunReturnY(0); + } + + case 0xf00005: { + return ~BurnGunReturnX(1); + } + + case 0xf00007: { + return BurnGunReturnY(1); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read byte => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Spacegun68K2WriteByte(UINT32 a, UINT8 d) +{ + switch (a) { + case 0x800008: { + SpacegunInputBypassWrite((a - 0x800000) >> 1, d); + return; + } + + case 0xc0000d: { + // nop + return; + } + + case 0xe00001: { + // ??? + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write byte => %06X, %02X\n"), a, d); + } + } +} + +UINT16 __fastcall Spacegun68K2ReadWord(UINT32 a) +{ + switch (a) { + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: + case 0x800008: + case 0x80000a: + case 0x80000c: + case 0x80000e: { + return SpacegunInputBypassRead((a - 0x800000) >> 1); + } + + case 0xc00000: { + return BurnYM2610Read(0); + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Read word => %06X\n"), a); + } + } + + return 0; +} + +void __fastcall Spacegun68K2WriteWord(UINT32 a, UINT16 d) +{ + switch (a) { + case 0x800000: + case 0x800002: + case 0x800004: + case 0x800006: + case 0x800008: + case 0x80000a: + case 0x80000c: + case 0x80000e: { + SpacegunInputBypassWrite((a - 0x800000) >> 1, d); + return; + } + + case 0xc00000: { + BurnYM2610Write(0, d & 0xff); + return; + } + + case 0xc00002: { + BurnYM2610Write(1, d & 0xff); + return; + } + + case 0xc00004: { + BurnYM2610Write(2, d & 0xff); + return; + } + + case 0xc00006: { + BurnYM2610Write(3, d & 0xff); + return; + } + + case 0xc20000: + case 0xc20002: + case 0xc20004: + case 0xc20006: { + // ??? + return; + } + + case 0xf00000: + case 0xf00002: + case 0xf00004: + case 0xf00006: { + nTaitoCyclesDone[1] += SekRun(10000); + SekSetIRQLine(5, SEK_IRQSTATUS_AUTO); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("68K #2 Write word => %06X, %04X\n"), a, d); + } + } +} + +UINT8 __fastcall TaitoZZ80Read(UINT16 a) +{ + switch (a) { + case 0xe000: { + return BurnYM2610Read(0); + } + + case 0xe001: { + return BurnYM2610Read(1); + } + + case 0xe002: { + return BurnYM2610Read(2); + } + + case 0xe200: { + // NOP + return 0; + } + + case 0xe201: { + return TC0140SYTSlaveCommRead(); + } + + case 0xea00: { + // NOP + return 0; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a); + } + } + + return 0; +} + +void __fastcall TaitoZZ80Write(UINT16 a, UINT8 d) +{ + switch (a) { + case 0xe000: { + BurnYM2610Write(0, d); + return; + } + + case 0xe001: { + BurnYM2610Write(1, d); + return; + } + + case 0xe002: { + BurnYM2610Write(2, d); + return; + } + + case 0xe003: { + BurnYM2610Write(3, d); + return; + } + + case 0xe200: { + TC0140SYTSlavePortWrite(d); + return; + } + + case 0xe201: { + TC0140SYTSlaveCommWrite(d); + return; + } + + case 0xe400: + case 0xe401: + case 0xe402: + case 0xe403: { + return; + } + + case 0xe600: { + return; + } + + case 0xee00: { + return; + } + + case 0xf000: { + return; + } + + case 0xf200: { + TaitoZ80Bank = (d - 1) & 7; + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + return; + } + + default: { + bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d); + } + } +} + +static INT32 CharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 CharXOffsets[8] = { 8, 12, 0, 4, 24, 28, 16, 20 }; +static INT32 CharYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; +static INT32 DblaxleCharPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 DblaxleCharXOffsets[16] = { 4, 0, 20, 16, 12, 8, 28, 24, 36, 32, 52, 48, 44, 40, 60, 56 }; +static INT32 DblaxleCharYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 SpritePlaneOffsets[4] = { 0, 8, 16, 24 }; +static INT32 SpriteXOffsets[16] = { 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 SpriteYOffsets[16] = { 0, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960 }; +static INT32 Sprite16x8YOffsets[8] = { 0, 64, 128, 192, 256, 320, 384, 448 }; + +static void TaitoZFMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus & 1) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +static INT32 TaitoZSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / (16000000 / 4); +} + +static double TaitoZGetTime() +{ + return (double)ZetTotalCycles() / (16000000 / 4); +} + +static INT32 TaitoZ68KSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)SekTotalCycles() * nSoundRate / (nTaitoCyclesTotal[1] * 60); +} + +static double TaitoZ68KGetTime() +{ + return (double)SekTotalCycles() / (nTaitoCyclesTotal[1] * 60); +} + +static void TaitoZZ80Init() +{ + // Setup the Z80 emulation + ZetInit(1); + ZetOpen(0); + ZetSetReadHandler(TaitoZZ80Read); + ZetSetWriteHandler(TaitoZZ80Write); + ZetMapArea(0x0000, 0x3fff, 0, TaitoZ80Rom1 ); + ZetMapArea(0x0000, 0x3fff, 2, TaitoZ80Rom1 ); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 ); + ZetMapArea(0xc000, 0xdfff, 0, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 1, TaitoZ80Ram1 ); + ZetMapArea(0xc000, 0xdfff, 2, TaitoZ80Ram1 ); + ZetMemEnd(); + ZetClose(); + + TaitoNumZ80s = 1; +} + +static void SwitchToMusashi() +{ + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } +} + +static INT32 AquajackInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x800000, 0x801fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0xa00000, 0xa0ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0xc40000, 0xc403ff, SM_RAM); + SekSetWriteByteHandler(0, Aquajack68K1WriteByte); + SekSetWriteWordHandler(0, Aquajack68K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x104000, 0x107fff, SM_RAM); + SekSetReadWordHandler(0, Aquajack68K2ReadWord); + SekSetWriteWordHandler(0, Aquajack68K2WriteWord); + SekSetReadByteHandler(0, Aquajack68K2ReadByte); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = AquajackMakeInputs; + TaitoDrawFunction = AquajackDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 500; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 BsharkInit() +{ + INT32 nLen; + + Sci = 1; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 1, NULL); + TC0150RODInit(TaitoRoadRomSize, 1); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x110000, 0x113fff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0xa00000, 0xa01fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xc00000, 0xc00fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0xd00000, 0xd0ffff, SM_READ); + SekSetWriteWordHandler(0, Bshark68K1WriteWord); + SekSetReadByteHandler(0, Bshark68K1ReadByte); + SekSetWriteByteHandler(0, Bshark68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x108000, 0x10bfff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x110000, 0x113fff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x800000, 0x801fff, SM_RAM); + SekSetReadWordHandler(0, Bshark68K2ReadWord); + SekSetWriteWordHandler(0, Bshark68K2WriteWord); + SekClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, NULL, TaitoZ68KSynchroniseStream, TaitoZ68KGetTime, 0); + BurnTimerAttachSek(12000000); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = BsharkMakeInputs; + TaitoDrawFunction = BsharkDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + TaitoFlipScreenX = 1; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 ChasehqInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + TaitoSpriteBModulo = 0x400; + TaitoSpriteBNumPlanes = 4; + TaitoSpriteBWidth = 16; + TaitoSpriteBHeight = 16; + TaitoSpriteBPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteBXOffsets = SpriteXOffsets; + TaitoSpriteBYOffsets = SpriteYOffsets; + TaitoNumSpriteB = 0x4000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x107fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x108000, 0x10bfff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0xc00000, 0xc0ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0xd00000, 0xd007ff, SM_RAM); + SekSetReadWordHandler(0, Chasehq68K1ReadWord); + SekSetWriteWordHandler(0, Chasehq68K1WriteWord); + SekSetReadByteHandler(0, Chasehq68K1ReadByte); + SekSetWriteByteHandler(0, Chasehq68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x108000, 0x10bfff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x800000, 0x801fff, SM_RAM); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = ChasehqMakeInputs; + TaitoDrawFunction = ChasehqDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 ContcircInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 16, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x080000, 0x083fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x084000, 0x087fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x200000, 0x20ffff, SM_READ); + SekMapMemory(TC0150RODRam , 0x300000, 0x301fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x400000, 0x4006ff, SM_RAM); + SekSetWriteByteHandler(0, Contcirc68K1WriteByte); + SekSetWriteWordHandler(0, Contcirc68K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x080000, 0x083fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x084000, 0x087fff, SM_RAM); + SekSetReadWordHandler(0, Contcirc68K2ReadWord); + SekSetWriteWordHandler(0, Contcirc68K2WriteWord); + SekSetReadByteHandler(0, Contcirc68K2ReadByte); + SekSetWriteByteHandler(0, Contcirc68K2WriteByte); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = ContcircMakeInputs; + TaitoDrawFunction = ContcircDraw; + TaitoIrqLine = 6; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 DblaxleInit() +{ + INT32 nLen; + + Dblaxle = 1; + + TaitoCharModulo = 0x400; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 16; + TaitoCharHeight = 16; + TaitoCharPlaneOffsets = DblaxleCharPlaneOffsets; + TaitoCharXOffsets = DblaxleCharXOffsets; + TaitoCharYOffsets = DblaxleCharYOffsets; + TaitoNumChar = 0x2000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x10000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + TC0150RODInit(TaitoRoadRomSize, 0); + TC0480SCPInit(TaitoNumChar, 0, 0x21, 8, 4, 0, 0); + TC0140SYTInit(); + TC0510NIOInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x200000, 0x203fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x210000, 0x21ffff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x800000, 0x801fff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0x900000, 0x90ffff, SM_RAM); + SekMapMemory(TC0480SCPRam , 0xa00000, 0xa0ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0xc00000, 0xc03fff, SM_RAM); + SekSetReadWordHandler(0, Dblaxle68K1ReadWord); + SekSetWriteWordHandler(0, Dblaxle68K1WriteWord); + SekSetReadByteHandler(0, Dblaxle68K1ReadByte); + SekSetWriteByteHandler(0, Dblaxle68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x110000, 0x11ffff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x300000, 0x301fff, SM_RAM); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = DblaxleMakeInputs; + TaitoDrawFunction = DblaxleDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 16000000 / 60; + nTaitoCyclesTotal[1] = 16000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + GenericTilesInit(); + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 EnforceInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 16, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x300000, 0x3006ff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x400000, 0x401fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x600000, 0x60ffff, SM_READ); + SekSetWriteByteHandler(0, Enforce68K1WriteByte); + SekSetReadWordHandler(0, Enforce68K1ReadWord); + SekSetWriteWordHandler(0, Enforce68K1WriteWord); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x104000, 0x107fff, SM_RAM); + SekSetReadWordHandler(0, Enforce68K2ReadWord); + SekSetWriteWordHandler(0, Enforce68K2WriteWord); + SekSetReadByteHandler(0, Enforce68K2ReadByte); + SekSetWriteByteHandler(0, Enforce68K2WriteByte); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = EnforceMakeInputs; + TaitoDrawFunction = EnforceDraw; + TaitoIrqLine = 6; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 NightstrInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x400; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 16; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = SpriteYOffsets; + TaitoNumSpriteA = 0x4000; + + TaitoSpriteBModulo = 0x400; + TaitoSpriteBNumPlanes = 4; + TaitoSpriteBWidth = 16; + TaitoSpriteBHeight = 16; + TaitoSpriteBPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteBXOffsets = SpriteXOffsets; + TaitoSpriteBYOffsets = SpriteYOffsets; + TaitoNumSpriteB = 0x4000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0110PCRInit(1, 0x1000); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x10ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x110000, 0x113fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0xc00000, 0xc0ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0xd00000, 0xd007ff, SM_RAM); + SekSetReadWordHandler(0, Nightstr68K1ReadWord); + SekSetWriteWordHandler(0, Nightstr68K1WriteWord); + SekSetReadByteHandler(0, Nightstr68K1ReadByte); + SekSetWriteByteHandler(0, Nightstr68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x100000, 0x103fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x104000, 0x107fff, SM_RAM); + SekMapMemory(TC0150RODRam , 0x800000, 0x801fff, SM_RAM); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = NightstrMakeInputs; + TaitoDrawFunction = ChasehqDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 SciInit() +{ + INT32 nLen; + + Sci = 1; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x8000; + + TaitoNum68Ks = 2; + TaitoNumZ80s = 1; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 0, 8, 0, NULL); + TC0150RODInit(TaitoRoadRomSize, 0); + TC0140SYTInit(); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x100000, 0x107fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x108000, 0x10bfff, SM_RAM); + SekMapMemory(TaitoPaletteRam , 0x800000, 0x801fff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0xa00000, 0xa0ffff, SM_READ); + SekMapMemory(TaitoSpriteRam , 0xc00000, 0xc03fff, SM_RAM); + SekSetWriteWordHandler(0, Sci68K1WriteWord); + SekSetReadByteHandler(0, Sci68K1ReadByte); + SekSetWriteByteHandler(0, Sci68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x01ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x200000, 0x203fff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x208000, 0x20bfff, SM_RAM); + SekMapMemory(TC0150RODRam , 0xa00000, 0xa01fff, SM_RAM); + SekClose(); + + TaitoZZ80Init(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, &TaitoZFMIRQHandler, TaitoZSynchroniseStream, TaitoZGetTime, 0); + BurnTimerAttachZet(16000000 / 4); + BurnYM2610SetSoundMixMode(1); + + TaitoMakeInputsFunction = SciMakeInputs; + TaitoDrawFunction = SciDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + + nTaitoCyclesTotal[0] = 12000000 / 60; + nTaitoCyclesTotal[1] = 12000000 / 60; + nTaitoCyclesTotal[2] = (16000000 / 4) / 60; + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 SpacegunInit() +{ + INT32 nLen; + + TaitoCharModulo = 0x100; + TaitoCharNumPlanes = 4; + TaitoCharWidth = 8; + TaitoCharHeight = 8; + TaitoCharPlaneOffsets = CharPlaneOffsets; + TaitoCharXOffsets = CharXOffsets; + TaitoCharYOffsets = CharYOffsets; + TaitoNumChar = 0x4000; + + TaitoSpriteAModulo = 0x200; + TaitoSpriteANumPlanes = 4; + TaitoSpriteAWidth = 16; + TaitoSpriteAHeight = 8; + TaitoSpriteAPlaneOffsets = SpritePlaneOffsets; + TaitoSpriteAXOffsets = SpriteXOffsets; + TaitoSpriteAYOffsets = Sprite16x8YOffsets; + TaitoNumSpriteA = 0x10000; + + TaitoNum68Ks = 2; + TaitoNumYM2610 = 1; + + TaitoLoadRoms(0); + + // Allocate and Blank all required memory + TaitoMem = NULL; + MemIndex(); + nLen = TaitoMemEnd - (UINT8 *)0; + if ((TaitoMem = (UINT8 *)malloc(nLen)) == NULL) return 1; + memset(TaitoMem, 0, nLen); + MemIndex(); + + GenericTilesInit(); + + TC0100SCNInit(0, TaitoNumChar, 4, 8, 1, NULL); + TC0110PCRInit(1, 0x1000); + TC0220IOCInit(); + + if (TaitoLoadRoms(1)) return 1; + + SwitchToMusashi(); + + // Setup the 68000 emulation + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Taito68KRom1 , 0x000000, 0x07ffff, SM_ROM); + SekMapMemory(Taito68KRam1 , 0x30c000, 0x30ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x310000, 0x31ffff, SM_RAM); + SekMapMemory(TaitoSpriteRam , 0x500000, 0x5005ff, SM_RAM); + SekMapMemory(TC0100SCNRam[0] , 0x900000, 0x90ffff, SM_READ); + SekSetReadWordHandler(0, Spacegun68K1ReadWord); + SekSetWriteWordHandler(0, Spacegun68K1WriteWord); + SekSetWriteByteHandler(0, Spacegun68K1WriteByte); + SekClose(); + + SekInit(1, 0x68000); + SekOpen(1); + SekMapMemory(Taito68KRom2 , 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Taito68KRam2 , 0x20c000, 0x20ffff, SM_RAM); + SekMapMemory(TaitoSharedRam , 0x210000, 0x21ffff, SM_RAM); + SekSetReadWordHandler(0, Spacegun68K2ReadWord); + SekSetWriteWordHandler(0, Spacegun68K2WriteWord); + SekSetReadByteHandler(0, Spacegun68K2ReadByte); + SekSetWriteByteHandler(0, Spacegun68K2WriteByte); + SekClose(); + + BurnYM2610Init(16000000 / 2, TaitoYM2610ARom, (INT32*)&TaitoYM2610ARomSize, TaitoYM2610BRom, (INT32*)&TaitoYM2610BRomSize, NULL, TaitoZ68KSynchroniseStream, TaitoZ68KGetTime, 0); + BurnTimerAttachSek(16000000); + BurnYM2610SetSoundMixMode(1); + + EEPROMInit(&spacegun_eeprom_intf); + if (!EEPROMAvailable()) EEPROMFill(spacegun_default_eeprom, 0, 128); + + TaitoMakeInputsFunction = SpacegunMakeInputs; + TaitoDrawFunction = SpacegunDraw; + TaitoIrqLine = 4; + TaitoFrameInterleave = 100; + TaitoFlipScreenX = 1; + TaitoNumEEPROM = 1; + + nTaitoCyclesTotal[0] = 16000000 / 60; + nTaitoCyclesTotal[1] = 16000000 / 60; + + BurnGunInit(2, true); + + // Reset the driver + TaitoZDoReset(); + + return 0; +} + +static INT32 TaitoZExit() +{ + TaitoExit(); + + SciSpriteFrame = 0; + OldSteer = 0; + Dblaxle = 0; + Sci = 0; + + BurnYM2610SetSoundMixMode(0); + + // Switch back CPU core if needed + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + return 0; +} + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = pal5bit(nColour >> 0); + g = pal5bit(nColour >> 5); + b = pal5bit(nColour >> 10); + + return BurnHighCol(r, g, b, 0); +} + +static void TaitoZCalcPalette() +{ + INT32 i; + UINT16* ps; + UINT32* pd; + + for (i = 0, ps = (UINT16*)TaitoPaletteRam, pd = TaitoPalette; i < 0x1000; i++, ps++, pd++) { + *pd = CalcCol(*ps); + } +} + +static void RenderSpriteZoom(INT32 Code, INT32 sx, INT32 sy, INT32 Colour, INT32 xFlip, INT32 yFlip, INT32 xScale, INT32 yScale, UINT8* pSource) +{ + // We can use sprite A for sizes, etc. as only Chase HQ uses sprite B and it has the same sizes and count + + UINT8 *SourceBase = pSource + ((Code % TaitoNumSpriteA) * TaitoSpriteAWidth * TaitoSpriteAHeight); + + INT32 SpriteScreenHeight = (yScale * TaitoSpriteAHeight + 0x8000) >> 16; + INT32 SpriteScreenWidth = (xScale * TaitoSpriteAWidth + 0x8000) >> 16; + + Colour = 0x10 * (Colour % 0x100); + + if (TaitoFlipScreenX) { + xFlip = !xFlip; + sx = 320 - sx - (xScale >> 12); + } + + if (SpriteScreenWidth && SpriteScreenHeight) { + INT32 dx = (TaitoSpriteAWidth << 16) / SpriteScreenWidth; + INT32 dy = (TaitoSpriteAHeight << 16) / SpriteScreenHeight; + + INT32 ex = sx + SpriteScreenWidth; + INT32 ey = sy + SpriteScreenHeight; + + INT32 xIndexBase; + INT32 yIndex; + + if (xFlip) { + xIndexBase = (SpriteScreenWidth - 1) * dx; + dx = -dx; + } else { + xIndexBase = 0; + } + + if (yFlip) { + yIndex = (SpriteScreenHeight - 1) * dy; + dy = -dy; + } else { + yIndex = 0; + } + + if (sx < 0) { + INT32 Pixels = 0 - sx; + sx += Pixels; + xIndexBase += Pixels * dx; + } + + if (sy < 0) { + INT32 Pixels = 0 - sy; + sy += Pixels; + yIndex += Pixels * dy; + } + + if (ex > nScreenWidth) { + INT32 Pixels = ex - nScreenWidth; + ex -= Pixels; + } + + if (ey > nScreenHeight) { + INT32 Pixels = ey - nScreenHeight; + ey -= Pixels; + } + + if (ex > sx) { + INT32 y; + + for (y = sy; y < ey; y++) { + UINT8 *Source = SourceBase + ((yIndex >> 16) * TaitoSpriteAWidth); + UINT16* pPixel = pTransDraw + (y * nScreenWidth); + + INT32 x, xIndex = xIndexBase; + for (x = sx; x < ex; x++) { + INT32 c = Source[xIndex >> 16]; + if (c != 0) { + pPixel[x] = c | Colour; + } + xIndex += dx; + } + + yIndex += dy; + } + } + } +} + +static void AquajackRenderSprites(INT32 PriorityDraw) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + for (Offset = 0x200 - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + Data = SpriteRam[Offset + 3]; + yFlip = (Data & 0x8000) >> 15; + Tile = Data & 0x1fff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0x7e00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + Colour = (Data & 0xff00) >> 8; + xZoom = (Data & 0x3f); + + MapOffset = Tile << 5; + + xZoom += 1; + yZoom += 1; + + y += 3; + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + k = SpriteChunk % 4; + j = SpriteChunk / 4; + + px = xFlip ? (3 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + + + } +} + +static void BsharkRenderSprites(INT32 PriorityDraw, INT32 yOffset, INT32 SpriteRamSize) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + for (Offset = 0; Offset < SpriteRamSize - 4; Offset += 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + Colour = (Data & 0x7f80) >> 7; + xZoom = (Data & 0x3f); + + Data = SpriteRam[Offset + 3]; + Tile = Data & 0x1fff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0x7e00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + yFlip = (Data & 0x8000) >> 15; + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + MapOffset = Tile << 5; + + xZoom += 1; + yZoom += 1; + + y += yOffset; + y += (64 - yZoom); + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + k = SpriteChunk % 4; + j = SpriteChunk / 4; + + px = xFlip ? (3 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + + } +} + +static void ChasehqRenderSprites(INT32 PriorityDraw) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + for (Offset = 0; Offset < 0x400; Offset += 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + Colour = (Data & 0x7f80) >> 7; + xZoom = (Data & 0x7f); + + Data = SpriteRam[Offset + 3]; + Tile = Data & 0x7ff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0xfe00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + yFlip = (Data & 0x8000) >> 15; + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + xZoom += 1; + yZoom += 1; + + y += 7; + y += (128 - yZoom); + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + if ((xZoom - 1) & 0x40) { + MapOffset = Tile << 6; + + for (SpriteChunk = 0; SpriteChunk < 64; SpriteChunk++) { + j = SpriteChunk / 8; + k = SpriteChunk % 8; + + px = xFlip ? (7 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 3)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 8); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 8) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 12, TaitoSpritesA); + } + } else if ((xZoom - 1) & 0x20) { + MapOffset = (Tile << 5) + 0x20000; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + j = SpriteChunk / 4; + k = SpriteChunk % 4; + + px = xFlip ? (3 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteB - 1); + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 12, TaitoSpritesB); + } + } else if (!((xZoom - 1) & 0x60)) { + MapOffset = (Tile << 4) + 0x30000; + + for (SpriteChunk = 0; SpriteChunk < 16; SpriteChunk++) { + j = SpriteChunk / 2; + k = SpriteChunk % 2; + + px = xFlip ? (1 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 1)]; + Code &= (TaitoNumSpriteB - 1); + + xCur = x + ((k * xZoom) / 2); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 2) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 12, TaitoSpritesB); + } + } + } +} + +static void ContcircRenderSprites(INT32 PriorityDraw, INT32 VisibleYOffset) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + for (Offset = 0x380 - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 2]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + xFlip = (Data & 0x4000) >> 14; + yFlip = (Data & 0x2000) >> 13; + x = Data & 0x1ff; + + Data = SpriteRam[Offset + 1]; + Tile = Data & 0x7ff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0xfe00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 3]; + Colour = (Data & 0xff00) >> 8; + xZoom = (Data & 0x7f); + + MapOffset = Tile << 7; + + xZoom += 1; + yZoom += 1; + + y += 5; + y += ( 128 - yZoom); + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + for (SpriteChunk = 0; SpriteChunk < 128; SpriteChunk++) { + k = SpriteChunk % 8; + j = SpriteChunk / 8; + + px = xFlip ? (7 - k) : k; + py = yFlip ? (15 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 3)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 8); + yCur = y + ((j * yZoom) / 16); + + zx = x + (((k + 1) * xZoom) / 8) - xCur; + zy = y + (((j + 1) * yZoom) / 16) - yCur; + + yCur -= VisibleYOffset; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + } +} + +static void SciRenderSprites(INT32 PriorityDraw, INT32 yOffs) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, StartOffs, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + StartOffs = (SciSpriteFrame & 1) ? 0x800 : 0; + + for (Offset = StartOffs; Offset < StartOffs + 0x800; Offset += 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + Colour = (Data & 0x7f80) >> 7; + xZoom = (Data & 0x3f); + + Data = SpriteRam[Offset + 3]; + Tile = Data & 0x1fff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0x7e00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + yFlip = (Data & 0x8000) >> 15; + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + MapOffset = Tile << 5; + + xZoom += 1; + yZoom += 1; + + y += yOffs; + y += (64 - yZoom); + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + k = SpriteChunk % 4; + j = SpriteChunk / 4; + + px = xFlip ? (3-k) : k; + py = yFlip ? (7-j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + } +} + +static void SpacegunRenderSprites(INT32 PriorityDraw) +{ + UINT16 *SpriteMap = (UINT16*)TaitoSpriteMapRom; + UINT16 *SpriteRam = (UINT16*)TaitoSpriteRam; + INT32 Offset, Data, Tile, Colour, xFlip, yFlip; + INT32 x, y, Priority, xCur, yCur; + INT32 xZoom, yZoom, zx, zy; + INT32 SpriteChunk, MapOffset, Code, j, k, px, py; + + for (Offset = 0x300 - 4; Offset >= 0; Offset -= 4) { + Data = SpriteRam[Offset + 1]; + Priority = (Data & 0x8000) >> 15; + + if (Priority != 0 && Priority != 1) bprintf(PRINT_NORMAL, _T("Unused Priority %x\n"), Priority); + if (Priority != PriorityDraw) continue; + + xFlip = (Data & 0x4000) >> 14; + x = Data & 0x1ff; + + Data = SpriteRam[Offset + 3]; + yFlip = (Data & 0x8000) >> 15; + Tile = Data & 0x1fff; + if (!Tile) continue; + + Data = SpriteRam[Offset + 0]; + yZoom = (Data & 0xfe00) >> 9; + y = Data & 0x1ff; + + Data = SpriteRam[Offset + 2]; + Colour = (Data & 0xff00) >> 8; + xZoom = (Data & 0x7f); + + MapOffset = Tile << 5; + + xZoom += 1; + yZoom += 1; + + y += 4; + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + for (SpriteChunk = 0; SpriteChunk < 32; SpriteChunk++) { + k = SpriteChunk % 4; + j = SpriteChunk / 4; + + px = xFlip ? (3 - k) : k; + py = yFlip ? (7 - j) : j; + + Code = SpriteMap[MapOffset + px + (py << 2)]; + Code &= (TaitoNumSpriteA - 1); + + xCur = x + ((k * xZoom) / 4); + yCur = y + ((j * yZoom) / 8); + + zx = x + (((k + 1) * xZoom) / 4) - xCur; + zy = y + (((j + 1) * yZoom) / 8) - yCur; + + yCur -= 16; + + RenderSpriteZoom(Code, xCur, yCur, Colour, xFlip, yFlip, zx << 12, zy << 13, TaitoSpritesA); + } + + } +} + +static void AquajackDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + AquajackRenderSprites(1); + + TC0150RODDraw(-1, 0, 2, 1, 1, 2); + + AquajackRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void BsharkDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + TaitoZCalcPalette(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + BsharkRenderSprites(1, 8, 0x800); + + TC0150RODDraw(-1, 0xc0, 0, 1, 1, 2); + + BsharkRenderSprites(0, 8, 0x800); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TaitoPalette); +} + +static void ChasehqDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + ChasehqRenderSprites(1); + + TC0150RODDraw(-1, 0xc0, 0, 0, 1, 2); + + ChasehqRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void ContcircDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + ContcircRenderSprites(1, 24); + + TC0150RODDraw(-3 + 8, TaitoRoadPalBank << 6, 1, 0, 1, 2); + + ContcircRenderSprites(0, 24); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void EnforceDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + ContcircRenderSprites(1, 24); + + TC0150RODDraw(-3 + 8, 0xc0, 1, 0, 1, 2); + + ContcircRenderSprites(0, 24); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); +} + +static void DblaxleDraw() +{ + UINT8 Layer[4]; + UINT16 Priority = TC0480SCPGetBgPriority(); + + Layer[0] = (Priority & 0xf000) >> 12; + Layer[1] = (Priority & 0x0f00) >> 8; + Layer[2] = (Priority & 0x00f0) >> 4; + Layer[3] = (Priority & 0x000f) >> 0; + + BurnTransferClear(); + TaitoZCalcPalette(); + + TC0480SCPTilemapRender(Layer[0], 1, TaitoChars); + TC0480SCPTilemapRender(Layer[1], 0, TaitoChars); + TC0480SCPTilemapRender(Layer[2], 0, TaitoChars); + + BsharkRenderSprites(1, 7, 0x2000); + + TC0150RODDraw(-1, 0xc0, 0, 0, 1, 2); + + BsharkRenderSprites(0, 7, 0x2000); + + TC0480SCPTilemapRender(Layer[3], 0, TaitoChars); + + TC0480SCPRenderCharLayer(); + BurnTransferCopy(TaitoPalette); +} + +static void SciDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + TaitoZCalcPalette(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + SciRenderSprites(1, 6); + + TC0150RODDraw(-1, 0xc0, 0, 0, 1, 2); + + SciRenderSprites(0, 6); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + + BurnTransferCopy(TaitoPalette); +} + +static void SpacegunDraw() +{ + INT32 Disable = TC0100SCNCtrl[0][6] & 0xf7; + + BurnTransferClear(); + + if (TC0100SCNBottomLayer(0)) { + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 1, TaitoChars); + SpacegunRenderSprites(1); + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 0, TaitoChars); + } else { + if (!(Disable & 0x01)) TC0100SCNRenderBgLayer(0, 1, TaitoChars); + SpacegunRenderSprites(1); + if (!(Disable & 0x02)) TC0100SCNRenderFgLayer(0, 0, TaitoChars); + } + + SpacegunRenderSprites(0); + + if (!(Disable & 0x04)) TC0100SCNRenderCharLayer(0); + BurnTransferCopy(TC0110PCRPalette); + + for (INT32 i = 0; i < nBurnGunNumPlayers; i++) { + BurnGunDrawTarget(i, BurnGunX[i] >> 8, BurnGunY[i] >> 8); + } +} + +static INT32 TaitoZFrame() +{ + INT32 nInterleave = TaitoFrameInterleave; + + if (TaitoReset) TaitoZDoReset(); + + TaitoMakeInputsFunction(); + + nTaitoCyclesDone[0] = nTaitoCyclesDone[1] = nTaitoCyclesDone[2] = 0; + + SekNewFrame(); + if (TaitoNumZ80s) ZetNewFrame(); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU, nNext; + + // Run 68000 #1 + nCurrentCPU = 0; + SekOpen(0); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == 10 && Sci && (GetCurrentFrame() & 1)) { SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); nTaitoCyclesDone[0] += SekRun(200000 - 500); } + if (i == 10 && Dblaxle && (GetCurrentFrame() & 1)) { SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); nTaitoCyclesDone[0] += SekRun(200000 - 500); } + if (i == 50 && Dblaxle) { SekSetIRQLine(6, SEK_IRQSTATUS_AUTO); nTaitoCyclesDone[0] += SekRun(200000 - 500); } + if (i == (TaitoFrameInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + + // Run 68000 #2 + if ((TaitoCpuACtrl & 0x01) && TaitoNumZ80s) { + nCurrentCPU = 1; + SekOpen(1); + nNext = (i + 1) * nTaitoCyclesTotal[nCurrentCPU] / nInterleave; + nTaitoCyclesSegment = nNext - nTaitoCyclesDone[nCurrentCPU]; + nTaitoCyclesDone[nCurrentCPU] += SekRun(nTaitoCyclesSegment); + if (i == (TaitoFrameInterleave - 1)) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + } + + if (TaitoNumZ80s) { + ZetOpen(0); + BurnTimerEndFrame(nTaitoCyclesTotal[2]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + ZetClose(); + } else { + SekOpen(1); + if (TaitoCpuACtrl & 0x01) BurnTimerEndFrame(nTaitoCyclesTotal[1]); + BurnYM2610Update(pBurnSoundOut, nBurnSoundLen); + if (TaitoCpuACtrl & 0x01) SekSetIRQLine(TaitoIrqLine, SEK_IRQSTATUS_AUTO); + SekClose(); + } + + if (pBurnDraw) TaitoDrawFunction(); + + return 0; +} + +static INT32 TaitoZScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029674; + } + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TaitoRamStart; + ba.nLen = TaitoRamEnd-TaitoRamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + TaitoICScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SekScan(nAction); + if (TaitoNumZ80s) ZetScan(nAction); + + BurnYM2610Scan(nAction, pnMin); + + BurnGunScan(); + + SCAN_VAR(TaitoAnalogPort0); + SCAN_VAR(TaitoAnalogPort1); + SCAN_VAR(TaitoAnalogPort2); + SCAN_VAR(TaitoAnalogPort3); + SCAN_VAR(TaitoInput); + SCAN_VAR(OldSteer); + SCAN_VAR(TaitoCpuACtrl); + SCAN_VAR(TaitoZ80Bank); + SCAN_VAR(SciSpriteFrame); + SCAN_VAR(TaitoRoadPalBank); + SCAN_VAR(nTaitoCyclesDone); + SCAN_VAR(nTaitoCyclesSegment); + } + + if (nAction & ACB_WRITE) { + if (TaitoNumZ80s) { + ZetOpen(0); + ZetMapArea(0x4000, 0x7fff, 0, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetMapArea(0x4000, 0x7fff, 2, TaitoZ80Rom1 + 0x4000 + (TaitoZ80Bank * 0x4000)); + ZetClose(); + } + } + + return 0; +} + +struct BurnDriver BurnDrvAquajack = { + "aquajack", NULL, NULL, NULL, "1990", + "Aquajack (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_MISC, 0, + NULL, AquajackRomInfo, AquajackRomName, NULL, NULL, AquajackInputInfo, AquajackDIPInfo, + AquajackInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvAquajackj = { + "aquajackj", "aquajack", NULL, NULL, "1990", + "Aquajack (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_MISC, 0, + NULL, AquajackjRomInfo, AquajackjRomName, NULL, NULL, AquajackInputInfo, AquajackjDIPInfo, + AquajackInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvAquajacku = { + "aquajacku", "aquajack", NULL, NULL, "1990", + "Aquajack (US)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_MISC, 0, + NULL, AquajackuRomInfo, AquajackuRomName, NULL, NULL, AquajackInputInfo, AquajackjDIPInfo, + AquajackInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBshark = { + "bshark", NULL, NULL, NULL, "1989", + "Battle Shark (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, BsharkRomInfo, BsharkRomName, NULL, NULL, BsharkInputInfo, BsharkDIPInfo, + BsharkInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBsharkj = { + "bsharkj", "bshark", NULL, NULL, "1989", + "Battle Shark (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, BsharkjRomInfo, BsharkjRomName, NULL, NULL, BsharkInputInfo, BsharkjDIPInfo, + BsharkInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBsharkjjs = { + "bsharkjjs", "bshark", NULL, NULL, "1989", + "Battle Shark (Japan, Joystick)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, BsharkjjsRomInfo, BsharkjjsRomName, NULL, NULL, BsharkjjsInputInfo, BsharkjjsDIPInfo, + BsharkInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvBsharku = { + "bsharku", "bshark", NULL, NULL, "1989", + "Battle Shark (US)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, BsharkuRomInfo, BsharkuRomName, NULL, NULL, BsharkInputInfo, BsharkuDIPInfo, + BsharkInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvChasehq = { + "chasehq", NULL, NULL, NULL, "1988", + "Chase H.Q. (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ChasehqRomInfo, ChasehqRomName, NULL, NULL, ChasehqInputInfo, ChasehqDIPInfo, + ChasehqInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvChasehqj = { + "chasehqj", "chasehq", NULL, NULL, "1988", + "Chase H.Q. (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ChasehqjRomInfo, ChasehqjRomName, NULL, NULL, ChasehqInputInfo, ChasehqjDIPInfo, + ChasehqInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvChasehqu = { + "chasehqu", "chasehq", NULL, NULL, "1988", + "Chase H.Q. (US)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ChasehquRomInfo, ChasehquRomName, NULL, NULL, ChasehqInputInfo, ChasehqDIPInfo, + ChasehqInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvContcirc = { + "contcirc", NULL, NULL, NULL, "1987", + "Continental Circus (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ContcircRomInfo, ContcircRomName, NULL, NULL, ContcircInputInfo, ContcircDIPInfo, + ContcircInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvContcircu = { + "contcircu", "contcirc", NULL, NULL, "1987", + "Continental Circus (US set 1)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ContcircuRomInfo, ContcircuRomName, NULL, NULL, ContcircInputInfo, ContcircuDIPInfo, + ContcircInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvContcircua = { + "contcircua", "contcirc", NULL, NULL, "1987", + "Continental Circus (US set 2)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ContcircuaRomInfo, ContcircuaRomName, NULL, NULL, ContcircInputInfo, ContcircuDIPInfo, + ContcircInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvDblaxle = { + "dblaxle", NULL, NULL, NULL, "1991", + "Double Axle (US)\0", "Imperfect sound, bad dump in sample rom?", "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, DblaxleRomInfo, DblaxleRomName, NULL, NULL, DblaxleInputInfo, DblaxleDIPInfo, + DblaxleInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvPwheelsj = { + "pwheelsj", "dblaxle", NULL, NULL, "1991", + "Power Wheels (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, PwheelsjRomInfo, PwheelsjRomName, NULL, NULL, DblaxleInputInfo, PwheelsjDIPInfo, + DblaxleInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvEnforce = { + "enforce", NULL, NULL, NULL, "1988", + "Enforce (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, EnforceRomInfo, EnforceRomName, NULL, NULL, EnforceInputInfo, EnforceDIPInfo, + EnforceInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 224, 4, 3 +}; + +struct BurnDriver BurnDrvNightstr = { + "nightstr", NULL, NULL, NULL, "1989", + "Night Striker (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_MISC, 0, + NULL, NightstrRomInfo, NightstrRomName, NULL, NULL, NightstrInputInfo, NightstrDIPInfo, + NightstrInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvNightstrj = { + "nightstrj", "nightstr", NULL, NULL, "1989", + "Night Striker (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_MISC, 0, + NULL, NightstrjRomInfo, NightstrjRomName, NULL, NULL, NightstrInputInfo, NightstrjDIPInfo, + NightstrInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvNightstru = { + "nightstru", "nightstr", NULL, NULL, "1989", + "Night Striker (US)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, NightstruRomInfo, NightstruRomName, NULL, NULL, NightstrInputInfo, NightstruDIPInfo, + NightstrInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSci = { + "sci", NULL, NULL, NULL, "1989", + "Special Criminal Investigation (World set 1)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, SciRomInfo, SciRomName, NULL, NULL, SciInputInfo, SciDIPInfo, + SciInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvScia = { + "scia", "sci", NULL, NULL, "1989", + "Special Criminal Investigation (World set 2)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, SciaRomInfo, SciaRomName, NULL, NULL, SciInputInfo, SciDIPInfo, + SciInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvScij = { + "scij", "sci", NULL, NULL, "1989", + "Special Criminal Investigation (Japan)\0", NULL, "Taito Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ScijRomInfo, ScijRomName, NULL, NULL, SciInputInfo, ScijDIPInfo, + SciInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSciu = { + "sciu", "sci", NULL, NULL, "1989", + "Special Criminal Investigation (US)\0", NULL, "Taito America Corporation", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, SciuRomInfo, SciuRomName, NULL, NULL, SciInputInfo, SciuDIPInfo, + SciInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvScinegro = { + "scinegro", "sci", NULL, NULL, "1989", + "Special Criminal Investigation (Negro bootleg)\0", NULL, "Negro", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TAITO_TAITOZ, GBF_RACING, 0, + NULL, ScinegroRomInfo, ScinegroRomName, NULL, NULL, SciInputInfo, SciDIPInfo, + SciInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvSpacegun = { + "spacegun", NULL, NULL, NULL, "1990", + "Space Gun (World)\0", NULL, "Taito Corporation Japan", "Taito-Z", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TAITO_TAITOZ, GBF_SHOOT, 0, + NULL, SpacegunRomInfo, SpacegunRomName, NULL, NULL, SpacegunInputInfo, SpacegunDIPInfo, + SpacegunInit, TaitoZExit, TaitoZFrame, NULL, TaitoZScan, + NULL, 0x1000, 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/taito/pc080sn.cpp b/src/burn/drivers/taito/pc080sn.cpp new file mode 100644 index 00000000..fd21cb5c --- /dev/null +++ b/src/burn/drivers/taito/pc080sn.cpp @@ -0,0 +1,851 @@ +// PC080SN + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *PC080SNRam[PC080SN_MAX_CHIPS] = { NULL, NULL }; +static UINT16 PC080SNCtrl[PC080SN_MAX_CHIPS][8]; +static INT32 BgScrollX[PC080SN_MAX_CHIPS]; +static INT32 BgScrollY[PC080SN_MAX_CHIPS]; +static INT32 FgScrollX[PC080SN_MAX_CHIPS]; +static INT32 FgScrollY[PC080SN_MAX_CHIPS]; +static INT32 PC080SNNumTiles[PC080SN_MAX_CHIPS]; +static INT32 PC080SNXOffset[PC080SN_MAX_CHIPS]; +static INT32 PC080SNYOffset[PC080SN_MAX_CHIPS]; +static INT32 PC080SNFgTransparentPen[PC080SN_MAX_CHIPS]; +static INT32 PC080SNYInvert[PC080SN_MAX_CHIPS]; +static INT32 PC080SNDblWidth[PC080SN_MAX_CHIPS]; +static INT32 PC080SNCols[PC080SN_MAX_CHIPS]; +static INT32 PC080SNNum = 0; + +void PC080SNDrawBgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc, UINT16 *pDest) +{ + INT32 mx, my, Offset, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)PC080SNRam[Chip] + 0x0000; + UINT16 *BgScrollRam = NULL; + + if (!PC080SNDblWidth[Chip]) BgScrollRam = (UINT16*)PC080SNRam[Chip] + 0x2000; + + INT32 BgScrollActive = 0; + if (BgScrollRam) { + for (INT32 i = 0; i < 512; i++) { + if (BgScrollRam[i]) { + BgScrollActive = 1; + break; + } + } + } + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < PC080SNCols[Chip]; mx++) { + Offset = 2 * TileIndex; + if (!PC080SNDblWidth[Chip]) { + Attr = VideoRam[Offset + 0]; + Code = VideoRam[Offset + 1] & (PC080SNNumTiles[Chip] - 1); + } else { + Attr = VideoRam[TileIndex + 0x0000]; + Code = VideoRam[TileIndex + 0x2000] & 0x3fff; + } + Colour = Attr & 0x1ff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + x -= 16; + + x -= PC080SNXOffset[Chip]; + y -= PC080SNYOffset[Chip]; + + if (BgScrollActive) { + INT32 px, py; + + UINT32 nPalette = (Colour << 4); + + for (py = 0; py < 8; py++) { + for (px = 0; px < 8; px++) { + UINT8 c = pSrc[(Code * 64) + (py * 8) + px]; + if (xFlip) c = pSrc[(Code * 64) + (py * 8) + (7 - px)]; + if (yFlip) c = pSrc[(Code * 64) + ((7 - py) * 8) + px]; + if (xFlip && yFlip) c = pSrc[(Code * 64) + ((7 - py) * 8) + (7 - px)]; + + if (c || Opaque) { + INT32 xPos = x + px; + INT32 yPos = y + py; + yPos -= BgScrollY[Chip] & 0x1ff; + + if (yPos < -8) yPos += 512; + if (yPos >= 512) yPos -= 512; + + if (yPos >= 0 && yPos < nScreenHeight) { + if (!PC080SNDblWidth[Chip]) { + xPos -= ((BgScrollX[Chip] - BgScrollRam[yPos + PC080SNYOffset[Chip]]) & 0x1ff); + if (xPos < -8) xPos += 512; + if (xPos >= 512) xPos -= 512; + } else { + xPos -= BgScrollX[Chip] & 0x3ff; + if (xPos < -8) xPos += 1024; + if (xPos >= 1024) xPos -= 1024; + } + + UINT16* pPixel = pDest + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + } else { + if (!PC080SNDblWidth[Chip]) { + x -= BgScrollX[Chip] & 0x1ff; + if (x < -8) x += 512; + if (x >= 512) x -= 512; + } else { + x -= BgScrollX[Chip] & 0x3ff; + if (x < -8) x += 1024; + if (x >= 1024) x -= 1024; + } + + y -= BgScrollY[Chip] & 0x1ff; + if (y < -8) y += 512; + if (y >= 512) y -= 512; + + if (Opaque) { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } + } + } else { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX_Clip(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + Render8x8Tile_Mask_Clip(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } + } + } + } + + TileIndex++; + } + } +} + +void PC080SNDrawFgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc, UINT16 *pDest) +{ + INT32 mx, my, Offset, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)PC080SNRam[Chip] + 0x4000; + UINT16 *FgScrollRam = NULL; + + if (!PC080SNDblWidth[Chip]) FgScrollRam = (UINT16*)PC080SNRam[Chip] + 0x6000; + + INT32 FgScrollActive = 0; + if (FgScrollRam) { + for (INT32 i = 0; i < 512; i++) { + if (FgScrollRam[i]) { + FgScrollActive = 1; + break; + } + } + } + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < PC080SNCols[Chip]; mx++) { + Offset = 2 * TileIndex; + if (!PC080SNDblWidth[Chip]) { + Attr = VideoRam[Offset + 0]; + Code = VideoRam[Offset + 1] & (PC080SNNumTiles[Chip] - 1); + } else { + Attr = VideoRam[TileIndex + 0x0000]; + Code = VideoRam[TileIndex + 0x2000] & 0x3fff; + } + Colour = Attr & 0x1ff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + x -= 16; + + x -= PC080SNXOffset[Chip]; + y -= PC080SNYOffset[Chip]; + + if (FgScrollActive) { + INT32 px, py; + + UINT32 nPalette = (Colour << 4); + + for (py = 0; py < 8; py++) { + for (px = 0; px < 8; px++) { + UINT8 c = pSrc[(Code * 64) + (py * 8) + px]; + if (xFlip) c = pSrc[(Code * 64) + (py * 8) + (7 - px)]; + if (yFlip) c = pSrc[(Code * 64) + ((7 - py) * 8) + px]; + if (xFlip && yFlip) c = pSrc[(Code * 64) + ((7 - py) * 8) + (7 - px)]; + + if (c != PC080SNFgTransparentPen[Chip] || Opaque) { + INT32 xPos = x + px; + INT32 yPos = y + py; + yPos -= FgScrollY[Chip] & 0x1ff; + + if (yPos < -8) yPos += 512; + if (yPos >= 512) yPos -= 512; + + if (yPos >= 0 && yPos < nScreenHeight) { + if (!PC080SNDblWidth[Chip]) { + xPos -= ((FgScrollX[Chip] - FgScrollRam[yPos + PC080SNYOffset[Chip]]) & 0x1ff); + if (xPos < -8) xPos += 512; + if (xPos >= 512) xPos -= 512; + } else { + xPos -= FgScrollX[Chip] & 0x3ff; + if (xPos < -8) xPos += 1024; + if (xPos >= 1024) xPos -= 1024; + } + + UINT16* pPixel = pDest + (yPos * nScreenWidth); + + if (xPos >= 0 && xPos < nScreenWidth) { + pPixel[xPos] = c | nPalette; + } + } + } + } + } + } else { + if (!PC080SNDblWidth[Chip]) { + x -= FgScrollX[Chip] & 0x1ff; + if (x < -8) x += 512; + if (x >= 512) x -= 512; + } else { + x -= FgScrollX[Chip] & 0x3ff; + if (x < -8) x += 1024; + if (x >= 1024) x -= 1024; + } + + y -= FgScrollY[Chip] & 0x1ff; + if (y < -8) y += 512; + if (y >= 512) y -= 512; + + if (Opaque) { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_FlipXY_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_FlipX_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_FlipY_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } else { + Render8x8Tile_Clip(pDest, Code, x , y, Colour, 4, 0, pSrc); + } + } + } + } else { + if (x > 8 && x < (nScreenWidth - 8) && y > 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } else { + Render8x8Tile_Mask(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } else { + Render8x8Tile_Mask_FlipX_Clip(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } else { + Render8x8Tile_Mask_Clip(pDest, Code, x , y, Colour, 4, PC080SNFgTransparentPen[Chip], 0, pSrc); + } + } + } + } + } + + TileIndex++; + } + } +} + +void PC080SNSetScrollX(INT32 Chip, UINT32 Offset, UINT16 Data) +{ + PC080SNCtrl[Chip][Offset] = Data; + + switch (Offset) { + case 0: { + BgScrollX[Chip] = -Data; + break; + } + + case 1: { + FgScrollX[Chip] = -Data; + break; + } + } +} + +void PC080SNSetScrollY(INT32 Chip, UINT32 Offset, UINT16 Data) +{ + PC080SNCtrl[Chip][Offset + 2] = Data; + + if (PC080SNYInvert[Chip]) Data = -Data; + + switch (Offset) { + case 0: { + BgScrollY[Chip] = -Data; + break; + } + + case 1: { + FgScrollY[Chip] = -Data; + break; + } + } +} + +void PC080SNCtrlWrite(INT32 Chip, UINT32 Offset, UINT16 Data) +{ + PC080SNCtrl[Chip][Offset + 4] = Data; + + switch (Offset) { + case 0: { + if (Data & 1) bprintf(PRINT_NORMAL, _T("PC080SN Flipped\n")); + return; + } + } +} + +void PC080SNOverrideFgScroll(INT32 Chip, INT32 xScroll, INT32 yScroll) +{ + FgScrollX[Chip] = xScroll; + FgScrollY[Chip] = yScroll; +} + +void PC080SNReset() +{ + for (INT32 i = 0; i < PC080SNNum; i++) { + memset(PC080SNCtrl[i], 0, 8 * sizeof(UINT16)); + BgScrollX[i] = 0; + BgScrollY[i] = 0; + FgScrollX[i] = 0; + FgScrollY[i] = 0; + } +} + +void PC080SNInit(INT32 Chip, INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 yInvert, INT32 DblWidth) +{ + PC080SNRam[Chip] = (UINT8*)malloc(0x10000); + memset(PC080SNRam[Chip], 0, 0x10000); + + PC080SNNumTiles[Chip] = nNumTiles; + + PC080SNXOffset[Chip] = xOffset; + PC080SNYOffset[Chip] = yOffset; + + PC080SNFgTransparentPen[Chip] = 0; + PC080SNYInvert[Chip] = yInvert; + + TaitoIC_PC080SNInUse = 1; + + PC080SNCols[Chip] = 64; + if (DblWidth) PC080SNCols[Chip] = 128; + + PC080SNDblWidth[Chip] = DblWidth; + PC080SNNum++; +} + +void PC080SNSetFgTransparentPen(INT32 Chip, INT32 Pen) +{ + PC080SNFgTransparentPen[Chip] = Pen; +} + +void PC080SNExit() +{ + for (INT32 i = 0; i < PC080SNNum; i++) { + if (PC080SNRam[i]) { + free(PC080SNRam[i]); + PC080SNRam[i] = NULL; + } + + memset(PC080SNCtrl[i], 0, 8 * sizeof(UINT16)); + BgScrollX[i] = 0; + BgScrollY[i] = 0; + FgScrollX[i] = 0; + FgScrollY[i] = 0; + + PC080SNNumTiles[i] = 0; + PC080SNXOffset[i] = 0; + PC080SNYOffset[i] = 0; + PC080SNFgTransparentPen[i] = 0; + PC080SNYInvert[i] = 0; + PC080SNDblWidth[i] = 0; + PC080SNCols[i] = 0; + } + + PC080SNNum = 0; +} + +void PC080SNScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + for (INT32 i = 0; i < PC080SNNum; i++) { + memset(&ba, 0, sizeof(ba)); + ba.Data = PC080SNRam[i]; + ba.nLen = 0x10000; + ba.szName = "PC080SN Ram"; + BurnAcb(&ba); + } + } + + if (nAction & ACB_DRIVER_DATA) { + for (INT32 i = 0; i < PC080SNNum; i++) { + SCAN_VAR(PC080SNCtrl[i]); + SCAN_VAR(BgScrollX[i]); + SCAN_VAR(BgScrollY[i]); + SCAN_VAR(FgScrollX[i]); + SCAN_VAR(FgScrollY[i]); + } + } +} + +// Top Speed Custom support + +#define PLOTPIXEL_MASK(x, mc, po) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x] | po;} +#define PLOTPIXEL_MASK_FLIPX(x, a, mc, po) if (pTileData[a] != mc) {pPixel[x] = nPalette | pTileData[a] | po;} + +static void RenderTile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * 512) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += 512, pTileData += 8) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * 512) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += 512, pTileData += 8) { + PLOTPIXEL_MASK_FLIPX( 7, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 6, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 5, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 4, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 3, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 2, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 1, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 0, 7, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * 512) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= 512, pTileData += 8) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * 512) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= 512, pTileData += 8) { + PLOTPIXEL_MASK_FLIPX( 7, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 6, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 5, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 4, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 3, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 2, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 1, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 0, 7, nMaskColour, nPaletteOffset); + } +} + +#undef PLOTPIXEL_MASK +#undef PLOTPIXEL_MASK_FLIPX + +void TopspeedPC080SNDrawBgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest) +{ + INT32 mx, my, Offset, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)PC080SNRam[Chip] + 0x0000; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < PC080SNCols[Chip]; mx++) { + Offset = 2 * TileIndex; + if (!PC080SNDblWidth[Chip]) { + Attr = VideoRam[Offset + 0]; + Code = VideoRam[Offset + 1] & (PC080SNNumTiles[Chip] - 1); + } else { + Attr = VideoRam[TileIndex + 0x0000]; + Code = VideoRam[TileIndex + 0x2000] & 0x3fff; + } + Colour = Attr & 0x1ff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (xFlip) { + if (yFlip) { + RenderTile_Mask_FlipXY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask_FlipX(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_Mask_FlipY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } + + TileIndex++; + } + } +} + +void TopspeedPC080SNDrawFgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest) +{ + INT32 mx, my, Offset, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)PC080SNRam[Chip] + 0x4000; + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < PC080SNCols[Chip]; mx++) { + Offset = 2 * TileIndex; + if (!PC080SNDblWidth[Chip]) { + Attr = VideoRam[Offset + 0]; + Code = VideoRam[Offset + 1] & (PC080SNNumTiles[Chip] - 1); + } else { + Attr = VideoRam[TileIndex + 0x0000]; + Code = VideoRam[TileIndex + 0x2000] & 0x3fff; + } + Colour = Attr & 0x1ff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (xFlip) { + if (yFlip) { + RenderTile_Mask_FlipXY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask_FlipX(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_Mask_FlipY(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask(pDest, Code, x , y, Colour, 4, 0, 0, pSrc); + } + } + + TileIndex++; + } + } +} + +static inline void DrawScanLine(INT32 y, const UINT16 *src, INT32 Transparent, INT32 /*Pri*/) +{ + UINT16* pPixel; + INT32 Length; + + pPixel = pTransDraw + (y * nScreenWidth); + + Length = nScreenWidth; + + if (Transparent) { + while (Length--) { + UINT16 sPixel = *src++; + if (sPixel < 0x7fff) { + *pPixel = sPixel; + } + pPixel++; + } + } else { + while (Length--) { + *pPixel++ = *src++; + } + } +} + +static UINT16 TopspeedGetRoadPixelColour(UINT16 Pixel, UINT16 Colour) +{ + UINT16 RoadBodyColour, OffRoadColour, PixelType; + + PixelType = (Pixel % 0x10); + RoadBodyColour = (Pixel & 0x7ff0) + 4; + OffRoadColour = RoadBodyColour + 1; + + if ((Colour & 0xffe0) == 0xffe0) { + Pixel += 10; + RoadBodyColour += 10; + OffRoadColour += 10; + } else { + if (Colour & 0x10) RoadBodyColour += 5; + if (Colour & 0x02) OffRoadColour += 5; + } + + switch (PixelType) { + case 0x01: { + if (Colour & 0x08) Pixel = RoadBodyColour; + break; + } + + case 0x02: { + if (Colour & 0x08) Pixel = RoadBodyColour; + break; + } + + case 0x03: { + if (Colour & 0x04) Pixel = RoadBodyColour; + break; + } + + case 0x04: { + Pixel = RoadBodyColour; + break; + } + + case 0x05: { + Pixel = OffRoadColour; + break; + } + } + + return Pixel; +} + +void TopspeedDrawBgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest, UINT16 *ColourCtrlRam) +{ + memset(pDest, 0, 512 * 512 * sizeof(UINT16)); + TopspeedPC080SNDrawBgLayer(Chip, pSrc, pDest); + + UINT16 *BgScrollRam = NULL; + + if (!PC080SNDblWidth[Chip]) BgScrollRam = (UINT16*)PC080SNRam[Chip] + 0x2000; + + UINT16 *Dst16, *Src16; + UINT16 ScanLine[512]; + + UINT16 a, Colour; + INT32 sx, xIndex; + INT32 i, y, yIndex, ySrcIndex, RowIndex; + + INT32 min_x = 0; + INT32 max_x = nScreenWidth - 1; + INT32 min_y = 0; + INT32 max_y = nScreenHeight - 1; + INT32 ScreenWidth = max_x - min_x + 1; + INT32 WidthMask = 0x1ff; + + sx = (BgScrollX[Chip] & 0x1ff) + 16 - PC080SNXOffset[Chip]; + yIndex = (BgScrollY[Chip] & 0x1ff) + min_y + PC080SNYOffset[Chip]; + + y = min_y; + + do { + ySrcIndex = yIndex & 0x1ff; + RowIndex = (ySrcIndex - (BgScrollY[Chip] & 0x1ff)) & 0x1ff; + Colour = ColourCtrlRam[(RowIndex + PC080SNYOffset[Chip] - 2) & 0xff]; + + xIndex = sx - ((BgScrollRam[RowIndex] & 0x1ff)); + + Src16 = pDest + (ySrcIndex * 512); + Dst16 = ScanLine; + + for (i = 0; i < ScreenWidth; i++) { + if ((Src16[xIndex & WidthMask] & 0x0f) != 0) { + a = Src16[xIndex & WidthMask]; + a = TopspeedGetRoadPixelColour(a, Colour); + + *Dst16++ = a; + } else { + *Dst16++ = 0x8000; + } + + xIndex++; + } + + DrawScanLine(y, ScanLine, 1, 0); + + yIndex++; + y++; + } + while (y <= max_y); +} + +void TopspeedDrawFgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest, UINT16 *ColourCtrlRam) +{ + memset(pDest, 0, 512 * 512 * sizeof(UINT16)); + TopspeedPC080SNDrawFgLayer(Chip, pSrc, pDest); + + UINT16 *FgScrollRam = NULL; + + if (!PC080SNDblWidth[Chip]) FgScrollRam = (UINT16*)PC080SNRam[Chip] + 0x6000; + + UINT16 *Dst16, *Src16; + UINT16 ScanLine[512]; + + UINT16 a, Colour; + INT32 sx, xIndex; + INT32 i, y, yIndex, ySrcIndex, RowIndex; + + INT32 min_x = 0; + INT32 max_x = nScreenWidth - 1; + INT32 min_y = 0; + INT32 max_y = nScreenHeight - 1; + INT32 ScreenWidth = max_x - min_x + 1; + INT32 WidthMask = 0x1ff; + + sx = (FgScrollX[Chip] & 0x1ff) + 16 - PC080SNXOffset[Chip]; + yIndex = (FgScrollY[Chip] & 0x1ff) + min_y + PC080SNYOffset[Chip]; + + y = min_y; + + do { + ySrcIndex = yIndex & 0x1ff; + RowIndex = (ySrcIndex - (FgScrollY[Chip] & 0x1ff)) & 0x1ff; + Colour = ColourCtrlRam[(RowIndex + PC080SNYOffset[Chip] - 2) & 0xff]; + + xIndex = sx - ((FgScrollRam[RowIndex] & 0x1ff)); + + Src16 = pDest + (ySrcIndex * 512); + Dst16 = ScanLine; + + for (i = 0; i < ScreenWidth; i++) { + if ((Src16[xIndex & WidthMask] & 0x0f) != 0) { + a = Src16[xIndex & WidthMask]; + a = TopspeedGetRoadPixelColour(a, Colour); + + *Dst16++ = a; + } else { + *Dst16++ = 0x8000; + } + + xIndex++; + } + + DrawScanLine(y, ScanLine, 1, 0); + + yIndex++; + y++; + } + while (y <= max_y); +} diff --git a/src/burn/drivers/taito/pc090oj.cpp b/src/burn/drivers/taito/pc090oj.cpp new file mode 100644 index 00000000..a8d77d4d --- /dev/null +++ b/src/burn/drivers/taito/pc090oj.cpp @@ -0,0 +1,143 @@ +// PC090OJ + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *PC090OJRam = NULL; +static INT32 PC090OJNumTiles; +static INT32 PC090OJXOffset; +static INT32 PC090OJYOffset; +static INT32 PC090OJUseBuffer; +static INT32 PC090OJPaletteOffset; +INT32 PC090OJSpriteCtrl; + +void PC090OJDrawSprites(UINT8 *pSrc) +{ + UINT16 *VideoRam = (UINT16*)PC090OJRam; + + INT32 PC090OJCtrl = VideoRam[0xdff]; + + INT32 Offset; + INT32 SpriteColBank = (PC090OJSpriteCtrl & 0x0f) << 4; + + for (Offset = 0x400 - 4; Offset >= 0; Offset -= 4) + { + INT32 xFlip, yFlip; + INT32 x, y; + INT32 Data, Code, Colour; + + Data = VideoRam[Offset + 0]; + yFlip = (Data & 0x8000) >> 15; + xFlip = (Data & 0x4000) >> 14; + Colour = (Data & 0x000f) | SpriteColBank | PC090OJPaletteOffset; + + Code = VideoRam[Offset + 2] & 0x1fff; + if (Code >= PC090OJNumTiles) { + Code %= PC090OJNumTiles; // ok? Mod seems to work fine for bonze. + } + + x = VideoRam[Offset + 3] & 0x1ff; + y = VideoRam[Offset + 1] & 0x1ff; + + if (x > 0x140) x -= 0x200; + if (y > 0x140) y -= 0x200; + + if (!(PC090OJCtrl & 1)) { + x = 320 - x - 16; + y = 256 - y - 16; + xFlip = !xFlip; + yFlip = !yFlip; + } + + x -= PC090OJXOffset; + y -= PC090OJYOffset; + + if (x > 16 && x < (nScreenWidth - 16) && y > 16 && y < (nScreenHeight - 16)) { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } + } +} + +void PC090OJReset() +{ + PC090OJSpriteCtrl = 0; +} + +void PC090OJInit(INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 UseBuffer) +{ + PC090OJRam = (UINT8*)malloc(0x4000); + memset(PC090OJRam, 0, 0x4000); + + PC090OJNumTiles = nNumTiles; + + PC090OJXOffset = xOffset; + PC090OJYOffset = yOffset; + PC090OJUseBuffer = UseBuffer; + PC090OJPaletteOffset = 0; + + TaitoIC_PC090OJInUse = 1; +} + +void PC090OJSetPaletteOffset(INT32 Offset) +{ + PC090OJPaletteOffset = Offset; +} + +void PC090OJExit() +{ + if (PC090OJRam) { + free(PC090OJRam); + PC090OJRam = NULL; + } + + PC090OJNumTiles = 0; + PC090OJXOffset = 0; + PC090OJYOffset = 0; + PC090OJUseBuffer = 0; + PC090OJPaletteOffset = 0; + + PC090OJSpriteCtrl = 0; +} + +void PC090OJScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = PC090OJRam; + ba.nLen = 0x4000; + ba.szName = "PC090OJ Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(PC090OJSpriteCtrl); + } +} diff --git a/src/burn/drivers/taito/taito.cpp b/src/burn/drivers/taito/taito.cpp new file mode 100644 index 00000000..d62f959f --- /dev/null +++ b/src/burn/drivers/taito/taito.cpp @@ -0,0 +1,996 @@ +#include "tiles_generic.h" +#include "taito.h" +#include "taito_ic.h" +#include "burn_ym2151.h" +#include "burn_ym2610.h" +#include "burn_ym2203.h" +#include "msm5205.h" +#include "msm6295.h" +#include "eeprom.h" +#include "burn_gun.h" + +UINT8 TaitoInputPort0[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoInputPort1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoInputPort2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoInputPort3[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoInputPort4[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoInputPort5[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoDip[2] = { 0, 0 }; +UINT8 TaitoInput[6] = { 0, 0, 0, 0, 0, 0 }; +UINT8 TaitoReset = 0; + +UINT8 TaitoCoinLockout[4] = { 0, 0, 0, 0 }; + +INT32 TaitoAnalogPort0 = 0; +INT32 TaitoAnalogPort1 = 0; +INT32 TaitoAnalogPort2 = 0; +INT32 TaitoAnalogPort3 = 0; + +UINT8 *TaitoMem = NULL; +UINT8 *TaitoMemEnd = NULL; +UINT8 *TaitoRamStart = NULL; +UINT8 *TaitoRamEnd = NULL; +UINT8 *Taito68KRam1 = NULL; +UINT8 *Taito68KRam2 = NULL; +UINT8 *Taito68KRam3 = NULL; +UINT8 *TaitoSharedRam = NULL; +UINT8 *TaitoZ80Ram1 = NULL; +UINT8 *TaitoZ80Ram2 = NULL; +UINT8 *TaitoPaletteRam = NULL; +UINT8 *TaitoSpriteRam = NULL; +UINT8 *TaitoSpriteRam2 = NULL; +UINT8 *TaitoSpriteRamBuffered = NULL; +UINT8 *TaitoSpriteRamDelayed = NULL; +UINT8 *TaitoSpriteExtension = NULL; +UINT8 *TaitoVideoRam = NULL; +UINT32 *TaitoPalette = NULL; +UINT8 *TaitoPriorityMap = NULL; + +UINT8 TaitoZ80Bank = 0; +UINT8 TaitoSoundLatch = 0; +UINT16 TaitoCpuACtrl = 0; +INT32 TaitoRoadPalBank = 0; + +INT32 TaitoXOffset = 0; +INT32 TaitoYOffset = 0; +INT32 TaitoIrqLine = 0; +INT32 TaitoFrameInterleave = 0; +INT32 TaitoFlipScreenX = 0; + +INT32 TaitoNum68Ks = 0; +INT32 TaitoNumZ80s = 0; +INT32 TaitoNumYM2610 = 0; +INT32 TaitoNumYM2151 = 0; +INT32 TaitoNumYM2203 = 0; +INT32 TaitoNumMSM5205 = 0; +INT32 TaitoNumMSM6295 = 0; +INT32 TaitoNumES5505 = 0; +INT32 TaitoNumEEPROM = 0; + +INT32 nTaitoCyclesDone[4], nTaitoCyclesTotal[4]; +INT32 nTaitoCyclesSegment; + +TaitoRender TaitoDrawFunction; +TaitoMakeInputs TaitoMakeInputsFunction; +TaitoResetFunc TaitoResetFunction; + +INT32 TaitoDoReset() +{ + INT32 i; + + for (i = 0; i < TaitoNum68Ks; i++) { + SekOpen(i); + SekReset(); + SekClose(); + } + + for (i = 0; i < TaitoNumZ80s; i++) { + ZetOpen(i); + ZetReset(); + ZetClose(); + } + + if (TaitoNumYM2610) BurnYM2610Reset(); + if (TaitoNumYM2151) BurnYM2151Reset(); + if (TaitoNumYM2203) BurnYM2203Reset(); + + if (TaitoNumMSM5205) MSM5205Reset(); + + for (i = 0; i < TaitoNumMSM6295; i++) { + MSM6295Reset(i); + } + + if (TaitoNumEEPROM) EEPROMReset(); + + TaitoICReset(); + + TaitoZ80Bank = 0; + TaitoSoundLatch = 0; + TaitoRoadPalBank = 0; + TaitoCpuACtrl = 0xff; + + memset (TaitoCoinLockout, 0, 4); + + return 0; +} + +UINT8 *Taito68KRom1 = NULL; +UINT8 *Taito68KRom2 = NULL; +UINT8 *Taito68KRom3 = NULL; +UINT8 *TaitoZ80Rom1 = NULL; +UINT8 *TaitoZ80Rom2 = NULL; +UINT8 *TaitoChars = NULL; +UINT8 *TaitoCharsB = NULL; +UINT8 *TaitoCharsPivot = NULL; +UINT8 *TaitoSpritesA = NULL; +UINT8 *TaitoSpritesB = NULL; +UINT8 *TaitoSpriteMapRom = NULL; +UINT8 *TaitoYM2610ARom = NULL; +UINT8 *TaitoYM2610BRom = NULL; +UINT8 *TaitoMSM5205Rom = NULL; +UINT8 *TaitoMSM6295Rom = NULL; +UINT8 *TaitoES5505Rom = NULL; +UINT8 *TaitoDefaultEEProm = NULL; + +UINT32 Taito68KRom1Num = 0; +UINT32 Taito68KRom2Num = 0; +UINT32 Taito68KRom3Num = 0; +UINT32 TaitoZ80Rom1Num = 0; +UINT32 TaitoZ80Rom2Num = 0; +UINT32 TaitoCharRomNum = 0; +UINT32 TaitoCharBRomNum = 0; +UINT32 TaitoCharPivotRomNum = 0; +UINT32 TaitoSpriteARomNum = 0; +UINT32 TaitoSpriteBRomNum = 0; +UINT32 TaitoRoadRomNum = 0; +UINT32 TaitoSpriteMapRomNum = 0; +UINT32 TaitoYM2610ARomNum = 0; +UINT32 TaitoYM2610BRomNum = 0; +UINT32 TaitoMSM5205RomNum = 0; +UINT32 TaitoMSM6295RomNum = 0; +UINT32 TaitoES5505RomNum = 0; +UINT32 TaitoDefaultEEPromNum = 0; + +UINT32 Taito68KRom1Size = 0; +UINT32 Taito68KRom2Size = 0; +UINT32 Taito68KRom3Size = 0; +UINT32 TaitoZ80Rom1Size = 0; +UINT32 TaitoZ80Rom2Size = 0; +UINT32 TaitoCharRomSize = 0; +UINT32 TaitoCharBRomSize = 0; +UINT32 TaitoCharPivotRomSize = 0; +UINT32 TaitoSpriteARomSize = 0; +UINT32 TaitoSpriteBRomSize = 0; +UINT32 TaitoRoadRomSize = 0; +UINT32 TaitoSpriteMapRomSize = 0; +UINT32 TaitoYM2610ARomSize = 0; +UINT32 TaitoYM2610BRomSize = 0; +UINT32 TaitoMSM5205RomSize = 0; +UINT32 TaitoMSM6295RomSize = 0; +UINT32 TaitoES5505RomSize = 0; +UINT32 TaitoDefaultEEPromSize = 0; + +UINT32 TaitoCharModulo = 0; +UINT32 TaitoCharNumPlanes = 0; +UINT32 TaitoCharWidth = 0; +UINT32 TaitoCharHeight = 0; +UINT32 TaitoNumChar = 0; +INT32 *TaitoCharPlaneOffsets = NULL; +INT32 *TaitoCharXOffsets = NULL; +INT32 *TaitoCharYOffsets = NULL; + +UINT32 TaitoCharBModulo = 0; +UINT32 TaitoCharBNumPlanes = 0; +UINT32 TaitoCharBWidth = 0; +UINT32 TaitoCharBHeight = 0; +UINT32 TaitoNumCharB = 0; +INT32 *TaitoCharBPlaneOffsets = NULL; +INT32 *TaitoCharBXOffsets = NULL; +INT32 *TaitoCharBYOffsets = NULL; + +UINT32 TaitoCharPivotModulo = 0; +UINT32 TaitoCharPivotNumPlanes = 0; +UINT32 TaitoCharPivotWidth = 0; +UINT32 TaitoCharPivotHeight = 0; +UINT32 TaitoNumCharPivot = 0; +INT32 *TaitoCharPivotPlaneOffsets = NULL; +INT32 *TaitoCharPivotXOffsets = NULL; +INT32 *TaitoCharPivotYOffsets = NULL; + +UINT32 TaitoSpriteAModulo = 0; +UINT32 TaitoSpriteANumPlanes = 0; +UINT32 TaitoSpriteAWidth = 0; +UINT32 TaitoSpriteAHeight = 0; +UINT32 TaitoNumSpriteA = 0; +INT32 *TaitoSpriteAPlaneOffsets = NULL; +INT32 *TaitoSpriteAXOffsets = NULL; +INT32 *TaitoSpriteAYOffsets = NULL; +INT32 TaitoSpriteAInvertRom = 0; + +UINT32 TaitoSpriteBModulo = 0; +UINT32 TaitoSpriteBNumPlanes = 0; +UINT32 TaitoSpriteBWidth = 0; +UINT32 TaitoSpriteBHeight = 0; +UINT32 TaitoNumSpriteB = 0; +INT32 *TaitoSpriteBPlaneOffsets = NULL; +INT32 *TaitoSpriteBXOffsets = NULL; +INT32 *TaitoSpriteBYOffsets = NULL; + +INT32 TaitoLoadRoms(INT32 bLoad) +{ + struct BurnRomInfo ri; + ri.nType = 0; + ri.nLen = 0; + INT32 nOffset = -1; + UINT32 i = 0; + INT32 nRet = 0; + + if (!bLoad) { + do { + ri.nLen = 0; + ri.nType = 0; + BurnDrvGetRomInfo(&ri, ++nOffset); + if ((ri.nType & 0xff) == TAITO_68KROM1 || (ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP || (ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP_JUMPING || (ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP32) { + Taito68KRom1Size += ri.nLen; + Taito68KRom1Num++; + } + if ((ri.nType & 0xff) == TAITO_68KROM2 || (ri.nType & 0xff) == TAITO_68KROM2_BYTESWAP) { + Taito68KRom2Size += ri.nLen; + Taito68KRom2Num++; + } + if ((ri.nType & 0xff) == TAITO_68KROM3 || (ri.nType & 0xff) == TAITO_68KROM3_BYTESWAP) { + Taito68KRom3Size += ri.nLen; + Taito68KRom3Num++; + } + if ((ri.nType & 0xff) == TAITO_Z80ROM1) { + TaitoZ80Rom1Size += ri.nLen; + TaitoZ80Rom1Num++; + } + if ((ri.nType & 0xff) == TAITO_Z80ROM2) { + TaitoZ80Rom2Size += ri.nLen; + TaitoZ80Rom2Num++; + } + if ((ri.nType & 0xff) == TAITO_CHARS || (ri.nType & 0xff) == TAITO_CHARS_BYTESWAP) { + TaitoCharRomSize += ri.nLen; + TaitoCharRomNum++; + } + if ((ri.nType & 0xff) == TAITO_CHARSB || (ri.nType & 0xff) == TAITO_CHARSB_BYTESWAP) { + TaitoCharBRomSize += ri.nLen; + TaitoCharBRomNum++; + } + if ((ri.nType & 0xff) == TAITO_SPRITESA || (ri.nType & 0xff) == TAITO_SPRITESA_BYTESWAP || (ri.nType & 0xff) == TAITO_SPRITESA_BYTESWAP32 || (ri.nType & 0xff) == TAITO_SPRITESA_TOPSPEED) { + TaitoSpriteARomSize += ri.nLen; + TaitoSpriteARomNum++; + } + if ((ri.nType & 0xff) == TAITO_SPRITESB || (ri.nType & 0xff) == TAITO_SPRITESB_BYTESWAP || (ri.nType & 0xff) == TAITO_SPRITESB_BYTESWAP32) { + TaitoSpriteBRomSize += ri.nLen; + TaitoSpriteBRomNum++; + } + if ((ri.nType & 0xff) == TAITO_ROAD) { + TaitoRoadRomSize += ri.nLen; + TaitoRoadRomNum++; + } + if ((ri.nType & 0xff) == TAITO_SPRITEMAP) { + TaitoSpriteMapRomSize += ri.nLen; + TaitoSpriteMapRomNum++; + } + if ((ri.nType & 0xff) == TAITO_YM2610A) { + TaitoYM2610ARomSize += ri.nLen; + TaitoYM2610ARomNum++; + } + if ((ri.nType & 0xff) == TAITO_YM2610B) { + TaitoYM2610BRomSize += ri.nLen; + TaitoYM2610BRomNum++; + } + if ((ri.nType & 0xff) == TAITO_MSM5205 || (ri.nType & 0xff) == TAITO_MSM5205_BYTESWAP) { + TaitoMSM5205RomSize += ri.nLen; + TaitoMSM5205RomNum++; + } + if ((ri.nType & 0xff) == TAITO_CHARS_PIVOT) { + TaitoCharPivotRomSize += ri.nLen; + TaitoCharPivotRomNum++; + } + if ((ri.nType & 0xff) == TAITO_MSM6295) { + TaitoMSM6295RomSize += ri.nLen; + TaitoMSM6295RomNum++; + } + if ((ri.nType & 0xff) == TAITO_ES5505 || (ri.nType & 0xff) == TAITO_ES5505_BYTESWAP) { + TaitoES5505RomSize += ri.nLen; + TaitoES5505RomNum++; + } + if ((ri.nType & 0xff) == TAITO_DEFAULT_EEPROM) { + TaitoDefaultEEPromSize += ri.nLen; + TaitoDefaultEEPromNum++; + } + } while (ri.nLen); + +#if 1 && defined FBA_DEBUG + if (Taito68KRom1Size) bprintf(PRINT_IMPORTANT, _T("68K #1 Rom Length %06X, (%i roms)\n"), Taito68KRom1Size, Taito68KRom1Num); + if (Taito68KRom2Size) bprintf(PRINT_IMPORTANT, _T("68K #2 Rom Length %06X, (%i roms)\n"), Taito68KRom2Size, Taito68KRom2Num); + if (Taito68KRom3Size) bprintf(PRINT_IMPORTANT, _T("68K #3 Rom Length %06X, (%i roms)\n"), Taito68KRom3Size, Taito68KRom3Num); + if (TaitoZ80Rom1Size) bprintf(PRINT_IMPORTANT, _T("Z80 #1 Rom Length %06X, (%i roms)\n"), TaitoZ80Rom1Size, TaitoZ80Rom1Num); + if (TaitoZ80Rom2Size) bprintf(PRINT_IMPORTANT, _T("Z80 #2 Rom Length %06X, (%i roms)\n"), TaitoZ80Rom2Size, TaitoZ80Rom2Num); + if (TaitoCharRomSize) bprintf(PRINT_IMPORTANT, _T("Char Rom Length %08X, (%i roms, 0x%06X tiles)\n"), TaitoCharRomSize, TaitoCharRomNum, TaitoNumChar); + if (TaitoCharBRomSize) bprintf(PRINT_IMPORTANT, _T("Char B Rom Length %08X, (%i roms, 0x%06X tiles)\n"), TaitoCharBRomSize, TaitoCharBRomNum, TaitoNumCharB); + if (TaitoSpriteARomSize) bprintf(PRINT_IMPORTANT, _T("Sprite A Rom Length %08X, (%i roms, 0x%06X tiles)\n"), TaitoSpriteARomSize, TaitoSpriteARomNum, TaitoNumSpriteA); + if (TaitoSpriteBRomSize) bprintf(PRINT_IMPORTANT, _T("Sprite B Rom Length %08X, (%i roms, 0x%06X tiles)\n"), TaitoSpriteBRomSize, TaitoSpriteBRomNum, TaitoNumSpriteB); + if (TaitoRoadRomSize) bprintf(PRINT_IMPORTANT, _T("Road Rom Length %08X, (%i roms)\n"), TaitoRoadRomSize, TaitoRoadRomNum); + if (TaitoSpriteMapRomSize) bprintf(PRINT_IMPORTANT, _T("Sprite Map Rom Length %08X, (%i roms)\n"), TaitoSpriteMapRomSize, TaitoSpriteMapRomNum); + if (TaitoYM2610ARomSize) bprintf(PRINT_IMPORTANT, _T("YM2610 Samples Rom Length %08X, (%i roms)\n"), TaitoYM2610ARomSize, TaitoYM2610ARomNum); + if (TaitoYM2610BRomSize) bprintf(PRINT_IMPORTANT, _T("YM2610 Delta-T Rom Length %08X, (%i roms)\n"), TaitoYM2610BRomSize, TaitoYM2610BRomNum); + if (TaitoMSM5205RomSize) bprintf(PRINT_IMPORTANT, _T("MSM5205 Rom Length %08X, (%i roms)\n"), TaitoMSM5205RomSize, TaitoMSM5205RomNum); + if (TaitoCharPivotRomSize) bprintf(PRINT_IMPORTANT, _T("Pivot Char Rom Length %08X, (%i roms, 0x%06X tiles)\n"), TaitoCharPivotRomSize, TaitoCharPivotRomNum, TaitoNumCharPivot); + if (TaitoMSM6295RomSize) bprintf(PRINT_IMPORTANT, _T("MSM6295 Rom Length %08X, (%i roms)\n"), TaitoMSM6295RomSize, TaitoMSM6295RomNum); + if (TaitoES5505RomSize) bprintf(PRINT_IMPORTANT, _T("ES5505 Rom Length %08X, (%i roms)\n"), TaitoES5505RomSize, TaitoES5505RomNum); + if (TaitoDefaultEEPromSize) bprintf(PRINT_IMPORTANT, _T("Default EEPROM Length %08X, (%i roms)\n"), TaitoDefaultEEPromSize, TaitoDefaultEEPromNum); +#endif + } + + if (bLoad) { + INT32 Offset = 0; + + i = 0; + while (i < Taito68KRom1Num) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP) { + nRet = BurnLoadRom(Taito68KRom1 + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom1 + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP32) { + nRet = BurnLoadRom(Taito68KRom1 + Offset + 1, i + 0, 4); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom1 + Offset + 0, i + 1, 4); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom1 + Offset + 3, i + 2, 4); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom1 + Offset + 2, i + 3, 4); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + + i += 4; + } + + if ((ri.nType & 0xff) == TAITO_68KROM1_BYTESWAP_JUMPING) { + nRet = BurnLoadRom(Taito68KRom1 + Offset + 0, i + 0, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_68KROM1) { + nRet = BurnLoadRom(Taito68KRom1 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + + if (Taito68KRom2Size) { + Offset = 0; + i = Taito68KRom1Num; + + while (i < Taito68KRom1Num + Taito68KRom2Num) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_68KROM2_BYTESWAP) { + nRet = BurnLoadRom(Taito68KRom2 + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom2 + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == TAITO_68KROM2) { + nRet = BurnLoadRom(Taito68KRom2 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + } + + if (Taito68KRom3Size) { + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_68KROM3_BYTESWAP) { + nRet = BurnLoadRom(Taito68KRom3 + Offset + 1, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(Taito68KRom3 + Offset + 0, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == TAITO_68KROM3) { + nRet = BurnLoadRom(Taito68KRom3 + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + } + + if (TaitoZ80Rom1Size) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num; i++) { + BurnLoadRom(TaitoZ80Rom1 + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoZ80Rom2Size) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num; i++) { + BurnLoadRom(TaitoZ80Rom2 + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoCharRomSize) { + UINT8 *TempRom = (UINT8*)malloc(TaitoCharRomSize); + memset(TempRom, 0, TaitoCharRomSize); + + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_CHARS) { + nRet = BurnLoadRom(TempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_CHARS_BYTESWAP) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + } + + if (TaitoNumChar) { + GfxDecode(TaitoNumChar, TaitoCharNumPlanes, TaitoCharWidth, TaitoCharHeight, TaitoCharPlaneOffsets, TaitoCharXOffsets, TaitoCharYOffsets, TaitoCharModulo, TempRom, TaitoChars); + } else { + memcpy (TaitoChars, TempRom, Offset); + } + + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + } + + if (TaitoCharBRomSize) { + UINT8 *TempRom = (UINT8*)malloc(TaitoCharBRomSize); + memset(TempRom, 0, TaitoCharBRomSize); + + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_CHARSB) { + nRet = BurnLoadRom(TempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_CHARSB_BYTESWAP) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + } + + GfxDecode(TaitoNumCharB, TaitoCharBNumPlanes, TaitoCharBWidth, TaitoCharBHeight, TaitoCharBPlaneOffsets, TaitoCharBXOffsets, TaitoCharBYOffsets, TaitoCharBModulo, TempRom, TaitoCharsB); + + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + } + + if (TaitoSpriteARomSize) { + UINT8 *TempRom = (UINT8*)malloc(TaitoSpriteARomSize); + memset(TempRom, 0, TaitoSpriteARomSize); + + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_SPRITESA) { + nRet = BurnLoadRom(TempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_SPRITESA_BYTESWAP) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == TAITO_SPRITESA_BYTESWAP32) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 2, i + 2, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 3, i + 3, 4); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + + i += 4; + } + + if ((ri.nType & 0xff) == TAITO_SPRITESA_TOPSPEED) { + nRet = BurnLoadRom(TempRom + 0x000003, i + 0, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100003, i + 1, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000007, i + 2, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100007, i + 3, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000002, i + 4, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100002, i + 5, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000006, i + 6, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100006, i + 7, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000001, i + 8, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100001, i + 9, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000005, i + 10, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100005, i + 11, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000000, i + 12, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100000, i + 13, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x000004, i + 14, 8); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + 0x100004, i + 15, 8); if (nRet) return 1; + + i += 16; + } + } + + if (TaitoSpriteAInvertRom) { + for (UINT32 j = 0; j < TaitoSpriteARomSize; j++) { + TempRom[j] ^= 0xff; + } + } + + if (TaitoNumSpriteA) { + GfxDecode(TaitoNumSpriteA, TaitoSpriteANumPlanes, TaitoSpriteAWidth, TaitoSpriteAHeight, TaitoSpriteAPlaneOffsets, TaitoSpriteAXOffsets, TaitoSpriteAYOffsets, TaitoSpriteAModulo, TempRom, TaitoSpritesA); + } else { + memcpy (TaitoSpritesA, TempRom, Offset); + } + + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + } + + if (TaitoSpriteBRomSize) { + UINT8 *TempRom = (UINT8*)malloc(TaitoSpriteBRomSize); + memset(TempRom, 0, TaitoSpriteBRomSize); + + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_SPRITESB) { + nRet = BurnLoadRom(TempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_SPRITESB_BYTESWAP) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + + if ((ri.nType & 0xff) == TAITO_SPRITESB_BYTESWAP32) { + nRet = BurnLoadRom(TempRom + Offset + 0, i + 0, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 1, i + 1, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 2, i + 2, 4); if (nRet) return 1; + nRet = BurnLoadRom(TempRom + Offset + 3, i + 3, 4); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 2); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 3); + Offset += ri.nLen; + + i += 4; + } + } + + GfxDecode(TaitoNumSpriteB, TaitoSpriteBNumPlanes, TaitoSpriteBWidth, TaitoSpriteBHeight, TaitoSpriteBPlaneOffsets, TaitoSpriteBXOffsets, TaitoSpriteBYOffsets, TaitoSpriteBModulo, TempRom, TaitoSpritesB); + + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + } + + if (TaitoRoadRomSize) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum; i++) { + BurnLoadRom(TC0150RODRom + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoSpriteMapRomSize) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum; i++) { + BurnLoadRom(TaitoSpriteMapRom + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoYM2610ARomSize) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum; i++) { + BurnLoadRom(TaitoYM2610ARom + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoYM2610BRomSize) { + Offset = 0; + for (i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum; i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum; i++) { + BurnLoadRom(TaitoYM2610BRom + Offset, i, 1); + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + } + } + + if (TaitoMSM5205RomSize) { + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_MSM5205) { + nRet = BurnLoadRom(TaitoMSM5205Rom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_MSM5205_BYTESWAP) { + nRet = BurnLoadRom(TaitoMSM5205Rom + Offset + 0, i + 0, 2); if (nRet) return 1; + nRet = BurnLoadRom(TaitoMSM5205Rom + Offset + 1, i + 1, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i + 0); + Offset += ri.nLen; + BurnDrvGetRomInfo(&ri, i + 1); + Offset += ri.nLen; + + i += 2; + } + } + } + + if (TaitoCharPivotRomSize) { + UINT8 *TempRom = (UINT8*)malloc(TaitoCharPivotRomSize); + memset(TempRom, 0, TaitoCharPivotRomSize); + + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_CHARS_PIVOT) { + nRet = BurnLoadRom(TempRom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + + GfxDecode(TaitoNumCharPivot, TaitoCharPivotNumPlanes, TaitoCharPivotWidth, TaitoCharPivotHeight, TaitoCharPivotPlaneOffsets, TaitoCharPivotXOffsets, TaitoCharPivotYOffsets, TaitoCharPivotModulo, TempRom, TaitoCharsPivot); + + if (TempRom) { + free(TempRom); + TempRom = NULL; + } + } + + if (TaitoMSM6295RomSize) { + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum + TaitoMSM6295RomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_MSM6295) { + nRet = BurnLoadRom(TaitoMSM6295Rom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + } + + if (TaitoES5505RomSize) { + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum + TaitoMSM6295RomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum + TaitoMSM6295RomNum + TaitoES5505RomNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_ES5505) { + nRet = BurnLoadRom(TaitoES5505Rom + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + + if ((ri.nType & 0xff) == TAITO_ES5505_BYTESWAP) { + nRet = BurnLoadRom(TaitoES5505Rom + (Offset * 2), i, 2); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + } + + if (TaitoDefaultEEPromSize) { + Offset = 0; + i = Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum + TaitoMSM6295RomNum + TaitoES5505RomNum; + + while (i < Taito68KRom1Num + Taito68KRom2Num + Taito68KRom3Num + TaitoZ80Rom1Num + TaitoZ80Rom2Num + TaitoCharRomNum + TaitoCharBRomNum + TaitoSpriteARomNum + TaitoSpriteBRomNum + TaitoRoadRomNum + TaitoSpriteMapRomNum + TaitoYM2610ARomNum + TaitoYM2610BRomNum + TaitoMSM5205RomNum + TaitoCharPivotRomNum + TaitoMSM6295RomNum + TaitoES5505RomNum + TaitoDefaultEEPromNum) { + BurnDrvGetRomInfo(&ri, i + 0); + + if ((ri.nType & 0xff) == TAITO_DEFAULT_EEPROM) { + nRet = BurnLoadRom(TaitoDefaultEEProm + Offset, i, 1); if (nRet) return 1; + + BurnDrvGetRomInfo(&ri, i); + Offset += ri.nLen; + + i++; + } + } + } + } + + return 0; +} + +INT32 TaitoExit() +{ + INT32 i; + + if (TaitoNum68Ks) SekExit(); + if (TaitoNumZ80s) ZetExit(); + if (TaitoNumYM2610) BurnYM2610Exit(); + if (TaitoNumYM2151) BurnYM2151Exit(); + if (TaitoNumYM2203) BurnYM2203Exit(); + if (TaitoNumMSM5205) MSM5205Exit(); + for (i = 0; i < TaitoNumMSM6295; i++) { + MSM6295Exit(i); + } + if (TaitoNumEEPROM) EEPROMExit(); + + TaitoICExit(); + + GenericTilesExit(); + BurnGunExit(); + + if (TaitoMem) { + free(TaitoMem); + TaitoMem = NULL; + } + + Taito68KRom1Num = 0; + Taito68KRom2Num = 0; + Taito68KRom3Num = 0; + TaitoZ80Rom1Num = 0; + TaitoZ80Rom2Num = 0; + TaitoCharRomNum = 0; + TaitoCharBRomNum = 0; + TaitoCharPivotRomNum = 0; + TaitoSpriteARomNum = 0; + TaitoSpriteBRomNum = 0; + TaitoRoadRomNum = 0; + TaitoSpriteMapRomNum = 0; + TaitoYM2610ARomNum = 0; + TaitoYM2610BRomNum = 0; + TaitoMSM5205RomNum = 0; + TaitoMSM6295RomNum = 0; + TaitoES5505RomNum = 0; + TaitoDefaultEEPromNum = 0; + + Taito68KRom1Size = 0; + Taito68KRom2Size = 0; + Taito68KRom3Size = 0; + TaitoZ80Rom1Size = 0; + TaitoZ80Rom2Size = 0; + TaitoCharRomSize = 0; + TaitoCharBRomSize = 0; + TaitoCharPivotRomSize = 0; + TaitoSpriteARomSize = 0; + TaitoSpriteBRomSize = 0; + TaitoRoadRomSize = 0; + TaitoSpriteMapRomSize = 0; + TaitoYM2610ARomSize = 0; + TaitoYM2610BRomSize = 0; + TaitoMSM5205RomSize = 0; + TaitoMSM6295RomSize = 0; + TaitoES5505RomSize = 0; + TaitoDefaultEEPromSize = 0; + + TaitoCharModulo = 0; + TaitoCharNumPlanes = 0; + TaitoCharWidth = 0; + TaitoCharHeight = 0; + TaitoNumChar = 0; + TaitoCharPlaneOffsets = NULL; + TaitoCharXOffsets = NULL; + TaitoCharYOffsets = NULL; + + TaitoCharBModulo = 0; + TaitoCharBNumPlanes = 0; + TaitoCharBWidth = 0; + TaitoCharBHeight = 0; + TaitoNumCharB = 0; + TaitoCharBPlaneOffsets = NULL; + TaitoCharBXOffsets = NULL; + TaitoCharBYOffsets = NULL; + + TaitoCharPivotModulo = 0; + TaitoCharPivotNumPlanes = 0; + TaitoCharPivotWidth = 0; + TaitoCharPivotHeight = 0; + TaitoNumCharPivot = 0; + TaitoCharPivotPlaneOffsets = NULL; + TaitoCharPivotXOffsets = NULL; + TaitoCharPivotYOffsets = NULL; + + TaitoSpriteAModulo = 0; + TaitoSpriteANumPlanes = 0; + TaitoSpriteAWidth = 0; + TaitoSpriteAHeight = 0; + TaitoNumSpriteA = 0; + TaitoSpriteAPlaneOffsets = NULL; + TaitoSpriteAXOffsets = NULL; + TaitoSpriteAYOffsets = NULL; + TaitoSpriteAInvertRom = 0; + + TaitoSpriteBModulo = 0; + TaitoSpriteBNumPlanes = 0; + TaitoSpriteBWidth = 0; + TaitoSpriteBHeight = 0; + TaitoNumSpriteB = 0; + TaitoSpriteBPlaneOffsets = NULL; + TaitoSpriteBXOffsets = NULL; + TaitoSpriteBYOffsets = NULL; + + TaitoZ80Bank = 0; + TaitoSoundLatch = 0; + TaitoRoadPalBank = 0; + TaitoCpuACtrl = 0; + + TaitoXOffset = 0; + TaitoYOffset = 0; + TaitoIrqLine = 0; + TaitoFrameInterleave = 0; + TaitoFlipScreenX = 0; + + TaitoNum68Ks = 0; + TaitoNumZ80s = 0; + TaitoNumYM2610 = 0; + TaitoNumYM2151 = 0; + TaitoNumYM2203 = 0; + TaitoNumMSM5205 = 0; + TaitoNumMSM6295 = 0; + TaitoNumES5505 = 0; + TaitoNumEEPROM = 0; + + TaitoDrawFunction = NULL; + TaitoMakeInputsFunction = NULL; + TaitoResetFunction = NULL; + + return 0; +} diff --git a/src/burn/drivers/taito/taito.h b/src/burn/drivers/taito/taito.h new file mode 100644 index 00000000..53342eaf --- /dev/null +++ b/src/burn/drivers/taito/taito.h @@ -0,0 +1,241 @@ +extern UINT8 TaitoInputPort0[8]; +extern UINT8 TaitoInputPort1[8]; +extern UINT8 TaitoInputPort2[8]; +extern UINT8 TaitoInputPort3[8]; +extern UINT8 TaitoInputPort4[8]; +extern UINT8 TaitoInputPort5[8]; +extern UINT8 TaitoDip[2]; +extern UINT8 TaitoInput[6]; +extern UINT8 TaitoReset; +extern UINT8 TaitoCoinLockout[4]; + +extern INT32 TaitoAnalogPort0; +extern INT32 TaitoAnalogPort1; +extern INT32 TaitoAnalogPort2; +extern INT32 TaitoAnalogPort3; + +extern UINT8 *TaitoMem; +extern UINT8 *TaitoMemEnd; +extern UINT8 *TaitoRamStart; +extern UINT8 *TaitoRamEnd; +extern UINT8 *Taito68KRam1; +extern UINT8 *Taito68KRam2; +extern UINT8 *Taito68KRam3; +extern UINT8 *TaitoSharedRam; +extern UINT8 *TaitoZ80Ram1; +extern UINT8 *TaitoZ80Ram2; +extern UINT8 *TaitoPaletteRam; +extern UINT8 *TaitoSpriteRam; +extern UINT8 *TaitoSpriteRam2; +extern UINT8 *TaitoSpriteRamBuffered; +extern UINT8 *TaitoSpriteRamDelayed; +extern UINT8 *TaitoSpriteExtension; +extern UINT8 *TaitoVideoRam; +extern UINT32 *TaitoPalette; +extern UINT8 *TaitoPriorityMap; + +extern UINT8 TaitoZ80Bank; +extern UINT8 TaitoSoundLatch; +extern UINT16 TaitoCpuACtrl; +extern INT32 TaitoRoadPalBank; + +extern INT32 TaitoXOffset; +extern INT32 TaitoYOffset; +extern INT32 TaitoIrqLine; +extern INT32 TaitoFrameInterleave; +extern INT32 TaitoNumEEPROM; +extern INT32 TaitoFlipScreenX; + +extern INT32 TaitoNum68Ks; +extern INT32 TaitoNumZ80s; +extern INT32 TaitoNumYM2610; +extern INT32 TaitoNumYM2151; +extern INT32 TaitoNumYM2203; +extern INT32 TaitoNumMSM5205; +extern INT32 TaitoNumMSM6295; +extern INT32 TaitoNumES5505; + +extern INT32 nTaitoCyclesDone[4], nTaitoCyclesTotal[4]; +extern INT32 nTaitoCyclesSegment; + +typedef void (*TaitoRender)(); +extern TaitoRender TaitoDrawFunction; +typedef void (*TaitoMakeInputs)(); +extern TaitoMakeInputs TaitoMakeInputsFunction; +typedef INT32 (*TaitoResetFunc)(); +extern TaitoResetFunc TaitoResetFunction; + +extern INT32 TaitoDoReset(); + +#define TAITO_68KROM1 1 +#define TAITO_68KROM1_BYTESWAP 2 +#define TAITO_68KROM1_BYTESWAP_JUMPING 3 +#define TAITO_68KROM1_BYTESWAP32 4 +#define TAITO_68KROM2 5 +#define TAITO_68KROM2_BYTESWAP 6 +#define TAITO_68KROM3 7 +#define TAITO_68KROM3_BYTESWAP 8 +#define TAITO_Z80ROM1 9 +#define TAITO_Z80ROM2 10 +#define TAITO_CHARS 11 +#define TAITO_CHARS_BYTESWAP 12 +#define TAITO_CHARSB 13 +#define TAITO_CHARSB_BYTESWAP 14 +#define TAITO_SPRITESA 15 +#define TAITO_SPRITESA_BYTESWAP 16 +#define TAITO_SPRITESA_BYTESWAP32 17 +#define TAITO_SPRITESA_TOPSPEED 18 +#define TAITO_SPRITESB 19 +#define TAITO_SPRITESB_BYTESWAP 20 +#define TAITO_SPRITESB_BYTESWAP32 21 +#define TAITO_ROAD 22 +#define TAITO_SPRITEMAP 23 +#define TAITO_YM2610A 24 +#define TAITO_YM2610B 25 +#define TAITO_MSM5205 26 +#define TAITO_MSM5205_BYTESWAP 27 +#define TAITO_CHARS_PIVOT 28 +#define TAITO_MSM6295 29 +#define TAITO_ES5505 30 +#define TAITO_ES5505_BYTESWAP 31 +#define TAITO_DEFAULT_EEPROM 32 + +extern UINT8 *Taito68KRom1; +extern UINT8 *Taito68KRom2; +extern UINT8 *Taito68KRom3; +extern UINT8 *TaitoZ80Rom1; +extern UINT8 *TaitoZ80Rom2; +extern UINT8 *TaitoChars; +extern UINT8 *TaitoCharsB; +extern UINT8 *TaitoCharsPivot; +extern UINT8 *TaitoSpritesA; +extern UINT8 *TaitoSpritesB; +extern UINT8 *TaitoSpriteMapRom; +extern UINT8 *TaitoYM2610ARom; +extern UINT8 *TaitoYM2610BRom; +extern UINT8 *TaitoMSM5205Rom; +extern UINT8 *TaitoMSM6295Rom; +extern UINT8 *TaitoES5505Rom; +extern UINT8 *TaitoDefaultEEProm; + +extern UINT32 Taito68KRom1Num; +extern UINT32 Taito68KRom2Num; +extern UINT32 Taito68KRom3Num; +extern UINT32 TaitoZ80Rom1Num; +extern UINT32 TaitoZ80Rom2Num; +extern UINT32 TaitoCharRomNum; +extern UINT32 TaitoCharBRomNum; +extern UINT32 TaitoCharPivotRomNum; +extern UINT32 TaitoSpriteARomNum; +extern UINT32 TaitoSpriteBRomNum; +extern UINT32 TaitoRoadRomNum; +extern UINT32 TaitoSpriteMapRomNum; +extern UINT32 TaitoYM2610ARomNum; +extern UINT32 TaitoYM2610BRomNum; +extern UINT32 TaitoMSM5205RomNum; +extern UINT32 TaitoMSM6295RomNum; +extern UINT32 TaitoES5505RomNum; +extern UINT32 TaitoDefaultEEPromNum; + +extern UINT32 Taito68KRom1Size; +extern UINT32 Taito68KRom2Size; +extern UINT32 Taito68KRom3Size; +extern UINT32 TaitoZ80Rom1Size; +extern UINT32 TaitoZ80Rom2Size; +extern UINT32 TaitoCharRomSize; +extern UINT32 TaitoCharRomBSize; +extern UINT32 TaitoCharPivotRomSize; +extern UINT32 TaitoSpriteARomSize; +extern UINT32 TaitoSpriteBRomSize; +extern UINT32 TaitoRoadRomSize; +extern UINT32 TaitoSpriteMapRomSize; +extern UINT32 TaitoYM2610ARomSize; +extern UINT32 TaitoYM2610BRomSize; +extern UINT32 TaitoMSM5205RomSize; +extern UINT32 TaitoMSM6295RomSize; +extern UINT32 TaitoES5505RomSize; +extern UINT32 TaitoDefaultEEPromSize; + +extern UINT32 TaitoCharModulo; +extern UINT32 TaitoCharNumPlanes; +extern UINT32 TaitoCharWidth; +extern UINT32 TaitoCharHeight; +extern UINT32 TaitoNumChar; +extern INT32 *TaitoCharPlaneOffsets; +extern INT32 *TaitoCharXOffsets; +extern INT32 *TaitoCharYOffsets; + +extern UINT32 TaitoCharBModulo; +extern UINT32 TaitoCharBNumPlanes; +extern UINT32 TaitoCharBWidth; +extern UINT32 TaitoCharBHeight; +extern UINT32 TaitoNumCharB; +extern INT32 *TaitoCharBPlaneOffsets; +extern INT32 *TaitoCharBXOffsets; +extern INT32 *TaitoCharBYOffsets; + +extern UINT32 TaitoCharPivotModulo; +extern UINT32 TaitoCharPivotNumPlanes; +extern UINT32 TaitoCharPivotWidth; +extern UINT32 TaitoCharPivotHeight; +extern UINT32 TaitoNumCharPivot; +extern INT32 *TaitoCharPivotPlaneOffsets; +extern INT32 *TaitoCharPivotXOffsets; +extern INT32 *TaitoCharPivotYOffsets; + +extern UINT32 TaitoSpriteAModulo; +extern UINT32 TaitoSpriteANumPlanes; +extern UINT32 TaitoSpriteAWidth; +extern UINT32 TaitoSpriteAHeight; +extern UINT32 TaitoNumSpriteA; +extern INT32 *TaitoSpriteAPlaneOffsets; +extern INT32 *TaitoSpriteAXOffsets; +extern INT32 *TaitoSpriteAYOffsets; +extern INT32 TaitoSpriteAInvertRom; + +extern UINT32 TaitoSpriteBModulo; +extern UINT32 TaitoSpriteBNumPlanes; +extern UINT32 TaitoSpriteBWidth; +extern UINT32 TaitoSpriteBHeight; +extern UINT32 TaitoNumSpriteB; +extern INT32 *TaitoSpriteBPlaneOffsets; +extern INT32 *TaitoSpriteBXOffsets; +extern INT32 *TaitoSpriteBYOffsets; + +extern INT32 TaitoLoadRoms(INT32 bLoad); +extern INT32 TaitoExit(); + +// Taito F2 Sprites +struct TaitoF2SpriteEntry { + INT32 Code; + INT32 x; + INT32 y; + INT32 Colour; + INT32 xFlip; + INT32 yFlip; + INT32 xZoom; + INT32 yZoom; + INT32 Priority; +}; +extern struct TaitoF2SpriteEntry *TaitoF2SpriteList; + +extern INT32 TaitoF2SpriteType; +extern INT32 TaitoF2SpritesFlipScreen; +extern INT32 TaitoF2PrepareSprites; +extern INT32 TaitoF2SpritesDisabled, TaitoF2SpritesActiveArea, TaitoF2SpritesMasterScrollX, TaitoF2SpritesMasterScrollY; +extern INT32 TaitoF2SpriteBlendMode; +extern UINT16 TaitoF2SpriteBank[8]; +extern UINT16 TaitoF2SpriteBankBuffered[8]; +extern UINT8 TaitoF2TilePriority[5]; +extern UINT8 TaitoF2SpritePriority[4]; + +typedef void (*TaitoF2SpriteBufferUpdate)(); +void TaitoF2NoBuffer(); +void TaitoF2PartialBufferDelayed(); +void TaitoF2PartialBufferDelayedQzchikyu(); +void TaitoF2PartialBufferDelayedThundfox(); +void TaitoF2FullBufferDelayed(); + +void TaitoF2MakeSpriteList(); +void TaitoF2RenderSpriteList(INT32 TaitoF2SpritePriorityLevel); +void TaitoF2HandleSpriteBuffering(); diff --git a/src/burn/drivers/taito/taito_ic.cpp b/src/burn/drivers/taito/taito_ic.cpp new file mode 100644 index 00000000..91018cb2 --- /dev/null +++ b/src/burn/drivers/taito/taito_ic.cpp @@ -0,0 +1,126 @@ +#include "burnint.h" +#include "taito_ic.h" + +INT32 TaitoIC_SupermanCChipInUse = 0; +INT32 TaitoIC_MegabCChipInUse = 0; +INT32 TaitoIC_RainbowCChipInUse = 0; +INT32 TaitoIC_OpwolfCChipInUse = 0; +INT32 TaitoIC_VolfiedCChipInUse = 0; + +INT32 TaitoIC_PC080SNInUse = 0; +INT32 TaitoIC_PC090OJInUse = 0; +INT32 TaitoIC_TC0100SCNInUse = 0; +INT32 TaitoIC_TC0110PCRInUse = 0; +INT32 TaitoIC_TC0140SYTInUse = 0; +INT32 TaitoIC_TC0150RODInUse = 0; +INT32 TaitoIC_TC0180VCUInUse = 0; +INT32 TaitoIC_TC0220IOCInUse = 0; +INT32 TaitoIC_TC0280GRDInUse = 0; +INT32 TaitoIC_TC0360PRIInUse = 0; +INT32 TaitoIC_TC0430GRWInUse = 0; +INT32 TaitoIC_TC0480SCPInUse = 0; +INT32 TaitoIC_TC0510NIOInUse = 0; +INT32 TaitoIC_TC0640FIOInUse = 0; + +INT32 TaitoWatchdog; + +void TaitoICReset() +{ + if (TaitoIC_SupermanCChipInUse) SupermanCChipReset(); + if (TaitoIC_MegabCChipInUse) MegabCChipReset(); + if (TaitoIC_RainbowCChipInUse) RainbowCChipReset(); + if (TaitoIC_OpwolfCChipInUse) OpwolfCChipReset(); + if (TaitoIC_VolfiedCChipInUse) VolfiedCChipReset(); + + if (TaitoIC_PC080SNInUse) PC080SNReset(); + if (TaitoIC_PC090OJInUse) PC090OJReset(); + if (TaitoIC_TC0100SCNInUse) TC0100SCNReset(); + if (TaitoIC_TC0110PCRInUse) TC0110PCRReset(); + if (TaitoIC_TC0140SYTInUse) TC0140SYTReset(); + if (TaitoIC_TC0150RODInUse) TC0150RODReset(); + if (TaitoIC_TC0180VCUInUse) TC0180VCUReset(); + if (TaitoIC_TC0220IOCInUse) TC0220IOCReset(); + if (TaitoIC_TC0280GRDInUse) TC0280GRDReset(); + if (TaitoIC_TC0360PRIInUse) TC0360PRIReset(); + if (TaitoIC_TC0430GRWInUse) TC0430GRWReset(); + if (TaitoIC_TC0480SCPInUse) TC0480SCPReset(); + if (TaitoIC_TC0510NIOInUse) TC0510NIOReset(); + if (TaitoIC_TC0640FIOInUse) TC0640FIOReset(); + + TaitoWatchdog = 0; +} + +void TaitoICExit() +{ + TaitoIC_SupermanCChipInUse = 0; + TaitoIC_MegabCChipInUse = 0; + TaitoIC_RainbowCChipInUse = 0; + TaitoIC_OpwolfCChipInUse = 0; + TaitoIC_VolfiedCChipInUse = 0; + + TaitoIC_PC080SNInUse = 0; + TaitoIC_PC090OJInUse = 0; + TaitoIC_TC0100SCNInUse = 0; + TaitoIC_TC0110PCRInUse = 0; + TaitoIC_TC0140SYTInUse = 0; + TaitoIC_TC0150RODInUse = 0; + TaitoIC_TC0180VCUInUse = 0; + TaitoIC_TC0220IOCInUse = 0; + TaitoIC_TC0280GRDInUse = 0; + TaitoIC_TC0360PRIInUse = 0; + TaitoIC_TC0430GRWInUse = 0; + TaitoIC_TC0480SCPInUse = 0; + TaitoIC_TC0510NIOInUse = 0; + TaitoIC_TC0640FIOInUse = 0; + + TaitoWatchdog = 0; + + SupermanCChipExit(); + MegabCChipExit(); + RainbowCChipExit(); + OpwolfCChipExit(); + VolfiedCChipExit(); + + PC080SNExit(); + PC090OJExit(); + TC0100SCNExit(); + TC0110PCRExit(); + TC0140SYTExit(); + TC0150RODExit(); + TC0180VCUExit(); + TC0220IOCExit(); + TC0280GRDExit(); + TC0360PRIExit(); + TC0430GRWExit(); + TC0480SCPExit(); + TC0510NIOExit(); + TC0640FIOExit(); +} + +void TaitoICScan(INT32 nAction) +{ + if (TaitoIC_SupermanCChipInUse) SupermanCChipScan(nAction); + if (TaitoIC_MegabCChipInUse) MegabCChipScan(nAction); + if (TaitoIC_RainbowCChipInUse) RainbowCChipScan(nAction); + if (TaitoIC_OpwolfCChipInUse) OpwolfCChipScan(nAction); + if (TaitoIC_VolfiedCChipInUse) VolfiedCChipScan(nAction); + + if (TaitoIC_PC080SNInUse) PC080SNScan(nAction); + if (TaitoIC_PC090OJInUse) PC090OJScan(nAction); + if (TaitoIC_TC0100SCNInUse) TC0100SCNScan(nAction); + if (TaitoIC_TC0110PCRInUse) TC0110PCRScan(nAction); + if (TaitoIC_TC0140SYTInUse) TC0140SYTScan(nAction); + if (TaitoIC_TC0150RODInUse) TC0150RODScan(nAction); + if (TaitoIC_TC0180VCUInUse) TC0180VCUScan(nAction); + if (TaitoIC_TC0220IOCInUse) TC0220IOCScan(nAction); + if (TaitoIC_TC0280GRDInUse) TC0280GRDScan(nAction); + if (TaitoIC_TC0360PRIInUse) TC0360PRIScan(nAction); + if (TaitoIC_TC0430GRWInUse) TC0430GRWScan(nAction); + if (TaitoIC_TC0480SCPInUse) TC0480SCPScan(nAction); + if (TaitoIC_TC0510NIOInUse) TC0510NIOScan(nAction); + if (TaitoIC_TC0640FIOInUse) TC0640FIOScan(nAction); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TaitoWatchdog); + } +} diff --git a/src/burn/drivers/taito/taito_ic.h b/src/burn/drivers/taito/taito_ic.h new file mode 100644 index 00000000..61c9ea2d --- /dev/null +++ b/src/burn/drivers/taito/taito_ic.h @@ -0,0 +1,559 @@ +extern INT32 TaitoIC_SupermanCChipInUse; +extern INT32 TaitoIC_MegabCChipInUse; +extern INT32 TaitoIC_RainbowCChipInUse; +extern INT32 TaitoIC_OpwolfCChipInUse; +extern INT32 TaitoIC_VolfiedCChipInUse; + +extern INT32 TaitoIC_PC080SNInUse; +extern INT32 TaitoIC_PC090OJInUse; +extern INT32 TaitoIC_TC0100SCNInUse; +extern INT32 TaitoIC_TC0110PCRInUse; +extern INT32 TaitoIC_TC0140SYTInUse; +extern INT32 TaitoIC_TC0150RODInUse; +extern INT32 TaitoIC_TC0180VCUInUse; +extern INT32 TaitoIC_TC0220IOCInUse; +extern INT32 TaitoIC_TC0280GRDInUse; +extern INT32 TaitoIC_TC0360PRIInUse; +extern INT32 TaitoIC_TC0430GRWInUse; +extern INT32 TaitoIC_TC0480SCPInUse; +extern INT32 TaitoIC_TC0510NIOInUse; +extern INT32 TaitoIC_TC0640FIOInUse; + +extern INT32 TaitoWatchdog; + +void TaitoICReset(); +void TaitoICExit(); +void TaitoICScan(INT32 nAction); + +// C-Chip +UINT16 SupermanCChipCtrlRead(); +UINT16 SupermanCChipRamRead(UINT32 Offset, UINT8 Input1, UINT8 Input2, UINT8 Input3); +void SupermanCChipCtrlWrite(); +void SupermanCChipBankWrite(UINT16 Data); +void SupermanCChipRamWrite(UINT32 Offset, UINT16 Data); +void SupermanCChipReset(); +void SupermanCChipInit(); +void SupermanCChipExit(); +void SupermanCChipScan(INT32 nAction); + +UINT16 MegabCChipRead(UINT32 Offset); +void MegabCChipWrite(UINT32 Offset, UINT16 Data); +void MegabCChipReset(); +void MegabCChipInit(); +void MegabCChipExit(); +void MegabCChipScan(INT32 nAction); + +void RainbowCChipUpdate(UINT8 Input1, UINT8 Input2, UINT8 Input3, UINT8 Input4); +UINT16 RainbowCChipCtrlRead(); +UINT16 RainbowCChipRamRead(UINT32 Offset); +void RainbowCChipCtrlWrite(UINT16); +void RainbowCChipBankWrite(UINT16 Data); +void RainbowCChipRamWrite(UINT32 Offset, UINT16 Data); +void RainbowCChipReset(); +void RainbowCChipInit(INT32 Version); +void RainbowCChipExit(); +void RainbowCChipScan(INT32 nAction); + +void OpwolfCChipUpdate(UINT8 Input1, UINT8 Input2); +UINT16 OpwolfCChipStatusRead(); +UINT16 OpwolfCChipDataRead(UINT32 Offset); +void OpwolfCChipStatusWrite(); +void OpwolfCChipBankWrite(UINT16 Data); +void OpwolfCChipDataWrite(UINT8 *p68kRom, UINT32 Offset, UINT16 Data ); +void OpwolfCChipReset(); +void OpwolfCChipInit(INT32 Region); +void OpwolfCChipExit(); +void OpwolfCChipScan(INT32 nAction); + +void BonzeWriteCChipRam(INT32 offset, INT32 data); +void BonzeWriteCChipBank(INT32 data); +UINT16 BonzeReadCChipRam(INT32 offset); +void BonzeCChipReset(); +void BonzeCChipScan(INT32 nAction); + +void VolfiedCChipBankWrite(UINT16 data); +void VolfiedCChipRamWrite(INT32 offset, UINT8 data); +UINT8 VolfiedCChipCtrlRead(); +UINT8 VolfiedCChipRamRead(INT32 offset); +void VolfiedCChipInit(); +void VolfiedCChipReset(); +void VolfiedCChipExit(); +void VolfiedCChipScan(INT32 nAction); + +// PC080SN +#define PC080SN_MAX_CHIPS 2 + +extern UINT8 *PC080SNRam[PC080SN_MAX_CHIPS]; + +void PC080SNDrawBgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc, UINT16 *pDest); +void PC080SNDrawFgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc, UINT16 *pDest); +void PC080SNSetScrollX(INT32 Chip, UINT32 Offset, UINT16 Data); +void PC080SNSetScrollY(INT32 Chip, UINT32 Offset, UINT16 Data); +void PC080SNCtrlWrite(INT32 Chip, UINT32 Offset, UINT16 Data); +void PC080SNOverrideFgScroll(INT32 Chip, INT32 xScroll, INT32 yScroll); +void PC080SNReset(); +void PC080SNInit(INT32 Chip, INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 yInvert, INT32 DblWidth); +void PC080SNSetFgTransparentPen(INT32 Chip, INT32 Pen); +void PC080SNExit(); +void PC080SNScan(INT32 nAction); +void TopspeedDrawBgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest, UINT16 *ColourCtrlRam); +void TopspeedDrawFgLayer(INT32 Chip, UINT8 *pSrc, UINT16 *pDest, UINT16 *ColourCtrlRam); + +// PC090OJ +extern UINT8 *PC090OJRam; +extern INT32 PC090OJSpriteCtrl; + +void PC090OJDrawSprites(UINT8 *pSrc); +void PC090OJReset(); +void PC090OJInit(INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 UseBuffer); +void PC090OJSetPaletteOffset(INT32 Offset); +void PC090OJExit(); +void PC090OJScan(INT32 nAction); + +// TC0100SCN +#define TC0100SCN_MAX_CHIPS 3 + +extern UINT8 *TC0100SCNRam[TC0100SCN_MAX_CHIPS]; +extern UINT16 TC0100SCNCtrl[TC0100SCN_MAX_CHIPS][8]; +extern UINT8 TC0100SCNBgLayerUpdate[TC0100SCN_MAX_CHIPS]; +extern UINT8 TC0100SCNFgLayerUpdate[TC0100SCN_MAX_CHIPS]; + +void TC0100SCNCtrlWordWrite(INT32 Chip, UINT32 Offset, UINT16 Data); +INT32 TC0100SCNBottomLayer(INT32 Chip); +void TC0100SCNRenderBgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc); +void TC0100SCNRenderFgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc); +void TC0100SCNRenderCharLayer(INT32 Chip); +void TC0100SCNReset(); +void TC0100SCNInit(INT32 Chip, INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 xFlip, UINT8 *PriorityMap); +void TC0100SCNSetColourDepth(INT32 Chip, INT32 ColourDepth); +void TC0100SCNSetGfxMask(INT32 Chip, INT32 Mask); +void TC0100SCNSetGfxBank(INT32 Chip, INT32 Bank); +void TC0100SCNSetClipArea(INT32 Chip, INT32 ClipWidth, INT32 ClipHeight, INT32 ClipStartX); +void TC0100SCNSetPaletteOffset(INT32 Chip, INT32 PaletteOffset); +void TC0100SCNExit(); +void TC0100SCNScan(INT32 nAction); + +// TC0110PCR +extern UINT32 *TC0110PCRPalette; +extern INT32 TC0110PCRTotalColours; + +UINT16 TC0110PCRWordRead(INT32 Chip); +void TC0110PCRWordWrite(INT32 Chip, INT32 Offset, UINT16 Data); +void TC0110PCRStep1WordWrite(INT32 Chip, INT32 Offset, UINT16 Data); +void TC0110PCRStep1RBSwapWordWrite(INT32 Chip, INT32 Offset, UINT16 Data); +void TC0110PCRStep14rbgWordWrite(INT32 Chip, INT32 Offset, UINT16 Data); +void TC0110PCRReset(); +void TC0110PCRInit(INT32 Num, INT32 nNumColours); +void TC0110PCRExit(); +void TC0110PCRScan(INT32 nAction); + +// TC0140SYT +void TC0140SYTPortWrite(UINT8 Data); +UINT8 TC0140SYTCommRead(); +void TC0140SYTCommWrite(UINT8 Data); +void TC0140SYTSlavePortWrite(UINT8 Data); +UINT8 TC0140SYTSlaveCommRead(); +void TC0140SYTSlaveCommWrite(UINT8 Data); +void TC0140SYTReset(); +void TC0140SYTInit(); +void TC0140SYTExit(); +void TC0140SYTScan(INT32 nAction); + +// TC0150ROD +extern UINT8 *TC0150RODRom; +extern UINT8 *TC0150RODRam; + +void TC0150RODDraw(INT32 yOffs, INT32 pOffs, INT32 Type, INT32 RoadTrans, INT32 LowPriority, INT32 HighPriority); +void TC0150RODReset(); +void TC0150RODInit(INT32 nRomSize, INT32 xFlip); +void TC0150RODExit(); +void TC0150RODScan(INT32 nAction); + +// TC0180VCU +extern UINT8 *TC0180VCURAM; +extern UINT8 *TC0180VCUScrollRAM; +extern UINT8 *TC0180VCUFbRAM; + +void TC0180VCUInit(UINT8 *gfx0, INT32 mask0, UINT8 *gfx1, INT32 mask1, INT32 global_x, INT32 global_y); +void TC0180VCUReset(); +void TC0180VCUExit(); +void TC0180VCUScan(INT32 nAction); + +void TC0180VCUDrawCharLayer(INT32 colorbase); +void TC0180VCUDrawLayer(INT32 colorbase, INT32 ctrl_offset, INT32 transparent); + +void TC0180VCUFramebufferDraw(INT32 priority, INT32 color_base); +void TC0180VCUDrawSprite(UINT16 *dest); +void TC0180VCUBufferSprites(); + +UINT16 TC0180VCUFramebufferRead(INT32 offset); +void TC0180VCUFramebufferWrite(INT32 offset); + +UINT8 TC0180VCUReadRegs(INT32 offset); +void TC0180VCUWriteRegs(INT32 offset, INT32 data); +UINT8 TC0180VCUReadControl(); + +// TC0220IOC +extern UINT8 TC0220IOCInputPort0[8]; +extern UINT8 TC0220IOCInputPort1[8]; +extern UINT8 TC0220IOCInputPort2[8]; +extern UINT8 TC0220IOCDip[2]; +extern UINT8 TC0220IOCInput[3]; + +UINT8 TC0220IOCPortRead(); +UINT8 TC0220IOCHalfWordPortRead(); +UINT8 TC0220IOCPortRegRead(); +UINT8 TC0220IOCHalfWordRead(INT32 Offset); +UINT8 TC0220IOCRead(UINT8 Port); +void TC0220IOCWrite(UINT8 Port, UINT8 Data); +void TC0220IOCHalfWordPortRegWrite(UINT16 Data); +void TC0220IOCHalfWordPortWrite(UINT16 Data); +void TC0220IOCHalfWordWrite(INT32 Offset, UINT16 Data); +void TC0220IOCReset(); +void TC0220IOCInit(); +void TC0220IOCExit(); +void TC0220IOCScan(INT32 nAction); + +// TC0280GRD +extern UINT8 *TC0280GRDRam; +extern INT32 TC0280GRDBaseColour; + +void TC0280GRDRenderLayer(); +void TC0280GRDCtrlWordWrite(UINT32 Offset, UINT16 Data); +void TC0280GRDReset(); +void TC0280GRDInit(INT32 xOffs, INT32 yOffs, UINT8 *pSrc); +void TC0430GRWInit(INT32 xOffs, INT32 yOffs, UINT8 *pSrc); +void TC0280GRDExit(); +void TC0280GRDScan(INT32 nAction); + +#define TC0430GRWRam TC0280GRDRam +#define TC0430GRWRenderLayer TC0280GRDRenderLayer +#define TC0430GRWCtrlWordWrite TC0280GRDCtrlWordWrite +#define TC0430GRWReset TC0280GRDReset +#define TC0430GRWExit TC0280GRDExit +#define TC0430GRWScan TC0280GRDScan + +// TC0360PRI +extern UINT8 TC0360PRIRegs[16]; + +void TC0360PRIWrite(UINT32 Offset, UINT8 Data); +void TC0360PRIHalfWordWrite(UINT32 Offset, UINT16 Data); +void TC0360PRIHalfWordSwapWrite(UINT32 Offset, UINT16 Data); +void TC0360PRIReset(); +void TC0360PRIInit(); +void TC0360PRIExit(); +void TC0360PRIScan(INT32 nAction); + +// TC0480SCP +extern UINT8 *TC0480SCPRam; +extern UINT16 TC0480SCPCtrl[0x18]; + +void TC0480SCPCtrlWordWrite(INT32 Offset, UINT16 Data); +void TC0480SCPTilemapRender(INT32 Layer, INT32 Opaque, UINT8 *pSrc); +void TC0480SCPRenderCharLayer(); +void TC0480SCPReset(); +INT32 TC0480SCPGetBgPriority(); +void TC0480SCPInit(INT32 nNumTiles, INT32 Pixels, INT32 xOffset, INT32 yOffset, INT32 xTextOffset, INT32 yTextOffset, INT32 VisYOffset); +void TC0480SCPSetColourBase(INT32 Base); +void TC0480SCPExit(); +void TC0480SCPScan(INT32 nAction); + +// TC0510NIO +extern UINT8 TC0510NIOInputPort0[8]; +extern UINT8 TC0510NIOInputPort1[8]; +extern UINT8 TC0510NIOInputPort2[8]; +extern UINT8 TC0510NIODip[2]; +extern UINT8 TC0510NIOInput[3]; + +UINT16 TC0510NIOHalfWordRead(INT32 Offset); +UINT16 TC0510NIOHalfWordSwapRead(INT32 Offset); +void TC0510NIOHalfWordWrite(INT32 Offset, UINT16 Data); +void TC0510NIOHalfWordSwapWrite(INT32 Offset, UINT16 Data); +void TC0510NIOReset(); +void TC0510NIOInit(); +void TC0510NIOExit(); +void TC0510NIOScan(INT32 nAction); + +// TC0640FIO +extern UINT8 TC0640FIOInputPort0[8]; +extern UINT8 TC0640FIOInputPort1[8]; +extern UINT8 TC0640FIOInputPort2[8]; +extern UINT8 TC0640FIOInputPort3[8]; +extern UINT8 TC0640FIOInputPort4[8]; +extern UINT8 TC0640FIOInput[5]; + +UINT8 TC0640FIORead(UINT32 Offset); +void TC0640FIOWrite(UINT32 Offset, UINT8 Data); +UINT16 TC0640FIOHalfWordRead(UINT32 Offset); +void TC0640FIOHalfWordWrite(UINT32 Offset, UINT16 Data); +UINT16 TC0640FIOHalfWordByteswapRead(UINT32 Offset); +void TC0640FIOHalfWordByteswapWrite(UINT32 Offset, UINT16 Data); +void TC0640FIOReset(); +void TC0640FIOInit(); +void TC0640FIOExit(); +void TC0640FIOScan(INT32 nAction); + +#define TC0100SCN0CtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0100SCNCtrlWordWrite(0, (a - base_address) >> 1, d); \ + return; \ + } + +#define TC0100SCN1CtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0100SCNCtrlWordWrite(1, (a - base_address) >> 1, d); \ + return; \ + } + +#define TC0100SCN2CtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0100SCNCtrlWordWrite(2, (a - base_address) >> 1, d); \ + return; \ + } + +#define TC0100SCN0ByteWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + INT32 Offset = (a - start) ^ 1; \ + if (TC0100SCNRam[0][Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + TC0100SCNRam[0][Offset] = d; \ + return; \ + } + +#define TC0100SCN0WordWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + UINT16 *Ram = (UINT16*)TC0100SCNRam[0]; \ + INT32 Offset = (a - start) >> 1; \ + if (Ram[Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + Ram[Offset] = d; \ + return; \ + } + +#define TC0100SCN1ByteWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + INT32 Offset = (a - start) ^ 1; \ + if (TC0100SCNRam[1][Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + TC0100SCNRam[1][Offset] = d; \ + return; \ + } + +#define TC0100SCN1WordWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + UINT16 *Ram = (UINT16*)TC0100SCNRam[1]; \ + INT32 Offset = (a - start) >> 1; \ + if (Ram[Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + Ram[Offset] = d; \ + return; \ + } + +#define TC0100SCN2ByteWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + INT32 Offset = (a - start) ^ 1; \ + if (TC0100SCNRam[2][Offset] != d) { \ + TC0100SCNBgLayerUpdate[2] = 1; \ + TC0100SCNFgLayerUpdate[2] = 1; \ + } \ + TC0100SCNRam[2][Offset] = d; \ + return; \ + } + +#define TC0100SCN2WordWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + UINT16 *Ram = (UINT16*)TC0100SCNRam[2]; \ + INT32 Offset = (a - start) >> 1; \ + if (Ram[Offset] != d) { \ + TC0100SCNBgLayerUpdate[2] = 1; \ + TC0100SCNFgLayerUpdate[2] = 1; \ + } \ + Ram[Offset] = d; \ + return; \ + } + +#define TC0100SCNDualScreenByteWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + INT32 Offset = (a - start) ^ 1; \ + if (TC0100SCNRam[0][Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + if (TC0100SCNRam[1][Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + TC0100SCNRam[0][Offset] = d; \ + TC0100SCNRam[1][Offset] = d; \ + return; \ + } + +#define TC0100SCNDualScreenWordWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + UINT16 *Ram0 = (UINT16*)TC0100SCNRam[0]; \ + UINT16 *Ram1 = (UINT16*)TC0100SCNRam[1]; \ + INT32 Offset = (a - start) >> 1; \ + if (Ram0[Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + if (Ram1[Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + Ram0[Offset] = d; \ + Ram1[Offset] = d; \ + return; \ + } + +#define TC0100SCNTripleScreenByteWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + INT32 Offset = (a - start) ^ 1; \ + if (TC0100SCNRam[0][Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + if (TC0100SCNRam[1][Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + if (TC0100SCNRam[2][Offset] != d) { \ + TC0100SCNBgLayerUpdate[2] = 1; \ + TC0100SCNFgLayerUpdate[2] = 1; \ + } \ + TC0100SCNRam[0][Offset] = d; \ + TC0100SCNRam[1][Offset] = d; \ + TC0100SCNRam[2][Offset] = d; \ + return; \ + } + +#define TC0100SCNTripleScreenWordWrite_Map(start, end) \ + if (a >= start && a <= end) { \ + UINT16 *Ram0 = (UINT16*)TC0100SCNRam[0]; \ + UINT16 *Ram1 = (UINT16*)TC0100SCNRam[1]; \ + UINT16 *Ram2 = (UINT16*)TC0100SCNRam[2]; \ + INT32 Offset = (a - start) >> 1; \ + if (Ram0[Offset] != d) { \ + TC0100SCNBgLayerUpdate[0] = 1; \ + TC0100SCNFgLayerUpdate[0] = 1; \ + } \ + if (Ram1[Offset] != d) { \ + TC0100SCNBgLayerUpdate[1] = 1; \ + TC0100SCNFgLayerUpdate[1] = 1; \ + } \ + if (Ram2[Offset] != d) { \ + TC0100SCNBgLayerUpdate[2] = 1; \ + TC0100SCNFgLayerUpdate[2] = 1; \ + } \ + Ram0[Offset] = d; \ + Ram1[Offset] = d; \ + Ram2[Offset] = d; \ + return; \ + } + +#define TC0220IOCHalfWordRead_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + return TC0220IOCHalfWordRead((a - base_address) >> 1); \ + } + +#define TC0220IOCHalfWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0220IOCHalfWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0280GRDCtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0280GRDCtrlWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0360PRIHalfWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x1f) { \ + TC0360PRIHalfWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0360PRIHalfWordSwapWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x1f) { \ + TC0360PRIHalfWordSwapWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0430GRWCtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0430GRWCtrlWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0480SCPCtrlWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x2f) { \ + TC0480SCPCtrlWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0510NIOHalfWordRead_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + return TC0510NIOHalfWordRead((a - base_address) >> 1); \ + } + +#define TC0510NIOHalfWordSwapRead_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + return TC0510NIOHalfWordSwapRead((a - base_address) >> 1); \ + } + +#define TC0510NIOHalfWordWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0510NIOHalfWordWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0510NIOHalfWordSwapWrite_Map(base_address) \ + if (a >= base_address && a <= base_address + 0x0f) { \ + TC0510NIOHalfWordSwapWrite((a - base_address) >> 1, d); \ + return; \ + } + +#define TC0180VCUHalfWordWrite_Map(base_address) \ + if (a >= (base_address + 0x40000) && a <= (base_address+0x7ffff)) { \ + TC0180VCUFbRAM[(a & 0x3ffff)^1] = d; \ + TC0180VCUFramebufferWrite(a); \ + return; \ + } \ + \ + if (a >= (base_address + 0x18000) && a <= (base_address+0x1801f)) { \ + TC0180VCUWriteRegs(a, d); \ + return; \ + } + +#define TC0180VCUWordWrite_Map(base_address) \ + if (a >= (base_address + 0x40000) && a <= (base_address+0x7ffff)) { \ + *((UINT16*)(TC0180VCUFbRAM + (a & 0x3fffe))) = d; \ + TC0180VCUFramebufferWrite(a); \ + return; \ + } \ + \ + if (a >= (base_address + 0x18000) && a <= (base_address+0x1801f)) { \ + TC0180VCUWriteRegs(a, d >> 8); \ + return; \ + } + +#define TC0180VCUHalfWordRead_Map(base_address) \ + if (a >= (base_address + 0x40000) && a <= (base_address+0x7ffff)) { \ + if (a & 1) return TC0180VCUFramebufferRead(a) >> 8; \ + return TC0180VCUFramebufferRead(a); \ + } \ + \ + if (a >= (base_address + 0x18000) && a <= (base_address+0x1801f)) { \ + return TC0180VCUReadRegs(a); \ + } + +// TC0180VCU doesn't seem to use word access at all diff --git a/src/burn/drivers/taito/taito_m68705.cpp b/src/burn/drivers/taito/taito_m68705.cpp new file mode 100644 index 00000000..b0f205c9 --- /dev/null +++ b/src/burn/drivers/taito/taito_m68705.cpp @@ -0,0 +1,224 @@ + +#include "burnint.h" +#include "taito_m68705.h" + +// taito m68705 protection + +UINT8 portA_in; +UINT8 portA_out; +UINT8 ddrA; +UINT8 portB_in; +UINT8 portB_out; +UINT8 ddrB; +UINT8 portC_in; +UINT8 portC_out; +UINT8 ddrC; + +UINT8 from_main; +UINT8 from_mcu; +INT32 mcu_sent; +INT32 main_sent; + +static struct m68705_interface *ptr; + +void m67805_mcu_write(UINT16 address, UINT8 data) +{ + switch (address & 0x7ff) + { + case 0x0000: + if (ptr->portA_out) { + ptr->portA_out(&data); + } + portA_out = data; + return; + + case 0x0001: + if (ptr->portB_out) { + ptr->portB_out(&data); + } + portB_out = data; + return; + + case 0x0002: + if (ptr->portC_out) { + ptr->portC_out(&data); + } + portC_out = data; + return; + + case 0x0004: + if (ptr->ddrA_out) { + ptr->ddrA_out(&data); + } + ddrA = data; + return; + + case 0x0005: + if (ptr->ddrB_out) { + ptr->ddrB_out(&data); + } + ddrB = data; + return; + + case 0x0006: + if (ptr->ddrC_out) { + ptr->ddrC_out(&data); + } + ddrC = data; + return; + } +} + +UINT8 m67805_mcu_read(UINT16 address) +{ + switch (address & 0x7ff) + { + case 0x0000: + if (ptr->portA_in) { + ptr->portA_in(); + } + return (portA_out & ddrA) | (portA_in & ~ddrA); + + case 0x0001: + if (ptr->portB_in) { + ptr->portB_in(); + } + return (portB_out & ddrB) | (portB_in & ~ddrB); + + case 0x0002: + if (ptr->portC_in) { + ptr->portC_in(); + } + return (portC_out & ddrC) | (portC_in & ~ddrC); + } + + return 0; +} + +void m67805_taito_reset() +{ + m6805Open(0); + m68705Reset(); + m6805Close(); + + portA_in = 0; + portA_out = 0; + ddrA = 0; + portB_in = 0; + portB_out = 0; + ddrB = 0; + portC_in = 0; + portC_out = 0; + ddrC = 0; + + from_main = 0; + from_mcu = 0; + mcu_sent = 0; + main_sent = 0; +} + +void m67805_taito_init(UINT8 *rom, UINT8 *ram, m68705_interface *interface) +{ + ptr = interface; + + m6805Init(1, 0x800 /*max memory range - page size is max range / 0x100*/); + m6805Open(0); + m6805MapMemory(ram, 0x0010, 0x007f, M6805_RAM); + m6805MapMemory(rom + 0x80, 0x0080, 0x07ff, M6805_ROM); + m6805SetWriteHandler(m67805_mcu_write); + m6805SetReadHandler(m67805_mcu_read); + m6805Close(); +} + +void m67805_taito_exit() +{ + portA_in = 0; + portA_out = 0; + ddrA = 0; + portB_in = 0; + portB_out = 0; + ddrB = 0; + portC_in = 0; + portC_out = 0; + ddrC = 0; + + from_main = 0; + from_mcu = 0; + mcu_sent = 0; + main_sent = 0; + + ptr = NULL; + + m6805Exit(); +} + +INT32 m68705_taito_scan(INT32 nAction) +{ + if (nAction & ACB_VOLATILE) { + m6805Scan(nAction, 0); + + SCAN_VAR(portA_in); + SCAN_VAR(portB_in); + SCAN_VAR(portC_in); + SCAN_VAR(ddrA); + SCAN_VAR(ddrB); + SCAN_VAR(ddrC); + SCAN_VAR(portA_out); + SCAN_VAR(portB_out); + SCAN_VAR(portC_out); + + SCAN_VAR(from_main); + SCAN_VAR(from_mcu); + SCAN_VAR(mcu_sent); + SCAN_VAR(main_sent); + } + + return 0; +} + + + + + +void standard_taito_mcu_write(INT32 data) +{ + from_main = data; + main_sent = 1; + m68705SetIrqLine(0, 1 /*ASSERT_LINE*/); +} + +INT32 standard_taito_mcu_read() +{ + mcu_sent = 0; + return from_mcu; +} + +void standard_m68705_portB_out(UINT8 *data) +{ + if ((ddrB & 0x02) && (~*data & 0x02) && (portB_out & 0x02)) + { + portA_in = from_main; + if (main_sent) + m68705SetIrqLine(0, 0 /*CLEAR_LINE*/); + main_sent = 0; + } + if ((ddrB & 0x04) && (*data & 0x04) && (~portB_out & 0x04)) + { + from_mcu = portA_out; + mcu_sent = 1; + } +} + +void standard_m68705_portC_in() +{ + portC_in = 0; + if (main_sent) portC_in |= 0x01; + if (!mcu_sent) portC_in |= 0x02; +} + +m68705_interface standard_m68705_interface = { + NULL /* portA */, standard_m68705_portB_out /* portB */, NULL /* portC */, + NULL /* ddrA */, NULL /* ddrB */, NULL /* ddrC */, + NULL /* portA */, NULL /* portB */, standard_m68705_portC_in /* portC */ +}; + diff --git a/src/burn/drivers/taito/taito_m68705.h b/src/burn/drivers/taito/taito_m68705.h new file mode 100644 index 00000000..e9b34a92 --- /dev/null +++ b/src/burn/drivers/taito/taito_m68705.h @@ -0,0 +1,40 @@ +#include "m6805_intf.h" + +struct m68705_interface { + void (*portA_out)(UINT8 *data); + void (*portB_out)(UINT8 *data); + void (*portC_out)(UINT8 *data); + void (*ddrA_out)(UINT8 *data); + void (*ddrB_out)(UINT8 *data); + void (*ddrC_out)(UINT8 *data); + void (*portA_in)(); + void (*portB_in)(); + void (*portC_in)(); +}; + +extern UINT8 portA_in; +extern UINT8 portA_out; +extern UINT8 ddrA; +extern UINT8 portB_in; +extern UINT8 portB_out; +extern UINT8 ddrB; +extern UINT8 portC_in; +extern UINT8 portC_out; +extern UINT8 ddrC; + +extern UINT8 from_main; +extern UINT8 from_mcu; +extern INT32 mcu_sent; +extern INT32 main_sent; + +void m67805_taito_reset(); +void m67805_taito_init(UINT8 *rom, UINT8 *ram, m68705_interface *interface); +void m67805_taito_exit(); +INT32 m68705_taito_scan(INT32 nAction); + +void standard_taito_mcu_write(INT32 data); +INT32 standard_taito_mcu_read(); +void standard_m68705_portB_out(UINT8 *data); +void standard_m68705_portC_in(); + +extern m68705_interface standard_m68705_interface; diff --git a/src/burn/drivers/taito/tc0100scn.cpp b/src/burn/drivers/taito/tc0100scn.cpp new file mode 100644 index 00000000..8a421bbc --- /dev/null +++ b/src/burn/drivers/taito/tc0100scn.cpp @@ -0,0 +1,627 @@ +// TC0100SCN + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *TC0100SCNRam[TC0100SCN_MAX_CHIPS]; +UINT16 TC0100SCNCtrl[TC0100SCN_MAX_CHIPS][8]; +UINT8 TC0100SCNBgLayerUpdate[TC0100SCN_MAX_CHIPS]; +UINT8 TC0100SCNFgLayerUpdate[TC0100SCN_MAX_CHIPS]; +static UINT8 *TC0100SCNChars[TC0100SCN_MAX_CHIPS]; +static INT32 BgScrollX[TC0100SCN_MAX_CHIPS]; +static INT32 BgScrollY[TC0100SCN_MAX_CHIPS]; +static INT32 FgScrollX[TC0100SCN_MAX_CHIPS]; +static INT32 FgScrollY[TC0100SCN_MAX_CHIPS]; +static INT32 CharScrollX[TC0100SCN_MAX_CHIPS]; +static INT32 CharScrollY[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNXOffset[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNYOffset[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNFlipScreenX[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNFlip[TC0100SCN_MAX_CHIPS]; +static UINT8 *TC0100SCNPriorityMap[TC0100SCN_MAX_CHIPS] = { NULL, }; +static INT32 TC0100SCNColourDepth[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNGfxBank[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNGfxMask[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNDblWidth[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNClipWidth[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNClipHeight[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNClipStartX[TC0100SCN_MAX_CHIPS]; +static INT32 TC0100SCNPaletteOffset[TC0100SCN_MAX_CHIPS]; +static UINT16 *pTC0100SCNBgTempDraw[TC0100SCN_MAX_CHIPS] = { NULL, }; +static UINT16 *pTC0100SCNFgTempDraw[TC0100SCN_MAX_CHIPS] = { NULL, }; +static INT32 TC0100SCNNum = 0; + +#define PLOTPIXEL(x, po) pPixel[x] = nPalette | pTileData[x] | po; +#define PLOTPIXEL_FLIPX(x, a, po) pPixel[x] = nPalette | pTileData[a] | po; + +static void RenderTile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, INT32 nTilemapWidth, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nTilemapWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nTilemapWidth, pTileData += 8) { + PLOTPIXEL( 0, nPaletteOffset); + PLOTPIXEL( 1, nPaletteOffset); + PLOTPIXEL( 2, nPaletteOffset); + PLOTPIXEL( 3, nPaletteOffset); + PLOTPIXEL( 4, nPaletteOffset); + PLOTPIXEL( 5, nPaletteOffset); + PLOTPIXEL( 6, nPaletteOffset); + PLOTPIXEL( 7, nPaletteOffset); + } +} + +static void RenderTile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, INT32 nTilemapWidth, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nTilemapWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nTilemapWidth, pTileData += 8) { + PLOTPIXEL_FLIPX( 7, 0, nPaletteOffset); + PLOTPIXEL_FLIPX( 6, 1, nPaletteOffset); + PLOTPIXEL_FLIPX( 5, 2, nPaletteOffset); + PLOTPIXEL_FLIPX( 4, 3, nPaletteOffset); + PLOTPIXEL_FLIPX( 3, 4, nPaletteOffset); + PLOTPIXEL_FLIPX( 2, 5, nPaletteOffset); + PLOTPIXEL_FLIPX( 1, 6, nPaletteOffset); + PLOTPIXEL_FLIPX( 0, 7, nPaletteOffset); + } +} + +static void RenderTile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, INT32 nTilemapWidth, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nTilemapWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nTilemapWidth, pTileData += 8) { + PLOTPIXEL( 0, nPaletteOffset); + PLOTPIXEL( 1, nPaletteOffset); + PLOTPIXEL( 2, nPaletteOffset); + PLOTPIXEL( 3, nPaletteOffset); + PLOTPIXEL( 4, nPaletteOffset); + PLOTPIXEL( 5, nPaletteOffset); + PLOTPIXEL( 6, nPaletteOffset); + PLOTPIXEL( 7, nPaletteOffset); + } +} + +static void RenderTile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, INT32 nTilemapWidth, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nTilemapWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nTilemapWidth, pTileData += 8) { + PLOTPIXEL_FLIPX( 7, 0, nPaletteOffset); + PLOTPIXEL_FLIPX( 6, 1, nPaletteOffset); + PLOTPIXEL_FLIPX( 5, 2, nPaletteOffset); + PLOTPIXEL_FLIPX( 4, 3, nPaletteOffset); + PLOTPIXEL_FLIPX( 3, 4, nPaletteOffset); + PLOTPIXEL_FLIPX( 2, 5, nPaletteOffset); + PLOTPIXEL_FLIPX( 1, 6, nPaletteOffset); + PLOTPIXEL_FLIPX( 0, 7, nPaletteOffset); + } +} + +#undef PLOTPIXEL +#undef PLOTPIXEL_FLIPX + +void TC0100SCNCtrlWordWrite(INT32 Chip, UINT32 Offset, UINT16 Data) +{ + TC0100SCNCtrl[Chip][Offset] = Data; + + switch (Offset) { + case 0x00: { + BgScrollX[Chip] = -Data; + return; + } + + case 0x01: { + FgScrollX[Chip] = -Data; + return; + } + + case 0x02: { + CharScrollX[Chip] = -Data; + return; + } + + case 0x03: { + BgScrollY[Chip] = -Data; + return; + } + + case 0x04: { + FgScrollY[Chip] = -Data; + return; + } + + case 0x05: { + CharScrollY[Chip] = -Data; + return; + } + + case 0x06: { + TC0100SCNDblWidth[Chip] = (Data & 0x10) >> 4; + if (TC0100SCNFlip[Chip]) bprintf(PRINT_NORMAL, _T("Double\n")); + return; + } + + case 0x07: { + TC0100SCNFlip[Chip] = (Data & 0x01) ? 1: 0; + if (TC0100SCNFlip[Chip]) bprintf(PRINT_NORMAL, _T("Flipped\n")); + return; + } + } + + bprintf(PRINT_IMPORTANT, _T("TC0100 Ctrl Word Write %02X, %04X\n"), Offset, Data); +} + +INT32 TC0100SCNBottomLayer(INT32 Chip) +{ + return (TC0100SCNCtrl[Chip][6] & 0x08) >> 3; +} + +void TC0100SCNRenderBgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc) +{ + INT32 mx, my, Attr, Code, Colour, x, y, xSrc = 0, ySrc = 0, TileIndex = 0, Offset, Flip, xFlip, yFlip, p, dxScroll, dyScroll; + + UINT16 *VideoRam = (UINT16*)TC0100SCNRam[Chip]; + UINT16 *ScrollRam = (UINT16*)TC0100SCNRam[Chip] + (0xc000 / 2); + INT32 Columns = 64; + INT32 WidthMask = 0x1ff; + INT32 HeightMask = 0x1ff; + + if (TC0100SCNDblWidth[Chip]) { + VideoRam = (UINT16*)TC0100SCNRam[Chip]; + ScrollRam = (UINT16*)TC0100SCNRam[Chip] + (0x10000 / 2); + Columns = 128; + WidthMask = 0x3ff; + } + + // Render the tilemap to a buffer + if (TC0100SCNBgLayerUpdate[Chip]) { + memset(pTC0100SCNBgTempDraw[Chip], 0, Columns * 8 * 512 * sizeof(UINT16)); + for (my = 0; my < 64; my++) { + for (mx = 0; mx < Columns; mx++) { + Offset = 2 * TileIndex; + Attr = VideoRam[Offset]; + Code = (VideoRam[Offset + 1] & TC0100SCNGfxMask[Chip]) + (TC0100SCNGfxBank[Chip] << 15); + Colour = Attr & 0xff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (TC0100SCNFlipScreenX[Chip]) { + xFlip = !xFlip; + x = (Columns * 8) - 8 - x; + } + + if (TC0100SCNFlip[Chip]) { + xFlip = !xFlip; + x = (Columns * 8) - 8 - x; + yFlip = !yFlip; + y = 512 - 8 - y; + } + + if (xFlip) { + if (yFlip) { + RenderTile_FlipXY(pTC0100SCNBgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } else { + RenderTile_FlipX(pTC0100SCNBgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } + } else { + if (yFlip) { + RenderTile_FlipY(pTC0100SCNBgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } else { + RenderTile(pTC0100SCNBgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } + } + + TileIndex++; + } + } + + TC0100SCNBgLayerUpdate[Chip] = 0; + } + + dxScroll = TC0100SCNXOffset[Chip] + 16 - TC0100SCNClipStartX[Chip]; + dyScroll = TC0100SCNYOffset[Chip]; + + ySrc = (BgScrollY[Chip] + dyScroll) & HeightMask; + if (TC0100SCNFlip[Chip]) ySrc = (256 + 16 - ySrc) & HeightMask; + + for (y = 0; y < TC0100SCNClipHeight[Chip]; y++) { + xSrc = (BgScrollX[Chip] - ScrollRam[(y + dyScroll) & 0x1ff] + dxScroll + TC0100SCNClipStartX[Chip]) & WidthMask; + if(TC0100SCNFlip[Chip]) xSrc = (256 - 58 - xSrc) & WidthMask; + if (TC0100SCNFlipScreenX[Chip]) xSrc = (256 - 64 - xSrc) & WidthMask; + + for (x = TC0100SCNClipStartX[Chip]; x < TC0100SCNClipStartX[Chip] + TC0100SCNClipWidth[Chip]; x++) { + p = pTC0100SCNBgTempDraw[Chip][((ySrc & HeightMask) * Columns * 8) + xSrc]; + + if ((p & 0x0f) != 0 || Opaque) { + pTransDraw[(y * nScreenWidth) + x] = p; +// if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(y * TC0100SCNClipWidth[Chip]) + (x - TC0100SCNClipStartX[Chip])] = 1; + if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(y * nScreenWidth) + x] = 1; + } + xSrc = (xSrc + 1); + xSrc &= WidthMask; + } + ySrc = (ySrc + 1); + ySrc &= HeightMask; + } +} + +void TC0100SCNRenderFgLayer(INT32 Chip, INT32 Opaque, UINT8 *pSrc) +{ + INT32 mx, my, Attr, Code, Colour, x, y, xSrc = 0, ySrc = 0, TileIndex = 0, Offset, Flip, xFlip, yFlip, p, ColumnOffset, dxScroll, dyScroll; + + UINT16 *VideoRam = (UINT16*)TC0100SCNRam[Chip] + (0x8000 / 2); + UINT16 *ScrollRam = (UINT16*)TC0100SCNRam[Chip] + (0xc400 / 2); + UINT16 *ColumnRam = (UINT16*)TC0100SCNRam[Chip] + (0xe000 / 2); + INT32 Columns = 64; + INT32 WidthMask = 0x1ff; + INT32 HeightMask = 0x1ff; + + if (TC0100SCNDblWidth[Chip]) { + VideoRam = (UINT16*)TC0100SCNRam[Chip] + (0x8000 / 2); + ScrollRam = (UINT16*)TC0100SCNRam[Chip] + (0x10400 / 2); + ColumnRam = (UINT16*)TC0100SCNRam[Chip] + (0x10800 / 2); + Columns = 128; + WidthMask = 0x3ff; + } + + // Render the tilemap to a buffer + if (TC0100SCNFgLayerUpdate[Chip]) { + memset(pTC0100SCNFgTempDraw[Chip], 0, Columns * 8 * 512 * sizeof(UINT16)); + for (my = 0; my < 64; my++) { + for (mx = 0; mx < Columns; mx++) { + Offset = 2 * TileIndex; + Attr = VideoRam[Offset]; + Code = (VideoRam[Offset + 1] & TC0100SCNGfxMask[Chip]) + (TC0100SCNGfxBank[Chip] << 15); + Colour = Attr & 0xff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + if (TC0100SCNFlipScreenX[Chip]) { + xFlip = !xFlip; + x = (Columns * 8) - 8 - x; + } + + if (TC0100SCNFlip[Chip]) { + xFlip = !xFlip; + x = (Columns * 8) - 8 - x; + yFlip = !yFlip; + y = 512 - 8 -y; + } + + if (xFlip) { + if (yFlip) { + RenderTile_FlipXY(pTC0100SCNFgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } else { + RenderTile_FlipX(pTC0100SCNFgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } + } else { + if (yFlip) { + RenderTile_FlipY(pTC0100SCNFgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } else { + RenderTile(pTC0100SCNFgTempDraw[Chip], Code, x, y, Colour, TC0100SCNColourDepth[Chip], TC0100SCNPaletteOffset[Chip], Columns * 8, pSrc); + } + } + + TileIndex++; + } + } + + TC0100SCNFgLayerUpdate[Chip] = 0; + } + + dxScroll = TC0100SCNXOffset[Chip] + 16 - TC0100SCNClipStartX[Chip]; + dyScroll = TC0100SCNYOffset[Chip]; + + ySrc = (FgScrollY[Chip] + dyScroll) & HeightMask; + if (TC0100SCNFlip[Chip]) ySrc = (256 + 16 - ySrc) & HeightMask; + + for (y = 0; y < TC0100SCNClipHeight[Chip]; y++) { + xSrc = (FgScrollX[Chip] - ScrollRam[(y + dyScroll) & 0x1ff] + dxScroll + TC0100SCNClipStartX[Chip]) & WidthMask; + if (TC0100SCNFlip[Chip]) xSrc = (256 - 58 - xSrc) & WidthMask; + if (TC0100SCNFlipScreenX[Chip]) xSrc = (256 - 64 - xSrc) & WidthMask; + + for (x = TC0100SCNClipStartX[Chip]; x < TC0100SCNClipStartX[Chip] + TC0100SCNClipWidth[Chip]; x++) { + ColumnOffset = ColumnRam[(xSrc & 0x3ff) / 8]; + p = pTC0100SCNFgTempDraw[Chip][(((ySrc - ColumnOffset) & HeightMask) * Columns * 8) + xSrc]; + + if ((p & 0x0f) != 0 || Opaque) { + pTransDraw[(y * nScreenWidth) + x] = p; +// if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(y * TC0100SCNClipWidth[Chip]) + (x - TC0100SCNClipStartX[Chip])] = 2; + if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(y * nScreenWidth) + x] = 2; + } + xSrc = (xSrc + 1); + xSrc &= WidthMask; + } + ySrc = (ySrc + 1); + ySrc &= HeightMask; + } +} + +static INT32 TC0100SCNPlaneOffsets[2] = { 8, 0 }; +static INT32 TC0100SCNXOffsets[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static INT32 TC0100SCNYOffsets[8] = { 0, 16, 32, 48, 64, 80, 96, 112 }; + +void TC0100SCNRenderCharLayer(INT32 Chip) +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)TC0100SCNRam[Chip] + (0x4000 / 2); + UINT16 *CharRam = (UINT16*)TC0100SCNRam[Chip] + (0x6000 / 2); + INT32 Columns = 64; + INT32 Rows = 64; + + if (TC0100SCNDblWidth[Chip]) { + VideoRam = (UINT16*)TC0100SCNRam[Chip] + (0x12000 / 2); + CharRam = (UINT16*)TC0100SCNRam[Chip] + (0x11000 / 2); + Columns = 128; + Rows = 32; + } + + GfxDecode(256, 2, 8, 8, TC0100SCNPlaneOffsets, TC0100SCNXOffsets, TC0100SCNYOffsets, 0x80, (UINT8*)CharRam, TC0100SCNChars[Chip]); + + for (my = 0; my < Rows; my++) { + for (mx = 0; mx < Columns; mx++) { + Attr = VideoRam[TileIndex]; + Code = Attr & 0xff; + Colour = (Attr >> 6) & 0xfc; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + x = 8 * mx; + y = 8 * my; + + x -= 16; + if (!TC0100SCNFlip[Chip] && !TC0100SCNFlipScreenX[Chip]) x -= TC0100SCNXOffset[Chip]; + if (TC0100SCNFlip[Chip] || TC0100SCNFlipScreenX[Chip]) x += TC0100SCNXOffset[Chip]; + y -= TC0100SCNYOffset[Chip]; + + if (TC0100SCNFlipScreenX[Chip]) { + xFlip = !xFlip; + x = TC0100SCNClipWidth[Chip] - x; + } + + if (TC0100SCNFlip[Chip]) { + xFlip = !xFlip; + x = TC0100SCNClipWidth[Chip] - x; + yFlip = !yFlip; + y = TC0100SCNClipHeight[Chip] + 8 - y; + } + + if (!TC0100SCNDblWidth[Chip]) { + if (!TC0100SCNFlip[Chip] && !TC0100SCNFlipScreenX[Chip]) x -= CharScrollX[Chip] & 0x1ff; + if (TC0100SCNFlip[Chip] || TC0100SCNFlipScreenX[Chip]) x += CharScrollX[Chip] & 0x1ff; + + if (x < -8) x += 512; + if (x >= 512) x -= 512; + + if (!TC0100SCNFlip[Chip]) y -= CharScrollY[Chip] & 0x1ff; + if (TC0100SCNFlip[Chip]) y += CharScrollY[Chip] & 0x1ff; + + if (y < -8) y += 512; + if (y >= 512) y -= 512; + } else { + if (!TC0100SCNFlip[Chip] && !TC0100SCNFlipScreenX[Chip]) x -= CharScrollX[Chip] & 0x3ff; + if (TC0100SCNFlip[Chip] || TC0100SCNFlipScreenX[Chip]) x += CharScrollX[Chip] & 0x3ff; + + if (x < -8) x += 1024; + if (x >= 1024) x -= 1024; + + if (!TC0100SCNFlip[Chip]) y -= CharScrollY[Chip] & 0xff; + if (TC0100SCNFlip[Chip]) y += CharScrollY[Chip] & 0xff; + + if (y < -8) y += 256; + if (y >= 256) y -= 256; + } + + INT32 px, py; + + UINT32 nPalette = Colour << 2; + + for (py = 0; py < 8; py++) { + for (px = 0; px < 8; px++) { + UINT8 c = TC0100SCNChars[Chip][(Code * 64) + (py * 8) + px]; + if (xFlip) c = TC0100SCNChars[Chip][(Code * 64) + (py * 8) + (7 - px)]; + if (yFlip) c = TC0100SCNChars[Chip][(Code * 64) + ((7 - py) * 8) + px]; + if (xFlip && yFlip) c = TC0100SCNChars[Chip][(Code * 64) + ((7 - py) * 8) + (7 - px)]; + + if (c) { + INT32 xPos = x + px + TC0100SCNClipStartX[Chip]; + INT32 yPos = y + py; + + if (yPos >= 0 && yPos < TC0100SCNClipHeight[Chip]) { + UINT16* pPixel = pTransDraw + (yPos * nScreenWidth); + + if (xPos >= TC0100SCNClipStartX[Chip] && xPos < TC0100SCNClipStartX[Chip] + TC0100SCNClipWidth[Chip]) { + pPixel[xPos] = c | nPalette | TC0100SCNPaletteOffset[Chip]; +// if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(yPos * TC0100SCNClipWidth[Chip]) + xPos - TC0100SCNClipStartX[Chip]] = 4; + if (TC0100SCNPriorityMap[Chip]) TC0100SCNPriorityMap[Chip][(yPos * nScreenWidth) + xPos] = 4; + } + } + } + } + } + + TileIndex++; + } + } +} + +void TC0100SCNReset() +{ + for (INT32 i = 0;i < TC0100SCNNum; i++) { + memset(TC0100SCNCtrl[i], 0, 8); + memset(TC0100SCNChars[i], 0, 256 * 8 * 8); + + BgScrollX[i] = 0; + BgScrollY[i] = 0; + FgScrollX[i] = 0; + FgScrollY[i] = 0; + CharScrollX[i] = 0; + CharScrollY[i] = 0; + TC0100SCNFlip[i] = 0; + TC0100SCNGfxBank[i] = 0; + TC0100SCNDblWidth[i] = 0; + TC0100SCNBgLayerUpdate[i] = 1; + TC0100SCNFgLayerUpdate[i] = 1; + } +} + +void TC0100SCNInit(INT32 Chip, INT32 nNumTiles, INT32 xOffset, INT32 yOffset, INT32 xFlip, UINT8 *PriorityMap) +{ + TC0100SCNRam[Chip] = (UINT8*)malloc(0x14000); + memset(TC0100SCNRam[Chip], 0, 0x14000); + + TC0100SCNChars[Chip] = (UINT8*)malloc(256 * 8 * 8); + memset(TC0100SCNChars[Chip], 0, 256 * 8 * 8); + + pTC0100SCNBgTempDraw[Chip] = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + memset(pTC0100SCNBgTempDraw[Chip], 0, 1024 * 512 * sizeof(UINT16)); + + pTC0100SCNFgTempDraw[Chip] = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + memset(pTC0100SCNFgTempDraw[Chip], 0, 1024 * 512 * sizeof(UINT16)); + + TC0100SCNXOffset[Chip] = xOffset; + TC0100SCNYOffset[Chip] = yOffset; + TC0100SCNFlipScreenX[Chip] = xFlip; + TC0100SCNPriorityMap[Chip] = PriorityMap; + TC0100SCNColourDepth[Chip] = 4; + TC0100SCNGfxMask[Chip] = nNumTiles - 1; + TC0100SCNDblWidth[Chip] = 0; + TC0100SCNClipWidth[Chip] = nScreenWidth; + TC0100SCNClipHeight[Chip] = nScreenHeight; + TC0100SCNClipStartX[Chip] = 0; + TC0100SCNPaletteOffset[Chip] = 0; + TC0100SCNFgLayerUpdate[Chip] = 1; + TC0100SCNBgLayerUpdate[Chip] = 1; + + if (!TC0100SCNClipWidth[Chip] || !TC0100SCNClipHeight[Chip]) bprintf(PRINT_IMPORTANT, _T("TC0100SCNInit called before GenericTilesInit\n")); + + TaitoIC_TC0100SCNInUse = 1; + TC0100SCNNum++; +} + +void TC0100SCNSetColourDepth(INT32 Chip, INT32 ColourDepth) +{ + TC0100SCNColourDepth[Chip] = ColourDepth; +} + +void TC0100SCNSetGfxMask(INT32 Chip, INT32 Mask) +{ + TC0100SCNGfxMask[Chip] = Mask; +} + +void TC0100SCNSetGfxBank(INT32 Chip, INT32 Bank) +{ + TC0100SCNGfxBank[Chip] = Bank & 0x01; +} + +void TC0100SCNSetClipArea(INT32 Chip, INT32 ClipWidth, INT32 ClipHeight, INT32 ClipStartX) +{ + TC0100SCNClipWidth[Chip] = ClipWidth; + TC0100SCNClipHeight[Chip] = ClipHeight; + TC0100SCNClipStartX[Chip] = ClipStartX; +} + +void TC0100SCNSetPaletteOffset(INT32 Chip, INT32 PaletteOffset) +{ + TC0100SCNPaletteOffset[Chip] = PaletteOffset; +} + +void TC0100SCNExit() +{ + for (INT32 i = 0; i < TC0100SCNNum; i++) { + if (TC0100SCNRam[i]) { + free(TC0100SCNRam[i]); + TC0100SCNRam[i] = NULL; + } + + if (TC0100SCNChars[i]) { + free(TC0100SCNChars[i]); + TC0100SCNChars[i] = NULL; + } + + if (pTC0100SCNBgTempDraw[i]) { + free(pTC0100SCNBgTempDraw[i]); + pTC0100SCNBgTempDraw[i] = NULL; + } + + if (pTC0100SCNFgTempDraw[i]) { + free(pTC0100SCNFgTempDraw[i]); + pTC0100SCNFgTempDraw[i] = NULL; + } + + memset(TC0100SCNCtrl[i], 0, 8); + + BgScrollX[i] = 0; + BgScrollY[i] = 0; + FgScrollX[i] = 0; + FgScrollY[i] = 0; + CharScrollX[i] = 0; + CharScrollY[i] = 0; + TC0100SCNXOffset[i] = 0; + TC0100SCNYOffset[i] = 0; + TC0100SCNFlipScreenX[i] = 0; + TC0100SCNFlip[i] = 0; + TC0100SCNPriorityMap[i] = NULL; + TC0100SCNColourDepth[i] = 0; + TC0100SCNGfxBank[i] = 0; + TC0100SCNGfxMask[i] = 0; + TC0100SCNDblWidth[i] = 0; + TC0100SCNClipWidth[i] = 0; + TC0100SCNClipHeight[i] = 0; + TC0100SCNClipStartX[i] = 0; + TC0100SCNPaletteOffset[i] = 0; + TC0100SCNBgLayerUpdate[i] = 0; + TC0100SCNFgLayerUpdate[i] = 0; + } + + TC0100SCNNum = 0; +} + +void TC0100SCNScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0100SCNRam[0]; + ba.nLen = 0x14000; + ba.szName = "TC0100SCN Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0100SCNCtrl[0]); + SCAN_VAR(BgScrollX); + SCAN_VAR(BgScrollY); + SCAN_VAR(FgScrollX); + SCAN_VAR(FgScrollY); + SCAN_VAR(CharScrollX); + SCAN_VAR(CharScrollY); + SCAN_VAR(TC0100SCNFlip); + SCAN_VAR(TC0100SCNGfxBank); + SCAN_VAR(TC0100SCNDblWidth); + } +} diff --git a/src/burn/drivers/taito/tc0110pcr.cpp b/src/burn/drivers/taito/tc0110pcr.cpp new file mode 100644 index 00000000..463af5a7 --- /dev/null +++ b/src/burn/drivers/taito/tc0110pcr.cpp @@ -0,0 +1,194 @@ +// TC0110PCR + +#include "burnint.h" +#include "taito_ic.h" + +#define MAX_TC0110PCR 3 + +static UINT8 *TC0110PCRRam[MAX_TC0110PCR]; +UINT32 *TC0110PCRPalette = NULL; +static INT32 TC0110PCRAddr[MAX_TC0110PCR]; +INT32 TC0110PCRTotalColours; + +static inline UINT8 pal5bit(UINT8 bits) +{ + bits &= 0x1f; + return (bits << 3) | (bits >> 2); +} + +static inline UINT8 pal4bit(UINT8 bits) +{ + bits &= 0x0f; + return (bits << 4) | (bits); +} + +UINT16 TC0110PCRWordRead(INT32 Chip) +{ + UINT16 *PalRam = (UINT16*)TC0110PCRRam[Chip]; + return PalRam[TC0110PCRAddr[Chip]]; +} + +void TC0110PCRWordWrite(INT32 Chip, INT32 Offset, UINT16 Data) +{ + INT32 PaletteOffset = Chip * 0x1000; + + switch (Offset) { + case 0: { + TC0110PCRAddr[Chip] = (Data >> 1) & 0xfff; + return; + } + + case 1: { + UINT16 *PalRam = (UINT16*)TC0110PCRRam[Chip]; + INT32 r, g, b; + + PalRam[TC0110PCRAddr[Chip]] = Data; + + r = pal5bit(Data >> 0); + g = pal5bit(Data >> 5); + b = pal5bit(Data >> 10); + + TC0110PCRPalette[TC0110PCRAddr[Chip] | PaletteOffset] = BurnHighCol(r, g, b, 0); + return; + } + } +} + +void TC0110PCRStep1WordWrite(INT32 Chip, INT32 Offset, UINT16 Data) +{ + INT32 PaletteOffset = Chip * 0x1000; + + switch (Offset) { + case 0: { + TC0110PCRAddr[Chip] = Data & 0xfff; + return; + } + + case 1: { + UINT16 *PalRam = (UINT16*)TC0110PCRRam[Chip]; + INT32 r, g, b; + + PalRam[TC0110PCRAddr[Chip]] = Data; + + r = pal5bit(Data >> 0); + g = pal5bit(Data >> 5); + b = pal5bit(Data >> 10); + + TC0110PCRPalette[TC0110PCRAddr[Chip] | PaletteOffset] = BurnHighCol(r, g, b, 0); + return; + } + } +} + +void TC0110PCRStep14rbgWordWrite(INT32 Chip, INT32 Offset, UINT16 Data) +{ + INT32 PaletteOffset = Chip * 0x1000; + + switch (Offset) { + case 0: { + TC0110PCRAddr[Chip] = Data & 0xfff; + return; + } + + case 1: { + UINT16 *PalRam = (UINT16*)TC0110PCRRam[Chip]; + INT32 r, g, b; + + PalRam[TC0110PCRAddr[Chip]] = Data; + + r = pal4bit(Data >> 0); + g = pal4bit(Data >> 4); + b = pal4bit(Data >> 8); + + TC0110PCRPalette[TC0110PCRAddr[Chip] | PaletteOffset] = BurnHighCol(r, g, b, 0); + return; + } + } +} + +void TC0110PCRStep1RBSwapWordWrite(INT32 Chip, INT32 Offset, UINT16 Data) +{ + INT32 PaletteOffset = Chip * 0x1000; + + switch (Offset) { + case 0: { + TC0110PCRAddr[Chip] = Data & 0xfff; + return; + } + + case 1: { + UINT16 *PalRam = (UINT16*)TC0110PCRRam[Chip]; + INT32 r, g, b; + + PalRam[TC0110PCRAddr[Chip]] = Data; + + r = pal5bit(Data >> 10); + g = pal5bit(Data >> 5); + b = pal5bit(Data >> 0); + + TC0110PCRPalette[TC0110PCRAddr[Chip] | PaletteOffset] = BurnHighCol(r, g, b, 0); + return; + } + } +} + +void TC0110PCRReset() +{ + TC0110PCRAddr[0] = 0; +} + +void TC0110PCRInit(INT32 Num, INT32 nNumColours) +{ + for (INT32 i = 0; i < Num; i++) { + TC0110PCRRam[i] = (UINT8*)malloc(0x4000); + memset(TC0110PCRRam[i], 0, 0x4000); + } + + TC0110PCRPalette = (UINT32*)malloc(nNumColours * sizeof(UINT32)); + memset(TC0110PCRPalette, 0, nNumColours); + + TC0110PCRTotalColours = nNumColours; + + TaitoIC_TC0110PCRInUse = 1; +} + +void TC0110PCRExit() +{ + for (INT32 i = 0; i < MAX_TC0110PCR; i++) { + if (TC0110PCRRam[i]) { + free(TC0110PCRRam[i]); + TC0110PCRRam[i] = NULL; + } + TC0110PCRAddr[i] = 0; + } + + if (TC0110PCRPalette) { + free(TC0110PCRPalette); + TC0110PCRPalette = NULL; + } + + TC0110PCRTotalColours = 0; +} + +void TC0110PCRScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0110PCRRam[0]; + ba.nLen = 0x4000; + ba.szName = "TC0110PCR Ram"; + BurnAcb(&ba); + + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0110PCRPalette; + ba.nLen = TC0110PCRTotalColours * sizeof(UINT32); + ba.szName = "TC0110PCR Palette"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0110PCRAddr[0]); + } +} diff --git a/src/burn/drivers/taito/tc0140syt.cpp b/src/burn/drivers/taito/tc0140syt.cpp new file mode 100644 index 00000000..d50510c6 --- /dev/null +++ b/src/burn/drivers/taito/tc0140syt.cpp @@ -0,0 +1,238 @@ +// TC0140SYT + +#include "burnint.h" +#include "taito_ic.h" + +#define TC0140SYT_PORT01_FULL (0x01) +#define TC0140SYT_PORT23_FULL (0x02) +#define TC0140SYT_PORT01_FULL_MASTER (0x04) +#define TC0140SYT_PORT23_FULL_MASTER (0x08) + +typedef struct TC0140SYT +{ + UINT8 SlaveData[4]; + UINT8 MasterData[4]; + UINT8 MainMode; + UINT8 SubMode; + UINT8 Status; + UINT8 NmiEnabled; + UINT8 NmiReq; +} TC0140SYT; + +static struct TC0140SYT tc0140syt; + +static void InterruptController(void) +{ + if (tc0140syt.NmiReq && tc0140syt.NmiEnabled ) { + ZetNmi(); + tc0140syt.NmiReq = 0; + } +} + +void TC0140SYTPortWrite(UINT8 Data) +{ + Data &= 0x0f; + + tc0140syt.MainMode = Data; +} + +UINT8 TC0140SYTCommRead() +{ + switch (tc0140syt.MainMode) { + case 0x00: { + return tc0140syt.MasterData[tc0140syt.MainMode++]; + } + + case 0x01: { + tc0140syt.Status &= ~TC0140SYT_PORT01_FULL_MASTER; + return tc0140syt.MasterData[tc0140syt.MainMode++]; + } + + case 0x02: { + return tc0140syt.MasterData[tc0140syt.MainMode++]; + } + + case 0x03: { + tc0140syt.Status &= ~TC0140SYT_PORT23_FULL_MASTER; + return tc0140syt.MasterData[tc0140syt.MainMode++]; + } + + case 0x04: { + return tc0140syt.Status; + } + } + + return 0; +} + +void TC0140SYTCommWrite(UINT8 Data) +{ + Data &= 0x0f; + + switch (tc0140syt.MainMode) { + case 0x00: { + tc0140syt.SlaveData[tc0140syt.MainMode++] = Data; + return; + } + + case 0x01: { + tc0140syt.SlaveData[tc0140syt.MainMode++] = Data; + tc0140syt.Status |= TC0140SYT_PORT01_FULL; + tc0140syt.NmiReq = 1; + return; + } + + case 0x02: { + tc0140syt.SlaveData[tc0140syt.MainMode++] = Data; + return; + } + + case 0x03: { + tc0140syt.SlaveData[tc0140syt.MainMode++] = Data; + tc0140syt.Status |= TC0140SYT_PORT23_FULL; + tc0140syt.NmiReq = 1; + return; + } + + case 0x04: { + if (Data) { + ZetOpen(0); + ZetReset(); + ZetClose(); + } + return; + } + } +} + +void TC0140SYTSlavePortWrite(UINT8 Data) +{ + Data &= 0x0f; + tc0140syt.SubMode = Data; +} + +UINT8 TC0140SYTSlaveCommRead() +{ + UINT8 nRet = 0; + + switch (tc0140syt.SubMode) { + case 0x00: { + nRet = tc0140syt.SlaveData[tc0140syt.SubMode++]; + break; + } + + case 0x01: { + tc0140syt.Status &= ~TC0140SYT_PORT01_FULL; + nRet = tc0140syt.SlaveData[tc0140syt.SubMode++]; + break; + } + + case 0x02: { + nRet = tc0140syt.SlaveData[tc0140syt.SubMode++]; + break; + } + + case 0x03: { + tc0140syt.Status &= ~TC0140SYT_PORT23_FULL; + nRet = tc0140syt.SlaveData[tc0140syt.SubMode++]; + break; + } + + case 0x04: { + nRet = tc0140syt.Status; + break; + } + } + + InterruptController(); + + return nRet; +} + +void TC0140SYTSlaveCommWrite(UINT8 Data) +{ + Data &= 0x0f; + + switch (tc0140syt.SubMode) { + case 0x00: { + tc0140syt.MasterData[tc0140syt.SubMode++]= Data; + break; + } + + case 0x01: { + tc0140syt.MasterData[tc0140syt.SubMode++]= Data; + tc0140syt.Status |= TC0140SYT_PORT01_FULL_MASTER; + break; + } + + case 0x02: { + tc0140syt.MasterData[tc0140syt.SubMode++]= Data; + break; + } + + case 0x03: { + tc0140syt.MasterData[tc0140syt.SubMode++]= Data; + tc0140syt.Status |= TC0140SYT_PORT23_FULL_MASTER; + break; + } + + case 0x05: { + tc0140syt.NmiEnabled = 0; + break; + } + + case 0x06: { + tc0140syt.NmiEnabled = 1; + break; + } + } + + InterruptController(); +} + +void TC0140SYTReset() +{ + for (INT32 i = 0; i < 4; i++) { + tc0140syt.SlaveData[i] = 0; + tc0140syt.MasterData[i] = 0; + } + + tc0140syt.MainMode = 0; + tc0140syt.SubMode = 0; + tc0140syt.Status = 0; + tc0140syt.NmiEnabled = 0; + tc0140syt.NmiReq = 0; +} + +void TC0140SYTInit() +{ + TaitoIC_TC0140SYTInUse = 1; +} + +void TC0140SYTExit() +{ + INT32 i; + + for (i = 0; i < 4; i++) { + tc0140syt.SlaveData[i] = 0; + tc0140syt.MasterData[i] = 0; + } + + tc0140syt.MainMode = 0; + tc0140syt.SubMode = 0; + tc0140syt.Status = 0; + tc0140syt.NmiEnabled = 0; + tc0140syt.NmiReq = 0; +} + +void TC0140SYTScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(tc0140syt); + } +} + +#undef TC0140SYT_PORT01_FULL +#undef TC0140SYT_PORT23_FULL +#undef TC0140SYT_PORT01_FULL_MASTER +#undef TC0140SYT_PORT23_FULL_MASTER diff --git a/src/burn/drivers/taito/tc0150rod.cpp b/src/burn/drivers/taito/tc0150rod.cpp new file mode 100644 index 00000000..6caf7af4 --- /dev/null +++ b/src/burn/drivers/taito/tc0150rod.cpp @@ -0,0 +1,461 @@ +// TC0150ROD + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *TC0150RODRom = NULL; +UINT8 *TC0150RODRam = NULL; +static INT32 TC0150RODFlipScreenX; + +static void DrawScanLine(INT32 y, const UINT16 *src, INT32 Transparent, INT32 /*Pri*/) +{ + UINT16* pPixel; + INT32 Length; + + if (!TC0150RODFlipScreenX) { + pPixel = pTransDraw + (y * nScreenWidth); + + Length = nScreenWidth; + + if (Transparent) { + while (Length--) { + UINT16 sPixel = *src++; + if (sPixel < 0x7fff) { + *pPixel = sPixel; + } + pPixel++; + } + } else { + while (Length--) { + *pPixel++ = *src++; + } + } + } else { + pPixel = pTransDraw + (y * nScreenWidth) + (nScreenWidth - 1); + + Length = nScreenWidth; + + if (Transparent) { + while (Length--) { + UINT16 sPixel = *src++; + if (sPixel < 0x7fff) { + *pPixel = sPixel; + } + pPixel--; + } + } else { + while (Length--) { + *pPixel-- = *src++; + } + } + } +} + +void TC0150RODDraw(INT32 yOffs, INT32 pOffs, INT32 Type, INT32 RoadTrans, INT32 LowPriority, INT32 HighPriority) +{ + INT32 xOffs = 0xa7; + yOffs += 16; + + UINT16* RoadRam = (UINT16*)TC0150RODRam; + + UINT16 ScanLine[512]; + UINT16 RoadALine[512]; + UINT16 RoadBLine[512]; + UINT16 *Dst16; + UINT16 *RoadA; + UINT16 *RoadB; + UINT16 *RoadGfx = (UINT16*)TC0150RODRom; + + UINT16 Pixel, Colour, GfxWord; + UINT16 RoadAClipL, RoadAClipR, RoadABodyCtrl; + UINT16 RoadBClipL, RoadBClipR, RoadBBodyCtrl;; + UINT16 Pri, PixPri; + UINT8 Priorities[6]; + INT32 xIndex, RoadRamIndex, RoadRam2Index, i; + INT32 xOffset, PalOffs, PalLOffs, PalROffs; + INT32 RoadGfxTileNum, ColBank, RoadCentre; + INT32 RoadCtrl = RoadRam[0xfff]; + INT32 LeftEdge, RightEdge, Begin, End, RightOver, LeftOver; + INT32 LineNeedsDrawing, DrawTopRoadLine, BackgroundOnly; + + INT32 y = 0; + + INT32 RoadAAddress = yOffs * 4 + ((RoadCtrl & 0x0300) << 2); + INT32 RoadBAddress = yOffs * 4 + ((RoadCtrl & 0x0c00) << 0); + + INT32 PrioritySwitchLine = (RoadCtrl & 0x00ff) - yOffs; + + do { + LineNeedsDrawing = 0; + RoadRamIndex = RoadAAddress + (y * 4); + RoadRam2Index = RoadBAddress + (y * 4); + + RoadA = RoadALine; + RoadB = RoadBLine; + + for (i = 0; i < nScreenWidth; i++) { + *RoadA++ = 0x8000; + *RoadB++ = 0x8000; + } + + Priorities[0] = 1; + Priorities[1] = 1; + Priorities[2] = 2; + Priorities[3] = 3; + Priorities[4] = 3; + Priorities[5] = 1; + + RoadAClipR = RoadRam[RoadRamIndex + 0]; + RoadAClipL = RoadRam[RoadRamIndex + 1]; + RoadABodyCtrl = RoadRam[RoadRamIndex + 2]; + RoadBClipR = RoadRam[RoadRam2Index + 0]; + RoadBClipL = RoadRam[RoadRam2Index + 1]; + RoadBBodyCtrl = RoadRam[RoadRam2Index + 2]; + + if (RoadABodyCtrl & 0x2000) Priorities[2] += 2; + if (RoadBBodyCtrl & 0x2000) Priorities[2] += 1; + if (RoadAClipL & 0x2000) Priorities[3] -= 1; + if (RoadBClipL & 0x2000) Priorities[3] -= 2; + if (RoadAClipR & 0x2000) Priorities[4] -= 1; + if (RoadBClipR & 0x2000) Priorities[4] -= 2; + + if (Priorities[4] == 0) Priorities[4]++; + + // Road A + PalROffs = (RoadAClipR & 0x1000) >> 11; + PalLOffs = (RoadAClipL & 0x1000) >> 11; + + xOffset = RoadABodyCtrl & 0x7ff; + PalOffs = (RoadABodyCtrl & 0x1800) >> 11; + ColBank = (RoadRam[RoadRamIndex + 3] & 0xf000) >> 10; + RoadGfxTileNum = RoadRam[RoadRamIndex + 3] & 0x3ff; + RightOver = 0; + LeftOver = 0; + + RoadCentre = 0x5ff - ((-xOffset + xOffs) & 0x7ff); + LeftEdge = RoadCentre - (RoadAClipL & 0x3ff); + RightEdge = RoadCentre + 1 + (RoadAClipR & 0x3ff); + + if (RoadAClipL || RoadAClipR) LineNeedsDrawing = 1; + + Begin = LeftEdge + 1; + if (Begin < 0) Begin = 0; + + End = RightEdge; + if (End > nScreenWidth) End = nScreenWidth; + + if (RightEdge < 0) { + RightOver = -RightEdge; + RightEdge = 0; + } + + if (LeftEdge >= nScreenWidth) + { + LeftOver = LeftEdge - nScreenWidth + 1; + LeftEdge = nScreenWidth - 1; + } + + BackgroundOnly = (RoadCentre > (nScreenWidth - 2 + (1024 / 2))) ? 1 : 0; + + Colour = ((pOffs + ColBank + PalOffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[2] << 12; + + xIndex = (-xOffset + xOffs + Begin) & 0x7ff; + RoadA = RoadALine + nScreenWidth - 1 - Begin; + + if ((LineNeedsDrawing) && (Begin < End)) { + for (i = Begin; i < End; i++) { + if (RoadGfxTileNum) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + if ((Pixel) || !(RoadTrans)) { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadA-- = (Colour + Pixel) | Pri; + } + else *RoadA-- = 0xf000; + } + else RoadA--; + + xIndex++; + xIndex &= 0x7ff; + } + } + + // Left Edge of Road A + Colour = ((pOffs + ColBank + PalLOffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[0] << 12; + + if (BackgroundOnly) { + if (RoadAClipL & 0x8000) { + RoadA = RoadALine; + for (i = 0; i < nScreenWidth; i++) { + *RoadA++ = (Colour + (Type ? (3) : (0))); + } + } + } else { + if ((LeftEdge >= 0) && (LeftEdge < nScreenWidth)) { + xIndex = ((1024 / 2) - 1 - LeftOver) & 0x7ff; + + RoadA = RoadALine + nScreenWidth - 1 - LeftEdge; + + if (LineNeedsDrawing) { + for (i = LeftEdge; i >= 0; i--) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + PixPri = (Pixel == 0) ? (0) : (Pri); + + if ((Pixel == 0) && !(RoadAClipL & 0x8000)) { + RoadA++; + } else { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadA++ = (Colour + Pixel) | PixPri; + } + + xIndex--; + xIndex &= 0x7ff; + } + } + } + } + + // Right Edge of Road A + Colour = ((pOffs + ColBank + PalROffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[1] << 12; + + if ((RightEdge < nScreenWidth) && (RightEdge >= 0)) { + xIndex = ((1024 / 2) + RightOver) & 0x7ff; + + RoadA = RoadALine + nScreenWidth - 1 - RightEdge; + + if (LineNeedsDrawing) { + for (i = RightEdge; i < nScreenWidth; i++) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + PixPri = (Pixel == 0) ? (0) : (Pri); + + if ((Pixel == 0) && !(RoadAClipR & 0x8000)) { + RoadA--; + } else { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadA-- = (Colour + Pixel) | PixPri; + } + + xIndex++; + xIndex &= 0x7ff; + } + } + } + + // Road B + PalROffs = (RoadBClipR & 0x1000) >> 11; + PalLOffs = (RoadBClipL & 0x1000) >> 11; + xOffset = RoadBBodyCtrl & 0x7ff; + PalOffs = (RoadBBodyCtrl & 0x1800) >> 11; + ColBank = (RoadRam[RoadRam2Index + 3] & 0xf000) >> 10; + RoadGfxTileNum = RoadRam[RoadRam2Index + 3] & 0x3ff; + RightOver = 0; + LeftOver = 0; + + RoadCentre = 0x5ff - ((-xOffset + xOffs) & 0x7ff); + + LeftEdge = RoadCentre - (RoadBClipL & 0x3ff); + RightEdge = RoadCentre + 1 + (RoadBClipR & 0x3ff); + + if (((RoadBClipL) || (RoadBClipR)) && ((RoadCtrl & 0x800) || (Type == 2))) { + DrawTopRoadLine = 1; + LineNeedsDrawing = 1; + } + else { + DrawTopRoadLine = 0; + } + + Begin = LeftEdge + 1; + if (Begin < 0) Begin = 0; + + End = RightEdge; + if (End > nScreenWidth) { + End = nScreenWidth; + } + + if (RightEdge < 0) { + RightOver = -RightEdge; + RightEdge = 0; + } + + if (LeftEdge >= nScreenWidth) + { + LeftOver = LeftEdge - nScreenWidth + 1; + LeftEdge = nScreenWidth - 1; + } + + BackgroundOnly = (RoadCentre > (nScreenWidth - 2 + (1024 / 2))) ? 1 : 0; + + Colour = ((pOffs + ColBank + PalOffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[5] << 12; + + xIndex = (-xOffset + xOffs + Begin) & 0x7ff; + + if (xIndex > 0x3ff) { + RoadB = RoadBLine + nScreenWidth - 1 - Begin; + + if (DrawTopRoadLine && RoadGfxTileNum && (Begin < End)) { + for (i = Begin; i < End; i++) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + if ((Pixel) || !(RoadTrans)) { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadB-- = (Colour + Pixel) | Pri; + } + else *RoadB-- = 0xf000; + + xIndex++; + xIndex &= 0x7ff; + } + } + } + + // Left Edge of Road B + Colour = ((pOffs + ColBank + PalLOffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[3] << 12; + + if (BackgroundOnly) { + if ((RoadBClipL & 0x8000) && DrawTopRoadLine) { + RoadB = RoadBLine; + for (i = 0; i < nScreenWidth; i++) { + *RoadB++ = (Colour + (Type ? (3) : (0))); + } + } + } else { + if ((LeftEdge >= 0) && (LeftEdge < nScreenWidth)) { + xIndex = ((1024 / 2) - 1 - LeftOver) & 0x7ff; + + RoadB = RoadBLine + nScreenWidth - 1 - LeftEdge; + + if (LineNeedsDrawing) { + for (i = LeftEdge; i >= 0; i--) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + PixPri = (Pixel == 0) ? (0) : (Pri); + + if ((Pixel == 0) && !(RoadBClipL & 0x8000)) { + RoadB++; + } else { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadB++ = (Colour + Pixel) | PixPri; + } + + xIndex--; + if (xIndex < 0) break; + } + } + } + } + + // Right Edge of Road B + Colour = ((pOffs + ColBank + PalROffs) << 4) + ((Type) ? (1) : (4)); + Pri = Priorities[4] << 12; + + if ((RightEdge < nScreenWidth) && (RightEdge >= 0)) { + xIndex = ((1024 / 2) + RightOver) & 0x7ff; + + RoadB = RoadBLine + nScreenWidth - 1 - RightEdge; + + if (DrawTopRoadLine) { + for (i = RightEdge; i < nScreenWidth; i++) { + GfxWord = RoadGfx[(RoadGfxTileNum << 8) + (xIndex >> 3)]; + Pixel = ((GfxWord >> (7 - (xIndex % 8) + 8)) & 1) * 2 + ((GfxWord >> (7 - (xIndex % 8))) & 1); + + PixPri = (Pixel == 0) ? (0) : (Pri); + + if ((Pixel == 0) && !(RoadBClipR & 0x8000)) { + RoadB--; + } else { + if (Type) Pixel = (Pixel - 1) & 3; + *RoadB-- = (Colour + Pixel) | PixPri; + } + + xIndex++; + if (xIndex > 0x3ff) break; + } + } + } + + if (LineNeedsDrawing) { + Dst16 = ScanLine; + + for (i = 0; i < nScreenWidth; i++) { + if (RoadALine[i] == 0x8000) { + *Dst16++ = RoadBLine[i] & 0x8fff; + } + else if (RoadBLine[i] == 0x8000) { + *Dst16++ = RoadALine[i] & 0x8fff; + } + else { + if ((RoadBLine[i] & 0x7000) > (RoadALine[i] & 0x7000)) { + *Dst16++ = RoadBLine[i] & 0x8fff; + } else { + *Dst16++ = RoadALine[i] & 0x8fff; + } + } + } + + if (y > PrioritySwitchLine) { + DrawScanLine(y, ScanLine, 1, HighPriority); + } else { + DrawScanLine(y, ScanLine, 1, LowPriority); + } + } + + y++; + } while (y < nScreenHeight); +} + +void TC0150RODReset() +{ + +} + +void TC0150RODInit(INT32 nRomSize, INT32 xFlip) +{ + TC0150RODRom = (UINT8*)malloc(nRomSize); + memset(TC0150RODRom, 0, nRomSize); + TC0150RODRam = (UINT8*)malloc(0x2000); + memset(TC0150RODRam, 0, 0x2000); + + TC0150RODFlipScreenX = xFlip; + + TaitoIC_TC0150RODInUse = 1; +} + +void TC0150RODExit() +{ + if (TC0150RODRom) { + free(TC0150RODRom); + TC0150RODRom = NULL; + } + + if (TC0150RODRam) { + free(TC0150RODRam); + TC0150RODRam = NULL; + } + + TC0150RODFlipScreenX = 0; +} + +void TC0150RODScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0150RODRam; + ba.nLen = 0x2000; + ba.szName = "TC0150ROD Ram"; + BurnAcb(&ba); + } +} diff --git a/src/burn/drivers/taito/tc0180vcu.cpp b/src/burn/drivers/taito/tc0180vcu.cpp new file mode 100644 index 00000000..73c82b3a --- /dev/null +++ b/src/burn/drivers/taito/tc0180vcu.cpp @@ -0,0 +1,713 @@ +#include "tiles_generic.h" +#include "taito_ic.h" +#include "taito.h" + +UINT8 *TC0180VCURAM; +UINT8 *TC0180VCUScrollRAM; +UINT8 *TC0180VCUFbRAM; // framebuffer ram + +static UINT16 *TC0180VCUFramebuffer[2]; + +static INT32 TC0180VCU_y_offset; +static INT32 TC0180VCU_x_offset; + +static UINT8 TC0180VCUControl[0x10]; + +static UINT8 *tiledata[2]; +static UINT32 tilemask[2]; +static UINT8 *transtiletab[2]; + +static UINT8 *dummy_tile = NULL; + +static INT32 *TC0180VCU_scrollx[2]; +static INT32 *TC0180VCU_scrolly[2]; + +static INT32 flipscreen; +static INT32 framebuffer_page; + +void TC0180VCUFramebufferWrite(INT32 offset) +{ + offset &= 0x3fffe; + INT32 data = *((UINT16*)(TC0180VCUFbRAM + offset)); + + INT32 fb = (offset >> 17) & 1; + + offset &= 0x1fffe; + + TC0180VCUFramebuffer[fb][offset + 0] = data >> 8; + TC0180VCUFramebuffer[fb][offset + 1] = data & 0xff; +} + +UINT16 TC0180VCUFramebufferRead(INT32 offset) +{ + offset &= 0x3fffe; + + INT32 fb = (offset >> 17) & 1; + + offset &= 0x1fffe; + + return (TC0180VCUFramebuffer[fb][offset + 0] << 8) | (TC0180VCUFramebuffer[fb][offset + 1] & 0xff); +} + +UINT8 TC0180VCUReadControl() +{ + return TC0180VCUControl[7]; +} + +UINT8 TC0180VCUReadRegs(INT32 offset) +{ + offset >>= 1; + offset &= 0x0f; + + return TC0180VCUControl[offset]; +} + +void TC0180VCUWriteRegs(INT32 offset, INT32 data) +{ + offset >>= 1; + offset &= 0x0f; + + TC0180VCUControl[offset] = data; + + if (offset == 7) { + if (data & 0x80) { + framebuffer_page = (data & 0x40) ? 0 : 1; + } + } +} + +void TC0180VCUReset() +{ + for (INT32 i = 0; i < 2; i++) { + + memset (TC0180VCUFramebuffer[i], 0, 512 * 256 * sizeof(UINT16)); + memset (TC0180VCU_scrollx[i], 0, 256 * sizeof(INT32)); + memset (TC0180VCU_scrolly[i], 0, 256 * sizeof(INT32)); + } + + memset (TC0180VCUControl, 0, 16); + memset (TC0180VCURAM, 0, 0x010000); + memset (TC0180VCUScrollRAM, 0, 0x000800); + memset (TC0180VCUFbRAM, 0, 0x040000); + + flipscreen = 0; + framebuffer_page = 0; +} + +static void create_transtile_table(INT32 tile) +{ + INT32 size = (tile) ? (16 * 16) : (8 * 8); + + if (tilemask[tile]) { + INT32 len = (tilemask[tile] + 1); + + transtiletab[tile] = (UINT8*)malloc(len); + + memset (transtiletab[tile], 1, len); + + for (INT32 i = 0; i < len * size; i++) + { + if (tiledata[tile][i]) { + transtiletab[tile][i / size] = 0; + i|=(size-1); + } + } + } +} + +void TC0180VCUInit(UINT8 *gfx0, INT32 mask0, UINT8 *gfx1, INT32 mask1, INT32 global_x, INT32 global_y) +{ + TaitoIC_TC0180VCUInUse = 1; + + for (INT32 i = 0; i < 2; i++) + { + TC0180VCUFramebuffer[i] = (UINT16*)malloc(512 * 256 * sizeof(UINT16)); + TC0180VCU_scrollx[i] = (INT32*)malloc(257 * sizeof(INT32)); + TC0180VCU_scrolly[i] = (INT32*)malloc(257 * sizeof(INT32)); + } + + TC0180VCURAM = (UINT8*)malloc(0x010000); + TC0180VCUScrollRAM = (UINT8*)malloc(0x000800); + TC0180VCUFbRAM = (UINT8*)malloc(0x040000); + + tilemask[0] = mask0; + tilemask[1] = mask1; + tiledata[0] = gfx0; + tiledata[1] = gfx1; + + if (mask0) create_transtile_table(0); + if (mask1) create_transtile_table(1); + + if (mask0 == 0) { + dummy_tile = (UINT8*)malloc(0x100); + transtiletab[1] = (UINT8*)malloc(1); + tiledata[1] = dummy_tile; + } + + TC0180VCU_y_offset = global_y; + TC0180VCU_x_offset = global_x; + + TC0180VCUReset(); +} + +void TC0180VCUExit() +{ + for (INT32 i = 0; i < 2; i++) + { + if (TC0180VCU_scrollx[i]) { + free (TC0180VCU_scrollx[i]); + TC0180VCU_scrollx[i] = NULL; + } + + if (TC0180VCU_scrolly[i]) { + free (TC0180VCU_scrolly[i]); + TC0180VCU_scrolly[i] = NULL; + } + + tilemask[i] = ~0; + tiledata[i] = NULL; + + if (TC0180VCUFramebuffer[i]) { + free (TC0180VCUFramebuffer[i]); + TC0180VCUFramebuffer[i] = NULL; + } + + if (transtiletab[i]) { + free (transtiletab[i]); + transtiletab[i] = NULL; + } + } + + if (dummy_tile) { + free (dummy_tile); + dummy_tile = NULL; + } + + if (TC0180VCURAM) { + free (TC0180VCURAM); + TC0180VCURAM = NULL; + } + + if (TC0180VCUScrollRAM) { + free (TC0180VCUScrollRAM); + TC0180VCUScrollRAM = NULL; + } + + if (TC0180VCUFbRAM) { + free (TC0180VCUFbRAM); + TC0180VCUFbRAM = NULL; + } + + TC0180VCU_y_offset = 0; + TC0180VCU_x_offset = 0; +} + +static void update_scroll(INT32 plane) +{ + flipscreen = TC0180VCUReadControl() & 0x10; + + UINT16 *scrollram = (UINT16*)TC0180VCUScrollRAM; + + INT32 lines_per_block = 256 - TC0180VCUControl[2 + plane]; + INT32 number_of_blocks = 256 / lines_per_block; + + for (INT32 i = 0; i < number_of_blocks; i++) + { + INT32 scrollx = scrollram[plane * 0x200 + i * 2 * lines_per_block + 0]; + INT32 scrolly = scrollram[plane * 0x200 + i * 2 * lines_per_block + 1]; + + INT32 min_y = (i + 0) * lines_per_block - 0; + INT32 max_y = (i + 1) * lines_per_block - 1; + + if (min_y <= max_y) + { + for (INT32 y = min_y; y <= max_y; y++) { + TC0180VCU_scrollx[plane][y] = -(scrollx & 0x3ff); + TC0180VCU_scrolly[plane][y] = -(scrolly & 0x3ff); + } + } + } +} + +void TC0180VCUDrawLayer(INT32 colorbase, INT32 ctrl_offset, INT32 transparent) // 0, -1 +{ + update_scroll(ctrl_offset); + + UINT16 *ram = (UINT16*)TC0180VCURAM; + + INT32 bank0 = (TC0180VCUControl[ctrl_offset] << 12) & 0xf000; // tile bank + INT32 bank1 = (TC0180VCUControl[ctrl_offset] << 8) & 0xf000; // color bank + + INT32 *scroll_x = TC0180VCU_scrollx[ctrl_offset]; + INT32 *scroll_y = TC0180VCU_scrolly[ctrl_offset]; + + INT32 lines = TC0180VCUControl[2 + ctrl_offset]; + + if (lines) + { + INT32 screen_width = nScreenWidth - 1; + INT32 screen_height = nScreenHeight - 1; + + UINT16 *dest; + + for (INT32 sy = 0; sy < nScreenHeight; sy++) + { + if (flipscreen) { + dest = pTransDraw + (screen_height - sy) * nScreenWidth; + } else { + dest = pTransDraw + sy * nScreenWidth; + } + + INT32 scly = (sy + scroll_y[(sy + TC0180VCU_y_offset) & 0xff] + TC0180VCU_y_offset) & 0x3ff; + + INT32 scly_off = (scly >> 4) << 6; + INT32 scly_ts = (scly & 0x0f) << 4; + + INT32 sclx_base = scroll_x[(sy + TC0180VCU_y_offset) & 0xff] + TC0180VCU_x_offset; + + for (INT32 sx = 0; sx < nScreenWidth + 16; sx+=16) + { + INT32 sclx = (sx + sclx_base) & 0x3ff; + + INT32 offs = scly_off | (sclx >> 4); + + INT32 attr = ram[offs + bank1]; + INT32 code = ram[offs + bank0]; + INT32 color = (attr & 0x003f) + colorbase; + code &= tilemask[1]; + + if (!transparent) { + if (transtiletab[1][code]) continue; + } + + { + INT32 sx4 = sx - (sclx & 0x0f); + + color <<= 4; + UINT8 *src = tiledata[1] + code * 256; + + if (attr & 0x80) { // flipy + src += (scly_ts ^ 0xf0); + } else { + src += (scly_ts); + } + + INT32 flipx = ((attr & 0x40) >> 6) * 0x0f; + + if (flipscreen) { + if (!transparent) { // transparency + for (INT32 sxx = 0; sxx < 16; sxx++, sx4++) { + if (sx4 >= nScreenWidth || sx4 < 0) continue; + + INT32 pxl = src[sxx ^ flipx]; + + if (pxl != transparent) { + dest[(screen_width - sx4)] = pxl | color; + } + } + } else { + for (INT32 sxx = 0; sxx < 16; sxx++, sx4++) { + if (sx4 >= nScreenWidth || sx4 < 0) continue; + + dest[(screen_width - sx4)] = src[sxx ^ flipx] | color; + } + } + } else { + if (!transparent) { // transparency + for (INT32 sxx = 0; sxx < 16; sxx++, sx4++) { + if (sx4 >= nScreenWidth || sx4 < 0) continue; + + INT32 pxl = src[sxx ^ flipx]; + + if (pxl != transparent) { + dest[sx4] = pxl | color; + } + } + } else { + for (INT32 sxx = 0; sxx < 16; sxx++, sx4++) { + if (sx4 >= nScreenWidth || sx4 < 0) continue; + + dest[sx4] = src[sxx ^ flipx] | color; + } + } + } + } + } + } + } + else + { + for (INT32 offs = 0; offs < 64 * 64; offs++) + { + INT32 sx = (offs & 0x3f) << 4; + INT32 sy = (offs >> 6) << 4; + + sy -= scroll_y[(sy + TC0180VCU_y_offset) & 0xff]; + if (sy >= 0x400-15) sy -= 0x400; + + sx -= scroll_x[(sy + TC0180VCU_y_offset) & 0xff]; + if (sx >= 0x400-15) sx -= 0x400; + + INT32 attr = ram[offs + bank1]; + INT32 code = ram[offs + bank0]; + + INT32 color = (attr & 0x003f) + colorbase; + INT32 flipx = (attr & 0x0040); + INT32 flipy = (attr & 0x0080); + + code &= tilemask[1]; + + if (flipscreen) { + sx = (nScreenWidth - 16) - sx; + sy = 240 - sy; + flipx ^= 0x40; + flipy ^= 0x80; + } + + sx -= TC0180VCU_x_offset; + sy -= TC0180VCU_y_offset; + + if (!transparent) { + if (transtiletab[1][code]) continue; + + if (sy >= 0 && sy < (nScreenHeight - 15) && sx >= 0 && sx < (nScreenWidth - 15)) { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } else { + Render16x16Tile_Mask_FlipY(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } else { + Render16x16Tile_Mask(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } else { + Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } else { + Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, tiledata[1]); + } + } + } + } else { + if (sy >= 0 && sy < (nScreenHeight - 15) && sx >= 0 && sx < (nScreenWidth - 15)) { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } else { + Render16x16Tile_FlipY(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } + } else { + if (flipx) { + Render16x16Tile_FlipX(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } else { + Render16x16Tile(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } + } + } else { + if (flipy) { + if (flipx) { + Render16x16Tile_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } else { + Render16x16Tile_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } + } else { + if (flipx) { + Render16x16Tile_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } else { + Render16x16Tile_Clip(pTransDraw, code, sx, sy, color, 4, 0, tiledata[1]); + } + } + } + } + } + } +} + +void TC0180VCUDrawCharLayer(INT32 colorbase) +{ + if (tilemask[0] == 0) return; + + UINT16 *ram = (UINT16*)TC0180VCURAM; + + INT32 bank0 = (TC0180VCUControl[6] & 0x0f) << 11; // tile bank + + for (INT32 offs = 0; offs < 64 * 32; offs++) + { + INT32 sx = (offs & 0x3f) << 3; + INT32 sy = (offs >> 6) << 3; + + INT32 code = ram[offs + bank0]; + INT32 color = (code >> 12) + colorbase; + + code = (code & 0x07ff) | (TC0180VCUControl[4 + ((code & 0x800) >> 11)] << 11); + + code &= tilemask[0]; + + if (transtiletab[0][code]) continue; + + if (flipscreen) { + sx = (nScreenWidth - 8) - sx; + sy = 248 - sy; + + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx - TC0180VCU_x_offset, sy - TC0180VCU_y_offset, color, 4, 0, 0, tiledata[0]); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, code, sx - TC0180VCU_x_offset, sy - TC0180VCU_y_offset, color, 4, 0, 0, tiledata[0]); + } + } +} + +void TC0180VCUFramebufferDraw(INT32 priority, INT32 color_base) +{ + priority <<= 4; + + INT32 ctrl = TC0180VCUReadControl(); + + if (ctrl & 0x08) + { + if (ctrl & 0x10) // flip screen + { + for (INT32 y = 0; y < nScreenHeight; y++) + { + UINT16 *src = TC0180VCUFramebuffer[framebuffer_page & 1] + (y + TC0180VCU_y_offset) * 512 + TC0180VCU_x_offset; + UINT16 *dst = pTransDraw + ((nScreenHeight - 1) - y) * nScreenWidth + (nScreenWidth - 1); + + for (INT32 x = 0; x < nScreenWidth; x++) + { + INT32 c = *src++; + + if (c != 0) *dst = color_base + c; + dst--; + } + } + } + else + { + for (INT32 y = 0; y < nScreenHeight; y++) + { + UINT16 *src = TC0180VCUFramebuffer[framebuffer_page & 1] + (y + TC0180VCU_y_offset) * 512 + TC0180VCU_x_offset; + UINT16 *dst = pTransDraw + y * nScreenWidth; + + for (INT32 x = 0; x < nScreenWidth; x++) + { + INT32 c = *src++; + + if (c != 0) *dst = color_base + c; + dst++; + } + } + } + } + else + { + if (ctrl & 0x10) // flip screen + { + for (INT32 y = 0; y < nScreenHeight; y++) + { + UINT16 *src = TC0180VCUFramebuffer[framebuffer_page & 1] + (y + TC0180VCU_y_offset) * 512 + TC0180VCU_x_offset; + UINT16 *dst = pTransDraw + ((nScreenHeight - 1) - y) * nScreenWidth + (nScreenWidth - 1); + + for (INT32 x = 0; x < nScreenWidth; x++) + { + INT32 c = *src++; + + if (c != 0 && (c & 0x10) == priority) + *dst = color_base + c; + dst--; + } + } + } + else + { + for (INT32 y = 0; y < nScreenHeight; y++) + { + UINT16 *src = TC0180VCUFramebuffer[framebuffer_page & 1] + (y + TC0180VCU_y_offset) * 512 + TC0180VCU_x_offset; + UINT16 *dst = pTransDraw + y * nScreenWidth; + + for (INT32 x = 0; x < nScreenWidth; x++) + { + INT32 c = *src++; + + if (c != 0 && (c & 0x10) == priority) + *dst = color_base + c; + dst++; + } + } + } + } +} + +void TC0180VCUDrawSprite(UINT16 *dest) +{ + INT32 t_swide = nScreenWidth; nScreenWidth = 512; // hack to allow use of generic tile routines + INT32 t_shigh = nScreenHeight; nScreenHeight = 256; + + INT32 xlatch = 0; + INT32 ylatch = 0; + INT32 x_no = 0; + INT32 y_no = 0; + INT32 x_num = 0; + INT32 y_num = 0; + INT32 big_sprite = 0; + UINT32 zoomx; + UINT32 zoomy; + UINT32 zx; + UINT32 zy; + UINT32 zoomxlatch = 0; + UINT32 zoomylatch = 0; + + UINT16 *ram = (UINT16*)TaitoSpriteRam; + + for (INT32 offs = (0x1980 - 16) / 2; offs >=0; offs -= 8) + { + INT32 code = ram[offs + 0] & tilemask[1]; + INT32 color = ram[offs + 1]; + INT32 x = ram[offs + 2] & 0x03ff; + INT32 y = ram[offs + 3] & 0x03ff; + + INT32 data = ram[offs + 5]; + + INT32 flipx = color & 0x4000; + INT32 flipy = color & 0x8000; + + if (x >= 0x200) x -= 0x400; + if (y >= 0x200) y -= 0x400; + + if (data) + { + if (!big_sprite) + { + x_num = (data >> 8) & 0xff; + y_num = (data >> 0) & 0xff; + x_no = 0; + y_no = 0; + xlatch = x; + ylatch = y; + data = ram[offs + 4]; + zoomxlatch = (data >> 8) & 0xff; + zoomylatch = (data >> 0) & 0xff; + big_sprite = 1; + } + } + + data = ram[offs + 4]; + zoomx = (data >> 8) & 0xff; + zoomy = (data >> 0) & 0xff; + zx = (0x100 - zoomx) / 16; + zy = (0x100 - zoomy) / 16; + + if (big_sprite) + { + zoomx = zoomxlatch; + zoomy = zoomylatch; + + x = xlatch + x_no * (0x100 - zoomx) / 16; + y = ylatch + y_no * (0x100 - zoomy) / 16; + zx = xlatch + (x_no + 1) * (0x100 - zoomx) / 16 - x; + zy = ylatch + (y_no + 1) * (0x100 - zoomy) / 16 - y; + y_no++; + + if (y_no > y_num) + { + y_no = 0; + x_no++; + + if (x_no > x_num) big_sprite = 0; + } + } + + if (zoomx || zoomy ) + { + RenderZoomedTile(dest, tiledata[1], code, (color & 0x3f) << 4, 0, x, y, flipx, flipy, 16, 16, zx << 12, zy << 12); + } + else + { + if (flipy) { + if (flipx) { + Render16x16Tile_Mask_FlipXY_Clip(dest, code, x, y, color & 0x3f, 4, 0, 0, tiledata[1]); + } else { + Render16x16Tile_Mask_FlipY_Clip(dest, code, x, y, color & 0x3f, 4, 0, 0, tiledata[1]); + } + } else { + if (flipx) { + Render16x16Tile_Mask_FlipX_Clip(dest, code, x, y, color & 0x3f, 4, 0,0, tiledata[1]); + } else { + Render16x16Tile_Mask_Clip(dest, code, x, y, color & 0x3f, 4, 0, 0, tiledata[1]); + } + } + } + } + + nScreenWidth = t_swide; + nScreenHeight = t_shigh; +} + +void TC0180VCUBufferSprites() +{ + INT32 ctrl = TC0180VCUReadControl(); + + if (~ctrl & 0x01) { + memset (TC0180VCUFbRAM + framebuffer_page * 0x20000, 0, 512 * 256); + memset (TC0180VCUFramebuffer[framebuffer_page], 0, 512 * 256 * sizeof(UINT16)); + } + + if (~ctrl & 0x80) { + framebuffer_page ^= 1; + } + + if (tilemask[1]) { + TC0180VCUDrawSprite(TC0180VCUFramebuffer[framebuffer_page]); + } +} + +void TC0180VCUScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_VOLATILE) + { + bprintf (0, _T("yup\n")); + + ba.Data = (UINT8*)TC0180VCUFramebuffer[0]; + ba.nLen = 512 * 256 * sizeof(UINT16); + ba.szName = "Framebuffer 0"; + BurnAcb(&ba); + + ba.Data = (UINT8*)TC0180VCUFramebuffer[1]; + ba.nLen = 512 * 256 * sizeof(UINT16); + ba.szName = "Framebuffer 1"; + BurnAcb(&ba); + + ba.Data = TC0180VCURAM; + ba.nLen = 0x10000; + ba.szName = "Tilemap RAM"; + BurnAcb(&ba); + + ba.Data = TC0180VCUScrollRAM; + ba.nLen = 0x00800; + ba.szName = "Scroll RAM"; + BurnAcb(&ba); + + ba.Data = TC0180VCUFbRAM; + ba.nLen = 0x00800; + ba.szName = "Framebuffer RAM"; + BurnAcb(&ba); + + ba.Data = TC0180VCUControl; + ba.nLen = 0x00010; + ba.szName = "Control RAM"; + BurnAcb(&ba); + + SCAN_VAR(framebuffer_page); + } +} diff --git a/src/burn/drivers/taito/tc0220ioc.cpp b/src/burn/drivers/taito/tc0220ioc.cpp new file mode 100644 index 00000000..e730e0e4 --- /dev/null +++ b/src/burn/drivers/taito/tc0220ioc.cpp @@ -0,0 +1,133 @@ +// TC0220IOC + +#include "burnint.h" +#include "taito_ic.h" + +UINT8 TC0220IOCInputPort0[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0220IOCInputPort1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0220IOCInputPort2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0220IOCDip[2] = { 0, 0 }; +UINT8 TC0220IOCInput[3] = { 0, 0, 0 }; + +static UINT8 TC0220IOCRegs[8]; +static UINT8 TC0220IOCPort; + +extern UINT8 TaitoCoinLockout[4]; + +UINT8 TC0220IOCPortRead() +{ + return TC0220IOCPort; +} + +UINT8 TC0220IOCHalfWordPortRead() +{ + return TC0220IOCPortRead(); +} + +UINT8 TC0220IOCRead(UINT8 Port) +{ + switch (Port) { + case 0x00: { + return TC0220IOCDip[0]; + } + + case 0x01: { + return TC0220IOCDip[1]; + } + + case 0x02: { + return TC0220IOCInput[0]; + } + + case 0x03: { + return TC0220IOCInput[1]; + } + + case 0x04: { + return TC0220IOCRegs[4]; + } + + case 0x07: { + return TC0220IOCInput[2]; + } + } + + bprintf(PRINT_IMPORTANT, _T("Unmapped TC0220IOC Read at %x\n"), Port); + + return 0; +} + +UINT8 TC0220IOCPortRegRead() +{ + return TC0220IOCRead(TC0220IOCPort); +} + +UINT8 TC0220IOCHalfWordRead(INT32 Offset) +{ + return TC0220IOCRead(Offset); +} + +void TC0220IOCWrite(UINT8 Port, UINT8 Data) +{ + TC0220IOCRegs[Port] = Data; + + if (Port == 0) { + TaitoWatchdog = 0; + } + + if (Port == 4) { + TaitoCoinLockout[0] = ~Data & 0x01; + TaitoCoinLockout[1] = ~Data & 0x02; + // coin counters 0x04 & 0x08 + } +} + +void TC0220IOCHalfWordPortRegWrite(UINT16 Data) +{ + TC0220IOCWrite(TC0220IOCPort, Data & 0xff); +} + +static void TC0220IOCPortWrite(UINT8 Data) +{ + TC0220IOCPort = Data; +} + +void TC0220IOCHalfWordPortWrite(UINT16 Data) +{ + TC0220IOCPortWrite(Data & 0xff); +} + +void TC0220IOCHalfWordWrite(INT32 Offset, UINT16 Data) +{ + TC0220IOCWrite(Offset, Data & 0xff); +} + +void TC0220IOCReset() +{ + memset(TC0220IOCRegs, 0, 8); + TC0220IOCPort = 0; +} + +void TC0220IOCInit() +{ + TaitoIC_TC0220IOCInUse = 1; +} + +void TC0220IOCExit() +{ + memset(TC0220IOCRegs, 0, 8); + TC0220IOCPort = 0; +} + +void TC0220IOCScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0220IOCInputPort0); + SCAN_VAR(TC0220IOCInputPort1); + SCAN_VAR(TC0220IOCInputPort2); + SCAN_VAR(TC0220IOCDip); + SCAN_VAR(TC0220IOCInput); + SCAN_VAR(TC0220IOCRegs); + SCAN_VAR(TC0220IOCPort); + } +} diff --git a/src/burn/drivers/taito/tc0280grd.cpp b/src/burn/drivers/taito/tc0280grd.cpp new file mode 100644 index 00000000..f3a5dee1 --- /dev/null +++ b/src/burn/drivers/taito/tc0280grd.cpp @@ -0,0 +1,222 @@ +// TC0280GRD + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *TC0280GRDRam; +static UINT16 TC0280GRDCtrl[8]; +INT32 TC0280GRDBaseColour; +static INT32 TC0280GRDxMultiply; +static INT32 TC0280GRDXOffset; +static INT32 TC0280GRDYOffset; +static UINT8 *pTC0280GRDSrc = NULL; + +static UINT16 *pRozTileMapData = NULL; + +#define PLOTPIXEL_MASK(x, mc, po) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x] | po;} + +static void RenderTile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * 512) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += 512, pTileData += 8) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + } +} + +#undef PLOTPIXEL_MASK + +static void RozRender(UINT32 xStart, UINT32 yStart, INT32 xxInc, INT32 xyInc, INT32 yxInc, INT32 yyInc) +{ + UINT32 cx; + UINT32 cy; + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, Pix; + UINT16 *Dest = NULL; + UINT16 *VideoRam = (UINT16*)TC0280GRDRam; + + if (xxInc == (1 << 16) && xyInc == 0 && yxInc == 0 && yyInc == (1 << 16)) { + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex]; + Code = (Attr & 0x3fff); + Colour = ((Attr & 0xc000) >> 14) + TC0280GRDBaseColour; + + x = 8 * mx; + y = 8 * my; + + x -= (xStart >> 16) & 0x1ff; + y -= (yStart >> 16) & 0x1ff; + + if (x < -8) x += 512; + if (y < -8) y += 512; + + if (x >= 0 && x < (nScreenWidth - 8) && y >= 0 && y < (nScreenHeight - 8)) { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, pTC0280GRDSrc); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, pTC0280GRDSrc); + } + + TileIndex++; + } + } + + return; + } + + memset(pRozTileMapData, 0, 512 * 512 * sizeof(UINT16)); + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex]; + Code = (Attr & 0x3fff); + Colour = ((Attr & 0xc000) >> 14) + TC0280GRDBaseColour; + + x = 8 * mx; + y = 8 * my; + + RenderTile_Mask(pRozTileMapData, Code, x, y, Colour, 4, 0, 0, pTC0280GRDSrc); + + TileIndex++; + } + } + + y = 0; + while (y < nScreenHeight) { + x = 0; + cx = xStart; + cy = yStart; + + Dest = pTransDraw + (y * nScreenWidth); + + while (x < nScreenWidth) { + Pix = pRozTileMapData[(((cy >> 16) & 0x1ff) * 512) + ((cx >> 16) & 0x1ff)]; + if (Pix) { + *Dest++ = Pix; + } else { + Dest++; + } + + cx += xxInc; + cy += xyInc; + x++; + } + + xStart += yxInc; + yStart += yyInc; + y++; + } +} + +void TC0280GRDRenderLayer() +{ + UINT32 xStart, yStart; + INT32 xxInc, xyInc, yxInc, yyInc; + + xStart = ((TC0280GRDCtrl[0] & 0xff) << 16) + TC0280GRDCtrl[1]; + if (xStart & 0x800000) xStart -= 0x1000000; + xxInc = (INT16)TC0280GRDCtrl[2]; + xxInc *= TC0280GRDxMultiply; + yxInc = (INT16)TC0280GRDCtrl[3]; + + yStart = ((TC0280GRDCtrl[4] & 0xff) << 16) + TC0280GRDCtrl[5]; + if (yStart & 0x800000) yStart -= 0x1000000; + xyInc = (INT16)TC0280GRDCtrl[6]; + xyInc *= TC0280GRDxMultiply; + yyInc = (INT16)TC0280GRDCtrl[7]; + + xStart -= TC0280GRDXOffset * xxInc + TC0280GRDYOffset * yxInc; + yStart -= TC0280GRDXOffset * xyInc + TC0280GRDYOffset * yyInc; + + RozRender(xStart << 4, yStart << 4, xxInc << 4, xyInc << 4, yxInc << 4, yyInc << 4); +} + +void TC0280GRDCtrlWordWrite(UINT32 Offset, UINT16 Data) +{ + TC0280GRDCtrl[Offset] = Data; +} + +void TC0280GRDReset() +{ + memset(TC0280GRDCtrl, 0, 8); + + TC0280GRDBaseColour = 0; +} + +void TC0280GRDInit(INT32 xOffs, INT32 yOffs, UINT8 *pSrc) +{ + TC0280GRDRam = (UINT8*)malloc(0x2000); + memset(TC0280GRDRam, 0, 0x2000); + + pRozTileMapData = (UINT16*)malloc(512 * 512 * sizeof(UINT16)); + memset(pRozTileMapData, 0, 512 * 512 * sizeof(UINT16)); + + TC0280GRDXOffset = xOffs; + TC0280GRDYOffset = yOffs; + + pTC0280GRDSrc = pSrc; + + TC0280GRDxMultiply = 2; + + TaitoIC_TC0280GRDInUse = 1; +} + +void TC0430GRWInit(INT32 xOffs, INT32 yOffs, UINT8 *pSrc) +{ + TC0280GRDInit(xOffs, yOffs, pSrc); + + TC0280GRDxMultiply = 1; + + TaitoIC_TC0280GRDInUse = 0; + TaitoIC_TC0430GRWInUse = 1; +} + +void TC0280GRDExit() +{ + if (TC0280GRDRam) { + free(TC0280GRDRam); + TC0280GRDRam = NULL; + } + + if (pRozTileMapData) { + free(pRozTileMapData); + pRozTileMapData = NULL; + } + + memset(TC0280GRDCtrl, 0, 8); + + TC0280GRDBaseColour = 0; + + TC0280GRDxMultiply = 0; + TC0280GRDXOffset = 0; + TC0280GRDYOffset = 0; + + pTC0280GRDSrc = NULL; +} + +void TC0280GRDScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0280GRDRam; + ba.nLen = 0x2000; + ba.szName = "TC0280GRD Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0280GRDCtrl); + SCAN_VAR(TC0280GRDBaseColour); + } +} diff --git a/src/burn/drivers/taito/tc0360pri.cpp b/src/burn/drivers/taito/tc0360pri.cpp new file mode 100644 index 00000000..119b43d6 --- /dev/null +++ b/src/burn/drivers/taito/tc0360pri.cpp @@ -0,0 +1,43 @@ +// TC0360PRI + +#include "burnint.h" +#include "taito_ic.h" + +UINT8 TC0360PRIRegs[16]; + +void TC0360PRIWrite(UINT32 Offset, UINT8 Data) +{ + TC0360PRIRegs[Offset] = Data; +} + +void TC0360PRIHalfWordWrite(UINT32 Offset, UINT16 Data) +{ + TC0360PRIWrite(Offset, Data & 0xff); +} + +void TC0360PRIHalfWordSwapWrite(UINT32 Offset, UINT16 Data) +{ + if (Data & 0xff00) TC0360PRIWrite(Offset, (Data >> 8) & 0xff); +} + +void TC0360PRIReset() +{ + memset(TC0360PRIRegs, 0, 16); +} + +void TC0360PRIInit() +{ + TaitoIC_TC0360PRIInUse = 1; +} + +void TC0360PRIExit() +{ + memset(TC0360PRIRegs, 0, 16); +} + +void TC0360PRIScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0360PRIRegs); + } +} diff --git a/src/burn/drivers/taito/tc0480scp.cpp b/src/burn/drivers/taito/tc0480scp.cpp new file mode 100644 index 00000000..cf61e5c0 --- /dev/null +++ b/src/burn/drivers/taito/tc0480scp.cpp @@ -0,0 +1,885 @@ +// TC0480SCP + +#include "tiles_generic.h" +#include "taito_ic.h" + +UINT8 *TC0480SCPRam = NULL; +static UINT8 *TC0480SCPChars; +UINT16 TC0480SCPCtrl[0x18]; +static INT32 BgScrollX[4]; +static INT32 BgScrollY[4]; +static INT32 CharScrollX; +static INT32 CharScrollY; +static INT32 TC0480SCPTilesNum; +static INT32 TC0480SCPPriReg; +static INT32 TC0480SCPXOffset; +static INT32 TC0480SCPYOffset; +static INT32 TC0480SCPTextXOffset; +static INT32 TC0480SCPTextYOffset; +static UINT16 *pTC0480SCPTempDraw = NULL; +static INT32 TC0480SCPColBase; +static INT32 TC0480SCPDblWidth; + +static INT32 TC0480SCPYVisOffset; + +static const UINT16 TC0480SCPBgPriLookup[8] = +{ + 0x0123, + 0x1230, + 0x2301, + 0x3012, + 0x3210, + 0x2103, + 0x1032, + 0x0321 +}; + +#define PLOTPIXEL(x, po) pPixel[x] = nPalette | pTileData[x] | po; +#define PLOTPIXEL_FLIPX(x, a, po) pPixel[x] = nPalette | pTileData[a] | po; +#define PLOTPIXEL_MASK(x, mc, po) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x] | po;} +#define PLOTPIXEL_MASK_FLIPX(x, a, mc, po) if (pTileData[a] != mc) {pPixel[x] = nPalette | pTileData[a] | po;} +#define CLIPPIXEL(x, sx, mx, a) if ((sx + x) >= 0 && (sx + x) < mx) { a; }; + +static void RenderTile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + (StartY * TileMapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TileMapWidth, pTileData += 16) { + PLOTPIXEL( 0, nPaletteOffset); + PLOTPIXEL( 1, nPaletteOffset); + PLOTPIXEL( 2, nPaletteOffset); + PLOTPIXEL( 3, nPaletteOffset); + PLOTPIXEL( 4, nPaletteOffset); + PLOTPIXEL( 5, nPaletteOffset); + PLOTPIXEL( 6, nPaletteOffset); + PLOTPIXEL( 7, nPaletteOffset); + PLOTPIXEL( 8, nPaletteOffset); + PLOTPIXEL( 9, nPaletteOffset); + PLOTPIXEL(10, nPaletteOffset); + PLOTPIXEL(11, nPaletteOffset); + PLOTPIXEL(12, nPaletteOffset); + PLOTPIXEL(13, nPaletteOffset); + PLOTPIXEL(14, nPaletteOffset); + PLOTPIXEL(15, nPaletteOffset); + } +} + +static void RenderTile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + (StartY * TileMapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TileMapWidth, pTileData += 16) { + PLOTPIXEL_FLIPX(15, 0, nPaletteOffset); + PLOTPIXEL_FLIPX(14, 1, nPaletteOffset); + PLOTPIXEL_FLIPX(13, 2, nPaletteOffset); + PLOTPIXEL_FLIPX(12, 3, nPaletteOffset); + PLOTPIXEL_FLIPX(11, 4, nPaletteOffset); + PLOTPIXEL_FLIPX(10, 5, nPaletteOffset); + PLOTPIXEL_FLIPX( 9, 6, nPaletteOffset); + PLOTPIXEL_FLIPX( 8, 7, nPaletteOffset); + PLOTPIXEL_FLIPX( 7, 8, nPaletteOffset); + PLOTPIXEL_FLIPX( 6, 9, nPaletteOffset); + PLOTPIXEL_FLIPX( 5, 10, nPaletteOffset); + PLOTPIXEL_FLIPX( 4, 11, nPaletteOffset); + PLOTPIXEL_FLIPX( 3, 12, nPaletteOffset); + PLOTPIXEL_FLIPX( 2, 13, nPaletteOffset); + PLOTPIXEL_FLIPX( 1, 14, nPaletteOffset); + PLOTPIXEL_FLIPX( 0, 15, nPaletteOffset); + } +} + +static void RenderTile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TileMapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TileMapWidth, pTileData += 16) { + PLOTPIXEL( 0, nPaletteOffset); + PLOTPIXEL( 1, nPaletteOffset); + PLOTPIXEL( 2, nPaletteOffset); + PLOTPIXEL( 3, nPaletteOffset); + PLOTPIXEL( 4, nPaletteOffset); + PLOTPIXEL( 5, nPaletteOffset); + PLOTPIXEL( 6, nPaletteOffset); + PLOTPIXEL( 7, nPaletteOffset); + PLOTPIXEL( 8, nPaletteOffset); + PLOTPIXEL( 9, nPaletteOffset); + PLOTPIXEL(10, nPaletteOffset); + PLOTPIXEL(11, nPaletteOffset); + PLOTPIXEL(12, nPaletteOffset); + PLOTPIXEL(13, nPaletteOffset); + PLOTPIXEL(14, nPaletteOffset); + PLOTPIXEL(15, nPaletteOffset); + } +} + +static void RenderTile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TileMapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TileMapWidth, pTileData += 16) { + PLOTPIXEL_FLIPX(15, 0, nPaletteOffset); + PLOTPIXEL_FLIPX(14, 1, nPaletteOffset); + PLOTPIXEL_FLIPX(13, 2, nPaletteOffset); + PLOTPIXEL_FLIPX(12, 3, nPaletteOffset); + PLOTPIXEL_FLIPX(11, 4, nPaletteOffset); + PLOTPIXEL_FLIPX(10, 5, nPaletteOffset); + PLOTPIXEL_FLIPX( 9, 6, nPaletteOffset); + PLOTPIXEL_FLIPX( 8, 7, nPaletteOffset); + PLOTPIXEL_FLIPX( 7, 8, nPaletteOffset); + PLOTPIXEL_FLIPX( 6, 9, nPaletteOffset); + PLOTPIXEL_FLIPX( 5, 10, nPaletteOffset); + PLOTPIXEL_FLIPX( 4, 11, nPaletteOffset); + PLOTPIXEL_FLIPX( 3, 12, nPaletteOffset); + PLOTPIXEL_FLIPX( 2, 13, nPaletteOffset); + PLOTPIXEL_FLIPX( 1, 14, nPaletteOffset); + PLOTPIXEL_FLIPX( 0, 15, nPaletteOffset); + } +} + +static void RenderTile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + (StartY * TileMapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TileMapWidth, pTileData += 16) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(15, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + (StartY * TileMapWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += TileMapWidth, pTileData += 16) { + PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TileMapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TileMapWidth, pTileData += 16) { + PLOTPIXEL_MASK( 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK( 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK(15, nMaskColour, nPaletteOffset); + } +} + +static void RenderTile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = nTilePalette << nColourDepth; + pTileData = pTile + (nTileNumber << 8); + + INT32 TileMapWidth = 512; + if (TC0480SCPDblWidth) TileMapWidth = 1024; + + UINT16* pPixel = pDestDraw + ((StartY + 15) * TileMapWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= TileMapWidth, pTileData += 16) { + PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour, nPaletteOffset); + PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour, nPaletteOffset); + } +} + +#undef PLOTPIXEL +#undef PLOTPIXEL_FLIPX +#undef PLOTPIXEL_MASK +#undef CLIPPIXEL + +void TC0480SCPCtrlWordWrite(INT32 Offset, UINT16 Data) +{ + INT32 Flip = TC0480SCPPriReg & 0x40; + + TC0480SCPCtrl[Offset] = Data; + + switch (Offset) { + case 0x00: { + if (!Flip) Data = -Data; + BgScrollX[0] = Data; + break; + } + + case 0x01: { + Data += 4; + if (!Flip) Data = -Data; + BgScrollX[1] = Data; + break; + } + + case 0x02: { + Data += 8; + if (!Flip) Data = -Data; + BgScrollX[2] = Data; + break; + } + + case 0x03: { + Data += 12; + if (!Flip) Data = -Data; + BgScrollX[3] = Data; + break; + } + + case 0x04: { + if (Flip) Data = -Data; + BgScrollY[0] = Data; + break; + } + + case 0x05: { + if (Flip) Data = -Data; + BgScrollY[1] = Data; + break; + } + + case 0x06: { + if (Flip) Data = -Data; + BgScrollY[2] = Data; + break; + } + + case 0x07: { + if (Flip) Data = -Data; + BgScrollY[3] = Data; + break; + } + + case 0x08: // bg0 zoom + case 0x09: // bg1 zoom + case 0x0a: // bg2 zoom + case 0x0b: { // bg3 zoom + break; + } + + case 0x0c: { + if (!Flip) Data -= TC0480SCPTextXOffset; + if (Flip) Data += TC0480SCPTextXOffset; + CharScrollX = -Data; + break; + } + + case 0x0d: { + if (!Flip) Data -= TC0480SCPTextYOffset + TC0480SCPYVisOffset; + if (Flip) Data += TC0480SCPTextYOffset + TC0480SCPYVisOffset; + CharScrollY = -Data; + break; + } + + case 0x0f: { + TC0480SCPPriReg = Data; + TC0480SCPDblWidth = (TC0480SCPPriReg & 0x80) >> 7; + if (Data & 0x40) bprintf(PRINT_NORMAL, _T("Flip\n")); + break; + } + } +} + +static inline void DrawScanLine(INT32 y, const UINT16 *src, INT32 Transparent, INT32 /*Pri*/) +{ + UINT16* pPixel; + INT32 Length; + + pPixel = pTransDraw + (y * nScreenWidth); + + Length = nScreenWidth; + + if (Transparent) { + while (Length--) { + UINT16 sPixel = *src++; + if (sPixel < 0x7fff) { + *pPixel = sPixel; + } + pPixel++; + } + } else { + while (Length--) { + *pPixel++ = *src++; + } + } +} + +static void TC0480SCPRenderLayer01(INT32 Layer, INT32 Opaque, UINT8 *pSrc) +{ + INT32 mx, my, Attr, Code, Colour, x, y, sx, TileIndex = 0, Offset, Flip, xFlip, yFlip, xZoom, yZoom, i, yIndex, ySrcIndex, RowIndex, xIndex, xStep, Columns, WidthMask; + + UINT16 *Dst16, *Src16; + UINT16 ScanLine[512]; + UINT16 *pSrcTileMap = pTC0480SCPTempDraw; + + UINT16 *VideoRam = (UINT16*)TC0480SCPRam + 0x0000; + UINT16 *ScrollRam = (UINT16*)TC0480SCPRam + 0x2000; + + if (TC0480SCPDblWidth) { + VideoRam = (UINT16*)TC0480SCPRam + 0x0000; + ScrollRam = (UINT16*)TC0480SCPRam + 0x4000; + } + + if (Layer == 1) { + VideoRam = (UINT16*)TC0480SCPRam + 0x0800; + ScrollRam = (UINT16*)TC0480SCPRam + 0x2200; + + if (TC0480SCPDblWidth) { + VideoRam = (UINT16*)TC0480SCPRam + 0x1000; + ScrollRam = (UINT16*)TC0480SCPRam + 0x4200; + } + } + + Columns = 32; + WidthMask = 0x1ff; + if (TC0480SCPDblWidth) { + Columns = 64; + WidthMask = 0x3ff; + } + + xZoom = 0x10000 - (TC0480SCPCtrl[0x08 + Layer] & 0xff00); + yZoom = 0x10000 - (((TC0480SCPCtrl[0x08 + Layer] & 0xff) - 0x7f) * 512); + + // Render the tilemap to a buffer + memset(pTC0480SCPTempDraw, 0, 1024 * 512 * sizeof(UINT16)); + for (my = 0; my < 32; my++) { + for (mx = 0; mx < Columns; mx++) { + Offset = 2 * TileIndex; + Attr = VideoRam[Offset]; + Code = VideoRam[Offset + 1] & (TC0480SCPTilesNum - 1); + Colour = Attr & 0xff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + Colour += TC0480SCPColBase; + + x = 16 * mx; + y = 16 * my; + + if (Opaque) { + if (xFlip) { + if (yFlip) { + RenderTile_FlipXY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + RenderTile_FlipX(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_FlipY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + RenderTile(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + RenderTile_Mask_FlipXY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask_FlipX(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_Mask_FlipY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } + + TileIndex++; + } + } + + sx = ((BgScrollX[Layer] + 15 + Layer * 4) << 16) + ((255 - (TC0480SCPCtrl[0x10 + Layer] & 0xff)) << 8); + sx += (-TC0480SCPXOffset - 15 - Layer * 4) * xZoom; + + yIndex = (BgScrollY[Layer] << 16) + ((TC0480SCPCtrl[0x14 + Layer] & 0xff) << 8); + yIndex -= (-TC0480SCPYOffset - TC0480SCPYVisOffset) * yZoom; + + y = 0; + + do { + ySrcIndex = (yIndex >> 16) & 0x1ff; + + RowIndex = ySrcIndex; + + xIndex = sx - ((ScrollRam[RowIndex] << 16)) - ((ScrollRam[RowIndex + 0x800] << 8) & 0xffff); + + Src16 = pSrcTileMap + (ySrcIndex * Columns * 16); + Dst16 = ScanLine; + + xStep = xZoom; + + if (Opaque) { + for (i = 0; i < 512; i++) { + *Dst16++ = Src16[(xIndex >> 16) & WidthMask]; + xIndex += xStep; + } + } else { + for (i = 0; i < 512; i++) { + INT32 Pix = Src16[(xIndex >> 16) & WidthMask]; + + if ((Pix & 0x0f) != 0) { + *Dst16++ = Pix; + } else { + *Dst16++ = 0x8000; + } + xIndex += xStep; + } + } + + if (Opaque) { + DrawScanLine(y, ScanLine, 0, 0); + } else { + DrawScanLine(y, ScanLine, 1, 0); + } + + yIndex += yZoom; + y++; + } while (y < nScreenHeight); +} + +static void TC0480SCPRenderLayer23(INT32 Layer, INT32 Opaque, UINT8 *pSrc) +{ + INT32 mx, my, Attr, Code, Colour, x, y, sx, TileIndex = 0, Offset, Flip, xFlip, yFlip, xZoom, yZoom, i, yIndex, ySrcIndex, RowIndex, RowZoom, xIndex, xStep, Columns, WidthMask; + + UINT16 *Dst16, *Src16; + UINT16 ScanLine[512]; + UINT16 *pSrcTileMap = pTC0480SCPTempDraw; + + xZoom = 0x10000 - (TC0480SCPCtrl[0x08 + Layer] & 0xff00); + yZoom = 0x10000 - (((TC0480SCPCtrl[0x08 + Layer] & 0xff) - 0x7f) * 512); + + UINT16 *VideoRam = (UINT16*)TC0480SCPRam + 0x1000; + UINT16 *ScrollRam = (UINT16*)TC0480SCPRam + 0x2400; + UINT16 *RowZoomRam = (UINT16*)TC0480SCPRam + 0x3000; + UINT16 *ColumnRam = (UINT16*)TC0480SCPRam + 0x3400; + + if (TC0480SCPDblWidth) { + VideoRam = (UINT16*)TC0480SCPRam + 0x2000; + ScrollRam = (UINT16*)TC0480SCPRam + 0x4400; + RowZoomRam = (UINT16*)TC0480SCPRam + 0x5000; + ColumnRam = (UINT16*)TC0480SCPRam + 0x5400; + } + + if (Layer == 3) { + VideoRam = (UINT16*)TC0480SCPRam + 0x1800; + ScrollRam = (UINT16*)TC0480SCPRam + 0x2600; + RowZoomRam = (UINT16*)TC0480SCPRam + 0x3200; + ColumnRam = (UINT16*)TC0480SCPRam + 0x3600; + + if (TC0480SCPDblWidth) { + VideoRam = (UINT16*)TC0480SCPRam + 0x3000; + ScrollRam = (UINT16*)TC0480SCPRam + 0x4600; + RowZoomRam = (UINT16*)TC0480SCPRam + 0x5200; + ColumnRam = (UINT16*)TC0480SCPRam + 0x5600; + } + } + + Columns = 32; + WidthMask = 0x1ff; + if (TC0480SCPDblWidth) { + Columns = 64; + WidthMask = 0x3ff; + } + + // Render the tilemap to a buffer + memset(pTC0480SCPTempDraw, 0, 1024 * 512 * sizeof(UINT16)); + for (my = 0; my < 32; my++) { + for (mx = 0; mx < Columns; mx++) { + Offset = 2 * TileIndex; + Attr = VideoRam[Offset]; + Code = VideoRam[Offset + 1] & (TC0480SCPTilesNum - 1); + Colour = Attr & 0xff; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + Colour += TC0480SCPColBase; + + x = 16 * mx; + y = 16 * my; + + if (Opaque) { + if (xFlip) { + if (yFlip) { + RenderTile_FlipXY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + RenderTile_FlipX(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_FlipY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } else { + RenderTile(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, pSrc); + } + } + } else { + if (xFlip) { + if (yFlip) { + RenderTile_Mask_FlipXY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask_FlipX(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } else { + if (yFlip) { + RenderTile_Mask_FlipY(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } else { + RenderTile_Mask(pTC0480SCPTempDraw, Code, x, y, Colour, 4, 0, 0, pSrc); + } + } + } + + TileIndex++; + } + } + + sx = ((BgScrollX[Layer] + 15 + Layer * 4) << 16) + ((255 - (TC0480SCPCtrl[0x10 + Layer] & 0xff)) << 8); + sx += (-TC0480SCPXOffset - 15 - Layer * 4) * xZoom; + + yIndex = (BgScrollY[Layer] << 16) + ((TC0480SCPCtrl[0x14 + Layer] & 0xff) << 8); + yIndex -= (-TC0480SCPYOffset - TC0480SCPYVisOffset) * yZoom; + + y = 0; + + do { + ySrcIndex = ((yIndex >> 16) + ColumnRam[(y + TC0480SCPYOffset + TC0480SCPYVisOffset) & 0x1ff]) & 0x1ff; + + RowIndex = ySrcIndex; + + if (TC0480SCPPriReg & (Layer - 1)) { + RowZoom = RowZoomRam[RowIndex]; + } else { + RowZoom = 0; + } + + xIndex = sx - ((ScrollRam[RowIndex] << 16)) - ((ScrollRam[RowIndex + 0x800] << 8) & 0xffff); + xIndex -= (-TC0480SCPXOffset - 0x1f + Layer * 4) * ((RowZoom & 0xff) << 8); + + xStep = xZoom; + if (RowZoom) { + if (!(RowZoom & 0xff00)) { + xStep -= ((RowZoom * 256) & 0xffff); + } else { + xStep -= (((RowZoom & 0xff) * 256) & 0xffff); + } + } + + Src16 = pSrcTileMap + (ySrcIndex * Columns * 16); + Dst16 = ScanLine; + + if (Opaque) { + for (i = 0; i < 512; i++) { + *Dst16++ = Src16[(xIndex >> 16) & WidthMask]; + xIndex += xStep; + } + } else { + for (i = 0; i < 512; i++) { + INT32 Pix = Src16[(xIndex >> 16) & WidthMask]; + + if ((Pix & 0x0f) != 0) { + *Dst16++ = Pix; + } else { + *Dst16++ = 0x8000; + } + xIndex += xStep; + } + } + + if (Opaque) { + DrawScanLine(y, ScanLine, 0, 0); + } else { + DrawScanLine(y, ScanLine, 1, 0); + } + + yIndex += yZoom; + y++; + } while (y < nScreenHeight); +} + +void TC0480SCPTilemapRender(INT32 Layer, INT32 Opaque, UINT8 *pSrc) +{ + switch (Layer) { + case 0: { + TC0480SCPRenderLayer01(0, Opaque, pSrc); + break; + } + + case 1: { + TC0480SCPRenderLayer01(1, Opaque, pSrc); + break; + } + + case 2: { + TC0480SCPRenderLayer23(2, Opaque, pSrc); + break; + } + + case 3: { + TC0480SCPRenderLayer23(3, Opaque, pSrc); + break; + } + } +} + +static INT32 TC0480SCPPlaneOffsets[4] = { 0, 1, 2, 3 }; +static INT32 TC0480SCPXOffsets[8] = { 4, 0, 12, 8, 20, 16, 28, 24 }; +static INT32 TC0480SCPYOffsets[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + +void TC0480SCPRenderCharLayer() +{ + INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, Flip, xFlip, yFlip; + + UINT16 *VideoRam = (UINT16*)TC0480SCPRam + 0x6000; + UINT16 *CharRam = (UINT16*)TC0480SCPRam + 0x7000; + + GfxDecode(256, 4, 8, 8, TC0480SCPPlaneOffsets, TC0480SCPXOffsets, TC0480SCPYOffsets, 0x100, (UINT8*)CharRam, TC0480SCPChars); + + for (my = 0; my < 64; my++) { + for (mx = 0; mx < 64; mx++) { + Attr = VideoRam[TileIndex]; + Code = Attr & 0xff; + Colour = (Attr & 0x3f00) >> 8; + Flip = (Attr & 0xc000) >> 14; + xFlip = (Flip >> 0) & 0x01; + yFlip = (Flip >> 1) & 0x01; + + Colour += TC0480SCPColBase; + + x = 8 * mx; + y = 8 * my; + + x -= CharScrollX & 0x1ff; + y -= CharScrollY & 0x1ff; + if (x < -8) x += 512; + if (y < -8) y += 512; + + if (x >= 8 && x < (nScreenWidth - 8) && y >= 8 && y < (nScreenHeight - 8)) { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } else { + Render8x8Tile_Mask_FlipX(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } else { + Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } + } + } else { + if (xFlip) { + if (yFlip) { + Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } else { + Render8x8Tile_Mask_FlipX_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } + } else { + if (yFlip) { + Render8x8Tile_Mask_FlipY_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } else { + Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 4, 0, 0, TC0480SCPChars); + } + } + } + + TileIndex++; + } + } +} + +void TC0480SCPReset() +{ + memset(TC0480SCPChars, 0, 256 * 8 * 8); + memset(TC0480SCPCtrl, 0, 0x18); + BgScrollX[0] = BgScrollX[1] = BgScrollX[2] = BgScrollX[3] = 0; + BgScrollY[0] = BgScrollY[1] = BgScrollY[2] = BgScrollY[3] = 0; + CharScrollX = 0; + CharScrollY = 0; + TC0480SCPPriReg = 0; + TC0480SCPDblWidth = 0; +} + +INT32 TC0480SCPGetBgPriority() +{ + return TC0480SCPBgPriLookup[(TC0480SCPPriReg &0x1c) >> 2]; +} + +void TC0480SCPInit(INT32 nNumTiles, INT32 Pixels, INT32 xOffset, INT32 yOffset, INT32 xTextOffset, INT32 yTextOffset, INT32 VisYOffset) +{ + TC0480SCPRam = (UINT8*)malloc(0x10000); + memset(TC0480SCPRam, 0, 0x10000); + TC0480SCPChars = (UINT8*)malloc(256 * 8 * 8); + memset(TC0480SCPChars, 0, 256 * 8 * 8); + + TC0480SCPTilesNum = nNumTiles; + + TC0480SCPXOffset = -(xOffset + Pixels); + TC0480SCPYOffset = yOffset; + TC0480SCPTextXOffset = xTextOffset - TC0480SCPXOffset + 3; + TC0480SCPTextYOffset = yTextOffset + TC0480SCPYOffset; + + pTC0480SCPTempDraw = (UINT16*)malloc(1024 * 512 * sizeof(UINT16)); + memset(pTC0480SCPTempDraw, 0, 1024 * 512 * sizeof(UINT16)); + + TC0480SCPColBase = 0; + TC0480SCPYVisOffset = VisYOffset; + + TaitoIC_TC0480SCPInUse = 1; +} + +void TC0480SCPSetColourBase(INT32 Base) +{ + TC0480SCPColBase = Base; +} + +void TC0480SCPExit() +{ + if (TC0480SCPRam) { + free(TC0480SCPRam); + TC0480SCPRam = NULL; + } + + if (TC0480SCPChars) { + free(TC0480SCPChars); + TC0480SCPChars = NULL; + } + + if (pTC0480SCPTempDraw) { + free(pTC0480SCPTempDraw); + pTC0480SCPTempDraw = NULL; + } + + memset(TC0480SCPCtrl, 0, 0x18); + BgScrollX[0] = BgScrollX[1] = BgScrollX[2] = BgScrollX[3] = 0; + BgScrollY[0] = BgScrollY[1] = BgScrollY[2] = BgScrollY[3] = 0; + CharScrollX = 0; + CharScrollY = 0; + TC0480SCPPriReg = 0; + TC0480SCPDblWidth = 0; + + TC0480SCPTilesNum = 0; + TC0480SCPXOffset = 0; + TC0480SCPYOffset = 0; + TC0480SCPTextXOffset = 0; + TC0480SCPTextYOffset = 0; + TC0480SCPColBase = 0; + TC0480SCPYVisOffset = 0; +} + +void TC0480SCPScan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_MEMORY_RAM) { + memset(&ba, 0, sizeof(ba)); + ba.Data = TC0480SCPRam; + ba.nLen = 0x10000; + ba.szName = "TC0480SCP Ram"; + BurnAcb(&ba); + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0480SCPCtrl); + SCAN_VAR(BgScrollX); + SCAN_VAR(BgScrollY); + SCAN_VAR(CharScrollX); + SCAN_VAR(CharScrollY); + SCAN_VAR(TC0480SCPPriReg); + } +} diff --git a/src/burn/drivers/taito/tc0510nio.cpp b/src/burn/drivers/taito/tc0510nio.cpp new file mode 100644 index 00000000..a534988d --- /dev/null +++ b/src/burn/drivers/taito/tc0510nio.cpp @@ -0,0 +1,91 @@ +// TC0510NIO + +#include "burnint.h" +#include "taito_ic.h" + +UINT8 TC0510NIOInputPort0[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0510NIOInputPort1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0510NIOInputPort2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0510NIODip[2] = { 0, 0 }; +UINT8 TC0510NIOInput[3] = { 0, 0, 0 }; +static UINT8 TC0510NIORegs[8]; + +extern UINT8 TaitoCoinLockout[4]; + +static UINT8 TC0510NIORead(INT32 Offset) +{ + switch (Offset) { + case 0x00: return TC0510NIODip[0]; + case 0x01: return TC0510NIODip[1]; + case 0x02: return TC0510NIOInput[0]; + case 0x03: return TC0510NIOInput[1]; + case 0x04: return TC0510NIORegs[4]; + case 0x07: return TC0510NIOInput[2]; + + default: { + return 0xff; + } + } +} + +static void TC0510NIOWrite(INT32 Offset, UINT16 Data) +{ + TC0510NIORegs[Offset] = Data; + + if (Offset == 0) { + TaitoWatchdog = 0; + } + + if (Offset == 4) { + TaitoCoinLockout[0] = ~Data & 0x01; + TaitoCoinLockout[1] = ~Data & 0x02; + // coin counters 0x04 & 0x08 + } +} + +UINT16 TC0510NIOHalfWordRead(INT32 Offset) +{ + return TC0510NIORead(Offset); +} + +UINT16 TC0510NIOHalfWordSwapRead(INT32 Offset) +{ + return TC0510NIOHalfWordRead(Offset ^ 1); +} + +void TC0510NIOHalfWordWrite(INT32 Offset, UINT16 Data) +{ + TC0510NIOWrite(Offset, Data & 0xff); +} + +void TC0510NIOHalfWordSwapWrite(INT32 Offset, UINT16 Data) +{ + TC0510NIOWrite(Offset ^ 1, Data); +} + +void TC0510NIOReset() +{ + memset(TC0510NIORegs, 0, 8); +} + +void TC0510NIOInit() +{ + TaitoIC_TC0510NIOInUse = 1; +} + +void TC0510NIOExit() +{ + memset(TC0510NIORegs, 0, 8); +} + +void TC0510NIOScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0510NIOInputPort0); + SCAN_VAR(TC0510NIOInputPort1); + SCAN_VAR(TC0510NIOInputPort2); + SCAN_VAR(TC0510NIODip); + SCAN_VAR(TC0510NIOInput); + SCAN_VAR(TC0510NIORegs); + } +} diff --git a/src/burn/drivers/taito/tc0640fio.cpp b/src/burn/drivers/taito/tc0640fio.cpp new file mode 100644 index 00000000..5b315982 --- /dev/null +++ b/src/burn/drivers/taito/tc0640fio.cpp @@ -0,0 +1,117 @@ +// TC0640FIO + +#include "burnint.h" +#include "taito_ic.h" + +UINT8 TC0640FIOInputPort0[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0640FIOInputPort1[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0640FIOInputPort2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0640FIOInputPort3[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0640FIOInputPort4[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +UINT8 TC0640FIOInput[5] = { 0, 0, 0, 0, 0 }; + +static UINT8 TC0640FIORegs[8]; + +UINT8 TC0640FIORead(UINT32 Offset) +{ + switch (Offset) { + case 0x00: { + return TC0640FIOInput[0]; + } + + case 0x01: { + return TC0640FIOInput[1]; + } + + case 0x02: { + return TC0640FIOInput[2]; + } + + case 0x03: { + return TC0640FIOInput[3]; + } + + case 0x04: { + return TC0640FIORegs[4]; + } + + case 0x07: { + return TC0640FIOInput[4]; + } + } + + return 0xff; +} + +void TC0640FIOWrite(UINT32 Offset, UINT8 Data) +{ + TC0640FIORegs[Offset] = Data; + + switch (Offset) { + case 0x00: { + TaitoWatchdog = 0; + return; + } + + case 0x04: { + // coin lockout and counters + return; + } + } +} + +UINT16 TC0640FIOHalfWordRead(UINT32 Offset) +{ + return TC0640FIORead(Offset); +} + +void TC0640FIOHalfWordWrite(UINT32 Offset, UINT16 Data) +{ + if ((Data & 0xff00) == 0) { + TC0640FIOWrite(Offset, Data & 0xff); + } else { + TC0640FIOWrite(Offset, (Data >> 8) & 0xff); + } +} + +UINT16 TC0640FIOHalfWordByteswapRead(UINT32 Offset) +{ + return TC0640FIOHalfWordRead(Offset) << 8; +} + +void TC0640FIOHalfWordByteswapWrite(UINT32 Offset, UINT16 Data) +{ + if ((Data & 0xff00) == 0) { + TC0640FIOWrite(Offset, (Data >> 8) & 0xff); + } else { + TC0640FIOWrite(Offset, Data & 0xff); + } +} + +void TC0640FIOReset() +{ + memset(TC0640FIORegs, 0, 8); +} + +void TC0640FIOInit() +{ + TaitoIC_TC0640FIOInUse = 1; +} + +void TC0640FIOExit() +{ + memset(TC0640FIORegs, 0, 8); +} + +void TC0640FIOScan(INT32 nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(TC0640FIOInputPort0); + SCAN_VAR(TC0640FIOInputPort1); + SCAN_VAR(TC0640FIOInputPort2); + SCAN_VAR(TC0640FIOInputPort3); + SCAN_VAR(TC0640FIOInputPort4); + SCAN_VAR(TC0640FIOInput); + SCAN_VAR(TC0640FIORegs); + } +} diff --git a/src/burn/drivers/toaplan/d_batrider.cpp b/src/burn/drivers/toaplan/d_batrider.cpp new file mode 100644 index 00000000..1ac0e569 --- /dev/null +++ b/src/burn/drivers/toaplan/d_batrider.cpp @@ -0,0 +1,1167 @@ +#include "toaplan.h" +// Batrider + +static UINT8 drvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 drvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 drvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 drvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 drvRegion = 0; +static UINT8 drvReset = 0; +static UINT8 bDrawScreen; + +static UINT8 nIRQPending; +static bool bVBlank; + +static INT32 nData; + +static INT32 nCurrentBank; +static INT32 nTextROMStatus; + +static void Map68KTextROM(bool bMapTextROM); + +static struct BurnInputInfo batriderInputList[] = { + {"P1 Coin", BIT_DIGITAL, drvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, drvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, drvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, drvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, drvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, drvJoy1 + 3, "p1 right"}, + {"P1 Shoot 1", BIT_DIGITAL, drvJoy1 + 4, "p1 fire 1"}, + {"P1 Shoot 2", BIT_DIGITAL, drvJoy1 + 5, "p1 fire 2"}, + {"P1 Shoot 3", BIT_DIGITAL, drvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, drvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, drvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, drvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, drvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, drvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, drvJoy2 + 3, "p2 right"}, + {"P2 Shoot 1", BIT_DIGITAL, drvJoy2 + 4, "p2 fire 1"}, + {"P2 Shoot 2", BIT_DIGITAL, drvJoy2 + 5, "p2 fire 2"}, + {"P2 Shoot 3", BIT_DIGITAL, drvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &drvReset, "reset"}, + {"Test", BIT_DIGITAL, drvButton + 2, "diag"}, + {"Service", BIT_DIGITAL, drvButton + 0, "service"}, + {"Dip 1", BIT_DIPSWITCH, drvInput + 3, "dip"}, + {"Dip 2", BIT_DIPSWITCH, drvInput + 4, "dip"}, + {"Dip 3", BIT_DIPSWITCH, drvInput + 5, "dip"}, + {"Region", BIT_DIPSWITCH, &drvRegion , "dip"}, +}; + +STDINPUTINFO(batrider) + + +static struct BurnDIPInfo batriderDIPList[] = { + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x00, NULL}, + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x15, 0x01, 0x01, 0x00, "Normal"}, + {0x15, 0x01, 0x01, 0x01, "Test"}, + // Normal + {0, 0xFE, 0, 2, "Starting coin"}, + {0x15, 0x82, 0x02, 0x00, "1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0x02, 0x02, "2 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Free play + {0, 0xFE, 0, 2, "Stick mode"}, + {0x15, 0x02, 0x02, 0x00, "Normal"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x02, 0x02, "Special"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Both + {0, 0xFE, 0, 8, "Coin 1"}, + {0x15, 0x01, 0x1C, 0x00, "1 coin 1 credit"}, + {0x15, 0x01, 0x1C, 0x04, "1 coin 2 credits"}, + {0x15, 0x01, 0x1C, 0x08, "1 coin 3 credits"}, + {0x15, 0x01, 0x1C, 0x0C, "1 coin 4 credits"}, + {0x15, 0x01, 0x1C, 0x10, "2 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x14, "3 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x18, "4 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x1C, "Free Play"}, + // 0x1C: Free play settings active + // Normal + {0, 0xFE, 0, 7, "Coin 2"}, + {0x15, 0x82, 0xE0, 0x00, "1 coin 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x20, "1 coin 2 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x40, "1 coin 3 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x60, "1 coin 4 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x80, "2 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0xA0, "3 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0xC0, "4 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0xE0, "1 coin 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Free play + {0, 0xFE, 0, 2, "Hit score"}, + {0x15, 0x02, 0x20, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x20, 0x20, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Sound effect"}, + {0x15, 0x02, 0x40, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x40, 0x40, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Music"}, + {0x15, 0x02, 0x80, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x80, 0x80, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Start rank"}, + {0x16, 0x01, 0x03, 0x00, "Normal"}, + {0x16, 0x01, 0x03, 0x01, "Easy"}, + {0x16, 0x01, 0x03, 0x02, "Hard"}, + {0x16, 0x01, 0x03, 0x03, "Very hard"}, + {0, 0xFE, 0, 4, "Timer rank"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Low"}, + {0x16, 0x01, 0x0C, 0x08, "High"}, + {0x16, 0x01, 0x0C, 0x0C, "Highest"}, + {0, 0xFE, 0, 4, "Player counts"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "4"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 4, "Extra player"}, + {0x16, 0x01, 0xC0, 0x00, "1500000 each"}, + {0x16, 0x01, 0xC0, 0x40, "1000000 each"}, + {0x16, 0x01, 0xC0, 0x80, "2000000 each"}, + {0x16, 0x01, 0xC0, 0xC0, "No extra player"}, + + // DIP 3 + {0, 0xFE, 0, 2, "Screen flip"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x17, 0x01, 0x02, 0x00, "On"}, + {0x17, 0x01, 0x02, 0x02, "Off"}, + {0, 0xFE, 0, 2, "Stage edit"}, + {0x17, 0x01, 0x04, 0x00, "Disable"}, + {0x17, 0x01, 0x04, 0x04, "Enable"}, + {0, 0xFE, 0, 2, "Continue play"}, + {0x17, 0x01, 0x08, 0x00, "Enable"}, + {0x17, 0x01, 0x08, 0x08, "Disable"}, + {0, 0xFE, 0, 2, "Invincible"}, + {0x17, 0x01, 0x10, 0x00, "Off"}, + {0x17, 0x01, 0x10, 0x10, "On"}, + // Free play + {0, 0xFE, 0, 2, "Guest Players"}, + {0x17, 0x02, 0x20, 0x00, "Disable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x17, 0x02, 0x20, 0x20, "Enable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Player select"}, + {0x17, 0x02, 0x40, 0x00, "Disable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x17, 0x02, 0x40, 0x40, "Enable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Special Course"}, + {0x17, 0x02, 0x80, 0x00, "Disable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x17, 0x02, 0x80, 0x80, "Enable"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + + // Region + {0, 0xFD, 0, 26, "Region"}, + {0x18, 0x01, 0x1F, 0x00, "Nippon"}, + {0x18, 0x01, 0x1F, 0x01, "U.S.A."}, + {0x18, 0x01, 0x1F, 0x02, "Europe"}, + {0x18, 0x01, 0x1F, 0x03, "Asia"}, + {0x18, 0x01, 0x1F, 0x04, "German"}, + {0x18, 0x01, 0x1F, 0x05, "Austria"}, + {0x18, 0x01, 0x1F, 0x06, "Belgium"}, + {0x18, 0x01, 0x1F, 0x07, "Denmark"}, + {0x18, 0x01, 0x1F, 0x08, "Finland"}, + {0x18, 0x01, 0x1F, 0x09, "France"}, + {0x18, 0x01, 0x1F, 0x0A, "Great Britain"}, + {0x18, 0x01, 0x1F, 0x0B, "Greece"}, + {0x18, 0x01, 0x1F, 0x0C, "Holland"}, + {0x18, 0x01, 0x1F, 0x0D, "Italy"}, + {0x18, 0x01, 0x1F, 0x0E, "Norway"}, + {0x18, 0x01, 0x1F, 0x0F, "Portugal"}, + {0x18, 0x01, 0x1F, 0x10, "Spain"}, + {0x18, 0x01, 0x1F, 0x11, "Sweden"}, + {0x18, 0x01, 0x1F, 0x12, "Switzerland"}, + {0x18, 0x01, 0x1F, 0x13, "Australia"}, + {0x18, 0x01, 0x1F, 0x14, "New Zealand"}, + {0x18, 0x01, 0x1F, 0x15, "Taiwan"}, + {0x18, 0x01, 0x1F, 0x16, "HongKong"}, + {0x18, 0x01, 0x1F, 0x17, "Korea"}, + {0x18, 0x01, 0x1F, 0x18, "China"}, + {0x18, 0x01, 0x1F, 0x19, "World"}, +}; + +static struct BurnDIPInfo batriderRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x00, NULL}, +}; + +static struct BurnDIPInfo batridRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x02, NULL}, +}; + +static struct BurnDIPInfo batriduRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x01, NULL}, +}; + +static struct BurnDIPInfo batridcRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x18, NULL}, +}; + +static struct BurnDIPInfo batridkRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x17, NULL}, +}; + +static struct BurnDIPInfo batridtaRegionDIPList[] = { + // Defaults + {0x18, 0xFF, 0xFF, 0x15, NULL}, +}; + +STDDIPINFOEXT(batrider, batriderRegion, batrider) +STDDIPINFOEXT(batrid, batridRegion, batrider) +STDDIPINFOEXT(batridu, batriduRegion, batrider) +STDDIPINFOEXT(batridc, batridcRegion, batrider) +STDDIPINFOEXT(batridk, batridkRegion, batrider) +STDDIPINFOEXT(batridta, batridtaRegion, batrider) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02, *RamPal; +UINT8 *RamShared; +static INT32 nColCount = 0x0800; + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x200000; // 68000 ROM + RomZ80 = Next; Next += 0x040000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // Tile data + MSM6295ROM = Next; Next += 0x200000; // MSM6295 ADPCM data + RamStart = Next; + ExtraTRAM = Next; Next += 0x002000; // Extra text layer + Ram01 = Next; Next += 0x005000; // RAM + Extra text layer scroll/offset + ExtraTROM = Next; Next += 0x008000; // Extra text layer tile data + Ram02 = Next; Next += 0x008000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // Palette + RamZ80 = Next; Next += 0x004000; // Z80 RAM + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamShared = Next; Next += 0x000008; // Shared data + RamEnd = Next; + ToaPalette = (UINT32*)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + ExtraTSelect= Ram01; // Extra text layer scroll + ExtraTScroll= Ram01 + 0x000200; // Extra text layer offset + + return 0; +} + +static void drvZ80Bankswitch(INT32 nBank) +{ + nBank &= 0x0F; + if (nBank != nCurrentBank) { + UINT8* nStartAddress = RomZ80 + (nBank << 14); + ZetMapArea(0x8000, 0xBFFF, 0, nStartAddress); + ZetMapArea(0x8000, 0xBFFF, 2, nStartAddress); + + nCurrentBank = nBank; + } +} + +// Scan ram +static INT32 drvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029496; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + SCAN_VAR(nCurrentBank); + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(nIRQPending); + SCAN_VAR(nTextROMStatus); + + SCAN_VAR(drvInput); + + if (nAction & ACB_WRITE) { + INT32 n = nTextROMStatus; + nTextROMStatus = -1; + Map68KTextROM(n); + + n = nCurrentBank; + nCurrentBank = -1; + drvZ80Bankswitch(n); + } + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROMs + if (ToaLoadCode(Rom01, 0, 4)) { + return 1; + } + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 4, 4, nGP9001ROMSize[0]); + + // Load the Z80 ROM + if (BurnLoadRom(RomZ80, 8, 1)) { + return 1; + } + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM + 0x000000, 9, 1); + BurnLoadRom(MSM6295ROM + 0x100000, 10, 1); + + return 0; +} + +UINT8 __fastcall batriderZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + + // The sound commands sent by the 68000 are read from these locations + case 0x48: + return RamShared[0]; + case 0x4A: + return RamShared[1]; + + case 0x81: + return BurnYM2151ReadStatus(); + case 0x82: + return MSM6295ReadStatus(0); + case 0x84: + return MSM6295ReadStatus(1); + } + + return 0; +} + +void __fastcall batriderZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + + // The 68000 expects to read back the sound command it sent + case 0x40: + RamShared[4] = nValue; + break; + case 0x42: + RamShared[5] = nValue; + break; + + case 0x44: // ??? + case 0x46: // Acknowledge interrupt + break; + + case 0x80: + BurnYM2151SelectRegister(nValue); + break; + case 0x81: + BurnYM2151WriteRegister(nValue); + break; + + case 0x82: + MSM6295Command(0, nValue); + break; + case 0x84: + MSM6295Command(1, nValue); + break; + + case 0x88: { + drvZ80Bankswitch(nValue); + break; + + case 0xC0: + MSM6295SampleInfo[0][0] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleData[0][0] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[0][1] = MSM6295ROM + ((nValue & 0xF0) << 12) + 0x0100; + MSM6295SampleData[0][1] = MSM6295ROM + ((nValue & 0xF0) << 12); + break; + case 0xC2: + MSM6295SampleInfo[0][2] = MSM6295ROM + ((nValue & 0x0F) << 16) + 0x0200; + MSM6295SampleData[0][2] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[0][3] = MSM6295ROM + ((nValue & 0xF0) << 12) + 0x0300; + MSM6295SampleData[0][3] = MSM6295ROM + ((nValue & 0xF0) << 12); + break; + case 0xC4: + MSM6295SampleInfo[1][0] = MSM6295ROM + 0x0100000 + ((nValue & 0x0F) << 16); + MSM6295SampleData[1][0] = MSM6295ROM + 0x0100000 + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[1][1] = MSM6295ROM + 0x0100000 + ((nValue & 0xF0) << 12) + 0x0100; + MSM6295SampleData[1][1] = MSM6295ROM + 0x0100000 + ((nValue & 0xF0) << 12); + break; + case 0xC6: + MSM6295SampleInfo[1][2] = MSM6295ROM + 0x0100000 + ((nValue & 0x0F) << 16) + 0x0200; + MSM6295SampleData[1][2] = MSM6295ROM + 0x0100000 + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[1][3] = MSM6295ROM + 0x0100000 + ((nValue & 0xF0) << 12) + 0x0300; + MSM6295SampleData[1][3] = MSM6295ROM + 0x0100000 + ((nValue & 0xF0) << 12); + break; + } + } +} + +static INT32 drvZInit() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(batriderZIn); + ZetSetOutHandler(batriderZOut); + + // ROM bank 1 + ZetMapArea(0x0000, 0x7FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea(0x0000, 0x7FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea(0x8000, 0xBFFF, 0, RomZ80 + 0x8000); // Direct Read from ROM + ZetMapArea(0x8000, 0xBFFF, 2, RomZ80 + 0x8000); // + // RAM + ZetMapArea(0xC000, 0xDFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea(0xC000, 0xDFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea(0xC000, 0xDFFF, 2, RamZ80); // + + ZetMemEnd(); + ZetClose(); + + nCurrentBank = 2; + + return 0; +} + +UINT8 __fastcall batriderReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x500000: // Player 2 inputs + return drvInput[1]; + case 0x500001: // Player 1 inputs + return drvInput[0]; + case 0x500002: // Dipswitch 3 + return drvInput[5]; + case 0x500003: // Other inputs + return drvInput[2]; + case 0x500004: // Dipswitch 2 + return drvInput[4]; + case 0x500005: // Dipswitch 1 + return drvInput[3]; + + default: { +// printf("Attempt to read %06X (byte).\n", sekAddress); + + if ((sekAddress & 0x00F80000) == 0x00300000) { + return RomZ80[(sekAddress & 0x7FFFF) >> 1]; + } + } + } + + return 0; +} + +UINT16 __fastcall batriderReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x500006: + return ToaScanlineRegister(); + + // These addresses contain the response of the Z80 to the sound commands + case 0x500008: + return RamShared[4]; + case 0x50000A: + return RamShared[5]; + + case 0x50000C: + // This address echos the value written to 0x500060 + return nData; + + default: { +// printf("Attempt to read %06X (word).\n", sekAddress); + } + } + + return 0; +} + +void __fastcall batriderWriteByte(UINT32 sekAddress, UINT8) // UINT8 byteValue +{ + switch (sekAddress) { + + case 0x500011: // Coin control + break; + +// default: +// printf("Attempt to write %06X (byte) -> %04X.\n", sekAddress, byteValue); + } +} + +void __fastcall batriderWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x500020: { + RamShared[0] = wordValue; + + // The 68K program normally writes 0x500020/0x500022 as a single longword, + // except during the communications test. + if (wordValue == 0x55) { + ZetNmi(); + nCyclesDone[1] += ZetRun(0x1800); + } + break; + } + case 0x500022: + RamShared[1] = wordValue; + + // Sound commands are processed by the Z80 using an NMI + // So, trigger a Z80 NMI and execute it + ZetNmi(); + nCyclesDone[1] += ZetRun(0x1800); + break; + + case 0x500024: + // Writes to this address only occur in situations where the program sets + // 0x20FA19 (Ram02[0x7A18]) to 0xFF, and then sits in a loop waiting for it to become 0x00 + // Interrupt 4 does this (the same code is also conditionally called from interrupt 2) + + nIRQPending = 1; + SekSetIRQLine(4, SEK_IRQSTATUS_ACK); + break; + + case 0x500060: + // Bit 0 of the value written to this location must be echod at 0x50000C + nData = wordValue; + break; + + case 0x500080: + Map68KTextROM(false); + break; + + case 0x500082: // Acknowledge interrupt + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + nIRQPending = 0; + break; + + case 0x5000C0: + case 0x5000C1: + case 0x5000C2: + case 0x5000C3: + case 0x5000C4: + case 0x5000C5: + case 0x5000C6: + case 0x5000C7: + case 0x5000C8: + case 0x5000C9: + case 0x5000CA: + case 0x5000CB: + case 0x5000CC: + case 0x5000CD: + case 0x5000CE: + GP9001TileBank[(sekAddress & 0x0F) >> 1] = ((wordValue & 0x0F) << 15); + break; + +// default: +// printf("Attempt to write %06X (word) -> %04X.\n", sekAddress, wordValue); + } +} + +UINT16 __fastcall batriderReadWordGP9001(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400008: + return ToaGP9001ReadRAM_Hi(0); + case 0x40000A: + return ToaGP9001ReadRAM_Lo(0); + + } + + return 0; +} + +void __fastcall batriderWriteWordGP9001(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x400000: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x400004: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x400008: + case 0x40000A: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x40000C: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + } +} + +UINT8 __fastcall batriderReadByteZ80ROM(UINT32 sekAddress) +{ + return RomZ80[(sekAddress & 0x7FFFF) >> 1]; +} + +UINT16 __fastcall batriderReadWordZ80ROM(UINT32 sekAddress) +{ + return RomZ80[(sekAddress & 0x7FFFF) >> 1]; +} + +static void Map68KTextROM(bool bMapTextROM) +{ + if (bMapTextROM) { + if (nTextROMStatus != 1) { + SekMapMemory(ExtraTROM, 0x200000, 0x207FFF, SM_RAM); // Extra text tile memory + + nTextROMStatus = 1; + } + } else { + if (nTextROMStatus != 0) { + SekMapMemory(ExtraTRAM, 0x200000, 0x201FFF, SM_RAM); // Extra text tilemap RAM + SekMapMemory(RamPal, 0x202000, 0x202FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram01, 0x203000, 0x207FFF, SM_RAM); // Extra text Scroll & offset; RAM + + nTextROMStatus = 0; + } + } +} + +static INT32 drvDoReset() +{ + // Insert region code into 68K ROM, code by BisonSAS + UINT8 nRegion = drvRegion & 0x1F; + if (nRegion<=25) { + Rom01[0x00000^1]=(UINT8)(nRegion<<13) | (drvRegion & 0x1F); + } + + SekOpen(0); + + nIRQPending = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + + Map68KTextROM(true); + + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + BurnYM2151Reset(); + + return 0; +} + +static INT32 drvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x01000000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8*)0; + if ((Mem = (UINT8*)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // Zero memory + MemIndex(); // Index the allocated memory + + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram02, 0x208000, 0x20FFFF, SM_RAM); + + Map68KTextROM(true); + + SekSetReadWordHandler(0, batriderReadWord); + SekSetReadByteHandler(0, batriderReadByte); + SekSetWriteWordHandler(0, batriderWriteWord); + SekSetWriteByteHandler(0, batriderWriteByte); + + SekMapHandler(1, 0x400000, 0x400400, SM_RAM); // GP9001 addresses + + SekSetReadWordHandler(1, batriderReadWordGP9001); + SekSetWriteWordHandler(1, batriderWriteWordGP9001); + + SekMapHandler(2, 0x300000, 0x37FFFF, SM_ROM); // Z80 ROM + + SekSetReadByteHandler(2, batriderReadByteZ80ROM); + SekSetReadWordHandler(2, batriderReadWordZ80ROM); + + SekClose(); + } + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nExtraTXOffset = 0x2C; + ToaExtraTextInit(); + + drvZInit(); // Initialize Z80 + + BurnYM2151Init(32000000 / 8, 50.0); + MSM6295Init(0, 32000000 / 10 / 132, 50.0, 1); + MSM6295Init(1, 32000000 / 10 / 165, 50.0, 1); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + nTextROMStatus = -1; + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + drvDoReset(); // Reset machine + return 0; +} + +static INT32 drvExit() +{ + MSM6295Exit(1); + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + ToaExitGP9001(); + ToaExtraTextExit(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000 + + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && + ((nCurrentPC >= 0x0009F4 && nCurrentPC <= 0x0009FA) || + (nCurrentPC >= 0x001FF6 && nCurrentPC <= 0x001FFC) || + (nCurrentPC >= 0x003C7C && nCurrentPC <= 0x003C82))) + { + return 1; + } +#endif + + return 0; +} + +static INT32 drvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +static INT32 drvFrame() +{ + INT32 nInterleave = 8; + + if (drvReset) { // Reset machine + drvDoReset(); + } + + // Compile digital inputs + drvInput[0] = 0x00; // Buttons + drvInput[1] = 0x00; // Player 1 + drvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + drvInput[0] |= (drvJoy1[i] & 1) << i; + drvInput[1] |= (drvJoy2[i] & 1) << i; + drvInput[2] |= (drvButton[i] & 1) << i; + } + ToaClearOpposites(&drvInput[0]); + ToaClearOpposites(&drvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = TOA_Z80_SPEED / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + ToaBufferGP9001Sprites(); + if (pBurnDraw) { // Draw screen if needed + drvDraw(); + } + + nIRQPending = 1; + SekSetIRQLine(2, SEK_IRQSTATUS_ACK); + + bVBlank = true; + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + if ((i & 1) == 0) { + // Run Z80 + nCurrentCPU = 1; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * i / nInterleave) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + SekClose(); + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + MSM6295Render(1, pSoundBuf, nSegmentLength); + } + } + } + + ZetClose(); + + return 0; +} + +// Rom information +static struct BurnRomInfo batridRomDesc[] = { + { "prg0_europe.u22", 0x080000, 0x91d3e975, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1b.u23", 0x080000, 0x8E70B492, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batrid) +STD_ROM_FN(batrid) + +static struct BurnRomInfo batriduRomDesc[] = { + { "prg0_usa.u22", 0x080000, 0x2049d007, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1b.u23", 0x080000, 0x8E70B492, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridu) +STD_ROM_FN(batridu) + +static struct BurnRomInfo batridcRomDesc[] = { + { "prg0_china.u22", 0x080000, 0xc3b91f7e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1b.u23", 0x080000, 0x8E70B492, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridc) +STD_ROM_FN(batridc) + +static struct BurnRomInfo batridjRomDesc[] = { + { "prg0b.u22", 0x080000, 0x4f3fc729, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1b.u23", 0x080000, 0x8E70B492, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridj) +STD_ROM_FN(batridj) + +static struct BurnRomInfo batridkRomDesc[] = { + { "prg0_korea.u22", 0x080000, 0xd9d8c907, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1b.u23", 0x080000, 0x8E70B492, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridk) +STD_ROM_FN(batridk) + +static struct BurnRomInfo batridjaRomDesc[] = { + { "prg0.bin", 0x080000, 0xf93ea27c, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1.u23", 0x080000, 0x8ae7f592, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridja) +STD_ROM_FN(batridja) + +static struct BurnRomInfo batridtaRomDesc[] = { + { "u22.bin", 0x080000, 0xb135820e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2.u21", 0x080000, 0xBDAA5FBF, BRF_ESS | BRF_PRG }, // 1 + { "prg1.u23", 0x080000, 0x8ae7f592, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3.u24", 0x080000, 0x7AA9F941, BRF_ESS | BRF_PRG }, // 3 + + { "rom-1.bin", 0x400000, 0x0DF69CA2, BRF_GRA }, // 4 GP9001 Tile data + { "rom-3.bin", 0x400000, 0x60167D38, BRF_GRA }, // 5 + { "rom-2.bin", 0x400000, 0x1BFEA593, BRF_GRA }, // 6 + { "rom-4.bin", 0x400000, 0xBEE03c94, BRF_GRA }, // 7 + + { "snd.u77", 0x040000, 0x56682696, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom-5.bin", 0x100000, 0x4274DAf6, BRF_SND }, // 9 MSM6295 #1 ADPCM data + { "rom-6.bin", 0x100000, 0x2A1C2426, BRF_SND }, // 10 MSM6295 #2 ADPCM data +}; + + +STD_ROM_PICK(batridta) +STD_ROM_FN(batridta) + +struct BurnDriver BurnDrvBatrid = { + "batrider", NULL, NULL, NULL, "1998", + "Armed Police Batrider (Europe) (Fri Feb 13 1998)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridRomInfo, batridRomName, NULL, NULL, batriderInputInfo, batridDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridu = { + "batrideru", "batrider", NULL, NULL, "1998", + "Armed Police Batrider (U.S.A.) (Fri Feb 13 1998)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batriduRomInfo, batriduRomName, NULL, NULL, batriderInputInfo, batriduDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridc = { + "batriderc", "batrider", NULL, NULL, "1998", + "Armed Police Batrider (China) (Fri Feb 13 1998)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridcRomInfo, batridcRomName, NULL, NULL, batriderInputInfo, batridcDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridj = { + "batriderj", "batrider", NULL, NULL, "1998", + "Armed Police Batrider - B Version (Japan) (Fri Feb 13 1998)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridjRomInfo, batridjRomName, NULL, NULL, batriderInputInfo, batriderDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridk = { + "batriderk", "batrider", NULL, NULL, "1998", + "Armed Police Batrider (Korea) (Fri Feb 13 1998)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridkRomInfo, batridkRomName, NULL, NULL, batriderInputInfo, batridkDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridja = { + "batriderja", "batrider", NULL, NULL, "1998", + "Armed Police Batrider - A Version (Japan) (Mon Dec 22 1997)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridjaRomInfo, batridjaRomName, NULL, NULL, batriderInputInfo, batriderDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatridta = { + "batridert", "batrider", NULL, NULL, "1998", + "Armed Police Batrider - A Version (Taiwan) (Mon Dec 22 1997)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, batridtaRomInfo, batridtaRomName, NULL, NULL, batriderInputInfo, batridtaDIPInfo, + drvInit, drvExit, drvFrame, drvDraw, drvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_batsugun.cpp b/src/burn/drivers/toaplan/d_batsugun.cpp new file mode 100644 index 00000000..636a5149 --- /dev/null +++ b/src/burn/drivers/toaplan/d_batsugun.cpp @@ -0,0 +1,718 @@ +#include "toaplan.h" +#include "vez.h" +// Batsugun & Batsugun Special Version + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 v25_reset = 0; + +// Rom information +static struct BurnRomInfo batsugunRomDesc[] = { + { "tp030_1a.bin", 0x080000, 0xcb1d4554, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp030_3l.bin", 0x100000, 0x3024B793, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp030_3h.bin", 0x100000, 0xED75730B, BRF_GRA }, // 2 + { "tp030_4l.bin", 0x100000, 0xFEDB9861, BRF_GRA }, // 3 + { "tp030_4h.bin", 0x100000, 0xD482948B, BRF_GRA }, // 4 + + { "tp030_5.bin", 0x100000, 0xBCF5BA05, BRF_GRA }, // 5 + { "tp030_6.bin", 0x100000, 0x0666FECD, BRF_GRA }, // 6 + + { "tp030_2.bin", 0x040000, 0x276146F5, BRF_SND }, // 7 ADPCM data +}; + +STD_ROM_PICK(batsugun) +STD_ROM_FN(batsugun) + +static struct BurnRomInfo batsugnaRomDesc[] = { + { "tp030_01.bin", 0x080000, 0x3873D7DD, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp030_3l.bin", 0x100000, 0x3024B793, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp030_3h.bin", 0x100000, 0xED75730B, BRF_GRA }, // 2 + { "tp030_4l.bin", 0x100000, 0xFEDB9861, BRF_GRA }, // 3 + { "tp030_4h.bin", 0x100000, 0xD482948B, BRF_GRA }, // 4 + + { "tp030_5.bin", 0x100000, 0xBCF5BA05, BRF_GRA }, // 5 + { "tp030_6.bin", 0x100000, 0x0666FECD, BRF_GRA }, // 6 + + { "tp030_2.bin", 0x040000, 0x276146F5, BRF_SND }, // 7 ADPCM data +}; + +STD_ROM_PICK(batsugna) +STD_ROM_FN(batsugna) + +static struct BurnRomInfo batugnspRomDesc[] = { + { "tp030-sp.u69", 0x080000, 0x8072A0CD, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp030_3l.bin", 0x100000, 0x3024B793, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp030_3h.bin", 0x100000, 0xED75730B, BRF_GRA }, // 2 + { "tp030_4l.bin", 0x100000, 0xFEDB9861, BRF_GRA }, // 3 + { "tp030_4h.bin", 0x100000, 0xD482948B, BRF_GRA }, // 4 + + { "tp030_5.bin", 0x100000, 0xBCF5BA05, BRF_GRA }, // 5 + { "tp030_6.bin", 0x100000, 0x0666FECD, BRF_GRA }, // 6 + + { "tp030_2.bin", 0x040000, 0x276146F5, BRF_SND }, // 7 ADPCM data +}; + +STD_ROM_PICK(batugnsp) +STD_ROM_FN(batugnsp) + +static struct BurnInputInfo batsugunInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(batsugun) + +static struct BurnDIPInfo batsugunDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0x0F, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Normal continue"}, + {0x14, 0x01, 0x01, 0x01, "Discount continue"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B (normal)"}, + {0x15, 0x01, 0x03, 0x01, "A (easy)"}, + {0x15, 0x01, 0x03, 0x02, "C (hard)"}, + {0x15, 0x01, 0x03, 0x03, "D (very hard)"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x15, 0x01, 0x0C, 0x00, "1,000,000pts only"}, + {0x15, 0x01, 0x0C, 0x04, "500,000 600,000 every"}, + {0x15, 0x01, 0x0C, 0x08, "1,500,000pts only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x01, "5"}, + {0x15, 0x01, 0x30, 0x02, "2"}, + {0x15, 0x01, 0x30, 0x03, "1"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "Debug mode"}, + {0, 0xFE, 0, 2, "Continue"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, + + // Region + {0, 0xFE, 0, 14, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Korea (Unite Trading license)"}, + {0x16, 0x01, 0x0F, 0x01, "Korea"}, + {0x16, 0x01, 0x0F, 0x02, "Hong Kong (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Taiwan (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "South East Asia (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x07, "South East Asia"}, + {0x16, 0x01, 0x0F, 0x08, "Europe (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x09, "Europe"}, + {0x16, 0x01, 0x0F, 0x0A, "U.S.A (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x0B, "U.S.A"}, +// {0x16, 0x01, 0x0F, 0x0C, "Japan (Taito Corp license)"}, + {0x16, 0x01, 0x0F, 0x0D, "Japan (Taito Corp license"}, +// {0x16, 0x01, 0x0F, 0x0E, "Japan"}, + {0x16, 0x01, 0x0F, 0x0F, "Japan"}, +}; + +STDDIPINFO(batsugun) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + GP9001ROM[1]= Next; Next += nGP9001ROMSize[1]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x040000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + ShareRAM = Next; Next += 0x010000; + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001RAM[1]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + GP9001Reg[1]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + VezScan(nAction); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 4, nGP9001ROMSize[0]); + ToaLoadGP9001Tiles(GP9001ROM[1], 5, 2, nGP9001ROMSize[1]); + + BurnLoadRom(MSM6295ROM, 7, 1); + + return 0; +} + +UINT8 __fastcall batsugunReadByte(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) { + case 0x200011: // Player 1 inputs + return DrvInput[0]; + case 0x200015: // Player 2 inputs + return DrvInput[1]; + case 0x200019: // Other inputs + return DrvInput[2]; + + case 0x30000D: + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read %06X (byte).\n", sekAddress); + } + return 0; +} + +UINT16 __fastcall batsugunReadWord(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) { + + case 0x200010: // Player 1 inputs + return DrvInput[0]; + case 0x200014: // Player 2 inputs + return DrvInput[1]; + case 0x200018: // Other inputs + return DrvInput[2]; + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x500004: + return ToaGP9001ReadRAM_Hi(1); + case 0x500006: + return ToaGP9001ReadRAM_Lo(1); + + case 0x700000: { +// int nCurrentScanline = (nCyclesDone[0] + nCyclesSegment - m68k_ICount) / ((16000000 / 60) / 0x0106); + return 0; + } + +// default: +// printf("Attempt to read %06X (word).\n", sekAddress); + } + return 0; +} + +void __fastcall batsugunWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = byteValue; + return; + } + + switch (sekAddress) { + case 0x20001c: + case 0x20001d: + if (!v25_reset && (~byteValue & 0x20)) VezReset(); + v25_reset = (~byteValue & 0x20); + break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall batsugunWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = wordValue; + return; + } + + switch (sekAddress) { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x500000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue, 1); + break; + + case 0x500004: + case 0x500006: + ToaGP9001WriteRAM(wordValue, 1); + break; + + case 0x500008: + ToaGP9001SelectRegister(wordValue, 1); + break; + + case 0x50000C: + ToaGP9001WriteRegister(wordValue, 1); + break; + +// default: +// printf("Attempt to write %06X (word) -> %04X.\n", sekAddress, wordValue); + } +} + +void __fastcall batsugun_v25_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x00000: + BurnYM2151SelectRegister(data); + return; + + case 0x00001: + BurnYM2151WriteRegister(data); + return; + + case 0x00004: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall batsugun_v25_read(UINT32 address) +{ + switch (address) + { + case 0x00001: + return BurnYM2151ReadStatus(); + + case 0x00004: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT8 __fastcall batsugun_v25_read_port(UINT32 port) +{ + switch (port) + { + case V25_PORT_PT: + return DrvInput[3]^0xff; + + case V25_PORT_P0: + return DrvInput[4]^0xff; + + case V25_PORT_P1: + return DrvInput[5]^0xff; + } + + return 0; +} + + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + VezOpen(0); + VezReset(); + VezClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + v25_reset = 1; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x400000; + nGP9001ROMSize[1] = 0x200000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, batsugunReadWord); + SekSetReadByteHandler(0, batsugunReadByte); + SekSetWriteWordHandler(0, batsugunWriteWord); + SekSetWriteByteHandler(0, batsugunWriteByte); + SekClose(); + + VezInit(0, V25_TYPE, 16000000 /*before divider*/); + VezOpen(0); + for (INT32 i = 0x80000; i < 0x100000; i += 0x8000) { + VezMapArea(i, i + 0x7fff, 0, ShareRAM); + VezMapArea(i, i + 0x7fff, 1, ShareRAM); + VezMapArea(i, i + 0x7fff, 2, ShareRAM); + } + VezSetReadHandler(batsugun_v25_read); + VezSetWriteHandler(batsugun_v25_write); + VezSetReadPort(batsugun_v25_read_port); + VezClose(); + } + + BurnYM2151Init(3375000, 50.0); + MSM6295Init(0, 4000000 / 132, 50.0, 1); + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(3); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + MSM6295Exit(0); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + VezExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + MSM6295ROM = NULL; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + if (SekGetPC(-1) >= 0x94BC && SekGetPC(-1) <= 0x94D0) { + return 1; + } else { + return 0; + } +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + VezNewFrame(); + + INT32 nSoundBufferPos = 0; + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + +#if 0 + // The VBlank interrupt isn't actually used + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); +#endif + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // sound! (increase interleave?) + if (v25_reset) { + nCyclesDone[1] += nCyclesTotal[1] / nInterleave; + } else { + nCyclesDone[1] += VezRun(nCyclesTotal[1] / nInterleave); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + + } + } + + VezClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvBatsugun = { + "batsugun", NULL, NULL, NULL, "1993", + "Batsugun (set 1)\0", NULL, "Toaplan", "Dual Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, batsugunRomInfo, batsugunRomName, NULL, NULL, batsugunInputInfo, batsugunDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatsugunSP = { + "batsugunsp", "batsugun", NULL, NULL, "1993", + "Batsugun (Special Ver.)\0", NULL, "Dual Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, batugnspRomInfo, batugnspRomName, NULL, NULL, batsugunInputInfo, batsugunDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBatsugna = { + "batsuguna", "batsugun", NULL, NULL, "1993", + "Batsugun (set 2)\0", NULL, "Dual Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, batsugnaRomInfo, batsugnaRomName, NULL, NULL, batsugunInputInfo, batsugunDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_battleg.cpp b/src/burn/drivers/toaplan/d_battleg.cpp new file mode 100644 index 00000000..c11ec7f2 --- /dev/null +++ b/src/burn/drivers/toaplan/d_battleg.cpp @@ -0,0 +1,975 @@ +#include "toaplan.h" +// Battle Garegga + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static UINT8 nIRQPending; + +static INT32 nSoundCommand; + +// Z80 ROM bank +static INT32 nCurrentBank; + +static INT32 nSpeedHackOffset; + +// Rom information +static struct BurnRomInfo bgareggaRomDesc[] = { + { "prg0.bin", 0x080000, 0xF80C2FC2, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg1.bin", 0x080000, 0x2CCFDD1E, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgaregga) +STD_ROM_FN(bgaregga) + +static struct BurnRomInfo bgareghkRomDesc[] = { + { "prg_0.rom", 0x080000, 0x26E0019E, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg_1.rom", 0x080000, 0x2CCFDD1E, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgareghk) +STD_ROM_FN(bgareghk) + +static struct BurnRomInfo bgaregnvRomDesc[] = { + { "prg_0.bin", 0x080000, 0x951ECC07, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg_1.bin", 0x080000, 0x729A60C6, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgaregnv) +STD_ROM_FN(bgaregnv) + +static struct BurnRomInfo bgaregt2RomDesc[] = { + { "prg0", 0x080000, 0x84094099, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg1", 0x080000, 0x46f92fe4, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgaregt2) +STD_ROM_FN(bgaregt2) + +static struct BurnRomInfo bgaregcnRomDesc[] = { + { "u123", 0x080000, 0x88A4E66A, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "u65", 0x080000, 0x5DEA32A3, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgaregcn) +STD_ROM_FN(bgaregcn) + +static struct BurnRomInfo bgaregtwRomDesc[] = { + { "garegga_prg0.u123",0x080000, 0x235b7405, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "garegga_prg1.u65", 0x080000, 0xc29ccf6a, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "rom4.bin", 0x200000, 0xB333D81F, BRF_GRA }, // 2 GP9001 Tile data + { "rom3.bin", 0x200000, 0x51B9EBFB, BRF_GRA }, // 3 + { "rom2.bin", 0x200000, 0xB330E5E2, BRF_GRA }, // 4 + { "rom1.bin", 0x200000, 0x7EAFDD70, BRF_GRA }, // 5 + + { "text.u81", 0x008000, 0xE67FD534, BRF_GRA }, // 6 Extra text layer tile data + + { "snd.bin", 0x020000, 0x68632952, BRF_ESS | BRF_PRG }, // 7 Z80 program + + { "rom5.bin", 0x100000, 0xF6D49863, BRF_SND }, // 8 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(bgaregtw) +STD_ROM_FN(bgaregtw) + +static struct BurnInputInfo battlegInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(battleg) + +static struct BurnDIPInfo bgareggaDIPList[] = { + + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x14, 0x01, 0x01, 0x00, "Normal"}, + {0x14, 0x01, 0x01, 0x01, "Test"}, + {0, 0xFE, 0, 2, "Starting coin"}, + {0x14, 0x01, 0x02, 0x00, "1 credit"}, + {0x14, 0x01, 0x02, 0x02, "2 credits"}, + {0, 0xFE, 0, 8, "Coin 1"}, + {0x14, 0x01, 0x1C, 0x00, "1 coin 1 credit"}, + {0x14, 0x01, 0x1C, 0x04, "1 coin 2 credits"}, + {0x14, 0x01, 0x1C, 0x08, "1 coin 3 credits"}, + {0x14, 0x01, 0x1C, 0x0C, "1 coin 3 credits"}, + {0x14, 0x01, 0x1C, 0x10, "2 coins 1 credit"}, + {0x14, 0x01, 0x1C, 0x14, "3 coins 1 credit"}, + {0x14, 0x01, 0x1C, 0x18, "4 coins 1 credit"}, + {0x14, 0x01, 0x1C, 0x1C, "Free Play"}, + // 0x1C: Free play settings active + // Normal + {0, 0xFE, 0, 7, "Coin 2"}, + {0x14, 0x82, 0xE0, 0x00, "1 coin 1 credit"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0x20, "1 coin 2 credits"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0x40, "1 coin 3 credits"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0x60, "1 coin 3 credits"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0x80, "2 coins 1 credit"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0xA0, "3 coins 1 credit"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0xC0, "4 coins 1 credit"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x82, 0xE0, 0x04, "1 coin 1 credit"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + // Free play + {0, 0xFE, 0, 2, "Stick mode"}, + {0x14, 0x02, 0x20, 0x00, "Special"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x02, 0x20, 0x20, "Normal"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Effect"}, + {0x14, 0x02, 0x40, 0x00, "Off"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x02, 0x40, 0x40, "On"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Music"}, + {0x14, 0x02, 0x80, 0x00, "Off"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + {0x14, 0x02, 0x80, 0x80, "On"}, + {0x14, 0x00, 0x1C, 0x1C, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Difficulty"}, + {0x15, 0x01, 0x03, 0x00, "Normal"}, + {0x15, 0x01, 0x03, 0x01, "Easy"}, + {0x15, 0x01, 0x03, 0x02, "Hard"}, + {0x15, 0x01, 0x03, 0x03, "Very hard"}, + {0, 0xFE, 0, 2, "Screen flip"}, + {0x15, 0x01, 0x04, 0x00, "Off"}, + {0x15, 0x01, 0x04, 0x04, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x15, 0x01, 0x08, 0x00, "On"}, + {0x15, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 8, "Player counts"}, + {0x15, 0x01, 0x70, 0x00, "3"}, + {0x15, 0x01, 0x70, 0x10, "4"}, + {0x15, 0x01, 0x70, 0x20, "2"}, + {0x15, 0x01, 0x70, 0x30, "1"}, + {0x15, 0x01, 0x70, 0x40, "5"}, + {0x15, 0x01, 0x70, 0x50, "6"}, + {0x15, 0x01, 0x70, 0x60, "Multiple"}, + {0x15, 0x01, 0x70, 0x70, "Invincible"}, + // Nippon and U.S.A. regions + {0, 0xFE, 0, 2, "Extra player"}, + {0x15, 0x02, 0x80, 0x00, "1000000 each"}, + {0x16, 0x00, 0x01, 0x00, NULL}, + {0x15, 0x02, 0x80, 0x80, "1000000 2000000"}, + {0x16, 0x00, 0x01, 0x00, NULL}, + // Europe/Denmark and Asia regions + {0, 0xFE, 0, 2, "Extra player"}, + {0x15, 0x02, 0x80, 0x80, "2000000 each"}, + {0x16, 0x00, 0x01, 0x01, NULL}, + {0x15, 0x02, 0x80, 0x00, "No extra"}, + {0x16, 0x00, 0x01, 0x01, NULL}, + + // DIP 3 + {0, 0xFE, 0, 2, "Continue play"}, + {0x16, 0x01, 0x04, 0x00, "On"}, + {0x16, 0x01, 0x04, 0x04, "Off"}, +}; + +static struct BurnDIPInfo bgaregcnRegionDIPList[] = { + // DIP 3 + {0, 0xFE, 0, 2, "Stage edit"}, + {0x16, 0x01, 0x08, 0x00, "Disable"}, + {0x16, 0x01, 0x08, 0x08, "Enable"}, + + // Region + {0x16, 0xFF, 0x0F, 0x01, NULL}, + {0, 0xFE, 0, 2, "Region"}, + {0x16, 0x01, 0x03, 0x01, "Denmark (German Tuning license)"}, + {0x16, 0x01, 0x03, 0x03, "China"}, + {0x16, 0x01, 0x03, 0x00, "Japan [illegal setting]"}, + {0x16, 0x01, 0x03, 0x02, "U.S.A. (Fabtek license) [illegal setting]"}, +}; + +static struct BurnDIPInfo bgareggaRegionDIPList[] = { + // DIP 3 + {0, 0xFE, 0, 2, "Stage edit"}, + {0x16, 0x01, 0x08, 0x00, "Disable"}, + {0x16, 0x01, 0x08, 0x08, "Enable"}, + + // Region + {0x16, 0xFF, 0x0F, 0x00, NULL}, + {0, 0xFE, 0, 4, "Region"}, + {0x16, 0x01, 0x03, 0x00, "Japan"}, + {0x16, 0x01, 0x03, 0x01, "Europe (German Tuning license"}, + {0x16, 0x01, 0x03, 0x02, "U.S.A. (Fabtek license)"}, + {0x16, 0x01, 0x03, 0x03, "Asia"}, +}; + +static struct BurnDIPInfo bgareghkRegionDIPList[] = { + // DIP 3 + {0, 0xFE, 0, 2, "Stage edit"}, + {0x16, 0x01, 0x08, 0x00, "Disable"}, + {0x16, 0x01, 0x08, 0x08, "Enable"}, + + // Region + {0x16, 0xFF, 0x0F, 0x01, NULL}, + {0, 0xFE, 0, 2, "Region"}, + {0x16, 0x01, 0x03, 0x01, "Austria (German Tuning license"}, + {0x16, 0x01, 0x03, 0x03, "Hong Kong (metrotainment license"}, + {0x16, 0x01, 0x03, 0x00, "Japan [illegal setting]"}, + {0x16, 0x01, 0x03, 0x02, "U.S.A. (Fabtek license) [illegal setting]"}, +}; + +static struct BurnDIPInfo bgaregtwRegionDIPList[] = { + // DIP 3 + {0, 0xFE, 0, 2, "Stage edit"}, + {0x16, 0x01, 0x08, 0x00, "Disable"}, + {0x16, 0x01, 0x08, 0x08, "Enable"}, + + // Region + {0x16, 0xFF, 0x0F, 0x01, NULL}, + {0, 0xFE, 0, 2, "Region"}, + {0x16, 0x01, 0x03, 0x01, "Germany (German Tuning license)"}, + {0x16, 0x01, 0x03, 0x03, "Taiwan (Liang Hwa license)"}, + {0x16, 0x01, 0x03, 0x00, "Japan [illegal setting]"}, + {0x16, 0x01, 0x03, 0x02, "U.S.A. (Fabtek license) [illegal setting]"}, +}; + +STDDIPINFOEXT(bgaregga, bgaregga, bgareggaRegion) +STDDIPINFOEXT(bgaregcn, bgaregga, bgaregcnRegion) +STDDIPINFOEXT(bgareghk, bgaregga, bgareghkRegion) +STDDIPINFOEXT(bgaregtw, bgaregga, bgaregtwRegion) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02, *RamPal; + +static INT32 nColCount = 0x0800; +static INT32 nMSM6295ROMSize = 0x100000; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // + RomZ80 = Next; Next += 0x020000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + ExtraTROM = Next; Next += 0x010000; // Extra Text layer tile data + MSM6295ROM = Next; Next += nMSM6295ROMSize; // ADPCM data + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + Ram02 = Next; Next += 0x000800; // + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + ExtraTScroll= Next; Next += 0x001000; // + ExtraTSelect= Next; Next += 0x001000; // + RamPal = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x004000; // Z80 RAM + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static void drvZ80Bankswitch(INT32 nBank) +{ + nBank &= 0x07; + if (nBank != nCurrentBank) { + UINT8* nStartAddress = RomZ80 + (nBank << 14); + ZetMapArea(0x8000, 0xBFFF, 0, nStartAddress); + ZetMapArea(0x8000, 0xBFFF, 2, nStartAddress); + + nCurrentBank = nBank; + } +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029497; + } + if (nAction & ACB_VOLATILE) { // Scan volatile data + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + SCAN_VAR(nCurrentBank); + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nSoundCommand); + SCAN_VAR(nIRQPending); + + if (nAction & ACB_WRITE) { + INT32 nBank = nCurrentBank; + nCurrentBank = -1; + drvZ80Bankswitch(nBank); + } + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + if (ToaLoadCode(Rom01, 0, 2)) { + return 1; + } + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 2, 4, nGP9001ROMSize[0]); + + // Load Extra text layer tile data + BurnLoadRom(ExtraTROM, 6, 1); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 7, 1); + + // Load ADPCM data + BurnLoadRom(MSM6295ROM, 8, 1); + + return 0; +} + +UINT8 __fastcall battlegZ80Read(UINT16 nAddress) +{ +// printf("z80 read %4X\n", nAddress); + switch (nAddress) { + case 0xE001: + return BurnYM2151ReadStatus(); + + case 0xE004: + return MSM6295ReadStatus(0); + + case 0xE01C: + return nSoundCommand; + + case 0xE01D: + // Bit 0 enables/disables interrupt processing (0 = enabled) + return 0; + } + return 0; +} + +void __fastcall battlegZ80Write(UINT16 nAddress, UINT8 nValue) +{ +// printf("z80 wrote %4X with %2X\n", nAddress, nValue); + switch (nAddress) { + case 0xE000: + BurnYM2151SelectRegister(nValue); + break; + case 0xE001: + BurnYM2151WriteRegister(nValue); + break; + + case 0xE004: + MSM6295Command(0, nValue); + break; + + case 0xE006: + MSM6295SampleInfo[0][0] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleData[0][0] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[0][1] = MSM6295ROM + ((nValue & 0xF0) << 12) + 0x0100; + MSM6295SampleData[0][1] = MSM6295ROM + ((nValue & 0xF0) << 12); + break; + case 0xE008: + MSM6295SampleInfo[0][2] = MSM6295ROM + ((nValue & 0x0F) << 16) + 0x0200; + MSM6295SampleData[0][2] = MSM6295ROM + ((nValue & 0x0F) << 16); + MSM6295SampleInfo[0][3] = MSM6295ROM + ((nValue & 0xF0) << 12) + 0x0300; + MSM6295SampleData[0][3] = MSM6295ROM + ((nValue & 0xF0) << 12); + break; + + case 0xE00A: { + drvZ80Bankswitch(nValue); + break; + } + + case 0xE00C: + // Once a sound command is processed, it is written to this address + // printf("z80 wrote %4X -> %2X\n", nAddress, nValue); + break; + + } +} + +static INT32 DrvZ80Init() +{ + ZetInit(1); + ZetOpen(0); + + ZetSetReadHandler(battlegZ80Read); + ZetSetWriteHandler(battlegZ80Write); + + // ROM bank 1 + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM + // ROM bank 2 + ZetMapArea (0x8000, 0xBFFF, 0, RomZ80 + 0x8000); // Direct Read from ROM + ZetMapArea (0x8000, 0xBFFF, 2, RomZ80 + 0x8000); // Direct Fetch from ROM + // RAM + ZetMapArea (0xC000, 0xDFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xC000, 0xDFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xC000, 0xDFFF, 2, RamZ80); // + // Ports + ZetMemCallback(0xE000, 0xE0FF, 0); // Read + ZetMemCallback(0xE000, 0xE0FF, 1); // Write + + ZetMemEnd(); + ZetClose(); + + nCurrentBank = 2; + + return 0; +} + +UINT8 __fastcall battlegReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x218021: // The 68K has access to the Z80 RAM + return RamZ80[0x10]; // Only these addresses are used, however + case 0x218023: // + return RamZ80[0x11]; // + + case 0x21C021: // Player 1 inputs + return DrvInput[0]; + case 0x21C025: // Player 2 inputs + return DrvInput[1]; + case 0x21C029: // Other inputs + return DrvInput[2]; + case 0x21C02D: // Dipswitch A + return DrvInput[3]; + case 0x21C031: // Dipswitch B + return DrvInput[4]; + case 0x21C035: // Dipswitch C - Territory + return DrvInput[5]; + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + return 0; +} + +UINT16 __fastcall battlegReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x21C03C: + return ToaScanlineRegister(); + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + return 0; +} + +void __fastcall battlegWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x218021: // The 68K has access to the Z80 RAM + RamZ80[0x10] = byteValue; // Only these addresses are used, however + break; + + case 0x21C01D: // Coin control + break; + + case 0x600001: + nSoundCommand = byteValue; + + // Trigger Z80 interrupt, and allow the Z80 to process it + ZetRaiseIrq(255); + nCyclesDone[1] += ZetRun(0x0200); + break; + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall battlegWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + +// static int p; + + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); +// p = wordValue & 0x1FFF; + break; + + case 0x300004: +// if (p++ >= 0x1800) { +// static int s; +// if (s != SekCurrentScanline()) { +// s = SekCurrentScanline(); +// bprintf(PRINT_NORMAL, _T(" - sprite (%3i).\n"), s); +// } +// } + case 0x300006: +// p++; + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: { + ToaGP9001WriteRegister(wordValue); + break; + } + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + nIRQPending = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 battlegInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x800000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram02, 0x401000, 0x4017FF, SM_RAM); // Unused + SekMapMemory(ExtraTRAM, 0x500000, 0x501FFF, SM_RAM); + SekMapMemory(ExtraTSelect, 0x502000, 0x502FFF, SM_RAM); // 0x502000 - Scroll; 0x502200 - RAM + SekMapMemory(ExtraTScroll, 0x503000, 0x503FFF, SM_RAM); // 0x203000 - Offset; 0x503200 - RAM + + SekSetReadWordHandler(0, battlegReadWord); + SekSetReadByteHandler(0, battlegReadByte); + SekSetWriteWordHandler(0, battlegWriteWord); + SekSetWriteByteHandler(0, battlegWriteByte); + + SekClose(); + } + + nSpriteXOffset = 0x0024; + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nExtraTXOffset = 0x2C; + ToaExtraTextInit(); + + DrvZ80Init(); // Initialize Z80 + + BurnYM2151Init(32000000 / 8, 50.0); + MSM6295Init(0, 32000000 / 16 / 132, 50.0, 1); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + // mar 2 1996 & apr 2 1996 ver: 0x0009AC - 0x0009B8 & 0x001F5E - 0x001F64 & 0x003A1C - 0x003A22 + // feb 2 1996 ver: 0x0009AC - 0x0009B8 & 0x001F2E - 0x001F34 & 0x0039EC - 0x0039F2 + + nSpeedHackOffset = 0; + if (strcmp(BurnDrvGetTextA(DRV_NAME), "bgaregga") == 0) { + nSpeedHackOffset = 0x30; + } + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + ToaExitGP9001(); + ToaExtraTextExit(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && nCurrentPC >= 0x0009AC && nCurrentPC <= 0x0009B8) { + return 1; + } + + nCurrentPC += nSpeedHackOffset; + + if (!nIRQPending && + ((nCurrentPC >= 0x001F5E && nCurrentPC <= 0x001F64) || + (nCurrentPC >= 0x003A1C && nCurrentPC <= 0x003A22))) + { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = TOA_Z80_SPEED / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + nIRQPending = 1; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + ToaBufferGP9001Sprites(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + bVBlank = true; + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + nIRQPending = 0; + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + if ((i & 1) == 0) { + // Run Z80 + nCurrentCPU = 1; + nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * i / nInterleave) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + SekClose(); + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + ZetClose(); + + return 0; +} + +struct BurnDriver BurnDrvBgaregga = { + "bgaregga", NULL, NULL, NULL, "1996", + "Battle Garegga (World) (Sat Feb 3 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgareggaRomInfo, bgareggaRomName, NULL, NULL, battlegInputInfo, bgareggaDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBgaregcn = { + "bgareggacn", "bgaregga", NULL, NULL, "1996", + "Battle Garegga - Type 2 (China / Denmark?) (Tue Apr 2 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgaregcnRomInfo, bgaregcnRomName, NULL, NULL, battlegInputInfo, bgaregcnDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBgaregt2 = { + "bgareggat2", "bgaregga", NULL, NULL, "1996", + "Battle Garegga - Type 2 (World) (Sat Mar 2 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgaregt2RomInfo, bgaregt2RomName, NULL, NULL, battlegInputInfo, bgareggaDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBgaregnv = { + "bgaregganv", "bgaregga", NULL, NULL, "1996", + "Battle Garegga - New Version (Hong Kong / Austria?) (Sat Mar 2 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgaregnvRomInfo, bgaregnvRomName, NULL, NULL, battlegInputInfo, bgareghkDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBgareghk = { + "bgareggahk", "bgaregga", NULL, NULL, "1996", + "Battle Garegga (Hong Kong / Austria?) (Sat Feb 3 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgareghkRomInfo, bgareghkRomName, NULL, NULL, battlegInputInfo, bgareghkDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBgaregtw = { + "bgareggatw", "bgaregga", NULL, NULL, "1996", + "Battle Garegga (Taiwan / Germany) (Thu Feb 1 1996)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bgaregtwRomInfo, bgaregtwRomName, NULL, NULL, battlegInputInfo, bgaregtwDIPInfo, + battlegInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_bbakraid.cpp b/src/burn/drivers/toaplan/d_bbakraid.cpp new file mode 100644 index 00000000..960600b6 --- /dev/null +++ b/src/burn/drivers/toaplan/d_bbakraid.cpp @@ -0,0 +1,1111 @@ +#include "toaplan.h" +#include "ymz280b.h" +#include "eeprom.h" +#include "timer.h" + +// Battle Bakraid. + +// #define ADJUST_Z80_SPEED + +static const UINT8 bbakraid_unlimited_nvram[512] = { + 0xc2,0x49,0x00,0x07,0xa1,0x20,0x2a,0x2a,0x2a,0x90,0x90,0x90,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x1a,0x80,0x2a,0x2a,0x2a,0x94, + 0x94,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04, + 0x93,0xe0,0x2a,0x2a,0x2a,0x98,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x00,0x03,0x0d,0x40,0x2a,0x2a,0x2a,0x9c,0x9c,0x9c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x86,0xa0,0x2a,0x2a, + 0x2a,0xa0,0xa0,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, + 0x00,0x07,0xa1,0x20,0x2b,0x2b,0x2b,0x90,0x90,0x90,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x1a,0x80,0x2b,0x2b,0x2b,0x94,0x94,0x94, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x93,0xe0, + 0x2b,0x2b,0x2b,0x98,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x00,0x03,0x0d,0x40,0x2b,0x2b,0x2b,0x9c,0x9c,0x9c,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x86,0xa0,0x2b,0x2b,0x2b,0xa0, + 0xa0,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x07, + 0xa1,0x20,0x23,0x23,0x23,0x90,0x90,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x00,0x06,0x1a,0x80,0x23,0x23,0x23,0x94,0x94,0x94,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x93,0xe0,0x23,0x23, + 0x23,0x98,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, + 0x00,0x03,0x0d,0x40,0x23,0x23,0x23,0x9c,0x9c,0x9c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x86,0xa0,0x23,0x23,0x23,0xa0,0xa0,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x07,0xa1,0x20, + 0x3f,0x3f,0x3f,0x90,0x90,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x00,0x06,0x1a,0x80,0x3f,0x3f,0x3f,0x94,0x94,0x94,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x93,0xe0,0x3f,0x3f,0x3f,0x98, + 0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03, + 0x0d,0x40,0x3f,0x3f,0x3f,0x9c,0x9c,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x00,0x01,0x86,0xa0,0x3f,0x3f,0x3f,0xa0,0xa0,0xa0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0xc2,0x49,0xc2,0x49, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0xcf,0x00,0x04,0x00,0x00,0x21,0xd5, + 0x00,0x05,0x06,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc2,0x49 +}; + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvRegion = 0; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static UINT8 nIRQPending; + +static INT32 nSoundData[4]; +static UINT8 nSoundlatchAck; + +static INT32 Z80BusRQ = 0; + +static INT32 nCycles68KSync; + +static INT32 nTextROMStatus; + +static bool bUseAsm68KCoreOldValue = false; + +// Rom information +static struct BurnRomInfo bkraiduRomDesc[] = { + { "prg0u022_usa.bin", 0x080000, 0x95fb2ffd, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2u021.bin", 0x080000, 0xFFBA8656, BRF_ESS | BRF_PRG }, // 1 + { "prg1u023.new", 0x080000, 0x4ae9aa64, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3u024.bin", 0x080000, 0x834B8AD6, BRF_ESS | BRF_PRG }, // 3 + + { "gfxu0510.bin", 0x400000, 0x9CCA3446, BRF_GRA }, // 4 GP9001 Tile data + { "gfxu0512.bin", 0x400000, 0xA2A281D5, BRF_GRA }, // 5 + { "gfxu0511.bin", 0x400000, 0xE16472C0, BRF_GRA }, // 6 + { "gfxu0513.bin", 0x400000, 0x8BB635A0, BRF_GRA }, // 7 + + { "sndu0720.bin", 0x020000, 0xE62AB246, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom6.829", 0x400000, 0x8848B4A0, BRF_SND }, // 9 YMZ280B (AD)PCM data + { "rom7.830", 0x400000, 0xD6224267, BRF_SND }, // 10 + { "rom8.831", 0x400000, 0xA101DFB0, BRF_SND }, // 11 + + { "eeprom-bbakraid-new.bin", 0x00200, 0x35c9275a, BRF_PRG }, +}; + + +STD_ROM_PICK(bkraidu) +STD_ROM_FN(bkraidu) + +static struct BurnRomInfo bkraidjRomDesc[] = { + { "prg0u022.bin", 0x080000, 0x0DD59512, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2u021.bin", 0x080000, 0xFFBA8656, BRF_ESS | BRF_PRG }, // 1 + { "prg1u023.bin", 0x080000, 0xFECDE223, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3u024.bin", 0x080000, 0x834B8AD6, BRF_ESS | BRF_PRG }, // 3 + + { "gfxu0510.bin", 0x400000, 0x9CCA3446, BRF_GRA }, // 4 GP9001 Tile data + { "gfxu0512.bin", 0x400000, 0xA2A281D5, BRF_GRA }, // 5 + { "gfxu0511.bin", 0x400000, 0xE16472C0, BRF_GRA }, // 6 + { "gfxu0513.bin", 0x400000, 0x8BB635A0, BRF_GRA }, // 7 + + { "sndu0720.bin", 0x020000, 0xE62AB246, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom6.829", 0x400000, 0x8848B4A0, BRF_SND }, // 9 YMZ280B (AD)PCM data + { "rom7.830", 0x400000, 0xD6224267, BRF_SND }, // 10 + { "rom8.831", 0x400000, 0xA101DFB0, BRF_SND }, // 11 + + { "eeprom-bbakraid.bin", 0x00200, 0x7f97d347, BRF_PRG }, +}; + + +STD_ROM_PICK(bkraidj) +STD_ROM_FN(bkraidj) + +static struct BurnRomInfo bkraidujRomDesc[] = { + { "prg0u022.new", 0x080000, 0xFA8D38D3, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "prg2u021.bin", 0x080000, 0xFFBA8656, BRF_ESS | BRF_PRG }, // 1 + { "prg1u023.new", 0x080000, 0x4AE9AA64, BRF_ESS | BRF_PRG }, // 2 (odd) + { "prg3u024.bin", 0x080000, 0x834B8AD6, BRF_ESS | BRF_PRG }, // 3 + + { "gfxu0510.bin", 0x400000, 0x9CCA3446, BRF_GRA }, // 4 GP9001 Tile data + { "gfxu0512.bin", 0x400000, 0xA2A281D5, BRF_GRA }, // 5 + { "gfxu0511.bin", 0x400000, 0xE16472C0, BRF_GRA }, // 6 + { "gfxu0513.bin", 0x400000, 0x8BB635A0, BRF_GRA }, // 7 + + { "sndu0720.bin", 0x020000, 0xE62AB246, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "rom6.829", 0x400000, 0x8848B4A0, BRF_SND }, // 9 YMZ280B (AD)PCM data + { "rom7.830", 0x400000, 0xD6224267, BRF_SND }, // 10 + { "rom8.831", 0x400000, 0xA101DFB0, BRF_SND }, // 11 + + { "eeprom-bbakraid-new.bin", 0x00200, 0x35c9275a, BRF_PRG }, +}; + + +STD_ROM_PICK(bkraiduj) +STD_ROM_FN(bkraiduj) + +static struct BurnInputInfo bbakraidInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Shoot 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Shoot 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Shoot 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Shoot 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Shoot 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Shoot 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Test", BIT_DIGITAL, DrvButton + 2, "diag"}, + {"Service", BIT_DIGITAL, DrvButton + 0, "service"}, + {"Dip 1", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip 2", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip 3", BIT_DIPSWITCH, DrvInput + 5, "dip"}, + {"Region", BIT_DIPSWITCH, &DrvRegion , "dip"}, +}; + +STDINPUTINFO(bbakraid) + +static struct BurnDIPInfo bbakraidDIPList[] = { + + // Defaults + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x00, NULL}, + {0x17, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, "Test mode"}, + {0x15, 0x01, 0x01, 0x00, "Normal"}, + {0x15, 0x01, 0x01, 0x01, "Test"}, + // Normal + {0, 0xFE, 0, 2, "Starting coin"}, + {0x15, 0x82, 0x02, 0x00, "1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0x02, 0x02, "2 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Free play + {0, 0xFE, 0, 2, "Stick mode"}, + {0x15, 0x02, 0x02, 0x00, "Normal"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x02, 0x02, "Special"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Normal + {0, 0xFE, 0, 8, "Coin 1"}, + {0x15, 0x01, 0x1C, 0x00, "1 coin 1 credit"}, + {0x15, 0x01, 0x1C, 0x04, "1 coin 2 credits"}, + {0x15, 0x01, 0x1C, 0x08, "1 coin 3 credits"}, + {0x15, 0x01, 0x1C, 0x0C, "1 coin 4 credits"}, + {0x15, 0x01, 0x1C, 0x10, "2 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x14, "3 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x18, "4 coins 1 credit"}, + {0x15, 0x01, 0x1C, 0x1C, "Free Play"}, + // 0x1C: Free play settings active + // Normal + {0, 0xFE, 0, 7, "Coin 2"}, + {0x15, 0x82, 0xE0, 0x00, "1 coin 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x20, "1 coin 2 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x40, "1 coin 3 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x60, "1 coin 4 credits"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x80, "2 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0xA0, "3 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0xC0, "4 coins 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x82, 0xE0, 0x04, "1 coin 1 credit"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + // Free play + {0, 0xFE, 0, 2, "Hit score"}, + {0x15, 0x02, 0x20, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x20, 0x20, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Sound effect"}, + {0x15, 0x02, 0x40, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x40, 0x40, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0, 0xFE, 0, 2, "Music"}, + {0x15, 0x02, 0x80, 0x00, "Off"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + {0x15, 0x02, 0x80, 0x80, "On"}, + {0x15, 0x00, 0x1C, 0x1C, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Start rank"}, + {0x16, 0x01, 0x03, 0x00, "Normal"}, + {0x16, 0x01, 0x03, 0x01, "Easy"}, + {0x16, 0x01, 0x03, 0x02, "Hard"}, + {0x16, 0x01, 0x03, 0x03, "Very hard"}, + {0, 0xFE, 0, 4, "Timer rank"}, + {0x16, 0x01, 0x0C, 0x00, "Normal"}, + {0x16, 0x01, 0x0C, 0x04, "Low"}, + {0x16, 0x01, 0x0C, 0x08, "High"}, + {0x16, 0x01, 0x0C, 0x0C, "Highest"}, + {0, 0xFE, 0, 4, "Player counts"}, + {0x16, 0x01, 0x30, 0x00, "3"}, + {0x16, 0x01, 0x30, 0x10, "4"}, + {0x16, 0x01, 0x30, 0x20, "2"}, + {0x16, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 4, "Extra player"}, + {0x16, 0x01, 0xC0, 0x00, "2000000 each"}, + {0x16, 0x01, 0xC0, 0x40, "3000000 each"}, + {0x16, 0x01, 0xC0, 0x80, "4000000 each"}, + {0x16, 0x01, 0xC0, 0xC0, "No extra player"}, + + // DIP 3 + {0, 0xFE, 0, 2, "Screen flip"}, + {0x17, 0x01, 0x01, 0x00, "Off"}, + {0x17, 0x01, 0x01, 0x01, "On"}, + {0, 0xFE, 0, 2, "Demo sound"}, + {0x17, 0x01, 0x02, 0x00, "On"}, + {0x17, 0x01, 0x02, 0x02, "Off"}, + {0, 0xFE, 0, 2, "Stage edit"}, + {0x17, 0x01, 0x04, 0x00, "Disable"}, + {0x17, 0x01, 0x04, 0x04, "Enable"}, + {0, 0xFE, 0, 2, "Continue play"}, + {0x17, 0x01, 0x08, 0x00, "Enable"}, + {0x17, 0x01, 0x08, 0x08, "Disable"}, + {0, 0xFE, 0, 2, "Invincible"}, + {0x17, 0x01, 0x10, 0x00, "Off"}, + {0x17, 0x01, 0x10, 0x10, "On"}, + {0, 0xFE, 0, 2, "Score ranking"}, + {0x17, 0x01, 0x20, 0x00, "Save"}, + {0x17, 0x01, 0x20, 0x20, "No save"}, +}; + +static struct BurnDIPInfo bbakraidRegionDIPList[] = { + + // Region + {0x18, 0xFF, 0xFF, 0x00, NULL}, + {0, 0xFD, 0, 26, "Region"}, + {0x18, 0x01, 0x1F, 0x00, "Nippon"}, + {0x18, 0x01, 0x1F, 0x01, "U.S.A."}, + {0x18, 0x01, 0x1F, 0x02, "Europe"}, + {0x18, 0x01, 0x1F, 0x03, "Asia"}, + {0x18, 0x01, 0x1F, 0x04, "German"}, + {0x18, 0x01, 0x1F, 0x05, "Austria"}, + {0x18, 0x01, 0x1F, 0x06, "Belgium"}, + {0x18, 0x01, 0x1F, 0x07, "Denmark"}, + {0x18, 0x01, 0x1F, 0x08, "Finland"}, + {0x18, 0x01, 0x1F, 0x09, "France"}, + {0x18, 0x01, 0x1F, 0x0A, "Great Britain"}, + {0x18, 0x01, 0x1F, 0x0B, "Greece"}, + {0x18, 0x01, 0x1F, 0x0C, "Holland"}, + {0x18, 0x01, 0x1F, 0x0D, "Italy"}, + {0x18, 0x01, 0x1F, 0x0E, "Norway"}, + {0x18, 0x01, 0x1F, 0x0F, "Portugal"}, + {0x18, 0x01, 0x1F, 0x10, "Spain"}, + {0x18, 0x01, 0x1F, 0x11, "Sweden"}, + {0x18, 0x01, 0x1F, 0x12, "Switzerland"}, + {0x18, 0x01, 0x1F, 0x13, "Australia"}, + {0x18, 0x01, 0x1F, 0x14, "New Zealand"}, + {0x18, 0x01, 0x1F, 0x15, "Taiwan"}, + {0x18, 0x01, 0x1F, 0x16, "HongKong"}, + {0x18, 0x01, 0x1F, 0x17, "Korea"}, + {0x18, 0x01, 0x1F, 0x18, "China"}, + {0x18, 0x01, 0x1F, 0x19, "World"}, +}; + +STDDIPINFOEXT(bbakraid, bbakraid, bbakraidRegion) + +static struct BurnDIPInfo bkraiduRegionDIPList[] = { + + // Region + {0x18, 0xFF, 0xFF, 0x01, NULL}, + {0, 0xFD, 0, 26, "Region"}, + {0x18, 0x01, 0x1F, 0x00, "Nippon"}, + {0x18, 0x01, 0x1F, 0x01, "U.S.A."}, + {0x18, 0x01, 0x1F, 0x02, "Europe"}, + {0x18, 0x01, 0x1F, 0x03, "Asia"}, + {0x18, 0x01, 0x1F, 0x04, "German"}, + {0x18, 0x01, 0x1F, 0x05, "Austria"}, + {0x18, 0x01, 0x1F, 0x06, "Belgium"}, + {0x18, 0x01, 0x1F, 0x07, "Denmark"}, + {0x18, 0x01, 0x1F, 0x08, "Finland"}, + {0x18, 0x01, 0x1F, 0x09, "France"}, + {0x18, 0x01, 0x1F, 0x0A, "Great Britain"}, + {0x18, 0x01, 0x1F, 0x0B, "Greece"}, + {0x18, 0x01, 0x1F, 0x0C, "Holland"}, + {0x18, 0x01, 0x1F, 0x0D, "Italy"}, + {0x18, 0x01, 0x1F, 0x0E, "Norway"}, + {0x18, 0x01, 0x1F, 0x0F, "Portugal"}, + {0x18, 0x01, 0x1F, 0x10, "Spain"}, + {0x18, 0x01, 0x1F, 0x11, "Sweden"}, + {0x18, 0x01, 0x1F, 0x12, "Switzerland"}, + {0x18, 0x01, 0x1F, 0x13, "Australia"}, + {0x18, 0x01, 0x1F, 0x14, "New Zealand"}, + {0x18, 0x01, 0x1F, 0x15, "Taiwan"}, + {0x18, 0x01, 0x1F, 0x16, "HongKong"}, + {0x18, 0x01, 0x1F, 0x17, "Korea"}, + {0x18, 0x01, 0x1F, 0x18, "China"}, + {0x18, 0x01, 0x1F, 0x19, "World"}, +}; + +STDDIPINFOEXT(bkraidu, bbakraid, bkraiduRegion) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02, *RamPal; + +static INT32 nColCount = 0x0800; + +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x200000; // + RomZ80 = Next; Next += 0x020000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + YMZ280BROM = Next; Next += 0xC00000; + RamStart = Next; + ExtraTROM = Next; Next += 0x008000; // Extra Text layer tile data + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + Ram01 = Next; Next += 0x005000; // RAM + Extra text layer scroll/offset + Ram02 = Next; Next += 0x008000; // + RamPal = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x004000; // Z80 RAM + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + ExtraTSelect= Ram01; // Extra text layer scroll + ExtraTScroll= Ram01 + 0x000200; // Extra text layer offset + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029521; + } + + EEPROMScan(nAction, pnMin); // Scan EEPROM + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + YMZ280BScan(); + BurnTimerScan(nAction, pnMin); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nSoundData); + SCAN_VAR(Z80BusRQ); + SCAN_VAR(nIRQPending); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + if (ToaLoadCode(Rom01, 0, 4)) { + return 1; + } + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 4, 4, nGP9001ROMSize[0]); + + // Load the z80 Rom + BurnLoadRom(RomZ80, 8, 1); + + // Load YMZ280B (AD)PCM data + BurnLoadRom(YMZ280BROM + 0x000000, 9, 1); + BurnLoadRom(YMZ280BROM + 0x400000, 10, 1); + BurnLoadRom(YMZ280BROM + 0x800000, 11, 1); + + return 0; +} + +static inline void bbakraidSynchroniseZ80(INT32 nExtraCycles) +{ +#ifdef ADJUST_Z80_SPEED + INT32 nCycles = SekTotalCycles() / 4 + nExtraCycles; +#else + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; +#endif + + if (nCycles <= ZetTotalCycles()) { + return; + } + + nCycles68KSync = nCycles - nExtraCycles; + + BurnTimerUpdate(nCycles); +} + +static INT32 bbakraidTimerOver(INT32, INT32) +{ +// bprintf(PRINT_NORMAL, _T(" - IRQ -> 1.\n")); + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_AUTO); + + return 0; +} + +UINT8 __fastcall bbakraidZIn(UINT16 nAddress) +{ + nAddress &= 0xFF; + switch (nAddress) { + case 0x48: + return nSoundData[0]; + case 0x4A: + return nSoundData[1]; + + case 0x81: + // YMZ280B status port. + return YMZ280BReadStatus(); + +// default: +// printf("Z80 read port #%02X\n", nAddress & 0xFF); + } + return 0; +} + +void __fastcall bbakraidZOut(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + switch (nAddress) { + case 0x40: + if (!(nSoundlatchAck & 1) && ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEnd(); + } + nSoundlatchAck |= 1; + nSoundData[2] = nValue; + break; + case 0x42: + if (!(nSoundlatchAck & 2) && ZetTotalCycles() > nCycles68KSync) { + BurnTimerUpdateEnd(); + } + nSoundlatchAck |= 2; + nSoundData[3] = nValue; + break; + +// case 0x44: // ??? +// case 0x46: // Acknowledge interrupt +// break; + + case 0x80: + // YMZ280B register select + YMZ280BSelectRegister(nValue); + break; + case 0x81: + // YMZ280B register write + YMZ280BWriteRegister(nValue); + break; + +// default: +// printf("Z80 wrote value %02X to port #%02x.\n", nValue, nAddress); + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(bbakraidZIn); + ZetSetOutHandler(bbakraidZOut); + + // ROM + ZetMapArea(0x0000, 0xBFFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea(0x0000, 0xBFFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea(0xC000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea(0xC000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea(0xC000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + ZetClose(); + + return 0; +} + +static void Map68KTextROM(bool bMapTextROM) +{ + if (bMapTextROM) { + if (nTextROMStatus != 1) { + SekMapMemory(ExtraTROM, 0x200000, 0x207FFF, SM_RAM); // Extra text tile memory + + nTextROMStatus = 1; + } + } else { + if (nTextROMStatus != 0) { + SekMapMemory(ExtraTRAM, 0x200000, 0x201FFF, SM_RAM); // Extra text tilemap RAM + SekMapMemory(RamPal, 0x202000, 0x202FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram01, 0x203000, 0x207FFF, SM_RAM); // Extra text Scroll & offset; RAM + + nTextROMStatus = 0; + } + } +} + +UINT8 __fastcall bbakraidReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x500000: // Player 2 Inputs + return DrvInput[1]; + case 0x500001: // Player 1 Inputs + return DrvInput[0]; + case 0x500002: // Other inputs + return DrvInput[5]; + case 0x500003: // Dipswitch 3 + return DrvInput[2]; + case 0x500004: // Dipswitch 2 + return DrvInput[4]; + case 0x500005: // Dipswitch 1 + return DrvInput[3]; + + // These addresses contain the response of the Z80 to the (sound) commands + case 0x500011: + return nSoundData[2]; + case 0x500013: + return nSoundData[3]; + + case 0x500019: + return ((EEPROMRead() & 0x01) << 4) | (Z80BusRQ >> 4); + + default: { +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + } + + return 0; +} + +UINT16 __fastcall bbakraidReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + // Video status register + case 0x500006: + return ToaScanlineRegister(); + + // These addresses contain the response of the Z80 to the (sound) commands + case 0x500010: +// bbakraidSynchroniseZ80(0); + if (!(nSoundlatchAck & 1)) { + bbakraidSynchroniseZ80(0x0100); + } + return nSoundData[2]; + case 0x500012: +// bbakraidSynchroniseZ80(0); + if (!(nSoundlatchAck & 2)) { + bbakraidSynchroniseZ80(0x0100); + } + return nSoundData[3]; + + case 0x500018: + return ((EEPROMRead() & 0x01) << 4) | (Z80BusRQ >> 4); + + default: { +// printf("Attempt to read word value of location %x\n", sekAddress); + } + } + + return 0; +} + +void __fastcall bbakraidWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x500009: // Coin control + return; + + case 0x50001F: + Z80BusRQ = byteValue & 0x10; + EEPROMWrite(byteValue & 8, byteValue & 1, byteValue & 4); + return; + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall bbakraidWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x500014: + nSoundlatchAck &= ~1; + nSoundData[0] = wordValue; + return; + case 0x500016: + nSoundlatchAck &= ~2; + nSoundData[1] = wordValue; + return; + + // This register is always written to after writing (sound) commands for the Z80 + case 0x50001A: + bbakraidSynchroniseZ80(0); + ZetNmi(); + return; + + // Serial EEPROM command + case 0x50001E: + Z80BusRQ = wordValue & 0x10; + EEPROMWrite(wordValue & 8, wordValue & 1, wordValue & 4); + return; + + case 0x500080: + Map68KTextROM(false); + return; + + case 0x50001C: // ??? + return; + + case 0x500082: // Acknowledge interrupt + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + nIRQPending = 0; + return; + + case 0x5000C0: + case 0x5000C1: + case 0x5000C2: + case 0x5000C3: + case 0x5000C4: + case 0x5000C5: + case 0x5000C6: + case 0x5000C7: + case 0x5000C8: + case 0x5000C9: + case 0x5000CA: + case 0x5000CB: + case 0x5000CC: + case 0x5000CD: + case 0x5000CE: + GP9001TileBank[(sekAddress & 0x0F) >> 1] = ((wordValue & 0x0F) << 15); + return; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +UINT16 __fastcall bbakraidReadWordGP9001(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400008: + return ToaGP9001ReadRAM_Hi(0); + case 0x40000A: + return ToaGP9001ReadRAM_Lo(0); + + } + + return 0; +} + +void __fastcall bbakraidWriteWordGP9001(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x400000: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x400004: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x400008: + case 0x40000A: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x40000C: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + } +} + +UINT8 __fastcall bbakraidReadByteZ80ROM(UINT32 sekAddress) +{ + return RomZ80[(sekAddress & 0x7FFFF) >> 1]; +} + +UINT16 __fastcall bbakraidReadWordZ80ROM(UINT32 sekAddress) +{ + return RomZ80[(sekAddress & 0x7FFFF) >> 1]; +} + +static INT32 DrvDoReset() +{ + // Insert region code into 68K ROM, code by BisonSAS + UINT8 nRegion = DrvRegion & 0x1F; + if (nRegion<=25) { + Rom01[0x00000^1]=(UINT8)(nRegion<<13) | (DrvRegion & 0x1F); + } + + SekOpen(0); + nIRQPending = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + EEPROMReset(); + + Z80BusRQ = 0; + + memset(nSoundData, 0, sizeof(nSoundData)); + nSoundlatchAck = 0; + + YMZ280BReset(); + + nCyclesDone[0] = nCyclesDone[1] = 0; + + BurnTimerReset(); + BurnTimerSetRetrig(0, 1.0 / 445.0); + + return 0; +} + +static const eeprom_interface eeprom_interface_93C66 = +{ + 9, // address bits + 8, // data bits + "*110", // read 110 aaaaaaaaa + "*101", // write 101 aaaaaaaaa dddddddd + "*111", // erase 111 aaaaaaaaa + "*10000xxxxxxx",// lock 100x 00xxxx + "*10011xxxxxxx",// unlock 100x 11xxxx + 0, + 0 +}; + +static INT32 bbakraidInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x1000000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + EEPROMInit(&eeprom_interface_93C66); + + // Make sure we use Musashi + if (bBurnUseASMCPUEmulation) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching to Musashi 68000 core\n")); +#endif + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } + + if (strcmp("bbakraid", BurnDrvGetTextA(DRV_NAME)) == 0 || strcmp("bbakraidj", BurnDrvGetTextA(DRV_NAME)) == 0) { + if (!EEPROMAvailable()) EEPROMFill(bbakraid_unlimited_nvram, 0, sizeof(bbakraid_unlimited_nvram)); + } + + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x1FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram02, 0x208000, 0x20FFFF, SM_RAM); + + Map68KTextROM(true); + + SekSetReadWordHandler(0, bbakraidReadWord); + SekSetReadByteHandler(0, bbakraidReadByte); + SekSetWriteWordHandler(0, bbakraidWriteWord); + SekSetWriteByteHandler(0, bbakraidWriteByte); + + SekMapHandler(1, 0x400000, 0x400400, SM_RAM); // GP9001 addresses + + SekSetReadWordHandler(1, bbakraidReadWordGP9001); + SekSetWriteWordHandler(1, bbakraidWriteWordGP9001); + + SekMapHandler(2, 0x300000, 0x37FFFF, SM_ROM); // Z80 ROM + + SekSetReadByteHandler(2, bbakraidReadByteZ80ROM); + SekSetReadWordHandler(2, bbakraidReadWordZ80ROM); + + SekClose(); + } + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nExtraTXOffset = 0x2C; + ToaExtraTextInit(); + + DrvZ80Init(); // Initialize Z80 + + YMZ280BInit(16934400, NULL, 2); + + BurnTimerInit(bbakraidTimerOver, NULL); + BurnTimerAttachZet(TOA_Z80_SPEED); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + nTextROMStatus = -1; + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + BurnTimerExit(); + YMZ280BExit(); + ToaExitGP9001(); + ToaExtraTextExit(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + EEPROMExit(); + + if (bUseAsm68KCoreOldValue) { +#if 1 && defined FBA_DEBUG + bprintf(PRINT_NORMAL, _T("Switching back to A68K core\n")); +#endif + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 0 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && + ((nCurrentPC >= 0x000A42 && nCurrentPC <= 0x000A48) || + (nCurrentPC >= 0x001FF0 && nCurrentPC <= 0x001FF6))) + { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); +#ifdef ADJUST_Z80_SPEED + nCyclesTotal[1] = nCyclesTotal[0] / 4; +#else + nCyclesTotal[1] = TOA_Z80_SPEED / 60; +#endif + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + for (INT32 i = 1; i <= nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = i * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + if (!CheckSleep(0)) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nIRQPending = 1; + SekSetIRQLine(3, SEK_IRQSTATUS_ACK); + + ToaBufferGP9001Sprites(); + + if (pBurnDraw) { // Draw screen if needed + DrvDraw(); + } + + bVBlank = true; + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (!CheckSleep(0)) { // See if this CPU is busywaiting + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + + if ((i & 1) == 0) { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos); + nSoundBufferPos = nSegmentEnd; + } + } + } + + nCycles68KSync = SekTotalCycles(); + BurnTimerEndFrame(nCyclesTotal[1]); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + + SekClose(); + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + YMZ280BRender(pSoundBuf, nSegmentLength); + } + } + } + + ZetClose(); + + return 0; +} + +struct BurnDriver BurnDrvBattleBkraidu = { + "bbakraid", NULL, NULL, NULL, "1999", + "Battle Bakraid - Unlimited Version (U.S.A.) (Tue Jun 8 1999)\0", NULL, "Eighting", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bkraiduRomInfo, bkraiduRomName, NULL, NULL, bbakraidInputInfo, bkraiduDIPInfo, + bbakraidInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBattleBkraiduj = { + "bbakraidj", "bbakraid", NULL, NULL, "1999", + "Battle Bakraid - Unlimited Version (Japan) (Tue Jun 8 1999)\0", NULL, "Eighting", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bkraidujRomInfo, bkraidujRomName, NULL, NULL, bbakraidInputInfo, bbakraidDIPInfo, + bbakraidInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvBattleBkraidj = { + "bbakraidja", "bbakraid", NULL, NULL, "1999", + "Battle Bakraid (Japan) (Wed Apr 7 1999)\0", NULL, "Eighting", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, bkraidjRomInfo, bkraidjRomName, NULL, NULL, bbakraidInputInfo, bbakraidDIPInfo, + bbakraidInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_demonwld.cpp b/src/burn/drivers/toaplan/d_demonwld.cpp new file mode 100644 index 00000000..d0728458 --- /dev/null +++ b/src/burn/drivers/toaplan/d_demonwld.cpp @@ -0,0 +1,870 @@ +#include "toaplan.h" + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalRAM2; +static UINT8 *DrvShareRAM; + +static UINT8 DrvInputs[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvReset; + +static INT32 nColCount = 0x0800; + +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +static bool bUseAsm68KCoreOldValue = false; +static INT32 demonwld_hack; + +static struct BurnInputInfo DemonwldInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Demonwld) + +static struct BurnDIPInfo DemonwldDIPList[]= +{ + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x01, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + {0x16, 0x01, 0x03, 0x00, "Medium" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x00, "30K, every 100K" }, + {0x16, 0x01, 0x0c, 0x04, "50K and 100K" }, + {0x16, 0x01, 0x0c, 0x08, "100K only" }, + {0x16, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x30, "1" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x00, "3" }, + {0x16, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x16, 0x01, 0x80, 0x00, "Off" }, + {0x16, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2, "Territory/Copyright" }, + {0x17, 0x01, 0x01, 0x01, "Toaplan" }, + {0x17, 0x01, 0x01, 0x00, "Japan/Taito Corp" }, +}; + +STDDIPINFO(Demonwld) + +static struct BurnDIPInfo Demonwl1DIPList[]= +{ + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + {0x16, 0x01, 0x03, 0x00, "Medium" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x00, "30K, every 100K" }, + {0x16, 0x01, 0x0c, 0x04, "50K and 100K" }, + {0x16, 0x01, 0x0c, 0x08, "100K only" }, + {0x16, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x30, "1" }, + {0x16, 0x01, 0x30, 0x20, "2" }, + {0x16, 0x01, 0x30, 0x00, "3" }, + {0x16, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x16, 0x01, 0x80, 0x00, "Off" }, + {0x16, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 4, "Territory/Copyright" }, + {0x17, 0x01, 0x03, 0x02, "World/Taito Japan" }, + {0x17, 0x01, 0x03, 0x03, "US/Toaplan" }, + {0x17, 0x01, 0x03, 0x01, "US/Taito America" }, + {0x17, 0x01, 0x03, 0x00, "Japan/Taito Corp" }, +}; + +STDDIPINFO(Demonwl1) + +void __fastcall demonwldWriteWord(UINT32 a, UINT16 d) +{ + switch (a) + { + case 0x400000: + return; // nop + + case 0x400002: + bEnableInterrupts = d & 0xff; + return; + + case 0x400008: + case 0x40000a: + case 0x40000c: + case 0x40000e: + // toaplan1_bcu_control_w + return; + + case 0x800000: + // toaplan1_bcu_flipscreen_w + return; + + case 0x800002: + ToaBCU2SetRAMPointer(d); + return; + + case 0x800004: + case 0x800006: + ToaBCU2WriteRAM(d); + return; + + case 0x800010: + case 0x800012: + case 0x800014: + case 0x800016: + case 0x800018: + case 0x80001a: + case 0x80001c: + case 0x80001e: + BCU2Reg[(a & 0x0f) >> 1] = d; + return; + + case 0xa00000: + return; // nop + + case 0xa00002: + ToaFCU2SetRAMPointer(d); + return; + + case 0xa00004: + ToaFCU2WriteRAM(d); + return; + + case 0xa00006: + ToaFCU2WriteRAMSize(d); + return; + + case 0xe00000: + nBCU2TileXOffset = d; + return; + + case 0xe00002: + nBCU2TileYOffset = d; + return; + + case 0xe00006: + // toaplan1_fcu_flipscreen_w + return; + + case 0xe00008: + if (d == 0) { + ZetReset(); + } + return; + + case 0xe0000a: + // dsp_ctrl_w + return; + } +} + +void __fastcall demonwldWriteByte(UINT32 , UINT8 ) +{ + return; +} + +UINT16 __fastcall demonwldReadWord(UINT32 a) +{ + switch (a) + { + case 0x800002: + return ToaBCU2GetRAMPointer(); + + case 0x800004: + return ToaBCU2ReadRAM_Hi(); + + case 0x800006: + return ToaBCU2ReadRAM_Lo(); + + case 0x800010: + case 0x800012: + case 0x800014: + case 0x800016: + case 0x800018: + case 0x80001a: + case 0x80001c: + case 0x80001e: + return BCU2Reg[(a & 0x0f) >> 1]; + + case 0xa00002: + return ToaFCU2GetRAMPointer(); + + case 0xa00004: + return ToaFCU2ReadRAM(); + + case 0xa00006: + return ToaFCU2ReadRAMSize(); + + case 0xe0000e: // hack + { + demonwld_hack++; + if (demonwld_hack & 4) + return 0x76; + else + return 0; + } + } + + return 0; +} + +UINT8 __fastcall demonwldReadByte(UINT32 a) +{ + switch (a) + { + case 0x400001: + case 0xa00001: + return ToaVBlankRegister(); + } + + return 0; +} + +void __fastcall demonwld_sound_write_port(UINT16 p, UINT8 d) +{ + switch (p & 0xff) + { + case 0x00: + BurnYM3812Write(0, d); + return; + + case 0x01: + BurnYM3812Write(1, d); + return; + + case 0x40: // toaplan1_coin_w + return; + } +} + +UINT8 __fastcall demonwld_sound_read_port(UINT16 p) +{ + switch (p & 0xff) + { + case 0x00: + case 0x01: + return BurnYM3812Read(p & 1); + + case 0x20: + return DrvDips[2]; + + case 0x60: + return DrvInputs[2]; + + case 0x80: + return DrvInputs[0]; + + case 0xa0: + return DrvDips[1]; + + case 0xc0: + return DrvInputs[1]; + + case 0xe0: + return DrvDips[0]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + demonwld_hack = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000 + 0x400; + DrvZ80ROM = Next; Next += 0x010000; + BCU2ROM = Next; Next += nBCU2ROMSize; + FCU2ROM = Next; Next += nFCU2ROMSize; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvPalRAM2 = Next; Next += 0x000800; + + RamZ80 = Next; + DrvShareRAM = Next; Next += 0x008000; + + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + + RamEnd = Next; + + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + if (bBurnUseASMCPUEmulation) { + bUseAsm68KCoreOldValue = bBurnUseASMCPUEmulation; + bBurnUseASMCPUEmulation = false; + } + + INT32 nLen; + +// bToaRotateScreen = true; + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(AllMem, 0, nLen); + MemIndex(); + + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 2, 1)) return 1; + + ToaLoadTiles(BCU2ROM, 5, nBCU2ROMSize); + ToaLoadTiles(FCU2ROM, 9, nFCU2ROMSize); + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03FFFF, SM_ROM); + SekMapMemory(DrvPalRAM, 0x404000, 0x4047FF, SM_RAM); + SekMapMemory(DrvPalRAM2, 0x406000, 0x4067FF, SM_RAM); + SekMapMemory(Drv68KRAM, 0xc00000, 0xc03FFF, SM_RAM); + SekSetReadWordHandler(0, demonwldReadWord); + SekSetReadByteHandler(0, demonwldReadByte); + SekSetWriteWordHandler(0, demonwldWriteWord); + SekSetWriteByteHandler(0, demonwldWriteByte); + + SekMapHandler(1, 0x600000, 0x600FFF, SM_RAM); + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xffff, 0, DrvShareRAM); + ZetMapArea(0x8000, 0xffff, 1, DrvShareRAM); + ZetMapArea(0x8000, 0xffff, 2, DrvShareRAM); + ZetSetOutHandler(demonwld_sound_write_port); + ZetSetInHandler(demonwld_sound_read_port); + ZetMemEnd(); + ZetClose(); + } + + ToaInitBCU2(); + + nToaPalLen = nColCount; + ToaPalSrc = DrvPalRAM; + ToaPalSrc2 = DrvPalRAM2; + ToaPalInit(); + + ToaOpaquePriority = 2; + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); + ZetExit(); + SekExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); + } + + ToaPalUpdate(); + ToaPal2Update(); + + if (bUseAsm68KCoreOldValue) { + bUseAsm68KCoreOldValue = false; + bBurnUseASMCPUEmulation = true; + } + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInputs, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] |= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + } + ToaClearOpposites(&DrvInputs[0]); + ToaClearOpposites(&DrvInputs[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + +// ToaBufferFCU2Sprites(); + + SekClose(); + ZetClose(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(nCyclesDone); + SCAN_VAR(demonwld_hack); + } + + return 0; +} + +// Hack to bypass the missing sub-cpu. All games except the taito +// set check the crc and rather than dealing with that, I'm seperating +// the opcodes and data and just patching the opcodes. +// Taito set patches from MAME 0.36b10. +static void map_hack(INT32 hack_off) +{ + INT32 cpy_off = hack_off & ~0x3ff; + + memcpy (Drv68KROM + 0x40000, Drv68KROM + cpy_off, 0x400); + + hack_off -= cpy_off; + hack_off += 0x40000; + + *((UINT16*)(Drv68KROM + hack_off + 0)) = 0x4e71; + *((UINT16*)(Drv68KROM + hack_off + 8)) = 0x600a; + + SekOpen(0); + SekMapMemory(Drv68KROM + 0x40000, cpy_off, cpy_off + 0x3ff, SM_FETCH); + SekClose(); +} + + +// Demon's World / Horror Story (set 1) + +static struct BurnRomInfo demonwldRomDesc[] = { + { "o16-10.v2", 0x20000, 0xca8194f3, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o16-09.v2", 0x20000, 0x7baea7ba, BRF_PRG | BRF_ESS }, // 1 + + { "rom11.v2", 0x08000, 0xdbe08c85, BRF_PRG | BRF_ESS }, // 2 CPU #1 code + + { "dsp_21.bin", 0x00800, 0x2d135376, BRF_PRG | BRF_ESS }, // 3 MCU code + { "dsp_22.bin", 0x00800, 0x79389a71, BRF_PRG | BRF_ESS }, // 4 + + { "rom05", 0x20000, 0x6506c982, BRF_GRA }, // 5 Tile data + { "rom07", 0x20000, 0xa3a0d993, BRF_GRA }, // 6 + { "rom06", 0x20000, 0x4fc5e5f3, BRF_GRA }, // 7 + { "rom08", 0x20000, 0xeb53ab09, BRF_GRA }, // 8 + + { "rom01", 0x20000, 0x1b3724e9, BRF_GRA }, // 9 + { "rom02", 0x20000, 0x7b20a44d, BRF_GRA }, // 10 + { "rom03", 0x20000, 0x2cacdcd0, BRF_GRA }, // 11 + { "rom04", 0x20000, 0x76fd3201, BRF_GRA }, // 12 + + { "prom12.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 13 Sprite attribute PROM + { "prom13.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 14 +}; + +STD_ROM_PICK(demonwld) +STD_ROM_FN(demonwld) + +static INT32 demonwldInit() +{ + INT32 nRet = DrvInit(); + + if (nRet == 0) { + map_hack(0x1430); + } + + return nRet; +} + +struct BurnDriver BurnDrvDemonwld = { + "demonwld", NULL, NULL, NULL, "1990", + "Demon's World / Horror Story (set 1)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TOAPLAN_RAIZING, GBF_PLATFORM, 0, + NULL, demonwldRomInfo, demonwldRomName, NULL, NULL, DemonwldInputInfo, DemonwldDIPInfo, + demonwldInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Demon's World / Horror Story (Taito license, set 2) + +static struct BurnRomInfo demonwld1RomDesc[] = { + { "o16-10.rom", 0x20000, 0x036ee46c, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o16-09.rom", 0x20000, 0xbed746e3, BRF_PRG | BRF_ESS }, // 1 + + { "rom11", 0x08000, 0x397eca1b, BRF_PRG | BRF_ESS }, // 2 CPU #1 code + + { "dsp_21.bin", 0x00800, 0x2d135376, BRF_PRG | BRF_ESS }, // 3 MCU code + { "dsp_22.bin", 0x00800, 0x79389a71, BRF_PRG | BRF_ESS }, // 4 + + { "rom05", 0x20000, 0x6506c982, BRF_GRA }, // 5 Tile data + { "rom07", 0x20000, 0xa3a0d993, BRF_GRA }, // 6 + { "rom06", 0x20000, 0x4fc5e5f3, BRF_GRA }, // 7 + { "rom08", 0x20000, 0xeb53ab09, BRF_GRA }, // 8 + + { "rom01", 0x20000, 0x1b3724e9, BRF_GRA }, // 9 + { "rom02", 0x20000, 0x7b20a44d, BRF_GRA }, // 10 + { "rom03", 0x20000, 0x2cacdcd0, BRF_GRA }, // 11 + { "rom04", 0x20000, 0x76fd3201, BRF_GRA }, // 12 + + { "prom12.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 13 Sprite attribute PROM + { "prom13.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 14 +}; + +STD_ROM_PICK(demonwld1) +STD_ROM_FN(demonwld1) + +static INT32 demonwld1Init() +{ + INT32 nRet = DrvInit(); + + if (nRet == 0) { + map_hack(0x181c); + } + + return nRet; +} + +struct BurnDriver BurnDrvDemonwld1 = { + "demonwld1", "demonwld", NULL, NULL, "1989", + "Demon's World / Horror Story (Taito license, set 2)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_PLATFORM, 0, + NULL, demonwld1RomInfo, demonwld1RomName, NULL, NULL, DemonwldInputInfo, Demonwl1DIPInfo, + demonwld1Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Demon's World / Horror Story (set 3) + +static struct BurnRomInfo demonwld2RomDesc[] = { + { "o16-10-2.bin", 0x20000, 0x84ee5218, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o16-09-2.bin", 0x20000, 0xcf474cb2, BRF_PRG | BRF_ESS }, // 1 + + { "rom11", 0x08000, 0x397eca1b, BRF_PRG | BRF_ESS }, // 2 CPU #1 code + + { "dsp_21.bin", 0x00800, 0x2d135376, BRF_PRG | BRF_ESS }, // 3 MCU code + { "dsp_22.bin", 0x00800, 0x79389a71, BRF_PRG | BRF_ESS }, // 4 + + { "rom05", 0x20000, 0x6506c982, BRF_GRA }, // 5 Tile data + { "rom07", 0x20000, 0xa3a0d993, BRF_GRA }, // 6 + { "rom06", 0x20000, 0x4fc5e5f3, BRF_GRA }, // 7 + { "rom08", 0x20000, 0xeb53ab09, BRF_GRA }, // 8 + + { "rom01", 0x20000, 0x1b3724e9, BRF_GRA }, // 9 + { "rom02", 0x20000, 0x7b20a44d, BRF_GRA }, // 10 + { "rom03", 0x20000, 0x2cacdcd0, BRF_GRA }, // 11 + { "rom04", 0x20000, 0x76fd3201, BRF_GRA }, // 12 + + { "prom12.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 13 Sprite attribute PROM + { "prom13.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 14 +}; + +STD_ROM_PICK(demonwld2) +STD_ROM_FN(demonwld2) + +struct BurnDriver BurnDrvDemonwld2 = { + "demonwld2", "demonwld", NULL, NULL, "1989", + "Demon's World / Horror Story (set 3)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_PLATFORM, 0, + NULL, demonwld2RomInfo, demonwld2RomName, NULL, NULL, DemonwldInputInfo, Demonwl1DIPInfo, + demonwld1Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Demon's World / Horror Story (set 4) + +static struct BurnRomInfo demonwld3RomDesc[] = { + { "o16-10.bin", 0x20000, 0x6f7468e0, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o16-09.bin", 0x20000, 0xa572f5f7, BRF_PRG | BRF_ESS }, // 1 + + { "rom11", 0x08000, 0x397eca1b, BRF_PRG | BRF_ESS }, // 2 CPU #1 code + + { "dsp_21.bin", 0x00800, 0x2d135376, BRF_PRG | BRF_ESS }, // 3 MCU code + { "dsp_22.bin", 0x00800, 0x79389a71, BRF_PRG | BRF_ESS }, // 4 + + { "rom05", 0x20000, 0x6506c982, BRF_GRA }, // 5 Tile data + { "rom07", 0x20000, 0xa3a0d993, BRF_GRA }, // 6 + { "rom06", 0x20000, 0x4fc5e5f3, BRF_GRA }, // 7 + { "rom08", 0x20000, 0xeb53ab09, BRF_GRA }, // 8 + + { "rom01", 0x20000, 0x1b3724e9, BRF_GRA }, // 9 + { "rom02", 0x20000, 0x7b20a44d, BRF_GRA }, // 10 + { "rom03", 0x20000, 0x2cacdcd0, BRF_GRA }, // 11 + { "rom04", 0x20000, 0x76fd3201, BRF_GRA }, // 12 + + { "prom12.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 13 Sprite attribute PROM + { "prom13.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 14 +}; + +STD_ROM_PICK(demonwld3) +STD_ROM_FN(demonwld3) + +static INT32 demonwld3Init() +{ + INT32 nRet = DrvInit(); + + if (nRet == 0) { + map_hack(0x1828); + } + + return nRet; +} + +struct BurnDriver BurnDrvDemonwld3 = { + "demonwld3", "demonwld", NULL, NULL, "1989", + "Demon's World / Horror Story (set 4)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_PLATFORM, 0, + NULL, demonwld3RomInfo, demonwld3RomName, NULL, NULL, DemonwldInputInfo, Demonwl1DIPInfo, + demonwld3Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/d_dogyuun.cpp b/src/burn/drivers/toaplan/d_dogyuun.cpp new file mode 100644 index 00000000..83d83f22 --- /dev/null +++ b/src/burn/drivers/toaplan/d_dogyuun.cpp @@ -0,0 +1,785 @@ +#include "toaplan.h" +#include "vez.h" +// Dogyuun + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 v25_reset = 0; + +// Rom information +static struct BurnRomInfo dogyuunRomDesc[] = { + { "tp022_01.r16", 0x080000, 0x79EB2429, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp022_3.w92", 0x100000, 0x191B595F, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp022_4.w93", 0x100000, 0xD58D29CA, BRF_GRA }, // 2 + + { "tp022_5.w16", 0x200000, 0xD4C1DB45, BRF_GRA }, // 3 GP9001 #2 Tile data + { "tp022_6.w17", 0x200000, 0xD48DC74F, BRF_GRA }, // 4 + + { "tp022_2.w30", 0x040000, 0x043271B3, BRF_SND }, // 5 ADPCM data +}; + + +STD_ROM_PICK(dogyuun) +STD_ROM_FN(dogyuun) + +static struct BurnRomInfo dogyuunkRomDesc[] = { + { "01.u64", 0x080000, 0xfe5bd7f4, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp022_3.w92", 0x100000, 0x191B595F, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp022_4.w93", 0x100000, 0xD58D29CA, BRF_GRA }, // 2 + + { "tp022_5.w16", 0x200000, 0xD4C1DB45, BRF_GRA }, // 3 GP9001 #2 Tile data + { "tp022_6.w17", 0x200000, 0xD48DC74F, BRF_GRA }, // 4 + + { "tp022_2.w30", 0x040000, 0x043271B3, BRF_SND }, // 5 ADPCM data +}; + + +STD_ROM_PICK(dogyuunk) +STD_ROM_FN(dogyuunk) + +static struct BurnRomInfo dogyuuntRomDesc[] = { + { "sample10.9.u64.bin", 0x080000, 0x585f5016, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp022_3.w92", 0x100000, 0x191B595F, BRF_GRA }, // 1 GP9001 #1 Tile data + { "tp022_4.w93", 0x100000, 0xD58D29CA, BRF_GRA }, // 2 + + { "tp022_5.w16", 0x200000, 0xD4C1DB45, BRF_GRA }, // 3 GP9001 #2 Tile data + { "tp022_6.w17", 0x200000, 0xD48DC74F, BRF_GRA }, // 4 + + { "tp022_2.w30", 0x040000, 0x043271B3, BRF_SND }, // 5 ADPCM data +}; + + +STD_ROM_PICK(dogyuunt) +STD_ROM_FN(dogyuunt) + +static struct BurnInputInfo dogyuunInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(dogyuun) + +static struct BurnDIPInfo dogyuunDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Coin play"}, + {0x14, 0x01, 0x01, 0x01, "Free play"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0F, 0x03, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B (normal)"}, + {0x15, 0x01, 0x03, 0x01, "A (easy)"}, + {0x15, 0x01, 0x03, 0x02, "C (hard)"}, + {0x15, 0x01, 0x03, 0x03, "D (very hard)"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x15, 0x01, 0x0C, 0x00, "200,000pts only"}, + {0x15, 0x01, 0x0C, 0x04, "200,000 every max 3"}, + {0x15, 0x01, 0x0C, 0x08, "400,000pts only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x01, "5"}, + {0x15, 0x01, 0x30, 0x02, "2"}, + {0x15, 0x01, 0x30, 0x03, "1"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "Debug mode"}, + {0, 0xFE, 0, 2, "Continue play"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, +}; + +static struct BurnDIPInfo dogyuunRegionDIPList[] = { + // Region + {0x16, 0xFF, 0x0F, 0x03, NULL}, + {0, 0xFE, 0, 9, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "U.S.A. (Atari Games Corp.)"}, + {0x16, 0x01, 0x0F, 0x03, "Europe"}, + {0x16, 0x01, 0x0F, 0x04, "Hong Kong (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x05, "Korea (Unite Trading)"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan"}, +// {0x16, 0x01, 0x0F, 0x07, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x08, "South East Asia (Charterfield)"}, +// {0x16, 0x01, 0x0F, 0x09, "Hong Kong (Charterfield)"}, +// {0x16, 0x01, 0x0F, 0x0A, "Korea (Unite Trading)"}, +// {0x16, 0x01, 0x0F, 0x0B, "Taiwan"}, +// {0x16, 0x01, 0x0F, 0x0C, "U.S.A. (Atari Games Corp.)"}, +// {0x16, 0x01, 0x0F, 0x0D, "South East Asia (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x0F, "Japan (Taito Corp license)"}, +}; + +STDDIPINFOEXT(dogyuun, dogyuunRegion, dogyuun) + +static struct BurnDIPInfo dogyuunkRegionDIPList[] = { + // Region + {0x16, 0xFF, 0x0F, 0x05, NULL}, + {0, 0xFE, 0, 9, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "U.S.A. (Atari Games Corp.)"}, + {0x16, 0x01, 0x0F, 0x03, "Europe"}, + {0x16, 0x01, 0x0F, 0x04, "Hong Kong (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x05, "Korea (Unite Trading)"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan"}, +// {0x16, 0x01, 0x0F, 0x07, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x08, "South East Asia (Charterfield)"}, +// {0x16, 0x01, 0x0F, 0x09, "Hong Kong (Charterfield)"}, +// {0x16, 0x01, 0x0F, 0x0A, "Korea (Unite Trading)"}, +// {0x16, 0x01, 0x0F, 0x0B, "Taiwan"}, +// {0x16, 0x01, 0x0F, 0x0C, "U.S.A. (Atari Games Corp.)"}, +// {0x16, 0x01, 0x0F, 0x0D, "South East Asia (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x0F, "Japan (Taito Corp license)"}, +}; + +STDDIPINFOEXT(dogyuunk, dogyuunkRegion, dogyuun) + +static struct BurnDIPInfo dogyuuntRegionDIPList[] = { + // Region + {0x16, 0xFF, 0x0F, 0x00, NULL}, + {0, 0xFE, 0, 12, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "South East Asia (Charterfield license)"}, + {0x16, 0x01, 0x0F, 0x07, "USA (Romstar license)"}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong and China (Honest Trading Co. license)"}, + {0x16, 0x01, 0x0F, 0x09, "Korea (JC Trading Corp. license)"}, + {0x16, 0x01, 0x0F, 0x0A, "USA (Fabtek license)"}, + {0x16, 0x01, 0x0F, 0x0F, "Japan (Taito Corp license)"}, + }; + +STDDIPINFOEXT(dogyuunt, dogyuuntRegion, dogyuun) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + GP9001ROM[1]= Next; Next += nGP9001ROMSize[1]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x040000; + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + ShareRAM = Next; Next += 0x010000; + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001RAM[1]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + GP9001Reg[1]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + VezScan(nAction); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0], true); + ToaLoadGP9001Tiles(GP9001ROM[1], 3, 2, nGP9001ROMSize[1], true); + + BurnLoadRom(MSM6295ROM, 5, 1); + + return 0; +} + +UINT8 __fastcall dogyuunReadByte(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) { + case 0x200011: // Player 1 inputs + return DrvInput[0]; + case 0x200015: // Player 2 inputs + return DrvInput[1]; + case 0x200019: // Other inputs + return DrvInput[2]; + + case 0x30000D: + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; + +} + +UINT16 __fastcall dogyuunReadWord(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) { + + case 0x200010: // Player 1 inputs + return DrvInput[0]; + case 0x200014: // Player 2 inputs + return DrvInput[1]; + case 0x200018: // Other inputs + return DrvInput[2]; + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + case 0x500004: + return ToaGP9001ReadRAM_Hi(1); + case 0x500006: + return ToaGP9001ReadRAM_Lo(1); + + case 0x700000: { + static INT32 i; + UINT16 nStatus; + + i++; + nStatus = 0xFFFF - (i & 0xFF); + if (i & 1) { + nStatus &= 0x00FF; + } + return nStatus; + + } + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall dogyuunWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = byteValue; + return; + } + + switch (sekAddress) { + case 0x20001c: + case 0x20001d: + if (!v25_reset && (~byteValue & 0x20)) VezReset(); + v25_reset = (~byteValue & 0x20); + break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall dogyuunWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = wordValue; + return; + } + + switch (sekAddress) { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x500000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue, 1); + break; + + case 0x500004: + ToaGP9001WriteRAM(wordValue, 1); + break; + case 0x500006: + ToaGP9001WriteRAM(wordValue, 1); + break; + + case 0x500008: + ToaGP9001SelectRegister(wordValue, 1); + break; + + case 0x50000C: + ToaGP9001WriteRegister(wordValue, 1); + break; + + default: { + printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } + } +} + +void __fastcall dogyuun_v25_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x00000: + BurnYM2151SelectRegister(data); + return; + + case 0x00001: + BurnYM2151WriteRegister(data); + return; + + case 0x00004: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall dogyuun_v25_read(UINT32 address) +{ + switch (address) + { + case 0x00001: + return BurnYM2151ReadStatus(); + + case 0x00004: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT8 __fastcall dogyuun_v25_read_port(UINT32 port) +{ + switch (port) + { + case V25_PORT_PT: + return DrvInput[4]^0xff; + + case V25_PORT_P0: + return DrvInput[3]^0xff; + + case V25_PORT_P1: + return DrvInput[5]^0xff; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + VezOpen(0); + VezReset(); + VezClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + v25_reset = 1; + + return 0; +} + +static UINT8 nitro_decryption_table[256] = { + 0x1b,0x56,0x75,0x88,0x8c,0x06,0x58,0x72, 0x83,0x86,0x36,0x1a,0x5f,0xd3,0x8c,0xe9, /* 00 */ + 0x22,0x0f,0x03,0x2a,0xeb,0x2a,0xf9,0x0f, 0xa4,0xbd,0x75,0xf3,0x4f,0x53,0x8e,0xfe, /* 10 */ + 0x87,0xe8,0xb1,0x8d,0x36,0xb5,0x43,0x73, 0x2a,0x5b,0xf9,0x02,0x24,0x8a,0x03,0x80, /* 20 */ + 0x86,0x8b,0xd1,0x3e,0x8d,0x3e,0x58,0xfb, 0xc3,0x79,0xbd,0xb7,0x8a,0xe8,0x0f,0x81, /* 30 */ + 0xb7,0xd0,0x8b,0xeb,0xff,0xb8,0x90,0x8b, 0x5e,0xa2,0x90,0x90,0xab,0xb4,0x80,0x59, /* 40 */ + 0x87,0x72,0xb5,0xbd,0xb0,0x88,0x50,0x0f, 0xfe,0xd2,0xc3,0x90,0x8a,0x90,0xf9,0x75, /* 50 */ + 0x1a,0xb3,0x74,0x0a,0x68,0x24,0xbb,0x90, 0x75,0x47,0xfe,0x2c,0xbe,0xc3,0x88,0xd2, /* 60 */ + 0x3e,0xc1,0x8c,0x33,0x0f,0x90,0x8b,0x90, 0xb9,0x1e,0xff,0xa2,0x3e,0x22,0xbe,0x57, /* 70 */ + 0x81,0x3a,0xf6,0x88,0xeb,0xb1,0x89,0x8a, 0x32,0x80,0x0f,0xb1,0x48,0xc3,0x68,0x72, /* 80 */ + 0x53,0x02,0xc0,0x02,0xe8,0xb4,0x74,0xbc, 0x90,0x58,0x0a,0xf3,0x75,0xc6,0x90,0xe8, /* 90 */ + 0x26,0x50,0xfc,0x8c,0x90,0xb1,0xc3,0xd1, 0xeb,0x83,0xa4,0xbf,0x26,0x4b,0x46,0xfe, /* a0 */ + 0xe2,0x89,0xb3,0x88,0x03,0x56,0x0f,0x38, 0xbb,0x0c,0x90,0x0f,0x07,0x8a,0x8a,0x33, /* b0 */ + 0xfe,0xf9,0xb1,0xa0,0x45,0x36,0x22,0x5e, 0x8a,0xbe,0xc6,0xea,0x3c,0xb2,0x1e,0xe8, /* c0 */ + 0x90,0xeb,0x55,0xf6,0x8a,0xb0,0x5d,0xc0, 0xbb,0x8d,0xf6,0xd0,0xd1,0x88,0x4d,0x90, /* d0 */ + 0x51,0x51,0x74,0xbd,0x32,0xd1,0x90,0xd2, 0x53,0xc7,0xab,0x36,0x50,0xe9,0x33,0xb3, /* e0 */ + 0x2e,0x05,0x88,0x59,0x74,0x74,0x22,0x8e, 0x8a,0x8a,0x36,0x08,0x0f,0x45,0x90,0x2e, /* f0 */ +}; + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x200000; + nGP9001ROMSize[1] = 0x400000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x103FFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, dogyuunReadWord); + SekSetReadByteHandler(0, dogyuunReadByte); + SekSetWriteWordHandler(0, dogyuunWriteWord); + SekSetWriteByteHandler(0, dogyuunWriteByte); + SekClose(); + + VezInit(0, V25_TYPE, 12500000 /*before divider*/); + VezOpen(0); + for (INT32 i = 0x80000; i < 0x100000; i += 0x8000) { + VezMapArea(i, i + 0x7fff, 0, ShareRAM); + VezMapArea(i, i + 0x7fff, 1, ShareRAM); + VezMapArea(i, i + 0x7fff, 2, ShareRAM); + } + VezSetReadHandler(dogyuun_v25_read); + VezSetWriteHandler(dogyuun_v25_write); + VezSetReadPort(dogyuun_v25_read_port); + VezSetDecode(nitro_decryption_table); + VezClose(); + } + + BurnYM2151Init(3375000, 50.0); + MSM6295Init(0, 1041667 / 132, 50.0, 1); + + nSpriteXOffset = 0x0024; + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(2); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + MSM6295Exit(0); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + VezExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + MSM6295ROM = NULL; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + VezNewFrame(); + + INT32 nSoundBufferPos = 0; + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)6250000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + ToaBufferGP9001Sprites(); + + bVBlank = true; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // sound! (increase interleave?) + if (v25_reset) { + nCyclesDone[1] += nCyclesTotal[1] / nInterleave; + } else { + nCyclesDone[1] += VezRun(nCyclesTotal[1] / nInterleave); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + + } + } + + VezClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvDogyuun = { + "dogyuun", NULL, NULL, NULL, "1992", + "Dogyuun\0", NULL, "Toaplan", "Dual Toaplan GP9001 based", + L"Dogyuun\0Dogyuun \u30C9\u30AD\u30E5\u30FC\u30F3\uFF01\uFF01\0", NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, dogyuunRomInfo, dogyuunRomName, NULL, NULL, dogyuunInputInfo, dogyuunDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDogyuunk = { + "dogyuuna", "dogyuun", NULL, NULL, "1992", + "Dogyuun (Licensed to Unite Trading For Korea)\0", NULL, "Toaplan", "Dual Toaplan GP9001 based", + L"Dogyuun (Licensed to Unite Trading For Korea)\0Dogyuun \u30C9\u30AD\u30E5\u30FC\u30F3\uFF01\uFF01\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, dogyuunkRomInfo, dogyuunkRomName, NULL, NULL, dogyuunInputInfo, dogyuunkDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvDogyuunt = { + "dogyuunt", "dogyuun", NULL, NULL, "1992", + "Dogyuun (test location version)\0", NULL, "Toaplan", "Dual Toaplan GP9001 based", + L"Dogyuun (test location version)\0Dogyuun \u30C9\u30AD\u30E5\u30FC\u30F3\uFF01\uFF01\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, dogyuuntRomInfo, dogyuuntRomName, NULL, NULL, dogyuunInputInfo, dogyuuntDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_fixeight.cpp b/src/burn/drivers/toaplan/d_fixeight.cpp new file mode 100644 index 00000000..a0306d3f --- /dev/null +++ b/src/burn/drivers/toaplan/d_fixeight.cpp @@ -0,0 +1,1031 @@ +#include "toaplan.h" +#include "eeprom.h" +#include "vez.h" + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM, *EEPROM; + +static const INT32 nColCount = 0x0800; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 v25_reset = 0; +static INT32 set_region = 0; + +static struct BurnInputInfo FixeightInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"P3 Coin", BIT_DIGITAL, DrvButton + 0, "p3 coin" }, + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 6, "p3 start" }, + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up" }, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down" }, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left" }, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right" }, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1" }, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Tilt", BIT_DIGITAL, DrvButton + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvInput + 4, "dip" }, +}; + +STDINPUTINFO(Fixeight) + +static struct BurnDIPInfo FixeightDIPList[]= +{ + {0x1a, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x1a, 0x01, 0x04, 0x00, "Off" }, + {0x1a, 0x01, 0x04, 0x04, "On" }, +}; + +STDDIPINFO(Fixeight) + +UINT8 __fastcall fixeightReadByte(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x280000) { + return ShareRAM[(sekAddress >> 1) & 0x7fff]; + } + + if ((sekAddress & 0xff0000) == 0x600000) { + return ExtraTROM[(sekAddress & 0xFFFF) >> 1]; + } + + switch (sekAddress) { + + case 0x200001: // Player 1 inputs + return DrvInput[0]; + case 0x200005: // Player 2 inputs + return DrvInput[1]; + case 0x200009: // Player 3 inputs + return DrvInput[2]; + case 0x200011: // Other inputs + return (DrvInput[3] & ~0x04) | (DrvInput[4] & 0x04); + + case 0x30000d: + return ToaVBlankRegister(); + + //default: + // bprintf(0, _T("Attempt to read byte value of location %x\n"), sekAddress); + } + return 0; +} + +UINT16 __fastcall fixeightReadWord(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x280000) { + return ShareRAM[(sekAddress >> 1) & 0x7fff]; + } + + if ((sekAddress & 0xff0000) == 0x600000) { + return ExtraTROM[(sekAddress & 0xFFFF) >> 1] | (ExtraTROM[0x8000 + ((sekAddress & 0xFFFF) >> 1)] << 8); + } + + switch (sekAddress) { + + case 0x200000: // Player 1 inputs + return DrvInput[0]; + case 0x200004: // Player 2 inputs + return DrvInput[1]; + case 0x200008: // Player 3 inputs + return DrvInput[2]; + case 0x200010: // Other inputs + return (DrvInput[3] & ~0x04) | (DrvInput[4] & 0x04); + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + case 0x800000: + return ToaScanlineRegister(); + + //default: + // bprintf(0, _T("Attempt to read word value of location %x\n"), sekAddress); + } + return 0; +} + +void __fastcall fixeightWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if ((sekAddress & 0xff0000) == 0x280000) { + ShareRAM[(sekAddress >> 1) & 0x7fff] = byteValue; + return; + } + + if ((sekAddress & 0xff0000) == 0x600000) { + ExtraTROM[(sekAddress & 0xFFFF) >> 1] = byteValue; + return; + } + + switch (sekAddress) { + case 0x200019: // nop? + break; + + case 0x20001d: // coin counter + break; + + case 0x700000: + case 0x700001: + if (!v25_reset && (~byteValue & 0x08)) VezReset(); + v25_reset = (~byteValue & 0x08); + break; + + //default: + // bprintf(0, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress); + } +} + +void __fastcall fixeightWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if ((sekAddress & 0xff0000) == 0x280000) { + ShareRAM[(sekAddress >> 1) & 0x7fff] = wordValue; + return; + } + + if ((sekAddress & 0xff0000) == 0x600000) { + ExtraTROM[(sekAddress & 0xFFFF) >> 1] = wordValue & 0xFF; + ExtraTROM[0x8000 + ((sekAddress & 0xFFFF) >> 1)] = wordValue << 8; + return; + } + + switch (sekAddress) { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x700000: + if (!v25_reset && (~wordValue & 0x08)) VezReset(); + v25_reset = (~wordValue & 0x08); + break; + + //default: + // bprintf(0, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress); + } +} + +void __fastcall fixeight_v25_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x0000a: + BurnYM2151SelectRegister(data); + return; + + case 0x0000b: + BurnYM2151WriteRegister(data); + return; + + case 0x0000c: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall fixeight_v25_read(UINT32 address) +{ + switch (address) + { + case 0x00004: + return set_region; + + case 0x0000b: + return BurnYM2151ReadStatus(); + + case 0x0000c: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT8 __fastcall fixeight_v25_read_port(UINT32 port) +{ + switch (port) + { + case V25_PORT_P0: + return EEPROMRead() ? 0x80 : 0x00; + } + + return 0; +} + +void __fastcall fixeight_v25_write_port(UINT32 port, UINT8 data) +{ + switch (port) + { + case V25_PORT_P0: + EEPROMWrite(data & 0x20, data & 0x10, data & 0x40); + return; + } +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + + ToaExtraTextExit(); + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + VezExit(); + + EEPROMExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + VezOpen(0); + VezReset(); + VezClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + EEPROMReset(); + if (!EEPROMAvailable()) { + EEPROMFill(EEPROM, 0, 0x80); + } + + v25_reset = 1; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 100; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + DrvInput[3] = 0x00; // Player 3 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvJoy3[i] & 1) << i; + DrvInput[3] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + VezNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + + ToaBufferGP9001Sprites(); + + bVBlank = true; + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // sound! (increase interleave?) + if (v25_reset) { + nCyclesDone[1] += nCyclesTotal[1] / nInterleave; + } else { + nCyclesDone[1] += VezRun(nCyclesTotal[1] / nInterleave); + } + } + + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + BurnYM2151Render(pBurnSoundOut, nBurnSoundLen); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + } + + VezClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0] = Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x040000; + EEPROM = Next; Next += 0x000080; + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + ExtraTROM = Next; Next += 0x010000; // Extra tile layer + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + ShareRAM = Next; Next += 0x010000; + ExtraTScroll = Next; Next += 0x001000; // + ExtraTSelect = Next; Next += 0x001000; // + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0] = Next; Next += 0x004000; + GP9001Reg[0] = (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 3, 1); + + BurnLoadRom(EEPROM, 4, 1); // dumped version + BurnLoadRom(EEPROM, 5, 1); // load over dumped version + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029497; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile data + struct BurnArea ba; + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + ba.Data = ShareRAM; + ba.nLen = 0x8000; + ba.szName = "Shared RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + VezScan(nAction); + + EEPROMScan(nAction, pnMin); + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static UINT8 ts001turbo_decryption_table[256] = { + 0x90,0x05,0x57,0x5f,0xfe,0x4f,0xbd,0x36, 0x80,0x8b,0x8a,0x0a,0x89,0x90,0x47,0x80, /* 00 */ + 0x22,0x90,0x90,0x5d,0x81,0x3c,0xb5,0x83, 0x68,0xff,0x75,0x75,0x8d,0x5b,0x8a,0x38, /* 10 */ + 0x8b,0xeb,0xd2,0x0a,0xb4,0xc7,0x46,0xd1, 0x0a,0x53,0xbd,0x90,0x22,0xff,0x1f,0x03, /* 20 */ + 0xfb,0x45,0xc3,0x02,0x90,0x0f,0x90,0x02, 0x0f,0xb7,0x90,0x24,0xc6,0xeb,0x1b,0x32, /* 30 */ + 0x8d,0xb9,0xfe,0x08,0x88,0x90,0x8a,0x8a, 0x75,0x8a,0xbd,0x58,0xfe,0x51,0x1e,0x8b, /* 40 */ + 0x0f,0x22,0xf6,0x90,0xc3,0x36,0x03,0x8d, 0xbb,0x16,0xbc,0x90,0x0f,0x5e,0xf9,0x2e, /* 50 */ + 0x90,0x90,0x59,0x90,0xbb,0x1a,0x0c,0x8d, 0x89,0x72,0x83,0xa4,0xc3,0xb3,0x8b,0xe9, /* 60 */ + 0x81,0x43,0xa0,0x2c,0x0f,0x55,0xf3,0x36, 0xb0,0x59,0xe8,0x03,0x26,0xe9,0x22,0xb0, /* 70 */ + 0x90,0x8e,0x24,0x8a,0xd0,0x3e,0xc3,0x3a, 0x90,0x79,0x57,0x16,0x88,0x86,0x24,0x74, /* 80 */ + 0x33,0xc3,0x53,0xb8,0xab,0x75,0x90,0x90, 0x8e,0xb1,0xe9,0x5d,0xf9,0x02,0x3c,0x90, /* 90 */ + 0x80,0xd3,0x89,0xe8,0x90,0x90,0x2a,0x74, 0x90,0x5f,0xf6,0x88,0x4f,0x56,0x8c,0x03, /* a0 */ + 0x47,0x90,0x88,0x90,0x03,0xfe,0x90,0xfc, 0x2a,0x90,0x33,0x07,0xb1,0x50,0x0f,0x3e, /* b0 */ + 0xbd,0x4d,0xf3,0xbf,0x59,0xd2,0xea,0xc6, 0x2a,0x74,0x72,0xe2,0x3e,0x2e,0x90,0x2e, /* c0 */ + 0x2e,0x73,0x88,0x72,0x45,0x5d,0xc1,0xb9, 0x32,0x38,0x88,0xc1,0xa0,0x06,0x45,0x90, /* d0 */ + 0x90,0x86,0x4b,0x87,0x90,0x8a,0x3b,0xab, 0x33,0xbe,0x90,0x32,0xbd,0xc7,0xb2,0x80, /* e0 */ + 0x0f,0x75,0xc0,0xb9,0x07,0x74,0x3e,0xa2, 0x8a,0x48,0x3e,0x8d,0xeb,0x90,0xfe,0x90, /* f0 */ +}; + +static INT32 DrvInit(INT32 region) +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x400000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x103FFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekMapMemory(ExtraTRAM, 0x500000, 0x501FFF, SM_RAM); + SekMapMemory(ExtraTSelect, 0x502000, 0x502FFF, SM_RAM); // 0x502000 - Scroll; 0x502200 - RAM + SekMapMemory(ExtraTScroll, 0x503000, 0x503FFF, SM_RAM); // 0x203000 - Offset; 0x503200 - RAM + SekSetReadWordHandler(0, fixeightReadWord); + SekSetReadByteHandler(0, fixeightReadByte); + SekSetWriteWordHandler(0, fixeightWriteWord); + SekSetWriteByteHandler(0, fixeightWriteByte); + SekClose(); + + VezInit(0, V25_TYPE, 16000000 /*before divider*/); + VezOpen(0); + for (INT32 i = 0x80000; i < 0x100000; i += 0x8000) { + VezMapArea(i, i + 0x7fff, 0, ShareRAM); + VezMapArea(i, i + 0x7fff, 1, ShareRAM); + VezMapArea(i, i + 0x7fff, 2, ShareRAM); + } + VezSetReadHandler(fixeight_v25_read); + VezSetWriteHandler(fixeight_v25_write); + VezSetReadPort(fixeight_v25_read_port); + VezSetWritePort(fixeight_v25_write_port); + VezSetDecode(ts001turbo_decryption_table); + VezClose(); + } + + EEPROMInit(&eeprom_interface_93C46); + + set_region = region; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + nSpriteYOffset = 0x0001; + ToaInitGP9001(); + + ToaExtraTextInit(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + BurnYM2151Init(27000000 / 8, 50.0); + MSM6295Init(0, 1000000 / 132, 50.0, 1); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + + +// FixEight (Europe) + +static struct BurnRomInfo fixeightRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeight.nv", 0x000080, 0x02e925d0, BRF_PRG | BRF_ESS }, // 5 EEPROM +}; + +STD_ROM_PICK(fixeight) +STD_ROM_FN(fixeight) + +static INT32 fixeightInit() { return DrvInit(0x00); } + +struct BurnDriver BurnDrvFixeight = { + "fixeight", NULL, NULL, NULL, "1992", + "FixEight (Europe)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightRomInfo, fixeightRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Korea, Taito license) + +static struct BurnRomInfo fixeightktRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightkt.nv", 0x000080, 0x08fa73ba, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightkt) +STD_ROM_FN(fixeightkt) + +static INT32 fixeightktInit() { return DrvInit(0x00); } + +struct BurnDriver BurnDrvFixeightkt = { + "fixeightkt", "fixeight", NULL, NULL, "1992", + "FixEight (Korea, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightktRomInfo, fixeightktRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightktInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Korea) + +static struct BurnRomInfo fixeightkRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightk.nv", 0x000080, 0xcac91c6f, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightk) +STD_ROM_FN(fixeightk) + +static INT32 fixeightkInit() { return DrvInit(0x01); } + +struct BurnDriver BurnDrvFixeightk = { + "fixeightk", "fixeight", NULL, NULL, "1992", + "FixEight (Korea)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightkRomInfo, fixeightkRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightkInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Hong Kong, Taito license) + +static struct BurnRomInfo fixeighthtRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightht.nv", 0x000080, 0x57edaa51, BRF_PRG | BRF_ESS }, // 5 EEPROM +}; + +STD_ROM_PICK(fixeightht) +STD_ROM_FN(fixeightht) + +static INT32 fixeighthtInit() { return DrvInit(0x02); } + +struct BurnDriver BurnDrvFixeightht = { + "fixeightht", "fixeight", NULL, NULL, "1992", + "FixEight (Hong Kong, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeighthtRomInfo, fixeighthtRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeighthtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Hong Kong) + +static struct BurnRomInfo fixeighthRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeighth.nv", 0x000080, 0x95dec584, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeighth) +STD_ROM_FN(fixeighth) + +static INT32 fixeighthInit() { return DrvInit(0x03); } + +struct BurnDriver BurnDrvFixeighth = { + "fixeighth", "fixeight", NULL, NULL, "1992", + "FixEight (Hong Kong)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeighthRomInfo, fixeighthRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeighthInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Taiwan, Taito license) + +static struct BurnRomInfo fixeighttwtRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeighttwt.nv", 0x000080, 0xb6d5c06c, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeighttwt) +STD_ROM_FN(fixeighttwt) + +static INT32 fixeighttwtInit() { return DrvInit(0x04); } + +struct BurnDriver BurnDrvFixeighttwt = { + "fixeighttwt", "fixeight", NULL, NULL, "1992", + "FixEight (Taiwan, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeighttwtRomInfo, fixeighttwtRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeighttwtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Taiwan) + +static struct BurnRomInfo fixeighttwRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeighttw.nv", 0x000080, 0x74e6afb9, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeighttw) +STD_ROM_FN(fixeighttw) + +static INT32 fixeighttwInit() { return DrvInit(0x05); } + +struct BurnDriver BurnDrvFixeighttw = { + "fixeighttw", "fixeight", NULL, NULL, "1992", + "FixEight (Taiwan)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeighttwRomInfo, fixeighttwRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeighttwInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + + +// FixEight (Southeast Asia, Taito license) + +static struct BurnRomInfo fixeightatRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightat.nv", 0x000080, 0xe9c21987, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightat) +STD_ROM_FN(fixeightat) + +static INT32 fixeightatInit() { return DrvInit(0x06); } + +struct BurnDriver BurnDrvFixeightat = { + "fixeightat", "fixeight", NULL, NULL, "1992", + "FixEight (Southeast Asia, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightatRomInfo, fixeightatRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightatInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Southeast Asia) + +static struct BurnRomInfo fixeightaRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeighta.nv", 0x000080, 0x2bf17652, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeighta) +STD_ROM_FN(fixeighta) + +static INT32 fixeightaInit() { return DrvInit(0x07); } + +struct BurnDriver BurnDrvFixeighta = { + "fixeighta", "fixeight", NULL, NULL, "1992", + "FixEight (Southeast Asia)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightaRomInfo, fixeightaRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Europe, Taito license) + +static struct BurnRomInfo fixeighttRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightt.nv", 0x000080, 0xc0da4a05, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightt) +STD_ROM_FN(fixeightt) + +static INT32 fixeighttInit() { return DrvInit(0x08); } + +struct BurnDriver BurnDrvFixeightt = { + "fixeightt", "fixeight", NULL, NULL, "1992", + "FixEight (Europe, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeighttRomInfo, fixeighttRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeighttInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (USA, Taito license) + +static struct BurnRomInfo fixeightutRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightut.nv", 0x000080, 0x9fcd93ee, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightut) +STD_ROM_FN(fixeightut) + +static INT32 fixeightutInit() { return DrvInit(0x0a); } + +struct BurnDriver BurnDrvFixeightut = { + "fixeightut", "fixeight", NULL, NULL, "1992", + "FixEight (USA, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightutRomInfo, fixeightutRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightutInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (USA) + +static struct BurnRomInfo fixeightuRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightu.nv", 0x000080, 0x5dfefc3b, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightu) +STD_ROM_FN(fixeightu) + +static INT32 fixeightuInit() { return DrvInit(0x0b); } + +struct BurnDriver BurnDrvFixeightu = { + "fixeightu", "fixeight", NULL, NULL, "1992", + "FixEight (USA)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightuRomInfo, fixeightuRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightuInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Japan, Taito license) + +static struct BurnRomInfo fixeightjtRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightjt.nv", 0x000080, 0xe3d14fed, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightjt) +STD_ROM_FN(fixeightjt) + +static INT32 fixeightjtInit() { return DrvInit(0x0e); } + +struct BurnDriver BurnDrvFixeightjt = { + "fixeightjt", "fixeight", NULL, NULL, "1992", + "FixEight (Japan, Taito license)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightjtRomInfo, fixeightjtRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightjtInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// FixEight (Japan) + +static struct BurnRomInfo fixeightjRomDesc[] = { + { "tp-026-1", 0x080000, 0xf7b1746a, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + + { "tp-026-3", 0x200000, 0xe5578d98, BRF_GRA }, // 1 GP9001 Tile data + { "tp-026-4", 0x200000, 0xb760cb53, BRF_GRA }, // 2 + + { "tp-026-2", 0x040000, 0x85063f1f, BRF_SND }, // 3 MSM6295 ADPCM data + + { "93c45.u21", 0x000080, 0x40d75df0, BRF_PRG | BRF_ESS }, // 4 EEPROM (dumped) + { "fixeightj.nv", 0x000080, 0x21e22038, BRF_PRG | BRF_ESS }, // 5 +}; + +STD_ROM_PICK(fixeightj) +STD_ROM_FN(fixeightj) + +static INT32 fixeightjInit() { return DrvInit(0x0f); } + +struct BurnDriver BurnDrvFixeightj = { + "fixeightj", "fixeight", NULL, NULL, "1992", + "FixEight (Japan)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 3, HARDWARE_TOAPLAN_68K_Zx80, GBF_SHOOT, 0, + NULL, fixeightjRomInfo, fixeightjRomName, NULL, NULL, FixeightInputInfo, FixeightDIPInfo, + fixeightjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + diff --git a/src/burn/drivers/toaplan/d_ghox.cpp b/src/burn/drivers/toaplan/d_ghox.cpp new file mode 100644 index 00000000..d17adef8 --- /dev/null +++ b/src/burn/drivers/toaplan/d_ghox.cpp @@ -0,0 +1,607 @@ +#include "toaplan.h" + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0, 0, 0, 0, 0, 0}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM; + +static INT8 Paddle[2]; +static INT8 PaddleOld[2]; + +static INT32 nColCount = 0x0800; + +static struct BurnInputInfo GhoxInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 0, "service"}, + {"Tilt", BIT_DIGITAL, DrvButton + 1, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(Ghox) + +static struct BurnDIPInfo GhoxDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0xf2, NULL }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x13, 0x01, 0x01, 0x00, "Off" }, + {0x13, 0x01, 0x01, 0x01, "On" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x13, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + {0x14, 0x01, 0x0c, 0x08, "100k only" }, + {0x14, 0x01, 0x0c, 0x04, "100k and 300k" }, + {0x14, 0x01, 0x0c, 0x00, "100k and every 200k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 4, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Unused" }, + {0x14, 0x01, 0x80, 0x00, "Off" }, + {0x14, 0x01, 0x80, 0x80, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x0f, 0x02, "Europe" }, + {0x15, 0x01, 0x0f, 0x0a, "Europe (Nova Apparate GMBH & Co)" }, + {0x15, 0x01, 0x0f, 0x0d, "Europe (Taito Corporation Japan)" }, + {0x15, 0x01, 0x0f, 0x01, "USA" }, + {0x15, 0x01, 0x0f, 0x09, "USA (Romstar)" }, + {0x15, 0x01, 0x0f, 0x0b, "USA (Taito America Corporation)" }, + {0x15, 0x01, 0x0f, 0x0c, "USA (Taito Corporation Japan)" }, + {0x15, 0x01, 0x0f, 0x00, "Japan" }, + {0x15, 0x01, 0x0f, 0x04, "Korea" }, + {0x15, 0x01, 0x0f, 0x03, "Hong Kong (Honest Trading Co.)" }, + {0x15, 0x01, 0x0f, 0x05, "Taiwan" }, + {0x15, 0x01, 0x0f, 0x06, "Spain & Portugal (APM Electronics SA)" }, + {0x15, 0x01, 0x0f, 0x07, "Italy (Star Electronica SRL)" }, + {0x15, 0x01, 0x0f, 0x08, "UK (JP Leisure Ltd)" }, +}; + +STDDIPINFO(Ghox) + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // 68000 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + ShareRAM = Next; Next += 0x001000; + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x008000; // Double size, as the game tests too much memory during POST + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 2, 2, nGP9001ROMSize[0]); + + return 0; +} + +UINT8 PaddleRead(UINT8 Num) +{ + INT8 Value; + + if (Paddle[Num] == PaddleOld[Num]) return 0; + + Value = Paddle[Num] - PaddleOld[Num]; + PaddleOld[Num] = Paddle[Num]; + return Value; +} + +UINT8 __fastcall ghoxReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x18000d: // Player 1 inputs + return DrvInput[0]; + case 0x18000f: // Player 2 inputs + return DrvInput[1]; + case 0x180011: // Other inputs + return DrvInput[2]; + + case 0x180007: // Dipswitch 1 + return DrvInput[3]; + case 0x180009: // Dipswitch 2 + return DrvInput[4]; + case 0x18100d: // Dipswitch 3 - Territory + return DrvInput[5]&0x0f; + + case 0x14000D: // VBlank + return ToaVBlankRegister(); + + case 0x040000: + case 0x040001: + return PaddleRead(1); + + case 0x100000: + case 0x100001: + return PaddleRead(0); + + case 0x180000: + case 0x180001: + return 0xff; + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + if ((sekAddress & 0xfff000) == 0x180000) { + return ShareRAM[(sekAddress >> 1) & 0x7ff]; + } + + return 0; +} + +UINT16 __fastcall ghoxReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x18000c: // Player 1 inputs + return DrvInput[0]; + case 0x18000e: // Player 2 inputs + return DrvInput[1]; + case 0x180010: // Other inputs + return DrvInput[2]; + + case 0x180006: // Dipswitch 1 + return DrvInput[3]; + case 0x180008: // Dipswitch 2 + return DrvInput[4]; + case 0x18100c: // Dipswitch 3 - Territory + return DrvInput[5]&0x0f; + + case 0x140004: + return ToaGP9001ReadRAM_Hi(0); + case 0x140006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x14000C: + return ToaVBlankRegister(); + + case 0x040000: + return PaddleRead(1); + + case 0x100000: + return PaddleRead(0); + + case 0x180000: + case 0x180001: + return 0xffff; + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + if ((sekAddress & 0xfff000) == 0x180000) { + return ShareRAM[(sekAddress >> 1) & 0x7ff]; + } + + return 0; +} + +static void ghox_mcu_write(INT32 data) +{ + if ((data >= 0xd0) && (data < 0xe0)) + { + INT32 offset = ((data & 0x0f) * 2) + (0x38 / 2); + ShareRAM[(0x500 / 2) + offset ] = 0x05; // Return address for + ShareRAM[(0x500 / 2) + offset-1] = 0x56; // RTS instruction + } + if (data == 0xd3) { + static const UINT8 prot_data[0x10] = { + 0x3a, 0x01, 0x08, 0x85, 0x00, 0x00, 0xcb, 0xfc, + 0x00, 0x03, 0x90, 0x45, 0xe5, 0x09, 0x4e, 0x75 + }; + + memcpy (ShareRAM + (0x556 / 2), prot_data, 0x10); + } else { + ShareRAM[0x556 / 2] = 0x4e; // Return an RTS instruction + ShareRAM[0x558 / 2] = 0x75; + } +} + +void __fastcall ghoxWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x180001: + ghox_mcu_write(byteValue); + break; + + // default: + // printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + + if ((sekAddress & 0xfff000) == 0x180000) { + ShareRAM[(sekAddress >> 1) & 0x7ff] = byteValue; + return; + } +} + +void __fastcall ghoxWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x140000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x140004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x140006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x140008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x14000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x180000: + ghox_mcu_write(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } + + if ((sekAddress & 0xfff000) == 0x180000) { + ShareRAM[(sekAddress >> 1) & 0x7ff] = wordValue; + return; + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + Paddle[0] = 0; + PaddleOld[0] = 0; + Paddle[1] = 0; + PaddleOld[1] = 0; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nGP9001ROMSize[0] = 0x100000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x080000, 0x083FFF, SM_RAM); + SekMapMemory(RamPal, 0x0c0000, 0x0c0FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, ghoxReadWord); + SekSetReadByteHandler(0, ghoxReadByte); + SekSetWriteWordHandler(0, ghoxWriteWord); + SekSetWriteByteHandler(0, ghoxWriteByte); + SekClose(); + } + + nToa1Cycles68KSync = SekTotalCycles(); + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInput, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + if (DrvJoy1[2]) Paddle[0] -= 0x04; + if (DrvJoy1[3]) Paddle[0] += 0x04; + if (DrvJoy2[2]) Paddle[1] -= 0x04; + if (DrvJoy2[3]) Paddle[1] += 0x04; + + SekNewFrame(); + + SekOpen(0); + + SekIdle(nCyclesDone[0]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + ToaBufferGP9001Sprites(); + + bVBlank = true; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + +// ToaBufferFCU2Sprites(); + + SekClose(); + + return 0; +} + + +// Ghox (spinner) + +static struct BurnRomInfo ghoxRomDesc[] = { + { "tp021-01.u10", 0x20000, 0x9e56ac67, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "tp021-02.u11", 0x20000, 0x15cac60f, BRF_PRG | BRF_ESS }, // 1 + + { "tp021-03.u36", 0x80000, 0xa15d8e9d, BRF_GRA }, // 2 GP9001 Tile data + { "tp021-04.u37", 0x80000, 0x26ed1c9a, BRF_GRA }, // 3 + + { "hd647180.021", 0x08000, 0x00000000, BRF_NODUMP }, // 4 CPU #1 code +}; + +STD_ROM_PICK(ghox) +STD_ROM_FN(ghox) + +struct BurnDriver BurnDrvGhox = { + "ghox", NULL, NULL, NULL, "1991", + "Ghox (spinner)\0", "No Sound (undumped MCU)", "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_BREAKOUT, 0, + NULL, ghoxRomInfo, ghoxRomName, NULL, NULL, GhoxInputInfo, GhoxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Ghox (joystick) + +static struct BurnRomInfo ghoxjRomDesc[] = { + { "tp021-01a.u10", 0x20000, 0xc11b13c8, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "tp021-02a.u11", 0x20000, 0x8d426767, BRF_PRG | BRF_ESS }, // 1 + + { "tp021-03.u36", 0x80000, 0xa15d8e9d, BRF_GRA }, // 2 GP9001 Tile data + { "tp021-04.u37", 0x80000, 0x26ed1c9a, BRF_GRA }, // 3 + + { "hd647180.021", 0x08000, 0x00000000, BRF_NODUMP }, // 4 CPU #1 code +}; + +STD_ROM_PICK(ghoxj) +STD_ROM_FN(ghoxj) + +struct BurnDriver BurnDrvGhoxj = { + "ghoxj", "ghox", NULL, NULL, "1991", + "Ghox (joystick)\0", "No Sound (undumped MCU)", "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_BREAKOUT, 0, + NULL, ghoxjRomInfo, ghoxjRomName, NULL, NULL, GhoxInputInfo, GhoxDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_hellfire.cpp b/src/burn/drivers/toaplan/d_hellfire.cpp new file mode 100644 index 00000000..2a44d347 --- /dev/null +++ b/src/burn/drivers/toaplan/d_hellfire.cpp @@ -0,0 +1,828 @@ +// Hell Fire + +#include "toaplan.h" + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +// Rom information +static struct BurnRomInfo hellfireRomDesc[] = { + { "b90_14.0", 0x020000, 0x101df9f5, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b90_15.1", 0x020000, 0xe67fd452, BRF_ESS | BRF_PRG }, // 1 + + { "b90_04.3", 0x020000, 0xea6150fc, BRF_GRA }, // 6 + { "b90_05.4", 0x020000, 0xbb52c507, BRF_GRA }, // 7 + { "b90_06.5", 0x020000, 0xcf5b0252, BRF_GRA }, // 8 + { "b90_07.6", 0x020000, 0xb98af263, BRF_GRA }, // 9 + + { "b90_11.10", 0x020000, 0xc33e543c, BRF_GRA }, // 2 + { "b90_10.9", 0x020000, 0x35fd1092, BRF_GRA }, // 3 + { "b90_09.8", 0x020000, 0xcf01009e, BRF_GRA }, // 4 + { "b90_08.7", 0x020000, 0x3404a5e3, BRF_GRA }, // 5 + + { "b90_03.2", 0x008000, 0x4058fa67, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "13.3w", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "12.6b", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + +STD_ROM_PICK(hellfire) +STD_ROM_FN(hellfire) + +static struct BurnRomInfo hellfir1RomDesc[] = { + { "b90_14x.0", 0x020000, 0xa3141ea5, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b90_15x.1", 0x020000, 0xe864daf4, BRF_ESS | BRF_PRG }, // 1 + + { "b90_04.3", 0x020000, 0xea6150fc, BRF_GRA }, // 6 + { "b90_05.4", 0x020000, 0xbb52c507, BRF_GRA }, // 7 + { "b90_06.5", 0x020000, 0xcf5b0252, BRF_GRA }, // 8 + { "b90_07.6", 0x020000, 0xb98af263, BRF_GRA }, // 9 + + { "b90_11.10", 0x020000, 0xc33e543c, BRF_GRA }, // 2 + { "b90_10.9", 0x020000, 0x35fd1092, BRF_GRA }, // 3 + { "b90_09.8", 0x020000, 0xcf01009e, BRF_GRA }, // 4 + { "b90_08.7", 0x020000, 0x3404a5e3, BRF_GRA }, // 5 + + { "b90_03x.2", 0x008000, 0xf58c368f, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "13.3w", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "12.6b", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + +STD_ROM_PICK(hellfir1) +STD_ROM_FN(hellfir1) + +static struct BurnRomInfo hellfir2RomDesc[] = { + { "b90_01.0", 0x020000, 0xc94acf53, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b90_02.1", 0x020000, 0xd17f03c3, BRF_ESS | BRF_PRG }, // 1 + + { "b90_04.3", 0x020000, 0xea6150fc, BRF_GRA }, // 6 + { "b90_05.4", 0x020000, 0xbb52c507, BRF_GRA }, // 7 + { "b90_06.5", 0x020000, 0xcf5b0252, BRF_GRA }, // 8 + { "b90_07.6", 0x020000, 0xb98af263, BRF_GRA }, // 9 + + { "b90_11.10", 0x020000, 0xc33e543c, BRF_GRA }, // 2 + { "b90_10.9", 0x020000, 0x35fd1092, BRF_GRA }, // 3 + { "b90_09.8", 0x020000, 0xcf01009e, BRF_GRA }, // 4 + { "b90_08.7", 0x020000, 0x3404a5e3, BRF_GRA }, // 5 + + { "b90_03x.2", 0x008000, 0xf58c368f, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "13.3w", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "12.6b", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + +STD_ROM_PICK(hellfir2) +STD_ROM_FN(hellfir2) + +static struct BurnRomInfo hellfir3RomDesc[] = { + { "b90_01.10m", 0x020000, 0x034966d3, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b90_02.9m", 0x020000, 0x06dd24c7, BRF_ESS | BRF_PRG }, // 1 + + { "b90_04.3", 0x020000, 0xea6150fc, BRF_GRA }, // 6 + { "b90_05.4", 0x020000, 0xbb52c507, BRF_GRA }, // 7 + { "b90_06.5", 0x020000, 0xcf5b0252, BRF_GRA }, // 8 + { "b90_07.6", 0x020000, 0xb98af263, BRF_GRA }, // 9 + + { "b90_11.10", 0x020000, 0xc33e543c, BRF_GRA }, // 2 + { "b90_10.9", 0x020000, 0x35fd1092, BRF_GRA }, // 3 + { "b90_09.8", 0x020000, 0xcf01009e, BRF_GRA }, // 4 + { "b90_08.7", 0x020000, 0x3404a5e3, BRF_GRA }, // 5 + + { "b90_03.2", 0x008000, 0x4058fa67, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "13.3w", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "12.6b", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + +STD_ROM_PICK(hellfir3) +STD_ROM_FN(hellfir3) + +static struct BurnInputInfo hellfireInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(hellfire) + +static struct BurnDIPInfo hellfireDIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x00, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal screen"}, + {0x12, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x04, 0x00, "Normal mode"}, + {0x12, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x12, 0x01, 0x08, 0x00, "On"}, + {0x12, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x12, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x12, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x13, 0x01, 0x03, 0x00, "B"}, + {0x13, 0x01, 0x03, 0x01, "A"}, + {0x13, 0x01, 0x03, 0x02, "C"}, + {0x13, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x13, 0x01, 0x0C, 0x00, "70000, every 200000"}, + {0x13, 0x01, 0x0C, 0x04, "100000, every 250000"}, + {0x13, 0x01, 0x0C, 0x08, "100000 only"}, + {0x13, 0x01, 0x0C, 0x0C, "200000 only"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x13, 0x01, 0x30, 0x30, "2"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x20, "4"}, + {0x13, 0x01, 0x30, 0x10, "5"}, + {0, 0xFE, 0, 2, NULL}, + {0x13, 0x01, 0x40, 0x00, "Normal Game"}, + {0x13, 0x01, 0x40, 0x40, "No death & stop mode"}, + + // Region + {0, 0xFE, 0, 3, "Region"}, + {0x14, 0x01, 0x03, 0x00, "Japan"}, + {0x14, 0x01, 0x03, 0x01, "US"}, + {0x14, 0x01, 0x03, 0x02, "Europe"}, +}; + +STDDIPINFO(hellfire) + +static struct BurnDIPInfo hellfir1DIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x01, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal screen"}, + {0x12, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x04, 0x00, "Normal mode"}, + {0x12, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x12, 0x01, 0x08, 0x00, "On"}, + {0x12, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x12, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x12, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x13, 0x01, 0x03, 0x00, "B"}, + {0x13, 0x01, 0x03, 0x01, "A"}, + {0x13, 0x01, 0x03, 0x02, "C"}, + {0x13, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x13, 0x01, 0x0C, 0x00, "70000, every 200000"}, + {0x13, 0x01, 0x0C, 0x04, "100000, every 250000"}, + {0x13, 0x01, 0x0C, 0x08, "100000 only"}, + {0x13, 0x01, 0x0C, 0x0C, "200000 only"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x13, 0x01, 0x30, 0x30, "2"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x20, "4"}, + {0x13, 0x01, 0x30, 0x10, "5"}, + {0, 0xFE, 0, 2, NULL}, + {0x13, 0x01, 0x40, 0x00, "Normal Game"}, + {0x13, 0x01, 0x40, 0x40, "No death & stop mode"}, + {0, 0xFE, 0, 2, "Allow Continue"}, + {0x13, 0x01, 0x80, 0x00, "Yes"}, + {0x13, 0x01, 0x80, 0x80, "No"}, + + // Region + {0, 0xFE, 0, 3, "Region"}, + {0x14, 0x01, 0x03, 0x00, "Japan"}, + {0x14, 0x01, 0x03, 0x01, "US"}, + {0x14, 0x01, 0x03, 0x02, "Europe"}, +}; + +STDDIPINFO(hellfir1) + +static INT32 __fastcall DrvResetCallback() +{ + // Reset instruction on 68000 + + ZetReset(); // Reset Z80 (CPU #1) + BurnYM3812Reset(); + return 0; +} + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal, *RamPal2; + +static INT32 nColCount = 0x0400; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // + RomZ80 = Next; Next += 0x008000; // Z80 ROM + BCU2ROM = Next; Next += nBCU2ROMSize; // BCU-2 tile data + FCU2ROM = Next; Next += nFCU2ROMSize; // FCU-2 tile data + RamStart = Next; + Ram01 = Next; Next += 0x008000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + RamPal2 = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x008000; // Z80 RAM + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029402; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nCyclesDone); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load BCU-2 tile data + ToaLoadTiles(BCU2ROM, 2, nBCU2ROMSize); + + // Load FCU-2 tile data + ToaLoadTiles(FCU2ROM, 6, nFCU2ROMSize); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 10, 1); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall hellfireZ80In(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x70: + return BurnYM3812Read(0); + case 0x00: // DIP A + return DrvInput[2]; + case 0x10: // DIP B + return DrvInput[3]; + case 0x60: // Sysytem inputs + return DrvInput[4] | (ToaVBlankRegister() << 7); + case 0x40: // Player 1 + return DrvInput[0]; + case 0x50: // Player 2 + return DrvInput[1]; + case 0x20: // Region + return DrvInput[5]; + + } + +// bprintf(PRINT_NORMAL, _T("z80 read %4X\n"), nAddress); + + return 0; +} + +void __fastcall hellfireZ80Out(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x70: + BurnYM3812Write(0, nValue); + break; + case 0x71: + BurnYM3812Write(1, nValue); + break; + + case 0x30: // Coin counter + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 attempted to write address %04X with value %02X.\n"), nAddress, nValue); + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(hellfireZ80In); + ZetSetOutHandler(hellfireZ80Out); + + // ROM + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0x8000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0x8000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0x8000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall hellfireReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x080001: + case 0x140001: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Byte %06X.\n"), sekAddress); + } + } + + return 0; +} + +UINT16 __fastcall hellfireReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x140002: + return ToaFCU2GetRAMPointer(); + case 0x140004: + return ToaFCU2ReadRAM(); + case 0x140006: + return ToaFCU2ReadRAMSize(); + + case 0x100002: + return ToaBCU2GetRAMPointer(); + case 0x100004: + return ToaBCU2ReadRAM_Hi(); + case 0x100006: + return ToaBCU2ReadRAM_Lo(); + + case 0x100010: + case 0x100011: + case 0x100012: + case 0x100013: + case 0x100014: + case 0x100015: + case 0x100016: + case 0x100017: + case 0x100018: + case 0x100019: + case 0x10001A: + case 0x10001B: + case 0x10001C: + case 0x10001D: + case 0x10001E: + case 0x10001F: + return BCU2Reg[(sekAddress & 15) >> 1]; + + case 0x080000: + case 0x140000: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Word %06X.\n"), sekAddress); + } + } + + return 0; +} + +void __fastcall hellfireWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x080003: + bEnableInterrupts = byteValue; + break; + + case 0x140006: + ToaFCU2WriteRAMSize(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write byte %06X, %02X.\n"), sekAddress, byteValue); + } + } +} + +void __fastcall hellfireWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x140002: // FCU-2 set VRAM address-pointer + ToaFCU2SetRAMPointer(wordValue); + break; + case 0x140004: + ToaFCU2WriteRAM(wordValue); + break; + case 0x140006: + ToaFCU2WriteRAMSize(wordValue); + break; + + case 0x100000: // BCU-2 flip + break; + case 0x100002: // BCU-2 set VRAM address-pointer + ToaBCU2SetRAMPointer(wordValue); + break; + case 0x100004: + ToaBCU2WriteRAM(wordValue); + break; + case 0x100006: + ToaBCU2WriteRAM(wordValue); + break; + + case 0x100010: + case 0x100011: + case 0x100012: + case 0x100013: + case 0x100014: + case 0x100015: + case 0x100016: + case 0x100017: + case 0x100018: + case 0x100019: + case 0x10001A: + case 0x10001B: + case 0x10001C: + case 0x10001D: + case 0x10001E: + case 0x10001F: + BCU2Reg[(sekAddress & 15) >> 1] = wordValue; + break; + + case 0x080002: + bEnableInterrupts = (wordValue & 0xFF); + break; + + case 0x180000: + nBCU2TileXOffset = wordValue; + break; + case 0x180002: + nBCU2TileYOffset = wordValue; + break; + + case 0x180006: // FCU-2 flip + break; + + case 0x180008: + if (wordValue == 0) DrvResetCallback(); + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write word %06X, %04X.\n"), sekAddress, wordValue); + } + } +} + +// ---------------------------------------------------------------------------- + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Hellfire = 1; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // 68K ROM + SekMapMemory(Ram01, 0x040000, 0x047FFF, SM_RAM); // 68K RAM + SekMapMemory(RamPal, 0x084000, 0x0847FF, SM_RAM); // BCU-2 palette RAM + SekMapMemory(RamPal2, 0x086000, 0x0867FF, SM_RAM); // FCU-2 palette RAM + + SekSetReadWordHandler(0, hellfireReadWord); + SekSetReadByteHandler(0, hellfireReadByte); + SekSetWriteWordHandler(0, hellfireWriteWord); + SekSetWriteByteHandler(0, hellfireWriteByte); + + SekMapHandler(1, 0x0c0000, 0x0c0FFF, SM_RAM); // Z80 RAM + + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + + SekClose(); + } + + ToaInitBCU2(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalSrc2 = RamPal2; + ToaPalInit(); + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + Hellfire = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); +// BurnClearScreen(); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); // Render BCU2 graphics + } + + ToaPalUpdate(); // Update the palette + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[4] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[4] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { // See if this CPU is busywaiting + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + ZetClose(); + SekClose(); + +// ToaBufferFCU2Sprites(); + + return 0; +} + +struct BurnDriver BurnDrvHellfire = { + "hellfire", NULL, NULL, NULL, "1989", + "Hellfire (2P Ver.)\0", NULL, "Toaplan (Taito License)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, hellfireRomInfo, hellfireRomName, NULL, NULL, hellfireInputInfo, hellfireDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHellfir1 = { + "hellfire1", "hellfire", NULL, NULL, "1989", + "Hellfire (1P Ver.)\0", NULL, "Toaplan (Taito License)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, hellfir1RomInfo, hellfir1RomName, NULL, NULL, hellfireInputInfo, hellfir1DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHellfir2 = { + "hellfire2", "hellfire", NULL, NULL, "1989", + "Hellfire (2P Ver., first edition)\0", NULL, "Toaplan (Taito License)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, hellfir2RomInfo, hellfir2RomName, NULL, NULL, hellfireInputInfo, hellfireDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvHellfir3 = { + "hellfire3", "hellfire", NULL, NULL, "1989", + "Hellfire (1P Ver., alt)\0", NULL, "Toaplan (Taito License)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, hellfir3RomInfo, hellfir3RomName, NULL, NULL, hellfireInputInfo, hellfireDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/d_kbash.cpp b/src/burn/drivers/toaplan/d_kbash.cpp new file mode 100644 index 00000000..6572facb --- /dev/null +++ b/src/burn/drivers/toaplan/d_kbash.cpp @@ -0,0 +1,614 @@ +#include "toaplan.h" +#include "vez.h" +// Knuckle Bash + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +// Rom information +static struct BurnRomInfo drvRomDesc[] = { + { "tp023_01.bin", 0x080000, 0x2965F81D, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp023_3.bin", 0x200000, 0x32AD508B, BRF_GRA }, // 1 GP9001 Tile data + { "tp023_5.bin", 0x200000, 0xB84C90EB, BRF_GRA }, // 2 + { "tp023_4.bin", 0x200000, 0xE493C077, BRF_GRA }, // 3 + { "tp023_6.bin", 0x200000, 0x9084B50A, BRF_GRA }, // 4 + + { "tp023_02.bin", 0x008000, 0x4CD882A1, BRF_ESS | BRF_PRG }, // 5 Sound CPU + { "tp023_7.bin", 0x040000, 0x3732318F, BRF_SND }, // 6 ADPCM data +}; + + +STD_ROM_PICK(drv) +STD_ROM_FN(drv) + +static struct BurnInputInfo kbashInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(kbash) + +static struct BurnDIPInfo kbashDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0x0F, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Discount off"}, + {0x14, 0x01, 0x01, 0x01, "Continue discount"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 plays"}, + {0x14, 0x01, 0x30, 0x20, "2 coins 1 play"}, + {0x14, 0x01, 0x30, 0x30, "2 coins 3 plays"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 plays"}, + {0x14, 0x01, 0xC0, 0x80, "2 coins 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "2 coins 3 plays"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x15, 0x01, 0x0C, 0x00, "100000, 400000"}, + {0x15, 0x01, 0x0C, 0x04, "100000 only"}, + {0x15, 0x01, 0x0C, 0x08, "200000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x15, 0x01, 0x30, 0x00, "2"}, + {0x15, 0x01, 0x30, 0x01, "5"}, + {0x15, 0x01, 0x30, 0x02, "4"}, + {0x15, 0x01, 0x30, 0x03, "2"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "no-death, stop mode"}, + {0, 0xFE, 0, 2, "Continue play"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, + + // DIP 3 + {0, 0xFE, 0, 7, "For"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "USA"}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Korea"}, + {0x16, 0x01, 0x0F, 0x04, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "Asia"}, + {0x16, 0x01, 0x0F, 0x07, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x08, "Japan"}, + {0x16, 0x01, 0x0F, 0x09, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x0A, "Europe"}, + {0x16, 0x01, 0x0F, 0x0B, "Korea"}, + {0x16, 0x01, 0x0F, 0x0C, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x0D, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x0E, "Asia"}, + {0x16, 0x01, 0x0F, 0x0F, ""}, +}; + +STDDIPINFO(kbash) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01, *Rom02; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68000 ROM + Rom02 = Next; Next += 0x008000; + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x040000; + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + ShareRAM = Next; Next += 0x001000; + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + VezScan(nAction); + BurnYM2151Scan(nAction); + MSM6295Scan(0, nAction); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 4, nGP9001ROMSize[0]); + + BurnLoadRom(Rom02, 5, 1); + BurnLoadRom(MSM6295ROM, 6, 1); + + return 0; +} + +UINT8 __fastcall kbashReadByte(UINT32 sekAddress) +{ + if ((sekAddress & 0xfff000) == 0x200000) { + return ShareRAM[(sekAddress / 2) & 0x07ff]; + } + + switch (sekAddress) { + case 0x208011: // Player 1 inputs + return DrvInput[0]; + case 0x208015: // Player 2 inputs + return DrvInput[1]; + case 0x208019: // Other inputs + return DrvInput[2]; + + case 0x30000D: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall kbashReadWord(UINT32 sekAddress) +{ + if ((sekAddress & 0xfff000) == 0x200000) { + return ShareRAM[(sekAddress / 2) & 0x07ff]; + } + + switch (sekAddress) { + + case 0x208010: // Player 1 inputs + return DrvInput[0]; + case 0x208014: // Player 2 inputs + return DrvInput[1]; + case 0x208018: // Other inputs + return DrvInput[2]; + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + case 0x700000: + return ToaScanlineRegister(); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall kbashWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + if ((sekAddress & 0xfff000) == 0x200000) { + ShareRAM[(sekAddress / 2) & 0x07ff] = byteValue; + return; + } + + switch (sekAddress) { + //case 0x20801c: + //case 0x20801d: + // break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall kbashWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if ((sekAddress & 0xfff000) == 0x200000) { + ShareRAM[(sekAddress / 2) & 0x07ff] = wordValue; + return; + } + + switch (sekAddress) { + + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +void __fastcall kbash_v25_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x04000: + BurnYM2151SelectRegister(data); + return; + + case 0x04001: + BurnYM2151WriteRegister(data); + return; + + case 0x04002: + MSM6295Command(0, data); + return; + } +} + +UINT8 __fastcall kbash_v25_read(UINT32 address) +{ + switch (address) + { + case 0x04001: + return BurnYM2151ReadStatus(); + + case 0x04002: + return MSM6295ReadStatus(0); + } + + return 0; +} + +UINT8 __fastcall kbash_v25_read_port(UINT32 port) +{ + switch (port) + { + case V25_PORT_PT: + return DrvInput[3]^0xff; + + case V25_PORT_P0: + return DrvInput[4]^0xff; + + case V25_PORT_P1: + return DrvInput[5]^0xff; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + VezOpen(0); + VezReset(); + VezClose(); + + BurnYM2151Reset(); + MSM6295Reset(0); + + return 0; +} + +static UINT8 nitro_decryption_table[256] = { + 0x1b,0x56,0x75,0x88,0x8c,0x06,0x58,0x72, 0x83,0x86,0x36,0x1a,0x5f,0xd3,0x8c,0xe9, /* 00 */ + 0x22,0x0f,0x03,0x2a,0xeb,0x2a,0xf9,0x0f, 0xa4,0xbd,0x75,0xf3,0x4f,0x53,0x8e,0xfe, /* 10 */ + 0x87,0xe8,0xb1,0x8d,0x36,0xb5,0x43,0x73, 0x2a,0x5b,0xf9,0x02,0x24,0x8a,0x03,0x80, /* 20 */ + 0x86,0x8b,0xd1,0x3e,0x8d,0x3e,0x58,0xfb, 0xc3,0x79,0xbd,0xb7,0x8a,0xe8,0x0f,0x81, /* 30 */ + 0xb7,0xd0,0x8b,0xeb,0xff,0xb8,0x90,0x8b, 0x5e,0xa2,0x90,0x90,0xab,0xb4,0x80,0x59, /* 40 */ + 0x87,0x72,0xb5,0xbd,0xb0,0x88,0x50,0x0f, 0xfe,0xd2,0xc3,0x90,0x8a,0x90,0xf9,0x75, /* 50 */ + 0x1a,0xb3,0x74,0x0a,0x68,0x24,0xbb,0x90, 0x75,0x47,0xfe,0x2c,0xbe,0xc3,0x88,0xd2, /* 60 */ + 0x3e,0xc1,0x8c,0x33,0x0f,0x90,0x8b,0x90, 0xb9,0x1e,0xff,0xa2,0x3e,0x22,0xbe,0x57, /* 70 */ + 0x81,0x3a,0xf6,0x88,0xeb,0xb1,0x89,0x8a, 0x32,0x80,0x0f,0xb1,0x48,0xc3,0x68,0x72, /* 80 */ + 0x53,0x02,0xc0,0x02,0xe8,0xb4,0x74,0xbc, 0x90,0x58,0x0a,0xf3,0x75,0xc6,0x90,0xe8, /* 90 */ + 0x26,0x50,0xfc,0x8c,0x90,0xb1,0xc3,0xd1, 0xeb,0x83,0xa4,0xbf,0x26,0x4b,0x46,0xfe, /* a0 */ + 0xe2,0x89,0xb3,0x88,0x03,0x56,0x0f,0x38, 0xbb,0x0c,0x90,0x0f,0x07,0x8a,0x8a,0x33, /* b0 */ + 0xfe,0xf9,0xb1,0xa0,0x45,0x36,0x22,0x5e, 0x8a,0xbe,0xc6,0xea,0x3c,0xb2,0x1e,0xe8, /* c0 */ + 0x90,0xeb,0x55,0xf6,0x8a,0xb0,0x5d,0xc0, 0xbb,0x8d,0xf6,0xd0,0xd1,0x88,0x4d,0x90, /* d0 */ + 0x51,0x51,0x74,0xbd,0x32,0xd1,0x90,0xd2, 0x53,0xc7,0xab,0x36,0x50,0xe9,0x33,0xb3, /* e0 */ + 0x2e,0x05,0x88,0x59,0x74,0x74,0x22,0x8e, 0x8a,0x8a,0x36,0x08,0x0f,0x45,0x90,0x2e, /* f0 */ +}; + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + nGP9001ROMSize[0] = 0x800000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x103FFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, kbashReadWord); + SekSetReadByteHandler(0, kbashReadByte); + SekSetWriteWordHandler(0, kbashWriteWord); + SekSetWriteByteHandler(0, kbashWriteByte); + SekClose(); + + VezInit(0, V25_TYPE, 16000000 /*before divider*/); + VezOpen(0); + VezMapArea(0x00000, 0x007ff, 0, ShareRAM); + VezMapArea(0x00000, 0x007ff, 1, ShareRAM); + VezMapArea(0x00000, 0x007ff, 2, ShareRAM); + for (INT32 i = 0x80000; i < 0x100000; i += 0x8000) { + VezMapArea(i, i + 0x7fff, 0, Rom02); + VezMapArea(i, i + 0x7fff, 1, Rom02); + VezMapArea(i, i + 0x7fff, 2, Rom02); + } + VezSetReadHandler(kbash_v25_read); + VezSetWriteHandler(kbash_v25_write); + VezSetReadPort(kbash_v25_read_port); + VezSetDecode(nitro_decryption_table); + VezClose(); + } + + BurnYM2151Init(3375000, 50.0); + MSM6295Init(0, 1000000 / 132, 50.0, 1); + + nSpriteYOffset = 0x0011; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + MSM6295Exit(0); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + VezExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + MSM6295ROM = NULL; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + VezNewFrame(); + + INT32 nSoundBufferPos = 0; + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)8000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + + // Trigger VBlank interrupt + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + nCyclesDone[1] += VezRun(nCyclesTotal[1] / nInterleave); + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + + VezClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvKBash = { + "kbash", NULL, NULL, NULL, "1993", + "Knuckle Bash\0", NULL, "Toaplan", "Toaplan GP9001 based", + L"Knuckle Bash\0Knuckle Bash \u30CA\u30C3\u30AF\u30EB\u30D0\u30C3\u30B7\u30E5\0", NULL, NULL, NULL, + 1, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_SCRFIGHT, 0, + NULL, drvRomInfo, drvRomName, NULL, NULL, kbashInputInfo,kbashDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + diff --git a/src/burn/drivers/toaplan/d_kbash2.cpp b/src/burn/drivers/toaplan/d_kbash2.cpp new file mode 100644 index 00000000..41b6218f --- /dev/null +++ b/src/burn/drivers/toaplan/d_kbash2.cpp @@ -0,0 +1,549 @@ +#include "toaplan.h" +// Knuckle Bash 2 + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 nPreviousOkiBank; + +static struct BurnRomInfo kbash2RomDesc[] = { + { "mecat-m", 0x080000, 0xbd2263c6, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "mecat-34", 0x400000, 0x6be7b37e, BRF_GRA }, // 1 GP9001 Tile data + { "mecat-12", 0x400000, 0x49e46b1f, BRF_GRA }, // 2 + + { "mecat-s", 0x080000, 0x3eb7adf4, BRF_SND }, // 3 oki1 + + { "eprom", 0x040000, 0x31115cb9, BRF_SND }, // 4 oki2 + + { "050917-10", 0x010000, 0x6b213183, BRF_OPT }, // 5 WTF is this? +}; + +STD_ROM_PICK(kbash2) +STD_ROM_FN(kbash2) + +static struct BurnInputInfo Kbash2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 0, "service"}, + {"Tilt", BIT_DIGITAL, DrvButton + 1, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(Kbash2) + +static struct BurnDIPInfo Kbash2DIPList[]= +{ + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x06, NULL }, + + {0 , 0xfe, 0 , 2, "Continue Mode" }, + {0x15, 0x01, 0x01, 0x00, "Normal" }, + {0x15, 0x01, 0x01, 0x01, "Discount" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x15, 0x01, 0x04, 0x00, "Off" }, + {0x15, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x15, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x15, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x15, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 1 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "2 Coins 3 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x00, "Medium" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x0c, "None" }, + {0x16, 0x01, 0x0c, 0x08, "200k only" }, + {0x16, 0x01, 0x0c, 0x04, "100k only" }, + {0x16, 0x01, 0x0c, 0x00, "100k and 400k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x30, "1" }, + {0x16, 0x01, 0x30, 0x00, "2" }, + {0x16, 0x01, 0x30, 0x20, "3" }, + {0x16, 0x01, 0x30, 0x10, "4" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "No" }, + {0x16, 0x01, 0x80, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 7, "Territory" }, + {0x17, 0x01, 0x0f, 0x00, "Japan (Taito Corp license)" }, + {0x17, 0x01, 0x0f, 0x0e, "South East Asia" }, + {0x17, 0x01, 0x0f, 0x06, "South East Asia (Charterfield license)" }, + {0x17, 0x01, 0x0f, 0x0b, "Korea" }, + {0x17, 0x01, 0x0f, 0x03, "Korea (Unite license)" }, + {0x17, 0x01, 0x0f, 0x04, "Hong Kong" }, + {0x17, 0x01, 0x0f, 0x05, "Taiwan" }, +}; + +STDDIPINFO(Kbash2) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *RomSnd; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // 68000 ROM + MSM6295ROM = Next; + RomSnd = Next; Next += 0x140000; + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(nPreviousOkiBank); + } + + if (nAction & ACB_WRITE) { + memcpy (RomSnd, RomSnd + 0x40000 + (nPreviousOkiBank * 0x40000), 0x40000); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]); + + if (BurnLoadRom(RomSnd + 0x040000, 3, 1)) return 1; + if (BurnLoadRom(RomSnd + 0x100000, 4, 1)) return 1; + + return 0; +} + +static void oki_set_bank(INT32 bank) +{ + bank &= 1; + if (nPreviousOkiBank != bank) { + nPreviousOkiBank = bank; + memcpy (RomSnd + 0x000000, RomSnd + 0x40000 + (bank * 0x40000), 0x40000); + } +} + +UINT8 __fastcall kbash2ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x200005: // Dipswitch 1 + return DrvInput[3]; + case 0x200009: // Dipswitch 2 + return DrvInput[4]; + case 0x20000d: // Dipswitch 3 - Territory + return DrvInput[5]; + + case 0x200011: // Player 1 Input + return DrvInput[0]; + case 0x200015: // Player 2 Input + return DrvInput[1]; + case 0x200019: // System... + return DrvInput[2]; + + case 0x200021: + return MSM6295ReadStatus(1); + + case 0x200025: + return MSM6295ReadStatus(0); + + case 0x20002D: + return ToaScanlineRegister(); + + case 0x30000d: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall kbash2ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x200004: // Dipswitch 1 + return DrvInput[3]; + case 0x200008: // Dipswitch 2 + return DrvInput[4]; + case 0x20000c: // Dipswitch 3 - Territory + return DrvInput[5]; + + case 0x200010: // Player 1 Input + return DrvInput[0]; + case 0x200014: // Player 2 Input + return DrvInput[1]; + case 0x200018: // System... + return DrvInput[2]; + + case 0x200020: + return MSM6295ReadStatus(1); + + case 0x200024: + return MSM6295ReadStatus(0); + + case 0x20002c: + return ToaScanlineRegister(); + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall kbash2WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x200021: + MSM6295Command(1, byteValue); + return; + + case 0x200025: + MSM6295Command(0, byteValue); + return; + + case 0x200029: + oki_set_bank(byteValue); + return; + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall kbash2WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + MSM6295Reset(1); + + nPreviousOkiBank = 0; + memcpy (RomSnd, RomSnd + 0x40000, 0x40000);//? + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + nGP9001ROMSize[0] = 0x800000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); + SekMapMemory(Ram01, 0x100000, 0x103FFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); + SekSetReadWordHandler(0, kbash2ReadWord); + SekSetReadByteHandler(0, kbash2ReadByte); + SekSetWriteWordHandler(0, kbash2WriteWord); + SekSetWriteByteHandler(0, kbash2WriteByte); + + SekClose(); + } + + MSM6295Init(0, 1000000 / 132, 100.0, 1); + MSM6295Init(1, 1000000 / 132, 100.0, 1); + + nSpriteYOffset = 0x0011; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + + // Trigger VBlank interrupt + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + } + + if (pBurnSoundOut) { + memset (pBurnSoundOut, 0, nBurnSoundLen * 2 * sizeof(INT16)); + MSM6295Render(0, pBurnSoundOut, nBurnSoundLen); + MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvKbash2 = { + "kbash2", NULL, NULL, NULL, "1999", + "Knuckle Bash 2 (bootleg)\0", NULL, "bootleg", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TOAPLAN_68K_ONLY, GBF_SCRFIGHT, 0, + NULL, kbash2RomInfo, kbash2RomName, NULL, NULL, Kbash2InputInfo, Kbash2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/d_mahoudai.cpp b/src/burn/drivers/toaplan/d_mahoudai.cpp new file mode 100644 index 00000000..4c7b4e41 --- /dev/null +++ b/src/burn/drivers/toaplan/d_mahoudai.cpp @@ -0,0 +1,696 @@ +#include "toaplan.h" +// Mahou Daisakusen + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +// Rom information +static struct BurnRomInfo mahoudaiRomDesc[] = { + { "ra_ma_01_01.u65", 0x080000, 0x970CCC5C, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "ra-ma01-rom2.u2", 0x100000, 0x54E2BD95, BRF_GRA }, // 1 GP9001 Tile data + { "ra-ma01-rom3.u1", 0x100000, 0x21CD378F, BRF_GRA }, // 2 + + { "ra_ma_01_05.u81", 0x008000, 0xC00D1E80, BRF_GRA }, // 3 Extra text layer tile data + + { "ra-ma-01_02.u66", 0x010000, 0xEABFA46D, BRF_ESS | BRF_PRG }, // 4 Z80 program + + { "ra-ma01-rom1.u57", 0x040000, 0x6EDB2AB8, BRF_SND }, // 5 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(mahoudai) +STD_ROM_FN(mahoudai) + +static struct BurnRomInfo sstrikerRomDesc[] = { + { "ra-ma_01_01.u65", 0x080000, 0x708FD51D, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "ra-ma01-rom2.u2", 0x100000, 0x54E2BD95, BRF_GRA }, // 1 GP9001 Tile data + { "ra-ma01-rom3.u1", 0x100000, 0x21CD378F, BRF_GRA }, // 2 + + { "ra-ma-01_05.u81", 0x008000, 0x88B58841, BRF_GRA }, // 3 Extra text layer tile data + + { "ra-ma-01_02.u66", 0x010000, 0xEABFA46D, BRF_ESS | BRF_PRG }, // 4 Z80 program + + { "ra-ma01-rom1.u57", 0x040000, 0x6EDB2AB8, BRF_SND }, // 5 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(sstriker) +STD_ROM_FN(sstriker) + +static struct BurnRomInfo sstrikraRomDesc[] = { + { "ra-ma-01_01.u65", 0x080000, 0x92259F84, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "ra-ma01-rom2.u2", 0x100000, 0x54E2BD95, BRF_GRA }, // 1 GP9001 Tile data + { "ra-ma01-rom3.u1", 0x100000, 0x21CD378F, BRF_GRA }, // 2 + + { "ra-ma-01_05.u81", 0x008000, 0x88B58841, BRF_GRA }, // 3 Extra text layer tile data + + { "ra-ma-01_02.u66", 0x010000, 0xEABFA46D, BRF_ESS | BRF_PRG }, // 4 Z80 program + + { "ra-ma01-rom1.u57", 0x040000, 0x6EDB2AB8, BRF_SND }, // 5 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(sstrikra) +STD_ROM_FN(sstrikra) + +static struct BurnInputInfo mahoudaiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(mahoudai) + +static struct BurnDIPInfo mahoudaiDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Coin play"}, + {0x14, 0x01, 0x01, 0x01, "Free play"}, + {0, 0xFE, 0, 2, "Screen"}, + {0x14, 0x01, 0x02, 0x00, "Normal"}, + {0x14, 0x01, 0x02, 0x02, "Invert"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 plays"}, + {0x14, 0x01, 0x30, 0x20, "2 coins 1 play"}, + {0x14, 0x01, 0x30, 0x30, "2 coins 3 plays"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 plays"}, + {0x14, 0x01, 0xC0, 0x80, "2 coins 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "2 coins 3 plays"}, + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B (normal)"}, + {0x15, 0x01, 0x03, 0x01, "A (easy)"}, + {0x15, 0x01, 0x03, 0x02, "C (hard)"}, + {0x15, 0x01, 0x03, 0x03, "D (more hard)"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "200000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heroes"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x80, 0x00, "Continue play"}, + {0x15, 0x01, 0x80, 0x80, "Continue impossible"}, +}; + +static struct BurnDIPInfo mahoudaiRegionDIPList[] = { + // Defaults + {0x16, 0xFF, 0x0E, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 1, "Region"}, + {0x16, 0x01, 0x0E, 0x00, "Japan"}, + {0x16, 0x01, 0x0E, 0x02, "U.S.A."}, + {0x16, 0x01, 0x0E, 0x04, "Europe"}, + {0x16, 0x01, 0x0E, 0x06, "South East Asia"}, + {0x16, 0x01, 0x0E, 0x08, "China"}, + {0x16, 0x01, 0x0E, 0x0A, "Korea"}, + {0x16, 0x01, 0x0E, 0x0C, "Hong Kong"}, + {0x16, 0x01, 0x0E, 0x0E, "Taiwan"}, +}; + +static struct BurnDIPInfo sstrikerRegionDIPList[] = { + // Defaults + {0x16, 0xFF, 0x0E, 0x04, NULL}, + + // Region + {0, 0xFE, 0, 7, "Region"}, + {0x16, 0x01, 0x0E, 0x02, "U.S.A."}, + {0x16, 0x01, 0x0E, 0x04, "Europe"}, + {0x16, 0x01, 0x0E, 0x06, "South East Asia"}, + {0x16, 0x01, 0x0E, 0x08, "China"}, + {0x16, 0x01, 0x0E, 0x0A, "Korea"}, + {0x16, 0x01, 0x0E, 0x0C, "Hong Kong"}, + {0x16, 0x01, 0x0E, 0x0E, "Taiwan"}, + {0x16, 0x01, 0x0E, 0x00, "Japan"}, +}; + +STDDIPINFOEXT(mahoudai, mahoudai, mahoudaiRegion) +STDDIPINFOEXT(sstriker, mahoudai, sstrikerRegion) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02, *RamPal; + +static INT32 nColCount = 0x0800; +static INT32 nRomADPCMSize = 0x040000; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + RomZ80 = Next; Next += 0x010000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + ExtraTROM = Next; Next += 0x008000; // Extra Text layer tile data + MSM6295ROM = Next; Next += nRomADPCMSize; // ADPCM data + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + Ram02 = Next; Next += 0x000800; // + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + ExtraTScroll= Next; Next += 0x001000; // + ExtraTSelect= Next; Next += 0x001000; // + RamPal = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x004000; // Z80 RAM + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(INT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029497; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]); + + // Load Extra text layer tile data + BurnLoadRom(ExtraTROM, 3, 1); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 4, 1); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 5, 1); + + return 0; +} + +UINT8 __fastcall mahoudaiZ80Read(UINT16 nAddress) +{ +// bprintf(PRINT_NORMAL, "z80 read %4X\n", nAddress); + if (nAddress == 0xE001) { + return BurnYM2151ReadStatus(); + } + if (nAddress == 0xE004) { + return MSM6295ReadStatus(0); + } + return 0; +} + +void __fastcall mahoudaiZ80Write(UINT16 nAddress, UINT8 nValue) +{ +// bprintf(PRINT_NORMAL, "Z80 attempted to write address %04X with value %02X.\n", nAddress, nValue); + + switch (nAddress) { + case 0xE000: + BurnYM2151SelectRegister(nValue); + break; + case 0xE001: + BurnYM2151WriteRegister(nValue); + break; + case 0xE004: + MSM6295Command(0, nValue); +// bprintf(PRINT_NORMAL, "OKI M6295 command %02X sent\n", nValue); + break; + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetReadHandler(mahoudaiZ80Read); + ZetSetWriteHandler(mahoudaiZ80Write); + + // ROM + ZetMapArea (0x0000, 0xBFFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0xBFFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0xC000, 0xDFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xC000, 0xDFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xC000, 0xDFFF, 2, RamZ80); // + // Callbacks + ZetMemCallback(0xE000, 0xE0FF, 0); // Read + ZetMemCallback(0xE000, 0xE0FF, 1); // Write + + ZetMemEnd(); + ZetClose(); + + return 0; +} + +UINT8 __fastcall mahoudaiReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x21C021: // Player 1 inputs + return DrvInput[0]; + case 0x21C025: // Player 2 inputs + return DrvInput[1]; + case 0x21C029: // Other inputs + return DrvInput[2]; + case 0x21C02D: // Dipswitch A + return DrvInput[3]; + case 0x21C031: // Dipswitch B + return DrvInput[4]; + case 0x21C035: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x30000D: + return ToaVBlankRegister(); + + default: { + if ((sekAddress & 0x00FFC000) == 0x00218000) { + return RamZ80[(sekAddress & 0x3FFF) >> 1]; + } + +// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall mahoudaiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x21C020: // Player 1 inputs + return DrvInput[0]; + case 0x21C024: // Player 2 inputs + return DrvInput[1]; + case 0x21C028: // Other inputs + return DrvInput[2]; + case 0x21C02C: // Dipswitch A + return DrvInput[3]; + case 0x21C030: // Dipswitch B + return DrvInput[4]; + case 0x21C034: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x21C03C: + return ToaScanlineRegister(); + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + default: { + if ((sekAddress & 0x00FFC000) == 0x00218000) { + return RamZ80[(sekAddress & 0x3FFF) >> 1]; + } + +// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall mahoudaiWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +// switch (sekAddress) { + +// default: { +// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + + if ((sekAddress & 0x00FFC000) == 0x00218000) { + RamZ80[(sekAddress & 0x3FFF) >> 1] = byteValue; + } +// } +// } +} + +void __fastcall mahoudaiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + default: { +// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + if ((sekAddress & 0x00FFC000) == 0x00218000) { + RamZ80[(sekAddress & 0x3FFF) >> 1] = wordValue; + } + } + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x200000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram02, 0x401000, 0x4017FF, SM_RAM); // Unused + SekMapMemory(ExtraTRAM, 0x500000, 0x502FFF, SM_RAM); + SekMapMemory(ExtraTSelect, 0x502000, 0x502FFF, SM_RAM); // 0x502000 - Scroll; 0x502200 - RAM + SekMapMemory(ExtraTScroll, 0x503000, 0x503FFF, SM_RAM); // 0x203000 - Offset; 0x503200 - RAM + + SekSetReadWordHandler(0, mahoudaiReadWord); + SekSetReadByteHandler(0, mahoudaiReadByte); + SekSetWriteWordHandler(0, mahoudaiWriteWord); + SekSetWriteByteHandler(0, mahoudaiWriteByte); + + SekClose(); + } + + nSpritePriority = 1; + ToaInitGP9001(); + + ToaExtraTextInit(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + BurnYM2151Init(27000000 / 8, 50.0); + MSM6295Init(0, 32000000 / 32 / 132, 50.0, 1); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + + ToaExitGP9001(); + ToaExtraTextExit(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = TOA_Z80_SPEED / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + ToaBufferGP9001Sprites(); + + bVBlank = true; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvMahouDai = { + "mahoudai", "sstriker", NULL, NULL, "1993", + "Mahou Daisakusen (Japan)\0", NULL, "Raizing", "Toaplan GP9001 based", + L"\u9B54\u6CD5\u5927\u4F5C\u6226 (Japan)\0Mahou Daisakusen (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, mahoudaiRomInfo, mahoudaiRomName, NULL, NULL, mahoudaiInputInfo, mahoudaiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvSStriker = { + "sstriker", NULL, NULL, NULL, "1993", + "Sorcer Striker (World)\0", NULL, "Raizing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, sstrikerRomInfo, sstrikerRomName, NULL, NULL, mahoudaiInputInfo, sstrikerDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvSStrikrA = { + "sstrikera", "sstriker", NULL, NULL, "1993", + "Sorcer Striker (World, alt)\0", NULL, "Raizing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, sstrikraRomInfo, sstrikraRomName, NULL, NULL, mahoudaiInputInfo, sstrikerDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + diff --git a/src/burn/drivers/toaplan/d_outzone.cpp b/src/burn/drivers/toaplan/d_outzone.cpp new file mode 100644 index 00000000..57dade37 --- /dev/null +++ b/src/burn/drivers/toaplan/d_outzone.cpp @@ -0,0 +1,1017 @@ +// Out Zone + +#include "toaplan.h" + +#define REFRESHRATE ((28000000.0 / 4.0) / (450.0 * 282.0)) +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +// Rom information +static struct BurnRomInfo outzoneRomDesc[] = { + { "tp018_7.bin", 0x020000, 0x0c2ac02d, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp018_8.bin", 0x020000, 0xca7e48aa, BRF_ESS | BRF_PRG }, // 1 + + { "rom5.bin", 0x080000, 0xC64EC7B6, BRF_GRA }, // 2 Tile data + { "rom6.bin", 0x080000, 0x64B6C5AC, BRF_GRA }, // 3 + + { "rom2.bin", 0x020000, 0x6BB72D16, BRF_GRA }, // 4 + { "rom1.bin", 0x020000, 0x0934782D, BRF_GRA }, // 5 + { "rom3.bin", 0x020000, 0xEC903C07, BRF_GRA }, // 6 + { "rom4.bin", 0x020000, 0x50CBF1A8, BRF_GRA }, // 7 + + { "rom9.bin", 0x008000, 0x73D8E235, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "tp018_10.bpr", 0x000020, 0xBC88CCED, BRF_SND }, // 9 Sprite attribute PROM + { "tp018_11.bpr", 0x000020, 0xA1E17492, BRF_SND }, // 10 ??? +}; + + +STD_ROM_PICK(outzone) +STD_ROM_FN(outzone) + +static struct BurnRomInfo outzonebRomDesc[] = { + { "rom7.bin", 0x020000, 0x936E25D8, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "rom8.bin", 0x020000, 0xD19B3ECF, BRF_ESS | BRF_PRG }, // 1 + + { "rom5.bin", 0x080000, 0xC64EC7B6, BRF_GRA }, // 2 Tile data + { "rom6.bin", 0x080000, 0x64B6C5AC, BRF_GRA }, // 3 + + { "rom2.bin", 0x020000, 0x6BB72D16, BRF_GRA }, // 4 + { "rom1.bin", 0x020000, 0x0934782D, BRF_GRA }, // 5 + { "rom3.bin", 0x020000, 0xEC903C07, BRF_GRA }, // 6 + { "rom4.bin", 0x020000, 0x50CBF1A8, BRF_GRA }, // 7 + + { "rom9.bin", 0x008000, 0x73D8E235, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "tp018_10.bpr", 0x000020, 0xBC88CCED, BRF_SND }, // 9 Sprite attribute PROM + { "tp018_11.bpr", 0x000020, 0xA1E17492, BRF_SND }, // 10 ??? +}; + + +STD_ROM_PICK(outzoneb) +STD_ROM_FN(outzoneb) + +static struct BurnRomInfo outzoneaRomDesc[] = { + { "18.bin", 0x020000, 0x31A171BB, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "19.bin", 0x020000, 0x804ECFD1, BRF_ESS | BRF_PRG }, // 1 + + { "rom5.bin", 0x080000, 0xC64EC7B6, BRF_GRA }, // 2 Tile data + { "rom6.bin", 0x080000, 0x64B6C5AC, BRF_GRA }, // 3 + + { "rom2.bin", 0x020000, 0x6BB72D16, BRF_GRA }, // 4 + { "rom1.bin", 0x020000, 0x0934782D, BRF_GRA }, // 5 + { "rom3.bin", 0x020000, 0xEC903C07, BRF_GRA }, // 6 + { "rom4.bin", 0x020000, 0x50CBF1A8, BRF_GRA }, // 7 + + { "rom9.bin", 0x008000, 0x73D8E235, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "tp018_10.bpr", 0x000020, 0xBC88CCED, BRF_SND }, // 9 Sprite attribute PROM + { "tp018_11.bpr", 0x000020, 0xA1E17492, BRF_SND }, // 10 ??? +}; + + +STD_ROM_PICK(outzonea) +STD_ROM_FN(outzonea) + +static struct BurnRomInfo outzonecRomDesc[] = { + { "prg1.bin", 0x020000, 0x127a38d7, BRF_ESS | BRF_PRG }, // 1 + { "prg2.bin", 0x020000, 0x9704db16, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "rom5.bin", 0x080000, 0xC64EC7B6, BRF_GRA }, // 2 Tile data + { "rom6.bin", 0x080000, 0x64B6C5AC, BRF_GRA }, // 3 + + { "rom2.bin", 0x020000, 0x6BB72D16, BRF_GRA }, // 4 + { "rom1.bin", 0x020000, 0x0934782D, BRF_GRA }, // 5 + { "rom3.bin", 0x020000, 0xEC903C07, BRF_GRA }, // 6 + { "rom4.bin", 0x020000, 0x50CBF1A8, BRF_GRA }, // 7 + + { "rom9.bin", 0x008000, 0x73D8E235, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "tp018_10.bpr", 0x000020, 0xBC88CCED, BRF_SND }, // 9 Sprite attribute PROM + { "tp018_11.bpr", 0x000020, 0xA1E17492, BRF_SND }, // 10 ??? +}; + + +STD_ROM_PICK(outzonec) +STD_ROM_FN(outzonec) + +static struct BurnRomInfo outzonedRomDesc[] = { + { "tp07.bin", 0x020000, 0xa85a1d48, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp08.bin", 0x020000, 0xd8cc44af, BRF_ESS | BRF_PRG }, // 1 + + { "rom5.bin", 0x080000, 0xC64EC7B6, BRF_GRA }, // 2 Tile data + { "rom6.bin", 0x080000, 0x64B6C5AC, BRF_GRA }, // 3 + + { "rom2.bin", 0x020000, 0x6BB72D16, BRF_GRA }, // 4 + { "rom1.bin", 0x020000, 0x0934782D, BRF_GRA }, // 5 + { "rom3.bin", 0x020000, 0xEC903C07, BRF_GRA }, // 6 + { "rom4.bin", 0x020000, 0x50CBF1A8, BRF_GRA }, // 7 + + { "tp09.bin", 0x008000, 0xdd56041f, BRF_ESS | BRF_PRG }, // 8 Z80 program + + { "tp018_10.bpr", 0x000020, 0xBC88CCED, BRF_SND }, // 9 Sprite attribute PROM + { "tp018_11.bpr", 0x000020, 0xA1E17492, BRF_SND }, // 10 ??? +}; + + +STD_ROM_PICK(outzoned) +STD_ROM_FN(outzoned) + +static struct BurnInputInfo outzoneInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(outzone) + +static struct BurnDIPInfo outzoneDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, +#if 1 + // Coinage for Europe + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x14, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x14, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, +#else + // Coinage for Japan + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 play"}, + {0x14, 0x01, 0x30, 0x20, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "3 coin 2 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 play"}, + {0x14, 0x01, 0xC0, 0x80, "2 coin 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "3 coin 2 play"}, +#endif + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "300000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heros"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + + // Region + {0, 0xFE, 0, 9, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan (Spacy License)"}, + {0x16, 0x01, 0x0F, 0x07, "US (Romstar License)"}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong (Honest Trading License)"}, + +}; + +STDDIPINFO(outzone) + +static struct BurnDIPInfo outzonebDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, +#if 1 + // Coinage for Europe + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x14, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x14, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, +#else + // Coinage for Japan + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 play"}, + {0x14, 0x01, 0x30, 0x20, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "3 coin 2 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 play"}, + {0x14, 0x01, 0xC0, 0x80, "2 coin 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "3 coin 2 play"}, +#endif + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "300000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heros"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + + // Region + {0, 0xFE, 0, 8, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "No Warning screen"}, + {0x16, 0x01, 0x0F, 0x07, "No Warning screen"}, + + +}; + +STDDIPINFO(outzoneb) + +static struct BurnDIPInfo outzonecDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, +#if 1 + // Coinage for Europe + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x14, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x14, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, +#else + // Coinage for Japan + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 play"}, + {0x14, 0x01, 0x30, 0x20, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "3 coin 2 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 play"}, + {0x14, 0x01, 0xC0, 0x80, "2 coin 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "3 coin 2 play"}, +#endif + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "300000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heros"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + + // Region + {0, 0xFE, 0, 9, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan (Spacy Co License)"}, + {0x16, 0x01, 0x0F, 0x07, "US (Romstar License)"}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong & China (Honest Trading License)"}, + +}; + +STDDIPINFO(outzonec) + +static struct BurnDIPInfo outzonedDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0xFF, 0x02, NULL}, + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, +#if 1 + // Coinage for Europe + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x14, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x14, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, +#else + // Coinage for Japan + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 play"}, + {0x14, 0x01, 0x30, 0x20, "2 coin 1 play"}, + {0x14, 0x01, 0x30, 0x30, "3 coin 2 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 play"}, + {0x14, 0x01, 0xC0, 0x80, "2 coin 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "3 coin 2 play"}, +#endif + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "300000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heros"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + + // Region + {0, 0xFE, 0, 9, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan (Spacy Co License)"}, + {0x16, 0x01, 0x0F, 0x07, "US (Romstar License)"}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong & China (Honest Trading License)"}, + +}; + +STDDIPINFO(outzoned) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal, *RamPal2; + +static INT32 nColCount = 0x0400; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // + RomZ80 = Next; Next += 0x008000; // Z80 ROM + BCU2ROM = Next; Next += nBCU2ROMSize; // BCU-2 tile data + FCU2ROM = Next; Next += nFCU2ROMSize; // FCU-2 tile data + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + RamPal2 = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x008000; // Z80 RAM + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029402; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nCyclesDone); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load BCU-2 tile data + ToaLoadGP9001Tiles(BCU2ROM, 2, 2, nBCU2ROMSize); + + // Load FCU-2 tile data + ToaLoadTiles(FCU2ROM, 4, nFCU2ROMSize); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 8, 1); + + return 0; +} + +UINT8 __fastcall outzoneZ80In(UINT16 nAddress) +{ +// bprintf(PRINT_NORMAL, _T("z80 read %4X\n"), nAddress); + + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: + return BurnYM3812Read(0); + case 0x08: // DIP A + return DrvInput[2]; + case 0x0C: // DIP B + return DrvInput[3]; + case 0x10: // Sysytem inputs + return DrvInput[4] | (ToaVBlankRegister() << 7); + case 0x14: // Player 1 + return DrvInput[0]; + case 0x18: // Player 2 + return DrvInput[1]; + case 0x1C: // Region + return DrvInput[5]; + + } + + return 0; +} + +void __fastcall outzoneZ80Out(UINT16 nAddress, UINT8 nValue) +{ +// bprintf(PRINT_NORMAL, _T("Z80 attempted to write address %04X with value %02X.\n"), nAddress, nValue); + + nAddress &= 0xFF; + + switch (nAddress) { + case 0x00: + BurnYM3812Write(0, nValue); + break; + case 0x01: + BurnYM3812Write(1, nValue); + break; + + case 0x04: // Coin counter + break; + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(outzoneZ80In); + ZetSetOutHandler(outzoneZ80Out); + + // ROM + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0x8000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0x8000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0x8000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall outzoneReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x100001: + case 0x300001: + return ToaVBlankRegister(); + + default: { +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + } + + return 0; +} + +UINT16 __fastcall outzoneReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x100002: + return ToaFCU2GetRAMPointer(); + case 0x100004: + return ToaFCU2ReadRAM(); + case 0x100006: + return ToaFCU2ReadRAMSize(); + + case 0x200002: + return ToaBCU2GetRAMPointer(); + case 0x200004: + return ToaBCU2ReadRAM_Hi(); + case 0x200006: + return ToaBCU2ReadRAM_Lo(); + + case 0x200010: + case 0x200011: + case 0x200012: + case 0x200013: + case 0x200014: + case 0x200015: + case 0x200016: + case 0x200017: + case 0x200018: + case 0x200019: + case 0x20001A: + case 0x20001B: + case 0x20001C: + case 0x20001D: + case 0x20001E: + case 0x20001F: + return BCU2Reg[(sekAddress & 15) >> 1]; + + case 0x100000: + case 0x300000: + return ToaVBlankRegister(); + + default: { +// printf("Attempt to read word value of location %x\n", sekAddress); + } + } + + return 0; +} + +void __fastcall outzoneWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x300003: + bEnableInterrupts = byteValue; + break; + + case 0x100006: + ToaFCU2WriteRAMSize(byteValue); + break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall outzoneWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x100002: // FCU-2 set VRAM address-pointer + ToaFCU2SetRAMPointer(wordValue); + break; + case 0x100004: + ToaFCU2WriteRAM(wordValue); + break; + case 0x100006: + ToaFCU2WriteRAMSize(wordValue); + break; + + case 0x200000: // BCU-2 flip + break; + case 0x200002: // BCU-2 set VRAM address-pointer + ToaBCU2SetRAMPointer(wordValue); + break; + case 0x200004: + ToaBCU2WriteRAM(wordValue); + break; + case 0x200006: + ToaBCU2WriteRAM(wordValue); + break; + + case 0x200010: + case 0x200011: + case 0x200012: + case 0x200013: + case 0x200014: + case 0x200015: + case 0x200016: + case 0x200017: + case 0x200018: + case 0x200019: + case 0x20001A: + case 0x20001B: + case 0x20001C: + case 0x20001D: + case 0x20001E: + case 0x20001F: + BCU2Reg[(sekAddress & 15) >> 1] = wordValue; + break; + + case 0x300002: + bEnableInterrupts = (wordValue & 0xFF); + break; + + case 0x340000: + nBCU2TileXOffset = wordValue; + break; + case 0x340002: + nBCU2TileYOffset = wordValue; + break; + + case 0x340006: // FCU-2 flip + break; + + default: { +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x100000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // 68K ROM + SekMapMemory(Ram01, 0x240000, 0x243FFF, SM_RAM); // 68K RAM + SekMapMemory(RamPal, 0x304000, 0x3047FF, SM_RAM); // BCU-2 palette RAM + SekMapMemory(RamPal2, 0x306000, 0x3067FF, SM_RAM); // FCU-2 palette RAM + + SekSetReadWordHandler(0, outzoneReadWord); + SekSetReadByteHandler(0, outzoneReadByte); + SekSetWriteWordHandler(0, outzoneWriteWord); + SekSetWriteByteHandler(0, outzoneWriteByte); + + SekMapHandler(1, 0x140000, 0x140FFF, SM_RAM); // Z80 RAM + + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + + SekClose(); + } + + ToaInitBCU2(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalSrc2 = RamPal2; + ToaPalInit(); + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); // Render BCU2 graphics + } + + ToaPalUpdate(); // Update the palette + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[4] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[4] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { // See if this CPU is busywaiting + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + ZetClose(); + SekClose(); + +// ToaBufferFCU2Sprites(); + + return 0; +} + +struct BurnDriver BurnDrvOutZone = { + "outzone", NULL, NULL, NULL, "1990", + "Out Zone (set 1)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, outzoneRomInfo, outzoneRomName, NULL, NULL, outzoneInputInfo, outzoneDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvOutZonea = { + "outzonea", "outzone", NULL, NULL, "1990", + "Out Zone (set 2)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, outzoneaRomInfo, outzoneaRomName, NULL, NULL, outzoneInputInfo, outzoneDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvOutZoneb = { + "outzoneb", "outzone", NULL, NULL, "1990", + "Out Zone (set 3, prototype?)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, outzonebRomInfo, outzonebRomName, NULL, NULL, outzoneInputInfo, outzonebDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvOutZonec = { + "outzonec", "outzone", NULL, NULL, "1990", + "Out Zone (set 4)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, outzonecRomInfo, outzonecRomName, NULL, NULL, outzoneInputInfo, outzonecDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvOutZoned = { + "outzoned", "outzone", NULL, NULL, "1990", + "Out Zone (set 5)\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, outzonedRomInfo, outzonedRomName, NULL, NULL, outzoneInputInfo, outzonedDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_pipibibs.cpp b/src/burn/drivers/toaplan/d_pipibibs.cpp new file mode 100644 index 00000000..3449a0e8 --- /dev/null +++ b/src/burn/drivers/toaplan/d_pipibibs.cpp @@ -0,0 +1,580 @@ +#include "toaplan.h" +// Pipi & Bibis / Whoopee!! + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static struct BurnInputInfo PipibibsInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 0, "service"}, + {"Tilt", BIT_DIGITAL, DrvButton + 1, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(Pipibibs) + +static struct BurnDIPInfo PipibibsDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0xf6, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x13, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + {0x14, 0x01, 0x0c, 0x08, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "200k and every 300k" }, + {0x14, 0x01, 0x0c, 0x04, "150k and every 200k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 4, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x07, 0x06, "Europe" }, + {0x15, 0x01, 0x07, 0x07, "Europe (Nova Apparate GMBH & Co)" }, + {0x15, 0x01, 0x07, 0x04, "USA" }, + {0x15, 0x01, 0x07, 0x05, "USA (Romstar)" }, + {0x15, 0x01, 0x07, 0x00, "Japan" }, + {0x15, 0x01, 0x07, 0x01, "Asia" }, + {0x15, 0x01, 0x07, 0x02, "Hong Kong (Honest Trading Co.)" }, + {0x15, 0x01, 0x07, 0x03, "Taiwan" }, + + {0 , 0xfe, 0 , 0, "Nudity" }, + {0x15, 0x01, 0x08, 0x08, "Low" }, + {0x15, 0x01, 0x08, 0x00, "High, but censored" }, +}; + +STDDIPINFO(Pipibibs) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // 68000 ROM + RomZ80 = Next; Next += 0x010000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + RamStart = Next; + Ram01 = Next; Next += 0x003000; // CPU #0 work RAM + RamZ80 = Next; Next += 0x001000; + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x008000; // Double size, as the game tests too much memory during POST + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 2, 2, nGP9001ROMSize[0]); + + BurnLoadRom(RomZ80, 4, 1); + + return 0; +} + +UINT8 __fastcall pipibibsReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x19c031: // Player 1 inputs + return DrvInput[0]; + case 0x19c035: // Player 2 inputs + return DrvInput[1]; + case 0x19c02d: // Other inputs + return DrvInput[2]; + + case 0x19c021: // Dipswitch 1 + return DrvInput[3]; + case 0x19c025: // Dipswitch 2 + return DrvInput[4]; + case 0x19c029: // Dipswitch 3 - Territory + return DrvInput[5]&0x0f; + + case 0x14000D: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall pipibibsReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x19c030: // Player 1 inputs + return DrvInput[0]; + case 0x19c034: // Player 2 inputs + return DrvInput[1]; + case 0x19c02c: // Other inputs + return DrvInput[2]; + + case 0x19c020: // Dipswitch 1 + return DrvInput[3]; + case 0x19c024: // Dipswitch 2 + return DrvInput[4]; + case 0x19c028: // Dipswitch 3 - Territory + return DrvInput[5]&0x0f; + + case 0x140004: + return ToaGP9001ReadRAM_Hi(0); + case 0x140006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x14000C: + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall pipibibsWriteByte(UINT32 /*sekAddress*/, UINT8 /*byteValue*/) +{ +// switch (sekAddress) { +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); +// } +} + +void __fastcall pipibibsWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x140000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x140004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x140006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x140008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x14000C: + ToaGP9001WriteRegister(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +void __fastcall pipibibs_sound_write(UINT16 address, UINT8 data) +{ + switch (address) + { + case 0xe000: + BurnYM3812Write(0, data); + return; + + case 0xe001: + BurnYM3812Write(1, data); + return; + } +} + +UINT8 __fastcall pipibibs_sound_read(UINT16 address) +{ + switch (address) + { + case 0xe000: + case 0xe001: + return BurnYM3812Read(0); + } + + return 0; +} + +inline static INT32 pipibibsSynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3375000; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nGP9001ROMSize[0] = 0x200000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x080000, 0x082FFF, SM_RAM); + SekMapMemory(RamPal, 0x0c0000, 0x0c0FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, pipibibsReadWord); + SekSetReadByteHandler(0, pipibibsReadByte); + SekSetWriteWordHandler(0, pipibibsWriteWord); + SekSetWriteByteHandler(0, pipibibsWriteByte); + + SekMapHandler(1, 0x190000, 0x190FFF, SM_RAM); + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, RomZ80); + ZetMapArea(0x0000, 0x7fff, 2, RomZ80); + ZetMapArea(0x8000, 0x87ff, 0, RamZ80); + ZetMapArea(0x8000, 0x87ff, 1, RamZ80); + ZetMapArea(0x8000, 0x87ff, 2, RamZ80); + ZetSetWriteHandler(pipibibs_sound_write); + ZetSetReadHandler(pipibibs_sound_read); + ZetMemEnd(); + ZetClose(); + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnYM3812Init(3375000, &toaplan1FMIRQHandler, pipibibsSynchroniseStream, 0); + BurnTimerAttachZetYM3812(3375000); + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + BurnYM3812Exit(); + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + ZetExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInput, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + ZetNewFrame(); + + SekOpen(0); + ZetOpen(0); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = (INT32)(27000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + ToaBufferGP9001Sprites(); + + bVBlank = true; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + if (pBurnSoundOut) { + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + } + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + +// ToaBufferFCU2Sprites(); + + SekClose(); + ZetClose(); + + return 0; +} + + +// Pipi & Bibis / Whoopee!! (Z80 sound cpu, set 1) + +static struct BurnRomInfo pipibibsRomDesc[] = { + { "tp025-1.bin", 0x020000, 0xb2ea8659, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp025-2.bin", 0x020000, 0xdc53b939, BRF_ESS | BRF_PRG }, // 1 + + { "tp025-4.bin", 0x100000, 0xab97f744, BRF_GRA }, // 2 GP9001 Tile data + { "tp025-3.bin", 0x100000, 0x7b16101e, BRF_GRA }, // 3 + + { "tp025-5.bin", 0x008000, 0xbf8ffde5, BRF_ESS | BRF_PRG }, // 4 CPU #1 code +}; + +STD_ROM_PICK(pipibibs) +STD_ROM_FN(pipibibs) + +struct BurnDriver BurnDrvPipibibs = { + "pipibibs", NULL, NULL, NULL, "1991", + "Pipi & Bibis / Whoopee!! (Z80 sound cpu, set 1)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_PLATFORM, 0, + NULL, pipibibsRomInfo, pipibibsRomName, NULL, NULL, PipibibsInputInfo, PipibibsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + + +// Pipi & Bibis / Whoopee!! (Z80 sound cpu, set 2) + +static struct BurnRomInfo pipibibsaRomDesc[] = { + { "tp025-1.alt.bin", 0x020000, 0x3e522d98, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp025-2.alt.bin", 0x020000, 0x48370485, BRF_ESS | BRF_PRG }, // 1 + + { "tp025-4.bin", 0x100000, 0xab97f744, BRF_GRA }, // 2 GP9001 Tile data + { "tp025-3.bin", 0x100000, 0x7b16101e, BRF_GRA }, // 3 + + { "tp025-5.bin", 0x008000, 0xbf8ffde5, BRF_ESS | BRF_PRG }, // 4 CPU #1 code +}; + +STD_ROM_PICK(pipibibsa) +STD_ROM_FN(pipibibsa) + +struct BurnDriver BurnDrvPipibibsa = { + "pipibibsa", "pipibibs", NULL, NULL, "1991", + "Pipi & Bibis / Whoopee!! (Z80 sound cpu, set 2)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_PLATFORM, 0, + NULL, pipibibsaRomInfo, pipibibsaRomName, NULL, NULL, PipibibsInputInfo, PipibibsDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/d_rallybik.cpp b/src/burn/drivers/toaplan/d_rallybik.cpp new file mode 100644 index 00000000..ebf36436 --- /dev/null +++ b/src/burn/drivers/toaplan/d_rallybik.cpp @@ -0,0 +1,620 @@ +#include "toaplan.h" + +#define REFRESHRATE 55.14 +#define VBLANK_LINES (32) + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *DrvZ80ROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvSprRAM; +static UINT8 *DrvSprBuf; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalRAM2; +static UINT8 *DrvShareRAM; + +static UINT8 DrvInputs[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvReset; + +static INT32 nColCount = 0x0800; + +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +static struct BurnInputInfo RallybikInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Rallybik) + +static struct BurnDIPInfo RallybikDIPList[]= +{ + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x20, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x01, "Upright" }, + {0x13, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + {0x14, 0x01, 0x03, 0x00, "Medium" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Territory/Copyright" }, + {0x14, 0x01, 0x30, 0x20, "World/Taito Corp Japan" }, + {0x14, 0x01, 0x30, 0x10, "USA/Taito America" }, + {0x14, 0x01, 0x30, 0x00, "Japan/Taito Corp" }, + {0x14, 0x01, 0x30, 0x30, "USA/Taito America (Romstar)" }, + + {0 , 0xfe, 0 , 2, "Dip Switch Display" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, +}; + +STDDIPINFO(Rallybik) + +void __fastcall rallybikWriteWord(UINT32 a, UINT16 d) +{ + switch (a) + { + case 0x100000: + // rallybik_bcu_flipscreen_w + return; + + case 0x100002: + ToaBCU2SetRAMPointer(d); + return; + + case 0x100004: + case 0x100006: + ToaBCU2WriteRAM(d); + return; + + case 0x100010: + case 0x100012: + case 0x100014: + case 0x100016: + case 0x100018: + case 0x10001a: + case 0x10001c: + case 0x10001e: + BCU2Reg[(a & 0x0f) >> 1] = d; + return; + + case 0x140002: + bEnableInterrupts = d & 0xff; + return; + + case 0x140008: + case 0x14000a: + case 0x14000c: + case 0x14000e: + // toaplan1_bcu_control_w + return; + + case 0x1c0000: + nBCU2TileXOffset = d; + return; + + case 0x1c0002: + nBCU2TileYOffset = d; + return; + + case 0x1c8000: + if (d == 0) { + ZetReset(); + } + return; + } +} + +void __fastcall rallybikWriteByte(UINT32 , UINT8 ) +{ + return; +} + +UINT16 __fastcall rallybikReadWord(UINT32 a) +{ + switch (a) + { + case 0x100002: + return ToaBCU2GetRAMPointer(); + + case 0x100004: // ok? + { + INT32 data = ToaBCU2ReadRAM_Hi(); + data |= ((data & 0xf000) >> 4) | ((data & 0x0030) << 2); + return data; + } + + case 0x100006: + return ToaBCU2ReadRAM_Lo(); + + case 0x100010: + case 0x100012: + case 0x100014: + case 0x100016: + case 0x100018: + case 0x10001a: + case 0x10001c: + case 0x10001e: + return BCU2Reg[(a & 0x0f) >> 1]; + } + + return 0; +} + +UINT8 __fastcall rallybikReadByte(UINT32 a) +{ + switch (a) + { + case 0x140001: + return ToaVBlankRegister(); + } + + return 0; +} + +void __fastcall rallybik_sound_write_port(UINT16 p, UINT8 d) +{ + switch (p & 0xff) + { + case 0x30: // toaplan1_coin_w + return; + + case 0x60: + BurnYM3812Write(0, d); + return; + + case 0x61: + BurnYM3812Write(1, d); + return; + } +} + +UINT8 __fastcall rallybik_sound_read_port(UINT16 p) +{ + switch (p & 0xff) + { + case 0x00: + return DrvInputs[0]; + + case 0x10: + return DrvInputs[1]; + + case 0x20: + return DrvInputs[2]; + + case 0x40: + return DrvDips[0]; + + case 0x50: + return DrvDips[1]; + + case 0x60: + case 0x61: + return BurnYM3812Read(p & 1); + + case 0x70: + return DrvDips[2]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + DrvZ80ROM = Next; Next += 0x010000; + BCU2ROM = Next; Next += nBCU2ROMSize; + FCU2ROM = Next; Next += nFCU2ROMSize; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvPalRAM2 = Next; Next += 0x000800; + + RamZ80 = Next; + DrvShareRAM = Next; Next += 0x008000; + + DrvSprRAM = Next; Next += 0x001000; + + BCU2RAM = Next; Next += 0x010000; + DrvSprBuf = Next; + FCU2RAM = Next; Next += 0x001000; + FCU2RAMSize = Next; Next += 0x000080; + + RamEnd = Next; + + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static void DrvSpriteDecode() +{ + UINT8 *tmp = (UINT8*)malloc(0x40000); + if (tmp == NULL) { + return; + } + + memcpy (tmp, FCU2ROM, 0x40000); + memset (FCU2ROM, 0, 0x80000); + + for (INT32 i = 0; i < (0x40000 / 4) * 8; i++) { + for (INT32 j = 0; j < 4; j++) { + FCU2ROM[i] |= ((tmp[(j * 0x10000) + (i/8)] >> (~i & 7)) & 1) << (3 - j); + } + } + + if (tmp) { + free (tmp); + tmp = NULL; + } +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Rallybik = 1; + +// bToaRotateScreen = true; + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(AllMem, 0, nLen); + MemIndex(); + + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM, 4, 1)) return 1; + + ToaLoadTiles(BCU2ROM, 5, nBCU2ROMSize); +// ToaLoadTiles(FCU2ROM, 9, nFCU2ROMSize); + + if (BurnLoadRom(FCU2ROM + 0x000000, 9, 1)) return 1; + if (BurnLoadRom(FCU2ROM + 0x010000, 10, 1)) return 1; + if (BurnLoadRom(FCU2ROM + 0x020000, 11, 1)) return 1; + if (BurnLoadRom(FCU2ROM + 0x030000, 12, 1)) return 1; + + DrvSpriteDecode(); + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x00FFFF, SM_ROM); + SekMapMemory(Drv68KROM + 0x40000, 0x040000, 0x07FFFF, SM_ROM); + SekMapMemory(Drv68KRAM, 0x080000, 0x083FFF, SM_RAM); + SekMapMemory(DrvSprRAM, 0x0c0000, 0x0C0FFF, SM_RAM); + SekMapMemory(DrvPalRAM, 0x144000, 0x1447FF, SM_RAM); + SekMapMemory(DrvPalRAM2, 0x146000, 0x1467FF, SM_RAM); + SekSetReadWordHandler(0, rallybikReadWord); + SekSetReadByteHandler(0, rallybikReadByte); + SekSetWriteWordHandler(0, rallybikWriteWord); + SekSetWriteByteHandler(0, rallybikWriteByte); + + SekMapHandler(1, 0x180000, 0x180FFF, SM_RAM); + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + SekClose(); + + ZetInit(1); + ZetOpen(0); + ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM); + ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM); + ZetMapArea(0x8000, 0xffff, 0, DrvShareRAM); + ZetMapArea(0x8000, 0xffff, 1, DrvShareRAM); + ZetMapArea(0x8000, 0xffff, 2, DrvShareRAM); + ZetSetOutHandler(rallybik_sound_write_port); + ZetSetInHandler(rallybik_sound_read_port); + ZetMemEnd(); + ZetClose(); + } + + nLayer0XOffset = 0x0d + 6; + nLayer1XOffset = 0x0d + 4; + nLayer2XOffset = 0x0d + 2; + nLayer3XOffset = 0x0d + 0; + nLayer0YOffset = nLayer1YOffset = nLayer2YOffset = nLayer3YOffset = 0x111; + + ToaInitBCU2(); + + ToaOpaquePriority = 0; + + nToaPalLen = nColCount; + ToaPalSrc = DrvPalRAM; + ToaPalSrc2 = DrvPalRAM2; + ToaPalInit(); + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); + + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); + ZetExit(); + SekExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + Rallybik = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); + } + + ToaPalUpdate(); + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInputs, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] |= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + } + ToaClearOpposites(&DrvInputs[0]); + ToaClearOpposites(&DrvInputs[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + memcpy (DrvSprBuf, DrvSprRAM, 0x1000); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + + SekClose(); + ZetClose(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + ZetScan(nAction); + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(nCyclesDone); + } + + return 0; +} + + +// Rally Bike / Dash Yarou + +static struct BurnRomInfo rallybikRomDesc[] = { + { "b45-02.rom", 0x08000, 0x383386d7, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "b45-01.rom", 0x08000, 0x7602f6a7, BRF_PRG | BRF_ESS }, // 1 + { "b45-04.rom", 0x20000, 0xe9b005b1, BRF_PRG | BRF_ESS }, // 2 + { "b45-03.rom", 0x20000, 0x555344ce, BRF_PRG | BRF_ESS }, // 3 + + { "b45-05.rom", 0x04000, 0x10814601, BRF_PRG | BRF_ESS }, // 4 CPU #1 code + + { "b45-09.bin", 0x20000, 0x1dc7b010, BRF_GRA }, // 5 Tile data + { "b45-08.bin", 0x20000, 0xfab661ba, BRF_GRA }, // 6 + { "b45-07.bin", 0x20000, 0xcd3748b4, BRF_GRA }, // 7 + { "b45-06.bin", 0x20000, 0x144b085c, BRF_GRA }, // 8 + + { "b45-11.rom", 0x10000, 0x0d56e8bb, BRF_GRA }, // 9 + { "b45-10.rom", 0x10000, 0xdbb7c57e, BRF_GRA }, // 10 + { "b45-12.rom", 0x10000, 0xcf5aae4e, BRF_GRA }, // 11 + { "b45-13.rom", 0x10000, 0x1683b07c, BRF_GRA }, // 12 + + { "b45-15.bpr", 0x00100, 0x24e7d62f, BRF_OPT }, // 13 + { "b45-16.bpr", 0x00100, 0xa50cef09, BRF_OPT }, // 14 + { "b45-14.bpr", 0x00020, 0xf72482db, BRF_OPT }, // 15 + { "b45-17.bpr", 0x00020, 0xbc88cced, BRF_OPT }, // 16 Sprite attribute PROM? +}; + +STD_ROM_PICK(rallybik) +STD_ROM_FN(rallybik) + +struct BurnDriver BurnDrvRallybik = { + "rallybik", NULL, NULL, NULL, "1988", + "Rally Bike / Dash Yarou\0", NULL, "[Toaplan] Taito Corporation", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, rallybikRomInfo, rallybikRomName, NULL, NULL, RallybikInputInfo, RallybikDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_samesame.cpp b/src/burn/drivers/toaplan/d_samesame.cpp new file mode 100644 index 00000000..18f536f2 --- /dev/null +++ b/src/burn/drivers/toaplan/d_samesame.cpp @@ -0,0 +1,820 @@ +#include "toaplan.h" + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalRAM2; + +static UINT8 DrvInputs[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvReset; + +static INT32 nColCount = 0x0800; + +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +static struct BurnInputInfo SamesameInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Samesame) + +static struct BurnDIPInfo SamesameDIPList[]= +{ + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x01, "Upright" }, + {0x13, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + {0x14, 0x01, 0x03, 0x00, "Medium" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x04, "50K, every 150K" }, + {0x14, 0x01, 0x0c, 0x00, "70K, every 200K" }, + {0x14, 0x01, 0x0c, 0x08, "100K" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, +}; + +STDDIPINFO(Samesame) + +static struct BurnDIPInfo Samesam2DIPList[]= +{ + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x00, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x01, "Upright" }, + {0x13, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + {0x14, 0x01, 0x03, 0x00, "Medium" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x04, "50K, every 150K" }, + {0x14, 0x01, 0x0c, 0x00, "70K, every 200K" }, + {0x14, 0x01, 0x0c, 0x08, "100K" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 2, "Show Territory Notice"}, + {0x15, 0x01, 0x01, 0x01, "No" }, + {0x15, 0x01, 0x01, 0x00, "Yes" }, +}; + +STDDIPINFO(Samesam2) + +static struct BurnDIPInfo FireshrkDIPList[]= +{ + {0x13, 0xff, 0xff, 0x01, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 2, "Cabinet" }, + {0x13, 0x01, 0x01, 0x01, "Upright" }, + {0x13, 0x01, 0x01, 0x00, "Cocktail" }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x13, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + {0x14, 0x01, 0x03, 0x00, "Medium" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x04, "50K, every 150K" }, + {0x14, 0x01, 0x0c, 0x00, "70K, every 200K" }, + {0x14, 0x01, 0x0c, 0x08, "100K" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x20, "4" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x14, 0x01, 0x80, 0x80, "No" }, + {0x14, 0x01, 0x80, 0x00, "Yes" }, + + + {0 , 0xfe, 0 , 3, "Territory" }, + {0x15, 0x01, 0x06, 0x02, "Europe" }, + {0x15, 0x01, 0x06, 0x04, "USA" }, + {0x15, 0x01, 0x06, 0x00, "USA (Romstar)" }, +}; + +STDDIPINFO(Fireshrk) + +void __fastcall samesameWriteWord(UINT32 a, UINT16 d) +{ + switch (a) + { + case 0x080000: + nBCU2TileXOffset = d; + return; + + case 0x080002: + nBCU2TileYOffset = d; + return; + + case 0x080006: + // toaplan1_fcu_flipscreen_w + return; + + case 0x100000: + return; // nop + + case 0x100002: + bEnableInterrupts = (d & 0xFF); + return; + + case 0x100008: + case 0x10000a: + case 0x10000c: + case 0x10000e: + // toaplan1_bcu_control_w + return; + + case 0x14000c: + // samesame_coin_w + return; + + case 0x14000e: + return; // mcu writes... + + case 0x180000: + // toaplan1_bcu_flipscreen_w + return; + + case 0x180002: + ToaBCU2SetRAMPointer(d); + return; + + case 0x180004: + case 0x180006: + ToaBCU2WriteRAM(d); + return; + + case 0x180010: + case 0x180012: + case 0x180014: + case 0x180016: + case 0x180018: + case 0x18001a: + case 0x18001c: + case 0x18001e: + BCU2Reg[(a & 0x0f) >> 1] = d; + return; + + case 0x1c0000: + return; // nop + + case 0x1c0002: + ToaFCU2SetRAMPointer(d); + return; + + case 0x1c0004: + ToaFCU2WriteRAM(d); + return; + + case 0x1c0006: + ToaFCU2WriteRAMSize(d); + return; + } +} + +void __fastcall samesameWriteByte(UINT32 , UINT8 ) +{ + return; +} + +UINT16 __fastcall samesameReadWord(UINT32 a) +{ + switch (a) + { + case 0x140000: + return DrvInputs[0]; + + case 0x140002: + return DrvInputs[1]; + + case 0x140004: + return DrvDips[0]; + + case 0x140006: + return DrvDips[1]; + + case 0x140008: + return DrvInputs[2]; + + case 0x14000a: + return (0x80 | DrvDips[2]); + + case 0x14000e: + return 0; // mcu reads... + + case 0x180002: + return ToaBCU2GetRAMPointer(); + + case 0x180004: + return ToaBCU2ReadRAM_Hi(); + + case 0x180006: + return ToaBCU2ReadRAM_Lo(); + + case 0x180010: + case 0x180012: + case 0x180014: + case 0x180016: + case 0x180018: + case 0x18001a: + case 0x18001c: + case 0x18001e: + return BCU2Reg[(a & 0x0f) >> 1]; + + case 0x1c0002: + return ToaFCU2GetRAMPointer(); + + case 0x1c0004: + return ToaFCU2ReadRAM(); + + case 0x1c0006: + return ToaFCU2ReadRAMSize(); + } + + return 0; +} + +UINT8 __fastcall samesameReadByte(UINT32 a) +{ + switch (a) + { + case 0x100001: + case 0x1c0001: + return ToaVBlankRegister(); + + case 0x140001: + return DrvInputs[0]; + + case 0x140003: + return DrvInputs[1]; + + case 0x140005: + return DrvDips[0]; + + case 0x140007: + return DrvDips[1]; + + case 0x140009: + return DrvInputs[2]; + + case 0x14000b: + return (0x80 | DrvDips[2]); + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + +// BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x080000; + BCU2ROM = Next; Next += nBCU2ROMSize; + FCU2ROM = Next; Next += nFCU2ROMSize; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x004000; + DrvPalRAM = Next; Next += 0x000800; + DrvPalRAM2 = Next; Next += 0x000800; + + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + + RamEnd = Next; + + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +// bToaRotateScreen = true; + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(AllMem, 0, nLen); + MemIndex(); + + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040001, 2, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x040000, 3, 2)) return 1; + + ToaLoadTiles(BCU2ROM, 4, nBCU2ROMSize); + ToaLoadTiles(FCU2ROM, 8, nFCU2ROMSize); + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x07FFFF, SM_ROM); + SekMapMemory(Drv68KRAM, 0x0c0000, 0x0c3FFF, SM_RAM); + SekMapMemory(DrvPalRAM, 0x104000, 0x1047FF, SM_RAM); + SekMapMemory(DrvPalRAM2, 0x106000, 0x1067FF, SM_RAM); + SekSetReadWordHandler(0, samesameReadWord); + SekSetReadByteHandler(0, samesameReadByte); + SekSetWriteWordHandler(0, samesameWriteWord); + SekSetWriteByteHandler(0, samesameWriteByte); + SekClose(); + } + + ToaInitBCU2(); + + nToaPalLen = nColCount; + ToaPalSrc = DrvPalRAM; + ToaPalSrc2 = DrvPalRAM2; + ToaPalInit(); + +// BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + + bDrawScreen = true; + + DrvDoReset(); + return 0; +} + +static INT32 DrvExit() +{ +// BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); + SekExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); + } + + ToaPalUpdate(); + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInputs, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] |= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + } + ToaClearOpposites(&DrvInputs[0]); + ToaClearOpposites(&DrvInputs[1]); + + SekOpen(0); + + SekNewFrame(); + + SekIdle(nCyclesDone[0]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); +// BurnTimerEndFrameYM3812(nCyclesTotal[1]); +// BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + ToaBufferFCU2Sprites(); + + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // sprite buffer finished... + + SekClose(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + + // BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(nCyclesDone); + } + + return 0; +} + + +// Fire Shark + +static struct BurnRomInfo fireshrkRomDesc[] = { + { "09.bin", 0x08000, 0xf0c70e6f, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "10.bin", 0x08000, 0x9d253d77, BRF_PRG | BRF_ESS }, // 1 + { "o17_11ii.7j", 0x20000, 0x6beac378, BRF_PRG | BRF_ESS }, // 2 + { "o17_12ii.7l", 0x20000, 0x6adb6eb5, BRF_PRG | BRF_ESS }, // 3 + + { "o17_05.12j", 0x20000, 0x565315f8, BRF_GRA }, // 4 Tile data + { "o17_06.13j", 0x20000, 0x95262d4c, BRF_GRA }, // 5 + { "o17_07.12l", 0x20000, 0x4c4b735c, BRF_GRA }, // 6 + { "o17_08.13l", 0x20000, 0x95c6586c, BRF_GRA }, // 7 + + { "o17_01.1d", 0x20000, 0xea12e491, BRF_GRA }, // 8 + { "o17_02.3d", 0x20000, 0x32a13a9f, BRF_GRA }, // 9 + { "o17_03.5d", 0x20000, 0x68723dc9, BRF_GRA }, // 10 + { "o17_04.7d", 0x20000, 0xfe0ecb13, BRF_GRA }, // 12 + + { "prom14.25b", 0x00020, 0xbc88cced, BRF_GRA }, // 12 Sprite attribute PROM + { "prom15.20c", 0x00020, 0xa1e17492, BRF_GRA }, // 13 + + { "hd647180.017", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 14 Sound HD647180 code +}; + +STD_ROM_PICK(fireshrk) +STD_ROM_FN(fireshrk) + +struct BurnDriver BurnDrvFireshrk = { + "fireshrk", NULL, NULL, NULL, "1990", + "Fire Shark\0", "No sound", "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, fireshrkRomInfo, fireshrkRomName, NULL, NULL, SamesameInputInfo, FireshrkDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Fire Shark (Korea, set 1, easier) + +static struct BurnRomInfo fireshrkdRomDesc[] = { + { "o17_09dyn.8j", 0x10000, 0xe25eee27, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o17_10dyn.8l", 0x10000, 0xc4c58cf6, BRF_PRG | BRF_ESS }, // 1 + { "o17_11ii.7j", 0x20000, 0x6beac378, BRF_PRG | BRF_ESS }, // 2 + { "o17_12ii.7l", 0x20000, 0x6adb6eb5, BRF_PRG | BRF_ESS }, // 3 + + { "o17_05.12j", 0x20000, 0x565315f8, BRF_GRA }, // 4 Tile data + { "o17_06.13j", 0x20000, 0x95262d4c, BRF_GRA }, // 5 + { "o17_07.12l", 0x20000, 0x4c4b735c, BRF_GRA }, // 6 + { "o17_08.13l", 0x20000, 0x95c6586c, BRF_GRA }, // 7 + + { "o17_01.1d", 0x20000, 0xea12e491, BRF_GRA }, // 8 + { "o17_02.3d", 0x20000, 0x32a13a9f, BRF_GRA }, // 9 + { "o17_03.5d", 0x20000, 0x68723dc9, BRF_GRA }, // 10 + { "o17_04.7d", 0x20000, 0xfe0ecb13, BRF_GRA }, // 12 + + { "prom14.25b", 0x00020, 0xbc88cced, BRF_GRA }, // 12 Sprite attribute PROM + { "prom15.20c", 0x00020, 0xa1e17492, BRF_GRA }, // 13 + + { "hd647180.017", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 14 Sound HD647180 code +}; + +STD_ROM_PICK(fireshrkd) +STD_ROM_FN(fireshrkd) + +struct BurnDriver BurnDrvFireshrkd = { + "fireshrkd", "fireshrk", NULL, NULL, "1990", + "Fire Shark (Korea, set 1, easier)\0", "No sound", "Toaplan (Dooyong license)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, fireshrkdRomInfo, fireshrkdRomName, NULL, NULL, SamesameInputInfo, Samesam2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Fire Shark (Korea, set 2, harder) + +static struct BurnRomInfo fireshrkdhRomDesc[] = { + { "o17_09dyh.8j", 0x10000, 0x7b4c14dd, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o17_10dyh.8l", 0x10000, 0xa3f159f9, BRF_PRG | BRF_ESS }, // 1 + { "o17_11x.bin", 0x20000, 0x6beac378, BRF_PRG | BRF_ESS }, // 2 + { "o17_12x.bin", 0x20000, 0x6adb6eb5, BRF_PRG | BRF_ESS }, // 3 + + { "o17_05.12j", 0x20000, 0x565315f8, BRF_GRA }, // 4 Tile data + { "o17_06.13j", 0x20000, 0x95262d4c, BRF_GRA }, // 5 + { "o17_07.12l", 0x20000, 0x4c4b735c, BRF_GRA }, // 6 + { "o17_08.13l", 0x20000, 0x95c6586c, BRF_GRA }, // 7 + + { "o17_01.1d", 0x20000, 0xea12e491, BRF_GRA }, // 8 + { "o17_02.3d", 0x20000, 0x32a13a9f, BRF_GRA }, // 9 + { "o17_03.5d", 0x20000, 0x68723dc9, BRF_GRA }, // 10 + { "o17_04.7d", 0x20000, 0xfe0ecb13, BRF_GRA }, // 12 + + { "prom14.25b", 0x00020, 0xbc88cced, BRF_GRA }, // 12 Sprite attribute PROM + { "prom15.20c", 0x00020, 0xa1e17492, BRF_GRA }, // 13 + + { "hd647180.017", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 14 Sound HD647180 code +}; + +STD_ROM_PICK(fireshrkdh) +STD_ROM_FN(fireshrkdh) + +struct BurnDriver BurnDrvFireshrkdh = { + "fireshrkdh", "fireshrk", NULL, NULL, "1990", + "Fire Shark (Korea, set 2, harder)\0", "No sound", "Toaplan (Dooyong license)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, fireshrkdhRomInfo, fireshrkdhRomName, NULL, NULL, SamesameInputInfo, Samesam2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Same! Same! Same! (2 player alternating ver.) + +static struct BurnRomInfo samesameRomDesc[] = { + { "o17_09.bin", 0x08000, 0x3f69e437, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o17_10.bin", 0x08000, 0x4e723e0a, BRF_PRG | BRF_ESS }, // 1 + { "o17_11.bin", 0x20000, 0xbe07d101, BRF_PRG | BRF_ESS }, // 2 + { "o17_12.bin", 0x20000, 0xef698811, BRF_PRG | BRF_ESS }, // 3 + + { "o17_05.12j", 0x20000, 0x565315f8, BRF_GRA }, // 4 Tile data + { "o17_06.13j", 0x20000, 0x95262d4c, BRF_GRA }, // 5 + { "o17_07.12l", 0x20000, 0x4c4b735c, BRF_GRA }, // 6 + { "o17_08.13l", 0x20000, 0x95c6586c, BRF_GRA }, // 7 + + { "o17_01.1d", 0x20000, 0xea12e491, BRF_GRA }, // 8 + { "o17_02.3d", 0x20000, 0x32a13a9f, BRF_GRA }, // 9 + { "o17_03.5d", 0x20000, 0x68723dc9, BRF_GRA }, // 10 + { "o17_04.7d", 0x20000, 0xfe0ecb13, BRF_GRA }, // 12 + + { "prom14.25b", 0x00020, 0xbc88cced, BRF_GRA }, // 12 Sprite attribute PROM + { "prom15.20c", 0x00020, 0xa1e17492, BRF_GRA }, // 13 + + { "hd647180.017", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 14 Sound HD647180 code +}; + +STD_ROM_PICK(samesame) +STD_ROM_FN(samesame) + +struct BurnDriver BurnDrvSamesame = { + "samesame", "fireshrk", NULL, NULL, "1989", + "Same! Same! Same! (2 player alternating ver.)\0", "No sound", "Toaplan", "Toaplan BCU-2 / FCU-2 based", + L"\u9BAB!\u9BAB!\u9BAB! (2 player alternating ver.)\0Same! Same! Same! (2 player alternating ver.)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, samesameRomInfo, samesameRomName, NULL, NULL, SamesameInputInfo, SamesameDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Same! Same! Same! + +static struct BurnRomInfo samesame2RomDesc[] = { + { "o17_09x.bin", 0x08000, 0x3472e03e, BRF_PRG | BRF_ESS }, // 0 CPU #0 code + { "o17_10x.bin", 0x08000, 0xa3ac49b5, BRF_PRG | BRF_ESS }, // 1 + { "o17_11ii.7j", 0x20000, 0x6beac378, BRF_PRG | BRF_ESS }, // 2 + { "o17_12ii.7l", 0x20000, 0x6adb6eb5, BRF_PRG | BRF_ESS }, // 3 + + { "o17_05.12j", 0x20000, 0x565315f8, BRF_GRA }, // 4 Tile data + { "o17_06.13j", 0x20000, 0x95262d4c, BRF_GRA }, // 5 + { "o17_07.12l", 0x20000, 0x4c4b735c, BRF_GRA }, // 6 + { "o17_08.13l", 0x20000, 0x95c6586c, BRF_GRA }, // 7 + + { "o17_01.1d", 0x20000, 0xea12e491, BRF_GRA }, // 8 + { "o17_02.3d", 0x20000, 0x32a13a9f, BRF_GRA }, // 9 + { "o17_03.5d", 0x20000, 0x68723dc9, BRF_GRA }, // 10 + { "o17_04.7d", 0x20000, 0xfe0ecb13, BRF_GRA }, // 12 + + { "prom14.25b", 0x00020, 0xbc88cced, BRF_GRA }, // 12 Sprite attribute PROM + { "prom15.20c", 0x00020, 0xa1e17492, BRF_GRA }, // 13 + + { "hd647180.017", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 14 Sound HD647180 code +}; + +STD_ROM_PICK(samesame2) +STD_ROM_FN(samesame2) + +struct BurnDriver BurnDrvSamesame2 = { + "samesame2", "fireshrk", NULL, NULL, "1989", + "Same! Same! Same!\0", "No sound", "Toaplan", "Toaplan BCU-2 / FCU-2 based", + L"\u9BAB!\u9BAB!\u9BAB!\0Same! Same! Same!\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, samesame2RomInfo, samesame2RomName, NULL, NULL, SamesameInputInfo, Samesam2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_shippumd.cpp b/src/burn/drivers/toaplan/d_shippumd.cpp new file mode 100644 index 00000000..a891272d --- /dev/null +++ b/src/burn/drivers/toaplan/d_shippumd.cpp @@ -0,0 +1,704 @@ +#include "toaplan.h" +// Shippu Mahou Daisakusen + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +// Rom information +static struct BurnRomInfo shippumdRomDesc[] = { + { "ma02rom1.bin", 0x080000, 0xA678B149, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "ma02rom0.bin", 0x080000, 0xF226A212, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "ma02rom3.bin", 0x200000, 0x0E797142, BRF_GRA }, // 2 GP9001 Tile data + { "ma02rom4.bin", 0x200000, 0x72A6FA53, BRF_GRA }, // 3 + + { "ma02rom5.bin", 0x008000, 0x116AE559, BRF_GRA }, // 4 Extra text layer tile data + + { "ma02rom2.bin", 0x010000, 0xDDE8A57E, BRF_ESS | BRF_PRG }, // 5 Z80 program + + { "ma02rom6.bin", 0x080000, 0x199E7CAE, BRF_SND }, // 6 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(shippumd) +STD_ROM_FN(shippumd) + +static struct BurnRomInfo kingdmgpRomDesc[] = { + { "ma02rom1.bin", 0x080000, 0xA678B149, BRF_ESS | BRF_PRG }, // 0 CPU #0 code (even) + { "ma02rom0.bin", 0x080000, 0xF226A212, BRF_ESS | BRF_PRG }, // 1 (odd) + + { "ma02rom3.bin", 0x200000, 0x0E797142, BRF_GRA }, // 2 GP9001 Tile data + { "ma02rom4.bin", 0x200000, 0x72A6FA53, BRF_GRA }, // 3 + + { "ma02rom5.eng", 0x008000, 0x8C28460B, BRF_GRA }, // 4 Extra text layer tile data + + { "ma02rom2.bin", 0x010000, 0xDDE8A57E, BRF_ESS | BRF_PRG }, // 5 Z80 program + + { "ma02rom6.bin", 0x080000, 0x199E7CAE, BRF_SND }, // 6 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(kingdmgp) +STD_ROM_FN(kingdmgp) + +static struct BurnInputInfo shippumdInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(shippumd) + +static struct BurnDIPInfo shippumdDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Coin play"}, + {0x14, 0x01, 0x01, 0x01, "Free play"}, + {0, 0xFE, 0, 2, "Screen"}, + {0x14, 0x01, 0x02, 0x00, "Normal"}, + {0x14, 0x01, 0x02, 0x02, "Invert"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0x30, 0x10, "1 coin 2 plays"}, + {0x14, 0x01, 0x30, 0x20, "2 coins 1 play"}, + {0x14, 0x01, 0x30, 0x30, "2 coins 3 plays"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x14, 0x01, 0xC0, 0x40, "1 coin 2 plays"}, + {0x14, 0x01, 0xC0, 0x80, "2 coins 1 play"}, + {0x14, 0x01, 0xC0, 0xC0, "2 coins 3 plays"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B (normal)"}, + {0x15, 0x01, 0x03, 0x01, "A (easy)"}, + {0x15, 0x01, 0x03, 0x02, "C (hard)"}, + {0x15, 0x01, 0x03, 0x03, "D (more hard)"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x15, 0x01, 0x0C, 0x00, "300000 pts every"}, + {0x15, 0x01, 0x0C, 0x04, "200000 & 500000 pts"}, + {0x15, 0x01, 0x0C, 0x08, "200000 only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heroes"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x10, "5"}, + {0x15, 0x01, 0x30, 0x20, "2"}, + {0x15, 0x01, 0x30, 0x30, "1"}, + {0, 0xFE, 0, 2, "No death & stop mode"}, + {0x15, 0x01, 0x40, 0x00, "Off"}, + {0x15, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x80, 0x00, "Continue play"}, + {0x15, 0x01, 0x80, 0x80, "Continue impossible"}, +}; + +static struct BurnDIPInfo shippumdRegionDIPList[] = { + // Defaults + {0x16, 0xFF, 0x0E, 0x00, NULL}, + + // Region + {0, 0xFE, 0, 1, "Region"}, + {0x16, 0x01, 0x0E, 0x00, "Japan"}, + {0x16, 0x01, 0x0E, 0x02, "U.S.A."}, + {0x16, 0x01, 0x0E, 0x04, "Europe"}, + {0x16, 0x01, 0x0E, 0x06, "South East Asia"}, + {0x16, 0x01, 0x0E, 0x08, "China"}, + {0x16, 0x01, 0x0E, 0x0A, "Korea"}, + {0x16, 0x01, 0x0E, 0x0C, "Hong Kong"}, + {0x16, 0x01, 0x0E, 0x0E, "Taiwan"}, +}; + +static struct BurnDIPInfo kingdmgpRegionDIPList[] = { + // Defaults + {0x16, 0xFF, 0x0E, 0x04, NULL}, + + // Region + {0, 0xFE, 0, 7, "Region"}, + {0x16, 0x01, 0x0E, 0x02, "U.S.A."}, + {0x16, 0x01, 0x0E, 0x04, "Europe"}, + {0x16, 0x01, 0x0E, 0x06, "South East Asia"}, + {0x16, 0x01, 0x0E, 0x08, "China"}, + {0x16, 0x01, 0x0E, 0x0A, "Korea"}, + {0x16, 0x01, 0x0E, 0x0C, "Hong Kong"}, + {0x16, 0x01, 0x0E, 0x0E, "Taiwan"}, + {0x16, 0x01, 0x0E, 0x00, "Japan"}, +}; + +STDDIPINFOEXT(shippumd, shippumd, shippumdRegion) +STDDIPINFOEXT(kingdmgp, shippumd, kingdmgpRegion) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *Ram02, *RamPal; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x100000; // + RomZ80 = Next; Next += 0x010000; // Z80 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + ExtraTROM = Next; Next += 0x008000; // Extra Text layer tile data + MSM6295ROM = Next; Next += 0x080000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + Ram02 = Next; Next += 0x000800; // + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + ExtraTScroll= Next; Next += 0x001000; // + ExtraTSelect= Next; Next += 0x001000; // + RamPal = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x004000; // Z80 RAM + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029497; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // Scan 68000 + ZetScan(nAction); // Scan Z80 + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + if (ToaLoadCode(Rom01, 0, 2)) { + return 1; + } + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 2, 2, nGP9001ROMSize[0]); + + // Load Extra text layer tile data + BurnLoadRom(ExtraTROM, 4, 1); + + // Load Z80 ROM + BurnLoadRom(RomZ80, 5, 1); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 6, 1); + + return 0; +} + +UINT8 __fastcall shippumdZ80Read(UINT16 nAddress) +{ + if (nAddress == 0xE001) { + return BurnYM2151ReadStatus(); + } + if (nAddress == 0xE004) { + return MSM6295ReadStatus(0); + } + return 0; +} + +void __fastcall shippumdZ80Write(UINT16 nAddress, UINT8 nValue) +{ + switch (nAddress) { + case 0xE000: + BurnYM2151SelectRegister(nValue); + break; + case 0xE001: + BurnYM2151WriteRegister(nValue); + break; + case 0xE004: + MSM6295Command(0, nValue); + break; + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetReadHandler(shippumdZ80Read); + ZetSetWriteHandler(shippumdZ80Write); + + // ROM + ZetMapArea (0x0000, 0xFFFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0xFFFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0xC000, 0xDFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0xC000, 0xDFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0xC000, 0xDFFF, 2, RamZ80); // + // Callbacks + ZetMemCallback(0xE000, 0xE0FF, 0); // Read + ZetMemCallback(0xE000, 0xE0FF, 1); // Write + + ZetMemEnd(); + ZetClose(); + + return 0; +} + +UINT8 __fastcall shippumdReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x21C021: // Player 1 inputs + return DrvInput[0]; + case 0x21C025: // Player 2 inputs + return DrvInput[1]; + case 0x21C029: // Other inputs + return DrvInput[2]; + case 0x21C02D: // Dipswitch A + return DrvInput[3]; + case 0x21C031: // Dipswitch B + return DrvInput[4]; + case 0x21C035: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x30000D: + return ToaVBlankRegister(); + + default: { +// printf("Attempt to read byte value of location %x\n", sekAddress); + + if ((sekAddress & 0x00FFC000) == 0x00218000) { + return RamZ80[(sekAddress & 0x3FFF) >> 1]; + } + } + } + return 0; +} + +UINT16 __fastcall shippumdReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x21C020: // Player 1 inputs + return DrvInput[0]; + case 0x21C024: // Player 2 inputs + return DrvInput[1]; + case 0x21C028: // Other inputs + return DrvInput[2]; + case 0x21C02C: // Dipswitch A + return DrvInput[3]; + case 0x21C030: // Dipswitch B + return DrvInput[4]; + case 0x21C034: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x21C03C: + return ToaScanlineRegister(); + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + default: { + if ((sekAddress & 0x00FFC000) == 0x00218000) { + return RamZ80[(sekAddress & 0x3FFF) >> 1]; + } + +// printf("Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall shippumdWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x21C01D: { + INT32 nBankOffset; + if (byteValue & 0x10) { + nBankOffset = 0x40000; + } else { + nBankOffset = 0x00000; + } + MSM6295SampleInfo[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleData[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleInfo[0][1] = MSM6295ROM + nBankOffset + 0x0100; + MSM6295SampleData[0][1] = MSM6295ROM + nBankOffset + 0x10000; + MSM6295SampleInfo[0][2] = MSM6295ROM + nBankOffset + 0x0200; + MSM6295SampleData[0][2] = MSM6295ROM + nBankOffset + 0x20000; + MSM6295SampleInfo[0][3] = MSM6295ROM + nBankOffset + 0x0300; + MSM6295SampleData[0][3] = MSM6295ROM + nBankOffset + 0x30000; + break; + } + + default: { + if ((sekAddress & 0x00FFC000) == 0x00218000) { + RamZ80[(sekAddress & 0x3FFF) >> 1] = byteValue; + } + +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall shippumdWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x21C01C: { + INT32 nBankOffset; + if (wordValue & 0x10) { + nBankOffset = 0x40000; + } else { + nBankOffset = 0x00000; + } + MSM6295SampleInfo[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleData[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleInfo[0][1] = MSM6295ROM + nBankOffset + 0x0100; + MSM6295SampleData[0][1] = MSM6295ROM + nBankOffset + 0x10000; + MSM6295SampleInfo[0][2] = MSM6295ROM + nBankOffset + 0x0200; + MSM6295SampleData[0][2] = MSM6295ROM + nBankOffset + 0x20000; + MSM6295SampleInfo[0][3] = MSM6295ROM + nBankOffset + 0x0300; + MSM6295SampleData[0][3] = MSM6295ROM + nBankOffset + 0x30000; + break; + } + + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + default: { +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + if ((sekAddress & 0x00FFC000) == 0x00218000) { + RamZ80[(sekAddress & 0x3FFF) >> 1] = wordValue; + } + } + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + ZetOpen(0); + ZetReset(); + ZetClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x400000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekMapMemory(Ram02, 0x401000, 0x4017FF, SM_RAM); // Unused + SekMapMemory(ExtraTRAM, 0x500000, 0x502FFF, SM_RAM); + SekMapMemory(ExtraTSelect, 0x502000, 0x502FFF, SM_RAM); // 0x502000 - Scroll; 0x502200 - RAM + SekMapMemory(ExtraTScroll, 0x503000, 0x503FFF, SM_RAM); // 0x203000 - Offset; 0x503200 - RAM + + SekSetReadWordHandler(0, shippumdReadWord); + SekSetReadByteHandler(0, shippumdReadByte); + SekSetWriteWordHandler(0, shippumdWriteWord); + SekSetWriteByteHandler(0, shippumdWriteByte); + + SekClose(); + } + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + ToaInitGP9001(); + + nExtraTXOffset = 0x2C; + ToaExtraTextInit(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + BurnYM2151Init(27000000 / 8, 50.0); + MSM6295Init(0, 32000000 / 32 / 132, 50.0, 1); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + + ToaExitGP9001(); + ToaExtraTextExit(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Free memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = TOA_Z80_SPEED / 60; + nCyclesDone[0] = nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + ZetOpen(0); + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + ToaBufferGP9001Sprites(); + + bVBlank = true; + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // Run Z80 + nCurrentCPU = 1; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += ZetRun(nCyclesSegment); + + { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + ZetClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvShippuMD = { + "shippumd", "kingdmgp", NULL, NULL, "1994", + "Shippu Mahou Daisakusen - kingdom grandprix (Japan)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + L"\u75BE\u98A8\u9B54\u6CD5\u5927\u4F5C\u6226 - kingdom grandprix (Japan)\0Shippu Mahou Daisakusen (Japan)\0", NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, shippumdRomInfo, shippumdRomName, NULL, NULL, shippumdInputInfo, shippumdDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvKingdmGP = { + "kingdmgp", NULL, NULL, NULL, "1994", + "Kingdom Grandprix (World)\0", NULL, "Raizing / 8ing", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, kingdmgpRomInfo, kingdmgpRomName, NULL, NULL, shippumdInputInfo, kingdmgpDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_snowbro2.cpp b/src/burn/drivers/toaplan/d_snowbro2.cpp new file mode 100644 index 00000000..416833f4 --- /dev/null +++ b/src/burn/drivers/toaplan/d_snowbro2.cpp @@ -0,0 +1,622 @@ +#include "toaplan.h" +// Snow Bros. 2 + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy3[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy4[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; + +static INT32 nColCount = 0x0800; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static struct BurnInputInfo snowbro2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy3 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy3 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy3 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy3 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2"}, + + {"P3 Start", BIT_DIGITAL, DrvJoy3 + 6, "p3 start"}, + + {"P3 Up", BIT_DIGITAL, DrvJoy3 + 0, "p3 up"}, + {"P3 Down", BIT_DIGITAL, DrvJoy3 + 1, "p3 down"}, + {"P3 Left", BIT_DIGITAL, DrvJoy3 + 2, "p3 left"}, + {"P3 Right", BIT_DIGITAL, DrvJoy3 + 3, "p3 right"}, + {"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p3 fire 1"}, + {"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p3 fire 2"}, + + {"P4 Start", BIT_DIGITAL, DrvJoy4 + 6, "p4 start"}, + + {"P4 Up", BIT_DIGITAL, DrvJoy4 + 0, "p4 up"}, + {"P4 Down", BIT_DIGITAL, DrvJoy4 + 1, "p4 down"}, + {"P4 Left", BIT_DIGITAL, DrvJoy4 + 2, "p4 left"}, + {"P4 Right", BIT_DIGITAL, DrvJoy4 + 3, "p4 right"}, + {"P4 Button 1", BIT_DIGITAL, DrvJoy4 + 4, "p4 fire 1"}, + {"P4 Button 2", BIT_DIGITAL, DrvJoy4 + 5, "p4 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(snowbro2) + +static struct BurnDIPInfo snowbro2DIPList[] = { + // Defaults + {0x20, 0xFF, 0xFF, 0x00, NULL}, + {0x21, 0xFF, 0xFF, 0x00, NULL}, + {0x22, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0 , 0xFE, 0 , 2 , "Continue Mode" }, + {0x20, 0x01, 0x01, 0x00, "Normal" }, + {0x20, 0x01, 0x01, 0x01, "Discount" }, + + {0 , 0xFE, 0 , 2 , "Flip Screen" }, + {0x20, 0x01, 0x02, 0x00, "Off" }, + {0x20, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xFE, 0 , 2 , "Service Mode" }, + {0x20, 0x01, 0x04, 0x00, "Off" }, + {0x20, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xFE, 0 , 2 , "Demo Sounds" }, + {0x20, 0x01, 0x08, 0x08, "Off" }, + {0x20, 0x01, 0x08, 0x00, "On" }, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0F, 0x08, NULL}, + + // DIP 2 + {0 , 0xFE, 0 , 4 , "Difficulty" }, + {0x21, 0x01, 0x03, 0x01, "Easy" }, + {0x21, 0x01, 0x03, 0x00, "Normal" }, + {0x21, 0x01, 0x03, 0x02, "Hard" }, + {0x21, 0x01, 0x03, 0x03, "Very Hard" }, + + {0 , 0xFE, 0 , 4 , "Bonus Life" }, + {0x21, 0x01, 0x0C, 0x04, "100000 / 500000" }, + {0x21, 0x01, 0x0C, 0x00, "100000 only" }, + {0x21, 0x01, 0x0C, 0x08, "200000 only" }, + {0x21, 0x01, 0x0C, 0x0C, "None" }, + + {0 , 0xFE, 0 , 4 , "Lives" }, + {0x21, 0x01, 0x30, 0x30, "1" }, + {0x21, 0x01, 0x30, 0x20, "2" }, + {0x21, 0x01, 0x30, 0x00, "3" }, + {0x21, 0x01, 0x30, 0x10, "4" }, + + {0 , 0xFE, 0 , 2 , "Game Type" }, + {0x21, 0x01, 0x40, 0x00, "Normal" }, + {0x21, 0x01, 0x40, 0x40, "No Death & Stop Mode" }, + + {0 , 0xFE, 0 , 2 , "Max Players" }, + {0x21, 0x01, 0x80, 0x80, "2" }, + {0x21, 0x01, 0x80, 0x00, "4" }, + + // Dip 3 + {0 , 0xFE, 0 , 7 , "Territory" }, + {0x22, 0x01, 0x1C, 0x08, "Europe" }, + {0x22, 0x01, 0x1C, 0x10, "Hong Kong" }, + {0x22, 0x01, 0x1C, 0x00, "Japan" }, + {0x22, 0x01, 0x1C, 0x0c, "Korea" }, + {0x22, 0x01, 0x1C, 0x18, "South East Asia" }, + {0x22, 0x01, 0x1C, 0x14, "Taiwan" }, + {0x22, 0x01, 0x1C, 0x04, "USA" }, + + {0 , 0xFE, 0 , 2 , "Show All Rights Reserved" }, + {0x22, 0x01, 0x20, 0x00, "No" }, + {0x22, 0x01, 0x20, 0x20, "Yes" }, +}; + +STDDIPINFO(snowbro2) + +UINT8 __fastcall snowbro2ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x30000D: + return ToaVBlankRegister(); + + case 0x70000D: // Player 1 inputs + return DrvInput[0]; + case 0x700011: // Player 2 inputs + return DrvInput[1]; + case 0x700015: // Player 3 inputs + return DrvInput[6]; + case 0x700019: // Player 4 inputs + return DrvInput[7]; + case 0x70001D: // Other inputs + return DrvInput[2]; + case 0x700005: // Dipswitch A + return DrvInput[3]; + case 0x700009: // Dipswitch B + return DrvInput[4]; + case 0x700000: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x600001: + return MSM6295ReadStatus(0); + case 0x500003: + return BurnYM2151ReadStatus(); + + default: { +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + } + return 0; +} + +UINT16 __fastcall snowbro2ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + case 0x70000C: // Player 1 inputs + return DrvInput[0]; + case 0x700010: // Player 2 inputs + return DrvInput[1]; + case 0x700014: // Player 3 inputs + return DrvInput[6]; + case 0x700018: // Player 4 inputs + return DrvInput[7]; + case 0x70001C: // Other inputs + return DrvInput[2]; + case 0x700004: // Dipswitch A + return DrvInput[3]; + case 0x700008: // Dipswitch B + return DrvInput[4]; + + case 0x600000: + return MSM6295ReadStatus(0); + case 0x500002: + return BurnYM2151ReadStatus(); + + default: { +// printf("Attempt to read word value of location %x\n", sekAddress); + } + } + return 0; +} + +void __fastcall snowbro2WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x600001: + MSM6295Command(0, byteValue); + break; + + case 0x500001: + BurnYM2151SelectRegister(byteValue); + break; + case 0x500003: + BurnYM2151WriteRegister(byteValue); + break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } + } +} + +void __fastcall snowbro2WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x600000: + MSM6295Command(0, wordValue & 0xFF); + break; + case 0x700030: { + INT32 nBankOffset = (wordValue & 0x01) << 18; + MSM6295SampleInfo[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleData[0][0] = MSM6295ROM + nBankOffset; + MSM6295SampleInfo[0][1] = MSM6295ROM + nBankOffset + 0x0100; + MSM6295SampleData[0][1] = MSM6295ROM + nBankOffset + 0x10000; + MSM6295SampleInfo[0][2] = MSM6295ROM + nBankOffset + 0x0200; + MSM6295SampleData[0][2] = MSM6295ROM + nBankOffset + 0x20000; + MSM6295SampleInfo[0][3] = MSM6295ROM + nBankOffset + 0x0300; + MSM6295SampleData[0][3] = MSM6295ROM + nBankOffset + 0x30000; + break; + } + + case 0x500000: + BurnYM2151SelectRegister(wordValue); + break; + case 0x500002: + BurnYM2151WriteRegister(wordValue); + break; + + default: { +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } + } +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + DrvInput[6] = 0x00; + DrvInput[7] = 0x00; + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + DrvInput[6] |= (DrvJoy3[i] & 1) << i; + DrvInput[7] |= (DrvJoy4[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + ToaClearOpposites(&DrvInput[6]); + ToaClearOpposites(&DrvInput[7]); + + SekNewFrame(); + + nCyclesTotal[0] = (int)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen / nInterleave; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x080000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 4, nGP9001ROMSize[0]); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 5, 1); + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + } + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + nGP9001ROMSize[0] = 0x400000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + + SekSetReadWordHandler(0, snowbro2ReadWord); + SekSetReadByteHandler(0, snowbro2ReadByte); + SekSetWriteWordHandler(0, snowbro2WriteWord); + SekSetWriteByteHandler(0, snowbro2WriteByte); + + SekClose(); + } + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + nSpriteYOffset = 0x0011; + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + BurnYM2151Init(27000000 / 8, 50.0); + MSM6295Init(0, 27000000 / 10 / 132, 50.0, 1); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +// Rom information +static struct BurnRomInfo snowbro2RomDesc[] = { + { "pro-4", 0x080000, 0x4c7ee341, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "rom2-l", 0x100000, 0xe9d366a9, BRF_GRA }, // 1 GP9001 Tile data + { "rom2-h", 0x080000, 0x9aab7a62, BRF_GRA }, // 2 + { "rom3-l", 0x100000, 0xeb06e332, BRF_GRA }, // 3 + { "rom3-h", 0x080000, 0xdf4a952a, BRF_GRA }, // 4 + + { "rom4", 0x080000, 0x638f341e, BRF_SND }, // 5 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(snowbro2) +STD_ROM_FN(snowbro2) + + +struct BurnDriver BurnDrvSnowbro2 = { + "snowbro2", NULL, NULL, NULL, "1994", + "Snow Bros. 2 - with new elves\0", NULL, "[Toaplan] Hanafram", "Toaplan GP9001 based", + L"Snow Bros. 2 - with new elves\0\u304A\u3066\u3093\u304D\u30D1\u30E9\u30C0\u30A4\u30B9\0\u96EA\u4EBA\u5144\u5F1F\uFF12\0\uB208\uC0AC\uB78C\uD615\uC81C\uFF12\0", NULL, NULL, NULL, + BDF_GAME_WORKING, 4, HARDWARE_TOAPLAN_68K_ONLY, GBF_PLATFORM, 0, + NULL, snowbro2RomInfo, snowbro2RomName, NULL, NULL, snowbro2InputInfo, snowbro2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + diff --git a/src/burn/drivers/toaplan/d_tekipaki.cpp b/src/burn/drivers/toaplan/d_tekipaki.cpp new file mode 100644 index 00000000..588b7c01 --- /dev/null +++ b/src/burn/drivers/toaplan/d_tekipaki.cpp @@ -0,0 +1,623 @@ +#include "toaplan.h" +// Teki Paki + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + + +// Rom information +static struct BurnRomInfo drvRomDesc[] = { + { "tp020-1.bin", 0x010000, 0xD8420BD5, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp020-2.bin", 0x010000, 0x7222DE8E, BRF_ESS | BRF_PRG }, // 1 + + { "tp020-4.bin", 0x080000, 0x3EBBE41E, BRF_GRA }, // 2 GP9001 Tile data + { "tp020-3.bin", 0x080000, 0x2D5E2201, BRF_GRA }, // 3 + + { "hd647180.020", 0x008000, 0x00000000, 0x10 | BRF_NODUMP }, // 4 Sound CPU +}; + +STD_ROM_PICK(drv) +STD_ROM_FN(drv) + + +// Rom information +static struct BurnRomInfo whoopeeRomDesc[] = { + { "whoopee.1", 0x020000, 0x28882e7e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "whoopee.2", 0x020000, 0x6796f133, BRF_ESS | BRF_PRG }, // 1 + + { "tp025-4.bin", 0x100000, 0xab97f744, BRF_GRA }, // 2 GP9001 Tile data + { "tp025-3.bin", 0x100000, 0x7b16101e, BRF_GRA }, // 3 + + { "hd647180.025", 0x008000, 0x00000000, 0x10 | BRF_NODUMP }, // 4 Sound CPU +}; + +STD_ROM_PICK(whoopee) +STD_ROM_FN(whoopee) + +static struct BurnInputInfo tekipakiInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(tekipaki) + +static struct BurnDIPInfo tekipakiDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFE, 0x00, NULL}, + {0x15, 0xFF, 0x43, 0x00, NULL}, + {0x16, 0xFF, 0x0F, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "Stop mode"}, + + // Region + {0, 0xFE, 0, 9, "Game difficulty"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "Taiwan (Spacey Co, ltd.)"}, + {0x16, 0x01, 0x0F, 0x07, "U.S.A. (Romstar inc.)"}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong (Honest Trading Co.)"}, + {0x16, 0x01, 0x0F, 0x09, "Japan"}, + {0x16, 0x01, 0x0F, 0x0A, "Japan"}, + {0x16, 0x01, 0x0F, 0x0B, "Japan"}, + {0x16, 0x01, 0x0F, 0x0C, "Japan"}, + {0x16, 0x01, 0x0F, 0x0D, "Japan"}, + {0x16, 0x01, 0x0F, 0x0E, "Japan"}, + {0x16, 0x01, 0x0F, 0x0F, "Japan"}, +}; + +STDDIPINFO(tekipaki) + +static struct BurnInputInfo whoopeeInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Service", BIT_DIGITAL, DrvButton + 0, "service"}, + {"Tilt", BIT_DIGITAL, DrvButton + 1, "tilt"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(whoopee) + +static struct BurnDIPInfo whoopeeDIPList[]= +{ + {0x13, 0xff, 0xff, 0x00, NULL }, + {0x14, 0xff, 0xff, 0x00, NULL }, + {0x15, 0xff, 0xff, 0xf6, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x13, 0x01, 0x02, 0x00, "Off" }, + {0x13, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Service Mode" }, + {0x13, 0x01, 0x04, 0x00, "Off" }, + {0x13, 0x01, 0x04, 0x04, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x13, 0x01, 0x08, 0x08, "Off" }, + {0x13, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 7, "Coin A" }, + {0x13, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x20, "2 Coins 1 Credits" }, + {0x13, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0x30, 0x30, "2 Coins 3 Credits" }, + {0x13, 0x01, 0x30, 0x10, "1 Coin 2 Credits" }, + + {0 , 0xfe, 0 , 8, "Coin B" }, + {0x13, 0x01, 0xc0, 0x80, "2 Coins 1 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 1 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "2 Coins 3 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x13, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x13, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x13, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 0, "Difficulty" }, + {0x14, 0x01, 0x03, 0x03, "Hardest" }, + {0x14, 0x01, 0x03, 0x02, "Hard" }, + {0x14, 0x01, 0x03, 0x00, "Normal" }, + {0x14, 0x01, 0x03, 0x01, "Easy" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x14, 0x01, 0x0c, 0x0c, "None" }, + {0x14, 0x01, 0x0c, 0x08, "200k only" }, + {0x14, 0x01, 0x0c, 0x00, "200k and every 300k" }, + {0x14, 0x01, 0x0c, 0x04, "150k and every 200k" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x14, 0x01, 0x30, 0x30, "1" }, + {0x14, 0x01, 0x30, 0x20, "2" }, + {0x14, 0x01, 0x30, 0x00, "3" }, + {0x14, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 4, "Invulnerability" }, + {0x14, 0x01, 0x40, 0x00, "Off" }, + {0x14, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Region" }, + {0x15, 0x01, 0x07, 0x06, "Europe" }, + {0x15, 0x01, 0x07, 0x07, "Europe (Nova Apparate GMBH & Co)" }, + {0x15, 0x01, 0x07, 0x04, "USA" }, + {0x15, 0x01, 0x07, 0x05, "USA (Romstar)" }, + {0x15, 0x01, 0x07, 0x00, "Japan" }, + {0x15, 0x01, 0x07, 0x01, "Asia" }, + {0x15, 0x01, 0x07, 0x02, "Hong Kong (Honest Trading Co.)" }, + {0x15, 0x01, 0x07, 0x03, "Taiwan" }, + + {0 , 0xfe, 0 , 0, "Nudity" }, + {0x15, 0x01, 0x08, 0x08, "Low" }, + {0x15, 0x01, 0x08, 0x00, "High, but censored" }, +}; + +STDDIPINFO(whoopee) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // 68000 ROM + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + RamStart = Next; + Ram01 = Next; Next += 0x003000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x008000; // Double size, as the game tests too much memory during POST + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 2, 2, nGP9001ROMSize[0]); + + return 0; +} + +UINT8 __fastcall tekipakiReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x180051: // Player 1 inputs + return DrvInput[0]; + case 0x180061: // Player 2 inputs + return DrvInput[1]; + case 0x180021: // Other inputs + return DrvInput[2]; + + case 0x180001: // Dipswitch 1 + return DrvInput[3]; + case 0x180011: // Dipswitch 2 + return DrvInput[4]; + case 0x180031: // Dipswitch 3 - Territory + return (DrvInput[5] & 0x0F) | 0x10; + + case 0x14000D: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall tekipakiReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x180050: // Player 1 inputs + return DrvInput[0]; + case 0x180060: // Player 2 inputs + return DrvInput[1]; + case 0x180020: // Other inputs + return DrvInput[2]; + + case 0x180000: // Dipswitch 1 + return DrvInput[3]; + case 0x180010: // Dipswitch 2 + return DrvInput[4]; + case 0x180030: // Dipswitch 3 - Territory + return (DrvInput[5] & 0x0F) | 0x10; + + case 0x140004: + return ToaGP9001ReadRAM_Hi(0); + case 0x140006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x14000C: + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall tekipakiWriteByte(UINT32 /*sekAddress*/, UINT8 /*byteValue*/) +{ +// switch (sekAddress) { + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); +// } +} + +void __fastcall tekipakiWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x140000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x140004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x140006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x140008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x14000C: + ToaGP9001WriteRegister(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = false; +#endif + + nGP9001ROMSize[0] = 0x800000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x080000, 0x082FFF, SM_RAM); + SekMapMemory(RamPal, 0x0c0000, 0x0c0FFF, SM_RAM); // Palette RAM + + SekSetReadWordHandler(0, tekipakiReadWord); + SekSetReadByteHandler(0, tekipakiReadByte); + SekSetWriteWordHandler(0, tekipakiWriteWord); + SekSetWriteByteHandler(0, tekipakiWriteByte); + + SekClose(); + } + + nSpriteYOffset = 0x0011; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + + // Trigger VBlank interrupt + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + } + + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvTekiPaki = { + "tekipaki", NULL, NULL, NULL, "1991", + "Teki Paki\0", "No sound (sound MCU not dumped)", "Toaplan", "Toaplan GP9001 based", + L"Teki Paki\0\u6D17\u8133\u30B2\u30FC\u30E0\0", NULL, NULL, NULL, + 1, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_PUZZLE, 0, + NULL, drvRomInfo, drvRomName, NULL, NULL, tekipakiInputInfo, tekipakiDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvWhoopee = { + "whoopee", "pipibibs", NULL, NULL, "1991", + "Pipi & Bibis / Whoopee!! (Teki Paki hardware)\0", "No sound (sound MCU not dumped)", "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + 1 | BDF_CLONE, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_PLATFORM, 0, + NULL, whoopeeRomInfo, whoopeeRomName, NULL, NULL, whoopeeInputInfo, whoopeeDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/d_truxton.cpp b/src/burn/drivers/toaplan/d_truxton.cpp new file mode 100644 index 00000000..c260f1e9 --- /dev/null +++ b/src/burn/drivers/toaplan/d_truxton.cpp @@ -0,0 +1,683 @@ +// Truxton + +#include "toaplan.h" + +#define REFRESHRATE ((28000000.0 / 4.0) / (450.0 * 270.0)) +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +// Rom information +static struct BurnRomInfo truxtonRomDesc[] = { + { "b65_11.bin", 0x020000, 0x1a62379a, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "b65_10.bin", 0x020000, 0xaff5195d, BRF_ESS | BRF_PRG }, // 1 + + { "b65_08.bin", 0x020000, 0xd2315b37, BRF_GRA }, // 2 Tile data + { "b65_07.bin", 0x020000, 0xfb83252a, BRF_GRA }, // 3 + { "b65_06.bin", 0x020000, 0x36cedcbe, BRF_GRA }, // 4 + { "b65_05.bin", 0x020000, 0x81cd95f1, BRF_GRA }, // 5 + + { "b65_04.bin", 0x020000, 0x8c6ff461, BRF_GRA }, // 6 + { "b65_03.bin", 0x020000, 0x58b1350b, BRF_GRA }, // 7 + { "b65_02.bin", 0x020000, 0x1dd55161, BRF_GRA }, // 8 + { "b65_01.bin", 0x020000, 0xe974937f, BRF_GRA }, // 9 + + { "b65_09.bin", 0x008000, 0xf1c0f410, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "b65_12.bpr", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "b65_13.bpr", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + +STD_ROM_PICK(truxton) +STD_ROM_FN(truxton) + +static struct BurnInputInfo truxtonInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(truxton) + +static struct BurnDIPInfo truxtonDIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x01, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal screen"}, + {0x12, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x04, 0x00, "Normal mode"}, + {0x12, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x12, 0x01, 0x08, 0x00, "On"}, + {0x12, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, +#if 1 + // Coinage for Europe + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "1 coin 2 play"}, + {0x12, 0x01, 0x30, 0x20, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "2 coin 3 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x80, "2 coin 1 play"}, + {0x12, 0x01, 0xC0, 0xC0, "2 coin 3 play"}, +#else + // Coinage for Japan + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x12, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x12, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, +#endif + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x13, 0x01, 0x03, 0x00, "B"}, + {0x13, 0x01, 0x03, 0x01, "A"}, + {0x13, 0x01, 0x03, 0x02, "C"}, + {0x13, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x13, 0x01, 0x0C, 0x00, "70000, every 200000"}, + {0x13, 0x01, 0x0C, 0x04, "50000, every 150000"}, + {0x13, 0x01, 0x0C, 0x08, "100000 only"}, + {0x13, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Number of heros"}, + {0x13, 0x01, 0x30, 0x30, "2"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x20, "4"}, + {0x13, 0x01, 0x30, 0x10, "5"}, + {0, 0xFE, 0, 2, "Dip Switch Display"}, + {0x13, 0x01, 0x40, 0x00, "Off"}, + {0x13, 0x01, 0x40, 0x40, "On"}, + {0, 0xFE, 0, 2, "Allow Continue"}, + {0x13, 0x01, 0x80, 0x00, "Yes"}, + {0x13, 0x01, 0x80, 0x80, "No"}, + + // Region + {0, 0xFE, 0, 5, "Region"}, + {0x14, 0x01, 0x07, 0x00, "Japan/Taito Corp"}, + {0x14, 0x01, 0x07, 0x01, "US/Romstar"}, + {0x14, 0x01, 0x07, 0x02, "World/Taito Corp"}, + {0x14, 0x01, 0x07, 0x04, "US/Taito America"}, + {0x14, 0x01, 0x07, 0x06, "World/Taito America"}, +}; + +STDDIPINFO(truxton) + +static INT32 __fastcall DrvResetCallback() +{ + // Reset instruction on 68000 + + ZetReset(); // Reset Z80 (CPU #1) + BurnYM3812Reset(); + return 0; +} + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal, *RamPal2; + +static INT32 nColCount = 0x0400; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x040000; // + RomZ80 = Next; Next += 0x008000; // Z80 ROM + BCU2ROM = Next; Next += nBCU2ROMSize; // BCU-2 tile data + FCU2ROM = Next; Next += nFCU2ROMSize; // FCU-2 tile data + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + RamPal2 = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x008000; // Z80 RAM + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029402; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nCyclesDone); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + + // Load BCU-2 tile data + ToaLoadTiles(BCU2ROM, 2, nBCU2ROMSize); + + // Load FCU-2 tile data + ToaLoadTiles(FCU2ROM, 6, nFCU2ROMSize); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 10, 1); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall truxtonZ80In(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x60: + return BurnYM3812Read(0); + case 0x40: // DIP A + return DrvInput[2]; + case 0x50: // DIP B + return DrvInput[3]; + case 0x20: // Sysytem inputs + return DrvInput[4] | (ToaVBlankRegister() << 7); + case 0x00: // Player 1 + return DrvInput[0]; + case 0x10: // Player 2 + return DrvInput[1]; + case 0x70: // Region + return DrvInput[5]; + + } + +// bprintf(PRINT_NORMAL, _T("z80 read %4X\n"), nAddress); + + return 0; +} + +void __fastcall truxtonZ80Out(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0x60: + BurnYM3812Write(0, nValue); + break; + case 0x61: + BurnYM3812Write(1, nValue); + break; + + case 0x30: // Coin counter + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 attempted to write address %04X with value %02X.\n"), nAddress, nValue); + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(truxtonZ80In); + ZetSetOutHandler(truxtonZ80Out); + + // ROM + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0x8000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0x8000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0x8000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall truxtonReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x0c0001: + case 0x140001: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Byte %06X.\n"), sekAddress); + } + } + + return 0; +} + +UINT16 __fastcall truxtonReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x0c0002: + return ToaFCU2GetRAMPointer(); + case 0x0c0004: + return ToaFCU2ReadRAM(); + case 0x0c0006: + return ToaFCU2ReadRAMSize(); + + case 0x100002: + return ToaBCU2GetRAMPointer(); + case 0x100004: + return ToaBCU2ReadRAM_Hi(); + case 0x100006: + return ToaBCU2ReadRAM_Lo(); + + case 0x100010: + case 0x100011: + case 0x100012: + case 0x100013: + case 0x100014: + case 0x100015: + case 0x100016: + case 0x100017: + case 0x100018: + case 0x100019: + case 0x10001A: + case 0x10001B: + case 0x10001C: + case 0x10001D: + case 0x10001E: + case 0x10001F: + return BCU2Reg[(sekAddress & 15) >> 1]; + + case 0x0c0000: + case 0x140000: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Word %06X.\n"), sekAddress); + } + } + + return 0; +} + +void __fastcall truxtonWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x140003: + bEnableInterrupts = byteValue; + break; + + case 0x0c0006: + ToaFCU2WriteRAMSize(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write byte %06X, %02X.\n"), sekAddress, byteValue); + } + } +} + +void __fastcall truxtonWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x0c0002: // FCU-2 set VRAM address-pointer + ToaFCU2SetRAMPointer(wordValue); + break; + case 0x0c0004: + ToaFCU2WriteRAM(wordValue); + break; + case 0x0c0006: + ToaFCU2WriteRAMSize(wordValue); + break; + + case 0x100000: // BCU-2 flip + break; + case 0x100002: // BCU-2 set VRAM address-pointer + ToaBCU2SetRAMPointer(wordValue); + break; + case 0x100004: + ToaBCU2WriteRAM(wordValue); + break; + case 0x100006: + ToaBCU2WriteRAM(wordValue); + break; + + case 0x100010: + case 0x100011: + case 0x100012: + case 0x100013: + case 0x100014: + case 0x100015: + case 0x100016: + case 0x100017: + case 0x100018: + case 0x100019: + case 0x10001A: + case 0x10001B: + case 0x10001C: + case 0x10001D: + case 0x10001E: + case 0x10001F: + BCU2Reg[(sekAddress & 15) >> 1] = wordValue; + break; + + case 0x140002: + bEnableInterrupts = (wordValue & 0xFF); + break; + + case 0x1c0000: + nBCU2TileXOffset = wordValue; + break; + case 0x1c0002: + nBCU2TileYOffset = wordValue; + break; + + case 0x1c0006: // FCU-2 flip + break; + + case 0x1d0000: + if (wordValue == 0) DrvResetCallback(); + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write word %06X, %04X.\n"), sekAddress, wordValue); + } + } +} + +// ---------------------------------------------------------------------------- + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x03FFFF, SM_ROM); // 68K ROM + SekMapMemory(Ram01, 0x080000, 0x083FFF, SM_RAM); // 68K RAM + SekMapMemory(RamPal, 0x144000, 0x1447FF, SM_RAM); // BCU-2 palette RAM + SekMapMemory(RamPal2, 0x146000, 0x1467FF, SM_RAM); // FCU-2 palette RAM + + SekSetReadWordHandler(0, truxtonReadWord); + SekSetReadByteHandler(0, truxtonReadByte); + SekSetWriteWordHandler(0, truxtonWriteWord); + SekSetWriteByteHandler(0, truxtonWriteByte); + + SekMapHandler(1, 0x180000, 0x180FFF, SM_RAM); // Z80 RAM + + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + + SekClose(); + } + + ToaInitBCU2(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalSrc2 = RamPal2; + ToaPalInit(); + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); // Render BCU2 graphics + } + + ToaPalUpdate(); // Update the palette + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[4] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[4] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { // See if this CPU is busywaiting + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + ZetClose(); + SekClose(); + +// ToaBufferFCU2Sprites(); + + return 0; +} + +struct BurnDriver BurnDrvTruxton = { + "truxton", NULL, NULL, NULL, "1988", + "Truxton\0Tatsujin\0", NULL, "[Toaplan] Taito Corporation", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, truxtonRomInfo, truxtonRomName, NULL, NULL, truxtonInputInfo, truxtonDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_truxton2.cpp b/src/burn/drivers/toaplan/d_truxton2.cpp new file mode 100644 index 00000000..8f02d361 --- /dev/null +++ b/src/burn/drivers/toaplan/d_truxton2.cpp @@ -0,0 +1,627 @@ +#include "toaplan.h" +// Truxton 2 + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; + +static const INT32 nColCount = 0x0800; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static UINT8 nIRQPending; + +static struct BurnInputInfo truxton2InputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(truxton2) + +static struct BurnDIPInfo truxton2DIPList[] = { + // Defaults + {0x14, 0xFF, 0xFE, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + {0x16, 0xFF, 0x0F, 0x02, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0F, 0x02, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B"}, + {0x15, 0x01, 0x03, 0x01, "A"}, + {0x15, 0x01, 0x03, 0x02, "C"}, + {0x15, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x15, 0x01, 0x0C, 0x00, "70000, 200000"}, + {0x15, 0x01, 0x0C, 0x04, "100000, 250000"}, + {0x15, 0x01, 0x0C, 0x08, "100000"}, + {0x15, 0x01, 0x0C, 0x0C, "200000"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x01, "5"}, + {0x15, 0x01, 0x30, 0x02, "4"}, + {0x15, 0x01, 0x30, 0x03, "2"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "No-death & stop mode"}, + {0, 0xFE, 0, 2, "Continue play"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, + + // DIP 3 + {0, 0xFE, 0, 7, "For"}, + {0x16, 0x01, 0x0F, 0x00, "Japan"}, + {0x16, 0x01, 0x0F, 0x01, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x02, "Europe"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Korea"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "South East Asia"}, + {0x16, 0x01, 0x0F, 0x07, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x08, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x09, "Korea"}, + {0x16, 0x01, 0x0F, 0x0A, "U.S.A."}, + {0x16, 0x01, 0x0F, 0x0B, ""}, + {0x16, 0x01, 0x0F, 0x0C, ""}, + {0x16, 0x01, 0x0F, 0x0D, ""}, + {0x16, 0x01, 0x0F, 0x0E, ""}, + {0x16, 0x01, 0x0F, 0x0F, "Japan"}, +}; + +STDDIPINFO(truxton2) + +UINT8 __fastcall truxton2ReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x700007: // Player 1 inputs + return DrvInput[0]; + case 0x700009: // Player 2 inputs + return DrvInput[1]; + case 0x70000B: // Other inputs + return DrvInput[2]; + case 0x700001: // Dipswitch A + return DrvInput[3]; + case 0x700003: // Dipswitch B + return DrvInput[4]; + case 0x700005: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x700011: + return MSM6295ReadStatus(0); + case 0x700017: + return BurnYM2151ReadStatus(); + + default: { +// printf("Attempt to read byte value of location %x\n", sekAddress); + + if ((sekAddress & 0x00FF0000) == 0x00500000) { + return ExtraTROM[(sekAddress & 0xFFFF) >> 1]; + } + } + } + return 0; +} + +UINT16 __fastcall truxton2ReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x200004: + return ToaGP9001ReadRAM_Hi(0); + case 0x200006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x20000C: + return ToaVBlankRegister(); + + case 0x600000: + return ToaScanlineRegister(); + + case 0x700006: // Player 1 inputs + return DrvInput[0]; + case 0x700008: // Player 2 inputs + return DrvInput[1]; + case 0x70000A: // Other inputs + return DrvInput[2]; + case 0x700000: // Dipswitch A + return DrvInput[3]; + case 0x700002: // Dipswitch B + return DrvInput[4]; + case 0x700004: // Dipswitch C - Territory + return DrvInput[5]; + + case 0x700010: + return MSM6295ReadStatus(0); + case 0x700016: + return BurnYM2151ReadStatus(); + + default: { +// printf("Attempt to read word value of location %x\n", sekAddress); + + if ((sekAddress & 0x00FF0000) == 0x00500000) { + return ExtraTROM[(sekAddress & 0xFFFF) >> 1] | (ExtraTROM[0x8000 + ((sekAddress & 0xFFFF) >> 1)] << 8); + } + } + } + return 0; +} + +void __fastcall truxton2WriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + case 0x700011: + MSM6295Command(0, byteValue); + break; + + case 0x700015: + BurnYM2151SelectRegister(byteValue); + break; + case 0x700017: + BurnYM2151WriteRegister(byteValue); + break; + + default: { +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + + if ((sekAddress & 0x00FF0000) == 0x00500000) { + ExtraTROM[(sekAddress & 0xFFFF) >> 1] = byteValue; + } + } + } +} + +void __fastcall truxton2WriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + case 0x200000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x200004: + case 0x200006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x200008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x20000C: + ToaGP9001WriteRegister(wordValue); + break; + + case 0x700010: + MSM6295Command(0, wordValue & 0xFF); + break; + case 0x700014: + BurnYM2151SelectRegister(wordValue); + break; + case 0x700016: + BurnYM2151WriteRegister(wordValue); + break; + + default: { +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + + if ((sekAddress & 0x00FF0000) == 0x00500000) { + ExtraTROM[(sekAddress & 0xFFFF) >> 1] = wordValue & 0xFF; + ExtraTROM[0x8000 + ((sekAddress & 0xFFFF) >> 1)] = wordValue << 8; + } + } + } +} + +static INT32 DrvExit() +{ + MSM6295Exit(0); + BurnYM2151Exit(); + + ToaPalExit(); + + ToaExtraTextExit(); + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + nIRQPending = 0; + SekSetIRQLine(0, SEK_IRQSTATUS_NONE); + SekReset(); + SekClose(); + + MSM6295Reset(0); + BurnYM2151Reset(); + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + ToaExtraTextLayer(); // Render extra text layer + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ +#if 1 && defined USE_SPEEDHACKS + INT32 nCurrentPC = SekGetPC(-1); + + if (!nIRQPending && nCurrentPC >= 0x00027E && nCurrentPC <= 0x000284) { + return 1; + } +#endif + + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 8; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + INT32 nSoundBufferPos = 0; + + SekOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + if (!CheckSleep(nCurrentCPU)) { + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + } + + nIRQPending = 1; + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + + ToaBufferGP9001Sprites(); + + bVBlank = true; + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nIRQPending = 0; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + if ((i & 1) == 0) { + // Render sound segment + if (pBurnSoundOut) { + INT32 nSegmentLength = (nBurnSoundLen * i / nInterleave) - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + nSoundBufferPos += nSegmentLength; + } + } + } + + { + // Make sure the buffer is entirely filled. + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + if (nSegmentLength) { + BurnYM2151Render(pSoundBuf, nSegmentLength); + MSM6295Render(0, pSoundBuf, nSegmentLength); + } + } + } + + SekClose(); + + if (pBurnDraw != NULL) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + MSM6295ROM = Next; Next += 0x080000; + RamStart = Next; + Ram01 = Next; Next += 0x010000; // CPU #0 work RAM + ExtraTROM = Next; Next += 0x010000; // Extra tile layer + ExtraTRAM = Next; Next += 0x002000; // Extra tile layer + ExtraTScroll= Next; Next += 0x001000; // + ExtraTSelect= Next; Next += 0x001000; // + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + BurnByteswap(Rom01, 0x80000); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]); + + // Load MSM6295 ADPCM data + BurnLoadRom(MSM6295ROM, 3, 1); + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + if (pnMin) { // Return minimum compatible version + *pnMin = 0x029497; + } + + if (nAction & ACB_VOLATILE) { // Scan volatile data + struct BurnArea ba; + + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + + MSM6295Scan(0, nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nIRQPending); + } + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x200000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM); + SekMapMemory(RamPal, 0x300000, 0x300FFF, SM_RAM); // Palette RAM + SekMapMemory(ExtraTRAM, 0x400000, 0x401FFF, SM_RAM); + SekMapMemory(ExtraTSelect, 0x402000, 0x402FFF, SM_RAM); // 0x502000 - Scroll; 0x502200 - RAM + SekMapMemory(ExtraTScroll, 0x403000, 0x403FFF, SM_RAM); // 0x203000 - Offset; 0x503200 - RAM + + SekSetReadWordHandler(0, truxton2ReadWord); + SekSetReadByteHandler(0, truxton2ReadByte); + SekSetWriteWordHandler(0, truxton2WriteWord); + SekSetWriteByteHandler(0, truxton2WriteByte); + + SekClose(); + } + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + nSpriteYOffset = 0x0001; + ToaInitGP9001(); + + ToaExtraTextInit(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + BurnYM2151Init(27000000 / 8, 50.0); + MSM6295Init(0, 27000000 / 10 / 132, 50.0, 1); + + bDrawScreen = true; + +#if defined FBA_DEBUG && defined USE_SPEEDHACKS + bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n")); +#endif + + DrvDoReset(); // Reset machine + + return 0; +} + +// Rom information +static struct BurnRomInfo truxton2RomDesc[] = { + { "tp024_1.bin", 0x080000, 0xf5cfe6ee, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp024_4.bin", 0x100000, 0x805C449E, BRF_GRA }, // 1 GP9001 Tile data + { "tp024_3.bin", 0x100000, 0x47587164, BRF_GRA }, // 2 + + { "tp024_2.bin", 0x080000, 0xF2F6CAE4, BRF_SND }, // 3 MSM6295 ADPCM data +}; + + +STD_ROM_PICK(truxton2) +STD_ROM_FN(truxton2) + + +struct BurnDriver BurnDrvTruxton2 = { + "truxton2", NULL, NULL, NULL, "1992", + "Truxton II\0Tatsujin Oh\0", NULL, "Toaplan", "Toaplan GP9001 based", + L"Truxton II\0\u9054\u4EBA\u738B\0", NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_ONLY, GBF_VERSHOOT, 0, + NULL, truxton2RomInfo, truxton2RomName, NULL, NULL, truxton2InputInfo, truxton2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + diff --git a/src/burn/drivers/toaplan/d_vfive.cpp b/src/burn/drivers/toaplan/d_vfive.cpp new file mode 100644 index 00000000..b8d482da --- /dev/null +++ b/src/burn/drivers/toaplan/d_vfive.cpp @@ -0,0 +1,679 @@ +#include "toaplan.h" +#include "vez.h" + +// V-Five & Grind Stormer + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static INT32 v25_reset = 0; + +// Rom information +static struct BurnRomInfo vfiveRomDesc[] = { + { "tp027_01.bin", 0x080000, 0x731D50F4, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp027_02.bin", 0x100000, 0x877B45E8, BRF_GRA }, // 1 GP9001 Tile data + { "tp027_03.bin", 0x100000, 0xB1FC6362, BRF_GRA }, // 2 +}; + + +STD_ROM_PICK(vfive) +STD_ROM_FN(vfive) + +static struct BurnRomInfo grindstmRomDesc[] = { + { "01.bin", 0x080000, 0x4923F790, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp027_02.bin", 0x100000, 0x877B45E8, BRF_GRA }, // 1 GP9001 Tile data + { "tp027_03.bin", 0x100000, 0xB1FC6362, BRF_GRA }, // 2 +}; + + +STD_ROM_PICK(grindstm) +STD_ROM_FN(grindstm) + +static struct BurnRomInfo grindstaRomDesc[] = { + { "tp027-01.rom", 0x080000, 0x8D8C0392, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + + { "tp027_02.bin", 0x100000, 0x877B45E8, BRF_GRA }, // 1 GP9001 Tile data + { "tp027_03.bin", 0x100000, 0xB1FC6362, BRF_GRA }, // 2 +}; + + +STD_ROM_PICK(grindsta) +STD_ROM_FN(grindsta) + +static struct BurnInputInfo vfiveInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 4, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(vfive) + +static struct BurnDIPInfo vfiveDIPList[] = { + // Defaults + {0x14, 0xFF, 0xFF, 0x00, NULL}, + {0x15, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x01, 0x00, "Upright"}, + {0x14, 0x01, 0x01, 0x01, "Table type"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x02, 0x00, "Normal screen"}, + {0x14, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x14, 0x01, 0x04, 0x00, "Normal mode"}, + {0x14, 0x01, 0x04, 0x04, "Test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x14, 0x01, 0x08, 0x00, "On"}, + {0x14, 0x01, 0x08, 0x08, "Off"}, + + // Normal coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x82, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x10, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x20, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0x30, 0x30, "2 coins 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x82, 0xC0, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x40, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0x80, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x82, 0xC0, 0xC0, "2 coins 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + + // European coin settings + {0, 0xFE, 0, 4, "Coin A"}, + {0x14, 0x02, 0x30, 0x00, "1 coin 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x10, "2 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x20, "3 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0x30, 0x30, "3 coins 1 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x14, 0x02, 0xC0, 0x00, "1 coin 2 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x40, "1 coin 3 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0x80, "1 coin 4 play"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + {0x14, 0x02, 0xC0, 0xC0, "1 coin 6 plays"}, + {0x16, 0x00, 0x0E, 0x08, NULL}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x15, 0x01, 0x03, 0x00, "B (normal)"}, + {0x15, 0x01, 0x03, 0x01, "A (easy)"}, + {0x15, 0x01, 0x03, 0x02, "C (hard)"}, + {0x15, 0x01, 0x03, 0x03, "D (very hard)"}, + {0, 0xFE, 0, 4, "Extend"}, + {0x15, 0x01, 0x0C, 0x00, "300,000pts 800,000pts"}, + {0x15, 0x01, 0x0C, 0x04, "300,000 800,000 every"}, + {0x15, 0x01, 0x0C, 0x08, "200,000pts only"}, + {0x15, 0x01, 0x0C, 0x0C, "No extend"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x15, 0x01, 0x30, 0x00, "3"}, + {0x15, 0x01, 0x30, 0x01, "5"}, + {0x15, 0x01, 0x30, 0x02, "2"}, + {0x15, 0x01, 0x30, 0x03, "1"}, + {0, 0xFE, 0, 2, NULL}, + {0x15, 0x01, 0x40, 0x00, "Normal game"}, + {0x15, 0x01, 0x40, 0x40, "Debug mode"}, + {0, 0xFE, 0, 2, "Continue"}, + {0x15, 0x01, 0x80, 0x00, "On"}, + {0x15, 0x01, 0x80, 0x80, "Off"}, +}; + +static struct BurnDIPInfo grindstmRegionDIPList[] = { + + {0x16, 0xFF, 0x0F, 0x00, NULL}, + {0, 0xFE, 0, 11, "Region"}, + {0x16, 0x01, 0x0F, 0x00, "Korea (Unite Trading)"}, + {0x16, 0x01, 0x0F, 0x01, "Korea"}, + {0x16, 0x01, 0x0F, 0x02, "Hong Kong (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x03, "Hong Kong"}, + {0x16, 0x01, 0x0F, 0x04, "Taiwan (Anamoto International inc.)"}, + {0x16, 0x01, 0x0F, 0x05, "Taiwan"}, + {0x16, 0x01, 0x0F, 0x06, "South East Asia (Charterfield)"}, + {0x16, 0x01, 0x0F, 0x07, "South East Asia"}, + {0x16, 0x01, 0x0F, 0x08, "Europe"}, + {0x16, 0x01, 0x0F, 0x0A, "U.S.A (American Sammy corp.)"}, + {0x16, 0x01, 0x0F, 0x0B, "U.S.A"}, + {0x16, 0x01, 0x0F, 0x09, "Europe"}, + {0x16, 0x01, 0x0F, 0x0C, "U.S.A (American Sammy corp.)"}, + {0x16, 0x01, 0x0F, 0x0D, "U.S.A"}, + {0x16, 0x01, 0x0F, 0x0E, "Korea"}, + {0x16, 0x01, 0x0F, 0x0F, "Korea"}, + +}; + +STDDIPINFO(vfive) +STDDIPINFOEXT(grindstm, vfive, grindstmRegion) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal; +static UINT8 *ShareRAM; + +static INT32 nColCount = 0x0800; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + GP9001ROM[0]= Next; Next += nGP9001ROMSize[0]; // GP9001 tile data + RamStart = Next; + Ram01 = Next; Next += 0x004000; // CPU #0 work RAM + ShareRAM = Next; Next += 0x010000; + RamPal = Next; Next += 0x001000; // palette + GP9001RAM[0]= Next; Next += 0x004000; + GP9001Reg[0]= (UINT16*)Next; Next += 0x0100 * sizeof(UINT16); + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin) { // Return minimum compatible version + *pnMin = 0x020997; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd-RamStart; + ba.szName = "All Ram"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + VezScan(nAction); + BurnYM2151Scan(nAction); + + ToaScanGP9001(nAction, pnMin); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + BurnLoadRom(Rom01, 0, 1); + + // Load GP9001 tile data + ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]); + + return 0; +} + +UINT8 __fastcall vfiveReadByte(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) + { + case 0x200011: // Player 1 inputs + return DrvInput[0]; + case 0x200015: // Player 2 inputs + return DrvInput[1]; + case 0x200019: // Other inputs + return DrvInput[2]; + + case 0x30000D: // VBlank + return ToaVBlankRegister(); + +// default: +// printf("Attempt to read byte value of location %x\n", sekAddress); + } + + return 0; +} + +UINT16 __fastcall vfiveReadWord(UINT32 sekAddress) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + return ShareRAM[(sekAddress / 2) & 0x7fff]; + } + + switch (sekAddress) + { + case 0x200010: // Player 1 inputs + return DrvInput[0]; + case 0x200014: // Player 2 inputs + return DrvInput[1]; + case 0x200018: // Other inputs + return DrvInput[2]; + + case 0x300004: + return ToaGP9001ReadRAM_Hi(0); + case 0x300006: + return ToaGP9001ReadRAM_Lo(0); + + case 0x30000C: + return ToaVBlankRegister(); + + case 0x700000: + return ToaScanlineRegister(); + +// default: +// printf("Attempt to read word value of location %x\n", sekAddress); + } + + return 0; +} + +void __fastcall vfiveWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ +//printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = byteValue; + return; + } + + switch (sekAddress) + { + case 0x20001c: + case 0x20001d: + if (!v25_reset && (~byteValue & 0x10)) VezReset(); + v25_reset = (~byteValue & 0x10); + break; + +// default: +// printf("Attempt to write byte value %x to location %x\n", byteValue, sekAddress); + } +} + +void __fastcall vfiveWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + if ((sekAddress & 0xff0000) == 0x210000) { + ShareRAM[(sekAddress / 2) & 0x7fff] = wordValue; + return; + } + + switch (sekAddress) + { + case 0x300000: // Set GP9001 VRAM address-pointer + ToaGP9001SetRAMPointer(wordValue); + break; + + case 0x300004: + ToaGP9001WriteRAM(wordValue, 0); + break; + case 0x300006: + ToaGP9001WriteRAM(wordValue, 0); + break; + + case 0x300008: + ToaGP9001SelectRegister(wordValue); + break; + + case 0x30000C: + ToaGP9001WriteRegister(wordValue); + break; + +// default: +// printf("Attempt to write word value %x to location %x\n", wordValue, sekAddress); + } +} + +void __fastcall vfive_v25_write(UINT32 address, UINT8 data) +{ + switch (address) + { + case 0x00000: + BurnYM2151SelectRegister(data); + return; + + case 0x00001: + BurnYM2151WriteRegister(data); + return; + } +} + +UINT8 __fastcall vfive_v25_read(UINT32 address) +{ + switch (address) + { + case 0x00001: + return BurnYM2151ReadStatus(); + } + + return 0; +} + +UINT8 __fastcall vfive_v25_read_port(UINT32 port) +{ + switch (port) + { + case V25_PORT_PT: + return DrvInput[3]^0xff; + + case V25_PORT_P0: + return DrvInput[4]^0xff; + + case V25_PORT_P1: + return DrvInput[5]^0xff; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + + VezOpen(0); + VezReset(); + VezClose(); + + BurnYM2151Reset(); + + v25_reset = 1; + + return 0; +} + +static UINT8 nitro_decryption_table[256] = { + 0x1b,0x56,0x75,0x88,0x8c,0x06,0x58,0x72, 0x83,0x86,0x36,0x1a,0x5f,0xd3,0x8c,0xe9, /* 00 */ + 0x22,0x0f,0x03,0x2a,0xeb,0x2a,0xf9,0x0f, 0xa4,0xbd,0x75,0xf3,0x4f,0x53,0x8e,0xfe, /* 10 */ + 0x87,0xe8,0xb1,0x8d,0x36,0xb5,0x43,0x73, 0x2a,0x5b,0xf9,0x02,0x24,0x8a,0x03,0x80, /* 20 */ + 0x86,0x8b,0xd1,0x3e,0x8d,0x3e,0x58,0xfb, 0xc3,0x79,0xbd,0xb7,0x8a,0xe8,0x0f,0x81, /* 30 */ + 0xb7,0xd0,0x8b,0xeb,0xff,0xb8,0x90,0x8b, 0x5e,0xa2,0x90,0x90,0xab,0xb4,0x80,0x59, /* 40 */ + 0x87,0x72,0xb5,0xbd,0xb0,0x88,0x50,0x0f, 0xfe,0xd2,0xc3,0x90,0x8a,0x90,0xf9,0x75, /* 50 */ + 0x1a,0xb3,0x74,0x0a,0x68,0x24,0xbb,0x90, 0x75,0x47,0xfe,0x2c,0xbe,0xc3,0x88,0xd2, /* 60 */ + 0x3e,0xc1,0x8c,0x33,0x0f,0x90,0x8b,0x90, 0xb9,0x1e,0xff,0xa2,0x3e,0x22,0xbe,0x57, /* 70 */ + 0x81,0x3a,0xf6,0x88,0xeb,0xb1,0x89,0x8a, 0x32,0x80,0x0f,0xb1,0x48,0xc3,0x68,0x72, /* 80 */ + 0x53,0x02,0xc0,0x02,0xe8,0xb4,0x74,0xbc, 0x90,0x58,0x0a,0xf3,0x75,0xc6,0x90,0xe8, /* 90 */ + 0x26,0x50,0xfc,0x8c,0x90,0xb1,0xc3,0xd1, 0xeb,0x83,0xa4,0xbf,0x26,0x4b,0x46,0xfe, /* a0 */ + 0xe2,0x89,0xb3,0x88,0x03,0x56,0x0f,0x38, 0xbb,0x0c,0x90,0x0f,0x07,0x8a,0x8a,0x33, /* b0 */ + 0xfe,0xf9,0xb1,0xa0,0x45,0x36,0x22,0x5e, 0x8a,0xbe,0xc6,0xea,0x3c,0xb2,0x1e,0xe8, /* c0 */ + 0x90,0xeb,0x55,0xf6,0x8a,0xb0,0x5d,0xc0, 0xbb,0x8d,0xf6,0xd0,0xd1,0x88,0x4d,0x90, /* d0 */ + 0x51,0x51,0x74,0xbd,0x32,0xd1,0x90,0xd2, 0x53,0xc7,0xab,0x36,0x50,0xe9,0x33,0xb3, /* e0 */ + 0x2e,0x05,0x88,0x59,0x74,0x74,0x22,0x8e, 0x8a,0x8a,0x36,0x08,0x0f,0x45,0x90,0x2e, /* f0 */ +}; + +static INT32 DrvInit() +{ + INT32 nLen; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + nGP9001ROMSize[0] = 0x200000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM + SekMapMemory(Ram01, 0x100000, 0x103FFF, SM_RAM); + // SekMapMemory(ShareRAM, 0x210000, 0x21ffff, SM_RAM); + SekMapMemory(RamPal, 0x400000, 0x400FFF, SM_RAM); // Palette RAM + SekSetReadWordHandler(0, vfiveReadWord); + SekSetReadByteHandler(0, vfiveReadByte); + SekSetWriteWordHandler(0, vfiveWriteWord); + SekSetWriteByteHandler(0, vfiveWriteByte); + SekClose(); + + VezInit(0, V25_TYPE, 10000000 /*before divider*/); + VezOpen(0); + for (INT32 i = 0x80000; i < 0x100000; i += 0x8000) { + VezMapArea(i, i + 0x7fff, 0, ShareRAM); + VezMapArea(i, i + 0x7fff, 1, ShareRAM); + VezMapArea(i, i + 0x7fff, 2, ShareRAM); + } + VezSetReadHandler(vfive_v25_read); + VezSetWriteHandler(vfive_v25_write); + VezSetReadPort(vfive_v25_read_port); + VezSetDecode(nitro_decryption_table); + VezClose(); + } + + BurnYM2151Init(3375000, 100.0); + + nSpriteYOffset = 0x0001; + + nLayer0XOffset = -0x01D6; + nLayer1XOffset = -0x01D8; + nLayer2XOffset = -0x01DA; + + ToaInitGP9001(); + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalInit(); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + ToaPalExit(); + + ToaExitGP9001(); + SekExit(); // Deallocate 68000s + VezExit(); + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderGP9001(); // Render GP9001 graphics + } + + ToaPalUpdate(); // Update the palette + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 10; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[2] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[2] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekNewFrame(); + VezNewFrame(); + + INT32 nSoundBufferPos = 0; + + nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesTotal[1] = (INT32)((INT64)5000000 * nBurnCPUSpeedAdjust / (0x0100 * 60)); + nCyclesDone[0] = 0; + nCyclesDone[1] = 0; + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + SekOpen(0); + VezOpen(0); + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nCurrentCPU; + INT32 nNext; + + // Run 68000 + nCurrentCPU = 0; + nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave; + + + // Trigger VBlank interrupt + if (!bVBlank && nNext > nToaCyclesVBlankStart) { + if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU]; + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } + + bVBlank = true; + + ToaBufferGP9001Sprites(); + + // Trigger VBlank interrupt + SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); + } + + nCyclesSegment = nNext - nCyclesDone[nCurrentCPU]; + if (bVBlank || (!CheckSleep(nCurrentCPU))) { // See if this CPU is busywaiting + nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment); + } else { + nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment); + } + + // sound! (increase interleave?) + if (v25_reset) { + nCyclesDone[1] += nCyclesTotal[1] / nInterleave; + } else { + nCyclesDone[1] += VezRun(nCyclesTotal[1] / nInterleave); + } + } + + if (pBurnSoundOut) { + INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos; + if (nSegmentLength) { + INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1); + BurnYM2151Render(pSoundBuf, nSegmentLength); + } + } + + VezClose(); + SekClose(); + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + return 0; +} + +struct BurnDriver BurnDrvVFive = { + "vfive", "grindstm", NULL, NULL, "1993", + "V-Five (Japan)\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, vfiveRomInfo, vfiveRomName, NULL, NULL, vfiveInputInfo, vfiveDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvGrindStormer = { + "grindstm", NULL, NULL, NULL, "1992", + "Grind Stormer\0", NULL, "Toaplan", "Toaplan GP9001 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, grindstmRomInfo, grindstmRomName, NULL, NULL, vfiveInputInfo, grindstmDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + +struct BurnDriver BurnDrvGrindStormerA = { + "grindstma", "grindstm", NULL, NULL, "1992", + "Grind Stormer (older set)\0", NULL, "Toaplan GP9001 based", "Toaplan", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_68K_Zx80, GBF_VERSHOOT, 0, + NULL, grindstaRomInfo, grindstaRomName, NULL, NULL, vfiveInputInfo, grindstmDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + diff --git a/src/burn/drivers/toaplan/d_vimana.cpp b/src/burn/drivers/toaplan/d_vimana.cpp new file mode 100644 index 00000000..186e90a1 --- /dev/null +++ b/src/burn/drivers/toaplan/d_vimana.cpp @@ -0,0 +1,693 @@ +#include "toaplan.h" + +#define REFRESHRATE 57.59 +#define VBLANK_LINES (32) + +static UINT8 *AllMem; +static UINT8 *MemEnd; +static UINT8 *AllRam; +static UINT8 *RamEnd; +static UINT8 *Drv68KROM; +static UINT8 *Drv68KRAM; +static UINT8 *DrvPalRAM; +static UINT8 *DrvPalRAM2; + +static INT32 nColCount = 0x0800; + +static UINT8 DrvInputs[3]; +static UINT8 DrvDips[3]; +static UINT8 DrvJoy1[8]; +static UINT8 DrvJoy2[8]; +static UINT8 DrvJoy3[8]; +static UINT8 DrvReset; + +static INT32 vimana_latch; +static INT32 vimana_credits; + +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +static struct BurnInputInfo VimanaInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 3, "p1 coin" }, + {"P1 Start", BIT_DIGITAL, DrvJoy3 + 5, "p1 start" }, + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up" }, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down" }, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left" }, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right" }, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" }, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" }, + {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" }, + + {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p2 coin" }, + {"P2 Start", BIT_DIGITAL, DrvJoy3 + 6, "p2 start" }, + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up" }, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down" }, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left" }, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right" }, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" }, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" }, + {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" }, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset" }, + {"Service", BIT_DIGITAL, DrvJoy3 + 0, "service" }, + {"Tilt", BIT_DIGITAL, DrvJoy3 + 1, "tilt" }, + {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" }, + {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, + {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" }, +}; + +STDINPUTINFO(Vimana) + +static struct BurnDIPInfo VimanaDIPList[]= +{ + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 2, "Demo Sounds" }, + {0x15, 0x01, 0x08, 0x08, "Off" }, + {0x15, 0x01, 0x08, 0x00, "On" }, + + {0 , 0xfe, 0 , 4, "Coin A" }, + {0x15, 0x01, 0x30, 0x30, "4 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x20, "3 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x10, "2 Coins 1 Credits" }, + {0x15, 0x01, 0x30, 0x00, "1 Coin 1 Credits" }, + + {0 , 0xfe, 0 , 4, "Coin B" }, + {0x15, 0x01, 0xc0, 0x00, "1 Coin 2 Credits" }, + {0x15, 0x01, 0xc0, 0x40, "1 Coin 3 Credits" }, + {0x15, 0x01, 0xc0, 0x80, "1 Coin 4 Credits" }, + {0x15, 0x01, 0xc0, 0xc0, "1 Coin 6 Credits" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + {0x16, 0x01, 0x03, 0x00, "Medium" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x00, "70K and 200K" }, + {0x16, 0x01, 0x0c, 0x04, "100K and 250K" }, + {0x16, 0x01, 0x0c, 0x08, "100K" }, + {0x16, 0x01, 0x0c, 0x0c, "200K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x30, "2" }, + {0x16, 0x01, 0x30, 0x00, "3" }, + {0x16, 0x01, 0x30, 0x20, "4" }, + {0x16, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "No" }, + {0x16, 0x01, 0x80, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 10, "Territory / License" }, + {0x17, 0x01, 0x0f, 0x00, "Japan (Distributed by Tecmo)" }, + {0x17, 0x01, 0x0f, 0x01, "US" }, + {0x17, 0x01, 0x0f, 0x02, "Europe" }, + {0x17, 0x01, 0x0f, 0x03, "Hong Kong" }, + {0x17, 0x01, 0x0f, 0x04, "Korea" }, + {0x17, 0x01, 0x0f, 0x05, "Taiwan" }, + {0x17, 0x01, 0x0f, 0x06, "Taiwan (Spacy License)" }, + {0x17, 0x01, 0x0f, 0x07, "US (Romstar License)" }, + {0x17, 0x01, 0x0f, 0x08, "Hong Kong (Honest Trading Co. License)" }, + {0x17, 0x01, 0x0f, 0x0f, "Japan (Distributed by Tecmo)" }, +}; + +STDDIPINFO(Vimana) + +static struct BurnDIPInfo VimananDIPList[]= +{ + {0x15, 0xff, 0xff, 0x00, NULL }, + {0x16, 0xff, 0xff, 0x00, NULL }, + {0x17, 0xff, 0xff, 0x02, NULL }, + + {0 , 0xfe, 0 , 2, "Flip Screen" }, + {0x15, 0x01, 0x02, 0x00, "Off" }, + {0x15, 0x01, 0x02, 0x02, "On" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x16, 0x01, 0x03, 0x01, "Easy" }, + {0x16, 0x01, 0x03, 0x00, "Medium" }, + {0x16, 0x01, 0x03, 0x02, "Hard" }, + {0x16, 0x01, 0x03, 0x03, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Bonus Life" }, + {0x16, 0x01, 0x0c, 0x00, "70K and 200K" }, + {0x16, 0x01, 0x0c, 0x04, "100K and 250K" }, + {0x16, 0x01, 0x0c, 0x08, "100K" }, + {0x16, 0x01, 0x0c, 0x0c, "200K" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x16, 0x01, 0x30, 0x30, "2" }, + {0x16, 0x01, 0x30, 0x00, "3" }, + {0x16, 0x01, 0x30, 0x20, "4" }, + {0x16, 0x01, 0x30, 0x10, "5" }, + + {0 , 0xfe, 0 , 2, "Invulnerability" }, + {0x16, 0x01, 0x40, 0x00, "Off" }, + {0x16, 0x01, 0x40, 0x40, "On" }, + + {0 , 0xfe, 0 , 2, "Allow Continue" }, + {0x16, 0x01, 0x80, 0x80, "No" }, + {0x16, 0x01, 0x80, 0x00, "Yes" }, + + {0 , 0xfe, 0 , 9, "Territory / License" }, + {0x17, 0x01, 0x0f, 0x00, "Japan (Distributed by Tecmo)" }, + {0x17, 0x01, 0x0f, 0x01, "US" }, + {0x17, 0x01, 0x0f, 0x02, "Europe (Nova Apparate GMBH License)" }, + {0x17, 0x01, 0x0f, 0x03, "Hong Kong" }, + {0x17, 0x01, 0x0f, 0x04, "Korea" }, + {0x17, 0x01, 0x0f, 0x05, "Taiwan" }, + {0x17, 0x01, 0x0f, 0x06, "Taiwan (Spacy License)" }, + {0x17, 0x01, 0x0f, 0x07, "US (Romstar License)" }, + {0x17, 0x01, 0x0f, 0x08, "Hong Kong (Honest Trading Co. License)" }, +}; + +STDDIPINFO(Vimanan) + +void __fastcall vimanaWriteWord(UINT32 a, UINT16 d) +{ + switch (a) + { + case 0x080000: + nBCU2TileXOffset = d; + return; + + case 0x080002: + nBCU2TileYOffset = d; + return; + + case 0x080006: + // toaplan1_fcu_flipscreen_w + return; + + case 0x0c0000: + return; // nop + + case 0x0c0002: + ToaFCU2SetRAMPointer(d); + return; + + case 0x0c0004: + ToaFCU2WriteRAM(d); + return; + + case 0x0c0006: + ToaFCU2WriteRAMSize(d); + return; + + case 0x400000: + return; // nop + + case 0x400002: + bEnableInterrupts = (d & 0xFF); + return; + + case 0x400008: + case 0x40000a: + case 0x40000c: + case 0x40000e: + // toaplan1_bcu_control_w + return; + + case 0x440000: + case 0x440002: + return; + + case 0x440004: + vimana_credits = d & 0xff; + return; + + case 0x4c0000: + // toaplan1_bcu_flipscreen_w + return; + + case 0x4c0002: + ToaBCU2SetRAMPointer(d); + return; + + case 0x4c0004: + case 0x4c0006: + ToaBCU2WriteRAM(d); + return; + + case 0x4c0010: + case 0x4c0012: + case 0x4c0014: + case 0x4c0016: + case 0x4c0018: + case 0x4c001a: + case 0x4c001c: + case 0x4c001e: + BCU2Reg[(a & 0x0f) >> 1] = d; + return; + } + + bprintf (0, _T("%5.5x %4.4x ww\n"), a, d); +} + +void __fastcall vimanaWriteByte(UINT32 , UINT8 ) +{ + return; +} + +UINT16 __fastcall vimanaReadWord(UINT32 a) +{ + switch (a) + { + case 0x0c0002: + return ToaFCU2GetRAMPointer(); + + case 0x0c0004: + return ToaFCU2ReadRAM(); + + case 0x0c0006: + return ToaFCU2ReadRAMSize(); + + case 0x4c0002: + return ToaBCU2GetRAMPointer(); + + case 0x4c0004: + return ToaBCU2ReadRAM_Hi(); + + case 0x4c0006: + return ToaBCU2ReadRAM_Lo(); + + case 0x4c0010: + case 0x4c0012: + case 0x4c0014: + case 0x4c0016: + case 0x4c0018: + case 0x4c001a: + case 0x4c001c: + case 0x4c001e: + return BCU2Reg[(a & 0x0f) >> 1]; + } + + return 0; +} + +UINT8 __fastcall vimanaReadByte(UINT32 a) +{ + switch (a) + { + case 0x0c0001: + case 0x400001: + return ToaVBlankRegister(); + + case 0x440001: + return 0xff; + + case 0x440003: + return 0; + + case 0x440005: + return vimana_credits; + + case 0x440007: + return DrvDips[0]; + + case 0x440009: + { + INT32 p = DrvInputs[2]; + vimana_latch ^= p; + p = vimana_latch & p; + + if (p & 0x18) { + vimana_credits++; + } + vimana_latch = p; + + return p; + } + + case 0x44000b: + return DrvInputs[0]; + + case 0x44000d: + return DrvInputs[1]; + + case 0x44000f: + return DrvDips[1]; + + case 0x440011: + return DrvDips[2]; + } + + return 0; +} + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + +// BurnYM3812Reset(); + + bEnableInterrupts = false; + + vimana_latch = 0; + vimana_credits = 0; + + return 0; +} + +static INT32 MemIndex() +{ + UINT8 *Next; Next = AllMem; + + Drv68KROM = Next; Next += 0x040000; + BCU2ROM = Next; Next += nBCU2ROMSize; + FCU2ROM = Next; Next += nFCU2ROMSize; + + AllRam = Next; + + Drv68KRAM = Next; Next += 0x008000; + DrvPalRAM = Next; Next += 0x000800; + DrvPalRAM2 = Next; Next += 0x000800; + + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + + RamEnd = Next; + + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + + MemEnd = Next; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + +// bToaRotateScreen = true; + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x100000; + + // Find out how much memory is needed + AllMem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(AllMem, 0, nLen); + MemIndex(); + + ToaLoadCode(Drv68KROM, 0, 2); + ToaLoadTiles(BCU2ROM, 2, nBCU2ROMSize); + ToaLoadGP9001Tiles(FCU2ROM, 6, 3, nFCU2ROMSize); + + { + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03FFFF, SM_ROM); + SekMapMemory(DrvPalRAM, 0x404000, 0x4047FF, SM_RAM); + SekMapMemory(DrvPalRAM2, 0x406000, 0x4067FF, SM_RAM); + SekMapMemory(Drv68KRAM, 0x480000, 0x487FFF, SM_RAM); + SekSetReadWordHandler(0, vimanaReadWord); + SekSetReadByteHandler(0, vimanaReadByte); + SekSetWriteWordHandler(0, vimanaWriteWord); + SekSetWriteByteHandler(0, vimanaWriteByte); + SekClose(); + } + + ToaInitBCU2(); + + nToaPalLen = nColCount; + ToaPalSrc = DrvPalRAM; + ToaPalSrc2 = DrvPalRAM2; + ToaPalInit(); + +// BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + + bDrawScreen = true; + + DrvDoReset(); + return 0; +} + +static INT32 DrvExit() +{ +// BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); + SekExit(); + + if (AllMem) { + free(AllMem); + AllMem = NULL; + } + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); + } + + ToaPalUpdate(); + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { + DrvDoReset(); + } + + memset (DrvInputs, 0, 3); + for (INT32 i = 0; i < 8; i++) { + DrvInputs[0] |= (DrvJoy1[i] & 1) << i; + DrvInputs[1] |= (DrvJoy2[i] & 1) << i; + DrvInputs[2] |= (DrvJoy3[i] & 1) << i; + } + ToaClearOpposites(&DrvInputs[0]); + ToaClearOpposites(&DrvInputs[1]); + + SekOpen(0); + + SekNewFrame(); + + SekIdle(nCyclesDone[0]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); +// BurnTimerEndFrameYM3812(nCyclesTotal[1]); +// BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + SekClose(); + +// ToaBufferFCU2Sprites(); + + return 0; +} + +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = AllRam; + ba.nLen = RamEnd - AllRam; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); + + // BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(nCyclesDone); + + SCAN_VAR(vimana_credits); + SCAN_VAR(vimana_latch); + } + + return 0; +} + + +// Vimana + +static struct BurnRomInfo vimanaRomDesc[] = { + { "tp019-7a.bin", 0x20000, 0x5a4bf73e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp019-8a.bin", 0x20000, 0x03ba27e8, BRF_ESS | BRF_PRG }, // 1 + + { "vim6.bin", 0x20000, 0x2886878d, BRF_GRA }, // 2 Tile data + { "vim5.bin", 0x20000, 0x61a63d7a, BRF_GRA }, // 3 + { "vim4.bin", 0x20000, 0xb0515768, BRF_GRA }, // 4 + { "vim3.bin", 0x20000, 0x0b539131, BRF_GRA }, // 5 + + { "vim1.bin", 0x80000, 0xcdde26cd, BRF_GRA }, // 6 + { "vim2.bin", 0x80000, 0x1dbfc118, BRF_GRA }, // 7 + + { "tp019-09.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 8 Sprite attribute PROM + { "tp019-10.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 9 + + { "hd647180.019", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 10 Sound HD647180 code +}; + +STD_ROM_PICK(vimana) +STD_ROM_FN(vimana) + +struct BurnDriver BurnDrvVimana = { + "vimana", NULL, NULL, NULL, "1991", + "Vimana\0", "No sound", "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, vimanaRomInfo, vimanaRomName, NULL, NULL, VimanaInputInfo, VimanaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Vimana (old set) + +static struct BurnRomInfo vimana1RomDesc[] = { + { "vim07.bin", 0x20000, 0x1efaea84, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "vim08.bin", 0x20000, 0xe45b7def, BRF_ESS | BRF_PRG }, // 1 + + { "vim6.bin", 0x20000, 0x2886878d, BRF_GRA }, // 2 Tile data + { "vim5.bin", 0x20000, 0x61a63d7a, BRF_GRA }, // 3 + { "vim4.bin", 0x20000, 0xb0515768, BRF_GRA }, // 4 + { "vim3.bin", 0x20000, 0x0b539131, BRF_GRA }, // 5 + + { "vim1.bin", 0x80000, 0xcdde26cd, BRF_GRA }, // 6 + { "vim2.bin", 0x80000, 0x1dbfc118, BRF_GRA }, // 7 + + { "tp019-09.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 8 Sprite attribute PROM + { "tp019-10.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 9 + + { "hd647180.019", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 10 Sound HD647180 code +}; + +STD_ROM_PICK(vimana1) +STD_ROM_FN(vimana1) + +struct BurnDriver BurnDrvVimana1 = { + "vimana1", "vimana", NULL, NULL, "1991", + "Vimana (old set)\0", "No sound", "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, vimana1RomInfo, vimana1RomName, NULL, NULL, VimanaInputInfo, VimanaDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; + + +// Vimana (Nova Apparate GMBH & Co) + +static struct BurnRomInfo vimananRomDesc[] = { + { "tp019-07.rom", 0x20000, 0x78888ff2, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "tp019-08.rom", 0x20000, 0x6cd2dc3c, BRF_ESS | BRF_PRG }, // 1 + + { "vim6.bin", 0x20000, 0x2886878d, BRF_GRA }, // 2 Tile data + { "vim5.bin", 0x20000, 0x61a63d7a, BRF_GRA }, // 3 + { "vim4.bin", 0x20000, 0xb0515768, BRF_GRA }, // 4 + { "vim3.bin", 0x20000, 0x0b539131, BRF_GRA }, // 5 + + { "vim1.bin", 0x80000, 0xcdde26cd, BRF_GRA }, // 6 + { "vim2.bin", 0x80000, 0x1dbfc118, BRF_GRA }, // 7 + + { "tp019-09.bpr", 0x00020, 0xbc88cced, BRF_GRA }, // 8 Sprite attribute PROM + { "tp019-10.bpr", 0x00020, 0xa1e17492, BRF_GRA }, // 9 + + { "hd647180.019", 0x08000, 0x00000000, BRF_OPT | BRF_NODUMP }, // 10 Sound HD647180 code +}; + +STD_ROM_PICK(vimanan) +STD_ROM_FN(vimanan) + +struct BurnDriver BurnDrvVimanan = { + "vimanan", "vimana", NULL, NULL, "1991", + "Vimana (Nova Apparate GMBH & Co)\0", "No sound", "Toaplan (Nova Apparate GMBH & Co license)", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | TOA_ROTATE_GRAPHICS_CCW, 2, HARDWARE_TOAPLAN_RAIZING, GBF_VERSHOOT, 0, + NULL, vimananRomInfo, vimananRomName, NULL, NULL, VimanaInputInfo, VimananDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800, + 240, 320, 3, 4 +}; diff --git a/src/burn/drivers/toaplan/d_zerowing.cpp b/src/burn/drivers/toaplan/d_zerowing.cpp new file mode 100644 index 00000000..b48db697 --- /dev/null +++ b/src/burn/drivers/toaplan/d_zerowing.cpp @@ -0,0 +1,756 @@ +// Zero Wing + +#include "toaplan.h" + +#define REFRESHRATE 60 +#define VBLANK_LINES (32) + +static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static UINT8 DrvReset = 0; +static UINT8 bDrawScreen; +static bool bVBlank; + +static bool bEnableInterrupts; + +// Rom information +static struct BurnRomInfo zerowingRomDesc[] = { + { "o15-11.rom", 0x008000, 0x6ff2b9a0, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "o15-12.rom", 0x008000, 0x9773e60b, BRF_ESS | BRF_PRG }, // 1 + { "o15-09.rom", 0x020000, 0x13764e95, BRF_ESS | BRF_PRG }, // 1 + { "o15-10.rom", 0x020000, 0x351ba71a, BRF_ESS | BRF_PRG }, // 1 + + { "o15-05.rom", 0x020000, 0x4e5dd246, BRF_GRA }, // 6 + { "o15-06.rom", 0x020000, 0xc8c6d428, BRF_GRA }, // 7 + { "o15-07.rom", 0x020000, 0xefc40e99, BRF_GRA }, // 8 + { "o15-08.rom", 0x020000, 0x1b019eab, BRF_GRA }, // 9 + + { "o15-03.rom", 0x020000, 0x7f245fd3, BRF_GRA }, // 2 + { "o15-04.rom", 0x020000, 0x0b1a1289, BRF_GRA }, // 3 + { "o15-01.rom", 0x020000, 0x70570e43, BRF_GRA }, // 4 + { "o15-02.rom", 0x020000, 0x724b487f, BRF_GRA }, // 5 + + { "o15-13.rom", 0x008000, 0xe7b72383, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "tp015_14.bpr", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "tp015_15.bpr", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + + +STD_ROM_PICK(zerowing) +STD_ROM_FN(zerowing) + +static struct BurnRomInfo zerowng2RomDesc[] = { + { "o15-11iiw.bin",0x008000, 0x38b0bb5b, BRF_ESS | BRF_PRG }, // 0 CPU #0 code + { "o15-12iiw.bin",0x008000, 0x74c91e6f, BRF_ESS | BRF_PRG }, // 1 + { "o15-09.rom", 0x020000, 0x13764e95, BRF_ESS | BRF_PRG }, // 1 + { "o15-10.rom", 0x020000, 0x351ba71a, BRF_ESS | BRF_PRG }, // 1 + + { "o15-05.rom", 0x020000, 0x4e5dd246, BRF_GRA }, // 6 + { "o15-06.rom", 0x020000, 0xc8c6d428, BRF_GRA }, // 7 + { "o15-07.rom", 0x020000, 0xefc40e99, BRF_GRA }, // 8 + { "o15-08.rom", 0x020000, 0x1b019eab, BRF_GRA }, // 9 + + { "o15-03.rom", 0x020000, 0x7f245fd3, BRF_GRA }, // 2 + { "o15-04.rom", 0x020000, 0x0b1a1289, BRF_GRA }, // 3 + { "o15-01.rom", 0x020000, 0x70570e43, BRF_GRA }, // 4 + { "o15-02.rom", 0x020000, 0x724b487f, BRF_GRA }, // 5 + + { "o15-13.rom", 0x008000, 0xe7b72383, BRF_ESS | BRF_PRG }, // 10 Z80 program + + { "tp015_14.bpr", 0x000020, 0xbc88cced, BRF_SND }, // 11 Sprite attribute PROM + { "tp015_15.bpr", 0x000020, 0xa1e17492, BRF_SND }, // 12 ??? +}; + + +STD_ROM_PICK(zerowng2) +STD_ROM_FN(zerowng2) + +static struct BurnInputInfo zerowingInputList[] = { + {"P1 Coin", BIT_DIGITAL, DrvButton + 3, "p1 coin"}, + {"P1 Start", BIT_DIGITAL, DrvButton + 5, "p1 start"}, + + {"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"}, + {"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"}, + {"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"}, + {"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"}, + {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"}, + {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"}, + + {"P2 Coin", BIT_DIGITAL, DrvButton + 4, "p2 coin"}, + {"P2 Start", BIT_DIGITAL, DrvButton + 6, "p2 start"}, + + {"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"}, + {"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"}, + {"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"}, + {"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"}, + {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"}, + {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"}, + + {"Reset", BIT_DIGITAL, &DrvReset, "reset"}, + {"Diagnostics", BIT_DIGITAL, DrvButton + 0, "diag"}, + {"Dip A", BIT_DIPSWITCH, DrvInput + 2, "dip"}, + {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip"}, + {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip"}, +}; + +STDINPUTINFO(zerowing) + +static struct BurnDIPInfo zerowingDIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x01, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x02, NULL}, + + // DIP 1 + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal screen"}, + {0x12, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x04, 0x00, "Normal mode"}, + {0x12, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x12, 0x01, 0x08, 0x00, "On"}, + {0x12, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x12, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x12, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x13, 0x01, 0x03, 0x00, "B"}, + {0x13, 0x01, 0x03, 0x01, "A"}, + {0x13, 0x01, 0x03, 0x02, "C"}, + {0x13, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x13, 0x01, 0x0C, 0x00, "200000, every 500000"}, + {0x13, 0x01, 0x0C, 0x04, "500000, every 1000000"}, + {0x13, 0x01, 0x0C, 0x08, "500000 only"}, + {0x13, 0x01, 0x0C, 0x0C, "Never"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x13, 0x01, 0x30, 0x30, "2"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x20, "4"}, + {0x13, 0x01, 0x30, 0x10, "5"}, + {0, 0xFE, 0, 2, NULL}, + {0x13, 0x01, 0x40, 0x00, "Normal Game"}, + {0x13, 0x01, 0x40, 0x40, "No death & stop mode"}, + {0, 0xFE, 0, 2, "Allow Continue"}, + {0x13, 0x01, 0x80, 0x00, "Yes"}, + {0x13, 0x01, 0x80, 0x80, "No"}, + + // Region + {0, 0xFE, 0, 3, "Region"}, + {0x14, 0x01, 0x03, 0x00, "Japan"}, + {0x14, 0x01, 0x03, 0x01, "US"}, + {0x14, 0x01, 0x03, 0x02, "Europe"}, +}; + +STDDIPINFO(zerowing) + +static struct BurnDIPInfo zerowng2DIPList[] = { + // Defaults + {0x12, 0xFF, 0xFF, 0x01, NULL}, + {0x13, 0xFF, 0xFF, 0x00, NULL}, + {0x14, 0xFF, 0xFF, 0x00, NULL}, + + // DIP 1 + {0x12, 0x01, 0x01, 0x01, "Upright"}, + {0x12, 0x01, 0x01, 0x00, "Cocktail"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x02, 0x00, "Normal screen"}, + {0x12, 0x01, 0x02, 0x02, "Invert screen"}, + {0, 0xFE, 0, 2, NULL}, + {0x12, 0x01, 0x04, 0x00, "Normal mode"}, + {0x12, 0x01, 0x04, 0x04, "Screen test mode"}, + {0, 0xFE, 0, 2, "Advertise sound"}, + {0x12, 0x01, 0x08, 0x00, "On"}, + {0x12, 0x01, 0x08, 0x08, "Off"}, + {0, 0xFE, 0, 4, "Coin A"}, + {0x12, 0x01, 0x30, 0x00, "1 coin 1 play"}, + {0x12, 0x01, 0x30, 0x10, "2 coin 1 play"}, + {0x12, 0x01, 0x30, 0x20, "3 coin 1 play"}, + {0x12, 0x01, 0x30, 0x30, "4 coin 1 play"}, + {0, 0xFE, 0, 4, "Coin B"}, + {0x12, 0x01, 0xC0, 0x00, "1 coin 2 play"}, + {0x12, 0x01, 0xC0, 0x40, "1 coin 3 play"}, + {0x12, 0x01, 0xC0, 0x80, "1 coin 4 play"}, + {0x12, 0x01, 0xC0, 0xC0, "1 coin 6 play"}, + + // DIP 2 + {0, 0xFE, 0, 4, "Game difficulty"}, + {0x13, 0x01, 0x03, 0x00, "B"}, + {0x13, 0x01, 0x03, 0x01, "A"}, + {0x13, 0x01, 0x03, 0x02, "C"}, + {0x13, 0x01, 0x03, 0x03, "D"}, + {0, 0xFE, 0, 4, "Extend bonus"}, + {0x13, 0x01, 0x0C, 0x00, "200000, every 500000"}, + {0x13, 0x01, 0x0C, 0x04, "500000, every 1000000"}, + {0x13, 0x01, 0x0C, 0x08, "500000 only"}, + {0x13, 0x01, 0x0C, 0x0C, "Never"}, + {0, 0xFE, 0, 4, "Hero counts"}, + {0x13, 0x01, 0x30, 0x30, "2"}, + {0x13, 0x01, 0x30, 0x00, "3"}, + {0x13, 0x01, 0x30, 0x20, "4"}, + {0x13, 0x01, 0x30, 0x10, "5"}, + {0, 0xFE, 0, 2, NULL}, + {0x13, 0x01, 0x40, 0x00, "Normal Game"}, + {0x13, 0x01, 0x40, 0x40, "No death & stop mode"}, + {0, 0xFE, 0, 2, "Allow Continue"}, + {0x13, 0x01, 0x80, 0x00, "Yes"}, + {0x13, 0x01, 0x80, 0x80, "No"}, +}; + +STDDIPINFO(zerowng2) + +static UINT8 *Mem = NULL, *MemEnd = NULL; +static UINT8 *RamStart, *RamEnd; +static UINT8 *Rom01; +static UINT8 *Ram01, *RamPal, *RamPal2; + +static INT32 nColCount = 0x0400; + +// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0), +// and then afterwards to set up all the pointers +static INT32 MemIndex() +{ + UINT8 *Next; Next = Mem; + Rom01 = Next; Next += 0x080000; // + RomZ80 = Next; Next += 0x008000; // Z80 ROM + BCU2ROM = Next; Next += nBCU2ROMSize; // BCU-2 tile data + FCU2ROM = Next; Next += nFCU2ROMSize; // FCU-2 tile data + RamStart = Next; + Ram01 = Next; Next += 0x008000; // CPU #0 work RAM + RamPal = Next; Next += 0x001000; // palette + RamPal2 = Next; Next += 0x001000; // palette + RamZ80 = Next; Next += 0x008000; // Z80 RAM + BCU2RAM = Next; Next += 0x010000; + FCU2RAM = Next; Next += 0x000800; + FCU2RAMSize = Next; Next += 0x000080; + RamEnd = Next; + ToaPalette = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + ToaPalette2 = (UINT32 *)Next; Next += nColCount * sizeof(UINT32); + MemEnd = Next; + + return 0; +} + +// Scan ram +static INT32 DrvScan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { // Return minimum compatible version + *pnMin = 0x029402; + } + if (nAction & ACB_VOLATILE) { // Scan volatile ram + memset(&ba, 0, sizeof(ba)); + ba.Data = RamStart; + ba.nLen = RamEnd - RamStart; + ba.szName = "RAM"; + BurnAcb(&ba); + + SekScan(nAction); // scan 68000 states + ZetScan(nAction); // Scan Z80 + + BurnYM3812Scan(nAction, pnMin); + + SCAN_VAR(DrvInput); + SCAN_VAR(nCyclesDone); + } + + return 0; +} + +static INT32 LoadRoms() +{ + // Load 68000 ROM + ToaLoadCode(Rom01, 0, 2); + BurnLoadRom(Rom01 + 0x40001, 2, 2); + BurnLoadRom(Rom01 + 0x40000, 3, 2); + + // Load BCU-2 tile data + ToaLoadTiles(BCU2ROM, 4, nBCU2ROMSize); + + // Load FCU-2 tile data + ToaLoadTiles(FCU2ROM, 8, nFCU2ROMSize); + + // Load the Z80 ROM + BurnLoadRom(RomZ80, 12, 1); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall zerowingZ80In(UINT16 nAddress) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0xa8: + return BurnYM3812Read(0); + case 0x20: // DIP A + return DrvInput[2]; + case 0x28: // DIP B + return DrvInput[3]; + case 0x80: // Sysytem inputs + return DrvInput[4] | (ToaVBlankRegister() << 7); + case 0x00: // Player 1 + return DrvInput[0]; + case 0x08: // Player 2 + return DrvInput[1]; + case 0x88: // Region + return DrvInput[5]; + + } + +// bprintf(PRINT_NORMAL, _T("z80 read %4X\n"), nAddress); + + return 0; +} + +void __fastcall zerowingZ80Out(UINT16 nAddress, UINT8 nValue) +{ + nAddress &= 0xFF; + + switch (nAddress) { + case 0xa8: + BurnYM3812Write(0, nValue); + break; + case 0xa9: + BurnYM3812Write(1, nValue); + break; + + case 0xa0: // Coin counter + break; + +// default: +// bprintf(PRINT_NORMAL, _T("Z80 attempted to write address %04X with value %02X.\n"), nAddress, nValue); + } +} + +static INT32 DrvZ80Init() +{ + // Init the Z80 + ZetInit(1); + ZetOpen(0); + + ZetSetInHandler(zerowingZ80In); + ZetSetOutHandler(zerowingZ80Out); + + // ROM + ZetMapArea (0x0000, 0x7FFF, 0, RomZ80); // Direct Read from ROM + ZetMapArea (0x0000, 0x7FFF, 2, RomZ80); // Direct Fetch from ROM + // RAM + ZetMapArea (0x8000, 0xFFFF, 0, RamZ80); // Direct Read from RAM + ZetMapArea (0x8000, 0xFFFF, 1, RamZ80); // Direct Write to RAM + ZetMapArea (0x8000, 0xFFFF, 2, RamZ80); // + + ZetMemEnd(); + + ZetClose(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +UINT8 __fastcall zerowingReadByte(UINT32 sekAddress) +{ + switch (sekAddress) { + case 0x400001: + case 0x4c0001: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Byte %06X.\n"), sekAddress); + } + } + + return 0; +} + +UINT16 __fastcall zerowingReadWord(UINT32 sekAddress) +{ + switch (sekAddress) { + + case 0x4c0002: + return ToaFCU2GetRAMPointer(); + case 0x4c0004: + return ToaFCU2ReadRAM(); + case 0x4c0006: + return ToaFCU2ReadRAMSize(); + + case 0x480002: + return ToaBCU2GetRAMPointer(); + case 0x480004: + return ToaBCU2ReadRAM_Hi(); + case 0x480006: + return ToaBCU2ReadRAM_Lo(); + + case 0x480010: + case 0x480011: + case 0x480012: + case 0x480013: + case 0x480014: + case 0x480015: + case 0x480016: + case 0x480017: + case 0x480018: + case 0x480019: + case 0x48001A: + case 0x48001B: + case 0x48001C: + case 0x48001D: + case 0x48001E: + case 0x48001F: + return BCU2Reg[(sekAddress & 15) >> 1]; + + case 0x400000: + case 0x4c0000: + return ToaVBlankRegister(); + + default: { +// bprintf(PRINT_NORMAL, _T("Read Word %06X.\n"), sekAddress); + } + } + + return 0; +} + +void __fastcall zerowingWriteByte(UINT32 sekAddress, UINT8 byteValue) +{ + switch (sekAddress) { + + case 0x400003: + bEnableInterrupts = byteValue; + break; + + case 0x4c0006: + ToaFCU2WriteRAMSize(byteValue); + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write byte %06X, %02X.\n"), sekAddress, byteValue); + } + } +} + +void __fastcall zerowingWriteWord(UINT32 sekAddress, UINT16 wordValue) +{ + switch (sekAddress) { + + case 0x4c0002: // FCU-2 set VRAM address-pointer + ToaFCU2SetRAMPointer(wordValue); + break; + case 0x4c0004: + ToaFCU2WriteRAM(wordValue); + break; + case 0x4c0006: + ToaFCU2WriteRAMSize(wordValue); + break; + + case 0x480000: // BCU-2 flip + break; + case 0x480002: // BCU-2 set VRAM address-pointer + ToaBCU2SetRAMPointer(wordValue); + break; + case 0x480004: + ToaBCU2WriteRAM(wordValue); + break; + case 0x480006: + ToaBCU2WriteRAM(wordValue); + break; + + case 0x480010: + case 0x480011: + case 0x480012: + case 0x480013: + case 0x480014: + case 0x480015: + case 0x480016: + case 0x480017: + case 0x480018: + case 0x480019: + case 0x48001A: + case 0x48001B: + case 0x48001C: + case 0x48001D: + case 0x48001E: + case 0x48001F: + BCU2Reg[(sekAddress & 15) >> 1] = wordValue; + break; + + case 0x400002: + bEnableInterrupts = (wordValue & 0xFF); + break; + + case 0x0c0000: + nBCU2TileXOffset = wordValue; + break; + case 0x0c0002: + nBCU2TileYOffset = wordValue; + break; + + case 0x0c0006: // FCU-2 flip + break; + + default: { +// bprintf(PRINT_NORMAL, _T("Write word %06X, %04X.\n"), sekAddress, wordValue); + } + } +} + +// ---------------------------------------------------------------------------- + +static INT32 DrvDoReset() +{ + SekOpen(0); + SekReset(); + SekClose(); + ZetOpen(0); + ZetReset(); + ZetClose(); + + BurnYM3812Reset(); + + bEnableInterrupts = false; + + return 0; +} + +static INT32 DrvInit() +{ + INT32 nLen; + + Hellfire = 1; + +#ifdef DRIVER_ROTATION + bToaRotateScreen = true; +#endif + + BurnSetRefreshRate(REFRESHRATE); + + nBCU2ROMSize = 0x080000; + nFCU2ROMSize = 0x080000; + + // Find out how much memory is needed + Mem = NULL; + MemIndex(); + nLen = MemEnd - (UINT8 *)0; + if ((Mem = (UINT8 *)malloc(nLen)) == NULL) { + return 1; + } + memset(Mem, 0, nLen); // blank all memory + MemIndex(); // Index the allocated memory + + // Load the roms into memory + if (LoadRoms()) { + return 1; + } + + { + SekInit(0, 0x68000); // Allocate 68000 + SekOpen(0); + + // Map 68000 memory: + SekMapMemory(Rom01, 0x000000, 0x00FFFF, SM_ROM); // 68K ROM + SekMapMemory(Rom01 + 0x040000, 0x040000, 0x07FFFF, SM_ROM); // 68K ROM + SekMapMemory(Ram01, 0x080000, 0x087FFF, SM_RAM); // 68K RAM + SekMapMemory(RamPal, 0x404000, 0x4047FF, SM_RAM); // BCU-2 palette RAM + SekMapMemory(RamPal2, 0x406000, 0x4067FF, SM_RAM); // FCU-2 palette RAM + + SekSetReadWordHandler(0, zerowingReadWord); + SekSetReadByteHandler(0, zerowingReadByte); + SekSetWriteWordHandler(0, zerowingWriteWord); + SekSetWriteByteHandler(0, zerowingWriteByte); + + SekMapHandler(1, 0x440000, 0x440FFF, SM_RAM); // Z80 RAM + + SekSetReadByteHandler(1, toaplan1ReadByteZ80RAM); + SekSetReadWordHandler(1, toaplan1ReadWordZ80RAM); + SekSetWriteByteHandler(1, toaplan1WriteByteZ80RAM); + SekSetWriteWordHandler(1, toaplan1WriteWordZ80RAM); + + SekClose(); + } + + ToaInitBCU2(); + + DrvZ80Init(); // Initialize Z80 + + nToaPalLen = nColCount; + ToaPalSrc = RamPal; + ToaPalSrc2 = RamPal2; + ToaPalInit(); + + BurnYM3812Init(28000000 / 8, &toaplan1FMIRQHandler, &toaplan1SynchroniseStream, 0); + BurnTimerAttachZetYM3812(28000000 / 8); + + bDrawScreen = true; + + DrvDoReset(); // Reset machine + return 0; +} + +static INT32 DrvExit() +{ + BurnYM3812Exit(); + ToaPalExit(); + + ToaExitBCU2(); + ToaZExit(); // Z80 exit + SekExit(); // Deallocate 68000s + + // Deallocate all used memory + if (Mem) { + free(Mem); + Mem = NULL; + } + + Hellfire = 0; + + return 0; +} + +static INT32 DrvDraw() +{ + ToaClearScreen(0x120); +// BurnClearScreen(); + + if (bDrawScreen) { + ToaGetBitmap(); + ToaRenderBCU2(); // Render BCU2 graphics + } + + ToaPalUpdate(); // Update the palette + ToaPal2Update(); + + return 0; +} + +inline static INT32 CheckSleep(INT32) +{ + return 0; +} + +static INT32 DrvFrame() +{ + INT32 nInterleave = 4; + + if (DrvReset) { // Reset machine + DrvDoReset(); + } + + // Compile digital inputs + DrvInput[0] = 0x00; // Buttons + DrvInput[1] = 0x00; // Player 1 + DrvInput[4] = 0x00; // Player 2 + for (INT32 i = 0; i < 8; i++) { + DrvInput[0] |= (DrvJoy1[i] & 1) << i; + DrvInput[1] |= (DrvJoy2[i] & 1) << i; + DrvInput[4] |= (DrvButton[i] & 1) << i; + } + ToaClearOpposites(&DrvInput[0]); + ToaClearOpposites(&DrvInput[1]); + + SekOpen(0); + ZetOpen(0); + + SekNewFrame(); + ZetNewFrame(); + + SekIdle(nCyclesDone[0]); + ZetIdle(nCyclesDone[1]); + + nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * REFRESHRATE)); + nCyclesTotal[1] = INT32(28000000.0 / 8 / REFRESHRATE); + + SekSetCyclesScanline(nCyclesTotal[0] / 262); + nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262); + nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262); + bVBlank = false; + + for (INT32 i = 0; i < nInterleave; i++) { + INT32 nNext; + + // Run 68000 + + nNext = (i + 1) * nCyclesTotal[0] / nInterleave; + + // Trigger VBlank interrupt + if (nNext > nToaCyclesVBlankStart) { + if (SekTotalCycles() < nToaCyclesVBlankStart) { + nCyclesSegment = nToaCyclesVBlankStart - SekTotalCycles(); + SekRun(nCyclesSegment); + } + + if (pBurnDraw) { + DrvDraw(); // Draw screen if needed + } + + ToaBufferFCU2Sprites(); + + bVBlank = true; + if (bEnableInterrupts) { + SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); + } + } + + nCyclesSegment = nNext - SekTotalCycles(); + if (bVBlank || (!CheckSleep(0))) { // See if this CPU is busywaiting + SekRun(nCyclesSegment); + } else { + SekIdle(nCyclesSegment); + } + } + + nToa1Cycles68KSync = SekTotalCycles(); + BurnTimerEndFrameYM3812(nCyclesTotal[1]); + BurnYM3812Update(pBurnSoundOut, nBurnSoundLen); + + nCyclesDone[0] = SekTotalCycles() - nCyclesTotal[0]; + nCyclesDone[1] = ZetTotalCycles() - nCyclesTotal[1]; + +// bprintf(PRINT_NORMAL, _T(" %i\n"), nCyclesDone[0]); + + ZetClose(); + SekClose(); + +// ToaBufferFCU2Sprites(); + + return 0; +} + +struct BurnDriver BurnDrvZerowing = { + "zerowing", NULL, NULL, NULL, "1989", + "Zero Wing\0", NULL, "Toaplan", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, zerowingRomInfo, zerowingRomName, NULL, NULL, zerowingInputInfo, zerowingDIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; + +struct BurnDriver BurnDrvZerowng2 = { + "zerowing2", "zerowing", NULL, NULL, "1989", + "Zero Wing (2 player simultaneous ver.)\0", NULL, "[Toaplan] Williams Electronics Games, Inc", "Toaplan BCU-2 / FCU-2 based", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TOAPLAN_RAIZING, GBF_HORSHOOT, 0, + NULL, zerowng2RomInfo, zerowng2RomName, NULL, NULL, zerowingInputInfo, zerowng2DIPInfo, + DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x400, + 320, 240, 4, 3 +}; diff --git a/src/burn/drivers/toaplan/toa_bcu2.cpp b/src/burn/drivers/toaplan/toa_bcu2.cpp new file mode 100644 index 00000000..fdaa1e2f --- /dev/null +++ b/src/burn/drivers/toaplan/toa_bcu2.cpp @@ -0,0 +1,460 @@ +#include "toaplan.h" + +INT32 ToaOpaquePriority; + +static UINT8* pTile; +static UINT32* pTileData; +static UINT32* pTilePalette; + +INT32 Rallybik = 0; +INT32 Hellfire = 0; + +typedef void (*RenderTileFunction)(); +static RenderTileFunction* RenderTile; + +static INT32 nTileXPos, nTileYPos; + +// Include the tile rendering functions +#include "toa_gp9001_func.h" + +static INT32 nLastBPP = 0; + +struct ToaTile { + UINT32 nTileAttrib; + INT16 nTileXPos; + INT16 nTileYPos; +}; + +extern UINT32* ToaPalette2; + +// ---------------------------------------------------------------------------- +// Rally Bike custom sprite function + +static void rallybik_draw_sprites(INT32 priority) +{ + UINT16 *sprite = (UINT16*)FCU2RAM; + + for (INT32 offs = 0; offs < (0x1000/2); offs += 4) + { + INT32 attrib = sprite[offs + 1]; + + if ((attrib & 0x0c00) == priority) + { + INT32 sy = (sprite[offs + 3] >> 7) & 0x1ff; + + if (sy != 0x0100) + { + INT32 code = sprite[offs] & 0x7ff; + INT32 color = attrib & 0x3f; + INT32 sx = (sprite[offs + 2] >> 7) & 0x1ff; + INT32 flipx = attrib & 0x100; + INT32 flipy = attrib & 0x200; + if (flipx) sx -= 15; + + sx -= 31; + sy -= 16; + + if (sy < -15 || sx < -15 || sy >= 240 || sx >= 320) continue; + + { + INT32 flip = 0; + if (flipx) flip |= 0x0f; + if (flipy) flip |= 0xf0; + UINT8 *gfx = FCU2ROM + (code * 0x100); + + pTilePalette = &ToaPalette2[color << 4]; + + for (INT32 y = 0; y < 16; y++, sy++) { + if (sy < 0 || sy >= 240) continue; + + for (INT32 x = 0; x < 16; x++, sx++) { + if (sx < 0 || sx >= 320) continue; + + INT32 pxl = gfx[((y * 16) + x) ^ flip]; + + if (pxl) { + PutPix(pBurnDraw + ((sy * 320) + sx) * nBurnBpp, pTilePalette[pxl]); + } + } + sx -= 16; + } + } + } + } + } +} + + +// ---------------------------------------------------------------------------- +// FCU-2 functions + +UINT8* FCU2ROM; +UINT32 nFCU2ROMSize; +static UINT8* FCU2TileAttrib; + +static UINT32 nFCU2MaxSprite; + +UINT8* FCU2RAM; +UINT8* FCU2RAMSize; +UINT32 FCU2Pointer; + +static UINT8* pFCU2SpriteBuffer; + +static UINT16** pFCU2SpriteQueue[16]; +static UINT16** pFCU2SpriteQueueData = NULL; + +//static INT32 nFCU2SpriteXOffset, nFCU2SpriteYOffset; + +static void FCU2PrepareSprites() +{ + UINT16* pSpriteInfo; + INT32 nSprite; + + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + pFCU2SpriteQueue[nPriority] = &pFCU2SpriteQueueData[(nPriority << 8) + nPriority]; + } + + for (nSprite = 0, pSpriteInfo = (UINT16*)pFCU2SpriteBuffer; nSprite < 0x0100; nSprite++, pSpriteInfo += 4) { + if (!(pSpriteInfo[0] & 0x8000)) { // Sprite is enabled + *pFCU2SpriteQueue[pSpriteInfo[1] >> 12]++ = pSpriteInfo; + } + } +} + +static void FCU2RenderSpriteQueue(INT32 nPriority) +{ + UINT16* pSpriteInfo; + UINT8* pSpriteData; + INT32 nSpriteXPos, nSpriteYPos; + INT32 nSpriteXSize, nSpriteYSize; + UINT32 nSpriteNumber; + INT32 x, y, s; + + *pFCU2SpriteQueue[nPriority] = NULL; + pFCU2SpriteQueue[nPriority] = &pFCU2SpriteQueueData[(nPriority << 8) + nPriority]; + + while ((pSpriteInfo = *pFCU2SpriteQueue[nPriority]++) != NULL) { + + pTilePalette = &ToaPalette2[(pSpriteInfo[1] & 0x3F) << 4]; + nSpriteNumber = pSpriteInfo[0] & nFCU2MaxSprite; + + pSpriteData = FCU2ROM + (nSpriteNumber << 5); + + s = (pSpriteInfo[1] & 0x0FC0) >> 6; + + nSpriteXSize = ((((UINT16*)FCU2RAMSize)[s] >> 0) & 0x0F); + nSpriteYSize = ((((UINT16*)FCU2RAMSize)[s] >> 4) & 0x0F); + + nSpriteXPos = (pSpriteInfo[2] >> 7) + 0;//nFCU2SpriteXOffset; + nSpriteXPos &= 0x01FF; + nSpriteYPos = (pSpriteInfo[3] >> 7) + 0;//nFCU2SpriteYOffset; + nSpriteYPos &= 0x01FF; + + if (Hellfire) nSpriteYPos -= 16; + + if (nSpriteXPos > 384) { + nSpriteXPos -= 0x0200; + } + if (nSpriteYPos > 384) { + nSpriteYPos -= 0x0200; + } + +// if (nSpriteNumber) { +// printf("Sprite\t0x%04X\n", nSpriteNumber); +// printf("xp: %4i, yp: %4i\n", nSpriteXPos, nSpriteYPos); +// printf("xs: %4i, ys: %4i\n", nSpriteXSize, nSpriteYSize); +// } + + for (y = 0, nTileYPos = nSpriteYPos; y < nSpriteYSize; y++, nTileYPos += 8) { + for (x = 0, nTileXPos = nSpriteXPos; x < nSpriteXSize; x++, nTileXPos += 8, nSpriteNumber++, pSpriteData += 32) { + if (nSpriteNumber > nFCU2MaxSprite) { + break; + } + if (FCU2TileAttrib[nSpriteNumber]) { + // Skip tile if it's completely off the screen + if (!(nTileXPos <= -8 || nTileXPos >= 320 || nTileYPos <= -8 || nTileYPos >= 240)) { + pTileData = (UINT32*)pSpriteData; + pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow); + if (nTileXPos < 0 || nTileXPos > 312 || nTileYPos < 0 || nTileYPos > 232) { + RenderTile[1](); + } else { + RenderTile[0](); + } + } + } + } + } + } +} + +// ---------------------------------------------------------------------------- +// BCU-2 functions + +UINT8* BCU2ROM; +UINT32 nBCU2ROMSize; +static UINT8* BCU2TileAttrib; + +static UINT32 nBCU2MaxTile; + +UINT8* BCU2RAM; + +UINT16 BCU2Reg[8]; + +UINT32 BCU2Pointer; + +static ToaTile* pBCU2TileQueue[16]; +static ToaTile* pBCU2TileQueueData = NULL; + +INT32 nBCU2TileXOffset = 0, nBCU2TileYOffset = 0; + +static void BCU2QueueLayer(UINT16* pTilemap, INT32 nXPos, INT32 nYPos) +{ + if (Hellfire) nYPos += 16; + + INT32 x, y; + INT32 nTileRow, nTileColumn; + UINT32 nTileNumber, nTileAttrib; + + for (y = 0; y < 31; y++) { + + nTileRow = (((nYPos >> 3) + y) << 7) & 0x1F80; + + for (x = 0; x < 41; x++) { + nTileColumn = (((nXPos >> 3) + x) << 1) & 0x7E; + nTileNumber = pTilemap[nTileRow + nTileColumn + 1]; + nTileAttrib = pTilemap[nTileRow + nTileColumn]; + + if (!(nTileNumber & 0x8000) && (nTileAttrib & 0xF000)) { + pBCU2TileQueue[nTileAttrib >> 12]->nTileAttrib = (nTileAttrib << 16) | nTileNumber; + pBCU2TileQueue[nTileAttrib >> 12]->nTileXPos = (x << 3) - (nXPos & 7); + pBCU2TileQueue[nTileAttrib >> 12]->nTileYPos = (y << 3) - (nYPos & 7); + pBCU2TileQueue[nTileAttrib >> 12]++; + } + } + } +} + +static void BCU2PrepareTiles() +{ + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + pBCU2TileQueue[nPriority] = &pBCU2TileQueueData[nPriority * 1280 * 4]; + } + + BCU2QueueLayer((UINT16*)(BCU2RAM + 0xC000), (BCU2Reg[6] >> 7) - nBCU2TileXOffset + nLayer3XOffset, (BCU2Reg[7] >> 7) - nBCU2TileYOffset + nLayer3YOffset); + BCU2QueueLayer((UINT16*)(BCU2RAM + 0x8000), (BCU2Reg[4] >> 7) - nBCU2TileXOffset + nLayer2XOffset, (BCU2Reg[5] >> 7) - nBCU2TileYOffset + nLayer2YOffset); + BCU2QueueLayer((UINT16*)(BCU2RAM + 0x4000), (BCU2Reg[2] >> 7) - nBCU2TileXOffset + nLayer1XOffset, (BCU2Reg[3] >> 7) - nBCU2TileYOffset + nLayer1YOffset); + BCU2QueueLayer((UINT16*)(BCU2RAM + 0x0000), (BCU2Reg[0] >> 7) - nBCU2TileXOffset + nLayer0XOffset, (BCU2Reg[1] >> 7) - nBCU2TileYOffset + nLayer0YOffset); +} + +static void BCU2RenderTileQueue(INT32 nPriority) +{ + UINT32 nTileNumber, nTileAttrib; + UINT8* pTileStart; + UINT8 nOpacity; + + pBCU2TileQueue[nPriority]->nTileAttrib = 0; + pBCU2TileQueue[nPriority] = &pBCU2TileQueueData[nPriority * 1280 * 4]; + + while ((nTileAttrib = pBCU2TileQueue[nPriority]->nTileAttrib) != 0) { + nTileXPos = pBCU2TileQueue[nPriority]->nTileXPos; + nTileYPos = pBCU2TileQueue[nPriority]->nTileYPos; + pBCU2TileQueue[nPriority]++; + + nTileNumber = nTileAttrib & nBCU2MaxTile; + + pTileStart = BCU2ROM + (nTileNumber << 5); + pTilePalette = &ToaPalette[(nTileAttrib >> 12) & 0x03F0]; + + pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow); + + if ((nOpacity = BCU2TileAttrib[nTileNumber]) != 0 || nPriority < ToaOpaquePriority) { + if (nPriority < ToaOpaquePriority) nOpacity = 9; + + pTileData = (UINT32*)pTileStart; + if (nTileXPos >= 0 && nTileXPos < 312 && nTileYPos >= 0 && nTileYPos < 232) { + RenderTile[nOpacity - 1](); + } else { + if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) { + RenderTile[nOpacity](); + } + } + } + } +} + +void ToaBufferFCU2Sprites() +{ + memcpy(pFCU2SpriteBuffer, FCU2RAM, 0x0800); +} + +INT32 ToaRenderBCU2() +{ + if (nLastBPP != nBurnBpp ) { + nLastBPP = nBurnBpp; + +#ifdef DRIVER_ROTATION + if (bRotatedScreen) { + RenderTile = RenderTile_ROT270[nBurnBpp - 2]; + } else { + RenderTile = RenderTile_ROT0[nBurnBpp - 2]; + } +#else + RenderTile = RenderTile_ROT0[nBurnBpp - 2]; +#endif + } + + BCU2PrepareTiles(); + if (!Rallybik) { + FCU2PrepareSprites(); + } + + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + if (Rallybik) { + rallybik_draw_sprites(nPriority << 8); + } else { + FCU2RenderSpriteQueue(nPriority); + } + BCU2RenderTileQueue(nPriority); + } + + return 0; +} + +INT32 ToaInitBCU2() +{ + INT32 nSize; + + nLastBPP = 0; + + nBCU2MaxTile = (nBCU2ROMSize - 1) >> 5; + + nSize = 1280 * 4 * 0x10 * sizeof(ToaTile); + pBCU2TileQueueData = (ToaTile*)malloc(nSize); + memset(pBCU2TileQueueData, 0, nSize); + + BCU2TileAttrib = (UINT8*)malloc(32768); + memset(BCU2TileAttrib, 0, 32768); + for (UINT32 j = 0; j < (nBCU2ROMSize >> 5); j++) { + bool bTransparent = true, bSolid = true; + INT32 nTwoPixels; + for (UINT32 k = (j << 5); k < ((j << 5) + 32); k++) { + if ((nTwoPixels = BCU2ROM[k]) != 0) { + bTransparent = false; + } + if ((nTwoPixels & 0xF0) == 0 || (nTwoPixels & 0x0F) == 0) { + bSolid = false; + } + } + if (bTransparent) { + BCU2TileAttrib[j] = 0; + } else { + if (bSolid) { + BCU2TileAttrib[j] = 9; + } else { + BCU2TileAttrib[j] = 1; + } + } + } + + nFCU2MaxSprite = (nFCU2ROMSize - 1) >> 5; + + nSize = 0x10 * 0x101 * sizeof(UINT16*); + pFCU2SpriteQueueData = (UINT16**)malloc(nSize); + memset(pFCU2SpriteQueueData, 0, nSize); + + pFCU2SpriteBuffer = (UINT8*)malloc(0x0800); + + FCU2TileAttrib = (UINT8*)malloc(32768); + memset(FCU2TileAttrib, 0, 32768); + for (UINT32 j = 0; j < (nFCU2ROMSize >> 5); j++) { + bool bTransparent = true, bSolid = true; + INT32 nTwoPixels; + for (UINT32 k = (j << 5); k < ((j << 5) + 32); k++) { + if ((nTwoPixels = FCU2ROM[k]) != 0) { + bTransparent = false; + } + if ((nTwoPixels & 0xF0) == 0 || (nTwoPixels & 0x0F) == 0) { + bSolid = false; + } + } + if (bTransparent) { + FCU2TileAttrib[j] = 0; + } else { + if (bSolid) { + FCU2TileAttrib[j] = 9; + } else { + FCU2TileAttrib[j] = 1; + } + } + } + + if (!nLayer0XOffset) { + nLayer0XOffset = 0x01EF + 6; + } + if (!nLayer1XOffset) { + nLayer1XOffset = 0x01EF + 4; + } + if (!nLayer2XOffset) { + nLayer2XOffset = 0x01EF + 2; + } + if (!nLayer3XOffset) { + nLayer3XOffset = 0x01EF + 0; + } + + if (!nLayer0YOffset) { + nLayer0YOffset = 0x0101; + } + if (!nLayer1YOffset) { + nLayer1YOffset = 0x0101; + } + if (!nLayer2YOffset) { + nLayer2YOffset = 0x0101; + } + if (!nLayer3YOffset) { + nLayer3YOffset = 0x0101; + } + + ToaOpaquePriority = 0; + + return 0; +} + +INT32 ToaExitBCU2() +{ + nLayer0XOffset = 0; + nLayer1XOffset = 0; + nLayer2XOffset = 0; + nLayer3XOffset = 0; + nLayer0YOffset = 0; + nLayer1YOffset = 0; + nLayer2YOffset = 0; + nLayer3YOffset = 0; + + if (pBCU2TileQueueData) { + free(pBCU2TileQueueData); + pBCU2TileQueueData = NULL; + } + + if (BCU2TileAttrib) { + free(BCU2TileAttrib); + BCU2TileAttrib = NULL; + } + + if (pFCU2SpriteQueueData) { + free(pFCU2SpriteQueueData); + pFCU2SpriteQueueData = NULL; + } + + if (pFCU2SpriteBuffer) { + free(pFCU2SpriteBuffer); + pFCU2SpriteBuffer = NULL; + } + + if (FCU2TileAttrib) { + free(FCU2TileAttrib); + FCU2TileAttrib = NULL; + } + + return 0; +} + diff --git a/src/burn/drivers/toaplan/toa_extratext.cpp b/src/burn/drivers/toaplan/toa_extratext.cpp new file mode 100644 index 00000000..903969f8 --- /dev/null +++ b/src/burn/drivers/toaplan/toa_extratext.cpp @@ -0,0 +1,340 @@ +#include "toaplan.h" + +UINT8* ExtraTROM; +UINT8* ExtraTRAM; +UINT8* ExtraTScroll; +UINT8* ExtraTSelect; + +INT32 nExtraTXOffset = 0x9999; +INT32 nTileXPos; + +static UINT8* pTile; +static UINT8* pTileData; +static UINT32* pTilePalette; + +typedef void (*RenderTileFunction)(); +static RenderTileFunction RenderTile[4]; + +static INT32 nLastBPP = 0; + +#define ROT 0 + +#define ROWMODE 0 + +#define DOCLIP 0 + +#define BPP 16 +#include "toa_extratext.h" +#undef BPP +#define BPP 24 +#include "toa_extratext.h" +#undef BPP +#define BPP 32 +#include "toa_extratext.h" +#undef BPP + +#undef DOCLIP +#define DOCLIP 1 + +#define BPP 16 +#include "toa_extratext.h" +#undef BPP +#define BPP 24 +#include "toa_extratext.h" +#undef BPP +#define BPP 32 +#include "toa_extratext.h" +#undef BPP + +#undef DOCLIP + +#undef ROWMODE +#define ROWMODE 1 + +#define DOCLIP 0 + +#define BPP 16 +#include "toa_extratext.h" +#undef BPP +#define BPP 24 +#include "toa_extratext.h" +#undef BPP +#define BPP 32 +#include "toa_extratext.h" +#undef BPP + +#undef DOCLIP +#define DOCLIP 1 + +#define BPP 16 +#include "toa_extratext.h" +#undef BPP +#define BPP 24 +#include "toa_extratext.h" +#undef BPP +#define BPP 32 +#include "toa_extratext.h" +#undef BPP + +#undef DOCLIP + +#undef ROWMODE + +#undef ROT + +#ifdef DRIVER_ROTATION + #define ROT 270 + + #define ROWMODE 0 + + #define DOCLIP 0 + + #define BPP 16 + #include "toa_extratext.h" + #undef BPP + #define BPP 24 + #include "toa_extratext.h" + #undef BPP + #define BPP 32 + #include "toa_extratext.h" + #undef BPP + + #undef DOCLIP + #define DOCLIP 1 + + #define BPP 16 + #include "toa_extratext.h" + #undef BPP + #define BPP 24 + #include "toa_extratext.h" + #undef BPP + #define BPP 32 + #include "toa_extratext.h" + #undef BPP + + #undef DOCLIP + + #undef ROWMODE + #define ROWMODE 1 + + #define DOCLIP 0 + + #define BPP 16 + #include "toa_extratext.h" + #undef BPP + #define BPP 24 + #include "toa_extratext.h" + #undef BPP + #define BPP 32 + #include "toa_extratext.h" + #undef BPP + + #undef DOCLIP + #define DOCLIP 1 + + #define BPP 16 + #include "toa_extratext.h" + #undef BPP + #define BPP 24 + #include "toa_extratext.h" + #undef BPP + #define BPP 32 + #include "toa_extratext.h" + #undef BPP + + #undef DOCLIP + + #undef ROWMODE + + #undef ROT +#endif + +INT32 ToaExtraTextLayer() +{ + if (nLastBPP != nBurnBpp ) { + nLastBPP = nBurnBpp; + +#ifdef DRIVER_ROTATION + switch (nBurnBpp) { + case 2: + if (bRotatedScreen) { + RenderTile[0] = *RenderTile16_ROT270_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile16_ROT270_CLIP_NORMAL; + RenderTile[2] = *RenderTile16_ROT270_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile16_ROT270_CLIP_ROWSEL; + } else { + RenderTile[0] = *RenderTile16_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile16_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile16_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile16_ROT0_CLIP_ROWSEL; + } + break; + case 3: + if (bRotatedScreen) { + RenderTile[0] = *RenderTile24_ROT270_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile24_ROT270_CLIP_NORMAL; + RenderTile[2] = *RenderTile24_ROT270_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile24_ROT270_CLIP_ROWSEL; + } else { + RenderTile[0] = *RenderTile24_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile24_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile24_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile24_ROT0_CLIP_ROWSEL; + } + break; + case 4: + if (bRotatedScreen) { + RenderTile[0] = *RenderTile32_ROT270_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile32_ROT270_CLIP_NORMAL; + RenderTile[2] = *RenderTile32_ROT270_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile32_ROT270_CLIP_ROWSEL; + } else { + RenderTile[0] = *RenderTile32_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile32_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile32_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile32_ROT0_CLIP_ROWSEL; + } + break; + default: + return 1; + } +#else + switch (nBurnBpp) { + case 2: + RenderTile[0] = *RenderTile16_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile16_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile16_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile16_ROT0_CLIP_ROWSEL; + break; + case 3: + RenderTile[0] = *RenderTile24_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile24_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile24_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile24_ROT0_CLIP_ROWSEL; + break; + case 4: + RenderTile[0] = *RenderTile32_ROT0_NOCLIP_NORMAL; + RenderTile[1] = *RenderTile32_ROT0_CLIP_NORMAL; + RenderTile[2] = *RenderTile32_ROT0_NOCLIP_ROWSEL; + RenderTile[3] = *RenderTile32_ROT0_CLIP_ROWSEL; + break; + default: + return 1; + } +#endif + } + + UINT32* pTextPalette = &ToaPalette[0x0400]; + UINT8* pCurrentRow = pBurnBitmap; + + INT32 nTileLeft = nBurnColumn << 3; + INT32 nTileDown = nBurnRow << 3; + UINT16* pTileRow; + + INT32 nOffset, nLine, nStartX; + INT32 x, y, i; + +#if 1 + y = 0; + do { + nLine = ((UINT16*)ExtraTSelect)[y]; + nOffset = ((UINT16*)ExtraTScroll)[y]; + + if (y < 233) { + for (i = 1; i < 8 && ((UINT16*)ExtraTSelect)[y + i] == (nLine + i) && ((UINT16*)ExtraTScroll)[y + i] == nOffset; i++) { } + + // draw whole tiles in one go + if (i == 8) { + + nOffset += nExtraTXOffset; + nStartX = (nOffset >> 3) & 0x3F; + pTileRow = ((UINT16*)ExtraTRAM) + ((nLine & (0x1F << 3)) << 3); + nOffset &= 7; + + for (x = 0, pTile = pCurrentRow - nOffset * nBurnColumn; x < 41; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[(x + nStartX) & 0x3F]; + if (nTile && nTile != 0x20) { + pTileData = ExtraTROM + ((nTile & 0x3FF) << 5); + pTilePalette = &pTextPalette[((nTile >> 6) & 0x03F0)]; + if (x == 0 || x == 40) { + nTileXPos = 0 - nOffset + (x << 3); + RenderTile[1](); + } else { + RenderTile[0](); + } + } + } + + pCurrentRow += nTileDown; + y += 8; + continue; + } + } + + // Draw each line seperately + + nOffset += nExtraTXOffset; + nStartX = (nOffset >> 3) & 0x3F; + pTileRow = ((UINT16*)ExtraTRAM) + ((nLine & (0x1F << 3)) << 3); + nOffset &= 7; + + for (x = 0, pTile = pCurrentRow - nOffset * nBurnColumn; x < 41; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[(x + nStartX) & 0x3F]; + if (nTile && nTile != 0x20) { + pTileData = ExtraTROM + ((nTile & 0x3FF) << 5) + ((nLine & 7) << 2); + pTilePalette = &pTextPalette[((nTile >> 6) & 0x03F0)]; + if (x == 0 || x == 40) { + nTileXPos = 0 - nOffset + (x << 3); + RenderTile[3](); + } else { + RenderTile[2](); + } + } + } + + pCurrentRow += nBurnRow; + y++; + + } while (y < 240); +#else + pTileRow = (UINT16*)(ExtraTRAM + ((nOffset >> 3) << 1)); + pCurrentRow = pBurnBitmap - (nOffset & 7) * nBurnColumn; + + nOffset = ((UINT16*)(ExtraTScroll + nExtraTXOffset))[y]; + nStartX = nOffset >> 3; + nOffset &= 7; + + for (y = 0; y < 30; y++, pCurrentRow += nTileDown, pTileRow += 0x40) { + for (x = 0, pTile = pCurrentRow; x < 41; x++, pTile += nTileLeft) { + UINT32 nTile = pTileRow[(x + nStartX) & 0x3F]; + if (nTile && nTile != 0x20) { + pTileData = ExtraTROM + ((nTile & 0x3FF) << 5); + pTilePalette = &pTextPalette[((nTile >> 6) & 0x03F0)]; + if (x == 0 || x == 40) { + nTileXPos = 0 - nOffset + (x << 3); + RenderTile[1](); + } else { + RenderTile[0](); + } + } + } + } +#endif + + return 0; +} + +INT32 ToaExtraTextInit() +{ + if (nExtraTXOffset == 0x9999) { + nExtraTXOffset = 0x2B; + } + + return 0; +} + +void ToaExtraTextExit() +{ + nExtraTXOffset = 0x9999; +} + diff --git a/src/burn/drivers/toaplan/toa_extratext.h b/src/burn/drivers/toaplan/toa_extratext.h new file mode 100644 index 00000000..7c8c4301 --- /dev/null +++ b/src/burn/drivers/toaplan/toa_extratext.h @@ -0,0 +1,115 @@ +#define FN(a,b,c,d) RenderTile ## a ## _ROT ## b ## c ## d +#define FUNCTIONNAME(a,b,c,d) FN(a,b,c,d) + +#define ISOPAQUE 0 + +#if ROT == 0 + #define ADVANCECOLUMN pPixel += (BPP >> 3) + #define ADVANCEROW pTileRow += ((BPP >> 3) * 320) +#elif ROT == 270 + #define ADVANCECOLUMN pPixel -= ((BPP >> 3) * 240) + #define ADVANCEROW pTileRow += (BPP >> 3) +#else + #error unsupported rotation angle specified. +#endif + +#if DOCLIP == 0 + #define CLIP _NOCLIP + #define TESTCLIP(x) 1 +#elif DOCLIP == 1 + #define CLIP _CLIP + #define TESTCLIP(x) (nTileXPos + x) >= 0 && (nTileXPos + x) < 320 +#else + #error illegal doclip value. +#endif + +#if ISOPAQUE == 0 + #define OPACITY _TRANS + #define TESTCOLOUR(x) x +#elif ISOPAQUE == 1 + #define OPACITY _OPAQUE + #define TESTCOLOUR(x) 1 +#else + #error illegal isopaque value +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT16 *)pPixel) = (UINT16)pTilePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + UINT32 nRGB = pTilePalette[b]; \ + pPixel[0] = (UINT8)nRGB; \ + pPixel[1] = (UINT8)(nRGB >> 8); \ + pPixel[2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT32 *)pPixel) = (UINT32)pTilePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +#if ROWMODE == 0 + #define MODE _NORMAL +#elif ROWMODE == 1 + #define MODE _ROWSEL +#else + #error unsupported rowmode specified. +#endif + +static void FUNCTIONNAME(BPP,ROT,CLIP,MODE)() +{ +#if ROWMODE == 0 + UINT8 *pTileRow, *pPixel; + INT32 y, nColour; + + for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) { + pPixel = pTileRow; +#else + UINT8 *pPixel = pTile; + INT32 nColour; +#endif + + nColour = *pTileData++; + PLOTPIXEL(0,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(1,nColour & 0x0F); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(2,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(3,nColour & 0x0F); + ADVANCECOLUMN; + + nColour = *pTileData++; + PLOTPIXEL(4,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(5,nColour & 0x0F); + ADVANCECOLUMN; + +#if ROWMODE == 0 + nColour = *pTileData++; +#else + nColour = *pTileData; +#endif + PLOTPIXEL(6,nColour >> 4); + ADVANCECOLUMN; + PLOTPIXEL(7,nColour & 0x0F); +#if ROWMODE == 0 + } +#endif +} + +#undef MODE +#undef PLOTPIXEL +#undef TESTCLIP +#undef TESTCOLOUR +#undef ADVANCEROW +#undef ADVANCECOLUMN +#undef CLIP +#undef FUNCTIONNAME +#undef FN diff --git a/src/burn/drivers/toaplan/toa_gp9001.cpp b/src/burn/drivers/toaplan/toa_gp9001.cpp new file mode 100644 index 00000000..aae5aba7 --- /dev/null +++ b/src/burn/drivers/toaplan/toa_gp9001.cpp @@ -0,0 +1,627 @@ +#include "toaplan.h" + +/* + * Some games write to addresses outside of VRAM. It looks like the hardware masks bit 15-12. + * Note that they only seem to set the VRAM pointer too high (tekipaki does read/write too far + * during POST -- 0x3800 = 2 * 0x1C00). Batsugun in particular sets the pointer too high often. + * + * Some games need 1 to be added to the sprite priorities (e.g the 2nd level boss in mahoudai). + * This is clearly wrong for some other games. + * + * For batsugun, controller 1 has higher priority then controller 0. + * Tiles with priority 0 are special -- they are always in the background. + * How to determine which controller has the highest priority is unknown. + * The code to accomplish this for Batsugun is a hack that checks the X positions of the layers. + * + */ + +UINT8* GP9001ROM[2]; +UINT32 nGP9001ROMSize[2]; +static UINT8* GP9001TileAttrib[2]; + +static UINT32 nMaxTile[2]; +static UINT32 nMaxSprite[2]; + +static INT32 nControllers; +static INT32 nMode; + +UINT32 GP9001TileBank[8]; + +UINT8* GP9001RAM[2]; +UINT16* GP9001Reg[2]; + +UINT8* GP9001Pointer[2]; +INT32 GP9001Regnum[2]; + +static UINT32* pTileQueue[32]; +static UINT32* pTileQueueData[2] = {NULL, }; + +static UINT8** pSpriteQueue[32]; +static UINT8** pSpriteQueueData[2] = {NULL, }; + +static UINT8* pSpriteBuffer[2]; +static UINT8* pSpriteBufferData[2] = {NULL, }; + +static INT32 nSpriteBuffer = 0; + +INT32 nSpriteXOffset = 0, nSpriteYOffset = 0, nSpritePriority = 0; + +INT32 nLayer0XOffset = 0, nLayer0YOffset = 0; +INT32 nLayer1XOffset = 0, nLayer1YOffset = 0; +INT32 nLayer2XOffset = 0, nLayer2YOffset = 0; +INT32 nLayer3XOffset = 0, nLayer3YOffset = 0; + +static UINT8* pTile; +static UINT32* pTileData; +static UINT32* pTilePalette; + +typedef void (*RenderTileFunction)(); +static RenderTileFunction* RenderTile; + +static INT32 nTileXPos, nTileYPos; + +static INT32 nLastBPP = 0; + +// Include the tile rendering functions +#include "toa_gp9001_func.h" + +static void PrepareSprites() +{ + UINT8* pSpriteInfo; + INT32 nSprite, nAttrib; + + for (INT32 i = 0; i < nControllers; i++) { + UINT8*** pMySpriteQueue = &pSpriteQueue[i << 4]; + + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + pMySpriteQueue[nPriority] = &pSpriteQueueData[i][(nPriority << 8) + nPriority]; + } + + for (nSprite = 0, pSpriteInfo = pSpriteBuffer[i]; nSprite < 0x0100; nSprite++, pSpriteInfo += 8) { + nAttrib = pSpriteInfo[1]; + if (nAttrib & 0x80) { // Sprite is enabled + *pMySpriteQueue[nAttrib & 0x0F]++ = pSpriteInfo; + } + } + } +} + +static void RenderSpriteQueue(INT32 i, INT32 nPriority) +{ + UINT8* pSpriteInfo; + UINT8* pSpriteData; + INT32 nSpriteXPos, nSpriteYPos; + INT32 nSpriteXSize, nSpriteYSize; + UINT32 nSpriteNumber; + INT32 x, y, xoff, yoff; + INT32 nFlip; + + UINT8*** pMySpriteQueue = &pSpriteQueue[i << 4]; + + *pMySpriteQueue[nPriority] = NULL; + pMySpriteQueue[nPriority] = &pSpriteQueueData[i][(nPriority << 8) + nPriority]; + + while ((pSpriteInfo = *pMySpriteQueue[nPriority]++) != NULL) { + nFlip = ((pSpriteInfo[1] & 0x30) >> 3); + + pTilePalette = &ToaPalette[((pSpriteInfo[0] & 0xFC) << 2)]; + nSpriteNumber = (((pSpriteInfo[3] << 8) | pSpriteInfo[2]) & 0x7FFF); + nSpriteNumber += GP9001TileBank[(((pSpriteInfo[0] & 3) << 1) | (pSpriteInfo[3] >> 7))]; + + pSpriteData = GP9001ROM[i] + (nSpriteNumber << 5); + + nSpriteXSize = pSpriteInfo[4] & 0x0F; + nSpriteXPos = ((pSpriteInfo[5] << 1) | (pSpriteInfo[4] >> 7)) + GP9001Reg[i][6] + nSpriteXOffset; + nSpriteXPos &= 0x01FF; + nSpriteYSize = pSpriteInfo[6] & 0x0F; + nSpriteYPos = ((pSpriteInfo[7] << 1) | (pSpriteInfo[6] >> 7)) + GP9001Reg[i][7] + nSpriteYOffset; + nSpriteYPos &= 0x01FF; + + if (nFlip & 2) { + xoff = -8; + nSpriteXPos -= 7; + if (nSpriteXPos > (320 + 128)) { + nSpriteXPos -= 0x0200; + } + } else { + xoff = 8; + if (nSpriteXPos > (512 - 128)) { + nSpriteXPos -= 0x0200; + } + } + if (nFlip & 4) { + yoff = -8; + nSpriteYPos -= 7; + } else { + yoff = 8; + } + + if (nSpriteYPos > 384) { + nSpriteYPos -= 0x0200; + } + + for (y = 0, nTileYPos = nSpriteYPos; y <= nSpriteYSize; y++, nTileYPos += yoff) { + for (x = 0, nTileXPos = nSpriteXPos; x <= nSpriteXSize; x++, nTileXPos += xoff, nSpriteNumber++, pSpriteData += 32) { + if (nSpriteNumber > nMaxSprite[i]) { + break; + } + if (GP9001TileAttrib[i][nSpriteNumber]) { + // Skip tile if it's completely off the screen + if (!(nTileXPos <= -8 || nTileXPos >= 320 || nTileYPos <= -8 || nTileYPos >= 240)) { + pTileData = (UINT32*)pSpriteData; + pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow); + if (nTileXPos < 0 || nTileXPos > 312 || nTileYPos < 0 || nTileYPos > 232) { + RenderTile[nFlip + 1](); + } else { + RenderTile[nFlip](); + } + } + } + } + } + } +} + +static void QueueLayer(INT32 i, UINT16* pTilemap, INT32 nXPos, INT32 nYPos) +{ + INT32 x, y; + INT32 nTileRow, nTileColumn; + UINT32 nTileNumber, nTileAttrib; + + UINT32** pMyTileQueue = &pTileQueue[i << 4]; + + for (y = 0; y < 16; y++) { + + nTileRow = (((nYPos >> 4) + y) << 6) & 0x7C0; + + for (x = 0; x < 21; x++) { + nTileColumn = (((nXPos >> 4) + x) << 1) & 0x3E; + nTileNumber = pTilemap[nTileRow + nTileColumn + 1]; + + if (nTileNumber > 0 && nTileNumber <= nMaxTile[i]) { + nTileAttrib = pTilemap[nTileRow + nTileColumn]; + *pMyTileQueue[(nTileAttrib >> 8) & 0x0F]++ = (nTileAttrib << 16) | nTileNumber; + nTileXPos = (x << 4) - (nXPos & 15); + nTileYPos = (y << 4) - (nYPos & 15); + *pMyTileQueue[(nTileAttrib >> 8) & 0x0F]++ = (nTileXPos << 16) | (nTileYPos & 0xFFFF); +#if 0 + printf("%X ", nTileAttrib >> 8); +#endif + } + } + } +} + +static void QueueLayer2(INT32 i, UINT16* pTilemap, INT32 nXPos, INT32 nYPos) +{ + INT32 x, y; + INT32 nTileRow, nTileColumn; + UINT32 nTileNumber, nTileAttrib; + + UINT32** pMyTileQueue = &pTileQueue[i << 4]; + + for (y = 0; y < 16; y++) { + + nTileRow = (((nYPos >> 4) + y) << 6) & 0x7C0; + + for (x = 0; x < 21; x++) { + nTileColumn = (((nXPos >> 4) + x) << 1) & 0x3E; + nTileNumber = pTilemap[nTileRow + nTileColumn + 1]; + + if (nTileNumber > 0 && nTileNumber <= nMaxTile[i]) { + nTileAttrib = pTilemap[nTileRow + nTileColumn]; + if ((nTileAttrib & 0x0F00) == 0) { + nTileAttrib |= 0x0100; + } + *pMyTileQueue[(nTileAttrib >> 8) & 0x0F]++ = (nTileAttrib << 16) | nTileNumber; + nTileXPos = (x << 4) - (nXPos & 15); + nTileYPos = (y << 4) - (nYPos & 15); + *pMyTileQueue[(nTileAttrib >> 8) & 0x0F]++ = (nTileXPos << 16) | (nTileYPos & 0xFFFF); + } + } + } +} + +static void PrepareTiles() +{ + for (INT32 i = 0; i < nControllers; i++) { + UINT32** pMyTileQueue = &pTileQueue[i << 4]; + + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + pMyTileQueue[nPriority] = &pTileQueueData[i][nPriority * 512 * 3 * 2]; + } + } + + if (nControllers == 1) { + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x0000), GP9001Reg[0][0] + nLayer0XOffset, GP9001Reg[0][1] + nLayer0YOffset); + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x1000), GP9001Reg[0][2] + nLayer1XOffset, GP9001Reg[0][3] + nLayer1YOffset); + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x2000), GP9001Reg[0][4] + nLayer2XOffset, GP9001Reg[0][5] + nLayer2YOffset); + } else { + if (nMode == 2) { + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x0000), GP9001Reg[0][0] + nLayer0XOffset, GP9001Reg[0][1] + nLayer0YOffset); + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x1000), GP9001Reg[0][2] + nLayer1XOffset, GP9001Reg[0][3] + nLayer1YOffset); + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x2000), GP9001Reg[0][4] + nLayer2XOffset, GP9001Reg[0][5] + nLayer2YOffset); + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x0000), GP9001Reg[1][0] + nLayer0XOffset, GP9001Reg[1][1] + nLayer0YOffset); + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x1000), GP9001Reg[1][2] + nLayer1XOffset, GP9001Reg[1][3] + nLayer1YOffset); + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x2000), GP9001Reg[1][4] + nLayer2XOffset, GP9001Reg[1][5] + nLayer2YOffset); + } else { + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x0000), GP9001Reg[0][0] + nLayer0XOffset, GP9001Reg[0][1] + nLayer0YOffset); + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x1000), GP9001Reg[0][2] + nLayer1XOffset, GP9001Reg[0][3] + nLayer1YOffset); + if (GP9001Reg[0][4] + nLayer2XOffset == 0) { + QueueLayer(0, (UINT16*)(GP9001RAM[0] + 0x2000), GP9001Reg[0][4] + nLayer2XOffset, GP9001Reg[0][5] + nLayer2YOffset); + } else { + QueueLayer2(0, (UINT16*)(GP9001RAM[0] + 0x2000), GP9001Reg[0][4] + nLayer2XOffset, GP9001Reg[0][5] + nLayer2YOffset); + } + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x0000), GP9001Reg[1][0] + nLayer0XOffset, GP9001Reg[1][1] + nLayer0YOffset); + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x1000), GP9001Reg[1][2] + nLayer1XOffset, GP9001Reg[1][3] + nLayer1YOffset); + QueueLayer(1, (UINT16*)(GP9001RAM[1] + 0x2000), GP9001Reg[1][4] + nLayer2XOffset, GP9001Reg[1][5] + nLayer2YOffset); + } + } +} + +static void RenderTileQueue(INT32 i, INT32 nPriority) +{ + UINT32 nTileNumber, nTileAttrib; + UINT8* pTileStart; + UINT8 nOpacity; + + UINT32** pMyTileQueue = &pTileQueue[i << 4]; + + *pMyTileQueue[nPriority] = 0; + pMyTileQueue[nPriority] = &pTileQueueData[i][nPriority * 512 * 3 * 2]; + + while ((nTileNumber = *pMyTileQueue[nPriority]++) != 0) { + nTileXPos = (INT16)(*pMyTileQueue[nPriority] >> 16); + nTileYPos = (INT16)(*pMyTileQueue[nPriority]++ & 0xFFFF); + nTileAttrib = nTileNumber; + nTileNumber = ((nTileNumber & 0x1FFF) << 2) + GP9001TileBank[(nTileNumber >> 13) & 7]; + + pTileStart = GP9001ROM[i] + (nTileNumber << 5); + pTilePalette = &ToaPalette[(nTileAttrib >> 12) & 0x07F0]; + + if (nTileXPos >= 0 && nTileXPos < 304 && nTileYPos >= 0 && nTileYPos < 224) { + INT32 nTileWidth = 8 * nBurnColumn; + pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow); + + if ((nOpacity = GP9001TileAttrib[i][nTileNumber]) != 0) { + pTileData = (UINT32*)pTileStart; + RenderTile[nOpacity - 1](); + } + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 1]) != 0) { + pTile += nTileWidth; + pTileData = (UINT32*)(pTileStart + 32); + RenderTile[nOpacity - 1](); + pTile -= nTileWidth; + } + pTile += 8 * nBurnRow; + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 2]) != 0) { + pTileData = (UINT32*)(pTileStart + 64); + RenderTile[nOpacity - 1](); + } + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 3]) != 0) { + pTile += nTileWidth; + pTileData = (UINT32*)(pTileStart + 96); + RenderTile[nOpacity - 1](); + } + } else { + INT32 nTileWidth = 8 * nBurnColumn; + pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow); + + if ((nOpacity = GP9001TileAttrib[i][nTileNumber]) != 0) { + if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) { + pTileData = (UINT32*)pTileStart; + if (nTileXPos > 0 && nTileXPos <= 312 && nTileYPos > 0 && nTileYPos <= 232) { + RenderTile[nOpacity - 1](); + } else { + RenderTile[nOpacity](); + } + } + } + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 1]) != 0) { + pTile += nTileWidth; + nTileXPos += 8; + if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) { + pTileData = (UINT32*)(pTileStart + 32); + if (nTileXPos > 0 && nTileXPos <= 312 && nTileYPos > 0 && nTileYPos <= 232) { + RenderTile[nOpacity - 1](); + } else { + RenderTile[nOpacity](); + } + } + nTileXPos -= 8; + pTile -= nTileWidth; + } + nTileYPos += 8; + pTile += 8 * nBurnRow; + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 2]) != 0) { + if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) { + pTileData = (UINT32*)(pTileStart + 64); + if (nTileXPos > 0 && nTileXPos <= 312 && nTileYPos > 0 && nTileYPos <= 232) { + RenderTile[nOpacity - 1](); + } else { + RenderTile[nOpacity](); + } + } + } + if ((nOpacity = GP9001TileAttrib[i][nTileNumber + 3]) != 0) { + nTileXPos += 8; + pTile += nTileWidth; + if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) { + pTileData = (UINT32*)(pTileStart + 96); + if (nTileXPos > 0 && nTileXPos <= 312 && nTileYPos > 0 && nTileYPos <= 232) { + RenderTile[nOpacity - 1](); + } else { + RenderTile[nOpacity](); + } + } + } + } + } +} + +INT32 ToaBufferGP9001Sprites() +{ + +#if 0 + pSpriteBuffer[0] = GP9001RAM[0] + 0x3000; + if (nControllers > 1) { + pSpriteBuffer[1] = GP9001RAM[1] + 0x3000; + } +#else + + pSpriteBuffer[0] = pSpriteBufferData[0] + 0x0800 * nSpriteBuffer; + if (nControllers > 1) { + pSpriteBuffer[1] = pSpriteBufferData[1] + 0x0800 * nSpriteBuffer; + } + + nSpriteBuffer ^= 1; + + memcpy(pSpriteBufferData[0] + 0x0800 * nSpriteBuffer, GP9001RAM[0] + 0x3000, 0x0800); + if (nControllers > 1) { + memcpy(pSpriteBufferData[1] + 0x0800 * nSpriteBuffer, GP9001RAM[1] + 0x3000, 0x0800); + } +#endif + + return 0; +} + +INT32 ToaRenderGP9001() +{ + if (nLastBPP != nBurnBpp ) { + nLastBPP = nBurnBpp; + +#ifdef DRIVER_ROTATION + if (bRotatedScreen) { + RenderTile = RenderTile_ROT270[nBurnBpp - 2]; + } else { + RenderTile = RenderTile_ROT0[nBurnBpp - 2]; + } +#else + RenderTile = RenderTile_ROT0[nBurnBpp - 2]; +#endif + } + + PrepareTiles(); + PrepareSprites(); + + if (nControllers > 1) { + if (nMode == 2) { // Dogyuun + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + RenderTileQueue(1, nPriority); + RenderSpriteQueue(1, nPriority); + + } + for (INT32 nPriority = 0; nPriority < 16; nPriority++) { + RenderTileQueue(0, nPriority); + RenderSpriteQueue(0, nPriority); + + } + } else { // Batsugun +// printf("%04X %04X %04X\n", GP9001Reg[1][0], GP9001Reg[1][2], GP9001Reg[1][4]); + + if ((((GP9001Reg[1][0] + nLayer0XOffset) && (GP9001Reg[1][2] + nLayer1XOffset)) || (GP9001Reg[0][4] + nLayer1XOffset < 0)) && (GP9001Reg[1][4] + nLayer2XOffset == 0)) { + RenderTileQueue(0, 0); + RenderTileQueue(1, 0); + } else { + RenderTileQueue(1, 0); + RenderTileQueue(0, 0); + } + + for (INT32 nPriority = 1; nPriority < 16; nPriority++) { + RenderTileQueue(0, nPriority); + if (nPriority < 4) { + RenderTileQueue(1, nPriority); + } + RenderSpriteQueue(0, nPriority - 1); + } + RenderSpriteQueue(0, 15); + + RenderSpriteQueue(1, 0); + for (INT32 nPriority = 1; nPriority < 16; nPriority++) { + if (nPriority >= 4) { + RenderTileQueue(1, nPriority); + } + RenderSpriteQueue(1, nPriority); + } + } + } else { + if (nSpritePriority) { + for (INT32 nPriority = 0; nPriority < nSpritePriority; nPriority++) { + RenderTileQueue(0, nPriority); + } + } + for (INT32 nPriority = nSpritePriority; nPriority < 16; nPriority++) { + RenderTileQueue(0, nPriority ); + RenderSpriteQueue(0, nPriority - nSpritePriority); + } + if (nSpritePriority) { + for (INT32 nPriority = 16 - nSpritePriority; nPriority < 16; nPriority++) { + RenderSpriteQueue(0, nPriority); + } + } + } + + return 0; +} + +INT32 ToaInitGP9001(INT32 n) +{ + INT32 nSize; + + if (n < 1 || n > 3) { + return 1; + } else { + nMode = n; + } + + if (n > 1) { + nControllers = 2; + } else { + nControllers = 1; + } + + nLastBPP = 0; + + for (INT32 i = 0; i < nControllers; i++) { + + nMaxTile[i] = (nGP9001ROMSize[i] - 1) >> 7; + nMaxSprite[i] = (nGP9001ROMSize[i] - 1) >> 5; + + nSize = 512 * 3 * 0x10 * 2 * sizeof(INT32); + pTileQueueData[i] = (UINT32*)malloc(nSize); + memset(pTileQueueData[i], 0, nSize); + + nSize = 0x10 * 0x101 * sizeof(UINT8*); + pSpriteQueueData[i] = (UINT8**)malloc(nSize); + memset(pSpriteQueueData[i], 0, nSize); + + nSize = 0x0800 * 2; + pSpriteBufferData[i] = (UINT8*)malloc(nSize); + memset(pSpriteBufferData[i], 0, nSize); + + GP9001TileAttrib[i] = (UINT8*)malloc(nGP9001ROMSize[i] >> 5); + for (UINT32 j = 0; j < (nGP9001ROMSize[i] >> 5); j++) { + bool bTransparent = true, bSolid = true; + INT32 nTwoPixels; + for (UINT32 k = (j << 5); k < ((j << 5) + 32); k++) { + if ((nTwoPixels = GP9001ROM[i][k]) != 0) { + bTransparent = false; + } + if ((nTwoPixels & 0xF0) == 0 || (nTwoPixels & 0x0F) == 0) { + bSolid = false; + } + } + if (bTransparent) { + GP9001TileAttrib[i][j] = 0; + } else { + if (bSolid) { + GP9001TileAttrib[i][j] = 9; + } else { + GP9001TileAttrib[i][j] = 1; + } + } + } + } + + // Mark the rubbish tiles that appear on level 1 of Batsugun transparent + if (nMode == 3) { + for (INT32 i = 0; i < 16; i++) { + GP9001TileAttrib[1][(0x225C << 2) + i] = 0; + } + } + + for (INT32 i = 0; i < 8; i++) { + GP9001TileBank[i] = i << 15; + } + + nSpriteBuffer = 0; + + ToaBufferGP9001Sprites(); + ToaBufferGP9001Sprites(); + + if (!nSpriteXOffset){ + nSpriteXOffset = 0x024; + } + if (!nSpriteYOffset){ + nSpriteYOffset = -0x01; + } + + if (!nLayer0XOffset) { + nLayer0XOffset = -0x01D5; + } + if (!nLayer1XOffset) { + nLayer1XOffset = -0x01D7; + } + if (!nLayer2XOffset) { + nLayer2XOffset = -0x01D9; + } + + if (!nLayer0YOffset) { + nLayer0YOffset = -0x01EF; + } + if (!nLayer1YOffset) { + nLayer1YOffset = -0x01EF; + } + if (!nLayer2YOffset) { + nLayer2YOffset = -0x01EF; + } + + return 0; +} + +INT32 ToaExitGP9001() +{ + nSpriteXOffset = 0; + nSpriteYOffset = 0; + nSpritePriority = 0; + + nLayer0XOffset = 0; + nLayer1XOffset = 0; + nLayer2XOffset = 0; + nLayer0YOffset = 0; + nLayer1YOffset = 0; + nLayer2YOffset = 0; + + for (INT32 i = 0; i < nControllers; i++) { + if (pSpriteBufferData[i]) { + free(pSpriteBufferData[i]); + pSpriteBufferData[i] = NULL; + } + + if (pSpriteQueueData[i]) { + free(pSpriteQueueData[i]); + pSpriteQueueData[i] = NULL; + } + + if (pTileQueueData[i]) { + free(pTileQueueData[i]); + pTileQueueData[i] = NULL; + } + + if (GP9001TileAttrib[i]) { + free(GP9001TileAttrib[i]); + GP9001TileAttrib[i] = NULL; + } + + } + + return 0; +} + +INT32 ToaScanGP9001(INT32 nAction, INT32* pnMin) +{ + if (nAction & ACB_VOLATILE) { // Scan volatile data + + if (pnMin) { + *pnMin = 0x029496; + } + + SCAN_VAR(nSpriteBuffer); + + SCAN_VAR(GP9001Pointer); + SCAN_VAR(GP9001Regnum); + SCAN_VAR(GP9001TileBank); + } + + return 0; +} diff --git a/src/burn/drivers/toaplan/toa_gp9001_render.h b/src/burn/drivers/toaplan/toa_gp9001_render.h new file mode 100644 index 00000000..39a4a6ac --- /dev/null +++ b/src/burn/drivers/toaplan/toa_gp9001_render.h @@ -0,0 +1,185 @@ +// Graphics format: 8 × 8 pixel tiles, 4 bits/pixel. + +// Create a unique name for each of the functions +#define FN(a,b,c,d,e) RenderTile ## a ## _ROT ## b ## c ## d ## e +#define FUNCTIONNAME(a,b,c,d,e) FN(a,b,c,d,e) + +#if ROT == 0 + + #if XFLIP == 0 + #define ADVANCECOLUMN pPixel += (BPP >> 3) + #elif XFLIP == 1 + #define ADVANCECOLUMN pPixel -= (BPP >> 3) + #else + #error illegal XFLIP value + #endif + + #if YFLIP == 0 + #define ADVANCEROW pTileRow += ((BPP >> 3) * 320) + #elif YFLIP == 1 + #define ADVANCEROW pTileRow -= ((BPP >> 3) * 320) + #else + #error illegal YFLIP value + #endif + +#elif ROT == 270 + + #if XFLIP == 0 + #define ADVANCECOLUMN pPixel -= ((BPP >> 3) * 240) + #elif XFLIP == 1 + #define ADVANCECOLUMN pPixel += ((BPP >> 3) * 240) + #else + #error illegal XFLIP value + #endif + + #if YFLIP == 0 + #define ADVANCEROW pTileRow += (BPP >> 3) + #elif YFLIP == 1 + #define ADVANCEROW pTileRow -= (BPP >> 3) + #else + #error illegal YFLIP value + #endif + +#else + #error unsupported rotation angle specified +#endif + +#if DOCLIP == 0 + #define CLIP _NOCLIP + #define TESTCLIP(x) (1) +#elif DOCLIP == 1 + #define CLIP _CLIP + #define TESTCLIP(x) (nTileXPos >= -(x) && nTileXPos < (320 - (x))) +#else + #error illegal doclip value. +#endif + +#if ISOPAQUE == 0 + #define OPACITY _TRANS + #define TESTCOLOUR(x) (x) +#elif ISOPAQUE == 1 + #define OPACITY _OPAQUE + #define TESTCOLOUR(x) (1) +#else + #error illegal isopaque value +#endif + +#if BPP == 16 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT16*)pPixel) = (UINT16)pTilePalette[b]; \ + } +#elif BPP == 24 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + UINT32 nRGB = pTilePalette[b]; \ + pPixel[0] = (UINT8)nRGB; \ + pPixel[1] = (UINT8)(nRGB >> 8); \ + pPixel[2] = (UINT8)(nRGB >> 16); \ + } +#elif BPP == 32 + #define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTCLIP(a)) { \ + *((UINT32*)pPixel) = (UINT32)pTilePalette[b]; \ + } +#else + #error unsupported bitdepth specified. +#endif + +// For decorating the function name +#if XFLIP == 1 + #if YFLIP == 1 + #define FLIP _FLIPXY + #else + #define FLIP _FLIPX + #endif +#elif YFLIP == 1 + #define FLIP _FLIPY +#else + #define FLIP _NOFLIP +#endif + +static void FUNCTIONNAME(BPP,ROT,FLIP,CLIP,OPACITY)() +{ + UINT8 *pTileRow, *pPixel; + INT32 y, nColour; + + #if ROT == 0 + #if YFLIP == 0 + for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) { + #else + for (y = 7, pTileRow = pTile + ((BPP >> 3) * 320 * 7); y >= 0; y--, ADVANCEROW) { + #endif + #else + #if YFLIP == 0 + for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) { + #else + for (y = 7, pTileRow = pTile + ((BPP >> 3) * 7); y >= 0; y--, ADVANCEROW) { + #endif + #endif + + #if DOCLIP == 1 + if (nTileYPos + y < 0 || nTileYPos + y >= 240) { + pTileData++; + continue; + } + #endif + + #if ROT == 0 + #if XFLIP == 0 + #define OFFSET(a) a + pPixel = pTileRow; + #else + #define OFFSET(a) (7 - a) + pPixel = pTileRow + ((BPP >> 3) * 7); + #endif + #else + #if XFLIP == 0 + #define OFFSET(a) a + pPixel = pTileRow; + #else + #define OFFSET(a) (7 - a) + pPixel = pTileRow - ((BPP >> 3) * 240 * 7); + #endif + #endif + + nColour = *pTileData++; + PLOTPIXEL(OFFSET(0), nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(OFFSET(1), nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(OFFSET(2), nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(OFFSET(3), nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(OFFSET(4), nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(OFFSET(5), nColour & 0x0F); + ADVANCECOLUMN; + + nColour >>= 4; + PLOTPIXEL(OFFSET(6), nColour & 0x0F); + ADVANCECOLUMN; + nColour >>= 4; + PLOTPIXEL(OFFSET(7), nColour & 0x0F); + + #undef OFFSET + + } +} + +#undef FLIP +#undef CLIP +#undef PLOTPIXEL +#undef TESTCLIP +#undef TESTCOLOUR +#undef ADVANCEROW +#undef ADVANCECOLUMN +#undef OPACITY +#undef FUNCTIONNAME +#undef FN + diff --git a/src/burn/drivers/toaplan/toa_palette.cpp b/src/burn/drivers/toaplan/toa_palette.cpp new file mode 100644 index 00000000..e4be87c7 --- /dev/null +++ b/src/burn/drivers/toaplan/toa_palette.cpp @@ -0,0 +1,60 @@ +#include "toaplan.h" +// Toaplan -- palette functions + +UINT8* ToaPalSrc; // Pointer to input palette +UINT8* ToaPalSrc2; +UINT32* ToaPalette; +UINT32* ToaPalette2; +INT32 nToaPalLen; + +UINT8 ToaRecalcPalette; // Set to 1 to force recalculation of the entire palette (not needed now) + +INT32 ToaPalInit() +{ + return 0; +} + +INT32 ToaPalExit() +{ + return 0; +} + +inline static UINT32 CalcCol(UINT16 nColour) +{ + INT32 r, g, b; + + r = (nColour & 0x001F) << 3; // Red + r |= r >> 5; + g = (nColour & 0x03E0) >> 2; // Green + g |= g >> 5; + b = (nColour & 0x7C00) >> 7; // Blue + b |= b >> 5; + + return BurnHighCol(r, g, b, 0); +} + +INT32 ToaPalUpdate() +{ + UINT16* ps = (UINT16*)ToaPalSrc; + UINT32* pd = ToaPalette; + + pBurnDrvPalette = ToaPalette; + + for (INT32 i = 0; i < nToaPalLen; i++) { + pd[i] = CalcCol(ps[i]); + } + return 0; +} + +INT32 ToaPal2Update() +{ + UINT16* ps = (UINT16*)ToaPalSrc2; + UINT32* pd = ToaPalette2; + +// pBurnDrvPalette = ToaPalette2; + + for (INT32 i = 0; i < nToaPalLen; i++) { + pd[i] = CalcCol(ps[i]); + } + return 0; +} diff --git a/src/burn/drivers/toaplan/toaplan.cpp b/src/burn/drivers/toaplan/toaplan.cpp new file mode 100644 index 00000000..d8dc9ef3 --- /dev/null +++ b/src/burn/drivers/toaplan/toaplan.cpp @@ -0,0 +1,148 @@ +#include "toaplan.h" + +UINT8* RomZ80; +UINT8* RamZ80; + +// Used to keep track of emulated CPU cycles +INT32 nCyclesDone[2], nCyclesTotal[2]; +INT32 nCyclesSegment; + +INT32 nToaCyclesScanline; +INT32 nToaCyclesDisplayStart; +INT32 nToaCyclesVBlankStart; + +// Variables for the graphics drawing +bool bRotatedScreen; +UINT8* pBurnBitmap; +INT32 nBurnColumn; +INT32 nBurnRow; + +// This function loads interleaved code ROMs. +// All even roms should be first, followed by all odd ROMs. +INT32 ToaLoadCode(UINT8* pROM, INT32 nStart, INT32 nCount) +{ + nCount >>= 1; + + for (INT32 nOdd = 0; nOdd < 2; nOdd++) { + UINT8* pLoad = pROM + (nOdd ^ 1); // ^1 for byteswapped + + for (INT32 i = 0; i < nCount; i++) { + struct BurnRomInfo ri; + // Load these even/odd bytes + if (BurnLoadRom(pLoad, nStart + i, 2)) { + return 1; + } + + // Increment position by the length of the rom * 2 + ri.nLen = 0; + BurnDrvGetRomInfo(&ri, nStart + i); + pLoad += ri.nLen << 1; + } + nStart += nCount; + } + return 0; +} + +// This function decodes the tile data for the GP9001 chip in place. +INT32 ToaLoadGP9001Tiles(UINT8* pDest, INT32 nStart, INT32 nNumFiles, INT32 nROMSize, bool bSwap) // bSwap = false +{ + UINT8* pTile; + INT32 nSwap; + + for (INT32 i = 0; i < (nNumFiles >> 1); i++) { + BurnLoadRom(pDest + (i * 2 * nROMSize / nNumFiles), nStart + i, 2); + BurnLoadRom(pDest + (i * 2 * nROMSize / nNumFiles) + 1, nStart + (nNumFiles >> 1) + i, 2); + } + + BurnUpdateProgress(0.0, _T("Decoding graphics..."), 0); + + if (bSwap) { + nSwap = 2; + } else { + nSwap = 0; + } + + for (pTile = pDest; pTile < (pDest + nROMSize); pTile += 4) { + UINT8 data[4]; + for (INT32 n = 0; n < 4; n++) { + INT32 m = 7 - (n << 1); + UINT8 nPixels = ((pTile[0 ^ nSwap] >> m) & 1) << 0; + nPixels |= ((pTile[2 ^ nSwap] >> m) & 1) << 1; + nPixels |= ((pTile[1 ^ nSwap] >> m) & 1) << 2; + nPixels |= ((pTile[3 ^ nSwap] >> m) & 1) << 3; + nPixels |= ((pTile[0 ^ nSwap] >> (m - 1)) & 1) << 4; + nPixels |= ((pTile[2 ^ nSwap] >> (m - 1)) & 1) << 5; + nPixels |= ((pTile[1 ^ nSwap] >> (m - 1)) & 1) << 6; + nPixels |= ((pTile[3 ^ nSwap] >> (m - 1)) & 1) << 7; + + data[n] = nPixels; + } + + for (INT32 n = 0; n < 4; n++) { + pTile[n] = data[n]; + } + } + return 0; +} + +// This function fills the screen with the first palette entry +void ToaClearScreen(INT32 PalOffset) +{ + if (*ToaPalette) { + switch (nBurnBpp) { + case 4: { + UINT32* pClear = (UINT32*)pBurnDraw; + UINT32 nColour = ToaPalette[PalOffset]; + for (INT32 i = 0; i < 320 * 240 / 8; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + + case 3: { + UINT8* pClear = pBurnDraw; + UINT16 nColour = ToaPalette[PalOffset]; + UINT8 r = nColour; + UINT8 g = (r >> 8) & 0xFF; + UINT8 b = (r >> 16) & 0xFF; + r &= 0xFF; + for (INT32 i = 0; i < 320 * 240; i++) { + *pClear++ = r; + *pClear++ = g; + *pClear++ = b; + } + break; + } + + case 2: { + UINT32* pClear = (UINT32*)pBurnDraw; + UINT32 nColour = ToaPalette[PalOffset] | ToaPalette[PalOffset] << 16; + for (INT32 i = 0; i < 320 * 240 / 16; i++) { + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + *pClear++ = nColour; + } + break; + } + } + } else { + memset(pBurnDraw, 0, 320 * 240 * nBurnBpp); + } +} + +void ToaZExit() +{ + ZetExit(); +} diff --git a/src/burn/drivers/toaplan/toaplan.h b/src/burn/drivers/toaplan/toaplan.h new file mode 100644 index 00000000..3c595f36 --- /dev/null +++ b/src/burn/drivers/toaplan/toaplan.h @@ -0,0 +1,292 @@ +#include "burnint.h" +#include "msm6295.h" +#include "burn_ym2151.h" +#include "burn_ym3812.h" + +// Uncomment to have the driver perform the screen rotation (faster unless 3D hardware is used for blitting). +// #undef DRIVER_ROTATION +// #define DRIVER_ROTATION + +const INT32 TOA_68K_SPEED = 16000000; +const INT32 TOA_Z80_SPEED = 4000000; +const INT32 TOA_VBLANK_LINES = 22; + +extern INT32 Hellfire; +extern INT32 Rallybik; + +// toaplan.cpp +extern INT32 nToaCyclesScanline; +extern INT32 nToaCyclesDisplayStart; +extern INT32 nToaCyclesVBlankStart; + +INT32 ToaLoadCode(UINT8 *Rom, INT32 nStart, INT32 nCount); +INT32 ToaLoadGP9001Tiles(UINT8* pDest, INT32 nStart, INT32 nNumFiles, INT32 nROMSize, bool bSwap = false); + +void ToaClearScreen(INT32 PalOffset); + +void ToaZExit(); + +extern UINT8* RomZ80; +extern UINT8* RamZ80; + +extern INT32 nCyclesDone[2], nCyclesTotal[2]; +extern INT32 nCyclesSegment; + +#ifdef DRIVER_ROTATION + extern bool bToaRotateScreen; + #define TOA_ROTATE_GRAPHICS_CCW 0 +#else + const bool bToaRotateScreen = false; + #define TOA_ROTATE_GRAPHICS_CCW BDF_ORIENTATION_VERTICAL +#endif + +extern UINT8* pBurnBitmap; +extern INT32 nBurnColumn; +extern INT32 nBurnRow; + +inline void ToaGetBitmap() +{ + if (bToaRotateScreen) { + pBurnBitmap = pBurnDraw + 319 * nBurnPitch; + nBurnColumn = -nBurnPitch; + nBurnRow = nBurnBpp; + } else { + pBurnBitmap = pBurnDraw; + nBurnColumn = nBurnBpp; + nBurnRow = nBurnPitch; + } +} + +inline void ToaClearOpposites(UINT8* nJoystickInputs) +{ + if ((*nJoystickInputs & 0x03) == 0x03) { + *nJoystickInputs &= ~0x03; + } + if ((*nJoystickInputs & 0x0C) == 0x0C) { + *nJoystickInputs &= ~0x0C; + } +} + +// toa_pal.cpp +extern UINT8 *ToaPalSrc; +extern UINT32* ToaPalette; +extern UINT8 ToaRecalcPalette; +extern INT32 nToaPalLen; + +INT32 ToaPalInit(); +INT32 ToaPalExit(); +INT32 ToaPalUpdate(); + +// toa_gp9001.cpp +extern UINT8* GP9001ROM[2]; +extern UINT32 nGP9001ROMSize[2]; + +extern UINT32 GP9001TileBank[8]; + +extern UINT8* GP9001RAM[2]; +extern UINT16* GP9001Reg[2]; + +extern INT32 nSpriteXOffset, nSpriteYOffset, nSpritePriority; + +extern INT32 nLayer0XOffset, nLayer0YOffset, nLayer0Priority; +extern INT32 nLayer1XOffset, nLayer1YOffset, nLayer1Priority; +extern INT32 nLayer2XOffset, nLayer2YOffset, nLayer2Priority; +extern INT32 nLayer3XOffset, nLayer3YOffset; + +INT32 ToaBufferGP9001Sprites(); +INT32 ToaRenderGP9001(); +INT32 ToaInitGP9001(INT32 n = 1); +INT32 ToaExitGP9001(); +INT32 ToaScanGP9001(INT32 nAction, INT32* pnMin); + +inline static void ToaGP9001SetRAMPointer(UINT32 wordValue, const INT32 nController = 0) +{ + extern UINT8* GP9001Pointer[2]; + + wordValue &= 0x1FFF; + GP9001Pointer[nController] = GP9001RAM[nController] + (wordValue << 1); +} + +inline static void ToaGP9001WriteRAM(const UINT16 wordValue, const INT32 nController) +{ + extern UINT8* GP9001Pointer[2]; + + *((UINT16*)(GP9001Pointer[nController])) = wordValue; + GP9001Pointer[nController] += 2; +} + +inline static UINT16 ToaGP9001ReadRAM_Hi(const INT32 nController) +{ + extern UINT8* GP9001Pointer[2]; + + return *((UINT16*)(GP9001Pointer[nController])); +} + +inline static UINT16 ToaGP9001ReadRAM_Lo(const INT32 nController) +{ + extern UINT8* GP9001Pointer[2]; + + return *((UINT16*)(GP9001Pointer[nController] + 2)); +} + +inline static void ToaGP9001SelectRegister(const UINT16 wordValue, const INT32 nController = 0) +{ + extern INT32 GP9001Regnum[2]; + + GP9001Regnum[nController] = wordValue & 0xFF; +} + +inline static void ToaGP9001WriteRegister(const UINT16 wordValue, const INT32 nController = 0) +{ + extern INT32 GP9001Regnum[2]; + + GP9001Reg[nController][GP9001Regnum[nController]] = wordValue; +} + +inline static UINT16 ToaVBlankRegister() +{ + INT32 nCycles = SekTotalCycles(); + + if (nCycles >= nToaCyclesVBlankStart) { + return 1; + } else { + if (nCycles < nToaCyclesDisplayStart) { + return 1; + } + } + return 0; +} + +inline static UINT16 ToaScanlineRegister() +{ + static INT32 nPreviousScanline; + UINT16 nFlags = 0xFE00; + INT32 nCurrentScanline = SekCurrentScanline(); + +#if 0 + // None of the games actually use this + INT32 nCurrentBeamPosition = SekTotalCycles() % nToaCyclesScanline; + if (nCurrentBeamPosition < 64) { + nFlags &= ~0x4000; + } +#endif + + if (nCurrentScanline != nPreviousScanline) { + nPreviousScanline = nCurrentScanline; + nFlags &= ~0x8000; + +// bprintf(PRINT_NORMAL, _T(" - line %3i, PC 0x%08X\n"), nCurrentScanline, SekGetPC(-1)); + + } + + return nFlags | nCurrentScanline; +} + +// toa_extratext.cpp +extern UINT8* ExtraTROM; +extern UINT8* ExtraTRAM; +extern UINT8* ExtraTScroll; +extern UINT8* ExtraTSelect; +extern INT32 nExtraTXOffset; + +INT32 ToaExtraTextLayer(); +INT32 ToaExtraTextInit(); +void ToaExtraTextExit(); + +// toa_bcu2.cpp +extern INT32 ToaOpaquePriority; +extern UINT8* ToaPalSrc2; +extern UINT32* ToaPalette2; + +extern UINT8* BCU2ROM; +extern UINT8* FCU2ROM; + +extern UINT8* BCU2RAM; +extern UINT8* FCU2RAM; +extern UINT8* FCU2RAMSize; + +extern UINT32 BCU2Pointer; +extern UINT32 FCU2Pointer; + +extern UINT32 nBCU2ROMSize; +extern UINT32 nFCU2ROMSize; + +extern UINT16 BCU2Reg[8]; + +extern INT32 nBCU2TileXOffset; +extern INT32 nBCU2TileYOffset; + +INT32 ToaPal2Update(); +INT32 ToaInitBCU2(); +INT32 ToaExitBCU2(); +void ToaBufferFCU2Sprites(); +INT32 ToaRenderBCU2(); + +// toaplan1.cpp +extern INT32 nToa1Cycles68KSync; + +INT32 ToaLoadTiles(UINT8* pDest, INT32 nStart, INT32 nROMSize); +void toaplan1FMIRQHandler(INT32, INT32 nStatus); +INT32 toaplan1SynchroniseStream(INT32 nSoundRate); +UINT8 __fastcall toaplan1ReadByteZ80RAM(UINT32 sekAddress); +UINT16 __fastcall toaplan1ReadWordZ80RAM(UINT32 sekAddress); +void __fastcall toaplan1WriteByteZ80RAM(UINT32 sekAddress, UINT8 byteValue); +void __fastcall toaplan1WriteWordZ80RAM(UINT32 sekAddress, UINT16 wordValue); + +inline void ToaBCU2SetRAMPointer(UINT32 wordValue) +{ + BCU2Pointer = (wordValue & 0x3FFF) << 1; +} + +inline UINT16 ToaBCU2GetRAMPointer() +{ + return (BCU2Pointer >> 1) & 0x3FFF; +} + +inline void ToaBCU2WriteRAM(const UINT16 wordValue) +{ + ((UINT16*)BCU2RAM)[BCU2Pointer & 0x7FFF] = wordValue; + BCU2Pointer++; +} + +inline UINT16 ToaBCU2ReadRAM_Hi() +{ + return ((UINT16*)BCU2RAM)[BCU2Pointer & 0x7FFF]; +} + +inline UINT16 ToaBCU2ReadRAM_Lo() +{ + return ((UINT16*)BCU2RAM)[(BCU2Pointer & 0x7FFF) + 1]; +} + +inline void ToaFCU2SetRAMPointer(UINT32 wordValue) +{ + FCU2Pointer = wordValue & 0x03FF; +} + +inline UINT16 ToaFCU2GetRAMPointer() +{ + return FCU2Pointer & 0x03FF; +} + +inline void ToaFCU2WriteRAM(const UINT16 wordValue) +{ + ((UINT16*)FCU2RAM)[FCU2Pointer & 0x03FF] = wordValue; + FCU2Pointer++; +} + +inline void ToaFCU2WriteRAMSize(const UINT16 wordValue) +{ + ((UINT16*)FCU2RAMSize)[FCU2Pointer & 0x003F] = wordValue; + FCU2Pointer++; +} + +inline UINT16 ToaFCU2ReadRAM() +{ + return ((UINT16*)FCU2RAM)[FCU2Pointer & 0x03FF]; +} + +inline UINT16 ToaFCU2ReadRAMSize() +{ + return ((UINT16*)FCU2RAMSize)[FCU2Pointer & 0x003F]; +} diff --git a/src/burn/drivers/toaplan/toaplan1.cpp b/src/burn/drivers/toaplan/toaplan1.cpp new file mode 100644 index 00000000..4a3476b7 --- /dev/null +++ b/src/burn/drivers/toaplan/toaplan1.cpp @@ -0,0 +1,105 @@ +#include "toaplan.h" + +// This function decodes the tile data for the GP9001 chip in place. +INT32 ToaLoadTiles(UINT8* pDest, INT32 nStart, INT32 nROMSize) +{ + UINT8* pTile; + INT32 nSwap = 3; + + BurnLoadRom(pDest + 3, nStart + 0, 4); + BurnLoadRom(pDest + 1, nStart + 1, 4); + BurnLoadRom(pDest + 2, nStart + 2, 4); + BurnLoadRom(pDest + 0, nStart + 3, 4); + + for (pTile = pDest; pTile < (pDest + nROMSize); pTile += 4) { + UINT8 data[4]; + for (INT32 n = 0; n < 4; n++) { + INT32 m = 7 - (n << 1); + UINT8 nPixels = ((pTile[0 ^ nSwap] >> m) & 1) << 0; + nPixels |= ((pTile[2 ^ nSwap] >> m) & 1) << 1; + nPixels |= ((pTile[1 ^ nSwap] >> m) & 1) << 2; + nPixels |= ((pTile[3 ^ nSwap] >> m) & 1) << 3; + nPixels |= ((pTile[0 ^ nSwap] >> (m - 1)) & 1) << 4; + nPixels |= ((pTile[2 ^ nSwap] >> (m - 1)) & 1) << 5; + nPixels |= ((pTile[1 ^ nSwap] >> (m - 1)) & 1) << 6; + nPixels |= ((pTile[3 ^ nSwap] >> (m - 1)) & 1) << 7; + + data[n] = nPixels; + } + + for (INT32 n = 0; n < 4; n++) { + pTile[n] = data[n]; + } + } + return 0; +} + +// ---------------------------------------------------------------------------- +// CPU synchronisation + +INT32 nToa1Cycles68KSync; + +// Callbacks for the FM chip + +void toaplan1FMIRQHandler(INT32, INT32 nStatus) +{ + if (nStatus) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else { + ZetSetIRQLine(0, ZET_IRQSTATUS_NONE); + } +} + +INT32 toaplan1SynchroniseStream(INT32 nSoundRate) +{ + return (INT64)ZetTotalCycles() * nSoundRate / 3500000; +} + +// ---------------------------------------------------------------------------- + +inline void toaplan1SynchroniseZ80(INT32 nExtraCycles) +{ + INT32 nCycles = ((INT64)SekTotalCycles() * nCyclesTotal[1] / nCyclesTotal[0]) + nExtraCycles; + + if (nCycles <= ZetTotalCycles()) { + return; + } + + nToa1Cycles68KSync = nCycles - nExtraCycles; + + BurnTimerUpdateYM3812(nCycles); +} + +UINT8 __fastcall toaplan1ReadByteZ80RAM(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" Z80 %04X read\n"), sekAddress & 0x0FFF); + + toaplan1SynchroniseZ80(0); + return RamZ80[(sekAddress & 0x0FFF) >> 1]; +} + +UINT16 __fastcall toaplan1ReadWordZ80RAM(UINT32 sekAddress) +{ +// bprintf(PRINT_NORMAL, _T(" Z80 %04X read\n"), sekAddress & 0x0FFF); + + toaplan1SynchroniseZ80(0); + return RamZ80[(sekAddress & 0x0FFF) >> 1]; +} + +void __fastcall toaplan1WriteByteZ80RAM(UINT32 sekAddress, UINT8 byteValue) +{ +// bprintf(PRINT_NORMAL, _T(" Z80 %04X -> %02X\n"), sekAddress & 0x0FFF, byteValue); + + toaplan1SynchroniseZ80(0); + RamZ80[(sekAddress & 0x0FFF) >> 1] = byteValue; +} + +void __fastcall toaplan1WriteWordZ80RAM(UINT32 sekAddress, UINT16 wordValue) +{ +// bprintf(PRINT_NORMAL, _T(" Z80 %04X -> %04X\n"), sekAddress & 0x0FFF, wordValue); + + toaplan1SynchroniseZ80(0); + RamZ80[(sekAddress & 0x0FFF) >> 1] = wordValue & 0xFF; +} + +// ---------------------------------------------------------------------------- diff --git a/src/burn/hiscore.cpp b/src/burn/hiscore.cpp new file mode 100644 index 00000000..ec15ab34 --- /dev/null +++ b/src/burn/hiscore.cpp @@ -0,0 +1,572 @@ +#include "burnint.h" +#include "vez.h" +#include "sh2.h" +#include "m6502_intf.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "s2650_intf.h" + +// A hiscore.dat support module for FBA - written by Treble Winner, Feb 2009 +// At some point we really need a CPU interface to track CPU types and numbers, +// to make this module and the cheat engine foolproof + +#define MAX_CONFIG_LINE_SIZE 48 + +#define HISCORE_MAX_RANGES 20 + +UINT32 nHiscoreNumRanges; + +#define APPLIED_STATE_NONE 0 +#define APPLIED_STATE_ATTEMPTED 1 +#define APPLIED_STATE_CONFIRMED 2 + +struct _HiscoreMemRange +{ + UINT32 Loaded, nCpu, Address, NumBytes, StartValue, EndValue, ApplyNextFrame, Applied; + UINT8 *Data; +}; + +_HiscoreMemRange HiscoreMemRange[HISCORE_MAX_RANGES]; + +INT32 EnableHiscores; +static INT32 HiscoresInUse; + +static INT32 nCpuType; +extern INT32 nSekCount; + +static void set_cpu_type() +{ + if (nSekCount > -1) + { + nCpuType = 1; // Motorola 68000 + } + else if (nVezCount) + { + nCpuType = 2; // NEC V30 / V33 + } + else if (has_sh2) + { + nCpuType = 3; // Hitachi SH2 + } + else if (nHD6309Count) + { + nCpuType = 7; // HD6309 + } + else if (nM6809Count) + { + nCpuType = 6; // M6809 + } + else if (nHasZet > -1) + { + nCpuType = 5; // Zilog Z80 + } + else if (nM6502Count) + { + nCpuType = 4; // MOS 6502 + } + else if (nM6800Count) + { + nCpuType = 8; // M6800 & Family + } + else if (s2650Count) + { + nCpuType = 9; // S2650 + } + else + { + nCpuType = 0; // Unknown (don't use cheats) + } +} + +static void cpu_open(INT32 nCpu) +{ + switch (nCpuType) + { + case 1: + SekOpen(nCpu); + break; + + case 2: + VezOpen(nCpu); + break; + + case 3: + Sh2Open(nCpu); + break; + + case 4: + M6502Open(nCpu); + break; + + case 5: + ZetOpen(nCpu); + break; + + case 6: + M6809Open(nCpu); + break; + + case 7: + HD6309Open(nCpu); + break; + + case 8: + break; + + case 9: + s2650Open(nCpu); + break; + } +} + +static void cpu_close() +{ + switch (nCpuType) + { + case 1: + SekClose(); + break; + + case 2: + VezClose(); + break; + + case 3: + Sh2Close(); + break; + + case 4: + M6502Close(); + break; + + case 5: + ZetClose(); + break; + + case 6: + M6809Close(); + break; + + case 7: + HD6309Close(); + break; + + case 8: + break; + + case 9: + s2650Close(); + break; + } +} + +/*static INT32 cpu_get_active() +{ + switch (nCpuType) { + case 1: { + return SekGetActive(); + } + + case 2: { + return VezGetActive(); + } + + case 3: { + return Sh2GetActive(); + } + + case 4: { + return m6502GetActive(); + } + + case 5: { + return ZetGetActive(); + } + + case 6: { + return M6809GetActive(); + } + + case 7: { + return HD6309GetActive(); + } + + case 8: { + return -1; + } + + case 9: { + return nActiveS2650; + } + } +} +*/ +static UINT8 cpu_read_byte(UINT32 a) +{ + switch (nCpuType) + { + case 1: + return SekReadByte(a); + + case 2: + return cpu_readmem20(a); + + case 3: + return Sh2ReadByte(a); + + case 4: + return M6502ReadByte(a); + + case 5: + return ZetReadByte(a); + + case 6: + return M6809ReadByte(a); + + case 7: + return HD6309ReadByte(a); + + case 8: + return M6800ReadByte(a); + + case 9: + return s2650_read(a); + } + + return 0; +} + +static void cpu_write_byte(UINT32 a, UINT8 d) +{ + switch (nCpuType) + { + case 1: + SekWriteByteROM(a, d); + break; + + case 2: + cpu_writemem20(a, d); + break; + + case 3: + Sh2WriteByte(a, d); + break; + + case 4: + M6502WriteByte(a, d); + break; + + case 5: + ZetWriteByte(a, d); + break; + + case 6: + M6809WriteByte(a, d); + break; + + case 7: + HD6309WriteByte(a, d); + break; + + case 8: + M6800WriteByte(a, d); + break; + + case 9: + s2650_write(a, d); + break; + } +} + +static UINT32 hexstr2num (const char **pString) +{ + const char *string = *pString; + UINT32 result = 0; + if (string) + { + for(;;) + { + char c = *string++; + INT32 digit; + + if (c>='0' && c<='9') + { + digit = c-'0'; + } + else if (c>='a' && c<='f') + { + digit = 10+c-'a'; + } + else if (c>='A' && c<='F') + { + digit = 10+c-'A'; + } + else + { + if (!c) string = NULL; + break; + } + result = result*16 + digit; + } + *pString = string; + } + return result; +} + +static INT32 is_mem_range (const char *pBuf) +{ + char c; + for(;;) + { + c = *pBuf++; + if (c == 0) return 0; /* premature EOL */ + if (c == ':') break; + } + c = *pBuf; /* character following first ':' */ + + return (c>='0' && c<='9') || + (c>='a' && c<='f') || + (c>='A' && c<='F'); +} + +static INT32 matching_game_name (const char *pBuf, const char *name) +{ + while (*name) + { + if (*name++ != *pBuf++) return 0; + } + return (*pBuf == ':'); +} + +static INT32 CheckHiscoreAllowed() +{ + INT32 Allowed = 1; + + if (!EnableHiscores) Allowed = 0; + if (!(BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED)) Allowed = 0; + + return Allowed; +} + +void HiscoreInit() +{ + if (!CheckHiscoreAllowed()) return; + + HiscoresInUse = 0; + + TCHAR szDatFilename[MAX_PATH]; + _stprintf(szDatFilename, _T("%shiscore.dat"), szAppHiscorePath); + + FILE *fp = _tfopen(szDatFilename, _T("r")); + if (fp) { + char buffer[MAX_CONFIG_LINE_SIZE]; + enum { FIND_NAME, FIND_DATA, FETCH_DATA } mode; + mode = FIND_NAME; + + while (fgets(buffer, MAX_CONFIG_LINE_SIZE, fp)) { + if (mode == FIND_NAME) { + if (matching_game_name(buffer, BurnDrvGetTextA(DRV_NAME))) { + mode = FIND_DATA; + } + } else { + if (is_mem_range(buffer)) { + if (nHiscoreNumRanges < HISCORE_MAX_RANGES) { + const char *pBuf = buffer; + + HiscoreMemRange[nHiscoreNumRanges].Loaded = 0; + HiscoreMemRange[nHiscoreNumRanges].nCpu = hexstr2num(&pBuf); + HiscoreMemRange[nHiscoreNumRanges].Address = hexstr2num(&pBuf); + HiscoreMemRange[nHiscoreNumRanges].NumBytes = hexstr2num(&pBuf); + HiscoreMemRange[nHiscoreNumRanges].StartValue = hexstr2num(&pBuf); + HiscoreMemRange[nHiscoreNumRanges].EndValue = hexstr2num(&pBuf); + HiscoreMemRange[nHiscoreNumRanges].ApplyNextFrame = 0; + HiscoreMemRange[nHiscoreNumRanges].Applied = 0; + HiscoreMemRange[nHiscoreNumRanges].Data = (UINT8*)malloc(HiscoreMemRange[nHiscoreNumRanges].NumBytes); + memset(HiscoreMemRange[nHiscoreNumRanges].Data, 0, HiscoreMemRange[nHiscoreNumRanges].NumBytes); + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Hi Score Memory Range %i Loaded - CPU %i, Address %x, Bytes %02x, Start Val %x, End Val %x\n"), nHiscoreNumRanges, HiscoreMemRange[nHiscoreNumRanges].nCpu, HiscoreMemRange[nHiscoreNumRanges].Address, HiscoreMemRange[nHiscoreNumRanges].NumBytes, HiscoreMemRange[nHiscoreNumRanges].StartValue, HiscoreMemRange[nHiscoreNumRanges].EndValue); +#endif + + nHiscoreNumRanges++; + + mode = FETCH_DATA; + } else { + break; + } + } else { + if (mode == FETCH_DATA) break; + } + } + } + + fclose(fp); + } + + if (nHiscoreNumRanges) HiscoresInUse = 1; + + TCHAR szFilename[MAX_PATH]; + _stprintf(szFilename, _T("%s%s.hi"), szAppHiscorePath, BurnDrvGetText(DRV_NAME)); + + fp = _tfopen(szFilename, _T("r")); + INT32 Offset = 0; + if (fp) { + UINT32 nSize = 0; + + while (!feof(fp)) { + fgetc(fp); + nSize++; + } + + UINT8 *Buffer = (UINT8*)malloc(nSize); + rewind(fp); + + fgets((char*)Buffer, nSize, fp); + + for (UINT32 i = 0; i < nHiscoreNumRanges; i++) { + for (UINT32 j = 0; j < HiscoreMemRange[i].NumBytes; j++) { + HiscoreMemRange[i].Data[j] = Buffer[j + Offset]; + } + Offset += HiscoreMemRange[i].NumBytes; + + HiscoreMemRange[i].Loaded = 1; + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Hi Score Memory Range %i Loaded from file\n"), i); +#endif + } + + if (Buffer) { + free(Buffer); + Buffer = NULL; + } + + fclose(fp); + } + + nCpuType = -1; +} + +void HiscoreReset() +{ + if (!CheckHiscoreAllowed() || !HiscoresInUse) return; + + if (nCpuType == -1) set_cpu_type(); + + for (UINT32 i = 0; i < nHiscoreNumRanges; i++) { + HiscoreMemRange[i].ApplyNextFrame = 0; + HiscoreMemRange[i].Applied = APPLIED_STATE_NONE; + + if (HiscoreMemRange[i].Loaded) { + cpu_open(HiscoreMemRange[i].nCpu); + cpu_write_byte(HiscoreMemRange[i].Address, (UINT8)~HiscoreMemRange[i].StartValue); + if (HiscoreMemRange[i].NumBytes > 1) cpu_write_byte(HiscoreMemRange[i].Address + HiscoreMemRange[i].NumBytes - 1, (UINT8)~HiscoreMemRange[i].EndValue); + cpu_close(); + +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Hi Score Memory Range %i Initted\n"), i); +#endif + } + } +} + +void HiscoreApply() +{ + if (!CheckHiscoreAllowed() || !HiscoresInUse) return; + + if (nCpuType == -1) set_cpu_type(); + + for (UINT32 i = 0; i < nHiscoreNumRanges; i++) { + if (HiscoreMemRange[i].Loaded && HiscoreMemRange[i].Applied == APPLIED_STATE_ATTEMPTED) { + INT32 Confirmed = 1; + cpu_open(HiscoreMemRange[i].nCpu); + for (UINT32 j = 0; j < HiscoreMemRange[i].NumBytes; j++) { + if (cpu_read_byte(HiscoreMemRange[i].Address + j) != HiscoreMemRange[i].Data[j]) { + Confirmed = 0; + } + } + cpu_close(); + + if (Confirmed == 1) { + HiscoreMemRange[i].Applied = APPLIED_STATE_CONFIRMED; +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Applied Hi Score Memory Range %i on frame number %i\n"), i, GetCurrentFrame()); +#endif + } else { + HiscoreMemRange[i].Applied = APPLIED_STATE_NONE; + HiscoreMemRange[i].ApplyNextFrame = 1; +#if 1 && defined FBA_DEBUG + bprintf(PRINT_IMPORTANT, _T("Failed attempt to apply Hi Score Memory Range %i on frame number %i\n"), i, GetCurrentFrame()); +#endif + } + } + + if (HiscoreMemRange[i].Loaded && HiscoreMemRange[i].Applied == APPLIED_STATE_NONE && HiscoreMemRange[i].ApplyNextFrame) { + cpu_open(HiscoreMemRange[i].nCpu); + for (UINT32 j = 0; j < HiscoreMemRange[i].NumBytes; j++) { + cpu_write_byte(HiscoreMemRange[i].Address + j, HiscoreMemRange[i].Data[j]); + } + cpu_close(); + + HiscoreMemRange[i].Applied = APPLIED_STATE_ATTEMPTED; + HiscoreMemRange[i].ApplyNextFrame = 0; + } + + if (HiscoreMemRange[i].Loaded && HiscoreMemRange[i].Applied == APPLIED_STATE_NONE) { + cpu_open(HiscoreMemRange[i].nCpu); + if (cpu_read_byte(HiscoreMemRange[i].Address) == HiscoreMemRange[i].StartValue && cpu_read_byte(HiscoreMemRange[i].Address + HiscoreMemRange[i].NumBytes - 1) == HiscoreMemRange[i].EndValue) { + HiscoreMemRange[i].ApplyNextFrame = 1; + } + cpu_close(); + } + } +} + +void HiscoreExit() +{ + if (!CheckHiscoreAllowed() || !HiscoresInUse) return; + + if (nCpuType == -1) set_cpu_type(); + + TCHAR szFilename[MAX_PATH]; + _stprintf(szFilename, _T("%s%s.hi"), szAppHiscorePath, BurnDrvGetText(DRV_NAME)); + + FILE *fp = _tfopen(szFilename, _T("w")); + if (fp) { + for (UINT32 i = 0; i < nHiscoreNumRanges; i++) { + UINT8 *Buffer = (UINT8*)malloc(HiscoreMemRange[i].NumBytes); + + cpu_open(HiscoreMemRange[i].nCpu); + for (UINT32 j = 0; j < HiscoreMemRange[i].NumBytes; j++) { + Buffer[j] = cpu_read_byte(HiscoreMemRange[i].Address + j); + } + cpu_close(); + + fwrite(Buffer, 1, HiscoreMemRange[i].NumBytes, fp); + + if (Buffer) { + free(Buffer); + Buffer = NULL; + } + } + } + fclose(fp); + + nCpuType = -1; + nHiscoreNumRanges = 0; + + for (UINT32 i = 0; i < HISCORE_MAX_RANGES; i++) { + HiscoreMemRange[i].Loaded = 0; + HiscoreMemRange[i].nCpu = 0; + HiscoreMemRange[i].Address = 0; + HiscoreMemRange[i].NumBytes = 0; + HiscoreMemRange[i].StartValue = 0; + HiscoreMemRange[i].EndValue = 0; + HiscoreMemRange[i].ApplyNextFrame = 0; + HiscoreMemRange[i].Applied = 0; + + free(HiscoreMemRange[i].Data); + HiscoreMemRange[i].Data = NULL; + } +} diff --git a/src/burn/hiscore.h b/src/burn/hiscore.h new file mode 100644 index 00000000..e6b3991c --- /dev/null +++ b/src/burn/hiscore.h @@ -0,0 +1,6 @@ +extern INT32 EnableHiscores; + +void HiscoreInit(); +void HiscoreReset(); +void HiscoreApply(); +void HiscoreExit(); diff --git a/src/burn/load.cpp b/src/burn/load.cpp new file mode 100644 index 00000000..8486526b --- /dev/null +++ b/src/burn/load.cpp @@ -0,0 +1,105 @@ +// Burn - Rom Loading module +#include "burnint.h" + +// Load a rom and separate out the bytes by nGap +// Dest is the memory block to insert the rom into +static INT32 LoadRom(UINT8 *Dest, INT32 i, INT32 nGap, INT32 bXor) +{ + INT32 nRet = 0, nLen = 0; + if (BurnExtLoadRom == NULL) return 1; // Load function was not defined by the application + + // Find the length of the rom (as given by the current driver) + { + struct BurnRomInfo ri; + ri.nType=0; + ri.nLen=0; + BurnDrvGetRomInfo(&ri,i); + if (ri.nType==0) return 0; // Empty rom slot - don't load anything and return success + nLen=ri.nLen; + } + + char* RomName = ""; //add by emufan + BurnDrvGetRomName(&RomName, i, 0); + + if (nLen<=0) return 1; + + if (nGap>1 || bXor) + { + UINT8 *Load=NULL; + UINT8 *pd=NULL,*pl=NULL,*LoadEnd=NULL; + INT32 nLoadLen=0; + + // Allocate space for the file + Load=(UINT8 *)malloc(nLen); + if (Load==NULL) return 1; + memset(Load,0,nLen); + + // Load in the file + nRet=BurnExtLoadRom(Load,&nLoadLen,i); + if (bDoIpsPatch) IpsApplyPatches(Load, RomName); + if (nRet!=0) { if (Load) { free(Load); Load = NULL; } return 1; } + + if (nLoadLen<0) nLoadLen=0; + if (nLoadLen>nLen) nLoadLen=nLen; + + // Loaded rom okay. Now insert into Dest + LoadEnd=Load+nLoadLen; + pd=Dest; pl=Load; + // Quickly copy in the bytes with a gap of 'nGap' between each byte + + if (bXor) + { + do { *pd ^= *pl++; pd+=nGap; } while (pl>(7-(nPix&7)); nBit&=1; + nBit<<=nField; // Move to correct bit for this field + + // use low nibble for each even pixel + if ((nPix&1)==1) nBit<<=4; // use high nibble for each odd pixel + + *pDest|=nBit; // OR into destination + if ((nPix&1)==1) pDest++; + if ((nPix&7)==7) pSrc++; + } + return 0; +} + diff --git a/src/burn/sound/ay8910.c b/src/burn/sound/ay8910.c new file mode 100644 index 00000000..55e2aa69 --- /dev/null +++ b/src/burn/sound/ay8910.c @@ -0,0 +1,744 @@ +/*************************************************************************** + + Modified from ay8910.c from MAME + + + Emulation of the AY-3-8910 / YM2149 sound chip. + + Based on various code snippets by Ville Hallik, Michael Cuddy, + Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria. + +***************************************************************************/ + +#include "driver.h" +#include "state.h" +#include "ay8910.h" + +#define MAX_OUTPUT 0x7fff + +#define STEP 0x8000 + +static void (*AYStreamUpdate)(void); + +INT32 ay8910_index_ym = 0; +static INT32 num = 0, ym_num = 0; + +struct AY8910 +{ + INT32 Channel; + INT32 SampleRate; + read8_handler PortAread; + read8_handler PortBread; + write8_handler PortAwrite; + write8_handler PortBwrite; + INT32 register_latch; + UINT8 Regs[16]; + INT32 lastEnable; + UINT32 UpdateStep; + INT32 PeriodA,PeriodB,PeriodC,PeriodN,PeriodE; + INT32 CountA,CountB,CountC,CountN,CountE; + UINT32 VolA,VolB,VolC,VolE; + UINT8 EnvelopeA,EnvelopeB,EnvelopeC; + UINT8 OutputA,OutputB,OutputC,OutputN; + INT8 CountEnv; + UINT8 Hold,Alternate,Attack,Holding; + INT32 RNG; + UINT32 VolTable[32]; +}; + +/* register id's */ +#define AY_AFINE (0) +#define AY_ACOARSE (1) +#define AY_BFINE (2) +#define AY_BCOARSE (3) +#define AY_CFINE (4) +#define AY_CCOARSE (5) +#define AY_NOISEPER (6) +#define AY_ENABLE (7) +#define AY_AVOL (8) +#define AY_BVOL (9) +#define AY_CVOL (10) +#define AY_EFINE (11) +#define AY_ECOARSE (12) +#define AY_ESHAPE (13) + +#define AY_PORTA (14) +#define AY_PORTB (15) + + +static struct AY8910 AYPSG[MAX_8910]; /* array of PSG's */ + + + +static void _AYWriteReg(INT32 n, INT32 r, INT32 v) +{ + struct AY8910 *PSG = &AYPSG[n]; + INT32 old; + + + PSG->Regs[r] = v; + + /* A note about the period of tones, noise and envelope: for speed reasons,*/ + /* we count down from the period to 0, but careful studies of the chip */ + /* output prove that it instead counts up from 0 until the counter becomes */ + /* greater or equal to the period. This is an important difference when the*/ + /* program is rapidly changing the period to modulate the sound. */ + /* To compensate for the difference, when the period is changed we adjust */ + /* our internal counter. */ + /* Also, note that period = 0 is the same as period = 1. This is mentioned */ + /* in the YM2203 data sheets. However, this does NOT apply to the Envelope */ + /* period. In that case, period = 0 is half as period = 1. */ + switch( r ) + { + case AY_AFINE: + case AY_ACOARSE: + PSG->Regs[AY_ACOARSE] &= 0x0f; + old = PSG->PeriodA; + PSG->PeriodA = (PSG->Regs[AY_AFINE] + 256 * PSG->Regs[AY_ACOARSE]) * PSG->UpdateStep; + if (PSG->PeriodA == 0) PSG->PeriodA = PSG->UpdateStep; + PSG->CountA += PSG->PeriodA - old; + if (PSG->CountA <= 0) PSG->CountA = 1; + break; + case AY_BFINE: + case AY_BCOARSE: + PSG->Regs[AY_BCOARSE] &= 0x0f; + old = PSG->PeriodB; + PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep; + if (PSG->PeriodB == 0) PSG->PeriodB = PSG->UpdateStep; + PSG->CountB += PSG->PeriodB - old; + if (PSG->CountB <= 0) PSG->CountB = 1; + break; + case AY_CFINE: + case AY_CCOARSE: + PSG->Regs[AY_CCOARSE] &= 0x0f; + old = PSG->PeriodC; + PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep; + if (PSG->PeriodC == 0) PSG->PeriodC = PSG->UpdateStep; + PSG->CountC += PSG->PeriodC - old; + if (PSG->CountC <= 0) PSG->CountC = 1; + break; + case AY_NOISEPER: + PSG->Regs[AY_NOISEPER] &= 0x1f; + old = PSG->PeriodN; + PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep; + if (PSG->PeriodN == 0) PSG->PeriodN = PSG->UpdateStep; + PSG->CountN += PSG->PeriodN - old; + if (PSG->CountN <= 0) PSG->CountN = 1; + break; + case AY_ENABLE: + if ((PSG->lastEnable == -1) || + ((PSG->lastEnable & 0x40) != (PSG->Regs[AY_ENABLE] & 0x40))) + { + /* write out 0xff if port set to input */ + if (PSG->PortAwrite) + (*PSG->PortAwrite)(0, (PSG->Regs[AY_ENABLE] & 0x40) ? PSG->Regs[AY_PORTA] : 0xff); + } + + if ((PSG->lastEnable == -1) || + ((PSG->lastEnable & 0x80) != (PSG->Regs[AY_ENABLE] & 0x80))) + { + /* write out 0xff if port set to input */ + if (PSG->PortBwrite) + (*PSG->PortBwrite)(0, (PSG->Regs[AY_ENABLE] & 0x80) ? PSG->Regs[AY_PORTB] : 0xff); + } + + PSG->lastEnable = PSG->Regs[AY_ENABLE]; + break; + case AY_AVOL: + PSG->Regs[AY_AVOL] &= 0x1f; + PSG->EnvelopeA = PSG->Regs[AY_AVOL] & 0x10; + PSG->VolA = PSG->EnvelopeA ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_AVOL] ? PSG->Regs[AY_AVOL]*2+1 : 0]; + break; + case AY_BVOL: + PSG->Regs[AY_BVOL] &= 0x1f; + PSG->EnvelopeB = PSG->Regs[AY_BVOL] & 0x10; + PSG->VolB = PSG->EnvelopeB ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_BVOL] ? PSG->Regs[AY_BVOL]*2+1 : 0]; + break; + case AY_CVOL: + PSG->Regs[AY_CVOL] &= 0x1f; + PSG->EnvelopeC = PSG->Regs[AY_CVOL] & 0x10; + PSG->VolC = PSG->EnvelopeC ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_CVOL] ? PSG->Regs[AY_CVOL]*2+1 : 0]; + break; + case AY_EFINE: + case AY_ECOARSE: + old = PSG->PeriodE; + PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep; + if (PSG->PeriodE == 0) PSG->PeriodE = PSG->UpdateStep / 2; + PSG->CountE += PSG->PeriodE - old; + if (PSG->CountE <= 0) PSG->CountE = 1; + break; + case AY_ESHAPE: + /* envelope shapes: + C AtAlH + 0 0 x x \___ + + 0 1 x x /___ + + 1 0 0 0 \\\\ + + 1 0 0 1 \___ + + 1 0 1 0 \/\/ + ___ + 1 0 1 1 \ + + 1 1 0 0 //// + ___ + 1 1 0 1 / + + 1 1 1 0 /\/\ + + 1 1 1 1 /___ + + The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it + has twice the steps, happening twice as fast. Since the end result is + just a smoother curve, we always use the YM2149 behaviour. + */ + PSG->Regs[AY_ESHAPE] &= 0x0f; + PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04) ? 0x1f : 0x00; + if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0) + { + /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */ + PSG->Hold = 1; + PSG->Alternate = PSG->Attack; + } + else + { + PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01; + PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02; + } + PSG->CountE = PSG->PeriodE; + PSG->CountEnv = 0x1f; + PSG->Holding = 0; + PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack]; + if (PSG->EnvelopeA) PSG->VolA = PSG->VolE; + if (PSG->EnvelopeB) PSG->VolB = PSG->VolE; + if (PSG->EnvelopeC) PSG->VolC = PSG->VolE; + break; + case AY_PORTA: + if (PSG->Regs[AY_ENABLE] & 0x40) + { + if (PSG->PortAwrite) + (*PSG->PortAwrite)(0, PSG->Regs[AY_PORTA]); +// else +// logerror("PC %04x: warning - write %02x to 8910 #%d Port A\n",activecpu_get_pc(),PSG->Regs[AY_PORTA],n); + } +// else +// { +// logerror("warning: write to 8910 #%d Port A set as input - ignored\n",n); +// } + break; + case AY_PORTB: + if (PSG->Regs[AY_ENABLE] & 0x80) + { + if (PSG->PortBwrite) + (*PSG->PortBwrite)(0, PSG->Regs[AY_PORTB]); +// else +// logerror("PC %04x: warning - write %02x to 8910 #%d Port B\n",activecpu_get_pc(),PSG->Regs[AY_PORTB],n); + } +// else +// { +// logerror("warning: write to 8910 #%d Port B set as input - ignored\n",n); +// } + break; + } +} + + +/* write a register on AY8910 chip number 'n' */ +static void AYWriteReg(INT32 chip, INT32 r, INT32 v) +{ + if (r > 15) return; + if (r < 14) + { + struct AY8910 *PSG = &AYPSG[chip]; + + if (r == AY_ESHAPE || PSG->Regs[r] != v) + { +// /* update the output buffer before changing the register */ +// stream_update(PSG->Channel,0); + AYStreamUpdate(); + } + } + + _AYWriteReg(chip,r,v); +} + + + +static UINT8 AYReadReg(INT32 n, INT32 r) +{ + struct AY8910 *PSG = &AYPSG[n]; + + + if (r > 15) return 0; + + switch (r) + { + case AY_PORTA: +// if ((PSG->Regs[AY_ENABLE] & 0x40) != 0) +// logerror("warning: read from 8910 #%d Port A set as output\n",n); + /* + even if the port is set as output, we still need to return the external + data. Some games, like kidniki, need this to work. + */ + if (PSG->PortAread) PSG->Regs[AY_PORTA] = (*PSG->PortAread)(0); +// else logerror("PC %04x: warning - read 8910 #%d Port A\n",activecpu_get_pc(),n); + break; + case AY_PORTB: +// if ((PSG->Regs[AY_ENABLE] & 0x80) != 0) +// logerror("warning: read from 8910 #%d Port B set as output\n",n); + if (PSG->PortBread) PSG->Regs[AY_PORTB] = (*PSG->PortBread)(0); +// else logerror("PC %04x: warning - read 8910 #%d Port B\n",activecpu_get_pc(),n); + break; + } + return PSG->Regs[r]; +} + +void AY8910Write(INT32 chip, INT32 a, INT32 data) +{ + struct AY8910 *PSG = &AYPSG[chip]; + + if (a & 1) + { /* Data port */ + AYWriteReg(chip,PSG->register_latch,data); + } + else + { /* Register port */ + PSG->register_latch = data & 0x0f; + } +} + +INT32 AY8910Read(INT32 chip) +{ + struct AY8910 *PSG = &AYPSG[chip]; + + return AYReadReg(chip,PSG->register_latch); +} + +void AY8910Update(INT32 chip, INT16 **buffer, INT32 length) +{ + struct AY8910 *PSG = &AYPSG[chip]; + INT16 *buf1,*buf2,*buf3; + INT32 outn; + + buf1 = buffer[0]; + buf2 = buffer[1]; + buf3 = buffer[2]; + + /* The 8910 has three outputs, each output is the mix of one of the three */ + /* tone generators and of the (single) noise generator. The two are mixed */ + /* BEFORE going into the DAC. The formula to mix each channel is: */ + /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */ + /* Note that this means that if both tone and noise are disabled, the output */ + /* is 1, not 0, and can be modulated changing the volume. */ + + + /* If the channels are disabled, set their output to 1, and increase the */ + /* counter, if necessary, so they will not be inverted during this update. */ + /* Setting the output to 1 is necessary because a disabled channel is locked */ + /* into the ON state (see above); and it has no effect if the volume is 0. */ + /* If the volume is 0, increase the counter, but don't touch the output. */ + if (PSG->Regs[AY_ENABLE] & 0x01) + { + if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP; + PSG->OutputA = 1; + } + else if (PSG->Regs[AY_AVOL] == 0) + { + /* note that I do count += length, NOT count = length + 1. You might think */ + /* it's the same since the volume is 0, but doing the latter could cause */ + /* interferencies when the program is rapidly modulating the volume. */ + if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP; + } + if (PSG->Regs[AY_ENABLE] & 0x02) + { + if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP; + PSG->OutputB = 1; + } + else if (PSG->Regs[AY_BVOL] == 0) + { + if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP; + } + if (PSG->Regs[AY_ENABLE] & 0x04) + { + if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP; + PSG->OutputC = 1; + } + else if (PSG->Regs[AY_CVOL] == 0) + { + if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP; + } + + /* for the noise channel we must not touch OutputN - it's also not necessary */ + /* since we use outn. */ + if ((PSG->Regs[AY_ENABLE] & 0x38) == 0x38) /* all off */ + if (PSG->CountN <= length*STEP) PSG->CountN += length*STEP; + + outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]); + + + /* buffering loop */ + while (length) + { + int vola,volb,volc; + int left; + + /* vola, volb and volc keep track of how long each square wave stays */ + /* in the 1 position during the sample period. */ + vola = volb = volc = 0; + + left = STEP; + do + { + int nextevent; + + if (PSG->CountN < left) nextevent = PSG->CountN; + else nextevent = left; + + if (outn & 0x08) + { + if (PSG->OutputA) vola += PSG->CountA; + PSG->CountA -= nextevent; + /* PeriodA is the half period of the square wave. Here, in each */ + /* loop I add PeriodA twice, so that at the end of the loop the */ + /* square wave is in the same status (0 or 1) it was at the start. */ + /* vola is also incremented by PeriodA, since the wave has been 1 */ + /* exactly half of the time, regardless of the initial position. */ + /* If we exit the loop in the middle, OutputA has to be inverted */ + /* and vola incremented only if the exit status of the square */ + /* wave is 1. */ + while (PSG->CountA <= 0) + { + PSG->CountA += PSG->PeriodA; + if (PSG->CountA > 0) + { + PSG->OutputA ^= 1; + if (PSG->OutputA) vola += PSG->PeriodA; + break; + } + PSG->CountA += PSG->PeriodA; + vola += PSG->PeriodA; + } + if (PSG->OutputA) vola -= PSG->CountA; + } + else + { + PSG->CountA -= nextevent; + while (PSG->CountA <= 0) + { + PSG->CountA += PSG->PeriodA; + if (PSG->CountA > 0) + { + PSG->OutputA ^= 1; + break; + } + PSG->CountA += PSG->PeriodA; + } + } + + if (outn & 0x10) + { + if (PSG->OutputB) volb += PSG->CountB; + PSG->CountB -= nextevent; + while (PSG->CountB <= 0) + { + PSG->CountB += PSG->PeriodB; + if (PSG->CountB > 0) + { + PSG->OutputB ^= 1; + if (PSG->OutputB) volb += PSG->PeriodB; + break; + } + PSG->CountB += PSG->PeriodB; + volb += PSG->PeriodB; + } + if (PSG->OutputB) volb -= PSG->CountB; + } + else + { + PSG->CountB -= nextevent; + while (PSG->CountB <= 0) + { + PSG->CountB += PSG->PeriodB; + if (PSG->CountB > 0) + { + PSG->OutputB ^= 1; + break; + } + PSG->CountB += PSG->PeriodB; + } + } + + if (outn & 0x20) + { + if (PSG->OutputC) volc += PSG->CountC; + PSG->CountC -= nextevent; + while (PSG->CountC <= 0) + { + PSG->CountC += PSG->PeriodC; + if (PSG->CountC > 0) + { + PSG->OutputC ^= 1; + if (PSG->OutputC) volc += PSG->PeriodC; + break; + } + PSG->CountC += PSG->PeriodC; + volc += PSG->PeriodC; + } + if (PSG->OutputC) volc -= PSG->CountC; + } + else + { + PSG->CountC -= nextevent; + while (PSG->CountC <= 0) + { + PSG->CountC += PSG->PeriodC; + if (PSG->CountC > 0) + { + PSG->OutputC ^= 1; + break; + } + PSG->CountC += PSG->PeriodC; + } + } + + PSG->CountN -= nextevent; + if (PSG->CountN <= 0) + { + /* Is noise output going to change? */ + if ((PSG->RNG + 1) & 2) /* (bit0^bit1)? */ + { + PSG->OutputN = ~PSG->OutputN; + outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]); + } + + /* The Random Number Generator of the 8910 is a 17-bit shift */ + /* register. The input to the shift register is bit0 XOR bit2 */ + /* (bit0 is the output). */ + + /* The following is a fast way to compute bit17 = bit0^bit2. */ + /* Instead of doing all the logic operations, we only check */ + /* bit0, relying on the fact that after two shifts of the */ + /* register, what now is bit2 will become bit0, and will */ + /* invert, if necessary, bit15, which previously was bit17. */ + if (PSG->RNG & 1) PSG->RNG ^= 0x24000; + PSG->RNG >>= 1; + PSG->CountN += PSG->PeriodN; + } + + left -= nextevent; + } while (left > 0); + + /* update envelope */ + if (PSG->Holding == 0) + { + PSG->CountE -= STEP; + if (PSG->CountE <= 0) + { + do + { + PSG->CountEnv--; + PSG->CountE += PSG->PeriodE; + } while (PSG->CountE <= 0); + + /* check envelope current position */ + if (PSG->CountEnv < 0) + { + if (PSG->Hold) + { + if (PSG->Alternate) + PSG->Attack ^= 0x1f; + PSG->Holding = 1; + PSG->CountEnv = 0; + } + else + { + /* if CountEnv has looped an odd number of times (usually 1), */ + /* invert the output. */ + if (PSG->Alternate && (PSG->CountEnv & 0x20)) + PSG->Attack ^= 0x1f; + + PSG->CountEnv &= 0x1f; + } + } + + PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack]; + /* reload volume */ + if (PSG->EnvelopeA) PSG->VolA = PSG->VolE; + if (PSG->EnvelopeB) PSG->VolB = PSG->VolE; + if (PSG->EnvelopeC) PSG->VolC = PSG->VolE; + } + } + + *(buf1++) = (vola * PSG->VolA) / STEP; + *(buf2++) = (volb * PSG->VolB) / STEP; + *(buf3++) = (volc * PSG->VolC) / STEP; + + length--; + } +} + + +void AY8910_set_clock(INT32 chip, INT32 clock) +{ + struct AY8910 *PSG = &AYPSG[chip]; + + /* the step clock for the tone and noise generators is the chip clock */ + /* divided by 8; for the envelope generator of the AY-3-8910, it is half */ + /* that much (clock/16), but the envelope of the YM2149 goes twice as */ + /* fast, therefore again clock/8. */ + /* Here we calculate the number of steps which happen during one sample */ + /* at the given sample rate. No. of events = sample rate / (clock/8). */ + /* STEP is a multiplier used to turn the fraction into a fixed point */ + /* number. */ + PSG->UpdateStep = ((double)STEP * PSG->SampleRate * 8 + clock/2) / clock; +} + + +static void build_mixer_table(INT32 chip) +{ + struct AY8910 *PSG = &AYPSG[chip]; + INT32 i; + double out; + + + /* calculate the volume->voltage conversion table */ + /* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */ + /* The YM2149 still has 16 levels for the tone generators, but 32 for */ + /* the envelope generator (1.5dB per step). */ + out = MAX_OUTPUT; + for (i = 31;i > 0;i--) + { + PSG->VolTable[i] = out + 0.5; /* round to nearest */ + + out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */ + } + PSG->VolTable[0] = 0; +} + + + +void AY8910Reset(INT32 chip) +{ + INT32 i; + struct AY8910 *PSG = &AYPSG[chip]; + + PSG->register_latch = 0; + PSG->RNG = 1; + PSG->OutputA = 0; + PSG->OutputB = 0; + PSG->OutputC = 0; + PSG->OutputN = 0xff; + PSG->lastEnable = -1; /* force a write */ + for (i = 0;i < AY_PORTA;i++) + _AYWriteReg(chip,i,0); /* AYWriteReg() uses the timer system; we cannot */ + /* call it at this time because the timer system */ + /* has not been initialized. */ +} + +void AY8910Exit(INT32 chip) +{ + (void)chip; + + num = 0; + ym_num = 0; + + ay8910_index_ym = 0; +} + +static void dummy_callback(void) +{ + return; +} + +INT32 AY8910Init(INT32 chip, INT32 clock, INT32 sample_rate, + read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite) +{ + struct AY8910 *PSG = &AYPSG[chip]; + + AYStreamUpdate = dummy_callback; + + if (chip != num) { + return 1; + } + + memset(PSG, 0, sizeof(struct AY8910)); + PSG->SampleRate = sample_rate; + PSG->PortAread = portAread; + PSG->PortBread = portBread; + PSG->PortAwrite = portAwrite; + PSG->PortBwrite = portBwrite; + + AY8910_set_clock(chip, clock); + + build_mixer_table(chip); + + AY8910Reset(chip); + + num++; + + return 0; +} + +INT32 AY8910InitYM(INT32 chip, INT32 clock, INT32 sample_rate, + read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite, + void (*update_callback)(void)) +{ + INT32 val = AY8910Init(ay8910_index_ym + chip, clock, sample_rate, portAread, portBread, portAwrite, portBwrite); + + AYStreamUpdate = update_callback; + + if (val == 0) { + ym_num++; + } + + ay8910_index_ym = num - ym_num; + + return val; +} + +// Useful for YM2203, etc games needing read/write ports +INT32 AY8910SetPorts(INT32 chip, read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite) +{ + struct AY8910 *PSG = &AYPSG[chip]; + + PSG->PortAread = portAread; + PSG->PortBread = portBread; + PSG->PortAwrite = portAwrite; + PSG->PortBwrite = portBwrite; + + return 0; +} + +INT32 AY8910Scan(INT32 nAction, INT32* pnMin) +{ + struct BurnArea ba; + INT32 i; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin && *pnMin < 0x029496) { // Return minimum compatible version + *pnMin = 0x029496; + } + + for (i = 0; i < num; i++) { + char szName[16]; + + sprintf(szName, "AY8910 #%d", i); + + ba.Data = &AYPSG[i]; + ba.nLen = sizeof(struct AY8910); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + return 0; +} + diff --git a/src/burn/sound/ay8910.h b/src/burn/sound/ay8910.h new file mode 100644 index 00000000..41de410b --- /dev/null +++ b/src/burn/sound/ay8910.h @@ -0,0 +1,45 @@ +#ifndef AY8910_H +#define AY8910_H + +#define MAX_8910 5 +#define ALL_8910_CHANNELS -1 + +struct AY8910interface +{ + INT32 num; /* total number of 8910 in the machine */ + INT32 baseclock; + INT32 mixing_level[MAX_8910]; + read8_handler portAread[MAX_8910]; + read8_handler portBread[MAX_8910]; + write8_handler portAwrite[MAX_8910]; + write8_handler portBwrite[MAX_8910]; + void (*handler[MAX_8910])(INT32 irq); /* IRQ handler for the YM2203 */ +}; + +extern INT32 ay8910_index_ym; + +void AY8910_set_clock(INT32 chip, INT32 clock); +void AY8910Reset(INT32 chip); + +void AY8910Update(INT32 chip, INT16** buffer, INT32 length); + +void AY8910Write(INT32 chip, INT32 a, INT32 data); +INT32 AY8910Read(INT32 chip); + +void AY8910Reset(INT32 chip); +void AY8910Exit(INT32 chip); +INT32 AY8910Init(INT32 chip, INT32 clock, INT32 sample_rate, + read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite); + +INT32 AY8910InitYM(INT32 chip, INT32 clock, INT32 sample_rate, + read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite, + void (*update_callback)(void)); + +INT32 AY8910Scan(INT32 nAction, INT32* pnMin); + +INT32 AY8910SetPorts(INT32 chip, read8_handler portAread, read8_handler portBread, + write8_handler portAwrite, write8_handler portBwrite); + +#endif diff --git a/src/burn/sound/burn_y8950.cpp b/src/burn/sound/burn_y8950.cpp new file mode 100644 index 00000000..fbbd79c7 --- /dev/null +++ b/src/burn/sound/burn_y8950.cpp @@ -0,0 +1,543 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_y8950.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "m6502_intf.h" + +// Timer Related + +#define MAX_TIMER_VALUE ((1 << 30) - 65536) + +static double dTimeY8950; // Time elapsed since the emulated machine was started + +static INT32 nTimerCount[2], nTimerStart[2]; + +// Callbacks +static INT32 (*pTimerOverCallback)(INT32, INT32); +static double (*pTimerTimeCallback)(); + +static INT32 nCPUClockspeed = 0; +static INT32 (*pCPUTotalCycles)() = NULL; +static INT32 (*pCPURun)(INT32) = NULL; +static void (*pCPURunEnd)() = NULL; + +// --------------------------------------------------------------------------- +// Running time + +static double BurnTimerTimeCallbackDummy() +{ + return 0.0; +} + +extern "C" double BurnTimerGetTimeY8950() +{ + return dTimeY8950 + pTimerTimeCallback(); +} + +// --------------------------------------------------------------------------- +// Update timers + +static INT32 nTicksTotal, nTicksDone, nTicksExtra; + +INT32 BurnTimerUpdateY8950(INT32 nCycles) +{ + INT32 nIRQStatus = 0; + + nTicksTotal = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" -- Ticks: %08X, cycles %i\n"), nTicksTotal, nCycles); + + while (nTicksDone < nTicksTotal) { + INT32 nTimer, nCyclesSegment, nTicksSegment; + + // Determine which timer fires first + if (nTimerCount[0] <= nTimerCount[1]) { + nTicksSegment = nTimerCount[0]; + } else { + nTicksSegment = nTimerCount[1]; + } + if (nTicksSegment > nTicksTotal) { + nTicksSegment = nTicksTotal; + } + + nCyclesSegment = MAKE_CPU_CYLES(nTicksSegment + nTicksExtra, nCPUClockspeed); +// bprintf(PRINT_NORMAL, _T(" - Timer: %08X, %08X, %08X, cycles %i, %i\n"), nTicksDone, nTicksSegment, nTicksTotal, nCyclesSegment, pCPUTotalCycles()); + + pCPURun(nCyclesSegment - pCPUTotalCycles()); + + nTicksDone = MAKE_TIMER_TICKS(pCPUTotalCycles() + 1, nCPUClockspeed) - 1; +// bprintf(PRINT_NORMAL, _T(" - ticks done -> %08X cycles -> %i\n"), nTicksDone, pCPUTotalCycles()); + + nTimer = 0; + if (nTicksDone >= nTimerCount[0]) { + if (nTimerStart[0] == MAX_TIMER_VALUE) { + nTimerCount[0] = MAX_TIMER_VALUE; + } else { + nTimerCount[0] += nTimerStart[0]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 0 fired\n")); + nTimer |= 1; + } + if (nTicksDone >= nTimerCount[1]) { + if (nTimerStart[1] == MAX_TIMER_VALUE) { + nTimerCount[1] = MAX_TIMER_VALUE; + } else { + nTimerCount[1] += nTimerStart[1]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 1 fired\n")); + nTimer |= 2; + } + if (nTimer & 1) { + nIRQStatus |= pTimerOverCallback(0, 0); + } + if (nTimer & 2) { + nIRQStatus |= pTimerOverCallback(0, 1); + } + } + + return nIRQStatus; +} + +void BurnTimerEndFrameY8950(INT32 nCycles) +{ + INT32 nTicks = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + + BurnTimerUpdateY8950(nCycles); + + if (nTimerCount[0] < MAX_TIMER_VALUE) { + nTimerCount[0] -= nTicks; + } + if (nTimerCount[1] < MAX_TIMER_VALUE) { + nTimerCount[1] -= nTicks; + } + + nTicksDone -= nTicks; + if (nTicksDone < 0) { +// bprintf(PRINT_ERROR, _T(" -- ticks done -> %08X\n"), nTicksDone); + nTicksDone = 0; + } +} + +void BurnTimerUpdateEndY8950() +{ +// bprintf(PRINT_NORMAL, _T(" - end %i\n"), pCPUTotalCycles()); + + pCPURunEnd(); + + nTicksTotal = 0; +} + +void BurnOPLTimerCallbackY8950(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerCount[c] = MAX_TIMER_VALUE; +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + return; + } + + nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnTimerScanY8950(INT32 nAction, INT32* pnMin) +{ + if (pnMin && *pnMin < 0x029521) { + *pnMin = 0x029521; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nTimerCount); + SCAN_VAR(nTimerStart); + SCAN_VAR(dTimeY8950); + + SCAN_VAR(nTicksDone); + } +} + +void BurnTimerExitY8950() +{ + nCPUClockspeed = 0; + pCPUTotalCycles = NULL; + pCPURun = NULL; + pCPURunEnd = NULL; + + return; +} + +void BurnTimerResetY8950() +{ + nTimerCount[0] = nTimerCount[1] = MAX_TIMER_VALUE; + nTimerStart[0] = nTimerStart[1] = MAX_TIMER_VALUE; + + dTimeY8950 = 0.0; + + nTicksDone = 0; +} + +INT32 BurnTimerInitY8950(INT32 (*pOverCallback)(INT32, INT32), double (*pTimeCallback)()) +{ + BurnTimerExitY8950(); + + pTimerOverCallback = pOverCallback; + pTimerTimeCallback = pTimeCallback ? pTimeCallback : BurnTimerTimeCallbackDummy; + + BurnTimerResetY8950(); + + return 0; +} + +INT32 BurnTimerAttachSekY8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = SekTotalCycles; + pCPURun = SekRun; + pCPURunEnd = SekRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachZetY8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = ZetTotalCycles; + pCPURun = ZetRun; + pCPURunEnd = ZetRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6809Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6809TotalCycles; + pCPURun = M6809Run; + pCPURunEnd = M6809RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD6309Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = HD6309TotalCycles; + pCPURun = HD6309Run; + pCPURunEnd = HD6309RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6800Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6800Run; + pCPURunEnd = M6800RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD63701Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = HD63701Run; + pCPURunEnd = HD63701RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6803Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6803Run; + pCPURunEnd = M6803RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6502Y8950(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6502TotalCycles; + pCPURun = M6502Run; + pCPURunEnd = M6502RunEnd; // doesn't do anything... + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +// Sound Related + +void (*BurnY8950Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnY8950StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnY8950SoundRate; + +static INT16* pBuffer; +static INT16* pY8950Buffer; + +static INT32 nY8950Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 bY8950AddSignal; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void Y8950UpdateDummy(INT16* , INT32 /* nSegmentEnd */) +{ + return; +} + +static int Y8950StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute Y8950 for part of a frame + +static void Y8950Render(INT32 nSegmentLength) +{ + if (nY8950Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" Y8950 render %6i -> %6i\n", nY8950Position, nSegmentLength)); + + nSegmentLength -= nY8950Position; + + Y8950UpdateOne(0, pBuffer + 0 * 4096 + 4 + nY8950Position, nSegmentLength); + + nY8950Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void Y8950UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnY8950SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" Y8950 update -> %6i\n", nSegmentLength)); + + if (nSamplesNeeded < nY8950Position) { + nSamplesNeeded = nY8950Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + Y8950Render(nSamplesNeeded); + + pY8950Buffer = pBuffer + 0 * 4096 + 4; + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT16 nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pY8950Buffer[(nFractionalPosition >> 16) - 3], + pY8950Buffer[(nFractionalPosition >> 16) - 2], + pY8950Buffer[(nFractionalPosition >> 16) - 1], + pY8950Buffer[(nFractionalPosition >> 16) - 0]); + if (bY8950AddSignal) { + pSoundBuf[i + 0] += nSample; + pSoundBuf[i + 1] += nSample; + } else { + pSoundBuf[i + 0] = nSample; + pSoundBuf[i + 1] = nSample; + } + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pY8950Buffer[i] = pY8950Buffer[(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0xFFFF; + + nY8950Position = nExtraSamples; + } +} + +static void Y8950UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" Y8950 render %6i -> %6i\n"), nY8950Position, nSegmentEnd); + + if (nSegmentEnd < nY8950Position) { + nSegmentEnd = nY8950Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + Y8950Render(nSegmentEnd); + + pY8950Buffer = pBuffer + 4 + 0 * 4096; + + for (INT32 i = nFractionalPosition; i < nSegmentLength; i++) { + if (bY8950AddSignal) { + pSoundBuf[(i << 1) + 0] += pY8950Buffer[i]; + pSoundBuf[(i << 1) + 1] += pY8950Buffer[i]; + } else { + pSoundBuf[(i << 1) + 0] = pY8950Buffer[i]; + pSoundBuf[(i << 1) + 1] = pY8950Buffer[i]; + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pY8950Buffer[i] = pY8950Buffer[nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nY8950Position = nExtraSamples; + + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for Y8950 core + +void BurnY8950UpdateRequest(INT32, INT32) +{ + Y8950Render(BurnY8950StreamCallback(nBurnY8950SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnY8950Reset() +{ + BurnTimerResetY8950(); + + Y8950ResetChip(0); +} + +void BurnY8950Exit() +{ + Y8950Shutdown(); + + BurnTimerExitY8950(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + bY8950AddSignal = 0; +} + +INT32 BurnY8950Init(INT32 nClockFrequency, UINT8* Y8950ADPCMROM, INT32 nY8950ADPCMSize, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal) +{ + BurnTimerInitY8950(&Y8950TimerOver, NULL); + + if (nBurnSoundRate <= 0) { + BurnY8950StreamCallback = Y8950StreamCallbackDummy; + + BurnY8950Update = Y8950UpdateDummy; + + Y8950Init(1, nClockFrequency, 11025); + return 0; + } + + BurnY8950StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set Y8950 core samplerate to match the hardware + nBurnY8950SoundRate = nClockFrequency / 72; + // Bring Y8950 core samplerate within usable range + while (nBurnY8950SoundRate > nBurnSoundRate * 3) { + nBurnY8950SoundRate >>= 1; + } + + BurnY8950Update = Y8950UpdateResample; + + nSampleSize = (UINT32)nBurnY8950SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 0; + } else { + nBurnY8950SoundRate = nBurnSoundRate; + + BurnY8950Update = Y8950UpdateNormal; + } + + Y8950Init(1, nClockFrequency, nBurnY8950SoundRate); + Y8950SetIRQHandler(0, IRQCallback, 0); + Y8950SetTimerHandler(0, &BurnOPLTimerCallbackY8950, 0); + Y8950SetUpdateHandler(0, &BurnY8950UpdateRequest, 0); + Y8950SetDeltaTMemory(0, Y8950ADPCMROM, nY8950ADPCMSize); + + pBuffer = (INT16*)malloc(4096 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * sizeof(INT16)); + + nY8950Position = 0; + + nFractionalPosition = 0; + + bY8950AddSignal = bAddSignal; + + return 0; +} + +void BurnY8950Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScanY8950(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nY8950Position); + } +} diff --git a/src/burn/sound/burn_y8950.h b/src/burn/sound/burn_y8950.h new file mode 100644 index 00000000..e1388904 --- /dev/null +++ b/src/burn/sound/burn_y8950.h @@ -0,0 +1,28 @@ +#include "driver.h" +extern "C" { + #include "fmopl.h" +} +#include "timer.h" + +INT32 BurnTimerUpdateY8950(INT32 nCycles); +void BurnTimerEndFrameY8950(INT32 nCycles); +void BurnTimerUpdateEndY8950(); +INT32 BurnTimerAttachSekY8950(INT32 nClockspeed); +INT32 BurnTimerAttachZetY8950(INT32 nClockspeed); +INT32 BurnTimerAttachM6809Y8950(INT32 nClockspeed); +INT32 BurnTimerAttachHD6309Y8950(INT32 nClockspeed); +INT32 BurnTimerAttachM6800Y8950(INT32 nClockspeed); +INT32 BurnTimerAttachHD63701Y8950(INT32 nClockspeed); +INT32 BurnTimerAttachM6803Y8950(INT32 nClockspeed); +INT32 BurnTimerAttachM6502Y8950(INT32 nClockspeed); + +extern "C" void BurnY8950UpdateRequest(); + +INT32 BurnY8950Init(INT32 nClockFrequency, UINT8* Y8950ADPCMROM, INT32 nY8950ADPCMSize, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal); +void BurnY8950Reset(); +void BurnY8950Exit(); +extern void (*BurnY8950Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnY8950Scan(INT32 nAction, INT32* pnMin); + +#define BurnY8950Write(a, n) Y8950Write(0, a, n) +#define BurnY8950Read(a) Y8950Read(0, a) diff --git a/src/burn/sound/burn_ym2151.cpp b/src/burn/sound/burn_ym2151.cpp new file mode 100644 index 00000000..330f82e1 --- /dev/null +++ b/src/burn/sound/burn_ym2151.cpp @@ -0,0 +1,173 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2151.h" + +void (*BurnYM2151Render)(INT16* pSoundBuf, INT32 nSegmentLength); + +UINT8 BurnYM2151Registers[0x0100]; +UINT32 nBurnCurrentYM2151Register; + +static INT32 nBurnYM2151SoundRate; + +static INT16* pBuffer; +static INT16* pYM2151Buffer[2]; + +static INT32 nBurnPosition; +static UINT32 nSampleSize; +static INT32 nFractionalPosition; +static UINT32 nSamplesRendered; + +static INT32 nYM2151Volume; + +static void YM2151RenderResample(INT16* pSoundBuf, INT32 nSegmentLength) +{ + nBurnPosition += nSegmentLength; + + if (nBurnPosition >= nBurnSoundRate) { + nBurnPosition = nSegmentLength; + + pYM2151Buffer[0][1] = pYM2151Buffer[0][(nFractionalPosition >> 16) - 3]; + pYM2151Buffer[0][2] = pYM2151Buffer[0][(nFractionalPosition >> 16) - 2]; + pYM2151Buffer[0][3] = pYM2151Buffer[0][(nFractionalPosition >> 16) - 1]; + + pYM2151Buffer[1][1] = pYM2151Buffer[1][(nFractionalPosition >> 16) - 3]; + pYM2151Buffer[1][2] = pYM2151Buffer[1][(nFractionalPosition >> 16) - 2]; + pYM2151Buffer[1][3] = pYM2151Buffer[1][(nFractionalPosition >> 16) - 1]; + + nSamplesRendered -= (nFractionalPosition >> 16) - 4; + + for (UINT32 i = 0; i <= nSamplesRendered; i++) { + pYM2151Buffer[0][4 + i] = pYM2151Buffer[0][(nFractionalPosition >> 16) + i]; + pYM2151Buffer[1][4 + i] = pYM2151Buffer[1][(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0x0000FFFF; + nFractionalPosition |= 4 << 16; + } + + pYM2151Buffer[0] = pBuffer + 4 + nSamplesRendered; + pYM2151Buffer[1] = pBuffer + 4 + nSamplesRendered + 65536; + + YM2151UpdateOne(0, pYM2151Buffer, (UINT32)(nBurnPosition + 1) * nBurnYM2151SoundRate / nBurnSoundRate - nSamplesRendered); + nSamplesRendered += (UINT32)(nBurnPosition + 1) * nBurnYM2151SoundRate / nBurnSoundRate - nSamplesRendered; + + pYM2151Buffer[0] = pBuffer; + pYM2151Buffer[1] = pBuffer + 65536; + + nSegmentLength <<= 1; + + for (INT32 i = 0; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + + // Left channel + pSoundBuf[i + 0] = INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0FFF, + pYM2151Buffer[0][(nFractionalPosition >> 16) - 3], + pYM2151Buffer[0][(nFractionalPosition >> 16) - 2], + pYM2151Buffer[0][(nFractionalPosition >> 16) - 1], + pYM2151Buffer[0][(nFractionalPosition >> 16) - 0], + nYM2151Volume); + + // Right channel + pSoundBuf[i + 1] = INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0FFF, + pYM2151Buffer[1][(nFractionalPosition >> 16) - 3], + pYM2151Buffer[1][(nFractionalPosition >> 16) - 2], + pYM2151Buffer[1][(nFractionalPosition >> 16) - 1], + pYM2151Buffer[1][(nFractionalPosition >> 16) - 0], + nYM2151Volume); + } +} + +static void YM2151RenderNormal(INT16* pSoundBuf, INT32 nSegmentLength) +{ + nBurnPosition += nSegmentLength; + + pYM2151Buffer[0] = pBuffer; + pYM2151Buffer[1] = pBuffer + nSegmentLength; + + YM2151UpdateOne(0, pYM2151Buffer, nSegmentLength); + + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + BurnSoundCopy_FM_A(pYM2151Buffer[0], pYM2151Buffer[1], pSoundBuf, nSegmentLength, nYM2151Volume, nYM2151Volume); +#endif + } else { + for (INT32 n = 0; n < nSegmentLength; n++) { + for (INT32 i = 0; i < 2; i++) { + INT32 nSample = pYM2151Buffer[i][n] * (nYM2151Volume >> 10); + nSample >>= 8; + + if (nSample < -32768) nSample = -32768; + if (nSample > 32767) nSample = 32767; + + pSoundBuf[(n << 1) + i] = nSample; + } + } + } +} + +void BurnYM2151Reset() +{ + YM2151ResetChip(0); +} + +void BurnYM2151Exit() +{ + YM2151Shutdown(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } +} + +INT32 BurnYM2151Init(INT32 nClockFrequency, float nVolume) +{ + if (nBurnSoundRate <= 0) { + YM2151Init(1, nClockFrequency, 11025); + return 0; + } + + if (nFMInterpolation == 3) { + // Set YM2151 core samplerate to match the hardware + nBurnYM2151SoundRate = nClockFrequency >> 6; + // Bring YM2151 core samplerate within usable range + while (nBurnYM2151SoundRate > nBurnSoundRate * 3) { + nBurnYM2151SoundRate >>= 1; + } + + BurnYM2151Render = YM2151RenderResample; + + nYM2151Volume = (INT32)((double)16384.0 * 100.0 / nVolume); + } else { + nBurnYM2151SoundRate = nBurnSoundRate; + BurnYM2151Render = YM2151RenderNormal; + + nYM2151Volume = (INT32)((double)65536.0 * 100.0 / nVolume); + } + + YM2151Init(1, nClockFrequency, nBurnYM2151SoundRate); + + pBuffer = (INT16*)malloc(65536 * 2 * sizeof(INT16)); + memset(pBuffer, 0, 65536 * 2 * sizeof(INT16)); + + nSampleSize = (UINT32)nBurnYM2151SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 4 << 16; + nSamplesRendered = 0; + nBurnPosition = 0; + + return 0; +} + +void BurnYM2151Scan(INT32 nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) { + return; + } + SCAN_VAR(nBurnCurrentYM2151Register); + SCAN_VAR(BurnYM2151Registers); + + if (nAction & ACB_WRITE) { + for (INT32 i = 0; i < 0x0100; i++) { + YM2151WriteReg(0, i, BurnYM2151Registers[i]); + } + } +} diff --git a/src/burn/sound/burn_ym2151.h b/src/burn/sound/burn_ym2151.h new file mode 100644 index 00000000..b90a5c90 --- /dev/null +++ b/src/burn/sound/burn_ym2151.h @@ -0,0 +1,31 @@ +// burn_ym2151.h +#include "driver.h" +extern "C" { + #include "ym2151.h" +} + +INT32 BurnYM2151Init(INT32 nClockFrequency, float nVolume); +void BurnYM2151Reset(); +void BurnYM2151Exit(); +extern void (*BurnYM2151Render)(INT16* pSoundBuf, INT32 nSegmentLength); +void BurnYM2151Scan(INT32 nAction); + +static inline void BurnYM2151SelectRegister(const UINT8 nRegister) +{ + extern UINT32 nBurnCurrentYM2151Register; + + nBurnCurrentYM2151Register = nRegister; +} + +static inline void BurnYM2151WriteRegister(const UINT8 nValue) +{ + extern UINT32 nBurnCurrentYM2151Register; + extern UINT8 BurnYM2151Registers[0x0100]; + + BurnYM2151Registers[nBurnCurrentYM2151Register] = nValue; + YM2151WriteReg(0, nBurnCurrentYM2151Register, nValue); +} + +#define BurnYM2151ReadStatus() YM2151ReadStatus(0) +#define BurnYM2151SetIrqHandler(h) YM2151SetIrqHandler(0, h) +#define BurnYM2151SetPortHandler(h) YM2151SetPortWriteHandler(0, h) diff --git a/src/burn/sound/burn_ym2203.cpp b/src/burn/sound/burn_ym2203.cpp new file mode 100644 index 00000000..b6d0b747 --- /dev/null +++ b/src/burn/sound/burn_ym2203.cpp @@ -0,0 +1,411 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2203.h" + +#define MAX_YM2203 2 + +void (*BurnYM2203Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM2203StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM2203SoundRate; + +static INT16* pBuffer; +static INT16* pYM2203Buffer[5 * MAX_YM2203]; + +static INT32 nYM2203Position; +static INT32 nAY8910Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 nNumChips = 0; + +static INT32 bYM2203AddSignal; +static INT32 nYM2203VolumeShift; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM2203UpdateDummy(INT16*, INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM2203StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM2203 for part of a frame + +static void AY8910Render(INT32 nSegmentLength) +{ + if (nAY8910Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" AY8910 render %6i -> %6i\n"), nAY8910Position, nSegmentLength); + + nSegmentLength -= nAY8910Position; + + pYM2203Buffer[1] = pBuffer + 1 * 4096 + 4 + nAY8910Position; + pYM2203Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position; + pYM2203Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position; + + AY8910Update(0, &pYM2203Buffer[1], nSegmentLength); + + if (nNumChips > 1) { + pYM2203Buffer[6] = pBuffer + 6 * 4096 + 4 + nAY8910Position; + pYM2203Buffer[7] = pBuffer + 7 * 4096 + 4 + nAY8910Position; + pYM2203Buffer[8] = pBuffer + 8 * 4096 + 4 + nAY8910Position; + + AY8910Update(1, &pYM2203Buffer[6], nSegmentLength); + } + + nAY8910Position += nSegmentLength; +} + +static void YM2203Render(INT32 nSegmentLength) +{ + if (nYM2203Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM2203 render %6i -> %6i\n", nYM2203Position, nSegmentLength)); + + nSegmentLength -= nYM2203Position; + + pYM2203Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2203Position; + + YM2203UpdateOne(0, pYM2203Buffer[0], nSegmentLength); + + if (nNumChips > 1) { + pYM2203Buffer[5] = pBuffer + 5 * 4096 + 4 + nYM2203Position; + + YM2203UpdateOne(1, pYM2203Buffer[5], nSegmentLength); + } + + nYM2203Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void YM2203UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2203SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" YM2203 update -> %6i\n", nSegmentLength)); + + if (nSamplesNeeded < nAY8910Position) { + nSamplesNeeded = nAY8910Position; + } + if (nSamplesNeeded < nYM2203Position) { + nSamplesNeeded = nYM2203Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + YM2203Render(nSamplesNeeded); + AY8910Render(nSamplesNeeded); + + pYM2203Buffer[0] = pBuffer + 0 * 4096 + 4; + pYM2203Buffer[1] = pBuffer + 1 * 4096 + 4; + pYM2203Buffer[2] = pBuffer + 2 * 4096 + 4; + pYM2203Buffer[3] = pBuffer + 3 * 4096 + 4; + pYM2203Buffer[4] = pBuffer + 4 * 4096 + 4; + + if (nNumChips > 1) { + pYM2203Buffer[5] = pBuffer + 5 * 4096 + 4; + pYM2203Buffer[6] = pBuffer + 6 * 4096 + 4; + pYM2203Buffer[7] = pBuffer + 7 * 4096 + 4; + pYM2203Buffer[8] = pBuffer + 8 * 4096 + 4; + pYM2203Buffer[9] = pBuffer + 9 * 4096 + 4; + } + + for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) { + pYM2203Buffer[4][i] = (((INT32)pYM2203Buffer[1][i] + pYM2203Buffer[2][i] + pYM2203Buffer[3][i]) * (4096 * 60 / 100)) >> 12; + if (nNumChips > 1) pYM2203Buffer[9][i] = (((INT32)pYM2203Buffer[6][i] + pYM2203Buffer[7][i] + pYM2203Buffer[8][i]) * (4096 * 60 / 100)) >> 12; + } + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT32 nSample, nSample2 = 0; + +#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) + + + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + (pYM2203Buffer[0][(nFractionalPosition >> 16) - 3] + pYM2203Buffer[4][(nFractionalPosition >> 16) - 3]) >> nYM2203VolumeShift, + (pYM2203Buffer[0][(nFractionalPosition >> 16) - 2] + pYM2203Buffer[4][(nFractionalPosition >> 16) - 2]) >> nYM2203VolumeShift, + (pYM2203Buffer[0][(nFractionalPosition >> 16) - 1] + pYM2203Buffer[4][(nFractionalPosition >> 16) - 1]) >> nYM2203VolumeShift, + (pYM2203Buffer[0][(nFractionalPosition >> 16) - 0] + pYM2203Buffer[4][(nFractionalPosition >> 16) - 0]) >> nYM2203VolumeShift); + if (nNumChips > 1) nSample2 = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + (pYM2203Buffer[5][(nFractionalPosition >> 16) - 3] + pYM2203Buffer[9][(nFractionalPosition >> 16) - 3]) >> nYM2203VolumeShift, + (pYM2203Buffer[5][(nFractionalPosition >> 16) - 2] + pYM2203Buffer[9][(nFractionalPosition >> 16) - 2]) >> nYM2203VolumeShift, + (pYM2203Buffer[5][(nFractionalPosition >> 16) - 1] + pYM2203Buffer[9][(nFractionalPosition >> 16) - 1]) >> nYM2203VolumeShift, + (pYM2203Buffer[5][(nFractionalPosition >> 16) - 0] + pYM2203Buffer[9][(nFractionalPosition >> 16) - 0]) >> nYM2203VolumeShift); + + nSample = CLIP(nSample); + nSample2 = CLIP(nSample2); + + if (bYM2203AddSignal) { + pSoundBuf[i + 0] += CLIP(nSample + nSample2); + pSoundBuf[i + 1] += CLIP(nSample + nSample2); + } else { + pSoundBuf[i + 0] = CLIP(nSample + nSample2); + pSoundBuf[i + 1] = CLIP(nSample + nSample2); + } + +#undef CLIP + + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pYM2203Buffer[0][i] = pYM2203Buffer[0][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[1][i] = pYM2203Buffer[1][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[2][i] = pYM2203Buffer[2][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[3][i] = pYM2203Buffer[3][(nFractionalPosition >> 16) + i]; + + if (nNumChips > 1) { + pYM2203Buffer[5][i] = pYM2203Buffer[5][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[6][i] = pYM2203Buffer[6][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[7][i] = pYM2203Buffer[7][(nFractionalPosition >> 16) + i]; + pYM2203Buffer[8][i] = pYM2203Buffer[8][(nFractionalPosition >> 16) + i]; + } + } + + nFractionalPosition &= 0xFFFF; + + nYM2203Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +static void YM2203UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 i; + +// bprintf(PRINT_NORMAL, _T(" YM2203 update -> %6i\n", nSegmentLength)); + + if (nSegmentEnd < nAY8910Position) { + nSegmentEnd = nAY8910Position; + } + if (nSegmentEnd < nYM2203Position) { + nSegmentEnd = nYM2203Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM2203Render(nSegmentEnd); + AY8910Render(nSegmentEnd); + + pYM2203Buffer[0] = pBuffer + 4 + 0 * 4096; + pYM2203Buffer[1] = pBuffer + 4 + 1 * 4096; + pYM2203Buffer[2] = pBuffer + 4 + 2 * 4096; + pYM2203Buffer[3] = pBuffer + 4 + 3 * 4096; + if (nNumChips > 1) { + pYM2203Buffer[5] = pBuffer + 5 + 4 * 4096; + pYM2203Buffer[6] = pBuffer + 6 + 5 * 4096; + pYM2203Buffer[7] = pBuffer + 7 + 6 * 4096; + pYM2203Buffer[8] = pBuffer + 8 + 7 * 4096; + } + + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + INT32 nAYSample; INT32 nTotalSample; + + nAYSample = pYM2203Buffer[1][n]; + nAYSample += pYM2203Buffer[2][n]; + nAYSample += pYM2203Buffer[3][n]; + if (nNumChips > 1) { + nAYSample += pYM2203Buffer[6][n]; + nAYSample += pYM2203Buffer[7][n]; + nAYSample += pYM2203Buffer[8][n]; + } + + nAYSample *= 4096 * 60 / 100; + nAYSample >>= 12; + + nTotalSample = nAYSample + pYM2203Buffer[0][n]; + if (nNumChips > 1) nTotalSample += pYM2203Buffer[5][n]; + + nTotalSample >>= nYM2203VolumeShift; + + if (nTotalSample < -32768) { + nTotalSample = -32768; + } else { + if (nTotalSample > 32767) { + nTotalSample = 32767; + } + } + + if (bYM2203AddSignal) { + pSoundBuf[(n << 1) + 0] += nTotalSample; + pSoundBuf[(n << 1) + 1] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 0] = nTotalSample; + pSoundBuf[(n << 1) + 1] = nTotalSample; + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (i = 0; i < nExtraSamples; i++) { + pYM2203Buffer[0][i] = pYM2203Buffer[0][nBurnSoundLen + i]; + pYM2203Buffer[1][i] = pYM2203Buffer[1][nBurnSoundLen + i]; + pYM2203Buffer[2][i] = pYM2203Buffer[2][nBurnSoundLen + i]; + pYM2203Buffer[3][i] = pYM2203Buffer[3][nBurnSoundLen + i]; + if (nNumChips > 1) { + pYM2203Buffer[5][i] = pYM2203Buffer[5][nBurnSoundLen + i]; + pYM2203Buffer[6][i] = pYM2203Buffer[6][nBurnSoundLen + i]; + pYM2203Buffer[7][i] = pYM2203Buffer[7][nBurnSoundLen + i]; + pYM2203Buffer[8][i] = pYM2203Buffer[8][nBurnSoundLen + i]; + } + } + + nFractionalPosition = 0; + + nYM2203Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM2203 core + +void BurnYM2203UpdateRequest() +{ + YM2203Render(BurnYM2203StreamCallback(nBurnYM2203SoundRate)); +} + +static void BurnAY8910UpdateRequest() +{ + AY8910Render(BurnYM2203StreamCallback(nBurnYM2203SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM2203Reset() +{ + BurnTimerReset(); + + for (INT32 i = 0; i < nNumChips; i++) { + YM2203ResetChip(i); + AY8910Reset(i); + } +} + +void BurnYM2203Exit() +{ + YM2203Shutdown(); + + for (INT32 i = 0; i < nNumChips; i++) { + AY8910Exit(i); + } + + BurnTimerExit(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + nNumChips = 0; + bYM2203AddSignal = 0; + nYM2203VolumeShift = 0; +} + +INT32 BurnYM2203Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal) +{ + if (num > MAX_YM2203) num = MAX_YM2203; + + BurnTimerInit(&YM2203TimerOver, GetTimeCallback); + + if (nBurnSoundRate <= 0) { + BurnYM2203StreamCallback = YM2203StreamCallbackDummy; + + BurnYM2203Update = YM2203UpdateDummy; + + for (INT32 i = 0; i < num; i++) { + AY8910InitYM(i, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + } + YM2203Init(num, nClockFrequency, 11025, &BurnOPNTimerCallback, IRQCallback); + return 0; + } + + BurnYM2203StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set YM2203 core samplerate to match the hardware + nBurnYM2203SoundRate = nClockFrequency / (144 * num); + // Bring YM2203 core samplerate within usable range + while (nBurnYM2203SoundRate > nBurnSoundRate * 3) { + nBurnYM2203SoundRate >>= 1; + } + + BurnYM2203Update = YM2203UpdateResample; + + nSampleSize = (UINT32)nBurnYM2203SoundRate * (1 << 16) / nBurnSoundRate; + } else { + nBurnYM2203SoundRate = nBurnSoundRate; + + BurnYM2203Update = YM2203UpdateNormal; + } + + for (INT32 i = 0; i < num; i++) { + AY8910InitYM(i, nClockFrequency, nBurnYM2203SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + } + + YM2203Init(num, nClockFrequency, nBurnYM2203SoundRate, &BurnOPNTimerCallback, IRQCallback); + + pBuffer = (INT16*)malloc(4096 * 5 * num * sizeof(INT16)); + memset(pBuffer, 0, 4096 * 5 * num * sizeof(INT16)); + + nYM2203Position = 0; + nAY8910Position = 0; + nFractionalPosition = 0; + + nNumChips = num; + bYM2203AddSignal = bAddSignal; + + return 0; +} + +void BurnYM2203SetVolumeShift(INT32 Shift) +{ + nYM2203VolumeShift = Shift; +} + +void BurnYM2203Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScan(nAction, pnMin); + AY8910Scan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM2203Position); + SCAN_VAR(nAY8910Position); + } +} + +#undef MAX_YM2203 diff --git a/src/burn/sound/burn_ym2203.h b/src/burn/sound/burn_ym2203.h new file mode 100644 index 00000000..72d18522 --- /dev/null +++ b/src/burn/sound/burn_ym2203.h @@ -0,0 +1,22 @@ +// burn_ym2203.h +#include "driver.h" +extern "C" { + #include "ay8910.h" + #include "fm.h" +} +#include "timer.h" + +extern "C" void BurnYM2203UpdateRequest(); + +INT32 BurnYM2203Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal); +void BurnYM2203SetVolumeShift(INT32 Shift); +void BurnYM2203Reset(); +void BurnYM2203Exit(); +extern void (*BurnYM2203Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM2203Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM2203Write(i, a, n) YM2203Write(i, a, n) +#define BurnYM2203Read(i, a) YM2203Read(i, a) + +#define BurnYM2203SetPorts(c, read0, read1, write0, write1) \ + AY8910SetPorts(c, read0, read1, write0, write1) diff --git a/src/burn/sound/burn_ym2413.cpp b/src/burn/sound/burn_ym2413.cpp new file mode 100644 index 00000000..4b8034aa --- /dev/null +++ b/src/burn/sound/burn_ym2413.cpp @@ -0,0 +1,179 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2413.h" + +void (*BurnYM2413Render)(INT16* pSoundBuf, INT32 nSegmentLength); + +//unsigned char BurnYM2151Registers[0x0100]; +//unsigned int nBurnCurrentYM2151Register; + +static INT32 nBurnYM2413SoundRate; + +static INT16* pBuffer; +static INT16* pYM2413Buffer[2]; + +static INT32 nBurnPosition; +static UINT32 nSampleSize; +static INT32 nFractionalPosition; +static UINT32 nSamplesRendered; + +static INT32 nYM2413Volume; + +static void YM2413RenderResample(INT16* pSoundBuf, INT32 nSegmentLength) +{ + nBurnPosition += nSegmentLength; + + if (nBurnPosition >= nBurnSoundRate) { + nBurnPosition = nSegmentLength; + + pYM2413Buffer[0][1] = pYM2413Buffer[0][(nFractionalPosition >> 16) - 3]; + pYM2413Buffer[0][2] = pYM2413Buffer[0][(nFractionalPosition >> 16) - 2]; + pYM2413Buffer[0][3] = pYM2413Buffer[0][(nFractionalPosition >> 16) - 1]; + + pYM2413Buffer[1][1] = pYM2413Buffer[1][(nFractionalPosition >> 16) - 3]; + pYM2413Buffer[1][2] = pYM2413Buffer[1][(nFractionalPosition >> 16) - 2]; + pYM2413Buffer[1][3] = pYM2413Buffer[1][(nFractionalPosition >> 16) - 1]; + + nSamplesRendered -= (nFractionalPosition >> 16) - 4; + + for (UINT32 i = 0; i <= nSamplesRendered; i++) { + pYM2413Buffer[0][4 + i] = pYM2413Buffer[0][(nFractionalPosition >> 16) + i]; + pYM2413Buffer[1][4 + i] = pYM2413Buffer[1][(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0x0000FFFF; + nFractionalPosition |= 4 << 16; + } + + pYM2413Buffer[0] = pBuffer + 4 + nSamplesRendered; + pYM2413Buffer[1] = pBuffer + 4 + nSamplesRendered + 65536; + + YM2413UpdateOne(0, pYM2413Buffer, (UINT32)(nBurnPosition + 1) * nBurnYM2413SoundRate / nBurnSoundRate - nSamplesRendered); + nSamplesRendered += (UINT32)(nBurnPosition + 1) * nBurnYM2413SoundRate / nBurnSoundRate - nSamplesRendered; + + pYM2413Buffer[0] = pBuffer; + pYM2413Buffer[1] = pBuffer + 65536; + + nSegmentLength <<= 1; + + for (INT32 i = 0; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + + INT32 nSample = INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0FFF, + pYM2413Buffer[0][(nFractionalPosition >> 16) - 3], + pYM2413Buffer[0][(nFractionalPosition >> 16) - 2], + pYM2413Buffer[0][(nFractionalPosition >> 16) - 1], + pYM2413Buffer[0][(nFractionalPosition >> 16) - 0], + nYM2413Volume / 100) + + INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0FFF, + pYM2413Buffer[1][(nFractionalPosition >> 16) - 3], + pYM2413Buffer[1][(nFractionalPosition >> 16) - 2], + pYM2413Buffer[1][(nFractionalPosition >> 16) - 1], + pYM2413Buffer[1][(nFractionalPosition >> 16) - 0], + nYM2413Volume / 100); + + pSoundBuf[i + 0] = nSample; + pSoundBuf[i + 1] = nSample; + } +} + +static void YM2413RenderNormal(INT16* pSoundBuf, INT32 nSegmentLength) +{ + nBurnPosition += nSegmentLength; + + pYM2413Buffer[0] = pBuffer; + pYM2413Buffer[1] = pBuffer + nSegmentLength; + + YM2413UpdateOne(0, pYM2413Buffer, nSegmentLength); + + for (INT32 n = 0; n < nSegmentLength; n++) { + INT32 nSample1 = pYM2413Buffer[0][n] * (nYM2413Volume >> 10); + nSample1 >>= 8; + INT32 nSample2 = pYM2413Buffer[1][n] * (nYM2413Volume >> 10); + nSample2 >>= 8; + + INT32 nSample = nSample1 + nSample2; + if (nSample < -32768) nSample = -32768; + if (nSample > 32767) nSample = 32767; + + pSoundBuf[(n << 1) + 0] = nSample; + pSoundBuf[(n << 1) + 1] = nSample; + } +} + +void BurnYM2413Reset() +{ + YM2413ResetChip(0); +} + +void BurnYM2413Exit() +{ + YM2413Shutdown(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } +} + +INT32 BurnYM2413Init(INT32 nClockFrequency, float nVolume) +{ + if (nBurnSoundRate <= 0) { + YM2413Init(1, nClockFrequency, 11025); + return 0; + } + + if (nFMInterpolation == 3) { + // Set YM2413 core samplerate to match the hardware + nBurnYM2413SoundRate = nClockFrequency >> 6; + // Bring YM2413 core samplerate within usable range + while (nBurnYM2413SoundRate > nBurnSoundRate * 3) { + nBurnYM2413SoundRate >>= 1; + } + + BurnYM2413Render = YM2413RenderResample; + + nYM2413Volume = (INT32)((double)16384.0 * 100.0 / nVolume); + } else { + nBurnYM2413SoundRate = nBurnSoundRate; + BurnYM2413Render = YM2413RenderNormal; + + nYM2413Volume = (INT32)((double)65536.0 * 100.0 / nVolume); + } + + YM2413Init(1, nClockFrequency, nBurnYM2413SoundRate); + + pBuffer = (INT16*)malloc(65536 * 2 * sizeof(INT16)); + memset(pBuffer, 0, 65536 * 2 * sizeof(INT16)); + + nSampleSize = (UINT32)nBurnYM2413SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 4 << 16; + nSamplesRendered = 0; + nBurnPosition = 0; + + return 0; +} + +void BurnYM2413IncreaseVolume(INT32 nFactor) +{ + nYM2413Volume *= nFactor; +} + +void BurnYM2413DecreaseVolume(INT32 nFactor) +{ + nYM2413Volume /= nFactor; +} + +void BurnYM2413Scan(INT32 nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) { + return; + } +// SCAN_VAR(nBurnCurrentYM2151Register); +// SCAN_VAR(BurnYM2151Registers); + + if (nAction & ACB_WRITE) { +// for (int i = 0; i < 0x0100; i++) { +// YM2151WriteReg(0, i, BurnYM2151Registers[i]); +// } + } +} diff --git a/src/burn/sound/burn_ym2413.h b/src/burn/sound/burn_ym2413.h new file mode 100644 index 00000000..f18da6c7 --- /dev/null +++ b/src/burn/sound/burn_ym2413.h @@ -0,0 +1,18 @@ +// burn_ym2413.h +#include "driver.h" +extern "C" { + #include "ym2413.h" +} + +INT32 BurnYM2413Init(INT32 nClockFrequency, float nVolume); +void BurnYM2413Reset(); +void BurnYM2413Exit(); +extern void (*BurnYM2413Render)(INT16* pSoundBuf, INT32 nSegmentLength); +void BurnYM2413Scan(INT32 nAction); +void BurnYM2413IncreaseVolume(INT32 nFactor); +void BurnYM2413DecreaseVolume(INT32 nFactor); + +#define BurnYM2413Read(a) YM2413Read(0, a) +#define BurnYM2413Write(a, d) YM2413Write(0, a, d) +//#define BurnYM2413SetUpdateHandler(h) YM2413SetUpdateHandler(0, h) + diff --git a/src/burn/sound/burn_ym2608.cpp b/src/burn/sound/burn_ym2608.cpp new file mode 100644 index 00000000..14ac4fba --- /dev/null +++ b/src/burn/sound/burn_ym2608.cpp @@ -0,0 +1,368 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2608.h" + +void (*BurnYM2608Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM2608StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM2608SoundRate; + +static INT16* pBuffer; +static INT16* pYM2608Buffer[6]; + +static INT32* pAYBuffer; + +static INT32 nYM2608Position; +static INT32 nAY8910Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 bYM2208AddSignal; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM2608UpdateDummy(INT16*, INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM2608StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM2608 for part of a frame + +static void AY8910Render(INT32 nSegmentLength) +{ + if (nAY8910Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" AY8910 render %6i -> %6i\n"), nAY8910Position, nSegmentLength); + + nSegmentLength -= nAY8910Position; + + pYM2608Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position; + pYM2608Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position; + pYM2608Buffer[4] = pBuffer + 4 * 4096 + 4 + nAY8910Position; + + AY8910Update(0, &pYM2608Buffer[2], nSegmentLength); + + nAY8910Position += nSegmentLength; +} + +static void YM2608Render(INT32 nSegmentLength) +{ + if (nYM2608Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM2608 render %6i -> %6i\n", nYM2608Position, nSegmentLength)); + + nSegmentLength -= nYM2608Position; + + pYM2608Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2608Position; + pYM2608Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2608Position; + + YM2608UpdateOne(0, &pYM2608Buffer[0], nSegmentLength); + + nYM2608Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void YM2608UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2608SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" YM2608 update -> %6i\n"), nSegmentLength); + + if (nSamplesNeeded < nAY8910Position) { + nSamplesNeeded = nAY8910Position; + } + if (nSamplesNeeded < nYM2608Position) { + nSamplesNeeded = nYM2608Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + YM2608Render(nSamplesNeeded); + AY8910Render(nSamplesNeeded); + + pYM2608Buffer[0] = pBuffer + 0 * 4096 + 4; + pYM2608Buffer[1] = pBuffer + 1 * 4096 + 4; + pYM2608Buffer[2] = pBuffer + 2 * 4096 + 4; + pYM2608Buffer[3] = pBuffer + 3 * 4096 + 4; + pYM2608Buffer[4] = pBuffer + 4 * 4096 + 4; + pYM2608Buffer[5] = pBuffer + 5 * 4096 + 4; + + for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) { + pYM2608Buffer[5][i] = (((INT32)pYM2608Buffer[2][i] + pYM2608Buffer[3][i] + pYM2608Buffer[4][i]) * (4096 * 60 / 100)) >> 12; + } + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT32 nSample; + +#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) + + // Left channel + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM2608Buffer[0][(nFractionalPosition >> 16) - 3] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 3], + pYM2608Buffer[0][(nFractionalPosition >> 16) - 2] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 2], + pYM2608Buffer[0][(nFractionalPosition >> 16) - 1] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 1], + pYM2608Buffer[0][(nFractionalPosition >> 16) - 0] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 0]); + if (bYM2208AddSignal) { + pSoundBuf[i + 0] += CLIP(nSample); + } else { + pSoundBuf[i + 0] = CLIP(nSample); + } + + // Right channel + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM2608Buffer[1][(nFractionalPosition >> 16) - 3] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 3], + pYM2608Buffer[1][(nFractionalPosition >> 16) - 2] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 2], + pYM2608Buffer[1][(nFractionalPosition >> 16) - 1] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 1], + pYM2608Buffer[1][(nFractionalPosition >> 16) - 0] + pYM2608Buffer[5][(nFractionalPosition >> 16) - 0]); + if (bYM2208AddSignal) { + pSoundBuf[i + 1] += CLIP(nSample); + } else { + pSoundBuf[i + 1] = CLIP(nSample); + } + +#undef CLIP + + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pYM2608Buffer[0][i] = pYM2608Buffer[0][(nFractionalPosition >> 16) + i]; + pYM2608Buffer[1][i] = pYM2608Buffer[1][(nFractionalPosition >> 16) + i]; + pYM2608Buffer[2][i] = pYM2608Buffer[2][(nFractionalPosition >> 16) + i]; + pYM2608Buffer[3][i] = pYM2608Buffer[3][(nFractionalPosition >> 16) + i]; + pYM2608Buffer[4][i] = pYM2608Buffer[4][(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0xFFFF; + + nYM2608Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +static void YM2608UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" YM2608 update -> %6i\n", nSegmentLength)); + + if (nSegmentEnd < nAY8910Position) { + nSegmentEnd = nAY8910Position; + } + if (nSegmentEnd < nYM2608Position) { + nSegmentEnd = nYM2608Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM2608Render(nSegmentEnd); + AY8910Render(nSegmentEnd); + + pYM2608Buffer[0] = pBuffer + 4 + 0 * 4096; + pYM2608Buffer[1] = pBuffer + 4 + 1 * 4096; + pYM2608Buffer[2] = pBuffer + 4 + 2 * 4096; + pYM2608Buffer[3] = pBuffer + 4 + 3 * 4096; + pYM2608Buffer[4] = pBuffer + 4 + 4 * 4096; + + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + pAYBuffer[n] = pYM2608Buffer[2][n] + pYM2608Buffer[3][n] + pYM2608Buffer[4][n]; + } + BurnSoundCopy_FM_OPN_A(pYM2608Buffer[0], pAYBuffer, pSoundBuf, nSegmentLength, 65536 * 60 / 100, 65536 * 60 / 100); +#endif + } else { + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + INT32 nAYSample, nTotalSample; + + nAYSample = pYM2608Buffer[2][n]; + nAYSample += pYM2608Buffer[3][n]; + nAYSample += pYM2608Buffer[4][n]; + + nAYSample *= 4096 * 60 / 100; + nAYSample >>= 12; + + nTotalSample = nAYSample + pYM2608Buffer[0][n]; + if (nTotalSample < -32768) { + nTotalSample = -32768; + } else { + if (nTotalSample > 32767) { + nTotalSample = 32767; + } + } + + if (bYM2208AddSignal) { + pSoundBuf[(n << 1) + 0] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 0] = nTotalSample; + } + + nTotalSample = nAYSample + pYM2608Buffer[1][n]; + if (nTotalSample < -32768) { + nTotalSample = -32768; + } else { + if (nTotalSample > 32767) { + nTotalSample = 32767; + } + } + + if (bYM2208AddSignal) { + pSoundBuf[(n << 1) + 1] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 1] = nTotalSample; + } + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pYM2608Buffer[0][i] = pYM2608Buffer[0][nBurnSoundLen + i]; + pYM2608Buffer[1][i] = pYM2608Buffer[1][nBurnSoundLen + i]; + pYM2608Buffer[2][i] = pYM2608Buffer[2][nBurnSoundLen + i]; + pYM2608Buffer[3][i] = pYM2608Buffer[3][nBurnSoundLen + i]; + pYM2608Buffer[4][i] = pYM2608Buffer[4][nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nYM2608Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM2608 core + +void BurnYM2608UpdateRequest() +{ + YM2608Render(BurnYM2608StreamCallback(nBurnYM2608SoundRate)); +} + +static void BurnAY8910UpdateRequest() +{ + AY8910Render(BurnYM2608StreamCallback(nBurnYM2608SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM2608Reset() +{ + BurnTimerReset(); + + YM2608ResetChip(0); +} + +void BurnYM2608Exit() +{ + YM2608Shutdown(); + AY8910Exit(0); + + BurnTimerExit(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + if (pAYBuffer) { + free(pAYBuffer); + pAYBuffer = NULL; + } + + bYM2208AddSignal = 0; +} + +INT32 BurnYM2608Init(INT32 nClockFrequency, UINT8* YM2608ADPCMROM, INT32* nYM2608ADPCMSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal) +{ + BurnTimerInit(&YM2608TimerOver, GetTimeCallback); + + if (nBurnSoundRate <= 0) { + BurnYM2608StreamCallback = YM2608StreamCallbackDummy; + + BurnYM2608Update = YM2608UpdateDummy; + + AY8910InitYM(0, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + YM2608Init(1, nClockFrequency, 11025, (void**)(&YM2608ADPCMROM), nYM2608ADPCMSize, &BurnOPNTimerCallback, IRQCallback); + return 0; + } + + BurnYM2608StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set YM2608 core samplerate to match the hardware + nBurnYM2608SoundRate = nClockFrequency / 144; + // Bring YM2608 core samplerate within usable range + while (nBurnYM2608SoundRate > nBurnSoundRate * 3) { + nBurnYM2608SoundRate >>= 1; + } + + BurnYM2608Update = YM2608UpdateResample; + + nSampleSize = (UINT32)nBurnYM2608SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 0; + } else { + nBurnYM2608SoundRate = nBurnSoundRate; + + BurnYM2608Update = YM2608UpdateNormal; + } + + AY8910InitYM(0, nClockFrequency, nBurnYM2608SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + YM2608Init(1, nClockFrequency, nBurnYM2608SoundRate, (void**)(&YM2608ADPCMROM), nYM2608ADPCMSize, &BurnOPNTimerCallback, IRQCallback); + + pBuffer = (INT16*)malloc(4096 * 6 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * 6 * sizeof(INT16)); + + pAYBuffer = (INT32*)malloc(4096 * sizeof(INT32)); + memset(pAYBuffer, 0, 4096 * sizeof(INT32)); + + nYM2608Position = 0; + nAY8910Position = 0; + + bYM2208AddSignal = bAddSignal; + + return 0; +} + +void BurnYM2608Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScan(nAction, pnMin); + AY8910Scan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM2608Position); + SCAN_VAR(nAY8910Position); + } +} diff --git a/src/burn/sound/burn_ym2608.h b/src/burn/sound/burn_ym2608.h new file mode 100644 index 00000000..86f5a1d4 --- /dev/null +++ b/src/burn/sound/burn_ym2608.h @@ -0,0 +1,19 @@ +// burn_ym2608.h +#include "driver.h" +extern "C" { + #include "ay8910.h" + #include "fm.h" +} +#include "timer.h" + +extern "C" void BurnYM2608UpdateRequest(); + +INT32 BurnYM2608Init(INT32 nClockFrequency, UINT8* YM2608ADPCMROM, INT32* nYM2608ADPCMSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal); +void BurnYM2608Reset(); +void BurnYM2608Exit(); +extern void (*BurnYM2608Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM2608Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM2608Write(a, n) YM2608Write(0, a, n) +#define BurnYM2608Read(a) YM2608Read(0, a) + diff --git a/src/burn/sound/burn_ym2610.cpp b/src/burn/sound/burn_ym2610.cpp new file mode 100644 index 00000000..6dcaba61 --- /dev/null +++ b/src/burn/sound/burn_ym2610.cpp @@ -0,0 +1,400 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2610.h" + +void (*BurnYM2610Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM2610StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM2610SoundRate; + +static INT16* pBuffer; +static INT16* pYM2610Buffer[6]; + +static INT32* pAYBuffer; + +static INT32 nYM2610Position; +static INT32 nAY8910Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 bYM2610AddSignal; +static INT32 bYM2610MixSound; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM2610UpdateDummy(INT16*, INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM2610StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM2610 for part of a frame + +static void AY8910Render(INT32 nSegmentLength) +{ + if (nAY8910Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" AY8910 render %6i -> %6i\n"), nAY8910Position, nSegmentLength); + + nSegmentLength -= nAY8910Position; + + pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position; + pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position; + pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4 + nAY8910Position; + + AY8910Update(0, &pYM2610Buffer[2], nSegmentLength); + + nAY8910Position += nSegmentLength; +} + +static void YM2610Render(INT32 nSegmentLength) +{ + if (nYM2610Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM2610 render %6i -> %6i\n", nYM2610Position, nSegmentLength)); + + nSegmentLength -= nYM2610Position; + + pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2610Position; + pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2610Position; + + YM2610UpdateOne(0, &pYM2610Buffer[0], nSegmentLength); + + nYM2610Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void YM2610UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2610SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" YM2610 update -> %6i\n", nSegmentLength)); + + if (nSamplesNeeded < nAY8910Position) { + nSamplesNeeded = nAY8910Position; + } + if (nSamplesNeeded < nYM2610Position) { + nSamplesNeeded = nYM2610Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + YM2610Render(nSamplesNeeded); + AY8910Render(nSamplesNeeded); + + pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4; + pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4; + pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4; + pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4; + pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4; + pYM2610Buffer[5] = pBuffer + 5 * 4096 + 4; + + for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) { + pYM2610Buffer[5][i] = (((INT32)pYM2610Buffer[2][i] + pYM2610Buffer[3][i] + pYM2610Buffer[4][i]) * (4096 * 60 / 100)) >> 12; + } + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT32 nSample; + +#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) + + if (bYM2610MixSound) { + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] + pYM2610Buffer[1][(nFractionalPosition >> 16) - 3], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] + pYM2610Buffer[1][(nFractionalPosition >> 16) - 1], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] + pYM2610Buffer[1][(nFractionalPosition >> 16) - 2], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] + pYM2610Buffer[1][(nFractionalPosition >> 16) - 0]); + + if (bYM2610AddSignal) { + pSoundBuf[i + 0] += CLIP(nSample); + pSoundBuf[i + 1] += CLIP(nSample); + } else { + pSoundBuf[i + 0] = CLIP(nSample); + pSoundBuf[i + 1] = CLIP(nSample); + } + } else { + // Left channel + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 3], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 2], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 1], + pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 0]); + if (bYM2610AddSignal) { + pSoundBuf[i + 0] += CLIP(nSample); + } else { + pSoundBuf[i + 0] = CLIP(nSample); + } + + // Right channel + nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 3], + pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 2], + pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 1], + pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] + pYM2610Buffer[5][(nFractionalPosition >> 16) - 0]); + if (bYM2610AddSignal) { + pSoundBuf[i + 1] += CLIP(nSample); + } else { + pSoundBuf[i + 1] = CLIP(nSample); + } + } + +#undef CLIP + + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pYM2610Buffer[0][i] = pYM2610Buffer[0][(nFractionalPosition >> 16) + i]; + pYM2610Buffer[1][i] = pYM2610Buffer[1][(nFractionalPosition >> 16) + i]; + pYM2610Buffer[2][i] = pYM2610Buffer[2][(nFractionalPosition >> 16) + i]; + pYM2610Buffer[3][i] = pYM2610Buffer[3][(nFractionalPosition >> 16) + i]; + pYM2610Buffer[4][i] = pYM2610Buffer[4][(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0xFFFF; + + nYM2610Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +static void YM2610UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" YM2610 update -> %6i\n", nSegmentLength)); + + if (nSegmentEnd < nAY8910Position) { + nSegmentEnd = nAY8910Position; + } + if (nSegmentEnd < nYM2610Position) { + nSegmentEnd = nYM2610Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM2610Render(nSegmentEnd); + AY8910Render(nSegmentEnd); + + pYM2610Buffer[0] = pBuffer + 4 + 0 * 4096; + pYM2610Buffer[1] = pBuffer + 4 + 1 * 4096; + pYM2610Buffer[2] = pBuffer + 4 + 2 * 4096; + pYM2610Buffer[3] = pBuffer + 4 + 3 * 4096; + pYM2610Buffer[4] = pBuffer + 4 + 4 * 4096; + + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + pAYBuffer[n] = pYM2610Buffer[2][n] + pYM2610Buffer[3][n] + pYM2610Buffer[4][n]; + } + BurnSoundCopy_FM_OPN_A(pYM2610Buffer[0], pAYBuffer, pSoundBuf, nSegmentLength, 65536 * 60 / 100, 65536 * 60 / 100); +#endif + } else { + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + INT32 nAYSample, nTotalSample; + + nAYSample = pYM2610Buffer[2][n]; + nAYSample += pYM2610Buffer[3][n]; + nAYSample += pYM2610Buffer[4][n]; + + nAYSample *= 4096 * 60 / 100; + nAYSample >>= 12; + +#define CLIP(A) A = ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A)) + + if (bYM2610MixSound) { + nTotalSample = nAYSample + pYM2610Buffer[0][n] + pYM2610Buffer[1][n];; + CLIP(nTotalSample); + + if (bYM2610AddSignal) { + pSoundBuf[(n << 1) + 0] += nTotalSample; + pSoundBuf[(n << 1) + 1] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 0] = nTotalSample; + pSoundBuf[(n << 1) + 1] = nTotalSample; + } + } else { + nTotalSample = nAYSample + pYM2610Buffer[0][n]; + CLIP(nTotalSample); + + if (bYM2610AddSignal) { + pSoundBuf[(n << 1) + 0] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 0] = nTotalSample; + } + + nTotalSample = nAYSample + pYM2610Buffer[1][n]; + CLIP(nTotalSample); + + if (bYM2610AddSignal) { + pSoundBuf[(n << 1) + 1] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 1] = nTotalSample; + } + } +#undef CLIP + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pYM2610Buffer[0][i] = pYM2610Buffer[0][nBurnSoundLen + i]; + pYM2610Buffer[1][i] = pYM2610Buffer[1][nBurnSoundLen + i]; + pYM2610Buffer[2][i] = pYM2610Buffer[2][nBurnSoundLen + i]; + pYM2610Buffer[3][i] = pYM2610Buffer[3][nBurnSoundLen + i]; + pYM2610Buffer[4][i] = pYM2610Buffer[4][nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nYM2610Position = nExtraSamples; + nAY8910Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM2610 core + +void BurnYM2610UpdateRequest() +{ + YM2610Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate)); +} + +static void BurnAY8910UpdateRequest() +{ + AY8910Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM2610Reset() +{ + BurnTimerReset(); + + YM2610ResetChip(0); +} + +void BurnYM2610Exit() +{ + YM2610Shutdown(); + AY8910Exit(0); + + BurnTimerExit(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + if (pAYBuffer) { + free(pAYBuffer); + pAYBuffer = NULL; + } + + bYM2610AddSignal = 0; + bYM2610MixSound = 0; +} + +void BurnYM2610MapADPCMROM(UINT8* YM2610ADPCMAROM, INT32 nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32 nYM2610ADPCMBSize) +{ + YM2610SetRom(0, YM2610ADPCMAROM, nYM2610ADPCMASize, YM2610ADPCMBROM, nYM2610ADPCMBSize); +} + +INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal) +{ + BurnTimerInit(&YM2610TimerOver, GetTimeCallback); + + if (nBurnSoundRate <= 0) { + BurnYM2610StreamCallback = YM2610StreamCallbackDummy; + + BurnYM2610Update = YM2610UpdateDummy; + + AY8910InitYM(0, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + YM2610Init(1, nClockFrequency, 11025, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback); + return 0; + } + + BurnYM2610StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set YM2610 core samplerate to match the hardware + nBurnYM2610SoundRate = nClockFrequency / 144; + // Bring YM2610 core samplerate within usable range + while (nBurnYM2610SoundRate > nBurnSoundRate * 3) { + nBurnYM2610SoundRate >>= 1; + } + + BurnYM2610Update = YM2610UpdateResample; + + nSampleSize = (UINT32)nBurnYM2610SoundRate * (1 << 16) / nBurnSoundRate; + } else { + nBurnYM2610SoundRate = nBurnSoundRate; + + BurnYM2610Update = YM2610UpdateNormal; + } + + AY8910InitYM(0, nClockFrequency, nBurnYM2610SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest); + YM2610Init(1, nClockFrequency, nBurnYM2610SoundRate, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback); + + pBuffer = (INT16*)malloc(4096 * 6 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * 6 * sizeof(INT16)); + + pAYBuffer = (INT32*)malloc(4096 * sizeof(INT32)); + memset(pAYBuffer, 0, 4096 * sizeof(INT32)); + + nYM2610Position = 0; + nAY8910Position = 0; + + nFractionalPosition = 0; + bYM2610AddSignal = bAddSignal; + + return 0; +} + +void BurnYM2610SetSoundMixMode(INT32 Mix) +{ + bYM2610MixSound = Mix; +} + +void BurnYM2610Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScan(nAction, pnMin); + AY8910Scan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM2610Position); + SCAN_VAR(nAY8910Position); + } +} diff --git a/src/burn/sound/burn_ym2610.h b/src/burn/sound/burn_ym2610.h new file mode 100644 index 00000000..ca0f4aee --- /dev/null +++ b/src/burn/sound/burn_ym2610.h @@ -0,0 +1,21 @@ +// burn_ym2610.h +#include "driver.h" +extern "C" { + #include "ay8910.h" + #include "fm.h" +} +#include "timer.h" + +extern "C" void BurnYM2610UpdateRequest(); + +void BurnYM2610MapADPCMROM(UINT8* YM2610ADPCMAROM, INT32 nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32 nYM2610ADPCMBSize); +INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal); +void BurnYM2610SetSoundMixMode(INT32 Mix); +void BurnYM2610Reset(); +void BurnYM2610Exit(); +extern void (*BurnYM2610Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM2610Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM2610Write(a, n) YM2610Write(0, a, n) +#define BurnYM2610Read(a) YM2610Read(0, a) + diff --git a/src/burn/sound/burn_ym2612.cpp b/src/burn/sound/burn_ym2612.cpp new file mode 100644 index 00000000..3a2eb5cd --- /dev/null +++ b/src/burn/sound/burn_ym2612.cpp @@ -0,0 +1,228 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym2612.h" + +#define MAX_YM2612 2 + +void (*BurnYM2612Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM2612StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM2612SoundRate; + +static INT16* pBuffer; +static INT16* pYM2612Buffer[2 * MAX_YM2612]; + +static INT32 nYM2612Position; + +static INT32 nFractionalPosition; + +static INT32 nNumChips = 0; +static INT32 bYM2612AddSignal; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM2612UpdateDummy(INT16*, INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM2612StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM2612 for part of a frame + +static void YM2612Render(INT32 nSegmentLength) +{ + if (nYM2612Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM2612 render %6i -> %6i\n", nYM2612Position, nSegmentLength)); + + nSegmentLength -= nYM2612Position; + + pYM2612Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2612Position; + pYM2612Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2612Position; + + YM2612UpdateOne(0, &pYM2612Buffer[0], nSegmentLength); + + if (nNumChips > 1) { + pYM2612Buffer[2] = pBuffer + 2 * 4096 + 4 + nYM2612Position; + pYM2612Buffer[3] = pBuffer + 3 * 4096 + 4 + nYM2612Position; + + YM2612UpdateOne(1, &pYM2612Buffer[2], nSegmentLength); + } + + nYM2612Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- + +// Update the sound buffer +static void YM2612UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 i; + +// bprintf(PRINT_NORMAL, _T(" YM2612 update -> %6i\n", nSegmentLength)); + + if (nSegmentEnd < nYM2612Position) { + nSegmentEnd = nYM2612Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM2612Render(nSegmentEnd); + + pYM2612Buffer[0] = pBuffer + 4 + 0 * 4096; + pYM2612Buffer[1] = pBuffer + 4 + 1 * 4096; + if (nNumChips > 1) { + pYM2612Buffer[2] = pBuffer + 4 + 2 * 4096; + pYM2612Buffer[3] = pBuffer + 4 + 3 * 4096; + } + + for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) { + INT32 nTotalSample; + + nTotalSample = pYM2612Buffer[0][n]; + if (nNumChips > 1) nTotalSample += pYM2612Buffer[2][n]; + if (nTotalSample < -32768) { + nTotalSample = -32768; + } else { + if (nTotalSample > 32767) { + nTotalSample = 32767; + } + } + + if (bYM2612AddSignal) { + pSoundBuf[(n << 1) + 0] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 0] = nTotalSample; + } + + nTotalSample = pYM2612Buffer[1][n]; + if (nNumChips > 1) nTotalSample += pYM2612Buffer[3][n]; + if (nTotalSample < -32768) { + nTotalSample = -32768; + } else { + if (nTotalSample > 32767) { + nTotalSample = 32767; + } + } + + if (bYM2612AddSignal) { + pSoundBuf[(n << 1) + 1] += nTotalSample; + } else { + pSoundBuf[(n << 1) + 1] = nTotalSample; + } + } + + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + int nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (i = 0; i < nExtraSamples; i++) { + pYM2612Buffer[0][i] = pYM2612Buffer[0][nBurnSoundLen + i]; + pYM2612Buffer[1][i] = pYM2612Buffer[1][nBurnSoundLen + i]; + if (nNumChips > 1) { + pYM2612Buffer[2][i] = pYM2612Buffer[2][nBurnSoundLen + i]; + pYM2612Buffer[3][i] = pYM2612Buffer[3][nBurnSoundLen + i]; + } + } + + nFractionalPosition = 0; + + nYM2612Position = nExtraSamples; + + dTime += 100.0 / nBurnFPS; + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM2612 core + +void BurnYM2612UpdateRequest() +{ + YM2612Render(BurnYM2612StreamCallback(nBurnYM2612SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM2612Reset() +{ + BurnTimerReset(); + + for (INT32 i = 0; i < nNumChips; i++) { + YM2612ResetChip(i); + } +} + +void BurnYM2612Exit() +{ + YM2612Shutdown(); + + BurnTimerExit(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + nNumChips = 0; + bYM2612AddSignal = 0; +} + +INT32 BurnYM2612Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal) +{ + if (num > MAX_YM2612) num = MAX_YM2612; + + BurnTimerInit(&YM2612TimerOver, GetTimeCallback); + + if (nBurnSoundRate <= 0) { + BurnYM2612StreamCallback = YM2612StreamCallbackDummy; + + BurnYM2612Update = YM2612UpdateDummy; + + YM2612Init(num, nClockFrequency, 11025, &BurnOPNTimerCallback, IRQCallback); + return 0; + } + + BurnYM2612StreamCallback = StreamCallback; + + nBurnYM2612SoundRate = nBurnSoundRate; + BurnYM2612Update = YM2612UpdateNormal; + + YM2612Init(num, nClockFrequency, nBurnYM2612SoundRate, &BurnOPNTimerCallback, IRQCallback); + + pBuffer = (INT16*)malloc(4096 * 2 * num * sizeof(INT16)); + memset(pBuffer, 0, 4096 * 2 * num * sizeof(INT16)); + + nYM2612Position = 0; + nFractionalPosition = 0; + + nNumChips = num; + bYM2612AddSignal = bAddSignal; + + return 0; +} + +void BurnYM2612Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScan(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM2612Position); + } +} + +#undef MAX_YM2612 diff --git a/src/burn/sound/burn_ym2612.h b/src/burn/sound/burn_ym2612.h new file mode 100644 index 00000000..ab1bdb45 --- /dev/null +++ b/src/burn/sound/burn_ym2612.h @@ -0,0 +1,26 @@ +// burn_ym2612.h +#include "driver.h" +extern "C" { + #include "fm.h" +} +#include "timer.h" + +extern "C" void BurnYM2612UpdateRequest(); + +INT32 BurnYM2612Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal); +void BurnYM2612Reset(); +void BurnYM2612Exit(); +extern void (*BurnYM2612Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM2612Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM2612Write(i, a, n) YM2612Write(i, a, n) +#define BurnYM2612Read(i, a) YM2612Read(i, a) + +#define BurnYM3438Init(i, n, a, b, c, d) BurnYM2612Init(i, n, a, b, c, d) +#define BurnYM3438Reset() BurnYM2612Reset() +#define BurnYM3438Exit() BurnYM2612Exit() +#define BurnYM3438Update(p, i) BurnYM2612Update(p, i) +#define BurnYM3438Scan(n, i) BurnYM2612Scan(n, i) + +#define BurnYM3438Write(i, a, n) YM2612Write(i, a, n) +#define BurnYM3438Read(i, a) YM2612Read(i, a) diff --git a/src/burn/sound/burn_ym3526.cpp b/src/burn/sound/burn_ym3526.cpp new file mode 100644 index 00000000..dece3e47 --- /dev/null +++ b/src/burn/sound/burn_ym3526.cpp @@ -0,0 +1,542 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym3526.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "m6502_intf.h" + +// Timer Related + +#define MAX_TIMER_VALUE ((1 << 30) - 65536) + +static double dTimeYM3526; // Time elapsed since the emulated machine was started + +static INT32 nTimerCount[2], nTimerStart[2]; + +// Callbacks +static INT32 (*pTimerOverCallback)(INT32, INT32); +static double (*pTimerTimeCallback)(); + +static INT32 nCPUClockspeed = 0; +static INT32 (*pCPUTotalCycles)() = NULL; +static INT32 (*pCPURun)(INT32) = NULL; +static void (*pCPURunEnd)() = NULL; + +// --------------------------------------------------------------------------- +// Running time + +static double BurnTimerTimeCallbackDummy() +{ + return 0.0; +} + +extern "C" double BurnTimerGetTimeYM3526() +{ + return dTimeYM3526 + pTimerTimeCallback(); +} + +// --------------------------------------------------------------------------- +// Update timers + +static INT32 nTicksTotal, nTicksDone, nTicksExtra; + +INT32 BurnTimerUpdateYM3526(INT32 nCycles) +{ + INT32 nIRQStatus = 0; + + nTicksTotal = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" -- Ticks: %08X, cycles %i\n"), nTicksTotal, nCycles); + + while (nTicksDone < nTicksTotal) { + INT32 nTimer, nCyclesSegment, nTicksSegment; + + // Determine which timer fires first + if (nTimerCount[0] <= nTimerCount[1]) { + nTicksSegment = nTimerCount[0]; + } else { + nTicksSegment = nTimerCount[1]; + } + if (nTicksSegment > nTicksTotal) { + nTicksSegment = nTicksTotal; + } + + nCyclesSegment = MAKE_CPU_CYLES(nTicksSegment + nTicksExtra, nCPUClockspeed); +// bprintf(PRINT_NORMAL, _T(" - Timer: %08X, %08X, %08X, cycles %i, %i\n"), nTicksDone, nTicksSegment, nTicksTotal, nCyclesSegment, pCPUTotalCycles()); + + pCPURun(nCyclesSegment - pCPUTotalCycles()); + + nTicksDone = MAKE_TIMER_TICKS(pCPUTotalCycles() + 1, nCPUClockspeed) - 1; +// bprintf(PRINT_NORMAL, _T(" - ticks done -> %08X cycles -> %i\n"), nTicksDone, pCPUTotalCycles()); + + nTimer = 0; + if (nTicksDone >= nTimerCount[0]) { + if (nTimerStart[0] == MAX_TIMER_VALUE) { + nTimerCount[0] = MAX_TIMER_VALUE; + } else { + nTimerCount[0] += nTimerStart[0]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 0 fired\n")); + nTimer |= 1; + } + if (nTicksDone >= nTimerCount[1]) { + if (nTimerStart[1] == MAX_TIMER_VALUE) { + nTimerCount[1] = MAX_TIMER_VALUE; + } else { + nTimerCount[1] += nTimerStart[1]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 1 fired\n")); + nTimer |= 2; + } + if (nTimer & 1) { + nIRQStatus |= pTimerOverCallback(0, 0); + } + if (nTimer & 2) { + nIRQStatus |= pTimerOverCallback(0, 1); + } + } + + return nIRQStatus; +} + +void BurnTimerEndFrameYM3526(INT32 nCycles) +{ + int nTicks = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + + BurnTimerUpdateYM3526(nCycles); + + if (nTimerCount[0] < MAX_TIMER_VALUE) { + nTimerCount[0] -= nTicks; + } + if (nTimerCount[1] < MAX_TIMER_VALUE) { + nTimerCount[1] -= nTicks; + } + + nTicksDone -= nTicks; + if (nTicksDone < 0) { +// bprintf(PRINT_ERROR, _T(" -- ticks done -> %08X\n"), nTicksDone); + nTicksDone = 0; + } +} + +void BurnTimerUpdateEndYM3526() +{ +// bprintf(PRINT_NORMAL, _T(" - end %i\n"), pCPUTotalCycles()); + + pCPURunEnd(); + + nTicksTotal = 0; +} + +void BurnOPLTimerCallbackYM3526(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerCount[c] = MAX_TIMER_VALUE; +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + return; + } + + nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnTimerScanYM3526(INT32 nAction, INT32* pnMin) +{ + if (pnMin && *pnMin < 0x029521) { + *pnMin = 0x029521; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nTimerCount); + SCAN_VAR(nTimerStart); + SCAN_VAR(dTimeYM3526); + + SCAN_VAR(nTicksDone); + } +} + +void BurnTimerExitYM3526() +{ + nCPUClockspeed = 0; + pCPUTotalCycles = NULL; + pCPURun = NULL; + pCPURunEnd = NULL; + + return; +} + +void BurnTimerResetYM3526() +{ + nTimerCount[0] = nTimerCount[1] = MAX_TIMER_VALUE; + nTimerStart[0] = nTimerStart[1] = MAX_TIMER_VALUE; + + dTimeYM3526 = 0.0; + + nTicksDone = 0; +} + +INT32 BurnTimerInitYM3526(INT32 (*pOverCallback)(INT32, INT32), double (*pTimeCallback)()) +{ + BurnTimerExitYM3526(); + + pTimerOverCallback = pOverCallback; + pTimerTimeCallback = pTimeCallback ? pTimeCallback : BurnTimerTimeCallbackDummy; + + BurnTimerResetYM3526(); + + return 0; +} + +INT32 BurnTimerAttachSekYM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = SekTotalCycles; + pCPURun = SekRun; + pCPURunEnd = SekRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachZetYM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = ZetTotalCycles; + pCPURun = ZetRun; + pCPURunEnd = ZetRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6809YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6809TotalCycles; + pCPURun = M6809Run; + pCPURunEnd = M6809RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD6309YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = HD6309TotalCycles; + pCPURun = HD6309Run; + pCPURunEnd = HD6309RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6800YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6800Run; + pCPURunEnd = M6800RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD63701YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = HD63701Run; + pCPURunEnd = HD63701RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6803YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6803Run; + pCPURunEnd = M6803RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6502YM3526(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6502TotalCycles; + pCPURun = M6502Run; + pCPURunEnd = M6502RunEnd; // doesn't do anything... + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +// Sound Related + +void (*BurnYM3526Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM3526StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM3526SoundRate; + +static INT16* pBuffer; +static INT16* pYM3526Buffer; + +static INT32 nYM3526Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 bYM3526AddSignal; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM3526UpdateDummy(INT16* , INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM3526StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM3526 for part of a frame + +static void YM3526Render(INT32 nSegmentLength) +{ + if (nYM3526Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM3526 render %6i -> %6i\n", nYM3526Position, nSegmentLength)); + + nSegmentLength -= nYM3526Position; + + YM3526UpdateOne(0, pBuffer + 0 * 4096 + 4 + nYM3526Position, nSegmentLength); + + nYM3526Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void YM3526UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnYM3526SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" YM3526 update -> %6i\n", nSegmentLength)); + + if (nSamplesNeeded < nYM3526Position) { + nSamplesNeeded = nYM3526Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + YM3526Render(nSamplesNeeded); + + pYM3526Buffer = pBuffer + 0 * 4096 + 4; + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT16 nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM3526Buffer[(nFractionalPosition >> 16) - 3], + pYM3526Buffer[(nFractionalPosition >> 16) - 2], + pYM3526Buffer[(nFractionalPosition >> 16) - 1], + pYM3526Buffer[(nFractionalPosition >> 16) - 0]); + if (bYM3526AddSignal) { + pSoundBuf[i + 0] += nSample; + pSoundBuf[i + 1] += nSample; + } else { + pSoundBuf[i + 0] = nSample; + pSoundBuf[i + 1] = nSample; + } + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pYM3526Buffer[i] = pYM3526Buffer[(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0xFFFF; + + nYM3526Position = nExtraSamples; + } +} + +static void YM3526UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" YM3526 render %6i -> %6i\n"), nYM3526Position, nSegmentEnd); + + if (nSegmentEnd < nYM3526Position) { + nSegmentEnd = nYM3526Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM3526Render(nSegmentEnd); + + pYM3526Buffer = pBuffer + 4 + 0 * 4096; + + for (INT32 i = nFractionalPosition; i < nSegmentLength; i++) { + if (bYM3526AddSignal) { + pSoundBuf[(i << 1) + 0] += pYM3526Buffer[i]; + pSoundBuf[(i << 1) + 1] += pYM3526Buffer[i]; + } else { + pSoundBuf[(i << 1) + 0] = pYM3526Buffer[i]; + pSoundBuf[(i << 1) + 1] = pYM3526Buffer[i]; + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pYM3526Buffer[i] = pYM3526Buffer[nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nYM3526Position = nExtraSamples; + + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM3526 core + +void BurnYM3526UpdateRequest(int, int) +{ + YM3526Render(BurnYM3526StreamCallback(nBurnYM3526SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM3526Reset() +{ + BurnTimerResetYM3526(); + + YM3526ResetChip(0); +} + +void BurnYM3526Exit() +{ + YM3526Shutdown(); + + BurnTimerExitYM3526(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + bYM3526AddSignal = 0; +} + +INT32 BurnYM3526Init(INT32 nClockFrequency, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal) +{ + BurnTimerInitYM3526(&YM3526TimerOver, NULL); + + if (nBurnSoundRate <= 0) { + BurnYM3526StreamCallback = YM3526StreamCallbackDummy; + + BurnYM3526Update = YM3526UpdateDummy; + + YM3526Init(1, nClockFrequency, 11025); + return 0; + } + + BurnYM3526StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set YM3526 core samplerate to match the hardware + nBurnYM3526SoundRate = nClockFrequency / 72; + // Bring YM3526 core samplerate within usable range + while (nBurnYM3526SoundRate > nBurnSoundRate * 3) { + nBurnYM3526SoundRate >>= 1; + } + + BurnYM3526Update = YM3526UpdateResample; + + nSampleSize = (UINT32)nBurnYM3526SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 0; + } else { + nBurnYM3526SoundRate = nBurnSoundRate; + + BurnYM3526Update = YM3526UpdateNormal; + } + + YM3526Init(1, nClockFrequency, nBurnYM3526SoundRate); + YM3526SetIRQHandler(0, IRQCallback, 0); + YM3526SetTimerHandler(0, &BurnOPLTimerCallbackYM3526, 0); + YM3526SetUpdateHandler(0, &BurnYM3526UpdateRequest, 0); + + pBuffer = (INT16*)malloc(4096 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * sizeof(INT16)); + + nYM3526Position = 0; + + nFractionalPosition = 0; + + bYM3526AddSignal = bAddSignal; + + return 0; +} + +void BurnYM3526Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScanYM3526(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM3526Position); + } +} diff --git a/src/burn/sound/burn_ym3526.h b/src/burn/sound/burn_ym3526.h new file mode 100644 index 00000000..04ac24cb --- /dev/null +++ b/src/burn/sound/burn_ym3526.h @@ -0,0 +1,27 @@ +#include "driver.h" +extern "C" { + #include "fmopl.h" +} +#include "timer.h" + +INT32 BurnTimerUpdateYM3526(INT32 nCycles); +void BurnTimerEndFrameYM3526(INT32 nCycles); +INT32 BurnTimerAttachSekYM3526(INT32 nClockspeed); +INT32 BurnTimerAttachZetYM3526(INT32 nClockspeed); +INT32 BurnTimerAttachM6809YM3526(INT32 nClockspeed); +INT32 BurnTimerAttachHD6309YM3526(INT32 nClockspeed); +INT32 BurnTimerAttachM6800YM3526(INT32 nClockspeed); +INT32 BurnTimerAttachHD63701YM3526(INT32 nClockspeed); +INT32 BurnTimerAttachM6803YM3526(INT32 nClockspeed); +INT32 BurnTimerAttachM6502YM3526(INT32 nClockspeed); + +extern "C" void BurnYM3526UpdateRequest(); + +INT32 BurnYM3526Init(INT32 nClockFrequency, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal); +void BurnYM3526Reset(); +void BurnYM3526Exit(); +extern void (*BurnYM3526Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM3526Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM3526Write(a, n) YM3526Write(0, a, n) +#define BurnYM3526Read(a) YM3526Read(0, a) diff --git a/src/burn/sound/burn_ym3812.cpp b/src/burn/sound/burn_ym3812.cpp new file mode 100644 index 00000000..5eaed966 --- /dev/null +++ b/src/burn/sound/burn_ym3812.cpp @@ -0,0 +1,542 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ym3812.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "m6502_intf.h" + +// Timer Related + +#define MAX_TIMER_VALUE ((1 << 30) - 65536) + +static double dTimeYM3812; // Time elapsed since the emulated machine was started + +static INT32 nTimerCount[2], nTimerStart[2]; + +// Callbacks +static INT32 (*pTimerOverCallback)(INT32, INT32); +static double (*pTimerTimeCallback)(); + +static INT32 nCPUClockspeed = 0; +static INT32 (*pCPUTotalCycles)() = NULL; +static INT32 (*pCPURun)(INT32) = NULL; +static void (*pCPURunEnd)() = NULL; + +// --------------------------------------------------------------------------- +// Running time + +static double BurnTimerTimeCallbackDummy() +{ + return 0.0; +} + +extern "C" double BurnTimerGetTimeYM3812() +{ + return dTimeYM3812 + pTimerTimeCallback(); +} + +// --------------------------------------------------------------------------- +// Update timers + +static INT32 nTicksTotal, nTicksDone, nTicksExtra; + +INT32 BurnTimerUpdateYM3812(INT32 nCycles) +{ + INT32 nIRQStatus = 0; + + nTicksTotal = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" -- Ticks: %08X, cycles %i\n"), nTicksTotal, nCycles); + + while (nTicksDone < nTicksTotal) { + INT32 nTimer, nCyclesSegment, nTicksSegment; + + // Determine which timer fires first + if (nTimerCount[0] <= nTimerCount[1]) { + nTicksSegment = nTimerCount[0]; + } else { + nTicksSegment = nTimerCount[1]; + } + if (nTicksSegment > nTicksTotal) { + nTicksSegment = nTicksTotal; + } + + nCyclesSegment = MAKE_CPU_CYLES(nTicksSegment + nTicksExtra, nCPUClockspeed); +// bprintf(PRINT_NORMAL, _T(" - Timer: %08X, %08X, %08X, cycles %i, %i\n"), nTicksDone, nTicksSegment, nTicksTotal, nCyclesSegment, pCPUTotalCycles()); + + pCPURun(nCyclesSegment - pCPUTotalCycles()); + + nTicksDone = MAKE_TIMER_TICKS(pCPUTotalCycles() + 1, nCPUClockspeed) - 1; +// bprintf(PRINT_NORMAL, _T(" - ticks done -> %08X cycles -> %i\n"), nTicksDone, pCPUTotalCycles()); + + nTimer = 0; + if (nTicksDone >= nTimerCount[0]) { + if (nTimerStart[0] == MAX_TIMER_VALUE) { + nTimerCount[0] = MAX_TIMER_VALUE; + } else { + nTimerCount[0] += nTimerStart[0]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 0 fired\n")); + nTimer |= 1; + } + if (nTicksDone >= nTimerCount[1]) { + if (nTimerStart[1] == MAX_TIMER_VALUE) { + nTimerCount[1] = MAX_TIMER_VALUE; + } else { + nTimerCount[1] += nTimerStart[1]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 1 fired\n")); + nTimer |= 2; + } + if (nTimer & 1) { + nIRQStatus |= pTimerOverCallback(0, 0); + } + if (nTimer & 2) { + nIRQStatus |= pTimerOverCallback(0, 1); + } + } + + return nIRQStatus; +} + +void BurnTimerEndFrameYM3812(INT32 nCycles) +{ + INT32 nTicks = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + + BurnTimerUpdateYM3812(nCycles); + + if (nTimerCount[0] < MAX_TIMER_VALUE) { + nTimerCount[0] -= nTicks; + } + if (nTimerCount[1] < MAX_TIMER_VALUE) { + nTimerCount[1] -= nTicks; + } + + nTicksDone -= nTicks; + if (nTicksDone < 0) { +// bprintf(PRINT_ERROR, _T(" -- ticks done -> %08X\n"), nTicksDone); + nTicksDone = 0; + } +} + +void BurnTimerUpdateEndYM3812() +{ +// bprintf(PRINT_NORMAL, _T(" - end %i\n"), pCPUTotalCycles()); + + pCPURunEnd(); + + nTicksTotal = 0; +} + +void BurnOPLTimerCallbackYM3812(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerCount[c] = MAX_TIMER_VALUE; +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + return; + } + + nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnTimerScanYM3812(INT32 nAction, INT32* pnMin) +{ + if (pnMin && *pnMin < 0x029521) { + *pnMin = 0x029521; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nTimerCount); + SCAN_VAR(nTimerStart); + SCAN_VAR(dTimeYM3812); + + SCAN_VAR(nTicksDone); + } +} + +void BurnTimerExitYM3812() +{ + nCPUClockspeed = 0; + pCPUTotalCycles = NULL; + pCPURun = NULL; + pCPURunEnd = NULL; + + return; +} + +void BurnTimerResetYM3812() +{ + nTimerCount[0] = nTimerCount[1] = MAX_TIMER_VALUE; + nTimerStart[0] = nTimerStart[1] = MAX_TIMER_VALUE; + + dTimeYM3812 = 0.0; + + nTicksDone = 0; +} + +INT32 BurnTimerInitYM3812(INT32 (*pOverCallback)(INT32, INT32), double (*pTimeCallback)()) +{ + BurnTimerExitYM3812(); + + pTimerOverCallback = pOverCallback; + pTimerTimeCallback = pTimeCallback ? pTimeCallback : BurnTimerTimeCallbackDummy; + + BurnTimerResetYM3812(); + + return 0; +} + +INT32 BurnTimerAttachSekYM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = SekTotalCycles; + pCPURun = SekRun; + pCPURunEnd = SekRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachZetYM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = ZetTotalCycles; + pCPURun = ZetRun; + pCPURunEnd = ZetRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6809YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6809TotalCycles; + pCPURun = M6809Run; + pCPURunEnd = M6809RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD6309YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = HD6309TotalCycles; + pCPURun = HD6309Run; + pCPURunEnd = HD6309RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6800YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6800Run; + pCPURunEnd = M6800RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD63701YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = HD63701Run; + pCPURunEnd = HD63701RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6803YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6803Run; + pCPURunEnd = M6803RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6502YM3812(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6502TotalCycles; + pCPURun = M6502Run; + pCPURunEnd = M6502RunEnd; // doesn't do anything... + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +// Sound Related + +void (*BurnYM3812Update)(INT16* pSoundBuf, INT32 nSegmentEnd); + +static INT32 (*BurnYM3812StreamCallback)(INT32 nSoundRate); + +static INT32 nBurnYM3812SoundRate; + +static INT16* pBuffer; +static INT16* pYM3812Buffer; + +static INT32 nYM3812Position; + +static UINT32 nSampleSize; +static INT32 nFractionalPosition; + +static INT32 bYM3812AddSignal; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static void YM3812UpdateDummy(INT16* , INT32 /* nSegmentEnd */) +{ + return; +} + +static INT32 YM3812StreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + +// ---------------------------------------------------------------------------- +// Execute YM3812 for part of a frame + +static void YM3812Render(INT32 nSegmentLength) +{ + if (nYM3812Position >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YM3812 render %6i -> %6i\n", nYM3812Position, nSegmentLength)); + + nSegmentLength -= nYM3812Position; + + YM3812UpdateOne(0, pBuffer + 0 * 4096 + 4 + nYM3812Position, nSegmentLength); + + nYM3812Position += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +static void YM3812UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + INT32 nSamplesNeeded = nSegmentEnd * nBurnYM3812SoundRate / nBurnSoundRate + 1; + +// bprintf(PRINT_NORMAL, _T(" YM3812 update -> %6i\n", nSegmentLength)); + + if (nSamplesNeeded < nYM3812Position) { + nSamplesNeeded = nYM3812Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + nSegmentLength <<= 1; + + YM3812Render(nSamplesNeeded); + + pYM3812Buffer = pBuffer + 0 * 4096 + 4; + + for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) { + INT16 nSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0FFF, + pYM3812Buffer[(nFractionalPosition >> 16) - 3], + pYM3812Buffer[(nFractionalPosition >> 16) - 2], + pYM3812Buffer[(nFractionalPosition >> 16) - 1], + pYM3812Buffer[(nFractionalPosition >> 16) - 0]); + if (bYM3812AddSignal) { + pSoundBuf[i + 0] += nSample; + pSoundBuf[i + 1] += nSample; + } else { + pSoundBuf[i + 0] = nSample; + pSoundBuf[i + 1] = nSample; + } + } + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16); + +// bprintf(PRINT_NORMAL, _T(" %6i rendered, %i extra, %i <- %i\n"), nSamplesNeeded, nExtraSamples, nExtraSamples, (nFractionalPosition >> 16) + nExtraSamples - 1); + + for (INT32 i = -4; i < nExtraSamples; i++) { + pYM3812Buffer[i] = pYM3812Buffer[(nFractionalPosition >> 16) + i]; + } + + nFractionalPosition &= 0xFFFF; + + nYM3812Position = nExtraSamples; + } +} + +static void YM3812UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd) +{ + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" YM3812 render %6i -> %6i\n"), nYM3812Position, nSegmentEnd); + + if (nSegmentEnd < nYM3812Position) { + nSegmentEnd = nYM3812Position; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YM3812Render(nSegmentEnd); + + pYM3812Buffer = pBuffer + 4 + 0 * 4096; + + for (INT32 i = nFractionalPosition; i < nSegmentLength; i++) { + if (bYM3812AddSignal) { + pSoundBuf[(i << 1) + 0] += pYM3812Buffer[i]; + pSoundBuf[(i << 1) + 1] += pYM3812Buffer[i]; + } else { + pSoundBuf[(i << 1) + 0] = pYM3812Buffer[i]; + pSoundBuf[(i << 1) + 1] = pYM3812Buffer[i]; + } + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pYM3812Buffer[i] = pYM3812Buffer[nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nYM3812Position = nExtraSamples; + + } +} + +// ---------------------------------------------------------------------------- +// Callbacks for YM3812 core + +void BurnYM3812UpdateRequest(INT32, INT32) +{ + YM3812Render(BurnYM3812StreamCallback(nBurnYM3812SoundRate)); +} + +// ---------------------------------------------------------------------------- +// Initialisation, etc. + +void BurnYM3812Reset() +{ + BurnTimerResetYM3812(); + + YM3812ResetChip(0); +} + +void BurnYM3812Exit() +{ + YM3812Shutdown(); + + BurnTimerExitYM3812(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + bYM3812AddSignal = 0; +} + +INT32 BurnYM3812Init(INT32 nClockFrequency, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal) +{ + BurnTimerInitYM3812(&YM3812TimerOver, NULL); + + if (nBurnSoundRate <= 0) { + BurnYM3812StreamCallback = YM3812StreamCallbackDummy; + + BurnYM3812Update = YM3812UpdateDummy; + + YM3812Init(1, nClockFrequency, 11025); + return 0; + } + + BurnYM3812StreamCallback = StreamCallback; + + if (nFMInterpolation == 3) { + // Set YM3812 core samplerate to match the hardware + nBurnYM3812SoundRate = nClockFrequency / 72; + // Bring YM3812 core samplerate within usable range + while (nBurnYM3812SoundRate > nBurnSoundRate * 3) { + nBurnYM3812SoundRate >>= 1; + } + + BurnYM3812Update = YM3812UpdateResample; + + nSampleSize = (UINT32)nBurnYM3812SoundRate * (1 << 16) / nBurnSoundRate; + nFractionalPosition = 0; + } else { + nBurnYM3812SoundRate = nBurnSoundRate; + + BurnYM3812Update = YM3812UpdateNormal; + } + + YM3812Init(1, nClockFrequency, nBurnYM3812SoundRate); + YM3812SetIRQHandler(0, IRQCallback, 0); + YM3812SetTimerHandler(0, &BurnOPLTimerCallbackYM3812, 0); + YM3812SetUpdateHandler(0, &BurnYM3812UpdateRequest, 0); + + pBuffer = (INT16*)malloc(4096 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * sizeof(INT16)); + + nYM3812Position = 0; + + nFractionalPosition = 0; + + bYM3812AddSignal = bAddSignal; + + return 0; +} + +void BurnYM3812Scan(INT32 nAction, INT32* pnMin) +{ + BurnTimerScanYM3812(nAction, pnMin); + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nYM3812Position); + } +} diff --git a/src/burn/sound/burn_ym3812.h b/src/burn/sound/burn_ym3812.h new file mode 100644 index 00000000..dd0b4c90 --- /dev/null +++ b/src/burn/sound/burn_ym3812.h @@ -0,0 +1,28 @@ +#include "driver.h" +extern "C" { + #include "fmopl.h" +} +#include "timer.h" + +INT32 BurnTimerUpdateYM3812(INT32 nCycles); +void BurnTimerEndFrameYM3812(INT32 nCycles); +void BurnTimerUpdateEndYM3812(); +INT32 BurnTimerAttachSekYM3812(INT32 nClockspeed); +INT32 BurnTimerAttachZetYM3812(INT32 nClockspeed); +INT32 BurnTimerAttachM6809YM3812(INT32 nClockspeed); +INT32 BurnTimerAttachHD6309YM3812(INT32 nClockspeed); +INT32 BurnTimerAttachM6800YM3812(INT32 nClockspeed); +INT32 BurnTimerAttachHD63701YM3812(INT32 nClockspeed); +INT32 BurnTimerAttachM6803YM3812(INT32 nClockspeed); +INT32 BurnTimerAttachM6502YM3812(INT32 nClockspeed); + +extern "C" void BurnYM3812UpdateRequest(); + +INT32 BurnYM3812Init(INT32 nClockFrequency, OPL_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), INT32 bAddSignal); +void BurnYM3812Reset(); +void BurnYM3812Exit(); +extern void (*BurnYM3812Update)(INT16* pSoundBuf, INT32 nSegmentEnd); +void BurnYM3812Scan(INT32 nAction, INT32* pnMin); + +#define BurnYM3812Write(a, n) YM3812Write(0, a, n) +#define BurnYM3812Read(a) YM3812Read(0, a) diff --git a/src/burn/sound/burn_ymf278b.cpp b/src/burn/sound/burn_ymf278b.cpp new file mode 100644 index 00000000..25c03647 --- /dev/null +++ b/src/burn/sound/burn_ymf278b.cpp @@ -0,0 +1,182 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "burn_ymf278b.h" + +static INT32 (*BurnYMF278BStreamCallback)(INT32 nSoundRate); + +static INT16* pBuffer; +static INT16* pYMF278BBuffer[2]; + +static INT32 nYMF278BPosition; +static INT32 nFractionalPosition; + +// ---------------------------------------------------------------------------- +// Dummy functions + +static INT32 YMF278BStreamCallbackDummy(INT32 /* nSoundRate */) +{ + return 0; +} + + +// ---------------------------------------------------------------------------- +// Execute YMF278B for part of a frame + +static void YMF278BRender(INT32 nSegmentLength) +{ + if (nYMF278BPosition >= nSegmentLength) { + return; + } + +// bprintf(PRINT_NORMAL, _T(" YMF278B render %6i -> %6i\n"), nYMF278BPosition, nSegmentLength); + + nSegmentLength -= nYMF278BPosition; + + pYMF278BBuffer[0] = pBuffer + 0 * 4096 + 4 + nYMF278BPosition; + pYMF278BBuffer[1] = pBuffer + 1 * 4096 + 4 + nYMF278BPosition; + + ymf278b_pcm_update(0, pYMF278BBuffer, nSegmentLength); + + nYMF278BPosition += nSegmentLength; +} + +// ---------------------------------------------------------------------------- +// Update the sound buffer + +void BurnYMF278BUpdate(INT32 nSegmentEnd) +{ + INT16* pSoundBuf = pBurnSoundOut; + INT32 nSegmentLength = nSegmentEnd; + +// bprintf(PRINT_NORMAL, _T(" YMF278B render %6i -> %6i\n"), nYMF278BPosition, nSegmentEnd); + + if (nBurnSoundRate == 0) { + return; + } + + if (nSegmentEnd < nYMF278BPosition) { + nSegmentEnd = nYMF278BPosition; + } + + if (nSegmentLength > nBurnSoundLen) { + nSegmentLength = nBurnSoundLen; + } + + YMF278BRender(nSegmentEnd); + + pYMF278BBuffer[0] = pBuffer + 0 * 4096 + 4; + pYMF278BBuffer[1] = pBuffer + 1 * 4096 + 4; + + for (INT32 i = nFractionalPosition; i < nSegmentLength; i++) { + pSoundBuf[(i << 1) + 0] = pYMF278BBuffer[0][i]; + pSoundBuf[(i << 1) + 1] = pYMF278BBuffer[1][i]; + } + + nFractionalPosition = nSegmentLength; + + if (nSegmentEnd >= nBurnSoundLen) { + INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen; + + for (INT32 i = 0; i < nExtraSamples; i++) { + pYMF278BBuffer[0][i] = pYMF278BBuffer[0][nBurnSoundLen + i]; + pYMF278BBuffer[1][i] = pYMF278BBuffer[1][nBurnSoundLen + i]; + } + + nFractionalPosition = 0; + + nYMF278BPosition = nExtraSamples; + + } +} + +// ---------------------------------------------------------------------------- + +void BurnYMF278BSelectRegister(INT32 nRegister, UINT8 nValue) +{ + switch (nRegister) { + case 0: +// bprintf(PRINT_NORMAL, _T(" YMF278B register A -> %i\n"), nValue); + YMF278B_control_port_0_A_w(nValue); + break; + case 1: + YMF278B_control_port_0_B_w(nValue); + break; + case 2: +// bprintf(PRINT_NORMAL, _T(" YMF278B register C -> %i\n"), nValue); + YMF278B_control_port_0_C_w(nValue); + break; + } +} +void BurnYMF278BWriteRegister(INT32 nRegister, UINT8 nValue) +{ + switch (nRegister) { + case 0: + BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate)); + YMF278B_data_port_0_A_w(nValue); + break; + case 1: + YMF278B_data_port_0_B_w(nValue); + break; + case 2: + BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate)); + YMF278B_data_port_0_C_w(nValue); + break; + } +} + +UINT8 BurnYMF278BReadStatus() +{ + BurnYMF278BUpdate(BurnYMF278BStreamCallback(nBurnSoundRate)); + return YMF278B_status_port_0_r(); +} + +UINT8 BurnYMF278BReadData() +{ + return YMF278B_data_port_0_r(); +} + +// ---------------------------------------------------------------------------- + +void BurnYMF278BReset() +{ + BurnTimerReset(); +} + +void BurnYMF278BExit() +{ + YMF278B_sh_stop(); + + BurnTimerExit(); + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } +} + +INT32 BurnYMF278BInit(INT32 /* nClockFrequency */, UINT8* YMF278BROM, void (*IRQCallback)(INT32, INT32), INT32 (*StreamCallback)(INT32)) +{ + BurnYMF278BExit(); + + BurnYMF278BStreamCallback = YMF278BStreamCallbackDummy; + if (StreamCallback) { + BurnYMF278BStreamCallback = StreamCallback; + } + + ymf278b_start(0, YMF278BROM, IRQCallback, BurnYMFTimerCallback, YMF278B_STD_CLOCK, nBurnSoundRate); + BurnTimerInit(ymf278b_timer_over, NULL); + + pBuffer = (INT16*)malloc(4096 * 2 * sizeof(INT16)); + memset(pBuffer, 0, 4096 * 2 * sizeof(INT16)); + + nYMF278BPosition = 0; + + nFractionalPosition = 0; + + return 0; +} + +void BurnYMF278BScan(int nAction, int* pnMin) +{ + BurnTimerScan(nAction, pnMin); +} diff --git a/src/burn/sound/burn_ymf278b.h b/src/burn/sound/burn_ymf278b.h new file mode 100644 index 00000000..17638efc --- /dev/null +++ b/src/burn/sound/burn_ymf278b.h @@ -0,0 +1,19 @@ +#include "driver.h" +extern "C" { + #include "ymf278b.h" +} + +#include "timer.h" + +void BurnYMF278BSelectRegister(INT32 nRegister, UINT8 nValue); +void BurnYMF278BWriteRegister(INT32 nRegister, UINT8 nValue); +UINT8 BurnYMF278BReadStatus(); +UINT8 BurnYMF278BReadData(); + +INT32 BurnYMF278BInit(INT32 nClockFrequency, UINT8* YMF278BROM, void (*IRQCallback)(INT32, INT32), INT32 (*StreamCallback)(INT32)); +void BurnYMF278BReset(); +void BurnYMF278BExit(); +void BurnYMF278BUpdate(INT32 nSegmentEnd); +void BurnYMF278BScan(INT32 nAction, INT32* pnMin); + + diff --git a/src/burn/sound/dac.cpp b/src/burn/sound/dac.cpp new file mode 100644 index 00000000..657d11bb --- /dev/null +++ b/src/burn/sound/dac.cpp @@ -0,0 +1,350 @@ +#include "burnint.h" +#include "burn_sound.h" + +#define DEFAULT_SAMPLE_RATE (48000 * 4) + +struct dac_info +{ + INT16 Output; + INT16 UnsignedVolTable[256]; + INT16 SignedVolTable[256]; + UINT32 Delta; + INT32 nVolShift; +}; + +static INT32 NumChips; +static struct dac_info *Chip0 = NULL; +static struct dac_info *Chip1 = NULL; +static struct dac_info *Chip2 = NULL; +static struct dac_info *Chip3 = NULL; +static struct dac_info *Chip4 = NULL; +static struct dac_info *Chip5 = NULL; +static struct dac_info *Chip6 = NULL; +static struct dac_info *Chip7 = NULL; + +static INT32 bAddSignal; + +void DACUpdate(INT16* Buffer, INT32 Length) +{ + INT32 Out = Chip0->Output; + + if (NumChips >= 2) Out += Chip1->Output; + if (NumChips >= 3) Out += Chip2->Output; + if (NumChips >= 4) Out += Chip3->Output; + if (NumChips >= 5) Out += Chip4->Output; + if (NumChips >= 6) Out += Chip5->Output; + if (NumChips >= 7) Out += Chip6->Output; + if (NumChips >= 8) Out += Chip7->Output; + + Out = BURN_SND_CLIP(Out); + + while (Length--) { + if (bAddSignal) { + Buffer[0] += Out; + Buffer[1] += Out; + } else { + Buffer[0] = Out; + Buffer[1] = Out; + } + Buffer += 2; + } +} + +void DACWrite(INT32 Chip, UINT8 Data) +{ + if (Chip == 0) Chip0->Output = Chip0->UnsignedVolTable[Data] >> Chip0->nVolShift; + if (Chip == 1) Chip1->Output = Chip1->UnsignedVolTable[Data] >> Chip1->nVolShift; + if (Chip == 2) Chip2->Output = Chip2->UnsignedVolTable[Data] >> Chip2->nVolShift; + if (Chip == 3) Chip3->Output = Chip3->UnsignedVolTable[Data] >> Chip3->nVolShift; + if (Chip == 4) Chip4->Output = Chip4->UnsignedVolTable[Data] >> Chip4->nVolShift; + if (Chip == 5) Chip5->Output = Chip5->UnsignedVolTable[Data] >> Chip5->nVolShift; + if (Chip == 6) Chip6->Output = Chip6->UnsignedVolTable[Data] >> Chip6->nVolShift; + if (Chip == 7) Chip7->Output = Chip7->UnsignedVolTable[Data] >> Chip7->nVolShift; +} + +void DACSignedWrite(INT32 Chip, UINT8 Data) +{ + if (Chip == 0) Chip0->Output = Chip0->SignedVolTable[Data] >> Chip0->nVolShift; + if (Chip == 1) Chip1->Output = Chip1->SignedVolTable[Data] >> Chip1->nVolShift; + if (Chip == 2) Chip2->Output = Chip2->SignedVolTable[Data] >> Chip2->nVolShift; + if (Chip == 3) Chip3->Output = Chip3->SignedVolTable[Data] >> Chip3->nVolShift; + if (Chip == 4) Chip4->Output = Chip4->SignedVolTable[Data] >> Chip4->nVolShift; + if (Chip == 5) Chip5->Output = Chip5->SignedVolTable[Data] >> Chip5->nVolShift; + if (Chip == 6) Chip6->Output = Chip6->SignedVolTable[Data] >> Chip6->nVolShift; + if (Chip == 7) Chip7->Output = Chip7->SignedVolTable[Data] >> Chip7->nVolShift; +} + +static void DACBuildVolTables() +{ + INT32 i; + + for (i = 0;i < 256;i++) { + Chip0->UnsignedVolTable[i] = i * 0x101 / 2; + Chip0->SignedVolTable[i] = i * 0x101 - 0x8000; + + if (NumChips >= 2) { + Chip1->UnsignedVolTable[i] = i * 0x101 / 2; + Chip1->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 3) { + Chip2->UnsignedVolTable[i] = i * 0x101 / 2; + Chip2->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 4) { + Chip3->UnsignedVolTable[i] = i * 0x101 / 2; + Chip3->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 5) { + Chip4->UnsignedVolTable[i] = i * 0x101 / 2; + Chip4->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 6) { + Chip5->UnsignedVolTable[i] = i * 0x101 / 2; + Chip5->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 7) { + Chip6->UnsignedVolTable[i] = i * 0x101 / 2; + Chip6->SignedVolTable[i] = i * 0x101 - 0x8000; + } + + if (NumChips >= 8) { + Chip7->UnsignedVolTable[i] = i * 0x101 / 2; + Chip7->SignedVolTable[i] = i * 0x101 - 0x8000; + } + } +} + +void DACInit(INT32 Num, UINT32 Clock, INT32 bAdd) +{ + NumChips = Num; + + if (Num == 0) { + Chip0 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip0, 0, sizeof(Chip0)); + Chip0->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip0->Output = 0; + Chip0->nVolShift = 0; + } + + if (Num == 1) { + Chip1 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip1, 0, sizeof(Chip1)); + Chip1->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip1->Output = 0; + Chip1->nVolShift = 0; + } + + if (Num == 2) { + Chip2 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip2, 0, sizeof(Chip2)); + Chip2->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip2->Output = 0; + Chip2->nVolShift = 0; + } + + if (Num == 3) { + Chip3 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip3, 0, sizeof(Chip3)); + Chip3->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip3->Output = 0; + Chip3->nVolShift = 0; + } + + if (Num == 4) { + Chip4 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip4, 0, sizeof(Chip4)); + Chip4->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip4->Output = 0; + Chip4->nVolShift = 0; + } + + if (Num == 5) { + Chip5 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip5, 0, sizeof(Chip5)); + Chip5->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip5->Output = 0; + Chip5->nVolShift = 0; + } + + if (Num == 6) { + Chip6 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip6, 0, sizeof(Chip6)); + Chip6->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip6->Output = 0; + Chip6->nVolShift = 0; + } + + if (Num == 7) { + Chip7 = (struct dac_info*)malloc(sizeof(struct dac_info)); + memset(Chip7, 0, sizeof(Chip7)); + Chip7->Delta = (Clock) ? Clock : DEFAULT_SAMPLE_RATE; + Chip7->Output = 0; + Chip7->nVolShift = 0; + } + + DACBuildVolTables(); + + bAddSignal = bAdd; +} + +void DACSetVolShift(INT32 Chip, INT32 nShift) +{ + if (Chip == 0) Chip0->nVolShift = nShift; + if (Chip == 1) Chip1->nVolShift = nShift; + if (Chip == 2) Chip2->nVolShift = nShift; + if (Chip == 3) Chip3->nVolShift = nShift; + if (Chip == 4) Chip4->nVolShift = nShift; + if (Chip == 5) Chip5->nVolShift = nShift; + if (Chip == 6) Chip6->nVolShift = nShift; + if (Chip == 7) Chip7->nVolShift = nShift; +} + +void DACReset() +{ + Chip0->Output = 0; + if (NumChips >= 2) Chip1->Output = 0; + if (NumChips >= 3) Chip2->Output = 0; + if (NumChips >= 4) Chip3->Output = 0; + if (NumChips >= 5) Chip4->Output = 0; + if (NumChips >= 6) Chip5->Output = 0; + if (NumChips >= 7) Chip6->Output = 0; + if (NumChips >= 8) Chip7->Output = 0; +} + +void DACExit() +{ + if (Chip0) { + free(Chip0); + Chip0 = NULL; + } + + if (Chip1) { + free(Chip1); + Chip1 = NULL; + } + + if (Chip2) { + free(Chip2); + Chip2 = NULL; + } + + if (Chip3) { + free(Chip3); + Chip3 = NULL; + } + + if (Chip4) { + free(Chip4); + Chip4 = NULL; + } + + if (Chip5) { + free(Chip5); + Chip5 = NULL; + } + + if (Chip6) { + free(Chip6); + Chip6 = NULL; + } + + if (Chip7) { + free(Chip7); + Chip7 = NULL; + } + + NumChips = 0; +} + +INT32 DACScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029678; + } + + sprintf(szName, "DAC #0"); + ba.Data = &Chip0; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + if (NumChips >= 2) { + sprintf(szName, "DAC #1"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 3) { + sprintf(szName, "DAC #2"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 4) { + sprintf(szName, "DAC #3"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 5) { + sprintf(szName, "DAC #4"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 6) { + sprintf(szName, "DAC #5"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 7) { + sprintf(szName, "DAC #6"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 8) { + sprintf(szName, "DAC #7"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct dac_info); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + return 0; +} + +#undef DEFAULT_SAMPLE_RATE diff --git a/src/burn/sound/dac.h b/src/burn/sound/dac.h new file mode 100644 index 00000000..86d2a1bc --- /dev/null +++ b/src/burn/sound/dac.h @@ -0,0 +1,8 @@ +void DACUpdate(INT16* Buffer, INT32 Length); +void DACWrite(INT32 Chip, UINT8 Data); +void DACSignedWrite(INT32 Chip, UINT8 Data); +void DACInit(INT32 Num, UINT32 Clock, INT32 bAdd); +void DACSetVolShift(INT32 Num, INT32 nShift); +void DACReset(); +void DACExit(); +INT32 DACScan(INT32 nAction,INT32 *pnMin); diff --git a/src/burn/sound/es5506.cpp b/src/burn/sound/es5506.cpp new file mode 100644 index 00000000..56cf3ea0 --- /dev/null +++ b/src/burn/sound/es5506.cpp @@ -0,0 +1,2267 @@ +/********************************************************************************************** + + Ensoniq ES5505/6 driver + by Aaron Giles + +Ensoniq OTIS - ES5505 Ensoniq OTTO - ES5506 + + OTIS is a VLSI device designed in a 2 micron double metal OTTO is a VLSI device designed in a 1.5 micron double metal + CMOS process. The device is the next generation of audio CMOS process. The device is the next generation of audio + technology from ENSONIQ. This new chip achieves a new technology from ENSONIQ. All calculations in the device are + level of audio fidelity performance. These improvements made with at least 18-bit accuracy. + are achieved through the use of frequency interpolation + and on board real time digital filters. All calculations The major features of OTTO are: + in the device are made with at least 16 bit accuracy. - 68 pin PLCC package + - On chip real time digital filters + The major features of OTIS are: - Frequency interpolation + - 48 Pin dual in line package - 32 independent voices + - On chip real time digital filters - Loop start and stop posistions for each voice + - Frequency interpolation - Bidirectional and reverse looping + - 32 independent voices (up from 25 in DOCII) - 68000 compatibility for asynchronous bus communication + - Loop start and stop positions for each voice - Seperate host and sound memory interface + - Bidirectional and reverse looping - 6 channel stereo serial communication port + - 68000 compatibility for asynchronous bus communication - Programmable clocks for defining serial protocol + - On board pulse width modulation D to A - Internal volume multiplication and stereo panning + - 4 channel stereo serial communication port - A to D input for pots and wheels + - Internal volume multiplication and stereo panning - Hardware support for envelopes + - A to D input for pots and wheels - Support for dual OTTO systems + - Up to 10MHz operation - Optional compressed data format for sample data + - Up to 16MHz operation + ______ ______ + _|o \__/ |_ + A17/D13 - |_|1 48|_| - VSS A A A A A A + _| |_ 2 1 1 1 1 1 A + A18/D14 - |_|2 47|_| - A16/D12 0 9 8 7 6 5 1 + _| |_ / / / / / / 4 + A19/D15 - |_|3 46|_| - A15/D11 H H H H H H H V V H D D D D D D / + _| |_ D D D D D D D S D D 1 1 1 1 1 1 D + BS - |_|4 45|_| - A14/D10 0 1 2 3 4 5 6 S D 7 5 4 3 2 1 0 9 + _| |_ ------------------------------------+ + PWZERO - |_|5 44|_| - A13/D9 / 9 8 7 6 5 4 3 2 1 6 6 6 6 6 6 6 6 | + _| |_ / 8 7 6 5 4 3 2 1 | + SER0 - |_|6 43|_| - A12/D8 | | + _| E |_ SER0|10 60|A13/D8 + SER1 - |_|7 N 42|_| - A11/D7 SER1|11 59|A12/D7 + _| S |_ SER2|12 58|A11/D6 + SER2 - |_|8 O 41|_| - A10/D6 SER3|13 ENSONIQ 57|A10/D5 + _| N |_ SER4|14 56|A9/D4 + SER3 - |_|9 I 40|_| - A9/D5 SER5|15 55|A8/D3 + _| Q |_ WCLK|16 54|A7/D2 + SERWCLK - |_|10 39|_| - A8/D4 LRCLK|17 ES5506 53|A6/D1 + _| |_ BCLK|18 52|A5/D0 + SERLR - |_|11 38|_| - A7/D3 RESB|19 51|A4 + _| |_ HA5|20 50|A3 + SERBCLK - |_|12 E 37|_| - A6/D2 HA4|21 OTTO 49|A2 + _| S |_ HA3|22 48|A1 + RLO - |_|13 5 36|_| - A5/D1 HA2|23 47|A0 + _| 5 |_ HA1|24 46|BS1 + RHI - |_|14 0 35|_| - A4/D0 HA0|25 45|BS0 + _| 5 |_ POT_IN|26 44|DTACKB + LLO - |_|15 34|_| - CLKIN | 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 | + _| |_ | 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 | + LHI - |_|16 33|_| - CAS +--------------------------------------+ + _| |_ B E E B E B B D S B B B E K B W W + POT - |_|17 O 32|_| - AMUX S B L N L S S D S S X S L Q / / + _| T |_ E E R E H M C V V A U A C R R R + DTACK - |_|18 I 31|_| - RAS R R D H R M C I M + _| S |_ _ D A + R/W - |_|19 30|_| - E T + _| |_ O + MS - |_|20 29|_| - IRQ P + _| |_ + CS - |_|21 28|_| - A3 + _| |_ + RES - |_|22 27|_| - A2 + _| |_ + VSS - |_|23 26|_| - A1 + _| |_ + VDD - |_|24 25|_| - A0 + |________________| + +***********************************************************************************************/ + +//#include "emu.h" +#include "burnint.h" +#include "es5506.h" + + + +/********************************************************************************************** + + CONSTANTS + +***********************************************************************************************/ + +#define LOG_COMMANDS 0 +#define RAINE_CHECK 0 +#define MAKE_WAVS 0 + +#if MAKE_WAVS +#include "wavwrite.h" +#endif + +#define ES5506_INLINE static +#define ES5506 1 +#define ES5505 2 + +#define MAX_SAMPLE_CHUNK 10000 +#define ULAW_MAXBITS 8 + +#define CONTROL_BS1 0x8000 +#define CONTROL_BS0 0x4000 +#define CONTROL_CMPD 0x2000 +#define CONTROL_CA2 0x1000 +#define CONTROL_CA1 0x0800 +#define CONTROL_CA0 0x0400 +#define CONTROL_LP4 0x0200 +#define CONTROL_LP3 0x0100 +#define CONTROL_IRQ 0x0080 +#define CONTROL_DIR 0x0040 +#define CONTROL_IRQE 0x0020 +#define CONTROL_BLE 0x0010 +#define CONTROL_LPE 0x0008 +#define CONTROL_LEI 0x0004 +#define CONTROL_STOP1 0x0002 +#define CONTROL_STOP0 0x0001 + +#define CONTROL_BSMASK (CONTROL_BS1 | CONTROL_BS0) +#define CONTROL_CAMASK (CONTROL_CA2 | CONTROL_CA1 | CONTROL_CA0) +#define CONTROL_LPMASK (CONTROL_LP4 | CONTROL_LP3) +#define CONTROL_LOOPMASK (CONTROL_BLE | CONTROL_LPE) +#define CONTROL_STOPMASK (CONTROL_STOP1 | CONTROL_STOP0) + + + +/********************************************************************************************** + + INTERNAL DATA STRUCTURES + +***********************************************************************************************/ + +/* struct describing a single playing voice */ +typedef struct _es5506_voice es5506_voice; +struct _es5506_voice +{ + /* external state */ + UINT32 control; /* control register */ + UINT32 freqcount; /* frequency count register */ + UINT32 start; /* start register */ + UINT32 lvol; /* left volume register */ + UINT32 end; /* end register */ + UINT32 lvramp; /* left volume ramp register */ + UINT32 accum; /* accumulator register */ + UINT32 rvol; /* right volume register */ + UINT32 rvramp; /* right volume ramp register */ + UINT32 ecount; /* envelope count register */ + UINT32 k2; /* k2 register */ + UINT32 k2ramp; /* k2 ramp register */ + UINT32 k1; /* k1 register */ + UINT32 k1ramp; /* k1 ramp register */ + INT32 o4n1; /* filter storage O4(n-1) */ + INT32 o3n1; /* filter storage O3(n-1) */ + INT32 o3n2; /* filter storage O3(n-2) */ + INT32 o2n1; /* filter storage O2(n-1) */ + INT32 o2n2; /* filter storage O2(n-2) */ + INT32 o1n1; /* filter storage O1(n-1) */ + UINT32 exbank; /* external address bank */ + + /* internal state */ + UINT8 index; /* index of this voice */ + UINT8 filtcount; /* filter count */ + UINT32 accum_mask; +}; + +//typedef struct _es5506_state es5506_state; +struct _es5506_state +{ +// sound_stream *stream; /* which stream are we using */ + INT32 sample_rate; /* current sample rate */ + UINT16 * region_base[4]; /* pointer to the base of the region */ + UINT32 write_latch; /* currently accumulated data for write */ + UINT32 read_latch; /* currently accumulated data for read */ + UINT32 master_clock; /* master clock frequency */ + void (*irq_callback)(INT32); /* IRQ callback */ + UINT16 (*port_read)(void); /* input port read */ + + UINT8 current_page; /* current register page */ + UINT8 active_voices; /* number of active voices */ + UINT8 mode; /* MODE register */ + UINT8 wst; /* W_ST register */ + UINT8 wend; /* W_END register */ + UINT8 lrend; /* LR_END register */ + UINT8 irqv; /* IRQV register */ + + es5506_voice voice[32]; /* the 32 voices */ + + INT32 * scratch; + + INT16 * ulaw_lookup; + UINT16 * volume_lookup; +// device_t *device; + +#if MAKE_WAVS + void * wavraw; /* raw waveform */ +#endif +}; + +static struct _es5506_state *chip = NULL; + + +/********************************************************************************************** + + GLOBAL VARIABLES + +***********************************************************************************************/ + +static FILE *eslog; + + + +/********************************************************************************************** + + update_irq_state -- update the IRQ state + +***********************************************************************************************/ + +static void update_irq_state() +{ + /* ES5505/6 irq line has been set high - inform the host */ + if (chip->irq_callback) + (*chip->irq_callback)(1); /* IRQB set high */ +} + +static void update_internal_irq_state() +{ + /* Host (cpu) has just read the voice interrupt vector (voice IRQ ack). + + Reset the voice vector to show the IRQB line is low (top bit set). + If we have any stacked interrupts (other voices waiting to be + processed - with their IRQ bit set) then they will be moved into + the vector next time the voice is processed. In emulation + terms they get updated next time generate_samples() is called. + */ + + chip->irqv=0x80; + if (chip->irq_callback) + (*chip->irq_callback)(0); /* IRQB set low */ +} + +/********************************************************************************************** + + compute_tables -- compute static tables + +***********************************************************************************************/ + +static void compute_tables() +{ + INT32 i; + + /* allocate ulaw lookup table */ + //chip->ulaw_lookup = auto_alloc_array(chip->device->machine, INT16, 1 << ULAW_MAXBITS); + chip->ulaw_lookup = (INT16*)malloc((1 << ULAW_MAXBITS) * sizeof(INT16)); + + /* generate ulaw lookup table */ + for (i = 0; i < (1 << ULAW_MAXBITS); i++) + { + UINT16 rawval = (i << (16 - ULAW_MAXBITS)) | (1 << (15 - ULAW_MAXBITS)); + UINT8 exponent = rawval >> 13; + UINT32 mantissa = (rawval << 3) & 0xffff; + + if (exponent == 0) + chip->ulaw_lookup[i] = (INT16)mantissa >> 7; + else + { + mantissa = (mantissa >> 1) | (~mantissa & 0x8000); + chip->ulaw_lookup[i] = (INT16)mantissa >> (7 - exponent); + } + } + + /* allocate volume lookup table */ + //chip->volume_lookup = auto_alloc_array(chip->device->machine, UINT16, 4096); + chip->volume_lookup = (UINT16*)malloc(4096 * sizeof(UINT16)); + + /* generate volume lookup table */ + for (i = 0; i < 4096; i++) + { + UINT8 exponent = i >> 8; + UINT32 mantissa = (i & 0xff) | 0x100; + + chip->volume_lookup[i] = (mantissa << 11) >> (20 - exponent); + } +} + + + +/********************************************************************************************** + + interpolate -- interpolate between two samples + +***********************************************************************************************/ + +#define interpolate(sample1, sample2, accum) \ + (sample1 * (INT32)(0x800 - (accum & 0x7ff)) + \ + sample2 * (INT32)(accum & 0x7ff)) >> 11; + + + +/********************************************************************************************** + + apply_filters -- apply the 4-pole digital filter to the sample + +***********************************************************************************************/ + +#define apply_filters(voice, sample) \ +do \ +{ \ + /* pole 1 is always low-pass using K1 */ \ + sample = ((INT32)(voice->k1 >> 2) * (sample - voice->o1n1) / 16384) + voice->o1n1; \ + voice->o1n1 = sample; \ + \ + /* pole 2 is always low-pass using K1 */ \ + sample = ((INT32)(voice->k1 >> 2) * (sample - voice->o2n1) / 16384) + voice->o2n1; \ + voice->o2n2 = voice->o2n1; \ + voice->o2n1 = sample; \ + \ + /* remaining poles depend on the current filter setting */ \ + switch (voice->control & CONTROL_LPMASK) \ + { \ + case 0: \ + /* pole 3 is high-pass using K2 */ \ + sample = sample - voice->o2n2 + ((INT32)(voice->k2 >> 2) * voice->o3n1) / 32768 + voice->o3n1 / 2; \ + voice->o3n2 = voice->o3n1; \ + voice->o3n1 = sample; \ + \ + /* pole 4 is high-pass using K2 */ \ + sample = sample - voice->o3n2 + ((INT32)(voice->k2 >> 2) * voice->o4n1) / 32768 + voice->o4n1 / 2; \ + voice->o4n1 = sample; \ + break; \ + \ + case CONTROL_LP3: \ + /* pole 3 is low-pass using K1 */ \ + sample = ((INT32)(voice->k1 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1; \ + voice->o3n2 = voice->o3n1; \ + voice->o3n1 = sample; \ + \ + /* pole 4 is high-pass using K2 */ \ + sample = sample - voice->o3n2 + ((INT32)(voice->k2 >> 2) * voice->o4n1) / 32768 + voice->o4n1 / 2; \ + voice->o4n1 = sample; \ + break; \ + \ + case CONTROL_LP4: \ + /* pole 3 is low-pass using K2 */ \ + sample = ((INT32)(voice->k2 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1; \ + voice->o3n2 = voice->o3n1; \ + voice->o3n1 = sample; \ + \ + /* pole 4 is low-pass using K2 */ \ + sample = ((INT32)(voice->k2 >> 2) * (sample - voice->o4n1) / 16384) + voice->o4n1; \ + voice->o4n1 = sample; \ + break; \ + \ + case CONTROL_LP4 | CONTROL_LP3: \ + /* pole 3 is low-pass using K1 */ \ + sample = ((INT32)(voice->k1 >> 2) * (sample - voice->o3n1) / 16384) + voice->o3n1; \ + voice->o3n2 = voice->o3n1; \ + voice->o3n1 = sample; \ + \ + /* pole 4 is low-pass using K2 */ \ + sample = ((INT32)(voice->k2 >> 2) * (sample - voice->o4n1) / 16384) + voice->o4n1; \ + voice->o4n1 = sample; \ + break; \ + } \ +} while (0) + + + +/********************************************************************************************** + + update_envelopes -- update the envelopes + +***********************************************************************************************/ + +#define update_envelopes(voice, samples) \ +do \ +{ \ + INT32 count = (samples > 1 && samples > (INT32)voice->ecount) ? voice->ecount : samples; \ + \ + /* decrement the envelope counter */ \ + voice->ecount -= count; \ + \ + /* ramp left volume */ \ + if (voice->lvramp) \ + { \ + voice->lvol += (INT8)voice->lvramp * count; \ + if ((INT32)voice->lvol < 0) voice->lvol = 0; \ + else if (voice->lvol > 0xffff) voice->lvol = 0xffff; \ + } \ + \ + /* ramp right volume */ \ + if (voice->rvramp) \ + { \ + voice->rvol += (INT8)voice->rvramp * count; \ + if ((INT32)voice->rvol < 0) voice->rvol = 0; \ + else if (voice->rvol > 0xffff) voice->rvol = 0xffff; \ + } \ + \ + /* ramp k1 filter constant */ \ + if (voice->k1ramp && ((INT32)voice->k1ramp >= 0 || !(voice->filtcount & 7))) \ + { \ + voice->k1 += (INT8)voice->k1ramp * count; \ + if ((INT32)voice->k1 < 0) voice->k1 = 0; \ + else if (voice->k1 > 0xffff) voice->k1 = 0xffff; \ + } \ + \ + /* ramp k2 filter constant */ \ + if (voice->k2ramp && ((INT32)voice->k2ramp >= 0 || !(voice->filtcount & 7))) \ + { \ + voice->k2 += (INT8)voice->k2ramp * count; \ + if ((INT32)voice->k2 < 0) voice->k2 = 0; \ + else if (voice->k2 > 0xffff) voice->k2 = 0xffff; \ + } \ + \ + /* update the filter constant counter */ \ + voice->filtcount += count; \ + \ +} while (0) + + + +/********************************************************************************************** + + check_for_end_forward + check_for_end_reverse -- check for loop end and loop appropriately + +***********************************************************************************************/ + +#define check_for_end_forward(voice, accum) \ +do \ +{ \ + /* are we past the end? */ \ + if (accum > voice->end && !(voice->control & CONTROL_LEI)) \ + { \ + /* generate interrupt if required */ \ + if (voice->control&CONTROL_IRQE) \ + voice->control |= CONTROL_IRQ; \ + \ + /* handle the different types of looping */ \ + switch (voice->control & CONTROL_LOOPMASK) \ + { \ + /* non-looping */ \ + case 0: \ + voice->control |= CONTROL_STOP0; \ + goto alldone; \ + \ + /* uni-directional looping */ \ + case CONTROL_LPE: \ + accum = (voice->start + (accum - voice->end)) & voice->accum_mask; \ + break; \ + \ + /* trans-wave looping */ \ + case CONTROL_BLE: \ + accum = (voice->start + (accum - voice->end)) & voice->accum_mask; \ + voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;\ + break; \ + \ + /* bi-directional looping */ \ + case CONTROL_LPE | CONTROL_BLE: \ + accum = (voice->end - (accum - voice->end)) & voice->accum_mask; \ + voice->control ^= CONTROL_DIR; \ + goto reverse; \ + } \ + } \ +} while (0) + + +#define check_for_end_reverse(voice, accum) \ +do \ +{ \ + /* are we past the end? */ \ + if (accum < voice->start && !(voice->control & CONTROL_LEI)) \ + { \ + /* generate interrupt if required */ \ + if (voice->control&CONTROL_IRQE) \ + voice->control |= CONTROL_IRQ; \ + \ + /* handle the different types of looping */ \ + switch (voice->control & CONTROL_LOOPMASK) \ + { \ + /* non-looping */ \ + case 0: \ + voice->control |= CONTROL_STOP0; \ + goto alldone; \ + \ + /* uni-directional looping */ \ + case CONTROL_LPE: \ + accum = (voice->end - (voice->start - accum)) & voice->accum_mask; \ + break; \ + \ + /* trans-wave looping */ \ + case CONTROL_BLE: \ + accum = (voice->end - (voice->start - accum)) & voice->accum_mask; \ + voice->control = (voice->control & ~CONTROL_LOOPMASK) | CONTROL_LEI;\ + break; \ + \ + /* bi-directional looping */ \ + case CONTROL_LPE | CONTROL_BLE: \ + accum = (voice->start + (voice->start - accum)) & voice->accum_mask;\ + voice->control ^= CONTROL_DIR; \ + goto reverse; \ + } \ + } \ +} while (0) + + + +/********************************************************************************************** + + generate_dummy -- generate nothing, just apply envelopes + +***********************************************************************************************/ + +static void generate_dummy(es5506_voice *voice, UINT16 */*base*/, INT32 */*lbuffer*/, INT32 */*rbuffer*/, INT32 samples) +{ + UINT32 freqcount = voice->freqcount; + UINT32 accum = voice->accum & voice->accum_mask; + + /* outer loop, in case we switch directions */ + while (samples > 0 && !(voice->control & CONTROL_STOPMASK)) + { +reverse: + /* two cases: first case is forward direction */ + if (!(voice->control & CONTROL_DIR)) + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + accum = (accum + freqcount) & voice->accum_mask; + + /* update filters/volumes */ + if (voice->ecount != 0) + update_envelopes(voice, 1); + + /* check for loop end */ + check_for_end_forward(voice, accum); + } + } + + /* two cases: second case is backward direction */ + else + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + accum = (accum - freqcount) & voice->accum_mask; + + /* update filters/volumes */ + if (voice->ecount != 0) + update_envelopes(voice, 1); + + /* check for loop end */ + check_for_end_reverse(voice, accum); + } + } + } + + /* if we stopped, process any additional envelope */ +alldone: + voice->accum = accum; + if (samples > 0) + update_envelopes(voice, samples); +} + + + +/********************************************************************************************** + + generate_ulaw -- general u-law decoding routine + +***********************************************************************************************/ + +static void generate_ulaw(es5506_voice *voice, UINT16 *base, INT32 *lbuffer, INT32 *rbuffer, INT32 samples) +{ + UINT32 freqcount = voice->freqcount; + UINT32 accum = voice->accum & voice->accum_mask; + INT32 lvol = chip->volume_lookup[voice->lvol >> 4]; + INT32 rvol = chip->volume_lookup[voice->rvol >> 4]; + + bprintf(PRINT_NORMAL, _T("ULAW\n")); + + /* pre-add the bank offset */ + base += voice->exbank; + + /* outer loop, in case we switch directions */ + while (samples > 0 && !(voice->control & CONTROL_STOPMASK)) + { +reverse: + /* two cases: first case is forward direction */ + if (!(voice->control & CONTROL_DIR)) + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + INT32 val1 = base[accum >> 11]; + INT32 val2 = base[((accum + (1 << 11)) & voice->accum_mask) >> 11]; + + /* decompress u-law */ + val1 = chip->ulaw_lookup[val1 >> (16 - ULAW_MAXBITS)]; + val2 = chip->ulaw_lookup[val2 >> (16 - ULAW_MAXBITS)]; + + /* interpolate */ + val1 = interpolate(val1, val2, accum); + accum = (accum + freqcount) & voice->accum_mask; + + /* apply filters */ + apply_filters(voice, val1); + + /* update filters/volumes */ + if (voice->ecount != 0) + { + update_envelopes(voice, 1); + lvol = chip->volume_lookup[voice->lvol >> 4]; + rvol = chip->volume_lookup[voice->rvol >> 4]; + } + + /* apply volumes and add */ + *lbuffer++ += (val1 * lvol) >> 11; + *rbuffer++ += (val1 * rvol) >> 11; + + /* check for loop end */ + check_for_end_forward(voice, accum); + } + } + + /* two cases: second case is backward direction */ + else + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + INT32 val1 = base[accum >> 11]; + INT32 val2 = base[((accum + (1 << 11)) & voice->accum_mask) >> 11]; + + /* decompress u-law */ + val1 = chip->ulaw_lookup[val1 >> (16 - ULAW_MAXBITS)]; + val2 = chip->ulaw_lookup[val2 >> (16 - ULAW_MAXBITS)]; + + /* interpolate */ + val1 = interpolate(val1, val2, accum); + accum = (accum - freqcount) & voice->accum_mask; + + /* apply filters */ + apply_filters(voice, val1); + + /* update filters/volumes */ + if (voice->ecount != 0) + { + update_envelopes(voice, 1); + lvol = chip->volume_lookup[voice->lvol >> 4]; + rvol = chip->volume_lookup[voice->rvol >> 4]; + } + + /* apply volumes and add */ + *lbuffer++ += (val1 * lvol) >> 11; + *rbuffer++ += (val1 * rvol) >> 11; + + /* check for loop end */ + check_for_end_reverse(voice, accum); + } + } + } + + /* if we stopped, process any additional envelope */ +alldone: + voice->accum = accum; + if (samples > 0) + update_envelopes(voice, samples); +} + + + +/********************************************************************************************** + + generate_pcm -- general PCM decoding routine + +***********************************************************************************************/ + +static void generate_pcm(es5506_voice *voice, UINT16 *base, INT32 *lbuffer, INT32 *rbuffer, INT32 samples) +{ + UINT32 freqcount = voice->freqcount; + UINT32 accum = voice->accum & voice->accum_mask; + INT32 lvol = chip->volume_lookup[voice->lvol >> 4]; + INT32 rvol = chip->volume_lookup[voice->rvol >> 4]; + +// bprintf(PRINT_NORMAL, _T("PCM, %x, %x, %x\n"), lvol, rvol, voice->control & CONTROL_STOPMASK); + + /* pre-add the bank offset */ + base += voice->exbank; + + /* outer loop, in case we switch directions */ + while (samples > 0 && !(voice->control & CONTROL_STOPMASK)) + { +reverse: + /* two cases: first case is forward direction */ + if (!(voice->control & CONTROL_DIR)) + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + INT32 val1 = (INT16)base[accum >> 11]; + INT32 val2 = (INT16)base[((accum + (1 << 11)) & voice->accum_mask) >> 11]; + + /* interpolate */ + val1 = interpolate(val1, val2, accum); + accum = (accum + freqcount) & voice->accum_mask; + + /* apply filters */ + apply_filters(voice, val1); + + /* update filters/volumes */ + if (voice->ecount != 0) + { + update_envelopes(voice, 1); + lvol = chip->volume_lookup[voice->lvol >> 4]; + rvol = chip->volume_lookup[voice->rvol >> 4]; + } + + /* apply volumes and add */ + *lbuffer++ += (val1 * lvol) >> 11; + *rbuffer++ += (val1 * rvol) >> 11; + + /* check for loop end */ + check_for_end_forward(voice, accum); + } + } + + /* two cases: second case is backward direction */ + else + { + /* loop while we still have samples to generate */ + while (samples--) + { + /* fetch two samples */ + INT32 val1 = (INT16)base[accum >> 11]; + INT32 val2 = (INT16)base[((accum + (1 << 11)) & voice->accum_mask) >> 11]; + + bprintf(PRINT_NORMAL, _T("%x, %x\n"), val1, val2); + + /* interpolate */ + val1 = interpolate(val1, val2, accum); + accum = (accum - freqcount) & voice->accum_mask; + + /* apply filters */ + apply_filters(voice, val1); + + /* update filters/volumes */ + if (voice->ecount != 0) + { + update_envelopes(voice, 1); + lvol = chip->volume_lookup[voice->lvol >> 4]; + rvol = chip->volume_lookup[voice->rvol >> 4]; + } + + /* apply volumes and add */ + *lbuffer++ += (val1 * lvol) >> 11; + *rbuffer++ += (val1 * rvol) >> 11; + + /* check for loop end */ + check_for_end_reverse(voice, accum); + } + } + } + + /* if we stopped, process any additional envelope */ +alldone: + voice->accum = accum; + if (samples > 0) + update_envelopes(voice, samples); +} + + + +/********************************************************************************************** + + generate_samples -- tell each voice to generate samples + +***********************************************************************************************/ + +static void generate_samples(INT32 *left, INT32 *right, INT32 samples) +{ + INT32 v; + + /* skip if nothing to do */ + if (!samples) + return; + + /* clear out the accumulator */ + memset(left, 0, samples * sizeof(left[0])); + memset(right, 0, samples * sizeof(right[0])); + + /* loop over voices */ + for (v = 0; v <= chip->active_voices; v++) + { + es5506_voice *voice = &chip->voice[v]; + UINT16 *base = chip->region_base[voice->control >> 14]; + + /* special case: if end == start, stop the voice */ + if (voice->start == voice->end) + voice->control |= CONTROL_STOP0; + + /* generate from the appropriate source */ + if (!base) + { +// logerror("NULL region base %d\n",voice->control >> 14); + generate_dummy(voice, base, left, right, samples); + } + else if (voice->control & 0x2000) + generate_ulaw(voice, base, left, right, samples); + else + generate_pcm(voice, base, left, right, samples); + + /* does this voice have it's IRQ bit raised? */ + if (voice->control&CONTROL_IRQ) + { +//logerror("IRQ raised on voice %d!!\n",v); + /* only update voice vector if existing IRQ is acked by host */ + if (chip->irqv&0x80) + { + /* latch voice number into vector, and set high bit low */ + chip->irqv=v&0x7f; + + /* take down IRQ bit on voice */ + voice->control&=~CONTROL_IRQ; + + /* inform host of irq */ + update_irq_state(); + } + } + } +} + + + +/********************************************************************************************** + + es5506_update -- update the sound chip so that it is in sync with CPU execution + +***********************************************************************************************/ + +//static STREAM_UPDATE( es5506_update ) +void ES5506Update(INT16 *pBuffer, INT32 samples) +{ +// es5506_state *chip = (es5506_state *)param; + INT32 *lsrc = chip->scratch, *rsrc = chip->scratch; +// short *ldest = &pBuffer[0]; +// short *rdest = &pBuffer[1]; + +#if MAKE_WAVS + /* start the logging once we have a sample rate */ + if (chip->sample_rate) + { + if (!chip->wavraw) + chip->wavraw = wav_open("raw.wav", chip->sample_rate, 2); + } +#endif + + /* loop until all samples are output */ + while (samples) + { + INT32 length = (samples > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : samples; + INT32 samp; + + /* determine left/right source data */ + lsrc = chip->scratch; + rsrc = chip->scratch + length; + generate_samples(lsrc, rsrc, length); + + /* copy the data */ + for (samp = 0; samp < length; samp++) + { +// *ldest++ = lsrc[samp] >> 4; +// *rdest++ = rsrc[samp] >> 4; + pBuffer[0] = lsrc[samp] >> 4; + pBuffer[1] = rsrc[samp] >> 4; + pBuffer += 2; +// bprintf(PRINT_NORMAL, _T("%x, %x\n"), lsrc[samp] >> 4, rsrc[samp] >> 4); + } + +#if MAKE_WAVS + /* log the raw data */ + if (chip->wavraw) + wav_add_data_32lr(chip->wavraw, lsrc, rsrc, length, 4); +#endif + + /* account for these samples */ + samples -= length; + } +} + + +/********************************************************************************************** + + DEVICE_START( es5506 ) -- start emulation of the ES5506 + +***********************************************************************************************/ + +static void es5506_start_common(INT32 clock, UINT8* region0, UINT8* region1, UINT8* region2, UINT8* region3, irq_callback callback, INT32 sndtype) +{ +// const es5506_interface *intf = (const es5506_interface *)config; +// es5506_state *chip = get_safe_token(device); + INT32 j; + UINT32 accum_mask; + + /* debugging */ + if (LOG_COMMANDS && !eslog) + eslog = fopen("es.log", "w"); + + /* create the stream */ +// chip->stream = device->machine->sound().stream_alloc(*device, 0, 2, device->clock() / (16*32), chip, es5506_update); + + chip = (struct _es5506_state*)malloc(sizeof(_es5506_state)); + memset(chip, 0, sizeof(_es5506_state)); + + /* initialize the regions */ + chip->region_base[0] = region0 ? (UINT16 *)region0 : NULL; + chip->region_base[1] = region1 ? (UINT16 *)region1 : NULL; + chip->region_base[2] = region2 ? (UINT16 *)region2 : NULL; + chip->region_base[3] = region3 ? (UINT16 *)region3 : NULL; + + /* initialize the rest of the structure */ + chip->master_clock = clock; + chip->irq_callback = callback; + chip->irqv = 0x80; + + /* compute the tables */ + compute_tables(); + + /* init the voices */ + accum_mask = (sndtype == ES5506) ? 0xffffffff : 0x7fffffff; + for (j = 0; j < 32; j++) + { + chip->voice[j].index = j; + chip->voice[j].control = CONTROL_STOPMASK; + chip->voice[j].lvol = 0xffff; + chip->voice[j].rvol = 0xffff; + chip->voice[j].exbank = 0; + chip->voice[j].accum_mask = accum_mask; + } + + /* allocate memory */ + chip->scratch = (INT32*)malloc(2 * MAX_SAMPLE_CHUNK * sizeof(INT32));//auto_alloc_array(device->machine, INT32, 2 * MAX_SAMPLE_CHUNK); + + /* register save */ +/* device->save_item(NAME(chip->sample_rate)); + device->save_item(NAME(chip->write_latch)); + device->save_item(NAME(chip->read_latch)); + + device->save_item(NAME(chip->current_page)); + device->save_item(NAME(chip->active_voices)); + device->save_item(NAME(chip->mode)); + device->save_item(NAME(chip->wst)); + device->save_item(NAME(chip->wend)); + device->save_item(NAME(chip->lrend)); + device->save_item(NAME(chip->irqv)); + + device->save_pointer(NAME(chip->scratch), 2 * MAX_SAMPLE_CHUNK); + + for (j = 0; j < 32; j++) + { + device->save_item(NAME(chip->voice[j].control), j); + device->save_item(NAME(chip->voice[j].freqcount), j); + device->save_item(NAME(chip->voice[j].start), j); + device->save_item(NAME(chip->voice[j].lvol), j); + device->save_item(NAME(chip->voice[j].end), j); + device->save_item(NAME(chip->voice[j].lvramp), j); + device->save_item(NAME(chip->voice[j].accum), j); + device->save_item(NAME(chip->voice[j].rvol), j); + device->save_item(NAME(chip->voice[j].rvramp), j); + device->save_item(NAME(chip->voice[j].ecount), j); + device->save_item(NAME(chip->voice[j].k2), j); + device->save_item(NAME(chip->voice[j].k2ramp), j); + device->save_item(NAME(chip->voice[j].k1), j); + device->save_item(NAME(chip->voice[j].k1ramp), j); + device->save_item(NAME(chip->voice[j].o4n1), j); + device->save_item(NAME(chip->voice[j].o3n1), j); + device->save_item(NAME(chip->voice[j].o3n2), j); + device->save_item(NAME(chip->voice[j].o2n1), j); + device->save_item(NAME(chip->voice[j].o2n2), j); + device->save_item(NAME(chip->voice[j].o1n1), j); + device->save_item(NAME(chip->voice[j].exbank), j); + device->save_item(NAME(chip->voice[j].filtcount), j); + }*/ + + /* success */ +} + + +/*static DEVICE_START( es5506 ) +{ + es5506_start_common(device, device->baseconfig().static_config(), ES5506); +}*/ + +void ES5506Init(INT32 clock, UINT8* region0, UINT8* region1, UINT8* region2, UINT8* region3, irq_callback callback) +{ + es5506_start_common(clock, region0, region1, region2, region3, callback, ES5506); +} + + + +/********************************************************************************************** + + DEVICE_STOP( es5506 ) -- stop emulation of the ES5506 + +***********************************************************************************************/ + +void ES5506Exit() +{ + /* debugging */ + if (LOG_COMMANDS && eslog) + { + fclose(eslog); + eslog = NULL; + } + +#if MAKE_WAVS +{ + INT32 i; + + for (i = 0; i < MAX_ES5506; i++) + { + if (es5506[i].wavraw) + wav_close(es5506[i].wavraw); + } +} +#endif +} + + +void ES5506Reset() +{ +} + + + +/********************************************************************************************** + + es5506_reg_write -- handle a write to the selected ES5506 register + +***********************************************************************************************/ + +ES5506_INLINE void es5506_reg_write_low(es5506_voice *voice, UINT32 offset, UINT32 data) +{ + switch (offset) + { + case 0x00/8: /* CR */ + voice->control = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, control=%04x\n", chip->current_page & 0x1f, voice->control); + break; + + case 0x08/8: /* FC */ + voice->freqcount = data & 0x1ffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, freq count=%08x\n", chip->current_page & 0x1f, voice->freqcount); + break; + + case 0x10/8: /* LVOL */ + voice->lvol = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, left vol=%04x\n", chip->current_page & 0x1f, voice->lvol); + break; + + case 0x18/8: /* LVRAMP */ + voice->lvramp = (data & 0xff00) >> 8; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, left vol ramp=%04x\n", chip->current_page & 0x1f, voice->lvramp); + break; + + case 0x20/8: /* RVOL */ + voice->rvol = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, right vol=%04x\n", chip->current_page & 0x1f, voice->rvol); + break; + + case 0x28/8: /* RVRAMP */ + voice->rvramp = (data & 0xff00) >> 8; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, right vol ramp=%04x\n", chip->current_page & 0x1f, voice->rvramp); + break; + + case 0x30/8: /* ECOUNT */ + voice->ecount = data & 0x1ff; + voice->filtcount = 0; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, envelope count=%04x\n", chip->current_page & 0x1f, voice->ecount); + break; + + case 0x38/8: /* K2 */ + voice->k2 = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, K2=%04x\n", chip->current_page & 0x1f, voice->k2); + break; + + case 0x40/8: /* K2RAMP */ + voice->k2ramp = ((data & 0xff00) >> 8) | ((data & 0x0001) << 31); + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, K2 ramp=%04x\n", chip->current_page & 0x1f, voice->k2ramp); + break; + + case 0x48/8: /* K1 */ + voice->k1 = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, K1=%04x\n", chip->current_page & 0x1f, voice->k1); + break; + + case 0x50/8: /* K1RAMP */ + voice->k1ramp = ((data & 0xff00) >> 8) | ((data & 0x0001) << 31); + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, K1 ramp=%04x\n", chip->current_page & 0x1f, voice->k1ramp); + break; + + case 0x58/8: /* ACTV */ + { + chip->active_voices = data & 0x1f; + chip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1)); +// chip->stream->set_sample_rate(chip->sample_rate); + + if (LOG_COMMANDS && eslog) + fprintf(eslog, "active voices=%d, sample_rate=%d\n", chip->active_voices, chip->sample_rate); + break; + } + + case 0x60/8: /* MODE */ + chip->mode = data & 0x1f; + break; + + case 0x68/8: /* PAR - read only */ + case 0x70/8: /* IRQV - read only */ + break; + + case 0x78/8: /* PAGE */ + chip->current_page = data & 0x7f; + break; + } +} + + +ES5506_INLINE void es5506_reg_write_high(es5506_voice *voice, UINT32 offset, UINT32 data) +{ + switch (offset) + { + case 0x00/8: /* CR */ + voice->control = data & 0xffff; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, control=%04x\n", chip->current_page & 0x1f, voice->control); + break; + + case 0x08/8: /* START */ + voice->start = data & 0xfffff800; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, loop start=%08x\n", chip->current_page & 0x1f, voice->start); + break; + + case 0x10/8: /* END */ + voice->end = data & 0xffffff80; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, loop end=%08x\n", chip->current_page & 0x1f, voice->end); + break; + + case 0x18/8: /* ACCUM */ + voice->accum = data; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, accum=%08x\n", chip->current_page & 0x1f, voice->accum); + break; + + case 0x20/8: /* O4(n-1) */ + voice->o4n1 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O4(n-1)=%05x\n", chip->current_page & 0x1f, voice->o4n1 & 0x3ffff); + break; + + case 0x28/8: /* O3(n-1) */ + voice->o3n1 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O3(n-1)=%05x\n", chip->current_page & 0x1f, voice->o3n1 & 0x3ffff); + break; + + case 0x30/8: /* O3(n-2) */ + voice->o3n2 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O3(n-2)=%05x\n", chip->current_page & 0x1f, voice->o3n2 & 0x3ffff); + break; + + case 0x38/8: /* O2(n-1) */ + voice->o2n1 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O2(n-1)=%05x\n", chip->current_page & 0x1f, voice->o2n1 & 0x3ffff); + break; + + case 0x40/8: /* O2(n-2) */ + voice->o2n2 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O2(n-2)=%05x\n", chip->current_page & 0x1f, voice->o2n2 & 0x3ffff); + break; + + case 0x48/8: /* O1(n-1) */ + voice->o1n1 = (INT32)(data << 14) >> 14; + if (LOG_COMMANDS && eslog) + fprintf(eslog, "voice %d, O1(n-1)=%05x\n", chip->current_page & 0x1f, voice->o1n1 & 0x3ffff); + break; + + case 0x50/8: /* W_ST */ + chip->wst = data & 0x7f; + break; + + case 0x58/8: /* W_END */ + chip->wend = data & 0x7f; + break; + + case 0x60/8: /* LR_END */ + chip->lrend = data & 0x7f; + break; + + case 0x68/8: /* PAR - read only */ + case 0x70/8: /* IRQV - read only */ + break; + + case 0x78/8: /* PAGE */ + chip->current_page = data & 0x7f; + break; + } +} + +ES5506_INLINE void es5506_reg_write_test(UINT32 offset, UINT32 data) +{ + switch (offset) + { + case 0x00/8: /* CHANNEL 0 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 0 left test write %08x\n", data); + break; + + case 0x08/8: /* CHANNEL 0 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 0 right test write %08x\n", data); + break; + + case 0x10/8: /* CHANNEL 1 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 1 left test write %08x\n", data); + break; + + case 0x18/8: /* CHANNEL 1 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 1 right test write %08x\n", data); + break; + + case 0x20/8: /* CHANNEL 2 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 2 left test write %08x\n", data); + break; + + case 0x28/8: /* CHANNEL 2 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 2 right test write %08x\n", data); + break; + + case 0x30/8: /* CHANNEL 3 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 3 left test write %08x\n", data); + break; + + case 0x38/8: /* CHANNEL 3 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 3 right test write %08x\n", data); + break; + + case 0x40/8: /* CHANNEL 4 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 4 left test write %08x\n", data); + break; + + case 0x48/8: /* CHANNEL 4 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 4 right test write %08x\n", data); + break; + + case 0x50/8: /* CHANNEL 5 LEFT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 5 left test write %08x\n", data); + break; + + case 0x58/8: /* CHANNEL 6 RIGHT */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Channel 5 right test write %08x\n", data); + break; + + case 0x60/8: /* EMPTY */ + if (LOG_COMMANDS && eslog) + fprintf(eslog, "Test write EMPTY %08x\n", data); + break; + + case 0x68/8: /* PAR - read only */ + case 0x70/8: /* IRQV - read only */ + break; + + case 0x78/8: /* PAGE */ + chip->current_page = data & 0x7f; + break; + } +} + +//WRITE8_DEVICE_HANDLER( es5506_w ) +void ES5506Write(UINT32 offset, UINT8 data) +{ +// es5506_state *chip = get_safe_token(device); + es5506_voice *voice = &chip->voice[chip->current_page & 0x1f]; + INT32 shift = 8 * (offset & 3); + + /* accumulate the data */ + chip->write_latch = (chip->write_latch & ~(0xff000000 >> shift)) | (data << (24 - shift)); + + /* wait for a write to complete */ + if (shift != 24) + return; + + /* force an update */ +// chip->stream->update(); + + /* switch off the page and register */ + if (chip->current_page < 0x20) + es5506_reg_write_low(voice, offset / 4, chip->write_latch); + else if (chip->current_page < 0x40) + es5506_reg_write_high(voice, offset / 4, chip->write_latch); + else + es5506_reg_write_test(offset / 4, chip->write_latch); + + /* clear the write latch when done */ + chip->write_latch = 0; +} + + + +/********************************************************************************************** + + es5506_reg_read -- read from the specified ES5506 register + +***********************************************************************************************/ + +ES5506_INLINE UINT32 es5506_reg_read_low(es5506_voice *voice, UINT32 offset) +{ + UINT32 result = 0; + + switch (offset) + { + case 0x00/8: /* CR */ + result = voice->control; + break; + + case 0x08/8: /* FC */ + result = voice->freqcount; + break; + + case 0x10/8: /* LVOL */ + result = voice->lvol; + break; + + case 0x18/8: /* LVRAMP */ + result = voice->lvramp << 8; + break; + + case 0x20/8: /* RVOL */ + result = voice->rvol; + break; + + case 0x28/8: /* RVRAMP */ + result = voice->rvramp << 8; + break; + + case 0x30/8: /* ECOUNT */ + result = voice->ecount; + break; + + case 0x38/8: /* K2 */ + result = voice->k2; + break; + + case 0x40/8: /* K2RAMP */ + result = (voice->k2ramp << 8) | (voice->k2ramp >> 31); + break; + + case 0x48/8: /* K1 */ + result = voice->k1; + break; + + case 0x50/8: /* K1RAMP */ + result = (voice->k1ramp << 8) | (voice->k1ramp >> 31); + break; + + case 0x58/8: /* ACTV */ + result = chip->active_voices; + break; + + case 0x60/8: /* MODE */ + result = chip->mode; + break; + + case 0x68/8: /* PAR */ + if (chip->port_read) + result = (*chip->port_read)(); + break; + + case 0x70/8: /* IRQV */ + result = chip->irqv; + update_internal_irq_state(); + break; + + case 0x78/8: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + + +ES5506_INLINE UINT32 es5506_reg_read_high(es5506_voice *voice, UINT32 offset) +{ + UINT32 result = 0; + + switch (offset) + { + case 0x00/8: /* CR */ + result = voice->control; + break; + + case 0x08/8: /* START */ + result = voice->start; + break; + + case 0x10/8: /* END */ + result = voice->end; + break; + + case 0x18/8: /* ACCUM */ + result = voice->accum; + break; + + case 0x20/8: /* O4(n-1) */ + result = voice->o4n1 & 0x3ffff; + break; + + case 0x28/8: /* O3(n-1) */ + result = voice->o3n1 & 0x3ffff; + break; + + case 0x30/8: /* O3(n-2) */ + result = voice->o3n2 & 0x3ffff; + break; + + case 0x38/8: /* O2(n-1) */ + result = voice->o2n1 & 0x3ffff; + break; + + case 0x40/8: /* O2(n-2) */ + result = voice->o2n2 & 0x3ffff; + break; + + case 0x48/8: /* O1(n-1) */ + result = voice->o1n1 & 0x3ffff; + break; + + case 0x50/8: /* W_ST */ + result = chip->wst; + break; + + case 0x58/8: /* W_END */ + result = chip->wend; + break; + + case 0x60/8: /* LR_END */ + result = chip->lrend; + break; + + case 0x68/8: /* PAR */ + if (chip->port_read) + result = (*chip->port_read)(); + break; + + case 0x70/8: /* IRQV */ + result = chip->irqv; + update_internal_irq_state(); + break; + + case 0x78/8: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + +ES5506_INLINE UINT32 es5506_reg_read_test(UINT32 offset) +{ + UINT32 result = 0; + + switch (offset) + { + case 0x68/8: /* PAR */ + if (chip->port_read) + result = (*chip->port_read)(); + break; + + case 0x70/8: /* IRQV */ + result = chip->irqv; + break; + + case 0x78/8: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + +//READ8_DEVICE_HANDLER( es5506_r ) +UINT8 ES5506Read(UINT32 offset) +{ +// es5506_state *chip = get_safe_token(device); + es5506_voice *voice = &chip->voice[chip->current_page & 0x1f]; + INT32 shift = 8 * (offset & 3); + + /* only read on offset 0 */ + if (shift != 0) + return chip->read_latch >> (24 - shift); + + if (LOG_COMMANDS && eslog) + fprintf(eslog, "read from %02x/%02x -> ", chip->current_page, offset / 4 * 8); + + /* force an update */ +// chip->stream->update(); + + /* switch off the page and register */ + if (chip->current_page < 0x20) + chip->read_latch = es5506_reg_read_low(voice, offset / 4); + else if (chip->current_page < 0x40) + chip->read_latch = es5506_reg_read_high(voice, offset / 4); + else + chip->read_latch = es5506_reg_read_test(offset / 4); + + if (LOG_COMMANDS && eslog) + fprintf(eslog, "%08x\n", chip->read_latch); + + /* return the high byte */ + return chip->read_latch >> 24; +} + + + +void es5506_voice_bank_w(INT32 voice, INT32 bank) +{ +// es5506_state *chip = get_safe_token(device); + chip->voice[voice].exbank=bank; +} + + +/********************************************************************************************** + + DEVICE_START( es5505 ) -- start emulation of the ES5505 + +***********************************************************************************************/ + +//static DEVICE_START( es5505 ) +void ES5505Init(INT32 clock, UINT8* region0, UINT8* region1, irq_callback callback) +{ + es5506_start_common(clock, region0, region1, NULL, NULL, callback, ES5505); +} + + + +/********************************************************************************************** + + DEVICE_STOP( es5505 ) -- stop emulation of the ES5505 + +***********************************************************************************************/ + +/*static DEVICE_STOP( es5505 ) +{ + DEVICE_STOP_CALL( es5506 ); +} + + +static DEVICE_RESET( es5505 ) +{ + DEVICE_RESET_CALL( es5506 ); +}*/ + + + +/********************************************************************************************** + + es5505_reg_write -- handle a write to the selected ES5505 register + +***********************************************************************************************/ + +ES5506_INLINE void es5505_reg_write_low(es5506_voice *voice, UINT32 offset, UINT16 data) +{ +// running_machine *machine = chip->device->machine; + + if (offset == 0) bprintf(PRINT_NORMAL, _T("low data %x\n"), data); + + switch (offset) + { + case 0x00: /* CR */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + { +#if RAINE_CHECK + voice->control &= ~(CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_DIR); +#else + voice->control &= ~(CONTROL_STOPMASK | CONTROL_BS0 | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ); +#endif + voice->control |= (data & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | + ((data << 12) & CONTROL_BS0); + } +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + { + voice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK); + voice->control |= ((data >> 2) & CONTROL_LPMASK) | + ((data << 2) & (CONTROL_CA0 | CONTROL_CA1)); + } + +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, control=%04x (raw=%04x & %04x)\n", machine->describe_context(), chip->current_page & 0x1f, voice->control, data, mem_mask ^ 0xffff); + break; + + case 0x01: /* FC */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->freqcount = (voice->freqcount & ~0x001fe) | ((data & 0x00ff) << 1); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->freqcount = (voice->freqcount & ~0x1fe00) | ((data & 0xff00) << 1); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, freq count=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->freqcount); + break; + + case 0x02: /* STRT (hi) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->start = (voice->start & ~0x03fc0000) | ((data & 0x00ff) << 18); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->start = (voice->start & ~0x7c000000) | ((data & 0x1f00) << 18); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, loop start=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->start); + break; + + case 0x03: /* STRT (lo) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->start = (voice->start & ~0x00000380) | ((data & 0x00e0) << 2); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->start = (voice->start & ~0x0003fc00) | ((data & 0xff00) << 2); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, loop start=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->start); + break; + + case 0x04: /* END (hi) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->end = (voice->end & ~0x03fc0000) | ((data & 0x00ff) << 18); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->end = (voice->end & ~0x7c000000) | ((data & 0x1f00) << 18); +#if RAINE_CHECK + voice->control |= CONTROL_STOP0; +#endif +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, loop end=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->end); + break; + + case 0x05: /* END (lo) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->end = (voice->end & ~0x00000380) | ((data & 0x00e0) << 2); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->end = (voice->end & ~0x0003fc00) | ((data & 0xff00) << 2); +#if RAINE_CHECK + voice->control |= CONTROL_STOP0; +#endif +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, loop end=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->end); + break; + + case 0x06: /* K2 */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->k2 = (voice->k2 & ~0x00f0) | (data & 0x00f0); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->k2 = (voice->k2 & ~0xff00) | (data & 0xff00); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, K2=%04x\n", machine->describe_context(), chip->current_page & 0x1f, voice->k2); + break; + + case 0x07: /* K1 */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->k1 = (voice->k1 & ~0x00f0) | (data & 0x00f0); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->k1 = (voice->k1 & ~0xff00) | (data & 0xff00); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, K1=%04x\n", machine->describe_context(), chip->current_page & 0x1f, voice->k1); + break; + + case 0x08: /* LVOL */ +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->lvol = (voice->lvol & ~0xff00) | (data & 0xff00); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, left vol=%04x\n", machine->describe_context(), chip->current_page & 0x1f, voice->lvol); + break; + + case 0x09: /* RVOL */ +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->rvol = (voice->rvol & ~0xff00) | (data & 0xff00); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, right vol=%04x\n", machine->describe_context(), chip->current_page & 0x1f, voice->rvol); + break; + + case 0x0a: /* ACC (hi) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->accum = (voice->accum & ~0x03fc0000) | ((data & 0x00ff) << 18); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->accum = (voice->accum & ~0x7c000000) | ((data & 0x1f00) << 18); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, accum=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->accum); + break; + + case 0x0b: /* ACC (lo) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->accum = (voice->accum & ~0x000003fc) | ((data & 0x00ff) << 2); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->accum = (voice->accum & ~0x0003fc00) | ((data & 0xff00) << 2); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, accum=%08x\n", machine->describe_context(), chip->current_page & 0x1f, voice->accum); + break; + + case 0x0c: /* unused */ + break; + + case 0x0d: /* ACT */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + { + chip->active_voices = data & 0x1f; + chip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1)); +// chip->stream->set_sample_rate(chip->sample_rate); + +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "active voices=%d, sample_rate=%d\n", chip->active_voices, chip->sample_rate); + } + break; + + case 0x0e: /* IRQV - read only */ + break; + + case 0x0f: /* PAGE */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + chip->current_page = data & 0x7f; + break; + } +} + + +ES5506_INLINE void es5505_reg_write_high(es5506_voice *voice, UINT32 offset, UINT16 data) +{ +// running_machine *machine = chip->device->machine; + + if (offset == 0) bprintf(PRINT_NORMAL, _T("high data %x\n"), data); + + switch (offset) + { + case 0x00: /* CR */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + { + voice->control &= ~(CONTROL_STOPMASK | CONTROL_BS0 | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ); + voice->control |= (data & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | + ((data << 12) & CONTROL_BS0); + } +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + { + voice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK); + voice->control |= ((data >> 2) & CONTROL_LPMASK) | + ((data << 2) & (CONTROL_CA0 | CONTROL_CA1)); + } +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, control=%04x (raw=%04x & %04x)\n", machine->describe_context(), chip->current_page & 0x1f, voice->control, data, mem_mask); + break; + + case 0x01: /* O4(n-1) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o4n1 = (voice->o4n1 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o4n1 = (INT16)((voice->o4n1 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O4(n-1)=%05x\n", machine->describe_context(), chip->current_page & 0x1f, voice->o4n1 & 0x3ffff); + break; + + case 0x02: /* O3(n-1) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o3n1 = (voice->o3n1 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o3n1 = (INT16)((voice->o3n1 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O3(n-1)=%05x\n", machine->describe_context(), chip->current_page & 0x1f, voice->o3n1 & 0x3ffff); + break; + + case 0x03: /* O3(n-2) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o3n2 = (voice->o3n2 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o3n2 = (INT16)((voice->o3n2 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O3(n-2)=%05x\n", machine->describe_context(), chip->current_page & 0x1f, voice->o3n2 & 0x3ffff); + break; + + case 0x04: /* O2(n-1) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o2n1 = (voice->o2n1 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o2n1 = (INT16)((voice->o2n1 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O2(n-1)=%05x\n", machine->describe_context(), chip->current_page & 0x1f, voice->o2n1 & 0x3ffff); + break; + + case 0x05: /* O2(n-2) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o2n2 = (voice->o2n2 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o2n2 = (INT16)((voice->o2n2 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O2(n-2)=%05x\n", machine->describe_context(), chip->current_page & 0x1f, voice->o2n2 & 0x3ffff); + break; + + case 0x06: /* O1(n-1) */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + voice->o1n1 = (voice->o1n1 & ~0x00ff) | (data & 0x00ff); +// if (ACCESSING_BITS_8_15) + if (data & 0xff00) + voice->o1n1 = (INT16)((voice->o1n1 & ~0xff00) | (data & 0xff00)); +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "%s:voice %d, O1(n-1)=%05x (accum=%08x)\n", machine->describe_context(), chip->current_page & 0x1f, voice->o2n1 & 0x3ffff, voice->accum); + break; + + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: /* unused */ + break; + + case 0x0d: /* ACT */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + { + chip->active_voices = data & 0x1f; + chip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1)); +// chip->stream->set_sample_rate(chip->sample_rate); + +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "active voices=%d, sample_rate=%d\n", chip->active_voices, chip->sample_rate); + } + break; + + case 0x0e: /* IRQV - read only */ + break; + + case 0x0f: /* PAGE */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + chip->current_page = data & 0x7f; + break; + } +} + + +ES5506_INLINE void es5505_reg_write_test(UINT32 offset, UINT16 data) +{ + switch (offset) + { + case 0x00: /* CH0L */ + case 0x01: /* CH0R */ + case 0x02: /* CH1L */ + case 0x03: /* CH1R */ + case 0x04: /* CH2L */ + case 0x05: /* CH2R */ + case 0x06: /* CH3L */ + case 0x07: /* CH3R */ + break; + + case 0x08: /* SERMODE */ + chip->mode = data & 0x0007; + break; + + case 0x09: /* PAR */ + break; + + case 0x0d: /* ACT */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + { + chip->active_voices = data & 0x1f; + chip->sample_rate = chip->master_clock / (16 * (chip->active_voices + 1)); +// chip->stream->set_sample_rate(chip->sample_rate); + +// if (LOG_COMMANDS && eslog) +// fprintf(eslog, "active voices=%d, sample_rate=%d\n", chip->active_voices, chip->sample_rate); + } + break; + + case 0x0e: /* IRQV - read only */ + break; + + case 0x0f: /* PAGE */ +// if (ACCESSING_BITS_0_7) + if (data & 0xff) + chip->current_page = data & 0x7f; + break; + } +} + + +//WRITE16_DEVICE_HANDLER( es5505_w ) +void ES5505Write(UINT32 offset, UINT16 data) +{ +// es5506_state *chip = get_safe_token(device); + es5506_voice *voice = &chip->voice[chip->current_page & 0x1f]; + +// logerror("%s:ES5505 write %02x/%02x = %04x & %04x\n", machine->describe_context(), chip->current_page, offset, data, mem_mask); + + /* force an update */ +// chip->stream->update(); + + /* switch off the page and register */ + if (chip->current_page < 0x20) + es5505_reg_write_low(voice, offset, data); + else if (chip->current_page < 0x40) + es5505_reg_write_high(voice, offset, data); + else + es5505_reg_write_test(offset, data); +} + + + +/********************************************************************************************** + + es5505_reg_read -- read from the specified ES5505 register + +***********************************************************************************************/ + +ES5506_INLINE UINT16 es5505_reg_read_low(es5506_voice *voice, UINT32 offset) +{ + UINT16 result = 0; + + switch (offset) + { + case 0x00: /* CR */ + result = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | + ((voice->control & CONTROL_BS0) >> 12) | + ((voice->control & CONTROL_LPMASK) << 2) | + ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) | + 0xf000; + break; + + case 0x01: /* FC */ + result = voice->freqcount >> 1; + break; + + case 0x02: /* STRT (hi) */ + result = voice->start >> 18; + break; + + case 0x03: /* STRT (lo) */ + result = voice->start >> 2; + break; + + case 0x04: /* END (hi) */ + result = voice->end >> 18; + break; + + case 0x05: /* END (lo) */ + result = voice->end >> 2; + break; + + case 0x06: /* K2 */ + result = voice->k2; + break; + + case 0x07: /* K1 */ + result = voice->k1; + break; + + case 0x08: /* LVOL */ + result = voice->lvol; + break; + + case 0x09: /* RVOL */ + result = voice->rvol; + break; + + case 0x0a: /* ACC (hi) */ + result = voice->accum >> 18; + break; + + case 0x0b: /* ACC (lo) */ + result = voice->accum >> 2; + break; + + case 0x0c: /* unused */ + break; + + case 0x0d: /* ACT */ + result = chip->active_voices; + break; + + case 0x0e: /* IRQV */ + result = chip->irqv; + update_internal_irq_state(); + break; + + case 0x0f: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + + +ES5506_INLINE UINT16 es5505_reg_read_high(es5506_voice *voice, UINT32 offset) +{ + UINT16 result = 0; + + switch (offset) + { + case 0x00: /* CR */ + result = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | + ((voice->control & CONTROL_BS0) >> 12) | + ((voice->control & CONTROL_LPMASK) << 2) | + ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) | + 0xf000; + break; + + case 0x01: /* O4(n-1) */ + result = voice->o4n1; + break; + + case 0x02: /* O3(n-1) */ + result = voice->o3n1; + break; + + case 0x03: /* O3(n-2) */ + result = voice->o3n2; + break; + + case 0x04: /* O2(n-1) */ + result = voice->o2n1; + break; + + case 0x05: /* O2(n-2) */ + result = voice->o2n2; + break; + + case 0x06: /* O1(n-1) */ + /* special case for the Taito F3 games: they set the accumulator on a stopped */ + /* voice and assume the filters continue to process the data. They then read */ + /* the O1(n-1) in order to extract raw data from the sound ROMs. Since we don't */ + /* want to waste time filtering stopped channels, we just look for a read from */ + /* this register on a stopped voice, and return the raw sample data at the */ + /* accumulator */ + if ((voice->control & CONTROL_STOPMASK) && chip->region_base[voice->control >> 14]) { + voice->o1n1 = chip->region_base[voice->control >> 14][voice->exbank + (voice->accum >> 11)]; +// logerror("%02x %08x ==> %08x\n",voice->o1n1,voice->control >> 14,voice->exbank + (voice->accum >> 11)); + } + result = voice->o1n1; + break; + + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: /* unused */ + break; + + case 0x0d: /* ACT */ + result = chip->active_voices; + break; + + case 0x0e: /* IRQV */ + result = chip->irqv; + update_internal_irq_state(); + break; + + case 0x0f: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + + +ES5506_INLINE UINT16 es5505_reg_read_test(UINT32 offset) +{ + UINT16 result = 0; + + switch (offset) + { + case 0x00: /* CH0L */ + case 0x01: /* CH0R */ + case 0x02: /* CH1L */ + case 0x03: /* CH1R */ + case 0x04: /* CH2L */ + case 0x05: /* CH2R */ + case 0x06: /* CH3L */ + case 0x07: /* CH3R */ + break; + + case 0x08: /* SERMODE */ + result = chip->mode; + break; + + case 0x09: /* PAR */ + if (chip->port_read) + result = (*chip->port_read)(); + break; + + case 0x0f: /* PAGE */ + result = chip->current_page; + break; + } + return result; +} + + +//READ16_DEVICE_HANDLER( es5505_r ) +UINT16 ES5505Read(UINT32 offset) +{ +// es5506_state *chip = get_safe_token(device); + es5506_voice *voice = &chip->voice[chip->current_page & 0x1f]; + UINT16 result = 0; + + if (LOG_COMMANDS && eslog) + fprintf(eslog, "read from %02x/%02x -> ", chip->current_page, offset); + + /* force an update */ +// chip->stream->update(); + + /* switch off the page and register */ + if (chip->current_page < 0x20) + result = es5505_reg_read_low(voice, offset); + else if (chip->current_page < 0x40) + result = es5505_reg_read_high(voice, offset); + else + result = es5505_reg_read_test(offset); + + if (LOG_COMMANDS && eslog) + fprintf(eslog, "%04x (accum=%08x)\n", result, voice->accum); + + /* return the high byte */ + return result; +} + + + +void es5505_voice_bank_w(INT32 voice, INT32 bank) +{ +// es5506_state *chip = get_safe_token(device); +#if RAINE_CHECK + chip->voice[voice].control = CONTROL_STOPMASK; +#endif + chip->voice[voice].exbank=bank; +} + + +#if 0 + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +DEVICE_GET_INFO( es5505 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(es5506_state); break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( es5505 ); break; + case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( es5505 ); break; + case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( es5505 ); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "ES5505"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Ensoniq Wavetable"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; + } +} + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +DEVICE_GET_INFO( es5506 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(es5506_state); break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( es5506 ); break; + case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( es5506 ); break; + case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( es5506 ); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "ES5506"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Ensoniq Wavetable"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; + } +} + + +DEFINE_LEGACY_SOUND_DEVICE(ES5505, es5505); +DEFINE_LEGACY_SOUND_DEVICE(ES5506, es5506); +#endif diff --git a/src/burn/sound/es5506.h b/src/burn/sound/es5506.h new file mode 100644 index 00000000..23ab8719 --- /dev/null +++ b/src/burn/sound/es5506.h @@ -0,0 +1,66 @@ +/********************************************************************************************** + * + * Ensoniq ES5505/6 driver + * by Aaron Giles + * + **********************************************************************************************/ + +//#pragma once + +#ifndef __ES5506_H__ +#define __ES5506_H__ + +//#include "devlegcy.h" + +typedef void (*irq_callback)(INT32 param); +typedef UINT16(port_read)(); + +typedef struct _es5505_interface es5505_interface; +struct _es5505_interface +{ + const INT8 * region0; /* memory region where the sample ROM lives */ + const INT8 * region1; /* memory region where the sample ROM lives */ + void (*irq_callback)(INT32 state); /* irq callback */ + UINT16 (*read_port)(); /* input port read */ +}; + +//READ16_DEVICE_HANDLER( es5505_r ); +//WRITE16_DEVICE_HANDLER( es5505_w ); +//void es5505_voice_bank_w(device_t *device, int voice, int bank); + +//DECLARE_LEGACY_SOUND_DEVICE(ES5505, es5505); + + +typedef struct _es5506_interface es5506_interface; +struct _es5506_interface +{ + const INT8 * region0; /* memory region where the sample ROM lives */ + const INT8 * region1; /* memory region where the sample ROM lives */ + const INT8 * region2; /* memory region where the sample ROM lives */ + const INT8 * region3; /* memory region where the sample ROM lives */ + void (*irq_callback)(INT32 state); /* irq callback */ + UINT16 (*read_port)(); /* input port read */ +}; + +//READ8_DEVICE_HANDLER( es5506_r ); +//WRITE8_DEVICE_HANDLER( es5506_w ); +//void es5506_voice_bank_w(device_t *device, int voice, int bank); + +//DECLARE_LEGACY_SOUND_DEVICE(ES5506, es5506); + +void ES5506Update(INT16 *pBuffer, INT32 samples); +#define ES5505Update ES5506Update +void ES5506Init(INT32 clock, UINT8 *region0, UINT8 *region1, UINT8 *region2, UINT8 *region3, irq_callback callback); +void ES5506Exit(); +void ES5506Reset(); +void ES5506Write(UINT32 offset, UINT8 data); +UINT8 ES5506Read(UINT32 offset); +void es5506_voice_bank_w(INT32 voice, INT32 bank); +void ES5505Init(INT32 clock, UINT8 *region0, UINT8* region1, irq_callback callback); +#define ES5505Reset ES5506Reset +#define ES5505Exit ES5505Exit +void ES5505Write(UINT32 offset, UINT16 data); +UINT16 ES5505Read(UINT32 offset); +void es5505_voice_bank_w(INT32 voice, INT32 bank); + +#endif /* __ES5506_H__ */ diff --git a/src/burn/sound/es8712.cpp b/src/burn/sound/es8712.cpp new file mode 100644 index 00000000..76f0ac43 --- /dev/null +++ b/src/burn/sound/es8712.cpp @@ -0,0 +1,416 @@ +/********************************************************************************************** + * + * Streaming singe channel ADPCM core for the ES8712 chip + * Chip is branded by Excellent Systems, probably OEM'd. + * + * Samples are currently looped, but whether they should and how, is unknown. + * Interface to the chip is also not 100% clear. + * Should there be any status signals signifying busy, end of sample - etc? + * + * Heavily borrowed from the OKI M6295 source + * + * Excellent Systems ADPCM Emulation + * Copyright Nicola Salmoria and the MAME Team + * + * From MAME 0.139u1. Modified for use in FBA Aug 23, 2010. + * + **********************************************************************************************/ + +#include "burnint.h" +#include "math.h" +#include "es8712.h" + +#define MAX_ES8712_CHIPS 1 + +#define MAX_SAMPLE_CHUNK 10000 + +/* struct describing a playing ADPCM chip */ +typedef struct _es8712_state es8712_state; +struct _es8712_state +{ + UINT8 playing; /* 1 if we're actively playing */ + + UINT32 base_offset; /* pointer to the base memory location */ + UINT32 sample; /* current sample number */ + UINT32 count; /* total samples to play */ + + UINT32 signal; /* current ADPCM signal */ + UINT32 step; /* current ADPCM step */ + + UINT32 start; /* starting address for the next loop */ + UINT32 end; /* ending address for the next loop */ + UINT8 repeat; /* Repeat current sample when 1 */ + + INT32 bank_offset; + +// non volatile + UINT8 *region_base; /* pointer to the base of the region */ + + INT32 sample_rate; /* samples per frame */ + INT32 volume; /* set gain */ + INT32 addSignal; /* add signal to stream? */ +}; + +static INT16 *tbuf[MAX_ES8712_CHIPS] = { NULL }; + +static _es8712_state chips[MAX_ES8712_CHIPS]; +static _es8712_state *chip; + +static const INT32 index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; +static INT32 diff_lookup[49*16]; + +/********************************************************************************************** + + compute_tables -- compute the difference tables + +***********************************************************************************************/ + +static void compute_tables() +{ + /* nibble to bit map */ + static const INT32 nbl2bit[16][4] = + { + { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1}, + { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1}, + {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1}, + {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1} + }; + + INT32 step, nib; + + /* loop over all possible steps */ + for (step = 0; step <= 48; step++) + { + /* compute the step value */ + INT32 stepval = (INT32)(floor(16.0 * pow(11.0 / 10.0, (double)step))); + + /* loop over all nibbles and compute the difference */ + for (nib = 0; nib < 16; nib++) + { + diff_lookup[step*16 + nib] = nbl2bit[nib][0] * + (stepval * nbl2bit[nib][1] + + stepval/2 * nbl2bit[nib][2] + + stepval/4 * nbl2bit[nib][3] + + stepval/8); + } + } +} + + +/********************************************************************************************** + + generate_adpcm -- general ADPCM decoding routine + +***********************************************************************************************/ + +static void generate_adpcm(INT16 *buffer, INT32 samples) +{ + /* if this chip is active */ + if (chip->playing) + { + UINT8 *base = chip->region_base + chip->bank_offset + chip->base_offset; + INT32 sample = chip->sample; + INT32 signal = chip->signal; + INT32 count = chip->count; + INT32 step = chip->step; + INT32 volume = chip->volume; + INT32 val; + + /* loop while we still have samples to generate */ + while (samples) + { + /* compute the new amplitude and update the current step */ + val = base[sample / 2] >> (((sample & 1) << 2) ^ 4); + signal += diff_lookup[step * 16 + (val & 15)]; + + /* clamp to the maximum */ + if (signal > 2047) + signal = 2047; + else if (signal < -2048) + signal = -2048; + + /* adjust the step size and clamp */ + step += index_shift[val & 7]; + if (step > 48) + step = 48; + else if (step < 0) + step = 0; + + /* output to the buffer */ + *buffer++ = (signal * 16 * volume) / 100; + samples--; + + /* next! */ + if (++sample >= count) + { + if (chip->repeat) + { + sample = 0; + signal = -2; + step = 0; + } + else + { + chip->playing = 0; + break; + } + } + } + + /* update the parameters */ + chip->sample = sample; + chip->signal = signal; + chip->step = step; + } + + /* fill the rest with silence */ + while (samples--) + *buffer++ = 0; +} + + +/********************************************************************************************** + + es8712Update -- update the sound chip so that it is in sync with CPU execution + +***********************************************************************************************/ + +void es8712Update(INT32 device, INT16 *buffer, INT32 samples) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + INT32 sample_num = (INT32)((float)(((samples / nBurnSoundLen) * 1.0000) * chip->sample_rate)); + + float step = ((chip->sample_rate * 1.00000) / nBurnSoundLen); + + INT16 *buf = tbuf[device]; + + generate_adpcm(buf, sample_num); + + float r = 0; + if (chip->addSignal) { + for (INT32 i = 0; i < samples; i++, r += step, buffer+=2) { + buffer[0] += buf[(INT32)r]; + buffer[1] += buf[(INT32)r]; + } + } else { + for (INT32 i = 0; i < samples; i++, r += step, buffer+=2) { + buffer[0] = buffer[1] = buf[(INT32)r]; + } + } +} + + +/********************************************************************************************** + + es8712Init -- start emulation of an ES8712 chip + +***********************************************************************************************/ + +void es8712Init(INT32 device, UINT8 *rom, INT32 sample_rate, float volume, INT32 addSignal) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + compute_tables(); + + chip->start = 0; + chip->end = 0; + chip->repeat = 0; + + chip->bank_offset = 0; + chip->region_base = (UINT8*)rom; + + /* initialize the rest of the structure */ + chip->signal = (UINT32)-2; + + chip->sample_rate = sample_rate; + + chip->volume = (INT32)(volume+0.5); + chip->addSignal = addSignal; + + if (tbuf[device] == NULL) { + tbuf[device] = (INT16*)malloc(sample_rate * sizeof(INT16)); + } +} + +/********************************************************************************************** + + es8712Exit -- stop emulation of an ES8712 chip + +***********************************************************************************************/ + +void es8712Exit(INT32 device) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + memset (chip, 0, sizeof(_es8712_state)); + + if (tbuf[device] != NULL) { + free (tbuf[device]); + tbuf[device] = NULL; + } +} + +/************************************************************************************* + + es8712Reset -- stop emulation of an ES8712-compatible chip + +**************************************************************************************/ + +void es8712Reset(INT32 device) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + if (chip->playing) + { + /* update the stream, then turn it off */ + chip->playing = 0; + chip->repeat = 0; + } +} + + +/**************************************************************************** + + es8712_set_bank_base -- set the base of the bank on a given chip + +*****************************************************************************/ + +void es8712SetBankBase(INT32 device, INT32 base) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + chip->bank_offset = base; +} + + +/********************************************************************************************** + + es8712Play -- Begin playing the addressed sample + +***********************************************************************************************/ + +void es8712Play(INT32 device) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + if (chip->start < chip->end) + { + if (!chip->playing) + { + chip->playing = 1; + chip->base_offset = chip->start; + chip->sample = 0; + chip->count = 2 * (chip->end - chip->start + 1); + chip->repeat = 0;//1; + + /* also reset the ADPCM parameters */ + chip->signal = (UINT32)-2; + chip->step = 0; + } + } + /* invalid samples go here */ + else + { + if (chip->playing) + { + /* update the stream */ + chip->playing = 0; + } + } +} + + +/********************************************************************************************** + + es8712Write -- generic data write function + +***********************************************************************************************/ + +/********************************************************************************************** + * + * offset Start End + * 0hmmll - 0HMMLL + * 00 ----ll + * 01 --mm-- + * 02 0h---- + * 03 ----LL + * 04 --MM-- + * 05 0H---- + * 06 Go! + * + * Offsets are written in the order -> 00, 02, 01, 03, 05, 04, 06 + * Offset 06 is written with the same value as offset 04. + * +***********************************************************************************************/ + +void es8712Write(INT32 device, INT32 offset, UINT8 data) +{ + if (device >= MAX_ES8712_CHIPS) return; + + chip = &chips[device]; + + switch (offset) + { + case 00: chip->start &= 0x000fff00; + chip->start |= ((data & 0xff) << 0); break; + case 01: chip->start &= 0x000f00ff; + chip->start |= ((data & 0xff) << 8); break; + case 02: chip->start &= 0x0000ffff; + chip->start |= ((data & 0x0f) << 16); break; + case 03: chip->end &= 0x000fff00; + chip->end |= ((data & 0xff) << 0); break; + case 04: chip->end &= 0x000f00ff; + chip->end |= ((data & 0xff) << 8); break; + case 05: chip->end &= 0x0000ffff; + chip->end |= ((data & 0x0f) << 16); break; + case 06: + es8712Play(device); + break; + default: break; + } + + chip->start &= 0xfffff; + chip->end &= 0xfffff; +} + + +/********************************************************************************************** + + es8712Scan -- save state function + +***********************************************************************************************/ + +INT32 es8712Scan(INT32 device, INT32 nAction) +{ + if (device >= MAX_ES8712_CHIPS) return 1; + + if (nAction & ACB_DRIVER_DATA) { + chip = &chips[device]; + + SCAN_VAR(chip->playing); + SCAN_VAR(chip->base_offset); + SCAN_VAR(chip->sample); + SCAN_VAR(chip->count); + SCAN_VAR(chip->signal); + SCAN_VAR(chip->step); + SCAN_VAR(chip->start); + SCAN_VAR(chip->end); + SCAN_VAR(chip->repeat); + SCAN_VAR(chip->bank_offset); + } + + return 0; +} diff --git a/src/burn/sound/es8712.h b/src/burn/sound/es8712.h new file mode 100644 index 00000000..8c49f8ae --- /dev/null +++ b/src/burn/sound/es8712.h @@ -0,0 +1,11 @@ +void es8712Write(INT32 device, INT32 offset, UINT8 data); +void es8712Play(INT32 device); + +void es8712SetBankBase(INT32 device, INT32 base); + +void es8712Init(INT32 device, UINT8 *rom, INT32 sample_rate, float volume, INT32 addSignal); +void es8712Reset(INT32 device); +void es8712Update(INT32 device, INT16 *buffer, INT32 samples); +void es8712Exit(INT32 device); + +INT32 es8712Scan(INT32 device, INT32 nAction); diff --git a/src/burn/sound/fm.c b/src/burn/sound/fm.c new file mode 100644 index 00000000..d7b7dc9e --- /dev/null +++ b/src/burn/sound/fm.c @@ -0,0 +1,5121 @@ +#define YM2610B_WARNING + +/* +** +** File: fm.c -- software implementation of Yamaha FM sound generator +** +** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net) +** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development +** +** Version 1.4 (final beta) +** +*/ + +/* +** History: +** +** 03-08-2003 Jarek Burczynski: +** - fixed YM2608 initial values (after the reset) +** - fixed flag and irqmask handling (YM2608) +** - fixed BUFRDY flag handling (YM2608) +** +** 14-06-2003 Jarek Burczynski: +** - implemented all of the YM2608 status register flags +** - implemented support for external memory read/write via YM2608 +** - implemented support for deltat memory limit register in YM2608 emulation +** +** 22-05-2003 Jarek Burczynski: +** - fixed LFO PM calculations (copy&paste bugfix) +** +** 08-05-2003 Jarek Burczynski: +** - fixed SSG support +** +** 22-04-2003 Jarek Burczynski: +** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608) +** +** 15-04-2003 Jarek Burczynski: +** - added support for YM2608's register 0x110 - status mask +** +** 01-12-2002 Jarek Burczynski: +** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608) +** The addressing patch used for early Neo-Geo games can be removed now. +** +** 26-11-2002 Jarek Burczynski, Nicola Salmoria: +** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to: +** - added emulation of YM2608 drums. +** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608) +** +** 16-08-2002 Jarek Burczynski: +** - binary exact Envelope Generator (verified on real YM2203); +** identical to YM2151 +** - corrected 'off by one' error in feedback calculations (when feedback is off) +** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610) +** +** 18-12-2001 Jarek Burczynski: +** - added SSG-EG support (verified on real YM2203) +** +** 12-08-2001 Jarek Burczynski: +** - corrected sin_tab and tl_tab data (verified on real chip) +** - corrected feedback calculations (verified on real chip) +** - corrected phase generator calculations (verified on real chip) +** - corrected envelope generator calculations (verified on real chip) +** - corrected FM volume level (YM2610 and YM2610B). +** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) : +** this was needed to calculate YM2610 FM channels output correctly. +** (Each FM channel is calculated as in other chips, but the output of the channel +** gets shifted right by one *before* sending to accumulator. That was impossible to do +** with previous implementation). +** +** 23-07-2001 Jarek Burczynski, Nicola Salmoria: +** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip) +** +** 11-06-2001 Jarek Burczynski: +** - corrected end of sample bug in ADPCMA_calc_cha(). +** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits). +** +** 08-12-98 hiro-shi: +** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA +** move ROM limit check.(CALC_CH? -> 2610Write1/2) +** test program (ADPCMB_TEST) +** move ADPCM A/B end check. +** ADPCMB repeat flag(no check) +** change ADPCM volume rate (8->16) (32->48). +** +** 09-12-98 hiro-shi: +** change ADPCM volume. (8->16, 48->64) +** replace ym2610 ch0/3 (YM-2610B) +** init cur_chip (restart bug fix) +** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff. +** add ADPCM_SHIFT_MASK +** change ADPCMA_DECODE_MIN/MAX. +*/ + + + + +/************************************************************************/ +/* comment of hiro-shi(Hiromitsu Shioya) */ +/* YM2610(B) = OPN-B */ +/* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/************************************************************************/ + +#include +#include +#include +#include +#include + +#ifndef __RAINE__ +#include "driver.h" /* use M.A.M.E. */ +#include "state.h" +#else +#include "deftypes.h" /* use RAINE */ +#include "support.h" /* use RAINE */ +#endif + +#include "ay8910.h" +#include "fm.h" + + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + + +/* include external DELTA-T unit (when needed) */ +#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) + #include "ymdeltat.h" +#endif + +/* shared function building option */ +#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B||BUILD_YM2612) +#define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608) + + +/* globals */ +#define TYPE_SSG 0x01 /* SSG support */ +#define TYPE_LFOPAN 0x02 /* OPN type LFO and PAN */ +#define TYPE_6CH 0x04 /* FM 6CH / 3CH */ +#define TYPE_DAC 0x08 /* YM2612's DAC device */ +#define TYPE_ADPCM 0x10 /* two ADPCM units */ +#define TYPE_2610 0x20 /* bogus flag to differentiate 2608 from 2610 */ + +#define TYPE_YM2203 (TYPE_SSG) +#define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM) +#define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM |TYPE_2610) +#define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH) + + + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */ +#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define FREQ_MASK ((1<>3) + +/* sin waveform table in 'decibel' scale */ +static unsigned int sin_tab[SIN_LEN]; + +/* sustain level table (3dB per step) */ +/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */ +/* 1, 2, 4, 8, 16, 32, 64 (value)*/ +/* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/ + +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ +#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) ) +static const UINT32 sl_table[16]={ + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) +}; +#undef SC + + +#define RATE_STEPS (8) +static const UINT8 eg_inc[19*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */ +/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */ +/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */ +/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */ + +/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ +/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */ +/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; + + +#define O(a) (a*RATE_STEPS) + +/*note that there is no O(17) in this table - it's directly in the code */ +static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), + +/* rates 00-11 */ +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 12 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 13 */ +O( 8),O( 9),O(10),O(11), + +/* rate 14 */ +O(12),O(13),O(14),O(15), + +/* rate 15 */ +O(16),O(16),O(16),O(16), + +/* 32 dummy rates (same as 15 3) */ +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) + +}; + +static const UINT8 eg_rate_select2612[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), + +/* rates 00-11 */ +O( 18),O( 18),O( 0),O( 0), +O( 0),O( 0),O( 2),O( 2), // Nemesis's tests + +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 12 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 13 */ +O( 8),O( 9),O(10),O(11), + +/* rate 14 */ +O(12),O(13),O(14),O(15), + +/* rate 15 */ +O(16),O(16),O(16),O(16), + +/* 32 dummy rates (same as 15 3) */ +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/ +/*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */ +/*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */ + +#define O(a) (a*1) +static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), + +/* rates 00-11 */ +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), +O( 0),O( 0),O( 0),O( 0), + +/* rate 12 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 32 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0) + +}; +#undef O + +static const UINT8 dt_tab[4 * 32]={ +/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/ +/* FD=0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* FD=1 */ + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, +/* FD=2 */ + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, + 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, +/* FD=3 */ + 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 8 , 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22 +}; + + +/* OPN key frequency number -> key code follow table */ +/* fnum higher 4bit -> keycode lower 2bit */ +static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; + + +/* 8 LFO speed parameters */ +/* each value represents number of samples that one LFO level will last for */ +static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5}; + + + +/*There are 4 different LFO AM depths available, they are: + 0 dB, 1.4 dB, 5.9 dB, 11.8 dB + Here is how it is generated (in EG steps): + + 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0 + 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0 + 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0 + + (1.4 dB is loosing precision as you can see) + + It's implemented as generator from 0..126 with step 2 then a shift + right N times, where N is: + 8 for 0 dB + 3 for 1.4 dB + 1 for 5.9 dB + 0 for 11.8 dB +*/ +static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0}; + + + +/*There are 8 different LFO PM depths available, they are: + 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents) + + Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10 + (bits 8,9,10 = FNUM MSB from OCT/FNUM register) + + Here we store only first quarter (positive one) of full waveform. + Full table (lfo_pm_table) containing all 128 waveforms is build + at run (init) time. + + One value in table below represents 4 (four) basic LFO steps + (1 PM step = 4 AM steps). + + For example: + at LFO SPEED=0 (which is 108 samples per basic LFO step) + one value from "lfo_pm_output" table lasts for 432 consecutive + samples (4*108=432) and one full LFO waveform cycle lasts for 13824 + samples (32*432=13824; 32 because we store only a quarter of whole + waveform in the table below) +*/ +static const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */ +/* FNUM BIT 4: 000 0001xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1}, + +/* FNUM BIT 5: 000 0010xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3}, + +/* FNUM BIT 6: 000 0100xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1}, +/* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6}, + +/* FNUM BIT 7: 000 1000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1}, +/* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2}, +/* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, + +/* FNUM BIT 8: 001 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2}, +/* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3}, +/* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4}, +/* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, + +/* FNUM BIT 9: 010 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2}, +/* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4}, +/* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6}, +/* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8}, +/* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, + +/* FNUM BIT10: 100 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4}, +/* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8}, +/* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc}, +/* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10}, +/* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, +/* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60}, + +}; + +/* all 128 LFO PM waveforms */ +static INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */ + + + + + +/* register number to channel number , slot offset */ +#define OPN_CHAN(N) (N&3) +#define OPN_SLOT(N) ((N>>2)&3) + +/* slot number */ +#define SLOT1 0 +#define SLOT2 2 +#define SLOT3 1 +#define SLOT4 3 + +/* bit0 = Right enable , bit1 = Left enable */ +#define OUTD_RIGHT 1 +#define OUTD_LEFT 2 +#define OUTD_CENTER 3 + + +/* save output as raw 16-bit sample */ +/* #define SAVE_SAMPLE */ + +#ifdef SAVE_SAMPLE +static FILE *sample[1]; + #if 1 /*save to MONO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #else /*save to STEREO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = rt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #endif +#endif + + +/* struct describing a single operator (SLOT) */ +typedef struct +{ + INT32 *DT; /* detune :dt_tab[DT] */ + UINT8 KSR; /* key scale rate :3-KSR */ + UINT32 ar; /* attack rate */ + UINT32 d1r; /* decay rate */ + UINT32 d2r; /* sustain rate */ + UINT32 rr; /* release rate */ + UINT8 ksr; /* key scale rate :kcode>>(3-KSR) */ + UINT32 mul; /* multiple :ML_TABLE[ML] */ + + /* Phase Generator */ + UINT32 phase; /* phase counter */ + INT32 Incr; /* phase step */ + + /* Envelope Generator */ + UINT8 state; /* phase type */ + UINT32 tl; /* total level: TL << 3 */ + INT32 volume; /* envelope counter */ + UINT32 sl; /* sustain level:sl_table[SL] */ + UINT32 vol_out; /* current output from EG circuit (without AM from LFO) */ + + UINT8 eg_sh_ar; /* (attack state) */ + UINT8 eg_sel_ar; /* (attack state) */ + UINT8 eg_sh_d1r; /* (decay state) */ + UINT8 eg_sel_d1r; /* (decay state) */ + UINT8 eg_sh_d2r; /* (sustain state) */ + UINT8 eg_sel_d2r; /* (sustain state) */ + UINT8 eg_sh_rr; /* (release state) */ + UINT8 eg_sel_rr; /* (release state) */ + + UINT8 ssg; /* SSG-EG waveform */ + UINT8 ssgn; /* SSG-EG negated output */ + + UINT32 key; /* 0=last key was KEY OFF, 1=KEY ON */ + + /* LFO */ + UINT32 AMmask; /* AM enable flag */ + +} FM_SLOT; + +typedef struct +{ + FM_SLOT SLOT[4]; /* four SLOTs (operators) */ + + UINT8 ALGO; /* algorithm */ + UINT8 FB; /* feedback shift */ + INT32 op1_out[2]; /* op1 output for feedback */ + + INT32 *connect1; /* SLOT1 output pointer */ + INT32 *connect3; /* SLOT3 output pointer */ + INT32 *connect2; /* SLOT2 output pointer */ + INT32 *connect4; /* SLOT4 output pointer */ + + INT32 *mem_connect;/* where to put the delayed sample (MEM) */ + INT32 mem_value; /* delayed sample (MEM) value */ + + INT32 pms; /* channel PMS */ + UINT8 ams; /* channel AMS */ + + UINT32 fc; /* fnum,blk:adjusted to sample rate */ + UINT8 kcode; /* key code: */ + UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ +} FM_CH; + + +typedef struct +{ + UINT8 index; /* this chip index (number of chip) */ + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ + double TimerBase; /* Timer base time */ +#if FM_BUSY_FLAG_SUPPORT + double BusyExpire; /* ExpireTime of Busy clear */ +#endif + UINT8 address; /* address register */ + UINT8 irq; /* interrupt level */ + UINT8 irqmask; /* irq mask */ + UINT8 status; /* status flag */ + UINT32 mode; /* mode CSM / 3SLOT */ + UINT8 prescaler_sel;/* prescaler selector */ + UINT8 fn_h; /* freq latch */ + int TA; /* timer a */ + int TAC; /* timer a counter */ + UINT8 TB; /* timer b */ + int TBC; /* timer b counter */ + /* local time tables */ + INT32 dt_tab[8][32];/* DeTune table */ + /* Extention Timer and IRQ handler */ + FM_TIMERHANDLER Timer_Handler; + FM_IRQHANDLER IRQ_Handler; +} FM_ST; + + + +/***********************************************************/ +/* OPN unit */ +/***********************************************************/ + +/* OPN 3slot struct */ +typedef struct +{ + UINT32 fc[3]; /* fnum3,blk3: calculated */ + UINT8 fn_h; /* freq3 latch */ + UINT8 kcode[3]; /* key code */ + UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ +} FM_3SLOT; + +/* OPN/A/B common state */ +typedef struct +{ + UINT8 type; /* chip type */ + FM_ST ST; /* general state */ + FM_3SLOT SL3; /* 3 slot mode state */ + FM_CH *P_CH; /* pointer of CH */ + unsigned int pan[6*2]; /* fm channels output masks (0xffffffff = enable) */ + + UINT32 eg_cnt; /* global envelope generator counter */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/64/3 */ + UINT32 eg_timer_add; /* step of eg_timer */ + UINT32 eg_timer_overflow;/* envelope generator timer overlfows every 3 samples (on real chip) */ + + + /* there are 2048 FNUMs that can be generated using FNUM/BLK registers + but LFO works with one more bit of a precision so we really need 4096 elements */ + + UINT32 fn_table[4096]; /* fnumber->increment counter */ + UINT32 fn_max; + + /* LFO */ + UINT32 lfo_cnt; + UINT32 lfo_inc; + + UINT32 lfo_freq[8]; /* LFO FREQ table */ +} FM_OPN; + + + +/* current chip state */ +static void *cur_chip = 0; /* pointer of current chip struct */ +static FM_ST *State; /* basic status */ +static FM_CH *cch[8]; /* pointer of FM channels */ + + +static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */ +static INT32 mem; /* one sample delay memory */ + +static INT32 out_fm[8]; /* outputs of working channels */ + +#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) +static INT32 out_adpcm[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 ADPCM */ +static INT32 out_delta[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 DELTAT*/ +#endif + +static UINT32 LFO_AM; /* runtime LFO calculations helper */ +static INT32 LFO_PM; /* runtime LFO calculations helper */ + +/* log output level */ +#define LOG_ERR 3 /* ERROR */ +#define LOG_WAR 2 /* WARNING */ +#define LOG_INF 1 /* INFORMATION */ +#define LOG_LEVEL LOG_INF + +#ifndef __RAINE__ +#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x +#endif + +/* limitter */ +#define Limit(val, max,min) { \ + if ( val > max ) val = max; \ + else if ( val < min ) val = min; \ +} + + +/* status set and IRQ handling */ +INLINE void FM_STATUS_SET(FM_ST *ST,int flag) +{ + /* set status flag */ + ST->status |= flag; + if ( !(ST->irq) && (ST->status & ST->irqmask) ) + { + ST->irq = 1; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,1); + } +} + +/* status reset and IRQ handling */ +INLINE void FM_STATUS_RESET(FM_ST *ST,int flag) +{ + /* reset status flag */ + ST->status &=~flag; + if ( (ST->irq) && !(ST->status & ST->irqmask) ) + { + ST->irq = 0; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,0); + } +} + +/* IRQ mask set */ +INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag) +{ + ST->irqmask = flag; + /* IRQ handling check */ + FM_STATUS_SET(ST,0); + FM_STATUS_RESET(ST,0); +} + +/* OPN Mode Register Write */ +INLINE void set_timers( FM_ST *ST, int n, int v ) +{ + /* b7 = CSM MODE */ + /* b6 = 3 slot mode */ + /* b5 = reset b */ + /* b4 = reset a */ + /* b3 = timer enable b */ + /* b2 = timer enable a */ + /* b1 = load b */ + /* b0 = load a */ + ST->mode = v; + + /* reset Timer b flag */ + if( v & 0x20 ) + FM_STATUS_RESET(ST,0x02); + /* reset Timer a flag */ + if( v & 0x10 ) + FM_STATUS_RESET(ST,0x01); + /* load b */ + if( v & 0x02 ) + { + if( ST->TBC == 0 ) + { + ST->TBC = ( 256-ST->TB)<<4; + /* External timer handler */ + if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,ST->TBC,ST->TimerBase); + } + } + else + { /* stop timer b */ + if( ST->TBC != 0 ) + { + ST->TBC = 0; + if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase); + } + } + /* load a */ + if( v & 0x01 ) + { + if( ST->TAC == 0 ) + { + ST->TAC = (1024-ST->TA); + /* External timer handler */ + if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,ST->TAC,ST->TimerBase); + } + } + else + { /* stop timer a */ + if( ST->TAC != 0 ) + { + ST->TAC = 0; + if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase); + } + } +} + + +/* Timer A Overflow */ +INLINE void TimerAOver(FM_ST *ST) +{ + /* set status (if enabled) */ + if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01); + /* clear or reload the counter */ + ST->TAC = (1024-ST->TA); + if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,0,ST->TAC,ST->TimerBase); +} +/* Timer B Overflow */ +INLINE void TimerBOver(FM_ST *ST) +{ + /* set status (if enabled) */ + if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02); + /* clear or reload the counter */ + ST->TBC = ( 256-ST->TB)<<4; + if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,1,ST->TBC,ST->TimerBase); +} + + +#if FM_INTERNAL_TIMER +/* ----- internal timer mode , update timer */ + +/* ---------- calculate timer A ---------- */ + #define INTERNAL_TIMER_A(ST,CSM_CH) \ + { \ + if( ST->TAC && (ST->Timer_Handler==0) ) \ + if( (ST->TAC -= (int)(ST->freqbase*4096)) <= 0 ) \ + { \ + TimerAOver( ST ); \ + /* CSM mode total level latch and auto key on */ \ + if( ST->mode & 0x80 ) \ + CSMKeyControll( CSM_CH ); \ + } \ + } +/* ---------- calculate timer B ---------- */ + #define INTERNAL_TIMER_B(ST,step) \ + { \ + if( ST->TBC && (ST->Timer_Handler==0) ) \ + if( (ST->TBC -= (int)(ST->freqbase*4096*step)) <= 0 ) \ + TimerBOver( ST ); \ + } +#else /* FM_INTERNAL_TIMER */ +/* external timer mode */ +#define INTERNAL_TIMER_A(ST,CSM_CH) +#define INTERNAL_TIMER_B(ST,step) +#endif /* FM_INTERNAL_TIMER */ + + + +#if FM_BUSY_FLAG_SUPPORT +INLINE UINT8 FM_STATUS_FLAG(FM_ST *ST) +{ + if( ST->BusyExpire ) + { + if( (ST->BusyExpire - FM_GET_TIME_NOW()) > 0) + return ST->status | 0x80; /* with busy */ + /* expire */ + ST->BusyExpire = 0; + } + return ST->status; +} +INLINE void FM_BUSY_SET(FM_ST *ST,int busyclock ) +{ + ST->BusyExpire = FM_GET_TIME_NOW() + (ST->TimerBase * busyclock); +} +#define FM_BUSY_CLEAR(ST) ((ST)->BusyExpire = 0) +#else +#define FM_STATUS_FLAG(ST) ((ST)->status) +#define FM_BUSY_SET(ST,bclock) {} +#define FM_BUSY_CLEAR(ST) {} +#endif + + + + +INLINE void FM_KEYON(UINT8 type, FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + if( !SLOT->key ) + { + SLOT->key = 1; + SLOT->phase = 0; /* restart Phase Generator */ + SLOT->ssgn = (SLOT->ssg & 0x04) >> 1; + + if ((type == TYPE_YM2612) || (type == TYPE_YM2608)) + { + if( (SLOT->ar + SLOT->ksr) < 32+62 ) + { + SLOT->state = EG_ATT; /* phase -> Attack */ + } + else + { + /* directly switch to Decay */ + SLOT->volume = MIN_ATT_INDEX; + SLOT->state = EG_DEC; + } + } + else + { + SLOT->state = EG_ATT; + } + } +} + +INLINE void FM_KEYOFF(FM_CH *CH , int s ) +{ + FM_SLOT *SLOT = &CH->SLOT[s]; + if( SLOT->key ) + { + SLOT->key = 0; + if (SLOT->state>EG_REL) + SLOT->state = EG_REL;/* phase -> Release */ + } +} + +/* set algorithm connection */ +static void setup_connection( FM_CH *CH, int ch ) +{ + INT32 *carrier = &out_fm[ch]; + + INT32 **om1 = &CH->connect1; + INT32 **om2 = &CH->connect3; + INT32 **oc1 = &CH->connect2; + + INT32 **memc = &CH->mem_connect; + + switch( CH->ALGO ){ + case 0: + /* M1---C1---MEM---M2---C2---OUT */ + *om1 = &c1; + *oc1 = &mem; + *om2 = &c2; + *memc= &m2; + break; + case 1: + /* M1------+-MEM---M2---C2---OUT */ + /* C1-+ */ + *om1 = &mem; + *oc1 = &mem; + *om2 = &c2; + *memc= &m2; + break; + case 2: + /* M1-----------------+-C2---OUT */ + /* C1---MEM---M2-+ */ + *om1 = &c2; + *oc1 = &mem; + *om2 = &c2; + *memc= &m2; + break; + case 3: + /* M1---C1---MEM------+-C2---OUT */ + /* M2-+ */ + *om1 = &c1; + *oc1 = &mem; + *om2 = &c2; + *memc= &c2; + break; + case 4: + /* M1---C1-+-OUT */ + /* M2---C2-+ */ + /* MEM: not used */ + *om1 = &c1; + *oc1 = carrier; + *om2 = &c2; + *memc= &mem; /* store it anywhere where it will not be used */ + break; + case 5: + /* +----C1----+ */ + /* M1-+-MEM---M2-+-OUT */ + /* +----C2----+ */ + *om1 = 0; /* special mark */ + *oc1 = carrier; + *om2 = carrier; + *memc= &m2; + break; + case 6: + /* M1---C1-+ */ + /* M2-+-OUT */ + /* C2-+ */ + /* MEM: not used */ + *om1 = &c1; + *oc1 = carrier; + *om2 = carrier; + *memc= &mem; /* store it anywhere where it will not be used */ + break; + case 7: + /* M1-+ */ + /* C1-+-OUT */ + /* M2-+ */ + /* C2-+ */ + /* MEM: not used*/ + *om1 = carrier; + *oc1 = carrier; + *om2 = carrier; + *memc= &mem; /* store it anywhere where it will not be used */ + break; + } + + CH->connect4 = carrier; +} + +/* set detune & multiple */ +INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v) +{ + SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; + SLOT->DT = ST->dt_tab[(v>>4)&7]; + CH->SLOT[SLOT1].Incr=-1; +} + +/* set total level */ +INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v) +{ + SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ +} + +/* set attack rate & key scale */ +INLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v) +{ + UINT8 old_KSR = SLOT->KSR; + + SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->KSR = 3-(v>>6); + if (SLOT->KSR != old_KSR) + { + CH->SLOT[SLOT1].Incr=-1; + } + + /* refresh Attack rate */ + if ((SLOT->ar + SLOT->ksr) < 32+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + if ((type == TYPE_YM2612) || (type == TYPE_YM2608)) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 17*RATE_STEPS; + } +} + +/* set decay rate */ +INLINE void set_dr(UINT8 type, FM_SLOT *SLOT,int v) +{ + SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; + if ((type == TYPE_YM2612) || (type == TYPE_YM2608)) + { + SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr]; + } + else + { + SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr]; + } + +} + +/* set sustain rate */ +INLINE void set_sr(UINT8 type, FM_SLOT *SLOT,int v) +{ + SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; + if ((type == TYPE_YM2612) || (type == TYPE_YM2608)) + { + SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr]; + } + else + { + SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr]; + } +} + +/* set release rate */ +INLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v) +{ + SLOT->sl = sl_table[ v>>4 ]; + + SLOT->rr = 34 + ((v&0x0f)<<2); + + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; + if ((type == TYPE_YM2612) || (type == TYPE_YM2608)) + { + SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr]; + } + else + { + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr]; + } +} + + + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p; + + p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p; + + p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +/* advance LFO to next sample */ +INLINE void advance_lfo(FM_OPN *OPN) +{ + UINT8 pos; + + if (OPN->lfo_inc) /* LFO enabled ? */ + { + OPN->lfo_cnt += OPN->lfo_inc; + + pos = (OPN->lfo_cnt >> LFO_SH) & 127; + + + /* update AM when LFO output changes */ + + /* actually I can't optimize is this way without rewritting chan_calc() + to use chip->lfo_am instead of global lfo_am */ + { + + /* triangle */ + /* AM: 0 to 126 step +2, 126 to 0 step -2 */ + if (pos<64) + LFO_AM = (pos&63) * 2; + else + LFO_AM = 126 - ((pos&63) * 2); + } + + /* PM works with 4 times slower clock */ + pos >>= 2; + /* update PM when LFO output changes */ + /*if (prev_pos != pos)*/ /* can't use global lfo_pm for this optimization, must be chip->lfo_pm instead*/ + { + LFO_PM = pos; + } + + } + else + { + LFO_AM = 0; + LFO_PM = 0; + } +} + +INLINE void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT) +{ + unsigned int out; + unsigned int swap_flag = 0; + unsigned int i; + + + i = 4; /* four operators per channel */ + do + { + /* reset SSG-EG swap flag */ + swap_flag = 0; + + switch(SLOT->state) + { + case EG_ATT: /* attack phase */ + if ( !(OPN->eg_cnt & ((1<eg_sh_ar)-1) ) ) + { + SLOT->volume += (~SLOT->volume * + (eg_inc[SLOT->eg_sel_ar + ((OPN->eg_cnt>>SLOT->eg_sh_ar)&7)]) + ) >>4; + + if (SLOT->volume <= MIN_ATT_INDEX) + { + SLOT->volume = MIN_ATT_INDEX; + SLOT->state = EG_DEC; + } + } + break; + + case EG_DEC: /* decay phase */ + if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608)) + { + if ( !(OPN->eg_cnt & ((1<eg_sh_d1r)-1) ) ) + { + if (SLOT->ssg&0x08) /* SSG EG type envelope selected */ + { + SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + } + else + { + SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + } + } + + /* check transition even if no volume update: this fixes the case when SL = MIN_ATT_INDEX */ + if ( SLOT->volume >= (INT32)(SLOT->sl) ) + { + SLOT->volume = (INT32)(SLOT->sl); + SLOT->state = EG_SUS; + } + } + else + { + if (SLOT->ssg&0x08) /* SSG EG type envelope selected */ + { + if ( !(OPN->eg_cnt & ((1<eg_sh_d1r)-1) ) ) + { + SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + + if ( SLOT->volume >= (INT32)(SLOT->sl) ) + SLOT->state = EG_SUS; + } + } + else + { + if ( !(OPN->eg_cnt & ((1<eg_sh_d1r)-1) ) ) + { + SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)]; + + if ( SLOT->volume >= (INT32)(SLOT->sl) ) + SLOT->state = EG_SUS; + } + } + } + break; + + case EG_SUS: /* sustain phase */ + if (SLOT->ssg&0x08) /* SSG EG type envelope selected */ + { + if ( !(OPN->eg_cnt & ((1<eg_sh_d2r)-1) ) ) + { + if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608)) + { + SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; + } + else + { + SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; + } + + if ( SLOT->volume >= ENV_QUIET ) + { + if ((OPN->type != TYPE_YM2612) && (OPN->type != TYPE_YM2608)) + { + SLOT->volume = MAX_ATT_INDEX; + } + + if (SLOT->ssg&0x01) /* bit 0 = hold */ + { + if (SLOT->ssgn&1) /* have we swapped once ??? */ + { + /* yes, so do nothing, just hold current level */ + } + else + swap_flag = (SLOT->ssg&0x02) | 1 ; /* bit 1 = alternate */ + + } + else + { + /* same as KEY-ON operation */ + + /* restart of the Phase Generator should be here */ + SLOT->phase = 0; + + if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608)) + { + if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/) + { + SLOT->state = EG_ATT; /* phase -> Attack */ + } + else + { + /* Attack Rate is maximal: directly switch to Decay (or Substain) */ + SLOT->volume = MIN_ATT_INDEX; + SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC; + } + } + else + { + /* phase -> Attack */ + SLOT->volume = 511; + SLOT->state = EG_ATT; + } + + swap_flag = (SLOT->ssg&0x02); /* bit 1 = alternate */ + } + } + } + } + else + { + if ( !(OPN->eg_cnt & ((1<eg_sh_d2r)-1) ) ) + { + SLOT->volume += eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)]; + + if ( SLOT->volume >= MAX_ATT_INDEX ) + { + SLOT->volume = MAX_ATT_INDEX; + /* do not change SLOT->state (verified on real chip) */ + } + } + + } + break; + + case EG_REL: /* release phase */ + if ( !(OPN->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + /* SSG-EG affects Release phase also (Nemesis) */ + if ((SLOT->ssg&0x08) && ((OPN->type = TYPE_YM2612) || (OPN->type = TYPE_YM2608))) + { + SLOT->volume += 6 * eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)]; + } + else + { + SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)]; + } + + if ( SLOT->volume >= MAX_ATT_INDEX ) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + } + break; + + } + + out = ((UINT32)SLOT->volume); + + /* negate output (changes come from alternate bit, init comes from attack bit) */ + if ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state > EG_REL)) + out ^= MAX_ATT_INDEX; + + /* we need to store the result here because we are going to change ssgn + in next instruction */ + SLOT->vol_out = out + SLOT->tl; + + /* reverse SLOT inversion flag */ + SLOT->ssgn ^= swap_flag; + + SLOT++; + i--; + }while (i); + +} + + + +#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask)) + +INLINE void update_phase_lfo_slot(FM_OPN *OPN, FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum) +{ + UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; + INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + LFO_PM ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + UINT8 blk; + UINT32 fn; + int kc, fc; + + block_fnum = block_fnum*2 + lfo_fn_table_index_offset; + + blk = (block_fnum&0x7000) >> 12; + fn = block_fnum & 0xfff; + + /* keyscale code */ + kc = (blk<<2) | opn_fktable[fn >> 8]; + + /* phase increment counter */ + fc = (OPN->fn_table[fn]>>(7-blk)) + SLOT->DT[kc]; + + /* detects frequency overflow (credits to Nemesis) */ + if (fc < 0) fc += OPN->fn_max; + + /* update phase */ + SLOT->phase += (fc * SLOT->mul) >> 1; + } + else /* LFO phase modulation = zero */ + { + SLOT->phase += SLOT->Incr; + } +} + +INLINE void update_phase_lfo_channel(FM_OPN *OPN, FM_CH *CH) +{ + UINT32 block_fnum = CH->block_fnum; + + UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; + INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + LFO_PM ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + UINT8 blk; + UINT32 fn; + int kc, fc, finc; + + block_fnum = block_fnum*2 + lfo_fn_table_index_offset; + + blk = (block_fnum&0x7000) >> 12; + fn = block_fnum & 0xfff; + + /* keyscale code */ + kc = (blk<<2) | opn_fktable[fn >> 8]; + + /* phase increment counter */ + fc = (OPN->fn_table[fn]>>(7-blk)); + + /* detects frequency overflow (credits to Nemesis) */ + finc = fc + CH->SLOT[SLOT1].DT[kc]; + + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1; + + finc = fc + CH->SLOT[SLOT2].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1; + + finc = fc + CH->SLOT[SLOT3].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1; + + finc = fc + CH->SLOT[SLOT4].DT[kc]; + if (finc < 0) finc += OPN->fn_max; + CH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1; + } + else /* LFO phase modulation = zero */ + { + CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr; + CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr; + CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr; + CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr; + } +} + +INLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum) +{ + unsigned int eg_out; + + UINT32 AM = LFO_AM >> CH->ams; + + + m2 = c1 = c2 = mem = 0; + + *CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ + + eg_out = volume_calc(&CH->SLOT[SLOT1]); + { + INT32 out = CH->op1_out[0] + CH->op1_out[1]; + CH->op1_out[0] = CH->op1_out[1]; + + if( !CH->connect1 ){ + /* algorithm 5 */ + mem = c1 = c2 = CH->op1_out[0]; + } + else + { + /* other algorithms */ + *CH->connect1 += CH->op1_out[0]; + } + + CH->op1_out[1] = 0; + if( eg_out < ENV_QUIET ) /* SLOT 1 */ + { + if (!CH->FB) + out=0; + + CH->op1_out[1] = op_calc1(CH->SLOT[SLOT1].phase, eg_out, (out<FB) ); + } + } + + eg_out = volume_calc(&CH->SLOT[SLOT3]); + if( eg_out < ENV_QUIET ) /* SLOT 3 */ + *CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2); + + eg_out = volume_calc(&CH->SLOT[SLOT2]); + if( eg_out < ENV_QUIET ) /* SLOT 2 */ + *CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1); + + eg_out = volume_calc(&CH->SLOT[SLOT4]); + if( eg_out < ENV_QUIET ) /* SLOT 4 */ + *CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2); + + + /* store current MEM */ + CH->mem_value = mem; + + /* update phase counters AFTER output calculations */ + if(CH->pms) + { + /* add support for 3 slot mode */ + if ((OPN->ST.mode & 0xC0) && (chnum == 2)) + { + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT1], CH->pms, OPN->SL3.block_fnum[1]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT2], CH->pms, OPN->SL3.block_fnum[2]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT3], CH->pms, OPN->SL3.block_fnum[0]); + update_phase_lfo_slot(OPN, &CH->SLOT[SLOT4], CH->pms, CH->block_fnum); + } + else update_phase_lfo_channel(OPN, CH); + } + else /* no LFO phase modulation */ + { + CH->SLOT[SLOT1].phase += CH->SLOT[SLOT1].Incr; + CH->SLOT[SLOT2].phase += CH->SLOT[SLOT2].Incr; + CH->SLOT[SLOT3].phase += CH->SLOT[SLOT3].Incr; + CH->SLOT[SLOT4].phase += CH->SLOT[SLOT4].Incr; + } +} + +/* update phase increment and envelope generator */ +INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc ) +{ + int ksr = kc >> SLOT->KSR; + + fc += SLOT->DT[kc]; + + /* detects frequency overflow (credits to Nemesis) */ + if (fc < 0) fc += OPN->fn_max; + + /* (frequency) phase increment counter */ + SLOT->Incr = (fc * SLOT->mul) >> 1; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ar + SLOT->ksr) < 32+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608)) + { + SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 17*RATE_STEPS; + } + + SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; + SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; + + if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608)) + { + SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr]; + SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr]; + SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr]; + } + else + { + SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr]; + SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr]; + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr]; + } + } +} + +/* update phase increment counters */ +/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */ +static void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH ) +{ + if( CH->SLOT[SLOT1].Incr==-1){ + int fc = CH->fc; + int kc = CH->kcode; + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT2] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT3] , fc , kc ); + refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT4] , fc , kc ); + } +} + +/* initialize time tables */ +static void init_timetables( FM_ST *ST , const UINT8 *dttable ) +{ + int i,d; + double rate; + +#if 0 + logerror("FM.C: samplerate=%8i chip clock=%8i freqbase=%f \n", + ST->rate, ST->clock, ST->freqbase ); +#endif + + /* DeTune table */ + for (d = 0;d <= 3;d++){ + for (i = 0;i <= 31;i++){ + rate = ((double)dttable[d*32 + i]) * SIN_LEN * ST->freqbase * (1<dt_tab[d][i] = (INT32) rate; + ST->dt_tab[d+4][i] = -ST->dt_tab[d][i]; +#if 0 + logerror("FM.C: DT [%2i %2i] = %8x \n", d, i, ST->dt_tab[d][i] ); +#endif + } + } + +} + + +static void reset_channels( FM_ST *ST , FM_CH *CH , int num ) +{ + int c,s; + + ST->mode = 0; /* normal mode */ + ST->TA = 0; + ST->TAC = 0; + ST->TB = 0; + ST->TBC = 0; + + for( c = 0 ; c < num ; c++ ) + { + CH[c].fc = 0; + for(s = 0 ; s < 4 ; s++ ) + { + CH[c].SLOT[s].ssg = 0; + CH[c].SLOT[s].ssgn = 0; + CH[c].SLOT[s].state= EG_OFF; + CH[c].SLOT[s].volume = MAX_ATT_INDEX; + CH[c].SLOT[s].vol_out= MAX_ATT_INDEX; + } + } +} + +/* initialize generic tables */ +static int init_tables(void) +{ + signed int i,x; + signed int n; + double o,m; + + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 2; /* 13 bits here (as in real chip) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + for (i=1; i<13; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + #if 0 + logerror("tl %04i", x); + for (i=0; i<13; i++) + logerror(", [%02i] %4x", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ]); + logerror("\n"); + } + #endif + } + /*logerror("FM.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ + + + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + /*logerror("FM.C: sin [%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[i],tl_tab[sin_tab[i]]);*/ + } + + /*logerror("FM.C: ENV_QUIET= %08x\n",ENV_QUIET );*/ + + + /* build LFO PM modulation table */ + for(i = 0; i < 8; i++) /* 8 PM depths */ + { + UINT8 fnum; + for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */ + { + UINT8 value; + UINT8 step; + UINT32 offset_depth = i; + UINT32 offset_fnum_bit; + UINT32 bit_tmp; + + for (step=0; step<8; step++) + { + value = 0; + for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */ + { + if (fnum & (1<SLOT[SLOT1].key) + { + FM_KEYON(type, CH,SLOT1); + FM_KEYOFF(CH, SLOT1); + } + if (!CH->SLOT[SLOT2].key) + { + FM_KEYON(type, CH,SLOT2); + FM_KEYOFF(CH, SLOT2); + } + if (!CH->SLOT[SLOT3].key) + { + FM_KEYON(type, CH,SLOT3); + FM_KEYOFF(CH, SLOT3); + } + if (!CH->SLOT[SLOT4].key) + { + FM_KEYON(type, CH,SLOT4); + FM_KEYOFF(CH, SLOT4); + } +} + +#ifdef _STATE_H +/* FM channel save , internal state only */ +static void FMsave_state_channel(const char *name,int num,FM_CH *CH,int num_ch) +{ + int slot , ch; + char state_name[20]; + const char slot_array[4] = { 1 , 3 , 2 , 4 }; + + for(ch=0;chop1_out , 2); + state_save_register_UINT32(state_name, num, "phasestep" , &CH->fc , 1); + /* slots */ + for(slot=0;slot<4;slot++) + { + FM_SLOT *SLOT = &CH->SLOT[slot]; + + sprintf(state_name,"%s.CH%d.SLOT%d",name,ch,slot_array[slot]); + state_save_register_UINT32(state_name, num, "phasecount" , &SLOT->phase, 1); + state_save_register_UINT8 (state_name, num, "state" , &SLOT->state, 1); + state_save_register_INT32 (state_name, num, "volume" , &SLOT->volume, 1); + } + } +} + +static void FMsave_state_st(const char *state_name,int num,FM_ST *ST) +{ +#if FM_BUSY_FLAG_SUPPORT + state_save_register_double(state_name, num, "BusyExpire", &ST->BusyExpire , 1); +#endif + state_save_register_UINT8 (state_name, num, "address" , &ST->address , 1); + state_save_register_UINT8 (state_name, num, "IRQ" , &ST->irq , 1); + state_save_register_UINT8 (state_name, num, "IRQ MASK" , &ST->irqmask , 1); + state_save_register_UINT8 (state_name, num, "status" , &ST->status , 1); + state_save_register_UINT32(state_name, num, "mode" , &ST->mode , 1); + state_save_register_UINT8 (state_name, num, "prescaler" , &ST->prescaler_sel , 1); + state_save_register_UINT8 (state_name, num, "freq latch", &ST->fn_h , 1); + state_save_register_int (state_name, num, "TIMER A" , &ST->TA ); + state_save_register_int (state_name, num, "TIMER Acnt", &ST->TAC ); + state_save_register_UINT8 (state_name, num, "TIMER B" , &ST->TB , 1); + state_save_register_int (state_name, num, "TIMER Bcnt", &ST->TBC ); +} +#endif /* _STATE_H */ + +#if BUILD_OPN + + + +/* prescaler set (and make time tables) */ +static void OPNSetPres(FM_OPN *OPN , int pres , int TimerPres, int SSGpres) +{ + int i; + + /* frequency base */ + OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock / OPN->ST.rate) / pres : 0; + +#if 0 + OPN->ST.rate = (double)OPN->ST.clock / pres; + OPN->ST.freqbase = 1.0; +#endif + + OPN->eg_timer_add = (1<ST.freqbase; + OPN->eg_timer_overflow = ( 3 ) * (1<ST.TimerBase = 1.0/((double)OPN->ST.clock / (double)TimerPres); + + /* SSG part prescaler set */ + if( SSGpres ) SSGClk( OPN->ST.index, OPN->ST.clock * 2 / SSGpres ); + + /* make time tables */ + init_timetables( &OPN->ST, dt_tab ); + + /* there are 2048 FNUMs that can be generated using FNUM/BLK registers + but LFO works with one more bit of a precision so we really need 4096 elements */ + /* calculate fnumber -> increment counter table */ + for(i = 0; i < 4096; i++) + { + /* freq table for octave 7 */ + /* OPN phase increment counter = 20bit */ + OPN->fn_table[i] = (UINT32)( (double)i * 32 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ +#if 0 + logerror("FM.C: fn_table[%4i] = %08x (dec=%8i)\n", + i, OPN->fn_table[i]>>6,OPN->fn_table[i]>>6 ); +#endif + } + + /* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */ + OPN->fn_max = (UINT32)( (double)0x20000 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) ); + + /* LFO freq. table */ + for(i = 0; i < 8; i++) + { + /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */ + /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */ + OPN->lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<ST.freqbase; +#if 0 + logerror("FM.C: lfo_freq[%i] = %08x (dec=%8i)\n", + i, OPN->lfo_freq[i],OPN->lfo_freq[i] ); +#endif + } +} + + + +/* write a OPN mode register 0x20-0x2f */ +static void OPNWriteMode(FM_OPN *OPN, int r, int v) +{ + UINT8 c; + FM_CH *CH; + + switch(r){ + case 0x21: /* Test */ + break; + case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */ + if( OPN->type & TYPE_LFOPAN ) + { + if (v&0x08) /* LFO enabled ? */ + { + OPN->lfo_inc = OPN->lfo_freq[v&7]; + } + else + { + OPN->lfo_inc = 0; + } + } + break; + case 0x24: /* timer A High 8*/ + OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2); + break; + case 0x25: /* timer A Low 2*/ + OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3); + break; + case 0x26: /* timer B */ + OPN->ST.TB = v; + break; + case 0x27: /* mode, timer control */ + set_timers( &(OPN->ST),OPN->ST.index,v ); + break; + case 0x28: /* key on / off */ + c = v & 0x03; + if( c == 3 ) break; + if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3; + CH = OPN->P_CH; + CH = &CH[c]; + if(v&0x10) FM_KEYON(OPN->type, CH,SLOT1); else FM_KEYOFF(CH,SLOT1); + if(v&0x20) FM_KEYON(OPN->type, CH,SLOT2); else FM_KEYOFF(CH,SLOT2); + if(v&0x40) FM_KEYON(OPN->type, CH,SLOT3); else FM_KEYOFF(CH,SLOT3); + if(v&0x80) FM_KEYON(OPN->type, CH,SLOT4); else FM_KEYOFF(CH,SLOT4); + break; + } +} + +/* write a OPN register (0x30-0xff) */ +static void OPNWriteReg(FM_OPN *OPN, int r, int v) +{ + FM_CH *CH; + FM_SLOT *SLOT; + + UINT8 c = OPN_CHAN(r); + + if (c == 3) return; /* 0xX3,0xX7,0xXB,0xXF */ + + if (r >= 0x100) c+=3; + + CH = OPN->P_CH; + CH = &CH[c]; + + SLOT = &(CH->SLOT[OPN_SLOT(r)]); + + switch( r & 0xf0 ) { + case 0x30: /* DET , MUL */ + set_det_mul(&OPN->ST,CH,SLOT,v); + break; + + case 0x40: /* TL */ + set_tl(CH,SLOT,v); + break; + + case 0x50: /* KS, AR */ + set_ar_ksr(OPN->type, CH,SLOT,v); + break; + + case 0x60: /* bit7 = AM ENABLE, DR */ + set_dr(OPN->type, SLOT,v); + + if(OPN->type & TYPE_LFOPAN) /* YM2608/2610/2610B/2612 */ + { + SLOT->AMmask = (v&0x80) ? ~0 : 0; + } + break; + + case 0x70: /* SR */ + set_sr(OPN->type, SLOT,v); + break; + + case 0x80: /* SL, RR */ + set_sl_rr(OPN->type, SLOT,v); + break; + + case 0x90: /* SSG-EG */ + SLOT->ssg = v&0x0f; + SLOT->ssgn = (v&0x04)>>1; /* bit 1 in ssgn = attack */ + + /* SSG-EG envelope shapes : + + E AtAlH + 1 0 0 0 \\\\ + + 1 0 0 1 \___ + + 1 0 1 0 \/\/ + ___ + 1 0 1 1 \ + + 1 1 0 0 //// + ___ + 1 1 0 1 / + + 1 1 1 0 /\/\ + + 1 1 1 1 /___ + + + E = SSG-EG enable + + + The shapes are generated using Attack, Decay and Sustain phases. + + Each single character in the diagrams above represents this whole + sequence: + + - when KEY-ON = 1, normal Attack phase is generated (*without* any + difference when compared to normal mode), + + - later, when envelope level reaches minimum level (max volume), + the EG switches to Decay phase (which works with bigger steps + when compared to normal mode - see below), + + - later when envelope level passes the SL level, + the EG swithes to Sustain phase (which works with bigger steps + when compared to normal mode - see below), + + - finally when envelope level reaches maximum level (min volume), + the EG switches to Attack phase again (depends on actual waveform). + + Important is that when switch to Attack phase occurs, the phase counter + of that operator will be zeroed-out (as in normal KEY-ON) but not always. + (I havent found the rule for that - perhaps only when the output level is low) + + The difference (when compared to normal Envelope Generator mode) is + that the resolution in Decay and Sustain phases is 4 times lower; + this results in only 256 steps instead of normal 1024. + In other words: + when SSG-EG is disabled, the step inside of the EG is one, + when SSG-EG is enabled, the step is four (in Decay and Sustain phases). + + Times between the level changes are the same in both modes. + + + Important: + Decay 1 Level (so called SL) is compared to actual SSG-EG output, so + it is the same in both SSG and no-SSG modes, with this exception: + + when the SSG-EG is enabled and is generating raising levels + (when the EG output is inverted) the SL will be found at wrong level !!! + For example, when SL=02: + 0 -6 = -6dB in non-inverted EG output + 96-6 = -90dB in inverted EG output + Which means that EG compares its level to SL as usual, and that the + output is simply inverted afterall. + + + The Yamaha's manuals say that AR should be set to 0x1f (max speed). + That is not necessary, but then EG will be generating Attack phase. + + */ + + + break; + + case 0xa0: + switch( OPN_SLOT(r) ){ + case 0: /* 0xa0-0xa2 : FNUM1 */ + { + UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v; + UINT8 blk = OPN->ST.fn_h>>3; + /* keyscale code */ + CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + CH->fc = OPN->fn_table[fn*2]>>(7-blk); + + /* store fnum in clear form for LFO PM calculations */ + CH->block_fnum = (blk<<11) | fn; + + CH->SLOT[SLOT1].Incr=-1; + } + break; + case 1: /* 0xa4-0xa6 : FNUM2,BLK */ + OPN->ST.fn_h = v&0x3f; + break; + case 2: /* 0xa8-0xaa : 3CH FNUM1 */ + if(r < 0x100) + { + UINT32 fn = (((UINT32)(OPN->SL3.fn_h&7))<<8) + v; + UINT8 blk = OPN->SL3.fn_h>>3; + /* keyscale code */ + OPN->SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + OPN->SL3.fc[c] = OPN->fn_table[fn*2]>>(7-blk); + OPN->SL3.block_fnum[c] = (blk<<11) | fn; + (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1; + } + break; + case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ + if(r < 0x100) + OPN->SL3.fn_h = v&0x3f; + break; + } + break; + + case 0xb0: + switch( OPN_SLOT(r) ){ + case 0: /* 0xb0-0xb2 : FB,ALGO */ + { + int feedback = (v>>3)&7; + CH->ALGO = v&7; + CH->FB = feedback ? feedback+6 : 0; + setup_connection( CH, c ); + } + break; + case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */ + if( OPN->type & TYPE_LFOPAN) + { + /* b0-2 PMS */ + CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */ + + /* b4-5 AMS */ + CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03]; + + /* PAN : b7 = L, b6 = R */ + OPN->pan[ c*2 ] = (v & 0x80) ? ~0 : 0; + OPN->pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0; + + } + break; + } + break; + } +} + +#endif /* BUILD_OPN */ + +#if BUILD_OPN_PRESCALER +/* + prescaler circuit (best guess to verified chip behaviour) + + +--------------+ +-sel2-+ + | +--|in20 | + +---+ | +-sel1-+ | | +M-CLK -+-|1/2|-+--|in10 | +---+ | out|--INT_CLOCK + | +---+ | out|-|1/3|-|in21 | + +----------|in11 | +---+ +------+ + +------+ + +reg.2d : sel2 = in21 (select sel2) +reg.2e : sel1 = in11 (select sel1) +reg.2f : sel1 = in10 , sel2 = in20 (clear selector) +reset : sel1 = in11 , sel2 = in21 (clear both) + +*/ +void OPNPrescaler_w(FM_OPN *OPN , int addr, int pre_divider) +{ + static const int opn_pres[4] = { 2*12 , 2*12 , 6*12 , 3*12 }; + static const int ssg_pres[4] = { 1 , 1 , 4 , 2 }; + int sel; + + switch(addr) + { + case 0: /* when reset */ + OPN->ST.prescaler_sel = 2; + break; + case 1: /* when postload */ + break; + case 0x2d: /* divider sel : select 1/1 for 1/3line */ + OPN->ST.prescaler_sel |= 0x02; + break; + case 0x2e: /* divider sel , select 1/3line for output */ + OPN->ST.prescaler_sel |= 0x01; + break; + case 0x2f: /* divider sel , clear both selector to 1/2,1/2 */ + OPN->ST.prescaler_sel = 0; + break; + } + sel = OPN->ST.prescaler_sel & 3; + /* update prescaler */ + OPNSetPres( OPN, opn_pres[sel]*pre_divider, + opn_pres[sel]*pre_divider, + ssg_pres[sel]*pre_divider ); +} +#endif /* BUILD_OPN_PRESCALER */ + +#if BUILD_YM2203 +/*****************************************************************************/ +/* YM2203 local section */ +/*****************************************************************************/ + +/* here's the virtual YM2203(OPN) */ +typedef struct +{ +#ifdef _STATE_H + UINT8 REGS[256]; /* registers */ +#endif + FM_OPN OPN; /* OPN state */ + FM_CH CH[3]; /* channel state */ +} YM2203; + +static YM2203 *FM2203=NULL; /* array of YM2203's */ +static int YM2203NumChips; /* number of chips */ + +/* Generate samples for one of the YM2203s */ +void YM2203UpdateOne(int num, INT16 *buffer, int length) +{ + YM2203 *F2203 = &(FM2203[num]); + FM_OPN *OPN = &(FM2203[num].OPN); + int i; + FMSAMPLE *buf = buffer; + + cur_chip = (void *)F2203; + State = &F2203->OPN.ST; + cch[0] = &F2203->CH[0]; + cch[1] = &F2203->CH[1]; + cch[2] = &F2203->CH[2]; + + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, cch[0] ); + refresh_fc_eg_chan( OPN, cch[1] ); + if( (State->mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[2]->SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); + } + }else refresh_fc_eg_chan( OPN, cch[2] ); + + + /* YM2203 doesn't have LFO so we must keep these globals at 0 level */ + LFO_AM = 0; + LFO_PM = 0; + + /* buffering */ + for (i=0; i < length ; i++) + { + /* clear outputs */ + out_fm[0] = 0; + out_fm[1] = 0; + out_fm[2] = 0; + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + OPN->eg_timer -= OPN->eg_timer_overflow; + OPN->eg_cnt++; + + advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]); + } + + /* calculate FM */ + chan_calc(OPN, cch[0], 0 ); + chan_calc(OPN, cch[1], 1 ); + chan_calc(OPN, cch[2], 2 ); + + /* buffering */ + { + int lt; + + lt = out_fm[0] + out_fm[1] + out_fm[2]; + + lt >>= FINAL_SH; + + Limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* buffering */ + buf[i] = lt; + } + + /* timer A control */ + INTERNAL_TIMER_A( State , cch[2] ) + } + INTERNAL_TIMER_B(State,length) +} + +/* ---------- reset one of chip ---------- */ +void YM2203ResetChip(int num) +{ + int i; + FM_OPN *OPN = &(FM2203[num].OPN); + + /* Reset Prescaler */ + OPNPrescaler_w(OPN, 0 , 1 ); + /* reset SSG section */ + SSGReset(OPN->ST.index); + /* status clear */ + FM_IRQMASK_SET(&OPN->ST,0x03); + FM_BUSY_CLEAR(&OPN->ST); + OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ + + OPN->eg_timer = 0; + OPN->eg_cnt = 0; + + FM_STATUS_RESET(&OPN->ST, 0xff); + + reset_channels( &OPN->ST , FM2203[num].CH , 3 ); + /* reset OPerator paramater */ + for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0); + for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); +} + +#ifdef _STATE_H +static void YM2203_postload(void) +{ + int num , r; + + for(num=0;numST.address = (v &= 0xff); + + /* Write register to SSG emulator */ + if( v < 16 ) SSGWrite(n,0,v); + + /* prescaler select : 2d,2e,2f */ + if( v >= 0x2d && v <= 0x2f ) + OPNPrescaler_w(OPN , v , 1); + } + else + { /* data port */ + int addr = OPN->ST.address; +#ifdef _STATE_H + FM2203[n].REGS[addr] = v; +#endif + switch( addr & 0xf0 ) + { + case 0x00: /* 0x00-0x0f : SSG section */ + /* Write data to SSG emulator */ + SSGWrite(n,a,v); + break; + case 0x20: /* 0x20-0x2f : Mode section */ + YM2203UpdateReq(n); + /* write register */ + OPNWriteMode(OPN,addr,v); + break; + default: /* 0x30-0xff : OPN section */ + YM2203UpdateReq(n); + /* write register */ + OPNWriteReg(OPN,addr,v); + } + FM_BUSY_SET(&OPN->ST,1); + } + return OPN->ST.irq; +} + +UINT8 YM2203Read(int n,int a) +{ + YM2203 *F2203 = &(FM2203[n]); + int addr = F2203->OPN.ST.address; + UINT8 ret = 0; + + if( !(a&1) ) + { /* status port */ + ret = FM_STATUS_FLAG(&F2203->OPN.ST); + } + else + { /* data port (only SSG) */ + if( addr < 16 ) ret = SSGRead(n); + } + return ret; +} + +int YM2203TimerOver(int n,int c) +{ + YM2203 *F2203 = &(FM2203[n]); + + if( c ) + { /* Timer B */ + TimerBOver( &(F2203->OPN.ST) ); + } + else + { /* Timer A */ + YM2203UpdateReq(n); + /* timer update */ + TimerAOver( &(F2203->OPN.ST) ); + /* CSM mode key,TL control */ + if( F2203->OPN.ST.mode & 0x80 ) + { /* CSM mode auto key on */ + CSMKeyControll( F2203->OPN.type, &(F2203->CH[2]) ); + } + } + return F2203->OPN.ST.irq; +} +#endif /* BUILD_YM2203 */ + + + +#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) + +/* ADPCM type A channel struct */ +typedef struct +{ + UINT8 flag; /* port state */ + UINT8 flagMask; /* arrived flag mask */ + UINT8 now_data; /* current ROM data */ + UINT32 now_addr; /* current ROM address */ + UINT32 now_step; + UINT32 step; + UINT32 start; /* sample data start address*/ + UINT32 end; /* sample data end address */ + UINT8 IL; /* Instrument Level */ + INT32 adpcm_acc; /* accumulator */ + INT32 adpcm_step; /* step */ + INT32 adpcm_out; /* (speedup) hiro-shi!! */ + INT8 vol_mul; /* volume in "0.75dB" steps */ + UINT8 vol_shift; /* volume in "-6dB" steps */ + INT32 *pan; /* &out_adpcm[OPN_xxxx] */ +} ADPCM_CH; + +/* here's the virtual YM2610 */ +typedef struct +{ +#ifdef _STATE_H + UINT8 REGS[512]; /* registers */ +#endif + FM_OPN OPN; /* OPN state */ + FM_CH CH[6]; /* channel state */ + UINT8 addr_A1; /* address line A1 */ + + /* ADPCM-A unit */ + UINT8 *pcmbuf; /* pcm rom buffer */ + UINT32 pcm_size; /* size of pcm rom */ + UINT8 adpcmTL; /* adpcmA total level */ + ADPCM_CH adpcm[6]; /* adpcm channels */ + UINT32 adpcmreg[0x30]; /* registers */ + UINT8 adpcm_arrivedEndAddress; + YM_DELTAT deltaT; /* Delta-T ADPCM unit */ + + UINT8 flagmask; /* YM2608 only */ + UINT8 irqmask; /* YM2608 only */ +} YM2610; + +/* here is the virtual YM2608 */ +typedef YM2610 YM2608; + + +/**** YM2610 ADPCM defines ****/ +#define ADPCM_SHIFT (16) /* frequency step rate */ +#define ADPCMA_ADDRESS_SHIFT 8 /* adpcm A address shift */ + +static UINT8 *pcmbufA; +static UINT32 pcmsizeA; + + +/* Algorithm and tables verified on real YM2608 and YM2610 */ + +/* usual ADPCM table (16 * 1.1^N) */ +static int steps[49] = +{ + 16, 17, 19, 21, 23, 25, 28, + 31, 34, 37, 41, 45, 50, 55, + 60, 66, 73, 80, 88, 97, 107, + 118, 130, 143, 157, 173, 190, 209, + 230, 253, 279, 307, 337, 371, 408, + 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552 +}; + +/* different from the usual ADPCM table */ +static int step_inc[8] = { -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9*16 }; + +/* speedup purposes only */ +static int jedi_table[ 49*16 ]; + + +static void Init_ADPCMATable(void){ + + int step, nib; + + for (step = 0; step < 49; step++) + { + /* loop over all nibbles and compute the difference */ + for (nib = 0; nib < 16; nib++) + { + int value = (2*(nib & 0x07) + 1) * steps[step] / 8; + jedi_table[step*16 + nib] = (nib&0x08) ? -value : value; + } + } +} + +/* ADPCM A (Non control type) : calculate one channel output */ +INLINE void ADPCMA_calc_chan( YM2610 *F2610, ADPCM_CH *ch ) +{ + UINT32 step; + UINT8 data; + + + ch->now_step += ch->step; + if ( ch->now_step >= (1<now_step >> ADPCM_SHIFT; + ch->now_step &= (1< instead of == */ + /* YM2610 checks lower 20 bits only, the 4 MSB bits are sample bank */ + /* Here we use 1<<21 to compensate for nibble calculations */ + + if ( (ch->now_addr & ((1<<21)-1)) == ((ch->end<<1) & ((1<<21)-1)) ) + { + ch->flag = 0; + F2610->adpcm_arrivedEndAddress |= ch->flagMask; + return; + } +#if 0 + if ( ch->now_addr > (pcmsizeA<<1) ) { + LOG(LOG_WAR,("YM2610: Attempting to play past adpcm rom size!\n" )); + return; + } +#endif + if ( ch->now_addr&1 ) + data = ch->now_data & 0x0f; + else + { + ch->now_data = *(pcmbufA+(ch->now_addr>>1)); + data = (ch->now_data >> 4) & 0x0f; + } + + ch->now_addr++; + + ch->adpcm_acc += jedi_table[ch->adpcm_step + data]; + + /* extend 12-bit signed int */ + if (ch->adpcm_acc & 0x800) + ch->adpcm_acc |= ~0xfff; + else + ch->adpcm_acc &= 0xfff; + + ch->adpcm_step += step_inc[data & 7]; + Limit( ch->adpcm_step, 48*16, 0*16 ); + + }while(--step); + + /* calc pcm * volume data */ + ch->adpcm_out = ((ch->adpcm_acc * ch->vol_mul) >> ch->vol_shift) & ~3; /* multiply, shift and mask out 2 LSB bits */ + } + + /* output for work of output channels (out_adpcm[OPNxxxx])*/ + *(ch->pan) += ch->adpcm_out; +} + +/* ADPCM type A Write */ +static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v) +{ + ADPCM_CH *adpcm = F2610->adpcm; + UINT8 c = r&0x07; + + F2610->adpcmreg[r] = v&0xff; /* stock data */ + switch( r ){ + case 0x00: /* DM,--,C5,C4,C3,C2,C1,C0 */ + if( !(v&0x80) ) + { + /* KEY ON */ + for( c = 0; c < 6; c++ ) + { + if( (v>>c)&1 ) + { + /**** start adpcm ****/ + adpcm[c].step = (UINT32)((float)(1<OPN.ST.freqbase)/3.0); + adpcm[c].now_addr = adpcm[c].start<<1; + adpcm[c].now_step = 0; + adpcm[c].adpcm_acc = 0; + adpcm[c].adpcm_step= 0; + adpcm[c].adpcm_out = 0; + adpcm[c].flag = 1; + + if(F2610->pcmbuf==NULL){ /* Check ROM Mapped */ + logerror("YM2608-YM2610: ADPCM-A rom not mapped\n"); + adpcm[c].flag = 0; + } else{ + if(adpcm[c].end >= F2610->pcm_size){ /* Check End in Range */ + logerror("YM2610: ADPCM-A end out of range: $%08x\n",adpcm[c].end); + /*adpcm[c].end = F2610->pcm_size-1;*/ /* JB: DO NOT uncomment this, otherwise you will break the comparison in the ADPCM_CALC_CHA() */ + } + if(adpcm[c].start >= F2610->pcm_size) /* Check Start in Range */ + { + logerror("YM2608-YM2610: ADPCM-A start out of range: $%08x\n",adpcm[c].start); + adpcm[c].flag = 0; + } + } + } + } + } + else + { + /* KEY OFF */ + for( c = 0; c < 6; c++ ) + if( (v>>c)&1 ) + adpcm[c].flag = 0; + } + break; + case 0x01: /* B0-5 = TL */ + F2610->adpcmTL = (v & 0x3f) ^ 0x3f; + for( c = 0; c < 6; c++ ) + { + int volume = F2610->adpcmTL + adpcm[c].IL; + + if ( volume >= 63 ) /* This is correct, 63 = quiet */ + { + adpcm[c].vol_mul = 0; + adpcm[c].vol_shift = 0; + } + else + { + adpcm[c].vol_mul = 15 - (volume & 7); /* so called 0.75 dB */ + adpcm[c].vol_shift = 1 + (volume >> 3); /* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */ + } + + /* calc pcm * volume data */ + adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3; /* multiply, shift and mask out low 2 bits */ + } + break; + default: + c = r&0x07; + if( c >= 0x06 ) return; + switch( r&0x38 ){ + case 0x08: /* B7=L,B6=R, B4-0=IL */ + { + int volume; + + adpcm[c].IL = (v & 0x1f) ^ 0x1f; + + volume = F2610->adpcmTL + adpcm[c].IL; + + if ( volume >= 63 ) /* This is correct, 63 = quiet */ + { + adpcm[c].vol_mul = 0; + adpcm[c].vol_shift = 0; + } + else + { + adpcm[c].vol_mul = 15 - (volume & 7); /* so called 0.75 dB */ + adpcm[c].vol_shift = 1 + (volume >> 3); /* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */ + } + + adpcm[c].pan = &out_adpcm[(v>>6)&0x03]; + + /* calc pcm * volume data */ + adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3; /* multiply, shift and mask out low 2 bits */ + } + break; + case 0x10: + case 0x18: + adpcm[c].start = ( (F2610->adpcmreg[0x18 + c]*0x0100 | F2610->adpcmreg[0x10 + c]) << ADPCMA_ADDRESS_SHIFT); + break; + case 0x20: + case 0x28: + adpcm[c].end = ( (F2610->adpcmreg[0x28 + c]*0x0100 | F2610->adpcmreg[0x20 + c]) << ADPCMA_ADDRESS_SHIFT); + adpcm[c].end += (1<flag , 1); + state_save_register_UINT8 (state_name, num, "data" , &adpcm->now_data , 1); + state_save_register_UINT32(state_name, num, "addr" , &adpcm->now_addr , 1); + state_save_register_UINT32(state_name, num, "step" , &adpcm->now_step , 1); + state_save_register_INT32 (state_name, num, "a_acc" , &adpcm->adpcm_acc , 1); + state_save_register_INT32 (state_name, num, "a_step" , &adpcm->adpcm_step, 1); + state_save_register_INT32 (state_name, num, "a_out" , &adpcm->adpcm_out , 1); + } +} +#endif /* _STATE_H */ + +#endif /* (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B) */ + + +#if BUILD_YM2608 +/*****************************************************************************/ +/* YM2608 local section */ +/*****************************************************************************/ +static YM2608 *FM2608=NULL; /* array of YM2608's */ +static int YM2608NumChips; /* total chip */ + + + + + +static unsigned int YM2608_ADPCM_ROM_addr[2*6] = { +0x0000, 0x01bf, /* bass drum */ +0x01c0, 0x043f, /* snare drum */ +0x0440, 0x1b7f, /* top cymbal */ +0x1b80, 0x1cff, /* high hat */ +0x1d00, 0x1f7f, /* tom tom */ +0x1f80, 0x1fff /* rim shot */ +}; + + +/* + This data is derived from the chip's output - internal ROM can't be read. + It was verified, using real YM2608, that this ADPCM stream produces 100% correct output signal. +*/ + +static unsigned char YM2608_ADPCM_ROM[0x2000] = { + +/* Source: 01BD.ROM */ +/* Length: 448 / 0x000001C0 */ + +0x88,0x08,0x08,0x08,0x00,0x88,0x16,0x76,0x99,0xB8,0x22,0x3A,0x84,0x3C,0xB1,0x54, +0x10,0xA9,0x98,0x32,0x80,0x33,0x9A,0xA7,0x4A,0xB4,0x58,0xBC,0x15,0x29,0x8A,0x97, +0x9B,0x44,0xAC,0x80,0x12,0xDE,0x13,0x1B,0xC0,0x58,0xC8,0x11,0x0A,0xA2,0x1A,0xA0, +0x00,0x98,0x0B,0x93,0x9E,0x92,0x0A,0x88,0xBE,0x14,0x1B,0x98,0x08,0xA1,0x4A,0xC1, +0x30,0xD9,0x33,0x98,0x10,0x89,0x17,0x1A,0x82,0x29,0x37,0x0C,0x83,0x50,0x9A,0x24, +0x1A,0x83,0x10,0x23,0x19,0xB3,0x72,0x8A,0x16,0x10,0x0A,0x93,0x70,0x99,0x23,0x99, +0x02,0x20,0x91,0x18,0x02,0x41,0xAB,0x24,0x18,0x81,0x99,0x4A,0xE8,0x28,0x9A,0x99, +0xA1,0x2F,0xA8,0x9D,0x90,0x08,0xCC,0xA3,0x1D,0xCA,0x82,0x0B,0xD8,0x08,0xB9,0x09, +0xBC,0xB8,0x00,0xBE,0x90,0x1B,0xCA,0x00,0x9B,0x8A,0xA8,0x91,0x0F,0xB3,0x3D,0xB8, +0x31,0x0B,0xA5,0x0A,0x11,0xA1,0x48,0x92,0x10,0x50,0x91,0x30,0x23,0x09,0x37,0x39, +0xA2,0x72,0x89,0x92,0x30,0x83,0x1C,0x96,0x28,0xB9,0x24,0x8C,0xA1,0x31,0xAD,0xA9, +0x13,0x9C,0xBA,0xA8,0x0B,0xBF,0xB8,0x9B,0xCA,0x88,0xDB,0xB8,0x19,0xFC,0x92,0x0A, +0xBA,0x89,0xAB,0xB8,0xAB,0xD8,0x08,0xAD,0xBA,0x33,0x9D,0xAA,0x83,0x3A,0xC0,0x40, +0xB9,0x15,0x39,0xA2,0x52,0x89,0x02,0x63,0x88,0x13,0x23,0x03,0x52,0x02,0x54,0x00, +0x11,0x23,0x23,0x35,0x20,0x01,0x44,0x41,0x80,0x24,0x40,0xA9,0x45,0x19,0x81,0x12, +0x81,0x02,0x11,0x21,0x19,0x02,0x61,0x8A,0x13,0x3A,0x10,0x12,0x23,0x8B,0x37,0x18, +0x91,0x24,0x10,0x81,0x34,0x20,0x05,0x32,0x82,0x53,0x20,0x14,0x33,0x31,0x34,0x52, +0x00,0x43,0x32,0x13,0x52,0x22,0x13,0x52,0x11,0x43,0x11,0x32,0x32,0x32,0x22,0x02, +0x13,0x12,0x89,0x22,0x19,0x81,0x81,0x08,0xA8,0x08,0x8B,0x90,0x1B,0xBA,0x8A,0x9B, +0xB9,0x89,0xCA,0xB9,0xAB,0xCA,0x9B,0xCA,0xB9,0xAB,0xDA,0x99,0xAC,0xBB,0x9B,0xAC, +0xAA,0xBA,0xAC,0xAB,0x9A,0xAA,0xAA,0xBA,0xB8,0xA9,0xBA,0x99,0xA9,0x9A,0xA0,0x8A, +0xA9,0x08,0x8A,0xA9,0x00,0x99,0x89,0x88,0x98,0x08,0x99,0x00,0x89,0x80,0x08,0x98, +0x00,0x88,0x88,0x80,0x90,0x80,0x90,0x80,0x81,0x99,0x08,0x88,0x99,0x09,0x00,0x1A, +0xA8,0x10,0x9A,0x88,0x08,0x0A,0x8A,0x89,0x99,0xA8,0x98,0xA9,0x99,0x99,0xA9,0x99, +0xAA,0x8A,0xAA,0x9B,0x8A,0x9A,0xA9,0x9A,0xBA,0x99,0x9A,0xAA,0x99,0x89,0xA9,0x99, +0x98,0x9A,0x98,0x88,0x09,0x89,0x09,0x08,0x08,0x09,0x18,0x18,0x00,0x12,0x00,0x11, +0x11,0x11,0x12,0x12,0x21,0x21,0x22,0x22,0x22,0x22,0x22,0x22,0x32,0x31,0x32,0x31, +0x32,0x32,0x21,0x31,0x21,0x32,0x21,0x12,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + +/* Source: 02SD.ROM */ +/* Length: 640 / 0x00000280 */ + +0x0A,0xDC,0x14,0x0B,0xBA,0xBC,0x01,0x0F,0xF5,0x2F,0x87,0x19,0xC9,0x24,0x1B,0xA1, +0x31,0x99,0x90,0x32,0x32,0xFE,0x83,0x48,0xA8,0xA9,0x23,0x19,0xBC,0x91,0x02,0x41, +0xDE,0x81,0x28,0xA8,0x0A,0xB1,0x72,0xDA,0x23,0xBC,0x04,0x19,0xB8,0x21,0x8A,0x03, +0x29,0xBA,0x14,0x21,0x0B,0xC0,0x43,0x08,0x91,0x50,0x93,0x0F,0x86,0x1A,0x91,0x18, +0x21,0xCB,0x27,0x0A,0xA1,0x42,0x8C,0xA9,0x21,0x10,0x08,0xAB,0x94,0x2A,0xDA,0x02, +0x8B,0x91,0x09,0x98,0xAE,0x80,0xA9,0x02,0x0A,0xE9,0x21,0xBB,0x15,0x20,0xBE,0x92, +0x42,0x09,0xA9,0x11,0x34,0x08,0x12,0x0A,0x27,0x29,0xA1,0x52,0x12,0x8E,0x92,0x28, +0x92,0x2B,0xD1,0x23,0xBF,0x81,0x10,0x99,0xA8,0x0A,0xC4,0x3B,0xB9,0xB0,0x00,0x62, +0xCF,0x92,0x29,0x92,0x2B,0xB1,0x1C,0xB2,0x72,0xAA,0x88,0x11,0x18,0x80,0x13,0x9E, +0x03,0x18,0xB0,0x60,0xA1,0x28,0x88,0x08,0x04,0x10,0x8F,0x96,0x19,0x90,0x01,0x09, +0xC8,0x50,0x91,0x8A,0x01,0xAB,0x03,0x50,0xBA,0x9D,0x93,0x68,0xBA,0x80,0x22,0xCB, +0x41,0xBC,0x92,0x60,0xB9,0x1A,0x95,0x4A,0xC8,0x20,0x88,0x33,0xAC,0x92,0x38,0x83, +0x09,0x80,0x16,0x09,0x29,0xD0,0x54,0x8C,0xA2,0x28,0x91,0x89,0x93,0x60,0xCD,0x85, +0x1B,0xA1,0x49,0x90,0x8A,0x80,0x34,0x0C,0xC9,0x14,0x19,0x98,0xA0,0x40,0xA9,0x21, +0xD9,0x34,0x0A,0xA9,0x10,0x23,0xCB,0x25,0xAA,0x25,0x9B,0x13,0xCD,0x16,0x09,0xA0, +0x80,0x01,0x19,0x90,0x88,0x21,0xAC,0x33,0x8B,0xD8,0x27,0x3B,0xB8,0x81,0x31,0x80, +0xAF,0x97,0x0A,0x82,0x0A,0xA0,0x21,0x89,0x8A,0xA2,0x32,0x8D,0xBB,0x87,0x19,0x21, +0xC9,0xBC,0x45,0x09,0x90,0x09,0xA1,0x24,0x1A,0xD0,0x10,0x08,0x11,0xA9,0x21,0xE8, +0x60,0xA9,0x14,0x0C,0xD1,0x32,0xAB,0x04,0x0C,0x81,0x90,0x29,0x83,0x9B,0x01,0x8F, +0x97,0x0B,0x82,0x18,0x88,0xBA,0x06,0x39,0xC8,0x23,0xBC,0x04,0x09,0x92,0x08,0x1A, +0xBB,0x74,0x8C,0x81,0x18,0x81,0x9D,0x83,0x41,0xCD,0x81,0x40,0x9A,0x90,0x10,0x12, +0x9C,0xA1,0x68,0xD8,0x33,0x9C,0x91,0x01,0x12,0xBE,0x02,0x09,0x12,0x99,0x9A,0x36, +0x0A,0xB0,0x30,0x88,0xA3,0x2D,0x12,0xBC,0x03,0x3A,0x11,0xBD,0x08,0xC8,0x62,0x80, +0x8B,0xD8,0x23,0x38,0xF9,0x12,0x08,0x99,0x91,0x21,0x99,0x85,0x2F,0xB2,0x30,0x90, +0x88,0xD9,0x53,0xAC,0x82,0x19,0x91,0x20,0xCC,0x96,0x29,0xC9,0x24,0x89,0x80,0x99, +0x12,0x08,0x18,0x88,0x99,0x23,0xAB,0x73,0xCB,0x33,0x9F,0x04,0x2B,0xB1,0x08,0x03, +0x1B,0xC9,0x21,0x32,0xFA,0x33,0xDB,0x02,0x33,0xAE,0xB9,0x54,0x8B,0xA1,0x20,0x89, +0x90,0x11,0x88,0x09,0x98,0x23,0xBE,0x37,0x8D,0x81,0x20,0xAA,0x34,0xBB,0x13,0x18, +0xB9,0x40,0xB1,0x18,0x83,0x8E,0xB2,0x72,0xBC,0x82,0x30,0xA9,0x9A,0x24,0x8B,0x27, +0x0E,0x91,0x20,0x90,0x08,0xB0,0x32,0xB9,0x21,0xB0,0xAC,0x45,0x9A,0xA1,0x50,0xA9, +0x80,0x0A,0x26,0x9B,0x11,0xBB,0x23,0x71,0xCB,0x12,0x10,0xB8,0x40,0xA9,0xA5,0x39, +0xC0,0x30,0xB2,0x20,0xAA,0xBA,0x76,0x1C,0xC1,0x48,0x98,0x80,0x18,0x81,0xAA,0x23, +0x9C,0xA2,0x32,0xAC,0x9A,0x43,0x9C,0x12,0xAD,0x82,0x72,0xBC,0x00,0x82,0x39,0xD1, +0x3A,0xB8,0x35,0x9B,0x10,0x40,0xF9,0x22,0x0A,0xC0,0x51,0xB9,0x82,0x18,0x98,0xA3, +0x79,0xD0,0x20,0x88,0x09,0x01,0x99,0x82,0x11,0x38,0xFC,0x33,0x09,0xC8,0x40,0xA9, +0x11,0x29,0xAA,0x94,0x3A,0xC2,0x4A,0xC0,0x89,0x52,0xBC,0x11,0x08,0x09,0xB8,0x71, +0xA9,0x08,0xA8,0x62,0x8D,0x92,0x10,0x00,0x9E,0x94,0x38,0xBA,0x13,0x88,0x90,0x4A, +0xE2,0x30,0xBA,0x02,0x00,0x19,0xD9,0x62,0xBB,0x04,0x0B,0xA3,0x68,0xB9,0x21,0x88, +0x9D,0x04,0x10,0x8C,0xC8,0x62,0x99,0xAA,0x24,0x1A,0x80,0x9A,0x14,0x9B,0x26,0x8C, +0x92,0x30,0xB9,0x09,0xA3,0x71,0xBB,0x10,0x19,0x82,0x39,0xDB,0x02,0x44,0x9F,0x10, + +/* Source: 04TOP.ROM */ +/* Length: 5952 / 0x00001740 */ + +0x07,0xFF,0x7C,0x3C,0x31,0xC6,0xC4,0xBB,0x7F,0x7F,0x7B,0x82,0x8A,0x4D,0x5F,0x7C, +0x3E,0x44,0xD2,0xB3,0xA0,0x19,0x1B,0x6C,0x81,0x28,0xC4,0xA1,0x1C,0x4B,0x18,0x00, +0x2A,0xA2,0x0A,0x7C,0x2A,0x00,0x01,0x89,0x98,0x48,0x8A,0x3C,0x28,0x2A,0x5B,0x3E, +0x3A,0x1A,0x3B,0x3D,0x4B,0x3B,0x4A,0x08,0x2A,0x1A,0x2C,0x4A,0x3B,0x82,0x99,0x3C, +0x5D,0x29,0x2B,0x39,0x0B,0x23,0xAB,0x1A,0x4C,0x79,0xA3,0x01,0xC1,0x2A,0x0A,0x38, +0xA7,0xB9,0x12,0x1F,0x29,0x08,0x82,0xA1,0x08,0xA9,0x42,0xAA,0x95,0xB3,0x90,0x81, +0x09,0xD4,0x1A,0x80,0x1B,0x07,0xB8,0x12,0x8E,0x49,0x81,0x92,0xD3,0x90,0xA1,0x2A, +0x02,0xE1,0xA3,0x99,0x02,0xB3,0x94,0xB3,0xB0,0xF4,0x98,0x93,0x90,0x13,0xE1,0x81, +0x99,0x38,0x91,0xA6,0xD3,0x99,0x94,0xC1,0x83,0xB1,0x92,0x98,0x49,0xC4,0xB2,0xA4, +0xA3,0xD0,0x1A,0x30,0xBA,0x59,0x02,0xD4,0xA0,0xA4,0xA2,0x8A,0x01,0x00,0xB7,0xA8, +0x18,0x2A,0x2B,0x1E,0x23,0xC8,0x1A,0x00,0x39,0xA0,0x18,0x92,0x4F,0x2D,0x5A,0x10, +0x89,0x81,0x2A,0x8B,0x6A,0x02,0x09,0xB3,0x8D,0x48,0x1B,0x80,0x19,0x34,0xF8,0x29, +0x0A,0x7B,0x2A,0x28,0x81,0x0C,0x02,0x1E,0x29,0x09,0x12,0xC2,0x94,0xE1,0x18,0x98, +0x02,0xC4,0x89,0x91,0x1A,0x20,0xA9,0x02,0x1B,0x48,0x8E,0x20,0x88,0x2D,0x08,0x59, +0x1B,0x02,0xA3,0xB1,0x8A,0x1E,0x58,0x80,0xC2,0xB6,0x88,0x91,0x88,0x11,0xA1,0xA3, +0xE2,0x01,0xB0,0x19,0x11,0x09,0xF4,0x88,0x09,0x88,0x19,0x89,0x12,0xF1,0x2A,0x28, +0x8C,0x25,0x99,0xA4,0x98,0x39,0xA1,0x00,0xD0,0x58,0xAA,0x59,0x01,0x0C,0x00,0x2B, +0x00,0x08,0x89,0x6B,0x69,0x90,0x01,0x90,0x98,0x12,0xB3,0xF3,0xA0,0x89,0x02,0x3B, +0x0C,0x50,0xA9,0x4E,0x6B,0x19,0x28,0x09,0xA2,0x08,0x2F,0x20,0x88,0x92,0x8A,0x11, +0xC4,0x93,0xF1,0x18,0x88,0x11,0xF2,0x80,0x92,0xA8,0x02,0xA8,0xB7,0xB3,0xA3,0xA0, +0x88,0x1A,0x40,0xE2,0x91,0x19,0x88,0x18,0x91,0x83,0xC1,0xB5,0x92,0xA9,0xC6,0x90, +0x01,0xC2,0x81,0x98,0x03,0xF0,0x00,0x2C,0x2A,0x92,0x2C,0x83,0x1F,0x3A,0x29,0x00, +0xB8,0x70,0xAB,0x69,0x18,0x89,0x10,0x0D,0x12,0x0B,0x88,0x4A,0x3A,0x9B,0x70,0xA8, +0x28,0x2F,0x2A,0x3A,0x1B,0x85,0x88,0x8B,0x6A,0x29,0x00,0x91,0x91,0x1B,0x7C,0x29, +0x01,0x88,0x90,0x19,0x2B,0x2B,0x00,0x39,0xA8,0x5E,0x21,0x89,0x91,0x09,0x3A,0x6F, +0x2A,0x18,0x18,0x8B,0x50,0x89,0x2B,0x19,0x49,0x88,0x29,0xF5,0x89,0x08,0x09,0x12, +0xAA,0x15,0xB0,0x82,0xAC,0x38,0x00,0x3F,0x81,0x10,0xB0,0x49,0xA2,0x81,0x3A,0xC8, +0x87,0x90,0xC4,0xA3,0x99,0x19,0x83,0xE1,0x84,0xE2,0xA2,0x90,0x80,0x93,0xB5,0xC4, +0xB3,0xA1,0x0A,0x18,0x92,0xC4,0xA0,0x93,0x0C,0x3A,0x18,0x01,0x1E,0x20,0xB1,0x82, +0x8C,0x03,0xB5,0x2E,0x82,0x19,0xB2,0x1B,0x1B,0x6B,0x4C,0x19,0x12,0x8B,0x5A,0x11, +0x0C,0x3A,0x2C,0x18,0x3D,0x08,0x2A,0x5C,0x18,0x00,0x88,0x3D,0x29,0x80,0x2A,0x09, +0x00,0x7A,0x0A,0x10,0x0B,0x69,0x98,0x10,0x81,0x3F,0x00,0x18,0x19,0x91,0xB7,0x9A, +0x28,0x8A,0x48,0x92,0xF3,0xA2,0x88,0x98,0x87,0xA1,0x88,0x80,0x81,0x95,0xD1,0xA3, +0x1B,0x1C,0x39,0x10,0xA1,0x2A,0x0B,0x7A,0x4B,0x80,0x13,0xC1,0xD1,0x2B,0x2A,0x85, +0xB2,0xA2,0x93,0xB2,0xD3,0x80,0xD1,0x18,0x08,0x08,0xB7,0x98,0x81,0x3F,0x01,0x88, +0x01,0xE2,0x00,0x9A,0x59,0x08,0x10,0xC3,0x99,0x84,0xA9,0xA5,0x91,0x91,0x91,0x80, +0xB5,0x94,0xC0,0x01,0x98,0x09,0x84,0xB0,0x80,0x7A,0x08,0x18,0x90,0xA8,0x6A,0x1C, +0x39,0x2A,0xB7,0x98,0x19,0x10,0x2A,0xA1,0x10,0xBD,0x39,0x18,0x2D,0x39,0x3F,0x10, +0x3F,0x01,0x09,0x19,0x0A,0x38,0x8C,0x40,0xB3,0xB4,0x93,0xAD,0x20,0x2B,0xD4,0x81, +0xC3,0xB0,0x39,0xA0,0x23,0xD8,0x04,0xB1,0x9B,0xA7,0x1A,0x92,0x08,0xA5,0x88,0x81, +0xE2,0x01,0xB8,0x01,0x81,0xC1,0xC7,0x90,0x92,0x80,0xA1,0x97,0xA0,0xA2,0x82,0xB8, +0x18,0x00,0x9C,0x78,0x98,0x83,0x0B,0x0B,0x32,0x7D,0x19,0x10,0xA1,0x19,0x09,0x0A, +0x78,0xA8,0x10,0x1B,0x29,0x29,0x1A,0x14,0x2F,0x88,0x4A,0x1B,0x10,0x10,0xAB,0x79, +0x0D,0x49,0x18,0xA0,0x02,0x1F,0x19,0x3A,0x2B,0x11,0x8A,0x88,0x79,0x8A,0x20,0x49, +0x9B,0x58,0x0B,0x28,0x18,0xA9,0x3A,0x7D,0x00,0x29,0x88,0x82,0x3D,0x1A,0x38,0xBA, +0x15,0x09,0xAA,0x51,0x8B,0x83,0x3C,0x8A,0x58,0x1B,0xB5,0x01,0xBB,0x50,0x19,0x99, +0x24,0xCA,0x21,0x1B,0xA2,0x87,0xA8,0xB1,0x68,0xA1,0xA6,0xA2,0xA8,0x29,0x8B,0x24, +0xB4,0xE2,0x92,0x8A,0x00,0x19,0x93,0xB5,0xB4,0xB1,0x81,0xB1,0x03,0x9A,0x82,0xA7, +0x90,0xD6,0xA0,0x80,0x1B,0x29,0x01,0xA4,0xE1,0x18,0x0A,0x2A,0x29,0x92,0xC7,0xA8, +0x81,0x19,0x89,0x30,0x10,0xE0,0x30,0xB8,0x10,0x0C,0x1A,0x79,0x1B,0xA7,0x80,0xA0, +0x00,0x0B,0x28,0x18,0xB1,0x85,0x1E,0x00,0x20,0xA9,0x18,0x18,0x1C,0x13,0xBC,0x15, +0x99,0x2E,0x12,0x00,0xE1,0x00,0x0B,0x3B,0x21,0x90,0x06,0xC9,0x2A,0x49,0x0A,0x18, +0x20,0xD1,0x3C,0x08,0x00,0x83,0xC9,0x41,0x8E,0x18,0x08,0x02,0xA0,0x09,0xA4,0x7B, +0x90,0x19,0x2A,0x10,0x2A,0xA8,0x71,0xBA,0x10,0x4A,0x0E,0x22,0xB2,0xB2,0x1B,0x8C, +0x78,0x1A,0xB5,0x93,0xA9,0x1B,0x49,0x19,0x29,0xA3,0xC6,0x88,0xAA,0x32,0x0D,0x1B, +0x22,0x08,0xC2,0x18,0xB9,0x79,0x3F,0x01,0x10,0xA9,0x84,0x1C,0x09,0x21,0xB0,0xA7, +0x0A,0x99,0x50,0x0C,0x81,0x28,0x8B,0x48,0x2E,0x00,0x08,0x99,0x38,0x5B,0x88,0x14, +0xA9,0x08,0x11,0xAA,0x72,0xC1,0xB3,0x09,0x8A,0x05,0x91,0xF2,0x81,0xA1,0x09,0x02, +0xF2,0x92,0x99,0x1A,0x49,0x80,0xC5,0x90,0x90,0x18,0x09,0x12,0xA1,0xF2,0x81,0x98, +0xC6,0x91,0xA0,0x11,0xA0,0x94,0xB4,0xF2,0x81,0x8B,0x03,0x80,0xD2,0x93,0xA8,0x88, +0x69,0xA0,0x03,0xB8,0x88,0x32,0xBC,0x97,0x80,0xB1,0x3B,0x1A,0xA6,0x00,0xD1,0x01, +0x0B,0x3B,0x30,0x9B,0x31,0x3E,0x92,0x19,0x8A,0xD3,0x5C,0x1B,0x41,0xA0,0x93,0xA2, +0xAF,0x39,0x4C,0x01,0x92,0xA8,0x81,0x3C,0x0D,0x78,0x98,0x00,0x19,0x0A,0x20,0x2D, +0x29,0x3C,0x1B,0x48,0x88,0x99,0x7A,0x2D,0x29,0x2A,0x82,0x80,0xA8,0x49,0x3E,0x19, +0x11,0x98,0x82,0x9A,0x3B,0x28,0x2F,0x20,0x4C,0x90,0x29,0x19,0x9A,0x7A,0x29,0x28, +0x98,0x88,0x33,0xCD,0x11,0x3A,0xC1,0xA4,0xA0,0xC4,0x82,0xC8,0x50,0x98,0xB2,0x21, +0xC0,0xB6,0x98,0x82,0x80,0x9C,0x23,0x00,0xF8,0x30,0xA8,0x1A,0x68,0xA8,0x86,0x9A, +0x01,0x2A,0x0A,0x97,0x91,0xC1,0x18,0x89,0x02,0x83,0xE0,0x01,0x8B,0x29,0x30,0xE2, +0x91,0x0B,0x18,0x3B,0x1C,0x11,0x28,0xAC,0x78,0x80,0x93,0x91,0xA9,0x49,0x8B,0x87, +0x90,0x99,0x3D,0x5A,0x81,0x08,0xA1,0x11,0x2F,0x1A,0x21,0x9B,0x15,0xA2,0xB0,0x11, +0xC0,0x91,0x5B,0x98,0x24,0xA2,0xF2,0x92,0x8B,0x6A,0x18,0x81,0xB5,0xB1,0x88,0x4C, +0x00,0x00,0xA4,0xC1,0x2B,0x1A,0x59,0x0A,0x02,0x80,0x1E,0x02,0x08,0xB3,0x80,0x9A, +0x23,0xB8,0xF2,0x84,0xAB,0x01,0x48,0x90,0xA7,0x90,0x0A,0x29,0x09,0x95,0x99,0xA0, +0x59,0x2B,0x00,0x97,0xB0,0x29,0x89,0x2A,0x03,0xD0,0xB7,0x1B,0x81,0x00,0xA6,0xB1, +0x90,0x09,0x48,0xC0,0x11,0x00,0x8A,0x00,0x5B,0x83,0x9A,0x18,0x2F,0x3C,0x18,0x11, +0xA9,0x04,0x1A,0x4F,0x01,0x98,0x81,0x09,0x09,0x4A,0x18,0xB4,0xA2,0x0B,0x59,0x90, +0x3B,0x49,0xBC,0x40,0x6A,0x88,0x3A,0x08,0x3E,0x3A,0x80,0x93,0xB0,0xE1,0x5A,0x00, +0xA4,0xB3,0xE3,0x90,0x0D,0x38,0x09,0x82,0xC4,0xA1,0xB1,0x4C,0x18,0x10,0x91,0xB2, +0x13,0xEA,0x34,0x99,0x88,0xA6,0x89,0x92,0x91,0xC1,0x20,0xB2,0xC2,0x86,0xD2,0xB3, +0x80,0xB2,0x08,0x09,0x87,0x91,0xC0,0x11,0x89,0x90,0x28,0xB9,0x79,0x19,0xA4,0x82, +0xD0,0x03,0x0C,0xA3,0xA5,0xB2,0xB2,0x1B,0x29,0x13,0xF1,0xB4,0x81,0x9D,0x38,0x00, +0xC4,0xA1,0x89,0x59,0x1A,0x81,0xA4,0xA9,0x1C,0x6A,0x19,0x02,0xB1,0x1A,0x4A,0x0B, +0x78,0x89,0x81,0x1C,0x2A,0x29,0x4A,0xA3,0x3E,0x1C,0x49,0x1A,0x08,0x21,0xAE,0x28, +0x4B,0x19,0x20,0x8C,0x10,0x3A,0xAB,0x26,0x8B,0x18,0x59,0x99,0x13,0xA2,0xAB,0x79, +0x2F,0x18,0x10,0xB2,0x80,0x1B,0x4D,0x5A,0x80,0x82,0x98,0x81,0x80,0x09,0xA5,0x90, +0x91,0x03,0xC2,0xE2,0x81,0xA8,0x82,0x09,0xC6,0xA3,0xB1,0x08,0x5B,0x08,0x05,0xD1, +0xA2,0x89,0x2A,0x28,0x91,0xA6,0x88,0xB0,0x49,0x80,0x09,0x08,0x88,0x07,0xB8,0x05, +0x99,0x81,0x88,0x18,0xE2,0x00,0xC3,0x18,0x0D,0x10,0x30,0xD0,0x93,0x8A,0x09,0x10, +0x2F,0x11,0x90,0xA1,0x20,0x9B,0xB1,0x73,0xC8,0x94,0x98,0x3B,0x01,0x0C,0x30,0x19, +0xF8,0x12,0x90,0xBA,0x78,0x0A,0x11,0x98,0xA0,0x79,0x8A,0x30,0x2B,0xC2,0x11,0x0D, +0x09,0x7A,0x00,0x82,0xB9,0x01,0x7A,0x89,0x21,0x09,0xA1,0x0A,0x7C,0x10,0x88,0xB5, +0x88,0x0A,0x2B,0x69,0x1A,0x10,0xA0,0x5B,0x19,0x1A,0x10,0x19,0x1A,0x6C,0x20,0x90, +0xA5,0x98,0x1B,0x0A,0x69,0x82,0xD1,0x18,0x09,0x19,0x2A,0x93,0xD4,0x9A,0x01,0x49, +0xA2,0xA2,0x82,0xD8,0x22,0xAA,0x97,0xA9,0x2D,0x38,0x2A,0xB6,0x80,0x90,0x0A,0x3C, +0x82,0x94,0xB8,0x21,0x0E,0x2A,0x22,0xB8,0x00,0x4F,0x2B,0x3A,0x81,0xA1,0x29,0x2C, +0x6A,0x13,0xD1,0xA2,0x98,0x28,0x0C,0x01,0xD5,0x08,0xA9,0x31,0xB3,0xB0,0xA7,0xB0, +0x29,0x1B,0x87,0xA2,0xA1,0xB2,0x4A,0x89,0x11,0xC3,0xF3,0x98,0x08,0x03,0xA0,0xA3, +0xC5,0x90,0xB3,0xB5,0xB4,0xB8,0x02,0x91,0x91,0xD3,0xA4,0xC1,0x1B,0x82,0x28,0xA4, +0xD1,0x94,0x8A,0x28,0x08,0x03,0xE0,0x80,0xD4,0x90,0x91,0xA1,0x3B,0x3D,0x02,0xE4, +0xA1,0x92,0x89,0x1A,0x4B,0x95,0xB3,0x90,0x99,0x6A,0x0A,0x30,0xA1,0x93,0xA6,0xA9, +0x85,0x8B,0x82,0x10,0xB1,0xA3,0x94,0xF8,0x38,0x9A,0x30,0x1A,0x8B,0xA7,0x89,0x01, +0x5B,0x19,0x18,0x11,0xF0,0x18,0x1C,0x39,0x19,0x0C,0x12,0x1C,0x2A,0x7B,0x3A,0x88, +0x2B,0x18,0x2B,0x5C,0x20,0x92,0x8D,0x38,0x8A,0x3A,0x5B,0x2E,0x3A,0x2B,0x10,0x12, +0xBB,0x6A,0x4D,0x18,0x10,0xB1,0x81,0x2A,0x8B,0x79,0x80,0x01,0x0A,0x09,0x5B,0x2D, +0x84,0x8A,0x08,0x02,0xA2,0x91,0x82,0xE8,0x50,0x9B,0x85,0xA3,0xB0,0xA3,0x1B,0x02, +0x18,0xF3,0xA2,0x88,0xAB,0x53,0xD1,0xB4,0xA3,0x09,0x09,0x18,0xD4,0x08,0xB0,0x09, +0x58,0xD1,0x82,0x89,0x81,0x1A,0x18,0x05,0xB9,0xC3,0x30,0xC0,0x95,0x80,0xC3,0x89, +0x89,0x13,0x88,0xF2,0x93,0x0E,0x18,0x01,0x92,0xA5,0xB8,0x2A,0x39,0xAA,0x33,0x9A, +0xB1,0x11,0xF5,0xA1,0xA1,0x0A,0x50,0xB8,0x03,0xC4,0xA0,0x4E,0x29,0x10,0x88,0xC2, +0x1A,0x39,0x1D,0x28,0x98,0x94,0x0E,0x10,0x2A,0x3C,0x02,0x2D,0x1B,0x4B,0x3B,0x49, +0x19,0xA9,0x48,0x2F,0x29,0x10,0x89,0x02,0x0C,0x10,0x09,0xB9,0x70,0x1B,0x8A,0x50, +0xA8,0x2B,0x49,0x89,0x69,0x88,0x95,0x89,0x90,0x92,0x4C,0x19,0x82,0xC1,0x01,0x80, +0xA0,0x2B,0x7A,0x81,0x10,0xC2,0xB7,0x98,0x88,0x19,0x2C,0x03,0xB1,0xA4,0xA1,0x0C, +0x3B,0x78,0x88,0x85,0xB1,0xA0,0x1B,0x3A,0x4A,0x08,0x94,0x81,0xF1,0x80,0x00,0x0C, +0x59,0x09,0x18,0x90,0xA6,0x92,0x8C,0x1A,0x79,0x92,0xA8,0x00,0x81,0x2E,0x2A,0x13, +0xA2,0xB0,0xA5,0x88,0x88,0x89,0x11,0x19,0xA0,0xF3,0x82,0xB0,0x83,0x5F,0x2A,0x01, +0xA1,0x94,0xB0,0x09,0x78,0x98,0xA3,0xA6,0xA0,0x91,0x80,0x93,0x98,0xC1,0x12,0x18, +0xC9,0x17,0xA0,0xA0,0x1A,0x21,0x80,0x99,0xD4,0x30,0x9D,0x00,0x10,0x2F,0x08,0x1C, +0x21,0x08,0xB4,0xC3,0x2B,0xA9,0x52,0xD2,0xA3,0xD1,0x09,0x10,0x8B,0x24,0x92,0xD1, +0x80,0x19,0xA0,0x2C,0x12,0x49,0xAA,0xB6,0x95,0xB8,0x08,0x3A,0x2B,0x01,0xF3,0xB3, +0x0B,0x09,0x79,0x18,0xA2,0xA4,0xA0,0x18,0x0C,0x20,0x08,0xA9,0x16,0x0C,0x00,0x1B, +0x08,0x2B,0x7B,0x01,0x01,0xB9,0x59,0x19,0x8B,0x45,0xA8,0x80,0x0C,0x1A,0x41,0x1E, +0x00,0x28,0xA8,0x5A,0x00,0xC1,0x49,0x99,0x21,0x1D,0x08,0x85,0x99,0x95,0x89,0x90, +0x11,0x90,0xD1,0x28,0xB2,0xA7,0x99,0x81,0x02,0xAC,0x13,0x81,0xB2,0xA6,0xA9,0x28, +0x1C,0xB1,0x33,0xD1,0xC1,0x58,0xA8,0x14,0xB0,0xB7,0x91,0xA0,0x82,0x89,0xC2,0x28, +0xA1,0xB2,0x49,0xD2,0x94,0xC8,0x12,0x80,0x99,0x85,0x08,0xD3,0x09,0xA2,0xB3,0x1E, +0x08,0x21,0xB9,0x23,0xB4,0xAB,0x41,0xAC,0x87,0x09,0xA2,0xC5,0x0B,0x2A,0x5A,0x91, +0x20,0x9A,0x89,0x78,0x9B,0x31,0x89,0x80,0x29,0x0A,0xB7,0x3C,0x98,0x48,0x1D,0x00, +0x01,0xB0,0x20,0x2F,0x29,0x4A,0x89,0x94,0x1C,0x88,0x28,0x2B,0x10,0x88,0x9A,0x71, +0x9A,0x08,0x4A,0x2F,0x18,0x2B,0x18,0x02,0xA8,0x4B,0x7A,0x99,0x48,0x80,0xA8,0x20, +0x1D,0x40,0xA8,0x10,0x08,0xA8,0xC5,0x88,0xC2,0x18,0x88,0x2A,0x12,0xF3,0x82,0xD8, +0x20,0x0A,0x09,0xA6,0x98,0x04,0xB9,0x11,0x18,0xC3,0xE1,0x29,0xA1,0x11,0xC1,0x03, +0xE2,0x9A,0x33,0xA9,0xB5,0x98,0x92,0xA1,0x02,0xF8,0x21,0xA8,0x10,0x02,0xC1,0xB7, +0x1B,0x90,0x5B,0x3C,0x83,0x93,0xE0,0x19,0x1A,0x11,0x11,0xF1,0x92,0x89,0x19,0x2C, +0x2C,0x41,0x99,0x92,0x90,0x3F,0x18,0x4B,0x00,0x08,0xD2,0x01,0xB2,0xAA,0x78,0x09, +0x01,0x91,0xA2,0x98,0x2F,0x3A,0x2C,0x01,0x00,0x93,0xE0,0x28,0x2C,0x2B,0x01,0x12, +0xE1,0x80,0xB3,0x3D,0x3A,0x0A,0x50,0x98,0xC2,0xA0,0x11,0xAA,0x30,0x87,0x90,0xC2, +0x29,0x88,0x38,0xC8,0xB5,0x90,0xBA,0x70,0x1A,0x02,0x94,0xD0,0x80,0x1A,0x82,0xA6, +0xB0,0x91,0x18,0xB3,0x00,0x13,0xF1,0xA2,0xC1,0x82,0xB0,0x00,0x15,0x0B,0xD3,0x02, +0xA8,0x91,0x2B,0x1F,0x49,0x88,0xA6,0x80,0x88,0x08,0x1B,0xA5,0x80,0xB9,0x06,0x0B, +0x90,0x21,0x9D,0x48,0x18,0xA0,0x15,0xC9,0x82,0x2B,0x1A,0x42,0x9A,0xC4,0x39,0xBC, +0x69,0x00,0xA0,0x29,0x8C,0x39,0x59,0x08,0x09,0x49,0xA9,0x6B,0x81,0x00,0x98,0xB0, +0x68,0x3D,0x81,0x88,0x18,0x19,0x1D,0x12,0x80,0xB2,0x3A,0x3F,0x85,0x92,0xD0,0x00, +0x0A,0x19,0x12,0xF1,0x02,0x9B,0x19,0x40,0xB9,0x11,0x02,0xF2,0x1A,0x08,0x94,0x0A, +0xC2,0x83,0x0B,0xB4,0xA4,0xC0,0x32,0xD8,0x86,0x98,0x90,0x95,0x89,0xA3,0x83,0xC2, +0x92,0xE1,0x92,0x82,0xD9,0x03,0x08,0xA9,0x85,0x92,0xA2,0x80,0xE0,0x30,0x8B,0xB3, +0x87,0x89,0x90,0x83,0xA0,0x08,0x92,0x93,0x3E,0xAB,0x43,0x89,0xE3,0x80,0x83,0x2F, +0x00,0xA3,0x80,0xC9,0x22,0x3F,0x08,0x81,0x0B,0x33,0x9A,0xA3,0x7B,0x0C,0x29,0x4A, +0x1B,0x21,0xAA,0x70,0x1B,0x0D,0x48,0x1A,0x81,0x88,0xB1,0x39,0x3F,0x08,0x58,0xA0, +0x81,0x1A,0x1A,0x2B,0x6D,0x11,0x0A,0x91,0x01,0x1A,0x98,0x5A,0x0C,0x03,0xB1,0x84, +0xA3,0xAD,0x58,0x2A,0xA1,0x84,0xB1,0xA0,0x5C,0x2B,0x13,0xA8,0x95,0x83,0xE8,0x10, +0x81,0xB0,0x00,0xC2,0x96,0xA0,0x91,0x00,0x2C,0x90,0x30,0xF2,0x80,0xA8,0x39,0x21, +0xC1,0x03,0xAC,0x39,0x7C,0x29,0x91,0x1A,0x00,0x19,0x2C,0x3A,0x93,0xB0,0x29,0x8F, +0x28,0x02,0x93,0xF3,0xA9,0x01,0x03,0xE0,0x08,0x09,0x1D,0x58,0xA1,0x83,0xA9,0x6B, +0x2A,0x3C,0x21,0x89,0xC2,0x2C,0x4B,0x8A,0x50,0x81,0x98,0xA8,0x32,0x0C,0x8E,0x24, +0x0B,0x1A,0x81,0x92,0xA1,0x4F,0x18,0x3A,0x0A,0xB4,0x18,0x2E,0x39,0x82,0x19,0xD3, +0xD0,0x28,0x1B,0x11,0x98,0x07,0xAA,0x28,0x00,0x88,0xB4,0x89,0x1B,0x1F,0x22,0x00, +0xB3,0xC9,0x33,0xAB,0x2B,0xB5,0x48,0x98,0x98,0xA7,0x10,0xD2,0xC1,0x23,0xCA,0x93, +0xC6,0x80,0xA1,0x88,0x02,0x89,0xE2,0x09,0x38,0xBA,0x40,0x89,0x21,0xD8,0x49,0x10, +0x8D,0x02,0x90,0xC3,0x9A,0x24,0x89,0x08,0x84,0xA5,0x9C,0x10,0x11,0x9C,0x88,0x30, +0x3C,0xA1,0x94,0x58,0x8C,0x0B,0x69,0x29,0x9A,0x81,0x12,0x2B,0x8B,0x79,0x94,0xB0, +0xC1,0x84,0xC2,0x99,0x25,0x99,0x11,0xA2,0x93,0xE4,0x99,0x80,0x0A,0x00,0x10,0xB7, +0xB0,0x31,0xBA,0x3C,0x21,0xB3,0xF1,0x18,0xA0,0x2A,0x20,0xA3,0x06,0xE8,0x28,0xA1, +0xB4,0x08,0x0B,0x11,0x4B,0xB7,0x90,0xA5,0x98,0x3D,0x19,0x02,0xA1,0xC4,0xB2,0x19, +0x28,0xC0,0xA5,0x92,0xB1,0xA3,0x0A,0x0A,0x08,0x2B,0x70,0xC4,0xB3,0x00,0xBC,0x4B, +0x39,0x12,0xE3,0xA0,0x00,0x3F,0x18,0x29,0x94,0xD1,0x19,0x09,0x00,0xA1,0x83,0x99, +0x9B,0x35,0x80,0xC4,0xB1,0x6A,0x1A,0x1C,0x29,0x38,0x0E,0x19,0x5A,0x1A,0x82,0x8A, +0x59,0x2A,0x2E,0x20,0x88,0xA8,0x3A,0x38,0x3D,0x00,0xB3,0x29,0xAD,0x49,0x10,0x0C, +0x01,0x01,0xA3,0x8F,0x85,0x09,0x1B,0x88,0x10,0xA3,0xD2,0x90,0x3C,0x5C,0x39,0x03, +0xD1,0xA0,0x00,0x2A,0x0B,0x04,0xA7,0x90,0xA0,0x11,0x90,0x99,0x83,0xB4,0xB1,0xF1, +0x84,0x88,0x90,0x18,0x18,0xD3,0xD2,0xB3,0xA0,0x1A,0x21,0xA7,0xB2,0xB3,0x92,0x9A, +0x22,0xB9,0x28,0x38,0xBD,0x87,0x2A,0xB1,0x13,0x0D,0x0A,0x38,0xC9,0x24,0xC0,0x19, +0x23,0x0F,0x01,0x88,0xC0,0x2A,0x82,0x18,0x28,0xF0,0x18,0x2A,0x29,0x4B,0x35,0xB8, +0xA3,0x9D,0x18,0x1B,0x40,0x00,0x9A,0x5C,0x3A,0x09,0x2F,0x38,0x8A,0x3B,0x3B,0x11, +0x5C,0x19,0x2B,0x4A,0x08,0x0A,0x3D,0x20,0x4F,0x3A,0x19,0x2A,0x18,0x4D,0x1B,0x3A, +0x11,0x0D,0x3A,0x3C,0x4B,0x93,0x81,0xAA,0x6B,0x4A,0x18,0x00,0xC3,0xC3,0x9A,0x59, +0x2A,0x1B,0xA7,0xA1,0x81,0x88,0x88,0x58,0xB2,0xB1,0x2B,0x83,0xD4,0x81,0x08,0x0F, +0x00,0x20,0xC2,0xE2,0x80,0x08,0x1C,0x29,0x04,0xB1,0xA2,0x01,0x1C,0x91,0x00,0x0C, +0x49,0xB0,0x43,0xF2,0x99,0x39,0x3F,0x00,0x81,0x94,0xC1,0x09,0x1A,0x69,0x90,0x80, +0x94,0xAA,0x20,0x2A,0x91,0xB1,0x39,0x7A,0x38,0xD1,0x10,0x8A,0x8C,0x5A,0x01,0xB5, +0x98,0x80,0x2A,0x0B,0x32,0x92,0xF1,0x81,0x9A,0x23,0x8A,0xA3,0xB7,0x09,0x03,0x08, +0xD0,0x94,0x9A,0x09,0x01,0x93,0xB7,0xC2,0x8C,0x3A,0x83,0x99,0x05,0xA0,0x0B,0x29, +0x93,0xE5,0x80,0x89,0x38,0x90,0x8A,0xD7,0xA1,0x19,0x1B,0x48,0x98,0x92,0xC3,0xA1, +0x09,0x3F,0x02,0x0C,0x22,0xC3,0xB2,0xA1,0x01,0x9F,0x4A,0x01,0xA3,0xD3,0xB0,0x28, +0x3F,0x29,0x20,0xA2,0xC2,0xB1,0x08,0x5A,0x98,0x13,0xD2,0xC1,0x01,0xB2,0x80,0x3D, +0x03,0xC1,0x89,0x96,0x90,0x90,0x3A,0x1A,0x9A,0x32,0xB6,0xA2,0x8E,0x4A,0x28,0x8A, +0x84,0xA2,0x8A,0x2D,0x49,0x09,0x88,0x18,0x30,0x9D,0x2C,0x23,0xB1,0x0C,0x92,0x2D, +0x39,0x82,0xC4,0x2E,0x10,0x1A,0x10,0xB9,0x48,0x19,0x39,0xBA,0x34,0xDA,0x2D,0x48, +0x1A,0xA6,0x98,0x83,0x9A,0x1D,0x38,0x04,0xD0,0x18,0x90,0x2C,0x11,0x93,0xD3,0x9A, +0x11,0x08,0x82,0xF1,0x01,0xA0,0x2A,0x93,0xD3,0xB4,0xB8,0x82,0x2F,0x11,0xA3,0xB3, +0xA8,0x3B,0x09,0x23,0x96,0xC8,0x3B,0x3F,0x93,0x82,0xA1,0x90,0x3F,0x28,0x81,0xD1, +0x93,0x08,0x2D,0x18,0x91,0xB3,0xB5,0x98,0x2A,0x2B,0x84,0xB1,0x5B,0x8A,0x31,0x18, +0x80,0x8B,0x7E,0x39,0x2B,0x02,0xC1,0x8B,0x6C,0x49,0x09,0x10,0xA1,0x08,0x01,0x0C, +0x20,0xA1,0x09,0x4F,0x18,0x00,0x01,0xA0,0x5C,0x1B,0x5B,0x10,0x92,0x90,0x2B,0x5A, +0x3D,0x18,0x91,0x19,0x98,0x2D,0x39,0x89,0x2D,0x3A,0x48,0x2C,0x11,0xB5,0x9A,0x19, +0x5B,0x28,0x90,0x95,0x98,0x89,0x2B,0x40,0x08,0x90,0xF3,0x0A,0x08,0xA6,0x80,0x91, +0xB2,0xA0,0x02,0xF2,0xA1,0xB7,0x89,0x81,0x82,0x91,0xB1,0x21,0xAB,0x32,0xE9,0x04, +0xA2,0x8D,0x12,0x91,0xA3,0xA3,0xD2,0x8B,0x39,0xD1,0x84,0xE2,0x90,0x00,0x2B,0x29, +0xA3,0xD4,0xA1,0x91,0x1D,0x5A,0x08,0x19,0x11,0x99,0x08,0x18,0x49,0x0F,0x18,0x10, +0x82,0xF1,0x00,0x89,0x2F,0x3A,0x01,0xB3,0xC2,0x81,0x3F,0x29,0x08,0x10,0xA1,0xA1, +0x3B,0x5D,0x19,0x28,0x0B,0x38,0x82,0x91,0x19,0xBD,0x3B,0x7A,0x80,0x12,0xB3,0xE0, +0x0B,0x6A,0x01,0x88,0xA4,0x08,0x0B,0x08,0x59,0x80,0x80,0x1D,0x49,0x89,0x00,0x84, +0x99,0x1A,0x2B,0x32,0xE3,0xB4,0xA9,0x3A,0x99,0x31,0xE3,0xAA,0x58,0x3B,0x88,0x95, +0xC0,0x18,0x4A,0x09,0x30,0xF2,0xA3,0x1C,0x1B,0x49,0x00,0xD3,0xB2,0xA0,0x18,0x11, +0x92,0xD3,0xB2,0x91,0x80,0xE7,0xA1,0x91,0x98,0x19,0x22,0xC2,0xD2,0x18,0x8D,0x3B, +0x10,0xA5,0x91,0x98,0x02,0x3E,0x80,0x01,0x90,0xAA,0x13,0xF1,0x02,0xD1,0x08,0x19, +0x49,0xB4,0x91,0xB4,0x99,0x2A,0x0C,0x32,0xC0,0x05,0x88,0x0B,0x80,0x2C,0x81,0x10, +0x0B,0x51,0xA9,0x19,0x05,0xBF,0x28,0x20,0xE1,0x90,0x80,0x28,0x19,0x08,0x26,0xB1, +0xA1,0x18,0x88,0x2A,0xF0,0x12,0x8A,0xB3,0x14,0x1B,0xD4,0xD8,0x10,0x08,0x8A,0x17, +0xA0,0x98,0x2B,0x3A,0x29,0x48,0xA4,0x99,0x0E,0x4A,0x12,0x8B,0x31,0x8B,0x4E,0x1A, +0x11,0xB5,0x89,0x91,0x29,0x89,0xC2,0x97,0x90,0x0A,0x19,0x11,0x91,0xC1,0xD5,0x08, +0x89,0x20,0x91,0xB1,0x1A,0x2D,0x18,0x29,0xD2,0x3B,0x3E,0x3A,0x2A,0x90,0x82,0x1C, +0x49,0x3B,0x93,0xB6,0xC8,0x4C,0x02,0x91,0x93,0xF2,0x88,0x2D,0x28,0x81,0x82,0xC1, +0x89,0x2D,0x6B,0x19,0x82,0x80,0x18,0x8B,0x39,0x39,0xC8,0x3A,0x6A,0x0A,0x22,0xD2, +0x09,0x2C,0x1A,0x68,0x92,0xE2,0x89,0x2A,0x2A,0x30,0xC2,0xA3,0xB4,0x1D,0x2A,0x09, +0x93,0x18,0xF2,0x89,0x28,0xB3,0x01,0x8F,0x18,0x11,0xA1,0x93,0x90,0xD1,0x7A,0x20, +0xC3,0xA2,0xA8,0x88,0x1D,0x28,0xA5,0xA2,0xA2,0x0B,0x29,0x2B,0x87,0xC1,0x80,0x0A, +0x19,0x01,0x12,0xF1,0x10,0x80,0x0A,0x18,0x08,0x2F,0x4A,0x02,0x89,0x1B,0x29,0x5D, +0x4C,0x08,0x82,0xA1,0x0A,0x3A,0x4B,0x29,0xC6,0xC3,0x09,0x09,0x88,0x39,0x98,0x82, +0xA5,0x1A,0x30,0x11,0xBD,0x3F,0x12,0x8B,0x28,0xC3,0x88,0x3F,0x2B,0x3B,0x48,0xA1, +0x80,0x8A,0x4D,0x39,0x01,0x93,0xA2,0xF1,0x19,0x19,0x0A,0x02,0xB2,0x8B,0x24,0xD2, +0x4B,0x12,0xC8,0x2E,0x10,0xB5,0x89,0x01,0x09,0x1C,0x2A,0x03,0xD4,0x91,0x98,0x99, +0x11,0x2B,0xE4,0x00,0x00,0x01,0xE0,0xA5,0x89,0x99,0x31,0x18,0xD0,0xB7,0x98,0x18, +0x0A,0x10,0x94,0xC2,0x90,0x18,0x00,0x99,0x87,0xA0,0x90,0x2A,0x3C,0x02,0xB8,0xC1, +0x79,0x1A,0x20,0x08,0xA1,0xD2,0x1C,0x29,0x03,0xD1,0x29,0x99,0x2C,0x50,0xB3,0xD1, +0x08,0x09,0x3C,0x10,0x04,0xB2,0x0D,0x2B,0x59,0x80,0x90,0x01,0x0F,0x3A,0x18,0x01, +0xA2,0x9B,0x5B,0x3D,0x81,0x03,0xD2,0x98,0x59,0x90,0x81,0x92,0xB4,0x8B,0x1B,0x40, +0xB2,0xB5,0x08,0x4B,0x01,0x09,0xD1,0x91,0x8B,0x7A,0x10,0xB3,0xC3,0x99,0x49,0x1A, +0x29,0xB5,0xA2,0xAB,0x40,0x81,0x19,0xB7,0xB0,0x20,0x2B,0xD4,0x88,0xA1,0x91,0x3C, +0x82,0x37,0xD3,0xB1,0x8A,0x1B,0x30,0xB3,0xF4,0xA1,0x91,0x09,0x10,0x03,0xD0,0x83, +0xA9,0x8F,0x10,0x01,0x90,0x18,0x80,0x20,0x2B,0xF1,0x28,0x99,0x2A,0x41,0xF0,0x12, +0xAA,0x83,0x82,0xD1,0xC1,0x08,0x89,0x59,0x09,0x83,0x87,0xB0,0x2A,0x4D,0x18,0x09, +0x19,0xB3,0x4B,0x3F,0x39,0x19,0x09,0x01,0x89,0x03,0x1F,0x00,0x1A,0x0B,0x10,0x68, +0xA0,0x18,0x8C,0x6A,0x09,0x08,0x97,0xA1,0x81,0x1B,0x2B,0x4C,0x03,0xB4,0xA8,0x92, +0x4B,0x3C,0xA1,0x81,0x95,0xA8,0x81,0x12,0xBB,0x92,0x45,0xB9,0x93,0xF4,0x88,0x0A, +0x2D,0x28,0x00,0xA3,0xA3,0x8A,0x3F,0x48,0xB1,0x92,0xB4,0xA8,0x30,0x80,0xD3,0x80, +0xD1,0x19,0x3B,0xC4,0x81,0xC1,0x29,0x0D,0x20,0x13,0xC8,0xB4,0x4C,0x09,0x00,0x82, +0xC2,0x3B,0x0D,0x30,0x0B,0x12,0xF0,0x1B,0x20,0x0A,0xA6,0x80,0x0A,0x4A,0x4A,0x80, +0x94,0xB1,0x2E,0x3B,0x1A,0x10,0x93,0x10,0x4C,0x3D,0x08,0x82,0xC9,0x19,0x6A,0x2B, +0x38,0xD1,0x08,0x19,0x2A,0x5A,0x82,0xB1,0x8D,0x29,0x78,0x09,0x82,0x0A,0x2C,0x1B, +0x19,0x41,0xB8,0x8C,0x79,0x2B,0x11,0x88,0x82,0x91,0xDC,0x28,0x11,0xB0,0x11,0x18, +0xC9,0x62,0xA1,0x91,0x98,0x3B,0x3A,0xB0,0xF4,0x01,0xC0,0x29,0x39,0xF8,0x95,0x91, +0x88,0x88,0x91,0x03,0xA1,0xE2,0x18,0x82,0xD1,0xA2,0xD1,0x80,0x19,0x20,0x83,0xB1, +0xE3,0x80,0x91,0x4D,0x1A,0x03,0xB2,0x09,0x18,0xD1,0x19,0x09,0x92,0xA6,0xA0,0xB6, +0xB2,0x8B,0x38,0x10,0x42,0xD3,0xD0,0xA8,0x20,0x2C,0x10,0x01,0xB1,0xB4,0xAB,0x5B, +0x79,0x80,0x10,0x1A,0xA8,0x3D,0x18,0x20,0xB3,0x8F,0x18,0x01,0x00,0x09,0xF3,0x89, +0x69,0x88,0x81,0x91,0x08,0xE1,0x1A,0x08,0x11,0x81,0x1E,0x29,0xA0,0x01,0x00,0x90, +0x3E,0x7B,0x18,0x82,0xC3,0xA1,0x2A,0x2C,0x5B,0x81,0xA5,0x90,0x81,0x00,0x0B,0x1A, +0x1C,0x2C,0x32,0xC0,0xF3,0x80,0x2D,0x2A,0x10,0x02,0xE4,0xC1,0x89,0x4A,0x09,0x01, +0x03,0xD2,0x98,0x2A,0x39,0x8A,0x89,0x26,0xB1,0xB2,0x12,0xC0,0x0A,0x5A,0x18,0x98, +0xF3,0x92,0x99,0x99,0x79,0x01,0xB5,0xA1,0x80,0x80,0x90,0x83,0xA0,0xE2,0x81,0x29, +0x93,0x8A,0x0A,0x6A,0x1F,0x18,0x02,0xC8,0x01,0x19,0x3B,0x4A,0x98,0x17,0xA8,0x0D, +0x38,0xA1,0x91,0x10,0xA2,0x2B,0x4C,0xA6,0x81,0xBA,0x21,0x4C,0x80,0x21,0xD1,0x92, +0x2C,0x08,0x30,0x9F,0x93,0x2A,0x89,0x03,0x8B,0x87,0x0A,0x0D,0x12,0x98,0xA4,0x93, +0xBB,0x59,0x18,0xA1,0x32,0xE9,0x84,0x08,0x8A,0x02,0xA1,0x91,0x4B,0xB4,0x20,0x88, +0xF0,0x3A,0x1A,0x88,0x87,0xB1,0x92,0x0A,0x08,0x6B,0x83,0xC3,0x91,0xC0,0x2B,0x79, +0x08,0x8A,0x84,0xA0,0x89,0x40,0x1B,0xA1,0x39,0x98,0x17,0xC2,0xA2,0x12,0xCD,0x20, +0x89,0x92,0x25,0xB0,0x2D,0x3A,0x8B,0x58,0x2A,0xA0,0x4C,0x08,0x30,0xAE,0x82,0x59, +0x89,0x1A,0x10,0xC2,0x18,0x2C,0x40,0x1E,0x01,0xA3,0x8A,0x81,0x2C,0x29,0x29,0xA9, +0x13,0x51,0xAD,0x12,0x89,0x8F,0x18,0x2C,0x39,0x00,0xC1,0x10,0x3C,0x2A,0x41,0xC8, +0xA2,0x91,0x0A,0x6C,0x10,0x12,0x88,0xE8,0x30,0x91,0x81,0xD8,0x01,0x1B,0x0D,0x07, +0x00,0xA8,0x92,0x0A,0x28,0xD2,0xC3,0x02,0xAA,0x94,0x81,0xB4,0xB3,0x1A,0x0B,0x13, +0xF9,0x16,0xA1,0x8A,0x59,0x19,0x02,0xC1,0x91,0x8B,0x3D,0x18,0x3B,0xA4,0x94,0x80, +0x99,0x88,0x1C,0x79,0x0A,0x02,0x03,0xF8,0x90,0x39,0x5B,0x19,0x02,0xC3,0x90,0xBB, +0x58,0x6A,0x09,0x02,0x89,0x91,0x88,0x1A,0x69,0x8A,0x19,0x15,0xA0,0xA2,0x00,0x9A, +0x6B,0x49,0x88,0xA3,0x92,0xBB,0x6B,0x3D,0x38,0x01,0x98,0x91,0x3F,0x09,0x18,0x20, +0x90,0x80,0xAC,0x70,0x91,0x9B,0x51,0x09,0x88,0x99,0x14,0x8B,0x98,0x83,0x79,0xA0, +0x99,0x13,0x01,0x19,0xE0,0x83,0x0B,0xB0,0x0C,0x31,0x95,0xB5,0xC2,0x8A,0x39,0x20, +0x80,0x39,0xF3,0xB1,0x10,0x88,0x5E,0x18,0x94,0xA1,0x88,0xA1,0x98,0x15,0xAA,0x39, +0xD4,0x84,0xC0,0xA2,0xA2,0x0C,0x81,0x86,0xB5,0xA1,0xB1,0x14,0x1B,0xB1,0x02,0x92, +0xC3,0xE0,0x88,0x11,0xAA,0x69,0x18,0x81,0xA3,0xB0,0x01,0xBF,0x2A,0x31,0x93,0xF1, +0x00,0x89,0x18,0x19,0x11,0xD3,0xE0,0x10,0x18,0xB1,0x18,0x24,0x9A,0x2B,0xA4,0xC0, +0xB0,0x31,0x6C,0x19,0xB4,0x12,0xA8,0xEA,0x58,0x10,0x8B,0x93,0x82,0x88,0x9A,0x41, +0x10,0xC3,0xEA,0x41,0xA9,0x9C,0x34,0xA1,0x2A,0x79,0xA2,0x01,0xA8,0xB3,0x28,0xCC, +0x41,0x9A,0xB3,0x4B,0xB3,0x27,0x8B,0x83,0x2B,0x2F,0x08,0x28,0xB2,0x80,0x2C,0x30, +0x5E,0x09,0x12,0x9B,0x09,0x22,0x5B,0x19,0x8A,0x11,0x59,0x99,0xA4,0x32,0xCD,0x18, +0x08,0x10,0x85,0xB3,0xB4,0x1E,0x88,0x28,0x8A,0x11,0x09,0xC0,0x79,0x80,0x91,0x3B, +0x80,0x10,0x0F,0x01,0x80,0x91,0x19,0x3D,0x92,0x28,0xA8,0x37,0x9A,0x0A,0x3A,0x8A, +0x45,0xA9,0xA4,0x00,0xAA,0x09,0x3D,0x59,0x20,0xE1,0x08,0x98,0x90,0x59,0x10,0x09, +0xA3,0xC3,0x93,0x99,0x2B,0x69,0x11,0xD1,0xB1,0xA4,0x91,0x3C,0x89,0x83,0xF0,0x10, +0x91,0xA1,0x89,0x59,0x05,0x99,0x93,0x94,0xC8,0x08,0x0A,0x09,0x17,0xB1,0x83,0xC1, +0x91,0x40,0xA2,0xC2,0x98,0xC3,0xBA,0x28,0x23,0x0F,0x80,0x50,0xB8,0x19,0x10,0x96, +0x98,0x8C,0x05,0x98,0x19,0x29,0x2B,0x3B,0x0A,0xE2,0x01,0x0F,0x3C,0x38,0x08,0x09, +0x81,0x4A,0x6C,0x08,0x00,0x88,0x98,0x38,0x2C,0x5A,0x1B,0x20,0x1A,0x39,0xB0,0x09, +0xCB,0x5B,0x49,0x09,0x71,0x00,0xC1,0x0E,0x08,0x38,0x0C,0x02,0x10,0x0E,0x10,0x8A, +0x48,0x19,0x90,0x92,0x0D,0xA3,0x98,0x3B,0x79,0x19,0x01,0x10,0xE1,0x80,0x19,0x2B, +0x10,0xF2,0x02,0xAB,0x84,0x9A,0x29,0xB4,0x80,0x92,0x03,0x88,0x95,0xD0,0x03,0x90, +0xA0,0xC7,0xA1,0xB0,0xA2,0x02,0x18,0xB5,0xD4,0x01,0xC0,0x08,0xA2,0x93,0xA8,0xA0, +0xC3,0x20,0xF3,0x90,0x00,0xD5,0x08,0x89,0xA5,0x80,0xA0,0x81,0x82,0xC2,0x09,0xD1, +0x13,0xCB,0x03,0x84,0x91,0xE1,0x1B,0x12,0x08,0xAB,0x87,0x18,0xAB,0x58,0x89,0x28, +0x81,0xC9,0x33,0xA9,0x80,0x2E,0x20,0x83,0xB9,0x20,0x3B,0x9E,0x7A,0x08,0x81,0x18, +0x0B,0x88,0x79,0x80,0x8B,0x00,0x12,0x0E,0x89,0x51,0x1B,0x81,0xA0,0x3A,0x01,0xAF, +0x11,0x28,0xBA,0x35,0x98,0x88,0x52,0xC0,0x83,0x2F,0xA9,0x11,0x0A,0x19,0x25,0xD0, +0x30,0x9C,0x08,0x21,0x98,0x81,0x2A,0xF3,0x2A,0x80,0xB6,0x2B,0x08,0x93,0xE9,0x02, +0x81,0x8C,0x21,0x00,0xA6,0xA9,0x94,0x01,0x8F,0x80,0x94,0x98,0x93,0xB4,0x00,0x08, +0xC0,0x14,0x98,0xB3,0xB4,0xC1,0x09,0x18,0xA7,0x00,0xA3,0xC8,0x0A,0x3C,0x19,0x96, +0x83,0xC1,0x99,0x19,0x4A,0x85,0x80,0xC1,0x91,0x99,0x90,0x2A,0x17,0x95,0x99,0x88, +0x12,0xAE,0x39,0x08,0x92,0x84,0xB0,0xA8,0x79,0x09,0x19,0x01,0xB2,0xA3,0x8F,0x28, +0x2B,0xA2,0x40,0x82,0xA0,0x4C,0xA9,0x39,0x8D,0x81,0x70,0x88,0xA0,0x1A,0x49,0x2D, +0x1A,0x26,0xA8,0x98,0x08,0x29,0x0B,0x12,0x96,0xB1,0xB2,0x3A,0x13,0x9B,0x60,0xA0, +0x88,0xB2,0x34,0xEA,0x1A,0x2A,0x79,0x98,0x10,0x04,0x8C,0x1C,0x81,0x04,0x8C,0x83, +0x19,0x2F,0x81,0x93,0x98,0x10,0x08,0x30,0x2A,0xFA,0x05,0x08,0x2A,0x89,0x91,0xA3, +0xFA,0x11,0x11,0x00,0x8C,0x04,0x8A,0x2A,0xB5,0x10,0xA9,0xC2,0x3D,0x1B,0x32,0x04, +0x0A,0x1A,0x09,0x40,0x1F,0x92,0x1D,0x2A,0x91,0x10,0x30,0x2F,0x0B,0x68,0x99,0xA2, +0x92,0x88,0x78,0xA9,0x20,0x28,0xE2,0x92,0x1A,0x99,0x4B,0x19,0x22,0xA1,0xE2,0x21, +0x2F,0x98,0x29,0x18,0x91,0x08,0xB0,0x79,0x1A,0x82,0x3B,0xB1,0xA7,0x8A,0xB3,0x98, +0x5B,0x23,0xCA,0x42,0x83,0xF0,0x90,0x18,0x98,0x08,0xB4,0x20,0xA3,0xC0,0x43,0xD8, +0x80,0x81,0xA3,0x99,0xD9,0xA7,0x19,0x90,0x10,0x05,0xB1,0x8B,0x02,0xA4,0xBD,0x23, +0x93,0x8A,0x99,0x4B,0x03,0xC1,0xF8,0x38,0x09,0x2B,0x14,0xD0,0x03,0x8A,0x2A,0x39, +0xB9,0x97,0x90,0xAA,0x50,0x01,0x99,0x51,0xD1,0x09,0x1A,0xB5,0x00,0x8B,0x93,0x08, +0x98,0x11,0xF9,0x85,0x2B,0x08,0x96,0x89,0x90,0x2A,0x12,0x4A,0xD8,0x85,0x2B,0x0E, +0x10,0x00,0x01,0xB1,0x9B,0x69,0x1A,0x90,0x40,0xB8,0x01,0x08,0x0A,0x2C,0x09,0x14, +0x4B,0xE2,0x82,0x88,0xB1,0x78,0x0A,0x01,0xC2,0x93,0x19,0xCE,0x20,0x3C,0x82,0xB4, +0x1B,0x20,0x8C,0x3B,0x29,0xAB,0x86,0x23,0xD8,0x81,0x9A,0x5A,0x49,0xB0,0x16,0xA0, +0xB0,0x28,0x1B,0x13,0x93,0xE4,0xA2,0xA9,0x08,0x5A,0xB3,0x12,0xC1,0xE1,0x10,0x88, +0x01,0x0C,0x92,0x08,0x89,0xB7,0x88,0x81,0x10,0x9A,0x17,0xA0,0xB0,0x13,0x99,0xE0, +0x39,0x31,0xD2,0xB2,0x80,0x0B,0x2D,0x49,0x80,0x01,0xB0,0x06,0x09,0x0C,0x3A,0x69, +0xA0,0x08,0xB2,0xA1,0x69,0x2B,0x5A,0x81,0x92,0xBA,0x21,0xB1,0x7D,0x10,0x80,0x08, +0x88,0x82,0x32,0x0D,0xB0,0x1A,0x1C,0x21,0x94,0xA9,0x58,0xB9,0x5A,0x4A,0xA0,0x13, +0xA9,0x80,0x7C,0x00,0x20,0x8A,0x04,0x0C,0x00,0x82,0x2A,0xB2,0xAC,0x4B,0x69,0xA0, +0xA6,0x81,0x9B,0x19,0x38,0x8B,0x17,0xB2,0x81,0x2A,0xBB,0x94,0x29,0xA2,0x15,0xBA, +0x97,0xA3,0xB9,0x79,0x01,0xB2,0x02,0xF1,0x90,0x0A,0x29,0x11,0x88,0xE5,0xA0,0x81, +0x19,0x91,0x90,0x28,0xB3,0x14,0xD0,0xB5,0x91,0x9A,0x29,0x0B,0x07,0xA2,0xB3,0x01, +0x9D,0x28,0x41,0xD0,0x91,0x90,0x82,0x1A,0xA8,0x44,0x9A,0xA9,0x21,0xE3,0xA9,0x4B, +0x19,0x78,0x89,0x83,0xA3,0xB9,0x5A,0x3D,0x80,0x82,0xA2,0xA0,0x6C,0x10,0x20,0x8B, +0x93,0x8B,0x0E,0x33,0xA9,0xB1,0x68,0x8A,0x31,0xAC,0x94,0xB4,0x8B,0x32,0x0B,0xB4, +0x81,0x91,0x1D,0x33,0xD9,0x31,0xE1,0x8B,0x3B,0x30,0x12,0x49,0xD2,0x8E,0x29,0x18, +0x8A,0x92,0x02,0xAA,0x59,0x1C,0x32,0x88,0x01,0x23,0xFB,0x83,0x29,0xDA,0x59,0x01, +0x81,0x92,0xE1,0x18,0x8A,0x1D,0x30,0x93,0xF1,0x00,0x01,0x0B,0x39,0x92,0x89,0xA0, +0x11,0x5B,0xE0,0x82,0x09,0x13,0xAA,0xB4,0x16,0xD8,0x91,0x2A,0x29,0x84,0x1B,0xC5, +0x98,0x98,0x31,0x98,0x99,0x17,0xA9,0x20,0x92,0xC3,0x18,0x9D,0x20,0x3D,0x89,0x94, +0xA2,0x1C,0x5C,0x29,0x39,0xA0,0xB3,0x00,0x0C,0x4C,0x48,0x92,0x0A,0x91,0x85,0x9A, +0x01,0x82,0x1F,0x10,0x99,0x15,0xC1,0xA0,0x39,0x1A,0x1D,0x85,0xB4,0x90,0x1A,0x2A, +0x4B,0x01,0xB2,0x93,0xBE,0x12,0x83,0xC9,0x18,0x09,0x20,0x78,0xF1,0x08,0x19,0x88, +0x3A,0x83,0xB3,0xA9,0x93,0x7A,0x0A,0x96,0x98,0x00,0xA8,0x3A,0x30,0x92,0xF2,0x9B, +0x3D,0x38,0x92,0x92,0xC3,0xB8,0x6B,0x29,0x01,0x01,0xB2,0x2F,0x09,0x19,0x18,0x01, +0x3B,0x7B,0x10,0xA1,0x90,0x39,0x0F,0x38,0x0A,0xB5,0xA4,0x89,0x8B,0x6A,0x2B,0x12, +0xC8,0x90,0x40,0x2A,0x9E,0x22,0x88,0x18,0x09,0x3A,0xC3,0xE8,0x09,0x59,0x08,0x12, +0x94,0xD0,0x1A,0x2C,0x38,0x00,0xA1,0x83,0xE8,0x08,0x3A,0x08,0x10,0x9E,0x83,0x1D, +0x92,0x19,0x2C,0x39,0x3B,0x59,0x04,0xE1,0x80,0x08,0x8D,0x21,0x81,0xB2,0xB2,0x02, +0x99,0x91,0xA4,0xD6,0x98,0x99,0x03,0x80,0x98,0xA7,0x91,0x09,0xA1,0xB2,0xB3,0xE1, +0x12,0x92,0xB1,0x81,0x06,0x99,0x0A,0x23,0xC4,0xB1,0xF2,0x89,0x19,0x3A,0x94,0x82, +0xE0,0x89,0x38,0x0B,0xA4,0xA5,0x80,0x80,0x8C,0x34,0xB9,0xA9,0x23,0x13,0xB9,0xC1, +0xC7,0x1B,0x89,0x10,0x20,0x11,0xE3,0xA8,0x4B,0x0B,0x40,0x91,0x90,0x1B,0x5F,0x2A, +0x18,0x82,0x91,0x0B,0x4A,0x28,0xCA,0x40,0x80,0x5B,0x2C,0x13,0xB0,0x8A,0xA9,0x5A, +0x58,0x89,0x82,0x88,0x2E,0x3B,0x31,0xA1,0x9B,0x01,0x7A,0x2C,0x01,0x91,0x93,0x3F, +0x88,0x39,0x10,0xF1,0x91,0x8B,0x48,0x0A,0x12,0xE3,0xA8,0x18,0x28,0x92,0x97,0x98, +0x99,0x19,0xA1,0x11,0xB6,0x88,0x3B,0x10,0xD3,0xC3,0xA1,0x2A,0x8A,0x49,0x04,0xF1, +0x91,0x02,0x8A,0x89,0x04,0xF1,0x98,0x80,0x18,0x12,0xE3,0x81,0x98,0x80,0x01,0xB3, +0xF2,0x99,0x12,0x2A,0xB5,0xB3,0x92,0xAA,0x19,0x50,0xB2,0xC3,0x92,0xD0,0x2B,0x68, +0x93,0x99,0xC0,0x2C,0x3E,0x80,0x20,0x08,0x93,0x0D,0x2A,0x31,0x8D,0x02,0x2B,0x91, +0x08,0x0A,0x03,0x2C,0x3C,0x52,0xB9,0xA0,0x12,0xBF,0x3A,0x29,0x01,0x88,0xC0,0x6A, +0x3C,0x0A,0x49,0x18,0x0B,0x39,0x2B,0x69,0x0A,0x84,0x2A,0x2A,0x1C,0x2A,0xC3,0x8C, +0x19,0x50,0x09,0x91,0xA7,0x8D,0x18,0x1A,0x28,0x00,0xA0,0x94,0x10,0x1F,0x20,0x90, +0x8A,0x12,0xD0,0x1A,0x5A,0x81,0x04,0xBC,0x23,0x10,0xE0,0x90,0x90,0x18,0x1A,0xA6, +0x12,0xB1,0xD0,0x4A,0x08,0x82,0x92,0xB6,0x9A,0x0A,0x12,0x88,0xC3,0xC5,0x8A,0x89, +0x20,0xB5,0x93,0x0B,0x18,0x00,0x09,0xF2,0x88,0x2A,0x4A,0x08,0x05,0xB2,0xA9,0x3B, +0x5D,0x28,0xA4,0xB1,0x00,0x19,0x19,0x7A,0xA3,0xB3,0x0A,0x90,0xA1,0xC4,0x80,0xBA, +0x50,0x13,0xC1,0xC2,0x9A,0x2A,0x7B,0x28,0x84,0xC1,0x09,0x3B,0x4E,0x20,0x91,0xA1, +0x18,0xAB,0x79,0x10,0xB4,0x08,0x9A,0x11,0x2B,0xF0,0x93,0xAA,0x01,0x6A,0x01,0x93, +0x80,0xB8,0x2A,0x5B,0x10,0x80,0x89,0x4A,0x5B,0x92,0x15,0xB2,0xA0,0x2F,0x19,0x93, +0xB8,0x95,0x80,0x1C,0x21,0xA9,0x02,0x0B,0xA0,0x5A,0x18,0x98,0x39,0x1B,0x68,0x00, +0x91,0x91,0x9C,0x39,0x3E,0x18,0x84,0xB3,0x9B,0x7A,0x08,0x18,0x0A,0xB5,0x91,0x0B, +0x28,0x39,0x19,0x90,0x0A,0x50,0xAC,0x11,0x01,0xAB,0x88,0x52,0x1B,0x83,0xC4,0xA2, +0x9A,0xAB,0x03,0x90,0x19,0x93,0x81,0x08,0x92,0x9A,0x68,0x98,0x19,0x39,0xC1,0x92, +0x8A,0x38,0x4E,0x02,0xB1,0x90,0xC3,0x18,0x2B,0x04,0xC3,0xD2,0x91,0x90,0x81,0x89, +0x13,0xF1,0x88,0x93,0xA2,0x00,0x91,0xC0,0x5B,0x21,0x99,0x93,0x06,0x9A,0x1B,0x48, +0x99,0xB7,0x90,0x89,0x18,0x1B,0x11,0xA4,0xB2,0x81,0x9A,0x08,0x97,0x98,0x91,0x10, +0xB8,0x06,0xA2,0xA0,0x29,0x2B,0x21,0xC2,0xD1,0x10,0x1A,0x4A,0x29,0xF1,0x98,0x29, +0x1B,0x31,0x10,0xA0,0xA1,0x1D,0x5A,0x29,0xB2,0x82,0xA8,0x0F,0x28,0x21,0x09,0x91, +0x82,0x4D,0x10,0xA3,0xB0,0x89,0x4C,0x39,0xA0,0xA4,0xA1,0x89,0x1E,0x28,0x29,0xA3, +0xC3,0x2D,0x19,0x01,0x49,0x01,0x9B,0x0C,0x21,0xC2,0xA2,0x93,0x7C,0x2A,0x10,0x90, + +/* Source: 08HH.ROM */ +/* Length: 384 / 0x00000180 */ + +0x75,0xF2,0xAB,0x7D,0x7E,0x5C,0x3B,0x4B,0x3C,0x4D,0x4A,0x02,0xB3,0xC5,0xE7,0xE3, +0x92,0xB3,0xC4,0xB3,0xC3,0x8A,0x3B,0x5D,0x5C,0x3A,0x84,0xC2,0x91,0xA4,0xE7,0xF7, +0xF7,0xF4,0xA1,0x1B,0x49,0xA5,0xB1,0x1E,0x7F,0x5A,0x00,0x89,0x39,0xB7,0xA8,0x3D, +0x4A,0x84,0xE7,0xF7,0xE2,0x2D,0x4C,0x3A,0x4E,0x7D,0x04,0xB0,0x2D,0x4B,0x10,0x80, +0xA3,0x99,0x10,0x0E,0x59,0x93,0xC4,0xB1,0x81,0xC4,0xA2,0xB2,0x88,0x08,0x3F,0x3B, +0x28,0xA6,0xC3,0xA2,0xA2,0xC5,0xC1,0x3F,0x7E,0x39,0x81,0x93,0xC2,0xA3,0xE5,0xD2, +0x80,0x93,0xB8,0x6D,0x49,0x82,0xD4,0xA1,0x90,0x01,0xA0,0x09,0x04,0xE3,0xB2,0x91, +0xB7,0xB3,0xA8,0x2A,0x03,0xF3,0xA1,0x92,0xC5,0xC3,0xB2,0x0B,0x30,0xB3,0x8E,0x6D, +0x4A,0x01,0xB4,0xB4,0xC4,0xC3,0x99,0x3B,0x12,0xE3,0xA1,0x88,0x82,0xB4,0x9A,0x5C, +0x3A,0x18,0x93,0xC3,0xB3,0xB4,0xA8,0x19,0x04,0xF3,0xA8,0x3B,0x10,0xA2,0x88,0xA5, +0xB2,0x0B,0x6D,0x4B,0x10,0x91,0x89,0x3C,0x18,0x18,0xA6,0xC4,0xC3,0x98,0x19,0x2B, +0x20,0x91,0xA0,0x4E,0x28,0x93,0xB3,0xC2,0x92,0xA9,0x5A,0x96,0xC4,0xC2,0x09,0x01, +0xC4,0xA1,0x92,0xC4,0xA1,0x89,0x10,0xA3,0xA1,0x90,0x1C,0x5A,0x01,0xC5,0xA1,0x92, +0xD4,0xB3,0xC4,0xC4,0xC3,0xA1,0x88,0x1A,0x28,0x89,0x3C,0x3A,0x3D,0x29,0x00,0x93, +0xB0,0x3D,0x28,0x80,0x91,0x82,0xE3,0x99,0x2A,0x11,0xD6,0xC3,0x99,0x29,0x82,0xC4, +0xC3,0xA1,0x0A,0x3B,0x3D,0x3A,0x02,0xC3,0xA2,0x99,0x3B,0x2C,0x7C,0x28,0x81,0xA3, +0xB2,0xA3,0xB1,0x08,0x1A,0x3C,0x18,0x2E,0x4C,0x39,0xA5,0xB3,0xB4,0xC2,0x88,0x08, +0x19,0x0A,0x49,0xB7,0xB3,0xA2,0xA1,0x92,0xA1,0x93,0xB1,0x0C,0x7D,0x39,0x93,0xB3, +0xB1,0x1A,0x19,0x5D,0x28,0xA6,0xC4,0xB2,0x90,0x09,0x2A,0x18,0x1B,0x5B,0x28,0x88, +0x2C,0x29,0x82,0xA0,0x18,0x91,0x2D,0x29,0x2B,0x5C,0x4C,0x3B,0x4C,0x28,0x80,0x92, +0x90,0x09,0x2B,0x28,0x1D,0x6B,0x11,0xC5,0xB2,0x0B,0x39,0x09,0x4D,0x28,0x88,0x00, +0x1B,0x28,0x94,0xE3,0xA0,0x1A,0x28,0xB5,0xB4,0xB3,0xB2,0x93,0xE2,0x91,0x92,0xD4, +0xA0,0x1B,0x4A,0x01,0xA1,0x88,0x2D,0x5C,0x3B,0x28,0x08,0x93,0xD4,0xB2,0x91,0xB4, +0xA0,0x3E,0x3B,0x4B,0x3B,0x29,0x08,0x93,0x9B,0x7B,0x3A,0x19,0x00,0x80,0x80,0xA0, + +/* Source: 10TOM.ROM */ +/* Length: 640 / 0x00000280 */ + +0x77,0x27,0x87,0x01,0x2D,0x4F,0xC3,0xC1,0x92,0x91,0x89,0x59,0x83,0x1A,0x32,0xC2, +0x95,0xB1,0x81,0x88,0x81,0x4A,0x3D,0x11,0x9E,0x0B,0x88,0x0C,0x18,0x3B,0x11,0x11, +0x91,0x00,0xA0,0xE2,0x0A,0x48,0x13,0x24,0x81,0x48,0x1B,0x39,0x1C,0x83,0x84,0xA1, +0xD1,0x8E,0x8A,0x0B,0xC0,0x98,0x92,0xB8,0x39,0x90,0x10,0x92,0xF0,0xB5,0x88,0x32, +0x49,0x51,0x21,0x03,0x82,0x10,0x8A,0x7A,0x09,0x00,0xA2,0xCA,0x1B,0xCC,0x1C,0xB9, +0x8E,0x89,0x89,0xA1,0x89,0x92,0x29,0x11,0x60,0x40,0x14,0x22,0x32,0x78,0x40,0x01, +0x02,0x90,0x81,0xAB,0x0B,0x00,0xAF,0x99,0xCC,0xAB,0xDA,0xA9,0x99,0x1B,0x30,0x14, +0x92,0x22,0x19,0x68,0x32,0x14,0x26,0x13,0x23,0x23,0x20,0x12,0x9A,0xA8,0xB9,0xFA, +0xAA,0xCA,0xCC,0x0C,0xA8,0xAE,0x88,0xB9,0x88,0xA0,0x02,0x21,0x50,0x43,0x03,0x81, +0x2A,0x11,0x34,0x63,0x24,0x33,0x22,0x38,0x8B,0xEA,0xAE,0x99,0xA0,0x90,0x82,0x00, +0x89,0xBF,0x8A,0xE8,0xA9,0x90,0x01,0x12,0x13,0x12,0x08,0xA9,0xAA,0xC9,0x22,0x63, +0x63,0x12,0x44,0x00,0x10,0x88,0x9C,0x98,0xA1,0x85,0x03,0x32,0x36,0x80,0x89,0xDB, +0xDB,0xBB,0xB9,0xBA,0x01,0x81,0x28,0x19,0xCB,0xFA,0xBC,0x09,0x13,0x37,0x34,0x34, +0x23,0x31,0x20,0x10,0x00,0x00,0x28,0x38,0x10,0x88,0xEC,0x8D,0xCB,0xBC,0xCC,0xBB, +0xBB,0xC9,0x99,0x00,0x00,0x33,0x11,0x22,0x81,0x07,0x41,0x54,0x34,0x34,0x22,0x31, +0x00,0x88,0x9A,0x9B,0x98,0xAB,0x8E,0x9B,0xBD,0x9C,0xBC,0xBB,0xDA,0xAA,0xA9,0x99, +0x18,0x38,0x60,0x20,0x31,0x13,0x13,0x51,0x14,0x31,0x53,0x33,0x35,0x22,0x01,0x8A, +0x9C,0xA9,0xCA,0xC9,0xA8,0x00,0x10,0x81,0x9C,0x9E,0xAB,0xCC,0xAB,0xBA,0x98,0x30, +0x52,0x03,0x81,0x08,0x9C,0xAC,0xAC,0x18,0x11,0x03,0x51,0x61,0x41,0x31,0x31,0x02, +0x01,0x20,0x24,0x43,0x44,0x40,0x30,0x10,0xBC,0xBE,0xCB,0xDB,0xAB,0xBA,0x99,0x98, +0x99,0xAA,0xBD,0xAA,0xC8,0x90,0x11,0x53,0x37,0x23,0x43,0x34,0x33,0x33,0x33,0x11, +0x28,0x00,0x19,0xA9,0x9A,0xCB,0xCE,0xBB,0xEB,0xBC,0xBB,0xCA,0xBA,0xA8,0x88,0x11, +0x12,0x21,0x20,0x22,0x26,0x26,0x23,0x23,0x43,0x24,0x22,0x32,0x20,0x31,0x81,0x9A, +0xBC,0xBC,0xCB,0xBD,0x9A,0xA9,0x90,0x98,0xBA,0xCC,0xCB,0xBC,0x8B,0x88,0x22,0x35, +0x23,0x12,0x99,0x8B,0xAA,0xAA,0x89,0x82,0x93,0x31,0x42,0x23,0x23,0x21,0x32,0x11, +0x20,0x13,0x13,0x24,0x24,0x24,0x22,0x11,0x8A,0x9E,0xAC,0xAC,0xAA,0xBA,0xAA,0xAB, +0xBD,0xBC,0xCB,0xCB,0xA9,0xA8,0x91,0x12,0x44,0x43,0x44,0x34,0x34,0x42,0x33,0x42, +0x21,0x11,0x11,0x88,0x80,0xAA,0x0B,0xAC,0xCB,0xEC,0xAC,0xBA,0xCA,0xAB,0x9A,0x99, +0x80,0x91,0x09,0x08,0x10,0x22,0x44,0x43,0x44,0x33,0x43,0x22,0x13,0x21,0x22,0x20, +0x09,0x88,0xB9,0xC8,0xBB,0xAB,0xAB,0xA9,0xA9,0x9B,0x9B,0x99,0x90,0x90,0x00,0x81, +0x00,0x08,0x09,0x8A,0x9A,0xAA,0xA9,0xA9,0x99,0x90,0x80,0x01,0x80,0x00,0x09,0x31, +0x32,0x44,0x33,0x43,0x34,0x33,0x24,0x22,0x23,0x12,0x10,0x09,0x9B,0xAB,0xCA,0xCC, +0xBB,0xCB,0xDA,0xCA,0xAB,0xCA,0xAB,0xA9,0xA8,0x92,0x12,0x43,0x53,0x35,0x23,0x33, +0x43,0x43,0x52,0x22,0x22,0x21,0x01,0x09,0x89,0xA9,0xBB,0xBD,0xBC,0xCB,0xDA,0xAB, +0xAB,0xAB,0xAA,0xA9,0x99,0xA8,0x09,0x01,0x11,0x34,0x25,0x23,0x33,0x51,0x22,0x31, +0x12,0x20,0x21,0x12,0x10,0x80,0x99,0x9A,0x99,0x99,0x88,0x08,0x00,0x88,0xA9,0x99, +0x99,0x80,0x80,0x10,0x01,0x00,0x9A,0xAA,0xBB,0xBA,0xBA,0xA9,0x99,0x99,0x89,0x99, +0x99,0x00,0x01,0x33,0x35,0x24,0x23,0x34,0x23,0x33,0x34,0x33,0x43,0x32,0x21,0x88, +0xAB,0xBD,0xBB,0xDB,0xAB,0xBA,0xBB,0xDA,0xBB,0xCB,0xBB,0xBC,0xA8,0x90,0x01,0x12, +0x23,0x43,0x53,0x34,0x34,0x39,0x80,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00, + +/* Source: 20RIM.ROM */ +/* Length: 128 / 0x00000080 */ + +0x0F,0xFF,0x73,0x8E,0x71,0xCD,0x00,0x49,0x10,0x90,0x21,0x49,0xA0,0xDB,0x02,0x3A, +0xE3,0x0A,0x50,0x98,0xC0,0x59,0xA2,0x99,0x09,0x22,0xA2,0x80,0x10,0xA8,0x5B,0xD2, +0x88,0x21,0x09,0x96,0xA8,0x10,0x0A,0xE0,0x08,0x48,0x19,0xAB,0x52,0xA8,0x92,0x0C, +0x03,0x19,0xE2,0x0A,0x12,0xC2,0x81,0x1E,0x01,0xD0,0x48,0x88,0x98,0x01,0x49,0x91, +0xAA,0x2C,0x25,0x89,0x88,0xB5,0x81,0xA2,0x9A,0x12,0x9E,0x38,0x3B,0x81,0x9B,0x59, +0x01,0x93,0xCA,0x4A,0x21,0xA0,0x3D,0x0A,0x39,0x3D,0x12,0xA8,0x3F,0x18,0x01,0x92, +0x1C,0x00,0xB2,0x48,0xB9,0x94,0xA3,0x19,0x4F,0x19,0xB2,0x32,0x90,0xBA,0x01,0xE6, +0x91,0x80,0xC1,0xA4,0x2A,0x08,0xA1,0xB1,0x25,0xD2,0x88,0x99,0x21,0x80,0x88,0x80, +}; + + + +/* flag enable control 0x110 */ +INLINE void YM2608IRQFlagWrite(FM_OPN *OPN, int n, int v) +{ + YM2608 *F2608 = &(FM2608[n]); + + if( v & 0x80 ) + { /* Reset IRQ flag */ + FM_STATUS_RESET(&OPN->ST, 0xf7); /* don't touch BUFRDY flag otherwise we'd have to call ymdeltat module to set the flag back */ + } + else + { /* Set status flag mask */ + F2608->flagmask = (~(v&0x1f)); + FM_IRQMASK_SET(&OPN->ST, (F2608->irqmask & F2608->flagmask) ); + } +} + +/* compatible mode & IRQ enable control 0x29 */ +INLINE void YM2608IRQMaskWrite(FM_OPN *OPN, int n, int v) +{ + YM2608 *F2608 = &(FM2608[n]); + /* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */ + + /* extend 3ch. enable/disable */ + if(v&0x80) + OPN->type |= TYPE_6CH; /* OPNA mode - 6 FM channels */ + else + OPN->type &= ~TYPE_6CH; /* OPN mode - 3 FM channels */ + + /* IRQ MASK store and set */ + F2608->irqmask = v&0x1f; + FM_IRQMASK_SET(&OPN->ST, (F2608->irqmask & F2608->flagmask) ); +} + +/* Generate samples for one of the YM2608s */ +void YM2608UpdateOne(int num, INT16 **buffer, int length) +{ + YM2608 *F2608 = &(FM2608[num]); + FM_OPN *OPN = &(FM2608[num].OPN); + YM_DELTAT *DELTAT = &(F2608[num].deltaT); + int i,j; + FMSAMPLE *bufL,*bufR; + + /* set bufer */ + bufL = buffer[0]; + bufR = buffer[1]; + + if( (void *)F2608 != cur_chip ){ + cur_chip = (void *)F2608; + + State = &OPN->ST; + cch[0] = &F2608->CH[0]; + cch[1] = &F2608->CH[1]; + cch[2] = &F2608->CH[2]; + cch[3] = &F2608->CH[3]; + cch[4] = &F2608->CH[4]; + cch[5] = &F2608->CH[5]; + /* setup adpcm rom address */ + pcmbufA = F2608->pcmbuf; + pcmsizeA = F2608->pcm_size; + + } + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, cch[0] ); + refresh_fc_eg_chan( OPN, cch[1] ); + if( (State->mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[2]->SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); + } + }else refresh_fc_eg_chan( OPN, cch[2] ); + refresh_fc_eg_chan( OPN, cch[3] ); + refresh_fc_eg_chan( OPN, cch[4] ); + refresh_fc_eg_chan( OPN, cch[5] ); + + + /* buffering */ + for(i=0; i < length ; i++) + { + + advance_lfo(OPN); + + /* clear output acc. */ + out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0; + out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0; + /* clear outputs */ + out_fm[0] = 0; + out_fm[1] = 0; + out_fm[2] = 0; + out_fm[3] = 0; + out_fm[4] = 0; + out_fm[5] = 0; + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + OPN->eg_timer -= OPN->eg_timer_overflow; + OPN->eg_cnt++; + + advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]); + } + + /* calculate FM */ + chan_calc(OPN, cch[0], 0 ); + chan_calc(OPN, cch[1], 1 ); + chan_calc(OPN, cch[2], 2 ); + chan_calc(OPN, cch[3], 3 ); + chan_calc(OPN, cch[4], 4 ); + chan_calc(OPN, cch[5], 5 ); + + /* deltaT ADPCM */ + if( DELTAT->portstate&0x80 ) + YM_DELTAT_ADPCM_CALC(DELTAT); + + /* ADPCMA */ + for( j = 0; j < 6; j++ ) + { + if( F2608->adpcm[j].flag ) + ADPCMA_calc_chan( F2608, &F2608->adpcm[j]); + } + + /* buffering */ + { + int lt,rt; + + lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER]; + rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER]; + lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9; + rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9; + lt += ((out_fm[0]>>1) & OPN->pan[0]); /* shift right verified on real YM2608 */ + rt += ((out_fm[0]>>1) & OPN->pan[1]); + lt += ((out_fm[1]>>1) & OPN->pan[2]); + rt += ((out_fm[1]>>1) & OPN->pan[3]); + lt += ((out_fm[2]>>1) & OPN->pan[4]); + rt += ((out_fm[2]>>1) & OPN->pan[5]); + lt += ((out_fm[3]>>1) & OPN->pan[6]); + rt += ((out_fm[3]>>1) & OPN->pan[7]); + lt += ((out_fm[4]>>1) & OPN->pan[8]); + rt += ((out_fm[4]>>1) & OPN->pan[9]); + lt += ((out_fm[5]>>1) & OPN->pan[10]); + rt += ((out_fm[5]>>1) & OPN->pan[11]); + + lt >>= FINAL_SH; + rt >>= FINAL_SH; + + Limit( lt, MAXOUT, MINOUT ); + Limit( rt, MAXOUT, MINOUT ); + /* buffering */ + bufL[i] = lt; + bufR[i] = rt; + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + } + + /* timer A control */ + INTERNAL_TIMER_A( State , cch[2] ) + } + INTERNAL_TIMER_B(State,length) + + + /* check IRQ for DELTA-T EOS */ + FM_STATUS_SET(State, 0); + +} +#ifdef _STATE_H +static void YM2608_postload(void) +{ + int num , r; + + for(num=0;numOPN,1,2); + F2608->deltaT.freqbase = F2608->OPN.ST.freqbase; + /* IRQ mask / mode */ + YM2608IRQMaskWrite(&F2608->OPN, num, F2608->REGS[0x29]); + /* SSG registers */ + for(r=0;r<16;r++) + { + SSGWrite(num,0,r); + SSGWrite(num,1,F2608->REGS[r]); + } + + /* OPN registers */ + /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */ + for(r=0x30;r<0x9e;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2608->OPN,r,F2608->REGS[r]); + OPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]); + } + /* FB / CONNECT , L / R / AMS / PMS */ + for(r=0xb0;r<0xb6;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2608->OPN,r,F2608->REGS[r]); + OPNWriteReg(&F2608->OPN,r|0x100,F2608->REGS[r|0x100]); + } + /* FM channels */ + /*FM_channel_postload(F2608->CH,6);*/ + /* rhythm(ADPCMA) */ + FM_ADPCMAWrite(F2608,1,F2608->REGS[0x111]); + for( r=0x08 ; r<0x0c ; r++) + FM_ADPCMAWrite(F2608,r,F2608->REGS[r+0x110]); + /* Delta-T ADPCM unit */ + YM_DELTAT_postload(&F2608->deltaT , &F2608->REGS[0x100] ); + } + cur_chip = NULL; +} + +static void YM2608_save_state(void) +{ + int num; + const char statename[] = "YM2608"; + + for(num=0;numREGS , 512); + FMsave_state_st(statename,num,&FM2608[num].OPN.ST); + FMsave_state_channel(statename,num,FM2608[num].CH,6); + /* 3slots */ + state_save_register_UINT32(statename, num, "slot3fc" , F2608->OPN.SL3.fc , 3); + state_save_register_UINT8 (statename, num, "slot3fh" , &F2608->OPN.SL3.fn_h, 1); + state_save_register_UINT8 (statename, num, "slot3kc" , F2608->OPN.SL3.kcode, 3); + /* address register1 */ + state_save_register_UINT8 (statename, num, "addr_A1" , &F2608->addr_A1 ,1); + /* rythm(ADPCMA) */ + FMsave_state_adpcma(statename,num,F2608->adpcm); + /* Delta-T ADPCM unit */ + YM_DELTAT_savestate(statename,num,&FM2608[num].deltaT); + } + state_save_register_func_postload(YM2608_postload); +} +#endif /* _STATE_H */ + +static void YM2608_deltat_status_set(UINT8 which, UINT8 changebits) +{ + FM_STATUS_SET(&(FM2608[which].OPN.ST), changebits); +} +static void YM2608_deltat_status_reset(UINT8 which, UINT8 changebits) +{ + FM_STATUS_RESET(&(FM2608[which].OPN.ST), changebits); +} +/* YM2608(OPNA) */ +int YM2608Init(int num, int clock, int rate, + void **pcmrom,int *pcmsize, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler) +{ + int i; + + if (FM2608) return (-1); /* duplicate init. */ + cur_chip = NULL; + + YM2608NumChips = num; + + /* allocate extend state space */ + if( (FM2608 = (YM2608 *)malloc(sizeof(YM2608) * YM2608NumChips))==NULL) + return (-1); + /* clear */ + memset(FM2608,0,sizeof(YM2608) * YM2608NumChips); + /* allocate total level table (128kb space) */ + if( !init_tables() ) + { + if (FM2608) { + free( FM2608 ); + FM2608 = NULL; + } + return (-1); + } + + for ( i = 0 ; i < YM2608NumChips; i++ ) { + FM2608[i].OPN.ST.index = i; + FM2608[i].OPN.type = TYPE_YM2608; + FM2608[i].OPN.P_CH = FM2608[i].CH; + FM2608[i].OPN.ST.clock = clock; + FM2608[i].OPN.ST.rate = rate; + + /* External handlers */ + FM2608[i].OPN.ST.Timer_Handler = TimerHandler; + FM2608[i].OPN.ST.IRQ_Handler = IRQHandler; + + /* DELTA-T */ + FM2608[i].deltaT.memory = (UINT8 *)(pcmrom[i]); + FM2608[i].deltaT.memory_size = pcmsize[i]; + + /*FM2608[i].deltaT.write_time = 20.0 / clock;*/ /* a single byte write takes 20 cycles of main clock */ + /*FM2608[i].deltaT.read_time = 18.0 / clock;*/ /* a single byte read takes 18 cycles of main clock */ + + FM2608[i].deltaT.status_set_handler = YM2608_deltat_status_set; + FM2608[i].deltaT.status_reset_handler = YM2608_deltat_status_reset; + FM2608[i].deltaT.status_change_which_chip = i; + FM2608[i].deltaT.status_change_EOS_bit = 0x04; /* status flag: set bit2 on End Of Sample */ + FM2608[i].deltaT.status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY */ + FM2608[i].deltaT.status_change_ZERO_bit = 0x10; /* status flag: set bit4 if silence continues for more than 290 miliseconds while recording the ADPCM */ + + /* ADPCM Rhythm */ + FM2608[i].pcmbuf = YM2608_ADPCM_ROM; + FM2608[i].pcm_size = 0x2000; + + YM2608ResetChip(i); + } + + Init_ADPCMATable(); + +#ifdef _STATE_H + YM2608_save_state(); +#endif + return 0; +} + +/* shut down emulator */ +void YM2608Shutdown() +{ + if (!FM2608) return; + + FMCloseTable(); + if (FM2608) { + free(FM2608); + FM2608 = NULL; + } +} + +/* reset one of chips */ +void YM2608ResetChip(int num) +{ + int i; + YM2608 *F2608 = &(FM2608[num]); + FM_OPN *OPN = &(FM2608[num].OPN); + YM_DELTAT *DELTAT = &(F2608[num].deltaT); + + /* Reset Prescaler */ + OPNPrescaler_w(OPN , 0 , 2); + F2608->deltaT.freqbase = OPN->ST.freqbase; + /* reset SSG section */ + SSGReset(OPN->ST.index); + + /* status clear */ + FM_BUSY_CLEAR(&OPN->ST); + + /* register 0x29 - default value after reset is: + enable only 3 FM channels and enable all the status flags */ + YM2608IRQMaskWrite(OPN, num, 0x1f ); /* default value for D4-D0 is 1 */ + + /* register 0x10, A1=1 - default value is 1 for D4, D3, D2, 0 for the rest */ + YM2608IRQFlagWrite(OPN, num, 0x1c ); /* default: enable timer A and B, disable EOS, BRDY and ZERO */ + + OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ + + OPN->eg_timer = 0; + OPN->eg_cnt = 0; + + FM_STATUS_RESET(&OPN->ST, 0xff); + + reset_channels( &OPN->ST , F2608->CH , 6 ); + /* reset OPerator paramater */ + for(i = 0xb6 ; i >= 0xb4 ; i-- ) + { + OPNWriteReg(OPN,i ,0xc0); + OPNWriteReg(OPN,i|0x100,0xc0); + } + for(i = 0xb2 ; i >= 0x30 ; i-- ) + { + OPNWriteReg(OPN,i ,0); + OPNWriteReg(OPN,i|0x100,0); + } + for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); + + /* ADPCM - percussion sounds */ + for( i = 0; i < 6; i++ ) + { + if (i<=3) /* channels 0,1,2,3 */ + F2608->adpcm[i].step = (UINT32)((float)(1<OPN.ST.freqbase)/3.0); + else /* channels 4 and 5 work with slower clock */ + F2608->adpcm[i].step = (UINT32)((float)(1<OPN.ST.freqbase)/6.0); + + F2608->adpcm[i].start = YM2608_ADPCM_ROM_addr[i*2]; + F2608->adpcm[i].end = YM2608_ADPCM_ROM_addr[i*2+1]; + + F2608->adpcm[i].now_addr = 0; + F2608->adpcm[i].now_step = 0; + /* F2608->adpcm[i].delta = 21866; */ + F2608->adpcm[i].vol_mul = 0; + F2608->adpcm[i].pan = &out_adpcm[OUTD_CENTER]; /* default center */ + F2608->adpcm[i].flagMask = 0; + F2608->adpcm[i].flag = 0; + F2608->adpcm[i].adpcm_acc = 0; + F2608->adpcm[i].adpcm_step= 0; + F2608->adpcm[i].adpcm_out = 0; + } + F2608->adpcmTL = 0x3f; + + F2608->adpcm_arrivedEndAddress = 0; /* not used */ + + /* DELTA-T unit */ + DELTAT->freqbase = OPN->ST.freqbase; + DELTAT->output_pointer = out_delta; + DELTAT->portshift = 5; /* always 5bits shift */ /* ASG */ + DELTAT->output_range = 1<<23; + YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_NORMAL); +} + +/* YM2608 write */ +/* n = number */ +/* a = address */ +/* v = value */ +int YM2608Write(int n, int a,UINT8 v) +{ + YM2608 *F2608 = &(FM2608[n]); + FM_OPN *OPN = &(FM2608[n].OPN); + int addr; + + v &= 0xff; /*adjust to 8 bit bus */ + + + switch(a&3) + { + case 0: /* address port 0 */ + OPN->ST.address = v; + F2608->addr_A1 = 0; + + /* Write register to SSG emulator */ + if( v < 16 ) SSGWrite(n,0,v); + /* prescaler selecter : 2d,2e,2f */ + if( v >= 0x2d && v <= 0x2f ) + { + OPNPrescaler_w(OPN , v , 2); + F2608->deltaT.freqbase = OPN->ST.freqbase; + } + break; + + case 1: /* data port 0 */ + if (F2608->addr_A1 != 0) + break; /* verified on real YM2608 */ + + addr = OPN->ST.address; +#ifdef _STATE_H + F2608->REGS[addr] = v; +#endif + switch(addr & 0xf0) + { + case 0x00: /* SSG section */ + /* Write data to SSG emulator */ + SSGWrite(n,a,v); + break; + case 0x10: /* 0x10-0x1f : Rhythm section */ + YM2608UpdateReq(n); + FM_ADPCMAWrite(F2608,addr-0x10,v); + break; + case 0x20: /* Mode Register */ + switch(addr) + { + case 0x29: /* SCH,xx,xxx,EN_ZERO,EN_BRDY,EN_EOS,EN_TB,EN_TA */ + YM2608IRQMaskWrite(OPN, n, v); + break; + default: + YM2608UpdateReq(n); + OPNWriteMode(OPN,addr,v); + } + break; + default: /* OPN section */ + YM2608UpdateReq(n); + OPNWriteReg(OPN,addr,v); + } + break; + + case 2: /* address port 1 */ + OPN->ST.address = v; + F2608->addr_A1 = 1; + break; + + case 3: /* data port 1 */ + if (F2608->addr_A1 != 1) + break; /* verified on real YM2608 */ + + addr = OPN->ST.address; +#ifdef _STATE_H + F2608->REGS[addr | 0x100] = v; +#endif + YM2608UpdateReq(n); + switch( addr & 0xf0 ) + { + case 0x00: /* DELTAT PORT */ + switch( addr ) + { + case 0x0e: /* DAC data */ + logerror("YM2608: write to DAC data (unimplemented) value=%02x\n",v); + break; + default: + /* 0x00-0x0d */ + YM_DELTAT_ADPCM_Write(&F2608->deltaT,addr,v); + } + break; + case 0x10: /* IRQ Flag control */ + if( addr == 0x10 ) + { + YM2608IRQFlagWrite(OPN, n, v); + } + break; + default: + OPNWriteReg(OPN,addr | 0x100,v); + } + } + return OPN->ST.irq; +} + +UINT8 YM2608Read(int n,int a) +{ + YM2608 *F2608 = &(FM2608[n]); + int addr = F2608->OPN.ST.address; + UINT8 ret = 0; + + switch( a&3 ){ + case 0: /* status 0 : YM2203 compatible */ + /* BUSY:x:x:x:x:x:FLAGB:FLAGA */ + ret = FM_STATUS_FLAG(&F2608->OPN.ST) & 0x83; + break; + + case 1: /* status 0, ID */ + if( addr < 16 ) ret = SSGRead(n); + else if(addr == 0xff) ret = 0x01; /* ID code */ + break; + + case 2: /* status 1 : status 0 + ADPCM status */ + /* BUSY : x : PCMBUSY : ZERO : BRDY : EOS : FLAGB : FLAGA */ + ret = (FM_STATUS_FLAG(&F2608->OPN.ST) & (F2608->flagmask|0x80)) | ((F2608->deltaT.PCM_BSY & 1)<<5) ; + break; + + case 3: + if(addr == 0x08) + { + ret = YM_DELTAT_ADPCM_Read(&F2608->deltaT); + } + else + { + if(addr == 0x0f) + { + logerror("YM2608 A/D convertion is accessed but not implemented !\n"); + ret = 0x80; /* 2's complement PCM data - result from A/D convertion */ + } + } + break; + } + return ret; +} + +int YM2608TimerOver(int n,int c) +{ + YM2608 *F2608 = &(FM2608[n]); + + switch(c) + { +#if 0 + case 2: + { /* BUFRDY flag */ + YM_DELTAT_BRDY_callback( &F2608->deltaT ); + } + break; +#endif + case 1: + { /* Timer B */ + TimerBOver( &(F2608->OPN.ST) ); + } + break; + case 0: + { /* Timer A */ + YM2608UpdateReq(n); + /* timer update */ + TimerAOver( &(F2608->OPN.ST) ); + /* CSM mode key,TL controll */ + if( F2608->OPN.ST.mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + CSMKeyControll( F2608->OPN.type, &(F2608->CH[2]) ); + } + } + break; + default: + break; + } + + return FM2608->OPN.ST.irq; +} + +#endif /* BUILD_YM2608 */ + + + +#if (BUILD_YM2610||BUILD_YM2610B) +/* YM2610(OPNB) */ +static YM2610 *FM2610=NULL; /* array of YM2610's */ +static int YM2610NumChips; + +/* Generate samples for one of the YM2610s */ +void YM2610UpdateOne(int num, INT16 **buffer, int length) +{ + YM2610 *F2610 = &(FM2610[num]); + FM_OPN *OPN = &(FM2610[num].OPN); + YM_DELTAT *DELTAT = &(F2610[num].deltaT); + int i,j; + FMSAMPLE *bufL,*bufR; + + /* buffer setup */ + bufL = buffer[0]; + bufR = buffer[1]; + + if( (void *)F2610 != cur_chip ){ + cur_chip = (void *)F2610; + State = &OPN->ST; + cch[0] = &F2610->CH[1]; + cch[1] = &F2610->CH[2]; + cch[2] = &F2610->CH[4]; + cch[3] = &F2610->CH[5]; + /* setup adpcm rom address */ + pcmbufA = F2610->pcmbuf; + pcmsizeA = F2610->pcm_size; + + } +#ifdef YM2610B_WARNING +#define FM_KEY_IS(SLOT) ((SLOT)->key) +#define FM_MSG_YM2610B "YM2610-%d.CH%d is playing,Check whether the type of the chip is YM2610B\n" + /* Check YM2610B warning message */ + if( FM_KEY_IS(&F2610->CH[0].SLOT[3]) ) + LOG(LOG_WAR,(FM_MSG_YM2610B,num,0)); + if( FM_KEY_IS(&F2610->CH[3].SLOT[3]) ) + LOG(LOG_WAR,(FM_MSG_YM2610B,num,3)); +#endif + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, cch[0] ); + if( (State->mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[1]->SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT4] , cch[1]->fc , cch[1]->kcode ); + } + }else refresh_fc_eg_chan( OPN, cch[1] ); + refresh_fc_eg_chan( OPN, cch[2] ); + refresh_fc_eg_chan( OPN, cch[3] ); + + /* buffering */ + for(i=0; i < length ; i++) + { + + advance_lfo(OPN); + + /* clear output acc. */ + out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0; + out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0; + /* clear outputs */ + out_fm[1] = 0; + out_fm[2] = 0; + out_fm[4] = 0; + out_fm[5] = 0; + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + OPN->eg_timer -= OPN->eg_timer_overflow; + OPN->eg_cnt++; + + advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]); + } + + /* calculate FM */ + chan_calc(OPN, cch[0], 1 ); /*remapped to 1*/ + chan_calc(OPN, cch[1], 2 ); /*remapped to 2*/ + chan_calc(OPN, cch[2], 4 ); /*remapped to 4*/ + chan_calc(OPN, cch[3], 5 ); /*remapped to 5*/ + + /* deltaT ADPCM */ + if( DELTAT->portstate&0x80 ) + YM_DELTAT_ADPCM_CALC(DELTAT); + + /* ADPCMA */ + for( j = 0; j < 6; j++ ) + { + if( F2610->adpcm[j].flag ) + ADPCMA_calc_chan( F2610, &F2610->adpcm[j]); + } + + /* buffering */ + { + int lt,rt; + + lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER]; + rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER]; + lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9; + rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9; + + + lt += ((out_fm[1]>>1) & OPN->pan[2]); /* the shift right was verified on real chip */ + rt += ((out_fm[1]>>1) & OPN->pan[3]); + lt += ((out_fm[2]>>1) & OPN->pan[4]); + rt += ((out_fm[2]>>1) & OPN->pan[5]); + + lt += ((out_fm[4]>>1) & OPN->pan[8]); + rt += ((out_fm[4]>>1) & OPN->pan[9]); + lt += ((out_fm[5]>>1) & OPN->pan[10]); + rt += ((out_fm[5]>>1) & OPN->pan[11]); + + + lt >>= FINAL_SH; + rt >>= FINAL_SH; + + Limit( lt, MAXOUT, MINOUT ); + Limit( rt, MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* buffering */ + bufL[i] = lt; + bufR[i] = rt; + } + + /* timer A control */ + INTERNAL_TIMER_A( State , cch[1] ) + } + INTERNAL_TIMER_B(State,length) + +} + +#if BUILD_YM2610B +/* Generate samples for one of the YM2610Bs */ +void YM2610BUpdateOne(int num, INT16 **buffer, int length) +{ + YM2610 *F2610 = &(FM2610[num]); + FM_OPN *OPN = &(FM2610[num].OPN); + YM_DELTAT *DELTAT = &(FM2610[num].deltaT); + int i,j; + FMSAMPLE *bufL,*bufR; + + /* buffer setup */ + bufL = buffer[0]; + bufR = buffer[1]; + + if( (void *)F2610 != cur_chip ){ + cur_chip = (void *)F2610; + State = &OPN->ST; + cch[0] = &F2610->CH[0]; + cch[1] = &F2610->CH[1]; + cch[2] = &F2610->CH[2]; + cch[3] = &F2610->CH[3]; + cch[4] = &F2610->CH[4]; + cch[5] = &F2610->CH[5]; + /* setup adpcm rom address */ + pcmbufA = F2610->pcmbuf; + pcmsizeA = F2610->pcm_size; + + } + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, cch[0] ); + refresh_fc_eg_chan( OPN, cch[1] ); + if( (State->mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[2]->SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); + } + }else refresh_fc_eg_chan( OPN, cch[2] ); + refresh_fc_eg_chan( OPN, cch[3] ); + refresh_fc_eg_chan( OPN, cch[4] ); + refresh_fc_eg_chan( OPN, cch[5] ); + + /* buffering */ + for(i=0; i < length ; i++) + { + + advance_lfo(OPN); + + /* clear output acc. */ + out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0; + out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0; + /* clear outputs */ + out_fm[0] = 0; + out_fm[1] = 0; + out_fm[2] = 0; + out_fm[3] = 0; + out_fm[4] = 0; + out_fm[5] = 0; + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + OPN->eg_timer -= OPN->eg_timer_overflow; + OPN->eg_cnt++; + + advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]); + } + + /* calculate FM */ + chan_calc(OPN, cch[0], 0 ); + chan_calc(OPN, cch[1], 1 ); + chan_calc(OPN, cch[2], 2 ); + chan_calc(OPN, cch[3], 3 ); + chan_calc(OPN, cch[4], 4 ); + chan_calc(OPN, cch[5], 5 ); + + /* deltaT ADPCM */ + if( DELTAT->portstate&0x80 ) + YM_DELTAT_ADPCM_CALC(DELTAT); + + /* ADPCMA */ + for( j = 0; j < 6; j++ ) + { + if( F2610->adpcm[j].flag ) + ADPCMA_calc_chan( F2610, &F2610->adpcm[j]); + } + + /* buffering */ + { + int lt,rt; + + lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER]; + rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER]; + lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9; + rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9; + + lt += ((out_fm[0]>>1) & OPN->pan[0]); /* the shift right is verified on YM2610 */ + rt += ((out_fm[0]>>1) & OPN->pan[1]); + lt += ((out_fm[1]>>1) & OPN->pan[2]); + rt += ((out_fm[1]>>1) & OPN->pan[3]); + lt += ((out_fm[2]>>1) & OPN->pan[4]); + rt += ((out_fm[2]>>1) & OPN->pan[5]); + lt += ((out_fm[3]>>1) & OPN->pan[6]); + rt += ((out_fm[3]>>1) & OPN->pan[7]); + lt += ((out_fm[4]>>1) & OPN->pan[8]); + rt += ((out_fm[4]>>1) & OPN->pan[9]); + lt += ((out_fm[5]>>1) & OPN->pan[10]); + rt += ((out_fm[5]>>1) & OPN->pan[11]); + + + lt >>= FINAL_SH; + rt >>= FINAL_SH; + + Limit( lt, MAXOUT, MINOUT ); + Limit( rt, MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* buffering */ + bufL[i] = lt; + bufR[i] = rt; + } + + /* timer A control */ + INTERNAL_TIMER_A( State , cch[2] ) + } + INTERNAL_TIMER_B(State,length) + +} +#endif /* BUILD_YM2610B */ + + +#ifdef _STATE_H +static void YM2610_postload(void) +{ + int num , r; + + for(num=0;numREGS[r]); + } + + /* OPN registers */ + /* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */ + for(r=0x30;r<0x9e;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2610->OPN,r,F2610->REGS[r]); + OPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]); + } + /* FB / CONNECT , L / R / AMS / PMS */ + for(r=0xb0;r<0xb6;r++) + if((r&3) != 3) + { + OPNWriteReg(&F2610->OPN,r,F2610->REGS[r]); + OPNWriteReg(&F2610->OPN,r|0x100,F2610->REGS[r|0x100]); + } + /* FM channels */ + /*FM_channel_postload(F2610->CH,6);*/ + + /* rhythm(ADPCMA) */ + FM_ADPCMAWrite(F2610,1,F2610->REGS[0x101]); + for( r=0 ; r<6 ; r++) + { + FM_ADPCMAWrite(F2610,r+0x08,F2610->REGS[r+0x108]); + FM_ADPCMAWrite(F2610,r+0x10,F2610->REGS[r+0x110]); + FM_ADPCMAWrite(F2610,r+0x18,F2610->REGS[r+0x118]); + FM_ADPCMAWrite(F2610,r+0x20,F2610->REGS[r+0x120]); + FM_ADPCMAWrite(F2610,r+0x28,F2610->REGS[r+0x128]); + } + /* Delta-T ADPCM unit */ + YM_DELTAT_postload(&F2610->deltaT , &F2610->REGS[0x010] ); + } + cur_chip = NULL; +} + +static void YM2610_save_state(void) +{ + int num; + const char statename[] = "YM2610"; + + for(num=0;numREGS , 512); + FMsave_state_st(statename,num,&FM2610[num].OPN.ST); + FMsave_state_channel(statename,num,FM2610[num].CH,6); + /* 3slots */ + state_save_register_UINT32(statename, num, "slot3fc" , F2610->OPN.SL3.fc , 3); + state_save_register_UINT8 (statename, num, "slot3fh" , &F2610->OPN.SL3.fn_h, 1); + state_save_register_UINT8 (statename, num, "slot3kc" , F2610->OPN.SL3.kcode, 3); + /* address register1 */ + state_save_register_UINT8 (statename, num, "addr_A1" , &F2610->addr_A1, 1); + + state_save_register_UINT8 (statename, num, "arrivedFlag", &F2610->adpcm_arrivedEndAddress , 1); + /* rythm(ADPCMA) */ + FMsave_state_adpcma(statename,num,F2610->adpcm); + /* Delta-T ADPCM unit */ + YM_DELTAT_savestate(statename,num,&FM2610[num].deltaT); + } + state_save_register_func_postload(YM2610_postload); +} +#endif /* _STATE_H */ + +static void YM2610_deltat_status_set(UINT8 which, UINT8 changebits) +{ + FM2610[which].adpcm_arrivedEndAddress |= changebits; +} +static void YM2610_deltat_status_reset(UINT8 which, UINT8 changebits) +{ + FM2610[which].adpcm_arrivedEndAddress &= (~changebits); +} + +int YM2610Init(int num, int clock, int rate, + void **pcmroma,int *pcmsizea,void **pcmromb,int *pcmsizeb, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler) + +{ + int i; + + if (FM2610) return (-1); /* duplicate init. */ + cur_chip = NULL; /* hiro-shi!! */ + + YM2610NumChips = num; + + /* allocate extend state space */ + if( (FM2610 = (YM2610 *)malloc(sizeof(YM2610) * YM2610NumChips))==NULL) + return (-1); + /* clear */ + memset(FM2610,0,sizeof(YM2610) * YM2610NumChips); + /* allocate total level table (128kb space) */ + if( !init_tables() ) + { + if (FM2610) { + free( FM2610 ); + FM2610 = NULL; + } + return (-1); + } + + for ( i = 0 ; i < YM2610NumChips; i++ ) { + YM2610 *F2610 = &(FM2610[i]); + /* FM */ + F2610->OPN.ST.index = i; + F2610->OPN.type = TYPE_YM2610; + F2610->OPN.P_CH = FM2610[i].CH; + F2610->OPN.ST.clock = clock; + F2610->OPN.ST.rate = rate; + /* Extend handler */ + F2610->OPN.ST.Timer_Handler = TimerHandler; + F2610->OPN.ST.IRQ_Handler = IRQHandler; + /* ADPCM */ + F2610->pcmbuf = (UINT8 *)(pcmroma[i]); + F2610->pcm_size = pcmsizea[i]; + /* DELTA-T */ + F2610->deltaT.memory = (UINT8 *)(pcmromb[i]); + F2610->deltaT.memory_size = pcmsizeb[i]; + + FM2610[i].deltaT.status_set_handler = YM2610_deltat_status_set; + FM2610[i].deltaT.status_reset_handler = YM2610_deltat_status_reset; + FM2610[i].deltaT.status_change_which_chip = i; + FM2610[i].deltaT.status_change_EOS_bit = 0x80; /* status flag: set bit7 on End Of Sample */ + + YM2610ResetChip(i); + } + Init_ADPCMATable(); +#ifdef _STATE_H + YM2610_save_state(); +#endif + return 0; +} + +/* remap sample memory of chip */ +void YM2610SetRom(int num, void *pcmroma,int pcmsizea,void *pcmromb,int pcmsizeb) +{ + YM2610 *F2610 = &(FM2610[num]); + + /* ADPCM */ + F2610->pcmbuf = (UINT8 *)pcmroma; + F2610->pcm_size = pcmsizea; + /* DELTA-T */ + F2610->deltaT.memory = (UINT8 *)pcmromb; + F2610->deltaT.memory_size = pcmsizeb; + + if( (void *)F2610 == cur_chip ){ + pcmbufA = F2610->pcmbuf; + pcmsizeA = F2610->pcm_size; + } +} + +/* shut down emulator */ +void YM2610Shutdown() +{ + if (!FM2610) return; + + FMCloseTable(); + if (FM2610) { + free(FM2610); + FM2610 = NULL; + } +} + +/* reset one of chip */ +void YM2610ResetChip(int num) +{ + int i; + YM2610 *F2610 = &(FM2610[num]); + FM_OPN *OPN = &(FM2610[num].OPN); + YM_DELTAT *DELTAT = &(FM2610[num].deltaT); + + /* Reset Prescaler */ + OPNSetPres( OPN, 6*24, 6*24, 4*2); /* OPN 1/6 , SSG 1/4 */ + /* reset SSG section */ + SSGReset(OPN->ST.index); + /* status clear */ + FM_IRQMASK_SET(&OPN->ST,0x03); + FM_BUSY_CLEAR(&OPN->ST); + OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ + + OPN->eg_timer = 0; + OPN->eg_cnt = 0; + + FM_STATUS_RESET(&OPN->ST, 0xff); + + reset_channels( &OPN->ST , F2610->CH , 6 ); + /* reset OPerator paramater */ + for(i = 0xb6 ; i >= 0xb4 ; i-- ) + { + OPNWriteReg(OPN,i ,0xc0); + OPNWriteReg(OPN,i|0x100,0xc0); + } + for(i = 0xb2 ; i >= 0x30 ; i-- ) + { + OPNWriteReg(OPN,i ,0); + OPNWriteReg(OPN,i|0x100,0); + } + for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); + /**** ADPCM work initial ****/ + for( i = 0; i < 6 ; i++ ){ + F2610->adpcm[i].step = (UINT32)((float)(1<OPN.ST.freqbase)/3.0); + F2610->adpcm[i].now_addr = 0; + F2610->adpcm[i].now_step = 0; + F2610->adpcm[i].start = 0; + F2610->adpcm[i].end = 0; + /* F2610->adpcm[i].delta = 21866; */ + F2610->adpcm[i].vol_mul = 0; + F2610->adpcm[i].pan = &out_adpcm[OUTD_CENTER]; /* default center */ + F2610->adpcm[i].flagMask = 1<adpcm[i].flag = 0; + F2610->adpcm[i].adpcm_acc = 0; + F2610->adpcm[i].adpcm_step= 0; + F2610->adpcm[i].adpcm_out = 0; + } + F2610->adpcmTL = 0x3f; + + F2610->adpcm_arrivedEndAddress = 0; + + /* DELTA-T unit */ + DELTAT->freqbase = OPN->ST.freqbase; + DELTAT->output_pointer = out_delta; + DELTAT->portshift = 8; /* allways 8bits shift */ + DELTAT->output_range = 1<<23; + YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_YM2610); +} + +/* YM2610 write */ +/* n = number */ +/* a = address */ +/* v = value */ +int YM2610Write(int n, int a, UINT8 v) +{ + YM2610 *F2610 = &(FM2610[n]); + FM_OPN *OPN = &(FM2610[n].OPN); + int addr; + int ch; + + v &= 0xff; /* adjust to 8 bit bus */ + + switch( a&3 ){ + case 0: /* address port 0 */ + OPN->ST.address = v; + F2610->addr_A1 = 0; + + /* Write register to SSG emulator */ + if( v < 16 ) SSGWrite(n,0,v); + break; + + case 1: /* data port 0 */ + if (F2610->addr_A1 != 0) + break; /* verified on real YM2608 */ + + addr = OPN->ST.address; +#ifdef _STATE_H + F2610->REGS[addr] = v; +#endif + switch(addr & 0xf0) + { + case 0x00: /* SSG section */ + /* Write data to SSG emulator */ + SSGWrite(n,a,v); + break; + case 0x10: /* DeltaT ADPCM */ + YM2610UpdateReq(n); + + switch(addr) + { + case 0x10: /* control 1 */ + case 0x11: /* control 2 */ + case 0x12: /* start address L */ + case 0x13: /* start address H */ + case 0x14: /* stop address L */ + case 0x15: /* stop address H */ + + case 0x19: /* delta-n L */ + case 0x1a: /* delta-n H */ + case 0x1b: /* volume */ + { + YM_DELTAT_ADPCM_Write(&F2610->deltaT,addr-0x10,v); + } + break; + + case 0x1c: /* FLAG CONTROL : Extend Status Clear/Mask */ + { + UINT8 statusmask = ~v; + /* set arrived flag mask */ + for(ch=0;ch<6;ch++) + F2610->adpcm[ch].flagMask = statusmask&(1<deltaT.status_change_EOS_bit = statusmask & 0x80; /* status flag: set bit7 on End Of Sample */ + + /* clear arrived flag */ + F2610->adpcm_arrivedEndAddress &= statusmask; + } + break; + + default: + logerror("YM2610: write to unknown deltat register %02x val=%02x\n",addr,v); + break; + } + + break; + case 0x20: /* Mode Register */ + YM2610UpdateReq(n); + OPNWriteMode(OPN,addr,v); + break; + default: /* OPN section */ + YM2610UpdateReq(n); + /* write register */ + OPNWriteReg(OPN,addr,v); + } + break; + + case 2: /* address port 1 */ + OPN->ST.address = v; + F2610->addr_A1 = 1; + break; + + case 3: /* data port 1 */ + if (F2610->addr_A1 != 1) + break; /* verified on real YM2608 */ + + YM2610UpdateReq(n); + addr = OPN->ST.address; +#ifdef _STATE_H + F2610->REGS[addr | 0x100] = v; +#endif + if( addr < 0x30 ) + /* 100-12f : ADPCM A section */ + FM_ADPCMAWrite(F2610,addr,v); + else + OPNWriteReg(OPN,addr | 0x100,v); + } + return OPN->ST.irq; +} + +UINT8 YM2610Read(int n,int a) +{ + YM2610 *F2610 = &(FM2610[n]); + int addr = F2610->OPN.ST.address; + UINT8 ret = 0; + + switch( a&3){ + case 0: /* status 0 : YM2203 compatible */ + ret = FM_STATUS_FLAG(&F2610->OPN.ST) & 0x83; + break; + case 1: /* data 0 */ + if( addr < 16 ) ret = SSGRead(n); + if( addr == 0xff ) ret = 0x01; + break; + case 2: /* status 1 : ADPCM status */ + /* ADPCM STATUS (arrived End Address) */ + /* B,--,A5,A4,A3,A2,A1,A0 */ + /* B = ADPCM-B(DELTA-T) arrived end address */ + /* A0-A5 = ADPCM-A arrived end address */ + ret = F2610->adpcm_arrivedEndAddress; + break; + case 3: + ret = 0; + break; + } + return ret; +} + +int YM2610TimerOver(int n,int c) +{ + YM2610 *F2610 = &(FM2610[n]); + + if( c ) + { /* Timer B */ + TimerBOver( &(F2610->OPN.ST) ); + } + else + { /* Timer A */ + YM2610UpdateReq(n); + /* timer update */ + TimerAOver( &(F2610->OPN.ST) ); + /* CSM mode key,TL controll */ + if( F2610->OPN.ST.mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + CSMKeyControll( F2610->OPN.type, &(F2610->CH[2]) ); + } + } + return F2610->OPN.ST.irq; +} + +#endif /* (BUILD_YM2610||BUILD_YM2610B) */ + + + +#if BUILD_YM2612 +/*******************************************************************************/ +/* YM2612 local section */ +/*******************************************************************************/ +/* here's the virtual YM2612 */ +typedef struct +{ + UINT8 REGS[512]; /* registers */ + FM_OPN OPN; /* OPN state */ + FM_CH CH[6]; /* channel state */ + UINT8 addr_A1; /* address line A1 */ + + /* dac output (YM2612) */ + int dacen; + INT32 dacout; +} YM2612; + +static int YM2612NumChips; /* total chip */ +static YM2612 *FM2612=NULL; /* array of YM2612's */ + +static int dacen; + +/* Generate samples for one of the YM2612s */ +void YM2612UpdateOne(int num, INT16 **buffer, int length) +{ + YM2612 *F2612 = &(FM2612[num]); + FM_OPN *OPN = &(FM2612[num].OPN); + int i; + FMSAMPLE *bufL,*bufR; + INT32 dacout = F2612->dacout; + + /* set bufer */ + bufL = buffer[0]; + bufR = buffer[1]; + + if( (void *)F2612 != cur_chip ){ + cur_chip = (void *)F2612; + State = &OPN->ST; + cch[0] = &F2612->CH[0]; + cch[1] = &F2612->CH[1]; + cch[2] = &F2612->CH[2]; + cch[3] = &F2612->CH[3]; + cch[4] = &F2612->CH[4]; + cch[5] = &F2612->CH[5]; + /* DAC mode */ + dacen = F2612->dacen; + + } + + /* refresh PG and EG */ + refresh_fc_eg_chan( OPN, cch[0] ); + refresh_fc_eg_chan( OPN, cch[1] ); + if( (State->mode & 0xc0) ) + { + /* 3SLOT MODE */ + if( cch[2]->SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); + refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); + } + }else refresh_fc_eg_chan( OPN, cch[2] ); + refresh_fc_eg_chan( OPN, cch[3] ); + refresh_fc_eg_chan( OPN, cch[4] ); + refresh_fc_eg_chan( OPN, cch[5] ); + + /* buffering */ + for(i=0; i < length ; i++) + { + + advance_lfo(OPN); + + /* clear outputs */ + out_fm[0] = 0; + out_fm[1] = 0; + out_fm[2] = 0; + out_fm[3] = 0; + out_fm[4] = 0; + out_fm[5] = 0; + + /* calculate FM */ + chan_calc(OPN, cch[0], 0 ); + chan_calc(OPN, cch[1], 1 ); + chan_calc(OPN, cch[2], 2 ); + chan_calc(OPN, cch[3], 3 ); + chan_calc(OPN, cch[4], 4 ); + if( dacen ) + *cch[5]->connect4 += dacout; + else + chan_calc(OPN, cch[5], 5 ); + + /* advance envelope generator */ + OPN->eg_timer += OPN->eg_timer_add; + while (OPN->eg_timer >= OPN->eg_timer_overflow) + { + OPN->eg_timer -= OPN->eg_timer_overflow; + OPN->eg_cnt++; + + advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]); + advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]); + } + + { + int lt,rt; + + lt = ((out_fm[0]>>0) & OPN->pan[0]); + rt = ((out_fm[0]>>0) & OPN->pan[1]); + lt += ((out_fm[1]>>0) & OPN->pan[2]); + rt += ((out_fm[1]>>0) & OPN->pan[3]); + lt += ((out_fm[2]>>0) & OPN->pan[4]); + rt += ((out_fm[2]>>0) & OPN->pan[5]); + lt += ((out_fm[3]>>0) & OPN->pan[6]); + rt += ((out_fm[3]>>0) & OPN->pan[7]); + lt += ((out_fm[4]>>0) & OPN->pan[8]); + rt += ((out_fm[4]>>0) & OPN->pan[9]); + lt += ((out_fm[5]>>0) & OPN->pan[10]); + rt += ((out_fm[5]>>0) & OPN->pan[11]); + + lt >>= FINAL_SH; + rt >>= FINAL_SH; + + Limit( lt, MAXOUT, MINOUT ); + Limit( rt, MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* buffering */ + bufL[i] = lt; + bufR[i] = rt; + } + + /* timer A control */ + INTERNAL_TIMER_A( State , cch[2] ) + } + INTERNAL_TIMER_B(State,length) + +} + +#ifdef _STATE_H +static void YM2612_postload(void) +{ + int num , r; + + for(num=0;numST,0x03); + FM_BUSY_CLEAR(&OPN->ST); + OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ + + OPN->eg_timer = 0; + OPN->eg_cnt = 0; + + FM_STATUS_RESET(&OPN->ST, 0xff); + + reset_channels( &OPN->ST , &F2612->CH[0] , 6 ); + for(i = 0xb6 ; i >= 0xb4 ; i-- ) + { + OPNWriteReg(OPN,i ,0xc0); + OPNWriteReg(OPN,i|0x100,0xc0); + } + for(i = 0xb2 ; i >= 0x30 ; i-- ) + { + OPNWriteReg(OPN,i ,0); + OPNWriteReg(OPN,i|0x100,0); + } + for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); + /* DAC mode clear */ + F2612->dacen = 0; +} + +/* YM2612 write */ +/* n = number */ +/* a = address */ +/* v = value */ +int YM2612Write(int n, int a, UINT8 v) +{ + YM2612 *F2612 = &(FM2612[n]); + int addr; + + v &= 0xff; /* adjust to 8 bit bus */ + + switch( a&3){ + case 0: /* address port 0 */ + F2612->OPN.ST.address = v; + F2612->addr_A1 = 0; + break; + + case 1: /* data port 0 */ + if (F2612->addr_A1 != 0) + break; /* verified on real YM2608 */ + + addr = F2612->OPN.ST.address; +#ifdef _STATE_H + F2612->REGS[addr] = v; +#endif + switch( addr & 0xf0 ) + { + case 0x20: /* 0x20-0x2f Mode */ + switch( addr ) + { + case 0x2a: /* DAC data (YM2612) */ + YM2612UpdateReq(n); + F2612->dacout = ((int)v - 0x80) << 6; /* level unknown */ + break; + case 0x2b: /* DAC Sel (YM2612) */ + /* b7 = dac enable */ + F2612->dacen = v & 0x80; + cur_chip = NULL; + break; + default: /* OPN section */ + YM2612UpdateReq(n); + /* write register */ + OPNWriteMode(&(F2612->OPN),addr,v); + } + break; + default: /* 0x30-0xff OPN section */ + YM2612UpdateReq(n); + /* write register */ + OPNWriteReg(&(F2612->OPN),addr,v); + } + break; + + case 2: /* address port 1 */ + F2612->OPN.ST.address = v; + F2612->addr_A1 = 1; + break; + + case 3: /* data port 1 */ + if (F2612->addr_A1 != 1) + break; /* verified on real YM2608 */ + + addr = F2612->OPN.ST.address; +#ifdef _STATE_H + F2612->REGS[addr | 0x100] = v; +#endif + YM2612UpdateReq(n); + OPNWriteReg(&(F2612->OPN),addr | 0x100,v); + break; + } + return F2612->OPN.ST.irq; +} + +UINT8 YM2612Read(int n,int a) +{ + YM2612 *F2612 = &(FM2612[n]); + + switch( a&3){ + case 0: /* status 0 */ + return FM_STATUS_FLAG(&F2612->OPN.ST); + case 1: + case 2: + case 3: + LOG(LOG_WAR,("YM2612 #%d:A=%d read unmapped area\n",n,a)); + return FM_STATUS_FLAG(&F2612->OPN.ST); + } + return 0; +} + +int YM2612TimerOver(int n,int c) +{ + YM2612 *F2612 = &(FM2612[n]); + + if( c ) + { /* Timer B */ + TimerBOver( &(F2612->OPN.ST) ); + } + else + { /* Timer A */ + YM2612UpdateReq(n); + /* timer update */ + TimerAOver( &(F2612->OPN.ST) ); + /* CSM mode key,TL controll */ + if( F2612->OPN.ST.mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + CSMKeyControll( F2612->OPN.type, &(F2612->CH[2]) ); + } + } + return F2612->OPN.ST.irq; +} + +#endif /* BUILD_YM2612 */ diff --git a/src/burn/sound/fm.h b/src/burn/sound/fm.h new file mode 100644 index 00000000..d9677c1f --- /dev/null +++ b/src/burn/sound/fm.h @@ -0,0 +1,241 @@ +/* + File: fm.h -- header file for software emulation for FM sound generator + +*/ +#ifndef _H_FM_FM_ +#define _H_FM_FM_ + +/* --- select emulation chips --- */ +#define BUILD_YM2203 (HAS_YM2203) /* build YM2203(OPN) emulator */ +#define BUILD_YM2608 (HAS_YM2608) /* build YM2608(OPNA) emulator */ +#define BUILD_YM2610 (HAS_YM2610) /* build YM2610(OPNB) emulator */ +#define BUILD_YM2610B (HAS_YM2610B) /* build YM2610B(OPNB?)emulator */ +#define BUILD_YM2612 (HAS_YM2612 || HAS_YM3438) /* build YM2612(OPN2) emulator */ + +//#define BUILD_YM2151 (HAS_YM2151) /* build YM2151(OPM) emulator */ + +/* select bit size of output : 8 or 16 */ +#define FM_SAMPLE_BITS 16 + +/* select timer system internal or external */ +#define FM_INTERNAL_TIMER 0 + +/* --- speedup optimize --- */ +/* busy flag enulation , The definition of FM_GET_TIME_NOW() is necessary. */ +#define FM_BUSY_FLAG_SUPPORT 1 + +/* --- external SSG(YM2149/AY-3-8910)emulator interface port */ +/* used by YM2203,YM2608,and YM2610 */ + +/* SSGClk : Set SSG Clock */ +/* int n = chip number */ +/* int clk = MasterClock(Hz) */ +/* int rate = sample rate(Hz) */ +#define SSGClk(chip,clock) AY8910_set_clock((chip)+ay8910_index_ym,clock) + +/* SSGWrite : Write SSG port */ +/* int n = chip number */ +/* int a = address */ +/* int v = data */ +#define SSGWrite(n,a,v) AY8910Write((n)+ay8910_index_ym,a,v) + +/* SSGRead : Read SSG port */ +/* int n = chip number */ +/* return = Read data */ +#define SSGRead(n) AY8910Read((n)+ay8910_index_ym) + +/* SSGReset : Reset SSG chip */ +/* int n = chip number */ +#define SSGReset(chip) AY8910Reset((chip)+ay8910_index_ym) + + +/* --- external callback funstions for realtime update --- */ + +/* for busy flag emulation , function FM_GET_TIME_NOW() should */ +/* return present time in seconds with "double" precision */ + /* in timer.c */ + #define FM_GET_TIME_NOW() timer_get_time() + +#if BUILD_YM2203 + /* in 2203intf.c */ +void BurnYM2203UpdateRequest(void); + #define YM2203UpdateReq(chip) BurnYM2203UpdateRequest() +#endif +#if BUILD_YM2608 + /* in 2608intf.c */ +void BurnYM2608UpdateRequest(void); + #define YM2608UpdateReq(chip) BurnYM2608UpdateRequest() +#endif +#if BUILD_YM2610 + /* in 2610intf.c */ +void BurnYM2610UpdateRequest(void); +#define YM2610UpdateReq(chip) BurnYM2610UpdateRequest() +#endif +#if BUILD_YM2612 + /* in 2612intf.c */ +void BurnYM2612UpdateRequest(void); + #define YM2612UpdateReq(chip) BurnYM2612UpdateRequest() +#endif +#if 0 //BUILD_YM2151 + /* in 2151intf.c */ + #define YM2151UpdateReq(chip) YM2151UpdateRequest(chip); +#endif + +/* compiler dependence */ +#if 0 +#ifndef OSD_CPU_H +#define OSD_CPU_H +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif +#endif + +#ifndef INLINE +#define INLINE static __inline__ +#endif + + + + + +#if (FM_SAMPLE_BITS==16) +typedef INT16 FMSAMPLE; +#endif +#if (FM_SAMPLE_BITS==8) +typedef unsigned char FMSAMPLE; +#endif + +typedef void (*FM_TIMERHANDLER)(int n,int c,int cnt,double stepTime); +typedef void (*FM_IRQHANDLER)(int n,int irq); +/* FM_TIMERHANDLER : Stop or Start timer */ +/* int n = chip number */ +/* int c = Channel 0=TimerA,1=TimerB */ +/* int count = timer count (0=stop) */ +/* doube stepTime = step time of one count (sec.)*/ + +/* FM_IRQHHANDLER : IRQ level changing sense */ +/* int n = chip number */ +/* int irq = IRQ level 0=OFF,1=ON */ + +//#if BUILD_YM2203 +#if 1 +/* -------------------- YM2203(OPN) Interface -------------------- */ + +/* +** Initialize YM2203 emulator(s). +** +** 'num' is the number of virtual YM2203's to allocate +** 'baseclock' +** 'rate' is sampling rate +** 'TimerHandler' timer callback handler when timer start and clear +** 'IRQHandler' IRQ callback handler when changed IRQ level +** return 0 = success +*/ +int YM2203Init(int num, int baseclock, int rate, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); + +/* +** shutdown the YM2203 emulators +*/ +void YM2203Shutdown(void); + +/* +** reset all chip registers for YM2203 number 'num' +*/ +void YM2203ResetChip(int num); + +/* +** update one of chip +*/ +void YM2203UpdateOne(int num, INT16 *buffer, int length); + +/* +** Write +** return : InterruptLevel +*/ +int YM2203Write(int n,int a,unsigned char v); + +/* +** Read +** return : InterruptLevel +*/ +unsigned char YM2203Read(int n,int a); + +/* +** Timer OverFlow +*/ +int YM2203TimerOver(int n, int c); + +#endif /* BUILD_YM2203 */ + +#if BUILD_YM2608 +/* -------------------- YM2608(OPNA) Interface -------------------- */ +int YM2608Init(int num, int baseclock, int rate, + void **pcmroma,int *pcmsizea, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); +void YM2608Shutdown(void); +void YM2608ResetChip(int num); +void YM2608UpdateOne(int num, INT16 **buffer, int length); + +int YM2608Write(int n, int a,unsigned char v); +unsigned char YM2608Read(int n,int a); +int YM2608TimerOver(int n, int c ); +#endif /* BUILD_YM2608 */ + +#if (BUILD_YM2610||BUILD_YM2610B) +/* -------------------- YM2610(OPNB) Interface -------------------- */ +int YM2610Init(int num, int baseclock, int rate, + void **pcmroma,int *pcmasize,void **pcmromb,int *pcmbsize, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); +void YM2610SetRom(int num, + void *pcmroma,int pcmsizea,void *pcmromb,int pcmsizeb); +void YM2610Shutdown(void); +void YM2610ResetChip(int num); +void YM2610UpdateOne(int num, INT16 **buffer, int length); +#if BUILD_YM2610B +void YM2610BUpdateOne(int num, INT16 **buffer, int length); +#endif + +int YM2610Write(int n, int a,unsigned char v); +unsigned char YM2610Read(int n,int a); +int YM2610TimerOver(int n, int c ); +#endif /* BUILD_YM2610 */ + +#if BUILD_YM2612 +int YM2612Init(int num, int baseclock, int rate, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); +void YM2612Shutdown(void); +void YM2612ResetChip(int num); +void YM2612UpdateOne(int num, INT16 **buffer, int length); + +int YM2612Write(int n, int a,unsigned char v); +unsigned char YM2612Read(int n,int a); +int YM2612TimerOver(int n, int c ); +#endif /* BUILD_YM2612 */ + +#if 0 //BUILD_YM2151 +/* -------------------- YM2151(OPM) Interface -------------------- */ +int OPMInit(int num, int baseclock, int rate, + FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); +void OPMShutdown(void); +void OPMResetChip(int num); + +void OPMUpdateOne(int num, INT16 **buffer, int length ); +/* ---- set callback hander when port CT0/1 write ----- */ +/* CT.bit0 = CT0 , CT.bit1 = CT1 */ +/* +typedef void (*write8_handler)(int offset,int data); +*/ +void OPMSetPortHander(int n,write8_handler PortWrite); +/* JB 981119 - so it will match MAME's memory write functions scheme*/ + +int YM2151Write(int n,int a,unsigned char v); +unsigned char YM2151Read(int n,int a); +int YM2151TimerOver(int n,int c); +#endif /* BUILD_YM2151 */ + +#endif /* _H_FM_FM_ */ diff --git a/src/burn/sound/fmopl.c b/src/burn/sound/fmopl.c new file mode 100644 index 00000000..ec59a8c3 --- /dev/null +++ b/src/burn/sound/fmopl.c @@ -0,0 +1,2522 @@ +/* +** +** File: fmopl.c - software implementation of FM sound generator +** types OPL and OPL2 +** +** Copyright (C) 2002,2003 Jarek Burczynski (bujar at mame dot net) +** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmulator development +** +** Version 0.72 +** + +Revision History: + +04-08-2003 Jarek Burczynski: + - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip + handles memory read/write or during the adpcm synthesis when the chip + requests another byte of ADPCM data. + +24-07-2003 Jarek Burczynski: + - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after + some (unknown) delay). Right now it's always set. + +14-06-2003 Jarek Burczynski: + - implemented all of the status register flags in Y8950 emulation + - renamed Y8950SetDeltaTMemory() parameters from _rom_ to _mem_ since + they can be either RAM or ROM + +08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip) + - corrected YM3526Read() to always set bit 2 and bit 1 + to HIGH state - identical to YM3812Read (verified on real YM3526) + +04-28-2002 Jarek Burczynski: + - binary exact Envelope Generator (verified on real YM3812); + compared to YM2151: the EG clock is equal to internal_clock, + rates are 2 times slower and volume resolution is one bit less + - modified interface functions (they no longer return pointer - + that's internal to the emulator now): + - new wrapper functions for OPLCreate: YM3526Init(), YM3812Init() and Y8950Init() + - corrected 'off by one' error in feedback calculations (when feedback is off) + - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22) + - speeded up noise generator calculations (Nicola Salmoria) + +03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip) + Complete rewrite (all verified on real YM3812): + - corrected sin_tab and tl_tab data + - corrected operator output calculations + - corrected waveform_select_enable register; + simply: ignore all writes to waveform_select register when + waveform_select_enable == 0 and do not change the waveform previously selected. + - corrected KSR handling + - corrected Envelope Generator: attack shape, Sustain mode and + Percussive/Non-percussive modes handling + - Envelope Generator rates are two times slower now + - LFO amplitude (tremolo) and phase modulation (vibrato) + - rhythm sounds phase generation + - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm) + - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM) + - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1) + +12-28-2001 Acho A. Tang + - reflected Delta-T EOS status on Y8950 status port. + - fixed subscription range of attack/decay tables + + + To do: + add delay before key off in CSM mode (see CSMKeyControll) + verify volume of the FM part on the Y8950 +*/ + +#include +#include +#include + +#include "driver.h" /* use M.A.M.E. */ + +#include "ymdeltat.h" + +#include "fmopl.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + + + +/* output final shift */ +#if (OPL_SAMPLE_BITS==16) + #define FINAL_SH (0) + #define MAXOUT (+32767) + #define MINOUT (-32768) +#else + #define FINAL_SH (8) + #define MAXOUT (+127) + #define MINOUT (-128) +#endif + + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (EG timing) */ +#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define FREQ_MASK ((1<=0) + { + if (value < 0x0200) + return (value & ~0); + if (value < 0x0400) + return (value & ~1); + if (value < 0x0800) + return (value & ~3); + if (value < 0x1000) + return (value & ~7); + if (value < 0x2000) + return (value & ~15); + if (value < 0x4000) + return (value & ~31); + return (value & ~63); + } + /*else value < 0*/ + if (value > -0x0200) + return (~abs(value) & ~0); + if (value > -0x0400) + return (~abs(value) & ~1); + if (value > -0x0800) + return (~abs(value) & ~3); + if (value > -0x1000) + return (~abs(value) & ~7); + if (value > -0x2000) + return (~abs(value) & ~15); + if (value > -0x4000) + return (~abs(value) & ~31); + return (~abs(value) & ~63); +} + + +static FILE *sample[1]; + #if 1 /*save to MONO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = acc_calc(lt); \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #else /*save to STEREO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = rt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #endif +#endif + +/* #define LOG_CYM_FILE */ +#ifdef LOG_CYM_FILE + FILE * cymfile = NULL; +#endif + + + +#define OPL_TYPE_WAVESEL 0x01 /* waveform select */ +#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ +#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ +#define OPL_TYPE_IO 0x08 /* I/O port */ + +/* ---------- Generic interface section ---------- */ +#define OPL_TYPE_YM3526 (0) +#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) +#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) + + + +typedef struct{ + UINT32 ar; /* attack rate: AR<<2 */ + UINT32 dr; /* decay rate: DR<<2 */ + UINT32 rr; /* release rate:RR<<2 */ + UINT8 KSR; /* key scale rate */ + UINT8 ksl; /* keyscale level */ + UINT8 ksr; /* key scale rate: kcode>>KSR */ + UINT8 mul; /* multiple: mul_tab[ML] */ + + /* Phase Generator */ + UINT32 Cnt; /* frequency counter */ + UINT32 Incr; /* frequency counter step */ + UINT8 FB; /* feedback shift value */ + INT32 *connect1; /* slot1 output pointer */ + INT32 op1_out[2]; /* slot1 output for feedback */ + UINT8 CON; /* connection (algorithm) type */ + + /* Envelope Generator */ + UINT8 eg_type; /* percussive/non-percussive mode */ + UINT8 state; /* phase type */ + UINT32 TL; /* total level: TL << 2 */ + INT32 TLL; /* adjusted now TL */ + INT32 volume; /* envelope counter */ + UINT32 sl; /* sustain level: sl_tab[SL] */ + UINT8 eg_sh_ar; /* (attack state) */ + UINT8 eg_sel_ar; /* (attack state) */ + UINT8 eg_sh_dr; /* (decay state) */ + UINT8 eg_sel_dr; /* (decay state) */ + UINT8 eg_sh_rr; /* (release state) */ + UINT8 eg_sel_rr; /* (release state) */ + UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ + + /* LFO */ + UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ + UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ + + /* waveform select */ + unsigned int wavetable; +} OPL_SLOT; + +typedef struct{ + OPL_SLOT SLOT[2]; + /* phase generator state */ + UINT32 block_fnum; /* block+fnum */ + UINT32 fc; /* Freq. Increment base */ + UINT32 ksl_base; /* KeyScaleLevel Base step */ + UINT8 kcode; /* key code (for key scaling) */ +} OPL_CH; + +/* OPL state */ +typedef struct fm_opl_f { + /* FM channel slots */ + OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/ + + UINT32 eg_cnt; /* global envelope generator counter */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */ + UINT32 eg_timer_add; /* step of eg_timer */ + UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */ + + UINT8 rhythm; /* Rhythm mode */ + + UINT32 fn_tab[1024]; /* fnumber->increment counter */ + + /* LFO */ + UINT8 lfo_am_depth; + UINT8 lfo_pm_depth_range; + UINT32 lfo_am_cnt; + UINT32 lfo_am_inc; + UINT32 lfo_pm_cnt; + UINT32 lfo_pm_inc; + + UINT32 noise_rng; /* 23 bit noise shift register */ + UINT32 noise_p; /* current noise 'phase' */ + UINT32 noise_f; /* current noise period */ + + UINT8 wavesel; /* waveform select enable flag */ + + int T[2]; /* timer counters */ + UINT8 st[2]; /* timer enable */ + +#if BUILD_Y8950 + /* Delta-T ADPCM unit (Y8950) */ + + YM_DELTAT *deltat; + + /* Keyboard and I/O ports interface */ + UINT8 portDirection; + UINT8 portLatch; + OPL_PORTHANDLER_R porthandler_r; + OPL_PORTHANDLER_W porthandler_w; + int port_param; + OPL_PORTHANDLER_R keyboardhandler_r; + OPL_PORTHANDLER_W keyboardhandler_w; + int keyboard_param; +#endif + + /* external event callback handlers */ + OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ + int TimerParam; /* TIMER parameter */ + OPL_IRQHANDLER IRQHandler; /* IRQ handler */ + int IRQParam; /* IRQ parameter */ + OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */ + int UpdateParam; /* stream update parameter */ + + UINT8 type; /* chip type */ + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + UINT8 statusmask; /* status mask */ + UINT8 mode; /* Reg.08 : CSM,notesel,etc. */ + + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ + double TimerBase; /* Timer base time (==sampling time)*/ +} FM_OPL; + + + +/* mapping of register number (offset) to slot number used by the emulator */ +static const int slot_array[32]= +{ + 0, 2, 4, 1, 3, 5,-1,-1, + 6, 8,10, 7, 9,11,-1,-1, + 12,14,16,13,15,17,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1 +}; + +/* key scale level */ +/* table is 3dB/octave , DV converts this into 6dB/octave */ +/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ +#define DV (0.1875/2.0) +static const UINT32 ksl_tab[8*16]= +{ + /* OCT 0 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + /* OCT 1 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, + 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, + /* OCT 2 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, + 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, + 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, + /* OCT 3 */ + 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, + 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, + 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, + 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, + /* OCT 4 */ + 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, + 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, + 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, + 10.875/DV,11.250/DV,11.625/DV,12.000/DV, + /* OCT 5 */ + 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, + 9.000/DV,10.125/DV,10.875/DV,11.625/DV, + 12.000/DV,12.750/DV,13.125/DV,13.500/DV, + 13.875/DV,14.250/DV,14.625/DV,15.000/DV, + /* OCT 6 */ + 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, + 12.000/DV,13.125/DV,13.875/DV,14.625/DV, + 15.000/DV,15.750/DV,16.125/DV,16.500/DV, + 16.875/DV,17.250/DV,17.625/DV,18.000/DV, + /* OCT 7 */ + 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, + 15.000/DV,16.125/DV,16.875/DV,17.625/DV, + 18.000/DV,18.750/DV,19.125/DV,19.500/DV, + 19.875/DV,20.250/DV,20.625/DV,21.000/DV +}; +#undef DV + +/* sustain level table (3dB per step) */ +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ +#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) ) +static const UINT32 sl_tab[16]={ + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) +}; +#undef SC + + +#define RATE_STEPS (8) +static const unsigned char eg_inc[15*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */ +/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */ +/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; + + +#define O(a) (a*RATE_STEPS) + +/*note that there is no O(13) in this table - it's directly in the code */ +static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */ +/* 16 infinite time rates */ +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), + +/* rates 00-12 */ +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 13 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 14 */ +O( 8),O( 9),O(10),O(11), + +/* rate 15 */ +O(12),O(12),O(12),O(12), + +/* 16 dummy rates (same as 15 3) */ +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ +/*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */ +/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */ + +#define O(a) (a*1) +static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */ +/* 16 infinite time rates */ +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), + +/* rates 00-12 */ +O(12),O(12),O(12),O(12), +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), +O( 0),O( 0),O( 0),O( 0), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 16 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), + +}; +#undef O + + +/* multiple table */ +#define ML 2 +static const UINT8 mul_tab[16]= { +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ + 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, + 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML +}; +#undef ML + +/* TL_TAB_LEN is calculated as: +* 12 - sinus amplitude bits (Y axis) +* 2 - sinus sign bit (Y axis) +* TL_RES_LEN - sinus resolution (X axis) +*/ +#define TL_TAB_LEN (12*2*TL_RES_LEN) +static signed int tl_tab[TL_TAB_LEN]; + +#define ENV_QUIET (TL_TAB_LEN>>4) + +/* sin waveform table in 'decibel' scale */ +/* four waveforms on OPL2 type chips */ +static unsigned int sin_tab[SIN_LEN * 4]; + + +/* LFO Amplitude Modulation table (verified on real YM3812) + 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples + + Length: 210 elements. + + Each of the elements has to be repeated + exactly 64 times (on 64 consecutive samples). + The whole table takes: 64 * 210 = 13440 samples. + + When AM = 1 data is used directly + When AM = 0 data is divided by 4 before being used (loosing precision is important) +*/ + +#define LFO_AM_TAB_ELEMENTS 210 + +static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { +0,0,0,0,0,0,0, +1,1,1,1, +2,2,2,2, +3,3,3,3, +4,4,4,4, +5,5,5,5, +6,6,6,6, +7,7,7,7, +8,8,8,8, +9,9,9,9, +10,10,10,10, +11,11,11,11, +12,12,12,12, +13,13,13,13, +14,14,14,14, +15,15,15,15, +16,16,16,16, +17,17,17,17, +18,18,18,18, +19,19,19,19, +20,20,20,20, +21,21,21,21, +22,22,22,22, +23,23,23,23, +24,24,24,24, +25,25,25,25, +26,26,26, +25,25,25,25, +24,24,24,24, +23,23,23,23, +22,22,22,22, +21,21,21,21, +20,20,20,20, +19,19,19,19, +18,18,18,18, +17,17,17,17, +16,16,16,16, +15,15,15,15, +14,14,14,14, +13,13,13,13, +12,12,12,12, +11,11,11,11, +10,10,10,10, +9,9,9,9, +8,8,8,8, +7,7,7,7, +6,6,6,6, +5,5,5,5, +4,4,4,4, +3,3,3,3, +2,2,2,2, +1,1,1,1 +}; + +/* LFO Phase Modulation table (verified on real YM3812) */ +static const INT8 lfo_pm_table[8*8*2] = { + +/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ +4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ +5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ +6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ +7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/ +}; + + +/* lock level of common table */ +static int num_lock = 0; + + +static void *cur_chip = NULL; /* current chip pointer */ +static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2; + +static signed int phase_modulation; /* phase modulation input (SLOT 2) */ +static signed int output[1]; + +#if BUILD_Y8950 +static INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */ +#endif + +static UINT32 LFO_AM; +static INT32 LFO_PM; + + + +INLINE int limit( int val, int max, int min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; + + return val; +} + + +/* status set and IRQ handling */ +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag) +{ + /* set status flag */ + OPL->status |= flag; + if(!(OPL->status & 0x80)) + { + if(OPL->status & OPL->statusmask) + { /* IRQ on */ + OPL->status |= 0x80; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); + } + } +} + +/* status reset and IRQ handling */ +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag) +{ + /* reset status flag */ + OPL->status &=~flag; + if((OPL->status & 0x80)) + { + if (!(OPL->status & OPL->statusmask) ) + { + OPL->status &= 0x7f; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); + } + } +} + +/* IRQ mask set */ +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) +{ + OPL->statusmask = flag; + /* IRQ handling check */ + OPL_STATUS_SET(OPL,0); + OPL_STATUS_RESET(OPL,0); +} + + +/* advance LFO to next sample */ +INLINE void advance_lfo(FM_OPL *OPL) +{ + UINT8 tmp; + + /* LFO */ + OPL->lfo_am_cnt += OPL->lfo_am_inc; + if (OPL->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ]; + + if (OPL->lfo_am_depth) + LFO_AM = tmp; + else + LFO_AM = tmp>>2; + + OPL->lfo_pm_cnt += OPL->lfo_pm_inc; + LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range; +} + +/* advance to next sample */ +INLINE void advance(FM_OPL *OPL) +{ + OPL_CH *CH; + OPL_SLOT *op; + int i; + + OPL->eg_timer += OPL->eg_timer_add; + + while (OPL->eg_timer >= OPL->eg_timer_overflow) + { + OPL->eg_timer -= OPL->eg_timer_overflow; + + OPL->eg_cnt++; + + for (i=0; i<9*2; i++) + { + CH = &OPL->P_CH[i/2]; + op = &CH->SLOT[i&1]; + + /* Envelope Generator */ + switch(op->state) + { + case EG_ATT: /* attack phase */ + if ( !(OPL->eg_cnt & ((1<eg_sh_ar)-1) ) ) + { + op->volume += (~op->volume * + (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)]) + ) >>3; + + if (op->volume <= MIN_ATT_INDEX) + { + op->volume = MIN_ATT_INDEX; + op->state = EG_DEC; + } + + } + break; + + case EG_DEC: /* decay phase */ + if ( !(OPL->eg_cnt & ((1<eg_sh_dr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)]; + + if ( op->volume >= op->sl ) + op->state = EG_SUS; + + } + break; + + case EG_SUS: /* sustain phase */ + + /* this is important behaviour: + one can change percusive/non-percussive modes on the fly and + the chip will remain in sustain phase - verified on real YM3812 */ + + if(op->eg_type) /* non-percussive mode */ + { + /* do nothing */ + } + else /* percussive mode */ + { + /* during sustain phase chip adds Release Rate (in percussive mode) */ + if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + op->volume = MAX_ATT_INDEX; + } + /* else do nothing in sustain phase */ + } + break; + + case EG_REL: /* release phase */ + if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + + } + break; + + default: + break; + } + } + } + + for (i=0; i<9*2; i++) + { + CH = &OPL->P_CH[i/2]; + op = &CH->SLOT[i&1]; + + /* Phase Generator */ + if(op->vib) + { + UINT8 block; + unsigned int block_fnum = CH->block_fnum; + + unsigned int fnum_lfo = (block_fnum&0x0380) >> 7; + + signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + block_fnum += lfo_fn_table_index_offset; + block = (block_fnum&0x1c00) >> 10; + op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; + } + else /* LFO phase modulation = zero */ + { + op->Cnt += op->Incr; + } + } + else /* LFO phase modulation disabled for this operator */ + { + op->Cnt += op->Incr; + } + } + + /* The Noise Generator of the YM3812 is 23-bit shift register. + * Period is equal to 2^23-2 samples. + * Register works at sampling frequency of the chip, so output + * can change on every sample. + * + * Output of the register and input to the bit 22 is: + * bit0 XOR bit14 XOR bit15 XOR bit22 + * + * Simply use bit 22 as the noise output. + */ + + OPL->noise_p += OPL->noise_f; + i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ + OPL->noise_p &= FREQ_MASK; + while (i) + { + /* + UINT32 j; + j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1; + OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1); + */ + + /* + Instead of doing all the logic operations above, we + use a trick here (and use bit 0 as the noise output). + The difference is only that the noise bit changes one + step ahead. This doesn't matter since we don't know + what is real state of the noise_rng after the reset. + */ + + if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302; + OPL->noise_rng >>= 1; + + i--; + } +} + + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) +{ + UINT32 p; + + p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) +{ + UINT32 p; + + p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + + +#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask)) + +/* calculate output */ +INLINE void OPL_CALC_CH( OPL_CH *CH ) +{ + OPL_SLOT *SLOT; + unsigned int env; + signed int out; + + phase_modulation = 0; + + /* SLOT 1 */ + SLOT = &CH->SLOT[SLOT1]; + env = volume_calc(SLOT); + out = SLOT->op1_out[0] + SLOT->op1_out[1]; + SLOT->op1_out[0] = SLOT->op1_out[1]; + *SLOT->connect1 += SLOT->op1_out[0]; + SLOT->op1_out[1] = 0; + if( env < ENV_QUIET ) + { + if (!SLOT->FB) + out = 0; + SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); + } + + /* SLOT 2 */ + SLOT++; + env = volume_calc(SLOT); + if( env < ENV_QUIET ) + output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable); +} + +/* + operators used in the rhythm sounds generation process: + + Envelope Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal + 6 / 0 12 50 70 90 f0 + + 6 / 1 15 53 73 93 f3 + + 7 / 0 13 51 71 91 f1 + + 7 / 1 16 54 74 94 f4 + + 8 / 0 14 52 72 92 f2 + + 8 / 1 17 55 75 95 f5 + + + Phase Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number MULTIPLE Drum Hat Drum Tom Cymbal + 6 / 0 12 30 + + 6 / 1 15 33 + + 7 / 0 13 31 + + + + 7 / 1 16 34 ----- n o t u s e d ----- + 8 / 0 14 32 + + 8 / 1 17 35 + + + +channel operator register number Bass High Snare Tom Top +number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal + 6 12,15 B6 A6 + + + 7 13,16 B7 A7 + + + + + 8 14,17 B8 A8 + + + + +*/ + +/* calculate rhythm */ + +INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) +{ + OPL_SLOT *SLOT; + signed int out; + unsigned int env; + + + /* Bass Drum (verified on real YM3812): + - depends on the channel 6 'connect' register: + when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) + when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored + - output sample always is multiplied by 2 + */ + + phase_modulation = 0; + /* SLOT 1 */ + SLOT = &CH[6].SLOT[SLOT1]; + env = volume_calc(SLOT); + + out = SLOT->op1_out[0] + SLOT->op1_out[1]; + SLOT->op1_out[0] = SLOT->op1_out[1]; + + if (!SLOT->CON) + phase_modulation = SLOT->op1_out[0]; + /* else ignore output of operator 1 */ + + SLOT->op1_out[1] = 0; + if( env < ENV_QUIET ) + { + if (!SLOT->FB) + out = 0; + SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); + } + + /* SLOT 2 */ + SLOT++; + env = volume_calc(SLOT); + if( env < ENV_QUIET ) + output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2; + + + /* Phase generation is based on: */ + /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */ + /* SD (16) channel 7->slot 1 */ + /* TOM (14) channel 8->slot 1 */ + /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */ + + /* Envelope generation based on: */ + /* HH channel 7->slot1 */ + /* SD channel 7->slot2 */ + /* TOM channel 8->slot1 */ + /* TOP channel 8->slot2 */ + + + /* The following formulas can be well optimized. + I leave them in direct form for now (in case I've missed something). + */ + + /* High Hat (verified on real YM3812) */ + env = volume_calc(SLOT7_1); + if( env < ENV_QUIET ) + { + + /* high hat phase generation: + phase = d0 or 234 (based on frequency only) + phase = 34 or 2d0 (based on noise) + */ + + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0xd0; */ + /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ + UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e ^ bit5e); + + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ + if (res2) + phase = (0x200|(0xd0>>2)); + + + /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ + /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ + if (phase&0x200) + { + if (noise) + phase = 0x200|0xd0; + } + else + /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ + /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ + { + if (noise) + phase = 0xd0>>2; + } + + output[0] += op_calc(phase<wavetable) * 2; + } + + /* Snare Drum (verified on real YM3812) */ + env = volume_calc(SLOT7_2); + if( env < ENV_QUIET ) + { + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1; + + /* when bit8 = 0 phase = 0x100; */ + /* when bit8 = 1 phase = 0x200; */ + UINT32 phase = bit8 ? 0x200 : 0x100; + + /* Noise bit XOR'es phase by 0x100 */ + /* when noisebit = 0 pass the phase from calculation above */ + /* when noisebit = 1 phase ^= 0x100; */ + /* in other words: phase ^= (noisebit<<8); */ + if (noise) + phase ^= 0x100; + + output[0] += op_calc(phase<wavetable) * 2; + } + + /* Tom Tom (verified on real YM3812) */ + env = volume_calc(SLOT8_1); + if( env < ENV_QUIET ) + output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2; + + /* Top Cymbal (verified on real YM3812) */ + env = volume_calc(SLOT8_2); + if( env < ENV_QUIET ) + { + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0x100; */ + /* when res1 = 1 phase = 0x200 | 0x100; */ + UINT32 phase = res1 ? 0x300 : 0x100; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e ^ bit5e); + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | 0x100; */ + if (res2) + phase = 0x300; + + output[0] += op_calc(phase<wavetable) * 2; + } + +} + + +/* generic table initialize */ +static int init_tables(void) +{ + signed int i,x; + signed int n; + double o,m; + + + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 1; /* 12 bits here (as in real chip) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + for (i=1; i<12; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + #if 0 + logerror("tl %04i", x*2); + for (i=0; i<12; i++) + logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] ); + logerror("\n"); + #endif + } + /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ + + + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + + /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ + } + + for (i=0; i>1) ]; + + /* waveform 3: _ _ _ _ */ + /* / |_/ |_/ |_/ |_*/ + /* abs(output only first quarter of the sinus waveform) */ + + if (i & (1<<(SIN_BITS-2)) ) + sin_tab[3*SIN_LEN+i] = TL_TAB_LEN; + else + sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)]; + + /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] ); + logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] ); + logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/ + } + /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/ + + +#ifdef SAVE_SAMPLE + sample[0]=fopen("sampsum.pcm","wb"); +#endif + + return 1; +} + +static void OPLCloseTable( void ) +{ +#ifdef SAVE_SAMPLE + fclose(sample[0]); +#endif +} + + + +static void OPL_initalize(FM_OPL *OPL) +{ + int i; + + /* frequency base */ + OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0; +#if 0 + OPL->rate = (double)OPL->clock / 72.0; + OPL->freqbase = 1.0; +#endif + + /*logerror("freqbase=%f\n", OPL->freqbase);*/ + + /* Timer base time */ + OPL->TimerBase = 1.0 / ((double)OPL->clock / 72.0 ); + + /* make fnumber -> increment counter table */ + for( i=0 ; i < 1024 ; i++ ) + { + /* opn phase increment counter = 20bit */ + OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ +#if 0 + logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n", + i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 ); +#endif + } + +#if 0 + for( i=0 ; i < 16 ; i++ ) + { + logerror("FMOPL.C: sl_tab[%i] = %08x\n", + i, sl_tab[i] ); + } + for( i=0 ; i < 8 ; i++ ) + { + int j; + logerror("FMOPL.C: ksl_tab[oct=%2i] =",i); + for (j=0; j<16; j++) + { + logerror("%08x ", ksl_tab[i*16+j] ); + } + logerror("\n"); + } +#endif + + + /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ + /* One entry from LFO_AM_TABLE lasts for 64 samples */ + OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase; + + /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ + OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase; + + /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/ + + /* Noise generator: a step takes 1 sample */ + OPL->noise_f = (1.0 / 1.0) * (1<freqbase; + + OPL->eg_timer_add = (1<freqbase; + OPL->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, OPL->eg_timer_overflow);*/ + +} + +INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set) +{ + if( !SLOT->key ) + { + /* restart Phase Generator */ + SLOT->Cnt = 0; + /* phase -> Attack */ + SLOT->state = EG_ATT; + } + SLOT->key |= key_set; +} + +INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr) +{ + if( SLOT->key ) + { + SLOT->key &= key_clr; + + if( !SLOT->key ) + { + /* phase -> Release */ + if (SLOT->state>EG_REL) + SLOT->state = EG_REL; + } + } +} + +/* update phase increment counter of operator (also update the EG rates if necessary) */ +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) +{ + int ksr; + + /* (frequency) phase increment counter */ + SLOT->Incr = CH->fc * SLOT->mul; + ksr = CH->kcode >> SLOT->KSR; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ar + SLOT->ksr) < 16+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 13*RATE_STEPS; + } + SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; + SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; + } +} + +/* set multi,am,vib,EG-TYP,KSR,mul */ +INLINE void set_mul(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->mul = mul_tab[v&0x0f]; + SLOT->KSR = (v&0x10) ? 0 : 2; + SLOT->eg_type = (v&0x20); + SLOT->vib = (v&0x40); + SLOT->AMmask = (v&0x80) ? ~0 : 0; + CALC_FCSLOT(CH,SLOT); +} + +/* set ksl & tl */ +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */ + + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */ + + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); +} + +/* set attack rate & decay rate */ +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0; + + if ((SLOT->ar + SLOT->ksr) < 16+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 13*RATE_STEPS; + } + + SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; + SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; +} + +/* set sustain level & release rate */ +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->sl = sl_tab[ v>>4 ]; + + SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; +} + + +/* write a value v to register r on OPL chip */ +static void OPLWriteReg(FM_OPL *OPL, int r, int v) +{ + OPL_CH *CH; + int slot; + int block_fnum; + + + /* adjust bus to 8 bits */ + r &= 0xff; + v &= 0xff; + +#ifdef LOG_CYM_FILE + if ((cymfile) && (r!=0) ) + { + fputc( (unsigned char)r, cymfile ); + fputc( (unsigned char)v, cymfile ); + } +#endif + + + switch(r&0xe0) + { + case 0x00: /* 00-1f:control */ + switch(r&0x1f) + { + case 0x01: /* waveform select enable */ + if(OPL->type&OPL_TYPE_WAVESEL) + { + OPL->wavesel = v&0x20; + /* do not change the waveform previously selected */ + } + break; + case 0x02: /* Timer 1 */ + OPL->T[0] = (256-v)*4; + break; + case 0x03: /* Timer 2 */ + OPL->T[1] = (256-v)*16; + break; + case 0x04: /* IRQ clear / mask and Timer enable */ + if(v&0x80) + { /* IRQ flag clear */ + OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */ + } + else + { /* set IRQ mask ,timer enable*/ + UINT8 st1 = v&1; + UINT8 st2 = (v>>1)&1; + + /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ + OPL_STATUS_RESET(OPL, v & (0x78-0x08) ); + OPL_STATUSMASK_SET(OPL, (~v) & 0x78 ); + + /* timer 2 */ + if(OPL->st[1] != st2) + { + double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; + OPL->st[1] = st2; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); + } + /* timer 1 */ + if(OPL->st[0] != st1) + { + double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; + OPL->st[0] = st1; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); + } + } + break; +#if BUILD_Y8950 + case 0x06: /* Key Board OUT */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_w) + OPL->keyboardhandler_w(OPL->keyboard_param,v); + else + logerror("Y8950: write unmapped KEYBOARD port\n"); + } + break; + case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + break; +#endif + case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ + OPL->mode = v; +#if BUILD_Y8950 + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */ +#endif + break; + +#if BUILD_Y8950 + case 0x09: /* START ADD */ + case 0x0a: + case 0x0b: /* STOP ADD */ + case 0x0c: + case 0x0d: /* PRESCALE */ + case 0x0e: + case 0x0f: /* ADPCM data write */ + case 0x10: /* DELTA-N */ + case 0x11: /* DELTA-N */ + case 0x12: /* ADPCM volume */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + break; + + case 0x15: /* DAC data high 8 bits (F7,F6...F2) */ + case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */ + case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */ + logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v); + break; + + case 0x18: /* I/O CTRL (Direction) */ + if(OPL->type&OPL_TYPE_IO) + OPL->portDirection = v&0x0f; + break; + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + OPL->portLatch = v; + if(OPL->porthandler_w) + OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); + } + break; +#endif + default: + logerror("FMOPL.C: write to unknown register: %02x\n",r); + break; + } + break; + case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ + slot = slot_array[r&0x1f]; + if(slot < 0) return; + set_mul(OPL,slot,v); + break; + case 0x40: + slot = slot_array[r&0x1f]; + if(slot < 0) return; + set_ksl_tl(OPL,slot,v); + break; + case 0x60: + slot = slot_array[r&0x1f]; + if(slot < 0) return; + set_ar_dr(OPL,slot,v); + break; + case 0x80: + slot = slot_array[r&0x1f]; + if(slot < 0) return; + set_sl_rr(OPL,slot,v); + break; + case 0xa0: + if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */ + { + OPL->lfo_am_depth = v & 0x80; + OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0; + + OPL->rhythm = v&0x3f; + + if(OPL->rhythm&0x20) + { + /* BD key on/off */ + if(v&0x10) + { + FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2); + FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2); + } + else + { + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); + } + /* HH key on/off */ + if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2); + else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); + /* SD key on/off */ + if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2); + else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); + /* TOM key on/off */ + if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2); + else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY key on/off */ + if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2); + else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); + } + else + { + /* BD key off */ + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); + /* HH key off */ + FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); + /* SD key off */ + FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); + /* TOM key off */ + FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY off */ + FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); + } + return; + } + /* keyon,block,fnum */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + if(!(r&0x10)) + { /* a0-a8 */ + block_fnum = (CH->block_fnum&0x1f00) | v; + } + else + { /* b0-b8 */ + block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); + + if(v&0x20) + { + FM_KEYON (&CH->SLOT[SLOT1], 1); + FM_KEYON (&CH->SLOT[SLOT2], 1); + } + else + { + FM_KEYOFF(&CH->SLOT[SLOT1],~1); + FM_KEYOFF(&CH->SLOT[SLOT2],~1); + } + } + /* update */ + if(CH->block_fnum != block_fnum) + { + UINT8 block = block_fnum >> 10; + + CH->block_fnum = block_fnum; + + CH->ksl_base = ksl_tab[block_fnum>>6]; + CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block); + + /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */ + CH->kcode = (CH->block_fnum&0x1c00)>>9; + + /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */ + /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */ + /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */ + if (OPL->mode&0x40) + CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */ + else + CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */ + + /* refresh Total Level in both SLOTs of this channel */ + CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); + CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); + + /* refresh frequency counter in both SLOTs of this channel */ + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); + } + break; + case 0xc0: + /* FB,C */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0; + CH->SLOT[SLOT1].CON = v&1; + CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation; + break; + case 0xe0: /* waveform select */ + /* simply ignore write to the waveform select register if selecting not enabled in test register */ + if(OPL->wavesel) + { + slot = slot_array[r&0x1f]; + if(slot < 0) return; + CH = &OPL->P_CH[slot/2]; + + CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN; + } + break; + } +} + +#ifdef LOG_CYM_FILE +static void cymfile_callback (int n) +{ + if (cymfile) + { + fputc( (unsigned char)0, cymfile ); + } +} +#endif + +/* lock/unlock for common table */ +static int OPL_LockTable(void) +{ + num_lock++; + if(num_lock>1) return 0; + + /* first time */ + + cur_chip = NULL; + /* allocate total level table (128kb space) */ + if( !init_tables() ) + { + num_lock--; + return -1; + } + +#ifdef LOG_CYM_FILE + cymfile = fopen("3812_.cym","wb"); + if (cymfile) + timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ + else + logerror("Could not create file 3812_.cym\n"); +#endif + + return 0; +} + +static void OPL_UnLockTable(void) +{ + if(num_lock) num_lock--; + if(num_lock) return; + + /* last time */ + + cur_chip = NULL; + OPLCloseTable(); + +#ifdef LOG_CYM_FILE + fclose (cymfile); + cymfile = NULL; +#endif + +} + +static void OPLResetChip(FM_OPL *OPL) +{ + int c,s; + int i; + + OPL->eg_timer = 0; + OPL->eg_cnt = 0; + + OPL->noise_rng = 1; /* noise shift register */ + OPL->mode = 0; /* normal mode */ + OPL_STATUS_RESET(OPL,0x7f); + + /* reset with register write */ + OPLWriteReg(OPL,0x01,0); /* wavesel disable */ + OPLWriteReg(OPL,0x02,0); /* Timer1 */ + OPLWriteReg(OPL,0x03,0); /* Timer2 */ + OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ + for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); + + /* reset operator parameters */ + for( c = 0 ; c < 9 ; c++ ) + { + OPL_CH *CH = &OPL->P_CH[c]; + for(s = 0 ; s < 2 ; s++ ) + { + /* wave table */ + CH->SLOT[s].wavetable = 0; + CH->SLOT[s].state = EG_OFF; + CH->SLOT[s].volume = MAX_ATT_INDEX; + } + } +#if BUILD_Y8950 + if(OPL->type&OPL_TYPE_ADPCM) + { + YM_DELTAT *DELTAT = OPL->deltat; + + DELTAT->freqbase = OPL->freqbase; + DELTAT->output_pointer = &output_deltat[0]; + DELTAT->portshift = 5; + DELTAT->output_range = 1<<23; + YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL); + } +#endif +} + +/* Create one of virtual YM3812/YM3526/Y8950 */ +/* 'clock' is chip clock in Hz */ +/* 'rate' is sampling rate */ +static FM_OPL *OPLCreate(int type, int clock, int rate) +{ + char *ptr; + FM_OPL *OPL; + int state_size; + + if (OPL_LockTable() ==-1) return NULL; + + /* calculate OPL state size */ + state_size = sizeof(FM_OPL); + +#if BUILD_Y8950 + if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); +#endif + + /* allocate memory block */ + ptr = malloc(state_size); + + if (ptr==NULL) + return NULL; + + /* clear */ + memset(ptr,0,state_size); + + OPL = (FM_OPL *)ptr; + + ptr += sizeof(FM_OPL); + +#if BUILD_Y8950 + if (type&OPL_TYPE_ADPCM) + { + OPL->deltat = (YM_DELTAT *)ptr; + } + ptr += sizeof(YM_DELTAT); +#endif + + OPL->type = type; + OPL->clock = clock; + OPL->rate = rate; + + /* init global tables */ + OPL_initalize(OPL); + + return OPL; +} + +/* Destroy one of virtual YM3812 */ +static void OPLDestroy(FM_OPL *OPL) +{ + OPL_UnLockTable(); + if (OPL) { + free(OPL); + OPL = NULL; + } +} + +/* Optional handlers */ + +static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) +{ + OPL->TimerHandler = TimerHandler; + OPL->TimerParam = channelOffset; +} +static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) +{ + OPL->IRQHandler = IRQHandler; + OPL->IRQParam = param; +} +static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPL->UpdateHandler = UpdateHandler; + OPL->UpdateParam = param; +} + +static int OPLWrite(FM_OPL *OPL,int a,int v) +{ + if( !(a&1) ) + { /* address port */ + OPL->address = v & 0xff; + } + else + { /* data port */ + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + OPLWriteReg(OPL,OPL->address,v); + } + return OPL->status>>7; +} + +static unsigned char OPLRead(FM_OPL *OPL,int a) +{ + if( !(a&1) ) + { + /* status port */ + + #if BUILD_Y8950 + + if(OPL->type&OPL_TYPE_ADPCM) /* Y8950 */ + { + return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1); + } + + #endif + + /* OPL and OPL2 */ + return OPL->status & (OPL->statusmask|0x80); + } + +#if BUILD_Y8950 + /* data port */ + switch(OPL->address) + { + case 0x05: /* KeyBoard IN */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_r) + return OPL->keyboardhandler_r(OPL->keyboard_param); + else + logerror("Y8950: read unmapped KEYBOARD port\n"); + } + return 0; + + case 0x0f: /* ADPCM-DATA */ + if(OPL->type&OPL_TYPE_ADPCM) + { + UINT8 val; + + val = YM_DELTAT_ADPCM_Read(OPL->deltat); + /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/ + return val; + } + return 0; + + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + if(OPL->porthandler_r) + return OPL->porthandler_r(OPL->port_param); + else + logerror("Y8950:read unmapped I/O port\n"); + } + return 0; + case 0x1a: /* PCM-DATA */ + if(OPL->type&OPL_TYPE_ADPCM) + { + logerror("Y8950 A/D convertion is accessed but not implemented !\n"); + return 0x80; /* 2's complement PCM data - result from A/D convertion */ + } + return 0; + } +#endif + + return 0xff; +} + +/* CSM Key Controll */ +INLINE void CSMKeyControll(OPL_CH *CH) +{ + FM_KEYON (&CH->SLOT[SLOT1], 4); + FM_KEYON (&CH->SLOT[SLOT2], 4); + + /* The key off should happen exactly one sample later - not implemented correctly yet */ + + FM_KEYOFF(&CH->SLOT[SLOT1], ~4); + FM_KEYOFF(&CH->SLOT[SLOT2], ~4); +} + + +static int OPLTimerOver(FM_OPL *OPL,int c) +{ + if( c ) + { /* Timer B */ + OPL_STATUS_SET(OPL,0x20); + } + else + { /* Timer A */ + OPL_STATUS_SET(OPL,0x40); + /* CSM mode key,TL controll */ + if( OPL->mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + int ch; + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + for(ch=0; ch<9; ch++) + CSMKeyControll( &OPL->P_CH[ch] ); + } + } + /* reload timer */ + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); + return OPL->status>>7; +} + + +#define MAX_OPL_CHIPS 2 + + +#if (BUILD_YM3812) + +static FM_OPL *OPL_YM3812[MAX_OPL_CHIPS]; /* array of pointers to the YM3812's */ +static int YM3812NumChips = 0; /* number of chips */ + +int YM3812Init(int num, int clock, int rate) +{ + int i; + + if (YM3812NumChips) + return -1; /* duplicate init. */ + + YM3812NumChips = num; + + for (i = 0;i < YM3812NumChips; i++) + { + /* emulator create */ + OPL_YM3812[i] = OPLCreate(OPL_TYPE_YM3812,clock,rate); + if(OPL_YM3812[i] == NULL) + { + /* it's really bad - we run out of memeory */ + YM3812NumChips = 0; + return -1; + } + /* reset */ + YM3812ResetChip(i); + } + + return 0; +} + +void YM3812Shutdown(void) +{ + int i; + + for (i = 0;i < YM3812NumChips; i++) + { + /* emulator shutdown */ + OPLDestroy(OPL_YM3812[i]); + OPL_YM3812[i] = NULL; + } + YM3812NumChips = 0; +} +void YM3812ResetChip(int which) +{ + OPLResetChip(OPL_YM3812[which]); +} + +int YM3812Write(int which, int a, int v) +{ + return OPLWrite(OPL_YM3812[which], a, v); +} + +unsigned char YM3812Read(int which, int a) +{ + /* YM3812 always returns bit2 and bit1 in HIGH state */ + return OPLRead(OPL_YM3812[which], a) | 0x06 ; +} +int YM3812TimerOver(int which, int c) +{ + return OPLTimerOver(OPL_YM3812[which], c); +} + +void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) +{ + OPLSetTimerHandler(OPL_YM3812[which], TimerHandler, channelOffset); +} +void YM3812SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) +{ + OPLSetIRQHandler(OPL_YM3812[which], IRQHandler, param); +} +void YM3812SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPLSetUpdateHandler(OPL_YM3812[which], UpdateHandler, param); +} + + +/* +** Generate samples for one of the YM3812's +** +** 'which' is the virtual YM3812 number +** '*buffer' is the output buffer pointer +** 'length' is the number of samples that should be generated +*/ +void YM3812UpdateOne(int which, INT16 *buffer, int length) +{ + FM_OPL *OPL = OPL_YM3812[which]; + UINT8 rhythm = OPL->rhythm&0x20; + OPLSAMPLE *buf = buffer; + int i; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* rhythm slots */ + SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; + } + for( i=0; i < length ; i++ ) + { + int lt; + + output[0] = 0; + + advance_lfo(OPL); + + /* FM part */ + OPL_CALC_CH(&OPL->P_CH[0]); + OPL_CALC_CH(&OPL->P_CH[1]); + OPL_CALC_CH(&OPL->P_CH[2]); + OPL_CALC_CH(&OPL->P_CH[3]); + OPL_CALC_CH(&OPL->P_CH[4]); + OPL_CALC_CH(&OPL->P_CH[5]); + + if(!rhythm) + { + OPL_CALC_CH(&OPL->P_CH[6]); + OPL_CALC_CH(&OPL->P_CH[7]); + OPL_CALC_CH(&OPL->P_CH[8]); + } + else /* Rhythm part */ + { + OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); + } + + lt = output[0]; + + lt >>= FINAL_SH; + + /* limit check */ + lt = limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + if (which==0) + { + SAVE_ALL_CHANNELS + } + #endif + + /* store to sound buffer */ + buf[i] = lt; + + advance(OPL); + } + +} +#endif /* BUILD_YM3812 */ + + + +#if (BUILD_YM3526) + +static FM_OPL *OPL_YM3526[MAX_OPL_CHIPS]; /* array of pointers to the YM3526's */ +static int YM3526NumChips = 0; /* number of chips */ + +int YM3526Init(int num, int clock, int rate) +{ + int i; + + if (YM3526NumChips) + return -1; /* duplicate init. */ + + YM3526NumChips = num; + + for (i = 0;i < YM3526NumChips; i++) + { + /* emulator create */ + OPL_YM3526[i] = OPLCreate(OPL_TYPE_YM3526,clock,rate); + if(OPL_YM3526[i] == NULL) + { + /* it's really bad - we run out of memeory */ + YM3526NumChips = 0; + return -1; + } + /* reset */ + YM3526ResetChip(i); + } + + return 0; +} + +void YM3526Shutdown(void) +{ + int i; + + for (i = 0;i < YM3526NumChips; i++) + { + /* emulator shutdown */ + OPLDestroy(OPL_YM3526[i]); + OPL_YM3526[i] = NULL; + } + YM3526NumChips = 0; +} +void YM3526ResetChip(int which) +{ + OPLResetChip(OPL_YM3526[which]); +} + +int YM3526Write(int which, int a, int v) +{ + return OPLWrite(OPL_YM3526[which], a, v); +} + +unsigned char YM3526Read(int which, int a) +{ + /* YM3526 always returns bit2 and bit1 in HIGH state */ + return OPLRead(OPL_YM3526[which], a) | 0x06 ; +} +int YM3526TimerOver(int which, int c) +{ + return OPLTimerOver(OPL_YM3526[which], c); +} + +void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) +{ + OPLSetTimerHandler(OPL_YM3526[which], TimerHandler, channelOffset); +} +void YM3526SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) +{ + OPLSetIRQHandler(OPL_YM3526[which], IRQHandler, param); +} +void YM3526SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPLSetUpdateHandler(OPL_YM3526[which], UpdateHandler, param); +} + + +/* +** Generate samples for one of the YM3526's +** +** 'which' is the virtual YM3526 number +** '*buffer' is the output buffer pointer +** 'length' is the number of samples that should be generated +*/ +void YM3526UpdateOne(int which, INT16 *buffer, int length) +{ + FM_OPL *OPL = OPL_YM3526[which]; + UINT8 rhythm = OPL->rhythm&0x20; + OPLSAMPLE *buf = buffer; + int i; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* rhythm slots */ + SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; + } + for( i=0; i < length ; i++ ) + { + int lt; + + output[0] = 0; + + advance_lfo(OPL); + + /* FM part */ + OPL_CALC_CH(&OPL->P_CH[0]); + OPL_CALC_CH(&OPL->P_CH[1]); + OPL_CALC_CH(&OPL->P_CH[2]); + OPL_CALC_CH(&OPL->P_CH[3]); + OPL_CALC_CH(&OPL->P_CH[4]); + OPL_CALC_CH(&OPL->P_CH[5]); + + if(!rhythm) + { + OPL_CALC_CH(&OPL->P_CH[6]); + OPL_CALC_CH(&OPL->P_CH[7]); + OPL_CALC_CH(&OPL->P_CH[8]); + } + else /* Rhythm part */ + { + OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); + } + + lt = output[0]; + + lt >>= FINAL_SH; + + /* limit check */ + lt = limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + if (which==0) + { + SAVE_ALL_CHANNELS + } + #endif + + /* store to sound buffer */ + buf[i] = lt; + + advance(OPL); + } + +} +#endif /* BUILD_YM3526 */ + + + + +#if BUILD_Y8950 + +static FM_OPL *OPL_Y8950[MAX_OPL_CHIPS]; /* array of pointers to the Y8950's */ +static int Y8950NumChips = 0; /* number of chips */ + +static void Y8950_deltat_status_set(UINT8 which, UINT8 changebits) +{ + OPL_STATUS_SET(OPL_Y8950[which], changebits); +} +static void Y8950_deltat_status_reset(UINT8 which, UINT8 changebits) +{ + OPL_STATUS_RESET(OPL_Y8950[which], changebits); +} + +int Y8950Init(int num, int clock, int rate) +{ + int i; + + if (Y8950NumChips) + return -1; /* duplicate init. */ + + Y8950NumChips = num; + + for (i = 0;i < Y8950NumChips; i++) + { + /* emulator create */ + OPL_Y8950[i] = OPLCreate(OPL_TYPE_Y8950,clock,rate); + if(OPL_Y8950[i] == NULL) + { + /* it's really bad - we run out of memeory */ + Y8950NumChips = 0; + return -1; + } + OPL_Y8950[i]->deltat->status_set_handler = Y8950_deltat_status_set; + OPL_Y8950[i]->deltat->status_reset_handler = Y8950_deltat_status_reset; + OPL_Y8950[i]->deltat->status_change_which_chip = i; + OPL_Y8950[i]->deltat->status_change_EOS_bit = 0x10; /* status flag: set bit4 on End Of Sample */ + OPL_Y8950[i]->deltat->status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */ + + /*OPL_Y8950[i]->deltat->write_time = 10.0 / clock;*/ /* a single byte write takes 10 cycles of main clock */ + /*OPL_Y8950[i]->deltat->read_time = 8.0 / clock;*/ /* a single byte read takes 8 cycles of main clock */ + /* reset */ + Y8950ResetChip(i); + } + + return 0; +} + +void Y8950Shutdown(void) +{ + int i; + + for (i = 0;i < Y8950NumChips; i++) + { + /* emulator shutdown */ + OPLDestroy(OPL_Y8950[i]); + OPL_Y8950[i] = NULL; + } + Y8950NumChips = 0; +} +void Y8950ResetChip(int which) +{ + OPLResetChip(OPL_Y8950[which]); +} + +int Y8950Write(int which, int a, int v) +{ + return OPLWrite(OPL_Y8950[which], a, v); +} + +unsigned char Y8950Read(int which, int a) +{ + return OPLRead(OPL_Y8950[which], a); +} +int Y8950TimerOver(int which, int c) +{ + return OPLTimerOver(OPL_Y8950[which], c); +} + +void Y8950SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) +{ + OPLSetTimerHandler(OPL_Y8950[which], TimerHandler, channelOffset); +} +void Y8950SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) +{ + OPLSetIRQHandler(OPL_Y8950[which], IRQHandler, param); +} +void Y8950SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPLSetUpdateHandler(OPL_Y8950[which], UpdateHandler, param); +} + +void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ) +{ + FM_OPL *OPL = OPL_Y8950[which]; + OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr); + OPL->deltat->memory_size = deltat_mem_size; +} + +/* +** Generate samples for one of the Y8950's +** +** 'which' is the virtual Y8950 number +** '*buffer' is the output buffer pointer +** 'length' is the number of samples that should be generated +*/ +void Y8950UpdateOne(int which, INT16 *buffer, int length) +{ + int i; + FM_OPL *OPL = OPL_Y8950[which]; + UINT8 rhythm = OPL->rhythm&0x20; + YM_DELTAT *DELTAT = OPL->deltat; + OPLSAMPLE *buf = buffer; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* rhythm slots */ + SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; + + } + for( i=0; i < length ; i++ ) + { + int lt; + + output[0] = 0; + output_deltat[0] = 0; + + advance_lfo(OPL); + + /* deltaT ADPCM */ + if( DELTAT->portstate&0x80 ) + YM_DELTAT_ADPCM_CALC(DELTAT); + + /* FM part */ + OPL_CALC_CH(&OPL->P_CH[0]); + OPL_CALC_CH(&OPL->P_CH[1]); + OPL_CALC_CH(&OPL->P_CH[2]); + OPL_CALC_CH(&OPL->P_CH[3]); + OPL_CALC_CH(&OPL->P_CH[4]); + OPL_CALC_CH(&OPL->P_CH[5]); + + if(!rhythm) + { + OPL_CALC_CH(&OPL->P_CH[6]); + OPL_CALC_CH(&OPL->P_CH[7]); + OPL_CALC_CH(&OPL->P_CH[8]); + } + else /* Rhythm part */ + { + OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); + } + + lt = output[0] + (output_deltat[0]>>11); + + lt >>= FINAL_SH; + + /* limit check */ + lt = limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + if (which==0) + { + SAVE_ALL_CHANNELS + } + #endif + + /* store to sound buffer */ + buf[i] = lt; + + advance(OPL); + } + +} + +void Y8950SetPortHandler(int which,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) +{ + FM_OPL *OPL = OPL_Y8950[which]; + OPL->porthandler_w = PortHandler_w; + OPL->porthandler_r = PortHandler_r; + OPL->port_param = param; +} + +void Y8950SetKeyboardHandler(int which,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param) +{ + FM_OPL *OPL = OPL_Y8950[which]; + OPL->keyboardhandler_w = KeyboardHandler_w; + OPL->keyboardhandler_r = KeyboardHandler_r; + OPL->keyboard_param = param; +} + +#endif + diff --git a/src/burn/sound/fmopl.h b/src/burn/sound/fmopl.h new file mode 100644 index 00000000..242a32d2 --- /dev/null +++ b/src/burn/sound/fmopl.h @@ -0,0 +1,109 @@ +#ifndef __FMOPL_H_ +#define __FMOPL_H_ + +/* --- select emulation chips --- */ +#define BUILD_YM3812 (HAS_YM3812) +#define BUILD_YM3526 (HAS_YM3526) +#define BUILD_Y8950 (HAS_Y8950) + +/* select output bits size of output : 8 or 16 */ +#define OPL_SAMPLE_BITS 16 + +/* compiler dependence */ +#ifndef OSD_CPU_H +#define OSD_CPU_H +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif + +#if (OPL_SAMPLE_BITS==16) +typedef INT16 OPLSAMPLE; +#endif +#if (OPL_SAMPLE_BITS==8) +typedef INT8 OPLSAMPLE; +#endif + + +typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); +typedef void (*OPL_IRQHANDLER)(int param,int irq); +typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); +typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data); +typedef unsigned char (*OPL_PORTHANDLER_R)(int param); + + +#if BUILD_YM3812 + +int YM3812Init(int num, int clock, int rate); +void YM3812Shutdown(void); +void YM3812ResetChip(int which); +int YM3812Write(int which, int a, int v); +unsigned char YM3812Read(int which, int a); +int YM3812TimerOver(int which, int c); +void YM3812UpdateOne(int which, INT16 *buffer, int length); + +void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); +void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param); +void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param); + +#endif + + +#if BUILD_YM3526 + +/* +** Initialize YM3526 emulator(s). +** +** 'num' is the number of virtual YM3526's to allocate +** 'clock' is the chip clock in Hz +** 'rate' is sampling rate +*/ +int YM3526Init(int num, int clock, int rate); +/* shutdown the YM3526 emulators*/ +void YM3526Shutdown(void); +void YM3526ResetChip(int which); +int YM3526Write(int which, int a, int v); +unsigned char YM3526Read(int which, int a); +int YM3526TimerOver(int which, int c); +/* +** Generate samples for one of the YM3526's +** +** 'which' is the virtual YM3526 number +** '*buffer' is the output buffer pointer +** 'length' is the number of samples that should be generated +*/ +void YM3526UpdateOne(int which, INT16 *buffer, int length); + +void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); +void YM3526SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param); +void YM3526SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param); + +#endif + + +#if BUILD_Y8950 + +/* Y8950 port handlers */ +void Y8950SetPortHandler(int which, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, int param); +void Y8950SetKeyboardHandler(int which, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, int param); +void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ); + +int Y8950Init (int num, int clock, int rate); +void Y8950Shutdown (void); +void Y8950ResetChip (int which); +int Y8950Write (int which, int a, int v); +unsigned char Y8950Read (int which, int a); +int Y8950TimerOver (int which, int c); +void Y8950UpdateOne (int which, INT16 *buffer, int length); + +void Y8950SetTimerHandler (int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); +void Y8950SetIRQHandler (int which, OPL_IRQHANDLER IRQHandler, int param); +void Y8950SetUpdateHandler (int which, OPL_UPDATEHANDLER UpdateHandler, int param); + +#endif + + +#endif /* __FMOPL_H_ */ diff --git a/src/burn/sound/ics2115.cpp b/src/burn/sound/ics2115.cpp new file mode 100644 index 00000000..98627beb --- /dev/null +++ b/src/burn/sound/ics2115.cpp @@ -0,0 +1,449 @@ +/****************************************************** + ICS 2115 sound synthesizer. + + ICS WaveFront ICS2115V Wavetable Midi Synthesizer, + clocked at 33.8688MHz + + Original ics2115.c in MAME + By O. Galibert, with a lot of help from the nebula + ics emulation by Elsemi. + + Port to FB Alpha by OopsWare + ******************************************************/ + +#include "burnint.h" +#include "msm6295.h" +#include "burn_sound.h" +#include "ics2115.h" + +UINT8 *ICSSNDROM; +UINT32 nICSSNDROMLen; + +enum { V_ON = 1, V_DONE = 2 }; + +struct ics2115 { + UINT8 * rom; + INT16 ulaw[256]; + struct { + UINT16 fc, addrh, addrl, strth, endh, volacc; + UINT8 strtl, endl, saddr, pan, conf, ctl; + UINT8 vstart, vend, vctl; + UINT8 state; + } voice[32]; + struct { + UINT8 scale, preset; + //mame_timer *timer; + bool active; + UINT32 period; + } timer[2]; + UINT8 reg, osc; + UINT8 irq_en, irq_pend; + INT32 irq_on; + //sound_stream * stream; +}; + +static struct ics2115 * chip = NULL; +static INT16 * sndbuffer = NULL; +static UINT16 nSoundlatch[3] = {0, 0, 0}; +static UINT8 bSoundlatchRead[3] = {0, 0, 0}; + +#define ICS2115_RATE 33075 +#define ICS2115_FRAME_BUFFER_SIZE (ICS2115_RATE / 60 + 1) + +static UINT32 nSoundDelta; + +/* ICS2115V chip emu */ + +static void recalc_irq() +{ + INT32 irq = 0; + if(chip->irq_en & chip->irq_pend) irq = 1; + for(INT32 i=0; !irq && i<32; i++) + if(chip->voice[i].state & V_DONE) irq = 1; + if(irq != chip->irq_on) { + chip->irq_on = irq; +// IRQ callback +// if(chip->intf->irq_cb) +// chip->intf->irq_cb(irq ? ASSERT_LINE : CLEAR_LINE); + + if (irq) { + ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK); + } else + ZetSetIRQLine(0x00, ZET_IRQSTATUS_NONE); + } +} + +static void timer_cb_0() +{ + chip->irq_pend |= 1<<0; + recalc_irq(); +} + +static void timer_cb_1() +{ + chip->irq_pend |= 1<<1; + recalc_irq(); +} + +static void recalc_timer(INT32 timer) +{ + float period = 0; + + if(chip->timer[timer].scale) { + INT32 sc = chip->timer[timer].scale; + float counter = (float)((((sc & 31)+1) * (chip->timer[timer].preset+1)) << (4+(sc >> 5))); + period = 1000000000 * counter / 33868800; + } else { + period = 0; + } + + if (chip->timer[timer].period != (UINT32)period) { + chip->timer[timer].period = (UINT32)period; + if(period) chip->timer[timer].active = true; + else chip->timer[timer].active = false; + } +} + +UINT16 ics2115read_reg(UINT8 reg) +{ + switch (reg) { + case 0x0d: // [osc] Volume Enveloppe Control + return 0x100; + case 0x0f: {// [osc] Interrupt source/oscillator + UINT8 res = 0xff; + for(INT32 osc=0; osc<32; osc++) + if(chip->voice[osc].state & V_DONE) { + chip->voice[osc].state &= ~V_DONE; + recalc_irq(); + res = 0x40 | osc; // 0x40 ? 0x80 ? + break; + } + return res << 8; } + case 0x40: // Timer 0 clear irq + chip->irq_pend &= ~(1<<0); + recalc_irq(); + return chip->timer[0].preset; + case 0x41: // Timer 1 clear irq + chip->irq_pend &= ~(1<<1); + recalc_irq(); + return chip->timer[1].preset; + case 0x43: // Timer status + return chip->irq_pend & 3; + case 0x4a: // IRQ Pending + return chip->irq_pend; + case 0x4b: // Address of Interrupting Oscillator + return 0x80; + case 0x4c: // Chip revision + return 0x01; + default: + return 0; + } +} + +void ics2115write_reg(UINT8 reg, UINT8 data, INT32 msb) +{ +// bprintf(PRINT_NORMAL, _T("ics2115write_reg(%02x, %02x, %d); %4.1f%%\n"), reg, data, msb, 6.0 * ZetTotalCycles() / 8468.0 ); + + switch (reg) { + case 0x00: // [osc] Oscillator Configuration + if( msb ) chip->voice[chip->osc].conf = data; + break; + case 0x01: // [osc] Wavesample frequency + if(msb) chip->voice[chip->osc].fc = (chip->voice[chip->osc].fc & 0xff) | (data << 8); + else chip->voice[chip->osc].fc = (chip->voice[chip->osc].fc & 0xff00) | data; + //bprintf(PRINT_NORMAL, _T("ICS2115: %2d: fc = %04x (%dHz)\n"), chip->osc,chip->voice[chip->osc].fc, chip->voice[chip->osc].(fc*33075+512)/1024); + break; + case 0x02: // [osc] Wavesample loop start address 19-4 + if(msb) chip->voice[chip->osc].strth = (chip->voice[chip->osc].strth & 0xff) | (data << 8); + else chip->voice[chip->osc].strth = (chip->voice[chip->osc].strth & 0xff00) | data; + break; + case 0x03: // [osc] Wavesample loop start address 3-0.3-0 + if(msb) chip->voice[chip->osc].strtl = data; + break; + case 0x04: // [osc] Wavesample loop end address 19-4 + if(msb) chip->voice[chip->osc].endh = (chip->voice[chip->osc].endh & 0xff)|(data << 8); + else chip->voice[chip->osc].endh = (chip->voice[chip->osc].endh & 0xff00)|data; + break; + case 0x05: // [osc] Wavesample loop end address 3-0.3-0 + if(msb) chip->voice[chip->osc].endl = data; + break; + case 0x07: // [osc] Volume Start + if(msb) chip->voice[chip->osc].vstart = data; + break; + case 0x08: // [osc] Volume End + if(msb) chip->voice[chip->osc].vend = data; + break; + case 0x09: // [osc] Volume accumulator + if(msb) chip->voice[chip->osc].volacc = (chip->voice[chip->osc].volacc & 0xff)|(data << 8); + else chip->voice[chip->osc].volacc = (chip->voice[chip->osc].volacc & 0xff00)|data; + //bprintf(PRINT_NORMAL, _T("ICS2115: %2d: volacc = %04x\n"), chip->osc,chip->voice[chip->osc].volacc); + break; + case 0x0a: // [osc] Wavesample address 19-4 + if(msb) chip->voice[chip->osc].addrh = (chip->voice[chip->osc].addrh & 0xff)|(data << 8); + else chip->voice[chip->osc].addrh = (chip->voice[chip->osc].addrh & 0xff00)|data; + break; + case 0x0b: // [osc] Wavesample address 3-0.8-0 + if(msb) chip->voice[chip->osc].addrl = (chip->voice[chip->osc].addrl & 0xff)|(data << 8); + else chip->voice[chip->osc].addrl = (chip->voice[chip->osc].addrl & 0xff00)|data; + break; + case 0x0c: // [osc] Pan + if(msb) chip->voice[chip->osc].pan = data; + break; + case 0x0d: // [osc] Volume Enveloppe Control + if(msb) chip->voice[chip->osc].vctl = data; + break; + case 0x10: // [osc] Oscillator Control + if(msb) { + chip->voice[chip->osc].ctl = data; + if(data == 0) { + chip->voice[chip->osc].state |= V_ON; +// bprintf(PRINT_NORMAL, _T("ICS2115: KEYON %2d volacc = %04x fc = %04x (%dHz)\n"), +// chip->osc, chip->voice[chip->osc].volacc, chip->voice[chip->osc].fc, (chip->voice[chip->osc].fc*33075 + 512) / 1024 ); + } + } break; + case 0x11: // [osc] Wavesample static address 27-20 + if(msb) chip->voice[chip->osc].saddr = data; + break; + case 0x40: // Timer 1 Preset + if(!msb) { + chip->timer[0].preset = data; + recalc_timer(0); + } break; + case 0x41: // Timer 2 Preset + if(!msb) { + chip->timer[1].preset = data; + recalc_timer(1); + } break; + case 0x42: // Timer 1 Prescaler + if(!msb) { + chip->timer[0].scale = data; + recalc_timer(0); + } break; + case 0x43: // Timer 2 Prescaler + if(!msb) { + chip->timer[1].scale = data; + recalc_timer(1); + } break; + case 0x4a: // IRQ Enable + if(!msb) { + chip->irq_en = data; + recalc_irq(); + } break; + case 0x4f: // Oscillator Address being Programmed + if(!msb) chip->osc = data & 31; + break; + } +} + +UINT8 ics2115read(UINT8 offset) +{ + switch ( offset ) { + case 0x00: { + UINT8 res = 0; + if(chip->irq_on) { + res |= 0x80; + if(chip->irq_en & chip->irq_pend & 3) res |= 1; // Timer irq + for(INT32 i=0; i<32; i++) + if(chip->voice[i].state & V_DONE) { + res |= 2; + break; + } + } + return res; } + case 0x01: + return chip->reg; + case 0x02: + return ics2115read_reg(chip->reg) & 0xff; + case 0x03: + default: + return ics2115read_reg(chip->reg) >> 8; + } +} + +void ics2115write(UINT8 offset, UINT8 data) +{ + switch (offset) { + case 0x01: + chip->reg = data; + break; + case 0x02: + ics2115write_reg(chip->reg, data, 0); + break; + case 0x03: + ics2115write_reg(chip->reg, data, 1); + break; + default: + break; + } +} + +INT32 ics2115_init() +{ + chip = (struct ics2115 *) malloc( sizeof(struct ics2115) ); // ICS2115V + if (chip == NULL) return 1; + + sndbuffer = (INT16*) malloc ( ICS2115_FRAME_BUFFER_SIZE * sizeof(INT16*)); + if (sndbuffer == NULL) return 1; + + return 0; +} + +void ics2115_exit() +{ + if (chip) { + free( chip ); + chip = NULL; + } + + nICSSNDROMLen = 0; + + if (ICSSNDROM) { + free(ICSSNDROM); + ICSSNDROM = NULL; + } + + if (sndbuffer) { + free( sndbuffer ); + sndbuffer = NULL; + } +} + +static void recalculate_ulaw() +{ + for(INT32 i=0; i<256; i++) { + UINT8 c = ((~i) & 0xFF); + INT32 v = ((c & 15) << 1) + 33; + v <<= ((c & 0x70) >> 4); + if(c & 0x80) v = 33-v; + else v = v-33; + chip->ulaw[i] = v; + } +} + +void ics2115_reset() +{ + memset(chip, 0, sizeof(struct ics2115)); + + chip->rom = ICSSNDROM; +// chip->timer[0].timer = timer_alloc_ptr(timer_cb_0, chip); +// chip->timer[1].timer = timer_alloc_ptr(timer_cb_1, chip); +// chip->stream = stream_create(0, 2, 33075, chip, update); +// if(!chip->timer[0].timer || !chip->timer[1].timer) return NULL; + + recalculate_ulaw(); + + if (nBurnSoundLen) { + nSoundDelta = ICS2115_FRAME_BUFFER_SIZE * 0x10000 / nBurnSoundLen; + } else { + nSoundDelta = ICS2115_FRAME_BUFFER_SIZE * 0x10000 / 184; // 11025Hz + } + + recalc_irq(); + + memset(nSoundlatch, 0, sizeof(nSoundlatch)); + memset(bSoundlatchRead, 0, sizeof(bSoundlatchRead)); +} + +UINT16 ics2115_soundlatch_r(INT32 i) +{ +// bprintf(PRINT_NORMAL, _T("soundlatch_r(%d) %4.1f%% of frame\n"), i, 6.0 * SekTotalCycles() / 20000.0 ); + bSoundlatchRead[i] = 1; + return nSoundlatch[i]; +} + +void ics2115_soundlatch_w(INT32 i, UINT16 d) +{ +// if ( !bSoundlatchRead[i] && nSoundlatch[i] != d ) +// bprintf(PRINT_ERROR, _T("soundlatch_w(%d, %04x) %4.1f%% of frame\n"), i, d, 6.0 * SekTotalCycles() / 20000.0); +// else +// bprintf(PRINT_NORMAL, _T("soundlatch_w(%d, %04x) %4.1f%% of frame\n"), i, d, 6.0 * SekTotalCycles() / 20000.0); + nSoundlatch[i] = d; + bSoundlatchRead[i] = 0; +} + +void ics2115_frame() +{ + if (chip->timer[0].active ) timer_cb_0(); + if (chip->timer[1].active ) timer_cb_1(); +} + +void ics2115_update(INT32 /*length*/) +{ + INT32 rec_irq = 0; + + //short* pSoundBuf = pBurnSoundOut; + + memset(sndbuffer, 0, ICS2115_FRAME_BUFFER_SIZE * sizeof(INT16)); + + for(INT32 osc=0; osc<32; osc++) + if(chip->voice[osc].state & V_ON) { + UINT32 badr = (chip->voice[osc].saddr << 20) & 0x0f00000; + if (badr >= nICSSNDROMLen) { // right? + chip->voice[osc].state &= ~V_ON; + chip->voice[osc].state |= V_DONE; + rec_irq = 1; + break; + } + UINT32 adr = (chip->voice[osc].addrh << 16) | chip->voice[osc].addrl; + UINT32 end = (chip->voice[osc].endh << 16) | (chip->voice[osc].endl << 8); + UINT32 loop = (chip->voice[osc].strth << 16) | (chip->voice[osc].strtl << 8); + UINT32 conf = chip->voice[osc].conf; + INT32 vol = chip->voice[osc].volacc; + vol = (((vol & 0xff0)|0x1000)<<(vol>>12))>>12; + UINT32 delta = chip->voice[osc].fc << 2; + + for(INT32 i=0; irom[(badr|(adr >> 12))]; + + if(conf & 1)v = chip->ulaw[v]; + else v = ((INT8)v) << 6; + + v = (v*vol)>>(16+5); + + sndbuffer[i] += v; + + adr += delta; + if(adr >= end) { + //if (ICS2115LOGERROR) logerror("ICS2115: KEYDONE %2d\n", osc); + adr -= (end-loop); + chip->voice[osc].state &= ~V_ON; + chip->voice[osc].state |= V_DONE; + rec_irq = 1; + break; + } + } + + chip->voice[osc].addrh = adr >> 16; + chip->voice[osc].addrl = adr; + } + + if(rec_irq) recalc_irq(); + + if (pBurnSoundOut) { + INT32 pos = 0; + INT16 * pOut = (INT16*)pBurnSoundOut; + for(INT32 i=0; i> 16 ] << 4; + } + +} + +void ics2115_scan(INT32 nAction,INT32 * /*pnMin*/) +{ + struct BurnArea ba; + + if ( nAction & ACB_DRIVER_DATA ) { + UINT8 *rom = chip->rom; + + ba.Data = chip; + ba.nLen = sizeof(struct ics2115); + ba.nAddress = 0; + ba.szName = "ICS 2115"; + BurnAcb(&ba); + + chip->rom = rom; + + SCAN_VAR(nSoundlatch); + SCAN_VAR(bSoundlatchRead); + } +} diff --git a/src/burn/sound/ics2115.h b/src/burn/sound/ics2115.h new file mode 100644 index 00000000..362c265d --- /dev/null +++ b/src/burn/sound/ics2115.h @@ -0,0 +1,16 @@ +extern UINT8 *ICSSNDROM; +extern UINT32 nICSSNDROMLen; + +extern UINT8 ics2115read(UINT8 offset); +extern void ics2115write(UINT8 offset, UINT8 data); + +extern INT32 ics2115_init(); +extern void ics2115_exit(); +extern void ics2115_reset(); + +extern UINT16 ics2115_soundlatch_r(INT32 i); +extern void ics2115_soundlatch_w(INT32 i, UINT16 d); + +extern void ics2115_frame(); +extern void ics2115_update(INT32 length); +extern void ics2115_scan(INT32 nAction,INT32 *pnMin); diff --git a/src/burn/sound/iremga20.cpp b/src/burn/sound/iremga20.cpp new file mode 100644 index 00000000..3f5042dd --- /dev/null +++ b/src/burn/sound/iremga20.cpp @@ -0,0 +1,260 @@ +/********************************************************* + +Irem GA20 PCM Sound Chip + +It's not currently known whether this chip is stereo. + + +Revisions: + +04-15-2002 Acho A. Tang +- rewrote channel mixing +- added prelimenary volume and sample rate emulation + +05-30-2002 Acho A. Tang +- applied hyperbolic gain control to volume and used + a musical-note style progression in sample rate + calculation(still very inaccurate) + +02-18-2004 R. Belmont +- sample rate calculation reverse-engineered. + Thanks to Fujix, Yasuhiro Ogawa, the Guru, and Tormod + for real PCB samples that made this possible. + +02-03-2007 R. Belmont +- Cleaned up faux x86 assembly. + +*********************************************************/ + +#include "burnint.h" +#include "iremga20.h" + +#define MAX_GA20 1 +#define MAX_VOL 256 + +struct IremGA20_channel_def +{ + UINT32 rate; + UINT32 size; + UINT32 start; + UINT32 pos; + UINT32 frac; + UINT32 end; + UINT32 volume; + UINT32 pan; + UINT32 effect; + UINT32 play; +}; + +typedef struct _ga20_state ga20_state; +struct _ga20_state +{ + UINT8 *rom; + INT32 rom_size; + UINT16 regs[0x40]; + struct IremGA20_channel_def channel[4]; + INT32 frequency; +}; + +static struct _ga20_state chips[MAX_GA20]; +static struct _ga20_state *chip; + +static UINT32 computed_steps; + +// 14318180/4 -> 3579545/4 -> 894886/60 -> 14915 +// 44100 / 60 -> 735 + +void iremga20_update(INT32 device, INT16 *buffer, INT32 length) +{ + chip = &chips[device]; + UINT32 rate[4], pos[4], frac[4], end[4], vol[4], play[4]; + UINT8 *pSamples; + INT32 i, sampleout; + + /* precache some values */ + for (i=0; i < 4; i++) + { + rate[i] = chip->channel[i].rate; + pos[i] = chip->channel[i].pos; + frac[i] = chip->channel[i].frac; + end[i] = chip->channel[i].end - 0x20; + vol[i] = chip->channel[i].volume; + play[i] = chip->channel[i].play; + } + + pSamples = chip->rom; + + for (i = 0; i < length; i++, buffer+=2) + { + sampleout = 0; + + // update the 4 channels inline + if (play[0]) + { + sampleout += (pSamples[pos[0]] - 0x80) * vol[0]; + frac[0] += rate[0] * computed_steps; + pos[0] += frac[0] >> 24; + frac[0] &= 0xffffff; + play[0] = (pos[0] < end[0]); + } + if (play[1]) + { + sampleout += (pSamples[pos[1]] - 0x80) * vol[1]; + frac[1] += rate[1] * computed_steps; + pos[1] += frac[1] >> 24; + frac[1] &= 0xffffff; + play[1] = (pos[1] < end[1]); + } + if (play[2]) + { + sampleout += (pSamples[pos[2]] - 0x80) * vol[2]; + frac[2] += rate[2] * computed_steps; + pos[2] += frac[2] >> 24; + frac[2] &= 0xffffff; + play[2] = (pos[2] < end[2]); + } + if (play[3]) + { + sampleout += (pSamples[pos[3]] - 0x80) * vol[3]; + frac[3] += rate[3] * computed_steps; + pos[3] += frac[3] >> 24; + frac[3] &= 0xffffff; + play[3] = (pos[3] < end[3]); + } + + sampleout >>= 2; + buffer[0] += sampleout; + buffer[1] += sampleout; + } + + /* update the regs now */ + for (i=0; i < 4; i++) + { + chip->channel[i].pos = pos[i]; + chip->channel[i].frac = frac[i]; + chip->channel[i].play = play[i]; + } +} + +void iremga20_write(INT32 device, INT32 offset, INT32 data) +{ + chip = &chips[device]; + + INT32 channel = offset >> 3; + + chip->regs[offset] = data; + + switch (offset & 0x7) + { + case 0: /* start address low */ + chip->channel[channel].start = ((chip->channel[channel].start)&0xff000) | (data<<4); + break; + + case 1: /* start address high */ + chip->channel[channel].start = ((chip->channel[channel].start)&0x00ff0) | (data<<12); + break; + + case 2: /* end address low */ + chip->channel[channel].end = ((chip->channel[channel].end)&0xff000) | (data<<4); + break; + + case 3: /* end address high */ + chip->channel[channel].end = ((chip->channel[channel].end)&0x00ff0) | (data<<12); + break; + + case 4: + chip->channel[channel].rate = 0x1000000 / (256 - data); + break; + + case 5: //AT: gain control + chip->channel[channel].volume = (data * MAX_VOL) / (data + 10); + break; + + case 6: //AT: this is always written 2(enabling both channels?) + chip->channel[channel].play = data; + chip->channel[channel].pos = chip->channel[channel].start; + chip->channel[channel].frac = 0; + break; + } +} + +UINT8 iremga20_read(INT32 device, INT32 offset) +{ + chip = &chips[device]; + + switch (offset & 0x7) + { + case 7: // voice status. bit 0 is 1 if active. (routine around 0xccc in rtypeleo) + return chip->channel[offset >> 3].play ? 1 : 0; + + default: + break; + } + + return 0; +} + +void iremga20_reset(INT32 device) +{ + chip = &chips[device]; + + for(INT32 i = 0; i < 4; i++ ) { + chip->channel[i].rate = 0; + chip->channel[i].size = 0; + chip->channel[i].start = 0; + chip->channel[i].pos = 0; + chip->channel[i].frac = 0; + chip->channel[i].end = 0; + chip->channel[i].volume = 0; + chip->channel[i].pan = 0; + chip->channel[i].effect = 0; + chip->channel[i].play = 0; + } + + for ( INT32 i = 0; i < 0x40; i++ ) + chip->regs[i] = 0; +} + +void iremga20_init(INT32 device, UINT8 *rom, INT32 rom_size, INT32 frequency) +{ + chip = &chips[device]; + + /* Initialize our chip structure */ + chip->rom = rom; + chip->rom_size = rom_size; + chip->frequency = (frequency / 4) / 60; + + iremga20_reset(device); + + computed_steps = (UINT32)((float)(chip->frequency / (1.00000 * nBurnSoundLen))); +} + +void iremga20_exit() +{ + +} + +INT32 iremga20_scan(INT32 device, INT32 nAction, INT32 *pnMin) +{ + chip = &chips[device]; + + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029678; + } + + sprintf(szName, "DAC #%d", device); + ba.Data = &chip; + ba.nLen = sizeof(_ga20_state); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + return 0; +} diff --git a/src/burn/sound/iremga20.h b/src/burn/sound/iremga20.h new file mode 100644 index 00000000..118bda7e --- /dev/null +++ b/src/burn/sound/iremga20.h @@ -0,0 +1,9 @@ +void iremga20_write(INT32 device, INT32 offset, INT32 data); +UINT8 iremga20_read(INT32 device, INT32 offset); + +void iremga20_reset(INT32 device); +void iremga20_init(INT32 device, UINT8 *rom, INT32 rom_size, INT32 frequency); +void iremga20_update(INT32 device, INT16 *buffer, INT32 length); +void iremga20_exit(); + +INT32 iremga20_scan(INT32 device, INT32 nAction, INT32 *pnMin); diff --git a/src/burn/sound/k007232.cpp b/src/burn/sound/k007232.cpp new file mode 100644 index 00000000..065d76cd --- /dev/null +++ b/src/burn/sound/k007232.cpp @@ -0,0 +1,280 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "k007232.h" + +#define KDAC_A_PCM_MAX (2) +#define BASE_SHIFT (12) + +typedef void (*K07232_PortWrite)(INT32 v); + +static UINT32 fncode[0x200]; + +struct kdacApcm +{ + UINT8 vol[KDAC_A_PCM_MAX][2]; + UINT32 addr[KDAC_A_PCM_MAX]; + UINT32 start[KDAC_A_PCM_MAX]; + UINT32 step[KDAC_A_PCM_MAX]; + UINT32 bank[KDAC_A_PCM_MAX]; + INT32 play[KDAC_A_PCM_MAX]; + + UINT8 wreg[0x10]; + + INT32 UpdateStep; +}; + +// stuff that doesn't need to be saved.. +struct kdacPointers +{ + UINT32 clock; + UINT8 *pcmbuf[2]; + UINT32 pcmlimit; + K07232_PortWrite K07232PortWriteHandler; +}; + +static struct kdacApcm Chips[2]; +static struct kdacPointers Pointers[2]; +static struct kdacApcm *Chip = NULL; +static struct kdacPointers *Ptr = NULL; +static INT32 *Left = NULL; +static INT32 *Right = NULL; + +void K007232Update(INT32 chip, INT16* pSoundBuf, INT32 nLength) +{ + INT32 i; + + Chip = &Chips[chip]; + Ptr = &Pointers[chip]; + + memset(Left, 0, nLength * sizeof(INT32)); + memset(Right, 0, nLength * sizeof(INT32)); + + for (i = 0; i < KDAC_A_PCM_MAX; i++) { + if (Chip->play[i]) { + INT32 volA,volB,j,out; + UINT32 addr, old_addr; + + addr = Chip->start[i] + ((Chip->addr[i]>>BASE_SHIFT)&0x000fffff); + volA = Chip->vol[i][0] * 2; + volB = Chip->vol[i][1] * 2; + + for( j = 0; j < nLength; j++) { + old_addr = addr; + addr = Chip->start[i] + ((Chip->addr[i]>>BASE_SHIFT)&0x000fffff); + while (old_addr <= addr) { + if( (Ptr->pcmbuf[i][old_addr] & 0x80) || old_addr >= Ptr->pcmlimit ) { + if( Chip->wreg[0x0d]&(1<start[i] = ((((UINT32)Chip->wreg[i*0x06 + 0x04]<<16)&0x00010000) | (((UINT32)Chip->wreg[i*0x06 + 0x03]<< 8)&0x0000ff00) | (((UINT32)Chip->wreg[i*0x06 + 0x02] )&0x000000ff) | Chip->bank[i]); + addr = Chip->start[i]; + Chip->addr[i] = 0; + old_addr = addr; + } else { + Chip->play[i] = 0; + } + break; + } + + old_addr++; + } + + if (Chip->play[i] == 0) break; + + Chip->addr[i] += (Chip->step[i] * Chip->UpdateStep) >> 16; + + out = (Ptr->pcmbuf[i][addr] & 0x7f) - 0x40; + + Left[j] += out * volA; + Right[j] += out * volB; + } + } + } + + for (i = 0; i < nLength; i++) { + if (Left[i] > 32767) Left[i] = 32767; + if (Left[i] < -32768) Left[i] = -32768; + + if (Right[i] > 32767) Right[i] = 32767; + if (Right[i] < -32768) Right[i] = -32768; + + pSoundBuf[0] += Left[i] >> 2; + pSoundBuf[1] += Right[i] >> 2; + pSoundBuf += 2; + } +} + +UINT8 K007232ReadReg(INT32 chip, INT32 r) +{ + INT32 ch = 0; + + Chip = &Chips[chip]; + Ptr = &Pointers[chip]; + + if (r == 0x0005 || r == 0x000b) { + ch = r / 0x0006; + r = ch * 0x0006; + + Chip->start[ch] = ((((UINT32)Chip->wreg[r + 0x04]<<16)&0x00010000) | (((UINT32)Chip->wreg[r + 0x03]<< 8)&0x0000ff00) | (((UINT32)Chip->wreg[r + 0x02] )&0x000000ff) | Chip->bank[ch]); + + if (Chip->start[ch] < Ptr->pcmlimit) { + Chip->play[ch] = 1; + Chip->addr[ch] = 0; + } + } + + return 0; +} + +void K007232WriteReg(INT32 chip, INT32 r, INT32 v) +{ + INT32 Data; + + Chip = &Chips[chip]; + Ptr = &Pointers[chip]; + + Chip->wreg[r] = v; + + if (r == 0x0c) { + if (Ptr->K07232PortWriteHandler) Ptr->K07232PortWriteHandler(v); + return; + } + else if( r == 0x0d ){ + // loopflag + return; + } + else { + INT32 RegPort; + + RegPort = 0; + if (r >= 0x06) { + RegPort = 1; + r -= 0x06; + } + + switch (r) { + case 0x00: + case 0x01: + Data = (((((UINT32)Chip->wreg[RegPort*0x06 + 0x01])<<8)&0x0100) | (((UINT32)Chip->wreg[RegPort*0x06 + 0x00])&0x00ff)); + Chip->step[RegPort] = fncode[Data]; + break; + + case 0x02: + case 0x03: + case 0x04: + break; + + case 0x05: + Chip->start[RegPort] = ((((UINT32)Chip->wreg[RegPort*0x06 + 0x04]<<16)&0x00010000) | (((UINT32)Chip->wreg[RegPort*0x06 + 0x03]<< 8)&0x0000ff00) | (((UINT32)Chip->wreg[RegPort*0x06 + 0x02] )&0x000000ff) | Chip->bank[RegPort]); + if (Chip->start[RegPort] < Ptr->pcmlimit ) { + Chip->play[RegPort] = 1; + Chip->addr[RegPort] = 0; + } + break; + } + } +} + +void K007232SetPortWriteHandler(INT32 chip, void (*Handler)(INT32 v)) +{ + Chip = &Chips[chip]; + Ptr = &Pointers[chip]; + + Ptr->K07232PortWriteHandler = Handler; +} + +static void KDAC_A_make_fncode() +{ + for (INT32 i = 0; i < 0x200; i++) fncode[i] = (32 << BASE_SHIFT) / (0x200 - i); +} + +void K007232Init(INT32 chip, INT32 clock, UINT8 *pPCMData, INT32 PCMDataSize) +{ + Chip = &Chips[chip]; + Ptr = &Pointers[chip]; + + memset(Chip, 0, sizeof(kdacApcm)); + memset(Ptr, 0, sizeof(kdacPointers)); + + if (Left == NULL) { + Left = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + } + + if (Right == NULL) { + Right = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + } + + Ptr->pcmbuf[0] = pPCMData; + Ptr->pcmbuf[1] = pPCMData; + Ptr->pcmlimit = PCMDataSize; + + Ptr->clock = clock; + + for (INT32 i = 0; i < KDAC_A_PCM_MAX; i++) { + Chip->start[i] = 0; + Chip->step[i] = 0; + Chip->play[i] = 0; + Chip->bank[i] = 0; + } + Chip->vol[0][0] = 255; + Chip->vol[0][1] = 0; + Chip->vol[1][0] = 0; + Chip->vol[1][1] = 255; + + for (INT32 i = 0; i < 0x10; i++) Chip->wreg[i] = 0; + + KDAC_A_make_fncode(); + + double Rate = (double)clock / 128 / nBurnSoundRate; + Chip->UpdateStep = (INT32)(Rate * 0x10000); +} + +void K007232Exit() +{ + if (Left) { + free(Left); + Left = NULL; + } + + if (Right) { + free(Right); + Right = NULL; + } +} + +INT32 K007232Scan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + char szName[32]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029693; + } + + sprintf(szName, "K007232 Chip # %d", 0); + ba.Data = &Chip; + ba.nLen = sizeof(struct kdacApcm); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + return 0; +} + +void K007232SetVolume(INT32 chip, INT32 channel,INT32 volumeA,INT32 volumeB) +{ + Chip = &Chips[chip]; + + Chip->vol[channel][0] = volumeA; + Chip->vol[channel][1] = volumeB; +} + +void k007232_set_bank(INT32 chip, INT32 chABank, INT32 chBBank ) +{ + Chip = &Chips[chip]; + + Chip->bank[0] = chABank<<17; + Chip->bank[1] = chBBank<<17; +} diff --git a/src/burn/sound/k007232.h b/src/burn/sound/k007232.h new file mode 100644 index 00000000..9a0abfcf --- /dev/null +++ b/src/burn/sound/k007232.h @@ -0,0 +1,9 @@ +void K007232Update(INT32 chip, INT16* pSoundBuf, INT32 nLength); +UINT8 K007232ReadReg(INT32 chip, INT32 r); +void K007232WriteReg(INT32 chip, INT32 r, INT32 v); +void K007232SetPortWriteHandler(INT32 chip, void (*Handler)(INT32 v)); +void K007232Init(INT32 chip, INT32 clock, UINT8 *pPCMData, INT32 PCMDataSize); +void K007232Exit(); +INT32 K007232Scan(INT32 nAction, INT32 *pnMin); +void K007232SetVolume(INT32 chip, INT32 channel,INT32 volumeA,INT32 volumeB); +void k007232_set_bank( INT32 chip, INT32 chABank, INT32 chBBank ); diff --git a/src/burn/sound/k051649.cpp b/src/burn/sound/k051649.cpp new file mode 100644 index 00000000..8251d71a --- /dev/null +++ b/src/burn/sound/k051649.cpp @@ -0,0 +1,269 @@ +/*************************************************************************** + + Konami 051649 - SCC1 sound as used in Haunted Castle, City Bomber + + This file is pieced together by Bryan McPhail from a combination of + Namco Sound, Amuse by Cab, Haunted Castle schematics and whoever first + figured out SCC! + + The 051649 is a 5 channel sound generator, each channel gets it's + waveform from RAM (32 bytes per waveform, 8 bit signed data). + + This sound chip is the same as the sound chip in some Konami + megaROM cartridges for the MSX. It is actually well researched + and documented: + + http://www.msxnet.org/tech/scc + + Thanks to Sean Young (sean@mess.org) for some bugfixes. + + K052539 is equivalent to this chip except channel 5 does not share + waveforms with channel 4. + +***************************************************************************/ + +#include "burnint.h" + +#define FREQBASEBITS 16 + +static UINT32 nUpdateStep; + +/* this structure defines the parameters for a channel */ +typedef struct +{ + //unsigned long counter; + UINT64 counter; + INT32 frequency; + INT32 volume; + INT32 key; + INT8 waveform[32]; /* 19991207.CAB */ +} k051649_sound_channel; + +typedef struct _k051649_state k051649_state; +struct _k051649_state +{ + k051649_sound_channel channel_list[5]; + + /* global sound parameters */ + INT32 mclock,rate,gain; + + /* mixer tables and internal buffers */ + INT16 *mixer_table; + INT16 *mixer_lookup; + INT16 *mixer_buffer; + + INT32 f[10]; +}; + +static k051649_state Chips[1]; // ok? +static k051649_state *info; + +/* build a table to divide by the number of voices */ +static void make_mixer_table(INT32 voices) +{ + INT32 count = voices * 256; + INT32 i; + INT32 gain = 8; + + /* allocate memory */ + info->mixer_table = (INT16 *)malloc(512 * voices * sizeof(INT16)); + + /* find the middle of the table */ + info->mixer_lookup = info->mixer_table + (256 * voices); + + /* fill in the table - 16 bit case */ + for (i = 0; i < count; i++) + { + INT32 val = i * gain * 16 / voices; + if (val > 32767) val = 32767; + info->mixer_lookup[ i] = val; + info->mixer_lookup[-i] = -val; + } +} + + +/* generate sound to the mix buffer */ +void K051649Update(INT16 *pBuf, INT32 samples) +{ + info = &Chips[0]; + k051649_sound_channel *voice=info->channel_list; + INT16 *mix; + INT32 i,v,f,j,k; + INT32 gain = info->gain; + + /* zap the contents of the mixer buffer */ + memset(info->mixer_buffer, 0, samples * sizeof(INT16)); + + for (j=0; j<5; j++) { + v=voice[j].volume; + f=voice[j].frequency; + k=voice[j].key; + /* SY 20040109: the SCC produces no sound for freq < 9 */ + if (v && f > 8 && k) + { + const INT8 *w = voice[j].waveform; /* 19991207.CAB */ + INT32 c=voice[j].counter; + + mix = info->mixer_buffer; + + /* add our contribution */ + for (i = 0; i < samples; i++) + { + INT32 offs; + + /* Amuse source: Cab suggests this method gives greater resolution */ + /* Sean Young 20010417: the formula is really: f = clock/(16*(f+1))*/ + //c+=(long)((((float)info->mclock / (float)((f+1) * 16))*(float)(1<rate / 32)); + c+=(INT32)((((((float)info->mclock / (float)((f+1) * 16))*(float)(1<rate / 32)) * nUpdateStep) / 32768); + offs = (c >> 16) & 0x1f; + //*mix++ += (((w[offs] * v)>>3) * nUpdateStep) >> 15; + *mix++ += ((w[offs] * v)>>3); + } + + /* update the counter for this voice */ + voice[j].counter = c; + } + } + + /* mix it down */ + mix = info->mixer_buffer; + for (i = 0; i < samples; i++) { + INT32 output = info->mixer_lookup[*mix++]; + + if (output < -0x7fff) output = -0x7fff; + if (output > 0x7fff) output = 0x7fff; + + output = (output * gain) / 100; + + pBuf[0] += output; + pBuf[1] += output; + pBuf += 2; + } +} + +void K051649Init(INT32 clock, float gain) +{ + info = &Chips[0]; + + /* get stream channels */ + info->rate = clock/16; + info->mclock = clock; + info->gain = (INT32)(gain * 100); + + nUpdateStep = (INT32)(((float)info->rate / nBurnSoundRate) * 32768); + + /* allocate a buffer to mix into - 1 second's worth should be more than enough */ + info->mixer_buffer = (INT16 *)malloc(2 * sizeof(INT16) * info->rate); + + /* build the mixer table */ + make_mixer_table(5); +} + +void K051659Exit() +{ + info = &Chips[0]; + + if (info->mixer_buffer) { + free (info->mixer_buffer); + info->mixer_buffer = NULL; + } + + if (info->mixer_table) { + free (info->mixer_table); + info->mixer_table = NULL; + } + + nUpdateStep = 0; +} + +void K051649Reset() +{ + info = &Chips[0]; + k051649_sound_channel *voice = info->channel_list; + INT32 i; + + /* reset all the voices */ + for (i=0; i>5; i++) { + voice[i].frequency = 0; + voice[i].volume = 0; + voice[i].counter = 0; + } +} + +INT32 K051649Scan(INT32 nAction, INT32 *pnMin) +{ + struct BurnArea ba; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029705; + } + + ba.Data = &info->channel_list; + ba.nLen = sizeof(k051649_sound_channel) * 5; + ba.nAddress = 0; + ba.szName = "K051649 Channel list"; + BurnAcb(&ba); + + ba.Data = info->f; + ba.nLen = sizeof(INT32) * 10; + ba.nAddress = 0; + ba.szName = "K051649 Frequency Regs"; + BurnAcb(&ba); + + return 0; +} + +/********************************************************************************/ + +void K051649WaveformWrite(INT32 offset, INT32 data) +{ + info = &Chips[0]; + info->channel_list[offset>>5].waveform[offset&0x1f]=data; + /* SY 20001114: Channel 5 shares the waveform with channel 4 */ + if (offset >= 0x60) + info->channel_list[4].waveform[offset&0x1f]=data; +} + +unsigned char K051649WaveformRead(INT32 offset) +{ + info = &Chips[0]; + return info->channel_list[offset>>5].waveform[offset&0x1f]; +} + +/* SY 20001114: Channel 5 doesn't share the waveform with channel 4 on this chip */ +void K052539WaveformWrite(INT32 offset, INT32 data) +{ + info = &Chips[0]; + + info->channel_list[offset>>5].waveform[offset&0x1f]=data; +} + +void K051649VolumeWrite(INT32 offset, INT32 data) +{ + info = &Chips[0]; + + info->channel_list[offset&0x7].volume=data&0xf; +} + +void K051649FrequencyWrite(INT32 offset, INT32 data) +{ + info = &Chips[0]; + info->f[offset]=data; + + info->channel_list[offset>>1].frequency=(info->f[offset&0xe] + (info->f[offset|1]<<8))&0xfff; +} + +void K051649KeyonoffWrite(INT32 data) +{ + info = &Chips[0]; + info->channel_list[0].key=data&1; + info->channel_list[1].key=data&2; + info->channel_list[2].key=data&4; + info->channel_list[3].key=data&8; + info->channel_list[4].key=data&16; +} + diff --git a/src/burn/sound/k051649.h b/src/burn/sound/k051649.h new file mode 100644 index 00000000..e0928579 --- /dev/null +++ b/src/burn/sound/k051649.h @@ -0,0 +1,15 @@ +void K051649Update(INT16 *pBuf, INT32 samples); +void K051649Init(INT32 clock, float gain); +void K051649Reset(); +void K051659Exit(); + +INT32 K051649Scan(INT32 nAction, INT32 *pnMin); + +void K051649WaveformWrite(INT32 offset, INT32 data); +UINT8 K051649WaveformRead(INT32 offset); + +void K052539WaveformWrite(INT32 offset, INT32 data); + +void K051649VolumeWrite(INT32 offset, INT32 data); +void K051649FrequencyWrite(INT32 offset, INT32 data); +void K051649KeyonoffWrite(INT32 data); diff --git a/src/burn/sound/k053260.cpp b/src/burn/sound/k053260.cpp new file mode 100644 index 00000000..4a6f9978 --- /dev/null +++ b/src/burn/sound/k053260.cpp @@ -0,0 +1,434 @@ +/********************************************************* + + Konami 053260 PCM Sound Chip + +*********************************************************/ + +#include "burnint.h" + +/* 2004-02-28: Fixed ppcm decoding. Games sound much better now.*/ + +#define BASE_SHIFT 16 + +#define K053260_INLINE static inline + +static UINT32 nUpdateStep; + +struct k053260_channel_def { + UINT32 rate; + UINT32 size; + UINT32 start; + UINT32 bank; + UINT32 volume; + INT32 play; + UINT32 pan; + INT32 pos; + INT32 loop; + INT32 ppcm; /* packed PCM ( 4 bit signed ) */ + INT32 ppcm_data; +}; +struct k053260_chip_def { + INT32 mode; + INT32 regs[0x30]; + UINT8 *rom; + INT32 rom_size; + UINT32 *delta_table; + k053260_channel_def channels[4]; +}; + +static k053260_chip_def Chips[2]; +static k053260_chip_def *ic; + +static void InitDeltaTable(INT32 rate, INT32 clock ) { + INT32 i; + double base = ( double )rate; + double max = (double)(clock); /* Hz */ + UINT32 val; + + for( i = 0; i < 0x1000; i++ ) { + double v = ( double )( 0x1000 - i ); + double target = (max) / v; + double fixed = ( double )( 1 << BASE_SHIFT ); + + if ( target && base ) { + target = fixed / ( base / target ); + val = (UINT32)target; + if ( val == 0 ) + val = 1; + } else + val = 1; + + ic->delta_table[i] = val; + } +} + +void K053260Reset(INT32 chip) +{ + ic = &Chips[chip]; + + for(INT32 i = 0; i < 4; i++ ) { + ic->channels[i].rate = 0; + ic->channels[i].size = 0; + ic->channels[i].start = 0; + ic->channels[i].bank = 0; + ic->channels[i].volume = 0; + ic->channels[i].play = 0; + ic->channels[i].pan = 0; + ic->channels[i].pos = 0; + ic->channels[i].loop = 0; + ic->channels[i].ppcm = 0; + ic->channels[i].ppcm_data = 0; + } +} + +K053260_INLINE INT32 limit( INT32 val, INT32 max, INT32 min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; + + return val; +} + +#define MAXOUT 0x3fff +#define MINOUT -0x4000 + +void K053260Update(INT32 chip, INT16 *pBuf, INT32 length) +{ + static const INT32 dpcmcnv[] = { 0,1,2,4,8,16,32,64, -128, -64, -32, -16, -8, -4, -2, -1}; + + INT32 i, j, lvol[4], rvol[4], play[4], loop[4], ppcm_data[4], ppcm[4]; + UINT8 *rom[4]; + UINT32 delta[4], end[4], pos[4]; + INT32 dataL, dataR; + INT8 d; + ic = &Chips[chip]; + + /* precache some values */ + for ( i = 0; i < 4; i++ ) { + rom[i]= &ic->rom[ic->channels[i].start + ( ic->channels[i].bank << 16 )]; + delta[i] = (ic->delta_table[ic->channels[i].rate] * nUpdateStep) >> 15; + lvol[i] = ic->channels[i].volume * ic->channels[i].pan; + rvol[i] = ic->channels[i].volume * ( 8 - ic->channels[i].pan ); + end[i] = ic->channels[i].size; + pos[i] = ic->channels[i].pos; + play[i] = ic->channels[i].play; + loop[i] = ic->channels[i].loop; + ppcm[i] = ic->channels[i].ppcm; + ppcm_data[i] = ic->channels[i].ppcm_data; + if ( ppcm[i] ) + delta[i] /= 2; + } + + for ( j = 0; j < length; j++ ) { + + dataL = dataR = 0; + + for ( i = 0; i < 4; i++ ) { + /* see if the voice is on */ + if ( play[i] ) { + /* see if we're done */ + if ( ( pos[i] >> BASE_SHIFT ) >= end[i] ) { + + ppcm_data[i] = 0; + if ( loop[i] ) + pos[i] = 0; + else { + play[i] = 0; + continue; + } + } + + if ( ppcm[i] ) { /* Packed PCM */ + /* we only update the signal if we're starting or a real sound sample has gone by */ + /* this is all due to the dynamic sample rate convertion */ + if ( pos[i] == 0 || ( ( pos[i] ^ ( pos[i] - delta[i] ) ) & 0x8000 ) == 0x8000 ) + + { + INT32 newdata; + if ( pos[i] & 0x8000 ){ + + newdata = ((rom[i][pos[i] >> BASE_SHIFT]) >> 4) & 0x0f; /*high nybble*/ + } + else{ + newdata = ( ( rom[i][pos[i] >> BASE_SHIFT] ) ) & 0x0f; /*low nybble*/ + } + + ppcm_data[i] = (( ( ppcm_data[i] * 62 ) >> 6 ) + dpcmcnv[newdata]); + + if ( ppcm_data[i] > 127 ) + ppcm_data[i] = 127; + else + if ( ppcm_data[i] < -128 ) + ppcm_data[i] = -128; + } + + d = ppcm_data[i]; + + pos[i] += delta[i]; + } else { /* PCM */ + d = rom[i][pos[i] >> BASE_SHIFT]; + + pos[i] += delta[i]; + } + + if ( ic->mode & 2 ) { + dataL += ( d * lvol[i] ) >> 4; + dataR += ( d * rvol[i] ) >> 4; + } + } + } + + pBuf[1] += limit( dataL, MAXOUT, MINOUT ); + pBuf[0] += limit( dataR, MAXOUT, MINOUT ); + pBuf += 2; + } + + /* update the regs now */ + for ( i = 0; i < 4; i++ ) { + ic->channels[i].pos = pos[i]; + ic->channels[i].play = play[i]; + ic->channels[i].ppcm_data = ppcm_data[i]; + } +} + +void K053260Init(INT32 chip, INT32 clock, UINT8 *rom, INT32 nLen) +{ + ic = &Chips[chip]; + memset (ic, 0, sizeof(k053260_chip_def)); + + INT32 rate = clock / 32; + INT32 i; + + nUpdateStep = (INT32)(((float)rate / nBurnSoundRate) * 32768); + + ic->mode = 0; + ic->rom = rom; + ic->rom_size = nLen - 1; + + K053260Reset(chip); + + for ( i = 0; i < 0x30; i++ ) + ic->regs[i] = 0; + + ic->delta_table = (UINT32* )malloc( 0x1000 * sizeof(UINT32) ); + + InitDeltaTable( rate, clock ); + + /* setup SH1 timer if necessary */ +// if ( ic->intf->irq ) +// timer_pulse( attotime_mul(ATTOTIME_IN_HZ(clock), 32), NULL, 0, ic->intf->irq ); +} + +void K053260Exit() +{ + for (INT32 i = 0; i < 2; i++) { + ic = &Chips[i]; + + if (ic->delta_table) { + free (ic->delta_table); + ic->delta_table = NULL; + } + } + + nUpdateStep = 0; +} + +K053260_INLINE void check_bounds(INT32 channel ) { + + INT32 channel_start = ( ic->channels[channel].bank << 16 ) + ic->channels[channel].start; + INT32 channel_end = channel_start + ic->channels[channel].size - 1; + + if ( channel_start > ic->rom_size ) { + ic->channels[channel].play = 0; + + return; + } + + if ( channel_end > ic->rom_size ) { + ic->channels[channel].size = ic->rom_size - channel_start; + } +} + +void K053260Write(INT32 chip, INT32 offset, UINT8 data) +{ + INT32 i, t; + INT32 r = offset; + INT32 v = data; + + ic = &Chips[chip]; + + if ( r > 0x2f ) { + return; + } + + /* before we update the regs, we need to check for a latched reg */ + if ( r == 0x28 ) { + t = ic->regs[r] ^ v; + + for ( i = 0; i < 4; i++ ) { + if ( t & ( 1 << i ) ) { + if ( v & ( 1 << i ) ) { + ic->channels[i].play = 1; + ic->channels[i].pos = 0; + ic->channels[i].ppcm_data = 0; + check_bounds( i ); + } else + ic->channels[i].play = 0; + } + } + + ic->regs[r] = v; + return; + } + + /* update regs */ + ic->regs[r] = v; + + /* communication registers */ + if ( r < 8 ) + return; + + /* channel setup */ + if ( r < 0x28 ) { + INT32 channel = ( r - 8 ) / 8; + + switch ( ( r - 8 ) & 0x07 ) { + case 0: /* sample rate low */ + ic->channels[channel].rate &= 0x0f00; + ic->channels[channel].rate |= v; + break; + + case 1: /* sample rate high */ + ic->channels[channel].rate &= 0x00ff; + ic->channels[channel].rate |= ( v & 0x0f ) << 8; + break; + + case 2: /* size low */ + ic->channels[channel].size &= 0xff00; + ic->channels[channel].size |= v; + break; + + case 3: /* size high */ + ic->channels[channel].size &= 0x00ff; + ic->channels[channel].size |= v << 8; + break; + + case 4: /* start low */ + ic->channels[channel].start &= 0xff00; + ic->channels[channel].start |= v; + break; + + case 5: /* start high */ + ic->channels[channel].start &= 0x00ff; + ic->channels[channel].start |= v << 8; + break; + + case 6: /* bank */ + ic->channels[channel].bank = v & 0xff; + break; + + case 7: /* volume is 7 bits. Convert to 8 bits now. */ + ic->channels[channel].volume = ( ( v & 0x7f ) << 1 ) | ( v & 1 ); + break; + } + + return; + } + + switch( r ) { + case 0x2a: /* loop, ppcm */ + for ( i = 0; i < 4; i++ ) + ic->channels[i].loop = ( v & ( 1 << i ) ) != 0; + + for ( i = 4; i < 8; i++ ) + ic->channels[i-4].ppcm = ( v & ( 1 << i ) ) != 0; + break; + + case 0x2c: /* pan */ + ic->channels[0].pan = v & 7; + ic->channels[1].pan = ( v >> 3 ) & 7; + break; + + case 0x2d: /* more pan */ + ic->channels[2].pan = v & 7; + ic->channels[3].pan = ( v >> 3 ) & 7; + break; + + case 0x2f: /* control */ + ic->mode = v & 7; + /* bit 0 = read ROM */ + /* bit 1 = enable sound output */ + /* bit 2 = unknown */ + break; + } +} + +UINT8 K053260Read(INT32 chip, INT32 offset) +{ + ic = & Chips[chip]; + + switch ( offset ) { + case 0x29: /* channel status */ + { + INT32 i, status = 0; + + for ( i = 0; i < 4; i++ ) + status |= ic->channels[i].play << i; + + return status; + } + break; + + case 0x2e: /* read rom */ + if ( ic->mode & 1 ) { + UINT32 offs = ic->channels[0].start + ( ic->channels[0].pos >> BASE_SHIFT ) + ( ic->channels[0].bank << 16 ); + + ic->channels[0].pos += ( 1 << 16 ); + + if ( offs > (UINT32)ic->rom_size ) { + + return 0; + } + + return ic->rom[offs]; + } + break; + } + + return ic->regs[offset]; +} + +INT32 K053260Scan(INT32 nAction) +{ + struct BurnArea ba; + char szName[32]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + for (INT32 i = 0; i < 2; i++) { + ic = &Chips[i]; + + sprintf(szName, "k053260 regs %d", 0); + ba.Data = ic->regs; + ba.nLen = 0x30 * sizeof(INT32); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + sprintf(szName, "k053260 channels # %d", 0); + ba.Data = ic->channels; + ba.nLen = 4 * sizeof(k053260_channel_def); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + SCAN_VAR(ic->mode); + } + + return 0; +} + +#undef K053260_INLINE diff --git a/src/burn/sound/k053260.h b/src/burn/sound/k053260.h new file mode 100644 index 00000000..1901ec9b --- /dev/null +++ b/src/burn/sound/k053260.h @@ -0,0 +1,8 @@ +void K053260Reset(INT32 chip); +void K053260Update(INT32 chip, INT16 *pBuf, INT32 length); +void K053260Init(INT32 chip, INT32 clock, UINT8 *rom, INT32 nLen); +void K053260Exit(); +void K053260Write(INT32 chip, INT32 offset, UINT8 data); +UINT8 K053260Read(INT32 chip, INT32 offset); + +INT32 K053260Scan(INT32 nAction); diff --git a/src/burn/sound/k054539.cpp b/src/burn/sound/k054539.cpp new file mode 100644 index 00000000..6875d9b0 --- /dev/null +++ b/src/burn/sound/k054539.cpp @@ -0,0 +1,592 @@ +/********************************************************* + + Konami 054539 PCM Sound Chip + + A lot of information comes from Amuse. + Big thanks to them. + +*********************************************************/ + +// IRQ handling is disabled for now... + +#include "burnint.h" +#include "math.h" +#include "k054539.h" + +static UINT32 nUpdateStep; + +typedef struct _k054539_interface k054539_interface; +struct _k054539_interface +{ + const char *rgnoverride; + void (*apan)(double, double); +// void (*irq)(running_machine *); +}; + +struct k054539_channel { + UINT32 pos; + UINT32 pfrac; + INT32 val; + INT32 pval; +}; + +struct k054539_info { + const k054539_interface *intf; + double voltab[256]; + double pantab[0xf]; + + double k054539_gain[8]; + UINT8 k054539_posreg_latch[8][3]; + INT32 k054539_flags; + + UINT8 regs[0x230]; + UINT8 *ram; + INT32 reverb_pos; + + INT32 cur_ptr; + INT32 cur_limit; + UINT8 *cur_zone; + UINT8 *rom; + UINT32 rom_size; + UINT32 rom_mask; + + INT32 clock; + + k054539_channel channels[8]; +}; + +static k054539_info Chips[2]; +static k054539_info *info; + +static INT32 *soundbuf[2]; + +void K054539_init_flags(INT32 chip, INT32 flags) +{ + info = &Chips[chip]; + info->k054539_flags = flags; +} + +void K054539_set_gain(INT32 chip, INT32 channel, double gain) +{ + info = &Chips[chip]; + if (gain >= 0) info->k054539_gain[channel] = gain; +} + +static INT32 k054539_regupdate() +{ + return !(info->regs[0x22f] & 0x80); +} + +static void k054539_keyon(INT32 channel) +{ + if(k054539_regupdate()) + info->regs[0x22c] |= 1 << channel; +} + +static void k054539_keyoff(INT32 channel) +{ + if(k054539_regupdate()) + info->regs[0x22c] &= ~(1 << channel); +} + +void K054539Write(INT32 chip, INT32 offset, UINT8 data) +{ + info = &Chips[chip]; + + INT32 latch, offs, ch, pan; + UINT8 *regbase, *regptr, *posptr; + + regbase = info->regs; + latch = (info->k054539_flags & K054539_UPDATE_AT_KEYON) && (regbase[0x22f] & 1); + + if (latch && offset < 0x100) + { + offs = (offset & 0x1f) - 0xc; + ch = offset >> 5; + + if (offs >= 0 && offs <= 2) + { + // latch writes to the position index registers + info->k054539_posreg_latch[ch][offs] = data; + return; + } + } + + else switch(offset) + { + case 0x13f: + pan = data >= 0x11 && data <= 0x1f ? data - 0x11 : 0x18 - 0x11; + if(info->intf->apan) + info->intf->apan(info->pantab[pan], info->pantab[0xe - pan]); + break; + + case 0x214: + if (latch) + { + for(ch=0; ch<8; ch++) + { + if(data & (1<k054539_posreg_latch[ch][0]; + regptr = regbase + (ch<<5) + 0xc; + + // update the chip at key-on + regptr[0] = posptr[0]; + regptr[1] = posptr[1]; + regptr[2] = posptr[2]; + + k054539_keyon(ch); + } + } + } + else + { + for(ch=0; ch<8; ch++) + if(data & (1<cur_zone[info->cur_ptr] = data; + info->cur_ptr++; + if(info->cur_ptr == info->cur_limit) + info->cur_ptr = 0; + break; + + case 0x22e: + info->cur_zone = + data == 0x80 ? info->ram : + info->rom + 0x20000*data; + info->cur_limit = data == 0x80 ? 0x4000 : 0x20000; + info->cur_ptr = 0; + break; + + default: + break; + } + + regbase[offset] = data; +} + +UINT8 K054539Read(INT32 chip, INT32 offset) +{ + info = &Chips[chip]; + + switch(offset) { + case 0x22d: + if(info->regs[0x22f] & 0x10) { + UINT8 res = info->cur_zone[info->cur_ptr]; + info->cur_ptr++; + if(info->cur_ptr == info->cur_limit) + info->cur_ptr = 0; + return res; + } else + return 0; + + case 0x22c: + break; + + default: + break; + } + + return info->regs[offset]; +} + +void K054539Reset(INT32 chip) +{ + info = &Chips[chip]; + INT32 data = info->regs[0x22e]; + info->cur_zone = + data == 0x80 ? info->ram : + info->rom + 0x20000*data; + info->cur_limit = data == 0x80 ? 0x4000 : 0x20000; +} + +static void k054539_init_chip(INT32 clock, UINT8 *rom, INT32 nLen) +{ + INT32 i; + + memset(info->regs, 0, sizeof(info->regs)); + memset(info->k054539_posreg_latch, 0, sizeof(info->k054539_posreg_latch)); + info->k054539_flags |= K054539_UPDATE_AT_KEYON; // make it default until proven otherwise + + // Real size of 0x4000, the addon is to simplify the reverb buffer computations + info->ram = (UINT8*)malloc(0x4000*2+clock/50*2); + info->reverb_pos = 0; + info->cur_ptr = 0; + memset(info->ram, 0, 0x4000*2+clock/50*2); + + info->rom = rom; + info->rom_size = nLen; + info->rom_mask = 0xffffffffU; + for(i=0; i<32; i++) + if((1U<= info->rom_size) { + info->rom_mask = (1U<intf->irq) +// timer_pulse(ATTOTIME_IN_HZ(480), info, 0, k054539_irq); // 10% of usual clock... +} + +void K054539Init(INT32 chip, INT32 clock, UINT8 *rom, INT32 nLen) +{ + static const k054539_interface defintrf = { 0, 0 }; + INT32 i; + + info = &Chips[chip]; + + info->intf = &defintrf; + info->clock = clock; + + nUpdateStep = (INT32)(((float)clock / nBurnSoundRate) * 32768); + + for (i = 0; i < 8; i++) + info->k054539_gain[i] = 1.0; + + info->k054539_flags = K054539_RESET_FLAGS; + + for(i=0; i<256; i++) + info->voltab[i] = pow(10.0, (-36.0 * (double)i / (double)0x40) / 20.0) / 4.0; + + for(i=0; i<0xf; i++) + info->pantab[i] = sqrt((double)i) / sqrt((double)0xe); + + k054539_init_chip(clock, rom, nLen); + + if (soundbuf[0] == NULL) soundbuf[0] = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + if (soundbuf[1] == NULL) soundbuf[1] = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); +} + +void K054539Exit() +{ + if (soundbuf[0] != NULL) { + free (soundbuf[0]); + soundbuf[0] = NULL; + } + + if (soundbuf[1] != NULL) { + free (soundbuf[1]); + soundbuf[1] = NULL; + } + + for (INT32 i = 0; i < 2; i++) { + info = &Chips[i]; + if (info->ram) { + free (info->ram); + info->ram = NULL; + } + } +} + +void K054539Update(INT32 chip, INT16 *pBuf, INT32 length) +{ + info = &Chips[chip]; +#define VOL_CAP 1.80 + + static const INT16 dpcm[16] = { + 0<<8, 1<<8, 4<<8, 9<<8, 16<<8, 25<<8, 36<<8, 49<<8, + -64<<8, -49<<8, -36<<8, -25<<8, -16<<8, -9<<8, -4<<8, -1<<8 + }; + + INT32 ch, reverb_pos; + INT16 *rbase; + UINT8 *samples; + UINT32 rom_mask; + + UINT8 *base1, *base2; + struct k054539_channel *chan; + INT32 *bufl, *bufr; + INT32 cur_pos, cur_pfrac, cur_val, cur_pval; + INT32 delta, rdelta, fdelta, pdelta; + INT32 vol, bval, pan, i; + + double gain, lvol, rvol, rbvol; + + reverb_pos = info->reverb_pos; + rbase = (INT16 *)(info->ram); + + INT32 **buffer = soundbuf; + + memset(buffer[0], 0, length*sizeof(*buffer[0])); + memset(buffer[1], 0, length*sizeof(*buffer[1])); + + samples = info->rom; + rom_mask = info->rom_mask; + + if(!(info->regs[0x22f] & 1)) return; + + info->reverb_pos = (reverb_pos + length) & 0x3fff; + + for(ch=0; ch<8; ch++) + if(info->regs[0x22c] & (1<regs + 0x20*ch; + base2 = info->regs + 0x200 + 0x2*ch; + chan = info->channels + ch; + delta = base1[0x00] | (base1[0x01] << 8) | (base1[0x02] << 16); + + vol = base1[0x03]; + + bval = vol + base1[0x04]; + if (bval > 255) bval = 255; + + pan = base1[0x05]; +// DJ Main: 81-87 right, 88 middle, 89-8f left +if (pan >= 0x81 && pan <= 0x8f) +pan -= 0x81; +else + if (pan >= 0x11 && pan <= 0x1f) pan -= 0x11; else pan = 0x18 - 0x11; + + gain = info->k054539_gain[ch]; + + lvol = info->voltab[vol] * info->pantab[pan] * gain; + if (lvol > VOL_CAP) lvol = VOL_CAP; + + rvol = info->voltab[vol] * info->pantab[0xe - pan] * gain; + if (rvol > VOL_CAP) rvol = VOL_CAP; + + rbvol= info->voltab[bval] * gain / 2; + if (rbvol > VOL_CAP) rbvol = VOL_CAP; + + rdelta = (base1[6] | (base1[7] << 8)) >> 3; +// rdelta = (reverb_pos + (int)((rdelta - 0x2000) * info->freq_ratio)) & 0x3fff; + rdelta = (INT32)(rdelta + reverb_pos) & 0x3fff; + + cur_pos = (base1[0x0c] | (base1[0x0d] << 8) | (base1[0x0e] << 16)) & rom_mask; + + bufl = buffer[0]; + bufr = buffer[1]; +//* + + if(base2[0] & 0x20) { + delta = -delta; + fdelta = +0x10000; + pdelta = -1; + } else { + fdelta = -0x10000; + pdelta = +1; + } + + if(cur_pos != (INT32)chan->pos) { + chan->pos = cur_pos; + cur_pfrac = 0; + cur_val = 0; + cur_pval = 0; + } else { + cur_pfrac = chan->pfrac; + cur_val = chan->val; + cur_pval = chan->pval; + } + +#define UPDATE_CHANNELS \ + do { \ + *bufl++ += (INT16)(cur_val*lvol); \ + *bufr++ += (INT16)(cur_val*rvol); \ + rbase[rdelta++] += (INT16)(cur_val*rbvol); \ + rdelta &= 0x3fff; \ + } while(0) + + switch(base2[0] & 0xc) { + case 0x0: { // 8bit pcm + for(i=0; i> 15; + + cur_pval = cur_val; + cur_val = (INT16)(samples[cur_pos] << 8); + if(cur_val == (INT16)0x8000) { + if(base2[1] & 1) { + cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask; + cur_val = (INT16)(samples[cur_pos] << 8); + if(cur_val != (INT16)0x8000) + continue; + } + k054539_keyoff(ch); + goto end_channel_0; + } + } + + UPDATE_CHANNELS; + } + end_channel_0: + break; + } + case 0x4: { // 16bit pcm lsb first + pdelta <<= 1; + + for(i=0; i> 15; + + cur_pval = cur_val; + cur_val = (INT16)(samples[cur_pos] | samples[cur_pos+1]<<8); + if(cur_val == (INT16)0x8000) { + if(base2[1] & 1) { + cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask; + cur_val = (INT16)(samples[cur_pos] | samples[cur_pos+1]<<8); + if(cur_val != (INT16)0x8000) + continue; + } + k054539_keyoff(ch); + goto end_channel_4; + } + } + + UPDATE_CHANNELS; + } + end_channel_4: + break; + } + case 0x8: { // 4bit dpcm + cur_pos <<= 1; + cur_pfrac <<= 1; + if(cur_pfrac & 0x10000) { + cur_pfrac &= 0xffff; + cur_pos |= 1; + } + + for(i=0; i> 15; + + cur_pval = cur_val; + cur_val = samples[cur_pos>>1]; + if(cur_val == 0x88) { + if(base2[1] & 1) { + cur_pos = ((base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask) << 1; + cur_val = samples[cur_pos>>1]; + if(cur_val != 0x88) + goto next_iter; + } + k054539_keyoff(ch); + goto end_channel_8; + } + next_iter: + if(cur_pos & 1) + cur_val >>= 4; + else + cur_val &= 15; + cur_val = cur_pval + dpcm[cur_val]; + if(cur_val < -32768) + cur_val = -32768; + else if(cur_val > 32767) + cur_val = 32767; + } + + UPDATE_CHANNELS; + } + end_channel_8: + cur_pfrac >>= 1; + if(cur_pos & 1) + cur_pfrac |= 0x8000; + cur_pos >>= 1; + break; + } + default: + break; + } + chan->pos = cur_pos; + chan->pfrac = cur_pfrac; + chan->pval = cur_pval; + chan->val = cur_val; + if(k054539_regupdate()) { + base1[0x0c] = cur_pos & 0xff; + base1[0x0d] = cur_pos>> 8 & 0xff; + base1[0x0e] = cur_pos>>16 & 0xff; + } + } + + //* drivers should be given the option to disable reverb when things go terribly wrong + if(!(info->k054539_flags & K054539_DISABLE_REVERB)) + { + for(i=0; i 32767) buffer[0][f] = 32767; + if (buffer[0][f] < -32768) buffer[0][f] = -32768; + + if (buffer[1][f] > 32767) buffer[1][f] = 32767; + if (buffer[1][f] < -32768) buffer[1][f] = -32768; + + pBuf[0] += buffer[0][f]; + pBuf[1] += buffer[1][f]; + pBuf += 2; + } + + if(reverb_pos + length > 0x4000) { + i = 0x4000 - reverb_pos; + memset(rbase + reverb_pos, 0, i*2); + memset(rbase, 0, (length-i)*2); + } else + memset(rbase + reverb_pos, 0, length*2); +} + +INT32 K054539Scan(INT32 nAction) +{ + struct BurnArea ba; + char szName[32]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + for (INT32 i = 0; i < 2; i++) { + info = &Chips[i]; + + sprintf(szName, "K054539 Latch %d", 0); + ba.Data = info->k054539_posreg_latch; + ba.nLen = 8*3; + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + sprintf(szName, "K054539 Regs # %d", 0); + ba.Data = info->regs; + ba.nLen = 0x230; + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + sprintf(szName, "K054539 Ram # %d", 0); + ba.Data = info->ram; + ba.nLen = 0x4000*2+info->clock/50*2; + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + ba.Data = &info->channels; + ba.nLen = sizeof(k054539_channel) * 8; + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + SCAN_VAR(info->k054539_flags); + SCAN_VAR(info->reverb_pos); + SCAN_VAR(info->cur_ptr); + SCAN_VAR(info->cur_limit); + + K054539Write(i, 0x22e, K054539Read(0, 0x22e)); + } + + return 0; +} diff --git a/src/burn/sound/k054539.h b/src/burn/sound/k054539.h new file mode 100644 index 00000000..e373c802 --- /dev/null +++ b/src/burn/sound/k054539.h @@ -0,0 +1,18 @@ +#define K054539_RESET_FLAGS 0 +#define K054539_REVERSE_STEREO 1 +#define K054539_DISABLE_REVERB 2 +#define K054539_UPDATE_AT_KEYON 4 + +void K054539_init_flags(INT32 chip, INT32 flags); +void K054539_set_gain(INT32 chip, INT32 channel, double gain); + +void K054539Update(INT32 chip, INT16 *pBuf, INT32 length); + +void K054539Write(INT32 chip, INT32 offset, UINT8 data); +UINT8 K054539Read(INT32 chip, INT32 offset); + +void K054539Reset(INT32 chip); +void K054539Init(INT32 chip, INT32 clock, UINT8 *rom, INT32 nLen); +void K054539Exit(); + +INT32 K054539Scan(INT32 nAction); diff --git a/src/burn/sound/msm5205.cpp b/src/burn/sound/msm5205.cpp new file mode 100644 index 00000000..822a19ce --- /dev/null +++ b/src/burn/sound/msm5205.cpp @@ -0,0 +1,363 @@ +#include "burnint.h" +#include "msm5205.h" +#include "math.h" + +#define MAX_MSM5205 2 + +struct _MSM5205_state +{ + INT32 data; /* next adpcm data */ + INT32 vclk; /* vclk signal (external mode) */ + INT32 reset; /* reset pin signal */ + INT32 prescaler; /* prescaler selector S1 and S2 */ + INT32 bitwidth; /* bit width selector -3B/4B */ + INT32 signal; /* current ADPCM signal */ + INT32 step; /* current ADPCM step */ + INT32 volume; + + INT32 clock; /* clock rate */ + + void (*vclk_callback)(); /* VCLK callback */ + INT32 (*stream_sync)(INT32); + INT32 select; /* prescaler / bit width selector */ + INT32 bAdd; + INT32 streampos; + + INT32 diff_lookup[49*16]; +}; + +static INT16 *stream[MAX_MSM5205]; +static struct _MSM5205_state chips[MAX_MSM5205]; +static struct _MSM5205_state *voice; + +static void MSM5205_playmode(INT32 chip, INT32 select); + +static const INT32 index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 }; + +static void ComputeTables(INT32 chip) +{ + voice = &chips[chip]; + + /* nibble to bit map */ + static const INT32 nbl2bit[16][4] = + { + { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1}, + { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1}, + {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1}, + {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1} + }; + + INT32 step, nib; + + /* loop over all possible steps */ + for (step = 0; step <= 48; step++) + { + /* compute the step value */ + INT32 stepval = (INT32)(floor (16.0 * pow (11.0 / 10.0, (double)step))); + + /* loop over all nibbles and compute the difference */ + for (nib = 0; nib < 16; nib++) + { + voice->diff_lookup[step*16 + nib] = nbl2bit[nib][0] * + (stepval * nbl2bit[nib][1] + + stepval/2 * nbl2bit[nib][2] + + stepval/4 * nbl2bit[nib][3] + + stepval/8); + } + } +} + +static void MSM5205_playmode(INT32 , INT32 select) +{ + static const INT32 prescaler_table[4] = {96,48,64,0}; + INT32 prescaler = prescaler_table[select & 3]; + INT32 bitwidth = (select & 4) ? 4 : 3; + + if( voice->prescaler != prescaler ) + { + voice->prescaler = prescaler; + + if( prescaler ) + { +// clock * prescaler +// 384000 / 48 -> 8000 + +// if cpu is 4000000 (4mhz) +// check MSM5205 every 4000000 / 8000 -> 500 cycles + +// attotime period = attotime_mul(ATTOTIME_IN_HZ(voice->clock), prescaler); +// timer_adjust_periodic(voice->timer, period, 0, period); + } + } + + if( voice->bitwidth != bitwidth ) + { + voice->bitwidth = bitwidth; + } +} + +static void MSM5205StreamUpdate(INT32 chip) +{ + voice = &chips[chip]; + + UINT32 len = voice->stream_sync((nBurnSoundLen * nBurnFPS) / 100); + if (len > (UINT32)nBurnSoundLen) len = nBurnSoundLen; + UINT32 pos = voice->streampos; + + if (pos >= len) return; + + len -= pos; + voice->streampos = pos + len; + + if (pos == 0) { + memset (stream[chip], 0, nBurnSoundLen * sizeof(INT16)); + } + + { + INT16 *buffer = stream[chip]; + buffer += pos; + + if(voice->signal) + { + INT32 i = 0; + + INT32 volval = ((voice->signal * 16) * voice->volume) / 100; + INT16 val = volval; + while (len) + { + buffer[i] = val; + len--; i++; + } + } else { + memset (buffer, 0, sizeof(INT16) * len); + } + } +} + +static void MSM5205_vclk_callback(INT32 chip) +{ + voice = &chips[chip]; + + if(voice->vclk_callback)(*voice->vclk_callback)(); + + INT32 new_signal; + + if(voice->reset) + { + new_signal = 0; + voice->step = 0; + } + else + { + INT32 val = voice->data; + new_signal = voice->signal + voice->diff_lookup[voice->step * 16 + (val & 15)]; + if (new_signal > 2047) new_signal = 2047; + else if (new_signal < -2048) new_signal = -2048; + voice->step += index_shift[val & 7]; + if (voice->step > 48) voice->step = 48; + else if (voice->step < 0) voice->step = 0; + } + /* update when signal changed */ + if( voice->signal != new_signal) + { + MSM5205StreamUpdate(chip); + voice->signal = new_signal; + } +} + +void MSM5205Render(INT32 chip, INT16 *buffer, INT32 len) +{ + voice = &chips[chip]; + INT16 *source = stream[chip]; + + MSM5205StreamUpdate(chip); + + voice->streampos = 0; + + if (voice->bAdd) { + for (INT32 i = 0; i < len; i++) + { + INT32 nSample0 = buffer[0] + source[i]; + INT32 nSample1 = buffer[1] + source[i]; + + if (nSample0 < -32768) { + nSample0 = -32768; + } else { + if (nSample0 > 32767) { + nSample0 = 32767; + } + } + + if (nSample1 < -32768) { + nSample1 = -32768; + } else { + if (nSample1 > 32767) { + nSample1 = 32767; + } + } + + buffer[0] = nSample0; + buffer[1] = nSample1; + buffer += 2; + } + } else { + for (INT32 i = 0; i < len; i++) + { + buffer[0] = buffer[1] = source[i]; + buffer+=2; + } + } +} + +void MSM5205Reset() +{ + for (INT32 chip = 0; chip < MAX_MSM5205; chip++) + { + voice = &chips[chip]; + + if (stream[chip] == NULL) continue; + + voice->data = 0; + voice->vclk = 0; + voice->reset = 0; + voice->signal = 0; + voice->step = 0; + + MSM5205_playmode(chip,voice->select); + voice->streampos = 0; + } +} + +void MSM5205Init(INT32 chip, INT32 (*stream_sync)(INT32), INT32 clock, void (*vclk_callback)(), INT32 select, INT32 volume, INT32 bAdd) +{ + voice = &chips[chip]; + + memset (voice, 0, sizeof(_MSM5205_state)); + + voice->stream_sync = stream_sync; + voice->vclk_callback = vclk_callback; + voice->select = select; + voice->clock = clock; + voice->bAdd = bAdd; + voice->volume = volume; + + float FPSRatio = (float)(6000 - nBurnFPS) / 6000; + INT32 nSoundLen = nBurnSoundLen + (INT32)((float)nBurnSoundLen * FPSRatio) + 1; + stream[chip] = (INT16*)malloc(nSoundLen * sizeof(INT16)); + + ComputeTables (chip); +} + +void MSM5205Exit() +{ + for (INT32 chip = 0; chip < MAX_MSM5205; chip++) + { + voice = &chips[chip]; + + if (stream[chip] == NULL) continue; + + memset (voice, 0, sizeof(_MSM5205_state)); + + if (stream[chip]) { + free (stream[chip]); + stream[chip] = NULL; + } + } +} + +void MSM5205VCLKWrite(INT32 chip, INT32 vclk) +{ + voice = &chips[chip]; + + if (voice->prescaler == 0) + { + if( voice->vclk != vclk) + { + voice->vclk = vclk; + if( !vclk ) MSM5205_vclk_callback(chip); + } + } +} + +void MSM5205ResetWrite(INT32 chip, INT32 reset) +{ + voice = &chips[chip]; + voice->reset = reset; +} + +void MSM5205DataWrite(INT32 chip, INT32 data) +{ + voice = &chips[chip]; + + if( voice->bitwidth == 4) + voice->data = data & 0x0f; + else + voice->data = (data & 0x07)<<1; +} + +void MSM5205PlaymodeWrite(INT32 chip, INT32 select) +{ + voice = &chips[chip]; + MSM5205_playmode(chip,select); +} + +void MSM5205SetVolume(INT32 chip, INT32 volume) +{ + voice = &chips[chip]; + voice->volume = volume; +} + +void MSM5205Update() +{ + for (INT32 chip = 0; chip < MAX_MSM5205; chip++) + { + voice = &chips[chip]; + + if (voice->prescaler) { + MSM5205_vclk_callback(chip); + } else { + if (stream[chip]) { + MSM5205StreamUpdate(chip); + } + } + } +} + +// see MSM5205_playmode for a more in-depth explanation of this +INT32 MSM5205CalcInterleave(INT32 chip, INT32 cpu_speed) +{ + static const INT32 table[4] = {96, 48, 64, 0}; + + voice = &chips[chip]; + + if ((voice->select & 3) == 3) { + return 133; // (usually...) + } + + INT32 ret = cpu_speed / (cpu_speed / (voice->clock / table[voice->select & 3])); + + return ret / (nBurnFPS / 100); +} + +void MSM5205Scan(INT32 nAction, INT32 *pnMin) +{ + if (pnMin != NULL) { + *pnMin = 0x029708; + } + + if (nAction & ACB_DRIVER_DATA) { + for (INT32 chip = 0; chip < MAX_MSM5205; chip++) { + voice = &chips[chip]; + + SCAN_VAR(voice->data); + + SCAN_VAR(voice->vclk); + SCAN_VAR(voice->reset); + SCAN_VAR(voice->prescaler); + SCAN_VAR(voice->bitwidth); + SCAN_VAR(voice->signal); + SCAN_VAR(voice->step); + SCAN_VAR(voice->volume); + } + } +} diff --git a/src/burn/sound/msm5205.h b/src/burn/sound/msm5205.h new file mode 100644 index 00000000..63d02e9c --- /dev/null +++ b/src/burn/sound/msm5205.h @@ -0,0 +1,40 @@ + +#define MSM5205_S96_3B 0 /* prescaler 1/96(4KHz) , data 3bit */ +#define MSM5205_S48_3B 1 /* prescaler 1/48(8KHz) , data 3bit */ +#define MSM5205_S64_3B 2 /* prescaler 1/64(6KHz) , data 3bit */ +#define MSM5205_SEX_3B 3 /* VCLK slave mode , data 3bit */ + +#define MSM5205_S96_4B 4 /* prescaler 1/96(4KHz) , data 4bit */ +#define MSM5205_S48_4B 5 /* prescaler 1/48(8KHz) , data 4bit */ +#define MSM5205_S64_4B 6 /* prescaler 1/64(6KHz) , data 4bit */ +#define MSM5205_SEX_4B 7 /* VCLK slave mode , data 4bit */ + +void MSM5205ResetWrite(INT32 chip, INT32 reset); +void MSM5205DataWrite(INT32 chip, INT32 data); +void MSM5205VCLKWrite(INT32 chip, INT32 reset); +void MSM5205PlaymodeWrite(INT32 chip, INT32 select); + +void MSM5205SetVolume(INT32 chip, INT32 volume); + +void MSM5205Init(INT32 chip, INT32 (*stream_sync)(INT32), INT32 clock, void (*vclk_callback)(), INT32 select, INT32 volume, INT32 bAdd); +void MSM5205Reset(); + +/* + All MSM5205 sounds need to be rendered in one call + or the data will likely be output badly +*/ + +void MSM5205Render(INT32 chip, INT16 *buffer, INT32 len); +void MSM5205Exit(); + +void MSM5205Scan(INT32 nAction, INT32 *pnMin); + +/* + MSM5205CalcInterleave is used to calculate after how + many cycles that the sound cpu has ran does + MSM5205Update need to be called. It returns how many + slices must be made of the sound cpu's cycles +*/ + +INT32 MSM5205CalcInterleave(INT32 chip, INT32 cpu_speed); +void MSM5205Update(); diff --git a/src/burn/sound/msm6295.cpp b/src/burn/sound/msm6295.cpp new file mode 100644 index 00000000..5d32287f --- /dev/null +++ b/src/burn/sound/msm6295.cpp @@ -0,0 +1,470 @@ +#include +#include "burnint.h" +#include "msm6295.h" +#include "burn_sound.h" + +UINT8* MSM6295ROM; +UINT8* MSM6295SampleInfo[MAX_MSM6295][4]; +UINT8* MSM6295SampleData[MAX_MSM6295][4]; + +UINT32 nMSM6295Status[MAX_MSM6295]; + +struct MSM6295ChannelInfo { + INT32 nOutput; + INT32 nVolume; + INT32 nPosition; + INT32 nSampleCount; + INT32 nSample; + INT32 nStep; + INT32 nDelta; + + INT32 nBufPos; +}; + +static struct { + INT32 nVolume; + INT32 nSampleRate; + INT32 nSampleSize; + INT32 nFractionalPosition; + + // All current settings for each channel + MSM6295ChannelInfo ChannelInfo[4]; + + // Used for sending commands + bool bIsCommand; + INT32 nSampleInfo; + +} MSM6295[MAX_MSM6295]; + +static UINT32 MSM6295VolumeTable[16]; +static INT32 MSM6295DeltaTable[49 * 16]; +static INT32 MSM6295StepShift[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + +static INT32* MSM6295ChannelData[MAX_MSM6295][4]; + +static INT32* pBuffer = NULL; +static INT32 nLastChip; + +static bool bAdd; + +void MSM6295Reset(INT32 nChip) +{ + nMSM6295Status[nChip] = 0; + MSM6295[nChip].bIsCommand = false; + + MSM6295[nChip].nFractionalPosition = 0; + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + // Set initial bank information + MSM6295SampleInfo[nChip][nChannel] = MSM6295ROM + (nChip * 0x0100000) + (nChannel << 8); + MSM6295SampleData[nChip][nChannel] = MSM6295ROM + (nChip * 0x0100000) + (nChannel << 16); + + memset(MSM6295ChannelData[nChip][nChannel], 0, 0x1000 * sizeof(INT32)); + MSM6295[nChip].ChannelInfo[nChannel].nBufPos = 4; + } +} + +INT32 MSM6295Scan(INT32 nChip, INT32 /*nAction*/) +{ + INT32 nSampleSize = MSM6295[nChip].nSampleSize; + SCAN_VAR(MSM6295[nChip]); + MSM6295[nChip].nSampleSize = nSampleSize; + + SCAN_VAR(nMSM6295Status[nChip]); + + for (INT32 i = 0; i < 4; i++) { + MSM6295SampleInfo[nChip][i] -= (uintptr_t)MSM6295ROM; + SCAN_VAR(MSM6295SampleInfo[nChip][i]); + MSM6295SampleInfo[nChip][i] += (uintptr_t)MSM6295ROM; + + MSM6295SampleData[nChip][i] -= (uintptr_t)MSM6295ROM; + SCAN_VAR(MSM6295SampleData[nChip][i]); + MSM6295SampleData[nChip][i] += (uintptr_t)MSM6295ROM; + } + + return 0; +} + +static void MSM6295Render_Linear(INT32 nChip, INT32* pBuf, INT32 nSegmentLength) +{ + static INT32 nPreviousSample[MAX_MSM6295], nCurrentSample[MAX_MSM6295]; + INT32 nVolume = MSM6295[nChip].nVolume; + INT32 nFractionalPosition = MSM6295[nChip].nFractionalPosition; + + INT32 nChannel, nDelta, nSample; + MSM6295ChannelInfo* pChannelInfo; + + while (nSegmentLength--) { + if (nFractionalPosition >= 0x1000) { + + nPreviousSample[nChip] = nCurrentSample[nChip]; + + do { + nCurrentSample[nChip] = 0; + + for (nChannel = 0; nChannel < 4; nChannel++) { + if (nMSM6295Status[nChip] & (1 << nChannel)) { + pChannelInfo = &MSM6295[nChip].ChannelInfo[nChannel]; + + // Check for end of sample + if (pChannelInfo->nSampleCount-- == 0) { + nMSM6295Status[nChip] &= ~(1 << nChannel); + continue; + } + + // Get new delta from ROM + if (pChannelInfo->nPosition & 1) { + nDelta = pChannelInfo->nDelta & 0x0F; + } else { + pChannelInfo->nDelta = MSM6295SampleData[nChip][(pChannelInfo->nPosition >> 17) & 3][(pChannelInfo->nPosition >> 1) & 0xFFFF]; + nDelta = pChannelInfo->nDelta >> 4; + } + + // Compute new sample + nSample = pChannelInfo->nSample + MSM6295DeltaTable[(pChannelInfo->nStep << 4) + nDelta]; + if (nSample > 2047) { + nSample = 2047; + } else { + if (nSample < -2048) { + nSample = -2048; + } + } + pChannelInfo->nSample = nSample; + pChannelInfo->nOutput = (nSample * pChannelInfo->nVolume); + + // Update step value + pChannelInfo->nStep = pChannelInfo->nStep + MSM6295StepShift[nDelta & 7]; + if (pChannelInfo->nStep > 48) { + pChannelInfo->nStep = 48; + } else { + if (pChannelInfo->nStep < 0) { + pChannelInfo->nStep = 0; + } + } + + nCurrentSample[nChip] += pChannelInfo->nOutput / 16; + + // Advance sample position + pChannelInfo->nPosition++; + } + } + + nFractionalPosition -= 0x1000; + + } while (nFractionalPosition >= 0x1000); + } + + // Compute linearly interpolated sample + nSample = nPreviousSample[nChip] + (((nCurrentSample[nChip] - nPreviousSample[nChip]) * nFractionalPosition) >> 12); + + // Scale all 4 channels + nSample *= nVolume; + + *pBuf++ += nSample; + + nFractionalPosition += MSM6295[nChip].nSampleSize; + } + + MSM6295[nChip].nFractionalPosition = nFractionalPosition; +} + +static void MSM6295Render_Cubic(INT32 nChip, INT32* pBuf, INT32 nSegmentLength) +{ + INT32 nVolume = MSM6295[nChip].nVolume; + INT32 nFractionalPosition; + + INT32 nChannel, nDelta, nSample, nOutput; + MSM6295ChannelInfo* pChannelInfo; + + while (nSegmentLength--) { + + nOutput = 0; + + for (nChannel = 0; nChannel < 4; nChannel++) { + pChannelInfo = &MSM6295[nChip].ChannelInfo[nChannel]; + nFractionalPosition = MSM6295[nChip].nFractionalPosition; + + if (nMSM6295Status[nChip] & (1 << nChannel)) { + + while (nFractionalPosition >= 0x1000) { + + // Check for end of sample + if (pChannelInfo->nSampleCount-- <= 0) { + if (pChannelInfo->nSampleCount <= -2) { + nMSM6295Status[nChip] &= ~(1 << nChannel); + } + + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos++] = pChannelInfo->nOutput / 16; + + break; + + } else { + // Get new delta from ROM + if (pChannelInfo->nPosition & 1) { + nDelta = pChannelInfo->nDelta & 0x0F; + } else { + pChannelInfo->nDelta = MSM6295SampleData[nChip][pChannelInfo->nPosition >> 17][(pChannelInfo->nPosition >> 1) & 0xFFFF]; + nDelta = pChannelInfo->nDelta >> 4; + } + + // Compute new sample + nSample = pChannelInfo->nSample + MSM6295DeltaTable[(pChannelInfo->nStep << 4) + nDelta]; + if (nSample > 2047) { + nSample = 2047; + } else { + if (nSample < -2048) { + nSample = -2048; + } + } + pChannelInfo->nSample = nSample; + pChannelInfo->nOutput = nSample * pChannelInfo->nVolume; + + // Update step value + pChannelInfo->nStep = pChannelInfo->nStep + MSM6295StepShift[nDelta & 7]; + if (pChannelInfo->nStep > 48) { + pChannelInfo->nStep = 48; + } else { + if (pChannelInfo->nStep < 0) { + pChannelInfo->nStep = 0; + } + } + + // The interpolator needs a 16-bit sample, pChannelInfo->nOutput is now a 20-bit number + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos++] = pChannelInfo->nOutput / 16; + + // Advance sample position + pChannelInfo->nPosition++; + nFractionalPosition -= 0x1000; + } + } + + if (pChannelInfo->nBufPos > 0x0FF0) { + MSM6295ChannelData[nChip][nChannel][0] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 4]; + MSM6295ChannelData[nChip][nChannel][1] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 3]; + MSM6295ChannelData[nChip][nChannel][2] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 2]; + MSM6295ChannelData[nChip][nChannel][3] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 1]; + pChannelInfo->nBufPos = 4; + } + + nOutput += INTERPOLATE4PS_16BIT(nFractionalPosition, + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 4], + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 3], + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 2], + MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 1]); + } else { + // Ramp channel output to 0 + if (pChannelInfo->nOutput != 0) { + INT32 nRamp = 2048 * 256 * 256 / nBurnSoundRate; + if (pChannelInfo->nOutput > 0) { + if (pChannelInfo->nOutput > nRamp) { + pChannelInfo->nOutput -= nRamp; + } else { + pChannelInfo->nOutput = 0; + } + } else { + if (pChannelInfo->nOutput < -nRamp) { + pChannelInfo->nOutput += nRamp; + } else { + pChannelInfo->nOutput = 0; + } + } + nOutput += pChannelInfo->nOutput / 16; + } + } + } + + nOutput *= nVolume; + + *pBuf++ += nOutput; + + MSM6295[nChip].nFractionalPosition = (MSM6295[nChip].nFractionalPosition & 0x0FFF) + MSM6295[nChip].nSampleSize; + } +} + +INT32 MSM6295Render(INT32 nChip, INT16* pSoundBuf, INT32 nSegmentLength) +{ + if (nChip == 0) { + memset(pBuffer, 0, nSegmentLength * sizeof(INT32)); + } + + if (nInterpolation >= 3) { + MSM6295Render_Cubic(nChip, pBuffer, nSegmentLength); + } else { + MSM6295Render_Linear(nChip, pBuffer, nSegmentLength); + } + + if (nChip == nLastChip) { + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + if (bAdd) { + BurnSoundCopyClamp_Mono_Add_A(pBuffer, pSoundBuf, nSegmentLength); + } else { + BurnSoundCopyClamp_Mono_A(pBuffer, pSoundBuf, nSegmentLength); + } +#endif + } else { + if (bAdd) { + BurnSoundCopyClamp_Mono_Add_C(pBuffer, pSoundBuf, nSegmentLength); + } else { + BurnSoundCopyClamp_Mono_C(pBuffer, pSoundBuf, nSegmentLength); + } + } + } + + return 0; +} + +void MSM6295Command(INT32 nChip, UINT8 nCommand) +{ + if (MSM6295[nChip].bIsCommand) { + // Process second half of command + INT32 nChannel, nSampleStart, nSampleCount; + INT32 nVolume = nCommand & 0x0F; + nCommand >>= 4; + + MSM6295[nChip].bIsCommand = false; + + for (nChannel = 0; nChannel < 4; nChannel++) { + if (nCommand & (0x01 << nChannel)) { + INT32 nBank = (MSM6295[nChip].nSampleInfo & 0x0300) >> 8; + MSM6295[nChip].nSampleInfo &= 0xFF; + + nSampleStart = MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 0]; + nSampleStart <<= 8; + nSampleStart |= MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 1]; + nSampleStart <<= 8; + nSampleStart |= MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 2]; + nSampleStart <<= 1; + + nSampleCount = MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 3]; + nSampleCount <<= 8; + nSampleCount |= MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 4]; + nSampleCount <<= 8; + nSampleCount |= MSM6295SampleInfo[nChip][nBank][MSM6295[nChip].nSampleInfo + 5]; + nSampleCount <<= 1; + + if (nSampleCount < 0x80000) { + nSampleCount -= nSampleStart; + + // Start playing channel + MSM6295[nChip].ChannelInfo[nChannel].nVolume = MSM6295VolumeTable[nVolume]; + MSM6295[nChip].ChannelInfo[nChannel].nPosition = nSampleStart; + MSM6295[nChip].ChannelInfo[nChannel].nSampleCount = nSampleCount; + MSM6295[nChip].ChannelInfo[nChannel].nStep = 0; + MSM6295[nChip].ChannelInfo[nChannel].nSample = -1; + + MSM6295[nChip].ChannelInfo[nChannel].nOutput = 0; + + nMSM6295Status[nChip] |= nCommand; + + if (nInterpolation >= 3) { + MSM6295ChannelData[nChip][nChannel][0] = 0; + MSM6295ChannelData[nChip][nChannel][1] = 0; + MSM6295ChannelData[nChip][nChannel][2] = 0; + MSM6295ChannelData[nChip][nChannel][3] = 0; + MSM6295[nChip].ChannelInfo[nChannel].nBufPos = 4; + } + } + } + } + + } else { + // Process command + if (nCommand & 0x80) { + MSM6295[nChip].nSampleInfo = (nCommand & 0x7F) << 3; + MSM6295[nChip].bIsCommand = true; + } else { + // Stop playing samples + nCommand >>= 3; + nMSM6295Status[nChip] &= ~nCommand; + } + } +} + +void MSM6295Exit(INT32 nChip) +{ + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + if (MSM6295ChannelData[nChip][nChannel]) { + free(MSM6295ChannelData[nChip][nChannel]); + MSM6295ChannelData[nChip][nChannel] = NULL; + } + } +} + +INT32 MSM6295Init(INT32 nChip, INT32 nSamplerate, float fMaxVolume, bool bAddSignal) +{ + if (nBurnSoundRate > 0) { + if (pBuffer == NULL) { + pBuffer = (INT32*)malloc(nBurnSoundRate * sizeof(INT32)); + } + } + + bAdd = bAddSignal; + + // Convert volume from percentage + MSM6295[nChip].nVolume = INT32(fMaxVolume * 256.0 / 100.0 + 0.5); + + MSM6295[nChip].nSampleRate = nSamplerate; + if (nBurnSoundRate > 0) { + MSM6295[nChip].nSampleSize = (nSamplerate << 12) / nBurnSoundRate; + } else { + MSM6295[nChip].nSampleSize = (nSamplerate << 12) / 11025; + } + + MSM6295[nChip].nFractionalPosition = 0; + + nMSM6295Status[nChip] = 0; + MSM6295[nChip].bIsCommand = false; + + if (nChip == 0) { + nLastChip = 0; + } else { + if (nLastChip < nChip) { + nLastChip = nChip; + } + } + + // Compute sample deltas + for (INT32 i = 0; i < 49; i++) { + INT32 nStep = (INT32)(pow(1.1, (double)i) * 16.0); + for (INT32 n = 0; n < 16; n++) { + INT32 nDelta = nStep >> 3; + if (n & 1) { + nDelta += nStep >> 2; + } + if (n & 2) { + nDelta += nStep >> 1; + } + if (n & 4) { + nDelta += nStep; + } + if (n & 8) { + nDelta = -nDelta; + } + MSM6295DeltaTable[(i << 4) + n] = nDelta; + } + } + + // Compute volume levels + for (INT32 i = 0; i < 16; i++) { + double nVolume = 256.0; + for (INT32 n = i; n > 0; n--) { + nVolume /= 1.412537545; + } + MSM6295VolumeTable[i] = (UINT32)(nVolume + 0.5); + } + + for (INT32 nChannel = 0; nChannel < 4; nChannel++) { + MSM6295ChannelData[nChip][nChannel] = (INT32*)malloc(0x1000 * sizeof(INT32)); + } + + MSM6295Reset(nChip); + + return 0; +} + diff --git a/src/burn/sound/msm6295.h b/src/burn/sound/msm6295.h new file mode 100644 index 00000000..e440f2d3 --- /dev/null +++ b/src/burn/sound/msm6295.h @@ -0,0 +1,23 @@ +// MSM6295 module header + +#define MAX_MSM6295 (2) + +INT32 MSM6295Init(INT32 nChip, INT32 nSamplerate, float fMaxVolume, bool bAddSignal); +void MSM6295Reset(INT32 nChip); +void MSM6295Exit(INT32 nChip); + +INT32 MSM6295Render(INT32 nChip, INT16* pSoundBuf, INT32 nSegmenLength); +void MSM6295Command(INT32 nChip, UINT8 nCommand); +INT32 MSM6295Scan(INT32 nChip, INT32 nAction); + +extern UINT8* MSM6295ROM; +extern UINT8* MSM6295SampleInfo[MAX_MSM6295][4]; +extern UINT8* MSM6295SampleData[MAX_MSM6295][4]; + +inline static UINT32 MSM6295ReadStatus(const INT32 nChip) +{ + extern UINT32 nMSM6295Status[MAX_MSM6295]; + + return nMSM6295Status[nChip]; +} + diff --git a/src/burn/sound/namco_snd.cpp b/src/burn/sound/namco_snd.cpp new file mode 100644 index 00000000..ab76fcb2 --- /dev/null +++ b/src/burn/sound/namco_snd.cpp @@ -0,0 +1,536 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "namco_snd.h" + +#define MAX_VOICES 8 +#define MAX_VOLUME 16 +#define INTERNAL_RATE 192000 +#define MIXLEVEL (1 << (16 - 4 - 4)) +#define OUTPUT_LEVEL(n) ((n) * MIXLEVEL / chip->num_voices) +#define WAVEFORM_POSITION(n) (((n) >> chip->f_fracbits) & 0x1f) + +UINT8* NamcoSoundProm = NULL; + +typedef struct +{ + UINT32 frequency; + UINT32 counter; + INT32 volume[2]; + INT32 noise_sw; + INT32 noise_state; + INT32 noise_seed; + UINT32 noise_counter; + INT32 noise_hold; + INT32 waveform_select; +} sound_channel; + +static UINT8 *namco_soundregs; +static UINT8 *namco_wavedata; + +struct namco_sound +{ + sound_channel channel_list[MAX_VOICES]; + sound_channel *last_channel; + + INT32 wave_size; + INT32 num_voices; + INT32 sound_enable; + INT32 namco_clock; + INT32 sample_rate; + INT32 f_fracbits; + INT32 stereo; + + INT16 *waveform[MAX_VOLUME]; + + INT32 update_step; +}; + +static struct namco_sound *chip = NULL; + +static void update_namco_waveform(INT32 offset, UINT8 data) +{ + if (chip->wave_size == 1) + { + INT16 wdata; + INT32 v; + + /* use full byte, first 4 high bits, then low 4 bits */ + for (v = 0; v < MAX_VOLUME; v++) + { + wdata = ((data >> 4) & 0x0f) - 8; + chip->waveform[v][offset * 2] = OUTPUT_LEVEL(wdata * v); + wdata = (data & 0x0f) - 8; + chip->waveform[v][offset * 2 + 1] = OUTPUT_LEVEL(wdata * v); + } + } + else + { + INT32 v; + + /* use only low 4 bits */ + for (v = 0; v < MAX_VOLUME; v++) + chip->waveform[v][offset] = OUTPUT_LEVEL(((data & 0x0f) - 8) * v); + } +} + +static inline UINT32 namco_update_one(INT16 *buffer, INT32 length, const INT16 *wave, UINT32 counter, UINT32 freq) +{ + while (length-- > 0) + { + *buffer++ += wave[WAVEFORM_POSITION(counter)]; + *buffer++ += wave[WAVEFORM_POSITION(counter)]; + counter += freq * chip->update_step; + } + + return counter; +} + +static inline UINT32 namco_stereo_update_one(INT16 *buffer, INT32 length, const INT16 *wave, UINT32 counter, UINT32 freq) +{ + while (length-- > 0) + { + *buffer += wave[WAVEFORM_POSITION(counter)]; + counter += freq * chip->update_step; + buffer +=2; + } + + return counter; +} + +void NamcoSoundUpdate(INT16* buffer, INT32 length) +{ + sound_channel *voice; + + /* zap the contents of the buffer */ + memset(buffer, 0, length * sizeof(*buffer) * 2); + + /* if no sound, we're done */ + if (chip->sound_enable == 0) + return; + + /* loop over each voice and add its contribution */ + for (voice = chip->channel_list; voice < chip->last_channel; voice++) + { + INT16 *mix = buffer; + INT32 v = voice->volume[0]; + + if (voice->noise_sw) + { + INT32 f = voice->frequency & 0xff; + + /* only update if we have non-zero volume and frequency */ + if (v && f) + { + INT32 hold_time = 1 << (chip->f_fracbits - 16); + INT32 hold = voice->noise_hold; + UINT32 delta = f << 4; + UINT32 c = voice->noise_counter; + INT16 noise_data = OUTPUT_LEVEL(0x07 * (v >> 1)); + INT32 i; + + /* add our contribution */ + for (i = 0; i < length; i++) + { + INT32 cnt; + + if (voice->noise_state) + *mix++ += noise_data; + else + *mix++ -= noise_data; + + if (hold) + { + hold--; + continue; + } + + hold = hold_time; + + c += delta; + cnt = (c >> 12); + c &= (1 << 12) - 1; + for( ;cnt > 0; cnt--) + { + if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1; + if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000; + voice->noise_seed >>= 1; + } + } + + /* update the counter and hold time for this voice */ + voice->noise_counter = c; + voice->noise_hold = hold; + } + } + else + { + /* only update if we have non-zero volume and frequency */ + if (v && voice->frequency) + { + const INT16 *w = &chip->waveform[v][voice->waveform_select * 32]; + + /* generate sound into buffer and update the counter for this voice */ + voice->counter = namco_update_one(mix, length, w, voice->counter, voice->frequency); + } + } + } +} + +void NamcoSoundUpdateStereo(INT16* buffer, INT32 length) +{ + sound_channel *voice; + + /* zap the contents of the buffers */ + memset(buffer, 0, length * 2 * sizeof(*buffer)); + + /* if no sound, we're done */ + if (chip->sound_enable == 0) + return; + + /* loop over each voice and add its contribution */ + for (voice = chip->channel_list; voice < chip->last_channel; voice++) + { + INT16 *lrmix = buffer; + INT32 lv = voice->volume[0]; + INT32 rv = voice->volume[1]; + + if (voice->noise_sw) + { + INT32 f = voice->frequency & 0xff; + + /* only update if we have non-zero volume and frequency */ + if ((lv || rv) && f) + { + INT32 hold_time = 1 << (chip->f_fracbits - 16); + INT32 hold = voice->noise_hold; + UINT32 delta = f << 4; + UINT32 c = voice->noise_counter; + INT16 l_noise_data = OUTPUT_LEVEL(0x07 * (lv >> 1)); + INT16 r_noise_data = OUTPUT_LEVEL(0x07 * (rv >> 1)); + INT32 i; + + /* add our contribution */ + for (i = 0; i < length; i++) + { + INT32 cnt; + + if (voice->noise_state) + { + *lrmix++ += l_noise_data; + *lrmix++ += r_noise_data; + } + else + { + *lrmix++ -= l_noise_data; + *lrmix++ -= r_noise_data; + } + + if (hold) + { + hold--; + continue; + } + + hold = hold_time; + + c += delta; + cnt = (c >> 12); + c &= (1 << 12) - 1; + for( ;cnt > 0; cnt--) + { + if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1; + if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000; + voice->noise_seed >>= 1; + } + } + + /* update the counter and hold time for this voice */ + voice->noise_counter = c; + voice->noise_hold = hold; + } + } + else + { + /* only update if we have non-zero frequency */ + if (voice->frequency) + { + /* save the counter for this voice */ + UINT32 c = voice->counter; + + /* only update if we have non-zero left volume */ + if (lv) + { + const INT16 *lw = &chip->waveform[lv][voice->waveform_select * 32]; + + /* generate sound into the buffer */ + c = namco_stereo_update_one(lrmix + 0, length, lw, voice->counter, voice->frequency); + } + + /* only update if we have non-zero right volume */ + if (rv) + { + const INT16 *rw = &chip->waveform[rv][voice->waveform_select * 32]; + + /* generate sound into the buffer */ + c = namco_stereo_update_one(lrmix + 1, length, rw, voice->counter, voice->frequency); + } + + /* update the counter for this voice */ + voice->counter = c; + } + } + } +} + +void NamcoSoundWrite(UINT32 offset, UINT8 data) +{ + sound_channel *voice; + INT32 ch; + + data &= 0x0f; + if (namco_soundregs[offset] == data) + return; + + /* set the register */ + namco_soundregs[offset] = data; + + if (offset < 0x10) + ch = (offset - 5) / 5; + else if (offset == 0x10) + ch = 0; + else + ch = (offset - 0x11) / 5; + + if (ch >= chip->num_voices) + return; + + /* recompute the voice parameters */ + voice = chip->channel_list + ch; + switch (offset - ch * 5) + { + case 0x05: + voice->waveform_select = data & 7; + break; + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + /* the frequency has 20 bits */ + /* the first voice has extra frequency bits */ + voice->frequency = (ch == 0) ? namco_soundregs[0x10] : 0; + voice->frequency += (namco_soundregs[ch * 5 + 0x11] << 4); + voice->frequency += (namco_soundregs[ch * 5 + 0x12] << 8); + voice->frequency += (namco_soundregs[ch * 5 + 0x13] << 12); + voice->frequency += (namco_soundregs[ch * 5 + 0x14] << 16); /* always 0 */ + break; + + case 0x15: + voice->volume[0] = data; + break; + } +} + +static void namcos1_sound_write(INT32 offset, INT32 data) +{ + /* verify the offset */ + if (offset > 63) + { + // logerror("NAMCOS1 sound: Attempting to write past the 64 registers segment\n"); + return; + } + + if (namco_soundregs[offset] == data) + return; + + /* set the register */ + namco_soundregs[offset] = data; + + INT32 ch = offset / 8; + if (ch >= chip->num_voices) + return; + + /* recompute the voice parameters */ + sound_channel *voice = chip->channel_list + ch; + + switch (offset - ch * 8) + { + case 0x00: + voice->volume[0] = data & 0x0f; + break; + + case 0x01: + voice->waveform_select = (data >> 4) & 15; + case 0x02: + case 0x03: + /* the frequency has 20 bits */ + voice->frequency = (namco_soundregs[ch * 8 + 0x01] & 15) << 16; /* high bits are from here */ + voice->frequency += namco_soundregs[ch * 8 + 0x02] << 8; + voice->frequency += namco_soundregs[ch * 8 + 0x03]; + break; + + case 0x04: + voice->volume[1] = data & 0x0f; + + INT32 nssw = ((data & 0x80) >> 7); + if (++voice == chip->last_channel) + voice = chip->channel_list; + voice->noise_sw = nssw; + break; + } +} + +void namcos1_custom30_write(INT32 offset, INT32 data) +{ + if (offset < 0x100) + { + if (namco_wavedata[offset] != data) + { + namco_wavedata[offset] = data; + + /* update the decoded waveform table */ + update_namco_waveform(offset, data); + } + } + else if (offset < 0x140) { + namco_wavedata[offset] = data; + namcos1_sound_write(offset - 0x100, data); + } else + namco_wavedata[offset] = data; +} + +UINT8 namcos1_custom30_read(INT32 offset) +{ + return namco_wavedata[offset]; +} + +static INT32 build_decoded_waveform() +{ + INT16 *p; + INT32 size; + INT32 offset; + INT32 v; + + if (NamcoSoundProm != NULL) + namco_wavedata = NamcoSoundProm; + + /* 20pacgal has waves in RAM but old sound system */ + if (NamcoSoundProm == NULL && chip->num_voices != 3) + { + chip->wave_size = 1; + size = 32 * 16; /* 32 samples, 16 waveforms */ + } + else + { + chip->wave_size = 0; + size = 32 * 8; /* 32 samples, 8 waveforms */ + } + + p = (INT16*)malloc(size * MAX_VOLUME * sizeof (INT16)); + + for (v = 0; v < MAX_VOLUME; v++) + { + chip->waveform[v] = p; + p += size; + } + + /* We need waveform data. It fails if region is not specified. */ + if (namco_wavedata) + { + for (offset = 0; offset < 256; offset++) + update_namco_waveform(offset, namco_wavedata[offset]); + } + + return 0; +} + +void NamcoSoundInit(INT32 clock) +{ + INT32 clock_multiple; + sound_channel *voice; + + chip = (struct namco_sound*)malloc(sizeof(*chip)); + memset(chip, 0, sizeof(*chip)); + + namco_soundregs = (UINT8*)malloc(0x40); + memset(namco_soundregs, 0, 0x40); + + chip->num_voices = 3; + chip->last_channel = chip->channel_list + chip->num_voices; + chip->stereo = 0; + + /* adjust internal clock */ + chip->namco_clock = clock; + for (clock_multiple = 0; chip->namco_clock < INTERNAL_RATE; clock_multiple++) + chip->namco_clock *= 2; + + chip->f_fracbits = clock_multiple + 15; + + /* adjust output clock */ + chip->sample_rate = chip->namco_clock; + + /* build the waveform table */ + if (build_decoded_waveform()) return; + + /* start with sound enabled, many games don't have a sound enable register */ + chip->sound_enable = 1; + + /* reset all the voices */ + for (voice = chip->channel_list; voice < chip->last_channel; voice++) + { + voice->frequency = 0; + voice->volume[0] = voice->volume[1] = 0; + voice->waveform_select = 0; + voice->counter = 0; + voice->noise_sw = 0; + voice->noise_state = 0; + voice->noise_seed = 1; + voice->noise_counter = 0; + voice->noise_hold = 0; + } + + chip->update_step = INTERNAL_RATE / nBurnSoundRate; +} + +void NamcoSoundExit() +{ + if (chip) { + free(chip); + chip = NULL; + } + + if (namco_soundregs) { + free(namco_soundregs); + namco_soundregs = NULL; + } +} + +void NamcoSoundScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return; + } + + if (pnMin != NULL) { + *pnMin = 0x029707; + } + +/* sprintf(szName, "NamcoSound"); + ba.Data = &chip; + ba.nLen = sizeof(chip); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba);*/ + + sprintf(szName, "NamcoSoundRegs"); + ba.Data = namco_soundregs; + ba.nLen = 0x40; + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); +} + diff --git a/src/burn/sound/namco_snd.h b/src/burn/sound/namco_snd.h new file mode 100644 index 00000000..482e8e5f --- /dev/null +++ b/src/burn/sound/namco_snd.h @@ -0,0 +1,10 @@ +extern UINT8* NamcoSoundProm; +void NamcoSoundUpdate(INT16* buffer, INT32 length); +void NamcoSoundUpdateStereo(INT16* buffer, INT32 length); +void NamcoSoundWrite(UINT32 offset, UINT8 data); +void NamcoSoundInit(INT32 clock); +void NamcoSoundExit(); +void NamcoSoundScan(INT32 nAction,INT32 *pnMin); + +void namcos1_custom30_write(INT32 offset, INT32 data); +UINT8 namcos1_custom30_read(INT32 offset); diff --git a/src/burn/sound/rf5c68.cpp b/src/burn/sound/rf5c68.cpp new file mode 100644 index 00000000..59d2bcb3 --- /dev/null +++ b/src/burn/sound/rf5c68.cpp @@ -0,0 +1,189 @@ +#include "burnint.h" +#include "rf5c68.h" +#include "burn_sound.h" + +#define NUM_CHANNELS (8) + +static UINT32 nUpdateStep; + +struct pcm_channel +{ + UINT8 enable; + UINT8 env; + UINT8 pan; + UINT8 start; + UINT32 addr; + UINT16 step; + UINT16 loopst; +}; + +struct rf5c68pcm +{ + struct pcm_channel chan[NUM_CHANNELS]; + UINT8 cbank; + UINT8 wbank; + UINT8 enable; + UINT8 data[0x10000]; +}; + +static struct rf5c68pcm *chip = NULL; + +static INT32 *left = NULL; +static INT32 *right = NULL; + +void RF5C68PCMUpdate(INT16* pSoundBuf, INT32 length) +{ + if (!chip->enable) return; + + INT32 i, j; + + left = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + right = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + + memset(left, 0, length * sizeof(INT32)); + memset(right, 0, length * sizeof(INT32)); + + for (i = 0; i < NUM_CHANNELS; i++) { + pcm_channel *chan = &chip->chan[i]; + + if (chan->enable) { + INT32 lv = (chan->pan & 0xf) * chan->env; + INT32 rv = ((chan->pan >> 4) & 0xf) * chan->env; + + for (j = 0; j < length; j++) { + INT32 sample; + + sample = chip->data[(chan->addr >> 11) & 0xffff]; + if (sample == 0xff) { + chan->addr = chan->loopst << 11; + sample = chip->data[(chan->addr >> 11) & 0xffff]; + if (sample == 0xff) break; + } + + chan->addr += (chan->step * nUpdateStep) >> 15;//(chan->step * 1181) / 1000; + + if (sample & 0x80) { + sample &= 0x7f; + left[j] += (sample * lv) >> 5; + right[j] += (sample * rv) >> 5; + } else { + left[j] -= (sample * lv) >> 5; + right[j] -= (sample * rv) >> 5; + } + } + } + } + + for (i = 0; i < length; i++) { + if (left[i] > 32767) left[i] = 32767; + if (left[i] < -32768) left[i] = -32768; + left[i] = left[i] & ~0x3f; + if (right[i] > 32767) right[i] = 32767; + if (right[i] < -32768) right[i] = -32768; + right[i] = right[i] & ~0x3f; + + pSoundBuf[i + 0] = left[i]; + pSoundBuf[i + 1] = right[i]; + } + + if (left) { + free(left); + left = NULL; + } + if (right) { + free(right); + right = NULL; + } +} + +void RF5C68PCMReset() +{ + memset(chip, 0, sizeof(*chip)); + memset(chip->data, 0xff, sizeof(chip->data)); +} + +void RF5C68PCMInit(INT32 clock) +{ + chip = (struct rf5c68pcm*)malloc(sizeof(struct rf5c68pcm)); + + INT32 Rate = clock / 384; + + nUpdateStep = (INT32)(((float)Rate / nBurnSoundRate) * 32768); +} + +void RF5C68PCMRegWrite(UINT8 offset, UINT8 data) +{ + struct pcm_channel *chan = &chip->chan[chip->cbank]; + INT32 i; + + /* force the stream to update first */ +// stream_update(chip->stream); + + switch (offset) { + case 0x00: { + chan->env = data; + break; + } + + case 0x01: { + chan->pan = data; + break; + } + + case 0x02: { + chan->step = (chan->step & 0xff00) | (data & 0xff); + break; + } + + case 0x03: { + chan->step = (chan->step & 0xff) | ((data << 8) & 0xff00); + break; + } + + case 0x04: { + chan->loopst = (chan->loopst & 0xff00) | (data & 0xff); + break; + } + + case 0x05: { + chan->loopst = (chan->loopst & 0xff) | ((data << 8) & 0xff00); + break; + } + + case 0x06: { + chan->start = data; + if (!chan->enable) chan->addr = chan->start << (8 + 11); + break; + } + + case 0x07: { + chip->enable = (data >> 7) & 1; + if (data & 0x40) { + chip->cbank = data & 7; + } else { + chip->wbank = data & 15; + } + break; + } + + case 0x08: { + for (i = 0; i < 8; i++) { + chip->chan[i].enable = (~data >> i) & 1; + if (!chip->chan[i].enable) chip->chan[i].addr = chip->chan[i].start << (8 + 11); + } + break; + } + } +} + +UINT8 RF5C68PCMRead(UINT16 offset) +{ + return chip->data[chip->wbank * 0x1000 + offset]; +} + +void RF5C68PCMWrite(UINT16 offset, UINT8 data) +{ + chip->data[(chip->wbank * 0x1000) + offset] = data; +} + +#undef NUM_CHANNELS diff --git a/src/burn/sound/rf5c68.h b/src/burn/sound/rf5c68.h new file mode 100644 index 00000000..0c71de55 --- /dev/null +++ b/src/burn/sound/rf5c68.h @@ -0,0 +1,6 @@ +void RF5C68PCMUpdate(INT16* pSoundBuf, INT32 length); +void RF5C68PCMReset(); +void RF5C68PCMInit(INT32 clock); +void RF5C68PCMRegWrite(UINT8 offset, UINT8 data); +UINT8 RF5C68PCMRead(UINT16 offset); +void RF5C68PCMWrite(UINT16 offset, UINT8 data); diff --git a/src/burn/sound/saa1099.cpp b/src/burn/sound/saa1099.cpp new file mode 100644 index 00000000..67a8d324 --- /dev/null +++ b/src/burn/sound/saa1099.cpp @@ -0,0 +1,447 @@ +/*************************************************************************** + + Philips SAA1099 Sound driver + + By Juergen Buchmueller and Manuel Abadia + + SAA1099 register layout: + ======================== + + offs | 7654 3210 | description + -----+-----------+--------------------------- + 0x00 | ---- xxxx | Amplitude channel 0 (left) + 0x00 | xxxx ---- | Amplitude channel 0 (right) + 0x01 | ---- xxxx | Amplitude channel 1 (left) + 0x01 | xxxx ---- | Amplitude channel 1 (right) + 0x02 | ---- xxxx | Amplitude channel 2 (left) + 0x02 | xxxx ---- | Amplitude channel 2 (right) + 0x03 | ---- xxxx | Amplitude channel 3 (left) + 0x03 | xxxx ---- | Amplitude channel 3 (right) + 0x04 | ---- xxxx | Amplitude channel 4 (left) + 0x04 | xxxx ---- | Amplitude channel 4 (right) + 0x05 | ---- xxxx | Amplitude channel 5 (left) + 0x05 | xxxx ---- | Amplitude channel 5 (right) + | | + 0x08 | xxxx xxxx | Frequency channel 0 + 0x09 | xxxx xxxx | Frequency channel 1 + 0x0a | xxxx xxxx | Frequency channel 2 + 0x0b | xxxx xxxx | Frequency channel 3 + 0x0c | xxxx xxxx | Frequency channel 4 + 0x0d | xxxx xxxx | Frequency channel 5 + | | + 0x10 | ---- -xxx | Channel 0 octave select + 0x10 | -xxx ---- | Channel 1 octave select + 0x11 | ---- -xxx | Channel 2 octave select + 0x11 | -xxx ---- | Channel 3 octave select + 0x12 | ---- -xxx | Channel 4 octave select + 0x12 | -xxx ---- | Channel 5 octave select + | | + 0x14 | ---- ---x | Channel 0 frequency enable (0 = off, 1 = on) + 0x14 | ---- --x- | Channel 1 frequency enable (0 = off, 1 = on) + 0x14 | ---- -x-- | Channel 2 frequency enable (0 = off, 1 = on) + 0x14 | ---- x--- | Channel 3 frequency enable (0 = off, 1 = on) + 0x14 | ---x ---- | Channel 4 frequency enable (0 = off, 1 = on) + 0x14 | --x- ---- | Channel 5 frequency enable (0 = off, 1 = on) + | | + 0x15 | ---- ---x | Channel 0 noise enable (0 = off, 1 = on) + 0x15 | ---- --x- | Channel 1 noise enable (0 = off, 1 = on) + 0x15 | ---- -x-- | Channel 2 noise enable (0 = off, 1 = on) + 0x15 | ---- x--- | Channel 3 noise enable (0 = off, 1 = on) + 0x15 | ---x ---- | Channel 4 noise enable (0 = off, 1 = on) + 0x15 | --x- ---- | Channel 5 noise enable (0 = off, 1 = on) + | | + 0x16 | ---- --xx | Noise generator parameters 0 + 0x16 | --xx ---- | Noise generator parameters 1 + | | + 0x18 | --xx xxxx | Envelope generator 0 parameters + 0x18 | x--- ---- | Envelope generator 0 control enable (0 = off, 1 = on) + 0x19 | --xx xxxx | Envelope generator 1 parameters + 0x19 | x--- ---- | Envelope generator 1 control enable (0 = off, 1 = on) + | | + 0x1c | ---- ---x | All channels enable (0 = off, 1 = on) + 0x1c | ---- --x- | Synch & Reset generators + +***************************************************************************/ + +#include "burnint.h" +#include "saa1099.h" + +#define LEFT 0x00 +#define RIGHT 0x01 + +/* this structure defines a channel */ +struct saa1099_channel +{ + INT32 frequency; /* frequency (0x00..0xff) */ + INT32 freq_enable; /* frequency enable */ + INT32 noise_enable; /* noise enable */ + INT32 octave; /* octave (0x00..0x07) */ + INT32 amplitude[2]; /* amplitude (0x00..0x0f) */ + INT32 envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */ + + /* vars to simulate the square wave */ + double counter; + double freq; + INT32 level; +}; + +/* this structure defines a noise channel */ +struct saa1099_noise +{ + /* vars to simulate the noise generator output */ + double counter; + double freq; + INT32 level; /* noise polynomal shifter */ +}; + +/* this structure defines a SAA1099 chip */ +struct saa1099_state +{ + INT32 noise_params[2]; /* noise generators parameters */ + INT32 env_enable[2]; /* envelope generators enable */ + INT32 env_reverse_right[2]; /* envelope reversed for right channel */ + INT32 env_mode[2]; /* envelope generators mode */ + INT32 env_bits[2]; /* non zero = 3 bits resolution */ + INT32 env_clock[2]; /* envelope clock mode (non-zero external) */ + INT32 env_step[2]; /* current envelope step */ + INT32 all_ch_enable; /* all channels enable */ + INT32 sync_state; /* sync all channels */ + INT32 selected_reg; /* selected register */ + struct saa1099_channel channels[6]; /* channels */ + struct saa1099_noise noise[2]; /* noise generators */ + double sample_rate; + INT32 bAdd; + INT32 volume; +}; + +static saa1099_state chips[2]; + +static const INT32 amplitude_lookup[16] = { + 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, + 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, + 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16, + 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16 +}; + +static const UINT8 envelope[8][64] = { + /* zero amplitude */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* maximum amplitude */ + {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, }, + /* single decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 } +}; + +static void saa1099_envelope(saa1099_state *saa, INT32 ch) +{ + if (saa->env_enable[ch]) + { + INT32 step, mode, mask; + mode = saa->env_mode[ch]; + /* step from 0..63 and then loop in steps 32..63 */ + step = saa->env_step[ch] = + ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20); + + mask = 15; + if (saa->env_bits[ch]) + mask &= ~1; /* 3 bit resolution, mask LSB */ + + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask; + if (saa->env_reverse_right[ch] & 0x01) + { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask; + } + else + { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask; + } + } + else + { + /* envelope mode off, set all envelope factors to 16 */ + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = 16; + } +} + +void saa1099Update(INT32 chip, INT16 *output, INT32 samples) +{ + saa1099_state *saa = &chips[chip]; + INT32 j, ch, vol; + + vol = saa->volume; + + /* if the channels are disabled we're done */ + if (!saa->all_ch_enable) + { + /* init output data */ + memset (output, 0, samples * sizeof(INT16) * 2); + return; + } + + for (ch = 0; ch < 2; ch++) + { + switch (saa->noise_params[ch]) + { + case 0: saa->noise[ch].freq = 31250.0 * 2; break; + case 1: saa->noise[ch].freq = 15625.0 * 2; break; + case 2: saa->noise[ch].freq = 7812.5 * 2; break; + case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; + } + } + + /* fill all data needed */ + for( j = 0; j < samples; j++, output+=2) + { + INT32 output_l = 0, output_r = 0; + + /* for each channel */ + for (ch = 0; ch < 6; ch++) + { + if (saa->channels[ch].freq == 0.0) + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); + + /* check the actual position in the square wave */ + saa->channels[ch].counter -= saa->channels[ch].freq; + + while (saa->channels[ch].counter < 0) + { + /* calculate new frequency now after the half wave is updated */ + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / + (511.0 - (double)saa->channels[ch].frequency); + + saa->channels[ch].counter += saa->sample_rate; + saa->channels[ch].level ^= 1; + + /* eventually clock the envelope counters */ + if (ch == 1 && saa->env_clock[0] == 0) + saa1099_envelope(saa, 0); + if (ch == 4 && saa->env_clock[1] == 0) + saa1099_envelope(saa, 1); + } + + /* if the noise is enabled */ + if (saa->channels[ch].noise_enable) + { + /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ + if (saa->noise[ch/3].level & 1) + { + /* subtract to avoid overflows, also use only half amplitude */ + output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; + output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; + } + } + + /* if the square wave is enabled */ + if (saa->channels[ch].freq_enable) + { + /* if the channel level is high */ + if (saa->channels[ch].level & 1) + { + output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; + output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; + } + } + } + + for (ch = 0; ch < 2; ch++) + { + /* check the actual position in noise generator */ + saa->noise[ch].counter -= saa->noise[ch].freq; + while (saa->noise[ch].counter < 0) + { + saa->noise[ch].counter += saa->sample_rate; + if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) + saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; + else + saa->noise[ch].level <<= 1; + } + } + /* write sound data to the buffer */ + output[LEFT] = ((output_l / 6) * vol) / 1000; + output[RIGHT] = ((output_r / 6) * vol) / 1000; + } +} + +void saa1099Reset(INT32 chip) +{ + saa1099_state *saa = &chips[chip]; + + double sample_rate = saa->sample_rate; + INT32 bAdd = saa->bAdd; + INT32 vol = saa->volume; + + memset (saa, 0, sizeof(saa1099_state)); + + saa->sample_rate = sample_rate; + saa->bAdd = bAdd; + saa->volume = vol; +} + +void saa1099Init(INT32 chip, INT32 clock, INT32 volume, INT32 bAdd) +{ + saa1099_state *saa = &chips[chip]; + + saa->sample_rate = clock / 256; + saa->bAdd = bAdd; + saa->volume = volume; +} + +void saa1099Exit(INT32 ) +{ + // nothing atm +} + +void saa1099ControlWrite(INT32 chip, INT32 data) +{ + saa1099_state *saa = &chips[chip]; + + saa->selected_reg = data & 0x1f; + + if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) + { + /* clock the envelope channels */ + if (saa->env_clock[0]) + saa1099_envelope(saa,0); + if (saa->env_clock[1]) + saa1099_envelope(saa,1); + } +} + +void saa1099DataWrite(INT32 chip, INT32 data) +{ + saa1099_state *saa = &chips[chip]; + INT32 reg = saa->selected_reg; + INT32 ch; + + switch (reg) + { + /* channel i amplitude */ + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: + ch = reg & 7; + saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; + saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; + break; + /* channel i frequency */ + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: + ch = reg & 7; + saa->channels[ch].frequency = data & 0xff; + break; + /* channel i octave */ + case 0x10: case 0x11: case 0x12: + ch = (reg - 0x10) << 1; + saa->channels[ch + 0].octave = data & 0x07; + saa->channels[ch + 1].octave = (data >> 4) & 0x07; + break; + /* channel i frequency enable */ + case 0x14: + saa->channels[0].freq_enable = data & 0x01; + saa->channels[1].freq_enable = data & 0x02; + saa->channels[2].freq_enable = data & 0x04; + saa->channels[3].freq_enable = data & 0x08; + saa->channels[4].freq_enable = data & 0x10; + saa->channels[5].freq_enable = data & 0x20; + break; + /* channel i noise enable */ + case 0x15: + saa->channels[0].noise_enable = data & 0x01; + saa->channels[1].noise_enable = data & 0x02; + saa->channels[2].noise_enable = data & 0x04; + saa->channels[3].noise_enable = data & 0x08; + saa->channels[4].noise_enable = data & 0x10; + saa->channels[5].noise_enable = data & 0x20; + break; + /* noise generators parameters */ + case 0x16: + saa->noise_params[0] = data & 0x03; + saa->noise_params[1] = (data >> 4) & 0x03; + break; + /* envelope generators parameters */ + case 0x18: case 0x19: + ch = reg - 0x18; + saa->env_reverse_right[ch] = data & 0x01; + saa->env_mode[ch] = (data >> 1) & 0x07; + saa->env_bits[ch] = data & 0x10; + saa->env_clock[ch] = data & 0x20; + saa->env_enable[ch] = data & 0x80; + /* reset the envelope */ + saa->env_step[ch] = 0; + break; + /* channels enable & reset generators */ + case 0x1c: + saa->all_ch_enable = data & 0x01; + saa->sync_state = data & 0x02; + if (data & 0x02) + { + INT32 i; + + /* Synch & Reset generators */ + for (i = 0; i < 6; i++) + { + saa->channels[i].level = 0; + saa->channels[i].counter = 0.0; + } + } + break; + default: break; /* Error! */ + } +} + +void saa1099Scan(INT32 chip, INT32 nAction) +{ + struct BurnArea ba; + saa1099_state *saa = &chips[chip]; + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = (UINT8*)saa; + ba.nLen = sizeof(saa1099_state); + ba.szName = "SAA data"; + BurnAcb(&ba); + } +} diff --git a/src/burn/sound/saa1099.h b/src/burn/sound/saa1099.h new file mode 100644 index 00000000..d6008e7d --- /dev/null +++ b/src/burn/sound/saa1099.h @@ -0,0 +1,7 @@ +void saa1099Update(INT32 chip, INT16 *output, INT32 samples); +void saa1099Reset(INT32 chip); +void saa1099Init(INT32 chip, INT32 clock, INT32 volume, INT32 bAdd); // volume of 100.0% is 1000 +void saa1099ControlWrite(INT32 chip, INT32 data); +void saa1099DataWrite(INT32 chip, INT32 data); +void saa1099Scan(INT32 chip, INT32 nAction); +void saa1099Exit(INT32 chip); diff --git a/src/burn/sound/samples.cpp b/src/burn/sound/samples.cpp new file mode 100644 index 00000000..685e6232 --- /dev/null +++ b/src/burn/sound/samples.cpp @@ -0,0 +1,374 @@ +// FB Alpha sample player module + +#include "burnint.h" +#include "direct.h" +#include "samples.h" + +#define SAMPLE_DIRECTORY szAppSamplesPath + +#define get_long() ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | (ptr[0] << 0)) +#define get_short() ((ptr[1] << 8) | (ptr[0] << 0)) + +static INT32 bAddToStream = 0; +static INT32 nTotalSamples = 0; +static INT32 nSampleSetGain = 100; + +struct sample_format +{ + UINT8 *data; + UINT32 length; + UINT32 position; + UINT8 playing; + UINT8 loop; + UINT8 flags; +}; + +static struct sample_format *samples = NULL; // store samples +static struct sample_format *sample_ptr = NULL; // generic pointer for sample + +static void make_raw(UINT8 *src, UINT32 len) +{ + UINT8 *ptr = src; + + if (ptr[0] != 'R' || ptr[1] != 'I' || ptr[2] != 'F' || ptr[3] != 'F') return; + ptr += 4; // skip RIFF + + UINT32 length = get_long(); ptr += 4; // total length of file + if (len < length) length = len - 8; // first 8 bytes (RIFF + Len) + + /* "WAVEfmt " */ ptr += 8; // WAVEfmt + 1 space + UINT32 length2 = get_long(); ptr += 4; // Wavefmt length +/* unsigned short format = get_short(); */ptr += 2; // format? + UINT16 channels = get_short(); ptr += 2; // channels + UINT32 sample_rate = get_long(); ptr += 4; // sample rate +/* unsigned int speed = get_long(); */ptr += 4; // speed - should equal (bits * channels * sample_rate) +/* unsigned short align = get_short(); */ptr += 2; // block align should be ((bits / 8) * channels) + UINT16 bits = get_short() / 8; ptr += 2; // bits per sample (0010) + ptr += length2 - 16; // get past the wave format chunk + + // are we in the 'data' chunk? if not, skip this chunk. + if (ptr[0] != 'd' || ptr[1] != 'a' || ptr[2] != 't' || ptr[3] != 'a') { + ptr += 4; // skip tag + + UINT32 length3 = get_long(); ptr += 4; + ptr += length3; + } + + /* "data" */ ptr += 4; // "data" + UINT32 data_length = get_long(); ptr += 4; // should be up to the data... + + if ((len - (ptr - src)) < data_length) data_length = len - (ptr - src); + + UINT32 converted_len = (UINT32)((float)(data_length * (nBurnSoundRate * 1.00000 / sample_rate) / (bits * channels))); + if (converted_len == 0) return; + + sample_ptr->data = (UINT8*)malloc(converted_len * 4); + + // up/down sample everything and convert to raw 16 bit stereo + { + INT16 *data = (INT16*)sample_ptr->data; + INT16 *poin = (INT16*)ptr; + UINT8 *poib = ptr; + + for (UINT32 i = 0; i < converted_len; i++) + { + UINT32 x = (UINT32)((float)(i * (sample_rate * 1.00000 / nBurnSoundRate))); + + if (bits == 2) { // signed 16 bit, stereo & mono + data[i * 2 + 0] = poin[x * channels + 0 ]; + data[i * 2 + 1] = poin[x * channels + (channels / 2)]; + } + + if (bits == 1) { // unsigned 8 bit, stereo & mono + data[i * 2 + 0] = (poib[x * channels + 0 ] - 128) << 8; + data[i * 2 + 1] = (poib[x * channels + (channels / 2)] - 128) << 8; + } + } + + // now go through and set the gain + for (UINT32 i = 0; i < converted_len * 2; i++) + { + INT32 d = (data[i] * nSampleSetGain) / 100; + if (d > 0x7fff) d = 0x7fff; + if (d < -0x7fff) d = -0x7fff; + data[i] = (INT16)d; + } + } + + sample_ptr->length = converted_len; + sample_ptr->playing = 0; + sample_ptr->position = 0; +} + +void BurnSamplePlay(INT32 sample) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + + if (sample_ptr->flags & SAMPLE_IGNORE) return; + + sample_ptr->playing = 1; + sample_ptr->position = 0; +} + +void BurnSamplePause(INT32 sample) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + sample_ptr->playing = 0; +} + +void BurnSampleResume(INT32 sample) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + sample_ptr->playing = 1; +} + +void BurnSampleStop(INT32 sample) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + sample_ptr->playing = 0; + sample_ptr->position = 0; +} + +void BurnSampleSetLoop(INT32 sample, bool dothis) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + + if (sample_ptr->flags & SAMPLE_NOLOOP) return; + + sample_ptr->loop = (dothis ? 1 : 0); +} + +INT32 BurnSampleGetStatus(INT32 sample) +{ + if (sample >= nTotalSamples) return -1; + + sample_ptr = &samples[sample]; + return (sample_ptr->playing); +} + +INT32 BurnSampleGetPosition(INT32 sample) +{ + if (sample >= nTotalSamples) return -1; + + sample_ptr = &samples[sample]; + return (sample_ptr->position); +} + +void BurnSampleSetPosition(INT32 sample, UINT32 position) +{ + if (sample >= nTotalSamples) return; + + sample_ptr = &samples[sample]; + sample_ptr->position = position; +} + +void BurnSampleReset() +{ + for (INT32 i = 0; i < nTotalSamples; i++) { + BurnSampleStop(i); + + if (sample_ptr->flags & SAMPLE_AUTOLOOP) { + BurnSampleSetLoop(i, true); + BurnSamplePlay(i); + } + } +} + +extern INT32 __cdecl ZipLoadOneFile(const char* arcName, const char* fileName, void** Dest, INT32* pnWrote); +char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, INT32 nOutSize); +#define _TtoA(a) TCHARToANSI(a, NULL, 0) + +void BurnSampleInit(INT32 nGain /*volume percentage!*/, INT32 bAdd /*add sample to stream?*/) +{ + if (nBurnSoundRate == 0) { + nTotalSamples = 0; + return; + } + + INT32 length; + char path[256]; + char setname[128]; + void *destination = NULL; + char szTempPath[MAX_PATH]; + sprintf(szTempPath, _TtoA(SAMPLE_DIRECTORY)); + + strcpy(setname, BurnDrvGetTextA(DRV_SAMPLENAME)); + sprintf(path, "%s%s.zip", szTempPath, setname); + + FILE *test = fopen(path, "rb"); + if (!test) return; + fclose(test); + + bAddToStream = bAdd; + nSampleSetGain = nGain; + nTotalSamples = 0; + + struct BurnSampleInfo si; + INT32 nSampleOffset = -1; + do { + BurnDrvGetSampleInfo(&si, ++nSampleOffset); + if (si.nFlags) nTotalSamples++; + } while (si.nFlags); + + samples = (sample_format*)malloc(sizeof(sample_format) * nTotalSamples); + memset (samples, 0, sizeof(sample_format) * nTotalSamples); + + for (INT32 i = 0; i < nTotalSamples; i++) { + BurnDrvGetSampleInfo(&si, i); + char *szSampleName = NULL; + BurnDrvGetSampleName(&szSampleName, i, 0); + sample_ptr = &samples[i]; + + if (si.nFlags == 0) break; + + sprintf (path, "%s%s.zip", szTempPath, setname); + + destination = NULL; + length = 0; + ZipLoadOneFile((const char*)path, (const char*)szSampleName, &destination, &length); + + if (length) { + make_raw((UINT8*)destination, length); + + sample_ptr->flags = si.nFlags; + } else { + sample_ptr->flags = SAMPLE_IGNORE; + } + + if (destination) { + free (destination); + destination = NULL; + } + } +} + +void BurnSampleExit() +{ + for (INT32 i = 0; i < nTotalSamples; i++) { + sample_ptr = &samples[i]; + if (sample_ptr->data != NULL) { + free (sample_ptr->data); + sample_ptr->data = NULL; + } + } + + if (samples) { + free (samples); + samples = NULL; + } + + sample_ptr = NULL; + nTotalSamples = 0; + bAddToStream = 0; + nSampleSetGain = 100; +} + +void BurnSampleRender(INT16 *pDest, UINT32 pLen) +{ + if (pBurnSoundOut == NULL) return; + + INT32 nFirstSample = 0; + UINT32 *dest = (UINT32*)pDest; + + for (INT32 i = 0; i < nTotalSamples; i++) + { + sample_ptr = &samples[i]; + if (sample_ptr->playing == 0) continue; + + INT32 playlen = pLen; + INT32 loop = sample_ptr->loop; + INT32 length = sample_ptr->length; + INT32 position = sample_ptr->position; + + UINT32 *data = (UINT32*)sample_ptr->data; + + if (loop) { + if (bAddToStream == 0 && nFirstSample == 0) { + for (INT32 j = 0; j < playlen; j++, position++) { + dest[j] = data[position % length]; + } + } else { + position *= 2; + length *= 2; + INT16 *dst = (INT16*)dest; + INT16 *dat = (INT16*)data; + + for (INT32 j = 0; j < playlen; j++, position+=2, dst += 2) { + INT32 t0 = dst[0] + dat[(position + 0) % length]; + INT32 t1 = dst[1] + dat[(position + 1) % length]; + + if (t0 > 0x7fff) t0 = 0x7fff; + if (t1 > 0x7fff) t1 = 0x7fff; + if (t0 < -0x7fff) t0 = -0x7fff; + if (t1 < -0x7fff) t1 = -0x7fff; + dst[0] = t0; + dst[1] = t1; + } + } + } else { + length = length - position; + + if (length <= 0) { + if (loop == 0) { + sample_ptr->playing = 0; + continue; + } + } + + data += position; + if (playlen > length) playlen = length; + + if (bAddToStream == 0 && nFirstSample == 0) { + for (INT32 j = 0; j < playlen; j++) { + dest[j] = data[j]; + } + } else { + INT16 *dst = (INT16*)dest; + INT16 *dat = (INT16*)data; + + for (INT32 j = 0; j < playlen; j++, dst +=2, dat+=2) { + INT32 t0 = dst[0] + dat[0]; + INT32 t1 = dst[1] + dat[1]; + + if (t0 > 0x7fff) t0 = 0x7fff; + if (t1 > 0x7fff) t1 = 0x7fff; + if (t0 < -0x7fff) t0 = -0x7fff; + if (t1 < -0x7fff) t1 = -0x7fff; + dst[0] = t0; + dst[1] = t1; + } + } + } + + sample_ptr->position += playlen; + nFirstSample++; + } +} + +INT32 BurnSampleScan(INT32 nAction, INT32 *pnMin) +{ + if (pnMin != NULL) { + *pnMin = 0x029707; + } + + if (nAction & ACB_DRIVER_DATA) { + for (INT32 i = 0; i < nTotalSamples; i++) { + sample_ptr = &samples[i]; + SCAN_VAR(sample_ptr->playing); + SCAN_VAR(sample_ptr->loop); + SCAN_VAR(sample_ptr->position); + } + } + + return 0; +} diff --git a/src/burn/sound/samples.h b/src/burn/sound/samples.h new file mode 100644 index 00000000..b808ee48 --- /dev/null +++ b/src/burn/sound/samples.h @@ -0,0 +1,24 @@ +#define SAMPLE_IGNORE 0x01 // don't ever play this sample +#define SAMPLE_AUTOLOOP 0x02 // start the looping on start +#define SAMPLE_NOLOOP 0x04 // don't allow this to loop + +void BurnSamplePlay(INT32 sample); +void BurnSamplePause(INT32 sample); +void BurnSampleResume(INT32 sample); +void BurnSampleStop(INT32 sample); + +void BurnSampleSetLoop(INT32 sample, bool dothis); + +INT32 BurnSampleGetStatus(INT32 sample); + +INT32 BurnSampleGetPosition(INT32 sample); +void BurnSampleSetPosition(INT32 sample, UINT32 position); + +void BurnSampleReset(); + +void BurnSampleInit(INT32 nGain, INT32 bAdd); + +INT32 BurnSampleScan(INT32 nAction, INT32 *pnMin); + +void BurnSampleRender(INT16 *pDest, UINT32 pLen); +void BurnSampleExit(); diff --git a/src/burn/sound/segapcm.cpp b/src/burn/sound/segapcm.cpp new file mode 100644 index 00000000..5d54acff --- /dev/null +++ b/src/burn/sound/segapcm.cpp @@ -0,0 +1,151 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "segapcm.h" + +struct segapcm +{ + UINT8 *ram; + UINT8 low[16]; + const UINT8 *rom; + INT32 bankshift; + INT32 bankmask; + INT32 UpdateStep; +}; + +static struct segapcm *Chip = NULL; +static INT32 *Left = NULL; +static INT32 *Right = NULL; + +void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength) +{ + INT32 Channel; + + memset(Left, 0, nLength * sizeof(INT32)); + memset(Right, 0, nLength * sizeof(INT32)); + + for (Channel = 0; Channel < 16; Channel++) { + UINT8 *Regs = Chip->ram + 8 * Channel; + if (!(Regs[0x86] & 1)) { + const UINT8 *Rom = Chip->rom + ((Regs[0x86] & Chip->bankmask) << Chip->bankshift); + UINT32 Addr = (Regs[0x85] << 16) | (Regs[0x84] << 8) | Chip->low[Channel]; + UINT32 Loop = (Regs[0x05] << 16) | (Regs[0x04] << 8); + UINT8 End = Regs[6] + 1; + INT32 i; + + for (i = 0; i < nLength; i++) { + INT8 v = 0; + + if ((Addr >> 16) == End) { + if (Regs[0x86] & 2) { + Regs[0x86] |= 1; + break; + } else { + Addr = Loop; + } + } + + v = Rom[Addr >> 8] - 0x80; + + Left[i] += v * Regs[2]; + Right[i] += v * Regs[3]; + Addr = (Addr + ((Regs[7] * Chip->UpdateStep) >> 16)) & 0xffffff; + } + + Regs[0x84] = Addr >> 8; + Regs[0x85] = Addr >> 16; + Chip->low[Channel] = Regs[0x86] & 1 ? 0 : Addr; + } + } + + for (INT32 i = 0; i < nLength; i++) { + if (Left[i] > 32767) Left[i] = 32767; + if (Left[i] < -32768) Left[i] = -32768; + + if (Right[i] > 32767) Right[i] = 32767; + if (Right[i] < -32768) Right[i] = -32768; + + pSoundBuf[0] += Left[i]; + pSoundBuf[1] += Right[i]; + pSoundBuf += 2; + } +} + +void SegaPCMInit(INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize) +{ + INT32 Mask, RomMask; + + Chip = (struct segapcm*)malloc(sizeof(*Chip)); + memset(Chip, 0, sizeof(*Chip)); + + Chip->rom = pPCMData; + + Chip->ram = (UINT8*)malloc(0x800); + memset(Chip->ram, 0xff, 0x800); + + Left = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + Right = (INT32*)malloc(nBurnSoundLen * sizeof(INT32)); + + Chip->bankshift = bank; + Mask = bank >> 16; + if(!Mask) + Mask = BANK_MASK7 >> 16; + + for (RomMask = 1; RomMask < PCMDataSize; RomMask *= 2) {} + RomMask--; + + Chip->bankmask = Mask & (RomMask >> Chip->bankshift); + + double Rate = (double)clock / 128 / nBurnSoundRate; + Chip->UpdateStep = (INT32)(Rate * 0x10000); +} + +void SegaPCMExit() +{ + if (Chip) { + free(Chip); + Chip = NULL; + } + + if (Left) { + free(Left); + Left = NULL; + } + + if (Right) { + free(Right); + Right = NULL; + } +} + +INT32 SegaPCMScan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029680; + } + + sprintf(szName, "SegaPCM"); + ba.Data = &Chip; + ba.nLen = sizeof(struct segapcm); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + return 0; +} + +UINT8 SegaPCMRead(UINT32 Offset) +{ + return Chip->ram[Offset & 0x07ff]; +} + +void SegaPCMWrite(UINT32 Offset, UINT8 Data) +{ + Chip->ram[Offset & 0x07ff] = Data; +} diff --git a/src/burn/sound/segapcm.h b/src/burn/sound/segapcm.h new file mode 100644 index 00000000..985dfafc --- /dev/null +++ b/src/burn/sound/segapcm.h @@ -0,0 +1,13 @@ +#define BANK_256 (11) +#define BANK_512 (12) +#define BANK_12M (13) +#define BANK_MASK7 (0x70<<16) +#define BANK_MASKF (0xf0<<16) +#define BANK_MASKF8 (0xf8<<16) + +void SegaPCMUpdate(INT16* pSoundBuf, INT32 nLength); +void SegaPCMInit(INT32 clock, INT32 bank, UINT8 *pPCMData, INT32 PCMDataSize); +void SegaPCMExit(); +INT32 SegaPCMScan(INT32 nAction,INT32 *pnMin); +UINT8 SegaPCMRead(UINT32 Offset); +void SegaPCMWrite(UINT32 Offset, UINT8 Data); diff --git a/src/burn/sound/sn76496.cpp b/src/burn/sound/sn76496.cpp new file mode 100644 index 00000000..baa0ac9a --- /dev/null +++ b/src/burn/sound/sn76496.cpp @@ -0,0 +1,469 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "sn76496.h" + +#define MAX_SN76496_CHIPS 5 + +#define MAX_OUTPUT 0x7fff + +#define STEP 0x10000 + +struct SN76496 +{ + UINT32 UpdateStep; + INT32 VolTable[16]; /* volume table */ + INT32 Register[8]; /* registers */ + INT32 LastRegister; /* last register written */ + INT32 Volume[4]; /* volume of voice 0-2 and noise */ + INT32 RNG; /* noise generator */ + INT32 NoiseMode; /* active noise mode */ + INT32 FeedbackMask; /* mask for feedback */ + INT32 WhitenoiseTaps; /* mask for white noise taps */ + INT32 WhitenoiseInvert; /* white noise invert flag */ + INT32 Period[4]; + INT32 Count[4]; + INT32 Output[4]; + INT32 bSignalAdd; +}; + +static INT32 NumChips; +static struct SN76496 *Chip0 = NULL; +static struct SN76496 *Chip1 = NULL; +static struct SN76496 *Chip2 = NULL; +static struct SN76496 *Chip3 = NULL; +static struct SN76496 *Chip4 = NULL; + +void SN76496Update(INT32 Num, INT16* pSoundBuf, INT32 Length) +{ + INT32 i; + INT32 Temp; + struct SN76496 *R = Chip0; + + if (Num >= MAX_SN76496_CHIPS) return; + + if (Num == 1) R = Chip1; + if (Num == 2) R = Chip2; + if (Num == 3) R = Chip3; + if (Num == 4) R = Chip4; + + /* If the volume is 0, increase the counter */ + for (i = 0;i < 4;i++) + { + if (R->Volume[i] == 0) + { + /* note that I do count += length, NOT count = length + 1. You might think */ + /* it's the same since the volume is 0, but doing the latter could cause */ + /* interferencies when the program is rapidly modulating the volume. */ + if (R->Count[i] <= Length*STEP) R->Count[i] += Length*STEP; + } + } + + while (Length > 0) + { + INT32 Vol[4]; + UINT32 Out; + INT32 Left; + + + /* vol[] keeps track of how long each square wave stays */ + /* in the 1 position during the sample period. */ + Vol[0] = Vol[1] = Vol[2] = Vol[3] = 0; + + for (i = 0;i < 3;i++) + { + if (R->Output[i]) Vol[i] += R->Count[i]; + R->Count[i] -= STEP; + /* Period[i] is the half period of the square wave. Here, in each */ + /* loop I add Period[i] twice, so that at the end of the loop the */ + /* square wave is in the same status (0 or 1) it was at the start. */ + /* vol[i] is also incremented by Period[i], since the wave has been 1 */ + /* exactly half of the time, regardless of the initial position. */ + /* If we exit the loop in the middle, Output[i] has to be inverted */ + /* and vol[i] incremented only if the exit status of the square */ + /* wave is 1. */ + while (R->Count[i] <= 0) + { + R->Count[i] += R->Period[i]; + if (R->Count[i] > 0) + { + R->Output[i] ^= 1; + if (R->Output[i]) Vol[i] += R->Period[i]; + break; + } + R->Count[i] += R->Period[i]; + Vol[i] += R->Period[i]; + } + if (R->Output[i]) Vol[i] -= R->Count[i]; + } + + Left = STEP; + do + { + INT32 NextEvent; + + + if (R->Count[3] < Left) NextEvent = R->Count[3]; + else NextEvent = Left; + + if (R->Output[3]) Vol[3] += R->Count[3]; + R->Count[3] -= NextEvent; + if (R->Count[3] <= 0) + { + if (R->NoiseMode == 1) /* White Noise Mode */ + { + if (((R->RNG & R->WhitenoiseTaps) != R->WhitenoiseTaps) && ((R->RNG & R->WhitenoiseTaps) != 0)) /* crappy xor! */ + { + R->RNG >>= 1; + R->RNG |= R->FeedbackMask; + } + else + { + R->RNG >>= 1; + } + R->Output[3] = R->WhitenoiseInvert ? !(R->RNG & 1) : R->RNG & 1; + } + else /* Periodic noise mode */ + { + if (R->RNG & 1) + { + R->RNG >>= 1; + R->RNG |= R->FeedbackMask; + } + else + { + R->RNG >>= 1; + } + R->Output[3] = R->RNG & 1; + } + R->Count[3] += R->Period[3]; + if (R->Output[3]) Vol[3] += R->Period[3]; + } + if (R->Output[3]) Vol[3] -= R->Count[3]; + + Left -= NextEvent; + } while (Left > 0); + + Out = Vol[0] * R->Volume[0] + Vol[1] * R->Volume[1] + + Vol[2] * R->Volume[2] + Vol[3] * R->Volume[3]; + + if (Out > MAX_OUTPUT * STEP) Out = MAX_OUTPUT * STEP; + + Out /= STEP; + + if (R->bSignalAdd) { + Temp = pSoundBuf[0] + Out; + if (Temp > 32767) Temp = 32767; + if (Temp < -32768) Temp = -32768; + pSoundBuf[0] = Temp; + + Temp = pSoundBuf[1] + Out; + if (Temp > 32767) Temp = 32767; + if (Temp < -32768) Temp = -32768; + pSoundBuf[1] = Temp; + } else { + pSoundBuf[0] = Out; + pSoundBuf[1] = Out; + } + + pSoundBuf += 2; + + Length--; + } +} + +void SN76496Write(INT32 Num, INT32 Data) +{ + struct SN76496 *R = Chip0; + INT32 n, r, c; + + if (Num >= MAX_SN76496_CHIPS) return; + + if (Num == 1) R = Chip1; + if (Num == 2) R = Chip2; + if (Num == 3) R = Chip3; + if (Num == 4) R = Chip4; + + if (Data & 0x80) { + r = (Data & 0x70) >> 4; + R->LastRegister = r; + R->Register[r] = (R->Register[r] & 0x3f0) | (Data & 0x0f); + } else { + r = R->LastRegister; + } + + c = r / 2; + + switch (r) + { + case 0: /* tone 0 : frequency */ + case 2: /* tone 1 : frequency */ + case 4: /* tone 2 : frequency */ + if ((Data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x0f) | ((Data & 0x3f) << 4); + R->Period[c] = R->UpdateStep * R->Register[r]; + if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (r == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + case 1: /* tone 0 : volume */ + case 3: /* tone 1 : volume */ + case 5: /* tone 2 : volume */ + case 7: /* noise : volume */ + R->Volume[c] = R->VolTable[Data & 0x0f]; + if ((Data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x3f0) | (Data & 0x0f); + break; + case 6: /* noise : frequency, mode */ + { + if ((Data & 0x80) == 0) R->Register[r] = (R->Register[r] & 0x3f0) | (Data & 0x0f); + n = R->Register[6]; + R->NoiseMode = (n & 4) ? 1 : 0; + /* N/512,N/1024,N/2048,Tone #3 output */ + R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+(n&3))); + /* Reset noise shifter */ + R->RNG = R->FeedbackMask; /* this is correct according to the smspower document */ + //R->RNG = 0xF35; /* this is not, but sounds better in do run run */ + R->Output[3] = R->RNG & 1; + } + break; + } +} + +static void SN76496SetGain(struct SN76496 *R,INT32 Gain) +{ + INT32 i; + double Out; + + Gain &= 0xff; + + /* increase max output basing on gain (0.2 dB per step) */ + Out = MAX_OUTPUT / 3; + while (Gain-- > 0) + Out *= 1.023292992; /* = (10 ^ (0.2/20)) */ + + /* build volume table (2dB per step) */ + for (i = 0;i < 15;i++) + { + /* limit volume to avoid clipping */ + if (Out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; + else R->VolTable[i] = (INT32)Out; + + Out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ + } + R->VolTable[15] = 0; +} + +static void SN76496Init(struct SN76496 *R, INT32 Clock) +{ + INT32 i; + + R->UpdateStep = (UINT32)(((double)STEP * nBurnSoundRate * 16) / Clock); + + for (i = 0; i < 4; i++) R->Volume[i] = 0; + + R->LastRegister = 0; + for (i = 0; i < 8; i += 2) { + R->Register[i + 0] = 0x00; + R->Register[i + 1] = 0x0f; + } + + for (i = 0; i < 4; i++) { + R->Output[i] = 0; + R->Period[i] = R->Count[i] = R->UpdateStep; + } + + R->FeedbackMask = 0x4000; + R->WhitenoiseTaps = 0x03; + R->WhitenoiseInvert = 1; + + R->RNG = R->FeedbackMask; + R->Output[3] = R->RNG & 1; +} + +static void GenericStart(INT32 Num, INT32 Clock, INT32 FeedbackMask, INT32 NoiseTaps, INT32 NoiseInvert, INT32 SignalAdd) +{ + if (Num >= MAX_SN76496_CHIPS) return; + + NumChips = Num; + + if (Num == 0) { + Chip0 = (struct SN76496*)malloc(sizeof(*Chip0)); + memset(Chip0, 0, sizeof(*Chip0)); + + SN76496Init(Chip0, Clock); + SN76496SetGain(Chip0, 0); + + Chip0->FeedbackMask = FeedbackMask; + Chip0->WhitenoiseTaps = NoiseTaps; + Chip0->WhitenoiseInvert = NoiseInvert; + Chip0->bSignalAdd = SignalAdd; + } + + if (Num == 1) { + Chip1 = (struct SN76496*)malloc(sizeof(*Chip1)); + memset(Chip1, 0, sizeof(*Chip1)); + + SN76496Init(Chip1, Clock); + SN76496SetGain(Chip1, 0); + + Chip1->FeedbackMask = FeedbackMask; + Chip1->WhitenoiseTaps = NoiseTaps; + Chip1->WhitenoiseInvert = NoiseInvert; + Chip1->bSignalAdd = SignalAdd; + } + + if (Num == 2) { + Chip2 = (struct SN76496*)malloc(sizeof(*Chip2)); + memset(Chip2, 0, sizeof(*Chip2)); + + SN76496Init(Chip2, Clock); + SN76496SetGain(Chip2, 0); + + Chip2->FeedbackMask = FeedbackMask; + Chip2->WhitenoiseTaps = NoiseTaps; + Chip2->WhitenoiseInvert = NoiseInvert; + Chip2->bSignalAdd = SignalAdd; + } + + if (Num == 3) { + Chip3 = (struct SN76496*)malloc(sizeof(*Chip3)); + memset(Chip3, 0, sizeof(*Chip3)); + + SN76496Init(Chip3, Clock); + SN76496SetGain(Chip3, 0); + + Chip3->FeedbackMask = FeedbackMask; + Chip3->WhitenoiseTaps = NoiseTaps; + Chip3->WhitenoiseInvert = NoiseInvert; + Chip3->bSignalAdd = SignalAdd; + } + + if (Num == 4) { + Chip4 = (struct SN76496*)malloc(sizeof(*Chip4)); + memset(Chip4, 0, sizeof(*Chip4)); + + SN76496Init(Chip4, Clock); + SN76496SetGain(Chip4, 0); + + Chip4->FeedbackMask = FeedbackMask; + Chip4->WhitenoiseTaps = NoiseTaps; + Chip4->WhitenoiseInvert = NoiseInvert; + Chip4->bSignalAdd = SignalAdd; + } +} + +void SN76489Init(INT32 Num, INT32 Clock, INT32 SignalAdd) +{ + return GenericStart(Num, Clock, 0x4000, 0x03, 1, SignalAdd); +} + +void SN76489AInit(INT32 Num, INT32 Clock, INT32 SignalAdd) +{ + return GenericStart(Num, Clock, 0x8000, 0x06, 0, SignalAdd); +} + +void SN76494Init(INT32 Num, INT32 Clock, INT32 SignalAdd) +{ + return GenericStart(Num, Clock, 0x8000, 0x06, 0, SignalAdd); +} + +void SN76496Init(INT32 Num, INT32 Clock, INT32 SignalAdd) +{ + return GenericStart(Num, Clock, 0x8000, 0x06, 0, SignalAdd); +} + +void SN76496Exit() +{ + NumChips = 0; + + if (Chip0!=NULL) + { + free(Chip0); + Chip0 = NULL; + } + if (Chip1!=NULL) + { + free(Chip1); + Chip1 = NULL; + } + if (Chip2!=NULL) + { + free(Chip2); + Chip2 = NULL; + } + if (Chip3!=NULL) + { + free(Chip3); + Chip3 = NULL; + } + if (Chip4!=NULL) + { + free(Chip4); + Chip4 = NULL; + } +} + +INT32 SN76496Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029675; + } + + sprintf(szName, "SN76496 #0"); + ba.Data = &Chip0; + ba.nLen = sizeof(struct SN76496); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + if (NumChips >= 1) { + sprintf(szName, "SN76496 #1"); + ba.Data = &Chip1; + ba.nLen = sizeof(struct SN76496); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 2) { + sprintf(szName, "SN76496 #2"); + ba.Data = &Chip2; + ba.nLen = sizeof(struct SN76496); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 3) { + sprintf(szName, "SN76496 #3"); + ba.Data = &Chip3; + ba.nLen = sizeof(struct SN76496); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + if (NumChips >= 4) { + sprintf(szName, "SN76496 #4"); + ba.Data = &Chip4; + ba.nLen = sizeof(struct SN76496); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + } + + return 0; +} + +#undef MAX_SN76496_CHIPS +#undef MAX_OUTPUT +#undef STEP diff --git a/src/burn/sound/sn76496.h b/src/burn/sound/sn76496.h new file mode 100644 index 00000000..763e7bb0 --- /dev/null +++ b/src/burn/sound/sn76496.h @@ -0,0 +1,8 @@ +void SN76496Update(INT32 Num, INT16* pSoundBuf, INT32 Length); +void SN76496Write(INT32 Num, INT32 Data); +void SN76489Init(INT32 Num, INT32 Clock, INT32 SignalAdd); +void SN76489AInit(INT32 Num, INT32 Clock, INT32 SignalAdd); +void SN76494Init(INT32 Num, INT32 Clock, INT32 SignalAdd); +void SN76496Init(INT32 Num, INT32 Clock, INT32 SignalAdd); +void SN76496Exit(); +INT32 SN76496Scan(INT32 nAction,INT32 *pnMin); diff --git a/src/burn/sound/upd7759.cpp b/src/burn/sound/upd7759.cpp new file mode 100644 index 00000000..48d0d52c --- /dev/null +++ b/src/burn/sound/upd7759.cpp @@ -0,0 +1,497 @@ +#include "burnint.h" +#include "burn_sound.h" +#include "upd7759.h" + +#define FRAC_BITS 20 +#define FRAC_ONE (1 << FRAC_BITS) +#define FRAC_MASK (FRAC_ONE - 1) + +static INT32 SlaveMode; + +/* chip states */ +enum +{ + STATE_IDLE, + STATE_DROP_DRQ, + STATE_START, + STATE_FIRST_REQ, + STATE_LAST_SAMPLE, + STATE_DUMMY1, + STATE_ADDR_MSB, + STATE_ADDR_LSB, + STATE_DUMMY2, + STATE_BLOCK_HEADER, + STATE_NIBBLE_COUNT, + STATE_NIBBLE_MSN, + STATE_NIBBLE_LSN +}; + +struct upd7759_chip +{ + /* internal clock to output sample rate mapping */ + UINT32 pos; /* current output sample position */ + UINT32 step; /* step value per output sample */ + + /* I/O lines */ + UINT8 fifo_in; /* last data written to the sound chip */ + UINT8 reset; /* current state of the RESET line */ + UINT8 start; /* current state of the START line */ + UINT8 drq; /* current state of the DRQ line */ + void (*drqcallback)(INT32 param); /* drq callback */ + + /* internal state machine */ + INT8 state; /* current overall chip state */ + INT32 clocks_left; /* number of clocks left in this state */ + UINT16 nibbles_left; /* number of ADPCM nibbles left to process */ + UINT8 repeat_count; /* number of repeats remaining in current repeat block */ + INT8 post_drq_state; /* state we will be in after the DRQ line is dropped */ + INT32 post_drq_clocks; /* clocks that will be left after the DRQ line is dropped */ + UINT8 req_sample; /* requested sample number */ + UINT8 last_sample; /* last sample number available */ + UINT8 block_header; /* header byte */ + UINT8 sample_rate; /* number of UPD clocks per ADPCM nibble */ + UINT8 first_valid_header; /* did we get our first valid header yet? */ + UINT32 offset; /* current ROM offset */ + UINT32 repeat_offset; /* current ROM repeat offset */ + + /* ADPCM processing */ + INT8 adpcm_state; /* ADPCM state index */ + UINT8 adpcm_data; /* current byte of ADPCM data */ + INT16 sample; /* current sample value */ + + /* ROM access */ + UINT8 * rom; /* pointer to ROM data or NULL for slave mode */ + UINT8 * rombase; /* pointer to ROM data or NULL for slave mode */ + UINT32 romoffset; /* ROM offset to make save/restore easier */ +}; + +static struct upd7759_chip *Chips[2]; // more? +static struct upd7759_chip *Chip = NULL; + +static const INT32 upd7759_step[16][16] = +{ + { 0, 0, 1, 2, 3, 5, 7, 10, 0, 0, -1, -2, -3, -5, -7, -10 }, + { 0, 1, 2, 3, 4, 6, 8, 13, 0, -1, -2, -3, -4, -6, -8, -13 }, + { 0, 1, 2, 4, 5, 7, 10, 15, 0, -1, -2, -4, -5, -7, -10, -15 }, + { 0, 1, 3, 4, 6, 9, 13, 19, 0, -1, -3, -4, -6, -9, -13, -19 }, + { 0, 2, 3, 5, 8, 11, 15, 23, 0, -2, -3, -5, -8, -11, -15, -23 }, + { 0, 2, 4, 7, 10, 14, 19, 29, 0, -2, -4, -7, -10, -14, -19, -29 }, + { 0, 3, 5, 8, 12, 16, 22, 33, 0, -3, -5, -8, -12, -16, -22, -33 }, + { 1, 4, 7, 10, 15, 20, 29, 43, -1, -4, -7, -10, -15, -20, -29, -43 }, + { 1, 4, 8, 13, 18, 25, 35, 53, -1, -4, -8, -13, -18, -25, -35, -53 }, + { 1, 6, 10, 16, 22, 31, 43, 64, -1, -6, -10, -16, -22, -31, -43, -64 }, + { 2, 7, 12, 19, 27, 37, 51, 76, -2, -7, -12, -19, -27, -37, -51, -76 }, + { 2, 9, 16, 24, 34, 46, 64, 96, -2, -9, -16, -24, -34, -46, -64, -96 }, + { 3, 11, 19, 29, 41, 57, 79, 117, -3, -11, -19, -29, -41, -57, -79, -117 }, + { 4, 13, 24, 36, 50, 69, 96, 143, -4, -13, -24, -36, -50, -69, -96, -143 }, + { 4, 16, 29, 44, 62, 85, 118, 175, -4, -16, -29, -44, -62, -85, -118, -175 }, + { 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214 }, +}; + +static const INT32 upd7759_state[16] = { -1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3 }; + +inline static void UpdateAdpcm(INT32 Data) +{ + Chip->sample += upd7759_step[Chip->adpcm_state][Data]; + Chip->adpcm_state += upd7759_state[Data]; + + /* clamp the state to 0..15 */ + if (Chip->adpcm_state < 0) + Chip->adpcm_state = 0; + else if (Chip->adpcm_state > 15) + Chip->adpcm_state = 15; +} + +static void UPD7759AdvanceState() +{ + switch (Chip->state) + { + /* Idle state: we stick around here while there's nothing to do */ + case STATE_IDLE: + Chip->clocks_left = 4; + break; + + /* drop DRQ state: update to the intended state */ + case STATE_DROP_DRQ: + Chip->drq = 0; + + Chip->clocks_left = Chip->post_drq_clocks; + Chip->state = Chip->post_drq_state; + break; + + /* Start state: we begin here as soon as a sample is triggered */ + case STATE_START: + Chip->req_sample = Chip->rom ? Chip->fifo_in : 0x10; + + /* 35+ cycles after we get here, the /DRQ goes low + * (first byte (number of samples in ROM) should be sent in response) + * + * (35 is the minimum number of cycles I found during heavy tests. + * Depending on the state the chip was in just before the /MD was set to 0 (reset, standby + * or just-finished-playing-previous-sample) this number can range from 35 up to ~24000). + * It also varies slightly from test to test, but not much - a few cycles at most.) */ + Chip->clocks_left = 70; /* 35 - breaks cotton */ + Chip->state = STATE_FIRST_REQ; + break; + + /* First request state: issue a request for the first byte */ + /* The expected response will be the index of the last sample */ + case STATE_FIRST_REQ: + Chip->drq = 1; + + /* 44 cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 44; + Chip->state = STATE_LAST_SAMPLE; + break; + + /* Last sample state: latch the last sample value and issue a request for the second byte */ + /* The second byte read will be just a dummy */ + case STATE_LAST_SAMPLE: + Chip->last_sample = Chip->rom ? Chip->rom[0] : Chip->fifo_in; + Chip->drq = 1; + + /* 28 cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 28; /* 28 - breaks cotton */ + Chip->state = (Chip->req_sample > Chip->last_sample) ? STATE_IDLE : STATE_DUMMY1; + break; + + /* First dummy state: ignore any data here and issue a request for the third byte */ + /* The expected response will be the MSB of the sample address */ + case STATE_DUMMY1: + Chip->drq = 1; + + /* 32 cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 32; + Chip->state = STATE_ADDR_MSB; + break; + + /* Address MSB state: latch the MSB of the sample address and issue a request for the fourth byte */ + /* The expected response will be the LSB of the sample address */ + case STATE_ADDR_MSB: + Chip->offset = (Chip->rom ? Chip->rom[Chip->req_sample * 2 + 5] : Chip->fifo_in) << 9; + Chip->drq = 1; + + /* 44 cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 44; + Chip->state = STATE_ADDR_LSB; + break; + + /* Address LSB state: latch the LSB of the sample address and issue a request for the fifth byte */ + /* The expected response will be just a dummy */ + case STATE_ADDR_LSB: + Chip->offset |= (Chip->rom ? Chip->rom[Chip->req_sample * 2 + 6] : Chip->fifo_in) << 1; + Chip->drq = 1; + + /* 36 cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 36; + Chip->state = STATE_DUMMY2; + break; + + /* Second dummy state: ignore any data here and issue a request for the the sixth byte */ + /* The expected response will be the first block header */ + case STATE_DUMMY2: + Chip->offset++; + Chip->first_valid_header = 0; + Chip->drq = 1; + + /* 36?? cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 36; + Chip->state = STATE_BLOCK_HEADER; + break; + + /* Block header state: latch the header and issue a request for the first byte afterwards */ + case STATE_BLOCK_HEADER: + + /* if we're in a repeat loop, reset the offset to the repeat point and decrement the count */ + if (Chip->repeat_count) + { + Chip->repeat_count--; + Chip->offset = Chip->repeat_offset; + } + Chip->block_header = Chip->rom ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in; + Chip->drq = 1; + + /* our next step depends on the top two bits */ + switch (Chip->block_header & 0xc0) + { + case 0x00: /* silence */ + Chip->clocks_left = 1024 * ((Chip->block_header & 0x3f) + 1); + Chip->state = (Chip->block_header == 0 && Chip->first_valid_header) ? STATE_IDLE : STATE_BLOCK_HEADER; + Chip->sample = 0; + Chip->adpcm_state = 0; + break; + + case 0x40: /* 256 nibbles */ + Chip->sample_rate = (Chip->block_header & 0x3f) + 1; + Chip->nibbles_left = 256; + Chip->clocks_left = 36; /* just a guess */ + Chip->state = STATE_NIBBLE_MSN; + break; + + case 0x80: /* n nibbles */ + Chip->sample_rate = (Chip->block_header & 0x3f) + 1; + Chip->clocks_left = 36; /* just a guess */ + Chip->state = STATE_NIBBLE_COUNT; + break; + + case 0xc0: /* repeat loop */ + Chip->repeat_count = (Chip->block_header & 7) + 1; + Chip->repeat_offset = Chip->offset; + Chip->clocks_left = 36; /* just a guess */ + Chip->state = STATE_BLOCK_HEADER; + break; + } + + /* set a flag when we get the first non-zero header */ + if (Chip->block_header != 0) + Chip->first_valid_header = 1; + break; + + /* Nibble count state: latch the number of nibbles to play and request another byte */ + /* The expected response will be the first data byte */ + case STATE_NIBBLE_COUNT: + Chip->nibbles_left = (Chip->rom ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in) + 1; + Chip->drq = 1; + + /* 36?? cycles later, we will latch this value and request another byte */ + Chip->clocks_left = 36; /* just a guess */ + Chip->state = STATE_NIBBLE_MSN; + break; + + /* MSN state: latch the data for this pair of samples and request another byte */ + /* The expected response will be the next sample data or another header */ + case STATE_NIBBLE_MSN: + Chip->adpcm_data = Chip->rom ? Chip->rom[Chip->offset++ & 0x1ffff] : Chip->fifo_in; + UpdateAdpcm(Chip->adpcm_data >> 4); + Chip->drq = 1; + + /* we stay in this state until the time for this sample is complete */ + Chip->clocks_left = Chip->sample_rate * 4; + if (--Chip->nibbles_left == 0) + Chip->state = STATE_BLOCK_HEADER; + else + Chip->state = STATE_NIBBLE_LSN; + break; + + /* LSN state: process the lower nibble */ + case STATE_NIBBLE_LSN: + UpdateAdpcm(Chip->adpcm_data & 15); + + /* we stay in this state until the time for this sample is complete */ + Chip->clocks_left = Chip->sample_rate * 4; + if (--Chip->nibbles_left == 0) + Chip->state = STATE_BLOCK_HEADER; + else + Chip->state = STATE_NIBBLE_MSN; + break; + } + + /* if there's a DRQ, fudge the state */ + if (Chip->drq) + { + Chip->post_drq_state = Chip->state; + Chip->post_drq_clocks = Chip->clocks_left - 21; + Chip->state = STATE_DROP_DRQ; + Chip->clocks_left = 21; + } +} + +static void UPD7759SlaveModeUpdate() +{ + UINT8 OldDrq = Chip->drq; + + UPD7759AdvanceState(); + + if (OldDrq != Chip->drq && Chip->drqcallback) { + (*Chip->drqcallback)(Chip->drq); + } +} + +void UPD7759Update(INT32 chip, INT16 *pSoundBuf, INT32 nLength) +{ + Chip = Chips[chip]; + + INT32 ClocksLeft = Chip->clocks_left; + INT16 Sample = Chip->sample; + UINT32 Step = Chip->step; + UINT32 Pos = Chip->pos; + + /* loop until done */ + if (Chip->state != STATE_IDLE) + while (nLength != 0) + { + /* store the current sample */ + pSoundBuf[0] += Sample << 7; + pSoundBuf[1] += Sample << 7; + pSoundBuf += 2; + nLength--; + + /* advance by the number of clocks/output sample */ + Pos += Step; + + /* handle clocks, but only in standalone mode */ + while (Chip->rom && Pos >= FRAC_ONE) + { + INT32 ClocksThisTime = Pos >> FRAC_BITS; + if (ClocksThisTime > ClocksLeft) + ClocksThisTime = ClocksLeft; + + /* clock once */ + Pos -= ClocksThisTime * FRAC_ONE; + ClocksLeft -= ClocksThisTime; + + /* if we're out of clocks, time to handle the next state */ + if (ClocksLeft == 0) + { + /* advance one state; if we hit idle, bail */ + UPD7759AdvanceState(); + if (Chip->state == STATE_IDLE) + break; + + /* reimport the variables that we cached */ + ClocksLeft = Chip->clocks_left; + Sample = Chip->sample; + } + } + } + + if (SlaveMode && ClocksLeft > 0) UPD7759SlaveModeUpdate(); + + Chip->clocks_left = ClocksLeft; + Chip->pos = Pos; +} + +void UPD7759Reset() +{ + for (INT32 i = 0; i < 2; i++) { + Chip = Chips[i]; + if (Chip == NULL) { + continue; + } + + Chip->pos = 0; + Chip->fifo_in = 0; + Chip->drq = 0; + Chip->state = STATE_IDLE; + Chip->clocks_left = 0; + Chip->nibbles_left = 0; + Chip->repeat_count = 0; + Chip->post_drq_state = STATE_IDLE; + Chip->post_drq_clocks = 0; + Chip->req_sample = 0; + Chip->last_sample = 0; + Chip->block_header = 0; + Chip->sample_rate = 0; + Chip->first_valid_header = 0; + Chip->offset = 0; + Chip->repeat_offset = 0; + Chip->adpcm_state = 0; + Chip->adpcm_data = 0; + Chip->sample = 0; + } +} + +void UPD7759Init(INT32 chip, INT32 clock, UINT8* pSoundData) +{ + Chips[chip] = (struct upd7759_chip*)malloc(sizeof(*Chip)); + Chip = Chips[chip]; + + memset(Chip, 0, sizeof(*Chip)); + + SlaveMode = 0; + + float Rate = (float)clock / 4 / nBurnSoundRate; + Chip->step = (INT32)(4 * FRAC_ONE * Rate); + Chip->state = STATE_IDLE; + + if (pSoundData) { + Chip->rom = pSoundData; + } else { + SlaveMode = 1; + } + + Chip->reset = 1; + Chip->start = 1; + + UPD7759Reset(); +} + +void UPD7759SetDrqCallback(INT32 chip, drqcallback Callback) +{ + Chip = Chips[chip]; + Chip->drqcallback = Callback; +} + +INT32 UPD7759BusyRead(INT32 chip) +{ + Chip = Chips[chip]; + return (Chip->state == STATE_IDLE); +} + +void UPD7759ResetWrite(INT32 chip, UINT8 Data) +{ + Chip = Chips[chip]; + UINT8 Oldreset = Chip->reset; + Chip->reset = (Data != 0); + + if (Oldreset && !Chip->reset) { + UPD7759Reset(); + } +} + +void UPD7759StartWrite(INT32 chip, UINT8 Data) +{ + Chip = Chips[chip]; + UINT8 Oldstart = Chip->start; + Chip->start = (Data != 0); + + if (Chip->state == STATE_IDLE && !Oldstart && Chip->start && Chip->reset) { + Chip->state = STATE_START; + + if (SlaveMode) UPD7759SlaveModeUpdate(); + } +} + +void UPD7759PortWrite(INT32 chip, UINT8 Data) +{ + Chip = Chips[chip]; + Chip->fifo_in = Data; +} + +INT32 UPD7759Scan(INT32 chip, INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029680; + } + + Chip = Chips[chip]; + + sprintf(szName, "UPD7759 %d", chip); + ba.Data = &Chip; + ba.nLen = sizeof(struct upd7759_chip); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + return 0; +} + +void UPD7759Exit() +{ + if (Chips[0]) { + free(Chips[0]); + Chips[0] = NULL; + } + if (Chips[1]) { + free(Chips[1]); + Chips[1] = NULL; + } + SlaveMode = 0; +} diff --git a/src/burn/sound/upd7759.h b/src/burn/sound/upd7759.h new file mode 100644 index 00000000..a9c35d1f --- /dev/null +++ b/src/burn/sound/upd7759.h @@ -0,0 +1,14 @@ +#define UPD7759_STANDARD_CLOCK 640000 + +typedef void (*drqcallback)(INT32 param); + +extern void UPD7759Update(INT32 chip, INT16 *pSoundBuf, INT32 nLength); +extern void UPD7759Reset(); +extern void UPD7759Init(INT32 chip, INT32 clock, UINT8* pSoundData); +extern void UPD7759SetDrqCallback(INT32 chip, drqcallback Callback); +extern INT32 UPD7759BusyRead(INT32 chip); +extern void UPD7759ResetWrite(INT32 chip, UINT8 Data); +extern void UPD7759StartWrite(INT32 chip, UINT8 Data); +extern void UPD7759PortWrite(INT32 chip, UINT8 Data); +extern INT32 UPD7759Scan(INT32 chip, INT32 nAction,INT32 *pnMin); +extern void UPD7759Exit(); diff --git a/src/burn/sound/x1010.cpp b/src/burn/sound/x1010.cpp new file mode 100644 index 00000000..3a1871f3 --- /dev/null +++ b/src/burn/sound/x1010.cpp @@ -0,0 +1,162 @@ +#include "burnint.h" +#include "msm6295.h" +#include "burn_sound.h" +#include "x1010.h" + +UINT8 *X1010SNDROM; + +struct x1_010_info * x1_010_chip = NULL; + +void x1010_sound_bank_w(UINT32 offset, UINT16 data) +{ + //int banks = (memory_region_length( REGION_SOUND1 ) - 0x100000) / 0x20000; + //if ( data >= banks ) { + // bprintf(PRINT_NORMAL, _T("invalid sound bank %04x\n"), data); + // data %= banks; + //} + memcpy(X1010SNDROM + offset * 0x20000, X1010SNDROM + 0x100000 + data * 0x20000, 0x20000); + + // backup sound bank index, need when game load status + x1_010_chip->sound_banks[ offset ] = data; +} + +UINT8 x1010_sound_read(UINT32 offset) +{ + offset ^= x1_010_chip->address; + return x1_010_chip->reg[offset]; +} + +UINT16 x1010_sound_read_word(UINT32 offset) +{ + UINT16 ret; + + ret = x1_010_chip->HI_WORD_BUF[offset] << 8; + ret += x1010_sound_read(offset); + + return ret; +} + +void x1010_sound_update() +{ + INT16* pSoundBuf = pBurnSoundOut; + memset(pSoundBuf, 0, nBurnSoundLen * sizeof(INT16) * 2); + + X1_010_CHANNEL *reg; + int ch, i, volL, volR, freq; + register INT8 *start, *end, data; + register UINT8 *env; + register UINT32 smp_offs, smp_step, env_offs, env_step, delta; + + for( ch = 0; ch < SETA_NUM_CHANNELS; ch++ ) { + reg = (X1_010_CHANNEL *) & (x1_010_chip->reg[ch * sizeof(X1_010_CHANNEL)]); + if( reg->status & 1 ) { // Key On + INT16 *bufL = pSoundBuf + 0; + INT16 *bufR = pSoundBuf + 1; + if( (reg->status & 2) == 0 ) { // PCM sampling + start = (INT8*)( reg->start * 0x1000 + X1010SNDROM ); + end = (INT8*)((0x100 - reg->end) * 0x1000 + X1010SNDROM ); + volL = ((reg->volume >> 4) & 0xf) * VOL_BASE; + volR = ((reg->volume >> 0) & 0xf) * VOL_BASE; + smp_offs = x1_010_chip->smp_offset[ch]; + freq = reg->frequency & 0x1f; + // Meta Fox does not write the frequency register. Ever + if( freq == 0 ) freq = 4; + + //smp_step = (unsigned int)((float)x1_010->base_clock / 8192.0 + // * freq * (1 << FREQ_BASE_BITS) / (float)x1_010->rate ); + smp_step = (UINT32)((float)x1_010_chip->rate / (float)nBurnSoundRate / 8.0 * freq * (1 << FREQ_BASE_BITS) ); + + //if( smp_offs == 0 ) { + // logerror( "Play sample %06X - %06X, channel %X volume %d freq %X step %X offset %X\n", + // start, end, ch, vol, freq, smp_step, smp_offs ); + //} + + for( i = 0; i < nBurnSoundLen; i++ ) { + delta = smp_offs >> FREQ_BASE_BITS; + // sample ended? + if( start + delta >= end ) { + reg->status &= 0xfe; // Key off + break; + } + data = *(start + delta); + *bufL += (data * volL / 256); bufL += 2; + *bufR += (data * volR / 256); bufR += 2; + smp_offs += smp_step; + } + x1_010_chip->smp_offset[ch] = smp_offs; + + } else { // Wave form + start = (INT8*) & (x1_010_chip->reg[reg->volume * 128 + 0x1000]); + smp_offs = x1_010_chip->smp_offset[ch]; + freq = (reg->pitch_hi << 8) + reg->frequency; + //smp_step = (unsigned int)((float)x1_010->base_clock / 128.0 / 1024.0 / 4.0 * freq * (1 << FREQ_BASE_BITS) / (float)x1_010->rate); + smp_step = (UINT32)((float)x1_010_chip->rate / (float)nBurnSoundRate / 128.0 / 4.0 * freq * (1 << FREQ_BASE_BITS) ); + + env = (UINT8*) & (x1_010_chip->reg[reg->end * 128]); + env_offs = x1_010_chip->env_offset[ch]; + //env_step = (unsigned int)((float)x1_010->base_clock / 128.0 / 1024.0 / 4.0 * reg->start * (1 << ENV_BASE_BITS) / (float)x1_010->rate); + env_step = (UINT32)((float)x1_010_chip->rate / (float)nBurnSoundRate / 128.0 / 4.0 * reg->start * (1 << ENV_BASE_BITS) ); + + //if( smp_offs == 0 ) { + // logerror( "Play waveform %X, channel %X volume %X freq %4X step %X offset %X\n", + // reg->volume, ch, reg->end, freq, smp_step, smp_offs ); + //} + + for( i = 0; i < nBurnSoundLen; i++ ) { + INT32 vol; + delta = env_offs>>ENV_BASE_BITS; + // Envelope one shot mode + if( (reg->status&4) != 0 && delta >= 0x80 ) { + reg->status &= 0xfe; // Key off + break; + } + + vol = *(env + (delta & 0x7f)); + volL = ((vol >> 4) & 0xf) * VOL_BASE; + volR = ((vol >> 0) & 0xf) * VOL_BASE; + data = *(start + ((smp_offs >> FREQ_BASE_BITS) & 0x7f)); + *bufL += (data * volL / 256); bufL += 2; + *bufR += (data * volR / 256); bufR += 2; + smp_offs += smp_step; + env_offs += env_step; + } + x1_010_chip->smp_offset[ch] = smp_offs; + x1_010_chip->env_offset[ch] = env_offs; + } + } + } +} + +void x1010_sound_init(UINT32 base_clock, INT32 address) +{ + x1_010_chip = (struct x1_010_info *) malloc( sizeof(struct x1_010_info) ); + + x1_010_chip->base_clock = base_clock; + x1_010_chip->rate = x1_010_chip->base_clock / 1024; + x1_010_chip->address = address; +} + +void x1010_scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (pnMin != NULL) { + *pnMin = 0x029672; + } + + if ( nAction & ACB_DRIVER_DATA ) { + memset(&ba, 0, sizeof(ba)); + ba.Data = x1_010_chip; + ba.nLen = sizeof(struct x1_010_info); + ba.szName = "X1-010"; + BurnAcb(&ba); + } +} + +void x1010_exit() +{ + if (x1_010_chip) { + free(x1_010_chip); + x1_010_chip = NULL; + } +} diff --git a/src/burn/sound/x1010.h b/src/burn/sound/x1010.h new file mode 100644 index 00000000..805c5555 --- /dev/null +++ b/src/burn/sound/x1010.h @@ -0,0 +1,42 @@ +#define SETA_NUM_CHANNELS 16 +#define SETA_NUM_BANKS (0x100000 / 0x20000) + +#define FREQ_BASE_BITS 8 // Frequency fixed decimal shift bits +#define ENV_BASE_BITS 16 // wave form envelope fixed decimal shift bits +#define VOL_BASE (2 * 32 * 256 / 30) // Volume base + +struct x1_010_info +{ + INT32 rate; // Output sampling rate (Hz) + //sound_stream * stream; // Stream handle + INT32 address; // address eor data + INT32 sound_enable; // sound output enable/disable + UINT8 reg[0x2000]; // X1-010 Register & wave form area + UINT8 HI_WORD_BUF[0x2000]; // X1-010 16bit access ram check avoidance work + UINT32 smp_offset[SETA_NUM_CHANNELS]; + UINT32 env_offset[SETA_NUM_CHANNELS]; + UINT32 base_clock; + UINT32 sound_banks[SETA_NUM_BANKS]; +}; + +typedef struct { + UINT8 status; + UINT8 volume; // volume / wave form no. + UINT8 frequency; // frequency / pitch lo + UINT8 pitch_hi; // reserved / pitch hi + UINT8 start; // start address / envelope time + UINT8 end; // end address / envelope no. + UINT8 reserve[2]; +} X1_010_CHANNEL; + +extern UINT8 *X1010SNDROM; + +extern struct x1_010_info * x1_010_chip; + +void x1010_sound_bank_w(UINT32 offset, UINT16 data); +UINT8 x1010_sound_read(UINT32 offset); +UINT16 x1010_sound_read_word(UINT32 offset); +void x1010_sound_update(); +void x1010_sound_init(UINT32 base_clock, INT32 address); +void x1010_scan(INT32 nAction,INT32 *pnMin); +void x1010_exit(); diff --git a/src/burn/sound/ym2151.c b/src/burn/sound/ym2151.c new file mode 100644 index 00000000..e0c83d5a --- /dev/null +++ b/src/burn/sound/ym2151.c @@ -0,0 +1,2474 @@ +/***************************************************************************** +* +* Yamaha YM2151 driver (version 2.150 final beta) +* +******************************************************************************/ + +#include +#include +#include +#include + +#include "driver.h" +#include "state.h" +#include "ym2151.h" + + +/* undef this to not use MAME timer system */ +// #define USE_MAME_TIMERS + +/*#define FM_EMU*/ +#ifdef FM_EMU + #define INLINE static __inline__ + #ifdef USE_MAME_TIMERS + #undef USE_MAME_TIMERS + #endif +#endif +#ifdef USE_MAME_TIMERS + /*#define LOG_CYM_FILE*/ + #ifdef LOG_CYM_FILE + FILE * cymfile = NULL; + #endif +#endif + + +/* struct describing a single operator */ +typedef struct{ + UINT32 phase; /* accumulated operator phase */ + UINT32 freq; /* operator frequency count */ + INT32 dt1; /* current DT1 (detune 1 phase inc/decrement) value */ + UINT32 mul; /* frequency count multiply */ + UINT32 dt1_i; /* DT1 index * 32 */ + UINT32 dt2; /* current DT2 (detune 2) value */ + + signed int *connect; /* operator output 'direction' */ + + /* only M1 (operator 0) is filled with this data: */ + signed int *mem_connect; /* where to put the delayed sample (MEM) */ + INT32 mem_value; /* delayed sample (MEM) value */ + + /* channel specific data; note: each operator number 0 contains channel specific data */ + UINT32 fb_shift; /* feedback shift value for operators 0 in each channel */ + INT32 fb_out_curr; /* operator feedback value (used only by operators 0) */ + INT32 fb_out_prev; /* previous feedback value (used only by operators 0) */ + UINT32 kc; /* channel KC (copied to all operators) */ + UINT32 kc_i; /* just for speedup */ + UINT32 pms; /* channel PMS */ + UINT32 ams; /* channel AMS */ + /* end of channel specific data */ + + UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ + UINT32 state; /* Envelope state: 4-attack(AR) 3-decay(D1R) 2-sustain(D2R) 1-release(RR) 0-off */ + UINT8 eg_sh_ar; /* (attack state) */ + UINT8 eg_sel_ar; /* (attack state) */ + UINT32 tl; /* Total attenuation Level */ + INT32 volume; /* current envelope attenuation level */ + UINT8 eg_sh_d1r; /* (decay state) */ + UINT8 eg_sel_d1r; /* (decay state) */ + UINT32 d1l; /* envelope switches to sustain state after reaching this level */ + UINT8 eg_sh_d2r; /* (sustain state) */ + UINT8 eg_sel_d2r; /* (sustain state) */ + UINT8 eg_sh_rr; /* (release state) */ + UINT8 eg_sel_rr; /* (release state) */ + + UINT32 key; /* 0=last key was KEY OFF, 1=last key was KEY ON */ + + UINT32 ks; /* key scale */ + UINT32 ar; /* attack rate */ + UINT32 d1r; /* decay rate */ + UINT32 d2r; /* sustain rate */ + UINT32 rr; /* release rate */ + + UINT32 reserved0; /**/ + UINT32 reserved1; /**/ + +} YM2151Operator; + + +typedef struct +{ + YM2151Operator oper[32]; /* the 32 operators */ + + UINT32 pan[16]; /* channels output masks (0xffffffff = enable) */ + + UINT32 eg_cnt; /* global envelope generator counter */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/64/3 */ + UINT32 eg_timer_add; /* step of eg_timer */ + UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 3 samples (on real chip) */ + + UINT32 lfo_phase; /* accumulated LFO phase (0 to 255) */ + UINT32 lfo_timer; /* LFO timer */ + UINT32 lfo_timer_add; /* step of lfo_timer */ + UINT32 lfo_overflow; /* LFO generates new output when lfo_timer reaches this value */ + UINT32 lfo_counter; /* LFO phase increment counter */ + UINT32 lfo_counter_add; /* step of lfo_counter */ + UINT8 lfo_wsel; /* LFO waveform (0-saw, 1-square, 2-triangle, 3-random noise) */ + UINT8 amd; /* LFO Amplitude Modulation Depth */ + INT8 pmd; /* LFO Phase Modulation Depth */ + UINT32 lfa; /* LFO current AM output */ + INT32 lfp; /* LFO current PM output */ + + UINT8 test; /* TEST register */ + UINT8 ct; /* output control pins (bit1-CT2, bit0-CT1) */ + + UINT32 noise; /* noise enable/period register (bit 7 - noise enable, bits 4-0 - noise period */ + UINT32 noise_rng; /* 17 bit noise shift register */ + UINT32 noise_p; /* current noise 'phase'*/ + UINT32 noise_f; /* current noise period */ + + UINT32 csm_req; /* CSM KEY ON / KEY OFF sequence request */ + + UINT32 irq_enable; /* IRQ enable for timer B (bit 3) and timer A (bit 2); bit 7 - CSM mode (keyon to all slots, everytime timer A overflows) */ + UINT32 status; /* chip status (BUSY, IRQ Flags) */ + UINT8 connect[8]; /* channels connections */ + +#ifdef USE_MAME_TIMERS +/* ASG 980324 -- added for tracking timers */ + void *timer_A; + void *timer_B; + double timer_A_time[1024]; /* timer A times for MAME */ + double timer_B_time[256]; /* timer B times for MAME */ +#else + UINT8 tim_A; /* timer A enable (0-disabled) */ + UINT8 tim_B; /* timer B enable (0-disabled) */ + INT32 tim_A_val; /* current value of timer A */ + INT32 tim_B_val; /* current value of timer B */ + UINT32 tim_A_tab[1024]; /* timer A deltas */ + UINT32 tim_B_tab[256]; /* timer B deltas */ +#endif + UINT32 timer_A_index; /* timer A index */ + UINT32 timer_B_index; /* timer B index */ + UINT32 timer_A_index_old; /* timer A previous index */ + UINT32 timer_B_index_old; /* timer B previous index */ + + /* Frequency-deltas to get the closest frequency possible. + * There are 11 octaves because of DT2 (max 950 cents over base frequency) + * and LFO phase modulation (max 800 cents below AND over base frequency) + * Summary: octave explanation + * 0 note code - LFO PM + * 1 note code + * 2 note code + * 3 note code + * 4 note code + * 5 note code + * 6 note code + * 7 note code + * 8 note code + * 9 note code + DT2 + LFO PM + * 10 note code + DT2 + LFO PM + */ + UINT32 freq[11*768]; /* 11 octaves, 768 'cents' per octave */ + + /* Frequency deltas for DT1. These deltas alter operator frequency + * after it has been taken from frequency-deltas table. + */ + INT32 dt1_freq[8*32]; /* 8 DT1 levels, 32 KC values */ + + UINT32 noise_tab[32]; /* 17bit Noise Generator periods */ + + void (*irqhandler)(int irq); /* IRQ function handler */ + write8_handler porthandler; /* port write function handler */ + + unsigned int clock; /* chip clock in Hz (passed from 2151intf.c) */ + unsigned int sampfreq; /* sampling frequency in Hz (passed from 2151intf.c) */ + +} YM2151; + + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */ +#define LFO_SH 10 /* 22.10 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define FREQ_MASK ((1<>3) + +/* sin waveform table in 'decibel' scale */ +static unsigned int sin_tab[SIN_LEN]; + + +/* translate from D1L to volume index (16 D1L levels) */ +static UINT32 d1l_tab[16]; + + +#define RATE_STEPS (8) +static UINT8 eg_inc[19*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */ +/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */ +/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */ +/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */ + +/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ +/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */ +/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; + + +#define O(a) (a*RATE_STEPS) + +/*note that there is no O(17) in this table - it's directly in the code */ +static UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ +/* 32 dummy (infinite time) rates */ +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), + +/* rates 00-11 */ +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 12 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 13 */ +O( 8),O( 9),O(10),O(11), + +/* rate 14 */ +O(12),O(13),O(14),O(15), + +/* rate 15 */ +O(16),O(16),O(16),O(16), + +/* 32 dummy rates (same as 15 3) */ +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/ +/*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */ +/*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */ + +#define O(a) (a*1) +static UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), + + +/* rates 00-11 */ +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), +O( 0),O( 0),O( 0),O( 0), + +/* rate 12 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 32 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0) + +}; +#undef O + +/* DT2 defines offset in cents from base note +* +* This table defines offset in frequency-deltas table. +* User's Manual page 22 +* +* Values below were calculated using formula: value = orig.val / 1.5625 +* +* DT2=0 DT2=1 DT2=2 DT2=3 +* 0 600 781 950 +*/ +static UINT32 dt2_tab[4] = { 0, 384, 500, 608 }; + +/* DT1 defines offset in Hertz from base note +* This table is converted while initialization... +* Detune table shown in YM2151 User's Manual is wrong (verified on the real chip) +*/ + +static UINT8 dt1_tab[4*32] = { /* 4*32 DT1 values */ +/* DT1=0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +/* DT1=1 */ + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, + +/* DT1=2 */ + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, + 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, + +/* DT1=3 */ + 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22 +}; + +static UINT16 phaseinc_rom[768]={ +1299,1300,1301,1302,1303,1304,1305,1306,1308,1309,1310,1311,1313,1314,1315,1316, +1318,1319,1320,1321,1322,1323,1324,1325,1327,1328,1329,1330,1332,1333,1334,1335, +1337,1338,1339,1340,1341,1342,1343,1344,1346,1347,1348,1349,1351,1352,1353,1354, +1356,1357,1358,1359,1361,1362,1363,1364,1366,1367,1368,1369,1371,1372,1373,1374, +1376,1377,1378,1379,1381,1382,1383,1384,1386,1387,1388,1389,1391,1392,1393,1394, +1396,1397,1398,1399,1401,1402,1403,1404,1406,1407,1408,1409,1411,1412,1413,1414, +1416,1417,1418,1419,1421,1422,1423,1424,1426,1427,1429,1430,1431,1432,1434,1435, +1437,1438,1439,1440,1442,1443,1444,1445,1447,1448,1449,1450,1452,1453,1454,1455, +1458,1459,1460,1461,1463,1464,1465,1466,1468,1469,1471,1472,1473,1474,1476,1477, +1479,1480,1481,1482,1484,1485,1486,1487,1489,1490,1492,1493,1494,1495,1497,1498, +1501,1502,1503,1504,1506,1507,1509,1510,1512,1513,1514,1515,1517,1518,1520,1521, +1523,1524,1525,1526,1528,1529,1531,1532,1534,1535,1536,1537,1539,1540,1542,1543, +1545,1546,1547,1548,1550,1551,1553,1554,1556,1557,1558,1559,1561,1562,1564,1565, +1567,1568,1569,1570,1572,1573,1575,1576,1578,1579,1580,1581,1583,1584,1586,1587, +1590,1591,1592,1593,1595,1596,1598,1599,1601,1602,1604,1605,1607,1608,1609,1610, +1613,1614,1615,1616,1618,1619,1621,1622,1624,1625,1627,1628,1630,1631,1632,1633, +1637,1638,1639,1640,1642,1643,1645,1646,1648,1649,1651,1652,1654,1655,1656,1657, +1660,1661,1663,1664,1666,1667,1669,1670,1672,1673,1675,1676,1678,1679,1681,1682, +1685,1686,1688,1689,1691,1692,1694,1695,1697,1698,1700,1701,1703,1704,1706,1707, +1709,1710,1712,1713,1715,1716,1718,1719,1721,1722,1724,1725,1727,1728,1730,1731, +1734,1735,1737,1738,1740,1741,1743,1744,1746,1748,1749,1751,1752,1754,1755,1757, +1759,1760,1762,1763,1765,1766,1768,1769,1771,1773,1774,1776,1777,1779,1780,1782, +1785,1786,1788,1789,1791,1793,1794,1796,1798,1799,1801,1802,1804,1806,1807,1809, +1811,1812,1814,1815,1817,1819,1820,1822,1824,1825,1827,1828,1830,1832,1833,1835, +1837,1838,1840,1841,1843,1845,1846,1848,1850,1851,1853,1854,1856,1858,1859,1861, +1864,1865,1867,1868,1870,1872,1873,1875,1877,1879,1880,1882,1884,1885,1887,1888, +1891,1892,1894,1895,1897,1899,1900,1902,1904,1906,1907,1909,1911,1912,1914,1915, +1918,1919,1921,1923,1925,1926,1928,1930,1932,1933,1935,1937,1939,1940,1942,1944, +1946,1947,1949,1951,1953,1954,1956,1958,1960,1961,1963,1965,1967,1968,1970,1972, +1975,1976,1978,1980,1982,1983,1985,1987,1989,1990,1992,1994,1996,1997,1999,2001, +2003,2004,2006,2008,2010,2011,2013,2015,2017,2019,2021,2022,2024,2026,2028,2029, +2032,2033,2035,2037,2039,2041,2043,2044,2047,2048,2050,2052,2054,2056,2058,2059, +2062,2063,2065,2067,2069,2071,2073,2074,2077,2078,2080,2082,2084,2086,2088,2089, +2092,2093,2095,2097,2099,2101,2103,2104,2107,2108,2110,2112,2114,2116,2118,2119, +2122,2123,2125,2127,2129,2131,2133,2134,2137,2139,2141,2142,2145,2146,2148,2150, +2153,2154,2156,2158,2160,2162,2164,2165,2168,2170,2172,2173,2176,2177,2179,2181, +2185,2186,2188,2190,2192,2194,2196,2197,2200,2202,2204,2205,2208,2209,2211,2213, +2216,2218,2220,2222,2223,2226,2227,2230,2232,2234,2236,2238,2239,2242,2243,2246, +2249,2251,2253,2255,2256,2259,2260,2263,2265,2267,2269,2271,2272,2275,2276,2279, +2281,2283,2285,2287,2288,2291,2292,2295,2297,2299,2301,2303,2304,2307,2308,2311, +2315,2317,2319,2321,2322,2325,2326,2329,2331,2333,2335,2337,2338,2341,2342,2345, +2348,2350,2352,2354,2355,2358,2359,2362,2364,2366,2368,2370,2371,2374,2375,2378, +2382,2384,2386,2388,2389,2392,2393,2396,2398,2400,2402,2404,2407,2410,2411,2414, +2417,2419,2421,2423,2424,2427,2428,2431,2433,2435,2437,2439,2442,2445,2446,2449, +2452,2454,2456,2458,2459,2462,2463,2466,2468,2470,2472,2474,2477,2480,2481,2484, +2488,2490,2492,2494,2495,2498,2499,2502,2504,2506,2508,2510,2513,2516,2517,2520, +2524,2526,2528,2530,2531,2534,2535,2538,2540,2542,2544,2546,2549,2552,2553,2556, +2561,2563,2565,2567,2568,2571,2572,2575,2577,2579,2581,2583,2586,2589,2590,2593 +}; + + +/* + Noise LFO waveform. + + Here are just 256 samples out of much longer data. + + It does NOT repeat every 256 samples on real chip and I wasnt able to find + the point where it repeats (even in strings as long as 131072 samples). + + I only put it here because its better than nothing and perhaps + someone might be able to figure out the real algorithm. + + + Note that (due to the way the LFO output is calculated) it is quite + possible that two values: 0x80 and 0x00 might be wrong in this table. + To be exact: + some 0x80 could be 0x81 as well as some 0x00 could be 0x01. +*/ + +static UINT8 lfo_noise_waveform[256] = { +0xFF,0xEE,0xD3,0x80,0x58,0xDA,0x7F,0x94,0x9E,0xE3,0xFA,0x00,0x4D,0xFA,0xFF,0x6A, +0x7A,0xDE,0x49,0xF6,0x00,0x33,0xBB,0x63,0x91,0x60,0x51,0xFF,0x00,0xD8,0x7F,0xDE, +0xDC,0x73,0x21,0x85,0xB2,0x9C,0x5D,0x24,0xCD,0x91,0x9E,0x76,0x7F,0x20,0xFB,0xF3, +0x00,0xA6,0x3E,0x42,0x27,0x69,0xAE,0x33,0x45,0x44,0x11,0x41,0x72,0x73,0xDF,0xA2, + +0x32,0xBD,0x7E,0xA8,0x13,0xEB,0xD3,0x15,0xDD,0xFB,0xC9,0x9D,0x61,0x2F,0xBE,0x9D, +0x23,0x65,0x51,0x6A,0x84,0xF9,0xC9,0xD7,0x23,0xBF,0x65,0x19,0xDC,0x03,0xF3,0x24, +0x33,0xB6,0x1E,0x57,0x5C,0xAC,0x25,0x89,0x4D,0xC5,0x9C,0x99,0x15,0x07,0xCF,0xBA, +0xC5,0x9B,0x15,0x4D,0x8D,0x2A,0x1E,0x1F,0xEA,0x2B,0x2F,0x64,0xA9,0x50,0x3D,0xAB, + +0x50,0x77,0xE9,0xC0,0xAC,0x6D,0x3F,0xCA,0xCF,0x71,0x7D,0x80,0xA6,0xFD,0xFF,0xB5, +0xBD,0x6F,0x24,0x7B,0x00,0x99,0x5D,0xB1,0x48,0xB0,0x28,0x7F,0x80,0xEC,0xBF,0x6F, +0x6E,0x39,0x90,0x42,0xD9,0x4E,0x2E,0x12,0x66,0xC8,0xCF,0x3B,0x3F,0x10,0x7D,0x79, +0x00,0xD3,0x1F,0x21,0x93,0x34,0xD7,0x19,0x22,0xA2,0x08,0x20,0xB9,0xB9,0xEF,0x51, + +0x99,0xDE,0xBF,0xD4,0x09,0x75,0xE9,0x8A,0xEE,0xFD,0xE4,0x4E,0x30,0x17,0xDF,0xCE, +0x11,0xB2,0x28,0x35,0xC2,0x7C,0x64,0xEB,0x91,0x5F,0x32,0x0C,0x6E,0x00,0xF9,0x92, +0x19,0xDB,0x8F,0xAB,0xAE,0xD6,0x12,0xC4,0x26,0x62,0xCE,0xCC,0x0A,0x03,0xE7,0xDD, +0xE2,0x4D,0x8A,0xA6,0x46,0x95,0x0F,0x8F,0xF5,0x15,0x97,0x32,0xD4,0x28,0x1E,0x55 +}; + + +static YM2151 * YMPSG = NULL; /* array of YM2151's */ +static unsigned int YMNumChips; /* total # of YM2151's emulated */ + + +/* these variables stay here for speedup purposes only */ +static YM2151 * PSG; +static signed int chanout[8]; +static signed int m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */ +static signed int mem; /* one sample delay memory */ + + +/* save output as raw 16-bit sample */ +/* #define SAVE_SAMPLE */ +/* #define SAVE_SEPARATE_CHANNELS */ +#if defined SAVE_SAMPLE || defined SAVE_SEPARATE_CHANNELS +static FILE *sample[9]; +#endif + + +/* own PI definition */ +#ifdef PI + #undef PI +#endif +#define PI 3.14159265358979323846 + + + +static void init_tables(void) +{ + signed int i,x,n; + double o,m; + + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to closest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 2; /* 13 bits here (as in real chip) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + for (i=1; i<13; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + #if 0 + logerror("tl %04i", x*2); + for (i=0; i<13; i++) + logerror(", [%02i] %4i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ]); + logerror("\n"); + #endif + } + /*logerror("TL_TAB_LEN = %i (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ + /*logerror("ENV_QUIET= %i\n",ENV_QUIET );*/ + + + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to closest */ + n = (n>>1)+1; + else + n = n>>1; + + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + /*logerror("sin [0x%4x]= %4i (tl_tab value=%8x)\n", i, sin_tab[i],tl_tab[sin_tab[i]]);*/ + } + + + /* calculate d1l_tab table */ + for (i=0; i<16; i++) + { + m = (i!=15 ? i : i+16) * (4.0/ENV_STEP); /* every 3 'dB' except for all bits = 1 = 45+48 'dB' */ + d1l_tab[i] = m; + /*logerror("d1l_tab[%02x]=%08x\n",i,d1l_tab[i] );*/ + } + +#ifdef SAVE_SAMPLE + sample[8]=fopen("sampsum.pcm","wb"); +#endif +#ifdef SAVE_SEPARATE_CHANNELS + sample[0]=fopen("samp0.pcm","wb"); + sample[1]=fopen("samp1.pcm","wb"); + sample[2]=fopen("samp2.pcm","wb"); + sample[3]=fopen("samp3.pcm","wb"); + sample[4]=fopen("samp4.pcm","wb"); + sample[5]=fopen("samp5.pcm","wb"); + sample[6]=fopen("samp6.pcm","wb"); + sample[7]=fopen("samp7.pcm","wb"); +#endif +} + + +static void init_chip_tables(YM2151 *chip) +{ + int i,j; + double mult,pom,phaseinc,Hz; + double scaler; + + scaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq ); + /*logerror("scaler = %20.15f\n", scaler);*/ + + + /* this loop calculates Hertz values for notes from c-0 to b-7 */ + /* including 64 'cents' (100/64 that is 1.5625 of real cent) per note */ + /* i*100/64/1200 is equal to i/768 */ + + /* real chip works with 10 bits fixed point values (10.10) */ + mult = (1<<(FREQ_SH-10)); /* -10 because phaseinc_rom table values are already in 10.10 format */ + + for (i=0; i<768; i++) + { + /* 3.4375 Hz is note A; C# is 4 semitones higher */ + Hz = 1000; +#if 0 +/* Hz is close, but not perfect */ + //Hz = scaler * 3.4375 * pow (2, (i + 4 * 64 ) / 768.0 ); + /* calculate phase increment */ + phaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq; +#endif + + phaseinc = phaseinc_rom[i]; /* real chip phase increment */ + phaseinc *= scaler; /* adjust */ + + + /* octave 2 - reference octave */ + chip->freq[ 768+2*768+i ] = ((int)(phaseinc*mult)) & 0xffffffc0; /* adjust to X.10 fixed point */ + /* octave 0 and octave 1 */ + for (j=0; j<2; j++) + { + chip->freq[768 + j*768 + i] = (chip->freq[ 768+2*768+i ] >> (2-j) ) & 0xffffffc0; /* adjust to X.10 fixed point */ + } + /* octave 3 to 7 */ + for (j=3; j<8; j++) + { + chip->freq[768 + j*768 + i] = chip->freq[ 768+2*768+i ] << (j-2); + } + + #if 0 + pom = (double)chip->freq[ 768+2*768+i ] / ((double)(1<sampfreq / (double)SIN_LEN; + logerror("1freq[%4i][%08x]= real %20.15f Hz emul %20.15f Hz\n", i, chip->freq[ 768+2*768+i ], Hz, pom); + #endif + } + + /* octave -1 (all equal to: oct 0, _KC_00_, _KF_00_) */ + for (i=0; i<768; i++) + { + chip->freq[ 0*768 + i ] = chip->freq[1*768+0]; + } + + /* octave 8 and 9 (all equal to: oct 7, _KC_14_, _KF_63_) */ + for (j=8; j<10; j++) + { + for (i=0; i<768; i++) + { + chip->freq[768+ j*768 + i ] = chip->freq[768 + 8*768 -1]; + } + } + +#if 0 + for (i=0; i<11*768; i++) + { + pom = (double)chip->freq[i] / ((double)(1<sampfreq / (double)SIN_LEN; + logerror("freq[%4i][%08x]= emul %20.15f Hz\n", i, chip->freq[i], pom); + } +#endif + + mult = (1<clock/64.0) ) / (double)(1<<20); + + /*calculate phase increment*/ + phaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq; + + /*positive and negative values*/ + chip->dt1_freq[ (j+0)*32 + i ] = phaseinc * mult; + chip->dt1_freq[ (j+4)*32 + i ] = -chip->dt1_freq[ (j+0)*32 + i ]; + +#if 0 + { + int x = j*32 + i; + pom = (double)chip->dt1_freq[x] / mult; + pom = pom * (double)chip->sampfreq / (double)SIN_LEN; + logerror("DT1(%03i)[%02i %02i][%08x]= real %19.15f Hz emul %19.15f Hz\n", + x, j, i, chip->dt1_freq[x], Hz, pom); + } +#endif + } + } + + + /* calculate timers' deltas */ + /* User's Manual pages 15,16 */ + mult = (1<clock ); + #ifdef USE_MAME_TIMERS + chip->timer_A_time[i] = pom; + #else + chip->tim_A_tab[i] = pom * (double)chip->sampfreq * mult; /* number of samples that timer period takes (fixed point) */ + #endif + } + for (i=0; i<256; i++) + { + /* ASG 980324: changed to compute both tim_B_tab and timer_B_time */ + pom= ( 1024.0 * (256.0-i) / (double)chip->clock ); + #ifdef USE_MAME_TIMERS + chip->timer_B_time[i] = pom; + #else + chip->tim_B_tab[i] = pom * (double)chip->sampfreq * mult; /* number of samples that timer period takes (fixed point) */ + #endif + } + + /* calculate noise periods table */ + scaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq ); + for (i=0; i<32; i++) + { + j = (i!=31 ? i : 30); /* rate 30 and 31 are the same */ + j = 32-j; + j = (65536.0 / (double)(j*32.0)); /* number of samples per one shift of the shift register */ + /*chip->noise_tab[i] = j * 64;*/ /* number of chip clock cycles per one shift */ + chip->noise_tab[i] = j * 64 * scaler; + /*logerror("noise_tab[%02x]=%08x\n", i, chip->noise_tab[i]);*/ + } +} + +#define KEY_ON(op, key_set){ \ + if (!(op)->key) \ + { \ + (op)->phase = 0; /* clear phase */ \ + (op)->state = EG_ATT; /* KEY ON = attack */ \ + (op)->volume += (~(op)->volume * \ + (eg_inc[(op)->eg_sel_ar + ((PSG->eg_cnt>>(op)->eg_sh_ar)&7)]) \ + ) >>4; \ + if ((op)->volume <= MIN_ATT_INDEX) \ + { \ + (op)->volume = MIN_ATT_INDEX; \ + (op)->state = EG_DEC; \ + } \ + } \ + (op)->key |= key_set; \ +} + +#define KEY_OFF(op, key_clr){ \ + if ((op)->key) \ + { \ + (op)->key &= key_clr; \ + if (!(op)->key) \ + { \ + if ((op)->state>EG_REL) \ + (op)->state = EG_REL;/* KEY OFF = release */\ + } \ + } \ +} + +INLINE void envelope_KONKOFF(YM2151Operator * op, int v) +{ + if (v&0x08) /* M1 */ + KEY_ON (op+0, 1) + else + KEY_OFF(op+0,~1) + + if (v&0x20) /* M2 */ + KEY_ON (op+1, 1) + else + KEY_OFF(op+1,~1) + + if (v&0x10) /* C1 */ + KEY_ON (op+2, 1) + else + KEY_OFF(op+2,~1) + + if (v&0x40) /* C2 */ + KEY_ON (op+3, 1) + else + KEY_OFF(op+3,~1) +} + + +#ifdef USE_MAME_TIMERS +static void timer_callback_a (int n) +{ + YM2151 *chip = &YMPSG[n]; + timer_adjust(chip->timer_A, chip->timer_A_time[ chip->timer_A_index ], n, 0); + chip->timer_A_index_old = chip->timer_A_index; + if (chip->irq_enable & 0x04) + { + int oldstate = chip->status & 3; + chip->status |= 1; + if ((!oldstate) && (chip->irqhandler)) (*chip->irqhandler)(1); + } + if (chip->irq_enable & 0x80) + chip->csm_req = 2; /* request KEY ON / KEY OFF sequence */ +} +static void timer_callback_b (int n) +{ + YM2151 *chip = &YMPSG[n]; + timer_adjust(chip->timer_B, chip->timer_B_time[ chip->timer_B_index ], n, 0); + chip->timer_B_index_old = chip->timer_B_index; + if (chip->irq_enable & 0x08) + { + int oldstate = chip->status & 3; + chip->status |= 2; + if ((!oldstate) && (chip->irqhandler)) (*chip->irqhandler)(1); + } +} +#if 0 +static void timer_callback_chip_busy (int n) +{ + YM2151 *chip = &YMPSG[n]; + chip->status &= 0x7f; /* reset busy flag */ +} +#endif +#endif + + + + + + +INLINE void set_connect( YM2151Operator *om1, int cha, int v) +{ + YM2151Operator *om2 = om1+1; + YM2151Operator *oc1 = om1+2; + + /* set connect algorithm */ + + /* MEM is simply one sample delay */ + + switch( v&7 ) + { + case 0: + /* M1---C1---MEM---M2---C2---OUT */ + om1->connect = &c1; + oc1->connect = &mem; + om2->connect = &c2; + om1->mem_connect = &m2; + break; + + case 1: + /* M1------+-MEM---M2---C2---OUT */ + /* C1-+ */ + om1->connect = &mem; + oc1->connect = &mem; + om2->connect = &c2; + om1->mem_connect = &m2; + break; + + case 2: + /* M1-----------------+-C2---OUT */ + /* C1---MEM---M2-+ */ + om1->connect = &c2; + oc1->connect = &mem; + om2->connect = &c2; + om1->mem_connect = &m2; + break; + + case 3: + /* M1---C1---MEM------+-C2---OUT */ + /* M2-+ */ + om1->connect = &c1; + oc1->connect = &mem; + om2->connect = &c2; + om1->mem_connect = &c2; + break; + + case 4: + /* M1---C1-+-OUT */ + /* M2---C2-+ */ + /* MEM: not used */ + om1->connect = &c1; + oc1->connect = &chanout[cha]; + om2->connect = &c2; + om1->mem_connect = &mem; /* store it anywhere where it will not be used */ + break; + + case 5: + /* +----C1----+ */ + /* M1-+-MEM---M2-+-OUT */ + /* +----C2----+ */ + om1->connect = 0; /* special mark */ + oc1->connect = &chanout[cha]; + om2->connect = &chanout[cha]; + om1->mem_connect = &m2; + break; + + case 6: + /* M1---C1-+ */ + /* M2-+-OUT */ + /* C2-+ */ + /* MEM: not used */ + om1->connect = &c1; + oc1->connect = &chanout[cha]; + om2->connect = &chanout[cha]; + om1->mem_connect = &mem; /* store it anywhere where it will not be used */ + break; + + case 7: + /* M1-+ */ + /* C1-+-OUT */ + /* M2-+ */ + /* C2-+ */ + /* MEM: not used*/ + om1->connect = &chanout[cha]; + oc1->connect = &chanout[cha]; + om2->connect = &chanout[cha]; + om1->mem_connect = &mem; /* store it anywhere where it will not be used */ + break; + } +} + + +INLINE void refresh_EG(YM2151Operator * op) +{ + UINT32 kc; + UINT32 v; + + kc = op->kc; + + /* v = 32 + 2*RATE + RKS = max 126 */ + + v = kc >> op->ks; + if ((op->ar+v) < 32+62) + { + op->eg_sh_ar = eg_rate_shift [op->ar + v ]; + op->eg_sel_ar = eg_rate_select[op->ar + v ]; + } + else + { + op->eg_sh_ar = 0; + op->eg_sel_ar = 17*RATE_STEPS; + } + op->eg_sh_d1r = eg_rate_shift [op->d1r + v]; + op->eg_sel_d1r= eg_rate_select[op->d1r + v]; + op->eg_sh_d2r = eg_rate_shift [op->d2r + v]; + op->eg_sel_d2r= eg_rate_select[op->d2r + v]; + op->eg_sh_rr = eg_rate_shift [op->rr + v]; + op->eg_sel_rr = eg_rate_select[op->rr + v]; + + + op+=1; + + v = kc >> op->ks; + if ((op->ar+v) < 32+62) + { + op->eg_sh_ar = eg_rate_shift [op->ar + v ]; + op->eg_sel_ar = eg_rate_select[op->ar + v ]; + } + else + { + op->eg_sh_ar = 0; + op->eg_sel_ar = 17*RATE_STEPS; + } + op->eg_sh_d1r = eg_rate_shift [op->d1r + v]; + op->eg_sel_d1r= eg_rate_select[op->d1r + v]; + op->eg_sh_d2r = eg_rate_shift [op->d2r + v]; + op->eg_sel_d2r= eg_rate_select[op->d2r + v]; + op->eg_sh_rr = eg_rate_shift [op->rr + v]; + op->eg_sel_rr = eg_rate_select[op->rr + v]; + + op+=1; + + v = kc >> op->ks; + if ((op->ar+v) < 32+62) + { + op->eg_sh_ar = eg_rate_shift [op->ar + v ]; + op->eg_sel_ar = eg_rate_select[op->ar + v ]; + } + else + { + op->eg_sh_ar = 0; + op->eg_sel_ar = 17*RATE_STEPS; + } + op->eg_sh_d1r = eg_rate_shift [op->d1r + v]; + op->eg_sel_d1r= eg_rate_select[op->d1r + v]; + op->eg_sh_d2r = eg_rate_shift [op->d2r + v]; + op->eg_sel_d2r= eg_rate_select[op->d2r + v]; + op->eg_sh_rr = eg_rate_shift [op->rr + v]; + op->eg_sel_rr = eg_rate_select[op->rr + v]; + + op+=1; + + v = kc >> op->ks; + if ((op->ar+v) < 32+62) + { + op->eg_sh_ar = eg_rate_shift [op->ar + v ]; + op->eg_sel_ar = eg_rate_select[op->ar + v ]; + } + else + { + op->eg_sh_ar = 0; + op->eg_sel_ar = 17*RATE_STEPS; + } + op->eg_sh_d1r = eg_rate_shift [op->d1r + v]; + op->eg_sel_d1r= eg_rate_select[op->d1r + v]; + op->eg_sh_d2r = eg_rate_shift [op->d2r + v]; + op->eg_sel_d2r= eg_rate_select[op->d2r + v]; + op->eg_sh_rr = eg_rate_shift [op->rr + v]; + op->eg_sel_rr = eg_rate_select[op->rr + v]; +} + + +/* write a register on YM2151 chip number 'n' */ +void YM2151WriteReg(int n, int r, int v) +{ + YM2151 *chip = &YMPSG[n]; + YM2151Operator *op = &chip->oper[ (r&0x07)*4+((r&0x18)>>3) ]; + + /* adjust bus to 8 bits */ + r &= 0xff; + v &= 0xff; + +#if 0 + /* There is no info on what YM2151 really does when busy flag is set */ + if ( chip->status & 0x80 ) return; + timer_set ( 64.0 / (double)chip->clock, n, timer_callback_chip_busy); + chip->status |= 0x80; /* set busy flag for 64 chip clock cycles */ +#endif + +#ifdef LOG_CYM_FILE + if ((cymfile) && (r!=0) ) + { + fputc( (unsigned char)r, cymfile ); + fputc( (unsigned char)v, cymfile ); + } +#endif + + + switch(r & 0xe0){ + case 0x00: + switch(r){ + case 0x01: /* LFO reset(bit 1), Test Register (other bits) */ + chip->test = v; + if (v&2) chip->lfo_phase = 0; + break; + + case 0x08: + PSG = &YMPSG[n]; /* PSG is used in KEY_ON macro */ + envelope_KONKOFF(&chip->oper[ (v&7)*4 ], v ); + break; + + case 0x0f: /* noise mode enable, noise period */ + chip->noise = v; + chip->noise_f = chip->noise_tab[ v & 0x1f ]; + break; + + case 0x10: /* timer A hi */ + chip->timer_A_index = (chip->timer_A_index & 0x003) | (v<<2); + break; + + case 0x11: /* timer A low */ + chip->timer_A_index = (chip->timer_A_index & 0x3fc) | (v & 3); + break; + + case 0x12: /* timer B */ + chip->timer_B_index = v; + break; + + case 0x14: /* CSM, irq flag reset, irq enable, timer start/stop */ + + chip->irq_enable = v; /* bit 3-timer B, bit 2-timer A, bit 7 - CSM */ + + if (v&0x20) /* reset timer B irq flag */ + { + int oldstate = chip->status & 3; + chip->status &= 0xfd; + if ((oldstate==2) && (chip->irqhandler)) (*chip->irqhandler)(0); + } + + if (v&0x10) /* reset timer A irq flag */ + { + int oldstate = chip->status & 3; + chip->status &= 0xfe; + if ((oldstate==1) && (chip->irqhandler)) (*chip->irqhandler)(0); + + } + + if (v&0x02){ /* load and start timer B */ + #ifdef USE_MAME_TIMERS + /* ASG 980324: added a real timer */ + /* start timer _only_ if it wasn't already started (it will reload time value next round) */ + if (!timer_enable(chip->timer_B, 1)) + { + timer_adjust(chip->timer_B, chip->timer_B_time[ chip->timer_B_index ], n, 0); + chip->timer_B_index_old = chip->timer_B_index; + } + #else + if (!chip->tim_B) + { + chip->tim_B = 1; + chip->tim_B_val = chip->tim_B_tab[ chip->timer_B_index ]; + } + #endif + }else{ /* stop timer B */ + #ifdef USE_MAME_TIMERS + /* ASG 980324: added a real timer */ + timer_enable(chip->timer_B, 0); + #else + chip->tim_B = 0; + #endif + } + + if (v&0x01){ /* load and start timer A */ + #ifdef USE_MAME_TIMERS + /* ASG 980324: added a real timer */ + /* start timer _only_ if it wasn't already started (it will reload time value next round) */ + if (!timer_enable(chip->timer_A, 1)) + { + timer_adjust(chip->timer_A, chip->timer_A_time[ chip->timer_A_index ], n, 0); + chip->timer_A_index_old = chip->timer_A_index; + } + #else + if (!chip->tim_A) + { + chip->tim_A = 1; + chip->tim_A_val = chip->tim_A_tab[ chip->timer_A_index ]; + } + #endif + }else{ /* stop timer A */ + #ifdef USE_MAME_TIMERS + /* ASG 980324: added a real timer */ + timer_enable(chip->timer_A, 0); + #else + chip->tim_A = 0; + #endif + } + break; + + case 0x18: /* LFO frequency */ + { + chip->lfo_overflow = ( 1 << ((15-(v>>4))+3) ) * (1<lfo_counter_add = 0x10 + (v & 0x0f); + } + break; + + case 0x19: /* PMD (bit 7==1) or AMD (bit 7==0) */ + if (v&0x80) + chip->pmd = v & 0x7f; + else + chip->amd = v & 0x7f; + break; + + case 0x1b: /* CT2, CT1, LFO waveform */ + chip->ct = v >> 6; + chip->lfo_wsel = v & 3; + if (chip->porthandler) (*chip->porthandler)(0 , chip->ct ); + break; + + default: + logerror("YM2151 Write %02x to undocumented register #%02x\n",v,r); + break; + } + break; + + case 0x20: + op = &chip->oper[ (r&7) * 4 ]; + switch(r & 0x18){ + case 0x00: /* RL enable, Feedback, Connection */ + op->fb_shift = ((v>>3)&7) ? ((v>>3)&7)+6:0; + chip->pan[ (r&7)*2 ] = (v & 0x40) ? ~0 : 0; + chip->pan[ (r&7)*2 +1 ] = (v & 0x80) ? ~0 : 0; + chip->connect[r&7] = v&7; + set_connect(op, r&7, v&7); + break; + + case 0x08: /* Key Code */ + v &= 0x7f; + if (v != op->kc) + { + UINT32 kc, kc_channel; + + kc_channel = (v - (v>>2))*64; + kc_channel += 768; + kc_channel |= (op->kc_i & 63); + + (op+0)->kc = v; + (op+0)->kc_i = kc_channel; + (op+1)->kc = v; + (op+1)->kc_i = kc_channel; + (op+2)->kc = v; + (op+2)->kc_i = kc_channel; + (op+3)->kc = v; + (op+3)->kc_i = kc_channel; + + kc = v>>2; + + (op+0)->dt1 = chip->dt1_freq[ (op+0)->dt1_i + kc ]; + (op+0)->freq = ( (chip->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1; + + (op+1)->dt1 = chip->dt1_freq[ (op+1)->dt1_i + kc ]; + (op+1)->freq = ( (chip->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1; + + (op+2)->dt1 = chip->dt1_freq[ (op+2)->dt1_i + kc ]; + (op+2)->freq = ( (chip->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1; + + (op+3)->dt1 = chip->dt1_freq[ (op+3)->dt1_i + kc ]; + (op+3)->freq = ( (chip->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1; + + refresh_EG( op ); + } + break; + + case 0x10: /* Key Fraction */ + v >>= 2; + if (v != (op->kc_i & 63)) + { + UINT32 kc_channel; + + kc_channel = v; + kc_channel |= (op->kc_i & ~63); + + (op+0)->kc_i = kc_channel; + (op+1)->kc_i = kc_channel; + (op+2)->kc_i = kc_channel; + (op+3)->kc_i = kc_channel; + + (op+0)->freq = ( (chip->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1; + (op+1)->freq = ( (chip->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1; + (op+2)->freq = ( (chip->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1; + (op+3)->freq = ( (chip->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1; + } + break; + + case 0x18: /* PMS, AMS */ + op->pms = (v>>4) & 7; + op->ams = (v & 3); + break; + } + break; + + case 0x40: /* DT1, MUL */ + { + UINT32 olddt1_i = op->dt1_i; + UINT32 oldmul = op->mul; + + op->dt1_i = (v&0x70)<<1; + op->mul = (v&0x0f) ? (v&0x0f)<<1: 1; + + if (olddt1_i != op->dt1_i) + op->dt1 = chip->dt1_freq[ op->dt1_i + (op->kc>>2) ]; + + if ( (olddt1_i != op->dt1_i) || (oldmul != op->mul) ) + op->freq = ( (chip->freq[ op->kc_i + op->dt2 ] + op->dt1) * op->mul ) >> 1; + } + break; + + case 0x60: /* TL */ + op->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ + break; + + case 0x80: /* KS, AR */ + { + UINT32 oldks = op->ks; + UINT32 oldar = op->ar; + + op->ks = 5-(v>>6); + op->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + if ( (op->ar != oldar) || (op->ks != oldks) ) + { + if ((op->ar + (op->kc>>op->ks)) < 32+62) + { + op->eg_sh_ar = eg_rate_shift [op->ar + (op->kc>>op->ks) ]; + op->eg_sel_ar = eg_rate_select[op->ar + (op->kc>>op->ks) ]; + } + else + { + op->eg_sh_ar = 0; + op->eg_sel_ar = 17*RATE_STEPS; + } + } + + if (op->ks != oldks) + { + op->eg_sh_d1r = eg_rate_shift [op->d1r + (op->kc>>op->ks) ]; + op->eg_sel_d1r= eg_rate_select[op->d1r + (op->kc>>op->ks) ]; + op->eg_sh_d2r = eg_rate_shift [op->d2r + (op->kc>>op->ks) ]; + op->eg_sel_d2r= eg_rate_select[op->d2r + (op->kc>>op->ks) ]; + op->eg_sh_rr = eg_rate_shift [op->rr + (op->kc>>op->ks) ]; + op->eg_sel_rr = eg_rate_select[op->rr + (op->kc>>op->ks) ]; + } + } + break; + + case 0xa0: /* LFO AM enable, D1R */ + op->AMmask = (v&0x80) ? ~0 : 0; + op->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + op->eg_sh_d1r = eg_rate_shift [op->d1r + (op->kc>>op->ks) ]; + op->eg_sel_d1r= eg_rate_select[op->d1r + (op->kc>>op->ks) ]; + break; + + case 0xc0: /* DT2, D2R */ + { + UINT32 olddt2 = op->dt2; + op->dt2 = dt2_tab[ v>>6 ]; + if (op->dt2 != olddt2) + op->freq = ( (chip->freq[ op->kc_i + op->dt2 ] + op->dt1) * op->mul ) >> 1; + } + op->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + op->eg_sh_d2r = eg_rate_shift [op->d2r + (op->kc>>op->ks) ]; + op->eg_sel_d2r= eg_rate_select[op->d2r + (op->kc>>op->ks) ]; + break; + + case 0xe0: /* D1L, RR */ + op->d1l = d1l_tab[ v>>4 ]; + op->rr = 34 + ((v&0x0f)<<2); + op->eg_sh_rr = eg_rate_shift [op->rr + (op->kc>>op->ks) ]; + op->eg_sel_rr = eg_rate_select[op->rr + (op->kc>>op->ks) ]; + break; + } +} + + +#ifdef LOG_CYM_FILE +static void cymfile_callback (int n) +{ + if (cymfile) + fputc( (unsigned char)0, cymfile ); +} +#endif + + +int YM2151ReadStatus( int n ) +{ + return YMPSG[n].status; +} + + + +//#ifdef USE_MAME_TIMERS +#if 0 // disabled for now due to crashing in debug+map+symbols build +/* +* state save support for MAME +*/ +static void ym2151_postload_refresh(void) +{ + int i,j; + + for (i=0; i>3)]; + + state_save_register_UINT32 (buf1, i, "phase", &op->phase, 1); + state_save_register_UINT32 (buf1, i, "freq" , &op->freq, 1); + state_save_register_INT32 (buf1, i, "dt1" , &op->dt1, 1); + state_save_register_UINT32 (buf1, i, "mul" , &op->mul, 1); + state_save_register_UINT32 (buf1, i, "dt1_i", &op->dt1_i, 1); + state_save_register_UINT32 (buf1, i, "dt2" , &op->dt2, 1); + /* operators connection is saved in chip data block */ + state_save_register_INT32 (buf1, i, "mem_v" ,&op->mem_value,1); + + state_save_register_UINT32 (buf1, i, "fb_sh", &op->fb_shift, 1); + state_save_register_INT32 (buf1, i, "fb_c" , &op->fb_out_curr,1); + state_save_register_INT32 (buf1, i, "fb_p" , &op->fb_out_prev,1); + state_save_register_UINT32 (buf1, i, "kc" , &op->kc, 1); + state_save_register_UINT32 (buf1, i, "kc_i" , &op->kc_i, 1); + state_save_register_UINT32 (buf1, i, "pms" , &op->pms, 1); + state_save_register_UINT32 (buf1, i, "ams" , &op->ams, 1); + state_save_register_UINT32 (buf1, i, "AMmask",&op->AMmask,1); + + state_save_register_UINT32 (buf1, i, "state" ,&op->state, 1); + state_save_register_UINT8 (buf1, i, "e_shAR",&op->eg_sh_ar, 1); + state_save_register_UINT8 (buf1, i, "e_slAR",&op->eg_sel_ar, 1); + state_save_register_UINT32 (buf1, i, "tl" ,&op->tl, 1); + state_save_register_INT32 (buf1, i, "volume",&op->volume, 1); + state_save_register_UINT8 (buf1, i, "e_shD1",&op->eg_sh_d1r, 1); + state_save_register_UINT8 (buf1, i, "e_slD1",&op->eg_sel_d1r,1); + state_save_register_UINT32 (buf1, i, "d1l" ,&op->d1l, 1); + state_save_register_UINT8 (buf1, i, "e_shD2",&op->eg_sh_d2r, 1); + state_save_register_UINT8 (buf1, i, "e_slD2",&op->eg_sel_d2r,1); + state_save_register_UINT8 (buf1, i, "e_shRR",&op->eg_sh_rr, 1); + state_save_register_UINT8 (buf1, i, "e_slRR",&op->eg_sel_rr, 1); + + state_save_register_UINT32 (buf1, i, "key" ,&op->key, 1); + state_save_register_UINT32 (buf1, i, "ks" ,&op->ks, 1); + state_save_register_UINT32 (buf1, i, "ar" ,&op->ar, 1); + state_save_register_UINT32 (buf1, i, "d1r" ,&op->d1r, 1); + state_save_register_UINT32 (buf1, i, "d2r" ,&op->d2r, 1); + state_save_register_UINT32 (buf1, i, "rr" ,&op->rr, 1); + + state_save_register_UINT32 (buf1, i, "rsrvd0",&op->reserved0, 1); + state_save_register_UINT32 (buf1, i, "rsrvd1",&op->reserved1, 1); + } + + sprintf(buf1,"YM2151.registers"); + + state_save_register_UINT32 (buf1, i, "pan" , &YMPSG[i].pan[0], 16); + + state_save_register_UINT32 (buf1, i, "eg_cnt" , &YMPSG[i].eg_cnt, 1); + state_save_register_UINT32 (buf1, i, "eg_tmr" , &YMPSG[i].eg_timer, 1); + state_save_register_UINT32 (buf1, i, "eg_tmra" , &YMPSG[i].eg_timer_add, 1); + state_save_register_UINT32 (buf1, i, "eg_ovr" , &YMPSG[i].eg_timer_overflow,1); + + state_save_register_UINT32 (buf1, i, "lfo_phas", &YMPSG[i].lfo_phase, 1); + state_save_register_UINT32 (buf1, i, "lfo_tmr" , &YMPSG[i].lfo_timer, 1); + state_save_register_UINT32 (buf1, i, "lfo_tmra", &YMPSG[i].lfo_timer_add, 1); + state_save_register_UINT32 (buf1, i, "lfo_ovr" , &YMPSG[i].lfo_overflow, 1); + state_save_register_UINT32 (buf1, i, "lfo_ctr" , &YMPSG[i].lfo_counter, 1); + state_save_register_UINT32 (buf1, i, "lfo_ctra", &YMPSG[i].lfo_counter_add,1); + state_save_register_UINT8 (buf1, i, "lfo_wsel", &YMPSG[i].lfo_wsel, 1); + state_save_register_UINT8 (buf1, i, "amd" , &YMPSG[i].amd, 1); + state_save_register_INT8 (buf1, i, "pmd" , &YMPSG[i].pmd, 1); + state_save_register_UINT32 (buf1, i, "lfa" , &YMPSG[i].lfa, 1); + state_save_register_INT32 (buf1, i, "lfp" , &YMPSG[i].lfp, 1); + + state_save_register_UINT8 (buf1, i, "test" , &YMPSG[i].test,1); + state_save_register_UINT8 (buf1, i, "ct" , &YMPSG[i].ct, 1); + + state_save_register_UINT32 (buf1, i, "noise" , &YMPSG[i].noise, 1); + state_save_register_UINT32 (buf1, i, "noiseRNG", &YMPSG[i].noise_rng, 1); + state_save_register_UINT32 (buf1, i, "noise_p" , &YMPSG[i].noise_p, 1); + state_save_register_UINT32 (buf1, i, "noise_f" , &YMPSG[i].noise_f, 1); + + state_save_register_UINT32 (buf1, i, "csm_req" , &YMPSG[i].csm_req, 1); + state_save_register_UINT32 (buf1, i, "irq_ena" , &YMPSG[i].irq_enable,1); + state_save_register_UINT32 (buf1, i, "status" , &YMPSG[i].status, 1); + + state_save_register_UINT32 (buf1, i, "TimAind" , &YMPSG[i].timer_A_index, 1); + state_save_register_UINT32 (buf1, i, "TimBind" , &YMPSG[i].timer_B_index, 1); + state_save_register_UINT32 (buf1, i, "TimAold" , &YMPSG[i].timer_A_index_old, 1); + state_save_register_UINT32 (buf1, i, "TimBold" , &YMPSG[i].timer_B_index_old, 1); + + state_save_register_UINT8 (buf1, i, "connect" , &YMPSG[i].connect[0], 8); + } + + state_save_register_func_postload(ym2151_postload_refresh); +} +#else +static void ym2151_state_save_register( int numchips ) +{ +} +#endif + + +/* +* Initialize YM2151 emulator(s). +* +* 'num' is the number of virtual YM2151's to allocate +* 'clock' is the chip clock in Hz +* 'rate' is sampling rate +*/ +int YM2151Init(int num, int clock, int rate) +{ + int i; + + if (YMPSG) + return -1; /* duplicate init. */ + + YMNumChips = num; + + YMPSG = (YM2151 *)malloc(sizeof(YM2151) * YMNumChips); + if (YMPSG == NULL) + return 1; + + memset(YMPSG, 0, sizeof(YM2151) * YMNumChips); + + ym2151_state_save_register( YMNumChips ); + + init_tables(); + + for (i=0 ; ioper[i],'\0',sizeof(YM2151Operator)); + chip->oper[i].volume = MAX_ATT_INDEX; + chip->oper[i].kc_i = 768; /* min kc_i value */ + } + + chip->eg_timer = 0; + chip->eg_cnt = 0; + + chip->lfo_timer = 0; + chip->lfo_counter= 0; + chip->lfo_phase = 0; + chip->lfo_wsel = 0; + chip->pmd = 0; + chip->amd = 0; + chip->lfa = 0; + chip->lfp = 0; + + chip->test= 0; + + chip->irq_enable = 0; +#ifdef USE_MAME_TIMERS + /* ASG 980324 -- reset the timers before writing to the registers */ + timer_enable(chip->timer_A, 0); + timer_enable(chip->timer_B, 0); +#else + chip->tim_A = 0; + chip->tim_B = 0; + chip->tim_A_val = 0; + chip->tim_B_val = 0; +#endif + chip->timer_A_index = 0; + chip->timer_B_index = 0; + chip->timer_A_index_old = 0; + chip->timer_B_index_old = 0; + + chip->noise = 0; + chip->noise_rng = 0; + chip->noise_p = 0; + chip->noise_f = chip->noise_tab[0]; + + chip->csm_req = 0; + chip->status = 0; + + YM2151WriteReg(num, 0x1b, 0); /* only because of CT1, CT2 output pins */ + YM2151WriteReg(num, 0x18, 0); /* set LFO frequency */ + for (i=0x20; i<0x100; i++) /* set the operators */ + { + YM2151WriteReg(num, i, 0); + } +} + + + +INLINE signed int op_calc(YM2151Operator * OP, unsigned int env, signed int pm) +{ + UINT32 p; + + + p = (env<<3) + sin_tab[ ( ((signed int)((OP->phase & ~FREQ_MASK) + (pm<<15))) >> FREQ_SH ) & SIN_MASK ]; + + if (p >= TL_TAB_LEN) + return 0; + + return tl_tab[p]; +} + +INLINE signed int op_calc1(YM2151Operator * OP, unsigned int env, signed int pm) +{ + UINT32 p; + INT32 i; + + + i = (OP->phase & ~FREQ_MASK) + pm; + +/*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, OP->phase>>FREQ_SH, pm);*/ + + p = (env<<3) + sin_tab[ (i>>FREQ_SH) & SIN_MASK]; + +/*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/ + + if (p >= TL_TAB_LEN) + return 0; + + return tl_tab[p]; +} + + + +#define volume_calc(OP) ((OP)->tl + ((UINT32)(OP)->volume) + (AM & (OP)->AMmask)) + +INLINE void chan_calc(unsigned int chan) +{ + YM2151Operator *op; + unsigned int env; + UINT32 AM = 0; + + m2 = c1 = c2 = mem = 0; + op = &PSG->oper[chan*4]; /* M1 */ + + *op->mem_connect = op->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ + + if (op->ams) + AM = PSG->lfa << (op->ams-1); + env = volume_calc(op); + { + INT32 out = op->fb_out_prev + op->fb_out_curr; + op->fb_out_prev = op->fb_out_curr; + + if (!op->connect) + /* algorithm 5 */ + mem = c1 = c2 = op->fb_out_prev; + else + /* other algorithms */ + *op->connect = op->fb_out_prev; + + op->fb_out_curr = 0; + if (env < ENV_QUIET) + { + if (!op->fb_shift) + out=0; + op->fb_out_curr = op_calc1(op, env, (out<fb_shift) ); + } + } + + env = volume_calc(op+1); /* M2 */ + if (env < ENV_QUIET) + *(op+1)->connect += op_calc(op+1, env, m2); + + env = volume_calc(op+2); /* C1 */ + if (env < ENV_QUIET) + *(op+2)->connect += op_calc(op+2, env, c1); + + env = volume_calc(op+3); /* C2 */ + if (env < ENV_QUIET) + chanout[chan] += op_calc(op+3, env, c2); + + /* M1 */ + op->mem_value = mem; +} +INLINE void chan7_calc(void) +{ + YM2151Operator *op; + unsigned int env; + UINT32 AM = 0; + + m2 = c1 = c2 = mem = 0; + op = &PSG->oper[7*4]; /* M1 */ + + *op->mem_connect = op->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ + + if (op->ams) + AM = PSG->lfa << (op->ams-1); + env = volume_calc(op); + { + INT32 out = op->fb_out_prev + op->fb_out_curr; + op->fb_out_prev = op->fb_out_curr; + + if (!op->connect) + /* algorithm 5 */ + mem = c1 = c2 = op->fb_out_prev; + else + /* other algorithms */ + *op->connect = op->fb_out_prev; + + op->fb_out_curr = 0; + if (env < ENV_QUIET) + { + if (!op->fb_shift) + out=0; + op->fb_out_curr = op_calc1(op, env, (out<fb_shift) ); + } + } + + env = volume_calc(op+1); /* M2 */ + if (env < ENV_QUIET) + *(op+1)->connect += op_calc(op+1, env, m2); + + env = volume_calc(op+2); /* C1 */ + if (env < ENV_QUIET) + *(op+2)->connect += op_calc(op+2, env, c1); + + env = volume_calc(op+3); /* C2 */ + if (PSG->noise & 0x80) + { + UINT32 noiseout; + + noiseout = 0; + if (env < 0x3ff) + noiseout = (env ^ 0x3ff) * 2; /* range of the YM2151 noise output is -2044 to 2040 */ + chanout[7] += ((PSG->noise_rng&0x10000) ? noiseout: -noiseout); /* bit 16 -> output */ + } + else + { + if (env < ENV_QUIET) + chanout[7] += op_calc(op+3, env, c2); + } + /* M1 */ + op->mem_value = mem; +} + + + + + + +/* +The 'rate' is calculated from following formula (example on decay rate): + rks = notecode after key scaling (a value from 0 to 31) + DR = value written to the chip register + rate = 2*DR + rks; (max rate = 2*31+31 = 93) +Four MSBs of the 'rate' above are the 'main' rate (from 00 to 15) +Two LSBs of the 'rate' above are the value 'x' (the shape type). +(eg. '11 2' means that 'rate' is 11*4+2=46) + +NOTE: A 'sample' in the description below is actually 3 output samples, +thats because the Envelope Generator clock is equal to internal_clock/3. + +Single '-' (minus) character in the diagrams below represents one sample +on the output; this is for rates 11 x (11 0, 11 1, 11 2 and 11 3) + +these 'main' rates: +00 x: single '-' = 2048 samples; (ie. level can change every 2048 samples) +01 x: single '-' = 1024 samples; +02 x: single '-' = 512 samples; +03 x: single '-' = 256 samples; +04 x: single '-' = 128 samples; +05 x: single '-' = 64 samples; +06 x: single '-' = 32 samples; +07 x: single '-' = 16 samples; +08 x: single '-' = 8 samples; +09 x: single '-' = 4 samples; +10 x: single '-' = 2 samples; +11 x: single '-' = 1 sample; (ie. level can change every 1 sample) + +Shapes for rates 11 x look like this: +rate: step: +11 0 01234567 + +level: +0 -- +1 -- +2 -- +3 -- + +rate: step: +11 1 01234567 + +level: +0 -- +1 -- +2 - +3 - +4 -- + +rate: step: +11 2 01234567 + +level: +0 -- +1 - +2 - +3 -- +4 - +5 - + +rate: step: +11 3 01234567 + +level: +0 -- +1 - +2 - +3 - +4 - +5 - +6 - + + +For rates 12 x, 13 x, 14 x and 15 x output level changes on every +sample - this means that the waveform looks like this: (but the level +changes by different values on different steps) +12 3 01234567 + +0 - +2 - +4 - +8 - +10 - +12 - +14 - +18 - +20 - + +Notes about the timing: +---------------------- + +1. Synchronism + +Output level of each two (or more) voices running at the same 'main' rate +(eg 11 0 and 11 1 in the diagram below) will always be changing in sync, +even if there're started with some delay. + +Note that, in the diagram below, the decay phase in channel 0 starts at +sample #2, while in channel 1 it starts at sample #6. Anyway, both channels +will always change their levels at exactly the same (following) samples. + +(S - start point of this channel, A-attack phase, D-decay phase): + +step: +01234567012345670123456 + +channel 0: + -- + | -- + | - + | - + | -- + | -- +| -- +| - +| - +| -- +AADDDDDDDDDDDDDDDD +S + +01234567012345670123456 +channel 1: + - + | - + | -- + | -- + | -- + | - + | - + | -- + | -- + | -- + AADDDDDDDDDDDDDDDD + S +01234567012345670123456 + + +2. Shifted (delayed) synchronism + +Output of each two (or more) voices running at different 'main' rate +(9 1, 10 1 and 11 1 in the diagrams below) will always be changing +in 'delayed-sync' (even if there're started with some delay as in "1.") + +Note that the shapes are delayed by exactly one sample per one 'main' rate +increment. (Normally one would expect them to start at the same samples.) + +See diagram below (* - start point of the shape). + +cycle: +0123456701234567012345670123456701234567012345670123456701234567 + +rate 09 1 +*------- + -------- + ---- + ---- + -------- + *------- + | -------- + | ---- + | ---- + | -------- +rate 10 1 | +-- | + *--- | + ---- | + -- | + -- | + ---- | + *--- | + | ---- | + | -- | | <- one step (two samples) delay between 9 1 and 10 1 + | -- | | + | ----| + | *--- + | ---- + | -- + | -- + | ---- +rate 11 1 | +- | + -- | + *- | + -- | + - | + - | + -- | + *- | + -- | + - || <- one step (one sample) delay between 10 1 and 11 1 + - || + --| + *- + -- + - + - + -- + *- + -- + - + - + -- +*/ + +INLINE void advance_eg(void) +{ + YM2151Operator *op; + unsigned int i; + + + + PSG->eg_timer += PSG->eg_timer_add; + + while (PSG->eg_timer >= PSG->eg_timer_overflow) + { + PSG->eg_timer -= PSG->eg_timer_overflow; + + PSG->eg_cnt++; + + /* envelope generator */ + op = &PSG->oper[0]; /* CH 0 M1 */ + i = 32; + do + { + switch(op->state) + { + case EG_ATT: /* attack phase */ + if ( !(PSG->eg_cnt & ((1<eg_sh_ar)-1) ) ) + { + op->volume += (~op->volume * + (eg_inc[op->eg_sel_ar + ((PSG->eg_cnt>>op->eg_sh_ar)&7)]) + ) >>4; + + if (op->volume <= MIN_ATT_INDEX) + { + op->volume = MIN_ATT_INDEX; + op->state = EG_DEC; + } + + } + break; + + case EG_DEC: /* decay phase */ + if ( !(PSG->eg_cnt & ((1<eg_sh_d1r)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_d1r + ((PSG->eg_cnt>>op->eg_sh_d1r)&7)]; + + if ( op->volume >= op->d1l ) + op->state = EG_SUS; + + } + break; + + case EG_SUS: /* sustain phase */ + if ( !(PSG->eg_cnt & ((1<eg_sh_d2r)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_d2r + ((PSG->eg_cnt>>op->eg_sh_d2r)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + + } + break; + + case EG_REL: /* release phase */ + if ( !(PSG->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rr + ((PSG->eg_cnt>>op->eg_sh_rr)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + + } + break; + } + op++; + i--; + }while (i); + } +} + + +INLINE void advance(void) +{ + YM2151Operator *op; + unsigned int i; + int a,p; + + /* LFO */ + if (PSG->test&2) + PSG->lfo_phase = 0; + else + { + PSG->lfo_timer += PSG->lfo_timer_add; + if (PSG->lfo_timer >= PSG->lfo_overflow) + { + PSG->lfo_timer -= PSG->lfo_overflow; + PSG->lfo_counter += PSG->lfo_counter_add; + PSG->lfo_phase += (PSG->lfo_counter>>4); + PSG->lfo_phase &= 255; + PSG->lfo_counter &= 15; + } + } + + i = PSG->lfo_phase; + /* calculate LFO AM and PM waveform value (all verified on real chip, except for noise algorithm which is impossible to analyse)*/ + switch (PSG->lfo_wsel) + { + case 0: + /* saw */ + /* AM: 255 down to 0 */ + /* PM: 0 to 127, -127 to 0 (at PMD=127: LFP = 0 to 126, -126 to 0) */ + a = 255 - i; + if (i<128) + p = i; + else + p = i - 255; + break; + case 1: + /* square */ + /* AM: 255, 0 */ + /* PM: 128,-128 (LFP = exactly +PMD, -PMD) */ + if (i<128){ + a = 255; + p = 128; + }else{ + a = 0; + p = -128; + } + break; + case 2: + /* triangle */ + /* AM: 255 down to 1 step -2; 0 up to 254 step +2 */ + /* PM: 0 to 126 step +2, 127 to 1 step -2, 0 to -126 step -2, -127 to -1 step +2*/ + if (i<128) + a = 255 - (i*2); + else + a = (i*2) - 256; + + if (i<64) /* i = 0..63 */ + p = i*2; /* 0 to 126 step +2 */ + else if (i<128) /* i = 64..127 */ + p = 255 - i*2; /* 127 to 1 step -2 */ + else if (i<192) /* i = 128..191 */ + p = 256 - i*2; /* 0 to -126 step -2*/ + else /* i = 192..255 */ + p = i*2 - 511; /*-127 to -1 step +2*/ + break; + case 3: + default: /*keep the compiler happy*/ + /* random */ + /* the real algorithm is unknown !!! + We just use a snapshot of data from real chip */ + + /* AM: range 0 to 255 */ + /* PM: range -128 to 127 */ + + a = lfo_noise_waveform[i]; + p = a-128; + break; + } + PSG->lfa = a * PSG->amd / 128; + PSG->lfp = p * PSG->pmd / 128; + + + /* The Noise Generator of the YM2151 is 17-bit shift register. + * Input to the bit16 is negated (bit0 XOR bit3) (EXNOR). + * Output of the register is negated (bit0 XOR bit3). + * Simply use bit16 as the noise output. + */ + PSG->noise_p += PSG->noise_f; + i = (PSG->noise_p>>16); /* number of events (shifts of the shift register) */ + PSG->noise_p &= 0xffff; + while (i) + { + UINT32 j; + j = ( (PSG->noise_rng ^ (PSG->noise_rng>>3) ) & 1) ^ 1; + PSG->noise_rng = (j<<16) | (PSG->noise_rng>>1); + i--; + } + + + /* phase generator */ + op = &PSG->oper[0]; /* CH 0 M1 */ + i = 8; + do + { + if (op->pms) /* only when phase modulation from LFO is enabled for this channel */ + { + INT32 mod_ind = PSG->lfp; /* -128..+127 (8bits signed) */ + if (op->pms < 6) + mod_ind >>= (6 - op->pms); + else + mod_ind <<= (op->pms - 5); + + if (mod_ind) + { + UINT32 kc_channel = op->kc_i + mod_ind; + (op+0)->phase += ( (PSG->freq[ kc_channel + (op+0)->dt2 ] + (op+0)->dt1) * (op+0)->mul ) >> 1; + (op+1)->phase += ( (PSG->freq[ kc_channel + (op+1)->dt2 ] + (op+1)->dt1) * (op+1)->mul ) >> 1; + (op+2)->phase += ( (PSG->freq[ kc_channel + (op+2)->dt2 ] + (op+2)->dt1) * (op+2)->mul ) >> 1; + (op+3)->phase += ( (PSG->freq[ kc_channel + (op+3)->dt2 ] + (op+3)->dt1) * (op+3)->mul ) >> 1; + } + else /* phase modulation from LFO is equal to zero */ + { + (op+0)->phase += (op+0)->freq; + (op+1)->phase += (op+1)->freq; + (op+2)->phase += (op+2)->freq; + (op+3)->phase += (op+3)->freq; + } + } + else /* phase modulation from LFO is disabled */ + { + (op+0)->phase += (op+0)->freq; + (op+1)->phase += (op+1)->freq; + (op+2)->phase += (op+2)->freq; + (op+3)->phase += (op+3)->freq; + } + + op+=4; + i--; + }while (i); + + + /* CSM is calculated *after* the phase generator calculations (verified on real chip) + * CSM keyon line seems to be ORed with the KO line inside of the chip. + * The result is that it only works when KO (register 0x08) is off, ie. 0 + * + * Interesting effect is that when timer A is set to 1023, the KEY ON happens + * on every sample, so there is no KEY OFF at all - the result is that + * the sound played is the same as after normal KEY ON. + */ + + if (PSG->csm_req) /* CSM KEYON/KEYOFF seqeunce request */ + { + if (PSG->csm_req==2) /* KEY ON */ + { + op = &PSG->oper[0]; /* CH 0 M1 */ + i = 32; + do + { + KEY_ON(op, 2); + op++; + i--; + }while (i); + PSG->csm_req = 1; + } + else /* KEY OFF */ + { + op = &PSG->oper[0]; /* CH 0 M1 */ + i = 32; + do + { + KEY_OFF(op,~2); + op++; + i--; + }while (i); + PSG->csm_req = 0; + } + } +} + +#if 0 +INLINE signed int acc_calc(signed int value) +{ + if (value>=0) + { + if (value < 0x0200) + return (value & ~0); + if (value < 0x0400) + return (value & ~1); + if (value < 0x0800) + return (value & ~3); + if (value < 0x1000) + return (value & ~7); + if (value < 0x2000) + return (value & ~15); + if (value < 0x4000) + return (value & ~31); + return (value & ~63); + } + /*else value < 0*/ + if (value > -0x0200) + return (~abs(value) & ~0); + if (value > -0x0400) + return (~abs(value) & ~1); + if (value > -0x0800) + return (~abs(value) & ~3); + if (value > -0x1000) + return (~abs(value) & ~7); + if (value > -0x2000) + return (~abs(value) & ~15); + if (value > -0x4000) + return (~abs(value) & ~31); + return (~abs(value) & ~63); +} +#endif + +/* first macro saves left and right channels to mono file */ +/* second macro saves left and right channels to stereo file */ +#if 0 /*MONO*/ + #ifdef SAVE_SEPARATE_CHANNELS + #define SAVE_SINGLE_CHANNEL(j) \ + { signed int pom= -(chanout[j] & PSG->pan[j*2]); \ + if (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \ + fputc((unsigned short)pom&0xff,sample[j]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[j]); } + #else + #define SAVE_SINGLE_CHANNEL(j) + #endif +#else /*STEREO*/ + #ifdef SAVE_SEPARATE_CHANNELS + #define SAVE_SINGLE_CHANNEL(j) \ + { signed int pom = -(chanout[j] & PSG->pan[j*2]); \ + if (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \ + fputc((unsigned short)pom&0xff,sample[j]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[j]); \ + pom = -(chanout[j] & PSG->pan[j*2+1]); \ + if (pom > 32767) pom = 32767; else if (pom < -32768) pom = -32768; \ + fputc((unsigned short)pom&0xff,sample[j]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[j]); \ + } + #else + #define SAVE_SINGLE_CHANNEL(j) + #endif +#endif + +/* first macro saves left and right channels to mono file */ +/* second macro saves left and right channels to stereo file */ +#if 1 /*MONO*/ + #ifdef SAVE_SAMPLE + #define SAVE_ALL_CHANNELS \ + { signed int pom = outl; \ + /*pom = acc_calc(pom);*/ \ + /*fprintf(sample[8]," %i\n",pom);*/ \ + fputc((unsigned short)pom&0xff,sample[8]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[8]); \ + } + #else + #define SAVE_ALL_CHANNELS + #endif +#else /*STEREO*/ + #ifdef SAVE_SAMPLE + #define SAVE_ALL_CHANNELS \ + { signed int pom = outl; \ + fputc((unsigned short)pom&0xff,sample[8]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[8]); \ + pom = outr; \ + fputc((unsigned short)pom&0xff,sample[8]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[8]); \ + } + #else + #define SAVE_ALL_CHANNELS + #endif +#endif + + +/* Generate samples for one of the YM2151's +* +* 'num' is the number of virtual YM2151 +* '**buffers' is table of pointers to the buffers: left and right +* 'length' is the number of samples that should be generated +*/ +void YM2151UpdateOne(int num, INT16 **buffers, int length) +{ + int i; + signed int outl,outr; + SAMP *bufL, *bufR; + + bufL = buffers[0]; + bufR = buffers[1]; + + PSG = &YMPSG[num]; + +#ifdef USE_MAME_TIMERS + /* ASG 980324 - handled by real timers now */ +#else + if (PSG->tim_B) + { + PSG->tim_B_val -= ( length << TIMER_SH ); + if (PSG->tim_B_val<=0) + { + PSG->tim_B_val += PSG->tim_B_tab[ PSG->timer_B_index ]; + if ( PSG->irq_enable & 0x08 ) + { + int oldstate = PSG->status & 3; + PSG->status |= 2; + if ((!oldstate) && (PSG->irqhandler)) (*PSG->irqhandler)(1); + } + } + } +#endif + + for (i=0; ipan[0]; + outr = chanout[0] & PSG->pan[1]; + outl += (chanout[1] & PSG->pan[2]); + outr += (chanout[1] & PSG->pan[3]); + outl += (chanout[2] & PSG->pan[4]); + outr += (chanout[2] & PSG->pan[5]); + outl += (chanout[3] & PSG->pan[6]); + outr += (chanout[3] & PSG->pan[7]); + outl += (chanout[4] & PSG->pan[8]); + outr += (chanout[4] & PSG->pan[9]); + outl += (chanout[5] & PSG->pan[10]); + outr += (chanout[5] & PSG->pan[11]); + outl += (chanout[6] & PSG->pan[12]); + outr += (chanout[6] & PSG->pan[13]); + outl += (chanout[7] & PSG->pan[14]); + outr += (chanout[7] & PSG->pan[15]); + + outl >>= FINAL_SH; + outr >>= FINAL_SH; + if (outl > MAXOUT) outl = MAXOUT; + else if (outl < MINOUT) outl = MINOUT; + if (outr > MAXOUT) outr = MAXOUT; + else if (outr < MINOUT) outr = MINOUT; + ((SAMP*)bufL)[i] = (SAMP)outl; + ((SAMP*)bufR)[i] = (SAMP)outr; + + SAVE_ALL_CHANNELS + +#ifdef USE_MAME_TIMERS + /* ASG 980324 - handled by real timers now */ +#else + /* calculate timer A */ + if (PSG->tim_A) + { + PSG->tim_A_val -= ( 1 << TIMER_SH ); + if (PSG->tim_A_val <= 0) + { + PSG->tim_A_val += PSG->tim_A_tab[ PSG->timer_A_index ]; + if (PSG->irq_enable & 0x04) + { + int oldstate = PSG->status & 3; + PSG->status |= 1; + if ((!oldstate) && (PSG->irqhandler)) (*PSG->irqhandler)(1); + } + if (PSG->irq_enable & 0x80) + PSG->csm_req = 2; /* request KEY ON / KEY OFF sequence */ + } + } +#endif + advance(); + } +} + +void YM2151SetIrqHandler(int n, void(*handler)(int irq)) +{ + YMPSG[n].irqhandler = handler; +} + +void YM2151SetPortWriteHandler(int n, write8_handler handler) +{ + YMPSG[n].porthandler = handler; +} + diff --git a/src/burn/sound/ym2151.h b/src/burn/sound/ym2151.h new file mode 100644 index 00000000..d693bfaa --- /dev/null +++ b/src/burn/sound/ym2151.h @@ -0,0 +1,81 @@ +/* +** +** File: ym2151.h - header file for software implementation of YM2151 +** FM Operator Type-M(OPM) +** +** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net) +** Some of the optimizing ideas by Tatsuyuki Satoh +** +** Version 2.150 final beta May, 11th 2002 +** +** +** I would like to thank following people for making this project possible: +** +** Beauty Planets - for making a lot of real YM2151 samples and providing +** additional informations about the chip. Also for the time spent making +** the samples and the speed of replying to my endless requests. +** +** Shigeharu Isoda - for general help, for taking time to scan his YM2151 +** Japanese Manual first of all, and answering MANY of my questions. +** +** Nao - for giving me some info about YM2151 and pointing me to Shigeharu. +** Also for creating fmemu (which I still use to test the emulator). +** +** Aaron Giles and Chris Hardy - they made some samples of one of my favourite +** arcade games so I could compare it to my emulator. +** +** Bryan McPhail and Tim (powerjaw) - for making some samples. +** +** Ishmair - for the datasheet and motivation. +*/ + +#ifndef _H_YM2151_ +#define _H_YM2151_ + +/* 16- and 8-bit samples (signed) are supported*/ +#define SAMPLE_BITS 16 + +#if (SAMPLE_BITS==16) + typedef INT16 SAMP; +#endif +#if (SAMPLE_BITS==8) + typedef signed char SAMP; +#endif + +/* +** Initialize YM2151 emulator(s). +** +** 'num' is the number of virtual YM2151's to allocate +** 'clock' is the chip clock in Hz +** 'rate' is sampling rate +*/ +int YM2151Init(int num, int clock, int rate); + +/* shutdown the YM2151 emulators*/ +void YM2151Shutdown(void); + +/* reset all chip registers for YM2151 number 'num'*/ +void YM2151ResetChip(int num); + +/* +** Generate samples for one of the YM2151's +** +** 'num' is the number of virtual YM2151 +** '**buffers' is table of pointers to the buffers: left and right +** 'length' is the number of samples that should be generated +*/ +void YM2151UpdateOne(int num, INT16 **buffers, int length); + +/* write 'v' to register 'r' on YM2151 chip number 'n'*/ +void YM2151WriteReg(int n, int r, int v); + +/* read status register on YM2151 chip number 'n'*/ +int YM2151ReadStatus(int n); + +/* set interrupt handler on YM2151 chip number 'n'*/ +void YM2151SetIrqHandler(int n, void (*handler)(int irq)); + +/* set port write handler on YM2151 chip number 'n'*/ +void YM2151SetPortWriteHandler(int n, write8_handler handler); + +#endif /*_H_YM2151_*/ diff --git a/src/burn/sound/ym2413.c b/src/burn/sound/ym2413.c new file mode 100644 index 00000000..80c71f8a --- /dev/null +++ b/src/burn/sound/ym2413.c @@ -0,0 +1,2160 @@ +/* +** +** File: ym2413.c - software implementation of YM2413 +** FM sound generator type OPLL +** +** Copyright (C) 2002 Jarek Burczynski +** +** Version 1.0 +** + + +to do: + +- make sure of the sinus amplitude bits + +- make sure of the EG resolution bits (looks like the biggest + modulation index generated by the modulator is 123, 124 = no modulation) +- find proper algorithm for attack phase of EG + +- tune up instruments ROM + +- support sample replay in test mode (it is NOT as simple as setting bit 0 + in register 0x0f and using register 0x10 for sample data). + Which games use this feature ? + + +*/ + +#include "driver.h" +#include "ym2413.h" + +#define MAME_INLINE static inline + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +/* output final shift */ +#if (SAMPLE_BITS==16) + #define FINAL_SH (0) + #define MAXOUT (+32767) + #define MINOUT (-32768) +#else + #define FINAL_SH (8) + #define MAXOUT (+127) + #define MINOUT (-128) +#endif + + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (EG timing) */ +#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ + +#define FREQ_MASK ((1<=0) + { + if (value < 0x0200) + return (value & ~0); + if (value < 0x0400) + return (value & ~1); + if (value < 0x0800) + return (value & ~3); + if (value < 0x1000) + return (value & ~7); + if (value < 0x2000) + return (value & ~15); + if (value < 0x4000) + return (value & ~31); + return (value & ~63); + } + /*else value < 0*/ + if (value > -0x0200) + return (~abs(value) & ~0); + if (value > -0x0400) + return (~abs(value) & ~1); + if (value > -0x0800) + return (~abs(value) & ~3); + if (value > -0x1000) + return (~abs(value) & ~7); + if (value > -0x2000) + return (~abs(value) & ~15); + if (value > -0x4000) + return (~abs(value) & ~31); + return (~abs(value) & ~63); +} + + +static FILE *sample[1]; + #if 0 /*save to MONO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = acc_calc(mo); \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #else /*save to STEREO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = mo; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = ro; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #define SAVE_SEPARATE_CHANNEL(j) \ + { signed int pom = outchan; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = chip->instvol_r[j]>>4; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #endif +#endif + +/*#define LOG_CYM_FILE*/ +#ifdef LOG_CYM_FILE + FILE * cymfile = NULL; +#endif + + + + +typedef struct{ + UINT32 ar; /* attack rate: AR<<2 */ + UINT32 dr; /* decay rate: DR<<2 */ + UINT32 rr; /* release rate:RR<<2 */ + UINT8 KSR; /* key scale rate */ + UINT8 ksl; /* keyscale level */ + UINT8 ksr; /* key scale rate: kcode>>KSR */ + UINT8 mul; /* multiple: mul_tab[ML] */ + + /* Phase Generator */ + UINT32 phase; /* frequency counter */ + UINT32 freq; /* frequency counter step */ + UINT8 fb_shift; /* feedback shift value */ + INT32 op1_out[2]; /* slot1 output for feedback */ + + /* Envelope Generator */ + UINT8 eg_type; /* percussive/nonpercussive mode*/ + UINT8 state; /* phase type */ + UINT32 TL; /* total level: TL << 2 */ + INT32 TLL; /* adjusted now TL */ + INT32 volume; /* envelope counter */ + UINT32 sl; /* sustain level: sl_tab[SL] */ + + UINT8 eg_sh_dp; /* (dump state) */ + UINT8 eg_sel_dp; /* (dump state) */ + UINT8 eg_sh_ar; /* (attack state) */ + UINT8 eg_sel_ar; /* (attack state) */ + UINT8 eg_sh_dr; /* (decay state) */ + UINT8 eg_sel_dr; /* (decay state) */ + UINT8 eg_sh_rr; /* (release state for non-perc.)*/ + UINT8 eg_sel_rr; /* (release state for non-perc.)*/ + UINT8 eg_sh_rs; /* (release state for perc.mode)*/ + UINT8 eg_sel_rs; /* (release state for perc.mode)*/ + + UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ + + /* LFO */ + UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ + UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ + + /* waveform select */ + unsigned int wavetable; +} YM2413_OPLL_SLOT; + +typedef struct{ + YM2413_OPLL_SLOT SLOT[2]; + /* phase generator state */ + UINT32 block_fnum; /* block+fnum */ + UINT32 fc; /* Freq. freqement base */ + UINT32 ksl_base; /* KeyScaleLevel Base step */ + UINT8 kcode; /* key code (for key scaling) */ + UINT8 sus; /* sus on/off (release speed in percussive mode)*/ +} YM2413_OPLL_CH; + +/* chip state */ +typedef struct { + YM2413_OPLL_CH P_CH[9]; /* OPLL chips have 9 channels*/ + UINT8 instvol_r[9]; /* instrument/volume (or volume/volume in percussive mode)*/ + + UINT32 eg_cnt; /* global envelope generator counter */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */ + UINT32 eg_timer_add; /* step of eg_timer */ + UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */ + + UINT8 rhythm; /* Rhythm mode */ + + /* LFO */ + UINT32 lfo_am_cnt; + UINT32 lfo_am_inc; + UINT32 lfo_pm_cnt; + UINT32 lfo_pm_inc; + + UINT32 noise_rng; /* 23 bit noise shift register */ + UINT32 noise_p; /* current noise 'phase' */ + UINT32 noise_f; /* current noise period */ + + +/* instrument settings */ +/* + 0-user instrument + 1-15 - fixed instruments + 16 -bass drum settings + 17,18 - other percussion instruments +*/ + UINT8 inst_tab[19][8]; + + /* external event callback handlers */ + OPLL_UPDATEHANDLER UpdateHandler; /* stream update handler */ + int UpdateParam; /* stream update parameter */ + + UINT32 fn_tab[1024]; /* fnumber->increment counter */ + + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ +} YM2413; + +/* key scale level */ +/* table is 3dB/octave, DV converts this into 6dB/octave */ +/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ +#define DV (0.1875/1.0) +static const UINT32 ksl_tab[8*16]= +{ + /* OCT 0 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + /* OCT 1 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, + 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, + /* OCT 2 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, + 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, + 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, + /* OCT 3 */ + 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, + 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, + 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, + 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, + /* OCT 4 */ + 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, + 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, + 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, + 10.875/DV,11.250/DV,11.625/DV,12.000/DV, + /* OCT 5 */ + 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, + 9.000/DV,10.125/DV,10.875/DV,11.625/DV, + 12.000/DV,12.750/DV,13.125/DV,13.500/DV, + 13.875/DV,14.250/DV,14.625/DV,15.000/DV, + /* OCT 6 */ + 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, + 12.000/DV,13.125/DV,13.875/DV,14.625/DV, + 15.000/DV,15.750/DV,16.125/DV,16.500/DV, + 16.875/DV,17.250/DV,17.625/DV,18.000/DV, + /* OCT 7 */ + 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, + 15.000/DV,16.125/DV,16.875/DV,17.625/DV, + 18.000/DV,18.750/DV,19.125/DV,19.500/DV, + 19.875/DV,20.250/DV,20.625/DV,21.000/DV +}; +#undef DV + +/* sustain level table (3dB per step) */ +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,45 (dB)*/ +#define SC(db) (UINT32) ( db * (1.0/ENV_STEP) ) +static const UINT32 sl_tab[16]={ + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15) +}; +#undef SC + + +#define RATE_STEPS (8) +static const unsigned char eg_inc[15*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */ +/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */ +/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; + + +#define O(a) (a*RATE_STEPS) + +/*note that there is no O(13) in this table - it's directly in the code */ +static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */ +/* 16 infinite time rates */ +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), + +/* rates 00-12 */ +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 13 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 14 */ +O( 8),O( 9),O(10),O(11), + +/* rate 15 */ +O(12),O(12),O(12),O(12), + +/* 16 dummy rates (same as 15 3) */ +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ +/*shift 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0 */ +/*mask 8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0 */ + +#define O(a) (a*1) +static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */ +/* 16 infinite time rates */ +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), + +/* rates 00-12 */ +O(13),O(13),O(13),O(13), +O(12),O(12),O(12),O(12), +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 16 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), + +}; +#undef O + + +/* multiple table */ +#define ML 2 +static const UINT8 mul_tab[16]= { +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ + 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, + 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML +}; +#undef ML + +/* TL_TAB_LEN is calculated as: +* 11 - sinus amplitude bits (Y axis) +* 2 - sinus sign bit (Y axis) +* TL_RES_LEN - sinus resolution (X axis) +*/ +#define TL_TAB_LEN (11*2*TL_RES_LEN) +static signed int tl_tab[TL_TAB_LEN]; + +#define ENV_QUIET (TL_TAB_LEN>>5) + +/* sin waveform table in 'decibel' scale */ +/* two waveforms on OPLL type chips */ +static unsigned int sin_tab[SIN_LEN * 2]; + + +/* LFO Amplitude Modulation table (verified on real YM3812) + 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples + + Length: 210 elements. + + Each of the elements has to be repeated + exactly 64 times (on 64 consecutive samples). + The whole table takes: 64 * 210 = 13440 samples. + +We use data>>1, until we find what it really is on real chip... + +*/ + +#define LFO_AM_TAB_ELEMENTS 210 + +static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { +0,0,0,0,0,0,0, +1,1,1,1, +2,2,2,2, +3,3,3,3, +4,4,4,4, +5,5,5,5, +6,6,6,6, +7,7,7,7, +8,8,8,8, +9,9,9,9, +10,10,10,10, +11,11,11,11, +12,12,12,12, +13,13,13,13, +14,14,14,14, +15,15,15,15, +16,16,16,16, +17,17,17,17, +18,18,18,18, +19,19,19,19, +20,20,20,20, +21,21,21,21, +22,22,22,22, +23,23,23,23, +24,24,24,24, +25,25,25,25, +26,26,26, +25,25,25,25, +24,24,24,24, +23,23,23,23, +22,22,22,22, +21,21,21,21, +20,20,20,20, +19,19,19,19, +18,18,18,18, +17,17,17,17, +16,16,16,16, +15,15,15,15, +14,14,14,14, +13,13,13,13, +12,12,12,12, +11,11,11,11, +10,10,10,10, +9,9,9,9, +8,8,8,8, +7,7,7,7, +6,6,6,6, +5,5,5,5, +4,4,4,4, +3,3,3,3, +2,2,2,2, +1,1,1,1 +}; + +/* LFO Phase Modulation table (verified on real YM2413) */ +static const INT8 lfo_pm_table[8*8] = { + +/* FNUM2/FNUM = 0 00xxxxxx (0x0000) */ +0, 0, 0, 0, 0, 0, 0, 0, + +/* FNUM2/FNUM = 0 01xxxxxx (0x0040) */ +1, 0, 0, 0,-1, 0, 0, 0, + +/* FNUM2/FNUM = 0 10xxxxxx (0x0080) */ +2, 1, 0,-1,-2,-1, 0, 1, + +/* FNUM2/FNUM = 0 11xxxxxx (0x00C0) */ +3, 1, 0,-1,-3,-1, 0, 1, + +/* FNUM2/FNUM = 1 00xxxxxx (0x0100) */ +4, 2, 0,-2,-4,-2, 0, 2, + +/* FNUM2/FNUM = 1 01xxxxxx (0x0140) */ +5, 2, 0,-2,-5,-2, 0, 2, + +/* FNUM2/FNUM = 1 10xxxxxx (0x0180) */ +6, 3, 0,-3,-6,-3, 0, 3, + +/* FNUM2/FNUM = 1 11xxxxxx (0x01C0) */ +7, 3, 0,-3,-7,-3, 0, 3, +}; + + + + + + +/* This is not 100% perfect yet but very close */ +/* + - multi parameters are 100% correct (instruments and drums) + - LFO PM and AM enable are 100% correct + - waveform DC and DM select are 100% correct +*/ + +static unsigned char table[19][8] = { +/* MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */ +/* 0 1 2 3 4 5 6 7 */ + {0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 }, //0 + + {0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 }, //1 + {0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 }, //2 + {0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 }, //3 + {0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 }, //4 + +//{0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 }, //5 + {0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 }, //5 + +//{0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 }, //6 + {0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 }, //6 + + {0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 }, //7 + {0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 }, //8 + {0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, //9 + +//{0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 }, //A + {0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 }, //A + + {0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 }, //B + {0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 }, //C + +//{0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 }, //D + {0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 }, //D + + {0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 }, //E + {0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 }, //F + +/* drum instruments definitions */ +/* MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR */ +/* 0 1 2 3 4 5 6 7 */ + {0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */ + {0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },/* HH(multi verified), SD(multi not used) */ + {0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */ +}; + +/* lock level of common table */ +static int num_lock = 0; + +/* work table */ +static void *cur_chip = NULL; /* current chip pointer */ +static YM2413_OPLL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2; + +static signed int output[2]; +static signed int outchan; + +static UINT32 LFO_AM; +static INT32 LFO_PM; + + +MAME_INLINE int limit( int val, int max, int min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; + + return val; +} + + +/* advance LFO to next sample */ +MAME_INLINE void advance_lfo(YM2413 *chip) +{ + /* LFO */ + chip->lfo_am_cnt += chip->lfo_am_inc; + if (chip->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ] >> 1; + + chip->lfo_pm_cnt += chip->lfo_pm_inc; + LFO_PM = (chip->lfo_pm_cnt>>LFO_SH) & 7; +} + +/* advance to next sample */ +MAME_INLINE void advance(YM2413 *chip) +{ + YM2413_OPLL_CH *CH; + YM2413_OPLL_SLOT *op; + unsigned int i; + +//profiler_mark(PROFILER_USER3); + + /* Envelope Generator */ + chip->eg_timer += chip->eg_timer_add; + + while (chip->eg_timer >= chip->eg_timer_overflow) + { + chip->eg_timer -= chip->eg_timer_overflow; + + chip->eg_cnt++; + + for (i=0; i<9*2; i++) + { + CH = &chip->P_CH[i/2]; + + op = &CH->SLOT[i&1]; + + switch(op->state) + { + + case EG_DMP: /* dump phase */ + /*dump phase is performed by both operators in each channel*/ + /*when CARRIER envelope gets down to zero level, + ** phases in BOTH opearators are reset (at the same time ?) + */ + if ( !(chip->eg_cnt & ((1<eg_sh_dp)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_dp + ((chip->eg_cnt>>op->eg_sh_dp)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_ATT; + /* restart Phase Generator */ + op->phase = 0; + } + } + break; + + case EG_ATT: /* attack phase */ + if ( !(chip->eg_cnt & ((1<eg_sh_ar)-1) ) ) + { + op->volume += (~op->volume * + (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)]) + ) >>2; + + if (op->volume <= MIN_ATT_INDEX) + { + op->volume = MIN_ATT_INDEX; + op->state = EG_DEC; + } + } + break; + + case EG_DEC: /* decay phase */ + if ( !(chip->eg_cnt & ((1<eg_sh_dr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)]; + + if ( op->volume >= op->sl ) + op->state = EG_SUS; + } + break; + + case EG_SUS: /* sustain phase */ + /* this is important behaviour: + one can change percusive/non-percussive modes on the fly and + the chip will remain in sustain phase - verified on real YM3812 */ + + if(op->eg_type) /* non-percussive mode (sustained tone) */ + { + /* do nothing */ + } + else /* percussive mode */ + { + /* during sustain phase chip adds Release Rate (in percussive mode) */ + if ( !(chip->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)]; + + if ( op->volume >= MAX_ATT_INDEX ) + op->volume = MAX_ATT_INDEX; + } + /* else do nothing in sustain phase */ + } + break; + + case EG_REL: /* release phase */ + /* exclude modulators in melody channels from performing anything in this mode*/ + /* allowed are only carriers in melody mode and rhythm slots in rhythm mode */ + + /*This table shows which operators and on what conditions are allowed to perform EG_REL: + (a) - always perform EG_REL + (n) - never perform EG_REL + (r) - perform EG_REL in Rhythm mode ONLY + 0: 0 (n), 1 (a) + 1: 2 (n), 3 (a) + 2: 4 (n), 5 (a) + 3: 6 (n), 7 (a) + 4: 8 (n), 9 (a) + 5: 10(n), 11(a) + 6: 12(r), 13(a) + 7: 14(r), 15(a) + 8: 16(r), 17(a) + */ + if ( (i&1) || ((chip->rhythm&0x20) && (i>=12)) )/* exclude modulators */ + { + if(op->eg_type) /* non-percussive mode (sustained tone) */ + /*this is correct: use RR when SUS = OFF*/ + /*and use RS when SUS = ON*/ + { + if (CH->sus) + { + if ( !(chip->eg_cnt & ((1<eg_sh_rs)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)]; + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + } + } + else + { + if ( !(chip->eg_cnt & ((1<eg_sh_rr)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)]; + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + } + } + } + else /* percussive mode */ + { + if ( !(chip->eg_cnt & ((1<eg_sh_rs)-1) ) ) + { + op->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)]; + if ( op->volume >= MAX_ATT_INDEX ) + { + op->volume = MAX_ATT_INDEX; + op->state = EG_OFF; + } + } + } + } + break; + + default: + break; + } + } + } + +//profiler_mark(PROFILER_END); + +//profiler_mark(PROFILER_USER4); + + for (i=0; i<9*2; i++) + { + CH = &chip->P_CH[i/2]; + op = &CH->SLOT[i&1]; + + /* Phase Generator */ + if(op->vib) + { + UINT8 block; + + unsigned int fnum_lfo = 8*((CH->block_fnum&0x01c0) >> 6); + unsigned int block_fnum = CH->block_fnum * 2; + signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + fnum_lfo ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + block_fnum += lfo_fn_table_index_offset; + block = (block_fnum&0x1c00) >> 10; + op->phase += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; + } + else /* LFO phase modulation = zero */ + { + op->phase += op->freq; + } + } + else /* LFO phase modulation disabled for this operator */ + { + op->phase += op->freq; + } + } + + /* The Noise Generator of the YM3812 is 23-bit shift register. + * Period is equal to 2^23-2 samples. + * Register works at sampling frequency of the chip, so output + * can change on every sample. + * + * Output of the register and input to the bit 22 is: + * bit0 XOR bit14 XOR bit15 XOR bit22 + * + * Simply use bit 22 as the noise output. + */ + + chip->noise_p += chip->noise_f; + i = chip->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ + chip->noise_p &= FREQ_MASK; + while (i) + { + /* + UINT32 j; + j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1; + chip->noise_rng = (j<<22) | (chip->noise_rng>>1); + */ + + /* + Instead of doing all the logic operations above, we + use a trick here (and use bit 0 as the noise output). + The difference is only that the noise bit changes one + step ahead. This doesn't matter since we don't know + what is real state of the noise_rng after the reset. + */ + + if (chip->noise_rng & 1) chip->noise_rng ^= 0x800302; + chip->noise_rng >>= 1; + + i--; + } +//profiler_mark(PROFILER_END); +} + + +MAME_INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) +{ + UINT32 p; + + p = (env<<5) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<17))) >> FREQ_SH ) & SIN_MASK) ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +MAME_INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) +{ + UINT32 p; + INT32 i; + + i = (phase & ~FREQ_MASK) + pm; + +/*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, phase>>FREQ_SH, pm);*/ + + p = (env<<5) + sin_tab[ wave_tab + ((i>>FREQ_SH) & SIN_MASK)]; + +/*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/ + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + + +#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask)) + +/* calculate output */ +MAME_INLINE void chan_calc( YM2413_OPLL_CH *CH ) +{ + YM2413_OPLL_SLOT *SLOT; + unsigned int env; + signed int out; + signed int phase_modulation; /* phase modulation input (SLOT 2) */ + + + /* SLOT 1 */ + SLOT = &CH->SLOT[SLOT1]; + env = volume_calc(SLOT); + out = SLOT->op1_out[0] + SLOT->op1_out[1]; + + SLOT->op1_out[0] = SLOT->op1_out[1]; + phase_modulation = SLOT->op1_out[0]; + + SLOT->op1_out[1] = 0; + + if( env < ENV_QUIET ) + { + if (!SLOT->fb_shift) + out = 0; + SLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<fb_shift), SLOT->wavetable ); + } + + /* SLOT 2 */ + +outchan=0; + + SLOT++; + env = volume_calc(SLOT); + if( env < ENV_QUIET ) + { + signed int outp = op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable); + output[0] += outp; + outchan = outp; + //output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable); + } +} + +/* + operators used in the rhythm sounds generation process: + + Envelope Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal + 6 / 0 12 50 70 90 f0 + + 6 / 1 15 53 73 93 f3 + + 7 / 0 13 51 71 91 f1 + + 7 / 1 16 54 74 94 f4 + + 8 / 0 14 52 72 92 f2 + + 8 / 1 17 55 75 95 f5 + + + Phase Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number MULTIPLE Drum Hat Drum Tom Cymbal + 6 / 0 12 30 + + 6 / 1 15 33 + + 7 / 0 13 31 + + + + 7 / 1 16 34 ----- n o t u s e d ----- + 8 / 0 14 32 + + 8 / 1 17 35 + + + +channel operator register number Bass High Snare Tom Top +number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal + 6 12,15 B6 A6 + + + 7 13,16 B7 A7 + + + + + 8 14,17 B8 A8 + + + + +*/ + +/* calculate rhythm */ + +MAME_INLINE void rhythm_calc( YM2413_OPLL_CH *CH, unsigned int noise ) +{ + YM2413_OPLL_SLOT *SLOT; + signed int out; + unsigned int env; + signed int phase_modulation; /* phase modulation input (SLOT 2) */ + + + /* Bass Drum (verified on real YM3812): + - depends on the channel 6 'connect' register: + when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) + when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored + - output sample always is multiplied by 2 + */ + + + /* SLOT 1 */ + SLOT = &CH[6].SLOT[SLOT1]; + env = volume_calc(SLOT); + + out = SLOT->op1_out[0] + SLOT->op1_out[1]; + SLOT->op1_out[0] = SLOT->op1_out[1]; + + phase_modulation = SLOT->op1_out[0]; + + SLOT->op1_out[1] = 0; + if( env < ENV_QUIET ) + { + if (!SLOT->fb_shift) + out = 0; + SLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<fb_shift), SLOT->wavetable ); + } + + /* SLOT 2 */ + SLOT++; + env = volume_calc(SLOT); + if( env < ENV_QUIET ) + output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) * 2; + + + /* Phase generation is based on: */ + // HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) + // SD (16) channel 7->slot 1 + // TOM (14) channel 8->slot 1 + // TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) + + /* Envelope generation based on: */ + // HH channel 7->slot1 + // SD channel 7->slot2 + // TOM channel 8->slot1 + // TOP channel 8->slot2 + + + /* The following formulas can be well optimized. + I leave them in direct form for now (in case I've missed something). + */ + + /* High Hat (verified on real YM3812) */ + env = volume_calc(SLOT7_1); + if( env < ENV_QUIET ) + { + + /* high hat phase generation: + phase = d0 or 234 (based on frequency only) + phase = 34 or 2d0 (based on noise) + */ + + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0xd0; */ + /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ + UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e | bit5e); + + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ + if (res2) + phase = (0x200|(0xd0>>2)); + + + /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ + /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ + if (phase&0x200) + { + if (noise) + phase = 0x200|0xd0; + } + else + /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ + /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ + { + if (noise) + phase = 0xd0>>2; + } + + output[1] += op_calc(phase<wavetable) * 2; + } + + /* Snare Drum (verified on real YM3812) */ + env = volume_calc(SLOT7_2); + if( env < ENV_QUIET ) + { + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit8 = ((SLOT7_1->phase>>FREQ_SH)>>8)&1; + + /* when bit8 = 0 phase = 0x100; */ + /* when bit8 = 1 phase = 0x200; */ + UINT32 phase = bit8 ? 0x200 : 0x100; + + /* Noise bit XOR'es phase by 0x100 */ + /* when noisebit = 0 pass the phase from calculation above */ + /* when noisebit = 1 phase ^= 0x100; */ + /* in other words: phase ^= (noisebit<<8); */ + if (noise) + phase ^= 0x100; + + output[1] += op_calc(phase<wavetable) * 2; + } + + /* Tom Tom (verified on real YM3812) */ + env = volume_calc(SLOT8_1); + if( env < ENV_QUIET ) + output[1] += op_calc(SLOT8_1->phase, env, 0, SLOT8_1->wavetable) * 2; + + /* Top Cymbal (verified on real YM2413) */ + env = volume_calc(SLOT8_2); + if( env < ENV_QUIET ) + { + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->phase>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->phase>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->phase>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0x100; */ + /* when res1 = 1 phase = 0x200 | 0x100; */ + UINT32 phase = res1 ? 0x300 : 0x100; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->phase>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->phase>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e | bit5e); + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | 0x100; */ + if (res2) + phase = 0x300; + + output[1] += op_calc(phase<wavetable) * 2; + } + +} + + +/* generic table initialize */ +static int init_tables(void) +{ + signed int i,x; + signed int n; + double o,m; + + + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + for (i=1; i<11; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + #if 0 + logerror("tl %04i", x*2); + for (i=0; i<11; i++) + logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] ); + logerror("\n"); + #endif + } + /*logerror("ym2413.c: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ + + + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + /* waveform 0: standard sinus */ + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + + /*logerror("ym2413.c: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ + + + /* waveform 1: __ __ */ + /* / \____/ \____*/ + /* output only first half of the sinus waveform (positive one) */ + if (i & (1<<(SIN_BITS-1)) ) + sin_tab[1*SIN_LEN+i] = TL_TAB_LEN; + else + sin_tab[1*SIN_LEN+i] = sin_tab[i]; + + /*logerror("ym2413.c: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );*/ + } +#if 0 + logerror("YM2413.C: ENV_QUIET= %08x (*32=%08x)\n", ENV_QUIET, ENV_QUIET*32 ); + for (i=0; ifreqbase = (chip->rate) ? ((double)chip->clock / 72.0) / chip->rate : 0; +#if 0 + chip->rate = (double)chip->clock / 72.0; + chip->freqbase = 1.0; + logerror("freqbase=%f\n", chip->freqbase); +#endif + + + + /* make fnumber -> increment counter table */ + for( i = 0 ; i < 1024; i++ ) + { + /* OPLL (YM2413) phase increment counter = 18bit */ + + chip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ +#if 0 + logerror("ym2413.c: fn_tab[%4i] = %08x (dec=%8i)\n", + i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 ); +#endif + } + +#if 0 + for( i=0 ; i < 16 ; i++ ) + { + logerror("ym2413.c: sl_tab[%i] = %08x\n", i, sl_tab[i] ); + } + for( i=0 ; i < 8 ; i++ ) + { + int j; + logerror("ym2413.c: ksl_tab[oct=%2i] =",i); + for (j=0; j<16; j++) + { + logerror("%08x ", ksl_tab[i*16+j] ); + } + logerror("\n"); + } +#endif + + + /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ + /* One entry from LFO_AM_TABLE lasts for 64 samples */ + chip->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase; + + /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ + chip->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase; + + /*logerror ("chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\n", chip->lfo_am_inc, chip->lfo_pm_inc);*/ + + /* Noise generator: a step takes 1 sample */ + chip->noise_f = (1.0 / 1.0) * (1<freqbase; + /*logerror("YM2413init noise_f=%8x\n", chip->noise_f);*/ + + chip->eg_timer_add = (1<freqbase; + chip->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, chip->eg_timer_overflow);*/ + +} + +MAME_INLINE void KEY_ON(YM2413_OPLL_SLOT *SLOT, UINT32 key_set) +{ + if( !SLOT->key ) + { + /* do NOT restart Phase Generator (verified on real YM2413)*/ + /* phase -> Dump */ + SLOT->state = EG_DMP; + } + SLOT->key |= key_set; +} + +MAME_INLINE void KEY_OFF(YM2413_OPLL_SLOT *SLOT, UINT32 key_clr) +{ + if( SLOT->key ) + { + SLOT->key &= key_clr; + + if( !SLOT->key ) + { + /* phase -> Release */ + if (SLOT->state>EG_REL) + SLOT->state = EG_REL; + } + } +} + +/* update phase increment counter of operator (also update the EG rates if necessary) */ +MAME_INLINE void CALC_FCSLOT(YM2413_OPLL_CH *CH,YM2413_OPLL_SLOT *SLOT) +{ + int ksr; + UINT32 SLOT_rs; + UINT32 SLOT_dp; + + /* (frequency) phase increment counter */ + SLOT->freq = CH->fc * SLOT->mul; + ksr = CH->kcode >> SLOT->KSR; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ar + SLOT->ksr) < 16+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 13*RATE_STEPS; + } + SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; + SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; + + } + + if (CH->sus) + SLOT_rs = 16 + (5<<2); + else + SLOT_rs = 16 + (7<<2); + + SLOT->eg_sh_rs = eg_rate_shift [SLOT_rs + SLOT->ksr ]; + SLOT->eg_sel_rs = eg_rate_select[SLOT_rs + SLOT->ksr ]; + + SLOT_dp = 16 + (13<<2); + SLOT->eg_sh_dp = eg_rate_shift [SLOT_dp + SLOT->ksr ]; + SLOT->eg_sel_dp = eg_rate_select[SLOT_dp + SLOT->ksr ]; +} + +/* set multi,am,vib,EG-TYP,KSR,mul */ +MAME_INLINE void set_mul(YM2413 *chip,int slot,int v) +{ + YM2413_OPLL_CH *CH = &chip->P_CH[slot/2]; + YM2413_OPLL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->mul = mul_tab[v&0x0f]; + SLOT->KSR = (v&0x10) ? 0 : 2; + SLOT->eg_type = (v&0x20); + SLOT->vib = (v&0x40); + SLOT->AMmask = (v&0x80) ? ~0 : 0; + CALC_FCSLOT(CH,SLOT); +} + +/* set ksl, tl */ +MAME_INLINE void set_ksl_tl(YM2413 *chip,int chan,int v) +{ + int ksl; + YM2413_OPLL_CH *CH = &chip->P_CH[chan]; +/* modulator */ + YM2413_OPLL_SLOT *SLOT = &CH->SLOT[SLOT1]; + + ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */ + + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TL = (v&0x3f)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); +} + +/* set ksl , waveforms, feedback */ +MAME_INLINE void set_ksl_wave_fb(YM2413 *chip,int chan,int v) +{ + int ksl; + YM2413_OPLL_CH *CH = &chip->P_CH[chan]; +/* modulator */ + YM2413_OPLL_SLOT *SLOT = &CH->SLOT[SLOT1]; + SLOT->wavetable = ((v&0x08)>>3)*SIN_LEN; + SLOT->fb_shift = (v&7) ? (v&7) + 8 : 0; + +/*carrier*/ + SLOT = &CH->SLOT[SLOT2]; + ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */ + + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + + SLOT->wavetable = ((v&0x10)>>4)*SIN_LEN; +} + +/* set attack rate & decay rate */ +MAME_INLINE void set_ar_dr(YM2413 *chip,int slot,int v) +{ + YM2413_OPLL_CH *CH = &chip->P_CH[slot/2]; + YM2413_OPLL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0; + + if ((SLOT->ar + SLOT->ksr) < 16+62) + { + SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + else + { + SLOT->eg_sh_ar = 0; + SLOT->eg_sel_ar = 13*RATE_STEPS; + } + + SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; + SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; +} + +/* set sustain level & release rate */ +MAME_INLINE void set_sl_rr(YM2413 *chip,int slot,int v) +{ + YM2413_OPLL_CH *CH = &chip->P_CH[slot/2]; + YM2413_OPLL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->sl = sl_tab[ v>>4 ]; + + SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; + SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; +} + +static void load_instrument(YM2413 *chip, UINT32 chan, UINT32 slot, UINT8* inst ) +{ + set_mul (chip, slot, inst[0]); + set_mul (chip, slot+1, inst[1]); + set_ksl_tl (chip, chan, inst[2]); + set_ksl_wave_fb (chip, chan, inst[3]); + set_ar_dr (chip, slot, inst[4]); + set_ar_dr (chip, slot+1, inst[5]); + set_sl_rr (chip, slot, inst[6]); + set_sl_rr (chip, slot+1, inst[7]); +} +static void update_instrument_zero(YM2413 *chip, UINT8 r ) +{ + UINT8* inst = &chip->inst_tab[0][0]; /* point to user instrument */ + UINT32 chan; + UINT32 chan_max; + + chan_max = 9; + if (chip->rhythm & 0x20) + chan_max=6; + + switch(r) + { + case 0: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_mul (chip, chan*2, inst[0]); + } + } + break; + case 1: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_mul (chip, chan*2+1,inst[1]); + } + } + break; + case 2: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_ksl_tl (chip, chan, inst[2]); + } + } + break; + case 3: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_ksl_wave_fb (chip, chan, inst[3]); + } + } + break; + case 4: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_ar_dr (chip, chan*2, inst[4]); + } + } + break; + case 5: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_ar_dr (chip, chan*2+1,inst[5]); + } + } + break; + case 6: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_sl_rr (chip, chan*2, inst[6]); + } + } + break; + case 7: + for (chan=0; chaninstvol_r[chan]&0xf0)==0) + { + set_sl_rr (chip, chan*2+1,inst[7]); + } + } + break; + } +} + +/* write a value v to register r on chip chip */ +static void OPLLWriteReg(YM2413 *chip, int r, int v) +{ + YM2413_OPLL_CH *CH; + YM2413_OPLL_SLOT *SLOT; + UINT8 *inst; + int chan; + int slot; + + /* adjust bus to 8 bits */ + r &= 0xff; + v &= 0xff; + + +#ifdef LOG_CYM_FILE + if ((cymfile) && (r!=8) ) + { + fputc( (unsigned char)r, cymfile ); + fputc( (unsigned char)v, cymfile ); + } +#endif + + + switch(r&0xf0) + { + case 0x00: /* 00-0f:control */ + { + switch(r&0x0f) + { + case 0x00: /* AM/VIB/EGTYP/KSR/MULTI (modulator) */ + case 0x01: /* AM/VIB/EGTYP/KSR/MULTI (carrier) */ + case 0x02: /* Key Scale Level, Total Level (modulator) */ + case 0x03: /* Key Scale Level, carrier waveform, modulator waveform, Feedback */ + case 0x04: /* Attack, Decay (modulator) */ + case 0x05: /* Attack, Decay (carrier) */ + case 0x06: /* Sustain, Release (modulator) */ + case 0x07: /* Sustain, Release (carrier) */ + chip->inst_tab[0][r & 0x07] = v; + update_instrument_zero(chip,r&7); + break; + + case 0x0e: /* x, x, r,bd,sd,tom,tc,hh */ + { + if(v&0x20) + { + if ((chip->rhythm&0x20)==0) + /*rhythm off to on*/ + { + logerror("YM2413: Rhythm mode enable\n"); + + /* Load instrument settings for channel seven(chan=6 since we're zero based). (Bass drum) */ + chan = 6; + inst = &chip->inst_tab[16][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + /* Load instrument settings for channel eight. (High hat and snare drum) */ + chan = 7; + inst = &chip->inst_tab[17][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + CH = &chip->P_CH[chan]; + SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH */ + SLOT->TL = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + + /* Load instrument settings for channel nine. (Tom-tom and top cymbal) */ + chan = 8; + inst = &chip->inst_tab[18][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + CH = &chip->P_CH[chan]; + SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is TOM */ + SLOT->TL = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + } + /* BD key on/off */ + if(v&0x10) + { + KEY_ON (&chip->P_CH[6].SLOT[SLOT1], 2); + KEY_ON (&chip->P_CH[6].SLOT[SLOT2], 2); + } + else + { + KEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2); + KEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2); + } + /* HH key on/off */ + if(v&0x01) KEY_ON (&chip->P_CH[7].SLOT[SLOT1], 2); + else KEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2); + /* SD key on/off */ + if(v&0x08) KEY_ON (&chip->P_CH[7].SLOT[SLOT2], 2); + else KEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2); + /* TOM key on/off */ + if(v&0x04) KEY_ON (&chip->P_CH[8].SLOT[SLOT1], 2); + else KEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY key on/off */ + if(v&0x02) KEY_ON (&chip->P_CH[8].SLOT[SLOT2], 2); + else KEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2); + } + else + { + if ((chip->rhythm&0x20)==1) + /*rhythm on to off*/ + { + logerror("YM2413: Rhythm mode disable\n"); + /* Load instrument settings for channel seven(chan=6 since we're zero based).*/ + chan = 6; + inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + /* Load instrument settings for channel eight.*/ + chan = 7; + inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + /* Load instrument settings for channel nine.*/ + chan = 8; + inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + } + /* BD key off */ + KEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2); + KEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2); + /* HH key off */ + KEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2); + /* SD key off */ + KEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2); + /* TOM key off */ + KEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY off */ + KEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2); + } + chip->rhythm = v&0x3f; + } + break; + } + } + break; + + case 0x10: + case 0x20: + { + int block_fnum; + + chan = r&0x0f; + + if (chan >= 9) + chan -= 9; /* verified on real YM2413 */ + + CH = &chip->P_CH[chan]; + + if(r&0x10) + { /* 10-18: FNUM 0-7 */ + block_fnum = (CH->block_fnum&0x0f00) | v; + } + else + { /* 20-28: suson, keyon, block, FNUM 8 */ + block_fnum = ((v&0x0f)<<8) | (CH->block_fnum&0xff); + + if(v&0x10) + { + KEY_ON (&CH->SLOT[SLOT1], 1); + KEY_ON (&CH->SLOT[SLOT2], 1); + } + else + { + KEY_OFF(&CH->SLOT[SLOT1],~1); + KEY_OFF(&CH->SLOT[SLOT2],~1); + } + + + if (CH->sus!=(v&0x20)) + logerror("chan=%i sus=%2x\n",chan,v&0x20); + + CH->sus = v & 0x20; + } + /* update */ + if(CH->block_fnum != block_fnum) + { + UINT8 block; + + CH->block_fnum = block_fnum; + + /* BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB */ + CH->kcode = (block_fnum&0x0f00)>>8; + + CH->ksl_base = ksl_tab[block_fnum>>5]; + + block_fnum = block_fnum * 2; + block = (block_fnum&0x1c00) >> 10; + CH->fc = chip->fn_tab[block_fnum&0x03ff] >> (7-block); + + /* refresh Total Level in both SLOTs of this channel */ + CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); + CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); + + /* refresh frequency counter in both SLOTs of this channel */ + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); + } + } + break; + + case 0x30: /* inst 4 MSBs, VOL 4 LSBs */ + { + UINT8 old_instvol; + + chan = r&0x0f; + + if (chan >= 9) + chan -= 9; /* verified on real YM2413 */ + + old_instvol = chip->instvol_r[chan]; + chip->instvol_r[chan] = v; /* store for later use */ + + CH = &chip->P_CH[chan]; + SLOT = &CH->SLOT[SLOT2]; /* carrier */ + SLOT->TL = ((v&0x0f)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + + + /*check wether we are in rhythm mode and handle instrument/volume register accordingly*/ + if ((chan>=6) && (chip->rhythm&0x20)) + { + /* we're in rhythm mode*/ + + if (chan>=7) /* only for channel 7 and 8 (channel 6 is handled in usual way)*/ + { + SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH(chan=7) or TOM(chan=8) */ + SLOT->TL = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + } + } + else + { + if ( (old_instvol&0xf0) == (v&0xf0) ) + return; + + inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0]; + slot = chan*2; + + load_instrument(chip, chan, slot, inst); + + #if 0 + logerror("YM2413: chan#%02i inst=%02i: (r=%2x, v=%2x)\n",chan,v>>4,r,v); + logerror(" 0:%2x 1:%2x\n",inst[0],inst[1]); logerror(" 2:%2x 3:%2x\n",inst[2],inst[3]); + logerror(" 4:%2x 5:%2x\n",inst[4],inst[5]); logerror(" 6:%2x 7:%2x\n",inst[6],inst[7]); + #endif + } + } + break; + + default: + break; + } +} + +#ifdef LOG_CYM_FILE +static void cymfile_callback (int n) +{ + if (cymfile) + { + fputc( (unsigned char)8, cymfile ); + } +} +#endif + +/* lock/unlock for common table */ +static int OPLL_LockTable(void) +{ + num_lock++; + if(num_lock>1) return 0; + + /* first time */ + + cur_chip = NULL; + /* allocate total level table (128kb space) */ + if( !init_tables() ) + { + num_lock--; + return -1; + } + +#ifdef LOG_CYM_FILE + cymfile = fopen("2413_.cym","wb"); + if (cymfile) + timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ + else + logerror("Could not create file 2413_.cym\n"); +#endif + + return 0; +} + +static void OPLL_UnLockTable(void) +{ + if(num_lock) num_lock--; + if(num_lock) return; + + /* last time */ + + cur_chip = NULL; + OPLCloseTable(); + +#ifdef LOG_CYM_FILE + fclose (cymfile); + cymfile = NULL; +#endif + +} + +static void OPLLResetChip(YM2413 *chip) +{ + int c,s; + int i; + + chip->eg_timer = 0; + chip->eg_cnt = 0; + + chip->noise_rng = 1; /* noise shift register */ + + + /* setup instruments table */ + for (i=0; i<19; i++) + { + for (c=0; c<8; c++) + { + chip->inst_tab[i][c] = table[i][c]; + } + } + + + /* reset with register write */ + OPLLWriteReg(chip,0x0f,0); /*test reg*/ + for(i = 0x3f ; i >= 0x10 ; i-- ) OPLLWriteReg(chip,i,0x00); + + /* reset operator parameters */ + for( c = 0 ; c < 9 ; c++ ) + { + YM2413_OPLL_CH *CH = &chip->P_CH[c]; + for(s = 0 ; s < 2 ; s++ ) + { + /* wave table */ + CH->SLOT[s].wavetable = 0; + CH->SLOT[s].state = EG_OFF; + CH->SLOT[s].volume = MAX_ATT_INDEX; + } + } +} + +/* Create one of virtual YM2413 */ +/* 'clock' is chip clock in Hz */ +/* 'rate' is sampling rate */ +static YM2413 *OPLLCreate(int clock, int rate) +{ + char *ptr; + YM2413 *chip; + int state_size; + + if (OPLL_LockTable() ==-1) return NULL; + + /* calculate chip state size */ + state_size = sizeof(YM2413); + + /* allocate memory block */ + ptr = malloc(state_size); + + if (ptr==NULL) + return NULL; + + /* clear */ + memset(ptr,0,state_size); + + chip = (YM2413 *)ptr; + + chip->clock = clock; + chip->rate = rate; + + /* init global tables */ + OPLL_initalize(chip); + + /* reset chip */ + OPLLResetChip(chip); + return chip; +} + +/* Destroy one of virtual YM3812 */ +static void OPLLDestroy(YM2413 *chip) +{ + OPLL_UnLockTable(); + if (chip) { + free(chip); + chip = NULL; + } +} + +/* Option handlers */ + +static void OPLLSetUpdateHandler(YM2413 *chip,OPLL_UPDATEHANDLER UpdateHandler,int param) +{ + chip->UpdateHandler = UpdateHandler; + chip->UpdateParam = param; +} + +/* YM3812 I/O interface */ +static void OPLLWrite(YM2413 *chip,int a,int v) +{ + if( !(a&1) ) + { /* address port */ + chip->address = v & 0xff; + } + else + { /* data port */ + if(chip->UpdateHandler) chip->UpdateHandler(chip->UpdateParam,0); + OPLLWriteReg(chip,chip->address,v); + } +} + +static unsigned char OPLLRead(YM2413 *chip,int a) +{ + if( !(a&1) ) + { + /* status port */ + return chip->status; + } + return 0xff; +} + + + + + +#define MAX_OPLL_CHIPS 4 + + +static YM2413 *OPLL_YM2413[MAX_OPLL_CHIPS]; /* array of pointers to the YM2413's */ +static int YM2413NumChips = 0; /* number of chips */ + +int YM2413Init(int num, int clock, int rate) +{ + int i; + + if (YM2413NumChips) + return -1; /* duplicate init. */ + + YM2413NumChips = num; + + for (i = 0;i < YM2413NumChips; i++) + { + /* emulator create */ + OPLL_YM2413[i] = OPLLCreate(clock, rate); + if(OPLL_YM2413[i] == NULL) + { + /* it's really bad - we run out of memeory */ + YM2413NumChips = 0; + return -1; + } + } + + return 0; +} + +void YM2413Shutdown(void) +{ + int i; + + for (i = 0;i < YM2413NumChips; i++) + { + /* emulator shutdown */ + if(OPLL_YM2413[i]) + OPLLDestroy(OPLL_YM2413[i]); + OPLL_YM2413[i] = NULL; + } + YM2413NumChips = 0; +} + +void YM2413ResetChip(int which) +{ + OPLLResetChip(OPLL_YM2413[which]); +} + +void YM2413Write(int which, int a, int v) +{ + OPLLWrite(OPLL_YM2413[which], a, v); +} + +unsigned char YM2413Read(int which, int a) +{ + return OPLLRead(OPLL_YM2413[which], a) & 0x03 ; +} + +void YM2413SetUpdateHandler(int which,OPLL_UPDATEHANDLER UpdateHandler,int param) +{ + OPLLSetUpdateHandler(OPLL_YM2413[which], UpdateHandler, param); +} + + +/* +** Generate samples for one of the YM2413's +** +** 'which' is the virtual YM2413 number +** '*buffer' is the output buffer pointer +** 'length' is the number of samples that should be generated +*/ +void YM2413UpdateOne(int which, INT16 **buffers, int length) +{ + YM2413 *chip = OPLL_YM2413[which]; + UINT8 rhythm = chip->rhythm&0x20; + SAMP *bufMO = buffers[0]; + SAMP *bufRO = buffers[1]; + + int i; + + if( (void *)chip != cur_chip ){ + cur_chip = (void *)chip; + /* rhythm slots */ + SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2]; + } + + + for( i=0; i < length ; i++ ) + { + int mo,ro; + + output[0] = 0; + output[1] = 0; + + advance_lfo(chip); + + /* FM part */ + chan_calc(&chip->P_CH[0]); +//SAVE_SEPARATE_CHANNEL(0); + chan_calc(&chip->P_CH[1]); + chan_calc(&chip->P_CH[2]); + chan_calc(&chip->P_CH[3]); + chan_calc(&chip->P_CH[4]); + chan_calc(&chip->P_CH[5]); + + if(!rhythm) + { + chan_calc(&chip->P_CH[6]); + chan_calc(&chip->P_CH[7]); + chan_calc(&chip->P_CH[8]); + } + else /* Rhythm part */ + { + rhythm_calc(&chip->P_CH[0], (chip->noise_rng>>0)&1 ); + } + + mo = output[0]; + ro = output[1]; + + mo >>= FINAL_SH; + ro >>= FINAL_SH; + + /* limit check */ + mo = limit( mo , MAXOUT, MINOUT ); + ro = limit( ro , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + if (which==0) + { + SAVE_ALL_CHANNELS + } + #endif + + /* store to sound buffer */ + bufMO[i] = mo; + bufRO[i] = ro; + + advance(chip); + } + +} diff --git a/src/burn/sound/ym2413.h b/src/burn/sound/ym2413.h new file mode 100644 index 00000000..087727ba --- /dev/null +++ b/src/burn/sound/ym2413.h @@ -0,0 +1,29 @@ +#ifndef _H_YM2413_ +#define _H_YM2413_ + +/* select output bits size of output : 8 or 16 */ +#define SAMPLE_BITS 16 + +#if (SAMPLE_BITS==16) +typedef INT16 SAMP; +#endif +#if (SAMPLE_BITS==8) +typedef INT8 SAMP; +#endif + + + + +int YM2413Init(int num, int clock, int rate); +void YM2413Shutdown(void); +void YM2413ResetChip(int which); +void YM2413Write(int which, int a, int v); +unsigned char YM2413Read(int which, int a); +void YM2413UpdateOne(int which, INT16 **buffers, int length); + +typedef void (*OPLL_UPDATEHANDLER)(int param,int min_interval_us); + +void YM2413SetUpdateHandler(int which, OPLL_UPDATEHANDLER UpdateHandler, int param); + + +#endif /*_H_YM2413_*/ diff --git a/src/burn/sound/ymdeltat.c b/src/burn/sound/ymdeltat.c new file mode 100644 index 00000000..b3c8a0a4 --- /dev/null +++ b/src/burn/sound/ymdeltat.c @@ -0,0 +1,653 @@ +/* +** +** File: ymdeltat.c +** +** YAMAHA DELTA-T adpcm sound emulation subroutine +** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B) +** +** Base program is YM2610 emulator by Hiromitsu Shioya. +** Written by Tatsuyuki Satoh +** Improvements by Jarek Burczynski (bujar at mame dot net) +** +** +** History: +** +** 03-08-2003 Jarek Burczynski: +** - fixed BRDY flag implementation. +** +** 24-07-2003 Jarek Burczynski, Frits Hilderink: +** - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset +** +** 22-07-2003 Jarek Burczynski, Frits Hilderink: +** - fixed external memory support +** +** 15-06-2003 Jarek Burczynski: +** - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08) +** - implemented support for the Limit address register +** - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM +** - implemented external memory access (read/write) via the ADPCM data reg reads/writes +** Thanks go to Frits Hilderink for the example code. +** +** 14-06-2003 Jarek Burczynski: +** - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO +** - modified EOS handling +** +** 05-04-2003 Jarek Burczynski: +** - implemented partial support for external/processor memory on sample replay +** +** 01-12-2002 Jarek Burczynski: +** - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi +** - renamed/removed some YM_DELTAT struct fields +** +** 28-12-2001 Acho A. Tang +** - added EOS status report on ADPCM playback. +** +** 05-08-2001 Jarek Burczynski: +** - now_step is initialized with 0 at the start of play. +** +** 12-06-2001 Jarek Burczynski: +** - corrected end of sample bug in YM_DELTAT_ADPCM_CALC. +** Checked on real YM2610 chip - address register is 24 bits wide. +** Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem. +** +** TO DO: +** Check size of the address register on the other chips.... +** +** Version 0.72 +** +** sound chips that have this unit: +** YM2608 OPNA +** YM2610/B OPNB +** Y8950 MSX AUDIO +** +*/ + +#include "driver.h" +#include "state.h" +#include "ymdeltat.h" + +#define YM_DELTAT_DELTA_MAX (24576) +#define YM_DELTAT_DELTA_MIN (127) +#define YM_DELTAT_DELTA_DEF (127) + +#define YM_DELTAT_DECODE_RANGE 32768 +#define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE)) +#define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1) + + +/* Forecast to next Forecast (rate = *8) */ +/* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */ +const INT32 ym_deltat_decode_tableB1[16] = { + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9, -11, -13, -15, +}; +/* delta to next delta (rate= *64) */ +/* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */ +const INT32 ym_deltat_decode_tableB2[16] = { + 57, 57, 57, 57, 77, 102, 128, 153, + 57, 57, 57, 57, 77, 102, 128, 153 +}; + +#if 0 +void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT) +{ + logerror("BRDY_callback reached (flag set) !\n"); + + /* set BRDY bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); +} +#endif + +UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT) +{ + UINT8 v = 0; + + /* external memory read */ + if ( (DELTAT->portstate & 0xe0)==0x20 ) + { + /* two dummy reads */ + if (DELTAT->memread) + { + DELTAT->now_addr = DELTAT->start << 1; + DELTAT->memread--; + return 0; + } + + + if ( DELTAT->now_addr != (DELTAT->end<<1) ) + { + v = DELTAT->memory[DELTAT->now_addr>>1]; + + /*logerror("YM Delta-T memory read $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/ + + DELTAT->now_addr+=2; /* two nibbles at a time */ + + /* reset BRDY bit in status register, which means we are reading the memory now */ + if(DELTAT->status_reset_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + + /* setup a timer that will callback us in 10 master clock cycles for Y8950 + * in the callback set the BRDY flag to 1 , which means we have another data ready. + * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work. + */ + /* set BRDY bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + } + else + { + /* set EOS bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_EOS_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit); + } + } + + return v; +} + + +/* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */ +static UINT8 dram_rightshift[4]={3,0,0,0}; + +/* DELTA-T ADPCM write register */ +void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v) +{ + if(r>=0x10) return; + DELTAT->reg[r] = v; /* stock data */ + + switch( r ) + { + case 0x00: +/* +START: + Accessing *external* memory is started when START bit (D7) is set to "1", so + you must set all conditions needed for recording/playback before starting. + If you access *CPU-managed* memory, recording/playback starts after + read/write of ADPCM data register $08. + +REC: + 0 = ADPCM synthesis (playback) + 1 = ADPCM analysis (record) + +MEMDATA: + 0 = processor (*CPU-managed*) memory (means: using register $08) + 1 = external memory (using start/end/limit registers to access memory: RAM or ROM) + + +SPOFF: + controls output pin that should disable the speaker while ADPCM analysis + +RESET and REPEAT only work with external memory. + + +some examples: +value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: + C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register + E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register + 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register + a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register + + 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 + 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 + +*/ + /* handle emulation mode */ + if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) + { + v |= 0x20; /* YM2610 always uses external memory and doesn't even have memory flag bit. */ + } + + DELTAT->portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */ + + if( DELTAT->portstate&0x80 )/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */ + { + /* set PCM BUSY bit */ + DELTAT->PCM_BSY = 1; + + /* start ADPCM */ + DELTAT->now_step = 0; + DELTAT->acc = 0; + DELTAT->prev_acc = 0; + DELTAT->adpcml = 0; + DELTAT->adpcmd = YM_DELTAT_DELTA_DEF; + DELTAT->now_data = 0; + + } + + if( DELTAT->portstate&0x20 ) /* do we access external memory? */ + { + DELTAT->now_addr = DELTAT->start << 1; + DELTAT->memread = 2; /* two dummy reads needed before accesing external memory via register $08*/ + + /* if yes, then let's check if ADPCM memory is mapped and big enough */ + if(DELTAT->memory == 0) + { + logerror("YM Delta-T ADPCM rom not mapped\n"); + DELTAT->portstate = 0x00; + DELTAT->PCM_BSY = 0; + } + else + { + if( DELTAT->end >= DELTAT->memory_size ) /* Check End in Range */ + { + logerror("YM Delta-T ADPCM end out of range: $%08x\n", DELTAT->end); + DELTAT->end = DELTAT->memory_size - 1; + } + if( DELTAT->start >= DELTAT->memory_size ) /* Check Start in Range */ + { + logerror("YM Delta-T ADPCM start out of range: $%08x\n", DELTAT->start); + DELTAT->portstate = 0x00; + DELTAT->PCM_BSY = 0; + } + } + } + else /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */ + { + DELTAT->now_addr = 0; + } + + if( DELTAT->portstate&0x01 ) + { + DELTAT->portstate = 0x00; + + /* clear PCM BUSY bit (in status register) */ + DELTAT->PCM_BSY = 0; + + /* set BRDY flag */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + } + break; + case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */ + /* handle emulation mode */ + if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) + { + v |= 0x01; /* YM2610 always uses ROM as an external memory and doesn't tave ROM/RAM memory flag bit. */ + } + + DELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03]; + if ((DELTAT->control2 & 3) != (v & 3)) + { + /*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */ + if (DELTAT->DRAMportshift != dram_rightshift[v&3]) + { + DELTAT->DRAMportshift = dram_rightshift[v&3]; + + /* final shift value depends on chip type and memory type selected: + 8 for YM2610 (ROM only), + 5 for ROM for Y8950 and YM2608, + 5 for x8bit DRAMs for Y8950 and YM2608, + 2 for x1bit DRAMs for Y8950 and YM2608. + */ + + /* refresh addresses */ + DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift); + DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift); + DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1; + DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift); + } + } + DELTAT->control2 = v; + break; + case 0x02: /* Start Address L */ + case 0x03: /* Start Address H */ + DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift); + /*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",DELTAT->reg[0x2], DELTAT->reg[0x3],DELTAT->start );*/ + break; + case 0x04: /* Stop Address L */ + case 0x05: /* Stop Address H */ + DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift); + DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1; + /*logerror("DELTAT end : 04=%2x 05=%2x addr=%8x\n",DELTAT->reg[0x4], DELTAT->reg[0x5],DELTAT->end );*/ + break; + case 0x06: /* Prescale L (ADPCM and Record frq) */ + case 0x07: /* Prescale H */ + break; + case 0x08: /* ADPCM data */ + +/* +some examples: +value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: + C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register + E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register + 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register + a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register + + 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 + 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 + +*/ + + /* external memory write */ + if ( (DELTAT->portstate & 0xe0)==0x60 ) + { + if (DELTAT->memread) + { + DELTAT->now_addr = DELTAT->start << 1; + DELTAT->memread = 0; + } + + /*logerror("YM Delta-T memory write $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/ + + if ( DELTAT->now_addr != (DELTAT->end<<1) ) + { + DELTAT->memory[DELTAT->now_addr>>1] = v; + DELTAT->now_addr+=2; /* two nibbles at a time */ + + /* reset BRDY bit in status register, which means we are processing the write */ + if(DELTAT->status_reset_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + + /* setup a timer that will callback us in 10 master clock cycles for Y8950 + * in the callback set the BRDY flag to 1 , which means we have written the data. + * For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work. + */ + /* set BRDY bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + + } + else + { + /* set EOS bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_EOS_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit); + } + + return; + } + + /* ADPCM synthesis from CPU */ + if ( (DELTAT->portstate & 0xe0)==0x80 ) + { + DELTAT->CPU_data = v; + + /* Reset BRDY bit in status register, which means we are full of data */ + if(DELTAT->status_reset_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + return; + } + + break; + case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */ + case 0x0a: /* DELTA-N H */ + DELTAT->delta = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]); + DELTAT->step = (UINT32)( (double)(DELTAT->delta /* *(1<<(YM_DELTAT_SHIFT-16)) */ ) * (DELTAT->freqbase) ); + /*logerror("DELTAT deltan:09=%2x 0a=%2x\n",DELTAT->reg[0x9], DELTAT->reg[0xa]);*/ + break; + case 0x0b: /* Output level control (volume, linear) */ + { + INT32 oldvol = DELTAT->volume; + DELTAT->volume = (v&0xff) * (DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE; +/* v * ((1<<16)>>8) >> 15; +* thus: v * (1<<8) >> 15; +* thus: output_range must be (1 << (15+8)) at least +* v * ((1<<23)>>8) >> 15; +* v * (1<<15) >> 15; +*/ + /*logerror("DELTAT vol = %2x\n",v&0xff);*/ + if( oldvol != 0 ) + { + DELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume); + } + } + break; + case 0x0c: /* Limit Address L */ + case 0x0d: /* Limit Address H */ + DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift); + /*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",DELTAT->reg[0xc], DELTAT->reg[0xd],DELTAT->limit );*/ + break; + } +} + +void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode) +{ + DELTAT->now_addr = 0; + DELTAT->now_step = 0; + DELTAT->step = 0; + DELTAT->start = 0; + DELTAT->end = 0; + DELTAT->limit = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */ + DELTAT->volume = 0; + DELTAT->pan = &DELTAT->output_pointer[pan]; + DELTAT->acc = 0; + DELTAT->prev_acc = 0; + DELTAT->adpcmd = 127; + DELTAT->adpcml = 0; + DELTAT->emulation_mode = (UINT8)emulation_mode; + DELTAT->portstate = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x20 : 0; + DELTAT->control2 = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x01 : 0; /* default setting depends on the emulation mode. MSX demo called "facdemo_4" doesn't setup control2 register at all and still works */ + DELTAT->DRAMportshift = dram_rightshift[DELTAT->control2 & 3]; + + /* The flag mask register disables the BRDY after the reset, however + ** as soon as the mask is enabled the flag needs to be set. */ + + /* set BRDY bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); +} + +void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs) +{ + int r; + + /* to keep adpcml */ + DELTAT->volume = 0; + /* update */ + for(r=1;r<16;r++) + YM_DELTAT_ADPCM_Write(DELTAT,r,regs[r]); + DELTAT->reg[0] = regs[0]; + + /* current rom data */ + if (DELTAT->memory) + DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1) ); + +} +void YM_DELTAT_savestate(const char *statename,int num,YM_DELTAT *DELTAT) +{ +#ifdef _STATE_H + state_save_register_UINT8 (statename, num, "DeltaT.portstate", &DELTAT->portstate, 1); + state_save_register_UINT32(statename, num, "DeltaT.address" , &DELTAT->now_addr , 1); + state_save_register_UINT32(statename, num, "DeltaT.step" , &DELTAT->now_step , 1); + state_save_register_INT32 (statename, num, "DeltaT.acc" , &DELTAT->acc , 1); + state_save_register_INT32 (statename, num, "DeltaT.prev_acc" , &DELTAT->prev_acc , 1); + state_save_register_INT32 (statename, num, "DeltaT.adpcmd" , &DELTAT->adpcmd , 1); + state_save_register_INT32 (statename, num, "DeltaT.adpcml" , &DELTAT->adpcml , 1); +#endif +} + + +#define YM_DELTAT_Limit(val,max,min) \ +{ \ + if ( val > max ) val = max; \ + else if ( val < min ) val = min; \ +} + +INLINE void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT) +{ + UINT32 step; + int data; + + DELTAT->now_step += DELTAT->step; + if ( DELTAT->now_step >= (1<now_step >> YM_DELTAT_SHIFT; + DELTAT->now_step &= (1<now_addr == (DELTAT->limit<<1) ) + DELTAT->now_addr = 0; + + if ( DELTAT->now_addr == (DELTAT->end<<1) ) { /* 12-06-2001 JB: corrected comparison. Was > instead of == */ + if( DELTAT->portstate&0x10 ){ + /* repeat start */ + DELTAT->now_addr = DELTAT->start<<1; + DELTAT->acc = 0; + DELTAT->adpcmd = YM_DELTAT_DELTA_DEF; + DELTAT->prev_acc = 0; + }else{ + /* set EOS bit in status register */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_EOS_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit); + + /* clear PCM BUSY bit (reflected in status register) */ + DELTAT->PCM_BSY = 0; + + DELTAT->portstate = 0; + DELTAT->adpcml = 0; + DELTAT->prev_acc = 0; + return; + } + } + + if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f; + else + { + DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1)); + data = DELTAT->now_data >> 4; + } + + DELTAT->now_addr++; + /* 12-06-2001 JB: */ + /* YM2610 address register is 24 bits wide.*/ + /* The "+1" is there because we use 1 bit more for nibble calculations.*/ + /* WARNING: */ + /* Side effect: we should take the size of the mapped ROM into account */ + DELTAT->now_addr &= ( (1<<(24+1))-1); + + /* store accumulator value */ + DELTAT->prev_acc = DELTAT->acc; + + /* Forecast to next Forecast */ + DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8); + YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN); + + /* delta to next delta */ + DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64; + YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN ); + + /* ElSemi: Fix interpolator. */ + /*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/ + + }while(--step); + + } + + /* ElSemi: Fix interpolator. */ + DELTAT->adpcml = DELTAT->prev_acc * (int)((1<now_step); + DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step); + DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume; + + /* output for work of output channels (outd[OPNxxxx])*/ + *(DELTAT->pan) += DELTAT->adpcml; +} + + + +INLINE void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT) +{ + UINT32 step; + int data; + + DELTAT->now_step += DELTAT->step; + if ( DELTAT->now_step >= (1<now_step >> YM_DELTAT_SHIFT; + DELTAT->now_step &= (1<now_addr&1 ) + { + data = DELTAT->now_data & 0x0f; + + DELTAT->now_data = DELTAT->CPU_data; + + /* after we used CPU_data, we set BRDY bit in status register, + * which means we are ready to accept another byte of data */ + if(DELTAT->status_set_handler) + if(DELTAT->status_change_BRDY_bit) + (DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit); + } + else + { + data = DELTAT->now_data >> 4; + } + + DELTAT->now_addr++; + + /* store accumulator value */ + DELTAT->prev_acc = DELTAT->acc; + + /* Forecast to next Forecast */ + DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8); + YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN); + + /* delta to next delta */ + DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64; + YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN ); + + + }while(--step); + + } + + /* ElSemi: Fix interpolator. */ + DELTAT->adpcml = DELTAT->prev_acc * (int)((1<now_step); + DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step); + DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume; + + /* output for work of output channels (outd[OPNxxxx])*/ + *(DELTAT->pan) += DELTAT->adpcml; +} + + + +/* ADPCM B (Delta-T control type) */ +void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT) +{ + +/* +some examples: +value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning: + 80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register + a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register + C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register + E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register + + 60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08 + 20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08 + +*/ + + if ( (DELTAT->portstate & 0xe0)==0xa0 ) + { + YM_DELTAT_synthesis_from_external_memory(DELTAT); + return; + } + + if ( (DELTAT->portstate & 0xe0)==0x80 ) + { + /* ADPCM synthesis from CPU-managed memory (from reg $08) */ + YM_DELTAT_synthesis_from_CPU_memory(DELTAT); /* change output based on data in ADPCM data reg ($08) */ + return; + } + +//todo: ADPCM analysis +// if ( (DELTAT->portstate & 0xe0)==0xc0 ) +// if ( (DELTAT->portstate & 0xe0)==0xe0 ) + + return; +} + diff --git a/src/burn/sound/ymdeltat.h b/src/burn/sound/ymdeltat.h new file mode 100644 index 00000000..e8cfe763 --- /dev/null +++ b/src/burn/sound/ymdeltat.h @@ -0,0 +1,82 @@ +#ifndef __YMDELTAT_H_ +#define __YMDELTAT_H_ + +#define YM_DELTAT_SHIFT (16) + +#define YM_DELTAT_EMULATION_MODE_NORMAL 0 +#define YM_DELTAT_EMULATION_MODE_YM2610 1 + + +typedef void (*STATUS_CHANGE_HANDLER)(UINT8 which_chip, UINT8 status_bits); + + +/* DELTA-T (adpcm type B) struct */ +typedef struct deltat_adpcm_state { /* AT: rearranged and tigntened structure */ + UINT8 *memory; + INT32 *output_pointer;/* pointer of output pointers */ + INT32 *pan; /* pan : &output_pointer[pan] */ + double freqbase; +#if 0 + double write_time; /* Y8950: 10 cycles of main clock; YM2608: 20 cycles of main clock */ + double read_time; /* Y8950: 8 cycles of main clock; YM2608: 18 cycles of main clock */ +#endif + UINT32 memory_size; + int output_range; + UINT32 now_addr; /* current address */ + UINT32 now_step; /* currect step */ + UINT32 step; /* step */ + UINT32 start; /* start address */ + UINT32 limit; /* limit address */ + UINT32 end; /* end address */ + UINT32 delta; /* delta scale */ + INT32 volume; /* current volume */ + INT32 acc; /* shift Measurement value*/ + INT32 adpcmd; /* next Forecast */ + INT32 adpcml; /* current value */ + INT32 prev_acc; /* leveling value */ + UINT8 now_data; /* current rom data */ + UINT8 CPU_data; /* current data from reg 08 */ + UINT8 portstate; /* port status */ + UINT8 control2; /* control reg: SAMPLE, DA/AD, RAM TYPE (x8bit / x1bit), ROM/RAM */ + UINT8 portshift; /* address bits shift-left: + ** 8 for YM2610, + ** 5 for Y8950 and YM2608 */ + + UINT8 DRAMportshift; /* address bits shift-right: + ** 0 for ROM and x8bit DRAMs, + ** 3 for x1 DRAMs */ + + UINT8 memread; /* needed for reading/writing external memory */ + + /* handlers and parameters for the status flags support */ + STATUS_CHANGE_HANDLER status_set_handler; + STATUS_CHANGE_HANDLER status_reset_handler; + + /* note that different chips have these flags on different + ** bits of the status register + */ + UINT8 status_change_which_chip; /* this chip id */ + UINT8 status_change_EOS_bit; /* 1 on End Of Sample (record/playback/cycle time of AD/DA converting has passed)*/ + UINT8 status_change_BRDY_bit; /* 1 after recording 2 datas (2x4bits) or after reading/writing 1 data */ + UINT8 status_change_ZERO_bit; /* 1 if silence lasts for more than 290 miliseconds on ADPCM recording */ + + /* neither Y8950 nor YM2608 can generate IRQ when PCMBSY bit changes, so instead of above, + ** the statusflag gets ORed with PCM_BSY (below) (on each read of statusflag of Y8950 and YM2608) + */ + UINT8 PCM_BSY; /* 1 when ADPCM is playing; Y8950/YM2608 only */ + + UINT8 reg[16]; /* adpcm registers */ + UINT8 emulation_mode; /* which chip we're emulating */ +}YM_DELTAT; + +/*void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT);*/ + +UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT); +void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v); +void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode); +void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT); + +void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs); +void YM_DELTAT_savestate(const char *statename,int num,YM_DELTAT *DELTAT); + +#endif diff --git a/src/burn/sound/ymf278b.c b/src/burn/sound/ymf278b.c new file mode 100644 index 00000000..b0565674 --- /dev/null +++ b/src/burn/sound/ymf278b.c @@ -0,0 +1,838 @@ +/* + Timer and PCM YMF278B. The FM will be shared with the ymf262, eventually. + + This chip roughly splits the difference between the Sega 315-5560 MultiPCM + (Multi32, Model 1/2) and YMF 292-F SCSP (later Model 2, STV, Saturn, Model 3). + + By R. Belmont and O. Galibert. + + Copyright (c) 2002-2003 R. Belmont and O. Galibert. + + This software is dual-licensed: it may be used in MAME and properly licensed + MAME derivatives under the terms of the MAME license. For use outside of + MAME and properly licensed derivatives, it is available under the + terms of the GNU Lesser General Public License (LGPL), version 2.1. + You may read the LGPL at http://www.gnu.org/licenses/lgpl.html + + Changelog: + Sep. 8, 2002 - fixed ymf278b_compute_rate when OCT is negative (RB) + Dec. 11, 2002 - added ability to set non-standard clock rates (RB) + fixed envelope target for release (fixes missing + instruments in hotdebut). + Thanks to Team Japump! for MP3s from a real PCB. + fixed crash if MAME is run with no sound. + June 4, 2003 - Changed to dual-license with LGPL for use in OpenMSX. + OpenMSX contributed a bugfix where looped samples were + not being addressed properly, causing pitch fluctuation. + + --- + + Jan 2005 - All changes needed for FB Alpha are marked as !!! FBA + and contained within #if blocks + +*/ + +#include +#include "driver.h" + +#ifdef FBA /* !!! FBA */ +#include "ymf278b.h" +typedef struct { int sample_rate; } MACHINE; +MACHINE machine; +MACHINE* Machine = &machine; +#else /* !!! FBA */ +#include "cpuintrf.h" +#include "ymf278b.h" +#endif /* !!! FBA */ + +#undef VERBOSE + +typedef struct +{ + INT16 wave; /* wavetable number */ + INT16 FN; /* f-number */ + INT8 OCT; /* octave */ + INT8 PRVB; /* pseudo-reverb */ + INT8 LD; /* level direct */ + INT8 TL; /* total level */ + INT8 pan; /* panpot */ + INT8 lfo; /* LFO */ + INT8 vib; /* vibrato */ + INT8 AM; /* AM level */ + + INT8 AR; + INT8 D1R; + INT8 DL; + INT8 D2R; + INT8 RC; /* rate correction */ + INT8 RR; + + UINT32 step; /* fixed-point frequency step */ + UINT32 stepptr; /* fixed-point pointer into the sample */ + + INT8 active; /* slot keyed on */ + INT8 bits; /* width of the samples */ + UINT32 startaddr; + UINT32 loopaddr; + UINT32 endaddr; + + int env_step; + UINT32 env_vol; + UINT32 env_vol_step; + UINT32 env_vol_lim; +} YMF278BSlot; + +typedef struct +{ + YMF278BSlot slots[24]; + INT8 lsitest0; + INT8 lsitest1; + INT8 wavetblhdr; + INT8 memmode; + INT32 memadr; + + INT32 fm_l, fm_r; + INT32 pcm_l, pcm_r; + + UINT8 timer_a_count, timer_b_count, enable, current_irq; +#ifndef FBA /* !!! FBA */ + void *timer_a, *timer_b; +#endif /* !!! FBA */ + int irq_line; + + UINT8 port_A, port_B, port_C; + void (*irq_callback)(int, int); +#ifdef FBA /* !!! FBA */ + void (*timer_callback)(int, int, double); +#endif /* !!! FBA */ + + const UINT8 *rom; + float clock_ratio; +} YMF278BChip; + +static YMF278BChip YMF278B[MAX_YMF278B]; +static INT32 volume[256*4]; // precalculated attenuation values with some marging for enveloppe and pan levels +static int pan_left[16], pan_right[16]; // pan volume offsets +static INT32 mix_level[8]; + +static int ymf278b_compute_rate(YMF278BSlot *slot, int val) +{ + int res, oct; + + if(val == 0) + return 0; + if(val == 15) + return 63; + if(slot->RC != 15) + { + oct = slot->OCT; + if (oct & 8) oct |= -8; + + res = (oct+slot->RC)*2 + (slot->FN & 0x200 ? 1 : 0) + val*4; + } + else + res = val * 4; + if(res < 0) + res = 0; + else if(res > 63) + res = 63; + return res; +} + +static UINT32 ymf278_compute_decay_rate(int num) +{ + int samples; + + if (num <= 3) + samples = 0; + else if (num >= 60) + samples = 15 << 4; + else + { + samples = (15 << (21 - num / 4)) / (4 + num % 4); + if (num % 4 && num / 4 <= 11) + samples += 2; + else if (num == 51) + samples += 2; + } + + return ((UINT64)samples * Machine->sample_rate) / 44100; +} + +static void ymf278b_envelope_next(YMF278BSlot *slot, float clock_ratio) +{ + if(slot->env_step == 0) + { + // Attack + slot->env_vol = (256U << 23) - 1; + slot->env_vol_lim = 256U<<23; +#ifdef VERBOSE + logerror("YMF278B: Skipping attack (rate = %d)\n", slot->AR); +#endif + slot->env_step++; + } + if(slot->env_step == 1) + { + // Decay 1 + slot->env_vol = 0; + slot->env_step++; + if(slot->DL) + { + int rate = ymf278b_compute_rate(slot, slot->D1R); +#ifdef VERBOSE + logerror("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g\n", slot->DL, slot->D1R, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate); +#endif + if(rate<4) + slot->env_vol_step = 0; + else + slot->env_vol_step = ((slot->DL*8)<<23) / (ymf278_compute_decay_rate(rate) * clock_ratio); + slot->env_vol_lim = (slot->DL*8)<<23; + return; + } + } + if(slot->env_step == 2) + { + // Decay 2 + int rate = ymf278b_compute_rate(slot, slot->D2R); +#ifdef VERBOSE + logerror("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, current vol = %d\n", slot->D2R, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate, slot->env_vol >> 23); +#endif + if(rate<4) + slot->env_vol_step = 0; + else + slot->env_vol_step = ((256U-slot->DL*8)<<23) / (ymf278_compute_decay_rate(rate) * clock_ratio); + slot->env_vol_lim = 256U<<23; + slot->env_step++; + return; + } + if(slot->env_step == 3) + { + // Decay 2 reached -96dB +#ifdef VERBOSE + logerror("YMF278B: Voice cleared because of decay 2\n"); +#endif + slot->env_vol = 256U<<23; + slot->env_vol_step = 0; + slot->env_vol_lim = 0; + slot->active = 0; + return; + } + if(slot->env_step == 4) + { + // Release + int rate = ymf278b_compute_rate(slot, slot->RR); +#ifdef VERBOSE + logerror("YMF278B: Release, val = %d, rate = %d, delay = %g\n", slot->RR, rate, ymf278_compute_decay_rate(rate)*1000.0*clock_ratio/Machine->sample_rate); +#endif + if(rate<4) + slot->env_vol_step = 0; + else + slot->env_vol_step = ((256U<<23)-slot->env_vol) / (ymf278_compute_decay_rate(rate) * clock_ratio); + slot->env_vol_lim = 256U<<23; + slot->env_step++; + return; + } + if(slot->env_step == 5) + { + // Release reached -96dB +#ifdef VERBOSE + logerror("YMF278B: Release ends\n"); +#endif + slot->env_vol = 256U<<23; + slot->env_vol_step = 0; + slot->env_vol_lim = 0; + slot->active = 0; + return; + } +} + +void ymf278b_pcm_update(int num, INT16 **outputs, int length) +{ + int i, j; + YMF278BSlot *slot = NULL; + INT16 sample = 0; + const UINT8 *rombase; + INT32 mix[44100*2]; + INT32 *mixp; + INT32 vl, vr; + + memset(mix, 0, sizeof(mix[0])*length*2); + + rombase = YMF278B[num].rom; + + for (i = 0; i < 24; i++) + { + slot = &YMF278B[num].slots[i]; + + if (slot->active) + { + mixp = mix; + + for (j = 0; j < length; j++) + { + switch (slot->bits) + { + case 8: // 8 bit + sample = rombase[slot->startaddr + (slot->stepptr>>16)]<<8; + break; + + case 12: // 12 bit + if (slot->stepptr & 1) + sample = rombase[slot->startaddr + (slot->stepptr>>17)*3 + 2]<<8 | ((rombase[slot->startaddr + (slot->stepptr>>17)*3 + 1] << 4) & 0xf0); + else + sample = rombase[slot->startaddr + (slot->stepptr>>17)*3]<<8 | (rombase[slot->startaddr + (slot->stepptr>>17)*3 + 1] & 0xf0); + break; + + case 16: // 16 bit + sample = rombase[slot->startaddr + ((slot->stepptr>>16)*2)]<<8; + sample |= rombase[slot->startaddr + ((slot->stepptr>>16)*2) + 1]; + break; + } + + *mixp++ += (sample * volume[slot->TL+pan_left [slot->pan]+(slot->env_vol>>23)])>>17; + *mixp++ += (sample * volume[slot->TL+pan_right[slot->pan]+(slot->env_vol>>23)])>>17; + + // update frequency + slot->stepptr += slot->step; + if(slot->stepptr >= slot->endaddr) + { + slot->stepptr = slot->stepptr - slot->endaddr + slot->loopaddr; + // If the step is bigger than the loop, finish the sample forcibly + if(slot->stepptr >= slot->endaddr) + { + slot->env_vol = 256U<<23; + slot->env_vol_step = 0; + slot->env_vol_lim = 0; + slot->active = 0; + slot->stepptr = 0; + slot->step = 0; + } + } + + // update envelope + slot->env_vol += slot->env_vol_step; + if(((INT32)(slot->env_vol - slot->env_vol_lim)) >= 0) + ymf278b_envelope_next(slot, YMF278B[num].clock_ratio); + } + } + } + + mixp = mix; + vl = mix_level[YMF278B[num].pcm_l]; + vr = mix_level[YMF278B[num].pcm_r]; + for (i = 0; i < length; i++) + { + outputs[0][i] = (*mixp++ * vl) >> 16; + outputs[1][i] = (*mixp++ * vr) >> 16; + } +} + +static void ymf278b_irq_check(int num) +{ + YMF278BChip *chip = &YMF278B[num]; + int prev_line = chip->irq_line; + chip->irq_line = chip->current_irq ? ASSERT_LINE : CLEAR_LINE; + if(chip->irq_line != prev_line && chip->irq_callback) + chip->irq_callback(num, chip->irq_line); +} + +#ifdef FBA /* !!! FBA */ +int ymf278b_timer_over(int num, int timer) +{ + YMF278BChip *chip = &YMF278B[num]; + if(!(chip->enable & (0x20 << timer))) + { + chip->current_irq |= (0x20 << timer); + ymf278b_irq_check(num); + } + + return 0; +} +#else /* !!! FBA */ +static void ymf278b_timer_a_tick(int num) +{ + YMF278BChip *chip = &YMF278B[num]; + if(!(chip->enable & 0x40)) + { + chip->current_irq |= 0x40; + ymf278b_irq_check(num); + } +} + +static void ymf278b_timer_b_tick(int num) +{ + YMF278BChip *chip = &YMF278B[num]; + if(!(chip->enable & 0x20)) + { + chip->current_irq |= 0x20; + ymf278b_irq_check(num); + } +} +#endif /* !!! FBA */ + +static void ymf278b_timer_a_reset(int num) +{ + YMF278BChip *chip = &YMF278B[num]; + if(chip->enable & 1) + { + double period = (256-chip->timer_a_count) * 80.8 * chip->clock_ratio; + chip->timer_callback(num, 0, period); + } + else + chip->timer_callback(num, 0, 0); +} + +static void ymf278b_timer_b_reset(int num) +{ + YMF278BChip *chip = &YMF278B[num]; + if(chip->enable & 2) + { + double period = (256-chip->timer_b_count) * 323.1 * chip->clock_ratio; + chip->timer_callback(num, 1, period); + } + else + chip->timer_callback(num, 1, 0); +} + +static void ymf278b_A_w(int num, UINT8 reg, UINT8 data) +{ + YMF278BChip *chip = &YMF278B[num]; + + if (!Machine->sample_rate) return; + + switch(reg) + { + case 0x02: + chip->timer_a_count = data; + ymf278b_timer_a_reset(num); + break; + case 0x03: + chip->timer_b_count = data; + ymf278b_timer_b_reset(num); + break; + case 0x04: + if(data & 0x80) + chip->current_irq = 0; + else + { + UINT8 old_enable = chip->enable; + chip->enable = data; + chip->current_irq &= ~data; + if((old_enable ^ data) & 1) + ymf278b_timer_a_reset(num); + if((old_enable ^ data) & 2) + ymf278b_timer_b_reset(num); + } + ymf278b_irq_check(num); + break; + default: + logerror("YMF278B: Port A write %02x, %02x\n", reg, data); + } +} + +static void ymf278b_B_w(int num, UINT8 reg, UINT8 data) +{ + if (!Machine->sample_rate) return; + + logerror("YMF278B: Port B write %02x, %02x\n", reg, data); +} + +static void ymf278b_C_w(int num, UINT8 reg, UINT8 data) +{ + YMF278BChip *chip = &YMF278B[num]; + + if (!Machine->sample_rate) return; + + // Handle slot registers specifically + if (reg >= 0x08 && reg <= 0xf7) + { + YMF278BSlot *slot = NULL; + int snum; + snum = (reg-8) % 24; + slot = &YMF278B[num].slots[snum]; + switch((reg-8) / 24) + { + case 0: + { + const UINT8 *p; + + slot->wave &= 0x100; + slot->wave |= data; + + if(slot->wave < 384 || !chip->wavetblhdr) + p = chip->rom + (slot->wave * 12); + else + p = chip->rom + chip->wavetblhdr*0x80000 + ((slot->wave - 384) * 12); + + switch (p[0]&0xc0) + { + case 0: + slot->bits = 8; + break; + case 0x40: + slot->bits = 12; + break; + case 0x80: + slot->bits = 16; + break; + } + + slot->lfo = (p[7] >> 2) & 7; + slot->vib = p[7] & 7; + slot->AR = p[8] >> 4; + slot->D1R = p[8] & 0xf; + slot->DL = p[9] >> 4; + slot->D2R = p[9] & 0xf; + slot->RC = p[10] >> 4; + slot->RR = p[10] & 0xf; + slot->AM = p[11] & 7; + + slot->startaddr = (p[2] | (p[1]<<8) | ((p[0]&0x3f)<<16)); + slot->loopaddr = (p[4]<<16) | (p[3]<<24); + slot->endaddr = (p[6]<<16) | (p[5]<<24); + slot->endaddr -= 0x00010000U; + slot->endaddr ^= 0xffff0000U; + break; + } + case 1: + slot->wave &= 0xff; + slot->wave |= ((data&0x1)<<8); + slot->FN &= 0x380; + slot->FN |= (data>>1); + break; + case 2: + slot->FN &= 0x07f; + slot->FN |= ((data&0x07)<<7); + slot->PRVB = ((data&0x4)>>3); + slot->OCT = ((data&0xf0)>>4); + break; + case 3: + slot->TL = (data>>1); + slot->LD = data&0x1; + break; + case 4: + slot->pan = data&0xf; + if (data & 0x80) + { + unsigned int step; + int oct; + + slot->active = 1; + + oct = slot->OCT; + if(oct & 8) + oct |= -8; + + slot->env_step = 0; + slot->env_vol = 256U<<23; + slot->env_vol_step = 0; + slot->env_vol_lim = 256U<<23; + slot->stepptr = 0; + slot->step = 0; + + step = (slot->FN | 1024) << (oct + 7); + slot->step = (UINT32) ((((INT64)step)*(44100/4)) / Machine->sample_rate * chip->clock_ratio); + + ymf278b_envelope_next(slot, chip->clock_ratio); + +#ifdef VERBOSE + logerror("YMF278B: slot %2d wave %3d lfo=%d vib=%d ar=%d d1r=%d dl=%d d2r=%d rc=%d rr=%d am=%d\n", snum, slot->wave, + slot->lfo, slot->vib, slot->AR, slot->D1R, slot->DL, slot->D2R, slot->RC, slot->RR, slot->AM); + logerror(" b=%d, start=%x, loop=%x, end=%x, oct=%d, fn=%d, step=%x\n", slot->bits, slot->startaddr, slot->loopaddr>>16, slot->endaddr>>16, oct, slot->FN, slot->step); +#endif + } + else + { +#ifdef VERBOSE + logerror("YMF278B: slot %2d off\n", snum); +#endif + if(slot->active) + { + slot->env_step = 4; + ymf278b_envelope_next(slot, chip->clock_ratio); + } + } + break; + case 5: + slot->vib = data&0x7; + slot->lfo = (data>>3)&0x7; + break; + case 6: + slot->AR = data>>4; + slot->D1R = data&0xf; + break; + case 7: + slot->DL = data>>4; + slot->D2R = data&0xf; + break; + case 8: + slot->RC = data>>4; + slot->RR = data&0xf; + break; + case 9: + slot->AM = data & 0x7; + break; + } + } + else + { + // All non-slot registers + switch (reg) + { + case 0x00: // TEST + case 0x01: + break; + + case 0x02: + chip->wavetblhdr = (data>>2)&0x7; + chip->memmode = data&1; + break; + + case 0x03: + chip->memadr &= 0xffff; + chip->memadr |= (data<<16); + break; + + case 0x04: + chip->memadr &= 0xff00ff; + chip->memadr |= (data<<8); + break; + + case 0x05: + chip->memadr &= 0xffff00; + chip->memadr |= data; + break; + + case 0x06: // memory data (ignored, we don't support RAM) + case 0x07: // unused + break; + + case 0xf8: + chip->fm_l = data & 0x7; + chip->fm_r = (data>>3)&0x7; + break; + + case 0xf9: + chip->pcm_l = data & 0x7; + chip->pcm_r = (data>>3)&0x7; + break; + } + } +} + +static UINT8 ymf278b_status_port_r(int num) +{ + return YMF278B[num].current_irq | (YMF278B[num].irq_line == ASSERT_LINE ? 0x80 : 0x00); +} + +// Not implemented yet +static UINT8 ymf278b_data_port_r(int num) +{ + return 0; +} + +static void ymf278b_control_port_A_w(int num, UINT8 data) +{ + YMF278B[num].port_A = data; +} + +static void ymf278b_data_port_A_w(int num, UINT8 data) +{ + ymf278b_A_w(num, YMF278B[num].port_A, data); +} + +static void ymf278b_control_port_B_w(int num, UINT8 data) +{ + YMF278B[num].port_B = data; +} + +static void ymf278b_data_port_B_w(int num, UINT8 data) +{ + ymf278b_B_w(num, YMF278B[num].port_B, data); +} + +static void ymf278b_control_port_C_w(int num, UINT8 data) +{ + YMF278B[num].port_C = data; +} + +static void ymf278b_data_port_C_w(int num, UINT8 data) +{ + ymf278b_C_w(num, YMF278B[num].port_C, data); +} + +#ifdef FBA /* !!! FBA */ +int ymf278b_start(INT8 num, UINT8 *rom, void (*irq_cb)(int, int), void (*timer_cb)(int, int, double), int clock, int rate) +{ + int i; + + memset(&YMF278B[num], 0, sizeof(YMF278BChip)); + YMF278B[num].rom = rom; + YMF278B[num].irq_callback = irq_cb; + YMF278B[num].timer_callback = timer_cb; + YMF278B[num].irq_line = CLEAR_LINE; + YMF278B[num].clock_ratio = (float)clock / (float)YMF278B_STD_CLOCK; + + Machine->sample_rate = rate; + + // Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB + for(i = 0; i < 256; i++) + volume[i] = 65536*pow(2.0, (-0.375/6)*i); + for(i = 256; i < 256*4; i++) + volume[i] = 0; + + // Pan values, units are -3dB, i.e. 8. + for(i = 0; i < 16; i++) + { + pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0; + pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8; + } + + // Mixing levels, units are -3dB, and add some marging to avoid clipping + for(i=0; i<7; i++) + mix_level[i] = volume[8*i+8]; + mix_level[7] = 0; + + return 0; +} +#else /* !!! FBA */ +static void ymf278b_init(INT8 num, UINT8 *rom, void (*cb)(int), int clock) +{ + memset(&YMF278B[num], 0, sizeof(YMF278BChip)); + YMF278B[num].rom = rom; + YMF278B[num].irq_callback = cb; + YMF278B[num].timer_a = timer_alloc(ymf278b_timer_a_tick); + YMF278B[num].timer_b = timer_alloc(ymf278b_timer_b_tick); + YMF278B[num].irq_line = CLEAR_LINE; + YMF278B[num].clock_ratio = (float)clock / (float)YMF278B_STD_CLOCK; +} + +int YMF278B_sh_start( const struct MachineSound *msound ) +{ + char buf[2][40]; + const char *name[2]; + int vol[2]; + struct YMF278B_interface *intf; + int i; + + intf = msound->sound_interface; + + for(i=0; inum; i++) + { + sprintf(buf[0], "YMF278B %d L", i); + sprintf(buf[1], "YMF278B %d R", i); + name[0] = buf[0]; + name[1] = buf[1]; + vol[0]=intf->mixing_level[i] >> 16; + vol[1]=intf->mixing_level[i] & 0xffff; + ymf278b_init(i, memory_region(intf->region[0]), intf->irq_callback[i], intf->clock[i]); + stream_init_multi(2, name, vol, Machine->sample_rate, i, ymf278b_pcm_update); + } + + // Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB + for(i = 0; i < 256; i++) + volume[i] = 65536*pow(2.0, (-0.375/6)*i); + for(i = 256; i < 256*4; i++) + volume[i] = 0; + + // Pan values, units are -3dB, i.e. 8. + for(i = 0; i < 16; i++) + { + pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0; + pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8; + } + + // Mixing levels, units are -3dB, and add some marging to avoid clipping + for(i=0; i<7; i++) + mix_level[i] = volume[8*i+8]; + mix_level[7] = 0; + + return 0; +} +#endif /* !!! FBA */ + +void YMF278B_sh_stop( void ) +{ +} + +READ8_HANDLER( YMF278B_status_port_0_r ) +{ + return ymf278b_status_port_r(0); +} + +READ8_HANDLER( YMF278B_data_port_0_r ) +{ + return ymf278b_data_port_r(0); +} + +WRITE8_HANDLER( YMF278B_control_port_0_A_w ) +{ + ymf278b_control_port_A_w(0, data); +} + +WRITE8_HANDLER( YMF278B_data_port_0_A_w ) +{ + ymf278b_data_port_A_w(0, data); +} + +WRITE8_HANDLER( YMF278B_control_port_0_B_w ) +{ + ymf278b_control_port_B_w(0, data); +} + +WRITE8_HANDLER( YMF278B_data_port_0_B_w ) +{ + ymf278b_data_port_B_w(0, data); +} + +WRITE8_HANDLER( YMF278B_control_port_0_C_w ) +{ + ymf278b_control_port_C_w(0, data); +} + +WRITE8_HANDLER( YMF278B_data_port_0_C_w ) +{ + ymf278b_data_port_C_w(0, data); +} + +#ifndef FBA /* !!! FBA */ +READ8_HANDLER( YMF278B_status_port_1_r ) +{ + return ymf278b_status_port_r(1); +} + +READ8_HANDLER( YMF278B_data_port_1_r ) +{ + return ymf278b_data_port_r(1); +} + +WRITE8_HANDLER( YMF278B_control_port_1_A_w ) +{ + ymf278b_control_port_A_w(1, data); +} + +WRITE8_HANDLER( YMF278B_data_port_1_A_w ) +{ + ymf278b_data_port_A_w(1, data); +} + +WRITE8_HANDLER( YMF278B_control_port_1_B_w ) +{ + ymf278b_control_port_B_w(1, data); +} + +WRITE8_HANDLER( YMF278B_data_port_1_B_w ) +{ + ymf278b_data_port_B_w(1, data); +} + +WRITE8_HANDLER( YMF278B_control_port_1_C_w ) +{ + ymf278b_control_port_C_w(1, data); +} + +WRITE8_HANDLER( YMF278B_data_port_1_C_w ) +{ + ymf278b_data_port_C_w(1, data); +} +#endif /* !!! FBA */ diff --git a/src/burn/sound/ymf278b.h b/src/burn/sound/ymf278b.h new file mode 100644 index 00000000..0925f7ae --- /dev/null +++ b/src/burn/sound/ymf278b.h @@ -0,0 +1,49 @@ +#ifndef __YMF278B_H__ +#define __YMF278B_H__ + +#ifdef FBA /* !!! FBA */ +#define MAX_YMF278B (1) +#else /* !!! FBA */ +#define MAX_YMF278B (2) +#endif /* !!! FBA */ + +#define YMF278B_STD_CLOCK (33868800) /* standard clock for OPL4 */ + +struct YMF278B_interface { + int num; /* Number of chips */ + int clock[MAX_YMF278B]; /* clock input, normally 33.8688 MHz */ + int region[MAX_YMF278B]; /* memory region of sample ROMs */ + int mixing_level[MAX_YMF278B]; /* volume */ + void (*irq_callback[MAX_YMF278B])(int num, int state); /* irq callback */ +}; + +#ifdef FBA /* !!! FBA */ +void ymf278b_pcm_update(int num, INT16 **outputs, int length); +int ymf278b_timer_over(int num, int timer); +int ymf278b_start(INT8 num, UINT8 *rom, void (*irq_cb)(int, int), void (*timer_cb)(int, int, double), int clock, int rate); +#else /* !!! FBA */ +int YMF278B_sh_start( const struct MachineSound *msound ); +#endif /* !!! FBA */ +void YMF278B_sh_stop(void); + +READ8_HANDLER( YMF278B_status_port_0_r ); +READ8_HANDLER( YMF278B_data_port_0_r ); +WRITE8_HANDLER( YMF278B_control_port_0_A_w ); +WRITE8_HANDLER( YMF278B_data_port_0_A_w ); +WRITE8_HANDLER( YMF278B_control_port_0_B_w ); +WRITE8_HANDLER( YMF278B_data_port_0_B_w ); +WRITE8_HANDLER( YMF278B_control_port_0_C_w ); +WRITE8_HANDLER( YMF278B_data_port_0_C_w ); + +#ifndef FBA /* !!! FBA */ +READ8_HANDLER( YMF278B_status_port_1_r ); +READ8_HANDLER( YMF278B_data_port_1_r ); +WRITE8_HANDLER( YMF278B_control_port_1_A_w ); +WRITE8_HANDLER( YMF278B_data_port_1_A_w ); +WRITE8_HANDLER( YMF278B_control_port_1_B_w ); +WRITE8_HANDLER( YMF278B_data_port_1_B_w ); +WRITE8_HANDLER( YMF278B_control_port_1_C_w ); +WRITE8_HANDLER( YMF278B_data_port_1_C_w ); +#endif /* !!! FBA */ + +#endif diff --git a/src/burn/sound/ymz280b.cpp b/src/burn/sound/ymz280b.cpp new file mode 100644 index 00000000..583a17c9 --- /dev/null +++ b/src/burn/sound/ymz280b.cpp @@ -0,0 +1,715 @@ +// Yamaha YMZ280B module +#include +#include "burnint.h" +#include "ymz280b.h" +#include "burn_sound.h" + +static INT32 nYMZ280BSampleRate; + +UINT8* YMZ280BROM; +void (*pYMZ280BRAMWrite)(INT32 offset, INT32 nValue) = NULL; +INT32 (*pYMZ280BRAMRead)(INT32 offset) = NULL; + +UINT32 nYMZ280BStatus; +UINT32 nYMZ280BRegister; + +static bool bYMZ280BEnable; + +static bool bYMZ280BIRQEnable; +static INT32 nYMZ280BIRQMask; +static INT32 nYMZ280BIRQStatus; +void (*YMZ280BIRQCallback)(INT32 nStatus) = NULL; + +static INT32* pBuffer = NULL; +static INT32 nOutputChannels; + +static double nYMZ280BFrequency; + +static INT32 YMZ280BDeltaTable[16]; + +static INT32 YMZ280BStepShift[8] = {0x0E6, 0x0E6, 0x0E6, 0x0E6, 0x133, 0x199, 0x200, 0x266}; + +struct sYMZ280BChannelInfo { + bool bEnabled; + bool bPlaying; + bool bLoop; + INT32 nMode; + INT32 nFrequency; + INT32 nSample; + INT32 nLoopSample; + UINT32 nSampleSize; + UINT32 nPosition; + INT32 nFractionalPosition; + INT32 nStep; + INT32 nLoopStep; + UINT32 nSampleStart; + UINT32 nSampleStop; + UINT32 nLoopStart; + UINT32 nLoopStop; + INT32 nVolume; + INT32 nVolumeLeft; + INT32 nVolumeRight; + INT32 nPan; + + INT32 nOutput; + INT32 nPreviousOutput; + + INT32 nBufPos; +}; + +static INT32 nActiveChannel, nDelta, nSample, nCount, nRamReadAddress; +static INT32* buf; + +sYMZ280BChannelInfo YMZ280BChannelInfo[8]; +static sYMZ280BChannelInfo* channelInfo; + +static INT32* YMZ280BChannelData[8]; + +void YMZ280BReset() +{ + memset(&YMZ280BChannelInfo[0], 0, sizeof(YMZ280BChannelInfo)); + + nYMZ280BIRQMask = 0; + nYMZ280BIRQStatus = 0; + nYMZ280BStatus = 0; + bYMZ280BEnable = false; + nRamReadAddress = 0; + + for (INT32 j = 0; j < 8; j++) { + memset(YMZ280BChannelData[j], 0, 0x1000 * sizeof(INT32)); + YMZ280BChannelInfo[j].nBufPos = 4; + } + + return; +} + +inline void YMZ280BSetSampleSize(const INT32 nChannel) +{ + double rate = (double)(YMZ280BChannelInfo[nChannel].nFrequency + 1) * nYMZ280BFrequency * 512; + rate /= nYMZ280BSampleRate * 3; + + YMZ280BChannelInfo[nChannel].nSampleSize = (UINT32)rate; +} + +INT32 YMZ280BScan() +{ + SCAN_VAR(nYMZ280BStatus); + SCAN_VAR(nYMZ280BRegister); + + SCAN_VAR(bYMZ280BEnable); + + SCAN_VAR(bYMZ280BIRQEnable); + SCAN_VAR(nYMZ280BIRQMask); + SCAN_VAR(nYMZ280BIRQStatus); + SCAN_VAR(nRamReadAddress); + + for (INT32 j = 0; j < 8; j++) { + SCAN_VAR(YMZ280BChannelInfo[j]); + YMZ280BSetSampleSize(j); + } + + return 0; +} + +INT32 YMZ280BInit(INT32 nClock, void (*IRQCallback)(INT32), INT32 nChannels) +{ + nYMZ280BFrequency = nClock; + + if (nBurnSoundRate > 0) { + nYMZ280BSampleRate = nBurnSoundRate; + } else { + nYMZ280BSampleRate = 11025; + } + + // Compute sample deltas + for (INT32 n = 0; n < 16; n++) { + nDelta = (n & 7) * 2 + 1; + if (n & 8) { + nDelta = -nDelta; + } + YMZ280BDeltaTable[n] = nDelta; + } + + YMZ280BIRQCallback = IRQCallback; + + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + pBuffer = (INT32*)malloc(nYMZ280BSampleRate * 2 * sizeof(INT32)); + + for (INT32 j = 0; j < 8; j++) { + YMZ280BChannelData[j] = (INT32*)malloc(0x1000 * sizeof(INT32)); + } + + nOutputChannels = nChannels; + + YMZ280BReset(); + + return 0; +} + +void YMZ280BExit() +{ + if (pBuffer) { + free(pBuffer); + pBuffer = NULL; + } + + YMZ280BIRQCallback = NULL; + pYMZ280BRAMWrite = NULL; + pYMZ280BRAMRead = NULL; +} + +inline static void UpdateIRQStatus() +{ + nYMZ280BIRQStatus = 0; + if (bYMZ280BIRQEnable && (nYMZ280BStatus & nYMZ280BIRQMask)) { + nYMZ280BIRQStatus = 1; + } + + if ((YMZ280BIRQCallback != NULL)) { + YMZ280BIRQCallback(nYMZ280BIRQStatus); + } +} + +inline static void ComputeVolume(sYMZ280BChannelInfo* channel) +{ + if (channel->nPan == 8) { + channel->nVolumeLeft = channel->nVolume; + channel->nVolumeRight = channel->nVolume; + } else { + if (channel->nPan < 8) { + channel->nVolumeLeft = channel->nVolume; + channel->nVolumeRight = channel->nVolume * channel->nPan / 8; + } else { + channel->nVolumeLeft = channel->nVolume * (15 - channel->nPan) / 8; + channel->nVolumeRight = channel->nVolume; + } + } +} + +inline static void RampChannel() +{ +#if 1 + if (channelInfo->nSample != 0) { + if (channelInfo->nSample > 0) { + INT32 nRamp = 64 * 32678 / nYMZ280BSampleRate; + while (nCount-- && channelInfo->nSample > nRamp) { + channelInfo->nSample -= nRamp; + *buf++ += channelInfo->nSample * channelInfo->nVolumeLeft; + *buf++ += channelInfo->nSample * channelInfo->nVolumeRight; + } + if (channelInfo->nSample < nRamp) { + channelInfo->nSample = 0; + } + } else { + INT32 nRamp = 0 - 64 * 32678 / nYMZ280BSampleRate; + while (nCount-- && channelInfo->nSample < nRamp) { + channelInfo->nSample -= nRamp; + *buf++ += channelInfo->nSample * channelInfo->nVolumeLeft; + *buf++ += channelInfo->nSample * channelInfo->nVolumeRight; + } + if (channelInfo->nSample > nRamp) { + channelInfo->nSample = 0; + } + } + } +#endif +} + +inline static void decode_adpcm() +{ + // Get next value & compute delta + nDelta = YMZ280BROM[channelInfo->nPosition >> 1]; + if (channelInfo->nPosition & 1) { + nDelta &= 0x0F; + } else { + nDelta >>= 4; + } + + nSample = channelInfo->nSample + channelInfo->nStep * YMZ280BDeltaTable[nDelta] / 8; + if (nSample > 32767) { + nSample = 32767; + } else { + if (nSample < -32768) { + nSample = -32768; + } + } + channelInfo->nSample = nSample; + + channelInfo->nStep = channelInfo->nStep * YMZ280BStepShift[nDelta & 7] / 256; + if (channelInfo->nStep > 0x6000) { + channelInfo->nStep = 0x6000; + } else { + if (channelInfo->nStep < 127) { + channelInfo->nStep = 127; + } + } + + channelInfo->nPosition++; +} + +inline static void decode_pcm8() +{ + nDelta = YMZ280BROM[channelInfo->nPosition >> 1]; + + channelInfo->nSample = (INT8)nDelta * 256; + channelInfo->nPosition+=2; +} + +inline static void decode_pcm16() +{ + nDelta = (INT16)((YMZ280BROM[channelInfo->nPosition / 2 + 1] << 8) + YMZ280BROM[channelInfo->nPosition / 2]); + + channelInfo->nSample = nDelta; + channelInfo->nPosition+=4; +} + +inline static void decode_none() +{ + channelInfo->nSample=0; +} + +static void (*decode_table[4])() = { decode_none, decode_adpcm, decode_pcm8, decode_pcm16 }; + +inline static void ComputeOutput_Linear() +{ + nSample = channelInfo->nPreviousOutput + (channelInfo->nOutput - channelInfo->nPreviousOutput) * (channelInfo->nFractionalPosition >> 12) / (0x01000000 >> 12); + + *buf++ += nSample * channelInfo->nVolumeLeft; + *buf++ += nSample * channelInfo->nVolumeRight; +} + +inline static void ComputeOutput_Cubic() +{ + if (channelInfo->nBufPos > 0x0FF0) { + YMZ280BChannelData[nActiveChannel][0] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 4]; + YMZ280BChannelData[nActiveChannel][1] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 3]; + YMZ280BChannelData[nActiveChannel][2] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 2]; + YMZ280BChannelData[nActiveChannel][3] = YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 1]; + channelInfo->nBufPos = 4; + } + + nSample = INTERPOLATE4PS_16BIT(channelInfo->nFractionalPosition >> 12, + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 4], + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 3], + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 2], + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos - 1]); + + *buf++ += nSample * channelInfo->nVolumeLeft; + *buf++ += nSample * channelInfo->nVolumeRight; +} + +inline static void RenderADPCM_Linear() +{ + while (nCount--) { + if (channelInfo->nFractionalPosition >= 0x01000000) { + + channelInfo->nPreviousOutput = channelInfo->nOutput; + + do { + // Check for end of sample + if (channelInfo->nPosition >= channelInfo->nSampleStop) { + channelInfo->bPlaying = false; + + RampChannel(); + + nYMZ280BStatus |= 1 << nActiveChannel; + UpdateIRQStatus(); + + return; + } else { + + decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample + + // Advance sample position + channelInfo->nFractionalPosition -= 0x01000000; + } + + } while (channelInfo->nFractionalPosition >= 0x01000000); + + channelInfo->nOutput = channelInfo->nSample; + } + + ComputeOutput_Linear(); + + channelInfo->nFractionalPosition += channelInfo->nSampleSize; + } +} + +inline static void RenderADPCMLoop_Linear() +{ + while (nCount--) { + if (channelInfo->nFractionalPosition >= 0x01000000) { + + channelInfo->nPreviousOutput = channelInfo->nOutput; + + do { + // Check for end of sample + if (channelInfo->nPosition == channelInfo->nLoopStop) { + channelInfo->nStep = channelInfo->nLoopStep; + channelInfo->nSample = channelInfo->nLoopSample; + channelInfo->nPosition = channelInfo->nLoopStart; + } else { + // Store the state of the channel at the point where the loop starts + if (channelInfo->nPosition == channelInfo->nLoopStart) { + channelInfo->nLoopStep = channelInfo->nStep; + channelInfo->nLoopSample = channelInfo->nSample; + } + } + + decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample + + // Advance sample position + channelInfo->nFractionalPosition -= 0x01000000; + + } while (channelInfo->nFractionalPosition >= 0x01000000); + + channelInfo->nOutput = channelInfo->nSample; + } + + ComputeOutput_Linear(); + + channelInfo->nFractionalPosition += channelInfo->nSampleSize; + } +} +inline static void RenderADPCM_Cubic() +{ + while (nCount--) { + while (channelInfo->nFractionalPosition >= 0x01000000) { + + // Check for end of sample + if (channelInfo->nPosition >= channelInfo->nSampleStop) { + channelInfo->bPlaying = false; + + RampChannel(); + + nYMZ280BStatus |= 1 << nActiveChannel; + UpdateIRQStatus(); + + return; + } else { + + decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample + + // Advance sample position + channelInfo->nFractionalPosition -= 0x01000000; + + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos++] = channelInfo->nSample; + } + } + + ComputeOutput_Cubic(); + + channelInfo->nFractionalPosition += channelInfo->nSampleSize; + } +} + +inline static void RenderADPCMLoop_Cubic() +{ + while (nCount--) { + + while (channelInfo->nFractionalPosition >= 0x01000000) { + // Check for end of sample + if (channelInfo->nPosition >= channelInfo->nLoopStop) { + + channelInfo->nStep = channelInfo->nLoopStep; + channelInfo->nSample = channelInfo->nLoopSample; + channelInfo->nPosition = channelInfo->nLoopStart; + } else { + // Store the state of the channel at the point where the loop starts + if (channelInfo->nPosition == channelInfo->nLoopStart) { + channelInfo->nLoopStep = channelInfo->nStep; + channelInfo->nLoopSample = channelInfo->nSample; + } + } + + decode_table[YMZ280BChannelInfo[nActiveChannel].nMode](); // decode one sample + + // Advance sample position + channelInfo->nFractionalPosition -= 0x01000000; + + YMZ280BChannelData[nActiveChannel][channelInfo->nBufPos++] = channelInfo->nSample; + } + + ComputeOutput_Cubic(); + + channelInfo->nFractionalPosition += channelInfo->nSampleSize; + } +} + +INT32 YMZ280BRender(INT16* pSoundBuf, INT32 nSegmentLength) +{ + memset(pBuffer, 0, nSegmentLength * 2 * sizeof(INT32)); + + for (nActiveChannel = 0; nActiveChannel < 8; nActiveChannel++) { + nCount = nSegmentLength; + buf = pBuffer; + channelInfo = &YMZ280BChannelInfo[nActiveChannel]; + + if (channelInfo->bPlaying) { + if (nInterpolation < 3) { + if (channelInfo->bEnabled && channelInfo->bLoop) { + RenderADPCMLoop_Linear(); + } else { + RenderADPCM_Linear(); + } + } else { + if (channelInfo->bEnabled && channelInfo->bLoop) { + RenderADPCMLoop_Cubic(); + } else { + RenderADPCM_Cubic(); + } + } + } else { + RampChannel(); + } + } + + switch (nOutputChannels) { + case 1: // Use only the left output channel + case 2: { // Use only the right output channel + nCount = nSegmentLength; + buf = pBuffer + (nOutputChannels >> 1); + while (nCount--) { + nSample = *buf >> 8; + buf += 2; + if (nSample > 32767) { + nSample = 32767; + } else { + if (nSample < -32768) { + nSample = -32768; + } + } + + *pSoundBuf++ = (INT16)nSample; + *pSoundBuf++ = (INT16)nSample; + } + break; + } + case 3: { // Use both output channels + if (bBurnUseMMX) { +#if defined BUILD_X86_ASM + BurnSoundCopyClamp_A(pBuffer, pSoundBuf, nSegmentLength); +#endif + } else { + BurnSoundCopyClamp_C(pBuffer, pSoundBuf, nSegmentLength); + } + + break; + } + } + + return 0; +} + +void YMZ280BWriteRegister(UINT8 nValue) +{ + if (nYMZ280BRegister < 0x80) { + INT32 nWriteChannel = (nYMZ280BRegister >> 2) & 0x07; + + switch (nYMZ280BRegister & 0x63) { + + // Miscellaneous + case 0: // Frequency + YMZ280BChannelInfo[nWriteChannel].nFrequency &= 0x0100; + YMZ280BChannelInfo[nWriteChannel].nFrequency |= nValue; + YMZ280BSetSampleSize(nWriteChannel); + break; + case 1: { // Start/mode/freq + YMZ280BChannelInfo[nWriteChannel].nFrequency &= 0x00FF; + YMZ280BChannelInfo[nWriteChannel].nFrequency |= ((nValue & 1) << 8); + YMZ280BSetSampleSize(nWriteChannel); + + YMZ280BChannelInfo[nWriteChannel].bLoop = (nValue & 0x10); + YMZ280BChannelInfo[nWriteChannel].nMode = ((nValue >> 5) & 0x03); + + if ((nValue & 0x80) == 0) { + YMZ280BChannelInfo[nWriteChannel].bEnabled = false; + if (!YMZ280BChannelInfo[nWriteChannel].bLoop) { + YMZ280BChannelInfo[nWriteChannel].bPlaying = false; + } + } else { + if (!YMZ280BChannelInfo[nWriteChannel].bEnabled) { + YMZ280BChannelInfo[nWriteChannel].bEnabled = true; + YMZ280BChannelInfo[nWriteChannel].bPlaying = true; + YMZ280BChannelInfo[nWriteChannel].nPosition = YMZ280BChannelInfo[nWriteChannel].nSampleStart; + YMZ280BChannelInfo[nWriteChannel].nStep = 127; + + if (YMZ280BChannelInfo[nWriteChannel].nMode > 1) { +#ifdef DEBUG + // bprintf(0,_T("Sample Start: %08X - Stop: %08X.\n"),YMZ280BChannelInfo[nWriteChannel].nSampleStart, YMZ280BChannelInfo[nWriteChannel].nSampleStop); +#endif + } + +#if 0 + if (nInterpolation < 3) { + YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0; + YMZ280BChannelInfo[nWriteChannel].nPreviousOutput = YMZ280BChannelInfo[nWriteChannel].nSample; + YMZ280BChannelInfo[nWriteChannel].nOutput = YMZ280BChannelInfo[nWriteChannel].nSample; + } else { + YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0x03000000; + YMZ280BChannelData[nWriteChannel][0] = YMZ280BChannelInfo[nWriteChannel].nSample; + YMZ280BChannelInfo[nWriteChannel].nBufPos = 1; + } +#else + YMZ280BChannelInfo[nWriteChannel].nSample = 0; + + if (nInterpolation < 3) { + YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0; + YMZ280BChannelInfo[nWriteChannel].nPreviousOutput = 0; + YMZ280BChannelInfo[nWriteChannel].nOutput = 0; + } else { + YMZ280BChannelInfo[nWriteChannel].nFractionalPosition = 0x03000000; + YMZ280BChannelData[nWriteChannel][3] = 0; + YMZ280BChannelInfo[nWriteChannel].nBufPos = 1; + } +#endif + } + } + + break; + } + case 2: // Volume + YMZ280BChannelInfo[nWriteChannel].nVolume = nValue; + ComputeVolume(&YMZ280BChannelInfo[nWriteChannel]); + break; + case 3: // Pan + YMZ280BChannelInfo[nWriteChannel].nPan = nValue & 0x0F; + ComputeVolume(&YMZ280BChannelInfo[nWriteChannel]); + break; + + // Hi bits + case 0x20: + YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x0001FFFE; + YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 17); + break; + case 0x21: + YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x0001FFFE; + YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 17); + break; + case 0x22: + YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x0001FFFE; + YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 17); + break; + case 0x23: + YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x0001FFFE; + YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 17); + break; + + // Mid bits + case 0x40: + YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x01FE01FE; + YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 9); + break; + case 0x41: + YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x01FE01FE; + YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 9); + break; + case 0x42: + YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x01FE01FE; + YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 9); + break; + case 0x43: + YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x01FE01FE; + YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 9); + break; + + // Lo bits + case 0x60: + YMZ280BChannelInfo[nWriteChannel].nSampleStart &= 0x01FFFE00; + YMZ280BChannelInfo[nWriteChannel].nSampleStart |= (nValue << 1); + break; + case 0x61: + YMZ280BChannelInfo[nWriteChannel].nLoopStart &= 0x01FFFE00; + YMZ280BChannelInfo[nWriteChannel].nLoopStart |= (nValue << 1); + break; + case 0x62: + YMZ280BChannelInfo[nWriteChannel].nLoopStop &= 0x01FFFE00; + YMZ280BChannelInfo[nWriteChannel].nLoopStop |= (nValue << 1); + break; + case 0x63: + YMZ280BChannelInfo[nWriteChannel].nSampleStop &= 0x01FFFE00; + YMZ280BChannelInfo[nWriteChannel].nSampleStop |= (nValue << 1); + break; + + } + } else { + switch (nYMZ280BRegister) + { + case 0x84: // ROM readback / RAM write (high) + nRamReadAddress &= 0x00ffff; + nRamReadAddress |= (nValue << 16); + break; + + case 0x85: // ROM readback / RAM write (med) + nRamReadAddress &= 0xff00ff; + nRamReadAddress |= (nValue << 8); + break; + + case 0x86: // ROM readback / RAM write (low) + nRamReadAddress &= 0xffff00; + nRamReadAddress |= (nValue << 0); + break; + + case 0x87: // RAM write + if (pYMZ280BRAMWrite) { + pYMZ280BRAMWrite(nRamReadAddress, nValue); + } + break; + + case 0xfe: // Set IRQ mask + nYMZ280BIRQMask = nValue; + UpdateIRQStatus(); + break; + + case 0xff: // Start/stop playing, enable/disable IRQ + { + if (nValue & 0x10) { + bYMZ280BIRQEnable = true; + } else { + bYMZ280BIRQEnable = false; + } + UpdateIRQStatus(); + + if (bYMZ280BEnable && !(nValue & 0x80)) { + bYMZ280BEnable = false; + for (INT32 n = 0; n < 8; n++) { + YMZ280BChannelInfo[n].bPlaying = false; + } + } else { + if (!bYMZ280BEnable && (nValue & 0x80)) { + bYMZ280BEnable = true; + for (INT32 n = 0; n < 8; n++) { + if (YMZ280BChannelInfo[n].bEnabled && YMZ280BChannelInfo[n].bLoop) { + YMZ280BChannelInfo[n].bPlaying = true; + } + } + } + } + } + break; + } + } +} + +UINT32 YMZ280BReadStatus() +{ + UINT32 nStatus = nYMZ280BStatus; + nYMZ280BStatus = 0; + + UpdateIRQStatus(); + + return nStatus; +} + +UINT32 YMZ280BReadRAM() +{ + if (pYMZ280BRAMRead) { + return pYMZ280BRAMRead(nRamReadAddress++ - 1); + } + + return 0; +} + diff --git a/src/burn/sound/ymz280b.h b/src/burn/sound/ymz280b.h new file mode 100644 index 00000000..bb3b2f43 --- /dev/null +++ b/src/burn/sound/ymz280b.h @@ -0,0 +1,44 @@ +// Yamaha YMZ280B module + +INT32 YMZ280BInit(INT32 nClock, void (*IRQCallback)(INT32), INT32 nChannels); +void YMZ280BReset(); +INT32 YMZ280BScan(); +void YMZ280BExit(); +INT32 YMZ280BRender(INT16* pSoundBuf, INT32 nSegmenLength); +void YMZ280BWriteRegister(UINT8 nValue); +UINT32 YMZ280BReadStatus(); +UINT32 YMZ280BReadRAM(); + +extern UINT8* YMZ280BROM; + +// external memory handlers +extern void (*pYMZ280BRAMWrite)(INT32 offset, INT32 nValue); +extern INT32 (*pYMZ280BRAMRead)(INT32 offset); + +extern UINT32 nYMZ280BStatus; +extern UINT32 nYMZ280BRegister; + +inline static void YMZ280BSelectRegister(UINT8 nRegister) +{ + nYMZ280BRegister = nRegister; +} + +inline static void YMZ280BWrite(INT32 offset, UINT8 nValue) +{ + if (offset & 1) { + YMZ280BWriteRegister(nValue); + } else { + nYMZ280BRegister = nValue; + } +} + +inline static UINT32 YMZ280BRead(INT32 offset) +{ + if (offset & 1) { + return YMZ280BReadStatus(); + } else { + return YMZ280BReadRAM(); + } + + return 0; +} diff --git a/src/burn/state.h b/src/burn/state.h new file mode 100644 index 00000000..f9c421f9 --- /dev/null +++ b/src/burn/state.h @@ -0,0 +1,70 @@ +#if !defined(_STATE_H) + +#ifdef __cplusplus + extern "C" { +#endif + +/* Scan driver data */ +INT32 BurnAreaScan(INT32 nAction, INT32* pnMin); + +/* flags to use for nAction */ +#define ACB_READ ( 1) +#define ACB_WRITE ( 2) + +#define ACB_MEMORY_ROM ( 4) +#define ACB_NVRAM ( 8) +#define ACB_MEMCARD (16) +#define ACB_MEMORY_RAM (32) +#define ACB_DRIVER_DATA (64) + +#define ACB_FULLSCAN (ACB_NVRAM | ACB_MEMCARD | ACB_MEMORY_RAM | ACB_DRIVER_DATA) + +#define ACB_ACCESSMASK (ACB_READ | ACB_WRITE) +#define ACB_TYPEMASK (ACB_MEMORY_ROM | ACB_NVRAM | ACB_MEMCARD | ACB_MEMORY_RAM | ACB_DRIVER_DATA) + +#define ACB_VOLATILE (ACB_MEMORY_RAM | ACB_DRIVER_DATA) + +/* Structure used for area scanning */ +struct BurnArea { void *Data; UINT32 nLen; INT32 nAddress; char *szName; }; + +/* Application-defined callback for processing the area */ +extern INT32 (__cdecl *BurnAcb) (struct BurnArea* pba); + +/* Scan a small variable or structure */ +inline static void ScanVar(void* pv, INT32 nSize, char* szName) +{ + struct BurnArea ba; + memset(&ba, 0, sizeof(ba)); + ba.Data = pv; + ba.nLen = nSize; + ba.szName = szName; + BurnAcb(&ba); +} + +#define SCAN_VAR(x) ScanVar(&x, sizeof(x), #x) + +#define SCAN_OFF(x, y, a) { INT32 n = y - x; ScanVar(&n, sizeof(n), #x); if (a & ACB_WRITE) { x = y + n; } } + +#ifdef OSD_CPU_H + /* wrappers for the MAME savestate functions (used by the FM sound cores) */ + void state_save_register_func_postload(void (*pFunction)()); + + void state_save_register_INT8(const char* module, INT32 instance, const char* name, INT8* val, unsigned size); + void state_save_register_UINT8(const char* module, INT32 instance, const char* name, UINT8* val, unsigned size); + void state_save_register_INT16(const char* module, INT32 instance, const char* name, INT16* val, unsigned size); + void state_save_register_UINT16(const char* module, INT32 instance, const char* name, UINT16* val, unsigned size); + void state_save_register_INT32(const char* module, INT32 instance, const char* name, INT32* val, unsigned size); + void state_save_register_UINT32(const char* module, INT32 instance, const char* name, UINT32* val, unsigned size); + + void state_save_register_int(const char* module, INT32 instance, const char* name, INT32* val); + void state_save_register_float(const char* module, INT32 instance, const char* name, float* val, unsigned size); + void state_save_register_double(const char* module, INT32 instance, const char* name, double* val, unsigned size); +#endif + +#ifdef __cplusplus + } +#endif + +#define _STATE_H + +#endif /* _STATE_H */ diff --git a/src/burn/stdfunc.h b/src/burn/stdfunc.h new file mode 100644 index 00000000..68ecdae5 --- /dev/null +++ b/src/burn/stdfunc.h @@ -0,0 +1,148 @@ +// Standard ROM/input/DIP info functions + +// A function to pick a rom, or return NULL if i is out of range +#define STD_ROM_PICK(Name) \ +static struct BurnRomInfo* Name##PickRom(UINT32 i) \ +{ \ + if (i >= sizeof(Name##RomDesc) / sizeof(Name##RomDesc[0])) { \ + return NULL; \ + } \ + return Name##RomDesc + i; \ +} + +#define STDROMPICKEXT(Name, Info1, Info2) \ +static struct BurnRomInfo* Name##PickRom(UINT32 i) \ +{ \ + if (i >= 0x80) { \ + i &= 0x7F; \ + if (i >= sizeof(Info2##RomDesc) / sizeof(Info2##RomDesc[0])) { \ + return NULL; \ + } \ + return Info2##RomDesc + i; \ + } else { \ + if (i >= sizeof(Info1##RomDesc) / sizeof(Info1##RomDesc[0])) { \ + return emptyRomDesc + 0; \ + } \ + return Info1##RomDesc + i; \ + } \ +} + +// Standard rom functions for returning Length, Crc, Type and one one Name +#define STD_ROM_FN(Name) \ +static INT32 Name##RomInfo(struct BurnRomInfo* pri, UINT32 i) \ +{ \ + struct BurnRomInfo* por = Name##PickRom(i); \ + if (por == NULL) { \ + return 1; \ + } \ + if (pri) { \ + pri->nLen = por->nLen; \ + pri->nCrc = por->nCrc; \ + pri->nType = por->nType; \ + } \ + return 0; \ +} \ + \ +static INT32 Name##RomName(char** pszName, UINT32 i, INT32 nAka) \ +{ \ + struct BurnRomInfo *por = Name##PickRom(i); \ + if (por == NULL) { \ + return 1; \ + } \ + if (nAka) { \ + return 1; \ + } \ + *pszName = por->szName; \ + return 0; \ +} + +#define STDINPUTINFO(Name) \ +static INT32 Name##InputInfo(struct BurnInputInfo* pii, UINT32 i) \ +{ \ + if (i >= sizeof(Name##InputList) / sizeof(Name##InputList[0])) { \ + return 1; \ + } \ + if (pii) { \ + *pii = Name##InputList[i]; \ + } \ + return 0; \ +} + +#define STDINPUTINFOSPEC(Name, Info1) \ +static INT32 Name##InputInfo(struct BurnInputInfo* pii, UINT32 i) \ +{ \ + if (i >= sizeof(Info1) / sizeof(Info1[0])) { \ + return 1; \ + } \ + if (pii) { \ + *pii = Info1[i]; \ + } \ + return 0; \ +} + +#define STDDIPINFO(Name) \ +static INT32 Name##DIPInfo(struct BurnDIPInfo* pdi, UINT32 i) \ +{ \ + if (i >= sizeof(Name##DIPList) / sizeof(Name##DIPList[0])) { \ + return 1; \ + } \ + if (pdi) { \ + *pdi = Name##DIPList[i]; \ + } \ + return 0; \ +} + +#define STDDIPINFOEXT(Name, Info1, Info2) \ +static INT32 Name##DIPInfo(struct BurnDIPInfo* pdi, UINT32 i) \ +{ \ + if (i >= sizeof(Info1##DIPList) / sizeof(Info1##DIPList[0])) { \ + i -= sizeof(Info1##DIPList) / sizeof(Info1##DIPList[0]); \ + if (i >= sizeof(Info2##DIPList) / sizeof(Info2##DIPList[0])) { \ + return 1; \ + } \ + if (pdi) { \ + *pdi = Info2##DIPList[i]; \ + } \ + return 0; \ + } \ + if (pdi) { \ + *pdi = Info1##DIPList[i]; \ + } \ + return 0; \ +} + +// sample support +#define STD_SAMPLE_PICK(Name) \ +static struct BurnSampleInfo* Name##PickSample(UINT32 i) \ +{ \ + if (i >= sizeof(Name##SampleDesc) / sizeof(Name##SampleDesc[0])) { \ + return NULL; \ + } \ + return Name##SampleDesc + i; \ +} + +#define STD_SAMPLE_FN(Name) \ +static INT32 Name##SampleInfo(struct BurnSampleInfo* pri, UINT32 i) \ +{ \ + struct BurnSampleInfo* por = Name##PickSample(i); \ + if (por == NULL) { \ + return 1; \ + } \ + if (pri) { \ + pri->nFlags = por->nFlags; \ + } \ + return 0; \ +} \ + \ +static INT32 Name##SampleName(char** pszName, UINT32 i, INT32 nAka) \ +{ \ + struct BurnSampleInfo *por = Name##PickSample(i); \ + if (por == NULL) { \ + return 1; \ + } \ + if (nAka) { \ + return 1; \ + } \ + *pszName = por->szName; \ + return 0; \ +} diff --git a/src/burn/tiles_generic.cpp b/src/burn/tiles_generic.cpp new file mode 100644 index 00000000..f5bd4523 --- /dev/null +++ b/src/burn/tiles_generic.cpp @@ -0,0 +1,1990 @@ +/*================================================================================================ +Generic Tile Rendering Module - Uses the Colour-Depth Independent Image Transfer Method + +Supports 8 x 8, 16 x 16 and 32 x 32 with or without masking and with full flipping. The functions fully +support varying colour-depths and palette offsets as well as all the usual variables. + +Call GenericTilesInit() in the driver Init function to store the drivers screen size for clipping. +This function also calls BurnTransferInit(). + +Call GenericTilesExit() in the driver Exit function to clear the screen size variables. +Again, this function also calls BurnTransferExit(). + +Otherwise, use the Transfer code as usual. +================================================================================================*/ + +#include "tiles_generic.h" + +UINT8* pTileData; +INT32 nScreenWidth, nScreenHeight; + +INT32 GenericTilesInit() +{ + INT32 nRet; + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth); + } else { + BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight); + } + + nRet = BurnTransferInit(); + + return nRet; +} + +INT32 GenericTilesExit() +{ + nScreenWidth = nScreenHeight = 0; + BurnTransferExit(); + + return 0; +} + +/*================================================================================================ +Graphics Decoding +================================================================================================*/ + +inline static INT32 readbit(const UINT8 *src, INT32 bitnum) +{ + return src[bitnum / 8] & (0x80 >> (bitnum % 8)); +} + +void GfxDecode(INT32 num, INT32 numPlanes, INT32 xSize, INT32 ySize, INT32 planeoffsets[], INT32 xoffsets[], INT32 yoffsets[], INT32 modulo, UINT8 *pSrc, UINT8 *pDest) +{ + INT32 c; + + for (c = 0; c < num; c++) { + INT32 plane, x, y; + + UINT8 *dp = pDest + (c * xSize * ySize); + memset(dp, 0, xSize * ySize); + + for (plane = 0; plane < numPlanes; plane++) { + INT32 planebit = 1 << (numPlanes - 1 - plane); + INT32 planeoffs = (c * modulo) + planeoffsets[plane]; + + for (y = 0; y < ySize; y++) { + INT32 yoffs = planeoffs + yoffsets[y]; + dp = pDest + (c * xSize * ySize) + (y * xSize); + + for (x = 0; x < xSize; x++) { + if (readbit(pSrc, yoffs + xoffsets[x])) dp[x] |= planebit; + } + } + } + } +} + +void GfxDecodeSingle(INT32 which, INT32 numPlanes, INT32 xSize, INT32 ySize, INT32 planeoffsets[], INT32 xoffsets[], INT32 yoffsets[], INT32 modulo, UINT8 *pSrc, UINT8 *pDest) +{ + INT32 plane, x, y; + + UINT8 *dp = pDest + (which * xSize * ySize); + memset(dp, 0, xSize * ySize); + + for (plane = 0; plane < numPlanes; plane++) { + INT32 planebit = 1 << (numPlanes - 1 - plane); + INT32 planeoffs = (which * modulo) + planeoffsets[plane]; + + for (y = 0; y < ySize; y++) { + INT32 yoffs = planeoffs + yoffsets[y]; + dp = pDest + (which * xSize * ySize) + (y * xSize); + + for (x = 0; x < xSize; x++) { + if (readbit(pSrc, yoffs + xoffsets[x])) dp[x] |= planebit; + } + } + } +} + +//================================================================================================ + +#define PLOTPIXEL(x) pPixel[x] = nPalette | pTileData[x]; +#define PLOTPIXEL_FLIPX(x, a) pPixel[x] = nPalette | pTileData[a]; +#define PLOTPIXEL_MASK(x, mc) if (pTileData[x] != mc) {pPixel[x] = nPalette | pTileData[x];} +#define PLOTPIXEL_MASK_FLIPX(x, a, mc) if (pTileData[a] != mc) {pPixel[x] = nPalette | pTileData[a] ;} +#define CLIPPIXEL(x, sx, mx, a) if ((sx + x) >= 0 && (sx + x) < mx) { a; }; + +/*================================================================================================ +8 x 8 Functions +================================================================================================*/ + +void Render8x8Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth ) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + PLOTPIXEL(0); + PLOTPIXEL(1); + PLOTPIXEL(2); + PLOTPIXEL(3); + PLOTPIXEL(4); + PLOTPIXEL(5); + PLOTPIXEL(6); + PLOTPIXEL(7); + } +} + +void Render8x8Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL(0)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL(1)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL(2)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL(3)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL(4)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL(5)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL(6)); + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL(7)); + } +} + +void Render8x8Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + PLOTPIXEL_FLIPX(7, 0); + PLOTPIXEL_FLIPX(6, 1); + PLOTPIXEL_FLIPX(5, 2); + PLOTPIXEL_FLIPX(4, 3); + PLOTPIXEL_FLIPX(3, 4); + PLOTPIXEL_FLIPX(2, 5); + PLOTPIXEL_FLIPX(1, 6); + PLOTPIXEL_FLIPX(0, 7); + } +} + +void Render8x8Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_FLIPX(7, 0)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_FLIPX(6, 1)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_FLIPX(5, 2)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_FLIPX(4, 3)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_FLIPX(3, 4)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_FLIPX(2, 5)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_FLIPX(1, 6)); + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_FLIPX(0, 7)); + } +} + +void Render8x8Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + PLOTPIXEL(0); + PLOTPIXEL(1); + PLOTPIXEL(2); + PLOTPIXEL(3); + PLOTPIXEL(4); + PLOTPIXEL(5); + PLOTPIXEL(6); + PLOTPIXEL(7); + } +} + +void Render8x8Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL(0)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL(1)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL(2)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL(3)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL(4)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL(5)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL(6)); + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL(7)); + } +} + +void Render8x8Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + PLOTPIXEL_FLIPX(7, 0); + PLOTPIXEL_FLIPX(6, 1); + PLOTPIXEL_FLIPX(5, 2); + PLOTPIXEL_FLIPX(4, 3); + PLOTPIXEL_FLIPX(3, 4); + PLOTPIXEL_FLIPX(2, 5); + PLOTPIXEL_FLIPX(1, 6); + PLOTPIXEL_FLIPX(0, 7); + } +} + +void Render8x8Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_FLIPX(7, 0)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_FLIPX(6, 1)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_FLIPX(5, 2)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_FLIPX(4, 3)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_FLIPX(3, 4)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_FLIPX(2, 5)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_FLIPX(1, 6)); + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_FLIPX(0, 7)); + } +} + +/*================================================================================================ +8 x 8 Functions with Masking +================================================================================================*/ + +void Render8x8Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + PLOTPIXEL_MASK(0, nMaskColour); + PLOTPIXEL_MASK(1, nMaskColour); + PLOTPIXEL_MASK(2, nMaskColour); + PLOTPIXEL_MASK(3, nMaskColour); + PLOTPIXEL_MASK(4, nMaskColour); + PLOTPIXEL_MASK(5, nMaskColour); + PLOTPIXEL_MASK(6, nMaskColour); + PLOTPIXEL_MASK(7, nMaskColour); + } +} + +void Render8x8Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_MASK(0, nMaskColour)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_MASK(1, nMaskColour)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_MASK(2, nMaskColour)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_MASK(3, nMaskColour)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_MASK(4, nMaskColour)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_MASK(5, nMaskColour)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_MASK(6, nMaskColour)); + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_MASK(7, nMaskColour)); + } +} + +void Render8x8Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + PLOTPIXEL_MASK_FLIPX(7, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(6, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(5, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(4, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(3, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(2, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX(1, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX(0, 7, nMaskColour); + } +} + +void Render8x8Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 8; y++, pPixel += nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(7, 0, nMaskColour)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(6, 1, nMaskColour)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(5, 2, nMaskColour)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(4, 3, nMaskColour)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(3, 4, nMaskColour)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(2, 5, nMaskColour)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(1, 6, nMaskColour)); + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(0, 7, nMaskColour)); + } +} + +void Render8x8Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + PLOTPIXEL_MASK(0, nMaskColour); + PLOTPIXEL_MASK(1, nMaskColour); + PLOTPIXEL_MASK(2, nMaskColour); + PLOTPIXEL_MASK(3, nMaskColour); + PLOTPIXEL_MASK(4, nMaskColour); + PLOTPIXEL_MASK(5, nMaskColour); + PLOTPIXEL_MASK(6, nMaskColour); + PLOTPIXEL_MASK(7, nMaskColour); + } +} + +void Render8x8Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_MASK(0, nMaskColour)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_MASK(1, nMaskColour)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_MASK(2, nMaskColour)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_MASK(3, nMaskColour)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_MASK(4, nMaskColour)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_MASK(5, nMaskColour)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_MASK(6, nMaskColour)); + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_MASK(7, nMaskColour)); + } +} + +void Render8x8Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + PLOTPIXEL_MASK_FLIPX(7, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(6, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(5, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(4, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(3, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(2, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX(1, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX(0, 7, nMaskColour); + } +} + +void Render8x8Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 6); + + UINT16* pPixel = pDestDraw + ((StartY + 7) * nScreenWidth) + StartX; + + for (INT32 y = 7; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 8) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(7, 0, nMaskColour)); + CLIPPIXEL(6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(6, 1, nMaskColour)); + CLIPPIXEL(5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(5, 2, nMaskColour)); + CLIPPIXEL(4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(4, 3, nMaskColour)); + CLIPPIXEL(3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(3, 4, nMaskColour)); + CLIPPIXEL(2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(2, 5, nMaskColour)); + CLIPPIXEL(1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(1, 6, nMaskColour)); + CLIPPIXEL(0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(0, 7, nMaskColour)); + } +} + +/*================================================================================================ +16 x 16 Functions +================================================================================================*/ + +void Render16x16Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + PLOTPIXEL( 0); + PLOTPIXEL( 1); + PLOTPIXEL( 2); + PLOTPIXEL( 3); + PLOTPIXEL( 4); + PLOTPIXEL( 5); + PLOTPIXEL( 6); + PLOTPIXEL( 7); + PLOTPIXEL( 8); + PLOTPIXEL( 9); + PLOTPIXEL(10); + PLOTPIXEL(11); + PLOTPIXEL(12); + PLOTPIXEL(13); + PLOTPIXEL(14); + PLOTPIXEL(15); + } +} + +void Render16x16Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL( 0)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL( 1)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL( 2)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL( 3)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL( 4)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL( 5)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL( 6)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL( 7)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL( 8)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL( 9)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL(10)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL(11)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL(12)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL(13)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL(14)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL(15)); + } +} + +void Render16x16Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + PLOTPIXEL_FLIPX(15, 0); + PLOTPIXEL_FLIPX(14, 1); + PLOTPIXEL_FLIPX(13, 2); + PLOTPIXEL_FLIPX(12, 3); + PLOTPIXEL_FLIPX(11, 4); + PLOTPIXEL_FLIPX(10, 5); + PLOTPIXEL_FLIPX( 9, 6); + PLOTPIXEL_FLIPX( 8, 7); + PLOTPIXEL_FLIPX( 7, 8); + PLOTPIXEL_FLIPX( 6, 9); + PLOTPIXEL_FLIPX( 5, 10); + PLOTPIXEL_FLIPX( 4, 11); + PLOTPIXEL_FLIPX( 3, 12); + PLOTPIXEL_FLIPX( 2, 13); + PLOTPIXEL_FLIPX( 1, 14); + PLOTPIXEL_FLIPX( 0, 15); + } +} + +void Render16x16Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_FLIPX(15, 0)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_FLIPX(14, 1)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_FLIPX(13, 2)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_FLIPX(12, 3)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_FLIPX(11, 4)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_FLIPX(10, 5)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 9, 6)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 8, 7)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 7, 8)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 6, 9)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 5, 10)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 4, 11)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 3, 12)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 2, 13)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 1, 14)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 0, 15)); + } +} + +void Render16x16Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + PLOTPIXEL( 0); + PLOTPIXEL( 1); + PLOTPIXEL( 2); + PLOTPIXEL( 3); + PLOTPIXEL( 4); + PLOTPIXEL( 5); + PLOTPIXEL( 6); + PLOTPIXEL( 7); + PLOTPIXEL( 8); + PLOTPIXEL( 9); + PLOTPIXEL(10); + PLOTPIXEL(11); + PLOTPIXEL(12); + PLOTPIXEL(13); + PLOTPIXEL(14); + PLOTPIXEL(15); + } +} + +void Render16x16Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL( 0)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL( 1)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL( 2)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL( 3)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL( 4)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL( 5)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL( 6)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL( 7)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL( 8)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL( 9)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL(10)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL(11)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL(12)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL(13)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL(14)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL(15)); + } +} + +void Render16x16Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + PLOTPIXEL_FLIPX(15, 0); + PLOTPIXEL_FLIPX(14, 1); + PLOTPIXEL_FLIPX(13, 2); + PLOTPIXEL_FLIPX(12, 3); + PLOTPIXEL_FLIPX(11, 4); + PLOTPIXEL_FLIPX(10, 5); + PLOTPIXEL_FLIPX( 9, 6); + PLOTPIXEL_FLIPX( 8, 7); + PLOTPIXEL_FLIPX( 7, 8); + PLOTPIXEL_FLIPX( 6, 9); + PLOTPIXEL_FLIPX( 5, 10); + PLOTPIXEL_FLIPX( 4, 11); + PLOTPIXEL_FLIPX( 3, 12); + PLOTPIXEL_FLIPX( 2, 13); + PLOTPIXEL_FLIPX( 1, 14); + PLOTPIXEL_FLIPX( 0, 15); + } +} + +void Render16x16Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_FLIPX(15, 0)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_FLIPX(14, 1)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_FLIPX(13, 2)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_FLIPX(12, 3)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_FLIPX(11, 4)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_FLIPX(10, 5)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 9, 6)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 8, 7)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 7, 8)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 6, 9)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 5, 10)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 4, 11)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 3, 12)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 2, 13)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 1, 14)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 0, 15)); + } +} + +/*================================================================================================ +16 x 16 Functions with Masking +================================================================================================*/ + +void Render16x16Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + PLOTPIXEL_MASK( 0, nMaskColour); + PLOTPIXEL_MASK( 1, nMaskColour); + PLOTPIXEL_MASK( 2, nMaskColour); + PLOTPIXEL_MASK( 3, nMaskColour); + PLOTPIXEL_MASK( 4, nMaskColour); + PLOTPIXEL_MASK( 5, nMaskColour); + PLOTPIXEL_MASK( 6, nMaskColour); + PLOTPIXEL_MASK( 7, nMaskColour); + PLOTPIXEL_MASK( 8, nMaskColour); + PLOTPIXEL_MASK( 9, nMaskColour); + PLOTPIXEL_MASK(10, nMaskColour); + PLOTPIXEL_MASK(11, nMaskColour); + PLOTPIXEL_MASK(12, nMaskColour); + PLOTPIXEL_MASK(13, nMaskColour); + PLOTPIXEL_MASK(14, nMaskColour); + PLOTPIXEL_MASK(15, nMaskColour); + } +} + +void Render16x16Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK( 0, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK( 1, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK( 2, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK( 3, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK( 4, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK( 5, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK( 6, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK( 7, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK( 8, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK( 9, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK(10, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK(11, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK(12, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK(13, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK(14, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK(15, nMaskColour)); + } +} + +void Render16x16Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour); + } +} + +void Render16x16Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 16; y++, pPixel += nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour)); + } +} + +void Render16x16Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + PLOTPIXEL_MASK( 0, nMaskColour); + PLOTPIXEL_MASK( 1, nMaskColour); + PLOTPIXEL_MASK( 2, nMaskColour); + PLOTPIXEL_MASK( 3, nMaskColour); + PLOTPIXEL_MASK( 4, nMaskColour); + PLOTPIXEL_MASK( 5, nMaskColour); + PLOTPIXEL_MASK( 6, nMaskColour); + PLOTPIXEL_MASK( 7, nMaskColour); + PLOTPIXEL_MASK( 8, nMaskColour); + PLOTPIXEL_MASK( 9, nMaskColour); + PLOTPIXEL_MASK(10, nMaskColour); + PLOTPIXEL_MASK(11, nMaskColour); + PLOTPIXEL_MASK(12, nMaskColour); + PLOTPIXEL_MASK(13, nMaskColour); + PLOTPIXEL_MASK(14, nMaskColour); + PLOTPIXEL_MASK(15, nMaskColour); + } +} + +void Render16x16Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK( 0, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK( 1, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK( 2, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK( 3, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK( 4, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK( 5, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK( 6, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK( 7, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK( 8, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK( 9, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK(10, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK(11, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK(12, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK(13, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK(14, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK(15, nMaskColour)); + } +} + +void Render16x16Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour); + } +} + +void Render16x16Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 8); + + UINT16* pPixel = pDestDraw + ((StartY + 15) * nScreenWidth) + StartX; + + for (INT32 y = 15; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 16) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(15, 0, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(14, 1, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(13, 2, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(12, 3, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(11, 4, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(10, 5, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 9, 6, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 8, 7, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 7, 8, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 6, 9, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 5, 10, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 4, 11, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 3, 12, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 2, 13, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 1, 14, nMaskColour)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 0, 15, nMaskColour)); + } +} + +/*================================================================================================ +32 x 32 Functions +================================================================================================*/ + +void Render32x32Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + PLOTPIXEL( 0); + PLOTPIXEL( 1); + PLOTPIXEL( 2); + PLOTPIXEL( 3); + PLOTPIXEL( 4); + PLOTPIXEL( 5); + PLOTPIXEL( 6); + PLOTPIXEL( 7); + PLOTPIXEL( 8); + PLOTPIXEL( 9); + PLOTPIXEL(10); + PLOTPIXEL(11); + PLOTPIXEL(12); + PLOTPIXEL(13); + PLOTPIXEL(14); + PLOTPIXEL(15); + PLOTPIXEL(16); + PLOTPIXEL(17); + PLOTPIXEL(18); + PLOTPIXEL(19); + PLOTPIXEL(20); + PLOTPIXEL(21); + PLOTPIXEL(22); + PLOTPIXEL(23); + PLOTPIXEL(24); + PLOTPIXEL(25); + PLOTPIXEL(26); + PLOTPIXEL(27); + PLOTPIXEL(28); + PLOTPIXEL(29); + PLOTPIXEL(30); + PLOTPIXEL(31); + } +} + +void Render32x32Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL( 0)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL( 1)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL( 2)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL( 3)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL( 4)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL( 5)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL( 6)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL( 7)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL( 8)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL( 9)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL(10)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL(11)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL(12)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL(13)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL(14)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL(15)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL(16)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL(17)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL(18)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL(19)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL(20)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL(21)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL(22)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL(23)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL(24)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL(25)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL(26)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL(27)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL(28)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL(29)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL(30)); + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL(31)); + } +} + +void Render32x32Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + PLOTPIXEL_FLIPX(31, 0); + PLOTPIXEL_FLIPX(30, 1); + PLOTPIXEL_FLIPX(29, 2); + PLOTPIXEL_FLIPX(28, 3); + PLOTPIXEL_FLIPX(27, 4); + PLOTPIXEL_FLIPX(26, 5); + PLOTPIXEL_FLIPX(25, 6); + PLOTPIXEL_FLIPX(24, 7); + PLOTPIXEL_FLIPX(23, 8); + PLOTPIXEL_FLIPX(22, 9); + PLOTPIXEL_FLIPX(21, 10); + PLOTPIXEL_FLIPX(20, 11); + PLOTPIXEL_FLIPX(19, 12); + PLOTPIXEL_FLIPX(18, 13); + PLOTPIXEL_FLIPX(17, 14); + PLOTPIXEL_FLIPX(16, 15); + PLOTPIXEL_FLIPX(15, 16); + PLOTPIXEL_FLIPX(14, 17); + PLOTPIXEL_FLIPX(13, 18); + PLOTPIXEL_FLIPX(12, 19); + PLOTPIXEL_FLIPX(11, 20); + PLOTPIXEL_FLIPX(10, 21); + PLOTPIXEL_FLIPX( 9, 22); + PLOTPIXEL_FLIPX( 8, 23); + PLOTPIXEL_FLIPX( 7, 24); + PLOTPIXEL_FLIPX( 6, 25); + PLOTPIXEL_FLIPX( 5, 26); + PLOTPIXEL_FLIPX( 4, 27); + PLOTPIXEL_FLIPX( 3, 28); + PLOTPIXEL_FLIPX( 2, 29); + PLOTPIXEL_FLIPX( 1, 30); + PLOTPIXEL_FLIPX( 0, 31); + } +} + +void Render32x32Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_FLIPX(31, 0)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_FLIPX(30, 1)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_FLIPX(29, 2)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_FLIPX(28, 3)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_FLIPX(27, 4)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_FLIPX(26, 5)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_FLIPX(25, 6)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_FLIPX(24, 7)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_FLIPX(23, 8)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_FLIPX(22, 9)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_FLIPX(21, 10)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_FLIPX(20, 11)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_FLIPX(19, 12)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_FLIPX(18, 13)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_FLIPX(17, 14)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_FLIPX(16, 15)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_FLIPX(15, 16)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_FLIPX(14, 17)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_FLIPX(13, 18)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_FLIPX(12, 19)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_FLIPX(11, 20)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_FLIPX(10, 21)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 9, 22)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 8, 23)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 7, 24)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 6, 25)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 5, 26)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 4, 27)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 3, 28)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 2, 29)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 1, 30)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 0, 31)); + } +} + +void Render32x32Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + PLOTPIXEL( 0); + PLOTPIXEL( 1); + PLOTPIXEL( 2); + PLOTPIXEL( 3); + PLOTPIXEL( 4); + PLOTPIXEL( 5); + PLOTPIXEL( 6); + PLOTPIXEL( 7); + PLOTPIXEL( 8); + PLOTPIXEL( 9); + PLOTPIXEL(10); + PLOTPIXEL(11); + PLOTPIXEL(12); + PLOTPIXEL(13); + PLOTPIXEL(14); + PLOTPIXEL(15); + PLOTPIXEL(16); + PLOTPIXEL(17); + PLOTPIXEL(18); + PLOTPIXEL(19); + PLOTPIXEL(20); + PLOTPIXEL(21); + PLOTPIXEL(22); + PLOTPIXEL(23); + PLOTPIXEL(24); + PLOTPIXEL(25); + PLOTPIXEL(26); + PLOTPIXEL(27); + PLOTPIXEL(28); + PLOTPIXEL(29); + PLOTPIXEL(30); + PLOTPIXEL(31); + } +} + +void Render32x32Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL( 0)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL( 1)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL( 2)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL( 3)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL( 4)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL( 5)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL( 6)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL( 7)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL( 8)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL( 9)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL(10)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL(11)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL(12)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL(13)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL(14)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL(15)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL(16)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL(17)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL(18)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL(19)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL(20)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL(21)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL(22)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL(23)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL(24)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL(25)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL(26)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL(27)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL(28)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL(29)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL(30)); + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL(31)); + } +} + +void Render32x32Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + PLOTPIXEL_FLIPX(31, 0); + PLOTPIXEL_FLIPX(30, 1); + PLOTPIXEL_FLIPX(29, 2); + PLOTPIXEL_FLIPX(28, 3); + PLOTPIXEL_FLIPX(27, 4); + PLOTPIXEL_FLIPX(26, 5); + PLOTPIXEL_FLIPX(25, 6); + PLOTPIXEL_FLIPX(24, 7); + PLOTPIXEL_FLIPX(23, 8); + PLOTPIXEL_FLIPX(22, 9); + PLOTPIXEL_FLIPX(21, 10); + PLOTPIXEL_FLIPX(20, 11); + PLOTPIXEL_FLIPX(19, 12); + PLOTPIXEL_FLIPX(18, 13); + PLOTPIXEL_FLIPX(17, 14); + PLOTPIXEL_FLIPX(16, 15); + PLOTPIXEL_FLIPX(15, 16); + PLOTPIXEL_FLIPX(14, 17); + PLOTPIXEL_FLIPX(13, 18); + PLOTPIXEL_FLIPX(12, 19); + PLOTPIXEL_FLIPX(11, 20); + PLOTPIXEL_FLIPX(10, 21); + PLOTPIXEL_FLIPX( 9, 22); + PLOTPIXEL_FLIPX( 8, 23); + PLOTPIXEL_FLIPX( 7, 24); + PLOTPIXEL_FLIPX( 6, 25); + PLOTPIXEL_FLIPX( 5, 26); + PLOTPIXEL_FLIPX( 4, 27); + PLOTPIXEL_FLIPX( 3, 28); + PLOTPIXEL_FLIPX( 2, 29); + PLOTPIXEL_FLIPX( 1, 30); + PLOTPIXEL_FLIPX( 0, 31); + } +} + +void Render32x32Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_FLIPX(31, 0)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_FLIPX(30, 1)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_FLIPX(29, 2)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_FLIPX(28, 3)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_FLIPX(27, 4)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_FLIPX(26, 5)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_FLIPX(25, 6)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_FLIPX(24, 7)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_FLIPX(23, 8)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_FLIPX(22, 9)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_FLIPX(21, 10)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_FLIPX(20, 11)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_FLIPX(19, 12)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_FLIPX(18, 13)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_FLIPX(17, 14)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_FLIPX(16, 15)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_FLIPX(15, 16)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_FLIPX(14, 17)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_FLIPX(13, 18)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_FLIPX(12, 19)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_FLIPX(11, 20)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_FLIPX(10, 21)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 9, 22)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 8, 23)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 7, 24)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 6, 25)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 5, 26)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 4, 27)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 3, 28)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 2, 29)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 1, 30)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_FLIPX( 0, 31)); + } +} + +/*================================================================================================ +32 x 32 Functions with Masking +================================================================================================*/ + +void Render32x32Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + PLOTPIXEL_MASK( 0, nMaskColour); + PLOTPIXEL_MASK( 1, nMaskColour); + PLOTPIXEL_MASK( 2, nMaskColour); + PLOTPIXEL_MASK( 3, nMaskColour); + PLOTPIXEL_MASK( 4, nMaskColour); + PLOTPIXEL_MASK( 5, nMaskColour); + PLOTPIXEL_MASK( 6, nMaskColour); + PLOTPIXEL_MASK( 7, nMaskColour); + PLOTPIXEL_MASK( 8, nMaskColour); + PLOTPIXEL_MASK( 9, nMaskColour); + PLOTPIXEL_MASK(10, nMaskColour); + PLOTPIXEL_MASK(11, nMaskColour); + PLOTPIXEL_MASK(12, nMaskColour); + PLOTPIXEL_MASK(13, nMaskColour); + PLOTPIXEL_MASK(14, nMaskColour); + PLOTPIXEL_MASK(15, nMaskColour); + PLOTPIXEL_MASK(16, nMaskColour); + PLOTPIXEL_MASK(17, nMaskColour); + PLOTPIXEL_MASK(18, nMaskColour); + PLOTPIXEL_MASK(19, nMaskColour); + PLOTPIXEL_MASK(20, nMaskColour); + PLOTPIXEL_MASK(21, nMaskColour); + PLOTPIXEL_MASK(22, nMaskColour); + PLOTPIXEL_MASK(23, nMaskColour); + PLOTPIXEL_MASK(24, nMaskColour); + PLOTPIXEL_MASK(25, nMaskColour); + PLOTPIXEL_MASK(26, nMaskColour); + PLOTPIXEL_MASK(27, nMaskColour); + PLOTPIXEL_MASK(28, nMaskColour); + PLOTPIXEL_MASK(29, nMaskColour); + PLOTPIXEL_MASK(30, nMaskColour); + PLOTPIXEL_MASK(31, nMaskColour); + } +} + +void Render32x32Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK( 0, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK( 1, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK( 2, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK( 3, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK( 4, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK( 5, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK( 6, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK( 7, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK( 8, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK( 9, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK(10, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK(11, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK(12, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK(13, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK(14, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK(15, nMaskColour)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_MASK(16, nMaskColour)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_MASK(17, nMaskColour)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_MASK(18, nMaskColour)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_MASK(19, nMaskColour)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_MASK(20, nMaskColour)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_MASK(21, nMaskColour)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_MASK(22, nMaskColour)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_MASK(23, nMaskColour)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_MASK(24, nMaskColour)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_MASK(25, nMaskColour)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_MASK(26, nMaskColour)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_MASK(27, nMaskColour)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_MASK(28, nMaskColour)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_MASK(29, nMaskColour)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_MASK(30, nMaskColour)); + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_MASK(31, nMaskColour)); + } +} + +void Render32x32Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + PLOTPIXEL_MASK_FLIPX(31, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(30, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(29, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(28, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(27, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(26, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX(25, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX(24, 7, nMaskColour); + PLOTPIXEL_MASK_FLIPX(23, 8, nMaskColour); + PLOTPIXEL_MASK_FLIPX(22, 9, nMaskColour); + PLOTPIXEL_MASK_FLIPX(21, 10, nMaskColour); + PLOTPIXEL_MASK_FLIPX(20, 11, nMaskColour); + PLOTPIXEL_MASK_FLIPX(19, 12, nMaskColour); + PLOTPIXEL_MASK_FLIPX(18, 13, nMaskColour); + PLOTPIXEL_MASK_FLIPX(17, 14, nMaskColour); + PLOTPIXEL_MASK_FLIPX(16, 15, nMaskColour); + PLOTPIXEL_MASK_FLIPX(15, 16, nMaskColour); + PLOTPIXEL_MASK_FLIPX(14, 17, nMaskColour); + PLOTPIXEL_MASK_FLIPX(13, 18, nMaskColour); + PLOTPIXEL_MASK_FLIPX(12, 19, nMaskColour); + PLOTPIXEL_MASK_FLIPX(11, 20, nMaskColour); + PLOTPIXEL_MASK_FLIPX(10, 21, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 9, 22, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 8, 23, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 7, 24, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 6, 25, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 5, 26, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 4, 27, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 3, 28, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 2, 29, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 1, 30, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 0, 31, nMaskColour); + } +} + +void Render32x32Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < 32; y++, pPixel += nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(31, 0, nMaskColour)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(30, 1, nMaskColour)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(29, 2, nMaskColour)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(28, 3, nMaskColour)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(27, 4, nMaskColour)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(26, 5, nMaskColour)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(25, 6, nMaskColour)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(24, 7, nMaskColour)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(23, 8, nMaskColour)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(22, 9, nMaskColour)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(21, 10, nMaskColour)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(20, 11, nMaskColour)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(19, 12, nMaskColour)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(18, 13, nMaskColour)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(17, 14, nMaskColour)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(16, 15, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(15, 16, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(14, 17, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(13, 18, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(12, 19, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(11, 20, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(10, 21, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 9, 22, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 8, 23, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 7, 24, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 6, 25, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 5, 26, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 4, 27, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 3, 28, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 2, 29, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 1, 30, nMaskColour)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 0, 31, nMaskColour)); + } +} + +void Render32x32Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + PLOTPIXEL_MASK( 0, nMaskColour); + PLOTPIXEL_MASK( 1, nMaskColour); + PLOTPIXEL_MASK( 2, nMaskColour); + PLOTPIXEL_MASK( 3, nMaskColour); + PLOTPIXEL_MASK( 4, nMaskColour); + PLOTPIXEL_MASK( 5, nMaskColour); + PLOTPIXEL_MASK( 6, nMaskColour); + PLOTPIXEL_MASK( 7, nMaskColour); + PLOTPIXEL_MASK( 8, nMaskColour); + PLOTPIXEL_MASK( 9, nMaskColour); + PLOTPIXEL_MASK(10, nMaskColour); + PLOTPIXEL_MASK(11, nMaskColour); + PLOTPIXEL_MASK(12, nMaskColour); + PLOTPIXEL_MASK(13, nMaskColour); + PLOTPIXEL_MASK(14, nMaskColour); + PLOTPIXEL_MASK(15, nMaskColour); + PLOTPIXEL_MASK(16, nMaskColour); + PLOTPIXEL_MASK(17, nMaskColour); + PLOTPIXEL_MASK(18, nMaskColour); + PLOTPIXEL_MASK(19, nMaskColour); + PLOTPIXEL_MASK(20, nMaskColour); + PLOTPIXEL_MASK(21, nMaskColour); + PLOTPIXEL_MASK(22, nMaskColour); + PLOTPIXEL_MASK(23, nMaskColour); + PLOTPIXEL_MASK(24, nMaskColour); + PLOTPIXEL_MASK(25, nMaskColour); + PLOTPIXEL_MASK(26, nMaskColour); + PLOTPIXEL_MASK(27, nMaskColour); + PLOTPIXEL_MASK(28, nMaskColour); + PLOTPIXEL_MASK(29, nMaskColour); + PLOTPIXEL_MASK(30, nMaskColour); + PLOTPIXEL_MASK(31, nMaskColour); + } +} + +void Render32x32Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK( 0, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK( 1, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK( 2, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK( 3, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK( 4, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK( 5, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK( 6, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK( 7, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK( 8, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK( 9, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK(10, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK(11, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK(12, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK(13, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK(14, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK(15, nMaskColour)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_MASK(16, nMaskColour)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_MASK(17, nMaskColour)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_MASK(18, nMaskColour)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_MASK(19, nMaskColour)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_MASK(20, nMaskColour)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_MASK(21, nMaskColour)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_MASK(22, nMaskColour)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_MASK(23, nMaskColour)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_MASK(24, nMaskColour)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_MASK(25, nMaskColour)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_MASK(26, nMaskColour)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_MASK(27, nMaskColour)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_MASK(28, nMaskColour)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_MASK(29, nMaskColour)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_MASK(30, nMaskColour)); + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_MASK(31, nMaskColour)); + } +} + +void Render32x32Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + PLOTPIXEL_MASK_FLIPX(31, 0, nMaskColour); + PLOTPIXEL_MASK_FLIPX(30, 1, nMaskColour); + PLOTPIXEL_MASK_FLIPX(29, 2, nMaskColour); + PLOTPIXEL_MASK_FLIPX(28, 3, nMaskColour); + PLOTPIXEL_MASK_FLIPX(27, 4, nMaskColour); + PLOTPIXEL_MASK_FLIPX(26, 5, nMaskColour); + PLOTPIXEL_MASK_FLIPX(25, 6, nMaskColour); + PLOTPIXEL_MASK_FLIPX(24, 7, nMaskColour); + PLOTPIXEL_MASK_FLIPX(23, 8, nMaskColour); + PLOTPIXEL_MASK_FLIPX(22, 9, nMaskColour); + PLOTPIXEL_MASK_FLIPX(21, 10, nMaskColour); + PLOTPIXEL_MASK_FLIPX(20, 11, nMaskColour); + PLOTPIXEL_MASK_FLIPX(19, 12, nMaskColour); + PLOTPIXEL_MASK_FLIPX(18, 13, nMaskColour); + PLOTPIXEL_MASK_FLIPX(17, 14, nMaskColour); + PLOTPIXEL_MASK_FLIPX(16, 15, nMaskColour); + PLOTPIXEL_MASK_FLIPX(15, 16, nMaskColour); + PLOTPIXEL_MASK_FLIPX(14, 17, nMaskColour); + PLOTPIXEL_MASK_FLIPX(13, 18, nMaskColour); + PLOTPIXEL_MASK_FLIPX(12, 19, nMaskColour); + PLOTPIXEL_MASK_FLIPX(11, 20, nMaskColour); + PLOTPIXEL_MASK_FLIPX(10, 21, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 9, 22, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 8, 23, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 7, 24, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 6, 25, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 5, 26, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 4, 27, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 3, 28, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 2, 29, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 1, 30, nMaskColour); + PLOTPIXEL_MASK_FLIPX( 0, 31, nMaskColour); + } +} + +void Render32x32Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber << 10); + + UINT16* pPixel = pDestDraw + ((StartY + 31) * nScreenWidth) + StartX; + + for (INT32 y = 31; y >= 0; y--, pPixel -= nScreenWidth, pTileData += 32) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + CLIPPIXEL(31, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(31, 0, nMaskColour)); + CLIPPIXEL(30, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(30, 1, nMaskColour)); + CLIPPIXEL(29, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(29, 2, nMaskColour)); + CLIPPIXEL(28, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(28, 3, nMaskColour)); + CLIPPIXEL(27, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(27, 4, nMaskColour)); + CLIPPIXEL(26, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(26, 5, nMaskColour)); + CLIPPIXEL(25, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(25, 6, nMaskColour)); + CLIPPIXEL(24, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(24, 7, nMaskColour)); + CLIPPIXEL(23, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(23, 8, nMaskColour)); + CLIPPIXEL(22, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(22, 9, nMaskColour)); + CLIPPIXEL(21, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(21, 10, nMaskColour)); + CLIPPIXEL(20, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(20, 11, nMaskColour)); + CLIPPIXEL(19, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(19, 12, nMaskColour)); + CLIPPIXEL(18, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(18, 13, nMaskColour)); + CLIPPIXEL(17, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(17, 14, nMaskColour)); + CLIPPIXEL(16, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(16, 15, nMaskColour)); + CLIPPIXEL(15, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(15, 16, nMaskColour)); + CLIPPIXEL(14, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(14, 17, nMaskColour)); + CLIPPIXEL(13, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(13, 18, nMaskColour)); + CLIPPIXEL(12, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(12, 19, nMaskColour)); + CLIPPIXEL(11, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(11, 20, nMaskColour)); + CLIPPIXEL(10, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(10, 21, nMaskColour)); + CLIPPIXEL( 9, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 9, 22, nMaskColour)); + CLIPPIXEL( 8, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 8, 23, nMaskColour)); + CLIPPIXEL( 7, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 7, 24, nMaskColour)); + CLIPPIXEL( 6, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 6, 25, nMaskColour)); + CLIPPIXEL( 5, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 5, 26, nMaskColour)); + CLIPPIXEL( 4, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 4, 27, nMaskColour)); + CLIPPIXEL( 3, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 3, 28, nMaskColour)); + CLIPPIXEL( 2, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 2, 29, nMaskColour)); + CLIPPIXEL( 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 1, 30, nMaskColour)); + CLIPPIXEL( 0, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX( 0, 31, nMaskColour)); + } +} + +/*================================================================================================ +Custom Height and Width Functions +================================================================================================*/ + +void RenderCustomTile(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth ) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL(x); + } + } +} + +void RenderCustomTile_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(x, StartX, nScreenWidth, PLOTPIXEL(x)); + } + } +} + +void RenderCustomTile_FlipX(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_FLIPX(nWidth - x - 1, x); + } + } +} + +void RenderCustomTile_FlipX_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(nWidth - x - 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX(nWidth - x - 1, x)); + } + } +} + +void RenderCustomTile_FlipY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL(x); + } + } +} + +void RenderCustomTile_FlipY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(x, StartX, nScreenWidth, PLOTPIXEL(x)); + } + } +} + +void RenderCustomTile_FlipXY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_FLIPX(nWidth - x - 1, x); + } + } +} + +void RenderCustomTile_FlipXY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(nWidth - x - 1, StartX, nScreenWidth, PLOTPIXEL_FLIPX(nWidth - x - 1, x)); + } + } +} + +/*================================================================================================ +Custom Height and Width Functions with Masking +================================================================================================*/ + +void RenderCustomTile_Mask(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_MASK(x, nMaskColour); + } + } +} + +void RenderCustomTile_Mask_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(x, StartX, nScreenWidth, PLOTPIXEL_MASK(x, nMaskColour)); + } + } +} + +void RenderCustomTile_Mask_FlipX(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_MASK_FLIPX(nWidth - x - 1, x, nMaskColour); + } + } +} + +void RenderCustomTile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + (StartY * nScreenWidth) + StartX; + + for (INT32 y = 0; y < nHeight; y++, pPixel += nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(nWidth - x - 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(nWidth - x - 1, x, nMaskColour)); + } + } +} + +void RenderCustomTile_Mask_FlipY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_MASK(x, nMaskColour); + } + } +} + +void RenderCustomTile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(x, StartX, nScreenWidth, PLOTPIXEL_MASK(x, nMaskColour)); + } + } +} + +void RenderCustomTile_Mask_FlipXY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + for (INT32 x = 0; x < nWidth; x++) { + PLOTPIXEL_MASK_FLIPX(nWidth - x - 1, x, nMaskColour); + } + } +} + +void RenderCustomTile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile) +{ + UINT32 nPalette = (nTilePalette << nColourDepth) | nPaletteOffset; + pTileData = pTile + (nTileNumber * nWidth * nHeight); + + UINT16* pPixel = pDestDraw + ((StartY + nHeight - 1) * nScreenWidth) + StartX; + + for (INT32 y = nHeight - 1; y >= 0; y--, pPixel -= nScreenWidth, pTileData += nHeight) { + if ((StartY + y) < 0 || (StartY + y) >= nScreenHeight) { + continue; + } + + for (INT32 x = 0; x < nWidth; x++) { + CLIPPIXEL(nWidth - x - 1, StartX, nScreenWidth, PLOTPIXEL_MASK_FLIPX(nWidth - x - 1, x, nMaskColour)); + } + } +} + +#undef PLOTPIXEL +#undef PLOTPIXEL_FLIPX +#undef PLOTPIXEL_MASK +#undef CLIPPIXEL + +/*================================================================================================ +Zoomed Tile Functions +================================================================================================*/ + +void RenderZoomedTile(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 t, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 width, INT32 height, INT32 zoomx, INT32 zoomy) +{ + INT32 h = ((zoomy << 4) + 0x8000) >> 16; + INT32 w = ((zoomx << 4) + 0x8000) >> 16; + + if (!h || !w || sx + w < 0 || sy + h < 0 || sx >= nScreenWidth || sy >= nScreenHeight) return; + + if (fy) fy = (height-1)*width; + if (fx) fy |= (width-1); + + INT32 hz = (height << 12) / h; + INT32 wz = (width << 12) / w; + + INT32 starty = 0, startx = 0, endy = h, endx = w; + if (sy < 0) starty = 0 - sy; + if (sx < 0) startx = 0 - sx; + if (sy + h >= nScreenHeight) endy -= (h + sy) - nScreenHeight; + if (sx + w >= nScreenWidth ) endx -= (w + sx) - nScreenWidth; + + UINT8 *src = gfx + (code * width * height); + UINT16 *dst = dest + (sy + starty) * nScreenWidth + sx; + + for (INT32 y = starty; y < endy; y++) + { + INT32 zy = ((y * hz) >> 12) * width; + + for (INT32 x = startx; x < endx; x++) + { + INT32 pxl = src[(zy + ((x * wz) >> 12)) ^ fy]; + + if (pxl != t) dst[x] = pxl | color; + } + + dst += nScreenWidth; + } +} + +/*================================================================================================ +Tile with Transparency Table Functions +================================================================================================*/ + +void RenderTileTranstab(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 trans_col, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height, UINT8 *tab) +{ + INT32 flip = 0; + if (flipy) flip |= (height - 1) * width; + if (flipx) flip |= width - 1; + + gfx += code * width * height; + + for (INT32 y = 0; y < height; y++, sy++) { + if (sy < 0 || sy >= nScreenHeight) continue; + + for (INT32 x = 0; x < width; x++, sx++) { + if (sx < 0 || sx >= nScreenWidth) continue; + + INT32 pxl = gfx[((y * width) + x) ^ flip] | color; + + if (tab[pxl] == trans_col) continue; + + dest[sy * nScreenWidth + sx] = pxl; + } + + sx -= width; + } +} diff --git a/src/burn/tiles_generic.h b/src/burn/tiles_generic.h new file mode 100644 index 00000000..a57e12b5 --- /dev/null +++ b/src/burn/tiles_generic.h @@ -0,0 +1,86 @@ +#include "burnint.h" + +extern UINT8* pTileData; +extern INT32 nScreenWidth, nScreenHeight; + +INT32 GenericTilesInit(); +INT32 GenericTilesExit(); + +void GfxDecode(INT32 num, INT32 numPlanes, INT32 xSize, INT32 ySize, INT32 planeoffsets[], INT32 xoffsets[], INT32 yoffsets[], INT32 modulo, UINT8 *pSrc, UINT8 *pDest); +void GfxDecodeSingle(INT32 which, INT32 numPlanes, INT32 xSize, INT32 ySize, INT32 planeoffsets[], INT32 xoffsets[], INT32 yoffsets[], INT32 modulo, UINT8 *pSrc, UINT8 *pDest); + +void RenderZoomedTile(UINT16 *pDestDraw, UINT8 *gfx, INT32 code, INT32 color, INT32 trans_color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height, INT32 zoomx, INT32 zoomy); + +void RenderTileTranstab(UINT16 *dest, UINT8 *gfx, INT32 code, INT32 color, INT32 trans_col, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height, UINT8 *tab); + +void Render8x8Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); + +void Render8x8Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render8x8Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); + +void Render16x16Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); + +void Render16x16Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render16x16Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); + +void Render32x32Tile(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); + +void Render32x32Tile_Mask(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipX(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipXY(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void Render32x32Tile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); + +void RenderCustomTile(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipX(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipX_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipXY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_FlipXY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nPaletteOffset, UINT8 *pTile); + +void RenderCustomTile_Mask(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipX(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipX_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipXY(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); +void RenderCustomTile_Mask_FlipXY_Clip(UINT16* pDestDraw, INT32 nWidth, INT32 nHeight, INT32 nTileNumber, INT32 StartX, INT32 StartY, INT32 nTilePalette, INT32 nColourDepth, INT32 nMaskColour, INT32 nPaletteOffset, UINT8 *pTile); diff --git a/src/burn/timer.cpp b/src/burn/timer.cpp new file mode 100644 index 00000000..68cc9152 --- /dev/null +++ b/src/burn/timer.cpp @@ -0,0 +1,430 @@ +// Timers (for Yamaha FM cips and generic) +#include "burnint.h" +#include "timer.h" +#include "m6809_intf.h" +#include "hd6309_intf.h" +#include "m6800_intf.h" +#include "m6502_intf.h" +#include "sh2.h" +//#include "h6280_intf.h" + +#define MAX_TIMER_VALUE ((1 << 30) - 65536) + +double dTime; // Time elapsed since the emulated machine was started + +static INT32 nTimerCount[2], nTimerStart[2]; + +// Callbacks +static INT32 (*pTimerOverCallback)(INT32, INT32); +static double (*pTimerTimeCallback)(); + +static INT32 nCPUClockspeed = 0; +static INT32 (*pCPUTotalCycles)() = NULL; +static INT32 (*pCPURun)(INT32) = NULL; +static void (*pCPURunEnd)() = NULL; + +// --------------------------------------------------------------------------- +// Running time + +static double BurnTimerTimeCallbackDummy() +{ + return 0.0; +} + +extern "C" double BurnTimerGetTime() +{ + return dTime + pTimerTimeCallback(); +} + +// --------------------------------------------------------------------------- +// Update timers + +static INT32 nTicksTotal, nTicksDone, nTicksExtra; + +INT32 BurnTimerUpdate(INT32 nCycles) +{ + INT32 nIRQStatus = 0; + + nTicksTotal = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" -- Ticks: %08X, cycles %i\n"), nTicksTotal, nCycles); + + while (nTicksDone < nTicksTotal) { + INT32 nTimer, nCyclesSegment, nTicksSegment; + + // Determine which timer fires first + if (nTimerCount[0] <= nTimerCount[1]) { + nTicksSegment = nTimerCount[0]; + } else { + nTicksSegment = nTimerCount[1]; + } + if (nTicksSegment > nTicksTotal) { + nTicksSegment = nTicksTotal; + } + + nCyclesSegment = MAKE_CPU_CYLES(nTicksSegment + nTicksExtra, nCPUClockspeed); +// bprintf(PRINT_NORMAL, _T(" - Timer: %08X, %08X, %08X, cycles %i, %i\n"), nTicksDone, nTicksSegment, nTicksTotal, nCyclesSegment, pCPUTotalCycles()); + + pCPURun(nCyclesSegment - pCPUTotalCycles()); + + nTicksDone = MAKE_TIMER_TICKS(pCPUTotalCycles() + 1, nCPUClockspeed) - 1; +// bprintf(PRINT_NORMAL, _T(" - ticks done -> %08X cycles -> %i\n"), nTicksDone, pCPUTotalCycles()); + + nTimer = 0; + if (nTicksDone >= nTimerCount[0]) { + if (nTimerStart[0] == MAX_TIMER_VALUE) { + nTimerCount[0] = MAX_TIMER_VALUE; + } else { + nTimerCount[0] += nTimerStart[0]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 0 fired\n")); + nTimer |= 1; + } + if (nTicksDone >= nTimerCount[1]) { + if (nTimerStart[1] == MAX_TIMER_VALUE) { + nTimerCount[1] = MAX_TIMER_VALUE; + } else { + nTimerCount[1] += nTimerStart[1]; + } +// bprintf(PRINT_NORMAL, _T(" - timer 1 fired\n")); + nTimer |= 2; + } + if (nTimer & 1) { + nIRQStatus |= pTimerOverCallback(0, 0); + } + if (nTimer & 2) { + nIRQStatus |= pTimerOverCallback(0, 1); + } + } + + return nIRQStatus; +} + +void BurnTimerEndFrame(INT32 nCycles) +{ + INT32 nTicks = MAKE_TIMER_TICKS(nCycles, nCPUClockspeed); + + BurnTimerUpdate(nCycles); + + if (nTimerCount[0] < MAX_TIMER_VALUE) { + nTimerCount[0] -= nTicks; + } + if (nTimerCount[1] < MAX_TIMER_VALUE) { + nTimerCount[1] -= nTicks; + } + + nTicksDone -= nTicks; + if (nTicksDone < 0) { +// bprintf(PRINT_ERROR, _T(" -- ticks done -> %08X\n"), nTicksDone); + nTicksDone = 0; + } +} + +void BurnTimerUpdateEnd() +{ +// bprintf(PRINT_NORMAL, _T(" - end %i\n"), pCPUTotalCycles()); + + pCPURunEnd(); + + nTicksTotal = 0; +} + + +// --------------------------------------------------------------------------- +// Callbacks for the sound cores +/* +static INT32 BurnTimerExtraCallbackDummy() +{ + return 0; +} +*/ +void BurnOPLTimerCallback(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerCount[c] = MAX_TIMER_VALUE; +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + return; + } + + nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnOPMTimerCallback(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerCount[c] = MAX_TIMER_VALUE; + return; + } + + nTimerCount[c] = (INT32)(period * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); +} + +void BurnOPNTimerCallback(INT32 /*n */, INT32 c, INT32 cnt, double stepTime) +{ + pCPURunEnd(); + + if (cnt == 0) { + nTimerCount[c] = MAX_TIMER_VALUE; + +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + + return; + } + + nTimerCount[c] = (INT32)(stepTime * cnt * (double)TIMER_TICKS_PER_SECOND); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], stepTime * cnt); +} + +void BurnYMFTimerCallback(INT32 /* n */, INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE; + +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + + return; + } + + nTimerStart[c] = nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND / 1000000)); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnTimerSetRetrig(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE; + +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + + return; + } + + nTimerStart[c] = nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND)); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period); +} + +void BurnTimerSetOneshot(INT32 c, double period) +{ + pCPURunEnd(); + + if (period == 0.0) { + nTimerStart[c] = nTimerCount[c] = MAX_TIMER_VALUE; + +// bprintf(PRINT_NORMAL, _T(" - timer %i stopped\n"), c); + + return; + } + + nTimerCount[c] = (INT32)(period * (double)(TIMER_TICKS_PER_SECOND)); + nTimerCount[c] += MAKE_TIMER_TICKS(pCPUTotalCycles(), nCPUClockspeed); + +// bprintf(PRINT_NORMAL, _T(" - timer %i started, %08X ticks (fires in %lf seconds)\n"), c, nTimerCount[c], period / 1000000.0); +} + +// ------------------------------------ --------------------------------------- +// Initialisation etc. + +void BurnTimerScan(INT32 nAction, INT32* pnMin) +{ + if (pnMin && *pnMin < 0x029521) { + *pnMin = 0x029521; + } + + if (nAction & ACB_DRIVER_DATA) { + SCAN_VAR(nTimerCount); + SCAN_VAR(nTimerStart); + SCAN_VAR(dTime); + + SCAN_VAR(nTicksDone); + } +} + +void BurnTimerExit() +{ + nCPUClockspeed = 0; + pCPUTotalCycles = NULL; + pCPURun = NULL; + pCPURunEnd = NULL; + + return; +} + +void BurnTimerReset() +{ + nTimerCount[0] = nTimerCount[1] = MAX_TIMER_VALUE; + nTimerStart[0] = nTimerStart[1] = MAX_TIMER_VALUE; + + dTime = 0.0; + + nTicksDone = 0; +} + +INT32 BurnTimerInit(INT32 (*pOverCallback)(INT32, INT32), double (*pTimeCallback)()) +{ + BurnTimerExit(); + + pTimerOverCallback = pOverCallback; + pTimerTimeCallback = pTimeCallback ? pTimeCallback : BurnTimerTimeCallbackDummy; + + BurnTimerReset(); + + return 0; +} + +INT32 BurnTimerAttachSek(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = SekTotalCycles; + pCPURun = SekRun; + pCPURunEnd = SekRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachZet(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = ZetTotalCycles; + pCPURun = ZetRun; + pCPURunEnd = ZetRunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6809(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6809TotalCycles; + pCPURun = M6809Run; + pCPURunEnd = M6809RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD6309(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = HD6309TotalCycles; + pCPURun = HD6309Run; + pCPURunEnd = HD6309RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6800(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6800Run; + pCPURunEnd = M6800RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachHD63701(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = HD63701Run; + pCPURunEnd = HD63701RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6803(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6800TotalCycles; + pCPURun = M6803Run; + pCPURunEnd = M6803RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachM6502(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = M6502TotalCycles; + pCPURun = M6502Run; + pCPURunEnd = M6502RunEnd; // doesn't do anything... + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + + +INT32 BurnTimerAttachSh2(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; + pCPUTotalCycles = Sh2TotalCycles; + pCPURun = Sh2Run; + pCPURunEnd = Sh2StopRun; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} + +INT32 BurnTimerAttachH6280(INT32 nClockspeed) +{ + nCPUClockspeed = nClockspeed; +// pCPUTotalCycles = h6280TotalCycles; +// pCPURun = h6280Run; +// pCPURunEnd = h6280RunEnd; + + nTicksExtra = MAKE_TIMER_TICKS(1, nCPUClockspeed) - 1; + +// bprintf(PRINT_NORMAL, _T("--- timer cpu speed %iHz, one cycle = %i ticks.\n"), nClockspeed, MAKE_TIMER_TICKS(1, nCPUClockspeed)); + + return 0; +} diff --git a/src/burn/timer.h b/src/burn/timer.h new file mode 100644 index 00000000..6db8f089 --- /dev/null +++ b/src/burn/timer.h @@ -0,0 +1,36 @@ +// FM timers + +#define TIMER_TICKS_PER_SECOND (2048000000) +#define MAKE_TIMER_TICKS(n, m) ((INT64)(n) * TIMER_TICKS_PER_SECOND / (m)) +#define MAKE_CPU_CYLES(n, m) ((INT64)(n) * (m) / TIMER_TICKS_PER_SECOND) + +extern "C" double BurnTimerGetTime(); + +// Callbacks for various sound chips +void BurnOPNTimerCallback(INT32 n, INT32 c, INT32 cnt, double stepTime); // period = cnt * stepTime in s +void BurnOPLTimerCallback(INT32 c, double period); // period in s +void BurnYMFTimerCallback(INT32 n, INT32 c, double period); // period in us + +// Start / stop a timer +void BurnTimerSetRetrig(INT32 c, double period); // period in s +void BurnTimerSetOneshot(INT32 c, double period); // period in s + +extern double dTime; + +void BurnTimerExit(); +void BurnTimerReset(); +INT32 BurnTimerInit(INT32 (*pOverCallback)(INT32, INT32), double (*pTimeCallback)()); +INT32 BurnTimerAttachSek(INT32 nClockspeed); +INT32 BurnTimerAttachZet(INT32 nClockspeed); +INT32 BurnTimerAttachM6809(INT32 nClockspeed); +INT32 BurnTimerAttachHD6309(INT32 nClockspeed); +INT32 BurnTimerAttachM6800(INT32 nClockspeed); +INT32 BurnTimerAttachHD63701(INT32 nClockspeed); +INT32 BurnTimerAttachM6803(INT32 nClockspeed); +INT32 BurnTimerAttachM6502(INT32 nClockspeed); +INT32 BurnTimerAttachSh2(INT32 nClockspeed); +INT32 BurnTimerAttachH6280(INT32 nClockspeed); +void BurnTimerScan(INT32 nAction, INT32* pnMin); +INT32 BurnTimerUpdate(INT32 nCycles); +void BurnTimerUpdateEnd(); +void BurnTimerEndFrame(INT32 nCycles); diff --git a/src/burn/vector.cpp b/src/burn/vector.cpp new file mode 100644 index 00000000..a1a38b1f --- /dev/null +++ b/src/burn/vector.cpp @@ -0,0 +1,167 @@ + +#include "tiles_generic.h" +#include "math.h" + +#define TABLE_SIZE 0x10000 // excessive? + +struct vector_line { + INT32 x; + INT32 y; + INT32 color; + UINT8 intensity; +}; + +static struct vector_line *vector_table; +struct vector_line *vector_ptr; // pointer +static INT32 vector_cnt; + +void vector_add_point(INT32 x, INT32 y, INT32 color, INT32 intensity) +{ + vector_ptr->x = x >> 16; + vector_ptr->y = y >> 16; + vector_ptr->color = color; + vector_ptr->intensity = intensity; + + vector_cnt++; + if (vector_cnt > (TABLE_SIZE - 2)) return; + vector_ptr++; + vector_ptr->color = -1; // mark it as the last one to save some cycles later... +} + +static void lineSimple(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, INT32 intensity) +{ + INT32 dx = x1 - x0; + INT32 dy = y1 - y0; + + color = color * 256 + intensity; + + if (!dx && dy) // vertical line + { + INT32 sy = (y1 < y0) ? y1 : y0; + INT32 y2 = (y1 < y0) ? (y0 - y1) : (y1 - y0); + + if (x1 >= 0 && x1 < nScreenWidth) + { + UINT16 *dst = pTransDraw + x1; + + for (INT32 y = 0; y < y2; y++, sy++) { + if (sy >= 0 && sy < nScreenHeight) { + dst[sy * nScreenWidth] = color; + } + } + } + } + else if (!dy && dx) // horizontal line + { + INT32 sx = (x1 < x0) ? x1 : x0; + INT32 x2 = (x1 < x0) ? (x0 - x1) : (x1 - x0); + + if (y1 >= 0 && y1 < nScreenHeight) + { + UINT16 *dst = pTransDraw + y1 * nScreenWidth; + + for (INT32 x = 0; x < x2; x++, sx++) { + if (sx >= 0 && sx < nScreenWidth) { + dst[sx] = color; + } + } + } + } + else if (dx && dy) // can we optimize further? + { + INT32 md = (dy << 16) / dx; + INT32 zd = (y0 << 16) - (md * x0) + 0x8000; // + 0x8000 for rounding! + + dx = (x1 > x0) ? 1 : -1; + + while (x0 != x1) { + x0 += dx; + y0 = ((md * x0) + zd) >> 16; + + if (x0 >= 0 && x0 < nScreenWidth && y0 >= 0 && y0 < nScreenHeight) { + pTransDraw[y0 * nScreenWidth + x0] = color; + } + } + } + else // point + { + if (x0 >= 0 && x0 < nScreenWidth && y0 >= 0 && y0 < nScreenHeight) { + pTransDraw[y0 * nScreenWidth + x0] = color; + } + } +} + +void draw_vector(UINT32 *palette) +{ + struct vector_line *ptr = &vector_table[0]; + + INT32 prev_x = 0, prev_y = 0; + + BurnTransferClear(); + + for (INT32 i = 0; i < vector_cnt && i < TABLE_SIZE; i++, ptr++) + { + if (ptr->color == -1) break; + + INT32 curr_y = ptr->y; + INT32 curr_x = ptr->x; + + if (ptr->intensity != 0) { // intensity 0 means turn off the beam... + lineSimple(curr_x, curr_y, prev_x, prev_y, ptr->color, ptr->intensity); + } + + prev_x = curr_x; + prev_y = curr_y; + } + + BurnTransferCopy(palette); +} + +void vector_reset() +{ + vector_cnt = 0; + vector_ptr = &vector_table[0]; + vector_ptr->color = -1; +} + +void vector_init() +{ + GenericTilesInit(); + + vector_table = (struct vector_line*)malloc(TABLE_SIZE * sizeof(vector_line)); + + memset (vector_table, 0, TABLE_SIZE * sizeof(vector_line)); + + vector_reset(); +} + +void vector_exit() +{ + GenericTilesExit(); + + free (vector_table); + vector_table = NULL; + vector_ptr = NULL; +} + +INT32 vector_scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = (UINT8*)vector_table; + ba.nLen = TABLE_SIZE * sizeof(vector_line); + ba.szName = "Vector Table"; + BurnAcb(&ba); + + SCAN_VAR(vector_cnt); + } + + if (nAction & ACB_WRITE) { + vector_ptr = &vector_table[vector_cnt]; + } + + return 0; +} diff --git a/src/burn/vector.h b/src/burn/vector.h new file mode 100644 index 00000000..074ad599 --- /dev/null +++ b/src/burn/vector.h @@ -0,0 +1,7 @@ + +void draw_vector(UINT32 *palette); +void vector_init(); +void vector_reset(); +INT32 vector_scan(INT32 nAction); +void vector_exit(); +void vector_add_point(INT32 x, INT32 y, INT32 color, INT32 intensity); diff --git a/src/burn/version.h b/src/burn/version.h new file mode 100644 index 00000000..a418d24d --- /dev/null +++ b/src/burn/version.h @@ -0,0 +1,13 @@ +// Version number, written as vV.V.BB or vV.V.BBaa +// (0xVVBBaa, in BCD notation) + +#define VER_MAJOR 0 +#define VER_MINOR 2 +#define VER_BETA 97 +#define VER_ALPHA 15 + +#define BURN_VERSION (VER_MAJOR * 0x100000) + (VER_MINOR * 0x010000) + (((VER_BETA / 10) * 0x001000) + ((VER_BETA % 10) * 0x000100)) + (((VER_ALPHA / 10) * 0x000010) + (VER_ALPHA % 10)) + + + + diff --git a/src/burner/burner.h b/src/burner/burner.h new file mode 100644 index 00000000..a4740130 --- /dev/null +++ b/src/burner/burner.h @@ -0,0 +1,158 @@ +// FB Alpha - Emulator for MC68000/Z80 based arcade games +// Refer to the "license.txt" file for more info + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tchar.h" + +// Macro to make quoted strings +#define MAKE_STRING_2(s) #s +#define MAKE_STRING(s) MAKE_STRING_2(s) + +#define BZIP_MAX (8) // Maximum zip files to search through +#define DIRS_MAX (8) // Maximum number of directories to search + +#include "title.h" +#include "burn.h" + +// --------------------------------------------------------------------------- +// OS dependent functionality + +#if defined (BUILD_WIN32) + #include "burner_win32.h" +#elif defined (BUILD_SDL) + #include "burner_sdl.h" +#endif + +#include "net.h" +#include "png.h" + +// --------------------------------------------------------------------------- +// OS independent functionality + +#include "interface.h" + +#define IMG_FREE (1 << 0) + +// Macros for parsing text +#define SKIP_WS(s) while (_istspace(*s)) { s++; } // Skip whitespace +#define FIND_WS(s) while (*s && !_istspace(*s)) { s++; } // Find whitespace +#define FIND_QT(s) while (*s && *s != _T('\"')) { s++; } // Find quote + +// image.cpp +void img_free(IMAGE* img); +INT32 img_alloc(IMAGE* img); + +bool PNGIsImage(FILE* fp); +INT32 PNGLoad(IMAGE* img, FILE* fp, INT32 nPreset); + +// gami.cpp +extern struct GameInp* GameInp; +extern UINT32 nGameInpCount; +extern UINT32 nMacroCount; +extern UINT32 nMaxMacro; + +extern INT32 nAnalogSpeed; + +extern INT32 nFireButtons; + +extern bool bStreetFighterLayout; +extern bool bLeftAltkeyMapped; + +INT32 GameInpInit(); +INT32 GameInpExit(); +TCHAR* InputCodeDesc(INT32 c); +TCHAR* InpToDesc(struct GameInp* pgi); +TCHAR* InpMacroToDesc(struct GameInp* pgi); +void GameInpCheckLeftAlt(); +void GameInpCheckMouse(); +INT32 GameInpBlank(INT32 bDipSwitch); +INT32 GameInputAutoIni(INT32 nPlayer, TCHAR* lpszFile, bool bOverWrite); +INT32 ConfigGameLoadHardwareDefaults(); +INT32 GameInpDefault(); +INT32 GameInpWrite(FILE* h); +INT32 GameInpRead(TCHAR* szVal, bool bOverWrite); +INT32 GameInpMacroRead(TCHAR* szVal, bool bOverWrite); +INT32 GameInpCustomRead(TCHAR* szVal, bool bOverWrite); + +// Player Default Controls +extern INT32 nPlayerDefaultControls[4]; +extern TCHAR szPlayerDefaultIni[4][MAX_PATH]; + +// cong.cpp +extern const INT32 nConfigMinVersion; // Minimum version of application for which input files are valid +extern bool bSaveInputs; +INT32 ConfigGameLoad(bool bOverWrite); // char* lpszName = NULL +INT32 ConfigGameSave(bool bSave); + +// conc.cpp +INT32 ConfigCheatLoad(); + +// gamc.cpp +INT32 GamcMisc(struct GameInp* pgi, char* szi, INT32 nPlayer); +INT32 GamcAnalogKey(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nSlide); +INT32 GamcAnalogJoy(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nJoy, INT32 nSlide); +INT32 GamcPlayer(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nDevice); +INT32 GamcPlayerHotRod(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nFlags, INT32 nSlide); + +// misc.cpp +#define QUOTE_MAX (128) // Maximum length of "quoted strings" +INT32 QuoteRead(TCHAR** ppszQuote, TCHAR** ppszEnd, TCHAR* pszSrc); // Read a quoted string from szSrc and poINT32 to the end +TCHAR* LabelCheck(TCHAR* s, TCHAR* pszLabel); + +TCHAR* ExtractFilename(TCHAR* fullname); +TCHAR* DriverToName(UINT32 nDrv); +UINT32 NameToDriver(TCHAR* szName); + +extern INT32 bDoGamma; +extern INT32 bHardwareGammaOnly; +extern double nGamma; + +INT32 SetBurnHighCol(INT32 nDepth); +char* DecorateGameName(UINT32 nBurnDrv); +TCHAR* DecorateGenreInfo(); +void ComputeGammaLUT(); + +// dat.cpp +INT32 write_datfile(INT32 bIncMegadrive, FILE* fDat); +INT32 create_datfile(TCHAR* szFilename, INT32 bIncMegadrive); + +// sshot.cpp +INT32 MakeScreenShot(); + +// state.cpp +INT32 BurnStateLoadEmbed(FILE* fp, INT32 nOffset, INT32 bAll, INT32 (*pLoadGame)()); +INT32 BurnStateLoad(TCHAR* szName, INT32 bAll, INT32 (*pLoadGame)()); +INT32 BurnStateSaveEmbed(FILE* fp, INT32 nOffset, INT32 bAll); +INT32 BurnStateSave(TCHAR* szName, INT32 bAll); + +// statec.cpp +INT32 BurnStateCompress(UINT8** pDef, INT32* pnDefLen, INT32 bAll); +INT32 BurnStateDecompress(UINT8* Def, INT32 nDefLen, INT32 bAll); + +// zipfn.cpp +struct ZipEntry { char* szName; UINT32 nLen; UINT32 nCrc; }; + +INT32 ZipOpen(const char* szZip); +INT32 ZipClose(); +INT32 ZipGetList(struct ZipEntry** pList, INT32* pnListCount); +INT32 ZipLoadFile(UINT8* Dest, INT32 nLen, INT32* pnWrote, INT32 nEntry); + +// bzip.cpp + +#define BZIP_STATUS_OK (0) +#define BZIP_STATUS_BADDATA (1) +#define BZIP_STATUS_ERROR (2) + +INT32 BzipOpen(bool); +INT32 BzipClose(); +INT32 BzipInit(); +INT32 BzipExit(); +INT32 BzipStatus(); diff --git a/src/burner/conc.cpp b/src/burner/conc.cpp new file mode 100644 index 00000000..9a9ad461 --- /dev/null +++ b/src/burner/conc.cpp @@ -0,0 +1,582 @@ +#include "burner.h" + +static bool SkipComma(TCHAR** s) +{ + while (**s && **s != _T(',')) { + (*s)++; + } + + if (**s == _T(',')) { + (*s)++; + } + + if (**s) { + return true; + } + + return false; +} + +static void CheatError(TCHAR* pszFilename, INT32 nLineNumber, CheatInfo* pCheat, TCHAR* pszInfo, TCHAR* pszLine) +{ + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Cheat file %s is malformed.\nPlease remove or repair the file.\n\n"), pszFilename); + if (pCheat) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Parse error at line %i, in cheat \"%s\".\n"), nLineNumber, pCheat->szCheatName); + } else { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Parse error at line %i.\n"), nLineNumber); + } + + if (pszInfo) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Problem:\t%s.\n"), pszInfo); + } + if (pszLine) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Text:\t%s\n"), pszLine); + } + + FBAPopupDisplay(PUF_TYPE_ERROR); +} + +static INT32 ConfigParseFile(TCHAR* pszFilename) +{ +#define INSIDE_NOTHING (0xFFFF & (1 << ((sizeof(TCHAR) * 8) - 1))) + + TCHAR szLine[1024]; + TCHAR* s; + TCHAR* t; + INT32 nLen; + + INT32 nLine = 0; + TCHAR nInside = INSIDE_NOTHING; + + CheatInfo* pCurrentCheat = NULL; + + FILE* h = _tfopen(pszFilename, _T("rt")); + if (h == NULL) { + return 1; + } + + while (1) { + if (_fgetts(szLine, sizeof(szLine), h) == NULL) { + break; + } + + nLine++; + + nLen = _tcslen(szLine); + // Get rid of the linefeed at the end + while (szLine[nLen - 1] == 0x0A || szLine[nLen - 1] == 0x0D) { + szLine[nLen - 1] = 0; + nLen--; + } + + s = szLine; // Start parsing + + if (s[0] == _T('/') && s[1] == _T('/')) { // Comment + continue; + } + + if ((t = LabelCheck(s, _T("include"))) != 0) { // Include a file + s = t; + + TCHAR szFilename[MAX_PATH] = _T(""); + + // Read name of the cheat file + TCHAR* szQuote = NULL; + QuoteRead(&szQuote, NULL, s); + + _stprintf(szFilename, _T("%s%s.dat"), szAppCheatsPath, szQuote); + + if (ConfigParseFile(szFilename)) { + _stprintf(szFilename, _T("%s%s.ini"), szAppCheatsPath, szQuote); + if (ConfigParseFile(szFilename)) { + CheatError(pszFilename, nLine, NULL, _T("included file doesn't exist"), szLine); + } + } + + continue; + } + + if ((t = LabelCheck(s, _T("cheat"))) != 0) { // Add new cheat + s = t; + + // Read cheat name + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + + QuoteRead(&szQuote, &szEnd, s); + + s = szEnd; + + if ((t = LabelCheck(s, _T("advanced"))) != 0) { // Advanced cheat + s = t; + } + + SKIP_WS(s); + + if (nInside == _T('{')) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("missing closing bracket"), NULL); + break; + } +#if 0 + if (*s != _T('\0') && *s != _T('{')) { + CheatError(pszFilename, nLine, NULL, _T("malformed cheat declaration"), szLine); + break; + } +#endif + nInside = *s; + + // Link new node into the list + CheatInfo* pPreviousCheat = pCurrentCheat; + pCurrentCheat = (CheatInfo*)malloc(sizeof(CheatInfo)); + if (pCheatInfo == NULL) { + pCheatInfo = pCurrentCheat; + } + + memset(pCurrentCheat, 0, sizeof(CheatInfo)); + pCurrentCheat->pPrevious = pPreviousCheat; + if (pPreviousCheat) { + pPreviousCheat->pNext = pCurrentCheat; + } + + // Fill in defaults + pCurrentCheat->nType = 0; // Default to cheat type 0 (apply each frame) + pCurrentCheat->nStatus = -1; // Disable cheat + + memcpy(pCurrentCheat->szCheatName, szQuote, QUOTE_MAX); + + continue; + } + + if ((t = LabelCheck(s, _T("type"))) != 0) { // Cheat type + if (nInside == INSIDE_NOTHING || pCurrentCheat == NULL) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("rogue cheat type"), szLine); + break; + } + s = t; + + // Set type + pCurrentCheat->nType = _tcstol(s, NULL, 0); + + continue; + } + + if ((t = LabelCheck(s, _T("default"))) != 0) { // Default option + if (nInside == INSIDE_NOTHING || pCurrentCheat == NULL) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("rogue default"), szLine); + break; + } + s = t; + + // Set default option + pCurrentCheat->nDefault = _tcstol(s, NULL, 0); + + continue; + } + + INT32 n = _tcstol(s, &t, 0); + if (t != s) { // New option + + if (nInside == INSIDE_NOTHING || pCurrentCheat == NULL) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("rogue option"), szLine); + break; + } + + // Link a new Option structure to the cheat + if (n < CHEAT_MAX_OPTIONS) { + s = t; + + // Read option name + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + if (QuoteRead(&szQuote, &szEnd, s)) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("option name omitted"), szLine); + break; + } + s = szEnd; + + if (pCurrentCheat->pOption[n] == NULL) { + pCurrentCheat->pOption[n] = (CheatOption*)malloc(sizeof(CheatOption)); + } + memset(pCurrentCheat->pOption[n], 0, sizeof(CheatOption)); + + memcpy(pCurrentCheat->pOption[n]->szOptionName, szQuote, QUOTE_MAX * sizeof(TCHAR)); + + INT32 nCurrentAddress = 0; + bool bOK = true; + while (nCurrentAddress < CHEAT_MAX_ADDRESS) { + INT32 nCPU = 0, nAddress = 0, nValue = 0; + + if (SkipComma(&s)) { + nCPU = _tcstol(s, &t, 0); // CPU number + if (t == s) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("CPU number omitted"), szLine); + bOK = false; + break; + } + s = t; + + SkipComma(&s); + nAddress = _tcstol(s, &t, 0); // Address + if (t == s) { + bOK = false; + CheatError(pszFilename, nLine, pCurrentCheat, _T("address omitted"), szLine); + break; + } + s = t; + + SkipComma(&s); + nValue = _tcstol(s, &t, 0); // Value + if (t == s) { + bOK = false; + CheatError(pszFilename, nLine, pCurrentCheat, _T("value omitted"), szLine); + break; + } + } else { + if (nCurrentAddress) { // Only the first option is allowed no address + break; + } + if (n) { + bOK = false; + CheatError(pszFilename, nLine, pCurrentCheat, _T("CPU / address / value omitted"), szLine); + break; + } + } + + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nCPU = nCPU; + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nAddress = nAddress; + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nValue = nValue; + nCurrentAddress++; + } + + if (!bOK) { + break; + } + + } + + continue; + } + + SKIP_WS(s); + if (*s == _T('}')) { + if (nInside != _T('{')) { + CheatError(pszFilename, nLine, pCurrentCheat, _T("missing opening bracket"), NULL); + break; + } + + nInside = INSIDE_NOTHING; + } + + // Line isn't (part of) a valid cheat +#if 0 + if (*s) { + CheatError(pszFilename, nLine, NULL, _T("rogue line"), szLine); + break; + } +#endif + + } + + if (h) { + fclose(h); + } + + return 0; +} + +static INT32 ConfigParseNebulaFile(TCHAR* pszFilename) +{ + FILE *fp = _tfopen(pszFilename, _T("rt")); + if (fp == NULL) { + return 1; + } + + INT32 nLen; + INT32 i, j, n = 0; + TCHAR tmp[32]; + TCHAR szLine[1024]; + + CheatInfo* pCurrentCheat = NULL; + + while (1) + { + if (_fgetts(szLine, 1024, fp) == NULL) + break; + + nLen = lstrlen(szLine); + + if (nLen < 3 || szLine[0] == '[') continue; + + if (!_tcsncmp (_T("Name="), szLine, 5)) + { + n = 0; + + // Link new node into the list + CheatInfo* pPreviousCheat = pCurrentCheat; + pCurrentCheat = (CheatInfo*)malloc(sizeof(CheatInfo)); + if (pCheatInfo == NULL) { + pCheatInfo = pCurrentCheat; + } + + memset(pCurrentCheat, 0, sizeof(CheatInfo)); + pCurrentCheat->pPrevious = pPreviousCheat; + if (pPreviousCheat) { + pPreviousCheat->pNext = pCurrentCheat; + } + + // Fill in defaults + pCurrentCheat->nType = 0; // Default to cheat type 0 (apply each frame) + pCurrentCheat->nStatus = -1; // Disable cheat + pCurrentCheat->nDefault = 0; // Set default option + + _tcsncpy (pCurrentCheat->szCheatName, szLine + 5, QUOTE_MAX); + pCurrentCheat->szCheatName[nLen-6] = '\0'; + + continue; + } + + if (!_tcsncmp (_T("Default="), szLine, 8) && n >= 0) + { + _tcsncpy (tmp, szLine + 8, nLen-9); + tmp[nLen-9] = '\0'; + _stscanf (tmp, _T("%d"), &(pCurrentCheat->nDefault)); + continue; + } + + + i = 0, j = 0; + while (i < nLen) + { + if (szLine[i] == '=' && i < 4) j = i+1; + if (szLine[i] == ',' || szLine[i] == '\n') + { + if (pCurrentCheat->pOption[n] == NULL) { + pCurrentCheat->pOption[n] = (CheatOption*)malloc(sizeof(CheatOption)); + } + memset(pCurrentCheat->pOption[n], 0, sizeof(CheatOption)); + + _tcsncpy (pCurrentCheat->pOption[n]->szOptionName, szLine + j, QUOTE_MAX * sizeof(TCHAR)); + pCurrentCheat->pOption[n]->szOptionName[i-j] = '\0'; + + i++; j = i; + break; + } + i++; + } + + INT32 nAddress = -1, nValue = 0, nCurrentAddress = 0; + while (nCurrentAddress < CHEAT_MAX_ADDRESS) + { + if (i == nLen) break; + + if (szLine[i] == ',' || szLine[i] == '\n') + { + _tcsncpy (tmp, szLine + j, i-j); + tmp[i-j] = '\0'; + + if (nAddress == -1) { + _stscanf (tmp, _T("%x"), &nAddress); + } else { + _stscanf (tmp, _T("%x"), &nValue); + + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nCPU = 0; // Always + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nAddress = nAddress ^ 1; + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nValue = nValue; + nCurrentAddress++; + + nAddress = -1; + nValue = 0; + } + j = i+1; + } + i++; + } + n++; + } + + fclose (fp); + + return 0; +} + +static INT32 ConfigParseMAMEFile() +{ + +#define AddressInfo() \ + INT32 k = (flags >> 20) & 3; \ + for (INT32 i = 0; i < k+1; i++) { \ + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nCPU = 0; \ + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nAddress = nAddress + i; \ + pCurrentCheat->pOption[n]->AddressInfo[nCurrentAddress].nValue = (nValue >> ((k*8)-(i*8))) & 0xff; \ + nCurrentAddress++; \ + } \ + +#define OptionName(a) \ + if (pCurrentCheat->pOption[n] == NULL) { \ + pCurrentCheat->pOption[n] = (CheatOption*)malloc(sizeof(CheatOption)); \ + } \ + memset(pCurrentCheat->pOption[n], 0, sizeof(CheatOption)); \ + _tcsncpy (pCurrentCheat->pOption[n]->szOptionName, a, QUOTE_MAX * sizeof(TCHAR)); \ + +#define tmpcpy(a) \ + _tcsncpy (tmp, szLine + c0[a] + 1, c0[a+1] - (c0[a]+1)); \ + tmp[c0[a+1] - (c0[a]+1)] = '\0'; \ + + TCHAR szFileName[MAX_PATH] = _T(""); + _stprintf(szFileName, _T("%scheat.dat"), szAppCheatsPath); + + FILE *fz = _tfopen(szFileName, _T("rt")); + if (fz == NULL) { + return 1; + } + + TCHAR tmp[256]; + TCHAR gName[64]; + TCHAR szLine[1024]; + + INT32 nLen; + INT32 n = 0; + INT32 menu = 0; + INT32 nFound = 0; + INT32 nCurrentAddress = 0; + UINT32 flags = 0; + UINT32 nAddress = 0; + UINT32 nValue = 0; + + CheatInfo* pCurrentCheat = NULL; + _stprintf(gName, _T(":%s:"), BurnDrvGetText(DRV_NAME)); + + while (1) + { + if (_fgetts(szLine, 1024, fz) == NULL) + break; + + nLen = lstrlen (szLine); + + if (szLine[0] == ';') continue; + + if (_tcsncmp (szLine, gName, lstrlen(gName))) { + if (nFound) break; + else continue; + } + + nFound = 1; + + INT32 c0[16], c1 = 0; // find colons / break + for (INT32 i = 0; i < nLen; i++) + if (szLine[i] == ':' || szLine[i] == '\n') + c0[c1++] = i; + + tmpcpy(1); // control flags + _stscanf (tmp, _T("%x"), &flags); + + tmpcpy(2); // cheat address + _stscanf (tmp, _T("%x"), &nAddress); + + tmpcpy(3); // cheat value + _stscanf (tmp, _T("%x"), &nValue); + + tmpcpy(5); // cheat name + + if (flags & 0x80007f00) continue; // skip various cheats + + // controls how many bytes we're going to patch (only allow single bytes for now) + // if (flags & 0x00300000) continue; + // nValue &= 0x000000ff; // only use a single byte + + if ( flags & 0x00008000 || (flags & 0x0001000 && !menu)) { + if (nCurrentAddress < CHEAT_MAX_ADDRESS) { + AddressInfo(); + } + + continue; + } + + if (~flags & 0x00010000) { + n = 0; + menu = 0; + nCurrentAddress = 0; + + // Link new node into the list + CheatInfo* pPreviousCheat = pCurrentCheat; + pCurrentCheat = (CheatInfo*)malloc(sizeof(CheatInfo)); + if (pCheatInfo == NULL) { + pCheatInfo = pCurrentCheat; + } + + memset(pCurrentCheat, 0, sizeof(CheatInfo)); + pCurrentCheat->pPrevious = pPreviousCheat; + if (pPreviousCheat) { + pPreviousCheat->pNext = pCurrentCheat; + } + + // Fill in defaults + pCurrentCheat->nType = 0; // Default to cheat type 0 (apply each frame) + pCurrentCheat->nStatus = -1; // Disable cheat + pCurrentCheat->nDefault = 0; // Set default option + + _tcsncpy (pCurrentCheat->szCheatName, tmp, QUOTE_MAX); + + if (lstrlen(tmp) <= 0 || flags == 0x60000000) { + n++; + continue; + } + + OptionName(_T("Disabled")); + + if (nAddress) { + n++; + + OptionName(tmp); + AddressInfo(); + } else { + menu = 1; + } + + continue; + } + + if ( flags & 0x00010000 && menu) { + n++; + nCurrentAddress = 0; + + OptionName(tmp); + AddressInfo(); + + continue; + } + } + + fclose (fz); + + return 0; +} + + +INT32 ConfigCheatLoad() +{ + TCHAR szFilename[MAX_PATH] = _T(""); + + _stprintf(szFilename, _T("%s%s.ini"), szAppCheatsPath, BurnDrvGetText(DRV_NAME)); + if (ConfigParseFile(szFilename)) { + _stprintf(szFilename, _T("%s%s.dat"), szAppCheatsPath, BurnDrvGetText(DRV_NAME)); + if (ConfigParseNebulaFile(szFilename)) { + if (ConfigParseMAMEFile()) { + return 1; + } + } + } + + if (pCheatInfo) { + INT32 nCurrentCheat = 0; + while (CheatEnable(nCurrentCheat, -1) == 0) { + nCurrentCheat++; + } + + CheatUpdate(); + } + + return 0; +} + + diff --git a/src/burner/cong.cpp b/src/burner/cong.cpp new file mode 100644 index 00000000..d65f2962 --- /dev/null +++ b/src/burner/cong.cpp @@ -0,0 +1,118 @@ +// Burner Config for Game file module +#include "burner.h" + +const INT32 nConfigMinVersion = 0x020921; + +bool bSaveInputs = true; + +static TCHAR* GameConfigName() +{ + // Return the path of the config file for this game + static TCHAR szName[32]; + _stprintf(szName, _T("config\\games\\%s.ini"), BurnDrvGetText(DRV_NAME)); + return szName; +} + +// Read in the config file for the game-specific inputs +INT32 ConfigGameLoad(bool bOverWrite) +{ + TCHAR szLine[256]; + INT32 nFileVersion = 0; + + FILE* h = _tfopen(GameConfigName(), _T("rt")); + if (h == NULL) { + return 1; + } + + if (bOverWrite) { + nAnalogSpeed = 0x0100; + nBurnCPUSpeedAdjust = 0x0100; + } + + // Go through each line of the config file and process inputs + while (_fgetts(szLine, sizeof(szLine), h)) { + TCHAR *szValue; + INT32 nLen = _tcslen(szLine); + + // Get rid of the linefeed at the end + if (szLine[nLen - 1] == 10) { + szLine[nLen - 1] = 0; + nLen--; + } + + szValue = LabelCheck(szLine, _T("version")); + if (szValue) { + nFileVersion = _tcstol(szValue, NULL, 0); + } + + if (bOverWrite) { + szValue = LabelCheck(szLine, _T("analog")); + if (szValue) { + nAnalogSpeed = _tcstol(szValue, NULL, 0); + } + szValue = LabelCheck(szLine, _T("cpu")); + if (szValue) { + nBurnCPUSpeedAdjust = _tcstol(szValue, NULL, 0); + } + } + + if (nConfigMinVersion <= nFileVersion && nFileVersion <= nBurnVer) { + szValue = LabelCheck(szLine, _T("input")); + if (szValue) { + GameInpRead(szValue, bOverWrite); + continue; + } + + szValue = LabelCheck(szLine, _T("macro")); + if (szValue) { + GameInpMacroRead(szValue, bOverWrite); + continue; + } + + szValue = LabelCheck(szLine, _T("custom")); + if (szValue) { + GameInpCustomRead(szValue, bOverWrite); + continue; + } + } + } + + fclose(h); + return 0; +} + +// Write out the config file for the game-specific inputs +INT32 ConfigGameSave(bool bSave) +{ + FILE* h; + + if (!bSave) { + GameInpBlank(0); + ConfigGameLoad(false); + } + + h = _tfopen(GameConfigName(), _T("wt")); + if (h == NULL) { + return 1; + } + + // Write title + _ftprintf(h, _T("// ") _T(APP_TITLE) _T(" v%s --- Config File for %s (%s)\n\n"), szAppBurnVer, BurnDrvGetText(DRV_NAME), ANSIToTCHAR(BurnDrvGetTextA(DRV_FULLNAME), NULL, 0)); + + _ftprintf(h, _T("// --- Miscellaneous ----------------------------------------------------------\n\n")); + // Write version number + _ftprintf(h, _T("version 0x%06X\n\n"), nBurnVer); + // Write speed for relative analog controls + _ftprintf(h, _T("analog 0x%04X\n"), nAnalogSpeed); + // Write CPU speed adjustment + _ftprintf(h, _T("cpu 0x%04X\n"), nBurnCPUSpeedAdjust); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- Inputs -----------------------------------------------------------------\n\n")); + + GameInpWrite(h); + + fclose(h); + return 0; +} + diff --git a/src/burner/dat.cpp b/src/burner/dat.cpp new file mode 100644 index 00000000..d0c75649 --- /dev/null +++ b/src/burner/dat.cpp @@ -0,0 +1,502 @@ +// Burner data file module (for ROM managers) +// written 2001 LoqiqX +// updated 11/2003 by LvR -- essentially a rewrite + +#include "burner.h" + +static void ReplaceAmpersand(char *szBuffer, char *szGameName) +{ + UINT32 nStringPos = 0; + + for (UINT32 i = 0; i < strlen(szGameName); i++) { + if (szGameName[i] == '&') { + szBuffer[nStringPos + 0] = '&'; + szBuffer[nStringPos + 1] = 'a'; + szBuffer[nStringPos + 2] = 'm'; + szBuffer[nStringPos + 3] = 'p'; + szBuffer[nStringPos + 4] = ';'; + nStringPos += 5; + } else { + szBuffer[nStringPos] = szGameName[i]; + nStringPos++; + } + } +} + +static void ReplaceLessThan(char *szBuffer, char *szGameName) +{ + UINT32 nStringPos = 0; + + for (UINT32 i = 0; i < strlen(szGameName); i++) { + if (szGameName[i] == '<') { + szBuffer[nStringPos + 0] = '&'; + szBuffer[nStringPos + 1] = 'l'; + szBuffer[nStringPos + 2] = 't'; + szBuffer[nStringPos + 3] = ';'; + nStringPos += 4; + } else { + szBuffer[nStringPos] = szGameName[i]; + nStringPos++; + } + } +} + +static void ReplaceGreaterThan(char *szBuffer, char *szGameName) +{ + UINT32 nStringPos = 0; + + for (UINT32 i = 0; i < strlen(szGameName); i++) { + if (szGameName[i] == '>') { + szBuffer[nStringPos + 0] = '&'; + szBuffer[nStringPos + 1] = 'g'; + szBuffer[nStringPos + 2] = 't'; + szBuffer[nStringPos + 3] = ';'; + nStringPos += 4; + } else { + szBuffer[nStringPos] = szGameName[i]; + nStringPos++; + } + } +} + +INT32 write_datfile(INT32 bIncMegadrive, FILE* fDat) +{ + INT32 nRet=0; + UINT32 nOldSelect=0; + UINT32 nGameSelect=0; + UINT32 nParentSelect,nBoardROMSelect; + + nOldSelect=nBurnDrvActive; // preserve the currently selected driver + + // Go over each of the games + for (nGameSelect=0;nGameSelect\n", sgName, spName, spName); + } else { + fprintf(fDat, "\t\n", sgName, spName, spName, ssName); + } + } + else + { + // Add "romof" (but not 'cloneof') line for games that have boardROMs + if (nBoardROMSelect!=nGameSelect && nBoardROMSelect!=-1U) + { + fprintf(fDat, "\t\n", sgName, sbName); + } else { + if (!strcmp(ssName, "") || !strcmp(ssName, sgName)) { + fprintf(fDat, "\t\n", sgName); + } else { + fprintf(fDat, "\t\n", sgName, ssName); + } + } + } + + char szGameName[255]; + char szGameNameBuffer[255]; + char szManufacturer[255]; + char szManufacturerBuffer[255]; + + memset(szGameName, 0, 255); + memset(szGameNameBuffer, 0, 255); + memset(szManufacturer, 0, 255); + memset(szManufacturerBuffer, 0, 255); + + strcpy(szGameName, DecorateGameName(nBurnDrvActive)); + ReplaceAmpersand(szGameNameBuffer, szGameName); + memset(szGameName, 0, 255); + strcpy(szGameName, szGameNameBuffer); + memset(szGameNameBuffer, 0, 255); + ReplaceLessThan(szGameNameBuffer, szGameName); + memset(szGameName, 0, 255); + strcpy(szGameName, szGameNameBuffer); + memset(szGameNameBuffer, 0, 255); + ReplaceGreaterThan(szGameNameBuffer, szGameName); + + strcpy(szManufacturer, BurnDrvGetTextA(DRV_MANUFACTURER)); + ReplaceAmpersand(szManufacturerBuffer, szManufacturer); + memset(szManufacturer, 0, 255); + strcpy(szManufacturer, szManufacturerBuffer); + memset(szManufacturerBuffer, 0, 255); + ReplaceLessThan(szManufacturerBuffer, szManufacturer); + memset(szManufacturer, 0, 255); + strcpy(szManufacturer, szManufacturerBuffer); + memset(szManufacturerBuffer, 0, 255); + ReplaceGreaterThan(szManufacturerBuffer, szManufacturer); + + fprintf(fDat, "\t\t%s\n", szGameNameBuffer); + fprintf(fDat, "\t\t%s\n", BurnDrvGetTextA(DRV_DATE)); + fprintf(fDat, "\t\t%s\n", szManufacturerBuffer); + + // Write the individual ROM info + for (nPass=0; nPass<2; nPass++) + { + nBurnDrvActive=nGameSelect; + + // Skip pass 0 if possible (pass 0 only needed for old-style clrMAME format) + if (nPass==0 /*&& (nBoardROMSelect==nGameSelect || nBoardROMSelect==-1U)*/) + continue; + + // Go over each of the files needed for this game (upto 0x0100) + for (i=0, nRet=0; nRet==0 && i<0x100; i++) + { + INT32 nRetTmp=0; + struct BurnRomInfo ri; + INT32 nLen; UINT32 nCrc; + char *szPossibleName=NULL; + INT32 j, nMerged=0; + + memset(&ri,0,sizeof(ri)); + + // Get info on this file + nBurnDrvActive=nGameSelect; + nRet=BurnDrvGetRomInfo(&ri,i); + nRet+=BurnDrvGetRomName(&szPossibleName,i,0); + + if (ri.nLen==0) continue; + + if (nRet==0) + { + struct BurnRomInfo riTmp; + char *szPossibleNameTmp; + nLen=ri.nLen; nCrc=ri.nCrc; + + // Check for files from boardROMs + if (nBoardROMSelect!=nGameSelect && nBoardROMSelect!=-1U) { + nBurnDrvActive=nBoardROMSelect; + nRetTmp=0; + + // Go over each of the files needed for this game (upto 0x0100) + for (j=0; nRetTmp==0 && j<0x100; j++) + { + memset(&riTmp,0,sizeof(riTmp)); + + nRetTmp+=BurnDrvGetRomInfo(&riTmp,j); + nRetTmp+=BurnDrvGetRomName(&szPossibleNameTmp,j,0); + + if (nRetTmp==0) + { + if (riTmp.nLen && riTmp.nCrc==nCrc && !strcmp(szPossibleName, szPossibleNameTmp)) + { + // This file is from a boardROM + nMerged|=2; + nRetTmp++; + } + } + } + } + + if (!nMerged && nParentSelect!=nGameSelect && nParentSelect!=-1U) { + nBurnDrvActive=nParentSelect; + nRetTmp=0; + + // Go over each of the files needed for this game (upto 0x0100) + for (j=0; nRetTmp==0 && j<0x100; j++) + { + memset(&riTmp,0,sizeof(riTmp)); + + nRetTmp+=BurnDrvGetRomInfo(&riTmp,j); + nRetTmp+=BurnDrvGetRomName(&szPossibleNameTmp,j,0); + + if (nRetTmp==0) + { + if (riTmp.nLen && riTmp.nCrc==nCrc && !strcmp(szPossibleName, szPossibleNameTmp)) + { + // This file is from a parent set + nMerged|=1; + nRetTmp++; + } + } + } + } + + nBurnDrvActive=nGameSelect; // Switch back to game + } + + char szPossibleNameBuffer[255]; + char szPossibleNameBuffer2[255]; + + memset(szPossibleNameBuffer, 0, 255); + memset(szPossibleNameBuffer2, 0, 255); + + ReplaceAmpersand(szPossibleNameBuffer, szPossibleName); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceLessThan(szPossibleNameBuffer, szPossibleNameBuffer2); + memset(szPossibleNameBuffer2, 0, 255); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceGreaterThan(szPossibleNameBuffer, szPossibleNameBuffer2); + + // File info + if (nPass==1 && !nMerged) { + if (ri.nType & BRF_NODUMP) { + fprintf(fDat, "\t\t\n", szPossibleNameBuffer, ri.nLen); + } else { + fprintf(fDat, "\t\t\n", szPossibleNameBuffer, ri.nLen, ri.nCrc); + } + } + if (nPass==1 && nMerged) + { + // Files from parent/boardROMs + if (ri.nType & BRF_NODUMP) { + fprintf(fDat, "\t\t\n", szPossibleNameBuffer, szPossibleNameBuffer, ri.nLen); + } else { + fprintf(fDat, "\t\t\n", szPossibleNameBuffer, szPossibleNameBuffer, ri.nLen, ri.nCrc); + } + } + } + + // samples + if (strcmp(ssName, "")) { + for (i=0, nRet=0; nRet==0 && i<0x100; i++) + { + struct BurnSampleInfo si; + char *szPossibleName=NULL; + + memset(&si,0,sizeof(si)); + + // Get info on this file + nBurnDrvActive=nGameSelect; + nRet=BurnDrvGetSampleInfo(&si,i); + nRet+=BurnDrvGetSampleName(&szPossibleName,i,0); + + if (si.nFlags==0) continue; + + if (nPass == 1) { + char szPossibleNameBuffer[255]; + char szPossibleNameBuffer2[255]; + + memset(szPossibleNameBuffer, 0, 255); + memset(szPossibleNameBuffer2, 0, 255); + + ReplaceAmpersand(szPossibleNameBuffer, szPossibleName); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceLessThan(szPossibleNameBuffer, szPossibleNameBuffer2); + memset(szPossibleNameBuffer2, 0, 255); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceGreaterThan(szPossibleNameBuffer, szPossibleNameBuffer2); + + fprintf(fDat, "\t\t\n", szPossibleNameBuffer); + } + } + } + } + + fprintf(fDat, "\t\n"); + } + + // Do another pass over each of the games to find boardROMs + for (nBurnDrvActive=0; nBurnDrvActive\n", BurnDrvGetTextA(DRV_NAME)); + fprintf(fDat, "\t\t%s\n", DecorateGameName(nBurnDrvActive)); + fprintf(fDat, "\t\t%s\n", BurnDrvGetTextA(DRV_DATE)); + fprintf(fDat, "\t\t%s\n", BurnDrvGetTextA(DRV_MANUFACTURER)); + + for (nPass=0; nPass<2; nPass++) + { + // No meta information needed (pass 0 only needed for old-style clrMAME format) + if (nPass==0) continue; + + // Go over each of the individual files (upto 0x0100) + for (i=0; i<0x100; i++) + { + struct BurnRomInfo ri; + char *szPossibleName=NULL; + + memset(&ri,0,sizeof(ri)); + + nRet=BurnDrvGetRomInfo(&ri,i); + nRet+=BurnDrvGetRomName(&szPossibleName,i,0); + + if (ri.nLen==0) continue; + + if (nRet==0) { + char szPossibleNameBuffer[255]; + char szPossibleNameBuffer2[255]; + + memset(szPossibleNameBuffer, 0, 255); + memset(szPossibleNameBuffer2, 0, 255); + + ReplaceAmpersand(szPossibleNameBuffer, szPossibleName); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceLessThan(szPossibleNameBuffer, szPossibleNameBuffer2); + memset(szPossibleNameBuffer2, 0, 255); + strcpy(szPossibleNameBuffer2, szPossibleNameBuffer); + memset(szPossibleNameBuffer, 0, 255); + ReplaceGreaterThan(szPossibleNameBuffer, szPossibleNameBuffer2); + + fprintf(fDat, "\t\t\n", szPossibleNameBuffer, ri.nLen, ri.nCrc); + } + } + } + + fprintf(fDat, "\t\n"); + } + + // Restore current driver + nBurnDrvActive=nOldSelect; + + fprintf(fDat, ""); + + return 0; +} + +INT32 create_datfile(TCHAR* szFilename, INT32 bIncMegadrive) +{ + FILE *fDat=0; + INT32 nRet=0; + + if ((fDat = _tfopen(szFilename, _T("wt")))==0) + return -1; + + fprintf(fDat, "\n"); + fprintf(fDat, "\n\n"); + fprintf(fDat, "\n"); + fprintf(fDat, "\t
\n"); + fprintf(fDat, "\t\t" APP_TITLE "\n"); + if (bIncMegadrive) { + _ftprintf(fDat, _T("\t\t") _T(APP_TITLE) _T(" v%s") _T(" Megadrive Games\n"), szAppBurnVer); + } else { + _ftprintf(fDat, _T("\t\t") _T(APP_TITLE) _T(" v%s") _T(" Arcade Games\n"), szAppBurnVer); + } + fprintf(fDat, "\t\tStandard DatFile\n"); + _ftprintf(fDat, _T("\t\t%s\n"), szAppBurnVer); + fprintf(fDat, "\t\t" APP_TITLE "\n"); + fprintf(fDat, "\t\thttp://www.barryharris.me.uk/\n"); + fprintf(fDat, "\t\thttp://www.barryharris.me.uk/\n"); + fprintf(fDat, "\t\t\n"); + fprintf(fDat, "\t
\n"); + + nRet = write_datfile(bIncMegadrive, fDat); + + fclose(fDat); + + return nRet; +} diff --git a/src/burner/gamc.cpp b/src/burner/gamc.cpp new file mode 100644 index 00000000..f350c992 --- /dev/null +++ b/src/burner/gamc.cpp @@ -0,0 +1,776 @@ +// Burner Game Control +#include "burner.h" + +static char szPlay[4][4]={"p1 ", "p2 ", "p3 ", "p4 "}; + +#define KEY(x) { pgi->nInput = GIT_SWITCH; pgi->Input.Switch.nCode = (UINT16)(x); } +#define MACRO(x) { pgi->Macro.nMode = 1; pgi->Macro.Switch.nCode = (UINT16)(x); } + +// Configure the misc game controls +INT32 GamcMisc(struct GameInp* pgi, char* szi, INT32 nPlayer) +{ + switch (nPlayer) { + case 0: + // Set general controls according to Player 1 settings + if (strcmp(szi, "diag") == 0) { + KEY(FBK_F2); + return 0; + } + if (strcmp(szi, "reset") == 0) { + KEY(FBK_F3); + return 0; + } + if (strcmp(szi, "service" ) == 0) { + KEY(FBK_9); + return 0; + } + if (strcmp(szi, "service2" ) == 0) { + KEY(FBK_0); + return 0; + } + if (strcmp(szi, "service3" ) == 0) { + KEY(FBK_MINUS); + return 0; + } + if (strcmp(szi, "service4" ) == 0) { + KEY(FBK_EQUALS); + return 0; + } + if (strcmp(szi, "tilt") == 0) { + KEY(FBK_T); + return 0; + } + + if (strcmp(szi, "op menu" ) == 0) { + KEY(FBK_F1); + return 0; + } + + if (strcmp(szi, "clear credit" ) == 0) { + KEY(FBK_G); + return 0; + } + + if (strcmp(szi, "hopper" ) == 0) { + KEY(FBK_H); + return 0; + } + + // Mahjong controls + if (strcmp(szi, "mah a") == 0) { + KEY(FBK_A); + return 0; + } + + if (strcmp(szi, "mah b") == 0) { + KEY(FBK_B); + return 0; + } + + if (strcmp(szi, "mah c") == 0) { + KEY(FBK_C); + return 0; + } + + if (strcmp(szi, "mah d") == 0) { + KEY(FBK_D); + return 0; + } + + if (strcmp(szi, "mah e") == 0) { + KEY(FBK_E); + return 0; + } + + if (strcmp(szi, "mah f") == 0) { + KEY(FBK_F); + return 0; + } + + if (strcmp(szi, "mah g") == 0) { + KEY(FBK_G); + return 0; + } + + if (strcmp(szi, "mah h") == 0) { + KEY(FBK_H); + return 0; + } + + if (strcmp(szi, "mah i") == 0) { + KEY(FBK_I); + return 0; + } + + if (strcmp(szi, "mah j") == 0) { + KEY(FBK_J); + return 0; + } + + if (strcmp(szi, "mah k") == 0) { + KEY(FBK_K); + return 0; + } + + if (strcmp(szi, "mah l") == 0) { + KEY(FBK_L); + return 0; + } + + if (strcmp(szi, "mah m") == 0) { + KEY(FBK_M); + return 0; + } + + if (strcmp(szi, "mah n") == 0) { + KEY(FBK_N); + return 0; + } + + if (strcmp(szi, "mah kan") == 0) { + KEY(FBK_LCONTROL); + return 0; + } + + if (strcmp(szi, "mah pon") == 0) { + KEY(FBK_LALT); + return 0; + } + + if (strcmp(szi, "mah chi") == 0) { + KEY(FBK_SPACE); + return 0; + } + + if (strcmp(szi, "mah reach") == 0) { + KEY(FBK_LSHIFT); + return 0; + } + + if (strcmp(szi, "mah ron") == 0) { + KEY(FBK_Z); + return 0; + } + + if (strcmp(szi, "mah ff") == 0) { + KEY(FBK_Y); + return 0; + } + + if (strcmp(szi, "mah lc") == 0) { + KEY(FBK_RALT); + return 0; + } + + if (strcmp(szi, "mah bet") == 0) { + KEY(FBK_2); + return 0; + } + + if (strcmp(szi, "mah score") == 0) { + KEY(FBK_RCONTROL); + return 0; + } + + // Player 1 controls + if (strcmp(szi, "p1 start") == 0) { + KEY(FBK_1); + return 0; + } + if (strcmp(szi, "p1 select" ) == 0) { + KEY(FBK_3); + return 0; + } + if (strcmp(szi, "p1 coin" ) == 0) { + KEY(FBK_5); + return 0; + } + break; + case 1: + if (strcmp(szi, "p2 start") == 0) { + KEY(FBK_2); + return 0; + } + if (strcmp(szi, "p2 select" ) == 0) { + KEY(FBK_4); + return 0; + } + if (strcmp(szi, "p2 coin" ) == 0) { + KEY(FBK_6); + return 0; + } + break; + case 2: + if (strcmp(szi, "p3 coin" ) == 0) { + KEY(FBK_7); + return 0; + } + if (strcmp(szi, "p3 start") == 0) { + KEY(FBK_3); + return 0; + } + break; + case 3: + if (strcmp(szi, "p4 start") == 0) { + KEY(FBK_4); + return 0; + } + if (strcmp(szi, "p4 coin" ) == 0) { + KEY(FBK_8); + return 0; + } + break; + } + + if (strncmp(szi, "mouse", 5) == 0) { + + if (strcmp(szi, "mouse x-axis") == 0) { + pgi->nInput = GIT_MOUSEAXIS; + pgi->Input.MouseAxis.nAxis = 0; + return 0; + + } + if (strcmp(szi, "mouse y-axis") == 0) { + pgi->nInput = GIT_MOUSEAXIS; + pgi->Input.MouseAxis.nAxis = 1; + return 0; + } + if (strncmp(szi, "mouse button", 12) == 0) { + char* szb = szi + 13; + INT32 nButton = strtol(szb, NULL, 0); + if (nButton >= 1) { + nButton--; + } + KEY(0x8080 + nButton); + return 0; + } + } + + return 0; +} + +static void SetSliderKey(struct GameInp* pgi, INT32 k0, INT32 k1, INT32 nSlide) +{ + pgi->nInput = GIT_KEYSLIDER; + pgi->Input.Slider.SliderAxis.nSlider[0] = (UINT8)k0; + pgi->Input.Slider.SliderAxis.nSlider[1] = (UINT8)k1; + + if (nSlide == 2) { + // Sliding + pgi->Input.Slider.nSliderSpeed = 0x0700; + pgi->Input.Slider.nSliderCenter = 0; + } else { + // Sliding (centering) + pgi->Input.Slider.nSliderSpeed = 0x0E00; + pgi->Input.Slider.nSliderCenter = 10; + } +} + +INT32 GamcAnalogKey(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nSlide) +{ + char *szSearch = NULL; + INT32 k0 = 0, k1 = 0; + szSearch = szPlay[nPlayer & 3]; + if (_strnicmp(szSearch, szi, 3) != 0) { // Not our player + return 1; + } + szi += 3; + + if (*szi == 0) { + return 1; + } + if (strcmp(szi + 1, "-axis") != 0) { + return 1; + } + + // Keyboard + if (szi[0] == 'x') { + k0 = FBK_LEFTARROW; + k1 = FBK_RIGHTARROW; + } + if (szi[0] == 'y') { + k0 = FBK_UPARROW; + k1 = FBK_DOWNARROW; + } + if (szi[0] == 'z') { + k0 = FBK_V; + k1 = FBK_F; + } + if (k0 == 0 || k1 == 0) { + return 1; + } + + SetSliderKey(pgi, k0, k1, nSlide); + + return 0; +} + +INT32 GamcAnalogJoy(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nJoy, INT32 nSlide) +{ + INT32 nAxis = 0; + + char* szSearch = szPlay[nPlayer & 3]; + if (_strnicmp(szSearch, szi, 3) != 0) { // Not our player + return 1; + } + szi += 3; + + if (szi[0] == 0) { + return 1; + } + if (strncmp(szi + 1, "-axis", 5) != 0) { + return 1; + } + + if (strncmp(szi, "x", 1) == 0) { + nAxis = 0; + } + if (strncmp(szi, "y", 1) == 0) { + nAxis = 1; + } + if (strncmp(szi, "z", 1) == 0) { + nAxis = 2; + } + + if (strlen(szi) > 6) { + if (strcmp(&szi[6], "-neg") == 0) { + nSlide = 3; + } + if (strcmp(&szi[6], "-pos") == 0) { + nSlide = 4; + } + } + + switch (nSlide) { + case 2: // Sliding + pgi->nInput = GIT_JOYSLIDER; + pgi->Input.Slider.nSliderValue = 0x8000; // Put slider in the middle + pgi->Input.Slider.nSliderSpeed = 0x0700; + pgi->Input.Slider.nSliderCenter = 0; + pgi->Input.Slider.JoyAxis.nAxis = nAxis; + pgi->Input.Slider.JoyAxis.nJoy = (UINT8)nJoy; + break; + case 1: // Sliding (centering) + pgi->nInput = GIT_JOYSLIDER; + pgi->Input.Slider.nSliderValue = 0x8000; // Put slider in the middle + pgi->Input.Slider.nSliderSpeed = 0x0E00; + pgi->Input.Slider.nSliderCenter = 10; + pgi->Input.Slider.JoyAxis.nAxis = nAxis; + pgi->Input.Slider.JoyAxis.nJoy = (UINT8)nJoy; + break; + case 3: // Absolute, axis-neg + pgi->nInput = GIT_JOYAXIS_NEG; + pgi->Input.JoyAxis.nAxis = nAxis; + pgi->Input.JoyAxis.nJoy = (UINT8)nJoy; + break; + case 4: // Absolute, axis-pos + pgi->nInput = GIT_JOYAXIS_POS; + pgi->Input.JoyAxis.nAxis = nAxis; + pgi->Input.JoyAxis.nJoy = (UINT8)nJoy; + break; + default: // Absolute, entire axis + pgi->nInput = GIT_JOYAXIS_FULL; + pgi->Input.JoyAxis.nAxis = nAxis; + pgi->Input.JoyAxis.nJoy = (UINT8)nJoy; + } + + return 0; +} + +// Set a Game Input to use Device 'nDevice' if it belongs to 'nPlayer' +// -2 = nothing -1 == keyboard, 0 == joystick 1, 1 == joystick 2 etc... +INT32 GamcPlayer(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nDevice) +{ + char* szSearch = szPlay[nPlayer & 3]; + INT32 nJoyBase = 0; + + if (_strnicmp(szSearch, szi, 3) != 0) { // Not our player + return 1; + } + szi += 3; + + if (nDevice <= -2) { + INT32 bOurs = 0; + if (strcmp(szi, "up") == 0 || strcmp(szi, "y-axis-neg") == 0) { + bOurs = 1; + } + if (strcmp(szi, "down") == 0 || strcmp(szi, "y-axis-pos") == 0) { + bOurs = 1; + } + if (strcmp(szi, "left") == 0 || strcmp(szi, "x-axis-neg") == 0) { + bOurs = 1; + } + if (strcmp(szi, "right") == 0 || strcmp(szi, "x-axis-pos") == 0) { + bOurs = 1; + } + if (strncmp(szi, "fire ", 5) == 0) { + bOurs = 1; + } + + if (!bOurs) { + return 1; + } + + pgi->nInput = GIT_CONSTANT; // Constant zero + pgi->Input.Constant.nConst = 0; // + + return 0; + } + + // Now check the rest of it + if (nDevice == -1) { + // Keyboard + if (strcmp(szi, "up") == 0 || strcmp(szi, "y-axis-neg") == 0) { + KEY(FBK_UPARROW); + } + if (strcmp(szi, "down") == 0 || strcmp(szi, "y-axis-pos") == 0) { + KEY(FBK_DOWNARROW); + } + if (strcmp(szi, "left") == 0 || strcmp(szi, "x-axis-neg") == 0) { + KEY(FBK_LEFTARROW); + } + if (strcmp(szi, "right") == 0 || strcmp(szi, "x-axis-pos") == 0) { + KEY(FBK_RIGHTARROW); + } + if (nFireButtons == 4) { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_X); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_C); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_V); + } + +// if (_stricmp(szi, "Button ABC") == 0) { +// MACRO(FBK_A); +// } +// if (_stricmp(szi, "Button BCD") == 0) { +// MACRO(FBK_S); +// } +// if (_stricmp(szi, "Button ABCD") == 0) { +// MACRO(FBK_D); +// } + + } else { + if (bStreetFighterLayout) { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_A); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_S); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_D); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_X); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_C); + } + if (_stricmp(szi, "3× Punch") == 0) { + MACRO(FBK_F); + } + if (_stricmp(szi, "3× Kick") == 0) { + MACRO(FBK_V); + } + } else { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_X); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_C); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_A); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_S); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_D); + } + if (strcmp(szi, "fire 7") == 0) { + KEY(FBK_Q); + } + if (strcmp(szi, "fire 8") == 0) { + KEY(FBK_W); + } + if (strcmp(szi, "fire 9") == 0) { + KEY(FBK_E); + } + } + } + + return 0; + } + + // Joystick + nJoyBase = 0x4000; + nJoyBase |= nDevice << 8; + + if (strcmp(szi, "up") == 0) { + KEY(nJoyBase + 0x02) + } + if (strcmp(szi, "down") == 0) { + KEY(nJoyBase + 0x03) + } + if (strcmp(szi, "left") == 0) { + KEY(nJoyBase + 0x00) + } + if (strcmp(szi, "right") == 0) { + KEY(nJoyBase + 0x01) + } + if (strncmp(szi, "fire ", 5) == 0) { + char *szb = szi + 5; + INT32 nButton = strtol(szb, NULL, 0); + if (nButton >= 1) { + nButton--; + } + KEY(nJoyBase + 0x80 + nButton); + } + + return 0; +} + +INT32 GamcPlayerHotRod(struct GameInp* pgi, char* szi, INT32 nPlayer, INT32 nFlags, INT32 nSlide) +{ + char *szSearch = NULL; + szSearch = szPlay[nPlayer & 3]; + INT32 k0 = 0, k1 = 0; + + if (_strnicmp(szSearch, szi, 3) != 0) { // Not our player + return 1; + } + szi += 3; + + if ((nFlags & 1) == 0) { + + // X-Arcade / Hanaho HotRod joystick left side + if (strcmp(szi, "x-axis") == 0) { + k0 = FBK_NUMPAD4; + k1 = FBK_NUMPAD6; + } + if (strcmp(szi, "y-axis") == 0) { + k0 = FBK_NUMPAD8; + k1 = FBK_NUMPAD2; + } + + if (strcmp(szi, "up") == 0 || strcmp(szi, "y-axis-neg") == 0) { + KEY(FBK_NUMPAD8); + } + if (strcmp(szi, "down") == 0 || strcmp(szi, "y-axis-pos") == 0) { + KEY(FBK_NUMPAD2); + } + if (strcmp(szi, "left") == 0 || strcmp(szi, "x-axis-neg") == 0) { + KEY(FBK_NUMPAD4); + } + if (strcmp(szi, "right") == 0 || strcmp(szi, "x-axis-pos") == 0) { + KEY(FBK_NUMPAD6); + } + + if (nFireButtons == 4) { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_C); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_LSHIFT); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_X); + } + } else { + if (bStreetFighterLayout) { + // Street Fighter and other Capcom 6-button games + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_LCONTROL); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_LALT); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_SPACE); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_LSHIFT); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_X); + } + + // Map the 3x macros on X-Arcade + if ((nFlags & 0x10)) { + if (_stricmp(szi, "3× Punch") == 0) { + MACRO(FBK_C); + } + if (_stricmp(szi, "3× Kick") == 0) { + MACRO(FBK_5); + } + } + } else { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_LSHIFT); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_Z); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_X); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_LCONTROL); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_LALT); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_SPACE); + } + } + } + + // Map remaining buttons as usual + if (strcmp(szi, "start") == 0) { + KEY(FBK_1); + } + if (strcmp(szi, "coin") == 0 || strcmp(szi, "select") == 0) { + KEY(FBK_3); + } + + if (k0 && k1) { + SetSliderKey(pgi, k0, k1, nSlide); + } + + return 0; + + } else { + if ((nFlags & 1) == 1) { + // X-Arcade / Hanaho HotRod joystick right side + + if (strcmp(szi, "x-axis") == 0) { + k0 = FBK_D; + k1 = FBK_G; + } + if (strcmp(szi, "y-axis") == 0) { + k0 = FBK_R; + k1 = FBK_F; + } + + if (strcmp(szi, "up") == 0 || strcmp(szi, "y-axis-neg") == 0) { + KEY(FBK_R); + } + if (strcmp(szi, "down") == 0 || strcmp(szi, "y-axis-pos") == 0) { + KEY(FBK_F); + } + if (strcmp(szi, "left") == 0 || strcmp(szi, "x-axis-neg") == 0) { + KEY(FBK_D); + } + if (strcmp(szi, "right") == 0 || strcmp(szi, "x-axis-pos") == 0) { + KEY(FBK_G); + } + + if (nFireButtons == 4) { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_RBRACKET); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_W); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_E); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_LBRACKET); + } + } else { + if (bStreetFighterLayout) { + // Street Fighter and other Capcom 6-button games + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_A); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_S); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_Q); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_W); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_E); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_LBRACKET); + } + + // Map the 3x macros on X-Arcade + if ((nFlags & 0x10)) { + if (_stricmp(szi, "3× Punch") == 0) { + MACRO(FBK_RBRACKET); + } + if (_stricmp(szi, "3× Kick") == 0) { + MACRO(FBK_6); + } + } + } else { + if (strcmp(szi, "fire 1") == 0) { + KEY(FBK_W); + } + if (strcmp(szi, "fire 2") == 0) { + KEY(FBK_E); + } + if (strcmp(szi, "fire 3") == 0) { + KEY(FBK_LBRACKET); + } + if (strcmp(szi, "fire 4") == 0) { + KEY(FBK_A); + } + if (strcmp(szi, "fire 5") == 0) { + KEY(FBK_S); + } + if (strcmp(szi, "fire 6") == 0) { + KEY(FBK_Q); + } + } + } + + // Map remaining buttons as usual + if (strcmp(szi, "start") == 0) { + KEY(FBK_2); + } + if (strcmp(szi, "coin") == 0 || strcmp(szi, "select") == 0) { + KEY(FBK_4); + } + + if (k0 && k1) { + SetSliderKey(pgi, k0, k1, nSlide); + } + + return 0; + } + } + + return 1; // Couldn't map input +} + +#undef MACRO +#undef KEY + diff --git a/src/burner/gameinp.h b/src/burner/gameinp.h new file mode 100644 index 00000000..d562f3d7 --- /dev/null +++ b/src/burner/gameinp.h @@ -0,0 +1,99 @@ + +struct giConstant { + UINT8 nConst; // The constant value +}; + +struct giSwitch { + UINT16 nCode; // The input code (for digital) +}; + +struct giJoyAxis { + UINT8 nJoy; // The joystick number + UINT8 nAxis; // The joystick axis number +}; + +struct giMouseAxis { + UINT8 nMouse; // The mouse number + UINT8 nAxis; // The axis number + UINT16 nOffset; // Used for absolute axes +}; + +struct giSliderAxis { + UINT16 nSlider[2]; // Keys to use for slider +}; + +struct giSlider { + union { + struct giJoyAxis JoyAxis; + struct giSliderAxis SliderAxis; + }; + INT16 nSliderSpeed; // speed with which keys move the slider + INT16 nSliderCenter; // Speed the slider should center itself (high value = slow) + INT32 nSliderValue; // Current position of the slider +}; + +struct giInput { + union { // Destination for the Input Value + UINT8* pVal; + UINT16* pShortVal; + }; + UINT16 nVal; // The Input Value + + union { + struct giConstant Constant; + struct giSwitch Switch; + struct giJoyAxis JoyAxis; + struct giMouseAxis MouseAxis; + struct giSlider Slider; + }; +}; + +struct giForce { + UINT8 nInput; // The input to apply force feedback efects to + UINT8 nEffect; // The effect to use +}; + +struct giMacro { + UINT8 nMode; // 0 = Unused, 1 = used + + UINT8* pVal[4]; // Destination for the Input Value + UINT8 nVal[4]; // The Input Value + UINT8 nInput[4]; // Which inputs are mapped + + struct giSwitch Switch; + + char szName[33]; // Maximum name length 16 chars +}; + +#define GIT_CONSTANT (0x01) +#define GIT_SWITCH (0x02) + +#define GIT_GROUP_SLIDER (0x08) +#define GIT_KEYSLIDER (0x08) +#define GIT_JOYSLIDER (0x09) + +#define GIT_GROUP_MOUSE (0x10) +#define GIT_MOUSEAXIS (0x10) + +#define GIT_GROUP_JOYSTICK (0x20) +#define GIT_JOYAXIS_FULL (0x20) +#define GIT_JOYAXIS_NEG (0x21) +#define GIT_JOYAXIS_POS (0x22) + +#define GIT_FORCE (0x40) + +#define GIT_GROUP_MACRO (0x80) +#define GIT_MACRO_AUTO (0x80) +#define GIT_MACRO_CUSTOM (0x81) + +struct GameInp { + UINT8 nInput; // PC side: see above + UINT8 nType; // game side: see burn.h + + union { + struct giInput Input; + struct giForce Force; + struct giMacro Macro; + }; +}; + diff --git a/src/burner/gami.cpp b/src/burner/gami.cpp new file mode 100644 index 00000000..6c60d24f --- /dev/null +++ b/src/burner/gami.cpp @@ -0,0 +1,1720 @@ +// Burner Game Input +#include "burner.h" + +// Player Default Controls +INT32 nPlayerDefaultControls[4] = {0, 1, 2, 3}; +TCHAR szPlayerDefaultIni[4][MAX_PATH] = { _T(""), _T(""), _T(""), _T("") }; + +// Mapping of PC inputs to game inputs +struct GameInp* GameInp = NULL; +UINT32 nGameInpCount = 0; +UINT32 nMacroCount = 0; +UINT32 nMaxMacro = 0; + +INT32 nAnalogSpeed; + +INT32 nFireButtons = 0; + +bool bStreetFighterLayout = false; +bool bLeftAltkeyMapped = false; + +// --------------------------------------------------------------------------- + +// Check if the left alt (menu) key is mapped +void GameInpCheckLeftAlt() +{ + struct GameInp* pgi; + UINT32 i; + + bLeftAltkeyMapped = false; + + for (i = 0, pgi = GameInp; i < (nGameInpCount + nMacroCount); i++, pgi++) { + + if (bLeftAltkeyMapped) { + break; + } + + switch (pgi->nInput) { + case GIT_SWITCH: + if (pgi->Input.Switch.nCode == FBK_LALT) { + bLeftAltkeyMapped = true; + } + break; + case GIT_MACRO_AUTO: + case GIT_MACRO_CUSTOM: + if (pgi->Macro.nMode) { + if (pgi->Macro.Switch.nCode == FBK_LALT) { + bLeftAltkeyMapped = true; + } + } + break; + + default: + continue; + } + } +} + +// Check if the sytem mouse is mapped and set the cooperative level apropriately +void GameInpCheckMouse() +{ + bool bMouseMapped = false; + struct GameInp* pgi; + UINT32 i; + + for (i = 0, pgi = GameInp; i < (nGameInpCount + nMacroCount); i++, pgi++) { + + if (bMouseMapped) { + break; + } + + switch (pgi->nInput) { + case GIT_SWITCH: + if ((pgi->Input.Switch.nCode & 0xFF00) == 0x8000) { + bMouseMapped = true; + } + break; + case GIT_MOUSEAXIS: + if (pgi->Input.MouseAxis.nMouse == 0) { + bMouseMapped = true; + } + break; + case GIT_MACRO_AUTO: + case GIT_MACRO_CUSTOM: + if (pgi->Macro.nMode) { + if ((pgi->Macro.Switch.nCode & 0xFF00) == 0x8000) { + bMouseMapped = true; + } + } + break; + + default: + continue; + } + } + + if (bDrvOkay) { + if (!bRunPause) { + InputSetCooperativeLevel(bMouseMapped, bAlwaysProcessKeyboardInput); + } else { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + } + } else { + InputSetCooperativeLevel(false, false); + } +} + +// --------------------------------------------------------------------------- + +INT32 GameInpBlank(INT32 bDipSwitch) +{ + UINT32 i = 0; + struct GameInp* pgi = NULL; + + // Reset all inputs to undefined (even dip switches, if bDipSwitch==1) + if (GameInp == NULL) { + return 1; + } + + // Get the targets in the library for the Input Values + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + BurnDrvGetInputInfo(&bii, i); + if (bDipSwitch == 0 && (bii.nType & BIT_GROUP_CONSTANT)) { // Don't blank the dip switches + continue; + } + + memset(pgi, 0, sizeof(*pgi)); // Clear input + + pgi->nType = bii.nType; // store input type + pgi->Input.pVal = bii.pVal; // store input pointer to value + + if (bii.nType & BIT_GROUP_CONSTANT) { // Further initialisation for constants/DIPs + pgi->nInput = GIT_CONSTANT; + pgi->Input.Constant.nConst = *bii.pVal; + } + } + + for (i = 0; i < nMacroCount; i++, pgi++) { + pgi->Macro.nMode = 0; + if (pgi->nInput == GIT_MACRO_CUSTOM) { + pgi->nInput = 0; + } + } + + bLeftAltkeyMapped = false; + + return 0; +} + +static void GameInpInitMacros() +{ + struct GameInp* pgi; + struct BurnInputInfo bii; + + INT32 nPunchx3[4] = {0, 0, 0, 0}; + INT32 nPunchInputs[4][3]; + INT32 nKickx3[4] = {0, 0, 0, 0}; + INT32 nKickInputs[4][3]; + + INT32 nNeogeoButtons[4][4]; + INT32 nPgmButtons[4][4]; + + bStreetFighterLayout = false; + nMacroCount = 0; + + nFireButtons = 0; + + for (UINT32 i = 0; i < nGameInpCount; i++) { + bii.szName = NULL; + BurnDrvGetInputInfo(&bii, i); + if (bii.szName == NULL) { + bii.szName = ""; + } + if (bii.szName[0] == 'P' && bii.szName[1] >= '1' && bii.szName[1] <= '4') { + INT32 nPlayer = bii.szName[1] - '1'; + + if (nPlayer == 0) { + if (strncmp(" fire", bii.szInfo + 2, 5) == 0) { + nFireButtons++; + } + } + + if (_stricmp(" Weak Punch", bii.szName + 2) == 0) { + nPunchx3[nPlayer] |= 1; + nPunchInputs[nPlayer][0] = i; + } + if (_stricmp(" Medium Punch", bii.szName + 2) == 0) { + nPunchx3[nPlayer] |= 2; + nPunchInputs[nPlayer][1] = i; + } + if (_stricmp(" Strong Punch", bii.szName + 2) == 0) { + nPunchx3[nPlayer] |= 4; + nPunchInputs[nPlayer][2] = i; + } + if (_stricmp(" Weak Kick", bii.szName + 2) == 0) { + nKickx3[nPlayer] |= 1; + nKickInputs[nPlayer][0] = i; + } + if (_stricmp(" Medium Kick", bii.szName + 2) == 0) { + nKickx3[nPlayer] |= 2; + nKickInputs[nPlayer][1] = i; + } + if (_stricmp(" Strong Kick", bii.szName + 2) == 0) { + nKickx3[nPlayer] |= 4; + nKickInputs[nPlayer][2] = i; + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + if (_stricmp(" Button A", bii.szName + 2) == 0) { + nNeogeoButtons[nPlayer][0] = i; + } + if (_stricmp(" Button B", bii.szName + 2) == 0) { + nNeogeoButtons[nPlayer][1] = i; + } + if (_stricmp(" Button C", bii.szName + 2) == 0) { + nNeogeoButtons[nPlayer][2] = i; + } + if (_stricmp(" Button D", bii.szName + 2) == 0) { + nNeogeoButtons[nPlayer][3] = i; + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_IGS_PGM) { + if (_stricmp(" Button 1", bii.szName + 2) == 0) { + nPgmButtons[nPlayer][0] = i; + } + if (_stricmp(" Button 2", bii.szName + 2) == 0) { + nPgmButtons[nPlayer][1] = i; + } + if (_stricmp(" Button 3", bii.szName + 2) == 0) { + nPgmButtons[nPlayer][2] = i; + } + if (_stricmp(" Button 4", bii.szName + 2) == 0) { + nPgmButtons[nPlayer][3] = i; + } + } + } + } + + pgi = GameInp + nGameInpCount; + + for (INT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) { + if (nPunchx3[nPlayer] == 7) { // Create a 3x punch macro + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + + sprintf(pgi->Macro.szName, "P%i 3× Punch", nPlayer + 1); + for (INT32 j = 0; j < 3; j++) { + BurnDrvGetInputInfo(&bii, nPunchInputs[nPlayer][j]); + pgi->Macro.pVal[j] = bii.pVal; + pgi->Macro.nVal[j] = 1; + } + + nMacroCount++; + pgi++; + } + + if (nKickx3[nPlayer] == 7) { // Create a 3x kick macro + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + + sprintf(pgi->Macro.szName, "P%i 3× Kick", nPlayer + 1); + for (INT32 j = 0; j < 3; j++) { + BurnDrvGetInputInfo(&bii, nKickInputs[nPlayer][j]); + pgi->Macro.pVal[j] = bii.pVal; + pgi->Macro.nVal[j] = 1; + } + + nMacroCount++; + pgi++; + } + + if (nFireButtons == 4 && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons AB", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons AC", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons AD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons BC", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons BD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons CD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons ABC", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons ABD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons ACD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons BCD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons ABCD", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][2]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + BurnDrvGetInputInfo(&bii, nNeogeoButtons[nPlayer][3]); + pgi->Macro.pVal[3] = bii.pVal; + pgi->Macro.nVal[3] = 1; + nMacroCount++; + pgi++; + } + + if (nFireButtons == 4 && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_IGS_PGM) { + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 12", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 13", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 14", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 23", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 24", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 34", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 123", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 124", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 134", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 234", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + nMacroCount++; + pgi++; + + pgi->nInput = GIT_MACRO_AUTO; + pgi->nType = BIT_DIGITAL; + pgi->Macro.nMode = 0; + sprintf(pgi->Macro.szName, "P%i Buttons 1234", nPlayer + 1); + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][0]); + pgi->Macro.pVal[0] = bii.pVal; + pgi->Macro.nVal[0] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][1]); + pgi->Macro.pVal[1] = bii.pVal; + pgi->Macro.nVal[1] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][2]); + pgi->Macro.pVal[2] = bii.pVal; + pgi->Macro.nVal[2] = 1; + BurnDrvGetInputInfo(&bii, nPgmButtons[nPlayer][3]); + pgi->Macro.pVal[3] = bii.pVal; + pgi->Macro.nVal[3] = 1; + nMacroCount++; + pgi++; + } + } + + if ((nPunchx3[0] == 7) && (nKickx3[0] == 7)) { + bStreetFighterLayout = true; + } + if (nFireButtons >= 5 && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_CAPCOM_CPS2) { + bStreetFighterLayout = true; + } +} + +INT32 GameInpInit() +{ + INT32 nRet = 0; + // Count the number of inputs + nGameInpCount = 0; + nMacroCount = 0; + nMaxMacro = nMaxPlayers * 12; + + for (UINT32 i = 0; i < 0x1000; i++) { + nRet = BurnDrvGetInputInfo(NULL,i); + if (nRet) { // end of input list + nGameInpCount = i; + break; + } + } + + // Allocate space for all the inputs + INT32 nSize = (nGameInpCount + nMaxMacro) * sizeof(struct GameInp); + GameInp = (struct GameInp*)malloc(nSize); + if (GameInp == NULL) { + return 1; + } + memset(GameInp, 0, nSize); + + GameInpBlank(1); + + InpDIPSWResetDIPs(); + + GameInpInitMacros(); + + nAnalogSpeed = 0x0100; + + return 0; +} + +INT32 GameInpExit() +{ + if (GameInp) { + free(GameInp); + GameInp = NULL; + } + + nGameInpCount = 0; + nMacroCount = 0; + + nFireButtons = 0; + + bStreetFighterLayout = false; + bLeftAltkeyMapped = false; + + return 0; +} + +// --------------------------------------------------------------------------- +// Convert a string from a config file to an input + +static TCHAR* SliderInfo(struct GameInp* pgi, TCHAR* s) +{ + TCHAR* szRet = NULL; + pgi->Input.Slider.nSliderSpeed = 0x700; // defaults + pgi->Input.Slider.nSliderCenter = 0; + pgi->Input.Slider.nSliderValue = 0x8000; + + szRet = LabelCheck(s, _T("speed")); + s = szRet; + if (s == NULL) { + return s; + } + pgi->Input.Slider.nSliderSpeed = (INT16)_tcstol(s, &szRet, 0); + s = szRet; + if (s==NULL) { + return s; + } + szRet = LabelCheck(s, _T("center")); + s = szRet; + if (s == NULL) { + return s; + } + pgi->Input.Slider.nSliderCenter = (INT16)_tcstol(s, &szRet, 0); + s = szRet; + if (s == NULL) { + return s; + } + + return szRet; +} + +static INT32 StringToJoyAxis(struct GameInp* pgi, TCHAR* s) +{ + TCHAR* szRet = s; + + pgi->Input.JoyAxis.nJoy = (UINT8)_tcstol(s, &szRet, 0); + if (szRet == NULL) { + return 1; + } + s = szRet; + pgi->Input.JoyAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0); + if (szRet == NULL) { + return 1; + } + + return 0; +} + +static INT32 StringToMouseAxis(struct GameInp* pgi, TCHAR* s) +{ + TCHAR* szRet = s; + + pgi->Input.MouseAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0); + if (szRet == NULL) { + return 1; + } + + return 0; +} + +static INT32 StringToMacro(struct GameInp* pgi, TCHAR* s) +{ + TCHAR* szRet = NULL; + + szRet = LabelCheck(s, _T("switch")); + if (szRet) { + s = szRet; + pgi->Macro.nMode = 0x01; + pgi->Macro.Switch.nCode = (UINT16)_tcstol(s, &szRet, 0); + return 0; + } + + return 1; +} + +static INT32 StringToInp(struct GameInp* pgi, TCHAR* s) +{ + TCHAR* szRet = NULL; + + SKIP_WS(s); // skip whitespace + szRet = LabelCheck(s, _T("undefined")); + if (szRet) { + pgi->nInput = 0; + return 0; + } + + szRet = LabelCheck(s, _T("constant")); + if (szRet) { + pgi->nInput = GIT_CONSTANT; + s = szRet; + pgi->Input.Constant.nConst=(UINT8)_tcstol(s, &szRet, 0); + *(pgi->Input.pVal) = pgi->Input.Constant.nConst; + return 0; + } + + szRet = LabelCheck(s, _T("switch")); + if (szRet) { + pgi->nInput = GIT_SWITCH; + s = szRet; + pgi->Input.Switch.nCode = (UINT16)_tcstol(s, &szRet, 0); + return 0; + } + + // Analog using mouse axis: + szRet = LabelCheck(s, _T("mouseaxis")); + if (szRet) { + pgi->nInput = GIT_MOUSEAXIS; + return StringToMouseAxis(pgi, szRet); + } + // Analog using joystick axis: + szRet = LabelCheck(s, _T("joyaxis-neg")); + if (szRet) { + pgi->nInput = GIT_JOYAXIS_NEG; + return StringToJoyAxis(pgi, szRet); + } + szRet = LabelCheck(s, _T("joyaxis-pos")); + if (szRet) { + pgi->nInput = GIT_JOYAXIS_POS; + return StringToJoyAxis(pgi, szRet); + } + szRet = LabelCheck(s, _T("joyaxis")); + if (szRet) { + pgi->nInput = GIT_JOYAXIS_FULL; + return StringToJoyAxis(pgi, szRet); + } + + // Analog using keyboard slider + szRet = LabelCheck(s, _T("slider")); + if (szRet) { + s = szRet; + pgi->nInput = GIT_KEYSLIDER; + pgi->Input.Slider.SliderAxis.nSlider[0] = 0; // defaults + pgi->Input.Slider.SliderAxis.nSlider[1] = 0; // + + pgi->Input.Slider.SliderAxis.nSlider[0] = (UINT16)_tcstol(s, &szRet, 0); + s = szRet; + if (s == NULL) { + return 1; + } + pgi->Input.Slider.SliderAxis.nSlider[1] = (UINT16)_tcstol(s, &szRet, 0); + s = szRet; + if (s == NULL) { + return 1; + } + szRet = SliderInfo(pgi, s); + s = szRet; + if (s == NULL) { // Get remaining slider info + return 1; + } + return 0; + } + + // Analog using joystick slider + szRet = LabelCheck(s, _T("joyslider")); + if (szRet) { + s = szRet; + pgi->nInput = GIT_JOYSLIDER; + pgi->Input.Slider.JoyAxis.nJoy = 0; // defaults + pgi->Input.Slider.JoyAxis.nAxis = 0; // + + pgi->Input.Slider.JoyAxis.nJoy = (UINT8)_tcstol(s, &szRet, 0); + s = szRet; + if (s == NULL) { + return 1; + } + pgi->Input.Slider.JoyAxis.nAxis = (UINT8)_tcstol(s, &szRet, 0); + s = szRet; + if (s == NULL) { + return 1; + } + szRet = SliderInfo(pgi, s); // Get remaining slider info + s = szRet; + if (s == NULL) { + return 1; + } + return 0; + } + + return 1; +} + +// --------------------------------------------------------------------------- +// Convert an input to a string for config files + +static TCHAR* InpToString(struct GameInp* pgi) +{ + static TCHAR szString[80]; + + if (pgi->nInput == 0) { + return _T("undefined"); + } + if (pgi->nInput == GIT_CONSTANT) { + _stprintf(szString, _T("constant 0x%.2X"), pgi->Input.Constant.nConst); + return szString; + } + if (pgi->nInput == GIT_SWITCH) { + _stprintf(szString, _T("switch 0x%.2X"), pgi->Input.Switch.nCode); + return szString; + } + if (pgi->nInput == GIT_KEYSLIDER) { + _stprintf(szString, _T("slider 0x%.2x 0x%.2x speed 0x%x center %d"), pgi->Input.Slider.SliderAxis.nSlider[0], pgi->Input.Slider.SliderAxis.nSlider[1], pgi->Input.Slider.nSliderSpeed, pgi->Input.Slider.nSliderCenter); + return szString; + } + if (pgi->nInput == GIT_JOYSLIDER) { + _stprintf(szString, _T("joyslider %d %d speed 0x%x center %d"), pgi->Input.Slider.JoyAxis.nJoy, pgi->Input.Slider.JoyAxis.nAxis, pgi->Input.Slider.nSliderSpeed, pgi->Input.Slider.nSliderCenter); + return szString; + } + if (pgi->nInput == GIT_MOUSEAXIS) { + _stprintf(szString, _T("mouseaxis %d"), pgi->Input.MouseAxis.nAxis); + return szString; + } + if (pgi->nInput == GIT_JOYAXIS_FULL) { + _stprintf(szString, _T("joyaxis %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + return szString; + } + if (pgi->nInput == GIT_JOYAXIS_NEG) { + _stprintf(szString, _T("joyaxis-neg %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + return szString; + } + if (pgi->nInput == GIT_JOYAXIS_POS) { + _stprintf(szString, _T("joyaxis-pos %d %d"), pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + return szString; + } + + return _T("unknown"); +} + +static TCHAR* InpMacroToString(struct GameInp* pgi) +{ + static TCHAR szString[256]; + + if (pgi->nInput == GIT_MACRO_AUTO) { + if (pgi->Macro.nMode) { + _stprintf(szString, _T("switch 0x%.2X"), pgi->Macro.Switch.nCode); + return szString; + } + } + + if (pgi->nInput == GIT_MACRO_CUSTOM) { + struct BurnInputInfo bii; + + if (pgi->Macro.nMode) { + _stprintf(szString, _T("switch 0x%.2X"), pgi->Macro.Switch.nCode); + } else { + _stprintf(szString, _T("undefined")); + } + + for (INT32 i = 0; i < 4; i++) { + if (pgi->Macro.pVal[i]) { + BurnDrvGetInputInfo(&bii, pgi->Macro.nInput[i]); + _stprintf(szString + _tcslen(szString), _T(" \"%hs\" 0x%02X"), bii.szName, pgi->Macro.nVal[i]); + } + } + + return szString; + } + + return _T("undefined"); +} + +// --------------------------------------------------------------------------- +// Generate a user-friendly name for a control (PC-side) + +static struct { INT32 nCode; TCHAR* szName; } KeyNames[] = { + +#define FBK_DEFNAME(k) k, _T(#k) + + { FBK_ESCAPE, _T("ESCAPE") }, + { FBK_1, _T("1") }, + { FBK_2, _T("2") }, + { FBK_3, _T("3") }, + { FBK_4, _T("4") }, + { FBK_5, _T("5") }, + { FBK_6, _T("6") }, + { FBK_7, _T("7") }, + { FBK_8, _T("8") }, + { FBK_9, _T("9") }, + { FBK_0, _T("0") }, + { FBK_MINUS, _T("MINUS") }, + { FBK_EQUALS, _T("EQUALS") }, + { FBK_BACK, _T("BACKSPACE") }, + { FBK_TAB, _T("TAB") }, + { FBK_Q, _T("Q") }, + { FBK_W, _T("W") }, + { FBK_E, _T("E") }, + { FBK_R, _T("R") }, + { FBK_T, _T("T") }, + { FBK_Y, _T("Y") }, + { FBK_U, _T("U") }, + { FBK_I, _T("I") }, + { FBK_O, _T("O") }, + { FBK_P, _T("P") }, + { FBK_LBRACKET, _T("OPENING BRACKET") }, + { FBK_RBRACKET, _T("CLOSING BRACKET") }, + { FBK_RETURN, _T("ENTER") }, + { FBK_LCONTROL, _T("LEFT CONTROL") }, + { FBK_A, _T("A") }, + { FBK_S, _T("S") }, + { FBK_D, _T("D") }, + { FBK_F, _T("F") }, + { FBK_G, _T("G") }, + { FBK_H, _T("H") }, + { FBK_J, _T("J") }, + { FBK_K, _T("K") }, + { FBK_L, _T("L") }, + { FBK_SEMICOLON, _T("SEMICOLON") }, + { FBK_APOSTROPHE, _T("APOSTROPHE") }, + { FBK_GRAVE, _T("ACCENT GRAVE") }, + { FBK_LSHIFT, _T("LEFT SHIFT") }, + { FBK_BACKSLASH, _T("BACKSLASH") }, + { FBK_Z, _T("Z") }, + { FBK_X, _T("X") }, + { FBK_C, _T("C") }, + { FBK_V, _T("V") }, + { FBK_B, _T("B") }, + { FBK_N, _T("N") }, + { FBK_M, _T("M") }, + { FBK_COMMA, _T("COMMA") }, + { FBK_PERIOD, _T("PERIOD") }, + { FBK_SLASH, _T("SLASH") }, + { FBK_RSHIFT, _T("RIGHT SHIFT") }, + { FBK_MULTIPLY, _T("NUMPAD MULTIPLY") }, + { FBK_LALT, _T("LEFT MENU") }, + { FBK_SPACE, _T("SPACE") }, + { FBK_CAPITAL, _T("CAPSLOCK") }, + { FBK_F1, _T("F1") }, + { FBK_F2, _T("F2") }, + { FBK_F3, _T("F3") }, + { FBK_F4, _T("F4") }, + { FBK_F5, _T("F5") }, + { FBK_F6, _T("F6") }, + { FBK_F7, _T("F7") }, + { FBK_F8, _T("F8") }, + { FBK_F9, _T("F9") }, + { FBK_F10, _T("F10") }, + { FBK_NUMLOCK, _T("NUMLOCK") }, + { FBK_SCROLL, _T("SCROLLLOCK") }, + { FBK_NUMPAD7, _T("NUMPAD 7") }, + { FBK_NUMPAD8, _T("NUMPAD 8") }, + { FBK_NUMPAD9, _T("NUMPAD 9") }, + { FBK_SUBTRACT, _T("NUMPAD SUBTRACT") }, + { FBK_NUMPAD4, _T("NUMPAD 4") }, + { FBK_NUMPAD5, _T("NUMPAD 5") }, + { FBK_NUMPAD6, _T("NUMPAD 6") }, + { FBK_ADD, _T("NUMPAD ADD") }, + { FBK_NUMPAD1, _T("NUMPAD 1") }, + { FBK_NUMPAD2, _T("NUMPAD 2") }, + { FBK_NUMPAD3, _T("NUMPAD 3") }, + { FBK_NUMPAD0, _T("NUMPAD 0") }, + { FBK_DECIMAL, _T("NUMPAD DECIMAL POINT") }, + { FBK_DEFNAME(FBK_OEM_102) }, + { FBK_F11, _T("F11") }, + { FBK_F12, _T("F12") }, + { FBK_F13, _T("F13") }, + { FBK_F14, _T("F14") }, + { FBK_F15, _T("F15") }, + { FBK_DEFNAME(FBK_KANA) }, + { FBK_DEFNAME(FBK_ABNT_C1) }, + { FBK_DEFNAME(FBK_CONVERT) }, + { FBK_DEFNAME(FBK_NOCONVERT) }, + { FBK_DEFNAME(FBK_YEN) }, + { FBK_DEFNAME(FBK_ABNT_C2) }, + { FBK_NUMPADEQUALS, _T("NUMPAD EQUALS") }, + { FBK_DEFNAME(FBK_PREVTRACK) }, + { FBK_DEFNAME(FBK_AT) }, + { FBK_COLON, _T("COLON") }, + { FBK_UNDERLINE, _T("UNDERSCORE") }, + { FBK_DEFNAME(FBK_KANJI) }, + { FBK_DEFNAME(FBK_STOP) }, + { FBK_DEFNAME(FBK_AX) }, + { FBK_DEFNAME(FBK_UNLABELED) }, + { FBK_DEFNAME(FBK_NEXTTRACK) }, + { FBK_NUMPADENTER, _T("NUMPAD ENTER") }, + { FBK_RCONTROL, _T("RIGHT CONTROL") }, + { FBK_DEFNAME(FBK_MUTE) }, + { FBK_DEFNAME(FBK_CALCULATOR) }, + { FBK_DEFNAME(FBK_PLAYPAUSE) }, + { FBK_DEFNAME(FBK_MEDIASTOP) }, + { FBK_DEFNAME(FBK_VOLUMEDOWN) }, + { FBK_DEFNAME(FBK_VOLUMEUP) }, + { FBK_DEFNAME(FBK_WEBHOME) }, + { FBK_DEFNAME(FBK_NUMPADCOMMA) }, + { FBK_DIVIDE, _T("NUMPAD DIVIDE") }, + { FBK_SYSRQ, _T("PRINTSCREEN") }, + { FBK_RALT, _T("RIGHT MENU") }, + { FBK_PAUSE, _T("PAUSE") }, + { FBK_HOME, _T("HOME") }, + { FBK_UPARROW, _T("ARROW UP") }, + { FBK_PRIOR, _T("PAGE UP") }, + { FBK_LEFTARROW, _T("ARROW LEFT") }, + { FBK_RIGHTARROW, _T("ARROW RIGHT") }, + { FBK_END, _T("END") }, + { FBK_DOWNARROW, _T("ARROW DOWN") }, + { FBK_NEXT, _T("PAGE DOWN") }, + { FBK_INSERT, _T("INSERT") }, + { FBK_DELETE, _T("DELETE") }, + { FBK_LWIN, _T("LEFT WINDOWS") }, + { FBK_RWIN, _T("RIGHT WINDOWS") }, + { FBK_DEFNAME(FBK_APPS) }, + { FBK_DEFNAME(FBK_POWER) }, + { FBK_DEFNAME(FBK_SLEEP) }, + { FBK_DEFNAME(FBK_WAKE) }, + { FBK_DEFNAME(FBK_WEBSEARCH) }, + { FBK_DEFNAME(FBK_WEBFAVORITES) }, + { FBK_DEFNAME(FBK_WEBREFRESH) }, + { FBK_DEFNAME(FBK_WEBSTOP) }, + { FBK_DEFNAME(FBK_WEBFORWARD) }, + { FBK_DEFNAME(FBK_WEBBACK) }, + { FBK_DEFNAME(FBK_MYCOMPUTER) }, + { FBK_DEFNAME(FBK_MAIL) }, + { FBK_DEFNAME(FBK_MEDIASELECT) }, + +#undef FBK_DEFNAME + + { 0, NULL } +}; + +TCHAR* InputCodeDesc(INT32 c) +{ + static TCHAR szString[64]; + TCHAR* szName = _T(""); + + // Mouse + if (c >= 0x8000) { + INT32 nMouse = (c >> 8) & 0x3F; + INT32 nCode = c & 0xFF; + if (nCode >= 0x80) { + _stprintf(szString, _T("Mouse %d Button %d"), nMouse, nCode & 0x7F); + return szString; + } + if (nCode < 0x06) { + TCHAR szAxis[3][3] = { _T("X"), _T("Y"), _T("Z") }; + TCHAR szDir[6][16] = { _T("negative"), _T("positive"), _T("Left"), _T("Right"), _T("Up"), _T("Down") }; + if (nCode < 4) { + _stprintf(szString, _T("Mouse %d %s (%s %s)"), nMouse, szDir[nCode + 2], szAxis[nCode >> 1], szDir[nCode & 1]); + } else { + _stprintf(szString, _T("Mouse %d %s %s"), nMouse, szAxis[nCode >> 1], szDir[nCode & 1]); + } + return szString; + } + } + + // Joystick + if (c >= 0x4000 && c < 0x8000) { + INT32 nJoy = (c >> 8) & 0x3F; + INT32 nCode = c & 0xFF; + if (nCode >= 0x80) { + _stprintf(szString, _T("Joy %d Button %d"), nJoy, nCode & 0x7F); + return szString; + } + if (nCode < 0x10) { + TCHAR szAxis[8][3] = { _T("X"), _T("Y"), _T("Z"), _T("rX"), _T("rY"), _T("rZ"), _T("s0"), _T("s1") }; + TCHAR szDir[6][16] = { _T("negative"), _T("positive"), _T("Left"), _T("Right"), _T("Up"), _T("Down") }; + if (nCode < 4) { + _stprintf(szString, _T("Joy %d %s (%s %s)"), nJoy, szDir[nCode + 2], szAxis[nCode >> 1], szDir[nCode & 1]); + } else { + _stprintf(szString, _T("Joy %d %s %s"), nJoy, szAxis[nCode >> 1], szDir[nCode & 1]); + } + return szString; + } + if (nCode < 0x20) { + TCHAR szDir[4][16] = { _T("Left"), _T("Right"), _T("Up"), _T("Down") }; + _stprintf(szString, _T("Joy %d POV-hat %d %s"), nJoy, (nCode & 0x0F) >> 2, szDir[nCode & 3]); + return szString; + } + } + + for (INT32 i = 0; KeyNames[i].nCode; i++) { + if (c == KeyNames[i].nCode) { + if (KeyNames[i].szName) { + szName = KeyNames[i].szName; + } + break; + } + } + + if (szName[0]) { + _stprintf(szString, _T("%s"), szName); + } else { + _stprintf(szString, _T("code 0x%.2X"), c); + } + + return szString; +} + +TCHAR* InpToDesc(struct GameInp* pgi) +{ + static TCHAR szInputName[64] = _T(""); + + if (pgi->nInput == 0) { + return _T(""); + } + if (pgi->nInput == GIT_CONSTANT) { + if (pgi->nType & BIT_GROUP_CONSTANT) { + for (INT32 i = 0; i < 8; i++) { + szInputName[7 - i] = pgi->Input.Constant.nConst & (1 << i) ? _T('1') : _T('0'); + } + szInputName[8] = 0; + + return szInputName; + } + + if (pgi->Input.Constant.nConst == 0) { + return _T("-"); + } + } + if (pgi->nInput == GIT_SWITCH) { + return InputCodeDesc(pgi->Input.Switch.nCode); + } + if (pgi->nInput == GIT_MOUSEAXIS) { + TCHAR nAxis = _T('?'); + switch (pgi->Input.MouseAxis.nAxis) { + case 0: + nAxis = _T('X'); + break; + case 1: + nAxis = _T('Y'); + break; + case 2: + nAxis = _T('Z'); + break; + } + _stprintf(szInputName, _T("Mouse %i %c axis"), pgi->Input.MouseAxis.nMouse, nAxis); + return szInputName; + } + if (pgi->nInput & GIT_GROUP_JOYSTICK) { + TCHAR szAxis[8][3] = { _T("X"), _T("Y"), _T("Z"), _T("rX"), _T("rY"), _T("rZ"), _T("s0"), _T("s1") }; + TCHAR szRange[4][16] = { _T("unknown"), _T("full"), _T("negative"), _T("positive") }; + INT32 nRange = 0; + switch (pgi->nInput) { + case GIT_JOYAXIS_FULL: + nRange = 1; + break; + case GIT_JOYAXIS_NEG: + nRange = 2; + break; + case GIT_JOYAXIS_POS: + nRange = 3; + break; + } + + _stprintf(szInputName, _T("Joy %d %s axis (%s range)"), pgi->Input.JoyAxis.nJoy, szAxis[pgi->Input.JoyAxis.nAxis], szRange[nRange]); + return szInputName; + } + + return InpToString(pgi); // Just do the rest as they are in the config file +} + +TCHAR* InpMacroToDesc(struct GameInp* pgi) +{ + if (pgi->nInput & GIT_GROUP_MACRO) { + if (pgi->Macro.nMode) { + return InputCodeDesc(pgi->Macro.Switch.nCode); + } + } + + return _T(""); +} + +// --------------------------------------------------------------------------- + +// Find the input number by info +static UINT32 InputInfoToNum(TCHAR* szName) +{ + for (UINT32 i = 0; i < nGameInpCount; i++) { + struct BurnInputInfo bii; + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal == NULL) { + continue; + } + + if (_tcsicmp(szName, ANSIToTCHAR(bii.szInfo, NULL, 0)) == 0) { + return i; + } + } + return ~0U; +} + +// Find the input number by name +static UINT32 InputNameToNum(TCHAR* szName) +{ + for (UINT32 i = 0; i < nGameInpCount; i++) { + struct BurnInputInfo bii; + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal == NULL) { + continue; + } + + if (_tcsicmp(szName, ANSIToTCHAR(bii.szName, NULL, 0)) == 0) { + return i; + } + } + return ~0U; +} + +static TCHAR* InputNumToName(UINT32 i) +{ + struct BurnInputInfo bii; + bii.szName = NULL; + BurnDrvGetInputInfo(&bii, i); + if (bii.szName == NULL) { + return _T("unknown"); + } + return ANSIToTCHAR(bii.szName, NULL, 0); +} + +static UINT32 MacroNameToNum(TCHAR* szName) +{ + struct GameInp* pgi = GameInp + nGameInpCount; + for (UINT32 i = 0; i < nMacroCount; i++, pgi++) { + if (pgi->nInput & GIT_GROUP_MACRO) { + if (_tcsicmp(szName, ANSIToTCHAR(pgi->Macro.szName, NULL, 0)) == 0) { + return i; + } + } + } + return ~0U; +} + +// --------------------------------------------------------------------------- + +static INT32 GameInpAutoOne(struct GameInp* pgi, char* szi) +{ + for (INT32 i = 0; i < nMaxPlayers; i++) { + INT32 nSlide = nPlayerDefaultControls[i] >> 4; + switch (nPlayerDefaultControls[i] & 0x0F) { + case 0: // Keyboard + GamcAnalogKey(pgi, szi, i, nSlide); + GamcPlayer(pgi, szi, i, -1); + GamcMisc(pgi, szi, i); + break; + case 1: // Joystick 1 + GamcAnalogJoy(pgi, szi, i, 0, nSlide); + GamcPlayer(pgi, szi, i, 0); + GamcMisc(pgi, szi, i); + break; + case 2: // Joystick 2 + GamcAnalogJoy(pgi, szi, i, 1, nSlide); + GamcPlayer(pgi, szi, i, 1); + GamcMisc(pgi, szi, i); + break; + case 3: // Joystick 3 + GamcAnalogJoy(pgi, szi, i, 2, nSlide); + GamcPlayer(pgi, szi, i, 2); + GamcMisc(pgi, szi, i); + break; + case 4: // X-Arcade left side + GamcMisc(pgi, szi, i); + GamcPlayerHotRod(pgi, szi, i, 0x10, nSlide); + break; + case 5: // X-Arcade right side + GamcMisc(pgi, szi, i); + GamcPlayerHotRod(pgi, szi, i, 0x11, nSlide); + break; + case 6: // Hot Rod left side + GamcMisc(pgi, szi, i); + GamcPlayerHotRod(pgi, szi, i, 0x00, nSlide); + break; + case 7: // Hot Rod right side + GamcMisc(pgi, szi, i); + GamcPlayerHotRod(pgi, szi, i, 0x01, nSlide); + break; + default: + GamcMisc(pgi, szi, i); + } + } + + return 0; +} + +static INT32 AddCustomMacro(TCHAR* szValue, bool bOverWrite) +{ + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + + if (QuoteRead(&szQuote, &szEnd, szValue)) { + return 1; + } + + INT32 nMode = -1; + INT32 nInput = -1; + bool bCreateNew = false; + struct BurnInputInfo bii; + + for (UINT32 j = nGameInpCount; j < nGameInpCount + nMacroCount; j++) { + if (GameInp[j].nInput == GIT_MACRO_CUSTOM) { + if (LabelCheck(szQuote, ANSIToTCHAR(GameInp[j].Macro.szName, NULL, 0))) { + nInput = j; + break; + } + } + } + + if (nInput == -1) { + if (nMacroCount + 1 == nMaxMacro) { + return 1; + } + nInput = nGameInpCount + nMacroCount; + bCreateNew = true; + } + + _tcscpy(szQuote, ANSIToTCHAR(GameInp[nInput].Macro.szName, NULL, 0)); + + if ((szValue = LabelCheck(szEnd, _T("undefined"))) != NULL) { + nMode = 0; + } else { + if ((szValue = LabelCheck(szEnd, _T("switch"))) != NULL) { + + if (bOverWrite || GameInp[nInput].Macro.nMode == 0) { + GameInp[nInput].Macro.Switch.nCode = (UINT16)_tcstol(szValue, &szValue, 0); + } + + nMode = 1; + } + } + + if (nMode >= 0) { + INT32 nFound = 0; + + for (INT32 i = 0; i < 4; i++) { + GameInp[nInput].Macro.pVal[i] = NULL; + GameInp[nInput].Macro.nVal[i] = 0; + GameInp[nInput].Macro.nInput[i] = 0; + + if (szValue == NULL) { + break; + } + + if (QuoteRead(&szQuote, &szEnd, szValue)) { + break; + } + + for (UINT32 j = 0; j < nGameInpCount; j++) { + bii.szName = NULL; + BurnDrvGetInputInfo(&bii, j); + if (bii.pVal == NULL) { + continue; + } + + TCHAR* szString = LabelCheck(szQuote, ANSIToTCHAR(bii.szName, NULL, 0)); + if (szString && szEnd) { + GameInp[nInput].Macro.pVal[i] = bii.pVal; + GameInp[nInput].Macro.nInput[i] = j; + + GameInp[nInput].Macro.nVal[i] = (UINT8)_tcstol(szEnd, &szValue, 0); + + nFound++; + + break; + } + } + } + + if (nFound) { + if (GameInp[nInput].Macro.pVal[nFound - 1]) { + GameInp[nInput].nInput = GIT_MACRO_CUSTOM; + GameInp[nInput].Macro.nMode = nMode; + if (bCreateNew) { + nMacroCount++; + } + return 0; + } + } + } + + return 1; +} + +INT32 GameInputAutoIni(INT32 nPlayer, TCHAR* lpszFile, bool bOverWrite) +{ + TCHAR szLine[1024]; + INT32 nFileVersion = 0; + UINT32 i; + + nAnalogSpeed = 0x0100; + + FILE* h = _tfopen(lpszFile, _T("rt")); + if (h == NULL) { + return 1; + } + + // Go through each line of the config file and process inputs + while (_fgetts(szLine, sizeof(szLine), h)) { + TCHAR* szValue; + INT32 nLen = _tcslen(szLine); + + // Get rid of the linefeed at the end + if (szLine[nLen - 1] == 10) { + szLine[nLen - 1] = 0; + nLen--; + } + + szValue = LabelCheck(szLine, _T("version")); + if (szValue) { + nFileVersion = _tcstol(szValue, NULL, 0); + } + szValue = LabelCheck(szLine, _T("analog")); + if (szValue) { + nAnalogSpeed = _tcstol(szValue, NULL, 0); + } + + if (nConfigMinVersion <= nFileVersion && nFileVersion <= nBurnVer) { + szValue = LabelCheck(szLine, _T("input")); + if (szValue) { + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + if (QuoteRead(&szQuote, &szEnd, szValue)) { + continue; + } + + if ((szQuote[0] == _T('p') || szQuote[0] == _T('P')) && szQuote[1] >= _T('1') && szQuote[1] <= _T('0') + nMaxPlayers && szQuote[2] == _T(' ')) { + if (szQuote[1] != _T('1') + nPlayer) { + continue; + } + } else { + if (nPlayer != 0) { + continue; + } + } + + // Find which input number this refers to + i = InputNameToNum(szQuote); + if (i == ~0U) { + i = InputInfoToNum(szQuote); + if (i == ~0U) { + continue; + } + } + + if (GameInp[i].nInput == 0 || bOverWrite) { // Undefined - assign mapping + StringToInp(GameInp + i, szEnd); + } + } + + szValue = LabelCheck(szLine, _T("macro")); + if (szValue) { + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + if (QuoteRead(&szQuote, &szEnd, szValue)) { + continue; + } + + i = MacroNameToNum(szQuote); + if (i != ~0U) { + i += nGameInpCount; + if (GameInp[i].Macro.nMode == 0 || bOverWrite) { // Undefined - assign mapping + StringToMacro(GameInp + i, szEnd); + } + } + } + + szValue = LabelCheck(szLine, _T("custom")); + if (szValue) { + AddCustomMacro(szValue, bOverWrite); + } + } + } + + fclose(h); + + return 0; +} + +INT32 ConfigGameLoadHardwareDefaults() +{ + TCHAR *szDefaultCpsFile = _T("config\\presets\\cps.ini"); + TCHAR *szDefaultNeogeoFile = _T("config\\presets\\neogeo.ini"); + TCHAR *szDefaultPgmFile = _T("config\\presets\\pgm.ini"); + TCHAR *szFileName = _T(""); + INT32 nApplyHardwareDefaults = 0; + + INT32 nHardwareFlag = (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK); + + if (nHardwareFlag == HARDWARE_CAPCOM_CPS1 || nHardwareFlag == HARDWARE_CAPCOM_CPS1_QSOUND || nHardwareFlag == HARDWARE_CAPCOM_CPS1_GENERIC || nHardwareFlag == HARDWARE_CAPCOM_CPSCHANGER || nHardwareFlag == HARDWARE_CAPCOM_CPS2 || nHardwareFlag == HARDWARE_CAPCOM_CPS3) { + szFileName = szDefaultCpsFile; + nApplyHardwareDefaults = 1; + } + + if (nHardwareFlag == HARDWARE_SNK_NEOGEO) { + szFileName = szDefaultNeogeoFile; + nApplyHardwareDefaults = 1; + } + + if (nHardwareFlag == HARDWARE_IGS_PGM) { + szFileName = szDefaultPgmFile; + nApplyHardwareDefaults = 1; + } + + if (nApplyHardwareDefaults) { + for (INT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) { + GameInputAutoIni(nPlayer, szFileName, true); + } + } + + return 0; +} + +// Auto-configure any undefined inputs to defaults +INT32 GameInpDefault() +{ + struct GameInp* pgi; + struct BurnInputInfo bii; + UINT32 i; + + for (INT32 nPlayer = 0; nPlayer < nMaxPlayers; nPlayer++) { + + if ((nPlayerDefaultControls[nPlayer] & 0x0F) != 0x0F) { + continue; + } + + GameInputAutoIni(nPlayer, szPlayerDefaultIni[nPlayer], false); + } + + // Fill all inputs still undefined + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + if (pgi->nInput) { // Already defined - leave it alone + continue; + } + + // Get the extra info about the input + bii.szInfo = NULL; + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal == NULL) { + continue; + } + if (bii.szInfo == NULL) { + bii.szInfo = ""; + } + + // Dip switches - set to constant + if (bii.nType & BIT_GROUP_CONSTANT) { + pgi->nInput = GIT_CONSTANT; + continue; + } + + GameInpAutoOne(pgi, bii.szInfo); + } + + // Fill in macros still undefined + for (i = 0; i < nMacroCount; i++, pgi++) { + if (pgi->nInput != GIT_MACRO_AUTO || pgi->Macro.nMode) { // Already defined - leave it alone + continue; + } + + GameInpAutoOne(pgi, pgi->Macro.szName); + } + + return 0; +} + +// --------------------------------------------------------------------------- +// Write all the GameInps out to config file 'h' + +INT32 GameInpWrite(FILE* h) +{ + // Write input types + for (UINT32 i = 0; i < nGameInpCount; i++) { + TCHAR* szName = NULL; + INT32 nPad = 0; + szName = InputNumToName(i); + _ftprintf(h, _T("input \"%s\" "), szName); + nPad = 16 - _tcslen(szName); + for (INT32 j = 0; j < nPad; j++) { + _ftprintf(h, _T(" ")); + } + _ftprintf(h, _T("%s\n"), InpToString(GameInp + i)); + } + + _ftprintf(h, _T("\n")); + + struct GameInp* pgi = GameInp + nGameInpCount; + for (UINT32 i = 0; i < nMacroCount; i++, pgi++) { + INT32 nPad = 0; + + if (pgi->nInput & GIT_GROUP_MACRO) { + switch (pgi->nInput) { + case GIT_MACRO_AUTO: // Auto-assigned macros + _ftprintf(h, _T("macro \"%hs\" "), pgi->Macro.szName); + break; + case GIT_MACRO_CUSTOM: // Custom macros + _ftprintf(h, _T("custom \"%hs\" "), pgi->Macro.szName); + break; + default: // Unknown -- ignore + continue; + } + + nPad = 16 - strlen(pgi->Macro.szName); + for (INT32 j = 0; j < nPad; j++) { + _ftprintf(h, _T(" ")); + } + _ftprintf(h, _T("%s\n"), InpMacroToString(pgi)); + } + } + + return 0; +} + +// --------------------------------------------------------------------------- + +// Read a GameInp in +INT32 GameInpRead(TCHAR* szVal, bool bOverWrite) +{ + INT32 nRet; + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + UINT32 i = 0; + + nRet = QuoteRead(&szQuote, &szEnd, szVal); + if (nRet) { + return 1; + } + + // Find which input number this refers to + i = InputNameToNum(szQuote); + if (i == ~0U) { + return 1; + } + + if (bOverWrite || GameInp[i].nInput == 0) { + // Parse the input description into the GameInp structure + StringToInp(GameInp + i, szEnd); + } + + return 0; +} + +INT32 GameInpMacroRead(TCHAR* szVal, bool bOverWrite) +{ + INT32 nRet; + TCHAR* szQuote = NULL; + TCHAR* szEnd = NULL; + UINT32 i = 0; + + nRet = QuoteRead(&szQuote, &szEnd, szVal); + if (nRet) { + return 1; + } + + i = MacroNameToNum(szQuote); + if (i != ~0U) { + i += nGameInpCount; + if (GameInp[i].Macro.nMode == 0 || bOverWrite) { + StringToMacro(GameInp + i, szEnd); + } + } + + return 0; +} + +INT32 GameInpCustomRead(TCHAR* szVal, bool bOverWrite) +{ + return AddCustomMacro(szVal, bOverWrite); +} + diff --git a/src/burner/image.cpp b/src/burner/image.cpp new file mode 100644 index 00000000..71be1689 --- /dev/null +++ b/src/burner/image.cpp @@ -0,0 +1,524 @@ +#include "burner.h" +#include "png.h" + +#define PNG_SIG_CHECK_BYTES (8) + +void img_free(IMAGE* img) +{ + free(img->rowptr); + img->rowptr = NULL; + if (img->flags & IMG_FREE) { + if (img->bmpbits) { + free(img->bmpbits); + img->bmpbits = NULL; + } + } +} + +INT32 img_alloc(IMAGE* img) +{ + img->flags = 0; + + img->rowbytes = ((DWORD)img->width * 24 + 31) / 32 * 4; + img->imgbytes = img->rowbytes * img->height; + img->rowptr = (BYTE**)malloc((size_t)img->height * sizeof(BYTE*)); + + if (img->bmpbits == NULL) { + img->flags |= IMG_FREE; + img->bmpbits = (BYTE*)malloc((size_t)img->imgbytes); + } + + if (img->rowptr == NULL || img->bmpbits == NULL) { + img_free(img); + return 1; + } + + for (UINT32 y = 0; y < img->height; y++) { + img->rowptr[img->height - y - 1] = img->bmpbits + y * img->rowbytes; + } + + return 0; +} + +// Interpolate using a Catmull-Rom spline +static inline double interpolate(const double f, const double* c) +{ + return 0.5 * (( 2.0 * c[1] ) + + ( -c[0] + c[2] ) * f + + (2.0 * c[0] - 5.0 * c[1] + 4.0 * c[2] - c[3]) * (f * f) + + ( -c[0] + 3.0 * c[1] - 3.0 * c[2] + c[3]) * (f * f * f)); +} + +static inline double interpolatePixelH(const double f, const INT32 x, const UINT8* row, const INT32 width) +{ + double c[4]; + + c[0] = x >= 1 ? row[(x - 1) * 3] : row[0 ]; + c[1] = row[ x * 3]; + c[2] = x < (width - 1) ? row[(x + 1) * 3] : row[width - 1]; + c[3] = x < (width - 2) ? row[(x + 2) * 3] : row[width - 1]; + + return interpolate(f, c); +} + +static void interpolateRowH(const IMAGE* img, const INT32 y, double* row, const INT32 width) +{ + for (INT32 x = 0, x2; x < width; x++) { + + double f = (double)x * img->width / width; + x2 = (INT32)f; f -= x2; + + row[x * 3 + 0] = interpolatePixelH(f, x2, img->rowptr[y] + 0, img->width); + row[x * 3 + 1] = interpolatePixelH(f, x2, img->rowptr[y] + 1, img->width); + row[x * 3 + 2] = interpolatePixelH(f, x2, img->rowptr[y] + 2, img->width); + } +} + +static inline void interpolateRowV(const double f, const INT32 y, double** row, const IMAGE* img) +{ + double c[5]; + + for (UINT32 x = 0; x < img->width * 3; x++) { + + c[0] = row[0][x]; + c[1] = row[1][x]; + c[2] = row[2][x]; + c[3] = row[3][x]; + + c[4] = interpolate(f, c); + + if (c[4] < 0.0) c[4] = 0.0; else if (c[4] > 255.0) c[4] = 255.0; + + img->rowptr[y][x] = (UINT8)c[4]; + } +} + +// Resize the image to the required size using area averaging +static INT32 img_process(IMAGE* img, UINT32 width, UINT32 height, INT32 preset, bool swapRB) +{ + static struct { double gamma; double sharpness; INT32 min; INT32 max; } presetdata[] = { + { 1.000, 0.000, 0x000000, 0xFFFFFF }, // 0 no effects + { 1.000, 1.000, 0x000000, 0xFFFFFF }, // 1 normal sharpening + { 1.000, 1.250, 0x000000, 0xFFFFFF }, // 2 preview 1 + { 1.250, 1.750, 0x000000, 0xFFFFFF }, // 3 preview 2 + { 1.000, 0.750, 0x000000, 0xFFFFFF }, // 4 preview 3 + { 1.125, 1.500, 0x000000, 0xFFFFFF }, // 5 preview 4 + { 1.000, 1.000, 0x000000, 0xFFFFFF }, // 6 marquee dim 1 + { 1.250, 1.000, 0x202020, 0xFFFFFF }, // 7 marquee light 1 + { 1.250, 1.000, 0x000000, 0xEFEFEF }, // 8 marquee dim 2 + { 0.750, 1.750, 0x202020, 0xFFFFFF }, // 9 marquee light 2 + }; + + IMAGE sized_img; + + double ratio = (double)(height * width) / (img->height * img->width); + + { + double LUT[256]; + + INT32 rdest = 0, gdest = 1, bdest = 2; + if (swapRB) { + rdest = 2, gdest = 1, bdest = 0; + } + + // Compute a look-up table for gamma correction + + double min = (presetdata[preset].min & 255); + double rng = ((presetdata[preset].max & 255) - (presetdata[preset].min & 255)); + + for (INT32 i = 0; i < 256; i++) { + + LUT[i] = min + rng * pow((i / 255.0), presetdata[preset].gamma); + } + + // Apply gamma + for (UINT32 y = 0; y < img->height; y++) { + for (UINT32 x = 0; x < img->width; x++) { + UINT8 r = (UINT8)LUT[img->rowptr[y][x * 3 + 0]]; + UINT8 g = (UINT8)LUT[img->rowptr[y][x * 3 + 1]]; + UINT8 b = (UINT8)LUT[img->rowptr[y][x * 3 + 2]]; + + img->rowptr[y][x * 3 + rdest] = r; + img->rowptr[y][x * 3 + gdest] = g; + img->rowptr[y][x * 3 + bdest] = b; + } + } + } + + if (img->height == height && img->width == width) { + + // We don't need to resize the image + + return 0; + } + + memset(&sized_img, 0, sizeof(IMAGE)); + sized_img.width = width; + sized_img.height = height; + img_alloc(&sized_img); + + if (ratio >= 1.0) { + + double* row[4]; + + // Enlarge the image using bi-cubic filtering + + for (INT32 i = 0; i < 4; i++) { + row[i] = (double*)malloc(width * 3 * sizeof(double)); + } + + interpolateRowH(img, 0, row[0], width); + interpolateRowH(img, 0, row[1], width); + interpolateRowH(img, 1, row[2], width); + interpolateRowH(img, 2, row[3], width); + + for (UINT32 y = 0, ylast = 0, y2 = 0; y < height; ylast = y2, y++) { + double f = (double)y * img->height / height; + + y2 = (UINT32)f; f -= y2; + + if (y2 > ylast) { + double* r = row[0]; + row[0] = row[1]; + row[1] = row[2]; + row[2] = row[3]; + row[3] = r; + + interpolateRowH(img, (y2 + 2) < img->height ? y2 + 2 : img->height - 1, row[3], width); + } + + interpolateRowV(f, y, row, &sized_img); + } + + for (INT32 i = 0; i < 4; i++) { + if (row[i]) { + free(row[i]); + row[i] = NULL; + } + } + + img_free(img); + + memcpy(img, &sized_img, sizeof(IMAGE)); + + return 0; + } + + // Shrink the image using area averaging and apply gamma + + for (UINT32 y = 0; y < sized_img.height; y++) { + for (UINT32 x = 0; x < sized_img.width; x++) { + + double r0, b0, g0, r1, g1, b1, xf, yf; + UINT32 x1, y1; + + r0 = g0 = b0 = 0.0; + + y1 = img->height * y / sized_img.height; + yf = (double)img->height * y / sized_img.height - y1; + + x1 = img->width * x / sized_img.width; + xf = (double)img->width * x / sized_img.width - x1; + r1 = (double)img->rowptr[y1][x1 * 3 + 0] * (1.0 - xf); + g1 = (double)img->rowptr[y1][x1 * 3 + 1] * (1.0 - xf); + b1 = (double)img->rowptr[y1][x1 * 3 + 2] * (1.0 - xf); + + for (x1 = x1 + 1; x1 < img->width * (x + 1) / sized_img.width; x1++) { + r1 += (double)img->rowptr[y1][x1 * 3 + 0]; + g1 += (double)img->rowptr[y1][x1 * 3 + 1]; + b1 += (double)img->rowptr[y1][x1 * 3 + 2]; + } + + if (x1 < img->width) { + xf = (double)img->width * (x + 1) / sized_img.width - x1; + r1 += (double)img->rowptr[y1][x1 * 3 + 0] * xf; + g1 += (double)img->rowptr[y1][x1 * 3 + 1] * xf; + b1 += (double)img->rowptr[y1][x1 * 3 + 2] * xf; + } + + r0 += r1 * (1.0 - yf); + g0 += g1 * (1.0 - yf); + b0 += b1 * (1.0 - yf); + + for (y1 = y1 + 1; y1 < img->height * (y + 1) / sized_img.height; y1++) { + x1 = img->width * x / sized_img.width; + xf = (double)img->width * x / sized_img.width - x1; + + r1 = (double)img->rowptr[y1][x1 * 3 + 0] * (1.0 - xf); + g1 = (double)img->rowptr[y1][x1 * 3 + 1] * (1.0 - xf); + b1 = (double)img->rowptr[y1][x1 * 3 + 2] * (1.0 - xf); + + for (x1 = x1 + 1; x1 < img->width * (x + 1) / sized_img.width; x1++) { + r1 += (double)img->rowptr[y1][x1 * 3 + 0]; + g1 += (double)img->rowptr[y1][x1 * 3 + 1]; + b1 += (double)img->rowptr[y1][x1 * 3 + 2]; + } + + if (x1 < img->width) { + xf = (double)img->width * (x + 1) / sized_img.width - x1; + r1 += (double)img->rowptr[y1][x1 * 3 + 0] * xf; + g1 += (double)img->rowptr[y1][x1 * 3 + 1] * xf; + b1 += (double)img->rowptr[y1][x1 * 3 + 2] * xf; + } + + r0 += r1; + g0 += g1; + b0 += b1; + } + + if (y1 < img->height) { + yf = (double)img->height * (y + 1) / sized_img.height - y1; + + x1 = img->width * x / sized_img.width; + xf = (double)img->width * x / sized_img.width - x1; + r1 = (double)img->rowptr[y1][x1 * 3 + 0] * (1.0 - xf); + g1 = (double)img->rowptr[y1][x1 * 3 + 1] * (1.0 - xf); + b1 = (double)img->rowptr[y1][x1 * 3 + 2] * (1.0 - xf); + + for (x1 = x1 + 1; x1 < img->width * (x + 1) / sized_img.width; x1++) { + r1 += (double)img->rowptr[y1][x1 * 3 + 0]; + g1 += (double)img->rowptr[y1][x1 * 3 + 1]; + b1 += (double)img->rowptr[y1][x1 * 3 + 2]; + } + + if (x1 < img->width) { + xf = (double)img->width * (x + 1) / sized_img.width - x1; + r1 += (double)img->rowptr[y1][x1 * 3 + 0] * xf; + g1 += (double)img->rowptr[y1][x1 * 3 + 1] * xf; + b1 += (double)img->rowptr[y1][x1 * 3 + 2] * xf; + } + + r0 += r1 * yf; + g0 += g1 * yf; + b0 += b1 * yf; + } + + sized_img.rowptr[y][x * 3 + 0] = (UINT8)(r0 * ratio);// + 0.5; + sized_img.rowptr[y][x * 3 + 1] = (UINT8)(g0 * ratio);// + 0.5; + sized_img.rowptr[y][x * 3 + 2] = (UINT8)(b0 * ratio);// + 0.5; + } + } + + img_free(img); + +// if (!presetdata[preset].sharpness || ratio >= 1.0) { + memcpy(img, &sized_img, sizeof(IMAGE)); + + return 0; +// } + + // Sharpen the image using an unsharp mask + +/* IMAGE sharp_img; + + memset(&sharp_img, 0, sizeof(IMAGE)); + sharp_img.width = width; + sharp_img.height = height; + img_alloc(&sharp_img); + + // Create a convolution matrix for a gaussian blur + + double matrix[9][9]; + + // Control the radius of the blur based on sharpness and image reduction + double b = presetdata[preset].sharpness / (8.0 * ratio); + +// dprintf(_T(" %3ix%3i -> %3ix%3i %0.4lf %0.4lf\n"), img->width, img->height, sized_img.width, sized_img.height, ratio, b); + if (b > 1.5) { b = 1.5; } + b = pow(b, 2.0); + + for (INT32 x = -4; x < 5; x++) { + for (INT32 y = -4; y < 5; y++) { + + double c = sqrt(double(x * x + y * y)); + + matrix[y + 4][x + 4] = 1.0 / exp(-c * -c / b); + } + } + + for (INT32 y = 0; y < sized_img.height; y++) { + for (INT32 x = 0; x < sized_img.width; x++) { + + double r, g, b, m; + + r = g = b = m = 0.0; + + // Convolve the image + for (INT32 y1 = -4; y1 < 5; y1++) { + if (y + y1 > 0 && y + y1 < sized_img.height) { + for (INT32 x1 = -4; x1 < 5; x1++) { + if (x + x1 > 0 && x + x1 < sized_img.width) { + r += matrix[y1 + 4][x1 + 4] * sized_img.rowptr[y + y1][(x + x1) * 3 + 0]; + g += matrix[y1 + 4][x1 + 4] * sized_img.rowptr[y + y1][(x + x1) * 3 + 1]; + b += matrix[y1 + 4][x1 + 4] * sized_img.rowptr[y + y1][(x + x1) * 3 + 2]; + m += abs(matrix[y1 + 4][x1 + 4]); + } + } + } + } + + // Normalise the image + r /= m; + g /= m; + b /= m; + + // create the mask by subtracting the blurred image from the original + r = presetdata[preset].sharpness * ((double)sized_img.rowptr[y][x * 3 + 0] - r); + g = presetdata[preset].sharpness * ((double)sized_img.rowptr[y][x * 3 + 1] - g); + b = presetdata[preset].sharpness * ((double)sized_img.rowptr[y][x * 3 + 2] - b); + + // Implement a treshold control, rolloff beneath the treshold based on image reduction + + double treshold = 32.0 / presetdata[preset].sharpness; + + if (abs(r) < treshold && abs(g) < treshold && abs(b) < treshold) { + r /= 1.0 + ((treshold - abs(r)) * ratio); + g /= 1.0 + ((treshold - abs(g)) * ratio); + b /= 1.0 + ((treshold - abs(b)) * ratio); + } + + // Add the mask back to the original + r = (double)sized_img.rowptr[y][x * 3 + 0] + r; + g = (double)sized_img.rowptr[y][x * 3 + 1] + g; + b = (double)sized_img.rowptr[y][x * 3 + 2] + b; + + // Clamp RGB values + if (r < 0) { r = 0; } if (r > 255) { r = 255; } + if (g < 0) { g = 0; } if (g > 255) { g = 255; } + if (b < 0) { b = 0; } if (b > 255) { b = 255; } + + // Store image + sharp_img.rowptr[y][x * 3 + 0] = r; + sharp_img.rowptr[y][x * 3 + 1] = g; + sharp_img.rowptr[y][x * 3 + 2] = b; + } + }*/ + + img_free(&sized_img); + +// memcpy(img, &sharp_img, sizeof(IMAGE)); + + return 0; +} + +bool PNGIsImage(FILE* fp) +{ + if (fp) { + UINT8 pngsig[PNG_SIG_CHECK_BYTES]; + + fseek(fp, 0, SEEK_SET); + fread(pngsig, 1, PNG_SIG_CHECK_BYTES, fp); + fseek(fp, 0, SEEK_SET); + + if (png_sig_cmp(pngsig, 0, PNG_SIG_CHECK_BYTES) == 0) { + return true; + } + } + + return false; +} + +INT32 PNGLoad(IMAGE* img, FILE* fp, INT32 nPreset) +{ + IMAGE temp_img; + png_uint_32 width, height; + INT32 bit_depth, color_type; + + if (fp) { + // check signature + UINT8 pngsig[PNG_SIG_CHECK_BYTES]; + fread(pngsig, 1, PNG_SIG_CHECK_BYTES, fp); + if (png_sig_cmp(pngsig, 0, PNG_SIG_CHECK_BYTES)) { + return 1; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + return 1; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); + return 1; + } + + memset(&temp_img, 0, sizeof(IMAGE)); + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, PNG_SIG_CHECK_BYTES); + png_read_info(png_ptr, info_ptr); + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + return 1; + } + + // Instruct libpng to convert the image to 24-bit RGB format + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + } + if (color_type & PNG_COLOR_MASK_ALPHA) { + png_set_strip_alpha(png_ptr); + } + + temp_img.width = width; + temp_img.height = height; + + // Initialize our img structure + if (img_alloc(&temp_img)) { + //longjmp(png_ptr->jmpbuf, 1); + png_jmpbuf(png_ptr); + } + + // If bad things happen in libpng we need to do img_free(&temp_img) as well + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + img_free(&temp_img); + return 1; + } + + // Read the .PNG image + png_set_bgr(png_ptr); + png_read_update_info(png_ptr, info_ptr); + png_read_image(png_ptr, temp_img.rowptr); + png_read_end(png_ptr, (png_infop)NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + } else { + +#ifdef WIN32 + // Find resource + HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(BMP_SPLASH), RT_BITMAP); + HGLOBAL hglobal = LoadResource(NULL, (HRSRC)hrsrc); + BYTE* pResourceData = (BYTE*)LockResource(hglobal); + + BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)LockResource(hglobal); + + // Allocate a new image + memset(&temp_img, 0, sizeof(IMAGE)); + temp_img.width = pbmih->biWidth; + temp_img.height = pbmih->biHeight; + temp_img.bmpbits = pResourceData + pbmih->biSize; + img_alloc(&temp_img); + +#else + return 1; +#endif + + } + + if (img_process(&temp_img, img->width ? img->width : temp_img.width, img->height ? img->height : temp_img.height, nPreset, false)) { + img_free(&temp_img); + return 1; + } + + memcpy(img, &temp_img, sizeof(IMAGE)); + + return 0; +} diff --git a/src/burner/misc.cpp b/src/burner/misc.cpp new file mode 100644 index 00000000..fc527b26 --- /dev/null +++ b/src/burner/misc.cpp @@ -0,0 +1,431 @@ +// Misc functions module +#include +#include "burner.h" + +// --------------------------------------------------------------------------- +// Software gamma + +INT32 bDoGamma = 0; +INT32 bHardwareGammaOnly = 1; +double nGamma = 1.25; +const INT32 nMaxRGB = 255; + +static UINT8 GammaLUT[256]; + +void ComputeGammaLUT() +{ + for (INT32 i = 0; i < 256; i++) { + GammaLUT[i] = (UINT8)((double)nMaxRGB * pow((i / 255.0), nGamma)); + } +} + +// Standard callbacks for 16/24/32 bit color: +static UINT32 __cdecl HighCol15(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + t =(r<<7)&0x7c00; // 0rrr rr00 0000 0000 + t|=(g<<2)&0x03e0; // 0000 00gg ggg0 0000 + t|=(b>>3)&0x001f; // 0000 0000 000b bbbb + return t; +} + +static UINT32 __cdecl HighCol16(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + t =(r<<8)&0xf800; // rrrr r000 0000 0000 + t|=(g<<3)&0x07e0; // 0000 0ggg ggg0 0000 + t|=(b>>3)&0x001f; // 0000 0000 000b bbbb + return t; +} + +// 24-bit/32-bit +static UINT32 __cdecl HighCol24(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + t =(r<<16)&0xff0000; + t|=(g<<8 )&0x00ff00; + t|=(b )&0x0000ff; + + return t; +} + +static UINT32 __cdecl HighCol15Gamma(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + t = (GammaLUT[r] << 7) & 0x7C00; // 0rrr rr00 0000 0000 + t |= (GammaLUT[g] << 2) & 0x03E0; // 0000 00gg ggg0 0000 + t |= (GammaLUT[b] >> 3) & 0x001F; // 0000 0000 000b bbbb + return t; +} + +static UINT32 __cdecl HighCol16Gamma(INT32 r, INT32 g ,INT32 b, INT32 /* i */) +{ + UINT32 t; + t = (GammaLUT[r] << 8) & 0xF800; // rrrr r000 0000 0000 + t |= (GammaLUT[g] << 3) & 0x07E0; // 0000 0ggg ggg0 0000 + t |= (GammaLUT[b] >> 3) & 0x001F; // 0000 0000 000b bbbb + return t; +} + +// 24-bit/32-bit +static UINT32 __cdecl HighCol24Gamma(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + t = (GammaLUT[r] << 16); + t |= (GammaLUT[g] << 8); + t |= GammaLUT[b]; + + return t; +} + +INT32 SetBurnHighCol(INT32 nDepth) +{ + VidRecalcPal(); + + if (bDoGamma && ((nVidFullscreen && !bVidUseHardwareGamma) || (!nVidFullscreen && !bHardwareGammaOnly))) { + if (nDepth == 15) { + VidHighCol = HighCol15Gamma; + } + if (nDepth == 16) { + VidHighCol = HighCol16Gamma; + } + if (nDepth > 16) { + VidHighCol = HighCol24Gamma; + } + } else { + if (nDepth == 15) { + VidHighCol = HighCol15; + } + if (nDepth == 16) { + VidHighCol = HighCol16; + } + if (nDepth > 16) { + VidHighCol = HighCol24; + } + } + if ((bDrvOkay && !(BurnDrvGetFlags() & BDF_16BIT_ONLY)) || nDepth <= 16) { + BurnHighCol = VidHighCol; + } + + return 0; +} + +// --------------------------------------------------------------------------- + +char* DecorateGameName(UINT32 nBurnDrv) +{ + static char szDecoratedName[256]; + UINT32 nOldBurnDrv = nBurnDrvActive; + + nBurnDrvActive = nBurnDrv; + + const char* s1 = ""; + const char* s2 = ""; + const char* s3 = ""; + const char* s4 = ""; + const char* s5 = ""; + const char* s6 = ""; + const char* s7 = ""; + const char* s8 = ""; + const char* s9 = ""; + const char* s10 = ""; + const char* s11 = ""; + const char* s12 = ""; + const char* s13 = ""; + const char* s14 = ""; + + s1 = BurnDrvGetTextA(DRV_FULLNAME); + if ((BurnDrvGetFlags() & BDF_DEMO) || (BurnDrvGetFlags() & BDF_HACK) || (BurnDrvGetFlags() & BDF_HOMEBREW) || (BurnDrvGetFlags() & BDF_PROTOTYPE) || (BurnDrvGetFlags() & BDF_BOOTLEG) || (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0)) { + s2 = " ["; + if (BurnDrvGetFlags() & BDF_DEMO) { + s3 = "Demo"; + if ((BurnDrvGetFlags() & BDF_HACK) || (BurnDrvGetFlags() & BDF_HOMEBREW) || (BurnDrvGetFlags() & BDF_PROTOTYPE) || (BurnDrvGetFlags() & BDF_BOOTLEG) || (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0)) { + s4 = ", "; + } + } + if (BurnDrvGetFlags() & BDF_HACK) { + s5 = "Hack"; + if ((BurnDrvGetFlags() & BDF_HOMEBREW) || (BurnDrvGetFlags() & BDF_PROTOTYPE) || (BurnDrvGetFlags() & BDF_BOOTLEG) || (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0)) { + s6 = ", "; + } + } + if (BurnDrvGetFlags() & BDF_HOMEBREW) { + s7 = "Homebrew"; + if ((BurnDrvGetFlags() & BDF_PROTOTYPE) || (BurnDrvGetFlags() & BDF_BOOTLEG) || (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0)) { + s8 = ", "; + } + } + if (BurnDrvGetFlags() & BDF_PROTOTYPE) { + s9 = "Prototype"; + if ((BurnDrvGetFlags() & BDF_BOOTLEG) || (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0)) { + s10 = ", "; + } + } + if (BurnDrvGetFlags() & BDF_BOOTLEG) { + s11 = "Bootleg"; + if (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0) { + s12 = ", "; + } + } + if (BurnDrvGetTextA(DRV_COMMENT) && strlen(BurnDrvGetTextA(DRV_COMMENT)) > 0) { + s13 = BurnDrvGetTextA(DRV_COMMENT); + } + s14 = "]"; + } + + sprintf(szDecoratedName, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14); + + nBurnDrvActive = nOldBurnDrv; + return szDecoratedName; +} + +TCHAR* DecorateGenreInfo() +{ + INT32 nGenre = BurnDrvGetGenreFlags(); + INT32 nFamily = BurnDrvGetFamilyFlags(); + + static TCHAR szDecoratedGenre[256]; + TCHAR szFamily[256]; + + _stprintf(szDecoratedGenre, _T("")); + _stprintf(szFamily, _T("")); + + if (nGenre) { + if (nGenre & GBF_HORSHOOT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_HORSHOOT, true)); + } + + if (nGenre & GBF_VERSHOOT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_VERSHOOT, true)); + } + + if (nGenre & GBF_SCRFIGHT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_SCRFIGHT, true)); + } + + if (nGenre & GBF_VSFIGHT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_VSFIGHT, true)); + } + + if (nGenre & GBF_BIOS) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_BIOS, true)); + } + + if (nGenre & GBF_BREAKOUT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_BREAKOUT, true)); + } + + if (nGenre & GBF_CASINO) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_CASINO, true)); + } + + if (nGenre & GBF_BALLPADDLE) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_BALLPADDLE, true)); + } + + if (nGenre & GBF_MAZE) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_MAZE, true)); + } + + if (nGenre & GBF_MINIGAMES) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_MINIGAMES, true)); + } + + if (nGenre & GBF_PINBALL) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_PINBALL, true)); + } + + if (nGenre & GBF_PLATFORM) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_PLATFORM, true)); + } + + if (nGenre & GBF_PUZZLE) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_PUZZLE, true)); + } + + if (nGenre & GBF_QUIZ) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_QUIZ, true)); + } + + if (nGenre & GBF_SPORTSMISC) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_SPORTSMISC, true)); + } + + if (nGenre & GBF_SPORTSFOOTBALL) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_SPORTSFOOTBALL, true)); + } + + if (nGenre & GBF_MISC) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_MISC, true)); + } + + if (nGenre & GBF_MAHJONG) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_MAHJONG, true)); + } + + if (nGenre & GBF_RACING) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_RACING, true)); + } + + if (nGenre & GBF_SHOOT) { + _stprintf(szDecoratedGenre, _T("%s%s, "), szDecoratedGenre, FBALoadStringEx(hAppInst, IDS_GENRE_SHOOT, true)); + } + + szDecoratedGenre[_tcslen(szDecoratedGenre) - 2] = _T('\0'); + } + + if (nFamily) { + _stprintf(szFamily, _T(" (")); + + if (nFamily & FBF_MSLUG) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_MSLUG, true)); + } + + if (nFamily & FBF_SF) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_SF, true)); + } + + if (nFamily & FBF_KOF) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_KOF, true)); + } + + if (nFamily & FBF_DSTLK) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_DSTLK, true)); + } + + if (nFamily & FBF_FATFURY) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_FATFURY, true)); + } + + if (nFamily & FBF_SAMSHO) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_SAMSHO, true)); + } + + if (nFamily & FBF_19XX) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_19XX, true)); + } + + if (nFamily & FBF_SONICWI) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_SONICWI, true)); + } + + if (nFamily & FBF_PWRINST) { + _stprintf(szFamily, _T("%s%s, "), szFamily, FBALoadStringEx(hAppInst, IDS_FAMILY_PWRINST, true)); + } + + szFamily[_tcslen(szFamily) - 2] = _T(')'); + szFamily[_tcslen(szFamily) - 1] = _T('\0'); + } + + _stprintf(szDecoratedGenre, _T("%s%s"), szDecoratedGenre, szFamily); + + return szDecoratedGenre; +} + +// --------------------------------------------------------------------------- +// config file parsing + +TCHAR* LabelCheck(TCHAR* s, TCHAR* pszLabel) +{ + INT32 nLen; + if (s == NULL) { + return NULL; + } + if (pszLabel == NULL) { + return NULL; + } + nLen = _tcslen(pszLabel); + + SKIP_WS(s); // Skip whitespace + + if (_tcsncmp(s, pszLabel, nLen)){ // Doesn't match + return NULL; + } + return s + nLen; +} + +INT32 QuoteRead(TCHAR** ppszQuote, TCHAR** ppszEnd, TCHAR* pszSrc) // Read a (quoted) string from szSrc and poINT32 to the end +{ + static TCHAR szQuote[QUOTE_MAX]; + TCHAR* s = pszSrc; + TCHAR* e; + + // Skip whitespace + SKIP_WS(s); + + e = s; + + if (*s == _T('\"')) { // Quoted string + s++; + e++; + // Find end quote + FIND_QT(e); + _tcsncpy(szQuote, s, e - s); + // Zero-terminate + szQuote[e - s] = _T('\0'); + e++; + } else { // Non-quoted string + // Find whitespace + FIND_WS(e); + _tcsncpy(szQuote, s, e - s); + // Zero-terminate + szQuote[e - s] = _T('\0'); + } + + if (ppszQuote) { + *ppszQuote = szQuote; + } + if (ppszEnd) { + *ppszEnd = e; + } + + return 0; +} + +TCHAR* ExtractFilename(TCHAR* fullname) +{ + TCHAR* filename = fullname + _tcslen(fullname); + + do { + filename--; + } while (filename >= fullname && *filename != _T('\\') && *filename != _T('/') && *filename != _T(':')); + + return filename; +} + +TCHAR* DriverToName(UINT32 nDrv) +{ + TCHAR* szName = NULL; + UINT32 nOldDrv; + + if (nDrv >= nBurnDrvCount) { + return NULL; + } + + nOldDrv = nBurnDrvActive; + nBurnDrvActive = nDrv; + szName = BurnDrvGetText(DRV_NAME); + nBurnDrvActive = nOldDrv; + + return szName; +} + +UINT32 NameToDriver(TCHAR* szName) +{ + UINT32 nOldDrv = nBurnDrvActive; + UINT32 nDrv = 0; + + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + if (_tcscmp(szName, BurnDrvGetText(DRV_NAME)) == 0 && !(BurnDrvGetFlags() & BDF_BOARDROM)) { + break; + } + } + nDrv = nBurnDrvActive; + if (nDrv >= nBurnDrvCount) { + nDrv = ~0U; + } + + nBurnDrvActive = nOldDrv; + + return nDrv; +} diff --git a/src/burner/sshot.cpp b/src/burner/sshot.cpp new file mode 100644 index 00000000..4acb5d55 --- /dev/null +++ b/src/burner/sshot.cpp @@ -0,0 +1,237 @@ +#include "burner.h" + +#define SSHOT_NOERROR 0 +#define SSHOT_ERROR_BPP_NOTSUPPORTED 1 +#define SSHOT_LIBPNG_ERROR 2 +#define SSHOT_OTHER_ERROR 3 + +#define SSHOT_DIRECTORY "screenshots\\" + +static UINT8* pSShot = NULL; +static UINT8* pConvertedImage = NULL; +static png_bytep* pSShotImageRows = NULL; +static FILE* ff; + +INT32 MakeScreenShot() +{ + char szAuthor[256]; char szDescription[256]; char szCopyright[256]; char szSoftware[256]; char szSource[256]; + png_text text_ptr[8] = { { 0, 0, 0, 0, 0, 0, 0 }, }; + INT32 num_text = 8; + + time_t currentTime; + tm* tmTime; + png_time_struct png_time_now; + + char szSShotName[MAX_PATH]; + INT32 w, h; + + // do our PNG construct things + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + return SSHOT_LIBPNG_ERROR; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + + return SSHOT_LIBPNG_ERROR; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (pConvertedImage) { + free(pConvertedImage); + pConvertedImage = NULL; + } + + if (pSShotImageRows) { + free(pSShotImageRows); + pSShotImageRows = NULL; + } + + fclose(ff); + remove(szSShotName); + + return SSHOT_LIBPNG_ERROR; + } + + if (pVidImage == NULL) { + return SSHOT_OTHER_ERROR; + } + + if (nVidImageBPP < 2 || nVidImageBPP > 4) { + return SSHOT_ERROR_BPP_NOTSUPPORTED; + } + + BurnDrvGetVisibleSize(&w, &h); + + pSShot = pVidImage; + + // Convert the image to 32-bit + if (nVidImageBPP < 4) { + UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); + + if (nVidImageBPP == 2) { + for (INT32 i = 0; i < h * w; i++) { + UINT16 nColour = ((UINT16*)pSShot)[i]; + + // Red + *(pTemp + i * 4 + 0) = (UINT8)((nColour & 0x1F) << 3); + *(pTemp + i * 4 + 0) |= *(pTemp + 4 * i + 0) >> 5; + + if (nVidImageDepth == 15) { + // Green + *(pTemp + i * 4 + 1) = (UINT8)(((nColour >> 5) & 0x1F) << 3); + *(pTemp + i * 4 + 1) |= *(pTemp + i * 4 + 1) >> 5; + // Blue + *(pTemp + i * 4 + 2) = (UINT8)(((nColour >> 10)& 0x1F) << 3); + *(pTemp + i * 4 + 2) |= *(pTemp + i * 4 + 2) >> 5; + } + + if (nVidImageDepth == 16) { + // Green + *(pTemp + i * 4 + 1) = (UINT8)(((nColour >> 5) & 0x3F) << 2); + *(pTemp + i * 4 + 1) |= *(pTemp + i * 4 + 1) >> 6; + // Blue + *(pTemp + i * 4 + 2) = (UINT8)(((nColour >> 11) & 0x1F) << 3); + *(pTemp + i * 4 + 2) |= *(pTemp + i * 4 + 2) >> 5; + } + } + } else { + memset(pTemp, 0, w * h * sizeof(INT32)); + for (INT32 i = 0; i < h * w; i++) { + *(pTemp + i * 4 + 0) = *(pSShot + i * 3 + 0); + *(pTemp + i * 4 + 1) = *(pSShot + i * 3 + 1); + *(pTemp + i * 4 + 2) = *(pSShot + i * 3 + 2); + } + } + + pConvertedImage = pTemp; + + pSShot = pConvertedImage; + } + + // Rotate and flip the image + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); + + for (INT32 x = 0; x < h; x++) { + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + for (INT32 y = 0; y < w; y++) { + ((UINT32*)pTemp)[(w - y - 1) + x * w] = ((UINT32*)pSShot)[x + y * h]; + } + } else { + for (INT32 y = 0; y < w; y++) { + ((UINT32*)pTemp)[y + (h - x - 1) * w] = ((UINT32*)pSShot)[x + y * h]; + } + } + } + + if (pConvertedImage) { + free(pConvertedImage); + pConvertedImage = pTemp; + } + + pSShot = pConvertedImage; + } + else if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { // fixed rotation by regret + UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); + + for (INT32 y = h - 1; y >= 0; y--) { + for (INT32 x = w - 1; x >= 0; x--) { + ((UINT32*)pTemp)[(w - x - 1) + (h - y - 1) * w] = ((UINT32*)pSShot)[x + y * w]; + } + } + + if (pConvertedImage) { + free(pConvertedImage); + pConvertedImage = pTemp; + } + + pSShot = pConvertedImage; + } + + // Get the time + time(¤tTime); + tmTime = localtime(¤tTime); + png_convert_from_time_t(&png_time_now, currentTime); + + // construct our filename -> "romname-mm-dd-hms.png" + sprintf(szSShotName,"%s%s-%.2d-%.2d-%.2d%.2d%.2d.png", SSHOT_DIRECTORY, BurnDrvGetTextA(DRV_NAME), tmTime->tm_mon + 1, tmTime->tm_mday, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec); + + ff = fopen(szSShotName, "wb"); + if (ff == NULL) { + png_destroy_write_struct(&png_ptr, &info_ptr); + + if (pConvertedImage) { + free(pConvertedImage); + pConvertedImage = NULL; + } + + return SSHOT_OTHER_ERROR; + } + + // Fill the PNG text fields +#ifdef _UNICODE + sprintf(szAuthor, APP_TITLE " v%.20ls", szAppBurnVer); +#else + sprintf(szAuthor, APP_TITLE " v%.20s", szAppBurnVer); +#endif + sprintf(szDescription, "Screenshot of %s", DecorateGameName(nBurnDrvActive)); + sprintf(szCopyright, "%s %s", BurnDrvGetTextA(DRV_DATE), BurnDrvGetTextA(DRV_MANUFACTURER)); +#ifdef _UNICODE + sprintf(szSoftware, APP_TITLE " v%.20ls using LibPNG " PNG_LIBPNG_VER_STRING, szAppBurnVer); +#else + sprintf(szSoftware, APP_TITLE " v%.20s using LibPNG " PNG_LIBPNG_VER_STRING, szAppBurnVer); +#endif + sprintf(szSource, "%s video game hardware", BurnDrvGetTextA(DRV_SYSTEM)); + + text_ptr[0].key = "Title"; text_ptr[0].text = BurnDrvGetTextA(DRV_FULLNAME); + text_ptr[1].key = "Author"; text_ptr[1].text = szAuthor; + text_ptr[2].key = "Description"; text_ptr[2].text = szDescription; + text_ptr[3].key = "Copyright"; text_ptr[3].text = szCopyright; + text_ptr[4].key = "Creation Time"; text_ptr[4].text = (char*)png_convert_to_rfc1123(png_ptr, &png_time_now); + text_ptr[5].key = "Software"; text_ptr[5].text = szSoftware; + text_ptr[6].key = "Source"; text_ptr[6].text = szSource; + text_ptr[7].key = "Comment"; text_ptr[7].text = "This screenshot was created by running the game in an emulator; it might not accurately reflect the actual hardware the game was designed to run on."; + + for (INT32 i = 0; i < num_text; i++) { + text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE; + } + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + png_init_io(png_ptr, ff); + + png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + + png_set_bgr(png_ptr); + + pSShotImageRows = (png_bytep*)malloc(h * sizeof(png_bytep)); + for (INT32 y = 0; y < h; y++) { + pSShotImageRows[y] = pSShot + (y * w * sizeof(INT32)); + } + + png_write_image(png_ptr, pSShotImageRows); + png_write_end(png_ptr, info_ptr); + + if (pSShotImageRows) { + free(pSShotImageRows); + pSShotImageRows = NULL; + } + + fclose(ff); + + png_destroy_write_struct(&png_ptr, &info_ptr); + + if (pConvertedImage) { + free(pConvertedImage); + pConvertedImage = NULL; + } + + return SSHOT_NOERROR; +} diff --git a/src/burner/state.cpp b/src/burner/state.cpp new file mode 100644 index 00000000..bafe8b5f --- /dev/null +++ b/src/burner/state.cpp @@ -0,0 +1,317 @@ +// Driver Save State module +#include "burner.h" + +// If bAll=0 save/load all non-volatile ram to .fs +// If bAll=1 save/load all ram to .fs + +// ------------ State len -------------------- +static INT32 nTotalLen = 0; + +static INT32 __cdecl StateLenAcb(struct BurnArea* pba) +{ + nTotalLen += pba->nLen; + + return 0; +} + +static INT32 StateInfo(INT32* pnLen, INT32* pnMinVer, INT32 bAll) +{ + INT32 nMin = 0; + nTotalLen = 0; + BurnAcb = StateLenAcb; + + BurnAreaScan(ACB_NVRAM, &nMin); // Scan nvram + if (bAll) { + INT32 m; + BurnAreaScan(ACB_MEMCARD, &m); // Scan memory card + if (m > nMin) { // Up the minimum, if needed + nMin = m; + } + BurnAreaScan(ACB_VOLATILE, &m); // Scan volatile ram + if (m > nMin) { // Up the minimum, if needed + nMin = m; + } + } + *pnLen = nTotalLen; + *pnMinVer = nMin; + + return 0; +} + +// State load +INT32 BurnStateLoadEmbed(FILE* fp, INT32 nOffset, INT32 bAll, INT32 (*pLoadGame)()) +{ + const char* szHeader = "FS1 "; // Chunk identifier + + INT32 nLen = 0; + INT32 nMin = 0, nFileVer = 0, nFileMin = 0; + INT32 t1 = 0, t2 = 0; + char ReadHeader[4]; + char szForName[33]; + INT32 nChunkSize = 0; + UINT8 *Def = NULL; + INT32 nDefLen = 0; // Deflated version + INT32 nRet = 0; + + if (nOffset >= 0) { + fseek(fp, nOffset, SEEK_SET); + } else { + if (nOffset == -2) { + fseek(fp, 0, SEEK_END); + } else { + fseek(fp, 0, SEEK_CUR); + } + } + + memset(ReadHeader, 0, 4); + fread(ReadHeader, 1, 4, fp); // Read identifier + if (memcmp(ReadHeader, szHeader, 4)) { // Not the right file type + return -2; + } + + fread(&nChunkSize, 1, 4, fp); + if (nChunkSize <= 0x40) { // Not big enough + return -1; + } + + INT32 nChunkData = ftell(fp); + + fread(&nFileVer, 1, 4, fp); // Version of FB that this file was saved from + + fread(&t1, 1, 4, fp); // Min version of FB that NV data will work with + fread(&t2, 1, 4, fp); // Min version of FB that All data will work with + + if (bAll) { // Get the min version number which applies to us + nFileMin = t2; + } else { + nFileMin = t1; + } + + fread(&nDefLen, 1, 4, fp); // Get the size of the compressed data block + + memset(szForName, 0, sizeof(szForName)); + fread(szForName, 1, 32, fp); + + if (nBurnVer < nFileMin) { // Error - emulator is too old to load this state + return -5; + } + + // Check the game the savestate is for, and load it if needed. + { + bool bLoadGame = false; + + if (nBurnDrvActive < nBurnDrvCount) { + if (strcmp(szForName, BurnDrvGetTextA(DRV_NAME))) { // The save state is for the wrong game + bLoadGame = true; + } + } else { // No game loaded + bLoadGame = true; + } + + if (bLoadGame) { + UINT32 nCurrentGame = nBurnDrvActive; + UINT32 i; + for (i = 0; i < nBurnDrvCount; i++) { + nBurnDrvActive = i; + if (strcmp(szForName, BurnDrvGetTextA(DRV_NAME)) == 0) { + break; + } + } + if (i == nBurnDrvCount) { + nBurnDrvActive = nCurrentGame; + return -3; + } else { + if (pLoadGame == NULL) { + return -1; + } + if (pLoadGame()) { + return -1; + } + } + } + } + + StateInfo(&nLen, &nMin, bAll); + if (nLen <= 0) { // No memory to load + return -1; + } + + // Check if the save state is okay + if (nFileVer < nMin) { // Error - this state is too old and cannot be loaded. + return -4; + } + + fseek(fp, nChunkData + 0x30, SEEK_SET); // Read current frame + fread(&nCurrentFrame, 1, 4, fp); // + + fseek(fp, 0x0C, SEEK_CUR); // Move file pointer to the start of the compressed block + Def = (UINT8*)malloc(nDefLen); + if (Def == NULL) { + return -1; + } + memset(Def, 0, nDefLen); + fread(Def, 1, nDefLen, fp); // Read in deflated block + + nRet = BurnStateDecompress(Def, nDefLen, bAll); // Decompress block into driver + if (Def) { + free(Def); // free deflated block + Def = NULL; + } + + fseek(fp, nChunkData + nChunkSize, SEEK_SET); + + if (nRet) { + return -1; + } else { + return 0; + } +} + +// State load +INT32 BurnStateLoad(TCHAR* szName, INT32 bAll, INT32 (*pLoadGame)()) +{ + const char szHeader[] = "FB1 "; // File identifier + char szReadHeader[4] = ""; + INT32 nRet = 0; + + FILE* fp = _tfopen(szName, _T("rb")); + if (fp == NULL) { + return 1; + } + + fread(szReadHeader, 1, 4, fp); // Read identifier + if (memcmp(szReadHeader, szHeader, 4) == 0) { // Check filetype + nRet = BurnStateLoadEmbed(fp, -1, bAll, pLoadGame); + } + fclose(fp); + + if (nRet < 0) { + return -nRet; + } else { + return 0; + } +} + +// Write a savestate as a chunk of an "FB1 " file +// nOffset is the absolute offset from the beginning of the file +// -1: Append at current position +// -2: Append at EOF +INT32 BurnStateSaveEmbed(FILE* fp, INT32 nOffset, INT32 bAll) +{ + const char* szHeader = "FS1 "; // Chunk identifier + + INT32 nLen = 0; + INT32 nNvMin = 0, nAMin = 0; + INT32 nZero = 0; + char szGame[33]; + UINT8 *Def = NULL; + INT32 nDefLen = 0; // Deflated version + INT32 nRet = 0; + + if (fp == NULL) { + return -1; + } + + StateInfo(&nLen, &nNvMin, 0); // Get minimum version for NV part + nAMin = nNvMin; + if (bAll) { // Get minimum version for All data + StateInfo(&nLen, &nAMin, 1); + } + + if (nLen <= 0) { // No memory to save + return -1; + } + + if (nOffset >= 0) { + fseek(fp, nOffset, SEEK_SET); + } else { + if (nOffset == -2) { + fseek(fp, 0, SEEK_END); + } else { + fseek(fp, 0, SEEK_CUR); + } + } + + fwrite(szHeader, 1, 4, fp); // Chunk identifier + INT32 nSizeOffset = ftell(fp); // Reserve space to write the size of this chunk + fwrite(&nZero, 1, 4, fp); // + + fwrite(&nBurnVer, 1, 4, fp); // Version of FB this was saved from + fwrite(&nNvMin, 1, 4, fp); // Min version of FB NV data will work with + fwrite(&nAMin, 1, 4, fp); // Min version of FB All data will work with + + fwrite(&nZero, 1, 4, fp); // Reserve space to write the compressed data size + + memset(szGame, 0, sizeof(szGame)); // Game name + sprintf(szGame, "%.32s", BurnDrvGetTextA(DRV_NAME)); // + fwrite(szGame, 1, 32, fp); // + + fwrite(&nCurrentFrame, 1, 4, fp); // Current frame + + fwrite(&nZero, 1, 4, fp); // Reserved + fwrite(&nZero, 1, 4, fp); // + fwrite(&nZero, 1, 4, fp); // + + nRet = BurnStateCompress(&Def, &nDefLen, bAll); // Compress block from driver and return deflated buffer + if (Def == NULL) { + return -1; + } + + nRet = fwrite(Def, 1, nDefLen, fp); // Write block to disk + if (Def) { + free(Def); // free deflated block and close file + Def = NULL; + } + + if (nRet != nDefLen) { // error writing block to disk + return -1; + } + + if (nDefLen & 3) { // Chunk size must be a multiple of 4 + fwrite(&nZero, 1, 4 - (nDefLen & 3), fp); // Pad chunk if needed + } + + fseek(fp, nSizeOffset + 0x10, SEEK_SET); // Write size of the compressed data + fwrite(&nDefLen, 1, 4, fp); // + + nDefLen = (nDefLen + 0x43) & ~3; // Add for header size and align + + fseek(fp, nSizeOffset, SEEK_SET); // Write size of the chunk + fwrite(&nDefLen, 1, 4, fp); // + + fseek (fp, 0, SEEK_END); // Set file pointer to the end of the chunk + + return nDefLen; +} + +// State save +INT32 BurnStateSave(TCHAR* szName, INT32 bAll) +{ + const char szHeader[] = "FB1 "; // File identifier + INT32 nLen = 0, nVer = 0; + INT32 nRet = 0; + + if (bAll) { // Get amount of data + StateInfo(&nLen, &nVer, 1); + } else { + StateInfo(&nLen, &nVer, 0); + } + if (nLen <= 0) { // No data, so exit without creating a savestate + return 0; // Don't return an error code + } + + FILE* fp = _tfopen(szName, _T("wb")); + if (fp == NULL) { + return 1; + } + + fwrite(&szHeader, 1, 4, fp); + nRet = BurnStateSaveEmbed(fp, -1, bAll); + fclose(fp); + + if (nRet < 0) { + return 1; + } else { + return 0; + } +} diff --git a/src/burner/statec.cpp b/src/burner/statec.cpp new file mode 100644 index 00000000..b6d743b6 --- /dev/null +++ b/src/burner/statec.cpp @@ -0,0 +1,171 @@ +// Driver State Compression module +#include "zlib.h" + +#include "burnint.h" + +static UINT8* Comp = NULL; // Compressed data buffer +static INT32 nCompLen = 0; +static INT32 nCompFill = 0; // How much of the buffer has been filled so far + +static z_stream Zstr; // Deflate stream + +// ----------------------------------------------------------------------------- +// Compression + +static INT32 CompEnlarge(INT32 nAdd) +{ + void* NewMem = NULL; + + // Need to make more room in the compressed buffer + NewMem = realloc(Comp, nCompLen + nAdd); + if (NewMem == NULL) { + return 1; + } + + Comp = (UINT8*)NewMem; + memset(Comp + nCompLen, 0, nAdd); + nCompLen += nAdd; + + return 0; +} + +static INT32 CompGo(INT32 bFinish) +{ + INT32 nResult = 0; + INT32 nAvailOut = 0; + + bool bRetry, bOverflow; + + do { + + bRetry = false; + + // PoINT32 to the remainder of out buffer + Zstr.next_out = Comp + nCompFill; + nAvailOut = nCompLen - nCompFill; + if (nAvailOut < 0) { + nAvailOut = 0; + } + Zstr.avail_out = nAvailOut; + + // Try to deflate into the buffer (there may not be enough room though) + if (bFinish) { + nResult = deflate(&Zstr, Z_FINISH); // deflate and finish + if (nResult != Z_OK && nResult != Z_STREAM_END) { + return 1; + } + } else { + nResult = deflate(&Zstr, 0); // deflate + if (nResult != Z_OK) { + return 1; + } + } + + nCompFill = Zstr.next_out - Comp; // Update how much has been filled + + // Check for overflow + bOverflow = bFinish ? (nResult == Z_OK) : (Zstr.avail_out <= 0); + + if (bOverflow) { + if (CompEnlarge(4 * 1024)) { + return 1; + } + + bRetry = true; + } + } while (bRetry); + + return 0; +} + +static INT32 __cdecl StateCompressAcb(struct BurnArea* pba) +{ + // Set the data as the next available input + Zstr.next_in = (UINT8*)pba->Data; + Zstr.avail_in = pba->nLen; + + CompGo(0); // Compress this Area + + Zstr.avail_in = 0; + Zstr.next_in = NULL; + + return 0; +} + +// Compress a state using deflate +INT32 BurnStateCompress(UINT8** pDef, INT32* pnDefLen, INT32 bAll) +{ + void* NewMem = NULL; + + memset(&Zstr, 0, sizeof(Zstr)); + + Comp = NULL; nCompLen = 0; nCompFill = 0; // Begin with a zero-length buffer + if (CompEnlarge(8 * 1024)) { + return 1; + } + + deflateInit(&Zstr, Z_DEFAULT_COMPRESSION); + + BurnAcb = StateCompressAcb; // callback our function with each area + + if (bAll) BurnAreaScan(ACB_FULLSCAN | ACB_READ, NULL); // scan all ram, read (from driver <- decompress) + else BurnAreaScan(ACB_NVRAM | ACB_READ, NULL); // scan nvram, read (from driver <- decompress) + + // Finish off + CompGo(1); + + deflateEnd(&Zstr); + + // Size down + NewMem = realloc(Comp, nCompFill); + if (NewMem) { + Comp = (UINT8*)NewMem; + nCompLen = nCompFill; + } + + // Return the buffer + if (pDef) { + *pDef = Comp; + } + if (pnDefLen) { + *pnDefLen = nCompFill; + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// Decompression + +static INT32 __cdecl StateDecompressAcb(struct BurnArea* pba) +{ + Zstr.next_out =(UINT8*)pba->Data; + Zstr.avail_out = pba->nLen; + + inflate(&Zstr, Z_SYNC_FLUSH); + + Zstr.avail_out = 0; + Zstr.next_out = NULL; + + return 0; +} + +INT32 BurnStateDecompress(UINT8* Def, INT32 nDefLen, INT32 bAll) +{ + memset(&Zstr, 0, sizeof(Zstr)); + inflateInit(&Zstr); + + // Set all of the buffer as available input + Zstr.next_in = (UINT8*)Def; + Zstr.avail_in = nDefLen; + + BurnAcb = StateDecompressAcb; // callback our function with each area + + if (bAll) BurnAreaScan(ACB_FULLSCAN | ACB_WRITE, NULL); // scan all ram, write (to driver <- decompress) + else BurnAreaScan(ACB_NVRAM | ACB_WRITE, NULL); // scan nvram, write (to driver <- decompress) + + inflateEnd(&Zstr); + memset(&Zstr, 0, sizeof(Zstr)); + + return 0; +} diff --git a/src/burner/title.h b/src/burner/title.h new file mode 100644 index 00000000..6484d3f8 --- /dev/null +++ b/src/burner/title.h @@ -0,0 +1,9 @@ +// Define macros for appliction title and description +#ifdef FBA_DEBUG + #define APP_TITLE "FB Alpha [DEBUG]" +#else + #define APP_TITLE "FB Alpha" +#endif + +#define APP_DESCRIPTION "Emulator for MC68000/Z80 based arcade games" + diff --git a/src/burner/unzip.c b/src/burner/unzip.c new file mode 100644 index 00000000..e0107db8 --- /dev/null +++ b/src/burner/unzip.c @@ -0,0 +1,1274 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char unz_copyright[] = + " unzip 0.15 Copyright 1998 Gilles Vollant "; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + FILE* file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + FILE* file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ +} unz_s; + + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte(FILE *fin, int *pi) +{ + unsigned char c; + int err = fread(&c, 1, 1, fin); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ferror(fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort (FILE *fin, uLong *pX) +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong (FILE *fin, uLong *pX) +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, const char* fileName2,int iCaseSensitivity) +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir(FILE *fin) +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (fseek(fin,0,SEEK_END) != 0) + return 0; + + + uSizeFile = ftell( fin ); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (fseek(fin,uReadPos,SEEK_SET)!=0) + break; + + if (fread(buf,(uInt)uReadSize,1,fin)!=1) + break; + + for (i=0;i<(int)uReadSize-3;i++) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\t_st\\zlib109.zip" or on an Unix computer + "zlib/zlib109.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen (const char *path) +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + FILE * fin ; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + fin=fopen(path,"rb"); + if (fin==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(fin); + if (central_pos==0) + err=UNZ_ERRNO; + + if (fseek(fin,central_pos,SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(fin,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + fclose(s->file); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info * pglobal_info) +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal( + unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize ) +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) { + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) { + err=UNZ_ERRNO; + } else { + if (uMagic!=0x02014b50) { + err=UNZ_BADZIPFILE; + } + } + } + + if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) { + lSeek=0; + } else { + err=UNZ_ERRNO; + } + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) { + lSeek=0; + } else { + err=UNZ_ERRNO; + } + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo( + unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize ) +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the lat'st. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile( + unzFile file, + const char *szFileName, + int iCaseSensitivity ) +{ + unz_s* s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + return err; +} + + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader( + unz_s* s, + uInt* piSizeVar, + uLong *poffset_local_extrafield, + uInt *psize_local_extrafield ) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek(s->file,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) { + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) { + err=UNZ_ERRNO; + } else { + if (uMagic!=0x04034b50) { + err=UNZ_BADZIPFILE; + } + } + } + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + int err=UNZ_OK; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + Store = s->cur_file_info.compression_method==0; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file=s->file; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if (!Store) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile( + unzFile file, + voidp buf, + unsigned len ) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (len>pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, + pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if (pfile_in_zip_read_info->compression_method==0) + { + uInt uDoCopy,i ; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield( + unzFile file, + voidp buf, + unsigned len ) +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment( + unzFile file, + char *szComment, + uLong uSizeBuf ) +{ +//dave int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + diff --git a/src/burner/unzip.h b/src/burner/unzip.h new file mode 100644 index 00000000..edeb60e2 --- /dev/null +++ b/src/burner/unzip.h @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the lat'st. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/src/burner/win32/about.cpp b/src/burner/win32/about.cpp new file mode 100644 index 00000000..13a587cf --- /dev/null +++ b/src/burner/win32/about.cpp @@ -0,0 +1,294 @@ +#include "burner.h" +#include "version.h" +#include "build_details.h" +#include + +// Print text surrounded by a black outline +static void myDrawText(HDC hDC, RECT* pRect, TCHAR* szText, int nSizeDelta, int nColour, UINT uFormat) +{ + TCHAR szName[32]; + RECT rect; + HFONT hFont, myFont; + TEXTMETRIC myMetric; + + GetTextFace(hDC, 32, szName); + GetTextMetrics(hDC, &myMetric); + myFont = CreateFont(myMetric.tmHeight + nSizeDelta, 0, 0, 0, FW_BLACK, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, 0, szName); + hFont = (HFONT)SelectObject(hDC, myFont); + SetBkMode(hDC, TRANSPARENT); + + // Shrink the rect to allow space for the outline + memcpy(&rect, pRect, sizeof(RECT)); + rect.left += 1; + rect.top += 1; + rect.right -= 1; + rect.bottom -= 1; + + // Print the outline first + SetTextColor(hDC, 0); + rect.left -= 1; + rect.right -= 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.top -= 1; + rect.bottom -= 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.left += 1; + rect.right += 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.left += 1; + rect.right += 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.top += 1; + rect.bottom += 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.top += 1; + rect.bottom += 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.left -= 1; + rect.right -= 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.left -= 1; + rect.right -= 1; + DrawText(hDC, szText, -1, &rect, uFormat); + rect.left += 1; + rect.right += 1; + rect.top -= 1; + rect.bottom -= 1; + + // Then print the text on top + SetTextColor(hDC, nColour); + DrawText(hDC, szText, -1, &rect, uFormat); + + SelectObject(hDC, hFont); + DeleteObject(myFont); +} + +static bool AboutDrawStrings(unsigned int nControlID, LPDRAWITEMSTRUCT pdis) +{ + switch (nControlID) { + case IDC_FBA_VER: { + TCHAR szVerString[128]; + if ((nBurnVer & 0xFFFF) > 0x9990) { + + int nVer1 = ((nBurnVer >> 16) & 0xFF) + 1; + if ((nVer1 & 0x0F) > 9) { + nVer1 += 6; + } + int nVer2 = nVer1 & 0x0F; + nVer1 >>= 4; + + _stprintf(szVerString, _T(APP_TITLE) _T(" v%s (v%i.%i Release Candidate %i)"), szAppBurnVer, nVer1, nVer2, nBurnVer & 0x0F); + } else { + if (nBurnVer & 0x00FF) { + _stprintf(szVerString, _T(APP_TITLE) _T(" v%s (alpha version)"), szAppBurnVer); + } else { + if (nBurnVer & 0xFF00) { + _stprintf(szVerString, _T(APP_TITLE) _T(" v%s (beta version)"), szAppBurnVer); + } else { + _stprintf(szVerString, _T(APP_TITLE) _T(" v%s (release version)"), szAppBurnVer); + } + } + } + + myDrawText(pdis->hDC, &pdis->rcItem, szVerString, 2, RGB(0xFF, 0xF7, 0xDF), DT_CENTER); + + return true; + } + case IDC_SPECIALSTRING: { + +#ifdef SPECIALBUILD + TCHAR* szSpecialBuild = _T(MAKE_STRING(SPECIALBUILD)); + + myDrawText(pdis->hDC, &pdis->rcItem, szSpecialBuild, -1, RGB(0xFF, 0xCF, 0x7F), DT_CENTER); +#else + TCHAR szBuild[256] = _T(""); + + RECT rect = pdis->rcItem; + rect.top += 1; + + _stprintf(szBuild, _T("built on ") _T(MAKE_STRING(BUILD_DATE)) _T(", ") _T(MAKE_STRING(BUILD_TIME)) _T(" (") _T(MAKE_STRING(BUILD_CHAR)) _T(", ") _T(MAKE_STRING(BUILD_COMP)) _T(", ") _T(MAKE_STRING(BUILD_CPU)) _T("%s)"), MMX ? _T(", MMX") : _T("")); + + myDrawText(pdis->hDC, &rect, szBuild, -2, RGB(0xDB, 0xDB, 0xDB), DT_CENTER); +#endif + return true; + } + } + + return false; +} + +// ---------------------------------------------------------------------------- + +void AddLicenseText(HWND hDlg, unsigned int nControlID) +{ + HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(ID_LICENSE), MAKEINTRESOURCE(256)); + HGLOBAL hglobal = LoadResource(NULL, hrsrc); + char* pszLicense = (char*)LockResource(hglobal); + + SendDlgItemMessageA(hDlg, nControlID, WM_SETTEXT, (WPARAM)0, (LPARAM)pszLicense); +} + +// ---------------------------------------------------------------------------- + +static INT_PTR CALLBACK AboutProc(HWND hDlg ,UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + WndInMid(hDlg, hScrnWnd); + return TRUE; + } + + if (Msg == WM_DRAWITEM) { + if (AboutDrawStrings(wParam, (LPDRAWITEMSTRUCT)lParam)) { + return TRUE; + } + + return 0; + } + + if (Msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_SHOWLICENSE) { + RECT rect = { 0, 0, 0, 80 }; + + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_SHOWLICENSE), FALSE); + + SendDlgItemMessage(hDlg, IDC_LICENSE, EM_SETMARGINS, EC_LEFTMARGIN, 3); +// SendDlgItemMessage(hDlg, IDC_LICENSE, EM_SETTYPOGRAPHYOPTIONS, TO_ADVANCEDTYPOGRAPHY, TO_ADVANCEDTYPOGRAPHY); + + AddLicenseText(hDlg, IDC_LICENSE); + + MapDialogRect(hDlg, &rect); + int nSize = rect.bottom; + GetWindowRect(hDlg, &rect); + MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + nSize, TRUE); + + WndInMid(hDlg, hScrnWnd); + return 0; + } + + if (Msg == WM_CLOSE) { + EndDialog(hDlg,0); + } + if (Msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + + return 0; +} + +int AboutCreate() +{ + HMODULE hRiched = NULL; + +#if defined (_UNICODE) + hRiched = LoadLibrary(L"RICHED20.DLL"); +#else + hRiched = LoadLibrary("RICHED20.DLL"); +#endif + if (hRiched) { + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_ABOUT), hScrnWnd, (DLGPROC)AboutProc); + FreeLibrary(hRiched); + hRiched = NULL; + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +static INT_PTR CALLBACK FirstProc(HWND hDlg ,UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static bool bLicenseDisplayed, bLicenseAccepted; + + if (Msg == WM_INITDIALOG) { + TCHAR szWarningString[4096]; + + bLicenseDisplayed = false; + bLicenseAccepted = false; + + SendDlgItemMessage(hDlg, IDC_LICENSE, EM_SETMARGINS, EC_LEFTMARGIN, 3); +// SendDlgItemMessage(hDlg, IDC_LICENSE, EM_SETTYPOGRAPHYOPTIONS, TO_ADVANCEDTYPOGRAPHY, TO_ADVANCEDTYPOGRAPHY); + + _stprintf(szWarningString, FBALoadStringEx(hAppInst, IDS_FIRSTRUN1, true), _T(APP_TITLE), szAppBurnVer); + _tcscat(szWarningString, FBALoadStringEx(hAppInst, IDS_FIRSTRUN2, true)); +#if VER_ALPHA > 0 && (VER_ALPHA < 90 || VER_BETA < 99) + _tcscat(szWarningString, FBALoadStringEx(hAppInst, IDS_FIRSTRUN3A, true)); +#elif VER_BETA > 0 && VER_BETA < 99 + _tcscat(szWarningString, FBALoadStringEx(hAppInst, IDS_FIRSTRUN3B, true)); +#endif + + SendDlgItemMessage(hDlg, IDC_LICENSE, WM_SETTEXT, (WPARAM)0, (LPARAM)szWarningString); + + ShowWindow(GetDlgItem(hDlg, IDC_ACCEPTLICENSE), SW_HIDE); + + SetForegroundWindow(hDlg); + WndInMid(hDlg, NULL); + + SplashDestroy(1); + + return TRUE; + } + + if (Msg == WM_DRAWITEM) { + if (AboutDrawStrings(wParam, (LPDRAWITEMSTRUCT)lParam)) { + return TRUE; + } + + return 0; + } + + if (Msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) { + + if (bLicenseDisplayed) { + if (bLicenseAccepted) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + return 0; + } + + bLicenseDisplayed = true; + + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + ShowWindow(GetDlgItem(hDlg, IDC_ACCEPTLICENSE), SW_SHOW); + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_ACCEPTLICENSE), TRUE); + + AddLicenseText(hDlg, IDC_LICENSE); + + return 0; + } + if (Msg == WM_COMMAND && LOWORD(wParam) == IDC_ACCEPTLICENSE) { + if (SendDlgItemMessage(hDlg, IDC_ACCEPTLICENSE, BM_GETSTATE, 0, 0) & BST_CHECKED) { + bLicenseAccepted = true; + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } else { + bLicenseAccepted = false; + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } + } + + if (Msg == WM_CLOSE) { + if (bLicenseAccepted) { + EndDialog(hDlg, 0); + } + } + + return 0; +} + +int FirstUsageCreate() +{ + HMODULE hRiched = NULL; + +#if defined (_UNICODE) + hRiched = LoadLibrary(L"RICHED20.DLL"); +#else + hRiched = LoadLibrary("RICHED20.DLL"); +#endif + if (hRiched) { + DialogBox(hAppInst, MAKEINTRESOURCE(IDD_FIRST), hScrnWnd, (DLGPROC)FirstProc); + FreeLibrary(hRiched); + hRiched = NULL; + } + + return 0; +} + diff --git a/src/burner/win32/app.rc b/src/burner/win32/app.rc new file mode 100644 index 00000000..ab3dde92 --- /dev/null +++ b/src/burner/win32/app.rc @@ -0,0 +1,1299 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SPLASH DIALOGEX 0, 0, 206, 141 +STYLE DS_MODALFRAME | DS_CENTER | DS_FIXEDSYS | WS_POPUP +EXSTYLE WS_EX_TOOLWINDOW +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL BMP_SPLASH,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,1,1,9999,9999 +END + +IDD_INPD DIALOGEX 0, 0, 250, 244 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Map Game Inputs" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDCANCEL,195,225,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 244, 220 + CTEXT "Double-click an input to change its mapping",IDC_STATIC,7,7,232,15,SS_CENTERIMAGE + CONTROL "List1",IDC_INPD_LIST,"SysListView32",LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 9, 24, 232, 128 + + CONTROL "", IDC_STATIC, "Static", SS_SUNKEN, 9, 156, 232, 58 + CTEXT "Make selection in all three drop-down boxes, click apropriate button",IDC_STATIC,11,159,228,15,SS_CENTERIMAGE + COMBOBOX IDC_INPD_GI,15,177,48,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_INPD_PCI,68,177,81,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_INPD_ANALOG,154,177,81,48,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +// PUSHBUTTON "Macro...",IDC_INPD_NEWMACRO,15,194,52,14 + PUSHBUTTON "Save preset",IDC_INPD_SAVE_AS_PRESET,71,194,52,14 + PUSHBUTTON "Make default",IDC_INPD_DEFAULT,127,194,52,14 + PUSHBUTTON "Use preset",IDC_INPD_USE,183,194,52,14 +END + +IDD_INPS DIALOGEX 0, 0, 195, 64 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select control" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Grab mouse",IDC_INPS_GRABMOUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,5,50,10 + PUSHBUTTON "Activate",IDC_INPS_PUSH,5,17,50,15 + PUSHBUTTON "Cancel",IDCANCEL,5,35,50,15 + CONTROL "",IDC_INPS_CONTROL,"Static",SS_SUNKEN | SS_CENTER | SS_CENTERIMAGE,60,5,130,45, WS_EX_STATICEDGE + CONTROL "",IDC_INPS_CONTROL_NAME,"Edit",ES_CENTER | ES_AUTOHSCROLL | ES_READONLY,5,53,185,8 +END + +IDD_INPC DIALOGEX 0, 0, 97, 26 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "Edit Constant" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_INPC_VALUE,5,5,40,15,ES_AUTOHSCROLL + PUSHBUTTON "Close",IDCANCEL,50,5,40,15 +END + +IDD_INPCHEAT DIALOGEX 0, 0, 250, 200 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit cheat settings" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "", IDC_STATIC, 3, 0, 244, 176 + CTEXT "Select a cheat to change it.", IDC_STATIC, 7, 7, 232, 15, SS_CENTERIMAGE + CONTROL "List1", IDC_INPCHEAT_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 9, 24, 232, 128 + COMBOBOX IDC_INPCX1_VALUE, 9, 157, 177, 128, CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + PUSHBUTTON "Defaults",IDC_INPC_RESET,191,156,50,14 + DEFPUSHBUTTON "OK",IDOK,195,181,50,14 + PUSHBUTTON "Cancel",IDCANCEL,140,181,50,14 +END + +IDD_INPDIP DIALOGEX 0, 0, 270, 200 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit DIPswitch settings" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "", IDC_STATIC, 3, 0, 264, 176 + CTEXT "Select a setting to change it.", IDC_STATIC, 7, 7, + 252, 15, SS_CENTERIMAGE + CONTROL "List1", IDC_INPCHEAT_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 9, 24, 252, 128 + COMBOBOX IDC_INPCX1_VALUE, 9, 157, 197, 128, CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + PUSHBUTTON "Defaults",IDC_INPC_RESET,211,156,50,14 + DEFPUSHBUTTON "OK",IDOK,215,181,50,14 + PUSHBUTTON "Cancel",IDCANCEL,160,181,50,14 +END + +IDD_VALUE DIALOG DISCARDABLE 0, 0, 97, 20 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "Close",ID_VALUE_CLOSE,50,3,40,13 + EDITTEXT IDC_VALUE_EDIT,8,3,40,12,ES_AUTOHSCROLL | ES_NUMBER +END + +IDD_WAIT DIALOGEX 0, 0, 206, 42 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP +EXSTYLE WS_EX_TOOLWINDOW +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL BMP_MISC,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,2,2,9999,9999 + CONTROL "Progress1",IDC_WAIT_PROG,"msctls_progress32",PBS_SMOOTH | WS_BORDER,62,5,139,11 + LTEXT "",IDC_WAIT_LABEL_A,65,23,134,14,SS_CENTERIMAGE | NOT WS_VISIBLE + LTEXT "",IDC_WAIT_LABEL_B1,65,19,134,10,SS_CENTERIMAGE | NOT WS_VISIBLE + LTEXT "",IDC_WAIT_LABEL_B2,65,29,134,10,SS_CENTERIMAGE | NOT WS_VISIBLE + PUSHBUTTON "Cancel",IDCANCEL,151,23,50,14, NOT WS_VISIBLE +END + +IDD_ROMSDIR DIALOGEX 0, 0, 242, 81 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit ROMs paths" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Tab2",IDC_ROMPATH_TAB,"SysTabControl32",WS_TABSTOP,9,6,224,48 + DEFPUSHBUTTON "OK",IDOK,183,57,50,14 + PUSHBUTTON "Cancel",IDCANCEL,128,57,50,14 + GROUPBOX "",IDC_STATIC,5,0,233,76 + EDITTEXT IDC_ROMSDIR_EDIT1,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR1,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT2,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR2,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT3,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR3,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT4,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR4,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT5,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR5,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT6,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR6,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT7,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR7,177,30,50,14 + EDITTEXT IDC_ROMSDIR_EDIT8,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_ROMSDIR_BR8,177,30,50,14 + //EDITTEXT IDC_ROMSDIR_EDIT9,14,31,154,12,ES_AUTOHSCROLL + //PUSHBUTTON "Browse...",IDC_ROMSDIR_BR9,177,30,50,14 + //EDITTEXT IDC_ROMSDIR_EDIT10,14,31,154,12,ES_AUTOHSCROLL + //PUSHBUTTON "Browse...",IDC_ROMSDIR_BR10,177,30,50,14 +END + +IDD_ABOUT DIALOGEX 0, 0, 349, 107 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP +EXSTYLE WS_EX_TOOLWINDOW +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL BMP_ABOUT,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,3,3,100,50 + CONTROL "version",IDC_FBA_VER,"Static",SS_OWNERDRAW | WS_GROUP,78,63,264,10 + CONTROL "specialbuild",IDC_SPECIALSTRING,"Static",SS_OWNERDRAW | WS_GROUP,78,71,264,10 + LTEXT "FB Alpha contains parts of MAME && Final Burn.\n© 2004-2011, Team FB Alpha.",IDC_STATIC,6,86,230,16,WS_DISABLED + DEFPUSHBUTTON "OK",IDOK,294,88,50,14 + PUSHBUTTON "License",IDC_SHOWLICENSE,240,88,50,14 + CONTROL "",IDC_LICENSE,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | WS_VSCROLL | ES_NOIME,3,107,342,77, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT +END + +IDD_FIRST DIALOGEX 0, 0, 349, 189 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP +EXSTYLE WS_EX_TOOLWINDOW +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL BMP_ABOUT,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,3,3,100,50 + CONTROL "version",IDC_FBA_VER,"Static",SS_OWNERDRAW | WS_GROUP,78,63,264,10 + CONTROL "specialbuild",IDC_SPECIALSTRING,"Static",SS_OWNERDRAW | WS_GROUP,78,71,264,10 + CONTROL "",IDC_LICENSE,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | WS_VSCROLL | ES_NOIME,3,88,342,77, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + DEFPUSHBUTTON "OK",IDOK,294,170,50,14 + CONTROL " I understand and agree to be bound by the terms of the above license agreement",IDC_ACCEPTLICENSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,170,282,14 +END + +IDD_SELNEW DIALOGEX 0, 0, 499, 360 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select Game" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Tree1",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | TVS_NOHSCROLL | WS_TABSTOP,9,13,320,212-25,WS_EX_STATICEDGE + CONTROL "Tree2",IDC_TREE2,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_TABSTOP | 0x8000,340,249,148,83,WS_EX_STATICEDGE + GROUPBOX "Preview",IDC_STATIC2,336,1,157,118 + GROUPBOX "Title",IDC_STATIC3,336,120,157,118 + CONTROL "",IDC_SCREENSHOT_H,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,342,13,50,50, WS_EX_CLIENTEDGE + CONTROL "",IDC_SCREENSHOT_V,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,370,13,50,50, WS_EX_CLIENTEDGE + CONTROL "",IDC_SCREENSHOT2_H,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,342,131,50,50, WS_EX_CLIENTEDGE + CONTROL "",IDC_SCREENSHOT2_V,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,370,131,50,50, WS_EX_CLIENTEDGE + GROUPBOX "Select Game",IDC_STATIC1,4,1,330,291 + CONTROL "",IDC_STATIC_INFOBOX,"Static",SS_WHITERECT | SS_SUNKEN,9,203,320,66 + LTEXT "Game info:",IDC_LABELCOMMENT,13,208,45,8,NOT WS_GROUP + LTEXT "ROM name:",IDC_LABELROMNAME,13,218,45,8,NOT WS_GROUP + LTEXT "ROM info:",IDC_LABELROMINFO,13,228,45,8,NOT WS_GROUP + LTEXT "Released by:",IDC_LABELSYSTEM,13,238,45,8,NOT WS_GROUP + LTEXT "Genre:",IDC_LABELGENRE,13,248,45,8,NOT WS_GROUP + LTEXT "Notes:",IDC_LABELNOTES,13,258,45,8,NOT WS_GROUP + EDITTEXT IDC_TEXTCOMMENT,60,208,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_TEXTROMNAME,60,218,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_TEXTROMINFO,60,228,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_TEXTSYSTEM,60,238,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_TEXTGENRE,60,248,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_TEXTNOTES,60,258,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + GROUPBOX "Filters",IDC_STATIC_SYS,336,238,157,99 + LTEXT "",IDC_DRVCOUNT,10,276,230,8 + CONTROL "Rom Info",IDROMINFO,"Button",WS_TABSTOP,262,274,68,14 + GROUPBOX "Options",IDC_STATIC_OPT,4,294,330,35 + CONTROL "Show available only",IDC_CHECKAVAILABLEONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,306,80,8 + CONTROL "Always show clones",IDC_CHECKAUTOEXPAND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,316,80,8 + CONTROL "Use zipnames",IDC_SEL_SHORTNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,95,306,80,8 + CONTROL "Latin text only",IDC_SEL_ASCIIONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,95,316,80,8 + CONTROL "ROMs Dirs...",IDROM,"Button",WS_TABSTOP,189,309,68,14 + CONTROL "Scan ROMs",IDRESCAN,"Button",WS_TABSTOP,262,309,68,14 + CONTROL "Cancel",IDCANCEL,"Button",WS_TABSTOP,372,340,58,14 + CONTROL "Play",IDOK,"Button",WS_TABSTOP,435,340,58,14 + GROUPBOX "IPS",IDC_SEL_IPSGROUP,4,331,144,27 + CONTROL "Apply Patches",IDC_SEL_APPLYIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,343,60,8 + CONTROL "IPS Manager",IDC_SEL_IPSMANAGER,"Button",WS_TABSTOP,75,340,68,14 + GROUPBOX "Search",IDC_SEL_SEARCHGROUP,150,331,184,27 + EDITTEXT IDC_SEL_SEARCH,155,340,174,12,ES_AUTOHSCROLL | WS_TABSTOP +END + +IDD_CAPTURE DIALOGEX DISCARDABLE 0, 0, 227, 122 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Shots Factory" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "&Capture",IDCAPTURE,76,101,50,14 + PUSHBUTTON "&Done",IDOK,128,101,50,14 + PUSHBUTTON "&Advance Frame",IDC_ADVANCE,17,101,57,14 + CONTROL "All Sprites",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,17,17,47,10 + CONTROL "Layer &2",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,17,29,39,10 + CONTROL "Layer &3",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,17,41,39,10 + CONTROL "Layer &4",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,17,53,39,10 + GROUPBOX "Show",IDC_STATIC,7,7,213,109 + CONTROL "Sprite Priority 1",IDC_SPRITE1,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,77,17,63,10 + CONTROL "Sprite Priority 2",IDC_SPRITE2,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,77,29,63,10 + CONTROL "Sprite Priority 4",IDC_SPRITE4,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,77,53,63,10 + CONTROL "Sprite Priority 3",IDC_SPRITE3,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,77,41,63,10 + CONTROL "Sprite Priority 5",IDC_SPRITE5,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,151,17,63,10 + CONTROL "Sprite Priority 6",IDC_SPRITE6,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,151,29,63,10 + CONTROL "Sprite Priority 7",IDC_SPRITE7,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,151,41,63,10 + CONTROL "Sprite Priority 8",IDC_SPRITE8,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,151,53,63,10 +END + +IDD_GAMMA DIALOGEX 0, 0, 214, 59 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select desired Gamma value" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,159,40,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 208, 35 + CONTROL "Gamma value",IDC_GAMMA_SLIDER,"msctls_trackbar32", WS_TABSTOP, 5, 10, 160, 18 + EDITTEXT IDC_GAMMA_EDIT,167,10,35,14,SS_CENTERIMAGE + PUSHBUTTON "Cancel",IDCANCEL,105,40,50,14 +END + +IDD_SCANLINE DIALOGEX 0, 0, 214, 59 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select desired scanline intensity" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,159,40,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 208, 35 + CONTROL "Scanline intensity",IDC_SCANLINE_SLIDER,"msctls_trackbar32", WS_TABSTOP, 5, 10, 160, 18 + EDITTEXT IDC_SCANLINE_EDIT,167,10,35,14,SS_CENTERIMAGE + PUSHBUTTON "Cancel",IDCANCEL,105,40,50,14 +END + +IDD_PHOSPHOR DIALOGEX 0, 0, 214, 82 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select desired feedback intensity" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,159,63,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 208, 58 + CONTROL "Feedback strength",IDC_PHOSPHOR_1_SLIDER,"msctls_trackbar32", WS_TABSTOP, 5, 10, 160, 18 + EDITTEXT IDC_PHOSPHOR_1_EDIT,167,10,35,14,SS_CENTERIMAGE + RTEXT "Max. Oversaturation:", IDC_STATIC, 8, 35, 75, 10, SS_CENTERIMAGE + CONTROL "Feedback oversaturation",IDC_PHOSPHOR_2_SLIDER,"msctls_trackbar32", WS_TABSTOP, 85, 33, 80, 18 + EDITTEXT IDC_PHOSPHOR_2_EDIT,167,33,35,14,SS_CENTERIMAGE + PUSHBUTTON "Cancel",IDCANCEL,105,63,50,14 +END + +IDD_SCREENANGLE DIALOGEX 0, 0, 234, 82 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select desired 3D projection properties" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,179,63,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 228, 58 + RTEXT "Angle:", IDC_STATIC, 8, 12, 25, 10, SS_CENTERIMAGE + CONTROL "Screen Angle",IDC_SCREENANGLE_SLIDER,"msctls_trackbar32", WS_TABSTOP, 35, 10, 150, 18 + EDITTEXT IDC_SCREENANGLE_EDIT,187,10,35,14,SS_CENTERIMAGE + RTEXT "Fishbowl Factor:", IDC_STATIC, 8, 35, 55, 10, SS_CENTERIMAGE + CONTROL "Fishbowl Factor",IDC_SCREENCURVATURE_SLIDER,"msctls_trackbar32", WS_TABSTOP, 65, 33, 120, 18 + EDITTEXT IDC_SCREENCURVATURE_EDIT,187,33,35,14,SS_CENTERIMAGE + PUSHBUTTON "Cancel",IDCANCEL,125,63,50,14 +END + +IDD_CHOOSERES DIALOGEX 0, 0, 134, 54 +STYLE DS_MODALFRAME | DS_CENTER | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select desired resolution" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK", IDOK, 79, 35, 50, 14 + GROUPBOX "", IDC_STATIC, 3, 0, 128, 30 + RTEXT "Resolution:", IDC_STATIC, 8, 11, 48, 10, SS_CENTERIMAGE + COMBOBOX IDC_CHOOSE_LIST, 60, 10, 64, 128, CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + PUSHBUTTON "Cancel", IDCANCEL, 25, 35, 50, 14 +END + +IDD_CPUCLOCK DIALOGEX 0, 0, 222, 59 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Adjust speed of the emulated CPU" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,167,40,50,14 + GROUPBOX "", IDC_STATIC, 3, 0, 216, 35 + CONTROL "CPU speed",IDC_CPUCLOCK_SLIDER,"msctls_trackbar32", WS_TABSTOP, 5, 10, 160, 18 + EDITTEXT IDC_CPUCLOCK_EDIT,167,10,35,14,SS_CENTERIMAGE + LTEXT "%", IDC_STATIC, 206, 11, 8, 10, SS_CENTERIMAGE + PUSHBUTTON "Cancel",IDCANCEL,113,40,50,14 +END + +IDD_EXCEPTION DIALOGEX 0, 0, 349, 69 +STYLE DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "FB Alpha has encountered an unrecoverable problem and will be terminated" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_SYSINFO_CODE, "Static", SS_SUNKEN | SS_CENTER | SS_CENTERIMAGE, 3,3,342,40, WS_EX_STATICEDGE + DEFPUSHBUTTON "OK",IDOK,294,49,50,14 + PUSHBUTTON "Debug",IDC_SYSINFO_DEBUG,240,49,50,14 + PUSHBUTTON "Details",IDC_SYSINFO_SHOW,186,49,50,14 + PUSHBUTTON "Log",IDC_SYSINFO_LOG,132,49,50,14 + CONTROL "",IDC_SYSINFO_EDIT,"EDIT",ES_MULTILINE | ES_WANTRETURN | ES_READONLY | WS_TABSTOP | WS_VSCROLL,3,69,342,122, WS_EX_STATICEDGE +END + +IDD_SYSINFO DIALOGEX 0, 0, 349, 151 +STYLE DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "FB Alpha system information report" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,294,131,50,14 + PUSHBUTTON "Save...",IDC_SYSINFO_LOG,240,131,50,14 + CONTROL "",IDC_SYSINFO_EDIT,"EDIT",ES_MULTILINE | ES_WANTRETURN | ES_READONLY | WS_TABSTOP | WS_VSCROLL,3,3,342,122, WS_EX_STATICEDGE +END + +IDD_DEBUG_LRG DIALOGEX 0, 0, 582, 442 +STYLE DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "FB Alpha debugger" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,3,399,523,14,WS_EX_STATICEDGE + CONTROL "",IDC_DBG_COMMAND,"RICHEDIT20A",ES_LOWERCASE | ES_AUTOHSCROLL | ES_NOIME | WS_TABSTOP,4,400,521,12, ES_EX_NOCALLOLEINIT + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,8,11,83,16,WS_EX_STATICEDGE + CTEXT "Disassembly", IDC_STATIC,13,3,48,16,SS_CENTERIMAGE + COMBOBOX IDC_DBG_MAINWN1_DRP1,95,3,145,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Endianness", IDC_STATIC,250,3,40,16,SS_CENTERIMAGE + COMBOBOX IDC_DBG_MAINWN1_DRP2,295,3,105,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,412,11,167,16,WS_EX_STATICEDGE + CTEXT "Internal CPU state", IDC_STATIC,417,3,67,16,SS_CENTERIMAGE + CONTROL "",IDC_DBG_MAINWN1,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP,3,19,401,179, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,8,209,83,16,WS_EX_STATICEDGE + CTEXT "Memory map", IDC_STATIC,13,201,48,16,SS_CENTERIMAGE + COMBOBOX IDC_DBG_MAINWN2_DRP1,95,201,145,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "Endianness", IDC_STATIC,250,201,40,16,SS_CENTERIMAGE + COMBOBOX IDC_DBG_MAINWN2_DRP2,295,201,105,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,412,209,167,16,WS_EX_STATICEDGE + CTEXT "Debugger messages", IDC_STATIC,417,201,72,16,SS_CENTERIMAGE + CONTROL "",IDC_DBG_MAINWN2,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP,3,217,401,179, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_DBG_INFOWN1,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME,407,19,172,179, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_DBG_INFOWN2,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME,407,217,172,179, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + DEFPUSHBUTTON "Execute",IDOK,529,399,50,14 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,3,417,577,4,WS_EX_STATICEDGE + PUSHBUTTON "Exit",IDCANCEL,527,423,50,14 + PUSHBUTTON "Go!",IDC_DBG_GO,473,423,50,14 + PUSHBUTTON "Step frame",IDC_DBG_STEPFRAME,419,423,50,14 + PUSHBUTTON "Step",IDC_DBG_STEP,365,423,50,14 + PUSHBUTTON "Step into",IDC_DBG_STEPINTO,311,423,50,14 + PUSHBUTTON "Skip",IDC_DBG_SKIP,257,423,50,14 + + PUSHBUTTON "Screenshot",IDC_DBG_SHOT,6,423,50,14 +END + +IDD_DEBUG_SML DIALOGEX 0, 0, 592, 356 +STYLE DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "FB Alpha debugger" +FONT 6, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,3,313,532,14,WS_EX_STATICEDGE + CONTROL "",IDC_DBG_COMMAND,"RICHEDIT20A",ES_LOWERCASE | ES_AUTOHSCROLL | ES_NOIME | WS_TABSTOP,4,314,530,12, ES_EX_NOCALLOLEINIT + COMBOBOX IDC_DBG_MAINWN1_DRP1,3,3,249,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_DBG_MAINWN1_DRP2,254,3,150,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_DBG_MAINWN1,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP,3,19,401,136, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + COMBOBOX IDC_DBG_MAINWN2_DRP1,3,158,249,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_DBG_MAINWN2_DRP2,254,158,150,128,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_DBG_MAINWN2,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP,3,174,401,136, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_DBG_INFOWN1,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME,407,3,182,182, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_DBG_INFOWN2,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME,407,188,182,122, WS_EX_STATICEDGE | ES_EX_NOCALLOLEINIT + DEFPUSHBUTTON "Execute",IDOK,538,313,50,14 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,3,331,586,4,WS_EX_STATICEDGE + PUSHBUTTON "Exit",IDCANCEL,536,337,50,14 + PUSHBUTTON "Go!",IDC_DBG_GO,482,337,50,14 + PUSHBUTTON "Step frame",IDC_DBG_STEPFRAME,428,337,50,14 + PUSHBUTTON "Step",IDC_DBG_STEP,374,337,50,14 + PUSHBUTTON "Step into",IDC_DBG_STEPINTO,320,337,50,14 + PUSHBUTTON "Skip",IDC_DBG_SKIP,266,337,50,14 + + PUSHBUTTON "Screenshot",IDC_DBG_SHOT,6,337,50,14 +END + +IDD_POPUP DIALOGEX 0, 0, 45, 36 +STYLE DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "FB Alpha message" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,38,16,50,14 + CONTROL "",IDC_MESSAGE_BACK,"Static",SS_WHITERECT | NOT WS_VISIBLE,0,0,0,0 + CONTROL "",IDC_MESSAGE_ICON,"Static",SS_OWNERDRAW,7,7,30,30 + CONTROL "",IDC_MESSAGE_EDIT_LOCAL,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP | NOT WS_VISIBLE,38,7,4,2 | ES_EX_NOCALLOLEINIT + CONTROL "",IDC_MESSAGE_EDIT_ENG,"RICHEDIT20A",ES_MULTILINE | ES_READONLY | ES_WANTRETURN | ES_NOIME | WS_TABSTOP,38,7,4,2 | ES_EX_NOCALLOLEINIT +END + +IDD_ROMINFO DIALOGEX 0, 0, 496, 204 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Game Information" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Tab1",IDC_TAB1,"SysTabControl32",TCS_SINGLELINE | WS_TABSTOP,4,6,488,176 + CONTROL "List1",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,24,480,153 + CONTROL "List2",IDC_LIST2,"SysListView32",LVS_REPORT | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,24,480,153 + DEFPUSHBUTTON "Close",IDCANCEL,432,186,60,14 +END + +IDD_SUPPORTDIR DIALOGEX 0, 0, 242, 81 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit support file paths" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Tab2",IDC_SPATH_TAB,"SysTabControl32",WS_TABSTOP,9,6,224,48 + DEFPUSHBUTTON "OK",IDOK,183,57,50,14 + PUSHBUTTON "Cancel",IDCANCEL,128,57,50,14 + GROUPBOX "",IDC_STATIC,5,0,233,76 + EDITTEXT IDC_SUPPORTDIR_EDIT1,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR1,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT2,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR2,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT3,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR3,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT4,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR4,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT5,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR5,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT6,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR6,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT7,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR7,177,30,50,14 + EDITTEXT IDC_SUPPORTDIR_EDIT8,14,31,154,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_SUPPORTDIR_BR8,177,30,50,14 +END + +IDD_PALETTEVIEWER DIALOGEX 0, 0, 320, 240 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Palette Viewer" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "00000",IDC_GFX_VIEWER_VERT_1,"Static",SS_RIGHT,1,15,22,8 + CONTROL "00010",IDC_GFX_VIEWER_VERT_2,"Static",SS_RIGHT,1,28,22,8 + CONTROL "00020",IDC_GFX_VIEWER_VERT_3,"Static",SS_RIGHT,1,41,22,8 + CONTROL "00030",IDC_GFX_VIEWER_VERT_4,"Static",SS_RIGHT,1,54,22,8 + CONTROL "00040",IDC_GFX_VIEWER_VERT_5,"Static",SS_RIGHT,1,67,22,8 + CONTROL "00050",IDC_GFX_VIEWER_VERT_6,"Static",SS_RIGHT,1,80,22,8 + CONTROL "00060",IDC_GFX_VIEWER_VERT_7,"Static",SS_RIGHT,1,93,22,8 + CONTROL "00070",IDC_GFX_VIEWER_VERT_8,"Static",SS_RIGHT,1,105,22,8 + CONTROL "00080",IDC_GFX_VIEWER_VERT_9,"Static",SS_RIGHT,1,118,22,8 + CONTROL "00090",IDC_GFX_VIEWER_VERT_10,"Static",SS_RIGHT,1,131,22,8 + CONTROL "000A0",IDC_GFX_VIEWER_VERT_11,"Static",SS_RIGHT,1,144,22,8 + CONTROL "000B0",IDC_GFX_VIEWER_VERT_12,"Static",SS_RIGHT,1,157,22,8 + CONTROL "000C0",IDC_GFX_VIEWER_VERT_13,"Static",SS_RIGHT,1,170,22,8 + CONTROL "000D0",IDC_GFX_VIEWER_VERT_14,"Static",SS_RIGHT,1,183,22,8 + CONTROL "000E0",IDC_GFX_VIEWER_VERT_15,"Static",SS_RIGHT,1,196,22,8 + CONTROL "000F0",IDC_GFX_VIEWER_VERT_16,"Static",SS_RIGHT,1,209,22,8 + CONTROL "0",IDC_GFX_VIEWER_HORI_1,"Static",0,30,3,8,8 + CONTROL "1",IDC_GFX_VIEWER_HORI_2,"Static",0,44,3,8,8 + CONTROL "2",IDC_GFX_VIEWER_HORI_3,"Static",0,58,3,8,8 + CONTROL "3",IDC_GFX_VIEWER_HORI_4,"Static",0,72,3,8,8 + CONTROL "4",IDC_GFX_VIEWER_HORI_5,"Static",0,86,3,8,8 + CONTROL "5",IDC_GFX_VIEWER_HORI_6,"Static",0,100,3,8,8 + CONTROL "6",IDC_GFX_VIEWER_HORI_7,"Static",0,114,3,8,8 + CONTROL "7",IDC_GFX_VIEWER_HORI_8,"Static",0,128,3,8,8 + CONTROL "8",IDC_GFX_VIEWER_HORI_9,"Static",0,142,3,8,8 + CONTROL "9",IDC_GFX_VIEWER_HORI_10,"Static",0,156,3,8,8 + CONTROL "A",IDC_GFX_VIEWER_HORI_11,"Static",0,170,3,8,8 + CONTROL "B",IDC_GFX_VIEWER_HORI_12,"Static",0,184,3,8,8 + CONTROL "C",IDC_GFX_VIEWER_HORI_13,"Static",0,198,3,8,8 + CONTROL "D",IDC_GFX_VIEWER_HORI_14,"Static",0,211,3,8,8 + CONTROL "E",IDC_GFX_VIEWER_HORI_15,"Static",0,226,3,8,8 + CONTROL "F",IDC_GFX_VIEWER_HORI_16,"Static",0,240,3,8,8 + LTEXT "Selected colour: ",IDC_LABELCOMMENT,3,226,80,8,NOT WS_GROUP + DEFPUSHBUTTON "Close",IDCANCEL,256,206,60,14 + CONTROL "Previous...",IDC_GFX_VIEWER_PREV,"Button",WS_TABSTOP,256,13,60,14 + CONTROL "Next...",IDC_GFX_VIEWER_NEXT,"Button",WS_TABSTOP,256,33,60,14 +END + +IDD_IPS_MANAGER DIALOGEX 0, 0, 474, 318 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "IPS Patch Manager" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Tree1",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_TABSTOP | 0x8000,8,10,250,150,WS_EX_STATICEDGE + GROUPBOX "",IDC_STATIC1,2,0,470,298 + CONTROL "",IDC_STATIC_INFOBOX,"Static",SS_WHITERECT | SS_SUNKEN,8,190,250,100 + EDITTEXT IDC_TEXTCOMMENT,8,190,458,100,ES_MULTILINE | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | WS_VSCROLL + RTEXT "Language:", IDC_STATIC, 8, 170, 40, 10, SS_CENTERIMAGE + COMBOBOX IDC_CHOOSE_LIST, 60, 169, 100, 128, CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + CONTROL "Deselect All",IDC_IPSMAN_DESELECTALL,"Button",WS_TABSTOP,170,169,58,13 + CONTROL "",IDC_SCREENSHOT_H,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,262,10,106,100, WS_EX_CLIENTEDGE + CONTROL "Cancel",IDCANCEL,"Button",WS_TABSTOP,350,300,58,14 + CONTROL "OK",IDOK,"Button",WS_TABSTOP,413,300,58,14 +END + +IDD_MVS_SELECT_CARTS DIALOGEX 0, 0, 319, 271 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select cartridges to load..." +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "", IDC_STATIC, 3, 0, 312, 247 + + DEFPUSHBUTTON "OK",IDOK,263,252,50,14 + PUSHBUTTON "Cancel",IDCANCEL,208,252,50,14 + + CONTROL "",IDC_MVS_CART1,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,8,48,36 + CONTROL "Slot 1", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,9,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME1,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,9,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT1,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,21,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM1,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,33,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR1,262,14,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT1,262,30,50,14 + + CONTROL "",IDC_MVS_CART2,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,48,48,36 + CONTROL "Slot 2", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,49,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME2,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,49,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT2,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,61,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM2,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,73,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR2,262,54,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT2,262,70,50,14 + + CONTROL "",IDC_MVS_CART3,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,88,48,36 + CONTROL "Slot 3", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,89,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME3,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,89,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT3,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,101,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM3,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,113,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR3,262,94,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT3,262,110,50,14 + + CONTROL "",IDC_MVS_CART4,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,128,48,36 + CONTROL "Slot 4", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,129,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME4,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,129,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT4,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,141,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM4,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,153,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR4,262,134,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT4,262,150,50,14 + + CONTROL "",IDC_MVS_CART5,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,168,48,36 + CONTROL "Slot 5", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,169,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME5,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,169,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT5,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,181,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM5,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,193,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR5,262,174,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT5,262,190,50,14 + + CONTROL "",IDC_MVS_CART6,"Static",SS_BITMAP | SS_REALSIZEIMAGE | SS_SUNKEN,8,208,48,36 + CONTROL "Slot 6", IDC_STATIC,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,209,20,8 + CONTROL "", IDC_MVS_TEXTROMNAME6,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,85,209,172,8 + CONTROL "", IDC_MVS_TEXTCOMMENT6,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,221,196,8 + CONTROL "", IDC_MVS_TEXTSYSTEM6,"Edit",ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE,61,233,196,8 + PUSHBUTTON "Clear",IDC_MVS_CLEAR6,262,214,50,14 + PUSHBUTTON "Select...",IDC_MVS_SELECT6,262,230,50,14 +END + +IDD_NCD_DLG DIALOGEX 0, 0, 520, 291 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "NeoGeo CDZ Game List" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_NCD_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,5,348,218 + DEFPUSHBUTTON "Play",IDC_NCD_PLAY_BUTTON,445,272,71,14 + PUSHBUTTON "Cancel",IDC_NCD_CANCEL_BUTTON,370,272,71,14 + PUSHBUTTON "Scan Games",IDC_NCD_SCAN_BUTTON,366,236,71,14 + PUSHBUTTON "Directories...",IDC_NCD_SEL_DIR_BUTTON,441,236,71,14 + CONTROL "Scan sub-dirs",IDC_NCD_SSUBDIR_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,367,255,71,10 + GROUPBOX "Front Cover",IDC_STATIC,362,1,156,108 + GROUPBOX "Back Cover",IDC_STATIC,362,115,156,108 +// GROUPBOX "Selection Info",IDC_STATIC,7,256,348,59 + CONTROL "",IDC_STATIC_INFOBOX,"Static",SS_WHITERECT | SS_SUNKEN,7,227,348,59 + GROUPBOX "Options",IDC_STATIC,362,226,155,43 + CONTROL "",IDC_NCD_FRONT_PIC,"Static",SS_BITMAP | SS_NOTIFY,368,12,22,19,WS_EX_CLIENTEDGE + CONTROL "",IDC_NCD_BACK_PIC,"Static",SS_BITMAP | SS_NOTIFY,368,126,17,15,WS_EX_CLIENTEDGE + CONTROL "",IDC_NCD_FRONT_PIC_FRAME,"Static",SS_BITMAP | NOT WS_VISIBLE,368,12,22,19,WS_EX_CLIENTEDGE + CONTROL "",IDC_NCD_BACK_PIC_FRAME,"Static",SS_BITMAP | NOT WS_VISIBLE,369,126,17,15,WS_EX_CLIENTEDGE + LTEXT "Short name:",IDC_NCD_LABELSHORT,13,231,44,8,NOT WS_GROUP + LTEXT "Released by:",IDC_NCD_LABELPUBLISHER,13,245,44,8,NOT WS_GROUP + LTEXT "Disc Image:",IDC_NCD_LABELIMAGE,13,259,44,8,NOT WS_GROUP + LTEXT "Audio Tracks:",IDC_NCD_LABELAUDIO,13,273,44,8,NOT WS_GROUP + EDITTEXT IDC_NCD_TEXTSHORT,64,231,286,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_NCD_TEXTPUBLISHER,64,245,286,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_NCD_TEXTIMAGE,64,259,286,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + EDITTEXT IDC_NCD_TEXTAUDIO,64,273,50,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + CONTROL "Scan for ISO only",IDC_NCD_SISO_ONLY_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,442,255,71,10 +END + + +// LTEXT "Game info:",IDC_LABELCOMMENT,13,208,45,8,NOT WS_GROUP +// LTEXT "ROM name:",IDC_LABELROMNAME,13,218,45,8,NOT WS_GROUP +// LTEXT "ROM info:",IDC_LABELROMINFO,13,228,45,8,NOT WS_GROUP +// LTEXT "Released by:",IDC_LABELSYSTEM,13,238,45,8,NOT WS_GROUP +// LTEXT "Genre:",IDC_LABELGENRE,13,248,45,8,NOT WS_GROUP +// LTEXT "Notes:",IDC_LABELNOTES,13,258,45,8,NOT WS_GROUP +// EDITTEXT IDC_TEXTCOMMENT,60,208,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP +// EDITTEXT IDC_TEXTROMNAME,60,218,268,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + +IDD_NCD_COVER_DLG DIALOGEX 0, 0, 397, 262 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Cover Image" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_NCD_COVER_PREVIEW_PIC,"Static",SS_BITMAP,3,2,312,179,WS_EX_CLIENTEDGE +END + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "Game" + BEGIN + MENUITEM "Load game...\tF6", MENU_LOAD + MENUITEM "Play via Kaillera...", MENU_STARTNET + POPUP "Most recent games..." + BEGIN + MENUITEM "no game selected", MENU_PREVIOUSGAMES1, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES2, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES3, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES4, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES5, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES6, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES7, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES8, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES9, GRAYED + MENUITEM "no game selected", MENU_PREVIOUSGAMES10, GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Start Neo Geo Multi-slot...\tCtrl+F6",MENU_START_NEOGEO_MVS + MENUITEM SEPARATOR + MENUITEM "Load Neo Geo CDZ game...\tCtrl+F8", MENU_LOAD_NEOCD + MENUITEM "Select CD image (ISO/CUE)...\tCtrl+Shift+F12", MENU_CDIMAGE + MENUITEM "Start Neo Geo CDZ...\tCtrl+Shift+F6", MENU_START_NEOGEO_CD + MENUITEM SEPARATOR + MENUITEM "Exit game\tCtrl+F4", MENU_QUIT, GRAYED + MENUITEM "Pause game\tPause", MENU_PAUSE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Adjust CPU speed...", MENU_SETCPUCLOCK, GRAYED + MENUITEM "Reset CPU speed to 100%", MENU_RESETCPUCLOCK, GRAYED + MENUITEM SEPARATOR + POPUP "Memory Card..." + BEGIN + MENUITEM "Create new memory card...\tCtrl+Shift+F7", MENU_MEMCARD_CREATE + MENUITEM "Select memory card...\tCtrl+F7", MENU_MEMCARD_SELECT + MENUITEM "Insert memory card\tF7", MENU_MEMCARD_INSERT + MENUITEM "Eject memory card\tF7", MENU_MEMCARD_EJECT + END + MENUITEM SEPARATOR + POPUP "Replay..." + BEGIN + MENUITEM "Replay input...", MENU_STARTREPLAY, GRAYED + MENUITEM "Record input...", MENU_STARTRECORD, GRAYED + MENUITEM "Stop replay/record", MENU_STOPREPLAY, GRAYED + END + MENUITEM SEPARATOR + POPUP "Save states..." + BEGIN + MENUITEM "Load state...\tCtrl+F9", MENU_STATE_LOAD_DIALOG, GRAYED + MENUITEM "Save state...\tCtrl+F10", MENU_STATE_SAVE_DIALOG, GRAYED + POPUP "State slots..." + BEGIN + MENUITEM "Activate previous slot\tF8", MENU_STATE_PREVSLOT + MENUITEM "Activate next slot\tF11", MENU_STATE_NEXTSLOT + MENUITEM "MENU_STATE_LOAD_SLOT", MENU_STATE_LOAD_SLOT, GRAYED + MENUITEM "MENU_STATE_SAVE_SLOT", MENU_STATE_SAVE_SLOT, GRAYED + END + MENUITEM "Restore full state on load", MENU_ALLRAM + END + MENUITEM SEPARATOR + MENUITEM "Exit emulator\tAlt+F4", MENU_EXIT + END + POPUP "Video" + BEGIN + POPUP "&Select blitter" + BEGIN + MENUITEM "Basic\t(DirectDraw 7)", MENU_BLITTER_1 + MENUITEM "SoftFX\t(DirectDraw 7)", MENU_BLITTER_3 + MENUITEM "Enhanced\t(Direct3D 7)", MENU_BLITTER_2 + MENUITEM "Experimental\t(DirectX Graphics 9)", MENU_BLITTER_4 + MENUITEM "DirectX9 Alt\t(DirectX Graphics 9)", MENU_BLITTER_5 + END + MENUITEM "&Blitter options", MENU_BLITTEROPTIONS, GRAYED + POPUP "&Stretch" + BEGIN + MENUITEM "&Normal stretch", MENU_NOSTRETCH + MENUITEM "&Full stretch", MENU_STRETCH + MENUITEM "Correct &aspect ratio", MENU_ASPECT + END + MENUITEM SEPARATOR + MENUITEM "&Enable gamma correction", MENU_GAMMA_DO + POPUP "&Gamma correction settings" + BEGIN + MENUITEM "&Darken midtones\t(1.25)", MENU_GAMMA_DARKER + MENUITEM "&Lighten midtones\t(0.80)", MENU_GAMMA_LIGHTER + MENUITEM "MENU_GAMMA_OTHER", MENU_GAMMA_OTHER + MENUITEM SEPARATOR + MENUITEM "Use video &hardware when possible", MENU_GAMMA_USE_HARDWARE + MENUITEM "Use video hardware &exclusively", MENU_GAMMA_HARDWARE_ONLY + MENUITEM "Use &software exclusively", MENU_GAMMA_SOFTWARE_ONLY + END + MENUITEM SEPARATOR + POPUP "&Window size" + BEGIN + MENUITEM "&Auto", MENU_AUTOSIZE + MENUITEM SEPARATOR + MENUITEM "&Single size", MENU_SINGLESIZEWINDOW + MENUITEM "&Double size", MENU_DOUBLESIZEWINDOW + MENUITEM "&Triple size", MENU_TRIPLESIZEWINDOW + MENUITEM "&Quadruple size", MENU_QUADSIZEWINDOW + MENUITEM "&Maximum size", MENU_MAXIMUMSIZEWINDOW + END + MENUITEM SEPARATOR + MENUITEM "Toggle &fullscreen mode\tAlt+Enter", MENU_FULL + MENUITEM "Auto Switch to Fullscreen after loading", MENU_AUTOSWITCHFULL + POPUP "Fullscreen Resolution (Horizontal)" + BEGIN + MENUITEM "MENU_RES_ARCADE", MENU_RES_ARCADE + MENUITEM SEPARATOR + MENUITEM "&Single size", MENU_SINGLESIZESCREEN + MENUITEM "&Double size", MENU_DOUBLESIZESCREEN + MENUITEM "&Triple size", MENU_TRIPLESIZESCREEN + MENUITEM "&Quadruple size", MENU_QUADSIZESCREEN + MENUITEM SEPARATOR + MENUITEM "MENU_RES_1", MENU_RES_1 + MENUITEM "MENU_RES_2", MENU_RES_2 + MENUITEM "MENU_RES_3", MENU_RES_3 + MENUITEM "MENU_RES_4", MENU_RES_4 + MENUITEM SEPARATOR + MENUITEM "MENU_RES_OTHER", MENU_RES_OTHER + END + POPUP "Fullscreen Resolution (Vertical)" + BEGIN + MENUITEM "MENU_RES_ARCADE_VERTICAL", MENU_RES_ARCADE_VERTICAL + MENUITEM SEPARATOR + MENUITEM "&Single size", MENU_SINGLESIZESCREEN_VERTICAL + MENUITEM "&Double size", MENU_DOUBLESIZESCREEN_VERTICAL + MENUITEM "&Triple size", MENU_TRIPLESIZESCREEN_VERTICAL + MENUITEM "&Quadruple size", MENU_QUADSIZESCREEN_VERTICAL + MENUITEM SEPARATOR + MENUITEM "MENU_RES_1_VERTICAL", MENU_RES_1_VERTICAL + MENUITEM "MENU_RES_2_VERTICAL", MENU_RES_2_VERTICAL + MENUITEM "MENU_RES_3_VERTICAL", MENU_RES_3_VERTICAL + MENUITEM "MENU_RES_4_VERTICAL", MENU_RES_4_VERTICAL + MENUITEM SEPARATOR + MENUITEM "MENU_RES_OTHER_VERTICAL", MENU_RES_OTHER_VERTICAL + END + POPUP "Fullscreen bit&depth" + BEGIN + MENUITEM "&16bit", MENU_16 + MENUITEM "&24bit", MENU_24 + MENUITEM "&32bit", MENU_32 + END + MENUITEM SEPARATOR + POPUP "&Monitor properties" + BEGIN + MENUITEM "Automatically detect aspect ratio", MENU_MONITORAUTOCHECK + MENUITEM SEPARATOR + MENUITEM "Normal CRT aspect ratio\t(4:3)", MENU_ASPECTNORMAL + MENUITEM "Normal LCD aspect ratio\t(5:4)", MENU_ASPECTLCD + MENUITEM "Widescreen CRT aspect ratio\t(16:9)", MENU_ASPECTWIDE + MENUITEM "Widescreen LCD aspect ratio\t(16:10)", MENU_ASPECTWIDELCD + MENUITEM SEPARATOR + MENUITEM "Mirrored vertical alignment", MENU_MONITORMIRRORVERT + END + MENUITEM SEPARATOR + MENUITEM "&Rotate vertically aligned games", MENU_ROTATEVERTICAL + MENUITEM "Force 60Hz refresh rate", MENU_FORCE60HZ + MENUITEM "Enable &Triple Buffering (Fullscreen)", MENU_TRIPLE + MENUITEM "Enable VSync (Windowed)", MENU_VIDEOVSYNC + MENUITEM "Enable Win7 DWM Fix (Windowed)", MENU_DWMFIX + MENUITEM "Auto Frameskip", MENU_AUTOFRAMESKIP + END + POPUP "Audio" + BEGIN + POPUP "Select &plugin" + BEGIN + MENUITEM "DirectSound", MENU_AUD_PLUGIN_1 + MENUITEM "XAudio2", MENU_AUD_PLUGIN_2 + END + MENUITEM "Plugin &options", MENU_AUDIO_OPTIONS, GRAYED + MENUITEM SEPARATOR + MENUITEM "2-point 1st order sample interpolation", MENU_INTERPOLATE_1 + MENUITEM "4-point 3rd order sample interpolation", MENU_INTERPOLATE_3 + MENUITEM SEPARATOR + MENUITEM "Disable FM interpolation", MENU_INTERPOLATE_FM_0 + MENUITEM "4-point 3rd order FM interpolation", MENU_INTERPOLATE_FM_3 + MENUITEM SEPARATOR + POPUP "&Sound logging" + BEGIN + MENUITEM "Log to file...", MENU_WLOGSTART, GRAYED + MENUITEM "Stop logging", MENU_WLOGEND, GRAYED + END + MENUITEM "Buffer size...", MENU_FRAMES + END + POPUP "Input" + BEGIN + POPUP "Select &plugin" + BEGIN + MENUITEM "DirectInput", MENU_INP_PLUGIN_1, GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Map game inputs...\tF5", MENU_INPUT, GRAYED + MENUITEM "Set dipswitches...\tCtrl+F5", MENU_DIPSW, GRAYED + END + POPUP "Misc" + BEGIN + POPUP "Options" + BEGIN + MENUITEM "Auto pause", MENU_AUTOPAUSE + MENUITEM "Always process keyboard input", MENU_PROCESSINPUT, GRAYED + MENUITEM "Display mode indicator", MENU_DISPLAYINDICATOR + MENUITEM "Modeless menu", MENU_MODELESS + MENUITEM "Don't change Num Lock status", MENU_NOCHANGENUMLOCK + MENUITEM SEPARATOR + POPUP "Set application thread priority" + BEGIN +// MENUITEM "Realtime", MENU_PRIORITY_REALTIME + MENUITEM "High", MENU_PRIORITY_HIGH + MENUITEM "Above normal", MENU_PRIORITY_ABOVE_NORMAL + MENUITEM "Normal", MENU_PRIORITY_NORMAL + MENUITEM "Below normal", MENU_PRIORITY_BELOW_NORMAL + MENUITEM "Low", MENU_PRIORITY_LOW + END + MENUITEM SEPARATOR + MENUITEM "Use assembly MC68000 core", MENU_ASSEMBLYCORE + MENUITEM SEPARATOR + MENUITEM "Save High Scores when supported", MENU_SAVEHISCORES + END + MENUITEM SEPARATOR + POPUP "Generate dat file" + BEGIN + MENUITEM "Generate dat (Arcade only)...", MENU_CLRMAME_PRO_XML + MENUITEM "Generate dat (Megadrive only)...", MENU_CLRMAME_PRO_XML_MD_ONLY + END + MENUITEM SEPARATOR + MENUITEM "Configure ROM paths...", MENU_ROMDIRS + MENUITEM "Configure support file paths...", MENU_SUPPORTDIRS + MENUITEM SEPARATOR + POPUP "UI language" + BEGIN + MENUITEM "Select UI language...", MENU_LANGUAGE_SELECT + MENUITEM "Export UI translation template...", MENU_LANGUAGE_EXPORT + MENUITEM "Reset UI default language", MENU_LANGUAGE_RESET + END + MENUITEM SEPARATOR + MENUITEM "Save snapshot\tF12", MENU_SAVESNAP + MENUITEM "Shot factory..\tCtrl+F12", MENU_SNAPFACT + MENUITEM SEPARATOR + MENUITEM "Enable cheats...\tCtrl+F1", MENU_ENABLECHEAT, GRAYED + POPUP "Cheat search" + BEGIN + MENUITEM "Start New Search\tCtrl+Home", MENU_CHEATSEARCH_START, GRAYED + MENUITEM SEPARATOR + MENUITEM "Target value has not changed\tCtrl+/", MENU_CHEATSEARCH_NOCHANGE, GRAYED + MENUITEM "Target value has changed\tCtrl+*", MENU_CHEATSEARCH_CHANGE, GRAYED + MENUITEM "Target value has decreased\tCtrl+-", MENU_CHEATSEARCH_DECREASE, GRAYED + MENUITEM "Target value has increased\tCtrl++", MENU_CHEATSEARCH_INCREASE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Dump search to file", MENU_CHEATSEARCH_DUMPFILE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Exit Cheat Search", MENU_CHEATSEARCH_EXIT, GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Invoke debugger...\tCtrl+Shift+F1", MENU_DEBUG + MENUITEM SEPARATOR + MENUITEM "Palette Viewer...\tCtrl+Shift+F5", MENU_PALETTEVIEWER, GRAYED + MENUITEM SEPARATOR + MENUITEM "Associate with .fs and .fr files", MENU_ASSOCIATE + MENUITEM "Disassociate from .fs and .fr files", MENU_DISASSOCIATE + MENUITEM SEPARATOR + MENUITEM "Save input mapping now", MENU_SAVEGAMEINPUTNOW + MENUITEM "Auto-save input mapping", MENU_SAVEGAMEINPUT + MENUITEM SEPARATOR + MENUITEM "Save settings to .ini now", MENU_SAVESET + MENUITEM "Reload settings from .ini", MENU_LOADSET + END + POPUP "Help" + BEGIN + MENUITEM "&Help", MENU_CONTENTS + MENUITEM SEPARATOR + MENUITEM "&What's New", MENU_WHATSNEW + MENUITEM SEPARATOR + MENUITEM "&FB Alpha homepage", MENU_WWW_HOME + MENUITEM "FB Alpha &forums", MENU_WWW_FORUM + MENUITEM "&Neo-Source forums", MENU_WWW_NSFORUM + MENUITEM SEPARATOR + MENUITEM "&System information", MENU_SYSINFO + MENUITEM "&About FB Alpha", MENU_ABOUT + END +END + +IDR_MENU_BLITTER_1 MENU +BEGIN + POPUP "Basic\t(DirectDraw 7)" + BEGIN + MENUITEM "&No effects", MENU_NORMAL + MENUITEM "&Scanlines", MENU_SCAN + MENUITEM "Scanlines &50%", MENU_SCAN50 + MENUITEM SEPARATOR + MENUITEM "&Rotate scanlines", MENU_ROTSCAN + MENUITEM SEPARATOR + POPUP "Buffering &method" + BEGIN + MENUITEM "&Autodetect", MENU_MEMAUTO + MENUITEM "&Video memory", MENU_VIDEOMEM + MENUITEM "&System memory", MENU_SYSMEM + END + END +END + +IDR_MENU_BLITTER_2 MENU +BEGIN + POPUP "Enhanced\t(Direct3D 7)" + BEGIN + MENUITEM "Disable all effects", MENU_DISABLEFX + MENUITEM SEPARATOR + MENUITEM "Enable &bi-linear filtering", MENU_BILINEAR + MENUITEM "&Rotate scanlines and RGB effects", MENU_ROTSCAN + MENUITEM SEPARATOR + MENUITEM "Enable &Pre-scale", MENU_PRESCALE + MENUITEM "Pre-scale using Soft&FX", MENU_SOFTFX + POPUP "SoftFX algorithm" + BEGIN + MENUITEM "Double pixels (3D hardware)", MENU_SOFT_STRETCH + MENUITEM "AdvanceMAME Scale2x", MENU_SOFT_SCALE2X + MENUITEM "AdvanceMAME Scale3x", MENU_SOFT_SCALE3X + MENUITEM "2xPM LQ", MENU_SOFT_2XPM_LQ + MENUITEM "2xPM HQ", MENU_SOFT_2XPM_HQ + MENUITEM "Eagle Graphics", MENU_SOFT_EAGLE + MENUITEM "Super Eagle", MENU_SOFT_SUPEREAGLE + MENUITEM "2xSaI", MENU_SOFT_2XSAI + MENUITEM "Super 2xSaI", MENU_SOFT_SUPER2XSAI + MENUITEM "Super Eagle (VBA)", MENU_SOFT_SUPEREAGLE_VBA + MENUITEM "2xSaI (VBA)", MENU_SOFT_2XSAI_VBA + MENUITEM "Super 2xSaI (VBA)", MENU_SOFT_SUPER2XSAI_VBA + MENUITEM "SuperScale", MENU_SOFT_SUPERSCALE + MENUITEM "SuperScale (75% Scanlines)", MENU_SOFT_SUPERSCALE75 + MENUITEM "hq2x Filter", MENU_SOFT_HQ2X + MENUITEM "hq3x Filter", MENU_SOFT_HQ3X + MENUITEM "hq4x Filter", MENU_SOFT_HQ4X + MENUITEM "hq2xS (VBA) Filter", MENU_SOFT_HQ2XS_VBA + MENUITEM "hq3xS (VBA) Filter", MENU_SOFT_HQ3XS_VBA, GRAYED + MENUITEM "hq2xS (SNES9X) Filter", MENU_SOFT_HQ2XS_SNES9X + MENUITEM "hq3xS (SNEX9X) Filter", MENU_SOFT_HQ3XS_SNES9X + MENUITEM "hq2xBold Filter", MENU_SOFT_HQ2XBOLD + MENUITEM "hq3xBold Filter", MENU_SOFT_HQ3XBOLD + MENUITEM "EPXB Filter", MENU_SOFT_EPXB + MENUITEM "EPXC Filter", MENU_SOFT_EPXC + MENUITEM SEPARATOR + MENUITEM "Force image to SoftFX size", MENU_SOFT_AUTOSIZE + END + MENUITEM SEPARATOR + MENUITEM "Enable &Scanlines", MENU_SCAN + MENUITEM "Set scanline &intensity...", MENU_SCANINTENSITY + MENUITEM SEPARATOR + MENUITEM "Enable phosphor &feedback", MENU_PHOSPHOR + MENUITEM "Set &phosphor feedback intensity...", MENU_PHOSPHORINTENSITY + MENUITEM SEPARATOR + MENUITEM "&No effects", MENU_NORMAL + MENUITEM "RGB &effects", MENU_RGBEFFECTS + MENUITEM "&3D projection", MENU_3DPROJECTION + MENUITEM SEPARATOR + MENUITEM "&Auto size scanlined RGB preset", MENU_EFFECT_AUTO + POPUP "Manually select RGB preset" + BEGIN + MENUITEM "Small faint RGB mask", MENU_EFFECT_01 + MENUITEM "Large faint RGB dot mask", MENU_EFFECT_02 + MENUITEM "Large faint RGB mask", MENU_EFFECT_03 + MENUITEM SEPARATOR + MENUITEM "MAME rgbmicro", MENU_EFFECT_04 + MENUITEM "MAME rgbtiny", MENU_EFFECT_05 + MENUITEM "Aperture grille", MENU_EFFECT_06 + MENUITEM SEPARATOR + MENUITEM "Large oversaturated RGB dot", MENU_EFFECT_07 + MENUITEM "Huge oversaturated pattern", MENU_EFFECT_08 + END + MENUITEM SEPARATOR + MENUITEM "Set 3&D projection properties...", MENU_3DSCREENANGLE +// MENUITEM "Enable &lighting", MENU_3DUSELIGHTING + MENUITEM SEPARATOR + POPUP "Advanced settings" + BEGIN + MENUITEM "Force &16-bit emulation", MENU_FORCE_16BIT + MENUITEM "Use DirectX texture &management", MENU_TEXTUREMANAGE + END + END +END + +IDR_MENU_BLITTER_3 MENU +BEGIN + POPUP "SoftFX\t(DirectDraw 7)" + BEGIN + MENUITEM "&Double pixels (Software)", MENU_SOFT_STRETCH + MENUITEM "AdvanceMAME Scale2x\t(16/32-bit only)", MENU_SOFT_SCALE2X + MENUITEM "AdvanceMAME Scale3x\t(16/32-bit only)", MENU_SOFT_SCALE3X + MENUITEM "2xPM LQ\t(15/16-bit only)", MENU_SOFT_2XPM_LQ + MENUITEM "2xPM HQ\t(15/16-bit only)", MENU_SOFT_2XPM_HQ + MENUITEM "Eagle Graphics\t(16-bit only)", MENU_SOFT_EAGLE + MENUITEM "Super Eagle\t(15/16-bit only)", MENU_SOFT_SUPEREAGLE + MENUITEM "2xSaI\t(15/16-bit only)", MENU_SOFT_2XSAI + MENUITEM "Super 2xSaI\t(15/16-bit only)", MENU_SOFT_SUPER2XSAI + MENUITEM "Super Eagle (VBA)\t(15/16/32-bit only)", MENU_SOFT_SUPEREAGLE_VBA + MENUITEM "2xSaI (VBA)\t(15/16/32-bit only)", MENU_SOFT_2XSAI_VBA + MENUITEM "Super 2xSaI (VBA)\t(15/16/32-bit only)", MENU_SOFT_SUPER2XSAI_VBA + MENUITEM "SuperScale\t(15/16-bit only)", MENU_SOFT_SUPERSCALE + MENUITEM "SuperScale (75% Scanlines)\t(15/16-bit only)",MENU_SOFT_SUPERSCALE75 + MENUITEM "hq2x filter\t(32-bit only)", MENU_SOFT_HQ2X + MENUITEM "hq3x filter\t(32-bit only)", MENU_SOFT_HQ3X + MENUITEM "hq4x filter\t(32-bit only)", MENU_SOFT_HQ4X + MENUITEM "hq2xS (VBA) filter\t(16/32-bit only)", MENU_SOFT_HQ2XS_VBA + MENUITEM "hq3xS (VBA) filter\t(16/32-bit only)", MENU_SOFT_HQ3XS_VBA, GRAYED + MENUITEM "hq2xS (SNES9X) Filter\t(16-bit only)", MENU_SOFT_HQ2XS_SNES9X + MENUITEM "hq3xS (SNEX9X) Filter\t(16-bit only)", MENU_SOFT_HQ3XS_SNES9X + MENUITEM "hq2xBold Filter\t(16-bit only)", MENU_SOFT_HQ2XBOLD + MENUITEM "hq3xBold Filter\t(16-bit only)", MENU_SOFT_HQ3XBOLD + MENUITEM "EPXB Filter\t(16-bit only)", MENU_SOFT_EPXB + MENUITEM "EPXC Filter\t(16-bit only)", MENU_SOFT_EPXC + MENUITEM SEPARATOR + MENUITEM "&Force image to SoftFX size", MENU_SOFT_AUTOSIZE + POPUP "Buffering &method" + BEGIN + MENUITEM "&Autodetect", MENU_MEMAUTO + MENUITEM "&Video memory", MENU_VIDEOMEM + MENUITEM "&System memory", MENU_SYSMEM + MENUITEM SEPARATOR + MENUITEM "Directly access video memory", MENU_SOFT_DIRECTACCESS + END + END +END +IDR_MENU_BLITTER_4 MENU +BEGIN + POPUP "Experimental\t(DirectX Graphics 9)" + BEGIN + MENUITEM "Enable point filtering", MENU_DX9_POINT + MENUITEM "Enable linear filtering", MENU_DX9_LINEAR + MENUITEM "Enable cubic filtering", MENU_DX9_CUBIC + POPUP "Cubic filter quality" + BEGIN + MENUITEM "Lightly filtered\tTensioned B-spline", MENU_DX9_CUBIC_LIGHT + MENUITEM SEPARATOR + MENUITEM "Smoothened strongly\tMitchell-Netravali notch", MENU_DX9_CUBIC_NOTCH + MENUITEM "Smoothened lightly\tCubic B-spline", MENU_DX9_CUBIC_BSPLINE + MENUITEM "Perceptual compromise\tMitchell-Netravali", MENU_DX9_CUBIC_OPTIMAL + MENUITEM "Sharpened lightly\tCatmull-Rom spline", MENU_DX9_CUBIC_CATMULL + MENUITEM "Sharpened strongly\tCardinal cubic spline", MENU_DX9_CUBIC_SHARP + MENUITEM SEPARATOR + MENUITEM "Duff's tensioned B-splines...", MENU_DX9_CUBIC_DUFF, GRAYED + MENUITEM "Mitchell-Netravali 2C + B = 1...", MENU_DX9_CUBIC_MITCHELL, GRAYED + MENUITEM "Cardinal cubic splines...", MENU_DX9_CUBIC_CARDINAL, GRAYED + MENUITEM "Mitchell-Netravali free...", MENU_DX9_CUBIC_CUSTOM, GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Enable &Scanlines", MENU_SCAN + MENUITEM "Set scanline &intensity...", MENU_SCANINTENSITY + MENUITEM SEPARATOR + POPUP "Advanced settings" + BEGIN +// MENUITEM "Single-pass reference implementation", MENU_DX9_CUBIC0 +// MENUITEM "Single-pass partial precision implementation", MENU_DX9_CUBIC1 +// MENUITEM "Multi-pass full precision implementation", MENU_DX9_CUBIC2 +// MENUITEM "Multi-pass partial precision implementation", MENU_DX9_CUBIC3 +// MENUITEM "Multi-pass high-performance implementation", MENU_DX9_CUBIC4 + MENUITEM "Single-pass\tRadeon GPUs", MENU_DX9_CUBIC1 + MENUITEM "Multi-pass\tGeforce GPUs", MENU_DX9_CUBIC3 + MENUITEM "High-performance", MENU_DX9_CUBIC4 + MENUITEM SEPARATOR + MENUITEM "Use PS1.4", MENU_DX9_FORCE_PS14, GRAYED + MENUITEM "Use floating-point textures", MENU_DX9_FPTERXTURES, GRAYED + END + END +END + +IDR_MENU_BLITTER_5 MENU +BEGIN + POPUP "DirectX9 Alt\t(DirectX 9)" + BEGIN + MENUITEM "Point filtering", MENU_DX9_ALT_POINT + MENUITEM "Linear filtering", MENU_DX9_ALT_LINEAR + MENUITEM SEPARATOR + POPUP "SoftFX algorithm" + BEGIN + MENUITEM "Double pixels (3D hardware)", MENU_SOFT_STRETCH + MENUITEM "AdvanceMAME Scale2x", MENU_SOFT_SCALE2X + MENUITEM "AdvanceMAME Scale3x", MENU_SOFT_SCALE3X + MENUITEM "2xPM LQ", MENU_SOFT_2XPM_LQ + MENUITEM "2xPM HQ", MENU_SOFT_2XPM_HQ + MENUITEM "Eagle Graphics", MENU_SOFT_EAGLE + MENUITEM "Super Eagle", MENU_SOFT_SUPEREAGLE + MENUITEM "2xSaI", MENU_SOFT_2XSAI + MENUITEM "Super 2xSaI", MENU_SOFT_SUPER2XSAI + MENUITEM "Super Eagle (VBA)", MENU_SOFT_SUPEREAGLE_VBA + MENUITEM "2xSaI (VBA)", MENU_SOFT_2XSAI_VBA + MENUITEM "Super 2xSaI (VBA)", MENU_SOFT_SUPER2XSAI_VBA + MENUITEM "SuperScale", MENU_SOFT_SUPERSCALE + MENUITEM "SuperScale (75% Scanlines)", MENU_SOFT_SUPERSCALE75 + MENUITEM "hq2x Filter", MENU_SOFT_HQ2X + MENUITEM "hq3x Filter", MENU_SOFT_HQ3X + MENUITEM "hq4x Filter", MENU_SOFT_HQ4X + MENUITEM "hq2xS (VBA) Filter", MENU_SOFT_HQ2XS_VBA + MENUITEM "hq3xS (VBA) Filter", MENU_SOFT_HQ3XS_VBA, GRAYED + MENUITEM "hq2xS (SNES9X) Filter", MENU_SOFT_HQ2XS_SNES9X + MENUITEM "hq3xS (SNEX9X) Filter", MENU_SOFT_HQ3XS_SNES9X + MENUITEM "hq2xBold Filter", MENU_SOFT_HQ2XBOLD + MENUITEM "hq3xBold Filter", MENU_SOFT_HQ3XBOLD + MENUITEM "EPXB Filter", MENU_SOFT_EPXB + MENUITEM "EPXC Filter", MENU_SOFT_EPXC + MENUITEM SEPARATOR + MENUITEM "Force image to SoftFX size", MENU_SOFT_AUTOSIZE + END + MENUITEM SEPARATOR + POPUP "Advanced settings" + BEGIN + MENUITEM "Hardware vertex processing", MENU_DX9_ALT_HARDWAREVERTEX + MENUITEM "Motion blur", MENU_DX9_ALT_MOTIONBLUR + END + END +END + +IDR_MENU_AUD_PLUGIN_1 MENU +BEGIN + POPUP "DirectSound plugin" + BEGIN + MENUITEM "Use Low-pass filter", MENU_DSOUND_BASS + MENUITEM SEPARATOR + MENUITEM "Sound disabled", MENU_DSOUND_NOSOUND + MENUITEM "11025Hz samplerate", MENU_DSOUND_11025 + MENUITEM "22050Hz samplerate", MENU_DSOUND_22050 + MENUITEM "44100Hz samplerate", MENU_DSOUND_44100 + MENUITEM "48000Hz samplerate", MENU_DSOUND_48000 + END +END + +IDR_MENU_AUD_PLUGIN_2 MENU +BEGIN + POPUP "XAudio2 plugin" + BEGIN + MENUITEM "Use Low-pass filter", MENU_XAUDIO_BASS + MENUITEM "Use reverb", MENU_XAUDIO_REVERB + MENUITEM SEPARATOR + MENUITEM "Sound disabled", MENU_XAUDIO_NOSOUND + MENUITEM "11025Hz samplerate", MENU_XAUDIO_11025 + MENUITEM "22050Hz samplerate", MENU_XAUDIO_22050 + MENUITEM "44100Hz samplerate", MENU_XAUDIO_44100 + MENUITEM "48000Hz samplerate", MENU_XAUDIO_48000 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +BMP_SPLASH BITMAP DISCARDABLE "resource/splash.bmp" +BMP_ABOUT BITMAP DISCARDABLE "resource/about.bmp" +BMP_MISC BITMAP DISCARDABLE "resource/misc.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCELERATOR ACCELERATORS DISCARDABLE +BEGIN + VK_F1, MENU_ENABLECHEAT, CONTROL, VIRTKEY, NOINVERT + VK_F1, MENU_DEBUG, CONTROL, SHIFT, VIRTKEY, NOINVERT + VK_F4, MENU_QUIT, CONTROL, VIRTKEY, NOINVERT + VK_F5, MENU_INPUT, VIRTKEY, NOINVERT + VK_F5, MENU_DIPSW, CONTROL, VIRTKEY, NOINVERT + VK_F5, MENU_PALETTEVIEWER, CONTROL, SHIFT, VIRTKEY, NOINVERT + VK_F6, MENU_LOAD, VIRTKEY, NOINVERT + VK_F6, MENU_START_NEOGEO_MVS, CONTROL, VIRTKEY, NOINVERT + VK_F6, MENU_START_NEOGEO_CD, CONTROL, SHIFT, VIRTKEY, NOINVERT + VK_F7, MENU_MEMCARD_TOGGLE, VIRTKEY, NOINVERT + VK_F7, MENU_MEMCARD_CREATE, CONTROL, SHIFT, VIRTKEY, NOINVERT + VK_F7, MENU_MEMCARD_SELECT, CONTROL, VIRTKEY, NOINVERT + VK_F8, MENU_STATE_PREVSLOT, VIRTKEY, NOINVERT + VK_F8, MENU_LOAD_NEOCD, CONTROL, VIRTKEY, NOINVERT + VK_F9, MENU_STATE_LOAD_SLOT, VIRTKEY, NOINVERT + VK_F9, MENU_STATE_LOAD_DIALOG, CONTROL, VIRTKEY, NOINVERT + VK_F10, MENU_STATE_SAVE_SLOT, VIRTKEY, NOINVERT + VK_F10, MENU_STATE_SAVE_DIALOG, CONTROL, VIRTKEY, NOINVERT + VK_F11, MENU_STATE_NEXTSLOT, VIRTKEY, NOINVERT + VK_F12, MENU_SAVESNAP, VIRTKEY, NOINVERT + VK_F12, MENU_SNAPFACT, CONTROL, VIRTKEY, NOINVERT + VK_F12, MENU_CDIMAGE, CONTROL, SHIFT, VIRTKEY, NOINVERT + VK_PAUSE, MENU_PAUSE, VIRTKEY, NOINVERT + VK_RETURN, MENU_FULL, ALT, VIRTKEY, NOINVERT + VK_HOME, MENU_CHEATSEARCH_START, CONTROL, VIRTKEY, NOINVERT + VK_DIVIDE, MENU_CHEATSEARCH_NOCHANGE, CONTROL, VIRTKEY, NOINVERT + VK_MULTIPLY, MENU_CHEATSEARCH_CHANGE, CONTROL, VIRTKEY, NOINVERT + VK_SUBTRACT, MENU_CHEATSEARCH_DECREASE, CONTROL, VIRTKEY, NOINVERT + VK_ADD, MENU_CHEATSEARCH_INCREASE, CONTROL, VIRTKEY, NOINVERT +END + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP ICON DISCARDABLE "resource/fba.ico" +IDI_TV_PLUS ICON DISCARDABLE "resource/TV Plus.ico" +IDI_TV_MINUS ICON DISCARDABLE "resource/TV Minus.ico" +IDI_TV_NOTWORKING ICON DISCARDABLE "resource/TV Not Working.ico" +IDI_TV_NOTFOUND_ESS ICON DISCARDABLE "resource/TV Not Found.ico" +IDI_TV_NOTFOUND_NON ICON DISCARDABLE "resource/TV Not Found Non Essential.ico" + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/burner/win32/burner_win32.h b/src/burner/win32/burner_win32.h new file mode 100644 index 00000000..68744687 --- /dev/null +++ b/src/burner/win32/burner_win32.h @@ -0,0 +1,442 @@ +#define _WIN32_WINDOWS 0x0410 +//#define _WIN32_WINNT 0x0400 +#define _WIN32_IE 0x0500 +#define _WIN32_WINNT 0x0501 +#define WINVER 0x0501 +#define STRICT + +#if defined (_UNICODE) + #define UNICODE +#endif + +#define WIN32_LEAN_AND_MEAN +#define OEMRESOURCE +#include +#include +#include +#include + +#include +#include +#include +#include "dwmapi_core.h" + +INT32 DSCore_Init(); +INT32 DICore_Init(); +INT32 DDCore_Init(); +INT32 Dx9Core_Init(); + +// Additions to the Cygwin/MinGW win32 headers +#ifdef __GNUC__ + #include "mingw_win32.h" +#endif + +#include "resource.h" +#include "resource_string.h" + +// --------------------------------------------------------------------------- + +// Macro for releasing a COM object +#define RELEASE(x) { if ((x)) (x)->Release(); (x) = NULL; } + +#define KEY_DOWN(Code) ((GetAsyncKeyState(Code) & 0x8000) ? 1 : 0) + +// Macros used for handling Window Messages +#define HANDLE_WM_ENTERMENULOOP(hwnd, wParam, lParam, fn) \ + ((fn)((hwnd), (BOOL)(wParam)), 0L) + +#ifdef __GNUC__ +#define HANDLE_WM_EXITMENULOOP(hwnd, wParam, lParam, fn) \ + ((fn)((hwnd), (BOOL)(wParam))) +#else +#define HANDLE_WM_EXITMENULOOP(hwnd, wParam, lParam, fn) \ + ((fn)((hwnd), (BOOL)(wParam)), 0L) +#endif + +#define HANDLE_WM_ENTERSIZEMOVE(hwnd, wParam, lParam, fn) \ + ((fn)(hwnd), 0L) + +#define HANDLE_WM_EXITSIZEMOVE(hwnd, wParam, lParam, fn) \ + ((fn)(hwnd), 0L) + +#define HANDLE_WM_UNINITMENUPOPUP(hwnd,wParam,lParam,fn) \ + ((fn)((hwnd), (HMENU)(wParam), (UINT)LOWORD(lParam), (BOOL)HIWORD(lParam)),0) + +// Extra macro used for handling Window Messages +#define HANDLE_MSGB(hwnd, message, fn) \ + case (message): \ + HANDLE_##message((hwnd), (wParam), (lParam), (fn)); \ + break; + +// Macro used for re-initialiging video/sound/input +// #define POST_INITIALISE_MESSAGE { dprintf(_T("*** (re-) initialising - %s %i\n"), _T(__FILE__), __LINE__); PostMessage(NULL, WM_APP + 0, 0, 0); } +#define POST_INITIALISE_MESSAGE PostMessage(NULL, WM_APP + 0, 0, 0) + +// --------------------------------------------------------------------------- + +// main.cpp +extern HINSTANCE hAppInst; // Application Instance +extern HANDLE hMainThread; // Handle to the main thread +extern long int nMainThreadID; // ID of the main thread +extern int nAppThreadPriority; +extern int nAppShowCmd; + +extern HACCEL hAccel; + +extern int nAppVirtualFps; // virtual fps + +#define EXE_NAME_SIZE (32) +extern TCHAR szAppExeName[EXE_NAME_SIZE + 1]; +extern TCHAR szAppBurnVer[16]; + +extern bool bCmdOptUsed; +extern bool bAlwaysProcessKeyboardInput; + +extern bool bNoChangeNumLock; +extern bool bMonitorAutoCheck; + +// Used for the load/save dialog in commdlg.h +extern TCHAR szChoice[MAX_PATH]; // File chosen by the user +extern OPENFILENAME ofn; + +// Used to convert strings when possibly needed +/* const */ char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize); +/* const */ TCHAR* ANSIToTCHAR(const char* pszString, TCHAR* pszOutString, int nOutSize); + +CHAR *astring_from_utf8(const char *s); +char *utf8_from_astring(const CHAR *s); + +WCHAR *wstring_from_utf8(const char *s); +char *utf8_from_wstring(const WCHAR *s); + +#ifdef _UNICODE +#define tstring_from_utf8 wstring_from_utf8 +#define utf8_from_tstring utf8_from_wstring +#else // !_UNICODE +#define tstring_from_utf8 astring_from_utf8 +#define utf8_from_tstring utf8_from_astring +#endif // _UNICODE + +int dprintf(TCHAR* pszFormat, ...); // Use instead of printf() in the UI + +void MonitorAutoCheck(); + +void AppCleanup(); +int AppMessage(MSG* pMsg); +bool AppProcessKeyboardInput(); + +// localise.cpp +extern bool bLocalisationActive; +extern TCHAR szLocalisationTemplate[MAX_PATH]; + +void FBALocaliseExit(); +int FBALocaliseInit(TCHAR* pszTemplate); +int FBALocaliseLoadTemplate(); +int FBALocaliseCreateTemplate(); +HMENU FBALoadMenu(HINSTANCE hInstance, LPTSTR lpMenuName); +INT_PTR FBADialogBox(HINSTANCE hInstance, LPTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc); +HWND FBACreateDialog(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc); +int FBALoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax); +TCHAR* FBALoadStringEx(HINSTANCE hInstance, UINT uID, bool bTranslate); + +// popup_win32.cpp +enum FBAPopupType { MT_NONE = 0, MT_ERROR, MT_WARNING, MT_INFO }; + +#define PUF_TYPE_ERROR (1) +#define PUF_TYPE_WARNING (2) +#define PUF_TYPE_INFO (3) +#define PUF_TYPE_LOGONLY (8) + +#define PUF_TEXT_TRANSLATE (1 << 16) + +#define PUF_TEXT_NO_TRANSLATE (0) +#define PUF_TEXT_DEFAULT (PUF_TEXT_TRANSLATE) + +int FBAPopupDisplay(int nFlags); +int FBAPopupAddText(int nFlags, TCHAR* pszFormat, ...); +int FBAPopupDestroyText(); + +// sysinfo.cpp +LONG CALLBACK ExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo); +int SystemInfoCreate(); + +// splash.cpp +int SplashCreate(); +void SplashDestroy(bool bForce); + +extern int nSplashTime; + +// about.cpp +int AboutCreate(); +int FirstUsageCreate(); + +// media.cpp +int MediaInit(); +int MediaExit(); + +// misc_win32.cpp +extern bool bIsWindowsXPorGreater; +BOOL DetectWindowsVersion(); +int AppDirectory(); +void UpdatePath(TCHAR* path); +void RegisterExtensions(bool bCreateKeys); +int GetClientScreenRect(HWND hWnd, RECT* pRect); +int WndInMid(HWND hMid, HWND hBase); +char* DecorateGameName(unsigned int nBurnDrv); + + +// drv.cpp +extern int bDrvOkay; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions +extern TCHAR szAppRomPaths[DIRS_MAX][MAX_PATH]; +int DrvInit(int nDrvNum, bool bRestore); +int DrvInitCallback(); // Used when Burn library needs to load a game. DrvInit(nBurnSelect, false) +int DrvExit(); + +// run.cpp +extern int bRunPause; +extern int bAltPause; +extern int bAlwaysDrawFrames; +extern int kNetGame; +int RunIdle(); +int RunMessageLoop(); +int RunReset(); +void ToggleLayer(unsigned char thisLayer); + +// mdi.cpp +#define ID_MDI_START_CHILD 2990 +extern HWND hWndChildFrame; +extern HWND hVideoWindow; +BOOL RegNewMDIChild(); +int InitBurnerMDI(HWND hParentWnd); +void DestroyBurnerMDI(int nAction); + +// scrn.cpp +extern HWND hScrnWnd; // Handle to the screen window +extern HWND hRebar; // Handle to the Rebar control containing the menu +extern HWND hwndChat; +extern bool bRescanRoms; +extern bool bMenuEnabled; + +extern RECT SystemWorkArea; // The full screen area +extern int nWindowPosX, nWindowPosY; + +extern int nSavestateSlot; + +int ScrnInit(); +int ScrnExit(); +int ScrnSize(); +int ScrnTitle(); +void SetPauseMode(bool bPause); +int ActivateChat(); +void DeActivateChat(); +int BurnerLoadDriver(TCHAR *szDriverName); + +// menu.cpp +#define UM_DISPLAYPOPUP (WM_USER + 0x0100) +#define UM_CANCELPOPUP (WM_USER + 0x0101) + +extern HANDLE hMenuThread; // Handle to the thread that executes TrackPopupMenuEx +extern DWORD nMenuThreadID; // ID of the thread that executes TrackPopupMenuEx +extern HWND hMenubar; // Handle to the Toolbar control comprising the menu +extern HWND hMenuWindow; +extern bool bMenuDisplayed; +extern int nLastMenu; +extern HMENU hMenu; // Handle to the menu +extern HMENU hMenuPopup; // Handle to a popup version of the menu +extern int nMenuHeight; +extern int bAutoPause; +extern int nScreenSize; +extern int nScreenSizeHor; // For horizontal orientation +extern int nScreenSizeVer; // For vertical orientation +extern int nWindowSize; + +#define SHOW_PREV_GAMES 10 +extern TCHAR szPrevGames[SHOW_PREV_GAMES][32]; + +extern bool bModelessMenu; + +int MenuCreate(); +void MenuDestroy(); +int SetMenuPriority(); +void MenuUpdate(); +void CreateArcaderesItem(); +void MenuEnableItems(); +bool MenuHandleKeyboard(MSG*); +void MenuRemoveTheme(); + +// sel.cpp +extern int nLoadMenuShowX; +extern int nLoadMenuBoardTypeFilter; +extern int nLoadMenuGenreFilter; +extern int nLoadMenuFamilyFilter; +int SelDialog(int nMVSCartsOnly, HWND hParentWND); +extern UINT_PTR nTimer; +extern HBITMAP hPrevBmp; +extern int nDialogSelect; +void CreateToolTipForRect(HWND hwndParent, PTSTR pszText); +int SelMVSDialog(); + +// neocdsel.cpp +extern int NeoCDList_Init(); +extern bool bNeoCDListScanSub; +extern bool bNeoCDListScanOnlyISO; +extern TCHAR szNeoCDCoverDir[MAX_PATH]; +extern TCHAR szNeoCDGamesDir[MAX_PATH]; + +// image_win32.cpp +typedef struct tagIMAGE { + unsigned int width; + unsigned int height; + unsigned int rowbytes; + unsigned int imgbytes; + unsigned char** rowptr; + unsigned char* bmpbits; + unsigned int flags; +} IMAGE; + +HBITMAP ImageToBitmap(HWND hwnd, IMAGE* img); +HBITMAP PNGLoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset); +HBITMAP LoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset); + +// cona.cpp +extern int nIniVersion; + +struct VidPresetData { int nWidth; int nHeight; }; +extern struct VidPresetData VidPreset[4]; + +struct VidPresetDataVer { int nWidth; int nHeight; }; +extern struct VidPresetDataVer VidPresetVer[4]; + +int ConfigAppLoad(); +int ConfigAppSave(); + +// wave.cpp +extern FILE* WaveLog; // wave log file + +int WaveLogStart(); +int WaveLogStop(); + +// inpd.cpp +extern HWND hInpdDlg; // Handle to the Input Dialog + +int InpdUpdate(); +int InpdCreate(); +int InpdListMake(int bBuild); + +// inpcheat.cpp +extern HWND hInpCheatDlg; // Handle to the Input Dialog + +int InpCheatCreate(); +int InpCheatListMake(int bBuild); + +// inpdipsw.cpp +extern HWND hInpDIPSWDlg; // Handle to the Input Dialog +void InpDIPSWResetDIPs(); +int InpDIPSWCreate(); + +// inpmacro.cpp +extern HWND hInpMacroDlg; +void InpMacroExit(); +int InpMacroCreate(int nInput); + +// inps.cpp +extern HWND hInpsDlg; // Handle to the Input Set Dialog +extern unsigned int nInpsInput; // The input number we are redefining +int InpsCreate(); +int InpsUpdate(); + +// inpc.cpp +extern HWND hInpcDlg; // Handle to the Input Constant Dialog +extern unsigned int nInpcInput; // The input number we are redefining +int InpcCreate(); + +// stated.cpp +extern int bDrvSaveAll; +int StatedAuto(int bSave); +int StatedLoad(int nSlot); +int StatedSave(int nSlot); + +// numdial.cpp +int NumDialCreate(int bDial); +void GammaDialog(); +void ScanlineDialog(); +void PhosphorDialog(); +void ScreenAngleDialog(); +void CPUClockDialog(); +void CubicSharpnessDialog(); +// sfactd.cpp +int SFactdCreate(); + +// roms.cpp +extern char* gameAv; +extern bool avOk; +int RomsDirCreate(HWND hParentWND); +int CreateROMInfo(HWND hParentWND); +void FreeROMInfo(); + +// support_paths.cpp +extern TCHAR szAppPreviewsPath[MAX_PATH]; +extern TCHAR szAppTitlesPath[MAX_PATH]; +extern TCHAR szAppCheatsPath[MAX_PATH]; +extern TCHAR szAppIpsPath[MAX_PATH]; +int SupportDirCreate(HWND hParentWND); +int SupportDirCreateTab(int nTab, HWND hParentWND); + +// res.cpp +int ResCreate(int); + +// fba_kaillera.cpp +int KailleraInitInput(); +int KailleraGetInput(); + +// replay.cpp +extern int nReplayStatus; +int RecordInput(); +int ReplayInput(); +int StartRecord(); +int StartReplay(const TCHAR* szFileName = NULL); +void StopReplay(); + +// memcard.cpp +extern int nMemoryCardStatus; // & 1 = file selected, & 2 = inserted + +int MemCardCreate(); +int MemCardSelect(); +int MemCardInsert(); +int MemCardEject(); +int MemCardToggle(); + +// progress.cpp +int ProgressUpdateBurner(double dProgress, const TCHAR* pszText, bool bAbs); +int ProgressCreate(); +int ProgressDestroy(); + +// --------------------------------------------------------------------------- +// Debugger + +// debugger.cpp +extern HWND hDbgDlg; + +int DebugExit(); +int DebugCreate(); + +// paletteviewer.cpp +int PaletteViewerDialogCreate(HWND hParentWND); + +// ips_manager.cpp +extern int nIpsSelectedLanguage; +int GetIpsNumPatches(); +void LoadIpsActivePatches(); +int GetIpsNumActivePatches(); +int IpsManagerCreate(HWND hParentWND); +void IpsPatchExit(); + +// Misc +#define _TtoA(a) TCHARToANSI(a, NULL, 0) +#define _AtoT(a) ANSIToTCHAR(a, NULL, 0) +int __cdecl ZipLoadOneFile(const char* arcName, const char* fileName, void** Dest, int* pnWrote); + +// numpluscommas.cpp +TCHAR* FormatCommasNumber(__int64); +#define _uInt64ToCommaFormattedTCHAR(szOUT, nIN) \ + _stprintf(szOUT, _T("%s"), FormatCommasNumber(nIN)); diff --git a/src/burner/win32/bzip.cpp b/src/burner/win32/bzip.cpp new file mode 100644 index 00000000..bd2ce2f2 --- /dev/null +++ b/src/burner/win32/bzip.cpp @@ -0,0 +1,595 @@ +// Burner Zip module +#include "burner.h" + +int nBzipError = 0; // non-zero if there is a problem with the opened romset + +static TCHAR* szBzipName[BZIP_MAX] = { NULL, }; // Zip files to search through + +struct RomFind { int nState; int nZip; int nPos; }; // State is non-zero if found. 1 = found totally okay. +static struct RomFind* RomFind = NULL; +static int nRomCount = 0; static int nTotalSize = 0; +static struct ZipEntry* List = NULL; static int nListCount = 0; // List of entries for current zip file +static int nCurrentZip = -1; // Zip which is currently open + +// ---------------------------------------------------------------------------- + +static void BzipListFree() +{ + if (List) { + for (int i = 0; i < nListCount; i++) { + if (List[i].szName) { + free(List[i].szName); + List[i].szName = NULL; + } + } + free(List); + List = NULL; + } + + nListCount = 0; +} + +static char* GetFilenameA(char* szFull) +{ + int nLen = strlen(szFull); + + if (nLen <= 0) { + return szFull; + } + for (int i = nLen - 1; i >= 0; i--) { + if (szFull[i] == '\\' || szFull[i] == '/') { + return szFull + i + 1; + } + } + + return szFull; +} + +static TCHAR* GetFilenameW(TCHAR* szFull) +{ + int nLen = _tcslen(szFull); + + if (nLen <= 0) { + return szFull; + } + for (int i = nLen - 1; i >= 0; i--) { + if (szFull[i] == _T('\\') || szFull[i] == _T('/')) { + return szFull + i + 1; + } + } + + return szFull; +} + +static int FindRomByName(TCHAR* szName) +{ + struct ZipEntry* pl; + int i; + + // Find the rom named szName in the List + for (i = 0, pl = List; i < nListCount; i++, pl++) { + TCHAR szCurrentName[MAX_PATH]; + if (_tcsicmp(szName, GetFilenameW(ANSIToTCHAR(pl->szName, szCurrentName, MAX_PATH))) == 0) { + return i; + } + } + return -1; // couldn't find the rom +} + +static int FindRomByCrc(unsigned int nCrc) +{ + struct ZipEntry* pl; + int i; + + // Find the rom named szName in the List + for (i = 0, pl = List; i< nListCount; i++, pl++) { + if (nCrc == pl->nCrc) { + return i; + } + } + + return -1; // couldn't find the rom +} + +// Find rom number i from the pBzipDriver game +static int FindRom(int i) +{ + struct BurnRomInfo ri; + int nRet; + + memset(&ri, 0, sizeof(ri)); + + nRet = BurnDrvGetRomInfo(&ri, i); + if (nRet != 0) { // Failure: no such rom + return -2; + } + + if (ri.nCrc) { // Search by crc first + nRet = FindRomByCrc(ri.nCrc); + if (nRet >= 0) { + return nRet; + } + } + + for (int nAka = 0; nAka < 0x10000; nAka++) { // Failing that, search for possible names + char *szPossibleName = NULL; + + nRet = BurnDrvGetRomName(&szPossibleName, i, nAka); + if (nRet) { // No more rom names + break; + } + nRet = FindRomByName(ANSIToTCHAR(szPossibleName, NULL, 0)); + if (nRet >= 0) { + return nRet; + } + } + + return -1; // Couldn't find the rom +} + +static int RomDescribe(struct BurnRomInfo* pri) +{ + if (nBzipError == 0) { + nBzipError |= 0x8000; + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_INVALID)); + } + + FBAPopupAddText(PUF_TEXT_DEFAULT, _T(" ") _T(SEPERATOR_1)); + if (pri->nType & BRF_ESS) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_ESS)); + } + if (pri->nType & BRF_BIOS) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_BIOS)); + } + if (pri->nType & BRF_PRG) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_PRG)); + } + if (pri->nType & BRF_GRA) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_GRA)); + } + if (pri->nType & BRF_SND) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_SND)); + } + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_ROM)); + + return 0; +} + +static int CheckRomsBoot() +{ + int nRet = 0; + + for (int i = 0; i < nRomCount; i++) { + struct BurnRomInfo ri; + int nState; + + memset(&ri, 0, sizeof(ri)); + BurnDrvGetRomInfo(&ri, i); // Find information about the wanted rom + nState = RomFind[i].nState; // Get the state of the rom in the zip file + + if (nState != 1 && ri.nType && ri.nCrc) { + if (!(ri.nType & BRF_OPT) && !(ri.nType & BRF_NODUMP)) { + return 1; + } + nRet = 2; + } + } + + return nRet; +} + +static int GetBZipError(int nState) +{ + switch (nState) { + case 1: // OK + return 0x0000; + case 0: // Not present + return 0x0001; + case 3: // Incomplete + return 0x0001; + default: // CRC wrong or too large + return 0x0100; + } + + return 0x0100; +} + +// Check the roms to see if they code, graphics etc are complete +static int CheckRoms() +{ + for (int i = 0; i < nRomCount; i++) { + struct BurnRomInfo ri; + + memset(&ri, 0, sizeof(ri)); + BurnDrvGetRomInfo(&ri, i); // Find information about the wanted rom + if ( /*ri.nCrc &&*/ (ri.nType & BRF_OPT) == 0 && (ri.nType & BRF_NODUMP) == 0) { + int nState = RomFind[i].nState; // Get the state of the rom in the zip file + int nError = GetBZipError(nState); + + if (nState == 0 && ri.nType) { // (A type of 0 means empty slot - no rom) + char* szName = "Unknown"; + RomDescribe(&ri); + BurnDrvGetRomName(&szName, i, 0); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_NOTFOUND), szName); + } + + if (nError == 0) { + nBzipError |= 0x2000; + } + + if (ri.nType & BRF_ESS) { // essential rom - without it the game may not run at all + nBzipError |= nError << 0; + } + if (ri.nType & BRF_PRG) { // rom which contains program information + nBzipError |= nError << 1; + } + if (ri.nType & BRF_GRA) { // rom which contains graphics information + nBzipError |= nError << 2; + } + if (ri.nType & BRF_SND) { // rom which contains sound information + nBzipError |= nError << 3; + } + } + } + + if (nBzipError & 0x0F0F) { + nBzipError |= 0x4000; + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +static int __cdecl BzipBurnLoadRom(unsigned char* Dest, int* pnWrote, int i) +{ +#if defined (BUILD_WIN32) + MSG Msg; +#endif + + struct BurnRomInfo ri; + int nWantZip = 0; + TCHAR szText[128]; + char* pszRomName = NULL; + int nRet = 0; + + if (i < 0 || i >= nRomCount) { + return 1; + } + + ri.nLen = 0; + BurnDrvGetRomInfo(&ri, i); // Get info + + // show what we're doing + BurnDrvGetRomName(&pszRomName, i, 0); + if (pszRomName == NULL) { + pszRomName = "unknown"; + } + _stprintf(szText, _T("Loading")); + if (ri.nType & (BRF_PRG | BRF_GRA | BRF_SND | BRF_BIOS)) { + if (ri.nType & BRF_BIOS) { + _stprintf (szText + _tcslen(szText), _T(" %s"), _T("BIOS ")); + } + if (ri.nType & BRF_PRG) { + _stprintf (szText + _tcslen(szText), _T(" %s"), _T("program ")); + } + if (ri.nType & BRF_GRA) { + _stprintf (szText + _tcslen(szText), _T(" %s"), _T("graphics ")); + } + if (ri.nType & BRF_SND) { + _stprintf (szText + _tcslen(szText), _T(" %s"), _T("sound ")); + } + _stprintf(szText + _tcslen(szText), _T("(%hs)..."), pszRomName); + } else { + _stprintf(szText + _tcslen(szText), _T(" %hs..."), pszRomName); + } + ProgressUpdateBurner(ri.nLen ? 1.0 / ((double)nTotalSize / ri.nLen) : 0, szText, 0); + +#if defined (BUILD_WIN32) + // Check for messages: + while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { + DispatchMessage(&Msg); + } +#endif + + if (RomFind[i].nState == 0) { // Rom not found in zip at all + return 1; + } + + nWantZip = RomFind[i].nZip; // Which zip file it is in + if (nCurrentZip != nWantZip) { // If we haven't got the right zip file currently open + ZipClose(); + nCurrentZip = -1; + if (ZipOpen(TCHARToANSI(szBzipName[nWantZip], NULL, 0))) { + return 1; + } + nCurrentZip = nWantZip; + } + + // Read in file and return how many bytes we read + if (ZipLoadFile(Dest, ri.nLen, pnWrote, RomFind[i].nPos)) { + + // Error loading from the zip file + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(nRet == 2 ? IDS_ERR_LOAD_DISK_CRC : IDS_ERR_LOAD_DISK), pszRomName, GetFilenameW(szBzipName[nCurrentZip])); + FBAPopupDisplay(PUF_TYPE_WARNING); + + return 1; + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +int BzipStatus() +{ + if (!(nBzipError & 0x0F0F)) { + return BZIP_STATUS_OK; + } + if (nBzipError & 1) { + return BZIP_STATUS_ERROR; + } + + return BZIP_STATUS_BADDATA; +} + +int BzipOpen(bool bootApp) +{ + int nMemLen; // Zip name number + + nTotalSize = 0; + nBzipError = 0; + + if (szBzipName == NULL) { + return 1; + } + + BzipClose(); // Make sure nothing is open + + // Count the number of roms needed + for (nRomCount = 0; ; nRomCount++) { + if (BurnDrvGetRomInfo(NULL, nRomCount)) { + break; + } + } + if (nRomCount <= 0) { + return 1; + } + + // Create an array for holding lookups for each rom -> zip entries + nMemLen = nRomCount * sizeof(struct RomFind); + RomFind = (struct RomFind*)malloc(nMemLen); + if (RomFind == NULL) { + return 1; + } + memset(RomFind, 0, nMemLen); + + for (int y = 0; y < BZIP_MAX; y++) { + if (szBzipName[y]) { + free(szBzipName[y]); + szBzipName[y] = NULL; + } + } + + // Locate each zip file + for (int y = 0, z = 0; y < BZIP_MAX && z < BZIP_MAX; y++) { + char* szName = NULL; + bool bFound = false; + + if (BurnDrvGetZipName(&szName, y)) { + break; + } + + for (int d = 0; d < DIRS_MAX; d++) { + TCHAR szFullName[MAX_PATH]; + + _stprintf(szFullName, _T("%s%hs"), szAppRomPaths[d], szName); + + if (ZipOpen(TCHARToANSI(szFullName, NULL, 0)) == 0) { // Open the rom zip file + ZipClose(); + + bFound = true; + + szBzipName[z] = (TCHAR*)malloc(MAX_PATH * sizeof(TCHAR)); + _tcscpy(szBzipName[z], szFullName); + + if (!bootApp) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_FOUND), szName, szBzipName[z]); + } + + z++; + + // Look further in the last two paths specified, so you can put files with ROMs + // used only by FB Alpha there without causing problems with dat files + if (d < DIRS_MAX - 3) { + d = DIRS_MAX - 3; + } else { + if (d >= DIRS_MAX - 1) { + break; + } + } + } + } + + if (!bootApp && !bFound) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_NOTFOUND), szName); + } + } + + if (!bootApp) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n")); + } + + // Locate the ROM data in the zip files + for (int z = 0; z < BZIP_MAX; z++) { + + if (szBzipName[z] == NULL) { + continue; + } + + if (ZipOpen(TCHARToANSI(szBzipName[z], NULL, 0)) == 0) { // Open the rom zip file + nCurrentZip = z; + + ZipGetList(&List, &nListCount); // Get the list of entries + + for (int i = 0; i < nRomCount; i++) { + struct BurnRomInfo ri; + int nFind; + + if (RomFind[i].nState == 1) { // Already found this and it's okay + continue; + } + + memset(&ri, 0, sizeof(ri)); + + nFind = FindRom(i); + + if (nFind < 0) { // Couldn't find this rom at all + continue; + } + + RomFind[i].nZip = z; // Remember which zip file it is in + RomFind[i].nPos = nFind; + RomFind[i].nState = 1; // Set to found okay + + BurnDrvGetRomInfo(&ri, i); // Get info about the rom + + if ((ri.nType & BRF_OPT) == 0 && (ri.nType & BRF_NODUMP) == 0) { + nTotalSize += ri.nLen; + } + + if (List[nFind].nLen == ri.nLen) { + if (ri.nCrc) { // If we know the CRC + if (List[nFind].nCrc != ri.nCrc) { // Length okay, but CRC wrong + RomFind[i].nState = 2; + } + } + } else { + if (List[nFind].nLen < ri.nLen) { + RomFind[i].nState = 3; // Too small + } else { + RomFind[i].nState = 4; // Too big + } + } + + if (!bootApp) { + if (RomFind[i].nState != 1) { + RomDescribe(&ri); + + if (RomFind[i].nState == 2) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_CRC), GetFilenameA(List[nFind].szName), List[nFind].nCrc, ri.nCrc); + } + if (RomFind[i].nState == 3) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_SMALL), GetFilenameA(List[nFind].szName), List[nFind].nLen >> 10, ri.nLen >> 10); + } + if (RomFind[i].nState == 4) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_LARGE), GetFilenameA(List[nFind].szName), List[nFind].nLen >> 10, ri.nLen >> 10); + } + } + } + } + + BzipListFree(); + } + + ZipClose(); // Close the last zip file if open + nCurrentZip = -1; + } + + if (!bootApp) { + // Check the roms to see if the code, graphics etc are complete + CheckRoms(); + + if (nBzipError & 0x2000) { + if (!(nBzipError & 0x0F0F)) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_OK)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n")); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_PROBLEM)); + } + + if (nBzipError & 0x0101) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n ") _T(SEPERATOR_1)); + if (nBzipError & 0x0001) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_ESS_MISS)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_ESS_BAD)); + } + } + if (nBzipError & 0x0202) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n ") _T(SEPERATOR_1)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_PRG)); + if (nBzipError & 0x0002) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_MISS)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_BAD)); + } + } + if (nBzipError & 0x0404) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n ") _T(SEPERATOR_1)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_GRA)); + if (nBzipError & 0x0004) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_MISS)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_BAD)); + } + } + if (nBzipError & 0x0808) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n ") _T(SEPERATOR_1)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DET_SND)); + if (nBzipError & 0x0008) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_MISS)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_BAD)); + } + } + + // Catch non-categorised ROMs + if ((nBzipError & 0x0F0F) == 0) { + if (nBzipError & 0x0010) { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n ") _T(SEPERATOR_1)); + if (nBzipError & 0x1000) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_MISS)); + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_DATA_BAD)); + } + } + } + } else { + FBAPopupAddText(PUF_TEXT_DEFAULT, _T("\n")); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_NODATA)); + } + + BurnExtLoadRom = BzipBurnLoadRom; // Okay to call our function to load each rom + + } else { + return CheckRomsBoot(); + } + + return 0; +} + +int BzipClose() +{ + ZipClose(); + nCurrentZip = -1; // Close the last zip file if open + + BurnExtLoadRom = NULL; // Can't call our function to load each rom anymore + nBzipError = 0; // reset romset errors + + if (RomFind) { + free(RomFind); + RomFind = NULL; + } + nRomCount = 0; + + for (int z = 0; z < BZIP_MAX; z++) { + if (szBzipName[z]) { + free(szBzipName[z]); + szBzipName[z] = NULL; + } + } + + return 0; +} diff --git a/src/burner/win32/cona.cpp b/src/burner/win32/cona.cpp new file mode 100644 index 00000000..47fa4301 --- /dev/null +++ b/src/burner/win32/cona.cpp @@ -0,0 +1,572 @@ +// Burner Config file module +#include "burner.h" + +#ifdef _UNICODE + #include +#endif + +int nIniVersion = 0; + +struct VidPresetData VidPreset[4] = { + { 400, 300}, + { 640, 480}, + { 1024, 768}, + { 1280, 960}, +}; + +struct VidPresetDataVer VidPresetVer[4] = { + { 400, 300}, + { 640, 480}, + { 1024, 768}, + { 1280, 960}, +}; + +static void CreateConfigName(TCHAR* szConfig) +{ + _stprintf(szConfig, _T("config\\%s.ini"), szAppExeName); + return; +} + +// Read in the config file for the whole application +int ConfigAppLoad() +{ + TCHAR szConfig[MAX_PATH]; + TCHAR szLine[1024]; + FILE* h; + +#ifdef _UNICODE + setlocale(LC_ALL, ""); +#endif + + CreateConfigName(szConfig); + + if ((h = _tfopen(szConfig, _T("rt"))) == NULL) { + return 1; + } + + // Go through each line of the config file + while (_fgetts(szLine, sizeof(szLine), h)) { + int nLen = _tcslen(szLine); + + // Get rid of the linefeed at the end + if (szLine[nLen - 1] == 10) { + szLine[nLen - 1] = 0; + nLen--; + } + +#define VAR(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x)); \ + if (szValue) x = _tcstol(szValue, NULL, 0); } +#define VAR64(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x)); \ + if (szValue) x = (long long)_tcstod(szValue, NULL); } +#define FLT(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x)); \ + if (szValue) x = _tcstod(szValue, NULL); } +#define STR(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x) _T(" ")); \ + if (szValue) _tcscpy(x,szValue); } +#define PAT(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x) _T(" ")); \ + if (szValue) { _tcscpy(x, szValue); UpdatePath(x); } } +#define DRV(x) { TCHAR* szValue = LabelCheck(szLine,_T(#x) _T(" ")); \ + if (szValue) x = NameToDriver(szValue); } + + VAR(nIniVersion); + + // Emulation + VAR(bBurnUseASMCPUEmulation); + + // Video + VAR(nVidDepth); VAR(nVidRefresh); + VAR(nVidRotationAdjust); + + // horizontal oriented + VAR(nVidHorWidth); VAR(nVidHorHeight); + VAR(bVidArcaderesHor); + VAR(VidPreset[0].nWidth); VAR(VidPreset[0].nHeight); + VAR(VidPreset[1].nWidth); VAR(VidPreset[1].nHeight); + VAR(VidPreset[2].nWidth); VAR(VidPreset[2].nHeight); + VAR(VidPreset[3].nWidth); VAR(VidPreset[3].nHeight); + VAR(nScreenSizeHor); + + // vertical oriented + VAR(nVidVerWidth); VAR(nVidVerHeight); + VAR(bVidArcaderesVer); + VAR(VidPresetVer[0].nWidth); VAR(VidPresetVer[0].nHeight); + VAR(VidPresetVer[1].nWidth); VAR(VidPresetVer[1].nHeight); + VAR(VidPresetVer[2].nWidth); VAR(VidPresetVer[2].nHeight); + VAR(VidPresetVer[3].nWidth); VAR(VidPresetVer[3].nHeight); + VAR(nScreenSizeVer); + + VAR(nWindowSize); + VAR(nWindowPosX); VAR(nWindowPosY); + VAR(bDoGamma); + VAR(bVidUseHardwareGamma); + VAR(bHardwareGammaOnly); + FLT(nGamma); + VAR(bVidFullStretch); + VAR(bVidCorrectAspect); + + VAR(bVidAutoSwitchFull); + + VAR(bVidTripleBuffer); + VAR(bVidVSync); + VAR(bVidDWMCore); + + VAR(bVidScanlines); + VAR(nVidScanIntensity); + VAR(bMonitorAutoCheck); + VAR(nVidScrnAspectX); + VAR(nVidScrnAspectY); + VAR(bForce60Hz); + VAR(bAlwaysDrawFrames); + + VAR(nVidSelect); + VAR(nVidBlitterOpt[0]); + VAR64(nVidBlitterOpt[1]); + VAR(nVidBlitterOpt[2]); + VAR(nVidBlitterOpt[3]); + VAR(nVidBlitterOpt[4]); + + // DirectDraw blitter + VAR(bVidScanHalf); + + // Direct3D blitter + VAR(bVidBilinear); + VAR(bVidScanDelay); + VAR(bVidScanRotate); + VAR(bVidScanBilinear); + VAR(nVidFeedbackIntensity); + VAR(nVidFeedbackOverSaturation); + FLT(fVidScreenAngle); + FLT(fVidScreenCurvature); + VAR(bVidForce16bit); + VAR(nVidTransferMethod); + + // DirectX Graphics blitter + FLT(dVidCubicB); + FLT(dVidCubicC); + + // DirectX Graphics 9 Alt blitter + VAR(bVidDX9Bilinear); + VAR(bVidHardwareVertex); + VAR(bVidMotionBlur); + + // Sound + VAR(nAudSelect); + VAR(nAudSegCount); + VAR(nInterpolation); + VAR(nFMInterpolation); + VAR(nAudSampleRate[0]); + VAR(nAudDSPModule[0]); + VAR(nAudSampleRate[1]); + VAR(nAudDSPModule[1]); + + // Other + STR(szLocalisationTemplate); + + VAR(nVidSDisplayStatus); + VAR(nMinChatFontSize); + VAR(nMaxChatFontSize); + + VAR(bModelessMenu); + + VAR(nSplashTime); + + VAR(bDrvSaveAll); + VAR(nAppThreadPriority); + VAR(bAlwaysProcessKeyboardInput); + VAR(bAutoPause); + VAR(bSaveInputs); + + VAR(nCDEmuSelect); + PAT(CDEmuImage); + + VAR(nLoadMenuShowX); + VAR(nLoadMenuBoardTypeFilter); + VAR(nLoadMenuGenreFilter); + VAR(nLoadMenuFamilyFilter); + + STR(szAppRomPaths[0]); + STR(szAppRomPaths[1]); + STR(szAppRomPaths[2]); + STR(szAppRomPaths[3]); + STR(szAppRomPaths[4]); + STR(szAppRomPaths[5]); + STR(szAppRomPaths[6]); + STR(szAppRomPaths[7]); + + STR(szNeoCDGamesDir); + + STR(szAppPreviewsPath); + STR(szAppTitlesPath); + STR(szAppCheatsPath); + STR(szAppHiscorePath); + STR(szAppSamplesPath); + STR(szAppIpsPath); + STR(szNeoCDCoverDir); + + VAR(bNoChangeNumLock); + + VAR(EnableHiscores); + + VAR(nIpsSelectedLanguage); + + STR(szPrevGames[0]); + STR(szPrevGames[1]); + STR(szPrevGames[2]); + STR(szPrevGames[3]); + STR(szPrevGames[4]); + STR(szPrevGames[5]); + STR(szPrevGames[6]); + STR(szPrevGames[7]); + STR(szPrevGames[8]); + STR(szPrevGames[9]); + + // MVS cartridges + DRV(nBurnDrvSelect[0]); + DRV(nBurnDrvSelect[1]); + DRV(nBurnDrvSelect[2]); + DRV(nBurnDrvSelect[3]); + DRV(nBurnDrvSelect[4]); + DRV(nBurnDrvSelect[5]); + + VAR(bNeoCDListScanSub); + VAR(bNeoCDListScanOnlyISO); + + // Default Controls + VAR(nPlayerDefaultControls[0]); + STR(szPlayerDefaultIni[0]); + VAR(nPlayerDefaultControls[1]); + STR(szPlayerDefaultIni[1]); + VAR(nPlayerDefaultControls[2]); + STR(szPlayerDefaultIni[2]); + VAR(nPlayerDefaultControls[3]); + STR(szPlayerDefaultIni[3]); + +#undef DRV +#undef PAT +#undef STR +#undef FLT +#undef VAR +#undef VAR64 + } + + fclose(h); + return 0; +} + +// Write out the config file for the whole application +int ConfigAppSave() +{ + TCHAR szConfig[MAX_PATH]; + FILE *h; + + if (bCmdOptUsed) { + return 1; + } + +#ifdef _UNICODE + setlocale(LC_ALL, ""); +#endif + + CreateConfigName(szConfig); + + if ((h = _tfopen(szConfig, _T("wt"))) == NULL) { + return 1; + } + + // Write title + _ftprintf(h, _T("// ") _T(APP_TITLE) _T(" v%s --- Main Config File\n\n"), szAppBurnVer); + _ftprintf(h, _T("// Don't edit this file manually unless you know what you're doing\n")); + _ftprintf(h, _T("// ") _T(APP_TITLE) _T(" will restore default settings when this file is deleted\n")); + +#define VAR(x) _ftprintf(h, _T(#x) _T(" %d\n"), x) +#define VAR64(x) _ftprintf(h, _T(#x) _T(" %lf\n"), (float)x) +#define FLT(x) _ftprintf(h, _T(#x) _T(" %lf\n"), x) +#define STR(x) _ftprintf(h, _T(#x) _T(" %s\n"), x) +#define DRV(x) _ftprintf(h, _T(#x) _T(" %s\n"), DriverToName(x)) + + _ftprintf(h, _T("\n// The application version this file was saved from\n")); + // We can't use the macros for this! + _ftprintf(h, _T("nIniVersion 0x%06X"), nBurnVer); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- emulation --------------------------------------------------------------\n")); + + _ftprintf(h, _T("\n// If non-zero, use A68K for MC68000 emulation\n")); + VAR(bBurnUseASMCPUEmulation); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- Video ------------------------------------------------------------------\n")); + + // Horizontal oriented + _ftprintf(h, _T("\n// (Horizontal Oriented) The display mode to use for fullscreen\n")); + VAR(nVidHorWidth); VAR(nVidHorHeight); + _ftprintf(h, _T("\n// (Horizontal Oriented) If non-zero, use the same fullscreen resolution as the original arcade game\n")); + VAR(bVidArcaderesHor); + _ftprintf(h, _T("\n// (Horizontal Oriented) The preset resolutions appearing in the menu\n")); + VAR(VidPreset[0].nWidth); VAR(VidPreset[0].nHeight); + VAR(VidPreset[1].nWidth); VAR(VidPreset[1].nHeight); + VAR(VidPreset[2].nWidth); VAR(VidPreset[2].nHeight); + VAR(VidPreset[3].nWidth); VAR(VidPreset[3].nHeight); + _ftprintf(h, _T("\n// (Horizontal Oriented) Full-screen size (0 = use display mode variables)\n")); + VAR(nScreenSizeHor); + + // Vertical oriented + _ftprintf(h, _T("\n// (Vertical Oriented) The display mode to use for fullscreen\n")); + VAR(nVidVerWidth); VAR(nVidVerHeight); + _ftprintf(h, _T("\n// (Vertical Oriented) If non-zero, use the same fullscreen resolution as the original arcade game\n")); + VAR(bVidArcaderesVer); + _ftprintf(h, _T("\n// (Vertical Oriented) The preset resolutions appearing in the menu\n")); + VAR(VidPresetVer[0].nWidth); VAR(VidPresetVer[0].nHeight); + VAR(VidPresetVer[1].nWidth); VAR(VidPresetVer[1].nHeight); + VAR(VidPresetVer[2].nWidth); VAR(VidPresetVer[2].nHeight); + VAR(VidPresetVer[3].nWidth); VAR(VidPresetVer[3].nHeight); + _ftprintf(h, _T("\n// (Vertical Oriented) Full-screen size (0 = use display mode variables)\n")); + VAR(nScreenSizeVer); + + _ftprintf(h, _T("\n// Full-screen bit depth\n")); + VAR(nVidDepth); + _ftprintf(h, _T("\n// Specify the refresh rate, 0 = default (changing this will not work with many video cards)\n")); + VAR(nVidRefresh); + _ftprintf(h, _T("\n// If non-zero, do not rotate the graphics for vertical games\n")); + VAR(nVidRotationAdjust); + _ftprintf(h, _T("\n// Initial window size (0 = autosize)\n")); + VAR(nWindowSize); + _ftprintf(h, _T("\n// Window position\n")); + VAR(nWindowPosX); VAR(nWindowPosY); + _ftprintf(h, _T("\n// If non-zero, perform gamma correction\n")); + VAR(bDoGamma); + _ftprintf(h, _T("\n// If non-zero, use the video hardware to correct gamma\n")); + VAR(bVidUseHardwareGamma); + _ftprintf(h, _T("\n// If non-zero, don't fall back on software gamma correction\n")); + VAR(bHardwareGammaOnly); + _ftprintf(h, _T("\n// Gamma to correct with\n")); + FLT(nGamma); + _ftprintf(h, _T("\n// If non-zero, auto-switch to fullscreen after loading game\n")); + VAR(bVidAutoSwitchFull); + _ftprintf(h, _T("\n// If non-zero, allow stretching of the image to any size\n")); + VAR(bVidFullStretch); + _ftprintf(h, _T("\n// If non-zero, stretch the image to the largest size preserving aspect ratio\n")); + VAR(bVidCorrectAspect); + _ftprintf(h, _T("\n// If non-zero, try to use a triple buffer in fullscreen\n")); + VAR(bVidTripleBuffer); + _ftprintf(h, _T("\n// If non-zero, try to synchronise blits with the display\n")); + VAR(bVidVSync); + _ftprintf(h, _T("\n// If non-zero, try to enable custom DWM parameters on Windows 7, this fixes frame stuttering problems.\n")); + VAR(bVidDWMCore); + _ftprintf(h, _T("\n// Transfer method: 0 = blit from system memory / use driver/DirectX texture management;\n")); + _ftprintf(h, _T("// 1 = copy to a video memory surface, then use bltfast();\n")); + _ftprintf(h, _T("// -1 = autodetect for DirectDraw, equals 1 for Direct3D\n")); + VAR(nVidTransferMethod); + _ftprintf(h, _T("\n// If non-zero, draw scanlines to simulate a low-res monitor\n")); + VAR(bVidScanlines); + _ftprintf(h, _T("\n// Maximum scanline intensity\n")); + VAR(nVidScanIntensity); + _ftprintf(h, _T("\n// If non-zero, rotate scanlines and RGB effects for rotated games\n")); + VAR(bVidScanRotate); + _ftprintf(h, _T("\n// The selected blitter module\n")); + VAR(nVidSelect); + _ftprintf(h, _T("\n// Options for the blitter modules\n")); + VAR(nVidBlitterOpt[0]); + VAR64(nVidBlitterOpt[1]); + VAR(nVidBlitterOpt[2]); + VAR(nVidBlitterOpt[3]); + VAR(nVidBlitterOpt[4]); + _ftprintf(h, _T("\n// If non-zero, attempt to auto-detect the monitor aspect ratio\n")); + VAR(bMonitorAutoCheck); + _ftprintf(h, _T("\n// The aspect ratio of the monitor\n")); + VAR(nVidScrnAspectX); + VAR(nVidScrnAspectY); + _ftprintf(h, _T("\n// If non-zero, force all games to use a 60Hz refresh rate\n")); + VAR(bForce60Hz); + _ftprintf(h, _T("\n// If non-zero, skip frames when needed to keep the emulation running at full speed\n")); + VAR(bAlwaysDrawFrames); + + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- DirectDraw blitter module settings -------------------------------------\n")); + _ftprintf(h, _T("\n// If non-zero, draw scanlines at 50%% intensity\n")); + VAR(bVidScanHalf); + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- Direct3D 7 blitter module settings -------------------------------------\n")); + _ftprintf(h, _T("\n// If non-zero, use bi-linear filtering to display the image\n")); + VAR(bVidBilinear); + _ftprintf(h, _T("\n// If non-zero, simulate slow phosphors (feedback)\n")); + VAR(bVidScanDelay); + _ftprintf(h, _T("\n// If non-zero, use bi-linear filtering for the scanlines\n")); + VAR(bVidScanBilinear); + _ftprintf(h, _T("\n// Feedback amount for slow phosphor simulation\n")); + VAR(nVidFeedbackIntensity); + _ftprintf(h, _T("\n// Oversaturation amount for slow phosphor simulation\n")); + VAR(nVidFeedbackOverSaturation); + _ftprintf(h, _T("\n// Angle at wich the emulated screen is tilted (in radians)\n")); + FLT(fVidScreenAngle); + _ftprintf(h, _T("\n// Angle of the sphere segment used for the 3D screen (in radians)\n")); + FLT(fVidScreenCurvature); + _ftprintf(h, _T("\n// If non-zero, force 16 bit emulation even in 32-bit screenmodes\n")); + VAR(bVidForce16bit); + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- DirectX Graphics 9 blitter module settings -----------------------------\n")); + _ftprintf(h, _T("\n// The filter parameters for the cubic filter\n")); + FLT(dVidCubicB); + FLT(dVidCubicC); + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- DirectX Graphics 9 Alt blitter module settings -------------------------\n")); + _ftprintf(h, _T("\n// If non-zero, use bi-linear filtering to display the image\n")); + VAR(bVidDX9Bilinear); + _ftprintf(h, _T("\n// If non-zero, use hardware vertex to display the image\n")); + VAR(bVidHardwareVertex); + _ftprintf(h, _T("\n// If non-zero, use motion blur to display the image\n")); + VAR(bVidMotionBlur); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- Sound ------------------------------------------------------------------\n")); + _ftprintf(h, _T("\n// The selected audio plugin\n")); + VAR(nAudSelect); + _ftprintf(h, _T("\n// Number of frames in sound buffer (= sound lag)\n")); + VAR(nAudSegCount); + _ftprintf(h, _T("\n// The order of PCM/ADPCM interpolation\n")); + VAR(nInterpolation); + _ftprintf(h, _T("\n// The order of FM interpolation\n")); + VAR(nFMInterpolation); + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- DirectSound plugin settings --------------------------------------------\n")); + _ftprintf(h, _T("\n// Sample rate\n")); + VAR(nAudSampleRate[0]); + _ftprintf(h, _T("\n// DSP module to use for sound enhancement: 0 = none, 1 = low-pass filter\n")); + VAR(nAudDSPModule[0]); + _ftprintf(h, _T("\n")); + _ftprintf(h, _T("// --- XAudio2 plugin settings ------------------------------------------------\n")); + _ftprintf(h, _T("\n// Sample rate\n")); + VAR(nAudSampleRate[1]); + _ftprintf(h, _T("\n// DSP module to use for sound enhancement: 0 = none, 1 = low-pass filter, 2 = reverb\n")); + VAR(nAudDSPModule[1]); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- UI ---------------------------------------------------------------------\n")); + + _ftprintf(h, _T("\n// Filename of the active UI translation template\n")); + STR(szLocalisationTemplate); + + _ftprintf(h, _T("\n// 1 = display pause/record/replay/kaillera icons in the upper right corner of the display\n")); + VAR(nVidSDisplayStatus); + _ftprintf(h, _T("\n// Minimum height (in pixels) of the font used for the Kaillera chat function (used for arcade resolution)\n")); + VAR(nMinChatFontSize); + _ftprintf(h, _T("\n// Maximum height (in pixels) of the font used for the Kaillera chat function (used for 1280x960 or higher).\n")); + VAR(nMaxChatFontSize); + + _ftprintf(h, _T("\n// Make the menu modeless\n")); + VAR(bModelessMenu); + + _ftprintf(h, _T("\n// Minimum length of time to display the splash screen (in milliseconds)\n")); + VAR(nSplashTime); + + _ftprintf(h, _T("\n// If non-zero, load and save all ram (the state)\n")); + VAR(bDrvSaveAll); + _ftprintf(h, _T("\n// The thread priority for the application. Do *NOT* edit this manually\n")); + VAR(nAppThreadPriority); + _ftprintf(h, _T("\n// If non-zero, process keyboard input even when the application loses focus\n")); + VAR(bAlwaysProcessKeyboardInput); + _ftprintf(h, _T("\n// If non-zero, pause when the application loses focus\n")); + VAR(bAutoPause); + _ftprintf(h, _T("\n// If non-zero, save the inputs for each game\n")); + VAR(bSaveInputs); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- CD emulation -----------------------------------------------------------\n")); + _ftprintf(h, _T("\n // The selected CD emulation module\n")); + VAR(nCDEmuSelect); + _ftprintf(h, _T("\n // The path to the CD image to use (.cue or .iso)\n")); + STR(CDEmuImage); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- Load Game Dialogs ------------------------------------------------------\n")); + _ftprintf(h, _T("\n// Load game dialog options\n")); + VAR(nLoadMenuShowX); + + _ftprintf(h, _T("\n// Load game dialog board type filter options\n")); + VAR(nLoadMenuBoardTypeFilter); + + _ftprintf(h, _T("\n// Load game dialog genre filter options\n")); + VAR(nLoadMenuGenreFilter); + + _ftprintf(h, _T("\n// Load game dialog family filter options\n")); + VAR(nLoadMenuFamilyFilter); + + _ftprintf(h, _T("\n// The paths to search for rom zips (include trailing backslash)\n")); + STR(szAppRomPaths[0]); + STR(szAppRomPaths[1]); + STR(szAppRomPaths[2]); + STR(szAppRomPaths[3]); + STR(szAppRomPaths[4]); + STR(szAppRomPaths[5]); + STR(szAppRomPaths[6]); + STR(szAppRomPaths[7]); + + _ftprintf(h, _T("\n// The path to search for Neo Geo CDZ isos\n")); + STR(szNeoCDGamesDir); + + _ftprintf(h, _T("\n// The paths to search for support files (include trailing backslash)\n")); + STR(szAppPreviewsPath); + STR(szAppTitlesPath); + STR(szAppCheatsPath); + STR(szAppHiscorePath); + STR(szAppSamplesPath); + STR(szAppIpsPath); + STR(szNeoCDCoverDir); + + _ftprintf(h, _T("\n// The cartridges to use for emulation of an MVS system\n")); + DRV(nBurnDrvSelect[0]); + DRV(nBurnDrvSelect[1]); + DRV(nBurnDrvSelect[2]); + DRV(nBurnDrvSelect[3]); + DRV(nBurnDrvSelect[4]); + DRV(nBurnDrvSelect[5]); + + _ftprintf(h, _T("\n// Neo Geo CD Load Game Dialog options\n")); + VAR(bNeoCDListScanSub); + VAR(bNeoCDListScanOnlyISO); + + _ftprintf(h, _T("\n\n\n")); + _ftprintf(h, _T("// --- miscellaneous ---------------------------------------------------------\n")); + + _ftprintf(h, _T("\n// If non-zero, don't change the status of the Num Lock key.\n")); + VAR(bNoChangeNumLock); + + _ftprintf(h, _T("\n// If non-zero, enable high score saving support.\n")); + VAR(EnableHiscores); + + _ftprintf(h, _T("\n// The language index to use for the IPS Patch Manager dialog.\n")); + VAR(nIpsSelectedLanguage); + + _ftprintf(h, _T("\n// Previous games list.\n")); + STR(szPrevGames[0]); + STR(szPrevGames[1]); + STR(szPrevGames[2]); + STR(szPrevGames[3]); + STR(szPrevGames[4]); + STR(szPrevGames[5]); + STR(szPrevGames[6]); + STR(szPrevGames[7]); + STR(szPrevGames[8]); + STR(szPrevGames[9]); + + _ftprintf(h, _T("\n// Player default controls, number is the index of the configuration in the input dialog\n")); + VAR(nPlayerDefaultControls[0]); + STR(szPlayerDefaultIni[0]); + VAR(nPlayerDefaultControls[1]); + STR(szPlayerDefaultIni[1]); + VAR(nPlayerDefaultControls[2]); + STR(szPlayerDefaultIni[2]); + VAR(nPlayerDefaultControls[3]); + STR(szPlayerDefaultIni[3]); + + _ftprintf(h, _T("\n\n\n")); + +#undef DRV +#undef STR +#undef FLT +#undef VAR +#undef VAR64 + + fclose(h); + return 0; +} + diff --git a/src/burner/win32/debugger.cpp b/src/burner/win32/debugger.cpp new file mode 100644 index 00000000..b4f42a33 --- /dev/null +++ b/src/burner/win32/debugger.cpp @@ -0,0 +1,1571 @@ +#include "burner.h" + +HWND hDbgDlg = NULL; + +#if defined (FBA_DEBUG) + +#include "sek.h" +#include "sekdebug.h" +#include "richedit.h" + +static bool bLargeWindow; +static bool bOldPause; + +static HFONT hCommandFont = NULL; +static unsigned int nMouseWheelScrollLines; + +static unsigned int nActiveWindow; +static unsigned int nDisassWindow; +static unsigned int nMemdumpWindow; + +static int nDisassCPUType; + +static unsigned int nDisassAddress[16]; +static int nDisassArea; +static int nDisassAttrib; + +static int nMemdumpAddress; +static int nMemdumpArea; +static int nMemdumpAttrib; + +static bool bBreakpointHit; + +struct DbgM68000State { + unsigned int a[8]; unsigned int d[8]; + unsigned int pc; + unsigned int sr; + unsigned int sp; unsigned int usp; unsigned int isp; unsigned int msp; + unsigned int vbr; + unsigned int sfc; unsigned int dfc; + unsigned int cacr; unsigned int caar; + + unsigned int irq; +}; + +static DbgM68000State curr_m68000, prev_m68000; + +static int nDbgMemoryAreaCount; +static int nDbgCurrentMemoryArea; +static struct BurnArea* DbgMemoryAreaInfo = NULL; + +// ---------------------------------------------------------------------------- +// Callbacks for m68k's disassembler + +static unsigned int DbgFetchByte(unsigned int nAddress) { return SekFetchByte(nAddress); } +static unsigned int DbgFetchWord(unsigned int nAddress) { return SekFetchWord(nAddress); } +static unsigned int DbgFetchLong(unsigned int nAddress) { return SekFetchLong(nAddress); } + +static unsigned int DbgFetchByteArea(unsigned int nAddress) +{ + if (nAddress < DbgMemoryAreaInfo[nDisassArea].nLen) { + return ((unsigned char*)(DbgMemoryAreaInfo[nDisassArea].Data))[nAddress ^ nDisassAttrib]; + } + + return 0; +} +static unsigned int DbgFetchWordArea(unsigned int nAddress) +{ + return (DbgFetchByteArea(nAddress) << 8) | DbgFetchByteArea(nAddress + 1); +} +static unsigned int DbgFetchLongArea(unsigned int nAddress) +{ + return (DbgFetchWordArea(nAddress) << 16) | DbgFetchWordArea(nAddress + 2); +} + +// ---------------------------------------------------------------------------- +// Message pump used when a breakpoint is hit + +static void BreakpointMessagePump() +{ + MSG msg; + + while (GetMessage(&msg, NULL, 0, 0)) { + + if (IsDialogMessage(hDbgDlg, &msg)) { + continue; + } + if (msg.message == (WM_APP + 0)) { + bBreakpointHit = false; + return; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +// ---------------------------------------------------------------------------- +// Feedback functions + +static void InitFeedback(HWND hWindow) +{ + TCHAR szBuffer[16384] = _T(""); + TCHAR* pszBuf = szBuffer; + + // RTF header and initial settings + pszBuf += _stprintf(pszBuf, _T("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\fmodern\\charset0\\fprq0 Courier New;)}{\\colortbl\\red0\\green0\\blue0;\\red96\\green96\\blue96;\\red255\\green0\\blue0;\\red0\\green0\\blue255;}\\deflang1033\\horzdoc\\pard\\plain\\f0\\fs18\\cf2 Welcome to the FB Alpha debugger.\\par}")); + // Send the new data to the RichEdit control + SendMessage(hWindow, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer); +} + +static int AddFeedback(HWND hWindow, TCHAR* pszText) +{ +#ifdef UNICODE + SETTEXTEX settext = { ST_SELECTION, 1200 }; +#else + SETTEXTEX settext = { ST_SELECTION, 1252 }; +#endif + + // Add the new info to the top + SendMessage(hWindow, EM_SETSEL, (WPARAM)0, (LPARAM)0); + // Doesn't work if you send it Unicode data... + SendMessageA(hWindow, EM_SETTEXTEX, (WPARAM)&settext, (LPARAM)TCHARToANSI(pszText, NULL, 0)); + + // Trim the bottom lines + SendMessage(hWindow, EM_SETSEL, (WPARAM)SendMessage(hWindow, EM_LINEINDEX, 18, 0) - 1, (LPARAM)-1); + SendMessage(hWindow, EM_SETTEXTEX, (WPARAM)&settext, (LPARAM)_T("")); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Trace back instructions starting at a given address + +static unsigned int trace_pc, trace_size, trace_max; + +static void TraceBackDo(unsigned int start_pc, unsigned int trace_level, int cpu_type) +{ + unsigned int pc; + unsigned int trace; + + // Go over all possible instruction sizes (the longest 68020 instruction is 30 bytes) + for (unsigned int size = (cpu_type == M68K_CPU_TYPE_68000) ? 10 : 30; size != 0 ; size -= 2) { + pc = start_pc; + trace = trace_level; + + // Make sure we don't go past the start of memory + if (size > pc) { + break; + } + + // Check if there is a valid instruction at the current address + if (m68k_is_valid_instruction(SekFetchWord(pc - size), cpu_type) != 0) { + char buf[100] = ""; + + // Check if the instruction at the current address has the right size + if (m68k_disassemble(buf, pc - size, cpu_type) == size) { + pc -= size; + trace++; + + // Update best result + if (trace_size < trace) { + trace_size = trace; + trace_pc = pc; + } + + // Recurse until we've traced back enough instructions + if (trace < trace_max) { + TraceBackDo(pc, trace, cpu_type); + } + } + } + } +} + +static unsigned int TraceBack(unsigned int nStartAddress, unsigned int nTotalInstructions, int nCPU) +{ + unsigned int pc = nStartAddress; + unsigned int trace = nTotalInstructions; + + if (nStartAddress == 0 || nTotalInstructions == 0) { + return 0; + } + + // If there's no valid instruction at the start adress, increase it + while (m68k_is_valid_instruction(SekFetchWord(pc), nCPU) == 0 && (pc - nStartAddress) < ((nCPU == M68K_CPU_TYPE_68000) ? 10 : 30) - 2) { + pc += 2; + } + + do { + trace_size = 0; + trace_pc = pc; + // Trace back a few extra instructions to ensure we'll return a valid code path + trace_max = trace + 4; + + TraceBackDo(pc, 0, nCPU); + + pc -= 2; + + } while (trace_size == 0 && pc >= nStartAddress); + + pc = trace_pc; + + // If we've traced back more instructions than needed, skip the extra ones + while (trace_size > trace) { + char buf[100] = ""; + pc += m68k_disassemble(buf, pc, nCPU); + trace++; + } + + // If we can't trace back at all, simply decrease the address + if (trace_size == 0) { + return nTotalInstructions * 2 < nStartAddress ? nStartAddress - nTotalInstructions * 2 : 0; + } + + return pc; +} + +// ---------------------------------------------------------------------------- +// Write a disassembly to a file + +static int CreateDisassFile(TCHAR* filename, unsigned int start, unsigned int end, int nCPU) +{ + unsigned int size; + unsigned int pc = start; + FILE* fp = _tfopen(filename, _T("wt")); + + if (fp == NULL) { + return 1; + } + + // Print the disassembly + while (pc <= end) { + char buf[100] = ""; + unsigned int j; + + if (pc > 0x00FFFFFE) { + break; + } + + // Get the mnemonic + size = m68k_disassemble(buf, pc, nCPU); + + // Print the address + _ftprintf(fp, _T("%06x "), pc); + + // Print the word values + if (nCPU == M68K_CPU_TYPE_68000) { + for (j = 10; j > size; j -= 2) { + _ftprintf(fp, _T(" ")); + } + for (j = 0; j < size; j += 2) { + _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); + } + } else { + if (size > 20) { + for (j = 0; j < 18; j += 2) { + _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); + } + _ftprintf(fp, _T("... ")); + } else { + for (j = 20; j > size; j -= 2) { + _ftprintf(fp, _T(" ")); + } + for (j = 0; j < size; j += 2) { + _ftprintf(fp, _T("%04x "), SekFetchWord(pc + j)); + } + } + } + + // Print the instruction + _ftprintf(fp, _T("%hs\n"), buf); + + pc += size; + } + + fclose(fp); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Create a disassembly in RTF format + +// Tabs are specified in twips (a single 16pt cell = 100twips) + +static void CreateDisass(HWND hWindow, unsigned int nAddress, int nCPU) +{ + int nPageSize = bLargeWindow ? 16 : 12; + TCHAR szBuffer[16384] = _T(""); + TCHAR* pszBuf = szBuffer; + unsigned int pc, nSize; + + pc = nAddress; + + // RTF header and initial settings + pszBuf += _stprintf(pszBuf, _T("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\fmodern\\charset0\\fprq0 Courier New;)}{\\colortbl\\red0\\green0\\blue0;\\red96\\green96\\blue96;\\red255\\green0\\blue0;\\red255\\green96\\blue96;\\red224\\green224\\blue224;}\\deflang1033\\horzdoc\\pard\\plain\\f0")); + if (bLargeWindow) { + if (nCPU == M68K_CPU_TYPE_68000) { + // Tabstops 5555 4444 3333 2222 1111 Mnemonic + pszBuf += _stprintf(pszBuf, _T("\\tx1050\\tx1513\\tx1976\\tx2429\\tx2892\\tx3450")); + } else { + // Tabstops 6666 5555 4444 3333 2222 1111 Mnemonic + pszBuf += _stprintf(pszBuf, _T("\\tx1050\\tx1435\\tx1820\\tx2205\\tx2590\\tx2975\\tx3450")); + } + // Indentation + pszBuf += _stprintf(pszBuf, _T("\\fi-4665\\li4665 ")); + } else { + // Tabstops + pszBuf += _stprintf(pszBuf, _T("\\tx735")); + } + + // Print the disassembly + for (int i = 0; i < nPageSize; i++) { + char buf[100] = ""; + unsigned int j; + unsigned int nCol; + + if (pc > 0x00FFFFFE) { + + do { + nDisassAddress[i++] = 0x00FFFFFE; + } while (i < nPageSize); + + break; + } + + nDisassAddress[i] = pc; + + // Get the mnemonic + nSize = m68k_disassemble(buf, pc, nCPU); + // Display the instruction at the current PC in red + nCol = (pc == SekDbgGetRegister(SEK_REG_PC)) ? 2 : 0; + + // Print the address + pszBuf += _stprintf(pszBuf, _T("\\fs%i\\cf%i %06x\t"), bLargeWindow ? 24 : 16, nCol, pc); + + if (bLargeWindow) { + // Print the word values + if (nCPU == M68K_CPU_TYPE_68000) { + // Print a filler + pszBuf += _stprintf(pszBuf, _T("\\fs16\\cf4 ")); + for (j = 10; j > nSize; j -= 2) { + pszBuf += _stprintf(pszBuf, _T(" -- \t")); + } + // Print the words that make up the instruction + pszBuf += _stprintf(pszBuf, _T("\\cf%i "), nCol + 1); + for (j = 0; j < nSize; j += 2) { + pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); + } + } else { + if (nSize > 12) { + // There's not enough room for all words, so print the first 5 words that make up the instruction + pszBuf += _stprintf(pszBuf, _T("\\fs13\\cf%i "), nCol + 1); + for (j = 0; j < 10; j += 2) { + pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); + } + // Print an ellipsis + pszBuf += _stprintf(pszBuf, _T("... \t")); + } else { + // Print a filler + pszBuf += _stprintf(pszBuf, _T("\\fs13\\cf4 ")); + for (j = 12; j > nSize; j -= 2) { + pszBuf += _stprintf(pszBuf, _T(" -- \t")); + } + // Print the words that make up the instruction + pszBuf += _stprintf(pszBuf, _T("\\cf%i "), nCol + 1); + for (j = 0; j < nSize; j += 2) { + pszBuf += _stprintf(pszBuf, _T("%04x\t"), SekFetchWord(pc + j)); + } + } + } + } + + // Colour Invalid instructions gray + if (nCol == 0) { + if (m68k_is_valid_instruction(SekFetchWord(pc), nCPU) == 0) { + nCol++; + } + } + // Print the instruction + pszBuf += _stprintf(pszBuf, _T("\\fs%i\\cf%i %hs\\par"), bLargeWindow ? 24 : 16, nCol, buf); + + pc += nSize; + } + pszBuf += _stprintf(pszBuf, _T("}\0")); + + // Send the new data to the RichEdit control + SendMessage(hWindow, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer); + +#if 0 + FILE* fp = _tfopen(_T("disass.rtf"), _T("wb")); + if (fp) { + fwrite(szBuffer, 1, _tcslen(szBuffer), fp); + fclose(fp); + } +#endif +} + +// ---------------------------------------------------------------------------- +// Create a memory dump in RTF format + +static unsigned int DbgReadByteArea(unsigned int nAddress) +{ + if (nAddress < DbgMemoryAreaInfo[nDbgCurrentMemoryArea].nLen) { + return ((unsigned char*)(DbgMemoryAreaInfo[nDbgCurrentMemoryArea].Data))[nAddress ^ nMemdumpAttrib]; + } + + return 0; +} + +static void CreateMemdump(HWND hWindow, int nArea, unsigned int nAddress) +{ + int nPageSize = bLargeWindow ? 16 : 12; + unsigned int (*DbgReadByte)(unsigned int); + TCHAR szBuffer[16384] = _T(""); + TCHAR* pszBuf = szBuffer; + unsigned int pc; + + nDbgCurrentMemoryArea = nArea; + + if (nDbgCurrentMemoryArea) { + DbgReadByte = DbgReadByteArea; + } else { + DbgReadByte = SekReadByte; + } + + pc = nAddress; + + // RTF header and initial settings + pszBuf += _stprintf(pszBuf, _T("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\fmodern\\fprq0 Courier New\\cpg1252;)}{\\colortbl\\red96\\green96\\blue96;\\red255\\green255\\blue255;\\red0\\green0\\blue0;\\red160\\green160\\blue160;\\red0\\green0\\blue0;\\red224\\green224\\blue224;}\\deflang1033\\horzdoc\\pard\\f0\\plain")); + + if (bLargeWindow) { + // Tabstops 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF abcdefghijklnmop + pszBuf += _stprintf(pszBuf, _T("\\tx1050\\tx1375\\tx1700\\tx2025\\tx2400\\tx2725\\tx3050\\tx3375\\tx3750\\tx4075\\tx4400\\tx4725\\tx5100\\tx5425\\tx5750\\tx6075\\tx6500")); + + // Print the memory dump + for (int i = 0; i < nPageSize; i++, pc += 16) { + pszBuf += _stprintf(pszBuf, _T("\\cf4 %06x\t"), pc); + for (int j = 0; j < 16; j += 2) { + pszBuf += _stprintf(pszBuf, _T("\\cf0\\cb1 %02x\t\\cf2\\cb3 %02x\t"), DbgReadByte(pc + j), DbgReadByte(pc + j + 1)); + } + pszBuf += _stprintf(pszBuf, _T("\\cf4 ")); + for (int j = 0; j < 16; j++) { + unsigned char c = DbgReadByte(pc + j); + + if (c == 0x00 || (c >= 0x09 && c <= 0x0D)) { + pszBuf += _stprintf(pszBuf, _T("{\\cf5 -}")); + } else { + pszBuf += _stprintf(pszBuf, _T("\\\'%02x"), c); + } + } + pszBuf += _stprintf(pszBuf, _T("\\par ")); + } + pszBuf += _stprintf(pszBuf, _T("}\0")); + } else { + pszBuf += _stprintf(pszBuf, _T("\\fs16")); + for (int i = 0; i < nPageSize; i++, pc += 16) { + pszBuf += _stprintf(pszBuf, _T("\\cf4 %06x "), pc); + for (int j = 0; j < 16; j += 2) { + pszBuf += _stprintf(pszBuf, _T("\\cf0\\cb1 %02x\\cf2\\cb3 %02x"), DbgReadByte(pc + j), DbgReadByte(pc + j + 1)); + } + pszBuf += _stprintf(pszBuf, _T("\\cf4 ")); + for (int j = 0; j < 16; j++) { + unsigned char c = DbgReadByte(pc + j); + + if (c == 0x00 || (c >= 0x09 && c <= 0x0D)) { + pszBuf += _stprintf(pszBuf, _T("{\\cf5 -}")); + } else { + pszBuf += _stprintf(pszBuf, _T("\\\'%02x"), c); + } + } + pszBuf += _stprintf(pszBuf, _T("\\par ")); + } + pszBuf += _stprintf(pszBuf, _T("}\0")); + } + + // Send the new data to the RichEdit control + SendMessage(hWindow, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer); + +#if 0 + FILE* fp = _tfopen(_T("memdump.rtf"), _T("wb")); + if (fp) { + fwrite(szBuffer, 1, _tcslen(szBuffer), fp); + fclose(fp); + } +#endif +} + +// ---------------------------------------------------------------------------- +// Memory area setup + +static int __cdecl GetMemoryAcb(struct BurnArea* pba) +{ + TCHAR szAreaName[256] = _T(""); + + memcpy(DbgMemoryAreaInfo + nDbgMemoryAreaCount, pba, sizeof(BurnArea)); + + _stprintf(szAreaName, _T("%hs - %x bytes"), pba->szName, pba->nLen); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP1, CB_ADDSTRING, 0, (LPARAM)szAreaName); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP1, CB_ADDSTRING, 0, (LPARAM)szAreaName); + + nDbgMemoryAreaCount++; + + return 0; +} + +static int GetMemoryAreas() +{ + nDbgMemoryAreaCount = 1; + DbgMemoryAreaInfo = (BurnArea*)malloc(256 * sizeof(BurnArea)); + if (DbgMemoryAreaInfo == NULL) { + return 1; + } + + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP1, CB_ADDSTRING, 0, (LPARAM)_T("Main CPU memory map")); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP1, CB_ADDSTRING, 0, (LPARAM)_T("Main CPU memory map")); + + BurnAcb = GetMemoryAcb; + BurnAreaScan(ACB_MEMORY_ROM | ACB_NVRAM | ACB_MEMCARD | ACB_MEMORY_RAM | ACB_READ, NULL); + + return 0; +} + +static int SetupDisass(int nArea) +{ + nDisassAddress[0] = 0; + nDisassArea = nArea; + nDisassAttrib = 0; + + nDisassCPUType = SekDbgGetCPUType(); + + if (nDisassArea) { + SekDbgFetchByteDisassembler = DbgFetchByteArea; + SekDbgFetchWordDisassembler = DbgFetchWordArea; + SekDbgFetchLongDisassembler = DbgFetchLongArea; + } else { + SekDbgFetchByteDisassembler = DbgFetchByte; + SekDbgFetchWordDisassembler = DbgFetchWord; + SekDbgFetchLongDisassembler = DbgFetchLong; + + nDisassAddress[0] = TraceBack(SekDbgGetRegister(SEK_REG_PC), 5, nDisassCPUType); + } + + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), nDisassAddress[0], nDisassCPUType); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP1, CB_SETCURSEL, (WPARAM)nDisassArea, (LPARAM)0); + + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); + if (nArea) { + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 8-bit / big-endian")); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 16-bit")); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 32-bit")); + } else { + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("Auto")); + } + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN1_DRP2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); + + return 0; +} + +static int SetupMemdump(int nArea) +{ + nMemdumpArea = nArea; + nMemdumpAddress = 0x000000; + nMemdumpAttrib = 0; + + CreateMemdump(GetDlgItem(hDbgDlg, nMemdumpWindow), nMemdumpArea, nMemdumpAddress); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP1, CB_SETCURSEL, (WPARAM)nMemdumpArea, (LPARAM)0); + + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0); + if (nArea) { + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 8-bit / big-endian")); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 16-bit")); + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("little-endian 32-bit")); + } else { + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_ADDSTRING, (WPARAM)0, (LPARAM)_T("Auto")); + } + SendDlgItemMessage(hDbgDlg, IDC_DBG_MAINWN2_DRP2, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); + + return 0; +} + +// ---------------------------------------------------------------------------- +// Create CPU info in RTF format + +int UpdateCPUState(DbgM68000State* Curr_M68000) { + Curr_M68000->a[0] = SekDbgGetRegister(SEK_REG_A0); + Curr_M68000->a[1] = SekDbgGetRegister(SEK_REG_A1); + Curr_M68000->a[2] = SekDbgGetRegister(SEK_REG_A2); + Curr_M68000->a[3] = SekDbgGetRegister(SEK_REG_A3); + Curr_M68000->a[4] = SekDbgGetRegister(SEK_REG_A4); + Curr_M68000->a[5] = SekDbgGetRegister(SEK_REG_A5); + Curr_M68000->a[6] = SekDbgGetRegister(SEK_REG_A6); + Curr_M68000->a[7] = SekDbgGetRegister(SEK_REG_A7); + + Curr_M68000->d[0] = SekDbgGetRegister(SEK_REG_D0); + Curr_M68000->d[1] = SekDbgGetRegister(SEK_REG_D1); + Curr_M68000->d[2] = SekDbgGetRegister(SEK_REG_D2); + Curr_M68000->d[3] = SekDbgGetRegister(SEK_REG_D3); + Curr_M68000->d[4] = SekDbgGetRegister(SEK_REG_D4); + Curr_M68000->d[5] = SekDbgGetRegister(SEK_REG_D5); + Curr_M68000->d[6] = SekDbgGetRegister(SEK_REG_D6); + Curr_M68000->d[7] = SekDbgGetRegister(SEK_REG_D7); + + Curr_M68000->pc = SekDbgGetRegister(SEK_REG_PC); + Curr_M68000->sr = SekDbgGetRegister(SEK_REG_SR); + + Curr_M68000->sp = SekDbgGetRegister(SEK_REG_SP); + Curr_M68000->usp = SekDbgGetRegister(SEK_REG_USP); + Curr_M68000->isp = SekDbgGetRegister(SEK_REG_ISP); + + Curr_M68000->irq = SekDbgGetPendingIRQ(); + + return 0; +} + +static void CreateCPUInfo(HWND hWindow, bool bUpdate, DbgM68000State* Curr_M68000, DbgM68000State* Prev_M68000) +{ + int col; + TCHAR szBuffer[16384] = _T(""); + TCHAR* pszBuf = szBuffer; + + int curr_sr, diff_sr; + + if (bUpdate) { + UpdateCPUState(Curr_M68000); + } + + curr_sr = Curr_M68000->sr; + diff_sr = Prev_M68000->sr ^ curr_sr; + + // RTF header and initial settings + pszBuf += _stprintf(pszBuf, _T("{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\fmodern\\fprq0 Courier New\\cpg1252;)}{\\colortbl\\red0\\green0\\blue0;\\red128\\green128\\blue128;\\red255\\green0\\blue0;\\red255\\green96\\blue96;}\\deflang1033\\horzdoc\\pard\\f0\\plain")); + // Tabstops + if (bLargeWindow) { + pszBuf += _stprintf(pszBuf, _T("\\tx1950\\fs24 ")); + } else { + pszBuf += _stprintf(pszBuf, _T("\\tx1365\\fs16 ")); + } + + // Print SR + pszBuf += _stprintf(pszBuf, _T("SR ")); + if (nDisassCPUType >= M68K_CPU_TYPE_68EC020) { + // T + if (diff_sr & 0xC000) { + pszBuf += _stprintf(pszBuf, _T("\\cf%i T%i"), (diff_sr & 0xC000) ? 2 : 0, curr_sr >> 14); + } else { + pszBuf += _stprintf(pszBuf, _T("\\cf%i \\\'95\\\'95"), (diff_sr & 0xC000) ? 2 : 0); + } + } else { + // T + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x8000) ? 2 : 0, (curr_sr & 0x8000) ? _T("T") : _T("\\\'95")); + // Unused + pszBuf += _stprintf(pszBuf, _T("{\\cf1\\\'B7}")); + } + // S + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x2000) ? 2 : 0, (curr_sr & 0x2000) ? _T("S") : _T("\\\'95")); + if (nDisassCPUType >= M68K_CPU_TYPE_68EC020) { + // M + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x1000) ? 2 : 0, (curr_sr & 0x1000) ? _T("M") : _T("\\\'95")); + } else { + // Unused + pszBuf += _stprintf(pszBuf, _T("{\\cf1\\\'B7}")); + } + // Unused + pszBuf += _stprintf(pszBuf, _T("{\\cf1\\\'B7}")); + // I + pszBuf += _stprintf(pszBuf, _T("\\cf%i IM%i"), (diff_sr & 0x0700) ? 2 : 0, (curr_sr & 0x0700) >> 8); + // Unused + pszBuf += _stprintf(pszBuf, _T("{\\cf1\\\'B7\\\'B7\\\'B7}")); + // X + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x10) ? 2 : 0, (curr_sr & 0x10) ? _T("X") : _T("\\\'95")); + // N + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x08) ? 2 : 0, (curr_sr & 0x08) ? _T("N") : _T("\\\'95")); + // Z + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x04) ? 2 : 0, (curr_sr & 0x04) ? _T("Z") : _T("\\\'95")); + // V + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s"), (diff_sr & 0x02) ? 2 : 0, (curr_sr & 0x02) ? _T("V") : _T("\\\'95")); + // C + pszBuf += _stprintf(pszBuf, _T("\\cf%i %s "), (diff_sr & 0x01) ? 2 : 0, (curr_sr & 0x01) ? _T("C") : _T("\\\'95")); + // Hex value + pszBuf += _stprintf(pszBuf, _T("\\cf%i %02x\\cf%i %02x\\par "), (diff_sr & 0xFF00) ? 2 : 0, curr_sr >> 8, (diff_sr & 0xFF) ? 2 : 0, curr_sr & 0xFF); + +#if 1 + // Print pending IRQ + { + int s1, s2; + + if (bLargeWindow) { + s1 = 16; + s2 = 22; + } else { + s1 = 12; + s2 = 14; + } + if (Curr_M68000->irq & 7) { + pszBuf += _stprintf(pszBuf, _T("\\cf0 IRQ %i{\\fs%i \\fs%i\\cf1 pending}\t"), Curr_M68000->irq & 7, s1, s2); + } else { + pszBuf += _stprintf(pszBuf, _T("\\cf1 IRQ 0{\\fs%i \\fs%i pending}\t"), s1, s2); + } + } +#else + if (nDisassCPUType >= M68K_CPU_TYPE_68010) { + // Print SFC/DFC + col = (Curr_M68000->sfc ^ Prev_M68000->sfc) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 SFC \\cf%i %i "), col + 1, Curr_M68000->sfc); + col = (Curr_M68000->dfc ^ Prev_M68000->dfc) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 DFC \\cf%i %i "), col + 1, Curr_M68000->dfc); + } else { + pszBuf += _stprintf(pszBuf, _T(" ")); + } +#endif + + // Print PC + col = (Curr_M68000->pc ^ Prev_M68000->pc) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 PC \\cf%i %02x\\cf%i %06x\\par\\par "), col + 1, Curr_M68000->pc >> 24, col, Curr_M68000->pc & 0x00FFFFFF); + + // Print data and address registers + for (int i = 0; i < 8; i++) { + col = (Curr_M68000->d[i] ^ Prev_M68000->d[i]) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 D%i \\cf%i %08x "), i, col, Curr_M68000->d[i]); + + col = (Curr_M68000->a[i] ^ Prev_M68000->a[i]) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 A%i \\cf%i %02x\\cf%i %06x\\par "), i, col + 1, Curr_M68000->a[i] >> 24, col, Curr_M68000->a[i] & 0x00FFFFFF); + } + pszBuf += _stprintf(pszBuf, _T("\\par")); + + if (nDisassCPUType >= M68K_CPU_TYPE_68EC020) { + // Print vector base register + col = (Curr_M68000->vbr ^ Prev_M68000->vbr) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 VBR \\cf%i %02x\\cf%i %06x "), col + 1, Curr_M68000->vbr >> 24, col, Curr_M68000->vbr & 0x00FFFFFF); + // Print master stack pointer + col = (Curr_M68000->msp ^ Prev_M68000->msp) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 MSP \\cf%i %02x\\cf%i %06x\\par "), col + 1, Curr_M68000->msp >> 24, col, Curr_M68000->msp & 0x00FFFFFF); + } + + // Print interrupt stack pointer + col = (Curr_M68000->isp ^ Prev_M68000->isp) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 ISP \\cf%i %02x\\cf%i %06x "), col + 1, Curr_M68000->isp >> 24, col, Curr_M68000->isp & 0x00FFFFFF); + // Print user stack pointer + col = (Curr_M68000->usp ^ Prev_M68000->usp) ? 2 : 0; + pszBuf += _stprintf(pszBuf, _T("\\cf0 USP \\cf%i %02x\\cf%i %06x\\par "), col + 1, Curr_M68000->usp >> 24, col, Curr_M68000->usp & 0x00FFFFFF); + + // Cycles done this frame + pszBuf += _stprintf(pszBuf, _T("\\par\\cf0 cycle%7i "), SekTotalCycles()); + if (nSekCyclesScanline) { + pszBuf += _stprintf(pszBuf, _T("scanline %3i\\par"), SekCurrentScanline()); + } else { + pszBuf += _stprintf(pszBuf, _T("\\cf1 scanline ---\\par")); + } + + SendMessage(hWindow, WM_SETTEXT, (WPARAM)0, (LPARAM)szBuffer); + + if (bUpdate) { + memcpy(Prev_M68000, Curr_M68000, sizeof(DbgM68000State)); + } + +#if 0 + FILE* fp = _ftopen(_T("cpuinfo.rtf"), _T("wb"); + if (fp) { + fwrite(szBuffer, 1, strlen(szBuffer), fp); + fclose(fp); + } +#endif +} + +// ---------------------------------------------------------------------------- +// Callbacks for when a breakpoint is hit + +void BreakpointProcessing(TCHAR* pszMessage) +{ + bBreakpointHit = true; + AudBlankSound(); + + // Make sure single stepping is disabled + SekDbgEnableBreakpoints(); + + // Update the feedback area + AddFeedback(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN2), pszMessage); + + // Update info + CreateCPUInfo(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN1), true, &curr_m68000, &prev_m68000); + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), TraceBack(SekDbgGetRegister(SEK_REG_PC), 5, nDisassCPUType), nDisassCPUType); + + SetWindowText(GetDlgItem(hDbgDlg, IDC_DBG_GO), _T("Go!")); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPFRAME), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPINTO), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEP), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_SKIP), TRUE); + + // Activate message pump + BreakpointMessagePump(); +} + +void BreakpointHitRead(unsigned int address, int breakpoint) +{ + TCHAR szBuffer[256] = _T(""); + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;\\red0\\green0\\blue255;}\\pard\\f0\\fs20\\cf1 Breakpoint R%i! read <- %06x\\par}"), breakpoint, address); + + BreakpointProcessing(szBuffer); +} + +void BreakpointHitFetch(unsigned int address, int breakpoint) +{ + TCHAR szBuffer[256] = _T(""); + + if (breakpoint == 0) { + + // Remove step into breakpoint + SekDbgSetBreakpointFetch(0, 0); + + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;\\red0\\green0\\blue255;}\\pard\\f0\\fs20\\cf1 Step complete! PC == %06x\\par}"), address); + } else { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;\\red0\\green0\\blue255;}\\pard\\f0\\fs20\\cf1 Breakpoint P%i! PC == %06x\\par}"), breakpoint, address); + } + + BreakpointProcessing(szBuffer); +} + +void BreakpointHitWrite(unsigned int address, int breakpoint) +{ + TCHAR szBuffer[256] = _T(""); + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;\\red0\\green0\\blue255;}\\pard\\f0\\fs20\\cf1 Breakpoint W%i! write -> %06x\\par}"), breakpoint, address); + + BreakpointProcessing(szBuffer); +} + +// ---------------------------------------------------------------------------- +// Command parsing + +static int cmd_exit(TCHAR* /*arg*/) +{ + SendMessage(hDbgDlg, WM_CLOSE, 0, 0); + + return 0; +} + +static int cmd_disass(TCHAR* arg) +{ + TCHAR* pos = arg; + long address; + + // Check if we need to write to a file + if (*pos == _T('>')) { + unsigned int start, end; + TCHAR filename[MAX_PATH] = _T(""); + TCHAR* fn; + + pos++; + + SKIP_WS(pos); + + fn = pos; + + if (*pos == _T('\"')) { + fn++; + pos++; + FIND_QT(pos); + _tcsncpy(filename, fn, pos - fn); + pos++; + } else { + FIND_WS(pos); + _tcsncpy(filename, fn, pos - fn); + } + + start = _tcstol(pos, &pos, 16); + end = _tcstol(pos, &pos, 16); + + CreateDisassFile(filename, start, end, nDisassCPUType); + + return 0; + } + + // Just set the active window when no arguments are specified + if (*pos == _T('\0')) { + nActiveWindow = nDisassWindow; + + return 0; + } + + // Check for keywords + if (!_tcsicmp(pos, _T("pc"))) { + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), TraceBack(SekDbgGetRegister(SEK_REG_PC), 5, nDisassCPUType), nDisassCPUType); + + nActiveWindow = nDisassWindow; + + return 0; + } + + // Disassemble to the window + address = _tcstol(pos, &pos, 16); + if (address > 0x00FFFFFE || address < 0) { + return 1; + } + + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), address & 0xFFFFFE, nDisassCPUType); + + nActiveWindow = nDisassWindow; + + return 0; +} + +static int cmd_memdump(TCHAR* arg) +{ + TCHAR* pos = arg; + long address = 0; + + // Just set the active window when no arguments are specified + if (*pos == _T('\0')) { + nActiveWindow = nMemdumpWindow; + + return 0; + } + + // Check for keywords + if (!_tcsicmp(pos, _T("pc"))) { + address = SekDbgGetRegister(SEK_REG_PC) - 5 * 16; + } + if (!_tcsicmp(pos, _T("sp"))) { + address = SekDbgGetRegister(SEK_REG_SP); + } + + if (!address) { + address = _tcstol(pos, &pos, 16); + } + + if (address > 0x00FFFFFE || address < 0) { + return 1; + } + + nMemdumpAddress = address; + CreateMemdump(GetDlgItem(hDbgDlg, nMemdumpWindow), nMemdumpArea, nMemdumpAddress); + + nActiveWindow = nMemdumpWindow; + + return 0; +} + +static int cmd_go(TCHAR* arg) +{ + TCHAR szBuffer[256]; + TCHAR* pos = arg; + long address = _tcstol(pos, &pos, 16); + + curr_m68000 = prev_m68000; + if (address) { + SekDbgSetRegister(SEK_REG_PC, address); + } + + SetWindowText(GetDlgItem(hDbgDlg, IDC_DBG_GO), _T("Halt")); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPFRAME), FALSE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPINTO), FALSE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEP), FALSE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_SKIP), FALSE); + + // Update the feedback area + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Running, start at PC = %06x\\par}"), SekDbgGetRegister(SEK_REG_PC)); + AddFeedback(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN2), szBuffer); + + if (bRunPause) { + SetPauseMode(false); + } + if (bBreakpointHit) { + PostMessage(hScrnWnd, WM_APP + 0, 0, 0); + } + + return 0; +} + +static int cmd_halt(TCHAR* /*arg*/) +{ + TCHAR szBuffer[256]; + + // remove temporary breakpoint (if any) + SekDbgSetBreakpointFetch(0, 0); + + SetWindowText(GetDlgItem(hDbgDlg, IDC_DBG_GO), _T("Go!")); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPFRAME), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEPINTO), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_STEP), TRUE); + EnableWindow(GetDlgItem(hDbgDlg, IDC_DBG_SKIP), TRUE); + + if (!bRunPause) { + SetPauseMode(true); + + SekOpen(0); + + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), TraceBack(SekGetPC(-1), 5, nDisassCPUType), nDisassCPUType); + CreateCPUInfo(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN1), true, &curr_m68000, &prev_m68000); + + SekClose(); + } + + // Update the feedback area + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Stopped, PC = %06x\\par}"), SekDbgGetRegister(SEK_REG_PC)); + AddFeedback(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN2), szBuffer); + + return 0; +} + +static int cmd_setbp(TCHAR* arg) +{ + TCHAR* pos = arg; + TCHAR szBuffer[256] = _T(""); + + long number, address; + + SKIP_WS(pos); + + switch (*pos) { + case _T('r'): { + number = _tcstol(pos + 1, &pos, 16); + address = _tcstol(pos, &pos, 16); + + if (number < 1 || number > 8) { + return 1; + } + + if (address) { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint R%i: read <- %06x\\par}"), number, address); + } else { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint R%i: disabled\\par}"), number); + } + + SekDbgSetBreakpointDataRead(address, number); + + break; + } + case _T('w'): { + number = _tcstol(pos + 1, &pos, 16); + address = _tcstol(pos, &pos, 16); + + if (number < 1 || number > 8) { + return 1; + } + + if (address) { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint W%i: write -> %06x\\par}"), number, address); + } else { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint W%i: disabled\\par}"), number); + } + + SekDbgSetBreakpointDataWrite(address, number); + + break; + } + case _T('p'): { + number = _tcstol(pos + 1, &pos, 16); + address = _tcstol(pos, &pos, 16); + + if (number < 1 || number > 8) { + return 1; + } + + if (address) { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint P%i: PC == %06x\\par}"), number, address); + } else { + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252{\\colortbl;}\\pard\\f0\\fs20\\cf0 Breakpoint P%i: disabled\\par}"), number); + } + + SekDbgSetBreakpointFetch(address, number); + + break; + } + } + + // Update the feedback area + AddFeedback(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN2), szBuffer); + + return 0; +} + +static int cmd_frame(TCHAR* /*arg*/) +{ + TCHAR szBuffer[256] = _T(""); + + SetPauseMode(true); + + prev_m68000 = curr_m68000; + + // Run until the next frame starts + if (bBreakpointHit) { + PostMessage(hScrnWnd, WM_APP + 0, 0, 0); + return 0; + } else { + VidFrame(); + } + + // Display the image + VidPaint(0); + + // Update the cpu info & disassembly + SekOpen(0); + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), TraceBack(SekGetPC(-1), 5, nDisassCPUType), nDisassCPUType); + CreateCPUInfo(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN1), true, &curr_m68000, &prev_m68000); + SekClose(); + + // Update the feedback area + _stprintf(szBuffer, _T("{\\rtf1\\ansi\\ansicpg1252\\pard\\f0\\fs20\\cf0 Stepped frame, PC = %06x\\par}"), SekDbgGetRegister(SEK_REG_PC)); + AddFeedback(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN2), szBuffer); + + return 0; +} + +static int cmd_single(TCHAR* /*arg*/) +{ + char buf[100] = ""; + + int size = m68k_disassemble(buf, SekDbgGetRegister(SEK_REG_PC), nDisassCPUType); + + SekDbgSetBreakpointFetch(SekDbgGetRegister(SEK_REG_PC) + size, 0); + + return cmd_go(_T("0")); +} + +static int cmd_into(TCHAR* /*arg*/) +{ + SekDbgEnableSingleStep(); + + return cmd_go(_T("0")); +} + +static int cmd_skip(TCHAR* /*arg*/) +{ + char buf[100] = ""; + + int size = m68k_disassemble(buf, SekDbgGetRegister(SEK_REG_PC), nDisassCPUType); + + prev_m68000 = curr_m68000; + + SekDbgSetRegister(SEK_REG_PC, SekDbgGetRegister(SEK_REG_PC) + size); + // Update active CPU context + SekClose(); + + CreateCPUInfo(GetDlgItem(hDbgDlg, IDC_DBG_INFOWN1), true, &curr_m68000, &prev_m68000); + CreateDisass(GetDlgItem(hDbgDlg, nDisassWindow), TraceBack(SekDbgGetRegister(SEK_REG_PC), 5, nDisassCPUType), nDisassCPUType); + + return 0; +} + +static struct { TCHAR* cmdstring; int (*cmdfunction)(TCHAR*); } CommandList[] = { + { _T(""), NULL }, + + { _T("x"), cmd_exit }, { _T("exit"), cmd_exit }, + { _T("d"), cmd_disass }, { _T("dasm"), cmd_disass }, + { _T("m"), cmd_memdump }, { _T("mem"), cmd_memdump }, + + { _T("g"), cmd_go }, { _T("go"), cmd_go }, { _T("go!"), cmd_go }, + { _T("h"), cmd_halt }, { _T("halt"), cmd_halt }, + + { _T("ss"), cmd_single }, { _T("step"), cmd_single }, + { _T("si"), cmd_into }, { _T("step into"), cmd_into }, + { _T("sk"), cmd_skip }, { _T("skip"), cmd_skip }, + + { _T("sf"), cmd_frame }, { _T("step frame"), cmd_frame }, + + { _T("sb"), cmd_setbp }, + + { NULL, NULL } +}; + +static int ExecuteCommand(TCHAR* cmd) +{ + TCHAR cmdonly[8] = _T(""); + TCHAR* pos = cmd; + + SKIP_WS(pos); + + for (int i = 0; *pos && !isspace(*pos); i++) { + cmdonly[i] = *pos++; + } + + SKIP_WS(pos); + + for (int i = 0; CommandList[i].cmdstring; i++) { + if (!_tcsicmp(cmdonly, CommandList[i].cmdstring)) { + if (CommandList[i].cmdfunction) { + return CommandList[i].cmdfunction(pos); + } + + return 0; + } + } + + return 1; +} + +// ---------------------------------------------------------------------------- +// Message processing + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + + hDbgDlg = hDlg; + + nDisassWindow = IDC_DBG_MAINWN1; + nMemdumpWindow = IDC_DBG_MAINWN2; + + nActiveWindow = nDisassWindow; + + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &nMouseWheelScrollLines, 0); + + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, EM_SETTEXTMODE, TM_PLAINTEXT, 0); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, EM_LIMITTEXT, 63, 0); + + hCommandFont = CreateFont(bLargeWindow ? 18 : 14, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_MODERN, _T("Courier New")); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, WM_SETFONT, (WPARAM)hCommandFont, (LPARAM)0); + + SendDlgItemMessage(hDlg, IDC_DBG_MAINWN1, EM_SETMARGINS, EC_LEFTMARGIN, 3); + SendDlgItemMessage(hDlg, IDC_DBG_MAINWN2, EM_SETMARGINS, EC_LEFTMARGIN, 3); + SendDlgItemMessage(hDlg, IDC_DBG_INFOWN1, EM_SETMARGINS, EC_LEFTMARGIN, 3); + SendDlgItemMessage(hDlg, IDC_DBG_INFOWN2, EM_SETMARGINS, EC_LEFTMARGIN, 3); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, EM_SETMARGINS, EC_LEFTMARGIN, 3); + + SendDlgItemMessage(hDlg, IDC_DBG_MAINWN1, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_PROTECTED); + SendDlgItemMessage(hDlg, IDC_DBG_MAINWN2, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_PROTECTED); + SendDlgItemMessage(hDlg, IDC_DBG_INFOWN1, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_PROTECTED); + SendDlgItemMessage(hDlg, IDC_DBG_INFOWN2, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_PROTECTED); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SCROLLEVENTS); + + // Initialise feedback window + InitFeedback(GetDlgItem(hDlg, IDC_DBG_INFOWN2)); + + // Get the list of memory areas + GetMemoryAreas(); + + // Initialise disassembly window + SekOpen(0); + SetupDisass(0); + + // Initialise memory dump window + SetupMemdump(0); + + UpdateCPUState(&prev_m68000); + CreateCPUInfo(GetDlgItem(hDlg, IDC_DBG_INFOWN1), true, &curr_m68000, &prev_m68000); + + SekClose(); + + SendDlgItemMessage(hDlg, IDC_DBG_MAINWN1_DRP1, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); + + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_DBG_COMMAND), TRUE); + + WndInMid(hDlg, NULL); + ShowWindow(hDlg, SW_NORMAL); + + return FALSE; + } + + if (Msg == WM_CLOSE) { + DebugExit(); + + return 0; + } + + if (Msg == WM_COMMAND) { + + // Exit the debugger + if (LOWORD(wParam) == IDCANCEL && HIWORD(wParam) == BN_CLICKED) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + if (LOWORD(wParam) == IDC_DBG_GO && HIWORD(wParam) == BN_CLICKED) { + if (bRunPause || bBreakpointHit) { + ExecuteCommand(_T("g")); + } else { + ExecuteCommand(_T("h")); + } + return 0; + } + + if (LOWORD(wParam) == IDC_DBG_STEP && HIWORD(wParam) == BN_CLICKED) { + ExecuteCommand(_T("ss")); + return 0; + } + if (LOWORD(wParam) == IDC_DBG_STEPINTO && HIWORD(wParam) == BN_CLICKED) { + ExecuteCommand(_T("si")); + return 0; + } + if (LOWORD(wParam) == IDC_DBG_SKIP && HIWORD(wParam) == BN_CLICKED) { + ExecuteCommand(_T("sk")); + return 0; + } + + if (LOWORD(wParam) == IDC_DBG_STEPFRAME && HIWORD(wParam) == BN_CLICKED) { + ExecuteCommand(_T("sf")); + return 0; + } + if (LOWORD(wParam) == IDC_DBG_SHOT && HIWORD(wParam) == BN_CLICKED) { + MakeScreenShot(); + return 0; + } + + // Execute the comnmand entered in the command text control + if (LOWORD(wParam) == IDOK) { + TCHAR CommandText[64] = _T(""); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, WM_GETTEXT, (WPARAM)64, (LPARAM)CommandText); + SendDlgItemMessage(hDlg, IDC_DBG_COMMAND, WM_SETTEXT, (WPARAM)0, (LPARAM)_T("")); + + ExecuteCommand(CommandText); + + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_DBG_COMMAND), TRUE); + } + + if (HIWORD(wParam) == CBN_SELENDOK) { + if (LOWORD(wParam) == IDC_DBG_MAINWN1_DRP1) { + SetupDisass(SendMessage((HWND)lParam, CB_GETCURSEL, (WPARAM)0, (LPARAM)0)); + } + if (LOWORD(wParam) == IDC_DBG_MAINWN1_DRP2) { + nDisassAttrib = SendMessage((HWND)lParam, CB_GETCURSEL, (WPARAM)0, (LPARAM)0); + CreateDisass(GetDlgItem(hDlg, nDisassWindow), nDisassAddress[0], nDisassCPUType); + } + if (LOWORD(wParam) == IDC_DBG_MAINWN2_DRP1) { + SetupMemdump(SendMessage((HWND)lParam, CB_GETCURSEL, (WPARAM)0, (LPARAM)0)); + } + if (LOWORD(wParam) == IDC_DBG_MAINWN2_DRP2) { + nMemdumpAttrib = SendMessage((HWND)lParam, CB_GETCURSEL, (WPARAM)0, (LPARAM)0); + CreateMemdump(GetDlgItem(hDlg, nMemdumpWindow), nMemdumpArea, nMemdumpAddress); + } + } + } + + if (Msg == WM_NOTIFY) { + int nPageSize = bLargeWindow ? 16 : 12; + unsigned int nWindow = 0; + bool bAffectCaret = true; + int nScrollLines = 0; + + if (((NMHDR*)lParam)->code == EN_MSGFILTER) { + nWindow = ((NMHDR*)lParam)->idFrom; + + if (nWindow == IDC_DBG_COMMAND) { + nWindow = nActiveWindow; + + bAffectCaret = false; + } + } + + if (((NMHDR*)lParam)->code == EN_MSGFILTER && ((MSGFILTER*)lParam)->msg == WM_MOUSEWHEEL) { + static int nMouseWheelDelta; + +// if (wParam & (MK_SHIFT | MK_CONTROL)) { +// break; +// } + + nMouseWheelDelta -= (short)HIWORD(((MSGFILTER*)lParam)->wParam); + + if (abs(nMouseWheelDelta) >= WHEEL_DELTA) { + if (nMouseWheelScrollLines == WHEEL_PAGESCROLL) { + nScrollLines = 2 * (nPageSize - ((nWindow == nDisassWindow) ? 1 : 0)); + if (nMouseWheelDelta < 0) { + nScrollLines = -nScrollLines; + } + } else { + nScrollLines = 2 * (nMouseWheelDelta / WHEEL_DELTA); + } + nMouseWheelDelta %= WHEEL_DELTA; + + bAffectCaret = false; + } + } + + if ((bBreakpointHit || bRunPause) && ((NMHDR*)lParam)->code == EN_MSGFILTER && (((MSGFILTER*)lParam)->msg == WM_KEYDOWN || ((MSGFILTER*)lParam)->msg == WM_SYSKEYDOWN)) { + + if (((NMHDR*)lParam)->idFrom != IDC_DBG_COMMAND && ((NMHDR*)lParam)->idFrom != nDisassWindow && ((NMHDR*)lParam)->idFrom != nMemdumpWindow) { + nWindow = 0; + } + + if (((MSGFILTER*)lParam)->wParam == VK_UP) { + if (KEY_DOWN(VK_CONTROL)) { + nScrollLines = -1; + } else { + nScrollLines = -2; + } + } + if (((MSGFILTER*)lParam)->wParam == VK_DOWN) { + if (KEY_DOWN(VK_CONTROL)) { + nScrollLines = 1; + } else { + nScrollLines = 2; + } + } + if (((MSGFILTER*)lParam)->wParam == VK_PRIOR) { + nScrollLines = -2 * (nPageSize - ((nWindow == nDisassWindow) ? 1 : 0)); + } + if (((MSGFILTER*)lParam)->wParam == VK_NEXT) { + nScrollLines = 2 * (nPageSize - ((nWindow == nDisassWindow) ? 1 : 0)); + } + } + + if (nScrollLines && nWindow) { + DWORD dwStart = 0, dwEnd = 0; + bool bResetCaret = false; + + if (nWindow == nDisassWindow) { + + SendDlgItemMessage(hDlg, nWindow, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); + + if (nScrollLines < 0) { + int nLine = SendDlgItemMessage(hDlg, nWindow, EM_LINEFROMCHAR, (WPARAM)((dwStart != (DWORD)-1) ? dwStart : dwEnd), (LPARAM)0); + + if (nScrollLines & 1) { + CreateDisass(GetDlgItem(hDlg, nWindow), nDisassAddress[0] < 2 ? 0 : nDisassAddress[0] - 2, nDisassCPUType); + + dwStart = dwEnd = 2 * nPageSize + SendDlgItemMessage(hDlg, nWindow, EM_LINEINDEX, nLine, 0); + bResetCaret = true; + } else { + if (!bAffectCaret || nScrollLines < -2 || nLine == 0) { + CreateDisass(GetDlgItem(hDlg, nWindow), TraceBack(nDisassAddress[0], -nScrollLines / 2, nDisassCPUType), nDisassCPUType); + + if (bAffectCaret) { + dwStart = dwEnd = 2 * nPageSize; + } + bResetCaret = true; + } + } + } + if (nScrollLines > 0) { + int nLine = SendDlgItemMessage(hDlg, nWindow, EM_LINEFROMCHAR, (WPARAM)dwEnd, (LPARAM)0); + + if (nScrollLines & 1) { + CreateDisass(GetDlgItem(hDlg, nWindow), nDisassAddress[0] >= 0x00FFFFFE ? 0x00FFFFFE : nDisassAddress[0] + 2, nDisassCPUType); + + dwStart = dwEnd = 32 + SendDlgItemMessage(hDlg, nWindow, EM_LINEINDEX, nLine, 0); + bResetCaret = true; + } else { + if (!bAffectCaret || nScrollLines > 2 || SendDlgItemMessage(hDlg, nWindow, EM_LINEFROMCHAR, (WPARAM)dwEnd, (LPARAM)0) >= (nPageSize - 1)) { + + // Make sure we don't go past the end of memory + if (nDisassAddress[0] >= 0x00FFFFFE) { + nDisassAddress[1] = 0x00FFFFFE; + } + + CreateDisass(GetDlgItem(hDlg, nWindow), nDisassAddress[nScrollLines / 2], nDisassCPUType); + + if (bAffectCaret) { + dwStart = dwEnd = 32 + SendDlgItemMessage(hDlg, nWindow, EM_LINEINDEX, nPageSize - 1, 0); + } + bResetCaret = true; + } + } + } + } + + if (nWindow == nMemdumpWindow) { + int nAreaSize = nMemdumpArea ? DbgMemoryAreaInfo[nMemdumpArea].nLen : 0x01000000; + bool bRefresh = true; + + SendDlgItemMessage(hDlg, nWindow, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); + + if (nScrollLines < 0) { + if (nScrollLines & 1) { + nMemdumpAddress -= 1; + } else { + if (!bAffectCaret || nScrollLines < -2 || SendDlgItemMessage(hDlg, nWindow, EM_LINEFROMCHAR, (WPARAM)dwStart, (LPARAM)0) == 0) { + nMemdumpAddress += 8 * nScrollLines; + } else { + bRefresh = false; + } + } + } + if (nScrollLines > 0) { + if (nScrollLines & 1) { + nMemdumpAddress += 1; + } else { + if (!bAffectCaret || nScrollLines > 2 || SendDlgItemMessage(hDlg, nWindow, EM_LINEFROMCHAR, (WPARAM)dwEnd, (LPARAM)0) >= nPageSize - 1) { + nMemdumpAddress += 8 * nScrollLines; + } else { + bRefresh = false; + } + } + } + + if (bRefresh) { + // Make sure we don't go past the end of memory + if (nMemdumpAddress > nAreaSize - nPageSize * 16) { + nMemdumpAddress = nAreaSize - nPageSize * 16; + } + if (nMemdumpAddress < 0) { + nMemdumpAddress = 0; + } + + CreateMemdump(GetDlgItem(hDlg, nWindow), nMemdumpArea, nMemdumpAddress); + bResetCaret = true; + } + } + + // If we've re-filled the RichEdit control, the caret position is reset as well, so restore it + if (bResetCaret) { + SendDlgItemMessage(hDlg, nWindow, EM_SETSEL, (WPARAM)dwStart, (LPARAM)dwEnd); + } + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Public functions + +#endif + +int DebugExit() +{ + +#if defined (FBA_DEBUG) + + if (DbgMemoryAreaInfo) { + free(DbgMemoryAreaInfo); + DbgMemoryAreaInfo = NULL; + } + + EnableWindow(hScrnWnd, TRUE); + DestroyWindow(hDbgDlg); + + DeleteObject(hCommandFont); + hCommandFont = NULL; + + SekDbgDisableBreakpoints(); + if (bBreakpointHit) { + bBreakpointHit = false; + POST_INITIALISE_MESSAGE; + } + + SetPauseMode(bOldPause); + MenuUpdate(); + +#endif + + return 0; +} + +int DebugCreate() +{ + +#if defined (FBA_DEBUG) + + if (bDrvOkay == 0) { + return 1; + } + + AudBlankSound(); + + DestroyWindow(hDbgDlg); + + SystemParametersInfo(SPI_GETWORKAREA, 0, &SystemWorkArea, 0); + bLargeWindow = (SystemWorkArea.right - SystemWorkArea.left >= 1024 && SystemWorkArea.bottom - SystemWorkArea.top >= 768) ? true : false; + hDbgDlg = FBACreateDialog(hAppInst, MAKEINTRESOURCE(bLargeWindow ? IDD_DEBUG_LRG : IDD_DEBUG_SML), hScrnWnd, (DLGPROC)DialogProc); + if (hDbgDlg == NULL) { + return 1; + } + + SekDbgBreakpointHandlerRead = BreakpointHitRead; + SekDbgBreakpointHandlerFetch = BreakpointHitFetch; + SekDbgBreakpointHandlerWrite = BreakpointHitWrite; + + bOldPause = bRunPause; + + SetPauseMode(true); + + return 0; + +#else + + POST_INITIALISE_MESSAGE; + + return 1; + +#endif + +} diff --git a/src/burner/win32/drv.cpp b/src/burner/win32/drv.cpp new file mode 100644 index 00000000..77166165 --- /dev/null +++ b/src/burner/win32/drv.cpp @@ -0,0 +1,271 @@ +// Driver Init module +#include "burner.h" + +int bDrvOkay = 0; // 1 if the Driver has been initted okay, and it's okay to use the BurnDrv functions + +TCHAR szAppRomPaths[DIRS_MAX][MAX_PATH] = { { _T("") }, { _T("") }, { _T("") }, { _T("") }, { _T("") }, { _T("") }, { _T("") }, { _T("roms\\") } }; + +static bool bSaveRAM = false; + +static int DrvBzipOpen() +{ + BzipOpen(false); + + // If there is a problem with the romset, report it + switch (BzipStatus()) { + case BZIP_STATUS_BADDATA: { + FBAPopupDisplay(PUF_TYPE_WARNING); + break; + } + case BZIP_STATUS_ERROR: { + FBAPopupDisplay(PUF_TYPE_ERROR); + +#if 0 || !defined FBA_DEBUG + // Don't even bother trying to start the game if we know it won't work + BzipClose(); + return 1; +#endif + + break; + } + default: { + +#if 0 && defined FBA_DEBUG + FBAPopupDisplay(PUF_TYPE_INFO); +#else + FBAPopupDisplay(PUF_TYPE_INFO | PUF_TYPE_LOGONLY); +#endif + + } + } + + return 0; +} + +static int DoLibInit() // Do Init of Burn library driver +{ + int nRet = 0; + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) != HARDWARE_SNK_MVS) { + ProgressCreate(); + } + + if (DrvBzipOpen()) { + return 1; + } + + nRet = BurnDrvInit(); + + BzipClose(); + + ProgressDestroy(); + + if (nRet) { + return 3; + } else { + return 0; + } +} + +// Catch calls to BurnLoadRom() once the emulation has started; +// Intialise the zip module before forwarding the call, and exit cleanly. +static int __cdecl DrvLoadRom(unsigned char* Dest, int* pnWrote, int i) +{ + int nRet; + + BzipOpen(false); + + if ((nRet = BurnExtLoadRom(Dest, pnWrote, i)) != 0) { + char* pszFilename; + + BurnDrvGetRomName(&pszFilename, i, 0); + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_LOAD_REQUEST), pszFilename, BurnDrvGetText(DRV_NAME)); + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + BzipClose(); + + BurnExtLoadRom = DrvLoadRom; + + ScrnTitle(); + + return nRet; +} + +int __cdecl DrvCartridgeAccess(BurnCartrigeCommand nCommand) +{ + switch (nCommand) { + case CART_INIT_START: + ProgressCreate(); + if (DrvBzipOpen()) { + return 1; + } + break; + case CART_INIT_END: + ProgressDestroy(); + BzipClose(); + break; + case CART_EXIT: + break; + default: + return 1; + } + + return 0; +} + +int DrvInit(int nDrvNum, bool bRestore) +{ + int nStatus; + + DrvExit(); // Make sure exitted + MediaExit(); + + nBurnDrvActive = nDrvNum; // Set the driver number + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_MVS) { + + BurnExtCartridgeSetupCallback = DrvCartridgeAccess; + + if (SelMVSDialog()) { + POST_INITIALISE_MESSAGE; + return 0; + } + } + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOCD) { + if (CDEmuInit()) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Couldn't initialise CD emulation.\n")); + FBAPopupDisplay(PUF_TYPE_ERROR); + + POST_INITIALISE_MESSAGE; + return 0; + } + } + + MediaInit(); + + // Define nMaxPlayers early; GameInpInit() needs it (normally defined in DoLibInit()). + nMaxPlayers = BurnDrvGetMaxPlayers(); + GameInpInit(); // Init game input + + if(ConfigGameLoad(true)) { + ConfigGameLoadHardwareDefaults(); + } + InputMake(true); + GameInpDefault(); + + if (kNetGame) { + nBurnCPUSpeedAdjust = 0x0100; + } + + nStatus = DoLibInit(); // Init the Burn library's driver + if (nStatus) { + if (nStatus & 2) { + BurnDrvExit(); // Exit the driver + + ScrnTitle(); + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_BURN_INIT), BurnDrvGetText(DRV_FULLNAME)); + FBAPopupDisplay(PUF_TYPE_WARNING); + } + + POST_INITIALISE_MESSAGE; + return 1; + } + + BurnExtLoadRom = DrvLoadRom; + + bDrvOkay = 1; // Okay to use all BurnDrv functions + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } else { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + + bSaveRAM = false; + if (kNetGame) { + KailleraInitInput(); + KailleraGetInput(); + } else { + if (bRestore) { + StatedAuto(0); + bSaveRAM = true; + + ConfigCheatLoad(); + } + } + + nBurnLayer = 0xFF; // show all layers + + // Reset the speed throttling code, so we don't 'jump' after the load + RunReset(); + + VidExit(); + POST_INITIALISE_MESSAGE; + + return 0; +} + +int DrvInitCallback() +{ + return DrvInit(nBurnDrvActive, false); +} + +int DrvExit() +{ + if (bDrvOkay) { + StopReplay(); + + VidExit(); + + InvalidateRect(hScrnWnd, NULL, 1); + UpdateWindow(hScrnWnd); // Blank screen window + + DestroyWindow(hInpdDlg); // Make sure the Input Dialog is exited + DestroyWindow(hInpDIPSWDlg); // Make sure the DipSwitch Dialog is exited + DestroyWindow(hInpCheatDlg); // Make sure the Cheat Dialog is exited + + if (nBurnDrvActive < nBurnDrvCount) { + MemCardEject(); // Eject memory card if present + + if (bSaveRAM) { + StatedAuto(1); // Save NV (or full) RAM + bSaveRAM = false; + } + + ConfigGameSave(bSaveInputs); + + GameInpExit(); // Exit game input + + BurnDrvExit(); // Exit the driver + } + } + + BurnExtLoadRom = NULL; + + bDrvOkay = 0; // Stop using the BurnDrv functions + + bRunPause = 0; // Don't pause when exitted + + if (bAudOkay) { + // Write silence into the sound buffer on exit, and for drivers which don't use pBurnSoundOut + memset(nAudNextSound, 0, nAudSegLen << 2); + } + + CDEmuExit(); + + BurnExtCartridgeSetupCallback = NULL; + + nBurnDrvActive = ~0U; // no driver selected + + return 0; +} diff --git a/src/burner/win32/dwmapi_core.cpp b/src/burner/win32/dwmapi_core.cpp new file mode 100644 index 00000000..cb3479e1 --- /dev/null +++ b/src/burner/win32/dwmapi_core.cpp @@ -0,0 +1,144 @@ +// FBA DWM API HANDLING FOR WINDOWS 7 (by CaptainCPS-X / Jezer Andino) +#include "burner.h" +//#include "dwmapi_core.h" + +HRESULT (WINAPI *DwmEnableComposition) (UINT uCompositionAction); +HRESULT (WINAPI *DwmSetDxFrameDuration) (HWND hwnd, INT cRefreshes); +HRESULT (WINAPI *DwmSetPresentParameters) (HWND hwnd, DWM_PRESENT_PARAMETERS *pPresentParams); +HRESULT (WINAPI *DwmExtendFrameIntoClientArea) (HWND hwnd, const MARGINS* pMarInset); +HRESULT (WINAPI *DwmSetWindowAttribute) (HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); +HRESULT (WINAPI *DwmIsCompositionEnabled) (BOOL*); + +HRESULT WINAPI Empty_DwmEnableComposition (UINT) { return 0; } +HRESULT WINAPI Empty_DwmSetDxFrameDuration (HWND, INT) { return 0; } +HRESULT WINAPI Empty_DwmSetPresentParameters (HWND, DWM_PRESENT_PARAMETERS*) { return 0; } +HRESULT WINAPI Empty_DwmExtendFrameIntoClientArea (HWND, const MARGINS*) { return 0; } +HRESULT WINAPI Empty_DwmSetWindowAttribute (HWND, DWORD, LPCVOID, DWORD ) { return 0; } +HRESULT WINAPI Empty_DwmIsCompositionEnabled (BOOL*) { return 0; } + +HINSTANCE hDwmApi; +int DWMAPI_Initialised = 0; + +bool bVidDWMCore = true; + +void ExitDWMAPI() { + FreeLibrary(hDwmApi); +} + +void GetDllFunctions() { + + if(!DWMAPI_Initialised) return; + + DwmEnableComposition = (HRESULT (WINAPI *)(UINT)) GetProcAddress(hDwmApi, "DwmEnableComposition"); + DwmSetDxFrameDuration = (HRESULT (WINAPI *)(HWND, INT)) GetProcAddress(hDwmApi, "DwmSetDxFrameDuration"); + DwmSetPresentParameters = (HRESULT (WINAPI *)(HWND, DWM_PRESENT_PARAMETERS*)) GetProcAddress(hDwmApi, "DwmSetPresentParameters"); + DwmExtendFrameIntoClientArea = (HRESULT (WINAPI *)(HWND, const MARGINS*)) GetProcAddress(hDwmApi, "DwmExtendFrameIntoClientArea"); + DwmSetWindowAttribute = (HRESULT (WINAPI *)(HWND, DWORD, LPCVOID, DWORD)) GetProcAddress(hDwmApi, "DwmSetWindowAttribute"); + DwmIsCompositionEnabled = (HRESULT (WINAPI *)(BOOL*)) GetProcAddress(hDwmApi, "DwmIsCompositionEnabled"); + + if(!DwmEnableComposition) DwmEnableComposition = Empty_DwmEnableComposition; + if(!DwmSetDxFrameDuration) DwmSetDxFrameDuration = Empty_DwmSetDxFrameDuration; + if(!DwmSetPresentParameters) DwmSetPresentParameters = Empty_DwmSetPresentParameters; + if(!DwmExtendFrameIntoClientArea) DwmExtendFrameIntoClientArea = Empty_DwmExtendFrameIntoClientArea; + if(!DwmSetWindowAttribute) DwmSetWindowAttribute = Empty_DwmSetWindowAttribute; + if(!DwmIsCompositionEnabled) DwmIsCompositionEnabled = Empty_DwmIsCompositionEnabled; + + ExitDWMAPI(); +} + +int InitDWMAPI() { + + if(!IsWindows7()) return 0; + + hDwmApi = LoadLibrary(_T("dwmapi.dll")); + + if (hDwmApi) { + DWMAPI_Initialised = 1; + + // Try to init DWM API Functions + bprintf(PRINT_IMPORTANT, _T("[Win7] Loading of DWMAPI.DLL was succesfull.\n")); + + GetDllFunctions(); + + // Functions Adquired + bprintf(PRINT_IMPORTANT, _T("[Win7] DWMAPI.DLL Functions adquired.\n")); + + return 1; + } + + bprintf(PRINT_IMPORTANT, _T("[Win7] Loading of DWMAPI.DLL failed.\n")); + DWMAPI_Initialised = 0; + return 0; +} + +void ExtendIntoClientAll(HWND hwnd) { + // Negative margins have special meaning to DwmExtendFrameIntoClientArea. + // Negative margins create the "sheet of glass" effect, where the client area + // is rendered as a solid surface with no window border. + MARGINS margins = {-1, -1, -1, -1}; + + // Extend the frame across the entire window. + DwmExtendFrameIntoClientArea(hwnd, &margins); +} + +BOOL IsWindows7() { + + OSVERSIONINFO osvi; + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + // Verify if the FBA is running on Windows 7 + GetVersionEx(&osvi); + + return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 1); +} + +// FIX FOR FRAME STUTTERING ON WINDOWS 7 +void DWM_StutterFix() +{ + // Windows 7 found... + if(IsWindows7() && !nVidFullscreen) + { + // If the DWM API Functions are loaded, continue. + if(DWMAPI_Initialised) + { + // Accurate + UNSIGNED_RATIO fps; + memset(&fps, 0, sizeof(UNSIGNED_RATIO)); + fps.uiNumerator = 60000; + fps.uiDenominator = 1000; + + // Stuttering frames fix for Windows 7 + DWM_PRESENT_PARAMETERS params; + memset(¶ms, 0, sizeof(DWM_PRESENT_PARAMETERS)); + params.cbSize = sizeof(DWM_PRESENT_PARAMETERS); + params.fQueue = TRUE; + params.cBuffer = 2; + params.cRefreshStart = 0; + params.fUseSourceRate = TRUE; + params.rateSource = fps; + //params.cRefreshesPerFrame = 1; + params.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT; + + DwmSetPresentParameters(hVideoWindow, ¶ms); + + bprintf(PRINT_IMPORTANT, _T("[Win7] DWM Presentation parameters were set.\n")); + + // Aero effects (disabled, useful in the future) + //ExtendIntoClientAll(hScrnWnd); + } + } +} + +BOOL IsCompositeOn() +{ + // not windows 7 + if(!IsWindows7() || !DWMAPI_Initialised) return false; + + BOOL bStatus = false; + + // check DWM composition status + DwmIsCompositionEnabled(&bStatus); + + return bStatus; +} diff --git a/src/burner/win32/dwmapi_core.h b/src/burner/win32/dwmapi_core.h new file mode 100644 index 00000000..2e0110eb --- /dev/null +++ b/src/burner/win32/dwmapi_core.h @@ -0,0 +1,94 @@ +#include + +#define DWM_EC_DISABLECOMPOSITION 0 +#define DWM_EC_ENABLECOMPOSITION 1 +#ifndef DWMAPI +#define DWMAPI STDAPI +#define DWMAPI_(type) STDAPI_(type) +#endif + +typedef ULONGLONG DWM_FRAME_COUNT; + +typedef struct _UNSIGNED_RATIO +{ + UINT32 uiNumerator; + UINT32 uiDenominator; +} UNSIGNED_RATIO; + +typedef enum +{ + // Use the first source frame that + // includes the first refresh of the output frame + DWM_SOURCE_FRAME_SAMPLING_POINT, + + // use the source frame that includes the most + // refreshes of out the output frame + // in case of multiple source frames with the + // same coverage the last will be used + DWM_SOURCE_FRAME_SAMPLING_COVERAGE, + + // Sentinel value + DWM_SOURCE_FRAME_SAMPLING_LAST +} DWM_SOURCE_FRAME_SAMPLING; + +typedef struct _DWM_PRESENT_PARAMETERS { + UINT32 cbSize; + BOOL fQueue; + DWM_FRAME_COUNT cRefreshStart; + UINT cBuffer; + BOOL fUseSourceRate; + UNSIGNED_RATIO rateSource; + UINT cRefreshesPerFrame; + DWM_SOURCE_FRAME_SAMPLING eSampling; +} DWM_PRESENT_PARAMETERS; + +//#if defined (_MARGINS) +//#else +//typedef struct _MARGINS +//{ +// int cxLeftWidth; +// int cxRightWidth; +// int cyTopHeight; +// int cyBottomHeight; +//} MARGINS; +//#endif + +typedef enum _DWMWINDOWATTRIBUTE { + DWMWA_NCRENDERING_ENABLED = 1, + DWMWA_NCRENDERING_POLICY, + DWMWA_TRANSITIONS_FORCEDISABLED, + DWMWA_ALLOW_NCPAINT, + DWMWA_CAPTION_BUTTON_BOUNDS, + DWMWA_NONCLIENT_RTL_LAYOUT, + DWMWA_FORCE_ICONIC_REPRESENTATION, + DWMWA_FLIP3D_POLICY, + DWMWA_EXTENDED_FRAME_BOUNDS, + DWMWA_HAS_ICONIC_BITMAP, + DWMWA_DISALLOW_PEEK, + DWMWA_EXCLUDED_FROM_PEEK, + DWMWA_LAST +} DWMWINDOWATTRIBUTE; + +typedef enum _DWMNCRENDERINGPOLICY { + DWMNCRP_USEWINDOWSTYLE, + DWMNCRP_DISABLED, + DWMNCRP_ENABLED, + DWMNCRP_LAST +} DWMNCRENDERINGPOLICY; + +extern HRESULT (WINAPI *DwmEnableComposition) (UINT uCompositionAction); +extern HRESULT (WINAPI *DwmSetDxFrameDuration) (HWND hwnd, INT cRefreshes); +extern HRESULT (WINAPI *DwmSetPresentParameters) (HWND hwnd, DWM_PRESENT_PARAMETERS *pPresentParams); +extern HRESULT (WINAPI *DwmExtendFrameIntoClientArea) (HWND hwnd, const MARGINS* pMarInset); +extern HRESULT (WINAPI *DwmSetWindowAttribute) (HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); +extern HRESULT (WINAPI *DwmIsCompositionEnabled) (BOOL*); + +void ExitDWMAPI(); +void GetDllFunctions(); +int InitDWMAPI(); +void ExtendIntoClientAll(HWND); +BOOL IsWindows7(); +void DWM_StutterFix(); +BOOL IsCompositeOn(); + +extern bool bVidDWMCore; diff --git a/src/burner/win32/dynhuff.cpp b/src/burner/win32/dynhuff.cpp new file mode 100644 index 00000000..64e923c9 --- /dev/null +++ b/src/burner/win32/dynhuff.cpp @@ -0,0 +1,1008 @@ +// +// Dynamic Huffman Encoder/Decoder +// +// implemented by Gangta +// +//----------------------------------------------------------- +// +// Version History +// +// version 0.1 - first release +// version 0.1a - fixed a bug where the bit remainder in +// the EncodeBuffer() function didn't reset +// to 32 if encoding is restarted before +// program exit +// version 0.1b - fixed right shift +// - fixed some utility functions +// +// version 0.1c - fixed PrintResult() +// - fixed a fatal bug in CorrectDH_T) 15% slower +// - optimized compression/decompression 95% faster +// - overall 80% faster :) +// +// version 0.2 - optimized even more, now O(lg 2) :) +// +//----------------------------------------------------------- +// +// Memory usage: +// +// 128 KB for both encoding/decoding +// +// I tested buffer size 16K, 32K, 64K, 128K, etc +// The performance started to drop after 512K, +// so I chose 128K. +// +// Comments: +// +// I tried to optimize the speed as best I can in my +// knowledge. +// +// It has buffer overflow protection for encoding and +// decoding. +// +// It has a frequency reset function which prevents +// frequency overflow. +// +// It can compress text files as well as any type of +// binary files. The compression is not as good as +// zlib, or bzlibb2, but it supports "on the fly" +// encoding/decoding, and I believe it is faster than +// bzlibb2. +// +// +/////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "dynhuff.h" + +#ifndef UINT32 +#define UINT32 unsigned int +#endif + +//# +//# Data sets for Dynamic Huffman Encoding/Decoding +//# +//############################################################################## + +// data sets for dynamic huffman +struct DHTNode { + unsigned int freq; + unsigned char value; + struct DHTNode *left; + struct DHTNode *right; + struct DHTNode *parent; + int l_index; // where this node is in the list +}; +static struct DHTNode DHTroot = {0,0,NULL,NULL,NULL,0}; +static struct DHTNode *null_node_ptr = &DHTroot; // where to add a new data +static struct DHTNode *look_up_table[257] = {NULL,}; // check if it's a new data +static struct DHTNode *node_list[MAX_LIST_LEN] = {NULL,}; // reverse level traverse +static int list_idx = MAX_LIST_LEN-1; + +// data sets for compressed buffer and compressed file I/O +static FILE *cFile = NULL; +static UINT32 c_buffer[MAX_BUFFER_LEN]={0,}; +static int c_buffer_idx = 0; +int end_of_buffer = 0; +static int code_length = 0; + +// data sets for decompressed buffer and decompressed file I/O +static FILE *dFile = NULL; +static UINT32 d_buffer[MAX_BUFFER_LEN]={0,}; +static int d_buffer_idx = 0; + +// file embedding +static int bEmbed = 0; +static int embed_offset = 0; + +// flags used to determine when to stop decoding +static unsigned int code_count = 0; +static int code_reset_count = 0; +static int buffer_reset_count = 0; + +// for saving compression result +static unsigned int nCompressedFileSize; // flag +static unsigned int nCodeCount; // flag +static int nCodeResetCount; // flag +static int nBufferIdx; +static int nBufferResetCount; // flag + +// function prototypes +static void ResetBufferC(); +static void ReloadBufferC(); +static void ResetBufferD(); +static void ReloadBufferD(); +static void SaveResult(); +#ifdef _DEBUG +static void CheckList(); +#endif + +//# +//# Functions for Dynamic Huffman Encoding/Decoding +//# +//############################################################################## + +// initialize a node in the dynamic huffman tree +static void SetNode (struct DHTNode *node_ptr,unsigned int freq, unsigned char value, struct DHTNode *left, struct DHTNode *right, struct DHTNode *parent) +{ + node_ptr->freq = freq; // count # of occurances + node_ptr->value = value; // corresponding key in the mInputSet + node_ptr->left = left; // left subtree + node_ptr->right = right; // right subtree + node_ptr->parent = parent; // parent node +} + +// the list is a reverse level traversal of the dynamic huffman tree +static void BuildNodeList (struct DHTNode *node_ptr) +{ + if(list_idx == MAX_LIST_LEN-1) { node_list[MAX_LIST_LEN-1] = NULL;} + node_list[--list_idx] = node_ptr->parent; + node_ptr->parent->l_index = list_idx; + node_list[--list_idx] = node_ptr; + node_ptr->l_index = list_idx; +} + +// swap the two nodes in the dynamic huffman tree +static void SwapNodes (struct DHTNode *node1, struct DHTNode *node2) +{ + unsigned int freq_diff; + struct DHTNode temp_node; + struct DHTNode *node_ptr = node1; // node1 always has higher freq + + // backup node1 before swapping + memcpy(&temp_node,node1,sizeof(struct DHTNode)); + + // swap each node's parent's left or right depending on + // whether each noce is a left child or a right child + if(node2->parent->left == node2) + node2->parent->left = node1; + else + node2->parent->right = node1; + if(temp_node.parent->left == node1) + node1->parent->left = node2; + else + node1->parent->right = node2; + + // swap each node's parent + node1->parent = node2->parent; + node2->parent = temp_node.parent; + + // swap each node's l_index + node1->l_index = node2->l_index; + node2->l_index = temp_node.l_index; + + // correct frequencies + freq_diff = node1->freq - node2->freq; + node_ptr = node1; + while(node_ptr->parent) + { + node_ptr = node_ptr->parent; + node_ptr->freq += freq_diff; + } + node_ptr = node2; + while(node_ptr->parent) + { + node_ptr = node_ptr->parent; + node_ptr->freq -= freq_diff; + } +} + +// correct the dynamic huffman tree if necessary +static void CorrectDHT(int curr_idx) +{ + struct DHTNode *temp; + int swap_idx; + + // search for nodes that are not in order + while(node_list[curr_idx+1]) + { + // if found something out of order + if(node_list[curr_idx]->freq > node_list[curr_idx+1]->freq) + { + // search for the node to swap with, then swap them + swap_idx = curr_idx+1; + while(node_list[swap_idx+1]) + { + // found node to swap it with, so swap them, + if(node_list[swap_idx]->freq < node_list[swap_idx+1]->freq) + { + // extra check for null node exception + if(node_list[list_idx]->parent == node_list[curr_idx]) + { + SwapNodes(node_list[list_idx], node_list[swap_idx]); + temp = node_list[list_idx]; + node_list[list_idx] = node_list[swap_idx]; + node_list[swap_idx] = temp; + } + else + { + SwapNodes(node_list[curr_idx], node_list[swap_idx]); + temp = node_list[curr_idx]; + node_list[curr_idx] = node_list[swap_idx]; + node_list[swap_idx] = temp; + } + + if(node_list[swap_idx]->parent) + CorrectDHT(node_list[swap_idx]->parent->l_index); + + return; + } + ++swap_idx; + } + } + if(!(node_list[curr_idx]->parent)) + return; + curr_idx = node_list[curr_idx]->parent->l_index; + } +} + +// prevent node frequency from overflowing +static void ResetFrequency() +{ + int idx = list_idx; // start with the bottom left node + + node_list[idx++]->freq = 1; + node_list[idx++]->freq = 1; + + while(node_list[idx]) + { + // if it's a leaf, set it to the minimum possible frequency + if(!node_list[idx]->right) + node_list[idx]->freq = node_list[idx-1]->freq; + // if it's a joint node, set the frequency to left + right + else if(node_list[idx]->left) + node_list[idx]->freq = node_list[idx]->left->freq + node_list[idx]->right->freq; + ++idx; + } +} + +// build the dynamic huffman tree +static void BuildDHT (unsigned char data) +{ + struct DHTNode *node_ptr = look_up_table[data]; + struct DHTNode *update_node_ptr = NULL; + + // if tree is empty, initialize the tree + if(!DHTroot.freq) + { + null_node_ptr->right = (struct DHTNode *)malloc(sizeof(struct DHTNode)); + SetNode(&DHTroot, 1, 0, NULL, DHTroot.right, NULL); + SetNode(DHTroot.right, 1, data, NULL, NULL, &DHTroot); + + look_up_table[data] = DHTroot.right; + BuildNodeList(look_up_table[data]); + } + // if the data already exists in the tree, + // just increment the node counter + else if(look_up_table[data]) + { + // reset frequencies before they overflow + if(DHTroot.freq+1 > MAX_FREQ) ResetFrequency(); + + // increment node frequency + node_ptr->freq += 1; + + // reduce level of reverse level traversing (optimization) + if(node_ptr->parent != null_node_ptr && node_ptr->freq > node_list[(node_ptr->l_index)+1]->freq) + update_node_ptr = node_ptr; + + // increment frequencies for all its ancestors + node_ptr = node_ptr->parent; + while (node_ptr) + { + node_ptr->freq += 1; + + // reduce level of reverse level traversing (optimization) + if(!update_node_ptr && node_ptr->parent && node_ptr->freq > node_list[(node_ptr->l_index)+1]->freq) + update_node_ptr = node_ptr; + + node_ptr = node_ptr->parent; + } + + // correct the dynamic huffman tree if neccessary + if(update_node_ptr) CorrectDHT(update_node_ptr->l_index); + } + // if it's a new data, insert it into a new node + else + { + // reset frequencies before they overflow + if(DHTroot.freq+1 > MAX_FREQ) ResetFrequency(); + + null_node_ptr->left = (struct DHTNode *)malloc(sizeof(struct DHTNode)); + SetNode(null_node_ptr->left, 1, 0, NULL, NULL, null_node_ptr); + null_node_ptr = null_node_ptr->left; + + null_node_ptr->right = (struct DHTNode *)malloc(sizeof(struct DHTNode)); + SetNode(null_node_ptr->right, 1, data, NULL, NULL, null_node_ptr); + + look_up_table[data] = null_node_ptr->right; + BuildNodeList(look_up_table[data]); + + // increment frequencies of all its ancestors + node_ptr = null_node_ptr->parent; + while (node_ptr) + { + node_ptr->freq += 1; + + // reduce level of reverse level traversing (optimization) + if(!update_node_ptr && node_ptr->parent && node_ptr->freq > node_list[(node_ptr->l_index)+1]->freq) + update_node_ptr = node_ptr; + + node_ptr = node_ptr->parent; + } + + // correct the dynamic huffman tree if necessary + if(update_node_ptr) CorrectDHT(list_idx); + } +} + +// clean-ups +static void DestroyDHT() +{ + int i; + + // free all nodes in the dynamic huffman tree + // and reset the node list + while(list_idx < MAX_LIST_LEN-3) + { + if (node_list[list_idx]) { + free(node_list[list_idx]); + node_list[list_idx] = NULL; + } + ++list_idx; + } + node_list[MAX_LIST_LEN-2]=NULL; + node_list[MAX_LIST_LEN-1]=NULL; + list_idx = MAX_LIST_LEN - 1; + + // reset lookup table + for(i=0; i<257; i++) + { + look_up_table[i] = NULL; + } + + // reset the root node and null node pointer + SetNode (&DHTroot,0,0,NULL,NULL,NULL); + null_node_ptr = &DHTroot; + end_of_buffer = 0; +} + +// return the reverse path for the data existing in the tree +static UINT32 ReverseDataPath(struct DHTNode *node_ptr) +{ + UINT32 path_reverse = 0; + code_length = 0; + + while(node_ptr->parent) + { + path_reverse <<= 1; + + if(node_ptr->parent->left == node_ptr) + path_reverse &= 0xFFFFFFFE; // fill the bit with 0 + else + path_reverse |= 1; // fill the bit with 1 + + node_ptr = node_ptr->parent; + ++code_length; + } + + return path_reverse; +} + +// generates and return a reverse code +static UINT32 GenerateReverseCode(unsigned char data) +{ + UINT32 path_reverse=0; + UINT32 code_reverse=0; + int i; + + // this data exists in the tree, so code is just + // return the reverse path of the data + if(look_up_table[data]) return ReverseDataPath(look_up_table[data]); + + // reverse the code + for(i=0;i<8;i++) + { + code_reverse <<= 1; // shift path_reverse 1 bit to the left + code_reverse |= data&1; // get the first bit + data >>= 1; // shift data 1 bit to the right + } + + // tree is empty, the reverse code is + // just the original data reversed. + if(!DHTroot.freq) + { + code_length = 8; + return code_reverse; // return the reversed code + } + + // it's a new data. get the reverse path for the null + // node and append it after the reverse code + path_reverse = ReverseDataPath(node_list[list_idx]->parent); + ++code_length; // for the null node path (0) + code_reverse <<= code_length; + code_length += 8; + return code_reverse | path_reverse; +} + +//# +//# Functions for Buffer Handling +//# +//############################################################################## + +// takes a decompressed file and compresses the whole thing into another file +int Compress(char *d_file_name, char *c_file_name) +{ + int i,nRet; + UINT32 code_slice; + unsigned char data; + int byte_count; + int bytes_remain; + + nRet = OpenDecompressedFile(d_file_name,"rb"); + if(nRet) return nRet; + + nRet = OpenCompressedFile(c_file_name,"wb"); + if(nRet) return nRet; + + // get file size (# of bytes) + fseek(dFile,0,SEEK_END); + byte_count = ftell(dFile); + fseek(dFile,0,SEEK_SET); + + // if buffer is smaller than the file, load max allowed bytes + // into the buffer, otherwise, load everything into the buffer + if(byte_count*4 > MAX_BUFFER_LEN) + fread(d_buffer,4,MAX_BUFFER_LEN,dFile); + else + fread(d_buffer,1,byte_count,dFile); + + d_buffer_idx = 0; + code_slice = d_buffer[0]; + bytes_remain = byte_count%4; + byte_count /= 4; + + for(i=0;i>24); + EncodeBuffer(data); + data = (unsigned char)((code_slice>>16)&0xFF); + EncodeBuffer(data); + data = (unsigned char)((code_slice>>8)&0xFF); + EncodeBuffer(data); + data = (unsigned char)(code_slice&0xFF); + EncodeBuffer(data); + + // prevent buffer overflow + if(++d_buffer_idx == MAX_BUFFER_LEN) {ReloadBufferD();} + code_slice = d_buffer[d_buffer_idx]; + } + if(bytes_remain) + { + code_slice <<= 32 - (bytes_remain*8); + for(i=0;i>24); + EncodeBuffer(data); + code_slice <<= 8; + } + } + CloseDecompressedFile(); + WriteCompressedFile(); + return nRet; +} + +// takes a compressed file and decompresses the whole thing into another file +int Decompress(char *c_file_name, char *d_file_name) +{ + int remainder = 32; + UINT32 code_slice = 0; + int bytes_remain = 0; + int nRet; + + nRet = OpenCompressedFile(c_file_name,"rb"); + if(nRet) return nRet; + + nRet = OpenDecompressedFile(d_file_name,"wb"); + if(nRet) return nRet; + + LoadCompressedFile(); + + d_buffer[0] = 0; + d_buffer_idx = 0; + + while(!end_of_buffer) + { + code_slice = (UINT32)DecodeBuffer(); + remainder -= 8; + code_slice <<= remainder; + d_buffer[d_buffer_idx] |= code_slice; + + if(!remainder) + { + if(++d_buffer_idx == MAX_BUFFER_LEN) ResetBufferD(); + d_buffer[d_buffer_idx] = 0; + remainder = 32; + } + } + bytes_remain = (32-remainder)/8; + + CloseCompressedFile(); + WriteDecompressedFile(bytes_remain); + return nRet; +} + +// take a data and encode it into c_buffer +void EncodeBuffer(unsigned char data) +{ + static int remainder = 32; // how many bits are left in current buffer element + UINT32 code = 0; // code that is ready to put into the buffer + UINT32 code_temp = 0; // used to break the code into two parts + UINT32 code_reverse; + int i; + + // at the beginning, reset everything + // also fill 0s for the headers (coude_count, code_reset_count, buffer_reset_count) + if(!DHTroot.freq) + { + remainder = 32; + code_count = 0; + code_reset_count = 0; + c_buffer_idx = 0; + buffer_reset_count = 0; + + // leave space for the 4 flags + fwrite(&code_count,sizeof(int),4,cFile); + } + + // generate reverse code for the data + code_reverse = GenerateReverseCode(data); + + // put the data in the tree + BuildDHT(data); + + // check for overflow and reset code counter + if(code_count+1 > MAX_FREQ) { code_count=DHTroot.freq; ++code_reset_count; } + else ++code_count; + + // convert the reversed code to original code + for(i=0;i>= 1; + } + + // calculate how many bits would remain in current buffer element after putting the code + remainder -= code_length; + + // if enough bits left to put the code, just put the code + if(remainder > 0) + { + code <<= remainder; + c_buffer[c_buffer_idx] |= code; + } + // if it will fit in perfectly, put the code, and increment buffer index + else if(remainder == 0) + { + c_buffer[c_buffer_idx] |= code; + remainder = 32; + + // prevent buffer overflow + if(++c_buffer_idx == MAX_BUFFER_LEN) {++buffer_reset_count; ResetBufferC();} + + // get next buffer element ready + c_buffer[c_buffer_idx] = 0; + } + // if not enough bits left to put the code + else + { + // retrieve part of the code + for(i=0;i>remainder;i--) + { + code_temp <<= 1; + code_temp |= code&1; + code >>= 1; + } + // put part of the code in the remaining bits of the current buffer element + c_buffer[c_buffer_idx] |= code; + + // retrieve rest of the code + for(i=0;i>remainder;i--) + { + code <<= 1; + code |= code_temp&1; + code_temp >>= 1; + } + remainder += 32; + code <<= remainder; + // prevent buffer overflow + if(++c_buffer_idx == MAX_BUFFER_LEN) {++buffer_reset_count; ResetBufferC();} + + // put the rest of the code in the next buffer element + c_buffer[c_buffer_idx] = code; + } +} + +// decode and return the next data from c_buffer +unsigned char DecodeBuffer() +{ + struct DHTNode *node_ptr = &DHTroot; // start with the root node + static UINT32 code_slice = 0; // slice of a buffer element + static int bit_counter = 0; // if 32, get a new slice + static unsigned int nCode = 0; // how many codes has been decoded so far + static int nCodeReset = 0; // how many times the data counter has been reset + static int nBuffer = 0; // how many times the buffer has been reset + unsigned char data = 0; // decoded data + int isData = 0; + int i; + + // if it's the first code, reset everything and decode the first data + // otherwise, get the next data + if(!DHTroot.freq) + { + c_buffer_idx = 0; + end_of_buffer = 0; + + code_slice = c_buffer[c_buffer_idx]; + data = (unsigned char)(code_slice>>24); + code_slice <<= 8; + + nCodeReset = 0; + nBuffer = 0; + nCode = 0; + bit_counter = 8; + } + else + { + do + { + isData = 0; + + // if it's the end of the code slice, get the next slice + if(bit_counter==32) + { + // prevent buffer overflow + if(++c_buffer_idx == MAX_BUFFER_LEN) { ++nBuffer; ReloadBufferC(); } + + code_slice=c_buffer[c_buffer_idx]; + bit_counter=0; + } + + // if next bit is 1, go to right. if it is 0, goto left + if(code_slice&0x80000000) + node_ptr = node_ptr->right; + else + node_ptr = node_ptr->left; + code_slice <<= 1; + ++bit_counter; + + // if it is a data node, just copy the data from that node + if(node_ptr && !node_ptr->right) + { + data = node_ptr->value; + isData = 1; + } + + // if the it's a new data, get the next 8 bits + else if(node_ptr==NULL) + { + for(i=0;i<8;i++) + { + // if it's the end of the code slice, get the next slice. + if(bit_counter==32) + { + // prevent buffer overflow + if(++c_buffer_idx == MAX_BUFFER_LEN) { ++nBuffer; ReloadBufferC(); } + + code_slice = c_buffer[c_buffer_idx]; + bit_counter = 0; + } + data <<= 1; + data |= code_slice>>31; + code_slice <<= 1; + ++bit_counter; + } + isData = 1; + } // end of 'else if(node_ptr==NULL)' + } while (!isData); + } // end of 'if(DHTroot.freq)' + + BuildDHT(data); + + // prevent code count overflow + if(nCode+1 > MAX_FREQ) { nCode = DHTroot.freq; ++nCodeReset; } + else ++nCode; + + // if everything has been decoded, set end_of_buffer flag + if(nBuffer == buffer_reset_count && nCodeReset == code_reset_count && nCode == code_count) + { + end_of_buffer=1; + } + + return data; // return the decoded data +} + +// prevent c_buffer overflow while encoding +static void ResetBufferC() +{ + fwrite(c_buffer,4,MAX_BUFFER_LEN,cFile); // write buffer to the file + c_buffer_idx = 0; // restart the buffer +} + +// prevent c_buffer overflow while decoding +static void ReloadBufferC() +{ + fread(c_buffer,4,MAX_BUFFER_LEN,cFile); // read max allowed bytes into buffer + c_buffer_idx = 0; // restart the buffer +} + +// prevent d_buffer foverflow while encoding +static void ReloadBufferD() +{ + fread(d_buffer,4,MAX_BUFFER_LEN,dFile); + d_buffer_idx = 0; +} + +// prevent d_buffer overflow while decoding +static void ResetBufferD() +{ + fwrite(d_buffer,4,MAX_BUFFER_LEN,dFile); + d_buffer_idx = 0; +} + +//# +//# Functions for File I/O +//# +//############################################################################## + +// return 0 if the compressed file is opened sucessfully, 1 otherwise +int OpenCompressedFile(char *file_name, char *mode) +{ + if(cFile) fclose(cFile); + cFile = NULL; + + cFile = fopen(file_name, mode); + if (cFile) return 0; + + return 1; +} + +// Always returns 0 +int EmbedCompressedFile(FILE *pEmb, int nOffset) +{ + if(cFile) fclose(cFile); + cFile = NULL; + + cFile = pEmb; + bEmbed = 1; + if (nOffset >= 0) { + embed_offset = nOffset; + fseek(cFile,nOffset,SEEK_SET); + } else { + if (nOffset == -2) { + fseek(cFile,0,SEEK_END); + } + embed_offset = ftell(cFile); + } + return 0; +} + +// return 0 if the decompressed file is opened sucessfully, 1 otherwise +int OpenDecompressedFile(char *file_name, char *mode) +{ + dFile = NULL; + dFile = fopen(file_name, mode); + if (dFile) return 0; + return 1; +} + +// load the compressed file into the c_buffer +// - call this function only if the compressed file is opened successfully +void LoadCompressedFile() +{ + int byte_count; + + // load the flags + fread(&byte_count,sizeof(int),1,cFile); + fread(&code_count,sizeof(int),1,cFile); + fread(&code_reset_count,sizeof(int),1,cFile); + fread(&buffer_reset_count,sizeof(int),1,cFile); + + // if buffer is smaller than the file, load max allowed bytes + // into the buffer, otherwise, load everything into the buffer + if(byte_count*4 > MAX_BUFFER_LEN) + fread(c_buffer,4,MAX_BUFFER_LEN,cFile); + else + fread(c_buffer,1,byte_count,cFile); +} + +// write whatever is left in the c_buffer to the +// compressed file, and close the compressed file +// - use this if the compressed file was opened in 'write' mode +void WriteCompressedFile() +{ + if(cFile) + { + // write what's left in the buffer to the file + fwrite(c_buffer,4,c_buffer_idx+1,cFile); + + // save file size, code count, etc + SaveResult(); + + // handle file embedding + fseek(cFile,embed_offset,SEEK_SET); + + fwrite(&nCompressedFileSize,sizeof(int),1,cFile); + fwrite(&nCodeCount,sizeof(int),1,cFile); + fwrite(&nCodeResetCount,sizeof(int),1,cFile); + fwrite(&nBufferResetCount,sizeof(int),1,cFile); + + CloseCompressedFile(); + } +} + +// write whatever is left in the d_buffer to the +// decompressed file, and close the decompressed file +// - use this if the decompressed file was opened in 'write' mode +void WriteDecompressedFile(int bytes_remain) +{ + UINT32 code_slice; + int i; + + if(dFile) + { + // write the buffer to the file + if(d_buffer_idx) fwrite(d_buffer,4,d_buffer_idx,dFile); + if(bytes_remain) + { + code_slice = d_buffer[d_buffer_idx]; + for(i=0;i<(4-bytes_remain);i++) + { + code_slice >>= 8; + } + fwrite(&code_slice,1,bytes_remain,dFile); + } + + fclose(dFile); + dFile = NULL; + } +} + +// close the compressed file +// - use this if the compressed file was opened in 'read' mode +void CloseCompressedFile() +{ + if(cFile) + { + // handle file embedding + if (!bEmbed) { + fclose(cFile); + } + + cFile = NULL; + embed_offset = 0; + bEmbed = 0; + +#ifdef _DEBUG + // PrintTree(); + CheckList(); +#endif + + DestroyDHT(); + } +} + +// close the decompressed file +// - use this if the decompressed file was opened in 'read' mode +void CloseDecompressedFile() +{ + if(dFile) + { + fclose(dFile); + dFile = NULL; + } +} + +//# +//# Utility Functions for Debugging Purpose +//# +//############################################################################## + +// print the node frequency while reverse level traversing +void PrintFreqTraverse() +{ + int curr_idx = list_idx; + + printf("Frequency Traverse -"); + while(node_list[curr_idx]) + { + printf(" %d",node_list[curr_idx]->freq); + if(node_list[curr_idx]->value) printf(":%c",node_list[curr_idx]->value); + ++curr_idx; + } +} + +// print the tree view (rotated -90 degrees) +void PrintTreeBreath(struct DHTNode *node_ptr, int spaces) +{ + int i; + int num_digits; + int tab_len; + if(node_ptr) + { + num_digits = node_ptr->freq; + tab_len = spaces; + PrintTreeBreath(node_ptr->right, spaces+7); // right tree first + + num_digits=num_digits/10; + while(num_digits) { --tab_len; num_digits=num_digits/10;} + for(i=0;ifreq); + if(node_ptr->value) printf(":%c",node_ptr->value); + printf("\n"); + + PrintTreeBreath(node_ptr->left, spaces+7); // then left tree + } +} + +// print the header, then print the tree in breath order +void PrintTree() +{ + printf("View of the Tree (rotated -90 degrees)\n"); + PrintTreeBreath(&DHTroot, 0); +} + +// check the reverse traverse list and print any frequencies that are out of order +#ifdef _DEBUG +static void CheckList() +{ + int curr_idx = list_idx; + int count_errors = 0; + while(curr_idx < MAX_LIST_LEN-3) + { + if(node_list[curr_idx]->freq > node_list[curr_idx+1]->freq) + printf("\nError: list is out of order.\n%d\n%d\n",node_list[curr_idx]->freq,node_list[curr_idx+1]->freq); + + curr_idx++; + count_errors++; + } + if(!count_errors) + printf("\nNo errors in reverse traverse list.\n"); +} +#endif + +// dump the buffer to the screen +void PrintBuffer() +{ + UINT32 i, j; + j = (UINT32)c_buffer_idx; + + printf("buffer = "); + for(i=0;i<=j;i++) printf("%.8X ",c_buffer[i]); +} + +// save compression result +static void SaveResult() +{ + nCompressedFileSize = buffer_reset_count*MAX_BUFFER_LEN*4 + (c_buffer_idx+1+4)*4; // convert to Bytes + nCodeCount = code_count; + nCodeResetCount = code_reset_count; + nBufferIdx = c_buffer_idx; + nBufferResetCount = buffer_reset_count; +} + +// print file size, how many codes, etc +void PrintResult() +{ + printf("\ncompressed file size = %.3f KB\n\n",(double)nCompressedFileSize/1024.0); // convert to KB + printf(" max code count = %u\n", MAX_FREQ); + printf(" current code count = %u\n", nCodeCount); + printf(" # code count reset = %d\n\n",nCodeResetCount); + printf(" max buffer size = %.3f KB\n",(float)(4*MAX_BUFFER_LEN)/1024.0); + printf(" max buffer index = %d\n", MAX_BUFFER_LEN); + printf("current buffer index = %u\n", nBufferIdx); + printf(" # buffer re-used = %d\n\n",nBufferResetCount); +} diff --git a/src/burner/win32/dynhuff.h b/src/burner/win32/dynhuff.h new file mode 100644 index 00000000..bb65f7b2 --- /dev/null +++ b/src/burner/win32/dynhuff.h @@ -0,0 +1,137 @@ +// +// Dynamic Huffman Encoder/Decoder +// +// implemented by Gangta +// +//----------------------------------------------------------- +// +// Version History +// +// version 0.1 - first release +// version 0.1a - fixed a bug where the bit remainder in +// the EncodeBuffer() function didn't reset +// to 32 if encoding is restarted before +// program exit +// version 0.1b - fixed right shift +// - fixed some utility functions +// +// version 0.1c - fixed PrintResult() +// - fixed a fatal bug in CorrectDHT() 15% slower +// - optimized compression/decompression 95% faster +// - overall 80% faster :) +// +// version 0.2 - optimized even more, now O(lg 2) :) +// +//----------------------------------------------------------- +// +// Memory usage: +// +// 128 KB for both encoding/decoding +// +// I tested buffer size 16K, 32K, 64K, 128K, etc +// The performance started to drop after 512K, +// so I chose 128K. +// +// Comments: +// +// I tried to optimize the speed as best I can in my +// knowledge. +// +// It has buffer overflow protection for encoding and +// decoding. +// +// It has a frequency reset function which prevents +// frequency overflow. +// +// It can compress text files as well as any type of +// binary files. The compression is not as good as +// zlib, or bzlibb2, but it supports "on the fly" +// encoding/decoding, and I believe it is faster than +// bzlibb2. +// +// +/////////////////////////////////////////////////////////////// + +#ifndef _DYNHUFF_H_ +#define _DYNHUFF_H_ + +#include + +#define MAX_FREQ ((unsigned int)0xFFFFFFFF) // max unsigned int +#define MAX_BUFFER_LEN 32768 // 4 B * 32768 = 128 KB +#define MAX_LIST_LEN 512 + +//# +//# Buffer Handling +//# +//############################################################################## + +// 1 if decoding is finished, 0 otherwise +extern int end_of_buffer; + +// takes a data and compress it to the buffer +void EncodeBuffer(unsigned char data); + +// decompresses and returns the next data from buffer +unsigned char DecodeBuffer(); + +//# +//# File I/O +//# +//############################################################################## + +// takes a decompressed file and compresses the whole thing into another file +int Compress(char *d_file_name, char *c_file_name); + +// takes a compressed file and decompresses the whole thing into another file +int Decompress(char *c_file_name, char *d_file_name); + +// returns 0 if the compressed file is opened successfully, 1 otherwise +int OpenCompressedFile(char *file_name, char *mode); + +// Always returns 0 +int EmbedCompressedFile(FILE *pEmb, int nOffset); + +// returns 0 if the decompressed file is opened successfully, 1 otherwise +int OpenDecompressedFile(char *file_name, char *mode); + +// loads the compressed file into c_buffer +// - use it only if the compressed file was opened successfully +void LoadCompressedFile(); + +// writes whatever is left in c_buffer to the compressed file, +// and closes the compressed file +// - use this if the compressed file was opened in 'write' mode +void WriteCompressedFile(); + +// writes whatever is left in d_buffer to the decompressed file, +// and closes the decompressed file +// - use this if the decompressed file was opened in 'write' mode +void WriteDecompressedFile(int bytes_remain); + +// closes the compressed file +// - use this if the compressed file was opened in 'read' mode +void CloseCompressedFile(); + +// closes the compressed file +// - use this if the decompressed file was opened in 'read' mode +void CloseDecompressedFile(); + +//# +//# Utility Functions +//# +//############################################################################## + +// print the encoded buffer (upto the current buffer item) +void PrintBuffer(); // use this while encoding + +// print all nodes while reverse level traversing +void PrintFreqTraverse(); // use this before DestroyDHT() happens + +// print the tree in breath order (rotated -90 degrees) +void PrintTree(); // use this before DestroyDHT() happens + +// print compression result +void PrintResult(); // use this after finish encoding + +#endif // end of '#ifndef _DYNHUFF_H_' diff --git a/src/burner/win32/fba_kaillera.cpp b/src/burner/win32/fba_kaillera.cpp new file mode 100644 index 00000000..81a31ca2 --- /dev/null +++ b/src/burner/win32/fba_kaillera.cpp @@ -0,0 +1,213 @@ +#include "burner.h" + +const int MAXPLAYER = 4; +static int nPlayerInputs[MAXPLAYER], nCommonInputs, nDIPInputs; +static int nPlayerOffset[MAXPLAYER], nCommonOffset, nDIPOffset; + +const int INPUTSIZE = 8 * (4 + 8); +static unsigned char nControls[INPUTSIZE]; + +// Inputs are assumed to be in the following order: +// All player 1 controls +// All player 2 controls (if any) +// All player 3 controls (if any) +// All player 4 controls (if any) +// All common controls +// All DIP switches + +int KailleraInitInput() +{ + if (nGameInpCount == 0) { + return 1; + } + + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + unsigned int i = 0; + + nPlayerOffset[0] = 0; + do { + BurnDrvGetInputInfo(&bii, i); + i++; + } while (!_strnicmp(bii.szName, "P1", 2) && i <= nGameInpCount); + i--; + nPlayerInputs[0] = i - nPlayerOffset[0]; + + for (int j = 1; j < MAXPLAYER; j++) { + char szString[3] = "P?"; + szString[1] = j + '1'; + nPlayerOffset[j] = i; + while (!_strnicmp(bii.szName, szString, 2) && i < nGameInpCount) { + i++; + BurnDrvGetInputInfo(&bii, i); + } + nPlayerInputs[j] = i - nPlayerOffset[j]; + } + + nCommonOffset = i; + while ((bii.nType & BIT_GROUP_CONSTANT) == 0 && i < nGameInpCount){ + i++; + BurnDrvGetInputInfo(&bii, i); + }; + nCommonInputs = i - nCommonOffset; + + nDIPOffset = i; + nDIPInputs = nGameInpCount - nDIPOffset; + +#if 0 && defined FBA_DEBUG + dprintf(_T(" * Kaillera inputs configured as follows --\n")); + for (int j = 0; j < MAXPLAYER; j++) { + dprintf(_T(" p%d offset %d, inputs %d.\n"), j + 1, nPlayerOffset[j], nPlayerInputs[j]); + } + dprintf(_T(" common offset %d, inputs %d.\n"), nCommonOffset, nCommonInputs); + dprintf(_T(" dip offset %d, inputs %d.\n"), nDIPOffset, nDIPInputs); +#endif + + return 0; +} + +int KailleraGetInput() +{ + int i, j, k; + + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + // Initialize controls to 0 + memset(nControls, 0, INPUTSIZE); + + // Pack all DIP switches + common controls + player 1 controls + for (i = 0, j = 0; i < nPlayerInputs[0]; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nPlayerOffset[0]); + if (*bii.pVal && bii.nType == BIT_DIGITAL) { + nControls[j >> 3] |= (1 << (j & 7)); + } + } + for (i = 0; i < nCommonInputs; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nCommonOffset); + if (*bii.pVal) { + nControls[j >> 3] |= (1 << (j & 7)); + } + } + + // Convert j to byte count + j = (j + 7) >> 3; + + // Analog controls/constants + for (i = 0; i < nPlayerInputs[0]; i++) { + BurnDrvGetInputInfo(&bii, i + nPlayerOffset[0]); + if (*bii.pVal && bii.nType != BIT_DIGITAL) { + if (bii.nType & BIT_GROUP_ANALOG) { + nControls[j++] = *bii.pShortVal >> 8; + nControls[j++] = *bii.pShortVal & 0xFF; + } else { + nControls[j++] = *bii.pVal; + } + } + } + + // DIP switches + for (i = 0; i < nDIPInputs; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nDIPOffset); + nControls[j] = *bii.pVal; + } + + // k has the size of all inputs for one player + k = j + 1; + + // Send the control block to the Kaillera DLL & retrieve all controls + //if (kailleraModifyPlayValues(nControls, k) == -1) { + if (Kaillera_Modify_Play_Values(nControls, k) == -1) { + kNetGame = 0; + return 1; + } + + // Decode Player 1 input block + for (i = 0, j = 0; i < nPlayerInputs[0]; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nPlayerOffset[0]); + if (bii.nType == BIT_DIGITAL) { + if (nControls[j >> 3] & (1 << (j & 7))) { + *bii.pVal = 0x01; + } else { + *bii.pVal = 0x00; + } + } + } + for (i = 0; i < nCommonInputs; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nCommonOffset); + if (nControls[j >> 3] & (1 << (j & 7))) { + *bii.pVal = 0x01; + } else { + *bii.pVal = 0x00; + } + } + + // Convert j to byte count + j = (j + 7) >> 3; + + // Analog inputs + for (i = 0; i < nPlayerInputs[0]; i++) { + BurnDrvGetInputInfo(&bii, i + nDIPOffset); + if (bii.nType & BIT_GROUP_ANALOG) { + *bii.pShortVal = (nControls[j] << 8) | nControls[j + 1]; + j += 2; + } + } + + // DIP switches + for (i = 0; i < nDIPInputs; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nDIPOffset); + *bii.pVal = nControls[j]; + } + + // Decode other player's input blocks + for (int l = 1; l < MAXPLAYER; l++) { + if (nPlayerInputs[l]) { + for (i = 0, j = k * (l << 3); i < nPlayerInputs[l]; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nPlayerOffset[l]); + if (bii.nType == BIT_DIGITAL) { + if (nControls[j >> 3] & (1 << (j & 7))) { + *bii.pVal = 0x01; + } else { + *bii.pVal = 0x00; + } + } + } + + for (i = 0; i < nCommonInputs; i++, j++) { +#if 0 + // Allow other players to use common inputs + BurnDrvGetInputInfo(&bii, i + nCommonOffset); + if (nControls[j >> 3] & (1 << (j & 7))) { + *bii.pVal |= 0x01; + } +#endif + } + + // Convert j to byte count + j = (j + 7) >> 3; + + // Analog inputs/constants + for (i = 0; i < nPlayerInputs[l]; i++) { + BurnDrvGetInputInfo(&bii, i + nPlayerOffset[l]); + if (bii.nType != BIT_DIGITAL) { + if (bii.nType & BIT_GROUP_ANALOG) { + *bii.pShortVal = (nControls[j] << 8) | nControls[j + 1]; + j += 2; + } + } + } + +#if 0 + // For a DIP switch to be set to 1, ALL players must set it + for (i = 0; i < nDIPInputs; i++, j++) { + BurnDrvGetInputInfo(&bii, i + nDIPOffset); + *bii.pVal &= nControls[j]; + } +#endif + } + } + + return 0; +} diff --git a/src/burner/win32/image_win32.cpp b/src/burner/win32/image_win32.cpp new file mode 100644 index 00000000..41aa3153 --- /dev/null +++ b/src/burner/win32/image_win32.cpp @@ -0,0 +1,56 @@ +#include "burner.h" +#include "png.h" + +HBITMAP ImageToBitmap(HWND hwnd, IMAGE* img) +{ + BITMAPINFO bi; + + if (hwnd == NULL || img == NULL) { + return NULL; + } + + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = img->width; + bi.bmiHeader.biHeight = img->height; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 24; + bi.bmiHeader.biCompression = BI_RGB; + bi.bmiHeader.biSizeImage = img->imgbytes; + bi.bmiHeader.biXPelsPerMeter = 0; + bi.bmiHeader.biYPelsPerMeter = 0; + bi.bmiHeader.biClrUsed = 0; + bi.bmiHeader.biClrImportant = 0; + + HDC hDC = GetDC(hwnd); + BYTE* pbits = NULL; + HBITMAP hBitmap = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, (void**)&pbits, NULL, 0); + if (pbits) { + memcpy(pbits, img->bmpbits, img->imgbytes); + } + ReleaseDC(hwnd, hDC); + img_free(img); + + return hBitmap; +} + +HBITMAP PNGLoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset) +{ + IMAGE img = { nWidth, nHeight, 0, 0, NULL, NULL, 0}; + + if (PNGLoad(&img, fp, nPreset)) { + return NULL; + } + + return ImageToBitmap(hWnd, &img); +} + +HBITMAP LoadBitmap(HWND hWnd, FILE* fp, int nWidth, int nHeight, int nPreset) +{ + if (hWnd == NULL || fp == NULL) { + return NULL; + } + + if (PNGIsImage(fp)) return PNGLoadBitmap(hWnd, fp, nWidth, nHeight, nPreset); + + return NULL; +} diff --git a/src/burner/win32/inpc.cpp b/src/burner/win32/inpc.cpp new file mode 100644 index 00000000..1bd8734f --- /dev/null +++ b/src/burner/win32/inpc.cpp @@ -0,0 +1,126 @@ +// Burner Input Constant dialog module +#include "burner.h" + +HWND hInpcDlg = NULL; // Handle to the Input Dialog +unsigned int nInpcInput = 0; // The input number we are redefining + +static HWND hValue = NULL; // Handle to value edit control +static struct GameInp* pgi = NULL; // Current GameInp + +static int InpcInit() +{ + TCHAR szOldTitle[1024] = _T(""); + TCHAR szNewTitle[1024] = _T(""); + int nCurrent = 0; + + struct BurnInputInfo bii; // Info about the input + + hValue = GetDlgItem(hInpcDlg, IDC_INPC_VALUE); // Get Edit controls + + // Get the extra info about the input + memset(&bii, 0, sizeof(bii)); + BurnDrvGetInputInfo(&bii, nInpcInput); + if (bii.szName == NULL) { + bii.szName= ""; + } + + // Set the dialog title + GetWindowText(hInpcDlg, szOldTitle, 1024); + _sntprintf(szNewTitle, 1024, _T(APP_TITLE) _T(SEPERATOR_1) _T("%s %hs"), szOldTitle, bii.szName); + SetWindowText(hInpcDlg, szNewTitle); + + pgi = NULL; + if (nInpcInput >= nGameInpCount) { // input out of range + return 1; + } + pgi = GameInp + nInpcInput; + + // Get current constant + if (pgi->nInput == GIT_CONSTANT) { + nCurrent=pgi->Input.Constant.nConst; } + _stprintf(szNewTitle, _T("0x%.2X"), nCurrent); + SetWindowText(hValue, szNewTitle); + + return 0; +} + +static int InpcExit() +{ + pgi=NULL; + hValue=NULL; + hInpcDlg=NULL; + + return 0; +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM /*lParam*/) +{ + if (Msg == WM_INITDIALOG) { // 1 = we didn't set focus? + hInpcDlg = hDlg; + InpcInit(); + + return 1; + } + if (Msg == WM_CLOSE){ + DestroyWindow(hInpcDlg); + + return 0; + } + if (Msg == WM_DESTROY) { + InpcExit(); + + return 0; + } + + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + if (Id == IDOK && Notify == BN_CLICKED) { // OK = close + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + if (Id == IDCANCEL && Notify == BN_CLICKED) { // cancel = close + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + if (Id == IDC_INPC_VALUE && Notify == EN_CHANGE) { + // Edit box may have been changed + TCHAR szNew[16] = _T(""); + int nVal = 0; + + if (pgi == NULL) { + return 0; + } + + GetWindowText(hValue, szNew, sizeof(szNew)); + + // Set new constant + pgi->nInput = GIT_CONSTANT; + nVal = _tcstol(szNew, NULL, 0); + pgi->Input.Constant.nConst = (unsigned char)nVal; + + InpdListMake(0); // refresh view + + return 0; + } + } + + return 0; +} + +int InpcCreate() +{ + DestroyWindow(hInpcDlg); + hInpcDlg = NULL; + + hInpcDlg = FBACreateDialog(hAppInst, MAKEINTRESOURCE(IDD_INPC), hInpdDlg, (DLGPROC)DialogProc); + if (hInpcDlg == NULL) { + return 1; + } + + WndInMid(hInpcDlg, hInpdDlg); + ShowWindow(hInpcDlg, SW_NORMAL); + + return 0; +} diff --git a/src/burner/win32/inpcheat.cpp b/src/burner/win32/inpcheat.cpp new file mode 100644 index 00000000..a94da68a --- /dev/null +++ b/src/burner/win32/inpcheat.cpp @@ -0,0 +1,277 @@ +#include "burner.h" + +HWND hInpCheatDlg = NULL; // Handle to the Cheat Dialog + +static HWND hInpCheatList = NULL; + +static bool bOK; + +static int nCurrentCheat; +static int* nPrevCheatSettings = NULL; + +static int InpCheatListBegin() +{ + LVCOLUMN LvCol; + if (hInpCheatList == NULL) { + return 1; + } + + // Full row select style: + SendMessage(hInpCheatList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + // Make column headers + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + LvCol.cx = 0xA4; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_CHEAT_NAME, true); + SendMessage(hInpCheatList, LVM_INSERTCOLUMN, 0, (LPARAM)&LvCol); + LvCol.cx = 0xA4; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_CHEAT_STATUS, true); + SendMessage(hInpCheatList, LVM_INSERTCOLUMN, 1, (LPARAM)&LvCol); + + return 0; +} + +// Make a list view of the DIPswitches +static int InpCheatListMake() +{ + if (hInpCheatList == NULL) { + return 1; + } + + SendMessage(hInpCheatList, LVM_DELETEALLITEMS, 0, 0); + + int i = 0; + CheatInfo* pCurrentCheat = pCheatInfo; + + while (pCurrentCheat) { + + LVITEM LvItem; + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = i; + LvItem.iSubItem = 0; + LvItem.pszText = pCurrentCheat->szCheatName; + SendMessage(hInpCheatList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + LvItem.mask = LVIF_TEXT; + LvItem.iSubItem = 1; + LvItem.pszText = pCurrentCheat->pOption[pCurrentCheat->nCurrent]->szOptionName; + SendMessage(hInpCheatList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + pCurrentCheat = pCurrentCheat->pNext; + i++; + } + + return 0; +} + +static int InpCheatInit() +{ + hInpCheatList = GetDlgItem(hInpCheatDlg, IDC_INPCHEAT_LIST); + InpCheatListBegin(); + InpCheatListMake(); + + // Save old cheat settings + CheatInfo* pCurrentCheat = pCheatInfo; + nCurrentCheat = 0; + while (pCurrentCheat) { + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + + nPrevCheatSettings = (int*)malloc(nCurrentCheat * sizeof(int)); + + pCurrentCheat = pCheatInfo; + nCurrentCheat = 0; + while (pCurrentCheat) { + nPrevCheatSettings[nCurrentCheat] = pCurrentCheat->nCurrent; + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + + return 0; +} + +static int InpCheatExit() +{ + if (nPrevCheatSettings) { + free(nPrevCheatSettings); + nPrevCheatSettings = NULL; + } + + hInpCheatList = NULL; + hInpCheatDlg = NULL; + if(!bAltPause && bRunPause) { + bRunPause = 0; + } + GameInpCheckMouse(); + return 0; +} + +static void InpCheatCancel() +{ + if (!bOK) { + CheatInfo* pCurrentCheat = pCheatInfo; + nCurrentCheat = 0; + while (pCurrentCheat) { + CheatEnable(nCurrentCheat, nPrevCheatSettings[nCurrentCheat]); + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + } +} + +static void InpCheatSelect() +{ + SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_RESETCONTENT, 0, 0); + + int nSel = SendMessage(hInpCheatList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED); + if (nSel >= 0) { + LVITEM LvItem; + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_PARAM; + LvItem.iItem = nSel; + SendMessage(hInpCheatList, LVM_GETITEM, 0, (LPARAM)&LvItem); + + CheatInfo* pCurrentCheat = pCheatInfo; + nCurrentCheat = 0; + while (pCurrentCheat && nCurrentCheat < nSel) { + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + + for (int i = 0; pCurrentCheat->pOption[i]; i++) { + TCHAR szText[256]; + _stprintf(szText, _T("%s: %s"), pCurrentCheat->szCheatName, pCurrentCheat->pOption[i]->szOptionName); + SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_ADDSTRING, 0, (LPARAM)szText); + } + + SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_SETCURSEL, (WPARAM)pCurrentCheat->nCurrent, 0); + } +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + +// EnableWindow(hScrnWnd, FALSE); + + hInpCheatDlg = hDlg; + InpCheatInit(); + if (!kNetGame && bAutoPause) { + bRunPause = 1; + } + + WndInMid(hDlg, hScrnWnd); + SetFocus(hDlg); // Enable Esc=close + + return TRUE; + } + + if (Msg == WM_CLOSE) { + EnableWindow(hScrnWnd, TRUE); + DestroyWindow(hInpCheatDlg); + return 0; + } + + if (Msg == WM_DESTROY) { + InpCheatCancel(); + InpCheatExit(); + return 0; + } + + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Id == IDOK && Notify == BN_CLICKED) { // OK button + bOK = true; + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + if (Id == IDCANCEL && Notify == BN_CLICKED) { // cancel = close + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + if (Id == IDC_INPCX1_VALUE && Notify == CBN_SELCHANGE) { + + int nSel = SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_GETCURSEL, 0, 0); + + CheatEnable(nCurrentCheat, nSel); + + InpCheatListMake(); + return 0; + } + + if (Id == IDC_INPC_RESET && Notify == BN_CLICKED) { + + CheatInfo* pCurrentCheat = pCheatInfo; + nCurrentCheat = 0; + while (pCurrentCheat) { + CheatEnable(nCurrentCheat, -1); + pCurrentCheat = pCurrentCheat->pNext; + nCurrentCheat++; + } + + InpCheatListMake(); // refresh view + SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_RESETCONTENT, 0, 0); + return 0; + } + + } + + if (Msg == WM_NOTIFY && lParam) { + int Id = LOWORD(wParam); + NMHDR *pnm = (NMHDR*)lParam; + + if (Id == IDC_INPCHEAT_LIST && pnm->code == LVN_ITEMCHANGED) { + if (((NM_LISTVIEW*)lParam)->uNewState & LVIS_SELECTED) { + InpCheatSelect(); + } + return 0; + } + + if (Id == IDC_INPCHEAT_LIST && ((pnm->code == NM_DBLCLK) || (pnm->code == NM_RDBLCLK))) { + // Select the next item of the currently selected one. + int nSel_Dbl = SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_GETCURSEL, 0, 0); + int nCount = SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_GETCOUNT, 0, 0); + if ((nSel_Dbl != LB_ERR) && (nCount > 1)) { + if (pnm->code == NM_DBLCLK) { + if (++nSel_Dbl >= nCount) nSel_Dbl = 0; + } else { + if (--nSel_Dbl < 0) nSel_Dbl = nCount - 1; + } + SendMessage(GetDlgItem(hInpCheatDlg, IDC_INPCX1_VALUE), CB_SETCURSEL, nSel_Dbl, 0); + CheatEnable(nCurrentCheat, nSel_Dbl); + InpCheatListMake(); + } + return 0; + } + } + + return 0; +} + +int InpCheatCreate() +{ + if (bDrvOkay == 0) { // No game is loaded + return 1; + } + + bOK = false; + +// DestroyWindow(hInpCheatDlg); // Make sure exitted + +// hInpCheatDlg = FBACreateDialog(hAppInst, MAKEINTRESOURCE(IDD_INPCHEAT), hScrnWnd, DialogProc); +// if (hInpCheatDlg == NULL) { +// return 1; +// } + +// WndInMid(hInpCheatDlg, hScrnWnd); +// ShowWindow(hInpCheatDlg, SW_NORMAL); + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_INPCHEAT), hScrnWnd, (DLGPROC)DialogProc); + + return 0; +} + diff --git a/src/burner/win32/inpd.cpp b/src/burner/win32/inpd.cpp new file mode 100644 index 00000000..46507468 --- /dev/null +++ b/src/burner/win32/inpd.cpp @@ -0,0 +1,905 @@ +// Burner Input Dialog module +#include "burner.h" + +HWND hInpdDlg = NULL; // Handle to the Input Dialog +static HWND hInpdList = NULL; +static unsigned char *LastVal = NULL; // Last input values/defined +static int bLastValDefined = 0; // + +static HWND hInpdGi = NULL, hInpdPci = NULL, hInpdAnalog = NULL; // Combo boxes + +// Update which input is using which PC input +static int InpdUseUpdate() +{ + unsigned int i, j = 0; + struct GameInp* pgi = NULL; + if (hInpdList == NULL) { + return 1; + } + + // Update the values of all the inputs + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + LVITEM LvItem; + TCHAR* pszVal = NULL; + + if (pgi->Input.pVal == NULL) { + continue; + } + + pszVal = InpToDesc(pgi); + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = j; + LvItem.iSubItem = 1; + LvItem.pszText = pszVal; + + SendMessage(hInpdList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + j++; + } + + for (i = 0, pgi = GameInp + nGameInpCount; i < nMacroCount; i++, pgi++) { + LVITEM LvItem; + TCHAR* pszVal = NULL; + + if (pgi->nInput & GIT_GROUP_MACRO) { + pszVal = InpMacroToDesc(pgi); + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = j; + LvItem.iSubItem = 1; + LvItem.pszText = pszVal; + + SendMessage(hInpdList, LVM_SETITEM, 0, (LPARAM)&LvItem); + } + + j++; + } + + return 0; +} + +int InpdUpdate() +{ + unsigned int i, j = 0; + struct GameInp* pgi = NULL; + unsigned char* plv = NULL; + unsigned short nThisVal; + if (hInpdList == NULL) { + return 1; + } + if (LastVal == NULL) { + return 1; + } + + // Update the values of all the inputs + for (i = 0, pgi = GameInp, plv = LastVal; i < nGameInpCount; i++, pgi++, plv++) { + LVITEM LvItem; + TCHAR szVal[16]; + + if (pgi->nType == 0) { + continue; + } + + if (pgi->nType & BIT_GROUP_ANALOG) { + if (bRunPause) { // Update LastVal + nThisVal = pgi->Input.nVal; + } else { + nThisVal = *pgi->Input.pShortVal; + } + + if (bLastValDefined && (pgi->nType != BIT_ANALOG_REL || nThisVal) && pgi->Input.nVal == *((unsigned short*)plv)) { + j++; + continue; + } + + *((unsigned short*)plv) = nThisVal; + } else { + if (bRunPause) { // Update LastVal + nThisVal = pgi->Input.nVal; + } else { + nThisVal = *pgi->Input.pVal; + } + + if (bLastValDefined && pgi->Input.nVal == *plv) { // hasn't changed + j++; + continue; + } + + *plv = nThisVal; + } + + switch (pgi->nType) { + case BIT_DIGITAL: { + if (nThisVal == 0) { + szVal[0] = 0; + } else { + if (nThisVal == 1) { + _tcscpy(szVal, _T("ON")); + } else { + _stprintf(szVal, _T("0x%02X"), nThisVal); + } + } + break; + } + case BIT_ANALOG_ABS: { + _stprintf(szVal, _T("0x%02X"), nThisVal >> 8); + break; + } + case BIT_ANALOG_REL: { + if (nThisVal == 0) { + szVal[0] = 0; + } + if ((short)nThisVal < 0) { + _stprintf(szVal, _T("%d"), ((short)nThisVal) >> 8); + } + if ((short)nThisVal > 0) { + _stprintf(szVal, _T("+%d"), ((short)nThisVal) >> 8); + } + break; + } + default: { + _stprintf(szVal, _T("0x%02X"), nThisVal); + } + } + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = j; + LvItem.iSubItem = 2; + LvItem.pszText = szVal; + + SendMessage(hInpdList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + j++; + } + + bLastValDefined = 1; // LastVal is now defined + + return 0; +} + +static int InpdListBegin() +{ + LVCOLUMN LvCol; + if (hInpdList == NULL) { + return 1; + } + + // Full row select style: + SendMessage(hInpdList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + + // Make column headers + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + + LvCol.cx = 0x90; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_INPUT_INPUT, true); + SendMessage(hInpdList, LVM_INSERTCOLUMN, 0, (LPARAM)&LvCol); + + LvCol.cx = 0x90; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_INPUT_MAPPING, true); + SendMessage(hInpdList, LVM_INSERTCOLUMN, 1, (LPARAM)&LvCol); + + LvCol.cx = 0x28; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_INPUT_STATE, true); + SendMessage(hInpdList, LVM_INSERTCOLUMN, 2, (LPARAM)&LvCol); + + return 0; +} + +// Make a list view of the game inputs +int InpdListMake(int bBuild) +{ + unsigned int j = 0; + + if (hInpdList == NULL) { + return 1; + } + + bLastValDefined = 0; + if (bBuild) { + SendMessage(hInpdList, LVM_DELETEALLITEMS, 0, 0); + } + + // Add all the input names to the list + for (unsigned int i = 0; i < nGameInpCount; i++) { + struct BurnInputInfo bii; + LVITEM LvItem; + + // Get the name of the input + bii.szName = NULL; + BurnDrvGetInputInfo(&bii, i); + + // skip unused inputs + if (bii.pVal == NULL) { + continue; + } + if (bii.szName == NULL) { + bii.szName = ""; + } + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT | LVIF_PARAM; + LvItem.iItem = j; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(bii.szName, NULL, 0); + LvItem.lParam = (LPARAM)i; + + SendMessage(hInpdList, bBuild ? LVM_INSERTITEM : LVM_SETITEM, 0, (LPARAM)&LvItem); + + j++; + } + + struct GameInp* pgi = GameInp + nGameInpCount; + for (unsigned int i = 0; i < nMacroCount; i++, pgi++) { + LVITEM LvItem; + + if (pgi->nInput & GIT_GROUP_MACRO) { + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT | LVIF_PARAM; + LvItem.iItem = j; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(pgi->Macro.szName, NULL, 0); + LvItem.lParam = (LPARAM)j; + + SendMessage(hInpdList, bBuild ? LVM_INSERTITEM : LVM_SETITEM, 0, (LPARAM)&LvItem); + } + + j++; + } + + InpdUseUpdate(); + + return 0; +} + +static void DisablePresets() +{ + EnableWindow(hInpdPci, FALSE); + EnableWindow(hInpdAnalog, FALSE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), FALSE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), FALSE); +} + +static void InitComboboxes() +{ + TCHAR szLabel[1024]; + HANDLE search; + WIN32_FIND_DATA findData; + + for (int i = 0; i < 4; i++) { + _stprintf(szLabel, FBALoadStringEx(hAppInst, IDS_INPUT_INP_PLAYER, true), i + 1); + SendMessage(hInpdGi, CB_ADDSTRING, 0, (LPARAM)szLabel); + } + + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_INP_KEYBOARD, true)); + for (int i = 0; i < 3; i++) { + _stprintf(szLabel, FBALoadStringEx(hAppInst, IDS_INPUT_INP_JOYSTICK, true), i); + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)szLabel); + } + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_INP_XARCADEL, true)); + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_INP_XARCADER, true)); + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_INP_HOTRODL, true)); + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_INP_HOTRODR, true)); + + // Scan presets directory for .ini files and add them to the list + if ((search = FindFirstFile(_T("config\\presets\\*.ini"), &findData)) != INVALID_HANDLE_VALUE) { + do { + findData.cFileName[_tcslen(findData.cFileName) - 4] = 0; + SendMessage(hInpdPci, CB_ADDSTRING, 0, (LPARAM)findData.cFileName); + } while (FindNextFile(search, &findData) != 0); + + FindClose(search); + } +} + +static int InpdInit() +{ + int nMemLen; + + hInpdList = GetDlgItem(hInpdDlg, IDC_INPD_LIST); + + // Allocate a last val array for the last input values + nMemLen = nGameInpCount * sizeof(char); + LastVal = (unsigned char*)malloc(nMemLen); + if (LastVal == NULL) { + return 1; + } + memset(LastVal, 0, nMemLen); + + InpdListBegin(); + InpdListMake(1); + + // Init the Combo boxes + hInpdGi = GetDlgItem(hInpdDlg, IDC_INPD_GI); + hInpdPci = GetDlgItem(hInpdDlg, IDC_INPD_PCI); + hInpdAnalog = GetDlgItem(hInpdDlg, IDC_INPD_ANALOG); + InitComboboxes(); + + DisablePresets(); + + return 0; +} + +static int InpdExit() +{ + // Exit the Combo boxes + hInpdPci = NULL; + hInpdGi = NULL; + hInpdAnalog = NULL; + + if (LastVal != NULL) { + free(LastVal); + LastVal = NULL; + } + hInpdList = NULL; + hInpdDlg = NULL; + if (!bAltPause && bRunPause) { + bRunPause=0; + } + GameInpCheckMouse(); + + return 0; +} + +static void GameInpConfigOne(int nPlayer, int nPcDev, int nAnalog, struct GameInp* pgi, char* szi) +{ + switch (nPcDev) { + case 0: + GamcPlayer(pgi, szi, nPlayer, -1); // Keyboard + GamcAnalogKey(pgi, szi, nPlayer, nAnalog); + GamcMisc(pgi, szi, nPlayer); + break; + case 1: + GamcPlayer(pgi, szi, nPlayer, 0); // Joystick 1 + GamcAnalogJoy(pgi, szi, nPlayer, 0, nAnalog); + GamcMisc(pgi, szi, nPlayer); + break; + case 2: + GamcPlayer(pgi, szi, nPlayer, 1); // Joystick 2 + GamcAnalogJoy(pgi, szi, nPlayer, 1, nAnalog); + GamcMisc(pgi, szi, nPlayer); + break; + case 3: + GamcPlayer(pgi, szi, nPlayer, 2); // Joystick 3 + GamcAnalogJoy(pgi, szi, nPlayer, 2, nAnalog); + GamcMisc(pgi, szi, nPlayer); + break; + case 4: + GamcPlayerHotRod(pgi, szi, nPlayer, 0x10, nAnalog); // X-Arcade left side + GamcMisc(pgi, szi, -1); + break; + case 5: + GamcPlayerHotRod(pgi, szi, nPlayer, 0x11, nAnalog); // X-Arcade right side + GamcMisc(pgi, szi, -1); + break; + case 6: + GamcPlayerHotRod(pgi, szi, nPlayer, 0x00, nAnalog); // HotRod left side + GamcMisc(pgi, szi, -1); + break; + case 7: + GamcPlayerHotRod(pgi, szi, nPlayer, 0x01, nAnalog); // HotRod right size + GamcMisc(pgi, szi, -1); + break; + } +} + +// Configure some of the game input +static int GameInpConfig(int nPlayer, int nPcDev, int nAnalog) +{ + struct GameInp* pgi = NULL; + unsigned int i; + + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + struct BurnInputInfo bii; + + // Get the extra info about the input + bii.szInfo = NULL; + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal == NULL) { + continue; + } + if (bii.szInfo == NULL) { + bii.szInfo = ""; + } + GameInpConfigOne(nPlayer, nPcDev, nAnalog, pgi, bii.szInfo); + } + + for (i = 0; i < nMacroCount; i++, pgi++) { + GameInpConfigOne(nPlayer, nPcDev, nAnalog, pgi, pgi->Macro.szName); + } + + GameInpCheckLeftAlt(); + + return 0; +} + +// List item activated; find out which one +static int ListItemActivate() +{ + struct BurnInputInfo bii; + LVITEM LvItem; + + int nSel = SendMessage(hInpdList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED); + if (nSel < 0) { + return 1; + } + + // Get the corresponding input + LvItem.mask = LVIF_PARAM; + LvItem.iItem = nSel; + LvItem.iSubItem = 0; + SendMessage(hInpdList, LVM_GETITEM, 0, (LPARAM)&LvItem); + nSel = LvItem.lParam; + + if (nSel >= (int)(nGameInpCount + nMacroCount)) { // out of range + return 1; + } + + bii.nType = 0; + BurnDrvGetInputInfo(&bii, nSel); + if (bii.pVal == NULL) { + return 1; + } + + DestroyWindow(hInpsDlg); // Make sure any existing dialogs are gone + DestroyWindow(hInpcDlg); // + + if (bii.nType & BIT_GROUP_CONSTANT) { + // Dip switch is a constant - change it + nInpcInput = nSel; + InpcCreate(); + } else { + if (GameInp[nSel].nInput == GIT_MACRO_CUSTOM) { +#if 0 + InpMacroCreate(nSel); +#endif + } else { + // Assign to a key + nInpsInput = nSel; + InpsCreate(); + } + } + + GameInpCheckLeftAlt(); + + return 0; +} + +static int NewMacroButton() +{ +#if 0 + LVITEM LvItem; + int nSel; + + DestroyWindow(hInpsDlg); // Make sure any existing dialogs are gone + DestroyWindow(hInpcDlg); // + + nSel = SendMessage(hInpdList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED); + if (nSel < 0) { + nSel = -1; + } + + // Get the corresponding input + LvItem.mask = LVIF_PARAM; + LvItem.iItem = nSel; + LvItem.iSubItem = 0; + SendMessage(hInpdList, LVM_GETITEM, 0, (LPARAM)&LvItem); + nSel = LvItem.lParam; + + if (nSel >= (int)nGameInpCount && nSel < (int)(nGameInpCount + nMacroCount)) { + if (GameInp[nSel].nInput != GIT_MACRO_CUSTOM) { + nSel = -1; + } + } else { + nSel = -1; + } + + InpMacroCreate(nSel); +#endif + + return 0; +} + +static int DeleteInput(unsigned int i) +{ + struct BurnInputInfo bii; + + if (i >= nGameInpCount) { + + if (i < nGameInpCount + nMacroCount) { // Macro + GameInp[i].Macro.nMode = 0; + } else { // out of range + return 1; + } + } else { // "True" input + bii.nType = BIT_DIGITAL; + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal == NULL) { + return 1; + } + if (bii.nType & BIT_GROUP_CONSTANT) { // Don't delete dip switches + return 1; + } + + GameInp[i].nInput = 0; + } + + GameInpCheckLeftAlt(); + + return 0; +} + +// List item(s) deleted; find out which one(s) +static int ListItemDelete() +{ + int nStart = -1; + LVITEM LvItem; + int nRet; + + while ((nRet = SendMessage(hInpdList, LVM_GETNEXTITEM, (WPARAM)nStart, LVNI_SELECTED)) != -1) { + nStart = nRet; + + // Get the corresponding input + LvItem.mask = LVIF_PARAM; + LvItem.iItem = nRet; + LvItem.iSubItem = 0; + SendMessage(hInpdList, LVM_GETITEM, 0, (LPARAM)&LvItem); + nRet = LvItem.lParam; + + DeleteInput(nRet); + } + + InpdListMake(0); // refresh view + return 0; +} + +static int InitAnalogOptions(int nGi, int nPci) +{ + // init analog options dialog + int nAnalog = -1; + if (nPci == (nPlayerDefaultControls[nGi] & 0x0F)) { + nAnalog = nPlayerDefaultControls[nGi] >> 4; + } + + SendMessage(hInpdAnalog, CB_RESETCONTENT, 0, 0); + if (nPci >= 1 && nPci <= 3) { + // Absolute mode only for joysticks + SendMessage(hInpdAnalog, CB_ADDSTRING, 0, (LPARAM)(LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_ANALOG_ABS, true)); + } else { + if (nAnalog > 0) { + nAnalog--; + } + } + SendMessage(hInpdAnalog, CB_ADDSTRING, 0, (LPARAM)(LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_ANALOG_AUTO, true)); + SendMessage(hInpdAnalog, CB_ADDSTRING, 0, (LPARAM)(LPARAM)FBALoadStringEx(hAppInst, IDS_INPUT_ANALOG_NORMAL, true)); + + SendMessage(hInpdAnalog, CB_SETCURSEL, (WPARAM)nAnalog, 0); + + return 0; +} + +static void SaveHardwarePreset() +{ + TCHAR *szDefaultCpsFile = _T("config\\presets\\cps.ini"); + TCHAR *szDefaultNeogeoFile = _T("config\\presets\\neogeo.ini"); + TCHAR *szDefaultPgmFile = _T("config\\presets\\pgm.ini"); + TCHAR *szFileName = _T("config\\presets\\preset.ini"); + TCHAR *szHardwareString = _T("Generic hardware"); + + int nHardwareFlag = (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK); + + if (nHardwareFlag == HARDWARE_CAPCOM_CPS1 || nHardwareFlag == HARDWARE_CAPCOM_CPS1_QSOUND || nHardwareFlag == HARDWARE_CAPCOM_CPS1_GENERIC || nHardwareFlag == HARDWARE_CAPCOM_CPSCHANGER || nHardwareFlag == HARDWARE_CAPCOM_CPS2 || nHardwareFlag == HARDWARE_CAPCOM_CPS3) { + szFileName = szDefaultCpsFile; + szHardwareString = _T("CPS-1/CPS-2/CPS-3 hardware"); + } + + if (nHardwareFlag == HARDWARE_SNK_NEOGEO) { + szFileName = szDefaultNeogeoFile; + szHardwareString = _T("Neo-Geo hardware"); + } + + if (nHardwareFlag == HARDWARE_IGS_PGM) { + szFileName = szDefaultPgmFile; + szHardwareString = _T("PGM hardware"); + } + + FILE *fp = _tfopen(szFileName, _T("wt")); + if (fp) { + _ftprintf(fp, _T(APP_TITLE) _T(" - Hardware Default Preset\n\n")); + _ftprintf(fp, _T("%s\n\n"), szHardwareString); + _ftprintf(fp, _T("version 0x%06X\n\n"), nBurnVer); + GameInpWrite(fp); + fclose(fp); + } + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_PRESET_SAVED), szFileName); + FBAPopupDisplay(PUF_TYPE_INFO); +} + +int UsePreset(bool bMakeDefault) +{ + int nGi, nPci, nAnalog = 0; + TCHAR szFilename[MAX_PATH] = _T("config\\presets\\"); + + nGi = SendMessage(hInpdGi, CB_GETCURSEL, 0, 0); + if (nGi == CB_ERR) { + return 1; + } + nPci = SendMessage(hInpdPci, CB_GETCURSEL, 0, 0); + if (nPci == CB_ERR) { + return 1; + } + if (nPci <= 7) { + // Determine analog option + nAnalog = SendMessage(hInpdAnalog, CB_GETCURSEL, 0, 0); + if (nAnalog == CB_ERR) { + return 1; + } + + if (nPci == 0 || nPci > 3) { // No "Absolute" option for keyboard or X-Arcade/HotRod controls + nAnalog++; + } + + GameInpConfig(nGi, nPci, nAnalog); // Re-configure inputs + } else { + // Find out the filename of the preset ini + SendMessage(hInpdPci, CB_GETLBTEXT, nPci, (LPARAM)(szFilename + _tcslen(szFilename))); + _tcscat(szFilename, _T(".ini")); + + GameInputAutoIni(nGi, szFilename, true); // Read inputs from file + + // Make sure all inputs are defined + for (unsigned int i = 0, j = 0; i < nGameInpCount; i++) { + if (GameInp[i].Input.pVal == NULL) { + continue; + } + + if (GameInp[i].nInput == 0) { + DeleteInput(j); + } + + j++; + } + + nPci = 0x0F; + } + + SendMessage(hInpdAnalog, CB_SETCURSEL, (WPARAM)-1, 0); + SendMessage(hInpdPci, CB_SETCURSEL, (WPARAM)-1, 0); + SendMessage(hInpdGi, CB_SETCURSEL, (WPARAM)-1, 0); + + DisablePresets(); + + if (bMakeDefault) { + nPlayerDefaultControls[nGi] = nPci | (nAnalog << 4); + _tcscpy(szPlayerDefaultIni[nGi], szFilename); + } + + GameInpCheckLeftAlt(); + + return 0; +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + hInpdDlg = hDlg; + InpdInit(); + if (!kNetGame && bAutoPause) { + bRunPause = 1; + } + + return TRUE; + } + + if (Msg == WM_CLOSE) { + EnableWindow(hScrnWnd, TRUE); + DestroyWindow(hInpdDlg); + return 0; + } + + if (Msg == WM_DESTROY) { + InpdExit(); + return 0; + } + + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Id == IDOK && Notify == BN_CLICKED) { + ListItemActivate(); + return 0; + } + if (Id == IDCANCEL && Notify == BN_CLICKED) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + if (Id == IDC_INPD_NEWMACRO && Notify == BN_CLICKED) { + + NewMacroButton(); + + return 0; + } + + if (Id == IDC_INPD_SAVE_AS_PRESET && Notify == BN_CLICKED) { + SaveHardwarePreset(); + return 0; + } + + if (Id == IDC_INPD_USE && Notify == BN_CLICKED) { + + UsePreset(false); + + InpdListMake(0); // refresh view + + return 0; + } + + if (Id == IDC_INPD_DEFAULT && Notify == BN_CLICKED) { + + UsePreset(true); + + InpdListMake(0); // refresh view + + return 0; + } + + if (Id == IDC_INPD_GI && Notify == CBN_SELCHANGE) { + int nGi; + nGi = SendMessage(hInpdGi, CB_GETCURSEL, 0, 0); + if (nGi == CB_ERR) { + SendMessage(hInpdPci, CB_SETCURSEL, (WPARAM)-1, 0); + SendMessage(hInpdAnalog, CB_SETCURSEL, (WPARAM)-1, 0); + + DisablePresets(); + + return 0; + } + int nPci = nPlayerDefaultControls[nGi] & 0x0F; + SendMessage(hInpdPci, CB_SETCURSEL, nPci, 0); + EnableWindow(hInpdPci, TRUE); + + if (nPci > 5) { + SendMessage(hInpdAnalog, CB_SETCURSEL, (WPARAM)-1, 0); + EnableWindow(hInpdAnalog, FALSE); + } else { + InitAnalogOptions(nGi, nPci); + EnableWindow(hInpdAnalog, TRUE); + } + + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), TRUE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), TRUE); + + return 0; + } + + if (Id == IDC_INPD_PCI && Notify == CBN_SELCHANGE) { + int nGi, nPci; + nGi = SendMessage(hInpdGi, CB_GETCURSEL, 0, 0); + if (nGi == CB_ERR) { + return 0; + } + nPci = SendMessage(hInpdPci, CB_GETCURSEL, 0, 0); + if (nPci == CB_ERR) { + return 0; + } + + if (nPci > 7) { + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), TRUE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), TRUE); + + SendMessage(hInpdAnalog, CB_SETCURSEL, (WPARAM)-1, 0); + EnableWindow(hInpdAnalog, FALSE); + } else { + EnableWindow(hInpdAnalog, TRUE); + InitAnalogOptions(nGi, nPci); + + if (SendMessage(hInpdAnalog, CB_GETCURSEL, 0, 0) != CB_ERR) { + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), TRUE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), TRUE); + } else { + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), FALSE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), FALSE); + } + } + + return 0; + } + + if (Id == IDC_INPD_ANALOG && Notify == CBN_SELCHANGE) { + if (SendMessage(hInpdAnalog, CB_GETCURSEL, 0, 0) != CB_ERR) { + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_DEFAULT), TRUE); + EnableWindow(GetDlgItem(hInpdDlg, IDC_INPD_USE), TRUE); + } + + return 0; + } + + } + + if (Msg == WM_NOTIFY && lParam != 0) { + int Id = LOWORD(wParam); + NMHDR* pnm = (NMHDR*)lParam; + + if (Id == IDC_INPD_LIST && pnm->code == LVN_ITEMACTIVATE) { + ListItemActivate(); + } + if (Id == IDC_INPD_LIST && pnm->code == LVN_KEYDOWN) { + NMLVKEYDOWN *pnmkd = (NMLVKEYDOWN*)lParam; + if (pnmkd->wVKey == VK_DELETE) { + ListItemDelete(); + } + } + + if (Id == IDC_INPD_LIST && pnm->code == NM_CUSTOMDRAW) { + NMLVCUSTOMDRAW* plvcd = (NMLVCUSTOMDRAW*)lParam; + + switch (plvcd->nmcd.dwDrawStage) { + case CDDS_PREPAINT: + SetWindowLongPtr(hInpdDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW); + return 1; + case CDDS_ITEMPREPAINT: + if (plvcd->nmcd.dwItemSpec < nGameInpCount) { + if (GameInp[plvcd->nmcd.dwItemSpec].nType & BIT_GROUP_CONSTANT) { + + if (GameInp[plvcd->nmcd.dwItemSpec].nInput == 0) { + plvcd->clrTextBk = RGB(0xDF, 0xDF, 0xDF); + + SetWindowLongPtr(hInpdDlg, DWLP_MSGRESULT, CDRF_NEWFONT); + return 1; + } + + if (GameInp[plvcd->nmcd.dwItemSpec].nType == BIT_DIPSWITCH) { + plvcd->clrTextBk = RGB(0xFF, 0xEF, 0xD7); + + SetWindowLongPtr(hInpdDlg, DWLP_MSGRESULT, CDRF_NEWFONT); + return 1; + } + } + } + + if (plvcd->nmcd.dwItemSpec >= nGameInpCount) { + if (GameInp[plvcd->nmcd.dwItemSpec].Macro.nMode) { + plvcd->clrTextBk = RGB(0xFF, 0xCF, 0xCF); + } else { + plvcd->clrTextBk = RGB(0xFF, 0xEF, 0xEF); + } + + SetWindowLongPtr(hInpdDlg, DWLP_MSGRESULT, CDRF_NEWFONT); + return 1; + } + return 1; + } + } + return 0; + } + + return 0; +} + +int InpdCreate() +{ + if (bDrvOkay == 0) { + return 1; + } + + DestroyWindow(hInpdDlg); // Make sure exitted + + hInpdDlg = FBACreateDialog(hAppInst, MAKEINTRESOURCE(IDD_INPD), hScrnWnd, (DLGPROC)DialogProc); + if (hInpdDlg == NULL) { + return 1; + } + + WndInMid(hInpdDlg, hScrnWnd); + ShowWindow(hInpdDlg, SW_NORMAL); + + return 0; +} + + diff --git a/src/burner/win32/inpdipsw.cpp b/src/burner/win32/inpdipsw.cpp new file mode 100644 index 00000000..319c9ee4 --- /dev/null +++ b/src/burner/win32/inpdipsw.cpp @@ -0,0 +1,360 @@ +// Burner DipSwitches Dialog module +#include "burner.h" + +HWND hInpDIPSWDlg = NULL; // Handle to the DIPSW Dialog +static HWND hInpDIPSWList = NULL; + +static unsigned char nPrevDIPSettings[4]; + +static unsigned int nDIPGroup; +static int nDIPOffset; + +static bool bOK; + +static void InpDIPSWGetOffset() +{ + BurnDIPInfo bdi; + + nDIPOffset = 0; + for (int i = 0; BurnDrvGetDIPInfo(&bdi, i) == 0; i++) { + if (bdi.nFlags == 0xF0) { + nDIPOffset = bdi.nInput; + break; + } + } +} + +void InpDIPSWResetDIPs() +{ + int i = 0; + BurnDIPInfo bdi; + struct GameInp* pgi; + + InpDIPSWGetOffset(); + + while (BurnDrvGetDIPInfo(&bdi, i) == 0) { + if (bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~bdi.nMask) | (bdi.nSetting & bdi.nMask); + } + i++; + } +} + +static int InpDIPSWListBegin() +{ + LVCOLUMN LvCol; + if (hInpDIPSWList == NULL) { + return 1; + } + + // Full row select style: + SendMessage(hInpDIPSWList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + // Make column headers + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + LvCol.cx = 158; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_DIP_GROUP, true); + SendMessage(hInpDIPSWList, LVM_INSERTCOLUMN, 0, (LPARAM)&LvCol); + LvCol.cx = 215; + LvCol.pszText = FBALoadStringEx(hAppInst, IDS_DIP_SETTING, true); + SendMessage(hInpDIPSWList, LVM_INSERTCOLUMN, 1, (LPARAM)&LvCol); + + return 0; +} + +static bool CheckSetting(int i) +{ + BurnDIPInfo bdi; + BurnDrvGetDIPInfo(&bdi, i); + struct GameInp* pgi = GameInp + bdi.nInput + nDIPOffset; + + if ((pgi->Input.Constant.nConst & bdi.nMask) == bdi.nSetting) { + unsigned char nFlags = bdi.nFlags; + if ((nFlags & 0x0F) <= 1) { + return true; + } else { + for (int j = 1; j < (nFlags & 0x0F); j++) { + BurnDrvGetDIPInfo(&bdi, i + j); + pgi = GameInp + bdi.nInput + nDIPOffset; + if (nFlags & 0x80) { + if ((pgi->Input.Constant.nConst & bdi.nMask) == bdi.nSetting) { + return false; + } + } else { + if ((pgi->Input.Constant.nConst & bdi.nMask) != bdi.nSetting) { + return false; + } + } + } + return true; + } + } + return false; +} + +// Make a list view of the DIPswitches +static int InpDIPSWListMake() +{ + if (hInpDIPSWList == NULL) { + return 1; + } + SendMessage(hInpDIPSWList, LVM_DELETEALLITEMS, 0, 0); + + BurnDIPInfo bdi; + unsigned int i = 0, j = 0, k = 0; + char* pDIPGroup = NULL; + while (BurnDrvGetDIPInfo(&bdi, i) == 0) { + if ((bdi.nFlags & 0xF0) == 0xF0) { + if (bdi.nFlags == 0xFE || bdi.nFlags == 0xFD) { + pDIPGroup = bdi.szText; + k = i; + } + i++; + } else { + if (CheckSetting(i)) { + LVITEM LvItem; + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_TEXT | LVIF_PARAM; + LvItem.iItem = j; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(pDIPGroup, NULL, 0); + LvItem.lParam = (LPARAM)k; + SendMessage(hInpDIPSWList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + LvItem.mask = LVIF_TEXT; + LvItem.iSubItem = 1; + LvItem.pszText = ANSIToTCHAR(bdi.szText, NULL, 0); + SendMessage(hInpDIPSWList, LVM_SETITEM, 0, (LPARAM)&LvItem); + j++; + } + i += (bdi.nFlags & 0x0F); + } + } + + return 0; +} + +static int InpDIPSWInit() +{ + BurnDIPInfo bdi; + struct GameInp *pgi; + + InpDIPSWGetOffset(); + + hInpDIPSWList = GetDlgItem(hInpDIPSWDlg, IDC_INPCHEAT_LIST); + InpDIPSWListBegin(); + InpDIPSWListMake(); + + for (int i = 0, j = 0; BurnDrvGetDIPInfo(&bdi, i) == 0; i++) { + if (bdi.nInput >= 0 && bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + nPrevDIPSettings[j] = pgi->Input.Constant.nConst; + j++; + } + } + + return 0; +} + +static int InpDIPSWExit() +{ + hInpDIPSWList = NULL; + hInpDIPSWDlg = NULL; + if(!bAltPause && bRunPause) { + bRunPause = 0; + } + GameInpCheckMouse(); + return 0; +} + +static void InpDIPSWCancel() +{ + if (!bOK) { + int i = 0, j = 0; + BurnDIPInfo bdi; + struct GameInp *pgi; + while (BurnDrvGetDIPInfo(&bdi, i) == 0) { + if (bdi.nInput >= 0 && bdi.nFlags == 0xFF) { + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = nPrevDIPSettings[j]; + j++; + } + i++; + } + } +} + +// Create the list of possible values for a DIPswitch +static void InpDIPSWSelect() +{ + SendMessage(GetDlgItem(hInpDIPSWDlg, IDC_INPCX1_VALUE), CB_RESETCONTENT, 0, 0); + + int nSel = SendMessage(hInpDIPSWList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED); + if (nSel >= 0) { + LVITEM LvItem; + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask = LVIF_PARAM; + LvItem.iItem = nSel; + SendMessage(hInpDIPSWList, LVM_GETITEM, 0, (LPARAM)&LvItem); + + nDIPGroup = LvItem.lParam; + + BurnDIPInfo bdiGroup; + BurnDrvGetDIPInfo(&bdiGroup, nDIPGroup); + + int nCurrentSetting = 0; + for (int i = 0, j = 0; i < bdiGroup.nSetting; i++) { + TCHAR szText[256]; + BurnDIPInfo bdi; + + do { + BurnDrvGetDIPInfo(&bdi, nDIPGroup + 1 + j++); + } while (bdi.nFlags == 0); + + if (bdiGroup.szText) { + _stprintf(szText, _T("%hs: %hs"), bdiGroup.szText, bdi.szText); + } else { + _stprintf(szText, _T("%hs"), bdi.szText); + } + SendMessage(GetDlgItem(hInpDIPSWDlg, IDC_INPCX1_VALUE), CB_ADDSTRING, 0, (LPARAM)szText); + + if (CheckSetting(nDIPGroup + j)) { + nCurrentSetting = i; + } + } + SendMessage(GetDlgItem(hInpDIPSWDlg, IDC_INPCX1_VALUE), CB_SETCURSEL, (WPARAM)nCurrentSetting, 0); + } +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + +// EnableWindow(hScrnWnd, FALSE); + + hInpDIPSWDlg = hDlg; + InpDIPSWInit(); + if (!kNetGame && bAutoPause) { + bRunPause = 1; + } + + WndInMid(hDlg, hScrnWnd); + SetFocus(hDlg); // Enable Esc=close + + return TRUE; + } + + if (Msg == WM_CLOSE) { + EnableWindow(hScrnWnd, TRUE); + DestroyWindow(hInpDIPSWDlg); + return 0; + } + + if (Msg == WM_DESTROY) { + InpDIPSWCancel(); + InpDIPSWExit(); + return 0; + } + + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Id == IDOK && Notify == BN_CLICKED) { // OK button + bOK = true; + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + if (Id == IDCANCEL && Notify == BN_CLICKED) { // cancel = close + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + // New DIPswitch value selected + if (Id == IDC_INPCX1_VALUE && Notify == CBN_SELCHANGE) { + BurnDIPInfo bdi = {0, 0, 0, 0, NULL}; + struct GameInp *pgi; + int nSel = SendMessage(GetDlgItem(hInpDIPSWDlg, IDC_INPCX1_VALUE), CB_GETCURSEL, 0, 0); + int j = 0; + for (int i = 0; i <= nSel; i++) { + do { + BurnDrvGetDIPInfo(&bdi, nDIPGroup + 1 + j++); + } while (bdi.nFlags == 0); + } + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~bdi.nMask) | (bdi.nSetting & bdi.nMask); + if (bdi.nFlags & 0x40) { + while (BurnDrvGetDIPInfo(&bdi, nDIPGroup + 1 + j++) == 0) { + if (bdi.nFlags == 0) { + pgi = GameInp + bdi.nInput + nDIPOffset; + pgi->Input.Constant.nConst = (pgi->Input.Constant.nConst & ~bdi.nMask) | (bdi.nSetting & bdi.nMask); + } else { + break; + } + } + } + + InpDIPSWListMake(); + return 0; + } + + // New DIPswitch selected + if (Id == IDC_INPC_RESET && Notify == BN_CLICKED) { + + InpDIPSWResetDIPs(); + + InpDIPSWListMake(); // refresh view + SendMessage(GetDlgItem(hInpDIPSWDlg, IDC_INPCX1_VALUE), CB_RESETCONTENT, 0, 0); + return 0; + } + + } + + if (Msg == WM_NOTIFY && lParam) { + int Id = LOWORD(wParam); + NMHDR* pnm = (NMHDR*)lParam; + + if (Id == IDC_INPCHEAT_LIST && pnm->code == LVN_ITEMCHANGED) { + if (((NM_LISTVIEW*)lParam)->uNewState & LVIS_SELECTED) { + InpDIPSWSelect(); + } + return 0; + } + + if (Id == IDC_INPCHEAT_LIST && pnm->code == NM_CUSTOMDRAW) { + NMLVCUSTOMDRAW* plvcd = (NMLVCUSTOMDRAW*)lParam; + + switch (plvcd->nmcd.dwDrawStage) { + case CDDS_PREPAINT: { + SetWindowLongPtr(hInpDIPSWDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW); + return 1; + } + case CDDS_ITEMPREPAINT: { + BurnDIPInfo bdi; + BurnDrvGetDIPInfo(&bdi, plvcd->nmcd.lItemlParam); + if (bdi.nFlags == 0xFD) { + plvcd->clrTextBk = RGB(0xFF, 0xDF, 0xBB); + SetWindowLongPtr(hInpDIPSWDlg, DWLP_MSGRESULT, CDRF_NEWFONT); + } + + return 1; + } + } + } + } + + return 0; +} + +int InpDIPSWCreate() +{ + if (bDrvOkay == 0) { // No game is loaded + return 1; + } + + bOK = false; + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_INPDIP), hScrnWnd, (DLGPROC)DialogProc); + + return 0; +} diff --git a/src/burner/win32/inps.cpp b/src/burner/win32/inps.cpp new file mode 100644 index 00000000..08ad99f9 --- /dev/null +++ b/src/burner/win32/inps.cpp @@ -0,0 +1,336 @@ +// Burner Input Set dialog module +#include "burner.h" + +HWND hInpsDlg = NULL; // Handle to the Input Set Dialog +static HBRUSH hWhiteBGBrush; + +unsigned int nInpsInput = 0; // The input number we are redefining +static struct BurnInputInfo bii; // Info about the input +static int nDlgState = 0; +static int nInputCode = -1; // If in state 3, code N was nInputCode +static int nCounter = 0; // Counter of frames since the dialog was made +static struct GameInp* pgi = NULL; // Current GameInp +static struct GameInp OldInp; // Old GameInp +static int bOldPush = 0; // 1 if the push button was pressed last time + +static bool bGrabMouse = false; + +static bool bOldLeftAltkeyMapped; + +static int InpsInit() +{ + TCHAR szTitle[128]; + memset(&OldInp, 0, sizeof(OldInp)); + + pgi = NULL; + if (nInpsInput >= nGameInpCount + nMacroCount) { // input out of range + return 1; + } + pgi = GameInp + nInpsInput; + + memset(&bii,0,sizeof(bii)); + BurnDrvGetInputInfo(&bii, nInpsInput); + + if (bii.nType & BIT_GROUP_CONSTANT) { // This dialog doesn't handle constants + return 1; + } + + OldInp = *pgi; + bOldPush = 0; + + bGrabMouse = false; + + bOldLeftAltkeyMapped = bLeftAltkeyMapped; + bLeftAltkeyMapped = true; + + // Set the dialog title + if (nInpsInput >= nGameInpCount) { + // Macro + _stprintf(szTitle, FBALoadStringEx(hAppInst, IDS_INPSET_MOVENAME, true), pgi->Macro.szName); + } else { + // Normal input + if (bii.szName == NULL || bii.szName[0] == _T('\0')) { + _stprintf(szTitle, FBALoadStringEx(hAppInst, IDS_INPSET_MOVE, true)); + } else { + _stprintf(szTitle, FBALoadStringEx(hAppInst, IDS_INPSET_MOVENAME, true), bii.szName); + } + } + SetWindowText(hInpsDlg, szTitle); + + InputFind(2); + + nDlgState = 4; + nInputCode = -1; + nCounter = 0; + + return 0; +} + +static int InpsExit() +{ + bOldPush = 0; + if (pgi != NULL) { + *pgi=OldInp; + } + memset(&OldInp, 0, sizeof(OldInp)); + + bLeftAltkeyMapped = bOldLeftAltkeyMapped; + + nDlgState = 0; + + return 0; +} + +static int SetInput(int nCode) +{ + if ((pgi->nInput & GIT_GROUP_MACRO) == 0) { + + if (bii.nType & BIT_GROUP_CONSTANT) { // Don't change dip switches! + DestroyWindow(hInpsDlg); + return 0; + } + + if ((bii.nType & BIT_GROUP_ANALOG) && (nCode & 0xFF) < 0x10) { // Analog controls + if (strcmp(bii.szInfo + 4, "-axis-neg") == 0 || strcmp(bii.szInfo + 4, "-axis-pos") == 0) { + if ((nCode & 0xF000) == 0x4000) { + if (nCode & 1) { + pgi->nInput = GIT_JOYAXIS_POS; + } else { + pgi->nInput = GIT_JOYAXIS_NEG; + } + pgi->Input.JoyAxis.nJoy = (nCode & 0x0F00) >> 8; + pgi->Input.JoyAxis.nAxis = (nCode & 0x0F) >> 1; + } + } else { // Map entire axis + if ((nCode & 0xF000) == 0x4000) { + pgi->nInput = GIT_JOYAXIS_FULL; + pgi->Input.JoyAxis.nJoy = (nCode & 0x0F00) >> 8; + pgi->Input.JoyAxis.nAxis = (nCode & 0x0F) >> 1; + } else { + pgi->nInput = GIT_MOUSEAXIS; + pgi->Input.MouseAxis.nMouse = (nCode & 0x0F00) >> 8; + pgi->Input.MouseAxis.nAxis = (nCode & 0x0F) >> 1; + } + } + } else { + pgi->nInput = GIT_SWITCH; + pgi->Input.Switch.nCode = (unsigned short)nCode; + } + } else { + pgi->Macro.nMode = 0x01; // Mark macro as in use + pgi->Macro.Switch.nCode = (unsigned short)nCode; // Assign switch + } + + OldInp = *pgi; + + InpdListMake(0); // Update list with new input type + + return 0; +} + +static int InpsPushUpdate() +{ + int nPushState = 0; + + if (pgi == NULL || nInpsInput >= nGameInpCount) { + return 0; + } + + // See if the push button is pressed + nPushState = SendDlgItemMessage(hInpsDlg, IDC_INPS_PUSH, BM_GETSTATE, 0, 0); + if (nPushState & BST_PUSHED) { + nPushState = 1; + } else { + nPushState = 0; + } + + if (nPushState) { + switch (OldInp.nType) { + case BIT_DIGITAL: // Set digital inputs to 1 + pgi->nInput = GIT_CONSTANT; + pgi->Input.Constant.nConst = 1; + break; + case BIT_DIPSWITCH: // Set dipswitch block to 0xFF + pgi->nInput = GIT_CONSTANT; + pgi->Input.Constant.nConst = 0xFF; + break; + } + } else { + // Change back + *pgi = OldInp; + } + if (nPushState != bOldPush) { // refresh view + InpdListMake(0); + } + + bOldPush = nPushState; + + return nPushState; +} + +static void InpsUpdateControl(int nCode) +{ + TCHAR szString[MAX_PATH] = _T(""); + TCHAR szDevice[MAX_PATH] = _T(""); + TCHAR szControl[MAX_PATH] = _T(""); + + _stprintf(szString, _T("%s"), InputCodeDesc(nCode)); + SetWindowText(GetDlgItem(hInpsDlg, IDC_INPS_CONTROL), szString); + + InputGetControlName(nCode, szDevice, szControl); + _sntprintf(szString, MAX_PATH, _T("%s %s"), szDevice, szControl); + SetWindowText(GetDlgItem(hInpsDlg, IDC_INPS_CONTROL_NAME), szString); +} + +int InpsUpdate() +{ + TCHAR szTemp[MAX_PATH] = _T(""); + int nButtonState; + int nFind = -1; + + if (hInpsDlg == NULL) { // Don't do anything if the dialog isn't created + return 1; + } + if (nCounter < 0x100000) { // advance frames since dialog was created + nCounter++; + } + + if (InpsPushUpdate()) { + return 0; + } + + nButtonState = SendDlgItemMessage(hInpsDlg, IDC_INPS_GRABMOUSE, BM_GETSTATE, 0, 0); + if (bGrabMouse) { + if ((nButtonState & BST_CHECKED) == 0) { + bGrabMouse = false; + nDlgState = 2; + return 0; + } + } else { + if (nButtonState & BST_CHECKED) { + bGrabMouse = true; + nDlgState = 4; + return 0; + } + } + // This doesn't work properly + if (nButtonState & BST_PUSHED) { + return 0; + } + + nButtonState = SendDlgItemMessage(hInpsDlg, IDCANCEL, BM_GETSTATE, 0, 0); + if (nButtonState & BST_PUSHED) { + return 0; + } + + nFind = InputFind(nDlgState); + + if (nDlgState & 4) { // 4 = Waiting for all controls to be released + + if (bGrabMouse ? nFind >= 0 : (nFind >= 0 && nFind < 0x8000)) { + + if (nCounter >= 60) { + + // Alert the user that a control is stuck + + _stprintf(szTemp, FBALoadStringEx(hAppInst, IDS_INPSET_WAITING, true), InputCodeDesc(nFind)); + SetWindowText(GetDlgItem(hInpsDlg, IDC_INPS_CONTROL), szTemp); + + nCounter = 0; + } + return 0; + } + + // All keys released + SetWindowText(GetDlgItem(hInpsDlg, IDC_INPS_CONTROL), _T("")); + SetWindowText(GetDlgItem(hInpsDlg, IDC_INPS_CONTROL_NAME), _T("")); + nDlgState = 8; + } + + if (nDlgState & 8) { // 8 = Waiting for a control to be activated + + if (bGrabMouse ? nFind < 0 : (nFind < 0 || nFind >= 0x8000)) { + return 0; + } + + // Key pressed + + nInputCode = nFind; + InpsUpdateControl(nInputCode); + + nDlgState = 16; + } + + if (nDlgState & 16) { // 16 = waiting for control to be released + + if (bGrabMouse ? nFind >= 0 : (nFind >= 0 && nFind < 0x8000)) { + if (nInputCode != nFind) { + nInputCode = nFind; + InpsUpdateControl(nInputCode); + } + return 0; + } + + // Key released + SetInput(nInputCode); + + nDlgState = 0; + DestroyWindow(hInpsDlg); // Quit dialog + } + + return 0; +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + hInpsDlg = hDlg; + hWhiteBGBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + if (InpsInit()) { + DestroyWindow(hInpsDlg); + return FALSE; + } + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_INPS_CONTROL), TRUE); + return FALSE; + } + if (Msg == WM_CLOSE) { + DestroyWindow(hInpsDlg); + return 0; + } + if (Msg == WM_DESTROY) { + DeleteObject(hWhiteBGBrush); + InpsExit(); + hInpsDlg = NULL; + return 0; + } + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + if (Id == IDCANCEL && Notify == BN_CLICKED) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + } + if (Msg == WM_CTLCOLORSTATIC) { + if ((HWND)lParam == GetDlgItem(hDlg, IDC_INPS_CONTROL)) { + return (INT_PTR)hWhiteBGBrush; + } + } + return 0; +} + +int InpsCreate() +{ + DestroyWindow(hInpsDlg); // Make sure exitted + hInpsDlg = NULL; + + hInpsDlg = FBACreateDialog(hAppInst, MAKEINTRESOURCE(IDD_INPS), hInpdDlg, (DLGPROC)DialogProc); + if (hInpsDlg == NULL) { + return 1; + } + + WndInMid(hInpsDlg, hInpdDlg); + ShowWindow(hInpsDlg, SW_NORMAL); + + return 0; +} diff --git a/src/burner/win32/ips_manager.cpp b/src/burner/win32/ips_manager.cpp new file mode 100644 index 00000000..20f31931 --- /dev/null +++ b/src/burner/win32/ips_manager.cpp @@ -0,0 +1,817 @@ +#include "burner.h" + +#define NUM_LANGUAGES 12 +#define MAX_NODES 1024 +#define MAX_ACTIVE_PATCHES 1024 + +static HWND hIpsDlg = NULL; +static HWND hParent = NULL; +static HWND hIpsList = NULL; + +int nIpsSelectedLanguage = 0; +static TCHAR szFullName[1024]; +static TCHAR szLanguages[NUM_LANGUAGES][32]; +static TCHAR szLanguageCodes[NUM_LANGUAGES][6]; + +static HTREEITEM hItemHandles[MAX_NODES]; + +static int nPatchIndex = 0; +static int nNumPatches = 0; +static HTREEITEM hPatchHandlesIndex[MAX_NODES]; +static TCHAR szPatchFileNames[MAX_NODES][MAX_PATH]; + +static HBRUSH hWhiteBGBrush; +static HBITMAP hBmp = NULL; +static HBITMAP hPreview = NULL; + +TCHAR szIpsActivePatches[MAX_ACTIVE_PATCHES][MAX_PATH]; + +// GCC doesn't seem to define these correctly..... +#define _TreeView_SetItemState(hwndTV, hti, data, _mask) \ +{ TVITEM _ms_TVi;\ + _ms_TVi.mask = TVIF_STATE; \ + _ms_TVi.hItem = hti; \ + _ms_TVi.stateMask = _mask;\ + _ms_TVi.state = data;\ + SNDMSG((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_ms_TVi);\ +} + +#define _TreeView_SetCheckState(hwndTV, hti, fCheck) \ + _TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK) + +#define _TreeView_GetCheckState(hwndTV, hti) \ + ((((UINT)(SNDMSG((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti), TVIS_STATEIMAGEMASK))) >> 12) -1) + +static TCHAR* GameIpsConfigName() +{ + // Return the path of the config file for this game + static TCHAR szName[32]; + _stprintf(szName, _T("config\\ips\\%s.ini"), BurnDrvGetText(DRV_NAME)); + return szName; +} + +int GetIpsNumPatches() +{ + WIN32_FIND_DATA wfd; + HANDLE hSearch; + TCHAR szFilePath[MAX_PATH]; + int Count = 0; + + _stprintf(szFilePath, _T("%s%s\\"), szAppIpsPath, BurnDrvGetText(DRV_NAME)); + _tcscat(szFilePath, _T("*.dat")); + + hSearch = FindFirstFile(szFilePath, &wfd); + + if (hSearch != INVALID_HANDLE_VALUE) { + int Done = 0; + + while (!Done ) { + Count++; + Done = !FindNextFile(hSearch, &wfd); + } + + FindClose(hSearch); + } + + return Count; +} + +static TCHAR* GetPatchDescByLangcode(FILE* fp, int nLang) +{ + TCHAR* result = NULL; + char* desc = NULL; + char langtag[8]; + + sprintf(langtag, "[%s]", TCHARToANSI(szLanguageCodes[nLang], NULL, 0)); + + fseek(fp, 0, SEEK_SET); + + while (!feof(fp)) + { + char s[4096]; + + if (fgets(s, sizeof s, fp) != NULL) + { + if (strncmp(langtag, s, strlen(langtag)) != 0) + continue; + + while (fgets(s, sizeof s, fp) != NULL) + { + char* p; + + if (*s == '[') + { + if (desc) + { + result = tstring_from_utf8(desc); + if (desc) { + free(desc); + desc = NULL; + } + return result; + } + else + return NULL; + } + + for (p = s; *p; p++) + { + if (*p == '\r' || *p == '\n') + { + *p = '\0'; + break; + } + } + + if (desc) + { + char* p1; + int len = strlen(desc); + + len += strlen(s) + 2; + p1 = (char*)malloc(len + 1); + sprintf(p1, "%s\r\n%s", desc, s); + if (desc) { + free(desc); + } + desc = p1; + } + else + { + desc = (char*)malloc(strlen(s) + 1); + if (desc != NULL) + strcpy(desc, s); + } + } + } + } + + if (desc) + { + result = tstring_from_utf8(desc); + if (desc) { + free(desc); + desc = NULL; + } + return result; + } + else + return NULL; +} + +static void FillListBox() +{ + WIN32_FIND_DATA wfd; + HANDLE hSearch; + TCHAR szFilePath[MAX_PATH]; + TCHAR szFilePathSearch[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + TCHAR *PatchDesc = NULL; + TCHAR PatchName[256]; + int nHandlePos = 0; + + TV_INSERTSTRUCT TvItem; + + memset(&TvItem, 0, sizeof(TvItem)); + TvItem.item.mask = TVIF_TEXT | TVIF_PARAM; + TvItem.hInsertAfter = TVI_LAST; + + _stprintf(szFilePath, _T("%s%s\\"), szAppIpsPath, BurnDrvGetText(DRV_NAME)); + _stprintf(szFilePathSearch, _T("%s*.dat"), szFilePath); + + hSearch = FindFirstFile(szFilePathSearch, &wfd); + + if (hSearch != INVALID_HANDLE_VALUE) { + int Done = 0; + + while (!Done ) { + memset(szFileName, '\0', MAX_PATH); + _stprintf(szFileName, _T("%s%s"), szFilePath, wfd.cFileName); + + FILE *fp = _tfopen(szFileName, _T("r")); + if (fp) { + PatchDesc = NULL; + memset(PatchName, '\0', 256); + + PatchDesc = GetPatchDescByLangcode(fp, nIpsSelectedLanguage); + // If not available - try English first + if (PatchDesc == NULL) PatchDesc = GetPatchDescByLangcode(fp, 0); + // Simplified Chinese is the reference language (should always be available!!) + if (PatchDesc == NULL) PatchDesc = GetPatchDescByLangcode(fp, 1); + + for (unsigned int i = 0; i < _tcslen(PatchDesc); i++) { + if (PatchDesc[i] == '\r' || PatchDesc[i] == '\n') break; + PatchName[i] = PatchDesc[i]; + } + + // Check for categories + TCHAR *Tokens; + int nNumTokens = 0; + int nNumNodes = 0; + TCHAR szCategory[256]; + unsigned int nPatchNameLength = _tcslen(PatchName); + + Tokens = _tcstok(PatchName, _T("/")); + while (Tokens != NULL) { + if (nNumTokens == 0) { + int bAddItem = 1; + // Check if item already exists + nNumNodes = SendMessage(hIpsList, TVM_GETCOUNT, (WPARAM)0, (LPARAM)0); + for (int i = 0; i < nNumNodes; i++) { + TCHAR Temp[256]; + TVITEM Tvi; + memset(&Tvi, 0, sizeof(Tvi)); + Tvi.hItem = hItemHandles[i]; + Tvi.mask = TVIF_TEXT | TVIF_HANDLE; + Tvi.pszText = Temp; + Tvi.cchTextMax = 256; + SendMessage(hIpsList, TVM_GETITEM, (WPARAM)0, (LPARAM)&Tvi); + + if (!_tcsicmp(Tvi.pszText, Tokens)) bAddItem = 0; + } + + if (bAddItem) { + TvItem.hParent = TVI_ROOT; + TvItem.item.pszText = Tokens; + hItemHandles[nHandlePos] = (HTREEITEM)SendMessage(hIpsList, TVM_INSERTITEM, 0, (LPARAM)&TvItem); + nHandlePos++; + } + + if (_tcslen(Tokens) == nPatchNameLength) { + hPatchHandlesIndex[nPatchIndex] = hItemHandles[nHandlePos - 1]; + _tcscpy(szPatchFileNames[nPatchIndex], szFileName); + + nPatchIndex++; + } + + _tcscpy(szCategory, Tokens); + } else { + HTREEITEM hNode = TVI_ROOT; + // See which category we should be in + nNumNodes = SendMessage(hIpsList, TVM_GETCOUNT, (WPARAM)0, (LPARAM)0); + for (int i = 0; i < nNumNodes; i++) { + TCHAR Temp[256]; + TVITEM Tvi; + memset(&Tvi, 0, sizeof(Tvi)); + Tvi.hItem = hItemHandles[i]; + Tvi.mask = TVIF_TEXT | TVIF_HANDLE; + Tvi.pszText = Temp; + Tvi.cchTextMax = 256; + SendMessage(hIpsList, TVM_GETITEM, (WPARAM)0, (LPARAM)&Tvi); + + if (!_tcsicmp(Tvi.pszText, szCategory)) hNode = Tvi.hItem; + } + + TvItem.hParent = hNode; + TvItem.item.pszText = Tokens; + hItemHandles[nHandlePos] = (HTREEITEM)SendMessage(hIpsList, TVM_INSERTITEM, 0, (LPARAM)&TvItem); + + hPatchHandlesIndex[nPatchIndex] = hItemHandles[nHandlePos]; + _tcscpy(szPatchFileNames[nPatchIndex], szFileName); + + nHandlePos++; + nPatchIndex++; + } + + Tokens = _tcstok(NULL, _T("/")); + nNumTokens++; + } + + fclose(fp); + } + + Done = !FindNextFile(hSearch, &wfd); + } + + FindClose(hSearch); + } + + nNumPatches = nPatchIndex; + + // Expand all branches + int nNumNodes = SendMessage(hIpsList, TVM_GETCOUNT, (WPARAM)0, (LPARAM)0);; + for (int i = 0; i < nNumNodes; i++) { + SendMessage(hIpsList, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItemHandles[i]); + } +} + +int GetIpsNumActivePatches() +{ + int nActivePatches = 0; + + for (int i = 0; i < MAX_ACTIVE_PATCHES; i++) { + if (_tcsicmp(szIpsActivePatches[i], _T(""))) nActivePatches++; + } + + return nActivePatches; +} + +void LoadIpsActivePatches() +{ + for (int i = 0; i < MAX_ACTIVE_PATCHES; i++) { + _stprintf(szIpsActivePatches[i], _T("")); + } + + FILE* fp = _tfopen(GameIpsConfigName(), _T("rt")); + TCHAR szLine[MAX_PATH]; + int nActivePatches = 0; + + if (fp) { + while (_fgetts(szLine, sizeof(szLine), fp)) { + int nLen = _tcslen(szLine); + + // Get rid of the linefeed at the end + if (szLine[nLen - 1] == 10) { + szLine[nLen - 1] = 0; + nLen--; + } + + if (!_tcsnicmp(szLine, _T("//"), 2)) continue; + if (!_tcsicmp(szLine, _T(""))) continue; + + _stprintf(szIpsActivePatches[nActivePatches], _T("%s%s\\%s"), szAppIpsPath, BurnDrvGetText(DRV_NAME), szLine); + nActivePatches++; + } + + fclose(fp); + } +} + +static void CheckActivePatches() +{ + LoadIpsActivePatches(); + + int nActivePatches = GetIpsNumActivePatches(); + + for (int i = 0; i < nActivePatches; i++) { + for (int j = 0; j < nNumPatches; j++) { + if (!_tcsicmp(szIpsActivePatches[i], szPatchFileNames[j])) { + _TreeView_SetCheckState(hIpsList, hPatchHandlesIndex[j], TRUE); + } + } + } +} + +static int IpsManagerInit() +{ + // Get the games full name + TCHAR szText[1024] = _T(""); + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(DRV_FULLNAME); + + pszPosition += _sntprintf(szText, 1024, pszName); + + pszName = BurnDrvGetText(DRV_FULLNAME); + while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + + _tcscpy(szFullName, szText); + + _stprintf(szText, _T("%s") _T(SEPERATOR_1) _T("%s"), FBALoadStringEx(hAppInst, IDS_IPSMANAGER_TITLE, true), szFullName); + + // Set the window caption + SetWindowText(hIpsDlg, szText); + + // Fill the combo box + _stprintf(szLanguages[0], _T("English (US)")); + _stprintf(szLanguages[1], _T("Simplified Chinese")); + _stprintf(szLanguages[2], _T("Traditional Chinese")); + _stprintf(szLanguages[3], _T("Japanese")); + _stprintf(szLanguages[4], _T("Korean")); + _stprintf(szLanguages[5], _T("French")); + _stprintf(szLanguages[6], _T("Spanish")); + _stprintf(szLanguages[7], _T("Italian")); + _stprintf(szLanguages[8], _T("German")); + _stprintf(szLanguages[9], _T("Portuguese")); + _stprintf(szLanguages[10], _T("Polish")); + _stprintf(szLanguages[11], _T("Hungarian")); + + _stprintf(szLanguageCodes[0], _T("en_US")); + _stprintf(szLanguageCodes[1], _T("zh_CN")); + _stprintf(szLanguageCodes[2], _T("zh_TW")); + _stprintf(szLanguageCodes[3], _T("ja_JP")); + _stprintf(szLanguageCodes[4], _T("ko_KR")); + _stprintf(szLanguageCodes[5], _T("fr_FR")); + _stprintf(szLanguageCodes[6], _T("es_ES")); + _stprintf(szLanguageCodes[7], _T("it_IT")); + _stprintf(szLanguageCodes[8], _T("de_DE")); + _stprintf(szLanguageCodes[9], _T("pt_BR")); + _stprintf(szLanguageCodes[10], _T("pl_PL")); + _stprintf(szLanguageCodes[11], _T("hu_HU")); + + for (int i = 0; i < NUM_LANGUAGES; i++) { + SendDlgItemMessage(hIpsDlg, IDC_CHOOSE_LIST, CB_ADDSTRING, 0, (LPARAM)&szLanguages[i]); + } + + SendDlgItemMessage(hIpsDlg, IDC_CHOOSE_LIST, CB_SETCURSEL, (WPARAM)nIpsSelectedLanguage, (LPARAM)0); + + hIpsList = GetDlgItem(hIpsDlg, IDC_TREE1); + + FillListBox(); + + CheckActivePatches(); + + return 0; +} + +static void RefreshPatch() +{ + SendMessage(GetDlgItem(hIpsDlg, IDC_TEXTCOMMENT), WM_SETTEXT, (WPARAM)0, (LPARAM)NULL); + SendDlgItemMessage(hIpsDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPreview); + + HTREEITEM hSelectHandle = (HTREEITEM)SendMessage(hIpsList, TVM_GETNEXTITEM, TVGN_CARET, ~0U); + + if (hBmp) { + DeleteObject((HGDIOBJ)hBmp); + hBmp = NULL; + } + + for (int i = 0; i < nNumPatches; i++) { + if (hSelectHandle == hPatchHandlesIndex[i]) { + TCHAR *PatchDesc = NULL; + + FILE *fp = _tfopen(szPatchFileNames[i], _T("r")); + if (fp) { + PatchDesc = GetPatchDescByLangcode(fp, nIpsSelectedLanguage); + // If not available - try English first + if (PatchDesc == NULL) PatchDesc = GetPatchDescByLangcode(fp, 0); + // Simplified Chinese is the reference language (should always be available!!) + if (PatchDesc == NULL) PatchDesc = GetPatchDescByLangcode(fp, 1); + + SendMessage(GetDlgItem(hIpsDlg, IDC_TEXTCOMMENT), WM_SETTEXT, (WPARAM)0, (LPARAM)PatchDesc); + + fclose(fp); + } + fp = NULL; + + TCHAR szImageFileName[MAX_PATH]; + szImageFileName[0] = _T('\0'); + + _tcscpy(szImageFileName, szPatchFileNames[i]); + szImageFileName[_tcslen(szImageFileName) - 3] = _T('p'); + szImageFileName[_tcslen(szImageFileName) - 2] = _T('n'); + szImageFileName[_tcslen(szImageFileName) - 1] = _T('g'); + + fp = _tfopen(szImageFileName, _T("rb")); + HBITMAP hNewImage = NULL; + if (fp) { + hNewImage = PNGLoadBitmap(hIpsDlg, fp, 304, 228, 3); + fclose(fp); + } + + if (hNewImage) { + DeleteObject((HGDIOBJ)hBmp); + hBmp = hNewImage; + SendDlgItemMessage(hIpsDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp); + } else { + SendDlgItemMessage(hIpsDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPreview); + } + } + } +} + +static void SavePatches() +{ + int nActivePatches = 0; + + for (int i = 0; i < MAX_ACTIVE_PATCHES; i++) { + _stprintf(szIpsActivePatches[i], _T("")); + } + + for (int i = 0; i < nNumPatches; i++) { + int nChecked = _TreeView_GetCheckState(hIpsList, hPatchHandlesIndex[i]); + + if (nChecked) { + _tcscpy(szIpsActivePatches[nActivePatches], szPatchFileNames[i]); + nActivePatches++; + } + } + + FILE* fp = _tfopen(GameIpsConfigName(), _T("wt")); + + if (fp) { + _ftprintf(fp, _T("// ") _T(APP_TITLE) _T(" v%s --- IPS Config File for %s (%s)\n\n"), szAppBurnVer, BurnDrvGetText(DRV_NAME), ANSIToTCHAR(BurnDrvGetTextA(DRV_FULLNAME), NULL, 0)); + for (int i = 0; i < nActivePatches; i++) { + TCHAR *Tokens; + TCHAR szFileName[MAX_PATH]; + Tokens = _tcstok(szIpsActivePatches[i], _T("\\")); + while (Tokens != NULL) { + szFileName[0] = _T('\0'); + _tcscpy(szFileName, Tokens); + Tokens = _tcstok(NULL, _T("\\")); + } + + _ftprintf(fp, _T("%s\n"), szFileName); + } + fclose(fp); + } +} + +static void IpsManagerExit() +{ + SendDlgItemMessage(hIpsDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + for (int i = 0; i < NUM_LANGUAGES; i++) { + szLanguages[i][0] = _T('\0'); + szLanguageCodes[i][0] = _T('\0'); + } + + memset(hItemHandles, 0, MAX_NODES); + memset(hPatchHandlesIndex, 0, MAX_NODES); + + nPatchIndex = 0; + nNumPatches = 0; + + for (int i = 0; i < MAX_NODES; i++) { + szPatchFileNames[i][0] = _T('\0'); + } + + if (hBmp) { + DeleteObject((HGDIOBJ)hBmp); + hBmp = NULL; + } + + if (hPreview) { + DeleteObject((HGDIOBJ)hPreview); + hPreview = NULL; + } + + DeleteObject(hWhiteBGBrush); + + hParent = NULL; + + EndDialog(hIpsDlg, 0); +} + +static void IpsOkay() +{ + SavePatches(); + IpsManagerExit(); +} + +static INT_PTR CALLBACK DefInpProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch (Msg) { + case WM_INITDIALOG: { + hIpsDlg = hDlg; + + hWhiteBGBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + hPreview = PNGLoadBitmap(hIpsDlg, NULL, 304, 228, 2); + SendDlgItemMessage(hIpsDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPreview); + + LONG_PTR Style; + Style = GetWindowLongPtr (GetDlgItem(hIpsDlg, IDC_TREE1), GWL_STYLE); + Style |= TVS_CHECKBOXES; + SetWindowLongPtr (GetDlgItem(hIpsDlg, IDC_TREE1), GWL_STYLE, Style); + + IpsManagerInit(); + + WndInMid(hDlg, hScrnWnd); + SetFocus(hDlg); // Enable Esc=close + break; + } + + case WM_COMMAND: { + int wID = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Notify == BN_CLICKED) { + switch (wID) { + case IDOK: { + IpsOkay(); + break; + } + + case IDCANCEL: { + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + + case IDC_IPSMAN_DESELECTALL: { + for (int i = 0; i < nNumPatches; i++) { + for (int j = 0; j < nNumPatches; j++) { + _TreeView_SetCheckState(hIpsList, hPatchHandlesIndex[j], FALSE); + } + } + break; + } + } + } + + if (wID == IDC_CHOOSE_LIST && Notify == CBN_SELCHANGE) { + nIpsSelectedLanguage = SendMessage(GetDlgItem(hIpsDlg, IDC_CHOOSE_LIST), CB_GETCURSEL, 0, 0); + TreeView_DeleteAllItems(hIpsList); + FillListBox(); + RefreshPatch(); + return 0; + } + + break; + } + + case WM_NOTIFY: { + NMHDR* pNmHdr = (NMHDR*)lParam; + + if (LOWORD(wParam) == IDC_TREE1 && pNmHdr->code == TVN_SELCHANGED) { + RefreshPatch(); + + return 1; + } + + if (LOWORD(wParam) == IDC_TREE1 && pNmHdr->code == NM_DBLCLK) { + // disable double-click node-expand + SetWindowLongPtr(hIpsDlg, DWLP_MSGRESULT, 1); + + return 1; + } + + if (LOWORD(wParam) == IDC_TREE1 && pNmHdr->code == NM_CLICK) { + POINT cursorPos; + GetCursorPos(&cursorPos); + ScreenToClient(hIpsList, &cursorPos); + + TVHITTESTINFO thi; + thi.pt = cursorPos; + TreeView_HitTest(hIpsList, &thi); + + if (thi.flags == TVHT_ONITEMSTATEICON) { + TreeView_SelectItem(hIpsList, thi.hItem); + } + + return 1; + } + + SetWindowLongPtr(hIpsDlg, DWLP_MSGRESULT, CDRF_DODEFAULT); + return 1; + } + + case WM_CTLCOLORSTATIC: { + if ((HWND)lParam == GetDlgItem(hIpsDlg, IDC_TEXTCOMMENT)) { + return (INT_PTR)hWhiteBGBrush; + } + break; + } + + case WM_CLOSE: { + IpsManagerExit(); + break; + } + } + + return 0; +} + +int IpsManagerCreate(HWND hParentWND) +{ + hParent = hParentWND; + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_IPS_MANAGER), hParent, (DLGPROC)DefInpProc); + return 1; +} + +// Game patching + +#define UTF8_SIGNATURE "\xef\xbb\xbf" +#define IPS_SIGNATURE "PATCH" +#define IPS_TAG_EOF "EOF" +#define IPS_EXT ".ips" + +#define BYTE3_TO_UINT(bp) \ + (((unsigned int)(bp)[0] << 16) & 0x00FF0000) | \ + (((unsigned int)(bp)[1] << 8) & 0x0000FF00) | \ + ((unsigned int)(bp)[2] & 0x000000FF) + +#define BYTE2_TO_UINT(bp) \ + (((unsigned int)(bp)[0] << 8) & 0xFF00) | \ + ((unsigned int) (bp)[1] & 0x00FF) + +bool bDoIpsPatch = FALSE; + +static void PatchFile(const char* ips_path, UINT8* base) +{ + char buf[6]; + FILE* f = NULL; + int Offset, Size; + UINT8* mem8 = NULL; + + if (NULL == (f = fopen(ips_path, "rb"))) + return; + + memset(buf, 0, sizeof buf); + fread(buf, 1, 5, f); + if (strcmp(buf, IPS_SIGNATURE)) { + return; + } else { + UINT8 ch = 0; + int bRLE = 0; + while (!feof(f)) { + // read patch address offset + fread(buf, 1, 3, f); + buf[3] = 0; + if (strcmp(buf, IPS_TAG_EOF) == 0) + break; + + Offset = BYTE3_TO_UINT(buf); + + // read patch length + fread(buf, 1, 2, f); + Size = BYTE2_TO_UINT(buf); + + bRLE = (Size == 0); + if (bRLE) { + fread(buf, 1, 2, f); + Size = BYTE2_TO_UINT(buf); + ch = fgetc(f); + } + + while (Size--) { + mem8 = base + Offset; + Offset++; + *mem8 = bRLE ? ch : fgetc(f); + } + } + } + + fclose(f); +} + +static void DoPatchGame(const char* patch_name, char* game_name, UINT8* base) +{ + char s[MAX_PATH]; + char* p = NULL; + char* rom_name = NULL; + char* ips_name = NULL; + FILE* fp = NULL; + unsigned long nIpsSize; + + if ((fp = fopen(patch_name, "rb")) != NULL) { + // get ips size + fseek(fp, 0, SEEK_END); + nIpsSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + while (!feof(fp)) { + if (fgets(s, sizeof s, fp) != NULL) { + p = s; + + // skip UTF-8 sig + if (strncmp(p, UTF8_SIGNATURE, strlen(UTF8_SIGNATURE)) == 0) + p += strlen(UTF8_SIGNATURE); + + if (p[0] == '[') // '[' + break; + + rom_name = strtok(p, " \t\r\n"); + if (!rom_name) + continue; + if (*rom_name == '#') + continue; + if (_stricmp(rom_name, game_name)) + continue; + + ips_name = strtok(NULL, " \t\r\n"); + if (!ips_name) + continue; + + // skip CRC check + strtok(NULL, "\r\n"); + + char ips_path[MAX_PATH]; + char ips_dir[MAX_PATH]; + TCHARToANSI(szAppIpsPath, ips_dir, sizeof(ips_dir)); + + if (strchr(ips_name, '\\')) { + // ips in parent's folder + sprintf(ips_path, "%s\\%s%s", ips_dir, ips_name, IPS_EXT); + } else { + sprintf(ips_path, "%s%s\\%s%s", ips_dir, BurnDrvGetTextA(DRV_NAME), ips_name, IPS_EXT); + } + + PatchFile(ips_path, base); + } + } + fclose(fp); + } +} + +void IpsApplyPatches(UINT8* base, char* rom_name) +{ + char ips_data[MAX_PATH]; + + int nActivePatches = GetIpsNumActivePatches(); + + for (int i = 0; i < nActivePatches; i++) { + memset(ips_data, 0, MAX_PATH); + TCHARToANSI(szIpsActivePatches[i], ips_data, sizeof(ips_data)); + DoPatchGame(ips_data, rom_name, base); + } +} + +void IpsPatchExit() +{ + bDoIpsPatch = FALSE; +} diff --git a/src/burner/win32/localise.cpp b/src/burner/win32/localise.cpp new file mode 100644 index 00000000..3a10823a --- /dev/null +++ b/src/burner/win32/localise.cpp @@ -0,0 +1,1698 @@ +#include "burner.h" +#include + +// #define PRINT_TRANSLATION_INFO + +bool bLocalisationActive = false; +TCHAR szLocalisationTemplate[MAX_PATH] = _T(""); + +static const unsigned int nMaxResources = 1000; + +static int nFBACodepage; + +struct LocaliseControlInfo { unsigned int nID; wchar_t szCaption[QUOTE_MAX]; }; +struct LocaliseResourceInfo { unsigned int nID; wchar_t szCaption[QUOTE_MAX]; LocaliseControlInfo* pControlInfo[1024]; }; + +#define RES_DEALLOCATE (1 << 0) +#define RES_ISTRANSLATION (1 << 1) + +struct FBAResourceInfo_t { int nResourceFlags; void* pResourceTranslation; }; +static FBAResourceInfo_t* FBAResourceInfo = NULL; + +typedef struct { + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x; + short y; + short cx; + short cy; +// sz_Or_Ord menu; +// sz_Or_Ord windowClass; +// WCHAR title[titleLen]; +// WORD pointsize; +// WORD weight; +// BYTE italic; +// BYTE charset; +// WCHAR typeface[stringLen]; +} DLGTEMPLATEEX; + +typedef struct { + DWORD helpID; + DWORD exStyle; + DWORD style; + short x; + short y; + short cx; + short cy; + WORD id; +// sz_Or_Ord windowClass; +// sz_Or_Ord title; +// WORD extraCount; +} DLGITEMTEMPLATEEX; + +// ---------------------------------------------------------------------------- + +#define WSKIP_WS(s) while (iswspace(*s)) { s++; } // Skip whitespace +#define WFIND_WS(s) while (*s && !iswspace(*s)) { s++; } // Find whitespace +#define WFIND_QT(s) while (*s && *s != L'\"') { s++; } // Find quote + +#if defined (UNICODE) +#define QuoteReadW QuoteRead +#define LabelCheckW LabelCheck +#else +int QuoteReadW(wchar_t** ppszQuote, wchar_t** ppszEnd, wchar_t* pszSrc) +{ + static wchar_t szQuote[QUOTE_MAX]; + wchar_t* s = pszSrc; + wchar_t* e; + + // Skip whitespace + WSKIP_WS(s); + + e = s; + + if (*s == _T('\"')) { // Quoted string + s++; + e++; + // Find end quote + WFIND_QT(e); + wcsncpy(szQuote, s, e - s); + // Zero-terminate + szQuote[e - s] = _T('\0'); + e++; + } else { // Non-quoted string + // Find whitespace + WFIND_WS(e); + wcsncpy(szQuote, s, e - s); + // Zero-terminate + szQuote[e - s] = _T('\0'); + } + + if (ppszQuote) { + *ppszQuote = szQuote; + } + if (ppszEnd) { + *ppszEnd = e; + } + + return 0; +} + +wchar_t* LabelCheckW(wchar_t* s, wchar_t* pszLabel) +{ + int nLen; + + if (s == NULL) { + return NULL; + } + if (pszLabel == NULL) { + return NULL; + } + nLen = wcslen(pszLabel); + + WSKIP_WS(s); // Skip whitespace + + if (wcsncmp(s, pszLabel, nLen)){ // Doesn't match + return NULL; + } + + return s + nLen; +} +#endif + +// ---------------------------------------------------------------------------- + +int EscapeString(wchar_t* pwszStringOut, wchar_t* pwszStringIn, int max) +{ + int in = 0, out = 0; + + while (pwszStringIn[in] && out < (max - 1)) { + switch (pwszStringIn[in]) { + case L'\n': + pwszStringOut[out++] = L'\\'; + pwszStringOut[out++] = L'n'; + break; + case L'\t': + pwszStringOut[out++] = L'\\'; + pwszStringOut[out++] = L't'; + break; + case L'\'': + pwszStringOut[out++] = L'\\'; + pwszStringOut[out++] = L'\''; + break; + case L'\"': + pwszStringOut[out++] = L'\\'; + pwszStringOut[out++] = L'\"'; + break; + case L'\\': + pwszStringOut[out++] = L'\\'; + pwszStringOut[out++] = L'\\'; + break; + + default: + pwszStringOut[out++] = pwszStringIn[in]; + } + + in++; + } + + pwszStringOut[out] = L'\0'; + + return out; +} + +int UnEscapeString(wchar_t* pwszStringOut, wchar_t* pwszStringIn, int max) +{ + int in = 0, out = 0; + + while (pwszStringIn[in] && in < max) { + if (pwszStringIn[in] == L'\\') { + in++; + switch (pwszStringIn[in++]) { + case L'n': + pwszStringOut[out++] = L'\n'; + break; + case L't': + pwszStringOut[out++] = L'\t'; + break; + case L'\'': + pwszStringOut[out++] = L'\''; + break; + case L'\"': + pwszStringOut[out++] = L'\"'; + break; + case L'\\': + pwszStringOut[out++] = L'\\'; + break; + + default: + pwszStringOut[out++] = pwszStringIn[in]; + } + } else { + pwszStringOut[out++] = pwszStringIn[in++]; + } + } + + pwszStringOut[out] = L'\0'; + + return out; +} + +// ---------------------------------------------------------------------------- +// Translation template creation + +int BuildTemplateDlgTemplateEx(const DLGTEMPLATEEX* pTemplate, LPTSTR lpszName, FILE* fp) +{ + wchar_t wszBuffer[5120]; + wchar_t* pszCaption = L""; + int nControls = 0; + + // 26 is sizeof(DLGTEMPLATEEX) + char* pTemplateDataIn = (char*)(((INT_PTR)pTemplate + 26 + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Menu + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + + // Caption + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + pszCaption = (wchar_t*)pTemplateDataIn; + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + + if (fp) { + EscapeString(wszBuffer, pszCaption, 5120); + _ftprintf(fp, _T(" //-- \"%ls\"\n"), wszBuffer); + if (IS_INTRESOURCE(lpszName)) { + _ftprintf(fp, _T("dialog\t%4i "), (INT_PTR)lpszName); + } else { +#if defined (UNICODE) + EscapeString(wszBuffer, lpszName, 5120); +#else + wchar_t szTemp[5120] = L""; + + MultiByteToWideChar(nFBACodepage, 0, lpszName, -1, szTemp, 5120); + EscapeString(wszBuffer, szTemp, 5120); +#endif + _ftprintf(fp, _T("dialog\t%s "), wszBuffer); + } + + _ftprintf(fp, _T("\"\" {\n")); + } + + // Font + if (pTemplate->style & (DS_SETFONT | DS_SHELLFONT)) { + +#if 0 + if (fp) { + EscapeString(wszBuffer, (wchar_t*)(pTemplateDataIn + 2 + 2 * sizeof(WORD)), 5120); + _ftprintf(fp, _T("\tfont %2i \"%ls\"\n"), *((WORD*)pTemplateDataIn), wszBuffer); + } +#endif + + pTemplateDataIn += 2 + 2 * sizeof(WORD); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + } + + // Controls + for (int i = 0; i < pTemplate->cDlgItems; i++) { + bool bExcludeControl = false; + DWORD dwStyle; + WORD wID; + + pTemplateDataIn = (char*)(((INT_PTR)pTemplateDataIn + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1)); + + dwStyle = ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->style; + wID = ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->id; + + pTemplateDataIn = (char*)(((INT_PTR)pTemplateDataIn + sizeof(DLGITEMTEMPLATEEX) + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + if ( ((WORD*)pTemplateDataIn)[1] == 0x0081 || + (((WORD*)pTemplateDataIn)[1] == 0x0082 && (dwStyle & SS_BITMAP))) { + + bExcludeControl = true; + } + + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + if ( !wcsicmp((wchar_t*)pTemplateDataIn, L"SysTreeView32") || + !wcsicmp((wchar_t*)pTemplateDataIn, L"SysListView32") || + !wcsicmp((wchar_t*)pTemplateDataIn, L"Edit") || + !wcsnicmp((wchar_t*)pTemplateDataIn, L"RichEdit", 8) || + (!wcsicmp((wchar_t*)pTemplateDataIn, L"Static") && (dwStyle & SS_BITMAP))) { + + bExcludeControl = true; + } + + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + + if (*((WORD*)pTemplateDataIn) == 0xFFFF) { + pTemplateDataIn += 4; + } + + if (wcslen((wchar_t*)pTemplateDataIn) && !bExcludeControl) { + nControls++; + + if (fp) { + EscapeString(wszBuffer, (wchar_t*)pTemplateDataIn, 5120); + _ftprintf(fp, _T(" //-- \"%ls\"\n"), wszBuffer); + _ftprintf(fp, _T(" %5i\t%4i \"\"\n"), wID, i); + } + } + + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + pTemplateDataIn += sizeof(WORD) + *((WORD*)pTemplateDataIn); + } + + if (fp) { + _ftprintf(fp, _T("}\n\n")); + } + + return nControls; +} + +int BuildTemplateMenuTemplate(const MENUTEMPLATE* pTemplate, LPTSTR lpszName, FILE* fp) +{ + wchar_t wszBuffer[5120]; + TCHAR szIndent[] = _T(" "); + + char* pTemplateDataIn = (char*)pTemplate + sizeof(MENUITEMTEMPLATEHEADER); + bool bLastPopup = false, bLastItem = false; + int nIndent = 0; + int bracketcnt = 0; // popup menu counter (BEGIN...END) + int i = 0; + + if (fp) { + if (IS_INTRESOURCE(lpszName)) { + _ftprintf(fp, _T("menu %4i {\n"), (INT_PTR)lpszName); + } else { +#if defined (UNICODE) + EscapeString(wszBuffer, lpszName, 5120); +#else + wchar_t szTemp[5120] = L""; + + MultiByteToWideChar(nFBACodepage, 0, lpszName, -1, szTemp, 5120); + EscapeString(wszBuffer, szTemp, 5120); +#endif + _ftprintf(fp, _T("menu %s {\n"), wszBuffer); + } + } + + do { + wchar_t pszTitle[1024] = L""; + WORD wOption = ((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption; + WORD wID = 0; + int l; + + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_POPUP) { + bLastPopup = false; + bLastItem = false; + bracketcnt++; + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastPopup = true; + bracketcnt--; + } + pTemplateDataIn += sizeof(WORD); + } else { + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastItem = true; + bracketcnt--; + } + wID = ((MENUITEMTEMPLATE*)pTemplateDataIn)->mtID; + pTemplateDataIn += sizeof(WORD) * 2; + } + + for (l = 0; l < 1023 && ((wchar_t*)pTemplateDataIn)[l] && ((wchar_t*)pTemplateDataIn)[l] != _T('\t'); l++) { } + + wcsncpy(pszTitle, (wchar_t*)pTemplateDataIn, l); + + if (fp) { + if (wcslen((wchar_t*)pTemplateDataIn)) { + EscapeString(wszBuffer, pszTitle, 5120); + _ftprintf(fp, _T("%s //-- \"%ls\"\n"), szIndent + (8 - nIndent) * 2, wszBuffer); + _ftprintf(fp, _T("%s"), szIndent + (8 - nIndent) * 2); + if (wOption & MF_POPUP) { + _ftprintf(fp, _T(" popup %4i \"\" {\n"), i); + nIndent++; + } else { + _ftprintf(fp, _T(" %5i %4i \"\"\n"), wID, i); + } + } + + if ((wOption & MF_END) && !(wOption & MF_POPUP)) { + nIndent--; + if (nIndent < 0) { + nIndent = 0; + } + if (nIndent > 8) { + nIndent = 8; + } + + if (fp) { + _ftprintf(fp, _T("%s }\n"), szIndent + (8 - nIndent) * 2); + } + } + } + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + + } while (i++ < 1024 && (!(bLastPopup && bLastItem) || bracketcnt > 0)); + + if (fp) { + while (nIndent) { + nIndent--; + _ftprintf(fp, _T("%s }\n"), szIndent + (8 - nIndent) * 2); + } + + _ftprintf(fp, _T("}\n\n")); + } + + return i; +} + +static BOOL CALLBACK FBALocaliseEnumResourceNamesDialog(HMODULE /* hModule */, LPCTSTR /* lpszType */, LPTSTR lpszName, LONG_PTR lParam) +{ + LPCDLGTEMPLATE pTemplate = (LPCDLGTEMPLATE)LoadResource(hAppInst, FindResource(hAppInst, lpszName, RT_DIALOG)); + + if (LockResource((HGLOBAL)pTemplate)) { + if (((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF && ((DLGTEMPLATEEX*)pTemplate)->dlgVer == 1) { + if (BuildTemplateDlgTemplateEx((DLGTEMPLATEEX*)pTemplate, lpszName, NULL)) { + BuildTemplateDlgTemplateEx((DLGTEMPLATEEX*)pTemplate, lpszName, (FILE*)lParam); + } + } + } + + return TRUE; +} + +static BOOL CALLBACK FBALocaliseEnumResourceNamesMenu(HMODULE /* hModule */, LPCTSTR /* lpszType */, LPTSTR lpszName, LONG_PTR lParam) +{ + MENUTEMPLATE* pTemplate = (MENUTEMPLATE*)LoadResource(hAppInst, FindResource(hAppInst, lpszName, RT_MENU)); + + if (LockResource((HGLOBAL)pTemplate)) { + if (((MENUITEMTEMPLATEHEADER*)pTemplate)->versionNumber == 0) { + BuildTemplateMenuTemplate((MENUITEMTEMPLATEHEADER*)pTemplate, lpszName, (FILE*)lParam); + } + } + + return TRUE; +} + +static BOOL CALLBACK FBALocaliseEnumResourceNamesString(HMODULE /* hModule */, LPCTSTR /* lpszType */, LPTSTR lpszName, LONG_PTR lParam) +{ + wchar_t* pwsz = (wchar_t*)LoadResource(hAppInst, FindResource(hAppInst, lpszName, RT_STRING)); + + if (LockResource(pwsz)) { + wchar_t wszBuffer[5120]; + + // Locate the string in the bundle + for (int i = 0; i < 16; i++) { + if (*pwsz) { + EscapeString(wszBuffer, pwsz + 1, 5120); + _ftprintf((FILE*)lParam, _T(" //-- \"%ls\"\n"), wszBuffer); + _ftprintf((FILE*)lParam, _T("string %5i \"\"\n\n"), (((INT_PTR)lpszName) - 1) * 16 + i); + } + pwsz += *pwsz + 1; + } + } + + return TRUE; +} + +static BOOL CALLBACK FBALocaliseEnumResTypeProc(HMODULE /* hModule */, LPTSTR lpszType, LONG_PTR lParam) +{ + if (lpszType == RT_DIALOG) { + EnumResourceNames(NULL, lpszType, &FBALocaliseEnumResourceNamesDialog, lParam); + } + if (lpszType == RT_MENU) { + EnumResourceNames(NULL, lpszType, &FBALocaliseEnumResourceNamesMenu, lParam); + } + if (lpszType == RT_STRING) { + EnumResourceNames(NULL, lpszType, &FBALocaliseEnumResourceNamesString, lParam); + } + + return TRUE; +} + +static int FBALocaliseWriteTemplate(TCHAR* pszTemplate) +{ + FILE* fp = _tfopen(pszTemplate, _T("wt")); + if (fp == NULL) { + return 1; + } + + _ftprintf(fp, _T("// translation template for FB Alpha\n\n")); + _ftprintf(fp, _T("version 0x%06X\n\n"), nBurnVer); + + _ftprintf(fp, _T("// codepage 1252\n\n")); + + EnumResourceTypes(NULL, (ENUMRESTYPEPROC)FBALocaliseEnumResTypeProc, (LONG_PTR)fp); + + fclose(fp); + + return 0; +} + +// ----------------------------------------------------------------------------- + +#define CATCH_UP { int nCopySize = pTemplateDataIn - pTemplateDataInSync; \ + int nTotalSize = pTemplateDataOutSync - pTemplateDataOut; \ + pTemplateDataOut = (char*)realloc(pTemplateDataOut, nTotalSize + nCopySize); \ + memcpy(pTemplateDataOut + nTotalSize, pTemplateDataInSync, nCopySize); \ + pTemplateDataInSync = pTemplateDataIn; \ + pTemplateDataOutSync = pTemplateDataOut + nTotalSize + nCopySize; } + +#define ALIGN(a) { int nTotalSize = (pTemplateDataOutSync - pTemplateDataOut + a - 1) & ~(a - 1); \ + pTemplateDataOut = (char*)realloc(pTemplateDataOut, nTotalSize); \ + pTemplateDataOutSync = pTemplateDataOut + nTotalSize; } + +#define ADD_STRING(s) { int nTotalSize = pTemplateDataOutSync - pTemplateDataOut; \ + int nExtraSize = wcslen((wchar_t*)s) * sizeof(wchar_t) + sizeof(wchar_t); \ + pTemplateDataOut = (char*)realloc(pTemplateDataOut, nTotalSize + nExtraSize); \ + wcscpy((wchar_t*)(pTemplateDataOut + nTotalSize), s); \ + pTemplateDataOutSync = pTemplateDataOut + nTotalSize + nExtraSize; } + +#ifdef PRINT_TRANSLATION_INFO +void ParseDlgTemplateEx(const DLGTEMPLATEEX* pTemplate) +{ + // 26 is sizeof(DLGTEMPLATEEX) + char* pTemplateDataIn = (char*)(((UINT32)pTemplate + 26 + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + +#if 0 + dprintf(_T("\n")); + char* pData = (char*)pTemplate; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 4; k++) { + unsigned int n = *pData; + dprintf(_T("%02X"), n & 255); + pData++; + } + dprintf(_T(" ")); + } + dprintf(_T("\n")); + } + dprintf(_T("\n")); +#endif + + // Menu + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + dprintf(_T(" menu is %04X.\n"), *((UINT16*)pTemplateDataIn + sizeof(WORD))); + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + dprintf(_T(" menu is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + dprintf(_T(" class is %04X.\n"), *((UINT16*)pTemplateDataIn + sizeof(WORD))); + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + dprintf(_T(" class is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Caption + dprintf(_T(" ")); + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + dprintf(_T("icon is %04X, "), *((UINT16*)pTemplateDataIn + sizeof(WORD))); + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + dprintf(_T("caption is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + + // Font + if (pTemplate->style & (DS_SETFONT | DS_SHELLFONT)) { + dprintf(_T(" Font: \"%ls\", %i pt.\n"), (wchar_t*)(pTemplateDataIn + 2 + 2 * sizeof(WORD)), *((WORD*)pTemplateDataIn)); + pTemplateDataIn += 2 + 2 * sizeof(WORD); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + } + + // Controls + dprintf(_T(" %i controls used.\n"), pTemplate->cDlgItems); + for (int i = 0; i < pTemplate->cDlgItems; i++) { + pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1)); + + dprintf(_T(" control %02i, ID is %05i, pos %03ix%03i, size %03ix%03i\n"), i, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->id, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->x, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->y, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->cx, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->cy); + + pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(DLGITEMTEMPLATEEX) + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + dprintf(_T(" ")); + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: + dprintf(_T("class is %04X, "), *((UINT16*)pTemplateDataIn + sizeof(WORD))); + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: + dprintf(_T("class is \"%ls\", "), (wchar_t*)pTemplateDataIn); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + if (*((WORD*)pTemplateDataIn) == 0xFFFF) { + pTemplateDataIn += 4; + } + + dprintf(_T("title is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + if (*((WORD*)pTemplateDataIn)) { + dprintf(_T(" %i bytes of extra data present.\n"), *((WORD*)pTemplateDataIn)); + } + pTemplateDataIn += sizeof(WORD) + *((WORD*)pTemplateDataIn); + } +} +#endif + +DLGTEMPLATE* TranslateDlgTemplateEx(const DLGTEMPLATEEX* pTemplate, const LocaliseResourceInfo* pLocaliseInfo) +{ + // 26 is sizeof(DLGTEMPLATEEX) + char* pTemplateDataIn = (char*)(((INT_PTR)pTemplate + 26 + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + char* pTemplateDataOut = NULL; + char* pTemplateDataInSync = NULL; + char* pTemplateDataOutSync = NULL; + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("Translating dialogex template:\n")); +#endif + + pTemplateDataOut = (char*)malloc(26); + memcpy(pTemplateDataOut, (char*)pTemplate, 26); + pTemplateDataInSync = pTemplateDataIn; + pTemplateDataOutSync = pTemplateDataOut + 26; + +#ifdef PRINT_TRANSLATION_INFO + #if 0 + dprintf(_T("\n")); + char* pData = (char*)pTemplate; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 4; k++) { + unsigned int n = *pData; + dprintf(_T("%02X"), n & 255); + pData++; + } + dprintf(_T(" ")); + } + dprintf(_T("\n")); + } + dprintf(_T("\n")); + #endif +#endif + + // Menu + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" menu is %04X.\n"), *((UINT16*)pTemplateDataIn + sizeof(WORD))); +#endif + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" menu is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); +#endif + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" class is %04X.\n"), *((UINT16*)pTemplateDataIn + sizeof(WORD))); +#endif + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" class is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); +#endif + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + // Caption +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" ")); +#endif + if (*((WORD*)pTemplateDataIn) == 0xFFFF) { +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("icon is %04X, "), *((UINT16*)pTemplateDataIn + sizeof(WORD))); +#endif + pTemplateDataIn += 2 * sizeof(WORD); + } + CATCH_UP; + if (pLocaliseInfo->szCaption[0]) { + ADD_STRING(pLocaliseInfo->szCaption); + } else { + ADD_STRING((wchar_t*)pTemplateDataIn); + } + + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + default: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("caption is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); +#endif + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + pTemplateDataInSync = pTemplateDataIn; + + // Font + if (pTemplate->style & (DS_SETFONT | DS_SHELLFONT)) { +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" Font: \"%ls\", %i pt.\n"), (wchar_t*)(pTemplateDataIn + 2 + 2 * sizeof(WORD)), *((WORD*)pTemplateDataIn)); +#endif + pTemplateDataIn += 2 + 2 * sizeof(WORD); + +#if 0 + CATCH_UP; + ADD_STRING(L"Times New Roman"); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + pTemplateDataInSync = pTemplateDataIn; +#else + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); +#endif + + } + + // Controls +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" %i controls used.\n"), pTemplate->cDlgItems); +#endif + for (int i = 0; i < pTemplate->cDlgItems; i++) { + + CATCH_UP; + ALIGN(sizeof(DWORD)); + + pTemplateDataIn = pTemplateDataInSync = (char*)(((INT_PTR)pTemplateDataIn + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1)); + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" control %02i, ID is %05i, pos %03ix%03i, size %03ix%03i\n"), i, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->id, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->x, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->y, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->cx, ((DLGITEMTEMPLATEEX*)pTemplateDataIn)->cy); +#endif + + pTemplateDataIn = (char*)(((INT_PTR)pTemplateDataIn + sizeof(DLGITEMTEMPLATEEX) + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" ")); +#endif + + // Class + switch (*((WORD*)pTemplateDataIn)) { + case 0x0000: + pTemplateDataIn += 1 * sizeof(WORD); + break; + case 0xFFFF: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("class is %04X, "), *((UINT16*)pTemplateDataIn + sizeof(WORD))); +#endif + pTemplateDataIn += 2 * sizeof(WORD); + break; + default: +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("class is \"%ls\", "), (wchar_t*)pTemplateDataIn); +#endif + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + break; + } + +// pTemplateDataIn = (char*)(((UINT32)pTemplateDataIn + sizeof(WORD) - 1) & ~(sizeof(WORD) - 1)); + + if (*((WORD*)pTemplateDataIn) == 0xFFFF) { + pTemplateDataIn += 4; + } + + CATCH_UP; + if (pLocaliseInfo->pControlInfo[i] && pLocaliseInfo->pControlInfo[i]->szCaption[0]) { + ADD_STRING(pLocaliseInfo->pControlInfo[i]->szCaption); + } else { + ADD_STRING((wchar_t*)pTemplateDataIn); + } + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("title is \"%ls\".\n"), (wchar_t*)pTemplateDataIn); +#endif + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + pTemplateDataInSync = pTemplateDataIn; +#ifdef PRINT_TRANSLATION_INFO + if (*((WORD*)pTemplateDataIn)) { + dprintf(_T(" %i bytes of extra data present.\n"), *((WORD*)pTemplateDataIn)); + } +#endif + pTemplateDataIn += sizeof(WORD) + *((WORD*)pTemplateDataIn); + } + + CATCH_UP; + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("Parsing translated template:\n")); + + if (((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF) { + ParseDlgTemplateEx((DLGTEMPLATEEX*)pTemplateDataOut); + } + + dprintf(_T("Done.\n")); +#endif + + return (DLGTEMPLATE*)pTemplateDataOut; +} + +INT_PTR FBADialogBox(HINSTANCE hInstance, LPTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc) +{ + // Try to load the translated dialog + if (bLocalisationActive && hInstance == hAppInst && (UINT_PTR)lpTemplate < nMaxResources && FBAResourceInfo[(UINT_PTR)lpTemplate].pResourceTranslation) { + return DialogBoxIndirect(hInstance, (LPCDLGTEMPLATE)FBAResourceInfo[(INT_PTR)lpTemplate].pResourceTranslation, hWndParent, lpDialogFunc); + } + + // Localisation disabled or couldn't lock resource, so use normal function + return DialogBox(hInstance, lpTemplate, hWndParent, lpDialogFunc); +} + +HWND FBACreateDialog(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc) +{ + // Try to load the translated dialog + if (bLocalisationActive && hInstance == hAppInst && (UINT_PTR)lpTemplate < nMaxResources && FBAResourceInfo[(UINT_PTR)lpTemplate].pResourceTranslation) { + return CreateDialogIndirect(hInstance, (LPCDLGTEMPLATE)FBAResourceInfo[(INT_PTR)lpTemplate].pResourceTranslation, hWndParent, lpDialogFunc); + } + + // Localisation disabled or couldn't lock resource, so use normal function + return CreateDialog(hInstance, lpTemplate, hWndParent, lpDialogFunc); +} + +// ---------------------------------------------------------------------------- + +#ifdef PRINT_TRANSLATION_INFO +void ParseMenuTemplate(const MENUTEMPLATE* pTemplate) +{ + // 26 is sizeof(DLGTEMPLATEEX) + char* pTemplateDataIn = (char*)pTemplate + sizeof(MENUITEMTEMPLATEHEADER); + +#if 0 + dprintf(_T("\n")); + char* pData = (char*)pTemplate; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 4; k++) { + unsigned int n = *pData; + dprintf(_T("%02X"), n & 255); + pData++; + } + dprintf(_T(" ")); + } + dprintf(_T("\n")); + } + dprintf(_T("\n")); +#endif + + int i = 0; + int bracketcnt = 0; // popup menu counter (BEGIN...END) + bool bLastPopup = false, bLastItem = false; + do { + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_POPUP) { + bLastPopup = false; + bLastItem = false; + bracketcnt++; + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastPopup = true; + bracketcnt--; + } + dprintf(_T(" popup %03i "), i); + pTemplateDataIn += sizeof(WORD); + } else { + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastItem = true; + bracketcnt--; + } + dprintf(_T(" item %03i ID is %05i "), i, ((MENUITEMTEMPLATE*)pTemplateDataIn)->mtID); + pTemplateDataIn += sizeof(WORD) * 2; + } + + dprintf(_T("\"%ls\".\n"), ((wchar_t*)pTemplateDataIn)); + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + } while (i++ < 1024 && (!(bLastPopup && bLastItem) || bracketcnt > 0)); +} +#endif + +MENUTEMPLATE* TranslateMenuTemplate(const MENUTEMPLATE* pTemplate, const LocaliseResourceInfo* pLocaliseInfo) +{ + // 26 is sizeof(DLGTEMPLATEEX) + char* pTemplateDataIn = (char*)pTemplate + sizeof(MENUITEMTEMPLATEHEADER); + char* pTemplateDataOut = NULL; + char* pTemplateDataInSync = NULL; + char* pTemplateDataOutSync = NULL; + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("Translating menu template:\n")); +#endif + + pTemplateDataOut = (char*)malloc(sizeof(MENUITEMTEMPLATEHEADER)); + memcpy(pTemplateDataOut, (char*)pTemplate, sizeof(MENUITEMTEMPLATEHEADER) + ((MENUITEMTEMPLATEHEADER*)pTemplate)->offset); + pTemplateDataInSync = pTemplateDataIn; + pTemplateDataOutSync = pTemplateDataOut + sizeof(MENUITEMTEMPLATEHEADER) + ((MENUITEMTEMPLATEHEADER*)pTemplate)->offset; + +#ifdef PRINT_TRANSLATION_INFO + #if 0 + dprintf(_T("\n")); + char* pData = (char*)pTemplate; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 4; k++) { + unsigned int n = *pData; + dprintf(_T("%02X"), n & 255); + pData++; + } + dprintf(_T(" ")); + } + dprintf(_T("\n")); + } + dprintf(_T("\n")); + #endif +#endif + + int i = 0; + int bracketcnt = 0; // popup menu counter (BEGIN...END) + bool bLastPopup = false, bLastItem = false; + do { + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_POPUP) { + bLastPopup = false; + bLastItem = false; + bracketcnt++; + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastPopup = true; + bracketcnt--; + } +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" popup %03i "), i); +#endif + pTemplateDataIn += sizeof(WORD); + } else { + if (((MENUITEMTEMPLATE*)pTemplateDataIn)->mtOption & MF_END) { + bLastItem = true; + bracketcnt--; + } +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T(" item %03i ID is %05i "), i, ((MENUITEMTEMPLATE*)pTemplateDataIn)->mtID); +#endif + pTemplateDataIn += sizeof(WORD) * 2; + } + + CATCH_UP; +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("\"%ls\".\n"), (wchar_t*)pTemplateDataIn); +#endif + if (pLocaliseInfo->pControlInfo[i] && pLocaliseInfo->pControlInfo[i]->szCaption[0]) { + wchar_t* pszHotkey = NULL; + + for (pszHotkey = (wchar_t*)pTemplateDataIn; *pszHotkey && *pszHotkey != _T('\t'); pszHotkey++) { } + + ADD_STRING(pLocaliseInfo->pControlInfo[i]->szCaption); + if (*pszHotkey) { + pTemplateDataOutSync -= sizeof(wchar_t); + ADD_STRING(pszHotkey); + } + } else { + ADD_STRING((wchar_t*)pTemplateDataIn); + } + + pTemplateDataIn += wcslen((wchar_t*)pTemplateDataIn) * sizeof(wchar_t) + sizeof(wchar_t); + pTemplateDataInSync = pTemplateDataIn; + } while (i++ < 1024 && (!(bLastPopup && bLastItem) || bracketcnt > 0)); + + CATCH_UP; + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("Parsing translated template:\n")); + ParseMenuTemplate((MENUTEMPLATE*)pTemplateDataOut); + dprintf(_T("Done.\n")); +#endif + + return (MENUTEMPLATE*)pTemplateDataOut; + +} + +HMENU FBALoadMenu(HINSTANCE hInstance, LPTSTR lpMenuName) +{ + // Try to load the translated menu + if (bLocalisationActive && hInstance == hAppInst && (UINT_PTR)lpMenuName < nMaxResources && FBAResourceInfo[(UINT_PTR)lpMenuName].pResourceTranslation) { + return LoadMenuIndirect((MENUTEMPLATE*)FBAResourceInfo[(INT_PTR)lpMenuName].pResourceTranslation); + } + + // Translation unavailable, so use normal function + return LoadMenu(hInstance, lpMenuName); +} + +// ---------------------------------------------------------------------------- + +TCHAR* FBALoadStringEx(HINSTANCE hInstance, UINT uID, bool bTranslate) +{ + if (bLocalisationActive && bTranslate && uID < nMaxResources) { + if (FBAResourceInfo[uID].pResourceTranslation) { + +#if 1 && defined (PRINT_TRANSLATION_INFO) + dprintf(_T("string %5i: \"%ls\"\n"), uID, (TCHAR*)FBAResourceInfo[uID].pResourceTranslation); +#endif + + return (TCHAR*)FBAResourceInfo[uID].pResourceTranslation; + } + } + + { + // Convert the string ID into a bundle number + wchar_t* pwsz = (wchar_t*)LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(uID / 16 + 1), RT_STRING)); + + if ((pwsz = (wchar_t*)LockResource(pwsz)) != NULL) { + // Locate the string in the bundle + for (unsigned int i = 0; i < (uID & 15); i++) { + pwsz += *pwsz + 1; + } + } + +#if 1 && defined (PRINT_TRANSLATION_INFO) + dprintf(_T("string %5i: \"%ls\"\n"), uID, *pwsz ? pwsz + 1 : pwsz); +#endif + +#if defined (UNICODE) && defined (_MSC_VER) + return *pwsz ? pwsz + 1 : pwsz; +#else + { +#if !defined (UNICODE) + static char szStringBuffer[5120]; +// memset(szStringBuffer, 0, sizeof(szStringBuffer)); + + if (WideCharToMultiByte(CP_ACP, 0, *pwsz ? pwsz + 1 : pwsz, *pwsz, szStringBuffer, 5120, NULL, NULL)) { + szStringBuffer[*pwsz] = '\0'; + return szStringBuffer; + } +#else + static wchar_t szStringBuffer[5120]; + + // When using GCC, copy the string since Windres can't zero-terminate strings in resource files + if (*pwsz) { + wcsncpy(szStringBuffer, pwsz + 1, *pwsz); + } + szStringBuffer[*pwsz] = '\0'; + return szStringBuffer; + +#endif + return NULL; + } +#endif + } +} + +int FBALoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax) +{ + if (bLocalisationActive && uID < nMaxResources) { + if (FBAResourceInfo[uID].pResourceTranslation) { + int nLen = _tcslen((TCHAR*)FBAResourceInfo[uID].pResourceTranslation); + +#if defined (UNICODE) + _tcsncpy(lpBuffer, (TCHAR*)FBAResourceInfo[uID].pResourceTranslation, nBufferMax - 1); +#else + strncpy(lpBuffer, (char*)FBAResourceInfo[uID].pResourceTranslation, nBufferMax - 1); +#endif + return ((nLen < nBufferMax) ? nLen : nBufferMax) - 1; + } + } + + return LoadString(hInstance, uID, lpBuffer, nBufferMax); +} + +// ---------------------------------------------------------------------------- + +static void FBALocaliseError(TCHAR* pszFilename, int nLineNumber, TCHAR* pszInfo, wchar_t* pszLine) +{ + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Language file %s is malformed.\nPlease remove or repair the file.\n\n"), pszFilename); + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Parse error at line %i.\n"), nLineNumber); + + if (pszInfo) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Problem:\t%s.\n"), pszInfo); + } + if (pszLine) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Text:\t%ls\n"), pszLine); + } + + FBAPopupDisplay(PUF_TYPE_ERROR); +} + +static int FBALocaliseParseFile(TCHAR* pszFilename) +{ + LocaliseResourceInfo CurrentResource; + wchar_t wszBuffer[5120]; + + int nTemplateVersion = 0; + + wchar_t szLine[5120]; + wchar_t* s; + wchar_t* t; + int nLen; + + int nLine = 0; + int nInside = 0; + TCHAR* nResourceType = 0; + + if (pszFilename == 0 || _tcslen(pszFilename) == 0) { + return -1; + } + + memset(&CurrentResource, 0, sizeof(LocaliseResourceInfo)); + + FILE* h = _tfopen(pszFilename, _T("rb")); + if (h == NULL) { + return 1; + } + + { + unsigned char szBOM[4] = { 0, }; + + fread(szBOM, 1, sizeof(szBOM), h); + + // See if it's a UTF-8 file + if (szBOM[0] == 0xEF && szBOM[1] == 0xBB && szBOM[2] == 0xBF) { + nFBACodepage = CP_UTF8; + } + +#ifdef _UNICODE + // See if it's a UTF-16 file + if (szBOM[0] == 0xFF && szBOM[1] == 0xFE) { + nFBACodepage = CP_WINUNICODE; + + fseek(h, 2, SEEK_SET); + } +#endif + + } + + if (nFBACodepage != CP_WINUNICODE) { + fclose(h); + h = _tfopen(pszFilename, _T("rt")); + if (h == NULL) { + return 1; + } + + if (nFBACodepage == CP_UTF8) { + fseek(h, 3, SEEK_SET); + } + + } + + while (1) { + char szTemp[1024]; + +#ifdef _UNICODE + if (nFBACodepage != CP_WINUNICODE) { +#endif + if (fgets(szTemp, sizeof(szTemp), h) == NULL) { + break; + } + MultiByteToWideChar(nFBACodepage, 0, szTemp, -1, szLine, sizeof(szLine) / sizeof(TCHAR)); +#ifdef _UNICODE + } else { + if (_fgetts(szLine, sizeof(szLine), h) == NULL) { + break; + } + } +#endif + + nLine++; + + nLen = wcslen(szLine); + // Get rid of the linefeed at the end + while (szLine[nLen - 1] == 0x0A || szLine[nLen - 1] == 0x0D) { + szLine[nLen - 1] = 0; + nLen--; + } + + s = szLine; // Start parsing + + WSKIP_WS(s); + + if (s[0] == _T('/') && s[1] == _T('/')) { // Comment + continue; + } + + if ((t = LabelCheckW(s, L"version")) != 0) { // Version + s = t; + + WSKIP_WS(s); + + nTemplateVersion = wcstol(s, &t, 0); + + if (s != t) { + if (nTemplateVersion != nBurnVer) { + break; + } + } + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("version\n"), nTemplateVersion); +#endif + + s = t; + + continue; + } + + if ((t = LabelCheckW(s, L"codepage")) != 0) { // Set codepage + s = t; + + WSKIP_WS(s); + + nFBACodepage = wcstol(s, &t, 0); + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("codepage\n"), nFBACodepage); +#endif + + s = t; + + continue; + } + + if ((t = LabelCheckW(s, L"menu")) != 0) { + s = t; + + nResourceType = RT_MENU; + + WSKIP_WS(s); + + unsigned int nID = wcstol(s, &t, 0); + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("menu %i\n"), nID); +#endif + s = t; + + WSKIP_WS(s); + + if (nInside) { + FBALocaliseError(pszFilename, nLine, _T("missing closing bracket"), NULL); + break; + } + if (*s != _T('{')) { + FBALocaliseError(pszFilename, nLine, _T("missing opening bracket"), NULL); + break; + } + nInside = 1; + + CurrentResource.nID = nID; + + continue; + } + + if ((t = LabelCheckW(s, L"dialog")) != 0) { // Add new resource + s = t; + + nResourceType = RT_DIALOG; + + WSKIP_WS(s); + + unsigned int nID = wcstol(s, &t, 0); + +#ifdef PRINT_TRANSLATION_INFO + dprintf(_T("dialog %i\n"), nID); +#endif + s = t; + + // Read dialog caption + wchar_t* szQuote = NULL; + wchar_t* szEnd = NULL; + + QuoteReadW(&szQuote, &szEnd, s); + + s = szEnd; + + WSKIP_WS(s); + + if (nInside) { + FBALocaliseError(pszFilename, nLine, _T("missing closing bracket"), NULL); + break; + } + if (*s != L'{') { + FBALocaliseError(pszFilename, nLine, _T("missing opening bracket"), NULL); + break; + } + nInside = 1; + + CurrentResource.nID = nID; + + if (wcslen(szQuote)) { + memcpy(CurrentResource.szCaption, szQuote, QUOTE_MAX * sizeof(TCHAR)); + } + + continue; + } + + if ((t = LabelCheckW(s, L"string")) != 0) { + s = t; + + if (nInside) { + FBALocaliseError(pszFilename, nLine, _T("missing closing bracket"), NULL); + break; + } + + WSKIP_WS(s); + + unsigned int nID = wcstol(s, &t, 0); + + s = t; + + // Read dialog caption + WFIND_QT(s); + s++; + wchar_t* szQuote = s; + WFIND_QT(s); + wchar_t* szEnd = s; + + if (nID < nMaxResources) { + +#ifdef PRINT_TRANSLATION_INFO + { + TCHAR szFormat[256]; + _stprintf(szFormat, _T("string %%5i \"%%.%ils\"\n"), szEnd - szQuote); + dprintf(szFormat, nID, szQuote); + } +#endif + + if (szEnd - szQuote > 0) { + UnEscapeString(wszBuffer, szQuote, szEnd - szQuote); + FBAResourceInfo[nID].nResourceFlags = RES_DEALLOCATE; +#ifdef _UNICODE + FBAResourceInfo[nID].pResourceTranslation = malloc((wcslen(wszBuffer) + 1) * sizeof(wchar_t)); + wcscpy((wchar_t*)FBAResourceInfo[nID].pResourceTranslation, wszBuffer); +#else + { + char szStringBuffer[5120]; + memset(szStringBuffer, 0, sizeof(szStringBuffer)); + + WideCharToMultiByte(CP_ACP, 0, wszBuffer, -1, szStringBuffer, 5120, NULL, NULL); + + FBAResourceInfo[nID].pResourceTranslation = malloc((strlen(szStringBuffer) + 1)); + strcpy((char*)FBAResourceInfo[nID].pResourceTranslation, szStringBuffer); + } +#endif + } + } + } + + int n = wcstol(s, &t, 0); + bool bPopup = false; + if (t == s) { + t = LabelCheckW(s, L"popup"); + bPopup = true; + } + if (t && t != s) { // New control + + if (nInside == 0) { + FBALocaliseError(pszFilename, nLine, _T("rogue control statement"), szLine); + break; + } + + s = t; + n = wcstol(s, &t, 0); + + // Link a new control info structure + if (n < 256) { + s = t; + + // Read option name + wchar_t* szQuote = NULL; + wchar_t* szEnd = NULL; + if (QuoteReadW(&szQuote, &szEnd, s)) { + FBALocaliseError(pszFilename, nLine, _T("control name omitted"), szLine); + break; + } + s = szEnd; + + if (bPopup) { + WSKIP_WS(s); + + if (*s != L'{') { + FBALocaliseError(pszFilename, nLine, _T("missing opening bracket"), NULL); + break; + } + nInside++; + } + + if (wcslen(szQuote)) { + if (CurrentResource.pControlInfo[n] == NULL) { + CurrentResource.pControlInfo[n] = (LocaliseControlInfo*)malloc(sizeof(LocaliseControlInfo)); + } + memset(CurrentResource.pControlInfo[n], 0, sizeof(LocaliseControlInfo)); + memcpy(CurrentResource.pControlInfo[n]->szCaption, szQuote, QUOTE_MAX * sizeof(TCHAR)); + } + +// dprintf(_T(" - %ls\n"), pCurrentResource->pControlInfo[n]->szCaption); + + } + + continue; + } + + WSKIP_WS(s); + if (*s == L'}') { + if (nInside == 0) { + FBALocaliseError(pszFilename, nLine, _T("rogue closing bracket"), NULL); + break; + } + + nInside--; + + if (nInside == 0) { + + if (CurrentResource.nID < nMaxResources) { + if (nResourceType == RT_MENU) { + MENUTEMPLATE* pTemplate; + + pTemplate = (MENUTEMPLATE*)LoadResource(hAppInst, FindResource(hAppInst, MAKEINTRESOURCE(CurrentResource.nID), RT_MENU)); + if (LockResource((HGLOBAL)pTemplate)) { + if (((MENUITEMTEMPLATEHEADER*)pTemplate)->versionNumber == 0) { + + // Translate the structure + FBAResourceInfo[CurrentResource.nID].pResourceTranslation = TranslateMenuTemplate((MENUTEMPLATE*)pTemplate, &CurrentResource); + FBAResourceInfo[CurrentResource.nID].nResourceFlags = RES_DEALLOCATE; + } + } + } + if (nResourceType == RT_DIALOG) { + LPCDLGTEMPLATE pTemplate; + + pTemplate = (LPCDLGTEMPLATE)LoadResource(hAppInst, FindResource(hAppInst, MAKEINTRESOURCE(CurrentResource.nID), RT_DIALOG)); + if (LockResource((HGLOBAL)pTemplate)) { + if (((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF && ((DLGTEMPLATEEX*)pTemplate)->dlgVer == 1) { + + // Translate the structure + FBAResourceInfo[CurrentResource.nID].pResourceTranslation = TranslateDlgTemplateEx((DLGTEMPLATEEX*)pTemplate, &CurrentResource); + FBAResourceInfo[CurrentResource.nID].nResourceFlags = RES_DEALLOCATE; + } + } + } + } + + for (int i = 0; i < 1024; i++) { + if (CurrentResource.pControlInfo[i]) { + free(CurrentResource.pControlInfo[i]); + CurrentResource.pControlInfo[i] = NULL; + } + } + memset(&CurrentResource, 0, sizeof(LocaliseResourceInfo)); + } + } + + // Line isn't (part of) a valid cheat +#if 0 + if (*s) { + FBALocaliseError(pszFilename, nLine, _T("rogue line"), szLine); + break; + } +#endif + + } + + for (int i = 0; i < 1024; i++) { + if (CurrentResource.pControlInfo[i]) { + free(CurrentResource.pControlInfo[i]); + CurrentResource.pControlInfo[i] = NULL; + } + } + + if (h) { + fclose(h); + } + + if (nTemplateVersion != nBurnVer) { + if (nTemplateVersion == 0) { + return -1; + } + return -2; + } + + return 0; +} + +void FBALocaliseExit() +{ + bLocalisationActive = false; + + if (FBAResourceInfo) { + for (int i = 0; i < 1000; i++) { + if (FBAResourceInfo[i].nResourceFlags & RES_DEALLOCATE) { + if (FBAResourceInfo[i].pResourceTranslation) { + free(FBAResourceInfo[i].pResourceTranslation); + FBAResourceInfo[i].pResourceTranslation = NULL; + } + } + } + + if (FBAResourceInfo) { + free(FBAResourceInfo); + FBAResourceInfo = NULL; + } + } + + return; +} + +int FBALocaliseInit(TCHAR* pszTemplate) +{ + int nRet; + + FBALocaliseExit(); + nFBACodepage = GetACP(); + + if (pszTemplate == NULL || _tcslen(pszTemplate) == 0) { + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" ** Translation disabled\n")); +#endif + + szLocalisationTemplate[0] = _T('\0'); + + return 0; + } + + FBAResourceInfo = (FBAResourceInfo_t*)malloc(1000 * sizeof(FBAResourceInfo_t)); + if (FBAResourceInfo == NULL) { + return 1; + } + + memset(FBAResourceInfo, 0, 1000 * sizeof(FBAResourceInfo_t)); + + nRet = FBALocaliseParseFile(pszTemplate); + if (nRet > 0) { + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" ** Translation initialisation failed\n")); +#endif + + return 1; + } + + if (nRet < 0) { + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" ** Translation disabled\n")); +#endif + + FBALocaliseExit(); + nFBACodepage = GetACP(); + + szLocalisationTemplate[0] = _T('\0'); + + return 0; + } + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" ** Translation initialised\n")); +#endif + + if (pszTemplate) { + _tcsncpy(szLocalisationTemplate, pszTemplate, sizeof(szLocalisationTemplate) / sizeof(TCHAR)); + } + + bLocalisationActive = true; + + return 0; +} + +// ---------------------------------------------------------------------------- +// Dialog box to load/save a template + +static void MakeOfn() +{ + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFilter = _T("FB Alpha localisation templates (*.flt)\0*.flt\0\0"); + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T(".\\config\\localisation"); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("flt"); + + return; +} + +int FBALocaliseLoadTemplate() +{ + _stprintf(szChoice, _T("template")); + MakeOfn(); + ofn.lpstrTitle = _T("Select localisation template"); + ofn.Flags |= OFN_OVERWRITEPROMPT; + + int bOldPause = bRunPause; + bRunPause = 1; + int nRet = GetOpenFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + + return FBALocaliseInit(szChoice); +} + +int FBALocaliseCreateTemplate() +{ + _stprintf(szChoice, _T("template")); + MakeOfn(); + ofn.lpstrTitle = _T("Create localisation template"); + ofn.Flags |= OFN_OVERWRITEPROMPT; + + int bOldPause = bRunPause; + bRunPause = 1; + int nRet = GetSaveFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + + return FBALocaliseWriteTemplate(szChoice); +} diff --git a/src/burner/win32/main.cpp b/src/burner/win32/main.cpp new file mode 100644 index 00000000..20464849 --- /dev/null +++ b/src/burner/win32/main.cpp @@ -0,0 +1,829 @@ +// FB Alpha - Emulator for MC68000/Z80 based arcade games +// Refer to the "license.txt" file for more info + +// Main module + +// #define USE_SDL // define if SDL is used +// #define DONT_DISPLAY_SPLASH // Prevent Splash screen from being displayed +#define APP_DEBUG_LOG // log debug messages to zzBurnDebug.html + +#ifdef USE_SDL + #include "SDL.h" +#endif + +#include "burner.h" + +#ifdef _MSC_VER +// #include + #ifdef _DEBUG + #include + #endif +#endif + +#include "version.h" + +HINSTANCE hAppInst = NULL; // Application Instance +HANDLE hMainThread; +long int nMainThreadID; +int nAppThreadPriority = THREAD_PRIORITY_NORMAL; +int nAppShowCmd; + +static TCHAR szCmdLine[1024] = _T(""); + +HACCEL hAccel = NULL; + +int nAppVirtualFps = 6000; // App fps * 100 + +TCHAR szAppBurnVer[16] = _T(""); +TCHAR szAppExeName[EXE_NAME_SIZE + 1]; + +bool bCmdOptUsed = 0; +bool bAlwaysProcessKeyboardInput = false; + +bool bNoChangeNumLock = 0; +static bool bNumlockStatus; + +bool bMonitorAutoCheck = true; + +// Used for the load/save dialog in commdlg.h (savestates, input replay, wave logging) +TCHAR szChoice[MAX_PATH] = _T(""); +OPENFILENAME ofn; + +#if defined (UNICODE) +char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize) +{ + + static char szStringBuffer[1024]; + memset(szStringBuffer, 0, sizeof(szStringBuffer)); + + char* pszBuffer = pszOutString ? pszOutString : szStringBuffer; + int nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer); + + if (WideCharToMultiByte(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize, NULL, NULL)) { + return pszBuffer; + } + + return NULL; +} + +TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int nOutSize) +{ + static TCHAR szStringBuffer[1024]; + + TCHAR* pszBuffer = pszOutString ? pszOutString : szStringBuffer; + int nBufferSize = pszOutString ? nOutSize * 2 : sizeof(szStringBuffer); + + if (MultiByteToWideChar(CP_ACP, 0, pszInString, -1, pszBuffer, nBufferSize)) { + return pszBuffer; + } + + return NULL; +} +#else +char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int /*nOutSize*/) +{ + if (pszOutString) { + strcpy(pszOutString, pszInString); + return pszOutString; + } + + return (char*)pszInString; +} + +TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int /*nOutSize*/) +{ + if (pszOutString) { + _tcscpy(pszOutString, pszInString); + return pszOutString; + } + + return (TCHAR*)pszInString; +} +#endif + +CHAR *astring_from_utf8(const char *utf8string) +{ + WCHAR *wstring; + int char_count; + CHAR *result; + + // convert MAME string (UTF-8) to UTF-16 + char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0); + wstring = (WCHAR *)malloc(char_count * sizeof(*wstring)); + MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, wstring, char_count); + + // convert UTF-16 to "ANSI code page" string + char_count = WideCharToMultiByte(CP_ACP, 0, wstring, -1, NULL, 0, NULL, NULL); + result = (CHAR *)malloc(char_count * sizeof(*result)); + if (result != NULL) + WideCharToMultiByte(CP_ACP, 0, wstring, -1, result, char_count, NULL, NULL); + + if (wstring) { + free(wstring); + wstring = NULL; + } + return result; +} + +char *utf8_from_astring(const CHAR *astring) +{ + WCHAR *wstring; + int char_count; + CHAR *result; + + // convert "ANSI code page" string to UTF-16 + char_count = MultiByteToWideChar(CP_ACP, 0, astring, -1, NULL, 0); + wstring = (WCHAR *)malloc(char_count * sizeof(*wstring)); + MultiByteToWideChar(CP_ACP, 0, astring, -1, wstring, char_count); + + // convert UTF-16 to MAME string (UTF-8) + char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); + result = (CHAR *)malloc(char_count * sizeof(*result)); + if (result != NULL) + WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); + + if (wstring) { + free(wstring); + wstring = NULL; + } + return result; +} + +WCHAR *wstring_from_utf8(const char *utf8string) +{ + int char_count; + WCHAR *result; + + // convert MAME string (UTF-8) to UTF-16 + char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0); + result = (WCHAR *)malloc(char_count * sizeof(*result)); + if (result != NULL) + MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count); + + return result; +} + +char *utf8_from_wstring(const WCHAR *wstring) +{ + int char_count; + char *result; + + // convert UTF-16 to MAME string (UTF-8) + char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); + result = (char *)malloc(char_count * sizeof(*result)); + if (result != NULL) + WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); + + return result; +} + +#if defined (FBA_DEBUG) + static TCHAR szConsoleBuffer[1024]; + static int nPrevConsoleStatus = -1; + + static HANDLE DebugBuffer; + static FILE *DebugLog = NULL; + static bool bEchoLog = true; // false; +#endif + +#if defined (FBA_DEBUG) +// Debug printf to a file +static int __cdecl AppDebugPrintf(int nStatus, TCHAR* pszFormat, ...) +{ + va_list vaFormat; + + va_start(vaFormat, pszFormat); + + if (DebugLog) { + + if (nStatus != nPrevConsoleStatus) { + switch (nStatus) { + case PRINT_ERROR: + _ftprintf(DebugLog, _T("")); + break; + case PRINT_IMPORTANT: + _ftprintf(DebugLog, _T("")); + break; + default: + _ftprintf(DebugLog, _T("")); + } + } + _vftprintf(DebugLog, pszFormat, vaFormat); + fflush(DebugLog); + } + + if (!DebugLog || bEchoLog) { + _vsntprintf(szConsoleBuffer, 1024, pszFormat, vaFormat); + + if (nStatus != nPrevConsoleStatus) { + switch (nStatus) { + case PRINT_UI: + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_INTENSITY); + break; + case PRINT_IMPORTANT: + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + break; + case PRINT_ERROR: + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + break; + default: + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_GREEN | FOREGROUND_INTENSITY); + } + } + + WriteConsole(DebugBuffer, szConsoleBuffer, _tcslen(szConsoleBuffer), NULL, NULL); + } + + nPrevConsoleStatus = nStatus; + + va_end(vaFormat); + + return 0; +} +#endif + +int dprintf(TCHAR* pszFormat, ...) +{ +#if defined (FBA_DEBUG) + va_list vaFormat; + va_start(vaFormat, pszFormat); + + _vsntprintf(szConsoleBuffer, 1024, pszFormat, vaFormat); + + if (nPrevConsoleStatus != PRINT_UI) { + if (DebugLog) { + _ftprintf(DebugLog, _T("")); + } + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_INTENSITY); + nPrevConsoleStatus = PRINT_UI; + } + + if (DebugLog) { + _ftprintf(DebugLog, szConsoleBuffer); + fflush(DebugLog); + } + WriteConsole(DebugBuffer, szConsoleBuffer, _tcslen(szConsoleBuffer), NULL, NULL); + va_end(vaFormat); +#else + (void)pszFormat; +#endif + + return 0; +} + +void CloseDebugLog() +{ +#if defined (FBA_DEBUG) + if (DebugLog) { + + _ftprintf(DebugLog, _T("")); + + fclose(DebugLog); + DebugLog = NULL; + } + + if (DebugBuffer) { + CloseHandle(DebugBuffer); + DebugBuffer = NULL; + } + + FreeConsole(); +#endif +} + +int OpenDebugLog() +{ +#if defined (FBA_DEBUG) + #if defined (APP_DEBUG_LOG) + + time_t nTime; + tm* tmTime; + + time(&nTime); + tmTime = localtime(&nTime); + + { + // Initialise the debug log file + + #ifdef _UNICODE + DebugLog = _tfopen(_T("zzBurnDebug.html"), _T("wb")); + + if (ftell(DebugLog) == 0) { + WRITE_UNICODE_BOM(DebugLog); + + _ftprintf(DebugLog, _T("")); + _ftprintf(DebugLog, _T("
"));
+		}
+  #else
+		DebugLog = _tfopen(_T("zzBurnDebug.html"), _T("wt"));
+
+		if (ftell(DebugLog) == 0) {
+			_ftprintf(DebugLog, _T(""));
+			_ftprintf(DebugLog, _T("
"), GetACP());
+		}
+  #endif
+
+		_ftprintf(DebugLog, _T(""));
+		_ftprintf(DebugLog, _T("Debug log created by ") _T(APP_TITLE) _T(" v%.20s on %s\n
"), szAppBurnVer, _tasctime(tmTime)); + } + #endif + + { + // Initialise the debug console + + COORD DebugBufferSize = { 80, 1000 }; + + { + + // Since AttachConsole is only present in Windows XP, import it manually + +#if _WIN32_WINNT >= 0x0500 && defined (_MSC_VER) +// #error Manually importing AttachConsole() function, but compiling with _WIN32_WINNT >= 0x0500 + if (!AttachConsole(ATTACH_PARENT_PROCESS)) { + AllocConsole(); + } +#else + #define ATTACH_PARENT_PROCESS ((DWORD)-1) + + BOOL (WINAPI* pAttachConsole)(DWORD dwProcessId) = NULL; + HINSTANCE hKernel32DLL = LoadLibrary(_T("kernel32.dll")); + + if (hKernel32DLL) { + pAttachConsole = (BOOL (WINAPI*)(DWORD))GetProcAddress(hKernel32DLL, "AttachConsole"); + } + if (pAttachConsole) { + if (!pAttachConsole(ATTACH_PARENT_PROCESS)) { + AllocConsole(); + } + } else { + AllocConsole(); + } + if (hKernel32DLL) { + FreeLibrary(hKernel32DLL); + } + + #undef ATTACH_PARENT_PROCESS +#endif + + } + + DebugBuffer = CreateConsoleScreenBuffer(GENERIC_WRITE, FILE_SHARE_READ, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); + SetConsoleScreenBufferSize(DebugBuffer, DebugBufferSize); + SetConsoleActiveScreenBuffer(DebugBuffer); + SetConsoleTitle(_T(APP_TITLE) _T(" Debug console")); + + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + _sntprintf(szConsoleBuffer, 1024, _T("Welcome to the ") _T(APP_TITLE) _T(" debug console.\n")); + WriteConsole(DebugBuffer, szConsoleBuffer, _tcslen(szConsoleBuffer), NULL, NULL); + + SetConsoleTextAttribute(DebugBuffer, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + if (DebugLog) { + _sntprintf(szConsoleBuffer, 1024, _T("Debug messages are logged in zzBurnDebug.html")); + if (!DebugLog || bEchoLog) { + _sntprintf(szConsoleBuffer + _tcslen(szConsoleBuffer), 1024 - _tcslen(szConsoleBuffer), _T(", and echod to this console")); + } + _sntprintf(szConsoleBuffer + _tcslen(szConsoleBuffer), 1024 - _tcslen(szConsoleBuffer), _T(".\n\n")); + } else { + _sntprintf(szConsoleBuffer, 1024, _T("Debug messages are echod to this console.\n\n")); + } + WriteConsole(DebugBuffer, szConsoleBuffer, _tcslen(szConsoleBuffer), NULL, NULL); + } + + nPrevConsoleStatus = -1; + + bprintf = AppDebugPrintf; // Redirect Burn library debug to our function +#endif + + return 0; +} + +void MonitorAutoCheck() +{ + RECT rect; + int x, y; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + x = GetSystemMetrics(SM_CXSCREEN); + y = GetSystemMetrics(SM_CYSCREEN); + + TCHAR szResXY[256] = _T(""); + _stprintf(szResXY, _T("%dx%d"), x, y); + + // Normal CRT (4:3) ( Verified at Wikipedia.Org ) + if( !_tcscmp(szResXY, _T("320x240")) || + !_tcscmp(szResXY, _T("512x384")) || + !_tcscmp(szResXY, _T("640x480")) || + !_tcscmp(szResXY, _T("800x600")) || + !_tcscmp(szResXY, _T("832x624")) || + !_tcscmp(szResXY, _T("1024x768")) || + !_tcscmp(szResXY, _T("1120x832")) || + !_tcscmp(szResXY, _T("1152x864")) || + !_tcscmp(szResXY, _T("1280x960")) || + !_tcscmp(szResXY, _T("1280x1024")) || + !_tcscmp(szResXY, _T("1400x1050")) || + !_tcscmp(szResXY, _T("1600x1200")) || + !_tcscmp(szResXY, _T("2048x1536")) || + !_tcscmp(szResXY, _T("2800x2100")) || + !_tcscmp(szResXY, _T("3200x2400")) || + !_tcscmp(szResXY, _T("4096x3072")) || + !_tcscmp(szResXY, _T("6400x4800")) ){ + nVidScrnAspectX = 4; + nVidScrnAspectY = 3; + } + + // Normal LCD (5:4) ( Verified at Wikipedia.Org ) + if( !_tcscmp(szResXY, _T("320x256")) || + !_tcscmp(szResXY, _T("640x512")) || + !_tcscmp(szResXY, _T("1280x1024")) || + !_tcscmp(szResXY, _T("2560x2048")) || + !_tcscmp(szResXY, _T("5120x4096")) ){ + nVidScrnAspectX = 5; + nVidScrnAspectY = 4; + } + + // CRT Widescreen (16:9) ( Verified at Wikipedia.Org ) + if( !_tcscmp(szResXY, _T("480x270")) || + !_tcscmp(szResXY, _T("1280x720")) || + !_tcscmp(szResXY, _T("1360x768")) || + !_tcscmp(szResXY, _T("1366x768")) || + !_tcscmp(szResXY, _T("1920x1080"))) { + nVidScrnAspectX = 16; + nVidScrnAspectY = 9; + } + + // LCD Widescreen (16:10) ( Verified at Wikipedia.Org ) + if( !_tcscmp(szResXY, _T("320x200")) || + !_tcscmp(szResXY, _T("1280x800")) || + !_tcscmp(szResXY, _T("1440x900")) || + !_tcscmp(szResXY, _T("1680x1050")) || + !_tcscmp(szResXY, _T("1920x1200")) || + !_tcscmp(szResXY, _T("2560x1600")) || + !_tcscmp(szResXY, _T("3840x2400")) || + !_tcscmp(szResXY, _T("5120x3200")) || + !_tcscmp(szResXY, _T("7680x4800")) ){ + nVidScrnAspectX = 16; + nVidScrnAspectY = 10; + } +} + +bool SetNumLock(bool bState) +{ + BYTE keyState[256]; + + if (bNoChangeNumLock) return 0; + + GetKeyboardState(keyState); + if ((bState && !(keyState[VK_NUMLOCK] & 1)) || (!bState && (keyState[VK_NUMLOCK] & 1))) { + keybd_event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY, 0 ); + + keybd_event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + } + + return keyState[VK_NUMLOCK] & 1; +} + +#include + +static int AppInit() +{ +#if defined (_MSC_VER) && defined (_DEBUG) + _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF); // Check for memory corruption + _CrtSetDbgFlag(_CRTDBG_DELAY_FREE_MEM_DF); // + _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF); // +#endif + + OpenDebugLog(); + + // Create a handle to the main thread of execution + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, 0, false, DUPLICATE_SAME_ACCESS); + + // Init the Burn library + BurnLibInit(); + + // Load config for the application + ConfigAppLoad(); + + FBALocaliseInit(szLocalisationTemplate); + + if (bMonitorAutoCheck) MonitorAutoCheck(); + +#if 1 || !defined (FBA_DEBUG) + // print a warning if we're running for the 1st time + if (nIniVersion < nBurnVer) { + ScrnInit(); + //SplashDestroy(1); + FirstUsageCreate(); + + ConfigAppSave(); // Create initial config file + } +#endif + + // Set the thread priority for the main thread + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + + bCheatsAllowed = true; + +#ifdef USE_SDL + SDL_Init(0); +#endif + + ComputeGammaLUT(); + + if (VidSelect(nVidSelect)) { + nVidSelect = 0; + VidSelect(nVidSelect); + } + + hAccel = LoadAccelerators(hAppInst, MAKEINTRESOURCE(IDR_ACCELERATOR)); + + // Build the ROM information + CreateROMInfo(NULL); + + // Write a clrmame dat file if we are verifying roms +#if defined (ROM_VERIFY) + create_datfile(_T("fba.dat"), 0); +#endif + + bNumlockStatus = SetNumLock(false); + + return 0; +} + +static int AppExit() +{ + SetNumLock(bNumlockStatus); + + DrvExit(); // Make sure any game driver is exitted + FreeROMInfo(); + MediaExit(); + BurnLibExit(); // Exit the Burn library + +#ifdef USE_SDL + SDL_Quit(); +#endif + + FBALocaliseExit(); + + if (hAccel) { + DestroyAcceleratorTable(hAccel); + hAccel = NULL; + } + + SplashDestroy(1); + + CloseHandle(hMainThread); + + CloseDebugLog(); + + return 0; +} + +void AppCleanup() +{ + StopReplay(); + WaveLogStop(); + + AppExit(); +} + +int AppMessage(MSG *pMsg) +{ + if (IsDialogMessage(hInpdDlg, pMsg)) return 0; + if (IsDialogMessage(hInpCheatDlg, pMsg)) return 0; + if (IsDialogMessage(hInpDIPSWDlg, pMsg)) return 0; + if (IsDialogMessage(hDbgDlg, pMsg)) return 0; + + if (IsDialogMessage(hInpsDlg, pMsg)) return 0; + if (IsDialogMessage(hInpcDlg, pMsg)) return 0; + + return 1; // Didn't process this message +} + +bool AppProcessKeyboardInput() +{ + if (hwndChat) { + return false; + } + + return true; +} + +int ProcessCmdLine() +{ + unsigned int i; + int nOptX = 0, nOptY = 0, nOptD = 0; + int nOpt1Size; + TCHAR szOpt2[3] = _T(""); + TCHAR szName[MAX_PATH]; + + if (szCmdLine[0] == _T('\"')) { + int nLen = _tcslen(szCmdLine); + nOpt1Size = 1; + while (szCmdLine[nOpt1Size] != _T('\"') && nOpt1Size < nLen) { + nOpt1Size++; + } + if (nOpt1Size == nLen) { + szName[0] = 0; + } else { + nOpt1Size++; + _tcsncpy(szName, szCmdLine + 1, nOpt1Size - 2); + szName[nOpt1Size - 2] = 0; + } + } else { + int nLen = _tcslen(szCmdLine); + nOpt1Size = 0; + while (szCmdLine[nOpt1Size] != _T(' ') && nOpt1Size < nLen) { + nOpt1Size++; + } + _tcsncpy(szName, szCmdLine, nOpt1Size); + szName[nOpt1Size] = 0; + } + + if (_tcslen(szName)) { + if (_tcscmp(szName, _T("-listinfo")) == 0) { + write_datfile(0, stdout); + return 1; + } + + if (_tcscmp(szName, _T("-listinfowithmd")) == 0) { + write_datfile(1, stdout); + return 1; + } + + if (_tcscmp(szName, _T("-listinfomdonly")) == 0) { + write_datfile(2, stdout); + return 1; + } + + if (_tcscmp(szName, _T("-listextrainfo")) == 0) { + int nWidth; + int nHeight; + int nAspectX; + int nAspectY; + for (i = 0; i < nBurnDrvCount; i++) { + nBurnDrvActive = i; + BurnDrvGetVisibleSize(&nWidth, &nHeight); + BurnDrvGetAspect(&nAspectX, &nAspectY); + printf("%s\t%ix%i\t%i:%i\t0x%08X\t\"%s\"\t%i\t%i\t%x\t%x\t\"%s\"\n", BurnDrvGetTextA(DRV_NAME), nWidth, nHeight, nAspectX, nAspectY, BurnDrvGetHardwareCode(), BurnDrvGetTextA(DRV_SYSTEM), BurnDrvIsWorking(), BurnDrvGetMaxPlayers(), BurnDrvGetGenreFlags(), BurnDrvGetFamilyFlags(), BurnDrvGetTextA(DRV_COMMENT)); + } + return 1; + } + } + + _stscanf(&szCmdLine[nOpt1Size], _T("%2s %i x %i x %i"), szOpt2, &nOptX, &nOptY, &nOptD); + + if (_tcslen(szName)) { + bool bFullscreen = 1; + bCmdOptUsed = 1; + + if (_tcscmp(szOpt2, _T("-r")) == 0) { + if (nOptX && nOptY) { + nVidWidth = nOptX; + nVidHeight = nOptY; + } + if (nOptD) { + nVidDepth = nOptD; + } + } else { + if (_tcscmp(szOpt2, _T("-a")) == 0) { + bVidArcaderes = 1; + } else { + if (_tcscmp(szOpt2, _T("-w")) == 0) { + bCmdOptUsed = 0; + bFullscreen = 0; + } + } + } + + if (bFullscreen) { + nVidFullscreen = 1; + } + + if (_tcscmp(&szName[_tcslen(szName) - 3], _T(".fs")) == 0) { + if (BurnStateLoad(szName, 1, &DrvInitCallback)) { + return 1; + } else { +// bRunPause = 1; + } + } else { + if (_tcscmp(&szName[_tcslen(szName) - 3], _T(".fr")) == 0) { + if (StartReplay(szName)) { + return 1; + } + } else { + for (i = 0; i < nBurnDrvCount; i++) { + nBurnDrvActive = i; + if ((_tcscmp(BurnDrvGetText(DRV_NAME), szName) == 0) && (!(BurnDrvGetFlags() & BDF_BOARDROM))){ + MediaInit(); + DrvInit(i, true); + break; + } + } + if (i == nBurnDrvCount) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_NOSUPPORT), szName, _T(APP_TITLE)); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } + } + } + } + + POST_INITIALISE_MESSAGE; + + if (!nVidFullscreen) { + MenuEnableItems(); + } + + return 0; +} + +// Main program entry point +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nShowCmd) +{ + DSCore_Init(); + DICore_Init(); + DDCore_Init(); + Dx9Core_Init(); + + // Try to initiate DWMAPI.DLL on Windows 7 + if(IsWindows7()) { + InitDWMAPI(); + } + + // Provide a custom exception handler + SetUnhandledExceptionFilter(ExceptionFilter); + + hAppInst = hInstance; + + // Make version string + if (nBurnVer & 0xFF) { + // private version (alpha) + _stprintf(szAppBurnVer, _T("%x.%x.%x.%02x"), nBurnVer >> 20, (nBurnVer >> 16) & 0x0F, (nBurnVer >> 8) & 0xFF, nBurnVer & 0xFF); + } else { + // public version + _stprintf(szAppBurnVer, _T("%x.%x.%x"), nBurnVer >> 20, (nBurnVer >> 16) & 0x0F, (nBurnVer >> 8) & 0xFF); + } + +#if !defined (DONT_DISPLAY_SPLASH) + if (lpCmdLine[0] == 0) SplashCreate(); +#endif + + nAppShowCmd = nShowCmd; + + AppDirectory(); // Set current directory to be the applications directory + + // Make sure there are roms and cfg subdirectories + TCHAR szDirs[18][MAX_PATH] = { + {_T("config")}, + {_T("config\\games")}, + {_T("config\\ips")}, + {_T("config\\localisation")}, + {_T("config\\presets")}, + {_T("recordings")}, + {_T("ROMs")}, + {_T("savestates")}, + {_T("screenshots")}, + {_T("support\\")}, + {_T("support\\previews\\")}, + {_T("support\\titles\\")}, + {_T("support\\cheats\\")}, + {_T("support\\hiscores\\")}, + {_T("support\\samples\\")}, + {_T("support\\ips\\")}, + {_T("support\\neocdz\\")}, + {_T("neocdiso\\")}, + }; + + for(int x = 0; x < 18; x++) { + CreateDirectory(szDirs[x], NULL); + } + + // + + { + INITCOMMONCONTROLSEX initCC = { + sizeof(INITCOMMONCONTROLSEX), + ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_LISTVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_TREEVIEW_CLASSES, + }; + InitCommonControlsEx(&initCC); + } + + if (lpCmdLine) { + _tcscpy(szCmdLine, ANSIToTCHAR(lpCmdLine, NULL, 0)); + } + + if (!(AppInit())) { // Init the application + if (!(ProcessCmdLine())) { + MediaInit(); + + RunMessageLoop(); // Run the application message loop + } + } + + ConfigAppSave(); // Save config for the application + + AppExit(); // Exit the application + + return 0; +} diff --git a/src/burner/win32/mdi.cpp b/src/burner/win32/mdi.cpp new file mode 100644 index 00000000..adbb635f --- /dev/null +++ b/src/burner/win32/mdi.cpp @@ -0,0 +1,408 @@ +/* + ================================================================================================ + FB Alpha MDI (Multiple Document Interface) (by CaptainCPS-X / Jezer Andino) + ================================================================================================ + ------------------------------------------------------------------------------------------------ + Notes: + ------------------------------------------------------------------------------------------------ + + At this point MDI basic features are working fine, since there is no need to minimize + the main Video Window (child window), I left it to be maximized always. When switching + to FullScreen mode DirectX will then use hScrnWnd instead of hVideoWindow (for now, + until a fullscreen child window is properly implemented). + + ------------------------------------------------------------------------------------------------ + Technical Notes: + ------------------------------------------------------------------------------------------------ + + Based on Microsoft Developer Network documentation, most of the MDI functions and features + will require a minimum operative system of Windows 2000. Maybe it will work on previous + versions of Windows but that's what is documented on MSDN. + + ------------------------------------------------------------------------------------------------ + TODO: + ------------------------------------------------------------------------------------------------ + + * ... + + ================================================================================================ +*/ + +#include "burner.h" + +const TCHAR szMDIFrameClass[] = _T("MDICLIENT"); // <- (don't change this) +const TCHAR szVidWndClass[] = _T("VidWndClass"); +const TCHAR szVidWndTitle[] = _T("\0"); + +HWND hWndChildFrame = NULL; +HWND hVideoWindow = NULL; + +// Prototypes +LRESULT CALLBACK VideoWndProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +BOOL RegNewMDIChild (); +HWND CreateNewMDIChild (HWND hMDIClient); +void DestroyBurnerMDI (int nAction); +bool GetThemeStatus (); + +// Window message handling stuff +static bool bDrag = false; +static int nOldWindowX, nOldWindowY; +static bool bRDblClick = false; +static float nDownX, nDownY, nMoveX, nMoveY; +HBITMAP hbitmap = NULL; +void StretchBmForClient(HDC, HWND, HBITMAP); + +//static int OnCreate (HWND, LPCREATESTRUCT); +//static void OnSize (HWND, UINT state, int, int); +static void OnMDIActivate (HWND, BOOL, HWND, HWND); +static void OnPaint (HWND); +static int OnMouseMove (HWND, int, int, UINT); +static int OnLButtonDown (HWND, BOOL, int, int, UINT); +static int OnLButtonUp (HWND, int, int, UINT); +static int OnLButtonDblClk (HWND, BOOL, int, int, UINT); +static int OnRButtonUp (HWND, int, int, UINT); +static int OnRButtonDown (HWND, BOOL, int, int, UINT); +static int OnSysCommand (HWND, UINT, int, int); + +int InitBurnerMDI (HWND hParentWnd) +{ + CLIENTCREATESTRUCT ccs; + ccs.hWindowMenu = NULL; + ccs.idFirstChild = ID_MDI_START_CHILD; + UINT nWindowStyle = WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE; + UINT nWindowStyleEx = 0; + + hWndChildFrame = CreateWindowEx( nWindowStyleEx, szMDIFrameClass, NULL, nWindowStyle, 0, 0, 0, 0, hParentWnd, NULL, hAppInst, (LPVOID)&ccs ); + + //if(!hWndChildFrame) MessageBox(hWnd, _T("Could not create MDI client."), _T("Error"), MB_OK | MB_ICONERROR); + + hVideoWindow = nVidFullscreen ? NULL : CreateNewMDIChild(hWndChildFrame); + + return 0; +} + +LRESULT CALLBACK VideoWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch (Msg) + { + //HANDLE_MSG(hWnd, WM_CREATE, OnCreate); + //HANDLE_MSG(hWnd, WM_SIZE, OnSize); + HANDLE_MSG(hWnd, WM_MDIACTIVATE, OnMDIActivate); + HANDLE_MSGB(hWnd, WM_PAINT, OnPaint); + HANDLE_MSG(hWnd, WM_MOUSEMOVE, OnMouseMove); + HANDLE_MSG(hWnd, WM_LBUTTONUP, OnLButtonUp); + HANDLE_MSG(hWnd, WM_LBUTTONDOWN, OnLButtonDown); + HANDLE_MSG(hWnd, WM_LBUTTONDBLCLK, OnLButtonDblClk); + HANDLE_MSG(hWnd, WM_RBUTTONUP, OnRButtonUp); + HANDLE_MSG(hWnd, WM_RBUTTONDBLCLK, OnRButtonDown); + HANDLE_MSG(hWnd, WM_RBUTTONDOWN, OnRButtonDown); + + // We can't use the macro from windowsx.h macro for this one + case WM_SYSCOMMAND: + { + if (OnSysCommand(hWnd,(UINT)wParam,(int)(short)LOWORD(lParam),(int)(short)HIWORD(lParam))) { + return 0; + } + break; + } + + default: + return DefMDIChildProc(hWnd, Msg, wParam, lParam); + } + return 0; +} + +BOOL RegNewMDIChild() +{ + if(nVidFullscreen) { + return FALSE; + } + + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS; // handle double click + wcex.lpfnWndProc = VideoWndProc; // video window process callback + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hAppInst; // fba instance handle + wcex.hIcon = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP)); // fba icon + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // regular cursor + wcex.hbrBackground = CreateSolidBrush(0); // black video window background + wcex.lpszMenuName = NULL; // no menu + wcex.lpszClassName = szVidWndClass; // video window class (MDI child) + wcex.hIconSm = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP)); + + if(!RegisterClassEx(&wcex)) + { + //MessageBox(NULL, _T("There was a problem registering the window class"), _T("Error"), MB_OK); + return FALSE; + } else { + return TRUE; + } +} + +HWND CreateNewMDIChild(HWND hMDIClient) +{ + HWND hNewWnd = NULL; + hNewWnd = CreateMDIWindow(szVidWndClass, szVidWndTitle, MDIS_ALLCHILDSTYLES | CS_DBLCLKS | WS_DLGFRAME | WS_MAXIMIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMDIClient, hAppInst, 0); + //if(!hNewWnd) MessageBox(NULL, _T("Error creating child window"), _T("Creation Error"), MB_OK); + return hNewWnd; +} + +void DestroyBurnerMDI(int nAction) +{ + switch(nAction) + { + // OnDestroy + case 0: + { + hVideoWindow = NULL; + hWndChildFrame = NULL; + break; + } + + // ScrnExit() + case 1: + { + if(hVideoWindow) + { + SendMessage(hWndChildFrame, WM_MDIDESTROY, (INT_PTR) hVideoWindow, 0L); + hVideoWindow = NULL; + } + if(hWndChildFrame) + { + DestroyWindow(hWndChildFrame); + hWndChildFrame = NULL; + } + UnregisterClass(szVidWndClass, hAppInst); + break; + } + } + DeleteObject(hbitmap); +} + +// Check if Windows has a Theme active (Windows XP+) +bool GetThemeStatus() +{ + bool bThemeActive = false; + + typedef BOOL WINAPI ISTHEMEACTIVE(); + ISTHEMEACTIVE* pISTHEMEACTIVE = NULL; + + HMODULE hMod = LoadLibrary(_T("uxtheme.dll")); + + if(hMod) { + pISTHEMEACTIVE = reinterpret_cast(GetProcAddress(hMod,"IsThemeActive")); + if(pISTHEMEACTIVE) { + bThemeActive = pISTHEMEACTIVE(); + } + FreeLibrary(hMod); + } + + return bThemeActive; +} + +//static int OnCreate(HWND, LPCREATESTRUCT) +//{ +// // ... +// return 1; +//} + +//static void OnSize(HWND hwnd, UINT /*state*/, int /*cx*/, int /*cy*/) +//{ +// // ... +//} + +static void OnMDIActivate(HWND /*hwnd*/, BOOL /*fActive*/, HWND /*hwndActivate*/, HWND /*hwndDeactivate*/) +{ + // ... + return; +} + +// Needed for the non-preview mode +void StretchBmForClient(HDC hDC, HWND hWnd, HBITMAP hBitmap) +{ + HDC memDC; BITMAP bm; RECT re; + + memDC = CreateCompatibleDC(hDC); + HGDIOBJ hOldObj = SelectObject(memDC, hBitmap); + + GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm); + GetClientRect(hWnd, &re); + + StretchBlt(hDC, 0, 0, re.right, re.bottom, memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + + SelectObject(memDC, hOldObj); + DeleteDC(memDC); +} + +static void OnPaint(HWND hwnd) +{ + if(!nVidFullscreen) + { + // This was formerly an alternative for the fail in using the "Preview blitter" + // option in Win9x plattaforms, now, this is used just to complement the option + // if you don't like the preview enabled. + if (!bDrvOkay) { + PAINTSTRUCT ps; + + //hbitmap = (HBITMAP)LoadImage(hAppInst, _T("BMP_SPLASH"), IMAGE_BITMAP, 304, 224, 0); + hbitmap = (HBITMAP)LoadImage(hAppInst, MAKEINTRESOURCE(BMP_SPLASH), IMAGE_BITMAP, 304, 224, 0); + + HDC hDC = BeginPaint(hwnd, &ps); + StretchBmForClient(hDC, hwnd, hbitmap); + + return; + } + + PAINTSTRUCT ps; + HDC hdc = NULL; + hdc = BeginPaint (hwnd, &ps); + EndPaint (hwnd, &ps); + + VidPaint(1); + } +} + +// MOUSE MOVE (DRAG) +static int OnMouseMove(HWND /*hwnd*/, int /*x*/, int /*y*/, UINT keyIndicators) +{ + if(bDrag && keyIndicators == MK_LBUTTON && !nVidFullscreen && !bMenuEnabled) + { + AudSoundStop(); + + // If UxThemes are active (Windows XP+) or DWM Composition is active + if(GetThemeStatus() || IsCompositeOn()) { + // Redraw everything on the MDI frame to get accurate calculatations + RedrawWindow(hWndChildFrame, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + } + + POINT pointer; + memset(&pointer, 0, sizeof(POINT)); + + GetCursorPos(&pointer); + + nMoveX = pointer.x; + nMoveY = pointer.y; + + // negative (left / up) [-] + if((nMoveX < nDownX && nMoveX != 0) || (nMoveY < nDownY && nMoveY != 0)) { + nWindowPosX = nOldWindowX - (int)(nDownX - nMoveX); + nWindowPosY = nOldWindowY - (int)(nDownY - nMoveY); + SetWindowPos(hScrnWnd, NULL, nWindowPosX, nWindowPosY, 0, 0, SWP_NOREPOSITION | SWP_NOSIZE); + } + + // positive (right / down) [+] + if((nMoveX > nDownX && nMoveX != 0) || (nMoveY > nDownY && nMoveY != 0)) { + nWindowPosX = nOldWindowX + (int)(nMoveX - nDownX); + nWindowPosY = nOldWindowY + (int)(nMoveY - nDownY); + SetWindowPos(hScrnWnd, NULL, nWindowPosX, nWindowPosY, 0, 0, SWP_NOREPOSITION | SWP_NOSIZE); + } + + AudSoundPlay(); + return 0; + } + return 1; +} + +// MOUSE LEFT BUTTON (DOWN) +static int OnLButtonDown(HWND /*hwnd*/, BOOL bDouble, int /*x*/, int /*y*/, UINT) +{ + if (!bDrag && !nVidFullscreen && !bMenuEnabled && !bDouble) + { + POINT pointer; + memset(&pointer, 0, sizeof(POINT)); + + GetCursorPos(&pointer); + + nDownX = pointer.x; + nDownY = pointer.y; + + RECT cr; + GetWindowRect(hScrnWnd, &cr); + + nOldWindowX = cr.left; + nOldWindowY = cr.top; + + bDrag = true; + + return 0; + } + return 1; +} + +// MOUSE LEFT BUTTON (UP) +static int OnLButtonUp(HWND /*hwnd*/, int /*x*/, int /*y*/, UINT) +{ + RECT cr; + GetWindowRect(hScrnWnd, &cr); + + if(bDrag && !nVidFullscreen && !bMenuEnabled) + { + if((nDownX != nMoveX || nDownY != nMoveY) && (nMoveX != 0 && nMoveY != 0)) { + // window moved - NO MENU + } else { + // window was not moved - SHOW MENU + TrackPopupMenuEx(hMenuPopup, TPM_LEFTALIGN | TPM_TOPALIGN, (int)nDownX, (int)nDownY, hScrnWnd, NULL); + } + + bDrag = false; + nDownX = nDownY = nMoveX = nMoveY = 0; + + return 0; + } + return 1; +} + +// MOUSE LEFT BUTTON (DOUBLE CLICK) +static int OnLButtonDblClk(HWND /*hwnd*/, BOOL, int, int, UINT) +{ + if (bDrvOkay) + { + nVidFullscreen = !nVidFullscreen; + POST_INITIALISE_MESSAGE; + return 0; + } + return 1; +} + +// MOUSE RIGHT BUTTON (DOWN) +static int OnRButtonDown(HWND hwnd, BOOL /*bDouble*/, int, int, UINT) +{ + return (hwnd == hVideoWindow && !nVidFullscreen) ? 0 : 1; +} + +// MOUSE RIGHT BUTTON (UP) +static int OnRButtonUp(HWND /*hwnd*/, int, int, UINT) +{ + // If not fullscreen and this event is not related to 'toggle fullscreen' right double-click event + if (!nVidFullscreen && !bRDblClick) + { + bMenuEnabled = !bMenuEnabled; + POST_INITIALISE_MESSAGE; + return 0; + } + return 1; +} + +// Block screensaver and windows menu if needed +static int OnSysCommand(HWND, UINT sysCommand, int, int) +{ + switch (sysCommand) { + case SC_MONITORPOWER: + case SC_SCREENSAVE: { + if (!bRunPause && bDrvOkay) { + return 1; + } + break; + } + case SC_KEYMENU: + case SC_MOUSEMENU: { + if (kNetGame && !bModelessMenu) { + return 1; + } + break; + } + } + return 0; +} diff --git a/src/burner/win32/media.cpp b/src/burner/win32/media.cpp new file mode 100644 index 00000000..ae1a70ee --- /dev/null +++ b/src/burner/win32/media.cpp @@ -0,0 +1,77 @@ +// Media module +#include "burner.h" + +int MediaInit() +{ + if (ScrnInit()) { // Init the Scrn Window + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_WINDOW)); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } + + if (!bInputOkay) { + InputInit(); // Init Input + } + + nAppVirtualFps = nBurnFPS; + + if (!bAudOkay) { + AudSoundInit(); // Init Sound (not critical if it fails) + } + + nBurnSoundRate = 0; // Assume no sound + pBurnSoundOut = NULL; + if (bAudOkay) { + nBurnSoundRate = nAudSampleRate[nAudSelect]; + nBurnSoundLen = nAudSegLen; + } + + if (!bVidOkay) { + + // Reinit the video plugin + VidInit(); + if (!bVidOkay && nVidFullscreen) { + + nVidFullscreen = 0; + + MediaExit(); + return (MediaInit()); + } + if (!nVidFullscreen) { + ScrnSize(); + } + + if (!bVidOkay) { + // Make sure the error will be visible + SplashDestroy(1); + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_MODULE), VidGetModuleName()); + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + if (bVidOkay && ((bRunPause && bAltPause) || !bDrvOkay)) { + VidRedraw(); + } + } + + return 0; +} + +int MediaExit() +{ + nBurnSoundRate = 0; // Blank sound + pBurnSoundOut = NULL; + + AudSoundExit(); // Exit Dsound + + VidExit(); + + InputExit(); + + DestroyWindow(hInpsDlg); // Make sure the Input Set dialog is exitted + DestroyWindow(hInpdDlg); // Make sure the Input Dialog is exitted + + ScrnExit(); // Exit the Scrn Window + + return 0; +} diff --git a/src/burner/win32/memcard.cpp b/src/burner/win32/memcard.cpp new file mode 100644 index 00000000..c3ef1351 --- /dev/null +++ b/src/burner/win32/memcard.cpp @@ -0,0 +1,309 @@ +// Memory card support module + +#include "burner.h" + +static TCHAR szMemoryCardFile[MAX_PATH]; + +int nMemoryCardStatus = 0; +int nMemoryCardSize; + +static int nMinVersion; +static bool bMemCardFC1Format; + +static int MakeOfn() +{ + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFile = szMemoryCardFile; + ofn.nMaxFile = sizeof(szMemoryCardFile); + ofn.lpstrInitialDir = _T("."); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("fc"); + + return 0; +} + +static int MemCardRead(TCHAR* szFilename, unsigned char* pData, int nSize) +{ + const char* szHeader = "FB1 FC1 "; // File + chunk identifier + char szReadHeader[8] = ""; + + bMemCardFC1Format = false; + + FILE* fp = _tfopen(szFilename, _T("rb")); + if (fp == NULL) { + return 1; + } + + fread(szReadHeader, 1, 8, fp); // Read identifiers + if (memcmp(szReadHeader, szHeader, 8) == 0) { + + // FB Alpha memory card file + + int nChunkSize = 0; + int nVersion = 0; + + bMemCardFC1Format = true; + + fread(&nChunkSize, 1, 4, fp); // Read chunk size + if (nSize < nChunkSize - 32) { + fclose(fp); + return 1; + } + + fread(&nVersion, 1, 4, fp); // Read version + if (nVersion < nMinVersion) { + fclose(fp); + return 1; + } + fread(&nVersion, 1, 4, fp); +#if 0 + if (nVersion < nBurnVer) { + fclose(fp); + return 1; + } +#endif + + fseek(fp, 0x0C, SEEK_CUR); // Move file pointer to the start of the data block + + fread(pData, 1, nChunkSize - 32, fp); // Read the data + } else { + + // MAME or old FB Alpha memory card file + + unsigned char* pTemp = (unsigned char*)malloc(nSize >> 1); + + memset(pData, 0, nSize); + fseek(fp, 0x00, SEEK_SET); + + if (pTemp) { + fread(pTemp, 1, nSize >> 1, fp); + + for (int i = 1; i < nSize; i += 2) { + pData[i] = pTemp[i >> 1]; + } + + free(pTemp); + pTemp = NULL; + } + } + + fclose(fp); + + return 0; +} + +static int MemCardWrite(TCHAR* szFilename, unsigned char* pData, int nSize) +{ + FILE* fp = _tfopen(szFilename, _T("wb")); + if (fp == NULL) { + return 1; + } + + if (bMemCardFC1Format) { + + // FB Alpha memory card file + + const char* szFileHeader = "FB1 "; // File identifier + const char* szChunkHeader = "FC1 "; // Chunk identifier + const int nZero = 0; + + int nChunkSize = nSize + 32; + + fwrite(szFileHeader, 1, 4, fp); + fwrite(szChunkHeader, 1, 4, fp); + + fwrite(&nChunkSize, 1, 4, fp); // Chunk size + + fwrite(&nBurnVer, 1, 4, fp); // Version of FBA this was saved from + fwrite(&nMinVersion, 1, 4, fp); // Min version of FBA data will work with + + fwrite(&nZero, 1, 4, fp); // Reserved + fwrite(&nZero, 1, 4, fp); // + fwrite(&nZero, 1, 4, fp); // + + fwrite(pData, 1, nSize, fp); + } else { + + // MAME or old FB Alpha memory card file + + unsigned char* pTemp = (unsigned char*)malloc(nSize >> 1); + if (pTemp) { + for (int i = 1; i < nSize; i += 2) { + pTemp[i >> 1] = pData[i]; + } + + fwrite(pTemp, 1, nSize >> 1, fp); + + free(pTemp); + pTemp = NULL; + } + } + + fclose(fp); + + return 0; +} + +static int __cdecl MemCardDoGetSize(struct BurnArea* pba) +{ + nMemoryCardSize = pba->nLen; + + return 0; +} + +static int MemCardGetSize() +{ + BurnAcb = MemCardDoGetSize; + BurnAreaScan(ACB_MEMCARD, &nMinVersion); + + return 0; +} + +int MemCardCreate() +{ + TCHAR szFilter[1024]; + int nRet; + + _stprintf(szFilter, FBALoadStringEx(hAppInst, IDS_DISK_FILE_CARD, true), _T(APP_TITLE)); + memcpy(szFilter + _tcslen(szFilter), _T(" (*.fc)\0*.fc\0\0"), 14 * sizeof(TCHAR)); + + _stprintf (szMemoryCardFile, _T("memorycard")); + MakeOfn(); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_MEMCARD_CREATE, true); + ofn.lpstrFilter = szFilter; + ofn.Flags |= OFN_OVERWRITEPROMPT; + + int bOldPause = bRunPause; + bRunPause = 1; + nRet = GetSaveFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + + { + unsigned char* pCard; + + MemCardGetSize(); + + pCard = (unsigned char*)malloc(nMemoryCardSize); + memset(pCard, 0, nMemoryCardSize); + + bMemCardFC1Format = true; + + if (MemCardWrite(szMemoryCardFile, pCard, nMemoryCardSize)) { + return 1; + } + + if (pCard) { + free(pCard); + pCard = NULL; + } + } + + nMemoryCardStatus = 1; + MenuEnableItems(); + + return 0; +} + +int MemCardSelect() +{ + TCHAR szFilter[1024]; + TCHAR* pszTemp = szFilter; + int nRet; + + pszTemp += _stprintf(pszTemp, FBALoadStringEx(hAppInst, IDS_DISK_ALL_CARD, true)); + memcpy(pszTemp, _T(" (*.fc, MEMCARD.\?\?\?)\0*.fc;MEMCARD.\?\?\?\0"), 38 * sizeof(TCHAR)); + pszTemp += 38; + pszTemp += _stprintf(pszTemp, FBALoadStringEx(hAppInst, IDS_DISK_FILE_CARD, true), _T(APP_TITLE)); + memcpy(pszTemp, _T(" (*.fc)\0*.fc\0"), 13 * sizeof(TCHAR)); + pszTemp += 13; + pszTemp += _stprintf(pszTemp, FBALoadStringEx(hAppInst, IDS_DISK_FILE_CARD, true), _T("MAME")); + memcpy(pszTemp, _T(" (MEMCARD.\?\?\?)\0MEMCARD.\?\?\?\0\0"), 28 * sizeof(TCHAR)); + + MakeOfn(); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_MEMCARD_SELECT, true); + ofn.lpstrFilter = szFilter; + + int bOldPause = bRunPause; + bRunPause = 1; + nRet = GetOpenFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + + MemCardGetSize(); + + if (nMemoryCardSize <= 0) { + return 1; + } + + nMemoryCardStatus = 1; + MenuEnableItems(); + + return 0; +} + +static int __cdecl MemCardDoInsert(struct BurnArea* pba) +{ + if (MemCardRead(szMemoryCardFile, (unsigned char*)pba->Data, pba->nLen)) { + return 1; + } + + nMemoryCardStatus |= 2; + MenuEnableItems(); + + return 0; +} + +int MemCardInsert() +{ + if ((nMemoryCardStatus & 1) && (nMemoryCardStatus & 2) == 0) { + BurnAcb = MemCardDoInsert; + BurnAreaScan(ACB_WRITE | ACB_MEMCARD, &nMinVersion); + } + + return 0; +} + +static int __cdecl MemCardDoEject(struct BurnArea* pba) +{ + if (MemCardWrite(szMemoryCardFile, (unsigned char*)pba->Data, pba->nLen) == 0) { + nMemoryCardStatus &= ~2; + MenuEnableItems(); + + return 0; + } + + return 1; +} + +int MemCardEject() +{ + if ((nMemoryCardStatus & 1) && (nMemoryCardStatus & 2)) { + BurnAcb = MemCardDoEject; + nMinVersion = 0; + BurnAreaScan(ACB_READ | ACB_MEMCARD, &nMinVersion); + } + + return 0; +} + +int MemCardToggle() +{ + if (nMemoryCardStatus & 1) { + if (nMemoryCardStatus & 2) { + return MemCardEject(); + } else { + return MemCardInsert(); + } + } + + return 1; +} diff --git a/src/burner/win32/menu.cpp b/src/burner/win32/menu.cpp new file mode 100644 index 00000000..70883375 --- /dev/null +++ b/src/burner/win32/menu.cpp @@ -0,0 +1,1341 @@ +// Menu handling + +#include "burner.h" + +#ifdef _MSC_VER +// #include +#endif + +int nOtherRes = 0; + +HMENU hMenu = NULL; +HMENU hMenuPopup = NULL; +HWND hMenubar = NULL; // Handle to the Toolbar control comprising the menu +static HMENU hBlitterMenu[8] = {NULL, }; // Handles to the blitter-specific sub-menus +static HMENU hAudioPluginMenu[8] = {NULL, }; + +bool bMenuDisplayed = false; +bool bModelessMenu = false; +int nLastMenu = 0; +static int nRecursions = -1; +static HMENU hCurrentMenu; +static int nCurrentItem; +static int nCurrentItemFlags; + +int nMenuHeight = 0; +int nWindowSize = 0; +int nScreenSize = 0; +int nScreenSizeHor = 0; +int nScreenSizeVer = 0; + +TCHAR szPrevGames[SHOW_PREV_GAMES][32]; + +static HHOOK hMenuHook; + +static LRESULT CALLBACK MenuHook(int nCode, WPARAM wParam, LPARAM lParam) +{ + + switch (((MSG*)lParam)->message) { + + case WM_MOUSEMOVE: { // Translate coordinates to menubar client coordinates + RECT rect; + POINT point = {GET_X_LPARAM(((MSG*)lParam)->lParam), GET_Y_LPARAM(((MSG*)lParam)->lParam)}; + + GetWindowRect(hMenubar, &rect); + + if (point.x >= rect.left && point.y >= rect.top && point.x < rect.right && point.y < rect.bottom) { + RECT buttonrect; + SendMessage(hMenubar, TB_GETITEMRECT, nLastMenu, (LPARAM)&buttonrect); + + if (!(point.x >= rect.left + buttonrect.left && point.y >= rect.top + buttonrect.top && point.x < rect.left + buttonrect.right && point.y < rect.top + buttonrect.bottom)) { + SendNotifyMessage(hMenubar, WM_MOUSEMOVE, wParam, MAKELONG(point.x - rect.left, point.y - rect.top)); + } + } + break; + } + + case WM_LBUTTONDOWN: { + RECT rect; + RECT buttonrect; + POINT point = {GET_X_LPARAM(((MSG*)lParam)->lParam), GET_Y_LPARAM(((MSG*)lParam)->lParam)}; + + GetWindowRect(hMenubar, &rect); + SendMessage(hMenubar, TB_GETITEMRECT, nLastMenu, (LPARAM)&buttonrect); + + // If the button is pressed over the currently selected menu title, eat the message and close the menu + if (point.x >= rect.left + buttonrect.left && point.y >= rect.top + buttonrect.top && point.x < rect.left + buttonrect.right && point.y < rect.top + buttonrect.bottom) { + PostMessage(hMenubar, WM_CANCELMODE, 0, 0); + return 1; + } + break; + } + + } + + MenuHandleKeyboard((MSG*)lParam); + + return CallNextHookEx(hMenuHook, nCode, wParam, lParam); +} + +void DisplayPopupMenu(int nMenu) +{ + if (bMenuDisplayed) { + EndMenu(); + if (nLastMenu != nMenu) { + PostMessage(hScrnWnd, UM_DISPLAYPOPUP, nMenu, 0); + } + } else { + HMENU hPopupMenu = GetSubMenu(hMenu, nMenu); + RECT clientRect; + RECT buttonRect; + + nLastMenu = nMenu; + nRecursions = 0; + nCurrentItemFlags = 0; + + GetWindowRect(hMenubar, &clientRect); + SendMessage(hMenubar, TB_GETITEMRECT, nMenu, (LPARAM)&buttonRect); + + if (!bModelessMenu) { + hMenuHook = SetWindowsHookEx(WH_MSGFILTER, MenuHook, NULL, GetCurrentThreadId()); + } + TrackPopupMenuEx(hPopupMenu, TPM_LEFTALIGN | TPM_TOPALIGN, clientRect.left + buttonRect.left, clientRect.top + buttonRect.bottom, hScrnWnd, NULL); + if (!bModelessMenu) { + UnhookWindowsHookEx(hMenuHook); + } + } +} + +int OnNotify(HWND, int, NMHDR* lpnmhdr) // HWND hwnd, int id, NMHDR* lpnmhdr +{ + switch (((TBNOTIFY*)lpnmhdr)->hdr.code) { + + case TBN_DROPDOWN: { + if (!bMenuDisplayed || ((TBNOTIFY*)lpnmhdr)->iItem - MENU_MENU_0 != nLastMenu) { + DisplayPopupMenu(((TBNOTIFY*)lpnmhdr)->iItem - MENU_MENU_0); + nLastMenu = ((TBNOTIFY*)lpnmhdr)->iItem - MENU_MENU_0; + } + return TBDDRET_DEFAULT; + } + + case TBN_HOTITEMCHANGE: { + int nItem = ((NMTBHOTITEM*)lpnmhdr)->idNew; + + // If a menu is being displayed, close it and display the new one + if (bMenuDisplayed) { + if (nItem) { + if (nItem - MENU_MENU_0 != nLastMenu) { + DisplayPopupMenu(nItem - MENU_MENU_0); + return 1; + } + } + } else { + nLastMenu = nItem - MENU_MENU_0; + if (!nItem && !bAltPause) { + GameInpCheckMouse(); + } + return 0; + } + } + } + return 0; +} + +int OnMenuSelect(HWND, HMENU, int nItem, HMENU, UINT nFlags) +{ +// printf("WM_MENUSELECT: %4i, %08x\n", nItem, nFlags); + nCurrentItem = nItem; + nCurrentItemFlags = nFlags; + return 0; +} + +int OnInitMenuPopup(HWND, HMENU hNewMenuPopup, UINT, BOOL bWindowsMenu) +{ + if (!bWindowsMenu) { + if (!nRecursions) { + bMenuDisplayed = true; + SendMessage(hMenubar, TB_PRESSBUTTON, nLastMenu + MENU_MENU_0, MAKELONG(1, 0)); + hCurrentMenu = hNewMenuPopup; + } + nRecursions++; + } + return 0; +} + +int OnUnInitMenuPopup(HWND, HMENU, UINT, BOOL) +{ + if (nRecursions <= 1) { + bMenuDisplayed = false; + SendMessage(hMenubar, TB_PRESSBUTTON, nLastMenu + MENU_MENU_0, MAKELONG(0, 0)); + if(!bAltPause) { + if (bRunPause) { + bRunPause = 0; + } + GameInpCheckMouse(); + } + } + nRecursions--; + + return 0; +} + +bool MenuHandleKeyboard(MSG* Msg) +{ + static bool bProcessAltKeyUp = true; + + if (!bMenuEnabled) { + return 0; + } + + if (Msg->message == WM_KEYDOWN) { + switch (Msg->wParam) { + case VK_ESCAPE: { + if (bMenuDisplayed) { + if (nRecursions > 1) { + break; + } else { + EndMenu(); + SendMessage(hMenubar, TB_SETHOTITEM, nLastMenu, 0); + return 1; + } + } else { + if (SendMessage(hMenubar, TB_GETHOTITEM, 0, 0) != -1) { + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)-1, 0); + if (!bAltPause) { + GameInpCheckMouse(); + } + return 1; + } + } + break; + } + case VK_LEFT: { + int nItem; + if (bMenuDisplayed) { + if (nRecursions > 1) { + break; + } else { + nItem = nLastMenu; + } + } else { + nItem = SendMessage(hMenubar, TB_GETHOTITEM, 0, 0); + } + if (nItem != -1) { + if (nItem) { + nItem -= 1; + } else { + nItem = 5; + } + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)nItem, 0); + return 1; + } + break; + } + case VK_RIGHT: { + int nItem; + if (bMenuDisplayed) { + if (nCurrentItemFlags & MF_POPUP) { + break; + } else { + nItem = nLastMenu; + } + } else { + nItem = SendMessage(hMenubar, TB_GETHOTITEM, 0, 0); + } + if (nItem != -1) { + if (nItem != 5) { + nItem += 1; + } else { + nItem = 0; + } + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)nItem, 0); + return 1; + } + break; + } + case VK_UP: { + if (!bMenuDisplayed) { + int nItem = SendMessage(hMenubar, TB_GETHOTITEM, 0, 0); + if (nItem == -1) { + break; + } else { + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)-1, 0); + DisplayPopupMenu(nItem); + return 1; + } + } + break; + } + case VK_DOWN: { + if (!bMenuDisplayed) { + int nItem = SendMessage(hMenubar, TB_GETHOTITEM, 0, 0); + if (nItem == -1) { + break; + } else { + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)-1, 0); + DisplayPopupMenu(nItem); + return 1; + } + } + break; + } + } + } else { + if (!bLeftAltkeyMapped || bRunPause || !bDrvOkay) { + if (Msg->message == WM_SYSKEYDOWN && Msg->wParam == VK_MENU) { + if (bMenuDisplayed) { + bProcessAltKeyUp = false; + EndMenu(); + if (!bAltPause) { + GameInpCheckMouse(); + } + return 1; + } + } else { + if (Msg->message == WM_SYSKEYUP && Msg->wParam == VK_MENU) { + if (bProcessAltKeyUp) { + int nItem = SendMessage(hMenubar, TB_GETHOTITEM, 0, 0); + if (nItem == -1) { // Menu enabled + SendMessage(hMenubar, TB_SETHOTITEM, 0, 0); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + return 1; + } else { // Menu disabled + SendMessage(hMenubar, TB_SETHOTITEM, (WPARAM)-1, 0); + if (!bAltPause) { + GameInpCheckMouse(); + } + return 1; + } + } + } else { + if (Msg->message == UM_DISPLAYPOPUP) { + DisplayPopupMenu(Msg->wParam); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + return 1; + } + } + } + } + } + + bProcessAltKeyUp = true; + + return 0; +} + +int MenuCreate() +{ + TBBUTTON button; + TCHAR szButtonText[32]; + MENUITEMINFO menuItemInfo; + MENUINFO menu; + + if (hMenu == NULL) { + hMenu = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU)); // Main application menu + hBlitterMenu[0] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_BLITTER_1)); // DirectDraw Standard blitter + hBlitterMenu[1] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_BLITTER_2)); // Direct3D + hBlitterMenu[2] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_BLITTER_3)); // Software effects blitter + hBlitterMenu[3] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_BLITTER_4)); // DirectX 9 + hBlitterMenu[4] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_BLITTER_5)); // DirectX 9 Alt + + hAudioPluginMenu[0] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_AUD_PLUGIN_1)); + hAudioPluginMenu[1] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_AUD_PLUGIN_2)); + } + + if (hMenuPopup == NULL) { + hMenuPopup = CreatePopupMenu(); + + menuItemInfo.cbSize = sizeof(MENUITEMINFO); + menuItemInfo.fMask = MIIM_TYPE; + menuItemInfo.dwTypeData = szButtonText; + + for (int i = 0; i < 6; i++) { + menuItemInfo.cch = 32; + GetMenuItemInfo(hMenu, i, true, &menuItemInfo); + AppendMenu(hMenuPopup, MF_POPUP | MF_STRING, (UINT_PTR)GetSubMenu(hMenu, i), szButtonText); + } + } + + MenuEnableItems(); + MenuUpdate(); + + bMenuDisplayed = false; + nLastMenu = -1; + + hMenubar = CreateWindowEx(0, + TOOLBARCLASSNAME, NULL, + TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 0, 0, + hScrnWnd, NULL, hAppInst, NULL); + + SendMessage(hMenubar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + SendMessage(hMenubar, TB_SETBITMAPSIZE, 0, 0); + + // Reset window menu to default + GetSystemMenu(hScrnWnd, TRUE); + + if (bModelessMenu) { // Make menu modeless + + memset(&menu, 0, sizeof(MENUINFO)); + menu.cbSize = sizeof(MENUINFO); + menu.fMask = MIM_APPLYTOSUBMENUS | MIM_STYLE; + menu.dwStyle = MNS_MODELESS | MNS_CHECKORBMP; + + SetMenuInfo(hMenuPopup, &menu); + + for (int i = 0; i < 6; i++) { + SetMenuInfo(GetSubMenu(hMenu, i), &menu); + } + + memset(&menu, 0, sizeof(MENUINFO)); + menu.cbSize = sizeof(MENUINFO); + menu.fMask = MIM_STYLE | MIM_MAXHEIGHT; + +#if 0 + // Doesn't seem to work + { + HMENU hWindowMenu = GetSystemMenu(hScrnWnd, FALSE); + GetMenuInfo(hWindowMenu, &menu); + menu.dwStyle |= MNS_MODELESS; + SetMenuInfo(hWindowMenu, &menu); + } +#endif + } + + // Add buttons to the menu toolbar + memset(&button, 0, sizeof(TBBUTTON)); + memset(&menuItemInfo, 0, sizeof(MENUITEMINFO)); + + menuItemInfo.cbSize = sizeof(MENUITEMINFO); + menuItemInfo.fMask = MIIM_TYPE; + menuItemInfo.dwTypeData = szButtonText; + + for (int i = 0; i < 6; i++) { + + menuItemInfo.cch = 32; + GetMenuItemInfo(hMenu, i, true, &menuItemInfo); + + button.iBitmap = 0; + button.idCommand = MENU_MENU_0 + i; + button.fsState = TBSTATE_ENABLED; + button.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE; + + button.iString = (INT_PTR)szButtonText; + + SendMessage(hMenubar, TB_ADDBUTTONS, 1, (LPARAM)&button); + } + + SendMessage(hMenubar, TB_AUTOSIZE, 0, 0); + + return 0; +} + +void MenuDestroy() +{ + if (hMenubar) { + DestroyWindow(hMenubar); + hMenubar = NULL; + } + + { + MENUITEMINFO myMenuItemInfo; + myMenuItemInfo.cbSize = sizeof(MENUITEMINFO); + myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE; + myMenuItemInfo.fState = MFS_GRAYED; + myMenuItemInfo.hSubMenu = NULL; + if (hMenu) { + SetMenuItemInfo(GetSubMenu(hMenu, 1), 1, TRUE, &myMenuItemInfo); + } + if (hMenuPopup) { + SetMenuItemInfo(GetSubMenu(hMenuPopup, 1), 1, TRUE, &myMenuItemInfo); + } + + for (int i = 0; i < 5; i++) { + if (hBlitterMenu[i]) { + DestroyMenu(hBlitterMenu[i]); + hBlitterMenu[i] = 0; + } + } + + for (int i = 0; i < 2; i++) { + if (hAudioPluginMenu[i]) { + DestroyMenu(hAudioPluginMenu[i]); + hAudioPluginMenu[i] = 0; + } + } + } + + if(hMenu) { + DestroyMenu(hMenu); + hMenu = NULL; + } + if (hMenuPopup) { + DestroyMenu(hMenuPopup); + hMenuPopup = NULL; + } +} + +// Update the arade resolution menuitem +void CreateArcaderesItem() +{ + int nGameWidth, nGameHeight; + + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0, }; + + // horizontal oriented + FBALoadString(hAppInst, IDS_MENU + 0, szItemText, 256); + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + _stprintf(szItemText + _tcslen(szItemText), _T("\t(%i x %i)"), nGameWidth, nGameHeight); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_RES_ARCADE, 0, &menuItem); + + // vertical oriented + TCHAR szItemText2[256]; + MENUITEMINFO menuItem2 = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText2, 0, 0, }; + + FBALoadString(hAppInst, IDS_MENU + 0, szItemText2, 256); + if (bDrvOkay && BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + _stprintf(szItemText + _tcslen(szItemText2), _T("\t(%i x %i)"), nGameWidth, nGameHeight); + } + menuItem2.cch = _tcslen(szItemText2); + SetMenuItemInfo(hMenu, MENU_RES_ARCADE_VERTICAL, 0, &menuItem2); +} + +// (Horizontal oriented) Update the custom resolution menuitem +static void CreateOtherresItem(bool bOther) +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + FBALoadString(hAppInst, IDS_MENU + 1, szItemText, 256); + if (bOther) { + _stprintf(szItemText + _tcslen(szItemText), _T("\t(%i x %i)"), nVidHorWidth, nVidHorHeight); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_RES_OTHER, 0, &menuItem); +} + +// (Vertical oriented) Update the custom resolution menuitem +static void CreateOtherresItemVer(bool bOther) +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + FBALoadString(hAppInst, IDS_MENU + 1, szItemText, 256); + if (bOther) { + _stprintf(szItemText + _tcslen(szItemText), _T("\t(%i x %i)"), nVidVerWidth, nVidVerHeight); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_RES_OTHER_VERTICAL, 0, &menuItem); +} + +static void CreatepresetResItems() +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + // horizontal oriented + for (int i = 0; i < 4; i++) { + _stprintf(szItemText, _T("%i x %i"), VidPreset[i].nWidth, VidPreset[i].nHeight); + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_RES_1 + i, 0, &menuItem); + } + + // vertical oriented + for (int i = 0; i < 4; i++) { + _stprintf(szItemText, _T("%i x %i"), VidPresetVer[i].nWidth, VidPresetVer[i].nHeight); + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_RES_1_VERTICAL + i, 0, &menuItem); + } + return; +} + +// Update the other gamma menuitem +static void CreateOtherGammaItem(bool bOther) +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + FBALoadString(hAppInst, IDS_MENU + 2, szItemText, 256); + if (bOther) { + _stprintf(szItemText + _tcslen(szItemText), _T("\t(%1.2f)"), nGamma); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_GAMMA_OTHER, 0, &menuItem); +} + +// Update the cpu speed menuitem +static void CreateCPUSpeedItem(bool bOther) +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + FBALoadString(hAppInst, IDS_MENU + 3, szItemText, 256); + if (bOther) { + _stprintf(szItemText + _tcslen(szItemText), _T("\t(%d%%)"), nBurnCPUSpeedAdjust * 100 / 256); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_SETCPUCLOCK, 0, &menuItem); +} + +// Update state slot menuitmes +static void CreateStateslotItems() +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = {sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, 0 }; + + _sntprintf(szItemText, 256, FBALoadStringEx(hAppInst, IDS_MENU + 4, true), nSavestateSlot); + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_STATE_LOAD_SLOT, 0, &menuItem); + + _sntprintf(szItemText, 256, FBALoadStringEx(hAppInst, IDS_MENU + 5, true), nSavestateSlot); + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_STATE_SAVE_SLOT, 0, &menuItem); +} +#if 0 +// Update CD menu items +static void CreateCDItems() +{ + TCHAR szItemText[256]; + MENUITEMINFO menuItem = { sizeof(MENUITEMINFO), MIIM_TYPE, MFT_STRING, 0, 0, NULL, NULL, NULL, 0, szItemText, 0, NULL }; + + _sntprintf(szItemText, 256, FBALoadStringEx(hAppInst, IDS_CD_SELECT_IMAGE, true)); + if (nCDEmuSelect == 0) { + TCHAR szImage[32]; + int length = _tcslen(szItemText); + + _sntprintf(szImage, 13, _T("\t%s"), CDEmuImage); + if (_tcslen(szImage) > 13) { + _sntprintf(szImage + 13, 8, _T("...")); + } + + _sntprintf(szItemText + length - 1, 256 - length, szImage); + } + menuItem.cch = _tcslen(szItemText); + SetMenuItemInfo(hMenu, MENU_CDIMAGE, 0, &menuItem); +} +#endif +// Update bullets, checkmarks, and item text +void MenuUpdate() +{ + int var; + +// if (!bMenuEnabled) { +// return; +// } + + CreateStateslotItems(); + + CheckMenuItem(hMenu, MENU_PAUSE, bAltPause ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_ALLRAM, bDrvSaveAll ? MF_CHECKED : MF_UNCHECKED); + +// CreateCDItems(); +// CheckMenuRadioItem(hMenu, MENU_CDIMAGE, MENU_CDIMAGE, MENU_CDIMAGE + nCDEmuSelect, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_SETCPUCLOCK, nBurnCPUSpeedAdjust != 0x0100 ? MF_CHECKED : MF_UNCHECKED); + CreateCPUSpeedItem(nBurnCPUSpeedAdjust != 0x0100); + + if (bVidFullStretch) { + var = MENU_STRETCH; + } else { + if (bVidCorrectAspect) { + var = MENU_ASPECT; + } else { + var = MENU_NOSTRETCH; + } + } + CheckMenuRadioItem(hMenu, MENU_NOSTRETCH, MENU_ASPECT, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_STRETCH, bVidFullStretch ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(hMenu, MENU_TRIPLE, bVidTripleBuffer ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(hMenu, MENU_DWMFIX, bVidDWMCore ? MF_CHECKED : MF_UNCHECKED); + + var = nVidSelect + MENU_BLITTER_1; + CheckMenuRadioItem(hMenu, MENU_BLITTER_1, MENU_BLITTER_8, var, MF_BYCOMMAND); + + switch (nVidSelect) { + case 0: + if (bVidScanlines) { + if (bVidScanHalf) { + var = MENU_SCAN50; + } else { + var = MENU_SCAN; + } + } else { + var = MENU_NORMAL; + } + CheckMenuRadioItem(hMenu, MENU_NORMAL, MENU_SCAN50, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_ROTSCAN, bVidScanRotate ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_RES_ARCADE, bVidArcaderes ? MF_CHECKED : MF_UNCHECKED); + break; + case 1: + CheckMenuItem(hMenu, MENU_BILINEAR, bVidBilinear ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_SCAN, bVidScanlines ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_PHOSPHOR, bVidScanDelay ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(hMenu, MENU_PRESCALE, nVidBlitterOpt[nVidSelect] & 0x01000000 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_SOFTFX, nVidBlitterOpt[nVidSelect] & 0x02000000 ? MF_CHECKED : MF_UNCHECKED); + + var = ((unsigned long long)nVidBlitterOpt[nVidSelect] >> 32) + MENU_SOFT_STRETCH; + CheckMenuRadioItem(hMenu, MENU_SOFT_STRETCH, MENU_SOFT_STRETCH + 25, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_SOFT_AUTOSIZE, (nVidBlitterOpt[nVidSelect] & 0x04000000) ? MF_CHECKED : MF_UNCHECKED); + if (nVidBlitterOpt[nVidSelect] & 0x00100000) { + var = MENU_3DPROJECTION; + } else { + if (nVidBlitterOpt[nVidSelect] & 0x00010000) { + var = MENU_RGBEFFECTS; + } else { + var = MENU_NORMAL; + } + } + CheckMenuRadioItem(hMenu, MENU_NORMAL, MENU_NORMAL, var, MF_BYCOMMAND); + CheckMenuRadioItem(hMenu, MENU_RGBEFFECTS, MENU_3DPROJECTION, var, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_EFFECT_AUTO, (nVidBlitterOpt[nVidSelect] & 0x00020000) ? MF_CHECKED : MF_UNCHECKED); + var = MENU_EFFECT_01 + (nVidBlitterOpt[nVidSelect] & 0x000000FF) - 8; + CheckMenuRadioItem(hMenu, MENU_EFFECT_01, MENU_EFFECT_08, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_3DUSELIGHTING, nVidBlitterOpt[nVidSelect] & 0x00200000 ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_ROTSCAN, bVidScanRotate ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_FORCE_16BIT, bVidForce16bit ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_TEXTUREMANAGE, (nVidTransferMethod & 1) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_RES_ARCADE, bVidArcaderes ? MF_CHECKED : MF_UNCHECKED); + break; + case 2: + var = (nVidBlitterOpt[nVidSelect] & 0xFF) + MENU_SOFT_STRETCH; + CheckMenuRadioItem(hMenu, MENU_SOFT_STRETCH, MENU_SOFT_STRETCH + 25, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_SOFT_AUTOSIZE, (nVidBlitterOpt[nVidSelect] & 0x0100) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_SOFT_DIRECTACCESS, !(nVidBlitterOpt[nVidSelect] & 0x0200) ? MF_CHECKED : MF_UNCHECKED); + break; + case 3: + var = ((nVidBlitterOpt[nVidSelect] >> 24) & 0x03) + MENU_DX9_POINT; + CheckMenuRadioItem(hMenu, MENU_DX9_POINT, MENU_DX9_POINT + 2, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_SCAN, bVidScanlines ? MF_CHECKED : MF_UNCHECKED); + + var = MENU_DX9_CUBIC_CUSTOM; + if (dVidCubicB > -0.001 && dVidCubicB < 0.001 && dVidCubicC > -0.001 && dVidCubicC < 0.001) { + var = MENU_DX9_CUBIC_LIGHT; + } + if (dVidCubicB > 1.499 && dVidCubicB < 1.501 && dVidCubicC > -0.251 && dVidCubicC < -0.249) { + var = MENU_DX9_CUBIC_NOTCH; + } + if (dVidCubicB > 0.999 && dVidCubicB < 1.001 && dVidCubicC > -0.001 && dVidCubicC < 0.001) { + var = MENU_DX9_CUBIC_BSPLINE; + } + if (dVidCubicB > 0.333 && dVidCubicB < 0.334 && dVidCubicC > 0.333 && dVidCubicC < 0.334) { + var = MENU_DX9_CUBIC_OPTIMAL; + } + if (dVidCubicB > -0.001 && dVidCubicB < 0.001 && dVidCubicC > 0.499 && dVidCubicC < 0.501) { + var = MENU_DX9_CUBIC_CATMULL; + } + if (dVidCubicB > -0.001 && dVidCubicB < 0.001 && dVidCubicC > 0.999 && dVidCubicC < 1.001) { + var = MENU_DX9_CUBIC_SHARP; + } + CheckMenuRadioItem(hMenu, MENU_DX9_CUBIC_LIGHT, MENU_DX9_CUBIC_BSPLINE + 8, var, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_DX9_FORCE_PS14, !(nVidBlitterOpt[nVidSelect] & (1 << 9)) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_DX9_FPTERXTURES, (nVidBlitterOpt[nVidSelect] & (1 << 8)) ? MF_CHECKED : MF_UNCHECKED); + if (!(nVidBlitterOpt[nVidSelect] & (1 << 9))) { + var = MENU_DX9_CUBIC4; + } else { + var = ((nVidBlitterOpt[nVidSelect] >> 28) & 0x07) + MENU_DX9_CUBIC0; + } + CheckMenuRadioItem(hMenu, MENU_DX9_CUBIC0, MENU_DX9_CUBIC0 + 8, var, MF_BYCOMMAND); + break; + case 4: + var = (nVidBlitterOpt[nVidSelect] & 0xFF) + MENU_SOFT_STRETCH; + CheckMenuRadioItem(hMenu, MENU_SOFT_STRETCH, MENU_SOFT_STRETCH + 25, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_SOFT_AUTOSIZE, (nVidBlitterOpt[nVidSelect] & 0x0100) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuRadioItem(hMenu, MENU_DX9_ALT_POINT, MENU_DX9_ALT_POINT + 1, MENU_DX9_ALT_POINT + bVidDX9Bilinear, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_DX9_ALT_HARDWAREVERTEX, (bVidHardwareVertex) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_DX9_ALT_MOTIONBLUR, (bVidMotionBlur) ? MF_CHECKED : MF_UNCHECKED); + break; + } + + var = 0; + if (nScreenSizeHor) { + var = MENU_SINGLESIZESCREEN + nScreenSizeHor - 1; + CreateOtherresItem(0); + } else { + for (int n = 0; n < 4; n++) { + if (nVidHorWidth == VidPreset[n].nWidth && nVidHorHeight == VidPreset[n].nHeight) { + var = MENU_RES_1 + n; + break; + } + } + if (var) { + CreateOtherresItem(0); + } else { + var = MENU_RES_OTHER; + CreateOtherresItem(1); + } + if (bVidArcaderesHor) { + var = MENU_RES_ARCADE; + } + } + CheckMenuRadioItem(hMenu, MENU_RES_1, MENU_QUADSIZESCREEN, var, MF_BYCOMMAND); + + var = 0; + if (nScreenSizeVer) { + var = MENU_SINGLESIZESCREEN_VERTICAL + nScreenSizeVer - 1; + CreateOtherresItemVer(0); + } else { + for (int n = 0; n < 4; n++) { + if (nVidVerWidth == VidPresetVer[n].nWidth && nVidVerHeight == VidPresetVer[n].nHeight) { + var = MENU_RES_1_VERTICAL + n; + break; + } + } + if (var) { + CreateOtherresItemVer(0); + } else { + var = MENU_RES_OTHER_VERTICAL; + CreateOtherresItemVer(1); + } + if (bVidArcaderesVer) { + var = MENU_RES_ARCADE_VERTICAL; + } + } + CheckMenuRadioItem(hMenu, MENU_RES_1_VERTICAL, MENU_QUADSIZESCREEN_VERTICAL, var, MF_BYCOMMAND); + + if (nVidDepth == 16) { + var = MENU_16; + } else { + if (nVidDepth == 24) { + var = MENU_24; + } else { + var = MENU_32; + } + } + CheckMenuRadioItem(hMenu, MENU_16, MENU_32, var, MF_BYCOMMAND); + + if (nGamma > 1.249 && nGamma < 1.251) { + var = MENU_GAMMA_DARKER; + } else { + if (nGamma > 0.799 && nGamma < 0.801) { + var = MENU_GAMMA_LIGHTER; + } else { + var = MENU_GAMMA_OTHER; + } + } + if (var == MENU_GAMMA_OTHER) { + CreateOtherGammaItem(1); + } else { + CreateOtherGammaItem(0); + } + if (!bDoGamma) { + var = MENU_GAMMA_DO; + } + CheckMenuRadioItem(hMenu, MENU_GAMMA_DARKER, MENU_GAMMA_OTHER, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_GAMMA_DO, bDoGamma ? MF_CHECKED : MF_UNCHECKED); + + var = MENU_GAMMA_SOFTWARE_ONLY; + if (bVidUseHardwareGamma) { + if (bHardwareGammaOnly) { + var = MENU_GAMMA_HARDWARE_ONLY; + } else { + var = MENU_GAMMA_USE_HARDWARE; + } + } + CheckMenuRadioItem(hMenu, MENU_GAMMA_USE_HARDWARE, MENU_GAMMA_SOFTWARE_ONLY, var, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_AUTOSWITCHFULL, bVidAutoSwitchFull ? MF_CHECKED : MF_UNCHECKED); + + if (nVidTransferMethod == 0) { + var = MENU_VIDEOMEM; + } else { + if (nVidTransferMethod == -1) { + var = MENU_MEMAUTO; + } else { + var = MENU_SYSMEM; + } + } + CheckMenuRadioItem(hMenu, MENU_MEMAUTO, MENU_SYSMEM, var, MF_BYCOMMAND); + if (nWindowSize <= 4) { + var = MENU_AUTOSIZE + nWindowSize; + } else { + var = MENU_MAXIMUMSIZEWINDOW; + } + CheckMenuRadioItem(hMenu, MENU_AUTOSIZE, MENU_MAXIMUMSIZEWINDOW, var, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_MONITORAUTOCHECK, bMonitorAutoCheck ? MF_CHECKED : MF_UNCHECKED); + + var = -1; + if (nVidScrnAspectX == 4 && nVidScrnAspectY == 3) { + var = MENU_ASPECTNORMAL; + } else { + if (nVidScrnAspectX == 5 && nVidScrnAspectY == 4) { + var = MENU_ASPECTLCD; + } else { + if (nVidScrnAspectX == 16 && nVidScrnAspectY == 9) { + var = MENU_ASPECTWIDE; + } else { + if (nVidScrnAspectX == 16 && nVidScrnAspectY == 10) { + var = MENU_ASPECTWIDELCD; + } + } + } + } + CheckMenuRadioItem(hMenu, MENU_ASPECTNORMAL, MENU_ASPECTWIDELCD, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_MONITORMIRRORVERT, (nVidRotationAdjust & 2) ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(hMenu, MENU_ROTATEVERTICAL, !(nVidRotationAdjust & 1) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_FORCE60HZ, bForce60Hz ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_VIDEOVSYNC, bVidVSync ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_AUTOFRAMESKIP, !bAlwaysDrawFrames ? MF_CHECKED : MF_UNCHECKED); + + var = nAudSelect + MENU_AUD_PLUGIN_1; + CheckMenuRadioItem(hMenu, MENU_AUD_PLUGIN_1, MENU_AUD_PLUGIN_8, var, MF_BYCOMMAND); + + switch (nAudSelect) { + case 0: { + var = MENU_DSOUND_NOSOUND; + if (nAudSampleRate[0] > 0) { + if (nAudSampleRate[0] <= 11025) { + var = MENU_DSOUND_11025; + } else { + if (nAudSampleRate[0] <= 22050) { + var = MENU_DSOUND_22050; + } else { + if (nAudSampleRate[0] <= 44100) { + var = MENU_DSOUND_44100; + } else { + var = MENU_DSOUND_48000; + } + } + } + } + CheckMenuRadioItem(hMenu, MENU_DSOUND_NOSOUND, MENU_DSOUND_48000, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_DSOUND_BASS, nAudDSPModule[0] ? MF_CHECKED : MF_UNCHECKED); + break; + } + + case 1: { + var = MENU_XAUDIO_NOSOUND; + if (nAudSampleRate[1] > 0) { + if (nAudSampleRate[1] <= 11025) { + var = MENU_XAUDIO_11025; + } else { + if (nAudSampleRate[1] <= 22050) { + var = MENU_XAUDIO_22050; + } else { + if (nAudSampleRate[1] <= 44100) { + var = MENU_XAUDIO_44100; + } else { + var = MENU_XAUDIO_48000; + } + } + } + } + CheckMenuRadioItem(hMenu, MENU_XAUDIO_NOSOUND, MENU_XAUDIO_48000, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_XAUDIO_BASS, (nAudDSPModule[1] & 1) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_XAUDIO_REVERB, (nAudDSPModule[1] & 2) ? MF_CHECKED : MF_UNCHECKED); + break; + } + } + + var = MENU_INTERPOLATE_0 + nInterpolation; + if (bDrvOkay) { + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + var = MENU_INTERPOLATE_0 + 1; + } + } + CheckMenuRadioItem(hMenu, MENU_INTERPOLATE_0, MENU_INTERPOLATE_5, var, MF_BYCOMMAND); + + var = MENU_INTERPOLATE_FM_0 + nFMInterpolation; + CheckMenuRadioItem(hMenu, MENU_INTERPOLATE_FM_0, MENU_INTERPOLATE_FM_5, var, MF_BYCOMMAND); + + CheckMenuItem(hMenu, MENU_AUTOPAUSE, bAutoPause ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_PROCESSINPUT, !bAlwaysProcessKeyboardInput ? MF_CHECKED : MF_UNCHECKED); + if (bAutoPause) { + EnableMenuItem(hMenu, MENU_PROCESSINPUT, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_PROCESSINPUT, MF_ENABLED | MF_BYCOMMAND); + } + CheckMenuItem(hMenu, MENU_DISPLAYINDICATOR, nVidSDisplayStatus ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_MODELESS, bModelessMenu ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_NOCHANGENUMLOCK, bNoChangeNumLock ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MENU_SAVEHISCORES, EnableHiscores ? MF_CHECKED : MF_UNCHECKED); + + if (nAppThreadPriority == THREAD_PRIORITY_TIME_CRITICAL) { + var = MENU_PRIORITY_REALTIME; + } else { + if (nAppThreadPriority == THREAD_PRIORITY_HIGHEST) { + var = MENU_PRIORITY_HIGH; + } else { + if (nAppThreadPriority == THREAD_PRIORITY_ABOVE_NORMAL) { + var = MENU_PRIORITY_ABOVE_NORMAL; + } else { + if (nAppThreadPriority == THREAD_PRIORITY_BELOW_NORMAL) { + var = MENU_PRIORITY_BELOW_NORMAL; + } else { + if (nAppThreadPriority == THREAD_PRIORITY_LOWEST) { + var = MENU_PRIORITY_LOW; + } else { + var = MENU_PRIORITY_NORMAL; + } + } + } + } + } + CheckMenuRadioItem(hMenu, MENU_PRIORITY_REALTIME, MENU_PRIORITY_LOW, var, MF_BYCOMMAND); + CheckMenuItem(hMenu, MENU_SAVEGAMEINPUT, bSaveInputs ? MF_CHECKED : MF_UNCHECKED); + +#if defined BUILD_A68K + CheckMenuItem(hMenu, MENU_ASSEMBLYCORE, bBurnUseASMCPUEmulation ? MF_CHECKED : MF_UNCHECKED); +#else + CheckMenuItem(hMenu, MENU_ASSEMBLYCORE, MF_UNCHECKED); + EnableMenuItem(hMenu, MENU_ASSEMBLYCORE, MF_GRAYED | MF_BYCOMMAND); +#endif + + // Previous games list + for (int i = 0; i < SHOW_PREV_GAMES; i++) { + MENUITEMINFO menuItemInfo; + TCHAR szText[256] = _T(""); + int OldDrvSelect = nBurnDrvActive; + + memset(&menuItemInfo, 0, sizeof(MENUITEMINFO)); + menuItemInfo.cbSize = sizeof(MENUITEMINFO); + menuItemInfo.fType = MFT_STRING; + menuItemInfo.fMask = MIIM_TYPE; + + if (_tcslen(szPrevGames[i])) { + for (unsigned int j = 0; j < nBurnDrvCount; j++) { + nBurnDrvActive = j; + if (!_tcsicmp(szPrevGames[i], BurnDrvGetText(DRV_NAME))) { + _stprintf(szText, _T("%s\t%s"), BurnDrvGetText(DRV_FULLNAME), BurnDrvGetText(DRV_NAME)); + + break; + } + } + + // Check for &s and change to && + TCHAR szText2[256] = _T(""); + TCHAR *Tokens = NULL; + int NumTokens = 0; + + Tokens = _tcstok(szText, _T("&")); + while (Tokens != NULL) { + if (NumTokens) { + _stprintf(szText2, _T("%s&&%s"), szText2, Tokens); + } else { + _stprintf(szText2, _T("%s"), Tokens); + } + + Tokens = _tcstok(NULL, _T("&")); + NumTokens++; + } + + menuItemInfo.dwTypeData = szText2; + menuItemInfo.cch = _tcslen(szText2); + + SetMenuItemInfo(hMenu, MENU_PREVIOUSGAMES1 + i, FALSE, &menuItemInfo); + EnableMenuItem(hMenu, MENU_PREVIOUSGAMES1 + i, MF_ENABLED | MF_BYCOMMAND); + } else { + _tcscpy(szText, _T("no game selected")); + + menuItemInfo.dwTypeData = szText; + menuItemInfo.cch = _tcslen(szText); + + SetMenuItemInfo(hMenu, MENU_PREVIOUSGAMES1 + i, FALSE, &menuItemInfo); + EnableMenuItem(hMenu, MENU_PREVIOUSGAMES1 + i, MF_GRAYED | MF_BYCOMMAND); + } + + nBurnDrvActive = OldDrvSelect; + } + +#if !defined BUILD_X86_ASM + EnableMenuItem(hMenu, MENU_SOFT_2XPM_LQ, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_2XPM_HQ, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_EAGLE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPEREAGLE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_2XSAI, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPER2XSAI, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPEREAGLE_VBA, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_2XSAI_VBA, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPER2XSAI_VBA, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPERSCALE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_SUPERSCALE75, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_HQ2X, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_HQ3X, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SOFT_HQ4X, MF_GRAYED | MF_BYCOMMAND); +#endif + +#if defined BUILD_X64_EXE + EnableMenuItem(hMenu, MENU_BLITTER_2, MF_GRAYED | MF_BYCOMMAND); +#endif +} + +void MenuEnableItems() +{ + CreateArcaderesItem(); + CreatepresetResItems(); + + if (hBlitterMenu[nVidSelect]) { + MENUITEMINFO myMenuItemInfo; + myMenuItemInfo.cbSize = sizeof(MENUITEMINFO); + myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE; + myMenuItemInfo.fState = MFS_ENABLED; + myMenuItemInfo.hSubMenu = GetSubMenu(hBlitterMenu[nVidSelect], 0); + SetMenuItemInfo(GetSubMenu(hMenu, 1), 1, TRUE, &myMenuItemInfo); + } else { + MENUITEMINFO myMenuItemInfo; + myMenuItemInfo.cbSize = sizeof(MENUITEMINFO); + myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE; + myMenuItemInfo.fState = MFS_GRAYED; + myMenuItemInfo.hSubMenu = NULL; + SetMenuItemInfo(GetSubMenu(hMenu, 1), 1, TRUE, &myMenuItemInfo); + } + + if (hBlitterMenu[nAudSelect]) { + MENUITEMINFO myMenuItemInfo; + myMenuItemInfo.cbSize = sizeof(MENUITEMINFO); + myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE; + myMenuItemInfo.fState = MFS_ENABLED; + myMenuItemInfo.hSubMenu = GetSubMenu(hAudioPluginMenu[nAudSelect], 0); + SetMenuItemInfo(GetSubMenu(hMenu, 2), 1, TRUE, &myMenuItemInfo); + } else { + MENUITEMINFO myMenuItemInfo; + myMenuItemInfo.cbSize = sizeof(MENUITEMINFO); + myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE; + myMenuItemInfo.fState = MFS_GRAYED; + myMenuItemInfo.hSubMenu = NULL; + SetMenuItemInfo(GetSubMenu(hMenu, 2), 1, TRUE, &myMenuItemInfo); + } + + // Auto-size image when software blitter effects anre enabled + if ((nVidSelect == 1 && (nVidBlitterOpt[1] & 0x07000000) == 0x07000000) || (nVidSelect == 2 && nVidBlitterOpt[2] & 0x0100)) { + EnableMenuItem(GetSubMenu(hMenu, 1), 2, MF_GRAYED | MF_BYPOSITION); + EnableMenuItem(GetSubMenu(hMenu, 1), 7, MF_GRAYED | MF_BYPOSITION); + EnableMenuItem(GetSubMenu(hMenu, 1), 10, MF_GRAYED | MF_BYPOSITION); + } else { + EnableMenuItem(GetSubMenu(hMenu, 1), 2, MF_ENABLED | MF_BYPOSITION); + EnableMenuItem(GetSubMenu(hMenu, 1), 7, MF_ENABLED | MF_BYPOSITION); + EnableMenuItem(GetSubMenu(hMenu, 1), 10, MF_ENABLED | MF_BYPOSITION); + } + EnableMenuItem(GetSubMenu(hMenu, 1), 11, MF_ENABLED | MF_BYPOSITION); + +#if 0 + if (nVidSelect == 3 && !(nVidBlitterOpt[3] & (1 << 9))) { + EnableMenuItem(hMenu, MENU_DX9_CUBIC0, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC1, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC2, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC3, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC4, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_DX9_CUBIC0, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC1, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC2, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC3, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC4, MF_ENABLED | MF_BYCOMMAND); + } +#endif + + if (nVidSelect == 3 && (!(nVidBlitterOpt[3] & (1 << 9)) || (nVidBlitterOpt[nVidSelect] & (7 << 28)) == (4 << 28))) { + EnableMenuItem(hMenu, MENU_DX9_CUBIC_BSPLINE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC_NOTCH, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC_OPTIMAL, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_DX9_CUBIC_BSPLINE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC_NOTCH, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DX9_CUBIC_OPTIMAL, MF_ENABLED | MF_BYCOMMAND); + } + if (nVidSelect == 3) { + EnableMenuItem(hMenu, MENU_24, MF_GRAYED | MF_BYCOMMAND); + } + + EnableMenuItem(hMenu, MENU_MODELESS, MF_ENABLED | MF_BYCOMMAND); + +#if defined _MSC_VER && defined BUILD_X86_ASM + EnableMenuItem(hBlitterMenu[1], MENU_SOFT_HQ3XS_VBA, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hBlitterMenu[2], MENU_SOFT_HQ3XS_VBA, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hBlitterMenu[4], MENU_SOFT_HQ3XS_VBA, MF_ENABLED | MF_BYCOMMAND); +#endif + + if (bDrvOkay) { + EnableMenuItem(hMenu, MENU_QUIT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INPUT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_FORCE60HZ, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_NOSOUND, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_11025, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_22050, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_44100, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_48000, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_NOSOUND, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_11025, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_22050, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_44100, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_48000, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_0, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_3, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_FRAMES, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVESNAP, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVEGAMEINPUTNOW, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_ASSEMBLYCORE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVEHISCORES, MF_GRAYED | MF_BYCOMMAND); + + EnableMenuItem(hMenu, MENU_CDIMAGE, MF_GRAYED | MF_BYCOMMAND); + + EnableMenuItem(hMenu, MENU_AUD_PLUGIN_1, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_AUD_PLUGIN_2, MF_GRAYED | MF_BYCOMMAND); + + BurnDIPInfo bdi; + if (BurnDrvGetDIPInfo(&bdi, 0) == 0) { + EnableMenuItem(hMenu, MENU_DIPSW, MF_ENABLED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_DIPSW, MF_GRAYED | MF_BYCOMMAND); + } + + EnableMenuItem(hMenu, MENU_INTERPOLATE_1, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_3, MF_ENABLED | MF_BYCOMMAND); + + EnableMenuItem(hMenu, MENU_MEMCARD_CREATE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_SELECT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_INSERT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_EJECT, MF_GRAYED | MF_BYCOMMAND); + + if ((BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + EnableMenuItem(hMenu, MENU_INTERPOLATE_1, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_3, MF_GRAYED | MF_BYCOMMAND); + + if (!kNetGame) { + EnableMenuItem(hMenu, MENU_MEMCARD_CREATE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_SELECT, MF_ENABLED | MF_BYCOMMAND); + if (nMemoryCardStatus & 1) { + if (nMemoryCardStatus & 2) { + EnableMenuItem(hMenu, MENU_MEMCARD_EJECT, MF_ENABLED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_MEMCARD_INSERT, MF_ENABLED | MF_BYCOMMAND); + } + } + } + } + + if (kNetGame) { + EnableMenuItem(hMenu, MENU_LOAD, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTNET, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_EXIT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SETCPUCLOCK, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_RESETCPUCLOCK, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_PAUSE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_ENABLECHEAT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SNAPFACT, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_LOAD, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTNET, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_EXIT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SETCPUCLOCK, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_RESETCPUCLOCK, (nBurnCPUSpeedAdjust != 0x0100 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_PAUSE, MF_ENABLED | MF_BYCOMMAND); + if (pCheatInfo) { + EnableMenuItem(hMenu, MENU_ENABLECHEAT, MF_ENABLED | MF_BYCOMMAND); + } + + if (CheatSearchInit()) { + EnableMenuItem(hMenu, MENU_CHEATSEARCH_START, MF_ENABLED | MF_BYCOMMAND); + } + +#if defined (FBA_DEBUG) + EnableMenuItem(hMenu, MENU_DEBUG, MF_ENABLED | MF_BYCOMMAND); +#else + EnableMenuItem(hMenu, MENU_DEBUG, MF_GRAYED | MF_BYCOMMAND); +#endif + + if (BurnDrvGetPaletteEntries()) EnableMenuItem(hMenu, MENU_PALETTEVIEWER, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SNAPFACT, MF_ENABLED | MF_BYCOMMAND); + } + + if (WaveLog) { + EnableMenuItem(hMenu, MENU_WLOGEND, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_WLOGSTART, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_WLOGEND, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_WLOGSTART, MF_ENABLED | MF_BYCOMMAND); + } + + if (nReplayStatus) { + EnableMenuItem(hMenu, MENU_STOPREPLAY, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTRECORD, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTREPLAY, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_SLOT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_DIALOG, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_STOPREPLAY, MF_GRAYED | MF_BYCOMMAND); + + if (kNetGame) { + EnableMenuItem(hMenu, MENU_STARTRECORD, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTREPLAY, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_SLOT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_DIALOG, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_SLOT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_DIALOG, MF_GRAYED | MF_BYCOMMAND); + } else { + EnableMenuItem(hMenu, MENU_STARTRECORD, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTREPLAY, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_SLOT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_DIALOG, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_SLOT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_DIALOG, MF_ENABLED | MF_BYCOMMAND); + } + } + + } else { + bAltPause = 0; + + EnableMenuItem(hMenu, MENU_LOAD, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_CREATE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_SELECT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_INSERT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_MEMCARD_EJECT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTNET, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTREPLAY, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STARTRECORD, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STOPREPLAY, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_QUIT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_EXIT, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INPUT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SETCPUCLOCK, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_RESETCPUCLOCK, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_PAUSE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_FORCE60HZ, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DIPSW, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_ENABLECHEAT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DEBUG, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_ASSEMBLYCORE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVEHISCORES, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_SLOT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_LOAD_DIALOG, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_SLOT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_STATE_SAVE_DIALOG, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_FRAMES, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_NOSOUND, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_11025, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_22050, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_44100, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_DSOUND_48000, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_NOSOUND, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_11025, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_22050, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_44100, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_XAUDIO_48000, MF_ENABLED | MF_BYCOMMAND); +// EnableMenuItem(hMenu, MENU_INTERPOLATE_1, MF_ENABLED | MF_BYCOMMAND); +// EnableMenuItem(hMenu, MENU_INTERPOLATE_3, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_WLOGSTART, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_0, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_3, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_WLOGEND, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVESNAP, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SNAPFACT, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_PALETTEVIEWER, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_SAVEGAMEINPUTNOW, MF_GRAYED | MF_BYCOMMAND); + + EnableMenuItem(hMenu, MENU_CDIMAGE, MF_ENABLED | MF_BYCOMMAND); + + EnableMenuItem(hMenu, MENU_AUD_PLUGIN_1, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_AUD_PLUGIN_2, MF_ENABLED | MF_BYCOMMAND); + } +} diff --git a/src/burner/win32/misc_win32.cpp b/src/burner/win32/misc_win32.cpp new file mode 100644 index 00000000..fb0468de --- /dev/null +++ b/src/burner/win32/misc_win32.cpp @@ -0,0 +1,254 @@ +#include "burner.h" + +bool bIsWindowsXPorGreater = FALSE; + +// Detect if we are using Windows XP/Vista/7 +BOOL DetectWindowsVersion() +{ + OSVERSIONINFO osvi; + BOOL bIsWindowsXPorLater; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + + // osvi.dwMajorVersion returns the windows version: 5 = XP 6 = Vista/7 + // osvi.dwMinorVersion returns the minor version, XP and 7 = 1, Vista = 0 + bIsWindowsXPorLater = ((osvi.dwMajorVersion > 5) || ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1))); + + return bIsWindowsXPorLater; +} + +// Set the current directory to be the application's directory +int AppDirectory() +{ + TCHAR szPath[MAX_PATH] = _T(""); + int nLen = 0; + TCHAR *pc1, *pc2; + TCHAR* szCmd = GetCommandLine(); + + // Find the end of the "c:\directory\program.exe" bit + if (szCmd[0] == _T('\"')) { // Filename is enclosed in quotes + szCmd++; + for (pc1 = szCmd; *pc1; pc1++) { + if (*pc1 == _T('\"')) break; // Find the last " + } + } else { + for (pc1 = szCmd; *pc1; pc1++) { + if (*pc1 == _T(' ')) break; // Find the first space + } + } + // Find the last \ or / + for (pc2 = pc1; pc2 >= szCmd; pc2--) { + if (*pc2 == _T('\\')) break; + if (*pc2 == _T('/')) break; + } + + // Copy the name of the executable into a variable + nLen = pc1 - pc2 - 1; + if (nLen > EXE_NAME_SIZE) { + nLen = EXE_NAME_SIZE; + } + _tcsncpy(szAppExeName, pc2 + 1, nLen); + szAppExeName[nLen] = 0; + + // strip .exe + if ((pc1 = _tcschr(szAppExeName, _T('.'))) != 0) { + *pc1 = 0; + } + + nLen = pc2 - szCmd; + if (nLen <= 0) return 1; // No path + + // Now copy the path into a new buffer + _tcsncpy(szPath, szCmd, nLen); + SetCurrentDirectory(szPath); // Finally set the current directory to be the application's directory + + dprintf(szPath); + dprintf(_T("\n")); + + return 0; +} + +void UpdatePath(TCHAR* path) +{ + int pathlen = _tcslen(path); + if (pathlen) { + DWORD attrib = INVALID_FILE_ATTRIBUTES; + TCHAR curdir[MAX_PATH] = _T(""); + int curlen = 0; + + attrib = GetFileAttributes(path); + if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) && path[pathlen - 1] != _T('\\')) { + path[pathlen] = _T('\\'); + path[pathlen + 1] = _T('\0'); + + pathlen++; + } + + GetCurrentDirectory(sizeof(curdir), curdir); + curlen = _tcslen(curdir); + + if (_tcsnicmp(curdir, path, curlen) == 0 && path[curlen] == _T('\\')) { + TCHAR newpath[MAX_PATH]; + + _tcscpy(newpath, path + curlen + 1); + _tcscpy(path, newpath); + } + } +} + +// --------------------------------------------------------------------------- + +static void MyRegCreateKeys(int nDepth, TCHAR* pNames[], HKEY* pResult) +{ + for (int i = 0; i < nDepth; i++) { + pResult[i] = NULL; + RegCreateKeyEx((i ? pResult[i - 1] : HKEY_CLASSES_ROOT), pNames[i], 0, _T(""), 0, KEY_WRITE, NULL, &pResult[i], NULL); + } +} + +static void MyRegCloseKeys(int nDepth, HKEY* pKeys) +{ + for (int i = nDepth - 1; i >= 0; i--) { + if (pKeys[i]) { + RegCloseKey(pKeys[i]); + } + } +} + +static void MyRegDeleteKeys(int nDepth, TCHAR* pNames[], HKEY* pKeys) +{ + for (int i = 0; i < nDepth - 1; i++) { + pKeys[i] = NULL; + RegOpenKeyEx((i ? pKeys[i - 1] : HKEY_CLASSES_ROOT), pNames[i], 0, 0, &pKeys[i]); + } + for (int i = nDepth - 1; i >= 0; i--) { + RegDeleteKey((i ? pKeys[i - 1] : HKEY_CLASSES_ROOT), pNames[i]); + if (i) { + RegCloseKey(pKeys[i - 1]); + } + } +} + +void RegisterExtensions(bool bCreateKeys) +{ + HKEY myKeys[4]; + + TCHAR* myKeynames1[1] = { _T(".fr") }; + TCHAR* myKeynames2[1] = { _T(".fs") }; + TCHAR* myKeynames3[4] = { _T("FBAlpha"), _T("shell"), _T("open"), _T("command") }; + TCHAR* myKeynames4[2] = { _T("FBAlpha"), _T("DefaultIcon") }; + TCHAR myKeyValue[MAX_PATH + 32] = _T(""); + + if (bCreateKeys) { + TCHAR szExename[MAX_PATH] = _T(""); + GetModuleFileName(NULL, szExename, MAX_PATH); + + MyRegCreateKeys(1, myKeynames1, myKeys); + _stprintf(myKeyValue, _T("FBAlpha")); + RegSetValueEx(myKeys[0], NULL, 0, REG_SZ, (BYTE*)myKeyValue, (_tcslen(myKeyValue) + 1) * sizeof(TCHAR)); + MyRegCloseKeys(2, myKeys); + + MyRegCreateKeys(1, myKeynames2, myKeys); + _stprintf(myKeyValue, _T("FBAlpha")); + RegSetValueEx(myKeys[0], NULL, 0, REG_SZ, (BYTE*)myKeyValue, (_tcslen(myKeyValue) + 1) * sizeof(TCHAR)); + MyRegCloseKeys(2, myKeys); + + MyRegCreateKeys(4, myKeynames3, myKeys); + _stprintf(myKeyValue, _T("\"%s\" \"%%1\" -w"), szExename); + RegSetValueEx(myKeys[3], NULL, 0, REG_SZ, (BYTE*)myKeyValue, (_tcslen(myKeyValue) + 1) * sizeof(TCHAR)); + _stprintf(myKeyValue, _T("FB Alpha file")); + RegSetValueEx(myKeys[0], NULL, 0, REG_SZ, (BYTE*)myKeyValue, (_tcslen(myKeyValue) + 1) * sizeof(TCHAR)); + MyRegCloseKeys(4, myKeys); + + MyRegCreateKeys(2, myKeynames4, myKeys); + _stprintf(myKeyValue, _T("\"%s\", 0"), szExename); + RegSetValueEx(myKeys[1], NULL, 0, REG_SZ, (BYTE*)myKeyValue, (_tcslen(myKeyValue) + 1) * sizeof(TCHAR)); + MyRegCloseKeys(2, myKeys); + } else { + MyRegDeleteKeys(2, myKeynames4, myKeys); + MyRegDeleteKeys(4, myKeynames3, myKeys); + MyRegDeleteKeys(1, myKeynames2, myKeys); + MyRegDeleteKeys(1, myKeynames1, myKeys); + } + + return; +} + +// --------------------------------------------------------------------------- + +// Get the position of the client area of a window on the screen +int GetClientScreenRect(HWND hWnd, RECT *pRect) +{ + POINT Corner = {0, 0}; + + GetClientRect(hWnd, pRect); + ClientToScreen(hWnd, &Corner); + + pRect->left += Corner.x; + pRect->right += Corner.x; + pRect->top += Corner.y; + pRect->bottom += Corner.y; + + return 0; +} + +// Put a window in the middle of another window +int WndInMid(HWND hMid, HWND hBase) +{ + RECT MidRect = {0, 0, 0, 0}; + int mw = 0, mh = 0; + RECT BaseRect = {0, 0, 0, 0}; + int bx = 0, by = 0; + + // Find the height and width of the Mid window + GetWindowRect(hMid, &MidRect); + mw = MidRect.right - MidRect.left; + mh = MidRect.bottom - MidRect.top; + + // Find the center of the Base window + if (hBase && IsWindowVisible(hBase)) { + GetWindowRect(hBase, &BaseRect); + if (hBase == hScrnWnd) { + // For the main window, center in the client area. + BaseRect.left += GetSystemMetrics(SM_CXSIZEFRAME); + BaseRect.right -= GetSystemMetrics(SM_CXSIZEFRAME); + BaseRect.top += GetSystemMetrics(SM_CYSIZEFRAME); + if (bMenuEnabled) { + BaseRect.top += GetSystemMetrics(SM_CYCAPTION) + nMenuHeight; + } + BaseRect.bottom -= GetSystemMetrics(SM_CYSIZEFRAME); + } + } else { + SystemParametersInfo(SPI_GETWORKAREA, 0, &BaseRect, 0); + } + + bx = BaseRect.left + BaseRect.right; + bx = (bx - mw) >> 1; + by = BaseRect.top + BaseRect.bottom; + by = (by - mh) >> 1; + + if (hBase) { + SystemParametersInfo(SPI_GETWORKAREA, 0, &SystemWorkArea, 0); + + if (bx + mw > SystemWorkArea.right) { + bx = SystemWorkArea.right - mw; + } + if (by + mh > SystemWorkArea.bottom) { + by = SystemWorkArea.bottom - mh; + } + if (bx < SystemWorkArea.left) { + bx = SystemWorkArea.left; + } + if (by < SystemWorkArea.top) { + by = SystemWorkArea.top; + } + } + + // Center the window + SetWindowPos(hMid, NULL, bx, by, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + return 0; +} diff --git a/src/burner/win32/neocdlist.cpp b/src/burner/win32/neocdlist.cpp new file mode 100644 index 00000000..f25c33b2 --- /dev/null +++ b/src/burner/win32/neocdlist.cpp @@ -0,0 +1,518 @@ +// --------------------------------------------------------------------------------------- +// NeoGeo CD Game Info Module (by CaptainCPS-X) +// --------------------------------------------------------------------------------------- +#include "burner.h" +#include "neocdlist.h" + +struct NGCDGAME games[] = +{ +// ---------------------------------------------------------------------------------------------------------------------------------------------// +// * Name * Title * Year * Company * Game ID // +// ---------------------------------------------------------------------------------------------------------------------------------------------// + { _T("nam1975") , _T("NAM-1975") , _T("1990") , _T("SNK") , 0x0001 }, // + { _T("bstars") , _T("Baseball Stars Professional") , _T("1991") , _T("SNK") , 0x0002 }, // + { _T("tpgolf") , _T("Top Player's Golf") , _T("1990") , _T("SNK") , 0x0003 }, // + { _T("mahretsu") , _T("Mahjong Kyo Retsuden - Nishi Nihon Hen") , _T("1990") , _T("SNK") , 0x0004 }, // + { _T("maglord") , _T("Magician Lord") , _T("1990") , _T("ADK") , 0x0005 }, // + { _T("ridhero") , _T("Riding Hero") , _T("1991") , _T("SNK") , 0x0006 }, // + { _T("alpham2") , _T("Alpha Mission II / ASO II - Last Guardian") , _T("1994") , _T("SNK") , 0x0007 }, // + { _T("ncombat") , _T("Ninja Combat") , _T("1990") , _T("SNK/ADK") , 0x0009 }, // + { _T("cyberlip") , _T("Cyber-Lip") , _T("1991") , _T("SNK") , 0x0010 }, // + { _T("superspy") , _T("The Super Spy") , _T("1990") , _T("SNK") , 0x0011 }, // + { _T("mutnat") , _T("Mutation Nation") , _T("1995") , _T("SNK") , 0x0014 }, // + { _T("sengoku") , _T("Sengoku / Sengoku Denshou") , _T("1994") , _T("SNK") , 0x0017 }, // + { _T("burningf") , _T("Burning Fight") , _T("1994") , _T("SNK") , 0x0018 }, // + { _T("lbowling") , _T("League Bowling") , _T("1994") , _T("SNK") , 0x0019 }, // + { _T("gpilots") , _T("Ghost Pilots") , _T("1991") , _T("SNK") , 0x0020 }, // + { _T("joyjoy") , _T("Puzzled / Joy Joy Kid") , _T("1990") , _T("SNK") , 0x0021 }, // + { _T("bjourney") , _T("Blue's Journey / Raguy") , _T("1990") , _T("SNK/ADK") , 0x0022 }, // + { _T("lresort") , _T("Last Resort") , _T("1994") , _T("SNK") , 0x0024 }, // + { _T("2020bb") , _T("2020 Super Baseball") , _T("1994") , _T("SNK") , 0x0030 }, // + { _T("socbrawl") , _T("Soccer Brawl") , _T("1991") , _T("SNK") , 0x0031 }, // + { _T("roboarmy") , _T("Robo Army") , _T("1991") , _T("SNK") , 0x0032 }, // + { _T("fatfury") , _T("Fatal Fury - The Battle of Fury") , _T("1994") , _T("SNK") , 0x0033 }, // + { _T("fbfrenzy") , _T("Football Frenzy") , _T("1994") , _T("SNK") , 0x0034 }, // + { _T("crswords") , _T("Crossed Swords") , _T("1994") , _T("SNK/ADK") , 0x0037 }, // + { _T("rallych") , _T("Rally Chase") , _T("1991") , _T("SNK/ADK") , 0x0038 }, // + { _T("kotm2") , _T("King of the Monsters 2") , _T("1992") , _T("SNK") , 0x0039 }, // + { _T("sengoku2") , _T("Sengoku 2 / Sengoku Denshou 2") , _T("1994") , _T("SNK") , 0x0040 }, // + { _T("bstars2") , _T("Baseball Stars 2") , _T("1992") , _T("SNK") , 0x0041 }, // + { _T("3countb") , _T("3 Count Bout / Fire Suplex") , _T("1995") , _T("SNK") , 0x0043 }, // + { _T("aof") , _T("Art of Fighting / Ryuuko no Ken") , _T("1994") , _T("SNK") , 0x0044 }, // + { _T("samsho") , _T("Samurai Shodown / Samurai Spirits") , _T("1993") , _T("SNK") , 0x0045 }, // + { _T("tophuntr") , _T("Top Hunter - Roddy & Cathy") , _T("1994") , _T("SNK") , 0x0046 }, // + { _T("fatfury2") , _T("Fatal Fury 2 / Garou Densetsu 2 - Aratanaru Tatakai") , _T("1994") , _T("SNK") , 0x0047 }, // + { _T("janshin") , _T("Janshin Densetsu - Quest of the Jongmaster") , _T("1995") , _T("Yubis") , 0x0048 }, // + { _T("ncommand") , _T("Ninja Commando") , _T("1992") , _T("SNK") , 0x0050 }, // + { _T("viewpoin") , _T("Viewpoint") , _T("1992") , _T("Sammy/Aicom") , 0x0051 }, // + { _T("ssideki") , _T("Super Sidekicks / Tokuten Oh") , _T("1993") , _T("SNK") , 0x0052 }, // + { _T("wh1") , _T("World Heroes") , _T("1992") , _T("ADK") , 0x0053 }, // + { _T("crsword2") , _T("Crossed Swords II") , _T("1995") , _T("SNK/ADK") , 0x0054 }, // + { _T("kof94") , _T("The King of Fighters '94 (JP)") , _T("1994") , _T("SNK") , 0x0055 }, // + { _T("kof94ju") , _T("The King of Fighters '94 (JP-US)") , _T("1994") , _T("SNK") , 0x1055 }, // custom id + { _T("aof2") , _T("Art of Fighting 2 / Ryuuko no Ken 2") , _T("1994") , _T("SNK") , 0x0056 }, // + { _T("wh2") , _T("World Heroes 2") , _T("1995") , _T("SNK/ADK") , 0x0057 }, // + { _T("fatfursp") , _T("Fatal Fury Special / Garou Densetsu Special") , _T("1994") , _T("SNK") , 0x0058 }, // + { _T("savagere") , _T("Savage Reign / Fu'un Mokujiroku - Kakutou Sousei") , _T("1995") , _T("SNK") , 0x0059 }, // + { _T("ssideki2") , _T("Super Sidekicks 2 / Tokuten Oh 2") , _T("1994") , _T("SNK") , 0x0061 }, // + { _T("samsho2") , _T("Samurai Shodown 2 / Shin Samurai Spirits") , _T("1994") , _T("SNK") , 0x0063 }, // + { _T("wh2j") , _T("World Heroes 2 Jet") , _T("1995") , _T("SNK/ADK") , 0x0064 }, // + { _T("wjammers") , _T("Windjammers / Flying Power Disc") , _T("1994") , _T("Data East") , 0x0065 }, // + { _T("karnovr") , _T("Karnov's Revenge / Fighters History Dynamite") , _T("1994") , _T("Data East") , 0x0066 }, // + { _T("pspikes2") , _T("Power Spikes II") , _T("1994") , _T("Video System") , 0x0068 }, // + { _T("aodk") , _T("Aggressors of Dark Kombat / Tsuukai GanGan Koushinkyoku") , _T("1994"), _T("SNK/ADK") , 0x0074 }, // + { _T("sonicwi2") , _T("Aero Fighters 2 / Sonic Wings 2") , _T("1994") , _T("Video System") , 0x0075 }, // + { _T("galaxyfg") , _T("Galaxy Fight - Universal Warriors") , _T("1995") , _T("Sunsoft") , 0x0078 }, // + { _T("strhoop") , _T("Street Hoop / Dunk Dream") , _T("1994") , _T("Data East") , 0x0079 }, // + { _T("quizkof") , _T("Quiz King of Fighters") , _T("1993") , _T("SNK/Saurus") , 0x0080 }, // + { _T("ssideki3") , _T("Super Sidekicks 3 - The Next Glory / Tokuten Oh 3 - Eikoue No Chousen"), _T("1995") , _T("SNK") , 0x0081 }, // + { _T("doubledr") , _T("Double Dragon") , _T("1995") , _T("Technos") , 0x0082 }, // + { _T("pbobblen") , _T("Puzzle Bobble / Bust-A-Move") , _T("1994") , _T("SNK") , 0x0083 }, // + { _T("kof95") , _T("The King of Fighters '95 (JP-US)") , _T("1995") , _T("SNK") , 0x0084 }, // + { _T("kof95r1") , _T("The King of Fighters '95 (JP-US)(Rev 1)") , _T("1995") , _T("SNK") , 0x1084 }, // + { _T("ssrpg") , _T("Shinsetsu Samurai Spirits - Bushidohretsuden") , _T("1997") , _T("SNK") , 0x0085 }, // + { _T("samsho3") , _T("Samurai Shodown 3 / Samurai Spirits 3") , _T("1995") , _T("SNK") , 0x0087 }, // + { _T("stakwin") , _T("Stakes Winner - GI Kanzen Seiha Heno Machi") , _T("1995") , _T("Saurus") , 0x0088 }, // + { _T("pulstar") , _T("Pulstar") , _T("1995") , _T("Aicom") , 0x0089 }, // + { _T("whp") , _T("World Heroes Perfect") , _T("1995") , _T("ADK") , 0x0090 }, // + { _T("kabukikl") , _T("Kabuki Klash / Tengai Makyou Shinden - Far East of Eden") , _T("1995"), _T("Hudson") , 0x0092 }, // + { _T("gowcaizr") , _T("Voltage Fighter Gowcaizer / Choujin Gakuen Gowcaizer"), _T("1995") , _T("Technos") , 0x0094 }, // + { _T("rbff1") , _T("Real Bout Fatal Fury") , _T("1995") , _T("SNK") , 0x0095 }, // + { _T("aof3") , _T("Art of Fighting 3: Path of the Warrior") , _T("1996") , _T("SNK") , 0x0096 }, // + { _T("sonicwi3") , _T("Aero Fighters 3 / Sonic Wings 3") , _T("1995") , _T("SNK") , 0x0097 }, // + { _T("fromanc2") , _T("Idol Mahjong Final Romance 2") , _T("1995") , _T("Video Systems") , 0x0098 }, // + { _T("turfmast") , _T("Neo Turf Masters / Big Tournament Golf") , _T("1996") , _T("Nazca") , 0x0200 }, // + { _T("mslug") , _T("Metal Slug - Super Vehicle-001") , _T("1996") , _T("Nazca") , 0x0201 }, // + { _T("mosyougi") , _T("Shougi no Tatsujin - Master of Syougi") , _T("1995") , _T("ADK") , 0x0203 }, // + { _T("adkworld") , _T("ADK World / ADK Special") , _T("1995") , _T("ADK") , 0x0204 }, // + { _T("ngcdsp") , _T("Neo Geo CD Special") , _T("1995") , _T("SNK") , 0x0205 }, // + { _T("zintrick") , _T("Zintrick / Oshidashi Zintrick") , _T("1996") , _T("ADK") , 0x0211 }, // + { _T("overtop") , _T("OverTop") , _T("1996") , _T("ADK") , 0x0212 }, // + { _T("neodrift") , _T("Neo DriftOut") , _T("1996") , _T("Visco") , 0x0213 }, // + { _T("kof96") , _T("The King of Fighters '96") , _T("1996") , _T("SNK") , 0x0214 }, // + { _T("ninjamas") , _T("Ninja Master's - Haou Ninpou-Chou") , _T("1996") , _T("ADK/SNK") , 0x0217 }, // + { _T("ragnagrd") , _T("Ragnagard / Shinouken") , _T("1996") , _T("Saurus") , 0x0218 }, // + { _T("pgoal") , _T("Pleasuregoal - 5 on 5 Mini Soccer / Futsal") , _T("1996") , _T("Saurus") , 0x0219 }, // + { _T("ironclad") , _T("Ironclad / Choutetsu Brikin'ger") , _T("1996") , _T("Saurus") , 0x0220 }, // + { _T("magdrop2") , _T("Magical Drop 2") , _T("1996") , _T("Data East") , 0x0221 }, // + { _T("samsho4") , _T("Samurai Shodown IV - Amakusa's Revenge") , _T("1996") , _T("SNK") , 0x0222 }, // + { _T("rbffspec") , _T("Real Bout Fatal Fury Special") , _T("1996") , _T("SNK") , 0x0223 }, // + { _T("twinspri") , _T("Twinkle Star Sprites") , _T("1996") , _T("ADK") , 0x0224 }, // + { _T("kof96ngc") , _T("The King of Fighters '96 NEOGEO Collection") , _T("1996") , _T("SNK") , 0x0229 }, // + { _T("breakers") , _T("Breakers") , _T("1996") , _T("Visco") , 0x0230 }, // + { _T("kof97") , _T("The King of Fighters '97") , _T("1997") , _T("SNK") , 0x0232 }, // + { _T("lastblad") , _T("The Last Blade / Bakumatsu Roman - Gekka no Kenshi") , _T("1997") , _T("SNK") , 0x0234 }, // + { _T("rbff2") , _T("Real Bout Fatal Fury 2 / Garou Densetsu 2 - Aratanaru Tatakai"), _T("1998"), _T("SNK") , 0x0240 }, // + { _T("mslug2") , _T("Metal Slug 2 - Super Vehicle-001/II") , _T("1998") , _T("SNK") , 0x0241 }, // + { _T("kof98") , _T("The King of Fighters '98 - The Slugfest") , _T("1998") , _T("SNK") , 0x0242 }, // + { _T("lastbld2") , _T("The Last Blade 2") , _T("1998") , _T("SNK") , 0x0243 }, // + { _T("kof99") , _T("The King of Fighters '99 - Millennium Battle") , _T("1999") , _T("SNK") , 0x0251 }, // + { _T("fatfury3") , _T("Fatal Fury 3 - Road to the Final Victory / Garou Densetsu 3 - Harukanaru Tatakai"), _T("1995"), _T("SNK"), 0x069c }, // +}; + +NGCDGAME* GetNeoGeoCDInfo(unsigned int nID) +{ + for(unsigned int nGame = 0; nGame < (sizeof(games) / sizeof(NGCDGAME)); nGame++) { + if(nID == games[nGame].id ) { + return &games[nGame]; + } + } + + return NULL; +} + +// Update the main window title +void SetNeoCDTitle(TCHAR* pszTitle) +{ + TCHAR szText[1024] = _T(""); + _stprintf(szText, _T(APP_TITLE) _T( " v%.20s") _T(SEPERATOR_1) _T("%s") _T(SEPERATOR_1) _T("%s"), szAppBurnVer, BurnDrvGetText(DRV_FULLNAME), pszTitle); + + SetWindowText(hScrnWnd, szText); +} + +NGCDGAME* game; + +// Get the title +int GetNeoCDTitle(unsigned int nGameID) +{ + game = (NGCDGAME*)malloc(sizeof(NGCDGAME)); + memset(game, 0, sizeof(NGCDGAME)); + + if(GetNeoGeoCDInfo(nGameID)) + { + memcpy(game, GetNeoGeoCDInfo(nGameID), sizeof(NGCDGAME)); + + bprintf(PRINT_NORMAL, _T(" Title: %s \n") , game->pszTitle); + bprintf(PRINT_NORMAL, _T(" Shortname: %s \n") , game->pszName); + bprintf(PRINT_NORMAL, _T(" Year: %s \n") , game->pszYear); + bprintf(PRINT_NORMAL, _T(" Company: %s \n") , game->pszCompany); + + // Update the main window title + SetNeoCDTitle(game->pszTitle); + + return 1; + } + + game = NULL; + return 0; +} + +void iso9660_ReadOffset(unsigned char *Dest, FILE* fp, unsigned int lOffset, unsigned int lSize, unsigned int lLength) +{ + if(fp == NULL) return; + if (Dest == NULL) return; + + fseek(fp, lOffset, SEEK_SET); + fread(Dest, lLength, lSize, fp); +} + +static void NeoCDList_iso9660_CheckDirRecord(FILE* fp, int nSector) +{ + int nSectorLength = 2048; + //int nFile = 0; + unsigned int lBytesRead = 0; + //int nLen = 0; + unsigned int lOffset = 0; + bool bNewSector = false; + bool bRevisionQueve = false; + int nRevisionQueveID = 0; + + lOffset = (nSector * nSectorLength); + + unsigned char* nLenDR = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char* Flags = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char* ExtentLoc = (unsigned char*)malloc(8 * sizeof(unsigned char)); + unsigned char* Data = (unsigned char*)malloc(0x10b * sizeof(unsigned char)); + unsigned char* LEN_FI = (unsigned char*)malloc(1 * sizeof(unsigned char)); + char *File = (char*)malloc(32 * sizeof(char)); + + while(1) + { + iso9660_ReadOffset(nLenDR, fp, lOffset, 1, sizeof(unsigned char)); + + if(nLenDR[0] == 0x22) { + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + continue; + } + + if(nLenDR[0] < 0x22) + { + if(bNewSector) + { + if(bRevisionQueve) { + bRevisionQueve = false; + + GetNeoCDTitle(nRevisionQueveID); + } + return; + } + + nLenDR[0] = 0; + iso9660_ReadOffset(nLenDR, fp, lOffset + 1, 1, sizeof(unsigned char)); + + if(nLenDR[0] < 0x22) { + lOffset += (2048 - lBytesRead); + lBytesRead = 0; + bNewSector = true; + continue; + } + } + + bNewSector = false; + + iso9660_ReadOffset(Flags, fp, lOffset + 25, 1, sizeof(unsigned char)); + + if(!(Flags[0] & (1 << 1))) + { + iso9660_ReadOffset(ExtentLoc, fp, lOffset + 2, 8, sizeof(unsigned char)); + + char szValue[9]; + sprintf(szValue, "%02x%02x%02x%02x", ExtentLoc[4], ExtentLoc[5], ExtentLoc[6], ExtentLoc[7]); + + unsigned int nValue = 0; + sscanf(szValue, "%x", &nValue); + + iso9660_ReadOffset(Data, fp, nValue * 2048, 0x10a, sizeof(unsigned char)); + + char szData[8]; + sprintf(szData, "%c%c%c%c%c%c%c", Data[0x100], Data[0x101], Data[0x102], Data[0x103], Data[0x104], Data[0x105], Data[0x106]); + + if(!strncmp(szData, "NEO-GEO", 7)) + { + char id[] = "0000"; + sprintf(id, "%02X%02X", Data[0x108], Data[0x109]); + + unsigned int nID = 0; + sscanf(id, "%x", &nID); + + iso9660_ReadOffset(LEN_FI, fp, lOffset + 32, 1, sizeof(unsigned char)); + + iso9660_ReadOffset((unsigned char*)File, fp, lOffset + 33, LEN_FI[0], sizeof(char)); + strncpy(File, File, LEN_FI[0]); + File[LEN_FI[0]] = 0; + + // King of Fighters '94, The (1994)(SNK)(JP) + // 10-6-1994 (P1.PRG) + if(nID == 0x0055 && Data[0x67] == 0xDE) { + // ...continue + } + + // King of Fighters '94, The (1994)(SNK)(JP-US) + // 11-21-1994 (P1.PRG) + if(nID == 0x0055 && Data[0x67] == 0xE6) { + // Change to custom revision id + nID = 0x1055; + } + + // King of Fighters '95, The (1995)(SNK)(JP-US)[!][NGCD-084 MT B01, B03-B06, NGCD-084E MT B01] + // 9-11-1995 (P1.PRG) + if(nID == 0x0084 && Data[0x6C] == 0xC0) { + // ... continue + } + + // King of Fighters '95, The (1995)(SNK)(JP-US)[!][NGCD-084 MT B10, NGCD-084E MT B03] + // 10-5-1995 (P1.PRG) + if(nID == 0x0084 && Data[0x6C] == 0xFF) { + // Change to custom revision id + nID = 0x1084; + } + + // King of Fighters '96 NEOGEO Collection, The + if(nID == 0x0229) { + bRevisionQueve = false; + + GetNeoCDTitle(nID); + break; + } + + // King of Fighters '96, The + if(nID == 0x0214) { + bRevisionQueve = true; + nRevisionQueveID = nID; + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + continue; + } + + GetNeoCDTitle(nID); + + break; + } + } + + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + } + + if (nLenDR) { + free(nLenDR); + nLenDR = NULL; + } + + if (Flags) { + free(Flags); + Flags = NULL; + } + + if (ExtentLoc) { + free(ExtentLoc); + ExtentLoc = NULL; + } + + if (Data) { + free(Data); + Data = NULL; + } + + if (LEN_FI) { + free(LEN_FI); + LEN_FI = NULL; + } + + if (File) { + free(File); + File = NULL; + } +} + +// Check the specified ISO, and proceed accordingly +static int NeoCDList_CheckISO(TCHAR* pszFile) +{ + if(!pszFile) { + // error + return 0; + } + + // Make sure we have a valid ISO file extension... + if(_tcsstr(pszFile, _T(".iso")) || _tcsstr(pszFile, _T(".ISO")) ) + { + FILE* fp = _tfopen(pszFile, _T("rb")); + if(fp) + { + // Read ISO and look for 68K ROM standard program header, ID is always there + // Note: This function works very quick, doesn't compromise performance :) + // it just read each sector first 264 bytes aproximately only. + + // Get ISO Size (bytes) + fseek(fp, 0, SEEK_END); + unsigned int lSize = 0; + lSize = ftell(fp); + //rewind(fp); + fseek(fp, 0, SEEK_SET); + + // If it has at least 16 sectors proceed + if(lSize > (2048 * 16)) + { + // Check for Standard ISO9660 Identifier + unsigned char IsoHeader[2048 * 16 + 1]; + unsigned char IsoCheck[6]; + + fread(IsoHeader, 1, 2048 * 16 + 1, fp); // advance to sector 16 and PVD Field 2 + fread(IsoCheck, 1, 5, fp); // get Standard Identifier Field from PVD + + // Verify that we have indeed a valid ISO9660 MODE1/2048 + if(!memcmp(IsoCheck, "CD001", 5)) + { + //bprintf(PRINT_NORMAL, _T(" Standard ISO9660 Identifier Found. \n")); + iso9660_VDH vdh; + + // Get Volume Descriptor Header + memset(&vdh, 0, sizeof(vdh)); + //memcpy(&vdh, iso9660_ReadOffset(fp, (2048 * 16), sizeof(vdh)), sizeof(vdh)); + iso9660_ReadOffset((unsigned char*)&vdh, fp, 2048 * 16, 1, sizeof(vdh)); + + // Check for a valid Volume Descriptor Type + if(vdh.vdtype == 0x01) + { +#if 0 +// This will fail on 64-bit due to differing variable sizes in the pvd struct + // Get Primary Volume Descriptor + iso9660_PVD pvd; + memset(&pvd, 0, sizeof(pvd)); + //memcpy(&pvd, iso9660_ReadOffset(fp, (2048 * 16), sizeof(pvd)), sizeof(pvd)); + iso9660_ReadOffset((unsigned char*)&pvd, fp, 2048 * 16, 1, sizeof(pvd)); + + // ROOT DIRECTORY RECORD + + // Handle Path Table Location + char szRootSector[32]; + unsigned int nRootSector = 0; + + sprintf(szRootSector, "%02X%02X%02X%02X", + pvd.root_directory_record.location_of_extent[4], + pvd.root_directory_record.location_of_extent[5], + pvd.root_directory_record.location_of_extent[6], + pvd.root_directory_record.location_of_extent[7]); + + // Convert HEX string to Decimal + sscanf(szRootSector, "%X", &nRootSector); +#else +// Just read from the file directly at the correct offset (0x8000 + 0x9e for the start of the root directory record) + unsigned char buffer[8]; + char szRootSector[4]; + unsigned int nRootSector = 0; + + fseek(fp, 0x809e, SEEK_SET); + fread(buffer, 1, 8, fp); + + sprintf(szRootSector, "%02x%02x%02x%02x", buffer[4], buffer[5], buffer[6], buffer[7]); + + sscanf(szRootSector, "%x", &nRootSector); +#endif + + // Process the Root Directory Records + NeoCDList_iso9660_CheckDirRecord(fp, nRootSector); + + // Path Table Records are not processed, since NeoGeo CD should not have subdirectories + // ... + } + } else { + + //bprintf(PRINT_NORMAL, _T(" Standard ISO9660 Identifier Not Found, cannot continue. \n")); + return 0; + } + } + } else { + + //bprintf(PRINT_NORMAL, _T(" Couldn't open %s \n"), GetIsoPath()); + return 0; + } + + if(fp) fclose(fp); + + } else { + + //bprintf(PRINT_NORMAL, _T(" File doesn't have a valid ISO extension [ .iso / .ISO ] \n")); + return 0; + } + + return 1; +} + +// This will do everything +int GetNeoGeoCD_Identifier() +{ + if(!GetIsoPath() || !IsNeoGeoCD()) { + return 0; + } + + // Make sure we have a valid ISO file extension... + if(_tcsstr(GetIsoPath(), _T(".iso")) || _tcsstr(GetIsoPath(), _T(".ISO")) ) + { + if(_tfopen(GetIsoPath(), _T("rb"))) + { + // Read ISO and look for 68K ROM standard program header, ID is always there + // Note: This function works very quick, doesn't compromise performance :) + // it just read each sector first 264 bytes aproximately only. + NeoCDList_CheckISO(GetIsoPath()); + + } else { + + bprintf(PRINT_NORMAL, _T(" Couldn't open %s \n"), GetIsoPath()); + return 0; + } + + } else { + + bprintf(PRINT_NORMAL, _T(" File doesn't have a valid ISO extension [ .iso / .ISO ] \n")); + return 0; + } + + return 1; +} + +int NeoCDInfo_Init() +{ + NeoCDInfo_Exit(); + return GetNeoGeoCD_Identifier(); +} + +TCHAR* NeoCDInfo_Text(int nText) +{ + if(!game || !IsNeoGeoCD() || !bDrvOkay) return NULL; + + switch(nText) + { + case DRV_NAME: return game->pszName; + case DRV_FULLNAME: return game->pszTitle; + case DRV_MANUFACTURER: return game->pszCompany; + case DRV_DATE: return game->pszYear; + } + + return NULL; +} + +int NeoCDInfo_ID() +{ + if(!game || !IsNeoGeoCD() || !bDrvOkay) return 0; + return game->id; +} + +void NeoCDInfo_Exit() +{ + if(game) { + free(game); + game = NULL; + } +} diff --git a/src/burner/win32/neocdlist.h b/src/burner/win32/neocdlist.h new file mode 100644 index 00000000..25dfd767 --- /dev/null +++ b/src/burner/win32/neocdlist.h @@ -0,0 +1,143 @@ +#ifndef _neocdlist_ +#define _neocdlist_ + +struct NGCDGAME +{ + TCHAR* pszName; // Short name + TCHAR* pszTitle; // Title + TCHAR* pszYear; // Release Year + TCHAR* pszCompany; // Developer + unsigned int id; // Game ID +}; + +NGCDGAME* GetNeoGeoCDInfo(unsigned int nID); +int GetNeoCDTitle(unsigned int nGameID); +void SetNeoCDTitle(TCHAR* pszTitle); +int GetNeoGeoCD_Identifier(); + +bool IsNeoGeoCD(); // neo_run.cpp +TCHAR* GetIsoPath(); // cd_isowav.cpp + +int NeoCDInfo_Init(); +TCHAR* NeoCDInfo_Text(int nText); +int NeoCDInfo_ID(); +void NeoCDInfo_Exit(); + +// ------------------------------------------------------ +// ISO9660 STUFF + +// ISO9660 date and time +struct iso9660_date +{ + unsigned char Year; // Number of year since 1900 + unsigned char Month; // Month (1 to 12) + unsigned char Day; // Day (1 to 31) + unsigned char Hour; // Hour (0 to 23) + unsigned char Minute; // Minute (0 to 59) + unsigned char Second; // Second (0 to 59) + unsigned char Zone; // Offset related to GMT, by 15-min interval (from -48 to +52) +}; + +// ISO9660 BCD date and time +struct iso9660_bcd_date +{ + unsigned char Year[4]; + unsigned char Month[2]; + unsigned char Day[2]; + unsigned char Hour[2]; + unsigned char Minute[2]; + unsigned char Second[2]; + unsigned char SecFrac[2]; + char Zone; +}; + +struct iso9660_DirectoryRecord +{ + unsigned char len_dr; // [1] Length of Directory Record (bytes) + unsigned char ext_attr_rec_len; // [1] Extended Attribute Record Length (bytes) + unsigned char location_of_extent[8]; // [8] [LEF / BEF] LBN / Sector location of the file data + unsigned char data_lenth[8]; // [8] [LEF / BEF] Length of the file section (bytes) + iso9660_date rec_date_time; // [7] Recording Date and Time + unsigned char file_flags; // [1] 8-bit flags + // [bit 0] File is Hidden if this bit is 1 + // [bit 1] Entry is a Directory if this bit is 1 + // [bit 2] Entry is an Associated file is this bit is 1 + // [bit 3] Information is structured according to the extended attribute record if this bit is 1 + // [bit 4] Owner, group and permissions are specified in the extended attribute record if this bit is 1 + // [bit 5] Reserved (0) + // [bit 6] Reserved (0) + // [bit 7] File has more than one directory record if this bit is 1 + unsigned char file_unit_size; // [1] This field is only valid if the file is recorded in interleave mode, otherwise this field is (00) + unsigned char int_gap_size; // [1] This field is only valid if the file is recorded in interleave mode, otherwise this field is (00) + unsigned char vol_seq_number[4]; // [4] The ordinal number of the volume in the Volume Set on which the file described by the directory record is recorded. + unsigned char len_fi; // [1] Length of File Identifier (LEN_FI) + char* file_id; // [LEN_FI] File Identifier +}; + +struct iso9660_PathTableRecord +{ + unsigned char len_di; // [1] Length of Directory Identifier + unsigned char extended_attr_len; // [1] Extended Attribute Record Length + unsigned char extent_location[4]; // [4] Extent Location (Sector) + unsigned char parent_dir_num; // [1] Parent Directory Number + char* directory_id; // [LEN_DI] Directory Identifier +}; + +// Volume Descriptor Header (Sector 16) +struct iso9660_VDH +{ + char vdtype; // [1] Volume Descriptor Type + unsigned char stdid[5]; // [5] ISO9660 Standard Identifier + char vdver; // [1] Volume Descriptor Version +}; + +// Primary Volume Descriptor (Volume Descriptor Type 1) +struct iso9660_PVD +{ + // ----------------------------- + // Volume Descriptor Header + char type; + unsigned char id[5]; + char version; + // ----------------------------- + // Primary Volume Descriptor + char unused1; + unsigned char system_id[32]; + unsigned char volume_id[32]; + unsigned char unused2[8]; + unsigned char volume_space_size[8]; + unsigned char unused3[32]; + unsigned char volume_set_size[4]; + unsigned char volume_sequence_number[4]; + unsigned char logical_block_size[4]; + unsigned char path_table_size[8]; + unsigned char type_l_path_table[4]; + unsigned char opt_type_l_path_table[4]; + unsigned char type_m_path_table[4]; + unsigned char opt_type_m_path_table[4]; + iso9660_DirectoryRecord root_directory_record; + unsigned char volume_set_id[128]; + unsigned char publisher_id[128]; + unsigned char preparer_id[128]; + unsigned char application_id[128]; + unsigned char copyright_file_id[37]; + unsigned char abstract_file_id[37]; + unsigned char bibliographic_file_id[37]; + + iso9660_bcd_date creation_date; // [17] + iso9660_bcd_date modification_date; // [17] + iso9660_bcd_date expiration_date; // [17] + iso9660_bcd_date effective_date; // [17] + + char file_structure_version; + char unused4; + unsigned char application_data[512]; + unsigned char unused5[643]; +}; + +void iso9660_ReadOffset(unsigned char *Dest, FILE* fp, unsigned int lOffset, unsigned int lSize, unsigned int lLength); + +// ------------------------------------------------------ + + +#endif diff --git a/src/burner/win32/neocdsel.cpp b/src/burner/win32/neocdsel.cpp new file mode 100644 index 00000000..6c983dba --- /dev/null +++ b/src/burner/win32/neocdsel.cpp @@ -0,0 +1,1323 @@ +// ---------------------------------------------------------------------------------------------------------- +// NEOCDSEL.CPP +#include "burner.h" +#include "png.h" +#include "neocdlist.h" + +#include + +int NeoCDList_Init(); +static void NeoCDList_InitListView(); +static int NeoCDList_CheckISO(HWND hList, TCHAR* pszFile); +static void NeoCDList_iso9660_CheckDirRecord(HWND hList, TCHAR* pszFile, FILE* fp, int nSector); +static int NeoCDList_AddGame(TCHAR* pszFile, unsigned int nGameID); +static void NeoCDList_ScanDir(HWND hList, TCHAR* pszDirectory); +static TCHAR* NeoCDList_ParseCUE(TCHAR* pszFile); +static void NeoCDList_ShowPreview(HWND hDlg, TCHAR* szFile, int nCtrID, int nFrameCtrID, float maxw, float maxh); +struct PNGRESOLUTION { int nWidth; int nHeight; }; +static PNGRESOLUTION GetPNGResolution(TCHAR* szFile); + +static INT_PTR CALLBACK NeoCDList_WndProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam); +static unsigned __stdcall NeoCDList_DoProc(void*); + +static HWND hNeoCDWnd = NULL; +static HWND hListView = NULL; +static HWND hProcParent = NULL; +static bool bProcessingList = false; +static HANDLE hProcessThread = NULL; +static unsigned ProcessThreadID = 0; + +static HBRUSH hWhiteBGBrush; + +bool bNeoCDListScanSub = false; +bool bNeoCDListScanOnlyISO = false; +TCHAR szNeoCDCoverDir[MAX_PATH] = _T("support\\neocdz\\"); +TCHAR szNeoCDGamesDir[MAX_PATH] = _T("\\neocdiso\\"); + +static int nSelectedItem = -1; + +struct GAMELIST { + unsigned int nID; + bool bFoundCUE; + TCHAR szPathCUE[256]; + TCHAR szPath[256]; + TCHAR szISOFile[256]; + int nAudioTracks; + TCHAR szTracks[99][256]; + TCHAR szShortName[32]; + TCHAR szPublisher[100]; +}; + +GAMELIST ngcd_list[100]; +int nListItems = 0; + +// Add game to List +static int NeoCDList_AddGame(TCHAR* pszFile, unsigned int nGameID) +{ + NGCDGAME* game; + game = (NGCDGAME*)malloc(sizeof(NGCDGAME)); + memset(game, 0, sizeof(NGCDGAME)); + + if(GetNeoGeoCDInfo(nGameID)) + { + memcpy(game, GetNeoGeoCDInfo(nGameID), sizeof(NGCDGAME)); + + TCHAR szNGCDID[12]; + _stprintf(szNGCDID, _T("%04X"), nGameID); + + LVITEM lvi; + ZeroMemory(&lvi, sizeof(lvi)); + + // NGCD-ID [Insert] + lvi.iImage = 0; + lvi.iItem = ListView_GetItemCount(hListView) + 1; + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvi.cchTextMax = 256; + TCHAR szTitle[256]; + _stprintf(szTitle, _T(" %s"), game->pszTitle); + lvi.pszText = szTitle; + + int nItem = ListView_InsertItem(hListView, &lvi); + + // TITLE + ZeroMemory(&lvi, sizeof(lvi)); + + lvi.iSubItem = 1; + lvi.iItem = nItem; + lvi.cchTextMax = _tcslen(game->pszTitle); + lvi.mask = LVIF_TEXT | LVIF_IMAGE; + lvi.pszText = szNGCDID; + + ListView_SetItem(hListView, &lvi); + + ngcd_list[nListItems].nID = nGameID; + + _tcscpy(ngcd_list[nListItems].szPath, pszFile); + _tcscpy(ngcd_list[nListItems].szShortName, game->pszName); + _stprintf(ngcd_list[nListItems].szPublisher, _T("%s (%s)"), game->pszCompany, game->pszYear); + + nListItems++; + + } else { + // error + return 0; + } + + if(game) { + free(game); + game = NULL; + } + return 1; +} + +static void NeoCDList_InitListView() +{ + LVCOLUMN LvCol; + ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT); + + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + + LvCol.cx = 445; + LvCol.pszText = _T("Title"); + SendMessage(hListView, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol); + + LvCol.cx = 70; + LvCol.pszText = _T("NGCD-ID"); + SendMessage(hListView, LVM_INSERTCOLUMN , 1, (LPARAM)&LvCol); + + // Setup ListView Icons +// HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR16, 0, 1); +// ListView_SetImageList(hListView, hImageList, LVSIL_SMALL); +// ImageList_AddMasked(hImageList, LoadBitmap(hAppInst, MAKEINTRESOURCE(BMP_CD)), RGB(255, 0, 255)); +} + +static int NeoCDList_CheckDuplicates(HWND hList, unsigned int nID) +{ + int nItemCount = ListView_GetItemCount(hList); + + for(int nItem = 0; nItem < nItemCount; nItem++) + { + unsigned int nItemVal = 0; + TCHAR szText[] = _T("0000"); + + ListView_GetItemText(hList, nItem, 1, szText, 5); + + _stscanf(szText, _T("%x"), &nItemVal); + + if(nItemVal == nID) { + ngcd_list[nItemCount].nAudioTracks = 0; + return 1; // let's get out of here... + } + } + + return 0; +} + +static void NeoCDList_iso9660_CheckDirRecord(HWND hList, TCHAR* pszFile, FILE* fp, int nSector) +{ + int nSectorLength = 2048; + //int nFile = 0; + unsigned int lBytesRead = 0; + //int nLen = 0; + unsigned int lOffset = 0; + bool bNewSector = false; + bool bRevisionQueve = false; + int nRevisionQueveID = 0; + + lOffset = (nSector * nSectorLength); + + unsigned char* nLenDR = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char* Flags = (unsigned char*)malloc(1 * sizeof(unsigned char)); + unsigned char* ExtentLoc = (unsigned char*)malloc(8 * sizeof(unsigned char)); + unsigned char* Data = (unsigned char*)malloc(0x10b * sizeof(unsigned char)); + unsigned char* LEN_FI = (unsigned char*)malloc(1 * sizeof(unsigned char)); + char *File = (char*)malloc(32 * sizeof(char)); + + while(1) + { + iso9660_ReadOffset(nLenDR, fp, lOffset, 1, sizeof(unsigned char)); + + if(nLenDR[0] == 0x22) { + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + continue; + } + + if(nLenDR[0] < 0x22) + { + if(bNewSector) + { + if(bRevisionQueve) { + bRevisionQueve = false; + + // make sure we don't add duplicates to the list + if(NeoCDList_CheckDuplicates(hList, nRevisionQueveID)) { + return; + } + + NeoCDList_AddGame(pszFile, nRevisionQueveID); + } + return; + } + + nLenDR[0] = 0; + iso9660_ReadOffset(nLenDR, fp, lOffset + 1, 1, sizeof(unsigned char)); + + if(nLenDR[0] < 0x22) { + lOffset += (2048 - lBytesRead); + lBytesRead = 0; + bNewSector = true; + continue; + } + } + + bNewSector = false; + + iso9660_ReadOffset(Flags, fp, lOffset + 25, 1, sizeof(unsigned char)); + + if(!(Flags[0] & (1 << 1))) + { + iso9660_ReadOffset(ExtentLoc, fp, lOffset + 2, 8, sizeof(unsigned char)); + + char szValue[9]; + sprintf(szValue, "%02x%02x%02x%02x", ExtentLoc[4], ExtentLoc[5], ExtentLoc[6], ExtentLoc[7]); + + unsigned int nValue = 0; + sscanf(szValue, "%x", &nValue); + + iso9660_ReadOffset(Data, fp, nValue * 2048, 0x10a, sizeof(unsigned char)); + + char szData[8]; + sprintf(szData, "%c%c%c%c%c%c%c", Data[0x100], Data[0x101], Data[0x102], Data[0x103], Data[0x104], Data[0x105], Data[0x106]); + + if(!strncmp(szData, "NEO-GEO", 7)) + { + _tcscpy(ngcd_list[nListItems].szISOFile, pszFile); + + char id[] = "0000"; + sprintf(id, "%02X%02X", Data[0x108], Data[0x109]); + + unsigned int nID = 0; + sscanf(id, "%x", &nID); + + iso9660_ReadOffset(LEN_FI, fp, lOffset + 32, 1, sizeof(unsigned char)); + + iso9660_ReadOffset((unsigned char*)File, fp, lOffset + 33, LEN_FI[0], sizeof(char)); + strncpy(File, File, LEN_FI[0]); + File[LEN_FI[0]] = 0; + + // King of Fighters '94, The (1994)(SNK)(JP) + // 10-6-1994 (P1.PRG) + if(nID == 0x0055 && Data[0x67] == 0xDE) { + // ...continue + } + + // King of Fighters '94, The (1994)(SNK)(JP-US) + // 11-21-1994 (P1.PRG) + if(nID == 0x0055 && Data[0x67] == 0xE6) { + // Change to custom revision id + nID = 0x1055; + } + + // King of Fighters '95, The (1995)(SNK)(JP-US)[!][NGCD-084 MT B01, B03-B06, NGCD-084E MT B01] + // 9-11-1995 (P1.PRG) + if(nID == 0x0084 && Data[0x6C] == 0xC0) { + // ... continue + } + + // King of Fighters '95, The (1995)(SNK)(JP-US)[!][NGCD-084 MT B10, NGCD-084E MT B03] + // 10-5-1995 (P1.PRG) + if(nID == 0x0084 && Data[0x6C] == 0xFF) { + // Change to custom revision id + nID = 0x1084; + } + + // King of Fighters '96 NEOGEO Collection, The + if(nID == 0x0229) { + bRevisionQueve = false; + + // make sure we don't add duplicates to the list + if(NeoCDList_CheckDuplicates(hList, nID)) { + return; + } + + NeoCDList_AddGame(pszFile, nID); + break; + } + + // King of Fighters '96, The + if(nID == 0x0214) { + bRevisionQueve = true; + nRevisionQueveID = nID; + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + continue; + } + + // make sure we don't add duplicates to the list + if(NeoCDList_CheckDuplicates(hList, nID)) { + return; + } + + NeoCDList_AddGame(pszFile, nID); + + //MessageBoxA(NULL, id, "", MB_OK); + break; + } + } + + lOffset += nLenDR[0]; + lBytesRead += nLenDR[0]; + } + + if (nLenDR) { + free(nLenDR); + nLenDR = NULL; + } + + if (Flags) { + free(Flags); + Flags = NULL; + } + + if (ExtentLoc) { + free(ExtentLoc); + ExtentLoc = NULL; + } + + if (Data) { + free(Data); + Data = NULL; + } + + if (LEN_FI) { + free(LEN_FI); + LEN_FI = NULL; + } + + if (File) { + free(File); + File = NULL; + } +} + +// Check the specified ISO, and proceed accordingly +static int NeoCDList_CheckISO(HWND hList, TCHAR* pszFile) +{ + if(!pszFile) { + // error + return 0; + } + + // Make sure we have a valid ISO file extension... + if(_tcsstr(pszFile, _T(".iso")) || _tcsstr(pszFile, _T(".ISO")) ) + { + FILE* fp = _tfopen(pszFile, _T("rb")); + if(fp) + { + // Read ISO and look for 68K ROM standard program header, ID is always there + // Note: This function works very quick, doesn't compromise performance :) + // it just read each sector first 264 bytes aproximately only. + + // Get ISO Size (bytes) + fseek(fp, 0, SEEK_END); + unsigned int lSize = 0; + lSize = ftell(fp); + rewind(fp); + + // If it has at least 16 sectors proceed + if(lSize > (2048 * 16)) + { + // Check for Standard ISO9660 Identifier + unsigned char IsoHeader[2048 * 16 + 1]; + unsigned char IsoCheck[6]; + + fread(IsoHeader, 1, 2048 * 16 + 1, fp); // advance to sector 16 and PVD Field 2 + fread(IsoCheck, 1, 5, fp); // get Standard Identifier Field from PVD + + // Verify that we have indeed a valid ISO9660 MODE1/2048 + if(!memcmp(IsoCheck, "CD001", 5)) + { + //bprintf(PRINT_NORMAL, _T(" Standard ISO9660 Identifier Found. \n")); + iso9660_VDH vdh; + + // Get Volume Descriptor Header + memset(&vdh, 0, sizeof(vdh)); + //memcpy(&vdh, iso9660_ReadOffset(fp, (2048 * 16), sizeof(vdh)), sizeof(vdh)); + iso9660_ReadOffset((unsigned char*)&vdh, fp, 2048 * 16, 1, sizeof(vdh)); + + // Check for a valid Volume Descriptor Type + if(vdh.vdtype == 0x01) + { +#if 0 +// This will fail on 64-bit due to differing variable sizes in the pvd struct + // Get Primary Volume Descriptor + iso9660_PVD pvd; + memset(&pvd, 0, sizeof(pvd)); + //memcpy(&pvd, iso9660_ReadOffset(fp, (2048 * 16), sizeof(pvd)), sizeof(pvd)); + iso9660_ReadOffset((unsigned char*)&pvd, fp, 2048 * 16, 1, sizeof(pvd)); + + // ROOT DIRECTORY RECORD + + // Handle Path Table Location + char szRootSector[32]; + unsigned int nRootSector = 0; + + sprintf(szRootSector, "%02X%02X%02X%02X", + pvd.root_directory_record.location_of_extent[4], + pvd.root_directory_record.location_of_extent[5], + pvd.root_directory_record.location_of_extent[6], + pvd.root_directory_record.location_of_extent[7]); + + // Convert HEX string to Decimal + sscanf(szRootSector, "%X", &nRootSector); +#else +// Just read from the file directly at the correct offset (0x8000 + 0x9e for the start of the root directory record) + unsigned char buffer[8]; + char szRootSector[4]; + unsigned int nRootSector = 0; + + fseek(fp, 0x809e, SEEK_SET); + fread(buffer, 1, 8, fp); + + sprintf(szRootSector, "%02x%02x%02x%02x", buffer[4], buffer[5], buffer[6], buffer[7]); + + sscanf(szRootSector, "%x", &nRootSector); +#endif + + // Process the Root Directory Records + NeoCDList_iso9660_CheckDirRecord(hList, pszFile, fp, nRootSector); + + // Path Table Records are not processed, since NeoGeo CD should not have subdirectories + // ... + } + } else { + + //bprintf(PRINT_NORMAL, _T(" Standard ISO9660 Identifier Not Found, cannot continue. \n")); + return 0; + } + } + } else { + + //bprintf(PRINT_NORMAL, _T(" Couldn't open %s \n"), GetIsoPath()); + return 0; + } + + if(fp) fclose(fp); + + } else { + + //bprintf(PRINT_NORMAL, _T(" File doesn't have a valid ISO extension [ .iso / .ISO ] \n")); + return 0; + } + + return 1; +} + +// Scan the specified directory for sub-directories that contain ISO / CUE files +static void NeoCDList_ScanDir(HWND hList, TCHAR* pszDirectory) +{ +// bProcessingList = true; + +// ListView_DeleteAllItems(hList); + + WIN32_FIND_DATA ffdDirectory; + + HANDLE hDirectory = NULL; + memset(&ffdDirectory, 0, sizeof(WIN32_FIND_DATA)); + + // Scan main dir for sub-directories + TCHAR szSearch[2048] = _T("\0"); + + _stprintf(szSearch, _T("%s*"), pszDirectory); + + hDirectory = FindFirstFile(szSearch, &ffdDirectory); + + if (hDirectory == INVALID_HANDLE_VALUE) { + // error + } else { + + do + { + // DIRECTORY + if((ffdDirectory.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + if(!_tcscmp(ffdDirectory.cFileName, _T(".")) || !_tcscmp(ffdDirectory.cFileName, _T(".."))) + { + // lets ignore " . " and " .. " + continue; + } + + TCHAR* pszISO = NULL; + pszISO = (TCHAR*)malloc(sizeof(TCHAR) * 512); + + bool bDone = false; + + WIN32_FIND_DATA ffdSubDirectory; + + HANDLE hSubDirectory = NULL; + memset(&ffdSubDirectory, 0, sizeof(WIN32_FIND_DATA)); + + TCHAR szSubSearch[512] = _T("\0"); + + if(!bNeoCDListScanOnlyISO) + { + + // Scan sub-directory for CUE + _stprintf(szSubSearch, _T("%s%s\\*.cue"), pszDirectory, ffdDirectory.cFileName); + + hSubDirectory = FindFirstFile(szSubSearch, &ffdSubDirectory); + + if (hSubDirectory == INVALID_HANDLE_VALUE) { + // error + } else { + + do + { + // Sub-directories only + if(!(ffdSubDirectory.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // File is CUE + if(_tcsstr(ffdSubDirectory.cFileName, _T(".cue")) || _tcsstr(ffdSubDirectory.cFileName, _T(".CUE"))) + { + // Parse CUE + TCHAR szParse[512] = _T("\0"); + _stprintf(szParse, _T("%s%s\\%s"), pszDirectory, ffdDirectory.cFileName, ffdSubDirectory.cFileName); + + //MessageBox(NULL, szParse, _T(""), MB_OK); + + pszISO = NeoCDList_ParseCUE( szParse ); + + TCHAR szISO[512] =_T("\0"); + _stprintf(szISO, _T("%s%s\\%s"), pszDirectory, ffdDirectory.cFileName, pszISO); + + NeoCDList_CheckISO(hList, szISO); + bDone = true; + + break; // no need to continue + } + } + } while(FindNextFile(hSubDirectory, &ffdSubDirectory)); + } + + if(pszISO) { + free(pszISO); + pszISO = NULL; + } + + if(bDone) { + FindClose(hSubDirectory); + continue; + } + } else { + if(!ngcd_list[nListItems].nAudioTracks) { + ngcd_list[nListItems].nAudioTracks = 0; + } + } + + hSubDirectory = NULL; + memset(&ffdSubDirectory, 0, sizeof(WIN32_FIND_DATA)); + + // Scan sub-directory for ISO + _stprintf(szSubSearch, _T("%s%s\\*.iso"), pszDirectory, ffdDirectory.cFileName); + + hSubDirectory = FindFirstFile(szSubSearch, &ffdSubDirectory); + + if (hSubDirectory == INVALID_HANDLE_VALUE) { + // error + } else { + + do + { + // Sub-directories only + if(!(ffdSubDirectory.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // File is ISO + if(_tcsstr(ffdSubDirectory.cFileName, _T(".iso")) || _tcsstr(ffdSubDirectory.cFileName, _T(".ISO"))) + { + TCHAR szISO[512] = _T("\0"); + _stprintf(szISO, _T("%s%s\\%s"), pszDirectory, ffdDirectory.cFileName, ffdSubDirectory.cFileName); + + NeoCDList_CheckISO(hList, szISO); + + break; // no need to continue + } + } + } while(FindNextFile(hSubDirectory, &ffdSubDirectory)); + } + } else { + // FILE + } + } while(FindNextFile(hDirectory, &ffdDirectory)); + } + FindClose(hDirectory); + +// bProcessingList = false; +} + +// Scan the specified directory for ISO / CUE files +static void NeoCDList_ScanSingleDir(HWND hList, TCHAR* pszDirectory) +{ +// bProcessingList = true; +// ListView_DeleteAllItems(hList); + + // + TCHAR* pszISO = NULL; + pszISO = (TCHAR*)malloc(sizeof(TCHAR) * 512); + + WIN32_FIND_DATA ffdDirectory; + + HANDLE hDirectory = NULL; + memset(&ffdDirectory, 0, sizeof(WIN32_FIND_DATA)); + + // Scan directory for CUE + TCHAR szSearch[512] = _T("\0"); + + if(!bNeoCDListScanOnlyISO) + { + _stprintf(szSearch, _T("%s*.cue"), pszDirectory); + + hDirectory = FindFirstFile(szSearch, &ffdDirectory); + + if (hDirectory == INVALID_HANDLE_VALUE) { + // error + } else { + + do + { + // Files only + if(!(ffdDirectory.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // File is CUE + if(_tcsstr(ffdDirectory.cFileName, _T(".cue")) || _tcsstr(ffdDirectory.cFileName, _T(".CUE"))) + { + // Parse CUE + TCHAR szParse[512] = _T("\0"); + _stprintf(szParse, _T("%s%s"), pszDirectory, ffdDirectory.cFileName); + + //MessageBox(NULL, szParse, _T(""), MB_OK); + + pszISO = NeoCDList_ParseCUE( szParse ); + + TCHAR szISO[512] =_T("\0"); + _stprintf(szISO, _T("%s%s"), pszDirectory, pszISO); + + NeoCDList_CheckISO(hList, szISO); + } + } + } while(FindNextFile(hDirectory, &ffdDirectory)); + + FindClose(hDirectory); + } + } else { + if(!ngcd_list[nListItems].nAudioTracks) { + ngcd_list[nListItems].nAudioTracks = 0; + } + } + + hDirectory = NULL; + memset(&ffdDirectory, 0, sizeof(WIN32_FIND_DATA)); + + // Scan directory for ISO + _stprintf(szSearch, _T("%s*.iso"), pszDirectory); + + hDirectory = FindFirstFile(szSearch, &ffdDirectory); + + if (hDirectory == INVALID_HANDLE_VALUE) { + // error + } else { + + do + { + // Files only + if(!(ffdDirectory.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // File is ISO + if(_tcsstr(ffdDirectory.cFileName, _T(".iso")) || _tcsstr(ffdDirectory.cFileName, _T(".ISO"))) + { + TCHAR szISO[512] = _T("\0"); + _stprintf(szISO, _T("%s%s"), pszDirectory, ffdDirectory.cFileName); + + NeoCDList_CheckISO(hList, szISO); + + } + } + } while(FindNextFile(hDirectory, &ffdDirectory)); + + FindClose(hDirectory); + } + + if (pszISO) { + free(pszISO); + pszISO = NULL; + } + +// bProcessingList = false; +} + + +// This will parse the specified CUE file and return the ISO path, if found +static TCHAR* NeoCDList_ParseCUE(TCHAR* pszFile) +{ + //if(!pszFile) return NULL; + + TCHAR* szISO = NULL; + szISO = (TCHAR*)malloc(sizeof(TCHAR) * 2048); + if(!szISO) return NULL; + + // open file + FILE* fp = NULL; + fp = _tfopen(pszFile, _T("r")); + + if(!fp) { + return NULL; + } + + while(!feof(fp)) + { + TCHAR szBuffer[2048]; + TCHAR szOriginal[2048]; + + _fgetts(szBuffer, sizeof(szBuffer), fp); + + // terminate string + szBuffer[260] = 0; + + if(!*szBuffer) { + return NULL; + } + + int nLength = 0; + nLength = _tcslen(szBuffer); + + // Remove ASCII control characters from the string (including the 'space' character) + while (szBuffer[nLength-1] < 32 && nLength > 0) + { + szBuffer[nLength-1] = 0; + nLength--; + } + + _tcscpy(szOriginal, szBuffer); + + if(!_tcsncmp(szBuffer, _T("FILE"), 4)) + { + TCHAR* pEnd = _tcsrchr(szBuffer, '"'); + if (!pEnd) { + break; // Invalid CUE format + } + + *pEnd = 0; + + TCHAR* pStart = _tcschr(szBuffer, '"'); + + if(!pStart) { + break; // Invalid CUE format + } + + if(!_tcsncmp(pEnd + 2, _T("BINARY"), 6)) + { + _tcscpy(szISO, pStart + 1); + ngcd_list[nListItems].bFoundCUE = true; + _tcscpy(ngcd_list[nListItems].szPathCUE, pszFile); + _tcscpy(ngcd_list[nListItems].szISOFile, pStart + 1); + } + + if (!_tcsncmp(pEnd + 2, _T("WAVE"), 5)) { + if(!ngcd_list[nListItems].nAudioTracks) { + ngcd_list[nListItems].nAudioTracks = 0; + } + + _tcscpy(ngcd_list[nListItems].szTracks[ngcd_list[nListItems].nAudioTracks], pStart + 1); + + ngcd_list[nListItems].nAudioTracks++; + } + } + } + if(fp) fclose(fp); + + return szISO; +} + +static PNGRESOLUTION GetPNGResolution(TCHAR* szFile) +{ + int width = 0; + int height = 0; + PNGRESOLUTION nResolution = { 0, 0 }; + png_structp png_ptr; + png_infop info_ptr; + char header[8]; + + FILE *fp = _tfopen(szFile, _T("rb")); + + if (!fp) { + return nResolution; + } + + fread(header, 1, 8, fp); + + if (png_sig_cmp((png_const_bytep)header, 0, 8)) { + return nResolution; + } + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) { + return nResolution; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + return nResolution; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + return nResolution; + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + + nResolution.nWidth = width; + nResolution.nHeight = height; + + fclose(fp); + + return nResolution; +} + +static void NeoCDList_ShowPreview(HWND hDlg, TCHAR* szFile, int nCtrID, int nFrameCtrID, float maxw, float maxh) +{ + PNGRESOLUTION PNGRes = { 0, 0 }; + if(!_tfopen(szFile, _T("rb"))) + { + HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(BMP_SPLASH), RT_BITMAP); + HGLOBAL hglobal = LoadResource(NULL, (HRSRC)hrsrc); + + BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)LockResource(hglobal); + + PNGRes.nWidth = pbmih->biWidth; + PNGRes.nHeight = pbmih->biHeight; + + FreeResource(hglobal); + + } else { + PNGRes = GetPNGResolution(szFile); + } + + // ------------------------------------------------------ + // PROPER ASPECT RATIO CALCULATIONS + + float w = (float)PNGRes.nWidth; + float h = (float)PNGRes.nHeight; + + //float maxw = 216; // + //float maxh = 150; // + + // max WIDTH + if(w > maxw) { + float nh = maxw * (float)(h / w); + float nw = maxw; + + // max HEIGHT + if(nh > maxh) { + nw = maxh * (float)(nw / nh); + nh = maxh; + } + + w = nw; + h = nh; + } + + // max HEIGHT + if(h > maxh) { + float nw = maxh * (float)(w / h); + float nh = maxh; + + // max WIDTH + if(nw > maxw) { + nh = maxw * (float)(nh / nw); + nw = maxw; + } + + w = nw; + h = nh; + } + + // Proper centering of preview + float x = ((maxw - w) / 2); + float y = ((maxh - h) / 2); + + RECT rc = {0, 0, 0, 0}; + GetWindowRect(GetDlgItem(hDlg, nFrameCtrID), &rc); + + POINT pt; + pt.x = rc.left; + pt.y = rc.top; + + ScreenToClient(hDlg, &pt); + + // ------------------------------------------------------ + + FILE* fp = _tfopen(szFile, _T("rb")); + + HBITMAP hCoverBmp = PNGLoadBitmap(hDlg, fp, (int)w, (int)h, 0); + + SetWindowPos(GetDlgItem(hDlg, nCtrID), NULL, (int)(pt.x + x), (int)(pt.y + y), 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + SendDlgItemMessage(hDlg, nCtrID, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hCoverBmp); + + if(fp) fclose(fp); + +} + +static void NeoCDList_Clean() +{ + NeoCDList_ShowPreview(hNeoCDWnd, _T(""), IDC_NCD_FRONT_PIC, IDC_NCD_FRONT_PIC_FRAME, 216, 150); + NeoCDList_ShowPreview(hNeoCDWnd, _T(""), IDC_NCD_BACK_PIC, IDC_NCD_BACK_PIC_FRAME, 216, 150); + + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTSHORT), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTPUBLISHER), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTIMAGE), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTAUDIO), _T("")); + + hProcessThread = NULL; + ProcessThreadID = 0; + + for(int x = 0; x < 100; x++) { + for(int y = 0; y < 99; y++) { + memset(&ngcd_list[x].szTracks[y], 0, sizeof(TCHAR) * 256); + } + ngcd_list[x].bFoundCUE = false; + } + memset(&ngcd_list, 0, (sizeof(GAMELIST) * 100)); + + hProcParent = NULL; + bProcessingList = false; + + nListItems = 0; + + nSelectedItem = -1; +} + +static HWND hNeoCDList_CoverDlg = NULL; +TCHAR szBigCover[512] = _T(""); + +static INT_PTR CALLBACK NeoCDList_CoverWndProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM /*lParam*/) +{ + if(Msg == WM_INITDIALOG) + { + hNeoCDList_CoverDlg = hDlg; + + NeoCDList_ShowPreview(hDlg, szBigCover, IDC_NCD_COVER_PREVIEW_PIC, IDC_NCD_COVER_PREVIEW_PIC, 580, 415); + + return TRUE; + } + + if(Msg == WM_CLOSE) + { + EndDialog(hDlg, 0); + hNeoCDList_CoverDlg = NULL; + } + + if(Msg == WM_COMMAND) + { + if (LOWORD(wParam) == WM_DESTROY) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + } + + return 0; +} + +void NeoCDList_InitCoverDlg() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_NCD_COVER_DLG), hNeoCDWnd, (DLGPROC)NeoCDList_CoverWndProc); +} + +static INT_PTR CALLBACK NeoCDList_WndProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if(Msg == WM_INITDIALOG) + { + hNeoCDWnd = hDlg; + + InitCommonControls(); + + hListView = GetDlgItem(hDlg, IDC_NCD_LIST); + + NeoCDList_InitListView(); + + HICON hIcon = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP)); + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); // Set the Game Selection dialog icon. + + hWhiteBGBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + + NeoCDList_ShowPreview(hNeoCDWnd, _T(""), IDC_NCD_FRONT_PIC, IDC_NCD_FRONT_PIC_FRAME, 216, 150); + NeoCDList_ShowPreview(hNeoCDWnd, _T(""), IDC_NCD_BACK_PIC, IDC_NCD_BACK_PIC_FRAME, 216, 150); + + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTSHORT), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTPUBLISHER), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTIMAGE), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTAUDIO), _T("")); + + CheckDlgButton(hNeoCDWnd, IDC_NCD_SSUBDIR_CHECK, bNeoCDListScanSub ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hNeoCDWnd, IDC_NCD_SISO_ONLY_CHECK, bNeoCDListScanOnlyISO ? BST_CHECKED : BST_UNCHECKED); + + TreeView_SetItemHeight(hListView, 40); + + SetWindowText(hDlg, _T(APP_TITLE) _T(SEPERATOR_1) _T("Neo Geo CDZ") _T(SEPERATOR_1) _T("Select Game")); + + hProcessThread = (HANDLE)_beginthreadex(NULL, 0, NeoCDList_DoProc, NULL, 0, &ProcessThreadID); + + WndInMid(hDlg, hScrnWnd); + SetFocus(hListView); + + return TRUE; + } + + if(Msg == WM_CLOSE) + { + NeoCDList_Clean(); + + DeleteObject(hWhiteBGBrush); + + hNeoCDWnd = NULL; + hListView = NULL; + + EndDialog(hDlg, 0); + } + + if (Msg == WM_CTLCOLORSTATIC) + { + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_LABELSHORT)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_LABELPUBLISHER)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_LABELIMAGE)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_LABELAUDIO)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTSHORT)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTPUBLISHER)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTIMAGE)) return (INT_PTR)hWhiteBGBrush; + if ((HWND)lParam == GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTAUDIO)) return (INT_PTR)hWhiteBGBrush; + } + + if (Msg == WM_NOTIFY) + { + NMLISTVIEW* pNMLV = (NMLISTVIEW*)lParam; + + // Game Selected + if (pNMLV->hdr.code == LVN_ITEMCHANGED && pNMLV->hdr.idFrom == IDC_NCD_LIST) + { + int iCount = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0); + int iSelCount = SendMessage(hListView, LVM_GETSELECTEDCOUNT, 0, 0); + + if(iCount == 0 || iSelCount == 0) return 1; + + TCHAR szID[] = _T("0000"); + + int iItem = pNMLV->iItem; + + LVITEM LvItem; + memset(&LvItem, 0, sizeof(LvItem)); + + LvItem.iItem = iItem; + LvItem.mask = LVIF_TEXT; + LvItem.iSubItem = 1; // id column + LvItem.pszText = szID; + LvItem.cchTextMax = sizeof(szID) + 1; + + SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)iItem, (LPARAM)&LvItem); + + //MessageBox(NULL, LvItem.pszText, _T(""), MB_OK); + + TCHAR szFront[512]; + TCHAR szBack[512]; + + _stprintf(szFront, _T("%s%s-front.png"), szNeoCDCoverDir, LvItem.pszText ); + _stprintf(szBack, _T("%s%s-back.png"), szNeoCDCoverDir, LvItem.pszText ); + + // Front / Back Cover preview + NeoCDList_ShowPreview(hNeoCDWnd, szFront, IDC_NCD_FRONT_PIC, IDC_NCD_FRONT_PIC_FRAME, 216, 150); + NeoCDList_ShowPreview(hNeoCDWnd, szBack, IDC_NCD_BACK_PIC, IDC_NCD_BACK_PIC_FRAME, 216, 150); + + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTSHORT), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTPUBLISHER), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTIMAGE), _T("")); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTAUDIO), _T("")); + + for(int nItem = 0; nItem < nListItems; nItem++) + { + unsigned int nID = 0; + _stscanf(szID, _T("%x"), &nID); + + TCHAR szAudioTracks[] =_T("0"); + + if(nID == ngcd_list[nItem].nID) { + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTSHORT), ngcd_list[nItem].szShortName); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTPUBLISHER), ngcd_list[nItem].szPublisher); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTIMAGE), ngcd_list[nItem].szISOFile); + _stprintf(szAudioTracks, _T("%d"), ngcd_list[nItem].nAudioTracks); + SetWindowText(GetDlgItem(hNeoCDWnd, IDC_NCD_TEXTAUDIO), szAudioTracks); + + nSelectedItem = nItem; + break; + } + } + + + } + + // Double Click + if (pNMLV->hdr.code == NM_DBLCLK && pNMLV->hdr.idFrom == IDC_NCD_LIST) + { + if(nSelectedItem >= 0) { + nCDEmuSelect = 0; + if(ngcd_list[nSelectedItem].bFoundCUE) { + _tcscpy(CDEmuImage, ngcd_list[nSelectedItem].szPathCUE); + } else { + _tcscpy(CDEmuImage, ngcd_list[nSelectedItem].szPath); + } + } else { + return 0; + } + + NeoCDList_Clean(); + + hNeoCDWnd = NULL; + hListView = NULL; + + EndDialog(hDlg, 0); + + BurnerLoadDriver(_T("neocdz")); + } + } + + if(Msg == WM_COMMAND) + { + if(HIWORD(wParam) == STN_CLICKED) + { + int nCtrlID = LOWORD(wParam); + + if(nCtrlID == IDC_NCD_FRONT_PIC) + { + if(nSelectedItem >= 0) { + _stprintf(szBigCover, _T("%s%04x-front.png"), szNeoCDCoverDir, ngcd_list[nSelectedItem].nID ); + + if(!_tfopen(szBigCover, _T("rb"))) { + szBigCover[0] = 0; + return 0; + } + } else { + return 0; + } + NeoCDList_InitCoverDlg(); + return 0; + } + + if(nCtrlID == IDC_NCD_BACK_PIC) + { + if(nSelectedItem >= 0) { + _stprintf(szBigCover, _T("%s%04x-back.png"), szNeoCDCoverDir, ngcd_list[nSelectedItem].nID ); + + if(!_tfopen(szBigCover, _T("rb"))) { + szBigCover[0] = 0; + return 0; + } + } else { + return 0; + } + NeoCDList_InitCoverDlg(); + return 0; + } + } + + if (LOWORD(wParam) == WM_DESTROY) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + + if(HIWORD(wParam) == BN_CLICKED) + { + int nCtrlID = LOWORD(wParam); + + switch(nCtrlID) + { + case IDC_NCD_PLAY_BUTTON: + { + if(nSelectedItem >= 0) { + nCDEmuSelect = 0; + if(ngcd_list[nSelectedItem].bFoundCUE) { + _tcscpy(CDEmuImage, ngcd_list[nSelectedItem].szPathCUE); + } else { + _tcscpy(CDEmuImage, ngcd_list[nSelectedItem].szPath); + } + } else { + break; + } + + NeoCDList_Clean(); + + DeleteObject(hWhiteBGBrush); + + hNeoCDWnd = NULL; + hListView = NULL; + + EndDialog(hDlg, 0); + + BurnerLoadDriver(_T("neocdz")); + break; + } + + case IDC_NCD_SCAN_BUTTON: + { + if(bProcessingList) break; + + NeoCDList_Clean(); + hProcessThread = (HANDLE)_beginthreadex(NULL, 0, NeoCDList_DoProc, NULL, 0, &ProcessThreadID); + SetFocus(hListView); + break; + } + + case IDC_NCD_SEL_DIR_BUTTON: + { + if(bProcessingList) break; + + NeoCDList_Clean(); + + SupportDirCreateTab(IDC_SUPPORTDIR_EDIT7, hNeoCDWnd); + hProcessThread = (HANDLE)_beginthreadex(NULL, 0, NeoCDList_DoProc, NULL, 0, &ProcessThreadID); + SetFocus(hListView); + break; + } + + case IDC_NCD_SSUBDIR_CHECK: + { + if(BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_NCD_SSUBDIR_CHECK)) { + bNeoCDListScanSub = true; + } else { + bNeoCDListScanSub = false; + } + + if(bProcessingList) break; + + NeoCDList_Clean(); + + hProcessThread = (HANDLE)_beginthreadex(NULL, 0, NeoCDList_DoProc, NULL, 0, &ProcessThreadID); + SetFocus(hListView); + break; + } + + case IDC_NCD_SISO_ONLY_CHECK: + { + if(BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_NCD_SISO_ONLY_CHECK)) { + bNeoCDListScanOnlyISO = true; + } else { + bNeoCDListScanOnlyISO = false; + } + + if(bProcessingList) break; + + NeoCDList_Clean(); + + hProcessThread = (HANDLE)_beginthreadex(NULL, 0, NeoCDList_DoProc, NULL, 0, &ProcessThreadID); + SetFocus(hListView); + break; + } + + case IDC_NCD_CANCEL_BUTTON: + { + NeoCDList_Clean(); + + DeleteObject(hWhiteBGBrush); + + hNeoCDWnd = NULL; + hListView = NULL; + + EndDialog(hDlg, 0); + break; + } + } + } + } + return 0; +} + +//static DWORD WINAPI NeoCDList_DoProc(LPVOID) +static unsigned __stdcall NeoCDList_DoProc(void*) +{ + if(bProcessingList) return 0; + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + bProcessingList = true; + ListView_DeleteAllItems(hListView); + + if(bNeoCDListScanSub) { + NeoCDList_ScanSingleDir(hListView, szNeoCDGamesDir); + NeoCDList_ScanDir(hListView, szNeoCDGamesDir); + } else { + NeoCDList_ScanSingleDir(hListView, szNeoCDGamesDir); + } + + bProcessingList = false; + + PostThreadMessage(ProcessThreadID, WM_APP + 0, 0, 0); + + // Wait for the thread to finish + if (WaitForSingleObject(hProcessThread, 10000) != WAIT_OBJECT_0) { + // If the thread doesn't finish within 10 seconds, forcibly kill it + TerminateThread(hProcessThread, 1); + bProcessingList = false; + } + + CloseHandle(hProcessThread); + hProcessThread = NULL; + ProcessThreadID = 0; + + return 0; +} + +int NeoCDList_Init() +{ + return FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_NCD_DLG), hScrnWnd, (DLGPROC)NeoCDList_WndProc); +} diff --git a/src/burner/win32/numdial.cpp b/src/burner/win32/numdial.cpp new file mode 100644 index 00000000..94f7dc93 --- /dev/null +++ b/src/burner/win32/numdial.cpp @@ -0,0 +1,1013 @@ +#include "burner.h" +#include + +const double PI = 3.14159265358979323846f; // Pi +const double DEGTORAD = 0.01745329251994329547f; // Degrees to Radians +const double RADTODEG = 57.29577951308232286465f; // Radians to Degrees + +static TCHAR* frDial = _T("Number of Frames"); + +static int nExitStatus; + +// ----------------------------------------------------------------------------- + +static INT_PTR CALLBACK DefInpProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) +{ + int nRet = 0; + BOOL fTrue = FALSE; + + switch (Msg) { + case WM_INITDIALOG: + nRet = nAudSegCount; + SetWindowText(hDlg, frDial); + SetDlgItemInt(hDlg, IDC_VALUE_EDIT, nRet, TRUE); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == ID_VALUE_CLOSE) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } else { + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + } + break; + + case WM_CLOSE: + nRet = GetDlgItemInt(hDlg, IDC_VALUE_EDIT, &fTrue, TRUE); + if (fTrue) { + nAudSegCount = nRet; + } + EndDialog(hDlg, 0); + } + + return 0; +} + +int NumDialCreate(int) +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_VALUE), hScrnWnd, (DLGPROC)DefInpProc); + + return 1; +} + +// ----------------------------------------------------------------------------- +// Gamma dialog + +static INT_PTR CALLBACK GammaProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + static double nPrevGamma; + + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + int nPos; + + nPrevGamma = nGamma; + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise gamma slider + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(1, 20000)); + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)200); + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)250); + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)7500); + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)10001); + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)12500); + + // Set slider to value of nGamma + if (nGamma > 1.0) { // Gamma > 1 + nPos = int((nGamma - 1.0) * 10000.0 + 10001.0); + } else { // Gamma < 1 + nPos = int(10000.0f - ((1.0 / nGamma) * 10000.0 - 10000.0)); + } + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nPos); + + // Set the edit control to the value of nGamma + _stprintf(szText, _T("%0.2f"), nGamma); + SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + // Update the screen + ComputeGammaLUT(); + if (bVidOkay) { + VidRedraw(); + VidPaint(0); + } + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bPoint = 0; + bool bValid = 1; + + if (SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (szText[i] == _T('.')) { + if (bPoint) { + bValid = 0; + break; + } + } else { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + } + + if (bValid) { + int nPos; + + nGamma = _tcstod(szText, NULL); + + // Set slider to value of nGamma + if (nGamma > 1.0) { // Gamma > 1 + nPos = int((nGamma - 1.0) * 10000.0 + 10001.0); + } else { // Gamma < 1 + nPos = int(10000.0 - ((1.0 / nGamma) * 10000.0 - 10000.0)); + } + SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nPos); + + // Update the screen + ComputeGammaLUT(); + if (bVidOkay) { + VidRedraw(); + VidPaint(0); + } + } + } + break; + } + break; + } + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + int nPos; + + // Update the contents of the edit control + nPos = SendDlgItemMessage(hDlg, IDC_GAMMA_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0); + if (nPos > 10000) { // Gamma > 1 + nGamma = 1.0 + (nPos - 10000.0) / 10000.0; + } else { // Gamma < 1 + nGamma = 1.0 / (1.0 + ((10001.0 - nPos) / 10000.0)); + } + _stprintf(szText, _T("%0.2f"), nGamma); + SendDlgItemMessage(hDlg, IDC_GAMMA_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + // Update the screen + ComputeGammaLUT(); + if (bVidOkay) { + VidRedraw(); + VidPaint(0); + } + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus != 1) { + nGamma = nPrevGamma; + } + EndDialog(hDlg, 0); + } + + return 0; +} + +void GammaDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_GAMMA), hScrnWnd, (DLGPROC)GammaProc); +} + +// ----------------------------------------------------------------------------- +// Scanline intensity dialog + +static INT_PTR CALLBACK ScanlineProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + static int nPrevIntensity; + + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + nPrevIntensity = nVidScanIntensity; + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise slider + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 255)); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)16); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)191); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)127); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63); + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidScanIntensity & 0xFF); + + // Set the edit control to current value + _stprintf(szText, _T("%i"), nVidScanIntensity & 0xFF); + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + // Update the screen + if (bDrvOkay) { + VidPaint(2); + } + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bValid = 1; + + if (SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + + if (bValid) { + nVidScanIntensity = _tcstol(szText, NULL, 0); + if (nVidScanIntensity < 0) { + nVidScanIntensity = 0; + } else { + if (nVidScanIntensity > 255) { + nVidScanIntensity = 255; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidScanIntensity); + + nVidScanIntensity |= (nVidScanIntensity << 8) | (nVidScanIntensity << 16); + + // Update the screen + if (bVidOkay) { + VidPaint(2); + } + } + } + break; + } + } + break; + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + + // Update the contents of the edit control + nVidScanIntensity = SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0); + _stprintf(szText, _T("%i"), nVidScanIntensity); + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + nVidScanIntensity |= (nVidScanIntensity << 8) | (nVidScanIntensity << 16); + // Update the screen + if (bVidOkay) { +// VidRedraw(); + VidPaint(2); + } + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus != 1) { + nVidScanIntensity = nPrevIntensity; + } + EndDialog(hDlg, 0); + break; + } + + return 0; +} + +void ScanlineDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCANLINE), hScrnWnd, (DLGPROC)ScanlineProc); +} + +// ----------------------------------------------------------------------------- +// Feedback intensity dialog +static INT_PTR CALLBACK PhosphorProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) // LPARAM lParam +{ + static int nPrevIntensity; + static int nPrevSaturation; + + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + nPrevIntensity = nVidFeedbackIntensity; + nPrevSaturation = nVidFeedbackOverSaturation; + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise sliders + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 255)); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)8); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)127); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)31); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)15); + + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 127)); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)4); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)63); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)31); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)15); + + // Set slider to current values + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackIntensity); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackOverSaturation); + + // Set the edit control to current values + _stprintf(szText, _T("%i"), nVidFeedbackIntensity); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + _stprintf(szText, _T("%i"), nVidFeedbackOverSaturation); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bValid = 1; + + switch (LOWORD(wParam)) { + case IDC_PHOSPHOR_1_EDIT: + if (SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + + if (bValid) { + nVidFeedbackIntensity = _tcstol(szText, NULL, 0); + if (nVidFeedbackIntensity < 0) { + nVidFeedbackIntensity = 0; + } else { + if (nVidFeedbackIntensity > 255) { + nVidFeedbackIntensity = 255; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackIntensity); + } + break; + case IDC_PHOSPHOR_2_EDIT: + if (SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + + if (bValid) { + nVidFeedbackOverSaturation = _tcstol(szText, NULL, 0); + if (nVidFeedbackOverSaturation < 0) { + nVidFeedbackOverSaturation = 0; + } else { + if (nVidFeedbackOverSaturation > 255) { + nVidFeedbackOverSaturation = 255; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nVidFeedbackOverSaturation); + + // Update the screen + if (bVidOkay) { + VidPaint(2); + } + } + break; + } + } + break; + } + } + break; + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + + // Update the contents of the edit control + switch (GetDlgCtrlID((HWND)lParam)) { + case IDC_PHOSPHOR_1_SLIDER: + nVidFeedbackIntensity = SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0); + _stprintf(szText, _T("%i"), nVidFeedbackIntensity); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_1_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + break; + case IDC_PHOSPHOR_2_SLIDER: + nVidFeedbackOverSaturation = SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0); + _stprintf(szText, _T("%i"), nVidFeedbackOverSaturation); + SendDlgItemMessage(hDlg, IDC_PHOSPHOR_2_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + break; + } + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus != 1) { + nVidFeedbackIntensity = nPrevIntensity; + nVidFeedbackOverSaturation = nPrevSaturation; + } + EndDialog(hDlg, 0); + break; + } + + return 0; +} + +void PhosphorDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_PHOSPHOR), hScrnWnd, (DLGPROC)PhosphorProc); +} + +// ----------------------------------------------------------------------------- +// Screen Angle dialog +static INT_PTR CALLBACK ScreenAngleProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static float fPrevScreenAngle, fPrevScreenCurvature; + static HWND hScreenAngleSlider, hScreenAngleEdit; + + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + fPrevScreenAngle = fVidScreenAngle; + fPrevScreenCurvature = fVidScreenCurvature; + hScreenAngleSlider = GetDlgItem(hDlg, IDC_SCREENANGLE_SLIDER); + hScreenAngleEdit = GetDlgItem(hDlg, IDC_SCREENANGLE_EDIT); + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise sliders + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 12000)); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)100); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)250); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)1000); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)2250); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)6000); + + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 12000)); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)150); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)375); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)3000); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)4500); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)6000); + + // Set sliders to current value + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenAngle * RADTODEG * 100.0f)); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenCurvature * RADTODEG * 150.0f)); + + // Set the edit controls to current value + _stprintf(szText, _T("%0.2f"), fVidScreenAngle * RADTODEG); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + _stprintf(szText, _T("%0.2f"), fVidScreenCurvature * RADTODEG); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + // Update the screen + if (bVidOkay) { + VidPaint(2); + } + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bPoint = 0; + bool bValid = 1; + + if ((HWND)lParam == hScreenAngleEdit) { + if (SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + } else { + if (SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (szText[i] == '.') { + if (bPoint) { + bValid = 0; + break; + } + } else { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + } + + if (bValid) { + if ((HWND)lParam == hScreenAngleEdit) { + fVidScreenAngle = _tcstod(szText, NULL) * DEGTORAD; + if (fVidScreenAngle < 0.0f) { + fVidScreenAngle = 0.0f; + } else { + if (fVidScreenAngle > PI / 1.5f) { + fVidScreenAngle = PI / 1.5f; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenAngle * RADTODEG * 100.0f)); + } else { + fVidScreenCurvature = _tcstod(szText, NULL) * DEGTORAD; + if (fVidScreenCurvature < 0.0f) { + fVidScreenCurvature = 0.0f; + } else { + if (fVidScreenCurvature > PI / 2.25f) { + fVidScreenCurvature = PI / 2.25f; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)(fVidScreenCurvature * RADTODEG * 150.0f)); + } + + // Update the screen + if (bVidOkay) { + VidPaint(2); + } + } + } + break; + } + } + break; + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + + // Update the contents of the edit control + if ((HWND)lParam == hScreenAngleSlider) { + fVidScreenAngle = (float)SendDlgItemMessage(hDlg, IDC_SCREENANGLE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) * DEGTORAD / 100.0f; + _stprintf(szText, _T("%0.2f"), fVidScreenAngle * RADTODEG); + SendDlgItemMessage(hDlg, IDC_SCREENANGLE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + } else { + fVidScreenCurvature = (float)SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) * DEGTORAD / 150.0f; + _stprintf(szText, _T("%0.2f"), fVidScreenCurvature * RADTODEG); + SendDlgItemMessage(hDlg, IDC_SCREENCURVATURE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + } + + // Update the screen + if (bVidOkay) { + VidPaint(0); + } + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus != 1) { + fVidScreenAngle = fPrevScreenAngle; + fVidScreenCurvature = fPrevScreenCurvature; + } + EndDialog(hDlg, 0); + break; + } + + return 0; +} + +void ScreenAngleDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCREENANGLE), hScrnWnd, (DLGPROC)ScreenAngleProc); +} + +// ----------------------------------------------------------------------------- +// CPU clock dialog + +static INT_PTR CALLBACK CPUClockProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise slider + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0x80, 0x0200)); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)0x05); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)0x10); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0100); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0120); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0140); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)0x0180); + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nBurnCPUSpeedAdjust); + + // Set the edit control to current value + _stprintf(szText, _T("%i"), nBurnCPUSpeedAdjust * 100 / 256); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bValid = 1; + int nValue; + + if (SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + + if (bValid) { + nValue = _tcstol(szText, NULL, 0); + if (nValue < 25) { + nValue = 25; + } else { + if (nValue > 400) { + nValue = 400; + } + } + + nValue = (int)((double)nValue * 256.0 / 100.0 + 0.5); + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)nValue); + } + } + break; + } + } + break; + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + int nValue; + + // Update the contents of the edit control + nValue = SendDlgItemMessage(hDlg, IDC_CPUCLOCK_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0); + nValue = (int)((double)nValue * 100.0 / 256.0 + 0.5); + _stprintf(szText, _T("%i"), nValue); + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus == 1) { + TCHAR szText[16] = _T(""); + + SendDlgItemMessage(hDlg, IDC_CPUCLOCK_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + nBurnCPUSpeedAdjust = _tcstol(szText, NULL, 0); + if (nBurnCPUSpeedAdjust < 25) { + nBurnCPUSpeedAdjust = 25; + } else { + if (nBurnCPUSpeedAdjust > 400) { + nBurnCPUSpeedAdjust = 400; + } + } + + nBurnCPUSpeedAdjust = (int)((double)nBurnCPUSpeedAdjust * 256.0 / 100.0 + 0.5); + } + EndDialog(hDlg, 0); + break; + } + + return 0; +} + +void CPUClockDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_CPUCLOCK), hScrnWnd, (DLGPROC)CPUClockProc); +} + +// ----------------------------------------------------------------------------- +// Cubic filter quality dialog + +static INT_PTR CALLBACK CubicProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + static double dPrevB, dPrevC; + + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[16]; + dPrevB = dVidCubicB; + dPrevC = dVidCubicC; + nExitStatus = 0; + + WndInMid(hDlg, hScrnWnd); + + // Initialise slider + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG(0, 10000)); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETLINESIZE, (WPARAM)0, (LPARAM)100); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)500); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)3333); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)5000); + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETTIC, (WPARAM)0, (LPARAM)7500); + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)((1.0 - dVidCubicB) * 10000)); + + // Set the edit control to current value + _stprintf(szText, _T("%.3lf"), 1.0 - dVidCubicB); + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + SetWindowText(hDlg, _T("Select desired filter sharpness")); + + // Update the screen + if (bDrvOkay) { + VidPaint(2); + } + + return TRUE; + } + case WM_COMMAND: { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + if (LOWORD(wParam) == IDOK) { + nExitStatus = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + nExitStatus = -1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case EN_UPDATE: { + if (nExitStatus == 0) { + TCHAR szText[16] = _T(""); + bool bPoint = 0; + bool bValid = 1; + + if (SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXTLENGTH, (WPARAM)0, (LPARAM)0) < 16) { + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_GETTEXT, (WPARAM)16, (LPARAM)szText); + } + + // Scan string in the edit control for illegal characters + for (int i = 0; szText[i]; i++) { + if (szText[i] == _T('.')) { + if (bPoint) { + bValid = 0; + break; + } + } else { + if (!_istdigit(szText[i])) { + bValid = 0; + break; + } + } + } + + if (bValid) { + dVidCubicB = 1.0 - _tcstod(szText, NULL); + if (dVidCubicB < 0.0) { + dVidCubicB = 0.0; + } else { + if (dVidCubicB > 1.0) { + dVidCubicB = 1.0; + } + } + + // Set slider to current value + SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_SETPOS, (WPARAM)true, (LPARAM)((1.0 - dVidCubicB) * 10000)); + + // Update the screen + if (bVidOkay) { + VidPaint(2); + } + } + } + break; + } + } + break; + } + + case WM_HSCROLL: { + switch (LOWORD(wParam)) { + case TB_BOTTOM: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + case TB_THUMBPOSITION: + case TB_THUMBTRACK: + case TB_TOP: { + if (nExitStatus == 0) { + TCHAR szText[16]; + + // Update the contents of the edit control + dVidCubicB = 1.0 - (double)SendDlgItemMessage(hDlg, IDC_SCANLINE_SLIDER, TBM_GETPOS, (WPARAM)0, (LPARAM)0) / 10000; + _stprintf(szText, _T("%.3lf"), 1.0 - dVidCubicB); + SendDlgItemMessage(hDlg, IDC_SCANLINE_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + // Update the screen + if (bVidOkay) { +// VidRedraw(); + VidPaint(2); + } + } + break; + } + } + break; + } + + case WM_CLOSE: + if (nExitStatus != 1) { + dVidCubicB = dPrevB; + dVidCubicC = dPrevC; + } + EndDialog(hDlg, 0); + break; + } + + return 0; +} + +void CubicSharpnessDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SCANLINE), hScrnWnd, (DLGPROC)CubicProc); +} + diff --git a/src/burner/win32/numpluscommas.cpp b/src/burner/win32/numpluscommas.cpp new file mode 100644 index 00000000..522571b1 --- /dev/null +++ b/src/burner/win32/numpluscommas.cpp @@ -0,0 +1,251 @@ +/* ------------------------------------------------------------------------------------------------ + Description: This module will add commas to a number and return it as TCHAR string + Author: CaptainCPS-X + Last update: Sep 18, 2008 + Originally for: FB alpha emulator UI features + Status: Positive and negative numbers are formatted with commas, so it's very complete + TODO: Optimize string management in the function. + ------------------------------------------------------------------------------------------------ */ +#include "burner.h" + +#define MAX_DIGITS 32 + +TCHAR* FormatCommasNumber(__int64 nNum) +{ + // Mixed Math & C++ Formula: + + // nNum = the big ass number + // S = the unformatted string containing the big ass number without commas + // L = string length / number of digits + // 3.0f = constant position of the commas + // R = main result, if this number is a decimal, this is the number of commas + // RS = string that will receive the result number as text for later comparison + // SC1 = comparison string 1 (see the formula / function for details) + // SC2 = comparison string 2 (see the formula / function for details) + // SC3 = comparison string 3 (see the formula / function for details) + // ISDEC1 = int acting as boolean + // ISDEC2 = int acting as boolean + // ISINT = int acting as boolean + + // ... other variable definitions should be easy to understand + + TCHAR szFinalText[256] = _T(""); + TCHAR S[MAX_PATH] = _T(""); + TCHAR RS[MAX_PATH] = _T(""); + TCHAR SC1[MAX_PATH] = _T(""); + TCHAR SC2[MAX_PATH] = _T(""); + TCHAR SC3[MAX_PATH] = _T(""); + unsigned int L = 0; + float R = 0.0f; + int ISDEC1 = 0; + int ISDEC2 = 0; + int ISINT = 0; + int nCompleteLength = 0; + int nCommaPos = 0; + int nFirstComma = 0; + bool bIsNegative = false; + + if(nNum < 0) bIsNegative = true; // Is a negative number + + _stprintf( S, _T("%I64d"), nNum); + + if(bIsNegative == true) { + TCHAR* szTemp = NULL; + szTemp = S; + _stprintf( S, _T("%s"), szTemp + 1); + } + + L = _tcslen(S); + R = (L / 3.0f); + + _stprintf( RS , _T("%1.1f") , R ); // x.x (could be a Integer 'x.0' or one of this decimal fractions 'x.7' , 'x.3') + _stprintf( SC1, _T("%i.7") , (L / 3) ); // x.6 [~x.7] (simulate the Decimal result xxx.6 for later comparison) + _stprintf( SC2, _T("%i.3") , (L / 3) ); // x.3 (simulate the Decimal result xxx.3 for later comparison) + _stprintf( SC3, _T("%i.0") , (L / 3) ); // x.0 (simulate the Integer result xxx.0 for later comparison) + + ISDEC1 = _tcscmp( RS, SC1 ); + ISDEC2 = _tcscmp( RS, SC2 ); + ISINT = _tcscmp( RS, SC3 ); + + if(ISDEC1 != 0 && ISDEC2 != 0 && ISINT == 0) { + R = R - 1.0f; + } + + nCompleteLength = L + (int)R; // Number of digits + number of commas + + if(ISDEC1 == 0 && ISDEC2 == 1) nFirstComma = 2; // 0.6 [~0.7] (.6 / .3 = 2) (place of the first comma from left to right) + if(ISDEC1 == -1 && ISDEC2 == 0) nFirstComma = 1; // 0.3 [~0.4] (.3 / .3 = 1) (place of the first comma from left to right) + if(ISDEC1 == -1 && ISDEC2 == -1) nFirstComma = 0; // x.0 (.0 / .3 = 0) (no place for a initial comma so start adding after 3 digits from left to right) + + TCHAR szTmp[2] = _T(""); + TCHAR szNumber[MAX_DIGITS] = _T(""); + TCHAR* pszTxt = NULL; + TCHAR szTxt2[MAX_DIGITS][2]; // array of digits characters + TCHAR szCommaString[MAX_DIGITS][2]; + int nCharStr = 0; + + _tcsncpy(szNumber, S, nCompleteLength); + + for(unsigned int nChar = 0; nChar < L; nChar++) { + pszTxt = szNumber; + _tcsncpy(szTxt2[nChar], pszTxt + nChar, 1); + } + + for(int nChar = 0; nChar < nCompleteLength; nChar++) { + // ADD COMMA AFTER 3 DIGITS + if(nFirstComma == 0 && nCommaPos == 3) { + // ADD COMMA + _tcsncpy(szCommaString[nCharStr], _T(","), 1); + // ADD NEXT NUMBER WAITING ON MEMORY AND CONTINUE LOOP + nCharStr = nCharStr + 1; + _tcsncpy(szCommaString[nCharStr], szTxt2[nChar], 1); + nCommaPos = 1; + nCharStr = nCharStr + 1; + } else { + // + if((nFirstComma != 1 && nFirstComma != 2)) { + // NO COMMAS SO ADD NUMBER... + _tcsncpy(szCommaString[nCharStr], szTxt2[nChar], 1); + } else { + // ADD COMMA AFTER 1 DIGIT + if(nFirstComma == 1 && nCommaPos == 1) { + _tcsncpy(szCommaString[nCharStr], _T(","), 1); + nFirstComma = 0; + nCommaPos = 0; + nCharStr = nCharStr + 1; + } + // ADD COMMA AFTER 2 DIGITS + if(nFirstComma == 2 && nCommaPos == 2) { + _tcsncpy(szCommaString[nCharStr], _T(","), 1); + nFirstComma = 0; + nCommaPos = 0; + nCharStr = nCharStr + 1; + } + // ADD NEXT NUMBER WAITING ON MEMORY AND CONTINUE LOOP + _tcsncpy(szCommaString[nCharStr], szTxt2[nChar], 1); + } + nCommaPos = nCommaPos + 1; + nCharStr = nCharStr + 1; + } + } + + _stprintf(szFinalText, _T("%s"), _T("")); + + for(int nChar = 0; nChar < nCompleteLength; nChar++) { + _tcsncpy(szTmp, szCommaString[nChar], 1); + _stprintf(szFinalText, _T("%s%s"), szFinalText, szTmp); // x + tmp + // x + x + tmp + // x + x + x + tmp ... + } + + TCHAR szNegative[1024] = _T(""); + if(bIsNegative == true) { + _stprintf(szNegative, _T("%s%s"), _T("-"), szFinalText); // add negative sign + } + + TCHAR* pszBuffer = NULL; + if(bIsNegative == true) { + pszBuffer = szNegative; + } else { + pszBuffer = szFinalText; + } + return (TCHAR*)pszBuffer; + + // -------------------------------------------------------------------------------------------------------------------------------------- + // NOTE!!!!: The following comments are personal notes I wrote here so I could keep up with my research + // it is not intended to be readed as standard C / C++, just see this as steps of various operations and calculations. + // -------------------------------------------------------------------------------------------------------------------------------------- + + // These are written test results I made before doing the formula ... + /* + + [ ] = operation or information holder + -> = next operation step + x = any number + nPreResult = preliminary result + Int = this means that the preliminary result is a Integer (Ex. 1.0) + Dec = this means that the preliminary result is a Decimal Fraction (Ex. 1.3) + nCommas = final number of commas the number will have + + xxx,xxx,xxx,xxx [ 12 digits ] -> [ nPreResult = (12 / 3.0f) = 4.0] -> [ Int ] -> [ nCommas = nPreResult - 1 ] -> [ 3 commas ] + xx,xxx,xxx,xxx [ 11 digits ] -> [ nPreResult = (11 / 3.0f) = 3.6] -> [ Dec ] -> [ nCommas = 3 ] -> [ 3 commas ] + x,xxx,xxx,xxx [ 10 digits ] -> [ nPreResult = (10 / 3.0f) = 3.3] -> [ Dec ] -> [ nCommas = 3 ] -> [ 3 commas ] + xxx,xxx,xxx [ 9 digits ] -> [ nPreResult = ( 9 / 3.0f) = 3.0] -> [ Int ] -> [ nCommas = nPreResult - 1 ] -> [ 2 commas ] + xx,xxx,xxx [ 8 digits ] -> [ nPreResult = ( 8 / 3.0f) = 2.6] -> [ Dec ] -> [ nCommas = 2 ] -> [ 2 commas ] + x,xxx,xxx [ 7 digits ] -> [ nPreResult = ( 7 / 3.0f) = 2.3] -> [ Dec ] -> [ nCommas = 2 ] -> [ 2 commas ] + xxx,xxx [ 6 digits ] -> [ nPreResult = ( 6 / 3.0f) = 2.0] -> [ Int ] -> [ nCommas = nPreResult - 1 ] -> [ 1 comma ] + xx,xxx [ 5 digits ] -> [ nPreResult = ( 5 / 3.0f) = 1.6] -> [ Dec ] -> [ nCommas = 1 ] -> [ 1 comma ] + x,xxx [ 4 digits ] -> [ nPreResult = ( 4 / 3.0f) = 1.3] -> [ Dec ] -> [ nCommas = 1 ] -> [ 1 comma ] + xxx [ 3 digits ] -> [ nPreResult = ( 3 / 3.0f) = 1.0] -> [ Int ] -> [ nCommas = nPreResult - 1 ] -> [ 0 commas ] + xx [ 2 digits ] -> [ nPreResult = ( 2 / 3.0f) = 0.6] -> [ Dec ] -> [ nCommas = 0 ] -> [ 0 commas ] + x [ 1 digits ] -> [ nPreResult = ( 1 / 3.0f) = 0.3] -> [ Dec ] -> [ nCommas = 0 ] -> [ 0 commas ] + + Number of Commas: + + The nCommas comes from the integer value of the decimal fraction, Example: + + If nPreResult is 1.6 , the final number of commas is 1 or 1.0, because where are not using the fraction value of 0.6 + + Placing Commas: + + Placing commas from left to right is made like from right to left, BUT before starting to count 3 digits and add + a comma we must complete one operation, this is of course if you wanna end with the commas in the right place =). + + Using the previous example, to start placing commas we have to use the decimal fraction value of 0.6. + We gonna divide (0.6 / 0.3) or (6 / 3) to get the number of digits at the left of the first comma, for + example: + + Lets say we wanna get the quantity of commas this number (10000) should have and we wanna place them from left to right + following my formula, and not the regular right to left method: + + First, count the digits: + + 10000 (5 digits) + + Second, divide the number of digits with 3 + + 5 / 3.0 = 1.6 + + Third, because the result is a decimal fraction we will not do the substraction of 1 and + we will separate each part of the result + + 1.0 (number of commas) + 0.6 (fraction piece we must use to know the number of digits at the left of the first comma) + + Fourth, divide the fraction number with 0.3 + + 0.6 / 0.3 = 2 (there will be 2 digits at the left of the first comma) + + Finally!, lets put the numbers from LEFT to RIGHT using the information we have ^^ + + nCommas = 1 ( number of commas) + nDigits = 2 (left digits before the first comma) + + nDigits ( 1 2 ) + | | + 1 0 , 0 0 0 + | + ( 1 ) nCommas + + The comma position operation rule applies only when we get a decimal fraction as a preliminar result, + if we have a integer as a preliminar result then there will be 3 digits at the left of + the first comma, for example: + + 100000 (6 digits) + + 6 / 3.0 = 2.0 (is integer lets follow the rule and substract 1) + + 2.0 - 1 = 1.0 (final number of commas) + + nCommas = 1 + nDigits = 3 (here the number of digits at the left of the first comma will be 3) + + nDigits ( 1 2 3) + | | | + 1 0 0 , 0 0 0 + | + ( 1 ) nCommas + + */ + // -------------------------------------------------------------------------------------------------------------------------------------- +} diff --git a/src/burner/win32/paletteviewer.cpp b/src/burner/win32/paletteviewer.cpp new file mode 100644 index 00000000..ec9bc323 --- /dev/null +++ b/src/burner/win32/paletteviewer.cpp @@ -0,0 +1,161 @@ +#include "burner.h" + +static HWND hPaletteViewerDlg = NULL; +static HWND hParent = NULL; +static HWND PaletteControl[256] = {NULL,}; +static HBRUSH PaletteBrush[256] = {NULL,}; + +static int nPalettePosition; +static int nPaletteEntries; + +static void CalcBrushes(int nStartColour) +{ + int Colour, r, g, b; + + for (int i = 0; i < 256; i++) { + DeleteObject(PaletteBrush[i]); + PaletteBrush[i] = NULL; + + if (i + nStartColour < nPaletteEntries) { + Colour = pBurnDrvPalette[i + nStartColour]; + r = (Colour & 0x7c00) >> 7; + g = (Colour & 0x3e0) >> 2; + b = (Colour & 0x1f) << 3; + PaletteBrush[i] = CreateSolidBrush(RGB(r, g, b)); + } + } +} + +static void UpdateLabels() +{ + TCHAR szItemText[10]; + + for (int i = 0; i < 16; i++) { + int nLabel = nPalettePosition + (i * 16); + szItemText[0] = _T('\0'); + _stprintf(szItemText, _T("%05X"), nLabel); + SendMessage(GetDlgItem(hPaletteViewerDlg, IDC_GFX_VIEWER_VERT_1 + i), WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + } +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + hPaletteViewerDlg = hDlg; + + if (bDrvOkay) { + if (!kNetGame && bAutoPause) bRunPause = 1; + AudSoundStop(); + } + + for (int y = 0; y < 16; y++) { + for (int x = 0; x < 16; x++) { + PaletteControl[(y * 16) + x] = CreateWindowEx(0, _T("STATIC"), NULL, WS_CHILD | WS_VISIBLE | SS_NOTIFY, (x * 21) + 38, (y * 21) + 21, 20, 20, hPaletteViewerDlg, NULL, NULL, NULL); + } + } + + nPaletteEntries = BurnDrvGetPaletteEntries(); + nPalettePosition = 0x0000; + CalcBrushes(nPalettePosition); + + WndInMid(hDlg, hParent); + SetFocus(hDlg); + + return TRUE; + } + + if (Msg == WM_CTLCOLORSTATIC) { + for (int i = 0; i < 256; i++) { + if ((HWND)lParam == PaletteControl[i]) { + return (INT_PTR)PaletteBrush[i]; + } + + } + } + + if (Msg == WM_CLOSE) { + for (int i = 0; i < 256; i++) { + DeleteObject(PaletteBrush[i]); + PaletteBrush[i] = NULL; + PaletteControl[i] = NULL; + } + + nPalettePosition = 0; + nPaletteEntries = 0; + + EndDialog(hPaletteViewerDlg, 0); + + EnableWindow(hScrnWnd, TRUE); + DestroyWindow(hPaletteViewerDlg); + + if (bDrvOkay) { + if(!bAltPause && bRunPause) bRunPause = 0; + AudSoundPlay(); + } + + return 0; + } + + if (Msg == WM_COMMAND) { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Notify == STN_CLICKED) { + TCHAR szText[50]; + + for (int i = 0; i < 256; i++) { + if ((HWND)lParam == PaletteControl[i]) { + int Colour, r, g, b; + + Colour = pBurnDrvPalette[i + nPalettePosition]; + r = (Colour & 0x7c00) >> 7; + g = (Colour & 0x3e0) >> 2; + b = (Colour & 0x1f) << 3; + + szText[0] = _T('\0'); + _stprintf(szText, _T("Selected colour: #%05X RGB #%02X%02X%02X"), i + nPalettePosition, r, g, b); + SendMessage(GetDlgItem(hPaletteViewerDlg, IDC_LABELCOMMENT), WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + return 0; + } + } + } + + if (Id == IDCANCEL && Notify == BN_CLICKED) { + SendMessage(hPaletteViewerDlg, WM_CLOSE, 0, 0); + return 0; + } + + if (Id == IDC_GFX_VIEWER_PREV && Notify == BN_CLICKED) { + nPalettePosition -= 0x100; + if (nPalettePosition < 0) nPalettePosition = nPaletteEntries - 0x100; + CalcBrushes(nPalettePosition); + RedrawWindow(hPaletteViewerDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + UpdateLabels(); + return 0; + } + + if (Id == IDC_GFX_VIEWER_NEXT && Notify == BN_CLICKED) { + nPalettePosition += 0x100; + if (nPalettePosition >= nPaletteEntries) nPalettePosition = 0x0000; + CalcBrushes(nPalettePosition); + RedrawWindow(hPaletteViewerDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + UpdateLabels(); + return 0; + } + } + + return 0; +} + +int PaletteViewerDialogCreate(HWND hParentWND) +{ + if (pBurnDrvPalette == NULL) return 1; + + hParent = hParentWND; + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_PALETTEVIEWER), hParent, (DLGPROC)DialogProc); + + hParent = NULL; + hPaletteViewerDlg = NULL; + + return 0; +} diff --git a/src/burner/win32/popup_win32.cpp b/src/burner/win32/popup_win32.cpp new file mode 100644 index 00000000..ed98c41f --- /dev/null +++ b/src/burner/win32/popup_win32.cpp @@ -0,0 +1,364 @@ +// Display a dialog containing error messages +#include "burner.h" +#include + +static TCHAR* pszBufferEnglish = NULL; +static TCHAR* pszBufferLocal = NULL; + +static int nBufferEnglishSize = 0; +static int nBufferLocalSize = 0; + +static int nPopupFlags; + +static HFONT hEditFont; +static int nIcon; + +// ---------------------------------------------------------------------------- +// Log the popup message to the debug log/console + +static int FBAPopupLog() +{ + TCHAR* pszTypeEnglish; + + switch (nPopupFlags & 7) { + case PUF_TYPE_ERROR: + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_ERROR, false); + break; + case PUF_TYPE_WARNING: + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_WARNING, false); + break; + default: + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_INFORMATION, false); + break; + } + + dprintf(_T("*** %s message:\n"), pszTypeEnglish); + + for (TCHAR* szText = pszBufferEnglish; ; ) { + int nLen; + + for (nLen = 0; szText[nLen] && szText[nLen] != _T('\n'); nLen++) { } + + if (nLen) { + TCHAR szFormat[16]; + _stprintf(szFormat, _T(" %%.%is\n"), nLen); + dprintf(szFormat, szText); + } + + if (!szText[nLen]) { + break; + } + + szText += nLen + 1; + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +static INT_PTR CALLBACK FBAPopupProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch (Msg) { + + // Grab the handle to the font we need to use + case WM_SETFONT: { + hEditFont = (HFONT)wParam; + break; + } + + case WM_DRAWITEM: { + if (((LPDRAWITEMSTRUCT)lParam)->CtlID == IDC_MESSAGE_ICON) { + DrawIconEx(((LPDRAWITEMSTRUCT)lParam)->hDC, 0, 0, (HICON)LoadImage(NULL, MAKEINTRESOURCE(nIcon), IMAGE_ICON, 0, 0, LR_LOADTRANSPARENT | LR_SHARED), 32, 32, 0, NULL, DI_NORMAL | DI_DEFAULTSIZE); + } + + break; + } + + case WM_INITDIALOG: { + int nBeep = -1; + TCHAR szCaption[1024] = _T(""); + TCHAR* pszTypeEnglish; + TCHAR* pszTypeLocal; + + nIcon = 0; + + switch (nPopupFlags & 7) { + case PUF_TYPE_ERROR: + nIcon = OIC_ERROR; + nBeep = MB_ICONHAND; + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_ERROR, false); + pszTypeLocal = FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true); + break; + case PUF_TYPE_WARNING: + nIcon = OIC_WARNING; + nBeep = MB_ICONEXCLAMATION; + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_WARNING, false); + pszTypeLocal = FBALoadStringEx(hAppInst, IDS_ERR_WARNING, true); + break; + default: + nIcon = OIC_INFORMATION; + nBeep = MB_ICONASTERISK; + pszTypeEnglish = FBALoadStringEx(hAppInst, IDS_ERR_INFORMATION, false); + pszTypeLocal = FBALoadStringEx(hAppInst, IDS_ERR_INFORMATION, true); + break; + } + + // Set the icon + SendDlgItemMessage(hDlg, IDC_MESSAGE_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(NULL, MAKEINTRESOURCE(nIcon), IMAGE_ICON, 32, 32, LR_SHARED)); + + // Set the caption + _sntprintf(szCaption, 1024, _T(APP_TITLE) _T(" %s"), pszTypeLocal); + SetWindowText(hDlg, szCaption); + + { + SIZE sizee = { 0, 0 }; + SIZE sizel = { 0, 0 }; + POINT p = { 0, 0 }; + RECT rect; + HWND hWnd; + + { + hWnd = GetDlgItem(hDlg, IDC_MESSAGE_EDIT_ENG); + HDC hDC = GetDC(hWnd); + HFONT hFont = (HFONT)SelectObject(hDC, hEditFont); + + for (TCHAR* szText = pszBufferEnglish; ; ) { + + SIZE line; + int nLen; + + for (nLen = 0; szText[nLen] && szText[nLen] != _T('\n'); nLen++) { } + + GetTextExtentPoint32(hDC, szText, nLen ? nLen : 1, &line); + + if (sizee.cx < line.cx) { + sizee.cx = line.cx; + } + sizee.cy += line.cy; + + if (!szText[nLen]) { + break; + } + + szText += nLen + 1; + } + + if (bLocalisationActive && pszBufferLocal) { + for (TCHAR* szText = pszBufferLocal; ; ) { + + SIZE line; + int nLen; + + for (nLen = 0; szText[nLen] && szText[nLen] != _T('\n'); nLen++) { } + + GetTextExtentPoint32(hDC, szText, nLen ? nLen : 1, &line); + + if (sizel.cx < line.cx) { + sizel.cx = line.cx; + } + sizel.cy += line.cy; + + if (!szText[nLen]) { + break; + } + + szText += nLen + 1; + } + } + + SelectObject(hDC, hFont); + ReleaseDC(hWnd, hDC); + } + + // Set minimum size if needed + hWnd = GetDlgItem(hDlg, IDOK); + GetWindowRect(hWnd, &rect); + if (sizee.cx < (rect.right - rect.left)) { + sizee.cx = rect.right - rect.left; + } + + ClientToScreen(hDlg, &p); + GetWindowRect(hDlg, &rect); + + // Size dialog and edit control containing message text + if (bLocalisationActive && pszBufferLocal) { + + if (sizel.cx < sizee.cx) { + sizel.cx = sizee.cx; + } else { + sizee.cx = sizel.cx; + } + if (sizel.cy < 32) { + sizel.cy = 32; + } + + MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left + sizee.cx, rect.bottom - rect.top + sizee.cy + sizel.cy + 12, FALSE); + + hWnd = GetDlgItem(hDlg, IDC_MESSAGE_EDIT_LOCAL); + GetWindowRect(hWnd, &rect); + SetWindowPos(hWnd, NULL, 0, 0, rect.right - rect.left + sizel.cx, rect.bottom - rect.top + sizel.cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW); + SendMessage(hWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)pszBufferLocal); + SendMessage(hWnd, EM_SETMARGINS, EC_LEFTMARGIN, 3); + ShowWindow(hWnd, SW_SHOW); + + hWnd = GetDlgItem(hDlg, IDC_MESSAGE_BACK); + SetWindowPos(hWnd, NULL, 0, 0, 9999, rect.bottom - p.y + sizel.cy + 6, SWP_NOZORDER | SWP_NOREDRAW); + ShowWindow(hWnd, SW_SHOW); + + p.y -= rect.bottom - rect.top + sizel.cy + 12; + } else { + if (sizee.cy < 32) { + sizee.cy = 32; + } + + MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left + sizee.cx, rect.bottom - rect.top + sizee.cy, FALSE); + } + + hWnd = GetDlgItem(hDlg, IDC_MESSAGE_EDIT_ENG); + SendMessage(hWnd, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_3DFACE)); + GetWindowRect(hWnd, &rect); + SetWindowPos(hWnd, NULL, rect.left - p.x, rect.top - p.y, rect.right - rect.left + sizee.cx, rect.bottom - rect.top + sizee.cy, (pszBufferLocal ? 0 : SWP_NOMOVE) | SWP_NOZORDER | SWP_NOREDRAW); + SendMessage(hWnd, WM_SETTEXT, (WPARAM)0, (LPARAM)pszBufferEnglish); + SendMessage(hWnd, EM_SETMARGINS, EC_LEFTMARGIN, 3); + + // Center button + GetClientRect(hDlg, &rect); + p.x = (rect.right - rect.left) / 2; + hWnd = GetDlgItem(hDlg, IDOK); + GetWindowRect(hWnd, &rect); + SetWindowPos(hWnd, NULL, p.x - (rect.right - rect.left) / 2, rect.top - p.y + sizee.cy, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + } + + WndInMid(hDlg, hScrnWnd); + SetForegroundWindow(hDlg); + MessageBeep(nBeep); + + return TRUE; + } + case WM_COMMAND: { + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + case WM_CLOSE: { + EndDialog(hDlg, 0); + break; + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +int FBAPopupAddText(int nFlags, TCHAR* pszFormat, ...) +{ + TCHAR szString[1024] = _T(""); + TCHAR* pszStringEnglish; + + va_list vaEnglish; + va_start(vaEnglish, pszFormat); + + if (IS_INTRESOURCE(pszFormat)) { + pszStringEnglish = FBALoadStringEx(hAppInst, (INT_PTR)pszFormat, false); + } else { + pszStringEnglish = pszFormat; + } + + // See if we need to load strings from reources + if (nFlags & PUF_TEXT_TRANSLATE) { + TCHAR* pszStringLocal; + + va_list vaLocal; + va_start(vaLocal, pszFormat); + + if (IS_INTRESOURCE(pszFormat)) { + pszStringLocal = FBALoadStringEx(hAppInst, (INT_PTR)pszFormat, true); + } else { + pszStringLocal = pszFormat; + } + + // Add the translated string if present + if (bLocalisationActive && (nFlags & PUF_TEXT_TRANSLATE) && pszStringLocal && *pszStringLocal) { + // Add the translated string + int nLen = _vsntprintf(szString, 1024, pszStringLocal, vaLocal); + if (nLen > 0) { + TCHAR* pszNewBuffer = (TCHAR*)realloc(pszBufferLocal, (nLen + nBufferLocalSize + 1) * sizeof(TCHAR)); + if (pszNewBuffer) { + pszBufferLocal = pszNewBuffer; + _tcsncpy(pszBufferLocal + nBufferLocalSize, szString, nLen); + nBufferLocalSize += nLen; + pszBufferLocal[nBufferLocalSize] = 0; + } + } + } + + va_end(vaLocal); + } + + // Add the English language string + if (pszStringEnglish && *pszStringEnglish) { + int nLen = _vsntprintf(szString, 1024, pszStringEnglish, vaEnglish); + if (nLen > 0) { + TCHAR* pszNewBuffer = (TCHAR*)realloc(pszBufferEnglish, (nLen + nBufferEnglishSize + 1) * sizeof(TCHAR)); + if (pszNewBuffer) { + pszBufferEnglish = pszNewBuffer; + _tcsncpy(pszBufferEnglish + nBufferEnglishSize, szString, nLen); + nBufferEnglishSize += nLen; + pszBufferEnglish[nBufferEnglishSize] = 0; + } + } + } + + va_end(vaEnglish); + + return 0; +} + +int FBAPopupDestroyText() +{ + if (pszBufferEnglish) { + free(pszBufferEnglish); + pszBufferEnglish = NULL; + } + nBufferEnglishSize = 0; + + if (pszBufferLocal) { + free(pszBufferLocal); + pszBufferLocal = NULL; + } + nBufferLocalSize = 0; + + return 0; +} + +// ---------------------------------------------------------------------------- + +int FBAPopupDisplay(int nFlags) +{ + HMODULE hRiched = NULL; + +#if defined (_UNICODE) + hRiched = LoadLibrary(L"RICHED20.DLL"); +#else + hRiched = LoadLibrary("RICHED20.DLL"); +#endif + + nPopupFlags = nFlags; + + SplashDestroy(true); + + FBAPopupLog(); + + if (!(nPopupFlags & PUF_TYPE_LOGONLY) && hRiched) { + DialogBox(hAppInst, MAKEINTRESOURCE(IDD_POPUP), hScrnWnd, (DLGPROC)FBAPopupProc); + FreeLibrary(hRiched); + hRiched = NULL; + } + + FBAPopupDestroyText(); + + return 1; +} diff --git a/src/burner/win32/progress.cpp b/src/burner/win32/progress.cpp new file mode 100644 index 00000000..d4092463 --- /dev/null +++ b/src/burner/win32/progress.cpp @@ -0,0 +1,202 @@ +#include "burner.h" +#include + +static HWND hProgressDlg = NULL; +static HANDLE hProgressThread = NULL; +static unsigned ProgressThreadID = 0; + +int nProgressPosBurn, nProgressPosBurner; +int nProgressMin, nProgressMax; + +static HANDLE hEvent = NULL; + +// ---------------------------------------------------------------------------- +// Callbacks for burn library + +static int __cdecl ProgressSetRangeBurn(double dProgressRange) +{ + if (hProgressThread == NULL || hProgressDlg == NULL) { + return 1; + } + + nProgressMin = -(int)((double)nProgressMax * dProgressRange); + SendDlgItemMessage(hProgressDlg, IDC_WAIT_PROG, PBM_SETRANGE32, nProgressMin, nProgressMax); + + return 0; +} + +static int __cdecl ProgressUpdateBurn(double dProgress, const TCHAR* pszText, bool bAbs) +{ + if (hProgressThread == NULL || hProgressDlg == NULL) { + return 1; + } + + if (pszText) { + SendDlgItemMessage(hProgressDlg, IDC_WAIT_LABEL_B2, WM_SETTEXT, 0, (LPARAM)pszText); + SetWindowText(hScrnWnd, pszText); + } + + if (bAbs) { + nProgressPosBurn = (int)((double)(-nProgressMin) * dProgress); + if (nProgressPosBurn > -nProgressMin) { + nProgressPosBurn = -nProgressMin; + } + SendDlgItemMessage(hProgressDlg, IDC_WAIT_PROG, PBM_SETPOS, (WPARAM)(nProgressMin + nProgressPosBurn + nProgressPosBurner), 0); + } else { + if (dProgress) { + nProgressPosBurn += (int)((double)(-nProgressMin) * dProgress); + if (nProgressPosBurn > -nProgressMin) { + nProgressPosBurn = -nProgressMin; + } + SendDlgItemMessage(hProgressDlg, IDC_WAIT_PROG, PBM_SETPOS, (WPARAM)(nProgressMin + nProgressPosBurn + nProgressPosBurner), 0); + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Callback for burner + +int ProgressUpdateBurner(double dProgress, const TCHAR* pszText, bool bAbs) +{ + if (hProgressThread == NULL || hProgressDlg == NULL) { + return 1; + } + + if (pszText) { + SendDlgItemMessage(hProgressDlg, IDC_WAIT_LABEL_B2, WM_SETTEXT, 0, (LPARAM)pszText); + SetWindowText(hScrnWnd, pszText); + } + + if (bAbs) { + nProgressPosBurner = (int)((double)nProgressMax * dProgress); + if (nProgressPosBurner > nProgressMax) { + nProgressPosBurner = nProgressMax; + } + SendDlgItemMessage(hProgressDlg, IDC_WAIT_PROG, PBM_SETPOS, (WPARAM)(nProgressMin + nProgressPosBurn + nProgressPosBurner), 0); + } else { + if (dProgress) { + if (nProgressPosBurner > nProgressMax) { + nProgressPosBurner = nProgressMax; + } + nProgressPosBurner += (int)((double)nProgressMax * dProgress); + SendDlgItemMessage(hProgressDlg, IDC_WAIT_PROG, PBM_SETPOS, (WPARAM)(nProgressMin + nProgressPosBurn + nProgressPosBurner), 0); + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Code that runs in a seperate thread + +static INT_PTR CALLBACK ProgressProc(HWND hDlg, UINT Msg, WPARAM /*wParam*/, LPARAM /*lParam*/) +{ + if (Msg == WM_INITDIALOG) { + TCHAR szText[128] = _T(""); + + hProgressDlg = hDlg; + + SendDlgItemMessage(hDlg, IDC_WAIT_PROG, PBM_SETRANGE32, nProgressMin, nProgressMax); + + _stprintf(szText, FBALoadStringEx(hAppInst, IDS_PROGRESS_LOADING, true), BurnDrvGetText(DRV_NAME)); + SendDlgItemMessage(hDlg, IDC_WAIT_LABEL_B1, WM_SETTEXT, 0, (LPARAM)szText); + + ShowWindow(GetDlgItem(hDlg, IDC_WAIT_LABEL_B1), TRUE); + ShowWindow(GetDlgItem(hDlg, IDC_WAIT_LABEL_B2), TRUE); + + WndInMid(hDlg, hScrnWnd); + SetForegroundWindow(hDlg); + SetWindowPos(hDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + return TRUE; + } + + return 0; +} + +static unsigned __stdcall DoProgress(void*) +{ + MSG msg; + + // Raise the thread priority for this thread + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + nProgressMin = 0; + nProgressMax = 1 << 30; + + nProgressPosBurn = 0; + nProgressPosBurner = 0; + + BurnExtProgressRangeCallback = ProgressSetRangeBurn; + BurnExtProgressUpdateCallback = ProgressUpdateBurn; + + FBACreateDialog(hAppInst, MAKEINTRESOURCE(IDD_WAIT), NULL, (DLGPROC)ProgressProc); + + if (hEvent) { + SetEvent(hEvent); + } + + while (GetMessage(&msg, NULL, 0, 0)) { + + // See if we need to end the thread + if (msg.message == (WM_APP + 0)) { + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + DestroyWindow(hProgressDlg); + + return 0; +} + +// ---------------------------------------------------------------------------- + +int ProgressCreate() +{ + if (hProgressDlg || hProgressThread) { + return 1; + } + + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + hProgressThread = (HANDLE)_beginthreadex(NULL, 0, DoProgress, NULL, 0, &ProgressThreadID); + + WaitForSingleObject(hEvent, 15000); + + CloseHandle(hEvent); + hEvent = NULL; + + return 0; +} + +int ProgressDestroy() +{ + if (hProgressThread) { + + // Signal the prgress thread to end + PostThreadMessage(ProgressThreadID, WM_APP + 0, 0, 0); + + // Wait for the thread to finish + if (WaitForSingleObject(hProgressThread, 15000) != WAIT_OBJECT_0) { + // If the thread doesn't finish within 15 seconds, forcibly kill it + TerminateThread(hProgressThread, 1); + } + + BurnExtProgressRangeCallback = NULL; + BurnExtProgressUpdateCallback = NULL; + + hProgressDlg = NULL; + + CloseHandle(hProgressThread); + + hProgressThread = NULL; + ProgressThreadID = 0; + } + + return 0; +} diff --git a/src/burner/win32/replay.cpp b/src/burner/win32/replay.cpp new file mode 100644 index 00000000..7c5dd11f --- /dev/null +++ b/src/burner/win32/replay.cpp @@ -0,0 +1,375 @@ +// Functions for recording & replaying input +#include "burner.h" +#include "dynhuff.h" +#include + +int nReplayStatus = 0; + +static unsigned int nStartFrame; +static unsigned int nEndFrame; + +static FILE* fp = NULL; +static int nSizeOffset; + +static short nPrevInputs[0x0100]; + +int RecordInput() +{ + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + for (unsigned int i = 0; i < nGameInpCount; i++) { + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal) { + if (bii.nType & BIT_GROUP_ANALOG) { + if (*bii.pShortVal != nPrevInputs[i]) { + EncodeBuffer(i); + EncodeBuffer(*bii.pShortVal >> 8); + EncodeBuffer(*bii.pShortVal & 0xFF); + nPrevInputs[i] = *bii.pShortVal; + } + } else { + if (*bii.pVal != nPrevInputs[i]) { + EncodeBuffer(i); + EncodeBuffer(*bii.pVal); + nPrevInputs[i] = *bii.pVal; + } + } + } + } + + EncodeBuffer(0xFF); + return 0; +} + +int ReplayInput() +{ + unsigned char n; + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + // Just to be safe, restore the inputs to the known correct settings + for (unsigned int i = 0; i < nGameInpCount; i++) { + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal) { + if (bii.nType & BIT_GROUP_ANALOG) { + *bii.pShortVal = nPrevInputs[i]; + } else { + *bii.pVal = nPrevInputs[i]; + } + } + } + + // Now read all inputs that need to change from the .fr file + while ((n = DecodeBuffer()) != 0xFF) { + BurnDrvGetInputInfo(&bii, n); + if (bii.pVal) { + if (bii.nType & BIT_GROUP_ANALOG) { + *bii.pShortVal = nPrevInputs[n] = (DecodeBuffer() << 8) | DecodeBuffer(); + } else { + *bii.pVal = nPrevInputs[n] = DecodeBuffer(); + } + } else { + DecodeBuffer(); + } + } + + if (end_of_buffer) { + StopReplay(); + return 1; + } else { + return 0; + } +} + +static void MakeOfn(TCHAR* pszFilter) +{ + _stprintf(pszFilter, FBALoadStringEx(hAppInst, IDS_DISK_FILE_REPLAY, true), _T(APP_TITLE)); + memcpy(pszFilter + _tcslen(pszFilter), _T(" (*.fr)\0*.fr\0\0"), 14 * sizeof(TCHAR)); + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFilter = pszFilter; + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T(".\\recordings"); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("fr"); + + return; +} + +int StartRecord() +{ + TCHAR szFilter[1024]; + + int nRet; + int bOldPause; + + fp = NULL; + + _stprintf(szChoice, _T("%s"), BurnDrvGetText(DRV_NAME)); + MakeOfn(szFilter); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_REPLAY_RECORD, true); + ofn.Flags |= OFN_OVERWRITEPROMPT; + + bOldPause = bRunPause; + bRunPause = 1; + nRet = GetSaveFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + + { + const char szFileHeader[] = "FB1 "; // File identifier + fp = _tfopen(szChoice, _T("wb")); + + nRet = 0; + if (fp == NULL) { + nRet = 1; + } else { + fwrite(&szFileHeader, 1, 4, fp); + nRet = BurnStateSaveEmbed(fp, -1, 1); + if (nRet >= 0) { + const char szChunkHeader[] = "FR1 "; // Chunk identifier + int nZero = 0; + + fwrite(&szChunkHeader, 1, 4, fp); // Write chunk identifier + + nSizeOffset = ftell(fp); + + fwrite(&nZero, 1, 4, fp); // reserve space for chunk size + + fwrite(&nZero, 1, 4, fp); // reserve space for number of frames + + fwrite(&nZero, 1, 4, fp); // reserved + fwrite(&nZero, 1, 4, fp); // + fwrite(&nZero, 1, 4, fp); // + + nRet = EmbedCompressedFile(fp, -1); + } + } + } + + if (nRet) { + if (fp) { + fclose(fp); + fp = NULL; + } + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_CREATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_REPLAY)); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } else { + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + nReplayStatus = 1; // Set record status + MenuEnableItems(); + + nStartFrame = GetCurrentFrame(); + + // Create a baseline so we can just record the deltas afterwards + for (unsigned int i = 0; i < nGameInpCount; i++) { + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal) { + if (bii.nType & BIT_GROUP_ANALOG) { + EncodeBuffer(*bii.pShortVal >> 8); + EncodeBuffer(*bii.pShortVal & 0xFF); + nPrevInputs[i] = *bii.pShortVal; + } else { + EncodeBuffer(*bii.pVal); + nPrevInputs[i] = *bii.pVal; + } + } else { + EncodeBuffer(0); + } + } + +#ifdef FBA_DEBUG + dprintf(_T("*** Recording of file %s started.\n"), szChoice); +#endif + + return 0; + } +} + +int StartReplay(const TCHAR* szFileName) // const char* szFileName = NULL +{ + TCHAR szFilter[1024]; + int nRet; + int bOldPause; + + fp = NULL; + + if (szFileName) { + _tcscpy(szChoice, szFileName); + } else { + if (bDrvOkay) { + _stprintf(szChoice, _T("%s*.fr"), BurnDrvGetText(DRV_NAME)); + } else { + _stprintf(szChoice, _T("recording")); + } + MakeOfn(szFilter); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_REPLAY_REPLAY, true); + + bOldPause = bRunPause; + bRunPause = 1; + nRet = GetOpenFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { + return 1; + } + } + + { + const char szFileHeader[] = "FB1 "; // File identifier + char ReadHeader[] = " "; + fp = _tfopen(szChoice, _T("rb")); + memset(ReadHeader, 0, 4); + fread(ReadHeader, 1, 4, fp); // Read identifier + if (memcmp(ReadHeader, szFileHeader, 4)) { // Not the right file type + fclose(fp); + fp = NULL; + nRet = 2; + } else { + // First load the savestate associated with the recording + nRet = BurnStateLoadEmbed(fp, -1, 1, &DrvInitCallback); + if (nRet == 0) { + const char szChunkHeader[] = "FR1 "; // Chunk identifier + fread(ReadHeader, 1, 4, fp); // Read identifier + if (memcmp(ReadHeader, szChunkHeader, 4)) { // Not the right file type + fclose(fp); + fp = NULL; + nRet = 2; + } else { + // Open the recording itself + fseek(fp, 0x04, SEEK_CUR); // Skip chunk size + fread(&nEndFrame, 1, 4, fp); // Read framecount + nStartFrame = GetCurrentFrame(); + nEndFrame += nStartFrame; + fseek(fp, 0x0C, SEEK_CUR); // Skip rest of header + nRet = EmbedCompressedFile(fp, -1); + + } + } + } + + // Describe any possible errors: + if (nRet == 3) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_REPLAY)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_UNAVAIL)); + } else { + if (nRet == 4) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_REPLAY)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_TOOOLD), _T(APP_TITLE)); + } else { + if (nRet == 5) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_REPLAY)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_TOONEW), _T(APP_TITLE)); + } else { + if (nRet) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_LOAD)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_REPLAY)); + } + } + } + } + + if (nRet) { + if (fp) { + fclose(fp); + fp = NULL; + } + + FBAPopupDisplay(PUF_TYPE_ERROR); + + return 1; + } + } + + nReplayStatus = 2; // Set replay status + MenuEnableItems(); + + { + struct BurnInputInfo bii; + memset(&bii, 0, sizeof(bii)); + + LoadCompressedFile(); + + // Get the baseline + for (unsigned int i = 0; i < nGameInpCount; i++) { + BurnDrvGetInputInfo(&bii, i); + if (bii.pVal) { + if (bii.nType & BIT_GROUP_ANALOG) { + *bii.pShortVal = nPrevInputs[i] = (DecodeBuffer() << 8) | DecodeBuffer(); + + } else { + *bii.pVal = nPrevInputs[i] = DecodeBuffer(); + } + } else { + DecodeBuffer(); + } + } + } + +#ifdef FBA_DEBUG + dprintf(_T("*** Replay of file %s started.\n"), szChoice); +#endif + + return 0; +} + +static void CloseRecord() +{ + int nFrames = GetCurrentFrame() - nStartFrame; + + WriteCompressedFile(); + + fseek(fp, 0, SEEK_END); + int nChunkSize = ftell(fp) - 4 - nSizeOffset; // Fill in chunk size and no of recorded frames + fseek(fp, nSizeOffset, SEEK_SET); + fwrite(&nChunkSize, 1, 4, fp); + fwrite(&nFrames, 1, 4, fp); + + fclose(fp); + fp = NULL; +} + +static void CloseReplay() +{ + CloseCompressedFile(); + + fclose(fp); + fp = NULL; +} + +void StopReplay() +{ + if (nReplayStatus) { + if (nReplayStatus == 1) { + +#ifdef FBA_DEBUG + dprintf(_T(" ** Recording stopped, recorded %d frames.\n"), GetCurrentFrame() - nStartFrame); +#endif + CloseRecord(); +#ifdef FBA_DEBUG + PrintResult(); +#endif + } else { +#ifdef FBA_DEBUG + dprintf(_T(" ** Replay stopped, replayed %d frames.\n"), GetCurrentFrame() - nStartFrame); +#endif + + CloseReplay(); + } + nReplayStatus = 0; + MenuEnableItems(); + } +} + diff --git a/src/burner/win32/res.cpp b/src/burner/win32/res.cpp new file mode 100644 index 00000000..84e4877e --- /dev/null +++ b/src/burner/win32/res.cpp @@ -0,0 +1,98 @@ +#include "burner.h" + +#define HORIZONTAL_ORIENTED_RES 0 +#define VERTICAL_ORIENTED_RES 1 +int nOrientation; + +static INT_PTR CALLBACK ResProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + static bool bOK; + + switch (Msg) { + case WM_INITDIALOG: { + DEVMODE devMode; + devMode.dmSize = sizeof(DEVMODE); + devMode.dmDriverExtra = 0; + + // Run through all possible screenmodes and fill the combobox + for (int i = 0; EnumDisplaySettings(NULL, i, &devMode); i++) { + + // We're only interested in 16, 24, or 32 bit modes. + if (devMode.dmBitsPerPel & 0x30) { + long nItem = 0, nItemValue; + long nNewRes = (devMode.dmPelsWidth << 16) | devMode.dmPelsHeight; + + // See if the resolution is already in the combobox + do { + nItemValue = SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_GETITEMDATA, nItem, 0); + nItem++; + } while ((nItemValue != CB_ERR) && (nItemValue != nNewRes)); + + // If not, add it + if (nItemValue == CB_ERR) { + TCHAR szTemp[32]; + _stprintf(szTemp, _T(" %li x %li"), devMode.dmPelsWidth, devMode.dmPelsHeight); + nItem = SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_ADDSTRING, 0, (LPARAM)&szTemp); + SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_SETITEMDATA, nItem, nNewRes); + } + } + } + + SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_SETCURSEL, 0, 0); + + bOK = 0; + WndInMid(hDlg, hScrnWnd); + + return TRUE; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) { + bOK = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDCANCEL) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + + case WM_CLOSE: { + + if (bOK) { + long nItem = SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_GETCURSEL, 0, 0); + long nItemValue = SendDlgItemMessage(hDlg, IDC_CHOOSE_LIST, CB_GETITEMDATA, nItem, 0); + + if(nOrientation == HORIZONTAL_ORIENTED_RES) { + nVidHorWidth = nItemValue >> 16; + nVidHorHeight = nItemValue & 0xFFFF; + } + if(nOrientation == VERTICAL_ORIENTED_RES) { + nVidVerWidth = nItemValue >> 16; + nVidVerHeight = nItemValue & 0xFFFF; + } + if(bDrvOkay) { + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } else { + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + } + } + + EndDialog(hDlg, 0); + } + } + + return 0; +} + + +int ResCreate(int nResOrientation) +{ + nOrientation = nResOrientation; + + FBADialogBox(hAppInst,MAKEINTRESOURCE(IDD_CHOOSERES),hScrnWnd,(DLGPROC)ResProc); + return 0; +} + diff --git a/src/burner/win32/resource.h b/src/burner/win32/resource.h new file mode 100644 index 00000000..fd31f8ab --- /dev/null +++ b/src/burner/win32/resource.h @@ -0,0 +1,628 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by app.rc +// + +#define IDS_STRING 5000 + +#define BMP_SPLASH 1 +#define BMP_ABOUT 2 +#define BMP_MISC 3 + +#define IDI_APP 10 +#define IDI_TV_PLUS 11 +#define IDI_TV_MINUS 12 +#define IDI_TV_NOTWORKING 13 +#define IDI_TV_NOTFOUND_ESS 14 +#define IDI_TV_NOTFOUND_NON 15 + +#define IDD_SPLASH 50 +#define IDD_INPD 51 +#define IDD_INPS 52 +#define IDD_INPCHEAT 53 +#define IDD_INPC 54 +#define IDD_INPDIP 55 +#define IDD_WAIT 56 +#define IDD_ABOUT 57 +#define IDD_FIRST 58 +#define IDD_VALUE 59 +#define IDD_ROMSDIR 60 +#define IDD_SELNEW 61 +#define IDD_CAPTURE 62 +#define IDD_GAMMA 63 +#define IDD_CHOOSERES 64 +#define IDD_SCANLINE 65 +#define IDD_PHOSPHOR 66 +#define IDD_SCREENANGLE 67 +#define IDD_CPUCLOCK 68 +#define IDD_SYSINFO 69 +#define IDD_EXCEPTION 70 +#define IDD_DEBUG_LRG 71 +#define IDD_DEBUG_SML 72 +#define IDD_POPUP 73 +#define IDD_SUPPORTDIR 74 +#define IDD_PALETTEVIEWER 75 +#define IDD_ROMINFO 76 +#define IDD_IPS_MANAGER 77 +#define IDD_MVS_SELECT_CARTS 78 +#define IDD_NCD_DLG 79 +#define IDD_NCD_COVER_DLG 80 + +#define IDR_MENU 100 +#define IDR_MENU_BLITTER_1 110 +#define IDR_MENU_BLITTER_2 111 +#define IDR_MENU_BLITTER_3 112 +#define IDR_MENU_BLITTER_4 113 +#define IDR_MENU_BLITTER_5 114 +#define IDR_MENU_AUD_PLUGIN_1 130 +#define IDR_MENU_AUD_PLUGIN_2 131 +#define IDR_ACCELERATOR 150 + +#define MENU_MENU_0 1000 +#define MENU_MENU_1 1001 +#define MENU_MENU_2 1002 +#define MENU_MENU_3 1003 +#define MENU_MENU_4 1004 +#define MENU_MENU_5 1005 + +#define IDC_INPD_LIST 20000 +#define IDC_INPD_NEWMACRO 20001 +#define IDC_INPD_GI 20002 +#define IDC_INPD_PCI 20003 +#define IDC_INPD_ANALOG 20004 +#define IDC_INPD_USE 20005 +#define IDC_INPD_DEFAULT 20006 +#define IDC_INPS_GRABMOUSE 20007 +#define IDC_INPS_CONTROL 20008 +#define IDC_INPS_CONTROL_NAME 20009 +#define IDC_INPC_VALUE 20010 +#define IDC_INPS_PUSH 20011 +#define IDC_INPCX1_VALUE 20012 +#define IDC_INPC_RESET 20013 +#define IDC_INPCHEAT_LIST 20014 +#define IDC_WAIT_PROG 20015 +#define IDC_WAIT_LABEL_A 20016 +#define IDC_WAIT_LABEL_B1 20017 +#define IDC_WAIT_LABEL_B2 20018 +#define ID_VALUE_CLOSE 20019 +#define IDC_VALUE_EDIT 20020 + +#define IDC_ROMSDIR_EDIT1 20030 +#define IDC_ROMSDIR_EDIT2 20031 +#define IDC_ROMSDIR_EDIT3 20032 +#define IDC_ROMSDIR_EDIT4 20033 +#define IDC_ROMSDIR_EDIT5 20034 +#define IDC_ROMSDIR_EDIT6 20035 +#define IDC_ROMSDIR_EDIT7 20036 +#define IDC_ROMSDIR_EDIT8 20037 + +#define IDC_ROMSDIR_BR1 20040 +#define IDC_ROMSDIR_BR2 20041 +#define IDC_ROMSDIR_BR3 20042 +#define IDC_ROMSDIR_BR4 20043 +#define IDC_ROMSDIR_BR5 20044 +#define IDC_ROMSDIR_BR6 20045 +#define IDC_ROMSDIR_BR7 20046 +#define IDC_ROMSDIR_BR8 20047 + +#define IDC_FBA_VER 20050 +#define IDC_SPECIALSTRING 20051 +#define IDC_SHOWLICENSE 20052 +#define IDC_LICENSE 20053 +#define IDC_ACCEPTLICENSE 20054 +#define IDC_CHECKAUTOEXPAND 20055 +#define IDC_SCREENSHOT_H 20056 +#define IDC_SCREENSHOT_V 20057 +#define IDC_SCREENSHOT2_H 20058 +#define IDC_SCREENSHOT2_V 20059 +#define IDC_CHECKAVAILABLEONLY 20060 +#define IDCAPTURE 20061 +#define IDC_ADVANCE 20062 +#define IDC_LABELROMNAME 20063 +#define IDC_LABELROMINFO 20064 +#define IDC_LABELCOMMENT 20065 +#define IDC_LABELGENRE 20066 +#define IDC_LABELSYSTEM 20067 +#define IDC_TEXTROMNAME 20068 +#define IDC_TEXTROMINFO 20069 +#define IDC_TEXTCOMMENT 20070 +#define IDC_TEXTGENRE 20071 +#define IDC_TEXTSYSTEM 20072 +#define IDC_TREE1 20073 +#define IDC_SEL_SHORTNAME 20074 +#define IDC_SEL_ASCIIONLY 20075 +#define IDC_LIST1 20076 +#define IDC_SPRITE1 20077 +#define IDC_SPRITE2 20078 +#define IDC_SPRITE4 20079 +#define IDC_SPRITE3 20080 +#define IDC_SPRITE5 20081 +#define IDC_SPRITE6 20082 +#define IDC_SPRITE7 20083 +#define IDC_SPRITE8 20084 +#define IDC_GAMMA_SLIDER 20085 +#define IDC_GAMMA_EDIT 20086 +#define IDC_CHOOSE_LIST 20087 +#define IDC_SCANLINE_SLIDER 20088 +#define IDC_SCANLINE_EDIT 20089 +#define IDC_PHOSPHOR_1_SLIDER 20090 +#define IDC_PHOSPHOR_1_EDIT 20091 +#define IDC_PHOSPHOR_2_SLIDER 20092 +#define IDC_PHOSPHOR_2_EDIT 20093 +#define IDC_SCREENANGLE_SLIDER 20094 +#define IDC_SCREENANGLE_EDIT 20095 +#define IDC_SCREENCURVATURE_SLIDER 20096 +#define IDC_SCREENCURVATURE_EDIT 20097 +#define IDC_CPUCLOCK_SLIDER 20098 +#define IDC_CPUCLOCK_EDIT 20099 +#define IDC_SYSINFO_CODE 20100 +#define IDC_SYSINFO_EDIT 20101 +#define IDC_SYSINFO_DEBUG 20102 +#define IDC_SYSINFO_SHOW 20103 +#define IDC_SYSINFO_LOG 20104 +#define IDC_DBG_MAINWN1 20105 +#define IDC_DBG_MAINWN1_DRP1 20106 +#define IDC_DBG_MAINWN1_DRP2 20107 +#define IDC_DBG_MAINWN2 20108 +#define IDC_DBG_MAINWN2_DRP1 20109 +#define IDC_DBG_MAINWN2_DRP2 20110 +#define IDC_DBG_INFOWN1 20111 +#define IDC_DBG_INFOWN2 20112 +#define IDC_DBG_COMMAND 20113 +#define IDC_DBG_GO 20114 +#define IDC_DBG_STEP 20115 +#define IDC_DBG_STEPINTO 20116 +#define IDC_DBG_SKIP 20117 +#define IDC_DBG_STEPFRAME 20118 +#define IDC_DBG_SHOT 20119 +#define IDC_MESSAGE_EDIT_ENG 20120 +#define IDC_MESSAGE_EDIT_LOCAL 20121 +#define IDC_MESSAGE_ICON 20122 +#define IDC_MESSAGE_BACK 20123 +#define IDC_LABELNOTES 20124 +#define IDC_TEXTNOTES 20125 +#define IDC_ROMSAVAILABLEINFO 20126 +#define IDC_INPD_SAVE_AS_PRESET 20127 +#define IDC_LIST2 20128 +#define IDC_IPSMAN_DESELECTALL 20129 +#define IDC_SEL_IPSMANAGER 20130 +#define IDC_SEL_APPLYIPS 20131 +#define IDC_SEL_IPSGROUP 20132 +#define IDC_SEL_SEARCH 20133 +#define IDC_SEL_SEARCHGROUP 20134 + +#define IDC_SUPPORTDIR_EDIT1 20150 +#define IDC_SUPPORTDIR_EDIT2 20151 +#define IDC_SUPPORTDIR_EDIT3 20152 +#define IDC_SUPPORTDIR_EDIT4 20153 +#define IDC_SUPPORTDIR_EDIT5 20154 +#define IDC_SUPPORTDIR_EDIT6 20155 +#define IDC_SUPPORTDIR_EDIT7 20156 +#define IDC_SUPPORTDIR_EDIT8 20157 + +#define IDC_SUPPORTDIR_BR1 20170 +#define IDC_SUPPORTDIR_BR2 20171 +#define IDC_SUPPORTDIR_BR3 20172 +#define IDC_SUPPORTDIR_BR4 20173 +#define IDC_SUPPORTDIR_BR5 20174 +#define IDC_SUPPORTDIR_BR6 20175 +#define IDC_SUPPORTDIR_BR7 20176 +#define IDC_SUPPORTDIR_BR8 20177 + +#define IDC_DRVCOUNT 20200 +#define IDC_TREE2 20201 +#define IDC_CHECK1 20202 +#define IDC_CHECK2 20203 +#define IDC_CHECK3 20204 +#define IDC_CHECK4 20205 + +#define IDC_STATIC_SYS 20300 +#define IDC_STATIC_OPT 20301 +#define IDC_STATIC1 20302 +#define IDC_STATIC2 20303 +#define IDC_STATIC3 20304 +#define IDC_STATIC_INFOBOX 20305 +#define IDC_STATIC_INFOBOX2 20306 +#define IDC_STATIC_INFOBOX3 20307 +#define IDC_STATIC_INFOBOX4 20308 +#define IDC_STATIC_INFOBOX5 20309 +#define IDC_STATIC_INFOBOX6 20310 + +#define IDC_GFX_VIEWER_HORI_1 20400 +#define IDC_GFX_VIEWER_HORI_2 20401 +#define IDC_GFX_VIEWER_HORI_3 20402 +#define IDC_GFX_VIEWER_HORI_4 20403 +#define IDC_GFX_VIEWER_HORI_5 20404 +#define IDC_GFX_VIEWER_HORI_6 20405 +#define IDC_GFX_VIEWER_HORI_7 20406 +#define IDC_GFX_VIEWER_HORI_8 20407 +#define IDC_GFX_VIEWER_HORI_9 20408 +#define IDC_GFX_VIEWER_HORI_10 20409 +#define IDC_GFX_VIEWER_HORI_11 20410 +#define IDC_GFX_VIEWER_HORI_12 20411 +#define IDC_GFX_VIEWER_HORI_13 20412 +#define IDC_GFX_VIEWER_HORI_14 20413 +#define IDC_GFX_VIEWER_HORI_15 20414 +#define IDC_GFX_VIEWER_HORI_16 20415 +#define IDC_GFX_VIEWER_VERT_1 20416 +#define IDC_GFX_VIEWER_VERT_2 20417 +#define IDC_GFX_VIEWER_VERT_3 20418 +#define IDC_GFX_VIEWER_VERT_4 20419 +#define IDC_GFX_VIEWER_VERT_5 20420 +#define IDC_GFX_VIEWER_VERT_6 20421 +#define IDC_GFX_VIEWER_VERT_7 20422 +#define IDC_GFX_VIEWER_VERT_8 20423 +#define IDC_GFX_VIEWER_VERT_9 20424 +#define IDC_GFX_VIEWER_VERT_10 20425 +#define IDC_GFX_VIEWER_VERT_11 20426 +#define IDC_GFX_VIEWER_VERT_12 20427 +#define IDC_GFX_VIEWER_VERT_13 20428 +#define IDC_GFX_VIEWER_VERT_14 20429 +#define IDC_GFX_VIEWER_VERT_15 20430 +#define IDC_GFX_VIEWER_VERT_16 20431 +#define IDC_GFX_VIEWER_PREV 20432 +#define IDC_GFX_VIEWER_NEXT 20433 + +#define IDC_TAB1 20500 +#define IDC_SPATH_TAB 20501 +#define IDC_ROMPATH_TAB 20502 + +#define IDROM 20600 +#define IDRESCAN 20601 +#define IDROMINFO 20602 + +#define IDC_MVS_CART1 20700 +#define IDC_MVS_CART2 20701 +#define IDC_MVS_CART3 20702 +#define IDC_MVS_CART4 20703 +#define IDC_MVS_CART5 20704 +#define IDC_MVS_CART6 20705 +#define IDC_MVS_TEXTROMNAME1 20706 +#define IDC_MVS_TEXTROMNAME2 20707 +#define IDC_MVS_TEXTROMNAME3 20708 +#define IDC_MVS_TEXTROMNAME4 20709 +#define IDC_MVS_TEXTROMNAME5 20710 +#define IDC_MVS_TEXTROMNAME6 20711 +#define IDC_MVS_TEXTSYSTEM1 20712 +#define IDC_MVS_TEXTSYSTEM2 20713 +#define IDC_MVS_TEXTSYSTEM3 20714 +#define IDC_MVS_TEXTSYSTEM4 20715 +#define IDC_MVS_TEXTSYSTEM5 20716 +#define IDC_MVS_TEXTSYSTEM6 20717 +#define IDC_MVS_TEXTCOMMENT1 20718 +#define IDC_MVS_TEXTCOMMENT2 20719 +#define IDC_MVS_TEXTCOMMENT3 20720 +#define IDC_MVS_TEXTCOMMENT4 20721 +#define IDC_MVS_TEXTCOMMENT5 20722 +#define IDC_MVS_TEXTCOMMENT6 20723 +#define IDC_MVS_SELECT1 20724 +#define IDC_MVS_SELECT2 20725 +#define IDC_MVS_SELECT3 20726 +#define IDC_MVS_SELECT4 20727 +#define IDC_MVS_SELECT5 20728 +#define IDC_MVS_SELECT6 20729 +#define IDC_MVS_CLEAR1 20730 +#define IDC_MVS_CLEAR2 20731 +#define IDC_MVS_CLEAR3 20732 +#define IDC_MVS_CLEAR4 20733 +#define IDC_MVS_CLEAR5 20734 +#define IDC_MVS_CLEAR6 20735 + +#define IDC_NCD_LIST 20800 +#define IDC_NCD_FRONT_PIC 20801 +#define IDC_NCD_BACK_PIC 20802 +#define IDC_NCD_FRONT_PIC_FRAME 20803 +#define IDC_NCD_BACK_PIC_FRAME 20804 +#define IDC_NCD_TEXTSHORT 20805 +#define IDC_NCD_TEXTPUBLISHER 20806 +#define IDC_NCD_TEXTIMAGE 20807 +#define IDC_NCD_TEXTAUDIO 20808 +#define IDC_NCD_SSUBDIR_CHECK 20809 +#define IDC_NCD_SISO_ONLY_CHECK 20810 +#define IDC_NCD_SCAN_BUTTON 20811 +#define IDC_NCD_SEL_DIR_BUTTON 20812 +#define IDC_NCD_PLAY_BUTTON 20813 +#define IDC_NCD_CANCEL_BUTTON 20814 +#define IDC_NCD_COVER_PREVIEW_PIC 20815 +#define IDC_NCD_LABELSHORT 20816 +#define IDC_NCD_LABELPUBLISHER 20817 +#define IDC_NCD_LABELIMAGE 20818 +#define IDC_NCD_LABELAUDIO 20819 + +#define ID_LICENSE 21000 +#define ID_DX9EFFECT 21001 + +#define MENU_LOAD 10001 +#define MENU_STARTNET 10002 +#define MENU_STARTREPLAY 10003 +#define MENU_STARTRECORD 10004 +#define MENU_STOPREPLAY 10005 +#define MENU_QUIT 10006 +#define MENU_INPUT 10007 +#define MENU_PAUSE 10008 +#define MENU_DIPSW 10009 +#define MENU_SETCPUCLOCK 10010 +#define MENU_RESETCPUCLOCK 10011 +#define MENU_EXIT 10012 +#define MENU_MEMCARD_CREATE 10020 +#define MENU_MEMCARD_SELECT 10021 +#define MENU_MEMCARD_INSERT 10022 +#define MENU_MEMCARD_EJECT 10023 +#define MENU_MEMCARD_TOGGLE 10024 +#define MENU_STATE_LOAD_DIALOG 10030 +#define MENU_STATE_SAVE_DIALOG 10031 +#define MENU_STATE_LOAD_SLOT 10032 +#define MENU_STATE_SAVE_SLOT 10033 +#define MENU_STATE_PREVSLOT 10034 +#define MENU_STATE_NEXTSLOT 10035 +#define MENU_ALLRAM 10036 +#define MENU_TRIPLE 10100 +#define MENU_FULL 10102 +#define MENU_DWMFIX 10103 +#define MENU_NOSTRETCH 10110 +#define MENU_STRETCH 10111 +#define MENU_ASPECT 10112 +#define MENU_BLITTER_1 10121 +#define MENU_BLITTER_2 10122 +#define MENU_BLITTER_3 10123 +#define MENU_BLITTER_4 10124 +#define MENU_BLITTER_5 10125 +#define MENU_BLITTER_6 10126 +#define MENU_BLITTER_7 10127 +#define MENU_BLITTER_8 10128 +#define MENU_RES_ARCADE 10130 +#define MENU_RES_1 10131 +#define MENU_RES_2 10132 +#define MENU_RES_3 10133 +#define MENU_RES_4 10134 +#define MENU_RES_OTHER 10135 +#define MENU_SINGLESIZESCREEN 10136 +#define MENU_DOUBLESIZESCREEN 10137 +#define MENU_TRIPLESIZESCREEN 10138 +#define MENU_QUADSIZESCREEN 10139 +#define MENU_16 10141 +#define MENU_24 10142 +#define MENU_32 10143 +#define MENU_GAMMA_DO 10150 +#define MENU_GAMMA_DARKER 10151 +#define MENU_GAMMA_LIGHTER 10152 +#define MENU_GAMMA_OTHER 10153 +#define MENU_GAMMA_USE_HARDWARE 10154 +#define MENU_GAMMA_HARDWARE_ONLY 10155 +#define MENU_GAMMA_SOFTWARE_ONLY 10156 +#define MENU_MEMAUTO 10160 +#define MENU_VIDEOMEM 10161 +#define MENU_SYSMEM 10162 +#define MENU_AUTOSIZE 10170 +#define MENU_SINGLESIZEWINDOW 10171 +#define MENU_DOUBLESIZEWINDOW 10172 +#define MENU_TRIPLESIZEWINDOW 10173 +#define MENU_QUADSIZEWINDOW 10174 +#define MENU_MAXIMUMSIZEWINDOW 10175 +#define MENU_FORCE60HZ 10176 +#define MENU_AUTOFRAMESKIP 10177 +#define MENU_ROTATEVERTICAL 10181 +#define MENU_ASPECTNORMAL 10190 +#define MENU_ASPECTLCD 10191 +#define MENU_ASPECTWIDE 10192 +#define MENU_ASPECTWIDELCD 10193 +#define MENU_MONITORMIRRORVERT 10194 +#define MENU_FRAMES 10200 +#define MENU_DSOUND_BASS 10201 +#define MENU_XAUDIO_BASS 10202 +#define MENU_XAUDIO_REVERB 10203 +#define MENU_DSOUND_NOSOUND 10210 +#define MENU_DSOUND_11025 10211 +#define MENU_DSOUND_22050 10212 +#define MENU_DSOUND_44100 10213 +#define MENU_DSOUND_48000 10214 +#define MENU_XAUDIO_NOSOUND 10220 +#define MENU_XAUDIO_11025 10221 +#define MENU_XAUDIO_22050 10222 +#define MENU_XAUDIO_44100 10223 +#define MENU_XAUDIO_48000 10224 +#define MENU_INTERPOLATE_0 10230 +#define MENU_INTERPOLATE_1 10231 +#define MENU_INTERPOLATE_3 10233 +#define MENU_INTERPOLATE_5 10235 +#define MENU_INTERPOLATE_FM_0 10240 +#define MENU_INTERPOLATE_FM_1 10241 +#define MENU_INTERPOLATE_FM_3 10243 +#define MENU_INTERPOLATE_FM_5 10245 +#define MENU_AUTOPAUSE 10300 +#define MENU_PROCESSINPUT 10301 +#define MENU_DISPLAYINDICATOR 10302 +#define MENU_MODELESS 10303 +#define MENU_ROMSDIR 10304 +#define MENU_ENABLECHEAT 10306 +#define MENU_LANGUAGE_SELECT 10307 +#define MENU_LANGUAGE_EXPORT 10308 +#define MENU_PRIORITY_REALTIME 10310 +#define MENU_PRIORITY_HIGH 10311 +#define MENU_PRIORITY_ABOVE_NORMAL 10312 +#define MENU_PRIORITY_NORMAL 10313 +#define MENU_PRIORITY_BELOW_NORMAL 10314 +#define MENU_PRIORITY_LOW 10315 +#define MENU_SNAPFACT 10317 +#define MENU_SAVESNAP 10318 +#define MENU_ASSOCIATE 10330 +#define MENU_DISASSOCIATE 10331 +#define MENU_SAVEGAMEINPUTNOW 10332 +#define MENU_SAVEGAMEINPUT 10333 +#define MENU_SAVESET 10334 +#define MENU_LOADSET 10335 +#define MENU_STARTLOG 10390 +#define MENU_STOPLOG 10391 +#define MENU_DEBUG 10392 +#define MENU_ASSEMBLYCORE 10393 +#define MENU_ABOUT 10501 +#define MENU_SYSINFO 10502 +#define MENU_CONTENTS 10503 +#define MENU_WWW_HOME 10504 +#define MENU_WWW_FORUM 10505 +#define MENU_WHATSNEW 10506 +#define MENU_WWW_NSFORUM 10507 +#define MENU_WLOGSTART 10606 +#define MENU_WLOGEND 10607 +#define MENU_AUTOSWITCHFULL 10613 +#define MENU_ROMDIRS 10614 +#define MENU_SUPPORTDIRS 10615 +#define MENU_NOCHANGENUMLOCK 10616 +#define MENU_PREVIOUSGAMES1 10617 +#define MENU_PREVIOUSGAMES2 10618 +#define MENU_PREVIOUSGAMES3 10619 +#define MENU_PREVIOUSGAMES4 10620 +#define MENU_PREVIOUSGAMES5 10621 +#define MENU_PREVIOUSGAMES6 10622 +#define MENU_PREVIOUSGAMES7 10623 +#define MENU_PREVIOUSGAMES8 10624 +#define MENU_PREVIOUSGAMES9 10625 +#define MENU_PREVIOUSGAMES10 10626 +#define MENU_CHEATSEARCH_START 10628 +#define MENU_CHEATSEARCH_NOCHANGE 10629 +#define MENU_CHEATSEARCH_CHANGE 10630 +#define MENU_CHEATSEARCH_DECREASE 10631 +#define MENU_CHEATSEARCH_INCREASE 10632 +#define MENU_CHEATSEARCH_DUMPFILE 10633 +#define MENU_CHEATSEARCH_EXIT 10634 +#define MENU_LANGUAGE_RESET 10635 +#define MENU_BLITTEROPTIONS 10643 +#define MENU_VIDEOVSYNC 10646 +#define MENU_MONITORAUTOCHECK 10650 +#define MENU_CLRMAME_PRO_XML 10651 +#define MENU_CLRMAME_PRO_XML_MD_ONLY 10653 +#define MENU_SAVEHISCORES 10654 +#define MENU_AUD_PLUGIN_1 10655 +#define MENU_AUD_PLUGIN_2 10656 +#define MENU_AUD_PLUGIN_3 10657 +#define MENU_AUD_PLUGIN_4 10658 +#define MENU_AUD_PLUGIN_5 10659 +#define MENU_AUD_PLUGIN_6 10660 +#define MENU_AUD_PLUGIN_7 10661 +#define MENU_AUD_PLUGIN_8 10662 +#define MENU_AUDIO_OPTIONS 10663 +#define MENU_INP_PLUGIN_1 10664 +#define MENU_INP_PLUGIN_2 10665 +#define MENU_INP_PLUGIN_3 10666 +#define MENU_INP_PLUGIN_4 10667 +#define MENU_INP_PLUGIN_5 10668 +#define MENU_INP_PLUGIN_6 10669 +#define MENU_INP_PLUGIN_7 10670 +#define MENU_INP_PLUGIN_8 10671 +#define MENU_PALETTEVIEWER 10672 +#define MENU_RES_ARCADE_VERTICAL 10700 +#define MENU_RES_1_VERTICAL 10701 +#define MENU_RES_2_VERTICAL 10702 +#define MENU_RES_3_VERTICAL 10703 +#define MENU_RES_4_VERTICAL 10704 +#define MENU_RES_OTHER_VERTICAL 10705 +#define MENU_SINGLESIZESCREEN_VERTICAL 10706 +#define MENU_DOUBLESIZESCREEN_VERTICAL 10707 +#define MENU_TRIPLESIZESCREEN_VERTICAL 10708 +#define MENU_QUADSIZESCREEN_VERTICAL 10709 +#define MENU_CDIMAGE 10710 +#define MENU_START_NEOGEO_MVS 10711 +#define MENU_START_NEOGEO_CD 10712 +#define MENU_LOAD_NEOCD 10713 + +#define MENU_NORMAL 11001 +#define MENU_SCAN 11002 +#define MENU_SCAN50 11003 + +#define MENU_DISABLEFX 11101 +#define MENU_BILINEAR 11102 +#define MENU_PHOSPHOR 11103 +#define MENU_RGBEFFECTS 11104 +#define MENU_3DPROJECTION 11105 +#define MENU_ROTSCAN 11106 +#define MENU_PRESCALE 11107 +#define MENU_SOFTFX 11108 +#define MENU_SCANINTENSITY 11109 +#define MENU_PHOSPHORINTENSITY 11110 +#define MENU_3DSCREENANGLE 11111 +#define MENU_3DUSELIGHTING 11112 +#define MENU_EFFECT_AUTO 11121 +#define MENU_EFFECT_01 11122 +#define MENU_EFFECT_02 11123 +#define MENU_EFFECT_03 11124 +#define MENU_EFFECT_04 11125 +#define MENU_EFFECT_05 11126 +#define MENU_EFFECT_06 11127 +#define MENU_EFFECT_07 11128 +#define MENU_EFFECT_08 11129 +#define MENU_EFFECT_09 11130 +#define MENU_EFFECT_0A 11131 +#define MENU_EFFECT_0B 11132 +#define MENU_EFFECT_0C 11133 +#define MENU_EFFECT_0D 11134 +#define MENU_EFFECT_0E 11135 +#define MENU_EFFECT_0F 11136 +#define MENU_EFFECT_10 11147 +#define MENU_FORCE_16BIT 11141 +#define MENU_TEXTUREMANAGE 11142 + +#define MENU_SOFT_STRETCH 11201 +#define MENU_SOFT_SCALE2X 11202 +#define MENU_SOFT_SCALE3X 11203 +#define MENU_SOFT_2XPM_LQ 11204 +#define MENU_SOFT_2XPM_HQ 11205 +#define MENU_SOFT_EAGLE 11206 +#define MENU_SOFT_SUPEREAGLE 11207 +#define MENU_SOFT_2XSAI 11208 +#define MENU_SOFT_SUPER2XSAI 11209 +#define MENU_SOFT_SUPEREAGLE_VBA 11210 +#define MENU_SOFT_2XSAI_VBA 11211 +#define MENU_SOFT_SUPER2XSAI_VBA 11212 +#define MENU_SOFT_SUPERSCALE 11213 +#define MENU_SOFT_SUPERSCALE75 11214 +#define MENU_SOFT_HQ2X 11215 +#define MENU_SOFT_HQ3X 11216 +#define MENU_SOFT_HQ4X 11217 +#define MENU_SOFT_HQ2XS_VBA 11218 +#define MENU_SOFT_HQ3XS_VBA 11219 +#define MENU_SOFT_HQ2XS_SNES9X 11220 +#define MENU_SOFT_HQ3XS_SNES9X 11221 +#define MENU_SOFT_HQ2XBOLD 11222 +#define MENU_SOFT_HQ3XBOLD 11223 +#define MENU_SOFT_EPXB 11224 +#define MENU_SOFT_EPXC 11225 +#define MENU_SOFT_AUTOSIZE 11290 +#define MENU_SOFT_DIRECTACCESS 11291 + +#define MENU_DX9_POINT 11301 +#define MENU_DX9_LINEAR 11302 +#define MENU_DX9_CUBIC 11303 +#define MENU_DX9_CUBIC_LIGHT 11310 +#define MENU_DX9_CUBIC_BSPLINE 11311 +#define MENU_DX9_CUBIC_NOTCH 11312 +#define MENU_DX9_CUBIC_OPTIMAL 11313 +#define MENU_DX9_CUBIC_CATMULL 11314 +#define MENU_DX9_CUBIC_SHARP 11315 +#define MENU_DX9_CUBIC_DUFF 11316 +#define MENU_DX9_CUBIC_MITCHELL 11317 +#define MENU_DX9_CUBIC_CARDINAL 11318 +#define MENU_DX9_CUBIC_CUSTOM 11319 +#define MENU_DX9_FPTERXTURES 11320 +#define MENU_DX9_FORCE_PS14 11321 +#define MENU_DX9_CUBIC0 11322 +#define MENU_DX9_CUBIC1 11323 +#define MENU_DX9_CUBIC2 11324 +#define MENU_DX9_CUBIC3 11325 +#define MENU_DX9_CUBIC4 11326 + +#define MENU_DX9_ALT_POINT 11401 +#define MENU_DX9_ALT_LINEAR 11402 +#define MENU_DX9_ALT_HARDWAREVERTEX 11403 +#define MENU_DX9_ALT_MOTIONBLUR 11404 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 0 +#define _APS_NEXT_COMMAND_VALUE 0 +#define _APS_NEXT_CONTROL_VALUE 0 +#define _APS_NEXT_SYMED_VALUE 0 +#endif +#endif diff --git a/src/burner/win32/resource.rc b/src/burner/win32/resource.rc new file mode 100644 index 00000000..c6fe0ff0 --- /dev/null +++ b/src/burner/win32/resource.rc @@ -0,0 +1,44 @@ +#ifdef APSTUDIO_INVOKED + #error This file cannot be edited using the Visual C resource editor +#endif + +#define MAKE_STRING_2(s) #s +#define MAKE_STRING(s) MAKE_STRING_2(s) + +#ifdef __GNUC__ + #define _WIN32_WINDOWS 0x410 + #define _WIN32_IE 0x0500 +#endif + +// For version macros +#include "version.h" +// For APP_TITLE and APP_DESCRIPTION macros (both include quotes) +#include "title.h" + +// String IDs +#include "resource_string.h" + +#ifdef __GNUC__ + #include "app_gnuc.rc" +#else + #include "app.rc" +#endif + +// Version resource +#include "version.rc" + +// Manifest for Windows XP in themed mode +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "resource/manifest.xml" + +// License (we need to use a custom resource type, since Windres doesn't understand rcdata strings +ID_LICENSE 256 "license.rtf" + +// DirectX 9 blitter effects/shaders +//#ifdef _MSC_VER +ID_DX9EFFECT RCDATA "resource/bicubic.fx" +//#endif + +// GUI strings +#include "string.rc" + + diff --git a/src/burner/win32/resource/TV Minus.ico b/src/burner/win32/resource/TV Minus.ico new file mode 100644 index 0000000000000000000000000000000000000000..5efea17a848cc40cbe951233ed1cfb55b63d489d GIT binary patch literal 1150 zcmeH_%W48a5Jf8>xOJ7a%Y0fsA)gX|Ac~9ZLL`Bx3HSg(9ATm{kccmg8pg*=gN|J9 zD1)HPq`{4gRCBuMs=l?TDv=AGSWI}w_EO@bhV zL|DH(UAAK2{-uCa<`v0Ie#_ls4(X@2ZQZ~0&2|^n#wW`428zZz3N;fs)_g8iwe-KU z8OD}{!DNE|XpGMA2hHyeDrQSdKecUePmVBJUs`%wDR?Y=90wz7ijQ_rOTThmtk&y2 rd@sq|QCfQTH_*KK&;oa!`IF`!R{K1295g5GV?{-RP->U+|9XA{RnH-_ literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/TV Not Found Non Essential.ico b/src/burner/win32/resource/TV Not Found Non Essential.ico new file mode 100644 index 0000000000000000000000000000000000000000..367cb47cfc254c672cc869fabf30141422d32e0b GIT binary patch literal 4286 zcmcIn3s93+7XBZ3hX4UWc!dx`62d!3K;8%{58ntVASynmW2X=C?Y6{L=~h?W>N>Nl zc4uqdy6x0fp}d6fNPzH2Kt+}+TB&Y#oZ8MZTW8m?j%Ux!7>Ck@wma@+4mY{?zxVs@ zx!*bG4@J@V7ZO5||I}YRDax0ksBknKqO#D)IB6!FdrnP?`)JYP&|=WkXcDylTN6|C zEF;6&wT>gGKfo1@p5h4az0Vc@;|y2)?QvG{x19`cXd%Nr8${8Yk%aDf5%Hy&xs^QO zg>yoW2ZJI{xFPg}F|->354gc|hnr}(xe^%1{tL7oo&*lDg1bpHdki@c-~3OF!E0Q~ z7yaQ=iTC%z9=(2F*NT!x9^=PP`7aL@v<(?W1? z#4v;$M$qmej~4VzD$V{8@rf*dvdI`W;TAoxVX}mZQl6pc6Sb{FN{i5eH_2 z@n7eY)5ktYpL6-6jO>w1saanS8&hE{SOdd|?_h*5i1?S$zCipT^hF-U{RF{fGZ7He zOvoW0zni^5q0kx-0xiV+lwiZ}-7&M^h{4!Wpw?_q%H`1lfxwGmXaU1v-DKY0szjYG ze|tvO?_1{OeRVlN^~?{%7h_L3q|ofUh(Fz3urGSa8oHDkXbx6GQ*anGE7V{Mi-0rH zhR;*{0}E&3?wZs1%JbV4>hA`hYJ&KIaJYpWTG0Y2dW-AX$^C4R+lCgE4w^!B(13k| zN()`uD0nL@yv3cz519Pybf4WQT6K^kvjGpWFqBks6FuT>pdk;k~ zU`0+nTtg1m&@Y%rj!s^i=I&Y99uW(5h*=vR1&#U`IH!x8kaM^{D}E(3qdwv(b2wxQ zr%o-NzR-iQF@!vt4T<-!qJ{_u*F9iU=aJgGXGN; zA1rz9^_W@b|LUs%`_tTT3w5xN<^74w#Y(;AcIM|9vr7jS%fWQro#2NWuMdt@Bc>7tx^ZNzx#(L}<|AmzK0 zvB^GxBDa{%@R)x)P>Xi-J&DC*9N`@-%z-O4+P!_tilA{`J~ZbpfVSKMNRi2RO@}XL z*w6zijolod=+sIrYPC)m2^Q4Oc4g=f&h6Sm!g7=s!=wH_i19#TlGLsDxZ?XXP3y|_ z`s)6YGHA|U0GAdnfwqFhkm%#P)3tVT?}pel8oj+eF%@bJh>tn37Jbken*dcI>QhtC z?OH2lIYFO<>h3y37?YSAuA>jma>d^;6dhg?5mjZcSPRXImO|^&?IVQZd0iM6Bq#J@?I!OIzvhXr;hULA|f*Y`3H@56Si<6Tel;&t@F zW}fH*ndfsj;t$tv9I>xj4Hm?xdHFK>U^bWcii_X2{DPySTV8_B(sHnrtpdX3 zP+G>9htspJ4Xs+^^h-P5OFQ1rz=~4XZJhmIb?(}4a-S>pe$9$C)q**x3-hA`^Uwt^ zzXzB%^{(f_6$*o6*Pch+rK_N;d^L0-eqY5JaG)*;AHu5xafwd%%ue}He7p9U+6M|n zX&-1J9@wqQYF~^!p*qf4e za=I9sx}QuaG#=IHzwE)h(1AJ9s@6k4;G{MPVT7{na;VMOe0IgkI7HIu>Id0laf7 z^5`mG)7%d3ZY{VQt<9o!k;FBg|wAxv}DlI$m z>GmDNecN_?e-*h5z3?K~H*5y`+I7&sx)N-tk-Fm2dx!HDH00|eE5!l<`HlQsn}Ej` zMTLdM7bGPWug=Kax*;R;^~%(=J%vW&#w49CNABsV{H1{KPzlh%0#Fn@rl`z^6s4S? zD35V04IRn}en;jwYpU*GO<`C?}7*8mw8n*)&_kjNZg(+2J literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/TV Not Found.ico b/src/burner/win32/resource/TV Not Found.ico new file mode 100644 index 0000000000000000000000000000000000000000..9cfa60df9574840139544cfba1ad8199976ac86b GIT binary patch literal 4286 zcmcIn3slqB8UH`>B7qPH5MCi6fdmp1fdUE`RG@(33kBq{Y zp0lalS*>e3Pwf=sWgsMkHwmC<)uNMXyW^?t8E5ru9_#Vjcf-=9SZKTBZqAqc&;LGt zzx&WEf~R=K}=ypNRm&h?M^R z2XD#ceGn4ThGv4GU=zsYy)b)r55&hGHbq1%u9C@=vjhTxFT+p*4u|!WO8vvN+N9j{ z^y=SbWtlz=2^n$o1M$U}lLNz~yovbJ?FB29Zfa60yFjUE#kI6RSXe7WMiT7PH-dvx z@@L}iYLm$#bHl>SU-J26{VqQc4!3bH+JL4*e(dV&UW-I?t5hlzsMRf?Qa6E0)dX5? z7vjHW;`7D9?tQ0wrfJV`F84sEhsPiYMW{`IOP2(H1br}$nymW-$A2R}X@)0}%a7gC zYTH4hxro*P(a{~q;n)2v%lDlQ&;313d#S|Y-`IV9FJr89qb^B|3?PRqi0SgfRpf9L z^^thQeXO^4TBTm!ftU@Ti>?Qqt{K<<-UOE``(E+OFkWgOpTmv-nZv15AB+>RxCeO* zqh?wk1O>S`Ozs2b2jT;zi$kQw*pirN1AWW|m^JGH?zai&S$4qHK2wd@DnGx2LqxMd zLG2I_(BX{LfPl*&_1$&c&o6vlN~-lsE|*{vO%NaSU`&Qql6kp2A9-@}+0PAzc8E`C zz}RZS^}jX2;fQrJ;gU9n@l?rVuRBz#E~i#WyaWcCF>Z#C$DWf6L$jn`Y}~8oWU>!2 zChUkmjQF>4PxAgq+I)RuGcz--uyA1u7z~XtcdiM-!?$!|6GPgkD;TTcp`mqlt=8() zYj}7wa=3(J`!P@KKE*JM6Pt_=4o)kHjJ$&QlX~Ry@8I*#?byT%3(MJB2lv{RWs_g2Xn=aH{G#Gf01X%?C5CgzXSpY zuATVcHsT+>OVd<{R9CF4aIk$Mcw;s?mt<^=B?kg%9fW^73ke6qI zB}+)YP1@la>t3_0r%I!#vnMBapswp7HueI<#MHx_Iac)hHr((3`rLgSha(DAt3S9W z@^s+2NzSXAh=1mDnr5Q(`oeAHacuFheYZ$XXJ zLt9NUJ9#5(X4Q-n6@*2RLK=Km7KlLg4U!m1z6mHls1S=7H^{RF# zEbK-7SGC|U4jD@dm+PfUNI2lg%CtE(nwru8$;l0nnrcDc6YNQyPxgNHTPW0J1qOCG zbAm{O=eG0i@T;qMF%t#`YT{mgx$ALZK__Bcpmw^JkGK-+23!9`f_EV?OHoPhPxpY(zPt@q<@e$KSD*Sm*euKQ zk;zVsOQpRak&ycXxxbL}ao%PZ-`w2oM}D&DI+PT5LTQN&2p7ZrgC83VhptwX55t-w z3;L!5_ooA&2O%kG*SG52HJ^L!>zln-sU(`}#JKLl`vl3+=O1F;jCS>t%cJ6U?i_kt zTGEZ!U1;4HAarmX*E!r%jti5wFw9p`v_}OIc}`lf$~TLy(rb=frd|Hg!G^kAOst=E%o- zeGh7s#0bG3KtGrtbGae&ruGjER7CFG+xtaDc|Vkul06`Pm^AV(Ep69@sbi-5Es^NU zqoaTOS?ru{%uD94@zv_9;N!Dy+T5C!mS0&@a|23?UHdSJUsl=+^Hb}_f`XFv^LWB! z#1&4(#u)VT@(N#}Qf;`HkZ=wXUa;Xg+J^Xer_ho-eHrgm#~lpAo$+7Ls#V+SYK&v3 z#U3|5^q?L_ps271G8UcsM_k<2LA84IyJ2D3#}$gDCp4P%jj^%&Z_l0gKBS~rF*leo zK3Wj}5=86UU{=f!^7!)|K412oXDV6O>ebt8_y6)HtXn&XJZw;g`#|D?a4IggBM%4W z$v#+`XM@~a8|H*=JhyBxe||gW#%7FWeV5rz?FjT#o znp(L#F){xotu{GBB9SS6C?Gsi09aT6ih?H;mHvpL6cZHXJx)=4i(-OrNgrp8`z)*x zjC2i9H2svSp`Xx3_7Q7jC-_Eo+}p@n6h_*ZZltMwH8>4zq|w-?tcCvsn;!AU@rley R<|Y_VDQX{12Qcmp{|2TdP*DH? literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/TV Not Working.ico b/src/burner/win32/resource/TV Not Working.ico new file mode 100644 index 0000000000000000000000000000000000000000..9149eeba31b10a3950dcdcfdfffa232df250fdf6 GIT binary patch literal 4286 zcmcInYfKeK6yD1s?+PN-gx3WWp=c3#h{PI*fQm*%6jV%&R1g&v1Q7&*MFABB6vR-) zT9I0Q0I^9mCjKG*Ys#%nsd>Z5gv(xlkLs<}iDAX3lpW-#IfX ziV6P$0u=sLx;zwRlAP2rii(Q#anq(vV&TGtcVTNYY+!8u(_=E3Ce4^JvrwhC3fuCArPm#h(|sQaDE#joSmH` z7A#nBjk+jC%-q~u{WtZ~f6g;5{7#`QT)%z$c2QhhEH-S|ApHIPKLb8#Ip%|SN2jHw z-C<0rS7LKyj4LWCL`g}>pLoB8HQ&S68|CHY4{K^_^f~TfOt_x$pdOA>r%vq!`1_+7 z0FDKKS3k);GT!`MR#rw|uEfU1X8ZW~eCXuleI^9v+^OnVH$9Y1)1I zE#p8t7$@pN98Lq@RxZ@|`1ni2q7Ph8*}Z!={rNF0EG%s_+vOZEQjnWJjB(>TIh2)^ zCBTO~xz;!a1_ov`r_3AiDfA;FBjbvTi;K5$t*v*&FA&_nDzPOm`J28lf8gXj?0>C3 z5kn8ummYVCPY$nMz51JRvqzVdl$5KO zvg5q1hg@5+Vnsi(BwrC-dOBlH}Qle8D-ML(t-aGvBII&?_K zudJ*Ts9zBo8QEeBm)|8e^D6mDZ2Ac7(?)ErpEz-1IM)6pb3+c`%({aqAJlw#Lqmg* z*!%bIXKYHjZ={DYU%7H+e`#r{-g_lyhp}JtTkc1%GQ-YaX(Rn7zoFw1@)I(D{`{(= zM~{l?>S{r3_EFSBiQH=(iH%(LGnULD^^mW$1%98h_FL}7K40+vt`R>yJ^eB8LlY7b zidtJ+b?myjI#FL=FJ{i1*&z4Ik=W=F7RHHjXAWrt`!Zr_6Px>Src8t1gXE_4AKbZ* zDRWFrOh#K86J3Bku($v(X=ccNvN-+M+*Ro~H z#>A#I@UelpqVE*)59ing&Y{1$!uK1;j~^H0A#rF2&XHp9daq3M+uKh--Ue7F5})tzyFl(iY@5!WJ*(?w{Amk(zKuR~{ltkAx;^9t zZ8&!97|(?fc`o%CN8F(*=r7|>A!l$7J_VmXkn4hif@YmNckUT|XZ$JjnY^SujLVTD zNA%xo*RFk|zNH@P(bLoOBlOy*xUan8EBS+(@3vkGyS_Mc=8TR@%P4!8|!*{dUP9P9Ei{OGY{x@zoU12J9qBfFL6$^&YnH{ zWKvSnMeyQh;;<*sZzDFpq4s}4PR2Y_X$!bt+uPgwihs-jv1w0pbF=WpFH*rUuW%P5bcl5PS&YwU3sI#+E=b`LRvJXg1o|n>Ra!q10-s~0N z>;?2+|FQ5!n#bKB6nX6E>gpOoed;wyeELeicos0vtSMsio!{9j5dWLVO%C*qdXE?h z*ZLdo-ciV3BVzvpYVZvrzB3Gs?Xh4+{w!Xh^!5+_VCbIkJ)VeM}KkSjkkxKAb11OcRj z=B2%ddJDO74Vl6t?g~}IZN7qR@yYc4&+m?>Xmkd6dF_DvLao_Gg*{8p4J-d^wZhzS z@U~bOfAao;?r4H~yKm($UDtT}+rMe`hgQC;6f|q1{k7-e(^;Z7o>}?Z-45IR-k^Q` rydmG7vhq1!-_ZME`2O>(pSAy>-j`Y9fVrg;PDI2HrH-}JyZSr;Le&

KI2+$&#}KNs^Nw8OewUNX{7=y6N2HoRy5^Xn-avDn>*{ zaZF>vgkeAotxcczoi07M2gCKg_m;;^?b@|#SNzwiRr{Q-f5)xAyXbdOsp|g{(ZKJ2 z_q%xi{MYZUi=O4mm6!bPchUcUlo2CF49}HGlO~NBGiJhs2@@wybeuYM>fE_=7cN}5 zXwjm@xgxM+$r3U1=g)U(#*7)0Cr=(bc5Hln{K%0b$B!SMl9G~S#U1q-BHx^(HX zTv@SVg}dV7;v^eAdi1nu)22+B;#qDXp5?Bjq$H8b;Fz48ETCY+h7B7$c<`V>gYLce z-d??W_2|)~Teog^-F4U9ci-K!XHNkll7z5GVQGT&=-%C@d$(>r;=ANZpFVvO5)#tV z(mZk2tXZC=Nb}~+6Ht-avuBIFMc8C9*?@4hfqM1o-I^(;FsH*Va#dGn@Cn?&s2zh6;Z)x63krBf}xdiCmuAAVR^*XZR@qekh7P)^At zR=fcN2K4RQcgT<-s_gWhd+yO(ny6{hrnldId#hHh8aHm-qD6~p)v76^u=2NS*Unu6 zH{X17(V|5Q7cP9$O*iGwpI_j{8*jYos;mC~_rK@MmrrEDf(0v8s-!LwhblK{(4bMH zM)m90m!V6QD_5>swW|86zPi_}S+iNQX8P#PJMRoVr3`hnTiv>vOJT%&x`4)UsZESo_Y4=`b|bRXfmpLtv(H#3{9A|Z~69rZrcC$<^%8i@Y(X zj=r-o^Itxj_WQgY`)rJc|Fvr4!*||!SE*9BRjbx^#E99iz4rQNpM7@Vz@dzc88har zUb5xY72Drhzx|03BgPIKICRL6k+WvafAPhCeEs#;+1c6O=Mksp&!0bY=8PF_j|zI1NJ`upc^xPRf^Jr5i`wEKx84?cDDkz+?6KK9td!jB!?b>zT~ zBl~w8&fM;EaPQWG`?em+4Lq=F(R~YN#7`K#U}j22(&W_miK~~+UbSTQnq_m>u9&xB z-KD2vvbqRqlb4NIj}RD?SUQgf9%k%AC8B1J$`tP1P||6 zci)n^X$cb_*|q-3M;}ru@!@mqv4;-t+qP`p^zp-nrX|E}jFw?m@9y2pm8p1p)7CAU zx2<@7{g;_GM;f9?TV!arf@sk3Rb7W4Utl=+Va? zfBcDDdGg684;^`Q>Wn3m(icq5Sm+a%zEJpAKG8I33#ZOpx_r}~`?o&ivvk9*`00x$ zr7cLEyJF9S5AOU?cI?=(ef#!p+qU5V0-L<1HWq;xN&_IWnfNnj&O{GzfHG7U2uG2D z;UT>vZh$IkA(+JY1|5XTpbO{=63_}J@^QQ8dZ<%j=mS#RBgiZtWk40#5-BN;e*O9( z55g1tK^r1K09M%5KD~R3q8Or|kStv8*^|P6UnwOED#o)^Q-M8Njg;0Cl|%usPD+E* zE#Qv~SYfz2;u}?B^cuHHPQS@bMdYR~PE}LW$yrtc@Q#Y$6WFL!sIFnPv%A!bqErU0 zr)_ls^%Sj0pFXeyq^N=wL2wM~K%PcG52z83kaz-#(BTM8V$e(>wIRsMUl~wWtLpy^ z8#XLozMN`avu2G`!|eIzpI6$ULx(DxN*Re1hq@RW6t^nSZW6d8Lz>a#r4E!_82t6V zUY1h+dO`arxfTnB2U3NEM}p6KLpy6dNW}Roue=iQk-tchBG+Gk{a^q3*T4PkZ&zP^ z^|jYtd);-{foD)^Y9tfYSFezjQ~XzPjiAz6KD_^u&xdMesR|Hy}4-B&K-Nd^wK|Ge)*k-&El%pYmi(eb0aX)A-yppYC|#(@i^%bm`K&bZNuy&T-=wpE~tH zBoaaLvuDpf_SoYKmTq6P`K=ARo*h1X?0^A72M-=GXU@V`UU@YqCr7fM3WdPxFqX8Q ziH1eP1`ZkCzyJ6VLzm8-wrSO(2Uae`QfPhp@kgFI`tUD(T=jYK(Fb>Kx_`rcw8jFI zUN&#q)^$tgWF*a-p0Z`ll1Fx~54Z2zyO z+Ned1YIO?aFVw8*?Z_Xnf8f9Y;AeMXzDSlBp&CrXr=NcMsi&TDd^T5(KK|s?nM=l} z%=_)1amjPzG8Qdbzhn942Ym#bj!&L9Ib+e0#~$|-@?fseNAwQS_~te2nBb;7*gBf; z7#Pe^q=IXLP9y}-QW{#r+{a8baF-kq04`h&{I_Tb{Eyuz;3^`?76v`e(k@!Z13b30K0&7~c- zY}w**8e#3)wfEnDzh)7}Pnm-WykK2G7O=1hkuU^sgYgLz&_UorIM~VH4>d@IU`nF1 zf-Y7^*k{#4I_!%Vqjy%WTq&??*DmWn&FlEU0}q@$dGhe#!}r~HpIfMjpwLxQN9%Nr zroM_wUx?9zA|+-^=tN3Tj4Eq1X10m|Db@*S0kD-=?`s^jVBxd#@gM40{@_pWKdb_7 zxZ#E}Wy+{dPW zFfKj4Kqz{h?x7+*F)SJMW60BkYHAex3h?ij=Ni%dpI7*Dm??7C)$fpYs2elke25-Ql|H ziss8#yIPI@gU4@K_0XxGa(?%dpB_B%#op&W&#M$-;hn$0{}|Zcc;n6a3)ijPdUV8y zari%U=&0@6cfIk(TNFerP2K>#0DxLpyO{!@_v*=4^ z-2UtQhw&$l?Ag6#mBgD?FZK~wyKL^>T^n$F*XEV@4C6sfz`m3ZZd>!*vCNQdi2p78 zU$bH%-LY}yLOD|bkM7?N_4L&81v4g%8qvFJ*8(>cYSW_m=GD3U@7fjr8`NzYJ_rN5p0QvNLbMY@zYYnc@W z_$vm<)dNvQKnvhMM$yHLSkqq^wEz%30+0oQd5k0kI*@VO5)bkS^bjckF7lL*9Kt1Gyv0UfaSRr{BMI;~m#KiL*__M& zs6GJyuqe3ap6=aPd)c$ z@67$QZ%+$!Fi$N;6iXqfMA@P?>Ga4E@>a_;ApBKKX|%V zQ@Dg$AR{H_zz8xBK%fioA3B7Qhls~U;u5?_j3mJqA>dU0x>a>FtiHC=^a#LbsC%3$ zYgk*X|(1032Eu^6Ws1Is|qQO-y zjEZU`XKf;L4P`tS_R?sR!i5X7|C##a^2;y3?6S+Qx#k)gfoll)nau(P3KWoxBSnnb z0k6ucK9Fiy%^L`;aj=wV77xW1q70OdrjUlviGj^9KG`{^L29&fK|+2M!#D|HFrm*}eOr@4ovkFZ1(; zT{3euiy^@u^1=%*y#4mu$??fy3Ba62+5-=7{$KgLXY1;#tbACJje;)oxQTQ|dpLzB<>Lz%f97#+I@Bo;(K*1;_Q~(;_znKml zcxa|G^WefMbTbzTd?CEKkN+mM8}TzJ4)+ppa6}$%A8aJymR!3yUD!h<01$V%S9*yT zE?6*W;>4LVW(cIGr3E-ksYreM-pl;&8TI0@`VAjifGXgKz6blk#wU7}%XWr=+pb2-rc(L|99_ocQ2QO9VLc$`FI2v4jed0N`|ZADVtgk9y~;XP8~aS_FuK$lkAT5IG?c-xYSk*Y=t_!A zjA!X|s*QR@T6xNxTJbEZM?Rityr~qt7b;YU7YP3y1Lt|mxqZMNFnP9${E$X`y24T10Y7ng#N);VL_e5<8`M9JF9c36I z9jUEwZ-WL6JVi<>K%R0CgWIz86iR_e5V}mH@(@T@P6|s=4F*@`FHg7YM>*(FVfs-f z%1PuysYzM1Xt7`Cf8BbG+}ON%&$@MoQ2}k*OtlJVbo+$LRa@uMzI^M}U0;3mpT~|p z>$G6O3O@Pr)os{x?5vf~{Qu5>Z0G79HELX&HXW&eY13vu@<=8pPhRHd4S)OXw5E5pt~>O|<{8QH)05-3u3MIo6j!2H$%^G~Y1X)9 zjp}uv-sgsV`CB$^8sq;>Hx{r2i1EKkIdK=r$XOb|fk$@*V#q{{+mVw(0em*4%qPc9PD)Ii zFn+?6$y0zPDKRN-Qrx()5kkFLWrabq!~7BxcHzKD6y23R95YzNpTXGtw`=@A>bCq+npWmqyq5Y z(WK>9R~H5_t|FmE6Jt8Vh*=-wzc3UK1OOkmfFU=y7S=2RT3(}B!vO|mwgVS(ju`}0$7BFF%`fi~b99<&o)~#dG7~a$$?5|(Ho{P!If&Cx`i8>mA z6o(<<7Ae(*lbn+$w&yF1_Vxvs`a}Tv!$vUvQx^Eog|2bXRjol4Lx2})HMmC5Sy2|} zin_oxTR}3HG@2WOxUN}fy&y6XFHc9gg-edX8V`CwSYiW?7LYRN1%a@L@DyW%Mj&*M z#Clm*Dx@wTI?E^$FEZ$Y5Kmc%2?chG+!RJ8+92lkj|Hy1`i7YQzxHkQ>5DF1hSsY$ zqC$o4wd)LR)-t|IwRR)Cc^7D z!0)?n>C$EQ-@kI{lBFx}U%6!Ql6iCIB~DGG6ljD{1ga@lJB=AR(&l4SQ-ye?8!=+! z@Zr1;BST>9n6dOv_>3Ms2I0eJ%$R6lM+_e^XwcxHL+xD-6&MJ+g9rOSH+)Is(%>OO z80zrVuYZ46)6+uH_sA|!6T9oz{hz2!F;#NM}`4+RD%REbj19i4$y-x2pfwM=sUcX zxpIbeNARS1irVR7y#Vzuzx=YROiCSO99q+fH%N?Cs)602n~Y)1H*6?7k#vD^%V?3_ z>hiVMUNf&@pVna8=yW5&kdT$9D1!_IyxzdtG1#a8JVbTOXa5uaACf z;6M16E?pY=!|Db(HG(D$@Yh!OPc#n3qG$kVfPYwyxkN&D=mq4|xe!D`YX@a5fqcRx zN691>N#rSUPz@4?3>85BRtk>z59aiOOF{K0fG*P=`c8pCJ`}7&hYn&G|Bh}EFQr=u z<>G4b;w699_~#h2^BX?5)oI|yZrz5rZk^bwRRa6Jd8>pvb-Gq4QxE@dx~WW`K102t z^TZQR2lzYQa6`RYYYrGabtm{=umr&W11G-tr7eKG{J-_q4&%o!`QU>OFJL?S-tAmkC+Wl?@$~f zUwG!g+WQuc8#;LWsIlY6#*G~{Y4oT`V@JnL7#BZyzzF7j;|9&ESFIiR&nED==>Bil zu0PoS76{eq)T>+H$TxRPA~XG`@Hc}3{O!ha$Zy@gBQAZx|LXYx|EPJNJa0nk{6*`c z8@|gn?TPOBuG=voWqwp6tlKep+G55(H=v2BZ5d!BrUgu7ZYZk3Bt>%YafC0ElyL}@ zfDcoSrfT4oOH{V7sZC7?394$T_Ms@dTp+#K@^xeztZQJDF|8LlALfzZCR4iNH5};_&s@|r|%l`re zDitWuq*A3`U3)KD^YG7X0eb}q|9^H1-~#?9C$GH#{!YL8>MOLk_ufJHzir#DH{bll z&0i@^8KBT*M1z||+C=+k`T6taO`SAlh}Bv5o;^BtnLKWE%H)YjaTAgzjbF87&XLS* zdAS{vt~Ruye}v#m8TG@%7hV_i_>Pn|eWl7N7{gpXUwF8TNVv&jqkTfS8^vRd^>(1KuHB ze2B~id{j+v%`0whdtIdgg=$YO z)?{YI*30X(-_WV+wi);Ap5E)BdwcBd)O}yO9+{20XIAf?S*crQxvrVF+?84B?#v2Z zGfQ>JEZ04=bhpf+oii)-$Sl!4v+!M+)q7;t?Ga7cuzP0H9+@>isfrxi_qR{zXe{r1)B zzxUR@4^_HrSA{McOSfKH;I<^{fY}%}1+2iaf`Zd-;D(trBW@suDbKJ$0Q?tV3JO4k zORPR4-(=TN)t2d2qHdH|#dzy~5^2=&3+AW!g-znsM&Kfz2# zDnK!2%$T9&U4<+n2kFf?)KXw7(^21nn_dPqipi|hr^X2*A#6^u>KP}-4>fH>iMLdt zJJi>ri4DW0sp7&06t2RgFVbQ2Ak&U^P*r&?8zvE2%#1sj@nb zaD}-lUYlrVEw6;(Mu64SK}1Td8C{Yrw6+A)gm{k-sTle~*EpqHr3@NhPYLL5A|J~N z6&FdQXZA}OyGl3V|7Dk6$=d__oIl?D&v$)6$D%ivD_N%M&Beh*MpC22~HcwyyTBTp6h1Wf|)Cq&cpxQ z7k;9y9v`~n>Bk?2{aL9~eYUJ!!eiqI`@Sjg!2Jt`_U}`qaIrEa%jCbQ(4andAKtsg zYQig{1NsaYHbi|vyr};h;lFV0cIG|Qd&!gK?;`;IKHwj`KvOanz5L2a3v>1u z4{eZ`3a}D?_0?C|-T;o|M` zfB>$-zVsqpHC6w7(WQU6`1(t(D0SIQ^{**+SN_{3Nna5F4msIp0sxU2 zd$kpHNf`g^aBUcX7E}P}VGG^iE{a38GM5i@I3*^LoEVv^7 zPlS|}7$w(73gC(6oq+-P77OC_xb--fENEK=2mrnz%5<@CWAj@M;E$9HR~6L7Fz7+1 zw&866fT|i<*zyIri*~Tkvqmtk*#9z@M!jtH!oGJty#h*T0mi?Vg23M;Vhg}t09_`` z3nU!ufBr5@0E-1jdjS11nkKTs8T7)(fA6n9>OvJk? zO-$S(TUSE@9TC$tZd4t;qY*R({o+;`Rq*jeu1M4*$*`jUykO>=xPu|j~Sr0G&H)-0UYu5oRf3E=De#evsQRAQU zr|vBk8kQ(ltyHPH)21!wfqCq)WA=Xw6>eI$(YQvp$JMAkq+!$1Gw**o>i_?REr9&ckZj7t`Wp={-cobV+>gKYFJYP2Du-3NGL?+kmY3G zyZhk(_~An*MPCP<8D8>%cPhZE{=D(wogXnjRRPlAzb#;dpFcf?76>o=+ZSN@bJ46` zI%mzYIq6d;WhBP=j+mGcgZjaK@uJ0BwP-(jR0xPyW6!ik7&iC5qtN(oMpa1-4c-_>~ zNlXhMKSPeo1?|BZsPR02oi!*d5(j|YC20c2o#Go}5HaFG9stoyz^Ql`)Q_w_%YW&E zxYVG2gFjz%`6YkJcllN2t}fj4`dj*5Q$I0(>lLND?XKA8=(y1@>`r|3v8k^gpZUf| z%io?b<&#zuK50GilQt7i*Pd{?-h|Vw5>B_7a=KsK>7yB^yT+YvIN@~N38$-%KV2s- z`l%Rqy6(i&4JMo}H}-Uk+)J$|p6)W~bmeiU%Zxc)a_s36V^5cwaJqcl=?ariSBO7d zF8*}!iKlNKce?nv(^V2q*G)TJBk^>piKoj>JY6;6bmb|htHgg&dCJG7#(z|H{QKp{ zzEyI_ONH+`RG{VB#fyENYEZ9U-qq>my-?7=0YG3_n%br?Fb33{%K{J~UIJtw5CjzH z4Fyv2tx*|ZXf6cxp}9Z?qLD4Q2;AZkK?UFjlgTN1xC$?x0xzBpgY0DFhe2$_N!X+U zycdL)RD)Cecb5dxGhZRvywl4J5=Me0p#h-4dfYf+Irt``!9&oSYGCsl6>gLU;jIKA z(NIwUjk6T;J4DG2n-&l)Q3f}l!5Rzc5VK0_%Qyd0B#>{f8^&B zy5fo}=mOuIwKVWL5X)ahR8!-CzknJA)uvJ;*Q}0y3s@QSg(DQR+Z7m%wZC%WvtnaA z;kuMe`3YsMk%_R5lhQS&b<_{HMTd7Nzp6AY;`&s@|Nxm}n(MKNvzA<1VV+bgH^2sO0359ED z!3fnba`3RO?K^d8+tDf@Vf^Toi)U}&usru0VNop*-uVv;feV%Z)(EV6-~aN)j<@t@ zaP_1o?%1&0cgpN359!ytVE)3zim=R!7LA(vWs4Ol*1Tz}fPF`751)}ECeBJvJNWP> zpII5{qef0*|A$Kg_5%9%9nz?NGajDs3Q+zV3)ZSuo$-(V-7U`>x7fIT^YSJ4C&VWs ze3$~}6!Vd-w0RI2@$3LK(W1pDX;A6~(00;=+wm@D*AW|Q> z3oE4O#9+rVT!n)=V8?<#p#@yZ)fMAiwLf-ol>aweepUIai!{$yc|f5?>7_cXEzx6N zxqi=HB=(J52eq&6IPk1=T>H%YngbidcwJSQ_nR|JXdY%xjPchHJ);=>Ev@wrkq=pe(s4SUo@I> zuG*Ay6(^r7J>^`fgmcBGoV(d)^0~qj&Xr3zS2g)ug{kLmn|7|w^m7%bo+}Y|u1fN` z2D74{3JG79iaT3o@|jX`pOqN*QSsq#6zy}Y*qxj3-(Isfi@J2_YPdoQ+8{unJvb12 z7K1sav-vKW7^eZ_j_`|Ah>cF%N4Sa!pcIw^8c>Wh92%0*1@e)hoE>Qs50%~}{E-`8 zv3}(ShWPIY^*BijAU|e04OX;E+$P{DPj~4rrZ_FYXtxGujp$P<2@-W5?~Q#KFQhrr z1qQ8NR!vudPJl)bsm!4TC=qTVR3~c9#`7MLHKuszGiET5vf~1!Da61v4-XZ9?U!6~ z3HVzJI9dqU2o`Xp0w^-y6r&^1-V%oDgiRIK8k$HZS}7R+8pPFLSJSN?p&21pBRf^> z0Q?xw)zoO0K>4+>V@xy-gPeksAg{o+OA-?SLKmp4tU|UPAwx%xQ^KGiBr^sK06Ilt z@j*2RD4RkCp#|jT71Y+Pr(%2ib}6^#zSv*4;h1{{El-?xXv)mYgxLoNkKfR%_ply4 zhDDt}EvMAIty`sX4N4ZT5w?1Z7OhsVUazfNk0S8FgO3$1(yUIyF}@w#u-U{~b%xfg zJ#grxZ9jDZ#rXeI*UxhkD){*bmJC-=k~q1@o5l>e;7Gtp@RN z$uYM7;O7}Tnc2T~#e$cfKe*=pWg~}AkiaE6qFjkgajbSr)v-ec`wH`< zQNz6r+_X{i4Qn^vw`^6D{^0rf5&l6JSPL-z?fky>`WxP=MR@%8Tp|#JA_xlsr{=FVHzfn@X=KEO&^RHg|N4|JM|0k*~_2e2u1E-*!WR zyY`nIaJOYh@RemBzqR0tB^h6LPx$uk#H`^-S;LaES|?^TpPChymbGQ}x1TNh zGHd^PSvx*@XTeun=4ACu&8j~&t9e>h)5NS6DOq8V*Yr)O2q$SN71RVpDGu0JQM z?yP8nG6~<5PWZa?l(VHKeO7YRJH`4vSLv>8t5&TZGiEIQck9+222E#dF}nqjIcS6s zV5@Vu;M~UyQrt0ER(R z1ZCkA1M$$kXs^vV%&h_lgBkqkg|GyWgMJBWT4y1%ty_kQ@u0wrF%RMqLVgT)NvS+t zb#yDgC6^A>V0CHQ+6XW(sE;?^c!O0#l~4f^1HOS|i6M-f)QvSSeFu8xesEF++nx%r z5y0&qmH=TpfM3Xtu%&@WuY*z+>Y{4usP&WtLo|gpRAq|5QJaLe0$5K}02PtIsqP4r zb|k3I;Yoz$qep)1oT%=0>ULG80%Bq$i*!kXkVaSsp_Vi<%*{Be2n6)FIw~g-(1}Db zv`g@#`H32*+FDO0~`)4^M|JoY31o7Zd1_>X?@pEs%Z(3Laqd-?*- z5B@%372vpJ$%?PO`ue9T;G1v0VIdf4dQcM?NcjKWd+&Kwl?vb&(wLfs zpU?tf^steB6bNwrq=TK`;Ko@vJ7fFCmAP+kKD=Y&eL)>q0(d)!Qh564!;*Q8hfANe zKe%tN(j_aPeXAC28Tohj=xZBy=CnDFJhbE)>jiFIo?3T*#@{K3y} zhquoFE}$2mJ7mjXW_p?>fE=n-t;M$=$Zwyw+AWnw4<3a4R2AcY;>ZyRu+TH$d zmySIL^&cKy0a8ud9CpO;)^04T3I9zW%WCW5tvet5b>pAqAKvp}-YhBna@{zePY=+V-vG`C1tlx%6Wb8_)FAKdp%)|M~- zu{di$a(1Qo?9%bsrQ);8C1+Pm$u1e6T_!2JT1GVBQ)7B|*~IKpQ?tt_XV;ybU4LG7 z_36>mGKt@pnVMBP;j7Yd|1L55{nCSv*XSL68EL|ViTK|m_c!OveU=``K)s`C20k0c zC?^J6#F*MH3FC%H0!rv%BH&dJFb`(AV=(*CKpKibKuY&UZR=iMG3$!?1nyiCFCc;G z12qC*$XdpH)-~gw76@UddVyYGNK2;V6b%JL^|Sn0Wja)U=}iSjBo2IpXF}k=nnI{F z7O*&PX-O{_!(RRgi&?{oNn=P;4F-?OTG1%H;(3tGFV+r6D0N``XcPSR&MNnm;(mT z95oSjKm?2#-#&iHZNg z|Iu+HhK^ske95y(*{up?qcDp27w3ANgYj|A+}AhSCBf2lN{^c=Y7d z-NQ$uSZhSLfD09)DeBj25Z?b`HJLm3Zz7mACX1IPG7lc{lWxE6`3W!iBYg1u;D7M^ z1ll_dYXSV1hVv(R_VPF0d<*=Er+BDEhhvbKBA^!z9Xtrsyfh|kaOs$vYI}@b-M$HR<~niP`m&&v!{W-!kcZyX2gH$vNBS zp3m9+(dm_08>Z#VNXwa!n$sgWr*m>nr}UhjDLL(vbNZy@?3;D|v(;aJvHa{u%f8Dw z@abzSvf3x*l#kCTn~+l`F{fNoPVxAhqLXtfq~w%O$tgA^8dEtvr$j=|tOO5PTA!1r4!Fn0i~x>0pFCGbf(PMQx%7uxTU8J%`KBA#c?h7>>0I?11E#2?}(WO zxnV5Ks8j2p7sNvcw&0apAPYC#E(RZ91Rul%dSjOW&Im{#D+zGSQJ8=a!~vZI@@K9~ zCQ??YXd!^BP#MVY$OROPXIj9iOH_bWfSITa6cZxpLH-H_ z#s(k0MFGfL7w{i4Bp@BzB_lDstGg-~9xfRb9>ncqQdZ50>M5NKqy3wV=bT-guYM(iPc*9l~bE&UM18fp;v%uU&IstF}{lei;9i%5(lyFILR=zFXC-*_rdF zWy>*}Hy;7FXP!M-x6#;ojeq!oI4YoetwD{Nj{ZMw0sNo%KVZPni4&)M@x{OQ??1G6 z@BX|h0PXR_7&9a=M~lHA>%tMEm=mmGb4Q2r6$1!^gw@f%_q{;{?Ao%LZBGU8{G{+z zj~Kr7f%~^@SZ*&^(*%;z5-x(fNRJrK$g8+tOh?zNj1SgX8b?6@8GY)KW6;HdtT3vQ(7Rv zKUn@j9r(e|ldryJRTad8z~2-m0zqPmfENhN`EVHaBm@Gtq1${n1qikaiy`_>N&&hc z@Sl+%lIb{MO9Su^E+hRYhWP{tCi|Z+y3G4Of4#Eo<%ODDRq5V*^^*&=Syj0ELlyf! zRn8kbW8S-U!l$+3&Ni6xb)&?r+Y-NTl9b&!>3pk{^WBqjMx^HKU2r~U&zX;wez$RY zBsDcMDLs;s7D<>MxhpMlS4yOBN@QS4BrZL&EF-cwJ+gCl&v=_MGqQ z%=z}#^s~1movJnVM2T*@wrtrtdGeHg{n++VQ=B`*iHCaeA(?m+ z+z3Y@$U+ZS14%?egh+%(9{hm|IfxYFMwvhv+6a3V)exKsV%+6%ZV_n(fr{Mw_#blt z@tI&|z^p}qUa&gAUK&Iu9;et?2V7J<AHNY7fc>qI3{PLT$K1%gEZ>xBtn zI!j=xhDEMZ<6Ht6y36Z)TucgY7l2<^ZYx%-@Per6@97Guz`-%4*d8IVd)39;K9qtQ zDPiy~;=fw3{HX&~VCo0sU#V0<%czC0Y)K%0Ah6uz?5M3`lr|=nfhdx}sU@S_&)uw% zt$vYPFli(}en+RC64Jzu0(6-Ku?z(~MVEOf@!TMKGb9dc1b0ycL4qPsh7KM2U&#MP zV_V&sX4^N||F!`73|iK@ReYlccYEQJ+ow<=@AjAH_ODUHYi46Rbck=?e#)jzhw<&% z=l)s0$;3STpY&U{04~@X{&oImWo6-f@c)4Sh!JB?oOsEjkzc$|Pyv1pf?3GB82tYz zWRb{_U_U?*i_}=+_OXQ2dYak@F|;^L42GUvde{r#T3<3Z`i-zH>z4KDd3XIfjaxKp z)v|e;^{bcSzfIxvl+?ikMtOT@qz%k*@w_^G`}-cw{NPmd*GhjyKKk&Z5kp7Tsof~H z1c-jsD|at=_<$i?KrcOi$a_S?`}M{A;N<7$VcV4~UfNpVmI_rZG}^cAYG1%N!g4o- zYy9vPutqI>L5%-j9j$H{NLqjj2+L$v)^9idv7K!n^ZYpV32%YMc7bEY|G(aT`_!pZ z@4x>(6~NKti7^R^Af^j6IE+JjlE%58i%M4=Mov1#ly{k1QMn z+y(wDNw>s2OJL~zpFdr6>BSdc=l##i3pTu_!reF4i!a=2X|XQb3*G%_!Tv9n8Sz%- zaUV9G^m&CzXB$rax@}TckEHLrBxZL^I^Q`dYTHjq&Dk+4XZ7^R-dQ;trbiAf$@y}_ z*N-fTj7y0ON{tLoi%iIf>V?#_$k4RNh_uM;8Id)!BAaJNs!WZPof;{f7%7_+DVL1x zxkoWcky6Q#ddZQR$Z z5-6~y5U=p)N4dBcV=)}egQ}vE)Wu!qzL92WqmV|FoQ*n*8ZQM|zu-T-D~xIe?GWIv z*_BiCI%R1qYF_v&fNFYTV09pWjOrka`RYZKkT{i_bt{u5uV|=PN{K^%1tlW4nBc!l zo*2Z_i9XVLS~9FYv;$F|AWE*lciuTL%KsmoKm0az8;-quz|w@-2RQ#Ze>&bZyRxuv1~p3=lLmBqUQD27rXAdn=JtvH0aZ*Q*w;|&ph{Py~Y#r@c+jxfFVD>1@N<9 z0lR?zDJkpnvh{sM)D|?@ZDW#u$cZv6?k_-J?6L#fz0FUbIB*8ue}C`hr#cx=m?;ZJSn|c=o{j zndu{jj2b^Ko*RcTPX*8s{d)I*T`<4@ zW(&Xlhhw;TU?X%GIepLZ8njMagcg8upX8(NasSm*!2e{IX6a}1JK z7buAt7fkvX_Tk<1B<5Xk;|S{%;UM9XN$SQaQ=)&g#mJ|%tr5gvK7ApKC$s?XkaeGt z&-nb~MSuPCpZ|Wz--=&;Q=O~JbiJV8YFyGBjKCsHh+`8@5;BIa(+lk&cw8wIcYgdGa|dE=bT&lUF7h`-){Tzsij#- zX_1NPk%?)M>9jysg5*D9&sR>*u9);~wUo2<(oQvsf3aHc|KWcw=A*_xaxx$x zQ5_xeM@$gQfe?vofw7c=NXc?x6MaX;DR#jHp#o$T)&LLv9@>e_9cMKw|s2arB&MR_`s)rv%vv{;jVj@o&YRqVNc8|Ui5X7UEL{&&ozU|Iy#`{2%8}bn|!8X4}5_&-v4#TY9aU{hKtryL_3tJU{qfxnd*Ee?Rj4 z_rDk60&3G{Vuub1J9b3h|M?03Cq=gaZt2yw%e3jsk43kD^K1dcUIF?g``^y;t+%$n z;QPO^mp^U$;{SvRlVki>04iYLz5}~=KV(Gleghz}LR`Jtm+n_FHk>jN3^RZd(COO5 z$TWm#3TX@~4B?&jLkfKFzGfSB!c?xsY5=#I-_?(Wuzx__?IBWs(F>-JV^~B;#`FBg-~acY|8(_# zUsm+eeATZg(e|pUgRg0r{P#PS7V5OMOs@ks_kF6sz?aL6e5=-kQx)PqDH-?q?TKf* zCV$m7^_zYvS$&hfADWsyDdl`pTF%0ZoITUdNA`Rb+4JQ`i@rHHJ7>kTNP21{BPB8` zJ+gJ~cjMC|os%O?+4f1f#(zST|CRuy5+mh7o;wKVr$*{bjr2>6#7&Q^n;Yqv5^0zc zRSIR2BW2SgWm6+|0m>(3S4sP}Z2Z~s6F;ak;l=8GcdcK)L5=&}+Yc3gT)szt_Y4PO z;xu;2yoP83v$4g#QyKxlrIZhL1)>OuaSXPl44o3#fe}1`5s@$=4U~x&$yDa_wgnt^ zKN-^4=ygzjm7oH&Jot04h^HeYa|`&xV<4CeAqePnmI1)zHc;6HMvD<*(P~j(0C>8| z7<`84%GCEQ5}aqT8#CZf>FabDXSNv(wh~Nm?-;P_j2!i4?^%0F$+R;h)J6HlOD{L` z-MBJ%m?DOyhXzoHv5+ZNte8q+KGkM*qb{_7>cEBSXixB`OtmMwTFa;)=JXa;g}yCwi!G=spEwDJg)u zlb{HK7SQ8A82|st|Jdel{H*aBbe)-v-XtDXbVZ)&S zx5tj2VEq55{XfhWaGOp)vjzMc_}_qjnKWrpUUI(j%E=3yKVe@rmWB%O^+5x}0MO~1 zH*eObIu|H{a(8O58EIZB(042o{b<;5m@o#63MmC>hsKSXV5twMI@rckKv)9UrS<2! z;wMcG@9KwD039))@8H*7eLYs5yn&n?+X3G@+7Ui_B-0m-{b4VE;fpuvsiO}*<%Oc$ zpN#M$LL2X&zhd#4u02NIbi+*)P{;P2yxyM}pIoC_?Pg6|mMv4EXp!Q6^Vy1n|3}#r zGWHXo)K;U0jn#-})%XX0b`h0lTJ3yr->>kW=ij?MVQ-hUAEQ0;hfmDyFF-*s{$GFd zE!YoYZ`}`T+iS=xd36CTV3DO4OnHqQ?0*xP&ed7iZl3Z0V1fV<5Glr0^Hh4L%sB%- zm_6<_ktIV3GeRUWarC~~#2xX6-~Z)Lf4t)2zZUrGwG}Tb()5Z7J+G-f_J*d@3%0xO zhAvyL@43HdzhgCrzF2?6KO2sDyZQJJ>rXu0JnoB*@n3dI{%U0Ewm9>o@Fmf;q^TKEMc%wg7nkVG{!x$wY2} z^YRw}x}cR*1c-E^uGF*KICcR{H!D^n$GaK)_7?2sred3kc79D*t_lPTLjwP42R$y6 zDA#gbxKzJ!#hAC$wGNdtm0_7+Wy<)W8Vn4NRv0-OPL>-6k9=IRKv0Hd%a%FS4puSV z3u5_GVL@}Lb?_bGf6H8vdB`d>sTwJ*x(5!+BxqOxk5kT2S^=V{p$jxf5Dlw|#ODcOU47ZpL!AC>|1kqLk+Cleq>^S&B=l_qJzrOj! z1vF%2Vx77jE0(*R@n5l=o!=k)|F!^p{M4skezOa(ZQJ80w`t44+ZvAJK?gql-#WH4rQv;ek) zkEH=5;-R5p80cS9iC>zX0GLLC(Pbzagoez;i4z_HiPY? z#Z6P|GUU;x!t603UWX!laLL-6Bc`ESi4=+MgMUXVQo9BCD?_dp8l$-s5`m?U+3gxLfI19UW7TstvJ8W!R!*W*)R#^q zAt0rAdB#Mm>QD(>A~Ga0mn`-;0Z&&{BSF2?muP$vbb)~8?bOL@|NrskCvMjZo4-?b zB+WZCaA>?&jD5ShLWSyAU3Jqn*A(>0m#>7^K8qKp>zg?Ghz~WM2M<_dkF7SHNQa|1xEQ{r`*nzrgvER|S0f>1Q)$%+)~} zAvC_xXfPNdyg+)KGn~_p64&W0Oyj{AGfwCQgOCc)$hxUb>vn|;6%9*(>eXt;RDdPG z18bM_0zJ5G_1qcLMva`9yMY@wH9niuR28ezajc<-@MF^tpcnLg7fFpsSjX3h@V;t{AYj#35p=- z0$PANu;vOH*_ecapbH?Kz&HVX&U|ScB_JYQ)py})?m&*hU$2EoJta3|I{?s>)bCse z-rv6Hzy9>ci!S-|pRfGOrTH(prtD?;>-?>Fo2x6{b8XGhH#A5o)M7!Y4y(&`*Va-9GM=9=T;|q+Ld2)7(f}#`#Lg*|%nVTQlu!mB}A8j(f2||6P7Z zl-sy}zv!04xIw3OTwYhM-W07a4=O27yO{FtIcUKqwKBF3CZ9_l8HfJ!k|8 zLVHRBYxocNQ~<&Now>sv<{@GKvz9T(Jc3zs4X8~t-3MjX;EXOB-0TZB81_oZs%N5b z{)jh3Ex-dv6->R{1@+z>^Qs230rNePa$&cFxpAV$m04m%RbWN+ILlt+!NTA0P#*ah zJYIw_sVN$&!H`oz1PCjA4^>X(k=PGDTz1)I`SRtnbFDhTb7g}YB|HLzVb+7B#9_@s zU_5k(mRBA}DFgfkNKlk6DHYKgxNW$Gb~c!eWHABwfD;o+O1vkkAT<#aO$2Bzg$$+V z0#Y^)3Qu$lxl^5E>D_&c;K*vu3dZjfrSwx#`q(a zS6q?Lo-dm}w)0!HYMZK6+unTht$zH+J6u4wcKyC8HHOFd?{_2`-#*D7i)nGkly+UF zc?C4D{U5&n^|OBhAjba+6`Iwq-7T;EAA9+yfBzxj&7TXLKS2f95r~iX+rrc6bmLZi zRYOx~QoXOc`9pXS*`IorDn}dcYc>M|6*d_R#+Z&4u%*+zOE2&C+;~HN3jrGec7dZC z!F8JYp4X=JD_(eJzaQWG=K}1% z@cx&_-#Y!myZ=7^{yCo)PDMW_PMtgY@|neJ|1lxy;rNV0`0smU$%*MZw(dOk#IfVg z9bdh2jlJL}9(&^c<*V?2Q2(KGX3oQW1;c*@6Sf8H6(AD_gi+TBH@P@Pf1Urq`Qr<} z*dAW;{3-ck{148bf4%*#Z_>rY3%3^UXm7&CB&GJ%(QaxWzrMyaJ?o|J-~a9pfB5~M|MZ7T|9tT^ z7hhWNlB>&JdSk82injP$*>3g%uB<)DH^K_sv7~&*^<}&5s?+;Gk3ml^9QVSB8ONWR z{pRwiA8kzg?7iiuzuNwO*7}dX-}7jy(l9yFASKcu7xlbAY<|qY%_rB|FFhs7{}!o{J5wT^lcLODK0m4gI;KbJ zCP!MPo%dz2TGPI5GW%@pqz|f(ez8gaT@O64G0OkkZ|$p~Y6jp4qaVHzfdF=GtNI~E zB#B+sM6Q|(j=*JjlYke=L=so!L&OK0lSc3$d7=<#m{7sR0de5Z;I|9F9_A+z)))8; z)NFeyAj~pY=5b|;;5_Qulky-j|PoBu{Ecndu|O|D~5+ zYUkJ2*6d%i{AHqERyVvQT0mloQp;!rfxz(4q?(r)mddY40sD@D%o-fAL&deWtZ>QL zCWdi13gi`$ZV7#)J7VHqVVQ)kQ3b{Dl$fsZPz8|8yZ}8Crkk=!EUe`Ev2*94KXv}x z(LQa&IV10DTgw_LYRPyyx2HEPhHZ~gkcD^zGYfBwp!@}DAT z+G6q@E#sTDO6WaoW%O6z@_YsCmz+P+1pasK+>7(SNt1zj`Tx#4KfL^d|G(t?p%K^% z!-tRYGN75EJB&bmWKbCoEDa;a$Ykvs70eRGfCdSp(d&x{W)l-ww3Q`fjT*Ij_3XEF z(TetMI@n|N`lYw-YuAYG1^CIG`7=`e$rvsj4t#EWKN(@`)}p}i`KR_Rn?GamoQ!9M zpU#X~`vLpM-}(3PT;NBs5B@)XUi|Rf6DQAXc<_U?`A^5C9f~k1 zv7;v(%sjYq#cKQ?&~JzpL9qF$r|?%GgA1tRot;3~GRKS4*3|gFdHbGUvHxSvpTK{| zpEdr23gG-nn|Hr0Up9YC0{=bKnmr~lML;ju9q^8*h7A&UZWd!jAUxn>NSFm?t0~|V z3Ur5X7|HIUDNJOyxMYqP*ruK-k5ndw-gLBP_q$$yyy%Y?{nsDu0`LO;>CabRe929h zTv6h(>#AH{pux2z+Wx&lul&`A-%vNcP_tPj+AMF^ZR65`dyXVL{OtXiPbI%}FyUX% zrhRxg<&#(DeDTr3e}A*$G&u5YSpMJRJJ8%9ENsSChjkHgR zZt1p5iL`MlG9z~vAa^^UTzu5e!y{D5YyXLnN(s?dK*wZ6wl9plec$){=boQ4Kle4E zr1MoWvTIHMw%+u!O)^eZ9rJFu{6B*z3pL^>MeBH<;pg8?tz zF&5A`+AT^bzNGQv^Xd+Skwds72NL)nGdN|XNg)MbS>RA3TX#975v;SCH*XG=c7%aQ zH!-U?aCC~Sl!|iKmCSN6<{E%o2q2h9;#uMq2_corsf8-j#dd(X=`O-`iT_50N9%5O zyLBI2yTxJzne{alU{xYpm#phebA^-=_7z^3$_Q;`B2W-ilB0pANK}$_0mUJKSCyCz z_OHG3LmfEQuOI!xi?%a7LYt^Kh2n`p1>`nZ^q>kxwYnIk9tXm)283dF(H)8x!cINQ z*w$P@jN}W%Trf4_{h$?_wL4Kl~5_Ii4_-C9y zjmNd=Jgvvwqq=vuwH<}OcWiuYF8S+ie&{s!2Y;e}-Yb9pa(?sQ%b#uAPP*+je_(DQ zFZYIx`(yTh^sfUqk89aFp?;%r?Yd0Qb^g5fTbw_6`Cp}q-yt99D_p^8l47T)&(I4-h}KhUO#vguhM}eFfl*4pXL!(t2DA3`2Ev&$XT*DFQcD`rRjX9< zi#jV;tbyFg6XJM9M-J%kdstq}_x)eL2;^@E`~3$hfRo43k3u|gcsJ$){?@fi=Vl~s z*|Ov1PtI}gu=ZovKk>o26F)LP27iIT|4n;8$yoU81^hp9@CYsN{Ik!mTeE)hq=a2N zcKfwY4j&5y{Euw`$6P?ZZ3DvKZwlB!dwAc$|K)4Hxy~QhNBD63S^Gci{3gy?{?5Da z1AdS%eiYi%L$$31drX2Z5NU(h*90)ZEH<5uO8sJ#nyr|icT54(fu@e4AwJ#&5f%gZ zrYZ@n5DzkL!4}g*Ztw*@fMD2%`L5qfmo9znwb%aXkAJ%8_f){e(RV@rbmhf=x&D&N z3SW9v*~{`(zp7A^zn8r8#!7t()f`=>K~j|#^E!4~wP~2&GkW-`X$SwY;Ka@;Z*H3U z!Jgz#UzzsVH`_k??$Og=RaQkedN&RkIc(%lpLv$kW)S> zr^@u~CJVo9Ht%fn>8Jb5w>*Y^h{+%&n<@xj3dHElVf1V$2I1ZVxW!0Ylfd8*JfAaF5{eSn} zasH-QjQ?TtxBo9Ye;EJp;};e%Ee>t2WU-Mgnt!0l+Bbi#Fc0hAyVQCD8TS zjiq5r$ZIM(l2q&=^4!0^_#ab0*V^apdG75mkG~i7_T+_s2*+GN_&;cHJTDW^Kk^?s zaCrNc9shdkU;p^WE3;?LdvNzdLk5jR`v&!!Ir@Yx;Ft@jRm(Q~Eq1ZJ3+G$UyB^&8 z>&AcV%^%qRCClH>LAb>D_k%wlef$aP`x&LY!o43>9P|zmCMGWxz?nu_co_qHjM8Ak z8=u0)zupNj57-amHVj~++FXDImn1f@9r+npZf z`iG1D@Wr`{-+1NaMgM+H`KxZInXgE*8%lR7Qn_E5+s3zRo-wi8 zqH%X^UO8&_fy75=jeU8}q_-bVJoWLakI(IV@7o<8e1G`U^9Mi4dEo5li@tku=J~bL zBlFTDi!&lqQltF$jj&N^kwM9kSC)T&W=&RlTBK)cWcKt3yn6-ItDe#C0_4Jf*{le~ zF=Kk<@rBvR>5)E3k$Q*2F_p$f=MMkMI)Ys%z0yi z8En?zKmU(+{$bOEqMCII5x{VUI?O5_$BR|A;?d()*4(hh0P;JvMP*_luw`AqKA`D$ z#ymyfM({^zYY=P~Ru>TSXp`60L$hYhnCJweO?f%EONP9-rnwnyFc>NZBv+58SXp>3 z<>Jx2Ql4V{QmRxbRj_8X^Gla8{$*~xBSSUyEN(6%D!|{O1N?~u#+&kx09cGQZVhrx z7bqPXGmu3EwfvA>(zb1n=Jo#s9F6cOBBV-^5WP z6DEwGJZ{{)jHD+XJHWAX;=SlL?uB;#e?mTL;lFxj{hm`hAN%md4}OOKF&EIZMK25* zlIU*)BqpTp+P<6pZx`ULH{W{crI+#l=%YthEL-U-z~281Hb1xj4=$kGKLpvV>Fp|o z{Ay=kW6Sp4zs`R@_{OXMOXQ~%z<=9;Cj|Tw6*uAKT-h~|LLN?Uh>Dw^Iv?;4VUD<>Tkuay|&_wH{Dk7=9b0F z-&L)~@VbqXTDDr;t@FlVeKH3Oe0uDNSLemOcWT3_vs>T!X2qGaOaFcTkY*{fENiEz~yYTOi%&g z%&G|hGJw?-CO7aJYRgZ8!;mg(7+S1!Ip_>jl`XV@?AC89`;cEZoI7z^nTx};Ibyqn zEOT8q;D$wz>1=W$A89?FTP+JE|nsz1>8f> z0@mTK+^3Z6+__(v@GXAr3;bE^&0BEsY3ng>Be&1lOEDFI|2lu?&tDtt^VI&|dW}YK z`}Y`df8_c3|6=?{_W!;w9^CvS|G)M{M#k*e_>Vh(jsG7xatzeRyFwr~{xuNfx$goS z|1RrQ4Y|(<;d>-Z6g=eNk#}qfE(_m?#3cr*jgnD+llY7WhU?fd*`qSXnXVaxEyi{V z`z(9UK9fz0J#GGTbC$ifYV$kWpZ@&m*S~@8xF`2)!#>_3+Lot3o4x$q?azIF@RQ^5 z_7DjCU-QT(dGlTxo%_h}k@>A#wV#ncd-tx#X#rgTEdK(ZJbvTNzr6XDCIEv!@ISbK zOavOu2vMbG(Er9=i>L$Q{?Qxt@8r5zkoB?L7{42vT{OwYY&_l)vs09iz z?Vw1jBh+*tzr8kwpK{GnP@{6GZge*ZwT~I5o?-=1TzcuHw7}2L`}wbb_MexZ_p3kr z{I|dV&kO(ft3O@z+cG6Cs(keo4X?ho{Y_QxZB&0;la}*Zbz0xK=M(+=@6Q_c?xW*B z`f&QEZ%p}SU;aN1&OGt?{C_5PeUjMv)z31y*@I!b)T8^Lhba%u1n z6rK-h@!EYgtT&6WhwAKz#mTCtvEDeOn!-=KuYa!U@G=Qf?G=s$)!9i|K}71TQi{m)_frz(PCD!};9 z{QM&Sd@BFzHW(J%{>%P#%qP76wDIp9;mvzLU$Jgy;Qz>xKMekS|NW@**Eb(I_TPN- ztzwg^Q32n4bByPo@lQeY?>}VQwnst9;P=_H=YYS$p#M=zlj3HFC<*eB4^x?hNAUOJ zA?+aAE6J%6Shk%y-Zm*GZ{_mUi{>wxKWAZB7R+7b=gu9Ejn7-rxZAwGqc%>S_sZ&R zpFI6q#Q$@;bj~LHo2mdIH@c;1>n06vNvq$q@4W+7 zu30y7;+%6f0a9Q4I;YP+82{^bK1~HAoj(gc{^T?8mqc7Tz-|bTA)wv@FuaF8m6+Nc z{7$e>1*m#9hWNSw6i&rn*;c}peC0M2(O^LZ)nKoJZ5>3>wOvfditIpV5Dr`Hg(iqQ zQ#m3PAZJxfYZM}iJ&TclK-br{y+iv$S=$ZC&npZo!DxU!L^0&t`n|*9BibIpz4ON#8$F@clav zoOoy1_md|j=1)$1yZU(IkAyd3nie zTr>-uRzSJz)78hHo;&k&_uRq?(+X?P`M%+-?;6cI*=+tlTg?A^vzcGl&-=X1^!GaD zKHs3%y6xL_eP-i-F~LJytUWu_goF|Z5`0AVstMM(EtMo`5Mf)wUMIn>pm6QA%OO(I zc96j+Tf)hOu~bR|wZox_1qI*;uM&X|=L|ERZ4d8=?X(EbIH!3-?|{1s5i}6wAiaRt zgs~0Uy4!%4GhYprcOq-<8KhyXj`&#WHaKs!EC}fF&*Qd9+jwjUdOH=R;Ff?6gxU67 zJqm{V(ecC_a&aJp_NnG!@~sT7K3$UbQv#7}#be}(y+LdSVt(c<{w3}Nk@az{?N zilm@GgZN3*i%>P(iTep6%iO1D=iV^kf0Jmo=V+E@ZvSS@O&cDK_WZZ}rwdY5K#3C9 zdYyu04!<$~>opvnbo;L_X8D7E@cbL|U+i-L!SiF|)@MIoxcp($879a7v`FQD=={C& z&R(--%?k#9>e@ZbnX>@-EpAer&_M7m*p401cco=LU$hKT>SUv}=q?MjuzCo4- zcMxS^1Ok_}iIgXd%N;&sqyazGtJbVpqqe0+^;(wY_b>nItFLpWt*+86yW4>KfqK=p zBhMt80ORe#1i(VADgJ@n0XulEursV&;Qi zu?q~YGQ1{y+wFHJNBEqh2@v=nJAcmE1VH``yY~g>k57HQ z1L*I*%dO(IB3twYOLjdim1{y)V6I1hwF1C@HVDkrOzGPQur9X)ceh5M^Mw+z> zr7e#wDuQ(&n~ib(Qq&!bGXYuZnu@Qg5|~mqgL$Ud2l12A=Os}6z2kHK`RD)g|M~d^ zKl|nH&-?X-|8c>^zr4Kk|CGP>vU;VgVVS|ah{ogfPc%tE)f84t8c;lJhc3k##$3n0zE{ z!dvaLpK0B9HU4uC7-=3V{uzG!fRWg@6Q_?flx|`u2qxfS;6$V~sDR^+X13*!QAG@Y}nV%vBx~ z3=Il3ngtTd4~M_URKe*EC!u9b`|tZNW_#8{6z;*{t`7M8Kb%@r3I4MgY*dy)ayhy4 zcnawd+Cfr7m~!;^N@iR*VOgpMO&StY!UhSMA_Y97)PVZ4#ddctBhDNY{V&S(k^LY5^5ZCQ3v1NxF0y6sG#u1PI@AG^>BDn;IvbKZ8@P{T~a*D!}`{M(lo= zoZmk1Kk4}ycTTtezlA@`f93ke^*FU_XL#xzzATW+|KR**|1VguIFF( ze*sQ%?x3)X3fQ^xF*uP&3=DAK6V`!GEy@CZ9&a5PFraMUlElP3pI&y~1K$6N?SBJ-@W1Mf zHGD6)YZvo{Y6Udp3!(zN!qBnv-NVM`^8%e&irxhd{Er8Go;~=7M&S9``1rGQ1m{oY zWb1AR4RK_vx+zNx*;w1rnbwQcHcR?|0{o)@!EUy-q|+ko2l9Vm^k6P!MUe;=bY}6 zljt}hQURl#$vHpG@K!!IQE6hLcK+$Ad_H-nd;+G{ z%5+d5IZ|10&ERQG;?JUqn-PFrP?U zw_z7;3qcqN*W4-WdV&B#9IELpN7>@(x3a%*pIIX{h~Y0ua*h=|okcX(JOhvxE7 z-tKoopw?3O-S2)EEPp3)1MZ61??EUsZYXUKO%hEE@V9ou($j57hmd*_&_?A-d9yL% zezHNTRD*D!F__R7lFOw-E?9?r2?5bC2kNbZ#9;xqoqAvhTL*DkxkGWdN-VJ!a2v5m zMu#AOP~Z69xLGC@(7Z+Xm~Zqw$5K~UOG|4xV1S;Zf8zoQN`VSsX&VuyHUHLI?;tJy zSE|;pNsFwW1D5@m+yBQb{|$S-*!0Zj53GA^zyKe8GpA_hbMhbjd3@i0|APSbcpZ#? zH-`W2f6JC_-+lL8yjK8)OoS!{6mJDj+-HW|fmn?lv>1#`sx<=M1T}n#G$`vbC z7JPQxLCGWy&*uv^z2cXq#f>5^rmGRBrFS*BFUYrGC{Y4W`=^YAxr(XZQp zm5Wv%+V;$skzsFy=fC#+7W4Di`x6nOCcvA~ivZIXzcDg%PTMw}y#<^*A#cU9RYn2* z<;}mm^wKL2EMN87!9!sbXk`2+U;eFBv1<4h@ZtqaJ9p|%1=vmnlq*x-$0%#pYd$z@ zT5_2hbODc0vRyDM@ZZ|YU&Utr(eu0U@qNMmH%tis554{d+7}bfe~>?M;zThO5Oe`8 zKsbw(SQSK>q<;fm0+--RfXE{yUq%GN3#)f39Z{QX_fr6ERHXnzAcCeql_aI2(Gg0! zx~YZ+!GAxAK+pn_kN1og_|^Hpyy)lWSN_FC6@FXh$`W-;U3Yu=x|vm5Ev|X{!yWE@ ze#(fq=4OAKmG$+CiT@Zg;kyAjW^Xv%At!o`E0EuKelPr5@ZaSB9R8;LH|Lw_J^6f0 z@?2wDqGE2sH(wgfIaQ0#XZm;bXPii1e7wQ*WA&yUZMWd_&i8+OOTppV*?(=B|5nQ> z2Ww~StJ8ODiyqPVN&J@-9zU3WX8;iWhY@S3A>HBxL`Wi`>c}ro^%t<@nf+0=Uc zJURmZ4SP09%1Hnw9j8#m@b`e! zs05eDl2pF@82o8K$s4js76gfN!B6)liICsAnBc#gKXXvgf0+`*Ic<_kYLlyYWO7a| zKqJUgNk`~z(!OJV&Yx)7&!Ug{)-$Wy)g^tnxib_9KDx`St21Z*%XDzq z9=d%84jkrAdiCndu0f$x_=hkkZQlHF#}1v$mJIu0R);XXoAp&!UTv{UyFgw`Rm}m- z%<9#c(={Q~i?@c{Jo)&O*8TbnU`Y+AG6;7tqLfn z5sLk!0=Dh@B7gCrth`;C0PWgz8Zvm~q}-{R0FQ3lv1Rkavu4hFcT^|2qMj630i{1L-R?$ZNQuq-@ zT_dVq5M@4KO(0YOR#4!Qs!9~{RQ}t7Q7SSO5cA)bSZo9+6B(=iMu1fMKmSwmzplFU zqUu+cX;-G^@CvugtK4OCTJLB7Jm@dC4gYB1*ss|CYbKrCJiTye?rHFEl6>3O^bS?b z@L9F+6 zw5gxepZGzCx$kyc@@BJ12U|~ksmZu!Y7N?1qvx7B9r6udAIQI9&!=m4eF*+8>V%dF6DHkv-?EM!|Hc3F{`*CpzYETC{-8bPBfn#5f&Kdr z(gy?SlwQe|T7hky=K=tbbFwcHqwkk^)dk}@704C^E zbYqQjXgbJP@|S9{7Sxc*r*bPVsE3mph95_Q4thx0c9K2 z1LOrFWsns0Jr(|b2Kb-ZAN{wHVW}&y#Ls_s^{@VP;U6krS^Cz?Y7D-<`K&6pZK!_t zGtCCR*>S{&gEEiK%s&3v(qku9e>ySeblVBhg#RXds68QirOPxv_#b`qB{}E6fDT_@ z`>HY}TJ!(kH1%|&d8cYlk7jtQpMN}U`qwqGKW{wc!zNSSt(En9-ON{8PkgR(!Jf7` zkEM@#xNg6-Rl6*#e9QPG|0iQk5RdPXJwA~ju}G+x{~%?(>s@ZA%v{AZAb15&NR|PZilS?1iMTRE0rd4(Ra{JQ@;BPIOpB(HQ z^%&oQfJeyfwQU={MCJ|+{^2Fo644N_1^?LzG@Wz0 zB}t*&3V3!FwZa*bA9X!NpfNJD?G^PH;~{P3OUN3#G@6j#Gp34-j&<4)(>l%+0cVr` z5}D$V&Oy$p1>A{@mJ~rK>)UT1(zG{D>UFJnT@3%|t=_OSX>x1-{)2zo3l!jQ zbl%dX4?O$q^Iv`S^#>mu9y@Mc!{%fAj$FTV>j$Z*|F`5HFko0{M_{;@{-1o(c*Q4u zJk9ve*#FPqH0=Lu=a27vZP~KT-GaZn(gln>=Y+qFOwgBKe)ZZimv`k)eqMa(|1A}O z|2mX6?*3xt(nFaOcW46m%4F;X!vBpAZJJpy=cy<6ELw11=miM;XY=#+hY!{Sy~^f3y!i z|DX%3gMfUHv-z(IBLklN_j$kh-T9aO{(?%Em2Q1m^?~J@%`DULq3U-(-L(JfgEJ04 zH{h1#q-1RH|Dd##6+Fh ziMsPn*PeT-!QAf}&;Mt$`N!HX`MhPp;al?FYCY-ICRzJx4tcCrzimwhZ)h`Wb&Emw zH@s_Zwf2)MG#J8(4JHBpA)zEoD*QugNGPc7byX$F*{D%#_P^m*i27qH zAQk@m_C0s>=vRTapM3J^qr09r&)cF+?}za`XRm|Jzv<~Bn?EMMb826VAD{c!V^8Q{ zVWIOMI`q2M*vy$f3w0!2NXW0KS|G}T-Z_UhR zYD91u2d5)DfQ1PNw;O#Yw?bP$6~Ac?i|4>;-$j0mvt)Kfo$V3abSGKN82>2(0{*aX9e&1ZTNrOaV*dZ~yx;u#{7Wyq;D+CoY7|)@R2b``ZWiADf(0*eU0<*?zj`B+_#uEnvboYfS*7eWFjg zB>g|7vl6AoMsI#q^+m}1(>G3zoImvnPBtp|d&B8R8|8i2BJZtRC%yRR?A>iMHl_7i zS*6R8DxK!k?ULW@&PfeBjji5nX!)CZ2L1=~ha|F=8bJlb@V7akSWrZtK9e*ct>y4<;=%Y z*k?%dsAv(;5#lhX(UrYzFP_7!z4*!Uck@&LU%e|rw*bEJ=j%<-D1b^RMtl6%tw6u9 z;hjPMFQq__$WZ8`KAwO6d5$1AuU}6=a#YYY^aV|U{G30ufW!Ix`J;G&oRAj4e=QOB zhWuJ9p+yk*5B|Zl2n|fdhNe^S!sC17K;S_BfMtkg-fJ;Q$&j#8K8T+Z5b8-0_h&@k zxhC|W)Dz)M+{h@3#i^W7QaE`m;c~^afZPf9W=*mQ{@K*JIV$c4W%UP{6(o?#})>^GdRyrdw#z9 z>g$Y*F)l=5#r%hE3s3%4SClGsmG3;3sZqT)Y#J?NBacwE$`MF||KBv5&+PdZ{_9j_ zMYm|yI_msQYo3*vLy6D@Is*Q0sQ^6)FTDHhhQ~h7U;J9;Bu#*5EU1a5g9=!);z2JX zco+EbU5}d%R7Y@_3&>M=E>Drl{5YJn{A+6gi9pTi4j7b~hwYjGXFGpv=llETrdVmYGmwGSkV+crsc^J}Qi%Ty`^8b=5 z{jX}Ae|7uy*Z0`dV#w>GvJTJ9J9=dG(N_wN@1J+F|D@B*{&o`*cjiXZerDt)`sXI@ zniM&LO!dI|!{HPBKjk$6rqBYXE9697o3exE79KHH+OKUTqC7 zCjAS-=551sy#rJUWue1Y{4HCycxAv(*VT6*vS{ER?0;!nEDGD z5#opJu$Ch-)CrwdiiJy92SpHT0RbnMT<(nsctu_FC3A-yD1XmG@RX`XSoW0_&gp+-D!pCcm>; z1`QfMW5%2ydey&DKUzcKcU1#YZV zJw(tKP@zKAIS)KEZ`C=RKWCi(`)C1vp}_yQ-+9M-Ua`P_2+K7iJd?wGept~3u~MJ~ z`2X>QD4c3N2|rNi*13rVQxhh9Gwp-%Kll&+#(Wz56M6n~5;sjxw48Rj&V*A{ z#(h^Q=O1;aeAQ^`hpnd`XgO+U{T|EfwVhJCaYnO-ed^V`qiW^O*OhO7V}-U=%D1|{ zO!Kl=HrTOa2dfgsLvmS5E2(EoNFs?Q4U54a`AJZ<0Uak`=^?7HrU$P^58iJ*(olBv&ZmejUbV<~vbGH3;Vl%^MSw!$)O8tnsm z92ZP?=VVtqgyV=!u3wln&TGUtXT1Y8i=FR?(N6g4H6m=(1mM7NPWC^XI+c>62|#i1 z{5v7vPL(QEC&>7Ag6ffFs*lRz z{)s^MJBBxE(4Eh}bg61do4*2^Keq5OU)UCU;p(d^`}DC%-uyHsC#V1^!OYggb}QSKqsT>-(!8{c!8P&zG;=C3%9)AI$!sP@Gmn!&S`5ryu#5XZ9IL zVwA{JPd$tOVg3h7Tnlmf^qKJ`1b`(Y+3oAj1t^`=y>U3eU*Ca?rt+VK9Ka6s_e*KlfaNa`ngCJD z;*1LDI$+hpRc}19_h@)KEN1)vCcyrG{$2e4To=ITi90eU?bZ?8zFpVh!$wm*8UlHf zrcchDGHmdOO&ho1|MV#ZjDLEKdH)mq4^03~8_(+*%UpBa%=_17=FNxq*!j=x!}!O4 z#=phSnE&s-_a5d4!TdA9!(R2`-l4wFmRKLi+2Bb)C)GUoD4XTa8tSrWY*8J8{6D|= z#ihUdeZ@RkBWV_%uvT z=GJp!;?SbgZ_WGX1aEjH$Nx|PWwH`R{%8Ww0yT0I1M^O=nse&Ux!+aDIbL(>7xnVq zt2_MJ+IOsP(q?*-dV?F^*tJo)TN{;WTEBE!^(*V$bY-1dm)~6Z(wf&@RCV*_%}|yK zf3U?3%(qdBos;|l{?IM8MU#eS_)&x)KP5Y=14S&z>1-hjLUve-W4k!kKy7cx5t-sD zwz!07GQuudCKp7I{<6th?#MXFE~y;?N*V?9vTVZY;2@Iz8Vd@;{rBGwo>aDWL9o?P zomYp4pQ8r75gzclXaIo+iI<*>2Dgbg^3=#5^5BCHGNg4MNIJdgYM#zUikwH9@d-gns|NQ?3 z7Ah)3hYn-m$5(OY{mFSgo$x0-KQa928dpr^KS)O3^Qzwrx7ombdJpW_zH1()H<-BY)bgv7^T6MDEhL2mU(=b)a83 zbO%?g+HO$xjy2mq``=Fx5mZBXL15osj(MSA{jSdn79Sjy`{?M2k7nmCG!Rr1fC|VM zKGxt*{NJ)^>%F}P^8W&Bd{lvQZDW)nMW0<@SA^#V-FOH7-bF#m%t0ONn6 zd47EMm-ByY^o3uq1L!Y)WL9CXypuO%|GmSPq$RP zsCM-Ws^9#F%5^WSROiANikotYHV0*(p=CR7&YzuRk--l5|44a!|x6WE#bfxy&S%N8At{AB6} zN07aN{J!myTpETzix!6&wGa<;Off zsqjCW|3*KeG@GB%o-sVr44>w9OK;JZJGc~|I}+= zKfLEl{5J|{#(i8sk0zS{v)bqdPV#@muuNC<6`1>%_%7IpW=&d!asE`8fU0N~{H*AOzD$xb5 z>sjzw8PFo2hC(lZ3n??MLPK#?2`FYBP(hVw9+U2Ko}l<*`1|QXQaeI(lKjE3_8++t#jKzjp0It5!X@X3aXZKXm8~%WJQ_{{H(Pzyk0JU_+YUyT2_$L>Y`5yK)AdhV?G=Ggaw zl_50Om8*2cCBDo|G5|i|FRZY}@X*=~x~Eq@uu6aQjTNiA`cJ^$E-eM*cYFL)6)RSqy?j0Xhryq* z{g3~l^ViG|Hrne=u?Yo>^!p;eNifb9?tR50RpJIZrd2NeJg%C_nd zstFpXm;o&67h)9Sd_X;h5VR-3=1&6t2j;W zs7l2D%iFKJqQ{<+_&@CMH6xFf$vj?e+{vR5|t)LE+G6jBB)~4sT$)7$K{;tIOf|bBR^@-=TMFAkKBL%GMt2$+f5{# zT)I+6$)#J@Zg+IQeM~6WQ@o_j3{Bx zf`8z@wU5Y%HZo(RKv;w|zykRL{HINwN?AmWu~DO}qa`yF>jt2L@U$Oim&po1h+$DFS#G&43&m zbx9l0#B&7|U>({5dWr)1E0u3hwNfJ%KKBmqhoxJ$o~>JZQ=@}- zGJ>_A#C{R{OO>i|2L5RQ{s;{IO`7y=-FifuHe(73R)6~GXWxHc_|w?8ml^-kOE1yR z6nBtXwQlCVQ_}VG@&*LUFkrz?2ERT;o&H>QCgkC-n>KAG)zhupD6auN`|Pud#Kw)A zPo9isbubomzyPz6{OFjUv*923uiX*)f0_LT%U`y32O0S`DE78tMH9 zFsZ|XCwoPVv>!h{xnu{UejKZQ0w26VCDW%(&tctX`^$+Jy9x?;n^B->na%N#T;|N4 zGk4D1g8YJsxf3Vx_n%q(%$uACPV-rs$z{R(1!7K~G&yqX@H`lxh23Wani%{jD%Svt zof$-C$tfZ$!(L(V$1#u;*$H4@4%z~q@>&GSI%x1<%xlsGX0rd$k~bUWM8qRGXbRXjw%^2V`h}ehHqm3}&Yjr8P<)Kl7*2rJ^1}}Ivx~&t_ zU9A~##~pXIY}t-Z^8yN)iFch=fjw177OwQ4DX(Cm`b9BzO7;~#a$OFf#}PzMD} z)@Yp#95}-FA3JmyY!V)6o|7}9Nt3(0^!D+`pK?Qm{@inVe$EMh{O{F^A8)wM3x1nU z?YnW>%$_k9GaENdkFeiyYU7Sm8h6fz{f3=qMEviRU#U_WhM&{^2Uz@9RJ7S!w`!{i zz!bl;TQ5E(rnNAoAY9}Hy6lRJFS?{{`;2Le4y}6lV}^a08sf)B1O@(YdFo64pU4sP z@!y|3_;v9Au>S`SpUQ5(>WY%Q_m)db{HaxoHhO+_SWpCOSFIbLHGvE3oc^B({%yNZ zPnthYQl?CW!9L}+dJFjL{N>?~jsM{M=LOpQX+Y~i(8r*F?mY@Ty^KwhHOghaR8L_rH7Jzqld*|MlxP$U7;i?IsIkjl^VPNmvS9?hwN* z{wpbRO8zQT@!bL2iS>-Ujwub&zh1_;Gopo{)+QR}vYGbcUa!@gl^ zhyec|QvqfNeffiLbp!|gYYrs+KRdG~@9H}+7xS6!{7aULF1)x+t9Epmm%r-OY22mL zon1TMc~1XNfIrKhhSGwlS-XkJA4X4}$L#0%Pj&t?`-A;|Hvd03{9#Of*pG!{hj8!X ze^{SU1^=QE3>H!gKmaAcA=C(U2kmXKRufSII#eZ&qwzm~I=@8uKScKbg;o0Fzy4qTpKAvmx-KK)f9cUh z{4Y2Dw0_<$lM)SbBM**nS|YquMpe&@7q{pNS-zqI}E zRh>t#>o|O4rxBYvkJ#LP$mU+7wq#A;GA@71z^u*Phi|@Z$mY(LVVk>HhHf4_X><1U z%~^SybMiN5P1>9@ZF6oikUMpA&aBM?b2s;&xOwoD&G%$&zGuwl{u4G2oVe+pF`Moh zv3}T?HDkx#pE-2qkZzee-8h9b0gAe3lKu7SCM<(<5aDS_{>!OY0_1~Q7au3NgVbWi zt#HV301r?Vpv`$#*o4qZSnnJKpyv=|2>cI5xI^T%$n0=shQ~%G+6cU|+jd!b+ikZw zgN6XYuq_QA(spoN2>gpwz%|#@WdEN9|043A zX$V9=X@T2spD3_)?H)}4PNA@T^UX1ewRP)TVIS?Kq?#rBQsr@N+eP#In3Zt%oV#Rua|K@*K|KNrv z9(zLnFaJOO>#Pe;RI_HyCXJehHiZsZj-U}kM)D~kZQKzYO$}6|Q_o@RGAHh&0=yBB zI!)-=TELdDPyy_J4S|BCuV+r$*>~VXZ)~~$=nb_$MROK;6JcWR&{N6nk-l#QYa#fhd!|Iqx^+ep#Zzg+=@i{-4Xb@44dML)VWyTz2%)t4AKMJn>}t z358|7&owa`-fyUnxt-bhCix8On$r_ir$iGzRG*fpHZ^hqHONV{j|Tr2rj0w%JnP$v z8AmD)K3KiWb{0EtkE^Q`H~%TELAmtCwYxQMJtVzrZhG&zUB^7oXZq%T`8)5;-_vvM zvv)0g@s5I5dd%K`=d1(WrXLu*;J}2n2ku>Ppxd+qcT7KUXa0d6mVyI43l8*{abWz~ z1JfTmFm>&L8JiB|tvXP!;lPXy2d1t*Fk}6JybTA2J#b+70|zo6JTUbB1A`XqAG-9_ zj0avByy(R~1$zfi-!*p9x-mm%Y6VQ4GL=^@a?B+K(gW^bpWq$|{0~;EwX9T;Wow9I z4ft4%y_7p(`U&i`c~JV4f*j<~dtK^46 z>eg=X#|tmb7%?*ZjL#VqL1+l*WNy`>b8z^?OvVL zJER+3%&^gXxV`J?f)?P3c%Sa zplB3m@)fYq|2tstq_p}?h7BH>?6%GvJ#w5cQFiUpbI^bxUQAoDd?l-%S3itF<^K=l z*D&!`TJZTt14OGtZh!nweg$9_^3PuWP%8h!Y@a{o|M~EvBdJI)X6<8s+#(2pVj96P zq2SwLL8)|VB2k5dfCHp}zlskR>XfRjt_Ao9)CcFkI!J;#h_?fNsH(7_5E213HyHe( z31D4}|H`U3XrS(2dfsoY|K%kme_!$PQt2hDMgD*OpR0QAxvcl0QbP}y&NzD2h~qcp zob;_m{-5eoqv?GrPfiHh`plXVpi&R(v#c?UBI`9_jbck-lq=^j>r1WqIrLkXp%2-M^%l5+X4DeD;D^&#ddK- z7LeVcX&^Ucx@^U86<@x~Zu(v3GXJ2JZwI=qahvt%oJxgUW+H+~XzK+(j9pG8>?jcg zoJ3@L0dwT9Gw?hBDMK1~+1|8?8(Xnrg+N-~X$-q%wvM0TvR zRj*d--h28A7ip2?zi)4klX#celMY!DniMylSPB!3eA*{1qwee3u;?l76#0PwGH zT|H{z+H0cm|7SUWg8gq@p;W2r#+{wv|G$C%y@Pix-u%J5^?zHq;c(uPSH|WnQ1R43 zbxK=I(s9tiKHwYV7T&O+UYY&U+4N1GlwVFZ$q`-f;i&}%4H{9QLX%pxZm&^eg73(u zH5<{idA}-EvudYhbm=-|Kko)&o4&) z@Uzdzb?tgBs@Hy6D*v(6mv)ydydVFK6vBVwf6^K@q0R_&AWYN7&C%Y6SM&wUDwuos zoxKbPYL(v3o3`9F7hiO-7XbqQ4dWc0yTdv(1h(%z8oe5j{9Zt+*&p~H8UKgAp1u67 zJ_9DVYunM6X!bp`&rqM&4!#x*uYLVZlYbhs+Nbw`3FC7q9cl>VBlsuBe+t_*XV!d; z5nd@b!|ks#BFX>A=VSh7@Q*(M!0p5NW5NG0_(%V*pJDJn|NlovKF0r4-%hHZAMIoB zP_Y1Y;6MY1)E5NMW`_l9CTvlnM@x=4US{k`(>Po^F5-Xff~W~lZ)T$Ij7S%x&5oE~e^#Q&yhQyuiCP7TCQG8p zf2vMSjF@)n-bsbErk$vl|83*EBezaH*nH6TojZ5wfxY{#yBWPTuV_;3`gYap-czsr z_%;LQbql48mFi zC{-8+Q<=spwu^*lnggMAfdBFrgoEDKl%NZcUoOjTL=C2q54uXB85b z0PU|x&?&?gWx!Ex07G0wv}C#Hr!_%?C}~c@vn1=8YB28J+_OxFARWY_1+F>?yHp!c z&#${;|MOAE6zvgP+>eX8f1;GS4F%E`rPoE3SYnr_(}oSKP9=YUKdcG3PY?TJA{iyM zL=KU~_rbvnFDNlGW0Y`wX7@}5B;ntw%r(`$ORayCxqI7fBU`r2ZrO_E5B}NKUb#!U zeL8_Z4ezQ|t6P<7<7?F$)~|ogTglJO#7Hj&|5US|w6O=S=|1ah70_?=L!J8ESHC0IP}CO??0-1bXS#U7eR@~%AJvWjso#81``dabUF;Jj z#PfE&{SN*gJ|(M@ISYClk_z!*M_eE(*iF%|ALRgPt3{FL+x6;I@~_2eRr!bSXl4& ziu+d@-AYH;ZXlCp3$GFWSFf2CeE#A4FZizu*vnsm|HzO3u%8_Kv(L=`G5?Qz{7C?Q z+@+fu!2hDbKqTU5Z5Cbf1 z3Gl}R6`u;03!!zO2oW2J0;#^U2?PJF!_TnAQ6%R7mFNAs(l0M5_lJs?mP)^*djE@? zdi=)=ikP* zOA|NGOf+7UXuKe57c|LDbe(dl?WDrSGf%W!^lj^zM_Nuec>Czc{$~Z_KmSj&l1=MW zXkVjlpW5vwq}{uy!-S1}7Ctp(<*OsszLT}>$nfmRSy*SoX$=QIAGT){`ej z?>I4X+llNwC#Jl7B6r`3DKGwW>PyG7c6~GY;V;H)`rGISUhJ2(eqECP)NrJUlOj`~ z2|uwttkqvIw=)KsIP%xtSmb6 z29d*of&YUBMqfiSG|L?Z&0^G6T3Rb_?6zssS+A}{(!E%((MaF(^)YwLE$La@=Dm6i z(cv4zAOH0ZpPB7Hw)u+%DwHf))v(WY?V`~>=Uf8(mp=UA;!Pibe^@3>UmPl(3Z-&| zz8L(cWEoe~C}pa*RGJ%_YuXJ>Fd5|ijxd#z5bOe zw<=q%OWm}Qwd(Z0?z#>`hUEVJ@BauqF9v^RzZZ(nY4)e`U-;X<|Fhja3ySfd=V!p^ z4dC3S=K?Aq$^WST*LwlRi!NEX)Rdcn|3F&1*`P*UW_0e>Tk!}ki1Ze%jQltFhZeBL zVdQVpIK5tN57evcfEAqoMet8i0l^ovdfP`D0y+f@`}{!{B>h6B0A056y$KWVGum^| zfZ^Wr;{VASnhbK|UyWS<;fSTL44=HoFrobE`Qat9z$MwFoer3R?E+lTI&ti^ zOWs+t_QUqz2^Z7GaJYhkU2sxYenkR2$#JVhQ_fO*FGz{1q?Yr9qeq@xfk)OIIVsOTfurybm(9s#$?cj1c8 zDL#lfP+4_jt|bvXHSD{VM{ongAwgnS#u?-Gkcauwo54$&PmeH;I zfVBFpF+X+rY5PCfD5!ARW!D*d->TKfWEVhj6#)MC4BEM7_b0yUwc^nu3m*C_igxFUor3HcCTJ0xQ?1X0^Ww) zvSphANX2M>_D>$9SN6Zz_U?J9DuD9`qRq6^zW3s^j?q9MLqNT3g{b(yaNd&O|6%{* zzaHeY&a)eLp4O#XpWqLKl$I@8^8#rC;6Dgo?9HzVRnqFQzWa3_yf$m{WBB$@A9uWZ-pM-o zg$-w)ZZtR1bY8U7&W}2Od4by8m$-FF)C*u^*9Q}ARwf$Fi#E1enrOZB)U8Vk|GebH z?JK^$Yw3|c=N)X^XS>0c!T- zux-&YeEX^4+fI#mBwA|9;vl z-%Wn@AJbm=CVR(6!xq0fVEiTnO1&}=@jpet4SWzjK%T*dhxR977SW6zw~?6|)R0oSxpS2brNyx6}HB0(E!=ra22e!OL4+s zwgF;O2Xb7GFjJEwh~9x9qr8mp(QGH2x7-mN(Fz0XGr2`Jg4BilRQ$v@#zS$^(p2hf zaZ#6ZDi0oPemCQaltmD?9RQBufS)SP>29T!+a__q;UNt}60z_>KB$bqe=1<`pdk{i zVOrxs1BWzg*0yx%YIM=|?K?Ma+?qdc%gDSPcMp1?S?lcjO-7|P&1l>_qieVR;9v3j z`sR6#7m6Th{1-F$i~qdrvg^y1t$R)vPz?Xgd%rNfvss;~fJGZWn7a6dUiS`DiFkD+ ztOTcI8T{7L)0W1KeQLFlpVC}uXZCAu3fL+4L7tXb8VNK>kaSR1rvPQCYnSv)$A|UFMKxn z<1MD6-23b+sVac;#~2%k9+~q}P^j&1L5 z->Pl5&RwAlqdK(j#PJUI(TLFG2W99ETbiWzy>syDbMXI6Lx2{bdMqv-bOCiRb^c4y z#!1n}QQ8g@cZ|-OJ$d3({{QFpJ@@S1XJ2^kg%1yZxPSk_`4hU0kuGdRVfgFO@#?6g<2o$2sKWss>{LKAKF>L z$)i>#ZTv_JL<%7JK9OBP>{6+LJ?Z9;R%jpE2m(PJL^|M195r2mH2>!>eo^ATlKj7@ zdjHFs=U>rj-F1EUR2Y7!eCFY@nMX@!9=~?n$?GN*R?a(JvmkQyH=UnoJU3A#FKP%- z0WCO!@}pKjhvkXxn-b|ui`oTuu0PfG{=yE+PPCl+?cK|d^qzCDONI{=Zt*g&n^7Zb zUeUCE#SXRV_p94Jw^5(_ZW*<;ZQkB4^AGi0`F`e(FAARhcE)oj3if@!=(STz-#$I> z)zi!0O>8-qSoOEW^0yN!-cBsspU8eHG5-0)n5PmW9*LHWN26urqlsD1B_4P!vGUzS z-iwJbyA!$l5;;#N#_di_+LxHP_w@MPmQzz-`aXaEiHUoTN#&my47O@y~SxGA7AP%f-#4ZB1j4gt)7aoY*yBJ0&7+k-}M z#h?+Cjo@^06pbJb5#K#H&@SguqFlv+$`w-qRH=hdU|6B}?+|eeC^cpy*r?VT2;LV^ zmNXWS+?uC|QsA=S1wu3BN+I-&POB(lzRO7g52D-#P2`5%DiO^+cy_2SCfXN-*6;{H zb6E$usYdOdJ@2;N;Tly9>NV20Kygq3G5V|F79)l0Ejn!T+#t z!0lC6m2c5vH1emXXC}KXCg8uBe+>S){`wKss^8rp?au42>sq(rC@q?L4eq%5>UK9) z?pZf&_$}!wev#$>zc>3&pFR!y$B!R>{q;BXBWpc9`Sc5MM?k+(58*BThbBPe0_r@o zMT@TZ&;IAtnLlSy?Ek6NWKiQSGdi~Ej{oh_+w|ym2O~l8FcDCl+6_ZrutSo|XeM{Y z=mjHloqT6x@CWP{TjxZb0-<*}=z^e$#7{1djLO-box5miUOv3P{Nl^cKl{Az5$g!v zzyDzJrQ^Pv9@_lCvK6L-+q`KjpTCJ9S~P3rd-0~NGk8gp0r`U#cyQ&~NCk|VFd|X` zQ5Wz}@ZU>eA`H)t_;2zbFb`Bu#lALIF_Fk5Y!qPmd&T>`_ufOFY*Cg;?4HXF6t?^%VX85JzT{zMZcSWCi3`)T|z(42$ zMOPyf|IhzLiT_UW|96!m|9`2@>#pmwr_zW+)yE&Ml6&-;tmD^apDZ__uzc?6@{kjI;~p!V_{@oEFCNR?`BB!I z1EcddZ{Pk%;J+M+1-_sgb*%vqj+n~!#!Q36V7}VLoW}pKOQy@*pcL$K2HPEonTYLF z1kYtXqA~+Sz}V0PP%!L@bjHGk0lA8en2c~+#1wFp0z)8Fd=cDg=&QwTr2^_fiFwaP zHOfeVVFp-Bd~OQJ(lzO4V3!C)H-Q?>_8{)Wed4@33F^q|pnF8>` znrA79lSm3@OBK_|^tiL9Q`sodZmwB($dF+{eb5Dr|F8@hJd{Rg(W1)(53K*^KTo{$ z=9lZ9FuQ();$_=DWP~qR_txmKQ_YG~ty)^yGBrzG?Iqt}+ZTP?@yyTS2LIXH@n0`+ zt5zAY3n+&Fre}VDzf1e636MEHpSq0ge|CNt?P<;D&(8+_M&yFOaaNo^mtTH`n}q$A zEyqOIZpDt9()e0PP4{i2O&cT}m;rb^YZwdxM4Sn>9o zZ*I%%A2493H?3cL?RE1A#fJUafq;Dz2kqZ~aOB7_UIgaP(?)do^Dn&G;*Qx|J!tRa zm4W{OylwAZXk*NOE}e`KV-2LF4)|f}H0#&7eQ)FsOPl7c?&x~Q@L?H-01Y0Lkw0}N z()w1fMWA5XEaNsavlfrc*$(4D3!DLaz+xY)SjU2CMnFIgM zZap*swr<&WZ?AsWlrCHLnsP?|3?GuAQJ@!~ZJSPJ2lAyD@Ha2e6T6?>wq^TcJ9l$l zMf^`$mMvKxses7;6MgnEy!;#Ne=Z=?K8KfoL+7t10REf&lO>;u`XuJhy^`SZ4wgUu zzx(dH>ZXdx5+k$#!iTVpG=eIuf~Zi)z|ylcyeSO6IhI10PEJ*a) zk{Gf((SEsh!Kpr*3kPpK(P#a)ZDt)w&pz07WO)B;tovdAw<^`NZS@ZA()+c$W8y9S z?rSmn;dXg@Z=e7A9ru0Ed(9X9AO8EO$4|_9wQ%A7Q*&QTEIgQ4@z=zChZ4))N^Cop z*zkE`)q9CGe@#5_W@5_T#DwP)%}AmLa~TL}WuJ-9&T*z)~5(w07p8P{avalo0r} zk+_ONMFk+gJ9KjK9jioPviORM@}sCoY9&EYQD7MJA}BM$3WiFYM9%nVyev_!b#2t zUGQ&JKv6Gn`}Pww0e%erG5^O;oNWLMSHG9IHJW&S82_|D=z^gI_}r)fF9K*0)T-6A zWy?(DPsKj?*KZsxG5^b#&!|}OwwrG1Qmwl2|M%3Y)unQk%({(6>*KDIHne8VTYL5D zw|)B#_Waqv4_nTOeOe(#8+ zv30uu|F$jKXa(GTXYYdPvjg^HOFP)xk?sA!8Z$*lqk|$Xz?k2fx{RH;ZQSJTsY}-6 zN5>}QO~;&(EbXXUb0PL-WCp?;l)3+JmO_x<65i}Wv3H(WqwH`3{#tJk~} z9R4i-82(hi?wz~c)ym~-Rz2{bW%Y`+E0(R!9GyKRYg)|zc}e+a1iB$fYRms+pBi-Z3>!@>R!{+~ZqkLG{= zW7~BllJ9?&9DKOUsG~I}AFoqzGHrfg!-c1BDu^K8Y(eDYPn(x$FgMX`aiaB##O<3C zJ+~*C-ydyHUl^%?+czX`S#+w+;=;b0jL-SD(}E+da}T!YAMqcu+=B*k>rzc`t=6G^ z%YL1EP3%7UzAiZt|2xlny~q6@^j`f%--rG_X#0tgPZSosd}`_Ik+)~jfy8RSe=BkS z>xpgOB({AW@&CcUC04zanE6~{{IiLf2NMra5Sj@|{%Zwj0<3yH@!(sDlD{-3`2si*cBaDxB16bp8-zyrI4ZHKHt_0V6L zx`sz&7C9UO$ZT@CeHc)^7h_Q zRb5--_CI%wZ+!Ru-doc(n%EUAs0dck_iiiaPMJWncklsNo*boH-qzTeR?5Kbk zyCPT;MU2rXQDQV|EO5SOpDEiDG`YF=_l|G6$8znp*Is+=!#U5KYp$j$1)2l!S=tx0 zE4f$n0^caUX8X>1#B@c~IQm7SA%9z9Id#eA4f#oBI6??nZm z3tAMx?`Z)R!w?tH@4#Q>f8^?|C{2D-{F-LZo=xisM-V<$BH~G-VTF-{FNk4FlO_c- zJXJOL1^W_?HuD=k%1i72nLNNKWX!k)@ZZQdXymB5`aNgk1(G(x$Z^XC46qzJ)auTi zd+);k_pwiBu^eat8UiOzpP%ZY%mq+7f1?li)Bh{}7F_X>2W=K^H#fHz{}1**^v1dt z{*M~^hW|E}Rt~eAU^|2d&H{WwV5=UwS^yp4vx4<|L)C**7LLft!bPKy`PWA_*jLD} zZAVZJeYi|9i;Re=zgf>*HYNhI{zFRA4u%E|HyOk5P8J0+H?`D-e@W4v!v_vy|EF%> z9U5~mH0D5X^uD0zz3VsSZBN`WZQ7irA#2$J7@HsCUsihq^?8SmtM}S(*W&UqRuiKqhH1>;pI%3m{k#UOuM;Y)Rr%dk}7^_V69kEd} zI!Ls7sT*_u^w=H8$#r zX*8wF_{jrottTk_cM4AS*tEwzvC3(i!v94%4;B~w>{;~7@&m6|9>rJRoO(@@d`Xjd zK{5Mx)@jnNX!bN}4nEW5-qz&Y)MQ`R#Gln<*J(VM;5JsuN7sn z{(>g#D8_&DsuNA&M_)%({1SQeaX`VHb!7LGNCG88omZYGtq|Q_T zT$6zkq~=0(UY7Li?ChPt7SsXN7UruVABd6RUJO(!tJ1t+ed^Rm@%guM`>0J1@&81xP2k7KH(7pD(iXtlrxyUH5I-(De{udB z7z~{_@h$vy$*+z3jyCljHe!kJ-`F^G^jN2^U2XgKx9Zc!ymuduQKri1)}g~ajE${& z_cj|afaZqBg9nX&#M)P}uSV!NW>KKx;yowNT(WfByu`oIKcdtpw8%GXx8iaMD<*E` zxXH{+0Y3i!clnRaFYw>6ZZlH@1oA5L-;JnRK#;B*W`TDd&&=Dnw$oO(WH1i@lM+*z z*H(AqCjGo=DH&`-$Y)QKhq-f~>4(ZA{6=_-DXBhZy{MhbmS6vrI%>dI3s-%^%tPm!4c5*eg*g z^IL*z4t;S`E7z`F<3}eyMr?cVF3ulJHGUENkmV}BO{_02kwNT#ngAlG0E{&3eDU+^ zssJ(m`4Wmid$a@DIOS_eNF4s72t*)1LONQ2uPA*|AN@&L|MUNRVDLfLiS33i?l>{F zoo(*tV*h*H?&Q;`7y8s>!;1l{mGS=!`yasEuGN}Rn-%g~?a)j})=W*)%*a%LzobEXCA1o<+;#Km?(!H;jA8hhF)*N+8lYCY2_9R`@WL?+n z`c_c^MfWvjFEoXBHMzGmdG(r1Ono{C9%ypw6w6=n{{#QaZ;qU+n%tY3t(P_7<;_vY zo7S9u9ai>B*ulr)`|kLrR(k|0{0G5`<0j^reeI$dLnTT}qvf5i%Xt=_Et-&AQA2{A@g16T)({bj) z{}2E5S)bnH3JVWZRo~0iy8Q*h%GT=T--kuU4jVQRwsRO6O&L9UzNsl&p0z$$%$c$M zzt#fpR{`*U;K1q215eQ5`&;lA`#T;S|uV>JWkc}Q@S!(5jE z{RVaGsz1<($yCbt&v*Gh!)m(g0uOxq0{?e`|K1dV`McqJGru>Hdzp+D9vaQ!)d7B? z+7%%JrdiwDSWVl%_rShA`+@(S;!+$wIa#~5Z!1`}v2ttX^(~nE}`b~6+n(NNBFNYAISff zFd~aCV>~}}{$9O$l^+^EE(|asKb93gG){@|>);27l|>#j0*L~DX(nKs0e^HhoENa` z!k<HbX8kwp|ADKOMLq|t(G1(9*#C?OW&9^yz=Sh1G;^~x3kx($ z_GA!Ve;j8v;GSIXU>nB>zll2 zZOO{as^z)03$ku4#Q&4~#Cs3+|EuNun|uy5`yFWxu4<02Y0kLToP4o4?Mid*?dFWD z&AGRlkGyQ&^PoBJR&(yn=FBV2S=X9Ne`qfJwmE~$HO-l|%8_+hIdZNx=hZc*-q70r z$6m#J^*rpbV*mT6T@?EtzOmMu%6}F9!Y(L>2w*W>5wVIT1b_&rgz6%gzC;KS@&Gzj z03(@6mzlWLMHZ4Hilu8#;nQg#0{19KC=RV2)KwL*P9s;PcOWnOQDNEV#b= zE8S=5IGwb;52%Lh!woB=56qakfFBVKfBI19I>+-vM*t2V%zno9_wP4k%9OAvR^j6I z`L*Tm3;8*i-Zj7o$gdnTmabkaqk%zVO&1y(PU)dPd&uy`efrqZ5a`*{R8MgPG1I}9 zki&Y~;_U1^dPXqj{|NSV6#@B|E%SZw@X?SV6PP5mI(ltMamm5`2QzkLZi`D`UofWq zGHsTvQrIB!9sZB1^Fe-c%i%~GqjQX-?m>%hKp?7XQQ63?!WOaBHHfXiz|$ZiL>$jv+QQVRC(I#7YP2ZO)G|8s)5 zz%n&>OJ-rjhNP?4zD5Nw_y@2H^HnWCq*c3sQ}WPdjOPaxaQX6O7!KHJVq^cK2>1>1 z%R(3Miz9-4MFdlg3}i#pE&$AaAP@XS062m=AYGJ#7VSy^@G<_?Y@A}}6Ur^XABBQj zn5RgAWag{OXf*skjQ{!jhX()btoVPrSjBdoo!efA|BU|`xb}t7y4O9h|0CGdS2H3? z(>F%bKSncbm1Zmr0TzGQszf-28qB5#T_2i8tjw(@=5pTiUaf_-5Smy`+w`<#x z$;6|yV}6LEg2s+9W7rQ`;G+*dga4yOIaXKKSJypy%m2zBiYxCYrDWUKEF3aq#+Wfc z*slfkOx=>Dn_GoSx@ZBsLoE2C^#%P(1+WlAx9$^XyTq?gtKNC2;rH$ToHF=-$kt97 zJ%yc*&j)W0_CI588FR(T5BhpNJAY}!dPGyEDE!xfzmQ+)_8m6D%gA{CC{rK$e@Bj< z4gXC{9Q*XaYcx*3*PM}~9rg9iy7#a*wG6g*j-Rz4VaB}8hDJ`qMtV=S=7;Vjbr^pB1eaIJuH8qkZ<4>@6ui8WCH$Mc^;w*A27l zQcL964hT)p4!4|^)r)@3@0{b6*AsxOz z9$ZT(Y=`{nC8!R@5h57&gwi8GPSFUG&Ls+=DZx_!0$KodLphB7Xxp~!|AYVM&u#zl zp~1hj{O@WN+kJL!$N7r=-_i4S$K{QkRx0B^d#!riEuwi$v?g_vW&&%wg=r>7Yi34i zSo3-Ec8zVOW?H&t8XdtoN;oN1W1WUysA+oI>zQf4xa2%pntwMS`%=&*?fRcV!8De! zk>LMu1KSa!-A7N4n6x;_X?3yVrb_#`OHL^_JqqqG+xKYsfuEP|`NeDZixmf6`5Z(G zyz)Kx${)M^)TR> zd=+;@u$h5mEAj(g1kee|!5snv38AH!#6opK=uHWvlR@$ja>}J#t!M$iizouQ-*o}JN(B5L<1o*uEKVv3sb#he)vwt6<5rFwy8@q2{{fD}M=#?TZRTS#!mdjfc8akuHnySLT2J53 zWQ0S{-m@9=Z$3H9WocG$>|u_;wFhU--)b~){v<1Y@5)y4y1!apS`4bRWNW%d6} z1}uE_cyBoj>}T^YJXG-C$-xEBKlVQ=;K-pP$w|fG>rcEj`*q>3Z3V<<-UyC4tmXfK zm0^1w-B-n><>UNksHbZGtNbUz0MXEO3BrFmbKeVm;lGRyB9v47MRQ>M5O0eurCTid^;HY z&>r$*{F8^cq;R9O_fY}(erX6W*QH&%cI^N1Kg|FANa_D=Gk7ul@9B`+$D^XFXKfGP z+dTpsy9Pb&68xf91IRC-2y^mHN{(1S{XG?cKUsm$mXaDmR`=0ykd+vMqd05r+ zt<}#nYM&>cQ^MT(=NXru=iPdK^x5;0d(ZQ3KHqiyd1lS??5ofBa9Z~~{o?Zs?U7mi zoFn7Hv&`zBv#K8@oc$rF@aEEOr@h1TPMlEq4_&dDe+&Nn;rI(eSCA`qG7+#QA-98H z0Y30lg#v~7DnH?&@Si-`-XdfpU1&)t!n1VqfMVz^P$dKTiQ{{rVuE7OihzA8BR&}( z%_(0qU{1S0+6zSWC0KP?|34kU2M!-!v?xp* zK7VA<=9bpMZ>a#*e_%W2*_M++`Wre~&xlUU|5|4Is(rq#A}jP%M#{V1g4;{XwZ{In6`_ArbFsom`x&8Y)&@s`WL*GuF z2Ec!MG3d+C(;Lg;KcuO93jz`>L;JU{E#$CZ}uZ)|MT>(P^)Q<&bBu_KFv!Iu7hp$>Bwuy_uw z02c6+CHGlK0bdZXMJYsvMKcuVy-ZdULAM(JBM}w#62X|Kw^uzlm2};rr~`WwFyk2g zWj%QYH3$CeQ?O%uVZ{35@fiQDu>Y%5#RViPfGH1nft)>8(a+0luXp+XW?sOql8cvW zu;dZE`ltXE^%BvY8X$4fQ5ILOT%id7|A9FsHv;6LhZsxf0{AcF$0o-(SNjM^M+?Aw zMGY)t&vS+UkX+P(*#A&n%zGeDIx0ZrKXGXSkbyW?5%^E}z+e0TXdgx_u;e4-|NpAx z|35oT{K8~$H>=oQj=6ds6?)#a#=*CZBN~mPpZ1A*p%?MGS41$OeNFEf%K+a=tcwx-(7_YMD9 zng;uSOlPyv{ilu`vuO165YvV6b0c?oB^+Lsc6v$r6_@n-McLnbyLMR{WzoMaoWYlg*P7;-FlpM;qi`h+T-lw9cLb;p8hfQ^n>K8y9wpr1g2Fj^2>(* zuuixKyWk;zEFvP{P8BRzfG+|+5rBq3T9_%8d<)c-wc}_Ms0bAdf>6*(9*P3{ga~j3 zj{s8@PT@b7$fF9CEGl9jw6}s$Ee|CWp)x9UiNImrg8K8_gV;Qm6gZDa#drnzT1p;5 zUY~d28QiW4)kb(a3WEGCPiy_ZsucK$D1lql66E#eblg~_pZC4T7wtNIsWbuF_31s9 z7SI0UH}YF%;9{AdI(ym8EvjY3W^DWS+WhZLe5(TJI1on=@MoW1YwJiGo2a2fTunxK z`ma8Mhv#>i0BDD}oz*`6(K4A1pO3Nepie((2mE;*_}})^-UA1+s;4-A#MKY^XXEW3 zXU3YPA=)Dt*U*TOGjTn2>SQ=zz(nkS#;kVu(rVyfH>bs^kz1zXs5R!r&jer&$Hs z!pv&T>h;+F*_k;RX$R==-IjgpclodM1t=~0A&xJIbZE~h>Od@i?vh4?IH34x^ElKEy}&FK z3IG58m$n~%Z1739i5*QAcejb{JU90Xr;5(*wFdsT4MH0Ggg)&N{GwaP>tT`2J~5i5 z(VD^y&5h~L1K99om4+DsW40)s|M6Qi7F(5-f1Gw{+zK@d^O~J^HO9cyT7coVa47C@1lmqISpR<4al?6}a7QPYre zuA$&oL+Sm7oNEnPwMydllMNY{8uIHJ(#|&|ooLv8q9Lj3e&X@(6Dz;lT6S}D$))v~ zM|~sHzxwJc;Xl?gu;tIxiv02y1a2T5vT4EphWy-!z*11mRV~in1~6PqU*R4+go>2F zQ&0^e#8Ew@Lsyof5Fsb`szM&(6ta8wZZb$tLO?A#f)KV-pge*QAp^9h@?cseGnPEh zLMV+qXfC;`qMV%QBgsQZ9yQLRQC{TaS*?V3SA|QwwcMrDLo4zLNQjbpw+SHX0Fcg` z=VWX&gj1IV?z_t_?LMI_!T^)8{};N&P5hs1K9s82Ut?F7sy||`UdZS9f9p4@6HiumBO4Rt4UL}{l9w-A1YhwwSw)m06yEe z4;?ZxHF?L)x|?{sPgI?lZZm@kR;;cd+X1w~IB*toUFglWEHIqJR?t@Og8XtzE7}Y5 zS>Xr%s|PATv_PxUXadj+%$%=I9lJ3j7?)IXLSfX#-}e0cstM4d0&oOH?)M2TarB5< z9=e_`VCny5I4BXB7sf)+@SiS#OIrTlxN$?5_6+h=<)@#N72(v7#sZ#yRKUfH7eOv0 z;Ri^FBB0%k&=`lqI9IZ5NNQ!^t? zW4%LTo!X55-?QYE|3MaBe!Md8j#onUqJTYn_LQ;-JE{j~>C`UcCL2yMAM0d3bLA}G zwQlQ@-8SVf*?Q0?y(%RCd`Lm9Z{9Wctm`i6b*>pVJ$BvnE~@t`sQ1XMch9U}l2h-g zJ-qYlefQL_IaU%h_3@SUspsmqRn_k}S6^6PpLJO|O+Hn>t)f1msy?f>KJ9G% zmLoUg4%cldyRrG;*BeS}*5;myO4t_?k_7+3AOMH|g!1>|ZztF%RN)Ewu$%!t1k-~5 zO?NF&g|u)_Xbi4Ja0)@f76d9Fg~{+AP;&{S6B6gSpcS@@l$4Zk3zra3j1WObaFx%I zs|az5;u5!un&8n?Udka9p=7YEvYJ{^GMA(#L;$jSRgF+Ag}*66t8O?&crLn6UX#bY zD_r7n)JO6Ys=9;cipG(M>2Egy+O<{s1wQ!Kr=NY=9@d@xy0P?3W7)+Y@x9D-+^F59 z{Xeq&b(;gy3RuBt&%TBZqs)B4J~UQ^#N+r0p&A+9c78ZvgQ*$4mn zM0{2Pe?o=-pY=8z;B0E{k5372|KPzc82m#1$vo)o;t#%K&HV=twQAF*n}NZ&9zBMC z{`u&>{T!#*t&ZAyVncduOu`9VPpBK-`r!G-#KOAZ=pC%pl$n{!Ad^-||Bp_8`Q-(R zhf8wB+kV^m=GUJ?)K4O@U|3?I9LvOGz z0{PJkz#O(CM8G}~LbAbg;^agr5OP%_+=VK^#U!l^R16QrxTPo-r)B-mfBvQIzdlyR z|1HQ7bMXM94-3bcI@R36iUoC(aYeLkW`e zO|`VeQhD9Xx_1%h5}y*PkQ+sPysHT0)8GRfGg_JL^*hH0|NInpP~`fYLl=KMQuAZU zR}bNTi}Od9>i2b!_S^0krmr8>GziGqjNztg{m*koH~t~kXz6ctmjFc+1sm?FsT`kq6e;4;zD>)0mPNgfMstM1%mJZoJ-OK5Za>%pgk!x7DQ8!LPR|OJd1V*S_XB)&yxrf zRT%$?|L5=Q|K4Td=Ytjhe;=pZex4PED{FiD-0l;k@V{H&iypzRdj~a-3ey;cX$FL7 z^nx{ALNxl}%3Lt^{~EqQnF}y>Bg?)uPuku*J-vBB!E5K-*YopUEXsenDCft8X}1@} zop%i=V*ao2pGRAE7-`mff~m<&b1OG1C;#c*t7Zpoab2IbB4yXg9lMt$?pv|_a6tO8 zfb??jq;i)nm2);!&Rt*WyrptsV&#Hum5v)L9XC`uZ`K}hl`dN=7pGK)TRgfD6pROgOK?ADbWHb3=$gY!&<5h2@XHe}JZ?>>F!bY;r&f?qHz65Gq1ua#9E= zR>;16J8|K*u$_>}(!zgK0P02*0eSZA+Xvp2snq-S?ccv2%_1d81`4Dml1H*p6qn># zgj9)FBT*HyQ8BqB6(-~@c&M63H^QTZ|DsLgebrEO0V;qOL}gI&d$oXQ1U?qBnG7AJ z%g=Y?|NO_tZQFE+jLq5ol`=ES!D$ox*ADgk516m(BbqWLWVTaIMEo%a*94PM%NU;{ zD!|4ja=3|y(LfhA6tJ|8^o>50b?{y*6@WFKefYjl=sqJuvw!{blXq(i|2uaa%<#_M zy=M*_bEJO@bTj(3^l|fjpyf&V_(hr?Ai0|Ol2?+D|{9e6f=aL2%En| zg-5f%g53-U#(y%$3evK)PIyQ}EB<4~!+C+TFq|d{9Su!QO&2dzvou6rPQG~W#oVL}hx2NcT1B{oKv!A^C<0XlNEa|2)1Q9Q#%!#4N+P55Py8FV|9fMyJMfsfaBPE?lSbr7!|09F8-6wV#zF6Nz8UN4vZ+f1!dMgzFk6!T8USThKguLz@ z(%dsxV;rg(#u2VD4%hS!Q#OKOBY?h<%?6RpCgIJ4S2d4X+hmpWdRoe>8L2O(CqJ9A z?Xh*-gDLB7P6;_Z**za_g@uOE^{l6-Xa1#$ss6ZeL#K|ja5S6lHPJC(+T!Thew*e; zBzSGy;hU7TB7T?mh63-6h0EiLmToF`SyMbKvUp}hv3*4G+?ZmA)y17D~d`lj7ZJ% ziQVZPmFlr_gNvj8>C>knr@$ZnW66U=_|J!i2>J1Bi0}adE|vTOe^5*ccc}u65%?_p z7o%6=+zy9%oCvTbMTku(Y={4(lT8GSQ~tq&2f;oKu!^mOFCB(vVm?< z4OD{&^${h)RY;By;TCO8-v+1vJ_KrlNH&SfDg5UXP?bfi2)ck22+yN|zqBBDgb3P_ z4@%`fpT>ycW8S4`s}!J$3UGE`oldC3t|AS2y)0Hr8yx){5 z3j9UI$c8ne#`y^OB^*88-(;j`&z{r!^`DF9-_bo~?eB*tKV#`bL56i;8k)2C0tFX{lH7oZhO-+M|AW>H=-*k|(; z7|Y_BV@H{V1cWVI;O^|`Due&&BVZp!5>@{XCjH($`!M5G>m5o{{=M(-ojZH3`eHSZ zXSq(?JE9;6$w`ZVkj8=v|Mynu-9$wPNL%2{S#bn03xFX&1C55lf73B$*_j99voQYu z6Z>D(fp~$U4lWNaUf>mzd!Rzs{>KG`{Vy&c76Ltg{(_kF4Gj&t%x4RjRze2Ye^D!E z&YS_@_;X-BoxeDLKrsUUAwQ-#{l8-W3;f9mnZdq@v>ix+=cI^7NaB(~Q4(It7*P@> zLMWF=kw?RP9z=@+`=7^gm8WyHd-v|}AN&71=6@%_xWZ*0O&Om^EvFQUJnKl3Ho6lu_BgNJnm^T$yOMB5|6Ra@Z|PoUv3n>{lc@1|)h%BrcCg^bSq*iB9xeo#+#l7`ibrdP`!^ zy2OCBi7TTLmW6Ix85!@tYLln$T9<{vGp*g>KL$KBhI_bT5F%pj>%t$)7J+^+ko>B^ zH1TP}Sop7!RH)m+<~RS72a>~8a0(<W>DbE&~5nAsPh2lSkEbL`acS_)ksb z)p$EZd`Hp{7&m5oNN|{LqhRD8;J)=SaxA zI&1zGlTk~B&lZ+}7M4L6|3YTQ>T}7%H=p4^nEf!BTY_WuO_&g9V-r1Sp!s|GkN>}2 zo4&pK%wn4brT{3GzbQLZvXT!=`ulT?8Sk%@uhjxPYvi~UxQS>i^fz<_v^alKO1@Rr zxTt)v^U(KObL--F-AF8`&pL2>o?G%*i$JD>1+FX0Dm+Omf58Iw1XRX?@>^HOc{0ME zUK+;#s2bt78VFeIUmgEy-I@*9{}<0+VA(XbR%Bcd2lKz+KZE}nX#;5){GXh-1ACtK z0{qAL2j;ixZ|UM1%OAZ1tFi5Y|DEsd5a$u(A&wT{_)p=lTRt{6C9uc?ql{>k3>s*H z|Ho{M`OeJ4+p@p?Bm8F-2=$P8!E8X*(gau)&uBGm696rM@h|)*g;@YB1b6QIdH9b% zpXGqyzc3$D|6O4hFxXE{1gZdG@Qb$}{0jfUuQUNr0SNpD{`h>LJ*XFGgLHvE8bR5Y#*{q}g#*b6MQ$_;t-ALYumUG<6GlZ5;Z_ zEcBIs^oy0Ne;Ks)xlQU*+Z{h!Z~w_L^WpNs``){5d8gMptUfkjQ3fs$KVLuikLv07 zp<$o4gZgwCWz=_q$*`&8#?7*@becTHb;?vvTe}r=9Q>S|0~fi5czK6aRUm>oWCUbwAOxXqmKDfZzuv%{y(4WCNr5N_ub?&2Em=@IVX8ot;q ze7RS+mq+-DrQxA|;Q>D3E4;#%E(!Hm6yi4D-*eH5h4${|!)FQq1^%E9f$)$J(%hy`o1*M97A_3GIVJgKkZ<0CzEOMdp9~^CM;a=a<8j z^?&gHbXi!g=T$q#@3w)jV*eWizZe(#+BvFedRX)D&?f89CeKLXuMLA==?A^)9`K@D zz%QKwo{tH8Iw|C5i}jDKlON5^eCU?fusH9oSN<)poNJyt&d!WDV7V}b2|&IpeVKa3 z))NaJ(+f)lT>+wolIWEx_K@d-|fqHVYR`n(sV*-i#4;6AUeBsliggtjd3I3h;&hE$olS zz6E+>|8t8L{BMRw!Z&UaHVXMwt^#3|!$i;>KvjsUVpb(TWCqbvA1VWH5vi4&s`Vsi zSy>q&ycIK>8xayEL?!V!DS^9C0odML1^Xhz@y4iiBLi_NkA@K25fEOP#+AKUQLR0`>2|PmTwqNhXzHTDxLVWyDyV0YaWubmuul~P{ zTU!S%SiFy&d?7z{CERti!F^@kkl~)fe+B|^;H44!Uqbxtj_yfOTPqiN?U14S%Bnt- z!`UiVm;axB(*E<$J8`sW(}7`2-8v7&_@7`Igh}tbWJko7<7`-_?j29xu6J*l8kK+6LE61~#!zrTUekRdiC!ZL6p*OLU$>Oe)mG$4cx|H`_QtKW3?P$M;ef)kl2>c~_^{Zzo&o)Iht&e@} z9r-G2&C6ZuUkncXWkTq4=ZL2x1Agum_*gIakzvTgvFm=YPPk_ke`n&xTa!24uv&j* z@|yFLA}Z_x3hmvuswO6WDrcJUC~r6#rkBd0GLK5fYm>v@KgEqa)nb{xU{FVG~I zh2aQ<$GZZ+RsLhxgHViHasp>WY}-Inp9>svA;>uI}J2o+a7UY`g_kqGGCW${UeE>Z7gN zn*fq?Rn==mL7LrfI@bKqK6N9MGs0M=(-I(OkVSMRimmcf%J zhXQ{F3ym=k?BCxMS3gz#|>roI9VrGlyM< zO@@rJvG#!fZwCKl*R#kc8`&sx0a`kIvGaxeV88VE+oMGb+#-Y81fUmyRe;W3zp_0YqR1n zPmR4`9)8j??3iUh=`7#$xeHdqna~iXnLDul+wi}18}OH|hJWp0_>Z0gJ}@x;*l_S? z1BbR9X3}n?d55vnyO=t3AMe=Rd|r18rydrwyHBv{YB{yL1nxG-*Q=R%cZ?7y?R*$^tD*o zXZ*~r~(;a~pu`@;|Tq2jA%Z z0|zd!m=MU|8oWdEz0xA$j^p`Pv#Am8%{_82BCcXf%AvtSruOYSpL4jxJ~i!9~Th(-x|M-6%|-)lV$cnJzcIOe)j3-P7VuM zDF_$P@9-bsk>|$It|qs-lNNW z$dAuQgg9eFar-cy9I2|Rg0~1(HZ=M)0uNhCr#q1wwp96>>#bX5BvtucQ5_`m$=Z`l9z|9;#R``@FR)w&LL zyLvevo3`Xq?WSwVG52i)ewrBc)H3+_l#u5RVb4!*`03}vw;%8RwrKUEovZIzuKZ!_ z%KM}I?(|yut#Q!Jp}}8|4!dF*U2PR})@s!W>s80*tUllvRp=0q?%=t3&g?+&2><8K znak7zngD141_B{02hponFD3=Bjuv~7BV=GTElycbmu1yC9W`ncAwoJUE^^A!i?aHP z?6^U5hGke-hH>)b$y26Gv9YmXd%o$@r_G%U?!Tf zP?DQFe;Bw29##HBS_S>ug*ss!6h*Y`SKtqL5wZEfDM&7hX`V zN)4r%pj#i&7kmg{U*1l_7CrE0cN>7O@?VYUwgq?=%lj~A78PJR&ce;r9UE!H@HZ>M zsi=Q%q=o;c!-jeON4)^>e_24~zH>jSTowP1n@{f0;fnwNokQud9WZdguwia8T~{oB z;LiY|DKl12v0FD{lx>HO`eOF$@}KyZ9rX+bSUE3AQ%w3_+w(j(eeW$#zg_rzF#8qn zP~7q4;#>L0-nJ2_By9w#Dg%KM3T_6iJLu@XeM4Gp&hC>&Mi!=~c8!fc;>O2%XZ#N? zo&Q1+pf$LW0qt>{x5^M8R@C3NHR0gCLwVWx1-V5yeDJr=ndLBGxQoYtgx;w>V9J3+FDB6z^dbP*yITX0s%GJ^qAC;^P4DX{!0iXlDROZf;b3s6r6LQxY$5Gug1b|TCd1G9hr)8APC2mk-aT`k)V z^7wMXx{fn*MlLvN?O7ekQq?ZPYtVOnNw0&+Eg;g z#0MHmD}7cnrYJBVFql?OP;gLS5OGrIXy92y0{jC=A)Tus!67Ih#-N6Wg-3)(Fd2a( zIx3n!47RI)kx+mM3`qn{(xEA4zl86FzwjTM7Jh=n_mZDWluroTRnuCRu@Z;dM92fZ zaW}nJxCB%yDk@L`LVF^*aW3%)Q5k9pa>@&eP#IFt7u-n5b7_@etD_O9fK;PZ^|+B& zLxrg?sOkb50(?GbG_`31|3zB$Aj>+REdIG@q1yve*sMvSzt@DS$Jc;>N?VaC@{}F4yMGGj4_6!`nsAta^BS(5NFM!!wxP1iv zmNt=|f%)FSyQkWDb?(}`V<*M!)9U!5Lyum4&F8u%tw}nm82>sd0RCs}yXC$zXZ)m4 zd_KTGwM1zksBHuyFh8m2+r+|Ki3PXT@3j zUQBM>`2U3>Q2C#@Ejd505c_}bEC<$wW*6PYhm90|q;keLWg02mIt zKsuMC6(CIjQeZpgJ=h245|Ow{e&Ijl=SFTvD2k_$E`ly#)C#DV76ICUwg3<1(ZHX( z$S;HN|L0GC``2IEw)qtQ|AbB^?p>|cbeX-gy<=H_xATj9zA;&LXSRRCIRA(GK8=Px z4^!7PYzVu*Iq=T*&^p)U^@BaX>F#!=vwL-?g=f1h{Hpu>@?HxL8@iSbb1xX`lx4Oc zW&FG?qixrYm=rbw&+2gZF$3m;)1}@^+5gLRk*k}l+d@e1vT)JDMc!WCkXdMqLgbC8 zGam@TEATofP_!rM#Hl~;!i(TEpeq(hOh`;hOk(%Ol;o7ul++!mJJR@BNR zc!uq4iQl$$8*vULbCP!KO44>RaBvqcY&_aRegPv)qhz3@eZn?Qp)sP^{l8)P!%X0h zdmN&YA3};idxXM8#Kxu&xGEO43Rrk6A}Ho@a2pd{SFqC6Q!sn{_;EP@Uf~k#l@f&i za-*&;;AN?aR&TrwC{6ST)sUK~wW2`Yg7@N$THf!CBH)$L2&g1pii+tULf47y{v8fkQO74Vis2DZY?zfr% zr1vqLxM)RA%AW6FzWQA7o_q9%$So)5xhK=%3;fkfYJ@xt{)|nl@rfw0vGwlI!OUTP zu#u6azP`yuWdSN>5+dD94B*#A=D_D#XG+`-fDr$hp2#UJ8$@e?PECz;s5UPllXsF3y6k*+6x@IZrkyy6ZGoR z3k>#Kc>f(fpZCg*8#jP0)PlVtkPVW9bO6p!9I%Fc4%6TsxC8hQ4~&yRbO90aqZCjF z5+MUQxgD1dCBS)61Y-8{II@99z9HO#?}$?}KuejkgYi!ahBSll|EBQ2&4(ZL`MkTu z=Y!nZkB{jzBlAm#13g?$5A(j#&AYyn_jg^FecyfA_kEV#oxI|<{qp)zUf)dfys{Q+ zf6+Np*ONn?D?XoH)^28LXWK%X89R-qrRq)IYB(Ww$mB@+$i|IbZZX2ca>)EqeP^5Y zx5E^N{4jsX;w7F-JQsT`_VVMI%dA?NSPN0H9)Sj=;sP_4 z#BYt0GE&$+3`$dJn;_;!zTAz7UF?HRDO^JG=whF^ z)Co&o3tc5p`LFn%S_A_d;f#=5c<0I%A+DYh;j^GJ(7xr?xBsge1pZTb3eeRcswR+T zg<2)jrFFwA@H&cC(~2kpK0T@=N{tU%{8|!0~LVpXwZ<^qs;=~_8(LM3jf27pSbb3^yEV@%Xm(V|Je)TW&SVzeB;53IEY~R z8xLAIc&HnvBZedFBOELdL%D+?U35>e3r;Pb>SMQ~W}71Q-mMf@uxWDH_L+Qze?fEr}mhPB4FQ|9#u|0Z>?Adc@ zP*9k$v3d9I142T=q=C=Ryt=vuvH$%d4){jwdt>=) z2ZFx!{8TFNSIK|jyPtIrQ3q;6p!nzy^c};0HiEoZUr!UDpsY%|0K^5vb}%7pw^bgm zf-k`3)~#DA^S}KKVGA%o%^yqPFNg-q2ucC7T>L*`qKmmJs3!xb#9=iearA<;4!DbZ zp*khQe^4*5LYr_SDgd2AB3HSWQ^^C<;22D!8Y~R~|NpA^|J(fY!`>fu8vn(hg`F)T zJKOH) ztbIH)Xff(fWf=Y!zjfz|kc=gvISWDxT_W}_h&;S#^%3{=o)Pk3)U;j{HbVDgEGohQOFPxvP&S69ZL@QKq#ww&h=?% zDJKHBwE2YZmMY(^Rgv4P(h4gxip$rgl`UUe>h7Pt$ZaFM#c9Lm1MO9_U(0?4{zRZ0 z{6}@mKh4?x`I%m`bXaji# z`dT60N~qO)OOV32gdzaZ+(iK`YUKBH0gqM{84(d)R#X7*E=sKx|9OO}0*Ii^xuw;# z-?pE9@n!oi^aTvj(F^ZY1T8M0vC6o8Gi-I;R={uif^_+>Sl5ReSl&UI{5uBY->HyIO#cuZxvMB`|85Y zhmAjefA8MSoAu|;oli{M(YLQD>q6`4jp)~JBpzHNBXed?(qaMvOdiGU&(_V%NTM&` zU81507>a+fWv5`~1&AV$R)FxIMg;d>yL#>Dkz=uIH?qer8$lZM8IZhl_t{&IE`0YG zghp>VZtb*fP+|a?GT`>?2#s8?Ch4apG(9B zt=p#s{^I#T6CFDJ2L8I(Zxu%ipaQ5Q`8Vyj>g>5%_>T%uy8zTCKvM3WqvaKtnEYg} zUcHL_5BO08sxUi@xEiuv1Z>Ap$LbbqpEyj$T?3Y}?fD}jB$5qH0q0f7gL*loAwau; zxU>$)Pfp>#`1awsj8P(Hp#;3>@E`yG-~Qa@laG70>1Ni( zXnuRsu=ZAo9cLAM;ZWAm<>Z$OFLZLN?zreuXSa(T7oHpGdTNC8@lJEfI@|ASKclFp zZO)WwJ4RY=>o{(Gr%}=E1_$dKu9$D+IiZhh7ky{_9(LV34(rsudlxo0GB##wRQg^S z$jYPFtzCzgCOs`9Zc}PRR7OC=u8@tTLEDZj-h5)g#xw5QFM4OydZu6VO8;iMgdi#!ql9XlGh=W7eoud ze@f$Bg#W4*&{YJGUlakK0G}ro3%$Ut2+uB%vK?5f^mk8b0`%x%%FNl3rYzTh3W#98 zT^pN_-&z+)_5WyHEB9I6jTL@Ij%5d~fF7fyXy~-hCqi-`sxAyIeO?BF#2Hg=D2;V ze;66XO1|`Q(P+JV`O2BI=f1gqu%Y4j9z6!SxGeJW@@7j|ta^s=pamMWJ;LweloaN9(a&2_vKK!wi-(C8 zaB*?RJ%Brbt&4p%&L_i!1%?1+X6yw1Y~$Dp{uuwdo*ydH3iz!~$v~}Wvrx&cnRTl- z<`tHm0R9}ffTRmR_%FS{VX+BXheIWQ8i7BwR|SW^uCN6R!~?tt?rR*^5F3&UmQev< z9KC>cfdAy=5(2j&Ik#XW6OtmjfD8yQ7o8#nay$M&eoYikf$*P@E@L8u#1Yg1Pn4x0 zh|p6^zbXT7{?DKO_V+)3_RkOWKk790bEA1}#{{&QxTVdsoc6Q!w0Aht&atwiQ&mUj zs;=`ZyE&D0p1Z%@jAEmyIVMxmI!xH6Z@Hm|X|&$(;2wilb~f}f?Cm(q#@Y*m3@0X3fK$wGT6@A7)%^Oh4b4cBV1$MC0nC zjX|Z#5m=&x5oL`r6^)y!8#iBSTvgE+S*9G}2OA>~DUqndjjJmf*H%4DJ@+v8;)C4k zAM$GMWuN^n=j7Mv2fm8gl#h=HAC$mf8dG3j$PcXW2oYknwsQLbe|$a&%ttVQF>Y~m zU{^y$T~tC&AwMCa@?YQ&_C*x*EAFgH(p$*=_J3{rLkVCwk5g$+gS3_4|Dqf<|Jx#T zVicmQL{u#x5zz%|qkvQ1PToiqSt~8TTk{IA65%^F4@BZ_RS%(z(Pq2Vfm#;@1j`L z0g8a*hexfwSSs^%BaAz$sytq@`$#}!kxyt*jNxS69d1P8ay3=n8EF z@C$PJ`$BTeZ=4?BUA#1;KxSZ$e}+qdT?kJGF2Q^vD*1^E_R%1GHxTZ^me9GZjaG1Xx!k`-X|382F>)-zT=?5R^ebiypzxvGnbfizO3G4K& zlRulbtH;dZadS$?&fV8#)*ijNMfx*yx=l^*F(J|3eB;oOG2KRl^c(JLIK->JpekOcp zbyVK9wR>-DF2B8{>ibPc8{#V)Q!YH(bn2&|{ZBTZe!A<%)9mX{Gisk@Tz-~)?OFcK zXL&cC?fP1YXJ3Anap_so`DZbe&q5AA3*|WYEaKR+)n7f^aN*gu8_(iupRGReEav#L zRU8#cB&z(`mUGVz-RF2(eB9-nFP9G%#~R~*-b?sDlE_ZGGz8EBEDfZuXEtZf zA_s?+c6JeVcHt`dC8F>@u%fW)feL>M%ek{>JKEbj*xAkX@bI#XeB9=g3g@bSBc?AD+#>gegP&7MP^+`{I_(>@!Mf|8xel#T;)4Mt6|tMWp_w@ z{ZT!84#BL$_{R|h{B<`1{)1XTngcje7&yv6@&^wdhJ{A6mu_Z87E3@Z_4Y|iO|Llh zZE^X7qOyDIlTMc$uRC)7QEI{MkhRB_uLy!62)}Cvl`~CjZOnT5f@uZZ`|0`F+fOdE z*xPu4F5Z2zyYloXUrl+9tqz35+5**WwX+Z$kjhg)l?e!EVm1X?FHDcGebF zUap}`-Ac&0Edzekd0r~~-_v0IDBBf03Qw`Bw`X{;gb&biAxgzEkGh4FCokq zjX)xb1H1!#NhE>^K{_y(qU3fShd_RA6qP~9DJlRpM6q1u&xf%weE9Ic2><`pqiy>U zAL!5cV36l{^GHjpP5rHt4Qw);r)SKakzp`Bwa?T9gNYk^kB{j;Hq>B(qynHWA7Pq&q#YlY~tbPaXeJ%mDrXXvp(H3JjXt;WKLw+{Mf2xN#`PS zYu1#09eb#L!_n_Hmfzb{{=??-AGezy{JNLBuD#5@{Bqm*m#ZpYMwGvdVL_&oB@-1pbek^Uk z3rJPk)96qcE)5V+3_XB6{ZPVuA|jlU4rDMU$;ORxi-c-9QaG&UE>Qt$3*x=H0G_ML zOWsIAc}GH2079`;jLMTA5l0aAKa!u9&!=mm9r=$6z}2&C=?XqobnYJ+`SUyK04>0h z3n&5`Yug12+-YSdChl(43V{Dhe2ztKskG2q{^k?r%$%uUf96bwS+nL%oH&2jFlDHZ zSpG89U&ewCFq%)}B4EwY-`^Bcd_jZ^E;Tysi z0PBb;Dzt_eM#x}7e!R?Ep^uFAGQU%Pp4`F&7CvOYko;_S?=BrYcoJS9RDizz;Drkp zF@J>t3mEXYaWMYXfjxgv3t&{^_NVXo`ZqTi`H9abz%O{kQa=Xyvu{hu{!6h*XTsK& z?K}A`mVDV+r3={Fd7F!?vKKALLRH~*<~JT57DbQnq5X$|^MxyQIQdl-AgzGnihJqB zckr&1S3gpeLW_cEg<=RyE1>$jC*M8zNmm63`Ols?>u5jM-e!iC`9y1r$u^c&ax7mG zu_fdB*6drrAM7)plOAWa&$rbhe*csvKuLMShONccV}TUPN3cD}Lr(4d-@pCs z|NZoT{@J5zdz0RJQ$HKv+Rnt^XiVhN$?K+=Z|rBfzSEes-Nr`u9UE#q(r>`vr2_|h z^zXZHP~W)&`%EzCIoQI&!p_bP;4|2s&I%ON#*LfO(=&FYWe2ZHTi~1R8dbV@!;z(1 zPb}Da-ueII>^z{WII_Hd&hF0H{bs+}8QU}C9C5-1Cu}g-7~4eK7!1ZHnP`F#0)Yrh zhzvprBqV_V1(GC`a}FpAm%BXZ8td-eV5U1&cG?DaQw`jqOm`t|Ej_50ttb-Oxb z_tc0(wh_l1Vooi|JnLV4VSUw=4fWSH)ZGZKyBS=2JGlDJrk!^q58eyk*Rrv(HGFq# zY*TC0f!4^qruZgP>SM2uNvnl1IDe1T=>8L5;pebsfDX`k)S!(hq zF|8;vd6k)bYfNi*n>L*^g&j5d*O^vUn!@*)vQL>ZPPS(1<=*!5xAV?iOW1XGOZM*I zjoBr|CD{K=e9u@f@E87z*)QY={tOT^MgUa7J4xI=nEfQ+kM&Cu{!^gkLPc`HriJ?V z$q)Pu{sVt&AB(^r0t^2I*VX{1>meU8KZO6}MiL2-j~o(PS~@GgWNmiE53w=)7ZspD z5+M*3AV-YI(KyaU&O*+Jk46#|K=SDIQ0B@Q9RVZ&AwZ1yFISICx_`^h|vOswH9Q?)4bY~wfIe1k`q zn@bg<`^-a{glcpDuq1hj(5Igc5(#+w?QTPc{Me_@u;}P`C#QMv-&z9Nc!U^GkS7JK z9VtecG2#RJ4=}F+6FB1?+PXP1z;Eqr2dB8q(wgHp>P}q8_z#IaGSM-r&nUmiwt8ZD zIwpV%d_fq_#c{5S-^zfT%$%x<%7(p1H2)t!9_=XIb2U8Wl=K307vQ%g06uGv&x|;05zybBglpS)CwvL`vLf@rz^pJ*cBc>e$j1M*AKtMv5$wxajqjnT3B@0#Xt`7rDx{*1t(8ik~q>Wea@QgBbM)& z=vTKqd5>52;bj@e=cS#tPdGa(?c$uwE3?wByJX$;D!v8wH|@T&W$)cBds{Z`ZrRk> zx@o5=VxKAQs3~%vY0EBi)IoFNadYfpbJTuw@=0^r8FRu>y`-Epr=KyWH|s+333FnT zIpMH*>mIXTrP;I0>{Vv=EHSUFGOunh2Ol|^KR%Jyv7m|a>@8WA1={AE&O?f0>Get9;b+J|2RW03#8|L6V;5BP%4 z1#OJ~{PQn($u+)EjDH#nhCM?7Sk5$CdI8iZcn%y`Lzfv-A8!vmXgog{R6OU%MQd(u z=Cb46<%xByHE}X*+_?FZPX>wvy!mG5!GnJ|bLQ;cz5D$AgKz|4`5V0eDX@lxcf^AM z96lz~qbKCij{pY*@u+WAWfk$C4)(J*hHc(;m)( zOkkJzpP?2uEeWdd;4ovy73DkXb|1bk0TvYi_zeESf0mTO3x$pMhY22uXua~(jbmpn z0e?Ca);7O2`GG(FpGl*~xz3t7ZNh|wF5c;-m;PnTA5qZ!KXC&EiB72tjm-e{;{Ra? zSSEsIEP$!uSdSJkC>$1-#^fm&HcSc){|)9dSYsrd|J-8if36r9=Ms^`_!n*ic?1+C zGB!3YFE78bv9X}2a@D#lhvg|lT{0&66wcka zW2jf%?5I69TMm!jaC};Lvv<+Cp!$oxrB@uYuFuK5>6mqEUeWD&g?C+Y?=3BA39M<| zyt_5>fN9%7Omy?sy=Jh_65FH_PpGKXs@Ov+u1RH_QyFJe(g~G(LZvsW z?DHz)tV%zvQctLqBP#xo+PF)ttW@4RlvkPZ*`Zd~s-V59_@3IWRM8cM3gnzNWzhvV zaW}2$M$+zc2^D*`#pYoD8~hjYi}4Tn4ftcelE4@6#OB8&7Rw)yV)jdd{3M76X`v$A z1DI{dFZ^dSXipm_QIG^|F}7i^@SmMn)7vP+c0euDOp#j`DA(53vNuZ~MQ8FYDHtEw zGbTD)A_0;_N*)#heh5V~WXm`gLkK8{%yGU*0QyKm0$9%%K^fWs^ze0%C~yI}j9LP$ z=6rbJ`9B)@^E>>1{BKWw^kKJNy+*zH=J3uRPfkkCOGqe@UI3E?eg36audf{kem4%| zp8?;QGw0y>>E8WEp78yC$a2HyBMqgHOLw~qNSu&=Fs3-fu7jQ2BU zR`X=BhJRAl4$LiDJ?(UOcZAErJ)%8w3uw6#Szc3*ful7e2yUFE5{N-LwP{5&Hi7J!)#|FqLoIxVdJ{dI|4rBLPNV0G|O) zBnA`=%ikyv9W;IFEM5dWXuuBxz8TEaYQdXx8Mob%bkcK8#l$&VgCgn~|DE6%>Uy!}v@ z^(<_lw>hmBjQ{Fm*E4d8CypMEpI^K^*5s!=Y|sxlf5r_P<+0c;IKX?R%_OIpi;}iC z|7&g^=@D=M91@SJMI~2<#H0)V83JY?n5O_31s47j0wg_xkeD=WfU9;pdjF3`;t1MgfY_{*$tN4G+I|B5kw^&|cFF3mdZl6=A`p?OB?xk*tMCq`bGopgOw*-iJ# zTeC86&&j?!ui&0bev4aS>*5_Iw<42ko(YRRw9y>7-yCy9MITmC2i3L%Dq@d{+@}(b zsl?+dYM+YUf1mlNK+ek;pg$WIF;fjjN= zdC2V}mOr%u{_|gJ_``fbC@_@7#^PORLw?{-r2@_Ze@*aTC+H!jyXL+n!4T_IS67Ey zi7)A1%0tQ689&6g9_-`(jD=`{2m!|+iG$=w9vrofLA90uIY*HI=>-@nfCNzHXemfC zBtTTax)<;}RR81udg8GsKX|{(7hnAJaW}iq`#5+1a&~5RQDR~l&VTs-+2`Kh4#1k8 zh}mzk|7U;m4g9x<{48JV=^gZIS$ORW&v{9x|AzRZ;aR7J^N%EdZvAE8pH*`S^7H6c zQf4{lOIzbA(HODh@#@faFt=!Nw0dYjTc%5nP+~A}{fPp?N)!VUdlJ-RUva@NUc5+X z5TgUQa1jv%f-lm#xrT&(eDFbEo(t>WpTUB8SFUJp$*o(r!8@it!vPOV0Nx=w0`w7F zToyDm?8MJwz+Vc83lqLg7-s|gc`3Zx;!WT`%Mbo9+s!QHMJARnBcCPb6 zXamPM63&G~r3*u1CHx`bn&32PN=yV=yX%l14zO^Z&`=%$s5yQO%<^mw)k#q8$hXZpo+q~% zot<*esi0+kX{%FC>%8rz1tsSB1?EL%<|UQp1;uJ%q4KLzTlXo<{@5dWK?R~LDgewe z{t<$0`&8Uvm3m6^KmM>Lf6hgnWBCLB+>0vbf-YpT=9o%8sv`EQ)zvDXRx3iraV&pT zbWPPOwaaWSyWW~}>Tbr-8;OJf748k&l0&#PT!a4vdSdyL4ET%NU-)m>u>xUyK5g7S zke@_DCKpbE0+PW`h7U-rq4^8{$uavS3H%|j*#G>B@LQm5l&N@afDiL!4FwXv&c=FV z`k};n_J;bfne|Srg+L^L968`zIC%Uya^!L%mUFtVXmXm;9Y7951>hUZhhrGJd>3jN z62LViiIR#05WvHXpnsh6kK7XfKQD-RtzGv|d)W8*5sEm4-td?oVrUI{?!+fO3tO{Rj*mI zHXR!NUVZ#JP{pq1iK+>+w@!D^lgWb}fR7!^8F5q$ zRntSkS;1kGFiQC^#DG6^1snDqscbr5d+drlguCgUTIj63`b{I5Q8JvOy2I6BRm|1uE}%*P!>UjP>nT>ypvcq71KpLJQ;S^|JP z;(YE z&kw_?7*eKQ@h@@pQ1?iDWdD2x<|8iT?1X~+1fHUvU-o?FPtU*l-><&=_&e`B+wG&b zdwtfe-#6d%=P6wVbD5TbA#40RJnq8~Wp;k`3jfp@i<4}YWRG$$8nCePC%?woTlYIf zHcbdQ@l)^_yYO>UqArh*ykZl3!?*6{x;?jicii!+xa(MW&n2(Lzq-|TN9(*SlXH%F zQKi|f!0ei9URjJ+X&X^Z`x&_#-Oyw9fgM zbWCGE>8M_?{8>^@s`OLZ7nFZV<(^krXH>>%m2Q!Vgrh18H_<8mG3%7teo>X*H1BL} zt+{(Q=k$%_J?FL+>RQ!JPqrnk3agjDJo4{QHwR z;3k5Nf=bDOClrN;{EM$ZegpnOe#xOO{5O~n!iD_8a@Ny3pwKvj`i>Mg#Ye^~|e6TyFf1_gPmeV?wM*a`f#8~>|$ojOm5ib_mQ-U0sy46q$N zdOS`NOSI<%W6bx#Xs^o`y&ZA*|33Vg$)A}y;|k9v7BwfA=$EtO@Zq^F`i(R2~3&aR> zDzmx z&XItj1GTFMS3hRIll^pq{FwbIu^Y>a(pV}=((}@za+9~#@wD>4#D7!+nPZZQnAF;b z`JY-`$>1;WM*=8VTtGYE|9sCi^4>n$Ec_SX)0MMM+&*p=3@7K-Q{bXu25=?mD8YH5 zG_?gF3#hr#tVab%tRd&SR4od8SGI)wB)-B<*cE*NG5+!MLw>3pzr|PB6^WhjyL_G7 zLE^sfkvi)r}J$ii3*b@`-czSwm+O!!vp9S{@j&b)jxs%<}zMq@j z->GQw%BoqRjWf6G9}(CzH0Z>v#4`(0&$%RDnwNgnCFT0~tv4sf-?E9nn%C8tmu)vYW~oIx)RGD{FJEE#FDX}xOVpAw5f1~vr25z_J7_bZTx4P(&W#(_=^ev z{Iuhm{O~`!S!JEHbOcVDiY~QQ+`e0X{rdJ(=VFTXY}}F!|9Kr3M1$}UNjv>F-VgW@ z_#5OGI~My5sDfFr|1kNnnSmY~AQJ!qGng`Z0rRnk8TO^&3;d}(7=eO)U@L|<9Omm# zx(&DaC;&%d_&VPLHPkUkj;B$0PJx}^AYw~$DNwfl$V$El{3Wpm3grB*xM1Hc+ z9pEJ_?c4WdCTAvv!}6EVP0H;%jM=<7Iy<|D_l14;-IP(I#^M8+Hf`pQ!yNj4&Fdg} z&ew?cabYf?had8_HvVx0MdmaIC!JgwR=vVI2pY%6#zjR%bNm=!`0aVDhIYrf&^BQL zcbTilwc^TyKGpJ2Xn3LHFr0f3JLfF^VS2N7Qx zJ$eiyAm4ub-RrNu*|EcWLVhg&7hiap<%Q>7eE!)NSh{o{-FuXO9}E0@k6JxqS{PO> z-u@}$#%qVqLRanZ*?gb;JBrgQOEYDuD$CrS8C{Sb4aWZk3BYTF@gJAo7@u2)@z0{; ze=PnV83N!VDu4t$Z~^I;0x$Aem!6@U7%f_u&seY|+MpD;#iE1Y7aIU9(-#2aTq{g> zEO}OPyJZd9ihyDOSg@^C0CbCR@O8*9%tt=B5hSoLc!&8o2@UwO2P&bc2|Fi=Is<>c zLYbUf#`_Mf5WczgTMM~7!rw!ESS_rRPHa}q}{&i-jh@rdPBgO~68&f~zC zfFq7EC)|?HOpiT3GW7D)gsaQ8-*C^r=}~ywv-plf(%s2%_ok(`OigN8UTO+IVcK}u zytdX1{KJo#H||rxjcVg=y`R`G!3rmW$--eC= z)_clHi^J!L?hfD!g8Uf&EDZG~9M%pWjDNg6i~{1>3n%CP_2xP65G2K*_oaU1wcgQY%@ zKs|MX4Jd;_m`~?jm@m2E@Dca}ZTOGXO%m{08}J6kDHvsOJ@KP-2iQ4#0OM3V&;e3p zOL8`oG6fP8;wy$;pc*0^h8Bnfa10y?8$*8FP+9;|?uVX=3IH?`7oiRRv20ln@Hq^N z0%-eR5?fkJ0GAZ|pNW8oR%4%BE9q)AvK4<}j@T^nA zM%gkh1_N<(alV`s&65CrS`&Cg*H}**r|nZuxV%`!G-SxnDZ>h`4C}c{C+2hF0bMwM0slYme8>OqxF`iJ>e{*c^Uu8qqKE!CRCta~F|^I`fFpbbfE{BJ zb|GH$1z;NfA1(s_rNG9l{J6`<|9Ik`&ph=kyMpru`Gx=Yb9_P1z1ZR1K3@*=88#)v zWm(32uL2Lx&=rf^wg#_`2n_)KV)Gm1uPDiorK&7zduB{tO8CFPfARbi`4g93Pi&8# z=h@=_hxWikw^ z#2}}D9I#T54!x-iu$?+Xg69xkP|x;UShhq}x#nz%vr*trPFV&N#Qx{Ir~o>`uOrZi z3;RcxEr-Fw2<*m*S(n$Z-+;AGJxoq5THupBd~U*sd6|RUiopI4D|gP=!V7$l{2YAp zhk!G~*PWjkdwEgT)!FGc#z)@#Ir{dzf;(QNcfHD5R+hJ{C~lpWV49X{nvr3inP&E` zGDn^=Z*EdSbt+`Hiaw>no3vrSX^#qNR4a;G<^>Z(%{L8u*fX^rYqE-a$ z5jv-x|Cz`20{?aV&+*pOraP$zucz)in_jy+H8G3PdMF9aXmljnDOQ#-=1T)73H-?| z5ia`iF1QLyLA{WloE`yoJ53nYVfzXB#o(va8xkNkKjb&yPgMcnWLui}?+g(<&~;7xUKm^ONl~uCab;Ul<8E^8*6|vHW>C5iu16 zOVF;UAv9YqCY#Y1=^fDM_!hT-OMzZPMaG3Oo-vi7C6u3fP4GRj@mxA80s(|)N=|PGoh*&`HX0D3ar7HBvD2JP(5T3sp6#Q3w-)%clLm{ z=U1q=nEh?m=wEsMCDfsNkCCqKxxO2!Qwq+f6rIn>D;1l6M{(N2ypv!s0VhQgsgu6#YuRC=wu@ z1*Cz0i3GrZwxp`?E%bs)1^L;GMD^n^PysSbePV_1aMP|q*S4t4CEjsk=EMw~mDb;R z`_L5?Q`a_3S-)@S>ZTz9C#J=maY?=~H~#Y2O;<;T-IyM8(>Ct*&rx@#B;TDF-7-DB z#iz1$Wkst`naRJ(v^dW^Ey3)NVV;$#=47cgJ5}^)6>(gxZ&0B~zzG$7Qf=O=19G

ysV0@s=`Zz{aB3u6DsRC@&7HEC+;NeyB1q} zCUX1EEfE>SZ^3`eS?~q7K^azDn=xPPH%YW^+NQX;0T&5sQ4RR6_&|WaND0KFMU!AM ziF(q;>_>K~BqSj}@F#&^C?W7Spe+S*eoJx+ZIY~~1`6KUEk7-XhZe|xVJtP1>Piy$ zOTnnUQb2?F3N?iD68^&_l65bD^OYq0=dAh2k#ml6z83ud!hb%Zm0UU`0KRbnrTGjR zIAr-Ucm5^(=Q#P5etjM-0RsQG-)8c+S>OM(YSzL8zb(7h#~oSXUt}|TYv2C!n7z3t zkvx`HdReHxc3sS#bC++Vr)P{GKbeu=L4&3Z8l+$8qQibHBfkv$GQB6p|HBXY%1|#7 zAmN=e9hqYE2O64G4^D)xB9CZ&^wCF5s7OpTZ?dBoK&#|m+*2AL1{gOKrNB<6@k;xp zrDOclqCo){ffh;=rnYdk*)w)NA8{*D=2CD6Y4|{uR*dIo>(+4QZLjBio!^75^&uKncW?hqI&eSOgS^3rk-ckg#Qc6#pF7hv_EL3oG<^T;P| zD4zExGK7zuI9CHL!{Eo%=U*_NkKMX`!dKe8^4cFEKU)g?JH6MLrDyNa8=?+ikQ0EK zS9f{$!Gk-BGl0LidJLQ2y1>7%|MOGB|M(C9X1~CnXMUqo>rx7}dk6lDZBK;15duUP zK;8&kXXz0bn=u5i$UDf=Io2;r66|xMjYJE=y5s&rc-YG=hWy+|$c!8SeB=OSlW2)+3hmOmS_2h0yPU}Gv9iHbp;A@LQGNC5UfHBc%cd*E@c zO`A5;oSAZX{l*lhxiJ_V>-x_1)CqAPXb+oChY=(`~?3eH|dT5#y=ea))Ze; z1sAmhY`>sNuBj4HfwSi9lcw~eE$K&YryRT*-_X1zvoUBx8lG6FN{owGwtx<%!6+J_ zHvPl3@elk#772opu+6Y$X}stK*r!Zxke~gq2Y@CdG~jPB`R|+k55u22L!t^nQT8mv zCYOTHo_#(t!A~}TAq+){LlUPJi8A{XAz(jP<7@!)Suf<5g0%{u3v339gwGU6k5mE9 zoihddoGb+no0CH3NOI!*uBZV2VxN@RCl`~i&}ukZa<2Bk0pBlMs^18V>Twnv=OZQH z0sMLYugh28F6{g5!qGPCeK$3RrJUq#SsN0Ld56~G!^fnzEY8^fqb99c5nR`F@={Dp z95yWRKch!GfA^h^`IM1giTU9D7o%o0M(#DXE*QkQ zN`1ikef8B>pL*)4=bwN6l~-Qj$x19_S|}}-4LDOykgsr3v_wuHuv0jG{5V?At>hB1 z25XI7aRq40G+tUOKSZLMF<3wWy`VYM3xFFSWrmgi-u(Qj1%y#V3=*I)Bs-2ff}A`v>+vu979O=iHFgfO83@SnZ_BZ=_*<(Jx# z|B;2?lI8t(Kjf9ZeR_WL{=1!RY@O=$vjBRjKXrZI;e(Z>xO&p9nct?&27hD-Kx6+w zm{9f6>&XSD{Wqk><&>rrR|@38KE{6={zHDuel`$ykjMl>0Q0@pCM9d{DECy%HcRvU zCBqN`_$1^WydwcPaDX$l0-Il(0+xgX;QyhBG;sIXfSLo?CD(co7>I(%Hb?-8T~Qg> zUN}z&6D$~#c>5$ZD_uF|DaULr0si$W_OyyUrM4VUp$#hPh)QVI zLID4_?bqLO%~EdJ+UJkk$GcW7B@n1o8~>gNLAhF0r&U0ULYdmos6&9#PHN_h3Sj)} zA>d;=?1#wDB>sz&hY+A=0{?!_Uk_L~?TRZnyD9A?FU;DKaZ28q zIL|Y8;EyW^>Ew-F`2U%`C%*VxRD2GmldbLav147~zrerETV1SQ)Fs}2@%%?*om#Zq zANYfJJR5)-cgN$8Ki;lgJD%`m9POX~{OAAt&;R`GZ-0B@i6`E8;|&aB>@i%3Tw$&l zZ4=;QuwhPck7%BpJI@Vqrffs&rgwlQQkEu6bEaw2z`;J!z-E{POcn}B*u%AJ*SMGt z4*JdSk6dhi-3uTnsIhSuqQO|e!@~i#w)Qh;&gJ!y%;DDY?RSO7-X1ygI$# zMflGX&CD3qxpQaSTy%5j?=TMl=gyoJoIW%Ce%R?Ffd2;#evt-#i|xtZ?eM<9AO3&Z z^>c?=3#*zgGAyf|^Cz$GIe5@Q``_dLZw&z$z?Xs+l#@4Vj$BJEJ{KHw*f%I?{kD|& z{4$V^dq-@0d^>IV-=rr3!VAPUEWhyIb8TFL7I)eL&76B=X~#OVH0x@b0BlFEp*@mK z_YFQ9@CW1EP;iYp0DrdRUqBl>pOwI$dP3bGr_2{&KD%P%mz**+ip~XlKv|Fm1cGWt z&ad$m>IpU~{Gl;cR#ZpFW-s)J88#yd><@6s8@#l9;L_Tm-psUraL%@)bD~Z=M4cNE zd}-9CD?e?zJ}>v?qU_sC3+_yex;r+a#WuOcv!ZoHp~=0#f z1W2Cwq9Z^EXr3hsDEWx~FJ?dSKiQ{M@l|dA=QAjL9{!t(ue9c$y_y7> zrdEfBB=H0v{5RmwJtaXrz>WkMZXYrJfxqzI!v06YUv|Y#XsT2LK_YB~kR);VNF|}R z7#0In$lyQ6BfvLuYt#!iStA7_XAj_Al3@SAC;brmL zfMz7i<@se$82AG;PD)PjwY*fB2szFsH+|AU5k+PlX5{zJZ7Gf&T3?2FwC>tH+04No|x{{OY4 z|6@siwMs9){4&iDV}ND|y}53{oWWBZ;{;4HUchP6()ky+55hxxS~LwA2#8q-E9gFu z<2yn}sAkj-O#s)3RJ@H7$dpV5R%m# zABR8t2mS{Czv?pp3Hb2+u9IvX<=No}{0IKO$A1|D$WM*X-?9kDeex3#1oJIjiK-*K z=jB3j;hBiUs)arwYa>&EKcl@E{K9|Bod1=Nd?uCdQfO7nxU9m{$}5f9-1mJuNU6XU9U~~bb7k~%?f60MAXGh{_NdkX45zaI%H4RtN zfNuvA*uz7R9KbhU55V##&a=Z?efsso?W3pY`M9giXJ0rF>VpA~3M}#~#sw6!{VWDN z7CRCUoOoi@#(E@xVS+JJ)~$;>P`~FG!z_%%_Wf$om;K!6AmH=y3aJUtJZ&B1XWp_t^<3wrc)WRy5vDJW4kmW{@BjYqC!c)snP;B)```bL=jR{)_y=p~0-yu*3viE! zNly)-fF+N=XqaV6PY91iVW~=b90VZXJ|dh3wxbd9m@sR=EJ8z<0sd1Vxt=@}fHjDx zg(goO!yRO6i=_O2NWk?6K|!_;W(tz82LuFNyMAlJ+{jLydP{uHgmF{m&s*y3IKT6U z-NgQX?_Ey%J$g4Uyzl~;V$=gsqf9Sg`0x?dVEPrgqU|{~tP3S(^3x{Fe|=hJb62>zN#Qn78`KHO6+!_FqmZ zYECUa6PI^7Ea7NWO6`2_V3*|qF75&Awj~39+&EbKI^gqxZQq9fh{7*J08QHd#}~v? z0DKqzySfK3)`y^Du83V{G;rZR?s|v~ow@HIUHH!h#K}X#%SVpN^Isu3eE~Mco<}dZ z!jPYv4*b~?`9L_>j2#*|*vGxJbScmL`ZA=OnwplKvppy*eZF_n6t`&G<*9b7@~8Qi zJA~BD+OlVQ*rA~T$HD&S&F4mjTpAgAb#Cg7#aR1!w-;vLv5UJqA*y9|dW&mzt8I#D z+&0scB=f`=y-Z8h5cVn8@b@lJEAh`1t63>(2Bv3qT@`UZRYI(Wd3Cq$#wJ1+5&QmK&mETUS z0=R(i{D6I54xm!`)vJJA`Xi4C1mRgatl^IY&=U|p%3KC+naC(TtLEz8b6xKmL3bfXTEq|Ie3G$Ob z7IlC`!?b{3XIe;7QsA3GMQX_JlON9yN%(I~{x+O%^O2t*u@ZYjEPMez<=;x83->j^ z^2hKO;hEu5AOWHRA_NZ<;Qn8(iSz*eLxloFkC>! z@pB3ydF-}V&whA*kN|#*r^9%>t5?rSLx!yA`;FU|eVsae^fS?(677#AKXlA$ui)C4 z?f2i$@<0NPBLO2P1h9CAH5BdGiw)e=bY$`Jut~Eb-Mq8BLuzDVH@3INzLb%YZMkQC z!s_NYFDJYQ@M7rF1!&*CJ#L@ZUVDv#IQ$v;MFo%mc!&hhAs`9}1CORnwV{$gOS%k9 z2Sm^{L#SB$SnpUAxE5*4?3_eg4I`(7)h;gcyhg3c}vF5nLQ}0oxn9g0aHM zlWlNk{Z<#?k-dOhzn&%nA(&}#{#?F#Yl%jJ0=Ym3w9zEuNWqz9t@b(jE%7V4u^YebZ$$j+539inI=D9AO zX6wL5huMoO4`0NFw*>QC-+So5Z@GZ*`~&}*aza33GvXo{HRfer1P<}ca#-B)_2C7s z9_yUl*Lns;rW950*t6fwbM2fZzM$LSKO~3$a9-HX5HNE-8{@yie}({3i>q)Dp#|b5 zipef!S8g6_qGRG{{v<3Mng9k56`MOHJfX+OEhd3(?k0)55A9(-)q|TzLJr`$NB{*k zAcywwAGeRV@!5>8P$lRa@Csd~-*nY)(M3lBwrz{z=dyDOSFMS&ag7|{5ItaS>R`8g z`=A|Qf9|$Dv$q~{iaYL_((Dv}?&r;yhKF7q6M21H#Lb^J-Lg-(v%K)`vci_dxh)HF zT9@SO$&<13UGmHmqRlq(YD%J-9IGg}7O22RZTah^RQZDCA~icrQ$1vlo^NNvPPMv0 zIp%1yUps$t6_0w+O>oLoZu!b>yH){42ZDF2RC)o;I?i+9cC`T1S7^^a9~tL`|I16% za(V>$YDvEC0tD>QLjX+U1Mt~DDzLIj7Xo+d@~TP|x>Jt}U!T1tW3u%g-X zfddC%JMJu!z+cLev&L9YS!BY{0ty@<{SK1wUnIcN5BODIfNMqK1o>%>U--|d$qAAR z|3w0%3t*@K&7_S47{@Os$cb~&=m_-g^%akUd93jKs^7OgzZ^egh|urji23Z$p#yz^H{X1d z{J;L|zvu#BC-X0?dR+Q6TfmO<9B;Y!&*>cu95@gl;Oz(X3>FhP1Nm7=H-U&y26-X5^eBK*ha^LdXx@ZaBe4X+iB*%s&Pv%1rJT_#PL^J^E-uZDnSL|Es= zX{7~8g}Eu~Bld1dI?9U%cvc*S!n}Yw|~EM$FSA)gT3}l-E!D9QBS<=ntIMH z{nDbmYm0KO+sEA;wfXkAs5=wm?~aMMM-1n(qE=?kU$&jayu85dQOf+un!wZ2HTmt5 zm2JFUrllzNaurykR+Ve`v-shSFH>u3)H=dD_o?-bDrA=m*l8g@BfmI*a+OQAa?H3d z0X*t8zd&mNBL#uG)CxQ~b!zzz?fhrVmtMfidP}qq{4drju&h8W-L94uYR?azBJKGp zQ>&^q{QYW`Z;jpwD!_kN*XV%K)Z^OD$LuHIA34D7lg_yC8C85mM}B4;*VDe`pS_oU z{GD#d-Q;>0e^ZTB-|ry_zwiYqrrT^KIAkKr+@J=5RT!XgmAkL1Bfxny%5~4(ViUfovpX62Vgodt(-j}tVp_Y0AtfG@E!n4mkZ1YQ~KVd(b z|791}MAW%1@V2wF1I`%m67I-zUQFza-vbrE2aX(odK^K70KtDCiB}v*k}#5~9vJo? ze)u6Tf*~}NgmB2nDJnn+CCn!gLW8)lXJ*vFzXbo`26iBjr<=f)qzk|?pcM2As7};C z;J`L)Px>7%&?9>Rh~VYRSC}=z#%3B%7vcPOT$&31M@-xFGB|L40`Zj7j_Pv8b-mUPq%MFd+U$l>LDD+dSL^0E3SSz8kqefhmCV} zo*x&Tkdl~MTU{HyEv7^JcSnw%BF_8=Ljaopf_+^mNv|%?s;kV&NRIfyCh(iFzT;*` z1#UeoFM`o?%{5)$u&rV2^c7CaRwDtPYqtRKioN?6djGTEeQELbYfFo6EX=vNtnl{o;yVkn?@rj(GB&cs zCZ%;kjCS(4<(j>Bm_16&?uGiXEUbFQSn>1oh%RQo9_LL_Q{$9ff|{AB-7o%C_u;=9 znDbqw+-y>Q&Gl6}VHc53E(u2lZ4B z`8*5EED${Q#q6L23!T9KZ!WlK$~@MRdiYNEi5qE$FGW|Mh%DK)DJ6gPs!esZdcrgV z{ubL-!yj~mJ{TxS#LnlQ3j8UP1peai7tfCYe=Q-F#C|Y+4ciz<0!*+;vWCC#AM(R+ zax7$lA(hHV2I?PKfUB?_)RT+?K_;@sC)Q7=@0*SN$Lot`{({+D0$0(at{$4dj8iGGCtbOh)W z0Bz|7&;{tyr3-9-{q@&nTo^wIWsEl*M-D4?ve=j_rbM`k;||LQAmKx|0<(u*$<=JeQOk1>#e zLIEz?!uWANTLa&^tl|IsOXBLm$;0wxk3QJ^u$_f22L2_-+4FeajF-o%;0cX+I&7PT+ZFRX*02Wqp8$T~j}1=&;L8v&62MR|?)``PkLSml z|MU?=J{GN9UtFSNJgC?(0SPb?P6OdTw+R*ChKdBhb7+sagL)EI5-ouFB)mQN_vj#K z508s09v&|*rU}*4Z_*OeGxAoijhnS7a)N8D?TU08pMqgtmBZIGOpM+)dQ;QTHOEH; zH;)WGKWg)(i3!(!+Hzx7>Mi$@+bc@%EaTmXB`sbRt&0moNI(21)W;=Xhx8)>z@M2MH2=vfwDAx8HyuzR zJM|et?Wk~aD+3I3C?jlrOhAKFtOhm(RzDUgc^ zEh}NKK;Am%wRC*6P7ligv_!T-~IC$U-WUDG&3wH zYG-)H(a5ahQ8_2K<(ya%R5EeK#`!+md4>ziUu=6w?zmv}OYJ&*(0Ry@qkMby8U8~XpPoDTYh3P7;IgTJ?CzEL*dFRmVPMtHIL`+qYS`1297fAy+BqKx9A;(a`QLqj$- z)YVs2RMpkgG6CJNA4c2QYX1)}2*Cc|wf_JSJ_hz1Ph74)afR6)jAeVnMZd6}(_Q0w zkMJEoCvr{r!HCr6b&>b^KWB+w;N}?U9hY0uhW~st_%9A0oIJq)VgB=VYyKk{GFe1$ zbPD_@QL$LHLJ^6E7vt91_@zIw@ZMil& z;>MWpn-k)0PfWb?bJV@%r7d2St==`QON&g-`KDDl&=TOz0W_%9 zyR-^;qeMu6MFo%m7X1H6fK~wx5&>$|4;m9L^cg}8=eq1g>p!3R=W_%Uxj4I_dqa)dwvX^;=b1;}MwnD`<*{AdlM0NDQk0TJW^!UXyq`2PV5 z%EjfS64Eumfh=xeE*iIN#;<1tdRPTS03&34Q1%N-@UfKmVVRA~2|GJbJ3t~n)#*JH;Il;Yf z@~TSPH4XM*`({Tq&51eboP1_}*7;c}m&Zh1v)g`SM(M4eV{ea*yz_JP-SN>awi&HI z$Fwe_tazcafFIhbN677TA2m7DCfH1-F0pN$vJe*mE(m>g3jv zePNkpzU$%^IS_VgGZF4F01UZQMShAhI8J1w!FJ zY!vtlHU*(#`D=@R*Dl~MIRz>JR5XAu1#8-i@htpgJ?1ndw+22F#qd#bS#MpIHKGEP zIV6NelANaGh6IQT&;w!{Ic9R{zmN<6IlDH!0PBGOQ30|4(Hasez}`esx$<%g$Tw^V z?%k{3!i9?+9K6Kx*KYs5&b*uj3Fy*wGLb(7{HzG73{E)817Ae`%b@MUIre-|RKvoR z**}i7f8oV9pMU;UUN`yDi*G*j^vjGazx?8BJZtc3yY{cV{HFE7hy$;Z`TOHf_2}_M zm(E?^d#4lp$4igFPZD=M20z1~SpMV;?2=>WlQ8UIBY3A5Ky(nO#1Vu95ERPj0HW}x zKmAEUX!tJU0*o5q9im4-8KSa(ocs(Kz<)wMut}(FUwg)bDB%+$Z28IoMScrm-sRGn^Rf8W6wUG*nOD)L6J$2+%Wi2 z0fvK(k7D*)=MneAbgZJ!qXM!rcj@`FWfar^xg0r!hhf|T>wS_F!C*Kemx5) z5>9FmL zW736rnU`HNuP?~Ev83qM+|1h(lI}QE+?!F-GBKfbLTu}VIMc*LlWnHiHqq>yW1f;KTTo$!+-K=X=-Y+ni!*8bM&yRFK}F$&M(%+Kk%QO zsb(ar89d&bp**To=pMBeuY08u_^+>3>udBAzItwlgO*7icB_bkdN_a?-f#qA)nn~r z`G@aSTXw2&W&}E*`Ogf`OzcJ^Cp`#)NOAu76Wdd-!#-E=tN{{3cVoBy7k(;PyqF!1 zA>$JLaPbDqPat0Yby^MxQVOV3>zQ$SznM3`2UfR4?7NrJbSvZNwTz>e5_X@8C_k`1 zy=qlhy1V=OAg{HM4W;Hzk$?|nh$Q?+&AB6NKoTBueHkLm(nuO7=(Qip&{4*L$0i;{=-ypvMd?^?o*?&`0lTh6tKLsQ4uQp}bm>mC) zR9$|N6C^!S0yqo)#W8bu9Jb}~bte4(tuBDI7f2+49P*r2t zw4Xi$&`qE2jq?Zi6Z6yi>v=lbv#%xEr?2xu-y*#Cym$-38>T)58NkhJxQr*CrS!m+ zIc_Wa|2SvP;^dxvMm+h{OZ^7gcn4Q3@X7zO*U-oQ`j5Z;&p)1c{3%dxy~v!>M4$35 znNPZPr_inIr%aQJWscvQxo+^oWB+5ii_xAf5!3$ z{+P|gg#v%H0GZ&w3>@GuqQEEsJ|(&UczzHX96`AH;Rf-6R6qJb2mu`dE;Yd+Tq156 zE+Fm&(!fRI8gely6J`Qk4B9`k0RI6J5^&4v6=0`MoqGFiZU3`)x_c+aCEMCef8*8m zJOzwHzNV^r#L$sLhm7jhwZ~IWJE(}Uo>*oASKM?1N@2VA&7{D zXi^OR%=E0XlCrv*x>>kGX3g2Xb2t3Q?Su0tEM!xCZ5_sca$?GySuQJAg%ioit7jlT z%$GMs$`irABLQqsdFWc=_VfOX2+$E2x!Pj?uMP^2&nmCN)$hE_-+8$|5T(kIxuWCX{4gpmg=lc8isNR(;~rt5?X*4i2F!K0G}Q< zKQUl1gx+y{QqCgp$Zy84`D|QRzZr=`7v@d$-C-A0Zx_1HF09Eu{N&8YGqYkZ%!$7| zH|e@l@(tIFTZ^{eUXXWZN%1|89WA_9YjTFkvCcHJMBDk3;>|zDm}g{Zqk3tPnvt!h zW~gadS^{wUOik7BC%k7$g0jz4wh7wLPs|U`RWXeZ%*Xk|!bc>)ml>N2HUDR(>Inat z6wrbU{gf`VI^)j?A_T|+{|$9&L#>to?EmlsDym6svCQ+s&@e-~Oaa7%54_b8&p#>< zv0H_+hIf7)*01+Uu&4mDeFo#kZ_pCJXfMOf82k)O5bC*Rk6tkQ@%%Gdp$DmX3<0Sk z25G0-a6ql4?|=%_n%C|&uWd93*0-+P-4e9>u3yzH-_mQF>Mq4LHpkQ)+FVexHYV3| z)n=FJ%hD23A-P7sB_Y9lH0*zf2kpfMHu#Sz4%@}}|9#6JlZ?bp$hp5lNU@n|%OF$| z>=*Lyu_S0L{O5<-U|(ntt0|C6f~9<9S4WNP8UqR(#lgYB7!_Re3l}b&KYt#W;PAoo&tbqB zt}s;*bA?_NcOOrJhll4Qv2VT7))t5K?9|i@0zsu0fD7pDw>otB@YD8hbXdA*IT4r< zTek5!$h@3<95N+EB}0b{BSh!ZZlB|xqO*hcagbxjjK{+R>J9Qs0sf2UhXG$1uYXg|XW>eOVa~S-f9>bouMwTDsWsw&v z4`1QIuHWLnY>WgD`I(S^-hbmBJLi~DcFQsT^J^Nj%d5olhySR6xP6G;d6@sk(_Rwo zX>IvSnGK|mz+(c80%%82Y`PwwD=46iaKB&)Bq1Tw)EVH9nv;tQh%NvF!8m*{HQ9di z=515$mwfuo%=f>U|M7@`&n9i_H7m34yz>6;J4dWJXt(9WoVe!Mi5F(aU7nM8%`y3g zbLuVUwA(IecU;r&Ey!(IQrx<@u$B4tJt|Cda?De+%q~04GYYi?%*@axH*qpV&MYfY z(=*ldY-N|BZ1LnH0m+uYentUO)XZ!h>Vtb9cY0u*mH^Fvp1La6^Yg5()WMu{^ECFE z*oW|bW_Zw#_h#yFP1wG^POHF%8Wmitmyo*q62LqU(RldxtF3#qt0&>4#y%3D`F}u9 z?2P@73Pj=y;+CXhUFP5e=D^-I|zu-=J-aUA=wg zc|vB$gG>wmaRiCwFWeTtH}o^$&n*Va&J3A zeV`3wI6{N}9Ap~_fd7UBh`-Ai2%x~%*$MKB?^=>2KrZ^*0YernTrB+W^<`gRJ9myF z4QKf98GV`O=i7xpj`s6dUlo#koJl@sxFvi&XbI2!+Pg;M`3LndUrc=p`8zMi7d3|@ z9Nv=F6rFQ)Th7tM;^qypdxwp6eCyp$+Q0o#yH`85d;Oh`9}IF>kTTz=&@-rX`m7~? z{mT=7f8x;+V7!b56@a~j@dIA5|B1$g{{(Piv;%*PVMvZik26QyK05fsEoF}@V+e*%HvDt>>)opL;{#u zZu!y`?#n&)?Ajd?ym9l!t#koc&u~LrOgxh$C2c>mz5WX1$Lz0ax*igBnlmFeUa*U~>YR3c zUgk}(@0@nWCF8DZMhlBuR_pw%)3g%z?`ckU}2@%lQlbZzPi!u zTWelWV4jv?w$C!#rJC(h%=Q_~;bXRmHBX5(+ozdlq?@P2nP;b({i@7?wPwEx^Qtnl zU%AeCSL2Li^Q=^}%XaguWb^EFvs1QtcADOJZl-xzxq0JWb4a6keT{iTjXAhhFCle$ z*}TiVb+38bA#>DWbNF8UhWGdr=D4HgZ3oOz`}Goi&>VBfyltO3Vz)VRk2&U`Iq|4D z@t8U3s5$9~IbxrA{Z4bhF7ujw=DzdEyLsoA^C?B8e(+NX_tzgqJujt**Sjy7G!w(Rt79r#$lyEljAL6P!QSE5^~;Z_c>c ziP3t}P6Pf_X=}@0JU?xWf9|iC1{h_D=UTnczZ+z zwxk`+E!`cLkn-K&k#D`zwc`h$jlz_+T{7@TkAB~dd*!u`@c)hWo!;!w<>Svr<5S|r z0qbJ+Pq1-80t}x|n=XLyvGYeCLwjQ&0On({18qicG58q;#_bQx@r^SIjGYhFNvvcn z7|#!GA6!8A|NrgZ{*B!5`J);<6bAnpOGQwC1JNK15n>-=>T?~qR#Zhk@?R3&BCb4P zKRE4iAagsoapc(WNC1;Uj2Scbe;o)w6p#QOIW;8U)Tz_GzUT-4*9UFLNX;zFFU0Kw zlL^S*zwdyZ?exX-mku8I1N;vS4dr;ojve<%&kvq|3HZeGgWDhN0R9H~cj$N4Rqbrt zxnjAehr3r~cod!=5t`iWJRC$mKAV9*4u3{|AvvSE#k;SB#2g9SdLT5mDZApr@7w<( z3h=+`FmroeU^v)jcH|Pjjaj=6FZ0{(=^Nv+Lc4(AKcSoOANV5y@(4g1{u@vGq6NRj ze5)0!Ce+$QcF{Ac_Z_><^#A>3#IRs`?f{o8;1<*EOE`lYAdexrTw z_MiOx&VWUo$87k_KDoDB=~v5l4)8fL$p6fcpi4v6UmLdZ=H%GhP8oL==G}G6x#yaB zAO4#E*{$<)Oh~|rQj>d$$#aLvyV5i_&$OV@6n)*a?x4xD%*3-@-sPsiT_)dZ)1pGt z^emHowrP5rUS?#P?2=5jaV8={XQcDq7SohClS`&4utqNdm8O-YrnzaRX^Ey;=_ZFX z)9f^pOMz*2x@lIb$tlM)J5?`pGEIw$O`&^Dn|GTw)R=-N3kVHrs8A+G~nGWJ)?_N@h7~N`LlduY#jYZ4s%?!Y&8H!qv1b^TL#00-iGmyy=raz<8c){(&FGS zkcVk)_}_;7A|mAI1^oXl%b)fO`LV9avE*ss{DdUozi?i18961Fu~b&FTiU)sbp!Q6 ze*Q(lI?0x-;gDcHd*D|d{NOJtU{Qcy&CkOH!HvUlTJztK0O{bcPmur$2oopHCBih7 zgx`$xfd8=rzx&a3-U11h=+#S4_`o~d7cN{pdi3mf-yQw#dn4ZcpyzzAc*~1dEPnoy z^RWeIJ=T>@a@fqwpE>o~{%1h~R)rQXT&gn%68w`m>OcJ2{Zl^Q}7Wi!l3Mi2QHMkbzQA_;LE;ZNr7;N*X# z3@rcqW`Au}b!v7&dU^Gs-jofpvaV?c22R2SB4fJ zJr|vIW_`rLgf(VSzcS$q^Er_ zRDd%70{blV5y<&^SZo?qU2uVI!>A1sKra3tfxqMoAz>Ii{-?h_{ePc*`RR8$yz^D( z-jhEW;ofc1=Fc25`z)yV#$(@iekZ?QbN+{QSAGn>F+A+n@J)BdZ@cS|e0M?KJ(hWy z_uMk>xn;G?w=4^?TNdTCEH7yx!r!C3#iy#pyQ(GVK+CqPE$a@o@NzB|@A8(wT`j)V zEw1@3cIhqlnJv>(Tc)SA%*<$+8sB0Y+hQB1%QMnjrbM^6X0@!T<)!T{b2D1(;#;Q2 zx7a7P%u4@%ot+6-6i52-_uFJQm)Rs6H8I{7o{0C2jv^?EsCXf$c;UgNfT$>%@j#GE zP`Qx-1UVEuf$_d?2k&@}nnaCbq9&8M3f9?yBnUs^9z8 zTh-N7!KI21JyaD^UKPB%YRSH;kkYD!d#V=hty*@lD)DO7mRnVuE2=UKiYKz!5@uFZ zZMj~RceASSUez`uv$0kAx2j4WRPFqxYWuya!rN7acdCl;cdNGDtt$AcD*r}RAqU*6 z+WDYr*Mq9vg!ilRZ&#&Ut=e?GD*0Ab(v7Nwi&fF5s$x(7XXEAnq}=#V()EAGpZizL z$;#MM|BN~DOT@vS!u2mA4?c@M`8ew6eeKR0p*iP5(hkgzF7#fwaq5&M{?mdFA5ypk z_UUM7q1bQ~-QBYC2X$Szt-_xtD=>tXIJzOgL>8#NfJ@^t z31tYN&Iofua2RuHh=3YH00aSc2~Ov>AR@&fZ4m)A`0qSo^olQ63ICb)1-z`x3|+Ep z+*p4*yUA_a^_lJ)xoPVyHuk~DpSAa!)d`2Z1JV+=URtlapxbqqwfg%jUSQ|nb?TYJ zkg*fSd&I{lPIUKb+^l_zR<R#DNZr zXZWUvC!JWha+hY1+sA*a`&#l#VwcX{Sf2_1Spup|eOeqM0D#L(E`or6kxU|Mdw@Ll zek=xVN+}G)z{3a`$L*82%j*CL0_){KKmYu*>j<~DHXYdc^Yn?+ zXzajWY%Z)`lzgpOwnPn&keP4c{O?9}7VFXWQzgGdtohG>IguqmOab#;=whyKr^ zVj6((zePj4j&{R)4V~vOEpkL~uFLX$!&Y5@|D)o+9h>xQTX zC+GfiZt*{tmRGV}+j4#7va-ssa>Xw%uUt`Hsolqp&6N=+c-yNo=A7a;U9T*7S($dP zGU`-i)XBRR-uQ{dZUT@2Q->r_#5$a$ZrT&$h}1rOHp@O8y+S zvvU59O8@PZ0r-;2pgoEY+*P^cK;@#c%D|nKi%Kg)N-KkRRtD`-QlidQW`9+wyHuHW zPVwpI6`ygTa`S~sT}9=VYn6FlRTkZ?EV^B}mAc)mEO}5_e7~~rmJ%n#^RJ?tmHF2y zw_dF*xL&#aPGyO)a_4=;m)uoyNWNUT;fiu;N!KdZpZn*!WB-i7&SUsT;^m(cE}COc zzFc?s`P%)aHTuUZc0OF1e`{&}<>dvZ7H=;1S(7_${(8^JizknsQ(RPxpHxluc4sC!xl>|iGUTzMK2qFOf!rC9SqOgrk&-!(nL?`XdKlrTh&{GzC!hhb|U7vLk`eJ3_BLZ%26I-_G z*s^7ZIv;$(cj5U`B>ZpIqC@w-PVH@bwP@L~eW%`Cdk<;Tp=alAquo4WC(lkP_W3_*DR9tjaEa{~O zkAq*<&v>ui;uE^N{OpTs-~9udKWlhO4n9rIzn_$Q7r$lKqobDTfHwfY_P-DT$FKjm zQFkq;`0&23zTLRxPHH}^{-N~b^NfOfu^YFmv%o6lUs@B`)`{>9G{vtNnUf4=-DPvyS#!#1bLwex+8M>CpH+OO!JKo&oOi=q zaMQf?hIz{s^VYA-#YS_{ZRKbFb;TF(->=O1*UY(>%v&nVTd$h8-87fnF_+vn@3>>$ z{*^iF(oY-D|Fogvr^G8iZn*ek%*mJG`=75p@I%b0XY0>AS$FiC)us1W?6|$O@ajU{ zxquCa=0@)HUYTd^& z2vDs+zzUoH&|$7CSFT|p5DWgT+1sLJhgLS7TD9)f$!_GR@vB|jv^K4}fBJC)U>>wA zmEnN;k{8Q<_MUytq`)lyjCSq%@Ol?gz|TL(KOp#>cRt{4-w*5j9gqIst&by`f9p1# zkpkU%JGSfClQDvWOMvV6XrGY$NmBwo{NNMoI@E~w?>CTUfH+{z7x*(-fX$y(Lo6SPjEv--a4WE@U@qXsG8$zI z2vV@g{No@0;2vT_;1wY>Nml!F0Fzd12+WKC?|&f(Kn*%M@yncXq(~m;}ZC^NRnd?o7+F{!{oL6&0PBm^kTm8$L4~z?x59_+rhE z+o*|b9LKJ1>ms8$y`-q5bpPSAw{IJ+U5^Z37Zn+UMA)ka z{tGW|JX838{QAqy+rHV9bt_<5iT{f22QMlXq1uFha|--Fd)s{K^4I5X-bvVTX4I?{ z*IB7)1$Qq#_<7IqXE7U!mqoCLT?vLD;XliGu=!xmLGu^2A3fjN?4ynXYUuy)pNU{y zaTy&SClKI?0DoT1koEtNABTu%{+CvSZSa$~|JI;RgBD-dcCdBo<>WnR>go}Jo1GTz z8oc!Qu+hiUCmQ|bj%>M7Hvqt!m~m?`PFDfzf5<%B8yj4AViDd&=D%Vksc zB_+P)k}3a&DetN&+hEGE_$?JCe9lEv);W{ztSRS$Desc0;HoMA%F}|YPjd}VBM&}Z zd-%K9(@)~gJc>U4?dtM}D|X&rQF3SH-mg}dU0%NZTyVxwzxcg#R&DhPPMqMi($&S+ zRpXwXm+fqys_(CzpfT&!~YLC<2jtLgdZ-$M_HA*REYhXBlYk@GEcYH*VgdJ^yOk zp-01ptx@WdG4q5m^4Oc=6i7oTyNw{VNIYnV-I zHY;d_M;3hiQT@MtShsnTK0W%5>e6#C{Ko_&{3m2BQ1^b5$GESLOfz`Sb=0UjQ=SAV)kdv z=hP|Qap1MEBrqVjWeXc;Cl^omX`UX_rcd)8d0PjD)X%)zsG+XKMoEc1<)#avIu47dC zuGnS#acdl_(wsB6LafZ(5mu>vA#JFa!aov7n_+BL*l&=&t zcZ+eh&gh+C^xkar&NTXLG0w{|&dWCX7a0BXjXqgM-&~_#p3yhk=u14u7`)vWdBC{o zm@#3$F}7Us>-CC{->3Ku{OhnW`Is^7lriJ9G4-S|^_UXLx?s#aXG}k7OgpZ4A{nQY zNa_(|%3)*5(R&#u@8z7kx9P~eWhHmRitmP%-2QU+t(B!W*66RU+;b^3|9oJ^$@$5L z79{Qoh%cD4GHtTox^a^hk93;p)N6E1cnpx|(Wv}K^F-YO{zw5FN-0lJxGjbbx+EP6 z9T?o<=z5|jLrc-d>AC7d=egGw9}4;{j!cCAbWfbM+7H8Vz@Gs=a7MMJ6qV0Jg!V!S z1^wrgJ@yHK12!K~=>_lBz$XsvYp1|!sk{`S@?RoyfrtQ+0&?NCM*-X=>cdqa0z~Z> z2`G0%l>&$W)dZwUULFAs*cRgH_cw$5Dbp`_P9}oYXN3VkaQEBH>x8I9MIqnmZHP&O@P?x1nBbGQi zFS8#!sZ+OsU3)p8_CtQ`KV;5AAp4%e!n4Q5*YeO8 zLmbOL@RzrJ+1Tgs!6O*_j~qIJKSl>Sa*Pcnc5L5Swx>KYA`)3S%Qq0k8{8uQ0z_VG{6P@>9{*|o((DOo^E^$)bYLIR%zM6=_z<1Md6AIWpAX-z zQ}=zWlWp6!AJ}E!q<-TU_VJ49HGA`b1=}1#%ZG#=8T#ePVJpu%uf8yR&BYPn1{c+@ zHH>`aN3AosCm3d@8x~|60x}IgX$C)w_fI$YXBYyr4Ix_%iwX^)+YC#$8^RA75-u24 z=?#nX4Iz1kuwsLDmlB_wX_%I7n3iUkl4S7SYzQkdEXgq}$}xoI8MGya726G=TMP>_ z4Kq><(^Cx7k_=Nf7`!ZgdXiygs$oWwVOFYPUZxVxOft+#Gt5pi%;H~(2JciuV4fj- zw;_7BVQsM?yvX9W8N#<2)^1mPWQieamm#jy5U)3E*k@Q@W{BIXM3N2~HXSg;ml+Z) zenXi7pHOOu-ED~F_+1x6^DYK&xv((zd~nXWz|E%vH=hX3JQ9+1U}0wIf~4X(k-1YB zr+WCtOqvlke!Q>CVE5s@M@Fn%OOFFP0)Jr<@W(-Z`XCNPl<5F4{)*YMs<)c|z#k;4 z{D*!xIE-Q}LSN-Svcp<@AVEZkh|NU!kHJSA*cb8>V*G*s@EH_K{ubE(CZI%dq>`bE zcNO&#AynPt$B&6~BoRun&Q40HAqZ3vz$N2;PXus{ke~k|_2k+KRsKtNU?5;E0%Qt6 zq%g*RATRcxfdgLY|JBOB9m;>FZUgKc=J_rz%qe4&pXYGCu& z)@_)8;pKA0GJl8h2aIFzhv&TND_a2Z6QRHq05iO3 z{_r2OKMtD@tfpN7ZN>`>91tHM9lH%pj{A>g7&RV~4sbwBU@OLGzz_q)9+I%^hX%ua zL$^nNz(&N0hy$v@>;rEfU`OI$_)ifiocs&supEek$!Fd?pErCaQltR_;HWT_Zl(EqXj1h3v#a^TtV%RgNH<|nK@2!azgUZxj5 zEYv@iwV*24|6oMrKlU8#Kdv)UCi4 z)jKcOk6)vo9;=@nub&m8pAn^>5v`wzkI{R_>E~_I`z7lG()A0{^&wmItIPB&cIX2$ z^nQu@1*!UwEPY_QepZ6sJx1>ltM^aRFU(NG9+4Iwp`Q|?_lnbdM(8~w^;2W?QzG@AYxN#$^ zBI#;K1jiVG`9Z0+WJvt?M1WkcDgw9pdY{6@Jbg97*QQ_1$=UO*Qw-YP%w zZ2#HE=k7i`Q1Jtw@nS{jA7sAuVZ#4YSCmaV_uZ8F-}}3dKIJU{ZES|FxcvO>JEGyk zb3BI;qWrVBo3a+@fwC6V8vAOTbankFmZEC=e~I#;K%S{M;@l|s&zwGLKf^sj93p_J z8FYsC-g>{zJD+^=QPcX3x-{+J*tVZXTPHtT*U+vL!+TDN>oa3hU+Fzh5q^d!K6BQpOpj%m9-*7v7p1u`OmSbBIB8+L`~0Z!bJvWS7Unu3aKy;j&O;_S z^>NX395B{lRCH7{{Xz__s839p@o1Pt1OB4?!+%mBKT9ca{EHq0&FDcm`k+{T1pbg& zj3DS(&|;UZ*~I0cCl_!G)X z4{P8cU*-Qe&sYcNDFI8wNMC{c#laY%ew+^ndhl+7-)tP&~LT+znK8nj9D>5nS^iP(^UqYG|2k^6>QOQ#3}b#N1Ux zB#8(Pn9qs44u&}hfFK%BBQYXTIs!-*9U(+Gn5?+r7=q&C<0+aE2TMk2oNwkoixc$b#=Da)3wOioN=B7jw(n1c#(3mNOpnl+1|%Cc1vV*H6t$z^l? z(Ad2$F7uL;l6e{V@uMf189Cmwe5OndPRhNNz2lL>|JSbkB++6TdaZ#7{-3{V-hbxK z!3&qq-oBf2_;yPE{k)P3YvMPj7wtj4zxE3ILVlV+M|BKx!48s|)m#k9cx1#Gm!ShNY<%a>@4o-nzkO7v!Kd}we%`EitIp0H`%bVO zG}G46*VZ|x^T@?rM=$H{wxau3ExyM%iznjttM55ht9Um{_$t!hUF+nf9XV4wa)#Dr zns$Vj)&)OJJ94^qjJI~|9PRjd+6jJI&p@sBa_x*z?Lw!^SQcI?Bgs z_)Nzko|?X+`*$AN+ooT?wtc2eoI+pVDbQu;M|49R<7h+xeTtqamVbJp%75TbUxWYj zKA0xZtHFQ4vd|d#!(rko{A-Y3l^|qA-{E)xugY7ANS^e1n1E1VI3SXO*;R}@2oBP5 zoGTGRR^8NqypSK%6H$o&L}9)}01Gn(lrE=BL@q(<^Lruy)Z=6nAp9o>YRIq!_!B{< zaE)^Lst7>&mr+1%5dfp;8aUDa;XnI7@P$WK{xbxy@Sm@a^asuzJNN59$h&I~=NY~c zD`F3z*bjCLY2C8h$T2~&nb)=-{hpa$bs{}&CK0slAizg^o7Sa>k?W0^-qM;5T`hZG!2I2>kr z7spgD%0E&7D>wZeAaKdFH;gl=@o4o#pfvXi6V1Q=^)Eu~Kj;j|eH@@*aLU7_tzr?v zQUo_>qL}oVYi8U*p^%@K&M+gxeb_xJOUOWf)>Wuv2K zJRu^Wul+b?ey2~H3;g+jBYOw&J{P7Qw0$-XB1D1^G8Twh7o`o4S{@$FXlPwRk{Ey1 zCFLv*-{`qSXKUvax_HUeD_3{z*v$%}`Tjxiaq*+Z1Q+NZqt(CO{{OA{^4C9J`uZo? zDTrAEyn3WeBJ4kXi=97N&zV`Q4~tH>R{O2>d9-~b0%jkuf91i$KgfT!iQ`00VZ5;O z@EIO7w;IRe7RUW(peF(y`#(<>xy%DaTlnk$dFQ>i>(qJo(~m!DQvdVz&06+s-9gj7 z%dk#8Ms?~nu4Au>?R$H+?>nVKzo{Mjdnvx3mu-K=6Y1F3;`>xbZ2NlQJM~k%66x>N zZJ<{_2QQ72m&Va+;1I8Y4i-PeYmk%I5N9u^5njVwyqrgRjT+}Q-rdV}tk=-tUXIR6 z;_#7P&X#b5>#I0Nj_`7F_HuOcavJ6}e1z8sQk=aUoV@xwc=fjUUK+1n0~Oy}IkQ-S_Nlw?ds*~;x%%F*T~_PaDTP+r)q{w)(rL>FmU340pt4j9^JdEb5CZ{+w||& zyhpdDoktCESroE}!58Z#1pX*p*6=HZ+XJ(} z2nE0klj-%$)glvV38)_c0W}^oAorh^hH{Ah&wb;LAr={p(l|MbHVG@R^JD6P=fEF9 zgVBkyFfqY=#u|tKUMQekMjsr8oqgVFAC4S43jZ?+xP^Q&9z|DTeSGSzchTwHu`*ak;We7yJ>f!T3s7dIsr zF>uJr$VOg(dVnv?M~+|uVsFp6b9^wJMQ=)r*_4L)D=smOnO}@Qp=&oyS(rG?bA4ZX zw`NV6wQJMCrd3-$7KvHOVX#N^rW5Q10m;R%1KS1i%nsmh-G9WF`*;}f5bZX$>Pgfiwhr1oF_&tH@wz+e9M;d^yI{ix9w^;2dO+(|16#JzD89AgTd7_Wt-@BVG}gX#YfalW8oTzI zZXGqD5v3eQcGV{W#rL)1!l?OM6YHb{boJTTRC{)t(gbRG@Qvr5bka6tBcz{fiTO z+G^}OYcyRn1MM{SoqqKLI%&j{KB%*1a2Jh3SIv;F8ck!bUhL*c6aLKh!o-tl_WD9azKPn*7$e33vs<tH$!0*_(f2-EE>arghTvYR)6`}3A zHfyeY8ld49$`IhqQvhvj+QE6Tx?pu@%rp5AKlz)&8_JKJHKT0Fz0)He9#wF$& z7-F#35QQRch~PMY=?M;ICkmE~k~ty(5lkaT==l5B{7j^3{D1lKWnS*qrAxxF|L@qo z>!`&9ga}|Spxrz6VENBT%a}fOhGzJJ;a;1B{F;feQ~k4|k}l?#Jv(>zr`Uw#F|KS7 zw3gkQ#V=mC%+Du~MEkzV)^{}+2vMyd|O*!bB= zG07(mUVJVx;`|-+p>uZt`?mcj7;6-iAE~{b2YL(qWiZ0QkRO=i)fr)Rn4m`FERJMr zAmTC?fc_6FEZ|pKIF3e+F`2O&&48zG8GG-)#rv^4%8!DcNlK7dDDBiY#l4$#R zweR?u4UENej3g2vtJd{wTDaRX;Z&-n|k<`Z9Z+$`tQwJe$=>Y3tMN6+Uu4!l63$v2E_AASNR4b73MnJo+)BzFjM@&E++INDn%=xmy z6DzJV`Krlr3B|DczJ9t!U5;4eER#y7V^-E1oh5tPV z`#DZY6#fr(kDC>o7ngpyXy3Clx6Ou!&o4jvIVK^wMYC3Rw%zc}o3)DGkdc*J$Q@&> zv?@A&Yw6*H)Xm7dyy9K(pKr2b{Fyj^qj#WA8(A8gawemQw{&l2@3_1B@VEQVKNa#T zYX5h?@OiJS9gkwt4Rb>a=P!(&K5Z8B)aTBg!(KFRc7T2V!HDKQeI_R5R$vZd^B?`G z7YEMXEz}>&*>!;Tv# z1K`gTJPwVNX&od!^S_MU{`{vuzx}7T5drW1`JFm%z4y1j)cN?YAN~EWAJu*5lX~xb z`q{g6@t?n2Pke)S>os_(_g?e%=2U&+&Lp{Nla(jV->>d-YY{={7 z{rb({uix^6`Zjgyx2{va#Rp1?B$AGA@yg3j!ls<~-mk}SFj+OURFZTsW-J?4D~PuCMi2jnM-483vkU(x@?@=w>3XGFU}hNWMZxMlcDfdbZ-gC3R6!F&0my%YyPX)e=YNc|B#;uA^JJUCugck z#8PD?;1c*rSeyS`3)Pd_aynIFRDuW)2mHm=7y_swK(YQ<>_3DgazhY*T&zXZC`L0W z(QWJ`;Xh%MCN|i1(EnBa9QzL&_^@tgW?v+G=EVY6);a_OYsm31V&wHyK3pUo?MG5DMt+ zva^K1A0rQiVt2yk5A9(-Yf2$J5yTB^jbJ`@CvhYaA!LS{g3y1c0}h#s@XgA~=7l6x z1o&81{@=K9^Vzd!3F|jt|H;zjVD@?Z=rP#;_rL%Bpa1;l`n4P5##r?KX)}7g;=iK& z2V}2HypXr&37htSXy#j?^o9G+Pu+ZU`qpFoshf{4fAcbSQwsH8uw*%}S;2oafBI=P z|5I|u&EGiHKRYV9g3t9ToBupgwtZ7S^`&I{>UDta2cBk?d{cVjd1}E`&lzFtR^8U7 zT{~Xk=xN`rOW&YCrm*+Aj`B;&Gv=2)DL?h1{N(e!N3Uh?+;7>*LD|@+HvBR8%O1`M z0{#p0MgJGWj`i`@anb*O-5}Ir|0y|mN_2i9KN269i2hGYK=|UY@)08UnZc38V+ue8;$lpd`XuB=W3jW3(%*i#%(#3TH1t9HUDKNu(L@UvaYV49$dbA~~R(Fd@aT zi>xR@S}e_Jxbtv4r4wg_$T5`8Ddb7hB~)gxTD2lV{^%PxB9cxWXnr`3XA4tuptj^s zS!76VIDWFkiz2ujD#PjIhPuMJm?(*(z%WoHLoSV4AqqL2vv4$T?f}{pRU&^UN2g&! zhdB>(b{yh}GDGMxVgyrfvR;l=WDKIgK7tiJhjA9#J|k!dPmcrdjCsL(QBjd<)t4ti zI{(EX9fbcJQ-lAa`NMyDB^nxz?gJ84T!SxxClrON^kp<;A~0WtKgvJwr-Mr<@E4-0 zS&^YA-oiuTxkoBzxLkDt0WF6&0|ab>l?s`jf9;s4>Q3jYJcN~X?U*3Pb<%Y?(M>D2vW00X4(=V9zrJeJRu$YE;hl{32 z6G}-*p?xweWeyh;Jxr#NFtbn7#lnxakJ17$kQ%gS;LrXKqWshB>1Ff?>4WrfdJx(^ znm^(O$6N!nr(C1}rYE)=A|#O%dK2Wq9E8D{LJ=`khLsLA_>b|Qb*GajPYquc5i~y} zIB?0@HBk|3W7v~(@2*mo@vL4M;pE_)mXbDY>Wn@P^F{x+R{l@l{0Z_`8{REafS>s5 z-~E!9p6TruIC<8*IsQS|Sm1x`rsSlIER=0U|4+#s3@^Bb}$j1!{{oW`CtC`Fij1@5@jB zP>A2Hgy#(}miiz9h%+gGGLPENd;xWnjX+aU-(}G{?^JrlN0F7(s!pVnoDHq2*Aui=omfSar@bH|T zoRa1>eYUFqvkr$L0Q|SM|Ddd}F#Ff!|CN_Z*6f-(C*8$uZkvw1hPj1| zB+{WLulgz$q>eoi1ghGvMil!`+pc`l5dEKz_wovWHUIe-fmo%8$P{pk=B-d^P{d#VY&=W7jb}=$bb>Yzi8fA!)S!G zXX5k)`pb|ZLu7eBW#Lc-$ri1i;xPNef4(U|Szw>i`Jezl83iDNr~^`fbVLBv<0qOJ zsu5j-29JCJ5h4Oq<3Ic#KHOzse}|ZLaao&lu&C_U??15bz`^|o_m%J4r{ABOoyQi? z_QL{Xu_j?NW|sW2BcWfe+L*T4n*US%vSLyy z3d)|I`s!CXB3WU{XD9!ihZXpv{2#JR2OwD#^Umq#8ATOSyu+M_jdOCIJA z{+}xLAwP}>$_?jni{&5cB91Ww!hf(V5MzW0$IuF7j39CO7l|AORB1Lq6%6v=Kq5{e zB+__D=Kz+}@?>dj&>ljP8!9oz5a#`<0N5mCbjdU{*%INh!KNzXtQs@Zmn8>eQdCCr4eUhC*PK!&Fig1acLkmUCTH zK={w9P7y;W|G&q75do?RNG3NqkxM`p2>iJ%YPpo9@*mBAQ(`hwMs@)bDIgrSUjHNf z@7mkZcX2u^d}>(!t?fVP|4SqGjG7RI&A+`}-(hZxM~<1>&bGJc|H|ZVE&eP2>eL&# zgZ|HZXEpSH%t3qzo)8hB^1oTrmY^PM3{YjvEBZgw1-Yo@SYtqRojP?$;V=XQBXL!^ zLJgyr(WKE;XlC?E8ZfP$cEy;K(J0b^9zlPkckqfaMKCBv+#p%tKSK;63_1wqEd$Cz z)hCWnU}sTEXNb)J1i8R4fsnBPwPN^yo(;Gv_wHR7+xO~h+l6I08fOLmPE!&v{{Nox|6Bh5yzkJ_b@3a~^CLE8;fa9O zh`59eDH+!Muh#!x$A3lvXW8;`|I_5W2SxiV3qh+_c>Y}RwfXwv?{{Ck6&SYNeOjoi zi@WQHiNPT;yN^9%&!5AFDVQ8v2!5r8DvE)>IO;FXazWJ-0n`E8K6QZqDE~NX z5r7Hk_pCr-2m=0y0O3D(LoJkoxMNZf_i&QOw1k9B@PCqrm-P?;5rD0Rz4}qnvDNS* zF#11{F&<&jn=e_f`B&xw*!<11{|{5Z*#DQV-K*IA2afC5)xOW585&1V_WU8A8gss? z@-L!+kAhJF_%HT;S02H3cDPV7Txf z+Cz0I1^$D5RDJ4$s*l{EK1d2GgNz^%@kEt4fYPzDau(u)E{5?lC}^?IE8{=SsY~as z@-fF=J^S+}Z{YmJn>Hk~jYEzucdF-%7R_x2jtCLU&mU3#5d_5X4knVdL(i97 zc%S#Rf}=)O{3H{ZGT`N}ZN()D^eqnZ<52z)>p%%S!dut~c)=qL0D=*RY-qVW4pFvI zgXI7y&0!ov+Ym#F1(4MNxF#lgH6en46UhXgizwklia<}MMG*&~IJ9LFsRQWdELs|8 zp=rQja-ah6R^$j(0^QV&L=Hoy@RR)cFDaZ$gsiwCkPDM3SCnurlfx*HayfvS%LS4% z`G9><{?TouT%-Vk42M9G%sG<$DTNbBk)ovzq)-sqa*apEh=}l?;T8Os z|AAP$0$WtPW3$~O$ zS-7%n$gnAV`3tb~@kcTEzk&Z^{87FL*`a&$7VSQ^y#Fif|LfQN0!gF{3YxdIObs`c zAwc6s%^)of>pDgr)Neu{kG>7_0Wypw5mlTBMtkP7m>pmg0P5jC3J+sdvH(5&Vtl{{D=T%98m0`I^+lP@&!rCLd1Y~5}`WMf#QHa@&fD= z$NEIAs2e{ylHma7ay%WJPC+-BKcAi+_Wb#C1Wog1E!fEi`1{PAzjTQfpOToqH77qe zE04|m`#7-d$MVkCA5;EW2vktKOHqb*m)GF`ny9$kq7p1Er1SFclC_)M0yYM%)^FSY zec7q!toB#=kMRdP56XYa)(1H|zddrv@@P5C4fEl7Rn?!>3<+Zf*Fh{O4NO{JChGVnz@L z`Nc7&gHBKvKml{KRw9HvYoH2>fg7NsRq)(#pcn`DNC$=xl_UADFkeCu18^I166bhw zASMc^n7+EcESA_fz(68_W1Xmt=6{EGOH97GaPC`hKirbK>nyzm)NbESZqayb&kM(jWI0z?3gM$Q$HPDr-oDVa0e;PR;z7saJf zCGHH;ipo$ZnNtcS!hh6$^5-YlC@J(KrqUQ+<5=^6J&Lu~G8{k_&>%&zhyUvvGBjW@Spu3 zKz)PHn=m6xO{%Aco3~{MKsx*fq2LtK!c}yB91AB@IcFZu=D6MHGg47n%e z|M1;*f1jYx#VbOBm)ZB#*tBfZrd7MaBbf88w*08d|JJ=vPF(+ux~_7Y$dVPS8O1Ql zC@$Rx=Xv)E`wvSoSu+!}F*!w-OPq9g%jR#cKJh^-OEZeT%`bgoz10tPem(?%@{i>o zXsL~c+Z!(sP5SO zne$~982DrP!6Oa??5_oWjYKkeW&Gb;Sfp6{RmU^Mp@^cOLP!88qW~I!802}}a23|U zH{b^PR0sN0MB$rHCTqB8`!oA{Ogd$eBtK`h}$^~-O%mQQl z2lxy|7zOZCMkOSw;(!K8?^D4p{D=AI{~`h~-NSjLgL)WodJ5^Hv3|LaUdPGQ#wL{ zDxvoG?b{bAz=(t8g*brExkv%dMe##ZqC`lArj(kxnMM8-+M;<&R#XmibV2{0IBp6% zIYWNF=R!DeM6lzOBw6$C;IUrT{1@u0m+M$#|5f~F|DZ)&J1<8U?AQb6BNMaXKa;;@ zrwp62w?$g!0w68_ib>n*7O-iWe~z*QsO%|9{;N!s6+}m`zCihh|Hy@FPyWICy!+27 z1JsM(KR(h=4nB0zl$| zL_&_?C)zR&&7Y7*Nyu3YB*_y;=Af7%1`b?P3eTF5g21xCpR+(Nj!Y;8hX6v~7VJZQ zPNc%*NklCFB#NV*ATOv4>69g74MG|=QUKZ$p)AG%5SWl-NTf3Gp9`c(qxRrv(uC9j zaUk;ogd!TK6|#VfBEltef&2?$A;Jqm$)JWfQhOZvifZ^SG4QkiU zu4RjM&6~C5BQK2`wP@6^`4^uzVb6yqja#&7+oelSO^-f~-Fi86?KK#0+l7HZUsA}S zM_t^4rw*!&3?Yq~l*MP-84KesPY~H>@*KWNuojUjF)J5^U zo`!ru|A+sgMMGM^3vw9?Fa#h(Gnc7YLa>Z}j`;=E9s55^-RK20C+q{XG43ASA8mwt z#bA@RN++UWqf_B%{PZ%~KMvK19z;`jad9CZOiAeWm~>(a%_T zs1kz|micWh-o={F)cjqm*QX_H&fj(POv%BMIXm~~?LD~n___SjL+r^gKPqqL{H%?e z4J8Mjp1AVz>LWA$+GF!Y)v9lL$-;w{4A`z-V9Wsje y1Wf7fqi4y%`rL|p_YC;EcWZn8b@2}G7c20O->{L}h*;;D!hCV0fTKVC>Hh-212oD2 literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/fba.ico b/src/burner/win32/resource/fba.ico new file mode 100644 index 0000000000000000000000000000000000000000..290321e95e5adf396e1c7ea5a1ca5bfea542d210 GIT binary patch literal 132942 zcmcG$XINCr(gs>&6cj`S6^SB==L{+Wq5>i! z5+w&Er(u|xyKwLGoxRUK_xqmvrxH)m=>hAOcFbZ~=aoxrYG)0DzVC zPn!~ep9X-I_7B^f4B#sR0ziZaSm8nrfEW`18vTcTj*?V7TTET$jv1__{f8 zia3JE4Ofsme+y)UWI*PIDyUu701FW{a1vDq31K_9A!PwqWZdEQO+~mZc?Z;G)xcO$ z4`gM{KugIKZr-s1Efph>ly-)Dx9vbl+XXZ=fHL+8H7}0 zLDV1-nC@l*vrYqWY8Qi$Rt~V~R0HRO2Doh805Up$psyYV(i%yiWatZO=8r+o{s~B% z$AGcr6R>c20xr%^!Q3qYWGr(*(X9aP*yVt>M+Rtk7lDLrCCE8f0f+eq5VUB6^VWU9 z=`ai;&fnmi>kM4>oQ3n=7`Wnt1Gz_SAn)-799-JK!eao$J?B8na}uPyH{qW57Fc;t zgRe&b#P~!)fOjMKd3J-z;{?z|7l2uC9yp-W!7HH%j6-X{Dyjh-`8t&-y_p^fTNK9|5(9K`;pI0K1@0Fnitx&WWvHlJEtL zV#mNBWf&Y%dciGb4BTIKfhB z(28FM*(bZ8{&*K;W3XTlI0=SPKfo$_94wM2z}z1LuKqi4`y~$4GqGTqHv>)uQ(#^C z3*5?Q!MI=>9Ew)KqHGUbs&~P&bq^9^;^BEhJ_N+qL0V!C0AhNIZ+0&{FX{o`su4)2?t=`ZuBrJ0lC!j2B4yvQ(;N>&Kj@*W-7hCY8ZU&+nXTYy<7e2jMgwOH6;9cAX^e1k> z(93mLt6hZY%r#hlwF+CMtB}|>1QjhG;nmwAC~N%;nZ0B1taS?F+h-u?-5xyuum|yd zILP=g355f5Q1X2N(z`K`{cR6QMpxn04;)lZmh`(RboVe{YR_b2*+F=I578e#y_Dn9dIlM)1MGwtqqV{gQ^^=0iKT{F0%e@1=cxzwyB#p+SEK z{lz*&!KP|u=U&qHWBSWbJ`y^=KM(29Ul4!4JVbg@?w+Mb-{kb{#Kb;6q%XfD?|+F; zM0$cvx%J)H?9}u=G9)B#s3he79S?_yNGRDgy}!=PObnKM>CX!;>B}$3_nsD;dgj2+0fm-|-+oLe1~|t*->>O&&6wp*iVJe~1u?7oz>oaA{ox5s54X6Z@ptz>EK*iA*V4R_egvQAW+KGG_z%S2D~MU| z+6FuH^@Rk7l!R+s;Ntqb`yUqRK0a@-FE2Q_@6|uN|EwVUjSoRSt^CrL;3@gIIk~H| zE4iz?yZb|DXGhO}G7fMc@sW`X4b98Tf~$O{iD^~CRTZ_vODomG!)d+$iQkVO8WK`a zP!?Jc4>yF2QuD&i6!TY7uHXse` zY$3AxU-3wPka<>CR$f1h^xrR~s=i@mYX^f+Hdp^^|LuZ9`a{dh>&lDa`W4fZs_NS6 z<;|V#&F#(2rGNB?Z2x}yOY_Rg%j=Q;2%=-VQYtG_KmMBgxi&ZVe*Qnl=QrNLVgC+l zQsL4$9lxhf{h#~C1O&cD6sA$aFLptllwgPA99|D=e*ZH@#>%R`^F#H**r6Q{GZPMVw16}+SomE zalCt9S?Jn-@&9KPF{{c$D@#=^d0r+N#5eyoF?DWkB&~AzW7@}$b94U~AL5hB_wOt5 zpV8kB)X{}Z%gwE=ovoFImDS}<%m(&9`(wY)KsboKveu1Ee->rO z9ArT1e-A|c?*@=ttzTYU-T!D2JTe&&K^VhbXh8Pudf_>_HKPb(8F^vU)ggCWSGUjK z{5=s`BKo<*3r?`MV?e09c>Lnv^BJKrF5hW3=E`1MXsFN&t4Eb5joXisy~E= zmiE}O+-xt&$rOa;!V#|oj$Ta?e1|YNm z_z-^L{y&%FfAV(zERmV`I}Wm?`aenv!hU-MKr*%eU(0{B^RE)gM1QyU=#P>Jx$}J+ zss3FG|5+l{f8hQok^B2?xBOY|7eqgCzpIgQ{7)ObUy}U%ja1IM}U!%0pRICbtmF!1UDJG&GJvPprchyt*4tHb5%svve*7w9kB0MBJJ5V~## zx30*;Z4p(tD`o^&WvoG1(GldNVxSrU7Wn z8^A49E4Z(11q%0^;DL-GINdS=EdwjCGH^z6N+0lX^#Ug4RN$5ihs!d4fYNyeLP}9^ z`CbCBXcPmxb{QzB#ekAVENGddLDMlDq)lT%(JC2KAI5;Xa|+nlg@BpU3o!9W011Oa zkhLlTN$XmWajXI<$9j0+nGQ@3I)K%<9nP7(0|AS6IAhWQTo#?cji~U$4&bo<0{l)R zaLN7)+;I8|Jdfsp+iMGMS+#+jdk469d;kd~XVman0c)QL2(}>OMnXc1w80Y;Pu79CI2nB9JmF7emJ=P7zbB_aUc?k1<~g?P(pXYy`cA? z|NK4N^7{;m0pCC?svpc^yTBp&4S1)#2FKJ7@E~>o9Fo3(%ggs*o;3!J8U5gv_Zd8j zkvuVQ8stN!KsIO&8ULZU*jw+T$(I z^j(L0{#ejK@<_GdJA-Q7cJUj}U0=I}6Fn_!bhDgq7 z^#lV(NE}bZ_VC{Yhu~fC2*H4E#u}(*;6Nvj0H!aIJT!X(tnwznIAakU3a7!fY!OTg zHj%s&3y$UMNG`eoo^_kxT!{sbYNW0f2ks3x@O+JffG0sn{)lK$7(5G&gqUY>5Fecg z0de_|nv@HVlS<%eS~0|=mq2Ood&mwNfz0SZc#_)%L1mo~QPBZU3cf&4X+QW^BDrZr zA0#*RKy<}-NNgN|obpb{Y3zplrUCGKx(F{qmmuWXHuweaKt#X}B!urkV#E%lKf^$J z)HXbAT7aacaqw%x!k73ZcoVk?UlKN8vw8`Za@U}+^*c0v_y*yvGm!XZ8Uk83Ah>M< z{9ofC_#GZXJMj?pVFQx7wjk;w9^yaZ;CbIBMD<`H@iPuyc1%L)rzv>ZI}O$SQ;^xe z1x2HqkkOBa%A~h!R@NqecOn)sgNRz%*u;2-rFrVh2;+bFiAZU$ zzaITDmXcv*`7O%yAAVpVIdc8Y_}KR^sg_ZpPyXo#pgf`dH8RA?+~)aH$N%Q9rO_OV zurfEd^^+I-Z~p2-N?{@W=9WQn^mPB-uc(naU}Kr|-<(KY%`s&Sn_W~0=WgXzuI=q&F>CXG<y)gBhPcUMO6B(ndQ{J60(GqXN3vo-Z^ zNFDW6q02mo-SPhCuWc-Ld2wY8hyS;~mg1x&z(?4-GKskyBi; zx>Pm4xVwh{5cvxq+T8O?iWVvtcQNw|iNGr$|4vloiqcYoEfxE&?~M%Yqn6 z8|0DmYat0e5SP{ishbbrmeK=IzViTXtJ#9eT?0^6djR+En}Me415i=71vNE0xT|Ro zn!4^_Zs80@CO*J+KL@U8W`NASr=Y2a25q%)&@=P{U6UZ>?ARAv9fQEtJs3o+yMfDb z47i=f;G*Lw+;o2f`p&&z^r!>Wy_Ue&Ee!m75&=*N$OdB_NIUONh&g?-?VHws=w-{EHPIw*#3fdaDLiiaa- zugLnUf}9WEf4T=+Ay{yKwhR_eSKwjLF4!Zgnu!OE96VU(jw8ANcKJWRId2@CU(JDa z;W|7l$AfFt3OH2Zz^QH*Tkt{d0Pe5@*dec=2xJW?Q3B}J23WB`=Be8e zAOv3oLb3`FitT~W8VQ8Yr9hbO{hxJG0GYXWND)3c!asoU4U0(3_bV7Qb3i@pEmQzHER5jc+U84*4k z!skTzya-?H2mv%M62M-C0HO9stVjYhmlFPZp3Zz$N>7r9@BHu268U!YIH#5V1r+bU zY#=&mX&^2Bm(w8<-5Ub@Xa2_z2iavVT;ck+P0Mys^x-KHLnBkI-<1d1F3Gu_P!96+ z{9^|}!zLm7gzlD^e}Kbp{}Fbv>lUQP7#W%NUt0i2SUBj_!Pef+{&@h+3@8#+d@+|BzVxu1@-EnqN^>FbB3G)R_MU{KEUG92%2YWyAa1SRFysThy zQ~0W|v9*o15H}E$lT#d^rlO*xq&iG}8hL-R{GlsIx$`eYg6`*w|D$aGz8>Fi5Yd0V zaf9yMmOFIt6f$Gsko-;QyMH*4H!d=lLB}B%*>YuX%S%h#fAsxlqeX;Or!%w5!^Nh4 z-4R{Y#%7bz8`R_{tT@i{Pn_=zracg4dWTa<2N! z;0fP7TBY|FYM$OqU}QZyal01|putRd+~C4`%xHaneOW;=Et*3$)_6hWGn;F#K6^@w*K5!=xu(d@ppL?T^2k5w;{yPrPO+k9?Niqd zFP88Uc88?KCYMo%*F0k}g|?(S_}%UC^DWz<%S6KmJyWF5c`l|^)yh}fqGXmm#;_?j z*(eXT2u~wISsuH}2x?Ypf*llrNQ5r+ia;Il6P!?XK30 zGSHl44Uk!BrSYB%I^wHH6cOnpy?c^vLitvbdtcH22v)jM}4P88gZ9J344r;yov|Jb2s%nXwIqU&zZ>M?K92Tz4^zj zaJ$3_r z_NO~H$_iF8r5c)Pek`{)&tF@bo=i&Y zj&!Ecvo#*k4rt zvvHH79bWW@weqZEF~dcT@exvoi7|uzN>OB~Fi#Din<#;o6K2l-S&=O!jyX zt$Sd&{@z1trtsl`F+EjNhkNl|>DIBe0bR_AmZOec$rDO^w0lBM&8()hb@Bts?j!!+ zDt0M8iXA79-lW@f7!XL+vj11>f!#9Lbd#yj; z&W;<&rpLD95^`RDzO)&3IJakvsWeq0-RD}xr?D944;-^5915*4(w>0 zKGS_h|5oj7Z+=x%)sPtJsKgNsT!72Mp2zc@#Res2LAv$)>0)hS=6nh-_oT+u*D?jl zf|#S_!^LqX^&e66Lqww}Qm-(7&lL{^-A#w&P=*rP4X^dEX^)fF1ghq-S0}J{yA8z- zG)<)3;NK9XOpDOY932ihLEXKq$(r)z+pn475MAuhF^&GW_GD>9y(jaC+^q~kI?$5caf6zh2#m;AN2 zs!iCMBbXRERAZyplbv%t>=kie^TYxOyDhu+vmdXSPB~xsDV}2Z)7!GxBY&BMaAmO^ zr!mS^tDlqS?Abl#m2^xvrnpwnh&RyTRba0VHP1zXm%A!e*w(SW6v0)$_*!D!q)k68 zW|liOxmV^o(}#5*AH^T8@(0PZshdvNwKy*Kyk%r1Zb@vi!+n=Acm*xnu@cSNjHWDu z-_@@Q1>F8nNMtv=vpRwve)!#(vDJTH+wm*pmlOTHk5e&erd#dyOAQml4lJX#*e@Cvgvg(6Tu^r% zS`ndY7<=bA$kg3(EnqmNQfyIUPi;8lamY*hu67yQBIzzc)5|QMI=iUx%s(j%u-<0= zR~bSooQJc94LohzSk<#$eD+?ztSvL09q0X)Gio43Pg)~(xG0M-V=G8AXM&&pJ!ep-}ZVaqC@VZ|y>*tLZsjTb~3r?=WQ;Q(%v;p8)mLK!S};YlJeVmgYEHtS@wuI&IbM?C+MJg zlY$lIQm1X$=|LVZl&~{h$$?6*xszkFxbk_n#eTALeCFMO0Out>p3I;X|1#%@n~y-UVEBPA5^I_S}B8tYYjJ@NL@mn{`+C`rf- z($jvT2fZ`O6NR2x*qf@<2Ns4%x6nKnPTMAFJam`TvwHmNYrfrq zQRefDA=&#=`1EztUyd(`Tef+eKB)}td94XW@xN^=FREMO!(P8SUnZQwbGw42$?UTi z*RI~#6IS!`7g@;YZ2~I3C8(j3Xuq}m>Mbx8rJ(si{}$_ZO@K+afO0OHPi~RqzTL^Q zV1*y6wRkK!a_yTMpQpn=CWZMSE)=uz*( zJ2!6CD9_j&(iHpn^c`7GkzX0Fmhr2FnfTHc5e8y4B3@#b1EXu%)qPm+1%2IkN<|JR z+cZOd?{3b+-Q`37;S2qUIcvhlfcsk ze?9f%7pAYIJ5J`+6LC6c=TY_-lVSDzXULzP=@wY-R_i4k z&TA1DOuv4Z>h9szczD(oOWENS6;g@~bUftq04Xz9{kRJG3mQNpCUU|`1qC`Lo*L68LD*WJBd7DN{? zwQbG(Ygps>Cws%M*X%qQ{7MSyCd761P+z6V86qDDAG>oFkLw)g6a#qD(4|E#f^F#|`Pg z`dKnH#WstSHDpg+X|M8bip%@s`7&PT=?lKlKc;^ln=Aaj-M?drL}0_pBL35Lip%Ad zLKP@6qxjBnhSY8D%EO#Z*|JGFn_EG6uYwmc*R(Ip7b@bvkldT?z9#gEWSqIP+abAG z-|WGlZm~|d$A>wWHzOu{r$3#y++`wCc|XGBe!t>zr_nqq8>f+Z;&2LGXbWa%8b1E=x1W$%xO+WZks1d`meHwN$CA-3JOPvYe-8-w+y2xUHaKCM3T|c z0msu}evUzl$qpJ~)M5UIj!Rj_bov21p2Lz4e8XNW@P9vdEymJO zCh=8^@LL`pU#|a}v!<>UKu=0dwO=ti($TIssYv(~@;%YQqUg4qnZ?-gu|ZLb>`y}T z7|iHu(_LwMmg!yj<+FP3I%c+&H~kxn>h)gLpC2EFPXYtUhd;P}m_59C3BQZoX=f^q zleM<@asBD~-f_*|^A$noo09aI*3?a}%0sVLdv?yAJR`3|qCqlefwn|1NuOj9kLal; z&23uyCef;(3Du@CPT4G^2Auh|Z=+Pi2wHlL8vb$~Y~ti-{r4|FqLx#1ylc2wcvRw8 zmWKFwKNfJ>NsJ831TSAXjge|!@H*};m*bA?RU~F9-h9=8!tNGFf) z!AQ;CVk+L6UQb;7l=W5lV1$qT>Pfl1b{UIa&e!Kc=(<*|96r(JoyBCVzZ47Wer!}4 z*4^ITfs-6NbovAD=d!gos|+odif5PKY))~H>`scdTyGIKf}1?8)yI6_7BadZKT!N; z%cxg+h1KI=kAj`kmzN0-pR;hC6OM!uf&iH~IYH8!FiESAiaS23l{6b;VdE0Re~UB2 zD%hD`I*IANx z?g$neeK;JTw9}{88W|mQpm$=?w0FI8fvQEA9XqvM?f*6BQ*n{SjO>ev_}X^PW)7C< z)R>qL!5JCHN}0;4jBvdwyHt{klC-mmd?D7!9@oQm)&{Z5zMkzXA9hYI@fK!IoRPQU z;^RygPp=|>MQJchLHtC(mSxdKa(taIkvK<@LP(dR^G$=abDYYdv~=iPt$`WTrH>Kz z^p^;gFjw#FcEn(f;U(j4u`<33-6_CwyJWhXJ9^>M0xf2`Nem<3h-ToLIV-(L^I8xi z!6ENNkEX@A)%%?GMisF%Gx|N0ca@3VZWD%6deD3RWpzG+$8p1*_4o)_ssAjJAg_7o zv*d*(-vd911CO5GjF!GIa8F!SRF+N5LdCIomhNfA^&VXxV|9Z}GIW{Vx#{O;A++Ea z$a`~&*&UynHM!BDcfD4Bx3$Rj)EbEZDlO!x(l+f`&$Y?APZ@DBhEf3;9StXjce~|+ zt~;H2O66(5LJ)4E*!@2FH0+zRiCeNe?)%+iXxelMJjS2hc{^BQ4U46*F6NFke(*7J zL!~oS-qZi)$eVA?!WZ zEBq|lliK)*j+Kw-Fnt;AjwsnPwKK<$eiO;>8D5w;Q%fAq0c;H8_8$lfl8QOyGrnl* zizfxQ?6vUc&iCapME291U3j>*XaY2yyL*wlOshN|OTM*UD?KZ8lxuR*+oZdndAo>9>oVe|R&@+?X!N^fa$DU0@C z^0kBG_?w~ddh2jGPd~Y4HW^j0C+Fh-hmCK zlLEww-twLi>Zrh-wYRgAMw_oE1G=?Sd5SdKp8e84OX@zDfK&87)mtW0{l)gajl?Ux z=Qr~%93Tuu3V&iXKP_x~>=29DKzn8Vj7gcmAg>|yYOb0P-CKs-!A0{&iy;rY`425C z2f-Y+rYNOz!dmHk1VIJXXez(@?Fb7j8xO19vR=kWV9?0SKKcMBweYmW0 zn+&b(c}QVuPVyIO@&MXP&gl$#vcEot?!Y`dC6z=y=`9XP$)1I?S?$Ix5sn9G8OLi{ zy!ngye3LW66i!GAvGMwL)e*-okUxR@YxPd$ruQvgAwLz7h8g^g|E%hj&X{LU|qX_ zkqKcEuYTwuWN4e3&+cRW=5z?5;GN)imF)`5E!i#svcL{ojMS7+jKa8d!?Wj|&29q` zDv=)}QVS!xZp4*ce~PD!;!)>VI>(-RPKd61a4Dl$2N!03`#`tm(2{)Oo=@3P7u_&yKgy@m^{T%;&dBCxRr0P&)wP#fE?B;X zGN|-9GqQ`Fa$Vd=Jn|4%5Rhinv5fXIa8CM`8Tp)6ql{{;d``Z6Oegj`4WTR7Jfm6= zv&yu)d&_N&8p?6vFZ*4Gcw}4;mvP+2ZSfZ5YMd_Pn8ML< z-RbVH)5!2<*H=#KA4ny`98GWWp6`3o(H$evU|927`U8<7fi0}k z2DaGayUk)7i?Iyo0QZjEgC8b|rZj*XK$h6FmMEH>2zQfE6XWv=6ve#<9!^esFIoq$ zzyE2)Oly5biAVEr15wnTb-8kN~G>xT5Z%iE!iDj9Wop3K2=)I zafV)~+rfZGl>|d27$DS(Pe06$m5{6%bP8g)j!nf z@SVCMayWmYe>a-BYg3Jh#I-A8ty$W!S!xfbFCbpYJYfW3Z3i zC@&wnJLAo<J}o+yg@ zZPRu1Xond%P%sK*IQ3|9a@q56vqj+kXCRn_;y!1IX zO@9h7>yI@TiqvvzgynQiw2y}rbdp$k&;xz%c>_ji;-beVNTUvp`bS83i(R$aRgeCf z;?L!DxQ3-vk@bkJ9^d%-z)LnuRt(eE^DUzF9s^Z9e5W`+anR)Q4wG-5&acc=Z5Qz` zE-p2QWqh;L5?(;s9J_6knV{p>ezfVS`s<3Op4wn zUM4P@&g6Mj-a%=N)>L=N}DM9#b6`FAUdRgP6n%5NOQRfUZgu$!|6J<0~g zi_4K?LO9JwWqOaiJF7CU8+6hvxi=n-H}&Z)3O}Y|i?R%y`QZIhp?YtIJjztGNIpux zIO9i5GutaaUPsiTca*R`eFbCB#kT|7!E}*^>Cf6+S1vVEa669GlXLeVkGOf)@h$IM zHI&|Yk+mH6WMjCy!Q8?W@igj zoZ&6J*B_4_9%-Kw}20i+Qr&ciK;2?wZ06p-5nhnLKZLhm#>fF3c zx^>;DOMv;_jj%oDRr{jjCh^DKC+vN(%BESZJK{VV^z4Wexx6j~DMjD>8|Uf6akx8k z$Jl$!nfo47%uS!~qrvsigiY;a9i?d6w)K27UR0*?3IwHucMM zZ#G;{a5j(rYF)LXqNXdO`KjeEd@*aXa79KZc+b}>bF6sm^*QY6bjQIIq7m!aJ#UF| z`A&Tu$~at}0F%AwsAGg1g&spHmM3Tli*4&v#2XZJw@PD}w9pCjU-iU<27_rTcRf=v zK1Azc(%u9&nXM+Lx@+MaxFs3xYOb(1^h6URQbp)O%Mvd!DZ$6qx>cbvq=5qh@8Sz+MoZIs}3wX^E)mB{ePh=`;oW9e?16 zk7=$v4!CwtsZsHouIkkG;wuqLL+2Oum!`JO#6x7P?~#%X1<8LjbWok5SZaDU9CA$e z<)*8j#JgwmAMY?8SToyMV?F>lt310 z3BzYg+9ZoEsf4%>J~Pd>uC$?mQl@zhN3Isg~yMCj-rad zZhToq%SU$pex*yhlpB$Y9D%fx{Uxr~R5B*?=j$oq?wMy+xQ9)HFnY))3p!a4PPiEo{bneD57Hb-4b;W;<7he=fIK7QH8RGk!pI zDB0AI^0s18@ZRoT;yliYNh(G_FP4Vk7=`uTGM82C<5<|*M9YM!`n!;|xexeD3q^l^FqYHk= zN8TUKvoZRyXvuWYi6&b*NjLS}irAH3mh={`Xj;;Hg>dkq0T*;Mj+JEZ&9Q67ZVFBD&(;hZu9Xh z>w_~Rt^&*T4MLiQO+(#X!>f*xC(_l%Y7ev9i5#0MM}4przgyV!h~iP|`-PRIGPXY?l)H)baJU^Y2zb?TB znJ4Tv$2Nzjrk2$f@23c1+2**O{s@p}wHUEK+7*+w^=^4k#V3}Hkn2@5w5)>jekObV zYUF!<>I8i0kt?J)r!G&;wdgBDLo+%HZI`F4IrQ6!By@)6B_v(qkjzMSB%5*3(a@g@ z(&_bG5+~Arsedrr+BCXFf!k5r;d41ZJ+OGF;}mKlC$8R6)3KSYNx=AP*F`o5Q3}fB z3*Q`b$4(T#dRVr2njBg`mhBEK#kDHXTOGQ|0|p9cBO=Dc>iK144fHS~L$~t3ZXEHr z{Ox_#Tk(UfYj@o_nJI~G-B(wWng99Pui(YgmkAx0r5B4+2P`BQzRmqituLjZ)1sd0 zaw)Qz_?-PKA!BO#YtxpE2I;#4EgfG|WvhkV2_1rRGGFvfGvfu;1zztx7}Iv${$;`? zU?P$5`SglqiGl3v+3H?bPEyw^F8)LB4AGk>HjcgMqbIH2rM|lDT)+~qh}ve99ky*M z-dQpnwA>sCPd6xFxwL&UiKWC)+f!-WboVr`bXouGy6k5|N;0Ct5YpG-Y$zZS|Ml7f zE6PACz1;E`8+jDH^@;!EtI@1w_wF&DOQeAIKvR*jk`L9(eHR5*^0IBvc+cg_BEkZ^ zB%G*AhsW`vGC?oym8uFAlkX!NduCgB#>&hCQ zZ)p=KQ?{xPO=J0-5-*Iu64pR2?|o^ckZops%vl3n4?+dnbYh1g@4h_UaDMZ^7bCV|BYZ3gx zIut>ME?6&9jW8i&)jwMyN#Uy<$bjiaG6`N#Vw&u8n?-EKH}{62M~75{wu`s~ms zRopciw`X-%a8gq=%!=7E5@pIALQE8?dooMgG!ZPB(&41hW40Kti{reT4PHK}vRdyM{)E5JpQWc?snwaI>T3!PBrj>5$vhF<<)x-j@lD zokDJPDi-bE;+M8u%!>N@!2Hto`7{L;D)Be;Q7t{UEjZtoV#FkM-Rm~T6x(Ot$-LNP zpm>QtS~;O&xcl_&t(iAwIC8wVO|s6OI5}yfjhHBJeR4!{UuFF$S|E(3!$zXHz_vBG z_;gEOX!JC%KFhaPoCDpfL^hG-o;cbPnuF~fPUH7eo4BGpy>6pTB9x`^n3Ju4J7`;Wx+?4xOfV!P1MVM&Cx8(tLPPNgqZ|kvPlN-+J zAVo#(kkkCTJQmYJzgGw3#UGJUWhM4#KYI7#$JdOq_at0!qPb9}HR`z~@!=rxn7qy+ z|5w*9EMzg#MII^iiRg&Dh+B1)UhBI_WKgDFJ2qOi$A7?_hYi)T6vZ52to4_+~;8HM?IgW_g zxx?N+Qi8Ld_j9E4xH4UQ#t%(X(a$BZDGFGem?uw*Odc5~E53Vb0RM<}JZCv*=Vv00 z?(-#ao0fMYtDMaZGoyJyTpfV?sRh*6kBC1L6WTR?0(KM19-qIa z-aTnnMA@19MXi>3@Oky}cgrLL`m-pz6NBq7RljC0r;NO96j%^S6}uqTjBkQLj9}s} z9V=>q$4>l?3)RAyaUs)B!Dg$v<0d`foxIv!^7w4lq~*nMsjd2Rj|Z1dW>p+KQF8ce2*Y!qM>C{EOMVr{)NFrCmXPteSr+&v=SuTo`?ZFjv%Q zrJwp4yD-)xZyg?@dz7kWO>@YZ>X!PrU~y6%f9s1u?TxIloyrRL0(`9i&^2$^jtbTg z@|0Cp`v-;%I9Pbe#WdgqFX;^?b#pxlt93KXfnbm$5P8SHtHevPIxVJN!U-zs=+X4~ z;7x^B82mivvrgE3LJ!H&tOymBj;(c_fa+bbOyMWQkCPbC)X6EyH%SVc^)scAA>ZYY zY{K7MQ#<`gTkMe^Oy2BInK2K+}X|TI_UiaQs5AE&2 z#e&E&9^@A>MXfiNei1H{p;xiZYkT8!%1eEgEX~T8a@5K54?amfA5@wXtxlh)Dl-)aiS%w5R=rgA@#P| zV)3xU+p&0DY3XH{U+?Osi;nQ=Gu5|gG$a+@#XbABc=uJ79QI1Ie`uJtpQ0MJJlIGY4I*Z+#)Cor`_RzQA2Fs{KJ=(cGJj?0Ks4cH6p=sMvP0Ha} zEzVz`+h~5)RsU8~A|Daz*`v|JYinL!P9NVBm+lgo4u>S1^-D|>|2fw8d4f1tdA<2YSjf;gFvG_FxTn-P=b?}(`ES$O4 zN9#s*BZrNY$go9}GW218MEtB-^dv24kR`dDW0PSuIcaqxCsrgdmn87&BY!P&cT?s8 zpQQspBWFrV5_)OHtbCzrVkK8H=*tILl}mTbJ2rBh^qcYg-OFZAJn^qm0N;4x*!^ny z6N<(eEFW-aW-esBzp5jG>c=lrFkH}(EEAK?WJwSh2;=6eSIT~ zjsceA6qH#9v5iE?5t@5E-tz#OG=!+0V&uAV@4YS|Cp{uwvUqcjLSnCsCngteLEN6W z&!%j?<&m78%vtw+) z8?);-#jT%WZm2(&+-0b{;h(sBgRO_C zl%w;U<4WY%Zulup%9^hzZiN>qBONom=0x9ash`}^CfH9g^h|QGUJ%3hM)A$Q$Ul^Z z-(seYW}&RyE0i7AdOt6&FW9rt^+A#_`{WYtZl}2Swq8<%8r@gqukkBYi6z;1{n(<% zMtQgoq6ebWNc^fy0r_#?P0_LDy(Qb!gXnO5&t)uy;HsQC;fAvFEk%oXcj{1u%YLja z>~p+v2FEAJTOZ0+aka7(3OBpGY0%Nx_BnQ;M^1V2cwfi<$TG>LI^FlU7ouq?-pIi@ z$3=X{Vc}xqB&k^Q2O9B+wY=)M&7aGQmQnUJDn_)8tT(I^UtQ(x6sRX3aSqf#D^eYf z-xJT>rO_t!w34Dt6=c`l)(hP8E7|jyK4vm{4z=1gh{xB2N)R=hciad51IhNe!;gFB zq&Lok?aPzjwF<}`sn8g+r5a++vbX~e8B>x|>r+Ve;h^i-E%${r*)yjFN_x~<7p$XY zxOf;$4z%<%_#HdPK{rUblfC*zG%7qvza(z8@u%9&)YMi^RBG5q3k`}JhfX=rWOk<3 zrJOiBYTD%31w56 zIWuHuWRsDZEt^BKSCTy{5?R^%PImU*D`f9^9DetG{QiQ^`}6s{$LsZ6@7vR#41%&? zp!W6NCe8R!+Wts#ydb4k^<0Bfuo#Iz?2OL4Qck#*Fp`7EAr9875S3tMlEgr<2j1(PB0G zZ9m2CpyMI0kB>iOpSUhJw{AUWT8WFz%be*<6|fryip7dH zK=Xn3-DO==eFcr@vNXZ6rP2{tq0hg+(FC|!TyQkCJU=^)-lU!TcR)~!afKAq1-C5Q zFqRWt5JoN_JFZP;S_H1x4xZ5blXSBA4)?6A3FCaY!OTW1kx3V^$r{UTn(D~U@L7Rwf3Jz39_T5P^ z2@p8-@pTcgBztfpm1MTpMHO{)5!#0Q*#U_b6;n#TBAGr4Hx5>PeEai{;u0;GCRMk~+=;(Zq#@K8FQ`gTh%OMpjq&zA z83n$FD%@|c_0t11j!atV9<=og=OkHvY3>MBy0{OrhEpf7lciygvfFQ-&Niq_#o!M%@#>@Tknr5} zM5Zq=^Hd>U(h3VGKn&3FAG(wHvkv_wcP@ZsrLRb{=sdaJrI&Ayl$ZO4_cks#gHwxq za{u1yXS4Jp6Na5=wO*p5%oZ+7`vT+Dl!HaK9~$&g~t(JSVHfDUcuc-f#vPS zMLD}89K6pEB(OQ}*qJO)f9k2rrPFQ61$57zoX2sI-j&S_ME}SJ%pU<|_sKROrS2D1GTudeH^vTbaeUv zM>_L{`tp2;X0sgbe;N{YnsA>l< z+BV$=VX|ANRT@vmNjTR%hB}s^9=HPC*EF}m?XOw558GZ-ZR)tDp{%dLki7a z(o)xV;<9Kj)RtHu+15@bL(6x1g`M}2ugRI)%fNmd3)EZ0@jg0&N~I~Z$PGesV%!(h zAg`nQa&;6m<^v6FbaqSoVB9261o{}AU<7c3sD6CtCMySW=|B^*0W~F@;%|wUk?;da z7_t&OT!~!0UyNsG%oI#O<^vLlQJ7L4XcHrmdxN;Ty0Q97l7RY^rONa-$t)dvbGee| z)YhF1LMlofsmfjYTfoY83f4bus+uj{#3l6XbDq984A_%7=m|=r&6$io1nx#*;Vqf+ z)L;RL^L6jXOGz-&yYFUZbsSG@5B_$IsWdCp#};J4T+rnbLEN4^UYvh2!F7Z%wh90U zm9@0}o;Pi8!b$mh4({`-Lfl8V;Y>pDekhP#RUQ#R|=k*&eyae9273-jTS} z%$ZF8hcqJ=h{kpkBzz88-0G!V{fH&!yqB=5A^oR)67}Hj!1;M^Re@3(#YU2xuiOo; z-Lc7IQQ=14@RgFYci}bF=zfnTWD%9vl?y3Ed=lc=?m5x`4P`E57%Xay69T?z}i5*X}nV@tx z`)KlUQ3P{}X5ALbyobj@o5kXE8gO(K`oSuCwr`16Jn)!(oAM<KNuaAo?qJUOATta7atg%;aUkusw^F&!k|!?ytYBh- zvp^8J-To@*)QqL+gymK#(NiHBSUHF|1F!lN4pb%q=rDLpXZsIjooJ-CZaf9|5V;swkSJkJuud~q#yQH15eYr~k@1B+GhY{SclwvAR=(IuJ!pT&5#%X)%ukKC zy89&sM@eI5f`yY+3>) z%=+L@P;x69h5dC&H@#%k#BLab*w1~a8px-}vCf)66{U34%i79%RG=EDzLuY-@LV+S z)9{w?ujxN$J^Z1_8t!z(aoRuMAh5)nT(HmAH$TPVDD$_s3~$1w0I(d z^1;>bm{0a;=hd)c9uEG4*H(ri`uNrTYDHY`SFR-?ivf%0q;c;IIn-S$zEs|^e%m(W zVOPPOc*_=#3=Kyjbi~49*MF4%Fig2b!;lXUa3JWy0VPv%4Cd`S`(fC$Qd2VcAaLzMCe2m@n9=i}^sPlO>lRcpf6%08?RXI|K#MS`%hjd)sK&-i(zOOa7y6 zQR(Q+o_$58OZw3)bw!I;?XOd&X^#E$>~rep$@rE>y&KOSo#RR?m6I2O%CaACnn?Z~ z-o$8e+-l}(#N6#Gnn~K+wyDB?GYq&fl}^ZUfT|0F%oNekiw);MS$;XdpIbT#SaFinZ9-7bcRo9}d%D?K?RUJs4MisuG zh$lwdoIKJTjgefP&Kz#&{rYW*UWv~rz_be_ecc>pb=U3LQ*&X~C+LzVt=V=s=DS4tO}VtsD!<#Z`5s zFhW2xOIhetAMiiALej(a&=GGObV?OZ{&UPF<}eyTNnL2#yW2ZEdDq$C^Qn*sB^guw zVl9bBT4H-cf8jnoqP+>O*+vs45f|Kkv{66*yx5@Ch1}yD{~))z{#=9`wxNj0i1l!# zP=1r}!vT?m`D3n`Kp}+5r)hn1DcjP*0~&xC;0ryYk9gZtqqFu}C@ryq_Vx2z{`%~y zZWmp+0fp@r*jTvpKi}P8vMSwjZl%pNm%}n-$_j&--XD7(=NG0UCwk;ydOkf7vMfXV3-2i*iCok^Fb z0!w^|^&j^`O2T$x(TE6xMDd?b4K`%!@ynbxha2SHV&Xp<&G;Q!)DSwkVQ}DXIjI>_ftx$_p**ojrzCn); zeK?VW#)DNBU2cITFwVXGo%X+@0Ek`r>qyBvNQoTB)^j|&kMK*mTrbP}Owi2ys4t+< zGH_f~v0+GGhbTz6%l#|>5 zW{_6zhg(+zWzqPcwp$Dz>3kMdvYCcpjARKln4k@6=r zu!N6og0Y(BF0m(4rfwaTsQ(mStU7uv?QH0}Z&f;aavq?|o zb#l;AR;Z3sa5a%YiLWl^yCVh8#jiOWVF`sQ%%zn)W9CP418{xVU*W1JxrU4EPt8TB z?~9l4jQIPQS`pSf)MKOQADk7kh|SBE)^nvuyPU0pzHo6-NX1&cvTTf@5WrlsvHTJcApNKJQ?2HSZ1YcS zi6T3bi4-_F?Y@Q@bDDz4PDr~)EX83P22ddl=}vH6^!|l_q^8mv2>2;?ypidrHT5-O z0fAldq{T9G_MX8f^q#$gqw%goLgdZ|b9WZO3E#l10Qxb$i`vpJK*FX#4h$Tv+YgT9 z9@-U^(b?vwoS-JxUv1bPyx|1U6F1>@56^8r4eo9YUdwz$k47X>IFGzVDj?x(?~#>v zKvqnqVe~kp{mO}7eQ0JXucLAmYMdz?td4g_tWaqnjjQz-ZvNQ9#=JOg#6o_B+_ODG zhCGN1wODgm;YpAu0bc=-s<4XnHUT3wr;7Yq6%#H-sFDBI_D7&YxzUCzPr}pX&lg+1 ze`Tk~q8(k-@QoUWS%`|AJwySno_KonYkwuW`dHklPUp>oUfBCtD2k*;&h*)MNXPRc zlcOF|6NS)ioBf358r?v)a^`b8{<6Gu-;bZiU|IrP1P+3lgt;N6p{C0BOnDaNWND<&xZxPAWD64IqT!KfVOrRKbsw9l9i6zJ1g4 zjgzed3mt4EgW8@PR{vQ>YlFPAmWa`^fztIaJL-Ycjb6Kw8?9y%5P*@{s&EtO?eJ8% z;r~y}a!ZzVa%Y-*o^CA4dZv*+`yMuzWjHfH#$OP~^m7T!G4(!`dcuEMbvf3V>~a5Q z3Uyg<8S+&9oo!=9>8&ieE#|GS#9$~;Jl@7D_9vay9LCc>u08Afb4x*rU;GF{4q$w~ zWKOPfN)SN0`R75rB!4P~R%>a4sR(GHDm&&1a7x~w0tMFst_Xg(cKGSK9_7ZUNZWlB z&x;pdyO!e`I8G(MWmBeICwZ)c&SBW7axko|V~K1G^Gfl!cbVb!RMe#=Gi@g1l+UvI;)HNKe)mN}|tuw6!+S^z`7#xN79!S6?hgc_Yjz;~0D_!V?h`IFCLy+u+odo^-CkZ3kQ z&XoH9;qBqe`}cZ*u=jw3pqiTJ&GmzmB`A*DFxG$1KjDniMs`=7DWh*zK+P^U&=cd^ z^+KLfTL@Jd#4lg3T^P_8A_t z)FeZPzQYznG zd{052NS5iP>}wqN#6y^K!Br*h92T?g6yp#y$odyc2J z91Ho$(^8%e&_~J1SMKi+wlo5D4ixp!pNgFpV&cNzNsVA|AIaHqgK#>s45yHB^;6Ph zr|8l#AhFojZOaczCq!OGKg&nA!HsOT~MK zJNQ(8J*uu{?fB)a^-nS-P--V&%Bci8pbCZqLZFCmx3%`lXhL2D5OS{maqp=<~%UV&?$4QEq4{`P65;rGI2^TX-WDQXp z9c{VMXgwJ_XAO;l0VL2qDD};7$yzN=(>X*e5+3wfI>GhHg+33Nx)<|sJzisG#hqY`VlV5}p-aB3UEm87Br6C>oZBB%5r}$#=x);LAzuVo#j+|`fBC9tWSd9)*wF0sy=xEEyUi8$pH1(3nFy8w4+kv^Q&S_~QMBM`U;h==Fh@&%q zSr5x>q#o*Wc0rg1xef3jQxI>rHsh&~8MSJ+B3HK}bbfK|Qkb*@BsIX(yW64*lshcR zy}J*7Ng@hmkad~ESXAEDQ|6D9jg$(B8U0zeW;I8v)fMq6*fDJM==6SHvyegRmX|jx zC|;M|tC1`ZdoDoB>bV%#f34qC{j~&2s80&-%tKCCjvfDnhhiR0Vm+p_fzI`|Hz1a@!iT~s@*M>XFsW>QrJuprHvds?#R#WiI z(uMhrgbN0qh`RPRG3(D=M4zN3HIP!5o=KIMKxwHMG^BZ!7cfLwpHU%i&TEZZf~$xI z7&pf(^SD&HLCTqLFABQIHZHKA9`$+|7cV_34!J!Jzddh-I|qKFg^Y`qkzBS)LgEC@eTOk^WA9of z$fa-6TAwmIzD?YVHE345?O(jY&3|J84jN$f=Kj@S{7q=_!9Ihkccg#5>~)gWv-Vun zQLWwgGp89$WsnRv=dD!r?V0k(ixq4cQvlAO-1=iezV7q z3_*`=jvy<3rFuXdnrK=Vq}0FnQ=O#r4;xNummjU6ef~p+@ok3GTa^sgKBSG_zposW z^v$rZaAsO*V^Aqx7u{+F-g8NHaA}p}=U3Y687E9_>#FBbR#^m=0ttT^!L?ZQ*&YQ= ziv7v%?FQz*S6Fp1pN8US-Qwh;Kd*KfK&gW9KnWr=G_V|;2M8P<(k-ol0%($HTU5(t z_nfo?Z@a?h@JR1%4JPxC`#_yDuIW8%@BFHcc1gU5;Z#T(Af|h*lPL`b!w+o&R-8?( zLnv0dT5csWdn#%^1^DX2b{8ttRX%XRe~3OL_p*KB&X>=y4zh}JSF#m#nGUl3;IYC4 zL{kUdgDy;l2k~LDfXfR8x8Kv(XJG?vbyN0Qn|nqZ``CEIW8Az)?%-!C;Zg>3V=mfG z&XxIFxBW0ST#KmXiJV~-9Vs6JBmBza?LTJMcbi-0Zk{wu1w@_^4ZggdXe@L+2%!Q9 z_Y~^rvFjdl^SP}{iYK1Gg`{VWmP;cU;W@e5I#L+Zqq|=|2QT1{i>k66v0PlN&~T^y z^%V%H~7p05`mR1|qD@9{zKfV~h83i@&w9KbdBq8Ajkrud}2Pk)@fSTtQ(IM{A~LKL{W z&{eQMLlvY>-0>~Fgx61J7cvmRqt&0}7CG%YcF*_Z3S81wCQ z+i%AYw{%c(QYG&}--8NH{bqzBt~eiSJO}FNf*Yw6K_LmV-ZKHuLF7xi>ZxMNZmaq9 zwv*EJP#4H|K_n;DXt-NPDm&GX7ij8Mk=xH*tiZ^Q7CAf2HXofV>WJmd=Q2~O^xMy0 z*yJzdg}a0qhJK(xZq;sIlc}qPEzJCRwSmH%1vHc1pl*tdArVnK&p)|-Xd6A*56%E2 z`vx^(WbPb93)?fUH%9-GXPT8RSI_sdMo`!+v(y#`4fuDmwWwCA&~gB%_DRZrstyc2 zJO5X&R67wnT{d)miI$i}$&xi@q>rur8`KABk~wSU%am?@E^1sc7AnsTcpz*Y@_!D7A*z4QR@rQPuT$)Mx>+L7GjtFiqIgHV4^_p6qW zfmf(-aS;+_#MMajiQ}4@FGDE^pqLI=3orD&QSo@(n2M3`2cabaiFt-+oWK&X49eoA zN3Dh$AJCqwAoyhPpWW@knGTSx`QP*9^zaOGdIun>^IXGjQtHIOnL*$A(ui~*X}R!+dUT{52qxnvQfT}>3Jp+NCw%prs?`pxp79vse|cpZeG{H@A^orM zOwH`tGt|$htUfL7#Ea>j9h3KB7j!V6JV&H+FDcCJ`sh9hH&^FNUbD+Oa(m)R%QJyR z?fD-g$B2_AKUy3lV1WZ@yPa=pOz(}~;nEJarX(l8h2=$TwFQN5syEXyErXPOi{`%G zEO4IK)BzDRh{5mG|Hi-b;|-qN7w?D()P6e4hC}S%{yNE7ge$&-#8Cn2py%g{J6Mrz&+YZwnLs%<04ENIk-qdw zp5YEs2zoxWkMFtZzhH%b2~LQ=`LOWR@3Mk28j*k9x<9;gXyf@+O9?>E2PQvfWe3kT zGZsC0_I>}-1|d8G_CC};@2uHiEgsA_fmY24S64X*L`~T~9Ja^Fp00XNQ=mEF9UX{Q z6Yp@Tld;1FzEf_JDFX|uyZUB3cSTB#9^3uHUYREYUW=Yd3+KK2IBMM!5JcV{5TlBt zLoNl8xx{b_K$3_Yg2a!`DZ9Fn=}QiLGJZL@YO(dN<>TM}{mJ1#yT6rid86AHw>2AM z)!d^a4eg*S&T${|_Me)sulI+2);~+}g^$c$({1J@!+=J}vC0Gcsz=XZL{FuLBs^$w ztO9-`;Y&PnCVv-?$2fN)SSQ-cmhvLc#(ac^1t*52j)Dp+_*#~)4s>ldG~cP!uoc@j z#-*LDW_MAy)hgw^U z)}O~;%5mj&9#uFPQ(u8mv)M(92Hfk@F=M#NtY-RMw+mWo5DzdK7R}M|{p;!0Y|J?< z`QpvKK@So-wPv(KOd_;Ssh&ecs0Y4ntiuEZgSi60W2hS(fIoF)aai& z2Vp4Dyt;#4!IRd5d=^ADl)n$a>28;(QcpJWF+feKi}%`*sA zh-|}qM<1X?W^n%tJA;}ltG4y?p#?Dg(f-SG%~4dqJr=;FDro3dQxl-1r(;7MmK2TG zX*7@Ku-By?&RuGfNXwOMmn{s@0#TN-z{x2QF`z8BVhor8va9Ej&U*&pPU!ZnwGSpC zYxdbQTV2#8f|{}`Tv!Kqt%z~RZiAq{E*<-|w`6v`Wpk;m4ae5jbd2((e0zhF)e4jA ztmA!QZJ%i=!)N=y44veE(MmKMM)tP(krjYlvJz;5vA=*;C+P~X=2TvCw|rhb3H=;U z14swrZ7zXbqWgoGtLWulkVF~c5uL2@@dG~K>x)ILhqpFzlXE8eUyS#+Jw@1F#)=^T zlkhN1O5|B!M*6nb<7pM{%9%R}=G?$90J#F{rdTR&?QO>acuY%;3Iz|3R7S3N9jl+t zZ4D}H{p?+ck=tFK@zn|p{u>zm=7@7E@BwJ}SdGeW*%Lb*J{Py<+GTRW{ZGP%MqzN5 z{ma&sPgWz}!uN^OZ$7w8{V&m##DBWl1o3^cqi>2RiLTrQ`_nGH>KZi$i|4u6&h5k9pS6@Xg;m(ILd1=sPAI9x5otnX z)#g(He)an!KA<_?RPKO6T9P&NUPoVLiwcRA+I%fb=9I0?kI*3gw0D+a(5+Z< zo~$P};G!O_CzYghW4aKvQlzE(GnSpuqz0Bux)6G@H$3@eVYkIxsxo0;6ey>+b=aU{?N|M!=m@vFgXd zN-i+UU^Fj^8d(%e z+_x6nL-yOO>N4&^xF+wiBduXEuXMAI$XrUOR@qlBz>j~X%@Qo_MlOmH(72wkbD8Bj zaJ?|fG{{>pjwG_lT1`y!anwg>N(HK8_QK>Un;SE0Ox-5RysmuK?G$|;uyMQ@6?>K& z&3w#bPBS;VH@w@(ctUnl@ZVO#!9Xm4E6DF`B(eOMQs(^7A2=dEA=8v*)UcMbNl%rM z(m3x`M7x}12#}9)cLrOftMB{;ZGd_D7ev5T0%m1ZAV-WO=k+HSf^6?N1dehl?G<9E2-GR?XT}I{w;9k?G2QT{QK%kQyVur7!zi` z>hmdr>AWw%o<*dZMxbCW5BEY;2}IaLjezItpqRUNME^kPY4GqW@X-FHh9irW{{kLk zC-=x$flPXN*ke|7yWaDW$232;8rOLWNs}XU5Z~+(J%qMLJ`_wmWBk0p2zW`yR3G>< zkrQdgOT@-K!ryno)LQ3hoGpmDlm82(D!m1nyxYY&R>E5>(Au8M&RH*Wse3<|E zAA6Wem77iYl$T6XKVcmI_MV(+=jo4%Gm?OPM7BDK8*joq(g3_v09L_;p4{V`?Es@! z70CtY30(M)g13nT=#uk;z$iQ|t)zQFcYgDJ!Q!A6(IQOO9EO{+`^g8{5dN>GDCi0H>Hq9^d?=3=&+M)4z)I}GRw zDX(Zjyg6-sy2E*%h<>U{^4nrLI+PZ2D!%jBuu2o9vUp8)yZqm7oisr5DH+BN#bJ>N z@$m~qO?R*tV06H3=gzs(J`V)7mO|g zzBy?(J3-JKH1(|v(-L&p4TeL4$Z-i$l@VrCNlr(r43fiK2?|?7?^)c;76#bQQy9j# zc$fztJfl)I=V&$_++HO?z=L3JK~f*WeiKB4zvRk2hfeTX|LF#Q$u0999k4VdxhVDWkJKK%Ldr)Bk4G$ z9uD}J!5E-4KkpQEQJKHCw9_(me!!kKm~cM1__iaYRvEXpq-F|kK3~37iN^JHe5x-g zcU)fv`|tpUH?2#=s?5?7k2L9SxaJGM0U<@88j7%WjA-Q={i4+G|ZN-JB@Vc<$xFELg+B+kNWa$mGbI4f5EkI*3 z>P@@3&lnT{74>w7$p!4agNgbAOIIylMw$CybXJ`U%!QDa4YY}Z+|yN z037MJ$zGi6fD*-m}LE?`qID(U;1xHy%jvE1!Zwd-t#LfK1uXvF~i^OXsNN$ z5IGVn4$HFFUCci`RsE4YgS?FkuM(Knvl_Kj&UDv@*ZJ}P#2K`TR;Bgxfc?rG)u2n_ zf;~IvZ}woY0T?L>FhGzrLj?tDuJK1A4Zm?|9GIw|PsF$VvucQZIT87aci1}U)==c! z(nJEa*t;3;kc9H)dU1~-Gv80wKSW@lpdXHTe}Nr*;|Zwu)se)!_%yWcS4%?bt%`%r z&(tf!_>98B*3);qfZY*9bwk%P$LGS0cT3x*b>L!lubv_{|8weft-j|96TN8mq%eNR zT@%Mraj=A&;Zf*DspqTJRZrnRhIOJ&8*f?5aiM!Mi!0&NAsoZc<~(s;{-svEc)d5y z!y^8JwHmlLbJ?5@RsR+%9K;EjQy7d{-;myDGxbjcnj0*5m1#7tW`1==`KR~^}~_uVMpPmTz237x@T>V7Iv z#kr0E;R(n#?dL_uy;wNP0|NN8tRz3-r1ihod8Xj)2!^l$b11G2tFON2IGm@H_{Kc9 zmm2TT0qjOjK92-^!N!yc-7AWpS(M`KQTeg8!^(%K@lxO~xRhyXfm5{~u)fqbz))6h zmdexNK#$wGJKYn~R(`Z|XI2=UX|^vO=Ir1vI#cXmG@tZm0MM#d&o_*nxD42GrVkDQ z*uSGdS6A>Byd*U`=& z)*P@VhI8XqE=7aSDa*MJ#uv}B|AW8b0L%4Ciihq}FA=gBw(12Din8hx%WAd}K7TAq z(Fw?O7YIw2#ZPTHq0W$&ZP048;X)B+!jp9Ku)OtWxAXf&^9#AdMQ67_>FS z(1mTthUF>e0G@Ff=VmpInViQ)3Wd7s6!pEV@{QJ;P<>PpbK%YmCOru=y#D>N!LQis zvA={*sDb|D4JJ+t{ok39Do=GUH_KSJiH;|ga^2& zEibR}pbkBA3z8=Daj%#AW7K#G!(%x3*H74*aa0cK@Q01rL$ zPc*$A4PX{oHci9*8o^Q{Aj*YmC-fadaDy2_d7Jn7pceo6t3H9H>%}1lEt0&)7acmJ zNT+L)4=fp&vj<5Q0!Atm5)s4UiX7KtEN~A45X=A|N6MVmxZ}|Ir(*%httj73)kzk# zKa{mHr-y7Lbd~i8GWTB=%RIVU@#P+YPx1$j2dEY!g02q-7AV%K>-mgcy8q1hFL!8vOC_EqJ+X?>!E?f0D zHPc>ju;%Jod;sYwMJRjIhEikQX5WfGkYkF28ixTFf&dIXS_v_6^0%9hIX0^)ER{4M zBnFItk66l&J5;Qp*iviK1jLNa#CU~oDc5`njQNW|cwOyfB{`egO}$Wu&8{LF3U4l| zEjpMZXuIx9C5ur%)0)#!|Yp+`|z0L62 zse}mI|EIHf-$j9R^#P)5%GF$dSs40vg46P{k5V>2nOlM1c}ba{=~@I^usBk{S>R?< zBL>LM+Vz{j>EC3vdwhHeVQuWN?gzhB1JDijJ~bP?sADs!&%nmu3*3@$@!PE-wc=&U zh`2~kO-<_IzYgF)u?9M(e5Ky>G1!L;w>5V@D;?A{HvMkfxvGN1IS@?sR=rB3;8@?c zN0t?FkW)vpSnmoY`I__gYHZDTxW1~znPS-TUT@u``}&AzOF_@#Gr_-nIZ%8B+)vUs^Z_uX!N0IR{Q8q-Xpx#*6UfDt^~l@UP(;O|{dn?1bC8Fs{5y(%GZh z;=h?5YV^>rNCIM&*94F59)DvXPFRQxuHea}`P#iGA)YULtlucM(IAi0o*?~lno}Ea z-UekT{PA4@6@qFlcBH)@**FN&8DLOy&eyOzMG?wt)(%!hsW#6|m2k=>{hl)CY) z0Tet%g_m_7Ef`wFNAV%>P<9%-7hwH`WpR-ugHSXQpw50$e@z_4;GiOw1wonuv;YT6 zb>THgS_dWN@HxD@?A6Q~o8j_P&)Gja{EFfo(*|+^^BOVJYe_lj6VHk!1Z?VA5#JAI zei3al>Z=|VDc*R;Bqu|S8E=x8?HxDahaJkrp`T&q_tqUba(!v(Qv_*{4(+-|02~1! zl=*-yTI1tB{xz%|dlE{6^f05^6;YPp(}W3&M#cU#@8J&z7d*$mOz;FDb#gVYjg0c@ z%tP#&->F9?i1A-#r!WvN;pKYdj#@8+i=WdNHYAO%DhjGu0hiB!%Rrx2L~THgT7|MF zTP^~|3RLM@ufUUaM}4>b%o$?b=AJa7?E6h5;bTWD0^7$9l_>5|l0=H=cU?Pvk)ILJ z*{!b1Ed~+8(lvrZ)=uda$6TYJd#O)w!^b0*<}K2C;Ot-jlNJz;Dtlmf+f93^KOBt0 zZnC85ye_@Ap$a+?v_9?L9sB#x-OPf0`7}g0S;k*MB`ZzZNZB0x4HVoCPn^(&yJ89MhO@XYRasTtq@TFrW2}dlBDR?$M3wL{)e1;Yho2lH zWR4>JPiNV-KeM!VAxbBs+<6R-?n}A+4vtW1vYo?4VmO$$2#i@yhE}k7s{N`k_YKXa zwQL7@|EBF57l;KJ-@i8w-pFDiP=veyNvk2TZ1F3#VDx-&CWBJvy2u065_i{!lWL=x zc8xo?YmdzkXp!yMz$8LxRr-q_HhhYGj{IMKy2pNIvr?JfkKuoQeBlvI%2~f`vz4|3 z0WP2+XetR-OqCF@Y#ACIk50qxU7o5Pb(8HH&OZj5e;*eJnoo%AdJrTbMvxTbr9tc3 z!gQc|!2APT9rU$l5Wqa#8tDjp)d*rDK-(&MKyhl4yN6t0^1CE?@frHSBk{Ju)Qj(P zDLoe}UvumkkNz!hw+${jvFC(8zb5Ra%?YNfb5b#9F=cNRKIO>K%Ne;rm`YZOr!d@s zfpAOM5_Cd6_tQkU{<{q*mt-pTvVjqgx&ojt#~T_f6Xwj{FB6GcVkwXM%;Ngt>5H4( z_CflipKH|xlt=DWIX#22z|j>5VeaK^@iB7Q@RoN)9CoxKzLM5m5564v^yKLsaEp5C z7&Ji!tpx_kVf1vkxB+AdFh1fnyTiy?*y3yEafNA>;slVK;L`D0Jq7ACw7zlzi&a#A zy#T#!jbVZCT8PW!Xm*8tLY9aV&wqv42zcn+>dW(SM(eUI4GU;-t;UCc+@JW6^$$N_ zVP~81TJ@u$ds-=6gD(*qi zZf2_}Zk%y-9wg`q2!K;pNE2)ieRO{dTwK91m`HNai&xi)`OVi6C`L@m+4)sHyGjY7 z(MmoyksM{#$5pfvOAdJ{;tG84#cfV`nV%hU*gMu59kVVofpnY= zO{wbv;m_Ew8P0XIy|x<;cB%Ww!9iX`dsuY!g^YBVCjWmV48x=~h$QWna)QR?L5tP- zf{%B@wv*q)Dy54FAhOvtEpQ0BN0~W%vsAlKb*xiN!qvKT)G4^ohBh#0!CSTR;Rnr(0 zenLBUJ=EcTN<#O}qCjaVuZ%kQ>RSzQ-NV0T&yDa-zuDSTyKd#$X~W+oJeLI1JM=gi+>zj{#IZ{XlbQz=he z(h*?x*XR@&oifnChNJ3qP%9rja|!DxOvNqBUKN}9gXqQXwC+z8iB6@^IMaufFxbwh zHyZ4?1O}mp#U`2Q5p~BGK;Hd?RA7WcloFpr6&Qg0Xi@6GU7h*Z93+c8P>6|n_xl3z zv)8^fIEhi?f^1j3uI@TjYX!9Pj}5!$rUHzgE>)X1E9!)^UeGIL=oYYpSg9{))eFyh zUHzGMZaxzA?f1P#=g}@@e=`Gbki<6BEHyCEb4dHW&!h$9Gks|!cAwW?M)j_(yT=Sc z)DJ*dw><8030fiqUc~PDxWw?gWxWf}fM#;Ek70-y3vw66gQp35DJhqabSPZ>GOD~|CT#VEInd%bT2B3?*K4V7?+lJ@Vz`UOwei`1nRV#Gk#RZnTz z>uZQC@R8EL_J8cXc{o(>`v-nz3^Rim6tc}&LMcng7RDAzh!%+mMM7lDe(XxNRQ60n zdnB@jK}BUN${tddtXXGl=XcKZ>HU3Q*Y9`z{{CLq_tVvLJ@4Sg)Fl9%1BHQug;n$jey!{+;(8 z#Lb^+rOuXgpsmZQ3q_4C#UHq1(nekIp__Q49F)OhigL#UB7i;&Q0P5r!~w+ND)Fr^ z9@$4vAJpfqu%76N^jvF5N;U8Ct`Uk^EA1Q0^pchE4*UoGu)SRo!j$3w6_k8gyfkK=sP62SmZRd8W#5A`*re65!7Irhw^; zuhvaD${J8I-|aRfCyKWT3XzqF86Mi~3+D+11OUIWvS)pdaKk49LCf&0XT3)J=BrHe zc=+xf9p}gjD3o)Uj9by*_is+#HKxT z<|0bSi(1cr6j(j@ek?5~myf);X+V3wq)ZsW9=OxGwhJ@QJ=}sx&Q*OOMY+p4(HF69 zo?o|(mCN}amq!-;f??zlOTtd9q^D&>v&0(kRLy0a1f`GPSo^4_cl2oeil6FP=Q1B+ zdy9sw6zGYGsqC_oojWf`Bug2(NLFddOP%7GVAwh?kEU_|R?Qnq9JOHsXRB;0-DxQ`2w!=s_< zdG`2*49u(g3BNu9IpoUS11lc~^49kX0AXQA(3X`u1kziDj{sgP+ELneB}0a5%QJl} z_9tnV^40cCE9rUz3PDpdMFr)NMO_^Jp_=@=+Q!Cxi(f!)m!Ca7!=uW+$=M4=si^1; z)q6D%`B0u=Y3MAj@cq18p(HPKEoPz{OTk7aiexx&*b=&Cm?lyL0jqn;Xc2=~#lu}; z&rlTyM)K~8oOl@EuPMYENXZVXPyF)ws96)s?YyfjUK<4n zXa|oSKL&;#1wVK3pQ=gl$t+Yn_Ti~i)0@a9<~PvknCl~^vWev5pKf;^8|hv~1s{!e z5ABxTo}4GWt?q|aV>g<#F~4$Y2!%tZozShWl|tbPZ`2jW}Y^1k4shojt0K}kSGt>^3$!C2~6 zduxk<1Ap~*@t0>p zr8Z1l7xFARf6uMuJe-ejCB~l31d|)!>JTYZr2Z8TqEOO z-RRtGb+Rmnal;}FQhxqwU%-PYH(zWa5L^uULTR|*0^fm zOJ3xjN>p5Tm!%ng_7@-cCQqSL{l=HjqkCV)kZ$aa`f)EGkYh$U#WvX*7k>pXCF@K$ zrmxepcEzUJIBoYCi*sK>(~O=D1@^0=9y>JW$(uy?ot?{pBrtXHeXY!U*jtXds}(n` zetigppE`Q7qLL?6K$o?8=Xwf!mu<8i?d=#}36nnUJmq2@>NSRduDBVL%%ONmiU(w6 zTEm!&2o?qgwj{8`i=(7A$VsmOS)Mz>HufP*FABq#@lHj1i`4)_VqKaNA6`qUT)0#C zTEzOI4UokIN&^<*Isi4`0nZMby&YhA#RBpFSPC=JZ%%S5q^G#-N=OlMk?8SZP zXpsI=c;UwU5hXHPSp7-XE13HZu6W8C@xe+iy6jT-BY6eBJN$~T@_Qp+_k69C!Vso6 zQg*VOO8DB?U{<*E32*2mPNHV#Ck}Q2@_zmwB6>W4yqZIXX3f%kvxJdQyr1NON z?w0Cxj(il@a`7afvcpp!5@X2HBZkof_Js|P>gyX=bkp*59n)NCioR%++0Le2pJOfw zr8dc%_e%;@03${2(~A?uBMyB_{4TS{X4-^3Y~L{*VJ*BH_V7Y5zj{%wf=bJ)nv?4x zBjeIWqwq;R)SMjN^D@sQSUrn6;(-e+twe`lNxjr(1(rLQjAa26a8r2Eaaf)*z4Ulj zg$M4tK=i}Go#6bDBC`KoCDxQ;5(xuXfaRHZ`*vl4ndw`*RTMA1OD2Y-?oW{Ov^sJH zz{EaTFIDkfe)Gw`rZ0kN@fCA;G9bxhD=h458;)`T&@N~P)*IVmF7HN%*Hhl!<1Of9 zs_zy`Ovk;xuQ4`vn`1iUQK4W)yZNh(f@inI)j6+j4J$iI$m++&a9194T>i<|GJh;@ zLf(Q|sNF1cZqH12!E$+vL-HZY6)o$ROnE2?;qY07Kvw|e(VFC)Ib}1V5w6yoxBf1n zYTyYk`4rO!djdHoa{uc)_HFd0P1I`^(F3B*bSAf(=5O?iO||&cqj-VicPc7zspOEz zl1?*zbWh#UnZB@b)crivEsm8(>Z)(bfM;1RA8;_i+EMX>usk0*3ESjE3AWeE-;FyQ zab8uL(h5v(p?_nkyoX%pJ3Q~KtY+FsM_GrPjIgpvVYKbm5QzjaB1e1w(9=gUt)dCmxreVh4y-NpT zSlnlH?OAasAP+@aVn*?ox_2(Ursf}gS@=-EICHPI6@ON%#p#8zIx%B|ov~)95vkP1wf5vMP3F z9mQm)gEY+;GXOB6W&op|ZvCd))67gT5j=zr42elw3`5{rndir79$&nD+5YQnvaEp> z&R$`~ch#nfP5AI)%Wz0m(y`cg4?DN^ugVaPuN;25mAi`-X1e-M=2_OR%0T^>y`|y+ zAVCp_A6-n2B0^&;2Tpe|do?^|#zs8B-uOTlxGFqOU*&4nEMD(khDj6Y;$usKr;$e1S(N8T1biQekv)|X^ zNd0VOea3aAQgRk{$DTI!PoLSA6{ArhJV1VZNkQpFHu&y;WH$a1NoYFx#qGD-3Eb2q z+fq~pAGrM-;6%XUWH3f&;p=5xC!c39NugFF317zxrR&_3t~XAzpD*lFD&v`chdndf zkVLEpD}3szfi12*W9-aiFiOD0d5qW6%zIa`?7R83o- zm3ijOtg261#Xaj;*K7RLFcT^+ejT_qobUDP+($y+f(OMoAyER(qvjR0m(9ofhk`zE zfr)6R&i0&4pp+AUFYHtX#OL=0ucQ;XZ~dT*Ql8-Gckjj!_^z<~hdiX7kVFX`!D?Ks z-jt|&B{=<~I-xBCPtobFmc;0>0fp1f;gX;WU=r@8*nU(u#HiC8zhlkuO_}}Tl-?rz zcRqh}GHpJW`B~+qaQmSfxaC>O>G71v3qR6BpQ9Y8%Q=G`#B-Q|`*7|eR}}wjuJ+V? zjloP^R%St0o2+t#?}lOB@)6Ox_+Vwolg3n~iK9ZqZ>>6aU$gGpoIHYsUw_+CvE|OyQ;9SVK3p9Y(Op zZ%PAhY3x8z_Nkg6_eyfH1n5BYw2(iZg@Sj9i<~bd^NB$^t?`cR(w@j zc(2#wj8Si}uaL$zR!8q!b5G6JXB~d1&PE5_Wiemvf0entq0S=nUfZCi`ok{~+M7-= ze^{#ou{uEik{G#{ zK-WE)@=>FYzAL-7U$8QwttXsUJ;u_IdKT~3`}w+Bd-Va{FVut8ynW-v8wlb+P~#^&=q_g82SD7 z5|!CCetXdKSrO>ZJb?7JEQ{g5oSu=wXaNn?lHdCaR)60!`N?zmD%;+P7^SgE%2Lrq zQu+4m#fydj$6ZT>??;NA#0AJfo7MH44;zkwKC?RN0#!O$>+PLyI+U$X(;c-|!Mp0m zm}pe2R)TFnuc-o9cS(nd7vV>(h-mi$`-9lO;^Sm7>wr zf)qn~m7nA7ud~6~>R+Ju?fx9rP2A*&IxUH?TWoN^cw{r#wFzt-1d>5B0Gwr;-~n!9 zCmt%a@2<+(G+RvMM7zv{rR-;_YkT&9w6XjvHHHLQZ3C;CNe5Lr4*XI+>^rtwb3IhO zr8e<%>=6@y5E?3E|6t*mdQY&ZD41)He9R$jOot378H^#3PdRpwr3DQaZ+%E7oNF@8 zd+)oIo%u-Rg*%7Pw%3VQ`onZ8r_;m*FofSyR4gH#zjg5Ok%JD36s{1vt6PeCbL{CC zwTi>iXj>gx*9Gm)Q*d3+Px26{X7V?+KQNEBc%xjNz`wj9Dj2Q$mAzPi z>^>{rRrQM6;Nh|GP~*HkeKDM6-Z7LtJo+Nw4sfANMM^Nk)1g`l-+pvp;InX6G)qJE zgTBmpw&@luv$io`9itq&4EaO5>CZMXV)T3)d07W_PdRk*d-6^1IU{nw@2N`WHs)j_ zP<2e7hcbBCG8DeCbEVr$=k7S-Hm-D-Sr*bgBvWlxo(Sy#R@Be2 zd@~(AT6+4m>C4{JYj&Oc)`-yh)Y7w};2gWGot%#S(WueVr^0V~r_9 zp{XL1Z7X;aZJjRzhCQS0+jK1Y!|}g`a!WcD3d)U`V~Bt?)$ZHi{kn}2_q9)pgO8q` z3CM~$GdNNC++A)osauAW5_`EOMQfctbR@KCT))JV??ya7=PVDLSlzRTUn~0blOS;^ z)&GO+UYyY@kvUpy`R*)cR9B$NcK4;(kZ~m-Fj7`qqwV)CyR7GyB!J;k2>^X{ef09Z_N})MQip!4rR*JG9zDwi-eU4@+$QGC z$}c8e{L5^8$A|HR!Ne+{wrPZ2gL#ArTqWW)j0Qec0ykdX1b1b=dlUP}YjJtnv&AFi zR-gE}E&u~i#0W=qq5u{SsR@$#>fBR~PFH2O;L0lHu0?olp4Tx+drgIS!~}%#gg^7( zXg$3wg*O)U7LTI|P+i8BH{@Jruj%S2E~A*GmIO%PT1c)^xAMtBuiqOQ+0lSoMGBGS za<7;re^iTJGPiZ)xtRK@86g&Jpf9qn;^J4w-_6NA*7lE|$_Xr!c~It)H!Nx#n)fMeG(R!s@f>Y=l#QCFV-8!GJuCH$+*|c#tn}d4T$mQT(Fu)P zN3`|I&h?)na{+-&==Q-uzk*5!)`5#y>xMv@qD?DjM&^mt+AJ=f5&L&fe-8hWefIUv zq`TQ`8PUH#2!>j;dmAh> zN*s6rZN3vDi%a$sAYRvVhQl-GUB9M1>$AN27HBY z#&cZ7wBgXop49qx_P4Ds?NkvYapplfTV|D??6+*-L_oe* zwsWN6iS!`-s0S4_k$5oYP6nL=O?DQU+2o_1mZAgm%$`!Y)8*gwLeMIg|=8#ud74aMP3cO5OBB6R)Q@&sykk--Y+e3Vz3d|B0I3X0kgD!f@4MtzuRmd#7 zyW#Dyv!#OWq`LMKgDxF}HgIR`7t_?6mol%65J80hckS?0E0?MnAzmCaNd;qlvyE3fOc#Wy?23-_RycKM;N?;cJi3ppK62eeQ$ zCZ#tj0Ehz{@r#46j-20fs{Hg3D)g6R*>*4f6xtv&k!!Vq@U(~It0g;pZYx+7rMZ*;hy4iyF z^a9I)-A3nG4t0ebgOnZeP$`o-XD@no|2U_ilKh^eT5Ef%QGNT)r^X_d)oX47b!wtJbe!|%fBbMGk^QEyO(FppUH~p!==mB_ z?AC9N#dtdI*}muaCtJblp&k9hLyhmt_v7OvsUh@zD3>^6pq1>Iw^nq|8MVF2d-3fg zpJ;e}Nsbsh_TDbm7Q%fO_|6{p>X!zY+PJ$2`+@77ofk@uekmP4>vlU^GMPYz5Xy;S zNS)zk20$~j>%Nyf1WAB&fvPK-Z5ZpS6$N43Slu9e*#wl{UDkoE4hxK`y0q4AwIOaw z79R3vGDPj%6Y++kE4^{Gj_j~1kAEZD+(zB(@46V= zIkWWoBT?#ytAy2?m8AEWB`H?5tE*pskQ&+>kGLHmWdYCj?Gbuf)nWhpLxduHMK3B{ z%RwM6iA<_R=jg$IXBhH#&fl$DPHg+Wz_zq0mEe392bZuhmWBXe2rM71QuqFtJ;eop z`Xu<%TL7>z{L8LHmgeWV?Rq(1MQcm0uw36X`?UXiMJ@0^BI^0EQT-9x0$HZ#&eT3s z7mIT`VR(DXDUJ#A*1AskF-F69o^t_x$tQ(SHgv(Fd^;MSvE*<75^Z%J1L4gso<{)1 zXf*-Bp)1u8ZHfK%=P~R)0Z%F9W_L zfJvY+Nj^)R^R)sa-q_@Vtx2}f!*dIC?3E19)h4Im(%z9MpfFPSbj%qsG~j~nXy62a z`(=E4){;NSBoj#BePRaQz6JQThxJM-2q-X%^`YKoatvOqRc1Z0<+m1{@_!WqQ~pyNS+Zo39ON+yC_mFlZ~?K zrK#J#myNwgW`2+9>WBj0knXOHa))iWYVX=GeJf{~E^Z#T!me8AW_9TL$F|FoY_YxJ zYsxvY?5WiHPIgQt0JBnw-*_-s;!num9WD&ffBG&k6Zb&&?|PnP0&muna){u(V{J&_ zaNu5)z3FDpn|&XWH0#^#P6sk;+J@Y@2HXv$_CgyhQ-yUzgQF;|_Cl6?ESQ1b_#(Rq zj_`mpi%r|~BRS(5L}wKUOs1HUT@5K~z{ZBB~ zK=oD2sUD-Hz)zpI|Dv50+V&Q5KBDcuwGF-`8nVB5lhbv$}qVmCA zcH`lRtg)k+?`pft0D+Q7acAIkq%?6%3kbJ&yroitRcL8Ej?G-<+wXFKxW6;%lj`xl znA7?nB5jL+mmjC1#Qj+IG?A=hekz*13?qND#EAyI4Ne;yT*jerqV}s;pJoCEY^J_E zZib_nNw9S@^(OVV7AI8&1?CVzLN2^pSiP?y6=;X9CYS9cAgLS&hva z%*`tVVy-n1Ndc&zO%Gov9I7dI`+Ml!bKuW9Xj*+@K%RNskeD7 zUYrZ9fPJhI;GhtecDwzBoem#Qy$UF;Q>kgxnkjl9O|H0VS}S)}4oBsKpD`87!;qc3 zjRcCKmI1E?(SZliM2@<~7VGZkMKhtIV1`ACaG23ncwf?8n&;NFc_tE&k&opD7ddT% zMK`SH4VaQ;>pt(sC2OH>kfUR(tpoBh$Bip0oR$5OC}2 zylN*sY0$tRbdGGm;a-)yUlB^bc72m;M(&v3yQf@_vAx^ji;985`jr)(2|-GS87YJr zR>s8l4W~`EUr_fltv#!uMJS(Q@}%9HP7~nSy8*Al0p7^S+sW6U4$Y%Ofz-77NqM)5dl@uF@%~Wmt>dkwHt@?uGak6c>zI0ZnqFCE37f_5 z4y~WH+CTgPo~gx=^lqmqIi%@S*iDLv^;zHZnM^nyGJ|dPeI@v5c%(_!*}j{DXvXqx zXAisO%_(J(^A`%)Ad`6=k>Q{SLP^l+Q9kLtR@zk7GXEnc0_iFf3i&)LWbDA7bCvSJgvbTr5&_vL*+X0KJ= zwMLECQ%pT{y0rlSnxUwxk`=^IeWBKq;HTu2Lp*v27^< z=+MAokL?kY^{XMD2RLUwp44g*zLCX5{NCPYy{XyVCPaS0&60JWEi7wDurns%eR6`* zj+77eZ!i-?x%lWsnU!E13~X9r?ZhPZ4Zd!A4de}-UZZ!lFDy=XyzCkXV-`Nz_9-E@ zl{4htGU1DiodcTsyza9NJ}1m?d53cm>l z|qS3x2U2eiuVXmH6?1!y7xI*Xg3ahS!~N@*`=Nt1)G> zM_D*dNh>AlDL>X|Biak5ke*7Lh~!Al+N3X!Q^w8^*L#Ptnub45@w%)}!kHAV z4$#w9@}bGezTv}ae=IuH3SflMPd~;LBvc#$N`5qIF-_5%p3ktx`OwTd^ft%S636IU z2Q#F5=)2Atn`FBh;(!v*G2SPT>~HC-m$|l{fBi1t#S``OgVN)ctY(a?k$*YPkS_&;a6RIe6Z zW*y)PG^XEn44uxci!?+Vwd_9I`f2%RR?1>kb~p;2#^|qZIP>cfRy@>Y#h2lm!Y;UVJ0*><`vKA&`Qa|@G5J4U zZ+!Rf=wpeMasP48XVrG2%JjfZS^W#Ogi6J9{ka}jlF2;+R>MUn%OTXaK*?(KX$7u#s^ zXoH}9$?Q-dE3F~PYm{I4t_!d^@>$kK2$gL}Gus|ahX3+)rirg z4By2*$q{PTt9~uC9&n$NBJ&H6vmXx+Yafd%m0+rnBU3W?QE7fol1_1%nD?qeR%?_= z!*m(*eHA$^d{K(#IQ!fSH}xr6Fab>o-@*TczW9}|c)RHi2Yx}~#AkF> zb`(o9T3?6DVKe&YkXN7Kguj*8jGPO+HdqU!%Xt#U>}bip=3l!GqF=5rj+-WVT`GpH zq7k+Vhvz*y8&E06^G;6P3FT=0m%CD>yLJlr7A0W|_xKfF3uobbYG2xYcvkuK;`+Yo z`}2ohLn()~cXdRlqCxO?&3z}Uw+q4nJ%`DfhGdP^me#Uua~jKWRb$xs7uNm(^7;0k zL8kC`&L~veONA&`g_zQj7o6tH@8ph67HPe`BxcQ&$2-a89U4?_93-rG#{7EttZB`G zi)`PpumefpyDsd6`c*ts8Kq5i6Fr(?QL1$H`i;oLQFTH%-72T9tp=(pL=L~SGwZa= z5f5b)uz!JVMg7VTdistF!is!v)HcN8jCYMiWi`s_kK?#~j}m^lF8;)v`7*Wo7}Z># zD5n;ir^Gjc&PymNW{Hs1kHM7AXRXIKn#W4*3WU$W>06H3O}a+z0ATIM3Hwr0G2q!+ zox{M5nZy(8Q&}bedU`FeiO-ivs1B3ni}@zm|0ysie5yvSH*o*l<^EvV=Wi@Gx4xH5 z=+oYg%57n`eUhfwQu#=2WMQ;VLz+TvmOK6V(}S1e9tIs{xt4xI`+!1(vW{Aj6J&f^ zp^D4DZz!%!>WB7?O%;OMaV9Z^_xc#tgXdLqrOt5ij{yLjhx0NbPb#mSF5uj|nNyzo z@CYq@!^bBy7gq~lk~!VBM!NV_2FQ<}ovhm>dZ^)w4Och(=pI>95!|az)?2)!1GP^& zPjwp~*U{i9IEMQ^Yg8Rg(TL5N{q9(MlqN5!Twcvdu28~psDYL|Dyq0boQojT zuB62`gEB8(9Z<}PB+Yv@8kG^rd4Ms0F%k)R(9(P@D`DKI?2|P3WTw8(BLCpkt@?iB za^dOH0kHGJu+FgUwonBjtZWJ@X4}Zc+uw8^ZSGe#Vj69HdjmW~($KDpeXy04dV{j+ zw#uCCWAY*F*NaEtA9Z=UAra(%;>~qion=&RoO83#v_z zAYGtumM_RoUOoL>keyoyTtS}oo?ZStzd2xMN9nx$7E2NIo_MU8Q&*(12*~Qf=e{`k zQCxUl?T+(cX~;GF0svBDbhbo6DGx!={`!mUV&N_1LnNlC&H1~*kM(yhY3iWM(!=xh zJ>F6DfvfnN^25=?pJfLw;was-a~hk3F&=8K6o9|+!(#e&TX`dK+;dM;&9qW!A7=tc zJTnA#qMs_7@23T$0UvtN^9TOA&UogA2W%0gi)Mt}uWS!(Yr9K_&lVqJ_S<{M<4V6= z+k&M+*wFN_5IT8pcF^au+3-gMdq@iaTtMjE0}`1uMwCg=_Pf`ZjUbg)MV5d0RO#r~#HpUis2 zq#L6umaJso){rW3mp}V92JPt#Ka#fLELdY5#})0^v=1Nktl`o~Hfq2Aa4ZVe8HjB- z73NBUqtjv9(@oHxB&g!3!R3O>s#123t448Tw-BmSL~t!(XU)%4kopKJ2ylcfgD(Tu zHse_+{ekZ_D|V#Kj5p=Jzl0IXRa9Iu^)|cp-E{;LsJz})w0gCb3kd1<;aL&Bo^nms z;YwFJCR1s0aG!M+=_TrBB6)KZjxO2oNf^}Ct;N~gTuQG`h2<}OB7t0OT~L2*ePAkY zCBED)cD67qN{UgfLuEpCldP>aUrr%1{P5!YNhzm}A3b}uj~Gbr}vzJ0G=gxRqX z-V}U$$LcF5Wp8!`XA=HG#j5?D;K{oheiI`WtLDKa|@0EZJ2eF(o`=D;TUwR zv*>g1Te`{t_fq&8WmSkU)WlKM{iwJ#_g7TehL=}ZxOhyH z{dzhqEsmOdZfJYx0(^;ZP_MxaTP@phfqon3R%1KzF*{7PYroB|<;_L{OOCmi?7pEj zE+}$DaBnd9YmjrIHk5rzup>3Rpn)SxYz zF(Ql03R~eQ*wafTzs2Vi1eH^l(&ddYhjElJ*w8f;QKZH83!4|mb9=T(0O|O8qb)H) z&MDc)!qAWN&d@^@aIf_#XQTwTw88=KL5G zC&CnO(*yd}IpY@L^M=iPUZ#BWI~`iGxTvd+rY2r)Mq#Ku<>+Y*;K8>K)i0>Ni^pt3 z%B+j-`G>B|K5-H!fVXxYIZv`1y^UWC>I>X-`+8&j*X`?1qK_XBbuRzdCi|+kO7b9I zp~1fWS_2nRQYk>RC>by&lW*dC5QgPs0QWz(8_8HqV$l;FSpgC4a7omy@ksOK7hbn{ zS;bR?GoSSQ>NS$Imzy}d0Z!eN$q9CIG$V00z?T9H+&3;BDHI8xpOTK6eJ$?(&ZeA_ zo-B6Vrw7F!oBm?xXcqhVU}ivRr3k-hx@ssII2H@ZU%(zpQ?Oc)3dMg zcG@1FdIj8pDB|NfiS-HdoYT`DXU=x{hKUu|me-mZN#-1|^hs#1fBj$)Wz`vx&r0Gu zqcOY+KcTkL)CcpfXQRq}^!BP&=q++`><=x8O_LEZ+u=4$0bf7eZpcr9Av&!2Kgu+5nq2>(v!L z+du^zxgjwTxKiXDdC<4Tj__WixDt@uPQxGWJQS>uocn6(IGvEkEdMmM=+r~GmMzQf zGbQuPMEEimC6rr>mi}evlwDP6-Dpq(Z10=gAbB02!0W1y6NZ9@%-TlAp9-g&s7`W{ zc&>syZPdrTShHXFs9xn|b{x3KkKT;U>xHz0T*T^8y4?CE%WQ zyw)I-%c; zp)lk<#Y7hUEof`HX=3YCbfTv5`!Cm2F6cPw`h7KZ?j-fR70sTw)7V7FT->uIVQd(u zkmq_6K)uV=}Yf5K{% z%#`?1;b38oz5JbN84=$;s+t?)7{OX24ojRUakKJ21!cg9nHS`e1KH zZO3$J0U6_1F);b$fm+j34<}0jTXu;N9c>MB9$>Yp+$)TR!hEj5QoY6kNDf`xx}TY;4WuDK(+cFVXgrD9RYt$F07270j6-!MTEKdgU8h z9O@XH;yyULgRNuszBE~G8&wK?A)3F%6i69Q2$$D0I%LCiQ;Hfdh|9*M%kF$P`*g+! zw|aPlFTgzR?qn0}{@5n+A1rcYQ`63#%e=tix^CJecSKT>Rj4y6YP*w1|Bm3XnP0@p zInwO}XVmkN)%Z#eA0?%H(m-_NiSAazT=59biA3!hQZ?lF_!fc63~P~WGXP%I1nt-* zYPLAzFOL&QF@ZQ#v!e^TxLYL+x{dktf=wf6R23ZC<;I1(w(k#x3E zf(dN}pD0&*h*EUB>1N{IrcVhIET{z%&9)VoyFSr8O%?l_^>Pn3@g1Svnx;VT($2|eYNyj z8_;Fb!FCiJ((`9Go!Pq0W1_}67~RqD;X~_oDX7$SG_-RTW$}D%RdY19KrmP&iaW{6 zjLU~S#4|qSxRBu~)Z}Sac`6(Hs2QYVm;atL8@M}%H(O$3AxGgj^Gxm1nv4C~=XbR` zJ8r^DjBtf2_P4#4d%f9b^mEg|#W}PXfPbA=x??8|Pj->wNZ9ktn9Q~_luEEB03AC6 z+@BVI@D;E&U*7y-O*YaQvP}Hlbjm4w6s+B9nfk>QD~Zk}e>b8^5eJ<`Idoaj@ai?3 zRgZp_8^|ICc|TC~@SB}X>{)#mp0=;x;!`!F&H+w2s~c*1+-$MC;8QiFYaH5|Mz0-G zWrHv6kOQ}$&DNw;Dm#Wns?Gu^`7!!pHtgU*8fbaJD+{}ju`vYj(0R8yZ>uFZy5o7O&w*?KNe!Yg$S zq7rng)*OmE%5T0WBkTGY{MmOjNZZ0$I%2Uj0)YP+8<^@p*R_w3hQ}bX0fqc0A*25l z|8z8UKs|$FpyA;Qpy|mg;Hfjo;BnV1(E7?_@LXU8qg@OC0N#%L%4o>=Z*z=l2TcR} zL8Ld2`T(AcZUfIIH!!v#V`QIEK=(g$kTEjXPw9mH>@(BG3DPA3fGw58v4@mPrzrR7q z1Y{gM1DOPmK-9!R$RcP2(hM7el!AXU8Zr+V@4Y(8IDWV9D5M0Bk>d~yPX+&i4u(!c zGJ!uKDfobO9IFP84d5ObH)SqEo>9xt-jHc%ci%o5fQ|3=-{?P(doIryvf@_fbf7*F)9Xbu;ZWv03Y~jA?_A=CY zdkLaf%roXU-CTmG*{hIk6pVHF8gwX<4jI5)(29k77<0R@HOM)9opJ2jv}Nd8G#$Da zy9Qas(4jq{>yR9LjCAM*wCg`(q*skwV>H=_4M+pVA9*bkx(V%r=c(UVV{ii5E(d=f z1^9dIgZYEtkN6N_=dSkK?KVcY%d2aq1|15q$X#$Z1_lf4AhrmjM@ zDJzg4ybr5dX7)QkKE5W|i0QTpaksFXU+z<}L!`cAx z{fO=7!M->WwsFKKAoG!C3hzh!gc%$U{9qezN&92-ed$Zk_uNHj^1%WW3daCB80UT9 z|KN|{i1-5pXNJ8;!24ldAWa(l!vkbL!iW8^k3i=CZTnzff#8qmM>(Hv=)d^?4*~wa z@F&9hPxKgkKM%WdhW?ZB?Pch5B!=q3_#+%ZVz+A81_RS$NDPPV8;Jq;Z_pSRju!sG z|7Pq46a{O*J8--QswuTwjA8 zCD9rF|4Awx`jY*}$LC(BK_JWpWR53{cOZ;=R^kQ}29FU9fy9-N*mZ_}G=T9}fPMa7 zEES^uj1jDnZ3rKbb|?;l6k#2RY(qF87qtoPjo4!70`;4lkXG^rBPQs=yfV5o_h0<~ zg*`IlW+gEE|KIu#uhcO{{YTI^nV|tiY^oVP-~g-vwE_nqlFu~Efkns+#vIXch`v^b zZ5Z(Z2!=?kNBTGz%cQt7 z|Jwh*IDm!YKOV;o;aG```X9HrDYQfB3baEfj-dgN7=Y+NBySeE*aPkL8)DRZB>bnL zeSr%M9goCv#Q!_P9B_miV%LbzzZJj1hzE!kK(yU(2Am7R^?|gQ4F*3Djv&52C5{d` z!p9?V!3frbS_ob+?t8yE=^Xd3c^L%(3`HI-~>Zj{}HifH{N22$`5a zJ>xaJPa%8}k`MXCs0BLTc?16IC-^@-MB+alsR6_rLu=vdtdWfk>{{0KY%t zS8gS(LpJa>BuCf>#{>lbJ+MAO@JIZCDy&82!8u6g%9sDz|GyZ|uz!|6HDDwMBnavM zSp$H5z)qbANb*=3BMu;1;IAJ*>gWgH8vjAK&WrE>sRbh19>E^bb%^a3-=srjuogt@ z9ntm({zwcMzqbfg!Z~4i!U`itK>Pxd1D0g|sR@|EaX}CE4;pY&f^|GY^TRw){!jcz zxPaiV7rp_R!dgEA&J}y%m=X=w7!SZX0pcIz;JF&G?nJbSDy#=o;P0aX$06;w8OC~m zbK-yV|GyMqK`}viX8b=f;I9whld)#RfxjF;>cP9t6hoqRuOUh2CdOLI0pBhN@dbIY zqfi{|yOG$B#B>C2#3qrrkNAAV|04~-A88|*ix5&5MEnAh`*+@3VsOU@_6dm1BmRF6 z?BCU4JdqfH_yokR72zJ)&xrBx7};Kzxe8I>Ix`YCjA2e7a}eG5F6U3}!5ZGC3i~6Z zMu_--y}(|`^L8Eh_wWC|-m?H`2#aQh@c;1vhz{J&cYqNG{>=fwBX=OACZuftg0Uv3 z?o1n91akqw5y4m%<^YoOslnsF?Evf>5H4io{HZx1`ti*z8e{?c4TJ+mVe8P7 z_*F;~&J7f=uS3XsfKn8!0ertgo;mOSi~oO!kKq504`8eX2{P7#|IGoUCWz<(L=z%B zkU5zT$=SVttUX>s$zT)o>1GF`mBxRE9>$I_Y#Z_Eh|fp-`@ix3TjN`7n}Pas7NOg4 zzK7I-5d4nAF~kJcgxcT+qz7v@_%RmHL6{4O4?z0A*dv@kd;roTTtWQC3E0hu|L``o(@>cm!;Duc1aoh{&b$$)>Hn9u37yTV-PWjGQ`$cSfAmfj% zBlv%>>W6;58DenZZ#;ODyuyeV2>wVd=rG)nIx&JhQcJp(4A=5uE-+&Fe=z@>2OxT2 z9~|ouTSxRlB%DK3CoeN%N>MVbL*cvt(GE!dr~$7nD8u`8umAdQ{{JuRks;^*!`^p* zWp!n1-??*>m`R;cSRBKD5GpbWplZ5X!fWL%og(h#ol;b0#gprUbhj&^WQ^Abm3X`lJCzy>H0@*#)u@)c2RY zAe&L+LGlSmkN2P)P`^MjB$<6X`IaT?)dvusvH@k+tJS8B&^q#_@gvKYQ1hHT8E--kLl<>Xc25vvqwiJ}#|qHOh%XyF=)7G0;ot^Xpla!670(dl+uU$FqjE<08NR7LWaN2_MBgqFKf5HTg1L~M)rbl#+ zvH66(_+Crtg39#utKTmlbUBXybRqs4AFfXOuVEs`|2Y=XnBz&3|6ON%|B(MJpnqri z@)LhIIzcq>{A16WCORm@SV75x*IufDQpK91E^UIgwLOh4aO<54x8dm+GE)c&50^ zvrj#jCkuqX)g%j~4{GGnK!aM|sL?SAHT$eYj}hs#2R=sD?8AoNzgcm{@cLTnbd3#) z*ORH&W%sRNzg&7=@gExZxB7T3$p5o>{$$#SqvEpBo;JP<;{mL(e-jI&@jl9c{((kCaz@CfFqvMQo#`bR&ahmtZdf5N}$KcO9tLQ6*GynGAkLLLa zBo9OfFFsuyYJ*X~*?83JHWQ79rek{eVZ8UoJNR_Xhd7e*17_0}(|Au9 z`{`CJi1fYUzP3;gghc&{@wD;O_fx-KK0xUMe_kg&ufCk6_r>3)Ur&F3HTLZrQoq-r zu5U=&p#ksLZr)Xh-wp1Q&!PXqpU^4kjPd=p3Ox7_|2$;>@fF#J&pq*M=A)#8C;nOh zB_Dkml^!XKk{mN|dbKf}D)&VFdI6~67H{w$;`^5I39(Ed7Dit*Hojs(G&U&QMFaBn z4T_*{CXR|B67N@~Ubl37NBZtMP^U}AtBDR2|EKZ&2IOnQSq z6JCG411i+^NBNFZjgPqPsDp?MJ%w=F4;UYQ36lNlmf z8W7Ibc%Q}l;&a(_!dvlOwc~TpVwPRk%fHi<{yo`v^%-6sqO}r*>0Owf9PsH`0-L zJ^K)GqN1;}gFyyso}}pQHomKRFZa!gip= z*mTtFyAUHHm)P!jnTI?6@E0ifQX#zf*eekJ1xq$V(W-+`tYr);bYF_dk1yU={HMlv6r0h3ejDSvq5Q9@mK(oi z$pFcCjq_>jw+Qoo%2DsvOQo!!A5eCHORkMCJ72n9I==VR!-m(H<4HSoo#FR}LubI% zXBrw0oQ4J+gE7o6;UWHa!uf~ySon+ot=M4;|8nkoF@XACd7v2yKN{ID|GdWJ<>P5j z9iToy7t(|JdPAuTH14Z$Ug0nPSCi})4QO9&%6!@XlKayA>g&~rzGC#fay}K8)N1S= z#w4smt5Gvhvm0$u_D5=Un1n`dHZZpx6&jAjP@kBG`2S(F@4UdmU%A5;{>mLy-nj60 z8gs$jVD)bPD{UVbP}aE99Ld{Mob7pm0tM3w4;;Z(gJDpu-(Awz>6 z;(sTce|V3Dzv2ch{FOUYzB_YAnKz(VOYvoO=H7(Sw=<0WKgD;8&udbqo4z0W{qF1w zDo>2{xAXb{q5(%cK*`J9I436fKK1Mb%g8ndbar4Git+`4Im* z;rzpUehYsqci6(eY|u|8|4z9gRVlY6%jN4)Y>#q26#K9Kq4G=R`_*yryT$(&4agSg z&GWW!%-ENHVQ1C~aE|%~WxS8VdDvd^{%qre60d7~Qdn1e-YH*`zp8)zt`G75!)V`m z!QJpL)I7nSH^e#{!e6ym#Q(~_RDQl`lI6tNi!u9(8&*vL$^WU7Swn#S-qsw)(>PB> zj`_;o6CKDFPzOydSdW;J_hCu@ZQS6m6C{e;0BK*~ay`|TM=}O9d^$8X0 zrT*bujtMFbWTKuov zE{z2#Zm%PGc?9#pqS-$fPW#@OwxRHryjR|4IW}jG9auC|hxVh!5Tq{@KNd6TXT0ut z}|iT*y>aKe8W$APyoUqf+v zZ5YF+91mZ{?G9ugUs%iUD}S$i{qpz72h@@41KIZrp#E1((7V&lp{w8VJMbSdVuVY- zPW^1Y{d{e{Ljr8RBO-01$Hv)w1E$-?M$WUvB+R#kCM>e~CM>aq&R(T@fVR+C+ssny zsq?njmZYSaW&E=3dHZ!tP5W$%w%V2~-EPj)xp!;2PxQ=%w%7%0%r&~sv1z}W`K|Z` zwuDL3ZT|lspg9KUrl%ld+7k-*@*ssZL10M zX0-KONehzub>;Kt`Lz;A3*2_19&n{iuzSW;xN)hzf?McSw4{H**(*Q)w`$(fR<~F+ zG%VZ@^fEBrOaUx(v8%HbDHRHp8i{8v4&MjQ`lC4U0z{Z;XLKi_w2 zP`!bz#7ouCJiV-Gk9_XfpbTEx^c_G=r}&9-8_tycfNP0ke*n@nSQE zz;Oisr5__;<;NJd@Dub%<~TO@DTc(cc`o<_DLalKX3fV)-10sWHhhBEbw`lAmE_6LYOwtzjauPh=bz zmo;MP`%k7mNT95sUQoS}iX20zJ?R=+#C~J^{*JHEyhRIJwZc`6&#z|fo@m+C7aa#h zqxbkZ7!a`m9?5&)x8ewb)*M4{+HnkD^%eZK{{Z*3Kfq(v4;Z=nM~vU{lUeuM@;y9O ze~Te2zc)?Ct#fpq-}>*7lJz~3c72E0@BM_N-HdhH_Y>y7{WB)-ID^q^enJTE5xV0? zgm3!+lQMrq=(e-)+xVSn5nE5eZ}~BdoW37pW7a%y_$vlXK9>3=nxV7vAe6}M|I7bx z^grdl{6E6~b=rF3bIE_jYpF(?^m`-4a*5Z8cPrwou|36gG)(0>`QLRu>4IZFWr@94 z5_3gpFV6`^=3{6=21d->Z}=~4%V|Vx{|ez- ze}eDkpD}j#1-P&J3E{ghV%q*on7H#i#;!e!&^;FnO=$i0CVXS}pU2`4FJsQZi0W;sdjEEf<;kWLbX_MZ(gs995h~hot-nmR#_yxADzaVJyw-61CS$G&;aq0Qq z!;z-%$93_)g}?Y;o!g2`WrAdU~~2tN7F~79ADR|mraac+t@QEw#V`N2><$pozRMY{~FHyP@~;=Gxpml zXaz>3>@nY3GFiMIv->B+A7cH0U6vhV2%ZNO16|n~|A%?US zfA}gU?Y)Gst(Oq6^=qRae3BkK{0r0myS@LX@jpxdm!|v|{#IR1)#nrT^8Z*mU$MOH zrvsgm?X;kH4`Hv?bT)JMW^t^avYMF+ssdHVA-eiQNERpu(yEVbjC361SY%*grwgv+llWnKRJtZu%F|h z{9Vz2|E6z^4hWm~;NdU(uh4Dde}%iQ$iu(rsIQIum#t7oRJBvmP-O9Z1f% z=XNJz?!vr4$%HP;fNpF$pQQ)TVjgLNu|J{<#d!B#`U|=+r=x!0Z{y#-&JZ&etk@6X z-y=2?!)CvWuuaD?Y5TVZ{}^JBdX)8w-pe+)ulP0_%fHCRyd%K8kAXQ{MiBq7gN$D$ zEjZFZz*g3vO1HP*?ZA>#!1xRxoaaReckYYW1;p+H7=mWD6W+;2!h2VY9MCc<<7b1v z`VWqB?0#Rj{6Dvk|Ed3H^gruum+<+<)C?;X^oyzIXz6>!aH)y!m9rt9m)$S?TanjA zE1edx&d(ak0P28FOYQsnaM@;F4tgzOyyu*s;kEor^qzJn{uK&4qfz-TXjr2^>U4<6 z>)em(R+Y+UMm_<<8U>mP-jRN#O^zX$c>*NVA_L^ zzx@BN_psxy@qfi+s_u$vFiY>NN%l*}*CpPv_ZpA}>jg0>Y{+Ik0|L4VjunvEPkYDn!xAcCsSoZB` z_qmeKd#}wgeCV(cshoD`jkbL~#bJ~aKO}jz;IPVSTF!2!c(z5LMiw4*o!`u(a^W^39 zbCd<&+V?FZO)Mm?VU+EnfiTj5u$K-aabm$w$O@ChfKJTqLi?eijr}M4U;HdQjlAcWj<8e{9ayb7`QL3RYdfappc8FB z*?h7S2dvD&0LlQ#{Z2gJV>NB@_2&)#%Imrv|3<~CL-_Y-+t>L1`UTA5yaH>C{U`pH z{1^XwuK5K%VJH_Rz-5vabvK zC2GQ+_gKPf)I=}Kd7mii4e@*e&yh@+NEs4;@H+dQmyCZPX!WuGNcJv!stH}nG?bm~Hz>WGqGD0$;7x#4`O>{}Qfnlr9q386kO}xJ& z{__7eC|=j#FZ;h|zaaDvNX3ZQHOl=&|CIMIkiuC$J^61u({3Vw^2LudK+?d1yU@T= z+H|{q1=fE_8aPQzKex*V*#ujD2HxN`lK+m_JJNu3f%Lzy7Yzvih+U*P+JEu`$sh3` z+W*fyUJ#DHGHNZSlMOJ-vwe zU}Eh>JKLT5-zVcH#=pt!jle+aiGk}F1GfGghA#fX_cZdq zPrwX}ieGE+52jz@TCrr4HvXOhyJ-7(Cu$z!92+UV*UpCSa#sH zE2M$%fz_w%O}4^HwoN~Bn=~Q&-@@H-sq>bTZdfMC&iiju573_wo_+z7GJZhd>f`?r z_P^r)W&d09U-(<`Uy}bC_mTal8m+3)EMIR;`gCLy$QRIlKCu^{(;n!@CBwNfBF*04 z8qaSRMm$6ZLEEk&a`z5ahd^LSP`yu=#|Hc3E z_xf$U3BU9lW5)&3P7fw;CK4affckwF4M+xv26j>oqzUg_8j!vJ23z`B(gJDVZZbf$ zpgshD7L&>Uk?b4BA7b4CzQee*bH*1LI&Wvb_i&`?`*B_N-;vuVTK>O0 z{K^07?%s z_L}VdMYqww^3NE%Ksg{9SVKJ5p1NUdy=A12ZKQ!Uv=7t=aO8h$-N*qRPx{~nY&)(Y zn*N6g+c_R2`Tqdoul%pu<^S#Yt7g2$f2y#KQx)=ixe2uOsqd4f(&xi`kIK{u^658a zZ4lW2ohbW-xokz_^CJyNF39eaA5gl%bNw|;*mZ%n^!M;xoWK7k{qOuzRWz^C6HV*( zGX9?qBa<0(vKl@!cbOcqK?{y!^g3Qk``>TtdE?I!{>Gmt{I}V4K?LQ%0`l%+(!pHz z5m%m|Z;<#c{^*9W3DrN899Tmgv4T2c8EGZ`2il5X5dXXAf;Wz48#%D%bT(#kyg)Q; z#s}BaAN_#({~Z1Q7XNGf*V6w6|DdaQjj>&ti=`Z8e{<@7U)E)<%6J~h0?qr-n0BA~ z1G4pG`wt?&4`*Lc{XO~r)VfhGsP*8SVtwYGr5^thBWB+l|CSwXrvKk3Yy~`~?nJ+o z!x*;cQ+TZS#*Y7v^9bC0o$KWPE%ei~PZqqDHORESlk(=!O)Ma8i$1)8`R}u??D6YZ zbMh+rn|ZCY{nCH3%Yb#KuhZVYZr@KELEDQsj&!SCH*_P~(LUW{YSu-{{~r-V{tsKU zN1_IMAnWnM3@a-Jm<+zP-o5yiMjrR&at#AB}^O*gTZRldd zmsg3g9e3fs{;S(*;1)eB$hwTVhc95p;gbkh{sG25VB>#Q{+ETn>OxxlFZ`94q52!O zqJE~1zsh#Q#Ba#|t2n^Xtkt$FxIg81B(fe%9P>RlCSAjhnOD$`I-nk7eKZzi{6y3b@(at?-;ez7 zPF-O9f~1Y%)CZm`&tuTybH~w? zAme}34^W(!B?m+Y8jCgKv5e2rw)_Jo=41U2CSFJOW;A1X6ze1GrXM(qrJsId;(bI`|XuK8sDq?dRwk#RtvV`>kohe&+ULh+BUUN%J@6dk@EV zx*ylemMo8_pD375{+DhZotOV%>3_xlmSp^I70P(c-;ok2%<}^%Mo)Agdtmr7jwR7AJZ9Yq_;36YW7eKDv@vE4W3=c1_E~)z zT35VAWagK|pM1OfIHv4B!G6L?q`dVR=6-O}V6E-B?;Xe7k4_l=p7+iPtUva(xn}0B z<7S_*pT6fa#BX{B@vAZro4E9W!r!@K4Ltp~7xLk+_#emdAI%+T_5YQ-QJwgQP!Ft_ zaupuT@p_BuW#6OJjnO^L~iw@L0-}uDD zTv1UJMpgZ~Ai~|#Y?bEvALKO#U#fiulAl}`7n}vU;(#?$x(6Y@ibQm}e-TdOwXZ$QX4b0n&v24->@(Bkm zdk5ndA26|jgQo3+)pSgaHG|DQtt);|+gkTo_%y+oScfXIh+YXt1 z!r5S*_9mw9_yE(kzJ>U8d%%1EOnf69zSGwrbi%BB@8S5Z@5goLO8NQ!cKc6rZIl{o zkN;5qr{cDSwPOCv96k~DdfxH}34i5$s9#{}I#D(#9#HfknIK!B*RmXRn9H~j`2cA9 zsh)R_l#}Q@F~9$>af8OTS_PdT{1pS(q+FM$UN-dbPc$^(oiLAbU^Rkfud>qt z4nvJXd2&%l7Vo%x#LMsMGzZSD6=+788TF((8;3$|e5@|}jKg=^}%T}VwM&Xn&K z);ceK%`UU;JBzZ2*!xae2>;**EB?QD@zQzvU-h3X`>!O&|K587=J*-NobK-Q18H1H$3zP)@{;X)wUH6upAyo2J;|L6OWG37wA~LG#c*e2H1t@&4fp%(2l^ z7Q;Vfk-0};(qhztsZg=XK_h}rN8oCK0oDOhEg*P~PsF&1DHsLVOF;mQoT`X@7)yPk}o=;XZL z(m4U7!LaaHc#gKgb4WnG_i%it`*FQOsY)nN;H7)oe`T2etMNa@f8}8>`Om(9=8o2U z;VJYDjG+B*<%eono;HF@$PENA=G!UiR}<^4c%RO*&(cn3pN#!6<@PfbXbKjPwXmjUW>@ z(52USd;AFVhm=F4SQ72Cn&Y;PYk$vvHh8;-z;{qE+=m1qU_=;vhljyu*m#6{2P1Gq zD15y_;5Rgw=LBN-kg@RT?}dIHhUR+@$9K9P*X!1sfYtgF6jJyXK?s**diw2Dg@;cbubrUE6rVyUPfS;62rRdU(OB`$+h79f8n3 zUI^|v0^Xh6O&jhu7=xPkL*KT8^1a9Xh`Hl4RduR^Ckoi{x8#4t*5P^apQSwCN3iWQ z>W8xaPsnA1?;`TL=KdMWx^Ekku9`VRRTFZ!#sP?R6n#Qn!>*gTWfeE3)-2&?Q_EZS zp7OmqPx=gQ6F)V1ACmpOLs#VcZnFQ&zECC)f8{5s7K}v)HOn?Zn{qADtx{WbckY1R zHM^rv)ox}vpiWl|sn^G>YkxQA?r2l3CpuPhgPU^?w5{C3EVaLDtsdq)t?QVzt?R6H zFZv(GH0}=XM!n$Qu!mXqZP*k3F5M8u?XmSc!M9F(^DKR z{Xg~pt?|F&?(d^5>;Gy#sK&W-Mfavo7yhaRu4TrQ^QQKjC+R_R%B!x!8}tL!2>F@5 zg71z0SaH6>y<@_0IEz0!{4d{RQJW|XjG(`X{rs? zwOnfqDBl4dWgS{2H-ks7iXG9HbDSuSW;>vAJA^p5gL}EQrcPC-a&7Xx$Nh-8<1d51J9Us)$-Mx zo$~Q^kN=Q00QQ*}zClx%yBoEUIi1VU*JE0~@7A(~tF83Quc2bWvMB#-5!1>RD$3e# zMNy$hSyU*Z?=D%OWu)$+IYH?G_eEy^}BP3vu{HbdJQ^e@zE0@u1N z^IE&QZP2+%yE|If#%>tg(#`DGa#(xHj+TAQvR~Wo=-rBR(rr+tlVYVD)mhidv-JU<|8mFb7|^qhrmJ%jS$f4_gX|CHx@t?(`XpT+;eU*kVz z`tL*~ulL|V`>$)z*Vq_;p0%Di21q|ptI&(4=94hj+#s_ezoDKuhPphr*vRAdykW+U zSMYk*v>M)T8{AdDyM^z1bQn7eZM{>?ykl-%CZK&I?}zyR8;I()BKiG4mi@1}qRS3S zH+7kY2Yq5{z?B{Mow4QQ3y@xq4`<(<@*y$&bA*N*!-x>p3L)O2nb+LkMX^B#PO zyR1XU&a=?B+Y}UcosJr9V^OtD1lqJ6hjuQb(Wl99D85^9e*cEo|Ns6cixw`OZ~Vvd z|7)Ib;jb95GM?mR%Jh=n$BkasveuYSv24;OaP>Z5Xr$P{x6Jvi2d+ni_Z!B35DmTD znwWEr(fZ9Nn7W>3&e0m9%zSgI@mjsO3(6L&g6d9nY`+IaYWxBh&(OuTfn(M%4sfHX zza#&>>hP#0fcywa8}^$q9F60s#jZSv2#yQ+&N^hq7&XqQv1a+4RIed$!P|&j`wqr) z3}_5vicFh+0Am~*&mGUi5H+)3*RoArmx(3mdoeF?4%wztvzbo3UQ6 z#pu%`#mpg8zI7BzxrC#5Eq`>XI~qf44nx)I!%?hESClMN8!tUu7*6G!GBtngy|AB= zw89n^vj_okYY;YT6MRzlVqo$?j9hTU#M~1zKc=Kt*?KzHwOs=!0fR1aarW|wAxE{Url*#eb{wUT2TD-4 z-jjNr`dsos^1W`qm8jTdfgSS>lTG|k`MN=d-z!xgg?5}*u1nSaXj{51{{Hu}c;&@n znWVdW^1Cn(OjwyYCT5+f^Q5si@m~b}#Z$I^j0DDCgsneq{D_M6nXv7wiN`YaTRynR zc;Aaq{FdUh)D*L&xSgr{FES47XU2+tZ|VaDZ@OsD-`LAomID`%dgLd>?7N64#&bt* zKW}OaD7RPZ%JG<#c@C5J{(@znT*iuz&zg9URiAvxyrGkZ1~gW9FIv9ej%obo$pX)T z^F-R~zjH27;a|LU913@sYjn79uGDvnnHN^;!oF<34Jg4NUYDM8Frr(c9dqUlRBRS% z=9L!im8*N8T%~@f^jc#SFIL&``n}{lYv{Se&RT77A2%Z%V;JWz%tOiFral+rbf)e9 z3h^1=ni@^>K4cx9gXb}B!_SB#ev0K>m~|;HR#)3)J($zU+^$KP_NC(dCuUwCZC%H<@2;BI;3Xej!0J!FGjt$1 zAboJZVSKOWsZiDlk3aep{{B=kyjrk6UMkZOFIFGJdMlA=-6_S`ffd;o9PZAs)gg0C zzfd-O`A#!XUc62j->P{?o^G#4`L1~ys#I)?D&<>d%8!4q-`6p}DXVQB30pD;N3O$2 z>hgfOZ<`uyipPoBb^_5m?3l;z{t?reXFZ?%ZSnKM53XVXv7LXIbzhEhZZgJotEq;| z3f2Kwbv)bPq?q2-Cm82{g0<>d<3;h?sqba8ZbLRE?csPv#tlU6VcnMl*O*6q-O#{{ z&pEI8p{pjxQ}rd{-(rm!=6i~!HlJa9Ynrrg6-jnq-UB*vaV+%}LnK^i3I)=t>N54eQHN@m?)#g)tRwV0s ziO*B^{>+%|UoeBQwvz2u%&o9qL44-17LRf|mLFqY2e%d9ulz0HvgV{cmut<*Y^?v{ zIyQWr%{-rMvwzibdoI^v(n$<+(Uiw0T2MZB!eP~RVeTN$o&U`Z*7&%Ac;=AAzs>ye zEanO@hj`1k+1T`zJ!X9S4_C4BW7dm%0QtX0)fxtW$^ViC>!C>nS5pH_GN4lZV1&1y z2v1j=p@)L?Z75$q%wVoQyJUQ`nnO^zq8rK=uZ*fyYGu+t>+)N;Yrp1gbdTPeDL>Hg zRZ3qAb1P@^@NE2+`CZ?L=j}P)8;RG}?a3Ky=*O%Em7HaFU)n! zZ(4dLu{S$ut*NVM0b)1+7raTVc4Xn|}I(~l2^!}@i$+g#V zTEVL3!Nkh|3$y)lv zWwvS2={Ip_{-Z4@Wm{&aQS|c%vR3kp1Mryhp^5QRKRRmX7pC7ecFT_#wCZP5|G|6R z&xn2N62cBJe{Tn4gLCsX19q}rA9ZsmaTvebUV}@y_e+?At+tXpE#6-wPAx6^q zk_Dm*?OXSyT@RRbV!Y!lx4D!Y7v>g@lILnVCOS~gxMYBG$R!6Bk=AzpVsHB{F;D1% zopz)H(x@NS9KT@X|AWT=7XHPbe+{KL2ej~4td(e>T!nV1RKYc~UY(}4d+|AAVqJO$ zrrY|2q%%KfJ3JD1q2H7vCdOmf%ukFzrT_dh7{gi*39P9qtktLT&%6c?*4^}A?GEK` zDmFaiK#r-?=tmk5?!nZ><1>J;LxAlqI}OC_wd0{&eARUj&ud*gubNG($nR;)-89?W zFWJ9^{4d&26OO`P`d_+SG+@zz z&UOgysmy_7eQeotJ!gE6{tH=ydHFfR>*DvggI6%)Q`Tx@zbfhw>wmD{6}aP9OegQg z(f(F$fZ=)aUSK-&x5;}3chW!vc|YPEHtq}O_DtI1s@Wj?CD*l7{`LyuFaF>7HE|=J zMn+H;Y@xi?KIQhaWN)4<5Z;zP&{8yzM+ZDt=Ue+_H%ga?|3wRLo~JM1N7)c|{2w&_ zm;GP*sUoQKav9Vp?Tk9rYs0m@>s@h|3}9V!n@7ktTi4(n=sbRhvEk(lmo2B5oC)!ewGf{ zKzSiLP@Naq0m5(#k4yGT7KpdiEO{W>5az;P$FxikOK8qywZ6Hs#6!(aAc>3gIYOpmXUu zHdtDGFa8z{=o~dm7HBElt@DiT;JJIhzl68h|J#4^!L$El%XRNM&_%rM_(whFqWMug zqqk+Y3)+gF(HSOIQ)6c%XCE=VuDtC*3(qjmlDXCVh#s69zVG7mti^ZP)I^Ehcb)wy z`qeV8o7~?Kn^gyrxu4|k#l%H4Af6ZR%a&9BYwicclCohI_eBs_@qY~0#qSIeHcR0y zIUrhy=P}h~6Aet|{*}aCysf^!u+_TgK>9%2;#o@;2usNV?cYSYF*e;-c0L#XJIVrW zi|=JKh$bvqu#WGL_QhqSpFV^1Pfj9Zcm6y!$8Y+etaEM^Ti>uWG-1)EesR0dJ#If# zZ%^`Fygqu>8Pji5{+60@I911MSlSIE+LoVbf;<-eIv8&36l)MV?)4iNs5`{Be{`d{l4_tLG*mpw08FIk{<)pn6Br*mZ2iQl!9T-bTezHRZoXh1Y0{MCfJg}vl}`u}E};n+DN z|I;3@{+~sYQ&oL& z?fky1)i>1nq7O?JnEj*yZHpFervuS|>Ho9;r}5wi$^N75?lN%P@=UMT)#%T8 z6^2A^H}lwZjIzu3KGRRIuGSe-J3+Zx;&s()(HNL&tBhs-Zukz?@yZ}?ugf<2U3Gr# z_1;*IHA^<0y-gQx!zb>6*Q|HpJMROG zW*mj`amDLB=A1>?b~~?++j7f}AGb5xjF;&fTTL}x#QVb6XNO%51n$W(JT3h$8K4@w z(*MF=GF|ohv}7q?!}s#*sYaLhUNj&-j%<1Pc~!$r_P=U+$qtxAK9^t4(gC6ejnPb` z4iG&^PDmz*E>z!h19@CBU$S7+8M_>i{ul1TQFI_#pl#^`HDmX4seZmi2U$2k{-$QeG zU1Ow!*IhAnoQBa)qp>mzdoAT78?n(&1K!(mh%@K;A-wThcEeF_^Vc* zuoT?{@O`DwHz<@dcC4aol|{$Kgg znfosOL-7=hpRsvQPGhY8YBSE-b;3S$upP;>=fvxtWH#ku2CSd`ekMLLX*>RON z7w2mtc9QFZ*RZY2vD;tdHB$$h{W8sqV99sk?z=79;4gn}#G9=B%6-P}Bi54rq5)yA z+H4k{$>dr2?W7Nu&{mUQUp5<4gjv_wuJ?t%cw90-*U1kg{Drl6T}_xLP!{N!qz^QP zlRz5On4aW|Yye}sQ5I-CM{>cE1=<$xi%ujLEW1F*B_l)=x>h>CvI{qz{K3S3EZXtj zzg_-s+x?a;CGBln|BwZ?ArZtpbffXd`pkUG#4M`6E<0ZGy$}29(&_Gte>OD?P0c*& z^-&wHq5F!P?6coAxJzcMew#b_-r&!5;VOI05r2K}0LpW3>HshDw@-Sup$XMW^~vRR zVK3Z`4B&kO$Bc8 zB?}VyyRr#H3!)Eg>pJ;!ExB*WdJAjG0?W@U8IY#~h`Z4r+$UKeI+5&`?_XoTstY9i z=WfXSw~YV9Ey}R@#;?rm8n6M4hO^!#LgM~%k_cdJbzR$i19-o#e8%bt^L zkK?+0`bORpf203%<$%_M$lUM9F!)mT%r z;#o(oyNLd4u9*J1#m|1^LE$YPa>U>2U(2S`xx(MF1Ed$?BwP7SE$pqO_N9{7L<6$j zr7JWC!vx9-=>TCb-=3D1J)m`AZ`pWL57_m-Xh3$IYLa&nWDN8eMzJ zj=SW%W$We90p)@ArF~_u6Klo%$nP^_^8utTT!Zv&do%wm){fW5&rh@U4wz>f9J&;P zqBoh^w?n7B1!1oG*Q$G|d61;jWzR{r4@t!perydu1<@272xzx^45Bm7m%U)PEM)k27czMUiflB-tJHEm-4NDeS@1XaPOiSjy zrjeeEEFeu7%ylo}E*j-Mq#NWj(l~_Sf6{<#d`DRzf6w-xvndSh_v670PQoUREb!YSXYtrY^ z>q9nNN5ADa$op*6>yndU{9fK$h#}|TvGBKiHrnNi zXVHLkdJMnmj4b;#7Vg$kv>`l&zsC7A#v|Ug5j*jH2r&}oR*X*w^?>?m!d^{%KsAjE zLFDU|MjL;ooX1m z&#}i;m~qxM-*6t%AB;X9uaH^@y2+{O!2Pa zU*cuqucdfc`?Wra-^=JkVv~nIzvEPWZ!SajNe}QEHXru!bgk*{Q=aoN^LXCE-dY;{ z&u_h$cq)EVeqGUmbb;iN<=YFT4AS_o;y5)Ik8qb9kdI#DxEk9reL5a9`kYHk76@O9 zudP0Sj;V=8EZH!fzpIwO^9}zKcRi=pQ%ILH`5V@@d=MJrksTl!5dO0HmGdE+PxV1% z_u0Z{V0!#K+aKk3>2+J`=FDM1iwv(Teo8rwgJvFv#{$lA$&aM@F;y=~F%@Q>5#}t( z2k*a$F%|U5jV6zKbDUNEbqiNJ&N=YdK;9xRtM6{{t}wg3FK6ii_1!Jq7*ATTXuul7 z5ucCUm2Ger-%Adt$&L>stx4BgnBTsXUsrlS@>NaSk_oaQWecc}7sKCFJfD1kW*#=4 zud!Q828a$chl}Ki_&ixS@;>U@OJ>O*YIESAS3O{!`QTAz{{1M2?>f`P=?c{6|k&Wh>u4 z+E#bK;>>RTE6uoz?71Oxj~L8V!+7M%Z|!xfS-V{ItJQbYT+^D9T64}!VqEmt434c+ zo{wjI^q5___|rdU=WEVQw3mKXeplh^wKdz|F8tLjTCtydizdRTlSKoT-nYJ=wzWTo z-_)Btt9!_f6aO0-z-0)(t>#&hkHr!HRDMS_`E@lnm++TfmmJXf!c2CA_G`>fO?+?W z;o&iMWsP4}_)9L!N2|Cl$#B!>mmKGP^JG7tF@?t^+a)KY2P|KZ@VDA@{tnG2`@2$3 z7#iR;qIbpo&f)Q?%Ku>Q&&;gLSbglQiSt#?pK8D=FEK1~27Ctu|3kdbc`R&o+sC73 zx2b4MCe`>$yD-MX(@>V5M!YT`jj31efV=#%^3Q1=@(AJ_#(7RAlJ8~DcoB;+dpWn( zN8-y|Uk&AX2zknSclqmtm;7?#eXUzOFZ`{2k{e#671=@hw!+)O-=Yb9n*hoH`Sc_M zB)_eGyq0l%CfV&8gSBYDU@!dHjO-^?ipyR`9OdJao}W*i7vGEDt(acXfVQo9cvSrLWacRAm-e(4XcLwim-jUBZopI)x zOImY^Pd~yrJ~+>J^xktOCrNd{mG7&XurV{1V!TfTW==`@P5hm!_jGyPsY7P@+MX!i zG6MAnB%!G%u@B5d^KnPvX8X*HuPYYb;&bu3g}LRI4c>Cy%xNNjm}S$*u9Ht>IOjd_ z-G39~-o8ouKgak+&HM44r}Fzn5t9+*|9jDZbh_rz6g>oPx8o=I=STyR0h7olIyaDf zr2e1ezs7JZ8W26m2P9oB+-I=~cgH5#FHFVz#?MPRAk0@2PmTR8CZ@vL#Q2iu#rGBs zh#m|LP!4F!PV!(QuM>`@&o9h*j_i5yx%~dq_$-q3q61^!h^~2D-zYlM-jcXI@5Bv` zM`jy-PyXP#!Cmvb$L~IeX>W3_@ogvIx8evw7w<*P%%upoB_Uwg=)2l|jH$Q1{6Yyl z_gn>&Q&Gjm2TolR(RkQW!}m?cy=$;{V{C=$;;9ceWcm3#IiH6+`QEJ4pKkS$tZ@+I z>*jlhbMC|8#5b7FKKaueL+7Ti!}k+EsBa|sYW(sXpA{Wg&9eQp^rr7uaXO*_`S2tM zEZa}tDvIAqHiD)5HRqymmv7gX_qAw1W4np`P08^**?$)r5Z~(@(SRlQP3#_NKy$K* z1}s@%bU$fCbRfD|%eX<4+s8hc{Pycf1G3x2@3IMmw{(N>m+dztcb{awbiC0Aq5&i0 z*hk_y2?uUq=FuCx_9|mhIj=Wc{2|7(G51vSJ5Nae)L=h)N*aa-&Vr{$5P}E$-l6wj zF7UkVnMa<)i%%Cvi4v?;#+=y7?Lt`tXBwJ#+H)f`=WUndlV%QV%O|g8-&I$b2Y1cH zR)nPAuwyS8;5T+`!d@7g{!cCqgp=QwoMT+wSN3C;jFViH{0pc3F5Im#daa8l9BDvf zciPq*9U6BP&#Ngv@gre~sq`@}3&cRdbXBq6v-tEhR6?E_CF7Yh7|ceLdm1 z;<$1+?Yu7w2w=!n03IGP(tb0jFfMmqlv zSs;4g{8sYo#q7Ig?B3XSuaoa@aNOlOmY-*S^Ktt-$#&5^waLtTj^EF*T=J$P4ajzL zv<2kn6McvVWD6wo8%=rVT3&xo*Q)t#az* z3-{ZXi)p(kKY!`58`SC7X(MD)?<>F3?q^lb_R7zd=X-cqkjG}` z{8cYa{NHg#e*8rXJ?30AJ{`{uSB=fDIY#eF1Ehn9omb5Bt3E;WA?DZc9g;r0f|VDp zBlXx7L(ke5caZfB_^uJ`Gx&1uP4WGxZ5J_&z9QkNr4^^|N!s(~1c}=A-^zZ*=3mVm ziyj+jU+_FVm*!m591gyeRlaGL;lGzO%XQfB^96WsI7ck)V}Y_ghpw^v4~4sOadq5pBV{1(uX#4* zhtN`Ut}35L*Z8IVVwTF=y?yR2$9{}*L8iZV(ae{oS}ecSRHH-qYHluJZ_T%*bP4!wPAK*86_X_JfTrqT@?<77C-}Va<-nxh>2RScP#u<~N zsQH8f*i=(Wa}B9Z>2TXz3>zDZ&Tj7L-TvNnzAgMUuh#2js-bTEUTDxU7|p$=qeI{- zWBaQnrs^PTyiW18j<`Fn_n}{3@t0%QpEW)p#p*bIS8ILzmY+=B8qt9IDymhJ^xk{+{&AHeun+J@U6_{$~{L*>pW|p zXk)}W_F*`YvgYNyy&r3ylg~c+%^xtEbv#ttLG5mIVAXoi+P(8eYfLZvvyC^ zaT{y!Z$5IlvHz|9pG5j?{zp`%2c{txeu}8p*85 zB|qEDw?8-YaLwBN8R_LSGY6CA<&qCJ<(<#XIo5evIyTMMqSM?L`BU1FDTII=EZAohDQxMPoo33o@}i^c&?{a=+e1@+)}# zG1KC99i{*3I59t#cWnH|Phf0X-b*!CgyEohpPCvhTK8G}abA73aGo2ol6HS;w#qwea`_gY%dW}V~s8`kfPS+E}yS7#z} z>6;kG`-k#(@78pVnQu#TZl%3xnrb|necU#4bLrUK8vV56X74a{B1flW!fIYqc0hGW zMkH*&=;YNH88aX55i`(tY@C@Zq-|#}bZpffF14GWL;Vi_5cZ-0;jg+{W^TpjE23PL z7I3aR08Xxfpx@v403{3L3u@)R!qh}o{MNmiMFa8~TkEQ=F>KOS44!!Rrgu~GPR^a9 zit|+2mhLd~T#brLM2*{@@4dI!Jh8{s!+ zecta{zkmDEHg~O==S%bLNlxn;?bCML;xw+W#`xUk&$+=S%wLNr9vhLc(LBSzh*cOe zX|-t{6BnDgpERdjuW{4SCm0SvwzbcpS;x$h`>k#DDOFEf z^BQ&aPllWSY;+8mgKhyy=o~N|UB}Hb^QH9u`}TpJrmkzo#VlG z>oG3HyhCTdM5t*l!Jh8%=rTMKZtmmJzPG=T^O|e0X}yky=c|>djwUr){2}ab;r}=& z2l8sGlqla691DO`^?rGDAe%rU4-eqpmjd9@e}@j>}F1#+ze$PpkDIoqLW8 zH}k4m`?}Ge*=y zB!=;Pci(WcJ)l-BY6C=XYj=1_WG)Y3ROkfN)1rOsim<8L>GQwB-r)bpe|mh+PIe{bXTNV^=lSWDm+G zAit2B{DW$hOEfXf+WtqDs@HP+dAg70J<($IWGL;KeMEQaxQK>{}bZFHcg9qQce=m&h^+()okN($xqrhJuBMm%Z zYV4XiTTc}>V*>IES*=u2&T&(!9E!bC#x!gHpIyHCN;#A+QQq8J_y4_CxpW0n14eV} z{NB0$&f^tJRyLUZ-ZSXD+OO5T<6Xqxs&}JS=ILT6_V-s%>eUjcTfIJhucqC-Fn2s= z;V&96dO&i3{Q>y|=o`w{USj<{(Z)Zs6?*&?sNL;1N$*{9#oGgf+}uxa`&$KTa{YoC5! z@BQl21yT617xTV*p(kH7&t8M|uUa&3g)UvX*c|cuv+JBw-S)&^3*c|${l_Q+{`SaI zccXoDw?;g{m=7$)^8Mgg!k3`bDvAs>ppqgx#vFpKYzn>Jjc4P zmipd0S2$by^?RjWE}r+BdGGG<8|MDG_qBdU`y6@1y1(PSt>4i5lz6pN-fwEZw$;j0 z&Q>m2p0!JBpj}(eBgr`ihYs-kKgIpe(#^x`|1-V-fM0UoB#i6&JNHNn-&1T;D zf4P}|`uWlw!`UW+u?Mxy*uyj=6<&xhWq(`j;Cwe@pNwIJN>`@id^BB zd(Xe-Kb^-NevGS+IX;}WPxGI{-!nFc4X!?ufAhbJ{myoy+m73*=GM;Jw{h!`*8Xza z_8pIZ+wo^^+b(w7cB9+2!}4$Q>*o7?@=U(%Vh%i#yIPhfII#_2`^$e7=l?(V_xEQC z&MI2gHLGlgX<2TgGO}hyew^hK`f*m7j#-7NkIOar_^SD!4)yIF9RVVmFR?Xn!TprJI3Hvmw)|i7?ZXxMq{@m03{?&gg z@WQDVO1h$i+g!9CdjwfCzQd^SD{u>C3|Zt=?4EfZNpY9anEM)sT}HPs#@okm-F6Y> zLocCh*cDU`zl>UwuEL4S+LNxJQph>HKIS-D2Bzy%|5N||_Sg%jo-f%Bh1?dR!I+N_ zJn*nZ`h*RL2k;a8kq$hfMQ>*&RG&5`^5tjqX%@db2=xPkJv9F(7sjS3MrQ6(}P z)h6DAQ$#i@hTTMYf9CGS@BXJhKj(Nq^+NHMDAG0suMd9*)q}o6vyf|yKmQdY_{?jk zUPW5cRV?Mwhx52cM%}jH@4t;=R&P-s?lu3;G7GwyW^q_m1InzMXmnC+A(loS0v+VcJ!6jrtYU z^_}_L71-MI+s~eM4NbVOa#Rkga=Uuyw-`8e??3(d=>s_Rbei}p>hKvW^V>U3$U$|sDGArnBkCrG zM&E!dkJk?W4qhq$eEOj;`&0q?AD(=M^97XZfLCh!qh{B+SQfnl+vAVpz2tMawDvqM zZ2J-4uVB0&zkQDhH{d?$SG3{tI`i49@I9JweMbu8N~3S0X3P!J)4zs(UVQe&PES1Y z_^AT)Rs8*lB6y)tJ(T7g7yY{@U}9(nmPUVx3o9?+(wg)5VAdrpNw|iQ5x-(e{5332 zx`uY7chQhLpF3*Gb;e)ZMEh92TiiDolDzMqPCpWEMP4ZS=#&3b!2hX7p1l5IffrEd z`AYO<^h2{Ab1-3i7LGD*cz4nj?3#TUN5}_}vDYz}IBb|fxk~v{kr>n`?YD`&iH1{t zMT?Y6Xd8Q)dFA{6CC_gO=pru_s`N~Or*^*l=yNFZQY}<(G9F|6_hakS?+``V(~t6K z1nH(VX}>O?*@e$uiOZTX*{BnL0}Ur%MTZ%`pzV}1XchJWMkVk3mp;Gs9Qt$a74!GPIt=@p3~zDfU<=YRFZS6!Zbq9|Ue=7}-`x5H)pcL zDC7S%Du-T2Eq?dt*lP%-jIR-4*S!t7Z*UZKSMZ4&HJXe*C~WB zy-Qd$`LA5+`JZ~SC|=_87wx-~&;Jc7gx)~w2{*AYk@-`UlPxGGEArb{3gbJ`o@f(r z>eRpT8SnL51)qD-rO=a{_bT`KOZ$C`3bZ8}llJRSPPQP=I#0|-jhLJ0Li=KL1Zm6f zgn9m^PR*CQx(v+fG&nxXbHd83LGe4X`o_PR6*%+Ftf5J7X7!2RpEW#Xe^%_my;*S! zGPB|r?9K|Fzb7kT&YM|dXT6!_m#{g@Heq)7y`Jy)j_LcC`CAFj&omOnIY;a3{%25; z_GYz7*{Bt3mp2WjWTRnnHX3ld#l&l99%cXjHOn;0s^4@tdIv8y^B@PMeZ`t@KQia# zEb}@T2fm8-`Ks?RfidDU5B|hB?Xw8t@ra#2@thwK#DdyBiQDJ@-ZS3oxSqc-`B&e+ z80n`xZPGf_sWthmwb@#wkY{IbIfu(>*=RfCD%!*xw}1Z%4YL|IWh{2^Y6Pt2Jdyi2 zS6tSwn9uy6#J95%$oypAP1($$%E7e5H<`=GTzJ-`o{*`z{8+bm7h~z?@Bh=!FZuHl z=Zb+2-m=Vf2U?*9e0C5Qe` zp8rLD{~~>MpaP%2ZUSwxsX1sqCkO2oWuqIPy~Cm$^yboI**_iXTf%edBJN+~+=aSXU zbrgojZ-D2L6BxDrB7!nlf0EyM(IcEOn3 z*pCHKVac`oghZMQ( z!}w?O?@;hB5B`;~e$d!(pHwhT8ez=bgmn%dW6uJ}jx%`o-UAuh@o)Jt0{^qW@FQno z8Tpo+C%>wDz>;9G&yQ&xVx7{DBY$%{i~s4S+8a+18;tXdPZ9g`6uDlXQT|t*w7%r% z2erS7;xzteh|e9T?SuK3&0lw+Ye2j|_E@X1H?hRHKPR_OhFJTr+54RQ#FwS=Z=q`3 zW^3h69#q8&3W6M=4K6RaToabos@$0nZ6i4|@ z@K@h|juMJ$K8SziDSiCQvpmZfe^evxlk$ch>H0x0wwJUpe;J|<78pC1mH``N$5Rq) z`d-Sv=_JE8tC`NU$S0P3Q%Webu#Q3skc&0FfjrU=l6x8}4HTH$NYUF5QbPG5%BX6h zq>2VgC~KssLipecb3cgxDU($A!-go(I2}Kl;?_h{*LH&cSEP&e=DNg}q>D9!Wz1`G z!dlK{8{*X}?$h$D(^CF5PsudlAvxsTA&2zu$Pq%p=0vRt8f{uKTBJSBm@HMS$ys|LdFVTm>kMbI z*Kwf*+U)2|jyg-EM`t}J@W=Z+iCYuOMRrvz*DW-xsD&_*4=@tT8T`Pf|?i_)=k*&Z1#nsqW;AOf<;AUk$tpA?OgHDmc^2224Qbsz9HqsY1 zkz}gxcIn;ct_Uj`>?W$?xhFUBqPI5jQc4?mAq7Wx9_dGTA)Al!)@^R)1!W)R1*IP3 z1r@gPf^u7U$>q(w_^k(dUTeg%?>_6#o-2%>4Ee|WrQt>j_GL8D^AsuiwvqnIqtFlS zB@>52nre|irUpTzHg#dQ`sc>GRVQoDWOO3aDlMXO>$k2iX#RQiw(}HLeu?s%Zy+89 zF;h)9X#)VP!>ewP=)f(CMK0y2TEw^2-K1E6nijWSBXRQuirakPgXBk5c^ZG%U^yD2 zyo5C8Z6af|v*waA6nPwYkx~@-;`gF%84MkHg?P&&+SEbY{dZ#t43(9HvPE>WC zQW|bi&Q}kp=*$z!Ki!QO%@>$!Utzv_fjHh*wCNzvAK zef-yTFg|;MeTeTIc*h#980)vDu3l>VsTWuqPpGW<+z0Wmqp8cEI$G(uj*?NWiH@aS zc>d9$zNtrjT@$}L>ACS7@Xt6}jhIr;N~{%+B4^+k#Oni-hpi!_unyh;{zYE_i~j3g z;0a=#1KumI_EI(YtwkT~W&C&cQp5eeWBskZIyL^-OGi2%QB`Z(2k~#B&mXkh)mzy^ zRHNk@-%#NKaLttfj9OaINx^7qPhjjO0#hOqSPHAK4=KPJatjJuUuL7-V_SPE4t0qK z|4FDv@p-H{!Fv_zPzzr7pbqtD{{weXhX-hP@Xh*!mAdPXsQ%br=Rc<4z-0Td+Hk+L zhN}Vqptu&^Air|N?^YxC?moor@B4+k>v}1g$p~b3HTaKg0`HLF?U0o+tceS-&WuGr z#Dn)lloZry6ZQb?9bmlgK^>U9vpO6^9~^p!0{LNmQggM7O8(^gTh?%Vu)nC<+&^`H zxwELH$3FF+6o}*i!O%OeD2H4(ye9YEz{LX33`Z_#KlsM}iDB1<;ymmC_8rZTckow+ zdgMW#W3k5)q9oxRO-4yOjdvAg2l{9q_?Gg|+8jI|eA5T4A8IfEK*jaP-b;RbQtBox z-LNljiKyvm;O5g5R(YNL%YUHd(DyS8g_x!u+HeT`qKz5mMg;g_xGizumGQI@?_PKV z)}P>?;j4&neJl8nLz~Cr_XH+KZ|abSzG5W<{ZNSdu|8nDv%=));60q*#rXNn4XUhd z{;&K4cXqIMT)CrH%E6{3X~$nWWL~0WTl#Xi#vOT1!Y1HM?gr)%Fk%>HWIQnA;=l)! z8HOd2BE{5!Je-AGUtoK1V1!@~76JaF8vDkRY}6|edt27_Om-5`PlE%zHsmY2fqe47 zD_~fOmB=*<{0brH_<~P&U>tdYe}-?46latMo>|V}fO@nu@UPe&objCtK1=Z4=7OIn z>=D^MdL{?jrYi_^pO<*BLY|z>%of%vMEBF2+sgli}8uR4S@`>I(XJVUeFgvMU-`B0t# zccWWcmpBP9V!rOCLaa?vfM1dbOywZp^7z!fB9GnA$rpR`$V1p4B6mh$9q>~21OJ2- zT#rKnp`x>WSSQ7&UjUP!8+bOB=UO-Rs9M~N%(3jni$!Ag= zhYeV_t=oAD*fT{8dt?jaoqa}ve>Dwj@SlrV;p1eVagA7BM(5nyw5+%Ta&!mpKqsvM zmSj|YCwRF_*{APQTvI171n-c~t`71lzeC<-w<)fn1M_VMd6wOhe)q#~ft9zV&j>+6 zhI9$=6VQfPNA5u%c%KSSc49ByL0istVvpO2{p}qpIRR{jwhmwpbb!WfiaBtVA}ha< z##IYKfPG=>ebL*=Z)6|${rU~*FVm)|G>dc=#*i7qMZk+^wYCMNm8>I=Vn5YFO94c> zGOLxmvk~u{cMN%|T1i;hihVcEfzhxcvz1mAHdAnZGldj2)5>hzlhRBsX|3d%-a-Q8 zw{k;q&upf!;%184+DwrsQQIXHUvZccs#++qx|x!zk5FReVM^R}m;!T}$v?Z1e9~&j zE3SwZyCJ^K-2MmKSqs$P^3IO^KN->{Bcnp9I!>eseV*=IV0@u2dh=pP*H%cn?1*CI z5JxsEVrjvO7+UBdLd>CvmamQ@r@$C;@Qo!W|5$SLjX|6pFs1O@JdaqiaQ%|_PO)UR zG>+!DB2I2OV&;|!$<957midZknYWOZu8bjf-)Qn!B_xmF7{tH{fmaYi^W37y7V(T$ z3;c+0yogLR`S(qXHq%>KF z)Tg2->yU=3F6pW3lKwOU(wT;MIW-;9QDsF}del}%Y?G1!;x7<`p{PfyN;oR%6V}zF zGS!eY)Y$*<3>Dm~qC<6WyJFM&-j7(-;mMbal_=qV+M{A!v`J(H1O<^ zc;=WvW5m2cW5tLw5KkI99>>vQ`4JPuien~<4K?*+=33jT{TAPEuQ5NYSkp279)G?4{A)-)8e7ruEliRUp^#3*3l25-~WF;;SYihdz4NfO?KHsMxpDhsY)CxXU!k)f9UL`r!Jb3;K;5CaW><F}>ey~prFKB)eT{@c%IgNAue z7&x{|75c=m^=Bv(_Qs`^J0>d5HJ+{=efmYUo&@ zobqCt8+e?)h9A`e*h39qJ7>OY>aa`9M7^z&Z;?fC1I_lzBd_qhzm@**A)|#OmF#Ki z%CE^m)J?PDix7vtR}~WJqW-pt&&e#HflPFkkrw*OZL#m)N`KfOSU1CTtMK zXm@7QHBIP&z3>T54`}D}HEdcJu88OSvl=~#`;L)~PBG3Sf49;pq} zr2@F2HBZPhuZ?e_X3aUS*+SksIqZ|*>(ca^irQZT{~5lhH+pE-6z zugPuekK~+ij6X|}&&_pQP2O>Z6r2qkZo+O7e91};1#hY$5io5MN@^&ku!=%sbKjf( z1i8t=u^9iR`y3}T_)QCwUI4rB74hLyJwNA1a?QCw4(n_9nqxIMUEl=R87?MwixsqV zwg)XR0Tu+`ofggVAc2Jk1>1N~n6(?N;5)xJeYw#*)PE6K`N3Wk{fKf>A5uW{Ez(;3 zEt!QLp?QAAG|y%Yf79TzPYjq-%{I*KX-;Df03Cj-_hKT z?`G}D7uY)g?i%{tcT;x61mV~z^J$_>JxvbymJEDPkg1@Wlr1yJK;QTEOm({hGu3Ry zL}t_)MdlwW3My%rr0%~g$vbjYBCNS4iKxCViK)LPiLA!=+G~={Ef*!prIL(yY5d;# z_%V<_o(1XKX2a%GNIDj=q^{$3MSa>re+xTLBmb8UrosxhoSJ z=L%9!R<7Fq{cDEH7L@P}SM1 z?@eEQiiWrLBz=)bc&?RO>ahfm?Do4}+ip=9a>fS(b2huZN2*g3BF{?<@TAkA4`R93 zs({(daGdvcAm`3qmUD&ig4{dzduU(#rT3yAzolvT(hYS2uhf>-6#(>K$?)`RyQMn6 z1n5e`q0?h}x$U6Ga!|yBKEtwS_}?r?-5!j8b-*2GdEns2EY0y+-_b*5Cw_nYU6s0T zHgLo?x@Vs1a>=_1Ox(xN0lkE74*IL3$iD%d;s)p(!=MXW3*FWxri;6b@g4M8uCrv& zPXm5;{`o#0Sg!K@XamN>!Fw-gXLI|1)ITJpV))ABeL=7}TyV&|2&~!%$P0wEcNH+B zp>IpT+~E)XS{U?dOfSghlPu^nSsO&68m_OftYnqLZXkODqgZYIXV=I@wJ?-^}|o;N8zfBxtZlRUI+ zVlG%lAVTW$^nb z1<81s@se@4&Wb#)Dat5F6lGCH@+69KlO$SGri%@<^#5bN>4B2r*QJ*!9)u{(?-pn) zn*U@G_Up&O^&X+%*0-O3;N&9|=ui3$V|t3=C_I$+)l-ZZqn+)%>Z>l-=&r7a#D`tM z@ejMSqaJr@#XRoPjJ(^mFt+K}aeH|Bzdu8UO%hLpUxH)QL;4zi;aP}p;!n!+MqWaFR$ck^z|JJh@edSP& zW?}!~gmt)J>yKhP`|z%{`ybIZj6-=CdsvBU_>udq`>{-t(qEGDTI$c}Q}#e?w-Z|}977cO%35!w4ERSUy6?h~%gJ|GO;*dR(1v&egf7Hf-LHq>kk-o;%=Zg~uw$7|qp|AM&}c>&;?SbOyJ78 ze{Ef&MIL$I?)5GG;blbQOQ}te%~vd6OC{#2dd$}c?_=$7<)?q~?~}Zj=aPQ*%ix{Y zZUn%l9lRg@znCl7Iv`qt`2h0}%OA{g9F=3w!|bBf?KiI|8@k&qNj-OPP1U{L(8gC% zd!X-L+;@!G1X*9f?)}CNRlsb2SVJ+t*Zi}ODXnC0s*0|CmtEX>axJ(H3~68{H{OIl z;0+4ib)9^+U#H*-j*<`DpxhRY3XXBGr(CDV>I>u%QE(Guz3hnL^5>_hSaOOgb2w#n z8&1!_hBGp;;bzXX<_rvNI8B|ooTjcdH)DnkXJ%}}nV8JwjAq!>VZ8jDwe^i*RiirrQdItN4VaM((i5gN0sUS0a#iN_W%F@ literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/manifest.xml b/src/burner/win32/resource/manifest.xml new file mode 100644 index 00000000..309586c2 --- /dev/null +++ b/src/burner/win32/resource/manifest.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/src/burner/win32/resource/misc.bmp b/src/burner/win32/resource/misc.bmp new file mode 100644 index 0000000000000000000000000000000000000000..408da009c0e17f902d50c3aadbc5e80debcce1c5 GIT binary patch literal 14456 zcmZXb2UJy8+V?Z>nzg<)Gg&1o=HI``fq7n^gZt!x?{(gr&!#nHyo^{;Wcb|RE-M{Dm>}T(DE}1yf zXVg1gHiEJ@|K{*-EdT!S&PSBe{`Qx5-ckSk+q7D3XlSTUm+joSGbkv?-`}54-rnAR zetwaWk;z?_l9Cc1AJ5qxT}Fq1fB>qpzpt+^{lmh-=+8~IZQJJN=H}w!vSGu9_3PKK zTer^9(Q!?et?n{D@?T2M(wQ;r+O>;ox$TxMTRc5IxwE^wJD2k@BqW3(a9fQ=6BQN3 zDH<_8W@ct`EgiT#F)=YZI+`)hm@(tqE*slrignK%Gt(92|@j=*ECuU0t1=oZwx% zcCF;4T(xQyq!<-=`F1F{koz!lT2`)H>EPh7eED+vz|J70C~O`7ywm%$43m@#8UjT$v`=1e+pIg;UC>WmgruBD_!YRCAwVQg$HTuDhu zRA>i;ZhSA-rlqCvUEBv_w492GiNVP@6VEV6Zq-f7;HhKaFfhrB$|waUgXb#lPs`G! zOBZ(;$lQl^j6QhP%gYN_%$+-TtwDiQuxPqH=A;WWac9yat zF(3#^NgdIl=A)F7NZ7o2Gb7>t^oJGXMO{YJaevTo3k|bo&4O#{)T!u;|8X+Lx8Q-v zlP6D@Fu~s59*L(yU#O<|BZNnL42>!O@gP zNdMN>Xs@cOI(qczkt0V63JQvfiptB&DXAA17c&eC@EUo6b;<8mV?^m%jYD_5;$MVNI-nDs!c)td8bNn+kyrFWQ28)*81Hp>xl5qK0%h={;vnQUq5;Bq@3nZ zGt_0vmNA`ItXLr@0@R3z`nUpzATjl6)20y;z|w8@?AgRH)JTlDwzjsYJaXhnSO5eQ zWC=)+00kYV0ECE-gbkCFY)pRO6!Vl8(i9iI|Ni?Q*lg@E|6p(DEB3yo#ldgpgjp7Z zDN93@+&HT#qa#u;*6PFpt?-W!my;~!17`my(I-Uo4G{x0qQ6G;(};muF)~sN(2Akq z)?vEehHr0TIuNlSGubIgbd)4#G61EV`=FsXI^qiI7@ol)^q~=Uj1I_3`Wi7}1jxWj zC@Cn~5gxFRh`^x^8nYWrjQLIr9v~!`4jBDE{`lh$2CV&jc3Q8swf)?F9OBzLF8Iy# zu(wOXI)n8}cC@HYv|di{^bHr@TH&J+e&J%HP7DfBk^6;-exYK5Rty0=ObiYewz1X; zvA>P=X{xWU-@0`xuyP$oL~=4|jdaJlOunKboq)1ZcRoT2FD~O(CqZC&zG_*58Xhd8B82|8*icH<_zWeUqKb`Q8!A_q{)_pNQtB>P}A)6W< zyzj+?KHnSty6wQLHwWH`ieK9dzduXwPBI?@G!D)FiE@Xu*1ddgNURBku+w zV!>hB!i$bXFD3ID&(N7mXd$@~6)XgQ{_~&z_j~>R`q8-m{(8|zBRqRf*)?Km!S3y+ zZ^m7!(>=YN&}u1bvDCDPl3!|)6<4h~kyq)2OQaYcEQSV)fg!>+OeDpK|`x?=|J)!KAC_R zq%bmt!I4_i$kYaz*$pNi;RTa0KxOGAxlb4{V8H+SC2DaxB2Fii9P!)8#u;y z+1x#mt`%`RZkFg<%=s;yr7zwdFqg+F88N~|CwwA=F}1@lLJSQRUx$ckIuRNp{A0wl zFvUKqb9(Y?JO3L${O|*VhYKR)qlAtT!bKwn9WzTZ@{#dl_y@Tuksi+w*kp2+Dv$vo zblE(}OvSZOOK?h}7hV8m0Mi08n3$BC%i(1zkrVp%?fZv!{_EX8zBl|Yy+-_P$bcSG z#thyxb5`oojkQ_951ynvuZ{h^dGGHfan|y@#w zo#W#y)051zlU~jaz4GYMBL)lzBWL{Zq6G#u?KDD)^I?=|j31*Xmq^dxE>tF-LB>mD zB%+i%z>9)hi<)3cDJ2(;+=M<|&hvvBO#FZo2xfu=XOb4k739N#0|)-sJAe4{%@-IFIzAd+a5_?9trG5N#JN0ee1w7^0g1nTtUBg3X-Y_PL(u_SSp z-9B`1F-Zw*j2tCf0GGSU4Lb= zTdB!p0+4T%umDOyVMHLj4UrrSEU3VM87%{&oeQa8bYOU_!qQy;GAm_HhL`Y`37Ko9 z;xc}i(embUDlq{3hH)#_N9G76yp*(H?1*^0?lovbpM^OS+?uk&U%brxH85P6suAO1 zWZ4Z?SKa|SF*s6;i&yNDI;O?Fm>bz_=UY3?``CQ%L*K4QYH4ZV+d*K=j2u9Wk8)u6 zfgxd1Spt=)Bm8J#kT`@Wl|e|fGeS0FsLbVbLw)YdC5X#HLj`wnTP~*qzCv8?)8#M^ zCI}{#C16N^m=ssmxjCYfw0jI(-*aBhP}e5s(ALb@-&blByD&jW?~D=yf<>QD6?t5w z_*QTIF80k7-JNNhkIY&cGhwQ~-4w5}<2FBk{#^1h43L4PWT=2JJVwPw3@sQc!^Wt{ zM*8qk^3uY{88Cs(z#!rh?u^j?53lq?cO>ICzLda#7jc1=)ZO~Zi7Zuy_tODRU(C<> z+O?^-ck7VAj=@37_hBL`QiPM1!&Kg0L1JlySflS8rvKH>>!SV4DEk4cruUvZzyG|M zz2`JGHZnF~83rbk45S!}K%~yGF5@hNmrDr^xPnQ_N3NCXQ(@##GiL4sFL##73b&v* zHDyGMfWu;EAxmu|e!?o(njPg6SyOxM+BN*i zW6`Z!w^)2{-@bk4&Yg!39}?KCO%EPC`1$9bdA^n=pS54UeEH(V3tIRnZO@)P&|wT4 zQjF|`(?9?RShS->?jETS(y|Ym3j81)g+J*gLxLfZnGu&@hPNBGdkO<9c}Lqg^_ZX2 z3tqq0e!(3!T4ktS4AhGe;bKgTu#FSLqr?=wun+5;qAs*kF;#eZ}lo_-Ep*aQ&#Kdtkx|DTcb|3rk`s~t8d*?+ZtNc8g{ZZsG>FC*z>@m zNBZQGurrG>22Td&S%7UnAMpUZXbL#6v{UktvycKvyNn0wnB)bPnTyJjnqZbjPDWgb zkK)vszvBiweYq&-E7zuh0j)!I9Yb^qtB-Ar7#}YtCJ6gfF+NdDW!oIzIXmUmqJUaN zB%G%$&@b0iY|m>BKlvj1oH_KICGmpMbD{_4B?JSxk8gpLgcdq}uo2M0Qy?_~5!Z{QG&4x9y$OVAovoI{rD&Q~BK zZr94QLC)fCp{2_3GJiiIo)_hO?cUUTXX`Ls$2fJJRe9}_gmkAd-(rzf(50$JRm4wTR|7pd$Oz}CU_*W@OSCrth zO7LkVTMrWf(INHPh46DXC+y^9s5vqpNSO2m{20 zmyiZfCU(4m)?AJU(3cd7N$T!ZNotDR@XGW>sqzj|^VR1r>io5h?id@VjEfhOlEu_? zu`pXK&Jio}#fm(!HotR);ngC)+N)Qu!n<*`Zc9S-rhRud=Dpl@>}~jYWp9%>&@2ib zi(-?=Y!I($v({y?gf> z3#z$tkxAHjzgBWn@Qs4S;2jA%`G%L*lOBQd=H80hr1LrzcErZ2r) zhedV_)hlBn#K;(7pCV>wh-KMgLy7RL7Tza2cN}}QF0}Uk{rm8)UZL|!uJSLr<9hg| zdr60PrJ`w2(yl27eozV?DMz0vhaV`1epK@BDA_lZoSRDC4@$~aMO$lucSnlKOD>XY zD}yIQk&mAt_Wj$WjtB}J1}15W$tx2YqT?&h(k{1H5|a{@<@yUdhQ3ha4X#Ccct0NG z)O&eOZ}+BNzO8*jJ8bmIym0l^jomIWGea!NQjZn6!nwH9yZn_;LM=-Vyt5YS*6Ax; z_BU_Jf4;rK>{V{@uCxT7wd}rT$!@k3+_#iHvlRVgDY&a12X9((nk;$Emc7?Ibf;hK zNIv)5Z@)1~NlmOZkYcEetOx#Wa3LRqlqRVu@eIMhS>`oSEqTGgAf*HfKuV@?cS!)y zpNv6%{(P`gzm+-tJevlGwDt?@7_L#gqQrqXF)3C|&k&3Di#7SerC6-Ywm4+Gbk^2f zxpIZ8W-kg|9#-O$d)2Gpky~-=_Of5S%i6q-w)vK~#hh!)ywa9)v+c;EwxS1ZdAHi~ zn%lCkwH>(pYu4pgX$_{p)HCoBw{ljp&;X0klHFwo4<4iu^-&pKFew==ZUI&~x{D4^0iEwx&GWkl*;;z)C7BaTkZPHF8a4V(&JBKfaIt^HvGssKjRrgmx z%E(|bHcZ`Cjg1ylqLn#&tgCY^s}Gvj7@n;OI>By=cwRYw`x>8=E%5~bS=E|?nxKRA z+xIqXOm1-A)8L%aupzl&OGZOrUPDZAL&C9!)DsQKRSj`R8+IM33qN=&AZ#DJ%+~$; z_miODk}n>4@&z|PKmX97LriLP

NmE({Twu(UIBU=df&Xta|OQ)19zT>-8Z)QNfe z151g%@b+7g({Ec--<_>}0y~C(J0nhv2t!5`SNn_r|sG<)-YP7I>9i zzkZ!~o-uaKqNRSTH|kwI6MO@92Wis-f-{^vGgi4}tntiP>zT2}T`fKQGJ--fblQyQ z=#1Ey481m86O!VxIs{%a6O)w^Se9V93d76KG=+tQ43DXbloFN+i}4YC@c_Y$Wbn#R zM`AgVDT#dC!YTT5mQ%EJU;FvzpMO2vsqf01fgVi@gIdP~cSMDEhKF~?N4%XE)-fgI z&Crmx8Hue9hNr7CAFNHix^74ArAwFKwfpA`dz&Tm#;jR4(b;{<7T+0e+h@72o8rFO z&fRgc`x-lUCwsNzaGC1vH`84^*FAE9d;DVepjlg1+pcDl25eSV7E_fl2A1@N;wTF& zKTFB!2DQ|YVN)mUNpUitvoq;F1rZ&j;RhT-3}9TseMsh%@^W5o_ZsT-&9dyV?$_hA z&mBYGEDSbZ+x_d^JNHYG&Jy{iIBzsrzA+Q z?uz{Q-h1!;{qKMO;DZl7`skxiKKbN}FTUv2tJgQ*eAA~-AAUDs@{*Z=MNp_wIWI5o z@ZrP2@=F{)%%KPaCP6WHIe(E1Qn}IUj!!A23~ahl!3h$RQ}~2QA;Iw#0mIn78NRNs zL)L&Tjgx#HkJ|C#JHHoxK`k!6k0yKE`P$|BAm@fL8!9KQ&ztMGd%=9Y!yGRr9eIzD zFjR6EN?||#_#+QW&z?Q|>8GE5`Q?}Yd=&cE6H(WHSazimwCJ0YlLINr!VW2hvcQ&< zlrUN;F$jR5ASJv+0(t>OY=eWE^u*{!iI;E%rCo zk$z%FR`a&Jhk+$e_BEIeUTE1{+Y(jL5>V6S z-1ziB-Gk8GXP^d?NG4xl$c?z&u>AHalMLgBju@r_FLY>xAIM#_!vYg^>EUs6GDc31896>=_tn-PnOEZ9Y^o}np@cjuiQP7li56DL<_QFrKP3(=uBQEQ=uTy zh*;1uV1_NzS2r3RK<2Cr20l{3C(=>OX!_#;I#7ZAuYdh(|Nbj_+eI#2lsR+Wfnl@L z#?FkL_Te zmApI3;rmL_L#5=gQu?z}{6H~WSE3t~@CGIMrjmS1$+@dkJyEJno#l_-4xR^bQVw+7lw^wOkn`gSE>vJj5tB&YDP#O+#;7|>hz=!{=r}*Jn$zIpLX=^ z-*0iBvEF0G1&GW>NQAR6Vhl zJ$Q5YvS9#qX4|^Q;J{5y5pL>bx*CsicSQs^#H(qUeD*`dEdnY!TJZMCDU)=#F|+ z{w&V6iE|y+>L+jVDz2H$W-xKPOZwv?JVOAJ*>EYOTtWwWVz^@d+@-2>687o#oZOPwxIF&BhRkQ|gq;h`x|+Aa zCoG$atN~|~j2{$3v)F%IBwQ4sH6pM^gw~1BdZDQo$yZfy$|=*tm8^?4I;B0>nDu-^UYmE> z@2-V!-AgR%i>!gCl!Qx4@JX?yOz6*x13!ubcSX)UVYne;&Z)ebb3)s7L|qVun<{Au z2NFLNWsk(M$0{Ok`q`RPg`-ET=Q+uC}(e zyu30lHGf-lg+sV;S@M04!sj6;+rrM6J&trZ=2@HyteUfm_Kb+ARdF^H3g<$hsS)w# zMQnqJt{3SyMB)|UcU*W?2%mD*3DE6s5}F2e<`U%St2wK_n<5foE~~s830Fl{vnn*= z0^5bGRQ+tJeDu2b>ixXzQhrsG`zV%Lauk{(E~JcE#yL-O7`&A77X&;&1wb&-l$--K zQMQ33bVc zs8LI|GO?*hxRr{Siz4}wNIEZe8^yj`>dPoX*SAXeR;qMaKZuMb5!3iDUc^OrU5$vS z7qOQ`e4|LXBI2)z-PhId2KM+mft1B!eSz3mEH)oeNs*G*iTXO>UM5_NRW%bYi`|z+%0-cOMST&Mc}s*h zh@ev<{i^yRjwObioOV-08`a56Fe7W!IT2AOV$O?%Mv-_`BwZ7U*G2kG<91S zx3}az^Db%kK5E`^?5%%Qr{=6Rq*n1bqqtNl+nAE))%S0kj*3ksV&h?6ObPD_5zm0@ z)wO0P-Z&=QOT><9k=!WK8^s=@$he}$XZ9VHI-eBXEOMy)APVn^+`A(ERu?Rjw@cjU z^IhJ%AQBsuq^s7%MoZj9bJF==GV1Q7=2h?Vi{S~2HHbI_O^ORIKhVG~lNjERTmW{% zQjxqpd-fdi^_0=GL%#Ezz6Zt^cn_nBRb-|noo0PA064LYH|>jqhKRY|;QjXH0Q zx?uIJwz`yAHEm?G;v!Qmb#3HQ|zV?-gsh(VEd{ z&1$md-?1LLs~-8ct$EGrarln4_?|WIjy3J35_d(3xvaz+t?`$vF%6y3b(US{evdof z7G3jPQ+{_x#!1hu(FfD^F8_etS%-&_@fC{sJxjCTHtT}CtJa109ZBA@5M>Uuu&zU_d z%q}J7%|+%-1!@^sW!_R`-dtdIKVsfiX5L;#PBU*SHAmE$(~Rcyi|UctXg+w;oc}}D zamSq3Y|g!5&TBFsYBm?%H6Ls?r(QG1T{6dB_$~I_>zMjiy6We_r9bV=yXKWr;p`f% z@zS#HlZOdr(p0y&@Y2qo>OoDALoJmBvupbP&-`Uxck$ZWFAJU>P&!3(Wme4n`AJU} zCYv~x>@jURX!0pG`4p;$|4~!uaZ}7?Q+%UIf7+xyY4SW`axO5f%Qm?mGU=;L0i~wR zc_!y9)23|GmOPW&VUt_FX-lrj_lPOxv?-;=lzc`#(&|lyOQ!ve>T!VbvMKYtY2O7? z_9atxqbcIlQ{9Q5btirbEx#LBc+GoX&8D#2RgR&q4sKcae?|zanGDN11~A4 zs;Y{lO?K*@tuj+VN^)j-;+egFuSws{_5ODA{)s+SQ$iZ1Yc5UKT%Msd&g9S=7qWdy zHE!8!bj>hsH5j)YGzOI#wbjPJ5~E+f(KXAs!Jt(Ig~sqAqn@(R7*%52Rc?&0GA3|T8sn*#UDh7H?2&oNbKiN- z%o>k9m9CMwPVTV|^R{kY=8|d1WO@>=z_P(WWw^Q{8Q7Yd8vc5Xk~nAQz&eY;NNj^i zon?r<7JL4lpV|%_yJqa-;Bl+t$F18lZvEcz8x7;v|IaaTgJH%N!(uPP3SaeDwZpI> z%-|Ml*cxrv7^c=;v<4TAVMEZr4mvFGG|X`~%yBa;*k)MhZCJQnZQ%}U0}QTV26v6Y zoifzmsWtdS8g|4O{JIYAu-rS{!82vq=GY~xf)>tpnLB!c>vHw4+K3^OGrS>D{P3mhm$9Bf1wHp{Yux#3S=p$3X3oQDwyFhWG8d$bQhw+tYcW30J61c6LEfAQ{@eg4*a;6Db~d^l*xhc@!C`Os#-hcr9wVd>+dQASzX5uF{6S|J?KCv18vCYsA z|8)%eNd3q`g*$LL-RwTGvF|#@eQY!8W1BIb4;lB(@TsFFIxJbn)MFbjANqim%Me=y zDX!c~F`W?_A@;8daEsSgw;lQfDFKeJrmy{{PPMLU}_)Nb&jNCA;sRwutP>*-8X(4PqVZETU+{}|$ZlR2Va z$WmV^F0XOuCbJw0qAVr{$=$d=-4F=lBOSouZYaf9;42Ieyb3RWfyp2KaV-v~8-EAL uV2}V;b050#Ej*$U((v*CPFf~S5yNtu!Lkc1bC!~o7iGJ7LB`&B=l=q84Ws=4 literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource/splash.bmp b/src/burner/win32/resource/splash.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1690a818d9ffc8857d5cd6a1c040bf9aec46419c GIT binary patch literal 204344 zcmZtv2Y^?_)%gGCNusfLV~w5On;^nc$=adB})MTK<9k|oo>mnl=GI4vzLEhs1` zD=U-F&(B}Hc=5b>^RBt(8W|~Buwa3btFOL#)~s3bN=iyf^78WL&z~>VR>MV$7Acph ztgO8D+H0@B{`#A4y6J`+Zjj!3>#fq8Z@&4KTW-1W#v5gR^{Zb=i z<;tq6Dg&4^XO6zg%gYN33+K+AtLude7aBRsgc@b7v<;iA?I^cpW!<`U)C|eMj5F*Q z>Z(<%mM&e&KC|r07&DP^EoxV+SfT5ptk73zNJQ7lV{)`LNHT5Ow3#z!#&lkF)m2wq zamD!Ycucz^|EEl4A?TcMtL)Au3VE9bVXLgvT0$>G8urpxiWhumYdC( zF(cQbfvL5Qk38~-r8MnEC8f_T4It)?9+q^wvh23>;dioTe&+}f(Q)>fQ- zzG`J@5*eqQ!Rqr*7pr#@qPa`H;DQUzJoC)cPe1*nlTI2maNyvRWvD0kvZITw=W z;e1s}_<2b9ThvC?|E5^5c;mdScl~JQcoqO)NXPj{cuuePeG%13z zkZp$%T*yM`kRd~qL#$6$5T_85^b{y3sDz{xvORnD?9ro#=0k@L1^apDo#zrvuQ}nm z+>&2e6r+m!xv7(p8oW6)8wTlA6P^}xB@I#KGF5Rr&S|QZxJEM>D=zrzB7DH*n=3PB zm4iE{G8{mO`G+Ak11qOA4U#F7X(U{oeW#|K7_%N3H;oY-HDo7@1cT^{jFd1Q8RhaW zoI!T1MO1MZu1NId0$mH^x(G*-@=Ow!CKH!tNHR|8b2AM!58+N`#@zA>p2>e;!d<2E z1T0yY{5M4{WXCGCL0mu=(J;ba*olULAx>54BLz0gBZHy953P$!i0zPxjkPd!?o{>; zuEHc>(5AwLm;{rl)}@8hx-A&C2+04L59maYkt0X)DCNV44?q9>^YKCfj}-K-iLOnH zMbs(dk3II--FM&3m$*$#uPMsTdU``J66?-k=v$z>?z+pEjlo*;G}jWm0AJVgGP>50 z;hA{@zVpsI!)aY9Plm8Xf9Roy*wL@GwtOy=<56HUt}84UIkRV-b(WY2G(4vGW#eEj z12@ni3us6@_0&_*2fbcd0jY*`ghkvb>)pFI`iK%uXv))}$tLPulnHl@LL@KZliViu z47|wXm?)=w-ZaMYDRF8J2?cbRE>k46SdkBh7UGEYjSQDl&T{mnm*~!r*f9*6MBXJE zzb<6>1BX#g-$J_(9z|rrNi?_C;Vn}7Mkr+`QZrz#0!EGzdsj;z#K{oLK_VaJS(wHt z0b@uG$>1@zrc#C|Xddw~Xb+t>{53>|~9 zYF0|d%0??0I?<`%bEq6m-$!3dGMw)=hl`R5;e@IgI7o@Gv} z*6?DS?EEq-V%D%>!^A|qzztbJqWGu;dg7W?yo*zskc4M8JoZ7Ke3rix15$YwG}lCx zR0%MpOt}``!n+6_4UC^h&`}<)#s4`ZUou5fwJ307aS4_tM=LcYse@*pp~6nUqMSa1 znzI=b8=aaEg1Cr)0br047zQckP;*OQlKFIghyFQ-7&7~uy57aXNRx}z#uWg zqLScI7a@8l`l3&n8tz-S_%>%qQOt^b4#waSOw@9l)pTEb#T98}ylnfUV(^$P-o9nsu_^~6A7(Jp z??*97$aY^fe%EE5-9}uO!JF8KS#H0vb|%67L@$isD|j3^VkAd$iaR3Dp9MrAqykIAIgG6NTN?3P&S;w zU?3)jA~z&hgB#GqM5lo*5;YGV;i;BRsOd$OdFEaB-+#ZEaqY(Js?9vNwn?eqE-f&v73zzElq8i(#kc4;DtVyX2g8vcr@WecV?T@1{Zu=CeV<|2dy;CTL36! z*{NQ_xRE$zT-R|oz>$2kWn8Dhqcj4Xj;sX*wcJBS7oi`$3lr9hH|j!nI&}${0l&FdX4A#K zLe89Xt#RW#b8X*+!VniZ7=t?{S%(Kus_Af=4Gt62n3_c*ZRV*{+w76el^DNrg%(A|Y*=gh#sk1hF2013 zi$`A!!yqvQQ+~8PYKo*Ir8Oevh!Nhl7`s_AGiKNXLL+8I7Zyd8sTLEhted>4Fg*7S z7&40M*ao9d6qD!YGK8yRAt1$+d!wbdMy@6N(`G>C(MKP>@4ovyRJu}*VVOV*MmGvP zGAJwpJi-|mF%BQ3U2<#~CuYE!%J5S2tcv|G6@78| z04mxtZlY2qvysb^#VLO_y_SpuS7Ay=QuB!p7Kn^ajf6y;a^p2BI%+up9^G?@bthq* zWnD-OfanF7s^aRRi||ACi4v({gWBFz7&Rn)p-nax)6u#l|RcSJ2%%#u+ zqXU@o7mmEp-c`m<7LRFU9C;x^r6Wd+%!bj6+!l0!1?$MNPR&d_1(qG5pYdfG=?me&S-G>JDQM zFR%vD?87ZKqNij9l|zOM!5smke({B@5QR##3egs(nqy7gs0>dlf@}1FQL2j2i6|*W zu8p_bi`2Dq8kQ%3Tz3x9^rDcVQRCypNqXa3Y z#nKR`@)4&@BL|3731p-O#?P&n*`~~ng_GBd)Dr8_;u@Z5C$X|pg)GE2fCZ+|WW7k3 z4Gaz5GPx+Hf+PC|Ote*EsJKh9&%Qx27?Jz7U;WDLDDlc>xf`-yZC0-~iR?(}m>fO2 zZOoZ7cgmEhh?_XkJOAxS;%mb8w=dgy%)ux_IY**Q1hvb)4{%QL$Xf0|rMy&IwGkYH zN&qT>iBqi{?8E^{8BI)nc&XvVjl%F4^z*FSqgj=j2h(Em-CM?d9~luhCTkgtBQ6+` z;(5s!3=ThkI0l_c163LOTX&yHS6u}Jrp&q3ag%gsa~m{cIbXx?Y$fzSmu!b)H z;srrO{8g?*Y9!GeNb#6u^khwRZB&GQa0*F?QPzaWgAR!Vl0ql(lZR8W5}2Z-9^C*a zyQ_eL8=ED6*W@k9vq$y1X5Q8FoGx6j&~$*bq_{+tL*e{+ z^XJZ)J7fBcDO0BMbBGCx;pahI@TkP0R-t3!_mtscM(~WB!6E2@%Q{&PMBc(VCtSa}sl9E#QMhouU04m*S+?kNV zhv8-$$$3OEXBq;WWp{Y^K$Svp3duB3UNAy4`)?11mIfMD_TGE%z5o9EZD2$$>!O_7 z2wS$1Y%7Yvl4qE6PIvFCKq*HUD(#T6nJ%3xTjXM47@YZD~+o0S*BR z9hhiHO%>5LYImg40O->R08OdIiWH0tGHwhSLXS;GOeTE|&9>it>up zt5!pG#qt$uu?a&rhnX{GPMSaU1R?o(6x{BJ@Q6Qsn}^#@4O&pt)M zC_UtJ;zWt9Y48|GN*!9oD5^=Q2#DKjKHuX`0W*rqF@L z;>AnQ>Xs5Im{S-pzL)~fv6CbS)vr;3(kY0fki;Mo?O+vLn0@)91MXy9%)gZdh}pKj zrk$8`Ug4(d_QVK3CxHoXm%&18P$4gaM}>S|hRBF?np@aA0wL&Ect_?|s1)_>InxUp6 zYot@l6u08Ib8-pBSq?EUZNnxEbxJ{Og`VMDxAr>REwAz&&Qcktx88DVd0BbYvZ`Bd zz9rbyTwiVuHeK<0&}$qU)7Yv?VQ8ajKbG>CA}KhglJa)>{L^?m_OfZ7WYXv zOyLZn7TOds0_qgV^UmYgaFY_mu|<>!WP&5%{DP4Z@dbSr)a;p94x=MCcI%>x2*=*+ zxzpZr&pomFZl0Xks__{+-UyDkh@GkwLBUR-1V&?sh#YyRA=u3E$O7oV2+}N$>6bZb zl|&b6MMhCl#FU9xDGI|X2N6Hy*sh328Kl%W4LIJKOGlNF zyJzwN%VCXxW|`cGC~IZd1W>w&jts_T*;`>_$;hYP>@j)vSXgIP$D&Wq6(p~HF$@% zYKbjumh`csM_=r55|SfEj2u4v0{#%wZj#NgP-V_N6!;0!WFkVXg+Mnn&mtP3vTr${aeepD z6u$IAumeU_3gbRNLAhRxCnxkNMBA_5c;ri| zAD5S#7FQA84ikCE$UqXCgvXjO-Y&1!9BSoqOmEge`ZW$~geeRL&ZeCa!ecd2E}v_z zJAxgPLz9lv;MYvD9Hf}Wpo~qo3u;a|B!gK43ux-y^hzn`x{!Aj=*FY_r12}UF4Q3D zal^Yf3v}0AcSSx@>*&|&2OfCvp@$xR_~A$Hz4yM`Zd-TDEw|ov*WL1W-f`!H4?cL; zop;@F`yKb)d*4G3KJ?&&58Zj^U7{zm?ArP}L|iu)X$juL3w1BtmzD8IRdM9IOs~8= zn16q0D=%h;g3R_Kd#hq9o%C!Mxzu9=Wv1fr`6-(U9lF!p=f4iKCa-r!Cj9nsb8e!*Tl5PbdAhmCm9?-mE!~Q)@PR&YU>h97JIr&Rs`lpC2z6 zeu0SY>itN>RV0Vk!uNp*W}`5`|b(7@{LQ=0tZW`@V88 z3*e&TDr~kjH@1kXkW>Z0Zr!>`aT>c;8&|txBgBsR$ug8aJQ^+6H9S*pa?(Y~ek1MD zNDdR_#2jji7n%TJL>`F>&Ad}-#5>BMPM0#vsUQL?wfxKE$ZJj*WJ)iAUUU~#EI5rJ z85>QM5#>% z`q$4q_0-b}HK8y6_~TC~eE#_tfcX|KyWT$vbE| z9((L@hm8A`HG~x&z3~|{=2DN7c$5myUhLSJTLSkjRPr>-YQ1=!<+Gr65h5T@CRo5D z26_J3XP?ctWZT7b8_j0^WIT)|M z{(63>32*|sco=lbxM2WaMj;7irOI6(F~ipKyC1pxKJE8BxZhq!p0;<}3l8c!_NczI+YTz|Fm%~5 zXRd8C;`ZL7ALuda(e9(49&*_WBgely=JHpkU-5_Qr~L7@sc+1?>di@$-@1Hq^~j0U zqpqqRJGuJQtE&4=tZsW{b&rYFXI)j@dt&vm6ROXgUVZY^>b4WBPs*0`omky%Vs+n1 z)t#nRcfO+fsPWa^vie6)tR66>y5HpLqb5}!JF$Auq}1BbtE&56S>1JF_32ktpLtdF zS#++dK5{~8mNg2UudF_7Z1pe3S08LbQiA9;D& zb-PJvNvA2*J!e$+nN{6yPIaF-)m>&+x1Cbm?y9tv@{{ML$BA>QJ5K)pIW+7&vwGmX z>XWaoK51_CNps#hY0jVe&wk^CnSbmz{rAUDeyP_L&-A$Tkv7BcMysfb8oXSVePQd} z4jw&1+P=zo%C+>o&WhM++sp$~$=dAWo(0mDC*unR+&G?6v!OP9ePo{uQXU>9IE_F_ zKjI@aV8X9p?rG6oSE?^JVV(mLsiH3n>+*?FOW(CA}r;1tl3yY|PB(ZnpqNakAhsSbz?#;gLH)ufkg;Ay z1-byrAn8YU6pTUMzyeZgEC_!{w5&EEQu++Wb?KKlWye|=q&pHGciCybU3WQTw>^&9 zecz6I9@2lWqtD!@{iwrwPCW9Y1-}?le%Kjn4n6Efq)T>9Jz<6l1Oir2|DMt%eVqrzdf1+usx<;l3?_MDj-=a0u*t@wF1=A^%&3y}m7q7Mq-0}6a$&}J!O0bjCT z^@zc@qmX;}fs(_>@LLwN)lg`Q-6nQIfTou;1dbf33owen3gKx;A;Dvo)D%@>@fE9Eo|Lq;J@T}TG2RCC`+5CLX;qY1gjZ&wjket~>3w`>u!WvF9;+?$>3X!%p6>&AA758FNsd zsRs_sKVaC(pPzeky9@5=ddZXB#=SWB%2!XF{HN(N{yJ~QyLT;o_lEf&JhJ$ouUEYL z`5k}z`ithRzjWUEu?uPkU0r+f)wNyc)()CiJ3Oy;&^5K^ z&Pz)Q7uSBe^5fzqwZj(Io;bgD$h_K~bJDc$)wLbw)ec)!d%FBJwe1$xw!Nlyz`WY? zvaQ<8s%<-`_VoF+Bd)F;Jg>IXoZ6G;)(*{fanih6N4L4PJ?7SSm|fd$PHnrnwe%gG z7u0rLSljKI+MbJRdoQW&wYav|lG>hmwVfB&wp&!&_UhVp-yi)7Y6q00$H3B5zr+06 zP77)~&a3S_f4!qqHa)p`{ea^2{R{uyec`8_=6%xVnvafO{LkJCYkJN7dzWc%9XI}! zqeee#XX_>?i~&tJ^K<8=mwIb7-hMUx9b`o6rEueH+&IDqkL5XhfG4!meltMuQBr#YbVW zOP4MY9Hm^Eqw-jTH!#y8!-q`^YKSXB2Tu+df#8Y)hj4PR{ z9;kOtdE6h5d+v4YJ_mF?;D|v7wLkx`9^($~H*^0%C5N1OU7Pdo=sf!2<1Txl*M#36 zf7M%)=Dz*s>)*Mn@Wa~M{$8`@y%&rA{n@RbY)J1P}u$JG8OI}^K{JQQ1bv+8weCNEn4*7NM z3hItqRM%!fUAu+p(Vp3B>iU+}4O~_?prUTj(z^cTbsZO{&7~SDahzCQ*SmN_m%I&~ z^EPx^^mWI@Uv<3Z%MJ@a?=b(f_Vd=aoAuFgQ{Fjl;+w~geHo8l0q}5`z{g8v2a>?3 zgp2awh<)-n;;vG{haoH=M(k5glLf7KHGv+`h^XWg1!{@YXcBZI1s&e!CbD7_)?9@G)XM00B-2BdCdB$4Cg{3WH?4K2ji+J=+qP`q@%=;bVu9-oT{RuN6{_Bu$|^^rxXm*ZP0{! zUI-pNyvG&@fSOZa-0rvJhiOt zIX841d3U!<9`8N=H@&ZVz3Y^}44nCHUg<|`3qSej`cFT&{tut7``1USzkGf9*N?2) zI3fR=vkK~m7S#94uOF0Oe|ABAuO;<8^XktmsK2D3epr6}yt4YgUSI#w&GmDN>I;kN z|FL@GD>rVwtGvFnq<&;U{p01E#}w4Fa9TkU`i_pg^k|n?e{6pJ z(FN&oOn&__i|dbBRNrQCeXr8`?nU)&m(+JHtRJu}JqA|Q4_clUM)UT0^?l3hhpb2o zrGr=0cPV7{o6h;)bjsh{DQ{CpfG_&0-NMh?&Hc3PjQ841`pdE7UiHd|>+pFpKWjsNj$O-#$eD}Rv3D&6d=6h!4!P_m_7lksv>?t2A*a{IW=aL2UALj5?#;f1eMzJKccPhPq1qc0zP?~7mm zebWmcJ->WYVZpa^3cj0K^xf=|Ei;N6E-YxcvZ!HFQNzWB4TB0A1{OA4QQUBTVZ)N* zhK9Sp{qqgqJip?*hQ~hN{HwZ#CqCV@Zqw6MTVAaCw&AJuH&itYFKrlJ+0ZY)q1}>( zQ%V}fS2heOXy{tj(6gxF+`@*w`Kiq_3mZ-?Xt=1b;f%tDi3JUx-n#Mg$G@y9Pft(Q zT~VsmDX*bZenW@ChIWMwZA%*36g3=M*l^5}hIV-k$1QF+c5#~aDs4Eis^R424LwR5 z`Yml3up&JMu59R6+0db&p`(MHqK1Jh8ctc&FgSat?NYp@Q^A(bgv5OAmg5nUS6p%Br0f?;>GR{o>E9*;DtL^|C$HwZG`TL}$>0jm_`f`S zG@%gw?^K=uL5fXwFv9Jbl}8HPq_{u_7U08|xQ+L^)M86XAw0^>nS0nuaVjn`CQmvJeAfP+!JCp8^cym70_&k6Q$rnz%;#mgexo5C5LW!&4p) z=)T`C2LHU>h(mf@ao7o0AA0K2!_K++kPGfV=%Oc&824(Q$!~R>_D+wP9}Hixer56J zAKvz#w|}+a^IJB&vwZWq$}KZXwq9Ah?c$-TGe>Un#NOBHx60TctVxhZJmp^buQZK z=v1_&Q{lHA^EP)}QfK4Ze)dOgr@nLC6>mKK^sl`Fh(HELA2*1&Lx%Fr^6wapYP^0Ht}jIt$#M&r^np z=5WKBd~gBqh>Y5r3UHYR&wT`I^fe4-jVH>*II)j7r3^Zq>IJz*Wq6^l3w^oQg|ZZn zao=N;G6mwIOw?hA9rnLG?zNrA1KN!^u-g>}^t<|iAxjTD`<8=--+#pDr#fB!s-Gd+ zO?{{DoPUm8xPJbUFMe14WnSLq2TJQV-nOy+vCY4&Y`CJN>5Ss0Q;M1{D{Y=x-aM@= zJ!Y3Sk1uWhWl8glvgVmeN}Eeco1a?N)co*QjgNiS{JXE4AN+6guRq^#|98bD&2vhd z$CfmoSJFJRw7Fk#^R#8nXIC`$ENZ@@wE4oN&6g}~uB>R@{CIO!W%KLTZ+mi0(@ho4 z53Fo{ptAYP+v+#m^WB4$%{NvyKfR)9Xi;;!{O0zB%^i!II~ApwE~U*qE1G*dmNs`U zZ|+su+^?#+Z&mXN%Tt}>@|us!Ppby3PSx5KHh0Lj>R8k~U{&*=)y)G}HJ`G&dGOli z9_6Wi=i;XH045|0g-b|o>bU634p)EDe)>P!PJHvJr=IrO&f^aXrlj8xO`9;mUv2n6 zAdPf{8)FAhFy!#^u#)m~CEOcvfTBjnn;)VT&73$@sFr952LhZRJz}UOW=DiY2ZyJi z934)jA{62TRtlWcU4u>pKATB8&=X!MuumsQgd}0g{lV>mK_a6BUv!9!=IqO8&PX6B zjZJlg-Oz-m&9JU@>iN+ZJ8lRzeq0(*gx}h@x|0wNELy3>h^p{^89t9kG-=D*W!zr) zdGN?oI6v-SVjoKZJ{SxIwTx(@&@Li)L|j0pM5nsY9q{8#sj3`hc+|uIf^mZ+de^TK zYQc42t0Bf2j9NpYEN?YCckaA%`uupnZo3}7N0!HZeld8Tb|d!9^7!*pmmYe~&BukZJ>Rwb z?u&PB+xGGDtt~HXYJTS1miy~B-qG;Ejoa3)ZaK54rAI+a*TR-=g)JQmTH58ew8?Af zT+-6BB0V}3wj8~rrF~(`@k?9!E^Fyg-f~=idUPymIdMhH2`gIKYf_M&wqv2JWzg!D zfveMW(3+P1%Ue1Yw{%L6=JY5^k?d61&?()xZtmpW&fHJhO?$7)lsCmkFBeiC9aGZ- zk6?80?HwtL=msL?5%R2yOmK$|xFLneP*Xx=G*n2LXp6fLZJ`Qkr|{Gl1ajL>Xaofc zVFekCh)Oh-$RLzpM6EFdK5_SuClT`K<1qw`L_|(O%?40iumDMr8Y-3pNzJJt)Q(p^ zl&OiEegX012u8x^xiLB*fEO{5K$0K`iK2;c$&&%Xlj)#ID==b*KoT9$iz?19uc78L zaE1>xt*}4`k5Xz-C8`9nl*X(CP_oSGLMD)uMh0#{Dv3Xwhk{OS?q&)h)qs^ZCciTJV@q+!jU4B5{IR_4@uwQLA^1hB^p6qb>E5}?} zZ8O$$_J`Q){#X`lgpZi6u0y*Zn>*b!=(t zh|<>6OIznwv<_d8Yc4W$Q^RTf3LHw#jd8U)0)vd28>bt-UH+PhQzNa8>J|HLU~J zq_rIxEMYT6vU7<*Y5VFKb4&VqXVKRk=KZ_v^!IyAuMQshk8hx-O`9G(3L_4_&3nB| z2|-hMJHG`{6h^E>8G&Io$fo~-2Tf|Z@=#W;1Uq7@TKWW%SU?SUfvFr66zmd}OX-6` z{E~-{2t{PTqL4CPr0|IWLysLWYDHKEeooYC$W#c>!ia%o?;q*ExJ7{l8D`~~LSlqP zFnXWkt&SJ1Ug_8q28>d4@NL|2TJy=(BRFznl5X{~kAy%2V2WZkx&eXbvqR*;!r?i; zQ>`!s6G9pIAj%rs9?<{`7OjFi?1Th;0bmx>luDaVDO1pPe=ryr8m$Z?@d78Jr@jQ` zxMMIL)?A(LD7(FwQold?y=lCokUUwdb(HhSQ3+jw)P)&d+o&&z!s})1xBOwlFO@X=P^6 z>P+{tO#7ltrxHhsWar{mv9e=PQ^&%s9lhT1VrTK!-LCm}pZPW2rdNBP<7MBBnKQj2 z^qSC-{!0bvThjEAkQ)n~A!v#%AGZgQ!k|x~5`xX|bp=`fa>8~2awyYRggBnB1CX*Q zgFB)-7BmEcQ-H9H2&<0{gvt}OL?fm_?SX=q|3 zL@NqN)E7ae0Vt$E(|yLZK-fxk?AS4Q+;!K(cH8sVJ@)Uq*Wm;AY4gkdx{cev@2rCd zmmYQ2b;l0B>yQf{IpVUHI!}C~=aj$pp7~yvIiDQA;6JA=`m*ohy8ij!^v>IIM#gXa0F(W9CnFnWs0l z-n#WSD_d`=O4cn)?x;%US0qWbu^s^r;K$$eF=cP>p{yS}yg_J-G1wU$>TGs}__OOqZ&Nw=b;ePPm}IO$Z9 zrtJ#TqkU1*rXcB5n)F_l^jeyhACs4KuSoh-CCBC`Ju8!rC28&PRY||)X{|!F1J)#c zs}eYOD9Us!&U7qsq)7ItXz91I`GghQdX_i%ain+QhC!w42j$iHlrG03Bxm?jP&}r8 z0lNKP^a&pAPY9Z@V=Z_u_f``0(FuQ!!mMukPX{Or!JT*!`oSY4DF@CBVhy2UC31BU z00u#zfDcj_#0ZY0bfid;Qd65HFAZu=K`mt@uw_9>6iO*GNSF#Sq`0Wuy#kMczfH2& zIQGUK7zrf()@ehFP~{}HqZ}29K_xIzLlg=_d|oD~5f-^R+&DSs4-91jH*Oyir_vx% zhEM|n3+k{lv^j6TE|(p6{EWi~7aeuh+GEeZNM_! zo)cf|Gv&|SroG!?)<;7ZtnaQ{QXjVEX~}qDzpBsEg!6HPJX}fv+J8)U)6f&@&rf46)9-t%aXN~ z$)hWh%4JF6n&iT=WNem4R4&b;I=3>JmPOKOVMSW#_}!Y;E^&!aY|N)qNH<43Rjo1G=-iNo5vL--Lj`pl>sBQu4SphartS!|H|Z~RcRHQ zU<@RM)RV7o9k#CJ^jn*U-P}0rmWBbV>rYv>VNl6>AKDF=x1GnCvt|X4kn|Jegzf)C zi9gJ`0!L^Hpr98>a`-5e%JXNkqcXUnP)Y%4>E1NEJ7q+n$QVHrvtX3Qo|gTHdYZro z7syhmEj8R>S$X6E7@*M+=A`<{_Hz}coDw=w!XQx&#t5%?q!3pWw+^%tT~NSXK<6nH zj03V?$>I^Dxwot^97TXt|QCD3LQt?bK$7;tP{a~C3mP1o!B zaVOuC@8o-O->)9M$9|pmI`pJ{jyq@nPL~|id&*%0^M7&r%A?P_wav);+F$leoAJLp z>WViGoA}rE(`&lU`S{3LwVkg1{M5x8&dlF*e4d}zzw2MnFsf*qpDIR{G)*jRo>X5PG^<@wc_TbCstu5Er}bxUPM^6M3uPakRe z_bn~o-P!W!waKK)B(EZwSCPyuPcA4+@+y;prOCwd6yCe4G8GkxW0rtekt~GpjmeEw z$+b(9&9^l^ydu*dM3Z(|GE&4MW$|pLXqrAr)zS z95_Ga(fdAsj|a(_Gt*;|f3ze8al0Tc_l|`GD_@bc103z^3 zJY`M4u0?k-LS_MLAM1fJUhF{9I~)Pg+awZf#@^MZ0%9WiT#iegll?d+!lF`Q6VN2^+*BNph$O9M%W(F_<3 zGB6bN#5>9`q#R)p_^yk{KvEOb8#!e>y49E~PtbVWIsN;NgLd2F$n<;iL;LS@%$fUl z9CcvNs}32k=5wR@Z6obf5KMyIG%{GT(=$Uv|5u z?wD&f^~&@8%y)jHzqDxU=%Q`s`r)Ivsef_viN!7bN?JTcj?TW)xw0%XzdWRS8RVG?f`hGuc zzFp+8scJ{T0-FJBE(KkH0G1Hev{fD{jsnjx#RzQGIz<+CLV@MbSB2a#3r0HMLz%w9 z1t$B9D1@Z8xho3$40=-(Z(Q*hFOJ|D`&$`c#`_#ESG~{S*l~w(p&$h;`>kMPqDo$El+&a}A_E`7AcY)^f}>%e30X$y zUg0i*W%mu-sika$=%YrcDHlfN6{=;Nz6*4je8AUAJNtU36+b%$K^@S&GHd*ry6J6-vDpQ-<^|E%{;p8d~(b3f@i z?>|S*{qpGf8%|lYad`eW=N5c7uwYA%yoN6M+qxGt_9|>Tt+e@~lIGFHEepz83(H#z zD_ZgBrOm>!%<2k98s;3&tjK(_w(;BR8e5y6G%9JI6SWwgD?`jfCy7L40p`nF(MuR&mpFvCMjcC z3(`O@0MDs8l~=1T`ot+a?88mhq8k#8(7@a%VyMPOQ>T`{BFo-DZ!2dhd1QkbT?!a{q3Z9oTQyfrAQue%kVb&${8@ z;rARd`teR79Tnd_Ej?q89)V_EB(%H)x% zOmg>@l7cRQD7 zG4z;udRcOAS-M9(r8G_ZW%sM7?1M*}Rj+i!$Kv$xIGJu=vxie8ijuvGlYYg?spZL> z<;jHQ$=5M>osL6UQory$acW8rvU;V&Plj5{m{&%O6aH!2`ZK3tVITW zz=4T0GTb|&Ckx<0jXfkPW1AYzFU2N&LeQ!gg@%_C*1qR8{Vyt|ag)KL3}FPAaV_k7 zW<=b1=cOO^Kr)^ak%&i;QMtIO5Rx{re)#Z7fUD52kil<*LEav2%x`4~CkIP##QB2} zNXh^(7>pD<3W?fKpdT#bC4#Ke5H@8L27@x7i&QK5un;`b2^d9fnP5}kL*mUhr~kiK zsOchj4D`_FifFooc%>slN8W0-Y18JXKi+lcpYHXuo%i2m*F$&R>zLgS?7rtO2JC(8 znfrFSXusZ*_CIOCfrE>Ge)@`o&bj5F3+_91)MM=~6(xUn*yV2=dc|K3pY(Ts8+hV1 z|2jSI(=!V{>$2#J_Sbyf@tV5sOEz6p@Xf^H?XFOt@Xz5URd7xd{yhSD>Cb< zlIxcyw=GLbOOiX6W*)7|tX-PCf9E#^AT3WWE=w*eOU@}vhLone)>F!ozKAPKj#`qw ztLc;td;%P-yxS2myNHh^Y2FK1@v&D?GQ2o>Zguj&nxwEi`)cU+?`))hS(XOhGwg4( zuV>Sz%cV)X%A{*~%A*%MolDZ6BYos^>Y7I1zWQ*zYu<*g3)c5pkn;HKv(Nd%10Tw5 z|F$Om&tz_vqWFIVDdE7`TqT8A24vqfv1)qa@KW6oPYZ- zM%;hM=*JJa^!dXkymHv2KOQx$dcfSj54rmN!B_wD)VUuIn_qj@!q3mU=F77ef8Bl2 z#*>zOb75Znl%nrO7Hv6q>DEydjisf&K5e?BqH;(MywP$uC+BUm`?OU4eW4jh6 z6HAlU+qV4umX@0tW!Lwaa`a>ib zyOgz_P}O{VWy)j!%KGm4DUaQ+{@{c;+j+D%1!6X42pf~R^bf#s8k9v$`5wpgzgUPE zL19PX^Qv;1^4f--P!m>y$G{etbaw2QSxcW2G^vey1*T$u8v#@=$^+FMc?22(W;{7E zs7I1R(jal_#SR`xY)XYfu~IzMN|k3uKY4h+>NSqk^CNGR`V|rdd=-G<@SI!_aT+iN zCOnyN^@v$8A<)Z4!tMVrqEM3ylu?e#ERks<>gk9u$PQ~VQZ&h^_2NaE(~P`cf=8BF zi

4bo`cL)<_N-bjquoy4#iXVYn57>~oMG(o6x`cBQ~F~=P9lmEfv?mO?a@6UEQ zXqVlO*loWKdmPed&m#xz-R7))yI!(ipUDTFIQQUF@{c&9>X={NaNNjshmXGR&@qo6 zdfD@bjeYru39tExuK%>ZoiyX!L33(`&imIH^ZtF_{LfH1WYJdx^Xi7?Z606n&D5fA zCzWowq-yIGW!oURsI+NTS@Y7e=5ra=E=!*uk1I^yj@r9=Ds<|>5RaY;{o&gGjL*j0^kEZ^0_)PGDSf|Ubdmf zqV)rpd@y8T%A-ejZkeSqh0)=u2rN6omCN&F&X25|IOXB=e<1M5!5A4$*amz0a{<<-Hs=E=u%~7hE{4a2fs&qJS~rf+Rr)0ZWJyc5+Ap zB+3D$6-J0mU`UfN&T?=nPt@jsjlOijroE`=M?XHw(-G`~FQWw=i93m5t2JyHIsgP? zq?XAZASW)?L>+O&5kL8#pZ)a5yY2MTy@beJb~|LZy^r1fz^;27+HcRJ2JhS9m;3j) z^yhu9I=KI=!w2X8;Hein zZ{E1=KesjfZB^rQE1Lhgrtu$ZnwoFjvh7z5$%Ee{Z){9n`7(L5VdE{0zhBw5JQ%n(u5#p8YO)d(*#fYpPnFeky>(3$h^+Vi+7$mOd4xzdsfwN983Q3X>Dc zk`uB&f1nbHfn@AvI~FDbeE?9Lf;_f7`SY5VH&?eTSelG2N`@&fNvl|Mh^J?+NT#hw zt|-qeF3b4T;j*QzCzdszw4$+hdBgE#DUYWwU4MGX2g4RsKmYs-!DIURhGhRy=&4hu zg^&FJF-yargT&bBMXDW5wK;L`1x0A)Qp(Kkr~?or2CXs_ay?Q5SA1qBR=CNx==(Mo*u;7LK0gsOe4_~>Ph z4|SN;ipP?;C>g#jhy;?TjF*!^4W>9e^a2*A@`#gC!v)H6NXnoRP?R-Sg*8p&i5Lf* zh>WTt&$y~klh=@OO+;HfvZfbfGfTz^NyF3DP^BUxYoHDo)q;_xR6aN7*3=A}M*D~T z_uu~~|FiQ?e!S~WKiy;JorTDs@4BZD*>3lrdx|_^@8eF}x5M!Lx{Nun*TjSS&pB-1 z5`Uq5^cgGKoO@II3-0W6;r(4Ne(dNm&m2DXw?~Zs{gD%1?>ptseWt(NbH+ag&HiA} z+Z{xfSex5|^z$2U zUmg96)55jOlH~Eaw{K{^(4%O1GORqctg5&7LY^Osk_A;s^1|m2t<8LJvyFG_x#g|B zOPfzz-sq1gdlc9A%-=AieEk`v+j;a)NbpQdr70e>2No>E4IPUcCmA^mWB7n|Kr-k?1M%tn5D_D@6Jpz)x@31dAxfNKBM#;pgHbBtx7EG&z)l zCMn_hbO3@Nr!t|8&Dga@EK?Osp-htiFrdSrRuK?`tl(5(sNvBF0f;r$48sWH`7w5$ zn1yP*$;V-S#RDAol-q^{W|mb#>}rbBrnz_&wjo2 zwykwHZTsT7rs|a~klc7f;|JF^KeIfu<&Le%vm5Tau61g5r+RAk{iZC`-d1 zJkKsm9}hi3`Vm9~MBh>QN!RQXW&hIT-sATq`IM z(Ta#`8s>x>>_{s$3L(70X^a_b3R#Q0hm5KnqbDR8XAL`g4ABa1B!{HoPtG)8WMoBATMPfnocWrKd`0H(teAfC(UF+}aGH-3p{9#k(wN1%izG=N@%a`8p+_|;o;jN$E z(ERVU&A(ffv2lH5S@PN~P3vxK8e5uNRF?ku=!3d5OVgh`ynBJ?SrzHCp@`|X$ex}Y zi__PwcB+D-lHf}^Ad6~eUj-DTFIvZ6m#kZp6j!Am%1+PzD!OIewij>Bj9Q+YD1a6x zXL$uwm|Rhsxv?rUH2Xg1_+`y~mo*;mA2C>2e|$;GCHL zYmrL>6D2_b%5oWbLaqjDQmuT||%Jvp9{{r?)t1LF}AiKz4d#fad- zvH<`p_IR+8At-QjhzwT;QBDFJ3X~%r!4?bA7Er{TsEXYzzBCC5`Y5ob1c|XXj#K5x zQmzS*6{3$Rq6_wk`GFx(MGcQy89zIE%#MBgW|gKHi@TqU%W>y1u~yA&?6%u(KmO5A zgvg)%_-8u>k~{Ca^DYPeY_~&q+2hFF_HFOyk3A0UyXP+k?s?4Vd$qe@-%b}F*nPr& zeWvey!h-!y&Ocyq`GLb$9dh%zNFxY$GG(*wpmKl+N7=S=+(PR zb=6xRtorlEx4-*Z@yB--{O5&bU*27^;ZMuz{cTfNKyNCb1_4cnDANaEQ$*)^~ zyP@@^4O?IN@;@(rnEA8!oSTy;zE1AhlsvyFdGEXA%}vP*-~8j+<|kKV{9frhI^XK} zmet2OzHzmm^w{XP55)QH!;2joS6fy)SmkK)9!8<3OR*A?zB$iDJylp!4oQVJw;1fc_rBK$LCYW7bcq2@GvI~+cjqQDwK%+ln{rczL2_mup1XV{yd45T0f@HalqE|DdVT9iH15=MU26y z48RCok?FEVW?RM_%9~hIvBw^Jq&)uUr-7s>`O}~7xf3LR2FdKtACNqtOZt((;R5Bb zecPOSNXH8g>o)GdUQ-V5H~ZL=7alaI_<*5R2c5C@;InV;F!HWGqaGZ6$>R^se&V*P zUwke9g*Vs!=A|1Se`nq6k1cxtp~e4vso-DFl>O(?(ywZkeg16e#`o54UVp=ePp|!^ z{?^S+4}RJ5($}qTZf<>jW9=Is)&Kd6%&QxdC%#Ia{yKTKE_q@@^0&>&OW*zDx~BW8 zGK-d`FGXQETGoBX$HuNjY1~X7Bz&W!q z94K$>U)3;db^Up3H=MIfe5~;=D(}c6rh><8n!X{iA{I2#@OjH*U2-Hw2E5Rtwj);7 z)FS>s^9QHFW89X*2XYpi>Jg7W5UimFQ$Ntxdk7pbMY0c_X%bsdc8pxD%Z!Igp%8<3 zv};AEvC&~)UaS-}RS~~~Akmu~A~^D1L_mN)>(MZr@?p~zq8H@~`Lb1{d{r5QHlzopmtez=F=FmK}Tg@?*}q zzSrBln*79*GoE{O*{@%}_cwpO;pLYW|Lw87_kUCHufJ5T|NPpTx61$f zKr>{-R3W@`*!0kpEdvH%dM|{x#iDazx?>~8~^y9bj$ksH_59Tl6$wb z-m$s)(e>+ZYkA050okuuebky?krZSsGtgltiydE0Qt(24s2i>TNCO`(usl zS31D-_EiM5arGLfP4>^PqynptdHks169PY3LeeI7Tt#xj(&XjaTHm_6W%J#QEq6D( zu*yFYl00~Q8d$;TuONM&gU10Y)A-n@yrGwW0dLucfh8%AeP^XST4gR85;BHGIwv6W56rJ=*J;EP9Ulr@*K7HWoV;moiraxKKnn0%>KGoRw)zWeUG z>#nUZ87ogZ_qx94-Fo4u`);57@G}b^xNFw4FBUxi zR_V)syYH=ktod7Y>4!Jwt-rhAvlmPM`&8M6=PEY+WyR*Yo9ebaTif);hUVAmwmkoz z<~KKPd+n=+Xa1A<&DWbA`)t#?Z7sKK{rCSz*?YiOQFHSVVf`@G%4d?%F=`b0l4yIN@uq{eB_DvmBmFkGLi}b%g8hE( zgFCy*ZTm_OZ?w#cwhxX_9*`cJE@2g&rF8Yk2vtTAFlvrBlHH7vuDsx&duL_5{m!mC zSGQQobMNzF#lGj>JLwO|hc}p=!)&ghwhrO84iVN)(U#t6=3!eN49hAVka~9@t{O`gYm3-t<5{js-jYw9> z5F^Bl9~L%AN{yr_*apz)^o|7}5-Wl@Et*XX3CcJk`;skq!WzV(vkT>96S}xa5+FE;69q!cenQ3Xk=2s@!ZY2;HIE-o%lKKbM$BLC-6)o_*W9bQT@Zl_vJhSKpK zr25m1o_e^L+C`P1=sB=Q_1k=a(CGU+Ctwx|2^xXTK=- zfyql>&e*;*dC%gU4YLlUE`0mlxc#T%4t=rXWN!S|*=v715PUT?_}9H*H@=U*aV6o_ zjkG(Zhkku<{CD$vH_e~kwtQ7+J8{c)tiZMx=U99-&3tV`Ij;rx#@kFWYS=0tEHi|a zFRl3eif^*!Fr++Ejb-Ka1b&bNN0aUMb`{${zGK~WCo}p6gUo4&(un0D5r^n%3|M8z z93#g0^h1SVYIqL~R~##VkB+cMG2A`I{?jJ2{lLBA9S`^}Yv9$=Z zx~EvY(#`!c%LZnZPS|<(rR-bdQ-2;B`5ohPKKUfikw=EGG8n*ElyPFH*cgIcK_3Q2 z4DnnVM+!t2!z0v2h|X=6^eR)s0g0k@R>dqagNKEDNT7v$M4*zAh?(hwYK6@4agG9; zSP_U3$>Bt>F>#k-Z(?lh3y*k4NTh$2$Ht*UD}IU#=g4>f+N%r(fJeGp@t9aF#efdX z9#WtKUD}p{kJJDm=OQOaHG&%D1n4iQZBR&pbT%mG$l2S5%-R>B}$ zi%t#*HwuU&TXN&*TtTuT0Sa3g9$++DGvz@NJaLqipUg=n>E&8eA=C^P9YI031k{@} z8|dR=qJYQnkcK?^$m0f*)fsB8kbM04C#%)2{$yR|^myu-CQM^qr&hZcUv#Tm-@Rrd z?}p9%8nzkPr2Pb^j?R*|fVDrL2>>J|j+vDx;Cs{ngZ2co`(J_4WY+add@s2I`O1$4A`d+WNyCXLhOi26h`1tRJ z27b;@ZmIb?w5Va_6+8+EST7e5qa_J3Tn-&CX7(>IVhrp~dY!!}ItGOVm?a{1Na!eX zP&uLwDT9C@dpV}3NF;+PL?bD_5+q>|5QIlUP715zj)AZVlVcZd{=D^&u{zSr3YD-) zcPlV5Mvh@Q@Q4oJl!Qzuh8Q!vfC<%w2%A_q^+N(yIU@0toRD}zO3Nlfa04H>fI&Ga z;foNr1wqnYNvm5)A(ql8KWNj{K#?Aa$Df4=$?b)J6m#hOn! zwSKl~gXde-g~}H?IXQXMZrrD7^8qbd4{u^LU)#Gc?Bcm{pl|4yA+e)}r;Q!EW#*)u zX;TknE_!#n|3^WK&-yRV5A**%A>i`1pkF?X`TfqJ-|ig0TJrWUrEmQ4VE2vk*Kb?4 z-LQW3r!DWcZTsDOTkn_exc_rT`GI)b2gz1G%i_uLREp(~&E@Z=TLUBQ{xNC@D}Al& zah)-Cx_X%LBMjG;W9AEy{Ry^9+ss>1)I1(vWtczCvMx+i-cUU-8lPOzYIWr!WrI-g zoEc*;+*|hLW@~za>W^I=Z~rRCHkaviOg0~rZM-oLPoFSbQmi#E-Ru)??i0<&kN1aV z-t&qr>J@!+)P`$gUF?&_vl{`uewr$)R)elLFs5Azc*f56lPofzi z0oPRaQn%Miofy#}f_pMX__yMio&rcdmH%tl*Q*4 zEWNm3#rKH;*Y?L;FW7tekHg;;?)bHI>&=p^qN2>=TiZ%3=Wkn%mfqq+kF6zkI(E(! z-b{ONA=!L0{lS@J^RWc0<-mRWdv{J`StD_X^sE~1A8EDn`eSZX#ix-;(e~0UWpvLn z()DDfWp$E$&PIE0URdxwvN4QDW(mMWswQicdWxKyVqcMJ56)5p2|UAXZYG;wk}YVX zZEO+)R&DJfY;8@}DH+zuDHf)O?H^V?H1fe)vqr(a;J5zh`s5|6^#!GTd^e(v8&281u4c*QLw)rn?qx4 zI;AMYVE=O8&^CkFU`2!&m{_A=LJo)^$x&#d^1z651W9;=K@or|Ugdqj|L&jjPqH z^TZ3atJkajRD(J-n$>&0P5s&(8olV|)WFlVS^s9OhBa+BzO~!zw(d)Oyw^_jGYuG; zJb3K3=@WA%%s4c1_WPseonF4=%b*pPLi{gBufP6j5UEdzuQo5*p`(e50i9v=DP1E0v74nD%-t43O?v{#wF z11jm;;U$Q>$;O;`UJ*8DzN?D0y_#<86Km~}X!VHW11oFqI7{ygOOKRtx2SU8)G`K> z_e(CGxcScs8*jX{;p*g+O9O)|c*LGCEoJ$5t%rEjC;*d6V+aZssL`vUa6z?@O!nds zjyTFHR*k`6C&H8tB?ej@chQH&!m%jXQSXaFyxhPYZ{xs70Wd!i>>nYeL8Kam!X4h| zZLJuy%EJ*YF`Ogl4L649(0fA<2Jo^Y$dDoMqO-5C#>tX7#w^(i5z_XfkVF!L(;)#N z$Phz~VgDGvrU`0*5j2PdLxcp931qP^Cnzv-II<;Agh&oeNE$+k7ZSw}k_N63$(ch? z2BDH20hYcawsKHuvT`75hEqf2R!k_|Q7zOJ!m8#`T&HZJ8o7f(W!tuG!I9=G4cI3h zd7}2C)f+wfw9{iXUU>ZZ+SO{+ed2|NPt||%nZ_?Z+oFEWw)J1=+|sE>yT*N+v>5E% zZbDDD*@Hb6jq1JDyMJWg;Tdx$?C3XfpWpPim(I&uvFP(xmt724`9oIVe@}+}d@Azy zt4TL6CEht7clYi1`yVDeIGdS6kb7_fjvRY^|_cCJkbMFe~(Dy8B;4BNImE}r$VSk>I4{ROCTt?MXF19G@N9`dm`$M zercwxZqud>K&t1;M;@*A$m6vhsb1^Rr(bxiMzhDCYx6|SHq~EfT)lq%ryJFMu4Us| z9h~cSY2wtgOS1vqZO8QOIBj6}`8~bX^dAs2Zg{%;*qvjh9vJiT2czbF_VSVoVXMF0 z8gTW?=xZ0Euir`gr69ZTLQ2u+2_>(`JoqH>!PYqI`K0n&yUNdOzi0pC_BT1^#5j9c zl$sp!%%;+k{SWRQy;gqo#_3E8oi;Cp+ZkNS6Ca;h`57-FKiFDieZA;ts{MA(Jtm!7 zpJbmGXa6$Wf;v-{<9+?H+H#)h%E_O*b;}JBvLBDLBJ$|y4@Rsjd2J}k&s(s|a;MdUltr(77`p#FL>Mj;$P#z1W@F z=C;g9;Tbt!0K^GOlT~UG`lu>uM($vQtO|*QxJVJ%N)v)xnNMGzR;^meTaicp&m&Jf z@_5Zh@Rd(BeXK^4$Dez#TJ3sI)~)wc!-h4QH?8UHRHtL-2A(~d4d~@O+TC?pNB6}; zeS(J#O6)RXQ?Cg*qh}tQ`pU^^3(sy@{pC-YU;ncI((mb4{>Z%c+y4BbJ$KH>7rz}} z_F-aqT$I%m%?n3nOSbdoF)q%&o(UnN?JJ_}pJtlvM{d~<7T6EnW_IP!MD;p@QE)8Y z3=xm8`$pK;B-l44D1M_8?AfVm3Xa|;^+JRp0rcnKAKe*g6Rtj0hDQ{pM`jx2PA1!| z6kAZFH8S10D8=d;%r6L-@rh&il=t0G&adrE*j6?q<9^TBQu=V_>@OLWRWvN^&wdHF z`$qra8~yXRgzqNDemODhlhdcq2#*+5z}f%<#=qf_tD_l27a@iVCq}NrN?Z8ff3Ch@ zB$FPV1!5ng4o1)aR@0hI+4_p9EfAKB$#5 z&ysWcd94}b7wI}Qt^c^!Cr&>yaP|jt7N6c7_VJIK&i!}y#ozXRd+Xqj*LI&TcHq)j#ucERRy}8R<<0vHVnvZ4;BYTA0}C<21|ZY-V{?xD8<- zt4U24z%bNNCiR+|uY|G@8%rl{zc(PYxKF~}m$ntn-t*`5ZMR0I z-|Q3hn@{A`ff3(MiaGyM=t=w|pQdx|jO)vwFIue%JuXKT040+6D#E4LSNvf`42EkB z6kO{nWJwHWfT>_Uhv3Sk&h^HrjW(Hgq#Z@)s9dPxtRHN#@#P}}$a(X~csbl6ja6PU zGVIOEq+a^J9AnRjx1Ue94C5suFF1^sjP%>klS3a4lgptnU!2bd)l6kR9Hww&Zq=R% zR`+;*xx>;coez!6y%K=&!JxGJ1Jg=}ZN2A{Rnj-9c>LzOqq7Qo$J`l|e0$oCf*ITX zn3DbLkc9vC4gaxE(AR?l&rAqBn&`rmC{h)|om4w9tWslyz{RRyi!SlRu$4%1 zCM#B@X-!BomFvR23k>D@63X3-`k@l26DmjUV5|y~R1pYDC@iu`LrFZz3@53E9U{~u zoz+m;tXVVlQ2FSi)gFE9xksLC^k|LtkJoJfM4eXE>$j-Uyk#wyHuc=wHTHFFGp1XY zSNnLcap@P?aaiW?NqfAfzddO7N0S$x%Ubiz<%Ek@Q-8X?>GGQqceY2~-4a!@I-+bx zZ29IGOJtP#37(Kh8)H-HGUZ(c-KUHp=cWH-V_rwb+b|Fg5>aS~HVsn4;TUGajHy66 zl&`U(>?0!Vt&IsDRX?iHhXaYss!9hA&x~G4_I~NM?lCscL^UOj(P^U^sD2yGp2>>D zAsMA!aree%6;IlBckI?ezb$_b-Eg~KLV<7m&Au^z3`_lW&aR)QWnY_`{^Q`NZ~Ck| z-)D8+$Ti2rKXQ$@K*A%J44ZVc=PC?p7)2o^7nDnkRS-G~mLmcVm;~tsM)F6{MImHg z(ohTm5XKP_U^5t}*d!skh>meoIF{s3sLO_>ku&zJkt7+JO9M=743op&I1w>Xc0nfx z>=Of{;R=8tNvjnku{U_C1`me3)S#tGyOd5;<}~KXk=`3Z*u-h_GdjMhw!s^112e7N ztqoYpy}&AYfpPG|G;cB*W5FgRJt^HU@?T zl16yMN+}OJVr(>7;Zd4feC5HLM||IwEnBv3-HLaEIIw~>6k$+wR!Jry3d}+!Apimw zN1-ra$SNV?NFtj^!|703gD@2cm2yjwdM1*}K_H8g>y+pe9+7yC#p!cKq(l)63DKz{ z;yFze0g#%fW(?redw(JksU=4kNkGd1q4^4W+99Gil8CO`x{{LmgiXN2S2FHm;fZs!d@9^3pC%WWlT%jfcmYv84)%Bq_2i~au_kr6CzKG zylUiW5j>enjy5XvF~uBTXD}%T81g9xZB$yPvOpzWsqjbx)jLJaY}_~1-X~QWuD0%R zwt*Y1L$a*>QY~JI=H5x=d_vVb@&4EyrK7i&@L{7@Y@t{59lykaiJNXt+4B4Boa@uK z{X8h{YTt+}eM~@GU-eo4dGFOHdoO*r*SxocN3JFq1}Yd0#kkf2QEFZn1m89Jfd^e$QBkS(E46HGZ*Mt0w)O+fS_5Wqv#FfZl`RTaVe{GU+YfneY0( z`l;{Y{7Eane|gQ-S?hjV9dvtTSW%qmUb32ouKcUi2m6yO{2tblDAisCM!vjY91aZ9 zMy1onjTwv?m}<;M)z$4d=7qqs#TumVit1x()!_Wo(=hv(?V z=^n%HJX(fknMZCeADOM*DtgB8$$#<0?M2hx_;dW`TLThqct!l?8*_bh>VKzXU7oq) zhnd^H8xi+y|M2{=abJv${d{1=>Avef_Fn#OuZ0JD&fX1={QObH-PM4R%POl}H7=Rv zk*kKVDoT}*%jyUt3}R85L=>?updclp6_BO8<#RY1)Y;Q*43JG1TRx z8WO2$7sJg~!6hq&X-i2Zk6732+ejN4zA?5!1q{5lO?97OZdwfUqe@N(hy* zNgAc{W&sA-7cde1zzBxIAg7?1G^nJm5Kf$sYNWsv4C0^p)1QG_@OjL23=Mtw>J z>eB~OL}N%5;R+F{D=G)>Smk6nccF%p6@N#Jqkq&1NJg5!^^dYIp@_y1h22GfUE--~ zevOQQh)g@+_GDep8jTx2*QQ<_xB88JI<%e8#O;-aJ^j1*#Wo+ct;?i+LuVaxpPM&$ z(N_~!d^c?6)p2WoTO52lAhakxyd*y2{)M>v=401C+gx%a!L}ljUx8E~9rxge`0d2x z{OOy&nz8A^__(v%lA(Ja-ro? zib9AzJdB}`XxNtuFq?luk7LOuF(e(5gFyH1A(l*mDbmCFOF0QS7qS(HOSTl47z|j7 zEk;fxwkP*|>;#=~^5n@l%CSaAD}d15DqmfJq4-DW(6-afFKzM{xbVAOWOT%eWE$~Q6xnA6b1b^1Flb3Pfc_^Y1FzMHiA%G`iomj~Zo z7g`h)R#c7 zo*8?`-R&85r)T6%@2EcpCtdeTy4EN1$KIjec?W;fFZipG(dQ?`o|&5Q*^~{Rj0yi> zbm)n(!S4(SIMi$Lo*uJycud`R_ALFYhJQ48)Fh&C#R<8N|AeHrbFHw8VOAA^#!wUt z3?m^!&Dy^xVre7*6IlBv7?nq<6e+FF(-BN5Ay$WfAuGe!E8ZqZS)mM}{Me)z3>JbR zv5L*$JFpp^C3)n*Q8IQKp?e4101W^UydJCKD8UmL4Ns^>q5@zQ67@49g`xO_6oUeA zvV@LxC_2T~FhUt*$*TBAeaa|8qQEFyg*8D^lS_rbowP-9i)=+WS>-Z~mqeVkU?RlP zRFDRPREtJTwu*~H*CIIUP)L-}kw?)v7CR0aI0znVR;$zCsfJF^wtS&>N2i9~t)0g> zcb@&C$I7PtqdZ4%?ly5xv#D=)oBQ#gMPH6x{+}_cuDl%ZYkK&tH)0C2O(h@2-@DC- z)7{0^4{sifFPk1|8y%^7Z(BLCeX7^WlY`cMFgoPD3DL*KM;sX$aA2hW zzG2IEdB3{VV`gTz35n;=IoA}?R;>XPMJyj3JHdXcV5nE2fIJ2kBs!}q2a-Zk7>pl(q($72m_56QiDDsmMpiLwP6`v1UI@G- zJ@&Lz33;K$>EPz16$(d`&++*YJOxQY(%>KQhL9)#63U?|lH4CCgCI$^`a+<{h2ZS8 z@1sbpN*W@CGJO?Tg+zp82xlRn5ps=4CRdFMO6yb_qS9EEWN?bG2>~c!O?VU}(Gks{ zR{jY_4e#IbNL3@6$LFindA53kS~XfWsO|cE1Menn#z-gqX~OjPdn=Q z%E$av)~Kc5j#_a!DERuV-2WDC`s41#TlY8K`E&E#FO%-S5zFt*ss0?=t4yQ8_lYz| zd4A+M5r2n^R}FKzTKcLN&{736dw6}gSIOZbg17Bh_DaXZ0onp z=AC8hnr!WwU~!8z`=*zV+;V^HYxgF+UNj}=&lx!dQ+ND2apTpI@jr}-y)-W7!dTPk z;lX*n{vUX+e8+Rqksk98_MEqW;F6rN0k4l;w|&T>EraK89QbmI*W}o4qr>2l0sdU` z%B8{(#0ChtV-v*{)I7@7lu&FyheTq)8bGaxy-A3jU?G~Ce^SJj*h+?&E@uD#6ioEt z+&GpNOqWaq2dLCwO2If;aSdXPxA&!?1p9qN{DNq0)NfeC+kAexLaLNGa2%|xyLQ*p*$%qlr@!CadD)EVcslB8e zn)E!L;~(Mix#|s`snNozwo6?nuR5(pIdz=Xs>kw9{UTbA*i?UPPS z`fp>_UEUt}^Y>}L{kHLD$-BSYfB#1LXSenxKM0JpEQ+#DinKAEBa`{#8F}%6Tf`4C zog==I_Z@`H4o5F*dq6XOH-}~_#K9vA3Y(ZPr@8SPj!citYmVNTcFzo(OAK>v*!X0_ zJ(jWJ=7H%CMrGe0ky$(L{QD5YWdoqTBfFuS` zg-5ycnnbN&1{y;YF?AhcZ{${m8nGNg;kW1gtTTw=eXh= z1y8o>lC#ONJk%A()mMT;uu5SNs!l{FU@Jla5N=#@Q6Nq(mOgz}HE1ZZmC%t#-E@RX z;Sp*o@lrf$Arid`cbZ3?j2aW+CMKehbmWoa3iyKz9-pmN`}yh(o~zNkel3^!4ZNOj zHL9lTtR@DJtwwCBH!i3Blq2nCpX|Hvi^!mFze)PfwY1BdLvNmqyH)b}ANM}^@43X{ zJ#l7!b7xkhb!3DM1{njukN}XJ6Rlo8`WQd1K~D~EKzQ4TXXFhC&y0)}hgP~+(fRpf zydlqzV2Fa#oY9Lu>$J;Bq_OS~Y-L!Qiote}@sX7t1Gc6?Qa$4=b1`)~k`! zmRv=_h9BOS7%@u}4(*taP#__P;6(H@6qHE|mNUYGNJEPR!Yr*;ObaVwD>WlXLIkVS z6&X?zN-OPEcmz^Bqqs$Jg``0dp;U6eqUyvC%AqAx99D{kQF!EVh{2)?I6)y1(1bNk zM=qJZ&j@JZ2ieN1++?)3;!K4a;?adN5EHUAYr-R2NlYjrgz7YoFmeY&NG1pR7aprW zUh8SqUR69gHRuJ8&%4ZQ@jD3*EccbJ2*pWeE z#89yx4Wk&CgxH%Fu|Sel0SA*tBvN!85=jB7pvNlaT}7Zk?^Q)16D(Htazs)y&Q>v9 zZONRJM9LEuP?JA5B`gX{(>#&}A)b%~2(<(+Fi3k_P!nNV$TjI^%>?zxss>bIqu_}&_ z=R}<2+-UnE8m`Ql6J`H4+j4P(IW^v%o2>eLc!XqN053#%x|H`FonsW9z{o2|BHQq> zRlL1JJntnd=4|X7W^oN?&i}H0$)(BiktgHmyYA$ zkQzn5F0EJauT>_ov5k)Ff60pj7i64~1aYP}J0w7XsN-pP1j8F-K z^v|FhXQtj;X&B)VVXH(6bQ(tJLx_}QD2N7@O|YXItFo$N9Ihv-3b3Cpu<+w~a++^m-_VX`vS^TZbipyU9 z*SoL1= z@3`Xr2?bu!*Zam_o|b)aO6;j|>)z@6>b^cRw)dWp+XKml3aJL zvIy6j9kCxRSdqv-!HCgfjieX*c{tQGi9!hPn6x8GqGR5ULQ%<0(u)((IS|hg#YwSC zm8>{5FZHIO9aLJ5b$t^)ZZ91D@tk#i(8aIARqNWs`jBtqGQO70~3j5r-uVGt?-4c{lg zN}sBBg-{7%gpM!@kDN6k90|M{MtIaniVqbS#XlNt)xWe?HH?xcA-fM8Fz_kF@Q?8L zOf8psPM(cgjeNm%M$PWaYWFcU8JguXA*aLC!wqJfbeVqv|JZWLWe@-Boz~v!xxR2n zaPiUjdkZ7W`-Yo)gpk#yTg_`f9kPQ}~0f(PcfNOMDWF zyyI_pC0rYt_@BX{7kV#x&tt}0e$%&)oRm6jSm==ct9*Jb9OOA?c+aUryT3HRZEU}e zqkDB2?&dtSbDJT(+79w=JJ7R@U*{J6IyU#M^pA=}M4|XsafA_F%#usb_2s&g7RwPB zQAGZoM9fbFGZXu9G&9j1L$O2h#F(*UM*tmlwo*33Y^w&68waKJ=(vmMsfM*dhYhRRl|LR>tdL5zBG6eQ_i<#i;^QT!uR3YZ*@V{v04PclRyJ%S=N zCWk}kK;%XNBy&PmISMC2sIF6G$1fG=SXWY?f9pMkNAdoUD8lI=@^nck4piuKV*lKn3kAfsyHHj#agMiGyIY!Mf#mBSi`LV)3!ehf$BO7;|QP<$H;n1wM z<8#{LA7}CWc%jXrOU;)2~-l&n}~chVqLcBDLF#)R6E(TNvWD5{j1;)&^E+b}}ToF)pZq?Z_uqIu+4!l2|s zCYo+`)I1U?RVqh8*Ox#@lscCS#6^*~ zkHDx!o-sjEHB~F$hE#EmnnyuW^QfOO9eI@YDw{}5N)&OO#EURgSo8RNb*E=*G_Pa$ z#|EuOHtIN|q5IMo`kG!Gs-7R4OgilR^2v@1FE}s0)O5*DtyWxjTYIa++Cta$#U0m| zb`L4<7;NqsZ1D=W^7}RY8T@Aa&<2hYFnPzph@IGIds?(TG)m3FI*#uj`3Wjx{3@^&sj!+U-A&aZZJp6u0nv{$nseH;7wH0<5i$;;cRXCEhz{tZ3)HgNZL za_{5h?pd$9cfIbt>veno{r72Kaf$zl$BOR;D?Ovw23Elp#}YJ#q6mf(Y79}t(i}rE za&mBF5MA(jIK=R9E>%!+T*U`*Ty_-utP-+2i4~0xiM}mh%p!7X91c+q%y40x1-31g zEIx%~RGJhOg+rjrIZ_yDucD9%CyS5|Tcui9mCT9J_cU})L2iSTigap5{&zf$?8>baamJ2#F#O`$z5Cq_L`b#KDO?>>Pnk@MIHd2zA>PrIJPU zzY32}Khyl_nl81SJe^u89-DeBZRn$TbQ+t}aPr}nvrl%If1%CdOU;-5>k*(y^Xz#}|5aspH{M zr@L33t}MM@=;HHYmwxrS^r_pW?~7f$Ug*;2g)W!}*A&tBWUUB^gpS|gVE9{fpgvW;gtU?xMhdnz2ScNYvA6qAx0>iLU#}Hlsku+K~mz=L0UEdj? zl1TCw?*=$16jf|nTnz0!sRt^71EG@)YS@tq0Y)0D9E+n!IVBVZB|}0gUss*bDi{*U zCaG$46v_{GgdBoUimJ}j=u+ldAOfAE@6)VlMI2&fb5(WtAhK1Qqa%z}{Nvy9SjnRL zFFXo*Iv$7U$gl9|NFqAeI`a6e(O!MJmdi8sJ!`g9&yS5fmNxS>H5``ZG(M-%l*7$m zKIsgPi!QZX{*&|S>m34awOwE65>)IGRO%dD-X+ZJ7H)A4v33iy@gjqTpN$Jiw{J>S z(|5d;Vt*sizBA7L^S1J%+tn)%mTA#;k7#>OX&LOwP2mP{o^>=ap=a~b{#l^K@!$yr7HEzP5^|LXM(I)C!%SU_t^ph`uLa?chK%wj#iYkOrIAEkM$6Htfq@gfIetJT~&q zk&!ustWrXDB;-KkhOTcZ=;94IkkksB1W!ULlaMk~;pkiu4ne5u-{|7zpd67HiXlE- z2(8i_tpXZ+X%X&(LC0j;Me3ABi?w0^k02?0=_f}aQ3EInTdRod1$x>=I#Q{5tnqlQ zXN1R^E;Z_VKHG9+O_v!??n|5anwk#JYHaY>Z1%}k^DeYre5v({pW66eZ@cbR+jWKQ z0*mohE@9;z!_4hMEbT+B9YSn;Wy~9Yh5_WH*dOe_&yXj;S0`i85~7xC!GYj2S&!Z#WHT( zctfU4p2Dwntm0jwv8-INa`h_pLSIOf(2+-O(=4zfFv6n(lMywBgAg9EA_NjOjDn=V zs6$AUg$@p^5rTkG0Q}ofxxDr3IfOzfzJfp7jAUEj*Aw7yL*e!cw#y|lhT4WX6 zjJ*Gcz3@f6aVTI?0xY^ID@c+dOaTacN)D{@ z>2J}~e$Y`73>}?g6&_h7Hxkfw^RSoHJTe}D_m9%xD0QKBgwd z`^P4Re{4DLLW@P0+Tb7kueV!w%XwX)v%zDBu=4is7)s}-wR@P2PyYEaxKYveOBrVS z(HjL>?HXEZ^rO-)WqdPkk()9k(rgN6%(?$+ z0OXRdA(@1tunShCXnY7ptngtHHIKL-FlVX|GIv~p@Hu~7CTnp9p&HhNF;9YZ+YYwi|Aif?;oFZdiI%$ z{v4hk>$=XU(|xIvkEt;{j?ZZZkF!rUpMRk_?bT&JwOez&!}?p!0jhtsLrAG>czN4U zbNdip)>}J-+W6dF z`+#UQbR3@ulCE*~Zt-f!oXpWdj6#whj0>@L4O7#rPK+>biz&;BDj61hw_i}fqQGlz zi@s?+_e@^iDZX*7?7!w6aK*BM?}i-~<1=F3bgPB&H4l>rkH9Dk&;bZAs=IO}jL;z@ zY91j`FU%E5O7V?RjQ*}%qUpw{Tw<_Chb0y=Dwkje2vzb}1w%IJB`y}Xg_Wx%33pd@ zNu&%RG`H0f?6??!f{qe&L>d4<0V8rJ!L~VJHbI#Hg@c1B1Sqh15o{iZ2+;^+ks&-1 zvKP4lAV|uN0wZZefie{Kk|Po#a3}N;l9FQ)!{JCqjO0nSno5cdo3hGQc43wB=(6b+ zwPV{=9un2<+Iaa0i6Z~hWvZDH=%7!-C?skyAEr|8D@qkA#YO%tkJ7)&_?#Nmo$AzR z{#-4Wnoge28|~HF-Iu=TV`?xwtI_zJrqd2LpL4R=tI9vNSn^X_cnrGL8XoCi4KM8w zTHZRy%wRUx2rCnYGfS29A)zcO zeDdqCkN_B=Qr%3{qMmrFj$p{|Q4!D*uH?$)8LfeuSJcV}|%g z+N<>EFn$#tYdLw=X*Kdi*BSNPmpaj(!}H^WoTgI`x14*j)xrzS7hY<<VB;B(53CaT@wiC)kz`v) zqJ26&ImY}{%&p2$9G)5RiS7w%v?}uh$oG#74B#n}x078%ZQaAHfw9&fHkO@CFkjhn z?e|^R@?r`+QhE&j1$T8(A&m{lx1NpPjOz7C>Wb{Gg9fPYyGQ&cg0 z)J|xaQ!=K`oP`@VW@)1}46P#gU!+P-S4Jx7`MP=Q)@`zE6WO|L8;c>^w{5So?AX48 zg^lUy>0->-GcJZuiL!3>%b|qKuSh;ScI=d8=g!w&t6X;O*eUv^tWBvYsq6)aAK4e)aC6IQmEO(T&wAE^_+x>F~(JR?iqb)~wOIb}g3|oIL9p zJo5grk-;PWvB}iKtzJ3ly!b+^C70T+RPEIk{{xnQXuL+T9tk>RV&xcnpcRcZI%iHL!g92KzW;M4YoRSk5z9wM)Ci+TD{>tJN!6 z5vtyOgxLqj*yH$BjxcNAaBFOYWq;g*-?rYqvF+mJgg+;(D{xtQwe|dqt!5iMCL{`v zYCvM;!j1IUv156EC!ZK1TSVnoS!Mb7VXs$$BsIyEFXPzQbH72KK$?_z2LGx z|NK15xpSX8E@#i4V{40|yR(B#yG8XPB0^vEahA01>tgQ^Fl!ia2sf43;n68calh0wTbN zdkBevj*ygc8$l6THH@llP}$L{b#NnRRtXVulYA%=$Wur{KocYh5x|t=qO*xhERK@m z!6Ps__U8zUgz_H5AW{XiU8^)!7`6(78c9*AAW7uIBx)Cl z0;Iy@6Hhz=k9Dd$wX4zGqfUnw4U~VZ<2vJo?n~<%JT@Gg(`eFR`d8tx{fbK+R{!L> z?s_Z#Th09oo2@DC5L((Ts=Q5zxkZqLIZ>TMZQYC?gPRg(k4T|wRJl3eVpdfer2q(z zr_-&=V(lII>@iw-Lt3Yd3g{kZ@3*m{f0f5c{3ehxJ|{Kac07Z*&8J{fqh?!@S7Gl?v>;ji!x>|**tm4wlPa~zO?#{nZbLetlc+p z)&7@O9+l{x4off0WPZsY^(B$iA_$tqyV zRupaykPD9pkqFNe!sf&N5vK`{(xpQO;6DjSI`Sw$Y5yn+k=pkOhB|cQ5fVwSUu`&I zC?x8T`EwY)`rPBSn5ewh^Ua1dXxq%-v7)`|quQ(Z$3~M6H=cR2>8lsoEWPCF|5K-R z*Ij~cHT5rSx~8~&NNM+&@|MBo*1;CHXf+-Hlz4f;yTyLd_7;o{;N4=h3e_B{_(9$| zMyWwNKQj8(x(dt9yoOtWo8!TIr)%%VCrt%n5+1#*_ zZtIFVuPGS1`f9JG7hBCScr^NR#5vNZI&tE}wr$%EYV7ORtbe~YL;X699@JyffIhPa z4qiHB%-W$7L;a@2_|D$&((+An1Gl{r`o`Sgee=R{Uojn-ZhCh{!h5f#eK0HGqv=r} zPY(TLM$9L3lJllT>PV}jetW%-cr&9KxirjwcmFT=FVR_R{YMBv{H`A0i z%VdO+d9zs})IyAZR$kivyvXdl@QrzK+w(TOslte?yr}HF#Mko@U&~9}l^3-+FKUxo z;Uq(vedl5?VqgJ@X4~2k5{CgoFDbU zeADqYamP$ahr(mt3<}yBx+eA5JIB(~(xqEi-qh$&JPRRakDZHC6Z#x=iGeae07eo! z3NcX0l*lAwFOmsLnq?H&A%A=ypb2q;r}l~(uUARr6&jaAd#@5_s?OgB#<;Dz=3L}gfhVjvRGvk4pfUYaW#yR zfHWw2FLp$P$|^{*Dv4!0dCkXbIX~s({d}{&b=$XZpuX>@=gRn1)xX+sL{`(6a#~DR z;{h7YxzJ?6rFN@+>Ku5zYnXc90gr8iN}1}-J=WYU+R`eRPZVv;dqZywh~W)!fA~iT z?G|hA8l$L$LB6Z%Y|M2Gcf8<$N7(dAvG-0>J9;M@zYBoVGV#{D9s0Yj)-P@62EGT7Kxk{E!3rt2XB^$^3ftj;~j4 z{@Q>0SD^>KT>IJ=E3+@Gpuj1oUyaLKp7?&mhNEFoIqL(m6_4rZCK_}VOE{y5Dh3kK z&NBogK?4M|2wZv(eiYt7WM-oUH)%RK{B-0O)8Z@XO z(y?*th@?)Y6<`z*7_0CoZy`w_d9s)I#}}*BYEs?F?b+sSYISH}JU`Z_KSy|!{?)06 zo6bJjXzqo^^Di}7tezh`1}h$$uPt^CD)opj=ZB>{;?(#YKIG>C5Qhk2gl_n_B&CBS z+|e|Zg*1T4M8|#^idj+uqnoH(nAIi3(w2_gkg|5`N)|>G z^$IQM5plJ5z(tScr+K8Jc_lYS-d51FI$^>DhT?cN_H%DGxM$muK3!iL*n8&SL5qgJ zv~JX_$T9PhCM?UEx^CBukbQIG4lPPQv1;4LYj=LOdfVszTfbcO+BdIk{dV5&@0K0> zVg74BzPjV5IoX#N?7aNywkvbDTv6esD?x8wS+V=d{GC@;zIEl*%~xL8q?T7%HeZ=1 z%a$wiSvFr;u%%*I`r4I*_pWUF^h)y4D+!0LWW0A}>!~a0$FC$EzLIkE%Ek|_Z2sg* z=6hGt-oBD{^h!+bmDRhigdDjNcI--E?v;T3Y6*Y$O2m6t0`^{B_4?(tZ(d&W#!mrz zehfMEL&%};1NMBo`n8M8H-EWs!m;Y?V6N&vB5aVY5Ck(}R=DAgN(QdDun5S0#?>zaZ(@Y9)rfbS9*M$LiIqx2;yo?I|a(=bCn|?M!>Mb(@i$ zJI!e7uHJVv8ll>&&88i0{mRLf3lxuy7OL?%ZPwmu=3m${pt$Aw(vA`3y%Npdi51U} zOwtHbcu8C&ZPb2g>UTGklCC1*anME;1EfqMH*Ax=cZ%ZCccXp8whA`;q}cmxwD-)i zch9uDCfZ!%tUV*FtD-CeBFZ~Pl(~hM^oT6#5neDd<7&Uqivt5rU%2oEKRC@LQ?hP7 zF9fGfoyvH*eoY4SXgS2A-RSO}CVP0!={IcI=;KoA};> z^t{!(KVP@^tB~AFAqRg5+;=tP;Ll6tT=jO!M>Xd_S{^0@aB?(H|M@q zu^$#ehh-PqF2B@f z#ZPX5*E@yWYO%JkML==u^`*{1RNN-ShIeB+aeN<*Pa3N9qIG|hep*=c`?b&Tg&t9*1_^t4p z96oko;!7*CCa-&aZes4-RioUOC*?zSwWqGS8^Q)paFBfHgT9lqwwDm&K?(d7Xe^r#3SF|y&Xy?~O zJM)WTJ}z2wxM)pok^eyzMtoe9@I{g7W3_~RP!yS0nD|9u?3u#Acm7;=_)h5iw*!yd z3OV*i?5Ed*4qsi9^WEy5Uo4FO=#{|Sci&Y!;ybGFC_{*_WXu=@z=ULu^gXQ8Ae8iq zZbMiVp}i{TX)4)WQz@-hLSlqR6g(p#$%uhF$l}@|CDa$MIL&K^sf`>OE(eBVL;D(^cw zEVKXnPb?jC;2EnL0tXtl1iO;EY3$;_PLG%R_2&p2>k?4PdYG{!{&-GEH{ z;7#@c845QRcpS00;wL!(6P;y1w!ORIRmbGmhrX_c2dGC*HE*Pi-#$K*Y93{>jE^t( z+gRqep~N?#Xjn?Ykl3p)XI~r}TEU}&5pm#gaI*nDnh)*Pc5IKXQ+xG()qBXQUSm!D zW~Yqx&z>Io#;n*Q3pT#DC_8US_PG_?FZ%EPF7(LdsP}(K$onJqx? zRUh3AJa^asgW@GeOV%7I-jrXw@r&ZLv&HFWixWRAUVEf?X>Rel4~v68EnfCk@zVX3 z%f8}e`zw~^Zxze3;($`tzFoZSyW%&m7H6L;-uPMZ_Wa`AKNi1!u{is*T8;Xsc>VF> zkPnIjjufvwT)g&Balql?h*QOhUl&JzR&4sXIQ+wss8b~=`Ni>{-wk{J?)oEzAt&yD zB)&50lV8H#`N{va{8gEsEHWL@Jn|OOSSm)<3Q&sE2<0suc?8Ud1#sX|_IfzP&4C*N z7x+8zv*3mz?N1_Eg;p>`CsI~PfI=jXhj=|{aB6P|SzJuvi=yHLNx&)z2q`wrR3h0# zvzAB_3xF`FUTH84#CQcst5u7{>rFzX5GvS$A-IXx6TZ*|$twO4S`ncVlt`?(d)P(l zO^U|K?jVEOzaXi3Y*VdP$EWJUqi@{~EgP!uky~_`QP*g%O8;v8iE4g;X7etzS$3(@ z+Ml|GT<;!!t4CB}_o!mma5Y{I|H$t!b}(7_u~Zo3(GMQ+bT~xXr8HlMW~+rr@t$~0 z8mqWSARV*KK6aaZ@K$^G1V!bPgQ|(Ew#KVzuO`RXW+z!A60H4Amf?xzLo&(+WtL3X zSu{SYU_j*6ArTknrv4+3Lz@j4>O8c6$8jER(>!|3^B%m~XL6+PtW@9mTSl(iGdt<+ z1(_c%&i-`O8(;Y6{AW$hPwU_Muj!rN5>6GQoclBNTw%f|#nB($GksjT=45H$+50K^ zWt+Y(%RFDUDZecH>#~f`RhW9JY~8W4m2Z~?eo_{6s%*ufvgHTMR^(PJD-V^)vg%OT zs>5ZgjRj@Rv9gpe%l7|Twj;l6^SQF^UzY8?T(>M{ThO6v zVTUfQ%|5j(`W@a~(wM|zfzcSer@l0iMMW9{U+_pWFeDTaBrDg{CV8j89)>$oLB;-& zk?al{^t}KDk-{UP00?m+tO~ZQqDTS>A(Y+0jpsf>u)+yK9KKtqL?NPg4D>O=h2LIQK%M zd6!x(|EW{pbq|x`kso*K6<_L|Sl&C?+&9(IBi`D;CB58h(;NVE@s!#bK32r_KAWn|FO{-g3dbBj23%wK?>ZdHuU;33=ZfampP2 ziP@BA4mxfQde>Nvo0Ia*Dc_XGoGp(%TOR${gM{;C>EGW^{;D+eMDh9~cfyX}ShxR| zwQu~#wCD8N)MNNZm@?pjAB9jA7=osH0e}?W2Zrp(UQkRViQ$(J9X1_dl8p14T#zvWTDBuy0<9g&1SEspWx935dKlWEhYF@6;u8&<2;xVlplV}1a> zN3LbepYvjmrS<(xjYnp+n3U6ImU@0{{OW}!3swJWtCiQ?!fy45F7%2m_DU%APAX@P z;yx)BpH!`Eg`M!PJdc2LxXnu==y}=PzJ0 zaxZn{ab)v>Biarh(rMgq&*@_Z&hs1Y?>#QsXJ*=}^EfFQkQFpm{^PoU4+2ocp=c6OXr_`I(2)td%hMvc zp^%j%W=Aq1vEU4zY+^_Jqc}&|OE*>pXI2q(L?a2F+Hdll2xa&_?e8>|Rs18=u<37+ z)G!K?j$neJh7MiBD0s3-5(x5a#W})b@7}%nzN1#PT5X3qxeDZkvlCzHn2*OLoSnNfe_ig6p@;t)_5N=$9~DHuR~YkQ zal*%?>F4in`A_-Q@5~whm$CN%kK#xdwePvl*>mqbXOq|K_1azs3?>*b$ru}xa}q%) z6NHEoC?KJn^GHHup&Um!BatMLgUDIPBnfN_8`%VdKp;lb)Ay|@G1lTe_y51Ao|@|F zs_N>V@9nR;s=E4o=eE=O)GJEfxB4BAmGYmJoSRC@MMZl{$-bdvTvaj~l%%st*g?hj zfD(CDi9D_N?NhvWD_*-5?>&l-bh{Pby+*f3@v9NeAHPo7dRZxNRl<)c0d-370VS$l zi8-T$9#n$rl#u;O{EagxBjfM<*I(;rB1A5%*mHACk2n2E!=yb@2l$JQM9MNh z6*d0j|jFMl{OM$8G7nrN&p$Q6-vy*iW_EOM0DsftCOenqKnURuYDglEn> zo-nfDn107$TZ37Uu#fz0{2Ru5q7OrmvVZmK_oq$kZ8m$b<(#h-}u9a?L(@u=-pzJa=ZJJ<|NSa`L z%}UC6(+CLjS0#_U-@*HjtoQf_nYyvU_LqTTlEfj+9&XN-w@rW;hh5_^D!)J zq&{)0xbKv9$8l?eLyVY2%|B)8E@M7`VmQ*rzwxr#IPWeebpR-iBij;toDZIR9+(sTUiLzT8ybnRH2? zc|*x+GNd;eww*F0oj2s(HtcRU?0jm-|IUzc)u6p;C~7gJT`_2{8&b{-UO+PJq(O7V z;8)wlV;77@B!7i*uOa%dA?LDi1vd=ow++!}1%Mz4gX=FCG$+L-F7l`$=9H1jddZ_9 z?0_Nspk5$(L%05HN9@Vxk%!x&4?Wm$;>Xy!TYhP0)<*ARjygaIcDmlU6c~!FZVQ_e zhDR7AMpz(#-(9d!##W&)b5g*>)X^$o1Vd@;B#(rp86~d-6C}YClrVV| zPL(i)AW1R;veC<-O)*rPj3)a?UJgwm)I>fcN`r_>$d1$3#xf*duMC~|l}L8CkAz9~ znn{(06;35t(l=o!1E5M?iKOJQdtwuk1mIC-kw{7&|Lx!Y4IWvqgZ0UOZ{+dMz2>~Z z{G1VP?@x;8F+aJNU16Uk)t|08Jkb68uz$OaA=_7cs2x8($KhtJ_u!VNr}3$TD7ZGXJ;8l zK(>pf?3{Fi^G?OSP??^npO>SXpVcvI`?Hzbp4g_}cgq(%u8cV$-nWX6H}S}{a>?VE z52lUmX*PC%<)kkbe?7`+)O4Ro3u7iNO_=N?c$^zqJ1^>(MckQ1NewIVn^xp~zf612 zukPXIlWiN1wQs-hV*7dB=K9Vpn8gc9)=ee%jv@29A>oW6<)T{ft-AY}y1QL1`9aNW zRCAlulDlelqpH23re08Ej;TQh)rhlde4`q$PxY%Yy1l~puT=w#&UcR*SgWR8P;(p9 zoXe{AidxdFrruWLE~z00)!=<<4+fx?FrIj&)X(PS105Q%^!aPhCvdIm$;p953mmF;O_5P+p*Q;clHVjMXx zk+R7O{-l&Vf+QlJ6D5-P5=m(vO?<%`kg`i!$?iPL2I_CqOBiA8HG2nHCaffkvbigb zEHT}I{VkiOz3|BUR=@k*?^qA{|NQTF{_7Qw*hkjS5$_|96ZY{FyTZN>g2zD~=LdT? z4h?7;5pj3)`UgX!9`^}(+Ar*R|0rGm=*|IA`p;sNff~c0SaryHb?|!O^9t1nCdH+y zv$E8wsVa?CI&c_Ugiy@2n^CRuv8A*oaWr};P zvb0dYqC~f{vSVKAv)S99m~FmqmvF}|y}>E|pLi6vM7Omj`#6#Q)uEQ=qZiMb=rnnz z<?Nz07((YI_)NUde;F`JENY_>Gmr!_eieZRW&o@2>FuRU#=lkMA1zu10Gmwcr& z;k2^#gtGmdXqtkgwpmSUP?OKAIXBfE57fQwYI&=`F!z>Pcv}Rt*VO#$YQh;c@PHa| zN{zd$MxW~<(FCL4UN!2lntnmm0^=0{BQEc%T0q|0YHG6@aa;}Ar-mI;HK)||=hVof zYUlwq{Gb|L50!=(jPD8Tqu?=Ye`myD-Ihzww_I-19DYEPJG}B%SpJ#Nw0%5Q=jP@L z{*3mKP7u)#@=7FM`0$mSoD6_)*B!(3S3;z0D0U~&6viIG0vIB&fDb{C0x!}gLLV5? z<}`vR!V)W<2f-Ya;1TX9L}nyRvr`H&GQeJh+EON2K#~gJ!!OU02*;IaWP4SbZ0Un! z_x38Fu}P#9Hl?8iLs%m$jcNBRz$=9`z-ST)mkB5~DFHF@C@raM%}O6U$^IIZvIO2o zo;YFRfBeUPz$5D+OCIUZdGnJw^yj=W+>Q0g-PB_=7WMP3>eNitu0mZ@tuEN1T9ybl&9hZoEp1WNijj_F z(O$)30;yfD>bOI7-LJaVs7nfk(S%2fOvP=l;#sSAsnB`s>~OAnHZS?f>@D}r;_g_* zHaKm5okteTS+HOM^X0~UG;LNNGmBxC7NZwiPIsDb?mc6nXs=Fk%AW04HaASzN1M%O z7N<5WOlq>vXmKpM=T`l2O-0+99qkdPczArd{j5IY8zt$YXsLo^_DwbKwwixOO}iwJ z%)X{p{;VD_s5|bf`ORwXO|{~l;4$}xntxN>dP)u0uZA8MNJgDeVNhB|0$9e(OTsc{ zU+&_Ouyh5DYQ=YI(oHq8UJcnVTD0pe++ zvdN)kl{f)vLi3fwaZuS_rA!i&oq&vyh*3#y*VGnyg`=>ZruHfpkWECUHGrb%hv5&M@rG4c2@z3v${A=$yZx6Qr z`XKdR$~xhe?pBwSsf!ELMfvKybkQ`0NBo8Ps`D<@`?%_| zOLZtz=cF2DBrDchW!+xAca6@qoS}BnpEE!C{+#u9%)%SY{Qp}XXZDz8+23p)_HmTp z(c0SEc6p5X>V%mt+0)jQnMc)HZxHR(1zSab&eF`5Wm)&uls@#>+qQOByGvC^`0EEfb=Y?6sX-)_v*Pj(85+tLJ z3M(0RMu|No>?1se)I1N~-KIJ8aLd^rHG6IaXP@=iEO;y_DM4M~(YP?kEBs#lN*l)( zHcQfnFOdXK%q2amJiE#66atu0o+Y~rX;5rwA|*=rP=gO6@Cbl#CvBoMk!;FH+N;<# z!Qm?-DA|-gWx^M>k~COb%7i#5gD>JSi)5E2P=9POdnL1yViSz=b|EWCnNnUu65L=7 zU&8n=dF&3OiO1KB9T>u6cO)T>zEeoVm%zd!0>#o?k^qrVlV-yB2__!@^HqBl`v{Nk zjdXi&qF4`^@3FpXTm9aW!yl|V-@~P`pYeTU-tYJ<^zoOPr=!;!$2+!mPTa1aoTALi zF^o%AzoPxg96798iaN(Q+GxfwN0vG_Q=P+TBMermOLwV`b*fX1x@woYyj)Bbpc_{7 z%BBb_iGB1xC49>)gBjx;sfulm-ffr8dvAwZ#j|zgPn?SHn{U1|H}YTb$op2dwzj={ z_ny~dnt4AntKnVt(aPF;;p&)0?g@+ivMv0}<^RbKleMRoAh0_shsr`osn$`GS&u#gKYgO*(HxvQaJkPAzT`ty2tT4p#EMTK7_| zd8U?pFGvJQ+OCC7qT!lxS&cich8>W5)F@5R>KiYPkk zzir=z3m3~u%YdRgkEV8}3_vRZ(tw_c7xY|qq(}=$8W_xGO_6^kXgHVv2v~t3_&_3! zVoIPKiKGM&6DeU7AZ-$J=QuQpv63JrK?WRnggykmD3hW{DbuqlpD5Wy$;6Wk7)e8R zA}I$FVb+A9?9u^1+2i_K9!Y@h!yw9(5=m(vyIVlR zX(CA@+p%Pn0~`=4i;_rUAK~%e|NY-tUrx4Hv5$ZFyO^Itd(~tgC6Dhri1(3MKZoyk z^zabM}wJuT}_o()})tSZW%xnQ8ZB#NcAhNnjwWE8d$}lfWnU|r=P1Da$ z*SYNI2;Be7x%A2W?e{IV+_B!+FgHlpM;cG^N^(_cuUcDM_vq2X>f>p1`iSw4`J)%x znK{|mc-yXuS>m0rA}rf!ec8$lwYG7`=Es~_l-RH|yJ=Zw%Zl84E)@?~m$a=ZX=e(Y z&;FO*wfc3nO5Aycp$&oFO*QqRntV=8zbv|RN?O#yJ0d3il3Mbu;PF7GTG6WJ-%^Y3 zsFnAGxh%P(<~E8Rp1{Lu`M>VBcjj9(& zf+0L&DC15MHbfj$qL1q1&vwS1(8U~m9(!-=|d2N5-)`kBx@!UNeoEBBhVorNk(ZpiIhB22$3Kulkxn>{G8W#uWJ>at?h zCRepCF)ZAv%+FEG)AjSxbQT#Mt4p3OD|s?M^}c!h9rKt5%Lu_E|2-F+ze6-synW#D z-FM%GM~i-Da~OXdxp>}Wrv~@<><~n!S2snOkzLYs#_Z+s@c-X>iD(Kc@vA z9Sa_=+tuc_qusfTS*b4rkLZ05(o|Mr&Kt6>3H0bn&7eQ$oUn{MGnTff#owtJSJbqN zYSDM<0iAkSRjcl+Ma`nkS@n~6oGiJmW?xm~>(%%(YT5Vd{-=NY1$pe+*igi z-w31hi?50D6K|>O&#MuK1d?$)PBzfVV~9AUgdfmH9_ox|`rL`h zGExG@i(?9l_-YXVA_>a_k&*G2TIc&L96W;4l9W&yUPsrM>#m)UNkC_# zHpHJ*A`a@qndy2^7gPUSbAl#V>51DDP4-ce0w5;t zOo1-^y8Q_Awo$yr{~C|5X~Gj000bD(a9H49zF#+NZ9CIMm6z$1hbkT6oL#8VEx=3m$t}i1j+&u@&>l1&^$UY_yN?*qiw|!B2<8JRh@B zHz8T955W3zyx+m>aRx8G+@cPP7sHE;_|pU>fGOn3(WXG1!7SD+)iPJLqMxTgwJ%Xu zRH!Q}LO_AILwIM@;M1z_K7&i8;#i?9-=SYvp>x{FTN2N_Dxa(^zP~Et zj!nFnPcG-@$a|yY(az3}FL%uSc-s7aW^;!K9_i1qvGTEA8nbY1!m{8j*DZp_b=k)P zO3s8QmW?xsc zf$O?xwK9N6qZBL2Gb1)J3#)fs-StpC)TthLp_XGkZ>tq8!eJAklD2CeJ*eNSdmpK_ zzoviTdMewXmVJ|vL>~xMNPg*-wrKRL*!w>@QW+D- z3Xdd~FcOy8@nun_wku#xnm7sj$og`!fAvqs`Es;Z-yUNB;n*%7`z$Q{ za6vWgRo=H^ee#cGdsXrn_Hd4itj$f zbEn>^Oy_^3BbK?-ho126yhrvOm&Ar8QNPZY6Zci)`yGsTy#N0Dqd%B7tFM`rw2zaW zY^;42I>jt-O<3%kwNg{+qpkJHJLbbs-Hry2@}}k5?^k4t{v79$HV^u9_PkhIrSm(` z>APR?*r|BeC?UrUK}JIvb558=nxOejYSvYOWLAS({H=I$#6E&#<`psUaZFW@(C_*{ zEpApT@2XYz1d@zp2qdqnWw+H`KdW_5gvIPKi;O=STdLAG!AOAa9f9Nxwd^}Xa+4wc zg5Z(o$Ji6hNblTm_GS1!E-Nd~NTWUI|RhjC% zLtVF5^{iF>4yyi#1dp-Tl$a~};G;UPT^*h~o`oKHqB(irul&y1lm^#$!6OR8ABvcG zFMRjCTwC4ATN{B#m=A>*QYoioHw`7thTKMj z_KKnCmSN8W!;zPUvfGBd21EYUE|+)JP|*0REBwY_awXRdJMS8DzcXyQVu(DVr@cz& z>c(>&>rX!quW1XedcgBzNQvOlcZ=Y$yu1P))6&uzzhF@tObhxfku;GAZiJ2S{pyK_ zy;njkZAEDxC5%inKx7zpAO$+GbdZJGOE!stCU|5MF7Vk48c;*iRH8~ef0@9>C=yH( zkQW0=Jt>n-4uMb|`h|#uM|nh(aU_lS>tC&rF7&`Clqw08Pm8AhncvdHE=)Yq9Z5Kn zB6-A@RuYc7b4_WIM-W3KfbtL$NqjcBGMv5?vP(iqPigp+Ognb0aXvZkcXS_r{1fx# z28j0`d(DdY#K>dsC0*@R@%@f&_OVyU)4{RNN3Pe6PVD?LUf(BF^ydtS67Ti9Z5FGl zvLF?BGB<#U0j%iA8;)bQi8XWN+saIn!_l~9lm1xZ8TDX%gds>wCu};Fs~*h6KA;31 zQXX{{xCo4XvP;$RfGA=3^mz2U=O63pA zj(bY}bw%5tlr$^*+LU98QujnDzoV4iR;uqA15HZdbtSJsDZZgp-Bk{@D?5KsioQ|u z8-y#k`l~B!RHQ3v6bXv189=h4St+`sBsA)yj)}%~u>6qH9 z^yjc%N5AmrU&iZ3ZtDCxK|eG`^ygp`zt*VUajJtxHH#Aqu`+RP0PkDDDWCR;6FoW1 zl!HM=Lokl48z4GkyS)#>6m+_Mc)x?a7MX@cdCKw<#kqpF2z8;yIy9%Bt-ttW!^Qg{ zyY6^pG`Md*arT_xQQjn3%!&_o@HIJ}AIE+$bzCpAai3X?8NPVbXveYBy=N`bEb&TM z7MQsrvcxU1#z%X^CFS&jtyh+3-Eyt`ZtadAUCZu!?tbiD`*dw}yF0J>SLwX=bow9a z^r_L)W)3>6_vY=z8YS$w0+j&=m6+2?{w;xCVN(~CIhU1^J4$t{QvRKiby>;1qE!8$ z99M)Bk#_`uJMSq)HTc+C5az$SVHCRjAUfe{ps80dgIY$5@CK$8!Kq+zeLm?V%-c93Ya zW?e%V6hb}aNF_CdT*)IoVeBS6O8dxh$t#iX`uB|wjMRa{nGox4^14$AagZfpB(W(y zH6#mWONykDu!%}Cnz)t$Vqi*IPXaPAo0Ly!2=$?cR2vu(ZeLskYR<{Bmt-WSOK0lT zsmzyS{87#)r@bn9Wc-o!I(oh0@e}*5{#BEGWPNhJ-_g_m=_f(Y2gK=yXgd2bUoKwh zA87!(@D1v=6!lQ1!Z$lUi%|RX4W0F>HJ^QqQK!VHUu+PsDq{^Xf=i3U=s#nWGt*Qv zCJbb&^KyhU*Q)0D@R)5d&s5Aa6st_VO}1`nL5FMkGrv7gLhJ6w9=Q{@zacbN*hj{i zr6zDC`O@6HdGqLBo$#UHaddx+abGN+INovmOz-hlnkh@SS^H)>tuI-#d9Q2Ak;U6j zEl$3?By zVgg|&^$;3)TAz7SpLh*gc>PwsT zW#8&|{j4v!r7v&R=U>(5UC|fc)bIUSf2`9O)1c4C5#OLMxT-ItWc)_qiiF=OUFkJl z<(-#>-*zN?^CI%Vv*2BigQ|Xxti2mqecdPV)Y|A;!DB_G_-=^!n1~SI>fSW%P9nS5 zl=Mj-B1{6040XJQV}5=BQlXXu_ zGIn**XvB~(S)`@IoXL!@Aqj?3h$k_Ku?fN?W|K0h8)v~O@E3p~wvtoeM7Ts`Atgvo zn>LO9)&KoFF(2Shf9UZB;~npg@RRsE*a@>YeK9YSoo_bfxONT-CBb%oeaKHrN&`wnd6jl&+^=|T z^4?{e56_P|VV`(uMb?dF8Mjwtwz!o2+nSy$Yo+uf=wyRECZqswp9zjf{-tU0NcSgE>ViwWYGP&Pk!Q)_8 zF@N=A*Tzr0ntBJ^?H%%<5A(@GpY{xV-Xl;qAhPrG_4=Xl%E0x8fiVKWxf*r0Ms?nx zCM2m-BE%=I_<}hwPTs1H*)A3Vz#xuKP{(Z(b5`kPU0xz!bTfA2EUy&y(JEiHV$py? z!-5iJak=79sb5^CTU^w!Fz?xdoF@x1@7pHav0LA;FyaKCzu^z!ns8G1CLX8sm@>B4 ztkIvs3K^{gCI>g^LR*r!}uk=3-i;JeiYKROrR zcdz=zr{=NWfv3K8?f(0o`_?}9tbW1DRNlKg{AxS=_jUNP%+!7n_TAGFe551za7W-F zUPA21y4I1`*pb`Vk<-wTakeA-az}A<$BrL5N^f^)uLxK5L&vd>jw2l%yY6+AHg!~d z+fn^PNAXSJ@*6tx8ahgEb<{lQsD02;e4``xaz`HSN|(#O(t#^zFuE%*@-ICvxcof- z(zAlgZH3=FPQLOW=J1cfJHGYFZuCm5_uaJT%9V!7${m@RSw_cKwS-`LutBd`MiZ5A zXA;5TD2apym#*k}RYr8Hf>(U`k6$Mktdc zN-8-t29#v%qMoQRK57iqXtFGs1CanBAdkW!C{VHngB%Nag`@bzV9C14H24xp;vona zr4MC)b^HExsmI*2&#uhAYM*>#S^904lDp2OKdol@;^K!swU7Pww|Vb<>c9UP zZe7(gkIHtO&)#;w+IG*X_5f%#2K;N zd&TW`?ZtNOB@u6Od6(LygGBB5Hto45IcI;#J@+vG{7*R-ThPY)piG&jJCESW;f$CH z&q!n!lCsH4JzqnTO{qVq5F$+^0V9zo3@4l&tB8BazTNxUfw1tKy#m7$W{KsZNE z1fhG4tHk|>QzIFNGcz;$umAclc;tJmZ~U>xn{SHmv5NHp2HW=>@Ak=b!DIi$g@aaB z5ArzN)8%|0_r~FY;{6WRmm3lNc!cKZh?wV}$LR*fb@pZb)kyLE4!TwOpw;IQs_zCh zC|+$$>{PYSqcrO17+lLBR?>nojw*F&nOHnWcI?p0ilZ}UO{MBqrFvAW z9y<-JLIaOB*?OyNolRDUO~y0Zj3;(!_ZKAJS-7>qF6N(jyDpXO71%sJ@l&i#sAP_?>$d^YM%J-YxCaO=3dd}QPJkTt1SRjtJ{2bwfWVw zc~-Ug>}(4;+!lDCjbyy~lzX);x1lYkp)KunTk0thF8{Wz;=8tjZ`v}>wiRA$t9{s3 z-`2MGep~VNwt~jCs+P8*Ya*Q2(3W+sE±#qG9zkJ@&(wrMZ4WuI@$F*?H1<(_|n zgG5~RnTMGtf6h4mW5%)Xa!=mcRCCEY>4H zph_H3T1GZyO#oANeUK8SD3ikh9mgUUnoLoI*^5XRIS?sPel#5JsEnZT6^~SaNC*NS z*_xtO#0YFWg^9$R2^3!mjF3zMC4Cc*Mkv=v7^N@yC7yuf8lPgR48ozQ4A+EHfJ9D> zQ>M0@2#^xs(6eXH{_~&zOndbY|L2{*{IRROO8@Hn!|i*Hb^ByS#HZHD104$ct*rjo zQGBobW0x)-zl;>?%kh54(5UBwqI5%|J3ouk56~#%VhwYnMbmUvlzKBue`ve%bAetx z`rznxB_vk0j#EF472lPclp>xGdEEo_So4Zmb9A@TaAhVr3()am@|toiqw29s_1a}v zw^NMBFVO03vvsyv9ad>iEmNOZCEmB%e8*CA#WM5+-$vwa!-bMUdv*T&`OF7kJ>+Tq zW=Q-6z|HO>u~yyfV=)AZPW4a@Xy9JTv$E=GF%mUSQ}Xp!B*&ag(F= zJE#1+Ze{n}N`G=Ly6;~8z_<3H@7{+#dms7MJoMT9a9!mi_p(PG6_0%PKJu!1#)A02q~sP^Hb%5Ozv$&E*a-#jY5{wVkIqs+69a?U?0XneHm-lMATALU(s zly&A&_F4RgxSX?(U@+_SgRE2cArY5e|6}Tr?^6ymC)Hd_+;u)S|A61diiU=(JK!<^)Ro7_MKSqt$sMRU$-{*Ar z0x2Jri&DpK5~Gkz3}9k8lUiBP5e#j#Vr~Gdlrt+}WvRNRLUpbbCUR+!VQHbkPHVt8 zuB+C2?-K7nuE>AtSny<3j#z)yN^@mSz=At*%9_t_7{`WvxCtTRkgV z*Oj&U?rQZYY4t2`4XA1L+uQ2T8ve&yvo5x#pKeV*)4KhLaOtO73$M2p-)PM~-lkWgI1v@+nN3MH7ZH zV1m(vApr>sT{=boEMN&5l1DTOF3>tujz}~O45W3C29aGd4OsDiVIwdQ)PWOz*#m{CH@qSaK!FB5++8*69BsI<_v8?h?H66UL%gbB1s61 z>Mp36giiVtXxd9yf=oaHPJlyjXek(RP6Uh3xq~D(C2muk1*b_oVH+D8#_5=!^XFGQ z{{8)tZ}pw?)@Sw~jdJU47V-YPg@ud;s3J>ftTE-|?Yu*Y{Xi&#GUjzF(-~ z9%;Cf@#1oNXJV`x7^~VxiY}d9sY+3@Y9676Y1G|(R4$@x?MK?EEOiBp_VlvmbWPD= zehx@tBI$!=Zh(1)!9uIp<}-=3GoVfvxQ`{fpZV{6>|1f)Bj>hT(v_vrf=5n}E5I3X z;;b(xd9>|0*|OjCd4uPgeQ7&sw8O-iE;E+}&Ri3{z-O~lY^uw)f>rV5jvID)r0)02 zJMNczI=J+FMAen>ifiGOH~lM{T#Ih6$hzZP^qpJTcdPTiU!D8CSM~Sads;jyTD*6* zcvZEy6}PzLx40CvcvZG|R)|gS9WCxfEv^MEK090d_lU@-LoJCXThdOpWSnkEINY-J zKudCci}rF$L1PP#d)p7Sq@QXjz133N(o*qVOWviH%rh^HsKJS<&ad$*);nk~+ z)m7D!N7+)9Ffx+JOUK<|ga|P=`696TV#l^)k02ctrm4`|MB!N+yFo`7E zE}5184vEo2w2{BeWFIB+5=Q8QJ83;pR4Gz>i8N_4#*tzrrywbXqjNZfV}T*{5tJH* z7?U9b6G;jv$@CH**pWN}9YPqNTZ$CP9WnnMk0fI+NRpATtOfxJrwUvRD$I#+cHE#O zp~PSxIWJ8)%#ZBd*$%R_pNBJ z_FOC8x02%>ANxP;9r(O|sIGsQ;Bi@`QoG5ZEBxt>w(Vxh%aW~py;0?3<(@I>kpzV= zBhQRf-B=+xMl5LsiNZc^7K^U}CSm5zEiV?6bLi)x!^b?^z~ZYmMFyKfWnq!tf4@F( z|I48LFM{_!4cY%Vc+by)<+pvZuXt_cE8Qp2B~DQO<0c->KbkbZ?=*{{b1c5Lo$sJQE@e*;#x?> zb+@9MtFpx>=UfV#)@Yj@Gn<_An>=?kyO%b5lr?))G`kfwugMn9tw6-M0Q~p`EYaM;pWs6%?XE^H`g|A-QS#ksyXLkbLJTl-gdA#=R)(Y=H{yA z=DaJ-X(yVs7n`%ri1ZmJn-dN+Z$H?aexkXcp}DxRDfw{I_WjMcgt}WscXM0a^{qAE zYzD?17uFY_ip@C~v9&TJO54!T0FOD@UGGWJ+LQv1fGL&V#GnkA?34sVl8BEzl|B!Q zkZ2N+gei0hr2;fm4lXcW5Jx0Rh)xoZNcAHDDcOsSlZcTR;t1n&2x^78O8bbG5-&xD z$q0ssYp;1SKtAoPSF_G%{D0N_%_}ta72=&W2(M;u;aokp60ilmsbF$US z^CJNZEvx7lmX{h97aEwE<5Z@1t764(mfU~oQ~lh#vdyRR7w@v4ywLfy%j>otKYjWP z|05@kNc(7OYfF1|?ne{NKAB=R(9CRv#heL?=FfGsSm4k`jOCcp!0!yyA=QXU%XjqYU)hX+$W7gG` zX;+=KjUHujgrZ7gqWENN^^J>HmltTE+iW5!7l zpGbl|jazHjysAAfT*AJq8+SEqgu$JcH}1R?UwLkQ`I(ra6PnyZ5vhBFHx&DareD2! zwaUmNK$=JdMmgaPW5-4N|Iee;9I}^`l$dxVK))-d7L9@k1Ray?aOam$5CfQ~H)sGR zC>fFJVv7HZNXQ}*9;pxZ5hF+;-Ay4RqQ<0=>{BL|k&GOXqfoxQ8>0Yh%1FthJTzQL z>5e2A8davN)0JJoB?Xiuq+rz@H_k%F03BhuX~L6Da&aK`;tN$Y3N@j^++;WlE&^AE zWCS>CPKUGR0&)X{N9K9{{qKMO@vdmEvR=pAUyAiQm`^^y*uOf= z{qS(_^TYibzX)pjGW;(6IrOi79{F@|#PcChx_+U;KK2e(hKCu#H>wMngcGjz4pm2n zi$MP{F_%^JyYgudX3gVeEO&bGp4PWXXkFU(%;54!g}p`8}9^%@O1Z-9A9mbS9+yi?oR)_y`Cxiz0wZ{ z6&(%CuMaLf8CH5KDF1X&{uy2aS)P1$$re7Ee0F8pS%)oWmu)}il6TG}_uT5tE`Ry< zb2!J8bIv)!U!8GoP3E~3iRYYB&$;EFbIv~Jrac!?eQtf#xedF|t*<^8U2-nA;@sA{ zb4iEKB_0&v*vfNBN6rlx(JgBs3wCM*>p+LEtsB z*xfiv3{5_dknm^{cx34S(!&lEpl@&ln{1+Wuz>bL4Z4T6OIXlAkVHSxQYj=uh{1f2 z3m?^$_Cgv*NJPjbGg2VQC(V=%1RO=VKgC0RbS!Q^-zgA z5eZz9FA3LcJW?#c$}}X98b~C`D4EJoH!3MDJ7)oO+zAO#Z4z(_+|cCZ?7^fzYP-aBlnsfF~Bx?(2~NzE2|}sU-&m-AN%`>{+!Pv9uJFn+Qa|( z#{q)J{$cuop~{d@!^8-6e1tk8LLFnYhC{-HW$YgzMmof+AI3L681Ep=s~(I92H#D|L>QFIShpSY6(}ru@m8vWII*?m1`Q z^3J^Ix%KF&Q>RV#k#jWhIKRjE*`G|B-hallq4TDFZ8L51(&=+u%aIrWD;P~YGI+sLB-iaV7=aWq0cZ+HwLzC)(8MDF;-#I1L;{F3a3~?#h@g9D zDXNYJvI$KnAwDn~_X{(Dv6DWD<-;STNgYOkrI?JPw2Y*eLQ@a`O(Hib91u9Jk;N_# z-Hlf1bDLjTNgTf3L#9^W8;4m@dL3_1NsM?rX--`w!!2E&9+hN*Fe(c2B%;ow78VxF zUp4z+oLR34GY3qaHq>m|NXw}c7f+q#INf6H%mu!4SA<%7XcqWwun*k2I4F5}WY*ek zxxSf&e%Ym=g_S;ORh~(^)+O%tO5W?8S`&~}lVe9!(aLYE=Ic%(3y3rWeQ0EX|w_;1(s)V{#+w0b4)CJ|# zMdS$=oLLu?Ru`IG7gtudv8pbrpe`(1_z5+2>9ut!wRP*u>S7A(HdfZf6bToptqac< zF0Q0Dv8HxoWldD>p5WA7fr(ZA3FW>Ui@Y@1?g0tTZZRevg;6w$w2Y8w5^(Eo4PPS> z)}&wrO~NB&X*Zz+l*(je3GiRQ4m!y{0x~Eb07{7Xg8+v}Ng`_Y8os0nLZ!&Pl1J%NRU?kVgCiM9G82y!LL@P; z41h?Nz8PO#VUu`{V#-b(WO|Ost%;gr@o6@2np|W~jlJ^X&=_EJn7w3Y$qw3efBM}U zfBDaM-ujc65AgOsMt<0T&d0;;dyRGLJ2PUSZ8Gm8%l;h3J9@c_^&STYitm+w=q=V? z9TYCwt2{q4-Z3yj`8?b(BwXzgtPTiMXE3^9oF+FTMja8U&gb)UMk@)1e3ovA#xO9- zFf7u*CzS{AR!F!qJyMaMmRl6Bm~GWhPSl&H>+EuLOY&YWD|oRm=ecFtGwZY`R>=>n zl76yIXt9j{#ysqdx!-|9hYm9nn(HI3mD}1itJln#GlzEg><>oI=rL|`pGlJjPM5+FIthxy&b_Y~9B4wejVv zU?fbIva&K0kpPHB!Jr9An1UA+5>-U&upMlokn#^grDZ(oheFCQkfNy61mlR(VjR&= z1TaxunzE=gM875yLz7Qwlw*RC!yzUlIgqT9OaN$Ti=>QQq$CERRx%4QRGu_4l6VZpLSd5`}m|;Sg zA!eJhTB8gKRjk65DWUqYk@_WDJD26@W@qab6zQC+c?t0akBv^1?Uq?jZL)u{$^6+W z?Vfegw>Fy^Eh0~w`|dk<@DQg-GoFrU96f0NcLM!POr>m8>J z*`|$17V%yhu`4D+yDd{2pQ#N`)CO(RMkHxNwrB%33g@NC@z!JqZp?~K$q3t)vMwyy z)qk6_=LW~s;VYK-z~j!HJF$t~jU$^T<0$99v6druY@|Dk-FY;@C2RDG`fh0TDuFWF1HeM{-kQCByi?4afq?P8PDW36GRO z;j(11$V0PNHl(Q`_2(=&HO`Tm%Xm^!a~aQZnOF9=zx|E&D)RyU_lWPeb(s!<0TD!rpxr zYG4BS&~RZNEn?N&c*BFt4xcDt2R{uJJo4Id-*9C}l(J^Ma$>74GFHDXT3?gU<`!^& z&4$j;!gW?zFRimW7UsWLod04;e*5ymXUhxQRu(>9ng3u#UaM2y-6a{fZ8lx8imtZ^ zuBopV?{}C+g-kqt@wcyrz4P_(kH&u8XX5z5(SYwf0=#fnBA}{f>8k8)#}$zG4JyukhHJ%jAk1YaKpL`8 zXG+69e(=Eu%m-lpDm-Ez-+XuEJALQ8GtBq1~whR63mj$hG3|YP^bor_K4J648mncR1&$i)*RDw(C5)IwX%J05?NxYW z6UzRjL3~AF*Dswp2-EE_i{<6zz=)4ggC=wgpIbdTNz+skC-DR#ln|ppJc4pcMP)C^ z2or;CMMwkM+*&CLAE*)X;*(KQNC0a>Mu|3uLns81FyccfH9-i=O_@ykXuhD)C=xoE z7aWKqJ;_J|CdN{`N|tHZOMty5Uj`(1@>ql^mO5~P)PV#D=Sa1wJm-tqUZ+}@iM@jmkbjPrB&9_v8Q^F2Kq2l_Sj_7Obx z3wYc&K+KoxAM&zqNats?S3{I9A`D|9g&q7l!Z1D3U>RwMiZp~oEAx$RY?#tNgk~)> zc{<55AhdHpFl}AkM}aRVgmnaJUW{fmGxYiB&F%BDp3Y2do0Hb&So(Nb!NVna4_24_ zysn~kUHRR0#dkakZ+YZ4dZeFT9COfYT@^g?{K#_(QwrhH$e*?T$Ju3Krfc9pfOtF6g+xx!c>77<3Uk(^r;QeBY|q%0qoz&i8U_>=)29!vF3t zzx%!Yf9V(av|r%!PlI0$3F({`uKyxjuZdTJH4J$e#zh*YMZlx7AX0JHD0UIbxCs51 zVfw)#oqdBl2ZVL@3DFG>(e)2~*)O=GPe{ktq0eVUw$BJ|Ump2v+~&49nNOCM{IV$T zk!$5cj~zdI@BGPg$B&*n?t1U|)~oE6SLrp+f=lih^%fCzbG$2#AFt;hghUgMytjgV z9PyW-!`>V+^sS*o-}!vVKfWCF;n$z_95<-Xq(ObB4jC|Wp5c= z&Y!f%X6h2_DNC&;FSnVx(sr8TqM42>=B;+LShH-d^U~SQYi(V;7rWql*t%NHbe%ET zb?!9RxzmN4H{I22vg_sRl*5%Kg zDhjkV6PrusxjI|8x>*XhdY-G}TvrzhS1&tPp9QXKtz6fbyL#BT1}%1tUhEpU*u}%z z#m&Om(`JpE#cCIGN2fWfmd{weWU~Fd(Kho(&A)#Ay2(D8`f#LiG_u&`!6Q}@$|R5f z62>kAnUX@!JWrzxbC`IP1WD6|vZ1#q7$Uioog2`^F7zBc@v&~OhFXFfS}HdskC;V7 z+C=sufQ(2JNr0kAFYyElnVlFEo&~MD2X^Ex5))vPa^xYX zwiFH_ifD?e;F9~ zbU@(q&qH5Mh|nc&=*-%zzp_nNyl_~P za%9-ckwG29f?f;@dBNv+`h~O)2zk~&l%+q~W`;dk8~b?1#z!-g9$IJIx6As;F1vMc z?vM64E%rIzEzQ2|ka1&a#y3k-FE33zyJYiW>+oIHzQz0ZAK?E5Mk%ycX@@he`sJSo z5C8MPp>KRP_{~8>-X1piz2SpD_-e>Uqlfk!JG9q?VST0y?>BACz!_7An3;V(citEC zEk;<{jI_2JWotKjf!(Nu3q~zmIA+n(@%F1G*{_;tzjXYPRg)an&2(^??qD~`Vg4A0 zxuYEBd@bC(QNj_JJyHaS$C=|B_Y$xg>tHp`=#Mp~B-z&vmSY^|kM8p4j}if!aSoPa z9c;%tI8JtOo8qu`s)O?+2d9a`_n7A3GgJ6$CONoFcJQ9z5N75OVz$I*<`TCl_U=;` zJ5O5ZI%$F9I9r<$mNN#;oiT8xO11w*^=(MExyapnoW)Jb$69Y%ZEl%@o=Cnf1oNJRF{Vjw^pMMc1nViD9H5)o-J zB^ppES&$Y-k|Gbsfe;v>d~}<`aV&(r#K=hMBZYVpNM@xu!zU#ra3GGzfv5vuQXsWO z$2cxb$$GL$#n>bnLN(+es1=2xt-;4fbV zwhaqv9~$~{Sg3B>dR=GkqX#MN8L|4nNd1B27tc$cdc<^wMC$Hrd8XU@lP3P<*pQA9 zVJ|F#pYPxPG;&k>(vYWfg4;gyebO)R@t4uR3=4ZWH0r@u8}E;e`^h}v-on%$trPD~ zi1~hU?6*_nny0V7HEaE~S+NZ>qb|&fI6X7;*ew4Vhv4$1K3aI>WV_xEbz95#SgozB zKl!6`;4;%W<@Xy~H@x=!tzxZ(U7axrq@zMA% zKb|oHIxgK_!b41VItACnNj5BaDoO8Z94Xv<7%b z7%dxaG+*Cnp1#pSLwQ?dXtcmUy=x%r99qn;hp3e$)EaKIbePeyVX}n<`tr8eK+d7S z5<{bd%PGYuvu>o(t}#Y?MjP!OZM1!)(YBFBJ4P9q{$zCECnJ-wMmt8zhb$); zIZRk$Gk&qj*u^_XE!;PH!SBQ7%^x&-?tmFH`~D1%v9Yo6C}QH5Btn)T5f~93@gv-# z@eK`(uqmP;hnOmU$sl@oc(}+>2QhiMhA|jA-Y6)5K27)#{?BKG_u{MUqTq^R*d~yK zM@@*t4n8lUBp~3x83l?t1z|*lNKT*0 z0yjObJQLU-fBaE?{`i0M*khRddpf)?$NX{7YCpcOqu=Iqo_|TU>Gh?LLB}3>A8SrM+8W~8YVFv% z#P;KCn-42(TD*_Fk9K)`^=R`3n>T~aU+Y`H8sqq4oWrv*_D$1|Kb`LWWZs#EMQ7@a z&ea;7uU>xP!K(B3mUxuSaV?p1^!7Zbym<~;b8S=ST15YD9k9{NGdVeh(_}qIUa~gX z506WiE+sxr`N!a~|EW9bE8P+Q(1pt3-wql6y}`&%Lq~KTKCdv31 zGk@9O`Rj(xU#UNT#gGL?gBHx!S+Gb~-WKaFSTbnA!hy0*zEDIChn5ds@Y~=8%k*Sr z3FQYaSUhmSvO)4@q`TlZJvozY#oz_Y_2hKB;ex$}3rvQ}=??t`JN4(A4V!;x`1}LI z=kL;=$97=YJi8I|Y(~sA8#-spkXc5$vy60R%E_g)2_lO0;)$wF@@kuaYn936Yyb&?W8?j4CM%ap-iF^P(1+a6}Kuq%(p_DhgET3B?4Jf<$^QI?uTy zROA+fz$2yvkIcEcb?f%|eSk0GBk$*Q8@s#5G`rpldxa4^$no zZn$js^qgzsGRt>Uty)Idw2rfBn{W4Nvt#?c^BrF3x-ZYb}jQQ-z~Ljo@@DbkJXz8r=A`-_F|~z^Fij%M%q68`Ph@mM;c}vtDk?e zZn8u5B)iIKjt|zHy|>{)*@m-4E05p(#U_8YZO$BZh(_ zCjB^Wa*qjvmx zfpWTX;N0H^e6B^Y$a*X> zQ2;0wQU5hKVq6G*D8K;|JQ*~EOS6mn;fi=N6yU&uM~;f}z=bCZhs4Q+P9`}}fFe>9 zp_31o7!hm|lJI=t^SC|vi0FWTQSivkffj{`o(TFh`DFfUNlejmnxhZgF=&zglR^#b zV2!imENGYWr7*j6Pn<6uqb{jNAs?L-qOnN|jCd^P#fby8xB+rA6ze(seTV!$xqAM{ z^GDWm;Bmm@-MX{w1}r((ce!8hRgryvPaCrJ_Ew9sV-{790*kZGJzi$xx-U=F>@A-D5VpMr=M3xXJq3=7VQ9?Q+e^%Hp~a90ia3-rS1iD|B^rL6T9c zmX;RJbQlJ3=OOK`mL6*1C_fWPNkmUA{Iv@U&WOIgzJY-Oc?0=_G|CJd$Tn!uAeO&I zjT$v{=ulCNGKPkR?2?a+7%_tRI0Z(J9zABvn6YEWj#JA|Km9a*{P+nICh!H+lP6D} zGG)roKmR;+>eT6KnK5GqU%bh8{UN{p`s=J&vu4kpJx47p6!UHavS7giCdJ5NwJce( zgfRfJY}vBk)WR$DE7Y=b<;sm4Hu7X05)m*&zKo2T_y}}DAQ2uZW}3xNzezA8q8cr2a|3qV9Z&McxQy95Y?>Quz55ft!5s3nY3 z01(jO0vxE0R|^=~6=6uw0cZ%A2r31MA|+EqOj62d4q=nRq{5EC9HwZU6M;u)qC7_h zJ5;1R>~Kc(mO(!GD0EK{heAa<`K2QI%!NWBr93ByaWOA|R?eE3!u(OJ=X`$t*nM25 z0rR>Wu3`Sz_ZPeVi_i66?$>8c|Xo0yjy71 zGT!FHRO^p(Z9Yt}`LNLD!+M(!mFHf+^Q(Us-&EsQ_~ugeEAMJwyBC-2Ulh4FPCN8e z*QC+V^ogEnz3zcJJ+p_yEUNVnRF1K@|Fd2BIE%6wjzx=4-u>17)+EckpKWrc*<}1| zk@Aa0!YaF%)mGsv4+X6>^If^;%F1nLR{rkt+X}nv>})qzH<`zMCJa`2-mz)prj;vJ zE;U-pws_IvxpU^un>%kluC4ZNd>g@~SFK#Ndev%;tXZ>$7YO;9XoO!mVHa-~4v)7B zS+!~vW$<|vD*mYo&yO~!h3|gnZ%enRf6s_P2tN_aUE<4)9C_O%|7n2yHstO-ymrgR zDXYR@OGw zHV*a<@W_1dzlBkZQAq`i0EkXx#4))4lPP!<>6ejFz)1QBj`IJ)@o+F;gc>}P6i*`u zAH&J!!y{(tlKP;WP)mcP$iya1a2E6dYa*(mb9Nl!To5vWi|a;cBcEPz zHK;=8sVgoBnFy>25f_S-)8quHC<@S9s_+$aJQw)#`6J)=2#;M1)-ZqU_OqSV0(iXM zV|m0cTT{31&7ZKVWTWMSOZL?f9qrS`juy6`RRrlm&QzwMpNsiU5B1pTRa)Qzd_gJQU85){Y`3h_g4)zy+7hm zg`sKr81oWClfub%cc$6g8fTh2#w>G&L&gI8n# z(#;;r*19ZRX18pSIq?x5nW6B_Il#!ab<0+Cz7dS?2tyZ{th;Kq9ou&ZZx;@)@p<9) zI6R&Y+A=BX7ydDhfV^Nq1me%Us6VRD$f%ze1Bjii-4Vwl;)jV{U0mtjan=sqj`LHD zCmE5Ept>FBXW%H~bi~Qg!IAPPN1cw6BPyzYw2}L)3l@YCjUDO=J0j)htHgH7{nTmR zBt3PCch~T8-n|i#k@Qa^RSk^9P`pCGh(d_`l1C97za&w^V`O9`JmOk7AZ1EA$8$VASqbJ0=oo6xWUS@WGi{-;PrjM5%YP#n1JoW6$wbpM954|07sM*lG zd7R~&*rTsrdo`pwKXW_$BE$9RvkTRMjt>qVd_2pnVWwIAr2Vxzdup`zRBG>eptJkl zpgko+_7&^yDjKr;w%)G1;buAGOtXgVNS|^jdFr9KU-w5%-yJb~ckq(E*B9*ap0~|& z{+4qKH@MGP<2v&aewlq>!OT6GnVC2+>#Lxrp^vx90g99j`ospLYy>7yf;dgk z5w}e~Bd&=MMh;>C40eq}p#C1ma5UIjvLHgzA%f;vB&pi{Lk?(tdkf^~BUIa28 zr#;T_wKN`Q_;E&bXrc_bQRQC&s=2OKTVrn=q?RJ@{EGLL?+=coe}=z{nwh zB_?Ww$s@v1!lED%MZhS>LbZUQM##XUa6I9MkcD#+^0-i37W^LtXXC<>$;A;7icHOQ z!~eNf7!iWsf+RW$=Z9qhHRT0sTwYq?(lRncr#U_j!MIT5k4G(7rd@=Jf;bdUkZ{jZ9 z+1A=iJo+#99=I;F?}nt_n{W2mQh4}Kxsz>`;lBEzW={;wnnoUYKF<85-T`?Va^U5- zgDxboAjt@jfuD$&e?pScpd8NrK#6Mt zdc;AX|Z~+Acf(R}YS4?E0fG1a;>nZMLI4Wn# zSVr_WJRK%f8@9L#A{-~&xmp$PxAlmT7`h6IYmvib2W<21)q{=m~XY4^V%L7yajMCjOX_bEGZdV<;4(QLJ&P z#V1Zl6b=ESxMh*@J~_)9-^kB9y8iHWpDsTP>fURtmfoD6Lsxehy|eqz)_vxm)?4K@ zaBWEcjfs7?Rid!R|r?3vENXZmJMhGtKvA8ed+ z;K_W`hFPYM=9twjGI_XWf2Hr?d+rA+hVyliJBo*IySsQt{!d$P_1uu#e`98!wdp#) zr)aH?|7lh9!c}2Qeh=1P?{Dy%m!Xm8z+QkiMj?Y@$7Px@)mUE$p2zMCbHFr5KAU&iffW}!v z8K$U$^N6G3?ng1ah!df=7~vG?3=4O>=c#`F*!7!#^!etyK|lOB=0_cPT-9sbj_yBO z^_+96*OIF}mk0M=8`oz;R-Y~Ty|))@?X1w*S2F-4P3v_`9}hHpqI2Mhj@gqzrjPaZ z)&IQz(X9P-Ys?-l*3f$?-?4I<@tP@{7mr&%eb}0r1}lynaRRr^{4%Y2V>l|-M#S<6fsdiA5L|+_4u*y2 z&z)ykA}1%8Ej2YQIXOja=)8T$A5UCw{GRL(S&9rQ{5b?5P4U#sf*>a%*Dbgw-CM$0#6Y40ayk%d`WnPhD4#@ zBtp2cFkTgrk(6=izrqNQ2=0wz3#Y~L1VQ*GPA+^Eg&QC#!ciO*#}g3&Clo&aCmsn& z;wDK+OksyxB_$~@#;Bw)0yyv@^3{0BFQg%q7tN8~e_a;Er>oytrcvc4ut*MEK`^Y~r2G2i!}-NSID_QY)iezDY9bW(Tu<$*9=9TBHOCk=JEZSY7y|rk- zmb-(u=Id|1Icjt6zzvxO>(VxCNIYpAGiFs(AEPiWqadxt*L%M{57_&MiS%sD-B z`iVhPoO@1i>_66K%oxi7qYnXzsW5aDcHx z=w{of%?_~}ZQ{2&CT%;KVtg!Z_lfkq?iqXBZyddrdB!j6q*s>5^=x;q>{Grur+sr= zFJ-%VW*@(jUx>Gxr>Gj-Hp(10FeMr*aOldsfy_^P%yIC_vGvTcxg_tJoy<9SI>+){ zj@5;1b}8(9CF@#HmTyF+f8>oz0cpoBrz265-%tPynp zzk)v?|1*rjRS1#l`J$X?U=$3Bls~RS!KH5~&>)F|kWUq?AviojT{*U?g}NNY6fsLQ1W64Zc*3ka2DVu7<0rvs04K)_4*rY_xP?!!@T8dMi| z4>1OyI!5>`*o8;xLNt%JcqGUBa$o~f!p(RcHZr?tyF9KJ*^!T{r5cRz2kx2{s(<_-tWKbUjOao zzw9fEc1SVbp0B?(zyGE@?G3qoe$VW+Cbievv}^l0NrBR5YPwsF?*-zN=T zHn8WoF5mY4>Z^b7V37xTJaZF|7=TecJ`hh32!)&=7oTg(`343A5&^@);xAkbvv>C2 zX%n*QVALAR`1Q6)+uYLkd1mdscys63TiZ_;?7DDwuV>-z^F_Na7F+w5T#PTdm`GZB zHmdY|Z0Wh^vU4$I7vsu2!plyFmU)Dgoe3{<3okoxt!&TvGPA2?me*z7 zWrzLBY=Xj)a%l2bEb|l{cH~Wwrrjw%5zNl1hCNORmI}_@x#H-zfA; zD!3GzXX}+^dOF4QSon^EzJyD@>gED><@54w86-*ZCE-rOqr|PA^pC)({;5cSynLCV zvWSct9yKsRqDHv3cpcQ>`2rSP6j#LeU@tt{B&o^7INfL+B@V7`38coKB*MVE|`Pj6&T0SZ-gl~NzbQxiO>*cy##(Qr z`Opz&OGfTnKXjL|!S=BRTYC-KJY?{OAv(*odyMP!ZSTMS^>1LvBXxStV4L8`vqGNw ziO48OZ;8&p^o=<-mko(X-yCyKN+AF>4de;4r{Br-S5}&j?Zo%0mZV4uiAq<{1JOZR3 zQKWy0kN*mz2&PPLVeo(E5f{Z{x!?ju;d1yGnK&?TiAW&=8D(%tT%BSF3N+!FFoL3S zd*Tk|@nIa5@_e9F#H&dujAel>#c*;e3Vi4T7*d6l4j|-U8B9>9h{CQw6&)dyV&sSd z^oJZ!!X|eT%+d{kByDNpBUg{hNH^#Y00Nz$44{Ytq#}ny=(NI_(uzVxg$(24U zg8HtF>9a1W$GY@B8*{Wa=V@&z=(p{5e>UUWT3c@G?#S2Pk~d&W4ofuJ8!~#WN$IyT ze!%jWaVsJxt_bP9#9!CQTYJ&f{_`*PpY5Uh>&cNbTzgMBI%tZ$_IRrSV=c5snhhDY zZ}{L{#`?ymMs0E*xk+DVL$`h_x^x@=&DXvD<3Ik=y?YPdd*M}<#fum7M4spMqzEwb zt8BFKoJA z)Z}xg$-AJ*JHP2lPLuELCZGJKtGP{=vYI@zZ>g%mvvywez5_$0XKvHz`lzgx9|x2uA0 zmHTDfIpLpi_+-?VJpQ}LC`eSt!_SEzQKYOR0iz}?3WdnX0-6wXJeg~b;MF)4F3SBM z!Ci4+AtDgq-ryj7l@E(D)Fm*X;GCrRr--W56(CT6d~9MFMcBs(uuCTE8=M!NK`}Bi`u5vz|M{11zWrP0@BY#2+wXL~?>6#> zzB9TGUea~=`kqrvew^;`5xr2+8bu{GaB1-Lbo6K{o|{D@Jbsm zo-rYOp1tzz2+5l{7l5*qhS^<(dKT67Vc?Q zXS3|D-gFDiKNVkiJgV$y$i1UsmClhhuCaAzGU`3^A7998bV_?>67+13|BL;huMQ`@ zw$FL(S;(*6yt#Dit#_fkUAxBZmus3& zmo}fc)9jeqd^AJ7r8ghD(QKdCd?c;eB}-1(J(k|=kkss&-Ryp+`Q)wU*!t$!y5@kQ zw*iH3LMvWJRlN!>eGyvL7*NpQommr*UFM&Zd&NJ2btMAa#S0h3cvbk4W|*ppi6|N# zH88TCgRsjgkcLOi7!?@#%Mns?zz~;1a50&`6y6)2J74B&>)3f-UzsUQwhnq3O8D~fTW zpdwt;XCauS&j<>wa2BLoI&qUh;r>SGmzz=Bfh^{U7$>Ex1axu`v50{}K0*N;RpjHh z+?3GC%kr%s*V@t=R~{LNQAzyEf?4?m9hMr(TKL5n*LUDtiW?k-bpd(LwE zVb<9mi>~!t8rXArSnt)*TC3uEtxD>8}p% zw=|%~Lf={QFPkj9xP0!}q0`*8r@0K8dPIM!{fKGSBPW>~jx!xLX5WZWyY+`|*VW&u zGkCMM?nXVG)&2WT@A9MW4?lF`Ek0iO&DJeNF zF4^-+wDYM@`;%c-Ct?n{CR(0Kv%j3_=zY`P`;M)5k^S}3BS95zaaHHCYA)v0ol2{B zi+^$=rRikqv(xD>F5iCXTmJe=@oT%}H+w^x_k}jwCA|x-eiv5%-ml{QwZiw_#VyzG zwOlJ|@hNQytZWIYZV9Vv3B2DDaIYnxqQ$qQC9t9;@Ii~$U3v2-ZL@jFuC3Tby%S>{D9KmbZ8{wp^%eIakqgG*dowEW71cR*Oqc zi(_)jk<=Eqyq2Tsa;EFe7RQtp=j@i~#+Kx!mZYYZ_{Z;q%ijkSHwTx#iKu!NSo9*O zxH0H%-PP0zpM+b!VaY7@3LZgH9$@|PoRRT^kUs@S4U9q&NHU8gM1D!)=g|1ae|!Y^ z7$UqEpztmPCs*SrCk$Lg^u+4~xljXHcq1upiF1l682Ml*0D%!W5*39_5#}&LVTuu? zL?opTq6*aoWdcmWBNhZWR40c58fMAI4nqGiMT$*8qa=NXL3SY&9fK&i9Cf*p@W_3J zk~EEdaSEg?C(<{HL8TCMIxn8Gq0<3zvSd<{lqG?Yel5qnsA-v!3L`W43_&EF1t2hp{M@r^Fybf+V{)xeY2g1k9X7>XFYV1#mI>V zhmPAnWx}2jBX*1!wr%|IEkpD+4ja7MV8~npgNeMRO=VGtf! zO69Ein0VBel$0DCmf(6O;($Zw0mtyet}*7v6D{4-9KEvKLT@<*6xjL{9tkXSjjC{q zuX2vAJ{Dc)65HSs|HR|Q)2l_#JPTi(z4_{N#_Ka#Z_Z@Dy>R=zPx*Vl$`<$AEf(<~ z+_OJkzWp)a!N;hlAHyEE23EFu7q83fr8r z+D_hSyV}@xwV~~Dt(-}YOKzKMZrh35ZO++kM>5)u=e4=!v^i(Bx!r0zeX}jHx-Io( zYuc-iDbGJ9HhqYyX$dNOA5{J}y82acNmD?6eZb91&xnFcercb1aZ&(0EoRiN5@51ZI!ISZ4;nJjdJ{%zeKuE-~ zaY&pH|D=j=P63N>P6}(B7F`4vr~wv?;MiCo74ei7X@WzfLI)FJjbb7`!j#BCp%^HE z7}do*mz0w1Qih{q-3Ii~>7=G7)DkU1F?IxuoDK>n0)zCEL-Yh|q%^@H@;O09q?8or zLYMGlGT9|Eaw2q_@g9Gt@b~}t=4*9){Q4X1?wyDA(E7QP_Ppoeb??HQbeS6f?_TcLF;Hvh3`|Y8% z?Ln38K~?P$_3e=j?GcY;C8WANyska8M&8i<%i06W+XE}wuavaA-DZGjl&sU@NtIbaTe^q&^#2}a1F+uXxY=m6|M4ee5xVswu=qv$6Xa@IsZ zc2TfN74A-Sl^BXytkD@PP>~e-lpzx%5=JpI|zC%s$=WyT^~-F@Dt6(T1B125*`$ zWaVi6Ukwc=^y#BTG$j1-mg&BIeCyFcUh3u?xrcCS@W`J<&`(Z;D|z|y6{ak{0g-km z!&V-O-0d8@> z{A$^&GdEwk-*|I2@9pK1_ZRNGKa<;X_U4Ckw^}dVZS{ZH7Toa3tNhdDJMCigD(wiY z?g)9*5mck_DOFr8>hLa6ggsIuy-~zISAskl<2NO`V^sa3>3?nr#v5mDWd z{Pa`y`%mewpz=f9qvpV(*Vk_~`R6|LOD^>E&*Y^9mX~E5)$x(nZsa#_NY(PEIim(f z5f;TOMgm53W|3d=2#G@AkxvI-!o$G|0YC(Y6e8j#Ih4UyDGWgvcn2o~rYT!@a* z3f3q?yMi)t>%cx#QcEBy?h*h+F;Y;1P+XKMVo8T4z#Ple5)oDmOJI|>IEqhY@J@vBaT1A0xKIdE1Vy=C2pZR|c~Z@2M>dQG+&IMr#^uWr`! zj{p3t`{LQBjAotGnt7`C4ENsCj_b{I9{!7y{!E7v)2+w)M8OW80GJ#C6RhFG*nvkO;DgVT30WK!tO=i|KU6_50!pM}7Z5}-GKE1w z4c&$d(K?{f0q_@8q6-UjjLxu2NkWFm7t1x|heY>89i#(m=W8@ z4&VCA=*?sF*Xn9d>(gT(81g5&yuQxJ698FS;3+GAUc`uoF9Ni;W7vO$#Vo$1-rL&; z2D5W+dIuyQa*Z~13EyrTz4TDx{DY~>t#6o~z3CKo+cCV*>UybtXa&ETY8v`*i_fF2 zevkJ>J>~a{_eVe59rkKh`0L$aZ_Q)gx@IOejb~ecCH!!V_gooigFE zyd^d&lA1cA>)NAg+LE4rOlf+b{Payi?X$4L+G}ye=Y3@!dFM?Ih)^h}mw2~Qe!cRK z1=T;ns2QdTDn)SQ?O7q1`WzJ1|HZ2Xl>i|y#GP<^bOg`GjiC>>#PJ{z1y@AJ)d3Cn z!^6d}lU*vZ3j!h&1>Y7WIVAAGnubRd0V9@$Su9h4lA?9E`;tBgML0?(1vpAA0xLKZ zb7_cH=s)b!t}rEb>6@U2t_o)98w9aSVRVtQOC~}YGD&HO{(v4=TRkd~?}Xd~<*V=M z$+VPqX%ze1kq}xTP_mxWzkh%A`>S2P`>N*;-)eX3Z17$8@jBWwIt^I(z23?$!#Dph za)-g_Jx1gA8%;jwHuIqMltUxOns*;@aKH$&!6Qr!N16;8zGv|8UE@Y>A3MT$?C>o! zM{NFi*xF%3=IHbt(xppR#>2d|&Vv=T)M09E>{LrE3TC&uNKPNwPICJjVk(?Dxy*4SE2GQQF)c9yh~L< z)vD-5RaB!Y^r6bHTy?!n75G4v{6>}hRu%PF6aYNRjER%RlZd!*IO#b43%5H>SUqHIY)K$hU#dh>Uh5DY`Mz4P<6aO zb*Wkv_EB}MQI*oHN@-HXJW?e;S0y#6Ql6_~AE`hx^@SqtQAd13d+eju(DL`OHE&ZJ zo=2C}g=QD~hG!NP6#(+D85HA!60so2a=LQc?wfeI5P%0L@}!1+i(HA7(sAyFeE;b0ys3m6mAb( zhz3T0BK#4gK#xpzQ4lf_+CoGvaK;p6um&KM5ek-Rm;TTPFriEIfv%FnE`38m;7FV= z{Y2idg2^I_s-n|K&U0U+wf&uOH;~9D{Fu z9N$}edY1w7yXgJaS$}=EVVipm+om&o=j`!&j7IO7JbdrMQG0$GwY!)8uG#uKX6bL& zGuS%PaO*Jr%_9e|((XISKu`X*3SOb%OHlcnde&s*zxF+Nh=6$Mk|*nS(C6!Woxf~= zK|&#KO_$%R3XIINS!O?%^%{dQl{yS>rx_e8YpPxxS-`Ozk?^>B8ZX&l?9 zgDLGcY3(O(w)rV4qaihCgi z*GRtQl24iBTP6iQkRs}(xMxz-V=3Ui=P-pN(y-(Mb^m1Jqo2GHzemA$-Pi=yCogXl(%C!(wTDU zT!nP9Kss3{#eS43B&kS}vOh?14Kj?0PgSWeRdMyom|A7ZGnvPjy4Lvm_raxagNvTW zR>(XCL}!WkDEot&$1j89zk^Yb_^&+jVgOX~^h86VM!}JAMf?f@8T=F11wbgk+tE1+ zccKgmLK$2dfkaq<5j+z{aDJSV0@x8SYHEq{Fd~M&+{Xb&1V_k%O6*`kq!^@i5eiWd z4Vx53C_qUREQmQN;D8LnNCZ+u(B#xWj8mY)=mIn-16y&IAfHCDCeDc7Ql6Au6i!M6 zM2sU?CM8x9G{tR%x>y54&YIaY7Z6@LckcY{U%v0k_sf0NyYn~NKXfwa-2JDneW!NS zp504tad-Vyee~BG4c*Xp$YvdbtrHE6dk-=0H+buS!CQI`+A?y`7Q;cC2I;QU)t;)= zb6}@Vomnj9sRR>4F+D_~do;&gilwG&*S!4v{39adZxnz2{CRavgKt>=KBwgMrr~Q3 zMz6C?TxglGz&d-~v76Qbw=F|TR-GwZ?0SEvf7Pzgx((Os*IaD)-K%l6=d*3sU)aUI zI(hT;wd%K*%A4JDoA*Vu>`(e|Fyq6)3#gPpGUk~SR3oEz z9V*MEkQynvQKmAyP70`y{O?I252cj1QrdedzDWwLmZCwgL5*aiOke6-De0vY+bAV8 zNl}lamZEc> zdLT( zjE{mxJmmigcuz<56C^#qiI2*pl zQ4~QO3SJE<_$^!rzSyM}oZ>T3sc}^7Q=XD|wHT~|3_?ZC6q2JF(7+99Xq_Cm6T29P zO+g|=Ak?K@=*BEO!i%7iOo12-(lk9s;k-nUr4~_@S_leuIK=7GLxgTqfGV6F%|Ra` zZX+l(#LWtuoEjpo7;Ryn-tyWfJa+v{ryu{;z4L$e>GDsVo}CS}dW`L(HKo7y%)SHX z_0u!b(pxch$jY9&YkCh{XQa2@KzDr??e*QX*Z0?5*{}c4KmMrAw?^>_4WV|`s#O@| z&cMxt-q9T0qgPyBCX8WW;Ry+e{2|hv!h4}{MYbnX=WLIhYmzX_ByF|LjqR>Ed(IZD zK3TNbxpcYvJ&Ul)BPkCpKa(;(NHLA-C|M`PHA&G8QuJe)$K)4M(sL>Cnam?mQl^ri*&rhsQ6ty&z9$_g zK4weD^QBXFCAXV0mBdZYGU>(}DeaY%{zl6CBvnb$T}jGqRi(XTysAonsYq&65Fg_n zwMA9Fk9*i0S@9w`ug*WErcBq1o$*wp=CdDXBJ{75sHOvAFJd%PK`4pzBv@324I5VB0 ztJLKvd{I)s3#1&S81&I?YKh?}_URtIMFhXpq6xU;)VPz-CBZ3-fFxyDDeBs_Ymfic zrR!gNbo#qi&u?_JI~(-*aZK-ClXUw{*VdjrNOw^`9i#rb%d`hB@2j(-kM^qW16B;v zpF48sc)nU~(xge^(IJCUriXkqqT86Idz>~m5&9M%pHN&}l9g9_>RP&`YwTvr*qu&E z+nmxCm}f4u&6{U)dyQ-Ho(pA%{O)hNQvKVRhs)1BG7Ep~cI&C@%_isU=e7wi9g|-l z&VIWss(EMByG{NrJEJ~qi}<)Ztko_>e!{*h`jd4*yJb#?X=2CTsE&il9kvAut6YUS z046If)0NiQsv~z)j(1d687lK6m1UYtrCYA#16g%4dS0bc=wm7Nr3@pH(eHs24rtYC zB+KOSDnT%j!6&h@Qbv-n2!n)3a^Q}UD!Xh1#~UA{jF!&>RKg-WGJGXC0%PhM8BBtv zK$0|`SXreGln|m9WlJ8#(usV@HCsLu-ymf+OIh!w#HUjBd#OepD~naC z^w+GiGG0|AK5b8IY>TXXA6nKNb^k?3LEZJF65j}!$F#IG5M#Wm;ZYMG!BB{1O;s~k z74cET#y@cU{5^H-^0!xsY7sp0$cztN0~el#)8c8u=hZCA15|d!;1Fj<$2|mPr1-G# zaN(Sgf`3u~o4794CDu+LJ-hwA?|^Rx4){U8SJyGxJti9Tou=3CSM7fDhUhHP zA80gKcggT!b4QPz27`RRAOQ0I42z|VOBq><6<|BN&oAoJflHS>V`Jm^tJ{Q>o5wFD zuh<_sZ(r0Llen$Usm4y3JC5g?T+CnXe0Q-+>0+0AOWi8>Uad9{tuqgA_}%--3eTp^ z*Poxre|0?n^{Jva&e?D6lioXLy|>M8*^~5PZ^Fl|!EL*v+qQ+bnMJi9h;BCyY2O#$ zVSlH??ykb(hQcIPu|HO6m8G=LS6XMO%u`gBDJttsmHjQ%(L$BOE!E+4$ud>4%94&` zN#|}$fi+TKmE=_{UB54nP9q*mzV{^WQaKg>w z9?g>6@+H3-DW2JAjl2P4?nfz=IQvv8mZXO&Rhd$m*QQM1(Pu+@;*++7`u8ypn*;C2 zJO-qcTnYTlV`xaIx0g3-eE%*!e)(wQza6P+;-d(WJk$J=M?QMtt2nBNXgDN3hVPL= zqCgd|W*7e?pG;y6K8Zp;DTf4%6o3d3Jt+W~*u(gy7h;2w4J2s^i-j zq%f%f6P-+Pi$F&xMtKpoum(X01t5;*Xq3~T1A;+1Nvz=zy9hm@IrxPj7^ETw$zhjF zK{qKK6HRc4vxY~3B!@(AX&0S%%56uK=S>(bEv;^U>CyeKefs`q{~_NF8u-J|{$0oF z_nb6BYnrasuYYv8;32*krHHOFL-h5%9v2s%n|l)s zV-s>*&nNA+iQZ%#HQzLT&i=GTR#^+Ib2psK-*>Ti*SXSz*Y9ojto+U6;mV8kOFbI4 zdp8~kX)=#{vBm%8dcW7}ufI7E-F&Y6ok#Ke)5R@rxgU?+Xg!(VYMIrxFZI*@l=dCr z?FSOt&)n{Czu94vqSzOy*c+{|&Q&_xQQF*89ZXc2#j4DcRW>;?hJ;0nR5`W3DIFsQ z-Ig3~Nmgl+^$qE8hUAhfc~!`hM1NLkDr6p`fa{SI@IVTxl4DmDHsgi>3%L+5cbb{J58O9iFs@HR%GUb(&#-tLmo=NeHgd3!k7gF3~ zDY{mQfbLp3P+lsP&fk@yA4$p2qy%uTlcH***hf;vTj@r#l=4i;c!Wfa z@NNJ@)}*8)s3b%(F2Z$jQJ^3?;93aIPl`Vy_#0SpNH{+!Ea0Ey;FcVsFs>^E7bO$_ zry`g$IfYF?z&JinT?z=HJggzufmUj96o;2#`{OI`;E|&=$5FwlI7A95^noe}#<2$7 zbd~6W03A)UOE-j*lOp6ZI>jdC1&pNd2$hhC1!5wHuqj9s{UJIF{84CH^hYQZprq&z z*MWCn^!4?7{qH_~{;sY6weHaG^oMmGVbE>7L9a;$+GF)}hZ!0g^0Z>d_8rUvm>Dx< z=FY?d7)#QOQRpr6X?hVD7{tWz*|Qg^xmDJu(l%MdY_^Ku?V7sf$c<_!VOn}XhN3U1jP z`tfk$$163ho>gt<%0Ic^{&YOM{rK$;i@Xk#l#YWpI^6OUXKpJlvtD{v>6)puNKoyG zQ06|0Dh7AY#TI7X+EQ=tr?O{N?cturLM9Led97@f+?r*&V1#TqH$g}jWziYvp^K(_l*M6Dbd6B&^<$_qQe z40>y%^kyl$Ri={I2bhG#SZ0*eh053RtPtE18O=7S$F!{Z)XM0QlAp>#5Trkn(q768 zMn9CIn5EWBnQs}m@&rVg@m5)_P*kZmgxq@X2_35-IaIfRqq9JwH(X`!Ig zCC-|@37wMYw9c!cg9i`p`_+H}U+Iqg)?j#-VMDcs>FMb6YBzsd!M6(YeNYT8I5{o@ zYckwi(HWPrXa$&juzXcZeM4hfR)xp4oGq3yzwV5kxjSXiq4dp8*}FV$?Y($+=h@<2 z*UFc=S1vjJ@VB$ID?RHEL_M(xe|jL~nQh7oWB*sXLf_aVy|syJ-s=BujaSRoun(Jp zK5h$n~Go%CY(!oT@K2LJGE0buY2GA~Ba>|!niY1pK$v#`M zN|g^m<(Yi-0?uQ}@4n<;A;mqH5?;&eEl^3y^pN<-NY(G23?TEzIe93I*Db}ELWn)vu-aAfBA&FpJ1`;wlkj=0fjmcP1>Y8+(FdA9 zFd|w($JG%O(VXa>=nOiz5r`4&&=3rwa3Z7};?%H7yEKGOKdJHuj`IH^CPJk+M_R$M zI9VE{50s}C7TBeebQL@FgdB84D4YxVyuYoZqoe)(AieH`_4*Ie*4F0FD|n}ruV~{k z@Xid8mZ(lxynOkJzkfh9n6%IBeqmD1CBs>}CO7mHQr3RJ9tn8r%`V1c^`ga97C{mKoq6zAA{{M|tkWc$bjdzPe*Aa2M2?IEL@_{R&d2~&o-i^Ht(P~(sO%CM zA(7?NlxBIniVl)&1WMLg!HpT>=ckRe(vA0Wpd{o0qda+JeYIXnel8DIK@u>TNQ!|g zcrr;OL<%a2j8MsF7Ch5m$zU?3jjB<_H>k4TDRSN`5+Ao`y=|>{|Gx0e+q|ad(WR{C z6#Imzc})MzBQO%wc>E!d{QruNfj%r1af+vgchYynvgFpe2qyiZX3J<3MRW!7ck4{PzjL;CCkIb_8EWH&lVh7s4j-4U?`@F?7}0bCPYL=dWeWBnzN%h zgj2>K03sMC6{pD|c8S8q#@iT?4j3?icS?C$K|tjDx_L>TQ8_SDoAAq*?)s`9-}8lO z@7}$8@#H{R$0`;ct6YAvW{+2$ zX<&nS^piuOO^4#2ul0Gk^3tm{-fw>QYqrmP?~wl9DxN?3`)Hf=(J`ad^;WB6>ZcuH zpEmfn8;5snkL=hP-LWH5u`^oXn5DelpuEOI!#dTa3f1{S<*7UwL%#-@Cgfy%3r zOv$rEx>g}wDV03(CEHY)$^&sSjK_-QIiqd1JXp0zl1HsaZ%aq-NOoCrWQ4&ZdD5{v z((zKs>6YY>CD~+1_F3|x%EcmilE_FE`oy%686pcfEU^+9qZ(vg4vP<@Fdlyp?_S9% zA(EIFQYlXuRG|{?h=$A@#T1f&n9gLA=Nhl2)K}^#NnFMt6U>Is zGeMt5365WeMKN>ycfnDEBf$~j!3QtrfF$dyxHN(T<8R#LQE)Rt44F7N zg0~CSgqKnb!3l9lk+KUZxH0aES5qCXv4aJ{n#L4W0FA-`!XZ!<(>e-pPXHM)gF~T3 zN}^zv@SY{}NpM7=A)263 zL^Q|AQkQd~tDGQLhK5jRi%jT)K@?Ji%SBuC2L}0?L@?whA@~glzPO&d9hZs|;^`A> zq(npJhFQ6H!r}^S-BYG+37@||_II1q#g>^fEpykNEZBLz*!WE8&WrbcKU2BrcPnT$=aI^@LgiU5oz9ak zl}Vv5B#`u~l&;rE7w*cNPqlQdT)K2uI*}_KN|4OrB#RW8$Kw^!k$icuYMv-l>3B;X zsS+PS&-R9_0HZ6#N+icz$tF#v^~g=>bb%Zbd87!K1VkdE910shM@C{IRDz@!tTI4N zfvIMBF^7>VFX6E9#GfH3vqi#U7^_27@~AcUla!;TlJTcJQso7MCsN8w8OhA|GL^(l zHu51C5}7tKsbrW+d`#xCraX(}5u`Gn7i+6KA|8B7XlPA;@jjvMO=$76h~hJ%sf z(g4EPPjEzvAL4@d#7t0U_HSB_nC@DOgT~UUVVmLF7El7kQ za6m_B5k^qJ1Q-R6zy*>VBA=2R!ZOXlBi&$9EKUlWP$u}LikK~mln1+FF$WlFjxwY| zp$X94wKuDbmCK=>QWn70n8&4=UO?@joyDeU7qpO2eETYnE~v&#H* zBLCBo4EYZLkKX7wn%UuYv%@u8VV@0s`r_6*8wXtu>!Vs)R)zNAmoU!KWChf+Pw9R2Ft*D(ht=c?WDhf8m(?$^=zvNK^qlQGGz#|NbRK!O@B<~yW%nR=Y85jfy zF|H$pJ}}|7521K9f=)gnJWx0%Rq#fHVjM!j4uz?Ui&6z$z{oBNf`V}ZD;C&=dI2Ma z(K(9qGn-SB_j$!t=%9fjkO4;cLIh1BKGHPR#chNR&@^2VZ5G0Z! zlmtT!gYv1WUq!&U5Y7(RIc3p#IxLW6EQ-pR5emh|@3XK>>g#(wGc&8Is_JHb*?F(j z9fw1g?G9RG8ZmuG?3@EBJ3O*BI^SICP_XiN(aIC|7CBcgJYKW>Vy#(JgIQ?fKK~}O zkmuX{UjBCJ^>WWQD=)uYez|#TK#O@y%l_C88v|N@4{Y5L-?k~FZDUZoaa8;EsCKuz z9nLul=bMU?cN9l66z;c`C-RgoS<3w}s%@dFeF>_4@#-yBWr7~3;(gA5Cz3B~o(+=E zL;2m6vjx(HLdl;YWxbpRJd(U0NSBJ_=NCQ?B(HMGlcyV*l2x)icIC07ONqR!>U>uo zsahsUhm+-1onyD<&HjcQD;=3X=1V6^B)1~Tg~{d(8B$QCX+9=)x z05|c_UtYj@Aa4){U(m;+e=$g$&?pVnHxToA2>24gh$>=B@-BV!Wh>e^T;rj z{H%9!G-OL^l2V_m6~ZX+*2-z>3sv$HWn3-e)sCbm?Xk5V!^+5_Yjhs3Mab3S&yFb7F+)Dn}7u!M=#gP)Qll zD79!sPzE4`KatW65wiq4poD-JpwT4^a!VnFM=@kY=N186R1{SxDW;9^NJW7piZDeh zlti#bE$#{QoGxij76#EdYr4ugqHw=a-(7eEpYOht=_I6!g&GE>6%`ffnYS-_r|hx{ zU1t`u?oi~ceTlQo(&yV|&$hg^!2ZsDzq0KY?(gudG`aqN_B_rqJ)AFh*Z z-F0o**1NW(XRUi>Th3R(mSo9F6Ewpa&I~z24rdra1R|0E2m%B_fCPvP5Sc{IIp>@+ zh@8P@0Gp{9nhm1S=<0gEQwQvUW@Odc>&&U@>gpz@e*NEP?|n|Ke4Kdet?2c=SM~3w z+&`NCD7fp1Pvujes%L&R&z(z5A7z>jWNaXX9@MZ^nm^7lJ5+5QDY7_JSX}D2j}~qp zFWq*mwtBZ(W5=vv-C~ka+?W#4YfG54#SGda`$U-3sodt-VDoHNy_!_ddex&*^=VNP z7}Gsgv&ix31(F#HYVw${To`$x77&41Q;Tk?*KY`Y%$Zm7m(`3L!hMbCQ~jD$-v;5G zMog(O3u4#^mHw@QR(KTS$3gW{pBlu7l2PZd8abiHpp|3lB_cmmeM4@)xNSOonQ&wmWo&;Wtezyunyp@^wBEP2KiIBb*@DOByT;17Ck4azb30b^n#S|0I_})L z+tv9QkK$oel{+gN!y}cb&;)>z$KT?qN(^NyF{CYiwZWrId2oYq%W*$*V@W``pFx97 zI-=a1@CB9fwgepROo=2NDUnh^*o8G(>FLpjL|Pb;u+XQ&?|@WKc6lQpKpb2E2t2Yu z2fNS&AhH9V?8;Z+i;Z*mK3s=?1=r`Ae0lkAk=`tCB)n1_?J#ms9_Lb=Ccgl0 zkyP?=5==gVjlTeYlS@3uOfxWqM_Rrn@{1aFb#8RIRw>-g3*ibEahdSmyn`36DNVF?^W*U4(00C6bu3p;RjQuA*r1+iQ$6cc&qk3eBv)Sf zRLv%qvMxr8S&Jf)!^jb31j&+hwSbiR{T-JTB&m4Gnh{lSxSayYMxl(17GoFGaHdz_ ztab_{5y42(ALD{bqB_Xs2i4e)|$&)9!lVL~R!?g0=lVZpH$qf&o-0Ixt zbYPYZf#5B`$Po~hRKgVR;vS~M`Lx{FTtU7aDdbEj<|X+q*^vZsP2S6AN!Da5ehV~b zQepz9>~c-Pq2_;boUg$bLyox`E&moN&9DPgd>O7OFUxzmEPbvcd6aBYf++u)kj}-~ zcq6|g9F#E9^4%nf%=yK5svtooz5*G;($X?klAoVnEUoGZh^Tt|WbPiPe1{9=htJhG zTyAs-YdaC%=MX)7B6j@kkg2yr=iX0P-V?d{UfeCe#`V+1di+wK%139ag;To!+Oq>0 z&kq*9a4g>l9oh(JeCgk?$?{D;bppnqRtFZ&BPlM`Qp}JP9r(0C_I@PB`^{N;BfL1kS zQmuNb=Hop+5+g^%QH&hN)QlOm0)^76c|=b1YLQOOm{c>Esc}=yTM{L3DWhsoyP)zM z8OdIOB%?*fjKBzz3^qfD1eIYU0>EG*vDEVnsZo<^9QEG7i$lx7K~Y>v$tx4DL_l>( zWd8}S63HoF*@@wh>7Wml7#I>(B?U>uhD;(z3Rzqe&=FQeE|Ewob82;J-%BBs-9`~d z#cM?nn+d%d#DKB?<&Fo7KDOMmwLh{oGwXT9TD@YaS>9@1->6%CUOZta8d)zLS;?p# zNzQEDt&hMc9)6>3z$kf?Q~pazN1__q(FhK@}V8|GP398F0YnAmw{!uk=yW|t1`Gr%(FI?;Q z1+=+d?RJP_!Tb@|vgN|b zjK}j$`!hBUX1+X9y!lDt=DBwBm4U6m7E4g;c5vJF#kOs+K1_%8Qm0rn=0ph$+DDBf%E+Y?~U=rIy?iY6y?z57bMBOMqF?iFEGz=Xt*UJ=*{(v&fZ@4(oTc+P+TGXjV9h8ho*j4LTEpq!vjZMbRBP0tixHxVOQRgLVl67QpA? zyq$Nk0TB`@Ap#BF0&Zv-=Wrc(VHYsjfQ1$$X*tf7`B2`@1^Eq;m~$zq zB>nqI4?oH@9LRd|LCVupmCrBrzrZQ=tJ?_fe(6(hK9Frbl)Lpwp5<7D(i#X z)(98{kJYMYjq2N_o@rLkwyUQb1(KY=RKaS4riR?!2qp8ORz&_$j2su#8iTMR#%M^@ zT{Uw`O`jC;QW0Nm6_Ffxlt|(m6XA(p7DGrOi(P79tH@w7enc6sj0h@G#w#R5n4&l> zsEpJGmBe5fRK^nOnbpvvB!FUoR}LxzNyJf9j8j-H$B#=w2N@@#gJd47_}VzDgnDj^ zgUBLmf-NVbk3$x9)F${vBBiHF2chgS+9+P_dMXBw1XmmHSX%U(H7lm#8&3;I9~KVX zDIQqJs2aR_t!X!pa^(0Mc_fVpl5mGa?&fi~k19!&Fz)6NB+*BBBb|Qnc(!p!g|( z3rVs3Ag;z|0i&Hq35$f07IJY%!5`K*8D-=Ou*R3+%X4v#v&m24gXl=5=HJM-;^tn>TMRF0PhW^#ny!9&yik*QMa+juo%D*T3%7 zyeF{Z-H`sbf=1rDIQ~}18RFm%sZ^~k&FQ*qa;Q14az;7r-0<2i;8QlB2oe)dV> zi;vP@kUG3FibwkLT>a*Sc2*YMaxArcoNM_cZ~JK3_Tl2~a~-UTwzEc)Sf;5{VGWAQ zUAC}p+m&vcM~y(zg+NWEV9>iqJyoMRSE-(@s#}A4l^OBlY63IjZwL}kRja=3LK)qv z1&{6^Ny!bxZ)6WUHKByfHi0mHY0VS0m_o8ABFdUi{&7YinK`YNQ>|@K3n(RJlEou6 zbxI^3sl$OvL{P#QpsA!BKgQ0f@r!Ess2DjiS_Daf+l&B{4oISjP>JK3xTwYx>KPF; z7Q+VB@L@H6SPUMKIb@NMBg%+_id>?M5K8)k5hCbGXO&?idB&a%K_Uk+;l4f)NCF@u zL{Y*@fo_Dso?K(F=(bA)Uvzo@Z3%C_T@tZTGiZ?^{SdHr#qqxBR4d;z4fT z?W~r$?3(`TxefTMpXsAEX8f;sY-niUC6N3rJW4lpH;hDRC6CNHC+k5gRT6x-MInop zja!`-`QRp}#jk@$?s;x$ZgN_HqGbaIPDZUbhkF|qcnilljhDC}9k~G-v~q&nwbR5A zd7Nvq@j-kv;6S1sLwiR9M?_%wEWQty;w@0g)wn(%%{O7=bNLH#d*JH@SNTh6aOSZhp0@ZZIUO>e!j=69Gj>{VR_J)*bL~degV- zt$_ZwgGTmV8QT{({chC4yOB%pGB%9Woi1JXt<-y!Jn*Z1=v{6gSbDbRnPb8853j#C zm}NRrx^Xaj^I*0)s83*cp~Vu|vK`d3eX4T%lYHyp0_)*I>xpW`tx+tA7TROGq+!Tv zFc>g~^@xbg6*RF*1x7TH)(aQ3Q*}WBYgP9q)xS%Pn^ci1531c-1ct;^5y8_$R%=yH z%@{xWwy8eNs$Yld+oJlms(#dp_ox}<0U0(jm+*mFwk|Z0{3F9g29L!!lLoaC<+`oL zObT&?N5qiNAkR;4~lW&9kBkSI5JWCl9=2#-i49dwF& z74D?l2_UjBVYKteUCn8bEAMb_csfAG1_GRh{Ne6OQaFtxGR^}joWOCk2}h7!=#aX} z6#$UWMabww5Msv%vCGwPCha8BkpoFC0>6;O6*!X)EgRR77~+KU>3jr`%C9H;{CEH$ zGYvVBK5swgcMgxVzP^DPjJdfvv)R0`sAEkwzt9rGq({$HI0V<8yxepuw$mlP-!Xd7 zF>dUg(5ZK>%o8bnFLvdlYr6d@cRonG_kQC24^tm`R~pW@h@3@0<8!}S;gk|7^{jgN zan2^$iX)}w!-ZQ1ax9dwMNVvc)R42V9xbt+sInd@RE`!4V|eIPW4knHyE-EnlrXaH z#Fbt(oCPSD&_{5xM}%n5KF=1_sX{#sZf&YdrRq|no^BPwbh=YGsO~lD8IY_|J#bSy z)H98*c&rmuaFmFnj8J*5L)40&>k=JiCp8dGp*BFL))8gBr5516E{J3YVVtr%YRZaw ziD_2U05B?KvXvGWBHKtbl>~=`5jRzOs;J@BMPZRt)@fRaT$1=e79&ZWXtEgEr$$eR z-;gA<5)B;|>KQ@qa!e#Z(L~B}&`LZ~O2V^AC$^-O-EK-Ma zQ!EG|G95Up>teS~Cq|B}4AA$2FpjNNuXH@JwyYCb-RgL>+5T{&5xFa!TheyIV!nDl}<8B`DSJ~i^$x~7#zv!t-9-)uz6^lFnWlDlwAL(!d!wU#V z9>I_so7 zZZSMOlxO+0$bv_DvUHm{hHkCaqvgt{1?eT%adm zghz6JlzG!e4~QF{VWWGa&_vioB5_s`K~|`s3XYPt)9pe=3EePM#8Z_>asnmds3bui zki=!BT->iss48Jtcw|yl+@M-Rwf0lBgxM3%)rxyU96^%V{gEUe+tr9kVJIWjstgz@ zii1j$9Yk`-Zh)lZQ6h;l61qubP)QPGRHPs|LK`O>5QC8rYR)Z`_>Cbj4o zuf~mur9Y^J!__3gLEHx71avs4Fi6!6U-g#oR6&yIjf@bX5(PvP(Mnp%UsC?b;6bjRAtvH*9t8g6g4=}j%`Pa1DMEStVlJiL_GI+j+@l9yk%zP?U9 z!0xcBoyS+gSZ9Y(@(7Zk_qiC3T^#9rkw+O{mHJ4_5E3GQ5lkS9O#;YG&c^MHl+ePC z>@XISD#oka^YXpG3sXP`7hDGkgGBI=Jc6X$K#7f$CChw}_94Q#<&9h)py&V;SHmy0 zUj!;4QEn(W=kvK-gfAw?zw#S$oP&H{W;xON`cReU%>;akOZl?IoYK;+fgwr5m6esc zroQl`y8W&Nzc`U|(7VXtLX}fkgF|SmS4yXA;s9#skv`#`KJAgc;9aufkxPi?)}hq9 zdlU5gk{|3(eRLqp@JYeb1L@B`N;iI({=&I<<5KrVVC&|E*3H0Hk*zr2Z1Hcje3~zY zhmIxNfnq&vCA3rV?NCnE3qb@!hYF#I$BKk8HauCWo~#y(Tw4}u2#?6(4vee}L&X~R zYOhd0kVGQ!RPkMz9n8p)wR5&?GMwG;PZm7wN!h?+(6D~Az zi6xGT=qphgIZi|(W!WkWGJS*N9I?;i06>x&q#DUQ!XpNQZ4ZPpVgz$)R&8}UThDW4 zTv7U8XptPTEWk$Xs6th-LH7G>m$m@CVBiKj7?2V zylVGU?Idc#xYI~oEYmjn_IQqc2+2Jx5s*A;x3tJ9KnJbtNHL;MhnrubN((-?px{gk zBU0M98iEUzU=r#d?H6^CF6Vzu;uNv$nGl;g~)O>j?2)HIA5De zi4I~uVCd=Pz#)%8?@-lK#|8v>++~64e1os^c0NRI(tz3tKm30C$zzRm$Y>RJZ## zwmKiZY*{zeE5=l-=!61N3BzYs7qF=gH zz2#f~E1#D4uXOFXIPj~$;devFPNh$K7cHJCUiQpe^R3XGty=dgyysW>xc*$x-KWK?*xOe8E0xICyI9#?1JD-S zVGAW7GblQjyG6$EWQ}^fL>QXrTq{TvR;HdTS6!P$xQ21o)iL3wN*D!+()xvCNgv$E zYg}ih#*nyUsY+$e6e`L3hbS6_G2YbVFpz8%Qi!v9x>k%FeYN^b>r@5 zgBso_wH1`O4*Ez3Na0B0gQ7{vqr*#_z;WKfHMtHSDlbKgH_I*;?; zZ}@h+<=?wEbZ}qH*hfjzd%{F9n`4&1(68zag6Lm=-@oaxZ}sD|HBSN>p9QuVFSNZl z-y%XZ#|mB^$Rc;FDz- z5-lZgOwT9fk+Gf&=u$JL1&NGF3Em{V*E%vhj1$^siKcb3u@}BnnVc!zAM+)29@MM5kwLh zj2Q{EvT7VPaw5LEDn^=A$59U;omC*EBw%=3l#WxainCg?qBP&NlIG}rzTI|zt7`FO z#hj^n`FY2~$4$5I6%Vgucg$us4X5Nc$HnDM-%LVF0-GNCHyJLpKMCr17TEIqY>n}JtLb9LMo`DgkRDOV=2!W|Zqb-Tku3qR76N+P4l!F2T#EZD-4KZdU zlEcJC=2D3OPMhdMqL|GwqSfAzd?Y)mxvBWB^!f2Y2PKcR0EiBvlE@##p@u-p9|z*l zV#beGr-bi{Zc0MF!daF2*xK645g3#_N^z79Dj4qGq`yil zJJMwZPc~SSQb?bU1XK2eKF zgF^#@qa{_n!7&vFJo4XgD|y|c=AFQ%kK@`8CG~uCb#Q;|*xMnK@5jvUjauB7xVA6p z=H9ql`%>2rW<5Ao_2|RvkM~_OxK=*B(DLkJr(iH_cq6#yWnk;e;BIqJ`_`r2txG*y zK^-D*c(P>sUoynKpdGc)g=arC?j|Z@02PX4Muom;s(md8aNjiCqiYP zxF(CmmEIJqRPoJGNuiaD^`=C19Md;Mrla$-1P2wW@n|R`LDY?+R;_>>HYXkwDL@=C6v)zKDSYS)7WzF zX~V6Dl|?PGvO?=JTBB?2@GDOj2O19!|ZgjH&MSRCkNx7h#kk01t&GXE%fq~#zR2Z4@`)ImDZzlBXUlo1T!kxlYQ$Bq@lPpH%ef+ENx z=>sv21EbtH2zT(vnYJ?;1&IivYrQ6s6@o_>jZh+}*Qpwv6+BWRz5}DiqZCJY6vhw|$8|>dtEgn* z9W{+1*qE9{wqj9)E|FvA6oVw<$Z%3%*rXxZEW}arD3IhJnG1eEdQ{dMXF=n_(S2KCN8LnWJU-ajfhkZzhenAYASW_JhOuY3ehcoA9y0bgz!#9 zsj5~fM==1Es|*`)R+;43Vc?+vw%VJ*Q^lC-IPk*K`+Tcrb+clAqjctZ>5QRjL0`Lg zyLf0mt!^y7uqWnP-PMGgvYg_fp&=2GDP+kbvF!wLUg;wPM!Ef0Jfe^A$cDU1BtIvP z%+-=$Qojmil1J#19m%8Y!=oHsa++io3?+|1N(U0@ut~=ieDEh_h(@X;A}EKG&d@W4D~6e#M8+RUAHF?{>A-DZ0x!uJ2Ux@JF!|d!wh{i=F>8f61YG?bCwW zM@sH~kh1IF$F~!}O=06p2WwW3%Z{-Ub6h=jzR%j?K^k^M!UxdJ2#k= zMSl5VP#VAR+-5SXc)nkCYuS-SJXNxaL`{K_#3EUKw>ptzJliS;l2;KO!Wx>{Jyl5} zFk+C%tbdS188cbzl!)uNnmj71#Gw)mx;P}3iGxZOz=29URVj#!90}t{7~v5%0S8%R zsee{(6zh%8h_zLji^0v$Z%7Q)r&B^7sg9FlMza61Iu0r!k?aP>L4=agA}J4Q*P%~{ z9lueO5a2UtJkr4^nY&6@_?DWoB)+F84CoerA9$2U@LF+J`MdE*4i2WTsVVbn{0$N5 z;xEY~b*QbSg07QAbr3|IC{i61LMcdWyd$!WECo=<171Z8$IMbW11|`x8cSz{r;G&r5tKA2L{5}r^V9GKeK(n%zT_5GP|Or+G#<8O3UrKd`3S4LozTYGyu9k@dx zC4EpSJG3ClCi9OF2X|lyad5|G@AH!6RN^VQqm_`-vhiN2kGPjeBuK&+Z~+=H;+;Yk zNJ1ixD3GFqv>f3Ccx02~L_p>^o-I7ed?m9BFI~C}fFeZW?;jBnnW?Q)($?0#w6xUQ zcOxaE$^CrELHB}>&y;=YU*izgbRw+7F{alkVbJj^*^0?Cg>&vXi>|pVhcj;NzjpVd z^!1bV_gy+3o~U_zw2H}wPY)G5Kalg{<6P6nc^ijvUmh-bd9-ZvL=Dq^w?59_I@@Xq z9~KN=>a#{q2?j+eX}{vrLM^v)yh8ajUrM2Rq)0tlXggVD6C=SYmHfrgA`y@wqm4s_ z#PHiLWBZUO9w&im^)}pE)N;$%seiZXTqBT#K^#<(<)_|;psPluL=t2&iENAuPxaSi zQH$OXzyU^5b&!as%9>P+`)HZ$Ps=Q-^cl5qP0&gbP>7>OqF79|Rba@BNPJhZ1P7(9 z;NK)DW<5sM{0Bymq{B+%f=y;IuL#V=zl$g+-YEmR8)_WkTy5BBFOY*uQ8zv>3f)mg z1e)lLaC-S&B8AG@J52G=b|sRu{Gs?AOI=aZr3Z`O%by5kq^gG^dF^3UFvvOs3Cz~S zr(F=9L&D^a2Md)Mv!Vi)gku|31nWW>dqk0{(sUahttq2VnXi{-|QchKTLQZ7R)!EruJXK~IW2^u`RVv`f0M2g-cIgbyQJ#p)M=GJF)Y$R!DB3*c-Z1dyX&BG<;k8`&UmspOLTbvq22@M0o zV`bKmJ|%KYxzwXv8CGH^6;{iqispEQ?O2)3k)rN$jl?36J;aXVZBo}=ukC6nMYn1( z>cOEBIW>H+T`5W?Vk3PbrN}Uffg~|iWD!Fmnb9xx5h^i{dU1s4VxCS!QyDE{ zQW*t_8jN-xlSTxLIm=?uM?9zWo|>~H`pnv3`UcgZ_>lOn#8jof3h6=_o3+AJ`cxNm z3AxGA3}=lQ#6-_)Y z9KTmi7-w!Nw`cNdaZhAgU1(%MNKkTaYA((yffz`XbB$#SJNT&ZNGsh`yR!<3a@*0x zU+1x-ql34=qr{LF5+#hZ0Jxh+>7BwFny4`+Iub^ygYZa)gKWUaE)25SFG2^2MCm{e z7};Qrja_h)u^Kw;!YLakppT3q!H^m@^b=2&AtAmf6IO84k^a%qQRdyZcTOZ{w4XSW zcfd6dH9T~-`jddhBf;&*!g`NK4IPgjbxfFaN}hE|Up!s3;!$|hyW+NI(YkxVz4NV) z{2CtnH$CyHetM|r`N4u0CmKv1!zS0h4d>R)Pm0W+6p%XHI$SJBBvo;&V%wp1+pXJr zxL7$b!|zUaj{T_m{FyH6VN9@I?zY-262Q(%5Uhf zOdMt8*@&#hBOQv?cm@aVD@c~`%$har2v5Xdh>H8#rG0D>f{3XgNTWgD-u*HwrikF0&+VM!K*Rev5W#Hvj&r>tQ#`5_W zJXEfB)lf3|Ft`6sM%PM4$83JjXnJ*PWKwx>NQVEJ=(dJ-@DUHA(m0e0anMC2aa?&x zZotTm%Jzyy@n0Fnk>ZFl+Bc3!H&r63;V8s$H;<4AUofbNp$PA=NhE2dZgP&?IFlpx zfg}vd<1)gdN##!N11Xdt9T;SU2!^o95n5hiLl$vp;Ss+yD2N5MBKRF**vrqz&6_uk z#uvQ}2AkW6B(JeqGX6PG#xb za_@K)uKU#7_pW;6*J$vmdE!l^wEbB?>x=WPFU~ZWj+Wz;ZaTM`Pmh^B2P`h_qM(%d zP1unVs!7RKSdWz}PEE?Gb}=?QR-pv-+JgGUl2DHIHs?m0a7W44qhfV}M*tKgLZt?# zL%HfwFO1|qDMb#VYb4hw!i+@ACbi->O(mt9il-VyP?TBxMD+=M465e`RL`~@PxTa2 zsG5Z=LLx>nD#dTi>-TC9wPaZ)%-p;9b2$6DeGLLY$<OuL;dj8OAdh1M5^=N!iPeM*jTw-?E#rVhz zapU9TXqgm82_vnX{!d{lek?qGP8q?_zU}r@?L0DP0djZ4$aR2`mPax{7Q{iHB+<^J z9Y#r?M3TPb6lL7aqa+b!w0o^cq>Sz0g33+Cc_fcgD`}BPMwf(Glao{UO3XC8b?esp zy$22LH!eg~f9jF@p+~_Xzp|sjb)Q~rJ94?}=#~EC(Zdc`Cr>8LI;Jf;r?0qV-ehS+ z*Sx!K1$xhtN1mmRy~+$Qc)soV*?OaYt0|ym!?$iDbogZu*@{lHU)$F4D$C(AixbbS znA&#l6H-V~H{2nJw8BblCm0E~*j(Cdi~+etfzF{$J;7u{CQ~%1C#f3MNOY=Koodw+ z<)870CORnZ4I4%A8(D7+$#@n>)H41TG$fhPkAbsS zv+729s>Y*iIYNOPW3&Q79|Zi-$5+F~9c6q4BRpcbsW_;tyun%=EV#kkjXVgQ5Ua+O z=+s>9=P5O?Paw&#k;OL{VCK#U5(%rKiQ>7&8jRGF%Lg2@S|g9!;Au51m&(#NAjuJy zRHaX<1^S{1@Ggl-$AFnk%^Uw}Mw-$orEaHB1W~D)L-lau>5C3?Jz$U@D6IwnF9H~a zy>jyT>k(PaSy$7D_5dC}BipAaWK*OKc}9ZO1B9-vJRMWJCj!Cu;?X zCxD_|z<7co9w~`x)ww~FNKG7p5knR!dxJ-jQq+pyK$3VSHw-`Z=peTZNQyC|2BWNk z!^J`+W3>7=l8ixvBJBu_Ajxbg-*(l#_A`l;CE`q^;#MrWEoKJ`9(Q}HU*HiWGv|cw zDyRHc-rre#1E-XS#DQwcoG3>p$iufPME+1xO&s%>hsa9B%VM&X;E^Y*&S;N~n-la^ z@)FD1(BWw~tXjMxo+?hLhwlT7iCUd1gGxE+n2{s0P8dfdIH0m$R02?+G=o>0JiN&b>l`7YT~7i@{sLK9<#l&fP( z@~m=w$$EWdJ7Lli)xQNEm#PH~FmT)|2uX0;+e5CUjM^i&>o$amBrH`K@tT z6_+kw^K}moI2AH6J^>>;YsP(HePdw6k+X}V-C6ydIND`#H3NMOPN)3y8yCLwZp6PGNd4jAoF6%q{HI&(FZ|lxzR+{<%Fyxnai_Fd_q>Hu*~`wE zH(he>xaQt-E4=RxhNTA2(kEVJPfu4qKU4Jr61{6Sd~09&)^7UMo6*Gcty>p+EdI@w zfadMU8{3x#te5-6>WD{cl#`8$@1*VAtj%k{cCt;FR{%cw#k14+Q-(HpEZ&Z@sDv3zuAfteUbQm_`ppr(xLFI=I z^kNC6u8KL8l&Ye7oJN2P#85_38}Z~WiLYvr9DdD25KQ|i!)t{~VmQQC=|}Y2!h6KR zde<~hHEGHkGi;3;wI)n#C(l^Y*S1pUHsi-OB6?m#^gavkG9>ptES_91o4lFbyOi28 zozpRxUe^|tQ5_PQ8+<;j9q!;xAXW#B!Q95K8lq7DkRcD8OePRIL*q+;;ZU(x5g)?!eg@b zejM;OKXm!~U!MEtJ)!@1f86&!N&lfk$&X!Yf8y2h^Rqp#1&zINY4WY8xepVUoicT9 zd3W54@13p`7yFXZEYNV9av5(77Gdg;_6l zThF&x!$y?Q0VSl*cCJ$}=+tOCGivjn7f8~F#N$;W|1OF)`IXitBT&#q9T$ESvzDBj zge*E!Fav8iu_Pnd)dq}C5cIykyWq{vxRi9SL}I+7aHBr<3NqWxSwDxNAS#YCnW zX-~~SK?vQP>l5qSNFSA=ar)j(8jrQ2r81mdIK^?zSrzgp7f=O8>846gRl-Qf1qT(Q z5;b>01anxqky(x9da(*e=A>A-1}Zs%8e&K!QpgJbUz9V5ybfTHHp-trgOcam^4{@I4MWL9; zB^ctGGL}RTQ9$Z*NH27(VnTmemF<7#-SFeo?awc?txK0iMcOH0dbt(}4A!+-j-gJ1jB zul~P(KJdT)&Eao_@=H3WhdNcCo zI|+9VX5BxT_sFC8v1j=czoutCb;i?`FV0kNc*9`rCgxjf_O09UYp}es?Q@OW{*6}b zVvqG=mlE6shGMEk^tA2rpzX?#&6{{>t)S9(La5~FK@G`b8*88;PcnJUFL?r)yEQE_ zJ*c|ig@Re`~oVzn48f+xqJ50!*O>7ycxkVxel#vBa_Z+HoU;&I+sgl$+Nyy~?za6nR9dBdkgAW4igdrf3FJ|l6LG9r%f zh#`>#S22c@ERREnRaGnXYAFdy6lYRoG;m*wnaO)!t-2?;!%fBitYA4E++EU_EX}Iv zpq)n^#vu)fWOZ>!6dj)I#-lfu#1U4!;UfH?F_uilJEiiR0vkqrj9W=hFl^-Kj*%n2 zD0K@2ZFt(aCZj3ZEJzWQ?zTk?+F~b|oox&66N{Fxt{3YFahx^SS&Th>l_vxV2Q_ZY z8a=Qb-ff8=vs_y+r_64~4R1vD8Y8-&NA*9A9ei|kR3FoS_fq4Uf9bqm(Zt!@p@8ch zG3ixN2|4Ej6Mfu6eUErn7nCx-LlAfK2#ky+IY>eu5_d;(z{>8XLgH_S(avLccQ^f4 zEQQC`!@*^Mcb?dG%F#!3XgUQ?p7{#Di_*qAQ?7fyTsbvEjEWbn`48`Z`yWtN~q+; zLGizy>_%vxEn>(PHeibwwk0mwk`~3f8NmZKmj;_tz0HM%_d9GZ^pJFth4!b*-o?ge~nmpTs)$&*5=)0JKJsx>arEy zw&kzcQpRn`qqY8kDQniPZAObJbC%fQt?+L1 zl@1;Qy^%ciB7W?7bpMmkwnvv+^`UKd!aLR?I+lWKCVjF7J(D{eX-7MckjQ4&$KMDeN`yFqp4>EFwTq8nLn65p&Z?vm&_2f_ z4BBD*Ej)fs7P*MrWIP8j*#$=8x9`6D?qB@zpZ(E)`@{eF-~Z&#zx0>?>wo^A|Mk^> z`KxdK^y~k$@00Q0)-@19e!|d0*b+-N$iH(B99T*`|Ghhs8 z5eAGPd5OnxciS#@+9LR+9kpHVxA}Aki6oR7v|vknXv@BDix^R^^ebV#O89_inJ^VK zq9iXWF=Gk~@(1@So^6U#t-_+jZf(k`M#Zs8ajsQP)eCd36Dt+7K(VxwWn%Ggj~3P| zR_HsHE3BT%)Q^;DC3Z-O8&(o0l$d@cx=$FLATC&`xKt=!4T@*I;##G+Rw`bNihqxC zrb%(HQaoxD&pO4oT{+XNc-1MM>}qzVQSsLPjcKz={+g0Lsicl7DWjrI9aFB2DQTKr zA6KMZ8&}fDm8?mnU`ffFSF)#-!eyoWu2Otc$(dHNr5*1s&6Uvca^eb zC3Qjw+0|K*)lHn!Y*tA`+HQ!M+E=>8$_e3pO2V{~wqi?~vn9;zv~lCM$N?UOAOtab zScw|4M)1gzZq2&3!#XVyy*z4m>)PUG>io+Dp3L6+BCNw0-uX0U=y6p4!|48dAq~2q z>Xi#M3jrmQ7fJ`t<+Pniu5$@3KJJtJ$%(K}KlXF@z_qcuUW9Qpaio=-^i+Y7GP(Z> zMkLa%jEoIC;85G_!$x@g9E|YD5w0nD++8mRVkjURkfM^i{Z%`dc75aoDVjhBdPpH} zw7<%(l*s-2_y5IT{KX&sKfm|K|LseE^56gTFaGFjfAy8W`RlKJ=UadG%Wr+}sa+kG-K3JW)!`N~T_k9#cYl6;@ni&J;X`^(ax?*el|m3GEWcIsa6X zz|gZpbWWBF7+oN!QJ8~1iC3K~ z1cL&@2IWkv;$AH<1igS>#jjiOs1-Om9yoKk*M?1CpGVuje8u;K-!>XuS_SE*Q2D%X^{b*7ysjUKTk&s(prDG5{7xN&RZjFnD!?{;V>5AfQK zAKQ)@wp{79gmrF(b(urkH^Vw!hIMR2557p7e|~-GY22tmj27$l=PU07)!e+&zI3r> zI-q#WC#%mRp~WM%((Ou~dvNM;m&+gR_kQPf$7>1M-~)a3f}B@G<`Pf^9NbjtseVow z?U9@><{a(fxEn^hKC*BVCs17glCqv0+}I>g0?1cL$}uA^*(0m=)9A=o?Nmw_X(geI zAJNKp-g)OsU-}X}e))I)=udw4D_{NNum9Co{_d~8_PxLP_G|z2!$aSB&Gld33HZl- zQU7{0`+Lr1Kk#b&v0wMkFOI)ts$ zjk;lt7`KKESR)yC+z^)Y*jiw;rmtJ0#;linnNVzv9JYoJSVMcQ(c{)@H?2{ePiUyy z>QrxaZL~VqSlyegr|PUH%dDpwtZtgQHds%V{+gYtwR*N%UF)rmWjhw!VNIE`#*bRB zj#<;Dts$LOmvUjQ71mP~qQy=(Sbf^8?p0RzN~?Rd^<1|wk7{v**1OSqw$18MWA%Dv zo;6nA7VFt|F%`PxwzXi@nmTSx9sA7E#;ww>k6Wc(8@HxUSTiQAg-h0=Rcq#?HGke( zecxJr&ze8Cvs=1mEm^Tv-m%s{w3e+}^Jc7h)7FZc)^eS-a9;F_m#o#dt>rhZ1#{Md znH?*fwPGa;)|xxQN|&rvx2(16*0LpQ`Lea~p0)n2_}qwLYvQ6cY0(-tX-!7Fvm65St!iouXS!ZpzMIe(R+8VRGFN9m^0N@d*btU~20dHl>-l|0fSi}sD2dw+jF z7un6DBo4$Rj8Y=M$fI;+?Z9#x8@os(^hqBT9??g3X(f+e(s=yS-~F?%{_!{d>d(IY z*I)ns-~PiJ|Ma6zzx#&!kM;-t_(<$`Pvm^xrTpJL8-H@H=jXu_uU(#d17|hnHp9ku z5+3bM{xu#yNZ;I_X~sUxHGfjF}~lE#{9k?y@FJfM$WMmdgVc zW=>%&e;Phwi5Rnl4Ok*ZEK%da3ZGeuOqQ(smZ(un_<-edw|K(ol|Ipr9I;%xX^9yV z2YuRk!j$Dyy~VA`;@)gIRckp}ZgHuxxYk{^NSW-tVX`?&sHTr}*MlILJb}XIFxFvha zQnF^rnHHVmRZF$rQnX~rx?#zj5S@}`OX-@W=ANbcuBCX%k~?K7n6*^sETyZK{25E$ zw54>#QhCc#v>=Wb%zS2rvz9XEQ{1*xtXRsHw9cxfc-~U6W~pBnZ;bAs2h?%U&X;8(}nTiPK@x{kEOR}o67k4(3+i=&-KIdZha_(f#|NxQRZ zhfxk2C6B-;d1RN;0>*a$B`K3g+J(<9e;RY*9J#RzXl!sN!IV5QX4C>Xq71<9!T#!3 zzxsne_yc(SAHVZQU-`X1`|6j!@wGqu_BX%rZ-4s_Z~pU-4}bSf_aE-R@U!EwZ+PXt z?o;`if74I>dw-or{kw^e7(7aU^@HoC5AatrHuk5#+@G6Q|f021Shc)c7MzjAeV|M?=PV=Q+^W`4%#V+%u9&^;VIjr9tF=P%OHpfkxGw+#; zOy*pJIqrrzw8wm4jBgUyA&$FLm_6&vF6CyIQuC>@9dj)+WA4>v?``U*X)&McF?%*2gRb%#UF#EQcy|{Rl*$b;SpQ#rI#dARV%sGqZyajXG zs5y1moHA@q9Wkd33%fS5W7kK_*GJ9inq`ccb7su>^XA++bJnD}XxUtG$6UH<&Ym>q zOqug%MZf%}x#E_&^0v8T*_<2J!p&>HpUD+59@q(sfCEmG>ed4)Zu^(t^ebKQ z&7V74FnO+MEU>IEps>{=q1Gw1@? zmr|2wy~(-Ex9CGpK)S@NI>OBpn!Vne2sAyb;PVbk>yQ_i$0 zf5DV7X382jm93eo?wayuOc|r5%rR5`oT+HZRJ3TSyk)AqZ7P@(=j2YBN|sC|i>90# zrtAq*{;a8N#Z)+J%9$|b-q4KBgemWasbJbvxn?ToF&T5F@@3I4nic(;o2Jr5Q$oKf zv|}Uo#zw;IM$Cx#BPY$7;%}H@_@C1E;&PiYq{SHAY>eo8e)Yz)gsG_lY+wkL@JK7eIG+>8-OlQ6A9c4f+QT>?X&*L9B!N+G z@W>GmgBlQ{1wD49EYi}Kc=8gs$xR-ol}N%M+@Y1c$`N+ipppUrHjbc=b{>Vl`sHtY z<1fDbzyJFCfA^30tDk)L4Ywce5B$$#(XV@C?>Sfgeo*}{&v*YUaP$|!)31dtycxOn zR_xt(uIk@OcZNK4Tc^s$pZqkTH4DSY$M2Jut>ki4#IQ zjiKGfux{g}4r4^WF=fFRGiGG865M5UsWUoN8=WeRZVg7~D&vV_(Wm25E!yJ+Ji*F% z;#KQhW^}I?FP$hfUT8E%c8c~?rO~C*$Xd!CwZ>BwM&}~UN{mi)N{lWgM(1LqXN|B^ zCBj_GjAz@8-i@N;R%&!BGkWolZ8myU8Cm;|zk@V(y&H_AYa<7YdCSJk8^**wV^W`J zllz6G&<+?=28^j%n>J{~QnmK_s4;)em@{R(K4i?EG*;d+maZ7HCXDGLqAgl57S0)q z7q#Qd#_S1W=BP1u(pa`)ESfWBj|(eVG?uR#3ulcvCH|nF5#oaj$$s^pc zNqq!HO&di+AL1lp(kZ1cH+JdR9aIS;e6h(hfmFJz5_=P;Y)8t>)wvNvnP&}$NjxYWIZ0fm;C6x^NQ>6yS ze1l_wFefbE;9Mw-bHuA92A4v^sbYgSb66S-9+jehs>tA0YB*hM@T?XcH?C76%$)-J zT7yT0A+XhuGH%G6G^7q05_${?-NF)k3`x7K*N~)Ha-Sik&yd=0$Qn0f-!Np13d@@| z6fGL^XAPNShHHc3rQ9h){*0ky$xymvD3~?mj2kjW40%)H%)A?htWjYcFJO1VkUeV1 z95!T)h?YK9Fl8v_)k#CioS}3mjKNj}hfq=d5dA|SV(LMk1fztt}x>}KL07hA~wp$!ILJff2SlO6e z^zm~%{&pC54;!U8?)Fr7^9Yjm`5kr)r7VIQn_VKMbaDg-74GOjDCmJFyK>mbOLh$D za1b8%?%n(QzyJI2_{YEVr9b`Mul&DX{`%Mc{BQsI>)-v>w}1JMKRo!I*PVa#;n|-Z zzw(;vwKq=Z|GQhokIppxCqu}WCde36LPnG^$qu!@df4W5PU8+B`%Y4f8pINy+piUpu zs=v^vKi{AaYSD-Fi8i=RAKI;t7}Q_Csn6HzlNR(Lt@?}2`rsDPxzL~wZq-Nh>7$4A z7kO8M{&cPWWSQQfP=Bgg?_8-rUZ6i#pm!+NJC^93O7+Kb^+z&x>{zBgs7@c#ORb1L ztW_UUufNYs+y?28! zI?nmR=y+A>-OKc+3SJpkE7ZG{isKiW^w%czS(EyNZhdTC;~u)ECSOyFRE-?$M|A>2oIZxi|DVH}r*b`odX##*jX>SD!wh z&zlm*ulMV(_35)l^o7&<+zEXKf6qS6`tM!uyO+^_FJs_d&e*-8Y0+YZ)A#Zx?&Xc% zOYFTD)U*zF=WFg>ZoeBpekZK!_T`RSkpsH$-kTxKYZvNP&Xq5D7c6?`&-s;11=UOh z*Np~L40&hw_~f*Er8PK3Rv!s0JbW(Ws9(|{x2X3I1@3v*>&@34fB7GWe)=za4!w1_ zth5XgXfB*Bp|M!pn^%p0<|E|xE4`2S3SMqOM%(9nR7@<>*cq z>3pkn-sL)v0-bxlXr*}->g>ijm`|B5pk5bHt2oT?r65| zSf1`gzRsagcO*;qNt!V4V%>!*VWBO$sBYcmCeaV#NTtrRPdBiZ-6HYR70L=Xx{C~Hta8I2;!gFr$# zj4~1u0t9G85}5&!5ez{@17`3#2gdd_HsiIu_WInt_ua7bdGFoTpYpzaN;)13)~`SH zX{x)c`&3oe?^K_onSom8FSy1oe4*h{*8FI9c{%dsn8jXC~2cKgS%8{dsxeK9ur zm$66xIrcysyZ+7C)qfeg;U2s5)7agg#_s=h?D2n$J=Df-eK&UP#n?^v*gg9HGUj+O zcKyZJ?eE7P{B>;fhq0UAj@|f1CuF`+bjv;V@E1jQe)z|OpZ@Ximwz1k;2(qU{^QUm z|1=(t@`9jJlkJvf82s=Tj$t z+Ms~PSCb=u;1Dnx`O*0Cf1o;kRQ>G!yi6|{!(yUD?Iscg(v^L^VXJxI9<><{9;PuK$?0Lu2_Sn;W-_!cGr~Q$q`L3t&rl<9ur|qGq^`WO} z)YEm>bLd^q0jKA{GsT?z%wzx3bMm?8FiSo29C^>P=ZUA|o~QMWr}egH+e5{--1M~E z7^hZNqj}TQao5xR$kVQiwcS$uuJ=7Xk3AiuirR1S!_J-^Pdr`sJe{MSZ4<=RcRcoN zf9yH~1no)Nd_;uoGXAA8PzGET#vcz&f%J?B1EO={@;XPyh6dq!S(u7B&f^o63E zfA-w_*>mHi;x9h;T>IK{^E;2@rRUCHJP&^H-1@WU$`_u?F3ANk1 z*Q~pT8@i8HHrOnib`<6`7o=C_tuLuAtb6qKBl&5mSMdnkIJE*p@8oEJQGVH&PtB1T zd50sl_nTGYZyZK)lxN1*J~j#%Ns$zu5W$xKO3t4GLx4$i@){(B%8Yd|H)GehL6cg2%;+7teZg*4($|E}pq``TW&>OG5+wPHgW?xgiRG4J^x+xBVB{x7lzU*sNi=Nm|*4UE6k3>%FV(c%b#%(YkMr)Am~$ z)UDS&x3!*ITJNaVcVFB4j@JJ~>wl!}dq+F)fj022Hu$b~@I&p`m)fPjYS%UG)C+C! znYQ<_HsI6-o+xJjGwtZ7+R%sEz+-LqL#^v=&3Z>`x~=NQTUy&0Q4;1Ztpbb3K_CL{v-q((Pq#bxi8+f4E-d01Mx3ngQ)_g;=I<%G>TJv?S;gZ&P z*^91d))6(-ep}Vnt6Ix7tz%T{eyDZa(V9mT(bIlY>%60NB6Ceqt4{4Vw2oU^&jW4G zJKFJ&wTmw8%*WdCXWDV6UO&@L=ydX3&7f0%(hRb{uMK~!o%>Wf|G9SV6Yb)2ZRBh1 z+6(RC=h~SMv~wS87e3WSzS2g%)UJQ6=(0;Y_mS$q^qF?`3+>{kiof`YcGab1F46o@ z7x+j!|B-g#V{Q1uU-mrU7s-Cv_s%czTY|e=e|+*uDjpv zd;9CbcfQXUZO0$C4Be~mzfs+Dsiyl(-L|7O&HJ`iZ7(ZnEy}9N zODxTZ%&9MJxPR|HVB{~1^4o5bAHg6+4y%BU*ErrMRc}0UYNarXQ!7aHezQ6WjQ{MN zsy7Vz;cmerc@S{%{R_U6$WLdG+Q1zJR8oWourPoTNeWp{vLWAR}_Gx$|c%UNUdh%Ecl6e(OR)H$*2{VzcWKiaL`v?=fvX9^Z6s zy;VUnrRz!Bj%S(s-p@JkN%p|=tbs3c2EWQZz&Ad=$vgCI-obA-9(rj|{^6JThuu(t z7Zo0M8&ovph6;z=B`4iwXWfk#-JK)u?W6AQ8}9Zi?zYRSHmKu@Td4Djd)tV+chuc? z*WG*Dy<^n9=aGBw6Zh_iim^R)AA9b;KXDH}aqqpaWOnMb>!y46Ew}BV``}Ym z?;dsc-*WG{9QLJsz2xM zxUC3#>xbP9=iCkF-K`_;w(IVu3+~4A6LijPz36Ve=5D*D^gsQf`z-$f^b_~N2kt`; z+=rousvdgydOGs98#>{1pLx%H>Y4l46Zh$N-IqRhU--m*%IQA#*nQ%O`|SJf;Sb&C zK2-hCnLoLYKX#vbs(LPb>^}3%ed>wZ?tFRv!}Mhw_p8i+r>}X&wSW*{!cp{&Yp{pJ5Jx< zcIsB=@oUYti?!QNm0J&6D)$wa^%WPkmgLoxm^bGo6l8>Mux_sB$C^e*M|mCukMiW` zjYpCr{eaOsIU)=m0VxF}sy|6SdjfgyMlNP;rXnf!(Z zNeyIyFPid%D5!)tkSLOXm)u7-q-GYsU@X760S_4Y0aX}&GLF>%ET3Opv}loz$2oJS zFIq5XXoeiel0^vbL-*>x;4+jHx&oSAQ<4btJiCG`aI(YS)wW9nZ4% zzMs4QqwIYjXYKtgYtQFdd!A?SeV)DVdCoqUQ0{u8L`&~sx zToor>4R%-S1y|>YtL1{L`K-%&R@KeJzfueQIYph9U0v688gcd9boGt8dTywC=cw!8 z2d=X&*J+n);Hj(Ux~uz|tJk3zX!l*$ey6ItF1y-BTs0S66=z(P!>*bOu5H&`eb-&P zZn}1ly7t_4?Y`~mx$5e^iuBy(4v#zQ$u8I?` zs?)C8Vb|8dv|v&bz8lxvG%F%=50+5m(b?SIsF`%}GVIr(I1K zT#e`S9=)^nlnY{g`dcn3eU3eK9eLy$xaAtSsmL}#gST7;?Z55vrURpD%84hgp$D!* zcU{MyxXymyvj53--b~W$#-0*p1Ou{+WW2(k6nlFs(z-NcDjz%klCM=m$+9j@y;UEh18x@BNXRbQ#4voOz^l~R!rTbvP{n-#U8 zy|#rA<^S{L3xId-+~Mm~pbSjuiE%tR@{e&+HS(i37*%T2AxVY>l^k~sFv5VuNq^&b z6^uY~QhpRXfE7gK=}Nlo&g9AAZ}23&{%Sj4EoAWZ-WJYo1jDlkaD3;{;@ z6~~&Inx#vZPJd(O%qg?yO!JvPYx%+jfs2<$EML7oFfuP}eOXjSZFo+5c=7J2P5Vt1 zN8@VFBsO14Y8gpxyP49#H?Z!fcfXy{_b8+HiMjV3bMMoP9>^(V?sZP0%wDHZ)(+>d z)a%UZ(}~VLXKueUf3I`%0cZ7)v+0zx;kdK@n6vJPvu?;)tCQk&sz2g{noc;IPdnR& zoh^1}`*~;QMd!9l&dv+Yu1n6Hx157doI_8Yd+s{BFFD)KI@`~vx?|YcdCu8)-Pt?h z>>PGBope^6aF!o)ww`zH9C7wsc5XZG>^kr4zUb_^q^RSJv+bm_^@OwSlwvyV-0ht^ zE<3x1ogJs09jBb_r<^rI&dMXsvIEX7hn(eyom&n%%l13V26VDH%O+^c0VP&}zyarG zo3s3&v*v`Nsw2+w1J3gO&I$}as;KI)v*Ms?R_L9T2c6YNlvw=<=Z-7Reb=1>BhG$o zMCaeqt_x0Y+I`U}gs|}kW1r}c-Q==7-m@S~=qZ#Nx%&~Wfx zOEW0d8)j1sIqmiyrI9WvS;(=w&MJ{g3PTOQ%WUAWB+7}G z8VK`x2P8_7$HrGrs>YjDz$lrK8YJ?Qk}5&|_#-$1O&m2rB4UEg)CWN z@?EoGRYbmjY*|QJU5L4TZBB1^VSn_d!Pu=w;wn$ZRh>zw9ZqSvnB06hvEfQm<48*L zweqCRs+tYR>>H>00Y~GYqy3np zwprg^Ih)y&q>2s9qbQJYCN_Huxu=_VuwA}#}_c$!O9A*8E;$Fp<^g1^0byV(G zHGBy@2=u9D84Kz?rM(UzORr^|ezcR|(LkE$W*q1iv|7&!0PJM7qTe4^j(*lkDP zdfmYF%Kq!MgV(F~UE8|rTE)(*6@6FAdoOM2xwvKfg)Lpf72D5j?KxH6d2Dmb;my{; z(%QYnTXz+ebrlq~=H)bGZK%piwd5w|XT)Ttg{Gzk#+9V!^YdziE}78)BS@t1gB4Oh zB>)6vk{rDctCAcIFdE5G@W|no0-X5(&!o)g{Ra-fXq;5N!3Ye&qd*cQQUDs64y=*a zXz~;(r&ekT@T5mx*9g`GbXTriA*<5QM9H22lTLmt4#UAC%QiGL@O`UkZ%mu<=FC}B z=gpb1c>bJ~3l|11S{Av?Kgl;FGccwwGG$A&xjr(pB{ZuuEVnnZpxs9Z`f#k=fVyHyQUcH8TA+MD*;8@SMRdsVl+y2oC=&7R+4&ug>iw%9ke z*b88+_S~k|P=2eusKZ{^ZqKtSqFK^qFWqi0Xti&o*{s$nYO|Mg+Kby2uX>v81rYu1 z_TmoZkfwfn*8%&sL3=Yg_bF=nEm`~Qigu1u^G>@^>u!6eO;KyV9lm?NeaDc!YtY_C zbC%a%fJ7;BSOttyU#t=3hmR!#lmwCQimnEBS++0%XI&R#Zuo}bU+wToA-TNaQU6k!fsR}hg@ z7L!(GGS|gqTEj9r!ZW)fa(bdR_L+)ynu>PE6z*A9yf@CWFU~Tsu1HaAi7n1zi!Zaq zmD*y9e?xJ_w#kGroq8Q#VlybA)CSQ^EVHFo*mA3EMfJ9l23ujRt)R-5UuD~<*YJv} zbwZ}jW@%DX+F;w%Y^!LuZD~^kQ@g{~-fwH|w^eo7%B;3cO^PgysxEJ{)pXmoG}|l< zwk<8T$`0Gsc2!q(*veaNWsRz?XtQl)omSf>-ptpJ6a3~zTV;RRrzFNovpM{Dc00&Yusk5X|+`~k5hHCO;O8lsHVl{O?7QHYnQEQ zn+>M1!`9kkYu{mO?pDpZR$F7c8g1@U{hd2i-Ox5rQag}eJy24=uefe+e%0QBs=b9( z{l&Gr3o3VQ+|rj<)|*?}om1SIUD%$L*PNZxkeyYXwV@&-xoks1VVWs7F)U+!aB6~o z{JIs}e(Q|Hf~v1smW-}&=b`z#4vwlc;) zFg|c?YDi>OXiQ#2Y*EyDOH9(1nB=W7$(51GHDO70p~(&5DUA_nO;H=HQR&vmbXEU` zPq#*ASfgb$%^ImwRGM|1L|&TkFnUikvwlnKGOP)i*3?|9d80MEz?xNH&B(K6LWynRRoOwYt_?S!*rZs(LmeQ>5zrVr%hc zYjK&iXp`a@f-j+GlVS>4q(o7XMG>RdjkMiVbWJV)7 zN@g^`NLr)_80A$h&yxH_QckLq!1(Gr93W|c5uRs55JZ}j^C}SIED9t+A4R|@JT++L zyb1<^8)6tMNQ9BsJJMt+e$J5;$vSOqZ9zdnZ~gHtl_KAqIpeK4v!>0T10?4xUohX_ zcWKDV{mIOzat~Hg0 zDzdDNu}}+zL|Y*EuyvL&hN6F^&jOSs7r6=z9Eu%ske(vmHy$(E$` zlPP(iq90U$eUk$ojpS%RlEbQZas-lqQSfMhQSfMh(fFf@Fl0#}$r%+q8t-tt zPpUvqivHmE7Xy-HG*Cw3184$CYEm9O0FXl|1%@U?9vivgfHio;m@cEFLJCbFNe<+dQ%$d1l!Q2%~7OwVP9JFHDTEFFy{;OgF{MH5e z#|H-{t_@0F8hxH1ZlXCq(VV&7oN7{|LP#>YACwMO2zZm(WX_IN6Jem-cynHYIVVoZ z;9FdZ+v6iM5~4B^qcajB(__QZOl#BDtxbtrn-UwG7!$ZY+CMI4^|~0pn5g9u;Y-89 z7KeoTtTFjT6z1gfUz!rMgeXDia5#8oBr^&aIjl}PuX^KA@}u$OD3F{4#(#!K@}mJs z@}m?Eu3*r>qa;Upv+4~-Ao=spKLbe^K@gbYkV%#VQ>04@uUo+>2~G+I0zgTEk|L4h z`4Mcw$mx{4$rKhu5*|GA7ZZLTVA--|Q~oeTLGq2M)83pueag(4dX}6&bCJ)SrHkh- zUpjx4uTQ|rMQc_r4)$BJ)_+-8z_Rc_--w{)QEQe*uUQctydowvDPHfPX2|G=j|&^mwBnV=8BuUoAsT30E|&lIxK6uL^$+LelEP9i!*z>vYrh}EWWKNHivJ5|pr zMM|DoLiG44VN6Eb^+BdYYLpK!#rvBQUQ1}J)A|6DP-1{7Dae!*sOBaInNow)3X#A1 zIVRFiQS|EQXuqh)m672qBEx(m!hFNRmW75c30b>nO~}H)kOlrBJ^}F|G5OgWTUuH; zs*zA6Es_}lqdYbmc$6nc^Ma0<{cS)MwX!V6VyL_9CkFVCC! z1b_o%@W|)o_g0+utR zGc=_~n!jJOvIsDp3;8by2wE5r>=O{YFdzv2b+l%I8eQu%PN9ne!WIQkhc60341m_^*P;h`2nI=688reHD4m6b z_x7H_BfzL3Ak8430BF(*m>)Q?p!c$LGKBKz5WQGYgik=Y7t#DZS`-k;#6?^1Rq*^(LGxAy%vrH|wy*ze-{{q$=A<-YjE{X1qQtG7PUV2A zKQfM2(j&=H|Er^Vnd6-t<*@o{a+LgNyi+yuqabn8lOtd>@F*X;1CktBU;EfdHWV;Y z^P@e2M>&p?@I(r_doH}p8wD~>&bNa%?GZrnGv3Ti>B}->6 zSvGU2ucBqkXDwT&i%aztsL_1&tY!YQ75U9twrb{5KSfJc&0G?)$S*N6cB46` za%&}TCkS8;W4y5eYx0iN8&m2fss0Pbz>QHbD9?}7@D$09)RPXY#><@7=11e<(K|D8 zUN!J2VC16(6#ghlay0(nC~sB`FzSi%X9JI9G;$d*B%P7+03$s#CH-NkoLzw-zyzK& z!6RU#a6|`>ipQgIR1g)B;rXa~E3{4?lUEyUDwJ@)GPkItKWs zgF!~bjDBIHAFI(JP$%>el?+1+Muv=f`Lu=0rY-cHwh#tdJ$Gr)qE*3*SB3ien}Q=! zx;5=+3K;jov3!@JOKtFp|zd5Vhn=YAgkw01$ggizG_P zi9ig5%9ExfNB*cmlcR#9QDy;WR$~!nG0Hc&OeWLXwQKn+BrkSWtXL5e62d3UDFFci zQBhH0VPR|5tO*Yfr=L%{@-j9eA_93Be}8{w@$nueGPGd90`*nOdGq*!GiBz?nX~jF z47D&bX3XFh38;~QnXVW0n_BbdQ!|4VL;-5Pd&1+bpPyfFa4>(Dk(wTKOGrpaPEL-G zk4I-D(Sd?8OhK!dn3%-GL`Gv{W2slKUX2y&^@1%Jg$Xd&Lh<$WMT@CZr=lT>!J`|u zDKtSJl%$}Wp%p`7AT?G~7-b?WOqnv}t+(DnB^2N)_?D}1X*`Jo@ffzCJhsq8X5G4V zD1ZP%Sy@?mxp}Bfe`shZVqy*!;T*1xK3s?bgR%G=hKr)GXfEEvKPbS*Jh&EyvksfZ zCAcDmOVi2aq#yO7qoYwHE-ns7;Z+n!N=iyeNx@t682vO;Q&TfDGjnrt^Ec)f78Dj2 z6+xvXCFME>c|Ayg2@FYy96^oqC&;3_7LVSL6evkjlUJkk05oKPp`=J}FdB0Oj|fvH zom9Q?D2G)eIRZv00Fy6($YUe5ksJXa`BA_~4R0V3Kyk>V7NB7`LjaA82?i8J3;Oim*-DI{6G*UYOSi^Wn}TB^3GxVW&O0D|9`x3M5UUl@9d3Jdc$ZltqB zmmvZR3JRD-;m5TotV1a)D`PbnzJb!z)P!#QG&EP?T8)j3+(s~m!Xq#OC`Lh;M-`dN zOFTYikA{4t5D#!H=aci8APOTU>(EIop_SQe&dJU}HZksF?h#r~{`YW9_ZK6U3 ziy#a^k|C_f%FH5ASp<@+P~%m6MU5LV0nO2bS}ek=D9N1`W$-6ANp?!qMpdx|hls~m zoGWH$WoKk$plw=O8t9+^9GWPAGNKhV3XA4=6{q1M3YMZg1s74o349<#wB=cpQ9TN$E83|f(qZFHc5fA7SBZT%G7v810E+m3<@NT90#BbOo2NcPrvz& zmArcaK|qO7guUl-SOtj`=E`)y_&a!fH93Mu9wDXhASqxp@Ms)X1(Gx|9D9Kk*dZHI zFqu3^-UN&UB;ZmHmiludkYsZypbY15k3t^6vI3pB4!l9AS{4oXJG&Z`zs6)D2(hcTMWwR;hsQ^7y|J0 z6Toae=2N(ba4ob&PYQO)*7I_J;}8m9Bj0vG9&->wRg}RqbTUdO0(?CUyJ)f+lIVtF z1RGH&=s+d8BcT#HUoZDC6w?Vxyr zQSiuNmEQ8t5h= zQdo^L0mskyC>;-v3#cU2agIO?+u2t9Kqr3FxB8&mmk2q$#LfaM97`y| z2=o|2-f%me!T+Ks)`?x{jGnAakZ=i#1QHCL*o)I}7oMabgH|Yy!gvqA5iNp5 ze2y)I3ffZG1(1l_Dc*SGwTzJ;<>kz)coa-Yj+6W-CspH|X(Tm)4?kB0g6KpH7^>{( zRQb`sqxW><9gg=&RnRSXG{DHR6h0&XBtasmq`*jKqy~}H7%oADL)2aM^mt0bIrt5C zv9oL<3=YI~@G!VnYC)nnpIQoQ5*6ZM)?rP6h9toZD&eW=l=zn(xot{RBPmy51vZF_ zvIyG*B-u?tBD+r{PzVVEgLohkKpf#p0Rr$cs*s>(AL0ZU5|c!Qo)y)PQeu|`491Fj za#4aokcdTsSrkSAF^%9SNRUKfVum65Y06DQ81y7=C1?qI2~@5wJi5V)8fb-X^wUGo z(o}}&zl$q?1(FD06sut!h!Bh*gEIw>{GpA4+Qco&utE3@?-8*i4$=oh*sDkPFtgxU zmKEflCaz;yzz7Bfi7=8Mfu|HQBQj!?Xo$8Hwu5!31&k~%Mcj)6xfTTj=|?ec^^zZP zI{|?dX*!S;I13()ML?o}QK0P&M&7bY0g{450i$F_YE9F?Bet+d zIDweQ8{z>1Ogixi0g3mBRe>k|6zm{FKTWn?V2JbKkz_TNqLU^JE6a3NkoXZ-!^1Gj z2C+NHBfzpapB|bhgSS~hc8x{YP~w(I0Ag};CI$qLM3i7tn#eFj^dbqvEQuVV0;Isp z?Hc{L5QcCEKp)wC07dk2Kq4v-LpSuqQIZ*nc63G(c?zoH5PHxYp2e}61-U4|K_wIb zjOc?7;EO`g(nJS|Nim913eyolNqG9XIyLgFhJh4N2_ir`0<3_~(U!|epyDW|pa6?t z8d`xz!62YOPhyxRcRZTNun3Ez9!_Iffg3gG1B`NNg`vrL)j%R@pg$8uVWwjvg-+HK zqo^5087_oT6tu+_aWyqVXvm)8TM9j>jbb>Knu2fP*?kH(J)p;q$f1kfp@*76v~ZZA zARtFpAUWw7Q1Cb@$H`ICJFgiT4LpJ!fh4a+IcI`0fGjEU)%^JTcvN{&Ur^SB=X)RC zX;Hu^z{DJGN9-w9;}$){R7F!d*+e!S^9fEu7atP3f*K|g0F2^Qc1Vdx~TDDVV{ zh*2|zcpzFNkkp-8|BXr(L?tvq2cRUefwo)`&=KJT08K&*4H*TGbP^KihOe-c@IxhP z#OTCiv_b)pNP(BDD=qbeF5!x?%#v6YT<8I-egU3-dMI3!f;^opLJ|F0oMq7*&)_TE zLQJARH5#HPn$ScyhA<5=c;ubqY@6sE)-^2iol$jPA(w^ViA`nX3&#MqaJRj$u7`CjaRXPFc3V_#2ggn z4o@N8q`(Uv*(Sjwo5E(j7LUgB05CO(%%a3+OL1SBemG`5UAq8LHQe#w?0$t4gLAj7j1Jd22v= zs0kSFn2{a&k!KcHVMwmU`YeTR;uh3E zD|QF>B7+IsG{}jZ=%kYi$+Zw8Xo+WR6hv?pfTOOeFV2OyI>-Wva$W_Pm)(Li?P(~f~-T$A{Z`vg#KIw15utLpu?HSFa$$9paV5SI9Bd3sK<`b#7s6q5Qn8S z(VzR?t9Zm%4lo?cCp|wJ=T%9LlHgv8rb%El@*~NS6e*AtR02EWyeeQc@TegD$*-?* z3?vE+srf|f_uqg2>PgkWBR5P8#8S3NZcTWD2$cJn-~s_cR3cD%#7lxfe8@!Z&n!i_ z;#ee+$DeqQIACwY)})uYzG@e3=myxpA>eJt)XTLOHso!my5C{7h;rI?6n}# z03(bykAOsrWD^1jd4R*USP%u!3VX4dWzmx`mSCVM_hC%N322KXdks%q5hTTc~jeicupbJ>o7A)@Q3kDRyB6qjaJ+ z%Af|?N|4h}Sn_6rk88rvq#qeBfiQ+6jMdzN*kv4xhv|n0GDu=RI>?JwAStMnM@V?A z1DK3bfTUoPPVgwV8c`2FV>{bH6Wp<7)O4ahYM=v_(t{P4Kqqd2K@(h!VyJ;WXeCi6 zV8j;o1@-<}eq@ih+hF*l=SNO({eL7$-<*B7idJ#%k!m zkPg1__v&mtfgwHc6al6j8U=|g0^YeIg#bVqbfXxC!_dS=tl+MKML>^>5g9{MRX5k_Hz zVZ;h*E+LO{VhC!Z68eb$aS;!RSi#X6Lokh8iSvnh7N^OM<6EY%H8in>O=LPT00g)$ z2~nOIIlBTzo+4?|3G_&vbb?28Koe|76MT-1Sc(Veffprlf?Sjyyg`l0*up5r;yOB+ z1%sp*j-JF1TA>MgqMO7Ocw`GC*knjX=|sT5EN_x|-OBL*hC7lJczTT2uq04<)x#?q z(wsLKIb?d{5in9njubK@MZm}}T+m%ERNo z>IF~|RB|?8N7y60!7fwS7iyq{09atNDDa5kCGiG5f)N}j?qU{B<4%Rs7-gd1k=SO4 zm}G+pGd6`VlZ}%dp_amCNueoQCcB2b6d5J*2?KbAKt1;fFa7igBa2Y8<4oteT%Aov zF-$;hlw?B*X_`bY9w3sbi5v>HNa`mZFbZHIkEPU@!?J`W5lBuX6sh6S7ELe>1W|Kc ztl-kb8w*mSgQy`9h-dIKZc%{Lvx)TJD{&Mxk_^d2R>L}=0YJDGwqOMT$uX4|8f*~i zN%Yc*EfR|CBRbP$?3hpPUL0qvZqAgnkkN$#3c!4Aea|^;K z43|?nw;-Bq6NOHi6mCb1f=z%)5nxiw;g(zpjwl9{z>fD}72HvDI8OfmRe>kM;E|&8 zqFxM8Gelu2;LHmgGNU9%!1yW>|E3qgBUWQRfk(~832^WddyRhp6x)XfupNeIp&*7l zE+VjjGdymTxyZ1~6h`SJwh0o3m?bL{U~CFILfp!}$ab)6Fzgx(HKR1CrH4)mO?F)7 zvaQ0?q)12*6);i|mLe006QWuyV#nEBR3dcQL1K~`8zmm7i4AmSTXBwV%^7wd|1c4I zv4}9^S`wwiC%mqpicA!PM?e8g#}Ov8ApXPy)Y4B4FP@P*6{v(kh9WmEkwJ{<@VEk> zP>5u(k0uhL=msNqO9@w;55ty89AXjhBsCD92unO;GGZ*wmNAMvV(1SZfeAU0Gb#*C zKu1jv2!+8|3RWY)5In%d6@pC^Lp?mtF0&f0Ky74Dn=PQpW~uq@?c`ZL#)DnlYFHcr zaXaR-H3ScZ0Hen9D2cY1iJsg-*&2W*)&Va0NB})-sDP0}!aoC}2!lsn!vZA%BVaNP znFbz#(rdveDH4>ueEAYog28b#>Wc^xrDpWUAAg)kjOt$lkD!l2ViYh+iUe-5cNk8v z0UtJqsNg<{bJ!sIB@V?K#1B(&3$@6TQi%j6;xQsb0*oPKn5a8-9F>AiRu)LIO%zEY zL@zu$B@8vYNug7EM2sHUR{GglcwI_$f&$6}1l6Cz2nIHtPL@TCb=YMTLr=*OXv?m# zee}qE6{AoO4@dw=>SPL5U=9og0ajy8Rwni+dT=Q`if)XeEtezG5XPA>0yO+dVSV6+ zd(j7XQRqR^C^U&l?5)+gJ2h%BF~$wh60!XvPgmy$%Y^W;0PG$lv|MClzw^Dql>H0_5ex12vk{zA`F`2 zCH%wgNDobfNxt-;C-wqKoJK8>6b!OKs3(xbI&8r}^k>(A9>qv}90SA(xxr3?B(SBB z9Obltq!gYm_2f1VNnk~hq$ZFw&Z~k-Ij>3$B*7!a?RL{+WLQ=ZTvG#Qz{sa@sP*(X zIYk^{QSD_#PLIFng4xp5I%#27p~&dN;W zRxANS&5pAgn~vw%EJ-B_MLJ{%Gqwz%u}8wNk1!MgBk}?_B;napnlg)BCJYD_mI56N z!P7%{P#8s?)#Ofs8iXY~j-Ko?wcL$~PqrH#t5KUKF)a4t846Pv6|LkdTtb3SUUbkz zB}|}jMQlV^A`J$^L74)i4oQ~Mv8Z01NkT*boKg@FPa*@4KJ18uD>XKC>m`sHztdoIuGNkG!|>PLZ5iUwr+wBE9ew osUuQlNrogvDoE>vx!-;F9Y~Y{Dg}~8uJnG2ltf9-AO7(F04gRoMgRZ+ literal 0 HcmV?d00001 diff --git a/src/burner/win32/resource_string.h b/src/burner/win32/resource_string.h new file mode 100644 index 00000000..8fc76377 --- /dev/null +++ b/src/burner/win32/resource_string.h @@ -0,0 +1,232 @@ +#define IDS_ERROR (IDS_STRING + 500) +#define IDS_MENU (IDS_STRING + 800) + +#define IDS_FIRSTRUN1 (IDS_STRING + 0) +#define IDS_FIRSTRUN2 (IDS_STRING + 1) +#define IDS_FIRSTRUN3A (IDS_STRING + 2) +#define IDS_FIRSTRUN3B (IDS_STRING + 3) + +#define IDS_CHEAT_NAME (IDS_STRING + 10) +#define IDS_CHEAT_STATUS (IDS_STRING + 11) + +#define IDS_INPUT_INPUT (IDS_STRING + 20) +#define IDS_INPUT_MAPPING (IDS_STRING + 21) +#define IDS_INPUT_STATE (IDS_STRING + 22) +#define IDS_INPUT_INP_PLAYER (IDS_STRING + 23) +#define IDS_INPUT_INP_KEYBOARD (IDS_STRING + 24) +#define IDS_INPUT_INP_JOYSTICK (IDS_STRING + 25) +#define IDS_INPUT_INP_XARCADEL (IDS_STRING + 26) +#define IDS_INPUT_INP_XARCADER (IDS_STRING + 27) +#define IDS_INPUT_INP_HOTRODL (IDS_STRING + 28) +#define IDS_INPUT_INP_HOTRODR (IDS_STRING + 29) +#define IDS_INPUT_ANALOG_ABS (IDS_STRING + 30) +#define IDS_INPUT_ANALOG_AUTO (IDS_STRING + 31) +#define IDS_INPUT_ANALOG_NORMAL (IDS_STRING + 32) + +#define IDS_DIP_GROUP (IDS_STRING + 40) +#define IDS_DIP_SETTING (IDS_STRING + 41) + +#define IDS_INPSET_MOVENAME (IDS_STRING + 50) +#define IDS_INPSET_MOVE (IDS_STRING + 51) +#define IDS_INPSET_WAITING (IDS_STRING + 52) + +#define IDS_MEMCARD_CREATE (IDS_STRING + 53) +#define IDS_MEMCARD_SELECT (IDS_STRING + 54) + +#define IDS_PROGRESS_LOADING (IDS_STRING + 60) + +#define IDS_REPLAY_RECORD (IDS_STRING + 70) +#define IDS_REPLAY_REPLAY (IDS_STRING + 71) + +#define IDS_ROMS_SELECT_DIR (IDS_STRING + 80) + +#define IDS_STATE_LOAD (IDS_STRING + 90) +#define IDS_STATE_SAVE (IDS_STRING + 91) +#define IDS_STATE_ACTIVESLOT (IDS_STRING + 92) +#define IDS_STATE_LOADED (IDS_STRING + 93) +#define IDS_STATE_LOAD_ERROR (IDS_STRING + 94) +#define IDS_STATE_SAVED (IDS_STRING + 95) +#define IDS_STATE_SAVE_ERROR (IDS_STRING + 96) + +#define IDS_DAT_GENERATE (IDS_STRING + 100) +#define IDS_SCRN_NOGAME (IDS_STRING + 101) + +#define IDS_NETPLAY_START (IDS_STRING + 110) +#define IDS_NETPLAY_START_YOU (IDS_STRING + 111) +#define IDS_NETPLAY_START_TOTAL (IDS_STRING + 112) +#define IDS_NETPLAY_DROP (IDS_STRING + 113) +#define IDS_NETPLAY_TOOMUCH (IDS_STRING + 114) + +#define IDS_SSHOT_SAVED (IDS_STRING + 120) +#define IDS_SSHOT_ERROR (IDS_STRING + 121) + +#define IDS_SOUND_NOVOLUME (IDS_STRING + 130) +#define IDS_SOUND_VOLUMESET (IDS_STRING + 131) +#define IDS_SOUND_MUTE (IDS_STRING + 132) +#define IDS_SOUND_MUTE_OFF (IDS_STRING + 133) + +#define IDS_DISK_REPLAY (IDS_STRING + 150) +#define IDS_DISK_THIS_REPLAY (IDS_STRING + 151) +#define IDS_DISK_FILE_REPLAY (IDS_STRING + 152) +#define IDS_DISK_STATE (IDS_STRING + 153) +#define IDS_DISK_THIS_STATE (IDS_STRING + 154) +#define IDS_DISK_FILE_STATE (IDS_STRING + 155) +#define IDS_DISK_SOUND (IDS_STRING + 156) +#define IDS_DISK_THIS_SOUND (IDS_STRING + 157) +#define IDS_DISK_FILE_SOUND (IDS_STRING + 158) +#define IDS_DISK_FILE_CARD (IDS_STRING + 159) +#define IDS_DISK_ALL_CARD (IDS_STRING + 160) +#define IDS_DISK_ALL_DAT (IDS_STRING + 161) +#define IDS_DISK_TEXT (IDS_STRING + 162) +#define IDS_DISK_FILE_PATCH (IDS_STRING + 163) + +#define IDS_DISK_SAVEREPORT (IDS_STRING + 180) + +#define IDS_GAMELANG_LOAD (IDS_STRING + 190) +#define IDS_GAMELANG_EXPORT (IDS_STRING + 191) + +#define IDS_ROMINFO_DIALOGTITLE (IDS_STRING + 200) +#define IDS_ROMINFO_ROMS (IDS_STRING + 201) +#define IDS_ROMINFO_SAMPLES (IDS_STRING + 202) + +#define IDS_SPATH_PREVIEW (IDS_STRING + 210) +#define IDS_SPATH_TITLES (IDS_STRING + 211) +#define IDS_SPATH_CHEATS (IDS_STRING + 212) +#define IDS_SPATH_HISCORE (IDS_STRING + 213) +#define IDS_SPATH_SAMPLES (IDS_STRING + 214) +#define IDS_SPATH_IPS (IDS_STRING + 215) +#define IDS_SPATH_NGCD_ISOS (IDS_STRING + 216) +#define IDS_SPATH_NGCD_COVERS (IDS_STRING + 217) + +#define IDS_ROMPATH_1 (IDS_STRING + 230) +#define IDS_ROMPATH_2 (IDS_STRING + 231) +#define IDS_ROMPATH_3 (IDS_STRING + 232) +#define IDS_ROMPATH_4 (IDS_STRING + 233) +#define IDS_ROMPATH_5 (IDS_STRING + 234) +#define IDS_ROMPATH_6 (IDS_STRING + 235) +#define IDS_ROMPATH_7 (IDS_STRING + 236) +#define IDS_ROMPATH_8 (IDS_STRING + 237) + +#define IDS_PRESET_SAVED (IDS_STRING + 240) + +#define IDS_CD_SELECT_IMAGE (IDS_STRING + 241) + + + + + + + + +#define IDS_SEL_FILTERS (IDS_STRING + 250) +#define IDS_SEL_HARDWARE (IDS_STRING + 251) +#define IDS_SEL_CAVE (IDS_STRING + 252) +#define IDS_SEL_CPS1 (IDS_STRING + 253) +#define IDS_SEL_CPS2 (IDS_STRING + 254) +#define IDS_SEL_CPS3 (IDS_STRING + 255) +#define IDS_SEL_NEOGEO (IDS_STRING + 257) +#define IDS_SEL_PGM (IDS_STRING + 258) +#define IDS_SEL_PSIKYO (IDS_STRING + 259) +#define IDS_SEL_SEGA (IDS_STRING + 260) +#define IDS_SEL_TAITO (IDS_STRING + 261) +#define IDS_SEL_TOAPLAN (IDS_STRING + 262) +#define IDS_SEL_MISCPRE90S (IDS_STRING + 263) +#define IDS_SEL_MISCPOST90S (IDS_STRING + 264) +#define IDS_SEL_MEGADRIVE (IDS_STRING + 265) +#define IDS_SEL_PACMAN (IDS_STRING + 266) +#define IDS_SEL_KONAMI (IDS_STRING + 267) +#define IDS_SEL_GALAXIAN (IDS_STRING + 268) +#define IDS_SEL_IREM (IDS_STRING + 269) +#define IDS_SEL_BOARDTYPE (IDS_STRING + 270) +#define IDS_SEL_BOOTLEG (IDS_STRING + 271) +#define IDS_SEL_PROTOTYPE (IDS_STRING + 272) +#define IDS_SEL_HACK (IDS_STRING + 273) +#define IDS_SEL_HOMEBREW (IDS_STRING + 274) +#define IDS_SEL_DEMO (IDS_STRING + 275) +#define IDS_SEL_GENUINE (IDS_STRING + 276) + +#define IDS_GENRE (IDS_STRING + 300) +#define IDS_GENRE_HORSHOOT (IDS_STRING + 301) +#define IDS_GENRE_VERSHOOT (IDS_STRING + 302) +#define IDS_GENRE_SCRFIGHT (IDS_STRING + 303) +#define IDS_GENRE_VSFIGHT (IDS_STRING + 304) +#define IDS_GENRE_BIOS (IDS_STRING + 305) +#define IDS_GENRE_BREAKOUT (IDS_STRING + 306) +#define IDS_GENRE_CASINO (IDS_STRING + 307) +#define IDS_GENRE_BALLPADDLE (IDS_STRING + 308) +#define IDS_GENRE_MAZE (IDS_STRING + 309) +#define IDS_GENRE_MINIGAMES (IDS_STRING + 310) +#define IDS_GENRE_PINBALL (IDS_STRING + 311) +#define IDS_GENRE_PLATFORM (IDS_STRING + 312) +#define IDS_GENRE_PUZZLE (IDS_STRING + 313) +#define IDS_GENRE_QUIZ (IDS_STRING + 314) +#define IDS_GENRE_SPORTSMISC (IDS_STRING + 315) +#define IDS_GENRE_SPORTSFOOTBALL (IDS_STRING + 316) +#define IDS_GENRE_MISC (IDS_STRING + 317) +#define IDS_GENRE_MAHJONG (IDS_STRING + 318) +#define IDS_GENRE_RACING (IDS_STRING + 319) +#define IDS_GENRE_SHOOT (IDS_STRING + 320) + +#define IDS_FAMILY (IDS_STRING + 340) +#define IDS_FAMILY_MSLUG (IDS_STRING + 341) +#define IDS_FAMILY_SF (IDS_STRING + 342) +#define IDS_FAMILY_KOF (IDS_STRING + 343) +#define IDS_FAMILY_DSTLK (IDS_STRING + 344) +#define IDS_FAMILY_FATFURY (IDS_STRING + 345) +#define IDS_FAMILY_SAMSHO (IDS_STRING + 346) +#define IDS_FAMILY_19XX (IDS_STRING + 347) +#define IDS_FAMILY_SONICWI (IDS_STRING + 348) +#define IDS_FAMILY_PWRINST (IDS_STRING + 349) +#define IDS_FAMILY_OTHER (IDS_STRING + 350) + +#define IDS_IPSMANAGER_TITLE (IDS_STRING + 370) + +#define IDS_ERR_ERROR (IDS_ERROR + 0) +#define IDS_ERR_WARNING (IDS_ERROR + 1) +#define IDS_ERR_INFORMATION (IDS_ERROR + 2) +#define IDS_ERR_UNKNOWN (IDS_ERROR + 3) + +#define IDS_ERR_LOAD_OK (IDS_ERROR + 10) +#define IDS_ERR_LOAD_PROBLEM (IDS_ERROR + 11) +#define IDS_ERR_LOAD_NODATA (IDS_ERROR + 12) +#define IDS_ERR_LOAD_ESS_MISS (IDS_ERROR + 13) +#define IDS_ERR_LOAD_ESS_BAD (IDS_ERROR + 14) +#define IDS_ERR_LOAD_DATA_MISS (IDS_ERROR + 15) +#define IDS_ERR_LOAD_DATA_BAD (IDS_ERROR + 16) +#define IDS_ERR_LOAD_FOUND (IDS_ERROR + 17) +#define IDS_ERR_LOAD_NOTFOUND (IDS_ERROR + 18) +#define IDS_ERR_LOAD_INVALID (IDS_ERROR + 19) +#define IDS_ERR_LOAD_CRC (IDS_ERROR + 20) +#define IDS_ERR_LOAD_SMALL (IDS_ERROR + 21) +#define IDS_ERR_LOAD_LARGE (IDS_ERROR + 22) +#define IDS_ERR_LOAD_DET_ESS (IDS_ERROR + 23) +#define IDS_ERR_LOAD_DET_PRG (IDS_ERROR + 24) +#define IDS_ERR_LOAD_DET_BIOS (IDS_ERROR + 25) +#define IDS_ERR_LOAD_DET_GRA (IDS_ERROR + 26) +#define IDS_ERR_LOAD_DET_SND (IDS_ERROR + 27) +#define IDS_ERR_LOAD_DET_ROM (IDS_ERROR + 28) +#define IDS_ERR_LOAD_REQUEST (IDS_ERROR + 29) +#define IDS_ERR_LOAD_DISK (IDS_ERROR + 30) +#define IDS_ERR_LOAD_DISK_CRC (IDS_ERROR + 31) + +#define IDS_ERR_BURN_INIT (IDS_ERROR + 50) + +#define IDS_ERR_UI_NOSUPPORT (IDS_ERROR + 100) +#define IDS_ERR_UI_WINDOW (IDS_ERROR + 101) +#define IDS_ERR_UI_MODULE (IDS_ERROR + 102) +#define IDS_ERR_UI_TRIPLE (IDS_ERROR + 103) +#define IDS_ERR_UI_FULL_NOMODE (IDS_ERROR + 104) +#define IDS_ERR_UI_FULL_PROBLEM (IDS_ERROR + 105) +#define IDS_ERR_UI_FULL_CUSTRES (IDS_ERROR + 106) + +#define IDS_ERR_DISK_CREATE (IDS_ERROR + 150) +#define IDS_ERR_DISK_LOAD (IDS_ERROR + 151) +#define IDS_ERR_DISK_UNAVAIL (IDS_ERROR + 152) +#define IDS_ERR_DISK_TOONEW (IDS_ERROR + 153) +#define IDS_ERR_DISK_TOOOLD (IDS_ERROR + 154) + +#define IDS_ERR_NO_NETPLAYDLL (IDS_ERROR + 160) + +#define IDS_ERR_NO_DRIVER_SELECTED (IDS_ERROR + 170) + +#define IDS_ERR_NO_DRIVER_SEL_SLOT1 (IDS_ERROR + 175) diff --git a/src/burner/win32/roms.cpp b/src/burner/win32/roms.cpp new file mode 100644 index 00000000..d04582c5 --- /dev/null +++ b/src/burner/win32/roms.cpp @@ -0,0 +1,444 @@ +#include "burner.h" +#include +#include + +static HWND hTabControl = NULL; + +HWND hRomsDlg = NULL; +static HWND hParent = NULL; + +char* gameAv = NULL; +bool avOk = false; + +static unsigned ScanThreadId = 0; +static HANDLE hScanThread = NULL; +static int nOldSelect = 0; + +static HANDLE hEvent = NULL; + +static void CreateRomDatName(TCHAR* szRomDat) +{ + _stprintf(szRomDat, _T("config\\%s.roms.dat"), szAppExeName); + + return; +} + +//Select Directory Dialog////////////////////////////////////////////////////////////////////////// + +static INT_PTR CALLBACK DefInpProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + int var; + static bool chOk; + + switch (Msg) { + case WM_INITDIALOG: { + chOk = false; + + // Setup edit controls values (ROMs Paths) + for(int x = 0; x < 8; x++) { + SetDlgItemText(hDlg, IDC_ROMSDIR_EDIT1 + x, szAppRomPaths[x]); + } + + // Setup the tabs + hTabControl = GetDlgItem(hDlg, IDC_ROMPATH_TAB); + + TC_ITEM tcItem; + tcItem.mask = TCIF_TEXT; + + UINT idsString[8] = { IDS_ROMPATH_1,IDS_ROMPATH_2,IDS_ROMPATH_3,IDS_ROMPATH_4,IDS_ROMPATH_5,IDS_ROMPATH_6,IDS_ROMPATH_7,IDS_ROMPATH_8 }; + + for(int nIndex = 0; nIndex < 8; nIndex++) { + tcItem.pszText = FBALoadStringEx(hAppInst, idsString[nIndex], true); + TabCtrl_InsertItem(hTabControl, nIndex, &tcItem); + } + + int TabPage = TabCtrl_GetCurSel(hTabControl); + + // hide all controls excluding the selected controls + for(int x = 0; x < 8; x++) { + if(x != TabPage) { + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_BR1 + x), SW_HIDE); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_EDIT1 + x), SW_HIDE); // edit controls + } + } + + // Show the proper controls + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_BR1 + TabPage), SW_SHOW); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_EDIT1 + TabPage), SW_SHOW); // edit controls + + UpdateWindow(hDlg); + + WndInMid(hDlg, hParent); + SetFocus(hDlg); // Enable Esc=close + break; + } + case WM_NOTIFY: { + NMHDR* pNmHdr = (NMHDR*)lParam; + + if (pNmHdr->code == TCN_SELCHANGE) { + + int TabPage = TabCtrl_GetCurSel(hTabControl); + + // hide all controls excluding the selected controls + for(int x = 0; x < 8; x++) { + if(x != TabPage) { + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_BR1 + x), SW_HIDE); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_EDIT1 + x), SW_HIDE); // edit controls + } + } + + // Show the proper controls + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_BR1 + TabPage), SW_SHOW); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_ROMSDIR_EDIT1 + TabPage), SW_SHOW); // edit controls + + UpdateWindow(hDlg); + + return FALSE; + } + break; + } + case WM_COMMAND: { + LPMALLOC pMalloc = NULL; + BROWSEINFO bInfo; + ITEMIDLIST* pItemIDList = NULL; + TCHAR buffer[MAX_PATH]; + + if (LOWORD(wParam) == IDOK) { + + for (int i = 0; i < 8; i++) { +// if (GetDlgItemText(hDlg, IDC_ROMSDIR_EDIT1 + i, buffer, sizeof(buffer)) && lstrcmp(szAppRomPaths[i], buffer)) { + GetDlgItemText(hDlg, IDC_ROMSDIR_EDIT1 + i, buffer, sizeof(buffer)); + if (lstrcmp(szAppRomPaths[i], buffer)) chOk = true; + lstrcpy(szAppRomPaths[i], buffer); +// } + } + + SendMessage(hDlg, WM_CLOSE, 0, 0); + break; + } else { + if (LOWORD(wParam) >= IDC_ROMSDIR_BR1 && LOWORD(wParam) <= IDC_ROMSDIR_BR8) { + var = IDC_ROMSDIR_EDIT1 + LOWORD(wParam) - IDC_ROMSDIR_BR1; + } else { + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + } + + SHGetMalloc(&pMalloc); + + memset(&bInfo, 0, sizeof(bInfo)); + bInfo.hwndOwner = hDlg; + bInfo.pszDisplayName = buffer; + bInfo.lpszTitle = FBALoadStringEx(hAppInst, IDS_ROMS_SELECT_DIR, true); + bInfo.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS; + + pItemIDList = SHBrowseForFolder(&bInfo); + + if (pItemIDList) { + if (SHGetPathFromIDList(pItemIDList, buffer)) { + int strLen = _tcslen(buffer); + if (strLen) { + if (buffer[strLen - 1] != _T('\\')) { + buffer[strLen] = _T('\\'); + buffer[strLen + 1] = _T('\0'); + } + SetDlgItemText(hDlg, var, buffer); + } + } + pMalloc->Free(pItemIDList); + } + pMalloc->Release(); + + break; + } + case WM_CLOSE: { + hParent = NULL; + EndDialog(hDlg, 0); + if (chOk) { + bRescanRoms = true; + CreateROMInfo(hDlg); + } + } + } + + return 0; +} + + +int RomsDirCreate(HWND hParentWND) +{ + hParent = hParentWND; + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_ROMSDIR), hParent, (DLGPROC)DefInpProc); + return 1; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +//Check Romsets Dialog///////////////////////////////////////////////////////////////////////////// + +static int WriteGameAvb() +{ + TCHAR szRomDat[MAX_PATH]; + FILE* h; + + CreateRomDatName(szRomDat); + + if ((h = _tfopen(szRomDat, _T("wt"))) == NULL) { + return 1; + } + + _ftprintf(h, _T(APP_TITLE) _T(" v%.20s ROMs"), szAppBurnVer); // identifier + _ftprintf(h, _T(" 0x%04X "), nBurnDrvCount); // no of games + + for (unsigned int i = 0; i < nBurnDrvCount; i++) { + if (gameAv[i] & 2) { + _fputtc(_T('*'), h); + } else { + if (gameAv[i] & 1) { + _fputtc(_T('+'), h); + } else { + _fputtc(_T('-'), h); + } + } + } + + _ftprintf(h, _T(" END")); // end marker + + fclose(h); + + return 0; +} + +static int DoCheck(TCHAR* buffPos) +{ + TCHAR label[256]; + + // Check identifier + memset(label, 0, sizeof(label)); + _stprintf(label, _T(APP_TITLE) _T(" v%.20s ROMs"), szAppBurnVer); + if ((buffPos = LabelCheck(buffPos, label)) == NULL) { + return 1; + } + + // Check no of supported games + memset(label, 0, sizeof(label)); + memcpy(label, buffPos, 16); + buffPos += 8; + unsigned int n = _tcstol(label, NULL, 0); + if (n != nBurnDrvCount) { + return 1; + } + + for (unsigned int i = 0; i < nBurnDrvCount; i++) { + if (*buffPos == _T('*')) { + gameAv[i] = 3; + } else { + if (*buffPos == _T('+')) { + gameAv[i] = 1; + } else { + if (*buffPos == _T('-')) { + gameAv[i] = 0; + } else { + return 1; + } + } + } + + buffPos++; + } + + memset(label, 0, sizeof(label)); + _stprintf(label, _T(" END")); + if (LabelCheck(buffPos, label) == NULL) { + avOk = true; + return 0; + } else { + return 1; + } +} + +int CheckGameAvb() +{ + TCHAR szRomDat[MAX_PATH]; + FILE* h; + int bOK; + int nBufferSize = nBurnDrvCount + 256; + TCHAR* buffer = (TCHAR*)malloc(nBufferSize * sizeof(TCHAR)); + if (buffer == NULL) { + return 1; + } + + memset(buffer, 0, nBufferSize * sizeof(TCHAR)); + CreateRomDatName(szRomDat); + + if ((h = _tfopen(szRomDat, _T("r"))) == NULL) { + return 1; + } + + _fgetts(buffer, nBufferSize, h); + fclose(h); + + bOK = DoCheck(buffer); + + if (buffer) { + free(buffer); + buffer = NULL; + } + return bOK; +} + +static int QuitRomsScan() +{ + DWORD dwExitCode; + + GetExitCodeThread(hScanThread, &dwExitCode); + + if (dwExitCode == STILL_ACTIVE) { + + // Signal the scan thread to abort + SetEvent(hEvent); + + // Wait for the thread to finish + if (WaitForSingleObject(hScanThread, 10000) != WAIT_OBJECT_0) { + // If the thread doesn't finish within 10 seconds, forcibly kill it + TerminateThread(hScanThread, 1); + } + + CloseHandle(hScanThread); + } + + CloseHandle(hEvent); + + hEvent = NULL; + + hScanThread = NULL; + ScanThreadId = 0; + + BzipClose(); + + nBurnDrvActive = nOldSelect; + nOldSelect = 0; + bRescanRoms = false; + + if (avOk) { + WriteGameAvb(); + } + + return 1; +} + +static unsigned __stdcall AnalyzingRoms(void*) +{ + for (unsigned int z = 0; z < nBurnDrvCount; z++) { + nBurnDrvActive = z; + + // See if we need to abort + if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) { + ExitThread(0); + } + + SendDlgItemMessage(hRomsDlg, IDC_WAIT_PROG, PBM_STEPIT, 0, 0); + + switch (BzipOpen(TRUE)) { + case 0: + gameAv[z] = 3; + break; + case 2: + gameAv[z] = 1; + break; + case 1: + gameAv[z] = 0; + } + BzipClose(); + } + + avOk = true; + + PostMessage(hRomsDlg, WM_CLOSE, 0, 0); + + return 0; +} + +static INT_PTR CALLBACK WaitProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) // LPARAM lParam +{ + switch (Msg) { + case WM_INITDIALOG: + hRomsDlg = hDlg; + nOldSelect = nBurnDrvActive; + memset(gameAv, 0, sizeof(gameAv)); + SendDlgItemMessage(hDlg, IDC_WAIT_PROG, PBM_SETRANGE, 0, MAKELPARAM(0, nBurnDrvCount)); + SendDlgItemMessage(hDlg, IDC_WAIT_PROG, PBM_SETSTEP, (WPARAM)1, 0); + + ShowWindow(GetDlgItem(hDlg, IDC_WAIT_LABEL_A), TRUE); + SendMessage(GetDlgItem(hDlg, IDC_WAIT_LABEL_A), WM_SETTEXT, (WPARAM)0, (LPARAM)_T("Scanning ROMs...")); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), TRUE); + + avOk = false; + hScanThread = (HANDLE)_beginthreadex(NULL, 0, AnalyzingRoms, NULL, 0, &ScanThreadId); + + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hParent == NULL) { + RECT rect; + int x, y; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + x = 315 + GetSystemMetrics(SM_CXDLGFRAME) * 2 + 6; + y = 74 + GetSystemMetrics(SM_CYDLGFRAME) * 2 + 6; + + SetForegroundWindow(hDlg); + SetWindowPos(hDlg, HWND_TOPMOST, (rect.right - rect.left) / 2 - x / 2, (rect.bottom - rect.top) / 2 - y / 2, x, y, 0); + RedrawWindow(hDlg, NULL, NULL, 0); + ShowWindow(hDlg, SW_SHOWNORMAL); + } else { + WndInMid(hDlg, hParent); + SetFocus(hDlg); // Enable Esc=close + } + + break; + + case WM_COMMAND: + if (LOWORD(wParam) == IDCANCEL) { + PostMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + + case WM_CLOSE: + QuitRomsScan(); + EndDialog(hDlg, 0); + hRomsDlg = NULL; + hParent = NULL; + + } + + return 0; +} + +int CreateROMInfo(HWND hParentWND) +{ + hParent = hParentWND; + + if (gameAv == NULL) { + gameAv = (char*)malloc(nBurnDrvCount); + memset(gameAv, 0, nBurnDrvCount); + } + + if (gameAv) { + if (CheckGameAvb() || bRescanRoms) { + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_WAIT), hParent, (DLGPROC)WaitProc); + } + } + + return 1; +} + +void FreeROMInfo() +{ + if (gameAv) { + free(gameAv); + gameAv = NULL; + } +} diff --git a/src/burner/win32/run.cpp b/src/burner/win32/run.cpp new file mode 100644 index 00000000..f2add624 --- /dev/null +++ b/src/burner/win32/run.cpp @@ -0,0 +1,547 @@ +// Run module +#include "burner.h" + +// for NeoGeo CD (WAV playback) +void wav_pause(bool bResume); + +int bRunPause = 0; +int bAltPause = 0; + +int bAlwaysDrawFrames = 0; + +static bool bShowFPS = false; +static unsigned int nDoFPS = 0; + +static bool bMute = false; +static int nOldAudVolume; + +int kNetGame = 0; // Non-zero if Kaillera is being used + +#ifdef FBA_DEBUG +int counter; // General purpose variable used when debugging +#endif + +static unsigned int nNormalLast = 0; // Last value of timeGetTime() +static int nNormalFrac = 0; // Extra fraction we did + +static bool bAppDoStep = 0; +static bool bAppDoFast = 0; +static int nFastSpeed = 6; + +static int GetInput(bool bCopy) +{ + static int i = 0; + InputMake(bCopy); // get input + + // Update Input dialog ever 3 frames + if (i == 0) { + InpdUpdate(); + } + + i++; + + if (i >= 3) { + i = 0; + } + + // Update Input Set dialog + InpsUpdate(); + return 0; +} + +static void DisplayFPS() +{ + static time_t fpstimer; + static unsigned int nPreviousFrames; + + TCHAR fpsstring[8]; + time_t temptime = clock(); + double fps = (double)(nFramesRendered - nPreviousFrames) * CLOCKS_PER_SEC / (temptime - fpstimer); + _sntprintf(fpsstring, 7, _T("%2.2lf"), fps); + VidSNewShortMsg(fpsstring, 0xDFDFFF, 480, 0); + + fpstimer = temptime; + nPreviousFrames = nFramesRendered; +} + +// define this function somewhere above RunMessageLoop() +void ToggleLayer(unsigned char thisLayer) +{ + nBurnLayer ^= thisLayer; // xor with thisLayer + VidRedraw(); + VidPaint(0); +} + +// With or without sound, run one frame. +// If bDraw is true, it's the last frame before we are up to date, and so we should draw the screen +static int RunFrame(int bDraw, int bPause) +{ + static int bPrevPause = 0; + static int bPrevDraw = 0; + + if (bPrevDraw && !bPause) { + VidPaint(0); // paint the screen (no need to validate) + } + + if (!bDrvOkay) { + return 1; + } + + if (bPause) { + GetInput(false); // Update burner inputs, but not game inputs + if (bPause != bPrevPause) { + VidPaint(2); // Redraw the screen (to ensure mode indicators are updated) + } + } else { + + nFramesEmulated++; + nCurrentFrame++; + + if (kNetGame) { + GetInput(true); // Update inputs + if (KailleraGetInput()) { // Synchronize input with Kaillera + return 0; + } + } else { + if (nReplayStatus == 2) { + GetInput(false); // Update burner inputs, but not game inputs + if (ReplayInput()) { // Read input from file + bAltPause = 1; + bRunPause = 1; + MenuEnableItems(); + InputSetCooperativeLevel(false, false); + } + } else { + GetInput(true); // Update inputs + } + } + + if (nReplayStatus == 1) { + RecordInput(); // Write input to file + } + + if (bDraw) { + nFramesRendered++; + + if (VidFrame()) { // Do one frame + AudBlankSound(); + } + } else { // frame skipping + pBurnDraw = NULL; // Make sure no image is drawn + BurnDrvFrame(); + } + + if (bShowFPS) { + if (nDoFPS < nFramesRendered) { + DisplayFPS(); + nDoFPS = nFramesRendered + 30; + } + } + } + + bPrevPause = bPause; + bPrevDraw = bDraw; + + return 0; +} + +// Callback used when DSound needs more sound +static int RunGetNextSound(int bDraw) +{ + if (nAudNextSound == NULL) { + return 1; + } + + if (bRunPause) { + if (bAppDoStep) { + RunFrame(bDraw, 0); + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + } else { + RunFrame(bDraw, 1); + } + + bAppDoStep = 0; // done one step + return 0; + } + + if (bAppDoFast) { // do more frames + for (int i = 0; i < nFastSpeed; i++) { + RunFrame(0, 0); + } + } + + // Render frame with sound + pBurnSoundOut = nAudNextSound; + RunFrame(bDraw, 0); + + if (WaveLog != NULL && pBurnSoundOut != NULL) { // log to the file + fwrite(pBurnSoundOut, 1, nBurnSoundLen << 2, WaveLog); + pBurnSoundOut = NULL; + } + + if (bAppDoStep) { + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + } + bAppDoStep = 0; // done one step + + return 0; +} + +extern bool bRunFrame; + +int RunIdle() +{ + int nTime, nCount; + + if (bAudPlaying) { + // Run with sound + + if(bRunFrame) { + bRunFrame = false; + if(bAlwaysDrawFrames) { + RunFrame(1, 0); + } else { + RunGetNextSound(0); + } + return 0; + } else { + AudSoundCheck(); + return 0; + } + } + + // Run without sound + nTime = timeGetTime() - nNormalLast; + nCount = (nTime * nAppVirtualFps - nNormalFrac) / 100000; + if (nCount <= 0) { // No need to do anything for a bit + //Sleep(2); + return 0; + } + + nNormalFrac += nCount * 100000; + nNormalLast += nNormalFrac / nAppVirtualFps; + nNormalFrac %= nAppVirtualFps; + + //if (bAppDoFast){ // Temporarily increase virtual fps + // nCount *= nFastSpeed; + //} + if (nCount > 100) { // Limit frame skipping + nCount = 100; + } + if (bRunPause) { + if (bAppDoStep) { // Step one frame + nCount = 10; + } else { + RunFrame(1, 1); // Paused + return 0; + } + } + bAppDoStep = 0; + + if (bAppDoFast) { // do more frames + for (int i = 0; i < nFastSpeed; i++) { + RunFrame(0, 0); + } + } + + if(!bAlwaysDrawFrames) { + for (int i = nCount / 10; i > 0; i--) { // Mid-frames + RunFrame(0, 0); + } + } + RunFrame(1, 0); // End-frame + + return 0; +} + +int RunReset() +{ + // Reset the speed throttling code + nNormalLast = 0; nNormalFrac = 0; + // Reset FPS display + nDoFPS = 0; + + if (!bAudPlaying) { + // run without sound + nNormalLast = timeGetTime(); + } + return 0; +} + +static int RunInit() +{ + // Try to run with sound + AudSetCallback(RunGetNextSound); + AudSoundPlay(); + + RunReset(); + + return 0; +} + +static int RunExit() +{ + nNormalLast = 0; + // Stop sound if it was playing + AudSoundStop(); + return 0; +} + +// The main message loop +int RunMessageLoop() +{ + int bRestartVideo; + MSG Msg; + + do { + bRestartVideo = 0; + + // Remove pending initialisation messages from the queue + while (PeekMessage(&Msg, NULL, WM_APP + 0, WM_APP + 0, PM_NOREMOVE)) { + if (Msg.message != WM_QUIT) { + PeekMessage(&Msg, NULL, WM_APP + 0, WM_APP + 0, PM_REMOVE); + } + } + + RunInit(); + + ShowWindow(hScrnWnd, nAppShowCmd); // Show the screen window + nAppShowCmd = SW_NORMAL; + + SetForegroundWindow(hScrnWnd); + + GameInpCheckLeftAlt(); + GameInpCheckMouse(); // Hide the cursor + + if(bVidDWMCore) { + DWM_StutterFix(); + } + + while (1) { + if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { + // A message is waiting to be processed + if (Msg.message == WM_QUIT) { // Quit program + break; + } + if (Msg.message == (WM_APP + 0)) { // Restart video + bRestartVideo = 1; + break; + } + + if (bMenuEnabled && nVidFullscreen == 0) { // Handle keyboard messages for the menu + if (MenuHandleKeyboard(&Msg)) { + continue; + } + } + + if (Msg.message == WM_SYSKEYDOWN || Msg.message == WM_KEYDOWN) { + if (Msg.lParam & 0x20000000) { + // An Alt/AltGr-key was pressed + switch (Msg.wParam) { + +#if defined (FBA_DEBUG) + case 'C': { + static int count = 0; + if (count == 0) { + count++; + { char* p = NULL; if (*p) { printf("crash...\n"); } } + } + break; + } +#endif + + // 'Silence' & 'Sound Restored' Code (added by CaptainCPS-X) + case 'S': { + TCHAR buffer[15]; + bMute = !bMute; + + if (bMute) { + nAudVolume = 0;// mute sound + _stprintf(buffer, FBALoadStringEx(hAppInst, IDS_SOUND_MUTE, true), nAudVolume / 100); + } else { + nAudVolume = nOldAudVolume;// restore volume + _stprintf(buffer, FBALoadStringEx(hAppInst, IDS_SOUND_MUTE_OFF, true), nAudVolume / 100); + } + if (AudSoundSetVolume() == 0) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_SOUND_NOVOLUME, true)); + } else { + VidSNewShortMsg(buffer); + } + break; + } + + case VK_OEM_PLUS: { + if (bMute) break; // if mute, not do this + nOldAudVolume = nAudVolume; + TCHAR buffer[15]; + + nAudVolume += 100; + if (GetAsyncKeyState(VK_CONTROL) & 0x80000000) { + nAudVolume += 900; + } + + if (nAudVolume > 10000) { + nAudVolume = 10000; + } + if (AudSoundSetVolume() == 0) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_SOUND_NOVOLUME, true)); + } else { + _stprintf(buffer, FBALoadStringEx(hAppInst, IDS_SOUND_VOLUMESET, true), nAudVolume / 100); + VidSNewShortMsg(buffer); + } + break; + } + case VK_OEM_MINUS: { + if (bMute) break; // if mute, not do this + nOldAudVolume = nAudVolume; + TCHAR buffer[15]; + + nAudVolume -= 100; + if (GetAsyncKeyState(VK_CONTROL) & 0x80000000) { + nAudVolume -= 900; + } + + if (nAudVolume < 0) { + nAudVolume = 0; + } + if (AudSoundSetVolume() == 0) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_SOUND_NOVOLUME, true)); + } else { + _stprintf(buffer, FBALoadStringEx(hAppInst, IDS_SOUND_VOLUMESET, true), nAudVolume / 100); + VidSNewShortMsg(buffer); + } + break; + } + case VK_MENU: { + continue; + } + } + } else { + switch (Msg.wParam) { + +#if defined (FBA_DEBUG) + case 'N': + counter--; + bprintf(PRINT_IMPORTANT, _T("*** New counter value: %04X.\n"), counter); + break; + case 'M': + counter++; + bprintf(PRINT_IMPORTANT, _T("*** New counter value: %04X.\n"), counter); + break; +#endif + case VK_ESCAPE: { + if (hwndChat) { + DeActivateChat(); + } else { + if (bCmdOptUsed) { + PostQuitMessage(0); + } else { + if (nVidFullscreen) { + nVidFullscreen = 0; + POST_INITIALISE_MESSAGE; + } + } + } + break; + } + case VK_RETURN: { + if (hwndChat) { + int i = 0; + while (EditText[i]) { + if (EditText[i++] != 0x20) { + break; + } + } + if (i) { + Kaillera_Chat_Send(TCHARToANSI(EditText, NULL, 0)); + //kailleraChatSend(TCHARToANSI(EditText, NULL, 0)); + } + DeActivateChat(); + + break; + } + if (GetAsyncKeyState(VK_CONTROL) & 0x80000000) { + bMenuEnabled = !bMenuEnabled; + POST_INITIALISE_MESSAGE; + + break; + } + + break; + } + case VK_F1: { + if (kNetGame) { + break; + } + + if (((GetAsyncKeyState(VK_CONTROL) | GetAsyncKeyState(VK_SHIFT)) & 0x80000000) == 0) { + if (bRunPause) { + bAppDoStep = 1; + } else { + bAppDoFast = 1; + } + } + break; + } + + case VK_BACK: { + bShowFPS = !bShowFPS; + if (bShowFPS) { + DisplayFPS(); + } else { + VidSKillShortMsg(); + VidSKillOSDMsg(); + } + break; + } + case 'T': { + if (kNetGame && hwndChat == NULL) { + if (AppMessage(&Msg)) { + ActivateChat(); + } + } + break; + } + } + } + } else { + if (Msg.message == WM_SYSKEYUP || Msg.message == WM_KEYUP) { + switch (Msg.wParam) { + case VK_MENU: + continue; + case VK_F1: + bAppDoFast = 0; + break; + } + } + } + + // Check for messages for dialogs etc. + if (AppMessage(&Msg)) { + if (TranslateAccelerator(hScrnWnd, hAccel, &Msg) == 0) { + if (hwndChat) { + TranslateMessage(&Msg); + } + DispatchMessage(&Msg); + } + } + } else { + + bRunPause ? wav_pause(false) : wav_pause(true); + + // No messages are waiting + SplashDestroy(0); + RunIdle(); + } + } + + RunExit(); + MediaExit(); + if (bRestartVideo) { + MediaInit(); + } + } while (bRestartVideo); + + return 0; +} + diff --git a/src/burner/win32/scrn.cpp b/src/burner/win32/scrn.cpp new file mode 100644 index 00000000..4713a8c5 --- /dev/null +++ b/src/burner/win32/scrn.cpp @@ -0,0 +1,2964 @@ +// Screen Window +#include "burner.h" +#include + +#define HORIZONTAL_ORIENTED_RES 0 +#define VERTICAL_ORIENTED_RES 1 + +int nActiveGame; + +static bool bLoading = 0; + +int OnMenuSelect(HWND, HMENU, int, HMENU, UINT); +int OnInitMenuPopup(HWND, HMENU, UINT, BOOL); +int OnUnInitMenuPopup(HWND, HMENU, UINT, BOOL); +void DisplayPopupMenu(int nMenu); + +RECT SystemWorkArea = { 0, 0, 640, 480 }; // Work area on the desktop +int nWindowPosX = -1, nWindowPosY = -1; // Window position + +int bAutoPause = 1; + +bool bMenuEnabled = true; + +int nSavestateSlot = 1; + +static TCHAR* szClass = _T("FB Alpha"); // Window class name +HWND hScrnWnd = NULL; // Handle to the screen window +HWND hRebar = NULL; // Handle to the Rebar control containing the menu + +static bool bMaximised; +static int nPrevWidth, nPrevHeight; + +#define ID_NETCHAT 999 +HWND hwndChat = NULL; +WNDPROC pOldWndProc = NULL; + +bool bRescanRoms = false; + +//static bool bDrag = false; +static int nDragX, nDragY; +//static int nOldWindowX, nOldWindowY; +//static int nLeftButtonX, nLeftButtonY; + +static int OnCreate(HWND, LPCREATESTRUCT); +static void OnActivateApp(HWND, BOOL, DWORD); +static void OnPaint(HWND); +static void OnClose(HWND); +static void OnDestroy(HWND); +static void OnCommand(HWND, int, HWND, UINT); +static int OnSysCommand(HWND, UINT, int, int); +static void OnSize(HWND, UINT, int, int); +static void OnEnterSizeMove(HWND); +static void OnExitSizeMove(HWND); +static void OnEnterIdle(HWND, UINT, HWND); +static void OnEnterMenuLoop(HWND, BOOL); +static void OnExitMenuLoop(HWND, BOOL); +//static int OnMouseMove(HWND, int, int, UINT); +//static int OnLButtonUp(HWND, int, int, UINT); +//static int OnLButtonDown(HWND, BOOL, int, int, UINT); +static int OnLButtonDblClk(HWND, BOOL, int, int, UINT); +static int OnRButtonUp(HWND, int, int, UINT); +static int OnRButtonDown(HWND, BOOL, int, int, UINT); + +static int OnDisplayChange(HWND, UINT, UINT, UINT); + +int OnNotify(HWND, int, NMHDR* lpnmhdr); + +static bool UseDialogs() +{ + if (/*!bDrvOkay ||*/ !nVidFullscreen) { + return true; + } + + return false; +} + +void SetPauseMode(bool bPause) +{ + bRunPause = bPause; + bAltPause = bPause; + + if (bPause) { + AudBlankSound(); + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + } + } else { + GameInpCheckMouse(); + } +} + +static char* CreateKailleraList() +{ + unsigned int nOldDrvSelect = nBurnDrvActive; + int nSize = 256 * 1024; + char* pList = (char*)malloc(nSize); + char* pName = pList; + + if (pList == NULL) { + return NULL; + } + + // Add chat option to the gamelist + pName += sprintf(pName, "* Chat only"); + pName++; + + if (avOk) { + // Add all the driver names to the list + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + + if(BurnDrvGetFlags() & BDF_GAME_WORKING && gameAv[nBurnDrvActive]) { + char* szDecoratedName = DecorateGameName(nBurnDrvActive); + + if (pName + strlen(szDecoratedName) >= pList + nSize) { + char* pNewList; + nSize <<= 1; + pNewList = (char*)realloc(pList, nSize); + if (pNewList == NULL) { + return NULL; + } + pName -= (INT_PTR)pList; + pList = pNewList; + pName += (INT_PTR)pList; + } + pName += sprintf(pName, "%s", szDecoratedName); + pName++; + } + } + } + + *pName = '\0'; + pName++; + + nBurnDrvActive = nOldDrvSelect; + + return pList; +} + +void DeActivateChat() +{ + bEditActive = false; + DestroyWindow(hwndChat); + hwndChat = NULL; +} + +int ActivateChat() +{ + RECT rect; + GetClientRect(hScrnWnd, &rect); + + DeActivateChat(); + + // Create an invisible edit control + hwndChat = CreateWindow( + _T("EDIT"), NULL, + WS_CHILD | ES_LEFT, + 0, rect.bottom - 32, rect.right, 32, + hScrnWnd, (HMENU)ID_NETCHAT, (HINSTANCE)GetWindowLongPtr(hScrnWnd, GWLP_HINSTANCE), NULL); // pointer not needed + + EditText[0] = 0; + bEditTextChanged = true; + bEditActive = true; + + SendMessage(hwndChat, EM_LIMITTEXT, MAX_CHAT_SIZE, 0); // Limit the amount of text + + SetFocus(hwndChat); + + return 0; +} + +static int WINAPI gameCallback(char* game, int player, int numplayers) +{ + bool bFound = false; + HWND hActive; + + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + + char* szDecoratedName = DecorateGameName(nBurnDrvActive); + + if (!strcmp(szDecoratedName, game)) { + bFound = true; + break; + } + } + + if (!bFound) { +// kailleraEndGame(); + Kaillera_End_Game(); + return 1; + } + + kNetGame = 1; + hActive = GetActiveWindow(); + + bCheatsAllowed = false; // Disable cheats during netplay + AudSoundStop(); // Stop while we load roms + DrvInit(nBurnDrvActive, false); // Init the game driver + ScrnInit(); + AudSoundPlay(); // Restart sound + VidInit(); + SetFocus(hScrnWnd); + +// dprintf(_T(" ** OSD startnet text sent.\n")); + + TCHAR szTemp1[256]; + TCHAR szTemp2[256]; + VidSAddChatMsg(FBALoadStringEx(hAppInst, IDS_NETPLAY_START, true), 0xFFFFFF, BurnDrvGetText(DRV_FULLNAME), 0xFFBFBF); + _sntprintf(szTemp1, 256, FBALoadStringEx(hAppInst, IDS_NETPLAY_START_YOU, true), player); + _sntprintf(szTemp2, 256, FBALoadStringEx(hAppInst, IDS_NETPLAY_START_TOTAL, true), numplayers); + VidSAddChatMsg(szTemp1, 0xFFFFFF, szTemp2, 0xFFBFBF); + + RunMessageLoop(); + + DrvExit(); + if (kNetGame) { + kNetGame = 0; +// kailleraEndGame(); + Kaillera_End_Game(); + } + DeActivateChat(); + + bCheatsAllowed = true; // reenable cheats netplay has ended + + SetFocus(hActive); + return 0; +} + +static void WINAPI kChatCallback(char* nick, char* text) +{ + TCHAR szTemp[128]; + _sntprintf(szTemp, 128, _T("%.32hs "), nick); + VidSAddChatMsg(szTemp, 0xBFBFFF, ANSIToTCHAR(text, NULL, 0), 0x7F7FFF); +} + +static void WINAPI kDropCallback(char *nick, int playernb) +{ + TCHAR szTemp[128]; + _sntprintf(szTemp, 128, FBALoadStringEx(hAppInst, IDS_NETPLAY_DROP, true), playernb, nick); + VidSAddChatMsg(szTemp, 0xFFFFFF, NULL, 0); +} + +static void DoNetGame() +{ + kailleraInfos ki; + char tmpver[128]; + char* gameList; + + if(bDrvOkay) { + DrvExit(); + ScrnTitle(); + } + MenuEnableItems(); + +#ifdef _UNICODE + _snprintf(tmpver, 128, APP_TITLE " v%.20ls", szAppBurnVer); +#else + _snprintf(tmpver, 128, APP_TITLE " v%.20s", szAppBurnVer); +#endif + + gameList = CreateKailleraList(); + + ki.appName = tmpver; + ki.gameList = gameList; + ki.gameCallback = &gameCallback; + ki.chatReceivedCallback = &kChatCallback; + ki.clientDroppedCallback = &kDropCallback; + ki.moreInfosCallback = NULL; + + Kaillera_Set_Infos(&ki); + //kailleraSetInfos(&ki); + + Kaillera_Select_Server_Dialog(NULL); + //kailleraSelectServerDialog(NULL); + + if (gameList) { + free(gameList); + gameList = NULL; + } + + End_Network(); + + POST_INITIALISE_MESSAGE; +} + +int CreateDatfileWindows(int bIncMegadrive) +{ + TCHAR szTitle[1024]; + TCHAR szFilter[1024]; + + TCHAR szMegadriveString[25]; + _sntprintf(szMegadriveString, 25, _T("")); + if (bIncMegadrive == 1) _sntprintf(szMegadriveString, 25, _T(", including Megadrive")); + if (bIncMegadrive == 2) _sntprintf(szMegadriveString, 25, _T(", Megadrive only")); + + TCHAR szProgramString[25]; + _sntprintf(szProgramString, 25, _T("ClrMame Pro XML")); + + _sntprintf(szChoice, MAX_PATH, _T(APP_TITLE) _T(" v%.20s (%s%s).dat"), szAppBurnVer, szProgramString, szMegadriveString); + _sntprintf(szTitle, 256, FBALoadStringEx(hAppInst, IDS_DAT_GENERATE, true), szProgramString); + + _stprintf(szFilter, FBALoadStringEx(hAppInst, IDS_DISK_ALL_DAT, true), _T(APP_TITLE)); + memcpy(szFilter + _tcslen(szFilter), _T(" (*.dat)\0*.dat\0\0"), 16 * sizeof(TCHAR)); + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T("."); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("dat"); + ofn.lpstrTitle = szTitle; + ofn.Flags |= OFN_OVERWRITEPROMPT; + + if (GetSaveFileName(&ofn) == 0) + return -1; + + return create_datfile(szChoice, bIncMegadrive); +} + +// Returns true if a VidInit is needed when the window is resized +static bool VidInitNeeded() +{ + // D3D blitter needs to re-initialise only when auto-size RGB effects are enabled + if (nVidSelect == 1 && (nVidBlitterOpt[nVidSelect] & 0x00030000) == 0x00030000) { + return true; + } + if (nVidSelect == 3) { + return true; + } + + return false; +} + +// Refresh the contents of the window when re-sizing it +static void RefreshWindow(bool bInitialise) +{ + if (nVidFullscreen) { + return; + } + + if (bInitialise && VidInitNeeded()) { + VidInit(); + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + VidPaint(0); + } + } +} + +static LRESULT CALLBACK ScrnProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch (Msg) { + HANDLE_MSG(hWnd, WM_CREATE, OnCreate); + HANDLE_MSG(hWnd, WM_ACTIVATEAPP, OnActivateApp); + HANDLE_MSGB(hWnd,WM_PAINT, OnPaint); + HANDLE_MSG(hWnd, WM_CLOSE, OnClose); + HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy); + HANDLE_MSG(hWnd, WM_COMMAND, OnCommand); + + // We can't use the macro from windowsx.h macro for this one + case WM_SYSCOMMAND: { + if (OnSysCommand(hWnd,(UINT)wParam,(int)(short)LOWORD(lParam),(int)(short)HIWORD(lParam))) { + return 0; + } + break; + } + + HANDLE_MSG(hWnd, WM_SIZE, OnSize); + HANDLE_MSG(hWnd, WM_ENTERSIZEMOVE, OnEnterSizeMove); + HANDLE_MSG(hWnd, WM_EXITSIZEMOVE, OnExitSizeMove); + HANDLE_MSG(hWnd, WM_ENTERIDLE, OnEnterIdle); + + //HANDLE_MSG(hWnd, WM_MOUSEMOVE, OnMouseMove); + //HANDLE_MSG(hWnd, WM_LBUTTONUP, OnLButtonUp); + //HANDLE_MSG(hWnd, WM_LBUTTONDOWN, OnLButtonDown); + + HANDLE_MSG(hWnd, WM_LBUTTONDBLCLK, OnLButtonDblClk); + + HANDLE_MSG(hWnd, WM_RBUTTONUP, OnRButtonUp); + HANDLE_MSG(hWnd, WM_RBUTTONDBLCLK, OnRButtonDown); + HANDLE_MSG(hWnd, WM_RBUTTONDOWN, OnRButtonDown); + + HANDLE_MSG(hWnd, WM_NOTIFY, OnNotify); + HANDLE_MSG(hWnd, WM_MENUSELECT, OnMenuSelect); + HANDLE_MSG(hWnd, WM_ENTERMENULOOP, OnEnterMenuLoop); + HANDLE_MSGB(hWnd,WM_EXITMENULOOP, OnExitMenuLoop); + HANDLE_MSGB(hWnd,WM_INITMENUPOPUP, OnInitMenuPopup); + HANDLE_MSG(hWnd, WM_UNINITMENUPOPUP,OnUnInitMenuPopup); + + HANDLE_MSG(hWnd, WM_DISPLAYCHANGE, OnDisplayChange); + } + + //return DefWindowProc(hWnd, Msg, wParam, lParam); + return nVidFullscreen ? DefWindowProc(hWnd, Msg, wParam, lParam) : DefFrameProc(hWnd, hWndChildFrame, Msg, wParam, lParam); +} + +static int OnDisplayChange(HWND, UINT, UINT, UINT) +{ + if (!nVidFullscreen) { + POST_INITIALISE_MESSAGE; + } + + return 0; +} + +/******************************************************************************/ +/* Fixed right click mouse events, now they work properly without interfering + with other applications in the background [CaptainCPS-X] */ +//----------------------------------------------------------------------------// +bool bRDblClick = false; + +static int OnRButtonDown(HWND hwnd, BOOL bDouble, int, int, UINT) +{ + if (hwnd != hScrnWnd && !nVidFullscreen) return 1; + + if (bDouble) { + // Right double-click at fullcreen happened, turn this flag 'true' so + // when right double-click ends (OnRButtonUp) it doesn't do anything else. + bRDblClick = true; + } + return 1; +} + +static int OnRButtonUp(HWND hwnd, int, int, UINT) +{ + // If fullscreen and right double-click + if (hwnd == hScrnWnd && nVidFullscreen && bRDblClick) + { + // game running + if (bDrvOkay) + { + // toggle fullscreen + nVidFullscreen = !nVidFullscreen; + bRDblClick = false; + POST_INITIALISE_MESSAGE; + return 0; + } + } + return 1; +} +/*************************************************************************/ + +/*static int OnMouseMove(HWND hwnd, int x, int y, UINT keyIndicators) +{ + //if(hwnd != hScrnWnd) { + // return 1; + //} + + if (bDrag && keyIndicators == MK_LBUTTON && !nVidFullscreen && !bMenuEnabled) { + RECT clientRect; + + GetWindowRect(hScrnWnd, &clientRect); + + if ((nLeftButtonX - (clientRect.left + x)) < nDragX && (nLeftButtonX - (clientRect.left + x)) > -nDragX && (nLeftButtonY - (clientRect.top + y)) < nDragY && (nLeftButtonY - (clientRect.top + y)) > -nDragY) { + SetWindowPos(hScrnWnd, NULL, nOldWindowX, nOldWindowY, 0, 0, SWP_NOREPOSITION | SWP_NOSIZE); + } else { + nWindowPosX = nOldWindowX - (nLeftButtonX - (clientRect.left + x)); + nWindowPosY = nOldWindowY - (nLeftButtonY - (clientRect.top + y)); + + SetWindowPos(hScrnWnd, NULL, nWindowPosX, nWindowPosY, 0, 0, SWP_NOREPOSITION | SWP_NOSIZE); + } + + return 0; + } + + return 1; +} + +static int OnLButtonDown(HWND hwnd, BOOL, int x, int y, UINT) +{ + //if(hwnd != hScrnWnd) { + // return 1; + //} + + if (!nVidFullscreen && !bMenuEnabled) { + RECT clientRect; + + GetWindowRect(hScrnWnd, &clientRect); + + nOldWindowX = clientRect.left; + nOldWindowY = clientRect.top; + + nLeftButtonX = clientRect.left + x; + nLeftButtonY = clientRect.top + y; + + bDrag = true; + + return 0; + } + + return 1; +} + +static int OnLButtonUp(HWND hwnd, int x, int y, UINT) +{ + //if (hwnd != hScrnWnd) { + // return 1; + //} + + bDrag = false; + + if (UseDialogs()) { + RECT clientRect; + GetWindowRect(hScrnWnd, &clientRect); + + TrackPopupMenuEx(hMenuPopup, TPM_LEFTALIGN | TPM_TOPALIGN, clientRect.left + x, clientRect.top + y, hScrnWnd, NULL); + return 0; + } + + if (!bMenuEnabled) { + RECT clientRect; + GetWindowRect(hScrnWnd, &clientRect); + + if ((nLeftButtonX - (clientRect.left + x)) < nDragX && (nLeftButtonX - (clientRect.left + x)) > -nDragX && (nLeftButtonY - (clientRect.top + y)) < nDragY && (nLeftButtonY - (clientRect.top + y)) > -nDragY) { + TrackPopupMenuEx(hMenuPopup, TPM_LEFTALIGN | TPM_TOPALIGN, clientRect.left + x, clientRect.top + y, hScrnWnd, NULL); + return 0; + } + } + + return 1; +}*/ + +static int OnLButtonDblClk(HWND hwnd, BOOL, int, int, UINT) +{ + if(nVidFullscreen) { + if (hwnd == hScrnWnd && bDrvOkay) { + nVidFullscreen = !nVidFullscreen; + POST_INITIALISE_MESSAGE; + return 0; + } + } + return 1; +} + +static int OnCreate(HWND hWnd, LPCREATESTRUCT /*lpCreateStruct*/) // HWND hwnd, LPCREATESTRUCT lpCreateStruct +{ + if(!nVidFullscreen) { + InitBurnerMDI(hWnd); + } + return 1; +} + +static void OnActivateApp(HWND hwnd, BOOL fActivate, DWORD /* dwThreadId */) +{ + if (!kNetGame && bAutoPause && !bAltPause && hInpdDlg == NULL && hInpCheatDlg == NULL && hInpDIPSWDlg == NULL) { + bRunPause = fActivate? 0 : 1; + } + if (fActivate == false && hwnd == hScrnWnd) { + EndMenu(); + } + if (fActivate == false && bRunPause) { + AudBlankSound(); + } + + if (fActivate) { + if (hInpdDlg || hInpCheatDlg || hInpDIPSWDlg || hDbgDlg) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + } else { + GameInpCheckMouse(); + } + } +} + +static void OnPaint(HWND hWnd) +{ + if (hWnd == hScrnWnd) + { + VidPaint(1); + + // draw menu + if (!nVidFullscreen) { + RedrawWindow(hRebar, NULL, NULL, RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + } + } +} + +static void OnClose(HWND) +{ + PostQuitMessage(0); // Quit the program if the window is closed +} + +static void OnDestroy(HWND) +{ + VidExit(); // Stop using video with the Window + hScrnWnd = NULL; // Make sure handle is not used again + + DestroyBurnerMDI(0); +} + +OPENFILENAME bgFn; +TCHAR szFile[MAX_PATH]; + +static void UpdatePreviousGameList() +{ + int nRecentIdenticalTo = -1; + + // check if this game is identical to any of the listed in the recent menu + for(int x = 0; x < SHOW_PREV_GAMES; x++) { + if(!_tcscmp(BurnDrvGetText(DRV_NAME), szPrevGames[x])) { + nRecentIdenticalTo = x; + } + } + + // Declare temporary array + TCHAR szTmp[SHOW_PREV_GAMES][32]; + + // Backup info for later use + for(int x = 0; x < SHOW_PREV_GAMES; x++) { + _tcscpy(szTmp[x], szPrevGames[x]); + } + + switch(nRecentIdenticalTo) + { + case -1: + // Normal rotation when recent game is not identical to any of the ones listed + // - - - + _tcscpy(szPrevGames[9], szPrevGames[8]); // Recent 10 = 9 + _tcscpy(szPrevGames[8], szPrevGames[7]); // Recent 9 = 8 + _tcscpy(szPrevGames[7], szPrevGames[6]); // Recent 8 = 7 + _tcscpy(szPrevGames[6], szPrevGames[5]); // Recent 7 = 6 + _tcscpy(szPrevGames[5], szPrevGames[4]); // Recent 6 = 5 + _tcscpy(szPrevGames[4], szPrevGames[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[3], szPrevGames[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[2], szPrevGames[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[1], szPrevGames[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[0], BurnDrvGetText(DRV_NAME)); // Update most recent game played (Recent 1) + break; + case 0: + break; // Nothing Change + case 1: + _tcscpy(szPrevGames[0], szTmp[1]); // Update most recent game played (Recent 1 = 2) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + break; + case 2: + _tcscpy(szPrevGames[0], szTmp[2]); // Update most recent game played (Recent 1 = 3) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + break; + case 3: + _tcscpy(szPrevGames[0], szTmp[3]); // Update most recent game played (Recent 1 = 4) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + break; + case 4: + _tcscpy(szPrevGames[0], szTmp[4]); // Update most recent game played (Recent 1 = 5) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + break; + case 5: + _tcscpy(szPrevGames[0], szTmp[5]); // Update most recent game played (Recent 1 = 6) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[5], szTmp[4]); // Recent 6 = 5 + break; + case 6: + _tcscpy(szPrevGames[0], szTmp[6]); // Update most recent game played (Recent 1 = 7) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[5], szTmp[4]); // Recent 6 = 5 + _tcscpy(szPrevGames[6], szTmp[5]); // Recent 7 = 6 + break; + case 7: + _tcscpy(szPrevGames[0], szTmp[7]); // Update most recent game played (Recent 1 = 8) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[5], szTmp[4]); // Recent 6 = 5 + _tcscpy(szPrevGames[6], szTmp[5]); // Recent 7 = 6 + _tcscpy(szPrevGames[7], szTmp[6]); // Recent 8 = 7 + break; + case 8: + _tcscpy(szPrevGames[0], szTmp[8]); // Update most recent game played (Recent 1 = 9) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[5], szTmp[4]); // Recent 6 = 5 + _tcscpy(szPrevGames[6], szTmp[5]); // Recent 7 = 6 + _tcscpy(szPrevGames[7], szTmp[6]); // Recent 8 = 7 + _tcscpy(szPrevGames[8], szTmp[7]); // Recent 9 = 8 + break; + case 9: + _tcscpy(szPrevGames[0], szTmp[9]); // Update most recent game played (Recent 1 = 10) + _tcscpy(szPrevGames[1], szTmp[0]); // Recent 2 = 1 + _tcscpy(szPrevGames[2], szTmp[1]); // Recent 3 = 2 + _tcscpy(szPrevGames[3], szTmp[2]); // Recent 4 = 3 + _tcscpy(szPrevGames[4], szTmp[3]); // Recent 5 = 4 + _tcscpy(szPrevGames[5], szTmp[4]); // Recent 6 = 5 + _tcscpy(szPrevGames[6], szTmp[5]); // Recent 7 = 6 + _tcscpy(szPrevGames[7], szTmp[6]); // Recent 8 = 7 + _tcscpy(szPrevGames[8], szTmp[7]); // Recent 9 = 8 + _tcscpy(szPrevGames[9], szTmp[8]); // Recent 10 = 9 + break; + } +} + +// Compact driver loading module +int BurnerLoadDriver(TCHAR *szDriverName) +{ + unsigned int j; + + int nOldDrvSelect = nBurnDrvActive; + DrvExit(); + bLoading = 1; + + for (j = 0; j < nBurnDrvCount; j++) { + nBurnDrvActive = j; + if (!_tcscmp(szDriverName, BurnDrvGetText(DRV_NAME)) && (!(BurnDrvGetFlags() & BDF_BOARDROM))) { + nBurnDrvActive = nOldDrvSelect; + nDialogSelect = j; + SplashDestroy(1); + StopReplay(); + + DrvExit(); + DrvInit(j, true); // Init the game driver + MenuEnableItems(); + bAltPause = 0; + AudSoundPlay(); // Restart sound + bLoading = 0; + UpdatePreviousGameList(); + if (bVidAutoSwitchFull) { + nVidFullscreen = 1; + POST_INITIALISE_MESSAGE; + } + break; + } + } + + return 0; +} + + +static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify) +{ + //if(id >= ID_MDI_START_CHILD) { + // DefFrameProc(hwndCtl, hWndChildFrame, WM_COMMAND, wParam, lParam); + // return; + //} else { + // HWND hWndCurrent = (HWND)SendMessage(hWndChildFrame, WM_MDIGETACTIVE,0,0); + // if(hWndCurrent) { + // SendMessage(hWndCurrent, WM_COMMAND, wParam, lParam); + // return; + // } + //} + + if (bLoading) { + return; + } + + switch (id) { + case MENU_LOAD: { + int nGame; + + if(kNetGame || !UseDialogs() || bLoading) { + break; + } + + SplashDestroy(1); + StopReplay(); + + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + + bLoading = 1; + AudSoundStop(); // Stop while the dialog is active or we're loading ROMs + + nGame = SelDialog(0, hScrnWnd); // Bring up select dialog to pick a driver + + extern bool bDialogCancel; + + if (nGame >= 0 && bDialogCancel == false) { + DrvExit(); + DrvInit(nGame, true); // Init the game driver + MenuEnableItems(); + bAltPause = 0; + AudSoundPlay(); // Restart sound + bLoading = 0; + UpdatePreviousGameList(); + if (bVidAutoSwitchFull) { + nVidFullscreen = 1; + POST_INITIALISE_MESSAGE; + } + + POST_INITIALISE_MESSAGE; + break; + } else { + GameInpCheckMouse(); + AudSoundPlay(); // Restart sound + bLoading = 0; + break; + } + } + + case MENU_PREVIOUSGAMES1: + case MENU_PREVIOUSGAMES2: + case MENU_PREVIOUSGAMES3: + case MENU_PREVIOUSGAMES4: + case MENU_PREVIOUSGAMES5: + case MENU_PREVIOUSGAMES6: + case MENU_PREVIOUSGAMES7: + case MENU_PREVIOUSGAMES8: + case MENU_PREVIOUSGAMES9: + case MENU_PREVIOUSGAMES10: { + BurnerLoadDriver(szPrevGames[id - MENU_PREVIOUSGAMES1]); + break; + } + + case MENU_START_NEOGEO_MVS: { + BurnerLoadDriver(_T("neogeo")); + break; + } + + case MENU_START_NEOGEO_CD: { + BurnerLoadDriver(_T("neocdz")); + break; + } + + case MENU_LOAD_NEOCD: { + AudBlankSound(); + if (UseDialogs()) { + NeoCDList_Init(); + } + break; + } + + case MENU_CDIMAGE: + nCDEmuSelect = 0; + if (UseDialogs() && !bDrvOkay) { + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFile = CDEmuImage; + ofn.nMaxFile = sizeof(CDEmuImage); + ofn.lpstrTitle = _T("Select CD Image"); + ofn.lpstrFilter = _T("CD images (*.iso,*.cue)\0*.iso;*.cue\0\0)"); + ofn.lpstrInitialDir = _T("."); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("iso"); + + GetOpenFileName(&ofn); + } + break; + + case MENU_STARTNET: + if (Init_Network()) { + MessageBox(hScrnWnd, FBALoadStringEx(hAppInst, IDS_ERR_NO_NETPLAYDLL, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK); + break; + } + if (!kNetGame) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + SplashDestroy(1); + StopReplay(); + DrvExit(); + DoNetGame(); + MenuEnableItems(); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + } + break; + + case MENU_STARTREPLAY: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudSoundStop(); + SplashDestroy(1); + StopReplay(); + StartReplay(); + GameInpCheckMouse(); + AudSoundPlay(); + } + break; + case MENU_STARTRECORD: + if (UseDialogs() && nReplayStatus != 1) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + StopReplay(); + StartRecord(); + GameInpCheckMouse(); + } + break; + case MENU_STOPREPLAY: + StopReplay(); + break; + + case MENU_QUIT: + AudBlankSound(); + if (nVidFullscreen) { + nVidFullscreen = 0; + VidExit(); + } + if (bDrvOkay) { + StopReplay(); + DrvExit(); + if (kNetGame) { + kNetGame = 0; +// kailleraEndGame(); + Kaillera_End_Game(); + DeActivateChat(); + PostQuitMessage(0); + } + bCheatsAllowed = true; // reenable cheats netplay has ended + + ScrnSize(); + ScrnTitle(); + MenuEnableItems(); + nDialogSelect = -1; + nBurnDrvActive = ~0U; + + POST_INITIALISE_MESSAGE; + } + break; + + case MENU_EXIT: + StopReplay(); + if (kNetGame) { + kNetGame = 0; +// kailleraEndGame(); + Kaillera_End_Game(); + DeActivateChat(); + } + PostQuitMessage(0); + return; + + case MENU_PAUSE: + if (bDrvOkay && !kNetGame) { + SetPauseMode(!bRunPause); + } else { + SetPauseMode(0); + } + break; + + case MENU_INPUT: + AudBlankSound(); + if (UseDialogs()) { + InputSetCooperativeLevel(false, false); + InpdCreate(); + } + break; + + case MENU_DIPSW: + AudBlankSound(); + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + InpDIPSWCreate(); + } + break; + + case MENU_SETCPUCLOCK: + AudBlankSound(); + CPUClockDialog(); + MenuEnableItems(); + GameInpCheckMouse(); + break; + case MENU_RESETCPUCLOCK: + nBurnCPUSpeedAdjust = 0x0100; + MenuEnableItems(); + break; + + case MENU_MEMCARD_CREATE: + if (bDrvOkay && UseDialogs() && !kNetGame && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + MemCardEject(); + MemCardCreate(); + MemCardInsert(); + GameInpCheckMouse(); + } + break; + case MENU_MEMCARD_SELECT: + if (bDrvOkay && UseDialogs() && !kNetGame && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + MemCardEject(); + MemCardSelect(); + MemCardInsert(); + GameInpCheckMouse(); + } + break; + case MENU_MEMCARD_INSERT: + if (!kNetGame && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + MemCardInsert(); + } + break; + case MENU_MEMCARD_EJECT: + if (!kNetGame && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + MemCardEject(); + } + break; + + case MENU_MEMCARD_TOGGLE: + if (bDrvOkay && !kNetGame && (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) == HARDWARE_SNK_NEOGEO) { + MemCardToggle(); + } + break; + + case MENU_STATE_LOAD_DIALOG: + if (UseDialogs() && !kNetGame) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudSoundStop(); + SplashDestroy(1); + StatedLoad(0); + GameInpCheckMouse(); + AudSoundPlay(); + } + break; + case MENU_STATE_SAVE_DIALOG: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + StatedSave(0); + GameInpCheckMouse(); + } + return; + case MENU_STATE_PREVSLOT: { + TCHAR szString[256]; + + nSavestateSlot--; + if (nSavestateSlot < 1) { + nSavestateSlot = 1; + } + _sntprintf(szString, 256, FBALoadStringEx(hAppInst, IDS_STATE_ACTIVESLOT, true), nSavestateSlot); + VidSNewShortMsg(szString); + break; + } + case MENU_STATE_NEXTSLOT: { + TCHAR szString[256]; + + nSavestateSlot++; + if (nSavestateSlot > 8) { + nSavestateSlot = 8; + } + _sntprintf(szString, 256, FBALoadStringEx(hAppInst, IDS_STATE_ACTIVESLOT, true), nSavestateSlot); + VidSNewShortMsg(szString); + break; + } + case MENU_STATE_LOAD_SLOT: + if (bDrvOkay && !kNetGame) { + if (StatedLoad(nSavestateSlot) == 0) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_STATE_LOADED, true)); + } else { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_STATE_LOAD_ERROR, true), 0xFF3F3F); + } + } + break; + case MENU_STATE_SAVE_SLOT: + if (bDrvOkay) { + if (StatedSave(nSavestateSlot) == 0) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_STATE_SAVED, true)); + } else { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_STATE_SAVE_ERROR, true), 0xFF3F3F); + SetPauseMode(1); + } + } + break; + + case MENU_ALLRAM: + bDrvSaveAll = !bDrvSaveAll; + break; + + case MENU_NOSTRETCH: + bVidCorrectAspect = 0; + bVidFullStretch = 0; + POST_INITIALISE_MESSAGE; + break; + + case MENU_STRETCH: + bVidFullStretch = true; + if (bVidFullStretch) { + bVidCorrectAspect = 0; + } + POST_INITIALISE_MESSAGE; + break; + + case MENU_ASPECT: + bVidCorrectAspect = true; + if (bVidCorrectAspect) { + bVidFullStretch = 0; + } + POST_INITIALISE_MESSAGE; + break; + + case MENU_TRIPLE: + bVidTripleBuffer = !bVidTripleBuffer; + POST_INITIALISE_MESSAGE; + break; + + case MENU_DWMFIX: + bVidDWMCore = !bVidDWMCore; + POST_INITIALISE_MESSAGE; + break; + + case MENU_BLITTER_1: + VidSelect(0); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_2: + VidSelect(1); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_3: + VidSelect(2); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_4: + VidSelect(3); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_5: + VidSelect(4); + POST_INITIALISE_MESSAGE; + break; +#if 0 + case MENU_BLITTER_6: + VidSelect(5); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_7: + VidSelect(6); + POST_INITIALISE_MESSAGE; + break; + case MENU_BLITTER_8: + VidSelect(7); + POST_INITIALISE_MESSAGE; + break; +#endif + + case MENU_RES_ARCADE: + bVidArcaderesHor = !bVidArcaderesHor; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + break; + + case MENU_SINGLESIZESCREEN: + nScreenSizeHor = 1; + bVidArcaderesHor = false; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + break; + case MENU_DOUBLESIZESCREEN: + nScreenSizeHor = 2; + bVidArcaderesHor = false; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + break; + case MENU_TRIPLESIZESCREEN: + nScreenSizeHor = 3; + bVidArcaderesHor = false; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + break; + case MENU_QUADSIZESCREEN: + nScreenSizeHor = 4; + bVidArcaderesHor = false; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + break; + + case MENU_RES_1: + nVidHorWidth = VidPreset[0].nWidth; + nVidHorHeight = VidPreset[0].nHeight; + bVidArcaderesHor = false; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + break; + case MENU_RES_2: + nVidHorWidth = VidPreset[1].nWidth; + nVidHorHeight = VidPreset[1].nHeight; + bVidArcaderesHor = false; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + break; + case MENU_RES_3: + nVidHorWidth = VidPreset[2].nWidth; + nVidHorHeight = VidPreset[2].nHeight; + bVidArcaderesHor = false; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + break; + case MENU_RES_4: + nVidHorWidth = VidPreset[3].nWidth; + nVidHorHeight = VidPreset[3].nHeight; + bVidArcaderesHor = false; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + nVidWidth = nVidHorWidth; + nVidHeight = nVidHorHeight; + } + break; + + + case MENU_RES_OTHER: + bVidArcaderesHor = false; + nScreenSizeHor = 0; + if ((bDrvOkay) && !(BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeHor; + bVidArcaderes = bVidArcaderesHor; + } + AudBlankSound(); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + ResCreate(HORIZONTAL_ORIENTED_RES); + GameInpCheckMouse(); + break; + + // Vertical + case MENU_RES_ARCADE_VERTICAL: + bVidArcaderesVer = !bVidArcaderesVer; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + break; + + case MENU_SINGLESIZESCREEN_VERTICAL: + nScreenSizeVer = 1; + bVidArcaderesVer = false; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + break; + case MENU_DOUBLESIZESCREEN_VERTICAL: + nScreenSizeVer = 2; + bVidArcaderesVer = false; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + break; + case MENU_TRIPLESIZESCREEN_VERTICAL: + nScreenSizeVer = 3; + bVidArcaderesVer = false; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + break; + case MENU_QUADSIZESCREEN_VERTICAL: + nScreenSizeVer = 4; + bVidArcaderesVer = false; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + break; + + case MENU_RES_1_VERTICAL: + nVidVerWidth = VidPresetVer[0].nWidth; + nVidVerHeight = VidPresetVer[0].nHeight; + bVidArcaderesVer = false; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } + break; + case MENU_RES_2_VERTICAL: + nVidVerWidth = VidPresetVer[1].nWidth; + nVidVerHeight = VidPresetVer[1].nHeight; + bVidArcaderesVer = false; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } + break; + case MENU_RES_3_VERTICAL: + nVidVerWidth = VidPresetVer[2].nWidth; + nVidVerHeight = VidPresetVer[2].nHeight; + bVidArcaderesVer = false; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } + break; + case MENU_RES_4_VERTICAL: + nVidVerWidth = VidPresetVer[3].nWidth; + nVidVerHeight = VidPresetVer[3].nHeight; + bVidArcaderesVer = false; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + nVidWidth = nVidVerWidth; + nVidHeight = nVidVerHeight; + } + break; + + case MENU_RES_OTHER_VERTICAL: + bVidArcaderesVer = false; + nScreenSizeVer = 0; + if ((bDrvOkay) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nScreenSize = nScreenSizeVer; + bVidArcaderes = bVidArcaderesVer; + } + AudBlankSound(); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + ResCreate(VERTICAL_ORIENTED_RES); + GameInpCheckMouse(); + break; + + case MENU_16: + nVidDepth = 16; + break; + + case MENU_24: + nVidDepth = 24; + break; + + case MENU_32: + nVidDepth = 32; + break; + + case MENU_GAMMA_DO: + bDoGamma = !bDoGamma; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + if (bRunPause) { + VidRedraw(); + } + } + break; + + case MENU_GAMMA_DARKER: + nGamma = 1.25; + ComputeGammaLUT(); + bDoGamma = 1; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + if (bRunPause) { + VidRedraw(); + } + } + break; + + case MENU_GAMMA_LIGHTER: + nGamma = 0.80; + ComputeGammaLUT(); + bDoGamma = 1; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + if (bRunPause) { + VidRedraw(); + } + } + break; + + case MENU_GAMMA_OTHER: { + if (UseDialogs()) { + double nOldGamma = nGamma; + bDoGamma = 1; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + } + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + GammaDialog(); + if (nGamma > 0.999 && nGamma < 1.001) { + nGamma = nOldGamma; + bDoGamma = 0; + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + } else { + bDoGamma = 1; + ComputeGammaLUT(); + } + if (bDrvOkay) { + VidRecalcPal(); + } + GameInpCheckMouse(); + } + break; + } + + case MENU_GAMMA_USE_HARDWARE: + bVidUseHardwareGamma = 1; + bHardwareGammaOnly = 0; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + VidRecalcPal(); + if (bRunPause) { + VidRedraw(); + } + } + break; + case MENU_GAMMA_HARDWARE_ONLY: + bVidUseHardwareGamma = 1; + bHardwareGammaOnly = 1; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + VidRecalcPal(); + if (bRunPause) { + VidRedraw(); + } + } + break; + case MENU_GAMMA_SOFTWARE_ONLY: + bVidUseHardwareGamma = 0; + bHardwareGammaOnly = 0; + if (bDrvOkay) { + if (nVidSelect == 1) { + VidInit(); + } + SetBurnHighCol(nVidImageDepth); + VidRecalcPal(); + if (bRunPause) { + VidRedraw(); + } + } + break; + + case MENU_FULL: + if (bDrvOkay || nVidFullscreen) { + nVidFullscreen = !nVidFullscreen; + POST_INITIALISE_MESSAGE; + } + return; + + case MENU_AUTOSWITCHFULL: + bVidAutoSwitchFull = !bVidAutoSwitchFull; + break; + + case MENU_MEMAUTO: + nVidTransferMethod = -1; + POST_INITIALISE_MESSAGE; + break; + + case MENU_VIDEOMEM: + nVidTransferMethod = 0; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SYSMEM: + nVidTransferMethod = 1; + POST_INITIALISE_MESSAGE; + break; + + case MENU_AUTOSIZE: + if (nWindowSize != 0) { + nWindowSize = 0; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_SINGLESIZEWINDOW: + if (nWindowSize != 1) { + nWindowSize = 1; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_DOUBLESIZEWINDOW: + if (nWindowSize != 2) { + nWindowSize = 2; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_TRIPLESIZEWINDOW: + if (nWindowSize != 3) { + nWindowSize = 3; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_QUADSIZEWINDOW: + if (nWindowSize != 4) { + nWindowSize = 4; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_MAXIMUMSIZEWINDOW: + if (nWindowSize <= 4) { + nWindowSize = 9999; + POST_INITIALISE_MESSAGE; + } + break; + + case MENU_MONITORAUTOCHECK: + bMonitorAutoCheck = !bMonitorAutoCheck; + if (bMonitorAutoCheck) MonitorAutoCheck(); + POST_INITIALISE_MESSAGE; + break; + + case MENU_ASPECTNORMAL: + bMonitorAutoCheck = false; nVidScrnAspectX = 4; nVidScrnAspectY = 3; + POST_INITIALISE_MESSAGE; + break; + case MENU_ASPECTLCD: + bMonitorAutoCheck = false; nVidScrnAspectX = 5; nVidScrnAspectY = 4; + POST_INITIALISE_MESSAGE; + break; + case MENU_ASPECTWIDE: + bMonitorAutoCheck = false; nVidScrnAspectX = 16; nVidScrnAspectY = 9; + POST_INITIALISE_MESSAGE; + break; + case MENU_ASPECTWIDELCD: + bMonitorAutoCheck = false; nVidScrnAspectX = 16; nVidScrnAspectY = 10; + POST_INITIALISE_MESSAGE; + break; + case MENU_MONITORMIRRORVERT: + nVidRotationAdjust ^= 2; + POST_INITIALISE_MESSAGE; + break; + + case MENU_ROTATEVERTICAL: + nVidRotationAdjust ^= 1; + POST_INITIALISE_MESSAGE; + break; + + case MENU_FORCE60HZ: + bForce60Hz = !bForce60Hz; + break; + + case MENU_VIDEOVSYNC: + bVidVSync = !bVidVSync; + POST_INITIALISE_MESSAGE; + break; + + case MENU_AUTOFRAMESKIP: + bAlwaysDrawFrames = !bAlwaysDrawFrames; + POST_INITIALISE_MESSAGE; + break; + + case MENU_AUD_PLUGIN_1: + AudSelect(0); + POST_INITIALISE_MESSAGE; + break; + + case MENU_AUD_PLUGIN_2: + AudSelect(1); + POST_INITIALISE_MESSAGE; + break; + + case MENU_DSOUND_NOSOUND: + if (!bDrvOkay) { + nAudSampleRate[0] = 0; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_DSOUND_11025: + if (!bDrvOkay) { + nAudSampleRate[0] = 11025; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_DSOUND_22050: + if (!bDrvOkay) { + nAudSampleRate[0] = 22050; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_DSOUND_44100: + if (!bDrvOkay) { + nAudSampleRate[0] = 44100; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_DSOUND_48000: + if (!bDrvOkay) { + nAudSampleRate[0] = 48000; + POST_INITIALISE_MESSAGE; + } + break; + + case MENU_XAUDIO_NOSOUND: + if (!bDrvOkay) { + nAudSampleRate[1] = 0; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_XAUDIO_11025: + if (!bDrvOkay) { + nAudSampleRate[1] = 11025; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_XAUDIO_22050: + if (!bDrvOkay) { + nAudSampleRate[1] = 22050; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_XAUDIO_44100: + if (!bDrvOkay) { + nAudSampleRate[1] = 44100; + POST_INITIALISE_MESSAGE; + } + break; + case MENU_XAUDIO_48000: + if (!bDrvOkay) { + nAudSampleRate[1] = 48000; + POST_INITIALISE_MESSAGE; + } + break; + + case MENU_FRAMES: + if (UseDialogs()) { + if (!bDrvOkay) { +// AudBlankSound(); + NumDialCreate(0); + POST_INITIALISE_MESSAGE; + } + } + break; + + case MENU_INTERPOLATE_0: + nInterpolation = 0; + break; + case MENU_INTERPOLATE_1: + nInterpolation = 1; + break; + case MENU_INTERPOLATE_3: + nInterpolation = 3; + break; + + case MENU_INTERPOLATE_FM_0: + nFMInterpolation = 0; + break; + case MENU_INTERPOLATE_FM_1: + nFMInterpolation = 1; + break; + case MENU_INTERPOLATE_FM_3: + nFMInterpolation = 3; + break; + + case MENU_DSOUND_BASS: + nAudDSPModule[0] = !nAudDSPModule[0]; + break; + + case MENU_XAUDIO_BASS: + nAudDSPModule[1] ^= 1; + break; + + case MENU_XAUDIO_REVERB: + nAudDSPModule[1] ^= 2; + break; + + case MENU_WLOGSTART: + AudBlankSound(); + WaveLogStart(); + break; + + case MENU_WLOGEND: + AudBlankSound(); + WaveLogStop(); + break; + + case MENU_AUTOPAUSE: + bAutoPause = !bAutoPause; + break; + + case MENU_PROCESSINPUT: + bAlwaysProcessKeyboardInput = !bAlwaysProcessKeyboardInput; + break; + + case MENU_DISPLAYINDICATOR: + nVidSDisplayStatus = !nVidSDisplayStatus; +// VidRedraw(); + VidPaint(2); + break; + + case MENU_MODELESS: + bModelessMenu = !bModelessMenu; + POST_INITIALISE_MESSAGE; + break; + + case MENU_NOCHANGENUMLOCK: + bNoChangeNumLock = !bNoChangeNumLock; + break; + + case MENU_SAVEHISCORES: + EnableHiscores = !EnableHiscores; + break; + + case MENU_ROMDIRS: + RomsDirCreate(hScrnWnd); + break; + + case MENU_SUPPORTDIRS: + SupportDirCreate(hScrnWnd); + break; + + case MENU_LANGUAGE_SELECT: + if (UseDialogs()) { + FBALocaliseLoadTemplate(); + POST_INITIALISE_MESSAGE; + } + break; + case MENU_LANGUAGE_EXPORT: + if (UseDialogs()) { + FBALocaliseCreateTemplate(); + } + break; + case MENU_LANGUAGE_RESET: + szLocalisationTemplate[0] = _T('\0'); + FBALocaliseInit(szLocalisationTemplate); + POST_INITIALISE_MESSAGE; + break; + + case MENU_PRIORITY_REALTIME: + nAppThreadPriority = THREAD_PRIORITY_TIME_CRITICAL; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + case MENU_PRIORITY_HIGH: + nAppThreadPriority = THREAD_PRIORITY_HIGHEST; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + case MENU_PRIORITY_ABOVE_NORMAL: + nAppThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + case MENU_PRIORITY_NORMAL: + nAppThreadPriority = THREAD_PRIORITY_NORMAL; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + case MENU_PRIORITY_BELOW_NORMAL: + nAppThreadPriority = THREAD_PRIORITY_BELOW_NORMAL; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + case MENU_PRIORITY_LOW: + nAppThreadPriority = THREAD_PRIORITY_LOWEST; + SetThreadPriority(GetCurrentThread(), nAppThreadPriority); + break; + + case MENU_CLRMAME_PRO_XML: + if (UseDialogs()) { + CreateDatfileWindows(0); + } + break; + + case MENU_CLRMAME_PRO_XML_MD_ONLY: + if (UseDialogs()) { + CreateDatfileWindows(2); + } + break; + + case MENU_ENABLECHEAT: + AudBlankSound(); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + InpCheatCreate(); + break; + + case MENU_DEBUG: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + DebugCreate(); + } + break; + + case MENU_PALETTEVIEWER: { + AudBlankSound(); + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + PaletteViewerDialogCreate(hScrnWnd); + break; + } + + case MENU_ASSEMBLYCORE: + bBurnUseASMCPUEmulation = !bBurnUseASMCPUEmulation; + break; + + case MENU_SAVESNAP: { + if (bDrvOkay) { + int status = MakeScreenShot(); + + if (!status) { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_SSHOT_SAVED, true)); + } else { + TCHAR tmpmsg[256]; + + _sntprintf(tmpmsg, 256, FBALoadStringEx(hAppInst, IDS_SSHOT_ERROR, true), status); + VidSNewShortMsg(tmpmsg, 0xFF3F3F); + } + } + break; + } + + case MENU_SNAPFACT: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + SFactdCreate(); + } + break; + + case MENU_CHEATSEARCH_START: { + CheatSearchStart(); + VidSAddChatMsg(NULL, 0xFFFFFF, _T("New cheat search started"), 0xFFBFBF); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_NOCHANGE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_CHANGE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_DECREASE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_INCREASE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_DUMPFILE, MF_ENABLED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_EXIT, MF_ENABLED | MF_BYCOMMAND); + break; + } + + case MENU_CHEATSEARCH_NOCHANGE: { + TCHAR tmpmsg[256]; + unsigned int nValues = CheatSearchValueNoChange(); + + _sntprintf(tmpmsg, 256, _T("%i Addresses Matched"), nValues); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + + if (nValues <= CHEATSEARCH_SHOWRESULTS) { + for (unsigned int i = 0; i < nValues; i++) { + _sntprintf(tmpmsg, 256, _T("Address %08X Value %02X"), CheatSearchShowResultAddresses[i], CheatSearchShowResultValues[i]); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + } + } + break; + } + + case MENU_CHEATSEARCH_CHANGE: { + TCHAR tmpmsg[256]; + unsigned int nValues = CheatSearchValueChange(); + + _sntprintf(tmpmsg, 256, _T("%i Addresses Matched"), nValues); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + + if (nValues <= CHEATSEARCH_SHOWRESULTS) { + for (unsigned int i = 0; i < nValues; i++) { + _sntprintf(tmpmsg, 256, _T("Address %08X Value %02X"), CheatSearchShowResultAddresses[i], CheatSearchShowResultValues[i]); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + } + } + break; + } + + case MENU_CHEATSEARCH_DECREASE: { + TCHAR tmpmsg[256]; + unsigned int nValues = CheatSearchValueDecreased(); + + _sntprintf(tmpmsg, 256, _T("%i Addresses Matched"), nValues); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + + if (nValues <= CHEATSEARCH_SHOWRESULTS) { + for (unsigned int i = 0; i < nValues; i++) { + _sntprintf(tmpmsg, 256, _T("Address %08X Value %02X"), CheatSearchShowResultAddresses[i], CheatSearchShowResultValues[i]); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + } + } + break; + } + + case MENU_CHEATSEARCH_INCREASE: { + TCHAR tmpmsg[256]; + + unsigned int nValues = CheatSearchValueIncreased(); + + _sntprintf(tmpmsg, 256, _T("%i Addresses Matched"), nValues); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + + if (nValues <= CHEATSEARCH_SHOWRESULTS) { + for (unsigned int i = 0; i < nValues; i++) { + _sntprintf(tmpmsg, 256, _T("Address %08X Value %02X"), CheatSearchShowResultAddresses[i], CheatSearchShowResultValues[i]); + VidSAddChatMsg(NULL, 0xFFFFFF, tmpmsg, 0xFFBFBF); + } + } + break; + } + + case MENU_CHEATSEARCH_DUMPFILE: { + CheatSearchDumptoFile(); + break; + } + + case MENU_CHEATSEARCH_EXIT: { + CheatSearchExit(); + VidSAddChatMsg(NULL, 0xFFFFFF, _T("Cheat search exited"), 0xFFBFBF); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_NOCHANGE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_CHANGE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_DECREASE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_INCREASE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_DUMPFILE, MF_GRAYED | MF_BYCOMMAND); + EnableMenuItem(hMenu, MENU_CHEATSEARCH_EXIT, MF_GRAYED | MF_BYCOMMAND); + break; + } + + case MENU_ASSOCIATE: + RegisterExtensions(true); + break; + case MENU_DISASSOCIATE: + RegisterExtensions(false); + break; + + case MENU_SAVEGAMEINPUTNOW: + ConfigGameSave(true); + break; + + case MENU_SAVEGAMEINPUT: + bSaveInputs = !bSaveInputs; + break; + + case MENU_SAVESET: + ConfigAppSave(); + break; + + case MENU_LOADSET: + ConfigAppLoad(); + POST_INITIALISE_MESSAGE; + break; + + case MENU_ABOUT: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + AboutCreate(); + GameInpCheckMouse(); + } + break; + case MENU_SYSINFO: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + SystemInfoCreate(); + GameInpCheckMouse(); + } + break; + + case MENU_CONTENTS: { + if (!nVidFullscreen) { + FILE* fp = _tfopen(_T("fba.chm"), _T("r")); + if (fp) { + fclose(fp); + ShellExecute(NULL, _T("open"), _T("fba.chm"), NULL, NULL, SW_SHOWNORMAL); + } + } + break; + } + + case MENU_WHATSNEW: { + if (!nVidFullscreen) { + FILE* fp = _tfopen(_T("whatsnew.html"), _T("r")); + if (fp) { + fclose(fp); + ShellExecute(NULL, _T("open"), _T("whatsnew.html"), NULL, NULL, SW_SHOWNORMAL); + } + } + break; + } + + case MENU_WWW_HOME: + if (!nVidFullscreen) { + ShellExecute(NULL, _T("open"), _T("http://www.barryharris.me.uk/"), NULL, NULL, SW_SHOWNORMAL); + } + break; + + case MENU_WWW_FORUM: + if (!nVidFullscreen) { + ShellExecute(NULL, _T("open"), _T("http://www.ojko.com/phpbb/viewforum.php?f=27"), NULL, NULL, SW_SHOWNORMAL); + } + break; + + case MENU_WWW_NSFORUM: + if (!nVidFullscreen) { + ShellExecute(NULL, _T("open"), _T("http://neosource.1emu.net/forums/"), NULL, NULL, SW_SHOWNORMAL); + } + break; + +// default: +// printf(" * Command %i sent.\n"); + + } + + switch (nVidSelect) { + case 0: { + switch (id) { + // Options for the Default DirectDraw blitter + case MENU_NORMAL: + bVidScanlines = 0; + POST_INITIALISE_MESSAGE; + break; + case MENU_SCAN: + bVidScanlines = 1; + bVidScanHalf = 0; + POST_INITIALISE_MESSAGE; + break; + case MENU_SCAN50: + bVidScanlines = 1; + bVidScanHalf = 1; + POST_INITIALISE_MESSAGE; + break; + + case MENU_ROTSCAN: + bVidScanRotate = !bVidScanRotate; + POST_INITIALISE_MESSAGE; + break; + } + break; + } + case 1: { + switch (id) { + // Options for the Direct3D blitter + case MENU_DISABLEFX: + bVidBilinear = 0; + bVidScanlines = 0; + nVidBlitterOpt[nVidSelect] &= 0xF40200FF; + POST_INITIALISE_MESSAGE; + break; + + case MENU_BILINEAR: + bVidBilinear = !bVidBilinear; + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + + case MENU_PHOSPHOR: + bVidScanDelay = !bVidScanDelay; + break; + + case MENU_NORMAL: + nVidBlitterOpt[nVidSelect] &= ~0x00110000; + POST_INITIALISE_MESSAGE; + break; + case MENU_SCAN: + bVidScanlines = !bVidScanlines; + nVidBlitterOpt[nVidSelect] &= ~0x00010000; + POST_INITIALISE_MESSAGE; + break; + case MENU_RGBEFFECTS: + nVidBlitterOpt[nVidSelect] &= ~0x00100000; + nVidBlitterOpt[nVidSelect] |= 0x00010000; + bVidScanlines = 0; + ScrnSize(); + VidInit(); + if (bVidScanlines) { + ScrnSize(); + VidInit(); + } + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + case MENU_3DPROJECTION: + nVidBlitterOpt[nVidSelect] &= ~0x00010000; + nVidBlitterOpt[nVidSelect] |= 0x00100000; + POST_INITIALISE_MESSAGE; + break; + + case MENU_EFFECT_AUTO: + nVidBlitterOpt[nVidSelect] &= ~0x001000000; + nVidBlitterOpt[nVidSelect] |= 0x00030000; + POST_INITIALISE_MESSAGE; + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + case MENU_EFFECT_01: + case MENU_EFFECT_02: + case MENU_EFFECT_03: + case MENU_EFFECT_04: + case MENU_EFFECT_05: + case MENU_EFFECT_06: + case MENU_EFFECT_07: + case MENU_EFFECT_08: + case MENU_EFFECT_09: + case MENU_EFFECT_0A: + case MENU_EFFECT_0B: + case MENU_EFFECT_0C: + case MENU_EFFECT_0D: + case MENU_EFFECT_0E: + case MENU_EFFECT_0F: + case MENU_EFFECT_10: + nVidBlitterOpt[nVidSelect] &= ~0x001300FF; + nVidBlitterOpt[nVidSelect] |= 0x00010008 + id - MENU_EFFECT_01; + POST_INITIALISE_MESSAGE; + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + + case MENU_ROTSCAN: + bVidScanRotate = !bVidScanRotate; + POST_INITIALISE_MESSAGE; + break; + + case MENU_PRESCALE: + nVidBlitterOpt[nVidSelect] ^= 0x01000000; + POST_INITIALISE_MESSAGE; + break; + case MENU_SOFTFX: + nVidBlitterOpt[nVidSelect] ^= 0x02000000; + nVidBlitterOpt[nVidSelect] |= 0x01000000; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SOFT_STRETCH: + case MENU_SOFT_SCALE2X: + case MENU_SOFT_SCALE3X: + case MENU_SOFT_2XPM_LQ: + case MENU_SOFT_2XPM_HQ: + case MENU_SOFT_EAGLE: + case MENU_SOFT_SUPEREAGLE: + case MENU_SOFT_2XSAI: + case MENU_SOFT_SUPER2XSAI: + case MENU_SOFT_SUPEREAGLE_VBA: + case MENU_SOFT_2XSAI_VBA: + case MENU_SOFT_SUPER2XSAI_VBA: + case MENU_SOFT_SUPERSCALE: + case MENU_SOFT_SUPERSCALE75: + case MENU_SOFT_HQ2X: + case MENU_SOFT_HQ3X: + case MENU_SOFT_HQ4X: + case MENU_SOFT_HQ2XS_VBA: + case MENU_SOFT_HQ3XS_VBA: + case MENU_SOFT_HQ2XS_SNES9X: + case MENU_SOFT_HQ3XS_SNES9X: + case MENU_SOFT_HQ2XBOLD: + case MENU_SOFT_HQ3XBOLD: + case MENU_SOFT_EPXB: + case MENU_SOFT_EPXC: { + nVidBlitterOpt[nVidSelect] &= 0x0FFFFFFF; + nVidBlitterOpt[nVidSelect] |= 0x03000000 + ((long long)(id - MENU_SOFT_STRETCH) << 32); + POST_INITIALISE_MESSAGE; + break; + } + case MENU_SOFT_AUTOSIZE: + nVidBlitterOpt[nVidSelect] ^= 0x04000000; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SCANINTENSITY: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + if (!bVidScanlines) { + bVidScanlines = 1; + ScrnSize(); + VidInit(); + VidRedraw(); + } + if (nVidBlitterOpt[nVidSelect] & 0x00010000) { + nVidBlitterOpt[nVidSelect] &= ~0x00010000; + ScrnSize(); + VidInit(); + VidRedraw(); + } + ScanlineDialog(); + GameInpCheckMouse(); + } + break; + + case MENU_PHOSPHORINTENSITY: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + PhosphorDialog(); + bVidScanDelay = 1; + } + break; + + case MENU_3DSCREENANGLE: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + if ((nVidBlitterOpt[nVidSelect] & 0x00100000) == 0) { + nVidBlitterOpt[nVidSelect] &= ~0x00010000; + nVidBlitterOpt[nVidSelect] |= 0x00100000; + ScrnSize(); + VidInit(); + VidRedraw(); + } + ScreenAngleDialog(); + if (!bRunPause) { + GameInpCheckMouse(); + } + } + break; + + case MENU_FORCE_16BIT: + bVidForce16bit = !bVidForce16bit; + VidInit(); + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + case MENU_TEXTUREMANAGE: + if (nVidTransferMethod != 0) { + nVidTransferMethod = 0; + } else { + nVidTransferMethod = 1; + } + VidInit(); + if (bVidOkay && (bRunPause || !bDrvOkay)) { + VidRedraw(); + } + break; + } + break; + } + case 2: { + switch (id) { + // Options for the DirectDraw Software Effects blitter + case MENU_SOFT_STRETCH: + case MENU_SOFT_SCALE2X: + case MENU_SOFT_SCALE3X: + case MENU_SOFT_2XPM_LQ: + case MENU_SOFT_2XPM_HQ: + case MENU_SOFT_EAGLE: + case MENU_SOFT_SUPEREAGLE: + case MENU_SOFT_2XSAI: + case MENU_SOFT_SUPER2XSAI: + case MENU_SOFT_SUPEREAGLE_VBA: + case MENU_SOFT_2XSAI_VBA: + case MENU_SOFT_SUPER2XSAI_VBA: + case MENU_SOFT_SUPERSCALE: + case MENU_SOFT_SUPERSCALE75: + case MENU_SOFT_HQ2X: + case MENU_SOFT_HQ3X: + case MENU_SOFT_HQ4X: + case MENU_SOFT_HQ2XS_VBA: + case MENU_SOFT_HQ3XS_VBA: + case MENU_SOFT_HQ2XS_SNES9X: + case MENU_SOFT_HQ3XS_SNES9X: + case MENU_SOFT_HQ2XBOLD: + case MENU_SOFT_HQ3XBOLD: + case MENU_SOFT_EPXB: + case MENU_SOFT_EPXC: + nVidBlitterOpt[nVidSelect] &= ~0xFF; + nVidBlitterOpt[nVidSelect] |= id - MENU_SOFT_STRETCH; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SOFT_AUTOSIZE: + nVidBlitterOpt[nVidSelect] ^= 0x0100; + POST_INITIALISE_MESSAGE; + break; + case MENU_SOFT_DIRECTACCESS: + nVidBlitterOpt[nVidSelect] ^= 0x0200; + POST_INITIALISE_MESSAGE; + break; + } + break; + } + case 3: + switch (id) { + // Options for the DirectX Graphics 9 blitter + case MENU_DX9_POINT: + nVidBlitterOpt[nVidSelect] &= ~(3 << 24); + nVidBlitterOpt[nVidSelect] |= (0 << 24); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_LINEAR: + nVidBlitterOpt[nVidSelect] &= ~(3 << 24); + nVidBlitterOpt[nVidSelect] |= (1 << 24); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_CUBIC: + nVidBlitterOpt[nVidSelect] &= ~(3 << 24); + nVidBlitterOpt[nVidSelect] |= (2 << 24); + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_CUBIC_LIGHT: + dVidCubicB = 0.0; + dVidCubicC = 0.0; + VidRedraw(); + break; + case MENU_DX9_CUBIC_BSPLINE: + dVidCubicB = 1.0; + dVidCubicC = 0.0; + VidRedraw(); + break; + case MENU_DX9_CUBIC_NOTCH: + dVidCubicB = 3.0 / 2.0; + dVidCubicC = -0.25; + VidRedraw(); + break; + case MENU_DX9_CUBIC_OPTIMAL: + dVidCubicB = 1.0 / 3.0; + dVidCubicC = 1.0 / 3.0; + VidRedraw(); + break; + case MENU_DX9_CUBIC_CATMULL: + dVidCubicB = 0.0; + dVidCubicC = 0.5; + VidRedraw(); + break; + case MENU_DX9_CUBIC_SHARP: + dVidCubicB = 0.0; + dVidCubicC = 1.0; + VidRedraw(); + break; + +/* + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + if ((nVidBlitterOpt[nVidSelect] & (3 << 24)) != (2 << 24)) { + nVidBlitterOpt[nVidSelect] &= ~(3 << 24); + nVidBlitterOpt[nVidSelect] |= (2 << 24); + ScrnSize(); + VidInit(); + VidRedraw(); + } + CubicSharpnessDialog(); + GameInpCheckMouse(); + } + break; +*/ + + case MENU_SCAN: + bVidScanlines = !bVidScanlines; + POST_INITIALISE_MESSAGE; + break; + case MENU_SCANINTENSITY: + if (UseDialogs()) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + if (!bVidScanlines) { + bVidScanlines = 1; + ScrnSize(); + VidInit(); + VidRedraw(); + } + ScanlineDialog(); + GameInpCheckMouse(); + } + break; + + case MENU_DX9_FPTERXTURES: + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_FORCE_PS14: + nVidBlitterOpt[nVidSelect] ^= (1 << 9); + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_CUBIC0: + nVidBlitterOpt[nVidSelect] &= ~(7 << 28); + nVidBlitterOpt[nVidSelect] |= (0 << 28); + + nVidBlitterOpt[nVidSelect] |= (1 << 8); + nVidBlitterOpt[nVidSelect] |= (1 << 9); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_CUBIC1: + nVidBlitterOpt[nVidSelect] &= ~(7 << 28); + nVidBlitterOpt[nVidSelect] |= (1 << 28); + + nVidBlitterOpt[nVidSelect] |= (1 << 8); + nVidBlitterOpt[nVidSelect] |= (1 << 9); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_CUBIC2: + nVidBlitterOpt[nVidSelect] &= ~(7 << 28); + nVidBlitterOpt[nVidSelect] |= (2 << 28); + + nVidBlitterOpt[nVidSelect] |= (1 << 8); + nVidBlitterOpt[nVidSelect] |= (1 << 9); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_CUBIC3: + nVidBlitterOpt[nVidSelect] &= ~(7 << 28); + nVidBlitterOpt[nVidSelect] |= (3 << 28); + + nVidBlitterOpt[nVidSelect] |= (1 << 8); + nVidBlitterOpt[nVidSelect] |= (1 << 9); + POST_INITIALISE_MESSAGE; + break; + case MENU_DX9_CUBIC4: + nVidBlitterOpt[nVidSelect] &= ~(7 << 28); + nVidBlitterOpt[nVidSelect] |= (4 << 28); + + nVidBlitterOpt[nVidSelect] &= ~(1 << 8); + nVidBlitterOpt[nVidSelect] &= ~(1 << 9); + POST_INITIALISE_MESSAGE; + break; + + } + break; + case 4: + switch (id) { + // Options for the DirectX Graphics 9 Alternate blitter + case MENU_DX9_ALT_POINT: + bVidDX9Bilinear = 0; + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_ALT_LINEAR: + bVidDX9Bilinear = 1; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SOFT_STRETCH: + case MENU_SOFT_SCALE2X: + case MENU_SOFT_SCALE3X: + case MENU_SOFT_2XPM_LQ: + case MENU_SOFT_2XPM_HQ: + case MENU_SOFT_EAGLE: + case MENU_SOFT_SUPEREAGLE: + case MENU_SOFT_2XSAI: + case MENU_SOFT_SUPER2XSAI: + case MENU_SOFT_SUPEREAGLE_VBA: + case MENU_SOFT_2XSAI_VBA: + case MENU_SOFT_SUPER2XSAI_VBA: + case MENU_SOFT_SUPERSCALE: + case MENU_SOFT_SUPERSCALE75: + case MENU_SOFT_HQ2X: + case MENU_SOFT_HQ3X: + case MENU_SOFT_HQ4X: + case MENU_SOFT_HQ2XS_VBA: + case MENU_SOFT_HQ3XS_VBA: + case MENU_SOFT_HQ2XS_SNES9X: + case MENU_SOFT_HQ3XS_SNES9X: + case MENU_SOFT_HQ2XBOLD: + case MENU_SOFT_HQ3XBOLD: + case MENU_SOFT_EPXB: + case MENU_SOFT_EPXC: + nVidBlitterOpt[nVidSelect] &= ~0xFF; + nVidBlitterOpt[nVidSelect] |= id - MENU_SOFT_STRETCH; + POST_INITIALISE_MESSAGE; + break; + + case MENU_SOFT_AUTOSIZE: + nVidBlitterOpt[nVidSelect] ^= 0x0100; + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_ALT_HARDWAREVERTEX: + bVidHardwareVertex = !bVidHardwareVertex; + POST_INITIALISE_MESSAGE; + break; + + case MENU_DX9_ALT_MOTIONBLUR: + bVidMotionBlur = !bVidMotionBlur; + POST_INITIALISE_MESSAGE; + break; + } + break; + } + + if (hwndChat) { + switch (codeNotify) { + case EN_CHANGE: { + bEditTextChanged = true; + SendMessage(hwndChat, WM_GETTEXT, (WPARAM)MAX_CHAT_SIZE + 1, (LPARAM)EditText); + break; + } + case EN_KILLFOCUS: { + SetFocus(hwndChat); + break; + } + case EN_MAXTEXT: { + VidSNewShortMsg(FBALoadStringEx(hAppInst, IDS_NETPLAY_TOOMUCH, true), 0xFF3F3F); + break; + } + } + } + + MenuUpdate(); +} + +// Block screensaver and windows menu if needed +static int OnSysCommand(HWND, UINT sysCommand, int, int) +{ + switch (sysCommand) { + case SC_MONITORPOWER: + case SC_SCREENSAVE: { + if (!bRunPause && bDrvOkay) { + return 1; + } + break; + } + case SC_KEYMENU: + case SC_MOUSEMENU: { + if (kNetGame && !bModelessMenu) { + return 1; + } + break; + } + } + + return 0; +} + +static void OnSize(HWND, UINT state, int cx, int cy) +{ + if (state == SIZE_MINIMIZED) { + bMaximised = false; + } else { + bool bSizeChanged = false; + + MoveWindow(hRebar, 0, 0, cx, nMenuHeight, TRUE); + + SetWindowPos(hWndChildFrame, NULL, 0, nMenuHeight, cx, bMenuEnabled ? (cy-nMenuHeight) : cy, SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOZORDER); + + //MoveWindow(hWndChildFrame, 0, nMenuHeight, cx, bMenuEnabled ? (cy-nMenuHeight) : cy, TRUE ); + + if (hwndChat) { + MoveWindow(hwndChat, 0, cy - 32, cx, 32, FALSE); + } + + if (state == SIZE_MAXIMIZED) { + if (!bMaximised) { + bSizeChanged = true; + } + bMaximised = true; + } + if (state == SIZE_RESTORED) { + if (bMaximised) { + bSizeChanged = true; + } + bMaximised = false; + } + + if (bSizeChanged) { + RefreshWindow(true); + } else { + RefreshWindow(false); + } + } +} + +static void OnEnterSizeMove(HWND) +{ + RECT rect; + + AudBlankSound(); + + GetClientRect(hScrnWnd, &rect); + nPrevWidth = rect.right; + nPrevHeight = rect.bottom; +} + +static void OnExitSizeMove(HWND) +{ + RECT rect; + + GetClientRect(hScrnWnd, &rect); + if (rect.right != nPrevWidth || rect.bottom != nPrevHeight) { + RefreshWindow(true); + } + + GetWindowRect(hScrnWnd, &rect); + nWindowPosX = rect.left; + nWindowPosY = rect.top; +} + +static void OnEnterIdle(HWND /*hwnd*/, UINT /*source*/, HWND /*hwndSource*/) +{ + MSG Message; + + // Modeless dialog is idle + while (kNetGame && !PeekMessage(&Message, NULL, 0, 0, PM_NOREMOVE)) { + RunIdle(); + } +} + +static void OnEnterMenuLoop(HWND, BOOL) +{ + if (!bModelessMenu) { + InputSetCooperativeLevel(false, bAlwaysProcessKeyboardInput); + AudBlankSound(); + } else { + if (!kNetGame && bAutoPause) { + bRunPause = 1; + } + } +} + +static void OnExitMenuLoop(HWND, BOOL) +{ + if (!bModelessMenu) { + GameInpCheckMouse(); + } +} + +static int ScrnRegister() +{ + WNDCLASSEX WndClassEx; + ATOM Atom = 0; + + // Register the window class + memset(&WndClassEx, 0, sizeof(WndClassEx)); // Init structure to all zeros + WndClassEx.cbSize = sizeof(WndClassEx); + WndClassEx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_CLASSDC;// These cause flicker in the toolbar + WndClassEx.lpfnWndProc = ScrnProc; + WndClassEx.hInstance = hAppInst; + WndClassEx.hIcon = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP)); + WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW); + WndClassEx.hbrBackground = CreateSolidBrush(0); + WndClassEx.lpszClassName = szClass; + + // Register the window class with the above information: + Atom = RegisterClassEx(&WndClassEx); + if (Atom) { + return 0; + } else { + return 1; + } +} + +int ScrnSize() +{ + int x, y, w, h, ew, eh; + int nScrnWidth, nScrnHeight; + int nBmapWidth = nVidImageWidth, nBmapHeight = nVidImageHeight; + int nGameAspectX = 4, nGameAspectY = 3; + int nMaxSize; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &SystemWorkArea, 0); // Find the size of the visible WorkArea + + if (hScrnWnd == NULL || nVidFullscreen) { + return 1; + } + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) && (nVidRotationAdjust & 1)) { + BurnDrvGetVisibleSize(&nBmapHeight, &nBmapWidth); + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetVisibleSize(&nBmapWidth, &nBmapHeight); + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + + if (nBmapWidth <= 0 || nBmapHeight <= 0) { + return 1; + } + } + + nDragX = GetSystemMetrics(SM_CXDRAG) / 2; + nDragY = GetSystemMetrics(SM_CYDRAG) / 2; + + nScrnWidth = SystemWorkArea.right - SystemWorkArea.left; + nScrnHeight = SystemWorkArea.bottom - SystemWorkArea.top; + + if (nVidSelect == 2 && nVidBlitterOpt[2] & 0x0100) { // The Software effects blitter uses a fixed size + nMaxSize = 9; + } else { + if (nWindowSize) { + nMaxSize = nWindowSize; + } else { + if (nBmapWidth < nBmapHeight) { + if (SystemWorkArea.bottom - SystemWorkArea.top <= 600) { + nMaxSize = 1; + } else { + if (SystemWorkArea.bottom - SystemWorkArea.top <= 960) { + nMaxSize = 2; + } else { + if (SystemWorkArea.bottom - SystemWorkArea.top <= 1280) { + nMaxSize = 3; + } else { + nMaxSize = 4; + } + } + } + } else { + if (SystemWorkArea.right - SystemWorkArea.left <= 640) { + nMaxSize = 1; + } else { + if (SystemWorkArea.right - SystemWorkArea.left <= 1152) { + nMaxSize = 2; + } else { + if (SystemWorkArea.right - SystemWorkArea.left <= 1600) { + nMaxSize = 3; + } else { + nMaxSize = 4; + } + } + } + } + } + } + + // Find the width and height + w = nScrnWidth; + h = nScrnHeight; + + // Find out how much space is taken up by the borders + ew = GetSystemMetrics(SM_CXSIZEFRAME) << 1; + eh = GetSystemMetrics(SM_CYSIZEFRAME) << 1; + + if (bMenuEnabled) { + eh += GetSystemMetrics(SM_CYCAPTION); + eh += nMenuHeight; + } else { + eh += 1 << 1; + ew += 1 << 1; + } + + if (bMenuEnabled || !bVidScanlines || nVidSelect == 2) { + // Subtract the border space + w -= ew; + h -= eh; + } + + if ((bVidCorrectAspect || bVidFullStretch) && !(nVidSelect == 2 && (nVidBlitterOpt[2] & 0x0100) == 0)) { + int ww = w; + int hh = h; + + do { + if (nBmapWidth < nBmapHeight && bVidScanRotate) { + if (ww > nBmapWidth * nMaxSize) { + ww = nBmapWidth * nMaxSize; + } + if (hh > ww * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX)) { + hh = ww * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX); + } + } else { + if (hh > nBmapHeight * nMaxSize) { + hh = nBmapHeight * nMaxSize; + } + if (ww > hh * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY)) { + ww = hh * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY); + } + } + } while ((ww > w || hh > h) && nMaxSize-- > 1); + w = ww; + h = hh; + } else { + while ((nBmapWidth * nMaxSize > w || nBmapHeight * nMaxSize > h) && nMaxSize > 1) { + nMaxSize--; + } + + if (w > nBmapWidth * nMaxSize || h > nBmapHeight * nMaxSize) { + w = nBmapWidth * nMaxSize; + h = nBmapHeight * nMaxSize; + } + } + + if (!bDrvOkay) { + if (w < 304) w = 304; + if (h < 224) h = 224; + } + + RECT rect = { 0, 0, w, h }; + VidImageSize(&rect, nBmapWidth, nBmapHeight); + w = rect.right - rect.left + ew; + h = rect.bottom - rect.top + eh; + + x = nWindowPosX; y = nWindowPosY; + if (x + w > SystemWorkArea.right || y + h > SystemWorkArea.bottom) { + // Find the midpoint for the window + x = SystemWorkArea.left + SystemWorkArea.right; + x /= 2; + y = SystemWorkArea.bottom + SystemWorkArea.top; + y /= 2; + + x -= w / 2; + y -= h / 2; + } + + MenuUpdate(); + + bMaximised = false; + + MoveWindow(hScrnWnd, x, y, w, h, true); + +// SetWindowPos(hScrnWnd, NULL, x, y, w, h, SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOZORDER); + + nWindowPosX = x; nWindowPosY = y; + + return 0; +} + +#include "neocdlist.h" + +int ScrnTitle() +{ + TCHAR szText[1024] = _T(""); + + // Create window title + if (bDrvOkay) { + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(DRV_FULLNAME); + + pszPosition += _sntprintf(szText, 1024, _T(APP_TITLE) _T( " v%.20s") _T(SEPERATOR_1) _T("%s"), szAppBurnVer, pszName); + while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + + if(NeoCDInfo_Init()) { + return 0; + } + + } else { + _stprintf(szText, _T(APP_TITLE) _T( " v%.20s") _T(SEPERATOR_1) _T("[%s]"), szAppBurnVer, FBALoadStringEx(hAppInst, IDS_SCRN_NOGAME, true)); + } + + SetWindowText(hScrnWnd, szText); + return 0; +} + + +// Init the screen window (create it) +int ScrnInit() +{ + REBARINFO rebarInfo; + REBARBANDINFO rebarBandInfo; + RECT rect; + int nWindowStyles, nWindowExStyles; + + ScrnExit(); + + if (ScrnRegister() != 0) { + return 1; + } + + if (nVidFullscreen) { + nWindowStyles = WS_POPUP; + nWindowExStyles = 0; + } else { + if (bMenuEnabled) { + nWindowStyles = WS_OVERLAPPEDWINDOW; + nWindowExStyles = 0; + } else { + nWindowStyles = WS_MINIMIZEBOX | WS_POPUP | WS_SYSMENU | WS_THICKFRAME; + nWindowExStyles = WS_EX_CLIENTEDGE; + } + } + + RegNewMDIChild(); + + hScrnWnd = CreateWindowEx(nWindowExStyles, szClass, _T(APP_TITLE), nWindowStyles, + 0, 0, 0, 0, // size of window + NULL, NULL, hAppInst, NULL); + + if (hScrnWnd == NULL) { + ScrnExit(); + return 1; + } + + nMenuHeight = 0; + if (!nVidFullscreen) { + + // Create the menu toolbar itself + MenuCreate(); + + // Create the toolbar + if (bMenuEnabled) { + // Create the Rebar control that will contain the menu toolbar + hRebar = CreateWindowEx(WS_EX_TOOLWINDOW, + REBARCLASSNAME, NULL, + RBS_BANDBORDERS | CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, + 0, 0, 0, 0, + hScrnWnd, NULL, hAppInst, NULL); + + rebarInfo.cbSize = sizeof(REBARINFO); + rebarInfo.fMask = 0; + rebarInfo.himl = NULL; + + SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&rebarInfo); + + // Add the menu toolbar to the rebar + GetWindowRect(hMenubar, &rect); + + rebarBandInfo.cbSize = sizeof(REBARBANDINFO); + rebarBandInfo.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;// | RBBIM_BACKGROUND; + rebarBandInfo.fStyle = RBBS_GRIPPERALWAYS;// | RBBS_FIXEDBMP; + rebarBandInfo.hwndChild = hMenubar; + rebarBandInfo.cxMinChild = 100; + rebarBandInfo.cyMinChild = ((SendMessage(hMenubar, TB_GETBUTTONSIZE, 0, 0)) >> 16) + 1; + rebarBandInfo.cx = rect.right - rect.left; + + SendMessage(hRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rebarBandInfo); + + GetWindowRect(hRebar, &rect); + nMenuHeight = rect.bottom - rect.top; + + } + + ScrnTitle(); + ScrnSize(); + } + + return 0; +} + +// Exit the screen window (destroy it) +int ScrnExit() +{ + // Ensure the window is destroyed + DeActivateChat(); + + DestroyBurnerMDI(1); + + if (hRebar) { + DestroyWindow(hRebar); + hRebar = NULL; + } + + if (hScrnWnd) { + DestroyWindow(hScrnWnd); + hScrnWnd = NULL; + } + + UnregisterClass(szClass, hAppInst); // Unregister the scrn class + + MenuDestroy(); + + return 0; +} + +void Reinitialise() +{ + POST_INITIALISE_MESSAGE; + VidReInitialise(); +} diff --git a/src/burner/win32/sel.cpp b/src/burner/win32/sel.cpp new file mode 100644 index 00000000..6e6083ef --- /dev/null +++ b/src/burner/win32/sel.cpp @@ -0,0 +1,2256 @@ +// Driver Selector module +// TreeView Version by HyperYagami +#include "burner.h" + +UINT_PTR nTimer = 0; +UINT_PTR nInitPreviewTimer = 0; +int nDialogSelect = -1; // The driver which this dialog selected +int nOldDlgSelected = -1; +bool bDialogCancel = false; + +bool bDrvSelected = false; + +static int nShowMVSCartsOnly = 0; + +HBITMAP hPrevBmp = NULL; +static HBITMAP hPreview = NULL; + +HWND hSelDlg = NULL; +static HWND hSelList = NULL; +static HWND hParent = NULL; +static HWND hInfoLabel[6] = { NULL, NULL, NULL, NULL, NULL }; // 4 things in our Info-box +static HWND hInfoText[6] = { NULL, NULL, NULL, NULL, NULL }; // 4 things in our Info-box + +static HBRUSH hWhiteBGBrush; +static HICON hExpand, hCollapse; +static HICON hNotWorking, hNotFoundEss, hNotFoundNonEss; + +static HICON hDrvIconMiss; + +static char TreeBuilding = 0; // if 1, ignore TVN_SELCHANGED messages + +static int bImageOrientation; +static int UpdatePreview(bool bReset, TCHAR *szPath, int HorCtrl, int VerCrtl); + +static int RomInfoDialog(); + +// Filter TreeView +HWND hFilterList = NULL; +HTREEITEM hFilterCave = NULL; +HTREEITEM hFilterCps1 = NULL; +HTREEITEM hFilterCps2 = NULL; +HTREEITEM hFilterCps3 = NULL; +HTREEITEM hFilterGalaxian = NULL; +HTREEITEM hFilterIrem = NULL; +HTREEITEM hFilterKonami = NULL; +HTREEITEM hFilterNeogeo = NULL; +HTREEITEM hFilterPacman = NULL; +HTREEITEM hFilterPgm = NULL; +HTREEITEM hFilterPsikyo = NULL; +HTREEITEM hFilterSega = NULL; +HTREEITEM hFilterTaito = NULL; +HTREEITEM hFilterToaplan = NULL; +HTREEITEM hFilterMegadrive = NULL; +HTREEITEM hFilterMiscPre90s = NULL; +HTREEITEM hFilterMiscPost90s = NULL; +HTREEITEM hFilterBootleg = NULL; +HTREEITEM hFilterDemo = NULL; +HTREEITEM hFilterHack = NULL; +HTREEITEM hFilterHomebrew = NULL; +HTREEITEM hFilterPrototype = NULL; +HTREEITEM hFilterGenuine = NULL; +HTREEITEM hFilterHorshoot = NULL; +HTREEITEM hFilterVershoot = NULL; +HTREEITEM hFilterScrfight = NULL; +HTREEITEM hFilterVsfight = NULL; +HTREEITEM hFilterBios = NULL; +HTREEITEM hFilterBreakout = NULL; +HTREEITEM hFilterCasino = NULL; +HTREEITEM hFilterBallpaddle = NULL; +HTREEITEM hFilterMaze = NULL; +HTREEITEM hFilterMinigames = NULL; +HTREEITEM hFilterPinball = NULL; +HTREEITEM hFilterPlatform = NULL; +HTREEITEM hFilterPuzzle = NULL; +HTREEITEM hFilterQuiz = NULL; +HTREEITEM hFilterSportsmisc = NULL; +HTREEITEM hFilterSportsfootball = NULL; +HTREEITEM hFilterMisc = NULL; +HTREEITEM hFilterMahjong = NULL; +HTREEITEM hFilterRacing = NULL; +HTREEITEM hFilterShoot = NULL; +HTREEITEM hFilterOtherFamily = NULL; +HTREEITEM hFilterMslug = NULL; +HTREEITEM hFilterSf = NULL; +HTREEITEM hFilterKof = NULL; +HTREEITEM hFilterDstlk = NULL; +HTREEITEM hFilterFatfury = NULL; +HTREEITEM hFilterSamsho = NULL; +HTREEITEM hFilter19xx = NULL; +HTREEITEM hFilterSonicwi = NULL; +HTREEITEM hFilterPwrinst = NULL; + +HTREEITEM hRoot = NULL; +HTREEITEM hBoardType = NULL; +HTREEITEM hFamily = NULL; +HTREEITEM hGenre = NULL; +HTREEITEM hHardware = NULL; + +// GCC doesn't seem to define these correctly..... +#define _TreeView_SetItemState(hwndTV, hti, data, _mask) \ +{ TVITEM _ms_TVi;\ + _ms_TVi.mask = TVIF_STATE; \ + _ms_TVi.hItem = hti; \ + _ms_TVi.stateMask = _mask;\ + _ms_TVi.state = data;\ + SNDMSG((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_ms_TVi);\ +} + +#define _TreeView_SetCheckState(hwndTV, hti, fCheck) \ + _TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK) + +// ----------------------------------------------------------------------------------------------------------------- + +#define DISABLE_NON_AVAILABLE_SELECT 0 // Disable selecting non-available sets +#define NON_WORKING_PROMPT_ON_LOAD 1 // Prompt user on loading non-working sets + +#define MASKCPS (1 << (HARDWARE_PREFIX_CAPCOM >> 24)) +#define MASKCPS2 (1 << (HARDWARE_PREFIX_CPS2 >> 24)) +#define MASKCPS3 (1 << (HARDWARE_PREFIX_CPS3 >> 24)) +#define MASKNEOGEO (1 << (HARDWARE_PREFIX_SNK >> 24)) +#define MASKSEGA (1 << (HARDWARE_PREFIX_SEGA >> 24)) +#define MASKTOAPLAN (1 << (HARDWARE_PREFIX_TOAPLAN >> 24)) +#define MASKCAVE (1 << (HARDWARE_PREFIX_CAVE >> 24)) +#define MASKPGM (1 << (HARDWARE_PREFIX_IGS_PGM >> 24)) +#define MASKMEGADRIVE (1 << (HARDWARE_PREFIX_SEGA_MEGADRIVE >> 24)) +#define MASKTAITO (1 << (HARDWARE_PREFIX_TAITO >> 24)) +#define MASKPSIKYO (1 << (HARDWARE_PREFIX_PSIKYO >> 24)) +#define MASKKONAMI (1 << (HARDWARE_PREFIX_KONAMI >> 24)) +#define MASKPACMAN (1 << (HARDWARE_PREFIX_PACMAN >> 24)) +#define MASKGALAXIAN (1 << (HARDWARE_PREFIX_GALAXIAN >> 24)) +#define MASKIREM (0x1000 * (HARDWARE_PREFIX_IREM >> 24)) +#define MASKMISCPRE90S (1 << (HARDWARE_PREFIX_MISC_PRE90S >> 24)) +#define MASKMISCPOST90S (1 << (HARDWARE_PREFIX_MISC_POST90S >> 24)) +#define MASKALL (MASKCPS | MASKCPS2 | MASKCPS3 | MASKNEOGEO | MASKSEGA | MASKTOAPLAN | MASKCAVE | MASKPGM | MASKTAITO | MASKPSIKYO | MASKKONAMI | MASKPACMAN | MASKGALAXIAN | MASKIREM | MASKMEGADRIVE | MASKMISCPRE90S | MASKMISCPOST90S) + +#define AVAILONLY (1 << 18) +#define AUTOEXPAND (1 << 19) +#define SHOWSHORT (1 << 20) +#define ASCIIONLY (1 << 21) + +#define MASKBOARDTYPEGENUINE (1) +#define MASKFAMILYOTHER 0x10000000 + +#define MASKALLGENRE (GBF_HORSHOOT | GBF_VERSHOOT | GBF_SCRFIGHT | GBF_VSFIGHT | GBF_BIOS | GBF_BREAKOUT | GBF_CASINO | GBF_BALLPADDLE | GBF_MAZE | GBF_MINIGAMES | GBF_PINBALL | GBF_PLATFORM | GBF_PUZZLE | GBF_QUIZ | GBF_SPORTSMISC | GBF_SPORTSFOOTBALL | GBF_MISC | GBF_MAHJONG | GBF_RACING | GBF_SHOOT) +#define MASKALLFAMILY (MASKFAMILYOTHER | FBF_MSLUG | FBF_SF | FBF_KOF | FBF_DSTLK | FBF_FATFURY | FBF_SAMSHO | FBF_19XX | FBF_SONICWI | FBF_PWRINST) +#define MASKALLBOARD (MASKBOARDTYPEGENUINE | BDF_BOOTLEG | BDF_DEMO | BDF_HACK | BDF_HOMEBREW | BDF_PROTOTYPE) + +int nLoadMenuShowX = 0; +int nLoadMenuBoardTypeFilter = 0; +int nLoadMenuGenreFilter = 0; +int nLoadMenuFamilyFilter = 0; + +struct NODEINFO { + int nBurnDrvNo; + bool bIsParent; + char* pszROMName; + HTREEITEM hTreeHandle; +}; + +static NODEINFO* nBurnDrv; +static unsigned int nTmpDrvCount; + +// prototype ----------------------- +static void RebuildEverything(); +// ---------------------------------- + +// Check if a specified driver is working +static bool CheckWorkingStatus(int nDriver) +{ + int nOldnBurnDrvActive = nBurnDrvActive; + nBurnDrvActive = nDriver; + bool bStatus = BurnDrvIsWorking(); + nBurnDrvActive = nOldnBurnDrvActive; + + return bStatus; +} + +static TCHAR* MangleGamename(const TCHAR* szOldName, bool /*bRemoveArticle*/) +{ + static TCHAR szNewName[256] = _T(""); + +#if 0 + TCHAR* pszName = szNewName; + + if (_tcsnicmp(szOldName, _T("the "), 4) == 0) { + int x = 0, y = 0; + while (szOldName[x] && szOldName[x] != _T('(') && szOldName[x] != _T('-')) { + x++; + } + y = x; + while (y && szOldName[y - 1] == _T(' ')) { + y--; + } + _tcsncpy(pszName, szOldName + 4, y - 4); + pszName[y - 4] = _T('\0'); + pszName += y - 4; + + if (!bRemoveArticle) { + pszName += _stprintf(pszName, _T(", the")); + } + if (szOldName[x]) { + _stprintf(pszName, _T(" %s"), szOldName + x); + } + } else { + _tcscpy(pszName, szOldName); + } +#endif + +#if 1 + _tcscpy(szNewName, szOldName); +#endif + + return szNewName; +} + +static int DoExtraFilters() +{ + if (nShowMVSCartsOnly && ((BurnDrvGetHardwareCode() & HARDWARE_PREFIX_CARTRIDGE) != HARDWARE_PREFIX_CARTRIDGE)) return 1; + + if ((nLoadMenuBoardTypeFilter & BDF_BOOTLEG) && (BurnDrvGetFlags() & BDF_BOOTLEG)) return 1; + if ((nLoadMenuBoardTypeFilter & BDF_DEMO) && (BurnDrvGetFlags() & BDF_DEMO)) return 1; + if ((nLoadMenuBoardTypeFilter & BDF_HACK) && (BurnDrvGetFlags() & BDF_HACK)) return 1; + if ((nLoadMenuBoardTypeFilter & BDF_HOMEBREW) && (BurnDrvGetFlags() & BDF_HOMEBREW)) return 1; + if ((nLoadMenuBoardTypeFilter & BDF_PROTOTYPE) && (BurnDrvGetFlags() & BDF_PROTOTYPE)) return 1; + + if ((nLoadMenuBoardTypeFilter & MASKBOARDTYPEGENUINE) && (!(BurnDrvGetFlags() & BDF_BOOTLEG)) + && (!(BurnDrvGetFlags() & BDF_DEMO)) + && (!(BurnDrvGetFlags() & BDF_HACK)) + && (!(BurnDrvGetFlags() & BDF_HOMEBREW)) + && (!(BurnDrvGetFlags() & BDF_PROTOTYPE))) return 1; + + if ((nLoadMenuFamilyFilter & FBF_MSLUG) && (BurnDrvGetFamilyFlags() & FBF_MSLUG)) return 1; + if ((nLoadMenuFamilyFilter & FBF_SF) && (BurnDrvGetFamilyFlags() & FBF_SF)) return 1; + if ((nLoadMenuFamilyFilter & FBF_KOF) && (BurnDrvGetFamilyFlags() & FBF_KOF)) return 1; + if ((nLoadMenuFamilyFilter & FBF_DSTLK) && (BurnDrvGetFamilyFlags() & FBF_DSTLK)) return 1; + if ((nLoadMenuFamilyFilter & FBF_FATFURY) && (BurnDrvGetFamilyFlags() & FBF_FATFURY)) return 1; + if ((nLoadMenuFamilyFilter & FBF_SAMSHO) && (BurnDrvGetFamilyFlags() & FBF_SAMSHO)) return 1; + if ((nLoadMenuFamilyFilter & FBF_19XX) && (BurnDrvGetFamilyFlags() & FBF_19XX)) return 1; + if ((nLoadMenuFamilyFilter & FBF_SONICWI) && (BurnDrvGetFamilyFlags() & FBF_SONICWI)) return 1; + if ((nLoadMenuFamilyFilter & FBF_PWRINST) && (BurnDrvGetFamilyFlags() & FBF_PWRINST)) return 1; + + if ((nLoadMenuFamilyFilter & MASKFAMILYOTHER) && (!(BurnDrvGetFamilyFlags() & FBF_MSLUG)) + && (!(BurnDrvGetFamilyFlags() & FBF_SF)) + && (!(BurnDrvGetFamilyFlags() & FBF_KOF)) + && (!(BurnDrvGetFamilyFlags() & FBF_DSTLK)) + && (!(BurnDrvGetFamilyFlags() & FBF_FATFURY)) + && (!(BurnDrvGetFamilyFlags() & FBF_SAMSHO)) + && (!(BurnDrvGetFamilyFlags() & FBF_19XX)) + && (!(BurnDrvGetFamilyFlags() & FBF_SONICWI)) + && (!(BurnDrvGetFamilyFlags() & FBF_PWRINST))) return 1; + + if ((nLoadMenuGenreFilter & GBF_HORSHOOT) && (BurnDrvGetGenreFlags() & GBF_HORSHOOT)) return 1; + if ((nLoadMenuGenreFilter & GBF_VERSHOOT) && (BurnDrvGetGenreFlags() & GBF_VERSHOOT)) return 1; + if ((nLoadMenuGenreFilter & GBF_SCRFIGHT) && (BurnDrvGetGenreFlags() & GBF_SCRFIGHT)) return 1; + if ((nLoadMenuGenreFilter & GBF_VSFIGHT) && (BurnDrvGetGenreFlags() & GBF_VSFIGHT)) return 1; + if ((nLoadMenuGenreFilter & GBF_BIOS) && (BurnDrvGetGenreFlags() & GBF_BIOS)) return 1; + if ((nLoadMenuGenreFilter & GBF_BREAKOUT) && (BurnDrvGetGenreFlags() & GBF_BREAKOUT)) return 1; + if ((nLoadMenuGenreFilter & GBF_CASINO) && (BurnDrvGetGenreFlags() & GBF_CASINO)) return 1; + if ((nLoadMenuGenreFilter & GBF_BALLPADDLE) && (BurnDrvGetGenreFlags() & GBF_BALLPADDLE)) return 1; + if ((nLoadMenuGenreFilter & GBF_MAZE) && (BurnDrvGetGenreFlags() & GBF_MAZE)) return 1; + if ((nLoadMenuGenreFilter & GBF_MINIGAMES) && (BurnDrvGetGenreFlags() & GBF_MINIGAMES)) return 1; + if ((nLoadMenuGenreFilter & GBF_PINBALL) && (BurnDrvGetGenreFlags() & GBF_PINBALL)) return 1; + if ((nLoadMenuGenreFilter & GBF_PLATFORM) && (BurnDrvGetGenreFlags() & GBF_PLATFORM)) return 1; + if ((nLoadMenuGenreFilter & GBF_PUZZLE) && (BurnDrvGetGenreFlags() & GBF_PUZZLE)) return 1; + if ((nLoadMenuGenreFilter & GBF_QUIZ) && (BurnDrvGetGenreFlags() & GBF_QUIZ)) return 1; + if ((nLoadMenuGenreFilter & GBF_SPORTSMISC) && (BurnDrvGetGenreFlags() & GBF_SPORTSMISC)) return 1; + if ((nLoadMenuGenreFilter & GBF_SPORTSFOOTBALL) && (BurnDrvGetGenreFlags() & GBF_SPORTSFOOTBALL)) return 1; + if ((nLoadMenuGenreFilter & GBF_MISC) && (BurnDrvGetGenreFlags() & GBF_MISC)) return 1; + if ((nLoadMenuGenreFilter & GBF_MAHJONG) && (BurnDrvGetGenreFlags() & GBF_MAHJONG)) return 1; + if ((nLoadMenuGenreFilter & GBF_RACING) && (BurnDrvGetGenreFlags() & GBF_RACING)) return 1; + if ((nLoadMenuGenreFilter & GBF_SHOOT) && (BurnDrvGetGenreFlags() & GBF_SHOOT)) return 1; + + return 0; +} + +// Make a tree-view control with all drivers +static int SelListMake() +{ + unsigned int i, j; + unsigned int nMissingDrvCount = 0; + + if (nBurnDrv) { + free(nBurnDrv); + nBurnDrv = NULL; + } + nBurnDrv = (NODEINFO*)malloc(nBurnDrvCount * sizeof(NODEINFO)); + memset(nBurnDrv, 0, nBurnDrvCount * sizeof(NODEINFO)); + + nTmpDrvCount = 0; + + if (hSelList == NULL) { + return 1; + } + + // Add all the driver names to the list + + // 1st: parents + for (i = 0; i < nBurnDrvCount; i++) { + TV_INSERTSTRUCT TvItem; + + nBurnDrvActive = i; // Switch to driver i + + if (BurnDrvGetFlags() & BDF_BOARDROM) { + continue; + } + if (BurnDrvGetText(DRV_PARENT) != NULL && (BurnDrvGetFlags() & BDF_CLONE)) { // Skip clones + continue; + } + //if (avOk && (nLoadMenuShowX & AVAILONLY) && !gameAv[i]) { // Skip non-available games if needed + // continue; + //} + + int nHardware = 1 << (BurnDrvGetHardwareCode() >> 24); + if ((BurnDrvGetHardwareCode() >> 24) == (HARDWARE_PREFIX_IREM >> 24)) nHardware = MASKIREM; + if ((nHardware & MASKALL) && ((nHardware & nLoadMenuShowX) || (nHardware & MASKALL) == 0)) { + continue; + } + + if (DoExtraFilters()) continue; + + TCHAR szSearchString[100]; + GetDlgItemText(hSelDlg, IDC_SEL_SEARCH, szSearchString, sizeof(szSearchString)); + if (szSearchString[0]) { + TCHAR *StringFound = NULL; + TCHAR *StringFound2 = NULL; + TCHAR szDriverName[100]; + wcscpy(szDriverName, BurnDrvGetText(DRV_FULLNAME)); + for (int k =0; k < 100; k++) { + szSearchString[k] = _totlower(szSearchString[k]); + szDriverName[k] = _totlower(szDriverName[k]); + } + StringFound = wcsstr(szDriverName, szSearchString); + StringFound2 = wcsstr(BurnDrvGetText(DRV_NAME), szSearchString); + if (!StringFound && !StringFound2) continue; + } + + if(!gameAv[i]) nMissingDrvCount++; + + if (avOk && (nLoadMenuShowX & AVAILONLY) && !gameAv[i]) { // Skip non-available games if needed + continue; + } + + memset(&TvItem, 0, sizeof(TvItem)); + TvItem.item.mask = TVIF_TEXT | TVIF_PARAM; + TvItem.hInsertAfter = TVI_SORT; + TvItem.item.pszText = (nLoadMenuShowX & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : MangleGamename(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME), true); + TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount]; + nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TvItem); + nBurnDrv[nTmpDrvCount].nBurnDrvNo = i; + nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME); + nBurnDrv[nTmpDrvCount].bIsParent = true; + nTmpDrvCount++; + } + + // 2nd: clones + for (i = 0; i < nBurnDrvCount; i++) { + TV_INSERTSTRUCT TvItem; + + nBurnDrvActive = i; // Switch to driver i + + if (BurnDrvGetFlags() & BDF_BOARDROM) { + continue; + } + + if (BurnDrvGetTextA(DRV_PARENT) == NULL || !(BurnDrvGetFlags() & BDF_CLONE)) { // Skip parents + continue; + } + //if (avOk && (nLoadMenuShowX & AVAILONLY) && !gameAv[i]) { // Skip non-available games if needed + // continue; + //} + + int nHardware = 1 << (BurnDrvGetHardwareCode() >> 24); + if ((BurnDrvGetHardwareCode() >> 24) == (HARDWARE_PREFIX_IREM >> 24)) nHardware = MASKIREM; + if ((nHardware & MASKALL) && ((nHardware & nLoadMenuShowX) || ((nHardware & MASKALL) == 0))) { + continue; + } + + if (DoExtraFilters()) continue; + + TCHAR szSearchString[100]; + GetDlgItemText(hSelDlg, IDC_SEL_SEARCH, szSearchString, sizeof(szSearchString)); + if (szSearchString[0]) { + TCHAR *StringFound = NULL; + TCHAR *StringFound2 = NULL; + TCHAR szDriverName[100]; + wcscpy(szDriverName, BurnDrvGetText(DRV_FULLNAME)); + for (int k =0; k < 100; k++) { + szSearchString[k] = _totlower(szSearchString[k]); + szDriverName[k] = _totlower(szDriverName[k]); + } + StringFound = wcsstr(szDriverName, szSearchString); + StringFound2 = wcsstr(BurnDrvGetText(DRV_NAME), szSearchString); + if (!StringFound && !StringFound2) continue; + } + + if(!gameAv[i]) nMissingDrvCount++; + + if (avOk && (nLoadMenuShowX & AVAILONLY) && !gameAv[i]) { // Skip non-available games if needed + continue; + } + + memset(&TvItem, 0, sizeof(TvItem)); + TvItem.item.mask = TVIF_TEXT | TVIF_PARAM; + TvItem.hInsertAfter = TVI_SORT; + TvItem.item.pszText = (nLoadMenuShowX & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : MangleGamename(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME), true); + + // Find the parent's handle + for (j = 0; j < nTmpDrvCount; j++) { + if (nBurnDrv[j].bIsParent) { + if (!_stricmp(BurnDrvGetTextA(DRV_PARENT), nBurnDrv[j].pszROMName)) { + TvItem.hParent = nBurnDrv[j].hTreeHandle; + break; + } + } + } + + // Find the parent and add a branch to the tree + if (!TvItem.hParent) { + char szTempName[9]; + strcpy(szTempName, BurnDrvGetTextA(DRV_PARENT)); + int nTempBurnDrvSelect = nBurnDrvActive; + for (j = 0; j < nBurnDrvCount; j++) { + nBurnDrvActive = j; + if (!strcmp(szTempName, BurnDrvGetTextA(DRV_NAME))) { + TV_INSERTSTRUCT TempTvItem; + memset(&TempTvItem, 0, sizeof(TempTvItem)); + TempTvItem.item.mask = TVIF_TEXT | TVIF_PARAM; + TempTvItem.hInsertAfter = TVI_SORT; + TempTvItem.item.pszText = (nLoadMenuShowX & SHOWSHORT) ? BurnDrvGetText(DRV_NAME) : MangleGamename(BurnDrvGetText(DRV_ASCIIONLY | DRV_FULLNAME), true); + TempTvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount]; + nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TempTvItem); + nBurnDrv[nTmpDrvCount].nBurnDrvNo = j; + nBurnDrv[nTmpDrvCount].bIsParent = true; + nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME); + TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount]; + TvItem.hParent = nBurnDrv[nTmpDrvCount].hTreeHandle; + nTmpDrvCount++; + break; + } + } + nBurnDrvActive = nTempBurnDrvSelect; + } + + TvItem.item.lParam = (LPARAM)&nBurnDrv[nTmpDrvCount]; + nBurnDrv[nTmpDrvCount].hTreeHandle = (HTREEITEM)SendMessage(hSelList, TVM_INSERTITEM, 0, (LPARAM)&TvItem); + nBurnDrv[nTmpDrvCount].pszROMName = BurnDrvGetTextA(DRV_NAME); + nBurnDrv[nTmpDrvCount].nBurnDrvNo = i; + nTmpDrvCount++; + } + + for (i = 0; i < nTmpDrvCount; i++) { + + // See if we need to expand the branch of an unavailable or non-working parent + if (nBurnDrv[i].bIsParent && ((nLoadMenuShowX & AUTOEXPAND) || !gameAv[nBurnDrv[i].nBurnDrvNo] || !CheckWorkingStatus(nBurnDrv[i].nBurnDrvNo))) { + for (j = 0; j < nTmpDrvCount; j++) { + + // Expand the branch only if a working clone is available + if (gameAv[nBurnDrv[j].nBurnDrvNo]) { + nBurnDrvActive = nBurnDrv[j].nBurnDrvNo; + if (BurnDrvGetTextA(DRV_PARENT)) { + if (strcmp(nBurnDrv[i].pszROMName, BurnDrvGetTextA(DRV_PARENT)) == 0) { + SendMessage(hSelList, TVM_EXPAND,TVE_EXPAND, (LPARAM)nBurnDrv[i].hTreeHandle); + break; + } + } + } + } + } + } + + // Update the status info + TCHAR szRomsAvailableInfo[128] = _T(""); + + _stprintf(szRomsAvailableInfo, _T("Showing %i of %i sets [%i Unavailable sets]"), nTmpDrvCount, nBurnDrvCount - 3, nMissingDrvCount); + SendDlgItemMessage(hSelDlg, IDC_DRVCOUNT, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)szRomsAvailableInfo); + + return 0; +} + +static void MyEndDialog() +{ + if (nTimer) { + KillTimer(hSelDlg, nTimer); + nTimer = 0; + } + + if (nInitPreviewTimer) { + KillTimer(hSelDlg, nInitPreviewTimer); + nInitPreviewTimer = 0; + } + + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + if (hPrevBmp) { + DeleteObject((HGDIOBJ)hPrevBmp); + hPrevBmp = NULL; + } + if (hPreview) { + DeleteObject((HGDIOBJ)hPreview); + hPreview = NULL; + } + + if (hExpand) { + DestroyIcon(hExpand); + hExpand = NULL; + } + if (hCollapse) { + DestroyIcon(hCollapse); + hCollapse = NULL; + } + if (hNotWorking) { + DestroyIcon(hNotWorking); + hNotWorking = NULL; + } + if (hNotFoundEss) { + DestroyIcon(hNotFoundEss); + hNotFoundEss = NULL; + } + if (hNotFoundNonEss) { + DestroyIcon(hNotFoundNonEss); + hNotFoundNonEss = NULL; + } + if(hDrvIconMiss) { + DestroyIcon(hDrvIconMiss); + hDrvIconMiss = NULL; + } + + EndDialog(hSelDlg, 0); +} + +// User clicked ok for a driver in the list +static void SelOkay() +{ + TV_ITEM TvItem; + unsigned int nSelect = 0; + HTREEITEM hSelectHandle = (HTREEITEM)SendMessage(hSelList, TVM_GETNEXTITEM, TVGN_CARET, ~0U); + + if (!hSelectHandle) { // Nothing is selected, return without closing the window + return; + } + + TvItem.hItem = hSelectHandle; + TvItem.mask = TVIF_PARAM; + SendMessage(hSelList, TVM_GETITEM, 0, (LPARAM)&TvItem); + nSelect = ((NODEINFO*)TvItem.lParam)->nBurnDrvNo; + +#if DISABLE_NON_AVAILABLE_SELECT + if (!gameAv[nSelect]) { // Game not available, return without closing the window + return; + } +#endif + +#if NON_WORKING_PROMPT_ON_LOAD + if (!CheckWorkingStatus(nSelect)) { + if (MessageBox(hSelDlg, _T("This game isn't working. Load it anyway?"), _T("Warning!"), MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDNO) { + return; + } + } +#endif + nDialogSelect = nSelect; + + bDialogCancel = false; + MyEndDialog(); +} + +static void RefreshPanel() +{ + // clear preview shot + if (hPrevBmp) { + DeleteObject((HGDIOBJ)hPrevBmp); + hPrevBmp = NULL; + } + if (nTimer) { + KillTimer(hSelDlg, nTimer); + nTimer = 0; + } + + + hPrevBmp = PNGLoadBitmap(hSelDlg, NULL, 213, 160, 2); + + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPrevBmp); + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPrevBmp); + SendDlgItemMessage(hSelDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + // Clear the things in our Info-box + for (int i = 0; i < 6; i++) { + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)_T("")); + EnableWindow(hInfoLabel[i], FALSE); + } + + CheckDlgButton(hSelDlg, IDC_CHECKAUTOEXPAND, (nLoadMenuShowX & AUTOEXPAND) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hSelDlg, IDC_CHECKAVAILABLEONLY, (nLoadMenuShowX & AVAILONLY) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hSelDlg, IDC_SEL_SHORTNAME, nLoadMenuShowX & SHOWSHORT ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hSelDlg, IDC_SEL_ASCIIONLY, nLoadMenuShowX & ASCIIONLY ? BST_CHECKED : BST_UNCHECKED); +} + +FILE* OpenPreview(int nIndex, TCHAR *szPath) +{ + static bool bTryParent; + + TCHAR szBaseName[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + + FILE* fp = NULL; + + // Try to load a .PNG preview image + _sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_NAME)); + if (nIndex <= 1) { + _stprintf(szFileName, _T("%s.png"), szBaseName); + fp = _tfopen(szFileName, _T("rb")); + } + if (!fp) { + _stprintf(szFileName, _T("%s [%02i].png"), szBaseName, nIndex); + fp = _tfopen(szFileName, _T("rb")); + } + + if (nIndex <= 1) { + bTryParent = fp ? false : true; + } + + if (!fp && BurnDrvGetText(DRV_PARENT) && bTryParent) { // Try the parent + _sntprintf(szBaseName, sizeof(szBaseName), _T("%s%s"), szPath, BurnDrvGetText(DRV_PARENT)); + if (nIndex <= 1) { + _stprintf(szFileName, _T("%s.png"), szBaseName); + fp = _tfopen(szFileName, _T("rb")); + } + if (!fp) { + _stprintf(szFileName, _T("%s [%02i].png"), szBaseName, nIndex); + fp = _tfopen(szFileName, _T("rb")); + } + } + + return fp; +} + +static VOID CALLBACK PreviewTimerProc(HWND, UINT, UINT_PTR, DWORD) +{ + UpdatePreview(false, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V); +} + +static VOID CALLBACK InitPreviewTimerProc(HWND, UINT, UINT_PTR, DWORD) +{ + UpdatePreview(true, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V); + + if (GetIpsNumPatches()) { + if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_IPSMANAGER), TRUE); + } else { + EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_IPSMANAGER), FALSE); + } + + LoadIpsActivePatches(); + if (GetIpsNumActivePatches()) { + if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_APPLYIPS), TRUE); + } else { + EnableWindow(GetDlgItem(hSelDlg, IDC_SEL_APPLYIPS), FALSE); + } + + KillTimer(hSelDlg, nInitPreviewTimer); + nInitPreviewTimer = 0; +} + +static int UpdatePreview(bool bReset, TCHAR *szPath, int HorCtrl, int VerCtrl) +{ + static int nIndex; + int nOldIndex = 0; + + FILE* fp = NULL; + HBITMAP hNewImage = NULL; + + if (HorCtrl == IDC_SCREENSHOT_H) { + nOldIndex = nIndex; + nIndex++; + if (bReset) { + nIndex = 1; + nOldIndex = -1; + if (hPrevBmp) { + DeleteObject((HGDIOBJ)hPrevBmp); + hPrevBmp = NULL; + } + if (nTimer) { + KillTimer(hSelDlg, 1); + nTimer = 0; + } + } + } + + nBurnDrvActive = nDialogSelect; + + if ((nIndex != nOldIndex) || (HorCtrl == IDC_SCREENSHOT2_H)) { + int x, y, ax, ay; + + BurnDrvGetAspect(&ax, &ay); + + //if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (ay > ax) { + bImageOrientation = true; + + y = 160; + x = y * ax / ay; + } else { + bImageOrientation = false; + + x = 213; + y = x * ay / ax; + } + + if (HorCtrl == IDC_SCREENSHOT_H) { + fp = OpenPreview(nIndex, szPath); + } else { + fp = OpenPreview(0, szPath); + } + if (!fp && nIndex > 1 && HorCtrl == IDC_SCREENSHOT_H) { + if (nIndex == 2) { + + // There's only a single preview image, stop timer + + if (nTimer) { + KillTimer(hSelDlg, 1); + nTimer = 0; + } + + return 0; + } + + nIndex = 1; + fp = OpenPreview(nIndex, szPath); + } + if (fp) { + hNewImage = PNGLoadBitmap(hSelDlg, fp, x, y, 3); + } + } + + if (fp) { + fclose(fp); + + if (HorCtrl == IDC_SCREENSHOT_H) nTimer = SetTimer(hSelDlg, 1, 2500, PreviewTimerProc); + } else { + + // We couldn't load a new image for this game, so kill the timer (it will be restarted when a new game is selected) + + if (HorCtrl == IDC_SCREENSHOT_H) { + if (nTimer) { + KillTimer(hSelDlg, 1); + nTimer = 0; + } + } + + bImageOrientation = false; + hNewImage = PNGLoadBitmap(hSelDlg, NULL, 213, 160, 2); + } + + if (hPrevBmp) { + DeleteObject((HGDIOBJ)hPrevBmp); + } + hPrevBmp = hNewImage; + + if (bImageOrientation == 0) { + SendDlgItemMessage(hSelDlg, HorCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPrevBmp); + SendDlgItemMessage(hSelDlg, VerCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + ShowWindow(GetDlgItem(hSelDlg, HorCtrl), SW_SHOW); + ShowWindow(GetDlgItem(hSelDlg, VerCtrl), SW_HIDE); + } else { + SendDlgItemMessage(hSelDlg, HorCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + SendDlgItemMessage(hSelDlg, VerCtrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hPrevBmp); + ShowWindow(GetDlgItem(hSelDlg, HorCtrl), SW_HIDE); + ShowWindow(GetDlgItem(hSelDlg, VerCtrl), SW_SHOW); + } + + UpdateWindow(hSelDlg); + + return 0; +} + +static void RebuildEverything() +{ + RefreshPanel(); + + bDrvSelected = false; + + TreeBuilding = 1; + SendMessage(hSelList, WM_SETREDRAW, (WPARAM)FALSE,(LPARAM)TVI_ROOT); // disable redraw + SendMessage(hSelList, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); // Destory all nodes + SelListMake(); + SendMessage(hSelList, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)TVI_ROOT); // enable redraw + + // Clear the things in our Info-box + for (int i = 0; i < 6; i++) { + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)_T("")); + EnableWindow(hInfoLabel[i], FALSE); + } + + TreeBuilding = 0; +} + +#define _TVCreateFiltersA(a, b, c, d) \ +{ \ + TvItem.hParent = a; \ + TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true); \ + c = TreeView_InsertItem(hFilterList, &TvItem); \ + _TreeView_SetCheckState(hFilterList, c, (d) ? FALSE : TRUE); \ +} + +#define _TVCreateFiltersB(a, b, c) \ +{ \ + TvItem.hParent = a; \ + TvItem.item.pszText = FBALoadStringEx(hAppInst, b, true); \ + c = TreeView_InsertItem(hFilterList, &TvItem); \ +} + +static void CreateFilters() +{ + TV_INSERTSTRUCT TvItem; + memset(&TvItem, 0, sizeof(TvItem)); + + hFilterList = GetDlgItem(hSelDlg, IDC_TREE2); + + TvItem.item.mask = TVIF_TEXT | TVIF_PARAM; + TvItem.hInsertAfter = TVI_LAST; + + _TVCreateFiltersB(TVI_ROOT , IDS_SEL_FILTERS , hRoot ); + _TVCreateFiltersB(hRoot , IDS_SEL_BOARDTYPE , hBoardType ); + + _TVCreateFiltersA(hBoardType , IDS_SEL_GENUINE , hFilterGenuine , nLoadMenuBoardTypeFilter & MASKBOARDTYPEGENUINE ); + _TVCreateFiltersA(hBoardType , IDS_SEL_BOOTLEG , hFilterBootleg , nLoadMenuBoardTypeFilter & BDF_BOOTLEG ); + _TVCreateFiltersA(hBoardType , IDS_SEL_DEMO , hFilterDemo , nLoadMenuBoardTypeFilter & BDF_DEMO ); + _TVCreateFiltersA(hBoardType , IDS_SEL_HACK , hFilterHack , nLoadMenuBoardTypeFilter & BDF_HACK ); + _TVCreateFiltersA(hBoardType , IDS_SEL_HOMEBREW , hFilterHomebrew , nLoadMenuBoardTypeFilter & BDF_HOMEBREW ); + _TVCreateFiltersA(hBoardType , IDS_SEL_PROTOTYPE , hFilterPrototype , nLoadMenuBoardTypeFilter & BDF_PROTOTYPE ); + + _TVCreateFiltersB(hRoot , IDS_FAMILY , hFamily ); + + _TVCreateFiltersA(hFamily , IDS_FAMILY_OTHER , hFilterOtherFamily , nLoadMenuFamilyFilter & MASKFAMILYOTHER ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_19XX , hFilter19xx , nLoadMenuFamilyFilter & FBF_19XX ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_SONICWI , hFilterSonicwi , nLoadMenuFamilyFilter & FBF_SONICWI ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_DSTLK , hFilterDstlk , nLoadMenuFamilyFilter & FBF_DSTLK ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_FATFURY , hFilterFatfury , nLoadMenuFamilyFilter & FBF_FATFURY ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_KOF , hFilterKof , nLoadMenuFamilyFilter & FBF_KOF ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_MSLUG , hFilterMslug , nLoadMenuFamilyFilter & FBF_MSLUG ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_PWRINST , hFilterPwrinst , nLoadMenuFamilyFilter & FBF_PWRINST ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_SAMSHO , hFilterSamsho , nLoadMenuFamilyFilter & FBF_SAMSHO ); + _TVCreateFiltersA(hFamily , IDS_FAMILY_SF , hFilterSf , nLoadMenuFamilyFilter & FBF_SF ); + + _TVCreateFiltersB(hRoot , IDS_GENRE , hGenre ); + + _TVCreateFiltersA(hGenre , IDS_GENRE_BALLPADDLE , hFilterBallpaddle , nLoadMenuGenreFilter & GBF_BALLPADDLE ); + _TVCreateFiltersA(hGenre , IDS_GENRE_BIOS , hFilterBios , nLoadMenuGenreFilter & GBF_BIOS ); + _TVCreateFiltersA(hGenre , IDS_GENRE_BREAKOUT , hFilterBreakout , nLoadMenuGenreFilter & GBF_BREAKOUT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_CASINO , hFilterCasino , nLoadMenuGenreFilter & GBF_CASINO ); + _TVCreateFiltersA(hGenre , IDS_GENRE_SCRFIGHT , hFilterScrfight , nLoadMenuGenreFilter & GBF_SCRFIGHT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_VSFIGHT , hFilterVsfight , nLoadMenuGenreFilter & GBF_VSFIGHT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_MAHJONG , hFilterMahjong , nLoadMenuGenreFilter & GBF_MAHJONG ); + _TVCreateFiltersA(hGenre , IDS_GENRE_MAZE , hFilterMaze , nLoadMenuGenreFilter & GBF_MAZE ); + _TVCreateFiltersA(hGenre , IDS_GENRE_MINIGAMES , hFilterMinigames , nLoadMenuGenreFilter & GBF_MINIGAMES ); + _TVCreateFiltersA(hGenre , IDS_GENRE_MISC , hFilterMisc , nLoadMenuGenreFilter & GBF_MISC ); + _TVCreateFiltersA(hGenre , IDS_GENRE_PINBALL , hFilterPinball , nLoadMenuGenreFilter & GBF_PINBALL ); + _TVCreateFiltersA(hGenre , IDS_GENRE_PLATFORM , hFilterPlatform , nLoadMenuGenreFilter & GBF_PLATFORM ); + _TVCreateFiltersA(hGenre , IDS_GENRE_PUZZLE , hFilterPuzzle , nLoadMenuGenreFilter & GBF_PUZZLE ); + _TVCreateFiltersA(hGenre , IDS_GENRE_QUIZ , hFilterQuiz , nLoadMenuGenreFilter & GBF_QUIZ ); + _TVCreateFiltersA(hGenre , IDS_GENRE_RACING , hFilterRacing , nLoadMenuGenreFilter & GBF_RACING ); + _TVCreateFiltersA(hGenre , IDS_GENRE_HORSHOOT , hFilterHorshoot , nLoadMenuGenreFilter & GBF_HORSHOOT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_SHOOT , hFilterShoot , nLoadMenuGenreFilter & GBF_SHOOT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_VERSHOOT , hFilterVershoot , nLoadMenuGenreFilter & GBF_VERSHOOT ); + _TVCreateFiltersA(hGenre , IDS_GENRE_SPORTSMISC , hFilterSportsmisc , nLoadMenuGenreFilter & GBF_SPORTSMISC ); + _TVCreateFiltersA(hGenre , IDS_GENRE_SPORTSFOOTBALL, hFilterSportsfootball, nLoadMenuGenreFilter & GBF_SPORTSFOOTBALL ); + + _TVCreateFiltersB(hRoot , IDS_SEL_HARDWARE, hHardware ); + + _TVCreateFiltersA(hHardware , IDS_SEL_CAVE , hFilterCave , nLoadMenuShowX & MASKCAVE ); + _TVCreateFiltersA(hHardware , IDS_SEL_CPS1 , hFilterCps1 , nLoadMenuShowX & MASKCPS ); + _TVCreateFiltersA(hHardware , IDS_SEL_CPS2 , hFilterCps2 , nLoadMenuShowX & MASKCPS2 ); + _TVCreateFiltersA(hHardware , IDS_SEL_CPS3 , hFilterCps3 , nLoadMenuShowX & MASKCPS3 ); + _TVCreateFiltersA(hHardware , IDS_SEL_GALAXIAN , hFilterGalaxian , nLoadMenuShowX & MASKGALAXIAN ); + _TVCreateFiltersA(hHardware , IDS_SEL_IREM , hFilterIrem , nLoadMenuShowX & MASKIREM ); + _TVCreateFiltersA(hHardware , IDS_SEL_KONAMI , hFilterKonami , nLoadMenuShowX & MASKKONAMI ); + _TVCreateFiltersA(hHardware , IDS_SEL_NEOGEO , hFilterNeogeo , nLoadMenuShowX & MASKNEOGEO ); + _TVCreateFiltersA(hHardware , IDS_SEL_PACMAN , hFilterPacman , nLoadMenuShowX & MASKPACMAN ); + _TVCreateFiltersA(hHardware , IDS_SEL_PGM , hFilterPgm , nLoadMenuShowX & MASKPGM ); + _TVCreateFiltersA(hHardware , IDS_SEL_PSIKYO , hFilterPsikyo , nLoadMenuShowX & MASKPSIKYO ); + _TVCreateFiltersA(hHardware , IDS_SEL_SEGA , hFilterSega , nLoadMenuShowX & MASKSEGA ); + _TVCreateFiltersA(hHardware , IDS_SEL_TAITO , hFilterTaito , nLoadMenuShowX & MASKTAITO ); + _TVCreateFiltersA(hHardware , IDS_SEL_TOAPLAN , hFilterToaplan , nLoadMenuShowX & MASKTOAPLAN ); + _TVCreateFiltersA(hHardware , IDS_SEL_MISCPRE90S , hFilterMiscPre90s , nLoadMenuShowX & MASKMISCPRE90S ); + _TVCreateFiltersA(hHardware , IDS_SEL_MISCPOST90S , hFilterMiscPost90s , nLoadMenuShowX & MASKMISCPOST90S ); + _TVCreateFiltersA(hHardware , IDS_SEL_MEGADRIVE , hFilterMegadrive , nLoadMenuShowX & MASKMEGADRIVE ); + + SendMessage(hFilterList , TVM_EXPAND,TVE_EXPAND, (LPARAM)hRoot); + SendMessage(hFilterList , TVM_EXPAND,TVE_EXPAND, (LPARAM)hHardware); +} + +#define UM_CHECKSTATECHANGE (WM_USER + 100) +#define UM_CLOSE (WM_USER + 101) + +#define _ToggleGameListing(nShowX, nMASK) \ +{ \ + nShowX ^= nMASK; \ + _TreeView_SetCheckState(hFilterList, hItemChanged, (nShowX & nMASK) ? FALSE : TRUE); \ +} + +static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (Msg == WM_INITDIALOG) { + + InitCommonControls(); + + hSelDlg = hDlg; + + SendDlgItemMessage(hDlg, IDC_SCREENSHOT_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + SendDlgItemMessage(hDlg, IDC_SCREENSHOT_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + SendDlgItemMessage(hDlg, IDC_SCREENSHOT2_H, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + SendDlgItemMessage(hDlg, IDC_SCREENSHOT2_V, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL); + + hWhiteBGBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + + hExpand = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_PLUS), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + hCollapse = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_MINUS), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + + hNotWorking = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTWORKING), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + hNotFoundEss = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTFOUND_ESS), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + hNotFoundNonEss = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_TV_NOTFOUND_NON), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + + hDrvIconMiss = (HICON)LoadImage(hAppInst, MAKEINTRESOURCE(IDI_APP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + + TCHAR szOldTitle[1024] = _T(""), szNewTitle[1024] = _T(""); + GetWindowText(hSelDlg, szOldTitle, 1024); + _sntprintf(szNewTitle, 1024, _T(APP_TITLE) _T(SEPERATOR_1) _T("%s"), szOldTitle); + SetWindowText(hSelDlg, szNewTitle); + + hSelList = GetDlgItem(hSelDlg, IDC_TREE1); + + hInfoLabel[0] = GetDlgItem(hSelDlg, IDC_LABELROMNAME); + hInfoLabel[1] = GetDlgItem(hSelDlg, IDC_LABELROMINFO); + hInfoLabel[2] = GetDlgItem(hSelDlg, IDC_LABELSYSTEM); + hInfoLabel[3] = GetDlgItem(hSelDlg, IDC_LABELCOMMENT); + hInfoLabel[4] = GetDlgItem(hSelDlg, IDC_LABELNOTES); + hInfoLabel[5] = GetDlgItem(hSelDlg, IDC_LABELGENRE); + hInfoText[0] = GetDlgItem(hSelDlg, IDC_TEXTROMNAME); + hInfoText[1] = GetDlgItem(hSelDlg, IDC_TEXTROMINFO); + hInfoText[2] = GetDlgItem(hSelDlg, IDC_TEXTSYSTEM); + hInfoText[3] = GetDlgItem(hSelDlg, IDC_TEXTCOMMENT); + hInfoText[4] = GetDlgItem(hSelDlg, IDC_TEXTNOTES); + hInfoText[5] = GetDlgItem(hSelDlg, IDC_TEXTGENRE); + +#if !defined _UNICODE + EnableWindow(GetDlgItem(hDlg, IDC_SEL_ASCIIONLY), FALSE); +#endif + + bool bFoundROMs = false; + for (unsigned int i = 0; i < nBurnDrvCount; i++) { + if (gameAv[i]) { + bFoundROMs = true; + break; + } + } + if (!bFoundROMs) { + RomsDirCreate(hSelDlg); + } + + SetFocus(hSelList); + + RebuildEverything(); + + TreeView_SetItemHeight(hSelList, 20); + + if (nDialogSelect > -1) { + for (unsigned int i = 0; i < nTmpDrvCount; i++) { + if (nBurnDrv[i].nBurnDrvNo == nDialogSelect) { + nBurnDrvActive = nBurnDrv[i].nBurnDrvNo; + TreeView_EnsureVisible(hSelList, nBurnDrv[i].hTreeHandle); + TreeView_Select(hSelList, nBurnDrv[i].hTreeHandle, TVGN_CARET); + break; + } + } + + // hack to load the preview image after a delay + nInitPreviewTimer = SetTimer(hSelDlg, 1, 20, InitPreviewTimerProc); + } + + LONG_PTR Style; + Style = GetWindowLongPtr (GetDlgItem(hSelDlg, IDC_TREE2), GWL_STYLE); + Style |= TVS_CHECKBOXES; + SetWindowLongPtr (GetDlgItem(hSelDlg, IDC_TREE2), GWL_STYLE, Style); + + CreateFilters(); + + EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), FALSE); + bDoIpsPatch = FALSE; + IpsPatchExit(); + + WndInMid(hDlg, hParent); + + HICON hIcon = LoadIcon(hAppInst, MAKEINTRESOURCE(IDI_APP)); + SendMessage(hSelDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); // Set the Game Selection dialog icon. + + return TRUE; + } + + if(Msg == UM_CHECKSTATECHANGE) { + + HTREEITEM hItemChanged = (HTREEITEM)lParam; + + if (hItemChanged == hHardware) { + if ((nLoadMenuShowX & MASKALL) == 0) { + _TreeView_SetCheckState(hFilterList, hItemChanged, FALSE); + + _TreeView_SetCheckState(hFilterList, hFilterCave, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterCps1, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterCps2, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterCps3, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterGalaxian, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterIrem, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterKonami, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterNeogeo, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPacman, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPgm, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPsikyo, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSega, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterToaplan, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterTaito, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMiscPre90s, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMiscPost90s, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMegadrive, FALSE); + + nLoadMenuShowX |= MASKALL; + } else { + _TreeView_SetCheckState(hFilterList, hItemChanged, TRUE); + + _TreeView_SetCheckState(hFilterList, hFilterCave, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterCps1, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterCps2, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterCps3, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterGalaxian, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterIrem, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterKonami, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterNeogeo, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPacman, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPgm, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPsikyo, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSega, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterToaplan, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterTaito, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMiscPre90s, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMiscPost90s, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMegadrive, TRUE); + + nLoadMenuShowX &= 0xfffc0000; + } + } + + if (hItemChanged == hBoardType) { + if ((nLoadMenuBoardTypeFilter & MASKALLBOARD) == 0) { + _TreeView_SetCheckState(hFilterList, hItemChanged, FALSE); + + _TreeView_SetCheckState(hFilterList, hFilterBootleg, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterDemo, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterHack, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterHomebrew, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPrototype, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterGenuine, FALSE); + + nLoadMenuBoardTypeFilter = MASKALLBOARD; + } else { + _TreeView_SetCheckState(hFilterList, hItemChanged, TRUE); + + _TreeView_SetCheckState(hFilterList, hFilterBootleg, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterDemo, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterHack, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterHomebrew, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPrototype, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterGenuine, TRUE); + + nLoadMenuBoardTypeFilter = 0; + } + } + + if (hItemChanged == hFamily) { + if ((nLoadMenuFamilyFilter & MASKALLFAMILY) == 0) { + _TreeView_SetCheckState(hFilterList, hItemChanged, FALSE); + + _TreeView_SetCheckState(hFilterList, hFilterOtherFamily, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMslug, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSf, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterKof, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterDstlk, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterFatfury, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSamsho, FALSE); + _TreeView_SetCheckState(hFilterList, hFilter19xx, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSonicwi, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPwrinst, FALSE); + + nLoadMenuFamilyFilter = MASKALLFAMILY; + } else { + _TreeView_SetCheckState(hFilterList, hItemChanged, TRUE); + + _TreeView_SetCheckState(hFilterList, hFilterOtherFamily, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMslug, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSf, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterKof, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterDstlk, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterFatfury, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSamsho, TRUE); + _TreeView_SetCheckState(hFilterList, hFilter19xx, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSonicwi, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPwrinst, TRUE); + + nLoadMenuFamilyFilter = 0; + } + } + + if (hItemChanged == hGenre) { + if ((nLoadMenuGenreFilter & MASKALLGENRE) == 0) { + _TreeView_SetCheckState(hFilterList, hItemChanged, FALSE); + + _TreeView_SetCheckState(hFilterList, hFilterHorshoot, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterVershoot, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterScrfight, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterVsfight, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterBios, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterBreakout, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterCasino, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterBallpaddle, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMaze, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMinigames, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPinball, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPlatform, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterPuzzle, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterQuiz, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSportsmisc, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterSportsfootball, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMisc, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterMahjong, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterRacing, FALSE); + _TreeView_SetCheckState(hFilterList, hFilterShoot, FALSE); + + nLoadMenuGenreFilter = MASKALLGENRE; + } else { + _TreeView_SetCheckState(hFilterList, hItemChanged, TRUE); + + _TreeView_SetCheckState(hFilterList, hFilterHorshoot, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterVershoot, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterScrfight, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterVsfight, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterBios, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterBreakout, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterCasino, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterBallpaddle, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMaze, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMinigames, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPinball, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPlatform, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterPuzzle, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterQuiz, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSportsmisc, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterSportsfootball, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMisc, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterMahjong, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterRacing, TRUE); + _TreeView_SetCheckState(hFilterList, hFilterShoot, TRUE); + + nLoadMenuGenreFilter = 0; + } + } + + if (hItemChanged == hFilterCave) _ToggleGameListing(nLoadMenuShowX, MASKCAVE); + if (hItemChanged == hFilterCps1) _ToggleGameListing(nLoadMenuShowX, MASKCPS); + if (hItemChanged == hFilterCps2) _ToggleGameListing(nLoadMenuShowX, MASKCPS2); + if (hItemChanged == hFilterCps3) _ToggleGameListing(nLoadMenuShowX, MASKCPS3); + if (hItemChanged == hFilterGalaxian) _ToggleGameListing(nLoadMenuShowX, MASKGALAXIAN); + if (hItemChanged == hFilterIrem) _ToggleGameListing(nLoadMenuShowX, MASKIREM); + if (hItemChanged == hFilterKonami) _ToggleGameListing(nLoadMenuShowX, MASKKONAMI); + if (hItemChanged == hFilterNeogeo) _ToggleGameListing(nLoadMenuShowX, MASKNEOGEO); + if (hItemChanged == hFilterPacman) _ToggleGameListing(nLoadMenuShowX, MASKPACMAN); + if (hItemChanged == hFilterPgm) _ToggleGameListing(nLoadMenuShowX, MASKPGM); + if (hItemChanged == hFilterPsikyo) _ToggleGameListing(nLoadMenuShowX, MASKPSIKYO); + if (hItemChanged == hFilterSega) _ToggleGameListing(nLoadMenuShowX, MASKSEGA); + if (hItemChanged == hFilterToaplan) _ToggleGameListing(nLoadMenuShowX, MASKTOAPLAN); + if (hItemChanged == hFilterTaito) _ToggleGameListing(nLoadMenuShowX, MASKTAITO); + if (hItemChanged == hFilterMiscPre90s) _ToggleGameListing(nLoadMenuShowX, MASKMISCPRE90S); + if (hItemChanged == hFilterMiscPost90s) _ToggleGameListing(nLoadMenuShowX, MASKMISCPOST90S); + if (hItemChanged == hFilterMegadrive) _ToggleGameListing(nLoadMenuShowX, MASKMEGADRIVE); + + if (hItemChanged == hFilterBootleg) _ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_BOOTLEG); + if (hItemChanged == hFilterDemo) _ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_DEMO); + if (hItemChanged == hFilterHack) _ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_HACK); + if (hItemChanged == hFilterHomebrew) _ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_HOMEBREW); + if (hItemChanged == hFilterPrototype) _ToggleGameListing(nLoadMenuBoardTypeFilter, BDF_PROTOTYPE); + if (hItemChanged == hFilterGenuine) _ToggleGameListing(nLoadMenuBoardTypeFilter, MASKBOARDTYPEGENUINE); + + if (hItemChanged == hFilterOtherFamily) _ToggleGameListing(nLoadMenuFamilyFilter, MASKFAMILYOTHER); + if (hItemChanged == hFilterMslug) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_MSLUG); + if (hItemChanged == hFilterSf) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_SF); + if (hItemChanged == hFilterKof) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_KOF); + if (hItemChanged == hFilterDstlk) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_DSTLK); + if (hItemChanged == hFilterFatfury) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_FATFURY); + if (hItemChanged == hFilterSamsho) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_SAMSHO); + if (hItemChanged == hFilter19xx) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_19XX); + if (hItemChanged == hFilterSonicwi) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_SONICWI); + if (hItemChanged == hFilterPwrinst) _ToggleGameListing(nLoadMenuFamilyFilter, FBF_PWRINST); + + if (hItemChanged == hFilterHorshoot) _ToggleGameListing(nLoadMenuGenreFilter, GBF_HORSHOOT); + if (hItemChanged == hFilterVershoot) _ToggleGameListing(nLoadMenuGenreFilter, GBF_VERSHOOT); + if (hItemChanged == hFilterScrfight) _ToggleGameListing(nLoadMenuGenreFilter, GBF_SCRFIGHT); + if (hItemChanged == hFilterVsfight) _ToggleGameListing(nLoadMenuGenreFilter, GBF_VSFIGHT); + if (hItemChanged == hFilterBios) _ToggleGameListing(nLoadMenuGenreFilter, GBF_BIOS); + if (hItemChanged == hFilterBreakout) _ToggleGameListing(nLoadMenuGenreFilter, GBF_BREAKOUT); + if (hItemChanged == hFilterCasino) _ToggleGameListing(nLoadMenuGenreFilter, GBF_CASINO); + if (hItemChanged == hFilterBallpaddle) _ToggleGameListing(nLoadMenuGenreFilter, GBF_BALLPADDLE); + if (hItemChanged == hFilterMaze) _ToggleGameListing(nLoadMenuGenreFilter, GBF_MAZE); + if (hItemChanged == hFilterMinigames) _ToggleGameListing(nLoadMenuGenreFilter, GBF_MINIGAMES); + if (hItemChanged == hFilterPinball) _ToggleGameListing(nLoadMenuGenreFilter, GBF_PINBALL); + if (hItemChanged == hFilterPlatform) _ToggleGameListing(nLoadMenuGenreFilter, GBF_PLATFORM); + if (hItemChanged == hFilterPuzzle) _ToggleGameListing(nLoadMenuGenreFilter, GBF_PUZZLE); + if (hItemChanged == hFilterQuiz) _ToggleGameListing(nLoadMenuGenreFilter, GBF_QUIZ); + if (hItemChanged == hFilterSportsmisc) _ToggleGameListing(nLoadMenuGenreFilter, GBF_SPORTSMISC); + if (hItemChanged == hFilterSportsfootball) _ToggleGameListing(nLoadMenuGenreFilter, GBF_SPORTSFOOTBALL); + if (hItemChanged == hFilterMisc) _ToggleGameListing(nLoadMenuGenreFilter, GBF_MISC); + if (hItemChanged == hFilterMahjong) _ToggleGameListing(nLoadMenuGenreFilter, GBF_MAHJONG); + if (hItemChanged == hFilterRacing) _ToggleGameListing(nLoadMenuGenreFilter, GBF_RACING); + if (hItemChanged == hFilterShoot) _ToggleGameListing(nLoadMenuGenreFilter, GBF_SHOOT); + + RebuildEverything(); + } + + if (Msg == WM_COMMAND) { + if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_SEL_SEARCH) { + RebuildEverything(); + } + + if (HIWORD(wParam) == BN_CLICKED) { + int wID = LOWORD(wParam); + switch (wID) { + case IDOK: + SelOkay(); + break; + case IDROM: + RomsDirCreate(hSelDlg); + RebuildEverything(); + break; + case IDRESCAN: + bRescanRoms = true; + CreateROMInfo(hSelDlg); + RebuildEverything(); + break; + case IDCANCEL: + bDialogCancel = true; + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + case IDC_CHECKAVAILABLEONLY: + nLoadMenuShowX ^= AVAILONLY; + RebuildEverything(); + break; + case IDC_CHECKAUTOEXPAND: + nLoadMenuShowX ^= AUTOEXPAND; + RebuildEverything(); + break; + case IDC_SEL_SHORTNAME: + nLoadMenuShowX ^= SHOWSHORT; + RebuildEverything(); + break; + case IDC_SEL_ASCIIONLY: + nLoadMenuShowX ^= ASCIIONLY; + RebuildEverything(); + break; + case IDROMINFO: + if (bDrvSelected) { + RomInfoDialog(); + } else { + MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK); + } + break; + case IDC_SEL_IPSMANAGER: + if (bDrvSelected) { + IpsManagerCreate(hSelDlg); + LoadIpsActivePatches(); + if (GetIpsNumActivePatches()) { + EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE); + } + SetFocus(hSelList); + } else { + MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SELECTED, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK); + } + break; + case IDC_SEL_APPLYIPS: + bDoIpsPatch = !bDoIpsPatch; + break; + } + } + } + + if (Msg == UM_CLOSE) { + nDialogSelect = nOldDlgSelected; + MyEndDialog(); + DeleteObject(hWhiteBGBrush); + return 0; + } + + if (Msg == WM_CLOSE) { + bDialogCancel = true; + nDialogSelect = nOldDlgSelected; + MyEndDialog(); + DeleteObject(hWhiteBGBrush); + return 0; + } + +// if (Msg == WM_TIMER) { +// UpdatePreview(false, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V); +// return 0; +// } + + if (Msg == WM_CTLCOLORSTATIC) { + for (int i = 0; i < 6; i++) { + if ((HWND)lParam == hInfoLabel[i]) { return (INT_PTR)hWhiteBGBrush; } + if ((HWND)lParam == hInfoText[i]) { return (INT_PTR)hWhiteBGBrush; } + } + } + + NMHDR* pNmHdr = (NMHDR*)lParam; + if (Msg == WM_NOTIFY) + { + if ((pNmHdr->code == NM_CLICK) && (pNmHdr->idFrom == IDC_TREE2)) + { + TVHITTESTINFO thi; + DWORD dwpos = GetMessagePos(); + thi.pt.x = GET_X_LPARAM(dwpos); + thi.pt.y = GET_Y_LPARAM(dwpos); + MapWindowPoints(HWND_DESKTOP, pNmHdr->hwndFrom, &thi.pt, 1); + TreeView_HitTest(pNmHdr->hwndFrom, &thi); + + if(TVHT_ONITEMSTATEICON & thi.flags) { + PostMessage(hSelDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)thi.hItem); + } + + return 1; + } + + NMTREEVIEW* pnmtv = (NMTREEVIEW*)lParam; + + if (!TreeBuilding && pnmtv->hdr.code == NM_DBLCLK && pnmtv->hdr.idFrom == IDC_TREE1) + { + DWORD dwpos = GetMessagePos(); + + TVHITTESTINFO thi; + thi.pt.x = GET_X_LPARAM(dwpos); + thi.pt.y = GET_Y_LPARAM(dwpos); + + MapWindowPoints(HWND_DESKTOP, pNmHdr->hwndFrom, &thi.pt, 1); + + TreeView_HitTest(pNmHdr->hwndFrom, &thi); + + HTREEITEM hSelectHandle = thi.hItem; + if(hSelectHandle == NULL) return 1; + + TreeView_SelectItem(hSelList, hSelectHandle); + + // Search through nBurnDrv[] for the nBurnDrvNo according to the returned hSelectHandle + for (unsigned int i = 0; i < nTmpDrvCount; i++) { + if (hSelectHandle == nBurnDrv[i].hTreeHandle) { + nBurnDrvActive = nBurnDrv[i].nBurnDrvNo; + break; + } + } + + nDialogSelect = nBurnDrvActive; + bDrvSelected = true; + + SelOkay(); + + // disable double-click node-expand + SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, 1); + + return 1; + } + + if (pNmHdr->code == NM_CUSTOMDRAW && LOWORD(wParam) == IDC_TREE1) { + LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; + int nGetTextFlags = nLoadMenuShowX & ASCIIONLY ? DRV_ASCIIONLY : 0; + HTREEITEM hSelectHandle; + + switch (lplvcd->nmcd.dwDrawStage) { + case CDDS_PREPAINT: { + SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW); + return 1; + } + + case CDDS_ITEMPREPAINT: { + hSelectHandle = (HTREEITEM)(lplvcd->nmcd.dwItemSpec); + HBRUSH hBackBrush; + RECT rect; + + // TVITEM (msdn.microsoft.com) This structure is identical to the TV_ITEM structure, but it has been renamed to + // follow current naming conventions. New applications should use this structure. + + //TV_ITEM TvItem; + TVITEM TvItem; + TvItem.hItem = hSelectHandle; + TvItem.mask = TVIF_PARAM | TVIF_STATE | TVIF_CHILDREN; + SendMessage(hSelList, TVM_GETITEM, 0, (LPARAM)&TvItem); + +// dprintf(_T(" - Item (%i×%i) - (%i×%i) %hs\n"), lplvcd->nmcd.rc.left, lplvcd->nmcd.rc.top, lplvcd->nmcd.rc.right, lplvcd->nmcd.rc.bottom, ((NODEINFO*)TvItem.lParam)->pszROMName); + + // Set the foreground and background colours unless the item is highlighted + if (!(TvItem.state & (TVIS_SELECTED | TVIS_DROPHILITED))) { + + // Set less contrasting colours for clones + if (!((NODEINFO*)TvItem.lParam)->bIsParent) { + lplvcd->clrTextBk = RGB(0xD7, 0xD7, 0xD7); + lplvcd->clrText = RGB(0x3F, 0x3F, 0x3F); + } + + // For parents, change the colour of the background, for clones, change only the text colour + if (!CheckWorkingStatus(((NODEINFO*)TvItem.lParam)->nBurnDrvNo)) { + lplvcd->clrText = RGB(0x7F, 0x7F, 0x7F); + } + } + + rect.left = lplvcd->nmcd.rc.left; + rect.right = lplvcd->nmcd.rc.right; + rect.top = lplvcd->nmcd.rc.top; + rect.bottom = lplvcd->nmcd.rc.bottom; + + hBackBrush = CreateSolidBrush(lplvcd->clrTextBk); + + nBurnDrvActive = ((NODEINFO*)TvItem.lParam)->nBurnDrvNo; + + { + // Fill background + FillRect(lplvcd->nmcd.hdc, &lplvcd->nmcd.rc, hBackBrush); + } + + { + // Draw plus and minus buttons + if (((NODEINFO*)TvItem.lParam)->bIsParent) { + if (TvItem.state & TVIS_EXPANDED) { + DrawIconEx(lplvcd->nmcd.hdc, rect.left + 4, rect.top + 0, hCollapse, 16, 16, 0, NULL, DI_NORMAL); + } else { + if (TvItem.cChildren) { + DrawIconEx(lplvcd->nmcd.hdc, rect.left + 4, rect.top + 0, hExpand, 16, 16, 0, NULL, DI_NORMAL); + } + } + } + rect.left += 16 + 8; + } + + rect.top += 2; + + { + // Draw text + + TCHAR szText[1024]; + TCHAR* pszPosition = szText; + TCHAR* pszName; + SIZE size = { 0, 0 }; + + SetTextColor(lplvcd->nmcd.hdc, lplvcd->clrText); + SetBkMode(lplvcd->nmcd.hdc, TRANSPARENT); + + // Display the short name if needed + if (nLoadMenuShowX & SHOWSHORT) { + DrawText(lplvcd->nmcd.hdc, BurnDrvGetText(DRV_NAME), -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER); + rect.left += 16 + 40 + 20 + 10; + } + + { + // Draw icons if needed + if (!CheckWorkingStatus(((NODEINFO*)TvItem.lParam)->nBurnDrvNo)) { + DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotWorking, 16, 16, 0, NULL, DI_NORMAL); + rect.left += 16 + 4; + } else { + if (!(gameAv[((NODEINFO*)TvItem.lParam)->nBurnDrvNo])) { + DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotFoundEss, 16, 16, 0, NULL, DI_NORMAL); + rect.left += 16 + 4; + } else { + if (!(nLoadMenuShowX & AVAILONLY) && !(gameAv[((NODEINFO*)TvItem.lParam)->nBurnDrvNo] & 2)) { + DrawIconEx(lplvcd->nmcd.hdc, rect.left, rect.top, hNotFoundNonEss, 16, 16, 0, NULL, DI_NORMAL); + rect.left += 16 + 4; + } + } + } + } + + _tcsncpy(szText, MangleGamename(BurnDrvGetText(nGetTextFlags | DRV_FULLNAME), false), 1024); + szText[1023] = _T('\0'); + + GetTextExtentPoint32(lplvcd->nmcd.hdc, szText, _tcslen(szText), &size); + + DrawText(lplvcd->nmcd.hdc, szText, -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER); + + // Display extra info if needed + szText[0] = _T('\0'); + + pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME); + while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + if (szText[0]) { + szText[255] = _T('\0'); + + unsigned int r = ((lplvcd->clrText >> 16 & 255) * 2 + (lplvcd->clrTextBk >> 16 & 255)) / 3; + unsigned int g = ((lplvcd->clrText >> 8 & 255) * 2 + (lplvcd->clrTextBk >> 8 & 255)) / 3; + unsigned int b = ((lplvcd->clrText >> 0 & 255) * 2 + (lplvcd->clrTextBk >> 0 & 255)) / 3; + + rect.left += size.cx; + SetTextColor(lplvcd->nmcd.hdc, (r << 16) | (g << 8) | (b << 0)); + DrawText(lplvcd->nmcd.hdc, szText, -1, &rect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER); + } + } + + DeleteObject(hBackBrush); + + SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_SKIPDEFAULT); + return 1; + } + + default: { + SetWindowLongPtr(hSelDlg, DWLP_MSGRESULT, CDRF_DODEFAULT); + return 1; + } + } + } + + if (pNmHdr->code == TVN_ITEMEXPANDING && !TreeBuilding && LOWORD(wParam) == IDC_TREE1) { + SendMessage(hSelList, TVM_SELECTITEM, TVGN_CARET, (LPARAM)((LPNMTREEVIEW)lParam)->itemNew.hItem); + return FALSE; + } + + if (pNmHdr->code == TVN_SELCHANGED && !TreeBuilding && LOWORD(wParam) == IDC_TREE1) { + HTREEITEM hSelectHandle = (HTREEITEM)SendMessage(hSelList, TVM_GETNEXTITEM, TVGN_CARET, ~0U); + + // Search through nBurnDrv[] for the nBurnDrvNo according to the returned hSelectHandle + for (unsigned int i = 0; i < nTmpDrvCount; i++) { + if (hSelectHandle == nBurnDrv[i].hTreeHandle) + { + nBurnDrvActive = nBurnDrv[i].nBurnDrvNo; + nDialogSelect = nBurnDrvActive; + bDrvSelected = true; + UpdatePreview(true, szAppPreviewsPath, IDC_SCREENSHOT_H, IDC_SCREENSHOT_V); + UpdatePreview(false, szAppTitlesPath, IDC_SCREENSHOT2_H, IDC_SCREENSHOT2_V); + break; + } + } + + if (GetIpsNumPatches()) { + if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, IDC_SEL_IPSMANAGER), FALSE); + } + + LoadIpsActivePatches(); + if (GetIpsNumActivePatches()) { + if (!nShowMVSCartsOnly) EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), TRUE); + } else { + EnableWindow(GetDlgItem(hDlg, IDC_SEL_APPLYIPS), FALSE); + } + + // Get the text from the drivers via BurnDrvGetText() + for (int i = 0; i < 6; i++) { + int nGetTextFlags = nLoadMenuShowX & ASCIIONLY ? DRV_ASCIIONLY : 0; + TCHAR szItemText[256]; + szItemText[0] = _T('\0'); + + switch (i) { + case 0: { + bool bBracket = false; + + _stprintf(szItemText, _T("%s"), BurnDrvGetText(DRV_NAME)); + if ((BurnDrvGetFlags() & BDF_CLONE) && BurnDrvGetTextA(DRV_PARENT)) { + int nOldDrvSelect = nBurnDrvActive; + TCHAR* pszName = BurnDrvGetText(DRV_PARENT); + + _stprintf(szItemText + _tcslen(szItemText), _T(" (clone of %s"), BurnDrvGetText(DRV_PARENT)); + + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + if (!_tcsicmp(pszName, BurnDrvGetText(DRV_NAME))) { + break; + } + } + if (nBurnDrvActive < nBurnDrvCount) { + if (BurnDrvGetText(DRV_PARENT)) { + _stprintf(szItemText + _tcslen(szItemText), _T(", uses ROMs from %s"), BurnDrvGetText(DRV_PARENT)); + } + } + nBurnDrvActive = nOldDrvSelect; + bBracket = true; + } else { + if (BurnDrvGetTextA(DRV_PARENT)) { + _stprintf(szItemText + _tcslen(szItemText), _T("%suses ROMs from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_PARENT)); + bBracket = true; + } + } + if (BurnDrvGetTextA(DRV_SAMPLENAME)) { + _stprintf(szItemText + _tcslen(szItemText), _T("%suses samples from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_SAMPLENAME)); + bBracket = true; + } + if (bBracket) { + _stprintf(szItemText + _tcslen(szItemText), _T(")")); + } + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], TRUE); + break; + } + case 1: { + bool bUseInfo = false; + + if (BurnDrvGetFlags() & BDF_PROTOTYPE) { + _stprintf(szItemText + _tcslen(szItemText), _T("prototype")); + bUseInfo = true; + } + if (BurnDrvGetFlags() & BDF_BOOTLEG) { + _stprintf(szItemText + _tcslen(szItemText), _T("%sbootleg"), bUseInfo ? _T(", ") : _T("")); + bUseInfo = true; + } + if (BurnDrvGetFlags() & BDF_HACK) { + _stprintf(szItemText + _tcslen(szItemText), _T("%shack"), bUseInfo ? _T(", ") : _T("")); + bUseInfo = true; + } + if (BurnDrvGetFlags() & BDF_HOMEBREW) { + _stprintf(szItemText + _tcslen(szItemText), _T("%shomebrew"), bUseInfo ? _T(", ") : _T("")); + bUseInfo = true; + } + if (BurnDrvGetFlags() & BDF_DEMO) { + _stprintf(szItemText + _tcslen(szItemText), _T("%sdemo"), bUseInfo ? _T(", ") : _T("")); + bUseInfo = true; + } + _stprintf(szItemText + _tcslen(szItemText), _T("%s%i player%s"), bUseInfo ? _T(", ") : _T(""), BurnDrvGetMaxPlayers(), (BurnDrvGetMaxPlayers() != 1) ? _T("s max") : _T("")); + bUseInfo = true; + if (BurnDrvGetText(DRV_BOARDROM)) { + _stprintf(szItemText + _tcslen(szItemText), _T("%suses board-ROMs from %s"), bUseInfo ? _T(", ") : _T(""), BurnDrvGetText(DRV_BOARDROM)); + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], TRUE); + bUseInfo = true; + } + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], bUseInfo); + break; + } + case 2: { + _stprintf(szItemText, _T("%s (%s, %s hardware)"), BurnDrvGetTextA(DRV_MANUFACTURER) ? BurnDrvGetText(nGetTextFlags | DRV_MANUFACTURER) : _T("unknown"), BurnDrvGetText(DRV_DATE), ((BurnDrvGetHardwareCode() & HARDWARE_SNK_MVS) == HARDWARE_SNK_MVS) ? _T("Neo Geo MVS Cartidge") : BurnDrvGetText(nGetTextFlags | DRV_SYSTEM)); + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], TRUE); + break; + } + case 3: { + TCHAR szText[1024] = _T(""); + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME); + + pszPosition += _sntprintf(szText, 1024, pszName); + + pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME); + while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + if (szText[0]) { + EnableWindow(hInfoLabel[i], TRUE); + } else { + EnableWindow(hInfoLabel[i], FALSE); + } + break; + } + case 4: { + _stprintf(szItemText, _T("%s"), BurnDrvGetTextA(DRV_COMMENT) ? BurnDrvGetText(nGetTextFlags | DRV_COMMENT) : _T("")); + if (BurnDrvGetFlags() & BDF_HISCORE_SUPPORTED) { + _stprintf(szItemText + _tcslen(szItemText), _T("%shigh scores supported"), _tcslen(szItemText) ? _T(", ") : _T("")); + } + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], TRUE); + break; + } + + case 5: { + _stprintf(szItemText, _T("%s"), DecorateGenreInfo()); + SendMessage(hInfoText[i], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + EnableWindow(hInfoLabel[i], TRUE); + break; + } + } + } + } + } + return 0; +} + +int SelDialog(int nMVSCartsOnly, HWND hParentWND) +{ + int nOldSelect = nBurnDrvActive; + + if(bDrvOkay) { + nOldDlgSelected = nBurnDrvActive; + } + + hParent = hParentWND; + nShowMVSCartsOnly = nMVSCartsOnly; + + InitCommonControls(); + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SELNEW), hParent, (DLGPROC)DialogProc); + + hSelDlg = NULL; + hSelList = NULL; + + if (nBurnDrv) { + free(nBurnDrv); + nBurnDrv = NULL; + } + + nBurnDrvActive = nOldSelect; + + return nDialogSelect; +} + +// Rom Info Dialog + +static HWND hTabControl = NULL; + +static INT_PTR CALLBACK RomInfoDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch (Msg) { + case WM_INITDIALOG: { + TCHAR szText[1024] = _T(""); + TCHAR szFullName[1024] = _T(""); + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(DRV_FULLNAME); + + pszPosition += _sntprintf(szText, 1024, pszName); + + pszName = BurnDrvGetText(DRV_FULLNAME); + while ((pszName = BurnDrvGetText(DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + + _tcscpy(szFullName, szText); + _stprintf(szText, _T("%s") _T(SEPERATOR_1) _T("%s"), FBALoadStringEx(hAppInst, IDS_ROMINFO_DIALOGTITLE, true), szFullName); + SetWindowText(hDlg, szText); + + // Setup the tabs + hTabControl = GetDlgItem(hDlg, IDC_TAB1); + + TC_ITEM tcItem; + tcItem.mask = TCIF_TEXT; + + UINT idsString[2] = { IDS_ROMINFO_ROMS, IDS_ROMINFO_SAMPLES }; + + for(int nIndex = 0; nIndex < 2; nIndex++) { + tcItem.pszText = FBALoadStringEx(hAppInst, idsString[nIndex], true); + TabCtrl_InsertItem(hTabControl, nIndex, &tcItem); + } + + // Set up the rom info list + HWND hList = GetDlgItem(hDlg, IDC_LIST1); + LV_COLUMN LvCol; + LV_ITEM LvItem; + + ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT); + + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + LvCol.cx = 200; + LvCol.pszText = _T("Name"); + SendMessage(hList, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol); + LvCol.cx = 100; + LvCol.pszText = _T("Size (bytes)"); + SendMessage(hList, LVM_INSERTCOLUMN , 1, (LPARAM)&LvCol); + LvCol.cx = 100; + LvCol.pszText = _T("CRC32"); + SendMessage(hList, LVM_INSERTCOLUMN , 2, (LPARAM)&LvCol); + LvCol.cx = 200; + LvCol.pszText = _T("Type"); + SendMessage(hList, LVM_INSERTCOLUMN , 3, (LPARAM)&LvCol); + LvCol.cx = 100; + LvCol.pszText = _T("Flags"); + SendMessage(hList, LVM_INSERTCOLUMN , 4, (LPARAM)&LvCol); + LvCol.cx = 100; + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask= LVIF_TEXT; + LvItem.cchTextMax = 256; + int RomPos = 0; + for (int i = 0; i < 0x100; i++) { // assume max 0x100 roms per game + int nRet; + struct BurnRomInfo ri; + char nLen[10] = ""; + char nCrc[8] = ""; + char *szRomName = NULL; + char Type[100] = ""; + char FormatType[100] = ""; + + memset(&ri, 0, sizeof(ri)); + + nRet = BurnDrvGetRomInfo(&ri, i); + nRet += BurnDrvGetRomName(&szRomName, i, 0); + + if (ri.nLen == 0) continue; + if (ri.nType & BRF_BIOS) continue; + + LvItem.iItem = RomPos; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(szRomName, NULL, 0); + SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + + sprintf(nLen, "%d", ri.nLen); + LvItem.iSubItem = 1; + LvItem.pszText = ANSIToTCHAR(nLen, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + sprintf(nCrc, "%08X", ri.nCrc); + if (!(ri.nType & BRF_NODUMP)) { + LvItem.iSubItem = 2; + LvItem.pszText = ANSIToTCHAR(nCrc, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + } + + if (ri.nType & BRF_ESS) sprintf(Type, "%s, Essential", Type); + if (ri.nType & BRF_OPT) sprintf(Type, "%s, Optional", Type); + if (ri.nType & BRF_PRG) sprintf(Type, "%s, Program", Type); + if (ri.nType & BRF_GRA) sprintf(Type, "%s, Graphics", Type); + if (ri.nType & BRF_SND) sprintf(Type, "%s, Sound", Type); + if (ri.nType & BRF_BIOS) sprintf(Type, "%s, BIOS", Type); + + for (int j = 0; j < 98; j++) { + FormatType[j] = Type[j + 2]; + } + + LvItem.iSubItem = 3; + LvItem.pszText = ANSIToTCHAR(FormatType, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + LvItem.iSubItem = 4; + LvItem.pszText = _T(""); + if (ri.nType & BRF_NODUMP) LvItem.pszText = _T("No Dump"); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + RomPos++; + } + + // Check for board roms + if (BurnDrvGetTextA(DRV_BOARDROM)) { + char szBoardName[8] = ""; + unsigned int nOldDrvSelect = nBurnDrvActive; + strcpy(szBoardName, BurnDrvGetTextA(DRV_BOARDROM)); + + for (unsigned int i = 0; i < nBurnDrvCount; i++) { + nBurnDrvActive = i; + if (!strcmp(szBoardName, BurnDrvGetTextA(DRV_NAME))) break; + } + + for (int j = 0; j < 0x100; j++) { + int nRetBoard; + struct BurnRomInfo riBoard; + char nLenBoard[10] = ""; + char nCrcBoard[8] = ""; + char *szBoardRomName = NULL; + char BoardType[100] = ""; + char BoardFormatType[100] = ""; + + memset(&riBoard, 0, sizeof(riBoard)); + + nRetBoard = BurnDrvGetRomInfo(&riBoard, j); + nRetBoard += BurnDrvGetRomName(&szBoardRomName, j, 0); + + if (riBoard.nLen == 0) continue; + + LvItem.iItem = RomPos; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(szBoardRomName, NULL, 0); + SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + + sprintf(nLenBoard, "%d", riBoard.nLen); + LvItem.iSubItem = 1; + LvItem.pszText = ANSIToTCHAR(nLenBoard, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + sprintf(nCrcBoard, "%08X", riBoard.nCrc); + if (!(riBoard.nType & BRF_NODUMP)) { + LvItem.iSubItem = 2; + LvItem.pszText = ANSIToTCHAR(nCrcBoard, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + } + + if (riBoard.nType & BRF_ESS) sprintf(BoardType, "%s, Essential", BoardType); + if (riBoard.nType & BRF_OPT) sprintf(BoardType, "%s, Optional", BoardType); + if (riBoard.nType & BRF_PRG) sprintf(BoardType, "%s, Program", BoardType); + if (riBoard.nType & BRF_GRA) sprintf(BoardType, "%s, Graphics", BoardType); + if (riBoard.nType & BRF_SND) sprintf(BoardType, "%s, Sound", BoardType); + if (riBoard.nType & BRF_BIOS) sprintf(BoardType, "%s, BIOS", BoardType); + + for (int k = 0; k < 98; k++) { + BoardFormatType[k] = BoardType[k + 2]; + } + + LvItem.iSubItem = 3; + LvItem.pszText = ANSIToTCHAR(BoardFormatType, NULL, 0); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + LvItem.iSubItem = 4; + LvItem.pszText = _T(""); + if (riBoard.nType & BRF_NODUMP) LvItem.pszText = _T("No Dump"); + SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&LvItem); + + RomPos++; + } + + nBurnDrvActive = nOldDrvSelect; + } + + // Set up the sample info list + hList = GetDlgItem(hDlg, IDC_LIST2); + + ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT); + + memset(&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + LvCol.cx = 200; + LvCol.pszText = _T("Name"); + SendMessage(hList, LVM_INSERTCOLUMN , 0, (LPARAM)&LvCol); + + memset(&LvItem, 0, sizeof(LvItem)); + LvItem.mask= LVIF_TEXT; + LvItem.cchTextMax = 256; + int SamplePos = 0; + if (BurnDrvGetTextA(DRV_SAMPLENAME) != NULL) { + for (int i = 0; i < 0x100; i++) { // assume max 0x100 samples per game + int nRet; + struct BurnSampleInfo si; + char *szSampleName = NULL; + + memset(&si, 0, sizeof(si)); + + nRet = BurnDrvGetSampleInfo(&si, i); + nRet += BurnDrvGetSampleName(&szSampleName, i, 0); + + if (si.nFlags == 0) continue; + + LvItem.iItem = SamplePos; + LvItem.iSubItem = 0; + LvItem.pszText = ANSIToTCHAR(szSampleName, NULL, 0); + SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + + SamplePos++; + } + } + + ShowWindow(GetDlgItem(hDlg, IDC_LIST1), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDC_LIST2), SW_HIDE); + UpdateWindow(hDlg); + + WndInMid(hDlg, hSelDlg); + SetFocus(hDlg); // Enable Esc=close + return TRUE; + } + + case WM_COMMAND: { + int Id = LOWORD(wParam); + int Notify = HIWORD(wParam); + + if (Id == IDCANCEL && Notify == BN_CLICKED) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + return 0; + } + } + + case WM_NOTIFY: { + NMHDR* pNmHdr = (NMHDR*)lParam; + + if (pNmHdr->code == TCN_SELCHANGE) { + int TabPage = TabCtrl_GetCurSel(hTabControl); + + ShowWindow(GetDlgItem(hDlg, IDC_LIST1), SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_LIST2), SW_HIDE); + + if (TabPage == 0) ShowWindow(GetDlgItem(hDlg, IDC_LIST1), SW_SHOW); + if (TabPage == 1) ShowWindow(GetDlgItem(hDlg, IDC_LIST2), SW_SHOW); + UpdateWindow(hDlg); + + return FALSE; + } + break; + } + + case WM_CLOSE: { + EndDialog(hDlg, 0); + break; + } + } + + return 0; +} + +static int RomInfoDialog() +{ + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_ROMINFO), hSelDlg, (DLGPROC)RomInfoDialogProc); + + SetFocus(hSelList); + + return 1; +} + +// ----------------------------------------------------------------------------- + +static HBITMAP hMVSpreview[6]; +static unsigned int nPrevDrvSelect[6]; + +static void UpdateInfoROMInfo() +{ +// int nGetTextFlags = nLoadMenuShowX & ASCIIONLY ? DRV_ASCIIONLY : 0; + TCHAR szItemText[256] = _T(""); + bool bBracket = false; + + _stprintf(szItemText, _T("%s"), BurnDrvGetText(DRV_NAME)); + if ((BurnDrvGetFlags() & BDF_CLONE) && BurnDrvGetTextA(DRV_PARENT)) { + int nOldDrvSelect = nBurnDrvActive; + TCHAR* pszName = BurnDrvGetText(DRV_PARENT); + + _stprintf(szItemText + _tcslen(szItemText), _T(" (clone of %s"), BurnDrvGetText(DRV_PARENT)); + + for (nBurnDrvActive = 0; nBurnDrvActive < nBurnDrvCount; nBurnDrvActive++) { + if (!_tcsicmp(pszName, BurnDrvGetText(DRV_NAME))) { + break; + } + } + if (nBurnDrvActive < nBurnDrvCount) { + if (BurnDrvGetText(DRV_PARENT)) { + _stprintf(szItemText + _tcslen(szItemText), _T(", uses ROMs from %s"), BurnDrvGetText(DRV_PARENT)); + } + } + nBurnDrvActive = nOldDrvSelect; + bBracket = true; + } else { + if (BurnDrvGetTextA(DRV_PARENT)) { + _stprintf(szItemText + _tcslen(szItemText), _T("%suses ROMs from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_PARENT)); + bBracket = true; + } + } + if (BurnDrvGetText(DRV_BOARDROM)) { + _stprintf(szItemText + _tcslen(szItemText), _T("%suses board-ROMs from %s"), bBracket ? _T(", ") : _T(" ("), BurnDrvGetText(DRV_BOARDROM)); + bBracket = true; + } + if (bBracket) { + _stprintf(szItemText + _tcslen(szItemText), _T(")")); + } + + if (hInfoText[0]) { + SendMessage(hInfoText[0], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + } + if (hInfoLabel[0]) { + EnableWindow(hInfoLabel[0], TRUE); + } + + return; +} + +static void UpdateInfoRelease() +{ + int nGetTextFlags = nLoadMenuShowX & ASCIIONLY ? DRV_ASCIIONLY : 0; + TCHAR szItemText[256] = _T(""); + + _stprintf(szItemText, _T("%s (%s, %s %s)"), BurnDrvGetTextA(DRV_MANUFACTURER) ? BurnDrvGetText(nGetTextFlags | DRV_MANUFACTURER) : _T("unknown"), BurnDrvGetText(DRV_DATE), + BurnDrvGetText(nGetTextFlags | DRV_SYSTEM), (BurnDrvGetHardwareCode() & HARDWARE_PREFIX_CARTRIDGE) ? _T("cartridge") : _T("hardware")); + + if (hInfoText[2]) { + SendMessage(hInfoText[2], WM_SETTEXT, (WPARAM)0, (LPARAM)szItemText); + } + if (hInfoLabel[2]) { + EnableWindow(hInfoLabel[2], TRUE); + } + + return; +} + +static void UpdateInfoGameInfo() +{ + int nGetTextFlags = nLoadMenuShowX & ASCIIONLY ? DRV_ASCIIONLY : 0; + TCHAR szText[1024] = _T(""); + TCHAR* pszPosition = szText; + TCHAR* pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME); + + pszPosition += _sntprintf(szText, 1024, pszName); + + pszName = BurnDrvGetText(nGetTextFlags | DRV_FULLNAME); + while ((pszName = BurnDrvGetText(nGetTextFlags | DRV_NEXTNAME | DRV_FULLNAME)) != NULL) { + if (pszPosition + _tcslen(pszName) - 1024 > szText) { + break; + } + pszPosition += _stprintf(pszPosition, _T(SEPERATOR_2) _T("%s"), pszName); + } + if (BurnDrvGetText(nGetTextFlags | DRV_COMMENT)) { + pszPosition += _sntprintf(pszPosition, szText + 1024 - pszPosition, _T(SEPERATOR_1) _T("%s"), BurnDrvGetText(nGetTextFlags | DRV_COMMENT)); + } + + if (hInfoText[3]) { + SendMessage(hInfoText[3], WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + } + if (hInfoLabel[3]) { + if (szText[0]) { + EnableWindow(hInfoLabel[3], TRUE); + } else { + EnableWindow(hInfoLabel[3], FALSE); + } + } + + return; +} + +static int MVSpreviewUpdateSlot(int nSlot, HWND hDlg) +{ + int nOldSelect = nBurnDrvActive; + + if (nSlot >= 0 && nSlot <= 6) { + hInfoLabel[0] = 0; hInfoLabel[1] = 0; hInfoLabel[2] = 0; hInfoLabel[3] = 0; + hInfoText[0] = GetDlgItem(hDlg, IDC_MVS_TEXTROMNAME1 + nSlot); + hInfoText[1] = 0; + hInfoText[2] = GetDlgItem(hDlg, IDC_MVS_TEXTSYSTEM1 + nSlot); + hInfoText[3] = GetDlgItem(hDlg, IDC_MVS_TEXTCOMMENT1 + nSlot); + + for (int j = 0; j < 4; j++) { + if (hInfoText[j]) { + SendMessage(hInfoText[j], WM_SETTEXT, (WPARAM)0, (LPARAM)_T("")); + } + if (hInfoLabel[j]) { + EnableWindow(hInfoLabel[j], FALSE); + } + } + + nBurnDrvActive = nBurnDrvSelect[nSlot]; + if (nBurnDrvActive < nBurnDrvCount) { + + FILE* fp = OpenPreview(0, szAppTitlesPath); + if (fp) { + hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, fp, 72, 54, 5); + fclose(fp); + } else { + hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, NULL, 72, 54, 4); + } + + UpdateInfoROMInfo(); + UpdateInfoRelease(); + UpdateInfoGameInfo(); + nPrevDrvSelect[nSlot] = nBurnDrvActive; + + } else { + hMVSpreview[nSlot] = PNGLoadBitmap(hDlg, NULL, 72, 54, 4); + SendMessage(hInfoText[0], WM_SETTEXT, (WPARAM)0, (LPARAM)_T("Empty")); + } + + SendDlgItemMessage(hDlg, IDC_MVS_CART1 + nSlot, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hMVSpreview[nSlot]); + } + + nBurnDrvActive = nOldSelect; + + return 0; +} + +static int MVSpreviewEndDialog() +{ + for (int i = 0; i < 6; i++) { + DeleteObject((HGDIOBJ)hMVSpreview[i]); + hMVSpreview[i] = NULL; + } + + return 0; +} + +static INT_PTR CALLBACK MVSpreviewProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM) +{ + switch (Msg) { + case WM_INITDIALOG: { + + nDialogSelect = ~0U; + + for (int i = 0; i < 6; i++) { + nPrevDrvSelect[i] = nBurnDrvSelect[i]; + MVSpreviewUpdateSlot(i, hDlg); + } + + WndInMid(hDlg, hScrnWnd); + + return TRUE; + } + case WM_COMMAND: + if (LOWORD(wParam) == ID_VALUE_CLOSE) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + break; + } + if (HIWORD(wParam) == BN_CLICKED) { + if (LOWORD(wParam) == IDOK) { + if (nPrevDrvSelect[0] == ~0U) { + MessageBox(hSelDlg, FBALoadStringEx(hAppInst, IDS_ERR_NO_DRIVER_SEL_SLOT1, true), FBALoadStringEx(hAppInst, IDS_ERR_ERROR, true), MB_OK); + break; + } + MVSpreviewEndDialog(); + for (int i = 0; i < 6; i++) { + nBurnDrvSelect[i] = nPrevDrvSelect[i]; + } + EndDialog(hDlg, 0); + break; + } + if (LOWORD(wParam) == IDCANCEL) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + break; + } + + if (LOWORD(wParam) >= IDC_MVS_CLEAR1 && LOWORD(wParam) <= IDC_MVS_CLEAR6) { + int nSlot = LOWORD(wParam) - IDC_MVS_CLEAR1; + + nBurnDrvSelect[nSlot] = ~0U; + nPrevDrvSelect[nSlot] = ~0U; + MVSpreviewUpdateSlot(nSlot, hDlg); + break; + } + + if (LOWORD(wParam) >= IDC_MVS_SELECT1 && LOWORD(wParam) <= IDC_MVS_SELECT6) { + int nSlot = LOWORD(wParam) - IDC_MVS_SELECT1; + + nBurnDrvSelect[nSlot] = SelDialog(HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, hDlg); + MVSpreviewUpdateSlot(nSlot, hDlg); + break; + } + } + break; + + case WM_CLOSE: { + MVSpreviewEndDialog(); + for (int i = 0; i < 6; i++) { + nBurnDrvSelect[i] = nPrevDrvSelect[i]; + } + EndDialog(hDlg, 1); + break; + } + } + + return 0; +} + +int SelMVSDialog() +{ + return FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_MVS_SELECT_CARTS), hScrnWnd, (DLGPROC)MVSpreviewProc); +} diff --git a/src/burner/win32/sfactd.cpp b/src/burner/win32/sfactd.cpp new file mode 100644 index 00000000..dafe443e --- /dev/null +++ b/src/burner/win32/sfactd.cpp @@ -0,0 +1,201 @@ +// Burner Shots Factory Test Dialog Rev. 0.02 +// history: +// rev 0.00: hacked together code +// rev 0.01: Added sprite toggle. +// rev 0.02: now uses VidRedraw() +// +// Known Problems: +// Swiching anything causes the frame to advance +// +// "ghosting" that appears on screen is not captured (this is a good thing) + +#include "burner.h" + +static HWND hSFactdlg=NULL; +unsigned char layerBackup; + +static bool bShotsFactory; +static bool bOldPause; + +void ToggleSprite(unsigned char PriNum) +{ + nSpriteEnable^=PriNum; // xor with thisLayer + VidRedraw(); + VidPaint(0); +} + +static int SFactdUpdate() +{ + + CheckDlgButton(hSFactdlg,IDC_CHECK1,(nBurnLayer & 1)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK2,(nBurnLayer & 2)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK3,(nBurnLayer & 4)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK4,(nBurnLayer & 8)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE1,(nSpriteEnable & 0x01)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE2,(nSpriteEnable & 0x02)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE3,(nSpriteEnable & 0x04)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE4,(nSpriteEnable & 0x08)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE5,(nSpriteEnable & 0x10)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE6,(nSpriteEnable & 0x20)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE7,(nSpriteEnable & 0x40)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE8,(nSpriteEnable & 0x80)?BST_CHECKED:BST_UNCHECKED); + return 0; +} + +static int SFactdInit() +{ + layerBackup=nBurnLayer; + bRunPause=1; + CheckDlgButton(hSFactdlg,IDC_CHECK1,(nBurnLayer & 1)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK2,(nBurnLayer & 2)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK3,(nBurnLayer & 4)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_CHECK4,(nBurnLayer & 8)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE1,(nSpriteEnable & 0x01)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE2,(nSpriteEnable & 0x02)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE3,(nSpriteEnable & 0x04)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE4,(nSpriteEnable & 0x08)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE5,(nSpriteEnable & 0x10)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE6,(nSpriteEnable & 0x20)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE7,(nSpriteEnable & 0x40)?BST_CHECKED:BST_UNCHECKED); + CheckDlgButton(hSFactdlg,IDC_SPRITE8,(nSpriteEnable & 0x80)?BST_CHECKED:BST_UNCHECKED); + return 0; +} + + +static int SFactdExit() +{ + nBurnLayer=layerBackup; + nSpriteEnable= 0xFF; + hSFactdlg=NULL; + bShotsFactory = 0; + bRunPause=bOldPause; + GameInpCheckMouse(); + return 0; +} + + +static INT_PTR CALLBACK DialogProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam) +{ + (void)lParam; (void)wParam; (void)hDlg; + + if (Msg==WM_INITDIALOG) + { + hSFactdlg=hDlg; + SFactdInit(); + SFactdUpdate(); + WndInMid(hDlg, hScrnWnd); + SetFocus(hDlg); // Enable Esc=close + return 0; + } + if (Msg==WM_CLOSE) + { + //DestroyWindow(hSFactdlg); + EndDialog(hDlg, 0); + return 0; + } + if (Msg==WM_DESTROY) { SFactdExit(); return 0; } + + if (Msg==WM_COMMAND) + { + int Id=LOWORD(wParam); int Notify=HIWORD(wParam); + if (Id==IDOK && Notify==BN_CLICKED) { SendMessage(hDlg,WM_CLOSE,0,0); return 0; } // cancel=close + if (Id==IDCAPTURE && Notify==BN_CLICKED) + { + if (bDrvOkay) + { + MakeScreenShot(); + SFactdUpdate(); + } + } + if (Id==IDC_CHECK1 && Notify==BN_CLICKED) + { + ToggleLayer(1); + SFactdUpdate(); + } + if (Id==IDC_CHECK2 && Notify==BN_CLICKED) + { + ToggleLayer(2); + SFactdUpdate(); + } + if (Id==IDC_CHECK3 && Notify==BN_CLICKED) + { + ToggleLayer(4); + SFactdUpdate(); + } + if (Id==IDC_CHECK4 && Notify==BN_CLICKED) + { + ToggleLayer(8); + SFactdUpdate(); + } + if (Id==IDC_SPRITE1 && Notify==BN_CLICKED) + { + ToggleSprite(0x01); + SFactdUpdate(); + } + if (Id==IDC_SPRITE2 && Notify==BN_CLICKED) + { + ToggleSprite(0x02); + SFactdUpdate(); + } + if (Id==IDC_SPRITE3 && Notify==BN_CLICKED) + { + ToggleSprite(0x04); + SFactdUpdate(); + } + if (Id==IDC_SPRITE4 && Notify==BN_CLICKED) + { + ToggleSprite(0x08); + SFactdUpdate(); + } + if (Id==IDC_SPRITE5 && Notify==BN_CLICKED) + { + ToggleSprite(0x10); + SFactdUpdate(); + } + if (Id==IDC_SPRITE6 && Notify==BN_CLICKED) + { + ToggleSprite(0x20); + SFactdUpdate(); + } + if (Id==IDC_SPRITE7 && Notify==BN_CLICKED) + { + ToggleSprite(0x40); + SFactdUpdate(); + } + if (Id==IDC_SPRITE8 && Notify==BN_CLICKED) + { + ToggleSprite(0x80); + SFactdUpdate(); + } + + if (Id==IDC_ADVANCE && Notify==BN_CLICKED) + { + VidFrame(); + VidPaint(0); + } + if (bRunPause) { + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + } + } + return 0; +} + + + +int SFactdCreate() +{ + if (bShotsFactory) { + return 1; + } + bShotsFactory = 1; + bOldPause = bRunPause; + bRunPause = 1; + AudBlankSound(); +// hSFactdlg=FBACreateDialog(hAppInst,MAKEINTRESOURCE(IDD_CAPTURE),hScrnWnd,DialogProc); +// if (hSFactdlg==NULL) return 1; +// WndInMid(hSFactdlg,hScrnWnd); +// ShowWindow(hSFactdlg,SW_NORMAL); +// SFactdUpdate(); + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_CAPTURE), hScrnWnd, (DLGPROC)DialogProc); + return 0; +} diff --git a/src/burner/win32/splash.cpp b/src/burner/win32/splash.cpp new file mode 100644 index 00000000..b6171762 --- /dev/null +++ b/src/burner/win32/splash.cpp @@ -0,0 +1,99 @@ +// Splash screen code +#include "burner.h" +#include + +int nSplashTime = 1500; + +static HWND hSplashDlg = NULL; +static HANDLE hSplashThread = NULL; +static unsigned SplashThreadID = 0; + +static clock_t StartTime; + +static INT_PTR CALLBACK SplashProc(HWND hDlg, UINT Msg, WPARAM /*wParam*/, LPARAM /*lParam*/) +{ + if (Msg == WM_INITDIALOG) { + RECT rect; + int x, y; + + hSplashDlg = hDlg; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + x = 304 + GetSystemMetrics(SM_CXDLGFRAME) * 2 + 6; + y = 224 + GetSystemMetrics(SM_CYDLGFRAME) * 2 + 6; + + SetForegroundWindow(hDlg); + SetWindowPos(hDlg, HWND_TOPMOST, (rect.right - rect.left) / 2 - x / 2, (rect.bottom - rect.top) / 2 - y / 2, x, y, 0); + RedrawWindow(hDlg, NULL, NULL, 0); + ShowWindow(hDlg, SW_SHOWNORMAL); + + return TRUE; + } + + return 0; +} + +static unsigned __stdcall DoSplash(void*) +{ + MSG msg; + + // Raise the thread priority for this thread + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + + CreateDialog(hAppInst, MAKEINTRESOURCE(IDD_SPLASH), NULL, (DLGPROC)SplashProc); + + while (GetMessage(&msg, NULL, 0, 0)) { + + // See if we need to end the thread + if (msg.message == (WM_APP + 0)) { + break; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + DestroyWindow(hSplashDlg); + + return 0; +} + +int SplashCreate() +{ + if (hSplashDlg || !nSplashTime || hSplashThread) { + return 1; + } + + hSplashThread = (HANDLE)_beginthreadex(NULL, 0, DoSplash, NULL, 0, &SplashThreadID); + + StartTime = clock(); + return 0; +} + +void SplashDestroy(bool bForce) +{ + if (hSplashThread) { + + if (!bForce && clock() - nSplashTime < StartTime) { + return; + } + + // Signal the splash thread to end + PostThreadMessage(SplashThreadID, WM_APP + 0, 0, 0); + + // Wait for the thread to finish + if (WaitForSingleObject(hSplashThread, 10000) != WAIT_OBJECT_0) { + // If the thread doesn't finish within 10 seconds, forcibly kill it + TerminateThread(hSplashThread, 1); + } + + hSplashDlg = NULL; + + CloseHandle(hSplashThread); + + hSplashThread = NULL; + SplashThreadID = 0; + + } +} diff --git a/src/burner/win32/stated.cpp b/src/burner/win32/stated.cpp new file mode 100644 index 00000000..01ed5b69 --- /dev/null +++ b/src/burner/win32/stated.cpp @@ -0,0 +1,146 @@ +// State dialog module +#include "burner.h" + +int bDrvSaveAll = 0; + +static void MakeOfn(TCHAR* pszFilter) +{ + _stprintf(pszFilter, FBALoadStringEx(hAppInst, IDS_DISK_FILE_STATE, true), _T(APP_TITLE)); + memcpy(pszFilter + _tcslen(pszFilter), _T(" (*.fs, *.fr)\0*.fs;*.fr\0\0"), 25 * sizeof(TCHAR)); + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFilter = pszFilter; + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T(".\\savestates"); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("fs"); + return; +} + +// The automatic save +int StatedAuto(int bSave) +{ + static TCHAR szName[32] = _T(""); + int nRet; + + _stprintf(szName, _T("config\\games\\%s.fs"), BurnDrvGetText(DRV_NAME)); + + if (bSave == 0) { + nRet = BurnStateLoad(szName, bDrvSaveAll, NULL); // Load ram + if (nRet && bDrvSaveAll) { + nRet = BurnStateLoad(szName, 0, NULL); // Couldn't get all - okay just try the nvram + } + } else { + nRet = BurnStateSave(szName, bDrvSaveAll); // Save ram + } + + return nRet; +} + +static void CreateStateName(int nSlot) +{ + _stprintf(szChoice, _T(".\\savestates\\%s slot %02x.fs"), BurnDrvGetText(DRV_NAME), nSlot); +} + +int StatedLoad(int nSlot) +{ + TCHAR szFilter[1024]; + int nRet; + int bOldPause; + + if (nSlot) { + CreateStateName(nSlot); + } else { + if (bDrvOkay) { + _stprintf(szChoice, _T("%s*.fs"), BurnDrvGetText(DRV_NAME)); + } else { + _stprintf(szChoice, _T("savestate")); + } + MakeOfn(szFilter); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_STATE_LOAD, true); + + bOldPause = bRunPause; + bRunPause = 1; + nRet = GetOpenFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { // Error + return 1; + } + } + + nRet = BurnStateLoad(szChoice, 1, &DrvInitCallback); + + if (nSlot) { + return nRet; + } + + // Describe any possible errors: + if (nRet == 3) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_STATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_UNAVAIL)); + } else { + if (nRet == 4) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_STATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_TOOOLD), _T(APP_TITLE)); + } else { + if (nRet == 5) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_THIS_STATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_TOONEW), _T(APP_TITLE)); + } else { + if (nRet && !nSlot) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_LOAD)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_STATE)); + } + } + } + } + + if (nRet) { + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + return nRet; +} + +int StatedSave(int nSlot) +{ + TCHAR szFilter[1024]; + int nRet; + int bOldPause; + + if (bDrvOkay == 0) { + return 1; + } + + if (nSlot) { + CreateStateName(nSlot); + } else { + _stprintf(szChoice, _T("%s"), BurnDrvGetText(DRV_NAME)); + MakeOfn(szFilter); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_STATE_SAVE, true); + ofn.Flags |= OFN_OVERWRITEPROMPT; + + bOldPause = bRunPause; + bRunPause = 1; + nRet = GetSaveFileName(&ofn); + bRunPause = bOldPause; + + if (nRet == 0) { // Error + return 1; + } + } + + nRet = BurnStateSave(szChoice, 1); + + if (nRet && !nSlot) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_CREATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_STATE)); + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + return nRet; +} diff --git a/src/burner/win32/string.rc b/src/burner/win32/string.rc new file mode 100644 index 00000000..a2fadfe9 --- /dev/null +++ b/src/burner/win32/string.rc @@ -0,0 +1,233 @@ + +STRINGTABLE DISCARDABLE +BEGIN + IDS_FIRSTRUN1 "This appears to be the first time you run %s v%.20s.\n\n" + IDS_FIRSTRUN2 "Please take some time to match the audio/video settings to your system capabilities and personal preferences. If you continue to use and/or distribute this software, you must agree to be bound by the terms of license agreement, which is always accessible via the about dialog.\n\n" + IDS_FIRSTRUN3A "Note that this is alpha quality software. As such, it likely will exhibit problems, including audio/video options not behaving correctly, the emulation of some games misses some features, and may exhibit stability problems. CAVEAT LECTOR!" + IDS_FIRSTRUN3B "Note that this is beta quality software. As such, it likely may be missing some features, or exhibit some problems with your system." + + IDS_CHEAT_NAME "Cheat name" + IDS_CHEAT_STATUS "Status" + + IDS_INPUT_INPUT "Game input" + IDS_INPUT_MAPPING "Mapped to" + IDS_INPUT_STATE "State" + IDS_INPUT_INP_PLAYER "Player %i" + IDS_INPUT_INP_KEYBOARD "Keyboard" + IDS_INPUT_INP_JOYSTICK "Joystick %i" + IDS_INPUT_INP_XARCADEL "X-Arcade (left side)" + IDS_INPUT_INP_XARCADER "X-Arcade (right side)" + IDS_INPUT_INP_HOTRODL "Hot Rod (left side)" + IDS_INPUT_INP_HOTRODR "Hot Rod (right side)" + IDS_INPUT_ANALOG_ABS "Absolute" + IDS_INPUT_ANALOG_AUTO "Auto-center" + IDS_INPUT_ANALOG_NORMAL "Normal" + + IDS_DIP_GROUP "DIPSwitch group" + IDS_DIP_SETTING "Setting" + + IDS_INPSET_MOVENAME "Move control or press key for %.100hs" + IDS_INPSET_MOVE "Move control or press key" + IDS_INPSET_WAITING "Waiting for %.80s to be released..." + + IDS_MEMCARD_CREATE "Create new memory card" + IDS_MEMCARD_SELECT "Select new memory card" + + IDS_PROGRESS_LOADING "Loading and initialising %s..." + + IDS_REPLAY_RECORD "Record Input to File" + IDS_REPLAY_REPLAY "Replay Input from File" + + IDS_ROMS_SELECT_DIR "Select Directory:" + + IDS_STATE_LOAD "Load State" + IDS_STATE_SAVE "Save State" + IDS_STATE_ACTIVESLOT "slot %d active" + IDS_STATE_LOADED "state loaded" + IDS_STATE_LOAD_ERROR "load error" + IDS_STATE_SAVED "state saved" + IDS_STATE_SAVE_ERROR "save error" + + IDS_DAT_GENERATE "Generate %s dat" + IDS_SCRN_NOGAME "no game loaded" + + IDS_NETPLAY_START "*** Starting netplay: " + IDS_NETPLAY_START_YOU "*** You are player %i. " + IDS_NETPLAY_START_TOTAL "There are %i total players." + IDS_NETPLAY_DROP "*** Player %1i «%.32hs» dropped from the game." + IDS_NETPLAY_TOOMUCH "too much text" + + IDS_SSHOT_SAVED "PNG saved" + IDS_SSHOT_ERROR "PNG error %1d" + + IDS_SOUND_NOVOLUME "No volume control" + IDS_SOUND_VOLUMESET "volume %03i %%" + IDS_SOUND_MUTE "Silence" + IDS_SOUND_MUTE_OFF "Sound Restored" + + IDS_DISK_REPLAY "This input recording" + IDS_DISK_THIS_REPLAY "input recording." + IDS_DISK_FILE_REPLAY "%s Input Recording Files" + IDS_DISK_STATE "state file" + IDS_DISK_THIS_STATE "This state file" + IDS_DISK_FILE_STATE "%s State Files" + IDS_DISK_FILE_PATCH "%s Patch Files" + IDS_DISK_SOUND "sound recording" + IDS_DISK_THIS_SOUND "This sound recording" + IDS_DISK_FILE_SOUND "%s Sound Recording Files" + IDS_DISK_FILE_CARD "%s Memory Card Files" + IDS_DISK_ALL_CARD "All Memory Card Files" + IDS_DISK_ALL_DAT "All Dat Files" + IDS_DISK_TEXT "Text Files" + + IDS_DISK_SAVEREPORT "Save system information report" + + IDS_GAMELANG_LOAD "Select game list localisation template" + IDS_GAMELANG_EXPORT "Create game list localisation template" + + IDS_ROMINFO_DIALOGTITLE "Rom Information" + IDS_ROMINFO_ROMS "Rom Info" + IDS_ROMINFO_SAMPLES "Sample Info" + + IDS_SPATH_PREVIEW "Previews" + IDS_SPATH_TITLES "Titles" + IDS_SPATH_CHEATS "Cheats" + IDS_SPATH_HISCORE "High Scores" + IDS_SPATH_SAMPLES "Samples" + IDS_SPATH_IPS "IPS" + IDS_SPATH_NGCD_ISOS "Neo Geo CDZ Games" + IDS_SPATH_NGCD_COVERS "Neo Geo CDZ Covers" + + IDS_ROMPATH_1 "Path #1" + IDS_ROMPATH_2 "Path #2" + IDS_ROMPATH_3 "Path #3" + IDS_ROMPATH_4 "Path #4" + IDS_ROMPATH_5 "Path #5" + IDS_ROMPATH_6 "Path #6" + IDS_ROMPATH_7 "Path #7" + IDS_ROMPATH_8 "Path #8" + + IDS_PRESET_SAVED "The preset file was saved to %s." + + IDS_CD_SELECT_IMAGE "Select CD-ROM image..." + + IDS_MENU + 0 "&Arcade" + IDS_MENU + 1 "&Other..." + IDS_MENU + 2 "&Other Gamma value..." + IDS_MENU + 3 "Adjust &CPU speed..." + IDS_MENU + 4 "Load state from active slot (no %d)\tF9" + IDS_MENU + 5 "Save state to active slot (no %d)\tF10" + + IDS_SEL_FILTERS "Filters" + IDS_SEL_HARDWARE "Hardware" + IDS_SEL_CAVE "Cave" + IDS_SEL_CPS1 "CPS-1" + IDS_SEL_CPS2 "CPS-2" + IDS_SEL_CPS3 "CPS-3" + IDS_SEL_NEOGEO "Neo Geo" + IDS_SEL_PGM "PGM" + IDS_SEL_PSIKYO "Psikyo" + IDS_SEL_SEGA "Sega" + IDS_SEL_TAITO "Taito" + IDS_SEL_TOAPLAN "Toaplan" + IDS_SEL_MISCPRE90S "Misc (pre 90s)" + IDS_SEL_MISCPOST90S "Misc (post 90s)" + IDS_SEL_MEGADRIVE "Megadrive" + IDS_SEL_PACMAN "Pacman" + IDS_SEL_KONAMI "Konami" + IDS_SEL_GALAXIAN "Galaxian" + IDS_SEL_IREM "Irem" + IDS_SEL_BOARDTYPE "Board Type" + IDS_SEL_BOOTLEG "Bootleg" + IDS_SEL_PROTOTYPE "Prototype" + IDS_SEL_HACK "Hack" + IDS_SEL_HOMEBREW "Homebrew" + IDS_SEL_DEMO "Demo" + IDS_SEL_GENUINE "Genuine" + + IDS_GENRE "Genre" + IDS_GENRE_HORSHOOT "Shooter - Horizontal" + IDS_GENRE_VERSHOOT "Shooter - Vertical" + IDS_GENRE_SCRFIGHT "Fighter - Scrolling" + IDS_GENRE_VSFIGHT "Fighter - Versus" + IDS_GENRE_BIOS "BIOS" + IDS_GENRE_BREAKOUT "Breakout" + IDS_GENRE_CASINO "Casino" + IDS_GENRE_BALLPADDLE "Ball & Paddle" + IDS_GENRE_MAZE "Maze" + IDS_GENRE_MINIGAMES "Mini-Games" + IDS_GENRE_PINBALL "Pinball" + IDS_GENRE_PLATFORM "Platform" + IDS_GENRE_PUZZLE "Puzzle" + IDS_GENRE_QUIZ "Quiz" + IDS_GENRE_SPORTSMISC "Sports - Misc" + IDS_GENRE_SPORTSFOOTBALL "Sports - Football" + IDS_GENRE_MISC "Misc" + IDS_GENRE_MAHJONG "Mahjong" + IDS_GENRE_RACING "Racing" + IDS_GENRE_SHOOT "Shooter - Other" + + IDS_FAMILY "Family" + IDS_FAMILY_MSLUG "Metal Slug" + IDS_FAMILY_SF "Street Fighter" + IDS_FAMILY_KOF "King of Fighters" + IDS_FAMILY_DSTLK "Darkstalkers" + IDS_FAMILY_FATFURY "Fatal Fury" + IDS_FAMILY_SAMSHO "Samurai Shodown" + IDS_FAMILY_19XX "19XX" + IDS_FAMILY_SONICWI "Aero Fighters" + IDS_FAMILY_PWRINST "Power Instinct" + IDS_FAMILY_OTHER "Other" + + IDS_IPSMANAGER_TITLE "IPS Patch Manager" + + IDS_ERR_ERROR "Error" + IDS_ERR_WARNING "Warning" + IDS_ERR_INFORMATION "Information" + IDS_ERR_UNKNOWN "Unknown" + + IDS_ERR_LOAD_OK "The ROMset is OK." + IDS_ERR_LOAD_PROBLEM "The ROMset exhibits the following problems:" + IDS_ERR_LOAD_NODATA "No data was found, the game will not run!" + IDS_ERR_LOAD_ESS_MISS "essential data is missing, the game will not run!" + IDS_ERR_LOAD_ESS_BAD "essential data is invalid, the game might not run!" + IDS_ERR_LOAD_DATA_MISS "data is missing." + IDS_ERR_LOAD_DATA_BAD "data is invalid." + IDS_ERR_LOAD_FOUND "%.32hs was found (%.512s).\n" + IDS_ERR_LOAD_NOTFOUND "%.32hs was not found.\n" + IDS_ERR_LOAD_INVALID "The following ROMs are invalid:\n" + IDS_ERR_LOAD_CRC "%.32hs has a CRC of %.8X (correct is %.8X).\n" + IDS_ERR_LOAD_SMALL "%.32hs is %dk which is too small (correct is %dkB).\n" + IDS_ERR_LOAD_LARGE "%.32hs is %dk which is too large (correct is %dkB).\n" + IDS_ERR_LOAD_DET_ESS "essential " + IDS_ERR_LOAD_DET_PRG "program " + IDS_ERR_LOAD_DET_BIOS "BIOS " + IDS_ERR_LOAD_DET_GRA "graphics " + IDS_ERR_LOAD_DET_SND "sound " + IDS_ERR_LOAD_DET_ROM "ROM " + IDS_ERR_LOAD_DISK "Error reading %.32hs from %.512s" + IDS_ERR_LOAD_DISK_CRC "CRC mismatch reading %.32hs from %.512s" + IDS_ERR_LOAD_REQUEST "Error loading %.32hs, requested by %.128s.\nThe emulation will likely suffer problems." + + IDS_ERR_BURN_INIT "There was a problem starting '%.128s'.\n" + + IDS_ERR_UI_NOSUPPORT "%.32s is not supported by %.32s." + IDS_ERR_UI_WINDOW "Couldn't create main window." + IDS_ERR_UI_MODULE "Couldn't intialise '%s' module." + IDS_ERR_UI_TRIPLE "Couldn't create a triple buffer." + IDS_ERR_UI_FULL_NOMODE "No appropriate display mode supported. Please adjust your full-screen settings." + IDS_ERR_UI_FULL_PROBLEM "Problem setting '%dx%dx%dbpp (%dHz)' display mode" + IDS_ERR_UI_FULL_CUSTRES "\n\nThis is not a standard VGA resolution; please make sure it is supported by your video card." + + IDS_ERR_DISK_CREATE "Error creating " + IDS_ERR_DISK_LOAD "Error loading " + IDS_ERR_DISK_UNAVAIL " is for an unavailable game." + IDS_ERR_DISK_TOONEW " does not work with this version of %s." + IDS_ERR_DISK_TOOOLD " requires a more recent version of %s, please upgrade." + + IDS_ERR_NO_NETPLAYDLL "Error finding 'kailleraclient.dll'." + + IDS_ERR_NO_DRIVER_SELECTED "No driver has been selected from the list." + + IDS_ERR_NO_DRIVER_SEL_SLOT1 "No driver has been selected for slot 1." +END diff --git a/src/burner/win32/support_paths.cpp b/src/burner/win32/support_paths.cpp new file mode 100644 index 00000000..f4f9cea5 --- /dev/null +++ b/src/burner/win32/support_paths.cpp @@ -0,0 +1,184 @@ +#include "burner.h" +#include + +static HWND hTabControl = NULL; +static int nInitTabSelect = 0; +static HWND hParent = NULL; + +TCHAR szAppPreviewsPath[MAX_PATH] = _T("support\\previews\\"); +TCHAR szAppTitlesPath[MAX_PATH] = _T("support\\titles\\"); +TCHAR szAppCheatsPath[MAX_PATH] = _T("support\\cheats\\"); +TCHAR szAppHiscorePath[MAX_PATH] = _T("support\\hiscores\\"); +TCHAR szAppSamplesPath[MAX_PATH] = _T("support\\samples\\"); +TCHAR szAppIpsPath[MAX_PATH] = _T("support\\ips\\"); + +static INT_PTR CALLBACK DefInpProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + int var; + + switch (Msg) { + case WM_INITDIALOG: { + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT1, szAppPreviewsPath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT2, szAppTitlesPath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT3, szAppCheatsPath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT4, szAppHiscorePath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT5, szAppSamplesPath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT6, szAppIpsPath); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT7, szNeoCDGamesDir); + SetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT8, szNeoCDCoverDir); + + // Setup the tabs + hTabControl = GetDlgItem(hDlg, IDC_SPATH_TAB); + + TC_ITEM tcItem; + tcItem.mask = TCIF_TEXT; + + UINT idsString[8] = { IDS_SPATH_PREVIEW, IDS_SPATH_TITLES, IDS_SPATH_CHEATS, IDS_SPATH_HISCORE, IDS_SPATH_SAMPLES, IDS_SPATH_IPS, IDS_SPATH_NGCD_ISOS, IDS_SPATH_NGCD_COVERS }; + + for(int nIndex = 0; nIndex < 8; nIndex++) { + tcItem.pszText = FBALoadStringEx(hAppInst, idsString[nIndex], true); + TabCtrl_InsertItem(hTabControl, nIndex, &tcItem); + } + + int TabPage = TabCtrl_GetCurSel(hTabControl); + + // hide all controls excluding the selected controls + for(int x = 0; x < 8; x++) { + if(x != TabPage) { + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + x), SW_HIDE); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + x), SW_HIDE); // edit controls + } + } + + // Show the proper controls + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + TabPage), SW_SHOW); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + TabPage), SW_SHOW); // edit controls + + WndInMid(hDlg, hParent); + SetFocus(hDlg); // Enable Esc=close + + if (nInitTabSelect) { + SendMessage(hTabControl, TCM_SETCURSEL, nInitTabSelect, 0); + // hide all controls excluding the selected controls + for(int x = 0; x < 8; x++) { + if(x != nInitTabSelect) { + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + x), SW_HIDE); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + x), SW_HIDE); // edit controls + } else { + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + x), SW_SHOW); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + x), SW_SHOW); // edit controls + } + } + } + + break; + } + + case WM_NOTIFY: + { + NMHDR* pNmHdr = (NMHDR*)lParam; + + if (pNmHdr->code == TCN_SELCHANGE) { + + int TabPage = TabCtrl_GetCurSel(hTabControl); + + // hide all controls excluding the selected controls + for(int x = 0; x < 8; x++) { + if(x != TabPage) { + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + x), SW_HIDE); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + x), SW_HIDE); // edit controls + } + } + + // Show the proper controls + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_BR1 + TabPage), SW_SHOW); // browse buttons + ShowWindow(GetDlgItem(hDlg, IDC_SUPPORTDIR_EDIT1 + TabPage), SW_SHOW); // edit controls + + UpdateWindow(hDlg); + + return FALSE; + } + break; + } + + case WM_COMMAND: { + LPMALLOC pMalloc = NULL; + BROWSEINFO bInfo; + ITEMIDLIST* pItemIDList = NULL; + TCHAR buffer[MAX_PATH]; + + if (LOWORD(wParam) == IDOK) { + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT1, szAppPreviewsPath, sizeof(szAppPreviewsPath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT2, szAppTitlesPath, sizeof(szAppTitlesPath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT3, szAppCheatsPath, sizeof(szAppCheatsPath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT4, szAppHiscorePath, sizeof(szAppHiscorePath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT5, szAppSamplesPath, sizeof(szAppSamplesPath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT6, szAppIpsPath, sizeof(szAppIpsPath)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT7, szNeoCDGamesDir, sizeof(szNeoCDGamesDir)); + GetDlgItemText(hDlg, IDC_SUPPORTDIR_EDIT8, szNeoCDCoverDir, sizeof(szNeoCDCoverDir)); + + SendMessage(hDlg, WM_CLOSE, 0, 0); + break; + } else { + if (LOWORD(wParam) >= IDC_SUPPORTDIR_BR1 && LOWORD(wParam) <= IDC_SUPPORTDIR_BR8) { + var = IDC_SUPPORTDIR_EDIT1 + LOWORD(wParam) - IDC_SUPPORTDIR_BR1; + } else { + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + break; + } + } + + SHGetMalloc(&pMalloc); + + memset(&bInfo, 0, sizeof(bInfo)); + bInfo.hwndOwner = hDlg; + bInfo.pszDisplayName = buffer; + bInfo.lpszTitle = FBALoadStringEx(hAppInst, IDS_ROMS_SELECT_DIR, true); + bInfo.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS; + + pItemIDList = SHBrowseForFolder(&bInfo); + + if (pItemIDList) { + if (SHGetPathFromIDList(pItemIDList, buffer)) { + int strLen = _tcslen(buffer); + if (strLen) { + if (buffer[strLen - 1] != _T('\\')) { + buffer[strLen] = _T('\\'); + buffer[strLen + 1] = _T('\0'); + } + SetDlgItemText(hDlg, var, buffer); + } + } + pMalloc->Free(pItemIDList); + } + pMalloc->Release(); + + break; + } + + case WM_CLOSE: { + EndDialog(hDlg, 0); + break; + } + } + + return 0; +} + +int SupportDirCreate(HWND hParentWND) +{ + hParent = hParentWND; + + return FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SUPPORTDIR), hParentWND, (DLGPROC)DefInpProc); +} + +int SupportDirCreateTab(int nTab, HWND hParentWND) +{ + nInitTabSelect = nTab - IDC_SUPPORTDIR_EDIT1; + + hParent = hParentWND; + + return FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SUPPORTDIR), hParentWND, (DLGPROC)DefInpProc); +} diff --git a/src/burner/win32/systeminfo.cpp b/src/burner/win32/systeminfo.cpp new file mode 100644 index 00000000..117541cd --- /dev/null +++ b/src/burner/win32/systeminfo.cpp @@ -0,0 +1,1386 @@ +#include "burner.h" +#include "build_details.h" +#include +#include +#include + +// these are not defined in the Cygwin/MinGW winapi package +#ifndef DISPLAY_DEVICE_ACTIVE + #define DISPLAY_DEVICE_ACTIVE 0x00000001 +#endif +#ifndef DISPLAY_DEVICE_ATTACHED + #define DISPLAY_DEVICE_ATTACHED 0x00000002 +#endif + +static _EXCEPTION_POINTERS* pExceptionPointers; + +static TCHAR* pszTextBuffer = NULL; +static int nTextBufferSize = 0; + +static int nRecursion = 0; + +static HFONT hLogFont, hCodeFont; +static HBRUSH hCodeBGBrush; + +static const bool bPrintDriverInfo = false; + +static int AddLine(TCHAR* pszFormat, ...) +{ + TCHAR szString[128] = _T(""); + + va_list vaFormat; + va_start(vaFormat, pszFormat); + + int nLen = _vsntprintf(szString, 70, pszFormat, vaFormat); + nLen = (nLen >= 0 && nLen < 70) ? nLen : 70; + nLen += _stprintf(szString + nLen, _T("\r\n")); + TCHAR* pszNewBuffer = (TCHAR*)realloc(pszTextBuffer, (nLen + nTextBufferSize + 1) * sizeof(TCHAR)); + if (pszNewBuffer) { + pszTextBuffer = pszNewBuffer; + _tcsncpy(pszTextBuffer + nTextBufferSize, szString, nLen); + nTextBufferSize += nLen; + pszTextBuffer[nTextBufferSize] = 0; + } + + va_end(vaFormat); + + return 0; +} + +static int AddText(TCHAR* pszFormat, ...) +{ + TCHAR szString[128] = _T(""); + + va_list vaFormat; + va_start(vaFormat, pszFormat); + + int nLen = _vsntprintf(szString, 70, pszFormat, vaFormat); + nLen = (nLen >= 0 && nLen < 70) ? nLen : 70; + TCHAR* pszNewBuffer = (TCHAR*)realloc(pszTextBuffer, (nLen + nTextBufferSize + 1) * sizeof(TCHAR)); + if (pszNewBuffer) { + pszTextBuffer = pszNewBuffer; + _tcsncpy(pszTextBuffer + nTextBufferSize, szString, nLen); + nTextBufferSize += nLen; + pszTextBuffer[nTextBufferSize] = 0; + } + + va_end(vaFormat); + + return 0; +} + +static int PrintInterfaceInfo(InterfaceInfo* pInfo) +{ + if (pInfo == NULL) { + return 1; + } + + if (pInfo->pszModuleName) { + AddLine(_T(" Selected module: %s"), pInfo->pszModuleName); + } + for (int i = 0; pInfo->ppszInterfaceSettings[i]; i++) { + AddLine(_T(" %s%s"), (i == 0) ? _T("Interface settings: ") : _T(" "), pInfo->ppszInterfaceSettings[i]); + } + for (int i = 0; pInfo->ppszModuleSettings[i]; i++) { + AddLine(_T(" %s%s"), (i == 0) ? _T("Module settings: ") : _T(" "), pInfo->ppszModuleSettings[i]); + } + + return 0; +} + +// Print information about the exception +int PrintExceptionInfo() +{ + static const struct { DWORD ExceptionCode; const TCHAR* szString; } ExceptionString[] = { + +#define EXCEPTION_LIST_ENTRY(exception) { exception, _T(#exception) } + + EXCEPTION_LIST_ENTRY(EXCEPTION_ACCESS_VIOLATION), + EXCEPTION_LIST_ENTRY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), + EXCEPTION_LIST_ENTRY(EXCEPTION_BREAKPOINT), + EXCEPTION_LIST_ENTRY(EXCEPTION_DATATYPE_MISALIGNMENT), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_DENORMAL_OPERAND), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_DIVIDE_BY_ZERO), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_INEXACT_RESULT), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_INVALID_OPERATION), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_OVERFLOW), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_STACK_CHECK), + EXCEPTION_LIST_ENTRY(EXCEPTION_FLT_UNDERFLOW), + EXCEPTION_LIST_ENTRY(EXCEPTION_ILLEGAL_INSTRUCTION), + EXCEPTION_LIST_ENTRY(EXCEPTION_IN_PAGE_ERROR), + EXCEPTION_LIST_ENTRY(EXCEPTION_INVALID_DISPOSITION), + EXCEPTION_LIST_ENTRY(EXCEPTION_INT_DIVIDE_BY_ZERO), + EXCEPTION_LIST_ENTRY(EXCEPTION_INT_OVERFLOW), + EXCEPTION_LIST_ENTRY(EXCEPTION_INVALID_HANDLE), + EXCEPTION_LIST_ENTRY(EXCEPTION_GUARD_PAGE), + EXCEPTION_LIST_ENTRY(EXCEPTION_NONCONTINUABLE_EXCEPTION), + EXCEPTION_LIST_ENTRY(EXCEPTION_PRIV_INSTRUCTION), + EXCEPTION_LIST_ENTRY(EXCEPTION_SINGLE_STEP), + EXCEPTION_LIST_ENTRY(EXCEPTION_STACK_OVERFLOW), + { 0, _T("unspecified exception") } + +#undef EXCEPTION_LIST_ENTRY + + }; + + int i; + + for (i = 0; ExceptionString[i].ExceptionCode; i++) { + if (ExceptionString[i].ExceptionCode == pExceptionPointers->ExceptionRecord->ExceptionCode) { + break; + } + } + + AddLine(_T("Exception 0x%08X (%s) thrown.\r\nEIP: 0x%p"), pExceptionPointers->ExceptionRecord->ExceptionCode, ExceptionString[i].szString, pExceptionPointers->ExceptionRecord->ExceptionAddress); + if (pExceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + AddLine(_T(" (attempting to %s address 0x%p)"), pExceptionPointers->ExceptionRecord->ExceptionInformation[0] ? _T("write") : _T("read"), pExceptionPointers->ExceptionRecord->ExceptionInformation[1]); + } + AddLine(_T("")); + +#ifdef BUILD_X86_ASM + AddLine(_T("EAX: 0x%08X, EBX: 0x%08X, ECX: 0x%08X, EDX: 0x%08X"), (unsigned int)pExceptionPointers->ContextRecord->Eax, (unsigned int)pExceptionPointers->ContextRecord->Ebx, (unsigned int)pExceptionPointers->ContextRecord->Ecx, (unsigned int)pExceptionPointers->ContextRecord->Edx); + AddLine(_T("ESI: 0x%08X, EDI: 0x%08X, ESP: 0x%08X, EBP: 0x%08X"), (unsigned int)pExceptionPointers->ContextRecord->Esi, (unsigned int)pExceptionPointers->ContextRecord->Edi, (unsigned int)pExceptionPointers->ContextRecord->Esp, (unsigned int)pExceptionPointers->ContextRecord->Ebp); +#endif + + return 0; +} + +// Print OS information +int PrintOSInfo() +{ + OSVERSIONINFOEX osvi; + + memset(&osvi, 0, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx((OSVERSIONINFO*)&osvi); + } + + AddText(_T("OS: ")); + { + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { + // http://msdn.microsoft.com/en-us/library/ms724833(VS.85).aspx + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { + AddText(_T("Microsoft Windows 2000 ")); + } + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { + AddText(_T("Microsoft Windows XP ")); + } + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { + AddText(_T("Microsoft Windows 2003 ")); + } + if (osvi.dwMajorVersion < 5 || osvi.dwMinorVersion > 2) { + AddText(_T("Microsoft Windows NT %d.%d "), osvi.dwMajorVersion, osvi.dwMinorVersion); + } + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 && osvi.wProductType == VER_NT_WORKSTATION) { + AddText(_T("Microsoft Windows Vista ")); + } + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 && osvi.wProductType != VER_NT_WORKSTATION) { + AddText(_T("Microsoft Server 2008 ")); + } + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1 && osvi.wProductType != VER_NT_WORKSTATION) { + AddText(_T("Microsoft Server 2008 R2 ")); + } + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1 && osvi.wProductType == VER_NT_WORKSTATION) { + AddText(_T("Microsoft Windows 7 ")); + } + + if (osvi.dwMajorVersion == 5) { + if (osvi.wProductType == VER_NT_WORKSTATION) { + if (osvi.wSuiteMask & VER_SUITE_PERSONAL) { + AddText(_T("Personal ")); + } else { + AddText(_T("Professional ")); + } + } + if (osvi.wProductType == VER_NT_SERVER) { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) { + AddText(_T("DataCenter Server ")); + } else { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) { + AddText(_T("Advanced Server ")); + } else { + AddText(_T("Server ")); + } + } + } + } + AddText(_T("%s (build %i)\r\n"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); + } + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion < 10) { + AddText(_T("Microsoft Windows 95")); + if (osvi.szCSDVersion[1] == _T('B') || osvi.szCSDVersion[1] == _T('C')) { + AddText(_T(" OSR2")); + } + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) { + AddText(_T("Microsoft Windows 98")); + if (osvi.szCSDVersion[1] == _T('A')) { + AddText(_T(" SE")); + } + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) { + AddText(_T("Microsoft Windows Me")); + } + if (osvi.dwMajorVersion != 4 && osvi.dwMinorVersion < 10) { + AddText(_T("Microsoft Windows %d.%d "), osvi.dwMajorVersion, osvi.dwMinorVersion); + } + AddText(_T("\r\n")); + } + } + + return 0; +} + +int PrintCPUInfo() +{ + // Determine the processor type using the CPUID instruction + SYSTEM_INFO si; + unsigned int nSignatureEAX = 0, nSignatureEBX = 0, nVendorEBX = 0, nVendorECX = 0, nVendorEDX = 0; +#if !defined BUILD_X64_EXE + unsigned int nSignatureECX = 0, nSignatureEDX = 0, nVendorEAX = 0; +#endif + bool bMMX = false, bXMMI = false, bXMMI64 = false; + char szCPUText[13] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 }; + TCHAR* szModel = NULL; + DWORD nSpeed = 0; + HKEY hKey; + + AddText(_T("CPU: ")); + + CPUID(0, nVendorEAX, nVendorEBX, nVendorECX, nVendorEDX); + CPUID(0, nVendorEAX, nVendorEBX, nVendorECX, nVendorEDX); + + for (int n = 0; n < 4; n++) { + szCPUText[n + 0] = (nVendorEBX >> (n << 3)) & 255; + szCPUText[n + 4] = (nVendorEDX >> (n << 3)) & 255; + szCPUText[n + 8] = (nVendorECX >> (n << 3)) & 255; + } + + CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); + + if (strcmp("GenuineIntel", szCPUText) == 0) { + switch (nSignatureEAX & 0x0F00) { + case 0x0500: + switch (nSignatureEAX & 0x00F0) { + case 0x040: + case 0x080: { + szModel = _T("Pentium MMX"); + break; + } + default: { + szModel = _T("Pentium"); + } + } + break; + case 0x0600: { + switch (nSignatureEAX & 0x00F0) { + case 0x010: { + szModel = _T("Pentium Pro"); + break; + } + case 0x030: { + szModel = _T("Pentium II \"Klamath\""); + break; + } + case 0x050: { + if (nSignatureEAX & 0x2000) { + szModel = _T("Pentium II Xeon \"Drake\""); + } else { + szModel = _T("Celeron \"Covington\" / Pentium II \"Deschutes\""); + } + break; + } + case 0x060: { + szModel = _T("Celeron A \"Mendochino\" / Mobile Pentium II \"Dixon\""); + break; + } + case 0x070: { + if (nSignatureEAX & 0x2000) { + szModel = _T("Pentium III Xeon \"Tanner\""); + } else { + szModel = _T("Pentium III \"Katmai\""); + } + break; + } + case 0x080: { + switch (nSignatureEBX & 0x0F) { + case 0x01: + szModel = _T("Celeron 2 \"Coppermine\""); + break; + case 0x03: + szModel = _T("Pentium III Xeon \"Coppermine\""); + break; + case 0x06: + szModel = _T("Mobile Pentium III \"Geyserville\""); + break; + case 0x07: + szModel = _T("Mobile Celeron 2 \"Coppermine\""); + break; + default: + szModel = _T("Pentium III \"Coppermine\""); + } + break; + } + case 0x090: { + szModel = _T("Pentium-M \"Banias\""); + break; + } + case 0x0A0: { + szModel = _T("Pentium III Xeon \"Cascades\""); + break; + } + case 0x0B0: { + switch (nSignatureEBX & 0x0F) { + case 0x03: + szModel = _T("Celeron 3 \"Tualatin\""); + break; + default: + szModel = _T("Pentium III \"Tualatin\""); + } + break; + } + default: { + szModel = _T("P6 family"); + } + } + break; + } + case 0x0F00: { + switch (nSignatureEAX & 0x00F0) { + case 0x000: + case 0x010: { + switch (nSignatureEBX & 0x0F) { + case 0x0A: + szModel = _T("Celeron 4 \"Willamette\""); + break; + case 0x0B: + if ((nSignatureEAX & 0xFF) < 0x13) { + szModel = _T("Pentium 4 Xeon MP \"Foster\""); + } else { + szModel = _T("Pentium 4 Xeon \"Foster\""); + } + break; + case 0x0C: + szModel = _T("Pentium 4 Xeon MP \"Foster\""); + break; + case 0x0E: + szModel = _T("Pentium 4 Xeon \"Foster\""); + break; + case 0x0F: + szModel = _T("Mobile Celeron 4 \"Willamette\""); + break; + default: + szModel = _T("Pentium 4 \"Willamette\""); + } + break; + } + case 0x020: { + switch (nSignatureEBX & 0x0F) { + case 0x0A: + szModel = _T("Celeron 4 \"Northwood\""); + break; + case 0x0B: + szModel = _T("Pentium 4 Xeon \"Prestonia\""); + break; + case 0x0C: + szModel = _T("Pentium 4 Xeon MP \"Prestonia\""); + break; + case 0x0E: + szModel = _T("Mobile Pentium 4 M \"Northwood\""); + break; + case 0x0F: + szModel = _T("Mobile Celeron 4 \"Northwood\""); + break; + default: + szModel = _T("Pentium 4 \"Northwood\""); + } + break; + } + case 0x030: { + switch (nSignatureEBX & 0x0F) { + case 0x02: + szModel = _T("Celeron 4 \"Prescott\""); + break; + case 0x03: + szModel = _T("Pentium 4 Xeon \"Nocona\""); + break; + case 0x04: + szModel = _T("Pentium 4 Xeon MP \"Nocona\""); + break; + case 0x06: + szModel = _T("Mobile Pentium 4 M \"Prescott\""); + break; + case 0x07: + szModel = _T("Mobile Celeron 4 \"Prescott\""); + break; + default: + szModel = _T("Pentium 4 \"Prescott\""); + } + break; + } + default: { + szModel = _T("Pentium 4 family"); + } + } + break; + } + } + } + + if (strcmp("AuthenticAMD", szCPUText) == 0) { + switch (nSignatureEAX & 0x0F00) { + case 0x0500: { + switch (nSignatureEAX & 0x00F0) { + case 0x000: + case 0x010: + case 0x020: + case 0x030: + szModel = _T("K5"); + break; + case 0x060: + szModel = _T("K6"); + break; + case 0x070: + szModel = _T("K6-2 \"Little Foot\""); + break; + case 0x080: + szModel = _T("K6-2 \"Chomper\""); + break; + case 0x090: + szModel = _T("K6-III \"Sharptooth\""); + break; + case 0x0D0: + szModel = _T("K6-2+ / K6-III+ \"Sharptooth\""); + break; + default: + szModel = _T("K5 / K6 family"); + } + break; + } + case 0x0600: { + switch (nSignatureEAX & 0x00F0) { + case 0x010: + szModel = _T("Athlon \"Pluto\""); + break; + case 0x020: + szModel = _T("Athlon \"Orion\""); + break; + case 0x030: + szModel = _T("Duron \"Spitfire\""); + break; + case 0x040: + szModel = _T("Athon \"Thunderbird\""); + break; + case 0x060: + if (nSignatureEAX & 0x2000) { + szModel = _T("Athlon MP \"Palomino\""); + } else { + szModel = _T("Mobile Athon 4 / Athon XP \"Palomino\""); + } + break; + case 0x070: + szModel = _T("Mobile Duron \"Camaro\" / Duron \"Morgan\""); + break; + case 0x080: + if (nSignatureEAX & 0x2000) { + szModel = _T("Sempron / Athlon MP \"Thoroughbred\""); + } else { + szModel = _T("Duron \"Applebred\" / Athon XP \"Thoroughbred\""); + } + break; + case 0x0A0: + if (nSignatureEAX & 0x2000) { + szModel = _T("Sempron \"Thorton\" / Athlon MP \"Barton\""); + } else { + // Thorton has 256KB cache, Barton has 512KB + szModel = _T("Athlon XP \"Thorton\" / Athon XP \"Barton\""); + } + break; + default: + szModel = _T("K7 family"); + } + break; + } + case 0x0F00: { + switch (nSignatureEAX & 0x00F0) { + case 0x040: // 1024KB l2 cache, socket 754 + case 0x080: // 256KB l2 cache, socket 754 + case 0x0B0: // 256KB l2 cache, socket 939 + case 0x0C0: // 512KB l2 cache, socket 754 + szModel = _T("Athlon 64 / Athlon 64 Mobile"); + break; + case 0x070: // 1024KB l2 cache, socket 939 + case 0x0F0: // 512KB l2 cache, socket 939 + szModel = _T("Athlon 64 FX / Athlon 64 / Athlon 64 Mobile"); + break; + case 0x050: // 1024KB l2 cache, socket 940 + szModel = _T("Athlon 64 FX / Opteron / Opteron FX"); + break; + default: + szModel = _T("x86-64 family"); + } + break; + } + } + } + + // Get the OS hardware info + GetSystemInfo(&si); + + // Determine speed (read from the registry as there's no reliable way to determine it on modern systems) + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_EXECUTE, &hKey) == ERROR_SUCCESS) { + DWORD nType = REG_DWORD; + DWORD nSize = sizeof(nSpeed); + + RegQueryValueEx(hKey, _T("~MHz"), NULL, &nType, (BYTE*)&nSpeed, &nSize); + RegCloseKey(hKey); + } + + // Determine extensions supported (MMX, etc.) + { + BOOL (WINAPI* pIsProcessorFeaturePresent)(DWORD) = NULL; + HINSTANCE hKernel32DLL; + + hKernel32DLL = LoadLibrary(_T("kernel32.dll")); + if (hKernel32DLL) { + pIsProcessorFeaturePresent = (BOOL (WINAPI*)(DWORD))GetProcAddress(hKernel32DLL, "IsProcessorFeaturePresent"); + if (pIsProcessorFeaturePresent) { + if (pIsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE)) { + bMMX = true; + } + if (pIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) { + bXMMI = true; + } + if (pIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) { + bXMMI64 = true; + } + } + FreeLibrary(hKernel32DLL); + } + } + + // Finally, print out the info + if (szModel) { + AddLine(_T("%12hs, %s"), szCPUText, szModel); + } else { + AddLine(_T("%12hs, Unknown CPU (CPUID 0x%08X:%08X)"), szCPUText, nSignatureEAX, nSignatureEBX); + } + + if (nSpeed) { + AddText(_T(" %i MHz"), nSpeed); + } else { + AddText(_T(" unknown speed")); + } + if (bMMX || bXMMI || bXMMI64) { + AddText(_T("%s%s%s"), bMMX ? _T(", MMX") : _T(""), bXMMI ? _T(", SSE") : _T(""), bXMMI64 ? _T(", SSE2") : _T("")); + } + AddText(_T(" (%i system processor%s)\r\n"), si.dwNumberOfProcessors, si.dwNumberOfProcessors > 1 ? _T("s") : _T("")); + + return 0; +} + +// Print global memory information +int PrintGlobalMemoryInfo() +{ + MEMORYSTATUS stat; + GlobalMemoryStatus(&stat); + + AddLine(_T("Physical RAM: %7i KB (%4i MB) total, %7i KB (%4i MB) avail"), stat.dwTotalPhys / 1024, stat.dwTotalPhys / (1024 * 1024), stat.dwAvailPhys / 1024, stat.dwAvailPhys / (1024 * 1024)); + AddLine(_T("Total RAM: %7i KB (%4i MB) total, %7i KB (%4i MB) avail"), stat.dwTotalPageFile / 1024, stat.dwTotalPageFile / (1024 * 1024), stat.dwAvailPageFile / 1024, stat.dwAvailPageFile / (1024 * 1024)); + + // Information on FB Alpha memory usage + BOOL (WINAPI* pGetProcessMemoryInfo)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD) = NULL; + HINSTANCE hPsapiDLL; + + hPsapiDLL = LoadLibrary(_T("psapi.dll")); + if (hPsapiDLL) { + pGetProcessMemoryInfo = (BOOL (WINAPI*)(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD))GetProcAddress(hPsapiDLL, "GetProcessMemoryInfo"); + if (pGetProcessMemoryInfo) { + PROCESS_MEMORY_COUNTERS pmc; + + if (pGetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { + TCHAR szLine[1024] = _T(""); + int length = _tcslen(_T(APP_TITLE)); + if (length > 12) { + length = 12; + } + _sntprintf(szLine, 12, _T(APP_TITLE)); + _sntprintf(szLine + length, 14 - length, _T(": ")); + AddLine(_T("%s%7i KB in use (%i KB peak, %i KB virtual)"), szLine, pmc.WorkingSetSize / 1024, pmc.PeakWorkingSetSize / 1024, pmc.PagefileUsage / 1024); + } + } + FreeLibrary(hPsapiDLL); + } + + return 0; +} + +// Find the registry key for this display in the hardware area of the registry +// szHardwareID is the PNP ID +// szDriver is the GUID/instance of the driver +HKEY FindMonitor(TCHAR* szHardwareID, TCHAR* szDriver) +{ + TCHAR szName[1024] = _T(""); DWORD nNameSize = sizeof(szName); + TCHAR szClass[1024] = _T(""); DWORD nClassSize = sizeof(szClass); + FILETIME ftLastWriteTime; + HKEY hKey = NULL; + HKEY hMonitorKey = NULL; + + bool bFound = false; + + // We need to enumerate all displays and all instances to check the values inside them + RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\"), 0, KEY_READ, &hKey); + for (int i = 0; !bFound && RegEnumKeyEx(hKey, i, szName, &nNameSize, NULL, szClass, &nClassSize, &ftLastWriteTime) != ERROR_NO_MORE_ITEMS; i++) { + TCHAR szSubName[1024] = _T(""); DWORD nSubNameSize = sizeof(szSubName); + TCHAR szSubClass[1024] = _T(""); DWORD nSubClassSize = sizeof(szSubClass); + FILETIME ftSubLastWriteTime; + HKEY hSubKey = NULL; + + nNameSize = sizeof(szName); + nClassSize = sizeof(szClass); + + RegOpenKeyEx(hKey, szName, 0, KEY_READ, &hSubKey); + for (int j = 0; !bFound && RegEnumKeyEx(hSubKey, j, szSubName, &nSubNameSize, NULL, szSubClass, &nSubClassSize, &ftSubLastWriteTime) != ERROR_NO_MORE_ITEMS; j++) { + HKEY hMonitorInfoKey = NULL; + TCHAR szKeyValue[1024]; DWORD nSize = sizeof(szKeyValue); + DWORD nType; + + nSubNameSize = sizeof(szSubName); + nSubClassSize = sizeof(szSubClass); + + RegOpenKeyEx(hSubKey, szSubName, 0, KEY_READ, &hMonitorKey); + + // Check if this instance is the one we're looking for + nType = REG_SZ; nSize = sizeof(szKeyValue); + RegQueryValueEx(hMonitorKey, _T("HardwareID"), NULL, &nType, (BYTE*)szKeyValue, &nSize); + if (_tcsicmp(szKeyValue, szHardwareID)) { + continue; + } + nType = REG_SZ; nSize = sizeof(szKeyValue); + RegQueryValueEx(hMonitorKey, _T("Driver"), NULL, &nType, (BYTE*)szKeyValue, &nSize); + if (_tcsicmp(szKeyValue, szDriver)) { + continue; + } + + // Make sure the "Device Parameters" key which contains any EDID data is present + RegOpenKeyEx(hMonitorKey, _T("Device Parameters"), 0, KEY_READ, &hMonitorInfoKey); + if (!hMonitorInfoKey) { + continue; + } + + // We've found the display we're looking for + bFound = true; + + RegCloseKey(hMonitorInfoKey); + } + RegCloseKey(hSubKey); + } + RegCloseKey(hKey); + + if (!bFound) { + return NULL; + } + + return hMonitorKey; +} + +int ProcessEDID(HKEY hMonitorKey) +{ + HKEY hMonitorInfoKey = NULL; + BYTE EDIDData[1024]; DWORD nEDIDSize = sizeof(EDIDData); + DWORD nType; + + if (hMonitorKey == NULL) { + return 1; + } + + RegOpenKeyEx(hMonitorKey, _T("Device Parameters"), 0, KEY_READ, &hMonitorInfoKey); + if (hMonitorInfoKey == NULL) { + return 1; + } + + // When Windows can't get valid EDID data from a Display, it creates a BAD_EDID value instead of EDID + // Thus we can forego ensuring the validity of the EDID data ourselves + nType = REG_BINARY; nEDIDSize = sizeof(EDIDData); + if (RegQueryValueEx(hMonitorInfoKey, _T("BAD_EDID"), NULL, &nType, EDIDData, &nEDIDSize) == 0) { + AddLine(_T(" No EDID data present for this device")); + } + nType = REG_BINARY; nEDIDSize = sizeof(EDIDData); + if (RegQueryValueEx(hMonitorInfoKey, _T("EDID"), NULL, &nType, EDIDData, &nEDIDSize) == 0) { + + // Print some basic information about this display + AddLine(_T(" Display size ~%dx%dcm, Gamma %1.2lf"), EDIDData[0x15], EDIDData[0x16], ((double)EDIDData[0x17] + 100.0) / 100.0); + + // Print the preferred mode for this display + if (EDIDData[0x18] & 2) { + int nPixelClock = ((EDIDData[0x36 + 0x01] << 8) | EDIDData[0x36 + 0x00]) * 10000; + + // Size of the display image in pixels (including blanking and sync) + int nActiveH = ((EDIDData[0x36 + 0x04] & 0xF0) << 4) | EDIDData[0x36 + 0x02]; + int nBlankH = ((EDIDData[0x36 + 0x04] & 0x0F) << 8) | EDIDData[0x36 + 0x03]; + int nActiveV = ((EDIDData[0x36 + 0x07] & 0xF0) << 4) | EDIDData[0x36 + 0x05]; + int nBlankV = ((EDIDData[0x36 + 0x07] & 0x0F) << 8) | EDIDData[0x36 + 0x06]; + + // Size of the display image in mm + int nSizeH = ((EDIDData[0x36 + 0x0E] & 0xF0) << 4) | EDIDData[0x36 + 0x0C]; + int nSizeV = ((EDIDData[0x36 + 0x0E] & 0x0F) << 8) | EDIDData[0x36 + 0x0D]; + + // We need to calculate the refresh rate ourselves based on the other numbers + double dRefresh = 1.0 / ((double)(nActiveH + nBlankH) * (nActiveV + nBlankV) / nPixelClock); + + AddLine(_T(" Preferred mode %dx%d, %1.3lf Hz (%dx%dmm, %1.3lf MHz)"), nActiveH, nActiveV, dRefresh, nSizeH, nSizeV, nPixelClock / 1000000.0); + } + + { + // Print the signal limits for this display + + int nLimitsOffset = 0; + + // Find the data block containing the limits + for (int i = 0; i < 4; i++) { + if (EDIDData[0x36 + i * 0x12 + 0] == 0x00 && EDIDData[0x36 + i * 0x12 + 1] == 0x00 && EDIDData[0x36 + i * 0x12 + 2] == 0x00 && EDIDData[0x36 + i * 0x12 + 3] == 0xFD) { + nLimitsOffset = 0x36 + i * 0x12; + break; + } + } + + if (nLimitsOffset) { + AddLine(_T(" Max. bandwidth %d MHz, H sync %d-%d KHz, V sync %d-%d Hz"), EDIDData[nLimitsOffset + 0x09] * 10, EDIDData[nLimitsOffset + 0x07], EDIDData[nLimitsOffset + 0x08], EDIDData[nLimitsOffset + 0x05], EDIDData[nLimitsOffset + 0x06]); + } + } + +#if 0 + { + + // Print the raw data block + BYTE* pData = EDIDData; + + AddText(_T("\r\n Raw EDID data\r\n")); + for (int n = 0; n < 8; n++) { + AddText(_T(" ")); + + for (int m = 0; m < 16; m++) { + AddText(_T("%02X "), *pData & 255); + pData++; + } + AddText(_T("")); + } + AddText(_T("")); + } +#endif + + } + + RegCloseKey(hMonitorInfoKey); + + return 0; +} + +// Print info about displays and display adapters +int PrintDisplayInfo() +{ + BOOL (WINAPI* pEnumDisplayDevices)(LPCTSTR, DWORD, PDISPLAY_DEVICE, DWORD) = NULL; + HINSTANCE hUser32DLL; + + // The EnumDisplayDevices() function is only available on NT based OSes + hUser32DLL = LoadLibrary(_T("user32.dll")); + if (hUser32DLL) { +#if defined (UNICODE) + pEnumDisplayDevices = (BOOL (WINAPI*)(LPCTSTR, DWORD, PDISPLAY_DEVICE, DWORD))GetProcAddress(hUser32DLL, "EnumDisplayDevicesW"); +#else + pEnumDisplayDevices = (BOOL (WINAPI*)(LPCTSTR, DWORD, PDISPLAY_DEVICE, DWORD))GetProcAddress(hUser32DLL, "EnumDisplayDevicesA"); +#endif + if (pEnumDisplayDevices) { + DISPLAY_DEVICE ddAdapter; + DISPLAY_DEVICE ddDisplay; + + ddAdapter.cb = sizeof(DISPLAY_DEVICE); + ddDisplay.cb = sizeof(DISPLAY_DEVICE); + + // Now that we've ensured we can use the EnumDisplayDevices() function, use it to enumerate the connected displays + AddLine(_T("Installed displays and display adapters:")); + + for (int i = 0; pEnumDisplayDevices(NULL, i, &ddAdapter, 0); i++) { + + // We're only interested in real display adapters + if (!(ddAdapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) { + for (int j = 0; pEnumDisplayDevices(ddAdapter.DeviceName, j, &ddDisplay, 0); j++) { + + HKEY hKey = NULL; + HKEY hMonitorKey = NULL; + + TCHAR szMfg[1024] = _T(""); DWORD nMfgSize = sizeof(szMfg); + TCHAR szDeviceDesc[1024] = _T(""); DWORD nDeviceDescSize = sizeof(szDeviceDesc); + + // If the display is active, get the data about it + if (ddDisplay.StateFlags & DISPLAY_DEVICE_ACTIVE) { + if (!_tcsnicmp(ddDisplay.DeviceKey, _T("\\Registry\\Machine\\"), 18)) { + TCHAR szDriver[1024]; DWORD nSize = sizeof(szDriver); + DWORD nType = REG_SZ; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, ddDisplay.DeviceKey + 18, 0, KEY_READ, &hKey); + + // Find the registry key for this display in the hardware area of the registry + RegQueryValueEx(hKey, _T("MatchingDeviceId"), NULL, &nType, (BYTE*)szDriver, &nSize); + hMonitorKey = FindMonitor(szDriver, ddDisplay.DeviceKey + 57); + + RegQueryValueEx(hMonitorKey, _T("DeviceDesc"), NULL, &nType, (BYTE*)szDeviceDesc, &nDeviceDescSize); + RegQueryValueEx(hMonitorKey, _T("Mfg"), NULL, &nType, (BYTE*)szMfg, &nMfgSize); + } + + // Print the information we've got so far + TCHAR* pszStatus = _T(""); + if (ddAdapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { + pszStatus = _T(" (primary)"); + } + if (!(ddAdapter.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) { + pszStatus = _T(" (disabled)"); + } + if (szMfg[0] && szDeviceDesc[0]) { + AddLine(_T(" %s %s on %s%s"), szMfg, szDeviceDesc, ddAdapter.DeviceString, pszStatus); + } else { + AddLine(_T(" %s on %s%s"), ddDisplay.DeviceString, ddAdapter.DeviceString, pszStatus); + } + + ProcessEDID(hMonitorKey); + + if (hMonitorKey) { + RegCloseKey(hMonitorKey); + } + if (hKey) { + RegCloseKey(hKey); + } + } + } + } + } + } + FreeLibrary(hUser32DLL); + } + + return 0; +} + +// Print FB Alpha settings +int PrintFBAInfo() +{ + InterfaceInfo* pInfo; + + AddLine(_T(APP_TITLE) _T(" information:")); + AddLine(_T("")); + + AddLine(_T("Built on ") _T(MAKE_STRING(BUILD_DATE)) _T(", ") _T(MAKE_STRING(BUILD_TIME)) _T(", using ") _T(MAKE_STRING(BUILD_COMP)) _T(".")); + AddLine(_T(" Optimised for ") _T(MAKE_STRING(BUILD_CPU)) _T(" CPUs.")); +#if defined (_UNICODE) + AddLine(_T(" Using Unicode for all text.")); +#else + AddLine(_T(" Using multi-byte characters for all text, active codepage is %d."), GetACP()); +#endif +#if defined (FBA_DEBUG) + AddLine(_T(" Debug functionality present.")); +#else + AddLine(_T(" Debug functionality absent.")); +#endif + AddLine(_T("")); + + AddLine(_T("MMX optimisations %s."), bBurnUseMMX ? _T("enabled") : _T("disabled")); + if (bBurnUseASMCPUEmulation) { + AddLine(_T("A68K emulation core enabled for MC68000 emulation.")); + AddLine(_T("Musashi emulation core enabled for MC68010/MC68EC020 emulation.")); + } else { + AddLine(_T("Musashi emulation core enabled for MC680x0 family emulation.")); + } + AddLine(_T("")); + + if (bDrvOkay) { + TCHAR szName[1024]; + + int n = _stprintf(szName, _T("Emulating %s (%hs)"), BurnDrvGetText(DRV_NAME), DecorateGameName(nBurnDrvActive)); + if (n >= 70) { + _tcscpy(szName + 66, _T("...)")); + } + AddLine(_T("%s"), szName); + AddLine(_T(" Vertical refresh is %.2lf Hz."), (double)nBurnFPS / 100); + AddLine(_T(" CPU running at %i%% of normal frequency."), nBurnCPUSpeedAdjust * 100 / 256); + AddLine(_T("")); + } else { + AddLine(_T("Not emulating any game.")); + AddLine(_T("")); + } + + if ((pInfo = VidGetInfo()) != NULL) { + AddLine(_T("Video settings:")); + PrintInterfaceInfo(pInfo); + } + AddLine(_T("")); + + if ((pInfo = AudGetInfo()) != NULL) { + AddLine(_T("Audio settings:")); + PrintInterfaceInfo(pInfo); + } + AddLine(_T("")); + + if ((pInfo = InputGetInfo()) != NULL) { + AddLine(_T("Input settings:")); + PrintInterfaceInfo(pInfo); + } + AddLine(_T("")); + + if ((pInfo = ProfileGetInfo()) != NULL) { + AddLine(_T("Profiling settings:")); + PrintInterfaceInfo(pInfo); + } + + return 0; +} + +// Print process information +int PrintProcessInfo() +{ +#if 1 + + HANDLE hModuleSnap; + MODULEENTRY32 me32; + + hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + if (hModuleSnap == INVALID_HANDLE_VALUE) { + AddLine(_T("Unable to retrieve detailed process information.")); + } else { + me32.dwSize = sizeof(MODULEENTRY32); + if(!Module32First(hModuleSnap, &me32)) { + AddLine(_T("Unable to retrieve detailed process information.")); + } else { + AddLine(_T("Detailed process information about %s:"), me32.szModule); + AddLine(_T("")); + AddLine(_T("%s (base address 0x%p, size %i KB)"), me32.szModule, me32.modBaseAddr, me32.modBaseSize / 1024); + AddLine(_T("")); + + if (pExceptionPointers) { + bool bFound = false; + do { + if (me32.modBaseAddr <= pExceptionPointers->ExceptionRecord->ExceptionAddress && (me32.modBaseAddr + me32.modBaseSize) > pExceptionPointers->ExceptionRecord->ExceptionAddress) { + bFound = true; + break; + } + } while (Module32Next(hModuleSnap, &me32)); + + if (bFound) { + AddLine(_T("Exception occurred in module %s:"), me32.szModule); + AddLine(_T(" %20s (base address 0x%p, size %6i KB)"), me32.szModule, me32.modBaseAddr, me32.modBaseSize / 1024); + AddLine(_T("")); + } else { + AddLine(_T("Unable to locate module in which exception occurred")); + AddLine(_T("")); + } + } + + Module32First(hModuleSnap, &me32); + AddLine(_T("Modules loaded by %s:"), me32.szModule); + while (Module32Next(hModuleSnap, &me32)){ + AddLine(_T(" %20s (base address 0x%p, size %6i KB)"), me32.szModule, me32.modBaseAddr, me32.modBaseSize / 1024); + } + } + + CloseHandle(hModuleSnap); + } + +#endif + + return 0; +} + +// Print information about installed devices +int PrintDeviceInfo() +{ + // Get a list of all devices that are present and enabled + HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT | DIGCF_PROFILE); + if (hDevInfo != INVALID_HANDLE_VALUE) { + SC_HANDLE (WINAPI* pOpenSCManager)(LPCTSTR, LPCTSTR, DWORD) = NULL; + SC_HANDLE (WINAPI* pOpenService)(SC_HANDLE, LPCTSTR, DWORD) = NULL; + BOOL (WINAPI* pQueryServiceConfig)(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD) = NULL; + BOOL (WINAPI* pCloseServiceHandle)(SC_HANDLE) = NULL; + HINSTANCE hAdvapi32DLL; + + SP_DEVINFO_DATA did; + + hAdvapi32DLL = LoadLibrary(_T("advapi32.dll")); + if (hAdvapi32DLL) { +#if defined (_UNICODE) + pOpenSCManager = (SC_HANDLE (WINAPI*)(LPCTSTR, LPCTSTR, DWORD))GetProcAddress(hAdvapi32DLL, "OpenSCManagerW"); + pOpenService = (SC_HANDLE (WINAPI*)(SC_HANDLE, LPCTSTR, DWORD))GetProcAddress(hAdvapi32DLL, "OpenServiceW"); + pQueryServiceConfig = (BOOL (WINAPI*)(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD))GetProcAddress(hAdvapi32DLL, "QueryServiceConfigW"); +#else + pOpenSCManager = (SC_HANDLE (WINAPI*)(LPCTSTR, LPCTSTR, DWORD))GetProcAddress(hAdvapi32DLL, "OpenSCManagerA"); + pOpenService = (SC_HANDLE (WINAPI*)(SC_HANDLE, LPCTSTR, DWORD))GetProcAddress(hAdvapi32DLL, "OpenServiceA"); + pQueryServiceConfig = (BOOL (WINAPI*)(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD))GetProcAddress(hAdvapi32DLL, "QueryServiceConfigA"); +#endif + pCloseServiceHandle = (BOOL (WINAPI*)(SC_HANDLE))GetProcAddress(hAdvapi32DLL, "CloseServiceHandle"); + } + + AddLine(_T("Installed devices (partial list):")); + AddLine(_T("")); + + // Enumerate all devices in the list + did.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &did); i++) { + TCHAR* list[] = { _T("display"), _T("media"), _T("hid"), _T("hidclass"), _T("mouse"), _T("system"), NULL }; + TCHAR szClass[1024] = _T(""); + + // Get the installer class of a device + SetupDiGetDeviceRegistryProperty(hDevInfo, &did, SPDRP_CLASS, NULL, (BYTE*)szClass, 1024, NULL); + + // determine if the device is of a class we're interested in + for (int j = 0; list[j]; j++) { + if (!_tcsicmp(list[j], szClass)) { + TCHAR szName[1024] = _T(""); + TCHAR szService[1024] = _T(""); + TCHAR szDriverDate[1024] = _T(""); + TCHAR szDriverVersion[1024] = _T(""); + TCHAR szImagePath[1024] = _T(""); + HKEY hKey; + + // Get the device name + SetupDiGetDeviceRegistryProperty(hDevInfo, &did, SPDRP_DEVICEDESC, NULL, (BYTE*)szName, 1024, NULL); + + // Check if there are any lower filter drivers + SetupDiGetDeviceRegistryProperty(hDevInfo, &did, SPDRP_LOWERFILTERS, NULL, (BYTE*)szService, 1024, NULL); + if (szService[0] == _T('\0')) { + // If we haven't got any lower filter drivers, just use the service key + SetupDiGetDeviceRegistryProperty(hDevInfo, &did, SPDRP_SERVICE, NULL, (BYTE*)szService, 1024, NULL); + } + + // Get driver info + hKey = SetupDiOpenDevRegKey(hDevInfo, &did, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); + if (hKey != INVALID_HANDLE_VALUE) { + DWORD nType = REG_SZ; + DWORD nSize = 1024; + + RegQueryValueEx(hKey, _T("DriverVersion"), NULL, &nType, (BYTE*)szDriverVersion, &nSize); + RegQueryValueEx(hKey, _T("DriverDate"), NULL, &nType, (BYTE*)szDriverDate, &nSize); + RegCloseKey(hKey); + } + + // If we have a driver, get the filename + if (szService[0] && pOpenSCManager && pOpenService && pQueryServiceConfig && pCloseServiceHandle) { + SC_HANDLE hSCManager, hService; + QUERY_SERVICE_CONFIG* pSC = NULL; + DWORD nSize; + + hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ); + hService = OpenService(hSCManager, szService, GENERIC_READ); + + QueryServiceConfig(hService, NULL, 0, &nSize); + pSC = (QUERY_SERVICE_CONFIG*)malloc(nSize); + + if (QueryServiceConfig(hService, pSC, nSize, &nSize)) { + _tcscpy(szImagePath, pSC->lpBinaryPathName); + } + + if (pSC) { + free(pSC); + pSC = NULL; + } + + CloseServiceHandle(hService); + CloseServiceHandle(hSCManager); + } + +#if 0 + if (szImagePath[0] == '\0') { + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + // Officially, we shouldn't be doing this, but there's no API for getting this info on Win9x + const TCHAR* pszServices = "SYSTEM\\CurrentControlSet\\Services\\"; + char szFullService[1024] = ""; + + _tcscpy(szFullService, pszServices); + _tcscat(szFullService, szService); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szFullService, 0, KEY_EXECUTE, &hKey) == ERROR_SUCCESS) { + DWORD nType = REG_SZ; + DWORD nSize = 1024; + + RegQueryValueEx(hKey, _T("ImagePath"), NULL, &nType, szImagePath, &nSize); + RegCloseKey(hKey); + } + } + } +#endif + + // Print the information + if (j < 2 || szImagePath[0]) { + AddLine(_T(" %s"), szName); + AddLine(_T(" %s"), szImagePath[0] ? szImagePath : _T("no driver needed")); + + if (szDriverVersion[0]) { + AddLine(_T(" version %s (%s)"), szDriverVersion, szDriverDate[0] ? szDriverDate : _T("no date")); + } + } + + break; + } + } + } + + FreeLibrary(hAdvapi32DLL); + + SetupDiDestroyDeviceInfoList(hDevInfo); + } + + return 0; +} + +static INT_PTR CALLBACK SysInfoProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static int nReturnCode = 0; + + switch (Msg) { + case WM_INITDIALOG: { + time_t nTime; + tm* tmTime; + + nReturnCode = 0; + + pszTextBuffer = NULL; + nTextBufferSize = 0; + + time(&nTime); + tmTime = localtime(&nTime); + + hLogFont = CreateFont(14, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, DEFAULT_QUALITY, FF_MODERN, _T("")); + + hCodeBGBrush = NULL; + hCodeFont = NULL; + + if (pExceptionPointers) { + TCHAR szText[1024] = _T(""); + hCodeBGBrush = CreateSolidBrush(RGB(0,0,0)); + hCodeFont = CreateFont(22, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_MODERN, _T("Lucida Console")); + SendDlgItemMessage(hDlg, IDC_SYSINFO_CODE, WM_SETFONT, (WPARAM)hCodeFont, (LPARAM)0); + + _stprintf(szText, _T("Guru Meditation #%08X.%08X"), pExceptionPointers->ExceptionRecord->ExceptionCode, (INT_PTR)pExceptionPointers->ExceptionRecord->ExceptionAddress); + SendDlgItemMessage(hDlg, IDC_SYSINFO_CODE, WM_SETTEXT, (WPARAM)0, (LPARAM)szText); + + AddLine(_T(APP_TITLE) _T(" v%.20s fatal exception report (%s)."), szAppBurnVer, _tasctime(tmTime)); + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + + // Exception + PrintExceptionInfo(); + } else { + AddLine(_T(APP_TITLE) _T(" v%.20s system information (%s)."), szAppBurnVer, _tasctime(tmTime)); + } + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + + AddLine(_T("System information:")); + AddLine(_T("")); + + // OS information + PrintOSInfo(); + + // CPU information + PrintCPUInfo(); + + AddLine(_T("")); + + // Global memory information + PrintGlobalMemoryInfo(); + + AddLine(_T("")); + + // Displays and display adapters + PrintDisplayInfo(); + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + + PrintFBAInfo(); + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + + // Process information + PrintProcessInfo(); + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + + if (bPrintDriverInfo) { + // Device information + PrintDeviceInfo(); + + AddLine(_T("")); + AddLine(_T("----------------------------------------------------------------------")); + } + + SendDlgItemMessage(hDlg, IDC_SYSINFO_EDIT, WM_SETFONT, (WPARAM)hLogFont, (LPARAM)0); + SendDlgItemMessage(hDlg, IDC_SYSINFO_EDIT, EM_SETMARGINS, (WPARAM)EC_LEFTMARGIN, (LPARAM)3); + SendDlgItemMessage(hDlg, IDC_SYSINFO_EDIT, WM_SETTEXT, (WPARAM)0, (LPARAM)pszTextBuffer); + + WndInMid(hDlg, hScrnWnd); + + return TRUE; + } + + case WM_CLOSE: { + if (pszTextBuffer) { + free(pszTextBuffer); + pszTextBuffer = NULL; + } + nTextBufferSize = 0; + + DeleteObject(hLogFont); + if (hCodeFont) { + DeleteObject(hCodeFont); + } + if (hCodeBGBrush) { + DeleteObject(hCodeBGBrush); + } + EndDialog(hDlg, nReturnCode); + break; + } + + case WM_CTLCOLORSTATIC: { + if ((HWND)lParam == GetDlgItem(hDlg, IDC_SYSINFO_EDIT)) { + return (INT_PTR)GetSysColorBrush(15); + } + if ((HWND)lParam == GetDlgItem(hDlg, IDC_SYSINFO_CODE)) { + SetTextColor((HDC)wParam, RGB(255, 0, 0)); + SetBkMode((HDC)wParam, TRANSPARENT); + return (INT_PTR)hCodeBGBrush; + } + break; + } + + case WM_COMMAND: { + if (HIWORD(wParam) == BN_CLICKED) { + if (LOWORD(wParam) == IDOK) { + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDC_SYSINFO_DEBUG) { + nReturnCode = 1; + SendMessage(hDlg, WM_CLOSE, 0, 0); + } + if (LOWORD(wParam) == IDC_SYSINFO_SHOW && pExceptionPointers) { + RECT rect = { 0, 0, 0, 125 }; + + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_SYSINFO_SHOW), FALSE); + + MapDialogRect(hDlg, &rect); + int nSize = rect.bottom; + GetWindowRect(hDlg, &rect); + MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + nSize, TRUE); + + WndInMid(hDlg, hScrnWnd); + } + if (LOWORD(wParam) == IDC_SYSINFO_LOG) { + FILE* fp = NULL; + + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE); + + if (pExceptionPointers) { + TCHAR szLogName[MAX_PATH]; + _stprintf(szLogName, _T("config\\%s.error.log"), szAppExeName); + fp = _tfopen(szLogName, _T("ab")); + + EnableWindow(GetDlgItem(hDlg, IDC_SYSINFO_LOG), FALSE); + } else { + TCHAR szFilter[1024]; + + _stprintf(szFilter, FBALoadStringEx(hAppInst, IDS_DISK_TEXT, true)); + memcpy(szFilter + _tcslen(szFilter), _T(" (*.txt)\0*.txt\0\0"), 16 * sizeof(TCHAR)); + + _stprintf(szChoice, _T("%s system information.txt"), szAppExeName); + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = szFilter; + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T("."); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.lpstrDefExt = _T("txt"); + ofn.lpstrTitle = FBALoadStringEx(hAppInst, IDS_DISK_SAVEREPORT, true); + + if (GetSaveFileName(&ofn)) { + fp = _tfopen(szChoice, _T("wb")); + } + } + + if (fp) { + TCHAR* szText; + int nSize = SendDlgItemMessage(hDlg, IDC_SYSINFO_EDIT, WM_GETTEXTLENGTH, 0, 0); + szText = (TCHAR*)malloc((nSize + 1) * sizeof(TCHAR)); + +#if defined (_UNICODE) + // write a Unicode Byte Order Mark if needed + if (ftell(fp) == 0) { + WRITE_UNICODE_BOM(fp); + } +#endif + + if (nSize && szText) { + SendDlgItemMessage(hDlg, IDC_SYSINFO_EDIT, WM_GETTEXT, (WPARAM)(nSize + 1) * sizeof(TCHAR), (LPARAM)szText); + fwrite(szText, sizeof(TCHAR), nSize, fp); + _ftprintf(fp, _T("")); + } + if (szText) { + free(szText); + szText = NULL; + } + fclose(fp); + } + } + } + } + } + + return 0; +} + +LONG CALLBACK ExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo) +{ + int nRet; + + // If we're getting recursive calls to this function, bail out + if (nRecursion++) { + if (nRecursion <= 2) { + MessageBox(hScrnWnd, _T(APP_TITLE) _T(" will now be terminated."), _T(APP_TITLE) _T(" Fatal exception"), MB_OK | MB_SETFOREGROUND); + AppCleanup(); + } +#ifdef _DEBUG + return EXCEPTION_CONTINUE_SEARCH; +#else + return EXCEPTION_EXECUTE_HANDLER; +#endif + } + + SplashDestroy(1); + AudSoundStop(); + + pExceptionPointers = pExceptionInfo; + + nRet = FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_EXCEPTION), hScrnWnd, (DLGPROC)SysInfoProc); + + switch (nRet) { + case 1: + return EXCEPTION_CONTINUE_SEARCH; + default: + AppCleanup(); + return EXCEPTION_EXECUTE_HANDLER; + } +} + +int SystemInfoCreate() +{ + pExceptionPointers = NULL; + + FBADialogBox(hAppInst, MAKEINTRESOURCE(IDD_SYSINFO), hScrnWnd, (DLGPROC)SysInfoProc); + + return 0; +} diff --git a/src/burner/win32/version.rc b/src/burner/win32/version.rc new file mode 100644 index 00000000..cd84438a --- /dev/null +++ b/src/burner/win32/version.rc @@ -0,0 +1,95 @@ +#ifdef APSTUDIO_INVOKED + #error This file cannot be edited using the Visual C resource editor +#endif + +#include "build_details.h" + +#ifndef FILENAME + #define FILENAME fba +#endif + +#ifdef MMX + #define MMX_VER ", MMX" +#else + #define MMX_VER +#endif + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VER_MAJOR,VER_MINOR,VER_BETA,VER_ALPHA + PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_BETA,VER_ALPHA + FILEFLAGSMASK 0x3FL +#ifdef SPECIALBUILD + #define SPECIALFLAG VS_FF_SPECIALBUILD +#else + #define SPECIALFLAG 0x0L +#endif +#ifdef _DEBUG + #define DEBUGFLAG VS_FF_DEBUG +#else + #define DEBUGFLAG 0x0L +#endif +#if VER_ALPHA != 0 + FILEFLAGS SPECIALFLAG | DEBUGFLAG | VS_FF_PRIVATEBUILD | VS_FF_PRERELEASE +#else + FILEFLAGS SPECIALFLAG | DEBUGFLAG +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "built on " MAKE_STRING(BUILD_DATE) ", " MAKE_STRING(BUILD_TIME) " (" MAKE_STRING(BUILD_CHAR) ", " MAKE_STRING(BUILD_COMP) ", " MAKE_STRING(BUILD_CPU) MMX_VER ").\0" + VALUE "CompanyName", "Team FB Alpha\0" + VALUE "FileDescription", APP_DESCRIPTION "\0" + VALUE "FileVersion", MAKE_STRING(VER_MAJOR) "," MAKE_STRING(VER_MINOR) "," MAKE_STRING(VER_BETA) "," MAKE_STRING(VER_ALPHA) "\0" + VALUE "InternalName", MAKE_STRING(FILENAME) "\0" + VALUE "LegalCopyright", "© 2004-2011 Team FB Alpha\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", MAKE_STRING(FILENAME) ".exe\0" + #ifdef FBA_DEBUG + #if VER_ALPHA != 0 + VALUE "PrivateBuild", "Pre-release debug build\0" + #else + VALUE "PrivateBuild", "Debug build\0" + #endif +#else + #if VER_ALPHA != 0 + VALUE "PrivateBuild", "Pre-release build\0" + #endif +#endif + VALUE "ProductName", APP_TITLE "\0" +#if VER_BETA == 99 && VER_ALPHA > 90 + VALUE "ProductVersion", "Release Candidate (v" MAKE_STRING(VER_MAJOR) "." MAKE_STRING(VER_MINOR) "." MAKE_STRING(VER_BETA) "." MAKE_STRING(VER_ALPHA) ")\0" +#else + #if VER_ALPHA != 0 + VALUE "ProductVersion", "Pre-release (alpha) version v" MAKE_STRING(VER_MAJOR) "." MAKE_STRING(VER_MINOR) "." MAKE_STRING(VER_BETA) "." MAKE_STRING(VER_ALPHA) "\0" + #else + #if VER_BETA != 0 + VALUE "ProductVersion", "Pre-release (beta) version v" MAKE_STRING(VER_MAJOR) "." MAKE_STRING(VER_MINOR) "." MAKE_STRING(VER_BETA) "." MAKE_STRING(VER_ALPHA) "\0" + #else + VALUE "ProductVersion", "Release version v" MAKE_STRING(VER_MAJOR) "." MAKE_STRING(VER_MINOR) "." MAKE_STRING(VER_BETA) "." MAKE_STRING(VER_ALPHA) "\0" + #endif + #endif +#endif +#ifdef SPECIALBUILD + VALUE "SpecialBuild", MAKE_STRING(SPECIALBUILD) "\0" +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + diff --git a/src/burner/win32/wave.cpp b/src/burner/win32/wave.cpp new file mode 100644 index 00000000..e1fc7f1b --- /dev/null +++ b/src/burner/win32/wave.cpp @@ -0,0 +1,116 @@ +// Wave log module +#include "burner.h" + + +FILE *WaveLog=NULL; // wave log file + + +static void MakeOfn(TCHAR* pszFilter) +{ + _stprintf(pszFilter, FBALoadStringEx(hAppInst, IDS_DISK_FILE_SOUND, true), _T(APP_TITLE)); + memcpy(pszFilter + _tcslen(pszFilter), _T(" (*.wav)\0*.wav\0\0"), 16 * sizeof(TCHAR)); + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hScrnWnd; + ofn.lpstrFilter = pszFilter; + ofn.lpstrFile = szChoice; + ofn.nMaxFile = sizeof(szChoice) / sizeof(TCHAR); + ofn.lpstrInitialDir = _T(".\\wav"); + ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("wav"); + + return; +} + + +// Make a wave header so we can write out raw samples after it to make a wave file +static int WaveLogHeaderStart(FILE *Hand,int nSamRate) +{ + unsigned int ua=0x10; + WORD wFormatTag=1; // PCM + WORD nChannels=0; + DWORD nSamplesPerSec=0,nAvgBytesPerSec=0; + WORD nBlockAlign=0,wBitsPerSample=0; + + nChannels=2; // stereo + nSamplesPerSec=nSamRate; + nAvgBytesPerSec=nSamRate*4; // samrate*2*short + nBlockAlign=4; // 2*short + wBitsPerSample=16; // 16-bit + + if (Hand==NULL) + return 1; + fwrite("RIFF WAVEfmt ",1,0x10,Hand); // fill in 0x04 later + fwrite(&ua,1,sizeof(ua),Hand); + fwrite(&wFormatTag,1,sizeof(wFormatTag),Hand); + fwrite(&nChannels,1,sizeof(nChannels),Hand); + fwrite(&nSamplesPerSec,1,sizeof(nSamplesPerSec),Hand); + fwrite(&nAvgBytesPerSec,1,sizeof(nAvgBytesPerSec),Hand); + fwrite(&nBlockAlign,1,sizeof(nBlockAlign),Hand); + fwrite(&wBitsPerSample,1,sizeof(wBitsPerSample),Hand); + fwrite("data ",1,0x08,Hand); // fill in 0x28 later + return 0; +} + +// Fill in the RIFF and data values +static int WaveLogHeaderFillIn(FILE *Hand) +{ + unsigned int nLen=0; + if (Hand==NULL) + return 1; + fseek(Hand,0,SEEK_END); nLen=ftell(Hand); + fseek(Hand,0x04,SEEK_SET); nLen-=8; fwrite(&nLen,1,sizeof(nLen),Hand); // RIFF value + fseek(Hand,0x28,SEEK_SET); nLen-=40; fwrite(&nLen,1,sizeof(nLen),Hand); // data value + fseek(Hand,0,SEEK_END); + return 0; +} + +int WaveLogStart() +{ + TCHAR szFilter[1024]; + int nRet; + int bOldPause; + + WaveLogStop(); // make sure old log is closed + + MakeOfn(szFilter); + bOldPause = bRunPause; + bRunPause = 1; + nRet = GetSaveFileName(&ofn); + bRunPause = bOldPause; + if (nRet == 0) { + return 1; + } + + { + WaveLog=_tfopen(szChoice,_T("wb")); + if (WaveLog==NULL) + { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_DISK_CREATE)); + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_DISK_SOUND)); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } + WaveLogHeaderStart(WaveLog,nAudSampleRate[nAudSelect]); + + } + MenuEnableItems(); + return 0; +} + +int WaveLogStop() +{ + if (WaveLog) + { + WaveLogHeaderFillIn(WaveLog); + fclose(WaveLog); + + WaveLog = NULL; + + MenuEnableItems(); + } + + return 0; +} + diff --git a/src/burner/zipfn.cpp b/src/burner/zipfn.cpp new file mode 100644 index 00000000..d96d9ff8 --- /dev/null +++ b/src/burner/zipfn.cpp @@ -0,0 +1,207 @@ +// Zip module +#include "burner.h" +#include "unzip.h" + +static unzFile Zip=NULL; +static INT32 nCurrFile=0; // The current file we are pointing to + +INT32 ZipOpen(const char* szZip) +{ + if (szZip == NULL) return 1; + + Zip = unzOpen(szZip); + if (Zip == NULL) return 1; + unzGoToFirstFile(Zip); nCurrFile=0; + return 0; +} + +INT32 ZipClose() +{ + if (Zip != NULL) { + unzClose(Zip); + Zip = NULL; + } + return 0; +} + +// Get the contents of a zip file into an array of ZipEntrys +INT32 ZipGetList(struct ZipEntry** pList, INT32* pnListCount) +{ + if (Zip == NULL) return 1; + if (pList == NULL) return 1; + + unz_global_info ZipGlobalInfo; + memset(&ZipGlobalInfo, 0, sizeof(ZipGlobalInfo)); + + unzGetGlobalInfo(Zip, &ZipGlobalInfo); + INT32 nListLen = ZipGlobalInfo.number_entry; + + // Make an array of File Entries + struct ZipEntry* List = (struct ZipEntry *)malloc(nListLen * sizeof(struct ZipEntry)); + if (List == NULL) { unzClose(Zip); return 1; } + memset(List, 0, nListLen * sizeof(struct ZipEntry)); + + INT32 nRet = unzGoToFirstFile(Zip); + if (nRet != UNZ_OK) { unzClose(Zip); return 1; } + + // Step through all of the files, until we get to the end + INT32 nNextRet = 0; + + for (nCurrFile = 0, nNextRet = UNZ_OK; + nCurrFile < nListLen && nNextRet == UNZ_OK; + nCurrFile++, nNextRet = unzGoToNextFile(Zip)) + { + unz_file_info FileInfo; + memset(&FileInfo, 0, sizeof(FileInfo)); + + nRet = unzGetCurrentFileInfo(Zip, &FileInfo, NULL, 0, NULL, 0, NULL, 0); + if (nRet != UNZ_OK) continue; + + // Allocate space for the filename + char* szName = (char *)malloc(FileInfo.size_filename + 1); + if (szName == NULL) continue; + + nRet = unzGetCurrentFileInfo(Zip, &FileInfo, szName, FileInfo.size_filename + 1, NULL, 0, NULL, 0); + if (nRet != UNZ_OK) continue; + + List[nCurrFile].szName = szName; + List[nCurrFile].nLen = FileInfo.uncompressed_size; + List[nCurrFile].nCrc = FileInfo.crc; + } + + // return the file list + *pList = List; + if (pnListCount != NULL) *pnListCount = nListLen; + + unzGoToFirstFile(Zip); + nCurrFile = 0; + return 0; +} + +INT32 ZipLoadFile(UINT8* Dest, INT32 nLen, INT32* pnWrote, INT32 nEntry) +{ + if (Zip == NULL) return 1; + + INT32 nRet = 0; + if (nEntry < nCurrFile) + { + // We'll have to go through the zip file again to get to our entry + nRet = unzGoToFirstFile(Zip); + if (nRet != UNZ_OK) return 1; + nCurrFile = 0; + } + + // Now step through to the file we need + while (nCurrFile < nEntry) + { + nRet = unzGoToNextFile(Zip); + if (nRet != UNZ_OK) return 1; + nCurrFile++; + } + + nRet = unzOpenCurrentFile(Zip); + if (nRet != UNZ_OK) return 1; + + nRet = unzReadCurrentFile(Zip, Dest, nLen); + // Return how many bytes were copied + if (nRet >= 0 && pnWrote != NULL) *pnWrote = nRet; + + nRet = unzCloseCurrentFile(Zip); + if (nRet == UNZ_CRCERROR) return 2; + if (nRet != UNZ_OK) return 1; + + return 0; +} + +// Load one file directly, added by regret +INT32 __cdecl ZipLoadOneFile(const char* arcName, const char* fileName, void** Dest, INT32* pnWrote) +{ + if (ZipOpen(arcName)) { + return 1; + } + + unz_global_info ZipGlobalInfo; + memset(&ZipGlobalInfo, 0, sizeof(ZipGlobalInfo)); + + unzGetGlobalInfo(Zip, &ZipGlobalInfo); + INT32 nListLen = ZipGlobalInfo.number_entry; + if (nListLen <= 0) { + ZipClose(); + return 1; + } + + INT32 nRet = unzGoToFirstFile(Zip); + if (nRet != UNZ_OK) { unzClose(Zip); return 1; } + + unz_file_info FileInfo; + memset(&FileInfo, 0, sizeof(FileInfo)); + + if (fileName != NULL) { + // Step through all of the files, until we get to the end + INT32 nNextRet = 0; + char szName[MAX_PATH] = ""; + + for (nCurrFile = 0, nNextRet = UNZ_OK; + nCurrFile < nListLen && nNextRet == UNZ_OK; + nCurrFile++, nNextRet = unzGoToNextFile(Zip)) + { + nRet = unzGetCurrentFileInfo(Zip, &FileInfo, szName, MAX_PATH, NULL, 0, NULL, 0); + if (nRet != UNZ_OK) continue; + + if (!strcmp(szName, fileName)) { + break; + } + } + + if (nCurrFile == nListLen) { + ZipClose(); + return 1; // didn't find + } + } + else { + nRet = unzGetCurrentFileInfo(Zip, &FileInfo, NULL, 0, NULL, 0, NULL, 0); + if (nRet != UNZ_OK) { + ZipClose(); + return 1; + } + } + + // Extract file + nRet = unzOpenCurrentFile(Zip); + if (nRet != UNZ_OK) { + unzCloseCurrentFile(Zip); + ZipClose(); + return 1; + } + + if (*Dest == NULL) { + *Dest = (UINT8*)malloc(FileInfo.uncompressed_size); + if (!*Dest) { + unzCloseCurrentFile(Zip); + ZipClose(); + return 1; + } + } + + nRet = unzReadCurrentFile(Zip, *Dest, FileInfo.uncompressed_size); + // Return how many bytes were copied + if (nRet >= 0 && pnWrote != NULL) *pnWrote = nRet; + + nRet = unzCloseCurrentFile(Zip); + ZipClose(); + + if (nRet == UNZ_CRCERROR) { + if (*Dest) { + free(*Dest); + } + return 2; + } + if (nRet != UNZ_OK) { + if (*Dest) { + free(*Dest); + } + return 1; + } + + return 0; +} diff --git a/src/cpu/a68k/fba_make68k.c b/src/cpu/a68k/fba_make68k.c new file mode 100644 index 00000000..a2dcc42c --- /dev/null +++ b/src/cpu/a68k/fba_make68k.c @@ -0,0 +1,8244 @@ +/*--------------------------------------------------------------- + * Motorola 68000 32 Bit emulator + * + * Copyright 1998-2001 Mike Coates, All rights reserved + * Darren Olafson + *--------------------------------------------------------------- + * + * Thanks to ... + * + * Neil Bradley (lots of optimisation help & ideas) + * + *--------------------------------------------------------------- + * History (so we know what bugs have been fixed) + * + * 02.11.98 MJC - CMPM bug, overwriting first value + * 04.11.98 MJC - Debug timing - same as C core + * save PC on calls to C memory routines + * 05.11.98 NS - Re-insert changes to make work on OS/2 + * 06.11.98 MJC - Flags saved on ADDA commands + * X set on ADD commands + * 23.11.98 MJC - Alternate Memory Read/Write for non DOS ports + * 24.11.98 CK - Add WIN32 specific stuff + * 25.11.98 DEO - ABCD Size not initialised + * 21.12.98 MJC - Change register saving on Memory Banking + * 13.01.99 M/D - Change to new C core disassembler + * 19.01.99 MJC - Proper? support for new Interrupt System + * 17.02.99 MJC - TRACE68K define added + * ABCD,SBCD not keeping Z flag + * JMP, JSR for some EA combo's damaging flags + * DIVU - Overflow not being set correctly + * ASL/ASR - Flag Handling now correct + * some minor optimisations + * 13.03.99 DEO - Added new cycle timing + * 24.03.99 MJC - TRACE68K define removed + * NEW INTERRUPT SYSTEM only + * interrupt check sped up (when not taken) + * STOP checks for interrupt + * 01.04.99 MJC - OS2 specifics added + * MOVEM reference point moved + * Data and Address register mode combined for :- + * movecodes + * dumpx + * 04.05.99 MJC - Add Previous PC support to MOVE.B #X,XXXXXX.L (F1 Dream) + * ABCD/SBCD could corrupt zero flag + * DIVS/DIVU overflow should not update register + * 22.05.99 MJC - Complete support of Previous PC on C calls + * Some optional bits now selected by DEFINES + * 27.05.99 MJC - Interrupt system changed + * 28.05.99 MJC - Use DEFINES in more places + * Interrupt check running one opcode when taken + * 16.07.99 MJC - Reset - Preload next opcode / external call + * 68010 commands almost complete + * more compression on jump table (16k smaller) + * Some optimising + * shl reg,1 -> add reg,reg + * or ecx,ecx:jz -> jecxz + * 22.08.99 DEO - SBCD/ABCD sets N flag same as carry + * 19.10.99 MJC - Change DOS memory routines + * Change DOS Clobber flags (ESI no longer safe) + * Save EAX around memory write where needed + * bit commands optimised + * 25.10.99 MJC - Was keeping masked register on read/write + * if register was preserved over call + * ESI assumed 'safe' again + * 25.10.99 MJC - Bank ID moved to CPU context + * 03.11.99 KENJO - VC++6.0 seems not to preserve EDI. Fixed "ABCD -(A0), -(A0)" crash / "roxr (A0)"-type shift crash + * 13.11.99 KENJO - Fixed "NABC" + * Now Win32 uses FASTCALL type call for interrupt callback + * 09.02.00 MJC - Check CPU type before allowing 68010/68020 instructions + * remove routines for 5 non existant opcodes + * 05.03.00 MJC - not command decrement A7 by 1 for bytes + * 10.03.00 MJC - as did btst,cmpm and nbcd + * 22.03.00 MJC - Divide by zero should not decrement PC by 2 before push + * Move memory banking into exception routine + * 14.04.00 Dave - BTST missing Opcode + * ASL.L > 31 shift + * 20.04.00 MJC - TST.B Also missing A7 specific routine + * - Extra Define A7ROUTINE to switch between having seperate + * routines for +-(A7) address modes. + * 24.06.00 MJC - ADDX/SUBX +-(A7) routines added. + * TAS should not touch X flag + * LSL/LSR EA not clearing V flag + * CHK not all opcodes in jump table + * Add define to mask status register + * 04.07.00 MJC - Keep high byte of Program Counter on Bxx and Jxx + * Fix flag handling on NEGX + * Really fix ADDX/SUBX +-(A7) + * PC could be set wrong after CHK.W instruction + * DIVS/DIVU always clear C flag + * ABCD/SBCD missing +-(A7) Routine + * TAS missing +-(A7) Routine + * Bitwise Static missing +-(A7) Routine + * CMPM missing +-(A7) Routine + * 30.09.00 DEO - added mull, divl, bfextu + * added '020 addressing modes + * fixed $6xff branching + * 23.01.01 MJC - Spits out seperate code for 68000 & 68020 + * allows seperate optimising! + * 17.02.01 MJC - Support for encrypted PC relative fetch calls + * 11.03.01 GUTI - change some cmp reg,0 and or reg,reg with test + * 13.03.01 MJC - Single Icount for Asm & C cores + * 16.05.01 ASG - use push/pop around mem calls instead of store to safe_REG + * optimized a bit the 020 extension word decoder + * removed lots of unnecessary code in branches + *--------------------------------------------------------------- + * Known Problems / Bugs + * + * 68000 + * None - Let us know if you find any! + * + * 68010 + * Instructions that are supervisor only as per 68000 spec. + * move address space not implemented. + * + * 68020 + * only long Bcc instruction implemented. + *--------------------------------------------------------------- + * Notes + * + * STALLCHECK should be defined for Pentium Class + * undefined for P2/Celerons + * + * ALIGNMENT is normally 4, but seems faster on my P2 as 0 ! + * + *--------------------------------------------------------------- + * + * Future Changes + * + * 68020 instructions to be completed + * assembler memory routines + + * + * and anything else that takes our fancy! + *---------------------------------------------------------------*/ + +/* Specials - Switch what program allows/disallows */ + +#undef STALLCHECK /* Affects fetching of Opcode */ +#undef SAVEPPC /* Save Previous PC (!!! FBA setting) */ +#define ENCRYPTED /* PC relative = decrypted */ +#define ASMBANK 10 /* Memory banking algorithm to use LVR - (bank size = 1 << ASMBANK (8 = 16)) */ +#define A7ROUTINE /* Define to use separate routines for -(a7)/(a7)+ */ +#define ALIGNMENT 4 /* Alignment to use for branches */ +#undef MASKCCR /* Mask the status register to filter out unused bits */ +#define KEEPHIGHPC /* Keep or Ignore bits 24-31 */ +#define QUICKZERO /* selects XOR r,r or MOV r,0 */ + +#include +#include +#include +#include + +/* New Disassembler */ + +char * codebuf; +int DisOp; + +#define cpu_readmem24bew(addr) (0) +#define cpu_readmem24bew_word(addr) (DisOp) + +#define MEMORY_H /* so memory.h will not be included... */ +/* +#include "d68k.c" +*/ +#undef MEMORY_H + +#undef cpu_readmem24bew +#undef cpu_readmem24bew_word + + +/* + * Defines used by Program + * + */ + +#define VERSION "0.30" + +#define TRUE -1 +#define FALSE 0 + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 +#define ESI 4 +#define PC ESI +#define EDI 5 +#define EBP 6 + + +#define NORMAL 0 +#define PCREL 1 + +#ifdef __ELF__ +#define PREF "" +#else +#define PREF "_" +#endif + +/* Register Location Offsets */ + +#define ICOUNT PREF "m68k_ICount" + +#define REG_DAT "R_D0" +#define REG_DAT_EBX "[R_D0+ebx*4]" +#define REG_ADD "R_A0" +#define REG_A7 "R_A7" +#define REG_USP "R_USP" +#define REG_ISP "R_ISP" +#define REG_SRH "R_SR_H" +#define REG_CCR "R_CCR" +#define REG_X "R_XC" +#define REG_PC "R_PC" +#define REG_IRQ "R_IRQ" +#define REG_S "R_SR" +#define REG_IRQ_CALLBACK "R_IRQ_CALLBACK" +#define REG_RESET_CALLBACK "R_RESET_CALLBACK" + + +/* 68010 Regs */ + +#define REG_VBR "R_VBR" +#define REG_SFC "R_SFC" +#define REG_DFC "R_DFC" + +#define FASTCALL_FIRST_REG "ecx" +#define FASTCALL_SECOND_REG "edx" + + + +/* + * Global Variables + * + */ + +FILE *fp = NULL; + +char *comptab = NULL; +char *CPUtype = NULL; + +int CPU = 0; +int FlagProcess = 0; +int CheckInterrupt = 0; +int ExternalIO = 0; +int Opcount = 0; +int TimingCycles = 0; +int AddEACycles = 0; +int AccessType = NORMAL; +int ppro = 0; + + + +/* External register preservation */ + +#ifdef DOS + +/* Registers normally saved around C routines anyway */ +/* GCC 2.9.1 (dos) seems to preserve EBX,EDI and EBP */ +static char SavedRegs[] = "-B--SDB"; + +#elif defined(WIN32) + +/* visual C++, win32, says it preserves ebx, edi, esi, and ebp */ +/* ---------- VC++ deosn't preserve EDI? (Kenjo, 110399) ---------- */ +static char SavedRegs[] = "-B--S-B"; + +#else + +/* Assume nothing preserved */ +static char SavedRegs[] = "-------"; + +#endif + + + +/* Jump Table */ + +int OpcodeArray[65536]; + +/* Lookup Arrays */ + +static char* regnameslong[] = +{ "EAX","EBX","ECX","EDX","ESI","EDI","EBP"}; + +static char* regnamesword[] = +{ "AX","BX","CX","DX", "SI", "DI", "BP"}; + +static char* regnamesshort[] = +{ "AL","BL","CL","DL"}; + + + +/*********************************/ +/* Conversion / Utility Routines */ +/*********************************/ + +/* Convert EA to Address Mode Number + * + * 0 Dn + * 1 An + * 2 (An) + * 3 (An)+ + * 4 -(An) + * 5 x(An) + * 6 x(An,xr.s) + * 7 x.w + * 8 x.l + * 9 x(PC) + * 10 x(PC,xr.s) + * 11 #x,SR,CCR Read = Immediate, Write = SR or CCR + * in order to read SR to AX, use READCCR + * 12-15 INVALID + * + * 19 (A7)+ + * 20 -(A7) + * + */ + +int EAtoAMN(int EA, int Way) +{ + int Work; + + if (Way) + { + Work = (EA & 0x7); + + if (Work == 7) Work += ((EA & 0x38) >> 3); + + if (((Work == 3) || (Work == 4)) && (((EA & 0x38) >> 3) == 7)) + { + Work += 16; + } + } + else + { + Work = (EA & 0x38) >> 3; + + if (Work == 7) Work += (EA & 7); + + if (((Work == 3) || (Work == 4)) && ((EA & 7) == 7)) + { + Work += 16; + } + } + + return Work; +} + +/* + * Generate Main or Sub label + */ + +char *GenerateLabel(int ID,int Type) +{ + static int LabID,LabNum; +/* + static char disasm[80]; + char *dis = disasm; +*/ + if (Type == 0) + { + CheckInterrupt=0; /* No need to check for Interrupts */ + ExternalIO=0; /* Not left Assembler Yet */ + TimingCycles=0; /* No timing info for this command */ + AddEACycles=1; /* default to add in EA timing */ + Opcount++; /* for screen display */ + + DisOp = ID; +/* + m68k_disassemble(dis,0); + sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t; %s", CPU,ID, dis); +*/ + sprintf(codebuf, "OP%d_%4.4x:\t\t\t\t;", CPU,ID); + + LabID = ID; + LabNum = 0; + } + else + { + LabNum++; + sprintf(codebuf, "OP%d_%4.4x_%1x", CPU,LabID, LabNum); + } + + return codebuf; +} + +/* + * Generate Alignment Line + */ + +void Align(void) +{ + fprintf(fp, "\t\t ALIGN %d\n\n",ALIGNMENT); +} + +/* + * Copy X into Carry + * + * There are several ways this could be done, this allows + * us to easily change the way we are doing it! + */ + +void CopyX(void) +{ + /* Copy bit 0 from X flag store into Carry */ + + fprintf(fp, "\t\t bt dword [%s],0\n",REG_X); +} + +/* + * Immediate 3 bit data + * + * 0=8, anything else is itself + * + * Again, several ways to achieve this + * + * ECX contains data as 3 lowest bits + * + */ + +void ClearRegister(int regno) +{ +#ifdef QUICKZERO + fprintf(fp, "\t\t mov %s,0\n",regnameslong[regno]); +#else + fprintf(fp, "\t\t xor %s,%s\n",regnameslong[regno],regnameslong[regno]); +#endif +} + +void Immediate8(void) +{ + /* This takes 3 cycles, 5 bytes, no memory reads */ + + fprintf(fp, "\t\t dec ecx ; Move range down\n"); + fprintf(fp, "\t\t and ecx,byte 7 ; Mask out lower bits\n"); + fprintf(fp, "\t\t inc ecx ; correct range\n"); + + + /* This takes 2 cycles, 10 bytes but has a memory read */ + /* I don't know timing for the mov command - assumed 1 */ + +#if 0 + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ecx,[ImmTable+ECX*4]\n"); +#endif +} + +/* + * This will check for bank changes before + * resorting to calling the C bank select code + * + * Most of the time it does not change! + * + */ + +/* forward used by MemoryBanking */ +void Exception(int Number, int BaseCode) ; + +void MemoryBanking(int BaseCode) +{ + /* check for odd address */ + fprintf(fp, "\t\t test esi, dword 1\n"); + fprintf(fp, "\t\t jz near OP%d_%5.5x\n",CPU,BaseCode); + + /* trying to run at an odd address */ + Exception(3,BaseCode); + + /* Keep Whole PC */ + + fprintf(fp, "OP%d_%5.5x:\n",CPU,BaseCode); + +/* ASG - always call to the changepc subroutine now, since the number of */ +/* bits varies based on the memory model */ +#ifdef KEEPHIGHPC + fprintf(fp, "\t\t mov [FullPC],ESI\n"); +#endif + + /* Mask to n bits */ + fprintf(fp, "\t\t and esi,[%smem_amask]\n", PREF); + +#if 0 +#ifdef KEEPHIGHPC + fprintf(fp, "\t\t mov [FullPC],ESI\n"); +#endif + + /* Mask to 24 bits */ +// fprintf(fp, "\t\t and esi,0ffffffh\n"); + +#ifdef ASMBANK + /* Assembler bank switch */ + + fprintf(fp, "\t\t mov eax,esi\n"); + /* LVR - use a variable bank size */ + fprintf(fp, "\t\t shr eax," ASMBANK "\n"); + fprintf(fp, "\t\t cmp [asmbank],eax\n"); + fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode); + + fprintf(fp, "\t\t mov [asmbank],eax\n"); +#else + /* This code is same as macro used by C core */ + + fprintf(fp, "\t\t mov ecx,esi\n"); + fprintf(fp, "\t\t mov ebx,[_cur_mrhard]\n"); + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t mov al,byte [_opcode_entry]\n"); + fprintf(fp, "\t\t cmp al,[ecx+ebx]\n"); + fprintf(fp, "\t\t je OP%d_%5.5x_Bank\n",CPU,BaseCode); +#endif +#endif + + /* Call Banking Routine */ + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + } + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + +#ifdef FASTCALL + fprintf(fp, "\t\t mov %s,esi\n",FASTCALL_FIRST_REG); +#else + fprintf(fp, "\t\t push esi\n"); +#endif + + fprintf(fp, "\t\t call [%sa68k_memory_intf+28]\n", PREF); + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + } + + /* Update our copy */ + + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + + fprintf(fp, "OP%d_%5.5x_Bank:\n",CPU,BaseCode); +} + +/* + * Update Previous PC value + * + */ + +void SavePreviousPC(void) +{ +#ifdef SAVEPPC + fprintf(fp, "\t\t mov [R_PPC],esi\t\t\t ; Keep Previous PC\n"); +#endif +} + +/* + * Complete Opcode handling + * + * Any tidying up, end code + * + */ + +void Completed(void) +{ + + /* Flag Processing to be finished off ? */ + + AccessType = NORMAL; + + /* Use assembler timing routines */ + + if (TimingCycles != 0) + { + if (TimingCycles > 127) + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles); + else + { + if (TimingCycles != -1) + fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,TimingCycles); + } + + if (FlagProcess > 0) + fprintf(fp, "\t\t pop EDX\n"); + if (FlagProcess == 2) + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + fprintf(fp, "\t\t js near MainExit\n\n"); + } + else + { + fprintf(fp, "\t\t test dword [%s],0xffffffff\n",ICOUNT); + + if (FlagProcess > 0) + fprintf(fp, "\t\t pop EDX\n"); + if (FlagProcess == 2) + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + fprintf(fp, "\t\t jle near MainExit\n\n"); + } + FlagProcess = 0; + +#ifdef MAME_DEBUG + + /* Check for Debug Active */ + + fprintf(fp, "\n\t\t test byte [%smame_debug],byte 0xff\n", PREF); + fprintf(fp, "\t\t jnz near MainExit\n\n"); + +#endif + +#ifdef FBA_DEBUG + + fprintf(fp, "\n\t\t test byte [%smame_debug],byte 0xff\n", PREF); + fprintf(fp, "\t\t jns near .NoDebug\n"); + fprintf(fp, "\t\t call near FBADebugActive\n\n"); + fprintf(fp, ".NoDebug\n"); + +#endif + + if (CheckInterrupt) + { + fprintf(fp,"; Check for Interrupt waiting\n\n"); + fprintf(fp,"\t\t test byte [%s],07H\n",REG_IRQ); + fprintf(fp,"\t\t jne near interrupt\n\n"); + } + + if(CPU==2) + { + /* 32 bit memory version */ + fprintf(fp, "\t\t mov eax,2\n"); /* ASG */ + fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */ + +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[eax+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n"); +#endif + } + else + { + /* 16 bit memory */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype); +} + +/* + * Flag Routines + * + * Size = B,W or L + * Sreg = Register to Test + * TestReg = Need to test register (false if flags already set up) + * SetX = if C needs to be copied across to X register + * Delayed = Delays final processing to end of routine (Completed()) + * + */ + +void TestFlags(char Size,int Sreg) +{ + char* Regname=""; + + switch (Size) + { + case 66: + Regname = regnamesshort[Sreg]; + break; + + case 87: + Regname = regnamesword[Sreg]; + break; + + case 76: + Regname = regnameslong[Sreg]; + break; + } + + /* Test does not update register */ + /* so cannot generate partial stall */ + + fprintf(fp, "\t\t test %s,%s\n",Regname,Regname); +} + +void SetFlags(char Size,int Sreg,int Testreg,int SetX,int Delayed) +{ + if (Testreg) TestFlags(Size,Sreg); + + fprintf(fp, "\t\t pushfd\n"); + + if (Delayed) + { + /* Rest of code done by Completed routine */ + + if (SetX) FlagProcess = 2; + else FlagProcess = 1; + } + else + { + fprintf(fp, "\t\t pop EDX\n"); + + if (SetX) fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } +} + +/******************/ +/* Check CPU Type */ +/******************/ + +void CheckCPUtype(int Minimum) +{ + if(CPU==2) + { + /* Only check for > 020 */ + + if(Minimum>2) + { + fprintf(fp, "\t\t mov eax,[CPUversion]\n"); + + fprintf(fp, "\t\t cmp al,%d\n",Minimum); + fprintf(fp, "\t\t jb near ILLEGAL\n\n"); + } + } + else + { + fprintf(fp, "\t\t mov eax,[CPUversion]\n"); + + if (Minimum == 1) + { + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jz near ILLEGAL\n\n"); + } + else + { + fprintf(fp, "\t\t cmp al,%d\n",Minimum); + fprintf(fp, "\t\t jb near ILLEGAL\n\n"); + } + } +} + +/************************************/ +/* Pre-increment and Post-Decrement */ +/************************************/ + +void IncrementEDI(int Size,int Rreg) +{ + switch (Size) + { + case 66: + +#ifdef A7ROUTINE + + /* Always does Byte Increment - A7 uses special routine */ + + fprintf(fp, "\t\t inc dword [%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + +#else + + /* A7 uses same routines, so inc by 2 if A7 */ + + fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]); + fprintf(fp, "\t\t cmc\n"); + fprintf(fp, "\t\t adc dword [%s+%s*4],byte 1\n",REG_ADD,regnameslong[Rreg]); + +#endif + break; + + case 87: + + fprintf(fp, "\t\t add dword [%s+%s*4],byte 2\n",REG_ADD,regnameslong[Rreg]); + break; + + case 76: + + fprintf(fp, "\t\t add dword [%s+%s*4],byte 4\n",REG_ADD,regnameslong[Rreg]); + break; + } +} + +void DecrementEDI(int Size,int Rreg) +{ + switch (Size) + { + case 66: + +#ifdef A7ROUTINE + + /* Always does Byte Increment - A7 uses special routine */ + + fprintf(fp, "\t\t dec EDI\n"); + +#else + + /* A7 uses same routines, so dec by 2 if A7 */ + + fprintf(fp, "\t\t cmp %s,7\n",regnamesshort[Rreg]); + fprintf(fp, "\t\t cmc\n"); + fprintf(fp, "\t\t sbb dword edi,byte 1\n"); + +#endif + break; + + case 87: + + fprintf(fp, "\t\t sub EDI,byte 2\n"); + break; + + case 76: + fprintf(fp, "\t\t sub EDI,byte 4\n"); + break; + } +} + +/* + * Generate an exception + * + * if Number = -1 then assume value in AL already + * code must continue running afterwards + * + */ + +void Exception(int Number, int BaseCode) +{ + if (Number > -1) + { + fprintf(fp, "\t\t sub esi,byte 2\n"); + fprintf(fp, "\t\t mov al,%d\n",Number); + } + + fprintf(fp, "\t\t call Exception\n\n"); + + if (Number > -1) + Completed(); +} + + +/********************/ +/* Address Routines */ +/********************/ + +/* + * Decode Intel flags into AX as SR register + * + * Wreg = spare register to use (must not be EAX or EDX) + */ + +void ReadCCR(char Size, int Wreg) +{ + fprintf(fp, "\t\t mov eax,edx\n"); + fprintf(fp, "\t\t mov ah,byte [%s]\n",REG_X); + + /* Partial stall so .. switch to new bit of processing */ + + fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]); + fprintf(fp, "\t\t and %s,byte 1\n",regnameslong[Wreg]); + + /* Finish what we started */ + + fprintf(fp, "\t\t shr eax,4\n"); + fprintf(fp, "\t\t and eax,byte 01Ch \t\t; X, N & Z\n\n"); + + /* and complete second task */ + + fprintf(fp, "\t\t or eax,%s \t\t\t\t; C\n\n",regnameslong[Wreg]); + + /* and Finally */ + + fprintf(fp, "\t\t mov %s,edx\n",regnameslong[Wreg]); + fprintf(fp, "\t\t shr %s,10\n",regnameslong[Wreg]); + fprintf(fp, "\t\t and %s,byte 2\n",regnameslong[Wreg]); + fprintf(fp, "\t\t or eax,%s\t\t\t\t; O\n\n",regnameslong[Wreg]); + + if (Size == 'W') + { + fprintf(fp, "\t\t mov ah,byte [%s] \t; T, S & I\n\n",REG_SRH); + +#ifdef MASKCCR + fprintf(fp, "\t\t and ax,0A71Fh\t; Mask unused bits\n"); +#endif + } +} + +/* + * Convert SR into Intel flags + * + * Also handles change of mode from Supervisor to User + * + * n.b. This is also called by EffectiveAddressWrite + */ + +void WriteCCR(char Size) +{ + if (Size == 'W') + { + /* Did we change from Supervisor to User mode ? */ + + char *Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t test ah,20h \t\t\t; User Mode ?\n"); + fprintf(fp, "\t\t jne short %s\n\n",Label); + + /* Mode Switch - Update A7 */ + + fprintf(fp, "\t\t mov edx,[%s]\n",REG_A7); + fprintf(fp, "\t\t mov [%s],edx\n",REG_ISP); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_USP); + fprintf(fp, "\t\t mov [%s],edx\n",REG_A7); + + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mov byte [%s],ah \t;T, S & I\n",REG_SRH); + + /* Mask may now allow Interrupt */ + + CheckInterrupt += 1; + } + + /* Flags */ + + fprintf(fp, "\t\t and eax,byte 1Fh\n"); + fprintf(fp, "\t\t mov edx,[IntelFlag+eax*4]\n"); + fprintf(fp, "\t\t mov [%s],dh\n",REG_X); + fprintf(fp, "\t\t and edx,0EFFh\n"); +} + + +/* + * Interface to Mame memory commands + * + * Flags = "ABCDSDB" - set to '-' if not required to preserve + * (order EAX,EBX,ECX,EDX,ESI,EDI,EBP) + * + * AReg = Register containing Address + * + * Mask 0 : No Masking + * 1 : Mask top byte, but preserve register + * 2 : Mask top byte, preserve masked register + */ + +void Memory_Read(char Size,int AReg,char *Flags,int Mask) +{ + ExternalIO = 1; + + /* Save PC */ + + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + + /* Check for special mask condition */ + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 2) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + + /* Check to see if registers need saving */ + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t push EBX\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t push ECX\n"); + } + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t push EDI\n"); + } + + /* Sort Address out */ + +#ifdef FASTCALL + + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]); + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 1) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/ + +#else + + if (Mask == 1) + { + if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-')) + { + /* Don't trash a wanted safe register */ + + fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/ + fprintf(fp, "\t\t push EAX\n"); + } + else + { + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + } + } + else + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + +#endif + + + + /* Call Mame memory routine */ + + /* ASG - changed these to call through the function pointers */ + +#ifdef ENCRYPTED + switch (AccessType) + { + case NORMAL : + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+4]\n", PREF); + break; + + case 87 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+8]\n", PREF); + break; + + case 76 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+12]\n", PREF); + break; + } + break; + + case PCREL : + + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+32]\n", PREF); + break; + + case 87 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+36]\n", PREF); + break; + + case 76 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+40]\n", PREF); + break; + } + break; + } + +// AccessType = NORMAL; + +#else + + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+4]\n", PREF); + break; + + case 87 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+8]\n", PREF); + break; + + case 76 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+12]\n", PREF); + break; + } +#endif + + /* Correct Stack */ + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + + + /* Restore registers */ + + /* Check to see if registers need restoring */ + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t pop EDI\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t pop ECX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t pop EBX\n"); + } + + if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-')) + { + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + } + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR); + } + + if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-')) + { + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + } +} + +void Memory_Write(char Size,int AReg,int DReg,char *Flags,int Mask) +{ + ExternalIO = 1; + + /* Save PC */ + + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + + /* Check for special mask condition */ + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 2) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + + /* Check to see if registers need saving */ + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + + if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-')) + { + fprintf(fp, "\t\t push EAX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t push EBX\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t push ECX\n"); + } + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t push EDI\n"); + } + +#ifdef FASTCALL + + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_SECOND_REG,regnameslong[DReg]); + fprintf(fp, "\t\t mov %s,%s\n",FASTCALL_FIRST_REG,regnameslong[AReg]); + + /* ASG - no longer need to mask addresses here */ +/* if (Mask == 1) + fprintf(fp, "\t\t and %s,0FFFFFFh\n",FASTCALL_FIRST_REG);*/ + +#else + + fprintf(fp, "\t\t push %s\n",regnameslong[DReg]); + + if (Mask == 1) + { + if ((Flags[AReg] != '-') && (SavedRegs[AReg] != '-')) + { + /* Don't trash a wanted safe register */ + + fprintf(fp, "\t\t mov EAX,%s\n",regnameslong[AReg]); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and EAX,0FFFFFFh\n");*/ + fprintf(fp, "\t\t push EAX\n"); + } + else + { + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp, "\t\t and %s,0FFFFFFh\n",regnameslong[AReg]);*/ + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + } + } + else + fprintf(fp, "\t\t push %s\n",regnameslong[AReg]); + +#endif + + + + /* Call Mame Routine */ + + /* ASG - changed these to call through the function pointers */ + switch (Size) + { + case 66 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+16]\n", PREF); + break; + + case 87 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+20]\n", PREF); + break; + + case 76 : + fprintf(fp, "\t\t call [%sa68k_memory_intf+24]\n", PREF); + break; + } + + /* Correct Stack */ + +#ifndef FASTCALL + fprintf(fp, "\t\t lea esp,[esp+8]\n"); +#endif + + + + /* Restore registers */ + + /* Check to see if registers need restoring */ + + if ((Flags[EDI] != '-') && (SavedRegs[EDI] == '-')) + { + fprintf(fp, "\t\t pop EDI\n"); + } + + if ((Flags[ECX] != '-') && (SavedRegs[ECX] == '-')) + { + fprintf(fp, "\t\t pop ECX\n"); + } + + if ((Flags[EBX] != '-') && (SavedRegs[EBX] == '-')) + { + fprintf(fp, "\t\t pop EBX\n"); + } + + if ((Flags[EAX] != '-') && (SavedRegs[EAX] == '-')) + { + fprintf(fp, "\t\t pop EAX\n"); + } + + if ((Flags[EDX] != '-') && (SavedRegs[EDX] == '-')) + { + fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR); + } + + if ((Flags[ESI] != '-') && (SavedRegs[ESI] == '-')) + { + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + } + + if ((Flags[EBP] != '-') && (SavedRegs[EBP] == '-')) + { + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + } +} + + +/* + * Fetch data from Code area + * + * Dreg = Destination Register + * Extend = Sign Extend Word to Long + * + */ + +void Memory_Fetch(char Size,int Dreg,int Extend) +{ + static int loopcount=0; + + /* Always goes via OP_ROM */ + + if(CPU!=2) + { + /* 16 Bit version */ + + if ((Extend == TRUE) & (Size == 'W')) + fprintf(fp, "\t\t movsx %s,word [esi+ebp]\n",regnameslong[Dreg]); + else if (Size == 'W') + fprintf(fp, "\t\t movzx %s,word [esi+ebp]\n",regnameslong[Dreg]); + else + fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]); + + if (Size == 'L') + fprintf(fp, "\t\t rol %s,16\n",regnameslong[Dreg]); + } + else + { + /* 32 Bit version */ + + if (Size == 'W') + { + fprintf(fp, "\t\t mov %s,esi\n",regnameslong[Dreg]); + fprintf(fp, "\t\t xor %s,byte 2\n",regnameslong[Dreg]); + + if (Extend == TRUE) + fprintf(fp, "\t\t movsx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]); + else + fprintf(fp, "\t\t movzx %s,word [%s+ebp]\n",regnameslong[Dreg],regnameslong[Dreg]); + } + else + { + // if address is exact multiple of 4, long read will work + // otherwise we need to get words address-2 and address+4 + + // Always read long + fprintf(fp, "\t\t test esi,2\n"); +if (!ppro) +{ + fprintf(fp, "\t\t mov %s,dword [esi+ebp]\n",regnameslong[Dreg]); + + // OK ? + fprintf(fp, "\t\t jz short FL%3.3d\n",loopcount+1); + + // no, so get high word + fprintf(fp, "\t\t mov %s,dword [esi+ebp-4]\n",regnameslong[Dreg]); + // and get low word + fprintf(fp, "\t\t mov %s,word [esi+ebp+4]\n",regnamesword[Dreg]); + + fprintf(fp, "FL%3.3d:\n",++loopcount); +} +else +{ + fprintf(fp, "\t\t cmovnz %s,dword [esi+ebp-4]\n",regnameslong[Dreg]); + fprintf(fp, "\t\t cmovz %s,dword [esi+ebp]\n",regnameslong[Dreg]); + fprintf(fp, "\t\t cmovnz %s,word [esi+ebp+4]\n",regnamesword[Dreg]); +} + } + } +} + +/**********************/ +/* Push PC onto Stack */ +/**********************/ + +void PushPC(int Wreg,int Wreg2,char *Flags, int Mask) +{ + + /* Wreg2 is only used when high byte is kept */ + /* If it is EBP then the register is restored */ + + fprintf(fp, "\t\t mov %s,[%s]\t ; Push onto Stack\n",regnameslong[Wreg],REG_A7); + fprintf(fp, "\t\t sub %s,byte 4\n",regnameslong[Wreg]); + fprintf(fp, "\t\t mov [%s],%s\n",REG_A7,regnameslong[Wreg]); + +#ifndef KEEPHIGHPC + + Memory_Write('L',Wreg,ESI,Flags,Mask); + +#else + + fprintf(fp, "\t\t mov %s,[FullPC]\n",regnameslong[Wreg2]); + fprintf(fp, "\t\t and %s,0xff000000\n",regnameslong[Wreg2]); + fprintf(fp, "\t\t or %s,ESI\n",regnameslong[Wreg2]); + + Memory_Write('L',Wreg,Wreg2,Flags,Mask); + + if (Wreg2 == EBP) + { + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + } + +#endif +} + +void ExtensionDecode(int SaveEDX) +{ + char *Label = GenerateLabel(0,1); + + if (SaveEDX) + fprintf(fp, "\t\t push edx\n"); + + Memory_Fetch('W',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if(CPU!=2) + { + /* 68000 Extension */ + + fprintf(fp, "\t\t mov edx,eax\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t test edx,0x0800\n"); + fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT); + fprintf(fp, "\t\t jnz short %s\n",Label); + fprintf(fp, "\t\t cwde\n"); + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + fprintf(fp, "\t\t movsx edx,dl\n"); + fprintf(fp, "\t\t lea edi,[edi+edx]\n"); + } + else + { + /* 68020 Extension */ + + // eax holds scaled index + + // might be faster just to push all regs + fprintf(fp, "\t\t push ebx\n"); + fprintf(fp, "\t\t push ecx\n"); + + // copies for later use + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t mov edx,eax\n"); + + // check E bit to see if displacement or full format + fprintf(fp, "\t\t test edx,0x0100\n"); + fprintf(fp, "\t\t jz short %s_a\n",Label); + // full mode so check IS (index supress) + fprintf(fp, "\t\t test edx,0x0040\n"); + fprintf(fp, "\t\t jz short %s_b\n",Label); + // set index to 0, it's not added + ClearRegister(EAX); + fprintf(fp, "\t\t jmp short %s_d\n",Label); // near + + // add displacement + fprintf(fp, "%s_a:\n",Label); + fprintf(fp, "\t\t movsx eax,al\n"); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + fprintf(fp, "%s_b:\n",Label); + // calc index always scale (68k will scale by 1) + fprintf(fp, "\t\t mov eax,edx\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t test edx,0x0800\n"); + fprintf(fp, "\t\t mov eax,[%s+eax*4]\n",REG_DAT); + fprintf(fp, "\t\t jnz short %s_c\n",Label); + fprintf(fp, "\t\t cwde\n"); + + fprintf(fp, "%s_c:\n",Label); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 3\n"); + fprintf(fp, "\t\t shl eax,cl\n"); + + // if brief mode we can add index and exit + fprintf(fp, "\t\t test edx,0x0100\n"); + fprintf(fp, "\t\t jz near %s_i2\n",Label); + + fprintf(fp, "%s_d:\n",Label); + // check BS (base supress) + // if BS is 1 then set edi to 0 + fprintf(fp, "\t\t test edx,0x0080\n"); + fprintf(fp, "\t\t jz short %s_4a\n",Label); + ClearRegister(EDI); + // if null displacement skip over + fprintf(fp, "%s_4a:\n",Label); + fprintf(fp, "\t\t test edx,0x0020\n"); + fprintf(fp, "\t\t jz short %s_f\n",Label); + + // **** calc base displacement **** + // is it long + fprintf(fp, "\t\t test edx,0x0010\n"); + fprintf(fp, "\t\t jz short %s_e\n",Label); + // fetch long base + Memory_Fetch('L',EBX,FALSE); + fprintf(fp, "\t\t lea edi,[edi+ebx]\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + fprintf(fp, "\t\t jmp short %s_f\n",Label); + + // fetch word base + fprintf(fp, "%s_e:\n",Label); + Memory_Fetch('W',EBX,TRUE); + fprintf(fp, "\t\t lea edi,[edi+ebx]\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + + // **** indirect? **** + fprintf(fp, "%s_f:\n",Label); + fprintf(fp, "\t\t test edx,0x0003\n"); + fprintf(fp, "\t\t jz near %s_7a\n",Label); + // pre or post indirect + fprintf(fp, "\t\t test edx,0x0004\n"); + fprintf(fp, "\t\t jnz short %s_g\n",Label); + // do pre + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + Memory_Read('L',EDI,"ABCDSDB",2); + fprintf(fp, "\t\t mov edi,eax\n"); + fprintf(fp, "\t\t jmp short %s_h\n",Label); + + // do post + fprintf(fp, "%s_g:\n",Label); + fprintf(fp, "\t\t push eax\n"); + Memory_Read('L',EDI,"-B-DS-B",2); + fprintf(fp, "\t\t pop edi\n"); + + fprintf(fp, "%s_7a:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + // **** outer displacement **** + // if null displacement skip over + fprintf(fp, "%s_h:\n",Label); + fprintf(fp, "\t\t test edx,0x0002\n"); + fprintf(fp, "\t\t jz short %s_j\n",Label); + // word or long? + fprintf(fp, "\t\t test edx,0x0001\n"); + fprintf(fp, "\t\t jz short %s_i\n",Label); + // fetch long + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + fprintf(fp, "\t\t jmp short %s_i2\n",Label); + // fetch word + fprintf(fp, "%s_i:\n",Label); + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "%s_i2:\n",Label); + fprintf(fp, "\t\t lea edi,[edi+eax]\n"); + + // **** exit **** + fprintf(fp, "%s_j:\n",Label); + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t pop ebx\n"); + } + + if (SaveEDX) + fprintf(fp, "\t\t pop edx\n"); +} + +/* Calculate Effective Address - Return address in EDI + * + * mode = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * + * Only for modes 2 - 10 (5-10 clobber EAX) + */ + +void EffectiveAddressCalculate(int mode,char Size,int Rreg,int SaveEDX) +{ + /* timing */ + + if ((TimingCycles > 0) && (AddEACycles!=0)) + { + switch (mode) + { + case 2: /* (An) */ + case 3: /* (An)+ */ + case 11: /* #x,SR,CCR */ + case 19: /* (A7)+ */ + TimingCycles += 4 ; + break ; + + case 4: /* -(An) */ + case 20: /* -(A7) */ + TimingCycles += (CPU==2) ? 5 : 6 ; + break ; + + case 5: /* x(An) */ + case 9: /* x(PC) */ + TimingCycles += (CPU==2) ? 5 : 8 ; + break ; + + case 7: /* x.w */ + TimingCycles += (CPU==2) ? 4 : 8 ; + break ; + + case 6: /* x(An,xr.s) */ + case 10: /* x(PC,xr.s) */ + TimingCycles += (CPU==2) ? 7 : 10 ; + break ; + + case 8: /* x.l */ + TimingCycles += (CPU==2) ? 4 : 12 ; + break ; + } + + /* long w/r adds 4 cycles */ + + if ((mode>1) && (Size == 'L') && (CPU != 2)) + TimingCycles += 4 ; + } + + AccessType = NORMAL; + + switch (mode) + { + + case 2: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + break; + + case 3: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + IncrementEDI(Size,Rreg); + break; + + case 4: + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + DecrementEDI(Size,Rreg); + fprintf(fp, "\t\t mov [%s+%s*4],EDI\n",REG_ADD,regnameslong[Rreg]); + break; + + case 5: + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add edi,eax\n"); + break; + + case 6: + + /* Get Address register Value */ + + fprintf(fp, "\t\t mov EDI,[%s+%s*4]\n",REG_ADD,regnameslong[Rreg]); + + /* Add Extension Details */ + + ExtensionDecode(SaveEDX); + break; + + case 7: + + /* Get Word */ + + Memory_Fetch('W',EDI,TRUE); +// fprintf(fp, "\t\t movsx edi,di\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + break; + + case 8: + + /* Get Long */ + + Memory_Fetch('L',EDI,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + break; + + case 9: + + AccessType = PCREL; + + Memory_Fetch('W',EAX,TRUE); +// fprintf(fp, "\t\t movsx eax,ax\n"); + fprintf(fp, "\t\t mov EDI,ESI ; Get PC\n"); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add edi,eax ; Add Offset to PC\n"); + break; + + case 10: + + AccessType = PCREL; + + /* Get PC */ + + fprintf(fp, "\t\t mov edi,esi ; Get PC\n"); + + /* Add Extension Details */ + + ExtensionDecode(SaveEDX); + + break; + + case 19: + + /* (A7)+ */ + + fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 2\n",REG_A7); + break; + + case 20: + + /* -(A7) */ + + fprintf(fp, "\t\t mov edi,[%s] ; Get A7\n",REG_A7); + fprintf(fp, "\t\t sub edi,byte 2\n"); + fprintf(fp, "\t\t mov [%s],edi\n",REG_A7); + break; + + } +} + +/* Read from Effective Address + * + * mode = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * Flag = Registers to preserve (EDX is handled by SaveEDX) + * + * Return + * Dreg = Register to return result in (EAX is usually most efficient) + * (modes 5 to 10) EDI = Address of data read (masked with FFFFFF) + */ + +void EffectiveAddressRead(int mode,char Size,int Rreg,int Dreg,const char *flags,int SaveEDX) +{ + char* Regname=""; + int MaskMode; + char Flags[8]; + + AccessType = NORMAL; + + strcpy(Flags,flags); + + /* Which Masking to Use */ + + if (Flags[5] != '-') + MaskMode = 2; + else + MaskMode = 1; + + if (SaveEDX) + Flags[3] = 'D'; + else + Flags[3] = '-'; + + switch (Size) + { + case 66: + Regname = regnamesshort[Dreg]; + break; + + case 87: + Regname = regnamesword[Dreg]; + break; + + case 76: + Regname = regnameslong[Dreg]; + break; + } + + switch (mode & 15) + { + + case 0: + + /* Read 32 bits - No prefix */ + + fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_DAT,regnameslong[Rreg]); + break; + + case 1: + + /* Read 32 bits - No prefix */ + + fprintf(fp, "\t\t mov %s,[%s+%s*4]\n",regnameslong[Dreg],REG_ADD,regnameslong[Rreg]); + break; + + case 2: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 3: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 4: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + + case 5: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 6: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 7: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 8: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 9: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 10: + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + + Memory_Read(Size,EDI,Flags,MaskMode); + + if (Dreg != EAX) + { + fprintf(fp, "\t\t mov %s,EAX\n",regnameslong[Dreg]); + } + break; + + case 11: + + /* Immediate - for SR or CCR see ReadCCR() */ + + if (Size == 'L') + { + Memory_Fetch('L',Dreg,FALSE); + fprintf(fp, "\t\t add esi,byte 4\n"); + } + else + { + Memory_Fetch('W',Dreg,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + }; + break; + } +} + +/* + * EA = Effective Address from Instruction + * Size = Byte,Word or Long + * Rreg = Register with Register Number in + * + * Writes from EAX + */ + +void EffectiveAddressWrite(int mode,char Size,int Rreg,int CalcAddress,const char *flags,int SaveEDX) +{ + int MaskMode; + char* Regname=""; + char Flags[8]; + + + strcpy(Flags,flags); + + /* Which Masking to Use ? */ + + if (CalcAddress) + { + if (Flags[5] != '-') + MaskMode = 2; + else + MaskMode = 1; + } + else + MaskMode = 0; + + if (SaveEDX) + Flags[3] = 'D'; + else + Flags[3] = '-'; + + switch (Size) + { + case 66: + Regname = regnamesshort[0]; + break; + + case 87: + Regname = regnamesword[0]; + break; + + case 76: + Regname = regnameslong[0]; + break; + } + + switch (mode & 15) + { + + case 0: + fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_DAT,regnameslong[Rreg],Regname); + break; + + case 1: + if (Size == 66) + { + /* Not Allowed */ + + fprintf(fp, "DUFF CODE!\n"); + } + else + { + if (Size == 87) + { + fprintf(fp, "\t\t cwde\n"); + } + + fprintf(fp, "\t\t mov [%s+%s*4],%s\n",REG_ADD,regnameslong[Rreg],regnameslong[0]); + } + break; + + case 2: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 3: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 4: + if (CalcAddress) EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 5: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 6: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 7: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 8: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 9: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 10: + if (CalcAddress) + { + fprintf(fp, "\t\t push EAX\n"); + EffectiveAddressCalculate(mode,Size,Rreg,SaveEDX); + fprintf(fp, "\t\t pop EAX\n"); + } + Memory_Write(Size,EDI,EAX,Flags,MaskMode); + break; + + case 11: + + /* SR, CCR - Chain to correct routine */ + + WriteCCR(Size); + } +} + +/* Condition Decode Routines */ + +/* + * mode = condition to check for + * + * Returns LABEL that is jumped to if condition is Condition + * + * Some conditions clobber AH + */ + +char *ConditionDecode(int mode, int Condition) +{ + char *Label = GenerateLabel(0,1); + + switch (mode) + { + + case 0: /* A - Always */ + if (Condition) + { + fprintf(fp, "\t\t jmp near %s\n",Label); + } + break; + + case 1: /* F - Never */ + if (!Condition) + { + fprintf(fp, "\t\t jmp near %s\n",Label); + } + break; + + case 2: /* Hi */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + + if (Condition) + { + fprintf(fp, "\t\t ja near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jbe near %s\n",Label); + } + break; + + case 3: /* Ls */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + + if (Condition) + { + fprintf(fp, "\t\t jbe near %s\n",Label); + } + else + { + fprintf(fp, "\t\t ja near %s\n",Label); + } + break; + + case 4: /* CC */ + fprintf(fp, "\t\t test dl,1H\t\t;check carry\n"); + + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + break; + + case 5: /* CS */ + fprintf(fp, "\t\t test dl,1H\t\t;check carry\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + break; + + case 6: /* NE */ + fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + break; + + case 7: /* EQ */ + fprintf(fp, "\t\t test dl,40H\t\t;Check zero\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n",Label); + } + break; + + case 8: /* VC */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + break; + + case 9: /* VS */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + break; + + case 10: /* PL */ + fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n"); + if (Condition) + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + break; + + case 11: /* MI */ + fprintf(fp,"\t\t test dl,80H\t\t;Check Sign\n"); + if (Condition) + { + fprintf(fp, "\t\t jnz near %s\n", Label); + } + else + { + fprintf(fp, "\t\t jz near %s\n", Label); + } + break; + + case 12: /* GE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jge near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jl near %s\n",Label); + } + break; + + case 13: /* LT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jl near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jge near %s\n",Label); + } + break; + + case 14: /* GT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jg near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jle near %s\n",Label); + } + break; + + case 15: /* LE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + if (Condition) + { + fprintf(fp, "\t\t jle near %s\n",Label); + } + else + { + fprintf(fp, "\t\t jg near %s\n",Label); + } + break; + } + + return Label; +} + +/* + * mode = condition to check for + * SetWhat = text for assembler command (usually AL or address descriptor) + * + * Some conditions clobber AH + */ + +void ConditionCheck(int mode, char *SetWhat) +{ + switch (mode) + { + + case 0: /* A - Always */ + fprintf(fp, "\t\t mov %s,byte 0ffh\n",SetWhat); + break; + + case 1: /* F - Never */ + if (SetWhat[1] == 'L') + { + ClearRegister(EAX); + } + else + { + fprintf(fp, "\t\t mov %s,byte 0h\n",SetWhat); + } + break; + + case 2: /* Hi */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + fprintf(fp, "\t\t seta %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 3: /* Ls */ + fprintf(fp, "\t\t mov ah,dl\n"); + fprintf(fp, "\t\t sahf\n"); + fprintf(fp, "\t\t setbe %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 4: /* CC */ + fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 5: /* CS */ + fprintf(fp, "\t\t test dl,1\t\t;Check Carry\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 6: /* NE */ + fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 7: /* EQ */ + fprintf(fp, "\t\t test dl,40H\t\t;Check Zero\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 8: /* VC */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 9: /* VS */ + fprintf(fp, "\t\t test dh,8H\t\t;Check Overflow\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 10: /* PL */ + fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n"); + fprintf(fp, "\t\t setz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 11: /* MI */ + fprintf(fp, "\t\t test dl,80H\t\t;Check Sign\n"); + fprintf(fp, "\t\t setnz %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 12: /* GE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setge %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 13: /* LT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setl %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 14: /* GT */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setg %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + + case 15: /* LE */ + fprintf(fp, "\t\t or edx,200h\n"); + fprintf(fp, "\t\t push edx\n"); + fprintf(fp, "\t\t popf\n"); + fprintf(fp, "\t\t setle %s\n",SetWhat); + fprintf(fp, "\t\t neg byte %s\n",SetWhat); + break; + } +} + + +/**********************************************************************/ +/* Instructions - Each routine generates a range of instruction codes */ +/**********************************************************************/ + +/* + * Immediate Commands + * + * ORI 00xx + * ANDI 02xx + * SUBI 04xx + * ADDI 06xx + * EORI 0axx + * CMPI 0cxx + * + */ + +void dump_imm( int type, int leng, int mode, int sreg ) +{ + int Opcode,BaseCode ; + char Size=' ' ; + char * RegnameEBX="" ; + char * Regname="" ; + char * OpcodeName[16] = {"or ", "and", "sub", "add",0,"xor","cmp",0} ; + int allow[] = {1,0,1,1, 1,1,1,1, 1,0,0,0, 0,0,0,0, 0,0,0,1, 1} ; + + Opcode = (type << 9) | ( leng << 6 ) | ( mode << 3 ) | sreg; + + BaseCode = Opcode & 0xfff8; + + if (mode == 7) BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + if (type != 4) /* Not Valid (for this routine) */ + { + int Dest = EAtoAMN(Opcode, FALSE); + int SetX; + + /* ADDI & SUBI also set X flag */ + + SetX = ((type == 2) || (type == 3)); + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (allow[Dest]) + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 8; + else + { + TimingCycles += (CPU==2) ? 8 : 14; + if ((type != 1) && (type!=6)) + TimingCycles += 2 ; + } + } + else + { + if (type != 6) + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 12 ; + else + TimingCycles += (CPU==2) ? 4 : 20 ; + } + else + { + if (Size != 'L') + TimingCycles += (CPU==2) ? 4 : 8 ; + else + TimingCycles += (CPU==2) ? 4 : 12 ; + } + } + + fprintf(fp, "\t\t and ecx,byte 7\n"); + + /* Immediate Mode Data */ + EffectiveAddressRead(11,Size,EBX,EBX,"--C-S-B",FALSE); + + /* Source Data */ + EffectiveAddressRead(Dest,Size,ECX,EAX,"-BC-SDB",FALSE); + + /* The actual work */ + fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX ); + + SetFlags(Size,EAX,FALSE,SetX,TRUE); + + if (type != 6) /* CMP no update */ + EffectiveAddressWrite(Dest,Size,ECX,EAX,"---DS-B",FALSE); + + Completed(); + } + } + else + { + /* Logicals are allowed to alter SR/CCR */ + + if ((!SetX) && (Dest == 11) && (Size != 'L') && (type != 6)) + { + Align(); + + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + TimingCycles += 20 ; + + if (Size=='W') + { + /* If SR then must be in Supervisor Mode */ + + char *Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jne near %s\n\n",Label); + + /* User Mode - Exception */ + + Exception(8,BaseCode); + + fprintf(fp, "%s:\n",Label); + } + + /* Immediate Mode Data */ + EffectiveAddressRead(11,Size,EBX,EBX,"---DS-B",TRUE); + + ReadCCR(Size,ECX); + + fprintf(fp, "\t\t %s %s,%s\n", OpcodeName[type], Regname, RegnameEBX ); + + WriteCCR(Size); + + Completed(); + } + else + { + + /* Illegal Opcode */ + + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + } + else + { + BaseCode = -2; + } + + OpcodeArray[Opcode] = BaseCode; +} + +void immediate(void) +{ + int type, size, mode, sreg ; + + for (type = 0 ; type < 0x7; type++) + for (size = 0 ; size < 3 ; size++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dump_imm( type, size, mode, sreg ) ; +} + + +/* + * Bitwise Codes + * + */ + +void dump_bit_dynamic( int sreg, int type, int mode, int dreg ) +{ + int Opcode, BaseCode ; + char Size ; + char *EAXReg,*ECXReg, *Label ; + char allow[] = "0-2345678-------" ; + int Dest ; + + /* BTST allows x(PC) and x(PC,xr.s) - others do not */ + + if (type == 0) + { + allow[9] = '9'; + allow[10] = 'a'; + allow[11] = 'b'; // dave fix to nhl + } + + Opcode = 0x0100 | (sreg << 9) | (type<<6) | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x01f8 ; + if (mode == 7) BaseCode |= dreg ; + + + // A7+, A7- + +#ifdef A7ROUTINE + if ((mode > 2) && (mode < 5)) + { + if (dreg == 7) BaseCode |= dreg; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (mode == 0) /* long*/ + { + /* Modify register memory directly */ + + Size = 'L' ; + EAXReg = REG_DAT_EBX; + ECXReg = regnameslong[ECX]; + } + else + { + Size = 'B' ; + EAXReg = regnamesshort[EAX]; + ECXReg = regnamesshort[ECX]; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode<2) + { + switch (type) + { + case 0: + TimingCycles += 6 ; + break; + case 1: + case 3: + TimingCycles += 8 ; + break; + case 2: + TimingCycles += 10; + break; + } + } + else + { + if (type==0) + TimingCycles += 4; + else + TimingCycles += 8; + } + + /* Only need this sorted out if a register is involved */ + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + /* Get bit number and create mask in ECX */ + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov ecx, [%s+ECX*4]\n",REG_DAT); + + if (Size == 'L') + fprintf(fp, "\t\t and ecx, byte 31\n"); + else + fprintf(fp, "\t\t and ecx, byte 7\n"); + + #ifdef QUICKZERO + fprintf(fp,"\t\t mov eax,1\n"); + #else + fprintf(fp,"\t\t xor eax,eax\n"); + fprintf(fp,"\t\t inc eax\n"); + #endif + + fprintf(fp,"\t\t shl eax,cl\n"); + fprintf(fp,"\t\t mov ecx,eax\n"); + + if (mode != 0) + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE); + + + /* All commands copy existing bit to Zero Flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n"); + fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg); + fprintf(fp,"\t\t jz short %s\n",Label); + fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n"); + fprintf(fp,"%s:\n",Label); + + /* Some then modify the data */ + + switch (type) + { + case 0: /* btst*/ + break; + + case 1: /* bchg*/ + fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg); + break; + + case 2: /* bclr*/ + fprintf(fp,"\t\t not ecx\n"); + fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg); + break; + + case 3: /* bset*/ + fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg); + break; + } + + if ((mode !=0) && (type != 0)) + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void bitdynamic(void) /* dynamic non-immediate bit operations*/ +{ + int type, sreg, mode, dreg ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ;mode++) + for (dreg = 0 ; dreg < 8 ;dreg++) + dump_bit_dynamic( sreg, type, mode, dreg ) ; +} + +void dump_bit_static(int type, int mode, int dreg ) +{ + int Opcode, BaseCode ; + char Size ; + char *EAXReg,*ECXReg, *Label ; + char allow[] = "0-2345678-------" ; + int Dest ; + + /* BTST allows x(PC) and x(PC,xr.s) - others do not */ + + if (type == 0) + { + allow[9] = '9'; + allow[10] = 'a'; + } + + Opcode = 0x0800 | (type<<6) | (mode<<3) | dreg ; + BaseCode = Opcode & 0x08f8 ; + if (mode == 7) BaseCode |= dreg ; + + // A7+, A7- + +#ifdef A7ROUTINE + if ((mode > 2) && (mode < 5)) + { + if (dreg == 7) BaseCode |= dreg; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (mode == 0) /* long*/ + { + /* Modify register memory directly */ + + Size = 'L' ; + EAXReg = REG_DAT_EBX; + ECXReg = regnameslong[ECX]; + } + else + { + Size = 'B' ; + EAXReg = regnamesshort[EAX]; + ECXReg = regnamesshort[ECX]; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + /* Save Previous PC if Memory Access */ + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode<2) + { + switch (type) + { + case 0: + TimingCycles += 10 ; + break ; + case 1: + case 3: + TimingCycles += 12 ; + break ; + case 2: + TimingCycles += 14 ; + break ; + } + } + else + { + if (type != 0) + TimingCycles += 12 ; + else + TimingCycles += 8 ; + } + + /* Only need this sorted out if a register is involved */ + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + } + + /* Get bit number and create mask in ECX */ + + Memory_Fetch('W',ECX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (Size == 'L') + fprintf(fp, "\t\t and ecx, byte 31\n"); + else + fprintf(fp, "\t\t and ecx, byte 7\n"); + + #ifdef QUICKZERO + fprintf(fp,"\t\t mov eax,1\n"); + #else + fprintf(fp,"\t\t xor eax,eax\n"); + fprintf(fp,"\t\t inc eax\n"); + #endif + + fprintf(fp,"\t\t shl eax,cl\n"); + fprintf(fp,"\t\t mov ecx,eax\n"); + + if (mode != 0) + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",TRUE); + + /* All commands copy existing bit to Zero Flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp,"\t\t or edx,byte 40h\t; Set Zero Flag\n"); + fprintf(fp,"\t\t test %s,%s\n",EAXReg,ECXReg); + fprintf(fp,"\t\t jz short %s\n",Label); + fprintf(fp,"\t\t xor edx,byte 40h\t; Clear Zero Flag\n"); + fprintf(fp,"%s:\n",Label); + + /* Some then modify the data */ + + switch (type) + { + case 0: /* btst*/ + break; + + case 1: /* bchg*/ + fprintf(fp,"\t\t xor %s,%s\n",EAXReg,ECXReg); + break; + + case 2: /* bclr*/ + fprintf(fp,"\t\t not ecx\n"); + fprintf(fp,"\t\t and %s,%s\n",EAXReg,ECXReg); + break; + + case 3: /* bset*/ + fprintf(fp,"\t\t or %s,%s\n",EAXReg,ECXReg); + break; + } + + if ((mode !=0) && (type != 0)) + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + + +void bitstatic(void) /* static non-immediate bit operations*/ +{ + int type, mode, dreg ; + + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ;mode++) + for (dreg = 0 ; dreg < 8 ;dreg++) + dump_bit_static( type, mode, dreg ) ; +} + +/* + * Move Peripheral + * + */ + +void movep(void) +{ + int sreg,dir,leng,dreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + { + for (dir = 0 ; dir < 2 ; dir++) + { + for (leng = 0 ; leng < 2 ; leng++) + { + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x0108 | (sreg<<9) | (dir<<7) | (leng<<6) | dreg; + BaseCode = Opcode & 0x01c8 ; + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (leng == 0) /* word */ + TimingCycles += 16 ; + else + TimingCycles += 24 ; + + /* Save Flags Register (so we only do it once) */ + + fprintf(fp, "\t\t push edx\n"); + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + /* Get Address to Read/Write in EDI */ + + EffectiveAddressCalculate(5,'L',EBX,FALSE); + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + + if (dir == 0) /* from memory to register*/ + { + Memory_Read('B',EDI,"-BC-SDB",2); /* mask first call */ + fprintf(fp,"\t\t mov bh,al\n"); + fprintf(fp,"\t\t add edi,byte 2\n"); + Memory_Read('B',EDI,"-BC-SDB",0); /* not needed then */ + fprintf(fp,"\t\t mov bl,al\n"); + + if (leng == 0) /* word d(Ax) into Dx.W*/ + { + fprintf(fp,"\t\t mov [%s+ecx*4],bx\n",REG_DAT); + } + else /* long d(Ax) into Dx.L*/ + { + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t shl ebx,16\n"); + Memory_Read('B',EDI,"-BC-SDB",0); + fprintf(fp,"\t\t mov bh,al\n"); + fprintf(fp,"\t\t add edi,byte 2\n"); + Memory_Read('B',EDI,"-BC-S-B",0); + fprintf(fp,"\t\t mov bl,al\n"); + fprintf(fp,"\t\t mov [%s+ecx*4],ebx\n",REG_DAT); + } + } + else /* Register to Memory*/ + { + fprintf(fp,"\t\t mov eax,[%s+ecx*4]\n",REG_DAT); + + /* Move bytes into Line */ + + if (leng == 1) + fprintf(fp,"\t\t rol eax,byte 8\n"); + else + fprintf(fp,"\t\t rol eax,byte 24\n"); + + Memory_Write('B',EDI,EAX,"A---SDB",2); /* Mask First */ + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + + if (leng == 1) /* long*/ + { + Memory_Write('B',EDI,EAX,"A---SDB",0); + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + Memory_Write('B',EDI,EAX,"A---SDB",0); + fprintf(fp,"\t\t add edi,byte 2\n"); + fprintf(fp,"\t\t rol eax,byte 8\n"); + } + Memory_Write('B',EDI,EAX,"A---S-B",0); + } + + fprintf(fp, "\t\t pop edx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } + } + } +} + +void movecodes(int allowfrom[],int allowto[],int Start,char Size) /* MJC */ +{ + int Opcode; + int Src,Dest; + int SaveEDX; + int BaseCode; + + for (Opcode=Start;Opcode> 6, TRUE); + + if ((allowfrom[(Src & 15)]) && (allowto[(Dest & 15)])) + { + /* If we are not going to calculate the flags */ + /* we need to preserve the existing ones */ + + SaveEDX = (Dest == 1); + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (((Src >= 2) && (Src <= 10)) || ((Dest >= 2) && (Dest <=10))) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + + TimingCycles += 4 ; + + if (Src < 7) + { + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + + if ((Src == 0) && allowfrom[1]) + fprintf(fp, "\t\t and ebx,byte 15\n"); + else + fprintf(fp, "\t\t and ebx,byte 7\n"); + + EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX); + } + else + { + if ((Src == 0) && allowfrom[1]) + fprintf(fp, "\t\t and ecx,byte 15\n"); + else + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Src,Size,ECX,EAX,"---DS-B",SaveEDX); + } + } + else + { + if (Dest < 7) + EffectiveAddressRead(Src,Size,EBX,EAX,"--CDS-B",SaveEDX); + else + EffectiveAddressRead(Src,Size,EBX,EAX,"---DS-B",SaveEDX); + } + + /* No flags if Destination Ax */ + + if (!SaveEDX) + { + SetFlags(Size,EAX,TRUE,FALSE,TRUE); + } + + if (Dest < 7) + { + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + EffectiveAddressWrite(Dest,Size,ECX,TRUE,"---DS-B",SaveEDX); + + Completed(); + } + else + { + BaseCode = -1; /* Invalid Code */ + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + if (OpcodeArray[Opcode] < 0) + OpcodeArray[Opcode] = BaseCode; + } +} + +void moveinstructions(void) +{ + int allowfrom[] = {1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}; + int allowto[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + + /* For Byte */ + + movecodes(allowfrom,allowto,0x1000,'B'); + + /* For Word & Long */ + + allowto[1] = 1; + movecodes(allowfrom,allowto,0x2000,'L'); + movecodes(allowfrom,allowto,0x3000,'W'); +} + +/* + * + * Opcodes 5### + * + * ADDQ,SUBQ,Scc and DBcc + * + */ + +void opcode5(void) +{ + /* ADDQ,SUBQ,Scc and DBcc */ + + int allowtoScc[] = {1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + int allowtoADDQ[] = {1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0}; + int Opcode,BaseCode; + char Label[32]; + char Label2[32]; + char Size=' '; + char* Regname=""; + char* RegnameECX=""; + + for (Opcode = 0x5000;Opcode < 0x6000;Opcode++) + { + if ((Opcode & 0xc0) == 0xc0) + { + /* Scc or DBcc */ + + BaseCode = Opcode & 0x5FF8; + if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7); + + /* If mode = 3 or 4 and register = A7 */ + /* then make it a separate code */ + +#ifdef A7ROUTINE + if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27)) + { + BaseCode |= 0x07; + } +#endif + + if (OpcodeArray[BaseCode] == -2) + { + OpcodeArray[BaseCode] = BaseCode; + + if ((BaseCode & 0x38) == 0x8) + { + /* DBcc */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + TimingCycles += 10 ; + + + strcpy(Label,GenerateLabel(BaseCode,1)) ; + strcpy(Label2,ConditionDecode((Opcode >> 8) & 0x0F,TRUE)); + + /* False - Decrement Counter - Loop if not -1 */ + + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ax,[%s+ecx*4]\n",REG_DAT); + fprintf(fp, "\t\t dec ax\n"); + fprintf(fp, "\t\t mov [%s+ecx*4],ax\n",REG_DAT); + fprintf(fp, "\t\t inc ax\t\t; Is it -1\n"); + fprintf(fp, "\t\t jz short %s\n",Label); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + Completed(); + + /* True - Exit Loop */ + fprintf(fp, "%s:\n",Label); + + fprintf(fp, "%s:\n",Label2); + fprintf(fp, "\t\t add esi,byte 4\n"); + TimingCycles += 2 ; + + Completed(); + } + else + { + /* Scc */ + + int Dest = EAtoAMN(Opcode, FALSE); + + if (allowtoScc[(Dest & 15)]) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Dest > 1) + TimingCycles += 8 ; + else + TimingCycles += 4 ; + + if (Dest < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (Dest > 1) + { + EffectiveAddressCalculate(Dest,'B',ECX,TRUE); + /* ASG - no longer need to mask addresses here */ +/* fprintf(fp,"\t\t and edi,0FFFFFFh\n");*/ + } + + ConditionCheck((Opcode >> 8) & 0x0F,"AL"); + + EffectiveAddressWrite(Dest,'B',ECX,FALSE,"---DS-B",TRUE); + + /* take advantage of AL being 0 for false, 0xff for true */ + /* need to add 2 cycles if register and condition is true */ + + if (Dest == 0) + { + fprintf(fp, "\t\t and eax,byte 2\n"); + fprintf(fp, "\t\t add eax,byte %d\n",TimingCycles); + fprintf(fp, "\t\t sub dword [%s],eax\n",ICOUNT); + + TimingCycles = -1; + } + Completed(); + } + else + { + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + OpcodeArray[Opcode] = BaseCode; + } + else + { + /* ADDQ or SUBQ */ + + BaseCode = Opcode & 0x51F8; + if ((BaseCode & 0x38) == 0x38) BaseCode |= (Opcode & 7); + + /* Special for Address Register Direct - Force LONG */ + + if ((Opcode & 0x38) == 0x8) BaseCode = ((BaseCode & 0xFF3F) | 0x80); + + + /* If mode = 3 or 4 and Size = byte and register = A7 */ + /* then make it a separate code */ + +#ifdef A7ROUTINE + if ((Opcode & 0xC0) == 0) + { + if (((Opcode & 0x3F) == 0x1F) || ((Opcode & 0x3F) == 0x27)) + { + BaseCode |= 0x07; + } + } +#endif + + if (OpcodeArray[BaseCode] == -2) + { + char *Operation; + int Dest = EAtoAMN(Opcode, FALSE); + int SaveEDX = (Dest == 1); + + if (allowtoADDQ[(Dest & 15)]) + { + switch (BaseCode & 0xC0) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + + case 0x40: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + + case 0x80: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + OpcodeArray[BaseCode] = BaseCode; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Dest == 0) /* write to Dx */ + { + if (Size != 'L') + TimingCycles += 4 ; + else + TimingCycles += 8 ; + } + + if (Dest == 1) + { + if ((Size == 'L') || (Opcode & 0x100)) /* if long or SUBQ */ + TimingCycles += 8 ; + else + TimingCycles += 4 ; + } + + if (Dest > 1) /* write to mem */ + { + if (Size != 'L') + TimingCycles += 8 ; + else + TimingCycles += 12 ; + } + + if (Dest < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + if (Dest > 1) + { + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX); + } + + /* Sub Immediate from Opcode */ + + fprintf(fp, "\t\t shr ecx,9\n"); + + Immediate8(); + + if (Opcode & 0x100) + { + /* SUBQ */ + Operation = "sub"; + } + else + { + /* ADDQ */ + Operation = "add"; + } + + /* For Data or Address register, operate directly */ + /* on the memory location. Don't load into EAX */ + + if (Dest < 2) + { + if (Dest == 0) + { + fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_DAT,RegnameECX); + } + else + { + fprintf(fp, "\t\t %s [%s+ebx*4],%s\n",Operation,REG_ADD,RegnameECX); + } + } + else + { + fprintf(fp, "\t\t %s %s,%s\n",Operation,Regname,RegnameECX); + } + + /* No Flags for Address Direct */ + + if (!SaveEDX) + { + /* Directly after ADD or SUB, so test not needed */ + + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + } + + if (Dest > 1) + { + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE); + } + + Completed(); + } + else + { + OpcodeArray[BaseCode] = -1; + BaseCode = -1; + } + } + else + { + BaseCode = OpcodeArray[BaseCode]; + } + + OpcodeArray[Opcode] = BaseCode; + } + } +} + +/* + * Branch Instructions + * + * BSR, Bcc + * + */ + +void branchinstructions(void) +{ + int Opcode,BaseCode; + int Counter; + char *Label; + char jmpLabel[40] ; + + for (Opcode = 0x60;Opcode < 0x70;Opcode++) + { + /* Displacement = 0 -> 16 Bit displacement */ + + BaseCode = Opcode * 0x100; + OpcodeArray[BaseCode] = BaseCode; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode == 0x60) + { + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode); + Completed(); + } + else + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + + fprintf(fp, "\t\t add esi,byte 2\n"); + + /* 2 less cycles for Failure */ + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + + Align(); + fprintf(fp, "%s:\n",Label); + + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+2); + Completed(); + + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + Memory_Fetch('W',EBX,TRUE); + fprintf(fp, "\t\t add ebx,esi\n"); + + fprintf(fp, "\t\t add esi,byte 2\n"); + PushPC(ECX,EAX,"-B-DS-B",1); + + fprintf(fp, "\t\t mov esi,ebx\n"); + MemoryBanking(BaseCode+3); + Completed(); + } + } + + /* 8 Bit Displacement */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+1,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode > 0x60) + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + + Align(); + fprintf(fp, "%s:\n",Label); + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + PushPC(EDI,EBX,"--CDS-B",1); + } + } + + /* Common Ending */ + + fprintf(fp, "\t\t movsx eax,cl ; Sign Extend displacement\n"); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+5); + Completed(); + + /* Fill up Opcode Array */ + + for (Counter=1;Counter<0x100;Counter++) + OpcodeArray[BaseCode+Counter] = BaseCode+1; + + if(CPU==2) + { + + /* 8 bit 0xff & 68020 instruction - 32 bit displacement */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+0xff,0)); + sprintf( jmpLabel, GenerateLabel(BaseCode+0xff,1) ) ; + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10 ; + + if (Opcode == 0x60) + { + /* bra - always branch */ + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+6); + Completed(); + } + else + { + if (Opcode != 0x61) + { + Label = ConditionDecode(Opcode & 0x0F,TRUE); + + /* Code for Failed branch */ + fprintf(fp, "\t\t add esi,byte 4\n"); + + TimingCycles -= 2; + Completed(); + TimingCycles += 2; + + /* Successful Branch */ + Align(); + fprintf(fp, "%s:\n",Label); + + Memory_Fetch('L',EAX,FALSE); + fprintf(fp, "\t\t add esi,eax\n"); + MemoryBanking(BaseCode+8); + Completed(); + } + else + { + /* BSR - Special Case */ + + TimingCycles += 8 ; + + Memory_Fetch('L',EBX,TRUE); + fprintf(fp, "\t\t add ebx,esi\n"); + + fprintf(fp, "\t\t add esi,byte 4\n"); + PushPC(ECX,EAX,"-B-DS-B",1); + + fprintf(fp, "\t\t mov esi,ebx\n"); + MemoryBanking(BaseCode+9); + Completed(); + } + } + + OpcodeArray[BaseCode+0xff] = BaseCode+0xff; + } + } +} + +/* + * Move Quick Commands + * + * Fairly simple, as only allowed to Data Registers + * + */ + +void moveq(void) +{ + int Count; + + /* The Code */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0x7000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t movsx eax,cl\n"); + fprintf(fp, "\t\t shr ecx,9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + EffectiveAddressWrite(0,'L',ECX,TRUE,"---DS-B",FALSE); + Completed(); + + /* Set OpcodeArray (Not strictly correct, since some are illegal!) */ + + for (Count=0x7000;Count<0x8000;Count++) + { + OpcodeArray[Count] = 0x7000; + } +} + +/* + * Extended version of Add & Sub commands + * + */ + +void addx_subx(void) +{ + int Opcode, BaseCode ; + int regx,type,leng,rm,regy,mode ; + int ModeModX; + int ModeModY; + char Size=' ' ; + char * Regname="" ; + char * RegnameEBX="" ; + char * Operand=""; + char * Label; + + for (type = 0 ; type < 2 ; type ++) /* 0=subx, 1=addx */ + for (regx = 0 ; regx < 8 ; regx++) + for (leng = 0 ; leng < 3 ; leng++) + for (rm = 0 ; rm < 2 ; rm++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0x9100 | (type<<14) | (regx<<9) | (leng<<6) | (rm<<3) | regy ; + + BaseCode = Opcode & 0xd1c8 ; + + ModeModX = 0; + ModeModY = 0; + +#ifdef A7ROUTINE + if ((rm == 1) && (leng == 0)) + { + if (regx == 7) + { + BaseCode |= (regx << 9); + ModeModY = 16; + } + if (regy == 7) + { + BaseCode |= regy; + ModeModX = 16; + } + } +#endif + + if (rm == 0) + mode = 0 ; + else + mode = 4 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (OpcodeArray[BaseCode] == -2) + { + if (type == 0) + Operand = "sbb"; + else + Operand = "adc"; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (mode == 4) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + /* don't add in EA timing for ADDX,SUBX */ + + AddEACycles = 0 ; + + if (rm == 0) /* reg to reg */ + { + if (Size != 'L') + TimingCycles += 4 ; + else + TimingCycles += 8 ; + } + else + { + if (Size != 'L') + TimingCycles += 18 ; + else + TimingCycles += 30 ; + } + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + /* Get Source */ + + EffectiveAddressRead(mode+ModeModX,Size,EBX,EBX,"--CDS-B",FALSE); + + /* Get Destination (if needed) */ + + if (mode == 4) + EffectiveAddressRead(mode+ModeModY,Size,ECX,EAX,"-BCDSDB",FALSE); + + /* Copy the X flag into the Carry Flag */ + + CopyX(); + + /* Do the sums */ + + if (mode == 0) + fprintf(fp, "\t\t %s [%s+ecx*4],%s\n",Operand,REG_DAT,RegnameEBX); + else + fprintf(fp, "\t\t %s %s,%s\n",Operand,Regname,RegnameEBX); + + /* Preserve old Z flag */ + + fprintf(fp, "\t\t mov ebx,edx\n"); + + /* Set the Flags */ + + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + + /* Handle the Z flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + fprintf(fp, "\t\t and dl,0BFh ; Remove Z\n"); + fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or dl,bl ; Copy across\n\n"); + fprintf(fp, "%s:\n",Label); + + /* Update the Data (if needed) */ + + if (mode == 4) + EffectiveAddressWrite(mode,Size,ECX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Logicals / Simple Maths (+ and -) + * + * OR,AND,CMP,EOR,ADD and SUB + * + */ + +void dumpx( int start, int reg, int type, char * Op, int dir, int leng, int mode, int sreg ) +{ + int Opcode,BaseCode ; + char Size=' ' ; + char * RegnameECX="" ; + char * Regname="" ; + int Dest ; + int SaveEDX ; + int SaveDir; + char * allow="" ; + char * allowtypes[] = { "0-23456789ab----", "--2345678-------", + "0123456789ab----", "0-2345678-------"}; + + SaveDir = dir; + + switch (type) + { + case 0: /* or and*/ + if (dir == 0) + allow = allowtypes[0]; + else + allow = allowtypes[1]; + break ; + + case 1: /* cmp*/ + allow = allowtypes[2] ; + break ; + + case 2: /* eor*/ + allow = allowtypes[3] ; + break ; + + case 3: /* adda suba cmpa*/ + allow = allowtypes[2] ; + break ; + + case 4: /* sub add*/ + if (dir == 0) + allow = allowtypes[0] ; + else + allow = allowtypes[1] ; + break ; + } + + if ((type == 4) && (dir == 0) && (leng > 0)) + { + allow = allowtypes[2] ; /* word and long ok*/ + } + + Opcode = start | (reg << 9 ) | (dir<<8) | (leng<<6) | (mode<<3) | sreg; + + BaseCode = Opcode & 0xf1f8; + + if (mode == 7) BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((mode == 3 || mode == 4) && ( leng == 0 ) && (sreg == 7 )) + BaseCode |= sreg ; +#endif + + + + /* If Source = Data or Address register - combine into same routine */ + + if (((Opcode & 0x38) == 0x08) && (allow[1] != '-')) + { + BaseCode &= 0xfff7; + } + + Dest = EAtoAMN(Opcode, FALSE); + SaveEDX = (Dest == 1) || (type == 3); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + + case 3: /* cmpa adda suba */ + if (dir == 0) + { + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + } + else + { + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + } + dir = 0 ; + break ; + } + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (dir==0) + { + if (Size != 'L') + TimingCycles += 4; + else + TimingCycles += 6; + } + else + { + if (Size != 'L') + TimingCycles += 8; + else + TimingCycles += 12; + } + + if ((mode == 0) && (dir==0) && (Size == 'L')) + TimingCycles += 2 ; + + if ((mode == 1) && (dir==0) && (Size != 'L')) + TimingCycles += 4 ; + + if (Dest < 7) /* Others do not need reg.no. */ + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + + if ((Dest == 0) & (allow[1] != '-')) + fprintf(fp, "\t\t and ebx,byte 15\n"); + else + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,Size,EBX,EAX,"-BCDSDB",SaveEDX); + + if (dir == 0) + { + if (type != 3) + { + fprintf(fp, "\t\t %s [%s+ECX*4],%s\n",Op ,REG_DAT ,Regname ) ; + + if (type == 4) + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + else + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + } + else + { + if (Size == 'W') + fprintf(fp, "\t\t cwde\n"); + + fprintf(fp, "\t\t %s [%s+ECX*4],EAX\n",Op ,REG_ADD); + + if (Op[0] == 'c') + { + SetFlags('L',EAX,FALSE,FALSE,FALSE); + } + } + } + else + { + fprintf(fp, "\t\t %s %s,[%s+ECX*4]\n", Op, Regname ,REG_DAT ) ; + + if (type == 4) + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + else + SetFlags(Size,EAX,FALSE,FALSE,TRUE); + + EffectiveAddressWrite(Dest,Size,EBX,FALSE,"---DS-B",FALSE); + } + Completed(); + } + + OpcodeArray[Opcode] = BaseCode; + } + + dir = SaveDir; +} + +void typelogicalmath(void) +{ + int dir, leng, mode, sreg ,reg ; + + for (reg = 0 ; reg < 8 ; reg++) + { + /* or */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x8000, reg, 0, "or ", dir, leng, mode, sreg ) ; + + /* sub */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x9000, reg, 4, "sub", dir, leng, mode, sreg ) ; + + /* suba */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0x9000, reg, 3, "sub", dir, 3, mode, sreg ) ; + + + /* cmp */ + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb000, reg, 1, "cmp", 0, leng, mode, sreg ) ; + + /* cmpa */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb000, reg, 3, "cmp", dir, 3, mode, sreg ) ; + + /* adda */ + + for (dir = 0 ; dir < 2 ; dir++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xd000, reg, 3, "add", dir, 3, mode, sreg ) ; + + + /* eor */ + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xb100, reg, 2, "xor", 1, leng, mode, sreg ) ; + + /* and */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xc000, reg, 0, "and", dir, leng, mode, sreg ) ; + + /* add */ + for (dir = 0 ; dir < 2 ; dir++) + for (leng = 0 ; leng < 3; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + dumpx( 0xd000, reg, 4, "add", dir, leng, mode, sreg ) ; + } +} + +/* + * Single commands missed out by routines above + * + */ + +void mul(void) +{ + int dreg, type, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xc0c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xc1f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 54 ; + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'W',EBX,EAX,"ABCDSDB",FALSE); + + if (type == 0) + fprintf(fp, "\t\t mul word [%s+ECX*4]\n",REG_DAT); + else + fprintf(fp, "\t\t imul word [%s+ECX*4]\n",REG_DAT); + + fprintf(fp, "\t\t shl edx, byte 16\n"); + fprintf(fp, "\t\t mov dx,ax\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); + SetFlags('L',EDX,TRUE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void mull(void) +{ + int mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char *Label = NULL ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4c00 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4c38 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + TimingCycles += 70 ; + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + Memory_Fetch('W', EBX, FALSE ); // fetch the next word + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EAX,"ABCDSDB",FALSE); // read from the EA + + fprintf(fp, "\t\t mov ecx,ebx\n"); // save 2nd word in ecx + fprintf(fp, "\t\t shr ebx,12\n"); // ebx = Dl register + fprintf(fp, "\t\t and ebx,7\n"); // 0-7 + + Label = GenerateLabel(BaseCode,1); + + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned? + fprintf(fp, "\t\t jz short %s\n",Label); // skip if unsigned + + fprintf(fp, "\t\t imul dword [%s+EBX*4]\n",REG_DAT); // signed 32x32->64 + fprintf(fp, "\t\t jmp short %s_1\n",Label); // skip + + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mul dword [%s+EBX*4]\n",REG_DAT); // unsigned 32x32->64 + + fprintf(fp, "%s_1:\n",Label); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT); // store Dl back + + fprintf(fp, "\t\t test ecx,0x0400\n"); // do we care? + fprintf(fp, "\t\t jz short %s_2\n",Label); // if not, skip + fprintf(fp, "\t\t and ecx,7\n"); // get Dh register + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); // store upper 32 bits + SetFlags('L',EDX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "\t\t and edx,~0x0800\n"); // clear the overflow + fprintf(fp, "\t\t jmp short %s_3\n",Label); // skip + + fprintf(fp, "%s_2:\n",Label); + fprintf(fp, "\t\t mov ebx,edx\n"); // save upper 32 in ebx + SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "\t\t sar eax,31\n"); // eax = sign-extended + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed/unsigned? + fprintf(fp, "\t\t jnz short %s_4\n",Label); // skip if signed + fprintf(fp, "\t\t xor eax,eax\n"); // always use 0 for unsigned + fprintf(fp, "%s_4:\n",Label); + fprintf(fp, "\t\t cmp eax,ebx\n"); // compare upper 32 against eax + fprintf(fp, "\t\t je short %s_3\n",Label); // if equal to sign extension, skip + fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow + + fprintf(fp, "%s_3:\n",Label); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void divl(void) +{ + int mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char *Label = NULL ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4c40 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4c78 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + TimingCycles += 70 ; + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t push edx\n"); // save edx + fprintf(fp, "\t\t add esi,byte 2\n\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); // read from ea + + Memory_Fetch('W', EDX, FALSE ); // fetch 2nd word in ecx + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EBX,"---DSDB",FALSE); + + fprintf(fp, "\t\t push esi\n"); // save and 0 esi + ClearRegister(ESI); + + Label = GenerateLabel(BaseCode,1); + + fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor against 0 + fprintf(fp, "\t\t jz near %s_ZERO\n",Label); // handle divide-by-zero +// low part always used + fprintf(fp, "\t\t mov ecx,edx\n"); // ecx = extension word + fprintf(fp, "\t\t shr edx,12\n"); // edx = Dq register + fprintf(fp, "\t\t and edx,7\n"); // 0-7 + fprintf(fp, "\t\t mov eax,[%s+edx*4]\n",REG_DAT); // eax = Dq register value + + ClearRegister(EDX); // edx = 0 + fprintf(fp, "\t\t test ecx,0x0400\n"); // check size + fprintf(fp, "\t\t jz short %s_1\n",Label); // skip if 32-bit dividend +// high longword (64bit) + fprintf(fp, "\t\t mov edx,ecx\n"); // edx = extension word + fprintf(fp, "\t\t and edx,7\n"); // 0-7 + fprintf(fp, "\t\t mov edx,[%s+edx*4]\n",REG_DAT); // fetch upper 32-bits + + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed? + fprintf(fp, "\t\t jz near %s_3\n",Label); // if not, skip to unsigned 64-bit + fprintf(fp, "\t\t jmp near %s_2\n",Label); // skip to signed 64-bit case + + fprintf(fp, "%s_1:\n",Label); // short case + ClearRegister(EDX); // clear edx + fprintf(fp, "\t\t test ecx,0x0800\n"); // signed? + fprintf(fp, "\t\t jz short %s_3\n",Label); // if not, don't convert + fprintf(fp, "\t\t cdq\n"); // sign extend into edx +// signed + fprintf(fp, "%s_2:\n",Label); // signed 32/64-bit case + fprintf(fp, "\t\t or esi,1\n"); // esi |= 1 to indicate signed + fprintf(fp, "\t\t test ebx,ebx\n"); // check divisor sign + fprintf(fp, "\t\t jge short %s_2b\n",Label); // if >= 0, don't set + fprintf(fp, "\t\t or esi,2\n"); // esi |= 2 to indicate negative divisor + fprintf(fp, "\t\t neg ebx\n"); // make positive + fprintf(fp, "%s_2b:\n",Label); + fprintf(fp, "\t\t test edx,edx\n"); // check dividend sign + fprintf(fp, "\t\t jge short %s_3\n",Label); // if >= 0, don't set + fprintf(fp, "\t\t push ebx\n"); // save ebx + fprintf(fp, "\t\t push ecx\n"); // save ecx + ClearRegister(EBX); // clear ebx + ClearRegister(ECX); // clear ecx + fprintf(fp, "\t\t sub ebx,eax\n"); // ebx = 0 - eax + fprintf(fp, "\t\t sbb ecx,edx\n"); // ecx = 0 - edx + fprintf(fp, "\t\t mov eax,ebx\n"); // eax = ebx + fprintf(fp, "\t\t mov edx,ecx\n"); // edx = ecx + fprintf(fp, "\t\t pop ecx\n"); // restore ecx + fprintf(fp, "\t\t pop ebx\n"); // restore ebx + fprintf(fp, "\t\t or esi,4\n"); // esi |= 4 to indicate negative dividend +// unsigned + fprintf(fp, "%s_3:\n",Label); // unsigned 32/64-bit case + fprintf(fp, "\t\t cmp ebx,edx\n"); // check ebx against upper 32 bits + fprintf(fp, "\t\t jbe near %s_OVERFLOW\n",Label); // generate overflow + fprintf(fp, "\t\t div ebx\n"); // do the divide + fprintf(fp, "\t\t test esi,esi\n"); // see if we need to post process + fprintf(fp, "\t\t jz short %s_4\n",Label); // if not, skip + fprintf(fp, "\t\t jpo short %s_4\n",Label); // if PO (pos*pos or neg*neg), leave the result + fprintf(fp, "\t\t neg eax\n"); // negate the result + +// store results + fprintf(fp, "%s_4:\n",Label); + fprintf(fp, "\t\t mov ebx,ecx\n"); // ebx = extension word + fprintf(fp, "\t\t and ebx,7\n"); // get Dr in ebx + fprintf(fp, "\t\t shr ecx,12\n"); // ecx = Dq + fprintf(fp, "\t\t and ecx,7\n"); // 0-7 + fprintf(fp, "\t\t mov [%s+ebx*4],edx\n",REG_DAT); // store remainder first + fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_DAT); // store quotient second + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + SetFlags('L',EAX,TRUE,FALSE,FALSE); // set the flags + fprintf(fp, "%s_5:\n",Label); + fprintf(fp, "\t\t and edx,~1\n"); // clear the carry + Completed(); + + fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", Label); + /* Correct cycle counter for error */ + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95); + fprintf(fp,"\t\t jmp short %s_5\n",Label); + Exception(5,BaseCode); + + fprintf(fp, "%s_OVERFLOW:\n",Label); +//set overflow + fprintf(fp, "\t\t pop esi\n"); // restore esi + fprintf(fp, "\t\t pop edx\n"); // restore edx + fprintf(fp, "\t\t or edx,0x0800\n"); // set the overflow bit + fprintf(fp, "\t\t jmp near %s_5\n",Label); // done + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void bfext(void) +{ +// just bfextu/bfexts for now + char allow[] = "0-2--56789a-----" ; + char *Label = NULL ; + int mode,dreg,sign,Opcode,BaseCode,Dest ; + for (mode=0; mode<8; mode++) + for (dreg=0; dreg<8; dreg++) + for (sign=0; sign<2; sign++) + { + Opcode = 0xe9c0 | (sign<<9) | (mode<<3) | dreg ; + BaseCode = Opcode & 0xebf8 ; + if (mode == 7) + BaseCode |= dreg ; + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label); + Label = GenerateLabel(BaseCode,1); + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + Memory_Fetch('W', EAX, FALSE ) ; + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + EffectiveAddressRead(Dest,'L',ECX,EDX,"ABCDSDB",FALSE); // edx = dword + + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t shr ecx,byte 6\n"); + fprintf(fp, "\t\t test eax,0x0800\n"); + fprintf(fp, "\t\t je short %s_1\n",Label); + //get offset from Dx + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t mov ecx,[%s+ECX*4]\n",REG_DAT); + //get offset from extension + fprintf(fp, "%s_1:\n",Label); + fprintf(fp, "\t\t and ecx,31\n"); // ecx = offset + fprintf(fp, "\t\t mov ebx,eax\n"); + fprintf(fp, "\t\t test eax,0x0020\n"); + fprintf(fp, "\t\t je short %s_2\n",Label); + //get width from Dy + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + //get width from extension + fprintf(fp, "%s_2:\n",Label); + //fix 0=32 + fprintf(fp, "\t\t sub ebx,byte 1\n"); + fprintf(fp, "\t\t and ebx,byte 31\n"); + fprintf(fp, "\t\t add ebx,byte 1\n"); // ebx = width + fprintf(fp, "\t\t rol edx,cl\n"); + // check for N + fprintf(fp, "\t\t mov ecx,32\n"); + fprintf(fp, "\t\t sub ecx,ebx\n"); + fprintf(fp, "\t\t mov ebx,edx\n"); + SetFlags('L',EBX,TRUE,FALSE,FALSE); + if (sign) + fprintf(fp, "\t\t sar ebx,cl\n"); + else + fprintf(fp, "\t\t shr ebx,cl\n"); + fprintf(fp, "\t\t shr eax,12\n"); + fprintf(fp, "\t\t and eax,7\n"); + fprintf(fp, "\t\t mov [%s+EAX*4],ebx\n",REG_DAT); + fprintf(fp, "\t\t test ebx,ebx\n"); + fprintf(fp, "\t\t jnz short %s_3\n",Label); + //zero flag + fprintf(fp, "\t\t or edx,40h\n"); + fprintf(fp, "%s_3:\n",Label); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * not + * clr + * neg + * negx + * + */ + +void not(void) +{ + int type,leng, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + int SaveEDX=0; + char Size=' ' ; + char * Regname="" ; + char * RegnameECX ; + char * Label; + + char allow[] = "0-2345678-------" ; + + for (type = 0 ; type < 4 ; type++) + for (leng = 0 ; leng < 3 ; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4000 | (type<<9) | (leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x46f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + // A7+, A7- + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 4; + else + TimingCycles += 6; + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + if (type == 0) SaveEDX = TRUE; + else SaveEDX = FALSE; + + /* CLR does not need to read source (although it does on a real 68000) */ + + if (type != 1) + { + EffectiveAddressRead(Dest,Size,ECX,EAX,"A-CDS-B",SaveEDX); + } + + switch (type) + { + case 0: /* negx */ + + /* Preserve old Z flag */ + + fprintf(fp, "\t\t mov ebx,edx\n"); + + CopyX(); + fprintf(fp, "\t\t adc %s,byte 0\n", Regname ) ; + fprintf(fp, "\t\t neg %s\n", Regname ) ; + + /* Set the Flags */ + + SetFlags(Size,EAX,FALSE,TRUE,FALSE); + + /* Handle the Z flag */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + fprintf(fp, "\t\t and edx,byte -65 ; Remove Z\n"); + fprintf(fp, "\t\t and ebx,byte 40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or edx,ebx ; Copy across\n\n"); + fprintf(fp, "%s:\n",Label); + + break; + + case 1: /* clr */ + ClearRegister(EAX); + EffectiveAddressWrite(Dest,Size,ECX,TRUE,"----S-B",FALSE); + fprintf(fp, "\t\t mov edx,40H\n"); + break; + + case 2: /* neg */ + fprintf(fp, "\t\t neg %s\n",Regname ) ; + SetFlags(Size,EAX,FALSE,TRUE,TRUE); + break; + + case 3: /* not */ + fprintf(fp, "\t\t xor %s,-1\n",Regname ) ; + SetFlags(Size,EAX,FALSE,FALSE,TRUE); + break; + } + + /* Update (unless CLR command) */ + + if (type != 1) + EffectiveAddressWrite(Dest,Size,ECX,FALSE,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Move to/from USP + * + */ + +void moveusp(void) +{ + int Opcode, BaseCode ; + int dir, sreg ; + char * Label; + + for (dir = 0 ; dir < 2 ; dir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4e60 | ( dir << 3 ) | sreg ; + BaseCode = Opcode & 0x4e68 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode); + + fprintf(fp, "\t\t and ecx,7\n"); + + if (dir == 0) /* reg 2 USP */ + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s],eax\n",REG_USP); + } + else + { + fprintf(fp, "\t\t mov eax,[%s]\n",REG_USP); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_ADD); + } + Completed(); + + fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode); + Exception(8,BaseCode); + } + OpcodeArray[Opcode] = BaseCode ; + } +} + + +/* + * Check + * + */ + +void chk(void) +{ + int dreg,mode,sreg,size ; + int Opcode, BaseCode ; + int Dest ; + char * Label ; + + char *allow = "0-23456789ab----" ; + + for (size = 0 ; size < (CPU==2 ? 2 : 1); size++) + for (dreg = 0 ; dreg < 8; dreg++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + if (size == 0) /* word */ + Opcode = 0x4180 | (dreg<<9) | (mode<<3) | sreg ; + else /* long */ + Opcode = 0x4100 | (dreg<<9) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x41f8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t shr ebx,byte 9\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,(size == 0) ? 'W' : 'L',ECX,EAX,"----S-B",FALSE); + + if (size == 0) /* word */ + { + fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t movsx eax,ax\n"); + } + else /* long */ + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + + fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */ + fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode); + + fprintf(fp, "\t\t cmp ebx,eax\n"); + fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode); + Completed(); + + /* N is set if data less than zero */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode); + fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */ + fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode); + + /* N is cleared if greated than compared number */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode); + fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */ + + fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode); + fprintf(fp, "\t\t mov al,6\n"); + Exception(-1,0x10000+BaseCode); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void chk2(void) +{ +#if 0 + int mode,sreg,size ; + int Opcode, BaseCode ; + int Dest ; + char * Label ; + + char *allow = "--2--56789a-----" ; + + for (size = 0 ; size < 2; size++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x00c0 | (size<<9) | (mode<<3) | sreg; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 10; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t shr ebx,byte 9\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,'W',ECX,EAX,"----S-B",FALSE); + + if (size == 0) /* word */ + { + fprintf(fp, "\t\t movsx ebx,word [%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t movsx eax,ax\n"); + } + else /* long */ + fprintf(fp, "\t\t mov ebx,[%s+EBX*4]\n",REG_DAT); + + fprintf(fp, "\t\t test ebx,ebx\n"); /* is word bx < 0 */ + fprintf(fp, "\t\t jl near OP%d_%4.4x_Trap_minus\n",CPU,BaseCode); + + fprintf(fp, "\t\t cmp ebx,eax\n"); + fprintf(fp, "\t\t jg near OP%d_%4.4x_Trap_over\n",CPU,BaseCode); + Completed(); + + /* N is set if data less than zero */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_minus:\n",CPU,BaseCode); + fprintf(fp, "\t\t or edx,0x0080\n"); /* N flag = 80H */ + fprintf(fp, "\t\t jmp short OP%d_%4.4x_Trap_Exception\n",CPU,BaseCode); + + /* N is cleared if greated than compared number */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap_over:\n",CPU,BaseCode); + fprintf(fp, "\t\t and edx,0x007f\n"); /* N flag = 80H */ + + fprintf(fp, "OP%d_%4.4x_Trap_Exception:\n",CPU,BaseCode); + fprintf(fp, "\t\t mov al,6\n"); + Exception(-1,0x10000+BaseCode); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +#endif +} + +/* + * Load Effective Address + */ + +void LoadEffectiveAddress(void) +{ + int Opcode, BaseCode ; + int sreg,mode,dreg ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x41c0 | (sreg<<9) | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x41f8 ; + + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 4; + break; + case 5: + case 7: + case 9: + TimingCycles += 8; + break; + case 6: + case 8: + case 10: + TimingCycles += 12; + break; + } + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressCalculate(Dest,'L',EBX,TRUE); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Negate BCD + * + */ + +void nbcd(void) +{ + int Opcode, BaseCode ; + int sreg,mode,Dest ; + char allow[] = "0-2345678-------" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4800 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4838 ; + + if (mode == 7) + BaseCode |= sreg ; + + // A7+, A7- + +#ifdef A7ROUTINE + if ((sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg; + } +#endif + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + TimingCycles += 6; + else + TimingCycles += 8; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'B',ECX,EBX,"--C-SDB",FALSE); + + ClearRegister(EAX); + CopyX(); + + fprintf(fp, "\t\t sbb al,bl\n"); + fprintf(fp, "\t\t das\n"); + + SetFlags('B',EAX,FALSE,TRUE,TRUE); + + EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void tas(void) +{ + int Opcode, BaseCode ; + int sreg,mode,Dest ; + char allow[] = "0-2345678-------" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4ac0 | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4af8 ; + + if (mode == 7) + BaseCode |= sreg ; + +#ifdef A7ROUTINE + if ((sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (mode < 2) + TimingCycles += 4; + else + TimingCycles += 14; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(Dest,'B',ECX,EAX,"--C-SDB",FALSE); + + SetFlags('B',EAX,TRUE,FALSE,TRUE); + fprintf(fp, "\t\t or al,128\n"); + + EffectiveAddressWrite(Dest,'B',ECX,EAX,"----S-B",FALSE); + Completed(); + } + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * push Effective Address + */ + +void PushEffectiveAddress(void) +{ + int Opcode, BaseCode ; + int mode,dreg ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x4840 | (mode<<3) | dreg ; + + BaseCode = Opcode & 0x4878 ; + + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 12; + break; + case 5: + case 7: + case 9: + TimingCycles += 16; + break; + case 6: + case 8: + case 10: + TimingCycles += 20; + break; + } + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ecx,[%s]\t ; Push onto Stack\n",REG_A7); + fprintf(fp, "\t\t sub ecx,byte 4\n"); + fprintf(fp, "\t\t mov [%s],ecx\n",REG_A7); + Memory_Write('L',ECX,EDI,"---DS-B",2); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Test + * + */ + +void tst(void) +{ + int leng, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size=' ' ; + char * Regname ; + char * RegnameECX ; + + char allow[] = "0-2345678-------" ; + if (CPU==2) + allow[1] = '1'; + + for (leng = 0 ; leng < 3 ; leng++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4a00 | (leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4af8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + // A7+, A7- + +#ifdef A7ROUTINE + if ((leng == 0) && (sreg == 7) && (mode > 2) && (mode < 5)) + { + BaseCode |= sreg ; + } +#endif + + Dest = EAtoAMN(Opcode, FALSE); + + if ((allow[Dest&0x0f] != '-') || (( mode == 1 ) && (leng != 0))) + { + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + if (Dest < 7) + fprintf(fp, "\t\t and ecx,byte 7\n"); + + EffectiveAddressRead(Dest,Size,ECX,EAX,"----S-B",FALSE); + + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Move registers too / from memory + * + */ + +void movem_reg_ea(void) +{ + int leng,mode,sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size ; + char * Label ; + + char *allow = "--2-45678-------" ; + + for (leng = 0 ; leng < 2; leng++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4880 | ( leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4cf8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + Size = "WL"[leng] ; + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s:\n",Label ) ; + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + case 4: + TimingCycles += 8 ; + break; + case 5: + case 7: + TimingCycles += 12 ; + break; + case 6: + case 8: + TimingCycles += 14 ; + break; + } + + fprintf(fp, "\t\t push edx\n"); + + Memory_Fetch('W',EDX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (mode == 4) + { + fprintf(fp, "\t\t push ecx\n"); + fprintf(fp, "\t\t mov edi,[%s+ECX*4]\n",REG_ADD); + } + else + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ebx,1\n"); + + /* predecrement uses d0-d7..a0-a7 a7 first*/ + /* other modes use a7-a0..d7-d0 d0 first*/ + + if (Dest != 4) + ClearRegister(ECX); + else + fprintf(fp, "\t\t mov ecx,3Ch\n"); + + fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode); + fprintf(fp, "\t\t test edx,ebx\n"); + fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode); + + fprintf(fp, "\t\t mov eax,[%s+ecx]\n",REG_DAT); /* load eax with current reg data */ + + if (Dest == 4) + { + if (Size == 'W') /* adjust pointer before write */ + fprintf(fp, "\t\t sub edi,byte 2\n"); + else + fprintf(fp, "\t\t sub edi,byte 4\n"); + } + + Memory_Write(Size,EDI,EAX,"-BCDSDB",1); + + if (Dest != 4) + { + if (Size == 'W') /* adjust pointer after write */ + fprintf(fp, "\t\t add edi,byte 2\n"); + else + fprintf(fp, "\t\t add edi,byte 4\n"); + } + + /* Update Cycle Count */ + + if (Size == 'W') + fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT); + else + fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT); + + fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode); + + if (Dest != 4) + fprintf(fp, "\t\t add ecx,byte 4h\n"); + else + fprintf(fp, "\t\t sub ecx,byte 4h\n"); + + fprintf(fp, "\t\t add ebx,ebx\n"); /* faster than shl ebx,1 */ + fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */ + fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode); + + if (Dest == 4) + { + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + } + + fprintf(fp, "\t\t pop edx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void movem_ea_reg(void) +{ + int leng,mode,sreg ; + int Opcode, BaseCode ; + int Dest ; + char Size ; + char * Label ; + + char *allow = "--23-56789a-----" ; + + for (leng = 0 ; leng < 2; leng++) + for (mode = 0 ; mode < 8; mode++) + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4c80 | ( leng<<6) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x4cf8 ; + + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + + Size = "WL"[leng] ; + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + + fprintf(fp, "%s:\n",Label ) ; + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + case 4: + TimingCycles += 8 ; + break; + case 5: + case 7: + TimingCycles += 12 ; + break; + case 6: + case 8: + TimingCycles += 14 ; + break; + } + + fprintf(fp, "\t\t push edx\n"); /* save edx because sr is unaffected */ + + Memory_Fetch('W',EDX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + if (mode == 3) + fprintf(fp, "\t\t push ecx\n"); /* if (An)+ then it needed later */ + + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + fprintf(fp, "\t\t mov ebx,1\n"); /* setup register list mask */ + + /* predecrement uses d0-d7..a0-a7 a7 first*/ + /* other modes use a7-a0..d7-d0 d0 first*/ + + ClearRegister(ECX); /* always start with D0 */ + + fprintf(fp, "OP%d_%4.4x_Again:\n",CPU,BaseCode); + fprintf(fp, "\t\t test edx,ebx\n"); /* is bit set for this register? */ + fprintf(fp, "\t\t je OP%d_%4.4x_Skip\n",CPU,BaseCode); + + Memory_Read(Size,EDI,"-BCDSDB",1); + + if (Size == 'W') + fprintf(fp, "\t\t cwde\n"); /* word size must be sign extended */ + + fprintf(fp, "\t\t mov [%s+ecx],eax\n",REG_DAT); /* load current reg with eax */ + + if (Size == 'W') /* adjust pointer after write */ + fprintf(fp, "\t\t add edi,byte 2\n"); + else + fprintf(fp, "\t\t add edi,byte 4\n"); + + /* Update Cycle Count */ + + if (Size == 'W') + fprintf(fp, "\t\t sub dword [%s],byte 4\n",ICOUNT); + else + fprintf(fp, "\t\t sub dword [%s],byte 8\n",ICOUNT); + + fprintf(fp, "OP%d_%4.4x_Skip:\n",CPU,BaseCode); + fprintf(fp, "\t\t add ecx,byte 4\n"); /* adjust pointer to next reg */ + fprintf(fp, "\t\t add ebx,ebx\n"); /* Faster than shl ebx,1 */ + fprintf(fp, "\t\t test bx,bx\n"); /* check low 16 bits */ + fprintf(fp, "\t\t jnz OP%d_%4.4x_Again\n",CPU,BaseCode); + + if (mode == 3) + { + fprintf(fp, "\t\t pop ecx\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); /* reset Ax if mode = (Ax)+ */ + } + + fprintf(fp, "\t\t pop edx\n"); /* restore flags */ + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Link / Unlink + * + * Local stack space + * + */ + +void link(void) +{ + int sreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4e50 | sreg ; + BaseCode = 0x4e50 ; + + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 16; + + fprintf(fp, "\t\t sub dword [%s],byte 4\n",REG_A7); + + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + + Memory_Write('L',EDI,EAX,"---DS-B",1); + + Memory_Fetch('W',EAX,TRUE); + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t add [%s],eax\n",REG_A7); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void unlinkasm(void) +{ + int sreg ; + int Opcode, BaseCode ; + + for (sreg = 0 ; sreg < 8; sreg++) + { + Opcode = 0x4e58 | sreg ; + BaseCode = 0x4e58 ; + + if (OpcodeArray[BaseCode] == - 2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 12; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + + Memory_Read('L',EDI,"-B-DSDB",1); + + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + fprintf(fp, "\t\t add edi,byte 4\n"); + fprintf(fp, "\t\t mov dword [%s],EDI\n",REG_A7); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void trap(void) +{ + int Count; + int BaseCode = 0x4E40; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + fprintf(fp, "\t\t mov eax,ecx\n"); + fprintf(fp, "\t\t and eax,byte 15\n"); + fprintf(fp, "\t\t or eax,byte 32\n"); + Exception(-1,BaseCode); + Completed(); + } + + for (Count=0;Count<=15;Count++) + OpcodeArray[BaseCode+Count] = BaseCode; +} + +void reset(void) +{ + int BaseCode = 0x4E70; + char * Label; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + + TimingCycles += 132; + + fprintf(fp, "%s:\n", Label ); + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jnz near OP%d_%4.4x_RESET\n",CPU,BaseCode); + Exception(8,BaseCode); + + fprintf(fp, "\nOP%d_%4.4x_RESET:\n",CPU,BaseCode); + + /* Prefetch next instruction */ + + if(CPU==2) + { + /* 32 bit memory version */ + + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ + } + else + { + /* 16 bit memory */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + + fprintf(fp, "\t\t mov eax,dword [%s]\n", REG_RESET_CALLBACK); + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jz near OP%d_%4.4x_END\n",CPU,BaseCode); + + /* Callback for Reset */ + + fprintf(fp, "\t\t mov [%s],ESI,\n",REG_PC); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + fprintf(fp, "\t\t push ECX\n"); + + fprintf(fp, "\t\t call eax\n"); + + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t pop ECX\n"); + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + + fprintf(fp, "OP%d_%4.4x_END:\n",CPU,BaseCode); + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,TimingCycles); + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n\n", CPUtype); + } + OpcodeArray[BaseCode] = BaseCode ; +} + +void nop(void) +{ + int BaseCode = 0x4e71 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + Completed(); + OpcodeArray[BaseCode] = BaseCode ; + } +} + +void stop(void) +{ + char TrueLabel[16]; + int BaseCode = 0x4e72 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + /* Must be in Supervisor Mode */ + + sprintf(TrueLabel,GenerateLabel(0,1)); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + + /* Next WORD is new SR */ + + Memory_Fetch('W',EAX,FALSE); + fprintf(fp, "\t\t add esi,byte 2\n"); + + WriteCCR('W'); + + /* See if Valid interrupt waiting */ + + CheckInterrupt = 0; + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ); + fprintf(fp, "\t\t and eax,byte 07H\n"); + + fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n"); + fprintf(fp, "\t\t je near procint\n\n"); + + fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH); + fprintf(fp, "\t\t and ebx,byte 07H\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jg near procint\n\n"); + + /* No int waiting - clear count, set stop */ + + ClearRegister(ECX); + fprintf(fp, "\t\t mov [%s],ecx\n",ICOUNT); + fprintf(fp, "\t\t or byte [%s],80h\n",REG_IRQ); + Completed(); + + /* User Mode - Exception */ + + Align(); + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,BaseCode); + + OpcodeArray[BaseCode] = BaseCode ; + } +} + +void ReturnFromException(void) +{ + char TrueLabel[16]; + + int BaseCode = 0x4e73; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 20; + + /* Check in Supervisor Mode */ + + sprintf(TrueLabel,GenerateLabel(0,1)); + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + + /* Get SR - Save in EBX */ + + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7); + Memory_Read('W',EDI,"-----DB",2); + fprintf(fp, "\t\t add edi,byte 2\n"); + fprintf(fp, "\t\t mov esi,eax\n"); + + /* Get PC */ + + Memory_Read('L',EDI,"----S-B",0); + fprintf(fp, "\t\t xchg esi,eax\n"); + + /* Update CCR (and A7) */ + + WriteCCR('W'); + + MemoryBanking(BaseCode); + Completed(); + + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,0x10000+BaseCode); + + OpcodeArray[BaseCode] = BaseCode; +} + +void trapv(void) +{ + int BaseCode = 0x4E76; + char * Label; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + Label = GenerateLabel(BaseCode,0); + fprintf(fp, "%s\n", Label ); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4; + + fprintf(fp, "\t\t test dh,08h\n"); + fprintf(fp, "\t\t jz near OP%d_%4.4x_Clear\n",CPU,BaseCode); + Exception(7,BaseCode); + + fprintf(fp, "OP%d_%4.4x_Clear:\n",CPU,BaseCode); + Completed(); + } + OpcodeArray[BaseCode] = BaseCode ; +} + +void illegal_opcode(void) +{ + Align(); + fprintf(fp, "ILLEGAL:\n"); + fprintf(fp, "\t\t mov [%sillegal_op],ecx\n", PREF); + fprintf(fp, "\t\t mov [%sillegal_pc],esi\n", PREF); + +#if 0 +#ifdef MAME_DEBUG + fprintf(fp, "\t\t jmp ecx\n"); + fprintf(fp, "\t\t pushad\n"); + fprintf(fp, "\t\t call %sm68k_illegal_opcode\n", PREF); + fprintf(fp, "\t\t popad\n"); +#endif +#endif + + Exception(4,0xFFFE); +} + +/* + * Return from subroutine + * restoring flags as well + * + */ + +void ReturnandRestore(void) +{ + int BaseCode = 0x4e77; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 20; + + /* Get SR into ESI */ + + fprintf(fp, "\t\t mov edi,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 6\n",REG_A7); + + Memory_Read('W',EDI,"-----DB",2); + fprintf(fp, "\t\t add edi,byte 2\n"); + fprintf(fp, "\t\t mov esi,eax\n"); + + /* Get PC */ + + Memory_Read('L',EDI,"----SDB",0); + fprintf(fp, "\t\t xchg esi,eax\n"); + + /* Update flags */ + + WriteCCR('B'); + + MemoryBanking(BaseCode); + Completed(); + + OpcodeArray[BaseCode] = BaseCode; +} + +/* + * Return from Subroutine + * + */ + +void rts(void) +{ + int BaseCode = 0x4e75 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + + TimingCycles += 16; + + OpcodeArray[BaseCode] = BaseCode ; + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7); + fprintf(fp, "\t\t add dword [%s],byte 4\n",REG_A7); + Memory_Read('L',EAX,"---D--B",1); + fprintf(fp, "\t\t mov esi,eax\n"); + MemoryBanking(BaseCode); + Completed(); + } +} + +void jmp_jsr(void) +{ + int Opcode, BaseCode ; + int dreg,mode,type ; + int Dest ; + char allow[] = "--2--56789a-----" ; + + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (dreg = 0 ; dreg < 8 ; dreg++) + { + Opcode = 0x4e80 | (type<<6) | (mode<<3) | dreg ; + BaseCode = Opcode & 0x4ef8 ; + if (mode == 7) + BaseCode = BaseCode | dreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + switch (mode) + { + case 2: + TimingCycles += 8; + break; + case 5: + case 7: + case 9: + TimingCycles += 10; + break; + case 8: + TimingCycles += 12; + break; + case 6: + case 10: + TimingCycles += 14; + break; + } + + if (type == 0) /* jsr takes 8 more than jmp */ + TimingCycles += 8; + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + EffectiveAddressCalculate(Dest,'L',ECX,TRUE); + + /* jsr needs to push PC onto stack */ + + if (type == 0) + { + PushPC(EBX,EAX,"---D-DB",1); + } + + fprintf(fp, "\t\t mov esi,edi\n"); + MemoryBanking(BaseCode); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +void cmpm(void) +{ + int Opcode, BaseCode ; + int regx,leng,regy ; + int ModeModX, ModeModY; + char Size=' ' ; + char * Regname="" ; + char * RegnameEBX="" ; + + for (regx = 0 ; regx < 8 ; regx++) + for (leng = 0 ; leng < 3 ; leng++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0xb108 | (regx<<9) | (leng<<6) | regy ; + BaseCode = Opcode & 0xb1c8 ; + + ModeModX = 0; + ModeModY = 0; + +#ifdef A7ROUTINE + if (leng==0) + { + if (regx==7) + { + BaseCode |= (regx<<9); + ModeModX = 16; + } + + if (regy==7) + { + BaseCode |= regy; + ModeModY = 16; + } + } +#endif + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[EAX]; + RegnameEBX = regnamesshort[EBX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[EAX]; + RegnameEBX = regnamesword[EBX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[EAX]; + RegnameEBX = regnameslong[EBX]; + break; + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + SavePreviousPC(); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + AddEACycles = 0 ; + + if (Size != 'L') + TimingCycles += 12 ; + else + TimingCycles += 20 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(3+ModeModY,Size,EBX,EBX,"--C-S-B",FALSE); + EffectiveAddressRead(3+ModeModX,Size,ECX,EAX,"-B--S-B",FALSE); + + fprintf(fp, "\t\t cmp %s,%s\n",Regname,RegnameEBX); + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void exg(void) +{ + int Opcode, BaseCode ; + int regx,type,regy ; + int opmask[3] = { 0x08, 0x09, 0x11} ; + + for (regx = 0 ; regx < 8 ; regx++) + for (type = 0 ; type < 3 ; type++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0xc100 | (regx<<9) | (opmask[type]<<3) | regy ; + BaseCode = Opcode & 0xc1c8 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 6 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + fprintf(fp, "\t\t and ecx,byte 7\n"); + + if (type == 0) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_DAT); + } + if (type == 1) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + } + if (type == 2) + { + fprintf(fp, "\t\t mov eax,[%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov edi,[%s+EBX*4]\n",REG_ADD); + fprintf(fp, "\t\t mov [%s+ECX*4],edi\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+EBX*4],eax\n",REG_ADD); + } + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void ext(void) +{ + int Opcode, BaseCode ; + int type,regy ; + + for (type = 2 ; type < 8 ; type++) + for (regy = 0 ; regy < 8 ; regy++) + { + if (type > 3 && type < 7) + continue ; + Opcode = 0x4800 | (type<<6) | regy ; + BaseCode = Opcode & 0x48c0 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + + if (type == 2) /* byte to word */ + { + fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],ax\n",REG_DAT); + SetFlags('W',EAX,TRUE,FALSE,FALSE); + } + if (type == 3) /* word to long */ + { + fprintf(fp, "\t\t movsx eax,word [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + } + if (type == 7) /* byte to long */ + { + fprintf(fp, "\t\t movsx eax,byte [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t mov [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,TRUE,FALSE,FALSE); + } + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void swap(void) +{ + int Opcode, BaseCode ; + int sreg ; + + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x4840 | sreg ; + BaseCode = Opcode & 0x4840; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 4 ; + + fprintf(fp, "\t\t and ecx, byte 7\n"); + fprintf(fp, "\t\t mov eax, dword [%s+ECX*4]\n",REG_DAT); + fprintf(fp, "\t\t ror eax, 16\n"); + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t mov dword [%s+ECX*4],eax\n",REG_DAT); + SetFlags('L',EAX,FALSE,FALSE,FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Line A and Line F commands + * + */ + +void LineA(void) +{ + int Count; + + /* Line A */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0xA000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Exception(0x0A,0xA000); + + for (Count=0xA000;Count<0xB000;Count++) + { + OpcodeArray[Count] = 0xA000; + } +} + +void LineF(void) +{ + int Count; + + /* Line F */ + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(0xF000,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + Exception(0x0B,0xF000); + + for (Count=0xF000;Count<0x10000;Count++) + { + OpcodeArray[Count] = 0xF000; + } +} + +/* + * Moves To/From CCR and SR + * + * (Move from CCR is 68010 command) + * + */ + +void movesr(void) +{ + int Opcode, BaseCode ; + int type, mode, sreg ; + int Dest ; + char allow[] = "0-2345678-------" ; + char Size; + + for (type = 0 ; type < 4 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x40c0 | (type << 9) | ( mode << 3 ) | sreg ; + + /* To has extra modes */ + + if (type > 1) + { + allow[0x9] = '9'; + allow[0xa] = 'a'; + allow[0xb] = 'b' ; + } + + if ((type == 0) | (type == 3)) + Size = 'W'; /* SR */ + else + Size = 'B'; /* CCR */ + + BaseCode = Opcode & 0x46f8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[BaseCode] == -2) + { + char TrueLabel[16]; + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (type > 1) /* move to */ + TimingCycles += 12 ; + else + { + if (mode < 2) + TimingCycles += 6 ; + else + TimingCycles += 8 ; + } + + /* If Move to SR then must be in Supervisor Mode */ + + if (type == 3) + { + sprintf(TrueLabel,GenerateLabel(0,1)); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t je near %s\n\n",TrueLabel); + } + + /* 68010 Command ? */ + if (type==1) CheckCPUtype(1); + + + if (mode < 7) + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + } + + /* Always read/write word 2 bytes */ + if (type < 2) + { + ReadCCR(Size,EBX); + EffectiveAddressWrite(Dest & 15,'W',ECX,TRUE,"---DS-B",TRUE); + } + else + { + EffectiveAddressRead(Dest & 15,'W',ECX,EAX,"----S-B",FALSE); + WriteCCR(Size); + } + Completed(); + + /* Exception if not Supervisor Mode */ + + if (type == 3) + { + /* Was in User Mode - Exception */ + + fprintf(fp, "%s:\n",TrueLabel); + Exception(8,BaseCode); + } + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Decimal mode Add / Subtracts + * + */ + +void abcd_sbcd(void) +{ + int Opcode, BaseCode ; + int regx,type,rm,regy,mode ; + int ModeModX; + int ModeModY; + char *Label; + + for (type = 0 ; type < 2 ; type ++) /* 0=sbcd, 1=abcd */ + for (regx = 0 ; regx < 8 ; regx++) + for (rm = 0 ; rm < 2 ; rm++) + for (regy = 0 ; regy < 8 ; regy++) + { + Opcode = 0x8100 | (type<<14) | (regx<<9) | (rm<<3) | regy ; + BaseCode = Opcode & 0xc108 ; + + ModeModX = 0; + ModeModY = 0; + + if (rm == 0) + mode = 0 ; + else + { + mode = 4 ; + +#ifdef A7ROUTINE + + if (regx == 7) + { + BaseCode |= (regx << 9); + ModeModY = 16; + } + if (regy == 7) + { + BaseCode |= regy; + ModeModX = 16; + } + +#endif + } + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if (mode == 4) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + AddEACycles = 0 ; + + if (rm == 0) + TimingCycles += 6 ; + else + TimingCycles += 18 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx, byte 7\n"); + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + EffectiveAddressRead(mode+ModeModX,'B',EBX,EBX,"--C-S-B",TRUE); + EffectiveAddressRead(mode+ModeModY,'B',ECX,EAX,"-BC-SDB",TRUE); + + CopyX(); + + if (type == 0) + { + fprintf(fp, "\t\t sbb al,bl\n"); + fprintf(fp, "\t\t das\n"); + } + else + { + fprintf(fp, "\t\t adc al,bl\n"); + fprintf(fp, "\t\t daa\n"); + } + + /* Should only clear Zero flag if not zero */ + + Label = GenerateLabel(0,1); + + fprintf(fp, "\t\t mov ebx,edx\n"); + fprintf(fp, "\t\t setc dl\n"); + + fprintf(fp, "\t\t jnz short %s\n\n",Label); + + /* Keep original Zero flag */ + fprintf(fp, "\t\t and bl,40h ; Mask out Old Z\n"); + fprintf(fp, "\t\t or dl,bl ; Copy across\n\n"); + + fprintf(fp, "%s:\n",Label); + + fprintf(fp, "\t\t mov bl,dl\n"); /* copy carry into sign */ + fprintf(fp, "\t\t and bl,1\n"); + fprintf(fp, "\t\t shl bl,7\n"); + fprintf(fp, "\t\t and dl,7Fh\n"); + fprintf(fp, "\t\t or dl,bl\n"); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + + EffectiveAddressWrite(mode,'B',ECX,EAX,"---DS-B",TRUE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +/* + * Rotate Left / Right + * + */ + +void rol_ror(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Label ; + char * Regname="" ; + char * RegnameECX ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe018 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + /* shift 0 - no time, no shift and clear carry */ + + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t jecxz %s\n",Label); + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + if (dr == 0) + fprintf(fp, "\t\t ror %s,cl\n",Regname); + else + fprintf(fp, "\t\t rol %s,cl\n",Regname); + + fprintf(fp, "\t\t setc ch\n"); + + fprintf(fp, "%s:\n",Label); + + SetFlags(Size,EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */ + fprintf(fp, "\t\t or dl,ch\n"); + + EffectiveAddressWrite(0,Size,EBX,EAX,"--C-S-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void rol_ror_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe6c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t ror ax,1\n"); + else + fprintf(fp, "\t\t rol ax,1\n"); + + fprintf(fp, "\t\t setc bl\n"); + SetFlags('W',EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test clears Carry */ + fprintf(fp, "\t\t or dl,bl\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Logical Shift Left / Right + * + */ + +void lsl_lsr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Regname="" ; + char * RegnameECX="" ; + char * RegnameEDX="" ; + char * Label ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe008 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + RegnameEDX = regnamesshort[EDX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + RegnameEDX = regnamesword[EDX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + RegnameEDX = regnameslong[EDX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + /* and 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + /* ASG: on the 68k, the shift count is mod 64; on the x86, the */ + /* shift count is mod 32; we need to check for shifts of 32-63 */ + /* and produce zero */ + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t test cl,0x20\n"); + fprintf(fp, "\t\t jnz %s_BigShift\n",Label); + + fprintf(fp, "%s_Continue:\n",Label); + if (dr == 0) + fprintf(fp, "\t\t shr %s,cl\n",Regname); + else + fprintf(fp, "\t\t shl %s,cl\n",Regname); + + SetFlags(Size,EAX,FALSE,FALSE,FALSE); + + /* Clear Overflow flag */ + fprintf(fp, "\t\t xor dh,dh\n"); + + EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE); + + /* if shift count is zero clear carry */ + + fprintf(fp, "\t\t jecxz %s\n",Label); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + Completed(); + + Align(); + fprintf(fp, "%s:\n",Label); + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + Completed(); + + fprintf(fp, "%s_BigShift:\n",Label); + if (dr == 0) + { + fprintf(fp, "\t\t shr %s,16\n",Regname); + fprintf(fp, "\t\t shr %s,16\n",Regname); + } + else + { + fprintf(fp, "\t\t shl %s,16\n",Regname); + fprintf(fp, "\t\t shl %s,16\n",Regname); + } + fprintf(fp, "\t\t jmp %s_Continue\n",Label); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void lsl_lsr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe2c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t shr ax,1\n"); + else + fprintf(fp, "\t\t shl ax,1\n"); + + SetFlags('W',EAX,FALSE,TRUE,FALSE); + + /* Clear Overflow flag */ + + fprintf(fp, "\t\t xor dh,dh\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Rotate Left / Right though Extend + * + */ + +void roxl_roxr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' ' ; + char * Regname="" ; + char * RegnameECX="" ; + char * Label ; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe010 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + } + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-SDB",FALSE); + + /* move X into C so RCR & RCL can be used */ + /* RCR & RCL only set the carry flag */ + + CopyX(); + + if (dr == 0) + fprintf(fp, "\t\t rcr %s,cl\n",Regname); + else + fprintf(fp, "\t\t rcl %s,cl\n",Regname); + + fprintf(fp, "\t\t setc ch\n"); + SetFlags(Size,EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); Test Clears Carry */ + + EffectiveAddressWrite(0,Size,EBX,EAX,"--CDS-B",TRUE); + + /* if shift count is zero clear carry */ + + Label = GenerateLabel(0,1); + fprintf(fp, "\t\t test cl,cl\n"); + fprintf(fp, "\t\t jz %s\n",Label); + + /* Add in Carry Flag */ + + fprintf(fp, "\t\t or dl,ch\n"); + fprintf(fp, "\t\t mov [%s],dl\n",REG_X); + Completed(); + + + /* copy X onto C when shift is zero */ + + Align(); + fprintf(fp, "%s:\n",Label); + fprintf(fp, "\t\t mov ecx,[%s]\n",REG_X); + fprintf(fp, "\t\t and ecx,byte 1\n"); + fprintf(fp, "\t\t or edx,ecx\n"); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void roxl_roxr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe4c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + /* move X into C so RCR & RCL can be used */ + /* RCR & RCL only set the carry flag */ + + CopyX(); + + if (dr == 0) + fprintf(fp, "\t\t rcr ax,1\n"); + else + fprintf(fp, "\t\t rcl ax,1\n"); + + fprintf(fp, "\t\t setc bl\n"); + SetFlags('W',EAX,TRUE,FALSE,FALSE); +/* fprintf(fp, "\t\t and dl,254\n"); - Intel Clears on Test */ + fprintf(fp, "\t\t or dl,bl\n"); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"---DS-B",TRUE); + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Arithmetic Shift Left / Right + * + */ + +void asl_asr(void) +{ + int Opcode, BaseCode ; + int dreg, dr, leng, ir, sreg ; + char Size=' '; + char * Sizename="" ; + char * Regname="" ; + char * RegnameEDX="" ; + char * RegnameECX="" ; + char * Label; + + /* Normal routines for codes */ + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (dr = 0 ; dr < 2 ; dr++) + for (leng = 0 ; leng < 3 ; leng++) + for (ir = 0 ; ir < 2 ; ir++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe000 | (dreg<<9) | (dr<<8) | (leng<<6) | (ir<<5) | sreg ; + BaseCode = Opcode & 0xe1f8 ; + + switch (leng) + { + case 0: + Size = 'B'; + Regname = regnamesshort[0]; + RegnameECX = regnamesshort[ECX]; + RegnameEDX = regnamesshort[EDX]; + break; + case 1: + Size = 'W'; + Regname = regnamesword[0]; + RegnameECX = regnamesword[ECX]; + RegnameEDX = regnamesword[EDX]; + break; + case 2: + Size = 'L'; + Regname = regnameslong[0]; + RegnameECX = regnameslong[ECX]; + RegnameEDX = regnameslong[EDX]; + break; + } + + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + Label = GenerateLabel(0,1); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + fprintf(fp, "\t\t shr ecx,byte 9\n"); + + EffectiveAddressRead(0,Size,EBX,EAX,"-BC-S-B",FALSE); + + if (ir == 0) + { + Immediate8(); + } + else + { + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(0,'L',ECX,ECX,"-B--S-B",FALSE); + fprintf(fp, "\t\t and ecx,byte 63\n"); + fprintf(fp, "\t\t jz short %s\n",Label); + } + + /* allow 2 cycles per shift */ + + fprintf(fp, "\t\t mov edx,ecx\n"); + fprintf(fp, "\t\t add edx,edx\n"); + fprintf(fp, "\t\t sub dword [%s],edx\n",ICOUNT); + + if (dr == 0) + { + /* ASR */ + + /* ASG: on the 68k, the shift count is mod 64; on the x86, the */ + /* shift count is mod 32; we need to check for shifts of 32-63 */ + /* and effectively shift 31 */ + fprintf(fp, "\t\t shrd edx,ecx,6\n"); + fprintf(fp, "\t\t sar edx,31\n"); + fprintf(fp, "\t\t and edx,31\n"); + fprintf(fp, "\t\t or ecx,edx\n"); + + fprintf(fp, "\t\t sar %s,cl\n",Regname); + + /* Mode 0 write does not affect Flags */ + EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE); + + /* Update Flags */ + fprintf(fp, "\t\t lahf\n"); + +#ifdef STALLCHECK + ClearRegister(EDX); + fprintf(fp, "\t\t mov dl,ah\n"); +#else + fprintf(fp, "\t\t movzx edx,ah\n"); +#endif + + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } + else + { + /* ASL */ + + /* Check to see if Overflow should be set */ + + fprintf(fp,"\t\t mov edi,eax\t\t; Save It\n"); + + ClearRegister(EDX); + fprintf(fp,"\t\t stc\n"); + fprintf(fp,"\t\t rcr %s,1\t\t; d=1xxxx\n",RegnameEDX); + fprintf(fp,"\t\t sar %s,cl\t\t; d=1CCxx\n",RegnameEDX); + fprintf(fp,"\t\t and eax,edx\n"); + fprintf(fp,"\t\t jz short %s_V\t\t; No Overflow\n",Label); + fprintf(fp,"\t\t cmp eax,edx\n"); + fprintf(fp,"\t\t je short %s_V\t\t; No Overflow\n",Label); + + /* Set Overflow */ + fprintf(fp,"\t\t mov edx,0x800\n"); + fprintf(fp,"\t\t jmp short %s_OV\n",Label); + + fprintf(fp,"%s_V:\n",Label); + ClearRegister(EDX); + + fprintf(fp,"%s_OV:\n",Label); + + /* more than 31 shifts and long */ + + if ((ir==1) && (leng==2)) + { + fprintf(fp,"\t\t test cl,0x20\n"); + fprintf(fp,"\t\t jnz short %s_32\n\n",Label); + } + + fprintf(fp,"\t\t mov eax,edi\t\t; Restore It\n"); + + fprintf(fp, "\t\t sal %s,cl\n",Regname); + + EffectiveAddressWrite(0,Size,EBX,EAX,"---DS-B",TRUE); + fprintf(fp, "\t\t lahf\n"); + fprintf(fp, "\t\t mov dl,ah\n"); + fprintf(fp, "\t\t mov [%s],edx\n",REG_X); + } + Completed(); + + if (ir != 0) + { + Align(); + fprintf(fp, "%s:\n",Label); + + + if (dr == 0) + { + /* ASR - Test clears V and C */ + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + } + else + { + /* ASL - Keep existing Carry flag, Clear V */ + fprintf(fp, "\t\t mov ebx,edx\n"); + fprintf(fp, "\t\t and ebx,byte 1\n"); + SetFlags(Size,EAX,TRUE,FALSE,FALSE); + fprintf(fp, "\t\t or edx,ebx\n"); + + if (leng==2) + { + Completed(); + + /* > 31 Shifts */ + + fprintf(fp, "%s_32:\n",Label); + fprintf(fp, "\t\t mov dl,40h\n"); // Zero flag + ClearRegister(EAX); + EffectiveAddressWrite(0,Size,EBX,EAX,"----S-B",TRUE); + } + } + + Completed(); + } + } + + OpcodeArray[Opcode] = BaseCode ; + } + + /* End with special routines for ASL.x #1,Dx */ + /* To do correct V setting, ASL needs quite a */ + /* bit of additional code. A Shift of one has */ + /* correct flags on Intel, and is very common */ + /* in 68000 programs. */ + + for (leng = 0 ; leng < 3 ; leng++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe300 | (leng<<6) | sreg ; + BaseCode = Opcode & 0xe3c8 ; + + switch (leng) + { + case 0: + Sizename = "byte"; + break; + case 1: + Sizename = "word"; + break; + case 2: + Sizename = "long"; + break; + } + + if (sreg == 0) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + Label = GenerateLabel(0,1); + + if (Size != 'L') + TimingCycles += 6 ; + else + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + fprintf(fp, "\t\t sal %s [%s+ecx*4],1\n",Sizename,REG_DAT); + SetFlags('L',EAX,FALSE,TRUE,FALSE); + Completed(); + + } + + OpcodeArray[Opcode] = BaseCode ; + } +} + +void asl_asr_ea(void) +{ + int Opcode, BaseCode ; + int dr, mode, sreg ; + int Dest ; + char allow[] = "--2345678-------" ; + + for (dr = 0 ; dr < 2 ; dr++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0xe0c0 | (dr<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0xfff8 ; + + if (mode == 7) + BaseCode |= sreg ; + + Dest = EAtoAMN(BaseCode, FALSE); + + if (allow[Dest&0xf] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + TimingCycles += 8 ; + + fprintf(fp, "\t\t and ecx,byte 7\n"); + EffectiveAddressRead(Dest&0xf,'W',ECX,EAX,"--C-SDB",FALSE); + + if (dr == 0) + fprintf(fp, "\t\t sar ax,1\n"); + else + fprintf(fp, "\t\t sal ax,1\n"); + + SetFlags('W',EAX,FALSE,TRUE,TRUE); + + EffectiveAddressWrite(Dest&0xf,'W',ECX,EAX,"----S-B",FALSE); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + +/* + * Divide Commands + */ + +void divides(void) +{ + int dreg, type, mode, sreg ; + int Opcode, BaseCode ; + int Dest ; + char allow[] = "0-23456789ab-----" ; + char TrapLabel[16]; + int Cycles; + + int divide_cycles[12] = + { + 38,0,42,42,44,46,50,46,50,46,48,42 + }; + + for (dreg = 0 ; dreg < 8 ; dreg++) + for (type = 0 ; type < 2 ; type++) + for (mode = 0 ; mode < 8 ; mode++) + for (sreg = 0 ; sreg < 8 ; sreg++) + { + Opcode = 0x80c0 | (dreg<<9) | (type<<8) | (mode<<3) | sreg ; + BaseCode = Opcode & 0x81f8 ; + if (mode == 7) + { + BaseCode |= sreg ; + } + + Dest = EAtoAMN(Opcode, FALSE); + if (allow[Dest&0x0f] != '-') + { + if (OpcodeArray[ BaseCode ] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + if ((Dest >= 2) && (Dest <=10)) + SavePreviousPC(); + + fprintf(fp, "\t\t add esi,byte 2\n\n"); + + + /* Save EDX (in case of overflow) */ + + fprintf(fp, "\t\t and edx,byte -2\n"); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + + + /* Cycle Timing (if succeeds OK) */ + + Cycles = divide_cycles[Dest & 0x0f] + 95 + (type * 17); + + if (Cycles > 127) + fprintf(fp, "\t\t sub dword [%s],%d\n",ICOUNT,Cycles); + else + fprintf(fp, "\t\t sub dword [%s],byte %d\n",ICOUNT,Cycles); + + if (mode < 7) + { + fprintf(fp, "\t\t mov ebx,ecx\n"); + fprintf(fp, "\t\t and ebx,byte 7\n"); + } + + fprintf(fp, "\t\t shr ecx, byte 9\n"); + fprintf(fp, "\t\t and ecx, byte 7\n"); + + sprintf(TrapLabel, "%s", GenerateLabel(0,1) ) ; + + EffectiveAddressRead(Dest,'W',EBX,EAX,"A-C-SDB",FALSE); /* source */ + + fprintf(fp, "\t\t test ax,ax\n"); + fprintf(fp, "\t\t je near %s_ZERO\t\t;do div by zero trap\n", TrapLabel); + + if (type == 1) /* signed */ + { + fprintf(fp, "\t\t movsx ebx,ax\n"); + } + else + { + fprintf(fp, "\t\t movzx ebx,ax\n"); + } + + EffectiveAddressRead(0,'L',ECX,EAX,"ABC-SDB",FALSE); /* dest */ + + if (type == 1) /* signed */ + { + fprintf(fp, "\t\t cdq\n"); /* EDX:EAX = 64 bit signed */ + fprintf(fp, "\t\t idiv ebx\n"); /* EBX = 32 bit */ + + /* Check for Overflow */ + + fprintf(fp, "\t\t movsx ebx,ax\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jne short %s_OVER\n",TrapLabel); + } + else + { + ClearRegister(EDX); + fprintf(fp, "\t\t div ebx\n"); + + /* Check for Overflow */ + + fprintf(fp, "\t\t test eax, 0FFFF0000H\n"); + fprintf(fp, "\t\t jnz short %s_OVER\n",TrapLabel); + } + + /* Sort out Result */ + + fprintf(fp, "\t\t shl edx, byte 16\n"); + fprintf(fp, "\t\t mov dx,ax\n"); + fprintf(fp, "\t\t mov [%s+ECX*4],edx\n",REG_DAT); + SetFlags('W',EDX,TRUE,FALSE,FALSE); + + Completed(); + + + /* Overflow */ + + Align(); + fprintf(fp, "%s_OVER:\n",TrapLabel); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t or edx,0x0800\t\t;V flag\n"); + Completed(); + + + /* Division by Zero */ + + Align(); + fprintf(fp, "%s_ZERO:\t\t ;Do divide by zero trap\n", TrapLabel); + + /* Correct cycle counter for error */ + + fprintf(fp, "\t\t add dword [%s],byte %d\n",ICOUNT,95 + (type * 17)); + fprintf(fp, "\t\t mov al,5\n"); + Exception(-1,BaseCode); + Completed(); + } + + OpcodeArray[Opcode] = BaseCode ; + } + } +} + + +/* + * 68010 Extra Opcodes + * + * move from CCR is done above + * + */ + +void ReturnandDeallocate(void) +{ + int BaseCode = 0x4e74 ; + + if (OpcodeArray[BaseCode] == -2) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode,0)); + + CheckCPUtype(1); + + SavePreviousPC(); + + TimingCycles += 16; + + OpcodeArray[BaseCode] = BaseCode ; + + /* Get Return Address */ + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_A7); + Memory_Read('L',EAX,"---D--B",1); + + + /* Get Displacement */ + + Memory_Fetch('W',EBX,TRUE); + + + /* Set PC = New Address */ + + fprintf(fp, "\t\t mov esi,eax\n"); + + + /* Correct Stack for Return Address and Displacement */ + + fprintf(fp, "\t\t add ebx,byte 4\n"); + fprintf(fp, "\t\t add dword [%s],ebx\n",REG_A7); + + MemoryBanking(BaseCode); + Completed(); + } +} + +void MoveControlRegister(void) +{ + int Direction; + int BaseCode = 0x4e7a ; + + for (Direction=0;Direction<2;Direction++) + { + Align(); + fprintf(fp, "%s:\n",GenerateLabel(BaseCode+Direction,0)); + + TimingCycles += 4; /* Assume same as move usp */ + + CheckCPUtype(1); + + fprintf(fp, "\t\t test byte [%s],20h \t\t\t; Supervisor Mode ?\n",REG_SRH); + fprintf(fp, "\t\t jz short OP%d_%4.4x_Trap\n",CPU,BaseCode+Direction); + + fprintf(fp, "\t\t add esi,byte 2\n"); + if (CPU==2) + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(EBX); + fprintf(fp, "\t\t mov bx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ebx,word [esi+ebp]\n"); +#endif + if (CPU==2) + fprintf(fp, "\t\t xor esi,2\n"); /* ASG */ + + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t mov eax,ebx\n"); + fprintf(fp, "\t\t mov ecx,ebx\n"); + + /* Sort out Register */ + + fprintf(fp, "\t\t shr ebx,12\n"); + + /* Sort out Control Register ID */ + + fprintf(fp, "\t\t and eax,byte 1\n"); + fprintf(fp, "\t\t shr ecx,10\n"); + fprintf(fp, "\t\t and ecx,2\n"); + fprintf(fp, "\t\t or ecx,eax\n"); + + if (Direction==0) + { + /* from Control */ + + fprintf(fp, "\t\t mov eax,[%s+ecx*4]\n",REG_SFC); + fprintf(fp, "\t\t mov %s,eax\n",REG_DAT_EBX); + } + else + { + /* To Control */ + + fprintf(fp, "\t\t mov eax,%s\n",REG_DAT_EBX); + + /* Mask out for SFC & DFC */ + + fprintf(fp, "\t\t test cl,2\n"); + fprintf(fp, "\t\t jne short OP%d_%4.4x_Mask\n",CPU,BaseCode+Direction); + fprintf(fp, "\t\t and eax,byte 7\n"); + fprintf(fp, "OP%d_%4.4x_Mask:\n",CPU,BaseCode+Direction); + + /* Write to control */ + + fprintf(fp, "\t\t mov [%s+ecx*4],eax\n",REG_SFC); + } + + Completed(); + + /* Not Supervisor Mode */ + + Align(); + fprintf(fp, "OP%d_%4.4x_Trap:\n",CPU,BaseCode+Direction); + Exception(8,BaseCode+Direction); + + OpcodeArray[BaseCode+Direction] = BaseCode+Direction; + } +} + +void MoveAddressSpace(void) +{ +} + +/* + * Generate Jump Table + * + */ + +void JumpTable(void) +{ + int Opcode,l,op; + + fprintf(fp, "DD OP%d_1000\n",CPU); + + l = 0 ; + for (Opcode=0x0;Opcode<0x10000;) + { + + op = OpcodeArray[Opcode]; + + fprintf(fp, "DD "); + + l = 1 ; + while (op == OpcodeArray[Opcode+l] && ((Opcode+l) & 0xfff) != 0) + { + l++ ; + } + + Opcode += l ; + + if (l > 255) + { + if (op > -1) + fprintf(fp, "OP%d_%4.4x - OP%d_1000\n",CPU,op,CPU); + else + fprintf(fp, "ILLEGAL - OP%d_1000\n",CPU); + + fprintf(fp, "DW %d\n", l); + } + else + { + if (op > -1) + fprintf(fp, "(OP%d_%4.4x - OP%d_1000) + (%d * 1000000h)\n",CPU,op,CPU,l); + else + fprintf(fp, "(ILLEGAL - OP%d_1000) + (%d * 1000000h)\n",CPU,l); + } + } +} + +void CodeSegmentBegin(void) +{ +/* Messages */ + + fprintf(fp, "; Make68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION); + fprintf(fp, "; & Darren Olafson (deo@mail.island.net)\n\n"); + +/* Needed code to make it work! */ + + fprintf(fp, "\t\t BITS 32\n\n"); + + fprintf(fp, "\t\t GLOBAL %s_RUN\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_RESET\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_regs\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_COMPTABLE\n",CPUtype); + fprintf(fp, "\t\t GLOBAL %s_OPCODETABLE\n",CPUtype); + + /* ASG - only one interface to memory now */ + fprintf(fp, "\t\t EXTERN %sm68k_ICount\n", PREF); + fprintf(fp, "\t\t EXTERN %sa68k_memory_intf\n", PREF); + fprintf(fp, "\t\t EXTERN %smem_amask\n", PREF); + + fprintf(fp, "; Vars Mame declares / needs access to\n\n"); + + fprintf(fp, "\t\t EXTERN %smame_debug\n", PREF); + fprintf(fp, "\t\t EXTERN %sillegal_op\n", PREF); + fprintf(fp, "\t\t EXTERN %sillegal_pc\n", PREF); + + fprintf(fp, "\t\t EXTERN %sOP_ROM\n", PREF); + fprintf(fp, "\t\t EXTERN %sOP_RAM\n", PREF); + + fprintf(fp, "\t\t EXTERN %sopcode_entry\n", PREF); +// fprintf(fp, "\t\t EXTERN %scur_mrhard\n", PREF); + +#ifdef MAME_DEBUG + fprintf(fp, "\t\t EXTERN %sm68k_illegal_opcode\n", PREF); +#endif + +#ifdef OS2 + fprintf(fp, "\t\t SECTION maincode USE32 FLAT CLASS=CODE\n\n"); +#else + fprintf(fp, "\t\t SECTION .text\n\n"); +#endif + + + +/* Reset routine */ + + fprintf(fp, "%s_RESET:\n",CPUtype); + + fprintf(fp, "\t\t pushad\n\n"); + + fprintf(fp, "; Build Jump Table (not optimised!)\n\n"); + + fprintf(fp, "\t\t lea edi,[%s_OPCODETABLE]\t\t; Jump Table\n", CPUtype); + fprintf(fp, "\t\t lea esi,[%s_COMPTABLE]\t\t; RLE Compressed Table\n", CPUtype); + + /* Reference Point in EBP */ + + fprintf(fp, "\t\t mov ebp,[esi]\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + + fprintf(fp, "RESET0:\n"); + fprintf(fp, "\t\t mov eax,[esi]\n"); + fprintf(fp, "\t\t mov ecx,eax\n"); + fprintf(fp, "\t\t and eax,0xffffff\n"); + fprintf(fp, "\t\t add eax,ebp\n"); + fprintf(fp, "\t\t add esi,byte 4\n"); + + /* if count is zero, then it's a word RLE length */ + + fprintf(fp, "\t\t shr ecx,24\n"); + fprintf(fp, "\t\t jne short RESET1\n"); + +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi]\t\t; Repeats\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi]\t\t; Repeats\n"); +#endif + + fprintf(fp, "\t\t add esi,byte 2\n"); + fprintf(fp, "\t\t jecxz RESET2\t\t; Finished!\n"); + + fprintf(fp, "RESET1:\n"); + fprintf(fp, "\t\t mov [edi],eax\n"); + fprintf(fp, "\t\t add edi,byte 4\n"); + fprintf(fp, "\t\t dec ecx\n"); + fprintf(fp, "\t\t jnz short RESET1\n"); + fprintf(fp, "\t\t jmp short RESET0\n"); + + fprintf(fp, "RESET2:\n"); + fprintf(fp, "\t\t popad\n"); + fprintf(fp, "\t\t ret\n\n"); + +/* Emulation Entry Point */ + + Align(); + + fprintf(fp, "%s_RUN:\n",CPUtype); + + fprintf(fp, "\t\t pushad\n"); + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + + fprintf(fp,"; Check for Interrupt waiting\n\n"); + fprintf(fp,"\t\t test [%s],byte 07H\n",REG_IRQ); + fprintf(fp,"\t\t jne near interrupt\n\n"); + + fprintf(fp, "IntCont:\n"); + + /* See if was only called to check for Interrupt */ + + fprintf(fp, "\t\t test dword [%s],-1\n",ICOUNT); + fprintf(fp, "\t\t js short MainExit\n\n"); + +#ifdef FBA_DEBUG + + fprintf(fp, "\n\t\t test byte [%smame_debug],byte 0xff\n", PREF); + fprintf(fp, "\t\t jns near .NoDebug\n"); + fprintf(fp, "\t\t call near FBADebugActive\n\n"); + fprintf(fp, ".NoDebug\n"); + +#endif + + if(CPU==2) + { + /* 32 Bit */ + fprintf(fp, "\t\t mov eax,2\n"); /* ASG */ + fprintf(fp, "\t\t xor eax,esi\n"); /* ASG */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[eax+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [eax+ebp]\n"); +#endif + } + else + { + /* 16 Bit Fetch */ +#ifdef STALLCHECK + ClearRegister(ECX); + fprintf(fp, "\t\t mov cx,[esi+ebp]\n"); +#else + fprintf(fp, "\t\t movzx ecx,word [esi+ebp]\n"); +#endif + } + fprintf(fp, "\t\t jmp [%s_OPCODETABLE+ecx*4]\n", CPUtype); + + Align(); + + fprintf(fp, "MainExit:\n"); + fprintf(fp, "\t\t mov [%s],esi\t\t; Save PC\n",REG_PC); + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + fprintf(fp, "\t\t test byte [%s],20H\n",REG_SRH); + fprintf(fp, "\t\t mov eax,[%s]\t\t; Get A7\n",REG_A7); + fprintf(fp, "\t\t jne short ME1\t\t; Mode ?\n"); + fprintf(fp, "\t\t mov [%s],eax\t\t;Save in USP\n",REG_USP); + fprintf(fp, "\t\t jmp short MC68Kexit\n"); + fprintf(fp, "ME1:\n"); + fprintf(fp, "\t\t mov [%s],eax\n",REG_ISP); + fprintf(fp, "MC68Kexit:\n"); + + /* If in Debug mode make normal SR register */ + +#ifdef MAME_DEBUG + + ReadCCR('W', ECX); + fprintf(fp, "\t\t mov [%s],eax\n\n",REG_S); + +#endif + + fprintf(fp, "\t\t popad\n"); + fprintf(fp, "\t\t ret\n"); + +/* Check for Pending Interrupts */ + + Align(); + fprintf(fp, "; Interrupt check\n\n"); + + fprintf(fp, "interrupt:\n"); + + /* check to exclude interrupts */ + + fprintf(fp, "\t\t mov eax,[%s]\n",REG_IRQ); + fprintf(fp, "\t\t and eax,byte 07H\n"); + + fprintf(fp, "\t\t cmp al,7\t\t ; Always take 7\n"); + fprintf(fp, "\t\t je short procint\n\n"); + + fprintf(fp, "\t\t mov ebx,[%s]\t\t; int mask\n",REG_SRH); + fprintf(fp, "\t\t and ebx,byte 07H\n"); + fprintf(fp, "\t\t cmp eax,ebx\n"); + fprintf(fp, "\t\t jle near IntCont\n\n"); + + /* Take pending Interrupt */ + + Align(); + fprintf(fp, "procint:\n"); + + /* LVR - Enable proper IRQ handling (require explicit acknowledge) */ + /* fprintf(fp, "\t\t and byte [%s],78h\t\t; remove interrupt & stop\n\n",REG_IRQ); */ + fprintf(fp, "\t\t and byte [%s],7fh\t\t; remove stop\n\n",REG_IRQ); + + /* Get Interrupt Vector from callback */ + + fprintf(fp, "\t\t push eax\t\t; save level\n\n"); + + if (SavedRegs[EBX] == '-') + { + fprintf(fp, "\t\t push EBX\n"); + } + else + { + fprintf(fp, "\t\t mov ebx,eax\n"); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + } + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov [%s],edx\n",REG_CCR); + } + +/* ----- Win32 uses FASTCALL (By Kenjo)----- */ + +#ifdef FASTCALL + fprintf(fp, "\t\t mov %s, eax\t\t; irq line #\n",FASTCALL_FIRST_REG); + fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK); +#else + fprintf(fp, "\t\t push eax\t\t; irq line #\n"); + fprintf(fp, "\t\t call dword [%s]\t; get the IRQ level\n", REG_IRQ_CALLBACK); + fprintf(fp, "\t\t lea esp,[esp+4]\n"); +#endif + + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov edx,[%s]\n",REG_CCR); + } + + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov esi,[%s]\n",REG_PC); + } + + /* Do we want to use normal vector number ? */ + + + fprintf(fp, "\t\t test eax,eax\n"); + fprintf(fp, "\t\t jns short AUTOVECTOR\n"); + + /* Only need EBX restored if default vector to be used */ + + if (SavedRegs[EBX] == '-') + { + fprintf(fp, "\t\t pop EBX\n"); + } + + /* Just get default vector */ + + fprintf(fp, "\t\t mov eax,ebx\n"); + + fprintf(fp, "\t\t add eax,byte 24\t\t; Vector\n\n"); + + fprintf(fp, "AUTOVECTOR:\n\n"); + + Exception(-1,0xFFFF); + + fprintf(fp, "\t\t pop eax\t\t; set Int mask\n"); + fprintf(fp, "\t\t mov bl,byte [%s]\n",REG_SRH); + fprintf(fp, "\t\t and bl,0F8h\n"); + fprintf(fp, "\t\t or bl,al\n"); + fprintf(fp, "\t\t mov byte [%s],bl\n\n",REG_SRH); + fprintf(fp, "\t\t jmp IntCont\n\n"); + +/* Exception Routine */ + + Align(); + fprintf(fp, "Exception:\n"); + fprintf(fp, "\t\t push edx\t\t; Save flags\n"); + fprintf(fp, "\t\t and eax,0FFH\t\t; Zero Extend IRQ Vector\n"); + + fprintf(fp, "\t\t push eax\t\t; Save for Later\n"); + + /* Update Cycle Count */ + + fprintf(fp, "\t\t mov al,[exception_cycles+eax]\t\t; Get Cycles\n"); + fprintf(fp, "\t\t sub [%s],eax\t\t; Decrement ICount\n",ICOUNT); + + ReadCCR('W',ECX); + + fprintf(fp, "\t\t mov edi,[%s]\t\t; Get A7\n",REG_A7); + + fprintf(fp, "\t\t test ah,20H\t; Which Mode ?\n"); + fprintf(fp, "\t\t jne short ExSuperMode\t\t; Supervisor\n"); + + fprintf(fp, "\t\t or byte [%s],20H\t; Set Supervisor Mode\n",REG_SRH); + fprintf(fp, "\t\t mov [%s],edi\t\t; Save in USP\n",REG_USP); + fprintf(fp, "\t\t mov edi,[%s]\t\t; Get ISP\n",REG_ISP); + + /* Write SR first (since it's in a register) */ + + fprintf(fp, "ExSuperMode:\n"); + fprintf(fp, "\t\t sub edi,byte 6\n"); + fprintf(fp, "\t\t mov [%s],edi\t\t; Put in A7\n",REG_A7); + Memory_Write('W',EDI,EAX,"----S-B",2); + + /* Then write PC */ + + fprintf(fp, "\t\t add edi,byte 2\n"); + Memory_Write('L',EDI,ESI,"------B",0); + + /* Get new PC */ + + fprintf(fp, "\t\t pop eax\t\t;Level\n"); + fprintf(fp, "\t\t shl eax,2\n"); + fprintf(fp, "\t\t add eax,[%s]\n",REG_VBR); /* 68010+ Vector Base */ + + /* Direct Read */ + + Memory_Read('L',EAX,"------B",0); + + fprintf(fp, "\t\t mov esi,eax\t\t;Set PC\n"); + fprintf(fp, "\t\t pop edx\t\t; Restore flags\n"); + + /* Sort out any bank changes */ + MemoryBanking(1); + + fprintf(fp, "\t\t ret\n"); + +#ifdef FBA_DEBUG + + fprintf(fp,"\n; Call FBA debugging callback\n\n"); + fprintf(fp, "FBADebugActive:"); + fprintf(fp, "\t\t mov [%s],ESI\n",REG_PC); + fprintf(fp, "\t\t mov [%s],EDX\n",REG_CCR); + fprintf(fp, "\t\t call [%sa68k_memory_intf+0]\n", PREF); + if (SavedRegs[EDX] == '-') + { + fprintf(fp, "\t\t mov EDX,[%s]\n",REG_CCR); + } + if (SavedRegs[ESI] == '-') + { + fprintf(fp, "\t\t mov ESI,[%s]\n",REG_PC); + } + if (SavedRegs[EBP] == '-') + { + fprintf(fp, "\t\t mov ebp,dword [%sOP_ROM]\n", PREF); + } + fprintf(fp,"\n; Now continue as usual\n\n"); + fprintf(fp, "\t\t ret\n"); + +#endif + +} + +void CodeSegmentEnd(void) +{ +#ifdef OS2 + fprintf(fp, "\t\t SECTION maindata USE32 FLAT CLASS=DATA\n\n"); +#else + fprintf(fp, "\t\t SECTION .data\n"); +#endif + + fprintf(fp, "\n\t\t align 16\n"); + fprintf(fp, "%s_ICount\n",CPUtype); + fprintf(fp, "asm_count\t DD 0\n\n"); + + /* Memory structure for 68000 registers */ + /* Same layout as structure in CPUDEFS.H */ + + fprintf(fp, "\n\n; Register Structure\n\n"); + fprintf(fp, "%s_regs\n",CPUtype); + + fprintf(fp, "R_D0\t DD 0\t\t\t ; Data Registers\n"); + fprintf(fp, "R_D1\t DD 0\n"); + fprintf(fp, "R_D2\t DD 0\n"); + fprintf(fp, "R_D3\t DD 0\n"); + fprintf(fp, "R_D4\t DD 0\n"); + fprintf(fp, "R_D5\t DD 0\n"); + fprintf(fp, "R_D6\t DD 0\n"); + fprintf(fp, "R_D7\t DD 0\n\n"); + + fprintf(fp, "R_A0\t DD 0\t\t\t ; Address Registers\n"); + fprintf(fp, "R_A1\t DD 0\n"); + fprintf(fp, "R_A2\t DD 0\n"); + fprintf(fp, "R_A3\t DD 0\n"); + fprintf(fp, "R_A4\t DD 0\n"); + fprintf(fp, "R_A5\t DD 0\n"); + fprintf(fp, "R_A6\t DD 0\n"); + fprintf(fp, "R_A7\t DD 0\n\n"); + + fprintf(fp, "R_ISP\t DD 0\t\t\t ; Supervisor Stack\n"); + fprintf(fp, "R_SR_H\t DD 0\t\t\t ; Status Register High TuSuuIII\n"); + fprintf(fp, "R_CCR\t DD 0\t\t\t ; CCR Register in Intel Format\n"); + fprintf(fp, "R_XC\t DD 0\t\t\t ; Extended Carry uuuuuuuX\n"); + + fprintf(fp, "R_PC\t DD 0\t\t\t ; Program Counter\n"); + fprintf(fp, "R_IRQ\t DD 0\t\t\t ; IRQ Request Level\n\n"); + fprintf(fp, "R_SR\t DD 0\t\t\t ; Motorola Format SR\n\n"); + + fprintf(fp, "R_IRQ_CALLBACK\t DD 0\t\t\t ; irq callback (get vector)\n\n"); + + fprintf(fp, "R_PPC\t DD 0\t\t\t ; Previous Program Counter\n"); + + fprintf(fp, "R_RESET_CALLBACK\t DD 0\t\t\t ; Reset Callback\n"); + + fprintf(fp, "R_SFC\t DD 0\t\t\t ; Source Function Call\n"); + fprintf(fp, "R_DFC\t DD 0\t\t\t ; Destination Function Call\n"); + fprintf(fp, "R_USP\t DD 0\t\t\t ; User Stack\n"); + fprintf(fp, "R_VBR\t DD 0\t\t\t ; Vector Base\n"); + + fprintf(fp, "asmbank\t DD 0\n\n"); + fprintf(fp, "CPUversion\t DD 0\n\n"); + fprintf(fp, "FullPC\t DD 0\n\n"); + + /* Extra space for variables mame uses for debugger */ + + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); + fprintf(fp, "\t\t DD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\n"); + + /* Safe Memory Locations */ + + fprintf(fp, "\t\t ALIGN 16\n"); + + fprintf(fp, "\n\nIntelFlag\t\t\t\t; Intel Flag Lookup Table\n"); + fprintf(fp, "\t\t DD 0000h,0001h,0800h,0801h,0040h,0041h,0840h,0841h\n"); + fprintf(fp, "\t\t DD 0080h,0081h,0880h,0881h,00C0h,00C1h,08C0h,08C1h\n"); + fprintf(fp, "\t\t DD 0100h,0101h,0900h,0901h,0140h,0141h,0940h,0941h\n"); + fprintf(fp, "\t\t DD 0180h,0181h,0980h,0981h,01C0h,01C1h,09C0h,09C1h\n"); + +#if 0 + fprintf(fp, "\n\nImmTable\n"); + fprintf(fp, "\t\t DD 8,1,2,3,4,5,6,7\n\n"); +#endif + + + + /* Exception Timing Table */ + + fprintf(fp, "exception_cycles\n"); + fprintf(fp, "\t\t DB 0, 0, 0, 0, 38, 42, 44, 38, 38, 0, 38, 38, 0, 0, 0, 0\n"); + fprintf(fp, "\t\t DB 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 46, 46\n"); + fprintf(fp, "\t\t DB 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38\n\n"); + + fprintf(fp, "; RLE Compressed Jump Table\n\n"); + + fprintf(fp, "%s_COMPTABLE\n\n", CPUtype); + + fprintf(fp, "%cinclude '%s'\n\n",'%', comptab); + + fprintf(fp, "\t\tDW 0,0,0\n\n"); + + +/* If using Windows, put the table area in .data section (Kenjo) */ +#ifdef WIN32 + + fprintf(fp, "%s_OPCODETABLE\tTIMES 65536 DD 0\n\n", CPUtype); + +#else + +#ifdef OS2 + fprintf(fp, "\t\t SECTION tempdata USE32 FLAT CLASS=BSS\n\n"); +#else + fprintf(fp, "\t\t SECTION .bss\n"); +#endif + + fprintf(fp, "%s_OPCODETABLE\tRESD 65536\n\n", CPUtype); + +#endif + +} + +void EmitCode(void) +{ + CodeSegmentBegin(); + + /* Instructions */ + + moveinstructions(); /* 1000 to 3FFF MOVE.X */ + immediate(); /* 0### XXX.I */ + bitdynamic(); /* 0### dynamic bit operations */ + movep(); /* 0### Move Peripheral */ + bitstatic(); /* 08## static bit operations */ + LoadEffectiveAddress(); /* 4### */ + PushEffectiveAddress(); /* ???? */ + movesr(); /* 4#C# */ + opcode5(); /* 5000 to 5FFF ADDQ,SUBQ,Scc and DBcc */ + branchinstructions(); /* 6000 to 6FFF Bcc,BSR */ + moveq(); /* 7000 to 7FFF MOVEQ */ + abcd_sbcd(); /* 8### Decimal Add/Sub */ + typelogicalmath(); /* Various ranges */ + addx_subx(); + divides(); + swap(); + not(); /* also neg negx clr */ + moveusp(); + chk(); + exg(); + cmpm(); + mul(); + ReturnandRestore(); + rts(); + jmp_jsr(); + nbcd(); + tas(); + trap(); + trapv(); + reset(); + nop(); + stop(); + ext(); + ReturnFromException(); + tst(); + movem_reg_ea(); + movem_ea_reg(); + link(); + unlinkasm(); + asl_asr(); /* E### Shift Commands */ + asl_asr_ea(); + roxl_roxr(); + roxl_roxr_ea(); + lsl_lsr(); + lsl_lsr_ea(); + rol_ror(); + rol_ror_ea(); + LineA(); /* A000 to AFFF Line A */ + LineF(); /* F000 to FFFF Line F */ + illegal_opcode(); + + ReturnandDeallocate(); /* 68010 Commands */ + MoveControlRegister(); + MoveAddressSpace(); + + if(CPU==2) /* 68020 Commands */ + { + divl(); + mull(); + bfext(); + } + + CodeSegmentEnd(); +} + +int main(int argc, char **argv) +{ + int dwLoop; + + printf("\nMake68K - V%s - Copyright 1998, Mike Coates (mame@btinternet.com)\n", VERSION); + printf(" 1999, & Darren Olafson (deo@mail.island.net)\n"); + printf(" 2000\n"); + + if (argc != 4 && argc != 5) + { + printf("Usage: %s outfile jumptable-outfile type [ppro]\n", argv[0]); + exit(1); + } + + printf("Building 680%s 2001\n\n",argv[3]); + + for (dwLoop=0;dwLoop<65536;) OpcodeArray[dwLoop++] = -2; + + codebuf=malloc(64); + if (!codebuf) + { + printf ("Memory allocation error\n"); + exit(3); + } + + /* Emit the code */ + fp = fopen(argv[1], "w"); + if (!fp) + { + fprintf(stderr, "Can't open %s for writing\n", argv[1]); + exit(1); + } + + comptab = argv[2]; + + + CPUtype = malloc(64); + + sprintf(CPUtype,"%sM680%s", PREF, argv[3]); + + if(argv[3][0]=='2') CPU = 2; + if(argc > 4 && !strcmp(argv[4], "ppro")) + { + ppro = 1; + printf("Generating ppro opcodes\n"); + } + + EmitCode(); + + fclose(fp); + + printf("\n%d Unique Opcodes\n",Opcount); + + /* output Jump table to separate file */ + fp = fopen(argv[2], "w"); + if (!fp) + { + fprintf(stderr, "Can't open %s for writing\n", argv[2]); + exit(1); + } + + JumpTable(); + + fclose(fp); + + exit(0); +} diff --git a/src/cpu/arm/arm.cpp b/src/cpu/arm/arm.cpp new file mode 100644 index 00000000..71202b88 --- /dev/null +++ b/src/cpu/arm/arm.cpp @@ -0,0 +1,1354 @@ +/* arm.c + + ARM 2/3/6 Emulation (26 bit address bus) + + Todo: + Timing - Currently very approximated, nothing relies on proper timing so far. + IRQ timing not yet correct (again, nothing is affected by this so far). + + Recent changes (2005): + Fixed software interrupts + Fixed various mode change bugs + Added preliminary co-processor support. + + By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino + +*/ + +#include +#include +#include +//#include "state.h" +//#include "driver.h" +#include "burnint.h" +#include "arm_intf.h" + +#define READ8(addr) cpu_read8(addr) +#define WRITE8(addr,data) cpu_write8(addr,data) +#define READ32(addr) cpu_read32(addr) +#define WRITE32(addr,data) cpu_write32(addr,data) + +#define change_pc(x) R15 = (R15&~ADDRESS_MASK)|((x)&ADDRESS_MASK) + +#define ARM_DEBUG_CORE 0 +#define ARM_DEBUG_COPRO 0 + +enum +{ + ARM32_PC=0, + ARM32_R0, ARM32_R1, ARM32_R2, ARM32_R3, ARM32_R4, ARM32_R5, ARM32_R6, ARM32_R7, + ARM32_R8, ARM32_R9, ARM32_R10, ARM32_R11, ARM32_R12, ARM32_R13, ARM32_R14, ARM32_R15, + ARM32_FR8, ARM32_FR9, ARM32_FR10, ARM32_FR11, ARM32_FR12, ARM32_FR13, ARM32_FR14, + ARM32_IR13, ARM32_IR14, ARM32_SR13, ARM32_SR14 +}; + +enum +{ + eARM_MODE_USER = 0x0, + eARM_MODE_FIQ = 0x1, + eARM_MODE_IRQ = 0x2, + eARM_MODE_SVC = 0x3, + + kNumModes +}; + +/* There are 27 32 bit processor registers */ +enum +{ + eR0=0,eR1,eR2,eR3,eR4,eR5,eR6,eR7, + eR8,eR9,eR10,eR11,eR12, + eR13, /* Stack Pointer */ + eR14, /* Link Register (holds return address) */ + eR15, /* Program Counter */ + + /* Fast Interrupt */ + eR8_FIQ,eR9_FIQ,eR10_FIQ,eR11_FIQ,eR12_FIQ,eR13_FIQ,eR14_FIQ, + + /* IRQ */ + eR13_IRQ,eR14_IRQ, + + /* Software Interrupt */ + eR13_SVC,eR14_SVC, + + kNumRegisters +}; + +/* 16 processor registers are visible at any given time, + * banked depending on processor mode. + */ +static const int sRegisterTable[kNumModes][16] = +{ + { /* USR */ + eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7, + eR8,eR9,eR10,eR11,eR12, + eR13,eR14, + eR15 + }, + { /* FIQ */ + eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7, + eR8_FIQ,eR9_FIQ,eR10_FIQ,eR11_FIQ,eR12_FIQ, + eR13_FIQ,eR14_FIQ, + eR15 + }, + { /* IRQ */ + eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7, + eR8,eR9,eR10,eR11,eR12, + eR13_IRQ,eR14_IRQ, + eR15 + }, + { /* SVC */ + eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7, + eR8,eR9,eR10,eR11,eR12, + eR13_SVC,eR14_SVC, + eR15 + } +}; + +#define N_BIT 31 +#define Z_BIT 30 +#define C_BIT 29 +#define V_BIT 28 +#define I_BIT 27 +#define F_BIT 26 + +#define N_MASK ((UINT32)(1<> 31) + +/* Deconstructing an instruction */ + +#define INSN_COND ((UINT32) 0xf0000000u) +#define INSN_SDT_L ((UINT32) 0x00100000u) +#define INSN_SDT_W ((UINT32) 0x00200000u) +#define INSN_SDT_B ((UINT32) 0x00400000u) +#define INSN_SDT_U ((UINT32) 0x00800000u) +#define INSN_SDT_P ((UINT32) 0x01000000u) +#define INSN_BDT_L ((UINT32) 0x00100000u) +#define INSN_BDT_W ((UINT32) 0x00200000u) +#define INSN_BDT_S ((UINT32) 0x00400000u) +#define INSN_BDT_U ((UINT32) 0x00800000u) +#define INSN_BDT_P ((UINT32) 0x01000000u) +#define INSN_BDT_REGS ((UINT32) 0x0000ffffu) +#define INSN_SDT_IMM ((UINT32) 0x00000fffu) +#define INSN_MUL_A ((UINT32) 0x00200000u) +#define INSN_MUL_RM ((UINT32) 0x0000000fu) +#define INSN_MUL_RS ((UINT32) 0x00000f00u) +#define INSN_MUL_RN ((UINT32) 0x0000f000u) +#define INSN_MUL_RD ((UINT32) 0x000f0000u) +#define INSN_I ((UINT32) 0x02000000u) +#define INSN_OPCODE ((UINT32) 0x01e00000u) +#define INSN_S ((UINT32) 0x00100000u) +#define INSN_BL ((UINT32) 0x01000000u) +#define INSN_BRANCH ((UINT32) 0x00ffffffu) +#define INSN_SWI ((UINT32) 0x00ffffffu) +#define INSN_RN ((UINT32) 0x000f0000u) +#define INSN_RD ((UINT32) 0x0000f000u) +#define INSN_OP2 ((UINT32) 0x00000fffu) +#define INSN_OP2_SHIFT ((UINT32) 0x00000f80u) +#define INSN_OP2_SHIFT_TYPE ((UINT32) 0x00000070u) +#define INSN_OP2_RM ((UINT32) 0x0000000fu) +#define INSN_OP2_ROTATE ((UINT32) 0x00000f00u) +#define INSN_OP2_IMM ((UINT32) 0x000000ffu) +#define INSN_OP2_SHIFT_TYPE_SHIFT 4 +#define INSN_OP2_SHIFT_SHIFT 7 +#define INSN_OP2_ROTATE_SHIFT 8 +#define INSN_MUL_RS_SHIFT 8 +#define INSN_MUL_RN_SHIFT 12 +#define INSN_MUL_RD_SHIFT 16 +#define INSN_OPCODE_SHIFT 21 +#define INSN_RN_SHIFT 16 +#define INSN_RD_SHIFT 12 +#define INSN_COND_SHIFT 28 + +#define S_CYCLE 1 +#define N_CYCLE 1 +#define I_CYCLE 1 + +enum +{ + OPCODE_AND, /* 0000 */ + OPCODE_EOR, /* 0001 */ + OPCODE_SUB, /* 0010 */ + OPCODE_RSB, /* 0011 */ + OPCODE_ADD, /* 0100 */ + OPCODE_ADC, /* 0101 */ + OPCODE_SBC, /* 0110 */ + OPCODE_RSC, /* 0111 */ + OPCODE_TST, /* 1000 */ + OPCODE_TEQ, /* 1001 */ + OPCODE_CMP, /* 1010 */ + OPCODE_CMN, /* 1011 */ + OPCODE_ORR, /* 1100 */ + OPCODE_MOV, /* 1101 */ + OPCODE_BIC, /* 1110 */ + OPCODE_MVN /* 1111 */ +}; + +enum +{ + COND_EQ = 0, /* Z: equal */ + COND_NE, /* ~Z: not equal */ + COND_CS, COND_HS = 2, /* C: unsigned higher or same */ + COND_CC, COND_LO = 3, /* ~C: unsigned lower */ + COND_MI, /* N: negative */ + COND_PL, /* ~N: positive or zero */ + COND_VS, /* V: overflow */ + COND_VC, /* ~V: no overflow */ + COND_HI, /* C && ~Z: unsigned higher */ + COND_LS, /* ~C || Z: unsigned lower or same */ + COND_GE, /* N == V: greater or equal */ + COND_LT, /* N != V: less than */ + COND_GT, /* ~Z && (N == V): greater than */ + COND_LE, /* Z || (N != V): less than or equal */ + COND_AL, /* always */ + COND_NV /* never */ +}; + +#define LSL(v,s) ((v) << (s)) +#define LSR(v,s) ((v) >> (s)) +#define ROL(v,s) (LSL((v),(s)) | (LSR((v),32u - (s)))) +#define ROR(v,s) (LSR((v),(s)) | (LSL((v),32u - (s)))) + +/* Private Data */ + +/* sArmRegister defines the CPU state */ +typedef struct +{ + UINT32 sArmRegister[kNumRegisters]; + UINT32 coproRegister[16]; + UINT8 pendingIrq; + UINT8 pendingFiq; + + UINT32 ArmTotalCycles; + UINT32 ArmLeftCycles; +} ARM_REGS; + +static ARM_REGS arm; + +static int arm_icount; + +/* Prototypes */ +static void HandleALU( UINT32 insn); +static void HandleMul( UINT32 insn); +static void HandleBranch( UINT32 insn); +static void HandleMemSingle( UINT32 insn); +static void HandleMemBlock( UINT32 insn); +static void HandleCoPro( UINT32 insn); +static UINT32 decodeShift( UINT32 insn, UINT32 *pCarry); +static void arm_check_irq_state(void); + +/***************************************************************************/ + +inline void cpu_write32( int addr, UINT32 data ) +{ + /* Unaligned writes are treated as normal writes */ + Arm_program_write_dword_32le(addr&ADDRESS_MASK,data); +} + +inline void cpu_write8( int addr, UINT8 data ) +{ + Arm_program_write_byte_32le(addr,data); +} + +inline UINT32 cpu_read32( int addr ) +{ + UINT32 result = Arm_program_read_dword_32le(addr&ADDRESS_MASK); + + /* Unaligned reads rotate the word, they never combine words */ + if (addr&3) { + if ((addr&3)==1) + return ((result&0x000000ff)<<24)|((result&0xffffff00)>> 8); + if ((addr&3)==2) + return ((result&0x0000ffff)<<16)|((result&0xffff0000)>>16); + if ((addr&3)==3) + return ((result&0x00ffffff)<< 8)|((result&0xff000000)>>24); + } + + return result; +} + +inline UINT8 cpu_read8( int addr ) +{ + return Arm_program_read_byte_32le(addr); +} + +inline UINT32 GetRegister( int rIndex ) +{ + return arm.sArmRegister[sRegisterTable[MODE][rIndex]]; +} + +inline void SetRegister( int rIndex, UINT32 value ) +{ + arm.sArmRegister[sRegisterTable[MODE][rIndex]] = value; + if (rIndex == eR15) + change_pc(value & ADDRESS_MASK); +} + +/***************************************************************************/ + +void ArmReset(void) +{ + memset(&arm, 0, sizeof(arm)); + + /* start up in SVC mode with interrupts disabled. */ + R15 = eARM_MODE_SVC|I_MASK|F_MASK; + change_pc(R15 & ADDRESS_MASK); +} + +int ArmRun( int cycles ) +{ + UINT32 pc; + UINT32 insn; + + arm_icount = cycles; + arm.ArmLeftCycles = cycles; + + do + { + /* load instruction */ + pc = R15; + insn = Arm_program_opcode_dword_32le( pc & ADDRESS_MASK ); + + switch (insn >> INSN_COND_SHIFT) + { + case COND_EQ: + if (Z_IS_CLEAR(pc)) goto L_Next; + break; + case COND_NE: + if (Z_IS_SET(pc)) goto L_Next; + break; + case COND_CS: + if (C_IS_CLEAR(pc)) goto L_Next; + break; + case COND_CC: + if (C_IS_SET(pc)) goto L_Next; + break; + case COND_MI: + if (N_IS_CLEAR(pc)) goto L_Next; + break; + case COND_PL: + if (N_IS_SET(pc)) goto L_Next; + break; + case COND_VS: + if (V_IS_CLEAR(pc)) goto L_Next; + break; + case COND_VC: + if (V_IS_SET(pc)) goto L_Next; + break; + case COND_HI: + if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; + break; + case COND_LS: + if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; + break; + case COND_GE: + if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ + break; + case COND_LT: + if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; + break; + case COND_GT: + if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; + break; + case COND_LE: + if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; + break; + case COND_NV: + goto L_Next; + } + /* Condition satisfied, so decode the instruction */ + if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ + { + HandleMul(insn); + R15 += 4; + } + else if (!(insn & 0x0c000000u)) /* Data processing */ + { + HandleALU(insn); + } + else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ + { + HandleMemSingle(insn); + R15 += 4; + } + else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ + { + HandleMemBlock(insn); + R15 += 4; + } + else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ + { + HandleBranch(insn); + } + else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ + { + HandleCoPro(insn); + R15 += 4; + } + else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ + { + pc=R15+4; + R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ + SetRegister( 14, pc ); /* save PC */ + R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); + change_pc(pc&ADDRESS_MASK); + arm_icount -= 2 * S_CYCLE + N_CYCLE; + } + else /* Undefined */ + { + L_Next: + arm_icount -= S_CYCLE; + R15 += 4; + } + + arm_check_irq_state(); + + } while( arm_icount > 0 ); + + arm.ArmTotalCycles += (cycles - arm_icount); + + return cycles - arm_icount; +} /* arm_execute */ + +static void arm_check_irq_state(void) +{ + UINT32 pc = R15+4; /* save old pc (already incremented in pipeline) */; + + /* Exception priorities (from ARM6, not specifically ARM2/3): + + Reset + Data abort + FIRQ + IRQ + Prefetch abort + Undefined instruction + */ + + if (arm.pendingFiq && (pc&F_MASK)==0) { + R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */ + SetRegister( 14, pc ); /* save PC */ + R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */ + change_pc(R15 & ADDRESS_MASK); + arm.pendingFiq=0; + return; + } + + if (arm.pendingIrq && (pc&I_MASK)==0) { + R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */ + SetRegister( 14, pc ); /* save PC */ + R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */ + change_pc(R15 & ADDRESS_MASK); + arm.pendingIrq=0; + return; + } +} + +void arm_set_irq_line(int irqline, int state) +{ + switch (irqline) { + + case ARM_IRQ_LINE: /* IRQ */ + if (state && (R15&0x3)!=eARM_MODE_IRQ) /* Don't allow nested IRQs */ + arm.pendingIrq=1; + else + arm.pendingIrq=0; + break; + + case ARM_FIRQ_LINE: /* FIRQ */ + if (state && (R15&0x3)!=eARM_MODE_FIQ) /* Don't allow nested FIRQs */ + arm.pendingFiq=1; + else + arm.pendingFiq=0; + break; + } + + arm_check_irq_state(); +} + +/***************************************************************************/ + +static void HandleBranch( UINT32 insn ) +{ + UINT32 off = (insn & INSN_BRANCH) << 2; + + /* Save PC into LR if this is a branch with link */ + if (insn & INSN_BL) + { + SetRegister(14,R15 + 4); + } + + /* Sign-extend the 24-bit offset in our calculations */ + if (off & 0x2000000u) + { + R15 -= ((~(off | 0xfc000000u)) + 1) - 8; + } + else + { + R15 += off + 8; + } + change_pc(R15 & ADDRESS_MASK); + arm_icount -= 2 * S_CYCLE + N_CYCLE; +} + +static void HandleMemSingle( UINT32 insn ) +{ + UINT32 rn, rnv, off, rd; + + /* Fetch the offset */ + if (insn & INSN_I) + { + off = decodeShift(insn, NULL); + } + else + { + off = insn & INSN_SDT_IMM; + } + + /* Calculate Rn, accounting for PC */ + rn = (insn & INSN_RN) >> INSN_RN_SHIFT; + + if (insn & INSN_SDT_P) + { + /* Pre-indexed addressing */ + if (insn & INSN_SDT_U) + { + rnv = (GetRegister(rn) + off); + } + else + { + rnv = (GetRegister(rn) - off); + } + + if (insn & INSN_SDT_W) + { + SetRegister(rn,rnv); + } + else if (rn == eR15) + { + rnv = (rnv & ADDRESS_MASK) + 8; + } + } + else + { + /* Post-indexed addressing */ + if (rn == eR15) + { + rnv = (R15 & ADDRESS_MASK) + 8; + } + else + { + rnv = GetRegister(rn); + } + } + + /* Do the transfer */ + rd = (insn & INSN_RD) >> INSN_RD_SHIFT; + if (insn & INSN_SDT_L) + { + /* Load */ + arm_icount -= S_CYCLE + I_CYCLE + N_CYCLE; + if (insn & INSN_SDT_B) + { + SetRegister(rd,(UINT32) READ8(rnv)); + } + else + { + if (rd == eR15) + { + R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); + change_pc(R15 & ADDRESS_MASK); + + /* + The docs are explicit in that the bottom bits should be masked off + when writing to R15 in this way, however World Cup Volleyball 95 has + an example of an unaligned jump (bottom bits = 2) where execution + should definitely continue from the rounded up address. + + In other cases, 4 is subracted from R15 here to account for pipelining. + */ + if ((READ32(rnv)&3)==0) + R15 -= 4; + + arm_icount -= S_CYCLE + N_CYCLE; + } + else + { + SetRegister(rd,READ32(rnv)); + } + } + } + else + { + /* Store */ + arm_icount -= 2 * N_CYCLE; + if (insn & INSN_SDT_B) + { + WRITE8(rnv, (UINT8) GetRegister(rd) & 0xffu); + } + else + { + WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); + } + } + + /* Do post-indexing writeback */ + if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) + { + if (insn & INSN_SDT_U) + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd==rn) { + SetRegister(rn,GetRegister(rd)); + } + else { + SetRegister(rn,(rnv + off)); + } + } + else + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd==rn) { + SetRegister(rn,GetRegister(rd)); + } + else { + SetRegister(rn,(rnv - off)); + } + } + } +} /* HandleMemSingle */ + +#define IsNeg(i) ((i) >> 31) +#define IsPos(i) ((~(i)) >> 31) + +/* Set NZCV flags for ADDS / SUBS */ + +#define HandleALUAddFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + R15 = \ + ((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) \ + << V_BIT) \ + | (((~(rn)) < (op2)) << C_BIT) \ + | HandleALUNZFlags(rd)) \ + + 4; \ + else R15 += 4; + +#define HandleALUSubFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + R15 = \ + ((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) \ + << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd)) \ + + 4; \ + else R15 += 4; + +/* Set NZC flags for logical operations. */ + +#define HandleALUNZFlags(rd) \ + (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT)) + +#define HandleALULogicalFlags(rd, sc) \ + if (insn & INSN_S) \ + R15 = ((R15 &~ (N_MASK | Z_MASK | C_MASK)) \ + | HandleALUNZFlags(rd) \ + | (((sc) != 0) << C_BIT)) + 4; \ + else R15 += 4; + +static void HandleALU( UINT32 insn ) +{ + UINT32 op2, sc=0, rd, rn, opcode; + UINT32 by, rdn; + + opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT; + arm_icount -= S_CYCLE; + + rd = 0; + rn = 0; + + /* Construct Op2 */ + if (insn & INSN_I) + { + /* Immediate constant */ + by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT; + if (by) + { + op2 = ROR(insn & INSN_OP2_IMM, by << 1); + sc = op2 & SIGN_BIT; + } + else + { + op2 = insn & INSN_OP2; + sc = R15 & C_MASK; + } + } + else + { + op2 = decodeShift(insn, (insn & INSN_S) ? &sc : NULL); + + if (!(insn & INSN_S)) + sc=0; + } + + /* Calculate Rn to account for pipelining */ + if ((opcode & 0xd) != 0xd) /* No Rn in MOV */ + { + if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15) + { + /* Docs strongly suggest the mode bits should be included here, but it breaks Captain + America, as it starts doing unaligned reads */ + rn=(R15+8)&ADDRESS_MASK; + } + else + { + rn = GetRegister(rn); + } + } + + /* Perform the operation */ + switch ((insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT) + { + /* Arithmetic operations */ + case OPCODE_SBC: + rd = (rn - op2 - (R15 & C_MASK ? 0 : 1)); + HandleALUSubFlags(rd, rn, op2); + break; + case OPCODE_CMP: + case OPCODE_SUB: + rd = (rn - op2); + HandleALUSubFlags(rd, rn, op2); + break; + case OPCODE_RSC: + rd = (op2 - rn - (R15 & C_MASK ? 0 : 1)); + HandleALUSubFlags(rd, op2, rn); + break; + case OPCODE_RSB: + rd = (op2 - rn); + HandleALUSubFlags(rd, op2, rn); + break; + case OPCODE_ADC: + rd = (rn + op2 + ((R15 & C_MASK) >> C_BIT)); + HandleALUAddFlags(rd, rn, op2); + break; + case OPCODE_CMN: + case OPCODE_ADD: + rd = (rn + op2); + HandleALUAddFlags(rd, rn, op2); + break; + + /* Logical operations */ + case OPCODE_AND: + case OPCODE_TST: + rd = rn & op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_BIC: + rd = rn &~ op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_TEQ: + case OPCODE_EOR: + rd = rn ^ op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_ORR: + rd = rn | op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_MOV: + rd = op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_MVN: + rd = (~op2); + HandleALULogicalFlags(rd, sc); + break; + } + + /* Put the result in its register if not a test */ + rdn = (insn & INSN_RD) >> INSN_RD_SHIFT; + if ((opcode & 0xc) != 0x8) + { + if (rdn == eR15 && !(insn & INSN_S)) + { + /* Merge the old NZCV flags into the new PC value */ + R15 = (rd & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & IRQ_MASK) | (R15&MODE_MASK); + change_pc(R15 & ADDRESS_MASK); + arm_icount -= S_CYCLE + N_CYCLE; + } + else + { + if (rdn==eR15) + { + /* S Flag is set - update PSR & mode if in non-user mode only */ + if ((R15&MODE_MASK)!=0) + { + SetRegister(rdn,rd); + } + else + { + SetRegister(rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); + } + arm_icount -= S_CYCLE + N_CYCLE; + } + else + { + SetRegister(rdn,rd); + } + } + /* TST & TEQ can affect R15 (the condition code register) with the S bit set */ + } else if (rdn==eR15) { + if (insn & INSN_S) { + /* Dubious hack for 'TEQS R15, #$3', the docs suggest execution + should continue two instructions later (because pipelined R15 + is read back as already being incremented), but it seems the + hardware should execute the instruction in the delay slot. + Simulate it by just setting the PC back to the previously + skipped instruction. + + See Heavy Smash (Data East) at 0x1c4 + */ + if (insn==0xe33ff003) + rd-=4; + + arm_icount -= S_CYCLE + N_CYCLE; + if ((R15&MODE_MASK)!=0) + { + SetRegister(15, rd); + } + else + { + SetRegister(15, (rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK)); + } + } + } +} + +static void HandleMul( UINT32 insn) +{ + UINT32 r; + + arm_icount -= S_CYCLE + I_CYCLE; + /* should be: + Range of Rs Number of cycles + + &0 -- &1 1S + 1I + &2 -- &7 1S + 2I + &8 -- &1F 1S + 3I + &20 -- &7F 1S + 4I + &80 -- &1FF 1S + 5I + &200 -- &7FF 1S + 6I + &800 -- &1FFF 1S + 7I + &2000 -- &7FFF 1S + 8I + &8000 -- &1FFFF 1S + 9I + &20000 -- &7FFFF 1S + 10I + &80000 -- &1FFFFF 1S + 11I + &200000 -- &7FFFFF 1S + 12I + &800000 -- &1FFFFFF 1S + 13I + &2000000 -- &7FFFFFF 1S + 14I + &8000000 -- &1FFFFFFF 1S + 15I + &20000000 -- &FFFFFFFF 1S + 16I + */ + + /* Do the basic multiply of Rm and Rs */ + r = GetRegister( insn&INSN_MUL_RM ) * + GetRegister( (insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT ); + + /* Add on Rn if this is a MLA */ + if (insn & INSN_MUL_A) + { + r += GetRegister((insn&INSN_MUL_RN)>>INSN_MUL_RN_SHIFT); + } + + /* Write the result */ + SetRegister((insn&INSN_MUL_RD)>>INSN_MUL_RD_SHIFT,r); + + /* Set N and Z if asked */ + if( insn & INSN_S ) + { + R15 = (R15 &~ (N_MASK | Z_MASK)) | HandleALUNZFlags(r); + } +} + +static int loadInc ( UINT32 pat, UINT32 rbv, UINT32 s) +{ + int i,result; + + result = 0; + for( i=0; i<16; i++ ) + { + if( (pat>>i)&1 ) + { + if (i==15) { + if (s) /* Pull full contents from stack */ + SetRegister( 15, READ32(rbv+=4) ); + else /* Pull only address, preserve mode & status flags */ + SetRegister( 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv+=4))&ADDRESS_MASK) ); + } else + SetRegister( i, READ32(rbv+=4) ); + + result++; + } + } + return result; +} + +static int loadDec( UINT32 pat, UINT32 rbv, UINT32 s, UINT32* deferredR15, int* defer) +{ + int i,result; + + result = 0; + for( i=15; i>=0; i-- ) + { + if( (pat>>i)&1 ) + { + if (i==15) { + *defer=1; + if (s) /* Pull full contents from stack */ + *deferredR15=READ32(rbv-=4); + else /* Pull only address, preserve mode & status flags */ + *deferredR15=(R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv-=4))&ADDRESS_MASK); + } + else + SetRegister( i, READ32(rbv -=4) ); + result++; + } + } + return result; +} + +static int storeInc( UINT32 pat, UINT32 rbv) +{ + int i,result; + + result = 0; + for( i=0; i<16; i++ ) + { + if( (pat>>i)&1 ) + { + WRITE32( rbv += 4, GetRegister(i) ); + result++; + } + } + return result; +} /* storeInc */ + +static int storeDec( UINT32 pat, UINT32 rbv) +{ + int i,result; + + result = 0; + for( i=15; i>=0; i-- ) + { + if( (pat>>i)&1 ) + { + WRITE32( rbv -= 4, GetRegister(i) ); + result++; + } + } + return result; +} /* storeDec */ + +static void HandleMemBlock( UINT32 insn) +{ + UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT; + UINT32 rbp = GetRegister(rb); + int result; + + if (insn & INSN_BDT_L) + { + /* Loading */ + if (insn & INSN_BDT_U) + { + /* Incrementing */ + if (!(insn & INSN_BDT_P)) rbp = rbp + (- 4); + + result = loadInc( insn & 0xffff, rbp, insn&INSN_BDT_S ); + + if (insn & 0x8000) { + R15-=4; + arm_icount -= S_CYCLE + N_CYCLE; + } + + if (insn & INSN_BDT_W) + { + /* Arm docs notes: The base register can always be loaded without any problems. + However, don't specify writeback if the base register is being loaded - + you can't end up with both a written-back value and a loaded value in the base register! + + However - Fighter's History does exactly that at 0x121e4 (LDMUW [R13], { R13-R15 })! + + This emulator implementation skips applying writeback in this case, which is confirmed + correct for this situation, but that is not necessarily true for all ARM hardware + implementations (the results are officially undefined). + */ + if ((insn&(1<> INSN_OP2_SHIFT_SHIFT; + UINT32 rm = GetRegister( insn & INSN_OP2_RM ); + UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT; + + if ((insn & INSN_OP2_RM)==0xf) { + /* If hardwired shift, then PC is 8 bytes ahead, else if register shift + is used, then 12 bytes - TODO?? */ + rm+=8; + } + + /* All shift types ending in 1 are Rk, not #k */ + if( t & 1 ) + { + //see p35 for check on this + k = GetRegister(k >> 1)&0x1f; + arm_icount -= S_CYCLE; + if( k == 0 ) /* Register shift by 0 is a no-op */ + { + if (pCarry) *pCarry = R15 & C_MASK; + return rm; + } + } + /* Decode the shift type and perform the shift */ + switch (t >> 1) + { + case 0: /* LSL */ + if (pCarry) + { + *pCarry = k ? (rm & (1 << (32 - k))) : (R15 & C_MASK); + } + return k ? LSL(rm, k) : rm; + break; + + case 1: /* LSR */ + if (k == 0 || k == 32) + { + if (pCarry) *pCarry = rm & SIGN_BIT; + return 0; + } + else if (k > 32) + { + if (pCarry) *pCarry = 0; + return 0; + } + else + { + if (pCarry) *pCarry = (rm & (1 << (k - 1))); + return LSR(rm, k); + } + break; + + case 2: /* ASR */ + if (k == 0 || k > 32) + k = 32; + if (pCarry) *pCarry = (rm & (1 << (k - 1))); + if (k >= 32) + return rm & SIGN_BIT ? 0xffffffffu : 0; + else + { + if (rm & SIGN_BIT) + return LSR(rm, k) | (0xffffffffu << (32 - k)); + else + return LSR(rm, k); + } + break; + + case 3: /* ROR and RRX */ + if (k) + { + while (k > 32) k -= 32; + if (pCarry) *pCarry = rm & SIGN_BIT; + return ROR(rm, k); + } + else + { + if (pCarry) *pCarry = (rm & 1); + return LSR(rm, 1) | ((R15 & C_MASK) << 2); + } + break; + } + + return 0; +} /* decodeShift */ + + +static UINT32 BCDToDecimal(UINT32 value) +{ + UINT32 accumulator = 0; + UINT32 multiplier = 1; + int i; + + for(i = 0; i < 8; i++) + { + accumulator += (value & 0xF) * multiplier; + + multiplier *= 10; + value >>= 4; + } + + return accumulator; +} + +static UINT32 DecimalToBCD(UINT32 value) +{ + UINT32 accumulator = 0; + UINT32 divisor = 10; + int i; + + for(i = 0; i < 8; i++) + { + UINT32 temp; + + temp = value % divisor; + value -= temp; + temp /= divisor / 10; + + accumulator += temp << (i * 4); + + divisor *= 10; + } + + return accumulator; +} + +static void HandleCoPro( UINT32 insn) +{ + UINT32 rn=(insn>>12)&0xf; + UINT32 crn=(insn>>16)&0xf; + + arm_icount -= S_CYCLE; + + /* MRC - transfer copro register to main register */ + if( (insn&0x0f100010)==0x0e100010 ) + { + SetRegister(rn, arm.coproRegister[crn]); + } + /* MCR - transfer main register to copro register */ + else if( (insn&0x0f100010)==0x0e000010 ) + { + arm.coproRegister[crn]=GetRegister(rn); + + /* Data East 156 copro specific - trigger BCD operation */ + if (crn==2) + { + if (arm.coproRegister[crn]==0) + { + /* Unpack BCD */ + int v0=BCDToDecimal(arm.coproRegister[0]); + int v1=BCDToDecimal(arm.coproRegister[1]); + + /* Repack vcd */ + arm.coproRegister[5]=DecimalToBCD(v0+v1); + } + else if (arm.coproRegister[crn]==1) + { + /* Unpack BCD */ + int v0=BCDToDecimal(arm.coproRegister[0]); + int v1=BCDToDecimal(arm.coproRegister[1]); + + /* Repack vcd */ + arm.coproRegister[5]=DecimalToBCD(v0*v1); + } + else if (arm.coproRegister[crn]==3) + { + /* Unpack BCD */ + int v0=BCDToDecimal(arm.coproRegister[0]); + int v1=BCDToDecimal(arm.coproRegister[1]); + + /* Repack vcd */ + arm.coproRegister[5]=DecimalToBCD(v0-v1); + } + } + } + /* CDP - perform copro operation */ + else if( (insn&0x0f000010)==0x0e000000 ) + { + /* Data East 156 copro specific divider - result in reg 3/4 */ + if (arm.coproRegister[1]) + { + arm.coproRegister[3]=arm.coproRegister[0] / arm.coproRegister[1]; + arm.coproRegister[4]=arm.coproRegister[0] % arm.coproRegister[1]; + } + else + { + /* Unverified */ + arm.coproRegister[3]=0xffffffff; + arm.coproRegister[4]=0xffffffff; + } + } +} + +// burn some cycles +void ArmIdleCycles(int cycles) +{ + if (arm_icount > cycles) { + arm_icount -= cycles; + } else { + arm_icount = 0; + } +} + +// get the current position +unsigned int ArmGetPc() +{ + return arm.sArmRegister[15]&ADDRESS_MASK; +} + +// get the remaining cycles left to run +unsigned int ArmRemainingCycles() +{ + return (arm.ArmLeftCycles - arm_icount); +} + +// get the total of cycles run +unsigned int ArmGetTotalCycles() +{ + return arm.ArmTotalCycles + (arm.ArmLeftCycles - arm_icount); +} + +// stop the current cpu slice +void ArmRunEnd() +{ + arm_icount = 0; +} + +// start a new frame +void ArmNewFrame() +{ + arm.ArmTotalCycles = 0; + arm_icount = 0; + arm.ArmLeftCycles = 0; +} + +int ArmScan(int nAction, int *) +{ + struct BurnArea ba; + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + ba.Data = &arm; + ba.nLen = sizeof(ARM_REGS); + ba.szName = "ARM Registers"; + BurnAcb(&ba); + + SCAN_VAR(arm_icount); + } + + return 0; +} + diff --git a/src/cpu/arm7/arm7.cpp b/src/cpu/arm7/arm7.cpp new file mode 100644 index 00000000..1579cefb --- /dev/null +++ b/src/cpu/arm7/arm7.cpp @@ -0,0 +1,177 @@ +/***************************************************************************** + * + * arm7.c + * Portable ARM7TDMI CPU Emulator + * + * Copyright Steve Ellenoff, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * sellenoff@hotmail.com + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on: + * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' + * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) + * #3) Thumb support by Ryan Holtz + * + *****************************************************************************/ + +/****************************************************************************** + * Notes: + + ** This is a plain vanilla implementation of an ARM7 cpu which incorporates my ARM7 core. + It can be used as is, or used to demonstrate how to utilize the arm7 core to create a cpu + that uses the core, since there are numerous different mcu packages that incorporate an arm7 core. + + See the notes in the arm7core.c file itself regarding issues/limitations of the arm7 core. + ** +*****************************************************************************/ +#include "burnint.h" +#include "arm7core.h" +#include "arm7_intf.h" + +#if defined __GNUC__ +__extension__ typedef unsigned long long UINT64; +__extension__ typedef signed long long INT64; +#endif + +#if defined _MSC_VER +typedef unsigned long long UINT64; +typedef signed long long INT64; +#endif + +/* Example for showing how Co-Proc functions work */ +#define TEST_COPROC_FUNCS 0 + +/* prototypes */ +#if TEST_COPROC_FUNCS +static WRITE32_HANDLER(test_do_callback); +static READ32_HANDLER(test_rt_r_callback); +static WRITE32_HANDLER(test_rt_w_callback); +static void test_dt_r_callback(UINT32 insn, UINT32 *prn, UINT32 (*read32)(UINT32 addr)); +static void test_dt_w_callback(UINT32 insn, UINT32 *prn, void (*write32)(UINT32 addr, UINT32 data)); +static char *Spec_RT(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0); +static char *Spec_DT(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0); +static char *Spec_DO(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0); +#endif + +/* Macros that can be re-defined for custom cpu implementations - The core expects these to be defined */ +/* In this case, we are using the default arm7 handlers (supplied by the core) + - but simply changes these and define your own if needed for cpu implementation specific needs */ +#define READ8(addr) arm7_cpu_read8(addr) +#define WRITE8(addr,data) arm7_cpu_write8(addr,data) +#define READ16(addr) arm7_cpu_read16(addr) +#define WRITE16(addr,data) arm7_cpu_write16(addr,data) +#define READ32(addr) arm7_cpu_read32(addr) +#define WRITE32(addr,data) arm7_cpu_write32(addr,data) +#define PTR_READ32 &arm7_cpu_read32 +#define PTR_WRITE32 &arm7_cpu_write32 + +/* Macros that need to be defined according to the cpu implementation specific need */ +#define ARM7REG(reg) arm7.sArmRegister[reg] +#define ARM7 arm7 +#define ARM7_ICOUNT arm7_icount + +/* CPU Registers */ +typedef struct +{ + ARM7CORE_REGS // these must be included in your cpu specific register implementation +} ARM7_REGS; + +static ARM7_REGS arm7; +static int ARM7_ICOUNT; +static int total_cycles = 0; +static int curr_cycles = 0; + +void Arm7Open(int ) +{ + +} + +void Arm7Close() +{ + +} + +int Arm7TotalCycles() +{ + return total_cycles; +} + +void Arm7RunEnd() +{ + arm7_icount = 0; +} + +void Arm7BurnCycles(int cycles) +{ + arm7_icount -= cycles; +} + +void Arm7NewFrame() +{ + total_cycles = 0; +} + +/* include the arm7 core */ +#include "arm7core.c" + +/*************************************************************************** + * CPU SPECIFIC IMPLEMENTATIONS + **************************************************************************/ +/* +static void arm7_init(int ) +{ + +}*/ + +void Arm7Reset() +{ + // must call core reset + arm7_core_reset(); +} + +/* +static void arm7_exit() +{ + +}*/ + +int Arm7Run(int cycles) +{ +/* include the arm7 core execute code */ +#include "arm7exec.c" +} + +void arm7_set_irq_line(int irqline, int state) +{ + // must call core + arm7_core_set_irq_line(irqline,state); +} + +int Arm7Scan(int nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_DRIVER_DATA) { + memset(&ba, 0, sizeof(ba)); + ba.Data = (unsigned char*)&ARM7; + ba.nLen = sizeof(ARM7); + ba.szName = "All Registers"; + BurnAcb(&ba); + + SCAN_VAR(ARM7_ICOUNT); + SCAN_VAR(total_cycles); + SCAN_VAR(curr_cycles); + } + + return 0; +} diff --git a/src/cpu/arm7/arm7core.c b/src/cpu/arm7/arm7core.c new file mode 100644 index 00000000..842f7542 --- /dev/null +++ b/src/cpu/arm7/arm7core.c @@ -0,0 +1,1726 @@ +/***************************************************************************** + * + * arm7core.c + * Portable ARM7TDMI Core Emulator + * + * Copyright Steve Ellenoff, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * sellenoff@hotmail.com + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on: + * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' + * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) + * #3) Thumb support by Ryan Holtz + * #4) Additional Thumb support and bugfixes by R. Belmont + * + *****************************************************************************/ + +/****************************************************************************** + * Notes: + + **This core comes from my AT91 cpu core contributed to PinMAME, + but with all the AT91 specific junk removed, + which leaves just the ARM7TDMI core itself. I further removed the CPU specific MAME stuff + so you just have the actual ARM7 core itself, since many cpu's incorporate an ARM7 core, but add on + many cpu specific functionality. + + Therefore, to use the core, you simpy include this file along with the .h file into your own cpu specific + implementation, and therefore, this file shouldn't be compiled as part of your project directly. + Additionally, you will need to include arm7exec.c in your cpu's execute routine. + + For better or for worse, the code itself is very much intact from it's arm 2/3/6 origins from + Bryan & Phil's work. I contemplated merging it in, but thought the fact that the CPSR is + no longer part of the PC was enough of a change to make it annoying to merge. + ** + + Coprocessor functions are heavily implementation specific, so callback handlers are used to allow the + implementation to handle the functionality. Custom DASM handlers are included as well to allow the DASM + output to be tailored to the co-proc implementation details. + + Todo: + 26 bit compatibility mode not implemented. + Data Processing opcodes need cycle count adjustments (see page 194 of ARM7TDMI manual for instruction timing summary) + Multi-emulated cpu support untested, but probably will not work too well, as no effort was made to code for more than 1. + Could not find info on what the TEQP opcode is from page 44.. + I have no idea if user bank switching is right, as I don't fully understand it's use. + Search for Todo: tags for remaining items not done. + + + Differences from Arm 2/3 (6 also?) + -Thumb instruction support + -Full 32 bit address support + -PC no longer contains CPSR information, CPSR is own register now + -New register SPSR to store previous contents of CPSR (this register is banked in many modes) + -New opcodes for CPSR transfer, Long Multiplication, Co-Processor support, and some others + -User Bank Mode transfer using certain flags which were previously unallowed (LDM/STM with S Bit & R15) + -New operation modes? (unconfirmed) + + Based heavily on arm core from MAME 0.76: + ***************************************** + ARM 2/3/6 Emulation + + Todo: + Software interrupts unverified (nothing uses them so far, but they should be ok) + Timing - Currently very approximated, nothing relies on proper timing so far. + IRQ timing not yet correct (again, nothing is affected by this so far). + + By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino +*****************************************************************************/ + +#include +//#include "deprecat.h" + +#define ARM7_DEBUG_CORE 0 +#define logerror printf +#define fatalerror logerror + +#if 0 +#define LOG(x) mame_printf_debug x +#else +#define LOG(x) logerror x +#endif + +#define ARM7_INLINE static inline + +/* Prototypes */ + +// SJE: should these be inline? or are they too big to see any benefit? + +static void HandleCoProcDO(UINT32 insn); +static void HandleCoProcRT(UINT32 insn); +static void HandleCoProcDT(UINT32 insn); +static void HandleHalfWordDT(UINT32 insn); +static void HandleSwap(UINT32 insn); +static void HandlePSRTransfer(UINT32 insn); +static void HandleALU(UINT32 insn); +static void HandleMul(UINT32 insn); +static void HandleUMulLong(UINT32 insn); +static void HandleSMulLong(UINT32 insn); +ARM7_INLINE void HandleBranch(UINT32 insn); // pretty short, so ARM7_INLINE should be ok +static void HandleMemSingle(UINT32 insn); +static void HandleMemBlock(UINT32 insn); +static UINT32 decodeShift(UINT32 insn, UINT32 *pCarry); +ARM7_INLINE void SwitchMode(int); +static void arm7_check_irq_state(void); + +ARM7_INLINE void arm7_cpu_write32(UINT32 addr, UINT32 data); +ARM7_INLINE void arm7_cpu_write16(UINT32 addr, UINT16 data); +ARM7_INLINE void arm7_cpu_write8(UINT32 addr, UINT8 data); +ARM7_INLINE UINT32 arm7_cpu_read32(UINT32 addr); +ARM7_INLINE UINT16 arm7_cpu_read16(UINT32 addr); +ARM7_INLINE UINT8 arm7_cpu_read8(UINT32 addr); + +/* Static Vars */ +// Note: for multi-cpu implementation, this approach won't work w/o modification +void((*arm7_coproc_do_callback)(unsigned int, unsigned int)); // holder for the co processor Data Operations Callback func. +unsigned int((*arm7_coproc_rt_r_callback)(unsigned int)); // holder for the co processor Register Transfer Read Callback func. +void((*arm7_coproc_rt_w_callback)(unsigned int, unsigned int)); // holder for the co processor Register Transfer Write Callback Callback func. +// holder for the co processor Data Transfer Read & Write Callback funcs +void (*arm7_coproc_dt_r_callback)(UINT32 insn, UINT32 *prn, UINT32 (*read32)(UINT32 addr)); +void (*arm7_coproc_dt_w_callback)(UINT32 insn, UINT32 *prn, void (*write32)(UINT32 addr, UINT32 data)); + + +/*************************************************************************** + * Default Memory Handlers + ***************************************************************************/ +ARM7_INLINE void arm7_cpu_write32(UINT32 addr, UINT32 data) +{ + addr &= ~3; + Arm7_program_write_dword_32le(addr, data); // iq_132 +} + + +ARM7_INLINE void arm7_cpu_write16(UINT32 addr, UINT16 data) +{ + addr &= ~1; + Arm7_program_write_word_32le(addr, data); // iq_132 +} + +ARM7_INLINE void arm7_cpu_write8(UINT32 addr, UINT8 data) +{ + Arm7_program_write_byte_32le(addr, data); // iq_132 +} + +ARM7_INLINE UINT32 arm7_cpu_read32(UINT32 addr) +{ + UINT32 result; + + if (addr & 3) + { + result = Arm7_program_read_dword_32le(addr & ~3); // iq_132 + result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + } + else + { + result = Arm7_program_read_dword_32le(addr); // iq_132 + } + + return result; +} + +ARM7_INLINE UINT16 arm7_cpu_read16(UINT32 addr) +{ + UINT16 result; + + result = Arm7_program_read_word_32le(addr & ~1); + + if (addr & 1) + { + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + + return result; +} + +ARM7_INLINE UINT8 arm7_cpu_read8(UINT32 addr) +{ + UINT8 result = Arm7_program_read_byte_32le(addr); + + // Handle through normal 8 bit handler (for 32 bit cpu) + return result; +} + +ARM7_INLINE UINT32 cpu_readop32(UINT32 addr) +{ + // iq_132 + + UINT32 result; + + if (addr & 3) + { + result = Arm7_program_opcode_dword_32le(addr & ~3); // iq_132 + result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + } + else + { + result = Arm7_program_opcode_dword_32le(addr); // iq_132 + } + + return result; +} + +ARM7_INLINE UINT32 cpu_readop16(UINT32 addr) +{ + UINT16 result; + + result = Arm7_program_opcode_word_32le(addr & ~1); // iq_132 + + if (addr & 1) + { + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + + return result; +} + +/*************** + * helper funcs + ***************/ + +// TODO LD: +// - SIGN_BITS_DIFFER = THUMB_SIGN_BITS_DIFFER +// - do while (0) +// - HandleALUAddFlags = HandleThumbALUAddFlags except for PC incr +// - HandleALUSubFlags = HandleThumbALUSubFlags except for PC incr + +/* Set NZCV flags for ADDS / SUBS */ +#define HandleALUAddFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((~(rn)) < (op2)) << C_BIT) \ + | HandleALUNZFlags(rd))); \ + R15 += 4; + +#define HandleThumbALUAddFlags(rd, rn, op2) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | (((!THUMB_SIGN_BITS_DIFFER(rn, op2)) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((~(rn)) < (op2)) << C_BIT) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +#define IsNeg(i) ((i) >> 31) +#define IsPos(i) ((~(i)) >> 31) + +#define HandleALUSubFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 4; + +#define HandleThumbALUSubFlags(rd, rn, op2) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | ((THUMB_SIGN_BITS_DIFFER(rn, op2) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +/* Set NZC flags for logical operations. */ + +// This macro (which I didn't write) - doesn't make it obvious that the SIGN BIT = 31, just as the N Bit does, +// therefore, N is set by default +#define HandleALUNZFlags(rd) \ + (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT)) + + +// Long ALU Functions use bit 63 +#define HandleLongALUNZFlags(rd) \ + ((((rd) & ((UINT64)1 << 63)) >> 32) | ((!(rd)) << Z_BIT)) + +#define HandleALULogicalFlags(rd, sc) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | C_MASK)) \ + | HandleALUNZFlags(rd) \ + | (((sc) != 0) << C_BIT))); \ + R15 += 4; + +// convert cpsr mode num into to text +static const char modetext[ARM7_NUM_MODES][5] = { + "USER", "FIRQ", "IRQ", "SVC", "ILL1", "ILL2", "ILL3", "ABT", + "ILL4", "ILL5", "ILL6", "UND", "ILL7", "ILL8", "ILL9", "SYS" +}; + +/*static const char *GetModeText(int cpsr) +{ + return modetext[cpsr & MODE_FLAG]; +}*/ + +// used to be functions, but no longer a need, so we'll use define for better speed. +#define GetRegister(rIndex) ARM7REG(sRegisterTable[GET_MODE][rIndex]) +#define SetRegister(rIndex, value) ARM7REG(sRegisterTable[GET_MODE][rIndex]) = value + +// I could prob. convert to macro, but Switchmode shouldn't occur that often in emulated code.. +ARM7_INLINE void SwitchMode(int cpsr_mode_val) +{ + UINT32 cspr = GET_CPSR & ~MODE_FLAG; + SET_CPSR(cspr | cpsr_mode_val); +} + + +/* Decodes an Op2-style shifted-register form. If @carry@ is non-zero the + * shifter carry output will manifest itself as @*carry == 0@ for carry clear + * and @*carry != 0@ for carry set. + + SJE: Rules: + IF RC = 256, Result = no shift. + LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit + LSL(0,31) = Result shifted, least significant bit is in carry out + LSL 32 = Result of 0, Carry = Bit 0 of RM + LSL >32 = Result of 0, Carry out 0 + LSR 0 = LSR 32 (see below) + LSR 32 = Result of 0, Carry = Bit 31 of RM + LSR >32 = Result of 0, Carry out 0 + ASR >=32 = ENTIRE Result = bit 31 of RM + ROR 32 = Result = RM, Carry = Bit 31 of RM + ROR >32 = Same result as ROR n-32 until amount in range of 1-32 then follow rules +*/ + +static UINT32 decodeShift(UINT32 insn, UINT32 *pCarry) +{ + UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT; // Bits 11-7 + UINT32 rm = GET_REGISTER(insn & INSN_OP2_RM); + UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT; + + if ((insn & INSN_OP2_RM) == 0xf) { + rm += 8; + } + + /* All shift types ending in 1 are Rk, not #k */ + if (t & 1) + { +// LOG(("%08x: RegShift %02x %02x\n", R15, k >> 1, GET_REGISTER(k >> 1))); +#if ARM7_DEBUG_CORE + if ((insn & 0x80) == 0x80) + LOG(("%08x: RegShift ERROR (p36)\n", R15)); +#endif + + // see p35 for check on this + //k = GET_REGISTER(k >> 1) & 0x1f; + + // Keep only the bottom 8 bits for a Register Shift + k = GET_REGISTER(k >> 1) & 0xff; + + if (k == 0) /* Register shift by 0 is a no-op */ + { +// LOG(("%08x: NO-OP Regshift\n", R15)); + /* TODO this is wrong for at least ROR by reg with lower + * 5 bits 0 but lower 8 bits non zero */ + if (pCarry) + *pCarry = GET_CPSR & C_MASK; + return rm; + } + } + /* Decode the shift type and perform the shift */ + switch (t >> 1) + { + case 0: /* LSL */ + // LSL 32 = Result of 0, Carry = Bit 0 of RM + // LSL >32 = Result of 0, Carry out 0 + if (k >= 32) + { + if (pCarry) + *pCarry = (k == 32) ? rm & 1 : 0; + return 0; + } + else + { + if (pCarry) + { + // LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit + // LSL (0,31) = Result shifted, least significant bit is in carry out + *pCarry = k ? (rm & (1 << (32 - k))) : (GET_CPSR & C_MASK); + } + return k ? LSL(rm, k) : rm; + } + break; + + case 1: /* LSR */ + if (k == 0 || k == 32) + { + if (pCarry) + *pCarry = rm & SIGN_BIT; + return 0; + } + else if (k > 32) + { + if (pCarry) + *pCarry = 0; + return 0; + } + else + { + if (pCarry) + *pCarry = (rm & (1 << (k - 1))); + return LSR(rm, k); + } + break; + + case 2: /* ASR */ + if (k == 0 || k > 32) + k = 32; + + if (pCarry) + *pCarry = (rm & (1 << (k - 1))); + if (k >= 32) + return rm & SIGN_BIT ? 0xffffffffu : 0; + else + { + if (rm & SIGN_BIT) + return LSR(rm, k) | (0xffffffffu << (32 - k)); + else + return LSR(rm, k); + } + break; + + case 3: /* ROR and RRX */ + if (k) + { + while (k > 32) + k -= 32; + if (pCarry) + *pCarry = rm & (1 << (k - 1)); + return ROR(rm, k); + } + else + { + /* RRX */ + if (pCarry) + *pCarry = (rm & 1); + return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2); + } + break; + } + + LOG(("%08x: Decodeshift error\n", R15)); + return 0; +} /* decodeShift */ + + +static int loadInc(UINT32 pat, UINT32 rbv, UINT32 s) +{ + int i, result; + + result = 0; + rbv &= ~3; + for (i = 0; i < 16; i++) + { + if ((pat >> i) & 1) + { + if (i == 15) { + if (s) /* Pull full contents from stack */ + SET_REGISTER(15, READ32(rbv += 4)); + else /* Pull only address, preserve mode & status flags */ + SET_REGISTER(15, READ32(rbv += 4)); + } else + SET_REGISTER(i, READ32(rbv += 4)); + + result++; + } + } + return result; +} + +static int loadDec(UINT32 pat, UINT32 rbv, UINT32 s) +{ + int i, result; + + result = 0; + rbv &= ~3; + for (i = 15; i >= 0; i--) + { + if ((pat >> i) & 1) + { + if (i == 15) { + if (s) /* Pull full contents from stack */ + SET_REGISTER(15, READ32(rbv -= 4)); + else /* Pull only address, preserve mode & status flags */ + SET_REGISTER(15, READ32(rbv -= 4)); + } + else + SET_REGISTER(i, READ32(rbv -= 4)); + result++; + } + } + return result; +} + +static int storeInc(UINT32 pat, UINT32 rbv) +{ + int i, result; + + result = 0; + for (i = 0; i < 16; i++) + { + if ((pat >> i) & 1) + { +#if ARM7_DEBUG_CORE + if (i == 15) /* R15 is plus 12 from address of STM */ + LOG(("%08x: StoreInc on R15\n", R15)); +#endif + WRITE32(rbv += 4, GET_REGISTER(i)); + result++; + } + } + return result; +} /* storeInc */ + +static int storeDec(UINT32 pat, UINT32 rbv) +{ + int i, result; + + result = 0; + for (i = 15; i >= 0; i--) + { + if ((pat >> i) & 1) + { +#if ARM7_DEBUG_CORE + if (i == 15) /* R15 is plus 12 from address of STM */ + LOG(("%08x: StoreDec on R15\n", R15)); +#endif + WRITE32(rbv -= 4, GET_REGISTER(i)); + result++; + } + } + return result; +} /* storeDec */ + +/*************************************************************************** + * Main CPU Funcs + ***************************************************************************/ + +// CPU INIT +#if 0 +static void arm7_core_init(const char *cpuname, int index) +{ + state_save_register_item_array(cpuname, index, ARM7.sArmRegister); + state_save_register_item(cpuname, index, ARM7.pendingIrq); + state_save_register_item(cpuname, index, ARM7.pendingFiq); + state_save_register_item(cpuname, index, ARM7.pendingAbtD); + state_save_register_item(cpuname, index, ARM7.pendingAbtP); + state_save_register_item(cpuname, index, ARM7.pendingUnd); + state_save_register_item(cpuname, index, ARM7.pendingSwi); +} +#endif + +// CPU RESET +static void arm7_core_reset(void) +{ + int (*save_irqcallback)(int) = ARM7.irq_callback; + + memset(&ARM7, 0, sizeof(ARM7)); + ARM7.irq_callback = save_irqcallback; + + /* start up in SVC mode with interrupts disabled. */ + SwitchMode(eARM7_MODE_SVC); + SET_CPSR(GET_CPSR | I_MASK | F_MASK | 0x10); + R15 = 0; +// change_pc(R15); +} + +// Execute used to be here.. moved to separate file (arm7exec.c) to be included by cpu cores separately + +// CPU CHECK IRQ STATE +// Note: couldn't find any exact cycle counts for most of these exceptions +static void arm7_check_irq_state(void) +{ + UINT32 cpsr = GET_CPSR; /* save current CPSR */ + UINT32 pc = R15 + 4; /* save old pc (already incremented in pipeline) */; + + /* Exception priorities: + + Reset + Data abort + FIRQ + IRQ + Prefetch abort + Undefined instruction + Software Interrupt + */ + + // Data Abort + if (ARM7.pendingAbtD) { + SwitchMode(eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */ + SET_REGISTER(14, pc); /* save PC to R14 */ + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */ + SET_CPSR(GET_CPSR & ~T_MASK); + R15 = 0x10; /* IRQ Vector address */ +// change_pc(R15); + ARM7.pendingAbtD = 0; + return; + } + + // FIQ + if (ARM7.pendingFiq && (cpsr & F_MASK) == 0) { + SwitchMode(eARM7_MODE_FIQ); /* Set FIQ mode so PC is saved to correct R14 bank */ + SET_REGISTER(14, pc); /* save PC to R14 */ + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK | F_MASK); /* Mask both IRQ & FIQ */ + SET_CPSR(GET_CPSR & ~T_MASK); + R15 = 0x1c; /* IRQ Vector address */ + // change_pc(R15); + return; + } + + // IRQ + if (ARM7.pendingIrq && (cpsr & I_MASK) == 0) { + SwitchMode(eARM7_MODE_IRQ); /* Set IRQ mode so PC is saved to correct R14 bank */ + SET_REGISTER(14, pc); /* save PC to R14 */ + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */ + SET_CPSR(GET_CPSR & ~T_MASK); + R15 = 0x18; /* IRQ Vector address */ + // change_pc(R15); + return; + } + + // Prefetch Abort + if (ARM7.pendingAbtP) { + SwitchMode(eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */ + SET_REGISTER(14, pc); /* save PC to R14 */ + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */ + SET_CPSR(GET_CPSR & ~T_MASK); + R15 = 0x0c; /* IRQ Vector address */ + // change_pc(R15); + ARM7.pendingAbtP = 0; + return; + } + + // Undefined instruction + if (ARM7.pendingUnd) { + SwitchMode(eARM7_MODE_UND); /* Set UND mode so PC is saved to correct R14 bank */ + SET_REGISTER(14, pc); /* save PC to R14 */ + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */ + SET_CPSR(GET_CPSR & ~T_MASK); + R15 = 0x04; /* IRQ Vector address */ + // change_pc(R15); + ARM7.pendingUnd = 0; + return; + } + + // Software Interrupt + if (ARM7.pendingSwi) { + SwitchMode(eARM7_MODE_SVC); /* Set SVC mode so PC is saved to correct R14 bank */ + // compensate for prefetch (should this also be done for normal IRQ?) + if (T_IS_SET(GET_CPSR)) + { + SET_REGISTER(14, pc-2); /* save PC to R14 */ + } + else + { + SET_REGISTER(14, pc); /* save PC to R14 */ + } + SET_REGISTER(SPSR, cpsr); /* Save current CPSR */ + SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */ + SET_CPSR(GET_CPSR & ~T_MASK); /* Go to ARM mode */ + R15 = 0x08; /* Jump to the SWI vector */ + // change_pc(R15); + ARM7.pendingSwi = 0; + return; + } +} + +// CPU - SET IRQ LINE +static void arm7_core_set_irq_line(int irqline, int state) +{ + switch (irqline) { + + case ARM7_IRQ_LINE: /* IRQ */ + ARM7.pendingIrq = state & 1; + break; + + case ARM7_FIRQ_LINE: /* FIRQ */ + ARM7.pendingFiq = state & 1; + break; + + case ARM7_ABORT_EXCEPTION: + ARM7.pendingAbtD = state & 1; + break; + case ARM7_ABORT_PREFETCH_EXCEPTION: + ARM7.pendingAbtP = state & 1; + break; + + case ARM7_UNDEFINE_EXCEPTION: + ARM7.pendingUnd = state & 1; + break; + } + + ARM7_CHECKIRQ; +} + +/*************************************************************************** + * OPCODE HANDLING + ***************************************************************************/ + +// Co-Processor Data Operation +static void HandleCoProcDO(UINT32 insn) +{ + // This instruction simply instructs the co-processor to do something, no data is returned to ARM7 core + if (arm7_coproc_do_callback) + arm7_coproc_do_callback(0, insn); // iq_132?? // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation + else + LOG(("%08x: Co-Processor Data Operation executed, but no callback defined!\n", R15)); +} + +// Co-Processor Register Transfer - To/From Arm to Co-Proc +static void HandleCoProcRT(UINT32 insn) +{ + + /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */ + + // Load (MRC) data from Co-Proc to ARM7 register + if (insn & 0x00100000) // Bit 20 = Load or Store + { + if (arm7_coproc_rt_r_callback) + { + UINT32 res = arm7_coproc_rt_r_callback(insn); // RT Read handler must parse opcode & return appropriate result + SET_REGISTER((insn >> 12) & 0xf, res); + } + else + LOG(("%08x: Co-Processor Register Transfer executed, but no RT Read callback defined!\n", R15)); + } + // Store (MCR) data from ARM7 to Co-Proc register + else + { + if (arm7_coproc_rt_r_callback) + ; // arm7_coproc_rt_w_callback(insn, GET_REGISTER((insn >> 12) & 0xf), 0); // iq_132 + else + LOG(("%08x: Co-Processor Register Transfer executed, but no RT Write callback defined!\n", R15)); + } +} + +/* Data Transfer - To/From Arm to Co-Proc + Loading or Storing, the co-proc function is responsible to read/write from the base register supplied + offset + 8 bit immediate value Base Offset address is << 2 to get the actual # + + issues - #1 - the co-proc function, needs direct access to memory reads or writes (ie, so we must send a pointer to a func) + - #2 - the co-proc may adjust the base address (especially if it reads more than 1 word), so a pointer to the register must be used + but the old value of the register must be restored if write back is not set.. + - #3 - when post incrementing is used, it's up to the co-proc func. to add the offset, since the transfer + address supplied in that case, is simply the base. I suppose this is irrelevant if write back not set + but if co-proc reads multiple address, it must handle the offset adjustment itself. +*/ +// todo: test with valid instructions +static void HandleCoProcDT(UINT32 insn) +{ + UINT32 rn = (insn >> 16) & 0xf; + UINT32 rnv = GET_REGISTER(rn); // Get Address Value stored from Rn + UINT32 ornv = rnv; // Keep value of Rn + UINT32 off = (insn & 0xff) << 2; // Offset is << 2 according to manual + UINT32 *prn = &ARM7REG(rn); // Pointer to our register, so it can be changed in the callback + + // Pointers to read32/write32 functions + void (*write32)(UINT32 addr, UINT32 data); + UINT32 (*read32)(UINT32 addr); + write32 = PTR_WRITE32; + read32 = PTR_READ32; + +#if ARM7_DEBUG_CORE + if (((insn >> 16) & 0xf) == 15 && (insn & 0x200000)) + LOG(("%08x: Illegal use of R15 as base for write back value!\n", R15)); +#endif + + // Pre-Increment base address (IF POST INCREMENT - CALL BACK FUNCTION MUST DO IT) + if ((insn & 0x1000000) && off) + { + // Up - Down bit + if (insn & 0x800000) + rnv += off; + else + rnv -= off; + } + + // Load (LDC) data from ARM7 memory to Co-Proc memory + if (insn & 0x00100000) + { + if (arm7_coproc_dt_r_callback) + arm7_coproc_dt_r_callback(insn, prn, read32); + else + LOG(("%08x: Co-Processer Data Transfer executed, but no READ callback defined!\n", R15)); + } + // Store (STC) data from Co-Proc to ARM7 memory + else + { + if (arm7_coproc_dt_w_callback) + arm7_coproc_dt_w_callback(insn, prn, write32); + else + LOG(("%08x: Co-Processer Data Transfer executed, but no WRITE callback defined!\n", R15)); + } + + // If writeback not used - ensure the original value of RN is restored in case co-proc callback changed value + if ((insn & 0x200000) == 0) + SET_REGISTER(rn, ornv); +} + +static void HandleBranch(UINT32 insn) +{ + UINT32 off = (insn & INSN_BRANCH) << 2; + + /* Save PC into LR if this is a branch with link */ + if (insn & INSN_BL) + { + SET_REGISTER(14, R15 + 4); + } + + /* Sign-extend the 24-bit offset in our calculations */ + if (off & 0x2000000u) + { + R15 -= ((~(off | 0xfc000000u)) + 1) - 8; + } + else + { + R15 += off + 8; + } + +// change_pc(R15); +} + +static void HandleMemSingle(UINT32 insn) +{ + UINT32 rn, rnv, off, rd; + + /* Fetch the offset */ + if (insn & INSN_I) + { + /* Register Shift */ + off = decodeShift(insn, NULL); + } + else + { + /* Immediate Value */ + off = insn & INSN_SDT_IMM; + } + + /* Calculate Rn, accounting for PC */ + rn = (insn & INSN_RN) >> INSN_RN_SHIFT; + + if (insn & INSN_SDT_P) + { + /* Pre-indexed addressing */ + if (insn & INSN_SDT_U) + { + rnv = (GET_REGISTER(rn) + off); + } + else + { + rnv = (GET_REGISTER(rn) - off); + } + + if (insn & INSN_SDT_W) + { + SET_REGISTER(rn, rnv); + + // check writeback??? + } + else if (rn == eR15) + { + rnv = rnv + 8; + } + } + else + { + /* Post-indexed addressing */ + if (rn == eR15) + { + rnv = R15 + 8; + } + else + { + rnv = GET_REGISTER(rn); + } + } + + /* Do the transfer */ + rd = (insn & INSN_RD) >> INSN_RD_SHIFT; + if (insn & INSN_SDT_L) + { + /* Load */ + if (insn & INSN_SDT_B) + { + SET_REGISTER(rd, (UINT32)READ8(rnv)); + } + else + { + if (rd == eR15) + { + R15 = READ32(rnv); + R15 -= 4; + // change_pc(R15); + // LDR, PC takes 2S + 2N + 1I (5 total cycles) + ARM7_ICOUNT -= 2; + } + else + { + SET_REGISTER(rd, READ32(rnv)); + } + } + } + else + { + /* Store */ + if (insn & INSN_SDT_B) + { +#if ARM7_DEBUG_CORE + if (rd == eR15) + LOG(("Wrote R15 in byte mode\n")); +#endif + + WRITE8(rnv, (UINT8) GET_REGISTER(rd) & 0xffu); + } + else + { +#if ARM7_DEBUG_CORE + if (rd == eR15) + LOG(("Wrote R15 in 32bit mode\n")); +#endif + + //WRITE32(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(rd)); + WRITE32(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(rd)); // manual says STR rd = PC, +12 + } + // Store takes only 2 N Cycles, so add + 1 + ARM7_ICOUNT += 1; + } + + /* Do post-indexing writeback */ + if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/) + { + if (insn & INSN_SDT_U) + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd == rn) { + SET_REGISTER(rn, GET_REGISTER(rd)); + // todo: check for offs... ? + } + else { + + if ((insn & INSN_SDT_W) != 0) + LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + + SET_REGISTER(rn, (rnv + off)); + } + } + else + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd == rn) { + SET_REGISTER(rn, GET_REGISTER(rd)); + } + else { + SET_REGISTER(rn, (rnv - off)); + + if ((insn & INSN_SDT_W) != 0) + LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + } + } + } + +// ARM7_CHECKIRQ + +} /* HandleMemSingle */ + +static void HandleHalfWordDT(UINT32 insn) +{ + UINT32 rn, rnv, off, rd; + + // Immediate or Register Offset? + if (insn & 0x400000) { // Bit 22 - 1 = immediate, 0 = register + // imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3) + off = (((insn >> 8) & 0x0f) << 4) | (insn & 0x0f); + } + else { + // register + off = GET_REGISTER(insn & 0x0f); + } + + /* Calculate Rn, accounting for PC */ + rn = (insn & INSN_RN) >> INSN_RN_SHIFT; + + if (insn & INSN_SDT_P) + { + /* Pre-indexed addressing */ + if (insn & INSN_SDT_U) + { + rnv = (GET_REGISTER(rn) + off); + } + else + { + rnv = (GET_REGISTER(rn) - off); + } + + if (insn & INSN_SDT_W) + { + SET_REGISTER(rn, rnv); + + // check writeback??? + } + else if (rn == eR15) + { + rnv = (rnv) + 8; + } + } + else + { + /* Post-indexed addressing */ + if (rn == eR15) + { + rnv = R15 + 8; + } + else + { + rnv = GET_REGISTER(rn); + } + } + + /* Do the transfer */ + rd = (insn & INSN_RD) >> INSN_RD_SHIFT; + + /* Load */ + if (insn & INSN_SDT_L) + { + // Signed? + if (insn & 0x40) + { + UINT32 newval = 0; + + // Signed Half Word? + if (insn & 0x20) { + UINT16 signbyte, databyte; + databyte = READ16(rnv) & 0xFFFF; + signbyte = (databyte & 0x8000) ? 0xffff : 0; + newval = (UINT32)(signbyte << 16)|databyte; + } + // Signed Byte + else { + UINT8 databyte; + UINT32 signbyte; + databyte = READ8(rnv) & 0xff; + signbyte = (databyte & 0x80) ? 0xffffff : 0; + newval = (UINT32)(signbyte << 8)|databyte; + } + + // PC? + if (rd == eR15) + { + R15 = newval + 8; + // LDR(H,SH,SB) PC takes 2S + 2N + 1I (5 total cycles) + ARM7_ICOUNT -= 2; + + } + else + { + SET_REGISTER(rd, newval); + R15 += 4; + } + } + // Unsigned Half Word + else + { + if (rd == eR15) + { + R15 = READ16(rnv) + 8; + } + else + { + SET_REGISTER(rd, READ16(rnv)); + R15 += 4; + } + } + + + } + /* Store */ + else + { + // WRITE16(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(rd)); + WRITE16(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(rd)); // manual says STR RD=PC, +12 of address + if (rn != eR15) + R15 += 4; + // STRH takes 2 cycles, so we add + 1 + ARM7_ICOUNT += 1; + } + + + + // SJE: No idea if this writeback code works or makes sense here.. + + /* Do post-indexing writeback */ + if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/) + { + if (insn & INSN_SDT_U) + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd == rn) { + SET_REGISTER(rn, GET_REGISTER(rd)); + // todo: check for offs... ? + } + else { + + if ((insn & INSN_SDT_W) != 0) + LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + + SET_REGISTER(rn, (rnv + off)); + } + } + else + { + /* Writeback is applied in pipeline, before value is read from mem, + so writeback is effectively ignored */ + if (rd == rn) { + SET_REGISTER(rn, GET_REGISTER(rd)); + } + else { + SET_REGISTER(rn, (rnv - off)); + + if ((insn & INSN_SDT_W) != 0) + LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0)); + } + } + } + // change_pc(R15); +} + +static void HandleSwap(UINT32 insn) +{ + UINT32 rn, rm, rd, tmp; + + rn = GET_REGISTER((insn >> 16) & 0xf); // reg. w/read address + rm = GET_REGISTER(insn & 0xf); // reg. w/write address + rd = (insn >> 12) & 0xf; // dest reg + +#if ARM7_DEBUG_CORE + if (rn == 15 || rm == 15 || rd == 15) + LOG(("%08x: Illegal use of R15 in Swap Instruction\n", R15)); +#endif + + // can be byte or word + if (insn & 0x400000) + { + tmp = READ8(rn); + WRITE8(rn, rm); + SET_REGISTER(rd, tmp); + } + else + { + tmp = READ32(rn); + WRITE32(rn, rm); + SET_REGISTER(rd, tmp); + } + + R15 += 4; + // Instruction takes 1S+2N+1I cycles - so we subtract one more.. + ARM7_ICOUNT -= 1; +} + +static void HandlePSRTransfer(UINT32 insn) +{ + int reg = (insn & 0x400000) ? SPSR : eCPSR; // Either CPSR or SPSR + UINT32 newval, val = 0; + UINT32 oldmode = GET_CPSR & MODE_FLAG; + + // get old value of CPSR/SPSR + newval = GET_REGISTER(reg); + + // MSR (bit 21 set) - Copy value to CPSR/SPSR + if ((insn & 0x00200000)) + { + // Immediate Value? + if (insn & INSN_I) { + // Value can be specified for a Right Rotate, 2x the value specified. + int by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT; + if (by) + val = ROR(insn & INSN_OP2_IMM, by << 1); + else + val = insn & INSN_OP2_IMM; + } + // Value from Register + else + { + val = GET_REGISTER(insn & 0x0f); + } + + // apply field code bits + if (reg == eCPSR) + { + if (oldmode != eARM7_MODE_USER) + { + if (insn & 0x00010000) + { + newval = (newval & 0xffffff00) | (val & 0x000000ff); + } + if (insn & 0x00020000) + { + newval = (newval & 0xffff00ff) | (val & 0x0000ff00); + } + if (insn & 0x00040000) + { + newval = (newval & 0xff00ffff) | (val & 0x00ff0000); + } + } + + // status flags can be modified regardless of mode + if (insn & 0x00080000) + { + // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit) + newval = (newval & 0x00ffffff) | (val & 0xf8000000); + } + } + else // SPSR has stricter requirements + { + if (((GET_CPSR & 0x1f) > 0x10) && ((GET_CPSR & 0x1f) < 0x1f)) + { + if (insn & 0x00010000) + { + newval = (newval & 0xffffff00) | (val & 0xff); + } + if (insn & 0x00020000) + { + newval = (newval & 0xffff00ff) | (val & 0xff00); + } + if (insn & 0x00040000) + { + newval = (newval & 0xff00ffff) | (val & 0xff0000); + } + if (insn & 0x00080000) + { + // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit) + newval = (newval & 0x00ffffff) | (val & 0xf8000000); + } + } + } + + // force valid mode + newval |= 0x10; + + // Update the Register + SET_REGISTER(reg, newval); + + // Switch to new mode if changed + if ((newval & MODE_FLAG) != oldmode) + SwitchMode(GET_MODE); + + } + // MRS (bit 21 clear) - Copy CPSR or SPSR to specified Register + else + { + SET_REGISTER((insn >> 12)& 0x0f, GET_REGISTER(reg)); + } +} + +static void HandleALU(UINT32 insn) +{ + UINT32 op2, sc = 0, rd, rn, opcode; + UINT32 by, rdn; + // UINT32 oldR15 = R15; // iq_132 + + opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT; + + rd = 0; + rn = 0; + + /* --------------*/ + /* Construct Op2 */ + /* --------------*/ + + /* Immediate constant */ + if (insn & INSN_I) + { + by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT; + if (by) + { + op2 = ROR(insn & INSN_OP2_IMM, by << 1); + sc = op2 & SIGN_BIT; + } + else + { + op2 = insn & INSN_OP2; // SJE: Shouldn't this be INSN_OP2_IMM? + sc = GET_CPSR & C_MASK; + } + } + /* Op2 = Register Value */ + else + { + op2 = decodeShift(insn, (insn & INSN_S) ? &sc : NULL); + + // LD TODO sc will always be 0 if this applies + if (!(insn & INSN_S)) + sc = 0; + } + + // LD TODO this comment is wrong + /* Calculate Rn to account for pipelining */ + if ((opcode & 0xd) != 0xd) /* No Rn in MOV */ + { + if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15) + { +#if ARM7_DEBUG_CORE + LOG(("%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12))); +#endif + rn = R15 + 8; + } + else + { + rn = GET_REGISTER(rn); + } + } + + /* Perform the operation */ + + switch (opcode) + { + /* Arithmetic operations */ + case OPCODE_SBC: + rd = (rn - op2 - (GET_CPSR & C_MASK ? 0 : 1)); + HandleALUSubFlags(rd, rn, op2); + break; + case OPCODE_CMP: + case OPCODE_SUB: + rd = (rn - op2); + HandleALUSubFlags(rd, rn, op2); + break; + case OPCODE_RSC: + rd = (op2 - rn - (GET_CPSR & C_MASK ? 0 : 1)); + HandleALUSubFlags(rd, op2, rn); + break; + case OPCODE_RSB: + rd = (op2 - rn); + HandleALUSubFlags(rd, op2, rn); + break; + case OPCODE_ADC: + rd = (rn + op2 + ((GET_CPSR & C_MASK) >> C_BIT)); + HandleALUAddFlags(rd, rn, op2); + break; + case OPCODE_CMN: + case OPCODE_ADD: + rd = (rn + op2); + HandleALUAddFlags(rd, rn, op2); + break; + + /* Logical operations */ + case OPCODE_AND: + case OPCODE_TST: + rd = rn & op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_BIC: + rd = rn & ~op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_TEQ: + case OPCODE_EOR: + rd = rn ^ op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_ORR: + rd = rn | op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_MOV: + rd = op2; + HandleALULogicalFlags(rd, sc); + break; + case OPCODE_MVN: + rd = (~op2); + HandleALULogicalFlags(rd, sc); + break; + } + + /* Put the result in its register if not one of the test only opcodes (TST,TEQ,CMP,CMN) */ + rdn = (insn & INSN_RD) >> INSN_RD_SHIFT; + if ((opcode & 0xc) != 0x8) + { + // If Rd = R15, but S Flag not set, Result is placed in R15, but CPSR is not affected (page 44) + if (rdn == eR15 && !(insn & INSN_S)) + { + R15 = rd; + } + else + { + // Rd = 15 and S Flag IS set, Result is placed in R15, and current mode SPSR moved to CPSR + if (rdn == eR15) { + + // Update CPSR from SPSR + SET_CPSR(GET_REGISTER(SPSR)); + SwitchMode(GET_MODE); + + R15 = rd; + + /* IRQ masks may have changed in this instruction */ +// ARM7_CHECKIRQ; + } + else + /* S Flag is set - Write results to register & update CPSR (which was already handled using HandleALU flag macros) */ + SET_REGISTER(rdn, rd); + } + } + // SJE: Don't think this applies any more.. (see page 44 at bottom) + /* TST & TEQ can affect R15 (the condition code register) with the S bit set */ + else if (rdn == eR15) + { + if (insn & INSN_S) { +#if ARM7_DEBUG_CORE + LOG(("%08x: TST class on R15 s bit set\n", R15)); +#endif + R15 = rd; + + /* IRQ masks may have changed in this instruction */ +// ARM7_CHECKIRQ; + } + else + { +#if ARM7_DEBUG_CORE + LOG(("%08x: TST class on R15 no s bit set\n", R15)); +#endif + } + } + + // if (oldR15 != R15) +// change_pc(R15); +} + +static void HandleMul(UINT32 insn) +{ + UINT32 r; + + /* Do the basic multiply of Rm and Rs */ + r = GET_REGISTER(insn & INSN_MUL_RM) * + GET_REGISTER((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT); + +#if ARM7_DEBUG_CORE + if ((insn & INSN_MUL_RM) == 0xf || + ((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT) == 0xf || + ((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT) == 0xf) + LOG(("%08x: R15 used in mult\n", R15)); +#endif + + /* Add on Rn if this is a MLA */ + if (insn & INSN_MUL_A) + { + r += GET_REGISTER((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT); + } + + /* Write the result */ + SET_REGISTER((insn & INSN_MUL_RD) >> INSN_MUL_RD_SHIFT, r); + + /* Set N and Z if asked */ + if (insn & INSN_S) + { + SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleALUNZFlags(r)); + } +} + +// todo: add proper cycle counts +static void HandleSMulLong(UINT32 insn) +{ + INT32 rm, rs; + UINT32 rhi, rlo; + INT64 res = 0; + + rm = (INT32)GET_REGISTER(insn & 0xf); + rs = (INT32)GET_REGISTER(((insn >> 8) & 0xf)); + rhi = (insn >> 16) & 0xf; + rlo = (insn >> 12) & 0xf; + +#if ARM7_DEBUG_CORE + if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15) + LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15)); +#endif + + /* Perform the multiplication */ + res = (INT64)rm * rs; + + /* Add on Rn if this is a MLA */ + if (insn & INSN_MUL_A) + { + INT64 acum = (INT64)((((INT64)(GET_REGISTER(rhi))) << 32) | GET_REGISTER(rlo)); + res += acum; + } + + /* Write the result (upper dword goes to RHi, lower to RLo) */ + SET_REGISTER(rhi, res >> 32); + SET_REGISTER(rlo, res & 0xFFFFFFFF); + + /* Set N and Z if asked */ + if (insn & INSN_S) + { + SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res)); + } +} + +// todo: add proper cycle counts +static void HandleUMulLong(UINT32 insn) +{ + UINT32 rm, rs; + UINT32 rhi, rlo; + UINT64 res = 0; + + rm = (INT32)GET_REGISTER(insn & 0xf); + rs = (INT32)GET_REGISTER(((insn >> 8) & 0xf)); + rhi = (insn >> 16) & 0xf; + rlo = (insn >> 12) & 0xf; + +#if ARM7_DEBUG_CORE + if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15) + LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15)); +#endif + + /* Perform the multiplication */ + res = (UINT64)rm * rs; + + /* Add on Rn if this is a MLA */ + if (insn & INSN_MUL_A) + { + UINT64 acum = (UINT64)((((UINT64)(GET_REGISTER(rhi))) << 32) | GET_REGISTER(rlo)); + res += acum; + } + + /* Write the result (upper dword goes to RHi, lower to RLo) */ + SET_REGISTER(rhi, res >> 32); + SET_REGISTER(rlo, res & 0xFFFFFFFF); + + /* Set N and Z if asked */ + if (insn & INSN_S) + { + SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res)); + } +} + +static void HandleMemBlock(UINT32 insn) +{ + UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT; + UINT32 rbp = GET_REGISTER(rb); +// UINT32 oldR15 = R15; // iq_132 + int result; + +#if ARM7_DEBUG_CORE + if (rbp & 3) + LOG(("%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp)); +#endif + + // We will specify the cycle count for each case, so remove the -3 that occurs at the end + ARM7_ICOUNT += 3; + + if (insn & INSN_BDT_L) + { + /* Loading */ + if (insn & INSN_BDT_U) + { + /* Incrementing */ + if (!(insn & INSN_BDT_P)) + { + rbp = rbp + (- 4); + } + + // S Flag Set, but R15 not in list = User Bank Transfer + if (insn & INSN_BDT_S && (insn & 0x8000) == 0) + { + // set to user mode - then do the transfer, and set back + int curmode = GET_MODE; + SwitchMode(eARM7_MODE_USER); + LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + result = loadInc(insn & 0xffff, rbp, insn & INSN_BDT_S); + // todo - not sure if Writeback occurs on User registers also.. + SwitchMode(curmode); + } + else + result = loadInc(insn & 0xffff, rbp, insn & INSN_BDT_S); + + if (insn & INSN_BDT_W) + { +#if ARM7_DEBUG_CORE + if (rb == 15) + LOG(("%08x: Illegal LDRM writeback to r15\n", R15)); +#endif + SET_REGISTER(rb, GET_REGISTER(rb) + result * 4); + } + + // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!) + if (insn & 0x8000) { + R15 -= 4; // SJE: I forget why i did this? + // S - Flag Set? Signals transfer of current mode SPSR->CPSR + if (insn & INSN_BDT_S) { + SET_CPSR(GET_REGISTER(SPSR)); + SwitchMode(GET_MODE); + } + } + // LDM PC - takes 1 extra cycle + ARM7_ICOUNT -= 1; + } + else + { + /* Decrementing */ + if (!(insn & INSN_BDT_P)) + { + rbp = rbp - (- 4); + } + + // S Flag Set, but R15 not in list = User Bank Transfer + if (insn & INSN_BDT_S && ((insn & 0x8000) == 0)) + { + // set to user mode - then do the transfer, and set back + int curmode = GET_MODE; + SwitchMode(eARM7_MODE_USER); + LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + result = loadDec(insn & 0xffff, rbp, insn & INSN_BDT_S); + // todo - not sure if Writeback occurs on User registers also.. + SwitchMode(curmode); + } + else + result = loadDec(insn & 0xffff, rbp, insn & INSN_BDT_S); + + if (insn & INSN_BDT_W) + { + if (rb == 0xf) + LOG(("%08x: Illegal LDRM writeback to r15\n", R15)); + SET_REGISTER(rb, GET_REGISTER(rb)-result*4); + } + + // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!) + if (insn & 0x8000) { + R15 -= 4; // SJE: I forget why i did this? + // S - Flag Set? Signals transfer of current mode SPSR->CPSR + if (insn & INSN_BDT_S) { + SET_CPSR(GET_REGISTER(SPSR)); + SwitchMode(GET_MODE); + } + // LDM PC - takes 1 extra cycle + ARM7_ICOUNT -= 1; + } + + // LDM (NO PC) takes nS + 1n + 1I cycles (n = # of register transfers) + ARM7_ICOUNT -= result + 1 + 1; + } + } /* Loading */ + else + { + /* Storing */ + if (insn & (1 << eR15)) + { +#if ARM7_DEBUG_CORE + LOG(("%08x: Writing R15 in strm\n", R15)); +#endif + /* special case handling if writing to PC */ + R15 += 12; + } + if (insn & INSN_BDT_U) + { + /* Incrementing */ + if (!(insn & INSN_BDT_P)) + { + rbp = rbp + (- 4); + } + + // S Flag Set, but R15 not in list = User Bank Transfer + if (insn & INSN_BDT_S && (insn & 0x8000) == 0) + { + // todo: needs to be tested.. + + // set to user mode - then do the transfer, and set back + int curmode = GET_MODE; + SwitchMode(eARM7_MODE_USER); + LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + result = storeInc(insn & 0xffff, rbp); + // todo - not sure if Writeback occurs on User registers also.. + SwitchMode(curmode); + } + else + result = storeInc(insn & 0xffff, rbp); + + if (insn & INSN_BDT_W) + { + SET_REGISTER(rb, GET_REGISTER(rb) + result * 4); + } + } + else + { + /* Decrementing */ + if (!(insn & INSN_BDT_P)) + { + rbp = rbp - (-4); + } + + // S Flag Set, but R15 not in list = User Bank Transfer + if (insn & INSN_BDT_S && (insn & 0x8000) == 0) + { + // set to user mode - then do the transfer, and set back + int curmode = GET_MODE; + SwitchMode(eARM7_MODE_USER); + LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15)); + result = storeDec(insn & 0xffff, rbp); + // todo - not sure if Writeback occurs on User registers also.. + SwitchMode(curmode); + } + else + result = storeDec(insn & 0xffff, rbp); + + if (insn & INSN_BDT_W) + { + SET_REGISTER(rb, GET_REGISTER(rb) - result * 4); + } + } + if (insn & (1 << eR15)) + R15 -= 12; + + // STM takes (n+1)S+2N+1I cycles (n = # of register transfers) + ARM7_ICOUNT -= (result + 1) + 2 + 1; + } + + // if (oldR15 != R15) + // change_pc(R15); +} /* HandleMemBlock */ diff --git a/src/cpu/arm7/arm7core.h b/src/cpu/arm7/arm7core.h new file mode 100644 index 00000000..cda27450 --- /dev/null +++ b/src/cpu/arm7/arm7core.h @@ -0,0 +1,400 @@ +/***************************************************************************** + * + * arm7core.h + * Portable ARM7TDMI Core Emulator + * + * Copyright Steve Ellenoff, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * sellenoff@hotmail.com + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on: + * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' + * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) + * + ***************************************************************************** + + This file contains everything related to the arm7 core itself, and is presumed + to be cpu implementation non-specific, ie, applies to only the core. + + ******************************************************************************/ + +#ifndef __ARM7CORE_H__ +#define __ARM7CORE_H__ + + +/**************************************************************************************************** + * INTERRUPT LINES/EXCEPTIONS + ***************************************************************************************************/ +enum +{ + ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE, + ARM7_ABORT_EXCEPTION, ARM7_ABORT_PREFETCH_EXCEPTION, ARM7_UNDEFINE_EXCEPTION, + ARM7_NUM_LINES +}; +// Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify + +/**************************************************************************************************** + * ARM7 CORE REGISTERS + ***************************************************************************************************/ +enum +{ + ARM7_PC = 0, + ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7, + ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15, + ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14, + ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR, + ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR +}; + +#define ARM7CORE_REGS \ + UINT32 sArmRegister[kNumRegisters]; \ + UINT8 pendingIrq; \ + UINT8 pendingFiq; \ + UINT8 pendingAbtD; \ + UINT8 pendingAbtP; \ + UINT8 pendingUnd; \ + UINT8 pendingSwi; \ + int (*irq_callback)(int); + + +/**************************************************************************************************** + * VARIOUS INTERNAL STRUCS/DEFINES/ETC.. + ***************************************************************************************************/ +// Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes +enum +{ + eARM7_MODE_USER = 0x0, // Bit: 4-0 = 10000 + eARM7_MODE_FIQ = 0x1, // Bit: 4-0 = 10001 + eARM7_MODE_IRQ = 0x2, // Bit: 4-0 = 10010 + eARM7_MODE_SVC = 0x3, // Bit: 4-0 = 10011 + eARM7_MODE_ABT = 0x7, // Bit: 4-0 = 10111 + eARM7_MODE_UND = 0xb, // Bit: 4-0 = 11011 + eARM7_MODE_SYS = 0xf // Bit: 4-0 = 11111 +}; + +#define ARM7_NUM_MODES 0x10 + +/* There are 36 Unique - 32 bit processor registers */ +/* Each mode has 17 registers (except user & system, which have 16) */ +/* This is a list of each *unique* register */ +enum +{ + /* All modes have the following */ + eR0 = 0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13, /* Stack Pointer */ + eR14, /* Link Register (holds return address) */ + eR15, /* Program Counter */ + eCPSR, /* Current Status Program Register */ + + /* Fast Interrupt - Bank switched registers */ + eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ, eR13_FIQ, eR14_FIQ, eSPSR_FIQ, + + /* IRQ - Bank switched registers */ + eR13_IRQ, eR14_IRQ, eSPSR_IRQ, + + /* Supervisor/Service Mode - Bank switched registers */ + eR13_SVC, eR14_SVC, eSPSR_SVC, + + /* Abort Mode - Bank switched registers */ + eR13_ABT, eR14_ABT, eSPSR_ABT, + + /* Undefined Mode - Bank switched registers */ + eR13_UND, eR14_UND, eSPSR_UND, + + kNumRegisters +}; + +static const int thumbCycles[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 4 + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 7 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 9 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // a + 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, // b + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, // d + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // e + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // f +}; + +/* 17 processor registers are visible at any given time, + * banked depending on processor mode. + */ + +static const int sRegisterTable[ARM7_NUM_MODES][18] = +{ + { /* USR */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13, eR14, + eR15, eCPSR // No SPSR in this mode + }, + { /* FIQ */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ, + eR13_FIQ, eR14_FIQ, + eR15, eCPSR, eSPSR_FIQ + }, + { /* IRQ */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13_IRQ, eR14_IRQ, + eR15, eCPSR, eSPSR_IRQ + }, + { /* SVC */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13_SVC, eR14_SVC, + eR15, eCPSR, eSPSR_SVC + }, + {0}, {0}, {0}, // values for modes 4,5,6 are not valid + { /* ABT */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13_ABT, eR14_ABT, + eR15, eCPSR, eSPSR_ABT + }, + {0}, {0}, {0}, // values for modes 8,9,a are not valid! + { /* UND */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13_UND, eR14_UND, + eR15, eCPSR, eSPSR_UND + }, + {0}, {0}, {0}, // values for modes c,d, e are not valid! + { /* SYS */ + eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7, + eR8, eR9, eR10, eR11, eR12, + eR13, eR14, + eR15, eCPSR // No SPSR in this mode + } +}; + +#define N_BIT 31 +#define Z_BIT 30 +#define C_BIT 29 +#define V_BIT 28 +#define I_BIT 7 +#define F_BIT 6 +#define T_BIT 5 // Thumb mode + +#define N_MASK ((UINT32)(1 << N_BIT)) /* Negative flag */ +#define Z_MASK ((UINT32)(1 << Z_BIT)) /* Zero flag */ +#define C_MASK ((UINT32)(1 << C_BIT)) /* Carry flag */ +#define V_MASK ((UINT32)(1 << V_BIT)) /* oVerflow flag */ +#define I_MASK ((UINT32)(1 << I_BIT)) /* Interrupt request disable */ +#define F_MASK ((UINT32)(1 << F_BIT)) /* Fast interrupt request disable */ +#define T_MASK ((UINT32)(1 << T_BIT)) /* Thumb Mode flag */ + +#define N_IS_SET(pc) ((pc) & N_MASK) +#define Z_IS_SET(pc) ((pc) & Z_MASK) +#define C_IS_SET(pc) ((pc) & C_MASK) +#define V_IS_SET(pc) ((pc) & V_MASK) +#define I_IS_SET(pc) ((pc) & I_MASK) +#define F_IS_SET(pc) ((pc) & F_MASK) +#define T_IS_SET(pc) ((pc) & T_MASK) + +#define N_IS_CLEAR(pc) (!N_IS_SET(pc)) +#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc)) +#define C_IS_CLEAR(pc) (!C_IS_SET(pc)) +#define V_IS_CLEAR(pc) (!V_IS_SET(pc)) +#define I_IS_CLEAR(pc) (!I_IS_SET(pc)) +#define F_IS_CLEAR(pc) (!F_IS_SET(pc)) +#define T_IS_CLEAR(pc) (!T_IS_SET(pc)) + +/* Deconstructing an instruction */ +// todo: use these in all places (including dasm file) +#define INSN_COND ((UINT32)0xf0000000u) +#define INSN_SDT_L ((UINT32)0x00100000u) +#define INSN_SDT_W ((UINT32)0x00200000u) +#define INSN_SDT_B ((UINT32)0x00400000u) +#define INSN_SDT_U ((UINT32)0x00800000u) +#define INSN_SDT_P ((UINT32)0x01000000u) +#define INSN_BDT_L ((UINT32)0x00100000u) +#define INSN_BDT_W ((UINT32)0x00200000u) +#define INSN_BDT_S ((UINT32)0x00400000u) +#define INSN_BDT_U ((UINT32)0x00800000u) +#define INSN_BDT_P ((UINT32)0x01000000u) +#define INSN_BDT_REGS ((UINT32)0x0000ffffu) +#define INSN_SDT_IMM ((UINT32)0x00000fffu) +#define INSN_MUL_A ((UINT32)0x00200000u) +#define INSN_MUL_RM ((UINT32)0x0000000fu) +#define INSN_MUL_RS ((UINT32)0x00000f00u) +#define INSN_MUL_RN ((UINT32)0x0000f000u) +#define INSN_MUL_RD ((UINT32)0x000f0000u) +#define INSN_I ((UINT32)0x02000000u) +#define INSN_OPCODE ((UINT32)0x01e00000u) +#define INSN_S ((UINT32)0x00100000u) +#define INSN_BL ((UINT32)0x01000000u) +#define INSN_BRANCH ((UINT32)0x00ffffffu) +#define INSN_SWI ((UINT32)0x00ffffffu) +#define INSN_RN ((UINT32)0x000f0000u) +#define INSN_RD ((UINT32)0x0000f000u) +#define INSN_OP2 ((UINT32)0x00000fffu) +#define INSN_OP2_SHIFT ((UINT32)0x00000f80u) +#define INSN_OP2_SHIFT_TYPE ((UINT32)0x00000070u) +#define INSN_OP2_RM ((UINT32)0x0000000fu) +#define INSN_OP2_ROTATE ((UINT32)0x00000f00u) +#define INSN_OP2_IMM ((UINT32)0x000000ffu) +#define INSN_OP2_SHIFT_TYPE_SHIFT 4 +#define INSN_OP2_SHIFT_SHIFT 7 +#define INSN_OP2_ROTATE_SHIFT 8 +#define INSN_MUL_RS_SHIFT 8 +#define INSN_MUL_RN_SHIFT 12 +#define INSN_MUL_RD_SHIFT 16 +#define INSN_OPCODE_SHIFT 21 +#define INSN_RN_SHIFT 16 +#define INSN_RD_SHIFT 12 +#define INSN_COND_SHIFT 28 + +#define THUMB_INSN_TYPE ((UINT16)0xf000) +#define THUMB_COND_TYPE ((UINT16)0x0f00) +#define THUMB_GROUP4_TYPE ((UINT16)0x0c00) +#define THUMB_GROUP5_TYPE ((UINT16)0x0e00) +#define THUMB_GROUP5_RM ((UINT16)0x01c0) +#define THUMB_GROUP5_RN ((UINT16)0x0038) +#define THUMB_GROUP5_RD ((UINT16)0x0007) +#define THUMB_ADDSUB_RNIMM ((UINT16)0x01c0) +#define THUMB_ADDSUB_RS ((UINT16)0x0038) +#define THUMB_ADDSUB_RD ((UINT16)0x0007) +#define THUMB_INSN_ADDSUB ((UINT16)0x0800) +#define THUMB_INSN_CMP ((UINT16)0x0800) +#define THUMB_INSN_SUB ((UINT16)0x0800) +#define THUMB_INSN_IMM_RD ((UINT16)0x0700) +#define THUMB_INSN_IMM_S ((UINT16)0x0080) +#define THUMB_INSN_IMM ((UINT16)0x00ff) +#define THUMB_ADDSUB_TYPE ((UINT16)0x0600) +#define THUMB_HIREG_OP ((UINT16)0x0300) +#define THUMB_HIREG_H ((UINT16)0x00c0) +#define THUMB_HIREG_RS ((UINT16)0x0038) +#define THUMB_HIREG_RD ((UINT16)0x0007) +#define THUMB_STACKOP_TYPE ((UINT16)0x0f00) +#define THUMB_STACKOP_L ((UINT16)0x0800) +#define THUMB_STACKOP_RD ((UINT16)0x0700) +#define THUMB_ALUOP_TYPE ((UINT16)0x03c0) +#define THUMB_BLOP_LO ((UINT16)0x0800) +#define THUMB_BLOP_OFFS ((UINT16)0x07ff) +#define THUMB_SHIFT_R ((UINT16)0x0800) +#define THUMB_SHIFT_AMT ((UINT16)0x07c0) +#define THUMB_HALFOP_L ((UINT16)0x0800) +#define THUMB_HALFOP_OFFS ((UINT16)0x07c0) +#define THUMB_BRANCH_OFFS ((UINT16)0x07ff) +#define THUMB_LSOP_L ((UINT16)0x0800) +#define THUMB_LSOP_OFFS ((UINT16)0x07c0) +#define THUMB_MULTLS ((UINT16)0x0800) +#define THUMB_MULTLS_BASE ((UINT16)0x0700) +#define THUMB_RELADDR_SP ((UINT16)0x0800) +#define THUMB_RELADDR_RD ((UINT16)0x0700) +#define THUMB_INSN_TYPE_SHIFT 12 +#define THUMB_COND_TYPE_SHIFT 8 +#define THUMB_GROUP4_TYPE_SHIFT 10 +#define THUMB_GROUP5_TYPE_SHIFT 9 +#define THUMB_ADDSUB_TYPE_SHIFT 9 +#define THUMB_INSN_IMM_RD_SHIFT 8 +#define THUMB_STACKOP_TYPE_SHIFT 8 +#define THUMB_HIREG_OP_SHIFT 8 +#define THUMB_STACKOP_RD_SHIFT 8 +#define THUMB_MULTLS_BASE_SHIFT 8 +#define THUMB_RELADDR_RD_SHIFT 8 +#define THUMB_HIREG_H_SHIFT 6 +#define THUMB_HIREG_RS_SHIFT 3 +#define THUMB_ALUOP_TYPE_SHIFT 6 +#define THUMB_SHIFT_AMT_SHIFT 6 +#define THUMB_HALFOP_OFFS_SHIFT 6 +#define THUMB_LSOP_OFFS_SHIFT 6 +#define THUMB_GROUP5_RM_SHIFT 6 +#define THUMB_GROUP5_RN_SHIFT 3 +#define THUMB_GROUP5_RD_SHIFT 0 +#define THUMB_ADDSUB_RNIMM_SHIFT 6 +#define THUMB_ADDSUB_RS_SHIFT 3 +#define THUMB_ADDSUB_RD_SHIFT 0 + +enum +{ + OPCODE_AND, /* 0000 */ + OPCODE_EOR, /* 0001 */ + OPCODE_SUB, /* 0010 */ + OPCODE_RSB, /* 0011 */ + OPCODE_ADD, /* 0100 */ + OPCODE_ADC, /* 0101 */ + OPCODE_SBC, /* 0110 */ + OPCODE_RSC, /* 0111 */ + OPCODE_TST, /* 1000 */ + OPCODE_TEQ, /* 1001 */ + OPCODE_CMP, /* 1010 */ + OPCODE_CMN, /* 1011 */ + OPCODE_ORR, /* 1100 */ + OPCODE_MOV, /* 1101 */ + OPCODE_BIC, /* 1110 */ + OPCODE_MVN /* 1111 */ +}; + +enum +{ + COND_EQ = 0, /* Z equal */ + COND_NE, /* ~Z not equal */ + COND_CS, COND_HS = 2, /* C unsigned higher or same */ + COND_CC, COND_LO = 3, /* ~C unsigned lower */ + COND_MI, /* N negative */ + COND_PL, /* ~N positive or zero */ + COND_VS, /* V overflow */ + COND_VC, /* ~V no overflow */ + COND_HI, /* C && ~Z unsigned higher */ + COND_LS, /* ~C || Z unsigned lower or same */ + COND_GE, /* N == V greater or equal */ + COND_LT, /* N != V less than */ + COND_GT, /* ~Z && N == V greater than */ + COND_LE, /* Z || N != V less than or equal */ + COND_AL, /* 1 always */ + COND_NV /* 0 never */ +}; + +#define LSL(v, s) ((v) << (s)) +#define LSR(v, s) ((v) >> (s)) +#define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s)))) +#define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s)))) + +/* Convenience Macros */ +#define R15 ARM7REG(eR15) +#define SPSR 17 // SPSR is always the 18th register in our 0 based array sRegisterTable[][18] +#define GET_CPSR ARM7REG(eCPSR) +#define SET_CPSR(v) (GET_CPSR = (v)) +#define MODE_FLAG 0xF // Mode bits are 4:0 of CPSR, but we ignore bit 4. +#define GET_MODE (GET_CPSR & MODE_FLAG) +#define SIGN_BIT ((UINT32)(1 << 31)) +#define SIGN_BITS_DIFFER(a, b) (((a) ^ (b)) >> 31) +/* I really don't know why these were set to 16-bit, the thumb registers are still 32-bit ... */ +#define THUMB_SIGN_BIT ((UINT32)(1 << 31)) +#define THUMB_SIGN_BITS_DIFFER(a, b) (((a)^(b)) >> 31) + +/* At one point I thought these needed to be cpu implementation specific, but they don't.. */ +#define GET_REGISTER(reg) GetRegister(reg) +#define SET_REGISTER(reg, val) SetRegister(reg, val) +#define ARM7_CHECKIRQ arm7_check_irq_state() + +extern void((*arm7_coproc_do_callback)(unsigned int, unsigned int)); +extern unsigned int((*arm7_coproc_rt_r_callback)(unsigned int)); +extern void((*arm7_coproc_rt_w_callback)(unsigned int, unsigned int)); +extern void (*arm7_coproc_dt_r_callback)(UINT32 insn, UINT32* prn, UINT32 (*read32)(UINT32 addr)); +extern void (*arm7_coproc_dt_w_callback)(UINT32 insn, UINT32* prn, void (*write32)(UINT32 addr, UINT32 data)); + +#endif /* __ARM7CORE_H__ */ diff --git a/src/cpu/arm7/arm7exec.c b/src/cpu/arm7/arm7exec.c new file mode 100644 index 00000000..c17884d3 --- /dev/null +++ b/src/cpu/arm7/arm7exec.c @@ -0,0 +1,1366 @@ +/***************************************************************************** + * + * arm7exec.c + * Portable ARM7TDMI Core Emulator + * + * Copyright Steve Ellenoff, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * sellenoff@hotmail.com + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on: + * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' + * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) + * + *****************************************************************************/ + +/****************************************************************************** + * Notes: + * This file contains the code to run during the CPU EXECUTE METHOD. + * It has been split into it's own file (from the arm7core.c) so it can be + * directly compiled into any cpu core that wishes to use it. + * + * It should be included as follows in your cpu core: + * + * int arm7_execute(int cycles) + * { + * #include "arm7exec.c" + * } + * +*****************************************************************************/ + +/* This implementation uses an improved switch() for hopefully faster opcode fetches compared to my last version +.. though there's still room for improvement. */ +{ + UINT32 pc; + UINT32 insn; + + ARM7_ICOUNT = cycles; + curr_cycles = total_cycles; + + do + { + /* handle Thumb instructions if active */ + if (T_IS_SET(GET_CPSR)) + { + UINT32 readword; + UINT32 addr; + UINT32 rm, rn, rs, rd, op2, imm, rrs, rrd; + INT32 offs; + + pc = R15; + insn = cpu_readop16(pc & (~1)); + ARM7_ICOUNT -= (3 - thumbCycles[insn >> 8]); + switch ((insn & THUMB_INSN_TYPE) >> THUMB_INSN_TYPE_SHIFT) + { + case 0x0: /* Logical shifting */ + SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); + if (insn & THUMB_SHIFT_R) /* Shift right */ + { + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; + if (offs != 0) + { + SET_REGISTER(rd, rrs >> offs); + if (rrs & (1 << (offs - 1))) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else + { + SET_REGISTER(rd, 0); + if (rrs & 0x80000000) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + } + else /* Shift left */ + { + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; + if (offs != 0) + { + SET_REGISTER(rd, rrs << offs); + if (rrs & (1 << (31 - (offs - 1)))) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else + { + SET_REGISTER(rd, rrs); + } + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + } + break; + case 0x1: /* Arithmetic */ + if (insn & THUMB_INSN_ADDSUB) + { + switch ((insn & THUMB_ADDSUB_TYPE) >> THUMB_ADDSUB_TYPE_SHIFT) + { + case 0x0: /* ADD Rd, Rs, Rn */ + rn = GET_REGISTER((insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); + rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, rs + rn); + HandleThumbALUAddFlags(GET_REGISTER(rd), rs, rn); + break; + case 0x1: /* SUB Rd, Rs, Rn */ + rn = GET_REGISTER((insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT); + rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, rs - rn); + HandleThumbALUSubFlags(GET_REGISTER(rd), rs, rn); + break; + case 0x2: /* ADD Rd, Rs, #imm */ + imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; + rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, rs + imm); + HandleThumbALUAddFlags(GET_REGISTER(rd), rs, imm); + break; + case 0x3: /* SUB Rd, Rs, #imm */ + imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT; + rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT); + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, rs - imm); + HandleThumbALUSubFlags(GET_REGISTER(rd), rs,imm); + break; + default: + fatalerror("%08x: G1 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + } + else + { + /* ASR.. */ + //if (insn & THUMB_SHIFT_R) /* Shift right */ + { + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT; + if (offs == 0) + { + offs = 32; + } + if (offs >= 32) + { + if (rrs >> 31) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + SET_REGISTER(rd, (rrs & 0x80000000) ? 0xFFFFFFFF : 0x00000000); + } + else + { + if ((rrs >> (offs - 1)) & 1) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + SET_REGISTER(rd, + (rrs & 0x80000000) + ? ((0xFFFFFFFF << (32 - offs)) | (rrs >> offs)) + : (rrs >> offs)); + } + SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + } + } + break; + case 0x2: /* CMP / MOV */ + if (insn & THUMB_INSN_CMP) + { + rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); + op2 = insn & THUMB_INSN_IMM; + rd = rn - op2; + HandleThumbALUSubFlags(rd, rn, op2); + //mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0); + } + else + { + rd = (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT; + op2 = (insn & THUMB_INSN_IMM); + SET_REGISTER(rd, op2); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + } + break; + case 0x3: /* ADD/SUB immediate */ + if (insn & THUMB_INSN_SUB) /* SUB Rd, #Offset8 */ + { + rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); + op2 = insn & THUMB_INSN_IMM; + //mame_printf_debug("%08x: Thumb instruction: SUB R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2); + rd = rn - op2; + SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); + HandleThumbALUSubFlags(rd, rn, op2); + } + else /* ADD Rd, #Offset8 */ + { + rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT); + op2 = insn & THUMB_INSN_IMM; + rd = rn + op2; + //mame_printf_debug("%08x: Thumb instruction: ADD R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2); + SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd); + HandleThumbALUAddFlags(rd, rn, op2); + } + break; + case 0x4: /* Rd & Rm instructions */ + switch ((insn & THUMB_GROUP4_TYPE) >> THUMB_GROUP4_TYPE_SHIFT) + { + case 0x0: + switch ((insn & THUMB_ALUOP_TYPE) >> THUMB_ALUOP_TYPE_SHIFT) + { + case 0x0: /* AND Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, GET_REGISTER(rd) & GET_REGISTER(rs)); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x1: /* EOR Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, GET_REGISTER(rd) ^ GET_REGISTER(rs)); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x2: /* LSL Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + offs = GET_REGISTER(rs) & 0x000000ff; + if (offs > 0) + { + if (offs < 32) + { + SET_REGISTER(rd, rrd << offs); + if (rrd & (1 << (31 - (offs - 1)))) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else if (offs == 32) + { + SET_REGISTER(rd, 0); + if (rrd & 1) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else + { + SET_REGISTER(rd, 0); + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x3: /* LSR Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + offs = GET_REGISTER(rs) & 0x000000ff; + if (offs > 0) + { + if (offs < 32) + { + SET_REGISTER(rd, rrd >> offs); + if (rrd & (1 << (offs - 1))) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else if (offs == 32) + { + SET_REGISTER(rd, 0); + if (rrd & 0x80000000) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + else + { + SET_REGISTER(rd, 0); + SET_CPSR(GET_CPSR & ~C_MASK); + } + } + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x4: /* ASR Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs)&0xff; + rrd = GET_REGISTER(rd); + if (rrs != 0) + { + if (rrs >= 32) + { + if (rrd >> 31) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + SET_REGISTER(rd, (GET_REGISTER(rd) & 0x80000000) ? 0xFFFFFFFF : 0x00000000); + } + else + { + if ((rrd >> (rrs-1)) & 1) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + SET_REGISTER(rd, (rrd & 0x80000000) + ? ((0xFFFFFFFF << (32 - rrs)) | (rrd >> rrs)) + : (rrd >> rrs)); + } + } + SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x5: /* ADC Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + op2=(GET_CPSR & C_MASK) ? 1 : 0; + rn=GET_REGISTER(rd) + GET_REGISTER(rs) + op2; + HandleThumbALUAddFlags(rn, GET_REGISTER(rd), (GET_REGISTER(rs))); // ? + SET_REGISTER(rd, rn); + break; + case 0x6: /* SBC Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + op2=(GET_CPSR & C_MASK) ? 0 : 1; + rn=GET_REGISTER(rd) - GET_REGISTER(rs) - op2; + HandleThumbALUSubFlags(rn, GET_REGISTER(rd), (GET_REGISTER(rs))); //? + SET_REGISTER(rd, rn); + break; + case 0x7: /* ROR Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrd = GET_REGISTER(rd); + imm = GET_REGISTER(rs) & 0x0000001f; + SET_REGISTER(rd, (rrd >> imm) | (rrd << (32 - imm))); + if (rrd & (1 << (imm - 1))) + { + SET_CPSR(GET_CPSR | C_MASK); + } + else + { + SET_CPSR(GET_CPSR & ~C_MASK); + } + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0x8: /* TST Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd) & GET_REGISTER(rs))); + R15 += 2; + break; + case 0x9: /* NEG Rd, Rs - todo: check me */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rrs = GET_REGISTER(rs); + rn = 0 - rrs; + SET_REGISTER(rd, rn); + HandleThumbALUSubFlags(GET_REGISTER(rd), 0, rrs); + break; + case 0xa: /* CMP Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) - GET_REGISTER(rs); + HandleThumbALUSubFlags(rn, GET_REGISTER(rd), GET_REGISTER(rs)); + break; + case 0xb: /* CMN Rd, Rs - check flags, add dasm */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) + GET_REGISTER(rs); + HandleThumbALUAddFlags(rn, GET_REGISTER(rd), GET_REGISTER(rs)); + break; + case 0xc: /* ORR Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, GET_REGISTER(rd) | GET_REGISTER(rs)); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0xd: /* MUL Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + rn = GET_REGISTER(rd) * GET_REGISTER(rs); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_REGISTER(rd, rn); + SET_CPSR(GET_CPSR | HandleALUNZFlags(rn)); + R15 += 2; + break; + case 0xe: /* BIC Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, GET_REGISTER(rd) & (~GET_REGISTER(rs))); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + case 0xf: /* MVN Rd, Rs */ + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + op2 = GET_REGISTER(rs); + SET_REGISTER(rd, ~op2); + SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK)); + SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd))); + R15 += 2; + break; + default: + fatalerror("%08x: G4-0 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_ALUOP_TYPE) >> THUMB_ALUOP_TYPE_SHIFT); + R15 += 2; + break; + } + break; + case 0x1: + switch ((insn & THUMB_HIREG_OP) >> THUMB_HIREG_OP_SHIFT) + { + case 0x0: /* ADD Rd, Rs */ + rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT) + { + case 0x1: /* ADD Rd, HRs */ + SET_REGISTER(rd, GET_REGISTER(rd) + GET_REGISTER(rs+8)); + // emulate the effects of pre-fetch + if (rs == 7) + { + SET_REGISTER(rd, GET_REGISTER(rd) + 4); + } + break; + case 0x2: /* ADD HRd, Rs */ + SET_REGISTER(rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs)); + if (rd == 7) + { + R15 += 2; + // change_pc(R15); + } + break; + case 0x3: /* Add HRd, HRs */ + SET_REGISTER(rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs+8)); + // emulate the effects of pre-fetch + if (rs == 7) + { + SET_REGISTER(rd+8, GET_REGISTER(rd+8) + 4); + } + if (rd == 7) + { + R15 += 2; + // change_pc(R15); + } + break; + default: + fatalerror("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); + break; + } + R15 += 2; + break; + case 0x1: /* CMP */ + switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT) + { + case 0x0: /* CMP Rd, Rs */ + rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); + rd = GET_REGISTER(insn & THUMB_HIREG_RD); + rn = rd - rs; + HandleThumbALUSubFlags(rn, rd, rs); + break; + case 0x1: /* CMP Rd, Hs */ + rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); + rd = GET_REGISTER(insn & THUMB_HIREG_RD); + rn = rd - rs; + HandleThumbALUSubFlags(rn, rd, rs); + break; + case 0x2: /* CMP Hd, Rs */ + rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT)); + rd = GET_REGISTER((insn & THUMB_HIREG_RD) + 8); + rn = rd - rs; + HandleThumbALUSubFlags(rn, rd, rs); + break; + case 0x3: /* CMP Hd, Hs */ + rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); + rd = GET_REGISTER((insn & THUMB_HIREG_RD) + 8); + rn = rd - rs; + HandleThumbALUSubFlags(rn, rd, rs); + break; + default: + fatalerror("%08x: G4-1 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); + R15 += 2; + break; + } + break; + case 0x2: /* MOV */ + switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT) + { + case 0x1: // MOV Rd, Hs + rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + if (rs == 7) + { + SET_REGISTER(rd, GET_REGISTER(rs + 8) + 4); + } + else + { + SET_REGISTER(rd, GET_REGISTER(rs + 8)); + } + R15 += 2; + break; + case 0x2: // MOV Hd, Rs + rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + SET_REGISTER(rd + 8, GET_REGISTER(rs)); + if (rd != 7) + { + R15 += 2; + } + else + { + R15 &= ~1; + // change_pc(R15); + } + break; + case 0x3: // MOV Hd, Hs + rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; + rd = insn & THUMB_HIREG_RD; + if (rs == 7) + { + SET_REGISTER(rd + 8, GET_REGISTER(rs+8)+4); + } + else + { + SET_REGISTER(rd + 8, GET_REGISTER(rs+8)); + } + if (rd != 7) + { + R15 += 2; + } + if (rd == 7) + { + R15 &= ~1; + // change_pc(R15); + } + break; + default: + fatalerror("%08x: G4-2 Undefined Thumb instruction: %04x (%x)\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT); + R15 += 2; + break; + } + break; + case 0x3: + switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT) + { + case 0x0: + rd = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT; + addr = GET_REGISTER(rd); + if (addr & 1) + { + addr &= ~1; + } + else + { + SET_CPSR(GET_CPSR & ~T_MASK); + if (addr & 2) + { + addr += 2; + } + } + R15 = addr; + break; + case 0x1: + addr = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8); + if ((((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8) == 15) + { + addr += 2; + } + if (addr & 1) + { + addr &= ~1; + } + else + { + SET_CPSR(GET_CPSR & ~T_MASK); + if (addr & 2) + { + addr += 2; + } + } + R15 = addr; + break; + default: + fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + default: + fatalerror("%08x: G4-x Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x2: + case 0x3: + readword = READ32((R15 & ~2) + 4 + ((insn & THUMB_INSN_IMM) << 2)); + SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword); + R15 += 2; + break; + default: + fatalerror("%08x: G4-y Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x5: /* LDR* STR* */ + switch ((insn & THUMB_GROUP5_TYPE) >> THUMB_GROUP5_TYPE_SHIFT) + { + case 0x0: /* STR Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + WRITE32(addr, GET_REGISTER(rd)); + R15 += 2; + break; + case 0x1: /* STRH Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + WRITE16(addr, GET_REGISTER(rd)); + R15 += 2; + break; + case 0x2: /* STRB Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + WRITE8(addr, GET_REGISTER(rd)); + R15 += 2; + break; + case 0x3: /* LDSB Rd, [Rn, Rm] todo, add dasm */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = READ8(addr); + if (op2 & 0x00000080) + { + op2 |= 0xffffff00; + } + SET_REGISTER(rd, op2); + R15 += 2; + break; + case 0x4: /* LDR Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = READ32(addr); + SET_REGISTER(rd, op2); + R15 += 2; + break; + case 0x5: /* LDRH Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = READ16(addr); + SET_REGISTER(rd, op2); + R15 += 2; + break; + case 0x6: /* LDRB Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = READ8(addr); + SET_REGISTER(rd, op2); + R15 += 2; + break; + case 0x7: /* LDSH Rd, [Rn, Rm] */ + rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT; + rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT; + rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT; + addr = GET_REGISTER(rn) + GET_REGISTER(rm); + op2 = READ16(addr); + if (op2 & 0x00008000) + { + op2 |= 0xffff0000; + } + SET_REGISTER(rd, op2); + R15 += 2; + break; + default: + fatalerror("%08x: G5 Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0x6: /* Word Store w/ Immediate Offset */ + if (insn & THUMB_LSOP_L) /* Load */ + { + rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; + SET_REGISTER(rd, READ32(GET_REGISTER(rn) + offs)); // fix + R15 += 2; + } + else /* Store */ + { + rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2; + WRITE32(GET_REGISTER(rn) + offs, GET_REGISTER(rd)); + R15 += 2; + } + break; + case 0x7: /* Byte Store w/ Immeidate Offset */ + if (insn & THUMB_LSOP_L) /* Load */ + { + rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; + SET_REGISTER(rd, READ8(GET_REGISTER(rn) + offs)); + R15 += 2; + } + else /* Store */ + { + rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = insn & THUMB_ADDSUB_RD; + offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT; + WRITE8(GET_REGISTER(rn) + offs, GET_REGISTER(rd)); + R15 += 2; + } + break; + case 0x8: /* Load/Store Halfword */ + if (insn & THUMB_HALFOP_L) /* Load */ + { + imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + SET_REGISTER(rd, READ16(GET_REGISTER(rs) + (imm << 1))); + R15 += 2; + } + else /* Store */ + { + imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT; + rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT; + rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT; + WRITE16(GET_REGISTER(rs) + (imm << 1), GET_REGISTER(rd)); + R15 += 2; + } + break; + case 0x9: /* Stack-Relative Load/Store */ + if (insn & THUMB_STACKOP_L) + { + rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; + offs = (UINT8)(insn & THUMB_INSN_IMM); + readword = READ32(GET_REGISTER(13) + ((UINT32)offs << 2)); + SET_REGISTER(rd, readword); + R15 += 2; + } + else + { + rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT; + offs = (UINT8)(insn & THUMB_INSN_IMM); + WRITE32(GET_REGISTER(13) + ((UINT32)offs << 2), GET_REGISTER(rd)); + R15 += 2; + } + break; + case 0xa: /* Get relative address */ + if (insn & THUMB_RELADDR_SP) /* ADD Rd, SP, #nn */ + { + rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; + offs = (UINT8)(insn & THUMB_INSN_IMM) << 2; + SET_REGISTER(rd, GET_REGISTER(13) + offs); + R15 += 2; + } + else /* ADD Rd, PC, #nn */ + { + rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT; + offs = (UINT8)(insn & THUMB_INSN_IMM) << 2; + SET_REGISTER(rd, ((R15 + 4) & ~2) + offs); + R15 += 2; + } + break; + case 0xb: /* Stack-Related Opcodes */ + switch ((insn & THUMB_STACKOP_TYPE) >> THUMB_STACKOP_TYPE_SHIFT) + { + case 0x0: /* ADD SP, #imm */ + addr = (insn & THUMB_INSN_IMM); + addr &= ~THUMB_INSN_IMM_S; + SET_REGISTER(13, GET_REGISTER(13) + ((insn & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2))); + R15 += 2; + break; + case 0x4: /* PUSH {Rlist} */ + for (offs = 7; offs >= 0; offs--) + { + if (insn & (1 << offs)) + { + SET_REGISTER(13, GET_REGISTER(13) - 4); + WRITE32(GET_REGISTER(13), GET_REGISTER(offs)); + } + } + R15 += 2; + break; + case 0x5: /* PUSH {Rlist}{LR} */ + SET_REGISTER(13, GET_REGISTER(13) - 4); + WRITE32(GET_REGISTER(13), GET_REGISTER(14)); + for (offs = 7; offs >= 0; offs--) + { + if (insn & (1 << offs)) + { + SET_REGISTER(13, GET_REGISTER(13) - 4); + WRITE32(GET_REGISTER(13), GET_REGISTER(offs)); + } + } + R15 += 2; + break; + case 0xc: /* POP {Rlist} */ + for (offs = 0; offs < 8; offs++) + { + if (insn & (1 << offs)) + { + SET_REGISTER(offs, READ32(GET_REGISTER(13))); + SET_REGISTER(13, GET_REGISTER(13) + 4); + } + } + R15 += 2; + break; + case 0xd: /* POP {Rlist}{PC} */ + for (offs = 0; offs < 8; offs++) + { + if (insn & (1 << offs)) + { + SET_REGISTER(offs, READ32(GET_REGISTER(13))); + SET_REGISTER(13, GET_REGISTER(13) + 4); + } + } + R15 = READ32(GET_REGISTER(13)) & ~1; + SET_REGISTER(13, GET_REGISTER(13) + 4); + break; + default: + fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + break; + case 0xc: /* Multiple Load/Store */ + { + UINT32 ld_st_address; + + rd = (insn & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT; + ld_st_address = GET_REGISTER(rd) & 0xfffffffc; + + if (insn & THUMB_MULTLS) /* Load */ + { + int rd_in_list; + + rd_in_list = insn & (1 << rd); + for (offs = 0; offs < 8; offs++) + { + if (insn & (1 << offs)) + { + SET_REGISTER(offs, READ32(ld_st_address)); + ld_st_address += 4; + } + } + if (!rd_in_list) + SET_REGISTER(rd, ld_st_address); + R15 += 2; + } + else /* Store */ + { + for (offs = 0; offs < 8; offs++) + { + if (insn & (1 << offs)) + { + WRITE32(ld_st_address, GET_REGISTER(offs)); + ld_st_address += 4; + } + } + SET_REGISTER(rd, ld_st_address); + R15 += 2; + } + } + break; + case 0xd: /* Conditional Branch */ + offs = (INT8)(insn & THUMB_INSN_IMM); + switch ((insn & THUMB_COND_TYPE) >> THUMB_COND_TYPE_SHIFT) + { + case COND_EQ: + if (Z_IS_SET(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_NE: + if (Z_IS_CLEAR(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_CS: + if (C_IS_SET(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_CC: + if (C_IS_CLEAR(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_MI: + if (N_IS_SET(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_PL: + if (N_IS_CLEAR(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_VS: + if (V_IS_SET(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_VC: + if (V_IS_CLEAR(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_HI: + if (C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LS: + if (C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_GE: + if (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LT: + if (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_GT: + if (Z_IS_CLEAR(GET_CPSR) && !(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_LE: + if (Z_IS_SET(GET_CPSR) || !(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) + { + R15 += 4 + (offs << 1); + } + else + { + R15 += 2; + } + break; + case COND_AL: + fatalerror("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, insn); + R15 += 2; + break; + case COND_NV: // SWI (this is sort of a "hole" in the opcode encoding) + ARM7.pendingSwi = 1; + ARM7_CHECKIRQ; + break; + } + break; + case 0xe: /* B #offs */ + if (insn & THUMB_BLOP_LO) + { + addr = GET_REGISTER(14); + addr += (insn & THUMB_BLOP_OFFS) << 1; + addr &= 0xfffffffc; + SET_REGISTER(14, (R15 + 4) | 1); + R15 = addr; + } + else + { + offs = (insn & THUMB_BRANCH_OFFS) << 1; + if (offs & 0x00000800) + { + offs |= 0xfffff800; + } + R15 += 4 + offs; + } + break; + case 0xf: /* BL */ + if (insn & THUMB_BLOP_LO) + { + addr = GET_REGISTER(14); + addr += (insn & THUMB_BLOP_OFFS) << 1; + SET_REGISTER(14, (R15 + 2) | 1); + R15 = addr; + //R15 += 2; + } + else + { + addr = (insn & THUMB_BLOP_OFFS) << 12; + if (addr & (1 << 22)) + { + addr |= 0xff800000; + } + addr += R15 + 4; + SET_REGISTER(14, addr); + R15 += 2; + } + break; + default: + fatalerror("%08x: Undefined Thumb instruction: %04x\n", pc, insn); + R15 += 2; + break; + } + } + else + { + + /* load 32 bit instruction */ + pc = R15; + insn = cpu_readop32(pc); + + /* process condition codes for this instruction */ + switch (insn >> INSN_COND_SHIFT) + { + case COND_EQ: + if (Z_IS_CLEAR(GET_CPSR)) + goto L_Next; + break; + case COND_NE: + if (Z_IS_SET(GET_CPSR)) + goto L_Next; + break; + case COND_CS: + if (C_IS_CLEAR(GET_CPSR)) + goto L_Next; + break; + case COND_CC: + if (C_IS_SET(GET_CPSR)) + goto L_Next; + break; + case COND_MI: + if (N_IS_CLEAR(GET_CPSR)) + goto L_Next; + break; + case COND_PL: + if (N_IS_SET(GET_CPSR)) + goto L_Next; + break; + case COND_VS: + if (V_IS_CLEAR(GET_CPSR)) + goto L_Next; + break; + case COND_VC: + if (V_IS_SET(GET_CPSR)) + goto L_Next; + break; + case COND_HI: + if (C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR)) + goto L_Next; + break; + case COND_LS: + if (C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR)) + goto L_Next; + break; + case COND_GE: + if (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) /* Use x ^ (x >> ...) method */ + goto L_Next; + break; + case COND_LT: + if (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)) + goto L_Next; + break; + case COND_GT: + if (Z_IS_SET(GET_CPSR) || (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK))) + goto L_Next; + break; + case COND_LE: + if (Z_IS_CLEAR(GET_CPSR) && (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK))) + goto L_Next; + break; + case COND_NV: + goto L_Next; + } + /*******************************************************************/ + /* If we got here - condition satisfied, so decode the instruction */ + /*******************************************************************/ + switch ((insn & 0xF000000) >> 24) + { + case 0: + case 1: + case 2: + case 3: + /* Branch and Exchange (BX) */ + if ((insn & 0x0ffffff0) == 0x012fff10) // bits 27-4 == 000100101111111111110001 + { + R15 = GET_REGISTER(insn & 0x0f); + // If new PC address has A0 set, switch to Thumb mode + if (R15 & 1) { + SET_CPSR(GET_CPSR|T_MASK); + R15--; + } + } + else + /* Multiply OR Swap OR Half Word Data Transfer */ + if ((insn & 0x0e000000) == 0 && (insn & 0x80) && (insn & 0x10)) // bits 27-25=000 bit 7=1 bit 4=1 + { + /* Half Word Data Transfer */ + if (insn & 0x60) // bits = 6-5 != 00 + { + HandleHalfWordDT(insn); + } + else + /* Swap */ + if (insn & 0x01000000) // bit 24 = 1 + { + HandleSwap(insn); + } + /* Multiply Or Multiply Long */ + else + { + /* multiply long */ + if (insn & 0x800000) // Bit 23 = 1 for Multiply Long + { + /* Signed? */ + if (insn & 0x00400000) + HandleSMulLong(insn); + else + HandleUMulLong(insn); + } + /* multiply */ + else + { + HandleMul(insn); + } + R15 += 4; + } + } + else + /* Data Processing OR PSR Transfer */ + if ((insn & 0x0c000000) == 0) // bits 27-26 == 00 - This check can only exist properly after Multiplication check above + { + /* PSR Transfer (MRS & MSR) */ + if (((insn & 0x00100000) == 0) && ((insn & 0x01800000) == 0x01000000)) // S bit must be clear, and bit 24,23 = 10 + { + HandlePSRTransfer(insn); + ARM7_ICOUNT += 2; // PSR only takes 1 - S Cycle, so we add + 2, since at end, we -3.. + R15 += 4; + } + /* Data Processing */ + else + { + HandleALU(insn); + } + } + break; + /* Data Transfer - Single Data Access */ + case 4: + case 5: + case 6: + case 7: + HandleMemSingle(insn); + R15 += 4; + break; + /* Block Data Transfer/Access */ + case 8: + case 9: + HandleMemBlock(insn); + R15 += 4; + break; + /* Branch or Branch & Link */ + case 0xa: + case 0xb: + HandleBranch(insn); + break; + /* Co-Processor Data Transfer */ + case 0xc: + case 0xd: + HandleCoProcDT(insn); + R15 += 4; + break; + /* Co-Processor Data Operation or Register Transfer */ + case 0xe: + if (insn & 0x10) + HandleCoProcRT(insn); + else + HandleCoProcDO(insn); + R15 += 4; + break; + /* Software Interrupt */ + case 0x0f: + ARM7.pendingSwi = 1; + ARM7_CHECKIRQ; + //couldn't find any cycle counts for SWI + break; + /* Undefined */ + default: + ARM7.pendingSwi = 1; + ARM7_CHECKIRQ; + ARM7_ICOUNT -= 1; //undefined takes 4 cycles (page 77) + LOG(("%08x: Undefined instruction\n",pc-4)); + L_Next: + R15 += 4; + ARM7_ICOUNT +=2; //Any unexecuted instruction only takes 1 cycle (page 193) + } + } + + ARM7_CHECKIRQ; + + /* All instructions remove 3 cycles.. Others taking less / more will have adjusted this # prior to here */ + ARM7_ICOUNT -= 3; + total_cycles = curr_cycles + cycles - ARM7_ICOUNT; + } while (ARM7_ICOUNT > 0); + + return cycles - ARM7_ICOUNT; +} diff --git a/src/cpu/arm7_intf.cpp b/src/cpu/arm7_intf.cpp new file mode 100644 index 00000000..c812d80d --- /dev/null +++ b/src/cpu/arm7_intf.cpp @@ -0,0 +1,275 @@ +#include "burnint.h" +#include "arm7_intf.h" + +//#define DEBUG_LOG + +#define MAX_MEMORY 0x80000000 // more than good enough for pgm +#define PAGE_SIZE 0x00001000 // 400 would be better... +#define PAGE_COUNT (MAX_MEMORY/PAGE_SIZE) +#define PAGE_SHIFT 12 // 0x1000 -> 12 bits +#define PAGE_BYTE_AND 0x00fff // 0x1000 - 1 (byte align) +#define PAGE_WORD_AND 0x00ffe // 0x1000 - 2 (word align) +#define PAGE_LONG_AND 0x00ffc // 0x1000 - 4 (ignore last 4 bytes, long align) + +#define READ 0 +#define WRITE 1 +#define FETCH 2 + +static UINT8 **membase[3]; // 0 read, 1, write, 2 opcode + +static void (*pWriteLongHandler)(UINT32, UINT32) = NULL; +static void (*pWriteWordHandler)(UINT32, UINT16) = NULL; +static void (*pWriteByteHandler)(UINT32, UINT8 ) = NULL; + +static UINT16 (*pReadWordHandler)(UINT32) = NULL; +static UINT32 (*pReadLongHandler)(UINT32) = NULL; +static UINT8 (*pReadByteHandler)(UINT32) = NULL; + +static UINT32 Arm7IdleLoop = ~0; + +void Arm7Init( INT32 num ) // only one cpu supported +{ + for (INT32 i = 0; i < 3; i++) { + membase[i] = (UINT8**)malloc(PAGE_COUNT * sizeof(UINT8*)); + } + + CpuCheatRegister(0x000a, num); +} + +void Arm7Exit() // only one cpu supported +{ + for (INT32 i = 0; i < 3; i++) { + if (membase[i]) { + free (membase[i]); + membase[i] = NULL; + } + } + + Arm7IdleLoop = ~0; +} + +void Arm7MapMemory(UINT8 *src, INT32 start, INT32 finish, INT32 type) +{ + UINT32 len = (finish-start) >> PAGE_SHIFT; + + for (UINT32 i = 0; i < len+1; i++) + { + UINT32 offset = i + (start >> PAGE_SHIFT); + if (type & (1 << READ)) membase[ READ][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << WRITE)) membase[WRITE][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << FETCH)) membase[FETCH][offset] = src + (i << PAGE_SHIFT); + } +} + +void Arm7SetWriteByteHandler(void (*write)(UINT32, UINT8)) +{ + pWriteByteHandler = write; +} + +void Arm7SetWriteWordHandler(void (*write)(UINT32, UINT16)) +{ + pWriteWordHandler = write; +} + +void Arm7SetWriteLongHandler(void (*write)(UINT32, UINT32)) +{ + pWriteLongHandler = write; +} + +void Arm7SetReadByteHandler(UINT8 (*read)(UINT32)) +{ + pReadByteHandler = read; +} + +void Arm7SetReadWordHandler(UINT16 (*read)(UINT32)) +{ + pReadWordHandler = read; +} + +void Arm7SetReadLongHandler(UINT32 (*read)(UINT32)) +{ + pReadLongHandler = read; +} + +void Arm7_program_write_byte_32le(UINT32 addr, UINT8 data) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, %2.2x wb\n"), addr, data); +#endif + + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + membase[WRITE][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + return; + } + + if (pWriteByteHandler) { + pWriteByteHandler(addr, data); + } +} + +void Arm7_program_write_word_32le(UINT32 addr, UINT16 data) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, %8.8x wd\n"), addr, data); +#endif + + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + *((UINT16*)(membase[WRITE][addr >> PAGE_SHIFT] + (addr & PAGE_WORD_AND))) = data; + return; + } + + if (pWriteWordHandler) { + pWriteWordHandler(addr, data); + } +} + +void Arm7_program_write_dword_32le(UINT32 addr, UINT32 data) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, %8.8x wd\n"), addr, data); +#endif + + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + *((UINT32*)(membase[WRITE][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))) = data; + return; + } + + if (pWriteLongHandler) { + pWriteLongHandler(addr, data); + } +} + + +UINT8 Arm7_program_read_byte_32le(UINT32 addr) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rb\n"), addr); +#endif + + if (membase[ READ][addr >> PAGE_SHIFT] != NULL) { + return membase[READ][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND]; + } + + if (pReadByteHandler) { + return pReadByteHandler(addr); + } + + return 0; +} + +UINT16 Arm7_program_read_word_32le(UINT32 addr) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rl\n"), addr); +#endif + + if (membase[ READ][addr >> PAGE_SHIFT] != NULL) { + return *((UINT16*)(membase[ READ][addr >> PAGE_SHIFT] + (addr & PAGE_WORD_AND))); + } + + if (pReadWordHandler) { + return pReadWordHandler(addr); + } + + return 0; +} + +UINT32 Arm7_program_read_dword_32le(UINT32 addr) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rl\n"), addr); +#endif + + if (membase[ READ][addr >> PAGE_SHIFT] != NULL) { + return *((UINT32*)(membase[ READ][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))); + } + + if (pReadLongHandler) { + return pReadLongHandler(addr); + } + + return 0; +} + +UINT16 Arm7_program_opcode_word_32le(UINT32 addr) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rwo\n"), addr); +#endif + + // speed hack -- skip idle loop... + if (addr == Arm7IdleLoop) { + Arm7RunEnd(); + } + + if (membase[FETCH][addr >> PAGE_SHIFT] != NULL) { + return *((UINT16*)(membase[FETCH][addr >> PAGE_SHIFT] + (addr & PAGE_WORD_AND))); + } + + // good enough for now... + if (pReadWordHandler) { + return pReadWordHandler(addr); + } + + return 0; +} + +UINT32 Arm7_program_opcode_dword_32le(UINT32 addr) +{ +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rlo\n"), addr); +#endif + + // speed hack - skip idle loop... + if (addr == Arm7IdleLoop) { + Arm7RunEnd(); + } + + if (membase[FETCH][addr >> PAGE_SHIFT] != NULL) { + return *((UINT32*)(membase[FETCH][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))); + } + + // good enough for now... + if (pReadLongHandler) { + return pReadLongHandler(addr); + } + + return 0; +} + +void Arm7SetIRQLine(INT32 line, INT32 state) +{ + if (state == ARM7_CLEAR_LINE || state == ARM7_ASSERT_LINE) { + arm7_set_irq_line(line, state); + } + else if (ARM7_HOLD_LINE) { + arm7_set_irq_line(line, ARM7_ASSERT_LINE); + Arm7Run(0); + arm7_set_irq_line(line, ARM7_CLEAR_LINE); + } +} + +// Set address of idle loop start - speed hack +void Arm7SetIdleLoopAddress(UINT32 address) +{ + Arm7IdleLoop = address; +} + + +// For cheats/etc + +void Arm7_write_rom_byte(UINT32 addr, UINT8 data) +{ + // write to rom & ram + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + membase[WRITE][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + } + + if (membase[READ][addr >> PAGE_SHIFT] != NULL) { + membase[READ][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + } + + if (pWriteByteHandler) { + pWriteByteHandler(addr, data); + } +} diff --git a/src/cpu/arm7_intf.h b/src/cpu/arm7_intf.h new file mode 100644 index 00000000..060d055e --- /dev/null +++ b/src/cpu/arm7_intf.h @@ -0,0 +1,60 @@ + +// use these in arm.cpp +void Arm7_program_write_byte_32le(UINT32 addr, UINT8 data); +void Arm7_program_write_word_32le(UINT32 addr, UINT16 data); +void Arm7_program_write_dword_32le(UINT32 addr, UINT32 data); +UINT8 Arm7_program_read_byte_32le(UINT32 addr); +UINT16 Arm7_program_read_word_32le(UINT32 addr); +UINT32 Arm7_program_read_dword_32le(UINT32 addr); +UINT16 Arm7_program_opcode_word_32le(UINT32 addr); +UINT32 Arm7_program_opcode_dword_32le(UINT32 addr); + +void arm7_set_irq_line(INT32 irqline, INT32 state); + +// use these everywhere else +#define ARM7_READ 1 +#define ARM7_WRITE 2 +#define ARM7_FETCH 4 + +#define ARM7_ROM (ARM7_READ | ARM7_FETCH) +#define ARM7_RAM (ARM7_READ | ARM7_FETCH | ARM7_WRITE) + +void Arm7MapMemory(UINT8 *src, INT32 start, INT32 finish, INT32 type); + +void Arm7SetWriteByteHandler(void (*write)(UINT32, UINT8)); +void Arm7SetWriteWordHandler(void (*write)(UINT32, UINT16)); +void Arm7SetWriteLongHandler(void (*write)(UINT32, UINT32)); +void Arm7SetReadByteHandler(UINT8 (*read)(UINT32)); +void Arm7SetReadWordHandler(UINT16 (*read)(UINT32)); +void Arm7SetReadLongHandler(UINT32 (*read)(UINT32)); + +INT32 Arm7Scan(INT32 nAction); + +void Arm7RunEnd(); +void Arm7BurnCycles(INT32 cycles); +INT32 Arm7TotalCycles(); +void Arm7NewFrame(); + +void Arm7Init(INT32); +void Arm7Open(INT32 ); +void Arm7Reset(); +INT32 Arm7Run(INT32 cycles); + +// defined in arm7core.h +#define ARM7_IRQ_LINE 0 +#define ARM7_FIRQ_LINE 1 + +#define ARM7_CLEAR_LINE 0 +#define ARM7_ASSERT_LINE 1 +#define ARM7_HOLD_LINE 2 + +void Arm7SetIRQLine(INT32 line, INT32 state); + +void Arm7Exit(); +void Arm7Close(); + +// speed hack stuff +void Arm7SetIdleLoopAddress(UINT32 address); + +// for cheat handling +void Arm7_write_rom_byte(UINT32 addr, UINT8 data); diff --git a/src/cpu/arm_intf.cpp b/src/cpu/arm_intf.cpp new file mode 100644 index 00000000..952c3772 --- /dev/null +++ b/src/cpu/arm_intf.cpp @@ -0,0 +1,248 @@ +#include "burnint.h" +#include "arm_intf.h" + +//#define DEBUG_LOG + +#define MAX_MEMORY 0x04000000 // max +#define MAX_MASK 0x03ffffff // max-1 +#define PAGE_SIZE 0x00001000 // 400 would be better... +#define PAGE_COUNT (MAX_MEMORY/PAGE_SIZE) +#define PAGE_SHIFT 12 // 0x1000 -> 12 bits +#define PAGE_BYTE_AND 0x00fff // 0x1000 - 1 (byte align) +#define PAGE_LONG_AND 0x00ffc // 0x1000 - 4 (ignore last 4 bytes, long align) + +#define READ 0 +#define WRITE 1 +#define FETCH 2 + +static UINT8 **membase[3]; // 0 read, 1, write, 2 opcode + +static void (*pWriteLongHandler)(UINT32, UINT32 ) = NULL; +static void (*pWriteByteHandler)(UINT32, UINT8 ) = NULL; + +static UINT32 (*pReadLongHandler)(UINT32) = NULL; +static UINT8 (*pReadByteHandler)(UINT32) = NULL; + +UINT32 ArmSpeedHackAddress; +static void (*pArmSpeedHackCallback)(); + +void ArmSetSpeedHack(UINT32 address, void (*pCallback)()) +{ + ArmSpeedHackAddress = address; + + pArmSpeedHackCallback = pCallback; +} + +void ArmOpen(INT32) +{ + +} + +void ArmClose() +{ + +} + +void ArmInit(INT32 num ) // only one cpu supported +{ + for (INT32 i = 0; i < 3; i++) { + membase[i] = (UINT8**)malloc(PAGE_COUNT * sizeof(UINT8**)); + memset (membase[i], 0, PAGE_COUNT * sizeof(UINT8**)); + } + + pWriteLongHandler = NULL; + pWriteByteHandler = NULL; + pReadLongHandler = NULL; + pReadByteHandler = NULL; + + CpuCheatRegister(0x0b, num); + + pArmSpeedHackCallback = NULL; + ArmSpeedHackAddress = ~0; +} + +void ArmExit() +{ + for (INT32 i = 0; i < 3; i++) { + if (membase[i]) { + free (membase[i]); + membase[i] = NULL; + } + } +} + +void ArmMapMemory(UINT8 *src, INT32 start, INT32 finish, INT32 type) +{ + UINT32 len = (finish-start) >> PAGE_SHIFT; + + for (UINT32 i = 0; i < len+1; i++) + { + UINT32 offset = i + (start >> PAGE_SHIFT); + if (type & (1 << READ)) membase[ READ][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << WRITE)) membase[WRITE][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << FETCH)) membase[FETCH][offset] = src + (i << PAGE_SHIFT); + } +} + +void ArmSetWriteByteHandler(void (*write)(UINT32, UINT8)) +{ + pWriteByteHandler = write; +} + +void ArmSetWriteLongHandler(void (*write)(UINT32, UINT32)) +{ + pWriteLongHandler = write; +} + +void ArmSetReadByteHandler(UINT8 (*read)(UINT32)) +{ + pReadByteHandler = read; +} + +void ArmSetReadLongHandler(UINT32 (*read)(UINT32)) +{ + pReadLongHandler = read; +} + +void Arm_program_write_byte_32le(UINT32 addr, UINT8 data) +{ + addr &= MAX_MASK; + +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, %2.2x wb\n"), addr, data); +#endif + + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + membase[WRITE][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + return; + } + + if (pWriteByteHandler) { + pWriteByteHandler(addr, data); + } +} + +void Arm_program_write_dword_32le(UINT32 addr, UINT32 data) +{ + addr &= MAX_MASK; + +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, %8.8x wd\n"), addr, data); +#endif + + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + *((UINT32*)(membase[WRITE][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))) = data; + return; + } + + if (pWriteLongHandler) { + pWriteLongHandler(addr, data); + } +} + + +UINT8 Arm_program_read_byte_32le(UINT32 addr) +{ + addr &= MAX_MASK; + +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rb\n"), addr); +#endif + + if (membase[ READ][addr >> PAGE_SHIFT] != NULL) { + return membase[READ][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND]; + } + + if (pReadByteHandler) { + return pReadByteHandler(addr); + } + + return 0; +} + +UINT32 Arm_program_read_dword_32le(UINT32 addr) +{ + addr &= MAX_MASK; + +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rl\n"), addr); +#endif + + if (membase[ READ][addr >> PAGE_SHIFT] != NULL) { + return *((UINT32*)(membase[ READ][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))); + } + + if (pReadLongHandler) { + return pReadLongHandler(addr); + } + + return 0; +} + +UINT32 Arm_program_opcode_dword_32le(UINT32 addr) +{ + addr &= MAX_MASK; + +#ifdef DEBUG_LOG + bprintf (PRINT_NORMAL, _T("%5.5x, rlo\n"), addr); +#endif + +#if 1 + if (ArmSpeedHackAddress == addr) { +// bprintf (0, _T("speed hack activated! %d cycles killed!\n"), ArmRemainingCycles()); + if (pArmSpeedHackCallback) { + pArmSpeedHackCallback(); + } else { + ArmRunEnd(); + } + } +#else + if (ArmSpeedHackAddress) { + bprintf (0, _T("%x, %d\n"), ArmGetPc(), ArmRemainingCycles()); + ArmRunEnd(); + } +#endif + + if (membase[FETCH][addr >> PAGE_SHIFT] != NULL) { + return *((UINT32*)(membase[FETCH][addr >> PAGE_SHIFT] + (addr & PAGE_LONG_AND))); + } + + // good enough for now... + if (pReadLongHandler) { + return pReadLongHandler(addr); + } + + return 0; +} + +void ArmSetIRQLine(INT32 line, INT32 state) +{ + if (state == ARM_CLEAR_LINE || state == ARM_ASSERT_LINE) { + arm_set_irq_line(line, state); + } + else if (ARM_HOLD_LINE) { + arm_set_irq_line(line, ARM_ASSERT_LINE); + ArmRun(0); + arm_set_irq_line(line, ARM_CLEAR_LINE); + } +} + +// For cheats/etc + +void Arm_write_rom_byte(UINT32 addr, UINT8 data) +{ + addr &= MAX_MASK; + + // write to rom & ram + if (membase[WRITE][addr >> PAGE_SHIFT] != NULL) { + membase[WRITE][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + } + + if (membase[READ][addr >> PAGE_SHIFT] != NULL) { + membase[READ][addr >> PAGE_SHIFT][addr & PAGE_BYTE_AND] = data; + } + + if (pWriteByteHandler) { + pWriteByteHandler(addr, data); + } +} diff --git a/src/cpu/arm_intf.h b/src/cpu/arm_intf.h new file mode 100644 index 00000000..67555ae0 --- /dev/null +++ b/src/cpu/arm_intf.h @@ -0,0 +1,90 @@ +// use these in arm.cpp +void Arm_program_write_byte_32le(UINT32 addr, UINT8 data); +void Arm_program_write_dword_32le(UINT32 addr, UINT32 data); +UINT8 Arm_program_read_byte_32le(UINT32 addr); +UINT32 Arm_program_read_dword_32le(UINT32 addr); +UINT32 Arm_program_opcode_dword_32le(UINT32 addr); + +void arm_set_irq_line(INT32 irqline, INT32 state); + +// use these everywhere else +#define ARM_READ 1 +#define ARM_WRITE 2 +#define ARM_FETCH 4 + +#define ARM_ROM (ARM_READ | ARM_FETCH) +#define ARM_RAM (ARM_READ | ARM_FETCH | ARM_WRITE) + +void ArmMapMemory(UINT8 *src, INT32 start, INT32 finish, INT32 type); + +void ArmSetWriteByteHandler(void (*write)(UINT32, UINT8)); +void ArmSetWriteLongHandler(void (*write)(UINT32, UINT32)); +void ArmSetReadByteHandler(UINT8 (*read)(UINT32)); +void ArmSetReadLongHandler(UINT32 (*read)(UINT32)); + +void ArmInit(INT32); +void ArmOpen(INT32); +void ArmReset(); +INT32 ArmRun(INT32 cycles); +INT32 ArmScan(INT32 nAction, INT32 *); + +#define ARM_IRQ_LINE 0 +#define ARM_FIRQ_LINE 1 + +#define ARM_CLEAR_LINE 0 +#define ARM_ASSERT_LINE 1 +#define ARM_HOLD_LINE 2 + +void ArmSetIRQLine(INT32 line, INT32 state); + +void ArmExit(); +void ArmClose(); + +extern UINT32 ArmSpeedHackAddress; +void ArmIdleCycles(INT32 cycles); +void ArmSetSpeedHack(UINT32 address, void (*pCallback)()); + +UINT32 ArmGetPc(); + +UINT32 ArmRemainingCycles(); +UINT32 ArmGetTotalCycles(); +void ArmRunEnd(); +void ArmNewFrame(); + +// for cheat handling +void Arm_write_rom_byte(UINT32 addr, UINT8 data); + + + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Macros for reading/writing to 16-bit RAM regions + +#define Write16Long(ram, a, b) \ + if (address >= a && address <= b) { \ + *((UINT16*)(ram + (((address - a) & ~3)/2))) = data; \ + return; \ + } + +#define Write16Byte(ram, a, b) \ + if (address >= a && address <= b) { \ + if (~address & 2) { \ + INT32 offset = address - a; \ + ram[(offset & 1) | ((offset & ~3) / 2)] = data; \ + } \ + return; \ + } + +#define Read16Long(ram, a, b) \ + if (address >= a && address <= b) { \ + return *((UINT16*)(ram + (((address - a) & ~3)/2))) | ~0xffff; \ + } + +#define Read16Byte(ram, a, b) \ + if (address >= a && address <= b) { \ + if (~address & 2) { \ + INT32 offset = address - a; \ + return ram[(offset & 1) | ((offset & ~3) / 2)]; \ + } else { \ + return 0xff; \ + } \ + } diff --git a/src/cpu/h6280/h6280.cpp b/src/cpu/h6280/h6280.cpp new file mode 100644 index 00000000..1e89e8c7 --- /dev/null +++ b/src/cpu/h6280/h6280.cpp @@ -0,0 +1,602 @@ +/***************************************************************************** + + h6280.c - Portable HuC6280 emulator + + Copyright Bryan McPhail, mish@tendril.co.uk + + This source code is based (with permission!) on the 6502 emulator by + Juergen Buchmueller. It is released as part of the Mame emulator project. + Let me know if you intend to use this code in any other project. + + + NOTICE: + + This code is around 99% complete! Several things are unimplemented, + some due to lack of time, some due to lack of documentation, mainly + due to lack of programs using these features. + + csh, csl opcodes are not supported. + + I am unsure if flag B is set upon execution of rti. + + Cycle counts should be quite accurate. + + + Changelog, version 1.02: + JMP + indirect X (0x7c) opcode fixed. + SMB + RMB opcodes fixed in disassembler. + change_pc function calls removed. + TSB & TRB now set flags properly. + BIT opcode altered. + + Changelog, version 1.03: + Swapped IRQ mask for IRQ1 & IRQ2 (thanks Yasuhiro) + + Changelog, version 1.04, 28/9/99-22/10/99: + Adjusted RTI (thanks Karl) + TST opcodes fixed in disassembler (missing break statements in a case!). + TST behaviour fixed. + SMB/RMB/BBS/BBR fixed in disassembler. + + Changelog, version 1.05, 8/12/99-16/12/99: + Added CAB's timer implementation (note: irq ack & timer reload are changed). + Fixed STA IDX. + Fixed B flag setting on BRK. + Assumed CSH & CSL to take 2 cycles each. + + Todo: Performance could be improved by precalculating timer fire position. + + Changelog, version 1.06, 4/5/00 - last opcode bug found? + JMP indirect was doing a EAL++; instead of EAD++; - Obviously causing + a corrupt read when L = 0xff! This fixes Bloody Wolf and Trio The Punch! + + Changelog, version 1.07, 3/9/00: + Changed timer to be single shot - fixes Crude Buster music in level 1. + + Changelog, version 1.08, 8/11/05: (Charles MacDonald) + + Changed timer implementation, no longer single shot and reading the + timer registers returns the count only. Fixes the following: + - Mesopotamia: Music tempo & in-game timer + - Dragon Saber: DDA effects + - Magical Chase: Music tempo and speed regulation + - Cadash: Allows the first level to start + - Turrican: Allows the game to start + + Changed PLX and PLY to set NZ flags. Fixes: + - Afterburner: Graphics unpacking + - Aoi Blink: Collision detection with background + + Fixed the decimal version of ADC/SBC to *not* update the V flag, + only the binary ones do. + + Fixed B flag handling so it is always set outside of an interrupt; + even after being set by PLP and RTI. + + Fixed P state after reset to set I and B, leaving T, D cleared and + NVZC randomized (cleared in this case). + + Fixed interrupt processing order (Timer has highest priority followed + by IRQ1 and finally IRQ2). + + Changelog, version 1.09, 1/07/06: (Rob Bohms) + + Added emulation of the T flag, fixes PCE Ankuku Densetsu title screen + + Changelog, version 1.10, 5/09/07: (Wilbert Pol) + + - Taking of interrupts is delayed to respect a pending instruction already + in the instruction pipeline; fixes After Burner. + - Added 1 cycle for decimal mode ADC and SBC instructions. + - Changed cycle counts for CSH and CSL instructions to 3. + - Added T flag support to the SBC instruction. + - Fixed ADC T flag to set the Z flag based on the value read. + - Added 3 cycle penalty to ADC, AND, EOR, ORA, and SBC instructions + when the T flag is set. + - Fixed cycle count and support for 65536 byte blocks for the TAI, TDD, + TIA, TII, and TIN instructions. + - Fixed RDWORD macro in the disassembler. + - Fixed setting of N and V flags in the TST instructions. + - Removed unneeded debug_mmr code. + - Fixed TSB and TRB instructions. + - Added 1 delay when accessing the VDC or VCE areas. + - Implemented low and high speed cpu modes. + + Changelog, version 1.11, 18/09/07: (Wilbert Pol) + + - Improvements to the handling of taking of delayed interrupts. + +******************************************************************************/ +//#include "debugger.h" +//#include "deprecat.h" +#include "burnint.h" +#include "h6280.h" +#include "h6280_intf.h" +//#include "driver.h" + +#define offs_t unsigned int +#define change_pc(x) PCW = (x) + +#define CLEAR_LINE 0 +#define ASSERT_LINE 1 +#define INPUT_LINE_NMI 0x20 + +#define H6280_INLINE static + +static int h6280_ICount = 0; +static unsigned int h6280_totalcycles = 0; + +/**************************************************************************** + * The 6280 registers. + ****************************************************************************/ +typedef struct +{ + PAIR ppc; /* previous program counter */ + PAIR pc; /* program counter */ + PAIR sp; /* stack pointer (always 100 - 1FF) */ + PAIR zp; /* zero page address */ + PAIR ea; /* effective address */ + UINT8 a; /* Accumulator */ + UINT8 x; /* X index register */ + UINT8 y; /* Y index register */ + UINT8 p; /* Processor status */ + UINT8 mmr[8]; /* Hu6280 memory mapper registers */ + UINT8 irq_mask; /* interrupt enable/disable */ + UINT8 timer_status; /* timer status */ + UINT8 timer_ack; /* timer acknowledge */ + UINT8 clocks_per_cycle; /* 4 = low speed mode, 1 = high speed mode */ + INT32 timer_value; /* timer interrupt */ + INT32 timer_load; /* reload value */ + UINT8 nmi_state; + UINT8 irq_state[3]; + UINT8 irq_pending; + int (*irq_callback)(int irqline); + +#if LAZY_FLAGS + INT32 NZ; /* last value (lazy N and Z flag) */ +#endif + UINT8 io_buffer; /* last value written to the PSG, timer, and interrupt pages */ +} h6280_Regs; + +static h6280_Regs h6280; + +//static void set_irq_line(int irqline, int state); +#define set_irq_line h6280_set_irq_line + +/* include the macros */ +#include "h6280ops.h" + +/* include the opcode macros, functions and function pointer tables */ +#include "tblh6280.c" + +#if 0 +/*****************************************************************************/ +static void h6280_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + state_save_register_item("h6280", index, h6280.ppc.w.l); + state_save_register_item("h6280", index, h6280.pc.w.l); + state_save_register_item("h6280", index, h6280.sp.w.l); + state_save_register_item("h6280", index, h6280.zp.w.l); + state_save_register_item("h6280", index, h6280.ea.w.l); + state_save_register_item("h6280", index, h6280.a); + state_save_register_item("h6280", index, h6280.x); + state_save_register_item("h6280", index, h6280.y); + state_save_register_item("h6280", index, h6280.p); + state_save_register_item_array("h6280", index, h6280.mmr); + state_save_register_item("h6280", index, h6280.irq_mask); + state_save_register_item("h6280", index, h6280.timer_status); + state_save_register_item("h6280", index, h6280.timer_ack); + state_save_register_item("h6280", index, h6280.clocks_per_cycle); + state_save_register_item("h6280", index, h6280.timer_value); + state_save_register_item("h6280", index, h6280.timer_load); + state_save_register_item("h6280", index, h6280.nmi_state); + state_save_register_item("h6280", index, h6280.irq_state[0]); + state_save_register_item("h6280", index, h6280.irq_state[1]); + state_save_register_item("h6280", index, h6280.irq_state[2]); + state_save_register_item("h6280", index, h6280.irq_pending); + + #if LAZY_FLAGS + state_save_register_item("h6280", index, h6280.NZ); + #endif + state_save_register_item("h6280", index, h6280.io_buffer); + + h6280.irq_callback = irqcallback; +} +#endif + +void h6280Reset(void) +{ + int (*save_irqcallback)(int); + int i; + + /* wipe out the h6280 structure */ + save_irqcallback = h6280.irq_callback; + memset(&h6280, 0, sizeof(h6280_Regs)); + h6280.irq_callback = save_irqcallback; + + /* set I and B flags */ + P = _fI | _fB; + + /* stack starts at 0x01ff */ + h6280.sp.d = 0x1ff; + + /* read the reset vector into PC */ + PCL = RDMEM(H6280_RESET_VEC); + PCH = RDMEM((H6280_RESET_VEC+1)); + CHANGE_PC; + + /* CPU starts in low speed mode */ + h6280.clocks_per_cycle = 4; + + /* timer off by default */ + h6280.timer_status=0; + h6280.timer_load = 128 * 1024; + + /* clear pending interrupts */ + for (i = 0; i < 3; i++) + h6280.irq_state[i] = CLEAR_LINE; + h6280.nmi_state = CLEAR_LINE; + + h6280.irq_pending = 0; + + h6280_totalcycles = 0; +} + +#if 0 +static void h6280_exit(void) +{ + /* nothing */ +} +#endif + +int h6280Run(int cycles) +{ + int in; + h6280_ICount = cycles; + + if ( h6280.irq_pending == 2 ) { + h6280.irq_pending--; + } + + /* Execute instructions */ + do + { + if ((h6280.ppc.w.l ^ h6280.pc.w.l) & 0xe000) + CHANGE_PC; + h6280.ppc = h6280.pc; + +// debugger_instruction_hook(Machine, PCW); + + /* Execute 1 instruction */ + in=RDOP(); + PCW++; + insnh6280[in](); + + if ( h6280.irq_pending ) { + if ( h6280.irq_pending == 1 ) { + if ( !(P & _fI) ) { + h6280.irq_pending--; + CHECK_AND_TAKE_IRQ_LINES; + } + } else { + h6280.irq_pending--; + } + } + + /* Check internal timer */ + if(h6280.timer_status) + { + if(h6280.timer_value<=0) + { + if ( ! h6280.irq_pending ) + h6280.irq_pending = 1; + while( h6280.timer_value <= 0 ) + h6280.timer_value += h6280.timer_load; + set_irq_line(2,ASSERT_LINE); + } + } + } while (h6280_ICount > 0); + + h6280_totalcycles += cycles - h6280_ICount; + + return cycles - h6280_ICount; +} + +//static void h6280_get_context (void *dst) +//{ +// if( dst ) +// *(h6280_Regs*)dst = h6280; +//} + +//static void h6280_set_context (void *src) +//{ +// if( src ) +// h6280 = *(h6280_Regs*)src; +// CHANGE_PC; +//} + +int h6280TotalCycles() +{ + return h6280_totalcycles; +} + +void h6280NewFrame() +{ + h6280_totalcycles = 0; +} + +void h6280RunEnd() +{ + h6280_ICount = 0; +} + +/*****************************************************************************/ + +void h6280_set_irq_line(int irqline, int state) +{ + if (irqline == INPUT_LINE_NMI) + { + if ( state != ASSERT_LINE ) return; + h6280.nmi_state = state; + CHECK_IRQ_LINES; + } + else if (irqline < 3) + { + /* If the state has not changed, just return */ + if ( h6280.irq_state[irqline] == state ) + return; + + h6280.irq_state[irqline] = state; + + CHECK_IRQ_LINES; + } +} + + + +/*****************************************************************************/ + +unsigned char h6280_irq_status_r(unsigned int offset) +{ + int status; + + switch (offset&3) + { + default:return h6280.io_buffer;break; + case 3: + { + status=0; + if(h6280.irq_state[1]!=CLEAR_LINE) status|=1; /* IRQ 2 */ + if(h6280.irq_state[0]!=CLEAR_LINE) status|=2; /* IRQ 1 */ + if(h6280.irq_state[2]!=CLEAR_LINE) status|=4; /* TIMER */ + return status|(h6280.io_buffer&(~H6280_IRQ_MASK)); + } + case 2: return h6280.irq_mask|(h6280.io_buffer&(~H6280_IRQ_MASK));break; + } +} + +void h6280_irq_status_w(unsigned int offset, unsigned char data) +{ + h6280.io_buffer=data; + switch (offset&3) + { + default:h6280.io_buffer=data;break; + case 2: /* Write irq mask */ + h6280.irq_mask=data&0x7; + CHECK_IRQ_LINES; + break; + + case 3: /* Timer irq ack */ + set_irq_line(2,CLEAR_LINE); + break; + } +} + +unsigned char h6280_timer_r(unsigned int) +{ + /* only returns countdown */ + return ((h6280.timer_value/1024)&0x7F)|(h6280.io_buffer&0x80); +} + +void h6280_timer_w(unsigned int offset, unsigned char data) +{ + h6280.io_buffer=data; + switch (offset) { + case 0: /* Counter preload */ + h6280.timer_load=h6280.timer_value=((data&127)+1)*1024; + return; + + case 1: /* Counter enable */ + if(data&1) + { /* stop -> start causes reload */ + if(h6280.timer_status==0) h6280.timer_value=h6280.timer_load; + } + h6280.timer_status=data&1; + return; + } +} + +#if 0 +static int h6280_translate(int space, int intention, offs_t *addr) +{ +#if 0 + if (space == ADDRESS_SPACE_PROGRAM) + *addr = TRANSLATED(*addr); + return TRUE; +#else + if (space == 0) + *addr = TRANSLATED(*addr); + return 1; +#endif +} +#endif + +UINT8 h6280io_get_buffer() +{ + return h6280.io_buffer; +} +void h6280io_set_buffer(UINT8 data) +{ + h6280.io_buffer=data; +} + +#if 0 +/*****************************************************************************/ + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void h6280_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; + case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break; + case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:set_irq_line(INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + H6280_PC: PCW = info->i; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + H6280_S: S = info->i; break; + case CPUINFO_INT_REGISTER + H6280_P: P = info->i; break; + case CPUINFO_INT_REGISTER + H6280_A: A = info->i; break; + case CPUINFO_INT_REGISTER + H6280_X: X = info->i; break; + case CPUINFO_INT_REGISTER + H6280_Y: Y = info->i; break; + case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: h6280.irq_mask = info->i; CHECK_IRQ_LINES; break; + case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: h6280.timer_status = info->i; break; + case CPUINFO_INT_REGISTER + H6280_NMI_STATE: set_irq_line( INPUT_LINE_NMI, info->i ); break; + case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: set_irq_line( 0, info->i ); break; + case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: set_irq_line( 1, info->i ); break; + case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: set_irq_line( 2, info->i ); break; + case CPUINFO_INT_REGISTER + H6280_M1: h6280.mmr[0] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M2: h6280.mmr[1] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M3: h6280.mmr[2] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M4: h6280.mmr[3] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M5: h6280.mmr[4] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M6: h6280.mmr[5] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M7: h6280.mmr[6] = info->i; break; + case CPUINFO_INT_REGISTER + H6280_M8: h6280.mmr[7] = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void h6280_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h6280); break; + case CPUINFO_INT_INPUT_LINES: info->i = 3; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 7; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 2; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 17 + 6*65536; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 21; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 2; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: info->i = h6280.irq_state[0]; break; + case CPUINFO_INT_INPUT_STATE + 1: info->i = h6280.irq_state[1]; break; + case CPUINFO_INT_INPUT_STATE + 2: info->i = h6280.irq_state[2]; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = h6280.nmi_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = h6280.ppc.d; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + H6280_PC: info->i = PCD; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + H6280_S: info->i = S; break; + case CPUINFO_INT_REGISTER + H6280_P: info->i = P; break; + case CPUINFO_INT_REGISTER + H6280_A: info->i = A; break; + case CPUINFO_INT_REGISTER + H6280_X: info->i = X; break; + case CPUINFO_INT_REGISTER + H6280_Y: info->i = Y; break; + case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: info->i = h6280.irq_mask; break; + case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: info->i = h6280.timer_status; break; + case CPUINFO_INT_REGISTER + H6280_NMI_STATE: info->i = h6280.nmi_state; break; + case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: info->i = h6280.irq_state[0]; break; + case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: info->i = h6280.irq_state[1]; break; + case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: info->i = h6280.irq_state[2]; break; + case CPUINFO_INT_REGISTER + H6280_M1: info->i = h6280.mmr[0]; break; + case CPUINFO_INT_REGISTER + H6280_M2: info->i = h6280.mmr[1]; break; + case CPUINFO_INT_REGISTER + H6280_M3: info->i = h6280.mmr[2]; break; + case CPUINFO_INT_REGISTER + H6280_M4: info->i = h6280.mmr[3]; break; + case CPUINFO_INT_REGISTER + H6280_M5: info->i = h6280.mmr[4]; break; + case CPUINFO_INT_REGISTER + H6280_M6: info->i = h6280.mmr[5]; break; + case CPUINFO_INT_REGISTER + H6280_M7: info->i = h6280.mmr[6]; break; + case CPUINFO_INT_REGISTER + H6280_M8: info->i = h6280.mmr[7]; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = h6280_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = h6280_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = h6280_set_context; break; + case CPUINFO_PTR_INIT: info->init = h6280_init; break; + case CPUINFO_PTR_RESET: info->reset = h6280_reset; break; + case CPUINFO_PTR_EXIT: info->exit = h6280_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = h6280_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = h6280_dasm; break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h6280_ICount; break; + case CPUINFO_PTR_TRANSLATE: info->translate = h6280_translate; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "HuC6280"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Hudsonsoft 6280"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.11"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Bryan McPhail, mish@tendril.co.uk"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c", + h6280.p & 0x80 ? 'N':'.', + h6280.p & 0x40 ? 'V':'.', + h6280.p & 0x20 ? 'R':'.', + h6280.p & 0x10 ? 'B':'.', + h6280.p & 0x08 ? 'D':'.', + h6280.p & 0x04 ? 'I':'.', + h6280.p & 0x02 ? 'Z':'.', + h6280.p & 0x01 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + H6280_PC: sprintf(info->s, "PC:%04X", h6280.pc.d); break; + case CPUINFO_STR_REGISTER + H6280_S: sprintf(info->s, "S:%02X", h6280.sp.b.l); break; + case CPUINFO_STR_REGISTER + H6280_P: sprintf(info->s, "P:%02X", h6280.p); break; + case CPUINFO_STR_REGISTER + H6280_A: sprintf(info->s, "A:%02X", h6280.a); break; + case CPUINFO_STR_REGISTER + H6280_X: sprintf(info->s, "X:%02X", h6280.x); break; + case CPUINFO_STR_REGISTER + H6280_Y: sprintf(info->s, "Y:%02X", h6280.y); break; + case CPUINFO_STR_REGISTER + H6280_IRQ_MASK: sprintf(info->s, "IM:%02X", h6280.irq_mask); break; + case CPUINFO_STR_REGISTER + H6280_TIMER_STATE: sprintf(info->s, "TMR:%02X", h6280.timer_status); break; + case CPUINFO_STR_REGISTER + H6280_NMI_STATE: sprintf(info->s, "NMI:%X", h6280.nmi_state); break; + case CPUINFO_STR_REGISTER + H6280_IRQ1_STATE: sprintf(info->s, "IRQ1:%X", h6280.irq_state[0]); break; + case CPUINFO_STR_REGISTER + H6280_IRQ2_STATE: sprintf(info->s, "IRQ2:%X", h6280.irq_state[1]); break; + case CPUINFO_STR_REGISTER + H6280_IRQT_STATE: sprintf(info->s, "IRQT:%X", h6280.irq_state[2]); break; + case CPUINFO_STR_REGISTER + H6280_M1: sprintf(info->s, "M1:%02X", h6280.mmr[0]); break; + case CPUINFO_STR_REGISTER + H6280_M2: sprintf(info->s, "M2:%02X", h6280.mmr[1]); break; + case CPUINFO_STR_REGISTER + H6280_M3: sprintf(info->s, "M3:%02X", h6280.mmr[2]); break; + case CPUINFO_STR_REGISTER + H6280_M4: sprintf(info->s, "M4:%02X", h6280.mmr[3]); break; + case CPUINFO_STR_REGISTER + H6280_M5: sprintf(info->s, "M5:%02X", h6280.mmr[4]); break; + case CPUINFO_STR_REGISTER + H6280_M6: sprintf(info->s, "M6:%02X", h6280.mmr[5]); break; + case CPUINFO_STR_REGISTER + H6280_M7: sprintf(info->s, "M7:%02X", h6280.mmr[6]); break; + case CPUINFO_STR_REGISTER + H6280_M8: sprintf(info->s, "M8:%02X", h6280.mmr[7]); break; + } +} +#endif diff --git a/src/cpu/h6280/h6280.h b/src/cpu/h6280/h6280.h new file mode 100644 index 00000000..50be2fe5 --- /dev/null +++ b/src/cpu/h6280/h6280.h @@ -0,0 +1,53 @@ +/***************************************************************************** + + h6280.h Portable Hu6280 emulator interface + + Copyright Bryan McPhail, mish@tendril.co.uk + + This source code is based (with permission!) on the 6502 emulator by + Juergen Buchmueller. It is released as part of the Mame emulator project. + Let me know if you intend to use this code in any other project. + +******************************************************************************/ + +#pragma once + +#ifndef __H6280_H__ +#define __H6280_H__ + +//#include "cpuintrf.h" + +enum +{ + H6280_PC=1, H6280_S, H6280_P, H6280_A, H6280_X, H6280_Y, + H6280_IRQ_MASK, H6280_TIMER_STATE, + H6280_NMI_STATE, H6280_IRQ1_STATE, H6280_IRQ2_STATE, H6280_IRQT_STATE, + H6280_M1, H6280_M2, H6280_M3, H6280_M4, + H6280_M5, H6280_M6, H6280_M7, H6280_M8 +}; + +#define LAZY_FLAGS 0 + +#define H6280_RESET_VEC 0xfffe +#define H6280_NMI_VEC 0xfffc +#define H6280_TIMER_VEC 0xfffa +#define H6280_IRQ1_VEC 0xfff8 +#define H6280_IRQ2_VEC 0xfff6 /* Aka BRK vector */ + +//void h6280_get_info(UINT32 state, cpuinfo *info); + +#if 0 +READ8_HANDLER( h6280_irq_status_r ); +WRITE8_HANDLER( h6280_irq_status_w ); + +READ8_HANDLER( h6280_timer_r ); +WRITE8_HANDLER( h6280_timer_w ); + +/* functions for use by the PSG and joypad port only! */ +UINT8 h6280io_get_buffer(void); +void h6280io_set_buffer(UINT8); +#endif + +//offs_t h6280_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +#endif /* __H6280_H__ */ diff --git a/src/cpu/h6280/h6280ops.h b/src/cpu/h6280/h6280ops.h new file mode 100644 index 00000000..0610bd29 --- /dev/null +++ b/src/cpu/h6280/h6280ops.h @@ -0,0 +1,1379 @@ +/***************************************************************************** + + h6280ops.h - Addressing modes and opcode macros for the Hu6820 cpu + + Copyright Bryan McPhail, mish@tendril.co.uk + + This source code is based (with permission!) on the 6502 emulator by + Juergen Buchmueller. It is released as part of the Mame emulator project. + Let me know if you intend to use this code in any other project. + +******************************************************************************/ + +/* 6280 flags */ +#define _fC 0x01 +#define _fZ 0x02 +#define _fI 0x04 +#define _fD 0x08 +#define _fB 0x10 +#define _fT 0x20 +#define _fV 0x40 +#define _fN 0x80 + +/* some shortcuts for improved readability */ +#define A h6280.a +#define X h6280.x +#define Y h6280.y +#define P h6280.p +#define S h6280.sp.b.l + +#define TRANSLATED(addr) ((h6280.mmr[(addr)>>13] << 13) | ((addr)&0x1fff)) +#define CHANGE_PC do { offs_t temp = TRANSLATED(PCW); change_pc(temp); } while (0) +#define H6280_CYCLES(cyc) \ + { \ + h6280_ICount -= ((cyc) * h6280.clocks_per_cycle); \ + h6280.timer_value -= ((cyc) * h6280.clocks_per_cycle); \ + } + +#if LAZY_FLAGS + +#define NZ h6280.NZ +#define SET_NZ(n) \ + P &= ~_fT; \ + NZ = ((n & _fN) << 8) | n + +#else + +#define SET_NZ(n) \ + P = (P & ~(_fN|_fT|_fZ)) | \ + (n & _fN) | \ + ((n == 0) ? _fZ : 0) + +#endif + +#define EAL h6280.ea.b.l +#define EAH h6280.ea.b.h +#define EAW h6280.ea.w.l +#define EAD h6280.ea.d + +#define ZPL h6280.zp.b.l +#define ZPH h6280.zp.b.h +#define ZPW h6280.zp.w.l +#define ZPD h6280.zp.d + +#define PCL h6280.pc.b.l +#define PCH h6280.pc.b.h +#define PCW h6280.pc.w.l +#define PCD h6280.pc.d + +#define CLEAR_T \ + P &= ~_fT; + +#define DO_INTERRUPT(vector) \ +{ \ + H6280_CYCLES(7); /* 7 cycles for an int */ \ + PUSH(PCH); \ + PUSH(PCL); \ + COMPOSE_P(0,_fB); \ + PUSH(P); \ + P = (P & ~_fD) | _fI; /* knock out D and set I flag */ \ + PCL = RDMEM(vector); \ + PCH = RDMEM((vector+1)); \ + CHANGE_PC; \ +} + +#define CHECK_AND_TAKE_IRQ_LINES \ + if ( h6280.nmi_state != CLEAR_LINE ) { \ + h6280.nmi_state = CLEAR_LINE; \ + DO_INTERRUPT(H6280_NMI_VEC); \ + } \ + else if( !(P & _fI) ) \ + { \ + if ( h6280.irq_state[2] != CLEAR_LINE && \ + !(h6280.irq_mask & 0x4) ) \ + { \ + DO_INTERRUPT(H6280_TIMER_VEC); \ + } else \ + if ( h6280.irq_state[0] != CLEAR_LINE && \ + !(h6280.irq_mask & 0x2) ) \ + { \ + DO_INTERRUPT(H6280_IRQ1_VEC); \ + (*h6280.irq_callback)(0); \ + } else \ + if ( h6280.irq_state[1] != CLEAR_LINE && \ + !(h6280.irq_mask & 0x1) ) \ + { \ + DO_INTERRUPT(H6280_IRQ2_VEC); \ + (*h6280.irq_callback)(1); \ + } \ + } + +#define CHECK_IRQ_LINES \ + if ( ! h6280.irq_pending ) \ + h6280.irq_pending = 2; + +/*************************************************************** + * CHECK_VDC_VCE_PENALTY + * The CPU inserts 1 clock delay when accessing the VDC or VCE + * area. + ***************************************************************/ +#define CHECK_VDC_VCE_PENALTY(addr) \ + if ( ( TRANSLATED(addr) & 0x1FF800 ) == 0x1FE000 ) { \ + H6280_CYCLES(1); \ + } + +/*************************************************************** + * RDMEM read memory + ***************************************************************/ +H6280_INLINE UINT8 RDMEM(offs_t addr) { + CHECK_VDC_VCE_PENALTY(addr); + return h6280_read(TRANSLATED(addr)); +} + +/*************************************************************** + * WRMEM write memory + ***************************************************************/ +H6280_INLINE void WRMEM(offs_t addr, UINT8 data) { + CHECK_VDC_VCE_PENALTY(addr); + h6280_write(TRANSLATED(addr),data); +} + +/*************************************************************** + * RDMEMZ read memory - zero page + ***************************************************************/ +#define RDMEMZ(addr) \ + h6280_read( (h6280.mmr[1] << 13) | ((addr)&0x1fff)); + +/*************************************************************** + * WRMEMZ write memory - zero page + ***************************************************************/ +#define WRMEMZ(addr,data) \ + h6280_write( (h6280.mmr[1] << 13) | ((addr)&0x1fff),data); + +/*************************************************************** + * RDMEMW read word from memory + ***************************************************************/ +#define RDMEMW(addr) \ + h6280_read(TRANSLATED(addr)) \ +| ( h6280_read(TRANSLATED(addr+1)) << 8 ) + +/*************************************************************** + * RDZPWORD read a word from a zero page address + ***************************************************************/ +#define RDZPWORD(addr) \ + ((addr&0xff)==0xff) ? \ + h6280_read( (h6280.mmr[1] << 13) | ((addr)&0x1fff)) \ + +(h6280_read( (h6280.mmr[1] << 13) | ((addr-0xff)&0x1fff))<<8) : \ + h6280_read( (h6280.mmr[1] << 13) | ((addr)&0x1fff)) \ + +(h6280_read( (h6280.mmr[1] << 13) | ((addr+1)&0x1fff))<<8) + + +/*************************************************************** + * push a register onto the stack + ***************************************************************/ +#define PUSH(Rg) h6280_write( (h6280.mmr[1] << 13) | h6280.sp.d,Rg); S-- + +/*************************************************************** + * pull a register from the stack + ***************************************************************/ +#define PULL(Rg) S++; Rg = h6280_read( (h6280.mmr[1] << 13) | h6280.sp.d) + +/*************************************************************** + * RDOP read an opcode + ***************************************************************/ +#define RDOP() \ + h6280_fetch(TRANSLATED(PCW)) + +/*************************************************************** + * RDOPARG read an opcode argument + ***************************************************************/ +#define RDOPARG() \ + h6280_fetch(TRANSLATED(PCW)) + +/*************************************************************** + * BRA branch relative + ***************************************************************/ +#define BRA(cond) \ + CLEAR_T; \ + if (cond) \ + { \ + H6280_CYCLES(4); \ + tmp = RDOPARG(); \ + PCW++; \ + EAW = PCW + (signed char)tmp; \ + PCD = EAD; \ + CHANGE_PC; \ + } \ + else \ + { \ + PCW++; \ + H6280_CYCLES(2); \ + } + +/*************************************************************** + * + * Helper macros to build the effective address + * + ***************************************************************/ + +/*************************************************************** + * EA = zero page address + ***************************************************************/ +#define EA_ZPG \ + ZPL = RDOPARG(); \ + PCW++; \ + EAD = ZPD + +/*************************************************************** + * EA = zero page address - T flag + ***************************************************************/ +#define EA_TFLG \ + ZPL = X; \ + EAD = ZPD + +/*************************************************************** + * EA = zero page address + X + ***************************************************************/ +#define EA_ZPX \ + ZPL = RDOPARG() + X; \ + PCW++; \ + EAD = ZPD + +/*************************************************************** + * EA = zero page address + Y + ***************************************************************/ +#define EA_ZPY \ + ZPL = RDOPARG() + Y; \ + PCW++; \ + EAD = ZPD + +/*************************************************************** + * EA = absolute address + ***************************************************************/ +#define EA_ABS \ + EAL = RDOPARG(); \ + PCW++; \ + EAH = RDOPARG(); \ + PCW++ + +/*************************************************************** + * EA = absolute address + X + ***************************************************************/ +#define EA_ABX \ + EA_ABS; \ + EAW += X + +/*************************************************************** + * EA = absolute address + Y + ***************************************************************/ +#define EA_ABY \ + EA_ABS; \ + EAW += Y + +/*************************************************************** + * EA = zero page indirect (65c02 pre indexed w/o X) + ***************************************************************/ +#define EA_ZPI \ + ZPL = RDOPARG(); \ + PCW++; \ + EAD = RDZPWORD(ZPD) + +/*************************************************************** + * EA = zero page + X indirect (pre indexed) + ***************************************************************/ +#define EA_IDX \ + ZPL = RDOPARG() + X; \ + PCW++; \ + EAD = RDZPWORD(ZPD); + +/*************************************************************** + * EA = zero page indirect + Y (post indexed) + ***************************************************************/ +#define EA_IDY \ + ZPL = RDOPARG(); \ + PCW++; \ + EAD = RDZPWORD(ZPD); \ + EAW += Y + +/*************************************************************** + * EA = indirect (only used by JMP) + ***************************************************************/ +#define EA_IND \ + EA_ABS; \ + tmp = RDMEM(EAD); \ + EAD++; \ + EAH = RDMEM(EAD); \ + EAL = tmp + +/*************************************************************** + * EA = indirect plus x (only used by JMP) + ***************************************************************/ +#define EA_IAX \ + EA_ABS; \ + EAD+=X; \ + tmp = RDMEM(EAD); \ + EAD++; \ + EAH = RDMEM(EAD); \ + EAL = tmp + +/* read a value into tmp */ +#define RD_IMM tmp = RDOPARG(); PCW++ +#define RD_IMM2 tmp2 = RDOPARG(); PCW++ +#define RD_ACC tmp = A +#define RD_ZPG EA_ZPG; tmp = RDMEMZ(EAD) +#define RD_ZPX EA_ZPX; tmp = RDMEMZ(EAD) +#define RD_ZPY EA_ZPY; tmp = RDMEMZ(EAD) +#define RD_ABS EA_ABS; tmp = RDMEM(EAD) +#define RD_ABX EA_ABX; tmp = RDMEM(EAD) +#define RD_ABY EA_ABY; tmp = RDMEM(EAD) +#define RD_ZPI EA_ZPI; tmp = RDMEM(EAD) +#define RD_IDX EA_IDX; tmp = RDMEM(EAD) +#define RD_IDY EA_IDY; tmp = RDMEM(EAD) +#define RD_TFL EA_TFLG; tflagtemp = RDMEMZ(EAD) + +/* write a value from tmp */ +#define WR_ZPG EA_ZPG; WRMEMZ(EAD, tmp) +#define WR_ZPX EA_ZPX; WRMEMZ(EAD, tmp) +#define WR_ZPY EA_ZPY; WRMEMZ(EAD, tmp) +#define WR_ABS EA_ABS; WRMEM(EAD, tmp) +#define WR_ABX EA_ABX; WRMEM(EAD, tmp) +#define WR_ABY EA_ABY; WRMEM(EAD, tmp) +#define WR_ZPI EA_ZPI; WRMEM(EAD, tmp) +#define WR_IDX EA_IDX; WRMEM(EAD, tmp) +#define WR_IDY EA_IDY; WRMEM(EAD, tmp) + +/* write back a value from tmp to the last EA */ +#define WB_ACC A = (UINT8)tmp; +#define WB_EA WRMEM(EAD, tmp) +#define WB_EAZ WRMEMZ(EAD, tmp) +#define WB_TFL WRMEMZ(EAD, tflagtemp) + +/*************************************************************** + * + * Macros to emulate the 6280 opcodes + * + ***************************************************************/ + +/*************************************************************** + * compose the real flag register by + * including N and Z and set any + * SET and clear any CLR bits also + ***************************************************************/ +#if LAZY_FLAGS + +#define COMPOSE_P(SET,CLR) \ + P = (P & ~(_fN | _fZ | CLR)) | \ + (NZ >> 8) | \ + ((NZ & 0xff) ? 0 : _fZ) | \ + SET + +#else + +#define COMPOSE_P(SET,CLR) \ + P = (P & ~CLR) | SET + +#endif + +/* 6280 ******************************************************** + * ADC Add with carry + ***************************************************************/ +#define TADC \ + { \ + int tflagtemp; \ + CLEAR_T; \ + RD_TFL; \ + if (P & _fD) \ + { \ + int c = (P & _fC); \ + int lo = (tflagtemp & 0x0f) + (tmp & 0x0f) + c; \ + int hi = (tflagtemp & 0xf0) + (tmp & 0xf0); \ + P &= ~_fC; \ + if (lo > 0x09) \ + { \ + hi += 0x10; \ + lo += 0x06; \ + } \ + if (hi > 0x90) \ + hi += 0x60; \ + if (hi & 0xff00) \ + P |= _fC; \ + tflagtemp = (lo & 0x0f) + (hi & 0xf0); \ + H6280_CYCLES(1); \ + } \ + else \ + { \ + int c = (P & _fC); \ + int sum = tflagtemp + tmp + c; \ + P &= ~(_fV | _fC); \ + if (~(tflagtemp^tmp) & (tflagtemp^sum) & _fN) \ + P |= _fV; \ + if (sum & 0xff00) \ + P |= _fC; \ + tflagtemp = (UINT8) sum; \ + } \ + SET_NZ(tflagtemp); \ + WB_TFL; \ + H6280_CYCLES(3); \ + } + + +#define ADC \ + if(P & _fT) \ + TADC \ + else { \ + if (P & _fD) \ + { \ + int c = (P & _fC); \ + int lo = (A & 0x0f) + (tmp & 0x0f) + c; \ + int hi = (A & 0xf0) + (tmp & 0xf0); \ + P &= ~_fC; \ + if (lo > 0x09) \ + { \ + hi += 0x10; \ + lo += 0x06; \ + } \ + if (hi > 0x90) \ + hi += 0x60; \ + if (hi & 0xff00) \ + P |= _fC; \ + A = (lo & 0x0f) + (hi & 0xf0); \ + H6280_CYCLES(1); \ + } \ + else \ + { \ + int c = (P & _fC); \ + int sum = A + tmp + c; \ + P &= ~(_fV | _fC); \ + if (~(A^tmp) & (A^sum) & _fN) \ + P |= _fV; \ + if (sum & 0xff00) \ + P |= _fC; \ + A = (UINT8) sum; \ + } \ + SET_NZ(A); \ + } + +/* 6280 ******************************************************** + * AND Logical and + ***************************************************************/ +#define TAND \ + { \ + int tflagtemp; \ + CLEAR_T; \ + RD_TFL; \ + tflagtemp = (UINT8)(tflagtemp & tmp); \ + WB_TFL; \ + SET_NZ(tflagtemp); \ + H6280_CYCLES(3); \ + } + +#define AND \ + if(P & _fT) \ + TAND \ + else { \ + A = (UINT8)(A & tmp); \ + SET_NZ(A); \ + } + +/* 6280 ******************************************************** + * ASL Arithmetic shift left + ***************************************************************/ +#define ASL \ + CLEAR_T; \ + P = (P & ~_fC) | ((tmp >> 7) & _fC); \ + tmp = (UINT8)(tmp << 1); \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * BBR Branch if bit is reset + ***************************************************************/ +#define BBR(bit) \ + BRA(!(tmp & (1<= tmp) \ + P |= _fC; \ + SET_NZ((UINT8)(A - tmp)) + +/* 6280 ******************************************************** + * CPX Compare index X + ***************************************************************/ +#define CPX \ + CLEAR_T; \ + P &= ~_fC; \ + if (X >= tmp) \ + P |= _fC; \ + SET_NZ((UINT8)(X - tmp)) + +/* 6280 ******************************************************** + * CPY Compare index Y + ***************************************************************/ +#define CPY \ + CLEAR_T; \ + P &= ~_fC; \ + if (Y >= tmp) \ + P |= _fC; \ + SET_NZ((UINT8)(Y - tmp)) + +/* 6280 ******************************************************** + * DEA Decrement accumulator + ***************************************************************/ +#define DEA \ + CLEAR_T; \ + A = (UINT8)--A; \ + SET_NZ(A) + +/* 6280 ******************************************************** + * DEC Decrement memory + ***************************************************************/ +#define DEC \ + CLEAR_T; \ + tmp = (UINT8)(tmp-1); \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * DEX Decrement index X + ***************************************************************/ +#define DEX \ + CLEAR_T; \ + X = (UINT8)--X; \ + SET_NZ(X) + +/* 6280 ******************************************************** + * DEY Decrement index Y + ***************************************************************/ +#define DEY \ + CLEAR_T; \ + Y = (UINT8)--Y; \ + SET_NZ(Y) + +/* 6280 ******************************************************** + * EOR Logical exclusive or + ***************************************************************/ +#define TEOR \ + { \ + int tflagtemp; \ + CLEAR_T; \ + RD_TFL; \ + tflagtemp = (UINT8)(tflagtemp ^ tmp); \ + WB_TFL; \ + SET_NZ(tflagtemp); \ + H6280_CYCLES(3); \ + } + +#define EOR \ + if(P & _fT) \ + TEOR \ + else { \ + A = (UINT8)(A ^ tmp); \ + SET_NZ(A); \ + } + +/* 6280 ******************************************************** + * INA Increment accumulator + ***************************************************************/ +#define INA \ + CLEAR_T; \ + A = (UINT8)++A; \ + SET_NZ(A) + +/* 6280 ******************************************************** + * INC Increment memory + ***************************************************************/ +#define INC \ + CLEAR_T; \ + tmp = (UINT8)(tmp+1); \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * INX Increment index X + ***************************************************************/ +#define INX \ + CLEAR_T; \ + X = (UINT8)++X; \ + SET_NZ(X) + +/* 6280 ******************************************************** + * INY Increment index Y + ***************************************************************/ +#define INY \ + CLEAR_T; \ + Y = (UINT8)++Y; \ + SET_NZ(Y) + +/* 6280 ******************************************************** + * JMP Jump to address + * set PC to the effective address + ***************************************************************/ +#define JMP \ + CLEAR_T; \ + PCD = EAD; \ + CHANGE_PC + +/* 6280 ******************************************************** + * JSR Jump to subroutine + * decrement PC (sic!) push PC hi, push PC lo and set + * PC to the effective address + ***************************************************************/ +#define JSR \ + CLEAR_T; \ + PCW--; \ + PUSH(PCH); \ + PUSH(PCL); \ + PCD = EAD; \ + CHANGE_PC + +/* 6280 ******************************************************** + * LDA Load accumulator + ***************************************************************/ +#define LDA \ + CLEAR_T; \ + A = (UINT8)tmp; \ + SET_NZ(A) + +/* 6280 ******************************************************** + * LDX Load index X + ***************************************************************/ +#define LDX \ + CLEAR_T; \ + X = (UINT8)tmp; \ + SET_NZ(X) + +/* 6280 ******************************************************** + * LDY Load index Y + ***************************************************************/ +#define LDY \ + CLEAR_T; \ + Y = (UINT8)tmp; \ + SET_NZ(Y) + +/* 6280 ******************************************************** + * LSR Logic shift right + * 0 -> [7][6][5][4][3][2][1][0] -> C + ***************************************************************/ +#define LSR \ + CLEAR_T; \ + P = (P & ~_fC) | (tmp & _fC); \ + tmp = (UINT8)tmp >> 1; \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * NOP No operation + ***************************************************************/ +#define NOP CLEAR_T; + +/* 6280 ******************************************************** + * ORA Logical inclusive or + ***************************************************************/ + +#define TORA \ + { \ + int tflagtemp; \ + CLEAR_T; \ + RD_TFL; \ + tflagtemp = (UINT8)(tflagtemp | tmp); \ + WB_TFL; \ + SET_NZ(tflagtemp); \ + H6280_CYCLES(3); \ + } + +#define ORA \ + if(P & _fT) \ + TORA \ + else { \ + A = (UINT8)(A | tmp); \ + SET_NZ(A); \ + } + +/* 6280 ******************************************************** + * PHA Push accumulator + ***************************************************************/ +#define PHA \ + CLEAR_T; \ + PUSH(A) + +/* 6280 ******************************************************** + * PHP Push processor status (flags) + ***************************************************************/ +#define PHP \ + CLEAR_T; \ + COMPOSE_P(0,0); \ + PUSH(P) + +/* 6280 ******************************************************** + * PHX Push index X + ***************************************************************/ +#define PHX \ + CLEAR_T; \ + PUSH(X) + +/* 6280 ******************************************************** + * PHY Push index Y + ***************************************************************/ +#define PHY \ + CLEAR_T; \ + PUSH(Y) + +/* 6280 ******************************************************** + * PLA Pull accumulator + ***************************************************************/ +#define PLA \ + CLEAR_T; \ + PULL(A); \ + SET_NZ(A) + +/* 6280 ******************************************************** + * PLP Pull processor status (flags) + ***************************************************************/ +#if LAZY_FLAGS + +#define PLP \ + PULL(P); \ + P |= _fB; \ + NZ = ((P & _fN) << 8) | \ + ((P & _fZ) ^ _fZ); \ + CHECK_IRQ_LINES + +#else + +#define PLP \ + PULL(P); \ + P |= _fB; \ + CHECK_IRQ_LINES +#endif + +/* 6280 ******************************************************** + * PLX Pull index X + ***************************************************************/ +#define PLX \ + CLEAR_T; \ + PULL(X); \ + SET_NZ(X) + +/* 6280 ******************************************************** + * PLY Pull index Y + ***************************************************************/ +#define PLY \ + CLEAR_T; \ + PULL(Y); \ + SET_NZ(Y) + +/* 6280 ******************************************************** + * RMB Reset memory bit + ***************************************************************/ +#define RMB(bit) \ + CLEAR_T; \ + tmp &= ~(1<> 8) & _fC); \ + tmp = (UINT8)tmp; \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * ROR Rotate right + * C -> [7][6][5][4][3][2][1][0] -> new C + ***************************************************************/ +#define ROR \ + CLEAR_T; \ + tmp |= (P & _fC) << 8; \ + P = (P & ~_fC) | (tmp & _fC); \ + tmp = (UINT8)(tmp >> 1); \ + SET_NZ(tmp) + +/* 6280 ******************************************************** + * RTI Return from interrupt + * pull flags, pull PC lo, pull PC hi and increment PC + ***************************************************************/ +#if LAZY_FLAGS + +#define RTI \ + PULL(P); \ + P |= _fB; \ + NZ = ((P & _fN) << 8) | \ + ((P & _fZ) ^ _fZ); \ + PULL(PCL); \ + PULL(PCH); \ + CHANGE_PC; \ + CHECK_IRQ_LINES +#else + +#define RTI \ + PULL(P); \ + P |= _fB; \ + PULL(PCL); \ + PULL(PCH); \ + CHANGE_PC; \ + CHECK_IRQ_LINES +#endif + +/* 6280 ******************************************************** + * RTS Return from subroutine + * pull PC lo, PC hi and increment PC + ***************************************************************/ +#define RTS \ + CLEAR_T; \ + PULL(PCL); \ + PULL(PCH); \ + PCW++; \ + CHANGE_PC + +/* 6280 ******************************************************** + * SAX Swap accumulator and index X + ***************************************************************/ +#define SAX \ + CLEAR_T; \ + tmp = X; \ + X = A; \ + A = tmp + +/* 6280 ******************************************************** + * SAY Swap accumulator and index Y + ***************************************************************/ +#define SAY \ + CLEAR_T; \ + tmp = Y; \ + Y = A; \ + A = tmp + +/* 6280 ******************************************************** + * SBC Subtract with carry + ***************************************************************/ +#define TSBC \ + { \ + int tflagtemp; \ + CLEAR_T; \ + RD_TFL; \ + if (P & _fD) \ + { \ + int c = (P & _fC) ^ _fC; \ + int sum = tflagtemp - tmp -c; \ + int lo = (tflagtemp & 0x0f) - (tmp & 0x0f) - c; \ + int hi = (tflagtemp & 0xf0) - (tmp & 0xf0); \ + P &= ~_fC; \ + if (lo & 0xf0) \ + lo -= 6; \ + if (lo & 0x80) \ + hi -= 0x10; \ + if (hi & 0x0f00) \ + hi -= 0x60; \ + if ((sum & 0xff00) == 0) \ + P |= _fC; \ + tflagtemp = (lo & 0x0f) + (hi & 0xf0); \ + H6280_CYCLES(1); \ + } \ + else \ + { \ + int c = (P & _fC) ^ _fC; \ + int sum = tflagtemp - tmp - c; \ + P &= ~(_fV | _fC); \ + if ((tflagtemp^tmp) & (tflagtemp^sum) & _fN) \ + P |= _fV; \ + if ((sum & 0xff00) == 0) \ + P |= _fC; \ + tflagtemp = (UINT8) sum; \ + } \ + SET_NZ(tflagtemp); \ + WB_TFL; \ + H6280_CYCLES(3); \ + } + +#define SBC \ + if(P & _fT) \ + TSBC \ + else { \ + if (P & _fD) \ + { \ + int c = (P & _fC) ^ _fC; \ + int sum = A - tmp - c; \ + int lo = (A & 0x0f) - (tmp & 0x0f) - c; \ + int hi = (A & 0xf0) - (tmp & 0xf0); \ + P &= ~_fC; \ + if (lo & 0xf0) \ + lo -= 6; \ + if (lo & 0x80) \ + hi -= 0x10; \ + if (hi & 0x0f00) \ + hi -= 0x60; \ + if ((sum & 0xff00) == 0) \ + P |= _fC; \ + A = (lo & 0x0f) + (hi & 0xf0); \ + H6280_CYCLES(1); \ + } \ + else \ + { \ + int c = (P & _fC) ^ _fC; \ + int sum = A - tmp - c; \ + P &= ~(_fV | _fC); \ + if ((A^tmp) & (A^sum) & _fN) \ + P |= _fV; \ + if ((sum & 0xff00) == 0) \ + P |= _fC; \ + A = (UINT8) sum; \ + } \ + SET_NZ(A); \ + } + +/* 6280 ******************************************************** + * SEC Set carry flag + ***************************************************************/ +#if defined(SEC) +#undef SEC +#endif +#define SEC \ + CLEAR_T; \ + P |= _fC + +/* 6280 ******************************************************** + * SED Set decimal flag + ***************************************************************/ +#define SED \ + CLEAR_T; \ + P |= _fD + +/* 6280 ******************************************************** + * SEI Set interrupt flag + ***************************************************************/ +#define SEI \ + CLEAR_T; \ + P |= _fI + +/* 6280 ******************************************************** + * SET Set t flag + ***************************************************************/ +#define SET \ + P |= _fT; + +/* 6280 ******************************************************** + * SMB Set memory bit + ***************************************************************/ +#define SMB(bit) \ + CLEAR_T; \ + tmp |= (1<> PAGE_SHIFT; + + for (UINT32 i = 0; i < len+1; i++) + { + UINT32 offset = i + (start >> PAGE_SHIFT); + if (type & (1 << READ)) mem[ READ][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << WRITE)) mem[WRITE][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << FETCH)) mem[FETCH][offset] = src + (i << PAGE_SHIFT); + } +} + +INT32 h6280DummyIrqCallback(INT32) +{ + return 0; +} + +void h6280SetIrqCallbackHandler(INT32 (*callback)(INT32)) +{ + irqcallback = callback; +} + +void h6280SetWriteHandler(void (*write)(UINT32, UINT8)) +{ + h6280Write = write; +} + +void h6280SetWritePortHandler(void (*write)(UINT8, UINT8)) +{ + h6280WriteIO = write; +} + +void h6280SetReadHandler(UINT8 (*read)(UINT32)) +{ + h6280Read = read; +} + +void h6280_write_rom(UINT32 address, UINT8 data) +{ + if (mem[READ][address >> PAGE_SHIFT] != NULL) { + mem[READ][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[WRITE][address >> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (h6280Write != NULL) { + h6280Write(address, data); + } +} + +void h6280_write_port(UINT8 port, UINT8 data) +{ +// bprintf (0, _T("%5.5x write port\n"), port); + + if (h6280WriteIO != NULL) { + h6280WriteIO(port, data); + return; + } + + return; +} + +void h6280_write(UINT32 address, UINT8 data) +{ +// bprintf (0, _T("%5.5x write\n"), address); + + if (mem[WRITE][address >> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + return; + } + + if (h6280Write != NULL) { + h6280Write(address, data); + return; + } + + return; +} + +UINT8 h6280_read(UINT32 address) +{ +// bprintf (0, _T("%5.5x read\n"), address); + + if (mem[ READ][address >> PAGE_SHIFT] != NULL) { + return mem[ READ][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + if (h6280Read != NULL) { + return h6280Read(address); + } + + return 0; +} + +UINT8 h6280_fetch1(UINT32 address) +{ +// address &= 0xffff; + + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + return mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + if (h6280Read != NULL) { + return h6280Read(address); + } + + return 0; +} + +UINT8 h6280_fetch(UINT32 a) +{ +// bprintf (0, _T("%5.5x %5.5x, %2.2x fetch\n"), a, a&0xffff, h6280_fetch1(a)); + return h6280_fetch1(a); +} + +void h6280SetIRQLine(INT32 line, INT32 state) +{ + if (state == H6280_IRQSTATUS_AUTO) { + h6280_set_irq_line(line, 1); + h6280Run(10); + h6280_set_irq_line(line, 0); + } else { + h6280_set_irq_line(line, state); + } +} + +void h6280Init(INT32 num) // only 1 cpu (No examples exist of multi-cpu h6280 games) +{ + nh6280CpuCount = 1; +// h6280_init(h6280DummyIrqCallback); + + for (INT32 i = 0; i < 3; i++) { + for (INT32 j = 0; j < (MEMORY_SPACE / PAGE_SIZE); j++) { + mem[i][j] = NULL; + } + } + + h6280Write = NULL; + h6280Read = NULL; + h6280WriteIO = NULL; + + CpuCheatRegister(0x0009, num); +} + +void h6280Exit() +{ + nh6280CpuCount = 0; + h6280Write = NULL; + h6280Read = NULL; + h6280WriteIO = NULL; +} + +void h6280Open(INT32 num) +{ + nh6280CpuActive = num; +} + +void h6280Close() +{ + nh6280CpuActive = -1; +} + +INT32 h6280GetActive() +{ + return nh6280CpuActive; +} + diff --git a/src/cpu/h6280_intf.h b/src/cpu/h6280_intf.h new file mode 100644 index 00000000..e0d61365 --- /dev/null +++ b/src/cpu/h6280_intf.h @@ -0,0 +1,58 @@ +// h6280.cpp +void h6280_set_irq_line(INT32 irqline, INT32 state); +void h6280_init(INT32 (*irqcallback)(INT32)); + +// h6280_intf.cpp +#define H6280_READ 1 +#define H6280_WRITE 2 +#define H6280_FETCH 4 + +#define H6280_ROM (H6280_READ | H6280_FETCH) +#define H6280_RAM (H6280_READ | H6280_FETCH | H6280_WRITE) + +void h6280MapMemory(UINT8 *src, UINT32 start, UINT32 finish, INT32 type); + +void h6280SetIrqCallbackHandler(INT32 (*callback)(INT32)); +void h6280SetlinesCallback(void (*setlines_callback)(INT32 lines)); + +void h6280SetWritePortHandler(void (*write)(UINT8, UINT8)); +void h6280SetWriteHandler(void (*write)(UINT32, UINT8)); +void h6280SetReadHandler(UINT8 (*read)(UINT32)); + +void h6280_write_port(UINT8 port, UINT8 data); +void h6280_write(UINT32 address, UINT8 data); +UINT8 h6280_read(UINT32 address); +UINT8 h6280_fetch(UINT32 address); + +void h6280Init(INT32); +void h6280Open(INT32); +void h6280Reset(); +INT32 h6280Run(INT32 cycles); +void h6280Close(); +void h6280Exit(); + +extern INT32 nh6280CpuCount; + +#define H6280_IRQSTATUS_NONE 0 +#define H6280_IRQSTATUS_ACK 1 +#define H6280_IRQSTATUS_AUTO 2 + +#define H6280_INPUT_LINE_NMI 0x20 + +void h6280SetIRQLine(INT32 line, INT32 state); + +//INT32 h6280CpuScan(INT32 nAction, INT32 *); + +INT32 h6280TotalCycles(); +void h6280NewFrame(); +void h6280RunEnd(); + +INT32 h6280GetActive(); + +void h6280_write_rom(UINT32 address, UINT8 data); + + +UINT8 h6280_irq_status_r(UINT32 offset); +void h6280_irq_status_w(UINT32 offset, UINT8 data); +UINT8 h6280_timer_r(UINT32); +void h6280_timer_w(UINT32 offset, UINT8 data); diff --git a/src/cpu/hd6309/6309ops.c b/src/cpu/hd6309/6309ops.c new file mode 100644 index 00000000..3e113b91 --- /dev/null +++ b/src/cpu/hd6309/6309ops.c @@ -0,0 +1,5599 @@ +/* + +HNZVC + +? = undefined +* = affected +- = unaffected +0 = cleared +1 = set +# = CCr directly affected by instruction +@ = special - carry set if bit 7 is set + +*/ + +HD6309_INLINE void illegal( void ) +{ +// LOG(("HD6309: illegal opcode at %04x\nVectoring to [$fff0]\n",PC)); + + CC |= CC_E; + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + hd6309_ICount -= 2; + } + + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + + PCD = RM16(0xfff0); + CHANGE_PC; +} + +static void IIError(void) +{ + SEII; // Set illegal Instruction Flag + illegal(); // Vector to Trap handler +} + +static void DZError(void) +{ + SEDZ; // Set Division by Zero Flag + illegal(); // Vector to Trap handler +} + +/* $00 NEG direct ?**** */ +HD6309_INLINE void neg_di( void ) +{ + UINT16 r,t; + DIRBYTE(t); + r = -t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $01 OIM direct ?**** */ +HD6309_INLINE void oim_di( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + DIRBYTE(t); + r = im | t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $02 AIM direct */ +HD6309_INLINE void aim_di( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + DIRBYTE(t); + r = im & t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $03 COM direct -**01 */ +HD6309_INLINE void com_di( void ) +{ + UINT8 t; + DIRBYTE(t); + t = ~t; + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $04 LSR direct -0*-* */ +HD6309_INLINE void lsr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $05 EIM direct */ +HD6309_INLINE void eim_di( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + DIRBYTE(t); + r = im ^ t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $06 ROR direct -**-* */ +HD6309_INLINE void ror_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r= (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $07 ASR direct ?**-* */ +HD6309_INLINE void asr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t = (t & 0x80) | (t >> 1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $08 ASL direct ?**** */ +HD6309_INLINE void asl_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $09 ROL direct -**** */ +HD6309_INLINE void rol_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = (CC & CC_C) | (t << 1); + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $0A DEC direct -***- */ +HD6309_INLINE void dec_di( void ) +{ + UINT8 t; + DIRBYTE(t); + --t; + CLR_NZV; + SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $0B TIM direct */ +HD6309_INLINE void tim_di( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + DIRBYTE(t); + r = im & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $OC INC direct -***- */ +HD6309_INLINE void inc_di( void ) +{ + UINT8 t; + DIRBYTE(t); + ++t; + CLR_NZV; + SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $OD TST direct -**0- */ +HD6309_INLINE void tst_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZV; + SET_NZ8(t); +} + +/* $0E JMP direct ----- */ +HD6309_INLINE void jmp_di( void ) +{ + DIRECT; + PCD = EAD; + CHANGE_PC; +} + +/* $0F CLR direct -0100 */ +HD6309_INLINE void clr_di( void ) +{ + UINT32 dummy; + DIRECT; + dummy = RM(EAD); + WM(EAD,0); + CLR_NZVC; + SEZ; +} + +/* $10 FLAG */ + +/* $11 FLAG */ + +/* $12 NOP inherent ----- */ +HD6309_INLINE void nop( void ) +{ + ; +} + +/* $13 SYNC inherent ----- */ +HD6309_INLINE void sync( void ) +{ + /* SYNC stops processing instructions until an interrupt request happens. */ + /* This doesn't require the corresponding interrupt to be enabled: if it */ + /* is disabled, execution continues with the next instruction. */ + hd6309.int_state |= HD6309_SYNC; /* HJB 990227 */ + CHECK_IRQ_LINES(); + /* if HD6309_SYNC has not been cleared by CHECK_IRQ_LINES(), + * stop execution until the interrupt lines change. */ + if( hd6309.int_state & HD6309_SYNC ) + if (hd6309_ICount > 0) hd6309_ICount = 0; +} + +/* $14 sexw inherent */ +HD6309_INLINE void sexw( void ) +{ + PAIR q; + q.d = SIGNED_16(W); + D = q.w.h; + W = q.w.l; + CLR_NZ; + SET_N16(D); + SET_Z(q.d); +} + +/* $15 ILLEGAL */ + +/* $16 LBRA relative ----- */ +HD6309_INLINE void lbra( void ) +{ + IMMWORD(ea); + PC += EA; + CHANGE_PC; + + if ( EA == 0xfffd ) /* EHC 980508 speed up busy loop */ + if ( hd6309_ICount > 0) + hd6309_ICount = 0; +} + +/* $17 LBSR relative ----- */ +HD6309_INLINE void lbsr( void ) +{ + IMMWORD(ea); + PUSHWORD(pPC); + PC += EA; + CHANGE_PC; +} + +/* $18 ILLEGAL */ + +/* $19 DAA inherent (A) -**0* */ +HD6309_INLINE void daa( void ) +{ + UINT8 msn, lsn; + UINT16 t, cf = 0; + msn = A & 0xf0; lsn = A & 0x0f; + if( lsn>0x09 || CC & CC_H) cf |= 0x06; + if( msn>0x80 && lsn>0x09 ) cf |= 0x60; + if( msn>0x90 || CC & CC_C) cf |= 0x60; + t = cf + A; + CLR_NZV; /* keep carry from previous operation */ + SET_NZ8((UINT8)t); SET_C8(t); + A = t; +} + +/* $1A ORCC immediate ##### */ +HD6309_INLINE void orcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC |= t; + CHECK_IRQ_LINES(); /* HJB 990116 */ +} + +/* $1B ILLEGAL */ + +/* $1C ANDCC immediate ##### */ +HD6309_INLINE void andcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + CHECK_IRQ_LINES(); /* HJB 990116 */ +} + +/* $1D SEX inherent -**0- */ +HD6309_INLINE void sex( void ) +{ + UINT16 t; + t = SIGNED(B); + D = t; + CLR_NZ; + SET_NZ16(t); +} + +HD6309_INLINE void exg( void ) +{ + UINT16 t1,t2; + UINT8 tb; + int promote = FALSE; + + IMMBYTE(tb); + if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */ + { + promote = TRUE; + } + + switch(tb>>4) { + case 0: t1 = D; break; + case 1: t1 = X; break; + case 2: t1 = Y; break; + case 3: t1 = U; break; + case 4: t1 = S; break; + case 5: t1 = PC; break; + case 6: t1 = W; break; + case 7: t1 = V; break; + case 8: t1 = (promote ? A + ((A) << 8) : A); break; + case 9: t1 = (promote ? B + ((B) << 8) : B); break; + case 10: t1 = (promote ? CC + ((CC) << 8) : CC); break; + case 11: t1 = (promote ? DP + ((DP) << 8) : DP); break; + case 12: t1 = 0; break; + case 13: t1 = 0; break; + case 14: t1 = (promote ? E + ((E) << 8) : E); break; + default: t1 = (promote ? F + ((F) << 8) : F); break; + } + switch(tb&15) { + case 0: t2 = D; break; + case 1: t2 = X; break; + case 2: t2 = Y; break; + case 3: t2 = U; break; + case 4: t2 = S; break; + case 5: t2 = PC; break; + case 6: t2 = W; break; + case 7: t2 = V; break; + case 8: t2 = (promote ? A + ((A) << 8) : A); break; + case 9: t2 = (promote ? B + ((B) << 8) : B); break; + case 10: t2 = (promote ? CC + ((CC) << 8) : CC); break; + case 11: t2 = (promote ? DP + ((DP) << 8) : DP); break; + case 12: t2 = 0; break; + case 13: t2 = 0; break; + case 14: t2 = (promote ? E + ((E) << 8) : E); break; + default: t2 = (promote ? F + ((F) << 8) : F); break; + } + + switch(tb>>4) { + case 0: D = t2; break; + case 1: X = t2; break; + case 2: Y = t2; break; + case 3: U = t2; break; + case 4: S = t2; break; + case 5: PC = t2; CHANGE_PC; break; + case 6: W = t2; break; + case 7: V = t2; break; + case 8: A = (promote ? t2 >> 8 : t2); break; + case 9: B = (promote ? t2 & 0xff : t2); break; + case 10: CC = (promote ? t2 & 0xff : t2); break; + case 11: DP = (promote ? t2 >> 8 : t2); break; + case 12: /* 0 = t2 */ break; + case 13: /* 0 = t2 */ break; + case 14: E = (promote ? t2 >> 8 : t2); break; + case 15: F = (promote ? t2 & 0xff : t2); break; + } + switch(tb&15) { + case 0: D = t1; break; + case 1: X = t1; break; + case 2: Y = t1; break; + case 3: U = t1; break; + case 4: S = t1; break; + case 5: PC = t1; CHANGE_PC; break; + case 6: W = t1; break; + case 7: V = t1; break; + case 8: A = (promote ? t1 >> 8 : t1); break; + case 9: B = (promote ? t1 & 0xff : t1); break; + case 10: CC = (promote ? t1 & 0xff : t1); break; + case 11: DP = (promote ? t1 >> 8 : t1); break; + case 12: /* 0 = t1 */ break; + case 13: /* 0 = t1 */ break; + case 14: E = (promote ? t1 >> 8 : t1); break; + case 15: F = (promote ? t1 & 0xff : t1); break; + } +} + +/* $1F TFR inherent ----- */ +HD6309_INLINE void tfr( void ) +{ + UINT8 tb; + UINT16 t; + int promote = FALSE; + + IMMBYTE(tb); + if( (tb^(tb>>4)) & 0x08 ) + { + promote = TRUE; + } + + switch(tb>>4) { + case 0: t = D; break; + case 1: t = X; break; + case 2: t = Y; break; + case 3: t = U; break; + case 4: t = S; break; + case 5: t = PC; break; + case 6: t = W; break; + case 7: t = V; break; + case 8: t = (promote ? A + ((A) << 8) : A); break; + case 9: t = (promote ? B + ((B) << 8) : B); break; + case 10: t = (promote ? CC + ((CC) << 8) : CC); break; + case 11: t = (promote ? DP + ((DP) << 8) : DP); break; + case 12: t = 0; break; + case 13: t = 0; break; + case 14: t = (promote ? E + ((E) << 8) : E); break; + default: t = (promote ? F + ((F) << 8) : F); break; + } + + switch(tb&15) { + case 0: D = t; break; + case 1: X = t; break; + case 2: Y = t; break; + case 3: U = t; break; + case 4: S = t; break; + case 5: PC = t; CHANGE_PC; break; + case 6: W = t; break; + case 7: V = t; break; + case 8: A = (promote ? t >> 8 : t); break; + case 9: B = (promote ? t & 0xff : t); break; + case 10: CC = (promote ? t & 0xff : t); break; + case 11: DP = (promote ? t >> 8 : t); break; + case 12: /* 0 = t */ break; + case 13: /* 0 = t */ break; + case 14: E = (promote ? t >> 8 : t); break; + case 15: F = (promote ? t & 0xff : t); break; + } +} + +/* $20 BRA relative ----- */ +HD6309_INLINE void bra( void ) +{ + UINT8 t; + IMMBYTE(t); + PC += SIGNED(t); + CHANGE_PC; + /* JB 970823 - speed up busy loops */ + if( t == 0xfe ) + if( hd6309_ICount > 0 ) hd6309_ICount = 0; +} + +/* $21 BRN relative ----- */ +HD6309_INLINE void brn( void ) +{ + UINT8 t; + IMMBYTE(t); +} + +/* $1021 LBRN relative ----- */ +HD6309_INLINE void lbrn( void ) +{ + IMMWORD(ea); +} + +/* $22 BHI relative ----- */ +HD6309_INLINE void bhi( void ) +{ + BRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $1022 LBHI relative ----- */ +HD6309_INLINE void lbhi( void ) +{ + LBRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $23 BLS relative ----- */ +HD6309_INLINE void bls( void ) +{ + BRANCH( (CC & (CC_Z|CC_C)) ); +} + +/* $1023 LBLS relative ----- */ +HD6309_INLINE void lbls( void ) +{ + LBRANCH( (CC&(CC_Z|CC_C)) ); +} + +/* $24 BCC relative ----- */ +HD6309_INLINE void bcc( void ) +{ + BRANCH( !(CC&CC_C) ); +} + +/* $1024 LBCC relative ----- */ +HD6309_INLINE void lbcc( void ) +{ + LBRANCH( !(CC&CC_C) ); +} + +/* $25 BCS relative ----- */ +HD6309_INLINE void bcs( void ) +{ + BRANCH( (CC&CC_C) ); +} + +/* $1025 LBCS relative ----- */ +HD6309_INLINE void lbcs( void ) +{ + LBRANCH( (CC&CC_C) ); +} + +/* $26 BNE relative ----- */ +HD6309_INLINE void bne( void ) +{ + BRANCH( !(CC&CC_Z) ); +} + +/* $1026 LBNE relative ----- */ +HD6309_INLINE void lbne( void ) +{ + LBRANCH( !(CC&CC_Z) ); +} + +/* $27 BEQ relative ----- */ +HD6309_INLINE void beq( void ) +{ + BRANCH( (CC&CC_Z) ); +} + +/* $1027 LBEQ relative ----- */ +HD6309_INLINE void lbeq( void ) +{ + LBRANCH( (CC&CC_Z) ); +} + +/* $28 BVC relative ----- */ +HD6309_INLINE void bvc( void ) +{ + BRANCH( !(CC&CC_V) ); +} + +/* $1028 LBVC relative ----- */ +HD6309_INLINE void lbvc( void ) +{ + LBRANCH( !(CC&CC_V) ); +} + +/* $29 BVS relative ----- */ +HD6309_INLINE void bvs( void ) +{ + BRANCH( (CC&CC_V) ); +} + +/* $1029 LBVS relative ----- */ +HD6309_INLINE void lbvs( void ) +{ + LBRANCH( (CC&CC_V) ); +} + +/* $2A BPL relative ----- */ +HD6309_INLINE void bpl( void ) +{ + BRANCH( !(CC&CC_N) ); +} + +/* $102A LBPL relative ----- */ +HD6309_INLINE void lbpl( void ) +{ + LBRANCH( !(CC&CC_N) ); +} + +/* $2B BMI relative ----- */ +HD6309_INLINE void bmi( void ) +{ + BRANCH( (CC&CC_N) ); +} + +/* $102B LBMI relative ----- */ +HD6309_INLINE void lbmi( void ) +{ + LBRANCH( (CC&CC_N) ); +} + +/* $2C BGE relative ----- */ +HD6309_INLINE void bge( void ) +{ + BRANCH( !NXORV ); +} + +/* $102C LBGE relative ----- */ +HD6309_INLINE void lbge( void ) +{ + LBRANCH( !NXORV ); +} + +/* $2D BLT relative ----- */ +HD6309_INLINE void blt( void ) +{ + BRANCH( NXORV ); +} + +/* $102D LBLT relative ----- */ +HD6309_INLINE void lblt( void ) +{ + LBRANCH( NXORV ); +} + +/* $2E BGT relative ----- */ +HD6309_INLINE void bgt( void ) +{ + BRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $102E LBGT relative ----- */ +HD6309_INLINE void lbgt( void ) +{ + LBRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $2F BLE relative ----- */ +HD6309_INLINE void ble( void ) +{ + BRANCH( (NXORV || (CC&CC_Z)) ); +} + +/* $102F LBLE relative ----- */ +HD6309_INLINE void lble( void ) +{ + LBRANCH( (NXORV || (CC&CC_Z)) ); +} + +#define REGREG_PREAMBLE \ + IMMBYTE(tb); \ + if( (tb^(tb>>4)) & 0x08 ) \ + {promote = TRUE;} \ + switch(tb>>4) { \ + case 0: src16Reg = &D; large = TRUE; break; \ + case 1: src16Reg = &X; large = TRUE; break; \ + case 2: src16Reg = &Y; large = TRUE; break; \ + case 3: src16Reg = &U; large = TRUE; break; \ + case 4: src16Reg = &S; large = TRUE; break; \ + case 5: src16Reg = &PC; large = TRUE; break; \ + case 6: src16Reg = &W; large = TRUE; break; \ + case 7: src16Reg = &V; large = TRUE; break; \ + case 8: if (promote) src16Reg = &D; else src8Reg = &A; break; \ + case 9: if (promote) src16Reg = &D; else src8Reg = &B; break; \ + case 10: if (promote) src16Reg = &z16; else src8Reg = &CC; break; \ + case 11: if (promote) src16Reg = &z16; else src8Reg = &DP; break; \ + case 12: if (promote) src16Reg = &z16; else src8Reg = &z8; break; \ + case 13: if (promote) src16Reg = &z16; else src8Reg = &z8; break; \ + case 14: if (promote) src16Reg = &W; else src8Reg = &E; break; \ + default: if (promote) src16Reg = &W; else src8Reg = &F; break; \ + } \ + switch(tb&15) { \ + case 0: dst16Reg = &D; large = TRUE; break; \ + case 1: dst16Reg = &X; large = TRUE; break; \ + case 2: dst16Reg = &Y; large = TRUE; break; \ + case 3: dst16Reg = &U; large = TRUE; break; \ + case 4: dst16Reg = &S; large = TRUE; break; \ + case 5: dst16Reg = &PC; large = TRUE; break; \ + case 6: dst16Reg = &W; large = TRUE; break; \ + case 7: dst16Reg = &V; large = TRUE; break; \ + case 8: if (promote) dst16Reg = &D; else dst8Reg = &A; break; \ + case 9: if (promote) dst16Reg = &D; else dst8Reg = &B; break; \ + case 10: if (promote) dst16Reg = &z16; else dst8Reg = &CC; break; \ + case 11: if (promote) dst16Reg = &z16; else dst8Reg = &DP; break; \ + case 12: if (promote) dst16Reg = &z16; else dst8Reg = &z8; break; \ + case 13: if (promote) dst16Reg = &z16; else dst8Reg = &z8; break; \ + case 14: if (promote) dst16Reg = &W; else dst8Reg = &E; break; \ + default: if (promote) dst16Reg = &W; else dst8Reg = &F; break; \ + } \ + +/* $1030 addr_r r1 + r2 -> r2 */ + +HD6309_INLINE void addr_r( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = *src16Reg + *dst16Reg; + CLR_NZVC; + *dst16Reg = r16; + SET_FLAGS16(*src16Reg,*dst16Reg,r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *src8Reg + *dst8Reg; + CLR_NZVC; + /* SET_H(*src8Reg,*src8Reg,r8);*/ /*Experimentation prooved this not to be the case */ + *dst8Reg = r8; + SET_FLAGS8(*src8Reg,*dst8Reg,r8); + } +} + +HD6309_INLINE void adcr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = *src16Reg + *dst16Reg + (CC & CC_C); + CLR_NZVC; + *dst16Reg = r16; + SET_FLAGS16(*src16Reg,*dst16Reg,r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *src8Reg + *dst8Reg + (CC & CC_C); + CLR_NZVC; + /* SET_H(*src8Reg,*src8Reg,r8);*/ /*Experimentation prooved this not to be the case */ + *dst8Reg = r8; + SET_FLAGS8(*src8Reg,*dst8Reg,r8); + } +} + +/* $1032 SUBR r1 - r2 -> r2 */ +HD6309_INLINE void subr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg; + CLR_NZVC; + *dst16Reg = r16; + SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *dst8Reg - *src8Reg; + CLR_NZVC; + *dst8Reg = r8; + SET_FLAGS8(*dst8Reg,*src8Reg,r8); + } +} + +/* $1033 SBCR r1 - r2 - C -> r2 */ +HD6309_INLINE void sbcr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg - (CC & CC_C); + CLR_NZVC; + *dst16Reg = r16; + SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *dst8Reg - *src8Reg - (CC & CC_C); + CLR_NZVC; + *dst8Reg = r8; + SET_FLAGS8(*dst8Reg,*src8Reg,r8); + } +} + +/* $1034 ANDR r1 & r2 -> r2 */ +HD6309_INLINE void andr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = *src16Reg & *dst16Reg; + CLR_NZV; + *dst16Reg = r16; + SET_NZ16(r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *src8Reg & *dst8Reg; + CLR_NZV; + *dst8Reg = r8; + SET_NZ8(r8); + } +} + +/* $1035 ORR r1 | r2 -> r2 */ +HD6309_INLINE void orr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = *src16Reg | *dst16Reg; + CLR_NZV; + *dst16Reg = r16; + SET_NZ16(r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *src8Reg | *dst8Reg; + CLR_NZV; + *dst8Reg = r8; + SET_NZ8(r8); + } +} + +/* $1036 EORR r1 ^ r2 -> r2 */ +HD6309_INLINE void eorr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = *src16Reg ^ *dst16Reg; + CLR_NZV; + *dst16Reg = r16; + SET_NZ16(r16); + + if ( (tb&15) == 5 ) + { + CHANGE_PC; + } + } + else + { + r8 = *src8Reg ^ *dst8Reg; + CLR_NZV; + *dst8Reg = r8; + SET_NZ8(r8); + } +} + +/* $1037 CMPR r1 - r2 */ +HD6309_INLINE void cmpr( void ) +{ + UINT8 tb, z8 = 0; + UINT16 z16 = 0, r8; + UINT32 r16; + UINT8 *src8Reg = NULL, *dst8Reg = NULL; + UINT16 *src16Reg = NULL, *dst16Reg = NULL; + int promote = FALSE, large = FALSE; + + REGREG_PREAMBLE; + + if ( large ) + { + r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg; + CLR_NZVC; + SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16); + } + else + { + r8 = *dst8Reg - *src8Reg; + CLR_NZVC; + SET_FLAGS8(*dst8Reg,*src8Reg,r8); + } +} + +/* $1138 TFM R0+,R1+ */ +HD6309_INLINE void tfmpp( void ) +{ + UINT8 tb, srcValue = 0; + + IMMBYTE(tb); + + if ( W != 0 ) + { + switch(tb>>4) { + case 0: srcValue = RM(D++); break; + case 1: srcValue = RM(X++); break; + case 2: srcValue = RM(Y++); break; + case 3: srcValue = RM(U++); break; + case 4: srcValue = RM(S++); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + switch(tb&15) { + case 0: WM(D++, srcValue); break; + case 1: WM(X++, srcValue); break; + case 2: WM(Y++, srcValue); break; + case 3: WM(U++, srcValue); break; + case 4: WM(S++, srcValue); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + PCD = PCD - 3; + CHANGE_PC; + W--; + } + else + hd6309_ICount -= 6; /* Needs six aditional cycles to get the 6+3n */ +} + +/* $1139 TFM R0-,R1- */ +HD6309_INLINE void tfmmm( void ) +{ + UINT8 tb, srcValue = 0; + + IMMBYTE(tb); + + if ( W != 0 ) + { + switch(tb>>4) { + case 0: srcValue = RM(D--); break; + case 1: srcValue = RM(X--); break; + case 2: srcValue = RM(Y--); break; + case 3: srcValue = RM(U--); break; + case 4: srcValue = RM(S--); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + switch(tb&15) { + case 0: WM(D--, srcValue); break; + case 1: WM(X--, srcValue); break; + case 2: WM(Y--, srcValue); break; + case 3: WM(U--, srcValue); break; + case 4: WM(S--, srcValue); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + PCD = PCD - 3; + CHANGE_PC; + W--; + } + else + hd6309_ICount -= 6; /* Needs six aditional cycles to get the 6+3n */ +} + +/* $113A TFM R0+,R1 */ +HD6309_INLINE void tfmpc( void ) +{ + UINT8 tb, srcValue = 0; + + IMMBYTE(tb); + + if ( W != 0 ) + { + switch(tb>>4) { + case 0: srcValue = RM(D++); break; + case 1: srcValue = RM(X++); break; + case 2: srcValue = RM(Y++); break; + case 3: srcValue = RM(U++); break; + case 4: srcValue = RM(S++); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + switch(tb&15) { + case 0: WM(D, srcValue); break; + case 1: WM(X, srcValue); break; + case 2: WM(Y, srcValue); break; + case 3: WM(U, srcValue); break; + case 4: WM(S, srcValue); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + PCD = PCD - 3; + CHANGE_PC; + W--; + } + else + hd6309_ICount -= 6; /* Needs six aditional cycles to get the 6+3n */ +} + +/* $113B TFM R0,R1+ */ +HD6309_INLINE void tfmcp( void ) +{ + UINT8 tb, srcValue = 0; + + IMMBYTE(tb); + + if ( W != 0 ) + { + switch(tb>>4) { + case 0: srcValue = RM(D); break; + case 1: srcValue = RM(X); break; + case 2: srcValue = RM(Y); break; + case 3: srcValue = RM(U); break; + case 4: srcValue = RM(S); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + switch(tb&15) { + case 0: WM(D++, srcValue); break; + case 1: WM(X++, srcValue); break; + case 2: WM(Y++, srcValue); break; + case 3: WM(U++, srcValue); break; + case 4: WM(S++, srcValue); break; + default: IIError(); return; break; /* reg PC thru F */ + } + + PCD = PCD - 3; + CHANGE_PC; + W--; + } + else + hd6309_ICount -= 6; /* Needs six aditional cycles to get the 6+3n */ +} + +/* $30 LEAX indexed --*-- */ +HD6309_INLINE void leax( void ) +{ + fetch_effective_address(); + X = EA; + CLR_Z; + SET_Z(X); +} + +/* $31 LEAY indexed --*-- */ +HD6309_INLINE void leay( void ) +{ + fetch_effective_address(); + Y = EA; + CLR_Z; + SET_Z(Y); +} + +/* $32 LEAS indexed ----- */ +HD6309_INLINE void leas( void ) +{ + fetch_effective_address(); + S = EA; + hd6309.int_state |= HD6309_LDS; +} + +/* $33 LEAU indexed ----- */ +HD6309_INLINE void leau( void ) +{ + fetch_effective_address(); + U = EA; +} + +/* $34 PSHS inherent ----- */ +HD6309_INLINE void pshs( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PUSHWORD(pPC); hd6309_ICount -= 2; } + if( t&0x40 ) { PUSHWORD(pU); hd6309_ICount -= 2; } + if( t&0x20 ) { PUSHWORD(pY); hd6309_ICount -= 2; } + if( t&0x10 ) { PUSHWORD(pX); hd6309_ICount -= 2; } + if( t&0x08 ) { PUSHBYTE(DP); hd6309_ICount -= 1; } + if( t&0x04 ) { PUSHBYTE(B); hd6309_ICount -= 1; } + if( t&0x02 ) { PUSHBYTE(A); hd6309_ICount -= 1; } + if( t&0x01 ) { PUSHBYTE(CC); hd6309_ICount -= 1; } +} + +/* $1038 PSHSW inherent ----- */ +HD6309_INLINE void pshsw( void ) +{ + PUSHWORD(pW); +} + +/* $103a PSHUW inherent ----- */ +HD6309_INLINE void pshuw( void ) +{ + PSHUWORD(pW); +} + +/* $35 PULS inherent ----- */ +HD6309_INLINE void puls( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULLBYTE(CC); hd6309_ICount -= 1; } + if( t&0x02 ) { PULLBYTE(A); hd6309_ICount -= 1; } + if( t&0x04 ) { PULLBYTE(B); hd6309_ICount -= 1; } + if( t&0x08 ) { PULLBYTE(DP); hd6309_ICount -= 1; } + if( t&0x10 ) { PULLWORD(XD); hd6309_ICount -= 2; } + if( t&0x20 ) { PULLWORD(YD); hd6309_ICount -= 2; } + if( t&0x40 ) { PULLWORD(UD); hd6309_ICount -= 2; } + if( t&0x80 ) { PULLWORD(PCD); CHANGE_PC; hd6309_ICount -= 2; } + + /* HJB 990225: moved check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES(); } +} + +/* $1039 PULSW inherent ----- */ +HD6309_INLINE void pulsw( void ) +{ + PULLWORD(W); +} + +/* $103b PULUW inherent ----- */ +HD6309_INLINE void puluw( void ) +{ + PULUWORD(W); +} + +/* $36 PSHU inherent ----- */ +HD6309_INLINE void pshu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PSHUWORD(pPC); hd6309_ICount -= 2; } + if( t&0x40 ) { PSHUWORD(pS); hd6309_ICount -= 2; } + if( t&0x20 ) { PSHUWORD(pY); hd6309_ICount -= 2; } + if( t&0x10 ) { PSHUWORD(pX); hd6309_ICount -= 2; } + if( t&0x08 ) { PSHUBYTE(DP); hd6309_ICount -= 1; } + if( t&0x04 ) { PSHUBYTE(B); hd6309_ICount -= 1; } + if( t&0x02 ) { PSHUBYTE(A); hd6309_ICount -= 1; } + if( t&0x01 ) { PSHUBYTE(CC); hd6309_ICount -= 1; } +} + +/* 37 PULU inherent ----- */ +HD6309_INLINE void pulu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULUBYTE(CC); hd6309_ICount -= 1; } + if( t&0x02 ) { PULUBYTE(A); hd6309_ICount -= 1; } + if( t&0x04 ) { PULUBYTE(B); hd6309_ICount -= 1; } + if( t&0x08 ) { PULUBYTE(DP); hd6309_ICount -= 1; } + if( t&0x10 ) { PULUWORD(XD); hd6309_ICount -= 2; } + if( t&0x20 ) { PULUWORD(YD); hd6309_ICount -= 2; } + if( t&0x40 ) { PULUWORD(SD); hd6309_ICount -= 2; } + if( t&0x80 ) { PULUWORD(PCD); CHANGE_PC; hd6309_ICount -= 2; } + + /* HJB 990225: moved check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES(); } +} + +/* $38 ILLEGAL */ + +/* $39 RTS inherent ----- */ +HD6309_INLINE void rts( void ) +{ + PULLWORD(PCD); + CHANGE_PC; +} + +/* $3A ABX inherent ----- */ +HD6309_INLINE void abx( void ) +{ + X += B; +} + +/* $3B RTI inherent ##### */ +HD6309_INLINE void rti( void ) +{ + UINT8 t; + PULLBYTE(CC); + t = CC & CC_E; /* HJB 990225: entire state saved? */ + if(t) + { + hd6309_ICount -= 9; + PULLBYTE(A); + PULLBYTE(B); + if ( MD & MD_EM ) + { + PULLBYTE(E); + PULLBYTE(F); + hd6309_ICount -= 2; + } + PULLBYTE(DP); + PULLWORD(XD); + PULLWORD(YD); + PULLWORD(UD); + } + PULLWORD(PCD); + CHANGE_PC; + CHECK_IRQ_LINES(); /* HJB 990116 */ +} + +/* $3C CWAI inherent ----1 */ +HD6309_INLINE void cwai( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + /* + * CWAI stacks the entire machine state on the hardware stack, + * then waits for an interrupt; when the interrupt is taken + * later, the state is *not* saved again after CWAI. + */ + CC |= CC_E; /* HJB 990225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(E); + PUSHBYTE(F); + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + hd6309.int_state |= HD6309_CWAI; /* HJB 990228 */ + CHECK_IRQ_LINES(); /* HJB 990116 */ + if( hd6309.int_state & HD6309_CWAI ) + if( hd6309_ICount > 0 ) + hd6309_ICount = 0; +} + +/* $3D MUL inherent --*-@ */ +HD6309_INLINE void mul( void ) +{ + UINT16 t; + t = A * B; + CLR_ZC; SET_Z16(t); if(t&0x80) SEC; + D = t; +} + +/* $3E ILLEGAL */ + +/* $3F SWI (SWI2 SWI3) absolute indirect ----- */ +HD6309_INLINE void swi( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD=RM16(0xfffa); + CHANGE_PC; +} + +/* $1130 BAND */ + +#define decodePB_tReg(n) (((n) >> 6) & 0x03) +#define decodePB_src(n) (((n) >> 3) & 0x07) +#define decodePB_dst(n) (((n) >> 0) & 0x07) + +static UINT8 dummy_byte; +static unsigned char *const regTable[4] = { &(CC), &(A), &(B), &dummy_byte }; + +static const UINT8 bitTable[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + +HD6309_INLINE void band( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) && ( db & bitTable[decodePB_src(pb)] )) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1131 BIAND */ + +HD6309_INLINE void biand( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) && ( (~db) & bitTable[decodePB_src(pb)] )) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1132 BOR */ + +HD6309_INLINE void bor( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) || ( db & bitTable[decodePB_src(pb)] )) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1133 BIOR */ + +HD6309_INLINE void bior( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) || ( (~db) & bitTable[decodePB_src(pb)] )) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1134 BEOR */ + +HD6309_INLINE void beor( void ) +{ + UINT8 pb; + UINT16 db; + UINT8 tReg, tMem; + + IMMBYTE(pb); + + DIRBYTE(db); + + tReg = *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)]; + tMem = db & bitTable[decodePB_src(pb)]; + + if ( (tReg || tMem ) && !(tReg && tMem) ) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1135 BIEOR */ + +HD6309_INLINE void bieor( void ) +{ + UINT8 pb; + UINT16 db; + UINT8 tReg, tMem; + + IMMBYTE(pb); + + DIRBYTE(db); + + tReg = *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)]; + tMem = (~db) & bitTable[decodePB_src(pb)]; + + if ( (tReg || tMem ) && !(tReg && tMem) ) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1133 LDBT */ + +HD6309_INLINE void ldbt( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( db & bitTable[decodePB_src(pb)] ) ) + *(regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)]; + else + *(regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]); +} + +/* $1134 STBT */ + +HD6309_INLINE void stbt( void ) +{ + UINT8 pb; + UINT16 db; + + IMMBYTE(pb); + + DIRBYTE(db); + + if ( ( *(regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) ) + WM( EAD, db | bitTable[decodePB_src(pb)] ); + else + WM( EAD, db & (~bitTable[decodePB_src(pb)]) ); +} + +/* $103F SWI2 absolute indirect ----- */ +HD6309_INLINE void swi2( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD = RM16(0xfff4); + CHANGE_PC; +} + +/* $113F SWI3 absolute indirect ----- */ +HD6309_INLINE void swi3( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD = RM16(0xfff2); + CHANGE_PC; +} + +/* $40 NEGA inherent ?**** */ +HD6309_INLINE void nega( void ) +{ + UINT16 r; + r = -A; + CLR_NZVC; + SET_FLAGS8(0,A,r); + A = r; +} + +/* $41 ILLEGAL */ + +/* $42 ILLEGAL */ + +/* $43 COMA inherent -**01 */ +HD6309_INLINE void coma( void ) +{ + A = ~A; + CLR_NZV; + SET_NZ8(A); + SEC; +} + +/* $44 LSRA inherent -0*-* */ +HD6309_INLINE void lsra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A >>= 1; + SET_Z8(A); +} + +/* $45 ILLEGAL */ + +/* $46 RORA inherent -**-* */ +HD6309_INLINE void rora( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (A & CC_C); + r |= A >> 1; + SET_NZ8(r); + A = r; +} + +/* $47 ASRA inherent ?**-* */ +HD6309_INLINE void asra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A = (A & 0x80) | (A >> 1); + SET_NZ8(A); +} + +/* $48 ASLA inherent ?**** */ +HD6309_INLINE void asla( void ) +{ + UINT16 r; + r = A << 1; + CLR_NZVC; + SET_FLAGS8(A,A,r); + A = r; +} + +/* $49 ROLA inherent -**** */ +HD6309_INLINE void rola( void ) +{ + UINT16 t,r; + t = A; + r = (CC & CC_C) | (t<<1); + CLR_NZVC; SET_FLAGS8(t,t,r); + A = r; +} + +/* $4A DECA inherent -***- */ +HD6309_INLINE void deca( void ) +{ + --A; + CLR_NZV; + SET_FLAGS8D(A); +} + +/* $4B ILLEGAL */ + +/* $4C INCA inherent -***- */ +HD6309_INLINE void inca( void ) +{ + ++A; + CLR_NZV; + SET_FLAGS8I(A); +} + +/* $4D TSTA inherent -**0- */ +HD6309_INLINE void tsta( void ) +{ + CLR_NZV; + SET_NZ8(A); +} + +/* $4E ILLEGAL */ + +/* $4F CLRA inherent -0100 */ +HD6309_INLINE void clra( void ) +{ + A = 0; + CLR_NZVC; SEZ; +} + +/* $50 NEGB inherent ?**** */ +HD6309_INLINE void negb( void ) +{ + UINT16 r; + r = -B; + CLR_NZVC; + SET_FLAGS8(0,B,r); + B = r; +} + +/* $1040 NEGD inherent ?**** */ +HD6309_INLINE void negd( void ) +{ + UINT32 r; + r = -D; + CLR_NZVC; + SET_FLAGS16(0,D,r); + D = r; +} + +/* $51 ILLEGAL */ + +/* $52 ILLEGAL */ + +/* $53 COMB inherent -**01 */ +HD6309_INLINE void comb( void ) +{ + B = ~B; + CLR_NZV; + SET_NZ8(B); + SEC; +} + +/* $1143 COME inherent -**01 */ +HD6309_INLINE void come( void ) +{ + E = ~E; + CLR_NZV; + SET_NZ8(E); + SEC; +} + +/* $1153 COMF inherent -**01 */ +HD6309_INLINE void comf( void ) +{ + F = ~F; + CLR_NZV; + SET_NZ8(F); + SEC; +} + +/* $1043 COMD inherent -**01 */ +HD6309_INLINE void comd( void ) +{ + D = ~D; + CLR_NZV; + SET_NZ16(D); + SEC; +} + +/* $1053 COMW inherent -**01 */ +HD6309_INLINE void comw( void ) +{ + W = ~W; + CLR_NZV; + SET_NZ16(W); + SEC; +} + +/* $54 LSRB inherent -0*-* */ +HD6309_INLINE void lsrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B >>= 1; + SET_Z8(B); +} + +/* $1044 LSRD inherent -0*-* */ +HD6309_INLINE void lsrd( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + D >>= 1; + SET_Z16(D); +} + +/* $1054 LSRW inherent -0*-* */ +HD6309_INLINE void lsrw( void ) +{ + CLR_NZC; + CC |= (F & CC_C); + W >>= 1; + SET_Z16(W); +} + +/* $55 ILLEGAL */ + +/* $56 RORB inherent -**-* */ +HD6309_INLINE void rorb( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (B & CC_C); + r |= B >> 1; + SET_NZ8(r); + B = r; +} + +/* $1046 RORD inherent -**-* */ +HD6309_INLINE void rord( void ) +{ + UINT16 r; + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (D & CC_C); + r |= D >> 1; + SET_NZ16(r); + D = r; +} + +/* $1056 RORW inherent -**-* */ +HD6309_INLINE void rorw( void ) +{ + UINT16 r; + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (W & CC_C); + r |= W >> 1; + SET_NZ16(r); + W = r; +} + +/* $57 ASRB inherent ?**-* */ +HD6309_INLINE void asrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B= (B & 0x80) | (B >> 1); + SET_NZ8(B); +} + +/* $1047 ASRD inherent ?**-* */ +HD6309_INLINE void asrd( void ) +{ + CLR_NZC; + CC |= (D & CC_C); + D= (D & 0x8000) | (D >> 1); + SET_NZ16(D); +} + +/* $58 ASLB inherent ?**** */ +HD6309_INLINE void aslb( void ) +{ + UINT16 r; + r = B << 1; + CLR_NZVC; + SET_FLAGS8(B,B,r); + B = r; +} + +/* $1048 ASLD inherent ?**** */ +HD6309_INLINE void asld( void ) +{ + UINT32 r; + r = D << 1; + CLR_NZVC; + SET_FLAGS16(D,D,r); + D = r; +} + +/* $59 ROLB inherent -**** */ +HD6309_INLINE void rolb( void ) +{ + UINT16 t,r; + t = B; + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + B = r; +} + +/* $1049 ROLD inherent -**** */ +HD6309_INLINE void rold( void ) +{ + UINT32 t,r; + t = D; + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS16(t,t,r); + D = r; +} + +/* $1059 ROLW inherent -**** */ +HD6309_INLINE void rolw( void ) +{ + UINT32 t,r; + t = W; + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS16(t,t,r); + W = r; +} + +/* $5A DECB inherent -***- */ +HD6309_INLINE void decb( void ) +{ + --B; + CLR_NZV; + SET_FLAGS8D(B); +} + +/* $114a DECE inherent -***- */ +HD6309_INLINE void dece( void ) +{ + --E; + CLR_NZV; + SET_FLAGS8D(E); +} + +/* $115a DECF inherent -***- */ +HD6309_INLINE void decf( void ) +{ + --F; + CLR_NZV; + SET_FLAGS8D(F); +} + +/* $104a DECD inherent -***- */ +HD6309_INLINE void decd( void ) +{ + UINT32 r; + r = D - 1; + CLR_NZVC; + SET_FLAGS16(D,D,r) + D = r; +} + +/* $105a DECW inherent -***- */ +HD6309_INLINE void decw( void ) +{ + UINT32 r; + r = W - 1; + CLR_NZVC; + SET_FLAGS16(W,W,r) + W = r; +} + +/* $5B ILLEGAL */ + +/* $5C INCB inherent -***- */ +HD6309_INLINE void incb( void ) +{ + ++B; + CLR_NZV; + SET_FLAGS8I(B); +} + +/* $114c INCE inherent -***- */ +HD6309_INLINE void ince( void ) +{ + ++E; + CLR_NZV; + SET_FLAGS8I(E); +} + +/* $115c INCF inherent -***- */ +HD6309_INLINE void incf( void ) +{ + ++F; + CLR_NZV; + SET_FLAGS8I(F); +} + +/* $104c INCD inherent -***- */ +HD6309_INLINE void incd( void ) +{ + UINT32 r; + r = D + 1; + CLR_NZVC; + SET_FLAGS16(D,D,r) + D = r; +} + +/* $105c INCW inherent -***- */ +HD6309_INLINE void incw( void ) +{ + UINT32 r; + r = W + 1; + CLR_NZVC; + SET_FLAGS16(W,W,r) + W = r; +} + +/* $5D TSTB inherent -**0- */ +HD6309_INLINE void tstb( void ) +{ + CLR_NZV; + SET_NZ8(B); +} + +/* $104d TSTD inherent -**0- */ +HD6309_INLINE void tstd( void ) +{ + CLR_NZV; + SET_NZ16(D); +} + +/* $105d TSTW inherent -**0- */ +HD6309_INLINE void tstw( void ) +{ + CLR_NZV; + SET_NZ16(W); +} + +/* $114d TSTE inherent -**0- */ +HD6309_INLINE void tste( void ) +{ + CLR_NZV; + SET_NZ8(E); +} + +/* $115d TSTF inherent -**0- */ +HD6309_INLINE void tstf( void ) +{ + CLR_NZV; + SET_NZ8(F); +} + +/* $5E ILLEGAL */ + +/* $5F CLRB inherent -0100 */ +HD6309_INLINE void clrb( void ) +{ + B = 0; + CLR_NZVC; SEZ; +} + +/* $104f CLRD inherent -0100 */ +HD6309_INLINE void clrd( void ) +{ + D = 0; + CLR_NZVC; SEZ; +} + +/* $114f CLRE inherent -0100 */ +HD6309_INLINE void clre( void ) +{ + E = 0; + CLR_NZVC; SEZ; +} + +/* $115f CLRF inherent -0100 */ +HD6309_INLINE void clrf( void ) +{ + F = 0; + CLR_NZVC; SEZ; +} + +/* $105f CLRW inherent -0100 */ +HD6309_INLINE void clrw( void ) +{ + W = 0; + CLR_NZVC; SEZ; +} + +/* $60 NEG indexed ?**** */ +HD6309_INLINE void neg_ix( void ) +{ + UINT16 r,t; + fetch_effective_address(); + t = RM(EAD); + r=-t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $61 OIM indexed */ +HD6309_INLINE void oim_ix( void ) +{ + UINT8 r,im; + IMMBYTE(im); + fetch_effective_address(); + r = im | RM(EAD); + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $62 AIM indexed */ +HD6309_INLINE void aim_ix( void ) +{ + UINT8 r,im; + IMMBYTE(im); + fetch_effective_address(); + r = im & RM(EAD); + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $63 COM indexed -**01 */ +HD6309_INLINE void com_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = ~RM(EAD); + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $64 LSR indexed -0*-* */ +HD6309_INLINE void lsr_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t=RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $65 EIM indexed */ +HD6309_INLINE void eim_ix( void ) +{ + UINT8 r,im; + IMMBYTE(im); + fetch_effective_address(); + r = im ^ RM(EAD); + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} +/* $66 ROR indexed -**-* */ +HD6309_INLINE void ror_ix( void ) +{ + UINT8 t,r; + fetch_effective_address(); + t=RM(EAD); + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $67 ASR indexed ?**-* */ +HD6309_INLINE void asr_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t=RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $68 ASL indexed ?**** */ +HD6309_INLINE void asl_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t=RM(EAD); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $69 ROL indexed -**** */ +HD6309_INLINE void rol_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t=RM(EAD); + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $6A DEC indexed -***- */ +HD6309_INLINE void dec_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD) - 1; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $6B TIM indexed */ +HD6309_INLINE void tim_ix( void ) +{ + UINT8 r,im,m; + IMMBYTE(im); + fetch_effective_address(); + m = RM(EAD); + r = im & m; + CLR_NZV; + SET_NZ8(r); +} + +/* $6C INC indexed -***- */ +HD6309_INLINE void inc_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD) + 1; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $6D TST indexed -**0- */ +HD6309_INLINE void tst_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD); + CLR_NZV; + SET_NZ8(t); +} + +/* $6E JMP indexed ----- */ +HD6309_INLINE void jmp_ix( void ) +{ + fetch_effective_address(); + PCD = EAD; + CHANGE_PC; +} + +/* $6F CLR indexed -0100 */ +HD6309_INLINE void clr_ix( void ) +{ + UINT32 dummy; + fetch_effective_address(); + dummy = RM(EAD); + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $70 NEG extended ?**** */ +HD6309_INLINE void neg_ex( void ) +{ + UINT16 r,t; + EXTBYTE(t); r=-t; + CLR_NZVC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $71 OIM extended */ +HD6309_INLINE void oim_ex( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + EXTBYTE(t); + r = im | t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $72 AIM extended */ +HD6309_INLINE void aim_ex( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + EXTBYTE(t); + r = im & t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $73 COM extended -**01 */ +HD6309_INLINE void com_ex( void ) +{ + UINT8 t; + EXTBYTE(t); t = ~t; + CLR_NZV; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $74 LSR extended -0*-* */ +HD6309_INLINE void lsr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $75 EIM extended */ +HD6309_INLINE void eim_ex( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + EXTBYTE(t); + r = im ^ t; + CLR_NZV; + SET_NZ8(r); + WM(EAD,r); +} + +/* $76 ROR extended -**-* */ +HD6309_INLINE void ror_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); r=(CC & CC_C) << 7; + CLR_NZC; CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $77 ASR extended ?**-* */ +HD6309_INLINE void asr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $78 ASL extended ?**** */ +HD6309_INLINE void asl_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r=t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $79 ROL extended -**** */ +HD6309_INLINE void rol_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = (CC & CC_C) | (t << 1); + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $7A DEC extended -***- */ +HD6309_INLINE void dec_ex( void ) +{ + UINT8 t; + EXTBYTE(t); --t; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $7B TIM extended */ +HD6309_INLINE void tim_ex( void ) +{ + UINT8 r,t,im; + IMMBYTE(im); + EXTBYTE(t); + r = im & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $7C INC extended -***- */ +HD6309_INLINE void inc_ex( void ) +{ + UINT8 t; + EXTBYTE(t); ++t; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $7D TST extended -**0- */ +HD6309_INLINE void tst_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZV; SET_NZ8(t); +} + +/* $7E JMP extended ----- */ +HD6309_INLINE void jmp_ex( void ) +{ + EXTENDED; + PCD = EAD; + CHANGE_PC; +} + +/* $7F CLR extended -0100 */ +HD6309_INLINE void clr_ex( void ) +{ + UINT32 dummy; + EXTENDED; + dummy = RM(EAD); + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $80 SUBA immediate ?**** */ +HD6309_INLINE void suba_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $81 CMPA immediate ?**** */ +HD6309_INLINE void cmpa_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $82 SBCA immediate ?**** */ +HD6309_INLINE void sbca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $83 SUBD (CMPD CMPU) immediate -**** */ +HD6309_INLINE void subd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1080 SUBW immediate -**** */ +HD6309_INLINE void subw_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $1083 CMPD immediate -**** */ +HD6309_INLINE void cmpd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1081 CMPW immediate -**** */ +HD6309_INLINE void cmpw_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1183 CMPU immediate -**** */ +HD6309_INLINE void cmpu_im( void ) +{ + UINT32 r, d; + PAIR b; + IMMWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $84 ANDA immediate -**0- */ +HD6309_INLINE void anda_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $85 BITA immediate -**0- */ +HD6309_INLINE void bita_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $86 LDA immediate -**0- */ +HD6309_INLINE void lda_im( void ) +{ + IMMBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $88 EORA immediate -**0- */ +HD6309_INLINE void eora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $89 ADCA immediate ***** */ +HD6309_INLINE void adca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8A ORA immediate -**0- */ +HD6309_INLINE void ora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $8B ADDA immediate ***** */ +HD6309_INLINE void adda_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8C CMPX (CMPY CMPS) immediate -**** */ +HD6309_INLINE void cmpx_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $108C CMPY immediate -**** */ +HD6309_INLINE void cmpy_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $118C CMPS immediate -**** */ +HD6309_INLINE void cmps_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $8D BSR ----- */ +HD6309_INLINE void bsr( void ) +{ + UINT8 t; + IMMBYTE(t); + PUSHWORD(pPC); + PC += SIGNED(t); + CHANGE_PC; +} + +/* $8E LDX (LDY) immediate -**0- */ +HD6309_INLINE void ldx_im( void ) +{ + IMMWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $CD LDQ immediate -**0- */ +HD6309_INLINE void ldq_im( void ) +{ + PAIR q; + + IMMLONG(q); + D = q.w.h; + W = q.w.l; + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $108E LDY immediate -**0- */ +HD6309_INLINE void ldy_im( void ) +{ + IMMWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $118f MULD immediate */ +HD6309_INLINE void muld_im( void ) +{ + PAIR t, q; + + IMMWORD( t ); + q.d = (INT16) D * (INT16)t.w.l; + D = q.w.h; + W = q.w.l; + CLR_NZVC; + SET_NZ16(D); +} + +/* $118d DIVD immediate */ +HD6309_INLINE void divd_im( void ) +{ + UINT8 t; + INT16 v, oldD; + + IMMBYTE( t ); + + if( t != 0 ) + { + oldD = D; + v = (INT16) D / (INT8) t; + A = (INT16) D % (INT8) t; + B = v; + + CLR_NZVC; + SET_NZ8(B); + + if( B & 0x01 ) + SEC; + + if( (INT16)D < 0 ) + SEN; + + if ( (v > 127) || (v < -128) ) /* soft overflow */ + { + SEV; + + if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */ + { + SET_NZ16( oldD ); + D = abs( oldD ); + } + } + } + else + { + hd6309_ICount -= 8; + DZError(); + } +} + +/* $118e DIVQ immediate */ +HD6309_INLINE void divq_im( void ) +{ + PAIR t,q, oldQ; + INT32 v; + + IMMWORD( t ); + + q.w.h = D; + q.w.l = W; + + if( t.w.l != 0 ) + { + oldQ = q; + + v = (INT32) q.d / (INT16) t.w.l; + D = (INT32) q.d % (INT16) t.w.l; + W = v; + + CLR_NZVC; + SET_NZ16(W); + + if( W & 0x0001 ) + SEC; + + if ( (v > 32768) || (v < -32767) ) /* soft overflow */ + { + SEV; + + if( (v > 65536 ) || (v < -65535 ) ) /* hard overflow - division is aborted */ + { + if( (INT32)oldQ.d < 0 ) + SEN; + else if( oldQ.d == 0 ) + SEZ; + + t.w.l = abs( t.w.l ); + D = oldQ.w.h; + W = oldQ.w.l; + } + } + } + else + DZError(); +} + +/* $90 SUBA direct ?**** */ +HD6309_INLINE void suba_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $91 CMPA direct ?**** */ +HD6309_INLINE void cmpa_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $92 SBCA direct ?**** */ +HD6309_INLINE void sbca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $93 SUBD (CMPD CMPU) direct -**** */ +HD6309_INLINE void subd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1090 SUBW direct -**** */ +HD6309_INLINE void subw_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $1093 CMPD direct -**** */ +HD6309_INLINE void cmpd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1091 CMPW direct -**** */ +HD6309_INLINE void cmpw_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1193 CMPU direct -**** */ +HD6309_INLINE void cmpu_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $94 ANDA direct -**0- */ +HD6309_INLINE void anda_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $95 BITA direct -**0- */ +HD6309_INLINE void bita_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $96 LDA direct -**0- */ +HD6309_INLINE void lda_di( void ) +{ + DIRBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $97 STA direct -**0- */ +HD6309_INLINE void sta_di( void ) +{ + CLR_NZV; + SET_NZ8(A); + DIRECT; + WM(EAD,A); +} + +/* $98 EORA direct -**0- */ +HD6309_INLINE void eora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $99 ADCA direct ***** */ +HD6309_INLINE void adca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9A ORA direct -**0- */ +HD6309_INLINE void ora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $9B ADDA direct ***** */ +HD6309_INLINE void adda_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9C CMPX (CMPY CMPS) direct -**** */ +HD6309_INLINE void cmpx_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $109C CMPY direct -**** */ +HD6309_INLINE void cmpy_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $119C CMPS direct -**** */ +HD6309_INLINE void cmps_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $9D JSR direct ----- */ +HD6309_INLINE void jsr_di( void ) +{ + DIRECT; + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $9E LDX (LDY) direct -**0- */ +HD6309_INLINE void ldx_di( void ) +{ + DIRWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $119f MULD direct -**0- */ +HD6309_INLINE void muld_di( void ) +{ + PAIR t,q; + + DIRWORD(t); + q.d = (INT16) D * (INT16)t.w.l; + + D = q.w.h; + W = q.w.l; + CLR_NZVC; + SET_NZ16(D); +} + +/* $119d DIVD direct -**0- */ +HD6309_INLINE void divd_di( void ) +{ + UINT8 t; + INT16 v, oldD; + + DIRBYTE(t); + + if( t != 0 ) + { + oldD = D; + v = (INT16) D / (INT8) t; + A = (INT16) D % (INT8) t; + B = v; + + CLR_NZVC; + SET_NZ8(B); + + if( B & 0x01 ) + SEC; + + if( (INT16)D < 0 ) + SEN; + + if ( (v > 127) || (v < -128) ) /* soft overflow */ + { + SEV; + + if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */ + { + SET_NZ16( oldD ); + D = abs( oldD ); + } + } + } + else + { + hd6309_ICount -= 8; + DZError(); + } +} + +/* $119e DIVQ direct -**0- */ +HD6309_INLINE void divq_di( void ) +{ + PAIR t,q, oldQ; + INT32 v; + + DIRWORD(t); + + q.w.h = D; + q.w.l = W; + + if( t.w.l != 0 ) + { + oldQ = q; + + v = (INT32) q.d / (INT16) t.w.l; + D = (INT32) q.d % (INT16) t.w.l; + W = v; + + CLR_NZVC; + SET_NZ16(W); + + if( W & 0x0001 ) + SEC; + + if ( (v > 32767) || (v < -32768) ) /* soft overflow */ + { + SEV; + + if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */ + { + if( (INT32)oldQ.d < 0 ) + SEN; + else if( oldQ.d == 0 ) + SEZ; + + t.w.l = abs( t.w.l ); + D = oldQ.w.h; + W = oldQ.w.l; + } + } + } + else + DZError(); +} +/* $10dc LDQ direct -**0- */ +HD6309_INLINE void ldq_di( void ) +{ + PAIR q; + + DIRLONG(q); + D = q.w.h; + W = q.w.l; + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $109E LDY direct -**0- */ +HD6309_INLINE void ldy_di( void ) +{ + DIRWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $9F STX (STY) direct -**0- */ +HD6309_INLINE void stx_di( void ) +{ + CLR_NZV; + SET_NZ16(X); + DIRECT; + WM16(EAD,&pX); +} + +/* $10dd STQ direct -**0- */ +HD6309_INLINE void stq_di( void ) +{ + PAIR q; + + q.w.h = D; + q.w.l = W; + DIRECT; + WM32(EAD,&q); + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $109F STY direct -**0- */ +HD6309_INLINE void sty_di( void ) +{ + CLR_NZV; + SET_NZ16(Y); + DIRECT; + WM16(EAD,&pY); +} + +/* $a0 SUBA indexed ?**** */ +HD6309_INLINE void suba_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a1 CMPA indexed ?**** */ +HD6309_INLINE void cmpa_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $a2 SBCA indexed ?**** */ +HD6309_INLINE void sbca_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a3 SUBD (CMPD CMPU) indexed -**** */ +HD6309_INLINE void subd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10a0 SUBW indexed -**** */ +HD6309_INLINE void subw_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $10a3 CMPD indexed -**** */ +HD6309_INLINE void cmpd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10a1 CMPW indexed -**** */ +HD6309_INLINE void cmpw_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11a3 CMPU indexed -**** */ +HD6309_INLINE void cmpu_ix( void ) +{ + UINT32 r; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + r = U - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $a4 ANDA indexed -**0- */ +HD6309_INLINE void anda_ix( void ) +{ + fetch_effective_address(); + A &= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a5 BITA indexed -**0- */ +HD6309_INLINE void bita_ix( void ) +{ + UINT8 r; + fetch_effective_address(); + r = A & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $a6 LDA indexed -**0- */ +HD6309_INLINE void lda_ix( void ) +{ + fetch_effective_address(); + A = RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a7 STA indexed -**0- */ +HD6309_INLINE void sta_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(A); + WM(EAD,A); +} + +/* $a8 EORA indexed -**0- */ +HD6309_INLINE void eora_ix( void ) +{ + fetch_effective_address(); + A ^= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a9 ADCA indexed ***** */ +HD6309_INLINE void adca_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aA ORA indexed -**0- */ +HD6309_INLINE void ora_ix( void ) +{ + fetch_effective_address(); + A |= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $aB ADDA indexed ***** */ +HD6309_INLINE void adda_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aC CMPX (CMPY CMPS) indexed -**** */ +HD6309_INLINE void cmpx_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10aC CMPY indexed -**** */ +HD6309_INLINE void cmpy_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11aC CMPS indexed -**** */ +HD6309_INLINE void cmps_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $aD JSR indexed ----- */ +HD6309_INLINE void jsr_ix( void ) +{ + fetch_effective_address(); + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $aE LDX (LDY) indexed -**0- */ +HD6309_INLINE void ldx_ix( void ) +{ + fetch_effective_address(); + X=RM16(EAD); + CLR_NZV; + SET_NZ16(X); +} + +/* $11af MULD indexed -**0- */ +HD6309_INLINE void muld_ix( void ) +{ + PAIR q; + UINT16 t; + + fetch_effective_address(); + t=RM16(EAD); + q.d = (INT16) D * (INT16)t; + + D = q.w.h; + W = q.w.l; + CLR_NZVC; + SET_NZ16(D); +} + +/* $11ad DIVD indexed -**0- */ +HD6309_INLINE void divd_ix( void ) +{ + UINT8 t; + INT16 v, oldD; + + fetch_effective_address(); + t=RM(EAD); + + if( t != 0 ) + { + oldD = D; + v = (INT16) D / (INT8) t; + A = (INT16) D % (INT8) t; + B = v; + + CLR_NZVC; + SET_NZ8(B); + + if( B & 0x01 ) + SEC; + + if( (INT16)D < 0 ) + SEN; + + if ( (v > 127) || (v < -128) ) /* soft overflow */ + { + SEV; + + if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */ + { + SET_NZ16( oldD ); + D = abs( oldD ); + } + } + } + else + { + hd6309_ICount -= 8; + DZError(); + } +} + +/* $11ae DIVQ indexed -**0- */ +HD6309_INLINE void divq_ix( void ) +{ + PAIR t,q, oldQ; + INT32 v; + + fetch_effective_address(); + t.w.l=RM16(EAD); + + q.w.h = D; + q.w.l = W; + + if( t.w.l != 0 ) + { + oldQ = q; + + v = (INT32) q.d / (INT16) t.w.l; + D = (INT32) q.d % (INT16) t.w.l; + W = v; + + CLR_NZVC; + SET_NZ16(W); + + if( W & 0x0001 ) + SEC; + + if ( (v > 32767) || (v < -32768) ) /* soft overflow */ + { + SEV; + + if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */ + { + if( (INT32)oldQ.d < 0 ) + SEN; + else if( oldQ.d == 0 ) + SEZ; + + t.w.l = abs( t.w.l ); + D = oldQ.w.h; + W = oldQ.w.l; + } + } + } + else + DZError(); +} + +/* $10ec LDQ indexed -**0- */ +HD6309_INLINE void ldq_ix( void ) +{ + PAIR q; + + fetch_effective_address(); + q.d=RM32(EAD); + D = q.w.h; + W = q.w.l; + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $10aE LDY indexed -**0- */ +HD6309_INLINE void ldy_ix( void ) +{ + fetch_effective_address(); + Y=RM16(EAD); + CLR_NZV; + SET_NZ16(Y); +} + +/* $aF STX (STY) indexed -**0- */ +HD6309_INLINE void stx_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(X); + WM16(EAD,&pX); +} + +/* $10ed STQ indexed -**0- */ +HD6309_INLINE void stq_ix( void ) +{ + PAIR q; + + q.w.h = D; + q.w.l = W; + fetch_effective_address(); + WM32(EAD,&q); + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $10aF STY indexed -**0- */ +HD6309_INLINE void sty_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(Y); + WM16(EAD,&pY); +} + +/* $b0 SUBA extended ?**** */ +HD6309_INLINE void suba_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b1 CMPA extended ?**** */ +HD6309_INLINE void cmpa_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $b2 SBCA extended ?**** */ +HD6309_INLINE void sbca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b3 SUBD (CMPD CMPU) extended -**** */ +HD6309_INLINE void subd_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10b0 SUBW extended -**** */ +HD6309_INLINE void subw_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $10b3 CMPD extended -**** */ +HD6309_INLINE void cmpd_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10b1 CMPW extended -**** */ +HD6309_INLINE void cmpw_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = W; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11b3 CMPU extended -**** */ +HD6309_INLINE void cmpu_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $b4 ANDA extended -**0- */ +HD6309_INLINE void anda_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b5 BITA extended -**0- */ +HD6309_INLINE void bita_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = A & t; + CLR_NZV; SET_NZ8(r); +} + +/* $b6 LDA extended -**0- */ +HD6309_INLINE void lda_ex( void ) +{ + EXTBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $b7 STA extended -**0- */ +HD6309_INLINE void sta_ex( void ) +{ + CLR_NZV; + SET_NZ8(A); + EXTENDED; + WM(EAD,A); +} + +/* $b8 EORA extended -**0- */ +HD6309_INLINE void eora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b9 ADCA extended ***** */ +HD6309_INLINE void adca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bA ORA extended -**0- */ +HD6309_INLINE void ora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $bB ADDA extended ***** */ +HD6309_INLINE void adda_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bC CMPX (CMPY CMPS) extended -**** */ +HD6309_INLINE void cmpx_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10bC CMPY extended -**** */ +HD6309_INLINE void cmpy_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11bC CMPS extended -**** */ +HD6309_INLINE void cmps_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $bD JSR extended ----- */ +HD6309_INLINE void jsr_ex( void ) +{ + EXTENDED; + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $bE LDX (LDY) extended -**0- */ +HD6309_INLINE void ldx_ex( void ) +{ + EXTWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $11bf MULD extended -**0- */ +HD6309_INLINE void muld_ex( void ) +{ + PAIR t, q; + + EXTWORD(t); + q.d = (INT16) D * (INT16)t.w.l; + + D = q.w.h; + W = q.w.l; + CLR_NZVC; + SET_NZ16(D); +} + +/* $11bd DIVD extended -**0- */ +HD6309_INLINE void divd_ex( void ) +{ + UINT8 t; + INT16 v, oldD; + + EXTBYTE(t); + + if( t != 0 ) + { + oldD = D; + v = (INT16) D / (INT8) t; + A = (INT16) D % (INT8) t; + B = v; + + CLR_NZVC; + SET_NZ8(B); + + if( B & 0x01 ) + SEC; + + if( (INT16)D < 0 ) + SEN; + + if ( (v > 127) || (v < -128) ) /* soft overflow */ + { + SEV; + + if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */ + { + SET_NZ16( oldD ); + D = abs( oldD ); + } + } + } + else + { + hd6309_ICount -= 8; + DZError(); + } +} + +/* $11be DIVQ extended -**0- */ +HD6309_INLINE void divq_ex( void ) +{ + PAIR t,q, oldQ; + INT32 v; + + EXTWORD(t); + + q.w.h = D; + q.w.l = W; + + if( t.w.l != 0 ) + { + oldQ = q; + + v = (INT32) q.d / (INT16) t.w.l; + D = (INT32) q.d % (INT16) t.w.l; + W = v; + + CLR_NZVC; + SET_NZ16(W); + + if( W & 0x0001 ) + SEC; + + if ( (v > 32767) || (v < -32768) ) /* soft overflow */ + { + SEV; + + if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */ + { + if( (INT32)oldQ.d < 0 ) + SEN; + else if( oldQ.d == 0 ) + SEZ; + + t.w.l = abs( t.w.l ); + D = oldQ.w.h; + W = oldQ.w.l; + } + } + } + else + DZError(); +} + +/* $10fc LDQ extended -**0- */ +HD6309_INLINE void ldq_ex( void ) +{ + PAIR q; + + EXTLONG(q); + D = q.w.h; + W = q.w.l; + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $10bE LDY extended -**0- */ +HD6309_INLINE void ldy_ex( void ) +{ + EXTWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $bF STX (STY) extended -**0- */ +HD6309_INLINE void stx_ex( void ) +{ + CLR_NZV; + SET_NZ16(X); + EXTENDED; + WM16(EAD,&pX); +} + +/* $10fd STQ extended -**0- */ +HD6309_INLINE void stq_ex( void ) +{ + PAIR q; + + q.w.h = D; + q.w.l = W; + EXTENDED; + WM32(EAD,&q); + CLR_NZV; + SET_N8(A); + SET_Z(q.d); +} + +/* $10bF STY extended -**0- */ +HD6309_INLINE void sty_ex( void ) +{ + CLR_NZV; + SET_NZ16(Y); + EXTENDED; + WM16(EAD,&pY); +} + +/* $c0 SUBB immediate ?**** */ +HD6309_INLINE void subb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $1180 SUBE immediate ?**** */ +HD6309_INLINE void sube_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); + E = r; +} + +/* $11C0 SUBF immediate ?**** */ +HD6309_INLINE void subf_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); + F = r; +} + +/* $c1 CMPB immediate ?**** */ +HD6309_INLINE void cmpb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $1181 CMPE immediate ?**** */ +HD6309_INLINE void cmpe_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = E - t; + CLR_NZVC; SET_FLAGS8(E,t,r); +} + +/* $11C1 CMPF immediate ?**** */ +HD6309_INLINE void cmpf_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = F - t; + CLR_NZVC; SET_FLAGS8(F,t,r); +} + +/* $c2 SBCB immediate ?**** */ +HD6309_INLINE void sbcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $1082 SBCD immediate ?**** */ +HD6309_INLINE void sbcd_im( void ) +{ + PAIR t; + UINT32 r; + IMMWORD(t); + r = D - t.w.l - (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $c3 ADDD immediate -**** */ +HD6309_INLINE void addd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $108b ADDW immediate -**** */ +HD6309_INLINE void addw_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = W; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $118b ADDE immediate -**** */ +HD6309_INLINE void adde_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = E + t; + CLR_HNZVC; + SET_FLAGS8(E,t,r); + SET_H(E,t,r); + E = r; +} + +/* $11Cb ADDF immediate -**** */ +HD6309_INLINE void addf_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = F + t; + CLR_HNZVC; + SET_FLAGS8(F,t,r); + SET_H(F,t,r); + F = r; +} + +/* $c4 ANDB immediate -**0- */ +HD6309_INLINE void andb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $1084 ANDD immediate -**0- */ +HD6309_INLINE void andd_im( void ) +{ + PAIR t; + IMMWORD(t); + D &= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $c5 BITB immediate -**0- */ +HD6309_INLINE void bitb_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $1085 BITD immediate -**0- */ +HD6309_INLINE void bitd_im( void ) +{ + PAIR t; + UINT16 r; + IMMWORD(t); + r = B & t.w.l; + CLR_NZV; + SET_NZ16(r); +} + +/* $113c BITMD immediate -**0- */ +HD6309_INLINE void bitmd_im( void ) +{ + /* + The following is from Darren A. + + The Z flag is the only condition code that should be affected by BITMD. + For example, when the "Divide-By-Zero" flag (bit 7) is set, BITMD should + not set the N flag. It should also NOT clear the V flag (unlike the other + BIT instructions). + + His comments come from experimentation and differ from Chris Burke + */ + + UINT8 t,r; + IMMBYTE(t); + r = MD & t; + CLR_Z; + SET_Z8(r); + + MD &= ~(r & 0xc0); /* clear the tested high bits */ + +} + +/* $c6 LDB immediate -**0- */ +HD6309_INLINE void ldb_im( void ) +{ + IMMBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $113d LDMD immediate -**0- */ +HD6309_INLINE void ldmd_im( void ) +{ + IMMBYTE(MD); + UpdateState(); +} + +/* $1186 LDE immediate -**0- */ +HD6309_INLINE void lde_im( void ) +{ + IMMBYTE(E); + CLR_NZV; + SET_NZ8(E); +} + +/* $11C6 LDF immediate -**0- */ +HD6309_INLINE void ldf_im( void ) +{ + IMMBYTE(F); + CLR_NZV; + SET_NZ8(F); +} + +/* $c8 EORB immediate -**0- */ +HD6309_INLINE void eorb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $1088 EORD immediate -**0- */ +HD6309_INLINE void eord_im( void ) +{ + PAIR t; + IMMWORD(t); + D ^= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $c9 ADCB immediate ***** */ +HD6309_INLINE void adcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $1089 ADCD immediate ***** */ +HD6309_INLINE void adcd_im( void ) +{ + PAIR t; + UINT32 r; + IMMWORD(t); + r = D + t.w.l + (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $cA ORB immediate -**0- */ +HD6309_INLINE void orb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $108a ORD immediate -**0- */ +HD6309_INLINE void ord_im( void ) +{ + PAIR t; + IMMWORD(t); + D |= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $cB ADDB immediate ***** */ +HD6309_INLINE void addb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $cC LDD immediate -**0- */ +HD6309_INLINE void ldd_im( void ) +{ + PAIR t; + + IMMWORD(t); + D=t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $1086 LDW immediate -**0- */ +HD6309_INLINE void ldw_im( void ) +{ + PAIR t; + IMMWORD(t); + W=t.w.l; + CLR_NZV; + SET_NZ16(W); +} + +/* $cE LDU (LDS) immediate -**0- */ +HD6309_INLINE void ldu_im( void ) +{ + IMMWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10cE LDS immediate -**0- */ +HD6309_INLINE void lds_im( void ) +{ + IMMWORD(pS); + CLR_NZV; + SET_NZ16(S); + hd6309.int_state |= HD6309_LDS; +} + +/* $d0 SUBB direct ?**** */ +HD6309_INLINE void subb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $1190 SUBE direct ?**** */ +HD6309_INLINE void sube_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); + E = r; +} + +/* $11d0 SUBF direct ?**** */ +HD6309_INLINE void subf_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); + F = r; +} + +/* $d1 CMPB direct ?**** */ +HD6309_INLINE void cmpb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $1191 CMPE direct ?**** */ +HD6309_INLINE void cmpe_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); +} + +/* $11D1 CMPF direct ?**** */ +HD6309_INLINE void cmpf_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); +} + +/* $d2 SBCB direct ?**** */ +HD6309_INLINE void sbcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $1092 SBCD direct ?**** */ +HD6309_INLINE void sbcd_di( void ) +{ + PAIR t; + UINT32 r; + DIRWORD(t); + r = D - t.w.l - (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $d3 ADDD direct -**** */ +HD6309_INLINE void addd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $109b ADDW direct -**** */ +HD6309_INLINE void addw_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = W; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $119b ADDE direct -**** */ +HD6309_INLINE void adde_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = E + t; + CLR_HNZVC; + SET_FLAGS8(E,t,r); + SET_H(E,t,r); + E = r; +} + +/* $11db ADDF direct -**** */ +HD6309_INLINE void addf_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = F + t; + CLR_HNZVC; + SET_FLAGS8(F,t,r); + SET_H(F,t,r); + F = r; +} + +/* $d4 ANDB direct -**0- */ +HD6309_INLINE void andb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $1094 ANDD direct -**0- */ +HD6309_INLINE void andd_di( void ) +{ + PAIR t; + DIRWORD(t); + D &= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $d5 BITB direct -**0- */ +HD6309_INLINE void bitb_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $1095 BITD direct -**0- */ +HD6309_INLINE void bitd_di( void ) +{ + PAIR t; + UINT16 r; + DIRWORD(t); + r = B & t.w.l; + CLR_NZV; + SET_NZ16(r); +} + +/* $d6 LDB direct -**0- */ +HD6309_INLINE void ldb_di( void ) +{ + DIRBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $1196 LDE direct -**0- */ +HD6309_INLINE void lde_di( void ) +{ + DIRBYTE(E); + CLR_NZV; + SET_NZ8(E); +} + +/* $11d6 LDF direct -**0- */ +HD6309_INLINE void ldf_di( void ) +{ + DIRBYTE(F); + CLR_NZV; + SET_NZ8(F); +} + +/* $d7 STB direct -**0- */ +HD6309_INLINE void stb_di( void ) +{ + CLR_NZV; + SET_NZ8(B); + DIRECT; + WM(EAD,B); +} + +/* $1197 STE direct -**0- */ +HD6309_INLINE void ste_di( void ) +{ + CLR_NZV; + SET_NZ8(E); + DIRECT; + WM(EAD,E); +} + +/* $11D7 STF direct -**0- */ +HD6309_INLINE void stf_di( void ) +{ + CLR_NZV; + SET_NZ8(F); + DIRECT; + WM(EAD,F); +} + +/* $d8 EORB direct -**0- */ +HD6309_INLINE void eorb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $1098 EORD direct -**0- */ +HD6309_INLINE void eord_di( void ) +{ + PAIR t; + DIRWORD(t); + D ^= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $d9 ADCB direct ***** */ +HD6309_INLINE void adcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $1099 adcd direct ***** */ +HD6309_INLINE void adcd_di( void ) +{ + UINT32 r; + PAIR t; + + DIRWORD(t); + r = D + t.w.l + (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $dA ORB direct -**0- */ +HD6309_INLINE void orb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $109a ORD direct -**0- */ +HD6309_INLINE void ord_di( void ) +{ + PAIR t; + DIRWORD(t); + D |= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $dB ADDB direct ***** */ +HD6309_INLINE void addb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $dC LDD direct -**0- */ +HD6309_INLINE void ldd_di( void ) +{ + PAIR t; + DIRWORD(t); + D=t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $1096 LDW direct -**0- */ +HD6309_INLINE void ldw_di( void ) +{ + PAIR t; + DIRWORD(t); + W=t.w.l; + CLR_NZV; + SET_NZ16(W); +} + +/* $dD STD direct -**0- */ +HD6309_INLINE void std_di( void ) +{ + CLR_NZV; + SET_NZ16(D); + DIRECT; + WM16(EAD,&pD); +} + +/* $1097 STW direct -**0- */ +HD6309_INLINE void stw_di( void ) +{ + CLR_NZV; + SET_NZ16(W); + DIRECT; + WM16(EAD,&pW); +} + +/* $dE LDU (LDS) direct -**0- */ +HD6309_INLINE void ldu_di( void ) +{ + DIRWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10dE LDS direct -**0- */ +HD6309_INLINE void lds_di( void ) +{ + DIRWORD(pS); + CLR_NZV; + SET_NZ16(S); + hd6309.int_state |= HD6309_LDS; +} + +/* $dF STU (STS) direct -**0- */ +HD6309_INLINE void stu_di( void ) +{ + CLR_NZV; + SET_NZ16(U); + DIRECT; + WM16(EAD,&pU); +} + +/* $10dF STS direct -**0- */ +HD6309_INLINE void sts_di( void ) +{ + CLR_NZV; + SET_NZ16(S); + DIRECT; + WM16(EAD,&pS); +} + +/* $e0 SUBB indexed ?**** */ +HD6309_INLINE void subb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $11a0 SUBE indexed ?**** */ +HD6309_INLINE void sube_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); + E = r; +} + +/* $11e0 SUBF indexed ?**** */ +HD6309_INLINE void subf_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); + F = r; +} + +/* $e1 CMPB indexed ?**** */ +HD6309_INLINE void cmpb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $11a1 CMPE indexed ?**** */ +HD6309_INLINE void cmpe_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); +} + +/* $11e1 CMPF indexed ?**** */ +HD6309_INLINE void cmpf_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); +} + +/* $e2 SBCB indexed ?**** */ +HD6309_INLINE void sbcb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $10a2 SBCD indexed ?**** */ +HD6309_INLINE void sbcd_ix( void ) +{ + UINT32 t,r; + fetch_effective_address(); + t = RM16(EAD); + r = D - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t,r); + D = r; +} + +/* $e3 ADDD indexed -**** */ +HD6309_INLINE void addd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10ab ADDW indexed -**** */ +HD6309_INLINE void addw_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = W; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $11ab ADDE indexed -**** */ +HD6309_INLINE void adde_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = E + t; + CLR_HNZVC; + SET_FLAGS8(E,t,r); + SET_H(E,t,r); + E = r; +} + +/* $11eb ADDF indexed -**** */ +HD6309_INLINE void addf_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = F + t; + CLR_HNZVC; + SET_FLAGS8(F,t,r); + SET_H(F,t,r); + F = r; +} + +/* $e4 ANDB indexed -**0- */ +HD6309_INLINE void andb_ix( void ) +{ + fetch_effective_address(); + B &= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $10a4 ANDD indexed -**0- */ +HD6309_INLINE void andd_ix( void ) +{ + fetch_effective_address(); + D &= RM16(EAD); + CLR_NZV; + SET_NZ16(D); +} + +/* $e5 BITB indexed -**0- */ +HD6309_INLINE void bitb_ix( void ) +{ + UINT8 r; + fetch_effective_address(); + r = B & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $10a5 BITD indexed -**0- */ +HD6309_INLINE void bitd_ix( void ) +{ + UINT16 r; + fetch_effective_address(); + r = D & RM16(EAD); + CLR_NZV; + SET_NZ16(r); +} + +/* $e6 LDB indexed -**0- */ +HD6309_INLINE void ldb_ix( void ) +{ + fetch_effective_address(); + B = RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $11a6 LDE indexed -**0- */ +HD6309_INLINE void lde_ix( void ) +{ + fetch_effective_address(); + E = RM(EAD); + CLR_NZV; + SET_NZ8(E); +} + +/* $11e6 LDF indexed -**0- */ +HD6309_INLINE void ldf_ix( void ) +{ + fetch_effective_address(); + F = RM(EAD); + CLR_NZV; + SET_NZ8(F); +} + +/* $e7 STB indexed -**0- */ +HD6309_INLINE void stb_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(B); + WM(EAD,B); +} + +/* $11a7 STE indexed -**0- */ +HD6309_INLINE void ste_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(E); + WM(EAD,E); +} + +/* $11e7 STF indexed -**0- */ +HD6309_INLINE void stf_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(F); + WM(EAD,F); +} + +/* $e8 EORB indexed -**0- */ +HD6309_INLINE void eorb_ix( void ) +{ + fetch_effective_address(); + B ^= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $10a8 EORD indexed -**0- */ +HD6309_INLINE void eord_ix( void ) +{ + fetch_effective_address(); + D ^= RM16(EAD); + CLR_NZV; + SET_NZ16(D); +} + +/* $e9 ADCB indexed ***** */ +HD6309_INLINE void adcb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $10a9 ADCD indexed ***** */ +HD6309_INLINE void adcd_ix( void ) +{ + UINT32 r; + PAIR t; + fetch_effective_address(); + t.d = RM16(EAD); + r = D + t.d + (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.d,r); + D = r; +} + +/* $eA ORB indexed -**0- */ +HD6309_INLINE void orb_ix( void ) +{ + fetch_effective_address(); + B |= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $10aa ORD indexed -**0- */ +HD6309_INLINE void ord_ix( void ) +{ + fetch_effective_address(); + D |= RM16(EAD); + CLR_NZV; + SET_NZ16(D); +} + +/* $eB ADDB indexed ***** */ +HD6309_INLINE void addb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $eC LDD indexed -**0- */ +HD6309_INLINE void ldd_ix( void ) +{ + fetch_effective_address(); + D=RM16(EAD); + CLR_NZV; SET_NZ16(D); +} + +/* $10a6 LDW indexed -**0- */ +HD6309_INLINE void ldw_ix( void ) +{ + fetch_effective_address(); + W=RM16(EAD); + CLR_NZV; SET_NZ16(W); +} + +/* $eD STD indexed -**0- */ +HD6309_INLINE void std_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&pD); +} + +/* $10a7 STW indexed -**0- */ +HD6309_INLINE void stw_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(W); + WM16(EAD,&pW); +} + +/* $eE LDU (LDS) indexed -**0- */ +HD6309_INLINE void ldu_ix( void ) +{ + fetch_effective_address(); + U=RM16(EAD); + CLR_NZV; + SET_NZ16(U); +} + +/* $10eE LDS indexed -**0- */ +HD6309_INLINE void lds_ix( void ) +{ + fetch_effective_address(); + S=RM16(EAD); + CLR_NZV; + SET_NZ16(S); + hd6309.int_state |= HD6309_LDS; +} + +/* $eF STU (STS) indexed -**0- */ +HD6309_INLINE void stu_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(U); + WM16(EAD,&pU); +} + +/* $10eF STS indexed -**0- */ +HD6309_INLINE void sts_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(S); + WM16(EAD,&pS); +} + +/* $f0 SUBB extended ?**** */ +HD6309_INLINE void subb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $11b0 SUBE extended ?**** */ +HD6309_INLINE void sube_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); + E = r; +} + +/* $11f0 SUBF extended ?**** */ +HD6309_INLINE void subf_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); + F = r; +} + +/* $f1 CMPB extended ?**** */ +HD6309_INLINE void cmpb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $11b1 CMPE extended ?**** */ +HD6309_INLINE void cmpe_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = E - t; + CLR_NZVC; + SET_FLAGS8(E,t,r); +} + +/* $11f1 CMPF extended ?**** */ +HD6309_INLINE void cmpf_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = F - t; + CLR_NZVC; + SET_FLAGS8(F,t,r); +} + +/* $f2 SBCB extended ?**** */ +HD6309_INLINE void sbcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $10b2 SBCD extended ?**** */ +HD6309_INLINE void sbcd_ex( void ) +{ + PAIR t = {{0,0,0,0}}; + UINT32 r; + + EXTWORD(t); + r = D - t.w.l - (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $f3 ADDD extended -**** */ +HD6309_INLINE void addd_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10bb ADDW extended -**** */ +HD6309_INLINE void addw_ex( void ) +{ + UINT32 r,d; + PAIR b = {{0,0,0,0}}; + EXTWORD(b); + d = W; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + W = r; +} + +/* $11bb ADDE extended -**** */ +HD6309_INLINE void adde_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = E + t; + CLR_HNZVC; + SET_FLAGS8(E,t,r); + SET_H(E,t,r); + E = r; +} + +/* $11fb ADDF extended -**** */ +HD6309_INLINE void addf_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = F + t; + CLR_HNZVC; + SET_FLAGS8(F,t,r); + SET_H(F,t,r); + F = r; +} + +/* $f4 ANDB extended -**0- */ +HD6309_INLINE void andb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $10b4 ANDD extended -**0- */ +HD6309_INLINE void andd_ex( void ) +{ + PAIR t = {{0,0,0,0}}; + EXTWORD(t); + D &= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $f5 BITB extended -**0- */ +HD6309_INLINE void bitb_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $10b5 BITD extended -**0- */ +HD6309_INLINE void bitd_ex( void ) +{ + PAIR t = {{0,0,0,0}}; + UINT8 r; + EXTWORD(t); + r = B & t.w.l; + CLR_NZV; + SET_NZ16(r); +} + +/* $f6 LDB extended -**0- */ +HD6309_INLINE void ldb_ex( void ) +{ + EXTBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $11b6 LDE extended -**0- */ +HD6309_INLINE void lde_ex( void ) +{ + EXTBYTE(E); + CLR_NZV; + SET_NZ8(E); +} + +/* $11f6 LDF extended -**0- */ +HD6309_INLINE void ldf_ex( void ) +{ + EXTBYTE(F); + CLR_NZV; + SET_NZ8(F); +} + +/* $f7 STB extended -**0- */ +HD6309_INLINE void stb_ex( void ) +{ + CLR_NZV; + SET_NZ8(B); + EXTENDED; + WM(EAD,B); +} + +/* $11b7 STE extended -**0- */ +HD6309_INLINE void ste_ex( void ) +{ + CLR_NZV; + SET_NZ8(E); + EXTENDED; + WM(EAD,E); +} + +/* $11f7 STF extended -**0- */ +HD6309_INLINE void stf_ex( void ) +{ + CLR_NZV; + SET_NZ8(F); + EXTENDED; + WM(EAD,F); +} + +/* $f8 EORB extended -**0- */ +HD6309_INLINE void eorb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $10b8 EORD extended -**0- */ +HD6309_INLINE void eord_ex( void ) +{ + PAIR t = {{0,0,0,0}}; + EXTWORD(t); + D ^= t.w.l; + CLR_NZV; + SET_NZ16(D); +} + +/* $f9 ADCB extended ***** */ +HD6309_INLINE void adcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $10b9 ADCD extended ***** */ +HD6309_INLINE void adcd_ex( void ) +{ + UINT32 r; + PAIR t; + EXTWORD(t); + r = D + t.w.l + (CC & CC_C); + CLR_NZVC; + SET_FLAGS16(D,t.w.l,r); + D = r; +} + +/* $fA ORB extended -**0- */ +HD6309_INLINE void orb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $10ba ORD extended -**0- */ +HD6309_INLINE void ord_ex( void ) +{ + PAIR t = {{0,0,0,0}}; + EXTWORD(t); + D |= t.w.l; + CLR_NZV; + SET_NZ8(D); +} + +/* $fB ADDB extended ***** */ +HD6309_INLINE void addb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $fC LDD extended -**0- */ +HD6309_INLINE void ldd_ex( void ) +{ + EXTWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* $10b6 LDW extended -**0- */ +HD6309_INLINE void ldw_ex( void ) +{ + EXTWORD(pW); + CLR_NZV; + SET_NZ16(W); +} + +/* $fD STD extended -**0- */ +HD6309_INLINE void std_ex( void ) +{ + CLR_NZV; + SET_NZ16(D); + EXTENDED; + WM16(EAD,&pD); +} + +/* $10b7 STW extended -**0- */ +HD6309_INLINE void stw_ex( void ) +{ + CLR_NZV; + SET_NZ16(W); + EXTENDED; + WM16(EAD,&pW); +} + +/* $fE LDU (LDS) extended -**0- */ +HD6309_INLINE void ldu_ex( void ) +{ + EXTWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10fE LDS extended -**0- */ +HD6309_INLINE void lds_ex( void ) +{ + EXTWORD(pS); + CLR_NZV; + SET_NZ16(S); + hd6309.int_state |= HD6309_LDS; +} + +/* $fF STU (STS) extended -**0- */ +HD6309_INLINE void stu_ex( void ) +{ + CLR_NZV; + SET_NZ16(U); + EXTENDED; + WM16(EAD,&pU); +} + +/* $10fF STS extended -**0- */ +HD6309_INLINE void sts_ex( void ) +{ + CLR_NZV; + SET_NZ16(S); + EXTENDED; + WM16(EAD,&pS); +} + +/* $10xx opcodes */ +HD6309_INLINE void pref10( void ) +{ + UINT8 ireg2 = ROP(PCD); + PC++; + +#ifdef BIG_SWITCH + switch( ireg2 ) + { + case 0x21: lbrn(); break; + case 0x22: lbhi(); break; + case 0x23: lbls(); break; + case 0x24: lbcc(); break; + case 0x25: lbcs(); break; + case 0x26: lbne(); break; + case 0x27: lbeq(); break; + case 0x28: lbvc(); break; + case 0x29: lbvs(); break; + case 0x2a: lbpl(); break; + case 0x2b: lbmi(); break; + case 0x2c: lbge(); break; + case 0x2d: lblt(); break; + case 0x2e: lbgt(); break; + case 0x2f: lble(); break; + + case 0x30: addr_r(); break; + case 0x31: adcr(); break; + case 0x32: subr(); break; + case 0x33: sbcr(); break; + case 0x34: andr(); break; + case 0x35: orr(); break; + case 0x36: eorr(); break; + case 0x37: cmpr(); break; + case 0x38: pshsw(); break; + case 0x39: pulsw(); break; + case 0x3a: pshuw(); break; + case 0x3b: puluw(); break; + case 0x3f: swi2(); break; + + case 0x40: negd(); break; + case 0x43: comd(); break; + case 0x44: lsrd(); break; + case 0x46: rord(); break; + case 0x47: asrd(); break; + case 0x48: asld(); break; + case 0x49: rold(); break; + case 0x4a: decd(); break; + case 0x4c: incd(); break; + case 0x4d: tstd(); break; + case 0x4f: clrd(); break; + + case 0x53: comw(); break; + case 0x54: lsrw(); break; + case 0x56: rorw(); break; + case 0x59: rolw(); break; + case 0x5a: decw(); break; + case 0x5c: incw(); break; + case 0x5d: tstw(); break; + case 0x5f: clrw(); break; + + case 0x80: subw_im(); break; + case 0x81: cmpw_im(); break; + case 0x82: sbcd_im(); break; + case 0x83: cmpd_im(); break; + case 0x84: andd_im(); break; + case 0x85: bitd_im(); break; + case 0x86: ldw_im(); break; + case 0x88: eord_im(); break; + case 0x89: adcd_im(); break; + case 0x8a: ord_im(); break; + case 0x8b: addw_im(); break; + case 0x8c: cmpy_im(); break; + case 0x8e: ldy_im(); break; + + case 0x90: subw_di(); break; + case 0x91: cmpw_di(); break; + case 0x92: sbcd_di(); break; + case 0x93: cmpd_di(); break; + case 0x94: andd_di(); break; + case 0x95: bitd_di(); break; + case 0x96: ldw_di(); break; + case 0x97: stw_di(); break; + case 0x98: eord_di(); break; + case 0x99: adcd_di(); break; + case 0x9a: ord_di(); break; + case 0x9b: addw_di(); break; + case 0x9c: cmpy_di(); break; + case 0x9e: ldy_di(); break; + case 0x9f: sty_di(); break; + + case 0xa0: subw_ix(); break; + case 0xa1: cmpw_ix(); break; + case 0xa2: sbcd_ix(); break; + case 0xa3: cmpd_ix(); break; + case 0xa4: andd_ix(); break; + case 0xa5: bitd_ix(); break; + case 0xa6: ldw_ix(); break; + case 0xa7: stw_ix(); break; + case 0xa8: eord_ix(); break; + case 0xa9: adcd_ix(); break; + case 0xaa: ord_ix(); break; + case 0xab: addw_ix(); break; + case 0xac: cmpy_ix(); break; + case 0xae: ldy_ix(); break; + case 0xaf: sty_ix(); break; + + case 0xb0: subw_ex(); break; + case 0xb1: cmpw_ex(); break; + case 0xb2: sbcd_ex(); break; + case 0xb3: cmpd_ex(); break; + case 0xb4: andd_ex(); break; + case 0xb5: bitd_ex(); break; + case 0xb6: ldw_ex(); break; + case 0xb7: stw_ex(); break; + case 0xb8: eord_ex(); break; + case 0xb9: adcd_ex(); break; + case 0xba: ord_ex(); break; + case 0xbb: addw_ex(); break; + case 0xbc: cmpy_ex(); break; + case 0xbe: ldy_ex(); break; + case 0xbf: sty_ex(); break; + + case 0xce: lds_im(); break; + + case 0xdc: ldq_di(); break; + case 0xdd: stq_di(); break; + case 0xde: lds_di(); break; + case 0xdf: sts_di(); break; + + case 0xec: ldq_ix(); break; + case 0xed: stq_ix(); break; + case 0xee: lds_ix(); break; + case 0xef: sts_ix(); break; + + case 0xfc: ldq_ex(); break; + case 0xfd: stq_ex(); break; + case 0xfe: lds_ex(); break; + case 0xff: sts_ex(); break; + + default: IIError(); break; + } +#else + + (*hd6309_page01[ireg2])(); + +#endif /* BIG_SWITCH */ + + hd6309_ICount -= cycle_counts_page01[ireg2]; +} + +/* $11xx opcodes */ +HD6309_INLINE void pref11( void ) +{ + UINT8 ireg2 = ROP(PCD); + PC++; + +#ifdef BIG_SWITCH + switch( ireg2 ) + { + case 0x30: band(); break; + case 0x31: biand(); break; + case 0x32: bor(); break; + case 0x33: bior(); break; + case 0x34: beor(); break; + case 0x35: bieor(); break; + case 0x36: ldbt(); break; + case 0x37: stbt(); break; + case 0x38: tfmpp(); break; /* Timing for TFM is actually 6+3n. */ + case 0x39: tfmmm(); break; /* To avoid saving the state, I decided */ + case 0x3a: tfmpc(); break; /* to push the initial 6 cycles to the end */ + case 0x3b: tfmcp(); break; /* We will soon see how this fairs! */ + case 0x3c: bitmd_im(); break; + case 0x3d: ldmd_im(); break; + case 0x3f: swi3(); break; + + case 0x43: come(); break; + case 0x4a: dece(); break; + case 0x4c: ince(); break; + case 0x4d: tste(); break; + case 0x4f: clre(); break; + + case 0x53: comf(); break; + case 0x5a: decf(); break; + case 0x5c: incf(); break; + case 0x5d: tstf(); break; + case 0x5f: clrf(); break; + + case 0x80: sube_im(); break; + case 0x81: cmpe_im(); break; + case 0x83: cmpu_im(); break; + case 0x86: lde_im(); break; + case 0x8b: adde_im(); break; + case 0x8c: cmps_im(); break; + case 0x8d: divd_im(); break; + case 0x8e: divq_im(); break; + case 0x8f: muld_im(); break; + + case 0x90: sube_di(); break; + case 0x91: cmpe_di(); break; + case 0x93: cmpu_di(); break; + case 0x96: lde_di(); break; + case 0x97: ste_di(); break; + case 0x9b: adde_di(); break; + case 0x9c: cmps_di(); break; + case 0x9d: divd_di(); break; + case 0x9e: divq_di(); break; + case 0x9f: muld_di(); break; + + case 0xa0: sube_ix(); break; + case 0xa1: cmpe_ix(); break; + case 0xa3: cmpu_ix(); break; + case 0xa6: lde_ix(); break; + case 0xa7: ste_ix(); break; + case 0xab: adde_ix(); break; + case 0xac: cmps_ix(); break; + case 0xad: divd_ix(); break; + case 0xae: divq_ix(); break; + case 0xaf: muld_ix(); break; + + case 0xb0: sube_ex(); break; + case 0xb1: cmpe_ex(); break; + case 0xb3: cmpu_ex(); break; + case 0xb6: lde_ex(); break; + case 0xb7: ste_ex(); break; + case 0xbb: adde_ex(); break; + case 0xbc: cmps_ex(); break; + case 0xbd: divd_ex(); break; + case 0xbe: divq_ex(); break; + case 0xbf: muld_ex(); break; + + case 0xc0: subf_im(); break; + case 0xc1: cmpf_im(); break; + case 0xc6: ldf_im(); break; + case 0xcb: addf_im(); break; + + case 0xd0: subf_di(); break; + case 0xd1: cmpf_di(); break; + case 0xd6: ldf_di(); break; + case 0xd7: stf_di(); break; + case 0xdb: addf_di(); break; + + case 0xe0: subf_ix(); break; + case 0xe1: cmpf_ix(); break; + case 0xe6: ldf_ix(); break; + case 0xe7: stf_ix(); break; + case 0xeb: addf_ix(); break; + + case 0xf0: subf_ex(); break; + case 0xf1: cmpf_ex(); break; + case 0xf6: ldf_ex(); break; + case 0xf7: stf_ex(); break; + case 0xfb: addf_ex(); break; + + default: IIError(); break; + } +#else + + (*hd6309_page11[ireg2])(); + +#endif /* BIG_SWITCH */ + hd6309_ICount -= cycle_counts_page11[ireg2]; +} + diff --git a/src/cpu/hd6309/6309tbl.c b/src/cpu/hd6309/6309tbl.c new file mode 100644 index 00000000..38537614 --- /dev/null +++ b/src/cpu/hd6309/6309tbl.c @@ -0,0 +1,814 @@ +HD6309_INLINE void illegal( void ); +HD6309_INLINE void neg_di( void ); +HD6309_INLINE void oim_di( void ); +HD6309_INLINE void aim_di( void ); +HD6309_INLINE void com_di( void ); +HD6309_INLINE void lsr_di( void ); +HD6309_INLINE void eim_di( void ); +HD6309_INLINE void ror_di( void ); +HD6309_INLINE void asr_di( void ); +HD6309_INLINE void asl_di( void ); +HD6309_INLINE void rol_di( void ); +HD6309_INLINE void dec_di( void ); +HD6309_INLINE void tim_di( void ); +HD6309_INLINE void inc_di( void ); +HD6309_INLINE void tst_di( void ); +HD6309_INLINE void jmp_di( void ); +HD6309_INLINE void clr_di( void ); +HD6309_INLINE void nop( void ); +HD6309_INLINE void sync( void ); +HD6309_INLINE void sexw( void ); +HD6309_INLINE void lbra( void ); +HD6309_INLINE void lbsr( void ); +HD6309_INLINE void daa( void ); +HD6309_INLINE void daa( void ); +HD6309_INLINE void orcc( void ); +HD6309_INLINE void andcc( void ); +HD6309_INLINE void sex( void ); +HD6309_INLINE void exg( void ); +HD6309_INLINE void tfr( void ); +HD6309_INLINE void bra( void ); +HD6309_INLINE void brn( void ); +HD6309_INLINE void lbrn( void ); +HD6309_INLINE void bhi( void ); +HD6309_INLINE void lbhi( void ); +HD6309_INLINE void bls( void ); +HD6309_INLINE void lbls( void ); +HD6309_INLINE void bcc( void ); +HD6309_INLINE void lbcc( void ); +HD6309_INLINE void bcs( void ); +HD6309_INLINE void lbcs( void ); +HD6309_INLINE void bne( void ); +HD6309_INLINE void lbne( void ); +HD6309_INLINE void beq( void ); +HD6309_INLINE void lbeq( void ); +HD6309_INLINE void bvc( void ); +HD6309_INLINE void lbvc( void ); +HD6309_INLINE void bvs( void ); +HD6309_INLINE void lbvs( void ); +HD6309_INLINE void bpl( void ); +HD6309_INLINE void lbpl( void ); +HD6309_INLINE void bmi( void ); +HD6309_INLINE void lbmi( void ); +HD6309_INLINE void bge( void ); +HD6309_INLINE void lbge( void ); +HD6309_INLINE void blt( void ); +HD6309_INLINE void lblt( void ); +HD6309_INLINE void bgt( void ); +HD6309_INLINE void lbgt( void ); +HD6309_INLINE void ble( void ); +HD6309_INLINE void lble( void ); +HD6309_INLINE void addr_r( void ); +HD6309_INLINE void adcr( void ); +HD6309_INLINE void subr( void ); +HD6309_INLINE void sbcr( void ); +HD6309_INLINE void andr( void ); +HD6309_INLINE void orr( void ); +HD6309_INLINE void eorr( void ); +HD6309_INLINE void cmpr( void ); +HD6309_INLINE void tfmpp( void ); +HD6309_INLINE void tfmmm( void ); +HD6309_INLINE void tfmpc( void ); +HD6309_INLINE void tfmcp( void ); +HD6309_INLINE void bitmd_im( void ); +HD6309_INLINE void leax( void ); +HD6309_INLINE void leay( void ); +HD6309_INLINE void leas( void ); +HD6309_INLINE void leau( void ); +HD6309_INLINE void pshs( void ); +HD6309_INLINE void ldmd_im( void ); +HD6309_INLINE void pshsw( void ); +HD6309_INLINE void pshuw( void ); +HD6309_INLINE void puls( void ); +HD6309_INLINE void pulsw( void ); +HD6309_INLINE void puluw( void ); +HD6309_INLINE void pshu( void ); +HD6309_INLINE void pulu( void ); +HD6309_INLINE void rts( void ); +HD6309_INLINE void abx( void ); +HD6309_INLINE void rti( void ); +HD6309_INLINE void cwai( void ); +HD6309_INLINE void bitd_di( void ); +HD6309_INLINE void bitd_ix( void ); +HD6309_INLINE void bitd_ex( void ); +HD6309_INLINE void mul( void ); +HD6309_INLINE void swi( void ); +HD6309_INLINE void band( void ); +HD6309_INLINE void bitd_im( void ); +HD6309_INLINE void biand( void ); +HD6309_INLINE void bor( void ); +HD6309_INLINE void bior( void ); +HD6309_INLINE void beor( void ); +HD6309_INLINE void bieor( void ); +HD6309_INLINE void ldbt( void ); +HD6309_INLINE void stbt( void ); +HD6309_INLINE void swi2( void ); +HD6309_INLINE void swi3( void ); +HD6309_INLINE void nega( void ); +HD6309_INLINE void coma( void ); +HD6309_INLINE void lsra( void ); +HD6309_INLINE void rora( void ); +HD6309_INLINE void asra( void ); +HD6309_INLINE void asla( void ); +HD6309_INLINE void rola( void ); +HD6309_INLINE void deca( void ); +HD6309_INLINE void inca( void ); +HD6309_INLINE void tsta( void ); +HD6309_INLINE void clra( void ); +HD6309_INLINE void negb( void ); +HD6309_INLINE void negd( void ); +HD6309_INLINE void comb( void ); +HD6309_INLINE void come( void ); +HD6309_INLINE void comf( void ); +HD6309_INLINE void comd( void ); +HD6309_INLINE void comw( void ); +HD6309_INLINE void lsrb( void ); +HD6309_INLINE void lsrd( void ); +HD6309_INLINE void lsrw( void ); +HD6309_INLINE void rorb( void ); +HD6309_INLINE void rord( void ); +HD6309_INLINE void rorw( void ); +HD6309_INLINE void asrb( void ); +HD6309_INLINE void asrd( void ); +HD6309_INLINE void aslb( void ); +HD6309_INLINE void asld( void ); +HD6309_INLINE void rolb( void ); +HD6309_INLINE void rold( void ); +HD6309_INLINE void rolw( void ); +HD6309_INLINE void decb( void ); +HD6309_INLINE void dece( void ); +HD6309_INLINE void decf( void ); +HD6309_INLINE void decd( void ); +HD6309_INLINE void decw( void ); +HD6309_INLINE void incb( void ); +HD6309_INLINE void ince( void ); +HD6309_INLINE void incf( void ); +HD6309_INLINE void incd( void ); +HD6309_INLINE void incw( void ); +HD6309_INLINE void tstb( void ); +HD6309_INLINE void tstd( void ); +HD6309_INLINE void tstw( void ); +HD6309_INLINE void tste( void ); +HD6309_INLINE void tstf( void ); +HD6309_INLINE void clrb( void ); +HD6309_INLINE void clrd( void ); +HD6309_INLINE void clre( void ); +HD6309_INLINE void clrf( void ); +HD6309_INLINE void clrw( void ); +HD6309_INLINE void neg_ix( void ); +HD6309_INLINE void oim_ix( void ); +HD6309_INLINE void aim_ix( void ); +HD6309_INLINE void com_ix( void ); +HD6309_INLINE void lsr_ix( void ); +HD6309_INLINE void eim_ix( void ); +HD6309_INLINE void ror_ix( void ); +HD6309_INLINE void asr_ix( void ); +HD6309_INLINE void asl_ix( void ); +HD6309_INLINE void rol_ix( void ); +HD6309_INLINE void dec_ix( void ); +HD6309_INLINE void tim_ix( void ); +HD6309_INLINE void inc_ix( void ); +HD6309_INLINE void tst_ix( void ); +HD6309_INLINE void jmp_ix( void ); +HD6309_INLINE void clr_ix( void ); +HD6309_INLINE void neg_ex( void ); +HD6309_INLINE void oim_ex( void ); +HD6309_INLINE void aim_ex( void ); +HD6309_INLINE void com_ex( void ); +HD6309_INLINE void lsr_ex( void ); +HD6309_INLINE void eim_ex( void ); +HD6309_INLINE void ror_ex( void ); +HD6309_INLINE void asr_ex( void ); +HD6309_INLINE void asl_ex( void ); +HD6309_INLINE void rol_ex( void ); +HD6309_INLINE void dec_ex( void ); +HD6309_INLINE void tim_ex( void ); +HD6309_INLINE void inc_ex( void ); +HD6309_INLINE void tst_ex( void ); +HD6309_INLINE void jmp_ex( void ); +HD6309_INLINE void clr_ex( void ); +HD6309_INLINE void suba_im( void ); +HD6309_INLINE void cmpa_im( void ); +HD6309_INLINE void sbca_im( void ); +HD6309_INLINE void subd_im( void ); +HD6309_INLINE void subw_im( void ); +HD6309_INLINE void cmpd_im( void ); +HD6309_INLINE void cmpw_im( void ); +HD6309_INLINE void cmpu_im( void ); +HD6309_INLINE void anda_im( void ); +HD6309_INLINE void bita_im( void ); +HD6309_INLINE void lda_im( void ); +HD6309_INLINE void eora_im( void ); +HD6309_INLINE void adca_im( void ); +HD6309_INLINE void ora_im( void ); +HD6309_INLINE void adda_im( void ); +HD6309_INLINE void cmpx_im( void ); +HD6309_INLINE void cmpy_im( void ); +HD6309_INLINE void cmps_im( void ); +HD6309_INLINE void bsr( void ); +HD6309_INLINE void ldx_im( void ); +HD6309_INLINE void ldq_im( void ); +HD6309_INLINE void ldy_im( void ); +HD6309_INLINE void suba_di( void ); +HD6309_INLINE void cmpa_di( void ); +HD6309_INLINE void sbca_di( void ); +HD6309_INLINE void subd_di( void ); +HD6309_INLINE void subw_di( void ); +HD6309_INLINE void cmpd_di( void ); +HD6309_INLINE void cmpw_di( void ); +HD6309_INLINE void cmpu_di( void ); +HD6309_INLINE void anda_di( void ); +HD6309_INLINE void bita_di( void ); +HD6309_INLINE void lda_di( void ); +HD6309_INLINE void sta_di( void ); +HD6309_INLINE void eora_di( void ); +HD6309_INLINE void adca_di( void ); +HD6309_INLINE void ora_di( void ); +HD6309_INLINE void adda_di( void ); +HD6309_INLINE void cmpx_di( void ); +HD6309_INLINE void cmpy_di( void ); +HD6309_INLINE void cmps_di( void ); +HD6309_INLINE void jsr_di( void ); +HD6309_INLINE void ldx_di( void ); +HD6309_INLINE void muld_di( void ); +HD6309_INLINE void divd_im( void ); +HD6309_INLINE void divq_im( void ); +HD6309_INLINE void muld_im( void ); +HD6309_INLINE void divd_di( void ); +HD6309_INLINE void divq_di( void ); +HD6309_INLINE void ldq_di( void ); +HD6309_INLINE void ldy_di( void ); +HD6309_INLINE void stx_di( void ); +HD6309_INLINE void stq_di( void ); +HD6309_INLINE void sty_di( void ); +HD6309_INLINE void suba_ix( void ); +HD6309_INLINE void cmpa_ix( void ); +HD6309_INLINE void sbca_ix( void ); +HD6309_INLINE void subd_ix( void ); +HD6309_INLINE void subw_ix( void ); +HD6309_INLINE void cmpd_ix( void ); +HD6309_INLINE void cmpw_ix( void ); +HD6309_INLINE void cmpu_ix( void ); +HD6309_INLINE void anda_ix( void ); +HD6309_INLINE void bita_ix( void ); +HD6309_INLINE void lda_ix( void ); +HD6309_INLINE void sta_ix( void ); +HD6309_INLINE void eora_ix( void ); +HD6309_INLINE void adca_ix( void ); +HD6309_INLINE void ora_ix( void ); +HD6309_INLINE void adda_ix( void ); +HD6309_INLINE void cmpx_ix( void ); +HD6309_INLINE void cmpy_ix( void ); +HD6309_INLINE void cmps_ix( void ); +HD6309_INLINE void jsr_ix( void ); +HD6309_INLINE void ldx_ix( void ); +HD6309_INLINE void muld_ix( void ); +HD6309_INLINE void divd_ix( void ); +HD6309_INLINE void divq_ix( void ); +HD6309_INLINE void ldq_ix( void ); +HD6309_INLINE void ldy_ix( void ); +HD6309_INLINE void stx_ix( void ); +HD6309_INLINE void stq_ix( void ); +HD6309_INLINE void sty_ix( void ); +HD6309_INLINE void suba_ex( void ); +HD6309_INLINE void cmpa_ex( void ); +HD6309_INLINE void sbca_ex( void ); +HD6309_INLINE void subd_ex( void ); +HD6309_INLINE void subw_ex( void ); +HD6309_INLINE void cmpd_ex( void ); +HD6309_INLINE void cmpw_ex( void ); +HD6309_INLINE void cmpu_ex( void ); +HD6309_INLINE void anda_ex( void ); +HD6309_INLINE void bita_ex( void ); +HD6309_INLINE void lda_ex( void ); +HD6309_INLINE void sta_ex( void ); +HD6309_INLINE void eora_ex( void ); +HD6309_INLINE void adca_ex( void ); +HD6309_INLINE void ora_ex( void ); +HD6309_INLINE void adda_ex( void ); +HD6309_INLINE void cmpx_ex( void ); +HD6309_INLINE void cmpy_ex( void ); +HD6309_INLINE void cmps_ex( void ); +HD6309_INLINE void jsr_ex( void ); +HD6309_INLINE void ldx_ex( void ); +HD6309_INLINE void muld_ex( void ); +HD6309_INLINE void divd_ex( void ); +HD6309_INLINE void divq_ex( void ); +HD6309_INLINE void ldq_ex( void ); +HD6309_INLINE void ldy_ex( void ); +HD6309_INLINE void stx_ex( void ); +HD6309_INLINE void stq_ex( void ); +HD6309_INLINE void sty_ex( void ); +HD6309_INLINE void subb_im( void ); +HD6309_INLINE void sube_im( void ); +HD6309_INLINE void subf_im( void ); +HD6309_INLINE void cmpb_im( void ); +HD6309_INLINE void cmpe_im( void ); +HD6309_INLINE void cmpf_im( void ); +HD6309_INLINE void sbcb_im( void ); +HD6309_INLINE void sbcd_im( void ); +HD6309_INLINE void addd_im( void ); +HD6309_INLINE void addw_im( void ); +HD6309_INLINE void adde_im( void ); +HD6309_INLINE void addf_im( void ); +HD6309_INLINE void andb_im( void ); +HD6309_INLINE void andd_im( void ); +HD6309_INLINE void bitb_im( void ); +HD6309_INLINE void ldb_im( void ); +HD6309_INLINE void lde_im( void ); +HD6309_INLINE void ldf_im( void ); +HD6309_INLINE void eorb_im( void ); +HD6309_INLINE void eord_im( void ); +HD6309_INLINE void adcb_im( void ); +HD6309_INLINE void adcd_im( void ); +HD6309_INLINE void orb_im( void ); +HD6309_INLINE void ord_im( void ); +HD6309_INLINE void addb_im( void ); +HD6309_INLINE void ldd_im( void ); +HD6309_INLINE void ldw_im( void ); +HD6309_INLINE void ldu_im( void ); +HD6309_INLINE void lds_im( void ); +HD6309_INLINE void subb_di( void ); +HD6309_INLINE void sube_di( void ); +HD6309_INLINE void subf_di( void ); +HD6309_INLINE void cmpb_di( void ); +HD6309_INLINE void cmpe_di( void ); +HD6309_INLINE void cmpf_di( void ); +HD6309_INLINE void sbcb_di( void ); +HD6309_INLINE void sbcd_di( void ); +HD6309_INLINE void addd_di( void ); +HD6309_INLINE void addw_di( void ); +HD6309_INLINE void adde_di( void ); +HD6309_INLINE void addf_di( void ); +HD6309_INLINE void andb_di( void ); +HD6309_INLINE void andd_di( void ); +HD6309_INLINE void bitb_di( void ); +HD6309_INLINE void ldb_di( void ); +HD6309_INLINE void lde_di( void ); +HD6309_INLINE void ldf_di( void ); +HD6309_INLINE void stb_di( void ); +HD6309_INLINE void ste_di( void ); +HD6309_INLINE void stf_di( void ); +HD6309_INLINE void eorb_di( void ); +HD6309_INLINE void eord_di( void ); +HD6309_INLINE void adcb_di( void ); +HD6309_INLINE void adcd_di( void ); +HD6309_INLINE void orb_di( void ); +HD6309_INLINE void ord_di( void ); +HD6309_INLINE void addb_di( void ); +HD6309_INLINE void ldd_di( void ); +HD6309_INLINE void ldw_di( void ); +HD6309_INLINE void std_di( void ); +HD6309_INLINE void stw_di( void ); +HD6309_INLINE void ldu_di( void ); +HD6309_INLINE void lds_di( void ); +HD6309_INLINE void stu_di( void ); +HD6309_INLINE void sts_di( void ); +HD6309_INLINE void subb_ix( void ); +HD6309_INLINE void sube_ix( void ); +HD6309_INLINE void subf_ix( void ); +HD6309_INLINE void cmpb_ix( void ); +HD6309_INLINE void cmpe_ix( void ); +HD6309_INLINE void cmpf_ix( void ); +HD6309_INLINE void sbcb_ix( void ); +HD6309_INLINE void sbcd_ix( void ); +HD6309_INLINE void addd_ix( void ); +HD6309_INLINE void addw_ix( void ); +HD6309_INLINE void adde_ix( void ); +HD6309_INLINE void addf_ix( void ); +HD6309_INLINE void andb_ix( void ); +HD6309_INLINE void andd_ix( void ); +HD6309_INLINE void bitb_ix( void ); +HD6309_INLINE void ldb_ix( void ); +HD6309_INLINE void lde_ix( void ); +HD6309_INLINE void ldf_ix( void ); +HD6309_INLINE void stb_ix( void ); +HD6309_INLINE void ste_ix( void ); +HD6309_INLINE void stf_ix( void ); +HD6309_INLINE void eorb_ix( void ); +HD6309_INLINE void eord_ix( void ); +HD6309_INLINE void adcb_ix( void ); +HD6309_INLINE void adcd_ix( void ); +HD6309_INLINE void orb_ix( void ); +HD6309_INLINE void ord_ix( void ); +HD6309_INLINE void addb_ix( void ); +HD6309_INLINE void ldd_ix( void ); +HD6309_INLINE void ldw_ix( void ); +HD6309_INLINE void std_ix( void ); +HD6309_INLINE void stw_ix( void ); +HD6309_INLINE void ldu_ix( void ); +HD6309_INLINE void lds_ix( void ); +HD6309_INLINE void stu_ix( void ); +HD6309_INLINE void sts_ix( void ); +HD6309_INLINE void subb_ex( void ); +HD6309_INLINE void sube_ex( void ); +HD6309_INLINE void subf_ex( void ); +HD6309_INLINE void cmpb_ex( void ); +HD6309_INLINE void cmpe_ex( void ); +HD6309_INLINE void cmpf_ex( void ); +HD6309_INLINE void sbcb_ex( void ); +HD6309_INLINE void sbcd_ex( void ); +HD6309_INLINE void addd_ex( void ); +HD6309_INLINE void addw_ex( void ); +HD6309_INLINE void adde_ex( void ); +HD6309_INLINE void addf_ex( void ); +HD6309_INLINE void andb_ex( void ); +HD6309_INLINE void andd_ex( void ); +HD6309_INLINE void bitb_ex( void ); +HD6309_INLINE void ldb_ex( void ); +HD6309_INLINE void lde_ex( void ); +HD6309_INLINE void ldf_ex( void ); +HD6309_INLINE void stb_ex( void ); +HD6309_INLINE void ste_ex( void ); +HD6309_INLINE void stf_ex( void ); +HD6309_INLINE void eorb_ex( void ); +HD6309_INLINE void eord_ex( void ); +HD6309_INLINE void adcb_ex( void ); +HD6309_INLINE void adcd_ex( void ); +HD6309_INLINE void orb_ex( void ); +HD6309_INLINE void ord_ex( void ); +HD6309_INLINE void addb_ex( void ); +HD6309_INLINE void ldd_ex( void ); +HD6309_INLINE void ldw_ex( void ); +HD6309_INLINE void std_ex( void ); +HD6309_INLINE void stw_ex( void ); +HD6309_INLINE void ldu_ex( void ); +HD6309_INLINE void lds_ex( void ); +HD6309_INLINE void stu_ex( void ); +HD6309_INLINE void sts_ex( void ); +HD6309_INLINE void pref10( void ); +HD6309_INLINE void pref11( void ); + +static const UINT8 flags8i[256]= /* increment */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; +static const UINT8 flags8d[256]= /* decrement */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; + +static const UINT8 index_cycle_em[256] = { /* Index Loopup cycle counts, emulated 6809 */ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ + +/* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x2X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x6X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x8X */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 0, +/* 0x9X */ 3, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 5, +/* 0xAX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 5, +/* 0xBX */ 5, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20, +/* 0xCX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 3, +/* 0xDX */ 4, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20, +/* 0xEX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 3, +/* 0xFX */ 4, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20 +}; + +static const UINT8 index_cycle_na[256] = { /* Index Loopup cycle counts, +native 6309 */ +/* X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, XA, XB, XC, XD, XE, XF */ + +/* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x2X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x6X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +/* 0x8X */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 0, +/* 0x9X */ 3, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 5, +/* 0xAX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 2, +/* 0xBX */ 5, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19, +/* 0xCX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 1, +/* 0xDX */ 4, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19, +/* 0xEX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 1, +/* 0xFX */ 4, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19 +}; + +#define IIP0 19 /* Illegal instruction cycle count page 0 */ +#define IIP1 20 /* Illegal instruction cycle count page 01 & 11 */ + +static const UINT8 ccounts_page0_em[256] = /* Cycle Counts Page zero, Emulated 6809 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6, +/* 0x1X */ 0, 0, 2, 4, 4, IIP0, 5, 9, IIP0, 2, 3, IIP0, 3, 2, 8, 6, +/* 0x2X */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +/* 0x3X */ 4, 4, 4, 4, 5, 5, 5, 5, IIP0, 5, 3, 6, 20, 11, IIP0, 19, +/* 0x4X */ 2, IIP0, IIP0, 2, 2, IIP0, 2, 2, 2, 2, 2, IIP0, 2, 2, IIP0, 2, +/* 0x5X */ 2, IIP0, IIP0, 2, 2, IIP0, 2, 2, 2, 2, 2, IIP0, 2, 2, IIP0, 2, +/* 0x6X */ 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 3, 6, +/* 0x7X */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 4, 7, +/* 0x8X */ 2, 2, 2, 4, 2, 2, 2, IIP0, 2, 2, 2, 2, 4, 7, 3, IIP0, +/* 0x9X */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5, +/* 0xAX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5, +/* 0xBX */ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 6, 6, +/* 0xCX */ 2, 2, 2, 4, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 5, 3, IIP0, +/* 0xDX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, +/* 0xEX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, +/* 0xFX */ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6 +}; + +static const UINT8 ccounts_page0_na[256] = /* Cycle Counts Page zero, Native 6309 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ 5, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 5, 4, 2, 5, +/* 0x1X */ 0, 0, 1, 4, 4, IIP0, 4, 7, IIP0, 1, 2, IIP0, 3, 1, 5, 4, +/* 0x2X */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, IIP0, 4, 1, 6, 22, 10, IIP0, 21, +/* 0x4X */ 1, IIP0, IIP0, 1, 1, IIP0, 1, 1, 1, 1, 1, IIP0, 1, 1, IIP0, 1, +/* 0x5X */ 1, IIP0, IIP0, 1, 1, IIP0, 1, 1, 1, 1, 1, IIP0, 1, 1, IIP0, 1, +/* 0x6X */ 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 5, 3, 6, +/* 0x7X */ 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 5, 3, 6, +/* 0x8X */ 2, 2, 2, 3, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 6, 3, IIP0, +/* 0x9X */ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 6, 4, 4, +/* 0xAX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, +/* 0xBX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 7, 5, 5, +/* 0xCX */ 2, 2, 2, 3, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 5, 3, IIP0, +/* 0xDX */ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, +/* 0xEX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, +/* 0xFX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +static const UINT8 ccounts_page01_em[256] = /* Cycle Counts Page 01, Emulated 6809 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x2X */ IIP1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, IIP1, IIP1, IIP1, 20, +/* 0x4X */ 2, IIP1,IIP1, 2, 2, IIP1, 2, 2, 2, 2, 2, IIP1, 2, 2, IIP1, 2, +/* 0x5X */ IIP1, IIP1, IIP1, 3, 3, IIP1, 3, IIP1, IIP1, 3, 3, IIP1, 3, 3, IIP1, 3, +/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x8X */ 5, 5, 5, 5, 5, 5, 4, IIP1, 5, 5, 5, 5, 5, IIP1, 4, IIP1, +/* 0x9X */ 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, IIP1, 6, 6, +/* 0xAX */ 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, IIP1, 6, 6, +/* 0xBX */ 8, 8, 8, 8, 8, 8, 7, 7, 8, 8, 8, 8, 8, IIP1, 7, 7, +/* 0xCX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 4, IIP1, +/* 0xDX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6, +/* 0xEX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6, +/* 0xFX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 9, 9, 7, 7 +}; + +static const UINT8 ccounts_page01_na[256] = /* Cycle Counts Page 01, Native 6309 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x2X */ IIP1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, IIP1, IIP1, IIP1, 22, +/* 0x4X */ 1, IIP1, IIP1, 1, 1, IIP1, 1, 1, 1, 1, 1, IIP1, 1, 1, IIP1, 1, +/* 0x5X */ IIP1, IIP1, IIP1, 2, 2, IIP1, 2, IIP1, IIP1, 2, 2, IIP1, 2, 2, IIP1, 1, +/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x8X */ 4, 4, 4, 4, 4, 4, 4, IIP1, 4, 4, 4, 4, 4, IIP1, 4, IIP1, +/* 0x9X */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, IIP1, 5, 5, +/* 0xAX */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, IIP1, 6, 6, +/* 0xBX */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, IIP1, 6, 6, +/* 0xCX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 4, IIP1, +/* 0xDX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 7, 7, 5, 5, +/* 0xEX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6, +/* 0xFX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6 +}; + +static const UINT8 ccounts_page11_em[256] = /* Cycle Counts Page 11, Emulated 6809 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x2X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x3X */ 7, 7, 7, 7, 7, 7, 7, 8, 3, 3, 3, 3, 4, 5, IIP1, 20, +/* 0x4X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2, +/* 0x5X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2, +/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x8X */ 3, 3, IIP1, 5, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, 5, 25, 34, 28, +/* 0x9X */ 5, 5, IIP1, 7, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 7, 27, 36, 30, +/* 0xAX */ 5, 5, IIP1, 7, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 7, 27, 36, 30, +/* 0xBX */ 6, 6, IIP1, 8, IIP1, IIP1, 6, 6, IIP1, IIP1, IIP1, 6, 8, 28, 37, 31, +/* 0xCX */ 3, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, +/* 0xDX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1, +/* 0xEX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1, +/* 0xFX */ 6, 6, IIP1, IIP1, IIP1, IIP1, 6, 6, IIP1, IIP1, IIP1, 6, IIP1, IIP1, IIP1, IIP1 +}; + +static const UINT8 ccounts_page11_na[256] = /* Cycle Counts Page 11, Native 6309 */ +{ +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ +/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x2X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x3X */ 6, 6, 6, 6, 6, 6, 6, 7, 3, 3, 3, 3, 4, 5, IIP1, 22, +/* 0x4X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2, +/* 0x5X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2, +/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, +/* 0x8X */ 3, 3, IIP1, 4, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, 4, 25, 34, 28, +/* 0x9X */ 4, 4, IIP1, 5, IIP1, IIP1, 4, 4, IIP1, IIP1, IIP1, 4, 5, 26, 35, 29, +/* 0xAX */ 5, 5, IIP1, 6, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 6, 27, 36, 30, +/* 0xBX */ 5, 5, IIP1, 6, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 6, 27, 36, 30, +/* 0xCX */ 3, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, +/* 0xDX */ 4, 4, IIP1, IIP1, IIP1, IIP1, 4, 4, IIP1, IIP1, IIP1, 4, IIP1, IIP1, IIP1, IIP1, +/* 0xEX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1, +/* 0xFX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1 +}; + +#ifndef BIG_SWITCH + +static void (*const hd6309_main[0x100])(void) = { +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, + 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ + +/* 0x0X */ neg_di, oim_di, aim_di, com_di, lsr_di, eim_di, ror_di, asr_di, + asl_di, rol_di, dec_di, tim_di, inc_di, tst_di, jmp_di, clr_di, + +/* 0x1X */ pref10, pref11, nop, sync, sexw, IIError, lbra, lbsr, + IIError, daa, orcc, IIError, andcc, sex, exg, tfr, + +/* 0x2X */ bra, brn, bhi, bls, bcc, bcs, bne, beq, + bvc, bvs, bpl, bmi, bge, blt, bgt, ble, + +/* 0x3X */ leax, leay, leas, leau, pshs, puls, pshu, pulu, + IIError, rts, abx, rti, cwai, mul, IIError, swi, + +/* 0x4X */ nega, IIError, IIError, coma, lsra, IIError, rora, asra, + asla, rola, deca, IIError, inca, tsta, IIError, clra, + +/* 0x5X */ negb, IIError, IIError, comb, lsrb, IIError, rorb, asrb, + aslb, rolb, decb, IIError, incb, tstb, IIError, clrb, + +/* 0x6X */ neg_ix, oim_ix, aim_ix, com_ix, lsr_ix, eim_ix, ror_ix, asr_ix, + asl_ix, rol_ix, dec_ix, tim_ix, inc_ix, tst_ix, jmp_ix, clr_ix, + +/* 0x7X */ neg_ex, oim_ex, aim_ex, com_ex, lsr_ex, eim_ex, ror_ex, asr_ex, + asl_ex, rol_ex, dec_ex, tim_ex, inc_ex, tst_ex, jmp_ex, clr_ex, + +/* 0x8X */ suba_im, cmpa_im, sbca_im, subd_im, anda_im, bita_im, lda_im, IIError, + eora_im, adca_im, ora_im, adda_im, cmpx_im, bsr, ldx_im, IIError, + +/* 0x9X */ suba_di, cmpa_di, sbca_di, subd_di, anda_di, bita_di, lda_di, sta_di, + eora_di, adca_di, ora_di, adda_di, cmpx_di, jsr_di, ldx_di, stx_di, + +/* 0xAX */ suba_ix, cmpa_ix, sbca_ix, subd_ix, anda_ix, bita_ix, lda_ix, sta_ix, + eora_ix, adca_ix, ora_ix, adda_ix, cmpx_ix, jsr_ix, ldx_ix, stx_ix, + +/* 0xBX */ suba_ex, cmpa_ex, sbca_ex, subd_ex, anda_ex, bita_ex, lda_ex, sta_ex, + eora_ex, adca_ex, ora_ex, adda_ex, cmpx_ex, jsr_ex, ldx_ex, stx_ex, + +/* 0xCX */ subb_im, cmpb_im, sbcb_im, addd_im, andb_im, bitb_im, ldb_im, IIError, + eorb_im, adcb_im, orb_im, addb_im, ldd_im, ldq_im, ldu_im, IIError, + +/* 0xDX */ subb_di, cmpb_di, sbcb_di, addd_di, andb_di, bitb_di, ldb_di, stb_di, + eorb_di, adcb_di, orb_di, addb_di, ldd_di, std_di, ldu_di, stu_di, + +/* 0xEX */ subb_ix, cmpb_ix, sbcb_ix, addd_ix, andb_ix, bitb_ix, ldb_ix, stb_ix, + eorb_ix, adcb_ix, orb_ix, addb_ix, ldd_ix, std_ix, ldu_ix, stu_ix, + +/* 0xFX */ subb_ex, cmpb_ex, sbcb_ex, addd_ex, andb_ex, bitb_ex, ldb_ex, stb_ex, + eorb_ex, adcb_ex, orb_ex, addb_ex, ldd_ex, std_ex, ldu_ex, stu_ex +}; + +static void (*const hd6309_page01[0x100])(void) = { +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, + 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ + +/* 0x0X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x1X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x2X */ IIError, lbrn, lbhi, lbls, lbcc, lbcs, lbne, lbeq, + lbvc, lbvs, lbpl, lbmi, lbge, lblt, lbgt, lble, + +/* 0x3X */ addr_r, adcr, subr, sbcr, andr, orr, eorr, cmpr, + pshsw, pulsw, pshuw, puluw, IIError, IIError, IIError, swi2, + +/* 0x4X */ negd, IIError, IIError, comd, lsrd, IIError, rord, asrd, + asld, rold, decd, IIError, incd, tstd, IIError, clrd, + +/* 0x5X */ IIError, IIError, IIError, comw, lsrw, IIError, rorw, IIError, + IIError, rolw, decw, IIError, incw, tstw, IIError, clrw, + +/* 0x6X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x7X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x8X */ subw_im, cmpw_im, sbcd_im, cmpd_im, andd_im, bitd_im, ldw_im, IIError, + eord_im, adcd_im, ord_im, addw_im, cmpy_im, IIError, ldy_im, IIError, + +/* 0x9X */ subw_di, cmpw_di, sbcd_di, cmpd_di, andd_di, bitd_di, ldw_di, stw_di, + eord_di, adcd_di, ord_di, addw_di, cmpy_di, IIError, ldy_di, sty_di, + +/* 0xAX */ subw_ix, cmpw_ix, sbcd_ix, cmpd_ix, andd_ix, bitd_ix, ldw_ix, stw_ix, + eord_ix, adcd_ix, ord_ix, addw_ix, cmpy_ix, IIError, ldy_ix, sty_ix, + +/* 0xBX */ subw_ex, cmpw_ex, sbcd_ex, cmpd_ex, andd_ex, bitd_ex, ldw_ex, stw_ex, + eord_ex, adcd_ex, ord_ex, addw_ex, cmpy_ex, IIError, ldy_ex, sty_ex, + +/* 0xCX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, lds_im, IIError, + +/* 0xDX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, ldq_di, stq_di, lds_di, sts_di, + +/* 0xEX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, ldq_ix, stq_ix, lds_ix, sts_ix, + +/* 0xFX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, ldq_ex, stq_ex, lds_ex, sts_ex +}; +static void (*const hd6309_page11[0x100])(void) = { +/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, + 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */ + +/* 0x0X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x1X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x2X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x3X */ band, biand, bor, bior, beor, bieor, ldbt, stbt, + tfmpp, tfmmm, tfmpc, tfmcp, bitmd_im,ldmd_im, IIError, swi3, + +/* 0x4X */ IIError, IIError, IIError, come, IIError, IIError, IIError, IIError, + IIError, IIError, dece, IIError, ince, tste, IIError, clre, + +/* 0x5X */ IIError, IIError, IIError, comf, IIError, IIError, IIError, IIError, + IIError, IIError, decf, IIError, incf, tstf, IIError, clrf, + +/* 0x6X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x7X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError, + +/* 0x8X */ sube_im, cmpe_im, IIError, cmpu_im, IIError, IIError, lde_im, IIError, + IIError, IIError, IIError, adde_im, cmps_im, divd_im, divq_im, muld_im, + +/* 0x9X */ sube_di, cmpe_di, IIError, cmpu_di, IIError, IIError, lde_di, ste_di, + IIError, IIError, IIError, adde_di, cmps_di, divd_di, divq_di, muld_di, + +/* 0xAX */ sube_ix, cmpe_ix, IIError, cmpu_ix, IIError, IIError, lde_ix, ste_ix, + IIError, IIError, IIError, adde_ix, cmps_ix, divd_ix, divq_ix, muld_ix, + +/* 0xBX */ sube_ex, cmpe_ex, IIError, cmpu_ex, IIError, IIError, lde_ex, ste_ex, + IIError, IIError, IIError, adde_ex, cmps_ex, divd_ex, divq_ex, muld_ex, + +/* 0xCX */ subf_im, cmpf_im, IIError, IIError, IIError, IIError, ldf_im, IIError, + IIError, IIError, IIError, addf_im, IIError, IIError, IIError, IIError, + +/* 0xDX */ subf_di, cmpf_di, IIError, IIError, IIError, IIError, ldf_di, stf_di, + IIError, IIError, IIError, addf_di, IIError, IIError, IIError, IIError, + +/* 0xEX */ subf_ix, cmpf_ix, IIError, IIError, IIError, IIError, ldf_ix, stf_ix, + IIError, IIError, IIError, addf_ix, IIError, IIError, IIError, IIError, + +/* 0xFX */ subf_ex, cmpf_ex, IIError, IIError, IIError, IIError, ldf_ex, stf_ex, + IIError, IIError, IIError, addf_ex, IIError, IIError, IIError, IIError + +}; + +#endif /* BIG_SWITCH */ diff --git a/src/cpu/hd6309/hd6309.cpp b/src/cpu/hd6309/hd6309.cpp new file mode 100644 index 00000000..5c415022 --- /dev/null +++ b/src/cpu/hd6309/hd6309.cpp @@ -0,0 +1,1333 @@ +/*** hd6309: Portable 6309 emulator ****************************************** + + Copyright John Butler + Copyright Tim Lindner + + References: + + HD63B09EP Technical Refrence Guide, by Chet Simpson with addition + by Alan Dekok + 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands. + + m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from + the 6809 Simulator V09) + + 6809 Microcomputer Programming & Interfacing with Experiments" + by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. + + System dependencies: UINT16 must be 16 bit unsigned int + UINT8 must be 8 bit unsigned int + UINT32 must be more than 16 bits + arrays up to 65536 bytes must be supported + machine must be twos complement + + History: +070614 ZV: + Fixed N flag setting in DIV overflow + +991026 HJB: + Fixed missing calls to cpu_changepc() for the TFR and EXG ocpodes. + Replaced m6809_slapstic checks by a macro (CHANGE_PC). ESB still + needs the tweaks. + +991024 HJB: + Tried to improve speed: Using bit7 of cycles1/2 as flag for multi + byte opcodes is gone, those opcodes now call fetch_effective_address(). + Got rid of the slow/fast flags for stack (S and U) memory accesses. + Minor changes to use 32 bit values as arguments to memory functions + and added defines for that purpose (e.g. X = 16bit XD = 32bit). + +990312 HJB: + Added bugfixes according to Aaron's findings. + Reset only sets CC_II and CC_IF, DP to zero and PC from reset vector. +990311 HJB: + Added _info functions. Now uses static m6808_Regs struct instead + of single statics. Changed the 16 bit registers to use the generic + PAIR union. Registers defined using macros. Split the core into + four execution loops for M6802, M6803, M6808 and HD63701. + TST, TSTA and TSTB opcodes reset carry flag. + Modified the read/write stack handlers to push LSB first then MSB + and pull MSB first then LSB. + +990228 HJB: + Changed the interrupt handling again. Now interrupts are taken + either right at the moment the lines are asserted or whenever + an interrupt is enabled and the corresponding line is still + asserted. That way the pending_interrupts checks are not + needed anymore. However, the CWAI and SYNC flags still need + some flags, so I changed the name to 'int_state'. + This core also has the code for the old interrupt system removed. + +990225 HJB: + Cleaned up the code here and there, added some comments. + Slightly changed the SAR opcodes (similiar to other CPU cores). + Added symbolic names for the flag bits. + Changed the way CWAI/Interrupt() handle CPU state saving. + A new flag M6809_STATE in pending_interrupts is used to determine + if a state save is needed on interrupt entry or already done by CWAI. + Added M6809_IRQ_LINE and M6809_FIRQ_LINE defines to m6809.h + Moved the internal interrupt_pending flags from m6809.h to m6809.c + Changed CWAI cycles2[0x3c] to be 2 (plus all or at least 19 if + CWAI actually pushes the entire state). + Implemented undocumented TFR/EXG for undefined source and mixed 8/16 + bit transfers (they should transfer/exchange the constant $ff). + Removed unused jmp/jsr _slap functions from 6809ops.c, + m6809_slapstick check moved into the opcode functions. + +000809 TJL: + Started converting m6809 into hd6309 + +001217 TJL: + Finished: + All opcodes + Dual Timing + To Do: + Verify new DIV opcodes. + +070805 TJL: + Fixed ADDR and ADCR opcodes not to clear the H condition code. Fixed ANDR, + EORR, ORR, ADDR, ADCR, SBCR, and SUBR to evaluate condition codes after + the destination register was set. Fixed BITMD opcode to only effect the Z + condition code. Fixed BITMD opcode to clear only tested flags. Fixed EXG + and TFR register promotion and demotion. Fixed illegal instruction handler + to not set I and F condition codes. Credit to Darren Atkinson for the + discovery of these bugs. + +090907 TJL: + The SEXW instruction is clearing the Overflow flag (V). It should not do + that. When an invalid source or destination register is specified for + the TFM instructions, real hardware invokes the Illegal Instruction + trap, whereas the emulator simply ignores the instruction. Credit to + Darren Atkinson for the discovery of these bugs. + +*****************************************************************************/ + +//#include "debugger.h" +//#include "deprecat.h" +#include "burnint.h" +#include "hd6309.h" + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#define HD6309_INLINE static +#define change_pc(newpc) hd6309.pc.w.l = (newpc) +#define HD6309_CLEAR_LINE 0 + +//extern offs_t hd6309_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +/*#define BIG_SWITCH*/ + +static void CHECK_IRQ_LINES( void ); +static void IIError(void); +static void DZError(void); + +HD6309_INLINE void fetch_effective_address( void ); + +/* flag bits in the cc register */ +#define CC_C 0x01 /* Carry */ +#define CC_V 0x02 /* Overflow */ +#define CC_Z 0x04 /* Zero */ +#define CC_N 0x08 /* Negative */ +#define CC_II 0x10 /* Inhibit IRQ */ +#define CC_H 0x20 /* Half (auxiliary) carry */ +#define CC_IF 0x40 /* Inhibit FIRQ */ +#define CC_E 0x80 /* entire state pushed */ + +/* flag bits in the md register */ +#define MD_EM 0x01 /* Execution mode */ +#define MD_FM 0x02 /* FIRQ mode */ +#define MD_II 0x40 /* Illegal instruction */ +#define MD_DZ 0x80 /* Division by zero */ + +/* 6309 registers */ +static hd6309_Regs hd6309; +//static int hd6309_slapstic = 0; + +#define pPPC hd6309.ppc +#define pPC hd6309.pc +#define pU hd6309.u +#define pS hd6309.s +#define pX hd6309.x +#define pY hd6309.y +#define pV hd6309.v +/*#define pQ hd6309.q*/ +#define pD hd6309.d +#define pW hd6309.w +#define pZ hd6309.z + +#define PPC hd6309.ppc.w.l +#define PC hd6309.pc.w.l +#define PCD hd6309.pc.d +#define U hd6309.u.w.l +#define UD hd6309.u.d +#define S hd6309.s.w.l +#define SD hd6309.s.d +#define X hd6309.x.w.l +#define XD hd6309.x.d +#define Y hd6309.y.w.l +#define YD hd6309.y.d +#define V hd6309.v.w.l +#define VD hd6309.v.d +#define D hd6309.d.w.l +#define A hd6309.d.b.h +#define B hd6309.d.b.l +#define W hd6309.w.w.l +#define E hd6309.w.b.h +#define F hd6309.w.b.l +#define DP hd6309.dp.b.h +#define DPD hd6309.dp.d +#define CC hd6309.cc +#define MD hd6309.md + +static PAIR ea; /* effective address */ +#define EA ea.w.l +#define EAD ea.d + +#define CHANGE_PC change_pc(PCD) +#if 0 +#define CHANGE_PC { \ + if( hd6309_slapstic ) \ + cpu_setOPbase16(PCD); \ + else \ + change_pc(PCD); \ + } +#endif + +#define HD6309_CWAI 8 /* set when CWAI is waiting for an interrupt */ +#define HD6309_SYNC 16 /* set when SYNC is waiting for an interrupt */ +#define HD6309_LDS 32 /* set when LDS occured at least once */ + +/* public globals */ +static int hd6309_ICount; + +/* these are re-defined in hd6309.h TO RAM, ROM or functions in cpuintrf.c */ +#define RM(mAddr) HD6309_RDMEM(mAddr) +#define WM(mAddr,Value) HD6309_WRMEM(mAddr,Value) +#define ROP(mAddr) HD6309_RDOP(mAddr) +#define ROP_ARG(mAddr) HD6309_RDOP_ARG(mAddr) + +/* macros to access memory */ +#define IMMBYTE(b) b = ROP_ARG(PCD); PC++ +#define IMMWORD(w) w.d = (ROP_ARG(PCD)<<8) | ROP_ARG((PCD+1)&0xffff); PC+=2 +#define IMMLONG(w) w.d = (ROP_ARG(PCD)<<24) + (ROP_ARG(PCD+1)<<16) + (ROP_ARG(PCD+2)<<8) + (ROP_ARG(PCD+3)); PC+=4 + +#define PUSHBYTE(b) --S; WM(SD,b) +#define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h) +#define PULLBYTE(b) b = RM(SD); S++ +#define PULLWORD(w) w = RM(SD)<<8; S++; w |= RM(SD); S++ + +#define PSHUBYTE(b) --U; WM(UD,b); +#define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h) +#define PULUBYTE(b) b = RM(UD); U++ +#define PULUWORD(w) w = RM(UD)<<8; U++; w |= RM(UD); U++ + +#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C) +#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V) +#define CLR_NZ CC&=~(CC_N|CC_Z) +#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C) +#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C) +#define CLR_Z CC&=~(CC_Z) +#define CLR_N CC&=~(CC_N) +#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C) +#define CLR_ZC CC&=~(CC_Z|CC_C) + +/* macros for CC -- CC bits affected should be reset before calling */ +#define SET_Z(a) if(!a)SEZ +#define SET_Z8(a) SET_Z((UINT8)a) +#define SET_Z16(a) SET_Z((UINT16)a) +#define SET_N8(a) CC|=((a&0x80)>>4) +#define SET_N16(a) CC|=((a&0x8000)>>12) +#define SET_N32(a) CC|=((a&0x8000)>>20) +#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1) +#define SET_C8(a) CC|=((a&0x100)>>8) +#define SET_C16(a) CC|=((a&0x10000)>>16) +#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6) +#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14) + +#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} +#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} + +static UINT8 const *cycle_counts_page0; +static UINT8 const *cycle_counts_page01; +static UINT8 const *cycle_counts_page11; +static UINT8 const *index_cycle; + +/* combos */ +#define SET_NZ8(a) {SET_N8(a);SET_Z(a);} +#define SET_NZ16(a) {SET_N16(a);SET_Z(a);} +#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} +#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);} + +#define NXORV ((CC&CC_N)^((CC&CC_V)<<2)) + +/* for treating an unsigned byte as a signed word */ +#define SIGNED(b) ((UINT16)(b&0x80?b|0xff00:b)) +/* for treating an unsigned short as a signed long */ +#define SIGNED_16(b) ((UINT32)(b&0x8000?b|0xffff0000:b)) + +/* macros for addressing modes (postbytes have their own code) */ +#define DIRECT EAD = DPD; IMMBYTE(ea.b.l) +#define IMM8 EAD = PCD; PC++ +#define IMM16 EAD = PCD; PC+=2 +#define EXTENDED IMMWORD(ea) + +/* macros to set status flags */ +#if defined(SEC) +#undef SEC +#endif +#define SEC CC|=CC_C +#define CLC CC&=~CC_C +#define SEZ CC|=CC_Z +#define CLZ CC&=~CC_Z +#define SEN CC|=CC_N +#define CLN CC&=~CC_N +#define SEV CC|=CC_V +#define CLV CC&=~CC_V +#define SEH CC|=CC_H +#define CLH CC&=~CC_H + +/* Macros to set mode flags */ +#define SEDZ MD|=MD_DZ +#define CLDZ MD&=~MD_DZ +#define SEII MD|=MD_II +#define CLII MD&=~MD_II +#define SEFM MD|=MD_FM +#define CLFM MD&=~MD_FM +#define SEEM MD|=MD_EM +#define CLEM MD&=~MD_EM + +/* macros for convenience */ +#define DIRBYTE(b) {DIRECT;b=RM(EAD);} +#define DIRWORD(w) {DIRECT;w.d=RM16(EAD);} +#define DIRLONG(lng) {DIRECT;lng.w.h=RM16(EAD);lng.w.l=RM16(EAD+2);} +#define EXTBYTE(b) {EXTENDED;b=RM(EAD);} +#define EXTWORD(w) {EXTENDED;w.d=RM16(EAD);} +#define EXTLONG(lng) {EXTENDED;lng.w.h=RM16(EAD);lng.w.l=RM16(EAD+2);} + +/* includes the static function prototypes and other tables */ +#include "6309tbl.c" + +/* macros for branch instructions */ +#define BRANCH(f) { \ + UINT8 t; \ + IMMBYTE(t); \ + if( f ) \ + { \ + PC += SIGNED(t); \ + CHANGE_PC; \ + } \ +} + +#define LBRANCH(f) { \ + PAIR t; \ + IMMWORD(t); \ + if( f ) \ + { \ + if( !(MD & MD_EM) ) \ + hd6309_ICount -= 1; \ + PC += t.w.l; \ + CHANGE_PC; \ + } \ +} + +HD6309_INLINE UINT32 RM16( UINT32 mAddr ); +HD6309_INLINE UINT32 RM16( UINT32 mAddr ) +{ + UINT32 result = RM(mAddr) << 8; + return result | RM((mAddr+1)&0xffff); +} + +HD6309_INLINE UINT32 RM32( UINT32 mAddr ); +HD6309_INLINE UINT32 RM32( UINT32 mAddr ) +{ + UINT32 result = RM(mAddr) << 24; + result += RM(mAddr+1) << 16; + result += RM(mAddr+2) << 8; + result += RM(mAddr+3); + return result; +} + +HD6309_INLINE void WM16( UINT32 mAddr, PAIR *p ); +HD6309_INLINE void WM16( UINT32 mAddr, PAIR *p ) +{ + WM( mAddr, p->b.h ); + WM( (mAddr+1)&0xffff, p->b.l ); +} + +HD6309_INLINE void WM32( UINT32 mAddr, PAIR *p ); +HD6309_INLINE void WM32( UINT32 mAddr, PAIR *p ) +{ + WM( mAddr, p->b.h3 ); + WM( (mAddr+1)&0xffff, p->b.h2 ); + WM( (mAddr+2)&0xffff, p->b.h ); + WM( (mAddr+3)&0xffff, p->b.l ); +} + +static void UpdateState(void) +{ + if ( hd6309.md & MD_EM ) + { + cycle_counts_page0 = ccounts_page0_na; + cycle_counts_page01 = ccounts_page01_na; + cycle_counts_page11 = ccounts_page11_na; + index_cycle = index_cycle_na; + } + else + { + cycle_counts_page0 = ccounts_page0_em; + cycle_counts_page01 = ccounts_page01_em; + cycle_counts_page11 = ccounts_page11_em; + index_cycle = index_cycle_em; + } +} + +static void CHECK_IRQ_LINES( void ) +{ + if( hd6309.irq_state[HD6309_IRQ_LINE] != HD6309_CLEAR_LINE || + hd6309.irq_state[HD6309_FIRQ_LINE] != HD6309_CLEAR_LINE ) + hd6309.int_state &= ~HD6309_SYNC; /* clear SYNC flag */ + if( hd6309.irq_state[HD6309_FIRQ_LINE]!=HD6309_CLEAR_LINE && !(CC & CC_IF)) + { + /* fast IRQ */ + /* HJB 990225: state already saved by CWAI? */ + if( hd6309.int_state & HD6309_CWAI ) + { + hd6309.int_state &= ~HD6309_CWAI; + hd6309.extra_cycles += 7; /* subtract +7 cycles */ + } + else + { + if ( MD & MD_FM ) + { + CC |= CC_E; /* save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + hd6309.extra_cycles += 2; /* subtract +2 cycles */ + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + hd6309.extra_cycles += 19; /* subtract +19 cycles */ + } + else + { + CC &= ~CC_E; /* save 'short' state */ + PUSHWORD(pPC); + PUSHBYTE(CC); + hd6309.extra_cycles += 10; /* subtract +10 cycles */ + } + } + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD=RM16(0xfff6); + CHANGE_PC; +// (void)(*hd6309.irq_callback)(HD6309_FIRQ_LINE); + } + else + if( hd6309.irq_state[HD6309_IRQ_LINE]!=HD6309_CLEAR_LINE && !(CC & CC_II) ) + { + /* standard IRQ */ + /* HJB 990225: state already saved by CWAI? */ + if( hd6309.int_state & HD6309_CWAI ) + { + hd6309.int_state &= ~HD6309_CWAI; /* clear CWAI flag */ + hd6309.extra_cycles += 7; /* subtract +7 cycles */ + } + else + { + CC |= CC_E; /* save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + hd6309.extra_cycles += 2; /* subtract +2 cycles */ + } + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + hd6309.extra_cycles += 19; /* subtract +19 cycles */ + } + CC |= CC_II; /* inhibit IRQ */ + PCD=RM16(0xfff8); + CHANGE_PC; +// (void)(*hd6309.irq_callback)(HD6309_IRQ_LINE); + } +} + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +void hd6309_get_context(void *dst) +{ + if( dst ) + *(hd6309_Regs*)dst = hd6309; +} + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +void hd6309_set_context(void *src) +{ + if( src ) + hd6309 = *(hd6309_Regs*)src; + CHANGE_PC; + + CHECK_IRQ_LINES(); + UpdateState(); +} + +//static STATE_POSTLOAD( hd6309_postload ) +//{ +// UpdateState(); +//} + +void hd6309_init() +{ +// hd6309.irq_callback = irqcallback; + +// state_save_register_item("hd6309", index, PC); +// state_save_register_item("hd6309", index, U); +// state_save_register_item("hd6309", index, S); +// state_save_register_item("hd6309", index, X); +// state_save_register_item("hd6309", index, Y); +// state_save_register_item("hd6309", index, V); +// state_save_register_item("hd6309", index, DP); +// state_save_register_item("hd6309", index, CC); +// state_save_register_item("hd6309", index, MD); +// state_save_register_postload(Machine, hd6309_postload, NULL); +// state_save_register_item("hd6309", index, hd6309.int_state); +// state_save_register_item("hd6309", index, hd6309.nmi_state); +// state_save_register_item("hd6309", index, hd6309.irq_state[0]); +// state_save_register_item("hd6309", index, hd6309.irq_state[1]); +} + +/****************************************************************************/ +/* Reset registers to their initial values */ +/****************************************************************************/ +void hd6309_reset(void) +{ + hd6309.int_state = 0; + hd6309.nmi_state = HD6309_CLEAR_LINE; + hd6309.irq_state[0] = HD6309_CLEAR_LINE; + hd6309.irq_state[0] = HD6309_CLEAR_LINE; + + DPD = 0; /* Reset direct page register */ + + MD = 0; /* Mode register gets reset */ + CC |= CC_II; /* IRQ disabled */ + CC |= CC_IF; /* FIRQ disabled */ + + PCD = RM16(0xfffe); + CHANGE_PC; + UpdateState(); +} + +int hd6309_get_pc() +{ + return PC; +} + +/* +static void hd6309_exit(void) +{ + +}*/ + +/* Generate interrupts */ +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ +void hd6309_set_irq_line(int irqline, int state) +{ + if (irqline == HD6309_INPUT_LINE_NMI) + { + if (hd6309.nmi_state == state) return; + hd6309.nmi_state = state; +// LOG(("HD6309#%d set_irq_line (NMI) %d (PC=%4.4X)\n", cpu_getactivecpu(), state, pPC.d)); + if( state == HD6309_CLEAR_LINE ) return; + + /* if the stack was not yet initialized */ + if( !(hd6309.int_state & HD6309_LDS) ) return; + + hd6309.int_state &= ~HD6309_SYNC; + /* HJB 990225: state already saved by CWAI? */ + if( hd6309.int_state & HD6309_CWAI ) + { + hd6309.int_state &= ~HD6309_CWAI; + hd6309.extra_cycles += 7; /* subtract +7 cycles next time */ + } + else + { + CC |= CC_E; /* save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + if ( MD & MD_EM ) + { + PUSHBYTE(F); + PUSHBYTE(E); + hd6309.extra_cycles += 2; /* subtract +2 cycles */ + } + + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + hd6309.extra_cycles += 19; /* subtract +19 cycles next time */ + } + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD = RM16(0xfffc); + CHANGE_PC; + } + else if (irqline < 2) + { +// LOG(("HD6309#%d set_irq_line %d, %d (PC=%4.4X)\n", cpu_getactivecpu(), irqline, state, pPC.d)); + hd6309.irq_state[irqline] = state; + if (state == HD6309_CLEAR_LINE) return; + CHECK_IRQ_LINES(); + } +} + +/* includes the actual opcode implementations */ +#include "6309ops.c" + +/* execute instructions on this CPU until icount expires */ +int hd6309_execute(int cycles) /* NS 970908 */ +{ + hd6309_ICount = cycles - hd6309.extra_cycles; + hd6309.extra_cycles = 0; + + if (hd6309.int_state & (HD6309_CWAI | HD6309_SYNC)) + { +// debugger_instruction_hook(Machine, PCD); + hd6309_ICount = 0; + } + else + { + do + { + pPPC = pPC; + +// debugger_instruction_hook(Machine, PCD); + + hd6309.ireg = ROP(PCD); + PC++; + +#ifdef BIG_SWITCH + switch( hd6309.ireg ) + { + case 0x00: neg_di(); break; + case 0x01: oim_di(); break; + case 0x02: aim_di(); break; + case 0x03: com_di(); break; + case 0x04: lsr_di(); break; + case 0x05: eim_di(); break; + case 0x06: ror_di(); break; + case 0x07: asr_di(); break; + case 0x08: asl_di(); break; + case 0x09: rol_di(); break; + case 0x0a: dec_di(); break; + case 0x0b: tim_di(); break; + case 0x0c: inc_di(); break; + case 0x0d: tst_di(); break; + case 0x0e: jmp_di(); break; + case 0x0f: clr_di(); break; + case 0x10: pref10(); break; + case 0x11: pref11(); break; + case 0x12: nop(); break; + case 0x13: sync(); break; + case 0x14: sexw(); break; + case 0x15: IIError(); break; + case 0x16: lbra(); break; + case 0x17: lbsr(); break; + case 0x18: IIError(); break; + case 0x19: daa(); break; + case 0x1a: orcc(); break; + case 0x1b: IIError(); break; + case 0x1c: andcc(); break; + case 0x1d: sex(); break; + case 0x1e: exg(); break; + case 0x1f: tfr(); break; + case 0x20: bra(); break; + case 0x21: brn(); break; + case 0x22: bhi(); break; + case 0x23: bls(); break; + case 0x24: bcc(); break; + case 0x25: bcs(); break; + case 0x26: bne(); break; + case 0x27: beq(); break; + case 0x28: bvc(); break; + case 0x29: bvs(); break; + case 0x2a: bpl(); break; + case 0x2b: bmi(); break; + case 0x2c: bge(); break; + case 0x2d: blt(); break; + case 0x2e: bgt(); break; + case 0x2f: ble(); break; + case 0x30: leax(); break; + case 0x31: leay(); break; + case 0x32: leas(); break; + case 0x33: leau(); break; + case 0x34: pshs(); break; + case 0x35: puls(); break; + case 0x36: pshu(); break; + case 0x37: pulu(); break; + case 0x38: IIError(); break; + case 0x39: rts(); break; + case 0x3a: abx(); break; + case 0x3b: rti(); break; + case 0x3c: cwai(); break; + case 0x3d: mul(); break; + case 0x3e: IIError(); break; + case 0x3f: swi(); break; + case 0x40: nega(); break; + case 0x41: IIError(); break; + case 0x42: IIError(); break; + case 0x43: coma(); break; + case 0x44: lsra(); break; + case 0x45: IIError(); break; + case 0x46: rora(); break; + case 0x47: asra(); break; + case 0x48: asla(); break; + case 0x49: rola(); break; + case 0x4a: deca(); break; + case 0x4b: IIError(); break; + case 0x4c: inca(); break; + case 0x4d: tsta(); break; + case 0x4e: IIError(); break; + case 0x4f: clra(); break; + case 0x50: negb(); break; + case 0x51: IIError(); break; + case 0x52: IIError(); break; + case 0x53: comb(); break; + case 0x54: lsrb(); break; + case 0x55: IIError(); break; + case 0x56: rorb(); break; + case 0x57: asrb(); break; + case 0x58: aslb(); break; + case 0x59: rolb(); break; + case 0x5a: decb(); break; + case 0x5b: IIError(); break; + case 0x5c: incb(); break; + case 0x5d: tstb(); break; + case 0x5e: IIError(); break; + case 0x5f: clrb(); break; + case 0x60: neg_ix(); break; + case 0x61: oim_ix(); break; + case 0x62: aim_ix(); break; + case 0x63: com_ix(); break; + case 0x64: lsr_ix(); break; + case 0x65: eim_ix(); break; + case 0x66: ror_ix(); break; + case 0x67: asr_ix(); break; + case 0x68: asl_ix(); break; + case 0x69: rol_ix(); break; + case 0x6a: dec_ix(); break; + case 0x6b: tim_ix(); break; + case 0x6c: inc_ix(); break; + case 0x6d: tst_ix(); break; + case 0x6e: jmp_ix(); break; + case 0x6f: clr_ix(); break; + case 0x70: neg_ex(); break; + case 0x71: oim_ex(); break; + case 0x72: aim_ex(); break; + case 0x73: com_ex(); break; + case 0x74: lsr_ex(); break; + case 0x75: eim_ex(); break; + case 0x76: ror_ex(); break; + case 0x77: asr_ex(); break; + case 0x78: asl_ex(); break; + case 0x79: rol_ex(); break; + case 0x7a: dec_ex(); break; + case 0x7b: tim_ex(); break; + case 0x7c: inc_ex(); break; + case 0x7d: tst_ex(); break; + case 0x7e: jmp_ex(); break; + case 0x7f: clr_ex(); break; + case 0x80: suba_im(); break; + case 0x81: cmpa_im(); break; + case 0x82: sbca_im(); break; + case 0x83: subd_im(); break; + case 0x84: anda_im(); break; + case 0x85: bita_im(); break; + case 0x86: lda_im(); break; + case 0x87: IIError(); break; + case 0x88: eora_im(); break; + case 0x89: adca_im(); break; + case 0x8a: ora_im(); break; + case 0x8b: adda_im(); break; + case 0x8c: cmpx_im(); break; + case 0x8d: bsr(); break; + case 0x8e: ldx_im(); break; + case 0x8f: IIError(); break; + case 0x90: suba_di(); break; + case 0x91: cmpa_di(); break; + case 0x92: sbca_di(); break; + case 0x93: subd_di(); break; + case 0x94: anda_di(); break; + case 0x95: bita_di(); break; + case 0x96: lda_di(); break; + case 0x97: sta_di(); break; + case 0x98: eora_di(); break; + case 0x99: adca_di(); break; + case 0x9a: ora_di(); break; + case 0x9b: adda_di(); break; + case 0x9c: cmpx_di(); break; + case 0x9d: jsr_di(); break; + case 0x9e: ldx_di(); break; + case 0x9f: stx_di(); break; + case 0xa0: suba_ix(); break; + case 0xa1: cmpa_ix(); break; + case 0xa2: sbca_ix(); break; + case 0xa3: subd_ix(); break; + case 0xa4: anda_ix(); break; + case 0xa5: bita_ix(); break; + case 0xa6: lda_ix(); break; + case 0xa7: sta_ix(); break; + case 0xa8: eora_ix(); break; + case 0xa9: adca_ix(); break; + case 0xaa: ora_ix(); break; + case 0xab: adda_ix(); break; + case 0xac: cmpx_ix(); break; + case 0xad: jsr_ix(); break; + case 0xae: ldx_ix(); break; + case 0xaf: stx_ix(); break; + case 0xb0: suba_ex(); break; + case 0xb1: cmpa_ex(); break; + case 0xb2: sbca_ex(); break; + case 0xb3: subd_ex(); break; + case 0xb4: anda_ex(); break; + case 0xb5: bita_ex(); break; + case 0xb6: lda_ex(); break; + case 0xb7: sta_ex(); break; + case 0xb8: eora_ex(); break; + case 0xb9: adca_ex(); break; + case 0xba: ora_ex(); break; + case 0xbb: adda_ex(); break; + case 0xbc: cmpx_ex(); break; + case 0xbd: jsr_ex(); break; + case 0xbe: ldx_ex(); break; + case 0xbf: stx_ex(); break; + case 0xc0: subb_im(); break; + case 0xc1: cmpb_im(); break; + case 0xc2: sbcb_im(); break; + case 0xc3: addd_im(); break; + case 0xc4: andb_im(); break; + case 0xc5: bitb_im(); break; + case 0xc6: ldb_im(); break; + case 0xc7: IIError(); break; + case 0xc8: eorb_im(); break; + case 0xc9: adcb_im(); break; + case 0xca: orb_im(); break; + case 0xcb: addb_im(); break; + case 0xcc: ldd_im(); break; + case 0xcd: ldq_im(); break; /* in m6809 was std_im */ + case 0xce: ldu_im(); break; + case 0xcf: IIError(); break; + case 0xd0: subb_di(); break; + case 0xd1: cmpb_di(); break; + case 0xd2: sbcb_di(); break; + case 0xd3: addd_di(); break; + case 0xd4: andb_di(); break; + case 0xd5: bitb_di(); break; + case 0xd6: ldb_di(); break; + case 0xd7: stb_di(); break; + case 0xd8: eorb_di(); break; + case 0xd9: adcb_di(); break; + case 0xda: orb_di(); break; + case 0xdb: addb_di(); break; + case 0xdc: ldd_di(); break; + case 0xdd: std_di(); break; + case 0xde: ldu_di(); break; + case 0xdf: stu_di(); break; + case 0xe0: subb_ix(); break; + case 0xe1: cmpb_ix(); break; + case 0xe2: sbcb_ix(); break; + case 0xe3: addd_ix(); break; + case 0xe4: andb_ix(); break; + case 0xe5: bitb_ix(); break; + case 0xe6: ldb_ix(); break; + case 0xe7: stb_ix(); break; + case 0xe8: eorb_ix(); break; + case 0xe9: adcb_ix(); break; + case 0xea: orb_ix(); break; + case 0xeb: addb_ix(); break; + case 0xec: ldd_ix(); break; + case 0xed: std_ix(); break; + case 0xee: ldu_ix(); break; + case 0xef: stu_ix(); break; + case 0xf0: subb_ex(); break; + case 0xf1: cmpb_ex(); break; + case 0xf2: sbcb_ex(); break; + case 0xf3: addd_ex(); break; + case 0xf4: andb_ex(); break; + case 0xf5: bitb_ex(); break; + case 0xf6: ldb_ex(); break; + case 0xf7: stb_ex(); break; + case 0xf8: eorb_ex(); break; + case 0xf9: adcb_ex(); break; + case 0xfa: orb_ex(); break; + case 0xfb: addb_ex(); break; + case 0xfc: ldd_ex(); break; + case 0xfd: std_ex(); break; + case 0xfe: ldu_ex(); break; + case 0xff: stu_ex(); break; + } +#else + (*hd6309_main[hd6309.ireg])(); +#endif /* BIG_SWITCH */ + + hd6309_ICount -= cycle_counts_page0[hd6309.ireg]; + + } while( hd6309_ICount > 0 ); + + hd6309_ICount -= hd6309.extra_cycles; + hd6309.extra_cycles = 0; + } + + return cycles - hd6309_ICount; /* NS 970908 */ +} + +HD6309_INLINE void fetch_effective_address( void ) +{ + UINT8 postbyte = ROP_ARG(PCD); + PC++; + + switch(postbyte) + { + case 0x00: EA=X; break; + case 0x01: EA=X+1; break; + case 0x02: EA=X+2; break; + case 0x03: EA=X+3; break; + case 0x04: EA=X+4; break; + case 0x05: EA=X+5; break; + case 0x06: EA=X+6; break; + case 0x07: EA=X+7; break; + case 0x08: EA=X+8; break; + case 0x09: EA=X+9; break; + case 0x0a: EA=X+10; break; + case 0x0b: EA=X+11; break; + case 0x0c: EA=X+12; break; + case 0x0d: EA=X+13; break; + case 0x0e: EA=X+14; break; + case 0x0f: EA=X+15; break; + + case 0x10: EA=X-16; break; + case 0x11: EA=X-15; break; + case 0x12: EA=X-14; break; + case 0x13: EA=X-13; break; + case 0x14: EA=X-12; break; + case 0x15: EA=X-11; break; + case 0x16: EA=X-10; break; + case 0x17: EA=X-9; break; + case 0x18: EA=X-8; break; + case 0x19: EA=X-7; break; + case 0x1a: EA=X-6; break; + case 0x1b: EA=X-5; break; + case 0x1c: EA=X-4; break; + case 0x1d: EA=X-3; break; + case 0x1e: EA=X-2; break; + case 0x1f: EA=X-1; break; + + case 0x20: EA=Y; break; + case 0x21: EA=Y+1; break; + case 0x22: EA=Y+2; break; + case 0x23: EA=Y+3; break; + case 0x24: EA=Y+4; break; + case 0x25: EA=Y+5; break; + case 0x26: EA=Y+6; break; + case 0x27: EA=Y+7; break; + case 0x28: EA=Y+8; break; + case 0x29: EA=Y+9; break; + case 0x2a: EA=Y+10; break; + case 0x2b: EA=Y+11; break; + case 0x2c: EA=Y+12; break; + case 0x2d: EA=Y+13; break; + case 0x2e: EA=Y+14; break; + case 0x2f: EA=Y+15; break; + + case 0x30: EA=Y-16; break; + case 0x31: EA=Y-15; break; + case 0x32: EA=Y-14; break; + case 0x33: EA=Y-13; break; + case 0x34: EA=Y-12; break; + case 0x35: EA=Y-11; break; + case 0x36: EA=Y-10; break; + case 0x37: EA=Y-9; break; + case 0x38: EA=Y-8; break; + case 0x39: EA=Y-7; break; + case 0x3a: EA=Y-6; break; + case 0x3b: EA=Y-5; break; + case 0x3c: EA=Y-4; break; + case 0x3d: EA=Y-3; break; + case 0x3e: EA=Y-2; break; + case 0x3f: EA=Y-1; break; + + case 0x40: EA=U; break; + case 0x41: EA=U+1; break; + case 0x42: EA=U+2; break; + case 0x43: EA=U+3; break; + case 0x44: EA=U+4; break; + case 0x45: EA=U+5; break; + case 0x46: EA=U+6; break; + case 0x47: EA=U+7; break; + case 0x48: EA=U+8; break; + case 0x49: EA=U+9; break; + case 0x4a: EA=U+10; break; + case 0x4b: EA=U+11; break; + case 0x4c: EA=U+12; break; + case 0x4d: EA=U+13; break; + case 0x4e: EA=U+14; break; + case 0x4f: EA=U+15; break; + + case 0x50: EA=U-16; break; + case 0x51: EA=U-15; break; + case 0x52: EA=U-14; break; + case 0x53: EA=U-13; break; + case 0x54: EA=U-12; break; + case 0x55: EA=U-11; break; + case 0x56: EA=U-10; break; + case 0x57: EA=U-9; break; + case 0x58: EA=U-8; break; + case 0x59: EA=U-7; break; + case 0x5a: EA=U-6; break; + case 0x5b: EA=U-5; break; + case 0x5c: EA=U-4; break; + case 0x5d: EA=U-3; break; + case 0x5e: EA=U-2; break; + case 0x5f: EA=U-1; break; + + case 0x60: EA=S; break; + case 0x61: EA=S+1; break; + case 0x62: EA=S+2; break; + case 0x63: EA=S+3; break; + case 0x64: EA=S+4; break; + case 0x65: EA=S+5; break; + case 0x66: EA=S+6; break; + case 0x67: EA=S+7; break; + case 0x68: EA=S+8; break; + case 0x69: EA=S+9; break; + case 0x6a: EA=S+10; break; + case 0x6b: EA=S+11; break; + case 0x6c: EA=S+12; break; + case 0x6d: EA=S+13; break; + case 0x6e: EA=S+14; break; + case 0x6f: EA=S+15; break; + + case 0x70: EA=S-16; break; + case 0x71: EA=S-15; break; + case 0x72: EA=S-14; break; + case 0x73: EA=S-13; break; + case 0x74: EA=S-12; break; + case 0x75: EA=S-11; break; + case 0x76: EA=S-10; break; + case 0x77: EA=S-9; break; + case 0x78: EA=S-8; break; + case 0x79: EA=S-7; break; + case 0x7a: EA=S-6; break; + case 0x7b: EA=S-5; break; + case 0x7c: EA=S-4; break; + case 0x7d: EA=S-3; break; + case 0x7e: EA=S-2; break; + case 0x7f: EA=S-1; break; + + case 0x80: EA=X; X++; break; + case 0x81: EA=X; X+=2; break; + case 0x82: X--; EA=X; break; + case 0x83: X-=2; EA=X; break; + case 0x84: EA=X; break; + case 0x85: EA=X+SIGNED(B); break; + case 0x86: EA=X+SIGNED(A); break; + case 0x87: EA=X+SIGNED(E); break; + case 0x88: IMMBYTE(EA); EA=X+SIGNED(EA); break; + case 0x89: IMMWORD(ea); EA+=X; break; + case 0x8a: EA=X+SIGNED(F); break; + case 0x8b: EA=X+D; break; + case 0x8c: IMMBYTE(EA); EA=PC+SIGNED(EA); break; + case 0x8d: IMMWORD(ea); EA+=PC; break; + case 0x8e: EA=X+W; break; + case 0x8f: EA=W; break; + + case 0x90: EA=W; EAD=RM16(EAD); break; + case 0x91: EA=X; X+=2; EAD=RM16(EAD); break; + case 0x92: IIError(); break; + case 0x93: X-=2; EA=X; EAD=RM16(EAD); break; + case 0x94: EA=X; EAD=RM16(EAD); break; + case 0x95: EA=X+SIGNED(B); EAD=RM16(EAD); break; + case 0x96: EA=X+SIGNED(A); EAD=RM16(EAD); break; + case 0x97: EA=X+SIGNED(E); EAD=RM16(EAD); break; + case 0x98: IMMBYTE(EA); EA=X+SIGNED(EA); EAD=RM16(EAD); break; + case 0x99: IMMWORD(ea); EA+=X; EAD=RM16(EAD); break; + case 0x9a: EA=X+SIGNED(F); EAD=RM16(EAD); break; + case 0x9b: EA=X+D; EAD=RM16(EAD); break; + case 0x9c: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); break; + case 0x9d: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); break; + case 0x9e: EA=X+W; EAD=RM16(EAD); break; + case 0x9f: IMMWORD(ea); EAD=RM16(EAD); break; + + case 0xa0: EA=Y; Y++; break; + case 0xa1: EA=Y; Y+=2; break; + case 0xa2: Y--; EA=Y; break; + case 0xa3: Y-=2; EA=Y; break; + case 0xa4: EA=Y; break; + case 0xa5: EA=Y+SIGNED(B); break; + case 0xa6: EA=Y+SIGNED(A); break; + case 0xa7: EA=Y+SIGNED(E); break; + case 0xa8: IMMBYTE(EA); EA=Y+SIGNED(EA); break; + case 0xa9: IMMWORD(ea); EA+=Y; break; + case 0xaa: EA=Y+SIGNED(F); break; + case 0xab: EA=Y+D; break; + case 0xac: IMMBYTE(EA); EA=PC+SIGNED(EA); break; + case 0xad: IMMWORD(ea); EA+=PC; break; + case 0xae: EA=Y+W; break; + case 0xaf: IMMWORD(ea); EA+=W; break; + + case 0xb0: IMMWORD(ea); EA+=W; EAD=RM16(EAD); break; + case 0xb1: EA=Y; Y+=2; EAD=RM16(EAD); break; + case 0xb2: IIError(); break; + case 0xb3: Y-=2; EA=Y; EAD=RM16(EAD); break; + case 0xb4: EA=Y; EAD=RM16(EAD); break; + case 0xb5: EA=Y+SIGNED(B); EAD=RM16(EAD); break; + case 0xb6: EA=Y+SIGNED(A); EAD=RM16(EAD); break; + case 0xb7: EA=Y+SIGNED(E); EAD=RM16(EAD); break; + case 0xb8: IMMBYTE(EA); EA=Y+SIGNED(EA); EAD=RM16(EAD); break; + case 0xb9: IMMWORD(ea); EA+=Y; EAD=RM16(EAD); break; + case 0xba: EA=Y+SIGNED(F); EAD=RM16(EAD); break; + case 0xbb: EA=Y+D; EAD=RM16(EAD); break; + case 0xbc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); break; + case 0xbd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); break; + case 0xbe: EA=Y+W; EAD=RM16(EAD); break; + case 0xbf: IIError(); break; + + case 0xc0: EA=U; U++; break; + case 0xc1: EA=U; U+=2; break; + case 0xc2: U--; EA=U; break; + case 0xc3: U-=2; EA=U; break; + case 0xc4: EA=U; break; + case 0xc5: EA=U+SIGNED(B); break; + case 0xc6: EA=U+SIGNED(A); break; + case 0xc7: EA=U+SIGNED(E); break; + case 0xc8: IMMBYTE(EA); EA=U+SIGNED(EA); break; + case 0xc9: IMMWORD(ea); EA+=U; break; + case 0xca: EA=U+SIGNED(F); break; + case 0xcb: EA=U+D; break; + case 0xcc: IMMBYTE(EA); EA=PC+SIGNED(EA); break; + case 0xcd: IMMWORD(ea); EA+=PC; break; + case 0xce: EA=U+W; break; + case 0xcf: EA=W; W+=2; break; + + case 0xd0: EA=W; W+=2; EAD=RM16(EAD); break; + case 0xd1: EA=U; U+=2; EAD=RM16(EAD); break; + case 0xd2: IIError(); break; + case 0xd3: U-=2; EA=U; EAD=RM16(EAD); break; + case 0xd4: EA=U; EAD=RM16(EAD); break; + case 0xd5: EA=U+SIGNED(B); EAD=RM16(EAD); break; + case 0xd6: EA=U+SIGNED(A); EAD=RM16(EAD); break; + case 0xd7: EA=U+SIGNED(E); EAD=RM16(EAD); break; + case 0xd8: IMMBYTE(EA); EA=U+SIGNED(EA); EAD=RM16(EAD); break; + case 0xd9: IMMWORD(ea); EA+=U; EAD=RM16(EAD); break; + case 0xda: EA=U+SIGNED(F); EAD=RM16(EAD); break; + case 0xdb: EA=U+D; EAD=RM16(EAD); break; + case 0xdc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); break; + case 0xdd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); break; + case 0xde: EA=U+W; EAD=RM16(EAD); break; + case 0xdf: IIError(); break; + + case 0xe0: EA=S; S++; break; + case 0xe1: EA=S; S+=2; break; + case 0xe2: S--; EA=S; break; + case 0xe3: S-=2; EA=S; break; + case 0xe4: EA=S; break; + case 0xe5: EA=S+SIGNED(B); break; + case 0xe6: EA=S+SIGNED(A); break; + case 0xe7: EA=S+SIGNED(E); break; + case 0xe8: IMMBYTE(EA); EA=S+SIGNED(EA); break; + case 0xe9: IMMWORD(ea); EA+=S; break; + case 0xea: EA=S+SIGNED(F); break; + case 0xeb: EA=S+D; break; + case 0xec: IMMBYTE(EA); EA=PC+SIGNED(EA); break; + case 0xed: IMMWORD(ea); EA+=PC; break; + case 0xee: EA=S+W; break; + case 0xef: W-=2; EA=W; break; + + case 0xf0: W-=2; EA=W; EAD=RM16(EAD); break; + case 0xf1: EA=S; S+=2; EAD=RM16(EAD); break; + case 0xf2: IIError(); break; + case 0xf3: S-=2; EA=S; EAD=RM16(EAD); break; + case 0xf4: EA=S; EAD=RM16(EAD); break; + case 0xf5: EA=S+SIGNED(B); EAD=RM16(EAD); break; + case 0xf6: EA=S+SIGNED(A); EAD=RM16(EAD); break; + case 0xf7: EA=S+SIGNED(E); EAD=RM16(EAD); break; + case 0xf8: IMMBYTE(EA); EA=S+SIGNED(EA); EAD=RM16(EAD); break; + case 0xf9: IMMWORD(ea); EA+=S; EAD=RM16(EAD); break; + case 0xfa: EA=S+SIGNED(F); EAD=RM16(EAD); break; + case 0xfb: EA=S+D; EAD=RM16(EAD); break; + case 0xfc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); break; + case 0xfd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); break; + case 0xfe: EA=S+W; EAD=RM16(EAD); break; + case 0xff: IIError(); break; + } + + hd6309_ICount -= index_cycle[postbyte]; +} + +#if 0 +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void hd6309_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + HD6309_IRQ_LINE: set_irq_line(HD6309_IRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + HD6309_FIRQ_LINE:set_irq_line(HD6309_FIRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + HD6309_INPUT_LINE_NMI: set_irq_line(HD6309_INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + HD6309_PC: PC = info->i; CHANGE_PC; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + HD6309_S: S = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_CC: CC = info->i; CHECK_IRQ_LINES(); break; + case CPUINFO_INT_REGISTER + HD6309_MD: MD = info->i; UpdateState(); break; + case CPUINFO_INT_REGISTER + HD6309_U: U = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_A: A = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_B: B = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_E: E = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_F: F = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_X: X = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_Y: Y = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_V: V = info->i; break; + case CPUINFO_INT_REGISTER + HD6309_DP: DP = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void hd6309_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(hd6309); break; + case CPUINFO_INT_INPUT_LINES: info->i = 2; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 20; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + HD6309_IRQ_LINE: info->i = hd6309.irq_state[HD6309_IRQ_LINE]; break; + case CPUINFO_INT_INPUT_STATE + HD6309_FIRQ_LINE:info->i = hd6309.irq_state[HD6309_FIRQ_LINE]; break; + case CPUINFO_INT_INPUT_STATE + HD6309_INPUT_LINE_NMI: info->i = hd6309.nmi_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + HD6309_PC: info->i = PC; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + HD6309_S: info->i = S; break; + case CPUINFO_INT_REGISTER + HD6309_CC: info->i = CC; break; + case CPUINFO_INT_REGISTER + HD6309_MD: info->i = MD; break; + case CPUINFO_INT_REGISTER + HD6309_U: info->i = U; break; + case CPUINFO_INT_REGISTER + HD6309_A: info->i = A; break; + case CPUINFO_INT_REGISTER + HD6309_B: info->i = B; break; + case CPUINFO_INT_REGISTER + HD6309_E: info->i = E; break; + case CPUINFO_INT_REGISTER + HD6309_F: info->i = F; break; + case CPUINFO_INT_REGISTER + HD6309_X: info->i = X; break; + case CPUINFO_INT_REGISTER + HD6309_Y: info->i = Y; break; + case CPUINFO_INT_REGISTER + HD6309_V: info->i = V; break; + case CPUINFO_INT_REGISTER + HD6309_DP: info->i = DP; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = hd6309_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = hd6309_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = hd6309_set_context; break; + case CPUINFO_PTR_INIT: info->init = hd6309_init; break; + case CPUINFO_PTR_RESET: info->reset = hd6309_reset; break; + case CPUINFO_PTR_EXIT: info->exit = hd6309_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = hd6309_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = hd6309_dasm; break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &hd6309_ICount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "HD6309"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Hitachi 6309"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.01"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright John Butler and Tim Lindner"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c (MD:%c%c%c%c)", + hd6309.cc & 0x80 ? 'E':'.', + hd6309.cc & 0x40 ? 'F':'.', + hd6309.cc & 0x20 ? 'H':'.', + hd6309.cc & 0x10 ? 'I':'.', + hd6309.cc & 0x08 ? 'N':'.', + hd6309.cc & 0x04 ? 'Z':'.', + hd6309.cc & 0x02 ? 'V':'.', + hd6309.cc & 0x01 ? 'C':'.', + + hd6309.md & 0x80 ? 'E':'e', + hd6309.md & 0x40 ? 'F':'f', + hd6309.md & 0x02 ? 'I':'i', + hd6309.md & 0x01 ? 'Z':'z'); + break; + + case CPUINFO_STR_REGISTER + HD6309_PC: sprintf(info->s, "PC:%04X", hd6309.pc.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_S: sprintf(info->s, "S:%04X", hd6309.s.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_CC: sprintf(info->s, "CC:%02X", hd6309.cc); break; + case CPUINFO_STR_REGISTER + HD6309_MD: sprintf(info->s, "MD:%02X", hd6309.md); break; + case CPUINFO_STR_REGISTER + HD6309_U: sprintf(info->s, "U:%04X", hd6309.u.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_A: sprintf(info->s, "A:%02X", hd6309.d.b.h); break; + case CPUINFO_STR_REGISTER + HD6309_B: sprintf(info->s, "B:%02X", hd6309.d.b.l); break; + case CPUINFO_STR_REGISTER + HD6309_E: sprintf(info->s, "E:%02X", hd6309.w.b.h); break; + case CPUINFO_STR_REGISTER + HD6309_F: sprintf(info->s, "F:%02X", hd6309.w.b.l); break; + case CPUINFO_STR_REGISTER + HD6309_X: sprintf(info->s, "X:%04X", hd6309.x.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_Y: sprintf(info->s, "Y:%04X", hd6309.y.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_V: sprintf(info->s, "V:%04X", hd6309.v.w.l); break; + case CPUINFO_STR_REGISTER + HD6309_DP: sprintf(info->s, "DP:%02X", hd6309.dp.b.h); break; + } +} +#endif diff --git a/src/cpu/hd6309/hd6309.h b/src/cpu/hd6309/hd6309.h new file mode 100644 index 00000000..98e0cfc8 --- /dev/null +++ b/src/cpu/hd6309/hd6309.h @@ -0,0 +1,89 @@ +/*** hd6309: Portable 6309 emulator ******************************************/ + +//#pragma once + +#ifndef __HD6309_H__ +#define __HD6309_H__ + +//#include "cpuintrf.h" + +enum +{ + HD6309_PC=1, HD6309_S, HD6309_CC ,HD6309_A, HD6309_B, HD6309_U, HD6309_X, HD6309_Y, HD6309_DP, + HD6309_E, HD6309_F, HD6309_V, HD6309_MD +}; + +#define HD6309_IRQ_LINE 0 /* IRQ line number */ +#define HD6309_FIRQ_LINE 1 /* FIRQ line number */ +#define HD6309_INPUT_LINE_NMI 32 + +/* 6309 Registers */ +typedef struct +{ + PAIR pc; /* Program counter */ + PAIR ppc; /* Previous program counter */ + PAIR d,w; /* Accumlator d and w (ab = d, ef = w, abef = q) */ + PAIR dp; /* Direct Page register (page in MSB) */ + PAIR u, s; /* Stack pointers */ + PAIR x, y; /* Index registers */ + PAIR v; /* New 6309 register */ + UINT8 cc; + UINT8 md; /* Special mode register */ + UINT8 ireg; /* First opcode */ + UINT8 irq_state[2]; + int extra_cycles; /* cycles used up by interrupts */ + int (*irq_callback)(int irqline); + UINT8 int_state; /* SYNC and CWAI flags */ + UINT8 nmi_state; +} hd6309_Regs; + +unsigned char HD6309ReadByte(unsigned short Address); +void HD6309WriteByte(unsigned short Address, unsigned char Data); +unsigned char HD6309ReadOp(unsigned short Address); +unsigned char HD6309ReadOpArg(unsigned short Address); + +void hd6309_init(); +void hd6309_reset(void); +int hd6309_get_pc(); +int hd6309_execute(int cycles); +void hd6309_set_irq_line(int irqline, int state); +void hd6309_get_context(void *dst); +void hd6309_set_context(void *src); + + +/* PUBLIC FUNCTIONS */ +//void hd6309_get_info(UINT32 state, cpuinfo *info); + +/****************************************************************************/ +/* Read a byte from given memory location */ +/****************************************************************************/ +/* ASG 971005 -- changed to program_read_byte_8/cpu_writemem16 */ +#define HD6309_RDMEM(Addr) ((unsigned)HD6309ReadByte(Addr)) + +/****************************************************************************/ +/* Write a byte to given memory location */ +/****************************************************************************/ +#define HD6309_WRMEM(Addr,Value) (HD6309WriteByte(Addr,Value)) + +/****************************************************************************/ +/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ +/* opcodes. In case of system with memory mapped I/O, this function can be */ +/* used to greatly speed up emulation */ +/****************************************************************************/ +#define HD6309_RDOP(Addr) ((unsigned)HD6309ReadOp(Addr)) + +/****************************************************************************/ +/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */ +/* opcode arguments. This difference can be used to support systems that */ +/* use different encoding mechanisms for opcodes and opcode arguments */ +/****************************************************************************/ +#define HD6309_RDOP_ARG(Addr) ((unsigned)HD6309ReadOpArg(Addr)) + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + +#endif /* __HD6309_H__ */ diff --git a/src/cpu/hd6309_intf.cpp b/src/cpu/hd6309_intf.cpp new file mode 100644 index 00000000..a23b3b4e --- /dev/null +++ b/src/cpu/hd6309_intf.cpp @@ -0,0 +1,320 @@ +#include "burnint.h" +#include "hd6309_intf.h" + +#define MAX_CPU 8 + +INT32 nHD6309Count = 0; +static INT32 nActiveCPU = 0; + +static HD6309Ext *HD6309CPUContext; + +static INT32 nHD6309CyclesDone[MAX_CPU]; +INT32 nHD6309CyclesTotal; + +static UINT8 HD6309ReadByteDummyHandler(UINT16) +{ + return 0; +} + +static void HD6309WriteByteDummyHandler(UINT16, UINT8) +{ +} + +static UINT8 HD6309ReadOpDummyHandler(UINT16) +{ + return 0; +} + +static UINT8 HD6309ReadOpArgDummyHandler(UINT16) +{ + return 0; +} + +void HD6309Reset() +{ + hd6309_reset(); +} + +void HD6309NewFrame() +{ + for (INT32 i = 0; i < nHD6309Count; i++) { + nHD6309CyclesDone[i] = 0; + } + nHD6309CyclesTotal = 0; +} + +INT32 HD6309Init(INT32 num) +{ + nActiveCPU = -1; + nHD6309Count = num % MAX_CPU; + + HD6309CPUContext = (HD6309Ext*)malloc(num * sizeof(HD6309Ext)); + if (HD6309CPUContext == NULL) { + return 1; + } + + memset(HD6309CPUContext, 0, num * sizeof(HD6309Ext)); + + for (INT32 i = 0; i < num; i++) { + HD6309CPUContext[i].ReadByte = HD6309ReadByteDummyHandler; + HD6309CPUContext[i].WriteByte = HD6309WriteByteDummyHandler; + HD6309CPUContext[i].ReadOp = HD6309ReadOpDummyHandler; + HD6309CPUContext[i].ReadOpArg = HD6309ReadOpArgDummyHandler; + + nHD6309CyclesDone[i] = 0; + + for (INT32 j = 0; j < (0x0100 * 3); j++) { + HD6309CPUContext[i].pMemMap[j] = NULL; + } + } + + nHD6309CyclesTotal = 0; + + hd6309_init(); + + for (INT32 i = 0; i < num; i++) + CpuCheatRegister(0x0006, i); + + return 0; +} + +void HD6309Exit() +{ + nHD6309Count = 0; + + if (HD6309CPUContext) { + free(HD6309CPUContext); + HD6309CPUContext = NULL; + } +} + +void HD6309Open(INT32 num) +{ + nActiveCPU = num; + + hd6309_set_context(&HD6309CPUContext[nActiveCPU].reg); + + nHD6309CyclesTotal = nHD6309CyclesDone[nActiveCPU]; +} + +void HD6309Close() +{ + hd6309_get_context(&HD6309CPUContext[nActiveCPU].reg); + + nHD6309CyclesDone[nActiveCPU] = nHD6309CyclesTotal; + + nActiveCPU = -1; +} + +INT32 HD6309GetActive() +{ + return nActiveCPU; +} + +void HD6309SetIRQ(INT32 vector, INT32 status) +{ + if (status == HD6309_IRQSTATUS_NONE) { + hd6309_set_irq_line(vector, 0); + } + + if (status == HD6309_IRQSTATUS_ACK) { + hd6309_set_irq_line(vector, 1); + } + + if (status == HD6309_IRQSTATUS_AUTO) { + hd6309_set_irq_line(vector, 1); + hd6309_execute(0); + hd6309_set_irq_line(vector, 0); + hd6309_execute(0); + } +} + +INT32 HD6309Run(INT32 cycles) +{ + cycles = hd6309_execute(cycles); + + nHD6309CyclesTotal += cycles; + + return cycles; +} + +void HD6309RunEnd() +{ + +} + +INT32 HD6309GetPC() +{ + return hd6309_get_pc(); +} + +INT32 HD6309MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = HD6309CPUContext[nActiveCPU].pMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + if (nType & HD6309_READ) { + pMemMap[0 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & HD6309_WRITE) { + pMemMap[0x100 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & HD6309_FETCH) { + pMemMap[0x200 + i] = pMemory + ((i - cStart) << 8); + } + } + return 0; + +} + +INT32 HD6309MemCallback(UINT16 nStart, UINT16 nEnd, INT32 nType) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = HD6309CPUContext[nActiveCPU].pMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + if (nType & HD6309_READ) { + pMemMap[0 + i] = NULL; + } + if (nType & HD6309_WRITE) { + pMemMap[0x100 + i] = NULL; + } + if (nType & HD6309_FETCH) { + pMemMap[0x200 + i] = NULL; + } + } + return 0; + +} + +void HD6309SetReadByteHandler(UINT8 (*pHandler)(UINT16)) +{ + HD6309CPUContext[nActiveCPU].ReadByte = pHandler; +} + +void HD6309SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)) +{ + HD6309CPUContext[nActiveCPU].WriteByte = pHandler; +} + +void HD6309SetReadOpHandler(UINT8 (*pHandler)(UINT16)) +{ + HD6309CPUContext[nActiveCPU].ReadOp = pHandler; +} + +void HD6309SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)) +{ + HD6309CPUContext[nActiveCPU].ReadOpArg = pHandler; +} + +UINT8 HD6309ReadByte(UINT16 Address) +{ + // check mem map + UINT8 * pr = HD6309CPUContext[nActiveCPU].pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (HD6309CPUContext[nActiveCPU].ReadByte != NULL) { + return HD6309CPUContext[nActiveCPU].ReadByte(Address); + } + + return 0; +} + +void HD6309WriteByte(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = HD6309CPUContext[nActiveCPU].pMemMap[0x100 | (Address >> 8)]; + if (pr != NULL) { + pr[Address & 0xff] = Data; + return; + } + + // check handler + if (HD6309CPUContext[nActiveCPU].WriteByte != NULL) { + HD6309CPUContext[nActiveCPU].WriteByte(Address, Data); + return; + } +} + +UINT8 HD6309ReadOp(UINT16 Address) +{ + // check mem map + UINT8 * pr = HD6309CPUContext[nActiveCPU].pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (HD6309CPUContext[nActiveCPU].ReadOp != NULL) { + return HD6309CPUContext[nActiveCPU].ReadOp(Address); + } + + return 0; +} + +UINT8 HD6309ReadOpArg(UINT16 Address) +{ + // check mem map + UINT8 * pr = HD6309CPUContext[nActiveCPU].pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (HD6309CPUContext[nActiveCPU].ReadOpArg != NULL) { + return HD6309CPUContext[nActiveCPU].ReadOpArg(Address); + } + + return 0; +} + +void HD6309WriteRom(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = HD6309CPUContext[nActiveCPU].pMemMap[0x000 | (Address >> 8)]; + UINT8 * pw = HD6309CPUContext[nActiveCPU].pMemMap[0x100 | (Address >> 8)]; + UINT8 * pf = HD6309CPUContext[nActiveCPU].pMemMap[0x200 | (Address >> 8)]; + + if (pr != NULL) { + pr[Address & 0xff] = Data; + } + + if (pw != NULL) { + pw[Address & 0xff] = Data; + } + + if (pf != NULL) { + pf[Address & 0xff] = Data; + } + + // check handler + if (HD6309CPUContext[nActiveCPU].WriteByte != NULL) { + HD6309CPUContext[nActiveCPU].WriteByte(Address, Data); + return; + } +} + +INT32 HD6309Scan(INT32 nAction) +{ + struct BurnArea ba; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + for (INT32 i = 0; i < nHD6309Count; i++) { + char szName[] = "HD6309 #n"; + szName[7] = '0' + i; + + ba.Data = &HD6309CPUContext[i]; + ba.nLen = sizeof(HD6309CPUContext[i]); + ba.szName = szName; + BurnAcb(&ba); + } + + return 0; +} diff --git a/src/cpu/hd6309_intf.h b/src/cpu/hd6309_intf.h new file mode 100644 index 00000000..70d1154e --- /dev/null +++ b/src/cpu/hd6309_intf.h @@ -0,0 +1,63 @@ +#include "hd6309.h" + +typedef UINT8 (*pReadByteHandler)(UINT16 a); +typedef void (*pWriteByteHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadOpHandler)(UINT16 a); +typedef UINT8 (*pReadOpArgHandler)(UINT16 a); + +struct HD6309Ext { + + hd6309_Regs reg; + + UINT8* pMemMap[0x100 * 3]; + + pReadByteHandler ReadByte; + pWriteByteHandler WriteByte; + pReadOpHandler ReadOp; + pReadOpArgHandler ReadOpArg; + + INT32 nCyclesTotal; + INT32 nCyclesSegment; + INT32 nCyclesLeft; +}; + +#define HD6309_IRQSTATUS_NONE 0 +#define HD6309_IRQSTATUS_ACK 1 +#define HD6309_IRQSTATUS_AUTO 2 + +#define HD6309_READ 1 +#define HD6309_WRITE 2 +#define HD6309_FETCH 4 + +#define HD6309_RAM (HD6309_READ | HD6309_WRITE | HD6309_FETCH) +#define HD6309_ROM (HD6309_READ | HD6309_FETCH) + +extern INT32 nHD6309Count; + +extern INT32 nHD6309CyclesTotal; + +void HD6309Reset(); +void HD6309NewFrame(); +INT32 HD6309Init(INT32 num); +void HD6309Exit(); +void HD6309Open(INT32 num); +void HD6309Close(); +INT32 HD6309GetActive(); +void HD6309SetIRQ(INT32 vector, INT32 status); +INT32 HD6309Run(INT32 cycles); +void HD6309RunEnd(); +INT32 HD6309GetPC(); +INT32 HD6309MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType); +INT32 HD6309MemCallback(UINT16 nStart, UINT16 nEnd, INT32 nType); +void HD6309SetReadByteHandler(UINT8 (*pHandler)(UINT16)); +void HD6309SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)); +void HD6309SetReadOpHandler(UINT8 (*pHandler)(UINT16)); +void HD6309SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)); +INT32 HD6309Scan(INT32 nAction); + +void HD6309WriteRom(UINT16 Address, UINT8 Data); + +inline static INT32 HD6309TotalCycles() +{ + return nHD6309CyclesTotal; +} diff --git a/src/cpu/i8039/i8039.cpp b/src/cpu/i8039/i8039.cpp new file mode 100644 index 00000000..e756d578 --- /dev/null +++ b/src/cpu/i8039/i8039.cpp @@ -0,0 +1,1256 @@ +/**************************************************************************** + * Intel 8039 Portable Emulator * + * * + * Copyright Mirko Buffoni * + * Based on the original work Copyright Dan Boris, an 8048 emulator * + * You are not allowed to distribute this software commercially * + * Please, notify me, if you make any changes to this file * + * * + * * + * **** Change Log **** * + * * + * TLP (19-Jun-2001) * + * - Changed Ports 1 and 2 to quasi bidirectional output latched ports * + * - Added the Port 1 & 2 output latch data to the debugger window * + * TLP (02-Jan-2002) * + * - External IRQs no longer go pending (sampled as a level state) * + * - Timer IRQs do not go pending if Timer interrupts are disabled * + * - Timer IRQs made pending, were incorrectly being cleared if the * + * external interrupt was being serviced * + * - External interrupts now take precedence when simultaneous * + * internal and external interrupt requests occur * + * - 'DIS TCNTI' now removes pending timer IRQs * + * - Nested IRQs of any sort are no longer allowed * + * - T_flag was not being set in the right place of execution, which * + * could have lead to it being incorrectly set after being cleared * + * - Counter overflows now also set the T_flag * + * - Added the Timer/Counter register to the debugger window * + * TLP (09-Jan-2002) * + * - Changed Interrupt system to instant servicing * + * - The Timer and Counter can no longer be 'on' simultaneously * + * - Added Save State * + * TLP (15-Feb-2002) * + * - Corrected Positive signal edge sensing (used on the T1 input) * + ****************************************************************************/ + + +#include "burnint.h" +#include "i8039.h" + +typedef union +{ + struct { UINT8 l,h,h2,h3; } b; + struct { UINT16 l,h; } w; + UINT32 d; +} I8039_PAIR; + +/*** Cycle times for the jump on condition instructions, are unusual. + Condition is tested during the first cycle, so if condition is not + met, second address fetch cycle may not really be taken. For now we + just use the cycle counts as listed in the i8048 user manual. +***/ + +#if 0 +#define ADJUST_CYCLES { inst_cycles -= 1; } /* Possible real cycles setting */ +#else +#define ADJUST_CYCLES { } /* User Manual cycles setting */ +#endif + +/* There are certain differences between the processors */ +#define FEATURE_M58715 1 + +/* HJB 01/05/99 changed to positive values to use pending_irq as a flag */ +#define I8039_NO_INT 0 /* No Interrupts pending or executing */ +#define I8039_EXTERNAL_INT 1 /* Execute a normal external interrupt */ +#define I8039_TIMCNT_INT 2 /* Execute a Timer/Counter interrupt */ + + +static int Ext_IRQ(void); +static int Timer_IRQ(void); + +#define M_RDMEM(A) I8039_RDMEM(A) +//#define M_RDOP(A) I8039_RDOP(A) +//#define M_RDOP_ARG(A) I8039_RDOP_ARG(A) +#define M_IN(A) I8039_In(A) +#define M_OUT(A,V) I8039_Out(A,V) + +#define port_r(A) I8039_In(I8039_p0 + A) +#define port_w(A,V) I8039_Out(I8039_p0 + A,V) +#define test_r(A) I8039_In(I8039_t0 + A) +#define test_w(A,V) I8039_Out(I8039_t0 + A,V) +#define bus_r() I8039_In(I8039_bus) +#define bus_w(V) I8039_Out(I8039_bus,V) + +#define INTRAM_R(A) (intRAM[(A) & R.ram_mask]) +#define INTRAM_W(A,V) do { intRAM[(A) & R.ram_mask] = V; } while (0); + +#define C_FLAG 0x80 +#define A_FLAG 0x40 +#define F_FLAG 0x20 +#define B_FLAG 0x10 + +typedef struct +{ + I8039_PAIR PREVPC; /* previous program counter */ + I8039_PAIR PC; /* program counter */ + UINT8 A, SP, PSW; + UINT8 RAM[128]; + UINT8 bus, f1; /* Bus data, and flag1 */ + UINT8 P1, P2; /* Internal Port 1 and 2 latched outputs */ + UINT8 EA; /* latched EA input */ + UINT8 cpu_feature; /* process feature */ + UINT8 ram_mask; /* internal ram size - 1 */ + UINT16 int_rom_size; /* internal rom size */ + UINT8 pending_irq, irq_executing, masterClock, regPtr; + UINT8 t_flag, timer, timerON, countON, xirq_en, tirq_en; + UINT16 A11; + UINT8 irq_state, irq_extra_cycles; + int (*irq_callback)(int irqline); + int inst_cycles; + UINT8 Old_T1; +} I8039_Regs; + +static I8039_Regs R; +static int i8039_ICount; + +#define I8039_INLINE static inline +#define change_pc(newpc) R.PC.w.l = (newpc) + +i8039ReadIoHandler I8039IORead; +i8039WriteIoHandler I8039IOWrite; +i8039ReadProgHandler I8039ProgramRead; +i8039WriteProgHandler I8039ProgramWrite; +i8039ReadOpHandler I8039CPUReadOp; +i8039ReadOpArgHandler I8039CPUReadOpArg; + +unsigned char __fastcall I8039DummyReadIo(unsigned int) +{ + return 0; +} + +void __fastcall I8039DummyWriteIo(unsigned int, unsigned char) +{ +} + +unsigned char __fastcall I8039DummyReadProg(unsigned int) +{ + return 0; +} + +void __fastcall I8039DummyWriteProg(unsigned int, unsigned char) +{ +} + +unsigned char __fastcall I8039DummyReadOp(unsigned int) +{ + return 0; +} + +unsigned char __fastcall I8039DummyReadOpArg(unsigned int) +{ + return 0; +} + +/* The opcode table now is a combination of cycle counts and function pointers */ +typedef struct { + unsigned cycles; + void (*function) (void); +} s_opcode; + +#define POSITIVE_EDGE_T1 (( (int)(T1-R.Old_T1) > 0) ? 1 : 0) +#define NEGATIVE_EDGE_T1 (( (int)(R.Old_T1-T1) > 0) ? 1 : 0) + +#define M_Cy ((R.PSW & C_FLAG) >> 7) +#define M_Cn (!M_Cy) +#define M_Ay ((R.PSW & A_FLAG)) +#define M_An (!M_Ay) +#define M_F0y ((R.PSW & F_FLAG)) +#define M_F0n (!M_F0y) +#define M_By ((R.PSW & B_FLAG)) +#define M_Bn (!M_By) + +#define intRAM R.RAM +#define regPTR R.regPtr + +#define R0 intRAM[regPTR ] +#define R1 intRAM[regPTR+1] +#define R2 intRAM[regPTR+2] +#define R3 intRAM[regPTR+3] +#define R4 intRAM[regPTR+4] +#define R5 intRAM[regPTR+5] +#define R6 intRAM[regPTR+6] +#define R7 intRAM[regPTR+7] + +I8039_INLINE UINT8 ea_r(void) +{ + R.EA = I8039_In(I8039_ea); + return R.EA; +} + +I8039_INLINE UINT8 M_RDOP(int A) +{ + if (R.cpu_feature & FEATURE_M58715) + if ((A> 1); +} + +I8039_INLINE UINT8 pull(void) { + R.SP = (R.SP + 15) & 0x0f; /* if (--R.SP < 0) R.SP = 15; */ + R.PSW = R.PSW & 0xf8; + R.PSW = R.PSW | (R.SP >> 1); + /* regPTR = ((M_By) ? 24 : 0); regPTR should not change */ + return intRAM[8+R.SP]; +} + +I8039_INLINE void daa_a(void) +{ + if ((R.A & 0x0f) > 0x09 || (R.PSW & A_FLAG)) + { + R.A += 0x06; + if ( ! ( R.A & 0xf0 ) ) + SET(C_FLAG); + } + if ((R.A & 0xf0) > 0x90 || (R.PSW & C_FLAG)) + { + R.A += 0x60; + SET(C_FLAG); + } else CLR(C_FLAG); +} + +I8039_INLINE void M_ADD(UINT8 dat) +{ + UINT16 temp; + + CLR(C_FLAG | A_FLAG); + if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG); + temp = R.A + dat; + if (temp > 0xff) SET(C_FLAG); + R.A = temp & 0xff; +} + +I8039_INLINE void M_ADDC(UINT8 dat) +{ + UINT16 temp; + + CLR(A_FLAG); + if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG); + temp = R.A + dat + M_Cy; + CLR(C_FLAG); + if (temp > 0xff) SET(C_FLAG); + R.A = temp & 0xff; +} + +I8039_INLINE void M_CALL(UINT16 addr) +{ + push(R.PC.b.l); + push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0)); + R.PC.w.l = addr; + change_pc(addr); +} + +I8039_INLINE void M_XCHD(UINT8 addr) +{ + UINT8 dat = R.A & 0x0f; + UINT8 val = INTRAM_R(addr); + R.A &= 0xf0; + R.A |= val & 0x0f; + val &= 0xf0; + val |= dat; + INTRAM_W(addr, val); +} + + +I8039_INLINE void M_ILLEGAL(void) +{ +// logerror("I8039: PC = %04x, Illegal opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1)); +} + +I8039_INLINE void M_UNDEFINED(void) +{ +// logerror("I8039: PC = %04x, Unimplemented opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1)); +} + +static void illegal(void) { M_ILLEGAL(); } + +static void add_a_n(void) { M_ADD(M_RDMEM_OPCODE()); } +static void add_a_r0(void) { M_ADD(R0); } +static void add_a_r1(void) { M_ADD(R1); } +static void add_a_r2(void) { M_ADD(R2); } +static void add_a_r3(void) { M_ADD(R3); } +static void add_a_r4(void) { M_ADD(R4); } +static void add_a_r5(void) { M_ADD(R5); } +static void add_a_r6(void) { M_ADD(R6); } +static void add_a_r7(void) { M_ADD(R7); } +static void add_a_xr0(void) { M_ADD(INTRAM_R(R0)); } +static void add_a_xr1(void) { M_ADD(INTRAM_R(R1)); } +static void adc_a_n(void) { M_ADDC(M_RDMEM_OPCODE()); } +static void adc_a_r0(void) { M_ADDC(R0); } +static void adc_a_r1(void) { M_ADDC(R1); } +static void adc_a_r2(void) { M_ADDC(R2); } +static void adc_a_r3(void) { M_ADDC(R3); } +static void adc_a_r4(void) { M_ADDC(R4); } +static void adc_a_r5(void) { M_ADDC(R5); } +static void adc_a_r6(void) { M_ADDC(R6); } +static void adc_a_r7(void) { M_ADDC(R7); } +static void adc_a_xr0(void) { M_ADDC(INTRAM_R(R0)); } +static void adc_a_xr1(void) { M_ADDC(INTRAM_R(R1)); } +static void anl_a_n(void) { R.A &= M_RDMEM_OPCODE(); } +static void anl_a_r0(void) { R.A &= R0; } +static void anl_a_r1(void) { R.A &= R1; } +static void anl_a_r2(void) { R.A &= R2; } +static void anl_a_r3(void) { R.A &= R3; } +static void anl_a_r4(void) { R.A &= R4; } +static void anl_a_r5(void) { R.A &= R5; } +static void anl_a_r6(void) { R.A &= R6; } +static void anl_a_r7(void) { R.A &= R7; } +static void anl_a_xr0(void) { R.A &= INTRAM_R(R0); } +static void anl_a_xr1(void) { R.A &= INTRAM_R(R1); } +static void anl_bus_n(void) { bus_w( bus_r() & M_RDMEM_OPCODE() ); } + +static void anl_p1_n(void) +{ + R.P1 &= M_RDMEM_OPCODE(); + port_w( 1, R.P1 ); +} + +static void anl_p2_n(void) +{ + R.P2 &= M_RDMEM_OPCODE(); + port_w( 2, R.P2 ); +} + +static void anld_p4_a(void) { port_w( 4, (port_r(4) & M_RDMEM_OPCODE()) & 0x0f ); } +static void anld_p5_a(void) { port_w( 5, (port_r(5) & M_RDMEM_OPCODE()) & 0x0f ); } +static void anld_p6_a(void) { port_w( 6, (port_r(6) & M_RDMEM_OPCODE()) & 0x0f ); } +static void anld_p7_a(void) { port_w( 7, (port_r(7) & M_RDMEM_OPCODE()) & 0x0f ); } +static void call(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | a11); } +static void call_1(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x100 | a11); } +static void call_2(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x200 | a11); } +static void call_3(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x300 | a11); } +static void call_4(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x400 | a11); } +static void call_5(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x500 | a11); } +static void call_6(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x600 | a11); } +static void call_7(void) { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x700 | a11); } +static void clr_a(void) { R.A=0; } +static void clr_c(void) { CLR(C_FLAG); } +static void clr_f0(void) { CLR(F_FLAG); } +static void clr_f1(void) { R.f1 = 0; } +static void cpl_a(void) { R.A ^= 0xff; } +static void cpl_c(void) { R.PSW ^= C_FLAG; } +static void cpl_f0(void) { R.PSW ^= F_FLAG; } +static void cpl_f1(void) { R.f1 ^= 1; } +static void dec_a(void) { R.A--; } +static void dec_r0(void) { R0--; } +static void dec_r1(void) { R1--; } +static void dec_r2(void) { R2--; } +static void dec_r3(void) { R3--; } +static void dec_r4(void) { R4--; } +static void dec_r5(void) { R5--; } +static void dec_r6(void) { R6--; } +static void dec_r7(void) { R7--; } +static void dis_i(void) { R.xirq_en = 0; } +static void dis_tcnti(void) { R.tirq_en = 0; R.pending_irq &= ~I8039_TIMCNT_INT; } +static void djnz_r0(void) { UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r1(void) { UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r2(void) { UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r3(void) { UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r4(void) { UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r5(void) { UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r6(void) { UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void djnz_r7(void) { UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void en_i(void) { R.xirq_en = 1; if (R.irq_state == I8039_EXTERNAL_INT) { R.irq_extra_cycles += Ext_IRQ(); } } +static void en_tcnti(void) { R.tirq_en = 1; } +static void ento_clk(void) { M_UNDEFINED(); } +static void in_a_p1(void) { R.A = port_r(1) & R.P1; } +static void in_a_p2(void) { R.A = port_r(2) & R.P2; } +static void ins_a_bus(void) { R.A = bus_r(); } +static void inc_a(void) { R.A++; } +static void inc_r0(void) { R0++; } +static void inc_r1(void) { R1++; } +static void inc_r2(void) { R2++; } +static void inc_r3(void) { R3++; } +static void inc_r4(void) { R4++; } +static void inc_r5(void) { R5++; } +static void inc_r6(void) { R6++; } +static void inc_r7(void) { R7++; } +static void inc_xr0(void) { INTRAM_W(R0, INTRAM_R(R0) + 1); } +static void inc_xr1(void) { INTRAM_W(R1, INTRAM_R(R1) + 1); } + +static void jmp(void) +{ + UINT8 i=M_RDOP(R.PC.w.l); + UINT16 oldpc,newpc; + UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; + + oldpc = R.PC.w.l-1; + R.PC.w.l = i | a11; + change_pc(R.PC.w.l); + newpc = R.PC.w.l; + if (newpc == oldpc) { if (i8039_ICount > 0) i8039_ICount = 0; } /* speed up busy loop */ + else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00) /* NOP - Gyruss */ + { if (i8039_ICount > 0) i8039_ICount = 0; } +} + +static void jmp_1(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x100 | a11; change_pc(R.PC.w.l); } +static void jmp_2(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x200 | a11; change_pc(R.PC.w.l); } +static void jmp_3(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x300 | a11; change_pc(R.PC.w.l); } +static void jmp_4(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x400 | a11; change_pc(R.PC.w.l); } +static void jmp_5(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x500 | a11; change_pc(R.PC.w.l); } +static void jmp_6(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x600 | a11; change_pc(R.PC.w.l); } +static void jmp_7(void) { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x700 | a11; change_pc(R.PC.w.l); } +static void jmpp_xa(void) { UINT16 addr = (R.PC.w.l & 0xf00) | R.A; R.PC.w.l = (R.PC.w.l & 0xf00) | M_RDMEM(addr); change_pc(R.PC.w.l); } +static void jb_0(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_1(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_2(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_3(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_4(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_5(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_6(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jb_7(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jf0(void) { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jf1(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.f1) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jnc(void) { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jc(void) { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jni(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state == I8039_EXTERNAL_INT) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jnt_0(void) { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jt_0(void) { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jnt_1(void) { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jt_1(void) { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jnz(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jz(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES } +static void jtf(void) { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); R.t_flag = 0; } else ADJUST_CYCLES } +static void mov_a_n(void) { R.A = M_RDMEM_OPCODE(); } +static void mov_a_r0(void) { R.A = R0; } +static void mov_a_r1(void) { R.A = R1; } +static void mov_a_r2(void) { R.A = R2; } +static void mov_a_r3(void) { R.A = R3; } +static void mov_a_r4(void) { R.A = R4; } +static void mov_a_r5(void) { R.A = R5; } +static void mov_a_r6(void) { R.A = R6; } +static void mov_a_r7(void) { R.A = R7; } +static void mov_a_psw(void) { R.A = R.PSW; } +static void mov_a_xr0(void) { R.A = INTRAM_R(R0); } +static void mov_a_xr1(void) { R.A = INTRAM_R(R1); } +static void mov_r0_a(void) { R0 = R.A; } +static void mov_r1_a(void) { R1 = R.A; } +static void mov_r2_a(void) { R2 = R.A; } +static void mov_r3_a(void) { R3 = R.A; } +static void mov_r4_a(void) { R4 = R.A; } +static void mov_r5_a(void) { R5 = R.A; } +static void mov_r6_a(void) { R6 = R.A; } +static void mov_r7_a(void) { R7 = R.A; } +static void mov_psw_a(void) { R.PSW = R.A; regPTR = ((M_By) ? 24 : 0); R.SP = (R.PSW & 7) << 1; } +static void mov_r0_n(void) { R0 = M_RDMEM_OPCODE(); } +static void mov_r1_n(void) { R1 = M_RDMEM_OPCODE(); } +static void mov_r2_n(void) { R2 = M_RDMEM_OPCODE(); } +static void mov_r3_n(void) { R3 = M_RDMEM_OPCODE(); } +static void mov_r4_n(void) { R4 = M_RDMEM_OPCODE(); } +static void mov_r5_n(void) { R5 = M_RDMEM_OPCODE(); } +static void mov_r6_n(void) { R6 = M_RDMEM_OPCODE(); } +static void mov_r7_n(void) { R7 = M_RDMEM_OPCODE(); } +static void mov_a_t(void) { R.A = R.timer; } +static void mov_t_a(void) { R.timer = R.A; } +static void mov_xr0_a(void) { INTRAM_W(R0, R.A); } +static void mov_xr1_a(void) { INTRAM_W(R1, R.A); } +static void mov_xr0_n(void) { INTRAM_W(R0, M_RDMEM_OPCODE()); } +static void mov_xr1_n(void) { INTRAM_W(R1, M_RDMEM_OPCODE()); } +static void movd_a_p4(void) { R.A = port_r(4) & 0x0F; } +static void movd_a_p5(void) { R.A = port_r(5) & 0x0F; } +static void movd_a_p6(void) { R.A = port_r(6) & 0x0F; } +static void movd_a_p7(void) { R.A = port_r(7) & 0x0F; } +static void movd_p4_a(void) { port_w(4, R.A & 0x0F); } +static void movd_p5_a(void) { port_w(5, R.A & 0x0F); } +static void movd_p6_a(void) { port_w(6, R.A & 0x0F); } +static void movd_p7_a(void) { port_w(7, R.A & 0x0F); } +static void movp_a_xa(void) { R.A = M_RDMEM((R.PC.w.l & 0x0f00) | R.A); } +static void movp3_a_xa(void) { R.A = M_RDMEM(0x300 | R.A); } +static void movx_a_xr0(void) { R.A = M_IN(R0); } +static void movx_a_xr1(void) { R.A = M_IN(R1); } +static void movx_xr0_a(void) { M_OUT(R0, R.A); } +static void movx_xr1_a(void) { M_OUT(R1, R.A); } +static void nop(void) { } +static void orl_a_n(void) { R.A |= M_RDMEM_OPCODE(); } +static void orl_a_r0(void) { R.A |= R0; } +static void orl_a_r1(void) { R.A |= R1; } +static void orl_a_r2(void) { R.A |= R2; } +static void orl_a_r3(void) { R.A |= R3; } +static void orl_a_r4(void) { R.A |= R4; } +static void orl_a_r5(void) { R.A |= R5; } +static void orl_a_r6(void) { R.A |= R6; } +static void orl_a_r7(void) { R.A |= R7; } +static void orl_a_xr0(void) { R.A |= INTRAM_R(R0); } +static void orl_a_xr1(void) { R.A |= INTRAM_R(R1); } +static void orl_bus_n(void) { bus_w( bus_r() | M_RDMEM_OPCODE() ); } +static void orl_p1_n(void) +{ + R.P1 |= M_RDMEM_OPCODE(); + port_w(1, R.P1); +} + +static void orl_p2_n(void) +{ + R.P2 |= M_RDMEM_OPCODE(); + port_w(2, R.P2); +} + +static void orld_p4_a(void) { port_w(4, port_r(4) | R.A ); } +static void orld_p5_a(void) { port_w(5, port_r(5) | R.A ); } +static void orld_p6_a(void) { port_w(6, port_r(6) | R.A ); } +static void orld_p7_a(void) { port_w(7, port_r(7) | R.A ); } +static void outl_bus_a(void) { bus_w(R.A); } +static void outl_p1_a(void) { port_w(1, R.A); R.P1 = R.A; } +static void outl_p2_a(void) { port_w(2, R.A); R.P2 = R.A; } +static void ret(void) { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull(); change_pc(R.PC.w.l); } + +static void retr(void) +{ + UINT8 i=pull(); + R.PC.w.l = ((i & 0x0f) << 8) | pull(); + change_pc(R.PC.w.l); + R.PSW = (R.PSW & 0x0f) | (i & 0xf0); /* Stack is already changed by pull */ + regPTR = ((M_By) ? 24 : 0); + + R.irq_executing = I8039_NO_INT; + + /* Take an interrupt if a request is still being made */ + if (R.irq_state == I8039_EXTERNAL_INT) { + R.irq_extra_cycles += Ext_IRQ(); /* Service External IRQ */ + } + else if (R.pending_irq == I8039_TIMCNT_INT) { + R.irq_extra_cycles += Timer_IRQ(); /* Service pending Timer/Counter IRQ */ + } +} +static void rl_a(void) { UINT8 i=R.A & 0x80; R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; } +/* NS990113 */ +static void rlc_a(void) { UINT8 i=M_Cy; if (R.A & 0x80) SET(C_FLAG); else CLR(C_FLAG); R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; } +static void rr_a(void) { UINT8 i=R.A & 1; R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; } +/* NS990113 */ +static void rrc_a(void) { UINT8 i=M_Cy; if (R.A & 1) SET(C_FLAG); else CLR(C_FLAG); R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; } +static void sel_mb0(void) { R.A11 = 0x000; } +static void sel_mb1(void) { R.A11 = 0x800; } +static void sel_rb0(void) { CLR(B_FLAG); regPTR = 0; } +static void sel_rb1(void) { SET(B_FLAG); regPTR = 24; } +static void stop_tcnt(void) { R.timerON = R.countON = 0; } +static void strt_cnt(void) { R.countON = 1; R.timerON = 0; R.Old_T1 = test_r(1); } /* NS990113 */ +static void strt_t(void) { R.timerON = 1; R.countON = 0; R.masterClock = 0; } /* NS990113 */ +static void swap_a(void) { UINT8 i=R.A >> 4; R.A <<= 4; R.A |= i; } +static void xch_a_r0(void) { UINT8 i=R.A; R.A=R0; R0=i; } +static void xch_a_r1(void) { UINT8 i=R.A; R.A=R1; R1=i; } +static void xch_a_r2(void) { UINT8 i=R.A; R.A=R2; R2=i; } +static void xch_a_r3(void) { UINT8 i=R.A; R.A=R3; R3=i; } +static void xch_a_r4(void) { UINT8 i=R.A; R.A=R4; R4=i; } +static void xch_a_r5(void) { UINT8 i=R.A; R.A=R5; R5=i; } +static void xch_a_r6(void) { UINT8 i=R.A; R.A=R6; R6=i; } +static void xch_a_r7(void) { UINT8 i=R.A; R.A=R7; R7=i; } +static void xch_a_xr0(void) { UINT8 i=R.A; R.A=INTRAM_R(R0); INTRAM_W(R0, i); } +static void xch_a_xr1(void) { UINT8 i=R.A; R.A=INTRAM_R(R1); INTRAM_W(R1, i); } +static void xchd_a_xr0(void) { M_XCHD(R0); } +static void xchd_a_xr1(void) { M_XCHD(R1); } +static void xrl_a_n(void) { R.A ^= M_RDMEM_OPCODE(); } +static void xrl_a_r0(void) { R.A ^= R0; } +static void xrl_a_r1(void) { R.A ^= R1; } +static void xrl_a_r2(void) { R.A ^= R2; } +static void xrl_a_r3(void) { R.A ^= R3; } +static void xrl_a_r4(void) { R.A ^= R4; } +static void xrl_a_r5(void) { R.A ^= R5; } +static void xrl_a_r6(void) { R.A ^= R6; } +static void xrl_a_r7(void) { R.A ^= R7; } +static void xrl_a_xr0(void) { R.A ^= INTRAM_R(R0); } +static void xrl_a_xr1(void) { R.A ^= INTRAM_R(R1); } + +static const s_opcode opcode_main[256]= +{ + {1, nop },{0, illegal },{2, outl_bus_a},{2, add_a_n },{2, jmp },{1, en_i },{0, illegal },{1, dec_a }, + {2, ins_a_bus },{2, in_a_p1 },{2, in_a_p2 },{0, illegal },{2, movd_a_p4 },{2, movd_a_p5 },{2, movd_a_p6 },{2, movd_a_p7 }, + {1, inc_xr0 },{1, inc_xr1 },{2, jb_0 },{2, adc_a_n },{2, call },{1, dis_i },{2, jtf },{1, inc_a }, + {1, inc_r0 },{1, inc_r1 },{1, inc_r2 },{1, inc_r3 },{1, inc_r4 },{1, inc_r5 },{1, inc_r6 },{1, inc_r7 }, + {1, xch_a_xr0 },{1, xch_a_xr1 },{0, illegal },{2, mov_a_n },{2, jmp_1 },{1, en_tcnti },{2, jnt_0 },{1, clr_a }, + {1, xch_a_r0 },{1, xch_a_r1 },{1, xch_a_r2 },{1, xch_a_r3 },{1, xch_a_r4 },{1, xch_a_r5 },{1, xch_a_r6 },{1, xch_a_r7 }, + {1, xchd_a_xr0 },{1, xchd_a_xr1 },{2, jb_1 },{0, illegal },{2, call_1 },{1, dis_tcnti },{2, jt_0 },{1, cpl_a }, + {0, illegal },{2, outl_p1_a },{2, outl_p2_a },{0, illegal },{2, movd_p4_a },{2, movd_p5_a },{2, movd_p6_a },{2, movd_p7_a }, + {1, orl_a_xr0 },{1, orl_a_xr1 },{1, mov_a_t },{2, orl_a_n },{2, jmp_2 },{1, strt_cnt },{2, jnt_1 },{1, swap_a }, + {1, orl_a_r0 },{1, orl_a_r1 },{1, orl_a_r2 },{1, orl_a_r3 },{1, orl_a_r4 },{1, orl_a_r5 },{1, orl_a_r6 },{1, orl_a_r7 }, + {1, anl_a_xr0 },{1, anl_a_xr1 },{2, jb_2 },{2, anl_a_n },{2, call_2 },{1, strt_t },{2, jt_1 },{1, daa_a }, + {1, anl_a_r0 },{1, anl_a_r1 },{1, anl_a_r2 },{1, anl_a_r3 },{1, anl_a_r4 },{1, anl_a_r5 },{1, anl_a_r6 },{1, anl_a_r7 }, + {1, add_a_xr0 },{1, add_a_xr1 },{1, mov_t_a },{0, illegal },{2, jmp_3 },{1, stop_tcnt },{0, illegal },{1, rrc_a }, + {1, add_a_r0 },{1, add_a_r1 },{1, add_a_r2 },{1, add_a_r3 },{1, add_a_r4 },{1, add_a_r5 },{1, add_a_r6 },{1, add_a_r7 }, + {1, adc_a_xr0 },{1, adc_a_xr1 },{2, jb_3 },{0, illegal },{2, call_3 },{1, ento_clk },{2, jf1 },{1, rr_a }, + {1, adc_a_r0 },{1, adc_a_r1 },{1, adc_a_r2 },{1, adc_a_r3 },{1, adc_a_r4 },{1, adc_a_r5 },{1, adc_a_r6 },{1, adc_a_r7 }, + {2, movx_a_xr0 },{2, movx_a_xr1 },{0, illegal },{2, ret },{2, jmp_4 },{1, clr_f0 },{2, jni },{0, illegal }, + {2, orl_bus_n },{2, orl_p1_n },{2, orl_p2_n },{0, illegal },{2, orld_p4_a },{2, orld_p5_a },{2, orld_p6_a },{2, orld_p7_a }, + {2, movx_xr0_a },{2, movx_xr1_a },{2, jb_4 },{2, retr },{2, call_4 },{1, cpl_f0 },{2, jnz },{1, clr_c }, + {2, anl_bus_n },{2, anl_p1_n },{2, anl_p2_n },{0, illegal },{2, anld_p4_a },{2, anld_p5_a },{2, anld_p6_a },{2, anld_p7_a }, + {1, mov_xr0_a },{1, mov_xr1_a },{0, illegal },{2, movp_a_xa },{2, jmp_5 },{1, clr_f1 },{0, illegal },{1, cpl_c }, + {1, mov_r0_a },{1, mov_r1_a },{1, mov_r2_a },{1, mov_r3_a },{1, mov_r4_a },{1, mov_r5_a },{1, mov_r6_a },{1, mov_r7_a }, + {2, mov_xr0_n },{2, mov_xr1_n },{2, jb_5 },{2, jmpp_xa },{2, call_5 },{1, cpl_f1 },{2, jf0 },{0, illegal }, + {2, mov_r0_n },{2, mov_r1_n },{2, mov_r2_n },{2, mov_r3_n },{2, mov_r4_n },{2, mov_r5_n },{2, mov_r6_n },{2, mov_r7_n }, + {0, illegal },{0, illegal },{0, illegal },{0, illegal },{2, jmp_6 },{1, sel_rb0 },{2, jz },{1, mov_a_psw }, + {1, dec_r0 },{1, dec_r1 },{1, dec_r2 },{1, dec_r3 },{1, dec_r4 },{1, dec_r5 },{1, dec_r6 },{1, dec_r7 }, + {1, xrl_a_xr0 },{1, xrl_a_xr1 },{2, jb_6 },{2, xrl_a_n },{2, call_6 },{1, sel_rb1 },{0, illegal },{1, mov_psw_a }, + {1, xrl_a_r0 },{1, xrl_a_r1 },{1, xrl_a_r2 },{1, xrl_a_r3 },{1, xrl_a_r4 },{1, xrl_a_r5 },{1, xrl_a_r6 },{1, xrl_a_r7 }, + {0, illegal },{0, illegal },{0, illegal },{2, movp3_a_xa},{2, jmp_7 },{1, sel_mb0 },{2, jnc },{1, rl_a }, + {2, djnz_r0 },{2, djnz_r1 },{2, djnz_r2 },{2, djnz_r3 },{2, djnz_r4 },{2, djnz_r5 },{2, djnz_r6 },{2, djnz_r7 }, + {1, mov_a_xr0 },{1, mov_a_xr1 },{2, jb_7 },{0, illegal },{2, call_7 },{1, sel_mb1 },{2, jc },{1, rlc_a }, + {1, mov_a_r0 },{1, mov_a_r1 },{1, mov_a_r2 },{1, mov_a_r3 },{1, mov_a_r4 },{1, mov_a_r5 },{1, mov_a_r6 },{1, mov_a_r7 } +}; + + +static int Ext_IRQ(void) +{ + int extra_cycles = 0; + + if (R.xirq_en) { + if (R.irq_executing == I8039_NO_INT) { +// logerror("I8039: EXT INTERRUPT being serviced\n"); + R.irq_executing = I8039_EXTERNAL_INT; + push(R.PC.b.l); + push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0)); + R.PC.w.l = 0x03; + + extra_cycles = 2; /* 2 clock cycles used */ + + if (R.timerON) /* NS990113 */ + R.masterClock += extra_cycles; + if (R.irq_callback) (*R.irq_callback)(0); + } + } + + return extra_cycles; +} + +static int Timer_IRQ(void) +{ + int extra_cycles = 0; + + if (R.tirq_en) { + if (R.irq_executing == I8039_NO_INT) { +// logerror("I8039: TIMER/COUNTER INTERRUPT\n"); + R.irq_executing = I8039_TIMCNT_INT; + R.pending_irq &= ~I8039_TIMCNT_INT; + push(R.PC.b.l); + push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0)); + R.PC.w.l = 0x07; + change_pc(0x07); + + extra_cycles = 2; /* 2 clock cycles used */ + + if (R.timerON) /* NS990113 */ + R.masterClock += extra_cycles; + } + else { + if (R.irq_executing == I8039_EXTERNAL_INT) { + R.pending_irq |= I8039_TIMCNT_INT; + } + } + } + + R.t_flag = 1; + + return extra_cycles; +} + +void I8039Init(int (*irqcallback)(int)) +{ + R.irq_callback = irqcallback; + + R.cpu_feature = 0; + R.ram_mask = 0x7F; + R.int_rom_size = 0x800; + /* not changed on reset*/ + memset(R.RAM, 0x00, 128); + R.timer = 0; + + I8039IORead = I8039DummyReadIo; + I8039IOWrite = I8039DummyWriteIo; + I8039ProgramRead = I8039DummyReadProg; + I8039ProgramWrite = I8039DummyWriteProg; + I8039CPUReadOp = I8039DummyReadOp; + I8039CPUReadOpArg = I8039DummyReadOpArg; +} + +void N7751Init(int (*irqcallback)(int)) +{ + I8039Init(irqcallback); +} + +void I8039SetIOReadHandler(i8039ReadIoHandler handler) +{ + I8039IORead = handler; +} + +void I8039SetIOWriteHandler(i8039WriteIoHandler handler) +{ + I8039IOWrite = handler; +} + +void I8039SetProgramReadHandler(i8039ReadProgHandler handler) +{ + I8039ProgramRead = handler; +} + +void I8039SetProgramWriteHandler(i8039WriteProgHandler handler) +{ + I8039ProgramWrite = handler; +} + +void I8039SetCPUOpReadHandler(i8039ReadOpHandler handler) +{ + I8039CPUReadOp = handler; +} + +void I8039SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler) +{ + I8039CPUReadOpArg = handler; +} + +void N7751SetIOReadHandler(i8039ReadIoHandler handler) +{ + I8039IORead = handler; +} + +void N7751SetIOWriteHandler(i8039WriteIoHandler handler) +{ + I8039IOWrite = handler; +} + +void N7751SetProgramReadHandler(i8039ReadProgHandler handler) +{ + I8039ProgramRead = handler; +} + +void N7751SetProgramWriteHandler(i8039WriteProgHandler handler) +{ + I8039ProgramWrite = handler; +} + +void N7751SetCPUOpReadHandler(i8039ReadOpHandler handler) +{ + I8039CPUReadOp = handler; +} + +void N7751SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler) +{ + I8039CPUReadOpArg = handler; +} + +void I8039Exit() +{ + i8039_ICount = 0; +} + +void N7751Exit() +{ + I8039Exit(); +} + +int I8039Run(int cycles) +{ + unsigned opcode, T1, timerInt; + int count; + + i8039_ICount = (cycles - R.irq_extra_cycles); + R.irq_extra_cycles = 0; + + do + { + R.PREVPC = R.PC; + +// CALL_DEBUGGER(R.PC.w.l); + + opcode=M_RDOP(R.PC.w.l); + +/* logerror("I8039: PC = %04x, opcode = %02x\n", R.PC.w.l, opcode); */ + + R.PC.w.l++; + R.inst_cycles = opcode_main[opcode].cycles; + (*(opcode_main[opcode].function))(); + i8039_ICount -= R.inst_cycles; /// + + timerInt = 0; + if (R.countON) /* NS990113 */ + { + for ( ; R.inst_cycles > 0; R.inst_cycles-- ) + { + T1 = test_r(1); + if (POSITIVE_EDGE_T1) + { + R.timer++; + if (R.timer == 0) + timerInt = 1; + } + R.Old_T1 = T1; + } + } + + if (R.timerON) { + R.masterClock += opcode_main[opcode].cycles; + if (R.masterClock >= 32) { /* NS990113 */ + R.masterClock -= 32; + R.timer++; + if (R.timer == 0) + timerInt = 1; + } + } + + if (timerInt) + { + count = Timer_IRQ(); /* Handle Timer IRQ */ + i8039_ICount -= count; + } + + } while (i8039_ICount>0); + + i8039_ICount -= R.irq_extra_cycles; + R.irq_extra_cycles = 0; + + return cycles - i8039_ICount; +} + +int N7751Run(int cycles) +{ + return I8039Run(cycles); +} + +void I8039Reset (void) +{ + R.PC.w.l = 0; + R.SP = 0; + R.A = 0; + R.PSW = 0x08; /* Start with No Carry, Bit 4 is always SET */ + //R.PSW = C_FLAG | 0x08; + R.P1 = 0xff; + R.P2 = 0xff; + R.bus = 0; + R.irq_executing = I8039_NO_INT; + R.pending_irq = I8039_NO_INT; + + R.A11 = 0; + R.tirq_en = R.xirq_en = 0; + R.timerON = R.countON = 0; + + if (R.cpu_feature & FEATURE_M58715) + { + //R.timerON = 1; /* Mario Bros. doesn't work without this */ + //R.PSW |= C_FLAG; //MB will play startup sound, but wrong # */ + } + R.irq_extra_cycles = 0; + R.masterClock = 0; +} + +void N7751Reset() +{ + I8039Reset(); +} + +void I8039SetIrqState(int state) +{ + if (state != 0) { + R.irq_state = I8039_EXTERNAL_INT; + R.irq_extra_cycles += Ext_IRQ(); /* Handle External IRQ */ + } + else { + R.irq_state = I8039_NO_INT; + } +} + +void N7751SetIrqState(int state) +{ + I8039SetIrqState(state); +} + +int I8039Scan(int nAction, int *pnMin) +{ + struct BurnArea ba; + char szName[16]; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + if (pnMin != NULL) { + *pnMin = 0x029678; + } + + sprintf(szName, "I8039"); + ba.Data = &R; + ba.nLen = sizeof(R); + ba.nAddress = 0; + ba.szName = szName; + BurnAcb(&ba); + + SCAN_VAR(i8039_ICount); + + return 0; +} + +int N7751Scan(int nAction, int *pnMin) +{ + return I8039Scan(nAction, pnMin); +} + +#if 0 + +/**************************************************************************** + * Initialize emulation + ****************************************************************************/ + + +#if (HAS_I8035||HAS_I8048||HAS_MB8884) +static void i8035_init (int index, int clock, const void *config, int (*irqcallback)(int)) +{ + i8039_init(index, clock, config, irqcallback); + R.ram_mask = 0x3F; + R.int_rom_size = 0x400; +} +#endif + +#if (HAS_I8749) +static void i8749_init (int index, int clock, const void *config, int (*irqcallback)(int)) +{ + i8039_init(index, clock, config, irqcallback); + + R.ram_mask = 0x7f; + R.int_rom_size = 0x800; +} +#endif + +#if (HAS_M58715) +static void m58715_init (int index, int clock, const void *config, int (*irqcallback)(int)) +{ + i8039_init(index, clock, config, irqcallback); + R.cpu_feature = FEATURE_M58715; +} +#endif /* HAS_M58715 */ + +/**************************************************************************** + * Reset registers to their initial values + ****************************************************************************/ + +/**************************************************************************** + * Shut down CPU emulation + ****************************************************************************/ +static void i8039_exit (void) +{ + /* nothing to do ? */ +} + +/**************************************************************************** + * Issue an interrupt if necessary + ****************************************************************************/ + + +/**************************************************************************** + * Execute cycles CPU cycles. Return number of cycles really executed + ****************************************************************************/ +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +static void i8039_get_context (void *dst) +{ + if( dst ) + *(I8039_Regs*)dst = R; +} + + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +static void i8039_set_context (void *src) +{ + if( src ) + { + R = *(I8039_Regs*)src; + regPTR = ((M_By) ? 24 : 0); + R.SP = (R.PSW << 1) & 0x0f; + change_pc(R.PC.w.l); + } + /* Handle forced Interrupts throught the Debugger */ + if (R.irq_state != I8039_NO_INT) { + R.irq_extra_cycles += Ext_IRQ(); /* Handle External IRQ */ + } + if (R.timer == 0) { + R.irq_extra_cycles += Timer_IRQ(); /* Handle Timer IRQ */ + } +} + + +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ + + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void i8039_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + I8039_PC: R.PC.w.l = info->i; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + I8039_SP: R.SP = info->i; break; + case CPUINFO_INT_REGISTER + I8039_PSW: R.PSW = info->i; break; + case CPUINFO_INT_REGISTER + I8039_A: R.A = info->i; break; + case CPUINFO_INT_REGISTER + I8039_TC: R.timer = info->i; break; + case CPUINFO_INT_REGISTER + I8039_P1: R.P1 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_P2: R.P2 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R0: R0 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R1: R1 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R2: R2 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R3: R3 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R4: R4 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R5: R5 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R6: R6 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_R7: R7 = info->i; break; + case CPUINFO_INT_REGISTER + I8039_EA: R.EA = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void i8039_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(R); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 3*5; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 12; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: info->i = (R.irq_state == I8039_EXTERNAL_INT) ? ASSERT_LINE : CLEAR_LINE; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = R.PREVPC.w.l; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + I8039_PC: info->i = R.PC.w.l; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + I8039_SP: info->i = R.SP; break; + case CPUINFO_INT_REGISTER + I8039_PSW: info->i = R.PSW; break; + case CPUINFO_INT_REGISTER + I8039_A: info->i = R.A; break; + case CPUINFO_INT_REGISTER + I8039_TC: info->i = R.timer; break; + case CPUINFO_INT_REGISTER + I8039_P1: info->i = R.P1; break; + case CPUINFO_INT_REGISTER + I8039_P2: info->i = R.P2; break; + case CPUINFO_INT_REGISTER + I8039_R0: info->i = R0; break; + case CPUINFO_INT_REGISTER + I8039_R1: info->i = R1; break; + case CPUINFO_INT_REGISTER + I8039_R2: info->i = R2; break; + case CPUINFO_INT_REGISTER + I8039_R3: info->i = R3; break; + case CPUINFO_INT_REGISTER + I8039_R4: info->i = R4; break; + case CPUINFO_INT_REGISTER + I8039_R5: info->i = R5; break; + case CPUINFO_INT_REGISTER + I8039_R6: info->i = R6; break; + case CPUINFO_INT_REGISTER + I8039_R7: info->i = R7; break; + case CPUINFO_INT_REGISTER + I8039_EA: info->i = R.EA; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = i8039_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8039_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8039_set_context; break; + case CPUINFO_PTR_INIT: info->init = i8039_init; break; + case CPUINFO_PTR_RESET: info->reset = i8039_reset; break; + case CPUINFO_PTR_EXIT: info->exit = i8039_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = i8039_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; +#ifdef ENABLE_DEBUGGER + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = i8039_dasm; break; +#endif /* ENABLE_DEBUGGER */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i8039_ICount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "I8039"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel 8039"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.2"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Mirko Buffoni\nBased on the original work Copyright Dan Boris"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c %c%c%c%c%c%c%c%c", + R.A11 ? 'M':'.', + R.PSW & 0x80 ? 'C':'.', + R.PSW & 0x40 ? 'A':'.', + R.PSW & 0x20 ? 'F':'.', + R.PSW & 0x10 ? 'B':'.', + R.PSW & 0x08 ? '?':'.', + R.PSW & 0x04 ? '4':'.', + R.PSW & 0x02 ? '2':'.', + R.PSW & 0x01 ? '1':'.'); + break; + + case CPUINFO_STR_REGISTER + I8039_PC: sprintf(info->s, "PC:%04X", R.PC.w.l); break; + case CPUINFO_STR_REGISTER + I8039_SP: sprintf(info->s, "SP:%02X", R.SP); break; + case CPUINFO_STR_REGISTER + I8039_PSW: sprintf(info->s, "PSW:%02X", R.PSW); break; + case CPUINFO_STR_REGISTER + I8039_A: sprintf(info->s, "A:%02X", R.A); break; + case CPUINFO_STR_REGISTER + I8039_TC: sprintf(info->s, "TC:%02X", R.timer); break; + case CPUINFO_STR_REGISTER + I8039_P1: sprintf(info->s, "P1:%02X", R.P1); break; + case CPUINFO_STR_REGISTER + I8039_P2: sprintf(info->s, "P2:%02X", R.P2); break; + case CPUINFO_STR_REGISTER + I8039_R0: sprintf(info->s, "R0:%02X", R.RAM[R.regPtr+0]); break; + case CPUINFO_STR_REGISTER + I8039_R1: sprintf(info->s, "R1:%02X", R.RAM[R.regPtr+1]); break; + case CPUINFO_STR_REGISTER + I8039_R2: sprintf(info->s, "R2:%02X", R.RAM[R.regPtr+2]); break; + case CPUINFO_STR_REGISTER + I8039_R3: sprintf(info->s, "R3:%02X", R.RAM[R.regPtr+3]); break; + case CPUINFO_STR_REGISTER + I8039_R4: sprintf(info->s, "R4:%02X", R.RAM[R.regPtr+4]); break; + case CPUINFO_STR_REGISTER + I8039_R5: sprintf(info->s, "R5:%02X", R.RAM[R.regPtr+5]); break; + case CPUINFO_STR_REGISTER + I8039_R6: sprintf(info->s, "R6:%02X", R.RAM[R.regPtr+6]); break; + case CPUINFO_STR_REGISTER + I8039_R7: sprintf(info->s, "R7:%02X", R.RAM[R.regPtr+7]); break; + case CPUINFO_STR_REGISTER + I8039_EA: sprintf(info->s, "EA:%02X", R.EA); break; + } +} + + + +#if (HAS_I8035) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void i8035_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "I8035"); break; + case CPUINFO_PTR_INIT: info->init = i8035_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif + + +#if (HAS_I8048) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void i8048_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "I8048"); break; + case CPUINFO_PTR_INIT: info->init = i8035_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif + +#if (HAS_I8749) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void i8749_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "I8749"); break; + case CPUINFO_PTR_INIT: info->init = i8749_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif + +#if (HAS_N7751) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void n7751_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "N7751"); break; + case CPUINFO_PTR_INIT: info->init = i8039_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif + +#if (HAS_MB8884) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void mb8884_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "MB8884"); break; + case CPUINFO_PTR_INIT: info->init = i8035_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif + +#if (HAS_M58715) +/************************************************************************** + * CPU-specific get_info/set_info + **************************************************************************/ +void m58715_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M58715"); break; + case CPUINFO_PTR_INIT: info->init = m58715_init; break; + + default: i8039_get_info(state, info); break; + } +} +#endif +#endif diff --git a/src/cpu/i8039/i8039.h b/src/cpu/i8039/i8039.h new file mode 100644 index 00000000..b5bdba5b --- /dev/null +++ b/src/cpu/i8039/i8039.h @@ -0,0 +1,295 @@ +/************************************************************************** + * Intel 8039 Portable Emulator * + * * + * Copyright Mirko Buffoni * + * Based on the original work Copyright Dan Boris, an 8048 emulator * + * You are not allowed to distribute this software commercially * + * Please, notify me, if you make any changes to this file * + **************************************************************************/ + +#include "driver.h" + +#define HAS_N7751 1 +#define HAS_I8035 0 +#define HAS_I8048 0 +#define HAS_I8749 0 +#define HAS_MB8884 0 +#define HAS_M58715 0 + +/************************************************************************** + Internal Clock divisor + + External Clock is divided internally by 3 to produce the machine state + generator. This is then divided by 5 for the instruction cycle times. + (Each instruction cycle passes through 5 machine states). +*/ + + +enum { I8039_PC=1, I8039_SP, I8039_PSW, I8039_A, I8039_TC, + I8039_P1, I8039_P2, I8039_R0, I8039_R1, I8039_R2, + I8039_R3, I8039_R4, I8039_R5, I8039_R6, I8039_R7, + I8039_EA +}; + +typedef unsigned char (__fastcall *i8039ReadIoHandler)(unsigned int a); +typedef void (__fastcall *i8039WriteIoHandler)(unsigned int a, unsigned char v); +typedef unsigned char (__fastcall *i8039ReadProgHandler)(unsigned int a); +typedef void (__fastcall *i8039WriteProgHandler)(unsigned int a, unsigned char v); +typedef unsigned char (__fastcall *i8039ReadOpHandler)(unsigned int a); +typedef unsigned char (__fastcall *i8039ReadOpArgHandler)(unsigned int a); +extern i8039ReadIoHandler I8039IORead; +extern i8039WriteIoHandler I8039IOWrite; +extern i8039ReadProgHandler I8039ProgramRead; +extern i8039WriteProgHandler I8039ProgramWrite; +extern i8039ReadOpHandler I8039CPUReadOp; +extern i8039ReadOpArgHandler I8039CPUReadOpArg; + +extern int I8039Run(int cycles); +extern void I8039Init(int (*irqcallback)(int)); +extern void I8039SetIOReadHandler(i8039ReadIoHandler handler); +extern void I8039SetIOWriteHandler(i8039WriteIoHandler handler); +extern void I8039SetProgramReadHandler(i8039ReadProgHandler handler); +extern void I8039SetProgramWriteHandler(i8039WriteProgHandler handler); +extern void I8039SetCPUOpReadHandler(i8039ReadOpHandler handler); +extern void I8039SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler); +extern void I8039Exit(); +extern void I8039Reset (void); +extern void I8039SetIrqState(int state); +extern int I8039Scan(int nAction,int *pnMin); + +extern int N7751Run(int cycles); +extern void N7751Init(int (*irqcallback)(int)); +extern void N7751SetIOReadHandler(i8039ReadIoHandler handler); +extern void N7751SetIOWriteHandler(i8039WriteIoHandler handler); +extern void N7751SetProgramReadHandler(i8039ReadProgHandler handler); +extern void N7751SetProgramWriteHandler(i8039WriteProgHandler handler); +extern void N7751SetCPUOpReadHandler(i8039ReadOpHandler handler); +extern void N7751SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler); +extern void N7751Exit(); +extern void N7751Reset (void); +extern void N7751SetIrqState(int state); +extern int N7751Scan(int nAction,int *pnMin); + + + +/* + * Input a UINT8 from given I/O port + */ +#define I8039_In(Port) ((UINT8)I8039IORead(Port)) + + +/* + * Output a UINT8 to given I/O port + */ +#define I8039_Out(Port,Value) (I8039IOWrite(Port,Value)) + + +/* + * Read a UINT8 from given memory location + */ +#define I8039_RDMEM(A) ((unsigned)I8039ProgramRead(A)) + + +/* + * Write a UINT8 to given memory location + */ +#define I8039_WRMEM(A,V) (I8039ProgramWrite(A,V)) + + +/* + * I8039_RDOP() is identical to I8039_RDMEM() except it is used for reading + * opcodes. In case of system with memory mapped I/O, this function can be + * used to greatly speed up emulation + */ +#define I8039_RDOP(A) ((unsigned)I8039CPUReadOp(A)) + + +/* + * I8039_RDOP_ARG() is identical to I8039_RDOP() except it is used for reading + * opcode arguments. This difference can be used to support systems that + * use different encoding mechanisms for opcodes and opcode arguments + */ +#define I8039_RDOP_ARG(A) ((unsigned)I8039CPUReadOpArg(A)) + + + + + +#if 0 +extern void i8039_get_info(UINT32 state, cpuinfo *info); +#endif + +/* This handling of special I/O ports should be better for actual MAME + * architecture. (i.e., define access to ports { I8039_p1, I8039_p1, dkong_out_w }) + */ + +#define I8039_p0 0x100 /* Not used */ +#define I8039_p1 0x101 +#define I8039_p2 0x102 +#define I8039_p4 0x104 +#define I8039_p5 0x105 +#define I8039_p6 0x106 +#define I8039_p7 0x107 +#define I8039_t0 0x110 +#define I8039_t1 0x111 +/* EA is activelow input on real hardware. It is treated + * as active high here to remain compatible with existing drivers! */ +#define I8039_ea 0x112 +#define I8039_bus 0x120 + +/************************************************************************** + * I8035 section + **************************************************************************/ +#if (HAS_I8035) +#define I8035_PC I8039_PC +#define I8035_SP I8039_SP +#define I8035_PSW I8039_PSW +#define I8035_A I8039_A +#define I8035_TC I8039_TC +#define I8035_P1 I8039_P1 +#define I8035_P2 I8039_P2 +#define I8035_R0 I8039_R0 +#define I8035_R1 I8039_R1 +#define I8035_R2 I8039_R2 +#define I8035_R3 I8039_R3 +#define I8035_R4 I8039_R4 +#define I8035_R5 I8039_R5 +#define I8035_R6 I8039_R6 +#define I8035_R7 I8039_R7 + +#define i8035_ICount i8039_ICount + +extern void i8035_get_info(UINT32 state, cpuinfo *info); +#endif + +/************************************************************************** + * I8048 section + **************************************************************************/ +#if (HAS_I8048) +#define I8048_PC I8039_PC +#define I8048_SP I8039_SP +#define I8048_PSW I8039_PSW +#define I8048_A I8039_A +#define I8048_TC I8039_TC +#define I8048_P1 I8039_P1 +#define I8048_P2 I8039_P2 +#define I8048_R0 I8039_R0 +#define I8048_R1 I8039_R1 +#define I8048_R2 I8039_R2 +#define I8048_R3 I8039_R3 +#define I8048_R4 I8039_R4 +#define I8048_R5 I8039_R5 +#define I8048_R6 I8039_R6 +#define I8048_R7 I8039_R7 + +#define i8048_ICount i8039_ICount + +extern void i8048_get_info(UINT32 state, cpuinfo *info); +#endif + +/************************************************************************** + * I8749 section + **************************************************************************/ +#if (HAS_I8749) +#define I8749_PC I8039_PC +#define I8749_SP I8039_SP +#define I8749_PSW I8039_PSW +#define I8749_A I8039_A +#define I8749_TC I8039_TC +#define I8749_P1 I8039_P1 +#define I8749_P2 I8039_P2 +#define I8749_R0 I8039_R0 +#define I8749_R1 I8039_R1 +#define I8749_R2 I8039_R2 +#define I8749_R3 I8039_R3 +#define I8749_R4 I8039_R4 +#define I8749_R5 I8039_R5 +#define I8749_R6 I8039_R6 +#define I8749_R7 I8039_R7 + +#define i8749_ICount i8039_ICount + +extern void i8749_get_info(UINT32 state, cpuinfo *info); +#endif + +/************************************************************************** + * N7751 section + **************************************************************************/ +#if (HAS_N7751) +#define N7751_PC I8039_PC +#define N7751_SP I8039_SP +#define N7751_PSW I8039_PSW +#define N7751_A I8039_A +#define N7751_TC I8039_TC +#define N7751_P1 I8039_P1 +#define N7751_P2 I8039_P2 +#define N7751_R0 I8039_R0 +#define N7751_R1 I8039_R1 +#define N7751_R2 I8039_R2 +#define N7751_R3 I8039_R3 +#define N7751_R4 I8039_R4 +#define N7751_R5 I8039_R5 +#define N7751_R6 I8039_R6 +#define N7751_R7 I8039_R7 + +#define n7751_ICount i8039_ICount + +#if 0 +extern void n7751_get_info(UINT32 state, cpuinfo *info); +#endif +#endif + +/************************************************************************** + * MB8884 section + **************************************************************************/ +#if (HAS_MB8884) +#define MB8884_PC I8039_PC +#define MB8884_SP I8039_SP +#define MB8884_PSW I8039_PSW +#define MB8884_A I8039_A +#define MB8884_TC I8039_TC +#define MB8884_P1 I8039_P1 +#define MB8884_P2 I8039_P2 +#define MB8884_R0 I8039_R0 +#define MB8884_R1 I8039_R1 +#define MB8884_R2 I8039_R2 +#define MB8884_R3 I8039_R3 +#define MB8884_R4 I8039_R4 +#define MB8884_R5 I8039_R5 +#define MB8884_R6 I8039_R6 +#define MB8884_R7 I8039_R7 + +#define mb8884_ICount i8039_ICount + +extern void mb8884_get_info(UINT32 state, cpuinfo *info); +#endif + +/************************************************************************** + * M58715 section + **************************************************************************/ +#if (HAS_M58715) +#define M58715_PC I8039_PC +#define M58715_SP I8039_SP +#define M58715_PSW I8039_PSW +#define M58715_A I8039_A +#define M58715_TC I8039_TC +#define M58715_P1 I8039_P1 +#define M58715_P2 I8039_P2 +#define M58715_R0 I8039_R0 +#define M58715_R1 I8039_R1 +#define M58715_R2 I8039_R2 +#define M58715_R3 I8039_R3 +#define M58715_R4 I8039_R4 +#define M58715_R5 I8039_R5 +#define M58715_R6 I8039_R6 +#define M58715_R7 I8039_R7 + +#define m58715_ICount i8039_ICount + +extern void m58715_get_info(UINT32 state, cpuinfo *info); +#endif + +#ifdef ENABLE_DEBUGGER +offs_t i8039_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +#endif + diff --git a/src/cpu/konami/konami.cpp b/src/cpu/konami/konami.cpp new file mode 100644 index 00000000..9fb1035a --- /dev/null +++ b/src/cpu/konami/konami.cpp @@ -0,0 +1,560 @@ +/*** konami: Portable Konami cpu emulator ****************************************** + + Copyright Nicola Salmoria and the MAME Team + + Based on M6809 cpu core copyright John Butler + + References: + + 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands. + + m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from + the 6809 Simulator V09) + + 6809 Microcomputer Programming & Interfacing with Experiments" + by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. + + System dependencies: UINT16 must be 16 bit unsigned int + UINT8 must be 8 bit unsigned int + UINT32 must be more than 16 bits + arrays up to 65536 bytes must be supported + machine must be twos complement + + History: +991022 HJB: + Tried to improve speed: Using bit7 of cycles1 as flag for multi + byte opcodes is gone, those opcodes now instead go through opcode2(). + KONAMI_INLINEd fetch_effective_address() into that function as well. + Got rid of the slow/fast flags for stack (S and U) memory accesses. + Minor changes to use 32 bit values as arguments to memory functions + and added defines for that purpose (e.g. X = 16bit XD = 32bit). + +990720 EHC: + Created this file + +*****************************************************************************/ + +#include "burnint.h" +#include "konami.h" +#include "konami_intf.h" +#define VERBOSE 0 + +#define change_pc(x) PC=x +#define logerror printf + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +#define KONAMI_INLINE inline + +/* Konami Registers */ +typedef struct +{ + PAIR pc; /* Program counter */ + PAIR ppc; /* Previous program counter */ + PAIR d; /* Accumulator a and b */ + PAIR dp; /* Direct Page register (page in MSB) */ + PAIR u, s; /* Stack pointers */ + PAIR x, y; /* Index registers */ + UINT8 cc; + UINT8 ireg; /* first opcode */ + UINT8 irq_state[2]; + int extra_cycles; /* cycles used up by interrupts */ + UINT8 int_state; /* SYNC and CWAI flags */ + UINT8 nmi_state; + int nTotalCycles; + int (*irq_callback)(int irqline); + void (*setlines_callback)( int lines ); /* callback called when A16-A23 are set */ +} konami_Regs; + +/* flag bits in the cc register */ +#define CC_C 0x01 /* Carry */ +#define CC_V 0x02 /* Overflow */ +#define CC_Z 0x04 /* Zero */ +#define CC_N 0x08 /* Negative */ +#define CC_II 0x10 /* Inhibit IRQ */ +#define CC_H 0x20 /* Half (auxiliary) carry */ +#define CC_IF 0x40 /* Inhibit FIRQ */ +#define CC_E 0x80 /* entire state pushed */ + +/* Konami registers */ +static konami_Regs konami; + +#define pPPC konami.ppc +#define pPC konami.pc +#define pU konami.u +#define pS konami.s +#define pX konami.x +#define pY konami.y +#define pD konami.d + +#define PPC konami.ppc.w.l +#define PC konami.pc.w.l +#define PCD konami.pc.d +#define U konami.u.w.l +#define UD konami.u.d +#define S konami.s.w.l +#define SD konami.s.d +#define X konami.x.w.l +#define XD konami.x.d +#define Y konami.y.w.l +#define YD konami.y.d +#define D konami.d.w.l +#define A konami.d.b.h +#define B konami.d.b.l +#define DP konami.dp.b.h +#define DPD konami.dp.d +#define CC konami.cc + +static PAIR ea; /* effective address */ +#define EA ea.w.l +#define EAD ea.d + +#define KONAMI_CWAI 8 /* set when CWAI is waiting for an interrupt */ +#define KONAMI_SYNC 16 /* set when SYNC is waiting for an interrupt */ +#define KONAMI_LDS 32 /* set when LDS occured at least once */ + +static int nCyclesToDo = 0; + +#define CHECK_IRQ_LINES \ + if( konami.irq_state[KONAMI_IRQ_LINE] != KONAMI_CLEAR_LINE || \ + konami.irq_state[KONAMI_FIRQ_LINE] != KONAMI_CLEAR_LINE ) \ + konami.int_state &= ~KONAMI_SYNC; /* clear SYNC flag */ \ + if( konami.irq_state[KONAMI_FIRQ_LINE]!=KONAMI_CLEAR_LINE && !(CC & CC_IF) ) \ + { \ + /* fast IRQ */ \ + /* state already saved by CWAI? */ \ + if( konami.int_state & KONAMI_CWAI ) \ + { \ + konami.int_state &= ~KONAMI_CWAI; /* clear CWAI */ \ + konami.extra_cycles += 7; /* subtract +7 cycles */ \ + } \ + else \ + { \ + CC &= ~CC_E; /* save 'short' state */ \ + PUSHWORD(pPC); \ + PUSHBYTE(CC); \ + konami.extra_cycles += 10; /* subtract +10 cycles */ \ + } \ + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ \ + PCD = RM16(0xfff6); \ + change_pc(PC); /* TS 971002 */ \ + (void)(*konami.irq_callback)(KONAMI_FIRQ_LINE); \ + } \ + else \ + if( konami.irq_state[KONAMI_IRQ_LINE]!=KONAMI_CLEAR_LINE && !(CC & CC_II) )\ + { \ + /* standard IRQ */ \ + /* state already saved by CWAI? */ \ + if( konami.int_state & KONAMI_CWAI ) \ + { \ + konami.int_state &= ~KONAMI_CWAI; /* clear CWAI flag */ \ + konami.extra_cycles += 7; /* subtract +7 cycles */ \ + } \ + else \ + { \ + CC |= CC_E; /* save entire state */ \ + PUSHWORD(pPC); \ + PUSHWORD(pU); \ + PUSHWORD(pY); \ + PUSHWORD(pX); \ + PUSHBYTE(DP); \ + PUSHBYTE(B); \ + PUSHBYTE(A); \ + PUSHBYTE(CC); \ + konami.extra_cycles += 19; /* subtract +19 cycles */ \ + } \ + CC |= CC_II; /* inhibit IRQ */ \ + PCD = RM16(0xfff8); \ + change_pc(PC); /* TS 971002 */ \ + (void)(*konami.irq_callback)(KONAMI_IRQ_LINE); \ + } + +/* public globals */ +static int konami_ICount; +//int konami_Flags; /* flags for speed optimization (obsolete!!) */ + +/* these are re-defined in konami.h TO RAM, ROM or functions in memory.c */ +#define RM(Addr) KONAMI_RDMEM(Addr) +#define WM(Addr,Value) KONAMI_WRMEM(Addr,Value) +#define ROP(Addr) KONAMI_RDOP(Addr) +#define ROP_ARG(Addr) KONAMI_RDOP_ARG(Addr) + +#define SIGNED(a) (UINT16)(INT16)(INT8)(a) + +/* macros to access memory */ +#define IMMBYTE(b) { b = ROP_ARG(PCD); PC++; } +#define IMMWORD(w) { w.d = (ROP_ARG(PCD)<<8) | ROP_ARG(PCD+1); PC += 2; } + +#define PUSHBYTE(b) --S; WM(SD,b) +#define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h) +#define PULLBYTE(b) b=KONAMI_RDMEM(SD); S++ +#define PULLWORD(w) w=KONAMI_RDMEM(SD)<<8; S++; w|=KONAMI_RDMEM(SD); S++ + +#define PSHUBYTE(b) --U; WM(UD,b); +#define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h) +#define PULUBYTE(b) b=KONAMI_RDMEM(UD); U++ +#define PULUWORD(w) w=KONAMI_RDMEM(UD)<<8; U++; w|=KONAMI_RDMEM(UD); U++ + +#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C) +#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V) +#define CLR_NZ CC&=~(CC_N|CC_Z) +#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C) +#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C) +#define CLR_Z CC&=~(CC_Z) +#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C) +#define CLR_ZC CC&=~(CC_Z|CC_C) + +/* macros for CC -- CC bits affected should be reset before calling */ +#define SET_Z(a) if(!a)SEZ +#define SET_Z8(a) SET_Z((UINT8)a) +#define SET_Z16(a) SET_Z((UINT16)a) +#define SET_N8(a) CC|=((a&0x80)>>4) +#define SET_N16(a) CC|=((a&0x8000)>>12) +#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1) +#define SET_C8(a) CC|=((a&0x100)>>8) +#define SET_C16(a) CC|=((a&0x10000)>>16) +#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6) +#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14) + +static const UINT8 flags8i[256]= /* increment */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; +static const UINT8 flags8d[256]= /* decrement */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; +#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} +#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} + +/* combos */ +#define SET_NZ8(a) {SET_N8(a);SET_Z(a);} +#define SET_NZ16(a) {SET_N16(a);SET_Z(a);} +#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} +#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);} + +/* macros for addressing modes (postbytes have their own code) */ +#define DIRECT EAD = DPD; IMMBYTE(ea.b.l) +#define IMM8 EAD = PCD; PC++ +#define IMM16 EAD = PCD; PC+=2 +#define EXTENDED IMMWORD(ea) + +/* macros to set status flags */ +#if defined(SEC) +#undef SEC +#endif +#define SEC CC|=CC_C +#define CLC CC&=~CC_C +#define SEZ CC|=CC_Z +#define CLZ CC&=~CC_Z +#define SEN CC|=CC_N +#define CLN CC&=~CC_N +#define SEV CC|=CC_V +#define CLV CC&=~CC_V +#define SEH CC|=CC_H +#define CLH CC&=~CC_H + +/* macros for convenience */ +#define DIRBYTE(b) DIRECT; b=RM(EAD) +#define DIRWORD(w) DIRECT; w.d=RM16(EAD) +#define EXTBYTE(b) EXTENDED; b=RM(EAD) +#define EXTWORD(w) EXTENDED; w.d=RM16(EAD) + +/* macros for branch instructions */ +#define BRANCH(f) { \ + UINT8 t; \ + IMMBYTE(t); \ + if( f ) \ + { \ + PC += SIGNED(t); \ + change_pc(PC); /* TS 971002 */ \ + } \ +} + +#define LBRANCH(f) { \ + PAIR t; \ + IMMWORD(t); \ + if( f ) \ + { \ + konami_ICount -= 1; \ + PC += t.w.l; \ + change_pc(PC); /* TS 971002 */ \ + } \ +} + +#define NXORV ((CC&CC_N)^((CC&CC_V)<<2)) + +/* macros for setting/getting registers in TFR/EXG instructions */ +#define GETREG(val,reg) \ + switch(reg) { \ + case 0: val = A; break; \ + case 1: val = B; break; \ + case 2: val = X; break; \ + case 3: val = Y; break; \ + case 4: val = S; break; /* ? */ \ + case 5: val = U; break; \ + default: val = 0xff; logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \ +} + +#define SETREG(val,reg) \ + switch(reg) { \ + case 0: A = val; break; \ + case 1: B = val; break; \ + case 2: X = val; break; \ + case 3: Y = val; break; \ + case 4: S = val; break; /* ? */ \ + case 5: U = val; break; \ + default: logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \ +} + +/* opcode timings */ +static const UINT8 cycles1[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5, + /*1*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /*2*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + /*3*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 7, 6, + /*4*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4, + /*5*/ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 1, 1, 1, + /*6*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, + /*7*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, + /*8*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, + /*9*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, + /*A*/ 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 2, 1, + /*B*/ 3, 2, 2,11,22,11, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3, + /*C*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2, + /*D*/ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /*E*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /*F*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +KONAMI_INLINE UINT32 RM16( UINT32 Addr ) +{ + UINT32 result = RM(Addr) << 8; + return result | RM((Addr+1)&0xffff); +} + +KONAMI_INLINE void WM16( UINT32 Addr, PAIR *p ) +{ + WM( Addr, p->b.h ); + WM( (Addr+1)&0xffff, p->b.l ); +} + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +#if 0 +static void konami_get_context(void *dst) +{ + if( dst ) + *(konami_Regs*)dst = konami; +} +#endif + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +#if 0 +static void konami_set_context(void *src) +{ + if( src ) + konami = *(konami_Regs*)src; + change_pc(PC); /* TS 971002 */ + + CHECK_IRQ_LINES; +} +#endif + +/****************************************************************************/ +/* Reset registers to their initial values */ +/****************************************************************************/ +void konami_init(int (*irqcallback)(int)) +{ + konami.irq_callback = irqcallback; +} + +void konamiReset() +{ + konami.nTotalCycles = 0; + konami.int_state = 0; + konami.nmi_state = KONAMI_CLEAR_LINE; + konami.irq_state[0] = KONAMI_CLEAR_LINE; + konami.irq_state[1] = KONAMI_CLEAR_LINE; + + DPD = 0; /* Reset direct page register */ + + CC |= CC_II; /* IRQ disabled */ + CC |= CC_IF; /* FIRQ disabled */ + + PCD = RM16(0xfffe); + change_pc(PC); /* TS 971002 */ +} + +#if 0 +static void konami_exit(void) +{ +} +#endif + +/* Generate interrupts */ +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ +void konami_set_irq_line(int irqline, int state) +{ + if (irqline == KONAMI_INPUT_LINE_NMI) + { + if (konami.nmi_state == state) return; + konami.nmi_state = state; + // LOG(("KONAMI#%d set_nmi_line %d\n", cpu_getactivecpu(), state)); + if( state == KONAMI_CLEAR_LINE ) return; + + /* if the stack was not yet initialized */ + if( !(konami.int_state & KONAMI_LDS) ) return; + + konami.int_state &= ~KONAMI_SYNC; + /* state already saved by CWAI? */ + if( konami.int_state & KONAMI_CWAI ) + { + konami.int_state &= ~KONAMI_CWAI; + konami.extra_cycles += 7; /* subtract +7 cycles next time */ + } + else + { + CC |= CC_E; /* save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + konami.extra_cycles += 19; /* subtract +19 cycles next time */ + } + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD = RM16(0xfffc); + change_pc(PC); /* TS 971002 */ + } + else if (irqline < 2) + { + // LOG(("KONAMI#%d set_irq_line %d, %d\n", cpu_getactivecpu(), irqline, state)); + konami.irq_state[irqline] = state; + if (state == KONAMI_CLEAR_LINE) return; + CHECK_IRQ_LINES; + } +} + +/* includes the static function prototypes and the master opcode table */ +#include "konamtbl.c" + +/* includes the actual opcode implementations */ +#include "konamops.c" + +/* execute instructions on this CPU until icount expires */ +int konamiRun(int cycles) +{ + konami_ICount = cycles - konami.extra_cycles; + nCyclesToDo = konami_ICount; + konami.extra_cycles = 0; + + if( konami.int_state & (KONAMI_CWAI | KONAMI_SYNC) ) + { + konami_ICount = 0; + } + else + { + do + { + pPPC = pPC; + + konami.ireg = ROP(PCD); + PC++; + + (*konami_main[konami.ireg])(); + + konami_ICount -= cycles1[konami.ireg]; + + } while( konami_ICount > 0 ); + + konami_ICount -= konami.extra_cycles; + konami.extra_cycles = 0; + } + + konami.nTotalCycles += cycles - konami_ICount; + return cycles - konami_ICount; +} + +int konamiCpuScan(int nAction,int */*pnMin*/) +{ + struct BurnArea ba; + + int (*irq_callback)(int irqline); + void (*setlines_callback)( int lines ); + + irq_callback = konami.irq_callback; + setlines_callback = konami.setlines_callback; + + if (nAction & ACB_DRIVER_DATA) { + memset(&ba, 0, sizeof(ba)); + ba.Data = (unsigned char*)&konami; + ba.nLen = sizeof(konami_Regs); + ba.szName = "All Registers"; + BurnAcb(&ba); + + SCAN_VAR(ea.w.l); + SCAN_VAR(ea.d); + } + + konami.irq_callback = irq_callback; + konami.setlines_callback = setlines_callback; + + return 0; +} + +void konamiSetlinesCallback(void (*setlines_callback)(int lines)) +{ + konami.setlines_callback = setlines_callback; +} + +int konamiTotalCycles() +{ + return konami.nTotalCycles; +} + +void konamiNewFrame() +{ + konami.nTotalCycles = 0; +} + diff --git a/src/cpu/konami/konami.h b/src/cpu/konami/konami.h new file mode 100644 index 00000000..c0101136 --- /dev/null +++ b/src/cpu/konami/konami.h @@ -0,0 +1,48 @@ +/*** konami: Portable Konami cpu emulator ******************************************/ + + +#ifndef __KONAMI_H__ +#define __KONAMI_H__ + + +enum +{ + KONAMI_PC=1, KONAMI_S, KONAMI_CC ,KONAMI_A, KONAMI_B, KONAMI_U, KONAMI_X, KONAMI_Y, + KONAMI_DP +}; + +/* PUBLIC FUNCTIONS */ + +/****************************************************************************/ +/* Read a byte from given memory location */ +/****************************************************************************/ +#define KONAMI_RDMEM(Addr) konami_read(Addr) + +/****************************************************************************/ +/* Write a byte to given memory location */ +/****************************************************************************/ +#define KONAMI_WRMEM(Addr,Value) konami_write(Addr,Value) + +/****************************************************************************/ +/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ +/* opcodes. In case of system with memory mapped I/O, this function can be */ +/* used to greatly speed up emulation */ +/****************************************************************************/ +#define KONAMI_RDOP(Addr) konami_fetch(Addr) + +/****************************************************************************/ +/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */ +/* opcode arguments. This difference can be used to support systems that */ +/* use different encoding mechanisms for opcodes and opcode arguments */ +/****************************************************************************/ +#define KONAMI_RDOP_ARG(Addr) konami_fetch(Addr) + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + + +#endif /* __KONAMI_H__ */ diff --git a/src/cpu/konami/konamops.c b/src/cpu/konami/konamops.c new file mode 100644 index 00000000..5216f6fc --- /dev/null +++ b/src/cpu/konami/konamops.c @@ -0,0 +1,4361 @@ +/* + +HNZVC + +? = undefined +* = affected +- = unaffected +0 = cleared +1 = set +# = CCr directly affected by instruction +@ = special - carry set if bit 7 is set + +*/ + +#ifdef NEW +static void illegal( void ) +#else +KONAMI_INLINE void illegal( void ) +#endif +{ + logerror("KONAMI: illegal opcode at %04x\n",PC); +} + +/* $00 NEG direct ?**** */ +KONAMI_INLINE void neg_di( void ) +{ + UINT16 r,t; + DIRBYTE(t); + r = -t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $01 ILLEGAL */ + +/* $02 ILLEGAL */ + +/* $03 COM direct -**01 */ +KONAMI_INLINE void com_di( void ) +{ + UINT8 t; + DIRBYTE(t); + t = ~t; + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $04 LSR direct -0*-* */ +KONAMI_INLINE void lsr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $05 ILLEGAL */ + +/* $06 ROR direct -**-* */ +KONAMI_INLINE void ror_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r= (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $07 ASR direct ?**-* */ +KONAMI_INLINE void asr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t = (t & 0x80) | (t >> 1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $08 ASL direct ?**** */ +KONAMI_INLINE void asl_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $09 ROL direct -**** */ +KONAMI_INLINE void rol_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = (CC & CC_C) | (t << 1); + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $0A DEC direct -***- */ +KONAMI_INLINE void dec_di( void ) +{ + UINT8 t; + DIRBYTE(t); + --t; + CLR_NZV; + SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $0B ILLEGAL */ + +/* $OC INC direct -***- */ +KONAMI_INLINE void inc_di( void ) +{ + UINT8 t; + DIRBYTE(t); + ++t; + CLR_NZV; + SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $OD TST direct -**0- */ +KONAMI_INLINE void tst_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZV; + SET_NZ8(t); +} + +/* $0E JMP direct ----- */ +KONAMI_INLINE void jmp_di( void ) +{ + DIRECT; + PCD=EAD; + change_pc(PCD); +} + +/* $0F CLR direct -0100 */ +KONAMI_INLINE void clr_di( void ) +{ + DIRECT; + WM(EAD,0); + CLR_NZVC; + SEZ; +} + +/* $10 FLAG */ + +/* $11 FLAG */ + +/* $12 NOP inherent ----- */ +KONAMI_INLINE void nop( void ) +{ + ; +} + +/* $13 SYNC inherent ----- */ +KONAMI_INLINE void sync( void ) +{ + /* SYNC stops processing instructions until an interrupt request happens. */ + /* This doesn't require the corresponding interrupt to be enabled: if it */ + /* is disabled, execution continues with the next instruction. */ + konami.int_state |= KONAMI_SYNC; + CHECK_IRQ_LINES; + /* if KONAMI_SYNC has not been cleared by CHECK_IRQ_LINES, + * stop execution until the interrupt lines change. */ + if( (konami.int_state & KONAMI_SYNC) && konami_ICount > 0 ) + konami_ICount = 0; +} + +/* $14 ILLEGAL */ + +/* $15 ILLEGAL */ + +/* $16 LBRA relative ----- */ +KONAMI_INLINE void lbra( void ) +{ + IMMWORD(ea); + PC += EA; + change_pc(PCD); + + /* EHC 980508 speed up busy loop */ + if( EA == 0xfffd && konami_ICount > 0 ) + konami_ICount = 0; +} + +/* $17 LBSR relative ----- */ +KONAMI_INLINE void lbsr( void ) +{ + IMMWORD(ea); + PUSHWORD(pPC); + PC += EA; + change_pc(PCD); +} + +/* $18 ILLEGAL */ + +#if 1 +/* $19 DAA inherent (A) -**0* */ +KONAMI_INLINE void daa( void ) +{ + UINT8 msn, lsn; + UINT16 t, cf = 0; + msn = A & 0xf0; lsn = A & 0x0f; + if( lsn>0x09 || CC & CC_H) cf |= 0x06; + if( msn>0x80 && lsn>0x09 ) cf |= 0x60; + if( msn>0x90 || CC & CC_C) cf |= 0x60; + t = cf + A; + CLR_NZV; /* keep carry from previous operation */ + SET_NZ8((UINT8)t); SET_C8(t); + A = t; +} +#else +/* $19 DAA inherent (A) -**0* */ +KONAMI_INLINE void daa( void ) +{ + UINT16 t; + t = A; + if (CC & CC_H) t+=0x06; + if ((t&0x0f)>9) t+=0x06; /* ASG -- this code is broken! $66+$99=$FF -> DAA should = $65, we get $05! */ + if (CC & CC_C) t+=0x60; + if ((t&0xf0)>0x90) t+=0x60; + if (t&0x100) SEC; + A = t; +} +#endif + +/* $1A ORCC immediate ##### */ +KONAMI_INLINE void orcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC |= t; + CHECK_IRQ_LINES; +} + +/* $1B ILLEGAL */ + +/* $1C ANDCC immediate ##### */ +KONAMI_INLINE void andcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + CHECK_IRQ_LINES; +} + +/* $1D SEX inherent -**0- */ +KONAMI_INLINE void sex( void ) +{ + UINT16 t; + t = SIGNED(B); + D = t; +// CLR_NZV; NS 20020905: applying the same fix that was applied to 6809 and 6309 + CLR_NZ; + SET_NZ16(t); +} + +/* $1E EXG inherent ----- */ +KONAMI_INLINE void exg( void ) +{ + UINT16 t1 = 0, t2 = 0; + UINT8 tb; + + IMMBYTE(tb); + + GETREG( t1, tb >> 4 ); + GETREG( t2, tb & 0x0f ); + + SETREG( t2, tb >> 4 ); + SETREG( t1, tb & 0x0f ); +} + +/* $1F TFR inherent ----- */ +KONAMI_INLINE void tfr( void ) +{ + UINT8 tb; + UINT16 t = 0; + + IMMBYTE(tb); + + GETREG( t, tb & 0x0f ); + SETREG( t, ( tb >> 4 ) & 0x07 ); +} + +/* $20 BRA relative ----- */ +KONAMI_INLINE void bra( void ) +{ + UINT8 t; + IMMBYTE(t); + PC += SIGNED(t); + change_pc(PCD); + /* JB 970823 - speed up busy loops */ + if( t == 0xfe && konami_ICount > 0 ) + konami_ICount = 0; +} + +/* $21 BRN relative ----- */ +KONAMI_INLINE void brn( void ) +{ + UINT8 t; + IMMBYTE(t); +} + +/* $1021 LBRN relative ----- */ +KONAMI_INLINE void lbrn( void ) +{ + IMMWORD(ea); +} + +/* $22 BHI relative ----- */ +KONAMI_INLINE void bhi( void ) +{ + BRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $1022 LBHI relative ----- */ +KONAMI_INLINE void lbhi( void ) +{ + LBRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $23 BLS relative ----- */ +KONAMI_INLINE void bls( void ) +{ + BRANCH( (CC & (CC_Z|CC_C)) ); +} + +/* $1023 LBLS relative ----- */ +KONAMI_INLINE void lbls( void ) +{ + LBRANCH( (CC&(CC_Z|CC_C)) ); +} + +/* $24 BCC relative ----- */ +KONAMI_INLINE void bcc( void ) +{ + BRANCH( !(CC&CC_C) ); +} + +/* $1024 LBCC relative ----- */ +KONAMI_INLINE void lbcc( void ) +{ + LBRANCH( !(CC&CC_C) ); +} + +/* $25 BCS relative ----- */ +KONAMI_INLINE void bcs( void ) +{ + BRANCH( (CC&CC_C) ); +} + +/* $1025 LBCS relative ----- */ +KONAMI_INLINE void lbcs( void ) +{ + LBRANCH( (CC&CC_C) ); +} + +/* $26 BNE relative ----- */ +KONAMI_INLINE void bne( void ) +{ + BRANCH( !(CC&CC_Z) ); +} + +/* $1026 LBNE relative ----- */ +KONAMI_INLINE void lbne( void ) +{ + LBRANCH( !(CC&CC_Z) ); +} + +/* $27 BEQ relative ----- */ +KONAMI_INLINE void beq( void ) +{ + BRANCH( (CC&CC_Z) ); +} + +/* $1027 LBEQ relative ----- */ +KONAMI_INLINE void lbeq( void ) +{ + LBRANCH( (CC&CC_Z) ); +} + +/* $28 BVC relative ----- */ +KONAMI_INLINE void bvc( void ) +{ + BRANCH( !(CC&CC_V) ); +} + +/* $1028 LBVC relative ----- */ +KONAMI_INLINE void lbvc( void ) +{ + LBRANCH( !(CC&CC_V) ); +} + +/* $29 BVS relative ----- */ +KONAMI_INLINE void bvs( void ) +{ + BRANCH( (CC&CC_V) ); +} + +/* $1029 LBVS relative ----- */ +KONAMI_INLINE void lbvs( void ) +{ + LBRANCH( (CC&CC_V) ); +} + +/* $2A BPL relative ----- */ +KONAMI_INLINE void bpl( void ) +{ + BRANCH( !(CC&CC_N) ); +} + +/* $102A LBPL relative ----- */ +KONAMI_INLINE void lbpl( void ) +{ + LBRANCH( !(CC&CC_N) ); +} + +/* $2B BMI relative ----- */ +KONAMI_INLINE void bmi( void ) +{ + BRANCH( (CC&CC_N) ); +} + +/* $102B LBMI relative ----- */ +KONAMI_INLINE void lbmi( void ) +{ + LBRANCH( (CC&CC_N) ); +} + +/* $2C BGE relative ----- */ +KONAMI_INLINE void bge( void ) +{ + BRANCH( !NXORV ); +} + +/* $102C LBGE relative ----- */ +KONAMI_INLINE void lbge( void ) +{ + LBRANCH( !NXORV ); +} + +/* $2D BLT relative ----- */ +KONAMI_INLINE void blt( void ) +{ + BRANCH( NXORV ); +} + +/* $102D LBLT relative ----- */ +KONAMI_INLINE void lblt( void ) +{ + LBRANCH( NXORV ); +} + +/* $2E BGT relative ----- */ +KONAMI_INLINE void bgt( void ) +{ + BRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $102E LBGT relative ----- */ +KONAMI_INLINE void lbgt( void ) +{ + LBRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $2F BLE relative ----- */ +KONAMI_INLINE void ble( void ) +{ + BRANCH( (NXORV || (CC&CC_Z)) ); +} + +/* $102F LBLE relative ----- */ +KONAMI_INLINE void lble( void ) +{ + LBRANCH( (NXORV || (CC&CC_Z)) ); +} + +/* $30 LEAX indexed --*-- */ +KONAMI_INLINE void leax( void ) +{ + X = EA; + CLR_Z; + SET_Z(X); +} + +/* $31 LEAY indexed --*-- */ +KONAMI_INLINE void leay( void ) +{ + Y = EA; + CLR_Z; + SET_Z(Y); +} + +/* $32 LEAS indexed ----- */ +KONAMI_INLINE void leas( void ) +{ + S = EA; + konami.int_state |= KONAMI_LDS; +} + +/* $33 LEAU indexed ----- */ +KONAMI_INLINE void leau( void ) +{ + U = EA; +} + +/* $34 PSHS inherent ----- */ +KONAMI_INLINE void pshs( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PUSHWORD(pPC); konami_ICount -= 2; } + if( t&0x40 ) { PUSHWORD(pU); konami_ICount -= 2; } + if( t&0x20 ) { PUSHWORD(pY); konami_ICount -= 2; } + if( t&0x10 ) { PUSHWORD(pX); konami_ICount -= 2; } + if( t&0x08 ) { PUSHBYTE(DP); konami_ICount -= 1; } + if( t&0x04 ) { PUSHBYTE(B); konami_ICount -= 1; } + if( t&0x02 ) { PUSHBYTE(A); konami_ICount -= 1; } + if( t&0x01 ) { PUSHBYTE(CC); konami_ICount -= 1; } +} + +/* 35 PULS inherent ----- */ +KONAMI_INLINE void puls( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULLBYTE(CC); konami_ICount -= 1; } + if( t&0x02 ) { PULLBYTE(A); konami_ICount -= 1; } + if( t&0x04 ) { PULLBYTE(B); konami_ICount -= 1; } + if( t&0x08 ) { PULLBYTE(DP); konami_ICount -= 1; } + if( t&0x10 ) { PULLWORD(XD); konami_ICount -= 2; } + if( t&0x20 ) { PULLWORD(YD); konami_ICount -= 2; } + if( t&0x40 ) { PULLWORD(UD); konami_ICount -= 2; } + if( t&0x80 ) { PULLWORD(PCD); change_pc(PCD); konami_ICount -= 2; } + + /* check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES; } +} + +/* $36 PSHU inherent ----- */ +KONAMI_INLINE void pshu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PSHUWORD(pPC); konami_ICount -= 2; } + if( t&0x40 ) { PSHUWORD(pS); konami_ICount -= 2; } + if( t&0x20 ) { PSHUWORD(pY); konami_ICount -= 2; } + if( t&0x10 ) { PSHUWORD(pX); konami_ICount -= 2; } + if( t&0x08 ) { PSHUBYTE(DP); konami_ICount -= 1; } + if( t&0x04 ) { PSHUBYTE(B); konami_ICount -= 1; } + if( t&0x02 ) { PSHUBYTE(A); konami_ICount -= 1; } + if( t&0x01 ) { PSHUBYTE(CC); konami_ICount -= 1; } +} + +/* 37 PULU inherent ----- */ +KONAMI_INLINE void pulu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULUBYTE(CC); konami_ICount -= 1; } + if( t&0x02 ) { PULUBYTE(A); konami_ICount -= 1; } + if( t&0x04 ) { PULUBYTE(B); konami_ICount -= 1; } + if( t&0x08 ) { PULUBYTE(DP); konami_ICount -= 1; } + if( t&0x10 ) { PULUWORD(XD); konami_ICount -= 2; } + if( t&0x20 ) { PULUWORD(YD); konami_ICount -= 2; } + if( t&0x40 ) { PULUWORD(SD); konami_ICount -= 2; } + if( t&0x80 ) { PULUWORD(PCD); change_pc(PCD); konami_ICount -= 2; } + + /* check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES; } +} + +/* $38 ILLEGAL */ + +/* $39 RTS inherent ----- */ +KONAMI_INLINE void rts( void ) +{ + PULLWORD(PCD); + change_pc(PCD); +} + +/* $3A ABX inherent ----- */ +KONAMI_INLINE void abx( void ) +{ + X += B; +} + +/* $3B RTI inherent ##### */ +KONAMI_INLINE void rti( void ) +{ + PULLBYTE(CC); + if( CC & CC_E ) /* entire state saved? */ + { + konami_ICount -= 9; + PULLBYTE(A); + PULLBYTE(B); + PULLBYTE(DP); + PULLWORD(XD); + PULLWORD(YD); + PULLWORD(UD); + } + PULLWORD(PCD); + change_pc(PCD); + CHECK_IRQ_LINES; +} + +/* $3C CWAI inherent ----1 */ +KONAMI_INLINE void cwai( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + /* + * CWAI stacks the entire machine state on the hardware stack, + * then waits for an interrupt; when the interrupt is taken + * later, the state is *not* saved again after CWAI. + */ + CC |= CC_E; /* HJB 990225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + konami.int_state |= KONAMI_CWAI; + CHECK_IRQ_LINES; + if( (konami.int_state & KONAMI_CWAI) && konami_ICount > 0 ) + konami_ICount = 0; +} + +/* $3D MUL inherent --*-@ */ +KONAMI_INLINE void mul( void ) +{ + UINT16 t; + t = A * B; + CLR_ZC; SET_Z16(t); if(t&0x80) SEC; + D = t; +} + +/* $3E ILLEGAL */ + +/* $3F SWI (SWI2 SWI3) absolute indirect ----- */ +KONAMI_INLINE void swi( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD=RM16(0xfffa); + change_pc(PCD); +} + +/* $103F SWI2 absolute indirect ----- */ +KONAMI_INLINE void swi2( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD=RM16(0xfff4); + change_pc(PCD); +} + +/* $113F SWI3 absolute indirect ----- */ +KONAMI_INLINE void swi3( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD=RM16(0xfff2); + change_pc(PCD); +} + +/* $40 NEGA inherent ?**** */ +KONAMI_INLINE void nega( void ) +{ + UINT16 r; + r = -A; + CLR_NZVC; + SET_FLAGS8(0,A,r); + A = r; +} + +/* $41 ILLEGAL */ + +/* $42 ILLEGAL */ + +/* $43 COMA inherent -**01 */ +KONAMI_INLINE void coma( void ) +{ + A = ~A; + CLR_NZV; + SET_NZ8(A); + SEC; +} + +/* $44 LSRA inherent -0*-* */ +KONAMI_INLINE void lsra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A >>= 1; + SET_Z8(A); +} + +/* $45 ILLEGAL */ + +/* $46 RORA inherent -**-* */ +KONAMI_INLINE void rora( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (A & CC_C); + r |= A >> 1; + SET_NZ8(r); + A = r; +} + +/* $47 ASRA inherent ?**-* */ +KONAMI_INLINE void asra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A = (A & 0x80) | (A >> 1); + SET_NZ8(A); +} + +/* $48 ASLA inherent ?**** */ +KONAMI_INLINE void asla( void ) +{ + UINT16 r; + r = A << 1; + CLR_NZVC; + SET_FLAGS8(A,A,r); + A = r; +} + +/* $49 ROLA inherent -**** */ +KONAMI_INLINE void rola( void ) +{ + UINT16 t,r; + t = A; + r = (CC & CC_C) | (t<<1); + CLR_NZVC; SET_FLAGS8(t,t,r); + A = r; +} + +/* $4A DECA inherent -***- */ +KONAMI_INLINE void deca( void ) +{ + --A; + CLR_NZV; + SET_FLAGS8D(A); +} + +/* $4B ILLEGAL */ + +/* $4C INCA inherent -***- */ +KONAMI_INLINE void inca( void ) +{ + ++A; + CLR_NZV; + SET_FLAGS8I(A); +} + +/* $4D TSTA inherent -**0- */ +KONAMI_INLINE void tsta( void ) +{ + CLR_NZV; + SET_NZ8(A); +} + +/* $4E ILLEGAL */ + +/* $4F CLRA inherent -0100 */ +KONAMI_INLINE void clra( void ) +{ + A = 0; + CLR_NZVC; SEZ; +} + +/* $50 NEGB inherent ?**** */ +KONAMI_INLINE void negb( void ) +{ + UINT16 r; + r = -B; + CLR_NZVC; + SET_FLAGS8(0,B,r); + B = r; +} + +/* $51 ILLEGAL */ + +/* $52 ILLEGAL */ + +/* $53 COMB inherent -**01 */ +KONAMI_INLINE void comb( void ) +{ + B = ~B; + CLR_NZV; + SET_NZ8(B); + SEC; +} + +/* $54 LSRB inherent -0*-* */ +KONAMI_INLINE void lsrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B >>= 1; + SET_Z8(B); +} + +/* $55 ILLEGAL */ + +/* $56 RORB inherent -**-* */ +KONAMI_INLINE void rorb( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (B & CC_C); + r |= B >> 1; + SET_NZ8(r); + B = r; +} + +/* $57 ASRB inherent ?**-* */ +KONAMI_INLINE void asrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B= (B & 0x80) | (B >> 1); + SET_NZ8(B); +} + +/* $58 ASLB inherent ?**** */ +KONAMI_INLINE void aslb( void ) +{ + UINT16 r; + r = B << 1; + CLR_NZVC; + SET_FLAGS8(B,B,r); + B = r; +} + +/* $59 ROLB inherent -**** */ +KONAMI_INLINE void rolb( void ) +{ + UINT16 t,r; + t = B; + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + B = r; +} + +/* $5A DECB inherent -***- */ +KONAMI_INLINE void decb( void ) +{ + --B; + CLR_NZV; + SET_FLAGS8D(B); +} + +/* $5B ILLEGAL */ + +/* $5C INCB inherent -***- */ +KONAMI_INLINE void incb( void ) +{ + ++B; + CLR_NZV; + SET_FLAGS8I(B); +} + +/* $5D TSTB inherent -**0- */ +KONAMI_INLINE void tstb( void ) +{ + CLR_NZV; + SET_NZ8(B); +} + +/* $5E ILLEGAL */ + +/* $5F CLRB inherent -0100 */ +KONAMI_INLINE void clrb( void ) +{ + B = 0; + CLR_NZVC; SEZ; +} + +/* $60 NEG indexed ?**** */ +KONAMI_INLINE void neg_ix( void ) +{ + UINT16 r,t; + t = RM(EAD); + r = -t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $61 ILLEGAL */ + +/* $62 ILLEGAL */ + +/* $63 COM indexed -**01 */ +KONAMI_INLINE void com_ix( void ) +{ + UINT8 t; + t = ~RM(EAD); + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $64 LSR indexed -0*-* */ +KONAMI_INLINE void lsr_ix( void ) +{ + UINT8 t; + t = RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $65 ILLEGAL */ + +/* $66 ROR indexed -**-* */ +KONAMI_INLINE void ror_ix( void ) +{ + UINT8 t,r; + t = RM(EAD); + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $67 ASR indexed ?**-* */ +KONAMI_INLINE void asr_ix( void ) +{ + UINT8 t; + t = RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $68 ASL indexed ?**** */ +KONAMI_INLINE void asl_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $69 ROL indexed -**** */ +KONAMI_INLINE void rol_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $6A DEC indexed -***- */ +KONAMI_INLINE void dec_ix( void ) +{ + UINT8 t; + t = RM(EAD) - 1; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $6B ILLEGAL */ + +/* $6C INC indexed -***- */ +KONAMI_INLINE void inc_ix( void ) +{ + UINT8 t; + t = RM(EAD) + 1; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $6D TST indexed -**0- */ +KONAMI_INLINE void tst_ix( void ) +{ + UINT8 t; + t = RM(EAD); + CLR_NZV; + SET_NZ8(t); +} + +/* $6E JMP indexed ----- */ +KONAMI_INLINE void jmp_ix( void ) +{ + PCD=EAD; + change_pc(PCD); +} + +/* $6F CLR indexed -0100 */ +KONAMI_INLINE void clr_ix( void ) +{ + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $70 NEG extended ?**** */ +KONAMI_INLINE void neg_ex( void ) +{ + UINT16 r,t; + EXTBYTE(t); r=-t; + CLR_NZVC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $71 ILLEGAL */ + +/* $72 ILLEGAL */ + +/* $73 COM extended -**01 */ +KONAMI_INLINE void com_ex( void ) +{ + UINT8 t; + EXTBYTE(t); t = ~t; + CLR_NZV; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $74 LSR extended -0*-* */ +KONAMI_INLINE void lsr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $75 ILLEGAL */ + +/* $76 ROR extended -**-* */ +KONAMI_INLINE void ror_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); r=(CC & CC_C) << 7; + CLR_NZC; CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $77 ASR extended ?**-* */ +KONAMI_INLINE void asr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $78 ASL extended ?**** */ +KONAMI_INLINE void asl_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r=t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $79 ROL extended -**** */ +KONAMI_INLINE void rol_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = (CC & CC_C) | (t << 1); + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $7A DEC extended -***- */ +KONAMI_INLINE void dec_ex( void ) +{ + UINT8 t; + EXTBYTE(t); --t; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $7B ILLEGAL */ + +/* $7C INC extended -***- */ +KONAMI_INLINE void inc_ex( void ) +{ + UINT8 t; + EXTBYTE(t); ++t; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $7D TST extended -**0- */ +KONAMI_INLINE void tst_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZV; SET_NZ8(t); +} + +/* $7E JMP extended ----- */ +KONAMI_INLINE void jmp_ex( void ) +{ + EXTENDED; + PCD=EAD; + change_pc(PCD); +} + +/* $7F CLR extended -0100 */ +KONAMI_INLINE void clr_ex( void ) +{ + EXTENDED; + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $80 SUBA immediate ?**** */ +KONAMI_INLINE void suba_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $81 CMPA immediate ?**** */ +KONAMI_INLINE void cmpa_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $82 SBCA immediate ?**** */ +KONAMI_INLINE void sbca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $83 SUBD (CMPD CMPU) immediate -**** */ +KONAMI_INLINE void subd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1083 CMPD immediate -**** */ +KONAMI_INLINE void cmpd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1183 CMPU immediate -**** */ +KONAMI_INLINE void cmpu_im( void ) +{ + UINT32 r, d; + PAIR b; + IMMWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $84 ANDA immediate -**0- */ +KONAMI_INLINE void anda_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $85 BITA immediate -**0- */ +KONAMI_INLINE void bita_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $86 LDA immediate -**0- */ +KONAMI_INLINE void lda_im( void ) +{ + IMMBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* is this a legal instruction? */ +/* $87 STA immediate -**0- */ +KONAMI_INLINE void sta_im( void ) +{ + CLR_NZV; + SET_NZ8(A); + IMM8; + WM(EAD,A); +} + +/* $88 EORA immediate -**0- */ +KONAMI_INLINE void eora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $89 ADCA immediate ***** */ +KONAMI_INLINE void adca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8A ORA immediate -**0- */ +KONAMI_INLINE void ora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $8B ADDA immediate ***** */ +KONAMI_INLINE void adda_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8C CMPX (CMPY CMPS) immediate -**** */ +KONAMI_INLINE void cmpx_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $108C CMPY immediate -**** */ +KONAMI_INLINE void cmpy_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $118C CMPS immediate -**** */ +KONAMI_INLINE void cmps_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $8D BSR ----- */ +KONAMI_INLINE void bsr( void ) +{ + UINT8 t; + IMMBYTE(t); + PUSHWORD(pPC); + PC += SIGNED(t); + change_pc(PCD); +} + +/* $8E LDX (LDY) immediate -**0- */ +KONAMI_INLINE void ldx_im( void ) +{ + IMMWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $108E LDY immediate -**0- */ +KONAMI_INLINE void ldy_im( void ) +{ + IMMWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* is this a legal instruction? */ +/* $8F STX (STY) immediate -**0- */ +KONAMI_INLINE void stx_im( void ) +{ + CLR_NZV; + SET_NZ16(X); + IMM16; + WM16(EAD,&pX); +} + +/* is this a legal instruction? */ +/* $108F STY immediate -**0- */ +KONAMI_INLINE void sty_im( void ) +{ + CLR_NZV; + SET_NZ16(Y); + IMM16; + WM16(EAD,&pY); +} + +/* $90 SUBA direct ?**** */ +KONAMI_INLINE void suba_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $91 CMPA direct ?**** */ +KONAMI_INLINE void cmpa_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $92 SBCA direct ?**** */ +KONAMI_INLINE void sbca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $93 SUBD (CMPD CMPU) direct -**** */ +KONAMI_INLINE void subd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1093 CMPD direct -**** */ +KONAMI_INLINE void cmpd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1193 CMPU direct -**** */ +KONAMI_INLINE void cmpu_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $94 ANDA direct -**0- */ +KONAMI_INLINE void anda_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $95 BITA direct -**0- */ +KONAMI_INLINE void bita_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $96 LDA direct -**0- */ +KONAMI_INLINE void lda_di( void ) +{ + DIRBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $97 STA direct -**0- */ +KONAMI_INLINE void sta_di( void ) +{ + CLR_NZV; + SET_NZ8(A); + DIRECT; + WM(EAD,A); +} + +/* $98 EORA direct -**0- */ +KONAMI_INLINE void eora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $99 ADCA direct ***** */ +KONAMI_INLINE void adca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9A ORA direct -**0- */ +KONAMI_INLINE void ora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $9B ADDA direct ***** */ +KONAMI_INLINE void adda_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9C CMPX (CMPY CMPS) direct -**** */ +KONAMI_INLINE void cmpx_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $109C CMPY direct -**** */ +KONAMI_INLINE void cmpy_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $119C CMPS direct -**** */ +KONAMI_INLINE void cmps_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $9D JSR direct ----- */ +KONAMI_INLINE void jsr_di( void ) +{ + DIRECT; + PUSHWORD(pPC); + PCD=EAD; + change_pc(PCD); +} + +/* $9E LDX (LDY) direct -**0- */ +KONAMI_INLINE void ldx_di( void ) +{ + DIRWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $109E LDY direct -**0- */ +KONAMI_INLINE void ldy_di( void ) +{ + DIRWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $9F STX (STY) direct -**0- */ +KONAMI_INLINE void stx_di( void ) +{ + CLR_NZV; + SET_NZ16(X); + DIRECT; + WM16(EAD,&pX); +} + +/* $109F STY direct -**0- */ +KONAMI_INLINE void sty_di( void ) +{ + CLR_NZV; + SET_NZ16(Y); + DIRECT; + WM16(EAD,&pY); +} + +/* $a0 SUBA indexed ?**** */ +KONAMI_INLINE void suba_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a1 CMPA indexed ?**** */ +KONAMI_INLINE void cmpa_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $a2 SBCA indexed ?**** */ +KONAMI_INLINE void sbca_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a3 SUBD (CMPD CMPU) indexed -**** */ +KONAMI_INLINE void subd_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10a3 CMPD indexed -**** */ +KONAMI_INLINE void cmpd_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11a3 CMPU indexed -**** */ +KONAMI_INLINE void cmpu_ix( void ) +{ + UINT32 r; + PAIR b; + b.d=RM16(EAD); + r = U - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $a4 ANDA indexed -**0- */ +KONAMI_INLINE void anda_ix( void ) +{ + A &= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a5 BITA indexed -**0- */ +KONAMI_INLINE void bita_ix( void ) +{ + UINT8 r; + r = A & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $a6 LDA indexed -**0- */ +KONAMI_INLINE void lda_ix( void ) +{ + A = RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a7 STA indexed -**0- */ +KONAMI_INLINE void sta_ix( void ) +{ + CLR_NZV; + SET_NZ8(A); + WM(EAD,A); +} + +/* $a8 EORA indexed -**0- */ +KONAMI_INLINE void eora_ix( void ) +{ + A ^= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a9 ADCA indexed ***** */ +KONAMI_INLINE void adca_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aA ORA indexed -**0- */ +KONAMI_INLINE void ora_ix( void ) +{ + A |= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $aB ADDA indexed ***** */ +KONAMI_INLINE void adda_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aC CMPX (CMPY CMPS) indexed -**** */ +KONAMI_INLINE void cmpx_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10aC CMPY indexed -**** */ +KONAMI_INLINE void cmpy_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11aC CMPS indexed -**** */ +KONAMI_INLINE void cmps_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $aD JSR indexed ----- */ +KONAMI_INLINE void jsr_ix( void ) +{ + PUSHWORD(pPC); + PCD=EAD; + change_pc(PCD); +} + +/* $aE LDX (LDY) indexed -**0- */ +KONAMI_INLINE void ldx_ix( void ) +{ + X=RM16(EAD); + CLR_NZV; + SET_NZ16(X); +} + +/* $10aE LDY indexed -**0- */ +KONAMI_INLINE void ldy_ix( void ) +{ + Y=RM16(EAD); + CLR_NZV; + SET_NZ16(Y); +} + +/* $aF STX (STY) indexed -**0- */ +KONAMI_INLINE void stx_ix( void ) +{ + CLR_NZV; + SET_NZ16(X); + WM16(EAD,&pX); +} + +/* $10aF STY indexed -**0- */ +KONAMI_INLINE void sty_ix( void ) +{ + CLR_NZV; + SET_NZ16(Y); + WM16(EAD,&pY); +} + +/* $b0 SUBA extended ?**** */ +KONAMI_INLINE void suba_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b1 CMPA extended ?**** */ +KONAMI_INLINE void cmpa_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $b2 SBCA extended ?**** */ +KONAMI_INLINE void sbca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b3 SUBD (CMPD CMPU) extended -**** */ +KONAMI_INLINE void subd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10b3 CMPD extended -**** */ +KONAMI_INLINE void cmpd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11b3 CMPU extended -**** */ +KONAMI_INLINE void cmpu_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $b4 ANDA extended -**0- */ +KONAMI_INLINE void anda_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b5 BITA extended -**0- */ +KONAMI_INLINE void bita_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = A & t; + CLR_NZV; SET_NZ8(r); +} + +/* $b6 LDA extended -**0- */ +KONAMI_INLINE void lda_ex( void ) +{ + EXTBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $b7 STA extended -**0- */ +KONAMI_INLINE void sta_ex( void ) +{ + CLR_NZV; + SET_NZ8(A); + EXTENDED; + WM(EAD,A); +} + +/* $b8 EORA extended -**0- */ +KONAMI_INLINE void eora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b9 ADCA extended ***** */ +KONAMI_INLINE void adca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bA ORA extended -**0- */ +KONAMI_INLINE void ora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $bB ADDA extended ***** */ +KONAMI_INLINE void adda_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bC CMPX (CMPY CMPS) extended -**** */ +KONAMI_INLINE void cmpx_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10bC CMPY extended -**** */ +KONAMI_INLINE void cmpy_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11bC CMPS extended -**** */ +KONAMI_INLINE void cmps_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $bD JSR extended ----- */ +KONAMI_INLINE void jsr_ex( void ) +{ + EXTENDED; + PUSHWORD(pPC); + PCD=EAD; + change_pc(PCD); +} + +/* $bE LDX (LDY) extended -**0- */ +KONAMI_INLINE void ldx_ex( void ) +{ + EXTWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $10bE LDY extended -**0- */ +KONAMI_INLINE void ldy_ex( void ) +{ + EXTWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $bF STX (STY) extended -**0- */ +KONAMI_INLINE void stx_ex( void ) +{ + CLR_NZV; + SET_NZ16(X); + EXTENDED; + WM16(EAD,&pX); +} + +/* $10bF STY extended -**0- */ +KONAMI_INLINE void sty_ex( void ) +{ + CLR_NZV; + SET_NZ16(Y); + EXTENDED; + WM16(EAD,&pY); +} + +/* $c0 SUBB immediate ?**** */ +KONAMI_INLINE void subb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $c1 CMPB immediate ?**** */ +KONAMI_INLINE void cmpb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $c2 SBCB immediate ?**** */ +KONAMI_INLINE void sbcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $c3 ADDD immediate -**** */ +KONAMI_INLINE void addd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $c4 ANDB immediate -**0- */ +KONAMI_INLINE void andb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $c5 BITB immediate -**0- */ +KONAMI_INLINE void bitb_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $c6 LDB immediate -**0- */ +KONAMI_INLINE void ldb_im( void ) +{ + IMMBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* is this a legal instruction? */ +/* $c7 STB immediate -**0- */ +KONAMI_INLINE void stb_im( void ) +{ + CLR_NZV; + SET_NZ8(B); + IMM8; + WM(EAD,B); +} + +/* $c8 EORB immediate -**0- */ +KONAMI_INLINE void eorb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $c9 ADCB immediate ***** */ +KONAMI_INLINE void adcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $cA ORB immediate -**0- */ +KONAMI_INLINE void orb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $cB ADDB immediate ***** */ +KONAMI_INLINE void addb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $cC LDD immediate -**0- */ +KONAMI_INLINE void ldd_im( void ) +{ + IMMWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* is this a legal instruction? */ +/* $cD STD immediate -**0- */ +KONAMI_INLINE void std_im( void ) +{ + CLR_NZV; + SET_NZ16(D); + IMM16; + WM16(EAD,&pD); +} + +/* $cE LDU (LDS) immediate -**0- */ +KONAMI_INLINE void ldu_im( void ) +{ + IMMWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10cE LDS immediate -**0- */ +KONAMI_INLINE void lds_im( void ) +{ + IMMWORD(pS); + CLR_NZV; + SET_NZ16(S); + konami.int_state |= KONAMI_LDS; +} + +/* is this a legal instruction? */ +/* $cF STU (STS) immediate -**0- */ +KONAMI_INLINE void stu_im( void ) +{ + CLR_NZV; + SET_NZ16(U); + IMM16; + WM16(EAD,&pU); +} + +/* is this a legal instruction? */ +/* $10cF STS immediate -**0- */ +KONAMI_INLINE void sts_im( void ) +{ + CLR_NZV; + SET_NZ16(S); + IMM16; + WM16(EAD,&pS); +} + +/* $d0 SUBB direct ?**** */ +KONAMI_INLINE void subb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $d1 CMPB direct ?**** */ +KONAMI_INLINE void cmpb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $d2 SBCB direct ?**** */ +KONAMI_INLINE void sbcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $d3 ADDD direct -**** */ +KONAMI_INLINE void addd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $d4 ANDB direct -**0- */ +KONAMI_INLINE void andb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $d5 BITB direct -**0- */ +KONAMI_INLINE void bitb_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $d6 LDB direct -**0- */ +KONAMI_INLINE void ldb_di( void ) +{ + DIRBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $d7 STB direct -**0- */ +KONAMI_INLINE void stb_di( void ) +{ + CLR_NZV; + SET_NZ8(B); + DIRECT; + WM(EAD,B); +} + +/* $d8 EORB direct -**0- */ +KONAMI_INLINE void eorb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $d9 ADCB direct ***** */ +KONAMI_INLINE void adcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $dA ORB direct -**0- */ +KONAMI_INLINE void orb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $dB ADDB direct ***** */ +KONAMI_INLINE void addb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $dC LDD direct -**0- */ +KONAMI_INLINE void ldd_di( void ) +{ + DIRWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* $dD STD direct -**0- */ +KONAMI_INLINE void std_di( void ) +{ + CLR_NZV; + SET_NZ16(D); + DIRECT; + WM16(EAD,&pD); +} + +/* $dE LDU (LDS) direct -**0- */ +KONAMI_INLINE void ldu_di( void ) +{ + DIRWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10dE LDS direct -**0- */ +KONAMI_INLINE void lds_di( void ) +{ + DIRWORD(pS); + CLR_NZV; + SET_NZ16(S); + konami.int_state |= KONAMI_LDS; +} + +/* $dF STU (STS) direct -**0- */ +KONAMI_INLINE void stu_di( void ) +{ + CLR_NZV; + SET_NZ16(U); + DIRECT; + WM16(EAD,&pU); +} + +/* $10dF STS direct -**0- */ +KONAMI_INLINE void sts_di( void ) +{ + CLR_NZV; + SET_NZ16(S); + DIRECT; + WM16(EAD,&pS); +} + +/* $e0 SUBB indexed ?**** */ +KONAMI_INLINE void subb_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $e1 CMPB indexed ?**** */ +KONAMI_INLINE void cmpb_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $e2 SBCB indexed ?**** */ +KONAMI_INLINE void sbcb_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $e3 ADDD indexed -**** */ +KONAMI_INLINE void addd_ix( void ) +{ + UINT32 r,d; + PAIR b; + b.d=RM16(EAD); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $e4 ANDB indexed -**0- */ +KONAMI_INLINE void andb_ix( void ) +{ + B &= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e5 BITB indexed -**0- */ +KONAMI_INLINE void bitb_ix( void ) +{ + UINT8 r; + r = B & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $e6 LDB indexed -**0- */ +KONAMI_INLINE void ldb_ix( void ) +{ + B = RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e7 STB indexed -**0- */ +KONAMI_INLINE void stb_ix( void ) +{ + CLR_NZV; + SET_NZ8(B); + WM(EAD,B); +} + +/* $e8 EORB indexed -**0- */ +KONAMI_INLINE void eorb_ix( void ) +{ + B ^= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e9 ADCB indexed ***** */ +KONAMI_INLINE void adcb_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $eA ORB indexed -**0- */ +KONAMI_INLINE void orb_ix( void ) +{ + B |= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $eb ADDB indexed ***** */ +KONAMI_INLINE void addb_ix( void ) +{ + UINT16 t,r; + t = RM(EAD); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $ec LDD indexed -**0- */ +KONAMI_INLINE void ldd_ix( void ) +{ + D=RM16(EAD); + CLR_NZV; SET_NZ16(D); +} + +/* $eD STD indexed -**0- */ +KONAMI_INLINE void std_ix( void ) +{ + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&pD); +} + +/* $eE LDU (LDS) indexed -**0- */ +KONAMI_INLINE void ldu_ix( void ) +{ + U=RM16(EAD); + CLR_NZV; + SET_NZ16(U); +} + +/* $10eE LDS indexed -**0- */ +KONAMI_INLINE void lds_ix( void ) +{ + S=RM16(EAD); + CLR_NZV; + SET_NZ16(S); + konami.int_state |= KONAMI_LDS; +} + +/* $eF STU (STS) indexed -**0- */ +KONAMI_INLINE void stu_ix( void ) +{ + CLR_NZV; + SET_NZ16(U); + WM16(EAD,&pU); +} + +/* $10eF STS indexed -**0- */ +KONAMI_INLINE void sts_ix( void ) +{ + CLR_NZV; + SET_NZ16(S); + WM16(EAD,&pS); +} + +/* $f0 SUBB extended ?**** */ +KONAMI_INLINE void subb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $f1 CMPB extended ?**** */ +KONAMI_INLINE void cmpb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $f2 SBCB extended ?**** */ +KONAMI_INLINE void sbcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $f3 ADDD extended -**** */ +KONAMI_INLINE void addd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $f4 ANDB extended -**0- */ +KONAMI_INLINE void andb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $f5 BITB extended -**0- */ +KONAMI_INLINE void bitb_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $f6 LDB extended -**0- */ +KONAMI_INLINE void ldb_ex( void ) +{ + EXTBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $f7 STB extended -**0- */ +KONAMI_INLINE void stb_ex( void ) +{ + CLR_NZV; + SET_NZ8(B); + EXTENDED; + WM(EAD,B); +} + +/* $f8 EORB extended -**0- */ +KONAMI_INLINE void eorb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $f9 ADCB extended ***** */ +KONAMI_INLINE void adcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $fA ORB extended -**0- */ +KONAMI_INLINE void orb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $fB ADDB extended ***** */ +KONAMI_INLINE void addb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $fC LDD extended -**0- */ +KONAMI_INLINE void ldd_ex( void ) +{ + EXTWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* $fD STD extended -**0- */ +KONAMI_INLINE void std_ex( void ) +{ + CLR_NZV; + SET_NZ16(D); + EXTENDED; + WM16(EAD,&pD); +} + +/* $fE LDU (LDS) extended -**0- */ +KONAMI_INLINE void ldu_ex( void ) +{ + EXTWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10fE LDS extended -**0- */ +KONAMI_INLINE void lds_ex( void ) +{ + EXTWORD(pS); + CLR_NZV; + SET_NZ16(S); + konami.int_state |= KONAMI_LDS; +} + +/* $fF STU (STS) extended -**0- */ +KONAMI_INLINE void stu_ex( void ) +{ + CLR_NZV; + SET_NZ16(U); + EXTENDED; + WM16(EAD,&pU); +} + +/* $10fF STS extended -**0- */ +KONAMI_INLINE void sts_ex( void ) +{ + CLR_NZV; + SET_NZ16(S); + EXTENDED; + WM16(EAD,&pS); +} + +KONAMI_INLINE void setline_im( void ) +{ + UINT8 t; + IMMBYTE(t); + + if ( konami.setlines_callback ) + (*konami.setlines_callback)( t ); +} + +KONAMI_INLINE void setline_ix( void ) +{ + UINT8 t; + t = RM(EA); + + if ( konami.setlines_callback ) + (*konami.setlines_callback)( t ); +} + +KONAMI_INLINE void setline_di( void ) +{ + UINT8 t; + DIRBYTE(t); + + if ( konami.setlines_callback ) + (*konami.setlines_callback)( t ); +} + +KONAMI_INLINE void setline_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + + if ( konami.setlines_callback ) + (*konami.setlines_callback)( t ); +} + +KONAMI_INLINE void bmove( void ) +{ + UINT8 t; + + while( U != 0 ) { + t = RM(Y); + WM(X,t); + Y++; + X++; + U--; + konami_ICount -= 2; + } +} + +KONAMI_INLINE void move( void ) +{ + UINT8 t; + + t = RM(Y); + WM(X,t); + Y++; + X++; + U--; +} + +/* CLRD inherent -0100 */ +KONAMI_INLINE void clrd( void ) +{ + D = 0; + CLR_NZVC; SEZ; +} + +/* CLRW indexed -0100 */ +KONAMI_INLINE void clrw_ix( void ) +{ + PAIR t; + t.d = 0; + WM16(EAD,&t); + CLR_NZVC; SEZ; +} + +/* CLRW direct -0100 */ +KONAMI_INLINE void clrw_di( void ) +{ + PAIR t; + t.d = 0; + DIRECT; + WM16(EAD,&t); + CLR_NZVC; + SEZ; +} + +/* CLRW extended -0100 */ +KONAMI_INLINE void clrw_ex( void ) +{ + PAIR t; + t.d = 0; + EXTENDED; + WM16(EAD,&t); + CLR_NZVC; SEZ; +} + +/* LSRD immediate -0*-* */ +KONAMI_INLINE void lsrd( void ) +{ + UINT8 t; + + IMMBYTE( t ); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D >>= 1; + SET_Z16(D); + } +} + +/* RORD immediate -**-* */ +KONAMI_INLINE void rord( void ) +{ + UINT16 r; + UINT8 t; + + IMMBYTE(t); + + while ( t-- ) { + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (D & CC_C); + r |= D >> 1; + SET_NZ16(r); + D = r; + } +} + +/* ASRD immediate ?**-* */ +KONAMI_INLINE void asrd( void ) +{ + UINT8 t; + + IMMBYTE(t); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D = (D & 0x8000) | (D >> 1); + SET_NZ16(D); + } +} + +/* ASLD immediate ?**** */ +KONAMI_INLINE void asld( void ) +{ + UINT32 r; + UINT8 t; + + IMMBYTE( t ); + + while ( t-- ) { + r = D << 1; + CLR_NZVC; + SET_FLAGS16(D,D,r); + D = r; + } +} + +/* ROLD immediate -**-* */ +KONAMI_INLINE void rold( void ) +{ + UINT16 r; + UINT8 t; + + IMMBYTE(t); + + while ( t-- ) { + CLR_NZC; + if ( D & 0x8000 ) SEC; + r = CC & CC_C; + r |= D << 1; + SET_NZ16(r); + D = r; + } +} + +/* DECB,JNZ relative ----- */ +KONAMI_INLINE void decbjnz( void ) +{ + --B; + CLR_NZV; + SET_FLAGS8D(B); + BRANCH( !(CC&CC_Z) ); +} + +/* DECX,JNZ relative ----- */ +KONAMI_INLINE void decxjnz( void ) +{ + --X; + CLR_NZV; + SET_NZ16(X); /* should affect V as well? */ + BRANCH( !(CC&CC_Z) ); +} + +KONAMI_INLINE void bset( void ) +{ + UINT8 t; + + while( U != 0 ) { + t = A; + WM(XD,t); + X++; + U--; + konami_ICount -= 2; + } +} + +KONAMI_INLINE void bset2( void ) +{ + while( U != 0 ) { + WM16(XD,&pD); + X += 2; + U--; + konami_ICount -= 3; + } +} + +/* LMUL inherent --*-@ */ +KONAMI_INLINE void lmul( void ) +{ + UINT32 t; + t = X * Y; + X = (t >> 16); + Y = (t & 0xffff); + CLR_ZC; SET_Z(t); if( t & 0x8000 ) SEC; +} + +/* DIVX inherent --*-@ */ +KONAMI_INLINE void divx( void ) +{ + UINT16 t; + UINT8 r; + if ( B != 0 ) + { + t = X / B; + r = X % B; + } + else + { + /* ?? */ + t = 0; + r = 0; + } + CLR_ZC; SET_Z16(t); if ( t & 0x80 ) SEC; + X = t; + B = r; +} + +/* INCD inherent -***- */ +KONAMI_INLINE void incd( void ) +{ + UINT32 r; + r = D + 1; + CLR_NZV; + SET_FLAGS16(D,D,r); + D = r; +} + +/* INCW direct -***- */ +KONAMI_INLINE void incw_di( void ) +{ + PAIR t,r; + DIRWORD(t); + r = t; + ++r.d; + CLR_NZV; + SET_FLAGS16(t.d, t.d, r.d); + WM16(EAD,&r); +} + +/* INCW indexed -***- */ +KONAMI_INLINE void incw_ix( void ) +{ + PAIR t,r; + t.d=RM16(EAD); + r = t; + ++r.d; + CLR_NZV; + SET_FLAGS16(t.d, t.d, r.d); + WM16(EAD,&r); +} + +/* INCW extended -***- */ +KONAMI_INLINE void incw_ex( void ) +{ + PAIR t, r; + EXTWORD(t); + r = t; + ++r.d; + CLR_NZV; SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* DECD inherent -***- */ +KONAMI_INLINE void decd( void ) +{ + UINT32 r; + r = D - 1; + CLR_NZV; + SET_FLAGS16(D,D,r); + D = r; +} + +/* DECW direct -***- */ +KONAMI_INLINE void decw_di( void ) +{ + PAIR t,r; + DIRWORD(t); + r = t; + --r.d; + CLR_NZV; + SET_FLAGS16(t.d, t.d, r.d); + WM16(EAD,&r); +} + +/* DECW indexed -***- */ +KONAMI_INLINE void decw_ix( void ) +{ + PAIR t, r; + t.d=RM16(EAD); + r = t; + --r.d; + CLR_NZV; SET_FLAGS16(t.d, t.d, r.d); + WM16(EAD,&r); +} + +/* DECW extended -***- */ +KONAMI_INLINE void decw_ex( void ) +{ + PAIR t, r; + EXTWORD(t); + r = t; + --r.d; + CLR_NZV; SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* TSTD inherent -**0- */ +KONAMI_INLINE void tstd( void ) +{ + CLR_NZV; + SET_NZ16(D); +} + +/* TSTW direct -**0- */ +KONAMI_INLINE void tstw_di( void ) +{ + PAIR t; + CLR_NZV; + DIRWORD(t); + SET_NZ16(t.d); +} + +/* TSTW indexed -**0- */ +KONAMI_INLINE void tstw_ix( void ) +{ + PAIR t; + CLR_NZV; + t.d=RM16(EAD); + SET_NZ16(t.d); +} + +/* TSTW extended -**0- */ +KONAMI_INLINE void tstw_ex( void ) +{ + PAIR t; + CLR_NZV; + EXTWORD(t); + SET_NZ16(t.d); +} + +/* LSRW direct -0*-* */ +KONAMI_INLINE void lsrw_di( void ) +{ + PAIR t; + DIRWORD(t); + CLR_NZC; + CC |= (t.d & CC_C); + t.d >>= 1; + SET_Z16(t.d); + WM16(EAD,&t); +} + +/* LSRW indexed -0*-* */ +KONAMI_INLINE void lsrw_ix( void ) +{ + PAIR t; + t.d=RM16(EAD); + CLR_NZC; + CC |= (t.d & CC_C); + t.d >>= 1; + SET_Z16(t.d); + WM16(EAD,&t); +} + +/* LSRW extended -0*-* */ +KONAMI_INLINE void lsrw_ex( void ) +{ + PAIR t; + EXTWORD(t); + CLR_NZC; + CC |= (t.d & CC_C); + t.d >>= 1; + SET_Z16(t.d); + WM16(EAD,&t); +} + +/* RORW direct -**-* */ +KONAMI_INLINE void rorw_di( void ) +{ + PAIR t,r; + DIRWORD(t); + r.d = (CC & CC_C) << 15; + CLR_NZC; + CC |= (t.d & CC_C); + r.d |= t.d>>1; + SET_NZ16(r.d); + WM16(EAD,&r); +} + +/* RORW indexed -**-* */ +KONAMI_INLINE void rorw_ix( void ) +{ + PAIR t,r; + t.d=RM16(EAD); + r.d = (CC & CC_C) << 15; + CLR_NZC; + CC |= (t.d & CC_C); + r.d |= t.d>>1; + SET_NZ16(r.d); + WM16(EAD,&r); +} + +/* RORW extended -**-* */ +KONAMI_INLINE void rorw_ex( void ) +{ + PAIR t,r; + EXTWORD(t); + r.d = (CC & CC_C) << 15; + CLR_NZC; + CC |= (t.d & CC_C); + r.d |= t.d>>1; + SET_NZ16(r.d); + WM16(EAD,&r); +} + +/* ASRW direct ?**-* */ +KONAMI_INLINE void asrw_di( void ) +{ + PAIR t; + DIRWORD(t); + CLR_NZC; + CC |= (t.d & CC_C); + t.d = (t.d & 0x8000) | (t.d >> 1); + SET_NZ16(t.d); + WM16(EAD,&t); +} + +/* ASRW indexed ?**-* */ +KONAMI_INLINE void asrw_ix( void ) +{ + PAIR t; + t.d=RM16(EAD); + CLR_NZC; + CC |= (t.d & CC_C); + t.d = (t.d & 0x8000) | (t.d >> 1); + SET_NZ16(t.d); + WM16(EAD,&t); +} + +/* ASRW extended ?**-* */ +KONAMI_INLINE void asrw_ex( void ) +{ + PAIR t; + EXTWORD(t); + CLR_NZC; + CC |= (t.d & CC_C); + t.d = (t.d & 0x8000) | (t.d >> 1); + SET_NZ16(t.d); + WM16(EAD,&t); +} + +/* ASLW direct ?**** */ +KONAMI_INLINE void aslw_di( void ) +{ + PAIR t,r; + DIRWORD(t); + r.d = t.d << 1; + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* ASLW indexed ?**** */ +KONAMI_INLINE void aslw_ix( void ) +{ + PAIR t,r; + t.d=RM16(EAD); + r.d = t.d << 1; + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* ASLW extended ?**** */ +KONAMI_INLINE void aslw_ex( void ) +{ + PAIR t,r; + EXTWORD(t); + r.d = t.d << 1; + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* ROLW direct -**** */ +KONAMI_INLINE void rolw_di( void ) +{ + PAIR t,r; + DIRWORD(t); + r.d = (CC & CC_C) | (t.d << 1); + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* ROLW indexed -**** */ +KONAMI_INLINE void rolw_ix( void ) +{ + PAIR t,r; + t.d=RM16(EAD); + r.d = (CC & CC_C) | (t.d << 1); + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* ROLW extended -**** */ +KONAMI_INLINE void rolw_ex( void ) +{ + PAIR t,r; + EXTWORD(t); + r.d = (CC & CC_C) | (t.d << 1); + CLR_NZVC; + SET_FLAGS16(t.d,t.d,r.d); + WM16(EAD,&r); +} + +/* NEGD inherent ?**** */ +KONAMI_INLINE void negd( void ) +{ + UINT32 r; + r = -D; + CLR_NZVC; + SET_FLAGS16(0,D,r); + D = r; +} + +/* NEGW direct ?**** */ +KONAMI_INLINE void negw_di( void ) +{ + PAIR r,t; + DIRWORD(t); + r.d = -t.d; + CLR_NZVC; + SET_FLAGS16(0,t.d,r.d); + WM16(EAD,&r); +} + +/* NEGW indexed ?**** */ +KONAMI_INLINE void negw_ix( void ) +{ + PAIR r,t; + t.d=RM16(EAD); + r.d = -t.d; + CLR_NZVC; + SET_FLAGS16(0,t.d,r.d); + WM16(EAD,&r); +} + +/* NEGW extended ?**** */ +KONAMI_INLINE void negw_ex( void ) +{ + PAIR r,t; + EXTWORD(t); + r.d = -t.d; + CLR_NZVC; + SET_FLAGS16(0,t.d,r.d); + WM16(EAD,&r); +} + +/* ABSA inherent ?**** */ +KONAMI_INLINE void absa( void ) +{ + UINT16 r; + if (A & 0x80) + r = -A; + else + r = A; + CLR_NZVC; + SET_FLAGS8(0,A,r); + A = r; +} + +/* ABSB inherent ?**** */ +KONAMI_INLINE void absb( void ) +{ + UINT16 r; + if (B & 0x80) + r = -B; + else + r = B; + CLR_NZVC; + SET_FLAGS8(0,B,r); + B = r; +} + +/* ABSD inherent ?**** */ +KONAMI_INLINE void absd( void ) +{ + UINT32 r; + if (D & 0x8000) + r = -D; + else + r = D; + CLR_NZVC; + SET_FLAGS16(0,D,r); + D = r; +} + +/* LSRD direct -0*-* */ +KONAMI_INLINE void lsrd_di( void ) +{ + UINT8 t; + + DIRBYTE( t ); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D >>= 1; + SET_Z16(D); + } +} + +/* RORD direct -**-* */ +KONAMI_INLINE void rord_di( void ) +{ + UINT16 r; + UINT8 t; + + DIRBYTE(t); + + while ( t-- ) { + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (D & CC_C); + r |= D >> 1; + SET_NZ16(r); + D = r; + } +} + +/* ASRD direct ?**-* */ +KONAMI_INLINE void asrd_di( void ) +{ + UINT8 t; + + DIRBYTE(t); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D = (D & 0x8000) | (D >> 1); + SET_NZ16(D); + } +} + +/* ASLD direct ?**** */ +KONAMI_INLINE void asld_di( void ) +{ + UINT32 r; + UINT8 t; + + DIRBYTE( t ); + + while ( t-- ) { + r = D << 1; + CLR_NZVC; + SET_FLAGS16(D,D,r); + D = r; + } +} + +/* ROLD direct -**-* */ +KONAMI_INLINE void rold_di( void ) +{ + UINT16 r; + UINT8 t; + + DIRBYTE(t); + + while ( t-- ) { + CLR_NZC; + if ( D & 0x8000 ) SEC; + r = CC & CC_C; + r |= D << 1; + SET_NZ16(r); + D = r; + } +} + +/* LSRD indexed -0*-* */ +KONAMI_INLINE void lsrd_ix( void ) +{ + UINT8 t; + + t=RM(EA); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D >>= 1; + SET_Z16(D); + } +} + +/* RORD indexed -**-* */ +KONAMI_INLINE void rord_ix( void ) +{ + UINT16 r; + UINT8 t; + + t=RM(EA); + + while ( t-- ) { + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (D & CC_C); + r |= D >> 1; + SET_NZ16(r); + D = r; + } +} + +/* ASRD indexed ?**-* */ +KONAMI_INLINE void asrd_ix( void ) +{ + UINT8 t; + + t=RM(EA); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D = (D & 0x8000) | (D >> 1); + SET_NZ16(D); + } +} + +/* ASLD indexed ?**** */ +KONAMI_INLINE void asld_ix( void ) +{ + UINT32 r; + UINT8 t; + + t=RM(EA); + + while ( t-- ) { + r = D << 1; + CLR_NZVC; + SET_FLAGS16(D,D,r); + D = r; + } +} + +/* ROLD indexed -**-* */ +KONAMI_INLINE void rold_ix( void ) +{ + UINT16 r; + UINT8 t; + + t=RM(EA); + + while ( t-- ) { + CLR_NZC; + if ( D & 0x8000 ) SEC; + r = CC & CC_C; + r |= D << 1; + SET_NZ16(r); + D = r; + } +} + +/* LSRD extended -0*-* */ +KONAMI_INLINE void lsrd_ex( void ) +{ + UINT8 t; + + EXTBYTE(t); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D >>= 1; + SET_Z16(D); + } +} + +/* RORD extended -**-* */ +KONAMI_INLINE void rord_ex( void ) +{ + UINT16 r; + UINT8 t; + + EXTBYTE(t); + + while ( t-- ) { + r = (CC & CC_C) << 15; + CLR_NZC; + CC |= (D & CC_C); + r |= D >> 1; + SET_NZ16(r); + D = r; + } +} + +/* ASRD extended ?**-* */ +KONAMI_INLINE void asrd_ex( void ) +{ + UINT8 t; + + EXTBYTE(t); + + while ( t-- ) { + CLR_NZC; + CC |= (D & CC_C); + D = (D & 0x8000) | (D >> 1); + SET_NZ16(D); + } +} + +/* ASLD extended ?**** */ +KONAMI_INLINE void asld_ex( void ) +{ + UINT32 r; + UINT8 t; + + EXTBYTE(t); + + while ( t-- ) { + r = D << 1; + CLR_NZVC; + SET_FLAGS16(D,D,r); + D = r; + } +} + +/* ROLD extended -**-* */ +KONAMI_INLINE void rold_ex( void ) +{ + UINT16 r; + UINT8 t; + + EXTBYTE(t); + + while ( t-- ) { + CLR_NZC; + if ( D & 0x8000 ) SEC; + r = CC & CC_C; + r |= D << 1; + SET_NZ16(r); + D = r; + } +} + +KONAMI_INLINE void opcode2( void ) +{ + UINT8 ireg2 = ROP_ARG(PCD); + PC++; + + switch ( ireg2 ) { +// case 0x00: EA=0; break; /* auto increment */ +// case 0x01: EA=0; break; /* double auto increment */ +// case 0x02: EA=0; break; /* auto decrement */ +// case 0x03: EA=0; break; /* double auto decrement */ +// case 0x04: EA=0; break; /* postbyte offs */ +// case 0x05: EA=0; break; /* postword offs */ +// case 0x06: EA=0; break; /* normal */ + case 0x07: + EAD=0; + (*konami_extended[konami.ireg])(); + konami_ICount -= 2; + return; +// case 0x08: EA=0; break; /* indirect - auto increment */ +// case 0x09: EA=0; break; /* indirect - double auto increment */ +// case 0x0a: EA=0; break; /* indirect - auto decrement */ +// case 0x0b: EA=0; break; /* indirect - double auto decrement */ +// case 0x0c: EA=0; break; /* indirect - postbyte offs */ +// case 0x0d: EA=0; break; /* indirect - postword offs */ +// case 0x0e: EA=0; break; /* indirect - normal */ + case 0x0f: /* indirect - extended */ + IMMWORD(ea); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0x10: EA=0; break; /* auto increment */ +// case 0x11: EA=0; break; /* double auto increment */ +// case 0x12: EA=0; break; /* auto decrement */ +// case 0x13: EA=0; break; /* double auto decrement */ +// case 0x14: EA=0; break; /* postbyte offs */ +// case 0x15: EA=0; break; /* postword offs */ +// case 0x16: EA=0; break; /* normal */ +// case 0x17: EA=0; break; /* extended */ +// case 0x18: EA=0; break; /* indirect - auto increment */ +// case 0x19: EA=0; break; /* indirect - double auto increment */ +// case 0x1a: EA=0; break; /* indirect - auto decrement */ +// case 0x1b: EA=0; break; /* indirect - double auto decrement */ +// case 0x1c: EA=0; break; /* indirect - postbyte offs */ +// case 0x1d: EA=0; break; /* indirect - postword offs */ +// case 0x1e: EA=0; break; /* indirect - normal */ +// case 0x1f: EA=0; break; /* indirect - extended */ + +/* base X */ + case 0x20: /* auto increment */ + EA=X; + X++; + konami_ICount-=2; + break; + case 0x21: /* double auto increment */ + EA=X; + X+=2; + konami_ICount-=3; + break; + case 0x22: /* auto decrement */ + X--; + EA=X; + konami_ICount-=2; + break; + case 0x23: /* double auto decrement */ + X-=2; + EA=X; + konami_ICount-=3; + break; + case 0x24: /* postbyte offs */ + IMMBYTE(EA); + EA=X+SIGNED(EA); + konami_ICount-=2; + break; + case 0x25: /* postword offs */ + IMMWORD(ea); + EA+=X; + konami_ICount-=4; + break; + case 0x26: /* normal */ + EA=X; + break; +// case 0x27: EA=0; break; /* extended */ + case 0x28: /* indirect - auto increment */ + EA=X; + X++; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x29: /* indirect - double auto increment */ + EA=X; + X+=2; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x2a: /* indirect - auto decrement */ + X--; + EA=X; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x2b: /* indirect - double auto decrement */ + X-=2; + EA=X; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x2c: /* indirect - postbyte offs */ + IMMBYTE(EA); + EA=X+SIGNED(EA); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0x2d: /* indirect - postword offs */ + IMMWORD(ea); + EA+=X; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0x2e: /* indirect - normal */ + EA=X; + EA=RM16(EAD); + konami_ICount-=3; + break; +// case 0x2f: EA=0; break; /* indirect - extended */ + +/* base Y */ + case 0x30: /* auto increment */ + EA=Y; + Y++; + konami_ICount-=2; + break; + case 0x31: /* double auto increment */ + EA=Y; + Y+=2; + konami_ICount-=3; + break; + case 0x32: /* auto decrement */ + Y--; + EA=Y; + konami_ICount-=2; + break; + case 0x33: /* double auto decrement */ + Y-=2; + EA=Y; + konami_ICount-=3; + break; + case 0x34: /* postbyte offs */ + IMMBYTE(EA); + EA=Y+SIGNED(EA); + konami_ICount-=2; + break; + case 0x35: /* postword offs */ + IMMWORD(ea); + EA+=Y; + konami_ICount-=4; + break; + case 0x36: /* normal */ + EA=Y; + break; +// case 0x37: EA=0; break; /* extended */ + case 0x38: /* indirect - auto increment */ + EA=Y; + Y++; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x39: /* indirect - double auto increment */ + EA=Y; + Y+=2; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x3a: /* indirect - auto decrement */ + Y--; + EA=Y; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x3b: /* indirect - double auto decrement */ + Y-=2; + EA=Y; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x3c: /* indirect - postbyte offs */ + IMMBYTE(EA); + EA=Y+SIGNED(EA); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0x3d: /* indirect - postword offs */ + IMMWORD(ea); + EA+=Y; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0x3e: /* indirect - normal */ + EA=Y; + EA=RM16(EAD); + konami_ICount-=3; + break; +// case 0x3f: EA=0; break; /* indirect - extended */ + +// case 0x40: EA=0; break; /* auto increment */ +// case 0x41: EA=0; break; /* double auto increment */ +// case 0x42: EA=0; break; /* auto decrement */ +// case 0x43: EA=0; break; /* double auto decrement */ +// case 0x44: EA=0; break; /* postbyte offs */ +// case 0x45: EA=0; break; /* postword offs */ +// case 0x46: EA=0; break; /* normal */ +// case 0x47: EA=0; break; /* extended */ +// case 0x48: EA=0; break; /* indirect - auto increment */ +// case 0x49: EA=0; break; /* indirect - double auto increment */ +// case 0x4a: EA=0; break; /* indirect - auto decrement */ +// case 0x4b: EA=0; break; /* indirect - double auto decrement */ +// case 0x4c: EA=0; break; /* indirect - postbyte offs */ +// case 0x4d: EA=0; break; /* indirect - postword offs */ +// case 0x4e: EA=0; break; /* indirect - normal */ +// case 0x4f: EA=0; break; /* indirect - extended */ + +/* base U */ + case 0x50: /* auto increment */ + EA=U; + U++; + konami_ICount-=2; + break; + case 0x51: /* double auto increment */ + EA=U; + U+=2; + konami_ICount-=3; + break; + case 0x52: /* auto decrement */ + U--; + EA=U; + konami_ICount-=2; + break; + case 0x53: /* double auto decrement */ + U-=2; + EA=U; + konami_ICount-=3; + break; + case 0x54: /* postbyte offs */ + IMMBYTE(EA); + EA=U+SIGNED(EA); + konami_ICount-=2; + break; + case 0x55: /* postword offs */ + IMMWORD(ea); + EA+=U; + konami_ICount-=4; + break; + case 0x56: /* normal */ + EA=U; + break; +// case 0x57: EA=0; break; /* extended */ + case 0x58: /* indirect - auto increment */ + EA=U; + U++; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x59: /* indirect - double auto increment */ + EA=U; + U+=2; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x5a: /* indirect - auto decrement */ + U--; + EA=U; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x5b: /* indirect - double auto decrement */ + U-=2; + EA=U; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x5c: /* indirect - postbyte offs */ + IMMBYTE(EA); + EA=U+SIGNED(EA); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0x5d: /* indirect - postword offs */ + IMMWORD(ea); + EA+=U; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0x5e: /* indirect - normal */ + EA=U; + EA=RM16(EAD); + konami_ICount-=3; + break; +// case 0x5f: EA=0; break; /* indirect - extended */ + +/* base S */ + case 0x60: /* auto increment */ + EAD=SD; + S++; + konami_ICount-=2; + break; + case 0x61: /* double auto increment */ + EAD=SD; + S+=2; + konami_ICount-=3; + break; + case 0x62: /* auto decrement */ + S--; + EAD=SD; + konami_ICount-=2; + break; + case 0x63: /* double auto decrement */ + S-=2; + EAD=SD; + konami_ICount-=3; + break; + case 0x64: /* postbyte offs */ + IMMBYTE(EA); + EA=S+SIGNED(EA); + konami_ICount-=2; + break; + case 0x65: /* postword offs */ + IMMWORD(ea); + EA+=S; + konami_ICount-=4; + break; + case 0x66: /* normal */ + EAD=SD; + break; +// case 0x67: EA=0; break; /* extended */ + case 0x68: /* indirect - auto increment */ + EAD=SD; + S++; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x69: /* indirect - double auto increment */ + EAD=SD; + S+=2; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x6a: /* indirect - auto decrement */ + S--; + EAD=SD; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x6b: /* indirect - double auto decrement */ + S-=2; + EAD=SD; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x6c: /* indirect - postbyte offs */ + IMMBYTE(EA); + EA=S+SIGNED(EA); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0x6d: /* indirect - postword offs */ + IMMWORD(ea); + EA+=S; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0x6e: /* indirect - normal */ + EAD=SD; + EA=RM16(EAD); + konami_ICount-=3; + break; +// case 0x6f: EA=0; break; /* indirect - extended */ + +/* base PC */ + case 0x70: /* auto increment */ + EAD=PCD; + PC++; + konami_ICount-=2; + break; + case 0x71: /* double auto increment */ + EAD=PCD; + PC+=2; + konami_ICount-=3; + break; + case 0x72: /* auto decrement */ + PC--; + EAD=PCD; + konami_ICount-=2; + break; + case 0x73: /* double auto decrement */ + PC-=2; + EAD=PCD; + konami_ICount-=3; + break; + case 0x74: /* postbyte offs */ + IMMBYTE(EA); + EA=PC-1+SIGNED(EA); + konami_ICount-=2; + break; + case 0x75: /* postword offs */ + IMMWORD(ea); + EA+=PC-2; + konami_ICount-=4; + break; + case 0x76: /* normal */ + EAD=PCD; + break; +// case 0x77: EA=0; break; /* extended */ + case 0x78: /* indirect - auto increment */ + EAD=PCD; + PC++; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x79: /* indirect - double auto increment */ + EAD=PCD; + PC+=2; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x7a: /* indirect - auto decrement */ + PC--; + EAD=PCD; + EA=RM16(EAD); + konami_ICount-=5; + break; + case 0x7b: /* indirect - double auto decrement */ + PC-=2; + EAD=PCD; + EA=RM16(EAD); + konami_ICount-=6; + break; + case 0x7c: /* indirect - postbyte offs */ + IMMBYTE(EA); + EA=PC-1+SIGNED(EA); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0x7d: /* indirect - postword offs */ + IMMWORD(ea); + EA+=PC-2; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0x7e: /* indirect - normal */ + EAD=PCD; + EA=RM16(EAD); + konami_ICount-=3; + break; +// case 0x7f: EA=0; break; /* indirect - extended */ + +// case 0x80: EA=0; break; /* register a */ +// case 0x81: EA=0; break; /* register b */ +// case 0x82: EA=0; break; /* ???? */ +// case 0x83: EA=0; break; /* ???? */ +// case 0x84: EA=0; break; /* ???? */ +// case 0x85: EA=0; break; /* ???? */ +// case 0x86: EA=0; break; /* ???? */ +// case 0x87: EA=0; break; /* register d */ +// case 0x88: EA=0; break; /* indirect - register a */ +// case 0x89: EA=0; break; /* indirect - register b */ +// case 0x8a: EA=0; break; /* indirect - ???? */ +// case 0x8b: EA=0; break; /* indirect - ???? */ +// case 0x8c: EA=0; break; /* indirect - ???? */ +// case 0x8d: EA=0; break; /* indirect - ???? */ +// case 0x8e: EA=0; break; /* indirect - register d */ +// case 0x8f: EA=0; break; /* indirect - ???? */ +// case 0x90: EA=0; break; /* register a */ +// case 0x91: EA=0; break; /* register b */ +// case 0x92: EA=0; break; /* ???? */ +// case 0x93: EA=0; break; /* ???? */ +// case 0x94: EA=0; break; /* ???? */ +// case 0x95: EA=0; break; /* ???? */ +// case 0x96: EA=0; break; /* ???? */ +// case 0x97: EA=0; break; /* register d */ +// case 0x98: EA=0; break; /* indirect - register a */ +// case 0x99: EA=0; break; /* indirect - register b */ +// case 0x9a: EA=0; break; /* indirect - ???? */ +// case 0x9b: EA=0; break; /* indirect - ???? */ +// case 0x9c: EA=0; break; /* indirect - ???? */ +// case 0x9d: EA=0; break; /* indirect - ???? */ +// case 0x9e: EA=0; break; /* indirect - register d */ +// case 0x9f: EA=0; break; /* indirect - ???? */ + case 0xa0: /* register a */ + EA=X+SIGNED(A); + konami_ICount-=1; + break; + case 0xa1: /* register b */ + EA=X+SIGNED(B); + konami_ICount-=1; + break; +// case 0xa2: EA=0; break; /* ???? */ +// case 0xa3: EA=0; break; /* ???? */ +// case 0xa4: EA=0; break; /* ???? */ +// case 0xa5: EA=0; break; /* ???? */ +// case 0xa6: EA=0; break; /* ???? */ + case 0xa7: /* register d */ + EA=X+D; + konami_ICount-=4; + break; + case 0xa8: /* indirect - register a */ + EA=X+SIGNED(A); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0xa9: /* indirect - register b */ + EA=X+SIGNED(B); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0xaa: EA=0; break; /* indirect - ???? */ +// case 0xab: EA=0; break; /* indirect - ???? */ +// case 0xac: EA=0; break; /* indirect - ???? */ +// case 0xad: EA=0; break; /* indirect - ???? */ +// case 0xae: EA=0; break; /* indirect - ???? */ + case 0xaf: /* indirect - register d */ + EA=X+D; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0xb0: /* register a */ + EA=Y+SIGNED(A); + konami_ICount-=1; + break; + case 0xb1: /* register b */ + EA=Y+SIGNED(B); + konami_ICount-=1; + break; +// case 0xb2: EA=0; break; /* ???? */ +// case 0xb3: EA=0; break; /* ???? */ +// case 0xb4: EA=0; break; /* ???? */ +// case 0xb5: EA=0; break; /* ???? */ +// case 0xb6: EA=0; break; /* ???? */ + case 0xb7: /* register d */ + EA=Y+D; + konami_ICount-=4; + break; + case 0xb8: /* indirect - register a */ + EA=Y+SIGNED(A); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0xb9: /* indirect - register b */ + EA=Y+SIGNED(B); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0xba: EA=0; break; /* indirect - ???? */ +// case 0xbb: EA=0; break; /* indirect - ???? */ +// case 0xbc: EA=0; break; /* indirect - ???? */ +// case 0xbd: EA=0; break; /* indirect - ???? */ +// case 0xbe: EA=0; break; /* indirect - ???? */ + case 0xbf: /* indirect - register d */ + EA=Y+D; + EA=RM16(EAD); + konami_ICount-=7; + break; +// case 0xc0: EA=0; break; /* register a */ +// case 0xc1: EA=0; break; /* register b */ +// case 0xc2: EA=0; break; /* ???? */ +// case 0xc3: EA=0; break; /* ???? */ + case 0xc4: + EAD=0; + (*konami_direct[konami.ireg])(); + konami_ICount -= 1; + return; +// case 0xc5: EA=0; break; /* ???? */ +// case 0xc6: EA=0; break; /* ???? */ +// case 0xc7: EA=0; break; /* register d */ +// case 0xc8: EA=0; break; /* indirect - register a */ +// case 0xc9: EA=0; break; /* indirect - register b */ +// case 0xca: EA=0; break; /* indirect - ???? */ +// case 0xcb: EA=0; break; /* indirect - ???? */ + case 0xcc: /* indirect - direct */ + DIRWORD(ea); + konami_ICount-=4; + break; +// case 0xcd: EA=0; break; /* indirect - ???? */ +// case 0xce: EA=0; break; /* indirect - register d */ +// case 0xcf: EA=0; break; /* indirect - ???? */ + case 0xd0: /* register a */ + EA=U+SIGNED(A); + konami_ICount-=1; + break; + case 0xd1: /* register b */ + EA=U+SIGNED(B); + konami_ICount-=1; + break; +// case 0xd2: EA=0; break; /* ???? */ +// case 0xd3: EA=0; break; /* ???? */ +// case 0xd4: EA=0; break; /* ???? */ +// case 0xd5: EA=0; break; /* ???? */ +// case 0xd6: EA=0; break; /* ???? */ + case 0xd7: /* register d */ + EA=U+D; + konami_ICount-=4; + break; + case 0xd8: /* indirect - register a */ + EA=U+SIGNED(A); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0xd9: /* indirect - register b */ + EA=U+SIGNED(B); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0xda: EA=0; break; /* indirect - ???? */ +// case 0xdb: EA=0; break; /* indirect - ???? */ +// case 0xdc: EA=0; break; /* indirect - ???? */ +// case 0xdd: EA=0; break; /* indirect - ???? */ +// case 0xde: EA=0; break; /* indirect - ???? */ + case 0xdf: /* indirect - register d */ + EA=U+D; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0xe0: /* register a */ + EA=S+SIGNED(A); + konami_ICount-=1; + break; + case 0xe1: /* register b */ + EA=S+SIGNED(B); + konami_ICount-=1; + break; +// case 0xe2: EA=0; break; /* ???? */ +// case 0xe3: EA=0; break; /* ???? */ +// case 0xe4: EA=0; break; /* ???? */ +// case 0xe5: EA=0; break; /* ???? */ +// case 0xe6: EA=0; break; /* ???? */ + case 0xe7: /* register d */ + EA=S+D; + konami_ICount-=4; + break; + case 0xe8: /* indirect - register a */ + EA=S+SIGNED(A); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0xe9: /* indirect - register b */ + EA=S+SIGNED(B); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0xea: EA=0; break; /* indirect - ???? */ +// case 0xeb: EA=0; break; /* indirect - ???? */ +// case 0xec: EA=0; break; /* indirect - ???? */ +// case 0xed: EA=0; break; /* indirect - ???? */ +// case 0xee: EA=0; break; /* indirect - ???? */ + case 0xef: /* indirect - register d */ + EA=S+D; + EA=RM16(EAD); + konami_ICount-=7; + break; + case 0xf0: /* register a */ + EA=PC+SIGNED(A); + konami_ICount-=1; + break; + case 0xf1: /* register b */ + EA=PC+SIGNED(B); + konami_ICount-=1; + break; +// case 0xf2: EA=0; break; /* ???? */ +// case 0xf3: EA=0; break; /* ???? */ +// case 0xf4: EA=0; break; /* ???? */ +// case 0xf5: EA=0; break; /* ???? */ +// case 0xf6: EA=0; break; /* ???? */ + case 0xf7: /* register d */ + EA=PC+D; + konami_ICount-=4; + break; + case 0xf8: /* indirect - register a */ + EA=PC+SIGNED(A); + EA=RM16(EAD); + konami_ICount-=4; + break; + case 0xf9: /* indirect - register b */ + EA=PC+SIGNED(B); + EA=RM16(EAD); + konami_ICount-=4; + break; +// case 0xfa: EA=0; break; /* indirect - ???? */ +// case 0xfb: EA=0; break; /* indirect - ???? */ +// case 0xfc: EA=0; break; /* indirect - ???? */ +// case 0xfd: EA=0; break; /* indirect - ???? */ +// case 0xfe: EA=0; break; /* indirect - ???? */ + case 0xff: /* indirect - register d */ + EA=PC+D; + EA=RM16(EAD); + konami_ICount-=7; + break; + default: + logerror("KONAMI: Unknown/Invalid postbyte at PC = %04x\n", PC -1 ); + EAD = 0; + } + (*konami_indexed[konami.ireg])(); +} diff --git a/src/cpu/konami/konamtbl.c b/src/cpu/konami/konamtbl.c new file mode 100644 index 00000000..3b9e1177 --- /dev/null +++ b/src/cpu/konami/konamtbl.c @@ -0,0 +1,491 @@ +KONAMI_INLINE void abx(void); +KONAMI_INLINE void adca_di(void); +KONAMI_INLINE void adca_ex(void); +KONAMI_INLINE void adca_im(void); +KONAMI_INLINE void adca_ix(void); +KONAMI_INLINE void adcb_di(void); +KONAMI_INLINE void adcb_ex(void); +KONAMI_INLINE void adcb_im(void); +KONAMI_INLINE void adcb_ix(void); +KONAMI_INLINE void adda_di(void); +KONAMI_INLINE void adda_ex(void); +KONAMI_INLINE void adda_im(void); +KONAMI_INLINE void adda_ix(void); +KONAMI_INLINE void addb_di(void); +KONAMI_INLINE void addb_ex(void); +KONAMI_INLINE void addb_im(void); +KONAMI_INLINE void addb_ix(void); +KONAMI_INLINE void addd_di(void); +KONAMI_INLINE void addd_ex(void); +KONAMI_INLINE void addd_im(void); +KONAMI_INLINE void addd_ix(void); +KONAMI_INLINE void anda_di(void); +KONAMI_INLINE void anda_ex(void); +KONAMI_INLINE void anda_im(void); +KONAMI_INLINE void anda_ix(void); +KONAMI_INLINE void andb_di(void); +KONAMI_INLINE void andb_ex(void); +KONAMI_INLINE void andb_im(void); +KONAMI_INLINE void andb_ix(void); +KONAMI_INLINE void andcc(void); +KONAMI_INLINE void asl_di(void); +KONAMI_INLINE void asl_ex(void); +KONAMI_INLINE void asl_ix(void); +KONAMI_INLINE void asla(void); +KONAMI_INLINE void aslb(void); +KONAMI_INLINE void asr_di(void); +KONAMI_INLINE void asr_ex(void); +KONAMI_INLINE void asr_ix(void); +KONAMI_INLINE void asra(void); +KONAMI_INLINE void asrb(void); +KONAMI_INLINE void bcc(void); +KONAMI_INLINE void bcs(void); +KONAMI_INLINE void beq(void); +KONAMI_INLINE void bge(void); +KONAMI_INLINE void bgt(void); +KONAMI_INLINE void bhi(void); +KONAMI_INLINE void bita_di(void); +KONAMI_INLINE void bita_ex(void); +KONAMI_INLINE void bita_im(void); +KONAMI_INLINE void bita_ix(void); +KONAMI_INLINE void bitb_di(void); +KONAMI_INLINE void bitb_ex(void); +KONAMI_INLINE void bitb_im(void); +KONAMI_INLINE void bitb_ix(void); +KONAMI_INLINE void ble(void); +KONAMI_INLINE void bls(void); +KONAMI_INLINE void blt(void); +KONAMI_INLINE void bmi(void); +KONAMI_INLINE void bne(void); +KONAMI_INLINE void bpl(void); +KONAMI_INLINE void bra(void); +KONAMI_INLINE void brn(void); +KONAMI_INLINE void bsr(void); +KONAMI_INLINE void bvc(void); +KONAMI_INLINE void bvs(void); +KONAMI_INLINE void clr_di(void); +KONAMI_INLINE void clr_ex(void); +KONAMI_INLINE void clr_ix(void); +KONAMI_INLINE void clra(void); +KONAMI_INLINE void clrb(void); +KONAMI_INLINE void cmpa_di(void); +KONAMI_INLINE void cmpa_ex(void); +KONAMI_INLINE void cmpa_im(void); +KONAMI_INLINE void cmpa_ix(void); +KONAMI_INLINE void cmpb_di(void); +KONAMI_INLINE void cmpb_ex(void); +KONAMI_INLINE void cmpb_im(void); +KONAMI_INLINE void cmpb_ix(void); +KONAMI_INLINE void cmpd_di(void); +KONAMI_INLINE void cmpd_ex(void); +KONAMI_INLINE void cmpd_im(void); +KONAMI_INLINE void cmpd_ix(void); +KONAMI_INLINE void cmps_di(void); +KONAMI_INLINE void cmps_ex(void); +KONAMI_INLINE void cmps_im(void); +KONAMI_INLINE void cmps_ix(void); +KONAMI_INLINE void cmpu_di(void); +KONAMI_INLINE void cmpu_ex(void); +KONAMI_INLINE void cmpu_im(void); +KONAMI_INLINE void cmpu_ix(void); +KONAMI_INLINE void cmpx_di(void); +KONAMI_INLINE void cmpx_ex(void); +KONAMI_INLINE void cmpx_im(void); +KONAMI_INLINE void cmpx_ix(void); +KONAMI_INLINE void cmpy_di(void); +KONAMI_INLINE void cmpy_ex(void); +KONAMI_INLINE void cmpy_im(void); +KONAMI_INLINE void cmpy_ix(void); +KONAMI_INLINE void com_di(void); +KONAMI_INLINE void com_ex(void); +KONAMI_INLINE void com_ix(void); +KONAMI_INLINE void coma(void); +KONAMI_INLINE void comb(void); +KONAMI_INLINE void cwai(void); +KONAMI_INLINE void daa(void); +KONAMI_INLINE void dec_di(void); +KONAMI_INLINE void dec_ex(void); +KONAMI_INLINE void dec_ix(void); +KONAMI_INLINE void deca(void); +KONAMI_INLINE void decb(void); +KONAMI_INLINE void eora_di(void); +KONAMI_INLINE void eora_ex(void); +KONAMI_INLINE void eora_im(void); +KONAMI_INLINE void eora_ix(void); +KONAMI_INLINE void eorb_di(void); +KONAMI_INLINE void eorb_ex(void); +KONAMI_INLINE void eorb_im(void); +KONAMI_INLINE void eorb_ix(void); +KONAMI_INLINE void exg(void); +KONAMI_INLINE void illegal(void); +KONAMI_INLINE void inc_di(void); +KONAMI_INLINE void inc_ex(void); +KONAMI_INLINE void inc_ix(void); +KONAMI_INLINE void inca(void); +KONAMI_INLINE void incb(void); +KONAMI_INLINE void jmp_di(void); +KONAMI_INLINE void jmp_ex(void); +KONAMI_INLINE void jmp_ix(void); +KONAMI_INLINE void jsr_di(void); +KONAMI_INLINE void jsr_ex(void); +KONAMI_INLINE void jsr_ix(void); +KONAMI_INLINE void lbcc(void); +KONAMI_INLINE void lbcs(void); +KONAMI_INLINE void lbeq(void); +KONAMI_INLINE void lbge(void); +KONAMI_INLINE void lbgt(void); +KONAMI_INLINE void lbhi(void); +KONAMI_INLINE void lble(void); +KONAMI_INLINE void lbls(void); +KONAMI_INLINE void lblt(void); +KONAMI_INLINE void lbmi(void); +KONAMI_INLINE void lbne(void); +KONAMI_INLINE void lbpl(void); +KONAMI_INLINE void lbra(void); +KONAMI_INLINE void lbrn(void); +KONAMI_INLINE void lbsr(void); +KONAMI_INLINE void lbvc(void); +KONAMI_INLINE void lbvs(void); +KONAMI_INLINE void lda_di(void); +KONAMI_INLINE void lda_ex(void); +KONAMI_INLINE void lda_im(void); +KONAMI_INLINE void lda_ix(void); +KONAMI_INLINE void ldb_di(void); +KONAMI_INLINE void ldb_ex(void); +KONAMI_INLINE void ldb_im(void); +KONAMI_INLINE void ldb_ix(void); +KONAMI_INLINE void ldd_di(void); +KONAMI_INLINE void ldd_ex(void); +KONAMI_INLINE void ldd_im(void); +KONAMI_INLINE void ldd_ix(void); +KONAMI_INLINE void lds_di(void); +KONAMI_INLINE void lds_ex(void); +KONAMI_INLINE void lds_im(void); +KONAMI_INLINE void lds_ix(void); +KONAMI_INLINE void ldu_di(void); +KONAMI_INLINE void ldu_ex(void); +KONAMI_INLINE void ldu_im(void); +KONAMI_INLINE void ldu_ix(void); +KONAMI_INLINE void ldx_di(void); +KONAMI_INLINE void ldx_ex(void); +KONAMI_INLINE void ldx_im(void); +KONAMI_INLINE void ldx_ix(void); +KONAMI_INLINE void ldy_di(void); +KONAMI_INLINE void ldy_ex(void); +KONAMI_INLINE void ldy_im(void); +KONAMI_INLINE void ldy_ix(void); +KONAMI_INLINE void leas(void); +KONAMI_INLINE void leau(void); +KONAMI_INLINE void leax(void); +KONAMI_INLINE void leay(void); +KONAMI_INLINE void lsr_di(void); +KONAMI_INLINE void lsr_ex(void); +KONAMI_INLINE void lsr_ix(void); +KONAMI_INLINE void lsra(void); +KONAMI_INLINE void lsrb(void); +KONAMI_INLINE void mul(void); +KONAMI_INLINE void neg_di(void); +KONAMI_INLINE void neg_ex(void); +KONAMI_INLINE void neg_ix(void); +KONAMI_INLINE void nega(void); +KONAMI_INLINE void negb(void); +KONAMI_INLINE void nop(void); +KONAMI_INLINE void ora_di(void); +KONAMI_INLINE void ora_ex(void); +KONAMI_INLINE void ora_im(void); +KONAMI_INLINE void ora_ix(void); +KONAMI_INLINE void orb_di(void); +KONAMI_INLINE void orb_ex(void); +KONAMI_INLINE void orb_im(void); +KONAMI_INLINE void orb_ix(void); +KONAMI_INLINE void orcc(void); +KONAMI_INLINE void pshs(void); +KONAMI_INLINE void pshu(void); +KONAMI_INLINE void puls(void); +KONAMI_INLINE void pulu(void); +KONAMI_INLINE void rol_di(void); +KONAMI_INLINE void rol_ex(void); +KONAMI_INLINE void rol_ix(void); +KONAMI_INLINE void rola(void); +KONAMI_INLINE void rolb(void); +KONAMI_INLINE void ror_di(void); +KONAMI_INLINE void ror_ex(void); +KONAMI_INLINE void ror_ix(void); +KONAMI_INLINE void rora(void); +KONAMI_INLINE void rorb(void); +KONAMI_INLINE void rti(void); +KONAMI_INLINE void rts(void); +KONAMI_INLINE void sbca_di(void); +KONAMI_INLINE void sbca_ex(void); +KONAMI_INLINE void sbca_im(void); +KONAMI_INLINE void sbca_ix(void); +KONAMI_INLINE void sbcb_di(void); +KONAMI_INLINE void sbcb_ex(void); +KONAMI_INLINE void sbcb_im(void); +KONAMI_INLINE void sbcb_ix(void); +KONAMI_INLINE void sex(void); +KONAMI_INLINE void sta_di(void); +KONAMI_INLINE void sta_ex(void); +KONAMI_INLINE void sta_im(void); +KONAMI_INLINE void sta_ix(void); +KONAMI_INLINE void stb_di(void); +KONAMI_INLINE void stb_ex(void); +KONAMI_INLINE void stb_im(void); +KONAMI_INLINE void stb_ix(void); +KONAMI_INLINE void std_di(void); +KONAMI_INLINE void std_ex(void); +KONAMI_INLINE void std_im(void); +KONAMI_INLINE void std_ix(void); +KONAMI_INLINE void sts_di(void); +KONAMI_INLINE void sts_ex(void); +KONAMI_INLINE void sts_im(void); +KONAMI_INLINE void sts_ix(void); +KONAMI_INLINE void stu_di(void); +KONAMI_INLINE void stu_ex(void); +KONAMI_INLINE void stu_im(void); +KONAMI_INLINE void stu_ix(void); +KONAMI_INLINE void stx_di(void); +KONAMI_INLINE void stx_ex(void); +KONAMI_INLINE void stx_im(void); +KONAMI_INLINE void stx_ix(void); +KONAMI_INLINE void sty_di(void); +KONAMI_INLINE void sty_ex(void); +KONAMI_INLINE void sty_im(void); +KONAMI_INLINE void sty_ix(void); +KONAMI_INLINE void suba_di(void); +KONAMI_INLINE void suba_ex(void); +KONAMI_INLINE void suba_im(void); +KONAMI_INLINE void suba_ix(void); +KONAMI_INLINE void subb_di(void); +KONAMI_INLINE void subb_ex(void); +KONAMI_INLINE void subb_im(void); +KONAMI_INLINE void subb_ix(void); +KONAMI_INLINE void subd_di(void); +KONAMI_INLINE void subd_ex(void); +KONAMI_INLINE void subd_im(void); +KONAMI_INLINE void subd_ix(void); +KONAMI_INLINE void swi(void); +KONAMI_INLINE void swi2(void); +KONAMI_INLINE void swi3(void); +KONAMI_INLINE void sync(void); +KONAMI_INLINE void tfr(void); +KONAMI_INLINE void tst_di(void); +KONAMI_INLINE void tst_ex(void); +KONAMI_INLINE void tst_ix(void); +KONAMI_INLINE void tsta(void); +KONAMI_INLINE void tstb(void); + +KONAMI_INLINE void clrd(void); /* 6309 */ +KONAMI_INLINE void clrw_ix(void); /* 6309 ? */ +KONAMI_INLINE void clrw_di(void); /* 6309 ? */ +KONAMI_INLINE void clrw_ex(void); /* 6309 ? */ +KONAMI_INLINE void negd(void); +KONAMI_INLINE void negw_ix(void); /* 6309 ? */ +KONAMI_INLINE void negw_di(void); /* 6309 ? */ +KONAMI_INLINE void negw_ex(void); /* 6309 ? */ +KONAMI_INLINE void lsrd( void ); /* 6309 */ +KONAMI_INLINE void lsrd_di( void ); /* 6309 */ +KONAMI_INLINE void lsrd_ix( void ); /* 6309 */ +KONAMI_INLINE void lsrd_ex( void ); /* 6309 */ +KONAMI_INLINE void rord( void ); /* 6309 ? */ +KONAMI_INLINE void rord_di( void ); /* 6309 */ +KONAMI_INLINE void rord_ix( void ); /* 6309 */ +KONAMI_INLINE void rord_ex( void ); /* 6309 */ +KONAMI_INLINE void asrd( void ); /* 6309 ? */ +KONAMI_INLINE void asrd_di( void ); /* 6309 */ +KONAMI_INLINE void asrd_ix( void ); /* 6309 */ +KONAMI_INLINE void asrd_ex( void ); /* 6309 */ +KONAMI_INLINE void asld( void ); /* 6309 */ +KONAMI_INLINE void asld_di( void ); /* 6309 */ +KONAMI_INLINE void asld_ix( void ); /* 6309 */ +KONAMI_INLINE void asld_ex( void ); /* 6309 */ +KONAMI_INLINE void rold( void ); /* 6309 ? */ +KONAMI_INLINE void rold_di( void ); /* 6309 */ +KONAMI_INLINE void rold_ix( void ); /* 6309 */ +KONAMI_INLINE void rold_ex( void ); /* 6309 */ +KONAMI_INLINE void tstd(void); +KONAMI_INLINE void tstw_di( void ); +KONAMI_INLINE void tstw_ix( void ); +KONAMI_INLINE void tstw_ex( void ); + +/* Custom opcodes */ +KONAMI_INLINE void setline_im( void ); +KONAMI_INLINE void setline_ix( void ); +KONAMI_INLINE void setline_di( void ); +KONAMI_INLINE void setline_ex( void ); +KONAMI_INLINE void bmove( void ); +KONAMI_INLINE void move( void ); +KONAMI_INLINE void decbjnz( void ); +KONAMI_INLINE void decxjnz( void ); +KONAMI_INLINE void bset( void ); +KONAMI_INLINE void bset2( void ); +KONAMI_INLINE void lmul(void); +KONAMI_INLINE void divx( void ); +KONAMI_INLINE void incd( void ); +KONAMI_INLINE void incw_di( void ); +KONAMI_INLINE void incw_ix( void ); +KONAMI_INLINE void incw_ex( void ); +KONAMI_INLINE void decd( void ); +KONAMI_INLINE void decw_di( void ); +KONAMI_INLINE void decw_ix( void ); +KONAMI_INLINE void decw_ex( void ); +KONAMI_INLINE void lsrw_di( void ); +KONAMI_INLINE void lsrw_ix( void ); +KONAMI_INLINE void lsrw_ex( void ); +KONAMI_INLINE void rorw_di( void ); +KONAMI_INLINE void rorw_ix( void ); +KONAMI_INLINE void rorw_ex( void ); +KONAMI_INLINE void asrw_di( void ); +KONAMI_INLINE void asrw_ix( void ); +KONAMI_INLINE void asrw_ex( void ); +KONAMI_INLINE void aslw_di( void ); +KONAMI_INLINE void aslw_ix( void ); +KONAMI_INLINE void aslw_ex( void ); +KONAMI_INLINE void rolw_di( void ); +KONAMI_INLINE void rolw_ix( void ); +KONAMI_INLINE void rolw_ex( void ); +KONAMI_INLINE void absa( void ); +KONAMI_INLINE void absb( void ); +KONAMI_INLINE void absd( void ); + +KONAMI_INLINE void opcode2( void ); + +static void (*const konami_main[0x100])(void) = { + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */ + opcode2,opcode2,opcode2,opcode2,pshs ,pshu ,puls ,pulu , + lda_im ,ldb_im ,opcode2,opcode2,adda_im,addb_im,opcode2,opcode2, /* 10 */ + adca_im,adcb_im,opcode2,opcode2,suba_im,subb_im,opcode2,opcode2, + sbca_im,sbcb_im,opcode2,opcode2,anda_im,andb_im,opcode2,opcode2, /* 20 */ + bita_im,bitb_im,opcode2,opcode2,eora_im,eorb_im,opcode2,opcode2, + ora_im ,orb_im ,opcode2,opcode2,cmpa_im,cmpb_im,opcode2,opcode2, /* 30 */ + setline_im,opcode2,opcode2,opcode2,andcc,orcc ,exg ,tfr , + ldd_im ,opcode2,ldx_im ,opcode2,ldy_im ,opcode2,ldu_im ,opcode2, /* 40 */ + lds_im ,opcode2,cmpd_im,opcode2,cmpx_im,opcode2,cmpy_im,opcode2, + cmpu_im,opcode2,cmps_im,opcode2,addd_im,opcode2,subd_im,opcode2, /* 50 */ + opcode2,opcode2,opcode2,opcode2,opcode2,illegal,illegal,illegal, + bra ,bhi ,bcc ,bne ,bvc ,bpl ,bge ,bgt , /* 60 */ + lbra ,lbhi ,lbcc ,lbne ,lbvc ,lbpl ,lbge ,lbgt , + brn ,bls ,bcs ,beq ,bvs ,bmi ,blt ,ble , /* 70 */ + lbrn ,lbls ,lbcs ,lbeq ,lbvs ,lbmi ,lblt ,lble , + clra ,clrb ,opcode2,coma ,comb ,opcode2,nega ,negb , /* 80 */ + opcode2,inca ,incb ,opcode2,deca ,decb ,opcode2,rts , + tsta ,tstb ,opcode2,lsra ,lsrb ,opcode2,rora ,rorb , /* 90 */ + opcode2,asra ,asrb ,opcode2,asla ,aslb ,opcode2,rti , + rola ,rolb ,opcode2,opcode2,opcode2,opcode2,opcode2,opcode2, /* a0 */ + opcode2,opcode2,bsr ,lbsr ,decbjnz,decxjnz,nop ,illegal, + abx ,daa ,sex ,mul ,lmul ,divx ,bmove ,move , /* b0 */ + lsrd ,opcode2,rord ,opcode2,asrd ,opcode2,asld ,opcode2, + rold ,opcode2,clrd ,opcode2,negd ,opcode2,incd ,opcode2, /* c0 */ + decd ,opcode2,tstd ,opcode2,absa ,absb ,absd ,bset , + bset2 ,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal +}; + +static void (*const konami_indexed[0x100])(void) = { + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */ + leax ,leay ,leau ,leas ,illegal,illegal,illegal,illegal, + illegal,illegal,lda_ix ,ldb_ix ,illegal,illegal,adda_ix,addb_ix, /* 10 */ + illegal,illegal,adca_ix,adcb_ix,illegal,illegal,suba_ix,subb_ix, + illegal,illegal,sbca_ix,sbcb_ix,illegal,illegal,anda_ix,andb_ix, /* 20 */ + illegal,illegal,bita_ix,bitb_ix,illegal,illegal,eora_ix,eorb_ix, + illegal,illegal,ora_ix ,orb_ix ,illegal,illegal,cmpa_ix,cmpb_ix, /* 30 */ + illegal,setline_ix,sta_ix,stb_ix,illegal,illegal,illegal,illegal, + illegal,ldd_ix ,illegal,ldx_ix ,illegal,ldy_ix ,illegal,ldu_ix , /* 40 */ + illegal,lds_ix ,illegal,cmpd_ix,illegal,cmpx_ix,illegal,cmpy_ix, + illegal,cmpu_ix,illegal,cmps_ix,illegal,addd_ix,illegal,subd_ix, /* 50 */ + std_ix ,stx_ix ,sty_ix ,stu_ix ,sts_ix ,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,clr_ix ,illegal,illegal,com_ix ,illegal,illegal, /* 80 */ + neg_ix ,illegal,illegal,inc_ix ,illegal,illegal,dec_ix ,illegal, + illegal,illegal,tst_ix ,illegal,illegal,lsr_ix ,illegal,illegal, /* 90 */ + ror_ix ,illegal,illegal,asr_ix ,illegal,illegal,asl_ix ,illegal, + illegal,illegal,rol_ix ,lsrw_ix,rorw_ix,asrw_ix,aslw_ix,rolw_ix, /* a0 */ + jmp_ix ,jsr_ix ,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */ + illegal,lsrd_ix,illegal,rord_ix,illegal,asrd_ix,illegal,asld_ix, + illegal,rold_ix,illegal,clrw_ix,illegal,negw_ix,illegal,incw_ix, /* c0 */ + illegal,decw_ix,illegal,tstw_ix,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal +}; + +static void (*const konami_direct[0x100])(void) = { + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,lda_di ,ldb_di ,illegal,illegal,adda_di,addb_di, /* 10 */ + illegal,illegal,adca_di,adcb_di,illegal,illegal,suba_di,subb_di, + illegal,illegal,sbca_di,sbcb_di,illegal,illegal,anda_di,andb_di, /* 20 */ + illegal,illegal,bita_di,bitb_di,illegal,illegal,eora_di,eorb_di, + illegal,illegal,ora_di ,orb_di ,illegal,illegal,cmpa_di,cmpb_di, /* 30 */ + illegal,setline_di,sta_di,stb_di,illegal,illegal,illegal,illegal, + illegal,ldd_di ,illegal,ldx_di ,illegal,ldy_di ,illegal,ldu_di , /* 40 */ + illegal,lds_di ,illegal,cmpd_di,illegal,cmpx_di,illegal,cmpy_di, + illegal,cmpu_di,illegal,cmps_di,illegal,addd_di,illegal,subd_di, /* 50 */ + std_di ,stx_di ,sty_di ,stu_di ,sts_di ,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,clr_di ,illegal,illegal,com_di ,illegal,illegal, /* 80 */ + neg_di ,illegal,illegal,inc_di ,illegal,illegal,dec_di ,illegal, + illegal,illegal,tst_di ,illegal,illegal,lsr_di ,illegal,illegal, /* 90 */ + ror_di ,illegal,illegal,asr_di ,illegal,illegal,asl_di ,illegal, + illegal,illegal,rol_di ,lsrw_di,rorw_di,asrw_di,aslw_di,rolw_di, /* a0 */ + jmp_di ,jsr_di ,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */ + illegal,lsrd_di,illegal,rord_di,illegal,asrd_di,illegal,asld_di, + illegal,rold_di,illegal,clrw_di,illegal,negw_di,illegal,incw_di, /* c0 */ + illegal,decw_di,illegal,tstw_di,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal +}; + +static void (*const konami_extended[0x100])(void) = { + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,lda_ex ,ldb_ex ,illegal,illegal,adda_ex,addb_ex, /* 10 */ + illegal,illegal,adca_ex,adcb_ex,illegal,illegal,suba_ex,subb_ex, + illegal,illegal,sbca_ex,sbcb_ex,illegal,illegal,anda_ex,andb_ex, /* 20 */ + illegal,illegal,bita_ex,bitb_ex,illegal,illegal,eora_ex,eorb_ex, + illegal,illegal,ora_ex ,orb_ex ,illegal,illegal,cmpa_ex,cmpb_ex, /* 30 */ + illegal,setline_ex,sta_ex,stb_ex,illegal,illegal,illegal,illegal, + illegal,ldd_ex ,illegal,ldx_ex ,illegal,ldy_ex ,illegal,ldu_ex , /* 40 */ + illegal,lds_ex ,illegal,cmpd_ex,illegal,cmpx_ex,illegal,cmpy_ex, + illegal,cmpu_ex,illegal,cmps_ex,illegal,addd_ex,illegal,subd_ex, /* 50 */ + std_ex ,stx_ex ,sty_ex ,stu_ex ,sts_ex ,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,clr_ex ,illegal,illegal,com_ex ,illegal,illegal, /* 80 */ + neg_ex ,illegal,illegal,inc_ex ,illegal,illegal,dec_ex ,illegal, + illegal,illegal,tst_ex ,illegal,illegal,lsr_ex ,illegal,illegal, /* 90 */ + ror_ex ,illegal,illegal,asr_ex ,illegal,illegal,asl_ex ,illegal, + illegal,illegal,rol_ex ,lsrw_ex,rorw_ex,asrw_ex,aslw_ex,rolw_ex, /* a0 */ + jmp_ex ,jsr_ex ,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */ + illegal,lsrd_ex,illegal,rord_ex,illegal,asrd_ex,illegal,asld_ex, + illegal,rold_ex,illegal,clrw_ex,illegal,negw_ex,illegal,incw_ex, /* c0 */ + illegal,decw_ex,illegal,tstw_ex,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */ + illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal +}; diff --git a/src/cpu/konami_intf.cpp b/src/cpu/konami_intf.cpp new file mode 100644 index 00000000..1f87c7de --- /dev/null +++ b/src/cpu/konami_intf.cpp @@ -0,0 +1,162 @@ +#include "burnint.h" +#include "konami_intf.h" + +#define MEMORY_SPACE 0x10000 +#define PAGE_SIZE 0x100 +#define PAGE_MASK 0xff +#define PAGE_SHIFT 8 +#define PAGE_COUNT MEMORY_SPACE / PAGE_SIZE + +#define READ 0 +#define WRITE 1 +#define FETCH 2 + +INT32 nKonamiCpuCount = 0; +static INT32 nKonamiCpuActive = -1; + +static UINT8 *mem[3][PAGE_COUNT]; + +static UINT8 (*konamiRead)(UINT16 address); +static void (*konamiWrite)(UINT16 address, UINT8 data); +static INT32 (*irqcallback)(INT32); + +void konamiMapMemory(UINT8 *src, UINT16 start, UINT16 finish, INT32 type) +{ + UINT16 len = (finish-start) >> PAGE_SHIFT; + + for (UINT16 i = 0; i < len+1; i++) + { + UINT32 offset = i + (start >> PAGE_SHIFT); + if (type & (1 << READ)) mem[ READ][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << WRITE)) mem[WRITE][offset] = src + (i << PAGE_SHIFT); + if (type & (1 << FETCH)) mem[FETCH][offset] = src + (i << PAGE_SHIFT); + } +} + +INT32 konamiDummyIrqCallback(INT32) +{ + return 0; +} + +void konamiSetIrqCallbackHandler(INT32 (*callback)(INT32)) +{ + irqcallback = callback; +} + +void konamiSetWriteHandler(void (*write)(UINT16, UINT8)) +{ + konamiWrite = write; +} + +void konamiSetReadHandler(UINT8 (*read)(UINT16)) +{ + konamiRead = read; +} + +void konami_write_rom(UINT16 address, UINT8 data) +{ + if (mem[READ][address >> PAGE_SHIFT] != NULL) { + mem[READ][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[WRITE][address >> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (konamiWrite != NULL) { + konamiWrite(address, data); + } +} + +void konami_write(UINT16 address, UINT8 data) +{ + if (mem[WRITE][address >> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + return; + } + + if (konamiWrite != NULL) { + konamiWrite(address, data); + return; + } + + return; +} + +UINT8 konami_read(UINT16 address) +{ + if (mem[ READ][address >> PAGE_SHIFT] != NULL) { + return mem[ READ][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + if (konamiRead != NULL) { + return konamiRead(address); + } + + return 0; +} + +UINT8 konami_fetch(UINT16 address) +{ + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + return mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + if (konamiRead != NULL) { + return konamiRead(address); + } + + return 0; +} + +void konamiSetIrqLine(INT32 line, INT32 state) +{ + if (state == KONAMI_HOLD_LINE) { + konami_set_irq_line(line, KONAMI_HOLD_LINE); + konamiRun(0); + konami_set_irq_line(line, KONAMI_CLEAR_LINE); + konamiRun(0); + } else { + konami_set_irq_line(line, state); + } +} + +void konamiInit(INT32 num) // only 1 cpu (No examples exist of multi-cpu konami games) +{ + nKonamiCpuCount = 1; + konami_init(konamiDummyIrqCallback); + + for (INT32 i = 0; i < 3; i++) { + for (INT32 j = 0; j < (MEMORY_SPACE / PAGE_SIZE); j++) { + mem[i][j] = NULL; + } + } + + CpuCheatRegister(0x0009, num); +} + +void konamiExit() +{ + nKonamiCpuCount = 0; + konamiWrite = NULL; + konamiRead = NULL; +} + +void konamiOpen(INT32 num) +{ + nKonamiCpuActive = num; +} + +void konamiClose() +{ + nKonamiCpuActive = -1; +} + +INT32 konamiGetActive() +{ + return nKonamiCpuActive; +} diff --git a/src/cpu/konami_intf.h b/src/cpu/konami_intf.h new file mode 100644 index 00000000..452347a5 --- /dev/null +++ b/src/cpu/konami_intf.h @@ -0,0 +1,50 @@ +// konami.cpp +void konami_set_irq_line(INT32 irqline, INT32 state); +void konami_init(INT32 (*irqcallback)(INT32)); + +// konami_intf.cpp +#define KON_READ 1 +#define KON_WRITE 2 +#define KON_FETCH 4 + +#define KON_ROM (KON_READ | KON_FETCH) +#define KON_RAM (KON_READ | KON_FETCH | KON_WRITE) + +void konamiMapMemory(UINT8 *src, UINT16 start, UINT16 finish, INT32 type); + +void konamiSetIrqCallbackHandler(INT32 (*callback)(INT32)); +void konamiSetlinesCallback(void (*setlines_callback)(INT32 lines)); + +void konamiSetWriteHandler(void (*write)(UINT16, UINT8)); +void konamiSetReadHandler(UINT8 (*read)(UINT16)); + +void konami_write(UINT16 address, UINT8 data); +UINT8 konami_read(UINT16 address); +UINT8 konami_fetch(UINT16 address); + +void konamiInit(INT32 ); +void konamiOpen(INT32 ); +void konamiReset(); +INT32 konamiRun(INT32 cycles); +void konamiClose(); +void konamiExit(); + +extern INT32 nKonamiCpuCount; + +#define KONAMI_IRQ_LINE 0 +#define KONAMI_FIRQ_LINE 1 + +#define KONAMI_CLEAR_LINE 0 +#define KONAMI_HOLD_LINE 1 +#define KONAMI_INPUT_LINE_NMI 2 + +void konamiSetIrqLine(INT32 line, INT32 state); + +INT32 konamiCpuScan(INT32 nAction, INT32 *); + +INT32 konamiTotalCycles(); +void konamiNewFrame(); + +INT32 konamiGetActive(); + +void konami_write_rom(UINT16 address, UINT8 data); diff --git a/src/cpu/m6502/ill02.h b/src/cpu/m6502/ill02.h new file mode 100644 index 00000000..86ecee8f --- /dev/null +++ b/src/cpu/m6502/ill02.h @@ -0,0 +1,335 @@ +#pragma once + +#ifndef __ILL02_H__ +#define __ILL02_H__ + +/***************************************************************************** + * + * ill02.h + * Addressing mode and opcode macros for the NMOS 6502 illegal opcodes + * + * Copyright Juergen Buchmueller, all rights reserved. + * 65sc02 core Copyright Peter Trauner, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ + +/* test with the excellent C64 Emulator test suite + ? at www.funet.fi/pub/cbm/documents/chipdata/tsuit215.zip + good reference in the vice emulator (source) distribution doc/64doc.txt + + $ab=OAL like in 6502-NMOS.extra.opcodes, vice so in vice (lxa) +*/ + +/*************************************************************** + *************************************************************** + * Macros to emulate the 6510 opcodes + *************************************************************** + ***************************************************************/ + +/* 6510 ******************************************************** + * ANC logical and, set carry from bit of A + ***************************************************************/ +#define ANC \ + P &= ~F_C; \ + A = (UINT8)(A & tmp); \ + if (A & 0x80) \ + P |= F_C; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * ASR logical and, logical shift right + ***************************************************************/ +#define ASR \ + tmp &= A; \ + LSR + +/* 6510 ******************************************************** + * AST and stack; transfer to accumulator and index X + * logical and stack (LSB) with data, transfer result to S + * transfer result to accumulator and index X also + ***************************************************************/ +#define AST \ + S &= tmp; \ + A = X = S; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * ARR logical and, rotate right + ***************************************************************/ +#define ARR \ + if( P & F_D ) \ + { \ + int lo, hi, t; \ + tmp &= A; \ + t = tmp; \ + hi = tmp &0xf0; \ + lo = tmp &0x0f; \ + if( P & F_C ) \ + { \ + tmp = (tmp >> 1) | 0x80; \ + P |= F_N; \ + } \ + else \ + { \ + tmp >>= 1; \ + P &= ~F_N; \ + } \ + if( tmp ) \ + P &= ~F_Z; \ + else \ + P |= F_Z; \ + if( (t^tmp) & 0x40 ) \ + P|=F_V; \ + else \ + P &= ~F_V; \ + if( lo + (lo & 0x01) > 0x05 ) \ + tmp = (tmp & 0xf0) | ((tmp+6) & 0xf); \ + if( hi + (hi & 0x10) > 0x50 ) \ + { \ + P |= F_C; \ + tmp = (tmp+0x60) & 0xff; \ + } \ + else \ + P &= ~F_C; \ + } \ + else \ + { \ + tmp &= A; \ + ROR; \ + P &=~(F_V|F_C); \ + if( tmp & 0x40 ) \ + P|=F_C; \ + if( (tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40 ) \ + P|=F_V; \ + } + +/* 6510 ******************************************************** + * ASX logical and X w/ A, subtract data from X + ***************************************************************/ +#define ASX \ + P &= ~F_C; \ + X &= A; \ + if (X >= tmp) \ + P |= F_C; \ + X = (UINT8)(X - tmp); \ + SET_NZ(X) + +/* 6510 ******************************************************** + * AXA transfer index X to accumulator, logical and + * depends on the data of the dma device (videochip) fetched + * between opcode read and operand read + ***************************************************************/ +#define AXA \ + A = (UINT8)( (A|0xee)& X & tmp); \ + SET_NZ(A) + +/* 6510 ******************************************************** + * DCP decrement data and compare + ***************************************************************/ +#define DCP \ + tmp = (UINT8)(tmp-1); \ + P &= ~F_C; \ + if (A >= tmp) \ + P |= F_C; \ + SET_NZ((UINT8)(A - tmp)) + +/* 6502 ******************************************************** + * DOP double no operation + ***************************************************************/ +#define DOP \ + RDOPARG() + +/* 6510 ******************************************************** + * ISB increment and subtract with carry + ***************************************************************/ +#define ISB \ + tmp = (UINT8)(tmp+1); \ + SBC + +/* 6510 ******************************************************** + * LAX load accumulator and index X + ***************************************************************/ +#define LAX \ + A = X = (UINT8)tmp; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * OAL load accumulator and index X + ***************************************************************/ +#define OAL \ + A = X = (UINT8)((A|0xee)&tmp); \ + SET_NZ(A) + +/* 6510 ******************************************************** + * RLA rotate left and logical and accumulator + * new C <- [7][6][5][4][3][2][1][0] <- C + ***************************************************************/ +#define RLA \ + tmp = (tmp << 1) | (P & F_C); \ + P = (P & ~F_C) | ((tmp >> 8) & F_C); \ + tmp = (UINT8)tmp; \ + A &= tmp; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * RRA rotate right and add with carry + * C -> [7][6][5][4][3][2][1][0] -> C + ***************************************************************/ +#define RRA \ + tmp |= (P & F_C) << 8; \ + P = (P & ~F_C) | (tmp & F_C); \ + tmp = (UINT8)(tmp >> 1); \ + ADC + +/* 6510 ******************************************************** + * SAX logical and accumulator with index X and store + ***************************************************************/ +#define SAX \ + tmp = A & X + +/* 6510 ******************************************************** + * SLO shift left and logical or + ***************************************************************/ +#define SLO \ + P = (P & ~F_C) | ((tmp >> 7) & F_C); \ + tmp = (UINT8)(tmp << 1); \ + A |= tmp; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * SRE logical shift right and logical exclusive or + * 0 -> [7][6][5][4][3][2][1][0] -> C + ***************************************************************/ +#define SRE \ + P = (P & ~F_C) | (tmp & F_C); \ + tmp = (UINT8)tmp >> 1; \ + A ^= tmp; \ + SET_NZ(A) + +/* 6510 ******************************************************** + * SAH store accumulator and index X and high + 1 + * result = accumulator and index X and memory [PC+1] + 1 + ***************************************************************/ +#define SAH tmp = A & X & (EAH+1) + +/* 6510 ******************************************************** + * SSH store stack high + * logical and accumulator with index X, transfer result to S + * logical and result with memory [PC+1] + 1 + ***************************************************************/ +#define SSH \ + S = A & X; \ + tmp = S & (EAH+1) +#if 0 +#define SSH \ + tmp = S = A & X; \ + tmp &= (UINT8)(cpu_readop_arg((PCW + 1) & 0xffff) + 1) +#endif + +/* 6510 ******************************************************** + * SXH store index X high + * logical and index X with memory[PC+1] and store the result + ***************************************************************/ +#define SXH tmp = X & (EAH+1) + +/* 6510 ******************************************************** + * SYH store index Y and (high + 1) + * logical and index Y with memory[PC+1] + 1 and store the result + ***************************************************************/ +#define SYH tmp = Y & (EAH+1) + +/* 6510 ******************************************************** + * TOP triple no operation + ***************************************************************/ +#define TOP \ + PCW+=2 + +/* 6510 ******************************************************** + * KIL Illegal opcode + * processor halted: no hardware interrupt will help, + * only reset + ***************************************************************/ +#define KIL \ + PCW--; \ + +/* N2A03 ******************************************************* + * ARR logical and, rotate right - no decimal mode + ***************************************************************/ +#define ARR_NES \ + { \ + tmp &= A; \ + ROR; \ + P &=~(F_V|F_C); \ + if( tmp & 0x40 ) \ + P|=F_C; \ + if( (tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40 ) \ + P|=F_V; \ + } + +/* N2A03 ******************************************************* + * ISB increment and subtract with carry + ***************************************************************/ +#define ISB_NES \ + tmp = (UINT8)(tmp+1); \ + SBC_NES + +/* N2A03 ******************************************************* + * RRA rotate right and add with carry + * C -> [7][6][5][4][3][2][1][0] -> C + ***************************************************************/ +#define RRA_NES \ + tmp |= (P & F_C) << 8; \ + P = (P & ~F_C) | (tmp & F_C); \ + tmp = (UINT8)(tmp >> 1); \ + ADC_NES + +/* N2A03 ******************************************************* + * OAL load accumulator and index X + ***************************************************************/ +#define OAL_NES \ + A = X = (UINT8)((A|0xff)&tmp); \ + SET_NZ(A) + +/* N2A03 ******************************************************* + * SXH store index X high + * logical and index X with memory[PC+1] and store the result + * + * This instruction writes to an odd address when crossing + * a page boundary. The one known test case can be explained + * with a shift of Y. More testing will be needed to determine + * if this is correct. + * + ***************************************************************/ +#define SXH_NES \ + if ( Y && Y > EAL ) \ + EAH |= ( Y << 1 ); \ + tmp = X & (EAH+1) + +/* N2A03 ******************************************************* + * SYH store index Y and (high + 1) + * logical and index Y with memory[PC+1] + 1 and store the result + * + * This instruction writs to an odd address when crossing a + * a page boundary. The one known test case can be explained + * with a shoft of X. More testing will be needed to determine + * if this is correct. + * + ***************************************************************/ +#define SYH_NES \ + if ( X && X > EAL ) \ + EAH |= ( X << 1 ); \ + tmp = Y & (EAH+1) + +#endif /* __ILL02_H__ */ diff --git a/src/cpu/m6502/m6502.cpp b/src/cpu/m6502/m6502.cpp new file mode 100644 index 00000000..d0a44ab9 --- /dev/null +++ b/src/cpu/m6502/m6502.cpp @@ -0,0 +1,998 @@ +/***************************************************************************** + * + * m6502.c + * Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2 + * + * Copyright Juergen Buchmueller, all rights reserved. + * 65sc02 core Copyright Peter Trauner. + * Deco16 portions Copyright Bryan McPhail. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ +/* 2.February 2000 PeT added 65sc02 subtype */ +/* 10.March 2000 PeT added 6502 set overflow input line */ +/* 13.September 2000 PeT N2A03 jmp indirect */ + +#include "burnint.h" +#include "m6502.h" + +#define M6502_INLINE + +#if ((HAS_M65SC02 || HAS_DECO16) && !HAS_M65C02) +#undef HAS_M65C02 +#define HAS_M65C02 1 +#endif + +#define change_pc(newpc) m6502.pc.d = (newpc) + +void (*const *insnActive)(void); + +#include "ops02.h" +#include "ill02.h" + + +#define M6502_NMI_VEC 0xfffa +#define M6502_RST_VEC 0xfffc +#define M6502_IRQ_VEC 0xfffe + +#define DECO16_RST_VEC 0xfff0 +#define DECO16_IRQ_VEC 0xfff2 +#define DECO16_NMI_VEC 0xfff4 + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +/**************************************************************************** + * The 6502 registers. + ****************************************************************************/ + + static int m6502_IntOccured = 0; +static int m6502_ICount = 0; + +static m6502_Regs m6502; + +//static READ8_HANDLER( default_rdmem_id ) { return program_read_byte_8le(offset); } +//static WRITE8_HANDLER( default_wdmem_id ) { program_write_byte_8le(offset, data); } + +/*************************************************************** + * include the opcode macros, functions and tables + ***************************************************************/ +#include "t6502.c" + +#if (HAS_M6510) +//#include "t6510.c" +#define insn6510 insn6502 +#endif + +#include "opsn2a03.h" + +#if (HAS_N2A03) +#include "tn2a03.c" +#endif + +#include "opsc02.h" + +#if (HAS_M65C02) +#include "t65c02.c" +#endif + +#if (HAS_M65SC02) +#include "t65sc02.c" +#endif + +#if (HAS_DECO16) +#include "tdeco16.c" +#endif + +/***************************************************************************** + * + * 6502 CPU interface functions + * + *****************************************************************************/ + +static void m6502_common_init(UINT8 subtype, void (*const *insn)(void)/*, const char *type*/) +{ + memset(&m6502, 0, sizeof(m6502)); +// m6502.irq_callback = irqcallback; + m6502.subtype = subtype; + //m6502.insn = insn; + insnActive = insn; +// m6502.rdmem_id = default_rdmem_id; +// m6502.wrmem_id = default_wdmem_id; + +// state_save_register_item(type, index, m6502.pc.w.l); +// state_save_register_item(type, index, m6502.sp.w.l); +// state_save_register_item(type, index, m6502.p); +// state_save_register_item(type, index, m6502.a); +// state_save_register_item(type, index, m6502.x); +// state_save_register_item(type, index, m6502.y); +// state_save_register_item(type, index, m6502.pending_irq); +// state_save_register_item(type, index, m6502.after_cli); +// state_save_register_item(type, index, m6502.nmi_state); +// state_save_register_item(type, index, m6502.irq_state); +// state_save_register_item(type, index, m6502.so_state); + +#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501) + if (subtype == SUBTYPE_6510) + { +// state_save_register_item(type, index, m6502.port); +// state_save_register_item(type, index, m6502.ddr); + } +#endif +} + +void m6502_init() +{ + m6502_common_init(SUBTYPE_6502, insn6502/*, "m6502"*/); +} + +void m6502_reset(void) +{ + /* wipe out the rest of the m6502 structure */ + /* read the reset vector into PC */ + PCL = RDMEM(M6502_RST_VEC); + PCH = RDMEM(M6502_RST_VEC+1); + + m6502.sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */ + m6502.p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */ + m6502.pending_irq = 0; /* nonzero if an IRQ is pending */ + m6502.after_cli = 0; /* pending IRQ and last insn cleared I */ + m6502.irq_state = 0; + m6502.nmi_state = 0; + + change_pc(PCD); +} + +void m6502_exit(void) +{ + /* nothing to do yet */ +} + +void m6502_get_context (void *dst) +{ + if( dst ) + *(m6502_Regs*)dst = m6502; +} + +void m6502_set_context (void *src) +{ + if( src ) + { + m6502 = *(m6502_Regs*)src; + if (m6502.subtype == SUBTYPE_6502) insnActive = insn6502; + if (m6502.subtype == SUBTYPE_65C02) insnActive = insn65c02; + if (m6502.subtype == SUBTYPE_2A03) insnActive = insn2a03; + if (m6502.subtype == SUBTYPE_65SC02)insnActive = insn65sc02; + if (m6502.subtype == SUBTYPE_DECO16)insnActive = insndeco16; + if (m6502.subtype == SUBTYPE_6510) insnActive = insn6510; + change_pc(PCD); + } +} + +M6502_INLINE void m6502_take_irq(void) +{ + if( !(P & F_I) ) + { + EAD = M6502_IRQ_VEC; + m6502_ICount -= 2; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P |= F_I; /* set I flag */ + PCL = RDMEM(EAD); + PCH = RDMEM(EAD+1); +// LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD)); + /* call back the cpuintrf to let it clear the line */ + if (m6502.irq_callback) (*m6502.irq_callback)(0); + change_pc(PCD); + } + m6502.pending_irq = 0; +} + +int m6502_execute(int cycles) +{ + m6502_ICount = cycles; + + change_pc(PCD); + + do + { + UINT8 op; + PPC = PCD; + +// debugger_instruction_hook(Machine, PCD); + + /* if an irq is pending, take it now */ + if( m6502.pending_irq ) + m6502_take_irq(); + + op = RDOP(); + //(*m6502.insn[op])(); + (*insnActive[op])(); + + /* check if the I flag was just reset (interrupts enabled) */ + if( m6502.after_cli ) + { +// LOG(("M6502#%d after_cli was >0", cpu_getactivecpu())); + m6502.after_cli = 0; + if (m6502.irq_state != M6502_CLEAR_LINE) + { +// LOG((": irq line is asserted: set pending IRQ\n")); + m6502.pending_irq = 1; + } + else + { +// LOG((": irq line is clear\n")); + } + } + else { + if ( m6502.pending_irq == 2 ) { + if ( m6502_IntOccured - m6502_ICount > 1 ) { + m6502.pending_irq = 1; + } + } + if( m6502.pending_irq == 1 ) + m6502_take_irq(); + if ( m6502.pending_irq == 2 ) { + m6502.pending_irq = 1; + } + } + + } while (m6502_ICount > 0); + + return cycles - m6502_ICount; +} + +void m6502_set_irq_line(int irqline, int state) +{ + if (irqline == M6502_INPUT_LINE_NMI) + { + if (m6502.nmi_state == state) return; + m6502.nmi_state = state; + if( state != M6502_CLEAR_LINE ) + { +// LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu())); + EAD = M6502_NMI_VEC; + m6502_ICount -= 2; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P |= F_I; /* set I flag */ + PCL = RDMEM(EAD); + PCH = RDMEM(EAD+1); +// LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD)); + change_pc(PCD); + } + } + else + { + if( irqline == M6502_SET_OVERFLOW ) + { + if( m6502.so_state && !state ) + { +// LOG(( "M6502#%d set overflow\n", cpu_getactivecpu())); + P|=F_V; + } + m6502.so_state=state; + return; + } + m6502.irq_state = state; + if( state != M6502_CLEAR_LINE ) + { +// LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu())); + m6502.pending_irq = 1; +// m6502.pending_irq = 2; + m6502_IntOccured = m6502_ICount; + } + } +} + +UINT32 m6502_get_pc() +{ + return m6502.pc.d; +} + +/**************************************************************************** + * 2A03 section + ****************************************************************************/ +#if (HAS_N2A03) + +void n2a03_init() +{ + m6502_common_init(SUBTYPE_2A03, insn2a03); +} + +/* The N2A03 is integrally tied to its PSG (they're on the same die). + Bit 7 of address $4011 (the PSG's DPCM control register), when set, + causes an IRQ to be generated. This function allows the IRQ to be called + from the PSG core when such an occasion arises. */ +void n2a03_irq(void) +{ + m6502_take_irq(); +} + + +/**************************************************************************** + * 6510 section + ****************************************************************************/ +#if (HAS_M6510) + +void m6510_init () +{ + m6502_common_init(SUBTYPE_6510, insn6510); +} + +void m6510_reset(void) +{ + m6502_reset(); + m6502.port = 0xff; + m6502.ddr = 0x00; +} + +//static UINT8 m6510_get_port(void) +//{ +// return (m6502.port & m6502.ddr) | (m6502.ddr ^ 0xff); +//} + +unsigned char m6510_read_0000(unsigned short address) +{ + UINT8 result = 0x00; + + switch (address) + { + case 0x0000: /* DDR */ + result = m6502.ddr; + break; + case 0x0001: /* Data Port */ + if (m6502.port_read) + result = M6502ReadPort( m6502.ddr ); + result = (m6502.ddr & m6502.port) | (~m6502.ddr & result); + break; + } + return result; +} + +void m6510_write_0000(unsigned short address, unsigned char data) +{ + switch (address) + { + case 0x0000: /* DDR */ + m6502.ddr = data; + break; + case 0x0001: /* Data Port */ + m6502.port = data; + break; + } + + M6502WritePort( m6502.ddr, m6502.port & m6502.ddr ); +} + +//static ADDRESS_MAP_START(m6510_mem, ADDRESS_SPACE_PROGRAM, 8) +// AM_RANGE(0x0000, 0x0001) AM_READWRITE(m6510_read_0000, m6510_write_0000) +//ADDRESS_MAP_END + +#endif + +#endif + +/**************************************************************************** + * 65C02 section + ****************************************************************************/ +#if (HAS_M65C02) + +void m65c02_init() +{ + m6502_common_init(SUBTYPE_65C02, insn65c02); +} + +void m65c02_reset() +{ + m6502_reset(); + P &=~F_D; +} + +M6502_INLINE void m65c02_take_irq(void) +{ + if( !(P & F_I) ) + { + EAD = M6502_IRQ_VEC; + m6502_ICount -= 2; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P = (P & ~F_D) | F_I; /* knock out D and set I flag */ + PCL = RDMEM(EAD); + PCH = RDMEM(EAD+1); + //LOG(("M65c02#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD)); + /* call back the cpuintrf to let it clear the line */ + if (m6502.irq_callback) (*m6502.irq_callback)(0); + change_pc(PCD); + } + m6502.pending_irq = 0; +} + +int m65c02_execute(int cycles) +{ + m6502_ICount = cycles; + + change_pc(PCD); + + do + { + UINT8 op; + PPC = PCD; + + //debugger_instruction_hook(Machine, PCD); + + op = RDOP(); + //(*m6502.insn[op])(); + (*insnActive[op])(); + + /* if an irq is pending, take it now */ + if( m6502.pending_irq ) + m65c02_take_irq(); + + + /* check if the I flag was just reset (interrupts enabled) */ + if( m6502.after_cli ) + { + //LOG(("M6502#%d after_cli was >0", cpu_getactivecpu())); + m6502.after_cli = 0; + if (m6502.irq_state != M6502_CLEAR_LINE) + { + // LOG((": irq line is asserted: set pending IRQ\n")); + m6502.pending_irq = 1; + } + //else + //{ + // LOG((": irq line is clear\n")); + //} + } + else + if( m6502.pending_irq ) + m65c02_take_irq(); + + } while (m6502_ICount > 0); + + return cycles - m6502_ICount; +} + +void m65c02_set_irq_line(int irqline, int state) +{ + if (irqline == M6502_INPUT_LINE_NMI) + { + if (m6502.nmi_state == state) return; + m6502.nmi_state = state; + if( state != M6502_CLEAR_LINE ) + { + // LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu())); + EAD = M6502_NMI_VEC; + m6502_ICount -= 2; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P = (P & ~F_D) | F_I; /* knock out D and set I flag */ + PCL = RDMEM(EAD); + PCH = RDMEM(EAD+1); + // LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD)); + change_pc(PCD); + } + } + else + m6502_set_irq_line(irqline,state); +} +#endif + +/**************************************************************************** + * 65SC02 section + ****************************************************************************/ +#if (HAS_M65SC02) +void m65sc02_init() +{ + m6502_common_init(SUBTYPE_65SC02, insn65sc02); +} +#endif + +/**************************************************************************** + * DECO16 section + ****************************************************************************/ +#if (HAS_DECO16) + +void deco16_init() +{ + m6502_common_init(SUBTYPE_DECO16, insndeco16); +} + + +void deco16_reset (void) +{ + m6502_reset(); + m6502.subtype = SUBTYPE_DECO16; + insnActive = insndeco16; + + PCL = RDMEM(DECO16_RST_VEC+1); + PCH = RDMEM(DECO16_RST_VEC); + + m6502.sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */ + m6502.p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */ + m6502.pending_irq = 0; /* nonzero if an IRQ is pending */ + m6502.after_cli = 0; /* pending IRQ and last insn cleared I */ + + change_pc(PCD); +} + +M6502_INLINE void deco16_take_irq(void) +{ + if( !(P & F_I) ) + { + EAD = DECO16_IRQ_VEC; + m6502_ICount -= 2; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P |= F_I; /* set I flag */ + PCL = RDMEM(EAD+1); + PCH = RDMEM(EAD); + //LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD)); + /* call back the cpuintrf to let it clear the line */ + if (m6502.irq_callback) (*m6502.irq_callback)(0); + change_pc(PCD); + } + m6502.pending_irq = 0; +} + +void deco16_set_irq_line(int irqline, int state) +{ + if (irqline == M6502_INPUT_LINE_NMI) + { + if (m6502.nmi_state == state) return; + m6502.nmi_state = state; + if( state != M6502_CLEAR_LINE ) + { + //LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu())); + EAD = DECO16_NMI_VEC; + m6502_ICount -= 7; + PUSH(PCH); + PUSH(PCL); + PUSH(P & ~F_B); + P |= F_I; /* set I flag */ + PCL = RDMEM(EAD+1); + PCH = RDMEM(EAD); + //LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD)); + change_pc(PCD); + } + } + else + { + if( irqline == M6502_SET_OVERFLOW ) + { + if( m6502.so_state && !state ) + { + // LOG(( "M6502#%d set overflow\n", cpu_getactivecpu())); + P|=F_V; + } + m6502.so_state=state; + return; + } + m6502.irq_state = state; + if( state != M6502_CLEAR_LINE ) + { + //LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu())); + m6502.pending_irq = 1; + } + } +} + +int deco16_execute(int cycles) +{ + m6502_ICount = cycles; + + change_pc(PCD); + + do + { + UINT8 op; + PPC = PCD; + + //debugger_instruction_hook(Machine, PCD); + + op = RDOP(); + //(*m6502.insn[op])(); + (*insnActive[op])(); + + /* if an irq is pending, take it now */ + if( m6502.pending_irq ) + deco16_take_irq(); + + + /* check if the I flag was just reset (interrupts enabled) */ + if( m6502.after_cli ) + { + //LOG(("M6502#%d after_cli was >0", cpu_getactivecpu())); + m6502.after_cli = 0; + if (m6502.irq_state != M6502_CLEAR_LINE) + { + // LOG((": irq line is asserted: set pending IRQ\n")); + m6502.pending_irq = 1; + } + //else + //{ + // LOG((": irq line is clear\n")); + //} + } + else + if( m6502.pending_irq ) + deco16_take_irq(); + + } while (m6502_ICount > 0); + + return cycles - m6502_ICount; +} + +#endif + + +#if 0 + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void m6502_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: m6502_set_irq_line(M6502_IRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: m6502_set_irq_line(M6502_SET_OVERFLOW, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m6502_set_irq_line(INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_PC: PCW = info->i; change_pc(PCD); break; + case CPUINFO_INT_REGISTER + M6502_PC: m6502.pc.w.l = info->i; break; + case CPUINFO_INT_SP: S = info->i; break; + case CPUINFO_INT_REGISTER + M6502_S: m6502.sp.b.l = info->i; break; + case CPUINFO_INT_REGISTER + M6502_P: m6502.p = info->i; break; + case CPUINFO_INT_REGISTER + M6502_A: m6502.a = info->i; break; + case CPUINFO_INT_REGISTER + M6502_X: m6502.x = info->i; break; + case CPUINFO_INT_REGISTER + M6502_Y: m6502.y = info->i; break; + case CPUINFO_INT_REGISTER + M6502_EA: m6502.ea.w.l = info->i; break; + case CPUINFO_INT_REGISTER + M6502_ZP: m6502.zp.w.l = info->i; break; + + /* --- the following bits of info are set as pointers to data or functions --- */ + case CPUINFO_PTR_M6502_READINDEXED_CALLBACK: m6502.rdmem_id = (read8_machine_func) info->f; break; + case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK: m6502.wrmem_id = (write8_machine_func) info->f; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void m6502_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6502); break; + case CPUINFO_INT_INPUT_LINES: info->i = 2; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 10; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: info->i = m6502.irq_state; break; + case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: info->i = m6502.so_state; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = m6502.nmi_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = m6502.ppc.w.l; break; + + case CPUINFO_INT_PC: info->i = PCD; break; + case CPUINFO_INT_REGISTER + M6502_PC: info->i = m6502.pc.w.l; break; + case CPUINFO_INT_SP: info->i = S; break; + case CPUINFO_INT_REGISTER + M6502_S: info->i = m6502.sp.b.l; break; + case CPUINFO_INT_REGISTER + M6502_P: info->i = m6502.p; break; + case CPUINFO_INT_REGISTER + M6502_A: info->i = m6502.a; break; + case CPUINFO_INT_REGISTER + M6502_X: info->i = m6502.x; break; + case CPUINFO_INT_REGISTER + M6502_Y: info->i = m6502.y; break; + case CPUINFO_INT_REGISTER + M6502_EA: info->i = m6502.ea.w.l; break; + case CPUINFO_INT_REGISTER + M6502_ZP: info->i = m6502.zp.w.l; break; + case CPUINFO_INT_REGISTER + M6502_SUBTYPE: info->i = m6502.subtype; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = m6502_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = m6502_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = m6502_set_context; break; + case CPUINFO_PTR_INIT: info->init = m6502_init; break; + case CPUINFO_PTR_RESET: info->reset = m6502_reset; break; + case CPUINFO_PTR_EXIT: info->exit = m6502_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = m6502_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6502_dasm; break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m6502_ICount; break; + case CPUINFO_PTR_M6502_READINDEXED_CALLBACK: info->f = (genf *) m6502.rdmem_id; break; + case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK: info->f = (genf *) m6502.wrmem_id; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6502"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Mostek 6502"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.2"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c", + m6502.p & 0x80 ? 'N':'.', + m6502.p & 0x40 ? 'V':'.', + m6502.p & 0x20 ? 'R':'.', + m6502.p & 0x10 ? 'B':'.', + m6502.p & 0x08 ? 'D':'.', + m6502.p & 0x04 ? 'I':'.', + m6502.p & 0x02 ? 'Z':'.', + m6502.p & 0x01 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + M6502_PC: sprintf(info->s, "PC:%04X", m6502.pc.w.l); break; + case CPUINFO_STR_REGISTER + M6502_S: sprintf(info->s, "S:%02X", m6502.sp.b.l); break; + case CPUINFO_STR_REGISTER + M6502_P: sprintf(info->s, "P:%02X", m6502.p); break; + case CPUINFO_STR_REGISTER + M6502_A: sprintf(info->s, "A:%02X", m6502.a); break; + case CPUINFO_STR_REGISTER + M6502_X: sprintf(info->s, "X:%02X", m6502.x); break; + case CPUINFO_STR_REGISTER + M6502_Y: sprintf(info->s, "Y:%02X", m6502.y); break; + case CPUINFO_STR_REGISTER + M6502_EA: sprintf(info->s, "EA:%04X", m6502.ea.w.l); break; + case CPUINFO_STR_REGISTER + M6502_ZP: sprintf(info->s, "ZP:%03X", m6502.zp.w.l); break; + } +} + + +#if (HAS_N2A03) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void n2a03_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = n2a03_init; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "N2A03"); break; + + default: m6502_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +static void m6510_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as pointers to data or functions --- */ + case CPUINFO_PTR_M6510_PORTREAD: m6502.port_read = (UINT8 (*)(UINT8)) info->f; break; + case CPUINFO_PTR_M6510_PORTWRITE: m6502.port_write = (void (*)(UINT8,UINT8)) info->f; break; + + default: m6502_set_info(state, info); break; + } +} + +void m6510_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = m6510_set_info; break; + case CPUINFO_PTR_INIT: info->init = m6510_init; break; + case CPUINFO_PTR_RESET: info->reset = m6510_reset; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6510_dasm; break; + case CPUINFO_PTR_INTERNAL_MEMORY_MAP: info->internal_map8 = address_map_m6510_mem; break; + case CPUINFO_PTR_M6510_PORTREAD: info->f = (genf *) m6502.port_read; break; + case CPUINFO_PTR_M6510_PORTWRITE: info->f = (genf *) m6502.port_write; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6510"); break; + + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_M6510_PORT: info->i = m6510_get_port(); break; + + default: m6502_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M6510T) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6510t_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6510T"); break; + + default: m6510_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M7501) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m7501_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M7501"); break; + + default: m6510_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M8502) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m8502_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M8502"); break; + + default: m6510_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M65C02) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +static void m65c02_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m65c02_set_irq_line(INPUT_LINE_NMI, info->i); break; + + default: m6502_set_info(state, info); break; + } +} + +void m65c02_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = m65c02_set_info; break; + case CPUINFO_PTR_INIT: info->init = m65c02_init; break; + case CPUINFO_PTR_RESET: info->reset = m65c02_reset; break; + case CPUINFO_PTR_EXECUTE: info->execute = m65c02_execute; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m65c02_dasm; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M65C02"); break; + + default: m6502_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M65SC02) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m65sc02_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = m65sc02_init; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m65sc02_dasm; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M65SC02"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Metal Oxid Semiconductor MOS 6502"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0beta"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Peter Trauner\nall rights reserved."); break; + + default: m65c02_get_info(state, info); break; + } +} +#endif + + +#if (HAS_DECO16) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +static void deco16_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: deco16_set_irq_line(M6502_IRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: deco16_set_irq_line(M6502_SET_OVERFLOW, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: deco16_set_irq_line(INPUT_LINE_NMI, info->i); break; + + default: m6502_set_info(state, info); break; + } +} + +void deco16_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = deco16_set_info; break; + case CPUINFO_PTR_INIT: info->init = deco16_init; break; + case CPUINFO_PTR_RESET: info->reset = deco16_reset; break; + case CPUINFO_PTR_EXECUTE: info->execute = deco16_execute; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = deco16_dasm; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "DECO CPU16"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "DECO"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Bryan McPhail\nall rights reserved."); break; + + default: m6502_get_info(state, info); break; + } +} +#endif + +#endif diff --git a/src/cpu/m6502/m6502.h b/src/cpu/m6502/m6502.h new file mode 100644 index 00000000..fc3cf7f5 --- /dev/null +++ b/src/cpu/m6502/m6502.h @@ -0,0 +1,340 @@ +/***************************************************************************** + * + * m6502.h + * Portable 6502/65c02/65sc02/6510/n2a03 emulator interface + * + * Copyright Juergen Buchmueller, all rights reserved. + * 65sc02 core Copyright Peter Trauner. + * Deco16 portions Copyright Bryan McPhail. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ +/* 2.February 2000 PeT added 65sc02 subtype */ + +#pragma once + +#ifndef __M6502_H__ +#define __M6502_H__ + +//#include "cpuintrf.h" + +#define HAS_M65C02 1 +#define HAS_M6510 1 +#define HAS_N2A03 1 +#define HAS_M65SC02 1 +#define HAS_DECO16 1 +#define HAS_M6510T 1 +#define HAS_M7501 1 +#define HAS_M8502 1 + +typedef struct +{ + UINT8 subtype; /* currently selected cpu sub type */ +// void (*const *insn)(void); /* pointer to the function pointer table */ + PAIR ppc; /* previous program counter */ + PAIR pc; /* program counter */ + PAIR sp; /* stack pointer (always 100 - 1FF) */ + PAIR zp; /* zero page address */ + PAIR ea; /* effective address */ + UINT8 a; /* Accumulator */ + UINT8 x; /* X index register */ + UINT8 y; /* Y index register */ + UINT8 p; /* Processor status */ + UINT8 pending_irq; /* nonzero if an IRQ is pending */ + UINT8 after_cli; /* pending IRQ and last insn cleared I */ + UINT8 nmi_state; + UINT8 irq_state; + UINT8 so_state; + int (*irq_callback)(int irqline); /* IRQ callback */ +// read8_machine_func rdmem_id; /* readmem callback for indexed instructions */ +// write8_machine_func wrmem_id; /* writemem callback for indexed instructions */ + +#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501) + UINT8 ddr; + UINT8 port; + UINT8 (*port_read)(UINT8 direction); + void (*port_write)(UINT8 direction, UINT8 data); +#endif + +} m6502_Regs; + +#define M6502_CLEAR_LINE 0 +#define M6502_ASSERT_LINE 1 +#define M6502_INPUT_LINE_NMI 32 + +/* set to 1 to test cur_mrhard/cur_wmhard to avoid calls */ +#define FAST_MEMORY 0 + +#define SUBTYPE_6502 0 +#if (HAS_M65C02) +#define SUBTYPE_65C02 1 +#endif +#if (HAS_M6510) +#define SUBTYPE_6510 2 +#endif +#if (HAS_N2A03) +#define SUBTYPE_2A03 3 +#endif +#if (HAS_M65SC02) +#define SUBTYPE_65SC02 4 +#endif +#if (HAS_DECO16) +#define SUBTYPE_DECO16 5 +#endif + +enum +{ + M6502_PC=1, M6502_S, M6502_P, M6502_A, M6502_X, M6502_Y, + M6502_EA, M6502_ZP, + M6502_SUBTYPE +}; + +#define M6502_IRQ_LINE 0 +/* use cpunum_set_input_line(machine, cpu, M6502_SET_OVERFLOW, level) + to change level of the so input line + positiv edge sets overflow flag */ +#define M6502_SET_OVERFLOW 1 + +/*typedef unsigned char (*M6502ReadIoHandler)(unsigned short a); +typedef void (*M6502WriteIoHandler)(unsigned short a, unsigned char v); +typedef unsigned char (*M6502ReadProgHandler)(unsigned short a); +typedef void (*M6502WriteProgHandler)(unsigned short a, unsigned char v); +typedef unsigned char (*M6502ReadMemIndexHandler)(unsigned short a); +typedef void (*M6502WriteMemIndexHandler)(unsigned short a, unsigned char v); +typedef unsigned char (*M6502ReadOpHandler)(unsigned short a); +typedef unsigned char (*M6502ReadOpArgHandler)(unsigned short a);*/ + +unsigned char M6502ReadPort(unsigned short Address); +void M6502WritePort(unsigned short Address, unsigned char Data); +unsigned char M6502ReadByte(unsigned short Address); +void M6502WriteByte(unsigned short Address, unsigned char Data); +unsigned char M6502ReadMemIndex(unsigned short Address); +void M6502WriteMemIndex(unsigned short Address, unsigned char Data); +unsigned char M6502ReadOp(unsigned short Address); +unsigned char M6502ReadOpArg(unsigned short Address); + +void m6502_init(); +void m6502_reset(void); +void m6502_exit(void); +void m6502_get_context (void *dst); +void m6502_set_context (void *src); +int m6502_execute(int cycles); +void m6502_set_irq_line(int irqline, int state); +UINT32 m6502_get_pc(); + +void m65c02_init(); +void m65c02_reset(); +int m65c02_execute(int cycles); +void m65c02_set_irq_line(int irqline, int state); + +void m65sc02_init(); + +void n2a03_init(); +void n2a03_irq(void); // used for PSG!! + +void deco16_init(); +void deco16_reset(); +int deco16_execute(int cycles); +void deco16_set_irq_line(int irqline, int state); + +void m6510_init(); +void m6510_reset(void); + +/*enum +{ + CPUINFO_PTR_M6502_READINDEXED_CALLBACK = CPUINFO_PTR_CPU_SPECIFIC, + CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK, + CPUINFO_PTR_M6510_PORTREAD, + CPUINFO_PTR_M6510_PORTWRITE, + + CPUINFO_INT_M6510_PORT = CPUINFO_INT_CPU_SPECIFIC +};*/ + +//extern void m6502_get_info(UINT32 state, cpuinfo *info); + +//extern unsigned m6502_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +/**************************************************************************** + * The 6510 + ****************************************************************************/ +#if (HAS_M6510) +#define M6510_A M6502_A +#define M6510_X M6502_X +#define M6510_Y M6502_Y +#define M6510_S M6502_S +#define M6510_PC M6502_PC +#define M6510_P M6502_P +#define M6510_EA M6502_EA +#define M6510_ZP M6502_ZP +#define M6510_NMI_STATE M6502_NMI_STATE +#define M6510_IRQ_STATE M6502_IRQ_STATE + +#define M6510_IRQ_LINE M6502_IRQ_LINE + +//extern void m6510_get_info(UINT32 state, cpuinfo *info); + +//extern unsigned m6510_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +#endif + +#if (HAS_M6510T) +#define M6510T_A M6502_A +#define M6510T_X M6502_X +#define M6510T_Y M6502_Y +#define M6510T_S M6502_S +#define M6510T_PC M6502_PC +#define M6510T_P M6502_P +#define M6510T_EA M6502_EA +#define M6510T_ZP M6502_ZP +#define M6510T_NMI_STATE M6502_NMI_STATE +#define M6510T_IRQ_STATE M6502_IRQ_STATE + +#define M6510T_IRQ_LINE M6502_IRQ_LINE + +//extern void m6510t_get_info(UINT32 state, cpuinfo *info); + +#endif + +#if (HAS_M7501) +#define M7501_A M6502_A +#define M7501_X M6502_X +#define M7501_Y M6502_Y +#define M7501_S M6502_S +#define M7501_PC M6502_PC +#define M7501_P M6502_P +#define M7501_EA M6502_EA +#define M7501_ZP M6502_ZP +#define M7501_NMI_STATE M6502_NMI_STATE +#define M7501_IRQ_STATE M6502_IRQ_STATE + +#define M7501_IRQ_LINE M6502_IRQ_LINE + +//extern void m7501_get_info(UINT32 state, cpuinfo *info); +#endif + +#if (HAS_M8502) +#define M8502_A M6502_A +#define M8502_X M6502_X +#define M8502_Y M6502_Y +#define M8502_S M6502_S +#define M8502_PC M6502_PC +#define M8502_P M6502_P +#define M8502_EA M6502_EA +#define M8502_ZP M6502_ZP +#define M8502_NMI_STATE M6502_NMI_STATE +#define M8502_IRQ_STATE M6502_IRQ_STATE + +#define M8502_IRQ_LINE M6502_IRQ_LINE + +//extern void m8502_get_info(UINT32 state, cpuinfo *info); +#endif + + +/**************************************************************************** + * The 2A03 (NES 6502 without decimal mode ADC/SBC) + ****************************************************************************/ +#if (HAS_N2A03) +#define N2A03_A M6502_A +#define N2A03_X M6502_X +#define N2A03_Y M6502_Y +#define N2A03_S M6502_S +#define N2A03_PC M6502_PC +#define N2A03_P M6502_P +#define N2A03_EA M6502_EA +#define N2A03_ZP M6502_ZP +#define N2A03_NMI_STATE M6502_NMI_STATE +#define N2A03_IRQ_STATE M6502_IRQ_STATE + +#define N2A03_IRQ_LINE M6502_IRQ_LINE + +//extern void n2a03_get_info(UINT32 state, cpuinfo *info); + +#define N2A03_DEFAULTCLOCK (21477272.724 / 12) + +/* The N2A03 is integrally tied to its PSG (they're on the same die). + Bit 7 of address $4011 (the PSG's DPCM control register), when set, + causes an IRQ to be generated. This function allows the IRQ to be called + from the PSG core when such an occasion arises. */ +//extern void n2a03_irq(void); +#endif + + +/**************************************************************************** + * The 65C02 + ****************************************************************************/ +#if (HAS_M65C02) +#define M65C02_A M6502_A +#define M65C02_X M6502_X +#define M65C02_Y M6502_Y +#define M65C02_S M6502_S +#define M65C02_PC M6502_PC +#define M65C02_P M6502_P +#define M65C02_EA M6502_EA +#define M65C02_ZP M6502_ZP +#define M65C02_NMI_STATE M6502_NMI_STATE +#define M65C02_IRQ_STATE M6502_IRQ_STATE + +#define M65C02_IRQ_LINE M6502_IRQ_LINE + +//extern void m65c02_get_info(UINT32 state, cpuinfo *info); + +//extern unsigned m65c02_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +#endif + +/**************************************************************************** + * The 65SC02 + ****************************************************************************/ +#if (HAS_M65SC02) +#define M65SC02_A M6502_A +#define M65SC02_X M6502_X +#define M65SC02_Y M6502_Y +#define M65SC02_S M6502_S +#define M65SC02_PC M6502_PC +#define M65SC02_P M6502_P +#define M65SC02_EA M6502_EA +#define M65SC02_ZP M6502_ZP +#define M65SC02_NMI_STATE M6502_NMI_STATE +#define M65SC02_IRQ_STATE M6502_IRQ_STATE + +#define M65SC02_IRQ_LINE M6502_IRQ_LINE + +//extern void m65sc02_get_info(UINT32 state, cpuinfo *info); + +//extern unsigned m65sc02_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +#endif + +/**************************************************************************** + * The DECO CPU16 + ****************************************************************************/ +#if (HAS_DECO16) +#define DECO16_A M6502_A +#define DECO16_X M6502_X +#define DECO16_Y M6502_Y +#define DECO16_S M6502_S +#define DECO16_PC M6502_PC +#define DECO16_P M6502_P +#define DECO16_EA M6502_EA +#define DECO16_ZP M6502_ZP +#define DECO16_NMI_STATE M6502_NMI_STATE +#define DECO16_IRQ_STATE M6502_IRQ_STATE + +#define DECO16_IRQ_LINE M6502_IRQ_LINE + +//extern void deco16_get_info(UINT32 state, cpuinfo *info); +#endif + +//extern unsigned deco16_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +#endif /* __M6502_H__ */ diff --git a/src/cpu/m6502/ops02.h b/src/cpu/m6502/ops02.h new file mode 100644 index 00000000..db3c5232 --- /dev/null +++ b/src/cpu/m6502/ops02.h @@ -0,0 +1,813 @@ +/***************************************************************************** + * + * ops02.h + * Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs + * + * Copyright Juergen Buchmueller, all rights reserved. + * 65sc02 core Copyright Peter Trauner, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ + + +/* 6502 flags */ +#define F_C 0x01 +#define F_Z 0x02 +#define F_I 0x04 +#define F_D 0x08 +#define F_B 0x10 +#define F_T 0x20 +#define F_V 0x40 +#define F_N 0x80 + +/* some shortcuts for improved readability */ +#define A m6502.a +#define X m6502.x +#define Y m6502.y +#define P m6502.p +#define S m6502.sp.b.l +#define SPD m6502.sp.d + +#define NZ m6502.nz + +#define SET_NZ(n) \ + if ((n) == 0) P = (P & ~F_N) | F_Z; else P = (P & ~(F_N | F_Z)) | ((n) & F_N) + +#define SET_Z(n) \ + if ((n) == 0) P |= F_Z; else P &= ~F_Z + +#define EAL m6502.ea.b.l +#define EAH m6502.ea.b.h +#define EAW m6502.ea.w.l +#define EAD m6502.ea.d + +#define ZPL m6502.zp.b.l +#define ZPH m6502.zp.b.h +#define ZPW m6502.zp.w.l +#define ZPD m6502.zp.d + +#define PCL m6502.pc.b.l +#define PCH m6502.pc.b.h +#define PCW m6502.pc.w.l +#define PCD m6502.pc.d + +#define PPC m6502.ppc.d + +//#define RDMEM_ID(a) m6502.rdmem_id(Machine,a) +//#define WRMEM_ID(a,d) m6502.wrmem_id(Machine,a,d) + +#define RDMEM_ID(a) M6502ReadMemIndex(a) +#define WRMEM_ID(a,d) M6502WriteMemIndex(a, d) + +#define CHANGE_PC change_pc(PCD) + +/*************************************************************** + * RDOP read an opcode + ***************************************************************/ +//#define RDOP() cpu_readop(PCW++); m6502_ICount -= 1 +#define RDOP() M6502ReadOp(PCW++); m6502_ICount -= 1 + +/*************************************************************** + * RDOPARG read an opcode argument + ***************************************************************/ +//#define RDOPARG() cpu_readop_arg(PCW++); m6502_ICount -= 1 +#define RDOPARG() M6502ReadOpArg(PCW++); m6502_ICount -= 1 + +/*************************************************************** + * RDMEM read memory + ***************************************************************/ +//#define RDMEM(addr) program_read_byte_8le(addr); m6502_ICount -= 1 +#define RDMEM(addr) M6502ReadByte(addr); m6502_ICount -= 1 + +/*************************************************************** + * WRMEM write memory + ***************************************************************/ +//#define WRMEM(addr,data) program_write_byte_8le(addr,data); m6502_ICount -= 1 +#define WRMEM(addr,data) M6502WriteByte(addr, data); m6502_ICount -= 1 + +/*************************************************************** + * BRA branch relative + * extra cycle if page boundary is crossed + ***************************************************************/ +#define BRA(cond) \ + { \ + INT8 tmp2 = RDOPARG(); \ + if (cond) \ + { \ + RDMEM(PCW); \ + EAW = PCW + (signed char)tmp2; \ + if ( EAH != PCH ) { \ + RDMEM( (PCH << 8 ) | EAL) ; \ + } \ + PCD = EAD; \ + CHANGE_PC; \ + } \ + } + +/*************************************************************** + * + * Helper macros to build the effective address + * + ***************************************************************/ + +/*************************************************************** + * EA = zero page address + ***************************************************************/ +#define EA_ZPG \ + ZPL = RDOPARG(); \ + EAD = ZPD + +/*************************************************************** + * EA = zero page address + X + ***************************************************************/ +#define EA_ZPX \ + ZPL = RDOPARG(); \ + RDMEM(ZPD); \ + ZPL = X + ZPL; \ + EAD = ZPD + +/*************************************************************** + * EA = zero page address + Y + ***************************************************************/ +#define EA_ZPY \ + ZPL = RDOPARG(); \ + RDMEM(ZPD); \ + ZPL = Y + ZPL; \ + EAD = ZPD + +/*************************************************************** + * EA = absolute address + ***************************************************************/ +#define EA_ABS \ + EAL = RDOPARG(); \ + EAH = RDOPARG() + +/*************************************************************** + * EA = absolute address + X + * one additional read if page boundary is crossed + ***************************************************************/ +#define EA_ABX_P \ + EA_ABS; \ + if ( EAL + X > 0xff ) { \ + RDMEM( ( EAH << 8 ) | ( ( EAL + X ) & 0xff ) ); \ + } \ + EAW += X; + +/*************************************************************** + * EA = absolute address + X + ***************************************************************/ +#define EA_ABX_NP \ + EA_ABS; \ + RDMEM( ( EAH << 8 ) | ( ( EAL + X ) & 0xff ) ); \ + EAW += X + +/*************************************************************** + * EA = absolute address + Y + * one additional read if page boundary is crossed + ***************************************************************/ +#define EA_ABY_P \ + EA_ABS; \ + if ( EAL + Y > 0xff ) { \ + RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \ + } \ + EAW += Y; + +/*************************************************************** + * EA = absolute address + Y + ***************************************************************/ +#define EA_ABY_NP \ + EA_ABS; \ + RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \ + EAW += Y + +/*************************************************************** + * EA = zero page + X indirect (pre indexed) + ***************************************************************/ +#define EA_IDX \ + ZPL = RDOPARG(); \ + RDMEM(ZPD); \ + ZPL = ZPL + X; \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD) + +/*************************************************************** + * EA = zero page indirect + Y (post indexed) + * subtract 1 cycle if page boundary is crossed + ***************************************************************/ +#define EA_IDY_P \ + ZPL = RDOPARG(); \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD); \ + if (EAL + Y > 0xff) { \ + RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \ + } \ + EAW += Y; + +/*************************************************************** + * EA = zero page indirect + Y + ***************************************************************/ +#define EA_IDY_NP \ + ZPL = RDOPARG(); \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD); \ + RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \ + EAW += Y + +/*************************************************************** + * EA = zero page indirect (65c02 pre indexed w/o X) + ***************************************************************/ +#define EA_ZPI \ + ZPL = RDOPARG(); \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD) + +/*************************************************************** + * EA = indirect (only used by JMP) + ***************************************************************/ +#define EA_IND \ + EA_ABS; \ + tmp = RDMEM(EAD); \ + EAL++; /* booby trap: stay in same page! ;-) */ \ + EAH = RDMEM(EAD); \ + EAL = tmp + + +/* read a value into tmp */ +/* Base number of cycles taken for each mode (including reading of opcode): + RD_IMM 2 + RD_DUM 2 + RD_ACC 0 + RD_ZPG/WR_ZPG 3 + RD_ZPX/WR_ZPX 4 + RD_ZPY/WR_ZPY 4 + RD_ABS/WR_ABS 4 + RD_ABX_P 4/5 + RD_ABX_NP/WR_ABX_NP 5 + RD_ABY_P 4/5 + RD_ABY_NP/WR_ABY_NP 5 + RD_IDX/WR_IDX 6 + RD_IDY_P 5/6 + RD_IDY_NP/WR_IDY_NP 6 + RD_ZPI/WR_ZPI 5 + */ +#define RD_IMM tmp = RDOPARG() +#define RD_DUM RDMEM(PCW) +#define RD_ACC tmp = A +#define RD_ZPG EA_ZPG; tmp = RDMEM(EAD) +#define RD_ZPX EA_ZPX; tmp = RDMEM(EAD) +#define RD_ZPY EA_ZPY; tmp = RDMEM(EAD) +#define RD_ABS EA_ABS; tmp = RDMEM(EAD) +#define RD_ABX_P EA_ABX_P; tmp = RDMEM(EAD) +#define RD_ABX_NP EA_ABX_NP; tmp = RDMEM(EAD) +#define RD_ABY_P EA_ABY_P; tmp = RDMEM(EAD) +#define RD_ABY_NP EA_ABY_NP; tmp = RDMEM(EAD) +#define RD_IDX EA_IDX; tmp = RDMEM_ID(EAD); m6502_ICount -= 1 +#define RD_IDY_P EA_IDY_P; tmp = RDMEM_ID(EAD); m6502_ICount -= 1 +#define RD_IDY_NP EA_IDY_NP; tmp = RDMEM_ID(EAD); m6502_ICount -= 1 +#define RD_ZPI EA_ZPI; tmp = RDMEM(EAD) + +/* write a value from tmp */ +#define WR_ZPG EA_ZPG; WRMEM(EAD, tmp) +#define WR_ZPX EA_ZPX; WRMEM(EAD, tmp) +#define WR_ZPY EA_ZPY; WRMEM(EAD, tmp) +#define WR_ABS EA_ABS; WRMEM(EAD, tmp) +#define WR_ABX_NP EA_ABX_NP; WRMEM(EAD, tmp) +#define WR_ABY_NP EA_ABY_NP; WRMEM(EAD, tmp) +#define WR_IDX EA_IDX; WRMEM_ID(EAD, tmp); m6502_ICount -= 1 +#define WR_IDY_NP EA_IDY_NP; WRMEM_ID(EAD, tmp); m6502_ICount -= 1 +#define WR_ZPI EA_ZPI; WRMEM(EAD, tmp) + +/* dummy read from the last EA */ +#define RD_EA RDMEM(EAD) + +/* write back a value from tmp to the last EA */ +#define WB_ACC A = (UINT8)tmp; +#define WB_EA WRMEM(EAD, tmp) + +/*************************************************************** + *************************************************************** + * Macros to emulate the plain 6502 opcodes + *************************************************************** + ***************************************************************/ + +/*************************************************************** + * push a register onto the stack + ***************************************************************/ +#define PUSH(Rg) WRMEM(SPD, Rg); S-- + +/*************************************************************** + * pull a register from the stack + ***************************************************************/ +#define PULL(Rg) S++; Rg = RDMEM(SPD) + +/* 6502 ******************************************************** + * ADC Add with carry + ***************************************************************/ +#define ADC \ + if (P & F_D) { \ + int c = (P & F_C); \ + int lo = (A & 0x0f) + (tmp & 0x0f) + c; \ + int hi = (A & 0xf0) + (tmp & 0xf0); \ + P &= ~(F_V | F_C|F_N|F_Z); \ + if (!((lo+hi)&0xff)) P|=F_Z; \ + if (lo > 0x09) { \ + hi += 0x10; \ + lo += 0x06; \ + } \ + if (hi&0x80) P|=F_N; \ + if (~(A^tmp) & (A^hi) & F_N) \ + P |= F_V; \ + if (hi > 0x90) \ + hi += 0x60; \ + if (hi & 0xff00) \ + P |= F_C; \ + A = (lo & 0x0f) + (hi & 0xf0); \ + } else { \ + int c = (P & F_C); \ + int sum = A + tmp + c; \ + P &= ~(F_V | F_C); \ + if (~(A^tmp) & (A^sum) & F_N) \ + P |= F_V; \ + if (sum & 0xff00) \ + P |= F_C; \ + A = (UINT8) sum; \ + SET_NZ(A); \ + } + +/* 6502 ******************************************************** + * AND Logical and + ***************************************************************/ +#define AND \ + A = (UINT8)(A & tmp); \ + SET_NZ(A) + +/* 6502 ******************************************************** + * ASL Arithmetic shift left + ***************************************************************/ +#define ASL \ + P = (P & ~F_C) | ((tmp >> 7) & F_C); \ + tmp = (UINT8)(tmp << 1); \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * BCC Branch if carry clear + ***************************************************************/ +#define BCC BRA(!(P & F_C)) + +/* 6502 ******************************************************** + * BCS Branch if carry set + ***************************************************************/ +#define BCS BRA(P & F_C) + +/* 6502 ******************************************************** + * BEQ Branch if equal + ***************************************************************/ +#define BEQ BRA(P & F_Z) + +/* 6502 ******************************************************** + * BIT Bit test + ***************************************************************/ +#undef BIT +#define BIT \ + P &= ~(F_N|F_V|F_Z); \ + P |= tmp & (F_N|F_V); \ + if ((tmp & A) == 0) \ + P |= F_Z + +/* 6502 ******************************************************** + * BMI Branch if minus + ***************************************************************/ +#define BMI BRA(P & F_N) + +/* 6502 ******************************************************** + * BNE Branch if not equal + ***************************************************************/ +#define BNE BRA(!(P & F_Z)) + +/* 6502 ******************************************************** + * BPL Branch if plus + ***************************************************************/ +#define BPL BRA(!(P & F_N)) + +/* 6502 ******************************************************** + * BRK Break + * increment PC, push PC hi, PC lo, flags (with B bit set), + * set I flag, jump via IRQ vector + ***************************************************************/ +#define BRK \ + RDOPARG(); \ + PUSH(PCH); \ + PUSH(PCL); \ + PUSH(P | F_B); \ + P = (P | F_I); \ + PCL = RDMEM(M6502_IRQ_VEC); \ + PCH = RDMEM(M6502_IRQ_VEC+1); \ + CHANGE_PC + +/* 6502 ******************************************************** + * BVC Branch if overflow clear + ***************************************************************/ +#define BVC BRA(!(P & F_V)) + +/* 6502 ******************************************************** + * BVS Branch if overflow set + ***************************************************************/ +#define BVS BRA(P & F_V) + +/* 6502 ******************************************************** + * CLC Clear carry flag + ***************************************************************/ +#define CLC \ + P &= ~F_C + +/* 6502 ******************************************************** + * CLD Clear decimal flag + ***************************************************************/ +#define CLD \ + P &= ~F_D + +/* 6502 ******************************************************** + * CLI Clear interrupt flag + ***************************************************************/ +#define CLI \ + if ((m6502.irq_state != M6502_CLEAR_LINE) && (P & F_I)) { \ + m6502.after_cli = 1; \ + } \ + P &= ~F_I + +/* 6502 ******************************************************** + * CLV Clear overflow flag + ***************************************************************/ +#define CLV \ + P &= ~F_V + +/* 6502 ******************************************************** + * CMP Compare accumulator + ***************************************************************/ +#define CMP \ + P &= ~F_C; \ + if (A >= tmp) \ + P |= F_C; \ + SET_NZ((UINT8)(A - tmp)) + +/* 6502 ******************************************************** + * CPX Compare index X + ***************************************************************/ +#define CPX \ + P &= ~F_C; \ + if (X >= tmp) \ + P |= F_C; \ + SET_NZ((UINT8)(X - tmp)) + +/* 6502 ******************************************************** + * CPY Compare index Y + ***************************************************************/ +#define CPY \ + P &= ~F_C; \ + if (Y >= tmp) \ + P |= F_C; \ + SET_NZ((UINT8)(Y - tmp)) + +/* 6502 ******************************************************** + * DEC Decrement memory + ***************************************************************/ +#define DEC \ + tmp = (UINT8)(tmp-1); \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * DEX Decrement index X + ***************************************************************/ +#define DEX \ + X = (UINT8)(X-1); \ + SET_NZ(X) + +/* 6502 ******************************************************** + * DEY Decrement index Y + ***************************************************************/ +#define DEY \ + Y = (UINT8)(Y-1); \ + SET_NZ(Y) + +/* 6502 ******************************************************** + * EOR Logical exclusive or + ***************************************************************/ +#define EOR \ + A = (UINT8)(A ^ tmp); \ + SET_NZ(A) + +/* 6502 ******************************************************** + * ILL Illegal opcode + ***************************************************************/ +#define ILL +// logerror("M6502 illegal opcode %04x: %02x\n",(PCW-1)&0xffff, cpu_readop((PCW-1)&0xffff)) + +/* 6502 ******************************************************** + * INC Increment memory + ***************************************************************/ +#define INC \ + tmp = (UINT8)(tmp+1); \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * INX Increment index X + ***************************************************************/ +#define INX \ + X = (UINT8)(X+1); \ + SET_NZ(X) + +/* 6502 ******************************************************** + * INY Increment index Y + ***************************************************************/ +#define INY \ + Y = (UINT8)(Y+1); \ + SET_NZ(Y) + +/* 6502 ******************************************************** + * JMP Jump to address + * set PC to the effective address + ***************************************************************/ +#define JMP \ + if( EAD == PPC && !m6502.pending_irq && !m6502.after_cli ) \ + if( m6502_ICount > 0 ) m6502_ICount = 0; \ + PCD = EAD; \ + CHANGE_PC + +/* 6502 ******************************************************** + * JSR Jump to subroutine + * decrement PC (sic!) push PC hi, push PC lo and set + * PC to the effective address + ***************************************************************/ +#define JSR \ + EAL = RDOPARG(); \ + RDMEM(SPD); \ + PUSH(PCH); \ + PUSH(PCL); \ + EAH = RDOPARG(); \ + PCD = EAD; \ + CHANGE_PC + +/* 6502 ******************************************************** + * LDA Load accumulator + ***************************************************************/ +#define LDA \ + A = (UINT8)tmp; \ + SET_NZ(A) + +/* 6502 ******************************************************** + * LDX Load index X + ***************************************************************/ +#define LDX \ + X = (UINT8)tmp; \ + SET_NZ(X) + +/* 6502 ******************************************************** + * LDY Load index Y + ***************************************************************/ +#define LDY \ + Y = (UINT8)tmp; \ + SET_NZ(Y) + +/* 6502 ******************************************************** + * LSR Logic shift right + * 0 -> [7][6][5][4][3][2][1][0] -> C + ***************************************************************/ +#define LSR \ + P = (P & ~F_C) | (tmp & F_C); \ + tmp = (UINT8)tmp >> 1; \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * NOP No operation + ***************************************************************/ +#define NOP + +/* 6502 ******************************************************** + * ORA Logical inclusive or + ***************************************************************/ +#define ORA \ + A = (UINT8)(A | tmp); \ + SET_NZ(A) + +/* 6502 ******************************************************** + * PHA Push accumulator + ***************************************************************/ +#define PHA \ + PUSH(A) + +/* 6502 ******************************************************** + * PHP Push processor status (flags) + ***************************************************************/ +#define PHP \ + PUSH(P) + +/* 6502 ******************************************************** + * PLA Pull accumulator + ***************************************************************/ +#define PLA \ + RDMEM(SPD); \ + PULL(A); \ + SET_NZ(A) + + +/* 6502 ******************************************************** + * PLP Pull processor status (flags) + ***************************************************************/ +#define PLP \ + RDMEM(SPD); \ + if ( P & F_I ) { \ + PULL(P); \ + if ((m6502.irq_state != M6502_CLEAR_LINE) && !(P & F_I)) { \ + m6502.after_cli = 1; \ + } \ + } else { \ + PULL(P); \ + } \ + P |= (F_T|F_B); + +/* 6502 ******************************************************** + * ROL Rotate left + * new C <- [7][6][5][4][3][2][1][0] <- C + ***************************************************************/ +#define ROL \ + tmp = (tmp << 1) | (P & F_C); \ + P = (P & ~F_C) | ((tmp >> 8) & F_C); \ + tmp = (UINT8)tmp; \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * ROR Rotate right + * C -> [7][6][5][4][3][2][1][0] -> new C + ***************************************************************/ +#define ROR \ + tmp |= (P & F_C) << 8; \ + P = (P & ~F_C) | (tmp & F_C); \ + tmp = (UINT8)(tmp >> 1); \ + SET_NZ(tmp) + +/* 6502 ******************************************************** + * RTI Return from interrupt + * pull flags, pull PC lo, pull PC hi and increment PC + * PCW++; + ***************************************************************/ +#define RTI \ + RDOPARG(); \ + RDMEM(SPD); \ + PULL(P); \ + PULL(PCL); \ + PULL(PCH); \ + P |= F_T | F_B; \ + if( (m6502.irq_state != M6502_CLEAR_LINE) && !(P & F_I) ) \ + { \ + m6502.after_cli = 1; \ + } \ + CHANGE_PC + +/* 6502 ******************************************************** + * RTS Return from subroutine + * pull PC lo, PC hi and increment PC + ***************************************************************/ +#define RTS \ + RDOPARG(); \ + RDMEM(SPD); \ + PULL(PCL); \ + PULL(PCH); \ + RDMEM(PCW); PCW++; \ + CHANGE_PC + +/* 6502 ******************************************************** + * SBC Subtract with carry + ***************************************************************/ +#define SBC \ + if (P & F_D) \ + { \ + int c = (P & F_C) ^ F_C; \ + int sum = A - tmp - c; \ + int lo = (A & 0x0f) - (tmp & 0x0f) - c; \ + int hi = (A & 0xf0) - (tmp & 0xf0); \ + if (lo & 0x10) \ + { \ + lo -= 6; \ + hi--; \ + } \ + P &= ~(F_V | F_C|F_Z|F_N); \ + if( (A^tmp) & (A^sum) & F_N ) \ + P |= F_V; \ + if( hi & 0x0100 ) \ + hi -= 0x60; \ + if( (sum & 0xff00) == 0 ) \ + P |= F_C; \ + if( !((A-tmp-c) & 0xff) ) \ + P |= F_Z; \ + if( (A-tmp-c) & 0x80 ) \ + P |= F_N; \ + A = (lo & 0x0f) | (hi & 0xf0); \ + } \ + else \ + { \ + int c = (P & F_C) ^ F_C; \ + int sum = A - tmp - c; \ + P &= ~(F_V | F_C); \ + if( (A^tmp) & (A^sum) & F_N ) \ + P |= F_V; \ + if( (sum & 0xff00) == 0 ) \ + P |= F_C; \ + A = (UINT8) sum; \ + SET_NZ(A); \ + } + +/* 6502 ******************************************************** + * SEC Set carry flag + ***************************************************************/ +#if defined(SEC) +#undef SEC +#endif +#define SEC \ + P |= F_C + +/* 6502 ******************************************************** + * SED Set decimal flag + ***************************************************************/ +#define SED \ + P |= F_D + +/* 6502 ******************************************************** + * SEI Set interrupt flag + ***************************************************************/ +#define SEI \ + P |= F_I + +/* 6502 ******************************************************** + * STA Store accumulator + ***************************************************************/ +#define STA \ + tmp = A + +/* 6502 ******************************************************** + * STX Store index X + ***************************************************************/ +#define STX \ + tmp = X + +/* 6502 ******************************************************** + * STY Store index Y + ***************************************************************/ +#define STY \ + tmp = Y + +/* 6502 ******************************************************** + * TAX Transfer accumulator to index X + ***************************************************************/ +#define TAX \ + X = A; \ + SET_NZ(X) + +/* 6502 ******************************************************** + * TAY Transfer accumulator to index Y + ***************************************************************/ +#define TAY \ + Y = A; \ + SET_NZ(Y) + +/* 6502 ******************************************************** + * TSX Transfer stack LSB to index X + ***************************************************************/ +#define TSX \ + X = S; \ + SET_NZ(X) + +/* 6502 ******************************************************** + * TXA Transfer index X to accumulator + ***************************************************************/ +#define TXA \ + A = X; \ + SET_NZ(A) + +/* 6502 ******************************************************** + * TXS Transfer index X to stack LSB + * no flags changed (sic!) + ***************************************************************/ +#define TXS \ + S = X + +/* 6502 ******************************************************** + * TYA Transfer index Y to accumulator + ***************************************************************/ +#define TYA \ + A = Y; \ + SET_NZ(A) diff --git a/src/cpu/m6502/opsc02.h b/src/cpu/m6502/opsc02.h new file mode 100644 index 00000000..14c55b13 --- /dev/null +++ b/src/cpu/m6502/opsc02.h @@ -0,0 +1,363 @@ +/***************************************************************************** + * + * m6502ops.h + * Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs + * + * Copyright Juergen Buchmueller, all rights reserved. + * 65sc02 core Copyright Peter Trauner, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + *****************************************************************************/ + + +/*************************************************************** + *************************************************************** + * Macros to emulate the 65C02 opcodes + *************************************************************** + ***************************************************************/ + +/* 65C02 ******************************************************* + * EA = absolute address + X + * one additional read if page boundary is crossed + ***************************************************************/ +#define EA_ABX_C02_P \ + EA_ABS; \ + if ( EAL + X > 0xff ) { \ + RDMEM( PCW - 1 ); \ + } \ + EAW += X; + +/* 65C02 ******************************************************* + * EA = absolute address + X + ***************************************************************/ +#define EA_ABX_C02_NP \ + EA_ABS; \ + RDMEM( PCW - 1 ); \ + EAW += X; + +/*************************************************************** + * EA = absolute address + Y + * one additional read if page boundary is crossed + ***************************************************************/ +#define EA_ABY_C02_P \ + EA_ABS; \ + if ( EAL + Y > 0xff ) { \ + RDMEM( PCW - 1 ); \ + } \ + EAW += Y; + +/* 65C02 ******************************************************* + * EA = absolute address + Y + ***************************************************************/ +#define EA_ABY_C02_NP \ + EA_ABS; \ + RDMEM( PCW - 1 ); \ + EAW += Y + +/* 65C02 ******************************************************* + * EA = zero page indirect + Y (post indexed) + * subtract 1 cycle if page boundary is crossed + ***************************************************************/ +#define EA_IDY_C02_P \ + ZPL = RDOPARG(); \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD); \ + if (EAL + Y > 0xff) { \ + RDMEM( PCW - 1 ); \ + } \ + EAW += Y; + +/* 65C02 ******************************************************* + * EA = zero page indirect + Y + ***************************************************************/ +#define EA_IDY_C02_NP \ + ZPL = RDOPARG(); \ + EAL = RDMEM(ZPD); \ + ZPL++; \ + EAH = RDMEM(ZPD); \ + RDMEM( PCW - 1 ); \ + EAW += Y + +/* 65C02 ******************************************************* + * EA = indirect (only used by JMP) + * correct overflow handling + ***************************************************************/ +#define EA_IND_C02 \ + EA_ABS; \ + tmp = RDMEM(EAD); \ + RDMEM(PCW-1); \ + EAD++; \ + EAH = RDMEM(EAD); \ + EAL = tmp + +/* 65C02 ******************************************************* + * EA = indirect plus x (only used by 65c02 JMP) + ***************************************************************/ +#define EA_IAX \ + EA_ABS; \ + RDMEM( PCW - 1 ); \ + if (EAL + X > 0xff) { \ + RDMEM( PCW - 1 ); \ + } \ + EAW += X; \ + tmp = RDMEM(EAD); \ + EAD++; \ + EAH = RDMEM(EAD); \ + EAL = tmp + +/* read a value into tmp */ +/* Base number of cycles taken for each mode (including reading of opcode): + RD_ABX_C02_P 4/5 + RD_ABX_C02_NP/WR_ABX_C02_NP 5 + RD_ABY_C02_P 4/5 + RD_IDY_C02_P 5/6 + WR_IDY_C02_NP 6 + */ +#define RD_ABX_C02_P EA_ABX_C02_P; tmp = RDMEM(EAD) +#define RD_ABX_C02_NP EA_ABX_C02_NP; tmp = RDMEM(EAD) +#define RD_ABX_C02_NP_DISCARD EA_ABX_C02_NP; RDMEM(EAD) +#define RD_ABY_C02_P EA_ABY_C02_P; tmp = RDMEM(EAD) +#define RD_IDY_C02_P EA_IDY_C02_P; tmp = RDMEM_ID(EAD); m6502_ICount -= 1 + +#define WR_ABX_C02_NP EA_ABX_C02_NP; WRMEM(EAD, tmp) +#define WR_ABY_C02_NP EA_ABY_C02_NP; WRMEM(EAD, tmp) +#define WR_IDY_C02_NP EA_IDY_C02_NP; WRMEM_ID(EAD, tmp); m6502_ICount -= 1 + + +/* 65C02******************************************************** + * BRA branch relative + * extra cycle if page boundary is crossed + ***************************************************************/ +#define BRA_C02(cond) \ + tmp = RDOPARG(); \ + if (cond) \ + { \ + RDMEM(PCW); \ + EAW = PCW + (signed char)tmp; \ + if ( EAH != PCH ) { \ + RDMEM( PCW - 1 ); \ + } \ + PCD = EAD; \ + CHANGE_PC; \ + } + +/* 65C02 ******************************************************** + * ADC Add with carry + * different setting of flags in decimal mode + ***************************************************************/ +#define ADC_C02 \ + if (P & F_D) \ + { \ + int c = (P & F_C); \ + int lo = (A & 0x0f) + (tmp & 0x0f) + c; \ + int hi = (A & 0xf0) + (tmp & 0xf0); \ + P &= ~(F_V | F_C); \ + if( lo > 0x09 ) \ + { \ + hi += 0x10; \ + lo += 0x06; \ + } \ + if( ~(A^tmp) & (A^hi) & F_N ) \ + P |= F_V; \ + if( hi > 0x90 ) \ + hi += 0x60; \ + if( hi & 0xff00 ) \ + P |= F_C; \ + A = (lo & 0x0f) + (hi & 0xf0); \ + RDMEM( PCW - 1 ); \ + } \ + else \ + { \ + int c = (P & F_C); \ + int sum = A + tmp + c; \ + P &= ~(F_V | F_C); \ + if( ~(A^tmp) & (A^sum) & F_N ) \ + P |= F_V; \ + if( sum & 0xff00 ) \ + P |= F_C; \ + A = (UINT8) sum; \ + } \ + SET_NZ(A) + +/* 65C02 ******************************************************** + * SBC Subtract with carry + * different setting of flags in decimal mode + ***************************************************************/ +#define SBC_C02 \ + if (P & F_D) \ + { \ + int c = (P & F_C) ^ F_C; \ + int sum = A - tmp - c; \ + int lo = (A & 0x0f) - (tmp & 0x0f) - c; \ + int hi = (A & 0xf0) - (tmp & 0xf0); \ + P &= ~(F_V | F_C); \ + if( (A^tmp) & (A^sum) & F_N ) \ + P |= F_V; \ + if( lo & 0xf0 ) \ + lo -= 6; \ + if( lo & 0x80 ) \ + hi -= 0x10; \ + if( hi & 0x0f00 ) \ + hi -= 0x60; \ + if( (sum & 0xff00) == 0 ) \ + P |= F_C; \ + A = (lo & 0x0f) + (hi & 0xf0); \ + RDMEM( PCW - 1 ); \ + } \ + else \ + { \ + int c = (P & F_C) ^ F_C; \ + int sum = A - tmp - c; \ + P &= ~(F_V | F_C); \ + if( (A^tmp) & (A^sum) & F_N ) \ + P |= F_V; \ + if( (sum & 0xff00) == 0 ) \ + P |= F_C; \ + A = (UINT8) sum; \ + } \ + SET_NZ(A) + +/* 65C02 ******************************************************* + * BBR Branch if bit is reset + ***************************************************************/ +#define BBR(bit) \ + BRA(!(tmp & (1<reset(); +} + +void M6502NewFrame() +{ + for (INT32 i = 0; i < nM6502Count; i++) { + nM6502CyclesDone[i] = 0; + } + nM6502CyclesTotal = 0; +} + +INT32 M6502Init(INT32 cpu, INT32 type) +{ + nActiveCPU = cpu; + nM6502Count++; + + pCurrentCPU = &m6502CPUContext[cpu]; + + memset(pCurrentCPU, 0, sizeof(M6502Ext)); + + switch (type) + { + case TYPE_M6502: + case TYPE_M6504: + pCurrentCPU->execute = m6502_execute; + pCurrentCPU->reset = m6502_reset; + pCurrentCPU->init = m6502_init; + pCurrentCPU->set_irq_line = m6502_set_irq_line; + break; + + case TYPE_M65C02: + pCurrentCPU->execute = m65c02_execute; + pCurrentCPU->reset = m65c02_reset; + pCurrentCPU->init = m65c02_init; + pCurrentCPU->set_irq_line = m65c02_set_irq_line; + break; + + case TYPE_DECO16: + pCurrentCPU->execute = deco16_execute; + pCurrentCPU->reset = deco16_reset; + pCurrentCPU->init = deco16_init; + pCurrentCPU->set_irq_line = deco16_set_irq_line; + break; + + case TYPE_N2A03: + pCurrentCPU->execute = m6502_execute; + pCurrentCPU->reset = m6502_reset; + pCurrentCPU->init = n2a03_init; // different + pCurrentCPU->set_irq_line = m6502_set_irq_line; + break; + + case TYPE_M65SC02: + pCurrentCPU->execute = m65c02_execute; + pCurrentCPU->reset = m65c02_reset; + pCurrentCPU->init = m65sc02_init; // different + pCurrentCPU->set_irq_line = m65c02_set_irq_line; + break; + + case TYPE_M6510: + case TYPE_M6510T: + case TYPE_M7501: + case TYPE_M8502: + pCurrentCPU->execute = m6502_execute; + pCurrentCPU->reset = m6510_reset; // different + pCurrentCPU->init = m6510_init; // different + pCurrentCPU->set_irq_line = m6502_set_irq_line; + break; + } + + pCurrentCPU->ReadPort = M6502ReadPortDummyHandler; + pCurrentCPU->WritePort = M6502WritePortDummyHandler; + pCurrentCPU->ReadByte = M6502ReadByteDummyHandler; + pCurrentCPU->WriteByte = M6502WriteByteDummyHandler; + pCurrentCPU->ReadMemIndex = M6502ReadMemIndexDummyHandler; + pCurrentCPU->WriteMemIndex = M6502WriteMemIndexDummyHandler; + pCurrentCPU->ReadOp = M6502ReadOpDummyHandler; + pCurrentCPU->ReadOpArg = M6502ReadOpArgDummyHandler; + + nM6502CyclesDone[cpu] = 0; + + for (INT32 j = 0; j < (0x0100 * 3); j++) { + pCurrentCPU->pMemMap[j] = NULL; + } + + nM6502CyclesTotal = 0; + + pCurrentCPU->init(); + + CpuCheatRegister(0x0003, cpu); + + return 0; +} + +void M6502Exit() +{ + nM6502Count = 0; +} + +void M6502Open(INT32 num) +{ + nActiveCPU = num; + + pCurrentCPU = &m6502CPUContext[num]; + + m6502_set_context(&pCurrentCPU->reg); + + nM6502CyclesTotal = nM6502CyclesDone[nActiveCPU]; +} + +void M6502Close() +{ + m6502_get_context(&pCurrentCPU->reg); + + nM6502CyclesDone[nActiveCPU] = nM6502CyclesTotal; + + pCurrentCPU = NULL; // cause problems! + + nActiveCPU = -1; +} + +INT32 M6502GetActive() +{ + return nActiveCPU; +} + +void M6502SetIRQ(INT32 vector, INT32 status) +{ + if (status == M6502_IRQSTATUS_NONE) { + pCurrentCPU->set_irq_line(vector, 0); + } + + if (status == M6502_IRQSTATUS_ACK) { + pCurrentCPU->set_irq_line(vector, 1); + } + + if (status == M6502_IRQSTATUS_AUTO) { + pCurrentCPU->set_irq_line(vector, 1); + pCurrentCPU->execute(0); + pCurrentCPU->set_irq_line(vector, 0); + pCurrentCPU->execute(0); + } +} + +INT32 M6502Run(INT32 cycles) +{ + cycles = pCurrentCPU->execute(cycles); + + nM6502CyclesTotal += cycles; + + return cycles; +} + +void M6502RunEnd() +{ + +} + +INT32 M6502MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = pCurrentCPU->pMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + if (nType & M6502_READ) { + pMemMap[0 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6502_WRITE) { + pMemMap[0x100 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6502_FETCH) { + pMemMap[0x200 + i] = pMemory + ((i - cStart) << 8); + } + } + return 0; + +} + +void M6502SetReadPortHandler(UINT8 (*pHandler)(UINT16)) +{ + pCurrentCPU->ReadPort = pHandler; +} + +void M6502SetWritePortHandler(void (*pHandler)(UINT16, UINT8)) +{ + pCurrentCPU->WritePort = pHandler; +} + +void M6502SetReadByteHandler(UINT8 (*pHandler)(UINT16)) +{ + pCurrentCPU->ReadByte = pHandler; +} + +void M6502SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)) +{ + pCurrentCPU->WriteByte = pHandler; +} + +void M6502SetReadMemIndexHandler(UINT8 (*pHandler)(UINT16)) +{ + pCurrentCPU->ReadMemIndex = pHandler; +} + +void M6502SetWriteMemIndexHandler(void (*pHandler)(UINT16, UINT8)) +{ + pCurrentCPU->WriteMemIndex = pHandler; +} + +void M6502SetReadOpHandler(UINT8 (*pHandler)(UINT16)) +{ + pCurrentCPU->ReadOp = pHandler; +} + +void M6502SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)) +{ + pCurrentCPU->ReadOpArg = pHandler; +} + +UINT8 M6502ReadPort(UINT16 Address) +{ + // check handler + if (pCurrentCPU->ReadPort != NULL) { + return pCurrentCPU->ReadPort(Address); + } + + return 0; +} + +void M6502WritePort(UINT16 Address, UINT8 Data) +{ + // check handler + if (pCurrentCPU->WritePort != NULL) { + pCurrentCPU->WritePort(Address, Data); + return; + } +} + +UINT8 M6502ReadByte(UINT16 Address) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (pCurrentCPU->ReadByte != NULL) { + return pCurrentCPU->ReadByte(Address); + } + + return 0; +} + +void M6502WriteByte(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x100 | (Address >> 8)]; + if (pr != NULL) { + pr[Address & 0xff] = Data; + return; + } + + // check handler + if (pCurrentCPU->WriteByte != NULL) { + pCurrentCPU->WriteByte(Address, Data); + return; + } +} + +UINT8 M6502ReadMemIndex(UINT16 Address) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (pCurrentCPU->ReadMemIndex != NULL) { + return pCurrentCPU->ReadMemIndex(Address); + } + + return 0; +} + +void M6502WriteMemIndex(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x100 | (Address >> 8)]; + if (pr != NULL) { + pr[Address & 0xff] = Data; + return; + } + + // check handler + if (pCurrentCPU->WriteMemIndex != NULL) { + pCurrentCPU->WriteMemIndex(Address, Data); + return; + } +} + +UINT8 M6502ReadOp(UINT16 Address) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (pCurrentCPU->ReadOp != NULL) { + return pCurrentCPU->ReadOp(Address); + } + + return 0; +} + +UINT8 M6502ReadOpArg(UINT16 Address) +{ + // check mem map + UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (pCurrentCPU->ReadOpArg != NULL) { + return pCurrentCPU->ReadOpArg(Address); + } + + return 0; +} + +void M6502WriteRom(UINT16 Address, UINT8 Data) +{ + UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)]; + UINT8 * pw = pCurrentCPU->pMemMap[0x100 | (Address >> 8)]; + UINT8 * pf = pCurrentCPU->pMemMap[0x200 | (Address >> 8)]; + + if (pr != NULL) { + pr[Address & 0xff] = Data; + } + + if (pw != NULL) { + pw[Address & 0xff] = Data; + } + + if (pf != NULL) { + pf[Address & 0xff] = Data; + } + + // check handler + if (pCurrentCPU->WriteByte != NULL) { + pCurrentCPU->WriteByte(Address, Data); + return; + } +} + +UINT32 M6502GetPC() +{ + return m6502_get_pc(); +} + +INT32 M6502Scan(INT32 nAction) +{ + struct BurnArea ba; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + for (INT32 i = 0; i < nM6502Count; i++) { + + M6502Ext *ptr = &m6502CPUContext[i]; + + INT32 (*Callback)(INT32 irqline); + + Callback = ptr->reg.irq_callback; + + char szName[] = "M6502 #n"; + szName[7] = '0' + i; + + ba.Data = &m6502CPUContext[i].reg; + ba.nLen = sizeof(m6502CPUContext[i].reg); + ba.szName = szName; + BurnAcb(&ba); + + // necessary? + SCAN_VAR(ptr->nCyclesTotal); + SCAN_VAR(ptr->nCyclesSegment); + SCAN_VAR(ptr->nCyclesLeft); + + ptr->reg.irq_callback = Callback; + } + + return 0; +} diff --git a/src/cpu/m6502_intf.h b/src/cpu/m6502_intf.h new file mode 100644 index 00000000..b67f212d --- /dev/null +++ b/src/cpu/m6502_intf.h @@ -0,0 +1,93 @@ +#include "m6502.h" + +typedef UINT8 (*pReadPortHandler)(UINT16 a); +typedef void (*pWritePortHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadByteHandler)(UINT16 a); +typedef void (*pWriteByteHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadMemIndexHandler)(UINT16 a); +typedef void (*pWriteMemIndexHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadOpHandler)(UINT16 a); +typedef UINT8 (*pReadOpArgHandler)(UINT16 a); + +struct M6502Ext { + + m6502_Regs reg; + + INT32 (*execute)(INT32 cycles); + void (*reset)(); + void (*init)(); + void (*set_irq_line)(INT32 irqline, INT32 state); + + UINT8* pMemMap[0x100 * 3]; + + pReadPortHandler ReadPort; + pWritePortHandler WritePort; + pReadByteHandler ReadByte; + pWriteByteHandler WriteByte; + pReadMemIndexHandler ReadMemIndex; + pWriteMemIndexHandler WriteMemIndex; + pReadOpHandler ReadOp; + pReadOpArgHandler ReadOpArg; + + INT32 nCyclesTotal; + INT32 nCyclesSegment; + INT32 nCyclesLeft; +}; + +#define M6502_IRQSTATUS_NONE 0 +#define M6502_IRQSTATUS_ACK 1 +#define M6502_IRQSTATUS_AUTO 2 + +#define M6502_READ 1 +#define M6502_WRITE 2 +#define M6502_FETCH 4 + +#define M6502_RAM (M6502_READ | M6502_WRITE | M6502_FETCH) +#define M6502_ROM (M6502_READ | M6502_FETCH) + +extern INT32 nM6502Count; + +extern INT32 nM6502CyclesTotal; + +void M6502Reset(); +void M6502NewFrame(); + +void n2a03_irq(void); // USED FOR PSG!! + +// use these at addresses 0 and 1 for M6510, M6510T, M7501, M8502 map! +UINT8 m6510_read_0000(UINT16 offset); +void m6510_write_0000(UINT16 address, UINT8 data); + +// The M6504 only has 13 address bits! use address mirroring! + +enum { TYPE_M6502=0, TYPE_M6504, TYPE_M65C02, TYPE_M65SC02, TYPE_N2A03, TYPE_DECO16, +// these are the same! + TYPE_M6510, TYPE_M6510T, TYPE_M7501, TYPE_M8502 }; + +INT32 M6502Init(INT32 cpu, INT32 type); // if you're using more than one type +void M6502Exit(); +void M6502Open(INT32 num); +void M6502Close(); +INT32 M6502GetActive(); +void M6502SetIRQ(INT32 vector, INT32 status); +INT32 M6502Run(INT32 cycles); +void M6502RunEnd(); +INT32 M6502MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType); +void M6502SetReadPortHandler(UINT8 (*pHandler)(UINT16)); +void M6502SetWritePortHandler(void (*pHandler)(UINT16, UINT8)); +void M6502SetReadByteHandler(UINT8 (*pHandler)(UINT16)); +void M6502SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)); +void M6502SetReadMemIndexHandler(UINT8 (*pHandler)(UINT16)); +void M6502SetWriteMemIndexHandler(void (*pHandler)(UINT16, UINT8)); +void M6502SetReadOpHandler(UINT8 (*pHandler)(UINT16)); +void M6502SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)); +INT32 M6502Scan(INT32 nAction); + +UINT32 M6502GetPC(); + +void M6502WriteRom(UINT16 Address, UINT8 Data); + +inline static INT32 M6502TotalCycles() +{ + return nM6502CyclesTotal; +} diff --git a/src/cpu/m6800/6800ops.c b/src/cpu/m6800/6800ops.c new file mode 100644 index 00000000..80a754e6 --- /dev/null +++ b/src/cpu/m6800/6800ops.c @@ -0,0 +1,2142 @@ + +/* + +HNZVC + +? = undefined +* = affected +- = unaffected +0 = cleared +1 = set +# = ccr directly affected by instruction +@ = special - carry set if bit 7 is set + +*/ + +//M6800_INLINE void illegal( void ) +static void illegal( void ) +{ +// logerror("M6808: illegal opcode: address %04X, op %02X\n",PC,(int) M_RDOP_ARG(PC)&0xFF); +} + +/* HD63701 only */ +#if (HAS_HD63701) +//M6800_INLINE void trap( void ) +static void trap( void ) +{ +// logerror("M6808: illegal opcode: address %04X, op %02X\n",PC,(int) M_RDOP_ARG(PC)&0xFF); + TAKE_TRAP; +} +#endif + +/* $00 ILLEGAL */ + +/* $01 NOP */ +M6800_INLINE void nop( void ) +{ +} + +/* $02 ILLEGAL */ + +/* $03 ILLEGAL */ + +/* $04 LSRD inherent -0*-* */ +M6800_INLINE void lsrd (void) +{ + UINT16 t; + CLR_NZC; t = D; CC|=(t&0x0001); + t>>=1; SET_Z16(t); D=t; +} + +/* $05 ASLD inherent ?**** */ +M6800_INLINE void asld (void) +{ + int r; + UINT16 t; + t = D; r=t<<1; + CLR_NZVC; SET_FLAGS16(t,t,r); + D=r; +} + +/* $06 TAP inherent ##### */ +M6800_INLINE void tap (void) +{ + CC=A; + ONE_MORE_INSN(); + CHECK_IRQ_LINES(); /* HJB 990417 */ +} + +/* $07 TPA inherent ----- */ +M6800_INLINE void tpa (void) +{ + A=CC; +} + +/* $08 INX inherent --*-- */ +M6800_INLINE void inx (void) +{ + ++X; + CLR_Z; SET_Z16(X); +} + +/* $09 DEX inherent --*-- */ +M6800_INLINE void dex (void) +{ + --X; + CLR_Z; SET_Z16(X); +} + +/* $0a CLV */ +M6800_INLINE void clv (void) +{ + CLV; +} + +/* $0b SEV */ +M6800_INLINE void sev (void) +{ + SEV; +} + +/* $0c CLC */ +M6800_INLINE void clc (void) +{ + CLC; +} + +/* $0d SEC */ +M6800_INLINE void sec (void) +{ + SEC; +} + +/* $0e CLI */ +M6800_INLINE void cli (void) +{ + CLI; + ONE_MORE_INSN(); + CHECK_IRQ_LINES(); /* HJB 990417 */ +} + +/* $0f SEI */ +M6800_INLINE void sei (void) +{ + SEI; + ONE_MORE_INSN(); + CHECK_IRQ_LINES(); /* HJB 990417 */ +} + +/* $10 SBA inherent -**** */ +M6800_INLINE void sba (void) +{ + UINT16 t; + t=A-B; + CLR_NZVC; SET_FLAGS8(A,B,t); + A=t; +} + +/* $11 CBA inherent -**** */ +M6800_INLINE void cba (void) +{ + UINT16 t; + t=A-B; + CLR_NZVC; SET_FLAGS8(A,B,t); +} + +/* $12 ILLEGAL */ +M6800_INLINE void undoc1 (void) +{ + X += RM( S + 1 ); +} + +/* $13 ILLEGAL */ +M6800_INLINE void undoc2 (void) +{ + X += RM( S + 1 ); +} + + +/* $14 ILLEGAL */ + +/* $15 ILLEGAL */ + +/* $16 TAB inherent -**0- */ +M6800_INLINE void tab (void) +{ + B=A; + CLR_NZV; SET_NZ8(B); +} + +/* $17 TBA inherent -**0- */ +M6800_INLINE void tba (void) +{ + A=B; + CLR_NZV; SET_NZ8(A); +} + +/* $18 XGDX inherent ----- */ /* HD63701YO only */ +M6800_INLINE void xgdx( void ) +{ + UINT16 t = X; + X = D; + D=t; +} + +/* $19 DAA inherent (A) -**0* */ +M6800_INLINE void daa( void ) +{ + UINT8 msn, lsn; + UINT16 t, cf = 0; + msn=A & 0xf0; lsn=A & 0x0f; + if( lsn>0x09 || CC&0x20 ) cf |= 0x06; + if( msn>0x80 && lsn>0x09 ) cf |= 0x60; + if( msn>0x90 || CC&0x01 ) cf |= 0x60; + t = cf + A; + CLR_NZV; /* keep carry from previous operation */ + SET_NZ8((UINT8)t); SET_C8(t); + A = t; +} + +/* $1a ILLEGAL */ + +#if (HAS_HD63701) +/* $1a SLP */ /* HD63701YO only */ +M6800_INLINE void slp (void) +{ + /* wait for next IRQ (same as waiting of wai) */ + m6808.wai_state |= HD63701_SLP; + EAT_CYCLES; +} +#endif + +/* $1b ABA inherent ***** */ +M6800_INLINE void aba (void) +{ + UINT16 t; + t=A+B; + CLR_HNZVC; SET_FLAGS8(A,B,t); SET_H(A,B,t); + A=t; +} + +/* $1c ILLEGAL */ + +/* $1d ILLEGAL */ + +/* $1e ILLEGAL */ + +/* $1f ILLEGAL */ + +/* $20 BRA relative ----- */ +M6800_INLINE void bra( void ) +{ + UINT8 t; + IMMBYTE(t);PC+=SIGNED(t);CHANGE_PC(); + /* speed up busy loops */ + if (t==0xfe) EAT_CYCLES; +} + +/* $21 BRN relative ----- */ +M6800_INLINE void brn( void ) +{ + UINT8 t; + IMMBYTE(t); +} + +/* $22 BHI relative ----- */ +M6800_INLINE void bhi( void ) +{ + UINT8 t; + BRANCH(!(CC&0x05)); +} + +/* $23 BLS relative ----- */ +M6800_INLINE void bls( void ) +{ + UINT8 t; + BRANCH(CC&0x05); +} + +/* $24 BCC relative ----- */ +M6800_INLINE void bcc( void ) +{ + UINT8 t; + BRANCH(!(CC&0x01)); +} + +/* $25 BCS relative ----- */ +M6800_INLINE void bcs( void ) +{ + UINT8 t; + BRANCH(CC&0x01); +} + +/* $26 BNE relative ----- */ +M6800_INLINE void bne( void ) +{ + UINT8 t; + BRANCH(!(CC&0x04)); +} + +/* $27 BEQ relative ----- */ +M6800_INLINE void beq( void ) +{ + UINT8 t; + BRANCH(CC&0x04); +} + +/* $28 BVC relative ----- */ +M6800_INLINE void bvc( void ) +{ + UINT8 t; + BRANCH(!(CC&0x02)); +} + +/* $29 BVS relative ----- */ +M6800_INLINE void bvs( void ) +{ + UINT8 t; + BRANCH(CC&0x02); +} + +/* $2a BPL relative ----- */ +M6800_INLINE void bpl( void ) +{ + UINT8 t; + BRANCH(!(CC&0x08)); +} + +/* $2b BMI relative ----- */ +M6800_INLINE void bmi( void ) +{ + UINT8 t; + BRANCH(CC&0x08); +} + +/* $2c BGE relative ----- */ +M6800_INLINE void bge( void ) +{ + UINT8 t; + BRANCH(!NXORV); +} + +/* $2d BLT relative ----- */ +M6800_INLINE void blt( void ) +{ + UINT8 t; + BRANCH(NXORV); +} + +/* $2e BGT relative ----- */ +M6800_INLINE void bgt( void ) +{ + UINT8 t; + BRANCH(!(NXORV||CC&0x04)); +} + +/* $2f BLE relative ----- */ +M6800_INLINE void ble( void ) +{ + UINT8 t; + BRANCH(NXORV||CC&0x04); +} + +/* $30 TSX inherent ----- */ +M6800_INLINE void tsx (void) +{ + X = ( S + 1 ); +} + +/* $31 INS inherent ----- */ +M6800_INLINE void ins (void) +{ + ++S; +} + +/* $32 PULA inherent ----- */ +M6800_INLINE void pula (void) +{ + PULLBYTE(m6808.d.b.h); +} + +/* $33 PULB inherent ----- */ +M6800_INLINE void pulb (void) +{ + PULLBYTE(m6808.d.b.l); +} + +/* $34 DES inherent ----- */ +M6800_INLINE void des (void) +{ + --S; +} + +/* $35 TXS inherent ----- */ +M6800_INLINE void txs (void) +{ + S = ( X - 1 ); +} + +/* $36 PSHA inherent ----- */ +M6800_INLINE void psha (void) +{ + PUSHBYTE(m6808.d.b.h); +} + +/* $37 PSHB inherent ----- */ +M6800_INLINE void pshb (void) +{ + PUSHBYTE(m6808.d.b.l); +} + +/* $38 PULX inherent ----- */ +M6800_INLINE void pulx (void) +{ + PULLWORD(pX); +} + +/* $39 RTS inherent ----- */ +M6800_INLINE void rts( void ) +{ + PULLWORD(pPC); + CHANGE_PC(); +} + +/* $3a ABX inherent ----- */ +M6800_INLINE void abx( void ) +{ + X += B; +} + +/* $3b RTI inherent ##### */ +M6800_INLINE void rti( void ) +{ + PULLBYTE(CC); + PULLBYTE(B); + PULLBYTE(A); + PULLWORD(pX); + PULLWORD(pPC); + CHANGE_PC(); + CHECK_IRQ_LINES(); /* HJB 990417 */ +} + +/* $3c PSHX inherent ----- */ +M6800_INLINE void pshx (void) +{ + PUSHWORD(pX); +} + +/* $3d MUL inherent --*-@ */ +M6800_INLINE void mul( void ) +{ + UINT16 t; + t=A*B; + CLR_C; if(t&0x80) SEC; + D=t; +} + +/* $3e WAI inherent ----- */ +M6800_INLINE void wai( void ) +{ + /* + * WAI stacks the entire machine state on the + * hardware stack, then waits for an interrupt. + */ + m6808.wai_state |= M6800_WAI; + PUSHWORD(pPC); + PUSHWORD(pX); + PUSHBYTE(A); + PUSHBYTE(B); + PUSHBYTE(CC); + CHECK_IRQ_LINES(); + if (m6808.wai_state & M6800_WAI) EAT_CYCLES; +} + +/* $3f SWI absolute indirect ----- */ +M6800_INLINE void swi( void ) +{ + PUSHWORD(pPC); + PUSHWORD(pX); + PUSHBYTE(A); + PUSHBYTE(B); + PUSHBYTE(CC); + SEI; + PCD = RM16(0xfffa); + CHANGE_PC(); +} + +/* $40 NEGA inherent ?**** */ +M6800_INLINE void nega( void ) +{ + UINT16 r; + r=-A; + CLR_NZVC; SET_FLAGS8(0,A,r); + A=r; +} + +/* $41 ILLEGAL */ + +/* $42 ILLEGAL */ + +/* $43 COMA inherent -**01 */ +M6800_INLINE void coma( void ) +{ + A = ~A; + CLR_NZV; SET_NZ8(A); SEC; +} + +/* $44 LSRA inherent -0*-* */ +M6800_INLINE void lsra( void ) +{ + CLR_NZC; CC|=(A&0x01); + A>>=1; SET_Z8(A); +} + +/* $45 ILLEGAL */ + +/* $46 RORA inherent -**-* */ +M6800_INLINE void rora( void ) +{ + UINT8 r; + r=(CC&0x01)<<7; + CLR_NZC; CC|=(A&0x01); + r |= A>>1; SET_NZ8(r); + A=r; +} + +/* $47 ASRA inherent ?**-* */ +M6800_INLINE void asra( void ) +{ + CLR_NZC; CC|=(A&0x01); + A>>=1; A|=((A&0x40)<<1); + SET_NZ8(A); +} + +/* $48 ASLA inherent ?**** */ +M6800_INLINE void asla( void ) +{ + UINT16 r; + r=A<<1; + CLR_NZVC; SET_FLAGS8(A,A,r); + A=r; +} + +/* $49 ROLA inherent -**** */ +M6800_INLINE void rola( void ) +{ + UINT16 t,r; + t = A; r = CC&0x01; r |= t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + A=r; +} + +/* $4a DECA inherent -***- */ +M6800_INLINE void deca( void ) +{ + --A; + CLR_NZV; SET_FLAGS8D(A); +} + +/* $4b ILLEGAL */ + +/* $4c INCA inherent -***- */ +M6800_INLINE void inca( void ) +{ + ++A; + CLR_NZV; SET_FLAGS8I(A); +} + +/* $4d TSTA inherent -**0- */ +M6800_INLINE void tsta( void ) +{ + CLR_NZVC; SET_NZ8(A); +} + +/* $4e ILLEGAL */ + +/* $4f CLRA inherent -0100 */ +M6800_INLINE void clra( void ) +{ + A=0; + CLR_NZVC; SEZ; +} + +/* $50 NEGB inherent ?**** */ +M6800_INLINE void negb( void ) +{ + UINT16 r; + r=-B; + CLR_NZVC; SET_FLAGS8(0,B,r); + B=r; +} + +/* $51 ILLEGAL */ + +/* $52 ILLEGAL */ + +/* $53 COMB inherent -**01 */ +M6800_INLINE void comb( void ) +{ + B = ~B; + CLR_NZV; SET_NZ8(B); SEC; +} + +/* $54 LSRB inherent -0*-* */ +M6800_INLINE void lsrb( void ) +{ + CLR_NZC; CC|=(B&0x01); + B>>=1; SET_Z8(B); +} + +/* $55 ILLEGAL */ + +/* $56 RORB inherent -**-* */ +M6800_INLINE void rorb( void ) +{ + UINT8 r; + r=(CC&0x01)<<7; + CLR_NZC; CC|=(B&0x01); + r |= B>>1; SET_NZ8(r); + B=r; +} + +/* $57 ASRB inherent ?**-* */ +M6800_INLINE void asrb( void ) +{ + CLR_NZC; CC|=(B&0x01); + B>>=1; B|=((B&0x40)<<1); + SET_NZ8(B); +} + +/* $58 ASLB inherent ?**** */ +M6800_INLINE void aslb( void ) +{ + UINT16 r; + r=B<<1; + CLR_NZVC; SET_FLAGS8(B,B,r); + B=r; +} + +/* $59 ROLB inherent -**** */ +M6800_INLINE void rolb( void ) +{ + UINT16 t,r; + t = B; r = CC&0x01; r |= t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + B=r; +} + +/* $5a DECB inherent -***- */ +M6800_INLINE void decb( void ) +{ + --B; + CLR_NZV; SET_FLAGS8D(B); +} + +/* $5b ILLEGAL */ + +/* $5c INCB inherent -***- */ +M6800_INLINE void incb( void ) +{ + ++B; + CLR_NZV; SET_FLAGS8I(B); +} + +/* $5d TSTB inherent -**0- */ +M6800_INLINE void tstb( void ) +{ + CLR_NZVC; SET_NZ8(B); +} + +/* $5e ILLEGAL */ + +/* $5f CLRB inherent -0100 */ +M6800_INLINE void clrb( void ) +{ + B=0; + CLR_NZVC; SEZ; +} + +/* $60 NEG indexed ?**** */ +M6800_INLINE void neg_ix( void ) +{ + UINT16 r,t; + IDXBYTE(t); r=-t; + CLR_NZVC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $61 AIM --**0- */ /* HD63701YO only */ +M6800_INLINE void aim_ix( void ) +{ + UINT8 t, r; + IMMBYTE(t); + IDXBYTE(r); + r &= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $62 OIM --**0- */ /* HD63701YO only */ +M6800_INLINE void oim_ix( void ) +{ + UINT8 t, r; + IMMBYTE(t); + IDXBYTE(r); + r |= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $63 COM indexed -**01 */ +M6800_INLINE void com_ix( void ) +{ + UINT8 t; + IDXBYTE(t); t = ~t; + CLR_NZV; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $64 LSR indexed -0*-* */ +M6800_INLINE void lsr_ix( void ) +{ + UINT8 t; + IDXBYTE(t); CLR_NZC; CC|=(t&0x01); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $65 EIM --**0- */ /* HD63701YO only */ +M6800_INLINE void eim_ix( void ) +{ + UINT8 t, r; + IMMBYTE(t); + IDXBYTE(r); + r ^= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $66 ROR indexed -**-* */ +M6800_INLINE void ror_ix( void ) +{ + UINT8 t,r; + IDXBYTE(t); r=(CC&0x01)<<7; + CLR_NZC; CC|=(t&0x01); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $67 ASR indexed ?**-* */ +M6800_INLINE void asr_ix( void ) +{ + UINT8 t; + IDXBYTE(t); CLR_NZC; CC|=(t&0x01); + t>>=1; t|=((t&0x40)<<1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $68 ASL indexed ?**** */ +M6800_INLINE void asl_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r=t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $69 ROL indexed -**** */ +M6800_INLINE void rol_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = CC&0x01; r |= t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $6a DEC indexed -***- */ +M6800_INLINE void dec_ix( void ) +{ + UINT8 t; + IDXBYTE(t); --t; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $6b TIM --**0- */ /* HD63701YO only */ +M6800_INLINE void tim_ix( void ) +{ + UINT8 t, r; + IMMBYTE(t); + IDXBYTE(r); + r &= t; + CLR_NZV; SET_NZ8(r); +} + +/* $6c INC indexed -***- */ +M6800_INLINE void inc_ix( void ) +{ + UINT8 t; + IDXBYTE(t); ++t; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $6d TST indexed -**0- */ +M6800_INLINE void tst_ix( void ) +{ + UINT8 t; + IDXBYTE(t); CLR_NZVC; SET_NZ8(t); +} + +/* $6e JMP indexed ----- */ +M6800_INLINE void jmp_ix( void ) +{ + INDEXED; PC=EA; CHANGE_PC(); +} + +/* $6f CLR indexed -0100 */ +M6800_INLINE void clr_ix( void ) +{ + INDEXED; WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $70 NEG extended ?**** */ +M6800_INLINE void neg_ex( void ) +{ + UINT16 r,t; + EXTBYTE(t); r=-t; + CLR_NZVC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $71 AIM --**0- */ /* HD63701YO only */ +M6800_INLINE void aim_di( void ) +{ + UINT8 t, r; + IMMBYTE(t); + DIRBYTE(r); + r &= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $72 OIM --**0- */ /* HD63701YO only */ +M6800_INLINE void oim_di( void ) +{ + UINT8 t, r; + IMMBYTE(t); + DIRBYTE(r); + r |= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $73 COM extended -**01 */ +M6800_INLINE void com_ex( void ) +{ + UINT8 t; + EXTBYTE(t); t = ~t; + CLR_NZV; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $74 LSR extended -0*-* */ +M6800_INLINE void lsr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + CLR_NZC; + CC|=(t&0x01); + t>>=1; + SET_Z8(t); + WM(EAD,t); +} + +/* $75 EIM --**0- */ /* HD63701YO only */ +M6800_INLINE void eim_di( void ) +{ + UINT8 t, r; + IMMBYTE(t); + DIRBYTE(r); + r ^= t; + CLR_NZV; SET_NZ8(r); + WM(EAD,r); +} + +/* $76 ROR extended -**-* */ +M6800_INLINE void ror_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); r=(CC&0x01)<<7; + CLR_NZC; CC|=(t&0x01); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $77 ASR extended ?**-* */ +M6800_INLINE void asr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC|=(t&0x01); + t>>=1; t|=((t&0x40)<<1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $78 ASL extended ?**** */ +M6800_INLINE void asl_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r=t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $79 ROL extended -**** */ +M6800_INLINE void rol_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = CC&0x01; r |= t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $7a DEC extended -***- */ +M6800_INLINE void dec_ex( void ) +{ + UINT8 t; + EXTBYTE(t); --t; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $7b TIM --**0- */ /* HD63701YO only */ +M6800_INLINE void tim_di( void ) +{ + UINT8 t, r; + IMMBYTE(t); + DIRBYTE(r); + r &= t; + CLR_NZV; SET_NZ8(r); +} + +/* $7c INC extended -***- */ +M6800_INLINE void inc_ex( void ) +{ + UINT8 t; + EXTBYTE(t); ++t; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $7d TST extended -**0- */ +M6800_INLINE void tst_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZVC; SET_NZ8(t); +} + +/* $7e JMP extended ----- */ +M6800_INLINE void jmp_ex( void ) +{ + EXTENDED; PC=EA; CHANGE_PC(); /* TS 971002 */ +} + +/* $7f CLR extended -0100 */ +M6800_INLINE void clr_ex( void ) +{ + EXTENDED; WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $80 SUBA immediate ?**** */ +M6800_INLINE void suba_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $81 CMPA immediate ?**** */ +M6800_INLINE void cmpa_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); +} + +/* $82 SBCA immediate ?**** */ +M6800_INLINE void sbca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = A-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $83 SUBD immediate -**** */ +M6800_INLINE void subd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $84 ANDA immediate -**0- */ +M6800_INLINE void anda_im( void ) +{ + UINT8 t; + IMMBYTE(t); A &= t; + CLR_NZV; SET_NZ8(A); +} + +/* $85 BITA immediate -**0- */ +M6800_INLINE void bita_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); r = A&t; + CLR_NZV; SET_NZ8(r); +} + +/* $86 LDA immediate -**0- */ +M6800_INLINE void lda_im( void ) +{ + IMMBYTE(A); + CLR_NZV; SET_NZ8(A); +} + +/* is this a legal instruction? */ +/* $87 STA immediate -**0- */ +M6800_INLINE void sta_im( void ) +{ + CLR_NZV; SET_NZ8(A); + IMM8; WM(EAD,A); +} + +/* $88 EORA immediate -**0- */ +M6800_INLINE void eora_im( void ) +{ + UINT8 t; + IMMBYTE(t); A ^= t; + CLR_NZV; SET_NZ8(A); +} + +/* $89 ADCA immediate ***** */ +M6800_INLINE void adca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = A+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $8a ORA immediate -**0- */ +M6800_INLINE void ora_im( void ) +{ + UINT8 t; + IMMBYTE(t); A |= t; + CLR_NZV; SET_NZ8(A); +} + +/* $8b ADDA immediate ***** */ +M6800_INLINE void adda_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = A+t; + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $8c CMPX immediate -***- */ +M6800_INLINE void cmpx_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = X; + r = d - b.d; + CLR_NZV; + SET_NZ16(r); SET_V16(d,b.d,r); +} + +/* $8c CPX immediate -**** (6803) */ +M6800_INLINE void cpx_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; SET_FLAGS16(d,b.d,r); +} + + +/* $8d BSR ----- */ +M6800_INLINE void bsr( void ) +{ + UINT8 t; + IMMBYTE(t); + PUSHWORD(pPC); + PC += SIGNED(t); + CHANGE_PC(); /* TS 971002 */ +} + +/* $8e LDS immediate -**0- */ +M6800_INLINE void lds_im( void ) +{ + IMMWORD(m6808.s); + CLR_NZV; + SET_NZ16(S); +} + +/* $8f STS immediate -**0- */ +M6800_INLINE void sts_im( void ) +{ + CLR_NZV; + SET_NZ16(S); + IMM16; + WM16(EAD,&m6808.s); +} + +/* $90 SUBA direct ?**** */ +M6800_INLINE void suba_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $91 CMPA direct ?**** */ +M6800_INLINE void cmpa_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); +} + +/* $92 SBCA direct ?**** */ +M6800_INLINE void sbca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = A-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $93 SUBD direct -**** */ +M6800_INLINE void subd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D=r; +} + +/* $94 ANDA direct -**0- */ +M6800_INLINE void anda_di( void ) +{ + UINT8 t; + DIRBYTE(t); A &= t; + CLR_NZV; SET_NZ8(A); +} + +/* $95 BITA direct -**0- */ +M6800_INLINE void bita_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); r = A&t; + CLR_NZV; SET_NZ8(r); +} + +/* $96 LDA direct -**0- */ +M6800_INLINE void lda_di( void ) +{ + DIRBYTE(A); + CLR_NZV; SET_NZ8(A); +} + +/* $97 STA direct -**0- */ +M6800_INLINE void sta_di( void ) +{ + CLR_NZV; SET_NZ8(A); + DIRECT; WM(EAD,A); +} + +/* $98 EORA direct -**0- */ +M6800_INLINE void eora_di( void ) +{ + UINT8 t; + DIRBYTE(t); A ^= t; + CLR_NZV; SET_NZ8(A); +} + +/* $99 ADCA direct ***** */ +M6800_INLINE void adca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = A+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $9a ORA direct -**0- */ +M6800_INLINE void ora_di( void ) +{ + UINT8 t; + DIRBYTE(t); A |= t; + CLR_NZV; SET_NZ8(A); +} + +/* $9b ADDA direct ***** */ +M6800_INLINE void adda_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = A+t; + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $9c CMPX direct -***- */ +M6800_INLINE void cmpx_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = X; + r = d - b.d; + CLR_NZV; + SET_NZ16(r); SET_V16(d,b.d,r); +} + +/* $9c CPX direct -**** (6803) */ +M6800_INLINE void cpx_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; SET_FLAGS16(d,b.d,r); +} + +/* $9d JSR direct ----- */ +M6800_INLINE void jsr_di( void ) +{ + DIRECT; + PUSHWORD(pPC); + PC = EA; + CHANGE_PC(); +} + +/* $9e LDS direct -**0- */ +M6800_INLINE void lds_di( void ) +{ + DIRWORD(m6808.s); + CLR_NZV; + SET_NZ16(S); +} + +/* $9f STS direct -**0- */ +M6800_INLINE void sts_di( void ) +{ + CLR_NZV; + SET_NZ16(S); + DIRECT; + WM16(EAD,&m6808.s); +} + +/* $a0 SUBA indexed ?**** */ +M6800_INLINE void suba_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $a1 CMPA indexed ?**** */ +M6800_INLINE void cmpa_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); +} + +/* $a2 SBCA indexed ?**** */ +M6800_INLINE void sbca_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = A-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $a3 SUBD indexed -**** */ +M6800_INLINE void subd_ix( void ) +{ + UINT32 r,d; + PAIR b; + IDXWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $a4 ANDA indexed -**0- */ +M6800_INLINE void anda_ix( void ) +{ + UINT8 t; + IDXBYTE(t); A &= t; + CLR_NZV; SET_NZ8(A); +} + +/* $a5 BITA indexed -**0- */ +M6800_INLINE void bita_ix( void ) +{ + UINT8 t,r; + IDXBYTE(t); r = A&t; + CLR_NZV; SET_NZ8(r); +} + +/* $a6 LDA indexed -**0- */ +M6800_INLINE void lda_ix( void ) +{ + IDXBYTE(A); + CLR_NZV; SET_NZ8(A); +} + +/* $a7 STA indexed -**0- */ +M6800_INLINE void sta_ix( void ) +{ + CLR_NZV; SET_NZ8(A); + INDEXED; WM(EAD,A); +} + +/* $a8 EORA indexed -**0- */ +M6800_INLINE void eora_ix( void ) +{ + UINT8 t; + IDXBYTE(t); A ^= t; + CLR_NZV; SET_NZ8(A); +} + +/* $a9 ADCA indexed ***** */ +M6800_INLINE void adca_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = A+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $aa ORA indexed -**0- */ +M6800_INLINE void ora_ix( void ) +{ + UINT8 t; + IDXBYTE(t); A |= t; + CLR_NZV; SET_NZ8(A); +} + +/* $ab ADDA indexed ***** */ +M6800_INLINE void adda_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = A+t; + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $ac CMPX indexed -***- */ +M6800_INLINE void cmpx_ix( void ) +{ + UINT32 r,d; + PAIR b; + IDXWORD(b); + d = X; + r = d - b.d; + CLR_NZV; + SET_NZ16(r); SET_V16(d,b.d,r); +} + +/* $ac CPX indexed -**** (6803)*/ +M6800_INLINE void cpx_ix( void ) +{ + UINT32 r,d; + PAIR b; + IDXWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; SET_FLAGS16(d,b.d,r); +} + +/* $ad JSR indexed ----- */ +M6800_INLINE void jsr_ix( void ) +{ + INDEXED; + PUSHWORD(pPC); + PC = EA; + CHANGE_PC(); +} + +/* $ae LDS indexed -**0- */ +M6800_INLINE void lds_ix( void ) +{ + IDXWORD(m6808.s); + CLR_NZV; + SET_NZ16(S); +} + +/* $af STS indexed -**0- */ +M6800_INLINE void sts_ix( void ) +{ + CLR_NZV; + SET_NZ16(S); + INDEXED; + WM16(EAD,&m6808.s); +} + +/* $b0 SUBA extended ?**** */ +M6800_INLINE void suba_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $b1 CMPA extended ?**** */ +M6800_INLINE void cmpa_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = A-t; + CLR_NZVC; SET_FLAGS8(A,t,r); +} + +/* $b2 SBCA extended ?**** */ +M6800_INLINE void sbca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = A-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(A,t,r); + A = r; +} + +/* $b3 SUBD extended -**** */ +M6800_INLINE void subd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D=r; +} + +/* $b4 ANDA extended -**0- */ +M6800_INLINE void anda_ex( void ) +{ + UINT8 t; + EXTBYTE(t); A &= t; + CLR_NZV; SET_NZ8(A); +} + +/* $b5 BITA extended -**0- */ +M6800_INLINE void bita_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); r = A&t; + CLR_NZV; SET_NZ8(r); +} + +/* $b6 LDA extended -**0- */ +M6800_INLINE void lda_ex( void ) +{ + EXTBYTE(A); + CLR_NZV; SET_NZ8(A); +} + +/* $b7 STA extended -**0- */ +M6800_INLINE void sta_ex( void ) +{ + CLR_NZV; SET_NZ8(A); + EXTENDED; WM(EAD,A); +} + +/* $b8 EORA extended -**0- */ +M6800_INLINE void eora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); A ^= t; + CLR_NZV; SET_NZ8(A); +} + +/* $b9 ADCA extended ***** */ +M6800_INLINE void adca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = A+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $ba ORA extended -**0- */ +M6800_INLINE void ora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); A |= t; + CLR_NZV; SET_NZ8(A); +} + +/* $bb ADDA extended ***** */ +M6800_INLINE void adda_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = A+t; + CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r); + A = r; +} + +/* $bc CMPX extended -***- */ +M6800_INLINE void cmpx_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = X; + r = d - b.d; + CLR_NZV; + SET_NZ16(r); SET_V16(d,b.d,r); +} + +/* $bc CPX extended -**** (6803) */ +M6800_INLINE void cpx_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; SET_FLAGS16(d,b.d,r); +} + +/* $bd JSR extended ----- */ +M6800_INLINE void jsr_ex( void ) +{ + EXTENDED; + PUSHWORD(pPC); + PC = EA; + CHANGE_PC(); +} + +/* $be LDS extended -**0- */ +M6800_INLINE void lds_ex( void ) +{ + EXTWORD(m6808.s); + CLR_NZV; + SET_NZ16(S); +} + +/* $bf STS extended -**0- */ +M6800_INLINE void sts_ex( void ) +{ + CLR_NZV; + SET_NZ16(S); + EXTENDED; + WM16(EAD,&m6808.s); +} + +/* $c0 SUBB immediate ?**** */ +M6800_INLINE void subb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $c1 CMPB immediate ?**** */ +M6800_INLINE void cmpb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $c2 SBCB immediate ?**** */ +M6800_INLINE void sbcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = B-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $c3 ADDD immediate -**** */ +M6800_INLINE void addd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $c4 ANDB immediate -**0- */ +M6800_INLINE void andb_im( void ) +{ + UINT8 t; + IMMBYTE(t); B &= t; + CLR_NZV; SET_NZ8(B); +} + +/* $c5 BITB immediate -**0- */ +M6800_INLINE void bitb_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); r = B&t; + CLR_NZV; SET_NZ8(r); +} + +/* $c6 LDB immediate -**0- */ +M6800_INLINE void ldb_im( void ) +{ + IMMBYTE(B); + CLR_NZV; SET_NZ8(B); +} + +/* is this a legal instruction? */ +/* $c7 STB immediate -**0- */ +M6800_INLINE void stb_im( void ) +{ + CLR_NZV; SET_NZ8(B); + IMM8; WM(EAD,B); +} + +/* $c8 EORB immediate -**0- */ +M6800_INLINE void eorb_im( void ) +{ + UINT8 t; + IMMBYTE(t); B ^= t; + CLR_NZV; SET_NZ8(B); +} + +/* $c9 ADCB immediate ***** */ +M6800_INLINE void adcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = B+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $ca ORB immediate -**0- */ +M6800_INLINE void orb_im( void ) +{ + UINT8 t; + IMMBYTE(t); B |= t; + CLR_NZV; SET_NZ8(B); +} + +/* $cb ADDB immediate ***** */ +M6800_INLINE void addb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = B+t; + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $CC LDD immediate -**0- */ +M6800_INLINE void ldd_im( void ) +{ + IMMWORD(m6808.d); + CLR_NZV; + SET_NZ16(D); +} + +/* is this a legal instruction? */ +/* $cd STD immediate -**0- */ +M6800_INLINE void std_im( void ) +{ + IMM16; + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&m6808.d); +} + +/* $ce LDX immediate -**0- */ +M6800_INLINE void ldx_im( void ) +{ + IMMWORD(m6808.x); + CLR_NZV; + SET_NZ16(X); +} + +/* $cf STX immediate -**0- */ +M6800_INLINE void stx_im( void ) +{ + CLR_NZV; + SET_NZ16(X); + IMM16; + WM16(EAD,&m6808.x); +} + +/* $d0 SUBB direct ?**** */ +M6800_INLINE void subb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $d1 CMPB direct ?**** */ +M6800_INLINE void cmpb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $d2 SBCB direct ?**** */ +M6800_INLINE void sbcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = B-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $d3 ADDD direct -**** */ +M6800_INLINE void addd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $d4 ANDB direct -**0- */ +M6800_INLINE void andb_di( void ) +{ + UINT8 t; + DIRBYTE(t); B &= t; + CLR_NZV; SET_NZ8(B); +} + +/* $d5 BITB direct -**0- */ +M6800_INLINE void bitb_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); r = B&t; + CLR_NZV; SET_NZ8(r); +} + +/* $d6 LDB direct -**0- */ +M6800_INLINE void ldb_di( void ) +{ + DIRBYTE(B); + CLR_NZV; SET_NZ8(B); +} + +/* $d7 STB direct -**0- */ +M6800_INLINE void stb_di( void ) +{ + CLR_NZV; SET_NZ8(B); + DIRECT; WM(EAD,B); +} + +/* $d8 EORB direct -**0- */ +M6800_INLINE void eorb_di( void ) +{ + UINT8 t; + DIRBYTE(t); B ^= t; + CLR_NZV; SET_NZ8(B); +} + +/* $d9 ADCB direct ***** */ +M6800_INLINE void adcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = B+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $da ORB direct -**0- */ +M6800_INLINE void orb_di( void ) +{ + UINT8 t; + DIRBYTE(t); B |= t; + CLR_NZV; SET_NZ8(B); +} + +/* $db ADDB direct ***** */ +M6800_INLINE void addb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); r = B+t; + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $dc LDD direct -**0- */ +M6800_INLINE void ldd_di( void ) +{ + DIRWORD(m6808.d); + CLR_NZV; + SET_NZ16(D); +} + +/* $dd STD direct -**0- */ +M6800_INLINE void std_di( void ) +{ + DIRECT; + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&m6808.d); +} + +/* $de LDX direct -**0- */ +M6800_INLINE void ldx_di( void ) +{ + DIRWORD(m6808.x); + CLR_NZV; + SET_NZ16(X); +} + +/* $dF STX direct -**0- */ +M6800_INLINE void stx_di( void ) +{ + CLR_NZV; + SET_NZ16(X); + DIRECT; + WM16(EAD,&m6808.x); +} + +/* $e0 SUBB indexed ?**** */ +M6800_INLINE void subb_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $e1 CMPB indexed ?**** */ +M6800_INLINE void cmpb_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $e2 SBCB indexed ?**** */ +M6800_INLINE void sbcb_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = B-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $e3 ADDD indexed -**** */ +M6800_INLINE void addd_ix( void ) +{ + UINT32 r,d; + PAIR b; + IDXWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $e4 ANDB indexed -**0- */ +M6800_INLINE void andb_ix( void ) +{ + UINT8 t; + IDXBYTE(t); B &= t; + CLR_NZV; SET_NZ8(B); +} + +/* $e5 BITB indexed -**0- */ +M6800_INLINE void bitb_ix( void ) +{ + UINT8 t,r; + IDXBYTE(t); r = B&t; + CLR_NZV; SET_NZ8(r); +} + +/* $e6 LDB indexed -**0- */ +M6800_INLINE void ldb_ix( void ) +{ + IDXBYTE(B); + CLR_NZV; SET_NZ8(B); +} + +/* $e7 STB indexed -**0- */ +M6800_INLINE void stb_ix( void ) +{ + CLR_NZV; SET_NZ8(B); + INDEXED; WM(EAD,B); +} + +/* $e8 EORB indexed -**0- */ +M6800_INLINE void eorb_ix( void ) +{ + UINT8 t; + IDXBYTE(t); B ^= t; + CLR_NZV; SET_NZ8(B); +} + +/* $e9 ADCB indexed ***** */ +M6800_INLINE void adcb_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = B+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $ea ORB indexed -**0- */ +M6800_INLINE void orb_ix( void ) +{ + UINT8 t; + IDXBYTE(t); B |= t; + CLR_NZV; SET_NZ8(B); +} + +/* $eb ADDB indexed ***** */ +M6800_INLINE void addb_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); r = B+t; + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $ec LDD indexed -**0- */ +M6800_INLINE void ldd_ix( void ) +{ + IDXWORD(m6808.d); + CLR_NZV; + SET_NZ16(D); +} + +#if 0 +/* $ec ADCX immediate -**** NSC8105 only. Flags are a guess - copied from addb_im() */ +M6800_INLINE void adcx_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); r = X+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(X,t,r); SET_H(X,t,r); + X = r; +} +#endif + +/* $ed STD indexed -**0- */ +M6800_INLINE void std_ix( void ) +{ + INDEXED; + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&m6808.d); +} + +/* $ee LDX indexed -**0- */ +M6800_INLINE void ldx_ix( void ) +{ + IDXWORD(m6808.x); + CLR_NZV; + SET_NZ16(X); +} + +/* $ef STX indexed -**0- */ +M6800_INLINE void stx_ix( void ) +{ + CLR_NZV; + SET_NZ16(X); + INDEXED; + WM16(EAD,&m6808.x); +} + +/* $f0 SUBB extended ?**** */ +M6800_INLINE void subb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $f1 CMPB extended ?**** */ +M6800_INLINE void cmpb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = B-t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $f2 SBCB extended ?**** */ +M6800_INLINE void sbcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = B-t-(CC&0x01); + CLR_NZVC; SET_FLAGS8(B,t,r); + B = r; +} + +/* $f3 ADDD extended -**** */ +M6800_INLINE void addd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $f4 ANDB extended -**0- */ +M6800_INLINE void andb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $f5 BITB extended -**0- */ +M6800_INLINE void bitb_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $f6 LDB extended -**0- */ +M6800_INLINE void ldb_ex( void ) +{ + EXTBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $f7 STB extended -**0- */ +M6800_INLINE void stb_ex( void ) +{ + CLR_NZV; SET_NZ8(B); + EXTENDED; WM(EAD,B); +} + +/* $f8 EORB extended -**0- */ +M6800_INLINE void eorb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); B ^= t; + CLR_NZV; SET_NZ8(B); +} + +/* $f9 ADCB extended ***** */ +M6800_INLINE void adcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = B+t+(CC&0x01); + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $fa ORB extended -**0- */ +M6800_INLINE void orb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); B |= t; + CLR_NZV; SET_NZ8(B); +} + +/* $fb ADDB extended ***** */ +M6800_INLINE void addb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = B+t; + CLR_HNZVC; SET_FLAGS8(B,t,r); SET_H(B,t,r); + B = r; +} + +/* $fc LDD extended -**0- */ +M6800_INLINE void ldd_ex( void ) +{ + EXTWORD(m6808.d); + CLR_NZV; + SET_NZ16(D); +} + +/* $fc ADDX extended -**** NSC8105 only. Flags are a guess */ +M6800_INLINE void addx_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = X; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + X = r; +} + +/* $fd STD extended -**0- */ +M6800_INLINE void std_ex( void ) +{ + EXTENDED; + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&m6808.d); +} + +/* $fe LDX extended -**0- */ +M6800_INLINE void ldx_ex( void ) +{ + EXTWORD(m6808.x); + CLR_NZV; + SET_NZ16(X); +} + +/* $ff STX extended -**0- */ +M6800_INLINE void stx_ex( void ) +{ + CLR_NZV; + SET_NZ16(X); + EXTENDED; + WM16(EAD,&m6808.x); +} diff --git a/src/cpu/m6800/6800tbl.c b/src/cpu/m6800/6800tbl.c new file mode 100644 index 00000000..ef75792e --- /dev/null +++ b/src/cpu/m6800/6800tbl.c @@ -0,0 +1,398 @@ +M6800_INLINE void aba(void); +M6800_INLINE void abx(void); +M6800_INLINE void adca_di(void); +M6800_INLINE void adca_ex(void); +M6800_INLINE void adca_im(void); +M6800_INLINE void adca_ix(void); +M6800_INLINE void adcb_di(void); +M6800_INLINE void adcb_ex(void); +M6800_INLINE void adcb_im(void); +M6800_INLINE void adcb_ix(void); +//M6800_INLINE void adcx_im(void); +M6800_INLINE void adda_di(void); +M6800_INLINE void adda_ex(void); +M6800_INLINE void adda_im(void); +M6800_INLINE void adda_ix(void); +M6800_INLINE void addb_di(void); +M6800_INLINE void addb_ex(void); +M6800_INLINE void addb_im(void); +M6800_INLINE void addb_ix(void); +M6800_INLINE void addd_di(void); +M6800_INLINE void addd_ex(void); +M6800_INLINE void addx_ex(void); +M6800_INLINE void addd_im(void); +M6800_INLINE void addd_ix(void); +M6800_INLINE void aim_di(void); +M6800_INLINE void aim_ix(void); +M6800_INLINE void anda_di(void); +M6800_INLINE void anda_ex(void); +M6800_INLINE void anda_im(void); +M6800_INLINE void anda_ix(void); +M6800_INLINE void andb_di(void); +M6800_INLINE void andb_ex(void); +M6800_INLINE void andb_im(void); +M6800_INLINE void andb_ix(void); +M6800_INLINE void asl_ex(void); +M6800_INLINE void asl_ix(void); +M6800_INLINE void asla(void); +M6800_INLINE void aslb(void); +M6800_INLINE void asld(void); +M6800_INLINE void asr_ex(void); +M6800_INLINE void asr_ix(void); +M6800_INLINE void asra(void); +M6800_INLINE void asrb(void); +M6800_INLINE void bcc(void); +M6800_INLINE void bcs(void); +M6800_INLINE void beq(void); +M6800_INLINE void bge(void); +M6800_INLINE void bgt(void); +M6800_INLINE void bhi(void); +M6800_INLINE void bita_di(void); +M6800_INLINE void bita_ex(void); +M6800_INLINE void bita_im(void); +M6800_INLINE void bita_ix(void); +M6800_INLINE void bitb_di(void); +M6800_INLINE void bitb_ex(void); +M6800_INLINE void bitb_im(void); +M6800_INLINE void bitb_ix(void); +M6800_INLINE void ble(void); +M6800_INLINE void bls(void); +M6800_INLINE void blt(void); +M6800_INLINE void bmi(void); +M6800_INLINE void bne(void); +M6800_INLINE void bpl(void); +M6800_INLINE void bra(void); +M6800_INLINE void brn(void); +M6800_INLINE void bsr(void); +M6800_INLINE void bvc(void); +M6800_INLINE void bvs(void); +M6800_INLINE void cba(void); +M6800_INLINE void clc(void); +M6800_INLINE void cli(void); +M6800_INLINE void clr_ex(void); +M6800_INLINE void clr_ix(void); +M6800_INLINE void clra(void); +M6800_INLINE void clrb(void); +M6800_INLINE void clv(void); +M6800_INLINE void cmpa_di(void); +M6800_INLINE void cmpa_ex(void); +M6800_INLINE void cmpa_im(void); +M6800_INLINE void cmpa_ix(void); +M6800_INLINE void cmpb_di(void); +M6800_INLINE void cmpb_ex(void); +M6800_INLINE void cmpb_im(void); +M6800_INLINE void cmpb_ix(void); +M6800_INLINE void cmpx_di(void); +M6800_INLINE void cmpx_ex(void); +M6800_INLINE void cmpx_im(void); +M6800_INLINE void cmpx_ix(void); +M6800_INLINE void com_ex(void); +M6800_INLINE void com_ix(void); +M6800_INLINE void coma(void); +M6800_INLINE void comb(void); +M6800_INLINE void daa(void); +M6800_INLINE void dec_ex(void); +M6800_INLINE void dec_ix(void); +M6800_INLINE void deca(void); +M6800_INLINE void decb(void); +M6800_INLINE void des(void); +M6800_INLINE void dex(void); +M6800_INLINE void eim_di(void); +M6800_INLINE void eim_ix(void); +M6800_INLINE void eora_di(void); +M6800_INLINE void eora_ex(void); +M6800_INLINE void eora_im(void); +M6800_INLINE void eora_ix(void); +M6800_INLINE void eorb_di(void); +M6800_INLINE void eorb_ex(void); +M6800_INLINE void eorb_im(void); +M6800_INLINE void eorb_ix(void); +//M6800_INLINE void illegal(void); +static void illegal(void); +M6800_INLINE void inc_ex(void); +M6800_INLINE void inc_ix(void); +M6800_INLINE void inca(void); +M6800_INLINE void incb(void); +M6800_INLINE void ins(void); +M6800_INLINE void inx(void); +M6800_INLINE void jmp_ex(void); +M6800_INLINE void jmp_ix(void); +M6800_INLINE void jsr_di(void); +M6800_INLINE void jsr_ex(void); +M6800_INLINE void jsr_ix(void); +M6800_INLINE void lda_di(void); +M6800_INLINE void lda_ex(void); +M6800_INLINE void lda_im(void); +M6800_INLINE void lda_ix(void); +M6800_INLINE void ldb_di(void); +M6800_INLINE void ldb_ex(void); +M6800_INLINE void ldb_im(void); +M6800_INLINE void ldb_ix(void); +M6800_INLINE void ldd_di(void); +M6800_INLINE void ldd_ex(void); +M6800_INLINE void ldd_im(void); +M6800_INLINE void ldd_ix(void); +M6800_INLINE void lds_di(void); +M6800_INLINE void lds_ex(void); +M6800_INLINE void lds_im(void); +M6800_INLINE void lds_ix(void); +M6800_INLINE void ldx_di(void); +M6800_INLINE void ldx_ex(void); +M6800_INLINE void ldx_im(void); +M6800_INLINE void ldx_ix(void); +M6800_INLINE void lsr_ex(void); +M6800_INLINE void lsr_ix(void); +M6800_INLINE void lsra(void); +M6800_INLINE void lsrb(void); +M6800_INLINE void lsrd(void); +M6800_INLINE void mul(void); +M6800_INLINE void neg_ex(void); +M6800_INLINE void neg_ix(void); +M6800_INLINE void nega(void); +M6800_INLINE void negb(void); +M6800_INLINE void nop(void); +M6800_INLINE void oim_di(void); +M6800_INLINE void oim_ix(void); +M6800_INLINE void ora_di(void); +M6800_INLINE void ora_ex(void); +M6800_INLINE void ora_im(void); +M6800_INLINE void ora_ix(void); +M6800_INLINE void orb_di(void); +M6800_INLINE void orb_ex(void); +M6800_INLINE void orb_im(void); +M6800_INLINE void orb_ix(void); +M6800_INLINE void psha(void); +M6800_INLINE void pshb(void); +M6800_INLINE void pshx(void); +M6800_INLINE void pula(void); +M6800_INLINE void pulb(void); +M6800_INLINE void pulx(void); +M6800_INLINE void rol_ex(void); +M6800_INLINE void rol_ix(void); +M6800_INLINE void rola(void); +M6800_INLINE void rolb(void); +M6800_INLINE void ror_ex(void); +M6800_INLINE void ror_ix(void); +M6800_INLINE void rora(void); +M6800_INLINE void rorb(void); +M6800_INLINE void rti(void); +M6800_INLINE void rts(void); +M6800_INLINE void sba(void); +M6800_INLINE void sbca_di(void); +M6800_INLINE void sbca_ex(void); +M6800_INLINE void sbca_im(void); +M6800_INLINE void sbca_ix(void); +M6800_INLINE void sbcb_di(void); +M6800_INLINE void sbcb_ex(void); +M6800_INLINE void sbcb_im(void); +M6800_INLINE void sbcb_ix(void); +M6800_INLINE void sec(void); +M6800_INLINE void sei(void); +M6800_INLINE void sev(void); +#if (HAS_HD63701) +M6800_INLINE void slp(void); +#endif +M6800_INLINE void sta_di(void); +M6800_INLINE void sta_ex(void); +M6800_INLINE void sta_im(void); +M6800_INLINE void sta_ix(void); +M6800_INLINE void stb_di(void); +M6800_INLINE void stb_ex(void); +M6800_INLINE void stb_im(void); +M6800_INLINE void stb_ix(void); +M6800_INLINE void std_di(void); +M6800_INLINE void std_ex(void); +M6800_INLINE void std_im(void); +M6800_INLINE void std_ix(void); +M6800_INLINE void sts_di(void); +M6800_INLINE void sts_ex(void); +M6800_INLINE void sts_im(void); +M6800_INLINE void sts_ix(void); +M6800_INLINE void stx_di(void); +M6800_INLINE void stx_ex(void); +M6800_INLINE void stx_im(void); +M6800_INLINE void stx_ix(void); +M6800_INLINE void suba_di(void); +M6800_INLINE void suba_ex(void); +M6800_INLINE void suba_im(void); +M6800_INLINE void suba_ix(void); +M6800_INLINE void subb_di(void); +M6800_INLINE void subb_ex(void); +M6800_INLINE void subb_im(void); +M6800_INLINE void subb_ix(void); +M6800_INLINE void subd_di(void); +M6800_INLINE void subd_ex(void); +M6800_INLINE void subd_im(void); +M6800_INLINE void subd_ix(void); +M6800_INLINE void swi(void); +M6800_INLINE void tab(void); +M6800_INLINE void tap(void); +M6800_INLINE void tba(void); +M6800_INLINE void tim_di(void); +M6800_INLINE void tim_ix(void); +M6800_INLINE void tpa(void); +M6800_INLINE void tst_ex(void); +M6800_INLINE void tst_ix(void); +M6800_INLINE void tsta(void); +M6800_INLINE void tstb(void); +M6800_INLINE void tsx(void); +M6800_INLINE void txs(void); +M6800_INLINE void undoc1(void); +M6800_INLINE void undoc2(void); +M6800_INLINE void wai(void); +M6800_INLINE void xgdx(void); + +M6800_INLINE void cpx_di(void); +M6800_INLINE void cpx_ex(void); +M6800_INLINE void cpx_im(void); +M6800_INLINE void cpx_ix(void); +#if (HAS_HD63701) +//M6800_INLINE void trap(void); +static void trap(void); +#endif + +static void (*m6800_insn[0x100])(void) = { +illegal,nop, illegal,illegal,illegal,illegal,tap, tpa, +inx, dex, clv, sev, clc, sec, cli, sei, +sba, cba, illegal,illegal,illegal,illegal,tab, tba, +illegal,daa, illegal,aba, illegal,illegal,illegal,illegal, +bra, brn, bhi, bls, bcc, bcs, bne, beq, +bvc, bvs, bpl, bmi, bge, blt, bgt, ble, +tsx, ins, pula, pulb, des, txs, psha, pshb, +illegal,rts, illegal,rti, illegal,illegal,wai, swi, +nega, illegal,illegal,coma, lsra, illegal,rora, asra, +asla, rola, deca, illegal,inca, tsta, illegal,clra, +negb, illegal,illegal,comb, lsrb, illegal,rorb, asrb, +aslb, rolb, decb, illegal,incb, tstb, illegal,clrb, +neg_ix, illegal,illegal,com_ix, lsr_ix, illegal,ror_ix, asr_ix, +asl_ix, rol_ix, dec_ix, illegal,inc_ix, tst_ix, jmp_ix, clr_ix, +neg_ex, illegal,illegal,com_ex, lsr_ex, illegal,ror_ex, asr_ex, +asl_ex, rol_ex, dec_ex, illegal,inc_ex, tst_ex, jmp_ex, clr_ex, +suba_im,cmpa_im,sbca_im,illegal,anda_im,bita_im,lda_im, sta_im, +eora_im,adca_im,ora_im, adda_im,cmpx_im,bsr, lds_im, sts_im, +suba_di,cmpa_di,sbca_di,illegal,anda_di,bita_di,lda_di, sta_di, +eora_di,adca_di,ora_di, adda_di,cmpx_di,jsr_di, lds_di, sts_di, +suba_ix,cmpa_ix,sbca_ix,illegal,anda_ix,bita_ix,lda_ix, sta_ix, +eora_ix,adca_ix,ora_ix, adda_ix,cmpx_ix,jsr_ix, lds_ix, sts_ix, +suba_ex,cmpa_ex,sbca_ex,illegal,anda_ex,bita_ex,lda_ex, sta_ex, +eora_ex,adca_ex,ora_ex, adda_ex,cmpx_ex,jsr_ex, lds_ex, sts_ex, +subb_im,cmpb_im,sbcb_im,illegal,andb_im,bitb_im,ldb_im, stb_im, +eorb_im,adcb_im,orb_im, addb_im,illegal,illegal,ldx_im, stx_im, +subb_di,cmpb_di,sbcb_di,illegal,andb_di,bitb_di,ldb_di, stb_di, +eorb_di,adcb_di,orb_di, addb_di,illegal,illegal,ldx_di, stx_di, +subb_ix,cmpb_ix,sbcb_ix,illegal,andb_ix,bitb_ix,ldb_ix, stb_ix, +eorb_ix,adcb_ix,orb_ix, addb_ix,illegal,illegal,ldx_ix, stx_ix, +subb_ex,cmpb_ex,sbcb_ex,illegal,andb_ex,bitb_ex,ldb_ex, stb_ex, +eorb_ex,adcb_ex,orb_ex, addb_ex,illegal,illegal,ldx_ex, stx_ex +}; + +#if (HAS_M6801||HAS_M6803) +static void (*m6803_insn[0x100])(void) = { +illegal,nop, illegal,illegal,lsrd, asld, tap, tpa, +inx, dex, clv, sev, clc, sec, cli, sei, +sba, cba, illegal,illegal,illegal,illegal,tab, tba, +illegal,daa, illegal,aba, illegal,illegal,illegal,illegal, +bra, brn, bhi, bls, bcc, bcs, bne, beq, +bvc, bvs, bpl, bmi, bge, blt, bgt, ble, +tsx, ins, pula, pulb, des, txs, psha, pshb, +pulx, rts, abx, rti, pshx, mul, wai, swi, +nega, illegal,illegal,coma, lsra, illegal,rora, asra, +asla, rola, deca, illegal,inca, tsta, illegal,clra, +negb, illegal,illegal,comb, lsrb, illegal,rorb, asrb, +aslb, rolb, decb, illegal,incb, tstb, illegal,clrb, +neg_ix, illegal,illegal,com_ix, lsr_ix, illegal,ror_ix, asr_ix, +asl_ix, rol_ix, dec_ix, illegal,inc_ix, tst_ix, jmp_ix, clr_ix, +neg_ex, illegal,illegal,com_ex, lsr_ex, illegal,ror_ex, asr_ex, +asl_ex, rol_ex, dec_ex, illegal,inc_ex, tst_ex, jmp_ex, clr_ex, +suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im, +eora_im,adca_im,ora_im, adda_im,cpx_im ,bsr, lds_im, sts_im, +suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di, +eora_di,adca_di,ora_di, adda_di,cpx_di ,jsr_di, lds_di, sts_di, +suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix, +eora_ix,adca_ix,ora_ix, adda_ix,cpx_ix ,jsr_ix, lds_ix, sts_ix, +suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex, +eora_ex,adca_ex,ora_ex, adda_ex,cpx_ex ,jsr_ex, lds_ex, sts_ex, +subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im, +eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldx_im, stx_im, +subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di, +eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldx_di, stx_di, +subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix, +eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldx_ix, stx_ix, +subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex, +eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldx_ex, stx_ex +}; +#endif + +#if (HAS_HD63701) +static void (*hd63701_insn[0x100])(void) = { +trap ,nop, trap ,trap ,lsrd, asld, tap, tpa, +inx, dex, clv, sev, clc, sec, cli, sei, +sba, cba, undoc1, undoc2, trap ,trap ,tab, tba, +xgdx, daa, slp ,aba, trap ,trap ,trap ,trap , +bra, brn, bhi, bls, bcc, bcs, bne, beq, +bvc, bvs, bpl, bmi, bge, blt, bgt, ble, +tsx, ins, pula, pulb, des, txs, psha, pshb, +pulx, rts, abx, rti, pshx, mul, wai, swi, +nega, trap ,trap ,coma, lsra, trap ,rora, asra, +asla, rola, deca, trap ,inca, tsta, trap ,clra, +negb, trap ,trap ,comb, lsrb, trap ,rorb, asrb, +aslb, rolb, decb, trap ,incb, tstb, trap ,clrb, +neg_ix, aim_ix, oim_ix, com_ix, lsr_ix, eim_ix, ror_ix, asr_ix, +asl_ix, rol_ix, dec_ix, tim_ix, inc_ix, tst_ix, jmp_ix, clr_ix, +neg_ex, aim_di, oim_di, com_ex, lsr_ex, eim_di, ror_ex, asr_ex, +asl_ex, rol_ex, dec_ex, tim_di, inc_ex, tst_ex, jmp_ex, clr_ex, +suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im, +eora_im,adca_im,ora_im, adda_im,cpx_im ,bsr, lds_im, sts_im, +suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di, +eora_di,adca_di,ora_di, adda_di,cpx_di ,jsr_di, lds_di, sts_di, +suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix, +eora_ix,adca_ix,ora_ix, adda_ix,cpx_ix ,jsr_ix, lds_ix, sts_ix, +suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex, +eora_ex,adca_ex,ora_ex, adda_ex,cpx_ex ,jsr_ex, lds_ex, sts_ex, +subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im, +eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldx_im, stx_im, +subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di, +eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldx_di, stx_di, +subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix, +eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldx_ix, stx_ix, +subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex, +eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldx_ex, stx_ex +}; +#endif + +#if (HAS_NSC8105) +static void (*nsc8105_insn[0x100])(void) = { +illegal,illegal,nop, illegal,illegal,tap, illegal,tpa, +inx, clv, dex, sev, clc, cli, sec, sei, +sba, illegal,cba, illegal,illegal,tab, illegal,tba, +illegal,illegal,daa, aba, illegal,illegal,illegal,illegal, +bra, bhi, brn, bls, bcc, bne, bcs, beq, +bvc, bpl, bvs, bmi, bge, bgt, blt, ble, +tsx, pula, ins, pulb, des, psha, txs, pshb, +illegal,illegal,rts, rti, illegal,wai, illegal,swi, +suba_im,sbca_im,cmpa_im,illegal,anda_im,lda_im, bita_im,sta_im, +eora_im,ora_im, adca_im,adda_im,cmpx_im,lds_im, bsr, sts_im, +suba_di,sbca_di,cmpa_di,illegal,anda_di,lda_di, bita_di,sta_di, +eora_di,ora_di, adca_di,adda_di,cmpx_di,lds_di, jsr_di, sts_di, +suba_ix,sbca_ix,cmpa_ix,illegal,anda_ix,lda_ix, bita_ix,sta_ix, +eora_ix,ora_ix, adca_ix,adda_ix,cmpx_ix,lds_ix, jsr_ix, sts_ix, +suba_ex,sbca_ex,cmpa_ex,illegal,anda_ex,lda_ex, bita_ex,sta_ex, +eora_ex,ora_ex, adca_ex,adda_ex,cmpx_ex,lds_ex, jsr_ex, sts_ex, +nega, illegal,illegal,coma, lsra, rora, illegal,asra, +asla, deca, rola, illegal,inca, illegal,tsta, clra, +negb, illegal,illegal,comb, lsrb, rorb, illegal,asrb, +aslb, decb, rolb, illegal,incb, illegal,tstb, clrb, +neg_ix, illegal,illegal,com_ix, lsr_ix, ror_ix, illegal,asr_ix, +asl_ix, dec_ix, rol_ix, illegal,inc_ix, jmp_ix, tst_ix, clr_ix, +neg_ex, illegal,illegal,com_ex, lsr_ex, ror_ex, illegal,asr_ex, +asl_ex, dec_ex, rol_ex, illegal,inc_ex, jmp_ex, tst_ex, clr_ex, +subb_im,sbcb_im,cmpb_im,illegal,andb_im,ldb_im, bitb_im,stb_im, +eorb_im,orb_im, adcb_im,addb_im,illegal,ldx_im, illegal,stx_im, +subb_di,sbcb_di,cmpb_di,illegal,andb_di,ldb_di, bitb_di,stb_di, +eorb_di,orb_di, adcb_di,addb_di,illegal,ldx_di, illegal,stx_di, +subb_ix,sbcb_ix,cmpb_ix,illegal,andb_ix,ldb_ix, bitb_ix,stb_ix, +eorb_ix,orb_ix, adcb_ix,addb_ix,adcx_im,ldx_ix, illegal,stx_ix, +subb_ex,sbcb_ex,cmpb_ex,illegal,andb_ex,ldb_ex, bitb_ex,stb_ex, +eorb_ex,orb_ex, adcb_ex,addb_ex,addx_ex,ldx_ex, illegal,stx_ex +}; +#endif diff --git a/src/cpu/m6800/m6800.cpp b/src/cpu/m6800/m6800.cpp new file mode 100644 index 00000000..5a022d9a --- /dev/null +++ b/src/cpu/m6800/m6800.cpp @@ -0,0 +1,2445 @@ +/*** m6800: Portable 6800 class emulator ************************************* + + m6800.c + + References: + + 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands. + + m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from + the 6809 Simulator V09) + + 6809 Microcomputer Programming & Interfacing with Experiments" + by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. + + System dependencies: UINT16 must be 16 bit unsigned int + UINT8 must be 8 bit unsigned int + UINT32 must be more than 16 bits + arrays up to 65536 bytes must be supported + machine must be twos complement + +History +991031 ZV + Added NSC-8105 support + +990319 HJB + Fixed wrong LSB/MSB order for push/pull word. + Subtract .extra_cycles at the beginning/end of the exectuion loops. + +990316 HJB + Renamed to 6800, since that's the basic CPU. + Added different cycle count tables for M6800/2/8, M6801/3 and HD63701. + +990314 HJB + Also added the M6800 subtype. + +990311 HJB + Added _info functions. Now uses static m6808_Regs struct instead + of single statics. Changed the 16 bit registers to use the generic + PAIR union. Registers defined using macros. Split the core into + four execution loops for M6802, M6803, M6808 and HD63701. + TST, TSTA and TSTB opcodes reset carry flag. +TODO: + Verify invalid opcodes for the different CPU types. + Add proper credits to _info functions. + Integrate m6808_Flags into the registers (multiple m6808 type CPUs?) + +990301 HJB + Modified the interrupt handling. No more pending interrupt checks. + WAI opcode saves state, when an interrupt is taken (IRQ or OCI), + the state is only saved if not already done by WAI. + +*****************************************************************************/ + + +//#include "debugger.h" +#include "burnint.h" +#include "m6800.h" + +#define VERBOSE 0 + +#if VERBOSE +#define LOG(x) logerror x +#else +#define LOG(x) +#endif + +#define M6800_INLINE static +#define change_pc(newpc) m6800.pc.w.l = (newpc) +#define M6800_CLEAR_LINE 0 + +#if 0 +/* CPU subtypes, needed for extra insn after TAP/CLI/SEI */ +enum { + SUBTYPE_M6800, + SUBTYPE_M6801, + SUBTYPE_M6802, + SUBTYPE_M6803, + SUBTYPE_M6808, + SUBTYPE_HD63701, + SUBTYPE_NSC8105 +}; +#endif + +/* 680x registers */ +static m6800_Regs m6800; + +#define m6801 m6800 +#define m6802 m6800 +#define m6803 m6800 +#define m6808 m6800 +#define hd63701 m6800 +#define nsc8105 m6800 + +#define pPPC m6800.ppc +#define pPC m6800.pc +#define pS m6800.s +#define pX m6800.x +#define pD m6800.d + +#define PC m6800.pc.w.l +#define PCD m6800.pc.d +#define S m6800.s.w.l +#define SD m6800.s.d +#define X m6800.x.w.l +#define D m6800.d.w.l +#define A m6800.d.b.h +#define B m6800.d.b.l +#define CC m6800.cc + +#define CT m6800.counter.w.l +#define CTH m6800.counter.w.h +#define CTD m6800.counter.d +#define OC m6800.output_compare.w.l +#define OCH m6800.output_compare.w.h +#define OCD m6800.output_compare.d +#define TOH m6800.timer_over.w.l +#define TOD m6800.timer_over.d + +static PAIR ea; /* effective address */ +#define EAD ea.d +#define EA ea.w.l + +/* public globals */ +static int m6800_ICount; + +/* point of next timer event */ +static UINT32 timer_next; + +/* DS -- THESE ARE RE-DEFINED IN m6800.h TO RAM, ROM or FUNCTIONS IN cpuintrf.c */ +#define RM M6800_RDMEM +#define WM M6800_WRMEM +#define M_RDOP M6800_RDOP +#define M_RDOP_ARG M6800_RDOP_ARG + +/* macros to access memory */ +#define IMMBYTE(b) b = M_RDOP_ARG(PCD); PC++ +#define IMMWORD(w) w.d = (M_RDOP_ARG(PCD)<<8) | M_RDOP_ARG((PCD+1)&0xffff); PC+=2 + +#define PUSHBYTE(b) WM(SD,b); --S +#define PUSHWORD(w) WM(SD,w.b.l); --S; WM(SD,w.b.h); --S +#define PULLBYTE(b) S++; b = RM(SD) +#define PULLWORD(w) S++; w.d = RM(SD)<<8; S++; w.d |= RM(SD) + +#define MODIFIED_tcsr { \ + m6800.irq2 = (m6800.tcsr&(m6800.tcsr<<3))&(TCSR_ICF|TCSR_OCF|TCSR_TOF); \ +} + +#define SET_TIMER_EVENT { \ + timer_next = (OCD - CTD < TOD - CTD) ? OCD : TOD; \ +} + +/* cleanup high-word of counters */ +#define CLEANUP_conters { \ + OCH -= CTH; \ + TOH -= CTH; \ + CTH = 0; \ + SET_TIMER_EVENT; \ +} + +/* when change freerunningcounter or outputcapture */ +#define MODIFIED_counters { \ + OCH = (OC >= CT) ? CTH : CTH+1; \ + SET_TIMER_EVENT; \ +} + +/* take interrupt */ +#define TAKE_ICI ENTER_INTERRUPT("M6800#%d take ICI\n",0xfff6) +#define TAKE_OCI ENTER_INTERRUPT("M6800#%d take OCI\n",0xfff4) +#define TAKE_TOI ENTER_INTERRUPT("M6800#%d take TOI\n",0xfff2) +#define TAKE_SCI ENTER_INTERRUPT("M6800#%d take SCI\n",0xfff0) +#define TAKE_TRAP ENTER_INTERRUPT("M6800#%d take TRAP\n",0xffee) + +/* check IRQ2 (internal irq) */ +#define CHECK_IRQ2 { \ + if(m6800.irq2&(TCSR_ICF|TCSR_OCF|TCSR_TOF)) \ + { \ + if(m6800.irq2&TCSR_ICF) \ + { \ + TAKE_ICI; \ + } \ + else if(m6800.irq2&TCSR_OCF) \ + { \ + TAKE_OCI; \ + } \ + else if(m6800.irq2&TCSR_TOF) \ + { \ + TAKE_TOI; \ + } \ + } \ +} + +/* operate one instruction for */ +#define ONE_MORE_INSN() { \ + UINT8 ireg; \ + pPPC = pPC; \ + ireg=M_RDOP(PCD); \ + PC++; \ + (*m6800.insn[ireg])(); \ + INCREMENT_COUNTER(m6800.cycles[ireg]); \ +} + +/* check the IRQ lines for pending interrupts */ +#define CHECK_IRQ_LINES() { \ + if( !(CC & 0x10) ) \ + { \ + if( m6800.irq_state[M6800_IRQ_LINE] != M6800_CLEAR_LINE ) \ + { /* standard IRQ */ \ + ENTER_INTERRUPT("M6800#%d take IRQ1\n",0xfff8); \ + } \ + else \ + CHECK_IRQ2; \ + } \ +} + +/* CC masks HI NZVC + 7654 3210 */ +#define CLR_HNZVC CC&=0xd0 +#define CLR_NZV CC&=0xf1 +#define CLR_HNZC CC&=0xd2 +#define CLR_NZVC CC&=0xf0 +#define CLR_Z CC&=0xfb +#define CLR_NZC CC&=0xf2 +#define CLR_ZC CC&=0xfa +#define CLR_C CC&=0xfe + +/* macros for CC -- CC bits affected should be reset before calling */ +#define SET_Z(a) if(!(a))SEZ +#define SET_Z8(a) SET_Z((UINT8)(a)) +#define SET_Z16(a) SET_Z((UINT16)(a)) +#define SET_N8(a) CC|=(((a)&0x80)>>4) +#define SET_N16(a) CC|=(((a)&0x8000)>>12) +#define SET_H(a,b,r) CC|=((((a)^(b)^(r))&0x10)<<1) +#define SET_C8(a) CC|=(((a)&0x100)>>8) +#define SET_C16(a) CC|=(((a)&0x10000)>>16) +#define SET_V8(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x80)>>6) +#define SET_V16(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x8000)>>14) + +static const UINT8 flags8i[256]= /* increment */ +{ +0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 +}; +static const UINT8 flags8d[256]= /* decrement */ +{ +0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 +}; +#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} +#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} + +/* combos */ +#define SET_NZ8(a) {SET_N8(a);SET_Z8(a);} +#define SET_NZ16(a) {SET_N16(a);SET_Z16(a);} +#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} +#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);} + +/* for treating an UINT8 as a signed INT16 */ +#define SIGNED(b) ((INT16)(b&0x80?b|0xff00:b)) + +/* Macros for addressing modes */ +#define DIRECT IMMBYTE(EAD) +#define IMM8 EA=PC++ +#define IMM16 {EA=PC;PC+=2;} +#define EXTENDED IMMWORD(ea) +#define INDEXED {EA=X+(UINT8)M_RDOP_ARG(PCD);PC++;} + +/* macros to set status flags */ +#define SEC CC|=0x01 +#define CLC CC&=0xfe +#define SEZ CC|=0x04 +#define CLZ CC&=0xfb +#define SEN CC|=0x08 +#define CLN CC&=0xf7 +#define SEV CC|=0x02 +#define CLV CC&=0xfd +#define SEH CC|=0x20 +#define CLH CC&=0xdf +#define SEI CC|=0x10 +#define CLI CC&=~0x10 + +/* mnemonicos for the Timer Control and Status Register bits */ +#define TCSR_OLVL 0x01 +#define TCSR_IEDG 0x02 +#define TCSR_ETOI 0x04 +#define TCSR_EOCI 0x08 +#define TCSR_EICI 0x10 +#define TCSR_TOF 0x20 +#define TCSR_OCF 0x40 +#define TCSR_ICF 0x80 + +#define INCREMENT_COUNTER(amount) \ +{ \ + m6800_ICount -= amount; \ + CTD += amount; \ + if( CTD >= timer_next) \ + check_timer_event(); \ +} + +#define EAT_CYCLES \ +{ \ + int cycles_to_eat; \ + \ + cycles_to_eat = timer_next - CTD; \ + if( cycles_to_eat > m6800_ICount) cycles_to_eat = m6800_ICount; \ + if (cycles_to_eat > 0) \ + { \ + INCREMENT_COUNTER(cycles_to_eat); \ + } \ +} + +/* macros for convenience */ +#define DIRBYTE(b) {DIRECT;b=RM(EAD);} +#define DIRWORD(w) {DIRECT;w.d=RM16(EAD);} +#define EXTBYTE(b) {EXTENDED;b=RM(EAD);} +#define EXTWORD(w) {EXTENDED;w.d=RM16(EAD);} + +#define IDXBYTE(b) {INDEXED;b=RM(EAD);} +#define IDXWORD(w) {INDEXED;w.d=RM16(EAD);} + +/* Macros for branch instructions */ +#define CHANGE_PC() change_pc(PCD) +#define BRANCH(f) {IMMBYTE(t);if(f){PC+=SIGNED(t);CHANGE_PC();}} +#define NXORV ((CC&0x08)^((CC&0x02)<<2)) + +/* Note: we use 99 cycles here for invalid opcodes so that we don't */ +/* hang in an infinite loop if we hit one */ +static const UINT8 cycles_6800[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 99, 2,99,99,99,99, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, + /*1*/ 2, 2,99,99,99,99, 2, 2,99, 2,99, 2,99,99,99,99, + /*2*/ 4,99, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,99, 5,99,10,99,99, 9,12, + /*4*/ 2,99,99, 2, 2,99, 2, 2, 2, 2, 2,99, 2, 2,99, 2, + /*5*/ 2,99,99, 2, 2,99, 2, 2, 2, 2, 2,99, 2, 2,99, 2, + /*6*/ 7,99,99, 7, 7,99, 7, 7, 7, 7, 7,99, 7, 7, 4, 7, + /*7*/ 6,99,99, 6, 6,99, 6, 6, 6, 6, 6,99, 6, 6, 3, 6, + /*8*/ 2, 2, 2,99, 2, 2, 2,99, 2, 2, 2, 2, 3, 8, 3,99, + /*9*/ 3, 3, 3,99, 3, 3, 3, 4, 3, 3, 3, 3, 4,99, 4, 5, + /*A*/ 5, 5, 5,99, 5, 5, 5, 6, 5, 5, 5, 5, 6, 8, 6, 7, + /*B*/ 4, 4, 4,99, 4, 4, 4, 5, 4, 4, 4, 4, 5, 9, 5, 6, + /*C*/ 2, 2, 2,99, 2, 2, 2,99, 2, 2, 2, 2,99,99, 3,99, + /*D*/ 3, 3, 3,99, 3, 3, 3, 4, 3, 3, 3, 3,99,99, 4, 5, + /*E*/ 5, 5, 5,99, 5, 5, 5, 6, 5, 5, 5, 5,99,99, 6, 7, + /*F*/ 4, 4, 4,99, 4, 4, 4, 5, 4, 4, 4, 4,99,99, 5, 6 +}; + +static const UINT8 cycles_6803[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 99, 2,99,99, 3, 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, + /*1*/ 2, 2,99,99,99,99, 2, 2,99, 2,99, 2,99,99,99,99, + /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /*3*/ 3, 3, 4, 4, 3, 3, 3, 3, 5, 5, 3,10, 4,10, 9,12, + /*4*/ 2,99,99, 2, 2,99, 2, 2, 2, 2, 2,99, 2, 2,99, 2, + /*5*/ 2,99,99, 2, 2,99, 2, 2, 2, 2, 2,99, 2, 2,99, 2, + /*6*/ 6,99,99, 6, 6,99, 6, 6, 6, 6, 6,99, 6, 6, 3, 6, + /*7*/ 6,99,99, 6, 6,99, 6, 6, 6, 6, 6,99, 6, 6, 3, 6, + /*8*/ 2, 2, 2, 4, 2, 2, 2,99, 2, 2, 2, 2, 4, 6, 3,99, + /*9*/ 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 4, + /*A*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, + /*B*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, + /*C*/ 2, 2, 2, 4, 2, 2, 2,99, 2, 2, 2, 2, 3,99, 3,99, + /*D*/ 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + /*E*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + /*F*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +static const UINT8 cycles_63701[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 99, 1,99,99, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /*1*/ 1, 1,99,99,99,99, 1, 1, 2, 2, 4, 1,99,99,99,99, + /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /*3*/ 1, 1, 3, 3, 1, 1, 4, 4, 4, 5, 1,10, 5, 7, 9,12, + /*4*/ 1,99,99, 1, 1,99, 1, 1, 1, 1, 1,99, 1, 1,99, 1, + /*5*/ 1,99,99, 1, 1,99, 1, 1, 1, 1, 1,99, 1, 1,99, 1, + /*6*/ 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 4, 3, 5, + /*7*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 3, 5, + /*8*/ 2, 2, 2, 3, 2, 2, 2,99, 2, 2, 2, 2, 3, 5, 3,99, + /*9*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4, + /*A*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + /*B*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, + /*C*/ 2, 2, 2, 3, 2, 2, 2,99, 2, 2, 2, 2, 3,99, 3,99, + /*D*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + /*E*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + /*F*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +static const UINT8 cycles_nsc8105[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 99,99, 2,99,99, 2,99, 2, 4, 2, 4, 2, 2, 2, 2, 2, + /*1*/ 2,99, 2,99,99, 2,99, 2,99,99, 2, 2,99,99,99,99, + /*2*/ 4, 4,99, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,99,99, 5,10,99, 9,99,12, + /*4*/ 2,99,99, 2, 2, 2,99, 2, 2, 2, 2,99, 2,99, 2, 2, + /*5*/ 2,99,99, 2, 2, 2,99, 2, 2, 2, 2,99, 2,99, 2, 2, + /*6*/ 7,99,99, 7, 7, 7,99, 7, 7, 7, 7,99, 7, 4, 7, 7, + /*7*/ 6,99,99, 6, 6, 6,99, 6, 6, 6, 6,99, 6, 3, 6, 6, + /*8*/ 2, 2, 2,99, 2, 2, 2,99, 2, 2, 2, 2, 3, 3, 8,99, + /*9*/ 3, 3, 3,99, 3, 3, 3, 4, 3, 3, 3, 3, 4, 4,99, 5, + /*A*/ 5, 5, 5,99, 5, 5, 5, 6, 5, 5, 5, 5, 6, 6, 8, 7, + /*B*/ 4, 4, 4,99, 4, 4, 4, 5, 4, 4, 4, 4, 5, 5, 9, 6, + /*C*/ 2, 2, 2,99, 2, 2, 2,99, 2, 2, 2, 2,99, 3,99,99, + /*D*/ 3, 3, 3,99, 3, 3, 3, 4, 3, 3, 3, 3,99, 4,99, 5, + /*E*/ 5, 5, 5,99, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6,99, 7, + /*F*/ 4, 4, 4,99, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,99, 6 +}; + +M6800_INLINE UINT32 RM16( UINT32 Addr ) +{ + UINT32 result = RM(Addr) << 8; + return result | RM((Addr+1)&0xffff); +} + +M6800_INLINE void WM16( UINT32 Addr, PAIR *p ) +{ + WM( Addr, p->b.h ); + WM( (Addr+1)&0xffff, p->b.l ); +} + +/* IRQ enter */ +static void ENTER_INTERRUPT(const char */*message*/,UINT16 irq_vector) +{ +// LOG((message, cpu_getactivecpu())); + if( m6800.wai_state & (M6800_WAI|M6800_SLP) ) + { + if( m6800.wai_state & M6800_WAI ) + m6800.extra_cycles += 4; + m6800.wai_state &= ~(M6800_WAI|M6800_SLP); + } + else + { + PUSHWORD(pPC); + PUSHWORD(pX); + PUSHBYTE(A); + PUSHBYTE(B); + PUSHBYTE(CC); + m6800.extra_cycles += 12; + } + SEI; + PCD = RM16( irq_vector ); + CHANGE_PC(); +} + +/* check OCI or TOI */ +static void check_timer_event(void) +{ + /* OCI */ + if( CTD >= OCD) + { + OCH++; // next IRQ point + m6800.tcsr |= TCSR_OCF; + m6800.pending_tcsr |= TCSR_OCF; + MODIFIED_tcsr; + if ( !(CC & 0x10) && (m6800.tcsr & TCSR_EOCI)) + TAKE_OCI; + } + /* TOI */ + if( CTD >= TOD) + { + TOH++; // next IRQ point +#if 0 + CLEANUP_conters; +#endif + m6800.tcsr |= TCSR_TOF; + m6800.pending_tcsr |= TCSR_TOF; + MODIFIED_tcsr; + if ( !(CC & 0x10) && (m6800.tcsr & TCSR_ETOI)) + TAKE_TOI; + } + /* set next event */ + SET_TIMER_EVENT; +} + +/* include the opcode prototypes and function pointer tables */ +#include "6800tbl.c" + +/* include the opcode functions */ +#include "6800ops.c" + +/**************************************************************************** + * Reset registers to their initial values + ****************************************************************************/ + +void m6800_init() +{ +// m6800.subtype = SUBTYPE_M6800; + m6800.insn = m6800_insn; + m6800.cycles = cycles_6800; +// m6800.irq_callback = irqcallback; +// state_register("m6800", index); +} + +void m6800_reset(void) +{ + SEI; /* IRQ disabled */ + PCD = RM16( 0xfffe ); + CHANGE_PC(); + + m6800.wai_state = 0; + m6800.nmi_state = 0; + m6800.irq_state[M6800_IRQ_LINE] = 0; + m6800.irq_state[M6800_TIN_LINE] = 0; + m6800.ic_eddge = 0; + + m6800.port1_ddr = 0x00; + m6800.port2_ddr = 0x00; + /* TODO: on reset port 2 should be read to determine the operating mode (bits 0-2) */ + m6800.tcsr = 0x00; + m6800.pending_tcsr = 0x00; + m6800.irq2 = 0; + CTD = 0x0000; + OCD = 0xffff; + TOD = 0xffff; + m6800.ram_ctrl |= 0x40; +} + +int m6800_get_pc() +{ + return PC; +} + +/**************************************************************************** + * Shut down CPU emulatio + ****************************************************************************/ +/* +static void m6800_exit(void) +{ + +}*/ + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +void m6800_get_context(void *dst) +{ + if( dst ) + *(m6800_Regs*)dst = m6800; +} + + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +void m6800_set_context(void *src) +{ + if( src ) + m6800 = *(m6800_Regs*)src; + CHANGE_PC(); + CHECK_IRQ_LINES(); /* HJB 990417 */ +} + + +void m6800_set_irq_line(int irqline, int state) +{ + if (irqline == M6800_INPUT_LINE_NMI) + { + if (m6800.nmi_state == state) return; + LOG(("M6800#%d set_nmi_line %d \n", cpu_getactivecpu(), state)); + m6800.nmi_state = state; + if (state == M6800_CLEAR_LINE) return; + + /* NMI */ + ENTER_INTERRUPT("M6800#%d take NMI\n",0xfffc); + } + else + { + int eddge; + + if (m6800.irq_state[irqline] == state) return; + LOG(("M6800#%d set_irq_line %d,%d\n", cpu_getactivecpu(), irqline, state)); + m6800.irq_state[irqline] = state; + + switch(irqline) + { + case M6800_IRQ_LINE: + if (state == M6800_CLEAR_LINE) return; + break; + case M6800_TIN_LINE: + eddge = (state == M6800_CLEAR_LINE ) ? 2 : 0; + if( ((m6800.tcsr&TCSR_IEDG) ^ (state==M6800_CLEAR_LINE ? TCSR_IEDG : 0))==0 ) + return; + /* active edge in */ + m6800.tcsr |= TCSR_ICF; + m6800.pending_tcsr |= TCSR_ICF; + m6800.input_capture = CT; + MODIFIED_tcsr; + if( !(CC & 0x10) ) + CHECK_IRQ2 + break; + default: + return; + } + CHECK_IRQ_LINES(); /* HJB 990417 */ + } +} + +/**************************************************************************** + * Execute cycles CPU cycles. Return number of cycles really executed + ****************************************************************************/ +int m6800_execute(int cycles) +{ + UINT8 ireg; + m6800_ICount = cycles; + + CLEANUP_conters; + INCREMENT_COUNTER(m6800.extra_cycles); + m6800.extra_cycles = 0; + + do + { + if( m6800.wai_state & M6800_WAI ) + { + EAT_CYCLES; + } + else + { + pPPC = pPC; +// CALL_MAME_DEBUG; + ireg=M_RDOP(PCD); + PC++; + + switch( ireg ) + { + case 0x00: illegal(); break; + case 0x01: nop(); break; + case 0x02: illegal(); break; + case 0x03: illegal(); break; + case 0x04: illegal(); break; + case 0x05: illegal(); break; + case 0x06: tap(); break; + case 0x07: tpa(); break; + case 0x08: inx(); break; + case 0x09: dex(); break; + case 0x0A: CLV; break; + case 0x0B: SEV; break; + case 0x0C: CLC; break; + case 0x0D: SEC; break; + case 0x0E: cli(); break; + case 0x0F: sei(); break; + case 0x10: sba(); break; + case 0x11: cba(); break; + case 0x12: illegal(); break; + case 0x13: illegal(); break; + case 0x14: illegal(); break; + case 0x15: illegal(); break; + case 0x16: tab(); break; + case 0x17: tba(); break; + case 0x18: illegal(); break; + case 0x19: daa(); break; + case 0x1a: illegal(); break; + case 0x1b: aba(); break; + case 0x1c: illegal(); break; + case 0x1d: illegal(); break; + case 0x1e: illegal(); break; + case 0x1f: illegal(); break; + case 0x20: bra(); break; + case 0x21: brn(); break; + case 0x22: bhi(); break; + case 0x23: bls(); break; + case 0x24: bcc(); break; + case 0x25: bcs(); break; + case 0x26: bne(); break; + case 0x27: beq(); break; + case 0x28: bvc(); break; + case 0x29: bvs(); break; + case 0x2a: bpl(); break; + case 0x2b: bmi(); break; + case 0x2c: bge(); break; + case 0x2d: blt(); break; + case 0x2e: bgt(); break; + case 0x2f: ble(); break; + case 0x30: tsx(); break; + case 0x31: ins(); break; + case 0x32: pula(); break; + case 0x33: pulb(); break; + case 0x34: des(); break; + case 0x35: txs(); break; + case 0x36: psha(); break; + case 0x37: pshb(); break; + case 0x38: illegal(); break; + case 0x39: rts(); break; + case 0x3a: illegal(); break; + case 0x3b: rti(); break; + case 0x3c: illegal(); break; + case 0x3d: illegal(); break; + case 0x3e: wai(); break; + case 0x3f: swi(); break; + case 0x40: nega(); break; + case 0x41: illegal(); break; + case 0x42: illegal(); break; + case 0x43: coma(); break; + case 0x44: lsra(); break; + case 0x45: illegal(); break; + case 0x46: rora(); break; + case 0x47: asra(); break; + case 0x48: asla(); break; + case 0x49: rola(); break; + case 0x4a: deca(); break; + case 0x4b: illegal(); break; + case 0x4c: inca(); break; + case 0x4d: tsta(); break; + case 0x4e: illegal(); break; + case 0x4f: clra(); break; + case 0x50: negb(); break; + case 0x51: illegal(); break; + case 0x52: illegal(); break; + case 0x53: comb(); break; + case 0x54: lsrb(); break; + case 0x55: illegal(); break; + case 0x56: rorb(); break; + case 0x57: asrb(); break; + case 0x58: aslb(); break; + case 0x59: rolb(); break; + case 0x5a: decb(); break; + case 0x5b: illegal(); break; + case 0x5c: incb(); break; + case 0x5d: tstb(); break; + case 0x5e: illegal(); break; + case 0x5f: clrb(); break; + case 0x60: neg_ix(); break; + case 0x61: illegal(); break; + case 0x62: illegal(); break; + case 0x63: com_ix(); break; + case 0x64: lsr_ix(); break; + case 0x65: illegal(); break; + case 0x66: ror_ix(); break; + case 0x67: asr_ix(); break; + case 0x68: asl_ix(); break; + case 0x69: rol_ix(); break; + case 0x6a: dec_ix(); break; + case 0x6b: illegal(); break; + case 0x6c: inc_ix(); break; + case 0x6d: tst_ix(); break; + case 0x6e: jmp_ix(); break; + case 0x6f: clr_ix(); break; + case 0x70: neg_ex(); break; + case 0x71: illegal(); break; + case 0x72: illegal(); break; + case 0x73: com_ex(); break; + case 0x74: lsr_ex(); break; + case 0x75: illegal(); break; + case 0x76: ror_ex(); break; + case 0x77: asr_ex(); break; + case 0x78: asl_ex(); break; + case 0x79: rol_ex(); break; + case 0x7a: dec_ex(); break; + case 0x7b: illegal(); break; + case 0x7c: inc_ex(); break; + case 0x7d: tst_ex(); break; + case 0x7e: jmp_ex(); break; + case 0x7f: clr_ex(); break; + case 0x80: suba_im(); break; + case 0x81: cmpa_im(); break; + case 0x82: sbca_im(); break; + case 0x83: illegal(); break; + case 0x84: anda_im(); break; + case 0x85: bita_im(); break; + case 0x86: lda_im(); break; + case 0x87: sta_im(); break; + case 0x88: eora_im(); break; + case 0x89: adca_im(); break; + case 0x8a: ora_im(); break; + case 0x8b: adda_im(); break; + case 0x8c: cmpx_im(); break; + case 0x8d: bsr(); break; + case 0x8e: lds_im(); break; + case 0x8f: sts_im(); /* orthogonality */ break; + case 0x90: suba_di(); break; + case 0x91: cmpa_di(); break; + case 0x92: sbca_di(); break; + case 0x93: illegal(); break; + case 0x94: anda_di(); break; + case 0x95: bita_di(); break; + case 0x96: lda_di(); break; + case 0x97: sta_di(); break; + case 0x98: eora_di(); break; + case 0x99: adca_di(); break; + case 0x9a: ora_di(); break; + case 0x9b: adda_di(); break; + case 0x9c: cmpx_di(); break; + case 0x9d: jsr_di(); break; + case 0x9e: lds_di(); break; + case 0x9f: sts_di(); break; + case 0xa0: suba_ix(); break; + case 0xa1: cmpa_ix(); break; + case 0xa2: sbca_ix(); break; + case 0xa3: illegal(); break; + case 0xa4: anda_ix(); break; + case 0xa5: bita_ix(); break; + case 0xa6: lda_ix(); break; + case 0xa7: sta_ix(); break; + case 0xa8: eora_ix(); break; + case 0xa9: adca_ix(); break; + case 0xaa: ora_ix(); break; + case 0xab: adda_ix(); break; + case 0xac: cmpx_ix(); break; + case 0xad: jsr_ix(); break; + case 0xae: lds_ix(); break; + case 0xaf: sts_ix(); break; + case 0xb0: suba_ex(); break; + case 0xb1: cmpa_ex(); break; + case 0xb2: sbca_ex(); break; + case 0xb3: illegal(); break; + case 0xb4: anda_ex(); break; + case 0xb5: bita_ex(); break; + case 0xb6: lda_ex(); break; + case 0xb7: sta_ex(); break; + case 0xb8: eora_ex(); break; + case 0xb9: adca_ex(); break; + case 0xba: ora_ex(); break; + case 0xbb: adda_ex(); break; + case 0xbc: cmpx_ex(); break; + case 0xbd: jsr_ex(); break; + case 0xbe: lds_ex(); break; + case 0xbf: sts_ex(); break; + case 0xc0: subb_im(); break; + case 0xc1: cmpb_im(); break; + case 0xc2: sbcb_im(); break; + case 0xc3: illegal(); break; + case 0xc4: andb_im(); break; + case 0xc5: bitb_im(); break; + case 0xc6: ldb_im(); break; + case 0xc7: stb_im(); break; + case 0xc8: eorb_im(); break; + case 0xc9: adcb_im(); break; + case 0xca: orb_im(); break; + case 0xcb: addb_im(); break; + case 0xcc: illegal(); break; + case 0xcd: illegal(); break; + case 0xce: ldx_im(); break; + case 0xcf: stx_im(); break; + case 0xd0: subb_di(); break; + case 0xd1: cmpb_di(); break; + case 0xd2: sbcb_di(); break; + case 0xd3: illegal(); break; + case 0xd4: andb_di(); break; + case 0xd5: bitb_di(); break; + case 0xd6: ldb_di(); break; + case 0xd7: stb_di(); break; + case 0xd8: eorb_di(); break; + case 0xd9: adcb_di(); break; + case 0xda: orb_di(); break; + case 0xdb: addb_di(); break; + case 0xdc: illegal(); break; + case 0xdd: illegal(); break; + case 0xde: ldx_di(); break; + case 0xdf: stx_di(); break; + case 0xe0: subb_ix(); break; + case 0xe1: cmpb_ix(); break; + case 0xe2: sbcb_ix(); break; + case 0xe3: illegal(); break; + case 0xe4: andb_ix(); break; + case 0xe5: bitb_ix(); break; + case 0xe6: ldb_ix(); break; + case 0xe7: stb_ix(); break; + case 0xe8: eorb_ix(); break; + case 0xe9: adcb_ix(); break; + case 0xea: orb_ix(); break; + case 0xeb: addb_ix(); break; + case 0xec: illegal(); break; + case 0xed: illegal(); break; + case 0xee: ldx_ix(); break; + case 0xef: stx_ix(); break; + case 0xf0: subb_ex(); break; + case 0xf1: cmpb_ex(); break; + case 0xf2: sbcb_ex(); break; + case 0xf3: illegal(); break; + case 0xf4: andb_ex(); break; + case 0xf5: bitb_ex(); break; + case 0xf6: ldb_ex(); break; + case 0xf7: stb_ex(); break; + case 0xf8: eorb_ex(); break; + case 0xf9: adcb_ex(); break; + case 0xfa: orb_ex(); break; + case 0xfb: addb_ex(); break; + case 0xfc: addx_ex(); break; + case 0xfd: illegal(); break; + case 0xfe: ldx_ex(); break; + case 0xff: stx_ex(); break; + } + INCREMENT_COUNTER(cycles_6800[ireg]); + } + } while( m6800_ICount>0 ); + + INCREMENT_COUNTER(m6800.extra_cycles); + m6800.extra_cycles = 0; + + return cycles - m6800_ICount; +} + +/**************************************************************************** + * M6801 almost (fully?) equal to the M6803 + ****************************************************************************/ +#if (HAS_M6801) +void m6801_init() +{ +// m6800.subtype = SUBTYPE_M6801; + m6800.insn = m6803_insn; + m6800.cycles = cycles_6803; +// m6800.irq_callback = irqcallback; +// state_register("m6801", index); +} +#endif + +/**************************************************************************** + * M6802 almost (fully?) equal to the M6800 + ****************************************************************************/ +#if (HAS_M6802) +static void m6802_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ +// m6800.subtype = SUBTYPE_M6802; + m6800.insn = m6800_insn; + m6800.cycles = cycles_6800; + m6800.irq_callback = irqcallback; + state_register("m6802", index); +} +#endif + +/**************************************************************************** + * M6803 almost (fully?) equal to the M6801 + ****************************************************************************/ +#if (HAS_M6803) +void m6803_init() +{ +// m6800.subtype = SUBTYPE_M6803; + m6800.insn = m6803_insn; + m6800.cycles = cycles_6803; +// m6800.irq_callback = irqcallback; +// state_register("m6803", index); +} +#endif + +/**************************************************************************** + * Execute cycles CPU cycles. Return number of cycles really executed + ****************************************************************************/ +#if (HAS_M6803||HAS_M6801) +int m6803_execute(int cycles) +{ + UINT8 ireg; + m6800_ICount = cycles; + + CLEANUP_conters; + INCREMENT_COUNTER(m6803.extra_cycles); + m6803.extra_cycles = 0; + + do + { + if( m6803.wai_state & M6800_WAI ) + { + EAT_CYCLES; + } + else + { + pPPC = pPC; +// CALL_MAME_DEBUG; + ireg=M_RDOP(PCD); + PC++; + + switch( ireg ) + { + case 0x00: illegal(); break; + case 0x01: nop(); break; + case 0x02: illegal(); break; + case 0x03: illegal(); break; + case 0x04: lsrd(); /* 6803 only */; break; + case 0x05: asld(); /* 6803 only */; break; + case 0x06: tap(); break; + case 0x07: tpa(); break; + case 0x08: inx(); break; + case 0x09: dex(); break; + case 0x0A: CLV; break; + case 0x0B: SEV; break; + case 0x0C: CLC; break; + case 0x0D: SEC; break; + case 0x0E: cli(); break; + case 0x0F: sei(); break; + case 0x10: sba(); break; + case 0x11: cba(); break; + case 0x12: illegal(); break; + case 0x13: illegal(); break; + case 0x14: illegal(); break; + case 0x15: illegal(); break; + case 0x16: tab(); break; + case 0x17: tba(); break; + case 0x18: illegal(); break; + case 0x19: daa(); break; + case 0x1a: illegal(); break; + case 0x1b: aba(); break; + case 0x1c: illegal(); break; + case 0x1d: illegal(); break; + case 0x1e: illegal(); break; + case 0x1f: illegal(); break; + case 0x20: bra(); break; + case 0x21: brn(); break; + case 0x22: bhi(); break; + case 0x23: bls(); break; + case 0x24: bcc(); break; + case 0x25: bcs(); break; + case 0x26: bne(); break; + case 0x27: beq(); break; + case 0x28: bvc(); break; + case 0x29: bvs(); break; + case 0x2a: bpl(); break; + case 0x2b: bmi(); break; + case 0x2c: bge(); break; + case 0x2d: blt(); break; + case 0x2e: bgt(); break; + case 0x2f: ble(); break; + case 0x30: tsx(); break; + case 0x31: ins(); break; + case 0x32: pula(); break; + case 0x33: pulb(); break; + case 0x34: des(); break; + case 0x35: txs(); break; + case 0x36: psha(); break; + case 0x37: pshb(); break; + case 0x38: pulx(); /* 6803 only */ break; + case 0x39: rts(); break; + case 0x3a: abx(); /* 6803 only */ break; + case 0x3b: rti(); break; + case 0x3c: pshx(); /* 6803 only */ break; + case 0x3d: mul(); /* 6803 only */ break; + case 0x3e: wai(); break; + case 0x3f: swi(); break; + case 0x40: nega(); break; + case 0x41: illegal(); break; + case 0x42: illegal(); break; + case 0x43: coma(); break; + case 0x44: lsra(); break; + case 0x45: illegal(); break; + case 0x46: rora(); break; + case 0x47: asra(); break; + case 0x48: asla(); break; + case 0x49: rola(); break; + case 0x4a: deca(); break; + case 0x4b: illegal(); break; + case 0x4c: inca(); break; + case 0x4d: tsta(); break; + case 0x4e: illegal(); break; + case 0x4f: clra(); break; + case 0x50: negb(); break; + case 0x51: illegal(); break; + case 0x52: illegal(); break; + case 0x53: comb(); break; + case 0x54: lsrb(); break; + case 0x55: illegal(); break; + case 0x56: rorb(); break; + case 0x57: asrb(); break; + case 0x58: aslb(); break; + case 0x59: rolb(); break; + case 0x5a: decb(); break; + case 0x5b: illegal(); break; + case 0x5c: incb(); break; + case 0x5d: tstb(); break; + case 0x5e: illegal(); break; + case 0x5f: clrb(); break; + case 0x60: neg_ix(); break; + case 0x61: illegal(); break; + case 0x62: illegal(); break; + case 0x63: com_ix(); break; + case 0x64: lsr_ix(); break; + case 0x65: illegal(); break; + case 0x66: ror_ix(); break; + case 0x67: asr_ix(); break; + case 0x68: asl_ix(); break; + case 0x69: rol_ix(); break; + case 0x6a: dec_ix(); break; + case 0x6b: illegal(); break; + case 0x6c: inc_ix(); break; + case 0x6d: tst_ix(); break; + case 0x6e: jmp_ix(); break; + case 0x6f: clr_ix(); break; + case 0x70: neg_ex(); break; + case 0x71: illegal(); break; + case 0x72: illegal(); break; + case 0x73: com_ex(); break; + case 0x74: lsr_ex(); break; + case 0x75: illegal(); break; + case 0x76: ror_ex(); break; + case 0x77: asr_ex(); break; + case 0x78: asl_ex(); break; + case 0x79: rol_ex(); break; + case 0x7a: dec_ex(); break; + case 0x7b: illegal(); break; + case 0x7c: inc_ex(); break; + case 0x7d: tst_ex(); break; + case 0x7e: jmp_ex(); break; + case 0x7f: clr_ex(); break; + case 0x80: suba_im(); break; + case 0x81: cmpa_im(); break; + case 0x82: sbca_im(); break; + case 0x83: subd_im(); /* 6803 only */ break; + case 0x84: anda_im(); break; + case 0x85: bita_im(); break; + case 0x86: lda_im(); break; + case 0x87: sta_im(); break; + case 0x88: eora_im(); break; + case 0x89: adca_im(); break; + case 0x8a: ora_im(); break; + case 0x8b: adda_im(); break; + case 0x8c: cpx_im(); /* 6803 difference */ break; + case 0x8d: bsr(); break; + case 0x8e: lds_im(); break; + case 0x8f: sts_im(); /* orthogonality */ break; + case 0x90: suba_di(); break; + case 0x91: cmpa_di(); break; + case 0x92: sbca_di(); break; + case 0x93: subd_di(); /* 6803 only */ break; + case 0x94: anda_di(); break; + case 0x95: bita_di(); break; + case 0x96: lda_di(); break; + case 0x97: sta_di(); break; + case 0x98: eora_di(); break; + case 0x99: adca_di(); break; + case 0x9a: ora_di(); break; + case 0x9b: adda_di(); break; + case 0x9c: cpx_di(); /* 6803 difference */ break; + case 0x9d: jsr_di(); break; + case 0x9e: lds_di(); break; + case 0x9f: sts_di(); break; + case 0xa0: suba_ix(); break; + case 0xa1: cmpa_ix(); break; + case 0xa2: sbca_ix(); break; + case 0xa3: subd_ix(); /* 6803 only */ break; + case 0xa4: anda_ix(); break; + case 0xa5: bita_ix(); break; + case 0xa6: lda_ix(); break; + case 0xa7: sta_ix(); break; + case 0xa8: eora_ix(); break; + case 0xa9: adca_ix(); break; + case 0xaa: ora_ix(); break; + case 0xab: adda_ix(); break; + case 0xac: cpx_ix(); /* 6803 difference */ break; + case 0xad: jsr_ix(); break; + case 0xae: lds_ix(); break; + case 0xaf: sts_ix(); break; + case 0xb0: suba_ex(); break; + case 0xb1: cmpa_ex(); break; + case 0xb2: sbca_ex(); break; + case 0xb3: subd_ex(); /* 6803 only */ break; + case 0xb4: anda_ex(); break; + case 0xb5: bita_ex(); break; + case 0xb6: lda_ex(); break; + case 0xb7: sta_ex(); break; + case 0xb8: eora_ex(); break; + case 0xb9: adca_ex(); break; + case 0xba: ora_ex(); break; + case 0xbb: adda_ex(); break; + case 0xbc: cpx_ex(); /* 6803 difference */ break; + case 0xbd: jsr_ex(); break; + case 0xbe: lds_ex(); break; + case 0xbf: sts_ex(); break; + case 0xc0: subb_im(); break; + case 0xc1: cmpb_im(); break; + case 0xc2: sbcb_im(); break; + case 0xc3: addd_im(); /* 6803 only */ break; + case 0xc4: andb_im(); break; + case 0xc5: bitb_im(); break; + case 0xc6: ldb_im(); break; + case 0xc7: stb_im(); break; + case 0xc8: eorb_im(); break; + case 0xc9: adcb_im(); break; + case 0xca: orb_im(); break; + case 0xcb: addb_im(); break; + case 0xcc: ldd_im(); /* 6803 only */ break; + case 0xcd: std_im(); /* 6803 only -- orthogonality */ break; + case 0xce: ldx_im(); break; + case 0xcf: stx_im(); break; + case 0xd0: subb_di(); break; + case 0xd1: cmpb_di(); break; + case 0xd2: sbcb_di(); break; + case 0xd3: addd_di(); /* 6803 only */ break; + case 0xd4: andb_di(); break; + case 0xd5: bitb_di(); break; + case 0xd6: ldb_di(); break; + case 0xd7: stb_di(); break; + case 0xd8: eorb_di(); break; + case 0xd9: adcb_di(); break; + case 0xda: orb_di(); break; + case 0xdb: addb_di(); break; + case 0xdc: ldd_di(); /* 6803 only */ break; + case 0xdd: std_di(); /* 6803 only */ break; + case 0xde: ldx_di(); break; + case 0xdf: stx_di(); break; + case 0xe0: subb_ix(); break; + case 0xe1: cmpb_ix(); break; + case 0xe2: sbcb_ix(); break; + case 0xe3: addd_ix(); /* 6803 only */ break; + case 0xe4: andb_ix(); break; + case 0xe5: bitb_ix(); break; + case 0xe6: ldb_ix(); break; + case 0xe7: stb_ix(); break; + case 0xe8: eorb_ix(); break; + case 0xe9: adcb_ix(); break; + case 0xea: orb_ix(); break; + case 0xeb: addb_ix(); break; + case 0xec: ldd_ix(); /* 6803 only */ break; + case 0xed: std_ix(); /* 6803 only */ break; + case 0xee: ldx_ix(); break; + case 0xef: stx_ix(); break; + case 0xf0: subb_ex(); break; + case 0xf1: cmpb_ex(); break; + case 0xf2: sbcb_ex(); break; + case 0xf3: addd_ex(); /* 6803 only */ break; + case 0xf4: andb_ex(); break; + case 0xf5: bitb_ex(); break; + case 0xf6: ldb_ex(); break; + case 0xf7: stb_ex(); break; + case 0xf8: eorb_ex(); break; + case 0xf9: adcb_ex(); break; + case 0xfa: orb_ex(); break; + case 0xfb: addb_ex(); break; + case 0xfc: ldd_ex(); /* 6803 only */ break; + case 0xfd: std_ex(); /* 6803 only */ break; + case 0xfe: ldx_ex(); break; + case 0xff: stx_ex(); break; + } + INCREMENT_COUNTER(cycles_6803[ireg]); + } + } while( m6800_ICount>0 ); + + INCREMENT_COUNTER(m6803.extra_cycles); + m6803.extra_cycles = 0; + + return cycles - m6800_ICount; +} +#endif + +#if (HAS_M6803) + +//static READ8_HANDLER( m6803_internal_registers_r ); +//static WRITE8_HANDLER( m6803_internal_registers_w ); + +//static ADDRESS_MAP_START(m6803_mem, ADDRESS_SPACE_PROGRAM, 8) +// AM_RANGE(0x0000, 0x001f) AM_READWRITE(m6803_internal_registers_r, m6803_internal_registers_w) +// AM_RANGE(0x0020, 0x007f) AM_NOP /* unused */ +// AM_RANGE(0x0080, 0x00ff) AM_RAM /* 6803 internal RAM */ +//ADDRESS_MAP_END + +#endif + +/**************************************************************************** + * M6808 almost (fully?) equal to the M6800 + ****************************************************************************/ +#if (HAS_M6808) +static void m6808_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ +// m6800.subtype = SUBTYPE_M6808; + m6800.insn = m6800_insn; + m6800.cycles = cycles_6800; + m6800.irq_callback = irqcallback; + state_register("m6808", index); +} +#endif + +/**************************************************************************** + * HD63701 similiar to the M6800 + ****************************************************************************/ +#if (HAS_HD63701) +void hd63701_init() +{ +// m6800.subtype = SUBTYPE_HD63701; + m6800.insn = hd63701_insn; + m6800.cycles = cycles_63701; +// m6800.irq_callback = irqcallback; +// state_register("hd63701", index); +} +/**************************************************************************** + * Execute cycles CPU cycles. Return number of cycles really executed + ****************************************************************************/ +int hd63701_execute(int cycles) +{ + UINT8 ireg; + m6800_ICount = cycles; + + CLEANUP_conters; + INCREMENT_COUNTER(hd63701.extra_cycles); + hd63701.extra_cycles = 0; + + do + { + if( hd63701.wai_state & (HD63701_WAI|HD63701_SLP) ) + { + EAT_CYCLES; + } + else + { + pPPC = pPC; +// CALL_MAME_DEBUG; + ireg=M_RDOP(PCD); + PC++; + + switch( ireg ) + { + case 0x00: trap(); break; + case 0x01: nop(); break; + case 0x02: trap(); break; + case 0x03: trap(); break; + case 0x04: lsrd(); /* 6803 only */; break; + case 0x05: asld(); /* 6803 only */; break; + case 0x06: tap(); break; + case 0x07: tpa(); break; + case 0x08: inx(); break; + case 0x09: dex(); break; + case 0x0A: CLV; break; + case 0x0B: SEV; break; + case 0x0C: CLC; break; + case 0x0D: SEC; break; + case 0x0E: cli(); break; + case 0x0F: sei(); break; + case 0x10: sba(); break; + case 0x11: cba(); break; + case 0x12: undoc1(); break; + case 0x13: undoc2(); break; + case 0x14: trap(); break; + case 0x15: trap(); break; + case 0x16: tab(); break; + case 0x17: tba(); break; + case 0x18: xgdx(); /* HD63701YO only */; break; + case 0x19: daa(); break; + case 0x1a: slp(); break; + case 0x1b: aba(); break; + case 0x1c: trap(); break; + case 0x1d: trap(); break; + case 0x1e: trap(); break; + case 0x1f: trap(); break; + case 0x20: bra(); break; + case 0x21: brn(); break; + case 0x22: bhi(); break; + case 0x23: bls(); break; + case 0x24: bcc(); break; + case 0x25: bcs(); break; + case 0x26: bne(); break; + case 0x27: beq(); break; + case 0x28: bvc(); break; + case 0x29: bvs(); break; + case 0x2a: bpl(); break; + case 0x2b: bmi(); break; + case 0x2c: bge(); break; + case 0x2d: blt(); break; + case 0x2e: bgt(); break; + case 0x2f: ble(); break; + case 0x30: tsx(); break; + case 0x31: ins(); break; + case 0x32: pula(); break; + case 0x33: pulb(); break; + case 0x34: des(); break; + case 0x35: txs(); break; + case 0x36: psha(); break; + case 0x37: pshb(); break; + case 0x38: pulx(); /* 6803 only */ break; + case 0x39: rts(); break; + case 0x3a: abx(); /* 6803 only */ break; + case 0x3b: rti(); break; + case 0x3c: pshx(); /* 6803 only */ break; + case 0x3d: mul(); /* 6803 only */ break; + case 0x3e: wai(); break; + case 0x3f: swi(); break; + case 0x40: nega(); break; + case 0x41: trap(); break; + case 0x42: trap(); break; + case 0x43: coma(); break; + case 0x44: lsra(); break; + case 0x45: trap(); break; + case 0x46: rora(); break; + case 0x47: asra(); break; + case 0x48: asla(); break; + case 0x49: rola(); break; + case 0x4a: deca(); break; + case 0x4b: trap(); break; + case 0x4c: inca(); break; + case 0x4d: tsta(); break; + case 0x4e: trap(); break; + case 0x4f: clra(); break; + case 0x50: negb(); break; + case 0x51: trap(); break; + case 0x52: trap(); break; + case 0x53: comb(); break; + case 0x54: lsrb(); break; + case 0x55: trap(); break; + case 0x56: rorb(); break; + case 0x57: asrb(); break; + case 0x58: aslb(); break; + case 0x59: rolb(); break; + case 0x5a: decb(); break; + case 0x5b: trap(); break; + case 0x5c: incb(); break; + case 0x5d: tstb(); break; + case 0x5e: trap(); break; + case 0x5f: clrb(); break; + case 0x60: neg_ix(); break; + case 0x61: aim_ix(); /* HD63701YO only */; break; + case 0x62: oim_ix(); /* HD63701YO only */; break; + case 0x63: com_ix(); break; + case 0x64: lsr_ix(); break; + case 0x65: eim_ix(); /* HD63701YO only */; break; + case 0x66: ror_ix(); break; + case 0x67: asr_ix(); break; + case 0x68: asl_ix(); break; + case 0x69: rol_ix(); break; + case 0x6a: dec_ix(); break; + case 0x6b: tim_ix(); /* HD63701YO only */; break; + case 0x6c: inc_ix(); break; + case 0x6d: tst_ix(); break; + case 0x6e: jmp_ix(); break; + case 0x6f: clr_ix(); break; + case 0x70: neg_ex(); break; + case 0x71: aim_di(); /* HD63701YO only */; break; + case 0x72: oim_di(); /* HD63701YO only */; break; + case 0x73: com_ex(); break; + case 0x74: lsr_ex(); break; + case 0x75: eim_di(); /* HD63701YO only */; break; + case 0x76: ror_ex(); break; + case 0x77: asr_ex(); break; + case 0x78: asl_ex(); break; + case 0x79: rol_ex(); break; + case 0x7a: dec_ex(); break; + case 0x7b: tim_di(); /* HD63701YO only */; break; + case 0x7c: inc_ex(); break; + case 0x7d: tst_ex(); break; + case 0x7e: jmp_ex(); break; + case 0x7f: clr_ex(); break; + case 0x80: suba_im(); break; + case 0x81: cmpa_im(); break; + case 0x82: sbca_im(); break; + case 0x83: subd_im(); /* 6803 only */ break; + case 0x84: anda_im(); break; + case 0x85: bita_im(); break; + case 0x86: lda_im(); break; + case 0x87: sta_im(); break; + case 0x88: eora_im(); break; + case 0x89: adca_im(); break; + case 0x8a: ora_im(); break; + case 0x8b: adda_im(); break; + case 0x8c: cpx_im(); /* 6803 difference */ break; + case 0x8d: bsr(); break; + case 0x8e: lds_im(); break; + case 0x8f: sts_im(); /* orthogonality */ break; + case 0x90: suba_di(); break; + case 0x91: cmpa_di(); break; + case 0x92: sbca_di(); break; + case 0x93: subd_di(); /* 6803 only */ break; + case 0x94: anda_di(); break; + case 0x95: bita_di(); break; + case 0x96: lda_di(); break; + case 0x97: sta_di(); break; + case 0x98: eora_di(); break; + case 0x99: adca_di(); break; + case 0x9a: ora_di(); break; + case 0x9b: adda_di(); break; + case 0x9c: cpx_di(); /* 6803 difference */ break; + case 0x9d: jsr_di(); break; + case 0x9e: lds_di(); break; + case 0x9f: sts_di(); break; + case 0xa0: suba_ix(); break; + case 0xa1: cmpa_ix(); break; + case 0xa2: sbca_ix(); break; + case 0xa3: subd_ix(); /* 6803 only */ break; + case 0xa4: anda_ix(); break; + case 0xa5: bita_ix(); break; + case 0xa6: lda_ix(); break; + case 0xa7: sta_ix(); break; + case 0xa8: eora_ix(); break; + case 0xa9: adca_ix(); break; + case 0xaa: ora_ix(); break; + case 0xab: adda_ix(); break; + case 0xac: cpx_ix(); /* 6803 difference */ break; + case 0xad: jsr_ix(); break; + case 0xae: lds_ix(); break; + case 0xaf: sts_ix(); break; + case 0xb0: suba_ex(); break; + case 0xb1: cmpa_ex(); break; + case 0xb2: sbca_ex(); break; + case 0xb3: subd_ex(); /* 6803 only */ break; + case 0xb4: anda_ex(); break; + case 0xb5: bita_ex(); break; + case 0xb6: lda_ex(); break; + case 0xb7: sta_ex(); break; + case 0xb8: eora_ex(); break; + case 0xb9: adca_ex(); break; + case 0xba: ora_ex(); break; + case 0xbb: adda_ex(); break; + case 0xbc: cpx_ex(); /* 6803 difference */ break; + case 0xbd: jsr_ex(); break; + case 0xbe: lds_ex(); break; + case 0xbf: sts_ex(); break; + case 0xc0: subb_im(); break; + case 0xc1: cmpb_im(); break; + case 0xc2: sbcb_im(); break; + case 0xc3: addd_im(); /* 6803 only */ break; + case 0xc4: andb_im(); break; + case 0xc5: bitb_im(); break; + case 0xc6: ldb_im(); break; + case 0xc7: stb_im(); break; + case 0xc8: eorb_im(); break; + case 0xc9: adcb_im(); break; + case 0xca: orb_im(); break; + case 0xcb: addb_im(); break; + case 0xcc: ldd_im(); /* 6803 only */ break; + case 0xcd: std_im(); /* 6803 only -- orthogonality */ break; + case 0xce: ldx_im(); break; + case 0xcf: stx_im(); break; + case 0xd0: subb_di(); break; + case 0xd1: cmpb_di(); break; + case 0xd2: sbcb_di(); break; + case 0xd3: addd_di(); /* 6803 only */ break; + case 0xd4: andb_di(); break; + case 0xd5: bitb_di(); break; + case 0xd6: ldb_di(); break; + case 0xd7: stb_di(); break; + case 0xd8: eorb_di(); break; + case 0xd9: adcb_di(); break; + case 0xda: orb_di(); break; + case 0xdb: addb_di(); break; + case 0xdc: ldd_di(); /* 6803 only */ break; + case 0xdd: std_di(); /* 6803 only */ break; + case 0xde: ldx_di(); break; + case 0xdf: stx_di(); break; + case 0xe0: subb_ix(); break; + case 0xe1: cmpb_ix(); break; + case 0xe2: sbcb_ix(); break; + case 0xe3: addd_ix(); /* 6803 only */ break; + case 0xe4: andb_ix(); break; + case 0xe5: bitb_ix(); break; + case 0xe6: ldb_ix(); break; + case 0xe7: stb_ix(); break; + case 0xe8: eorb_ix(); break; + case 0xe9: adcb_ix(); break; + case 0xea: orb_ix(); break; + case 0xeb: addb_ix(); break; + case 0xec: ldd_ix(); /* 6803 only */ break; + case 0xed: std_ix(); /* 6803 only */ break; + case 0xee: ldx_ix(); break; + case 0xef: stx_ix(); break; + case 0xf0: subb_ex(); break; + case 0xf1: cmpb_ex(); break; + case 0xf2: sbcb_ex(); break; + case 0xf3: addd_ex(); /* 6803 only */ break; + case 0xf4: andb_ex(); break; + case 0xf5: bitb_ex(); break; + case 0xf6: ldb_ex(); break; + case 0xf7: stb_ex(); break; + case 0xf8: eorb_ex(); break; + case 0xf9: adcb_ex(); break; + case 0xfa: orb_ex(); break; + case 0xfb: addb_ex(); break; + case 0xfc: ldd_ex(); /* 6803 only */ break; + case 0xfd: std_ex(); /* 6803 only */ break; + case 0xfe: ldx_ex(); break; + case 0xff: stx_ex(); break; + } + INCREMENT_COUNTER(cycles_63701[ireg]); + } + } while( m6800_ICount>0 ); + + INCREMENT_COUNTER(hd63701.extra_cycles); + hd63701.extra_cycles = 0; + + return cycles - m6800_ICount; +} + +/* + if change_pc() direccted these areas ,Call hd63701_trap_pc(). + 'mode' is selected by the sense of p2.0,p2.1,and p2.3 at reset timming. + mode 0,1,2,4,6 : $0000-$001f + mode 5 : $0000-$001f,$0200-$efff + mode 7 : $0000-$001f,$0100-$efff +*/ +void hd63701_trap_pc(void) +{ + TAKE_TRAP; +} + +//static READ8_HANDLER( m6803_internal_registers_r ); +//static WRITE8_HANDLER( m6803_internal_registers_w ); + +//READ8_HANDLER( hd63701_internal_registers_r ) +//{ +// return m6803_internal_registers_r(offset); +//} + +//WRITE8_HANDLER( hd63701_internal_registers_w ) +//{ +// m6803_internal_registers_w(offset,data); +//} +#endif + +/**************************************************************************** + * NSC-8105 similiar to the M6800, but the opcodes are scrambled and there + * is at least one new opcode ($fc) + ****************************************************************************/ +#if (HAS_NSC8105) +static void nsc8105_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ +// m6800.subtype = SUBTYPE_NSC8105; + m6800.insn = nsc8105_insn; + m6800.cycles = cycles_nsc8105; + state_register("nsc8105", index); +} +/**************************************************************************** + * Execute cycles CPU cycles. Return number of cycles really executed + ****************************************************************************/ +static int nsc8105_execute(int cycles) +{ + UINT8 ireg; + m6800_ICount = cycles; + + CLEANUP_conters; + INCREMENT_COUNTER(nsc8105.extra_cycles); + nsc8105.extra_cycles = 0; + + do + { + if( nsc8105.wai_state & NSC8105_WAI ) + { + EAT_CYCLES; + } + else + { + pPPC = pPC; + CALL_MAME_DEBUG; + ireg=M_RDOP(PCD); + PC++; + + switch( ireg ) + { + case 0x00: illegal(); break; + case 0x01: illegal(); break; + case 0x02: nop(); break; + case 0x03: illegal(); break; + case 0x04: illegal(); break; + case 0x05: tap(); break; + case 0x06: illegal(); break; + case 0x07: tpa(); break; + case 0x08: inx(); break; + case 0x09: CLV; break; + case 0x0a: dex(); break; + case 0x0b: SEV; break; + case 0x0c: CLC; break; + case 0x0d: cli(); break; + case 0x0e: SEC; break; + case 0x0f: sei(); break; + case 0x10: sba(); break; + case 0x11: illegal(); break; + case 0x12: cba(); break; + case 0x13: illegal(); break; + case 0x14: illegal(); break; + case 0x15: tab(); break; + case 0x16: illegal(); break; + case 0x17: tba(); break; + case 0x18: illegal(); break; + case 0x19: illegal(); break; + case 0x1a: daa(); break; + case 0x1b: aba(); break; + case 0x1c: illegal(); break; + case 0x1d: illegal(); break; + case 0x1e: illegal(); break; + case 0x1f: illegal(); break; + case 0x20: bra(); break; + case 0x21: bhi(); break; + case 0x22: brn(); break; + case 0x23: bls(); break; + case 0x24: bcc(); break; + case 0x25: bne(); break; + case 0x26: bcs(); break; + case 0x27: beq(); break; + case 0x28: bvc(); break; + case 0x29: bpl(); break; + case 0x2a: bvs(); break; + case 0x2b: bmi(); break; + case 0x2c: bge(); break; + case 0x2d: bgt(); break; + case 0x2e: blt(); break; + case 0x2f: ble(); break; + case 0x30: tsx(); break; + case 0x31: pula(); break; + case 0x32: ins(); break; + case 0x33: pulb(); break; + case 0x34: des(); break; + case 0x35: psha(); break; + case 0x36: txs(); break; + case 0x37: pshb(); break; + case 0x38: illegal(); break; + case 0x39: illegal(); break; + case 0x3a: rts(); break; + case 0x3b: rti(); break; + case 0x3c: illegal(); break; + case 0x3d: wai(); break; + case 0x3e: illegal(); break; + case 0x3f: swi(); break; + case 0x40: suba_im(); break; + case 0x41: sbca_im(); break; + case 0x42: cmpa_im(); break; + case 0x43: illegal(); break; + case 0x44: anda_im(); break; + case 0x45: lda_im(); break; + case 0x46: bita_im(); break; + case 0x47: sta_im(); break; + case 0x48: eora_im(); break; + case 0x49: ora_im(); break; + case 0x4a: adca_im(); break; + case 0x4b: adda_im(); break; + case 0x4c: cmpx_im(); break; + case 0x4d: lds_im(); break; + case 0x4e: bsr(); break; + case 0x4f: sts_im(); /* orthogonality */ break; + case 0x50: suba_di(); break; + case 0x51: sbca_di(); break; + case 0x52: cmpa_di(); break; + case 0x53: illegal(); break; + case 0x54: anda_di(); break; + case 0x55: lda_di(); break; + case 0x56: bita_di(); break; + case 0x57: sta_di(); break; + case 0x58: eora_di(); break; + case 0x59: ora_di(); break; + case 0x5a: adca_di(); break; + case 0x5b: adda_di(); break; + case 0x5c: cmpx_di(); break; + case 0x5d: lds_di(); break; + case 0x5e: jsr_di(); break; + case 0x5f: sts_di(); break; + case 0x60: suba_ix(); break; + case 0x61: sbca_ix(); break; + case 0x62: cmpa_ix(); break; + case 0x63: illegal(); break; + case 0x64: anda_ix(); break; + case 0x65: lda_ix(); break; + case 0x66: bita_ix(); break; + case 0x67: sta_ix(); break; + case 0x68: eora_ix(); break; + case 0x69: ora_ix(); break; + case 0x6a: adca_ix(); break; + case 0x6b: adda_ix(); break; + case 0x6c: cmpx_ix(); break; + case 0x6d: lds_ix(); break; + case 0x6e: jsr_ix(); break; + case 0x6f: sts_ix(); break; + case 0x70: suba_ex(); break; + case 0x71: sbca_ex(); break; + case 0x72: cmpa_ex(); break; + case 0x73: illegal(); break; + case 0x74: anda_ex(); break; + case 0x75: lda_ex(); break; + case 0x76: bita_ex(); break; + case 0x77: sta_ex(); break; + case 0x78: eora_ex(); break; + case 0x79: ora_ex(); break; + case 0x7a: adca_ex(); break; + case 0x7b: adda_ex(); break; + case 0x7c: cmpx_ex(); break; + case 0x7d: lds_ex(); break; + case 0x7e: jsr_ex(); break; + case 0x7f: sts_ex(); break; + case 0x80: nega(); break; + case 0x81: illegal(); break; + case 0x82: illegal(); break; + case 0x83: coma(); break; + case 0x84: lsra(); break; + case 0x85: rora(); break; + case 0x86: illegal(); break; + case 0x87: asra(); break; + case 0x88: asla(); break; + case 0x89: deca(); break; + case 0x8a: rola(); break; + case 0x8b: illegal(); break; + case 0x8c: inca(); break; + case 0x8d: illegal(); break; + case 0x8e: tsta(); break; + case 0x8f: clra(); break; + case 0x90: negb(); break; + case 0x91: illegal(); break; + case 0x92: illegal(); break; + case 0x93: comb(); break; + case 0x94: lsrb(); break; + case 0x95: rorb(); break; + case 0x96: illegal(); break; + case 0x97: asrb(); break; + case 0x98: aslb(); break; + case 0x99: decb(); break; + case 0x9a: rolb(); break; + case 0x9b: illegal(); break; + case 0x9c: incb(); break; + case 0x9d: illegal(); break; + case 0x9e: tstb(); break; + case 0x9f: clrb(); break; + case 0xa0: neg_ix(); break; + case 0xa1: illegal(); break; + case 0xa2: illegal(); break; + case 0xa3: com_ix(); break; + case 0xa4: lsr_ix(); break; + case 0xa5: ror_ix(); break; + case 0xa6: illegal(); break; + case 0xa7: asr_ix(); break; + case 0xa8: asl_ix(); break; + case 0xa9: dec_ix(); break; + case 0xaa: rol_ix(); break; + case 0xab: illegal(); break; + case 0xac: inc_ix(); break; + case 0xad: jmp_ix(); break; + case 0xae: tst_ix(); break; + case 0xaf: clr_ix(); break; + case 0xb0: neg_ex(); break; + case 0xb1: illegal(); break; + case 0xb2: illegal(); break; + case 0xb3: com_ex(); break; + case 0xb4: lsr_ex(); break; + case 0xb5: ror_ex(); break; + case 0xb6: illegal(); break; + case 0xb7: asr_ex(); break; + case 0xb8: asl_ex(); break; + case 0xb9: dec_ex(); break; + case 0xba: rol_ex(); break; + case 0xbb: illegal(); break; + case 0xbc: inc_ex(); break; + case 0xbd: jmp_ex(); break; + case 0xbe: tst_ex(); break; + case 0xbf: clr_ex(); break; + case 0xc0: subb_im(); break; + case 0xc1: sbcb_im(); break; + case 0xc2: cmpb_im(); break; + case 0xc3: illegal(); break; + case 0xc4: andb_im(); break; + case 0xc5: ldb_im(); break; + case 0xc6: bitb_im(); break; + case 0xc7: stb_im(); break; + case 0xc8: eorb_im(); break; + case 0xc9: orb_im(); break; + case 0xca: adcb_im(); break; + case 0xcb: addb_im(); break; + case 0xcc: illegal(); break; + case 0xcd: ldx_im(); break; + case 0xce: illegal(); break; + case 0xcf: stx_im(); break; + case 0xd0: subb_di(); break; + case 0xd1: sbcb_di(); break; + case 0xd2: cmpb_di(); break; + case 0xd3: illegal(); break; + case 0xd4: andb_di(); break; + case 0xd5: ldb_di(); break; + case 0xd6: bitb_di(); break; + case 0xd7: stb_di(); break; + case 0xd8: eorb_di(); break; + case 0xd9: orb_di(); break; + case 0xda: adcb_di(); break; + case 0xdb: addb_di(); break; + case 0xdc: illegal(); break; + case 0xdd: ldx_di(); break; + case 0xde: illegal(); break; + case 0xdf: stx_di(); break; + case 0xe0: subb_ix(); break; + case 0xe1: sbcb_ix(); break; + case 0xe2: cmpb_ix(); break; + case 0xe3: illegal(); break; + case 0xe4: andb_ix(); break; + case 0xe5: ldb_ix(); break; + case 0xe6: bitb_ix(); break; + case 0xe7: stb_ix(); break; + case 0xe8: eorb_ix(); break; + case 0xe9: orb_ix(); break; + case 0xea: adcb_ix(); break; + case 0xeb: addb_ix(); break; + case 0xec: adcx_im(); break; /* NSC8105 only */ + case 0xed: ldx_ix(); break; + case 0xee: illegal(); break; + case 0xef: stx_ix(); break; + case 0xf0: subb_ex(); break; + case 0xf1: sbcb_ex(); break; + case 0xf2: cmpb_ex(); break; + case 0xf3: illegal(); break; + case 0xf4: andb_ex(); break; + case 0xf5: ldb_ex(); break; + case 0xf6: bitb_ex(); break; + case 0xf7: stb_ex(); break; + case 0xf8: eorb_ex(); break; + case 0xf9: orb_ex(); break; + case 0xfa: adcb_ex(); break; + case 0xfb: addb_ex(); break; + case 0xfc: addx_ex(); break; + case 0xfd: ldx_ex(); break; + case 0xfe: illegal(); break; + case 0xff: stx_ex(); break; + } + INCREMENT_COUNTER(cycles_nsc8105[ireg]); + } + } while( m6800_ICount>0 ); + + INCREMENT_COUNTER(nsc8105.extra_cycles); + nsc8105.extra_cycles = 0; + + return cycles - m6800_ICount; +} +#endif + + +#if (HAS_M6803||HAS_HD63701) + +unsigned char m6803_internal_registers_r(unsigned short offset) +{ + switch (offset) + { + case 0x00: + return m6800.port1_ddr; + case 0x01: + return m6800.port2_ddr; + case 0x02: + return (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff)) + | (m6800.port1_data & m6800.port1_ddr); + case 0x03: + return (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff)) + | (m6800.port2_data & m6800.port2_ddr); + case 0x04: + return m6800.port3_ddr; + case 0x05: + return m6800.port4_ddr; + case 0x06: + return (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff)) + | (m6800.port3_data & m6800.port3_ddr); + case 0x07: + return (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff)) + | (m6800.port4_data & m6800.port4_ddr); + case 0x08: + m6800.pending_tcsr = 0; +//logerror("CPU #%d PC %04x: warning - read TCSR register\n",cpu_getactivecpu(),activecpu_get_pc()); + return m6800.tcsr; + case 0x09: + if(!(m6800.pending_tcsr&TCSR_TOF)) + { + m6800.tcsr &= ~TCSR_TOF; + MODIFIED_tcsr; + } + return m6800.counter.b.h; + case 0x0a: + return m6800.counter.b.l; + case 0x0b: + if(!(m6800.pending_tcsr&TCSR_OCF)) + { + m6800.tcsr &= ~TCSR_OCF; + MODIFIED_tcsr; + } + return m6800.output_compare.b.h; + case 0x0c: + if(!(m6800.pending_tcsr&TCSR_OCF)) + { + m6800.tcsr &= ~TCSR_OCF; + MODIFIED_tcsr; + } + return m6800.output_compare.b.l; + case 0x0d: + if(!(m6800.pending_tcsr&TCSR_ICF)) + { + m6800.tcsr &= ~TCSR_ICF; + MODIFIED_tcsr; + } + return (m6800.input_capture >> 0) & 0xff; + case 0x0e: + return (m6800.input_capture >> 8) & 0xff; + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: +// logerror("CPU #%d PC %04x: warning - read from unsupported internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset); + return 0; + case 0x14: +// logerror("CPU #%d PC %04x: read RAM control register\n",cpu_getactivecpu(),activecpu_get_pc()); + return m6800.ram_ctrl; + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + default: +// logerror("CPU #%d PC %04x: warning - read from reserved internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset); + return 0; + } +} + +void m6803_internal_registers_w(unsigned short offset, unsigned char data) +{ + static int latch09; + + switch (offset) + { + case 0x00: + if (m6800.port1_ddr != data) + { + m6800.port1_ddr = data; + if(m6800.port1_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT1,m6800.port1_data); + else + M6800_io_write_byte_8(M6803_PORT1,(m6800.port1_data & m6800.port1_ddr) + | (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff))); + } + break; + case 0x01: + if (m6800.port2_ddr != data) + { + m6800.port2_ddr = data; + if(m6800.port2_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT2,m6800.port2_data); + else + M6800_io_write_byte_8(M6803_PORT2,(m6800.port2_data & m6800.port2_ddr) + | (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff))); + +// if (m6800.port2_ddr & 2) +// logerror("CPU #%d PC %04x: warning - port 2 bit 1 set as output (OLVL) - not supported\n",cpu_getactivecpu(),activecpu_get_pc()); + } + break; + case 0x02: + m6800.port1_data = data; + if(m6800.port1_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT1,m6800.port1_data); + else + M6800_io_write_byte_8(M6803_PORT1,(m6800.port1_data & m6800.port1_ddr) + | (M6800_io_read_byte_8(M6803_PORT1) & (m6800.port1_ddr ^ 0xff))); + break; + case 0x03: + m6800.port2_data = data; + m6800.port2_ddr = data; + if(m6800.port2_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT2,m6800.port2_data); + else + M6800_io_write_byte_8(M6803_PORT2,(m6800.port2_data & m6800.port2_ddr) + | (M6800_io_read_byte_8(M6803_PORT2) & (m6800.port2_ddr ^ 0xff))); + break; + case 0x04: + if (m6800.port3_ddr != data) + { + m6800.port3_ddr = data; + if(m6800.port3_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT3,m6800.port3_data); + else + M6800_io_write_byte_8(M6803_PORT3,(m6800.port3_data & m6800.port3_ddr) + | (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff))); + } + break; + case 0x05: + if (m6800.port4_ddr != data) + { + m6800.port4_ddr = data; + if(m6800.port4_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT4,m6800.port4_data); + else + M6800_io_write_byte_8(M6803_PORT4,(m6800.port4_data & m6800.port4_ddr) + | (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff))); + } + break; + case 0x06: + m6800.port3_data = data; + if(m6800.port3_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT3,m6800.port3_data); + else + M6800_io_write_byte_8(M6803_PORT3,(m6800.port3_data & m6800.port3_ddr) + | (M6800_io_read_byte_8(M6803_PORT3) & (m6800.port3_ddr ^ 0xff))); + break; + case 0x07: + m6800.port4_data = data; + if(m6800.port4_ddr == 0xff) + M6800_io_write_byte_8(M6803_PORT4,m6800.port4_data); + else + M6800_io_write_byte_8(M6803_PORT4,(m6800.port4_data & m6800.port4_ddr) + | (M6800_io_read_byte_8(M6803_PORT4) & (m6800.port4_ddr ^ 0xff))); + break; + case 0x08: + m6800.tcsr = data; + m6800.pending_tcsr &= m6800.tcsr; + MODIFIED_tcsr; + if( !(CC & 0x10) ) + CHECK_IRQ2; +//logerror("CPU #%d PC %04x: TCSR = %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data); + break; + case 0x09: + latch09 = data & 0xff; /* 6301 only */ + CT = 0xfff8; + TOH = CTH; + MODIFIED_counters; + break; + case 0x0a: /* 6301 only */ + CT = (latch09 << 8) | (data & 0xff); + TOH = CTH; + MODIFIED_counters; + break; + case 0x0b: + if( m6800.output_compare.b.h != data) + { + m6800.output_compare.b.h = data; + MODIFIED_counters; + } + break; + case 0x0c: + if( m6800.output_compare.b.l != data) + { + m6800.output_compare.b.l = data; + MODIFIED_counters; + } + break; + case 0x0d: + case 0x0e: +// logerror("CPU #%d PC %04x: warning - write %02x to read only internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset); + break; + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: +// logerror("CPU #%d PC %04x: warning - write %02x to unsupported internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset); + break; + case 0x14: +// logerror("CPU #%d PC %04x: write %02x to RAM control register\n",cpu_getactivecpu(),activecpu_get_pc(),data); + m6800.ram_ctrl = data; + break; + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + default: +// logerror("CPU #%d PC %04x: warning - write %02x to reserved internal register %02x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset); + break; + } +} +#endif + +#if 0 +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void m6800_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE: set_irq_line(M6800_IRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6800_TIN_LINE: set_irq_line(M6800_TIN_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6800_INPUT_LINE_NMI: set_irq_line(M6800_INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_PC: PC = info->i; CHANGE_PC(); break; + case CPUINFO_INT_REGISTER + M6800_PC: m6800.pc.w.l = info->i; break; + case CPUINFO_INT_SP: S = info->i; break; + case CPUINFO_INT_REGISTER + M6800_S: m6800.s.w.l = info->i; break; + case CPUINFO_INT_REGISTER + M6800_CC: m6800.cc = info->i; break; + case CPUINFO_INT_REGISTER + M6800_A: m6800.d.b.h = info->i; break; + case CPUINFO_INT_REGISTER + M6800_B: m6800.d.b.l = info->i; break; + case CPUINFO_INT_REGISTER + M6800_X: m6800.x.w.l = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void m6800_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6800); break; + case CPUINFO_INT_INPUT_LINES: info->i = 2; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 12; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE: info->i = m6800.irq_state[M6800_IRQ_LINE]; break; + case CPUINFO_INT_INPUT_STATE + M6800_TIN_LINE: info->i = m6800.irq_state[M6800_TIN_LINE]; break; + case CPUINFO_INT_INPUT_STATE + M6800_INPUT_LINE_NMI: info->i = m6800.nmi_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = m6800.ppc.w.l; break; + + case CPUINFO_INT_PC: info->i = PC; break; + case CPUINFO_INT_REGISTER + M6800_PC: info->i = m6800.pc.w.l; break; + case CPUINFO_INT_SP: info->i = S; break; + case CPUINFO_INT_REGISTER + M6800_S: info->i = m6800.s.w.l; break; + case CPUINFO_INT_REGISTER + M6800_CC: info->i = m6800.cc; break; + case CPUINFO_INT_REGISTER + M6800_A: info->i = m6800.d.b.h; break; + case CPUINFO_INT_REGISTER + M6800_B: info->i = m6800.d.b.l; break; + case CPUINFO_INT_REGISTER + M6800_X: info->i = m6800.x.w.l; break; + case CPUINFO_INT_REGISTER + M6800_WAI_STATE: info->i = m6800.wai_state; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = m6800_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = m6800_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = m6800_set_context; break; + case CPUINFO_PTR_INIT: info->init = m6800_init; break; + case CPUINFO_PTR_RESET: info->reset = m6800_reset; break; + case CPUINFO_PTR_EXIT: info->exit = m6800_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = m6800_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6800_dasm; break; +#endif /* MAME_DEBUG */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m6800_ICount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6800"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Motorola 6800"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.1"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "The MAME team."); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c", + m6800.cc & 0x80 ? '?':'.', + m6800.cc & 0x40 ? '?':'.', + m6800.cc & 0x20 ? 'H':'.', + m6800.cc & 0x10 ? 'I':'.', + m6800.cc & 0x08 ? 'N':'.', + m6800.cc & 0x04 ? 'Z':'.', + m6800.cc & 0x02 ? 'V':'.', + m6800.cc & 0x01 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + M6800_A: sprintf(info->s, "A:%02X", m6800.d.b.h); break; + case CPUINFO_STR_REGISTER + M6800_B: sprintf(info->s, "B:%02X", m6800.d.b.l); break; + case CPUINFO_STR_REGISTER + M6800_PC: sprintf(info->s, "PC:%04X", m6800.pc.w.l); break; + case CPUINFO_STR_REGISTER + M6800_S: sprintf(info->s, "S:%04X", m6800.s.w.l); break; + case CPUINFO_STR_REGISTER + M6800_X: sprintf(info->s, "X:%04X", m6800.x.w.l); break; + case CPUINFO_STR_REGISTER + M6800_CC: sprintf(info->s, "CC:%02X", m6800.cc); break; + case CPUINFO_STR_REGISTER + M6800_WAI_STATE: sprintf(info->s, "WAI:%X", m6800.wai_state); break; + } +} + + +#if (HAS_M6801) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6801_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = m6801_init; break; + case CPUINFO_PTR_EXECUTE: info->execute = m6803_execute; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6801_dasm; break; +#endif /* MAME_DEBUG */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6801"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M6802) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6802_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = m6802_init; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6802_dasm; break; +#endif /* MAME_DEBUG */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6802"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M6803) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6803_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = m6803_init; break; + case CPUINFO_PTR_EXECUTE: info->execute = m6803_execute; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6803_dasm; break; +#endif /* MAME_DEBUG */ + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_m6803_mem; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6803"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + + +#if (HAS_M6808) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6808_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = m6808_init; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6808_dasm; break; +#endif /* MAME_DEBUG */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6808"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + + +#if (HAS_HD63701) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void hd63701_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = hd63701_init; break; + case CPUINFO_PTR_EXECUTE: info->execute = hd63701_execute; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = hd63701_dasm; break; +#endif /* MAME_DEBUG */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "HD63701"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + + +#if (HAS_NSC8105) +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void nsc8105_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_INIT: info->init = nsc8105_init; break; + case CPUINFO_PTR_EXECUTE: info->execute = nsc8105_execute; break; +#ifdef MAME_DEBUG + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = nsc8105_dasm; break; +#endif /* MAME_DEBUG */ + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "NSC8105"); break; + + default: m6800_get_info(state, info); break; + } +} +#endif + +#endif diff --git a/src/cpu/m6800/m6800.h b/src/cpu/m6800/m6800.h new file mode 100644 index 00000000..209a7601 --- /dev/null +++ b/src/cpu/m6800/m6800.h @@ -0,0 +1,296 @@ +/*** m6800: Portable 6800 class emulator *************************************/ + +#define HAS_M6801 1 +#define HAS_M6802 0 +#define HAS_M6803 1 +#define HAS_M6808 0 +#define HAS_HD63701 1 +#define HAS_NSC8105 0 + +#ifndef _M6800_H +#define _M6800_H + +//#include "cpuintrf.h" + +/* 6800 Registers */ +typedef struct +{ +// int subtype; /* CPU subtype */ + PAIR ppc; /* Previous program counter */ + PAIR pc; /* Program counter */ + PAIR s; /* Stack pointer */ + PAIR x; /* Index register */ + PAIR d; /* Accumulators */ + UINT8 cc; /* Condition codes */ + UINT8 wai_state; /* WAI opcode state ,(or sleep opcode state) */ + UINT8 nmi_state; /* NMI line state */ + UINT8 irq_state[2]; /* IRQ line state [IRQ1,TIN] */ + UINT8 ic_eddge; /* InputCapture eddge , b.0=fall,b.1=raise */ + +// int (*irq_callback)(int irqline); + int extra_cycles; /* cycles used for interrupts */ + void (* const * insn)(void); /* instruction table */ + const UINT8 *cycles; /* clock cycle of instruction table */ + /* internal registers */ + UINT8 port1_ddr; + UINT8 port2_ddr; + UINT8 port3_ddr; + UINT8 port4_ddr; + UINT8 port1_data; + UINT8 port2_data; + UINT8 port3_data; + UINT8 port4_data; + UINT8 tcsr, rmcr; /* Timer Control and Status Register */ + UINT8 pending_tcsr; /* pending IRQ flag for clear IRQflag process */ + UINT8 irq2; /* IRQ2 flags */ + UINT8 ram_ctrl; + PAIR counter; /* free running counter */ + PAIR output_compare; /* output compare */ + UINT16 input_capture; /* input capture */ + + PAIR timer_over; +} m6800_Regs; + +enum { + M6800_PC=1, M6800_S, M6800_A, M6800_B, M6800_X, M6800_CC, + M6800_WAI_STATE }; + +#define M6800_WAI 8 /* set when WAI is waiting for an interrupt */ +#define M6800_SLP 0x10 /* HD63701 only */ + + +#define M6800_IRQ_LINE 0 /* IRQ line number */ +#define M6800_TIN_LINE 1 /* P20/Tin Input Capture line (eddge sense) */ + /* Active eddge is selecrable by internal reg. */ + /* raise eddge : CLEAR_LINE -> ASSERT_LINE */ + /* fall eddge : ASSERT_LINE -> CLEAR_LINE */ + /* it is usuali to use PULSE_LINE state */ +#define M6800_INPUT_LINE_NMI 32 + +unsigned char M6800ReadByte(unsigned short Address); +void M6800WriteByte(unsigned short Address, unsigned char Data); +unsigned char M6800ReadOp(unsigned short Address); +unsigned char M6800ReadOpArg(unsigned short Address); +unsigned char M6800ReadPort(unsigned short Address); +void M6800WritePort(unsigned short Address, unsigned char Data); + +void m6800_init(); +void hd63701_init(); +void m6803_init(); +void m6801_init(); +void m6800_reset(void); +int m6800_get_pc(); +void m6800_get_context(void *dst); +void m6800_set_context(void *src); +int m6800_execute(int cycles); +int m6803_execute(int cycles); +int hd63701_execute(int cycles); +void m6800_set_irq_line(int irqline, int state); + +void m6803_internal_registers_w(unsigned short offset, unsigned char data); +unsigned char m6803_internal_registers_r(unsigned short offset); + +//extern void m6800_get_info(UINT32 state, cpuinfo *info); + +/**************************************************************************** + * For now make the 6801 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_M6801) +#define M6801_A M6800_A +#define M6801_B M6800_B +#define M6801_PC M6800_PC +#define M6801_S M6800_S +#define M6801_X M6800_X +#define M6801_CC M6800_CC +#define M6801_WAI_STATE M6800_WAI_STATE +#define M6801_NMI_STATE M6800_NMI_STATE +#define M6801_IRQ_STATE M6800_IRQ_STATE + +#define M6801_WAI M6800_WAI +#define M6801_IRQ_LINE M6800_IRQ_LINE + +//extern void m6801_get_info(UINT32 state, cpuinfo *info); +#endif + +/**************************************************************************** + * For now make the 6802 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_M6802) +#define M6802_A M6800_A +#define M6802_B M6800_B +#define M6802_PC M6800_PC +#define M6802_S M6800_S +#define M6802_X M6800_X +#define M6802_CC M6800_CC +#define M6802_WAI_STATE M6800_WAI_STATE +#define M6802_NMI_STATE M6800_NMI_STATE +#define M6802_IRQ_STATE M6800_IRQ_STATE + +#define M6802_WAI M6800_WAI +#define M6802_IRQ_LINE M6800_IRQ_LINE + +extern void m6802_get_info(UINT32 state, cpuinfo *info); +#endif + +/**************************************************************************** + * For now make the 6803 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_M6803) +#define M6803_A M6800_A +#define M6803_B M6800_B +#define M6803_PC M6800_PC +#define M6803_S M6800_S +#define M6803_X M6800_X +#define M6803_CC M6800_CC +#define M6803_WAI_STATE M6800_WAI_STATE +#define M6803_NMI_STATE M6800_NMI_STATE +#define M6803_IRQ_STATE M6800_IRQ_STATE + +#define M6803_WAI M6800_WAI +#define M6803_IRQ_LINE M6800_IRQ_LINE +#define M6803_TIN_LINE M6800_TIN_LINE + +//extern void m6803_get_info(UINT32 state, cpuinfo *info); +#endif + +#if (HAS_M6803||HAS_HD63701) +/* By default, on a port write port bits which are not set as output in the DDR */ +/* are set to the value returned by a read from the same port. If you need to */ +/* know the DDR for e.g. port 1, do m6803_internal_registers_r(M6801_DDR1) */ + +#define M6803_DDR1 0x00 +#define M6803_DDR2 0x01 +#define M6803_DDR3 0x04 +#define M6803_DDR4 0x05 + +#define M6803_PORT1 0x100 +#define M6803_PORT2 0x101 +#define M6803_PORT3 0x102 +#define M6803_PORT4 0x103 +#endif + +/**************************************************************************** + * For now make the 6808 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_M6808) +#define M6808_A M6800_A +#define M6808_B M6800_B +#define M6808_PC M6800_PC +#define M6808_S M6800_S +#define M6808_X M6800_X +#define M6808_CC M6800_CC +#define M6808_WAI_STATE M6800_WAI_STATE +#define M6808_NMI_STATE M6800_NMI_STATE +#define M6808_IRQ_STATE M6800_IRQ_STATE + +#define M6808_WAI M6800_WAI +#define M6808_IRQ_LINE M6800_IRQ_LINE + +extern void m6808_get_info(UINT32 state, cpuinfo *info); +#endif + +/**************************************************************************** + * For now make the HD63701 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_HD63701) +#define HD63701_A M6800_A +#define HD63701_B M6800_B +#define HD63701_PC M6800_PC +#define HD63701_S M6800_S +#define HD63701_X M6800_X +#define HD63701_CC M6800_CC +#define HD63701_WAI_STATE M6800_WAI_STATE +#define HD63701_NMI_STATE M6800_NMI_STATE +#define HD63701_IRQ_STATE M6800_IRQ_STATE + +#define HD63701_WAI M6800_WAI +#define HD63701_SLP M6800_SLP +#define HD63701_IRQ_LINE M6800_IRQ_LINE +#define HD63701_TIN_LINE M6800_TIN_LINE + +//extern void hd63701_get_info(UINT32 state, cpuinfo *info); + +void hd63701_trap_pc(void); + +#define HD63701_DDR1 M6803_DDR1 +#define HD63701_DDR2 M6803_DDR2 +#define HD63701_DDR3 M6803_DDR3 +#define HD63701_DDR4 M6803_DDR4 + +#define HD63701_PORT1 M6803_PORT1 +#define HD63701_PORT2 M6803_PORT2 +#define HD63701_PORT3 M6803_PORT3 +#define HD63701_PORT4 M6803_PORT4 + +//READ8_HANDLER( hd63701_internal_registers_r ); +//WRITE8_HANDLER( hd63701_internal_registers_w ); + +#endif + +/**************************************************************************** + * For now make the NSC8105 using the m6800 variables and functions + ****************************************************************************/ +#if (HAS_NSC8105) +#define NSC8105_A M6800_A +#define NSC8105_B M6800_B +#define NSC8105_PC M6800_PC +#define NSC8105_S M6800_S +#define NSC8105_X M6800_X +#define NSC8105_CC M6800_CC +#define NSC8105_WAI_STATE M6800_WAI_STATE +#define NSC8105_NMI_STATE M6800_NMI_STATE +#define NSC8105_IRQ_STATE M6800_IRQ_STATE + +#define NSC8105_WAI M6800_WAI +#define NSC8105_IRQ_LINE M6800_IRQ_LINE +#define NSC8105_TIN_LINE M6800_TIN_LINE + +extern void nsc8105_get_info(UINT32 state, cpuinfo *info); +#endif + +/****************************************************************************/ +/* Read a byte from given memory location */ +/****************************************************************************/ +/* ASG 971005 -- changed to program_read_byte_8/program_write_byte_8 */ +#define M6800_RDMEM(Addr) ((unsigned)M6800ReadByte(Addr)) + +/****************************************************************************/ +/* Write a byte to given memory location */ +/****************************************************************************/ +#define M6800_WRMEM(Addr,Value) (M6800WriteByte(Addr,Value)) + +/****************************************************************************/ +/* M6800_RDOP() is identical to M6800_RDMEM() except it is used for reading */ +/* opcodes. In case of system with memory mapped I/O, this function can be */ +/* used to greatly speed up emulation */ +/****************************************************************************/ +#define M6800_RDOP(Addr) ((unsigned)M6800ReadOp(Addr)) + +/****************************************************************************/ +/* M6800_RDOP_ARG() is identical to M6800_RDOP() but it's used for reading */ +/* opcode arguments. This difference can be used to support systems that */ +/* use different encoding mechanisms for opcodes and opcode arguments */ +/****************************************************************************/ +#define M6800_RDOP_ARG(Addr) ((unsigned)M6800ReadOpArg(Addr)) + +#define M6800_io_read_byte_8(Port) ((unsigned)M6800ReadPort(Port)) +#define M6800_io_write_byte_8(Port,Value) (M6800WritePort(Port, Value)) + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + +#ifdef MAME_DEBUG +offs_t m6800_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +offs_t m6801_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +offs_t m6802_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +ffs_t m6803_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +offs_t m6808_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +offs_t hd63701_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +offs_t nsc8105_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); +#endif + +#endif /* _M6800_H */ diff --git a/src/cpu/m6800_intf.cpp b/src/cpu/m6800_intf.cpp new file mode 100644 index 00000000..f21b182b --- /dev/null +++ b/src/cpu/m6800_intf.cpp @@ -0,0 +1,420 @@ +#include "burnint.h" +#include "m6800_intf.h" + +#define MAX_CPU 8 + +INT32 nM6800Count = 0; + +static M6800Ext *M6800CPUContext; + +static INT32 nM6800CyclesDone[MAX_CPU]; +INT32 nM6800CyclesTotal; + +static UINT8 M6800ReadByteDummyHandler(UINT16) +{ + return 0; +} + +static void M6800WriteByteDummyHandler(UINT16, UINT8) +{ +} + +static UINT8 M6800ReadOpDummyHandler(UINT16) +{ + return 0; +} + +static UINT8 M6800ReadOpArgDummyHandler(UINT16) +{ + return 0; +} + +static UINT8 M6800ReadPortDummyHandler(UINT16) +{ + return 0; +} + +static void M6800WritePortDummyHandler(UINT16, UINT8) +{ +} + +void M6800Reset() +{ + m6800_reset(); +} + +void M6800NewFrame() +{ + for (INT32 i = 0; i < nM6800Count; i++) { + nM6800CyclesDone[i] = 0; + } + nM6800CyclesTotal = 0; +} + +INT32 M6800CoreInit(INT32 num, INT32 type) +{ + nM6800Count = num % MAX_CPU; + + M6800CPUContext = (M6800Ext*)malloc(num * sizeof(M6800Ext)); + if (M6800CPUContext == NULL) { + return 1; + } + + memset(M6800CPUContext, 0, num * sizeof(M6800Ext)); + + for (INT32 i = 0; i < num; i++) { + M6800CPUContext[i].ReadByte = M6800ReadByteDummyHandler; + M6800CPUContext[i].WriteByte = M6800WriteByteDummyHandler; + M6800CPUContext[i].ReadOp = M6800ReadOpDummyHandler; + M6800CPUContext[i].ReadOpArg = M6800ReadOpArgDummyHandler; + M6800CPUContext[i].ReadPort = M6800ReadPortDummyHandler; + M6800CPUContext[i].WritePort = M6800WritePortDummyHandler; + + nM6800CyclesDone[i] = 0; + + for (INT32 j = 0; j < (0x0100 * 3); j++) { + M6800CPUContext[i].pMemMap[j] = NULL; + } + } + + nM6800CyclesTotal = 0; + + if (type == CPU_TYPE_M6800) m6800_init(); + if (type == CPU_TYPE_HD63701) hd63701_init(); + if (type == CPU_TYPE_M6803) m6803_init(); + if (type == CPU_TYPE_M6801) m6801_init(); + + for (INT32 i = 0; i < num; i++) + CpuCheatRegister(0x0007, i); + + return 0; +} + +INT32 M6800Init(INT32 num) +{ + return M6800CoreInit(num, CPU_TYPE_M6800); +} + +INT32 HD63701Init(INT32 num) +{ + return M6800CoreInit(num, CPU_TYPE_HD63701); +} + +INT32 M6803Init(INT32 num) +{ + return M6800CoreInit(num, CPU_TYPE_M6803); +} + +INT32 M6801Init(INT32 num) +{ + return M6800CoreInit(num, CPU_TYPE_M6801); +} + +void M6800Exit() +{ + nM6800Count = 0; + + if (M6800CPUContext) { + free(M6800CPUContext); + M6800CPUContext = NULL; + } +} + +void M6800SetIRQ(INT32 vector, INT32 status) +{ + if (status == M6800_IRQSTATUS_NONE) { + m6800_set_irq_line(vector, 0); + } + + if (status == M6800_IRQSTATUS_ACK) { + m6800_set_irq_line(vector, 1); + } + + if (status == M6800_IRQSTATUS_AUTO) { + m6800_set_irq_line(vector, 1); + m6800_execute(0); + m6800_set_irq_line(vector, 0); + m6800_execute(0); + } +} + +void HD63701SetIRQ(INT32 vector, INT32 status) +{ + if (status == HD63701_IRQSTATUS_NONE) { + m6800_set_irq_line(vector, 0); + } + + if (status == HD63701_IRQSTATUS_ACK) { + m6800_set_irq_line(vector, 1); + } + + if (status == HD63701_IRQSTATUS_AUTO) { + m6800_set_irq_line(vector, 1); + hd63701_execute(0); + m6800_set_irq_line(vector, 0); + hd63701_execute(0); + } +} + +void M6803SetIRQ(INT32 vector, INT32 status) +{ + if (status == M6803_IRQSTATUS_NONE) { + m6800_set_irq_line(vector, 0); + } + + if (status == M6803_IRQSTATUS_ACK) { + m6800_set_irq_line(vector, 1); + } + + if (status == M6803_IRQSTATUS_AUTO) { + m6800_set_irq_line(vector, 1); + m6803_execute(0); + m6800_set_irq_line(vector, 0); + m6803_execute(0); + } +} + +void M6801SetIRQ(INT32 vector, INT32 status) +{ + if (status == M6801_IRQSTATUS_NONE) { + m6800_set_irq_line(vector, 0); + } + + if (status == M6801_IRQSTATUS_ACK) { + m6800_set_irq_line(vector, 1); + } + + if (status == M6801_IRQSTATUS_AUTO) { + m6800_set_irq_line(vector, 1); + m6803_execute(0); + m6800_set_irq_line(vector, 0); + m6803_execute(0); + } +} + +INT32 M6800Run(INT32 cycles) +{ + cycles = m6800_execute(cycles); + + nM6800CyclesTotal += cycles; + + return cycles; +} + +INT32 HD63701Run(INT32 cycles) +{ + cycles = hd63701_execute(cycles); + + nM6800CyclesTotal += cycles; + + return cycles; +} + +INT32 M6803Run(INT32 cycles) +{ + cycles = m6803_execute(cycles); + + nM6800CyclesTotal += cycles; + + return cycles; +} + +void M6800RunEnd() +{ + +} + +INT32 M6800GetPC() +{ + return m6800_get_pc(); +} + +INT32 M6800MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = M6800CPUContext[0].pMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + if (nType & M6800_READ) { + pMemMap[0 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6800_WRITE) { + pMemMap[0x100 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6800_FETCH) { + pMemMap[0x200 + i] = pMemory + ((i - cStart) << 8); + } + } + return 0; + +} + +void M6800SetReadByteHandler(UINT8 (*pHandler)(UINT16)) +{ + M6800CPUContext[0].ReadByte = pHandler; +} + +void M6800SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)) +{ + M6800CPUContext[0].WriteByte = pHandler; +} + +void M6800SetReadOpHandler(UINT8 (*pHandler)(UINT16)) +{ + M6800CPUContext[0].ReadOp = pHandler; +} + +void M6800SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)) +{ + M6800CPUContext[0].ReadOpArg = pHandler; +} + +void M6800SetReadPortHandler(UINT8 (*pHandler)(UINT16)) +{ + M6800CPUContext[0].ReadPort = pHandler; +} + +void M6800SetWritePortHandler(void (*pHandler)(UINT16, UINT8)) +{ + M6800CPUContext[0].WritePort = pHandler; +} + +UINT8 M6800ReadByte(UINT16 Address) +{ + // check mem map + UINT8 * pr = M6800CPUContext[0].pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (M6800CPUContext[0].ReadByte != NULL) { + return M6800CPUContext[0].ReadByte(Address); + } + + return 0; +} + +void M6800WriteByte(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = M6800CPUContext[0].pMemMap[0x100 | (Address >> 8)]; + if (pr != NULL) { + pr[Address & 0xff] = Data; + return; + } + + // check handler + if (M6800CPUContext[0].WriteByte != NULL) { + M6800CPUContext[0].WriteByte(Address, Data); + return; + } +} + +UINT8 M6800ReadOp(UINT16 Address) +{ + // check mem map + UINT8 * pr = M6800CPUContext[0].pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (M6800CPUContext[0].ReadOp != NULL) { + return M6800CPUContext[0].ReadOp(Address); + } + + return 0; +} + +UINT8 M6800ReadOpArg(UINT16 Address) +{ + // check mem map + UINT8 * pr = M6800CPUContext[0].pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (M6800CPUContext[0].ReadOpArg != NULL) { + return M6800CPUContext[0].ReadOpArg(Address); + } + + return 0; +} + +UINT8 M6800ReadPort(UINT16 Address) +{ + // check handler + if (M6800CPUContext[0].ReadPort != NULL) { + return M6800CPUContext[0].ReadPort(Address); + } + + return 0; +} + +void M6800WritePort(UINT16 Address, UINT8 Data) +{ + // check handler + if (M6800CPUContext[0].WritePort != NULL) { + M6800CPUContext[0].WritePort(Address, Data); + return; + } +} + +void M6800WriteRom(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = M6800CPUContext[0].pMemMap[0x000 | (Address >> 8)]; + UINT8 * pw = M6800CPUContext[0].pMemMap[0x100 | (Address >> 8)]; + UINT8 * pf = M6800CPUContext[0].pMemMap[0x200 | (Address >> 8)]; + + if (pr != NULL) { + pr[Address & 0xff] = Data; + } + + if (pw != NULL) { + pw[Address & 0xff] = Data; + } + + if (pf != NULL) { + pf[Address & 0xff] = Data; + } + + // check handler + if (M6800CPUContext[0].WriteByte != NULL) { + M6800CPUContext[0].WriteByte(Address, Data); + return; + } +} + +INT32 M6800Scan(INT32 nAction) +{ + struct BurnArea ba; + + if (nAction & ACB_DRIVER_DATA) { + m6800_Regs *tmp; + void (* const * insn)(void); + const UINT8 *cycles; + + for (INT32 i = 0; i < nM6800Count; i++) { + tmp = &M6800CPUContext[i].reg; + + char szName[] = "M6800 #n"; + szName[7] = '0' + i; + + cycles = tmp->cycles; + insn = tmp->insn; + + ba.Data = &M6800CPUContext[i].reg; + ba.nLen = sizeof(M6800CPUContext[i].reg); + ba.szName = szName; + BurnAcb(&ba); + + tmp->cycles = cycles; + tmp->insn = insn; + } + } + + return 0; +} diff --git a/src/cpu/m6800_intf.h b/src/cpu/m6800_intf.h new file mode 100644 index 00000000..de5ebf26 --- /dev/null +++ b/src/cpu/m6800_intf.h @@ -0,0 +1,179 @@ +#include "M6800.h" + +typedef UINT8 (*pReadByteHandler)(UINT16 a); +typedef void (*pWriteByteHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadOpHandler)(UINT16 a); +typedef UINT8 (*pReadOpArgHandler)(UINT16 a); +typedef UINT8 (*pReadPortHandler)(UINT16 a); +typedef void (*pWritePortHandler)(UINT16 a, UINT8 d); + +struct M6800Ext { + + m6800_Regs reg; + + UINT8* pMemMap[0x100 * 3]; + + pReadByteHandler ReadByte; + pWriteByteHandler WriteByte; + pReadOpHandler ReadOp; + pReadOpArgHandler ReadOpArg; + pReadPortHandler ReadPort; + pWritePortHandler WritePort; + + INT32 nCyclesTotal; + INT32 nCyclesSegment; + INT32 nCyclesLeft; +}; + +#define M6800_IRQSTATUS_NONE 0 +#define M6800_IRQSTATUS_ACK 1 +#define M6800_IRQSTATUS_AUTO 2 + +#define HD63701_IRQSTATUS_NONE M6800_IRQSTATUS_NONE +#define HD63701_IRQSTATUS_ACK M6800_IRQSTATUS_ACK +#define HD63701_IRQSTATUS_AUTO M6800_IRQSTATUS_AUTO + +#define HD63701_INPUT_LINE_NMI M6800_INPUT_LINE_NMI +#define HD63701_IRQ_LINE M6800_IRQ_LINE +#define HD63701_TIN_LINE M6800_TIN_LINE + +#define M6801_IRQSTATUS_NONE M6800_IRQSTATUS_NONE +#define M6801_IRQSTATUS_ACK M6800_IRQSTATUS_ACK +#define M6801_IRQSTATUS_AUTO M6800_IRQSTATUS_AUTO + +#define M6801_INPUT_LINE_NMI M6800_INPUT_LINE_NMI +#define M6801_IRQ_LINE M6800_IRQ_LINE +#define M6801_TIN_LINE M6800_TIN_LINE + +#define M6803_IRQSTATUS_NONE M6800_IRQSTATUS_NONE +#define M6803_IRQSTATUS_ACK M6800_IRQSTATUS_ACK +#define M6803_IRQSTATUS_AUTO M6800_IRQSTATUS_AUTO + +#define M6803_INPUT_LINE_NMI M6800_INPUT_LINE_NMI +#define M6803_IRQ_LINE M6800_IRQ_LINE +#define M6803_TIN_LINE M6800_TIN_LINE + +#define M6800_READ 1 +#define M6800_WRITE 2 +#define M6800_FETCH 4 + +#define HD63701_READ 1 +#define HD63701_WRITE 2 +#define HD63701_FETCH 4 + +#define M6801_READ 1 +#define M6801_WRITE 2 +#define M6801_FETCH 4 + +#define M6803_READ 1 +#define M6803_WRITE 2 +#define M6803_FETCH 4 + +#define M6800_RAM (M6800_READ | M6800_WRITE | M6800_FETCH) +#define M6800_ROM (M6800_READ | M6800_FETCH) + +#define HD63701_RAM (HD63701_READ | HD63701_WRITE | HD63701_FETCH) +#define HD63701_ROM (HD63701_READ | HD63701_FETCH) + +#define M6801_RAM (M6801_READ | M6801_WRITE | M6801_FETCH) +#define M6801_ROM (M6801_READ | M6801_FETCH) + +#define M6803_RAM (M6803_READ | M6803_WRITE | M6803_FETCH) +#define M6803_ROM (M6803_READ | M6803_FETCH) + +#define CPU_TYPE_M6800 1 +#define CPU_TYPE_HD63701 2 +#define CPU_TYPE_M6803 3 +#define CPU_TYPE_M6801 4 + +extern INT32 nM6800Count; + +extern INT32 nM6800CyclesTotal; + +void M6800Reset(); +#define HD63701Reset M6800Reset +#define M6803Reset M6800Reset +#define M6801Reset M6800Reset + +void M6800NewFrame(); +#define HD63701NewFrame M6800NewFrame +#define M6803NewFrame M6800NewFrame +#define M6801NewFrame M6800NewFrame + +INT32 M6800CoreInit(INT32 num, INT32 type); +INT32 M6800Init(INT32 num); +INT32 HD63701Init(INT32 num); +INT32 M6803Init(INT32 num); +INT32 M6801Init(INT32 num); + +void M6800Exit(); +#define HD63701Exit M6800Exit +#define M6803Exit M6800Exit +#define M6801Exit M6800Exit + +void M6800SetIRQ(INT32 vector, INT32 status); +void HD63701SetIRQ(INT32 vector, INT32 status); +void M6803SetIRQ(INT32 vector, INT32 status); +void M6801SetIRQ(INT32 vector, INT32 status); + +INT32 M6800Run(INT32 cycles); +INT32 HD63701Run(INT32 cycles); +INT32 M6803Run(INT32 cycles); +#define M6801Run(nCycles) M6803Run(nCycles) + +void M6800RunEnd(); +#define HD63701RunEnd M6800RunEnd +#define M6803RunEnd M6800RunEnd +#define M6801RunEnd M6800RunEnd + +INT32 M6800GetPC(); +#define HD63701GetPC M6800GetPC +#define M6803GetPC M6800GetPC +#define M6801GetPC M6800GetPC + +INT32 M6800MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType); +#define HD63701MapMemory M6800MapMemory +#define M6803MapMemory M6800MapMemory +#define M6801MapMemory M6800MapMemory + +void M6800SetReadByteHandler(UINT8 (*pHandler)(UINT16)); +#define HD63701SetReadByteHandler M6800SetReadByteHandler +#define M6803SetReadByteHandler M6800SetReadByteHandler +#define M6801SetReadByteHandler M6800SetReadByteHandler + +void M6800SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)); +#define HD63701SetWriteByteHandler M6800SetWriteByteHandler +#define M6803SetWriteByteHandler M6800SetWriteByteHandler +#define M6801SetWriteByteHandler M6800SetWriteByteHandler + +void M6800SetReadOpHandler(UINT8 (*pHandler)(UINT16)); +#define HD63701SetReadOpHandler M6800SetReadOpHandler +#define M6803SetReadOpHandler M6800SetReadOpHandler +#define M6801SetReadOpHandler M6800SetReadOpHandler + +void M6800SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)); +#define HD63701SetReadOpArgHandler M6800SetReadOpArgHandler +#define M6803SetReadOpArgHandler M6800SetReadOpArgHandler +#define M6801SetReadOpArgHandler M6800SetReadOpArgHandler + +void M6800SetReadPortHandler(UINT8 (*pHandler)(UINT16)); +#define HD63701SetReadPortHandler M6800SetReadPortHandler +#define M6803SetReadPortHandler M6800SetReadPortHandler +#define M6801SetReadPortHandler M6800SetReadPortHandler + +void M6800SetWritePortHandler(void (*pHandler)(UINT16, UINT8)); +#define HD63701SetWritePortHandler M6800SetWritePortHandler +#define M6803SetWritePortHandler M6800SetWritePortHandler +#define M6801SetWritePortHandler M6800SetWritePortHandler + +INT32 M6800Scan(INT32 nAction); +#define HD63701Scan M6800Scan +#define M6803Scan M6800Scan +#define M6801Scan M6800Scan + +void M6800WriteRom(UINT16 Address, UINT8 Data); + +inline static INT32 M6800TotalCycles() +{ + return nM6800CyclesTotal; +} diff --git a/src/cpu/m6805/6805ops.c b/src/cpu/m6805/6805ops.c new file mode 100644 index 00000000..76028566 --- /dev/null +++ b/src/cpu/m6805/6805ops.c @@ -0,0 +1,1822 @@ + +/* + +HNZC + +? = undefined +* = affected +- = unaffected +0 = cleared +1 = set +# = ccr directly affected by instruction +@ = special - carry set if bit 7 is set + +*/ + +static void illegal( void ) +{ +// logerror("M6805: illegal opcode\n"); +} + +/* $00/$02/$04/$06/$08/$0A/$0C/$0E BRSET direct,relative ---- */ +M6805_INLINE void brset (UINT8 bit) +{ + UINT8 t,r; + DIRBYTE(r); + IMMBYTE(t); + + CLC; + + if (r&bit) { + SEC; + PC+=SIGNED(t); + + if (t==0xfd) + { + /* speed up busy loops */ + if(m6805_ICount > 0) + m6805_ICount = 0; + } + } +} + +/* $01/$03/$05/$07/$09/$0B/$0D/$0F BRCLR direct,relative ---- */ +M6805_INLINE void brclr (UINT8 bit) +{ + UINT8 t,r; + DIRBYTE(r); + IMMBYTE(t); + + SEC; + + if (!(r&bit)) { + CLC; + PC+=SIGNED(t); + + if (t==0xfd) + { + /* speed up busy loops */ + if(m6805_ICount > 0) + m6805_ICount = 0; + } + } +} + +/* $10/$12/$14/$16/$18/$1A/$1C/$1E BSET direct ---- */ +M6805_INLINE void bset (UINT8 bit) +{ + UINT8 t,r; + DIRBYTE(t); r=t|bit; + WM(EAD,r); +} + +/* $11/$13/$15/$17/$19/$1B/$1D/$1F BCLR direct ---- */ +M6805_INLINE void bclr (UINT8 bit) +{ + UINT8 t,r; + DIRBYTE(t); r=t&(~bit); + WM(EAD,r); +} + +/* $20 BRA relative ---- */ +M6805_INLINE void bra( void ) +{ + UINT8 t; + IMMBYTE(t);PC+=SIGNED(t); + if (t==0xfe) + { + /* speed up busy loops */ + if(m6805_ICount > 0) + m6805_ICount = 0; + } +} + +/* $21 BRN relative ---- */ +M6805_INLINE void brn( void ) +{ + UINT8 t; + IMMBYTE(t); +} + +/* $22 BHI relative ---- */ +M6805_INLINE void bhi( void ) +{ + BRANCH( !(CC&(CFLAG|ZFLAG)) ); +} + +/* $23 BLS relative ---- */ +M6805_INLINE void bls( void ) +{ + BRANCH( CC&(CFLAG|ZFLAG) ); +} + +/* $24 BCC relative ---- */ +M6805_INLINE void bcc( void ) +{ + BRANCH( !(CC&CFLAG) ); +} + +/* $25 BCS relative ---- */ +M6805_INLINE void bcs( void ) +{ + BRANCH( CC&CFLAG ); +} + +/* $26 BNE relative ---- */ +M6805_INLINE void bne( void ) +{ + BRANCH( !(CC&ZFLAG) ); +} + +/* $27 BEQ relative ---- */ +M6805_INLINE void beq( void ) +{ + BRANCH( CC&ZFLAG ); +} + +/* $28 BHCC relative ---- */ +M6805_INLINE void bhcc( void ) +{ + BRANCH( !(CC&HFLAG) ); +} + +/* $29 BHCS relative ---- */ +M6805_INLINE void bhcs( void ) +{ + BRANCH( CC&HFLAG ); +} + +/* $2a BPL relative ---- */ +M6805_INLINE void bpl( void ) +{ + BRANCH( !(CC&NFLAG) ); +} + +/* $2b BMI relative ---- */ +M6805_INLINE void bmi( void ) +{ + BRANCH( CC&NFLAG ); +} + +/* $2c BMC relative ---- */ +M6805_INLINE void bmc( void ) +{ + BRANCH( !(CC&IFLAG) ); +} + +/* $2d BMS relative ---- */ +M6805_INLINE void bms( void ) +{ + BRANCH( CC&IFLAG ); +} + +/* $2e BIL relative ---- */ +M6805_INLINE void bil( void ) +{ + if(SUBTYPE==SUBTYPE_HD63705) + { + BRANCH( m6805.nmi_state!=CLEAR_LINE ); + } + else + { + BRANCH( m6805.irq_state[0]!=CLEAR_LINE ); + } +} + +/* $2f BIH relative ---- */ +M6805_INLINE void bih( void ) +{ + if(SUBTYPE==SUBTYPE_HD63705) + { + BRANCH( m6805.nmi_state==CLEAR_LINE ); + } + else + { + BRANCH( m6805.irq_state[0]==CLEAR_LINE ); + } +} + +/* $30 NEG direct -*** */ +M6805_INLINE void neg_di( void ) +{ + UINT8 t; + UINT16 r; + DIRBYTE(t); r=-t; + CLR_NZC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $31 ILLEGAL */ + +/* $32 ILLEGAL */ + +/* $33 COM direct -**1 */ +M6805_INLINE void com_di( void ) +{ + UINT8 t; + DIRBYTE(t); t = ~t; + CLR_NZ; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $34 LSR direct -0** */ +M6805_INLINE void lsr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t&0x01); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $35 ILLEGAL */ + +/* $36 ROR direct -*** */ +M6805_INLINE void ror_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = (CC & 0x01) << 7; + CLR_NZC; + CC |= (t & 0x01); + r |= t>>1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $37 ASR direct ?*** */ +M6805_INLINE void asr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; CC|=(t&0x01); + t>>=1; t|=((t&0x40)<<1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $38 LSL direct ?*** */ +M6805_INLINE void lsl_di( void ) +{ + UINT8 t; + UINT16 r; + DIRBYTE(t); + r = t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $39 ROL direct -*** */ +M6805_INLINE void rol_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = CC & 0x01; + r |= t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $3a DEC direct -**- */ +M6805_INLINE void dec_di( void ) +{ + UINT8 t; + DIRBYTE(t); + --t; + CLR_NZ; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $3b ILLEGAL */ + +/* $3c INC direct -**- */ +M6805_INLINE void inc_di( void ) +{ + UINT8 t; + DIRBYTE(t); + ++t; + CLR_NZ; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $3d TST direct -**- */ +M6805_INLINE void tst_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZ; SET_NZ8(t); +} + +/* $3e ILLEGAL */ + +/* $3f CLR direct -0100 */ +M6805_INLINE void clr_di( void ) +{ + DIRECT; + CLR_NZC; SEZ; + WM(EAD,0); +} + +/* $40 NEGA inherent ?*** */ +M6805_INLINE void nega( void ) +{ + UINT16 r; + r = -A; + CLR_NZC; SET_FLAGS8(0,A,r); + A = r; +} + +/* $41 ILLEGAL */ + +/* $42 ILLEGAL */ + +/* $43 COMA inherent -**1 */ +M6805_INLINE void coma( void ) +{ + A = ~A; + CLR_NZ; + SET_NZ8(A); + SEC; +} + +/* $44 LSRA inherent -0** */ +M6805_INLINE void lsra( void ) +{ + CLR_NZC; + CC |= (A & 0x01); + A >>= 1; + SET_Z8(A); +} + +/* $45 ILLEGAL */ + +/* $46 RORA inherent -*** */ +M6805_INLINE void rora( void ) +{ + UINT8 r; + r = (CC & 0x01) << 7; + CLR_NZC; + CC |= (A & 0x01); + r |= A >> 1; + SET_NZ8(r); + A = r; +} + +/* $47 ASRA inherent ?*** */ +M6805_INLINE void asra( void ) +{ + CLR_NZC; + CC |= (A & 0x01); + A = (A & 0x80) | (A >> 1); + SET_NZ8(A); +} + +/* $48 LSLA inherent ?*** */ +M6805_INLINE void lsla( void ) +{ + UINT16 r; + r = A << 1; + CLR_NZC; + SET_FLAGS8(A,A,r); + A = r; +} + +/* $49 ROLA inherent -*** */ +M6805_INLINE void rola( void ) +{ + UINT16 t,r; + t = A; + r = CC & 0x01; + r |= t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + A = r; +} + +/* $4a DECA inherent -**- */ +M6805_INLINE void deca( void ) +{ + --A; + CLR_NZ; + SET_FLAGS8D(A); +} + +/* $4b ILLEGAL */ + +/* $4c INCA inherent -**- */ +M6805_INLINE void inca( void ) +{ + ++A; + CLR_NZ; + SET_FLAGS8I(A); +} + +/* $4d TSTA inherent -**- */ +M6805_INLINE void tsta( void ) +{ + CLR_NZ; + SET_NZ8(A); +} + +/* $4e ILLEGAL */ + +/* $4f CLRA inherent -010 */ +M6805_INLINE void clra( void ) +{ + A = 0; + CLR_NZ; + SEZ; +} + +/* $50 NEGX inherent ?*** */ +M6805_INLINE void negx( void ) +{ + UINT16 r; + r = -X; + CLR_NZC; + SET_FLAGS8(0,X,r); + X = r; +} + +/* $51 ILLEGAL */ + +/* $52 ILLEGAL */ + +/* $53 COMX inherent -**1 */ +M6805_INLINE void comx( void ) +{ + X = ~X; + CLR_NZ; + SET_NZ8(X); + SEC; +} + +/* $54 LSRX inherent -0** */ +M6805_INLINE void lsrx( void ) +{ + CLR_NZC; + CC |= (X & 0x01); + X >>= 1; + SET_Z8(X); +} + +/* $55 ILLEGAL */ + +/* $56 RORX inherent -*** */ +M6805_INLINE void rorx( void ) +{ + UINT8 r; + r = (CC & 0x01) << 7; + CLR_NZC; + CC |= (X & 0x01); + r |= X>>1; + SET_NZ8(r); + X = r; +} + +/* $57 ASRX inherent ?*** */ +M6805_INLINE void asrx( void ) +{ + CLR_NZC; + CC |= (X & 0x01); + X = (X & 0x80) | (X >> 1); + SET_NZ8(X); +} + +/* $58 ASLX inherent ?*** */ +M6805_INLINE void aslx( void ) +{ + UINT16 r; + r = X << 1; + CLR_NZC; + SET_FLAGS8(X,X,r); + X = r; +} + +/* $59 ROLX inherent -*** */ +M6805_INLINE void rolx( void ) +{ + UINT16 t,r; + t = X; + r = CC & 0x01; + r |= t<<1; + CLR_NZC; + SET_FLAGS8(t,t,r); + X = r; +} + +/* $5a DECX inherent -**- */ +M6805_INLINE void decx( void ) +{ + --X; + CLR_NZ; + SET_FLAGS8D(X); +} + +/* $5b ILLEGAL */ + +/* $5c INCX inherent -**- */ +M6805_INLINE void incx( void ) +{ + ++X; + CLR_NZ; + SET_FLAGS8I(X); +} + +/* $5d TSTX inherent -**- */ +M6805_INLINE void tstx( void ) +{ + CLR_NZ; + SET_NZ8(X); +} + +/* $5e ILLEGAL */ + +/* $5f CLRX inherent -010 */ +M6805_INLINE void clrx( void ) +{ + X = 0; + CLR_NZC; + SEZ; +} + +/* $60 NEG indexed, 1 byte offset -*** */ +M6805_INLINE void neg_ix1( void ) +{ + UINT8 t; + UINT16 r; + IDX1BYTE(t); r=-t; + CLR_NZC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $61 ILLEGAL */ + +/* $62 ILLEGAL */ + +/* $63 COM indexed, 1 byte offset -**1 */ +M6805_INLINE void com_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); t = ~t; + CLR_NZ; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $64 LSR indexed, 1 byte offset -0** */ +M6805_INLINE void lsr_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + CLR_NZC; + CC |= (t & 0x01); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $65 ILLEGAL */ + +/* $66 ROR indexed, 1 byte offset -*** */ +M6805_INLINE void ror_ix1( void ) +{ + UINT8 t,r; + IDX1BYTE(t); + r = (CC & 0x01) << 7; + CLR_NZC; + CC |= (t & 0x01); + r |= t>>1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $67 ASR indexed, 1 byte offset ?*** */ +M6805_INLINE void asr_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + CLR_NZC; CC|=(t&0x01); + t>>=1; t|=((t&0x40)<<1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $68 LSL indexed, 1 byte offset ?*** */ +M6805_INLINE void lsl_ix1( void ) +{ + UINT8 t; + UINT16 r; + IDX1BYTE(t); + r = t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $69 ROL indexed, 1 byte offset -*** */ +M6805_INLINE void rol_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = CC & 0x01; + r |= t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $6a DEC indexed, 1 byte offset -**- */ +M6805_INLINE void dec_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + --t; + CLR_NZ; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $6b ILLEGAL */ + +/* $6c INC indexed, 1 byte offset -**- */ +M6805_INLINE void inc_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + ++t; + CLR_NZ; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $6d TST indexed, 1 byte offset -**- */ +M6805_INLINE void tst_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + CLR_NZ; SET_NZ8(t); +} + +/* $6e ILLEGAL */ + +/* $6f CLR indexed, 1 byte offset -0100 */ +M6805_INLINE void clr_ix1( void ) +{ + INDEXED1; + CLR_NZC; SEZ; + WM(EAD,0); +} + +/* $70 NEG indexed -*** */ +M6805_INLINE void neg_ix( void ) +{ + UINT8 t; + UINT16 r; + IDXBYTE(t); r=-t; + CLR_NZC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $71 ILLEGAL */ + +/* $72 ILLEGAL */ + +/* $73 COM indexed -**1 */ +M6805_INLINE void com_ix( void ) +{ + UINT8 t; + IDXBYTE(t); t = ~t; + CLR_NZ; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $74 LSR indexed -0** */ +M6805_INLINE void lsr_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + CLR_NZC; + CC |= (t & 0x01); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $75 ILLEGAL */ + +/* $76 ROR indexed -*** */ +M6805_INLINE void ror_ix( void ) +{ + UINT8 t,r; + IDXBYTE(t); + r = (CC & 0x01) << 7; + CLR_NZC; + CC |= (t & 0x01); + r |= t >> 1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $77 ASR indexed ?*** */ +M6805_INLINE void asr_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + CLR_NZC; + CC |= (t & 0x01); + t = (t & 0x80) | (t >> 1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $78 LSL indexed ?*** */ +M6805_INLINE void lsl_ix( void ) +{ + UINT8 t; + UINT16 r; + IDXBYTE(t); r=t<<1; + CLR_NZC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $79 ROL indexed -*** */ +M6805_INLINE void rol_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = CC & 0x01; + r |= t << 1; + CLR_NZC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $7a DEC indexed -**- */ +M6805_INLINE void dec_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + --t; + CLR_NZ; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $7b ILLEGAL */ + +/* $7c INC indexed -**- */ +M6805_INLINE void inc_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + ++t; + CLR_NZ; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $7d TST indexed -**- */ +M6805_INLINE void tst_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + CLR_NZ; SET_NZ8(t); +} + +/* $7e ILLEGAL */ + +/* $7f CLR indexed -0100 */ +M6805_INLINE void clr_ix( void ) +{ + INDEXED; + CLR_NZC; SEZ; + WM(EAD,0); +} + +/* $80 RTI inherent #### */ +M6805_INLINE void rti( void ) +{ + PULLBYTE(CC); + PULLBYTE(A); + PULLBYTE(X); + PULLWORD(pPC); + change_pc(PC); +#if IRQ_LEVEL_DETECT + if( m6805.irq_state != CLEAR_LINE && (CC & IFLAG) == 0 ) + m6805.pending_interrupts |= M6805_INT_IRQ; +#endif +} + +/* $81 RTS inherent ---- */ +M6805_INLINE void rts( void ) +{ + PULLWORD(pPC); + change_pc(PC); +} + +/* $82 ILLEGAL */ + +/* $83 SWI absolute indirect ---- */ +M6805_INLINE void swi( void ) +{ + PUSHWORD(m6805.pc); + PUSHBYTE(m6805.x); + PUSHBYTE(m6805.a); + PUSHBYTE(m6805.cc); + SEI; + if(SUBTYPE==SUBTYPE_HD63705) RM16( 0x1ffa, &pPC ); else RM16( 0xfffc, &pPC ); + change_pc(PC); +} + +/* $84 ILLEGAL */ + +/* $85 ILLEGAL */ + +/* $86 ILLEGAL */ + +/* $87 ILLEGAL */ + +/* $88 ILLEGAL */ + +/* $89 ILLEGAL */ + +/* $8A ILLEGAL */ + +/* $8B ILLEGAL */ + +/* $8C ILLEGAL */ + +/* $8D ILLEGAL */ + +/* $8E ILLEGAL */ + +/* $8F ILLEGAL */ + +/* $90 ILLEGAL */ + +/* $91 ILLEGAL */ + +/* $92 ILLEGAL */ + +/* $93 ILLEGAL */ + +/* $94 ILLEGAL */ + +/* $95 ILLEGAL */ + +/* $96 ILLEGAL */ + +/* $97 TAX inherent ---- */ +M6805_INLINE void tax (void) +{ + X = A; +} + +/* $98 CLC */ + +/* $99 SEC */ + +/* $9A CLI */ + +/* $9B SEI */ + +/* $9C RSP inherent ---- */ +M6805_INLINE void rsp (void) +{ + S = SP_MASK; +} + +/* $9D NOP inherent ---- */ +M6805_INLINE void nop (void) +{ +} + +/* $9E ILLEGAL */ + +/* $9F TXA inherent ---- */ +M6805_INLINE void txa (void) +{ + A = X; +} + +/* $a0 SUBA immediate ?*** */ +M6805_INLINE void suba_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a1 CMPA immediate ?*** */ +M6805_INLINE void cmpa_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $a2 SBCA immediate ?*** */ +M6805_INLINE void sbca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a3 CPX immediate -*** */ +M6805_INLINE void cpx_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $a4 ANDA immediate -**- */ +M6805_INLINE void anda_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $a5 BITA immediate -**- */ +M6805_INLINE void bita_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $a6 LDA immediate -**- */ +M6805_INLINE void lda_im( void ) +{ + IMMBYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $a7 ILLEGAL */ + +/* $a8 EORA immediate -**- */ +M6805_INLINE void eora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $a9 ADCA immediate **** */ +M6805_INLINE void adca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aa ORA immediate -**- */ +M6805_INLINE void ora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $ab ADDA immediate **** */ +M6805_INLINE void adda_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $ac ILLEGAL */ + +/* $ad BSR ---- */ +M6805_INLINE void bsr( void ) +{ + UINT8 t; + IMMBYTE(t); + PUSHWORD(m6805.pc); + PC += SIGNED(t); +} + +/* $ae LDX immediate -**- */ +M6805_INLINE void ldx_im( void ) +{ + IMMBYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $af ILLEGAL */ + +/* $b0 SUBA direct ?*** */ +M6805_INLINE void suba_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b1 CMPA direct ?*** */ +M6805_INLINE void cmpa_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $b2 SBCA direct ?*** */ +M6805_INLINE void sbca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b3 CPX direct -*** */ +M6805_INLINE void cpx_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $b4 ANDA direct -**- */ +M6805_INLINE void anda_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $b5 BITA direct -**- */ +M6805_INLINE void bita_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $b6 LDA direct -**- */ +M6805_INLINE void lda_di( void ) +{ + DIRBYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $b7 STA direct -**- */ +M6805_INLINE void sta_di( void ) +{ + CLR_NZ; + SET_NZ8(A); + DIRECT; + WM(EAD,A); +} + +/* $b8 EORA direct -**- */ +M6805_INLINE void eora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $b9 ADCA direct **** */ +M6805_INLINE void adca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $ba ORA direct -**- */ +M6805_INLINE void ora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $bb ADDA direct **** */ +M6805_INLINE void adda_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bc JMP direct -*** */ +M6805_INLINE void jmp_di( void ) +{ + DIRECT; + PC = EA; + change_pc(PC); +} + +/* $bd JSR direct ---- */ +M6805_INLINE void jsr_di( void ) +{ + DIRECT; + PUSHWORD(m6805.pc); + PC = EA; + change_pc(PC); +} + +/* $be LDX direct -**- */ +M6805_INLINE void ldx_di( void ) +{ + DIRBYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $bf STX direct -**- */ +M6805_INLINE void stx_di( void ) +{ + CLR_NZ; + SET_NZ8(X); + DIRECT; + WM(EAD,X); +} + +/* $c0 SUBA extended ?*** */ +M6805_INLINE void suba_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $c1 CMPA extended ?*** */ +M6805_INLINE void cmpa_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $c2 SBCA extended ?*** */ +M6805_INLINE void sbca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $c3 CPX extended -*** */ +M6805_INLINE void cpx_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $c4 ANDA extended -**- */ +M6805_INLINE void anda_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $c5 BITA extended -**- */ +M6805_INLINE void bita_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $c6 LDA extended -**- */ +M6805_INLINE void lda_ex( void ) +{ + EXTBYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $c7 STA extended -**- */ +M6805_INLINE void sta_ex( void ) +{ + CLR_NZ; + SET_NZ8(A); + EXTENDED; + WM(EAD,A); +} + +/* $c8 EORA extended -**- */ +M6805_INLINE void eora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $c9 ADCA extended **** */ +M6805_INLINE void adca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $ca ORA extended -**- */ +M6805_INLINE void ora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $cb ADDA extended **** */ +M6805_INLINE void adda_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $cc JMP extended -*** */ +M6805_INLINE void jmp_ex( void ) +{ + EXTENDED; + PC = EA; + change_pc(PC); +} + +/* $cd JSR extended ---- */ +M6805_INLINE void jsr_ex( void ) +{ + EXTENDED; + PUSHWORD(m6805.pc); + PC = EA; + change_pc(PC); +} + +/* $ce LDX extended -**- */ +M6805_INLINE void ldx_ex( void ) +{ + EXTBYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $cf STX extended -**- */ +M6805_INLINE void stx_ex( void ) +{ + CLR_NZ; + SET_NZ8(X); + EXTENDED; + WM(EAD,X); +} + +/* $d0 SUBA indexed, 2 byte offset ?*** */ +M6805_INLINE void suba_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $d1 CMPA indexed, 2 byte offset ?*** */ +M6805_INLINE void cmpa_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $d2 SBCA indexed, 2 byte offset ?*** */ +M6805_INLINE void sbca_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $d3 CPX indexed, 2 byte offset -*** */ +M6805_INLINE void cpx_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $d4 ANDA indexed, 2 byte offset -**- */ +M6805_INLINE void anda_ix2( void ) +{ + UINT8 t; + IDX2BYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $d5 BITA indexed, 2 byte offset -**- */ +M6805_INLINE void bita_ix2( void ) +{ + UINT8 t,r; + IDX2BYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $d6 LDA indexed, 2 byte offset -**- */ +M6805_INLINE void lda_ix2( void ) +{ + IDX2BYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $d7 STA indexed, 2 byte offset -**- */ +M6805_INLINE void sta_ix2( void ) +{ + CLR_NZ; + SET_NZ8(A); + INDEXED2; + WM(EAD,A); +} + +/* $d8 EORA indexed, 2 byte offset -**- */ +M6805_INLINE void eora_ix2( void ) +{ + UINT8 t; + IDX2BYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $d9 ADCA indexed, 2 byte offset **** */ +M6805_INLINE void adca_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $da ORA indexed, 2 byte offset -**- */ +M6805_INLINE void ora_ix2( void ) +{ + UINT8 t; + IDX2BYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $db ADDA indexed, 2 byte offset **** */ +M6805_INLINE void adda_ix2( void ) +{ + UINT16 t,r; + IDX2BYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $dc JMP indexed, 2 byte offset -*** */ +M6805_INLINE void jmp_ix2( void ) +{ + INDEXED2; + PC = EA; + change_pc(PC); +} + +/* $dd JSR indexed, 2 byte offset ---- */ +M6805_INLINE void jsr_ix2( void ) +{ + INDEXED2; + PUSHWORD(m6805.pc); + PC = EA; + change_pc(PC); +} + +/* $de LDX indexed, 2 byte offset -**- */ +M6805_INLINE void ldx_ix2( void ) +{ + IDX2BYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $df STX indexed, 2 byte offset -**- */ +M6805_INLINE void stx_ix2( void ) +{ + CLR_NZ; + SET_NZ8(X); + INDEXED2; + WM(EAD,X); +} + +/* $e0 SUBA indexed, 1 byte offset ?*** */ +M6805_INLINE void suba_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $e1 CMPA indexed, 1 byte offset ?*** */ +M6805_INLINE void cmpa_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $e2 SBCA indexed, 1 byte offset ?*** */ +M6805_INLINE void sbca_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $e3 CPX indexed, 1 byte offset -*** */ +M6805_INLINE void cpx_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $e4 ANDA indexed, 1 byte offset -**- */ +M6805_INLINE void anda_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $e5 BITA indexed, 1 byte offset -**- */ +M6805_INLINE void bita_ix1( void ) +{ + UINT8 t,r; + IDX1BYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $e6 LDA indexed, 1 byte offset -**- */ +M6805_INLINE void lda_ix1( void ) +{ + IDX1BYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $e7 STA indexed, 1 byte offset -**- */ +M6805_INLINE void sta_ix1( void ) +{ + CLR_NZ; + SET_NZ8(A); + INDEXED1; + WM(EAD,A); +} + +/* $e8 EORA indexed, 1 byte offset -**- */ +M6805_INLINE void eora_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $e9 ADCA indexed, 1 byte offset **** */ +M6805_INLINE void adca_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $ea ORA indexed, 1 byte offset -**- */ +M6805_INLINE void ora_ix1( void ) +{ + UINT8 t; + IDX1BYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $eb ADDA indexed, 1 byte offset **** */ +M6805_INLINE void adda_ix1( void ) +{ + UINT16 t,r; + IDX1BYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $ec JMP indexed, 1 byte offset -*** */ +M6805_INLINE void jmp_ix1( void ) +{ + INDEXED1; + PC = EA; + change_pc(PC); +} + +/* $ed JSR indexed, 1 byte offset ---- */ +M6805_INLINE void jsr_ix1( void ) +{ + INDEXED1; + PUSHWORD(m6805.pc); + PC = EA; + change_pc(PC); +} + +/* $ee LDX indexed, 1 byte offset -**- */ +M6805_INLINE void ldx_ix1( void ) +{ + IDX1BYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $ef STX indexed, 1 byte offset -**- */ +M6805_INLINE void stx_ix1( void ) +{ + CLR_NZ; + SET_NZ8(X); + INDEXED1; + WM(EAD,X); +} + +/* $f0 SUBA indexed ?*** */ +M6805_INLINE void suba_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $f1 CMPA indexed ?*** */ +M6805_INLINE void cmpa_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = A - t; + CLR_NZC; + SET_FLAGS8(A,t,r); +} + +/* $f2 SBCA indexed ?*** */ +M6805_INLINE void sbca_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = A - t - (CC & 0x01); + CLR_NZC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $f3 CPX indexed -*** */ +M6805_INLINE void cpx_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = X - t; + CLR_NZC; + SET_FLAGS8(X,t,r); +} + +/* $f4 ANDA indexed -**- */ +M6805_INLINE void anda_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + A &= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $f5 BITA indexed -**- */ +M6805_INLINE void bita_ix( void ) +{ + UINT8 t,r; + IDXBYTE(t); + r = A & t; + CLR_NZ; + SET_NZ8(r); +} + +/* $f6 LDA indexed -**- */ +M6805_INLINE void lda_ix( void ) +{ + IDXBYTE(A); + CLR_NZ; + SET_NZ8(A); +} + +/* $f7 STA indexed -**- */ +M6805_INLINE void sta_ix( void ) +{ + CLR_NZ; + SET_NZ8(A); + INDEXED; + WM(EAD,A); +} + +/* $f8 EORA indexed -**- */ +M6805_INLINE void eora_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + A ^= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $f9 ADCA indexed **** */ +M6805_INLINE void adca_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = A + t + (CC & 0x01); + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $fa ORA indexed -**- */ +M6805_INLINE void ora_ix( void ) +{ + UINT8 t; + IDXBYTE(t); + A |= t; + CLR_NZ; + SET_NZ8(A); +} + +/* $fb ADDA indexed **** */ +M6805_INLINE void adda_ix( void ) +{ + UINT16 t,r; + IDXBYTE(t); + r = A + t; + CLR_HNZC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $fc JMP indexed -*** */ +M6805_INLINE void jmp_ix( void ) +{ + INDEXED; + PC = EA; + change_pc(PC); +} + +/* $fd JSR indexed ---- */ +M6805_INLINE void jsr_ix( void ) +{ + INDEXED; + PUSHWORD(m6805.pc); + PC = EA; + change_pc(PC); +} + +/* $fe LDX indexed -**- */ +M6805_INLINE void ldx_ix( void ) +{ + IDXBYTE(X); + CLR_NZ; + SET_NZ8(X); +} + +/* $ff STX indexed -**- */ +M6805_INLINE void stx_ix( void ) +{ + CLR_NZ; + SET_NZ8(X); + INDEXED; + WM(EAD,X); +} diff --git a/src/cpu/m6805/m6805.cpp b/src/cpu/m6805/m6805.cpp new file mode 100644 index 00000000..6ed44f95 --- /dev/null +++ b/src/cpu/m6805/m6805.cpp @@ -0,0 +1,863 @@ +/*** m6805: Portable 6805 emulator ****************************************** + + m6805.c (Also supports hd68705 and hd63705 variants) + + References: + + 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands. + + m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from + the 6809 Simulator V09) + + 6809 Microcomputer Programming & Interfacing with Experiments" + by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. + + System dependencies: UINT16 must be 16 bit unsigned int + UINT8 must be 8 bit unsigned int + UINT32 must be more than 16 bits + arrays up to 65536 bytes must be supported + machine must be twos complement + + Additional Notes: + + K.Wilkins 18/03/99 - Added 63705 functonality and modified all CPU functions + necessary to support: + Variable width address bus + Different stack pointer + Alternate boot vectors + Alternate interrups vectors + + +*****************************************************************************/ + +#include "burnint.h" +#include "driver.h" +#include "m6805_intf.h" + +#define change_pc(x) PC = x + +#define IRQ_LEVEL_DETECT 0 + +#define M6805_INLINE static + +enum +{ + SUBTYPE_M6805, + SUBTYPE_M68705, + SUBTYPE_HD63705 +}; + +/* 6805 Registers */ +typedef struct +{ + int subtype; /* Which sub-type is being emulated */ + UINT32 sp_mask; /* Stack pointer address mask */ + UINT32 sp_low; /* Stack pointer low water mark (or floor) */ + PAIR pc; /* Program counter */ + PAIR s; /* Stack pointer */ + UINT8 a; /* Accumulator */ + UINT8 x; /* Index register */ + UINT8 cc; /* Condition codes */ + + UINT16 pending_interrupts; /* MB */ + int (*irq_callback)(int irqline); + int irq_state[9]; /* KW Additional lines for HD63705 */ + int nmi_state; + int nTotalCycles; +} m6805_Regs; + +/* 6805 registers */ +static m6805_Regs m6805; + +#define SUBTYPE m6805.subtype /* CPU Type */ +#define SP_MASK m6805.sp_mask /* stack pointer mask */ +#define SP_LOW m6805.sp_low /* stack pointer low water mark */ +#define pPC m6805.pc /* program counter PAIR */ +#define PC m6805.pc.w.l /* program counter lower word */ +#define S m6805.s.w.l /* stack pointer lower word */ +#define A m6805.a /* accumulator */ +#define X m6805.x /* index register */ +#define CC m6805.cc /* condition codes */ + +static PAIR ea; /* effective address */ +#define EAD ea.d +#define EA ea.w.l + +/* public globals */ +static int m6805_ICount=50000; + +/* DS -- THESE ARE RE-DEFINED IN m6805.h TO RAM, ROM or FUNCTIONS IN cpuintrf.c */ +#define RM(Addr) M6805_RDMEM(Addr) +#define WM(Addr,Value) M6805_WRMEM(Addr,Value) +#define M_RDOP(Addr) M6805_RDOP(Addr) +#define M_RDOP_ARG(Addr) M6805_RDOP_ARG(Addr) + +/* macros to tweak the PC and SP */ +#define SP_INC if( ++S > SP_MASK) S = SP_LOW +#define SP_DEC if( --S < SP_LOW) S = SP_MASK +#define SP_ADJUST(s) ( ( (s) & SP_MASK ) | SP_LOW ) + +/* macros to access memory */ +#define IMMBYTE(b) {b = M_RDOP_ARG(PC++);} +#define IMMWORD(w) {w.d = 0; w.b.h = M_RDOP_ARG(PC); w.b.l = M_RDOP_ARG(PC+1); PC+=2;} + +#define PUSHBYTE(b) wr_s_handler_b(&b) +#define PUSHWORD(w) wr_s_handler_w(&w) +#define PULLBYTE(b) rd_s_handler_b(&b) +#define PULLWORD(w) rd_s_handler_w(&w) + +/* CC masks H INZC + 7654 3210 */ +#define CFLAG 0x01 +#define ZFLAG 0x02 +#define NFLAG 0x04 +#define IFLAG 0x08 +#define HFLAG 0x10 + +#define CLR_NZ CC&=~(NFLAG|ZFLAG) +#define CLR_HNZC CC&=~(HFLAG|NFLAG|ZFLAG|CFLAG) +#define CLR_Z CC&=~(ZFLAG) +#define CLR_NZC CC&=~(NFLAG|ZFLAG|CFLAG) +#define CLR_ZC CC&=~(ZFLAG|CFLAG) + +/* macros for CC -- CC bits affected should be reset before calling */ +#define SET_Z(a) if(!a)SEZ +#define SET_Z8(a) SET_Z((UINT8)a) +#define SET_N8(a) CC|=((a&0x80)>>5) +#define SET_H(a,b,r) CC|=((a^b^r)&0x10) +#define SET_C8(a) CC|=((a&0x100)>>8) + +static const UINT8 flags8i[256]= /* increment */ +{ +0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 +}; +static const UINT8 flags8d[256]= /* decrement */ +{ +0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 +}; +#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} +#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} + +/* combos */ +#define SET_NZ8(a) {SET_N8(a);SET_Z(a);} +#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_C8(r);} + +/* for treating an unsigned UINT8 as a signed INT16 */ +#define SIGNED(b) ((INT16)(b&0x80?b|0xff00:b)) + +/* Macros for addressing modes */ +#define DIRECT EAD=0;IMMBYTE(ea.b.l) +#define IMM8 EA=PC++ +#define EXTENDED IMMWORD(ea) +#define INDEXED EA=X +#define INDEXED1 {EAD=0; IMMBYTE(ea.b.l); EA+=X;} +#define INDEXED2 {IMMWORD(ea); EA+=X;} + +/* macros to set status flags */ +#if defined(SEC) +#undef SEC +#endif +#define SEC CC|=CFLAG +#define CLC CC&=~CFLAG +#define SEZ CC|=ZFLAG +#define CLZ CC&=~ZFLAG +#define SEN CC|=NFLAG +#define CLN CC&=~NFLAG +#define SEH CC|=HFLAG +#define CLH CC&=~HFLAG +#define SEI CC|=IFLAG +#define CLI CC&=~IFLAG + +/* macros for convenience */ +#define DIRBYTE(b) {DIRECT;b=RM(EAD);} +#define EXTBYTE(b) {EXTENDED;b=RM(EAD);} +#define IDXBYTE(b) {INDEXED;b=RM(EAD);} +#define IDX1BYTE(b) {INDEXED1;b=RM(EAD);} +#define IDX2BYTE(b) {INDEXED2;b=RM(EAD);} +/* Macros for branch instructions */ +#define BRANCH(f) { UINT8 t; IMMBYTE(t); if(f) { PC+=SIGNED(t); change_pc(PC); if (t==0xfe) { /* speed up busy loops */ if(m6805_ICount > 0) m6805_ICount = 0; } } } + +/* what they say it is ... */ +static const unsigned char cycles1[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + /*1*/ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + /*2*/ 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + /*3*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 0, 6, 6, 0, + /*4*/ 4, 0, 0, 4, 4, 0, 4, 4, 4, 4, 4, 0, 4, 4, 0, 4, + /*5*/ 4, 0, 0, 4, 4, 0, 4, 4, 4, 4, 4, 0, 4, 4, 0, 4, + /*6*/ 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 0, 7, + /*7*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 0, 6, + /*8*/ 9, 6, 0,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*9*/ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, + /*A*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 8, 2, 0, + /*B*/ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 7, 4, 5, + /*C*/ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 8, 5, 6, + /*D*/ 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 5, 9, 6, 7, + /*E*/ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 8, 5, 6, + /*F*/ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 7, 4, 5 +}; + + +/* pre-clear a PAIR union; clearing h2 and h3 only might be faster? */ +#define CLEAR_PAIR(p) p->d = 0 + +M6805_INLINE void rd_s_handler_b( UINT8 *b ) +{ + SP_INC; + *b = RM( S ); +} + +M6805_INLINE void rd_s_handler_w( PAIR *p ) +{ + CLEAR_PAIR(p); + SP_INC; + p->b.h = RM( S ); + SP_INC; + p->b.l = RM( S ); +} + +M6805_INLINE void wr_s_handler_b( UINT8 *b ) +{ + WM( S, *b ); + SP_DEC; +} + +M6805_INLINE void wr_s_handler_w( PAIR *p ) +{ + WM( S, p->b.l ); + SP_DEC; + WM( S, p->b.h ); + SP_DEC; +} + +M6805_INLINE void RM16( UINT32 Addr, PAIR *p ) +{ + CLEAR_PAIR(p); + p->b.h = RM(Addr); + ++Addr; +// if( ++Addr > AMASK ) Addr = 0; + p->b.l = RM(Addr); +} + +#ifdef UNUSED_FUNCTION +M6805_INLINE void WM16( UINT32 Addr, PAIR *p ) +{ + WM( Addr, p->b.h ); + ++Addr; +// if( ++Addr > AMASK ) Addr = 0; + WM( Addr, p->b.l ); +} +#endif + + +/* Generate interrupt - m68705 version */ +static void m68705_Interrupt(void) +{ + if( (m6805.pending_interrupts & ((1< 0 ); + + return cycles - m6805_ICount; +} + +void m6805RunEnd() +{ + m6805_ICount = 0; +} + +void m6805NewFrame() +{ + m6805.nTotalCycles = 0; +} + +int m6805TotalCycles() +{ + return m6805.nTotalCycles; +} + +int m6805Scan(int nAction, int */*pnMin*/) +{ + struct BurnArea ba; + + int (*save_irqcallback)(int) = m6805.irq_callback; + + if (nAction & ACB_DRIVER_DATA) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = &m6805; + ba.nLen = sizeof(m6805); + ba.szName = "m6805 Registers"; + BurnAcb(&ba); + } + + m6805.irq_callback = save_irqcallback; + + return 0; +} + + +/**************************************************************************** + * M68705 section + ****************************************************************************/ + +void m68705Reset() +{ + m6805_reset(); + /* Overide default 6805 type */ + m6805.subtype = SUBTYPE_M68705; + RM16( 0xfffe, &m6805.pc ); +} + +void m68705SetIrqLine(int irqline, int state) +{ + if (m6805.irq_state[irqline] == state ) return; + m6805.irq_state[irqline] = state; + if (state != CLEAR_LINE) m6805.pending_interrupts |= 1<> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + return; + } + + if (m6805Write != NULL) { + m6805Write(address, data); + return; + } + + return; +} + +UINT8 m6805_read(UINT16 address) +{ + address &= ADDRESS_MASK; + + if (mem[READ][address >> PAGE_SHIFT] != NULL) { + return mem[READ][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + if (m6805Read != NULL) { + return m6805Read(address); + } + + return 0; +} + +UINT8 m6805_fetch(UINT16 address) +{ + address &= ADDRESS_MASK; + + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + return mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK]; + } + + return m6805_read(address); +} + +void m6805_write_rom(UINT16 address, UINT8 data) +{ + address &= ADDRESS_MASK; + + if (mem[READ][address >> PAGE_SHIFT] != NULL) { + mem[READ][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[WRITE][address >> PAGE_SHIFT] != NULL) { + mem[WRITE][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (mem[FETCH][address >> PAGE_SHIFT] != NULL) { + mem[FETCH][address >> PAGE_SHIFT][address & PAGE_MASK] = data; + } + + if (m6805Write != NULL) { + m6805Write(address, data); + return; + } + + return; +} + +void m6805Init(INT32 num, INT32 max) +{ + ADDRESS_MAX = max; + ADDRESS_MASK = ADDRESS_MAX - 1; + PAGE = ADDRESS_MAX / 0x100; + PAGE_MASK = PAGE - 1; + PAGE_SHIFT = 0; + for (PAGE_SHIFT = 0; (1 << PAGE_SHIFT) < PAGE; PAGE_SHIFT++) {} + + memset (mem[0], 0, PAGE * sizeof(UINT8 *)); + memset (mem[1], 0, PAGE * sizeof(UINT8 *)); + memset (mem[2], 0, PAGE * sizeof(UINT8 *)); + + for (INT32 i = 0; i < num; i++) + CpuCheatRegister(0x0b, i); +} + +void m6805Exit() +{ + ADDRESS_MAX = 0; + ADDRESS_MASK = 0; + PAGE = 0; + PAGE_MASK = 0; + PAGE_SHIFT = 0; +} + +void m6805Open(INT32) +{ + +} + +void m6805Close() +{ + +} + diff --git a/src/cpu/m6805_intf.h b/src/cpu/m6805_intf.h new file mode 100644 index 00000000..3ee29ee5 --- /dev/null +++ b/src/cpu/m6805_intf.h @@ -0,0 +1,41 @@ +#include "m6805.h" + +#define M6805_READ 1 +#define M6805_WRITE 2 +#define M6805_FETCH 4 + +#define M6805_ROM (M6805_READ | M6805_FETCH) +#define M6805_RAM (M6805_ROM | M6805_WRITE) + +void m6805MapMemory(UINT8 *ptr, INT32 nStart, INT32 nEnd, INT32 nType); + +void m6805SetWriteHandler(void (*write)(UINT16, UINT8)); +void m6805SetReadHandler(UINT8 (*read)(UINT16)); + +void m6805_write(UINT16 address, UINT8 data); +UINT8 m6805_read(UINT16 address); +UINT8 m6805_fetch(UINT16 address); +void m6805_write_rom(UINT16 address, UINT8 data); + +void m6805Init(INT32 num, INT32 address_range); +void m6805Exit(); +void m6805Open(INT32 ); +void m6805Close(); + +INT32 m6805Scan(INT32 nAction, INT32 */*pnMin*/); + +void m6805Reset(); +void m6805SetIrqLine(INT32 , INT32 state); +INT32 m6805Run(INT32 cycles); + +void m6805RunEnd(); + +void m68705Reset(); +void m68705SetIrqLine(INT32 irqline, INT32 state); + +void hd63705Reset(void); +void hd63705SetIrqLine(INT32 irqline, INT32 state); + +void m6805NewFrame(); +INT32 m6805TotalCycles(); + diff --git a/src/cpu/m6809/6809ops.c b/src/cpu/m6809/6809ops.c new file mode 100644 index 00000000..30f2971b --- /dev/null +++ b/src/cpu/m6809/6809ops.c @@ -0,0 +1,2997 @@ +/* + +HNZVC + +? = undefined +* = affected +- = unaffected +0 = cleared +1 = set +# = CCr directly affected by instruction +@ = special - carry set if bit 7 is set + +*/ + +#ifdef NEW +static void illegal( void ) +#else +M6809_INLINE void illegal( void ) +#endif +{ +// logerror("M6809: illegal opcode at %04x\n",PC); +} + +/* $00 NEG direct ?**** */ +M6809_INLINE void neg_di( void ) +{ + UINT16 r,t; + DIRBYTE(t); + r = -t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $01 ILLEGAL */ + +/* $02 ILLEGAL */ + +/* $03 COM direct -**01 */ +M6809_INLINE void com_di( void ) +{ + UINT8 t; + DIRBYTE(t); + t = ~t; + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $04 LSR direct -0*-* */ +M6809_INLINE void lsr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t >>= 1; + SET_Z8(t); + WM(EAD,t); +} + +/* $05 ILLEGAL */ + +/* $06 ROR direct -**-* */ +M6809_INLINE void ror_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r= (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; + SET_NZ8(r); + WM(EAD,r); +} + +/* $07 ASR direct ?**-* */ +M6809_INLINE void asr_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZC; + CC |= (t & CC_C); + t = (t & 0x80) | (t >> 1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $08 ASL direct ?**** */ +M6809_INLINE void asl_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $09 ROL direct -**** */ +M6809_INLINE void rol_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = (CC & CC_C) | (t << 1); + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $0A DEC direct -***- */ +M6809_INLINE void dec_di( void ) +{ + UINT8 t; + DIRBYTE(t); + --t; + CLR_NZV; + SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $0B ILLEGAL */ + +/* $OC INC direct -***- */ +M6809_INLINE void inc_di( void ) +{ + UINT8 t; + DIRBYTE(t); + ++t; + CLR_NZV; + SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $OD TST direct -**0- */ +M6809_INLINE void tst_di( void ) +{ + UINT8 t; + DIRBYTE(t); + CLR_NZV; + SET_NZ8(t); +} + +/* $0E JMP direct ----- */ +M6809_INLINE void jmp_di( void ) +{ + DIRECT; + PCD = EAD; + CHANGE_PC; +} + +/* $0F CLR direct -0100 */ +M6809_INLINE void clr_di( void ) +{ + DIRECT; + (void)RM(EAD); + WM(EAD,0); + CLR_NZVC; + SEZ; +} + +/* $10 FLAG */ + +/* $11 FLAG */ + +/* $12 NOP inherent ----- */ +M6809_INLINE void nop( void ) +{ + ; +} + +/* $13 SYNC inherent ----- */ +M6809_INLINE void sync( void ) +{ + /* SYNC stops processing instructions until an interrupt request happens. */ + /* This doesn't require the corresponding interrupt to be enabled: if it */ + /* is disabled, execution continues with the next instruction. */ + m6809.int_state |= M6809_SYNC; /* HJB 990227 */ + CHECK_IRQ_LINES; + /* if M6809_SYNC has not been cleared by CHECK_IRQ_LINES, + * stop execution until the interrupt lines change. */ + if( m6809.int_state & M6809_SYNC ) + if (m6809_ICount > 0) m6809_ICount = 0; +} + +/* $14 ILLEGAL */ + +/* $15 ILLEGAL */ + +/* $16 LBRA relative ----- */ +M6809_INLINE void lbra( void ) +{ + IMMWORD(ea); + PC += EA; + CHANGE_PC; + + if ( EA == 0xfffd ) /* EHC 980508 speed up busy loop */ + if ( m6809_ICount > 0) + m6809_ICount = 0; +} + +/* $17 LBSR relative ----- */ +M6809_INLINE void lbsr( void ) +{ + IMMWORD(ea); + PUSHWORD(pPC); + PC += EA; + CHANGE_PC; +} + +/* $18 ILLEGAL */ + +/* $19 DAA inherent (A) -**0* */ +M6809_INLINE void daa( void ) +{ + UINT8 msn, lsn; + UINT16 t, cf = 0; + msn = A & 0xf0; lsn = A & 0x0f; + if( lsn>0x09 || CC & CC_H) cf |= 0x06; + if( msn>0x80 && lsn>0x09 ) cf |= 0x60; + if( msn>0x90 || CC & CC_C) cf |= 0x60; + t = cf + A; + CLR_NZV; /* keep carry from previous operation */ + SET_NZ8((UINT8)t); SET_C8(t); + A = t; +} + +/* $1A ORCC immediate ##### */ +M6809_INLINE void orcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC |= t; + CHECK_IRQ_LINES; /* HJB 990116 */ +} + +/* $1B ILLEGAL */ + +/* $1C ANDCC immediate ##### */ +M6809_INLINE void andcc( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + CHECK_IRQ_LINES; /* HJB 990116 */ +} + +/* $1D SEX inherent -**-- */ +M6809_INLINE void sex( void ) +{ + UINT16 t; + t = SIGNED(B); + D = t; +// CLR_NZV; Tim Lindner 20020905: verified that V flag is not affected + CLR_NZ; + SET_NZ16(t); +} + +/* $1E EXG inherent ----- */ +M6809_INLINE void exg( void ) +{ + UINT16 t1,t2; + UINT8 tb; + + IMMBYTE(tb); + if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */ + { + /* transfer $ff to both registers */ + t1 = t2 = 0xff; + } + else + { + switch(tb>>4) { + case 0: t1 = D; break; + case 1: t1 = X; break; + case 2: t1 = Y; break; + case 3: t1 = U; break; + case 4: t1 = S; break; + case 5: t1 = PC; break; + case 8: t1 = A; break; + case 9: t1 = B; break; + case 10: t1 = CC; break; + case 11: t1 = DP; break; + default: t1 = 0xff; + } + switch(tb&15) { + case 0: t2 = D; break; + case 1: t2 = X; break; + case 2: t2 = Y; break; + case 3: t2 = U; break; + case 4: t2 = S; break; + case 5: t2 = PC; break; + case 8: t2 = A; break; + case 9: t2 = B; break; + case 10: t2 = CC; break; + case 11: t2 = DP; break; + default: t2 = 0xff; + } + } + switch(tb>>4) { + case 0: D = t2; break; + case 1: X = t2; break; + case 2: Y = t2; break; + case 3: U = t2; break; + case 4: S = t2; break; + case 5: PC = t2; CHANGE_PC; break; + case 8: A = t2; break; + case 9: B = t2; break; + case 10: CC = t2; break; + case 11: DP = t2; break; + } + switch(tb&15) { + case 0: D = t1; break; + case 1: X = t1; break; + case 2: Y = t1; break; + case 3: U = t1; break; + case 4: S = t1; break; + case 5: PC = t1; CHANGE_PC; break; + case 8: A = t1; break; + case 9: B = t1; break; + case 10: CC = t1; break; + case 11: DP = t1; break; + } +} + +/* $1F TFR inherent ----- */ +M6809_INLINE void tfr( void ) +{ + UINT8 tb; + UINT16 t; + + IMMBYTE(tb); + if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */ + { + /* transfer $ff to register */ + t = 0xff; + } + else + { + switch(tb>>4) { + case 0: t = D; break; + case 1: t = X; break; + case 2: t = Y; break; + case 3: t = U; break; + case 4: t = S; break; + case 5: t = PC; break; + case 8: t = A; break; + case 9: t = B; break; + case 10: t = CC; break; + case 11: t = DP; break; + default: t = 0xff; + } + } + switch(tb&15) { + case 0: D = t; break; + case 1: X = t; break; + case 2: Y = t; break; + case 3: U = t; break; + case 4: S = t; break; + case 5: PC = t; CHANGE_PC; break; + case 8: A = t; break; + case 9: B = t; break; + case 10: CC = t; break; + case 11: DP = t; break; + } +} + +/* $20 BRA relative ----- */ +M6809_INLINE void bra( void ) +{ + UINT8 t; + IMMBYTE(t); + PC += SIGNED(t); + CHANGE_PC; + /* JB 970823 - speed up busy loops */ + if( t == 0xfe ) + if( m6809_ICount > 0 ) m6809_ICount = 0; +} + +/* $21 BRN relative ----- */ +M6809_INLINE void brn( void ) +{ + UINT8 t; + IMMBYTE(t); +} + +/* $1021 LBRN relative ----- */ +M6809_INLINE void lbrn( void ) +{ + IMMWORD(ea); +} + +/* $22 BHI relative ----- */ +M6809_INLINE void bhi( void ) +{ + BRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $1022 LBHI relative ----- */ +M6809_INLINE void lbhi( void ) +{ + LBRANCH( !(CC & (CC_Z|CC_C)) ); +} + +/* $23 BLS relative ----- */ +M6809_INLINE void bls( void ) +{ + BRANCH( (CC & (CC_Z|CC_C)) ); +} + +/* $1023 LBLS relative ----- */ +M6809_INLINE void lbls( void ) +{ + LBRANCH( (CC&(CC_Z|CC_C)) ); +} + +/* $24 BCC relative ----- */ +M6809_INLINE void bcc( void ) +{ + BRANCH( !(CC&CC_C) ); +} + +/* $1024 LBCC relative ----- */ +M6809_INLINE void lbcc( void ) +{ + LBRANCH( !(CC&CC_C) ); +} + +/* $25 BCS relative ----- */ +M6809_INLINE void bcs( void ) +{ + BRANCH( (CC&CC_C) ); +} + +/* $1025 LBCS relative ----- */ +M6809_INLINE void lbcs( void ) +{ + LBRANCH( (CC&CC_C) ); +} + +/* $26 BNE relative ----- */ +M6809_INLINE void bne( void ) +{ + BRANCH( !(CC&CC_Z) ); +} + +/* $1026 LBNE relative ----- */ +M6809_INLINE void lbne( void ) +{ + LBRANCH( !(CC&CC_Z) ); +} + +/* $27 BEQ relative ----- */ +M6809_INLINE void beq( void ) +{ + BRANCH( (CC&CC_Z) ); +} + +/* $1027 LBEQ relative ----- */ +M6809_INLINE void lbeq( void ) +{ + LBRANCH( (CC&CC_Z) ); +} + +/* $28 BVC relative ----- */ +M6809_INLINE void bvc( void ) +{ + BRANCH( !(CC&CC_V) ); +} + +/* $1028 LBVC relative ----- */ +M6809_INLINE void lbvc( void ) +{ + LBRANCH( !(CC&CC_V) ); +} + +/* $29 BVS relative ----- */ +M6809_INLINE void bvs( void ) +{ + BRANCH( (CC&CC_V) ); +} + +/* $1029 LBVS relative ----- */ +M6809_INLINE void lbvs( void ) +{ + LBRANCH( (CC&CC_V) ); +} + +/* $2A BPL relative ----- */ +M6809_INLINE void bpl( void ) +{ + BRANCH( !(CC&CC_N) ); +} + +/* $102A LBPL relative ----- */ +M6809_INLINE void lbpl( void ) +{ + LBRANCH( !(CC&CC_N) ); +} + +/* $2B BMI relative ----- */ +M6809_INLINE void bmi( void ) +{ + BRANCH( (CC&CC_N) ); +} + +/* $102B LBMI relative ----- */ +M6809_INLINE void lbmi( void ) +{ + LBRANCH( (CC&CC_N) ); +} + +/* $2C BGE relative ----- */ +M6809_INLINE void bge( void ) +{ + BRANCH( !NXORV ); +} + +/* $102C LBGE relative ----- */ +M6809_INLINE void lbge( void ) +{ + LBRANCH( !NXORV ); +} + +/* $2D BLT relative ----- */ +M6809_INLINE void blt( void ) +{ + BRANCH( NXORV ); +} + +/* $102D LBLT relative ----- */ +M6809_INLINE void lblt( void ) +{ + LBRANCH( NXORV ); +} + +/* $2E BGT relative ----- */ +M6809_INLINE void bgt( void ) +{ + BRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $102E LBGT relative ----- */ +M6809_INLINE void lbgt( void ) +{ + LBRANCH( !(NXORV || (CC&CC_Z)) ); +} + +/* $2F BLE relative ----- */ +M6809_INLINE void ble( void ) +{ + BRANCH( (NXORV || (CC&CC_Z)) ); +} + +/* $102F LBLE relative ----- */ +M6809_INLINE void lble( void ) +{ + LBRANCH( (NXORV || (CC&CC_Z)) ); +} + +/* $30 LEAX indexed --*-- */ +M6809_INLINE void leax( void ) +{ + fetch_effective_address(); + X = EA; + CLR_Z; + SET_Z(X); +} + +/* $31 LEAY indexed --*-- */ +M6809_INLINE void leay( void ) +{ + fetch_effective_address(); + Y = EA; + CLR_Z; + SET_Z(Y); +} + +/* $32 LEAS indexed ----- */ +M6809_INLINE void leas( void ) +{ + fetch_effective_address(); + S = EA; + m6809.int_state |= M6809_LDS; +} + +/* $33 LEAU indexed ----- */ +M6809_INLINE void leau( void ) +{ + fetch_effective_address(); + U = EA; +} + +/* $34 PSHS inherent ----- */ +M6809_INLINE void pshs( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PUSHWORD(pPC); m6809_ICount -= 2; } + if( t&0x40 ) { PUSHWORD(pU); m6809_ICount -= 2; } + if( t&0x20 ) { PUSHWORD(pY); m6809_ICount -= 2; } + if( t&0x10 ) { PUSHWORD(pX); m6809_ICount -= 2; } + if( t&0x08 ) { PUSHBYTE(DP); m6809_ICount -= 1; } + if( t&0x04 ) { PUSHBYTE(B); m6809_ICount -= 1; } + if( t&0x02 ) { PUSHBYTE(A); m6809_ICount -= 1; } + if( t&0x01 ) { PUSHBYTE(CC); m6809_ICount -= 1; } +} + +/* 35 PULS inherent ----- */ +M6809_INLINE void puls( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULLBYTE(CC); m6809_ICount -= 1; } + if( t&0x02 ) { PULLBYTE(A); m6809_ICount -= 1; } + if( t&0x04 ) { PULLBYTE(B); m6809_ICount -= 1; } + if( t&0x08 ) { PULLBYTE(DP); m6809_ICount -= 1; } + if( t&0x10 ) { PULLWORD(XD); m6809_ICount -= 2; } + if( t&0x20 ) { PULLWORD(YD); m6809_ICount -= 2; } + if( t&0x40 ) { PULLWORD(UD); m6809_ICount -= 2; } + if( t&0x80 ) { PULLWORD(PCD); CHANGE_PC; m6809_ICount -= 2; } + + /* HJB 990225: moved check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES; } +} + +/* $36 PSHU inherent ----- */ +M6809_INLINE void pshu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x80 ) { PSHUWORD(pPC); m6809_ICount -= 2; } + if( t&0x40 ) { PSHUWORD(pS); m6809_ICount -= 2; } + if( t&0x20 ) { PSHUWORD(pY); m6809_ICount -= 2; } + if( t&0x10 ) { PSHUWORD(pX); m6809_ICount -= 2; } + if( t&0x08 ) { PSHUBYTE(DP); m6809_ICount -= 1; } + if( t&0x04 ) { PSHUBYTE(B); m6809_ICount -= 1; } + if( t&0x02 ) { PSHUBYTE(A); m6809_ICount -= 1; } + if( t&0x01 ) { PSHUBYTE(CC); m6809_ICount -= 1; } +} + +/* 37 PULU inherent ----- */ +M6809_INLINE void pulu( void ) +{ + UINT8 t; + IMMBYTE(t); + if( t&0x01 ) { PULUBYTE(CC); m6809_ICount -= 1; } + if( t&0x02 ) { PULUBYTE(A); m6809_ICount -= 1; } + if( t&0x04 ) { PULUBYTE(B); m6809_ICount -= 1; } + if( t&0x08 ) { PULUBYTE(DP); m6809_ICount -= 1; } + if( t&0x10 ) { PULUWORD(XD); m6809_ICount -= 2; } + if( t&0x20 ) { PULUWORD(YD); m6809_ICount -= 2; } + if( t&0x40 ) { PULUWORD(SD); m6809_ICount -= 2; } + if( t&0x80 ) { PULUWORD(PCD); CHANGE_PC; m6809_ICount -= 2; } + + /* HJB 990225: moved check after all PULLs */ + if( t&0x01 ) { CHECK_IRQ_LINES; } +} + +/* $38 ILLEGAL */ + +/* $39 RTS inherent ----- */ +M6809_INLINE void rts( void ) +{ + PULLWORD(PCD); + CHANGE_PC; +} + +/* $3A ABX inherent ----- */ +M6809_INLINE void abx( void ) +{ + X += B; +} + +/* $3B RTI inherent ##### */ +M6809_INLINE void rti( void ) +{ + UINT8 t; + PULLBYTE(CC); + t = CC & CC_E; /* HJB 990225: entire state saved? */ + if(t) + { + m6809_ICount -= 9; + PULLBYTE(A); + PULLBYTE(B); + PULLBYTE(DP); + PULLWORD(XD); + PULLWORD(YD); + PULLWORD(UD); + } + PULLWORD(PCD); + CHANGE_PC; + CHECK_IRQ_LINES; /* HJB 990116 */ +} + +/* $3C CWAI inherent ----1 */ +M6809_INLINE void cwai( void ) +{ + UINT8 t; + IMMBYTE(t); + CC &= t; + /* + * CWAI stacks the entire machine state on the hardware stack, + * then waits for an interrupt; when the interrupt is taken + * later, the state is *not* saved again after CWAI. + */ + CC |= CC_E; /* HJB 990225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + m6809.int_state |= M6809_CWAI; /* HJB 990228 */ + CHECK_IRQ_LINES; /* HJB 990116 */ + if( m6809.int_state & M6809_CWAI ) + if( m6809_ICount > 0 ) + m6809_ICount = 0; +} + +/* $3D MUL inherent --*-@ */ +M6809_INLINE void mul( void ) +{ + UINT16 t; + t = A * B; + CLR_ZC; SET_Z16(t); if(t&0x80) SEC; + D = t; +} + +/* $3E ILLEGAL */ + +/* $3F SWI (SWI2 SWI3) absolute indirect ----- */ +M6809_INLINE void swi( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD=RM16(0xfffa); + CHANGE_PC; +} + +/* $103F SWI2 absolute indirect ----- */ +M6809_INLINE void swi2( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD = RM16(0xfff4); + CHANGE_PC; +} + +/* $113F SWI3 absolute indirect ----- */ +M6809_INLINE void swi3( void ) +{ + CC |= CC_E; /* HJB 980225: save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + PCD = RM16(0xfff2); + CHANGE_PC; +} + +/* $40 NEGA inherent ?**** */ +M6809_INLINE void nega( void ) +{ + UINT16 r; + r = -A; + CLR_NZVC; + SET_FLAGS8(0,A,r); + A = r; +} + +/* $41 ILLEGAL */ + +/* $42 ILLEGAL */ + +/* $43 COMA inherent -**01 */ +M6809_INLINE void coma( void ) +{ + A = ~A; + CLR_NZV; + SET_NZ8(A); + SEC; +} + +/* $44 LSRA inherent -0*-* */ +M6809_INLINE void lsra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A >>= 1; + SET_Z8(A); +} + +/* $45 ILLEGAL */ + +/* $46 RORA inherent -**-* */ +M6809_INLINE void rora( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (A & CC_C); + r |= A >> 1; + SET_NZ8(r); + A = r; +} + +/* $47 ASRA inherent ?**-* */ +M6809_INLINE void asra( void ) +{ + CLR_NZC; + CC |= (A & CC_C); + A = (A & 0x80) | (A >> 1); + SET_NZ8(A); +} + +/* $48 ASLA inherent ?**** */ +M6809_INLINE void asla( void ) +{ + UINT16 r; + r = A << 1; + CLR_NZVC; + SET_FLAGS8(A,A,r); + A = r; +} + +/* $49 ROLA inherent -**** */ +M6809_INLINE void rola( void ) +{ + UINT16 t,r; + t = A; + r = (CC & CC_C) | (t<<1); + CLR_NZVC; SET_FLAGS8(t,t,r); + A = r; +} + +/* $4A DECA inherent -***- */ +M6809_INLINE void deca( void ) +{ + --A; + CLR_NZV; + SET_FLAGS8D(A); +} + +/* $4B ILLEGAL */ + +/* $4C INCA inherent -***- */ +M6809_INLINE void inca( void ) +{ + ++A; + CLR_NZV; + SET_FLAGS8I(A); +} + +/* $4D TSTA inherent -**0- */ +M6809_INLINE void tsta( void ) +{ + CLR_NZV; + SET_NZ8(A); +} + +/* $4E ILLEGAL */ + +/* $4F CLRA inherent -0100 */ +M6809_INLINE void clra( void ) +{ + A = 0; + CLR_NZVC; SEZ; +} + +/* $50 NEGB inherent ?**** */ +M6809_INLINE void negb( void ) +{ + UINT16 r; + r = -B; + CLR_NZVC; + SET_FLAGS8(0,B,r); + B = r; +} + +/* $51 ILLEGAL */ + +/* $52 ILLEGAL */ + +/* $53 COMB inherent -**01 */ +M6809_INLINE void comb( void ) +{ + B = ~B; + CLR_NZV; + SET_NZ8(B); + SEC; +} + +/* $54 LSRB inherent -0*-* */ +M6809_INLINE void lsrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B >>= 1; + SET_Z8(B); +} + +/* $55 ILLEGAL */ + +/* $56 RORB inherent -**-* */ +M6809_INLINE void rorb( void ) +{ + UINT8 r; + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (B & CC_C); + r |= B >> 1; + SET_NZ8(r); + B = r; +} + +/* $57 ASRB inherent ?**-* */ +M6809_INLINE void asrb( void ) +{ + CLR_NZC; + CC |= (B & CC_C); + B= (B & 0x80) | (B >> 1); + SET_NZ8(B); +} + +/* $58 ASLB inherent ?**** */ +M6809_INLINE void aslb( void ) +{ + UINT16 r; + r = B << 1; + CLR_NZVC; + SET_FLAGS8(B,B,r); + B = r; +} + +/* $59 ROLB inherent -**** */ +M6809_INLINE void rolb( void ) +{ + UINT16 t,r; + t = B; + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + B = r; +} + +/* $5A DECB inherent -***- */ +M6809_INLINE void decb( void ) +{ + --B; + CLR_NZV; + SET_FLAGS8D(B); +} + +/* $5B ILLEGAL */ + +/* $5C INCB inherent -***- */ +M6809_INLINE void incb( void ) +{ + ++B; + CLR_NZV; + SET_FLAGS8I(B); +} + +/* $5D TSTB inherent -**0- */ +M6809_INLINE void tstb( void ) +{ + CLR_NZV; + SET_NZ8(B); +} + +/* $5E ILLEGAL */ + +/* $5F CLRB inherent -0100 */ +M6809_INLINE void clrb( void ) +{ + B = 0; + CLR_NZVC; SEZ; +} + +/* $60 NEG indexed ?**** */ +M6809_INLINE void neg_ix( void ) +{ + UINT16 r,t; + fetch_effective_address(); + t = RM(EAD); + r=-t; + CLR_NZVC; + SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $61 ILLEGAL */ + +/* $62 ILLEGAL */ + +/* $63 COM indexed -**01 */ +M6809_INLINE void com_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = ~RM(EAD); + CLR_NZV; + SET_NZ8(t); + SEC; + WM(EAD,t); +} + +/* $64 LSR indexed -0*-* */ +M6809_INLINE void lsr_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t=RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $65 ILLEGAL */ + +/* $66 ROR indexed -**-* */ +M6809_INLINE void ror_ix( void ) +{ + UINT8 t,r; + fetch_effective_address(); + t=RM(EAD); + r = (CC & CC_C) << 7; + CLR_NZC; + CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $67 ASR indexed ?**-* */ +M6809_INLINE void asr_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t=RM(EAD); + CLR_NZC; + CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $68 ASL indexed ?**** */ +M6809_INLINE void asl_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t=RM(EAD); + r = t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $69 ROL indexed -**** */ +M6809_INLINE void rol_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t=RM(EAD); + r = CC & CC_C; + r |= t << 1; + CLR_NZVC; + SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $6A DEC indexed -***- */ +M6809_INLINE void dec_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD) - 1; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $6B ILLEGAL */ + +/* $6C INC indexed -***- */ +M6809_INLINE void inc_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD) + 1; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $6D TST indexed -**0- */ +M6809_INLINE void tst_ix( void ) +{ + UINT8 t; + fetch_effective_address(); + t = RM(EAD); + CLR_NZV; + SET_NZ8(t); +} + +/* $6E JMP indexed ----- */ +M6809_INLINE void jmp_ix( void ) +{ + fetch_effective_address(); + PCD = EAD; + CHANGE_PC; +} + +/* $6F CLR indexed -0100 */ +M6809_INLINE void clr_ix( void ) +{ + fetch_effective_address(); + (void)RM(EAD); + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $70 NEG extended ?**** */ +M6809_INLINE void neg_ex( void ) +{ + UINT16 r,t; + EXTBYTE(t); r=-t; + CLR_NZVC; SET_FLAGS8(0,t,r); + WM(EAD,r); +} + +/* $71 ILLEGAL */ + +/* $72 ILLEGAL */ + +/* $73 COM extended -**01 */ +M6809_INLINE void com_ex( void ) +{ + UINT8 t; + EXTBYTE(t); t = ~t; + CLR_NZV; SET_NZ8(t); SEC; + WM(EAD,t); +} + +/* $74 LSR extended -0*-* */ +M6809_INLINE void lsr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t>>=1; SET_Z8(t); + WM(EAD,t); +} + +/* $75 ILLEGAL */ + +/* $76 ROR extended -**-* */ +M6809_INLINE void ror_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); r=(CC & CC_C) << 7; + CLR_NZC; CC |= (t & CC_C); + r |= t>>1; SET_NZ8(r); + WM(EAD,r); +} + +/* $77 ASR extended ?**-* */ +M6809_INLINE void asr_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZC; CC |= (t & CC_C); + t=(t&0x80)|(t>>1); + SET_NZ8(t); + WM(EAD,t); +} + +/* $78 ASL extended ?**** */ +M6809_INLINE void asl_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r=t<<1; + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $79 ROL extended -**** */ +M6809_INLINE void rol_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); r = (CC & CC_C) | (t << 1); + CLR_NZVC; SET_FLAGS8(t,t,r); + WM(EAD,r); +} + +/* $7A DEC extended -***- */ +M6809_INLINE void dec_ex( void ) +{ + UINT8 t; + EXTBYTE(t); --t; + CLR_NZV; SET_FLAGS8D(t); + WM(EAD,t); +} + +/* $7B ILLEGAL */ + +/* $7C INC extended -***- */ +M6809_INLINE void inc_ex( void ) +{ + UINT8 t; + EXTBYTE(t); ++t; + CLR_NZV; SET_FLAGS8I(t); + WM(EAD,t); +} + +/* $7D TST extended -**0- */ +M6809_INLINE void tst_ex( void ) +{ + UINT8 t; + EXTBYTE(t); CLR_NZV; SET_NZ8(t); +} + +/* $7E JMP extended ----- */ +M6809_INLINE void jmp_ex( void ) +{ + EXTENDED; + PCD = EAD; + CHANGE_PC; +} + +/* $7F CLR extended -0100 */ +M6809_INLINE void clr_ex( void ) +{ + EXTENDED; + (void)RM(EAD); + WM(EAD,0); + CLR_NZVC; SEZ; +} + +/* $80 SUBA immediate ?**** */ +M6809_INLINE void suba_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $81 CMPA immediate ?**** */ +M6809_INLINE void cmpa_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $82 SBCA immediate ?**** */ +M6809_INLINE void sbca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $83 SUBD (CMPD CMPU) immediate -**** */ +M6809_INLINE void subd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1083 CMPD immediate -**** */ +M6809_INLINE void cmpd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1183 CMPU immediate -**** */ +M6809_INLINE void cmpu_im( void ) +{ + UINT32 r, d; + PAIR b; + IMMWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $84 ANDA immediate -**0- */ +M6809_INLINE void anda_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $85 BITA immediate -**0- */ +M6809_INLINE void bita_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $86 LDA immediate -**0- */ +M6809_INLINE void lda_im( void ) +{ + IMMBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* is this a legal instruction? */ +/* $87 STA immediate -**0- */ +M6809_INLINE void sta_im( void ) +{ + CLR_NZV; + SET_NZ8(A); + IMM8; + WM(EAD,A); +} + +/* $88 EORA immediate -**0- */ +M6809_INLINE void eora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $89 ADCA immediate ***** */ +M6809_INLINE void adca_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8A ORA immediate -**0- */ +M6809_INLINE void ora_im( void ) +{ + UINT8 t; + IMMBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $8B ADDA immediate ***** */ +M6809_INLINE void adda_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $8C CMPX (CMPY CMPS) immediate -**** */ +M6809_INLINE void cmpx_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $108C CMPY immediate -**** */ +M6809_INLINE void cmpy_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $118C CMPS immediate -**** */ +M6809_INLINE void cmps_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $8D BSR ----- */ +M6809_INLINE void bsr( void ) +{ + UINT8 t; + IMMBYTE(t); + PUSHWORD(pPC); + PC += SIGNED(t); + CHANGE_PC; +} + +/* $8E LDX (LDY) immediate -**0- */ +M6809_INLINE void ldx_im( void ) +{ + IMMWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $108E LDY immediate -**0- */ +M6809_INLINE void ldy_im( void ) +{ + IMMWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* is this a legal instruction? */ +/* $8F STX (STY) immediate -**0- */ +M6809_INLINE void stx_im( void ) +{ + CLR_NZV; + SET_NZ16(X); + IMM16; + WM16(EAD,&pX); +} + +/* is this a legal instruction? */ +/* $108F STY immediate -**0- */ +M6809_INLINE void sty_im( void ) +{ + CLR_NZV; + SET_NZ16(Y); + IMM16; + WM16(EAD,&pY); +} + +/* $90 SUBA direct ?**** */ +M6809_INLINE void suba_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $91 CMPA direct ?**** */ +M6809_INLINE void cmpa_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $92 SBCA direct ?**** */ +M6809_INLINE void sbca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $93 SUBD (CMPD CMPU) direct -**** */ +M6809_INLINE void subd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $1093 CMPD direct -**** */ +M6809_INLINE void cmpd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $1193 CMPU direct -**** */ +M6809_INLINE void cmpu_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $94 ANDA direct -**0- */ +M6809_INLINE void anda_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $95 BITA direct -**0- */ +M6809_INLINE void bita_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = A & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $96 LDA direct -**0- */ +M6809_INLINE void lda_di( void ) +{ + DIRBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $97 STA direct -**0- */ +M6809_INLINE void sta_di( void ) +{ + CLR_NZV; + SET_NZ8(A); + DIRECT; + WM(EAD,A); +} + +/* $98 EORA direct -**0- */ +M6809_INLINE void eora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $99 ADCA direct ***** */ +M6809_INLINE void adca_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9A ORA direct -**0- */ +M6809_INLINE void ora_di( void ) +{ + UINT8 t; + DIRBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $9B ADDA direct ***** */ +M6809_INLINE void adda_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $9C CMPX (CMPY CMPS) direct -**** */ +M6809_INLINE void cmpx_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $109C CMPY direct -**** */ +M6809_INLINE void cmpy_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $119C CMPS direct -**** */ +M6809_INLINE void cmps_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $9D JSR direct ----- */ +M6809_INLINE void jsr_di( void ) +{ + DIRECT; + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $9E LDX (LDY) direct -**0- */ +M6809_INLINE void ldx_di( void ) +{ + DIRWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $109E LDY direct -**0- */ +M6809_INLINE void ldy_di( void ) +{ + DIRWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $9F STX (STY) direct -**0- */ +M6809_INLINE void stx_di( void ) +{ + CLR_NZV; + SET_NZ16(X); + DIRECT; + WM16(EAD,&pX); +} + +/* $109F STY direct -**0- */ +M6809_INLINE void sty_di( void ) +{ + CLR_NZV; + SET_NZ16(Y); + DIRECT; + WM16(EAD,&pY); +} + +/* $a0 SUBA indexed ?**** */ +M6809_INLINE void suba_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a1 CMPA indexed ?**** */ +M6809_INLINE void cmpa_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $a2 SBCA indexed ?**** */ +M6809_INLINE void sbca_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $a3 SUBD (CMPD CMPU) indexed -**** */ +M6809_INLINE void subd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10a3 CMPD indexed -**** */ +M6809_INLINE void cmpd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11a3 CMPU indexed -**** */ +M6809_INLINE void cmpu_ix( void ) +{ + UINT32 r; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + r = U - b.d; + CLR_NZVC; + SET_FLAGS16(U,b.d,r); +} + +/* $a4 ANDA indexed -**0- */ +M6809_INLINE void anda_ix( void ) +{ + fetch_effective_address(); + A &= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a5 BITA indexed -**0- */ +M6809_INLINE void bita_ix( void ) +{ + UINT8 r; + fetch_effective_address(); + r = A & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $a6 LDA indexed -**0- */ +M6809_INLINE void lda_ix( void ) +{ + fetch_effective_address(); + A = RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a7 STA indexed -**0- */ +M6809_INLINE void sta_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(A); + WM(EAD,A); +} + +/* $a8 EORA indexed -**0- */ +M6809_INLINE void eora_ix( void ) +{ + fetch_effective_address(); + A ^= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $a9 ADCA indexed ***** */ +M6809_INLINE void adca_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aA ORA indexed -**0- */ +M6809_INLINE void ora_ix( void ) +{ + fetch_effective_address(); + A |= RM(EAD); + CLR_NZV; + SET_NZ8(A); +} + +/* $aB ADDA indexed ***** */ +M6809_INLINE void adda_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $aC CMPX (CMPY CMPS) indexed -**** */ +M6809_INLINE void cmpx_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10aC CMPY indexed -**** */ +M6809_INLINE void cmpy_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11aC CMPS indexed -**** */ +M6809_INLINE void cmps_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $aD JSR indexed ----- */ +M6809_INLINE void jsr_ix( void ) +{ + fetch_effective_address(); + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $aE LDX (LDY) indexed -**0- */ +M6809_INLINE void ldx_ix( void ) +{ + fetch_effective_address(); + X=RM16(EAD); + CLR_NZV; + SET_NZ16(X); +} + +/* $10aE LDY indexed -**0- */ +M6809_INLINE void ldy_ix( void ) +{ + fetch_effective_address(); + Y=RM16(EAD); + CLR_NZV; + SET_NZ16(Y); +} + +/* $aF STX (STY) indexed -**0- */ +M6809_INLINE void stx_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(X); + WM16(EAD,&pX); +} + +/* $10aF STY indexed -**0- */ +M6809_INLINE void sty_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(Y); + WM16(EAD,&pY); +} + +/* $b0 SUBA extended ?**** */ +M6809_INLINE void suba_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b1 CMPA extended ?**** */ +M6809_INLINE void cmpa_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t; + CLR_NZVC; + SET_FLAGS8(A,t,r); +} + +/* $b2 SBCA extended ?**** */ +M6809_INLINE void sbca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(A,t,r); + A = r; +} + +/* $b3 SUBD (CMPD CMPU) extended -**** */ +M6809_INLINE void subd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $10b3 CMPD extended -**** */ +M6809_INLINE void cmpd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11b3 CMPU extended -**** */ +M6809_INLINE void cmpu_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = U; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $b4 ANDA extended -**0- */ +M6809_INLINE void anda_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A &= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b5 BITA extended -**0- */ +M6809_INLINE void bita_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = A & t; + CLR_NZV; SET_NZ8(r); +} + +/* $b6 LDA extended -**0- */ +M6809_INLINE void lda_ex( void ) +{ + EXTBYTE(A); + CLR_NZV; + SET_NZ8(A); +} + +/* $b7 STA extended -**0- */ +M6809_INLINE void sta_ex( void ) +{ + CLR_NZV; + SET_NZ8(A); + EXTENDED; + WM(EAD,A); +} + +/* $b8 EORA extended -**0- */ +M6809_INLINE void eora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A ^= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $b9 ADCA extended ***** */ +M6809_INLINE void adca_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bA ORA extended -**0- */ +M6809_INLINE void ora_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + A |= t; + CLR_NZV; + SET_NZ8(A); +} + +/* $bB ADDA extended ***** */ +M6809_INLINE void adda_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = A + t; + CLR_HNZVC; + SET_FLAGS8(A,t,r); + SET_H(A,t,r); + A = r; +} + +/* $bC CMPX (CMPY CMPS) extended -**** */ +M6809_INLINE void cmpx_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = X; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $10bC CMPY extended -**** */ +M6809_INLINE void cmpy_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = Y; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $11bC CMPS extended -**** */ +M6809_INLINE void cmps_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = S; + r = d - b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); +} + +/* $bD JSR extended ----- */ +M6809_INLINE void jsr_ex( void ) +{ + EXTENDED; + PUSHWORD(pPC); + PCD = EAD; + CHANGE_PC; +} + +/* $bE LDX (LDY) extended -**0- */ +M6809_INLINE void ldx_ex( void ) +{ + EXTWORD(pX); + CLR_NZV; + SET_NZ16(X); +} + +/* $10bE LDY extended -**0- */ +M6809_INLINE void ldy_ex( void ) +{ + EXTWORD(pY); + CLR_NZV; + SET_NZ16(Y); +} + +/* $bF STX (STY) extended -**0- */ +M6809_INLINE void stx_ex( void ) +{ + CLR_NZV; + SET_NZ16(X); + EXTENDED; + WM16(EAD,&pX); +} + +/* $10bF STY extended -**0- */ +M6809_INLINE void sty_ex( void ) +{ + CLR_NZV; + SET_NZ16(Y); + EXTENDED; + WM16(EAD,&pY); +} + +/* $c0 SUBB immediate ?**** */ +M6809_INLINE void subb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $c1 CMPB immediate ?**** */ +M6809_INLINE void cmpb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t; + CLR_NZVC; SET_FLAGS8(B,t,r); +} + +/* $c2 SBCB immediate ?**** */ +M6809_INLINE void sbcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $c3 ADDD immediate -**** */ +M6809_INLINE void addd_im( void ) +{ + UINT32 r,d; + PAIR b; + IMMWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $c4 ANDB immediate -**0- */ +M6809_INLINE void andb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $c5 BITB immediate -**0- */ +M6809_INLINE void bitb_im( void ) +{ + UINT8 t,r; + IMMBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $c6 LDB immediate -**0- */ +M6809_INLINE void ldb_im( void ) +{ + IMMBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* is this a legal instruction? */ +/* $c7 STB immediate -**0- */ +M6809_INLINE void stb_im( void ) +{ + CLR_NZV; + SET_NZ8(B); + IMM8; + WM(EAD,B); +} + +/* $c8 EORB immediate -**0- */ +M6809_INLINE void eorb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $c9 ADCB immediate ***** */ +M6809_INLINE void adcb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $cA ORB immediate -**0- */ +M6809_INLINE void orb_im( void ) +{ + UINT8 t; + IMMBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $cB ADDB immediate ***** */ +M6809_INLINE void addb_im( void ) +{ + UINT16 t,r; + IMMBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $cC LDD immediate -**0- */ +M6809_INLINE void ldd_im( void ) +{ + IMMWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* is this a legal instruction? */ +/* $cD STD immediate -**0- */ +M6809_INLINE void std_im( void ) +{ + CLR_NZV; + SET_NZ16(D); + IMM16; + WM16(EAD,&pD); +} + +/* $cE LDU (LDS) immediate -**0- */ +M6809_INLINE void ldu_im( void ) +{ + IMMWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10cE LDS immediate -**0- */ +M6809_INLINE void lds_im( void ) +{ + IMMWORD(pS); + CLR_NZV; + SET_NZ16(S); + m6809.int_state |= M6809_LDS; +} + +/* is this a legal instruction? */ +/* $cF STU (STS) immediate -**0- */ +M6809_INLINE void stu_im( void ) +{ + CLR_NZV; + SET_NZ16(U); + IMM16; + WM16(EAD,&pU); +} + +/* is this a legal instruction? */ +/* $10cF STS immediate -**0- */ +M6809_INLINE void sts_im( void ) +{ + CLR_NZV; + SET_NZ16(S); + IMM16; + WM16(EAD,&pS); +} + +/* $d0 SUBB direct ?**** */ +M6809_INLINE void subb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $d1 CMPB direct ?**** */ +M6809_INLINE void cmpb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $d2 SBCB direct ?**** */ +M6809_INLINE void sbcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $d3 ADDD direct -**** */ +M6809_INLINE void addd_di( void ) +{ + UINT32 r,d; + PAIR b; + DIRWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $d4 ANDB direct -**0- */ +M6809_INLINE void andb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $d5 BITB direct -**0- */ +M6809_INLINE void bitb_di( void ) +{ + UINT8 t,r; + DIRBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $d6 LDB direct -**0- */ +M6809_INLINE void ldb_di( void ) +{ + DIRBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $d7 STB direct -**0- */ +M6809_INLINE void stb_di( void ) +{ + CLR_NZV; + SET_NZ8(B); + DIRECT; + WM(EAD,B); +} + +/* $d8 EORB direct -**0- */ +M6809_INLINE void eorb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $d9 ADCB direct ***** */ +M6809_INLINE void adcb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $dA ORB direct -**0- */ +M6809_INLINE void orb_di( void ) +{ + UINT8 t; + DIRBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $dB ADDB direct ***** */ +M6809_INLINE void addb_di( void ) +{ + UINT16 t,r; + DIRBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $dC LDD direct -**0- */ +M6809_INLINE void ldd_di( void ) +{ + DIRWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* $dD STD direct -**0- */ +M6809_INLINE void std_di( void ) +{ + CLR_NZV; + SET_NZ16(D); + DIRECT; + WM16(EAD,&pD); +} + +/* $dE LDU (LDS) direct -**0- */ +M6809_INLINE void ldu_di( void ) +{ + DIRWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10dE LDS direct -**0- */ +M6809_INLINE void lds_di( void ) +{ + DIRWORD(pS); + CLR_NZV; + SET_NZ16(S); + m6809.int_state |= M6809_LDS; +} + +/* $dF STU (STS) direct -**0- */ +M6809_INLINE void stu_di( void ) +{ + CLR_NZV; + SET_NZ16(U); + DIRECT; + WM16(EAD,&pU); +} + +/* $10dF STS direct -**0- */ +M6809_INLINE void sts_di( void ) +{ + CLR_NZV; + SET_NZ16(S); + DIRECT; + WM16(EAD,&pS); +} + +/* $e0 SUBB indexed ?**** */ +M6809_INLINE void subb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $e1 CMPB indexed ?**** */ +M6809_INLINE void cmpb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $e2 SBCB indexed ?**** */ +M6809_INLINE void sbcb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $e3 ADDD indexed -**** */ +M6809_INLINE void addd_ix( void ) +{ + UINT32 r,d; + PAIR b; + fetch_effective_address(); + b.d=RM16(EAD); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $e4 ANDB indexed -**0- */ +M6809_INLINE void andb_ix( void ) +{ + fetch_effective_address(); + B &= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e5 BITB indexed -**0- */ +M6809_INLINE void bitb_ix( void ) +{ + UINT8 r; + fetch_effective_address(); + r = B & RM(EAD); + CLR_NZV; + SET_NZ8(r); +} + +/* $e6 LDB indexed -**0- */ +M6809_INLINE void ldb_ix( void ) +{ + fetch_effective_address(); + B = RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e7 STB indexed -**0- */ +M6809_INLINE void stb_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ8(B); + WM(EAD,B); +} + +/* $e8 EORB indexed -**0- */ +M6809_INLINE void eorb_ix( void ) +{ + fetch_effective_address(); + B ^= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $e9 ADCB indexed ***** */ +M6809_INLINE void adcb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $eA ORB indexed -**0- */ +M6809_INLINE void orb_ix( void ) +{ + fetch_effective_address(); + B |= RM(EAD); + CLR_NZV; + SET_NZ8(B); +} + +/* $eB ADDB indexed ***** */ +M6809_INLINE void addb_ix( void ) +{ + UINT16 t,r; + fetch_effective_address(); + t = RM(EAD); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $eC LDD indexed -**0- */ +M6809_INLINE void ldd_ix( void ) +{ + fetch_effective_address(); + D=RM16(EAD); + CLR_NZV; SET_NZ16(D); +} + +/* $eD STD indexed -**0- */ +M6809_INLINE void std_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(D); + WM16(EAD,&pD); +} + +/* $eE LDU (LDS) indexed -**0- */ +M6809_INLINE void ldu_ix( void ) +{ + fetch_effective_address(); + U=RM16(EAD); + CLR_NZV; + SET_NZ16(U); +} + +/* $10eE LDS indexed -**0- */ +M6809_INLINE void lds_ix( void ) +{ + fetch_effective_address(); + S=RM16(EAD); + CLR_NZV; + SET_NZ16(S); + m6809.int_state |= M6809_LDS; +} + +/* $eF STU (STS) indexed -**0- */ +M6809_INLINE void stu_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(U); + WM16(EAD,&pU); +} + +/* $10eF STS indexed -**0- */ +M6809_INLINE void sts_ix( void ) +{ + fetch_effective_address(); + CLR_NZV; + SET_NZ16(S); + WM16(EAD,&pS); +} + +/* $f0 SUBB extended ?**** */ +M6809_INLINE void subb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $f1 CMPB extended ?**** */ +M6809_INLINE void cmpb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t; + CLR_NZVC; + SET_FLAGS8(B,t,r); +} + +/* $f2 SBCB extended ?**** */ +M6809_INLINE void sbcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B - t - (CC & CC_C); + CLR_NZVC; + SET_FLAGS8(B,t,r); + B = r; +} + +/* $f3 ADDD extended -**** */ +M6809_INLINE void addd_ex( void ) +{ + UINT32 r,d; + PAIR b; + EXTWORD(b); + d = D; + r = d + b.d; + CLR_NZVC; + SET_FLAGS16(d,b.d,r); + D = r; +} + +/* $f4 ANDB extended -**0- */ +M6809_INLINE void andb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B &= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $f5 BITB extended -**0- */ +M6809_INLINE void bitb_ex( void ) +{ + UINT8 t,r; + EXTBYTE(t); + r = B & t; + CLR_NZV; + SET_NZ8(r); +} + +/* $f6 LDB extended -**0- */ +M6809_INLINE void ldb_ex( void ) +{ + EXTBYTE(B); + CLR_NZV; + SET_NZ8(B); +} + +/* $f7 STB extended -**0- */ +M6809_INLINE void stb_ex( void ) +{ + CLR_NZV; + SET_NZ8(B); + EXTENDED; + WM(EAD,B); +} + +/* $f8 EORB extended -**0- */ +M6809_INLINE void eorb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B ^= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $f9 ADCB extended ***** */ +M6809_INLINE void adcb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t + (CC & CC_C); + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $fA ORB extended -**0- */ +M6809_INLINE void orb_ex( void ) +{ + UINT8 t; + EXTBYTE(t); + B |= t; + CLR_NZV; + SET_NZ8(B); +} + +/* $fB ADDB extended ***** */ +M6809_INLINE void addb_ex( void ) +{ + UINT16 t,r; + EXTBYTE(t); + r = B + t; + CLR_HNZVC; + SET_FLAGS8(B,t,r); + SET_H(B,t,r); + B = r; +} + +/* $fC LDD extended -**0- */ +M6809_INLINE void ldd_ex( void ) +{ + EXTWORD(pD); + CLR_NZV; + SET_NZ16(D); +} + +/* $fD STD extended -**0- */ +M6809_INLINE void std_ex( void ) +{ + CLR_NZV; + SET_NZ16(D); + EXTENDED; + WM16(EAD,&pD); +} + +/* $fE LDU (LDS) extended -**0- */ +M6809_INLINE void ldu_ex( void ) +{ + EXTWORD(pU); + CLR_NZV; + SET_NZ16(U); +} + +/* $10fE LDS extended -**0- */ +M6809_INLINE void lds_ex( void ) +{ + EXTWORD(pS); + CLR_NZV; + SET_NZ16(S); + m6809.int_state |= M6809_LDS; +} + +/* $fF STU (STS) extended -**0- */ +M6809_INLINE void stu_ex( void ) +{ + CLR_NZV; + SET_NZ16(U); + EXTENDED; + WM16(EAD,&pU); +} + +/* $10fF STS extended -**0- */ +M6809_INLINE void sts_ex( void ) +{ + CLR_NZV; + SET_NZ16(S); + EXTENDED; + WM16(EAD,&pS); +} + +/* $10xx opcodes */ +M6809_INLINE void pref10( void ) +{ + UINT8 ireg2 = ROP(PCD); + PC++; + switch( ireg2 ) + { + case 0x21: lbrn(); m6809_ICount-=5; break; + case 0x22: lbhi(); m6809_ICount-=5; break; + case 0x23: lbls(); m6809_ICount-=5; break; + case 0x24: lbcc(); m6809_ICount-=5; break; + case 0x25: lbcs(); m6809_ICount-=5; break; + case 0x26: lbne(); m6809_ICount-=5; break; + case 0x27: lbeq(); m6809_ICount-=5; break; + case 0x28: lbvc(); m6809_ICount-=5; break; + case 0x29: lbvs(); m6809_ICount-=5; break; + case 0x2a: lbpl(); m6809_ICount-=5; break; + case 0x2b: lbmi(); m6809_ICount-=5; break; + case 0x2c: lbge(); m6809_ICount-=5; break; + case 0x2d: lblt(); m6809_ICount-=5; break; + case 0x2e: lbgt(); m6809_ICount-=5; break; + case 0x2f: lble(); m6809_ICount-=5; break; + + case 0x3f: swi2(); m6809_ICount-=20; break; + + case 0x83: cmpd_im(); m6809_ICount-=5; break; + case 0x8c: cmpy_im(); m6809_ICount-=5; break; + case 0x8e: ldy_im(); m6809_ICount-=4; break; + case 0x8f: sty_im(); m6809_ICount-=4; break; + + case 0x93: cmpd_di(); m6809_ICount-=7; break; + case 0x9c: cmpy_di(); m6809_ICount-=7; break; + case 0x9e: ldy_di(); m6809_ICount-=6; break; + case 0x9f: sty_di(); m6809_ICount-=6; break; + + case 0xa3: cmpd_ix(); m6809_ICount-=7; break; + case 0xac: cmpy_ix(); m6809_ICount-=7; break; + case 0xae: ldy_ix(); m6809_ICount-=6; break; + case 0xaf: sty_ix(); m6809_ICount-=6; break; + + case 0xb3: cmpd_ex(); m6809_ICount-=8; break; + case 0xbc: cmpy_ex(); m6809_ICount-=8; break; + case 0xbe: ldy_ex(); m6809_ICount-=7; break; + case 0xbf: sty_ex(); m6809_ICount-=7; break; + + case 0xce: lds_im(); m6809_ICount-=4; break; + case 0xcf: sts_im(); m6809_ICount-=4; break; + + case 0xde: lds_di(); m6809_ICount-=6; break; + case 0xdf: sts_di(); m6809_ICount-=6; break; + + case 0xee: lds_ix(); m6809_ICount-=6; break; + case 0xef: sts_ix(); m6809_ICount-=6; break; + + case 0xfe: lds_ex(); m6809_ICount-=7; break; + case 0xff: sts_ex(); m6809_ICount-=7; break; + + default: illegal(); break; + } +} + +/* $11xx opcodes */ +M6809_INLINE void pref11( void ) +{ + UINT8 ireg2 = ROP(PCD); + PC++; + switch( ireg2 ) + { + case 0x3f: swi3(); m6809_ICount-=20; break; + + case 0x83: cmpu_im(); m6809_ICount-=5; break; + case 0x8c: cmps_im(); m6809_ICount-=5; break; + + case 0x93: cmpu_di(); m6809_ICount-=7; break; + case 0x9c: cmps_di(); m6809_ICount-=7; break; + + case 0xa3: cmpu_ix(); m6809_ICount-=7; break; + case 0xac: cmps_ix(); m6809_ICount-=7; break; + + case 0xb3: cmpu_ex(); m6809_ICount-=8; break; + case 0xbc: cmps_ex(); m6809_ICount-=8; break; + + default: illegal(); break; + } +} + + diff --git a/src/cpu/m6809/6809tbl.c b/src/cpu/m6809/6809tbl.c new file mode 100644 index 00000000..fec237f1 --- /dev/null +++ b/src/cpu/m6809/6809tbl.c @@ -0,0 +1,316 @@ +M6809_INLINE void abx(void); +M6809_INLINE void adca_di(void); +M6809_INLINE void adca_ex(void); +M6809_INLINE void adca_im(void); +M6809_INLINE void adca_ix(void); +M6809_INLINE void adcb_di(void); +M6809_INLINE void adcb_ex(void); +M6809_INLINE void adcb_im(void); +M6809_INLINE void adcb_ix(void); +M6809_INLINE void adda_di(void); +M6809_INLINE void adda_ex(void); +M6809_INLINE void adda_im(void); +M6809_INLINE void adda_ix(void); +M6809_INLINE void addb_di(void); +M6809_INLINE void addb_ex(void); +M6809_INLINE void addb_im(void); +M6809_INLINE void addb_ix(void); +M6809_INLINE void addd_di(void); +M6809_INLINE void addd_ex(void); +M6809_INLINE void addd_im(void); +M6809_INLINE void addd_ix(void); +M6809_INLINE void anda_di(void); +M6809_INLINE void anda_ex(void); +M6809_INLINE void anda_im(void); +M6809_INLINE void anda_ix(void); +M6809_INLINE void andb_di(void); +M6809_INLINE void andb_ex(void); +M6809_INLINE void andb_im(void); +M6809_INLINE void andb_ix(void); +M6809_INLINE void andcc(void); +M6809_INLINE void asl_di(void); +M6809_INLINE void asl_ex(void); +M6809_INLINE void asl_ix(void); +M6809_INLINE void asla(void); +M6809_INLINE void aslb(void); +M6809_INLINE void asr_di(void); +M6809_INLINE void asr_ex(void); +M6809_INLINE void asr_ix(void); +M6809_INLINE void asra(void); +M6809_INLINE void asrb(void); +M6809_INLINE void bcc(void); +M6809_INLINE void bcs(void); +M6809_INLINE void beq(void); +M6809_INLINE void bge(void); +M6809_INLINE void bgt(void); +M6809_INLINE void bhi(void); +M6809_INLINE void bita_di(void); +M6809_INLINE void bita_ex(void); +M6809_INLINE void bita_im(void); +M6809_INLINE void bita_ix(void); +M6809_INLINE void bitb_di(void); +M6809_INLINE void bitb_ex(void); +M6809_INLINE void bitb_im(void); +M6809_INLINE void bitb_ix(void); +M6809_INLINE void ble(void); +M6809_INLINE void bls(void); +M6809_INLINE void blt(void); +M6809_INLINE void bmi(void); +M6809_INLINE void bne(void); +M6809_INLINE void bpl(void); +M6809_INLINE void bra(void); +M6809_INLINE void brn(void); +M6809_INLINE void bsr(void); +M6809_INLINE void bvc(void); +M6809_INLINE void bvs(void); +M6809_INLINE void clr_di(void); +M6809_INLINE void clr_ex(void); +M6809_INLINE void clr_ix(void); +M6809_INLINE void clra(void); +M6809_INLINE void clrb(void); +M6809_INLINE void cmpa_di(void); +M6809_INLINE void cmpa_ex(void); +M6809_INLINE void cmpa_im(void); +M6809_INLINE void cmpa_ix(void); +M6809_INLINE void cmpb_di(void); +M6809_INLINE void cmpb_ex(void); +M6809_INLINE void cmpb_im(void); +M6809_INLINE void cmpb_ix(void); +M6809_INLINE void cmpd_di(void); +M6809_INLINE void cmpd_ex(void); +M6809_INLINE void cmpd_im(void); +M6809_INLINE void cmpd_ix(void); +M6809_INLINE void cmps_di(void); +M6809_INLINE void cmps_ex(void); +M6809_INLINE void cmps_im(void); +M6809_INLINE void cmps_ix(void); +M6809_INLINE void cmpu_di(void); +M6809_INLINE void cmpu_ex(void); +M6809_INLINE void cmpu_im(void); +M6809_INLINE void cmpu_ix(void); +M6809_INLINE void cmpx_di(void); +M6809_INLINE void cmpx_ex(void); +M6809_INLINE void cmpx_im(void); +M6809_INLINE void cmpx_ix(void); +M6809_INLINE void cmpy_di(void); +M6809_INLINE void cmpy_ex(void); +M6809_INLINE void cmpy_im(void); +M6809_INLINE void cmpy_ix(void); +M6809_INLINE void com_di(void); +M6809_INLINE void com_ex(void); +M6809_INLINE void com_ix(void); +M6809_INLINE void coma(void); +M6809_INLINE void comb(void); +M6809_INLINE void cwai(void); +M6809_INLINE void daa(void); +M6809_INLINE void dec_di(void); +M6809_INLINE void dec_ex(void); +M6809_INLINE void dec_ix(void); +M6809_INLINE void deca(void); +M6809_INLINE void decb(void); +M6809_INLINE void eora_di(void); +M6809_INLINE void eora_ex(void); +M6809_INLINE void eora_im(void); +M6809_INLINE void eora_ix(void); +M6809_INLINE void eorb_di(void); +M6809_INLINE void eorb_ex(void); +M6809_INLINE void eorb_im(void); +M6809_INLINE void eorb_ix(void); +M6809_INLINE void exg(void); +M6809_INLINE void illegal(void); +M6809_INLINE void inc_di(void); +M6809_INLINE void inc_ex(void); +M6809_INLINE void inc_ix(void); +M6809_INLINE void inca(void); +M6809_INLINE void incb(void); +M6809_INLINE void jmp_di(void); +M6809_INLINE void jmp_ex(void); +M6809_INLINE void jmp_ix(void); +M6809_INLINE void jsr_di(void); +M6809_INLINE void jsr_ex(void); +M6809_INLINE void jsr_ix(void); +M6809_INLINE void lbcc(void); +M6809_INLINE void lbcs(void); +M6809_INLINE void lbeq(void); +M6809_INLINE void lbge(void); +M6809_INLINE void lbgt(void); +M6809_INLINE void lbhi(void); +M6809_INLINE void lble(void); +M6809_INLINE void lbls(void); +M6809_INLINE void lblt(void); +M6809_INLINE void lbmi(void); +M6809_INLINE void lbne(void); +M6809_INLINE void lbpl(void); +M6809_INLINE void lbra(void); +M6809_INLINE void lbrn(void); +M6809_INLINE void lbsr(void); +M6809_INLINE void lbvc(void); +M6809_INLINE void lbvs(void); +M6809_INLINE void lda_di(void); +M6809_INLINE void lda_ex(void); +M6809_INLINE void lda_im(void); +M6809_INLINE void lda_ix(void); +M6809_INLINE void ldb_di(void); +M6809_INLINE void ldb_ex(void); +M6809_INLINE void ldb_im(void); +M6809_INLINE void ldb_ix(void); +M6809_INLINE void ldd_di(void); +M6809_INLINE void ldd_ex(void); +M6809_INLINE void ldd_im(void); +M6809_INLINE void ldd_ix(void); +M6809_INLINE void lds_di(void); +M6809_INLINE void lds_ex(void); +M6809_INLINE void lds_im(void); +M6809_INLINE void lds_ix(void); +M6809_INLINE void ldu_di(void); +M6809_INLINE void ldu_ex(void); +M6809_INLINE void ldu_im(void); +M6809_INLINE void ldu_ix(void); +M6809_INLINE void ldx_di(void); +M6809_INLINE void ldx_ex(void); +M6809_INLINE void ldx_im(void); +M6809_INLINE void ldx_ix(void); +M6809_INLINE void ldy_di(void); +M6809_INLINE void ldy_ex(void); +M6809_INLINE void ldy_im(void); +M6809_INLINE void ldy_ix(void); +M6809_INLINE void leas(void); +M6809_INLINE void leau(void); +M6809_INLINE void leax(void); +M6809_INLINE void leay(void); +M6809_INLINE void lsr_di(void); +M6809_INLINE void lsr_ex(void); +M6809_INLINE void lsr_ix(void); +M6809_INLINE void lsra(void); +M6809_INLINE void lsrb(void); +M6809_INLINE void mul(void); +M6809_INLINE void neg_di(void); +M6809_INLINE void neg_ex(void); +M6809_INLINE void neg_ix(void); +M6809_INLINE void nega(void); +M6809_INLINE void negb(void); +M6809_INLINE void nop(void); +M6809_INLINE void ora_di(void); +M6809_INLINE void ora_ex(void); +M6809_INLINE void ora_im(void); +M6809_INLINE void ora_ix(void); +M6809_INLINE void orb_di(void); +M6809_INLINE void orb_ex(void); +M6809_INLINE void orb_im(void); +M6809_INLINE void orb_ix(void); +M6809_INLINE void orcc(void); +M6809_INLINE void pshs(void); +M6809_INLINE void pshu(void); +M6809_INLINE void puls(void); +M6809_INLINE void pulu(void); +M6809_INLINE void rol_di(void); +M6809_INLINE void rol_ex(void); +M6809_INLINE void rol_ix(void); +M6809_INLINE void rola(void); +M6809_INLINE void rolb(void); +M6809_INLINE void ror_di(void); +M6809_INLINE void ror_ex(void); +M6809_INLINE void ror_ix(void); +M6809_INLINE void rora(void); +M6809_INLINE void rorb(void); +M6809_INLINE void rti(void); +M6809_INLINE void rts(void); +M6809_INLINE void sbca_di(void); +M6809_INLINE void sbca_ex(void); +M6809_INLINE void sbca_im(void); +M6809_INLINE void sbca_ix(void); +M6809_INLINE void sbcb_di(void); +M6809_INLINE void sbcb_ex(void); +M6809_INLINE void sbcb_im(void); +M6809_INLINE void sbcb_ix(void); +M6809_INLINE void sex(void); +M6809_INLINE void sta_di(void); +M6809_INLINE void sta_ex(void); +M6809_INLINE void sta_im(void); +M6809_INLINE void sta_ix(void); +M6809_INLINE void stb_di(void); +M6809_INLINE void stb_ex(void); +M6809_INLINE void stb_im(void); +M6809_INLINE void stb_ix(void); +M6809_INLINE void std_di(void); +M6809_INLINE void std_ex(void); +M6809_INLINE void std_im(void); +M6809_INLINE void std_ix(void); +M6809_INLINE void sts_di(void); +M6809_INLINE void sts_ex(void); +M6809_INLINE void sts_im(void); +M6809_INLINE void sts_ix(void); +M6809_INLINE void stu_di(void); +M6809_INLINE void stu_ex(void); +M6809_INLINE void stu_im(void); +M6809_INLINE void stu_ix(void); +M6809_INLINE void stx_di(void); +M6809_INLINE void stx_ex(void); +M6809_INLINE void stx_im(void); +M6809_INLINE void stx_ix(void); +M6809_INLINE void sty_di(void); +M6809_INLINE void sty_ex(void); +M6809_INLINE void sty_im(void); +M6809_INLINE void sty_ix(void); +M6809_INLINE void suba_di(void); +M6809_INLINE void suba_ex(void); +M6809_INLINE void suba_im(void); +M6809_INLINE void suba_ix(void); +M6809_INLINE void subb_di(void); +M6809_INLINE void subb_ex(void); +M6809_INLINE void subb_im(void); +M6809_INLINE void subb_ix(void); +M6809_INLINE void subd_di(void); +M6809_INLINE void subd_ex(void); +M6809_INLINE void subd_im(void); +M6809_INLINE void subd_ix(void); +M6809_INLINE void swi(void); +M6809_INLINE void swi2(void); +M6809_INLINE void swi3(void); +M6809_INLINE void sync(void); +M6809_INLINE void tfr(void); +M6809_INLINE void tst_di(void); +M6809_INLINE void tst_ex(void); +M6809_INLINE void tst_ix(void); +M6809_INLINE void tsta(void); +M6809_INLINE void tstb(void); + +M6809_INLINE void pref10(void); +M6809_INLINE void pref11(void); + +#if (BIG_SWITCH==0) +static void (*const m6809_main[0x100])(void) = { + neg_di, neg_di, illegal,com_di, lsr_di, illegal,ror_di, asr_di, /* 00 */ + asl_di, rol_di, dec_di, illegal,inc_di, tst_di, jmp_di, clr_di, + pref10, pref11, nop, sync, illegal,illegal,lbra, lbsr, /* 10 */ + illegal,daa, orcc, illegal,andcc, sex, exg, tfr, + bra, brn, bhi, bls, bcc, bcs, bne, beq, /* 20 */ + bvc, bvs, bpl, bmi, bge, blt, bgt, ble, + leax, leay, leas, leau, pshs, puls, pshu, pulu, /* 30 */ + illegal,rts, abx, rti, cwai, mul, illegal,swi, + nega, illegal,illegal,coma, lsra, illegal,rora, asra, /* 40 */ + asla, rola, deca, illegal,inca, tsta, illegal,clra, + negb, illegal,illegal,comb, lsrb, illegal,rorb, asrb, /* 50 */ + aslb, rolb, decb, illegal,incb, tstb, illegal,clrb, + neg_ix, illegal,illegal,com_ix, lsr_ix, illegal,ror_ix, asr_ix, /* 60 */ + asl_ix, rol_ix, dec_ix, illegal,inc_ix, tst_ix, jmp_ix, clr_ix, + neg_ex, illegal,illegal,com_ex, lsr_ex, illegal,ror_ex, asr_ex, /* 70 */ + asl_ex, rol_ex, dec_ex, illegal,inc_ex, tst_ex, jmp_ex, clr_ex, + suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im, /* 80 */ + eora_im,adca_im,ora_im, adda_im,cmpx_im,bsr, ldx_im, stx_im, + suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di, /* 90 */ + eora_di,adca_di,ora_di, adda_di,cmpx_di,jsr_di, ldx_di, stx_di, + suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix, /* a0 */ + eora_ix,adca_ix,ora_ix, adda_ix,cmpx_ix,jsr_ix, ldx_ix, stx_ix, + suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex, /* b0 */ + eora_ex,adca_ex,ora_ex, adda_ex,cmpx_ex,jsr_ex, ldx_ex, stx_ex, + subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im, /* c0 */ + eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldu_im, stu_im, + subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di, /* d0 */ + eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldu_di, stu_di, + subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix, /* e0 */ + eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldu_ix, stu_ix, + subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex, /* f0 */ + eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldu_ex, stu_ex +}; +#endif diff --git a/src/cpu/m6809/m6809.cpp b/src/cpu/m6809/m6809.cpp new file mode 100644 index 00000000..195fbf20 --- /dev/null +++ b/src/cpu/m6809/m6809.cpp @@ -0,0 +1,1217 @@ +/*** m6809: Portable 6809 emulator ****************************************** + + Copyright John Butler + + References: + + 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands. + + m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from + the 6809 Simulator V09) + + 6809 Microcomputer Programming & Interfacing with Experiments" + by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc. + + System dependencies: UINT16 must be 16 bit unsigned int + UINT8 must be 8 bit unsigned int + UINT32 must be more than 16 bits + arrays up to 65536 bytes must be supported + machine must be twos complement + + History: +991026 HJB: + Fixed missing calls to cpu_changepc() for the TFR and EXG ocpodes. + Replaced m6809_slapstic checks by a macro (CHANGE_PC). ESB still + needs the tweaks. + +991024 HJB: + Tried to improve speed: Using bit7 of cycles1/2 as flag for multi + byte opcodes is gone, those opcodes now call fetch_effective_address(). + Got rid of the slow/fast flags for stack (S and U) memory accesses. + Minor changes to use 32 bit values as arguments to memory functions + and added defines for that purpose (e.g. X = 16bit XD = 32bit). + +990312 HJB: + Added bugfixes according to Aaron's findings. + Reset only sets CC_II and CC_IF, DP to zero and PC from reset vector. +990311 HJB: + Added _info functions. Now uses static m6808_Regs struct instead + of single statics. Changed the 16 bit registers to use the generic + PAIR union. Registers defined using macros. Split the core into + four execution loops for M6802, M6803, M6808 and HD63701. + TST, TSTA and TSTB opcodes reset carry flag. + Modified the read/write stack handlers to push LSB first then MSB + and pull MSB first then LSB. + +990228 HJB: + Changed the interrupt handling again. Now interrupts are taken + either right at the moment the lines are asserted or whenever + an interrupt is enabled and the corresponding line is still + asserted. That way the pending_interrupts checks are not + needed anymore. However, the CWAI and SYNC flags still need + some flags, so I changed the name to 'int_state'. + This core also has the code for the old interrupt system removed. + +990225 HJB: + Cleaned up the code here and there, added some comments. + Slightly changed the SAR opcodes (similiar to other CPU cores). + Added symbolic names for the flag bits. + Changed the way CWAI/Interrupt() handle CPU state saving. + A new flag M6809_STATE in pending_interrupts is used to determine + if a state save is needed on interrupt entry or already done by CWAI. + Added M6809_IRQ_LINE and M6809_FIRQ_LINE defines to m6809.h + Moved the internal interrupt_pending flags from m6809.h to m6809.c + Changed CWAI cycles2[0x3c] to be 2 (plus all or at least 19 if + CWAI actually pushes the entire state). + Implemented undocumented TFR/EXG for undefined source and mixed 8/16 + bit transfers (they should transfer/exchange the constant $ff). + Removed unused jmp/jsr _slap functions from 6809ops.c, + m6809_slapstick check moved into the opcode functions. + +*****************************************************************************/ + +//#include "debugger.h" +#include "burnint.h" +#include "m6809.h" + +/* Enable big switch statement for the main opcodes */ +#ifndef BIG_SWITCH +#define BIG_SWITCH 1 +#endif + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +//extern offs_t m6809_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); + +#define M6809_INLINE static +#define change_pc(newpc) m6809.pc.w.l = (newpc) +#define M6809_CLEAR_LINE 0 +#define M6809_INPUT_LINE_NMI 32 + +M6809_INLINE void fetch_effective_address( void ); + +/* flag bits in the cc register */ +#define CC_C 0x01 /* Carry */ +#define CC_V 0x02 /* Overflow */ +#define CC_Z 0x04 /* Zero */ +#define CC_N 0x08 /* Negative */ +#define CC_II 0x10 /* Inhibit IRQ */ +#define CC_H 0x20 /* Half (auxiliary) carry */ +#define CC_IF 0x40 /* Inhibit FIRQ */ +#define CC_E 0x80 /* entire state pushed */ + +/* 6809 registers */ +static m6809_Regs m6809; + +#define pPPC m6809.ppc +#define pPC m6809.pc +#define pU m6809.u +#define pS m6809.s +#define pX m6809.x +#define pY m6809.y +#define pD m6809.d + +#define PPC m6809.ppc.w.l +#define PC m6809.pc.w.l +#define PCD m6809.pc.d +#define U m6809.u.w.l +#define UD m6809.u.d +#define S m6809.s.w.l +#define SD m6809.s.d +#define X m6809.x.w.l +#define XD m6809.x.d +#define Y m6809.y.w.l +#define YD m6809.y.d +#define D m6809.d.w.l +#define A m6809.d.b.h +#define B m6809.d.b.l +#define DP m6809.dp.b.h +#define DPD m6809.dp.d +#define CC m6809.cc + +static PAIR ea; /* effective address */ +#define EA ea.w.l +#define EAD ea.d + +#define CHANGE_PC change_pc(PCD) + +#define M6809_CWAI 8 /* set when CWAI is waiting for an interrupt */ +#define M6809_SYNC 16 /* set when SYNC is waiting for an interrupt */ +#define M6809_LDS 32 /* set when LDS occured at least once */ + +#define CHECK_IRQ_LINES \ + if( m6809.irq_state[M6809_IRQ_LINE] != M6809_CLEAR_LINE || \ + m6809.irq_state[M6809_FIRQ_LINE] != M6809_CLEAR_LINE ) \ + m6809.int_state &= ~M6809_SYNC; /* clear SYNC flag */ \ + if( m6809.irq_state[M6809_FIRQ_LINE]!=M6809_CLEAR_LINE && !(CC & CC_IF) ) \ + { \ + /* fast IRQ */ \ + /* HJB 990225: state already saved by CWAI? */ \ + if( m6809.int_state & M6809_CWAI ) \ + { \ + m6809.int_state &= ~M6809_CWAI; /* clear CWAI */ \ + m6809.extra_cycles += 7; /* subtract +7 cycles */ \ + } \ + else \ + { \ + CC &= ~CC_E; /* save 'short' state */ \ + PUSHWORD(pPC); \ + PUSHBYTE(CC); \ + m6809.extra_cycles += 10; /* subtract +10 cycles */ \ + } \ + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ \ + PCD=RM16(0xfff6); \ + CHANGE_PC; \ + } \ + else \ + if( m6809.irq_state[M6809_IRQ_LINE]!=M6809_CLEAR_LINE && !(CC & CC_II) ) \ + { \ + /* standard IRQ */ \ + /* HJB 990225: state already saved by CWAI? */ \ + if( m6809.int_state & M6809_CWAI ) \ + { \ + m6809.int_state &= ~M6809_CWAI; /* clear CWAI flag */ \ + m6809.extra_cycles += 7; /* subtract +7 cycles */ \ + } \ + else \ + { \ + CC |= CC_E; /* save entire state */ \ + PUSHWORD(pPC); \ + PUSHWORD(pU); \ + PUSHWORD(pY); \ + PUSHWORD(pX); \ + PUSHBYTE(DP); \ + PUSHBYTE(B); \ + PUSHBYTE(A); \ + PUSHBYTE(CC); \ + m6809.extra_cycles += 19; /* subtract +19 cycles */ \ + } \ + CC |= CC_II; /* inhibit IRQ */ \ + PCD=RM16(0xfff8); \ + CHANGE_PC; \ + } + +/* public globals */ +static int m6809_ICount; + +/* these are re-defined in m6809.h TO RAM, ROM or functions in cpuintrf.c */ +#define RM(Addr) M6809_RDMEM(Addr) +#define WM(Addr,Value) M6809_WRMEM(Addr,Value) +#define ROP(Addr) M6809_RDOP(Addr) +#define ROP_ARG(Addr) M6809_RDOP_ARG(Addr) + +/* macros to access memory */ +#define IMMBYTE(b) b = ROP_ARG(PCD); PC++ +#define IMMWORD(w) w.d = (ROP_ARG(PCD)<<8) | ROP_ARG((PCD+1)&0xffff); PC+=2 + +#define PUSHBYTE(b) --S; WM(SD,b) +#define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h) +#define PULLBYTE(b) b = RM(SD); S++ +#define PULLWORD(w) w = RM(SD)<<8; S++; w |= RM(SD); S++ + +#define PSHUBYTE(b) --U; WM(UD,b); +#define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h) +#define PULUBYTE(b) b = RM(UD); U++ +#define PULUWORD(w) w = RM(UD)<<8; U++; w |= RM(UD); U++ + +#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C) +#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V) +#define CLR_NZ CC&=~(CC_N|CC_Z) +#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C) +#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C) +#define CLR_Z CC&=~(CC_Z) +#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C) +#define CLR_ZC CC&=~(CC_Z|CC_C) + +/* macros for CC -- CC bits affected should be reset before calling */ +#define SET_Z(a) if(!a)SEZ +#define SET_Z8(a) SET_Z((UINT8)a) +#define SET_Z16(a) SET_Z((UINT16)a) +#define SET_N8(a) CC|=((a&0x80)>>4) +#define SET_N16(a) CC|=((a&0x8000)>>12) +#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1) +#define SET_C8(a) CC|=((a&0x100)>>8) +#define SET_C16(a) CC|=((a&0x10000)>>16) +#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6) +#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14) + +static const UINT8 flags8i[256]= /* increment */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; +static const UINT8 flags8d[256]= /* decrement */ +{ +CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N, +CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N +}; +#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];} +#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];} + +/* combos */ +#define SET_NZ8(a) {SET_N8(a);SET_Z(a);} +#define SET_NZ16(a) {SET_N16(a);SET_Z(a);} +#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);} +#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);} + +/* for treating an unsigned byte as a signed word */ +#define SIGNED(b) ((UINT16)(b&0x80?b|0xff00:b)) + +/* macros for addressing modes (postbytes have their own code) */ +#define DIRECT EAD = DPD; IMMBYTE(ea.b.l) +#define IMM8 EAD = PCD; PC++ +#define IMM16 EAD = PCD; PC+=2 +#define EXTENDED IMMWORD(ea) + +/* macros to set status flags */ +#if defined(SEC) +#undef SEC +#endif +#define SEC CC|=CC_C +#define CLC CC&=~CC_C +#define SEZ CC|=CC_Z +#define CLZ CC&=~CC_Z +#define SEN CC|=CC_N +#define CLN CC&=~CC_N +#define SEV CC|=CC_V +#define CLV CC&=~CC_V +#define SEH CC|=CC_H +#define CLH CC&=~CC_H + +/* macros for convenience */ +#define DIRBYTE(b) {DIRECT;b=RM(EAD);} +#define DIRWORD(w) {DIRECT;w.d=RM16(EAD);} +#define EXTBYTE(b) {EXTENDED;b=RM(EAD);} +#define EXTWORD(w) {EXTENDED;w.d=RM16(EAD);} + +/* macros for branch instructions */ +#define BRANCH(f) { \ + UINT8 t; \ + IMMBYTE(t); \ + if( f ) \ + { \ + PC += SIGNED(t); \ + CHANGE_PC; \ + } \ +} + +#define LBRANCH(f) { \ + PAIR t; \ + IMMWORD(t); \ + if( f ) \ + { \ + m6809_ICount -= 1; \ + PC += t.w.l; \ + CHANGE_PC; \ + } \ +} + +#define NXORV ((CC&CC_N)^((CC&CC_V)<<2)) + +/* macros for setting/getting registers in TFR/EXG instructions */ + +#if (!BIG_SWITCH) +/* timings for 1-byte opcodes */ +static const UINT8 cycles1[] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /*0*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 3, 6, + /*1*/ 0, 0, 2, 4, 0, 0, 5, 9, 0, 2, 3, 0, 3, 2, 8, 6, + /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + /*3*/ 4, 4, 4, 4, 5, 5, 5, 5, 0, 5, 3, 6,20,11, 0,19, + /*4*/ 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, + /*5*/ 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, + /*6*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 3, 6, + /*7*/ 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 4, 7, + /*8*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 4, 7, 3, 0, + /*9*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5, + /*A*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5, + /*B*/ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 6, 6, + /*C*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 3, + /*D*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + /*E*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, + /*F*/ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6 +}; +#endif + +M6809_INLINE UINT32 RM16( UINT32 Addr ) +{ + UINT32 result = RM(Addr) << 8; + return result | RM((Addr+1)&0xffff); +} + +M6809_INLINE void WM16( UINT32 Addr, PAIR *p ) +{ + WM( Addr, p->b.h ); + WM( (Addr+1)&0xffff, p->b.l ); +} + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +void m6809_get_context(void *dst) +{ + if( dst ) + *(m6809_Regs*)dst = m6809; +} + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +void m6809_set_context(void *src) +{ + if( src ) + m6809 = *(m6809_Regs*)src; + CHANGE_PC; + + CHECK_IRQ_LINES; +} + + +/****************************************************************************/ +/* Reset registers to their initial values */ +/****************************************************************************/ +void m6809_init(int (*irqcallback)(int)) +{ +// state_save_register_item("m6809", index, PC); +// state_save_register_item("m6809", index, PPC); +// state_save_register_item("m6809", index, D); +// state_save_register_item("m6809", index, DP); +// state_save_register_item("m6809", index, U); +// state_save_register_item("m6809", index, S); +// state_save_register_item("m6809", index, X); +// state_save_register_item("m6809", index, Y); +// state_save_register_item("m6809", index, CC); +// state_save_register_item_array("m6809", index, m6809.irq_state); +// state_save_register_item("m6809", index, m6809.int_state); +// state_save_register_item("m6809", index, m6809.nmi_state); + + m6809.irq_callback = irqcallback; +} + +void m6809_reset(void) +{ + m6809.int_state = 0; + m6809.nmi_state = M6809_CLEAR_LINE; + m6809.irq_state[0] = M6809_CLEAR_LINE; + m6809.irq_state[1] = M6809_CLEAR_LINE; + + DPD = 0; /* Reset direct page register */ + + CC |= CC_II; /* IRQ disabled */ + CC |= CC_IF; /* FIRQ disabled */ + + PCD = RM16(0xfffe); + CHANGE_PC; +} + +/* +static void m6809_exit(void) +{ + +}*/ + +/* Generate interrupts */ +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ +void m6809_set_irq_line(int irqline, int state) +{ + if (irqline == M6809_INPUT_LINE_NMI) + { + if (m6809.nmi_state == state) return; + m6809.nmi_state = state; +// LOG(("M6809#%d set_irq_line (NMI) %d\n", cpu_getactivecpu(), state)); + if( state == M6809_CLEAR_LINE ) return; + + /* if the stack was not yet initialized */ + if( !(m6809.int_state & M6809_LDS) ) return; + + m6809.int_state &= ~M6809_SYNC; + /* HJB 990225: state already saved by CWAI? */ + if( m6809.int_state & M6809_CWAI ) + { + m6809.int_state &= ~M6809_CWAI; + m6809.extra_cycles += 7; /* subtract +7 cycles next time */ + } + else + { + CC |= CC_E; /* save entire state */ + PUSHWORD(pPC); + PUSHWORD(pU); + PUSHWORD(pY); + PUSHWORD(pX); + PUSHBYTE(DP); + PUSHBYTE(B); + PUSHBYTE(A); + PUSHBYTE(CC); + m6809.extra_cycles += 19; /* subtract +19 cycles next time */ + } + CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ + PCD = RM16(0xfffc); + CHANGE_PC; + } + else if (irqline < 2) + { +// LOG(("M6809#%d set_irq_line %d, %d\n", cpu_getactivecpu(), irqline, state)); + m6809.irq_state[irqline] = state; + if (state == M6809_CLEAR_LINE) return; + CHECK_IRQ_LINES; + } +} + +/* includes the static function prototypes and the master opcode table */ +#include "6809tbl.c" + +/* includes the actual opcode implementations */ +#include "6809ops.c" + +/* execute instructions on this CPU until icount expires */ +int m6809_execute(int cycles) /* NS 970908 */ +{ + m6809_ICount = cycles - m6809.extra_cycles; + m6809.extra_cycles = 0; + + if (m6809.int_state & (M6809_CWAI | M6809_SYNC)) + { +// debugger_instruction_hook(Machine, PCD); + m6809_ICount = 0; + } + else + { + do + { + pPPC = pPC; + +// debugger_instruction_hook(Machine, PCD); + + m6809.ireg = ROP(PCD); + PC++; +#if BIG_SWITCH + switch( m6809.ireg ) + { + case 0x00: neg_di(); m6809_ICount-= 6; break; + case 0x01: neg_di(); m6809_ICount-= 6; break; /* undocumented */ + case 0x02: illegal(); m6809_ICount-= 2; break; + case 0x03: com_di(); m6809_ICount-= 6; break; + case 0x04: lsr_di(); m6809_ICount-= 6; break; + case 0x05: illegal(); m6809_ICount-= 2; break; + case 0x06: ror_di(); m6809_ICount-= 6; break; + case 0x07: asr_di(); m6809_ICount-= 6; break; + case 0x08: asl_di(); m6809_ICount-= 6; break; + case 0x09: rol_di(); m6809_ICount-= 6; break; + case 0x0a: dec_di(); m6809_ICount-= 6; break; + case 0x0b: illegal(); m6809_ICount-= 2; break; + case 0x0c: inc_di(); m6809_ICount-= 6; break; + case 0x0d: tst_di(); m6809_ICount-= 6; break; + case 0x0e: jmp_di(); m6809_ICount-= 3; break; + case 0x0f: clr_di(); m6809_ICount-= 6; break; + case 0x10: pref10(); break; + case 0x11: pref11(); break; + case 0x12: nop(); m6809_ICount-= 2; break; + case 0x13: sync(); m6809_ICount-= 4; break; + case 0x14: illegal(); m6809_ICount-= 2; break; + case 0x15: illegal(); m6809_ICount-= 2; break; + case 0x16: lbra(); m6809_ICount-= 5; break; + case 0x17: lbsr(); m6809_ICount-= 9; break; + case 0x18: illegal(); m6809_ICount-= 2; break; + case 0x19: daa(); m6809_ICount-= 2; break; + case 0x1a: orcc(); m6809_ICount-= 3; break; + case 0x1b: illegal(); m6809_ICount-= 2; break; + case 0x1c: andcc(); m6809_ICount-= 3; break; + case 0x1d: sex(); m6809_ICount-= 2; break; + case 0x1e: exg(); m6809_ICount-= 8; break; + case 0x1f: tfr(); m6809_ICount-= 6; break; + case 0x20: bra(); m6809_ICount-= 3; break; + case 0x21: brn(); m6809_ICount-= 3; break; + case 0x22: bhi(); m6809_ICount-= 3; break; + case 0x23: bls(); m6809_ICount-= 3; break; + case 0x24: bcc(); m6809_ICount-= 3; break; + case 0x25: bcs(); m6809_ICount-= 3; break; + case 0x26: bne(); m6809_ICount-= 3; break; + case 0x27: beq(); m6809_ICount-= 3; break; + case 0x28: bvc(); m6809_ICount-= 3; break; + case 0x29: bvs(); m6809_ICount-= 3; break; + case 0x2a: bpl(); m6809_ICount-= 3; break; + case 0x2b: bmi(); m6809_ICount-= 3; break; + case 0x2c: bge(); m6809_ICount-= 3; break; + case 0x2d: blt(); m6809_ICount-= 3; break; + case 0x2e: bgt(); m6809_ICount-= 3; break; + case 0x2f: ble(); m6809_ICount-= 3; break; + case 0x30: leax(); m6809_ICount-= 4; break; + case 0x31: leay(); m6809_ICount-= 4; break; + case 0x32: leas(); m6809_ICount-= 4; break; + case 0x33: leau(); m6809_ICount-= 4; break; + case 0x34: pshs(); m6809_ICount-= 5; break; + case 0x35: puls(); m6809_ICount-= 5; break; + case 0x36: pshu(); m6809_ICount-= 5; break; + case 0x37: pulu(); m6809_ICount-= 5; break; + case 0x38: illegal(); m6809_ICount-= 2; break; + case 0x39: rts(); m6809_ICount-= 5; break; + case 0x3a: abx(); m6809_ICount-= 3; break; + case 0x3b: rti(); m6809_ICount-= 6; break; + case 0x3c: cwai(); m6809_ICount-=20; break; + case 0x3d: mul(); m6809_ICount-=11; break; + case 0x3e: illegal(); m6809_ICount-= 2; break; + case 0x3f: swi(); m6809_ICount-=19; break; + case 0x40: nega(); m6809_ICount-= 2; break; + case 0x41: illegal(); m6809_ICount-= 2; break; + case 0x42: illegal(); m6809_ICount-= 2; break; + case 0x43: coma(); m6809_ICount-= 2; break; + case 0x44: lsra(); m6809_ICount-= 2; break; + case 0x45: illegal(); m6809_ICount-= 2; break; + case 0x46: rora(); m6809_ICount-= 2; break; + case 0x47: asra(); m6809_ICount-= 2; break; + case 0x48: asla(); m6809_ICount-= 2; break; + case 0x49: rola(); m6809_ICount-= 2; break; + case 0x4a: deca(); m6809_ICount-= 2; break; + case 0x4b: illegal(); m6809_ICount-= 2; break; + case 0x4c: inca(); m6809_ICount-= 2; break; + case 0x4d: tsta(); m6809_ICount-= 2; break; + case 0x4e: illegal(); m6809_ICount-= 2; break; + case 0x4f: clra(); m6809_ICount-= 2; break; + case 0x50: negb(); m6809_ICount-= 2; break; + case 0x51: illegal(); m6809_ICount-= 2; break; + case 0x52: illegal(); m6809_ICount-= 2; break; + case 0x53: comb(); m6809_ICount-= 2; break; + case 0x54: lsrb(); m6809_ICount-= 2; break; + case 0x55: illegal(); m6809_ICount-= 2; break; + case 0x56: rorb(); m6809_ICount-= 2; break; + case 0x57: asrb(); m6809_ICount-= 2; break; + case 0x58: aslb(); m6809_ICount-= 2; break; + case 0x59: rolb(); m6809_ICount-= 2; break; + case 0x5a: decb(); m6809_ICount-= 2; break; + case 0x5b: illegal(); m6809_ICount-= 2; break; + case 0x5c: incb(); m6809_ICount-= 2; break; + case 0x5d: tstb(); m6809_ICount-= 2; break; + case 0x5e: illegal(); m6809_ICount-= 2; break; + case 0x5f: clrb(); m6809_ICount-= 2; break; + case 0x60: neg_ix(); m6809_ICount-= 6; break; + case 0x61: illegal(); m6809_ICount-= 2; break; + case 0x62: illegal(); m6809_ICount-= 2; break; + case 0x63: com_ix(); m6809_ICount-= 6; break; + case 0x64: lsr_ix(); m6809_ICount-= 6; break; + case 0x65: illegal(); m6809_ICount-= 2; break; + case 0x66: ror_ix(); m6809_ICount-= 6; break; + case 0x67: asr_ix(); m6809_ICount-= 6; break; + case 0x68: asl_ix(); m6809_ICount-= 6; break; + case 0x69: rol_ix(); m6809_ICount-= 6; break; + case 0x6a: dec_ix(); m6809_ICount-= 6; break; + case 0x6b: illegal(); m6809_ICount-= 2; break; + case 0x6c: inc_ix(); m6809_ICount-= 6; break; + case 0x6d: tst_ix(); m6809_ICount-= 6; break; + case 0x6e: jmp_ix(); m6809_ICount-= 3; break; + case 0x6f: clr_ix(); m6809_ICount-= 6; break; + case 0x70: neg_ex(); m6809_ICount-= 7; break; + case 0x71: illegal(); m6809_ICount-= 2; break; + case 0x72: illegal(); m6809_ICount-= 2; break; + case 0x73: com_ex(); m6809_ICount-= 7; break; + case 0x74: lsr_ex(); m6809_ICount-= 7; break; + case 0x75: illegal(); m6809_ICount-= 2; break; + case 0x76: ror_ex(); m6809_ICount-= 7; break; + case 0x77: asr_ex(); m6809_ICount-= 7; break; + case 0x78: asl_ex(); m6809_ICount-= 7; break; + case 0x79: rol_ex(); m6809_ICount-= 7; break; + case 0x7a: dec_ex(); m6809_ICount-= 7; break; + case 0x7b: illegal(); m6809_ICount-= 2; break; + case 0x7c: inc_ex(); m6809_ICount-= 7; break; + case 0x7d: tst_ex(); m6809_ICount-= 7; break; + case 0x7e: jmp_ex(); m6809_ICount-= 4; break; + case 0x7f: clr_ex(); m6809_ICount-= 7; break; + case 0x80: suba_im(); m6809_ICount-= 2; break; + case 0x81: cmpa_im(); m6809_ICount-= 2; break; + case 0x82: sbca_im(); m6809_ICount-= 2; break; + case 0x83: subd_im(); m6809_ICount-= 4; break; + case 0x84: anda_im(); m6809_ICount-= 2; break; + case 0x85: bita_im(); m6809_ICount-= 2; break; + case 0x86: lda_im(); m6809_ICount-= 2; break; + case 0x87: sta_im(); m6809_ICount-= 2; break; + case 0x88: eora_im(); m6809_ICount-= 2; break; + case 0x89: adca_im(); m6809_ICount-= 2; break; + case 0x8a: ora_im(); m6809_ICount-= 2; break; + case 0x8b: adda_im(); m6809_ICount-= 2; break; + case 0x8c: cmpx_im(); m6809_ICount-= 4; break; + case 0x8d: bsr(); m6809_ICount-= 7; break; + case 0x8e: ldx_im(); m6809_ICount-= 3; break; + case 0x8f: stx_im(); m6809_ICount-= 2; break; + case 0x90: suba_di(); m6809_ICount-= 4; break; + case 0x91: cmpa_di(); m6809_ICount-= 4; break; + case 0x92: sbca_di(); m6809_ICount-= 4; break; + case 0x93: subd_di(); m6809_ICount-= 6; break; + case 0x94: anda_di(); m6809_ICount-= 4; break; + case 0x95: bita_di(); m6809_ICount-= 4; break; + case 0x96: lda_di(); m6809_ICount-= 4; break; + case 0x97: sta_di(); m6809_ICount-= 4; break; + case 0x98: eora_di(); m6809_ICount-= 4; break; + case 0x99: adca_di(); m6809_ICount-= 4; break; + case 0x9a: ora_di(); m6809_ICount-= 4; break; + case 0x9b: adda_di(); m6809_ICount-= 4; break; + case 0x9c: cmpx_di(); m6809_ICount-= 6; break; + case 0x9d: jsr_di(); m6809_ICount-= 7; break; + case 0x9e: ldx_di(); m6809_ICount-= 5; break; + case 0x9f: stx_di(); m6809_ICount-= 5; break; + case 0xa0: suba_ix(); m6809_ICount-= 4; break; + case 0xa1: cmpa_ix(); m6809_ICount-= 4; break; + case 0xa2: sbca_ix(); m6809_ICount-= 4; break; + case 0xa3: subd_ix(); m6809_ICount-= 6; break; + case 0xa4: anda_ix(); m6809_ICount-= 4; break; + case 0xa5: bita_ix(); m6809_ICount-= 4; break; + case 0xa6: lda_ix(); m6809_ICount-= 4; break; + case 0xa7: sta_ix(); m6809_ICount-= 4; break; + case 0xa8: eora_ix(); m6809_ICount-= 4; break; + case 0xa9: adca_ix(); m6809_ICount-= 4; break; + case 0xaa: ora_ix(); m6809_ICount-= 4; break; + case 0xab: adda_ix(); m6809_ICount-= 4; break; + case 0xac: cmpx_ix(); m6809_ICount-= 6; break; + case 0xad: jsr_ix(); m6809_ICount-= 7; break; + case 0xae: ldx_ix(); m6809_ICount-= 5; break; + case 0xaf: stx_ix(); m6809_ICount-= 5; break; + case 0xb0: suba_ex(); m6809_ICount-= 5; break; + case 0xb1: cmpa_ex(); m6809_ICount-= 5; break; + case 0xb2: sbca_ex(); m6809_ICount-= 5; break; + case 0xb3: subd_ex(); m6809_ICount-= 7; break; + case 0xb4: anda_ex(); m6809_ICount-= 5; break; + case 0xb5: bita_ex(); m6809_ICount-= 5; break; + case 0xb6: lda_ex(); m6809_ICount-= 5; break; + case 0xb7: sta_ex(); m6809_ICount-= 5; break; + case 0xb8: eora_ex(); m6809_ICount-= 5; break; + case 0xb9: adca_ex(); m6809_ICount-= 5; break; + case 0xba: ora_ex(); m6809_ICount-= 5; break; + case 0xbb: adda_ex(); m6809_ICount-= 5; break; + case 0xbc: cmpx_ex(); m6809_ICount-= 7; break; + case 0xbd: jsr_ex(); m6809_ICount-= 8; break; + case 0xbe: ldx_ex(); m6809_ICount-= 6; break; + case 0xbf: stx_ex(); m6809_ICount-= 6; break; + case 0xc0: subb_im(); m6809_ICount-= 2; break; + case 0xc1: cmpb_im(); m6809_ICount-= 2; break; + case 0xc2: sbcb_im(); m6809_ICount-= 2; break; + case 0xc3: addd_im(); m6809_ICount-= 4; break; + case 0xc4: andb_im(); m6809_ICount-= 2; break; + case 0xc5: bitb_im(); m6809_ICount-= 2; break; + case 0xc6: ldb_im(); m6809_ICount-= 2; break; + case 0xc7: stb_im(); m6809_ICount-= 2; break; + case 0xc8: eorb_im(); m6809_ICount-= 2; break; + case 0xc9: adcb_im(); m6809_ICount-= 2; break; + case 0xca: orb_im(); m6809_ICount-= 2; break; + case 0xcb: addb_im(); m6809_ICount-= 2; break; + case 0xcc: ldd_im(); m6809_ICount-= 3; break; + case 0xcd: std_im(); m6809_ICount-= 2; break; + case 0xce: ldu_im(); m6809_ICount-= 3; break; + case 0xcf: stu_im(); m6809_ICount-= 3; break; + case 0xd0: subb_di(); m6809_ICount-= 4; break; + case 0xd1: cmpb_di(); m6809_ICount-= 4; break; + case 0xd2: sbcb_di(); m6809_ICount-= 4; break; + case 0xd3: addd_di(); m6809_ICount-= 6; break; + case 0xd4: andb_di(); m6809_ICount-= 4; break; + case 0xd5: bitb_di(); m6809_ICount-= 4; break; + case 0xd6: ldb_di(); m6809_ICount-= 4; break; + case 0xd7: stb_di(); m6809_ICount-= 4; break; + case 0xd8: eorb_di(); m6809_ICount-= 4; break; + case 0xd9: adcb_di(); m6809_ICount-= 4; break; + case 0xda: orb_di(); m6809_ICount-= 4; break; + case 0xdb: addb_di(); m6809_ICount-= 4; break; + case 0xdc: ldd_di(); m6809_ICount-= 5; break; + case 0xdd: std_di(); m6809_ICount-= 5; break; + case 0xde: ldu_di(); m6809_ICount-= 5; break; + case 0xdf: stu_di(); m6809_ICount-= 5; break; + case 0xe0: subb_ix(); m6809_ICount-= 4; break; + case 0xe1: cmpb_ix(); m6809_ICount-= 4; break; + case 0xe2: sbcb_ix(); m6809_ICount-= 4; break; + case 0xe3: addd_ix(); m6809_ICount-= 6; break; + case 0xe4: andb_ix(); m6809_ICount-= 4; break; + case 0xe5: bitb_ix(); m6809_ICount-= 4; break; + case 0xe6: ldb_ix(); m6809_ICount-= 4; break; + case 0xe7: stb_ix(); m6809_ICount-= 4; break; + case 0xe8: eorb_ix(); m6809_ICount-= 4; break; + case 0xe9: adcb_ix(); m6809_ICount-= 4; break; + case 0xea: orb_ix(); m6809_ICount-= 4; break; + case 0xeb: addb_ix(); m6809_ICount-= 4; break; + case 0xec: ldd_ix(); m6809_ICount-= 5; break; + case 0xed: std_ix(); m6809_ICount-= 5; break; + case 0xee: ldu_ix(); m6809_ICount-= 5; break; + case 0xef: stu_ix(); m6809_ICount-= 5; break; + case 0xf0: subb_ex(); m6809_ICount-= 5; break; + case 0xf1: cmpb_ex(); m6809_ICount-= 5; break; + case 0xf2: sbcb_ex(); m6809_ICount-= 5; break; + case 0xf3: addd_ex(); m6809_ICount-= 7; break; + case 0xf4: andb_ex(); m6809_ICount-= 5; break; + case 0xf5: bitb_ex(); m6809_ICount-= 5; break; + case 0xf6: ldb_ex(); m6809_ICount-= 5; break; + case 0xf7: stb_ex(); m6809_ICount-= 5; break; + case 0xf8: eorb_ex(); m6809_ICount-= 5; break; + case 0xf9: adcb_ex(); m6809_ICount-= 5; break; + case 0xfa: orb_ex(); m6809_ICount-= 5; break; + case 0xfb: addb_ex(); m6809_ICount-= 5; break; + case 0xfc: ldd_ex(); m6809_ICount-= 6; break; + case 0xfd: std_ex(); m6809_ICount-= 6; break; + case 0xfe: ldu_ex(); m6809_ICount-= 6; break; + case 0xff: stu_ex(); m6809_ICount-= 6; break; + } +#else + (*m6809_main[m6809.ireg])(); + m6809_ICount -= cycles1[m6809.ireg]; +#endif + + } while( m6809_ICount > 0 ); + + m6809_ICount -= m6809.extra_cycles; + m6809.extra_cycles = 0; + } + + return cycles - m6809_ICount; /* NS 970908 */ +} + +M6809_INLINE void fetch_effective_address( void ) +{ + UINT8 postbyte = ROP_ARG(PCD); + PC++; + + switch(postbyte) + { + case 0x00: EA=X; m6809_ICount-=1; break; + case 0x01: EA=X+1; m6809_ICount-=1; break; + case 0x02: EA=X+2; m6809_ICount-=1; break; + case 0x03: EA=X+3; m6809_ICount-=1; break; + case 0x04: EA=X+4; m6809_ICount-=1; break; + case 0x05: EA=X+5; m6809_ICount-=1; break; + case 0x06: EA=X+6; m6809_ICount-=1; break; + case 0x07: EA=X+7; m6809_ICount-=1; break; + case 0x08: EA=X+8; m6809_ICount-=1; break; + case 0x09: EA=X+9; m6809_ICount-=1; break; + case 0x0a: EA=X+10; m6809_ICount-=1; break; + case 0x0b: EA=X+11; m6809_ICount-=1; break; + case 0x0c: EA=X+12; m6809_ICount-=1; break; + case 0x0d: EA=X+13; m6809_ICount-=1; break; + case 0x0e: EA=X+14; m6809_ICount-=1; break; + case 0x0f: EA=X+15; m6809_ICount-=1; break; + + case 0x10: EA=X-16; m6809_ICount-=1; break; + case 0x11: EA=X-15; m6809_ICount-=1; break; + case 0x12: EA=X-14; m6809_ICount-=1; break; + case 0x13: EA=X-13; m6809_ICount-=1; break; + case 0x14: EA=X-12; m6809_ICount-=1; break; + case 0x15: EA=X-11; m6809_ICount-=1; break; + case 0x16: EA=X-10; m6809_ICount-=1; break; + case 0x17: EA=X-9; m6809_ICount-=1; break; + case 0x18: EA=X-8; m6809_ICount-=1; break; + case 0x19: EA=X-7; m6809_ICount-=1; break; + case 0x1a: EA=X-6; m6809_ICount-=1; break; + case 0x1b: EA=X-5; m6809_ICount-=1; break; + case 0x1c: EA=X-4; m6809_ICount-=1; break; + case 0x1d: EA=X-3; m6809_ICount-=1; break; + case 0x1e: EA=X-2; m6809_ICount-=1; break; + case 0x1f: EA=X-1; m6809_ICount-=1; break; + + case 0x20: EA=Y; m6809_ICount-=1; break; + case 0x21: EA=Y+1; m6809_ICount-=1; break; + case 0x22: EA=Y+2; m6809_ICount-=1; break; + case 0x23: EA=Y+3; m6809_ICount-=1; break; + case 0x24: EA=Y+4; m6809_ICount-=1; break; + case 0x25: EA=Y+5; m6809_ICount-=1; break; + case 0x26: EA=Y+6; m6809_ICount-=1; break; + case 0x27: EA=Y+7; m6809_ICount-=1; break; + case 0x28: EA=Y+8; m6809_ICount-=1; break; + case 0x29: EA=Y+9; m6809_ICount-=1; break; + case 0x2a: EA=Y+10; m6809_ICount-=1; break; + case 0x2b: EA=Y+11; m6809_ICount-=1; break; + case 0x2c: EA=Y+12; m6809_ICount-=1; break; + case 0x2d: EA=Y+13; m6809_ICount-=1; break; + case 0x2e: EA=Y+14; m6809_ICount-=1; break; + case 0x2f: EA=Y+15; m6809_ICount-=1; break; + + case 0x30: EA=Y-16; m6809_ICount-=1; break; + case 0x31: EA=Y-15; m6809_ICount-=1; break; + case 0x32: EA=Y-14; m6809_ICount-=1; break; + case 0x33: EA=Y-13; m6809_ICount-=1; break; + case 0x34: EA=Y-12; m6809_ICount-=1; break; + case 0x35: EA=Y-11; m6809_ICount-=1; break; + case 0x36: EA=Y-10; m6809_ICount-=1; break; + case 0x37: EA=Y-9; m6809_ICount-=1; break; + case 0x38: EA=Y-8; m6809_ICount-=1; break; + case 0x39: EA=Y-7; m6809_ICount-=1; break; + case 0x3a: EA=Y-6; m6809_ICount-=1; break; + case 0x3b: EA=Y-5; m6809_ICount-=1; break; + case 0x3c: EA=Y-4; m6809_ICount-=1; break; + case 0x3d: EA=Y-3; m6809_ICount-=1; break; + case 0x3e: EA=Y-2; m6809_ICount-=1; break; + case 0x3f: EA=Y-1; m6809_ICount-=1; break; + + case 0x40: EA=U; m6809_ICount-=1; break; + case 0x41: EA=U+1; m6809_ICount-=1; break; + case 0x42: EA=U+2; m6809_ICount-=1; break; + case 0x43: EA=U+3; m6809_ICount-=1; break; + case 0x44: EA=U+4; m6809_ICount-=1; break; + case 0x45: EA=U+5; m6809_ICount-=1; break; + case 0x46: EA=U+6; m6809_ICount-=1; break; + case 0x47: EA=U+7; m6809_ICount-=1; break; + case 0x48: EA=U+8; m6809_ICount-=1; break; + case 0x49: EA=U+9; m6809_ICount-=1; break; + case 0x4a: EA=U+10; m6809_ICount-=1; break; + case 0x4b: EA=U+11; m6809_ICount-=1; break; + case 0x4c: EA=U+12; m6809_ICount-=1; break; + case 0x4d: EA=U+13; m6809_ICount-=1; break; + case 0x4e: EA=U+14; m6809_ICount-=1; break; + case 0x4f: EA=U+15; m6809_ICount-=1; break; + + case 0x50: EA=U-16; m6809_ICount-=1; break; + case 0x51: EA=U-15; m6809_ICount-=1; break; + case 0x52: EA=U-14; m6809_ICount-=1; break; + case 0x53: EA=U-13; m6809_ICount-=1; break; + case 0x54: EA=U-12; m6809_ICount-=1; break; + case 0x55: EA=U-11; m6809_ICount-=1; break; + case 0x56: EA=U-10; m6809_ICount-=1; break; + case 0x57: EA=U-9; m6809_ICount-=1; break; + case 0x58: EA=U-8; m6809_ICount-=1; break; + case 0x59: EA=U-7; m6809_ICount-=1; break; + case 0x5a: EA=U-6; m6809_ICount-=1; break; + case 0x5b: EA=U-5; m6809_ICount-=1; break; + case 0x5c: EA=U-4; m6809_ICount-=1; break; + case 0x5d: EA=U-3; m6809_ICount-=1; break; + case 0x5e: EA=U-2; m6809_ICount-=1; break; + case 0x5f: EA=U-1; m6809_ICount-=1; break; + + case 0x60: EA=S; m6809_ICount-=1; break; + case 0x61: EA=S+1; m6809_ICount-=1; break; + case 0x62: EA=S+2; m6809_ICount-=1; break; + case 0x63: EA=S+3; m6809_ICount-=1; break; + case 0x64: EA=S+4; m6809_ICount-=1; break; + case 0x65: EA=S+5; m6809_ICount-=1; break; + case 0x66: EA=S+6; m6809_ICount-=1; break; + case 0x67: EA=S+7; m6809_ICount-=1; break; + case 0x68: EA=S+8; m6809_ICount-=1; break; + case 0x69: EA=S+9; m6809_ICount-=1; break; + case 0x6a: EA=S+10; m6809_ICount-=1; break; + case 0x6b: EA=S+11; m6809_ICount-=1; break; + case 0x6c: EA=S+12; m6809_ICount-=1; break; + case 0x6d: EA=S+13; m6809_ICount-=1; break; + case 0x6e: EA=S+14; m6809_ICount-=1; break; + case 0x6f: EA=S+15; m6809_ICount-=1; break; + + case 0x70: EA=S-16; m6809_ICount-=1; break; + case 0x71: EA=S-15; m6809_ICount-=1; break; + case 0x72: EA=S-14; m6809_ICount-=1; break; + case 0x73: EA=S-13; m6809_ICount-=1; break; + case 0x74: EA=S-12; m6809_ICount-=1; break; + case 0x75: EA=S-11; m6809_ICount-=1; break; + case 0x76: EA=S-10; m6809_ICount-=1; break; + case 0x77: EA=S-9; m6809_ICount-=1; break; + case 0x78: EA=S-8; m6809_ICount-=1; break; + case 0x79: EA=S-7; m6809_ICount-=1; break; + case 0x7a: EA=S-6; m6809_ICount-=1; break; + case 0x7b: EA=S-5; m6809_ICount-=1; break; + case 0x7c: EA=S-4; m6809_ICount-=1; break; + case 0x7d: EA=S-3; m6809_ICount-=1; break; + case 0x7e: EA=S-2; m6809_ICount-=1; break; + case 0x7f: EA=S-1; m6809_ICount-=1; break; + + case 0x80: EA=X; X++; m6809_ICount-=2; break; + case 0x81: EA=X; X+=2; m6809_ICount-=3; break; + case 0x82: X--; EA=X; m6809_ICount-=2; break; + case 0x83: X-=2; EA=X; m6809_ICount-=3; break; + case 0x84: EA=X; break; + case 0x85: EA=X+SIGNED(B); m6809_ICount-=1; break; + case 0x86: EA=X+SIGNED(A); m6809_ICount-=1; break; + case 0x87: EA=0; break; /* ILLEGAL*/ + case 0x88: IMMBYTE(EA); EA=X+SIGNED(EA); m6809_ICount-=1; break; /* this is a hack to make Vectrex work. It should be m6809_ICount-=1. Dunno where the cycle was lost :( */ + case 0x89: IMMWORD(ea); EA+=X; m6809_ICount-=4; break; + case 0x8a: EA=0; break; /* ILLEGAL*/ + case 0x8b: EA=X+D; m6809_ICount-=4; break; + case 0x8c: IMMBYTE(EA); EA=PC+SIGNED(EA); m6809_ICount-=1; break; + case 0x8d: IMMWORD(ea); EA+=PC; m6809_ICount-=5; break; + case 0x8e: EA=0; break; /* ILLEGAL*/ + case 0x8f: IMMWORD(ea); m6809_ICount-=5; break; + + case 0x90: EA=X; X++; EAD=RM16(EAD); m6809_ICount-=5; break; /* Indirect ,R+ not in my specs */ + case 0x91: EA=X; X+=2; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0x92: X--; EA=X; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0x93: X-=2; EA=X; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0x94: EA=X; EAD=RM16(EAD); m6809_ICount-=3; break; + case 0x95: EA=X+SIGNED(B); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0x96: EA=X+SIGNED(A); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0x97: EA=0; break; /* ILLEGAL*/ + case 0x98: IMMBYTE(EA); EA=X+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0x99: IMMWORD(ea); EA+=X; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0x9a: EA=0; break; /* ILLEGAL*/ + case 0x9b: EA=X+D; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0x9c: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0x9d: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); m6809_ICount-=8; break; + case 0x9e: EA=0; break; /* ILLEGAL*/ + case 0x9f: IMMWORD(ea); EAD=RM16(EAD); m6809_ICount-=8; break; + + case 0xa0: EA=Y; Y++; m6809_ICount-=2; break; + case 0xa1: EA=Y; Y+=2; m6809_ICount-=3; break; + case 0xa2: Y--; EA=Y; m6809_ICount-=2; break; + case 0xa3: Y-=2; EA=Y; m6809_ICount-=3; break; + case 0xa4: EA=Y; break; + case 0xa5: EA=Y+SIGNED(B); m6809_ICount-=1; break; + case 0xa6: EA=Y+SIGNED(A); m6809_ICount-=1; break; + case 0xa7: EA=0; break; /* ILLEGAL*/ + case 0xa8: IMMBYTE(EA); EA=Y+SIGNED(EA); m6809_ICount-=1; break; + case 0xa9: IMMWORD(ea); EA+=Y; m6809_ICount-=4; break; + case 0xaa: EA=0; break; /* ILLEGAL*/ + case 0xab: EA=Y+D; m6809_ICount-=4; break; + case 0xac: IMMBYTE(EA); EA=PC+SIGNED(EA); m6809_ICount-=1; break; + case 0xad: IMMWORD(ea); EA+=PC; m6809_ICount-=5; break; + case 0xae: EA=0; break; /* ILLEGAL*/ + case 0xaf: IMMWORD(ea); m6809_ICount-=5; break; + + case 0xb0: EA=Y; Y++; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xb1: EA=Y; Y+=2; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xb2: Y--; EA=Y; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xb3: Y-=2; EA=Y; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xb4: EA=Y; EAD=RM16(EAD); m6809_ICount-=3; break; + case 0xb5: EA=Y+SIGNED(B); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xb6: EA=Y+SIGNED(A); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xb7: EA=0; break; /* ILLEGAL*/ + case 0xb8: IMMBYTE(EA); EA=Y+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xb9: IMMWORD(ea); EA+=Y; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xba: EA=0; break; /* ILLEGAL*/ + case 0xbb: EA=Y+D; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xbc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xbd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); m6809_ICount-=8; break; + case 0xbe: EA=0; break; /* ILLEGAL*/ + case 0xbf: IMMWORD(ea); EAD=RM16(EAD); m6809_ICount-=8; break; + + case 0xc0: EA=U; U++; m6809_ICount-=2; break; + case 0xc1: EA=U; U+=2; m6809_ICount-=3; break; + case 0xc2: U--; EA=U; m6809_ICount-=2; break; + case 0xc3: U-=2; EA=U; m6809_ICount-=3; break; + case 0xc4: EA=U; break; + case 0xc5: EA=U+SIGNED(B); m6809_ICount-=1; break; + case 0xc6: EA=U+SIGNED(A); m6809_ICount-=1; break; + case 0xc7: EA=0; break; /*ILLEGAL*/ + case 0xc8: IMMBYTE(EA); EA=U+SIGNED(EA); m6809_ICount-=1; break; + case 0xc9: IMMWORD(ea); EA+=U; m6809_ICount-=4; break; + case 0xca: EA=0; break; /*ILLEGAL*/ + case 0xcb: EA=U+D; m6809_ICount-=4; break; + case 0xcc: IMMBYTE(EA); EA=PC+SIGNED(EA); m6809_ICount-=1; break; + case 0xcd: IMMWORD(ea); EA+=PC; m6809_ICount-=5; break; + case 0xce: EA=0; break; /*ILLEGAL*/ + case 0xcf: IMMWORD(ea); m6809_ICount-=5; break; + + case 0xd0: EA=U; U++; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xd1: EA=U; U+=2; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xd2: U--; EA=U; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xd3: U-=2; EA=U; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xd4: EA=U; EAD=RM16(EAD); m6809_ICount-=3; break; + case 0xd5: EA=U+SIGNED(B); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xd6: EA=U+SIGNED(A); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xd7: EA=0; break; /*ILLEGAL*/ + case 0xd8: IMMBYTE(EA); EA=U+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xd9: IMMWORD(ea); EA+=U; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xda: EA=0; break; /*ILLEGAL*/ + case 0xdb: EA=U+D; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xdc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xdd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); m6809_ICount-=8; break; + case 0xde: EA=0; break; /*ILLEGAL*/ + case 0xdf: IMMWORD(ea); EAD=RM16(EAD); m6809_ICount-=8; break; + + case 0xe0: EA=S; S++; m6809_ICount-=2; break; + case 0xe1: EA=S; S+=2; m6809_ICount-=3; break; + case 0xe2: S--; EA=S; m6809_ICount-=2; break; + case 0xe3: S-=2; EA=S; m6809_ICount-=3; break; + case 0xe4: EA=S; break; + case 0xe5: EA=S+SIGNED(B); m6809_ICount-=1; break; + case 0xe6: EA=S+SIGNED(A); m6809_ICount-=1; break; + case 0xe7: EA=0; break; /*ILLEGAL*/ + case 0xe8: IMMBYTE(EA); EA=S+SIGNED(EA); m6809_ICount-=1; break; + case 0xe9: IMMWORD(ea); EA+=S; m6809_ICount-=4; break; + case 0xea: EA=0; break; /*ILLEGAL*/ + case 0xeb: EA=S+D; m6809_ICount-=4; break; + case 0xec: IMMBYTE(EA); EA=PC+SIGNED(EA); m6809_ICount-=1; break; + case 0xed: IMMWORD(ea); EA+=PC; m6809_ICount-=5; break; + case 0xee: EA=0; break; /*ILLEGAL*/ + case 0xef: IMMWORD(ea); m6809_ICount-=5; break; + + case 0xf0: EA=S; S++; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xf1: EA=S; S+=2; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xf2: S--; EA=S; EAD=RM16(EAD); m6809_ICount-=5; break; + case 0xf3: S-=2; EA=S; EAD=RM16(EAD); m6809_ICount-=6; break; + case 0xf4: EA=S; EAD=RM16(EAD); m6809_ICount-=3; break; + case 0xf5: EA=S+SIGNED(B); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xf6: EA=S+SIGNED(A); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xf7: EA=0; break; /*ILLEGAL*/ + case 0xf8: IMMBYTE(EA); EA=S+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xf9: IMMWORD(ea); EA+=S; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xfa: EA=0; break; /*ILLEGAL*/ + case 0xfb: EA=S+D; EAD=RM16(EAD); m6809_ICount-=7; break; + case 0xfc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(EAD); m6809_ICount-=4; break; + case 0xfd: IMMWORD(ea); EA+=PC; EAD=RM16(EAD); m6809_ICount-=8; break; + case 0xfe: EA=0; break; /*ILLEGAL*/ + case 0xff: IMMWORD(ea); EAD=RM16(EAD); m6809_ICount-=8; break; + } +} + +#if 0 + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void m6809_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + M6809_IRQ_LINE: set_irq_line(M6809_IRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6809_FIRQ_LINE: set_irq_line(M6809_FIRQ_LINE, info->i); break; + case CPUINFO_INT_INPUT_STATE + M6809_INPUT_LINE_NMI: set_irq_line(M6809_INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + M6809_PC: PC = info->i; CHANGE_PC; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + M6809_S: S = info->i; break; + case CPUINFO_INT_REGISTER + M6809_CC: CC = info->i; CHECK_IRQ_LINES; break; + case CPUINFO_INT_REGISTER + M6809_U: U = info->i; break; + case CPUINFO_INT_REGISTER + M6809_A: A = info->i; break; + case CPUINFO_INT_REGISTER + M6809_B: B = info->i; break; + case CPUINFO_INT_REGISTER + M6809_X: X = info->i; break; + case CPUINFO_INT_REGISTER + M6809_Y: Y = info->i; break; + case CPUINFO_INT_REGISTER + M6809_DP: DP = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void m6809_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6809); break; + case CPUINFO_INT_INPUT_LINES: info->i = 2; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 2; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 19; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + M6809_IRQ_LINE: info->i = m6809.irq_state[M6809_IRQ_LINE]; break; + case CPUINFO_INT_INPUT_STATE + M6809_FIRQ_LINE: info->i = m6809.irq_state[M6809_FIRQ_LINE]; break; + case CPUINFO_INT_INPUT_STATE + M6809_INPUT_LINE_NMI: info->i = m6809.nmi_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + M6809_PC: info->i = PC; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + M6809_S: info->i = S; break; + case CPUINFO_INT_REGISTER + M6809_CC: info->i = CC; break; + case CPUINFO_INT_REGISTER + M6809_U: info->i = U; break; + case CPUINFO_INT_REGISTER + M6809_A: info->i = A; break; + case CPUINFO_INT_REGISTER + M6809_B: info->i = B; break; + case CPUINFO_INT_REGISTER + M6809_X: info->i = X; break; + case CPUINFO_INT_REGISTER + M6809_Y: info->i = Y; break; + case CPUINFO_INT_REGISTER + M6809_DP: info->i = DP; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = m6809_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = m6809_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = m6809_set_context; break; + case CPUINFO_PTR_INIT: info->init = m6809_init; break; + case CPUINFO_PTR_RESET: info->reset = m6809_reset; break; + case CPUINFO_PTR_EXIT: info->exit = m6809_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = m6809_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6809_dasm; break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m6809_ICount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6809"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Motorola 6809"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.11"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright John Butler"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c", + m6809.cc & 0x80 ? 'E':'.', + m6809.cc & 0x40 ? 'F':'.', + m6809.cc & 0x20 ? 'H':'.', + m6809.cc & 0x10 ? 'I':'.', + m6809.cc & 0x08 ? 'N':'.', + m6809.cc & 0x04 ? 'Z':'.', + m6809.cc & 0x02 ? 'V':'.', + m6809.cc & 0x01 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + M6809_PC: sprintf(info->s, "PC:%04X", m6809.pc.w.l); break; + case CPUINFO_STR_REGISTER + M6809_S: sprintf(info->s, "S:%04X", m6809.s.w.l); break; + case CPUINFO_STR_REGISTER + M6809_CC: sprintf(info->s, "CC:%02X", m6809.cc); break; + case CPUINFO_STR_REGISTER + M6809_U: sprintf(info->s, "U:%04X", m6809.u.w.l); break; + case CPUINFO_STR_REGISTER + M6809_A: sprintf(info->s, "A:%02X", m6809.d.b.h); break; + case CPUINFO_STR_REGISTER + M6809_B: sprintf(info->s, "B:%02X", m6809.d.b.l); break; + case CPUINFO_STR_REGISTER + M6809_X: sprintf(info->s, "X:%04X", m6809.x.w.l); break; + case CPUINFO_STR_REGISTER + M6809_Y: sprintf(info->s, "Y:%04X", m6809.y.w.l); break; + case CPUINFO_STR_REGISTER + M6809_DP: sprintf(info->s, "DP:%02X", m6809.dp.b.h); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +void m6809e_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "M6809E"); break; + + default: m6809_get_info(state, info); break; + } +} + +#endif diff --git a/src/cpu/m6809/m6809.h b/src/cpu/m6809/m6809.h new file mode 100644 index 00000000..f074341f --- /dev/null +++ b/src/cpu/m6809/m6809.h @@ -0,0 +1,83 @@ +/*** m6809: Portable 6809 emulator ******************************************/ + +//#pragma once + +#ifndef __M6809_H__ +#define __M6809_H__ + +//#include "cpuintrf.h" + +/* 6809 Registers */ +typedef struct +{ + PAIR pc; /* Program counter */ + PAIR ppc; /* Previous program counter */ + PAIR d; /* Accumulator a and b */ + PAIR dp; /* Direct Page register (page in MSB) */ + PAIR u, s; /* Stack pointers */ + PAIR x, y; /* Index registers */ + UINT8 cc; + UINT8 ireg; /* First opcode */ + UINT8 irq_state[2]; + int extra_cycles; /* cycles used up by interrupts */ + int (*irq_callback)(int irqline); + UINT8 int_state; /* SYNC and CWAI flags */ + UINT8 nmi_state; +} m6809_Regs; + +enum +{ + M6809_PC=1, M6809_S, M6809_CC ,M6809_A, M6809_B, M6809_U, M6809_X, M6809_Y, + M6809_DP +}; + +#define M6809_IRQ_LINE 0 /* IRQ line number */ +#define M6809_FIRQ_LINE 1 /* FIRQ line number */ + +//void m6809_get_info(UINT32 state, cpuinfo *info); +//void m6809e_get_info(UINT32 state, cpuinfo *info); + +void m6809_init(int (*irqcallback)(int)); +void m6809_reset(void); +int m6809_execute(int cycles); +void m6809_set_irq_line(int irqline, int state); +void m6809_get_context(void *dst); +void m6809_set_context(void *src); + +unsigned char M6809ReadByte(unsigned short Address); +void M6809WriteByte(unsigned short Address, unsigned char Data); +unsigned char M6809ReadOp(unsigned short Address); +unsigned char M6809ReadOpArg(unsigned short Address); + +/****************************************************************************/ +/* Read a byte from given memory location */ +/****************************************************************************/ +#define M6809_RDMEM(Addr) ((unsigned)M6809ReadByte(Addr)) + +/****************************************************************************/ +/* Write a byte to given memory location */ +/****************************************************************************/ +#define M6809_WRMEM(Addr,Value) (M6809WriteByte(Addr,Value)) + +/****************************************************************************/ +/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ +/* opcodes. In case of system with memory mapped I/O, this function can be */ +/* used to greatly speed up emulation */ +/****************************************************************************/ +#define M6809_RDOP(Addr) ((unsigned)M6809ReadOp(Addr)) + +/****************************************************************************/ +/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */ +/* opcode arguments. This difference can be used to support systems that */ +/* use different encoding mechanisms for opcodes and opcode arguments */ +/****************************************************************************/ +#define M6809_RDOP_ARG(Addr) ((unsigned)M6809ReadOpArg(Addr)) + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + +#endif /* __M6809_H__ */ diff --git a/src/cpu/m6809_intf.cpp b/src/cpu/m6809_intf.cpp new file mode 100644 index 00000000..ff6de6bc --- /dev/null +++ b/src/cpu/m6809_intf.cpp @@ -0,0 +1,308 @@ +#include "burnint.h" +#include "m6809_intf.h" + +#define MAX_CPU 8 + +INT32 nM6809Count = 0; +static INT32 nActiveCPU = 0; + +static M6809Ext *m6809CPUContext; + +static INT32 nM6809CyclesDone[MAX_CPU]; +INT32 nM6809CyclesTotal; + +static UINT8 M6809ReadByteDummyHandler(UINT16) +{ + return 0; +} + +static void M6809WriteByteDummyHandler(UINT16, UINT8) +{ +} + +static UINT8 M6809ReadOpDummyHandler(UINT16) +{ + return 0; +} + +static UINT8 M6809ReadOpArgDummyHandler(UINT16) +{ + return 0; +} + +void M6809Reset() +{ + m6809_reset(); +} + +void M6809NewFrame() +{ + for (INT32 i = 0; i < nM6809Count; i++) { + nM6809CyclesDone[i] = 0; + } + nM6809CyclesTotal = 0; +} + +INT32 M6809Init(INT32 num) +{ + nActiveCPU = -1; + nM6809Count = num % MAX_CPU; + + m6809CPUContext = (M6809Ext*)malloc(num * sizeof(M6809Ext)); + if (m6809CPUContext == NULL) { + return 1; + } + + memset(m6809CPUContext, 0, num * sizeof(M6809Ext)); + + for (INT32 i = 0; i < num; i++) { + m6809CPUContext[i].ReadByte = M6809ReadByteDummyHandler; + m6809CPUContext[i].WriteByte = M6809WriteByteDummyHandler; + m6809CPUContext[i].ReadOp = M6809ReadOpDummyHandler; + m6809CPUContext[i].ReadOpArg = M6809ReadOpArgDummyHandler; + + nM6809CyclesDone[i] = 0; + + for (INT32 j = 0; j < (0x0100 * 3); j++) { + m6809CPUContext[i].pMemMap[j] = NULL; + } + } + + nM6809CyclesTotal = 0; + + m6809_init(NULL); + + for (INT32 i = 0; i < num; i++) + CpuCheatRegister(0x0005, i); + + return 0; +} + +void M6809Exit() +{ + nM6809Count = 0; + + if (m6809CPUContext) { + free(m6809CPUContext); + m6809CPUContext = NULL; + } +} + +void M6809Open(INT32 num) +{ + nActiveCPU = num; + + m6809_set_context(&m6809CPUContext[nActiveCPU].reg); + + nM6809CyclesTotal = nM6809CyclesDone[nActiveCPU]; +} + +void M6809Close() +{ + m6809_get_context(&m6809CPUContext[nActiveCPU].reg); + + nM6809CyclesDone[nActiveCPU] = nM6809CyclesTotal; + + nActiveCPU = -1; +} + +INT32 M6809GetActive() +{ + return nActiveCPU; +} + +void M6809SetIRQ(INT32 vector, INT32 status) +{ + if (status == M6809_IRQSTATUS_NONE) { + m6809_set_irq_line(vector, 0); + } + + if (status == M6809_IRQSTATUS_ACK) { + m6809_set_irq_line(vector, 1); + } + + if (status == M6809_IRQSTATUS_AUTO) { + m6809_set_irq_line(vector, 1); + m6809_execute(0); + m6809_set_irq_line(vector, 0); + m6809_execute(0); + } +} + +INT32 M6809Run(INT32 cycles) +{ + cycles = m6809_execute(cycles); + + nM6809CyclesTotal += cycles; + + return cycles; +} + +void M6809RunEnd() +{ + +} + +INT32 M6809MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = m6809CPUContext[nActiveCPU].pMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + if (nType & M6809_READ) { + pMemMap[0 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6809_WRITE) { + pMemMap[0x100 + i] = pMemory + ((i - cStart) << 8); + } + if (nType & M6809_FETCH) { + pMemMap[0x200 + i] = pMemory + ((i - cStart) << 8); + } + } + return 0; + +} + +void M6809SetReadByteHandler(UINT8 (*pHandler)(UINT16)) +{ + m6809CPUContext[nActiveCPU].ReadByte = pHandler; +} + +void M6809SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)) +{ + m6809CPUContext[nActiveCPU].WriteByte = pHandler; +} + +void M6809SetReadOpHandler(UINT8 (*pHandler)(UINT16)) +{ + m6809CPUContext[nActiveCPU].ReadOp = pHandler; +} + +void M6809SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)) +{ + m6809CPUContext[nActiveCPU].ReadOpArg = pHandler; +} + +UINT8 M6809ReadByte(UINT16 Address) +{ + // check mem map + UINT8 * pr = m6809CPUContext[nActiveCPU].pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (m6809CPUContext[nActiveCPU].ReadByte != NULL) { + return m6809CPUContext[nActiveCPU].ReadByte(Address); + } + + return 0; +} + +void M6809WriteByte(UINT16 Address, UINT8 Data) +{ + // check mem map + UINT8 * pr = m6809CPUContext[nActiveCPU].pMemMap[0x100 | (Address >> 8)]; + if (pr != NULL) { + pr[Address & 0xff] = Data; + return; + } + + // check handler + if (m6809CPUContext[nActiveCPU].WriteByte != NULL) { + m6809CPUContext[nActiveCPU].WriteByte(Address, Data); + return; + } +} + +UINT8 M6809ReadOp(UINT16 Address) +{ + // check mem map + UINT8 * pr = m6809CPUContext[nActiveCPU].pMemMap[0x200 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (m6809CPUContext[nActiveCPU].ReadOp != NULL) { + return m6809CPUContext[nActiveCPU].ReadOp(Address); + } + + return 0; +} + +UINT8 M6809ReadOpArg(UINT16 Address) +{ + // check mem map + UINT8 * pr = m6809CPUContext[nActiveCPU].pMemMap[0x000 | (Address >> 8)]; + if (pr != NULL) { + return pr[Address & 0xff]; + } + + // check handler + if (m6809CPUContext[nActiveCPU].ReadOpArg != NULL) { + return m6809CPUContext[nActiveCPU].ReadOpArg(Address); + } + + return 0; +} + +void M6809WriteRom(UINT16 Address, UINT8 Data) +{ + UINT8 * pr = m6809CPUContext[nActiveCPU].pMemMap[0x000 | (Address >> 8)]; + UINT8 * pw = m6809CPUContext[nActiveCPU].pMemMap[0x100 | (Address >> 8)]; + UINT8 * pf = m6809CPUContext[nActiveCPU].pMemMap[0x200 | (Address >> 8)]; + + if (pr != NULL) { + pr[Address & 0xff] = Data; + } + + if (pw != NULL) { + pw[Address & 0xff] = Data; + } + + if (pf != NULL) { + pf[Address & 0xff] = Data; + } + + // check handler + if (m6809CPUContext[nActiveCPU].WriteByte != NULL) { + m6809CPUContext[nActiveCPU].WriteByte(Address, Data); + return; + } +} + +INT32 M6809Scan(INT32 nAction) +{ + struct BurnArea ba; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + for (INT32 i = 0; i < nM6809Count; i++) { + + M6809Ext *ptr = &m6809CPUContext[i]; + + INT32 (*Callback)(INT32 irqline); + + Callback = ptr->reg.irq_callback; + + char szName[] = "M6809 #n"; + szName[7] = '0' + i; + + ba.Data = &m6809CPUContext[i].reg; + ba.nLen = sizeof(m6809CPUContext[i].reg); + ba.szName = szName; + BurnAcb(&ba); + + // necessary? + SCAN_VAR(ptr->nCyclesTotal); + SCAN_VAR(ptr->nCyclesSegment); + SCAN_VAR(ptr->nCyclesLeft); + + ptr->reg.irq_callback = Callback; + } + + return 0; +} diff --git a/src/cpu/m6809_intf.h b/src/cpu/m6809_intf.h new file mode 100644 index 00000000..ad29f524 --- /dev/null +++ b/src/cpu/m6809_intf.h @@ -0,0 +1,61 @@ +#include "m6809.h" + +typedef UINT8 (*pReadByteHandler)(UINT16 a); +typedef void (*pWriteByteHandler)(UINT16 a, UINT8 d); +typedef UINT8 (*pReadOpHandler)(UINT16 a); +typedef UINT8 (*pReadOpArgHandler)(UINT16 a); + +struct M6809Ext { + + m6809_Regs reg; + + UINT8* pMemMap[0x100 * 3]; + + pReadByteHandler ReadByte; + pWriteByteHandler WriteByte; + pReadOpHandler ReadOp; + pReadOpArgHandler ReadOpArg; + + INT32 nCyclesTotal; + INT32 nCyclesSegment; + INT32 nCyclesLeft; +}; + +#define M6809_IRQSTATUS_NONE 0 +#define M6809_IRQSTATUS_ACK 1 +#define M6809_IRQSTATUS_AUTO 2 + +#define M6809_READ 1 +#define M6809_WRITE 2 +#define M6809_FETCH 4 + +#define M6809_RAM (M6809_READ | M6809_WRITE | M6809_FETCH) +#define M6809_ROM (M6809_READ | M6809_FETCH) + +extern INT32 nM6809Count; + +extern INT32 nM6809CyclesTotal; + +void M6809Reset(); +void M6809NewFrame(); +INT32 M6809Init(INT32 num); +void M6809Exit(); +void M6809Open(INT32 num); +void M6809Close(); +INT32 M6809GetActive(); +void M6809SetIRQ(INT32 vector, INT32 status); +INT32 M6809Run(INT32 cycles); +void M6809RunEnd(); +INT32 M6809MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType); +void M6809SetReadByteHandler(UINT8 (*pHandler)(UINT16)); +void M6809SetWriteByteHandler(void (*pHandler)(UINT16, UINT8)); +void M6809SetReadOpHandler(UINT8 (*pHandler)(UINT16)); +void M6809SetReadOpArgHandler(UINT8 (*pHandler)(UINT16)); +INT32 M6809Scan(INT32 nAction); + +void M6809WriteRom(UINT16 Address, UINT8 Data); + +inline static INT32 M6809TotalCycles() +{ + return nM6809CyclesTotal; +} diff --git a/src/cpu/m68k/m68k.h b/src/cpu/m68k/m68k.h new file mode 100644 index 00000000..983de068 --- /dev/null +++ b/src/cpu/m68k/m68k.h @@ -0,0 +1,365 @@ +#ifndef M68K__HEADER +#define M68K__HEADER + +#ifdef __cplusplus + extern "C" { +#endif + +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ + +/* ======================================================================== */ + +/* There are 7 levels of interrupt to the 68K. + * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). + */ +#define M68K_IRQ_NONE 0 +#define M68K_IRQ_1 1 +#define M68K_IRQ_2 2 +#define M68K_IRQ_3 3 +#define M68K_IRQ_4 4 +#define M68K_IRQ_5 5 +#define M68K_IRQ_6 6 +#define M68K_IRQ_7 7 + + +/* Special interrupt acknowledge values. + * Use these as special returns from the interrupt acknowledge callback + * (specified later in this header). + */ + +/* Causes an interrupt autovector (0x18 + interrupt level) to be taken. + * This happens in a real 68K if VPA or AVEC is asserted during an interrupt + * acknowledge cycle instead of DTACK. + */ +#define M68K_INT_ACK_AUTOVECTOR 0xffffffff + +/* Causes the spurious interrupt vector (0x18) to be taken + * This happens in a real 68K if BERR is asserted during the interrupt + * acknowledge cycle (i.e. no devices responded to the acknowledge). + */ +#define M68K_INT_ACK_SPURIOUS 0xfffffffe + + +/* CPU types for use in m68k_set_cpu_type() */ +enum +{ + M68K_CPU_TYPE_INVALID, + M68K_CPU_TYPE_68000, + M68K_CPU_TYPE_68008, + M68K_CPU_TYPE_68010, + M68K_CPU_TYPE_68EC020, + M68K_CPU_TYPE_68020, + M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */ + M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */ +}; + +/* Registers used by m68k_get_reg() and m68k_set_reg() */ +typedef enum +{ + /* Real registers */ + M68K_REG_D0, /* Data registers */ + M68K_REG_D1, + M68K_REG_D2, + M68K_REG_D3, + M68K_REG_D4, + M68K_REG_D5, + M68K_REG_D6, + M68K_REG_D7, + M68K_REG_A0, /* Address registers */ + M68K_REG_A1, + M68K_REG_A2, + M68K_REG_A3, + M68K_REG_A4, + M68K_REG_A5, + M68K_REG_A6, + M68K_REG_A7, + M68K_REG_PC, /* Program Counter */ + M68K_REG_SR, /* Status Register */ + M68K_REG_SP, /* The current Stack Pointer (located in A7) */ + M68K_REG_USP, /* User Stack Pointer */ + M68K_REG_ISP, /* Interrupt Stack Pointer */ + M68K_REG_MSP, /* Master Stack Pointer */ + M68K_REG_SFC, /* Source Function Code */ + M68K_REG_DFC, /* Destination Function Code */ + M68K_REG_VBR, /* Vector Base Register */ + M68K_REG_CACR, /* Cache Control Register */ + M68K_REG_CAAR, /* Cache Address Register */ + + /* Assumed registers */ + /* These are cheat registers which emulate the 1-longword prefetch + * present in the 68000 and 68010. + */ + M68K_REG_PREF_ADDR, /* Last prefetch address */ + M68K_REG_PREF_DATA, /* Last prefetch data */ + + /* Convenience registers */ + M68K_REG_PPC, /* Previous value in the program counter */ + M68K_REG_IR, /* Instruction register */ + M68K_REG_CPU_TYPE /* Type of CPU being run */ +} m68k_register_t; + +/* ======================================================================== */ +/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ +/* ======================================================================== */ + +/* You will have to implement these functions */ + +/* read/write functions called by the CPU to access memory. + * while values used are 32 bits, only the appropriate number + * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits + * of value should be written to memory). + * + * NOTE: I have separated the immediate and PC-relative memory fetches + * from the other memory fetches because some systems require + * differentiation between PROGRAM and DATA fetches (usually + * for security setups such as encryption). + * This separation can either be achieved by setting + * M68K_SEPARATE_READS in m68kconf.h and defining + * the read functions, or by setting M68K_EMULATE_FC and + * making a function code callback function. + * Using the callback offers better emulation coverage + * because you can also monitor whether the CPU is in SYSTEM or + * USER mode, but it is also slower. + */ + +/* Read from anywhere */ +unsigned int m68k_read_memory_8(unsigned int address); +unsigned int m68k_read_memory_16(unsigned int address); +unsigned int m68k_read_memory_32(unsigned int address); + +/* Read data immediately following the PC */ +unsigned int m68k_read_immediate_16(unsigned int address); +unsigned int m68k_read_immediate_32(unsigned int address); + +/* Read data relative to the PC */ +unsigned int m68k_read_pcrelative_8(unsigned int address); +unsigned int m68k_read_pcrelative_16(unsigned int address); +unsigned int m68k_read_pcrelative_32(unsigned int address); + +/* Memory access for the disassembler */ +unsigned int m68k_read_disassembler_8 (unsigned int address); +unsigned int m68k_read_disassembler_16 (unsigned int address); +unsigned int m68k_read_disassembler_32 (unsigned int address); + +/* Write to anywhere */ +void m68k_write_memory_8(unsigned int address, unsigned int value); +void m68k_write_memory_16(unsigned int address, unsigned int value); +void m68k_write_memory_32(unsigned int address, unsigned int value); + +/* Special call to simulate undocumented 68k behavior when move.l with a + * predecrement destination mode is executed. + * To simulate real 68k behavior, first write the high word to + * [address+2], and then write the low word to [address]. + * + * Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h. + */ +void m68k_write_memory_32_pd(unsigned int address, unsigned int value); + + + +/* ======================================================================== */ +/* ============================== CALLBACKS =============================== */ +/* ======================================================================== */ + +/* These functions allow you to set callbacks to the host when specific events + * occur. Note that you must enable the corresponding value in m68kconf.h + * in order for these to do anything useful. + * Note: I have defined default callbacks which are used if you have enabled + * the corresponding #define in m68kconf.h but either haven't assigned a + * callback or have assigned a callback of NULL. + */ + +/* Set the callback for an interrupt acknowledge. + * You must enable M68K_EMULATE_INT_ACK in m68kconf.h. + * The CPU will call the callback with the interrupt level being acknowledged. + * The host program must return either a vector from 0x02-0xff, or one of the + * special interrupt acknowledge values specified earlier in this header. + * If this is not implemented, the CPU will always assume an autovectored + * interrupt, and will automatically clear the interrupt request when it + * services the interrupt. + * Default behavior: return M68K_INT_ACK_AUTOVECTOR. + */ +void m68k_set_int_ack_callback(int (*callback)(int int_level)); + + +/* Set the callback for a breakpoint acknowledge (68010+). + * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h. + * The CPU will call the callback with whatever was in the data field of the + * BKPT instruction for 68020+, or 0 for 68010. + * Default behavior: do nothing. + */ +void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)); + + +/* Set the callback for the RESET instruction. + * You must enable M68K_EMULATE_RESET in m68kconf.h. + * The CPU calls this callback every time it encounters a RESET instruction. + * Default behavior: do nothing. + */ +void m68k_set_reset_instr_callback(void (*callback)(void)); + + +/* Set the callback for the CMPI.L #v, Dn instruction. + * You must enable M68K_CMPILD_HAS_CALLBACK in m68kconf.h. + * The CPU calls this callback every time it encounters a CMPI.L #v, Dn instruction. + * Default behavior: do nothing. + */ +void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int val, int reg)); + + +/* Set the callback for the RTE instruction. + * You must enable M68K_RTE_HAS_CALLBACK in m68kconf.h. + * The CPU calls this callback every time it encounters a RTE instruction. + * Default behavior: do nothing. + */ +void m68k_set_rte_instr_callback(void (*callback)(void)); + + +/* Set the callback for informing of a large PC change. + * You must enable M68K_MONITOR_PC in m68kconf.h. + * The CPU calls this callback with the new PC value every time the PC changes + * by a large value (currently set for changes by longwords). + * Default behavior: do nothing. + */ +void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)); + + +/* Set the callback for CPU function code changes. + * You must enable M68K_EMULATE_FC in m68kconf.h. + * The CPU calls this callback with the function code before every memory + * access to set the CPU's function code according to what kind of memory + * access it is (supervisor/user, program/data and such). + * Default behavior: do nothing. + */ +void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)); + + +/* Set a callback for the instruction cycle of the CPU. + * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h. + * The CPU calls this callback just before fetching the opcode in the + * instruction cycle. + * Default behavior: do nothing. + */ +void m68k_set_instr_hook_callback(void (*callback)(void)); + + + +/* ======================================================================== */ +/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ +/* ======================================================================== */ + +/* Use this function to set the CPU type you want to emulate. + * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68008, + * M68K_CPU_TYPE_68010, M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020. + */ +void m68k_set_cpu_type(unsigned int cpu_type); + +/* Do whatever initialisations the core requires. Should be called + * at least once at init time. + */ +void m68k_init(void); + +/* Pulse the RESET pin on the CPU. + * You *MUST* reset the CPU at least once to initialize the emulation + * Note: If you didn't call m68k_set_cpu_type() before resetting + * the CPU for the first time, the CPU will be set to + * M68K_CPU_TYPE_68000. + */ +void m68k_pulse_reset(void); + +/* execute num_cycles worth of instructions. returns number of cycles used */ +int m68k_execute(int num_cycles); + +/* These functions let you read/write/modify the number of cycles left to run + * while m68k_execute() is running. + * These are useful if the 68k accesses a memory-mapped port on another device + * that requires immediate processing by another CPU. + */ +int m68k_cycles_run(void); /* Number of cycles run so far */ +int m68k_cycles_remaining(void); /* Number of cycles left */ +void m68k_modify_timeslice(int cycles); /* Modify cycles left */ +void m68k_end_timeslice(void); /* End timeslice now */ + +/* Set the IPL0-IPL2 pins on the CPU (IRQ). + * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). + * Setting IRQ to 0 will clear an interrupt request. + */ +void m68k_set_irq(unsigned int int_level); + + +/* Halt the CPU as if you pulsed the HALT pin. */ +void m68k_pulse_halt(void); + + +/* Context switching to allow multiple CPUs */ + +/* Get the size of the cpu context in bytes */ +unsigned int m68k_context_size(void); + +/* Get a cpu context */ +unsigned int m68k_get_context(void* dst); + +/* set the current cpu context */ +void m68k_set_context(void* dst); + +/* Register the CPU state information */ +void m68k_state_register(const char *type); + + +/* Peek at the internals of a CPU context. This can either be a context + * retrieved using m68k_get_context() or the currently running context. + * If context is NULL, the currently running CPU context will be used. + */ +unsigned int m68k_get_reg(void* context, m68k_register_t reg); + +/* Poke values into the internals of the currently running CPU context */ +void m68k_set_reg(m68k_register_t reg, unsigned int value); + +/* Check if an instruction is valid for the specified CPU type */ +unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type); + +/* Disassemble 1 instruction using the epecified CPU type at pc. Stores + * disassembly in str_buff and returns the size of the instruction in bytes. + */ +unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type); + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +/* Import the configuration for this build */ +#include "m68kconf.h" + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#ifdef __cplusplus + } +#endif + +#endif /* M68K__HEADER */ diff --git a/src/cpu/m68k/m68k_in.c b/src/cpu/m68k/m68k_in.c new file mode 100644 index 00000000..bdd4fd12 --- /dev/null +++ b/src/cpu/m68k/m68k_in.c @@ -0,0 +1,10459 @@ +/* +must fix: + callm + chk +*/ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + +/* Special thanks to Bart Trzynadlowski for his insight into the + * undocumented features of this chip: + * + * http://dynarec.com/~bart/files/68knotes.txt + */ + + +/* Input file for m68kmake + * ----------------------- + * + * All sections begin with 80 X's in a row followed by an end-of-line + * sequence. + * After this, m68kmake will expect to find one of the following section + * identifiers: + * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes + * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes + * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable + * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable + * M68KMAKE_TABLE_BODY - the table itself + * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation + * + * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and + * M68KMAKE_TABLE_BODY must be second last in the file. + * + * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler + * primitives themselves. Each opcode handler begins with: + * M68KMAKE_OP(A, B, C, D) + * + * where A is the opcode handler name, B is the size of the operation, + * C denotes any special processing mode, and D denotes a specific + * addressing mode. + * For C and D where nothing is specified, use "." + * + * Example: + * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA + * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7 + * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing + * + * All opcode handler primitives end with a closing curly brace "}" at column 1 + * + * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler, + * and do not put a closing curly brace at column 1 unless it is + * marking the end of the handler! + * + * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx, + * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple + * opcode handlers to handle variations in the opcode handler. + * Note: M68KMAKE_CC will only be interpreted in condition code opcodes. + * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only + * be interpreted on instructions where the corresponding table entry + * specifies multiple effective addressing modes. + * Example: + * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 + * + * This table entry says that the clr.l opcde has 7 variations (A+-DXWL). + * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for + * 68000, 6 cycles for 68010, and 4 cycles for 68020. + */ + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_HEADER + +#ifndef M68KOPS__HEADER +#define M68KOPS__HEADER + +/* ======================================================================== */ +/* ============================ OPCODE HANDLERS =========================== */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_FOOTER + + +/* Build the opcode handler table */ +void m68ki_build_opcode_table(void); + +extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +extern unsigned char m68ki_cycles[][0x10000]; + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KOPS__HEADER */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_HEADER + +/* ======================================================================== */ +/* ========================= OPCODE TABLE BUILDER ========================= */ +/* ======================================================================== */ + +#include "m68kops.h" + +#define NUM_CPU_TYPES 3 + +void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ + +/* This is used to generate the opcode handler jump table */ +typedef struct +{ + void (*opcode_handler)(void); /* handler function */ + unsigned int mask; /* mask on opcode */ + unsigned int match; /* what to match after masking */ + unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ +} opcode_handler_struct; + + +/* Opcode handler table */ +static opcode_handler_struct m68k_opcode_handler_table[] = +{ +/* function mask match 000 010 020 */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_FOOTER + + {0, 0, 0, {0, 0, 0}} +}; + + +/* Build the opcode handler jump table */ +void m68ki_build_opcode_table(void) +{ + opcode_handler_struct *ostruct; + int instr; + int i; + int j; + int k; + + for(i = 0; i < 0x10000; i++) + { + /* default to illegal */ + m68ki_instruction_jump_table[i] = m68k_op_illegal; + for(k=0;kmask != 0xff00) + { + for(i = 0;i < 0x10000;i++) + { + if((i & ostruct->mask) == ostruct->match) + { + m68ki_instruction_jump_table[i] = ostruct->opcode_handler; + for(k=0;kcycles[k]; + } + } + ostruct++; + } + while(ostruct->mask == 0xff00) + { + for(i = 0;i <= 0xff;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1f8) + { + for(i = 0;i < 8;i++) + { + for(j = 0;j < 8;j++) + { + instr = ostruct->match | (i << 9) | j; + m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; + for(k=0;kcycles[k]; + if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) + m68ki_cycles[0][instr] = m68ki_cycles[1][instr] = ostruct->cycles[k] + ((((j-1)&7)+1)<<1); + } + } + ostruct++; + } + while(ostruct->mask == 0xfff0) + { + for(i = 0;i <= 0x0f;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1ff) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; + for(k=0;kmatch | (i << 9)] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xfff8) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xffff) + { + m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; + for(k=0;kmatch] = ostruct->cycles[k]; + ostruct++; + } +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_HEADER + +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_FOOTER + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_BODY + +The following table is arranged as follows: + +name: Opcode mnemonic + +size: Operation size + +spec proc: Special processing mode: + .: normal + s: static operand + r: register operand + rr: register to register + mm: memory to memory + er: effective address to register + re: register to effective address + dd: data register to data register + da: data register to address register + aa: address register to address register + cr: control register to register + rc: register to control register + toc: to condition code register + tos: to status register + tou: to user stack pointer + frc: from condition code register + frs: from status register + fru: from user stack pointer + * for move.x, the special processing mode is a specific + destination effective addressing mode. + +spec ea: Specific effective addressing mode: + .: normal + i: immediate + d: data register + a: address register + ai: address register indirect + pi: address register indirect with postincrement + pd: address register indirect with predecrement + di: address register indirect with displacement + ix: address register indirect with index + aw: absolute word address + al: absolute long address + pcdi: program counter relative with displacement + pcix: program counter relative with index + a7: register specified in instruction is A7 + ax7: register field X of instruction is A7 + ay7: register field Y of instruction is A7 + axy7: register fields X and Y of instruction are A7 + +bit pattern: Pattern to recognize this opcode. "." means don't care. + +allowed ea: List of allowed addressing modes: + .: not present + A: address register indirect + +: ARI (address register indirect) with postincrement + -: ARI with predecrement + D: ARI with displacement + X: ARI with index + W: absolute word address + L: absolute long address + d: program counter indirect with displacement + x: program counter indirect with index + I: immediate +mode: CPU operating mode for each cpu type. U = user or supervisor, + S = supervisor only, "." = opcode not present. + +cpu cycles: Base number of cycles required to execute this opcode on the + specified CPU type. + Use "." if CPU does not have this opcode. + + + + spec spec allowed ea mode cpu cycles +name size proc ea bit pattern A+-DXWLdxI 0 1 2 000 010 020 comments +====== ==== ==== ==== ================ ========== = = = === === === ============= +M68KMAKE_TABLE_START +1010 0 . . 1010............ .......... U U U 4 4 4 +1111 0 . . 1111............ .......... U U U 4 4 4 +abcd 8 rr . 1100...100000... .......... U U U 6 6 4 +abcd 8 mm ax7 1100111100001... .......... U U U 18 18 16 +abcd 8 mm ay7 1100...100001111 .......... U U U 18 18 16 +abcd 8 mm axy7 1100111100001111 .......... U U U 18 18 16 +abcd 8 mm . 1100...100001... .......... U U U 18 18 16 +add 8 er d 1101...000000... .......... U U U 4 4 2 +add 8 er . 1101...000...... A+-DXWLdxI U U U 4 4 2 +add 16 er d 1101...001000... .......... U U U 4 4 2 +add 16 er a 1101...001001... .......... U U U 4 4 2 +add 16 er . 1101...001...... A+-DXWLdxI U U U 4 4 2 +add 32 er d 1101...010000... .......... U U U 6 6 2 +add 32 er a 1101...010001... .......... U U U 6 6 2 +add 32 er . 1101...010...... A+-DXWLdxI U U U 6 6 2 +add 8 re . 1101...100...... A+-DXWL... U U U 8 8 4 +add 16 re . 1101...101...... A+-DXWL... U U U 8 8 4 +add 32 re . 1101...110...... A+-DXWL... U U U 12 12 4 +adda 16 . d 1101...011000... .......... U U U 8 8 2 +adda 16 . a 1101...011001... .......... U U U 8 8 2 +adda 16 . . 1101...011...... A+-DXWLdxI U U U 8 8 2 +adda 32 . d 1101...111000... .......... U U U 6 6 2 +adda 32 . a 1101...111001... .......... U U U 6 6 2 +adda 32 . . 1101...111...... A+-DXWLdxI U U U 6 6 2 +addi 8 . d 0000011000000... .......... U U U 8 8 2 +addi 8 . . 0000011000...... A+-DXWL... U U U 12 12 4 +addi 16 . d 0000011001000... .......... U U U 8 8 2 +addi 16 . . 0000011001...... A+-DXWL... U U U 12 12 4 +addi 32 . d 0000011010000... .......... U U U 16 14 2 +addi 32 . . 0000011010...... A+-DXWL... U U U 20 20 4 +addq 8 . d 0101...000000... .......... U U U 4 4 2 +addq 8 . . 0101...000...... A+-DXWL... U U U 8 8 4 +addq 16 . d 0101...001000... .......... U U U 4 4 2 +addq 16 . a 0101...001001... .......... U U U 4 4 2 +addq 16 . . 0101...001...... A+-DXWL... U U U 8 8 4 +addq 32 . d 0101...010000... .......... U U U 8 8 2 +addq 32 . a 0101...010001... .......... U U U 8 8 2 +addq 32 . . 0101...010...... A+-DXWL... U U U 12 12 4 +addx 8 rr . 1101...100000... .......... U U U 4 4 2 +addx 16 rr . 1101...101000... .......... U U U 4 4 2 +addx 32 rr . 1101...110000... .......... U U U 8 6 2 +addx 8 mm ax7 1101111100001... .......... U U U 18 18 12 +addx 8 mm ay7 1101...100001111 .......... U U U 18 18 12 +addx 8 mm axy7 1101111100001111 .......... U U U 18 18 12 +addx 8 mm . 1101...100001... .......... U U U 18 18 12 +addx 16 mm . 1101...101001... .......... U U U 18 18 12 +addx 32 mm . 1101...110001... .......... U U U 30 30 12 +and 8 er d 1100...000000... .......... U U U 4 4 2 +and 8 er . 1100...000...... A+-DXWLdxI U U U 4 4 2 +and 16 er d 1100...001000... .......... U U U 4 4 2 +and 16 er . 1100...001...... A+-DXWLdxI U U U 4 4 2 +and 32 er d 1100...010000... .......... U U U 6 6 2 +and 32 er . 1100...010...... A+-DXWLdxI U U U 6 6 2 +and 8 re . 1100...100...... A+-DXWL... U U U 8 8 4 +and 16 re . 1100...101...... A+-DXWL... U U U 8 8 4 +and 32 re . 1100...110...... A+-DXWL... U U U 12 12 4 +andi 16 toc . 0000001000111100 .......... U U U 20 16 12 +andi 16 tos . 0000001001111100 .......... S S S 20 16 12 +andi 8 . d 0000001000000... .......... U U U 8 8 2 +andi 8 . . 0000001000...... A+-DXWL... U U U 12 12 4 +andi 16 . d 0000001001000... .......... U U U 8 8 2 +andi 16 . . 0000001001...... A+-DXWL... U U U 12 12 4 +andi 32 . d 0000001010000... .......... U U U 14 14 2 +andi 32 . . 0000001010...... A+-DXWL... U U U 20 20 4 +asr 8 s . 1110...000000... .......... U U U 6 6 6 +asr 16 s . 1110...001000... .......... U U U 6 6 6 +asr 32 s . 1110...010000... .......... U U U 8 8 6 +asr 8 r . 1110...000100... .......... U U U 6 6 6 +asr 16 r . 1110...001100... .......... U U U 6 6 6 +asr 32 r . 1110...010100... .......... U U U 8 8 6 +asr 16 . . 1110000011...... A+-DXWL... U U U 8 8 5 +asl 8 s . 1110...100000... .......... U U U 6 6 8 +asl 16 s . 1110...101000... .......... U U U 6 6 8 +asl 32 s . 1110...110000... .......... U U U 8 8 8 +asl 8 r . 1110...100100... .......... U U U 6 6 8 +asl 16 r . 1110...101100... .......... U U U 6 6 8 +asl 32 r . 1110...110100... .......... U U U 8 8 8 +asl 16 . . 1110000111...... A+-DXWL... U U U 8 8 6 +bcc 8 . . 0110............ .......... U U U 8 8 6 +bcc 16 . . 0110....00000000 .......... U U U 10 10 6 +bcc 32 . . 0110....11111111 .......... . . U . . 6 +bchg 8 r . 0000...101...... A+-DXWL... U U U 8 8 4 +bchg 32 r d 0000...101000... .......... U U U 8 8 4 +bchg 8 s . 0000100001...... A+-DXWL... U U U 12 12 4 +bchg 32 s d 0000100001000... .......... U U U 12 12 4 +bclr 8 r . 0000...110...... A+-DXWL... U U U 8 10 4 +bclr 32 r d 0000...110000... .......... U U U 10 10 4 +bclr 8 s . 0000100010...... A+-DXWL... U U U 12 12 4 +bclr 32 s d 0000100010000... .......... U U U 14 14 4 +bfchg 32 . d 1110101011000... .......... . . U . . 12 timing not quite correct +bfchg 32 . . 1110101011...... A..DXWL... . . U . . 20 +bfclr 32 . d 1110110011000... .......... . . U . . 12 +bfclr 32 . . 1110110011...... A..DXWL... . . U . . 20 +bfexts 32 . d 1110101111000... .......... . . U . . 8 +bfexts 32 . . 1110101111...... A..DXWLdx. . . U . . 15 +bfextu 32 . d 1110100111000... .......... . . U . . 8 +bfextu 32 . . 1110100111...... A..DXWLdx. . . U . . 15 +bfffo 32 . d 1110110111000... .......... . . U . . 18 +bfffo 32 . . 1110110111...... A..DXWLdx. . . U . . 28 +bfins 32 . d 1110111111000... .......... . . U . . 10 +bfins 32 . . 1110111111...... A..DXWL... . . U . . 17 +bfset 32 . d 1110111011000... .......... . . U . . 12 +bfset 32 . . 1110111011...... A..DXWL... . . U . . 20 +bftst 32 . d 1110100011000... .......... . . U . . 6 +bftst 32 . . 1110100011...... A..DXWLdx. . . U . . 13 +bkpt 0 . . 0100100001001... .......... . U U . 10 10 +bra 8 . . 01100000........ .......... U U U 10 10 10 +bra 16 . . 0110000000000000 .......... U U U 10 10 10 +bra 32 . . 0110000011111111 .......... U U U . . 10 +bset 32 r d 0000...111000... .......... U U U 8 8 4 +bset 8 r . 0000...111...... A+-DXWL... U U U 8 8 4 +bset 8 s . 0000100011...... A+-DXWL... U U U 12 12 4 +bset 32 s d 0000100011000... .......... U U U 12 12 4 +bsr 8 . . 01100001........ .......... U U U 18 18 7 +bsr 16 . . 0110000100000000 .......... U U U 18 18 7 +bsr 32 . . 0110000111111111 .......... . . U . . 7 +btst 8 r . 0000...100...... A+-DXWLdxI U U U 4 4 4 +btst 32 r d 0000...100000... .......... U U U 6 6 4 +btst 8 s . 0000100000...... A+-DXWLdx. U U U 8 8 4 +btst 32 s d 0000100000000... .......... U U U 10 10 4 +callm 32 . . 0000011011...... A..DXWLdx. . . U . . 60 not properly emulated +cas 8 . . 0000101011...... A+-DXWL... . . U . . 12 +cas 16 . . 0000110011...... A+-DXWL... . . U . . 12 +cas 32 . . 0000111011...... A+-DXWL... . . U . . 12 +cas2 16 . . 0000110011111100 .......... . . U . . 12 +cas2 32 . . 0000111011111100 .......... . . U . . 12 +chk 16 . d 0100...110000... .......... U U U 10 8 8 +chk 16 . . 0100...110...... A+-DXWLdxI U U U 10 8 8 +chk 32 . d 0100...100000... .......... . . U . . 8 +chk 32 . . 0100...100...... A+-DXWLdxI . . U . . 8 +chk2cmp2 8 . pcdi 0000000011111010 .......... . . U . . 23 +chk2cmp2 8 . pcix 0000000011111011 .......... . . U . . 23 +chk2cmp2 8 . . 0000000011...... A..DXWL... . . U . . 18 +chk2cmp2 16 . pcdi 0000001011111010 .......... . . U . . 23 +chk2cmp2 16 . pcix 0000001011111011 .......... . . U . . 23 +chk2cmp2 16 . . 0000001011...... A..DXWL... . . U . . 18 +chk2cmp2 32 . pcdi 0000010011111010 .......... . . U . . 23 +chk2cmp2 32 . pcix 0000010011111011 .......... . . U . . 23 +chk2cmp2 32 . . 0000010011...... A..DXWL... . . U . . 18 +clr 8 . d 0100001000000... .......... U U U 4 4 2 +clr 8 . . 0100001000...... A+-DXWL... U U U 8 4 4 +clr 16 . d 0100001001000... .......... U U U 4 4 2 +clr 16 . . 0100001001...... A+-DXWL... U U U 8 4 4 +clr 32 . d 0100001010000... .......... U U U 6 6 2 +clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 +cmp 8 . d 1011...000000... .......... U U U 4 4 2 +cmp 8 . . 1011...000...... A+-DXWLdxI U U U 4 4 2 +cmp 16 . d 1011...001000... .......... U U U 4 4 2 +cmp 16 . a 1011...001001... .......... U U U 4 4 2 +cmp 16 . . 1011...001...... A+-DXWLdxI U U U 4 4 2 +cmp 32 . d 1011...010000... .......... U U U 6 6 2 +cmp 32 . a 1011...010001... .......... U U U 6 6 2 +cmp 32 . . 1011...010...... A+-DXWLdxI U U U 6 6 2 +cmpa 16 . d 1011...011000... .......... U U U 6 6 4 +cmpa 16 . a 1011...011001... .......... U U U 6 6 4 +cmpa 16 . . 1011...011...... A+-DXWLdxI U U U 6 6 4 +cmpa 32 . d 1011...111000... .......... U U U 6 6 4 +cmpa 32 . a 1011...111001... .......... U U U 6 6 4 +cmpa 32 . . 1011...111...... A+-DXWLdxI U U U 6 6 4 +cmpi 8 . d 0000110000000... .......... U U U 8 8 2 +cmpi 8 . . 0000110000...... A+-DXWL... U U U 8 8 2 +cmpi 8 . pcdi 0000110000111010 .......... . . U . . 7 +cmpi 8 . pcix 0000110000111011 .......... . . U . . 9 +cmpi 16 . d 0000110001000... .......... U U U 8 8 2 +cmpi 16 . . 0000110001...... A+-DXWL... U U U 8 8 2 +cmpi 16 . pcdi 0000110001111010 .......... . . U . . 7 +cmpi 16 . pcix 0000110001111011 .......... . . U . . 9 +cmpi 32 . d 0000110010000... .......... U U U 14 12 2 +cmpi 32 . . 0000110010...... A+-DXWL... U U U 12 12 2 +cmpi 32 . pcdi 0000110010111010 .......... . . U . . 7 +cmpi 32 . pcix 0000110010111011 .......... . . U . . 9 +cmpm 8 . ax7 1011111100001... .......... U U U 12 12 9 +cmpm 8 . ay7 1011...100001111 .......... U U U 12 12 9 +cmpm 8 . axy7 1011111100001111 .......... U U U 12 12 9 +cmpm 8 . . 1011...100001... .......... U U U 12 12 9 +cmpm 16 . . 1011...101001... .......... U U U 12 12 9 +cmpm 32 . . 1011...110001... .......... U U U 20 20 9 +cpbcc 32 . . 1111...01....... .......... . . U . . 4 unemulated +cpdbcc 32 . . 1111...001001... .......... . . U . . 4 unemulated +cpgen 32 . . 1111...000...... .......... . . U . . 4 unemulated +cpscc 32 . . 1111...001...... .......... . . U . . 4 unemulated +cptrapcc 32 . . 1111...001111... .......... . . U . . 4 unemulated +dbt 16 . . 0101000011001... .......... U U U 12 12 6 +dbf 16 . . 0101000111001... .......... U U U 14 14 6 +dbcc 16 . . 0101....11001... .......... U U U 12 12 6 +divs 16 . d 1000...111000... .......... U U U 158 122 56 +divs 16 . . 1000...111...... A+-DXWLdxI U U U 158 122 56 +divu 16 . d 1000...011000... .......... U U U 140 108 44 +divu 16 . . 1000...011...... A+-DXWLdxI U U U 140 108 44 +divl 32 . d 0100110001000... .......... . . U . . 84 +divl 32 . . 0100110001...... A+-DXWLdxI . . U . . 84 +eor 8 . d 1011...100000... .......... U U U 4 4 2 +eor 8 . . 1011...100...... A+-DXWL... U U U 8 8 4 +eor 16 . d 1011...101000... .......... U U U 4 4 2 +eor 16 . . 1011...101...... A+-DXWL... U U U 8 8 4 +eor 32 . d 1011...110000... .......... U U U 8 6 2 +eor 32 . . 1011...110...... A+-DXWL... U U U 12 12 4 +eori 16 toc . 0000101000111100 .......... U U U 20 16 12 +eori 16 tos . 0000101001111100 .......... S S S 20 16 12 +eori 8 . d 0000101000000... .......... U U U 8 8 2 +eori 8 . . 0000101000...... A+-DXWL... U U U 12 12 4 +eori 16 . d 0000101001000... .......... U U U 8 8 2 +eori 16 . . 0000101001...... A+-DXWL... U U U 12 12 4 +eori 32 . d 0000101010000... .......... U U U 16 14 2 +eori 32 . . 0000101010...... A+-DXWL... U U U 20 20 4 +exg 32 dd . 1100...101000... .......... U U U 6 6 2 +exg 32 aa . 1100...101001... .......... U U U 6 6 2 +exg 32 da . 1100...110001... .......... U U U 6 6 2 +ext 16 . . 0100100010000... .......... U U U 4 4 4 +ext 32 . . 0100100011000... .......... U U U 4 4 4 +extb 32 . . 0100100111000... .......... . . U . . 4 +illegal 0 . . 0100101011111100 .......... U U U 4 4 4 +jmp 32 . . 0100111011...... A..DXWLdx. U U U 4 4 0 +jsr 32 . . 0100111010...... A..DXWLdx. U U U 12 12 0 +lea 32 . . 0100...111...... A..DXWLdx. U U U 0 0 2 +link 16 . a7 0100111001010111 .......... U U U 16 16 5 +link 16 . . 0100111001010... .......... U U U 16 16 5 +link 32 . a7 0100100000001111 .......... . . U . . 6 +link 32 . . 0100100000001... .......... . . U . . 6 +lsr 8 s . 1110...000001... .......... U U U 6 6 4 +lsr 16 s . 1110...001001... .......... U U U 6 6 4 +lsr 32 s . 1110...010001... .......... U U U 8 8 4 +lsr 8 r . 1110...000101... .......... U U U 6 6 6 +lsr 16 r . 1110...001101... .......... U U U 6 6 6 +lsr 32 r . 1110...010101... .......... U U U 8 8 6 +lsr 16 . . 1110001011...... A+-DXWL... U U U 8 8 5 +lsl 8 s . 1110...100001... .......... U U U 6 6 4 +lsl 16 s . 1110...101001... .......... U U U 6 6 4 +lsl 32 s . 1110...110001... .......... U U U 8 8 4 +lsl 8 r . 1110...100101... .......... U U U 6 6 6 +lsl 16 r . 1110...101101... .......... U U U 6 6 6 +lsl 32 r . 1110...110101... .......... U U U 8 8 6 +lsl 16 . . 1110001111...... A+-DXWL... U U U 8 8 5 +move 8 d d 0001...000000... .......... U U U 4 4 2 +move 8 d . 0001...000...... A+-DXWLdxI U U U 4 4 2 +move 8 ai d 0001...010000... .......... U U U 8 8 4 +move 8 ai . 0001...010...... A+-DXWLdxI U U U 8 8 4 +move 8 pi d 0001...011000... .......... U U U 8 8 4 +move 8 pi . 0001...011...... A+-DXWLdxI U U U 8 8 4 +move 8 pi7 d 0001111011000... .......... U U U 8 8 4 +move 8 pi7 . 0001111011...... A+-DXWLdxI U U U 8 8 4 +move 8 pd d 0001...100000... .......... U U U 8 8 5 +move 8 pd . 0001...100...... A+-DXWLdxI U U U 8 8 5 +move 8 pd7 d 0001111100000... .......... U U U 8 8 5 +move 8 pd7 . 0001111100...... A+-DXWLdxI U U U 8 8 5 +move 8 di d 0001...101000... .......... U U U 12 12 5 +move 8 di . 0001...101...... A+-DXWLdxI U U U 12 12 5 +move 8 ix d 0001...110000... .......... U U U 14 14 7 +move 8 ix . 0001...110...... A+-DXWLdxI U U U 14 14 7 +move 8 aw d 0001000111000... .......... U U U 12 12 4 +move 8 aw . 0001000111...... A+-DXWLdxI U U U 12 12 4 +move 8 al d 0001001111000... .......... U U U 16 16 6 +move 8 al . 0001001111...... A+-DXWLdxI U U U 16 16 6 +move 16 d d 0011...000000... .......... U U U 4 4 2 +move 16 d a 0011...000001... .......... U U U 4 4 2 +move 16 d . 0011...000...... A+-DXWLdxI U U U 4 4 2 +move 16 ai d 0011...010000... .......... U U U 8 8 4 +move 16 ai a 0011...010001... .......... U U U 8 8 4 +move 16 ai . 0011...010...... A+-DXWLdxI U U U 8 8 4 +move 16 pi d 0011...011000... .......... U U U 8 8 4 +move 16 pi a 0011...011001... .......... U U U 8 8 4 +move 16 pi . 0011...011...... A+-DXWLdxI U U U 8 8 4 +move 16 pd d 0011...100000... .......... U U U 8 8 5 +move 16 pd a 0011...100001... .......... U U U 8 8 5 +move 16 pd . 0011...100...... A+-DXWLdxI U U U 8 8 5 +move 16 di d 0011...101000... .......... U U U 12 12 5 +move 16 di a 0011...101001... .......... U U U 12 12 5 +move 16 di . 0011...101...... A+-DXWLdxI U U U 12 12 5 +move 16 ix d 0011...110000... .......... U U U 14 14 7 +move 16 ix a 0011...110001... .......... U U U 14 14 7 +move 16 ix . 0011...110...... A+-DXWLdxI U U U 14 14 7 +move 16 aw d 0011000111000... .......... U U U 12 12 4 +move 16 aw a 0011000111001... .......... U U U 12 12 4 +move 16 aw . 0011000111...... A+-DXWLdxI U U U 12 12 4 +move 16 al d 0011001111000... .......... U U U 16 16 6 +move 16 al a 0011001111001... .......... U U U 16 16 6 +move 16 al . 0011001111...... A+-DXWLdxI U U U 16 16 6 +move 32 d d 0010...000000... .......... U U U 4 4 2 +move 32 d a 0010...000001... .......... U U U 4 4 2 +move 32 d . 0010...000...... A+-DXWLdxI U U U 4 4 2 +move 32 ai d 0010...010000... .......... U U U 12 12 4 +move 32 ai a 0010...010001... .......... U U U 12 12 4 +move 32 ai . 0010...010...... A+-DXWLdxI U U U 12 12 4 +move 32 pi d 0010...011000... .......... U U U 12 12 4 +move 32 pi a 0010...011001... .......... U U U 12 12 4 +move 32 pi . 0010...011...... A+-DXWLdxI U U U 12 12 4 +move 32 pd d 0010...100000... .......... U U U 12 14 5 +move 32 pd a 0010...100001... .......... U U U 12 14 5 +move 32 pd . 0010...100...... A+-DXWLdxI U U U 12 14 5 +move 32 di d 0010...101000... .......... U U U 16 16 5 +move 32 di a 0010...101001... .......... U U U 16 16 5 +move 32 di . 0010...101...... A+-DXWLdxI U U U 16 16 5 +move 32 ix d 0010...110000... .......... U U U 18 18 7 +move 32 ix a 0010...110001... .......... U U U 18 18 7 +move 32 ix . 0010...110...... A+-DXWLdxI U U U 18 18 7 +move 32 aw d 0010000111000... .......... U U U 16 16 4 +move 32 aw a 0010000111001... .......... U U U 16 16 4 +move 32 aw . 0010000111...... A+-DXWLdxI U U U 16 16 4 +move 32 al d 0010001111000... .......... U U U 20 20 6 +move 32 al a 0010001111001... .......... U U U 20 20 6 +move 32 al . 0010001111...... A+-DXWLdxI U U U 20 20 6 +movea 16 . d 0011...001000... .......... U U U 4 4 2 +movea 16 . a 0011...001001... .......... U U U 4 4 2 +movea 16 . . 0011...001...... A+-DXWLdxI U U U 4 4 2 +movea 32 . d 0010...001000... .......... U U U 4 4 2 +movea 32 . a 0010...001001... .......... U U U 4 4 2 +movea 32 . . 0010...001...... A+-DXWLdxI U U U 4 4 2 +move 16 frc d 0100001011000... .......... . U U . 4 4 +move 16 frc . 0100001011...... A+-DXWL... . U U . 8 4 +move 16 toc d 0100010011000... .......... U U U 12 12 4 +move 16 toc . 0100010011...... A+-DXWLdxI U U U 12 12 4 +move 16 frs d 0100000011000... .......... U S S 6 4 8 U only for 000 +move 16 frs . 0100000011...... A+-DXWL... U S S 8 8 8 U only for 000 +move 16 tos d 0100011011000... .......... S S S 12 12 8 +move 16 tos . 0100011011...... A+-DXWLdxI S S S 12 12 8 +move 32 fru . 0100111001101... .......... S S S 4 6 2 +move 32 tou . 0100111001100... .......... S S S 4 6 2 +movec 32 cr . 0100111001111010 .......... . S S . 12 6 +movec 32 rc . 0100111001111011 .......... . S S . 10 12 +movem 16 re pd 0100100010100... .......... U U U 8 8 4 +movem 16 re . 0100100010...... A..DXWL... U U U 8 8 4 +movem 32 re pd 0100100011100... .......... U U U 8 8 4 +movem 32 re . 0100100011...... A..DXWL... U U U 8 8 4 +movem 16 er pi 0100110010011... .......... U U U 12 12 8 +movem 16 er pcdi 0100110010111010 .......... U U U 16 16 9 +movem 16 er pcix 0100110010111011 .......... U U U 18 18 11 +movem 16 er . 0100110010...... A..DXWL... U U U 12 12 8 +movem 32 er pi 0100110011011... .......... U U U 12 12 8 +movem 32 er pcdi 0100110011111010 .......... U U U 16 16 9 +movem 32 er pcix 0100110011111011 .......... U U U 18 18 11 +movem 32 er . 0100110011...... A..DXWL... U U U 12 12 8 +movep 16 er . 0000...100001... .......... U U U 16 16 12 +movep 32 er . 0000...101001... .......... U U U 24 24 18 +movep 16 re . 0000...110001... .......... U U U 16 16 11 +movep 32 re . 0000...111001... .......... U U U 24 24 17 +moveq 32 . . 0111...0........ .......... U U U 4 4 2 +moves 8 . . 0000111000...... A+-DXWL... . S S . 14 5 +moves 16 . . 0000111001...... A+-DXWL... . S S . 14 5 +moves 32 . . 0000111010...... A+-DXWL... . S S . 16 5 +muls 16 . d 1100...111000... .......... U U U 54 32 27 +muls 16 . . 1100...111...... A+-DXWLdxI U U U 54 32 27 +mulu 16 . d 1100...011000... .......... U U U 54 30 27 +mulu 16 . . 1100...011...... A+-DXWLdxI U U U 54 30 27 +mull 32 . d 0100110000000... .......... . . U . . 43 +mull 32 . . 0100110000...... A+-DXWLdxI . . U . . 43 +nbcd 8 . d 0100100000000... .......... U U U 6 6 6 +nbcd 8 . . 0100100000...... A+-DXWL... U U U 8 8 6 +neg 8 . d 0100010000000... .......... U U U 4 4 2 +neg 8 . . 0100010000...... A+-DXWL... U U U 8 8 4 +neg 16 . d 0100010001000... .......... U U U 4 4 2 +neg 16 . . 0100010001...... A+-DXWL... U U U 8 8 4 +neg 32 . d 0100010010000... .......... U U U 6 6 2 +neg 32 . . 0100010010...... A+-DXWL... U U U 12 12 4 +negx 8 . d 0100000000000... .......... U U U 4 4 2 +negx 8 . . 0100000000...... A+-DXWL... U U U 8 8 4 +negx 16 . d 0100000001000... .......... U U U 4 4 2 +negx 16 . . 0100000001...... A+-DXWL... U U U 8 8 4 +negx 32 . d 0100000010000... .......... U U U 6 6 2 +negx 32 . . 0100000010...... A+-DXWL... U U U 12 12 4 +nop 0 . . 0100111001110001 .......... U U U 4 4 2 +not 8 . d 0100011000000... .......... U U U 4 4 2 +not 8 . . 0100011000...... A+-DXWL... U U U 8 8 4 +not 16 . d 0100011001000... .......... U U U 4 4 2 +not 16 . . 0100011001...... A+-DXWL... U U U 8 8 4 +not 32 . d 0100011010000... .......... U U U 6 6 2 +not 32 . . 0100011010...... A+-DXWL... U U U 12 12 4 +or 8 er d 1000...000000... .......... U U U 4 4 2 +or 8 er . 1000...000...... A+-DXWLdxI U U U 4 4 2 +or 16 er d 1000...001000... .......... U U U 4 4 2 +or 16 er . 1000...001...... A+-DXWLdxI U U U 4 4 2 +or 32 er d 1000...010000... .......... U U U 6 6 2 +or 32 er . 1000...010...... A+-DXWLdxI U U U 6 6 2 +or 8 re . 1000...100...... A+-DXWL... U U U 8 8 4 +or 16 re . 1000...101...... A+-DXWL... U U U 8 8 4 +or 32 re . 1000...110...... A+-DXWL... U U U 12 12 4 +ori 16 toc . 0000000000111100 .......... U U U 20 16 12 +ori 16 tos . 0000000001111100 .......... S S S 20 16 12 +ori 8 . d 0000000000000... .......... U U U 8 8 2 +ori 8 . . 0000000000...... A+-DXWL... U U U 12 12 4 +ori 16 . d 0000000001000... .......... U U U 8 8 2 +ori 16 . . 0000000001...... A+-DXWL... U U U 12 12 4 +ori 32 . d 0000000010000... .......... U U U 16 14 2 +ori 32 . . 0000000010...... A+-DXWL... U U U 20 20 4 +pack 16 rr . 1000...101000... .......... . . U . . 6 +pack 16 mm ax7 1000111101001... .......... . . U . . 13 +pack 16 mm ay7 1000...101001111 .......... . . U . . 13 +pack 16 mm axy7 1000111101001111 .......... . . U . . 13 +pack 16 mm . 1000...101001... .......... . . U . . 13 +pea 32 . . 0100100001...... A..DXWLdx. U U U 6 6 5 +reset 0 . . 0100111001110000 .......... S S S 0 0 0 +ror 8 s . 1110...000011... .......... U U U 6 6 8 +ror 16 s . 1110...001011... .......... U U U 6 6 8 +ror 32 s . 1110...010011... .......... U U U 8 8 8 +ror 8 r . 1110...000111... .......... U U U 6 6 8 +ror 16 r . 1110...001111... .......... U U U 6 6 8 +ror 32 r . 1110...010111... .......... U U U 8 8 8 +ror 16 . . 1110011011...... A+-DXWL... U U U 8 8 7 +rol 8 s . 1110...100011... .......... U U U 6 6 8 +rol 16 s . 1110...101011... .......... U U U 6 6 8 +rol 32 s . 1110...110011... .......... U U U 8 8 8 +rol 8 r . 1110...100111... .......... U U U 6 6 8 +rol 16 r . 1110...101111... .......... U U U 6 6 8 +rol 32 r . 1110...110111... .......... U U U 8 8 8 +rol 16 . . 1110011111...... A+-DXWL... U U U 8 8 7 +roxr 8 s . 1110...000010... .......... U U U 6 6 12 +roxr 16 s . 1110...001010... .......... U U U 6 6 12 +roxr 32 s . 1110...010010... .......... U U U 8 8 12 +roxr 8 r . 1110...000110... .......... U U U 6 6 12 +roxr 16 r . 1110...001110... .......... U U U 6 6 12 +roxr 32 r . 1110...010110... .......... U U U 8 8 12 +roxr 16 . . 1110010011...... A+-DXWL... U U U 8 8 5 +roxl 8 s . 1110...100010... .......... U U U 6 6 12 +roxl 16 s . 1110...101010... .......... U U U 6 6 12 +roxl 32 s . 1110...110010... .......... U U U 8 8 12 +roxl 8 r . 1110...100110... .......... U U U 6 6 12 +roxl 16 r . 1110...101110... .......... U U U 6 6 12 +roxl 32 r . 1110...110110... .......... U U U 8 8 12 +roxl 16 . . 1110010111...... A+-DXWL... U U U 8 8 5 +rtd 32 . . 0100111001110100 .......... . U U . 16 10 +rte 32 . . 0100111001110011 .......... S S S 20 24 20 bus fault not emulated +rtm 32 . . 000001101100.... .......... . . U . . 19 not properly emulated +rtr 32 . . 0100111001110111 .......... U U U 20 20 14 +rts 32 . . 0100111001110101 .......... U U U 16 16 10 +sbcd 8 rr . 1000...100000... .......... U U U 6 6 4 +sbcd 8 mm ax7 1000111100001... .......... U U U 18 18 16 +sbcd 8 mm ay7 1000...100001111 .......... U U U 18 18 16 +sbcd 8 mm axy7 1000111100001111 .......... U U U 18 18 16 +sbcd 8 mm . 1000...100001... .......... U U U 18 18 16 +st 8 . d 0101000011000... .......... U U U 6 4 4 +st 8 . . 0101000011...... A+-DXWL... U U U 8 8 6 +sf 8 . d 0101000111000... .......... U U U 4 4 4 +sf 8 . . 0101000111...... A+-DXWL... U U U 8 8 6 +scc 8 . d 0101....11000... .......... U U U 4 4 4 +scc 8 . . 0101....11...... A+-DXWL... U U U 8 8 6 +stop 0 . . 0100111001110010 .......... S S S 4 4 8 +sub 8 er d 1001...000000... .......... U U U 4 4 2 +sub 8 er . 1001...000...... A+-DXWLdxI U U U 4 4 2 +sub 16 er d 1001...001000... .......... U U U 4 4 2 +sub 16 er a 1001...001001... .......... U U U 4 4 2 +sub 16 er . 1001...001...... A+-DXWLdxI U U U 4 4 2 +sub 32 er d 1001...010000... .......... U U U 6 6 2 +sub 32 er a 1001...010001... .......... U U U 6 6 2 +sub 32 er . 1001...010...... A+-DXWLdxI U U U 6 6 2 +sub 8 re . 1001...100...... A+-DXWL... U U U 8 8 4 +sub 16 re . 1001...101...... A+-DXWL... U U U 8 8 4 +sub 32 re . 1001...110...... A+-DXWL... U U U 12 12 4 +suba 16 . d 1001...011000... .......... U U U 8 8 2 +suba 16 . a 1001...011001... .......... U U U 8 8 2 +suba 16 . . 1001...011...... A+-DXWLdxI U U U 8 8 2 +suba 32 . d 1001...111000... .......... U U U 6 6 2 +suba 32 . a 1001...111001... .......... U U U 6 6 2 +suba 32 . . 1001...111...... A+-DXWLdxI U U U 6 6 2 +subi 8 . d 0000010000000... .......... U U U 8 8 2 +subi 8 . . 0000010000...... A+-DXWL... U U U 12 12 4 +subi 16 . d 0000010001000... .......... U U U 8 8 2 +subi 16 . . 0000010001...... A+-DXWL... U U U 12 12 4 +subi 32 . d 0000010010000... .......... U U U 16 14 2 +subi 32 . . 0000010010...... A+-DXWL... U U U 20 20 4 +subq 8 . d 0101...100000... .......... U U U 4 4 2 +subq 8 . . 0101...100...... A+-DXWL... U U U 8 8 4 +subq 16 . d 0101...101000... .......... U U U 4 4 2 +subq 16 . a 0101...101001... .......... U U U 8 4 2 +subq 16 . . 0101...101...... A+-DXWL... U U U 8 8 4 +subq 32 . d 0101...110000... .......... U U U 8 8 2 +subq 32 . a 0101...110001... .......... U U U 8 8 2 +subq 32 . . 0101...110...... A+-DXWL... U U U 12 12 4 +subx 8 rr . 1001...100000... .......... U U U 4 4 2 +subx 16 rr . 1001...101000... .......... U U U 4 4 2 +subx 32 rr . 1001...110000... .......... U U U 8 6 2 +subx 8 mm ax7 1001111100001... .......... U U U 18 18 12 +subx 8 mm ay7 1001...100001111 .......... U U U 18 18 12 +subx 8 mm axy7 1001111100001111 .......... U U U 18 18 12 +subx 8 mm . 1001...100001... .......... U U U 18 18 12 +subx 16 mm . 1001...101001... .......... U U U 18 18 12 +subx 32 mm . 1001...110001... .......... U U U 30 30 12 +swap 32 . . 0100100001000... .......... U U U 4 4 4 +tas 8 . d 0100101011000... .......... U U U 4 4 4 +tas 8 . . 0100101011...... A+-DXWL... U U U 14 14 12 +trap 0 . . 010011100100.... .......... U U U 4 4 4 +trapt 0 . . 0101000011111100 .......... . . U . . 4 +trapt 16 . . 0101000011111010 .......... . . U . . 6 +trapt 32 . . 0101000011111011 .......... . . U . . 8 +trapf 0 . . 0101000111111100 .......... . . U . . 4 +trapf 16 . . 0101000111111010 .......... . . U . . 6 +trapf 32 . . 0101000111111011 .......... . . U . . 8 +trapcc 0 . . 0101....11111100 .......... . . U . . 4 +trapcc 16 . . 0101....11111010 .......... . . U . . 6 +trapcc 32 . . 0101....11111011 .......... . . U . . 8 +trapv 0 . . 0100111001110110 .......... U U U 4 4 4 +tst 8 . d 0100101000000... .......... U U U 4 4 2 +tst 8 . . 0100101000...... A+-DXWL... U U U 4 4 2 +tst 8 . pcdi 0100101000111010 .......... . . U . . 7 +tst 8 . pcix 0100101000111011 .......... . . U . . 9 +tst 8 . i 0100101000111100 .......... . . U . . 6 +tst 16 . d 0100101001000... .......... U U U 4 4 2 +tst 16 . a 0100101001001... .......... . . U . . 2 +tst 16 . . 0100101001...... A+-DXWL... U U U 4 4 2 +tst 16 . pcdi 0100101001111010 .......... . . U . . 7 +tst 16 . pcix 0100101001111011 .......... . . U . . 9 +tst 16 . i 0100101001111100 .......... . . U . . 6 +tst 32 . d 0100101010000... .......... U U U 4 4 2 +tst 32 . a 0100101010001... .......... . . U . . 2 +tst 32 . . 0100101010...... A+-DXWL... U U U 4 4 2 +tst 32 . pcdi 0100101010111010 .......... . . U . . 7 +tst 32 . pcix 0100101010111011 .......... . . U . . 9 +tst 32 . i 0100101010111100 .......... . . U . . 6 +unlk 32 . a7 0100111001011111 .......... U U U 12 12 6 +unlk 32 . . 0100111001011... .......... U U U 12 12 6 +unpk 16 rr . 1000...110000... .......... . . U . . 8 +unpk 16 mm ax7 1000111110001... .......... . . U . . 13 +unpk 16 mm ay7 1000...110001111 .......... . . U . . 13 +unpk 16 mm axy7 1000111110001111 .......... . . U . . 13 +unpk 16 mm . 1000...110001... .......... . . U . . 13 + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_BODY + +M68KMAKE_OP(1010, 0, ., .) +{ + m68ki_exception_1010(); +} + + +M68KMAKE_OP(1111, 0, ., .) +{ + m68ki_exception_1111(); +} + + +M68KMAKE_OP(abcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(abcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(add, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(adda, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(adda, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(adda, 16, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(M68KMAKE_GET_OPER_AY_16)); +} + + +M68KMAKE_OP(adda, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); +} + + +M68KMAKE_OP(adda, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); +} + + +M68KMAKE_OP(adda, 32, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + M68KMAKE_GET_OPER_AY_32); +} + + +M68KMAKE_OP(addi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(addx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(addx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(and, 8, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, d) +{ + FLAG_Z = DX &= DY; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, .) +{ + FLAG_Z = DX &= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 8, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(andi, 16, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(andi, 32, ., d) +{ + FLAG_Z = DY &= (OPER_I_32()); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() & OPER_I_16()); +} + + +M68KMAKE_OP(andi, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() & src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(asr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_16(src)) + { + *r_dst |= 0xffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_32(src)) + { + *r_dst = 0xffffffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +M68KMAKE_OP(asl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +M68KMAKE_OP(bcc, 8, ., .) +{ + if(M68KMAKE_CC) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +M68KMAKE_OP(bcc, 16, ., .) +{ + if(M68KMAKE_CC) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +M68KMAKE_OP(bcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bchg, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bchg, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bclr, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bclr, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bfchg, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfclr, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + uint bit; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + uint64 insert = REG_D[(word2>>12)&7]; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + insert = MASK_OUT_ABOVE_32(insert << (32 - width)); + FLAG_N = NFLAG_32(insert); + FLAG_Z = insert; + insert = ROR_32(insert, offset); + + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + *data |= insert; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfset, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bftst, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bkpt, 0, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bra, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 16, ., .) +{ + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bset, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bset, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bsr, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); +} + + +M68KMAKE_OP(bsr, 16, ., .) +{ + uint offset = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 2; + m68ki_branch_16(offset); +} + + +M68KMAKE_OP(bsr, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 4; + m68ki_branch_32(offset); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(btst, 32, r, d) +{ + FLAG_Z = DY & (1 << (DX & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, r, .) +{ + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7)); +} + + +M68KMAKE_OP(btst, 32, s, d) +{ + FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, s, .) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << bit); +} + + +M68KMAKE_OP(callm, 32, ., .) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; +(void)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_16(ea1); + uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_16(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res1); + FLAG_Z = MASK_OUT_ABOVE_16(res1); + FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); + FLAG_C = CFLAG_16(res1); + + if(COND_EQ()) + { + res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); + + FLAG_N = NFLAG_16(res2); + FLAG_Z = MASK_OUT_ABOVE_16(res2); + FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); + FLAG_C = CFLAG_16(res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = BIT_1F(word2) ? MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; + *compare2 = BIT_F(word2) ? MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_32(ea1); + uint res1 = dest1 - *compare1; + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_32(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res1); + FLAG_Z = MASK_OUT_ABOVE_32(res1); + FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); + FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); + + if(COND_EQ()) + { + res2 = dest2 - *compare2; + + FLAG_N = NFLAG_32(res2); + FLAG_Z = MASK_OUT_ABOVE_32(res2); + FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); + FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = dest1; + *compare2 = dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 16, ., d) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(DY); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 16, ., .) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(DY); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCDI_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCIX_8(); + uint lower_bound = m68ki_read_pcrel_8(ea); + uint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = M68KMAKE_GET_EA_AY_8; + uint lower_bound = m68ki_read_8(ea); + uint upper_bound = m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCDI_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCIX_16(); + uint lower_bound = m68ki_read_pcrel_16(ea); + uint upper_bound = m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = M68KMAKE_GET_EA_AY_16; + uint lower_bound = m68ki_read_16(ea); + uint upper_bound = m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound); + else + FLAG_C = compare - lower_bound; + + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + if(!BIT_F(word2)) + FLAG_C = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare); + else + FLAG_C = upper_bound - compare; + + FLAG_C = CFLAG_16(FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCDI_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCIX_32(); + uint lower_bound = m68ki_read_pcrel_32(ea); + uint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = M68KMAKE_GET_EA_AY_32; + uint lower_bound = m68ki_read_32(ea); + uint upper_bound = m68ki_read_32(ea + 4); + + FLAG_C = compare - lower_bound; + FLAG_Z = !((upper_bound==compare) | (lower_bound==compare)); + FLAG_C = CFLAG_SUB_32(lower_bound, compare, FLAG_C); + if(COND_CS()) + { + if(BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + FLAG_C = upper_bound - compare; + FLAG_C = CFLAG_SUB_32(compare, upper_bound, FLAG_C); + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(clr, 8, ., d) +{ + DY &= 0xffffff00; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., d) +{ + DY &= 0xffff0000; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., .) +{ + m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., d) +{ + DY = 0; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., .) +{ + m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(cmp, 8, ., d) +{ + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 8, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 16, ., d) +{ + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., a) +{ + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 32, ., d) +{ + uint src = DY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., a) +{ + uint src = AY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., d) +{ + uint src = MAKE_INT_16(DY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., a) +{ + uint src = MAKE_INT_16(AY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., .) +{ + uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., d) +{ + uint src = DY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., a) +{ + uint src = AY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 8, ., d) +{ + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(DY); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., .) +{ + uint src = OPER_I_8(); + uint dst = M68KMAKE_GET_OPER_AY_8; + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCDI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCIX_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., d) +{ + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(DY); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., .) +{ + uint src = OPER_I_16(); + uint dst = M68KMAKE_GET_OPER_AY_16; + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCDI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCIX_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., d) +{ + uint src = OPER_I_32(); + uint dst = DY; + uint res = dst - src; + + m68ki_cmpild_callback(src, REG_IR & 7); /* auto-disable (see m68kcpu.h) */ + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., .) +{ + uint src = OPER_I_32(); + uint dst = M68KMAKE_GET_OPER_AY_32; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCDI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCIX_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpm, 8, ., ax7) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., ay7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., axy7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., .) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 16, ., .) +{ + uint src = OPER_AY_PI_16(); + uint dst = OPER_AX_PI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpm, 32, ., .) +{ + uint src = OPER_AY_PI_32(); + uint dst = OPER_AX_PI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cpbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpdbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpgen, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpscc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cptrapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(dbt, 16, ., .) +{ + REG_PC += 2; +} + + +M68KMAKE_OP(dbf, 16, ., .) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + return; + } + REG_PC += 2; +} + + +M68KMAKE_OP(dbcc, 16, ., .) +{ + if(M68KMAKE_NOT_CC) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +M68KMAKE_OP(divs, 16, ., d) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(DY); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divs, 16, ., .) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divl, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = DY; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = DY; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(divl, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = M68KMAKE_GET_OPER_AY_32; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = M68KMAKE_GET_OPER_AY_32; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(eor, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., d) +{ + uint res = DY ^= DX; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., d) +{ + uint res = DY ^= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() ^ OPER_I_16()); +} + + +M68KMAKE_OP(eori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() ^ src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(exg, 32, dd, .) +{ + uint* reg_a = &DX; + uint* reg_b = &DY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, aa, .) +{ + uint* reg_a = &AX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, da, .) +{ + uint* reg_a = &DX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(ext, 16, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); + + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(ext, 32, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(extb, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(illegal, 0, ., .) +{ + m68ki_exception_illegal(); +} + +M68KMAKE_OP(jmp, 32, ., .) +{ + m68ki_jump(M68KMAKE_GET_EA_AY_32); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(jsr, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_jump(ea); +} + + +M68KMAKE_OP(lea, 32, ., .) +{ + AX = M68KMAKE_GET_EA_AY_32; +} + + +M68KMAKE_OP(link, 16, ., a7) +{ + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 16, ., .) +{ + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 32, ., a7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(link, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(lsr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, d) +{ + uint res = DY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, a) +{ + uint res = AY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, d) +{ + uint res = DY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, a) +{ + uint res = AY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, d) +{ + uint res = DY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, a) +{ + uint res = AY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, d) +{ + uint res = DY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, a) +{ + uint res = AY; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PD_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, d) +{ + uint res = DY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, a) +{ + uint res = AY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, d) +{ + uint res = DY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, a) +{ + uint res = AY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, d) +{ + uint res = DY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, a) +{ + uint res = AY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, d) +{ + uint res = DY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, a) +{ + uint res = AY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(movea, 16, ., d) +{ + AX = MAKE_INT_16(DY); +} + + +M68KMAKE_OP(movea, 16, ., a) +{ + AX = MAKE_INT_16(AY); +} + + +M68KMAKE_OP(movea, 16, ., .) +{ + AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(movea, 32, ., d) +{ + AX = DY; +} + + +M68KMAKE_OP(movea, 32, ., a) +{ + AX = AY; +} + + +M68KMAKE_OP(movea, 32, ., .) +{ + AX = M68KMAKE_GET_OPER_AY_32; +} + + +M68KMAKE_OP(move, 16, frc, d) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, frc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(M68KMAKE_GET_EA_AY_16, m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, toc, d) +{ + m68ki_set_ccr(DY); +} + + +M68KMAKE_OP(move, 16, toc, .) +{ + m68ki_set_ccr(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(move, 16, frs, d) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, frs, .) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = M68KMAKE_GET_EA_AY_16; + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, d) +{ + if(FLAG_S) + { + m68ki_set_sr(DY); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, .) +{ + if(FLAG_S) + { + uint new_sr = M68KMAKE_GET_OPER_AY_16; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(new_sr); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, fru, .) +{ + if(FLAG_S) + { + AY = REG_USP; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, tou, .) +{ + if(FLAG_S) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_USP = AY; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(movec, 32, cr, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_DA[(word2 >> 12) & 15] = REG_SFC; + return; + case 0x001: /* DFC */ + REG_DA[(word2 >> 12) & 15] = REG_DFC; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CACR; + return; + } + return; + case 0x800: /* USP */ + REG_DA[(word2 >> 12) & 15] = REG_USP; + return; + case 0x801: /* VBR */ + REG_DA[(word2 >> 12) & 15] = REG_VBR; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CAAR; + return; + } + m68ki_exception_illegal(); + break; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movec, 32, rc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x001: /* DFC */ + REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CACR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x800: /* USP */ + REG_USP = REG_DA[(word2 >> 12) & 15]; + return; + case 0x801: /* VBR */ + REG_VBR = REG_DA[(word2 >> 12) & 15]; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CAAR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* we are in supervisor mode so just check for M flag */ + if(!FLAG_M) + { + REG_MSP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(!FLAG_M) + { + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_ISP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movem, 16, re, pd) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 2; + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); + count++; + } + AY = ea; + + USE_CYCLES(count<> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 32, re, .) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 16, er, .) +{ + uint ea = EA_AY_DI_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); +} + + +M68KMAKE_OP(movep, 32, er, .) +{ + uint ea = EA_AY_DI_32(); + + DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) + + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); +} + + +M68KMAKE_OP(moves, 8, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 16, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moveq, 32, ., .) +{ + uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(muls, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(muls, 16, ., .) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., .) +{ + uint* r_dst = &DX; + uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mull, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = DY; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = DY; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(mull, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = M68KMAKE_GET_OPER_AY_32; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(nbcd, 8, ., d) +{ + uint* r_dst = &DY; + uint dst = *r_dst; + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(nbcd, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(neg, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = *r_dst & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - *r_dst; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(neg, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(negx, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = *r_dst & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(negx, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(negx, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(negx, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(nop, 0, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +} + + +M68KMAKE_OP(not, 8, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_8(~*r_dst); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(~*r_dst); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., d) +{ + uint* r_dst = &DY; + uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, d) +{ + uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, .) +{ + uint res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, d) +{ + uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, .) +{ + uint res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, d) +{ + uint res = DX |= DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, .) +{ + uint res = DX |= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., d) +{ + uint res = DY |= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() | OPER_I_16()); +} + + +M68KMAKE_OP(ori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() | src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(pack, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY + OPER_I_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pea, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_push_32(ea); +} + + +M68KMAKE_OP(reset, 0, ., .) +{ + if(FLAG_S) + { + m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ + USE_CYCLES(CYC_RESET); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(ror, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> ((shift - 1) & 15)) << 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> ((shift - 1) & 31)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_16(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + if(shift != 0) + USE_CYCLES(shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + USE_CYCLES(orig_shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + if(shift != 0) + USE_CYCLES(shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + USE_CYCLES(orig_shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rtd, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + uint new_pc = m68ki_pull_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); + m68ki_jump(new_pc); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rte, 32, ., .) +{ + if(FLAG_S) + { + uint new_sr; + uint new_pc; + uint format_word; + + m68ki_rte_callback(); /* auto-disable (see m68kcpu.h) */ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + + return; + } + + if(CPU_TYPE_IS_010(CPU_TYPE)) + { + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + if(format_word == 0) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + /* Not handling bus fault (9) */ + m68ki_exception_format_error(); + return; + } + + /* Otherwise it's 020 */ +rte_loop: + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + switch(format_word) + { + case 0: /* Normal */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + case 1: /* Throwaway */ + new_sr = m68ki_pull_16(); + m68ki_fake_pull_32(); /* program counter */ + m68ki_fake_pull_16(); /* format word */ + m68ki_set_sr_noint(new_sr); + goto rte_loop; + case 2: /* Trap */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_fake_pull_32(); /* address */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + /* Not handling long or short bus fault */ + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + m68ki_exception_format_error(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(rtm, 32, ., .) +{ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rtr, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_ccr(m68ki_pull_16()); + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(rts, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(sbcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + +// FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + if(res > 0x99) + { + res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ + } + else + FLAG_N = FLAG_X = FLAG_C = 0; + + res = MASK_OUT_ABOVE_8(res); + +// FLAG_V &= res; /* Undefined V behavior part II */ +// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(sbcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + +// FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + if(res > 0x99) + { + res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ + } + else + FLAG_N = FLAG_X = FLAG_C = 0; + + res = MASK_OUT_ABOVE_8(res); + +// FLAG_V &= res; /* Undefined V behavior part II */ +// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + +// FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + if(res > 0x99) + { + res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ + } + else + FLAG_N = FLAG_X = FLAG_C = 0; + + res = MASK_OUT_ABOVE_8(res); + +// FLAG_V &= res; /* Undefined V behavior part II */ +// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + +// FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + if(res > 0x99) + { + res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ + } + else + FLAG_N = FLAG_X = FLAG_C = 0; + + res = MASK_OUT_ABOVE_8(res); + +// FLAG_V &= res; /* Undefined V behavior part II */ +// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + +// FLAG_V = ~res; /* Undefined V behavior */ + FLAG_V = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + if(res > 0x99) + { + res += 0xa0; + FLAG_X = FLAG_C = CFLAG_SET; + FLAG_N = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */ + } + else + FLAG_N = FLAG_X = FLAG_C = 0; + + res = MASK_OUT_ABOVE_8(res); + +// FLAG_V &= res; /* Undefined V behavior part II */ +// FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(st, 8, ., d) +{ + DY |= 0xff; +} + + +M68KMAKE_OP(st, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0xff); +} + + +M68KMAKE_OP(sf, 8, ., d) +{ + DY &= 0xffffff00; +} + + +M68KMAKE_OP(sf, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); +} + + +M68KMAKE_OP(scc, 8, ., d) +{ + if(M68KMAKE_CC) + { + DY |= 0xff; + USE_CYCLES(CYC_SCC_R_TRUE); + return; + } + DY &= 0xffffff00; +} + + +M68KMAKE_OP(scc, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0); +} + + +M68KMAKE_OP(stop, 0, ., .) +{ + if(FLAG_S) + { + uint new_sr = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + CPU_STOPPED |= STOP_LEVEL_STOP; + m68ki_set_sr(new_sr); + m68ki_remaining_cycles = 0; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(sub, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(suba, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(suba, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(suba, 16, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(M68KMAKE_GET_OPER_AY_16)); +} + + +M68KMAKE_OP(suba, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); +} + + +M68KMAKE_OP(suba, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); +} + + +M68KMAKE_OP(suba, 32, ., .) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - M68KMAKE_GET_OPER_AY_32); +} + + +M68KMAKE_OP(subi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(subx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(subx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(swap, 32, ., .) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); + *r_dst = (*r_dst>>16) | FLAG_Z; + + FLAG_Z = *r_dst; + FLAG_N = NFLAG_32(*r_dst); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(tas, 8, ., d) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_N = NFLAG_8(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst |= 0x80; +} + + +M68KMAKE_OP(tas, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + m68ki_write_8(ea, dst | 0x80); +} + + +M68KMAKE_OP(trap, 0, ., .) +{ + /* Trap#n stacks exception frame type 0 */ + m68ki_exception_trapN(EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ +} + + +M68KMAKE_OP(trapt, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapv, 0, ., .) +{ + if(COND_VC()) + { + return; + } + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ +} + + +M68KMAKE_OP(tst, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = MAKE_INT_16(AY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., d) +{ + uint res = DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = AY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unlk, 32, ., a7) +{ + REG_A[7] = m68ki_read_32(REG_A[7]); +} + + +M68KMAKE_OP(unlk, 32, ., .) +{ + uint* r_dst = &AY; + + REG_A[7] = *r_dst; + *r_dst = m68ki_pull_32(); +} + + +M68KMAKE_OP(unpk, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_END diff --git a/src/cpu/m68k/m68kconf.h b/src/cpu/m68k/m68kconf.h new file mode 100644 index 00000000..10335c4e --- /dev/null +++ b/src/cpu/m68k/m68kconf.h @@ -0,0 +1,268 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + +#ifndef M68KCONF__HEADER +#define M68KCONF__HEADER + +#define M68K_COMPILE_FOR_MAME OPT_OFF + +/* Configuration switches. + * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks. + * OPT_SPECIFY_HANDLER causes the core to link directly to the function + * or macro you specify, rather than using callback functions whose pointer + * must be passed in using m68k_set_xxx_callback(). + */ +#define OPT_OFF 0 +#define OPT_ON 1 +#define OPT_SPECIFY_HANDLER 2 + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +/* Turn ON if you want to use the following M68K variants */ +#define M68K_EMULATE_008 OPT_OFF +#define M68K_EMULATE_010 OPT_ON +#define M68K_EMULATE_EC020 OPT_ON +#define M68K_EMULATE_020 OPT_OFF + + +/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing + * and m68k_read_pcrelative_xx() for PC-relative addressing. + * If off, all read requests from the CPU will be redirected to m68k_read_xx() + */ +#define M68K_SEPARATE_READS OPT_ON + +/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a + * predecrement destination EA mode instead of m68k_write_32(). + * To simulate real 68k behavior, m68k_write_32_pd() must first write the high + * word to [address+2], and then write the low word to [address]. + */ +#define M68K_SIMULATE_PD_WRITES OPT_OFF + +/* If ON, CPU will call the interrupt acknowledge callback when it services an + * interrupt. + * If off, all interrupts will be autovectored and all interrupt requests will + * auto-clear when the interrupt is serviced. + */ +#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER +#define M68K_INT_ACK_CALLBACK(A) M68KIRQAcknowledge(A) + + +/* If ON, CPU will call the breakpoint acknowledge callback when it encounters + * a breakpoint instruction and it is running a 68010+. + */ +#define M68K_EMULATE_BKPT_ACK OPT_OFF +#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function() + + +/* If ON, the CPU will monitor the trace flags and take trace exceptions + */ +#define M68K_EMULATE_TRACE OPT_OFF + + +/* If ON, CPU will call the output reset callback when it encounters a reset + * instruction. + */ +#define M68K_EMULATE_RESET OPT_SPECIFY_HANDLER +#define M68K_RESET_CALLBACK() M68KResetCallback() + + +/* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn + * instruction. + */ +#define M68K_CMPILD_HAS_CALLBACK OPT_SPECIFY_HANDLER +//#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r) +#define M68K_CMPILD_CALLBACK(v, r) M68KcmpildCallback(v, r) + +/* If ON, CPU will call the callback when it encounters a rte + * instruction. + */ +#define M68K_RTE_HAS_CALLBACK OPT_SPECIFY_HANDLER +//#define M68K_RTE_CALLBACK() your_rte_handler_function() +#define M68K_RTE_CALLBACK() M68KRTECallback() + + +/* If ON, CPU will call the set fc callback on every memory access to + * differentiate between user/supervisor, program/data access like a real + * 68000 would. This should be enabled and the callback should be set if you + * want to properly emulate the m68010 or higher. (moves uses function codes + * to read/write data from different address spaces) + */ +#define M68K_EMULATE_FC OPT_OFF +#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A) + + +/* If ON, CPU will call the pc changed callback when it changes the PC by a + * large value. This allows host programs to be nicer when it comes to + * fetching immediate data and instructions on a banked memory system. + */ +#define M68K_MONITOR_PC OPT_OFF +#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) + + +/* If ON, CPU will call the instruction hook callback before every + * instruction. + */ +#ifdef FBA_DEBUG + #define M68K_INSTRUCTION_HOOK OPT_ON +#else + #define M68K_INSTRUCTION_HOOK OPT_OFF +#endif +#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function() + + +/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ +#define M68K_EMULATE_PREFETCH OPT_ON + + +/* If ON, the CPU will generate address error exceptions if it tries to + * access a word or longword at an odd address. + * NOTE: This is only emulated properly for 68000 mode. + */ +#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF + + +/* Turn ON to enable logging of illegal instruction calls. + * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. + * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls. + */ +#define M68K_LOG_ENABLE OPT_OFF +#define M68K_LOG_1010_1111 OPT_OFF +#define M68K_LOG_FILEHANDLE some_file_handle + + +/* ----------------------------- COMPATIBILITY ---------------------------- */ + +/* The following options set optimizations that violate the current ANSI + * standard, but will be compliant under the forthcoming C9X standard. + */ + + +/* If ON, the enulation core will use 64-bit integers to speed up some + * operations. +*/ +#define M68K_USE_64_BIT OPT_OFF + + +/* Set to your compiler's static inline keyword to enable it, or + * set it to blank to disable it. + * If you define INLINE in the makefile, it will override this value. + * NOTE: not enabling inline functions will SEVERELY slow down emulation. + */ +#ifndef INLINE +#define INLINE static __inline__ +#endif /* INLINE */ + +/* --------------------------- FB Alpha handlers -------------------------- */ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef FASTCALL + #undef __fastcall + #define __fastcall +#endif + +/* Reset callback */ +void M68KResetCallback(void); +int M68KIRQAcknowledge(int nIRQ); +void M68KRTECallback(void); +void M68KcmpildCallback(unsigned int val, int reg); + +unsigned int __fastcall M68KFetchByte(unsigned int a); +unsigned int __fastcall M68KFetchWord(unsigned int a); +unsigned int __fastcall M68KFetchLong(unsigned int a); + +extern unsigned int (*SekDbgFetchByteDisassembler)(unsigned int); +extern unsigned int (*SekDbgFetchWordDisassembler)(unsigned int); +extern unsigned int (*SekDbgFetchLongDisassembler)(unsigned int); + +#if defined FBA_DEBUG +extern unsigned int (__fastcall *M68KReadByteDebug)(unsigned int); +extern unsigned int (__fastcall *M68KReadWordDebug)(unsigned int); +extern unsigned int (__fastcall *M68KReadLongDebug)(unsigned int); + +extern void (__fastcall *M68KWriteByteDebug)(unsigned int, unsigned int); +extern void (__fastcall *M68KWriteWordDebug)(unsigned int, unsigned int); +extern void (__fastcall *M68KWriteLongDebug)(unsigned int, unsigned int); +#else +unsigned int __fastcall M68KReadByte(unsigned int a); +unsigned int __fastcall M68KReadWord(unsigned int a); +unsigned int __fastcall M68KReadLong(unsigned int a); + +void __fastcall M68KWriteByte(unsigned int a, unsigned int d); +void __fastcall M68KWriteWord(unsigned int a, unsigned int d); +void __fastcall M68KWriteLong(unsigned int a, unsigned int d); +#endif + +#ifdef __cplusplus + } +#endif + +#define m68ki_remaining_cycles m68k_ICount + +/* Read data relative to the PC */ +#define m68k_read_pcrelative_8(address) M68KFetchByte(address) +#define m68k_read_pcrelative_16(address) M68KFetchWord(address) +#define m68k_read_pcrelative_32(address) M68KFetchLong(address) + +/* Read data immediately following the PC */ +#define m68k_read_immediate_16(address) M68KFetchWord(address) +#define m68k_read_immediate_32(address) M68KFetchLong(address) + +/* Memory access for the disassembler */ +#define m68k_read_disassembler_8(address) SekDbgFetchByteDisassembler(address) +#define m68k_read_disassembler_16(address) SekDbgFetchWordDisassembler(address) +#define m68k_read_disassembler_32(address) SekDbgFetchLongDisassembler(address) + +#if defined FBA_DEBUG +/* Read from anywhere */ +#define m68k_read_memory_8(address) M68KReadByteDebug(address) +#define m68k_read_memory_16(address) M68KReadWordDebug(address) +#define m68k_read_memory_32(address) M68KReadLongDebug(address) + +/* Write to anywhere */ +#define m68k_write_memory_8(address, value) M68KWriteByteDebug(address, value) +#define m68k_write_memory_16(address, value) M68KWriteWordDebug(address, value) +#define m68k_write_memory_32(address, value) M68KWriteLongDebug(address, value) +#else +/* Read from anywhere */ +#define m68k_read_memory_8(address) M68KReadByte(address) +#define m68k_read_memory_16(address) M68KReadWord(address) +#define m68k_read_memory_32(address) M68KReadLong(address) + +/* Write to anywhere */ +#define m68k_write_memory_8(address, value) M68KWriteByte(address, value) +#define m68k_write_memory_16(address, value) M68KWriteWord(address, value) +#define m68k_write_memory_32(address, value) M68KWriteLong(address, value) +#endif /* FBA_DEBUG */ + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KCONF__HEADER */ diff --git a/src/cpu/m68k/m68kcpu.c b/src/cpu/m68k/m68kcpu.c new file mode 100644 index 00000000..b87af4e6 --- /dev/null +++ b/src/cpu/m68k/m68kcpu.c @@ -0,0 +1,923 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ + +#if 1 +static const char* copyright_notice = +"MUSASHI\n" +"Version 3.3 (2001-01-29)\n" +"A portable Motorola M680x0 processor emulation engine.\n" +"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n" +"\n" +"This code may be freely used for non-commercial purpooses as long as this\n" +"copyright notice remains unaltered in the source code and any binary files\n" +"containing this code in compiled form.\n" +"\n" +"All other lisencing terms must be negotiated with the author\n" +"(Karl Stenerud).\n" +"\n" +"The latest version of this code can be obtained at:\n" +"http://kstenerud.cjb.net\n" +; +#endif + + +/* ======================================================================== */ +/* ================================= NOTES ================================ */ +/* ======================================================================== */ + + + +/* ======================================================================== */ +/* ================================ INCLUDES ============================== */ +/* ======================================================================== */ + +#include "m68kops.h" +#include "m68kcpu.h" + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +int m68ki_initial_cycles; +int m68ki_remaining_cycles = 0; /* Number of clocks remaining */ +uint m68ki_tracing = 0; +uint m68ki_address_space; + +#ifdef M68K_LOG_ENABLE +const char* m68ki_cpu_names[] = +{ + "Invalid CPU", + "M68000", + "M68008", + "Invalid CPU", + "M68010", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "M68EC020", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "Invalid CPU", + "M68020" +}; +#endif /* M68K_LOG_ENABLE */ + +/* The CPU core */ +m68ki_cpu_core m68ki_cpu = {0}; + +#if M68K_EMULATE_ADDRESS_ERROR +jmp_buf m68ki_aerr_trap; +#endif /* M68K_EMULATE_ADDRESS_ERROR */ + +uint m68ki_aerr_address; +uint m68ki_aerr_write_mode; +uint m68ki_aerr_fc; + +/* Used by shift & rotate instructions */ +uint8 m68ki_shift_8_table[65] = +{ + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff +}; +uint16 m68ki_shift_16_table[65] = +{ + 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, + 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff +}; +uint m68ki_shift_32_table[65] = +{ + 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, + 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, + 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, + 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, + 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, + 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; + + +/* Number of clock cycles to use for exception processing. + * I used 4 for any vectors that are undocumented for processing times. + */ +uint8 m68ki_exception_cycle_table[3][256] = +{ + { /* 000 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 50, /* 2: Bus Error (unemulated) */ + 50, /* 3: Address Error (unemulated) */ + 34, /* 4: Illegal Instruction */ + 38, /* 5: Divide by Zero -- ASG: changed from 42 */ + 40, /* 6: CHK -- ASG: chanaged from 44 */ + 34, /* 7: TRAPV */ + 34, /* 8: Privilege Violation */ + 34, /* 9: Trace */ + 4, /* 10: 1010 */ + 4, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 44, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 44, /* 24: Spurious Interrupt */ + 44, /* 25: Level 1 Interrupt Autovector */ + 44, /* 26: Level 2 Interrupt Autovector */ + 44, /* 27: Level 3 Interrupt Autovector */ + 44, /* 28: Level 4 Interrupt Autovector */ + 44, /* 29: Level 5 Interrupt Autovector */ + 44, /* 30: Level 6 Interrupt Autovector */ + 44, /* 31: Level 7 Interrupt Autovector */ + 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */ + 34, /* 33: TRAP #1 */ + 34, /* 34: TRAP #2 */ + 34, /* 35: TRAP #3 */ + 34, /* 36: TRAP #4 */ + 34, /* 37: TRAP #5 */ + 34, /* 38: TRAP #6 */ + 34, /* 39: TRAP #7 */ + 34, /* 40: TRAP #8 */ + 34, /* 41: TRAP #9 */ + 34, /* 42: TRAP #10 */ + 34, /* 43: TRAP #11 */ + 34, /* 44: TRAP #12 */ + 34, /* 45: TRAP #13 */ + 34, /* 46: TRAP #14 */ + 34, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + }, + { /* 010 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 126, /* 2: Bus Error (unemulated) */ + 126, /* 3: Address Error (unemulated) */ + 38, /* 4: Illegal Instruction */ + 44, /* 5: Divide by Zero */ + 44, /* 6: CHK */ + 34, /* 7: TRAPV */ + 38, /* 8: Privilege Violation */ + 38, /* 9: Trace */ + 4, /* 10: 1010 */ + 4, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 44, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 46, /* 24: Spurious Interrupt */ + 46, /* 25: Level 1 Interrupt Autovector */ + 46, /* 26: Level 2 Interrupt Autovector */ + 46, /* 27: Level 3 Interrupt Autovector */ + 46, /* 28: Level 4 Interrupt Autovector */ + 46, /* 29: Level 5 Interrupt Autovector */ + 46, /* 30: Level 6 Interrupt Autovector */ + 46, /* 31: Level 7 Interrupt Autovector */ + 38, /* 32: TRAP #0 */ + 38, /* 33: TRAP #1 */ + 38, /* 34: TRAP #2 */ + 38, /* 35: TRAP #3 */ + 38, /* 36: TRAP #4 */ + 38, /* 37: TRAP #5 */ + 38, /* 38: TRAP #6 */ + 38, /* 39: TRAP #7 */ + 38, /* 40: TRAP #8 */ + 38, /* 41: TRAP #9 */ + 38, /* 42: TRAP #10 */ + 38, /* 43: TRAP #11 */ + 38, /* 44: TRAP #12 */ + 38, /* 45: TRAP #13 */ + 38, /* 46: TRAP #14 */ + 38, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + }, + { /* 020 */ + 4, /* 0: Reset - Initial Stack Pointer */ + 4, /* 1: Reset - Initial Program Counter */ + 50, /* 2: Bus Error (unemulated) */ + 50, /* 3: Address Error (unemulated) */ + 20, /* 4: Illegal Instruction */ + 38, /* 5: Divide by Zero */ + 40, /* 6: CHK */ + 20, /* 7: TRAPV */ + 34, /* 8: Privilege Violation */ + 25, /* 9: Trace */ + 20, /* 10: 1010 */ + 20, /* 11: 1111 */ + 4, /* 12: RESERVED */ + 4, /* 13: Coprocessor Protocol Violation (unemulated) */ + 4, /* 14: Format Error */ + 30, /* 15: Uninitialized Interrupt */ + 4, /* 16: RESERVED */ + 4, /* 17: RESERVED */ + 4, /* 18: RESERVED */ + 4, /* 19: RESERVED */ + 4, /* 20: RESERVED */ + 4, /* 21: RESERVED */ + 4, /* 22: RESERVED */ + 4, /* 23: RESERVED */ + 30, /* 24: Spurious Interrupt */ + 30, /* 25: Level 1 Interrupt Autovector */ + 30, /* 26: Level 2 Interrupt Autovector */ + 30, /* 27: Level 3 Interrupt Autovector */ + 30, /* 28: Level 4 Interrupt Autovector */ + 30, /* 29: Level 5 Interrupt Autovector */ + 30, /* 30: Level 6 Interrupt Autovector */ + 30, /* 31: Level 7 Interrupt Autovector */ + 20, /* 32: TRAP #0 */ + 20, /* 33: TRAP #1 */ + 20, /* 34: TRAP #2 */ + 20, /* 35: TRAP #3 */ + 20, /* 36: TRAP #4 */ + 20, /* 37: TRAP #5 */ + 20, /* 38: TRAP #6 */ + 20, /* 39: TRAP #7 */ + 20, /* 40: TRAP #8 */ + 20, /* 41: TRAP #9 */ + 20, /* 42: TRAP #10 */ + 20, /* 43: TRAP #11 */ + 20, /* 44: TRAP #12 */ + 20, /* 45: TRAP #13 */ + 20, /* 46: TRAP #14 */ + 20, /* 47: TRAP #15 */ + 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ + 4, /* 49: FP Inexact Result (unemulated) */ + 4, /* 50: FP Divide by Zero (unemulated) */ + 4, /* 51: FP Underflow (unemulated) */ + 4, /* 52: FP Operand Error (unemulated) */ + 4, /* 53: FP Overflow (unemulated) */ + 4, /* 54: FP Signaling NAN (unemulated) */ + 4, /* 55: FP Unimplemented Data Type (unemulated) */ + 4, /* 56: MMU Configuration Error (unemulated) */ + 4, /* 57: MMU Illegal Operation Error (unemulated) */ + 4, /* 58: MMU Access Level Violation Error (unemulated) */ + 4, /* 59: RESERVED */ + 4, /* 60: RESERVED */ + 4, /* 61: RESERVED */ + 4, /* 62: RESERVED */ + 4, /* 63: RESERVED */ + /* 64-255: User Defined */ + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + } +}; + +uint8 m68ki_ea_idx_cycle_table[64] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* ..01.000 no memory indirect, base NULL */ + 5, /* ..01..01 memory indirect, base NULL, outer NULL */ + 7, /* ..01..10 memory indirect, base NULL, outer 16 */ + 7, /* ..01..11 memory indirect, base NULL, outer 32 */ + 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7, + 2, /* ..10.000 no memory indirect, base 16 */ + 7, /* ..10..01 memory indirect, base 16, outer NULL */ + 9, /* ..10..10 memory indirect, base 16, outer 16 */ + 9, /* ..10..11 memory indirect, base 16, outer 32 */ + 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9, + 6, /* ..11.000 no memory indirect, base 32 */ + 11, /* ..11..01 memory indirect, base 32, outer NULL */ + 13, /* ..11..10 memory indirect, base 32, outer 16 */ + 13, /* ..11..11 memory indirect, base 32, outer 32 */ + 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13 +}; + + + +/* ======================================================================== */ +/* =============================== CALLBACKS ============================== */ +/* ======================================================================== */ + +/* Default callbacks used if the callback hasn't been set yet, or if the + * callback is set to NULL + */ + +/* Interrupt acknowledge */ +static int default_int_ack_callback_data; +static int default_int_ack_callback(int int_level) +{ + default_int_ack_callback_data = int_level; + CPU_INT_LEVEL = 0; + return M68K_INT_ACK_AUTOVECTOR; +} + +/* Breakpoint acknowledge */ +static unsigned int default_bkpt_ack_callback_data; +static void default_bkpt_ack_callback(unsigned int data) +{ + default_bkpt_ack_callback_data = data; +} + +/* Called when a reset instruction is executed */ +static void default_reset_instr_callback(void) +{ +} + +/* Called when a cmpi.l #v, dn instruction is executed */ +static void default_cmpild_instr_callback(unsigned int val, int reg) +{ +} + +/* Called when a rte instruction is executed */ +static void default_rte_instr_callback(void) +{ +} + +/* Called when the program counter changed by a large value */ +static unsigned int default_pc_changed_callback_data; +static void default_pc_changed_callback(unsigned int new_pc) +{ + default_pc_changed_callback_data = new_pc; +} + +/* Called every time there's bus activity (read/write to/from memory */ +static unsigned int default_set_fc_callback_data; +static void default_set_fc_callback(unsigned int new_fc) +{ + default_set_fc_callback_data = new_fc; +} + +/* Called every instruction cycle prior to execution */ +static void default_instr_hook_callback(void) +{ +} + + +#if M68K_EMULATE_ADDRESS_ERROR + #include + jmp_buf m68ki_aerr_trap; +#endif /* M68K_EMULATE_ADDRESS_ERROR */ + + +/* ======================================================================== */ +/* ================================= API ================================== */ +/* ======================================================================== */ + +/* Access the internals of the CPU */ +unsigned int m68k_get_reg(void* context, m68k_register_t regnum) +{ + m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu; + + switch(regnum) + { + case M68K_REG_D0: return cpu->dar[0]; + case M68K_REG_D1: return cpu->dar[1]; + case M68K_REG_D2: return cpu->dar[2]; + case M68K_REG_D3: return cpu->dar[3]; + case M68K_REG_D4: return cpu->dar[4]; + case M68K_REG_D5: return cpu->dar[5]; + case M68K_REG_D6: return cpu->dar[6]; + case M68K_REG_D7: return cpu->dar[7]; + case M68K_REG_A0: return cpu->dar[8]; + case M68K_REG_A1: return cpu->dar[9]; + case M68K_REG_A2: return cpu->dar[10]; + case M68K_REG_A3: return cpu->dar[11]; + case M68K_REG_A4: return cpu->dar[12]; + case M68K_REG_A5: return cpu->dar[13]; + case M68K_REG_A6: return cpu->dar[14]; + case M68K_REG_A7: return cpu->dar[15]; + case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); + case M68K_REG_SR: return cpu->t1_flag | + cpu->t0_flag | + (cpu->s_flag << 11) | + (cpu->m_flag << 11) | + cpu->int_mask | + ((cpu->x_flag & XFLAG_SET) >> 4) | + ((cpu->n_flag & NFLAG_SET) >> 4) | + ((!cpu->not_z_flag) << 2) | + ((cpu->v_flag & VFLAG_SET) >> 6) | + ((cpu->c_flag & CFLAG_SET) >> 8); + case M68K_REG_SP: return cpu->dar[15]; + case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15]; + case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4]; + case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6]; + case M68K_REG_SFC: return cpu->sfc; + case M68K_REG_DFC: return cpu->dfc; + case M68K_REG_VBR: return cpu->vbr; + case M68K_REG_CACR: return cpu->cacr; + case M68K_REG_CAAR: return cpu->caar; + case M68K_REG_PREF_ADDR: return cpu->pref_addr; + case M68K_REG_PREF_DATA: return cpu->pref_data; + case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc); + case M68K_REG_IR: return cpu->ir; + case M68K_REG_CPU_TYPE: + switch(cpu->cpu_type) + { + case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; + case CPU_TYPE_008: return (unsigned int)M68K_CPU_TYPE_68008; + case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; + case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; + case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; + } + return M68K_CPU_TYPE_INVALID; + default: return 0; + } + return 0; +} + +void m68k_set_reg(m68k_register_t regnum, unsigned int value) +{ + switch(regnum) + { + case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return; + case M68K_REG_SR: m68ki_set_sr(value); return; + case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_USP: if(FLAG_S) + REG_USP = MASK_OUT_ABOVE_32(value); + else + REG_SP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_ISP: if(FLAG_S && !FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_ISP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_MSP: if(FLAG_S && FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_MSP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_SFC: REG_SFC = value & 7; return; + case M68K_REG_DFC: REG_DFC = value & 7; return; + case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return; + case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return; + default: return; + } +} + +/* Set the callbacks */ +void m68k_set_int_ack_callback(int (*callback)(int int_level)) +{ + CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback; +} + +void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)) +{ + CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback; +} + +void m68k_set_reset_instr_callback(void (*callback)(void)) +{ + CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback; +} + +void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int)) +{ + CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback; +} + +void m68k_set_rte_instr_callback(void (*callback)(void)) +{ + CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback; +} + +void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)) +{ + CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback; +} + +void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)) +{ + CALLBACK_SET_FC = callback ? callback : default_set_fc_callback; +} + +void m68k_set_instr_hook_callback(void (*callback)(void)) +{ + CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; +} + +#include +/* Set the CPU type. */ +void m68k_set_cpu_type(unsigned int cpu_type) +{ + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + CPU_TYPE = CPU_TYPE_000; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[0]; + CYC_EXCEPTION = m68ki_exception_cycle_table[0]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 2; + CYC_DBCC_F_NOEXP = -2; + CYC_DBCC_F_EXP = 2; + CYC_SCC_R_TRUE = 2; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 132; + return; + case M68K_CPU_TYPE_68008: + CPU_TYPE = CPU_TYPE_008; + CPU_ADDRESS_MASK = 0x003fffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[0]; + CYC_EXCEPTION = m68ki_exception_cycle_table[0]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 2; + CYC_DBCC_F_NOEXP = -2; + CYC_DBCC_F_EXP = 2; + CYC_SCC_R_TRUE = 2; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 132; + return; + case M68K_CPU_TYPE_68010: + CPU_TYPE = CPU_TYPE_010; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[1]; + CYC_EXCEPTION = m68ki_exception_cycle_table[1]; + CYC_BCC_NOTAKE_B = -4; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 6; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 130; + return; + case M68K_CPU_TYPE_68EC020: + CPU_TYPE = CPU_TYPE_EC020; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + return; + case M68K_CPU_TYPE_68020: + CPU_TYPE = CPU_TYPE_020; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + return; + } +} + +/* Execute some instructions until we use up num_cycles clock cycles */ +/* ASG: removed per-instruction interrupt checks */ +int m68k_execute(int num_cycles) +{ + /* Make sure we're not stopped */ + if(!CPU_STOPPED) + { + /* Set our pool of clock cycles available */ + SET_CYCLES(num_cycles); + m68ki_initial_cycles = num_cycles; + + /* ASG: update cycles */ + USE_CYCLES(CPU_INT_CYCLES); + CPU_INT_CYCLES = 0; + + /* Return point if we had an address error */ + m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ + + /* Main loop. Keep going until we run out of clock cycles */ + do + { + /* Set tracing accodring to T1. (T0 is done inside instruction) */ + m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ + + /* Set the address space for reads */ + m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ + + /* Call external hook to peek at CPU */ + m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */ + + /* Record previous program counter */ + REG_PPC = REG_PC; + + /* Read an instruction and call its handler */ + REG_IR = m68ki_read_imm_16(); + m68ki_instruction_jump_table[REG_IR](); + USE_CYCLES(CYC_INSTRUCTION[REG_IR]); + + /* Trace m68k_exception, if necessary */ + m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ + } while(GET_CYCLES() > 0); + + /* set previous PC to current PC for the next entry into the loop */ + REG_PPC = REG_PC; + + /* ASG: update cycles */ + USE_CYCLES(CPU_INT_CYCLES); + CPU_INT_CYCLES = 0; + + /* return how many clocks we used */ + return m68ki_initial_cycles - GET_CYCLES(); + } + + /* We get here if the CPU is stopped or halted */ + SET_CYCLES(0); + CPU_INT_CYCLES = 0; + + return num_cycles; +} + + +int m68k_cycles_run(void) +{ + return m68ki_initial_cycles - GET_CYCLES(); +} + +int m68k_cycles_remaining(void) +{ + return GET_CYCLES(); +} + +/* Change the timeslice */ +void m68k_modify_timeslice(int cycles) +{ + m68ki_initial_cycles += cycles; + ADD_CYCLES(cycles); +} + + +void m68k_end_timeslice(void) +{ + m68ki_initial_cycles -= GET_CYCLES(); + SET_CYCLES(0); +} + + +/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */ +/* KS: Modified so that IPL* bits match with mask positions in the SR + * and cleaned out remenants of the interrupt controller. + */ +void m68k_set_irq(unsigned int int_level) +{ + uint old_level = CPU_INT_LEVEL; + CPU_INT_LEVEL = int_level << 8; + + /* A transition from < 7 to 7 always interrupts (NMI) */ + /* Note: Level 7 can also level trigger like a normal IRQ */ + if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) + m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */ + else + m68ki_check_interrupts(); /* Level triggered (IRQ) */ +} + +void m68k_init(void) +{ + static uint emulation_initialized = 0; + + /* The first call to this function initializes the opcode handler jump table */ + if(!emulation_initialized) + { + m68ki_build_opcode_table(); + emulation_initialized = 1; + } + + m68k_set_int_ack_callback(NULL); + m68k_set_bkpt_ack_callback(NULL); + m68k_set_reset_instr_callback(NULL); + m68k_set_cmpild_instr_callback(NULL); + m68k_set_rte_instr_callback(NULL); + m68k_set_pc_changed_callback(NULL); + m68k_set_fc_callback(NULL); + m68k_set_instr_hook_callback(NULL); +} + +/* Pulse the RESET line on the CPU */ +void m68k_pulse_reset(void) +{ + /* Clear all stop levels and eat up all remaining cycles */ + CPU_STOPPED = 0; + SET_CYCLES(0); + + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + + /* Turn off tracing */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Interrupt mask to level 7 */ + FLAG_INT_MASK = 0x0700; + /* Reset VBR */ + REG_VBR = 0; + /* Go to supervisor mode */ + m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR); + + /* Invalidate the prefetch queue */ +#if M68K_EMULATE_PREFETCH + /* Set to arbitrary number since our first fetch is from 0 */ + CPU_PREF_ADDR = 0x1000; +#endif /* M68K_EMULATE_PREFETCH */ + + /* Read the initial stack pointer and program counter */ + m68ki_jump(0); + REG_SP = m68ki_read_imm_32(); + REG_PC = m68ki_read_imm_32(); + m68ki_jump(REG_PC); + + CPU_RUN_MODE = RUN_MODE_NORMAL; +} + +/* Pulse the HALT line on the CPU */ +void m68k_pulse_halt(void) +{ + CPU_STOPPED |= STOP_LEVEL_HALT; +} + + +/* Get and set the current CPU context */ +/* This is to allow for multiple CPUs */ +unsigned int m68k_context_size() +{ + return sizeof(m68ki_cpu_core); +} + +unsigned int m68k_get_context(void* dst) +{ + if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu; + return sizeof(m68ki_cpu_core); +} + +void m68k_set_context(void* src) +{ + if(src) m68ki_cpu = *(m68ki_cpu_core*)src; +} + + + +/* ======================================================================== */ +/* ============================== MAME STUFF ============================== */ +/* ======================================================================== */ + +#if M68K_COMPILE_FOR_MAME == OPT_ON + +#include "state.h" + +static struct { + UINT16 sr; + int stopped; + int halted; +} m68k_substate; + +static void m68k_prepare_substate(void) +{ + m68k_substate.sr = m68ki_get_sr(); + m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0; + m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0; +} + +static void m68k_post_load(void) +{ + m68ki_set_sr_noint_nosp(m68k_substate.sr); + CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0 + | m68k_substate.halted ? STOP_LEVEL_HALT : 0; + m68ki_jump(REG_PC); +} + +void m68k_state_register(const char *type) +{ + int cpu = cpu_getactivecpu(); + + state_save_register_UINT32(type, cpu, "D" , REG_D, 8); + state_save_register_UINT32(type, cpu, "A" , REG_A, 8); + state_save_register_UINT32(type, cpu, "PPC" , ®_PPC, 1); + state_save_register_UINT32(type, cpu, "PC" , ®_PC, 1); + state_save_register_UINT32(type, cpu, "USP" , ®_USP, 1); + state_save_register_UINT32(type, cpu, "ISP" , ®_ISP, 1); + state_save_register_UINT32(type, cpu, "MSP" , ®_MSP, 1); + state_save_register_UINT32(type, cpu, "VBR" , ®_VBR, 1); + state_save_register_UINT32(type, cpu, "SFC" , ®_SFC, 1); + state_save_register_UINT32(type, cpu, "DFC" , ®_DFC, 1); + state_save_register_UINT32(type, cpu, "CACR" , ®_CACR, 1); + state_save_register_UINT32(type, cpu, "CAAR" , ®_CAAR, 1); + state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1); + state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1); + state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1); + state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped); + state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted); + state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1); + state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1); + state_save_register_func_presave(m68k_prepare_substate); + state_save_register_func_postload(m68k_post_load); +} + +#endif /* M68K_COMPILE_FOR_MAME */ + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/src/cpu/m68k/m68kcpu.h b/src/cpu/m68k/m68kcpu.h new file mode 100644 index 00000000..85bd4e01 --- /dev/null +++ b/src/cpu/m68k/m68kcpu.h @@ -0,0 +1,1993 @@ +#include +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + + +#ifndef M68KCPU__HEADER +#define M68KCPU__HEADER + +#include "m68k.h" +#include + +#if M68K_EMULATE_ADDRESS_ERROR +#include +#endif /* M68K_EMULATE_ADDRESS_ERROR */ + +/* ======================================================================== */ +/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ +/* ======================================================================== */ + +/* Check for > 32bit sizes */ +#if UINT_MAX > 0xffffffff + #define M68K_INT_GT_32_BIT 1 +#else + #define M68K_INT_GT_32_BIT 0 +#endif + +/* Data types used in this emulation core */ +#undef sint8 +#undef sint16 +#undef sint32 +#undef sint64 +#undef uint8 +#undef uint16 +#undef uint32 +#undef uint64 +#undef sint +#undef uint + +#define sint8 signed char /* ASG: changed from char to signed char */ +#define sint16 signed short +#define sint32 signed long +#define uint8 unsigned char +#define uint16 unsigned short +#define uint32 unsigned long + +/* signed and unsigned int must be at least 32 bits wide */ +#define sint signed int +#define uint unsigned int + + +#if M68K_USE_64_BIT +#define sint64 signed long long +#define uint64 unsigned long long +#else +#define sint64 sint32 +#define uint64 uint32 +#endif /* M68K_USE_64_BIT */ + + + +/* Allow for architectures that don't have 8-bit sizes */ +#if UCHAR_MAX == 0xff + #define MAKE_INT_8(A) (sint8)(A) +#else + #undef sint8 + #define sint8 signed int + #undef uint8 + #define uint8 unsigned int + INLINE sint MAKE_INT_8(uint value) + { + return (value & 0x80) ? value | ~0xff : value & 0xff; + } +#endif /* UCHAR_MAX == 0xff */ + + +/* Allow for architectures that don't have 16-bit sizes */ +#if USHRT_MAX == 0xffff + #define MAKE_INT_16(A) (sint16)(A) +#else + #undef sint16 + #define sint16 signed int + #undef uint16 + #define uint16 unsigned int + INLINE sint MAKE_INT_16(uint value) + { + return (value & 0x8000) ? value | ~0xffff : value & 0xffff; + } +#endif /* USHRT_MAX == 0xffff */ + + +/* Allow for architectures that don't have 32-bit sizes */ +#if ULONG_MAX == 0xffffffff + #define MAKE_INT_32(A) (sint32)(A) +#else + #undef sint32 + #define sint32 signed int + #undef uint32 + #define uint32 unsigned int + INLINE sint MAKE_INT_32(uint value) + { + return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; + } +#endif /* ULONG_MAX == 0xffffffff */ + + + + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ +/* ======================================================================== */ + +/* Exception Vectors handled by emulation */ +#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */ +#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */ +#define EXCEPTION_ILLEGAL_INSTRUCTION 4 +#define EXCEPTION_ZERO_DIVIDE 5 +#define EXCEPTION_CHK 6 +#define EXCEPTION_TRAPV 7 +#define EXCEPTION_PRIVILEGE_VIOLATION 8 +#define EXCEPTION_TRACE 9 +#define EXCEPTION_1010 10 +#define EXCEPTION_1111 11 +#define EXCEPTION_FORMAT_ERROR 14 +#define EXCEPTION_UNINITIALIZED_INTERRUPT 15 +#define EXCEPTION_SPURIOUS_INTERRUPT 24 +#define EXCEPTION_INTERRUPT_AUTOVECTOR 24 +#define EXCEPTION_TRAP_BASE 32 + +/* Function codes set by CPU during data/address bus activity */ +#define FUNCTION_CODE_USER_DATA 1 +#define FUNCTION_CODE_USER_PROGRAM 2 +#define FUNCTION_CODE_SUPERVISOR_DATA 5 +#define FUNCTION_CODE_SUPERVISOR_PROGRAM 6 +#define FUNCTION_CODE_CPU_SPACE 7 + +/* CPU types for deciding what to emulate */ +#define CPU_TYPE_000 1 +#define CPU_TYPE_008 2 +#define CPU_TYPE_010 4 +#define CPU_TYPE_EC020 8 +#define CPU_TYPE_020 16 + +/* Different ways to stop the CPU */ +#define STOP_LEVEL_STOP 1 +#define STOP_LEVEL_HALT 2 + +/* Used for 68000 address error processing */ +#define INSTRUCTION_YES 0 +#define INSTRUCTION_NO 0x08 +#define MODE_READ 0x10 +#define MODE_WRITE 0 + +#define RUN_MODE_NORMAL 0 +#define RUN_MODE_BERR_AERR_RESET 1 + +#ifndef NULL +#define NULL ((void*)0) +#endif + +/* ======================================================================== */ +/* ================================ MACROS ================================ */ +/* ======================================================================== */ + + +/* ---------------------------- General Macros ---------------------------- */ + +/* Bit Isolation Macros */ +#define BIT_0(A) ((A) & 0x00000001) +#define BIT_1(A) ((A) & 0x00000002) +#define BIT_2(A) ((A) & 0x00000004) +#define BIT_3(A) ((A) & 0x00000008) +#define BIT_4(A) ((A) & 0x00000010) +#define BIT_5(A) ((A) & 0x00000020) +#define BIT_6(A) ((A) & 0x00000040) +#define BIT_7(A) ((A) & 0x00000080) +#define BIT_8(A) ((A) & 0x00000100) +#define BIT_9(A) ((A) & 0x00000200) +#define BIT_A(A) ((A) & 0x00000400) +#define BIT_B(A) ((A) & 0x00000800) +#define BIT_C(A) ((A) & 0x00001000) +#define BIT_D(A) ((A) & 0x00002000) +#define BIT_E(A) ((A) & 0x00004000) +#define BIT_F(A) ((A) & 0x00008000) +#define BIT_10(A) ((A) & 0x00010000) +#define BIT_11(A) ((A) & 0x00020000) +#define BIT_12(A) ((A) & 0x00040000) +#define BIT_13(A) ((A) & 0x00080000) +#define BIT_14(A) ((A) & 0x00100000) +#define BIT_15(A) ((A) & 0x00200000) +#define BIT_16(A) ((A) & 0x00400000) +#define BIT_17(A) ((A) & 0x00800000) +#define BIT_18(A) ((A) & 0x01000000) +#define BIT_19(A) ((A) & 0x02000000) +#define BIT_1A(A) ((A) & 0x04000000) +#define BIT_1B(A) ((A) & 0x08000000) +#define BIT_1C(A) ((A) & 0x10000000) +#define BIT_1D(A) ((A) & 0x20000000) +#define BIT_1E(A) ((A) & 0x40000000) +#define BIT_1F(A) ((A) & 0x80000000) + +/* Get the most significant bit for specific sizes */ +#define GET_MSB_8(A) ((A) & 0x80) +#define GET_MSB_9(A) ((A) & 0x100) +#define GET_MSB_16(A) ((A) & 0x8000) +#define GET_MSB_17(A) ((A) & 0x10000) +#define GET_MSB_32(A) ((A) & 0x80000000) +#if M68K_USE_64_BIT +#define GET_MSB_33(A) ((A) & 0x100000000) +#endif /* M68K_USE_64_BIT */ + +/* Isolate nibbles */ +#define LOW_NIBBLE(A) ((A) & 0x0f) +#define HIGH_NIBBLE(A) ((A) & 0xf0) + +/* These are used to isolate 8, 16, and 32 bit sizes */ +#define MASK_OUT_ABOVE_2(A) ((A) & 3) +#define MASK_OUT_ABOVE_8(A) ((A) & 0xff) +#define MASK_OUT_ABOVE_16(A) ((A) & 0xffff) +#define MASK_OUT_BELOW_2(A) ((A) & ~3) +#define MASK_OUT_BELOW_8(A) ((A) & ~0xff) +#define MASK_OUT_BELOW_16(A) ((A) & ~0xffff) + +/* No need to mask if we are 32 bit */ +#if M68K_INT_GT_32_BIT || M68K_USE_64_BIT + #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) + #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) +#else + #define MASK_OUT_ABOVE_32(A) (A) + #define MASK_OUT_BELOW_32(A) 0 +#endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */ + +/* Simulate address lines of 68k family */ +#define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK) + + +/* Shift & Rotate Macros. */ +#define LSL(A, C) ((A) << (C)) +#define LSR(A, C) ((A) >> (C)) + +/* Some > 32-bit optimizations */ +#if M68K_INT_GT_32_BIT + /* Shift left and right */ + #define LSR_32(A, C) ((A) >> (C)) + #define LSL_32(A, C) ((A) << (C)) +#else + /* We have to do this because the morons at ANSI decided that shifts + * by >= data size are undefined. + */ + #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) + #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) +#endif /* M68K_INT_GT_32_BIT */ + +#if M68K_USE_64_BIT + #define LSL_32_64(A, C) ((A) << (C)) + #define LSR_32_64(A, C) ((A) >> (C)) + #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C))) + #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C))) +#endif /* M68K_USE_64_BIT */ + +#define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C))) +#define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C))) +#define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C))) +#define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C))) +#define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C))) +#define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C))) + +#define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C))) +#define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C))) +#define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C))) +#define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C))) +#define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C))) +#define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C))) + + + +/* ------------------------------ CPU Access ------------------------------ */ + +/* Access the CPU registers */ +#define CPU_TYPE m68ki_cpu.cpu_type + +#define REG_DA m68ki_cpu.dar /* easy access to data and address regs */ +#define REG_D m68ki_cpu.dar +#define REG_A (m68ki_cpu.dar+8) +#define REG_PPC m68ki_cpu.ppc +#define REG_PC m68ki_cpu.pc +#define REG_SP_BASE m68ki_cpu.sp +#define REG_USP m68ki_cpu.sp[0] +#define REG_ISP m68ki_cpu.sp[4] +#define REG_MSP m68ki_cpu.sp[6] +#define REG_SP m68ki_cpu.dar[15] +#define REG_VBR m68ki_cpu.vbr +#define REG_SFC m68ki_cpu.sfc +#define REG_DFC m68ki_cpu.dfc +#define REG_CACR m68ki_cpu.cacr +#define REG_CAAR m68ki_cpu.caar +#define REG_IR m68ki_cpu.ir + +#define FLAG_T1 m68ki_cpu.t1_flag +#define FLAG_T0 m68ki_cpu.t0_flag +#define FLAG_S m68ki_cpu.s_flag +#define FLAG_M m68ki_cpu.m_flag +#define FLAG_X m68ki_cpu.x_flag +#define FLAG_N m68ki_cpu.n_flag +#define FLAG_Z m68ki_cpu.not_z_flag +#define FLAG_V m68ki_cpu.v_flag +#define FLAG_C m68ki_cpu.c_flag +#define FLAG_INT_MASK m68ki_cpu.int_mask + +#define CPU_INT_LEVEL m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */ +#define CPU_INT_CYCLES m68ki_cpu.int_cycles /* ASG */ +#define CPU_STOPPED m68ki_cpu.stopped +#define CPU_PREF_ADDR m68ki_cpu.pref_addr +#define CPU_PREF_DATA m68ki_cpu.pref_data +#define CPU_ADDRESS_MASK m68ki_cpu.address_mask +#define CPU_SR_MASK m68ki_cpu.sr_mask +#define CPU_INSTR_MODE m68ki_cpu.instr_mode +#define CPU_RUN_MODE m68ki_cpu.run_mode + +#define CYC_INSTRUCTION m68ki_cpu.cyc_instruction +#define CYC_EXCEPTION m68ki_cpu.cyc_exception +#define CYC_BCC_NOTAKE_B m68ki_cpu.cyc_bcc_notake_b +#define CYC_BCC_NOTAKE_W m68ki_cpu.cyc_bcc_notake_w +#define CYC_DBCC_F_NOEXP m68ki_cpu.cyc_dbcc_f_noexp +#define CYC_DBCC_F_EXP m68ki_cpu.cyc_dbcc_f_exp +#define CYC_SCC_R_TRUE m68ki_cpu.cyc_scc_r_true +#define CYC_MOVEM_W m68ki_cpu.cyc_movem_w +#define CYC_MOVEM_L m68ki_cpu.cyc_movem_l +#define CYC_SHIFT m68ki_cpu.cyc_shift +#define CYC_RESET m68ki_cpu.cyc_reset + + +#define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback +#define CALLBACK_BKPT_ACK m68ki_cpu.bkpt_ack_callback +#define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback +#define CALLBACK_CMPILD_INSTR m68ki_cpu.cmpild_instr_callback +#define CALLBACK_RTE_INSTR m68ki_cpu.rte_instr_callback +#define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback +#define CALLBACK_SET_FC m68ki_cpu.set_fc_callback +#define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback + + + +/* ----------------------------- Configuration ---------------------------- */ + +/* These defines are dependant on the configuration defines in m68kconf.h */ + +/* Disable certain comparisons if we're not using all CPU types */ +#if M68K_EMULATE_020 + #define CPU_TYPE_IS_020_PLUS(A) ((A) & CPU_TYPE_020) + #define CPU_TYPE_IS_020_LESS(A) 1 +#else + #define CPU_TYPE_IS_020_PLUS(A) 0 + #define CPU_TYPE_IS_020_LESS(A) 1 +#endif + +#if M68K_EMULATE_EC020 + #define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) + #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020)) +#else + #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A) + #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A) +#endif + +#if M68K_EMULATE_010 + #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010) + #define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020)) + #define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010)) +#else + #define CPU_TYPE_IS_010(A) 0 + #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A) + #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A) +#endif + +#if M68K_EMULATE_020 || M68K_EMULATE_EC020 + #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) +#else + #define CPU_TYPE_IS_020_VARIANT(A) 0 +#endif + +#if M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010 + #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000 || (A) == CPU_TYPE_008) +#else + #define CPU_TYPE_IS_000(A) 1 +#endif + + +#if !M68K_SEPARATE_READS +#define m68k_read_immediate_16(A) m68ki_read_program_16(A) +#define m68k_read_immediate_32(A) m68ki_read_program_32(A) + +#define m68k_read_pcrelative_8(A) m68ki_read_program_8(A) +#define m68k_read_pcrelative_16(A) m68ki_read_program_16(A) +#define m68k_read_pcrelative_32(A) m68ki_read_program_32(A) +#endif /* M68K_SEPARATE_READS */ + + +/* Enable or disable callback functions */ +#if M68K_EMULATE_INT_ACK + #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_int_ack(A) M68K_INT_ACK_CALLBACK(A) + #else + #define m68ki_int_ack(A) CALLBACK_INT_ACK(A) + #endif +#else + /* Default action is to used autovector mode, which is most common */ + #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR +#endif /* M68K_EMULATE_INT_ACK */ + +#if M68K_EMULATE_BKPT_ACK + #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A) + #else + #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A) + #endif +#else + #define m68ki_bkpt_ack(A) +#endif /* M68K_EMULATE_BKPT_ACK */ + +#if M68K_EMULATE_RESET + #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER + #define m68ki_output_reset() M68K_RESET_CALLBACK() + #else + #define m68ki_output_reset() CALLBACK_RESET_INSTR() + #endif +#else + #define m68ki_output_reset() +#endif /* M68K_EMULATE_RESET */ + +#if M68K_CMPILD_HAS_CALLBACK + #if M68K_CMPILD_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_cmpild_callback(v,r) M68K_CMPILD_CALLBACK(v,r) + #else + #define m68ki_cmpild_callback(v,r) CALLBACK_CMPILD_INSTR(v,r) + #endif +#else + #define m68ki_cmpild_callback(v,r) +#endif /* M68K_CMPILD_HAS_CALLBACK */ + +#if M68K_RTE_HAS_CALLBACK + #if M68K_RTE_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_rte_callback() M68K_RTE_CALLBACK() + #else + #define m68ki_rte_callback() CALLBACK_RTE_INSTR() + #endif +#else + #define m68ki_rte_callback() +#endif /* M68K_RTE_HAS_CALLBACK */ + +#if M68K_INSTRUCTION_HOOK + #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER + #define m68ki_instr_hook() M68K_INSTRUCTION_CALLBACK() + #else + #define m68ki_instr_hook() CALLBACK_INSTR_HOOK() + #endif +#else + #define m68ki_instr_hook() +#endif /* M68K_INSTRUCTION_HOOK */ + +#if M68K_MONITOR_PC + #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER + #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A)) + #else + #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A)) + #endif +#else + #define m68ki_pc_changed(A) +#endif /* M68K_MONITOR_PC */ + + +/* Enable or disable function code emulation */ +#if M68K_EMULATE_FC + #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER + #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A) + #else + #define m68ki_set_fc(A) CALLBACK_SET_FC(A) + #endif + #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA + #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM + #define m68ki_get_address_space() m68ki_address_space +#else + #define m68ki_set_fc(A) + #define m68ki_use_data_space() + #define m68ki_use_program_space() + #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA +#endif /* M68K_EMULATE_FC */ + + +/* Enable or disable trace emulation */ +#if M68K_EMULATE_TRACE + /* Initiates trace checking before each instruction (t1) */ + #define m68ki_trace_t1() m68ki_tracing = FLAG_T1 + /* adds t0 to trace checking if we encounter change of flow */ + #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0 + /* Clear all tracing */ + #define m68ki_clear_trace() m68ki_tracing = 0 + /* Cause a trace exception if we are tracing */ + #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace() +#else + #define m68ki_trace_t1() + #define m68ki_trace_t0() + #define m68ki_clear_trace() + #define m68ki_exception_if_trace() +#endif /* M68K_EMULATE_TRACE */ + + + +/* Address error */ +#if M68K_EMULATE_ADDRESS_ERROR + #include + extern jmp_buf m68ki_aerr_trap; + + #define m68ki_set_address_error_trap() \ + if(setjmp(m68ki_aerr_trap) != 0) \ + { \ + m68ki_exception_address_error(); \ + if(CPU_STOPPED) \ + { \ + SET_CYCLES(0); \ + CPU_INT_CYCLES = 0; \ + return m68ki_initial_cycles; \ + } \ + } + + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ + if((ADDR)&1) \ + { \ + m68ki_aerr_address = ADDR; \ + m68ki_aerr_write_mode = WRITE_MODE; \ + m68ki_aerr_fc = FC; \ + longjmp(m68ki_aerr_trap, 1); \ + } +#else + #define m68ki_set_address_error_trap() + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) +#endif /* M68K_ADDRESS_ERROR */ + +/* Logging */ +#if M68K_LOG_ENABLE + #include + extern FILE* M68K_LOG_FILEHANDLE + extern char* m68ki_cpu_names[]; + + #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A + #if M68K_LOG_1010_1111 + #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A + #else + #define M68K_DO_LOG_EMU(A) + #endif +#else + #define M68K_DO_LOG(A) + #define M68K_DO_LOG_EMU(A) +#endif + + + +/* -------------------------- EA / Operand Access ------------------------- */ + +/* + * The general instruction format follows this pattern: + * .... XXX. .... .YYY + * where XXX is register X and YYY is register Y + */ +/* Data Register Isolation */ +#define DX (REG_D[(REG_IR >> 9) & 7]) +#define DY (REG_D[REG_IR & 7]) +/* Address Register Isolation */ +#define AX (REG_A[(REG_IR >> 9) & 7]) +#define AY (REG_A[REG_IR & 7]) + + +/* Effective Address Calculations */ +#define EA_AY_AI_8() AY /* address register indirect */ +#define EA_AY_AI_16() EA_AY_AI_8() +#define EA_AY_AI_32() EA_AY_AI_8() +#define EA_AY_PI_8() (AY++) /* postincrement (size = byte) */ +#define EA_AY_PI_16() ((AY+=2)-2) /* postincrement (size = word) */ +#define EA_AY_PI_32() ((AY+=4)-4) /* postincrement (size = long) */ +#define EA_AY_PD_8() (--AY) /* predecrement (size = byte) */ +#define EA_AY_PD_16() (AY-=2) /* predecrement (size = word) */ +#define EA_AY_PD_32() (AY-=4) /* predecrement (size = long) */ +#define EA_AY_DI_8() (AY+MAKE_INT_16(m68ki_read_imm_16())) /* displacement */ +#define EA_AY_DI_16() EA_AY_DI_8() +#define EA_AY_DI_32() EA_AY_DI_8() +#define EA_AY_IX_8() m68ki_get_ea_ix(AY) /* indirect + index */ +#define EA_AY_IX_16() EA_AY_IX_8() +#define EA_AY_IX_32() EA_AY_IX_8() + +#define EA_AX_AI_8() AX +#define EA_AX_AI_16() EA_AX_AI_8() +#define EA_AX_AI_32() EA_AX_AI_8() +#define EA_AX_PI_8() (AX++) +#define EA_AX_PI_16() ((AX+=2)-2) +#define EA_AX_PI_32() ((AX+=4)-4) +#define EA_AX_PD_8() (--AX) +#define EA_AX_PD_16() (AX-=2) +#define EA_AX_PD_32() (AX-=4) +#define EA_AX_DI_8() (AX+MAKE_INT_16(m68ki_read_imm_16())) +#define EA_AX_DI_16() EA_AX_DI_8() +#define EA_AX_DI_32() EA_AX_DI_8() +#define EA_AX_IX_8() m68ki_get_ea_ix(AX) +#define EA_AX_IX_16() EA_AX_IX_8() +#define EA_AX_IX_32() EA_AX_IX_8() + +#define EA_A7_PI_8() ((REG_A[7]+=2)-2) +#define EA_A7_PD_8() (REG_A[7]-=2) + +#define EA_AW_8() MAKE_INT_16(m68ki_read_imm_16()) /* absolute word */ +#define EA_AW_16() EA_AW_8() +#define EA_AW_32() EA_AW_8() +#define EA_AL_8() m68ki_read_imm_32() /* absolute long */ +#define EA_AL_16() EA_AL_8() +#define EA_AL_32() EA_AL_8() +#define EA_PCDI_8() m68ki_get_ea_pcdi() /* pc indirect + displacement */ +#define EA_PCDI_16() EA_PCDI_8() +#define EA_PCDI_32() EA_PCDI_8() +#define EA_PCIX_8() m68ki_get_ea_pcix() /* pc indirect + index */ +#define EA_PCIX_16() EA_PCIX_8() +#define EA_PCIX_32() EA_PCIX_8() + + +#define OPER_I_8() m68ki_read_imm_8() +#define OPER_I_16() m68ki_read_imm_16() +#define OPER_I_32() m68ki_read_imm_32() + + + +/* --------------------------- Status Register ---------------------------- */ + +/* Flag Calculation Macros */ +#define CFLAG_8(A) (A) +#define CFLAG_16(A) ((A)>>8) + +#if M68K_INT_GT_32_BIT + #define CFLAG_ADD_32(S, D, R) ((R)>>24) + #define CFLAG_SUB_32(S, D, R) ((R)>>24) +#else + #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23) + #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23) +#endif /* M68K_INT_GT_32_BIT */ + +#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R)) +#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8) +#define VFLAG_ADD_32(S, D, R) (((S^R) & (D^R))>>24) + +#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D)) +#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8) +#define VFLAG_SUB_32(S, D, R) (((S^D) & (R^D))>>24) + +#define NFLAG_8(A) (A) +#define NFLAG_16(A) ((A)>>8) +#define NFLAG_32(A) ((A)>>24) +#define NFLAG_64(A) ((A)>>56) + +#define ZFLAG_8(A) MASK_OUT_ABOVE_8(A) +#define ZFLAG_16(A) MASK_OUT_ABOVE_16(A) +#define ZFLAG_32(A) MASK_OUT_ABOVE_32(A) + + +/* Flag values */ +#define NFLAG_SET 0x80 +#define NFLAG_CLEAR 0 +#define CFLAG_SET 0x100 +#define CFLAG_CLEAR 0 +#define XFLAG_SET 0x100 +#define XFLAG_CLEAR 0 +#define VFLAG_SET 0x80 +#define VFLAG_CLEAR 0 +#define ZFLAG_SET 0 +#define ZFLAG_CLEAR 0xffffffff + +#define SFLAG_SET 4 +#define SFLAG_CLEAR 0 +#define MFLAG_SET 2 +#define MFLAG_CLEAR 0 + +/* Turn flag values into 1 or 0 */ +#define XFLAG_AS_1() ((FLAG_X>>8)&1) +#define NFLAG_AS_1() ((FLAG_N>>7)&1) +#define VFLAG_AS_1() ((FLAG_V>>7)&1) +#define ZFLAG_AS_1() (!FLAG_Z) +#define CFLAG_AS_1() ((FLAG_C>>8)&1) + + +/* Conditions */ +#define COND_CS() (FLAG_C&0x100) +#define COND_CC() (!COND_CS()) +#define COND_VS() (FLAG_V&0x80) +#define COND_VC() (!COND_VS()) +#define COND_NE() FLAG_Z +#define COND_EQ() (!COND_NE()) +#define COND_MI() (FLAG_N&0x80) +#define COND_PL() (!COND_MI()) +#define COND_LT() ((FLAG_N^FLAG_V)&0x80) +#define COND_GE() (!COND_LT()) +#define COND_HI() (COND_CC() && COND_NE()) +#define COND_LS() (COND_CS() || COND_EQ()) +#define COND_GT() (COND_GE() && COND_NE()) +#define COND_LE() (COND_LT() || COND_EQ()) + +/* Reversed conditions */ +#define COND_NOT_CS() COND_CC() +#define COND_NOT_CC() COND_CS() +#define COND_NOT_VS() COND_VC() +#define COND_NOT_VC() COND_VS() +#define COND_NOT_NE() COND_EQ() +#define COND_NOT_EQ() COND_NE() +#define COND_NOT_MI() COND_PL() +#define COND_NOT_PL() COND_MI() +#define COND_NOT_LT() COND_GE() +#define COND_NOT_GE() COND_LT() +#define COND_NOT_HI() COND_LS() +#define COND_NOT_LS() COND_HI() +#define COND_NOT_GT() COND_LE() +#define COND_NOT_LE() COND_GT() + +/* Not real conditions, but here for convenience */ +#define COND_XS() (FLAG_X&0x100) +#define COND_XC() (!COND_XS) + + +/* Get the condition code register */ +#define m68ki_get_ccr() ((COND_XS() >> 4) | \ + (COND_MI() >> 4) | \ + (COND_EQ() << 2) | \ + (COND_VS() >> 6) | \ + (COND_CS() >> 8)) + +/* Get the status register */ +#define m68ki_get_sr() ( FLAG_T1 | \ + FLAG_T0 | \ + (FLAG_S << 11) | \ + (FLAG_M << 11) | \ + FLAG_INT_MASK | \ + m68ki_get_ccr()) + + + +/* ---------------------------- Cycle Counting ---------------------------- */ + +#define ADD_CYCLES(A) m68ki_remaining_cycles += (A) +#define USE_CYCLES(A) m68ki_remaining_cycles -= (A) +#define SET_CYCLES(A) m68ki_remaining_cycles = A +#define GET_CYCLES() m68ki_remaining_cycles +#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0 + + + +/* ----------------------------- Read / Write ----------------------------- */ + +/* Read from the current address space */ +#define m68ki_read_8(A) m68ki_read_8_fc (A, FLAG_S | m68ki_get_address_space()) +#define m68ki_read_16(A) m68ki_read_16_fc(A, FLAG_S | m68ki_get_address_space()) +#define m68ki_read_32(A) m68ki_read_32_fc(A, FLAG_S | m68ki_get_address_space()) + +/* Write to the current data space */ +#define m68ki_write_8(A, V) m68ki_write_8_fc (A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#define m68ki_write_16(A, V) m68ki_write_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#define m68ki_write_32(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) + +#if M68K_SIMULATE_PD_WRITES +#define m68ki_write_32_pd(A, V) m68ki_write_32_pd_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#else +#define m68ki_write_32_pd(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) +#endif + +/* map read immediate 8 to read immediate 16 */ +#define m68ki_read_imm_8() MASK_OUT_ABOVE_8(m68ki_read_imm_16()) + +/* Map PC-relative reads */ +#define m68ki_read_pcrel_8(A) m68k_read_pcrelative_8(A) +#define m68ki_read_pcrel_16(A) m68k_read_pcrelative_16(A) +#define m68ki_read_pcrel_32(A) m68k_read_pcrelative_32(A) + +/* Read from the program space */ +#define m68ki_read_program_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) + +/* Read from the data space */ +#define m68ki_read_data_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) + + + +/* ======================================================================== */ +/* =============================== PROTOTYPES ============================= */ +/* ======================================================================== */ + +typedef struct +{ + uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, or 68020 */ + uint dar[16]; /* Data and Address Registers */ + uint ppc; /* Previous program counter */ + uint pc; /* Program Counter */ + uint sp[7]; /* User, Interrupt, and Master Stack Pointers */ + uint vbr; /* Vector Base Register (m68010+) */ + uint sfc; /* Source Function Code Register (m68010+) */ + uint dfc; /* Destination Function Code Register (m68010+) */ + uint cacr; /* Cache Control Register (m68020, unemulated) */ + uint caar; /* Cache Address Register (m68020, unemulated) */ + uint ir; /* Instruction Register */ + uint t1_flag; /* Trace 1 */ + uint t0_flag; /* Trace 0 */ + uint s_flag; /* Supervisor */ + uint m_flag; /* Master/Interrupt state */ + uint x_flag; /* Extend */ + uint n_flag; /* Negative */ + uint not_z_flag; /* Zero, inverted for speedups */ + uint v_flag; /* Overflow */ + uint c_flag; /* Carry */ + uint int_mask; /* I0-I2 */ + uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ + uint int_cycles; /* ASG: extra cycles from generated interrupts */ + uint stopped; /* Stopped state */ + uint pref_addr; /* Last prefetch address */ + uint pref_data; /* Data in the prefetch queue */ + uint address_mask; /* Available address pins */ + uint sr_mask; /* Implemented status register bits */ + uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ + uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ + + /* Clocks required for instructions / exceptions */ + uint cyc_bcc_notake_b; + uint cyc_bcc_notake_w; + uint cyc_dbcc_f_noexp; + uint cyc_dbcc_f_exp; + uint cyc_scc_r_true; + uint cyc_movem_w; + uint cyc_movem_l; + uint cyc_shift; + uint cyc_reset; + uint8* cyc_instruction; + uint8* cyc_exception; + + /* Callbacks to host */ + int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ + void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */ + void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ + void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */ + void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */ + void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */ + void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ + void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */ + +} m68ki_cpu_core; + + +extern m68ki_cpu_core m68ki_cpu; +extern sint m68ki_remaining_cycles; +extern uint m68ki_tracing; +extern uint8 m68ki_shift_8_table[]; +extern uint16 m68ki_shift_16_table[]; +extern uint m68ki_shift_32_table[]; +extern uint8 m68ki_exception_cycle_table[][256]; +extern uint m68ki_address_space; +extern uint8 m68ki_ea_idx_cycle_table[]; + +extern uint m68ki_aerr_address; +extern uint m68ki_aerr_write_mode; +extern uint m68ki_aerr_fc; + +/* Read data immediately after the program counter */ +INLINE uint m68ki_read_imm_16(void); +INLINE uint m68ki_read_imm_32(void); + +/* Read data with specific function code */ +INLINE uint m68ki_read_8_fc (uint address, uint fc); +INLINE uint m68ki_read_16_fc (uint address, uint fc); +INLINE uint m68ki_read_32_fc (uint address, uint fc); + +/* Write data with specific function code */ +INLINE void m68ki_write_8_fc (uint address, uint fc, uint value); +INLINE void m68ki_write_16_fc(uint address, uint fc, uint value); +INLINE void m68ki_write_32_fc(uint address, uint fc, uint value); +#if M68K_SIMULATE_PD_WRITES +INLINE void m68ki_write_32_pd_fc(uint address, uint fc, uint value); +#endif /* M68K_SIMULATE_PD_WRITES */ + +/* Indexed and PC-relative ea fetching */ +INLINE uint m68ki_get_ea_pcdi(void); +INLINE uint m68ki_get_ea_pcix(void); +INLINE uint m68ki_get_ea_ix(uint An); + +/* Operand fetching */ +INLINE uint OPER_AY_AI_8(void); +INLINE uint OPER_AY_AI_16(void); +INLINE uint OPER_AY_AI_32(void); +INLINE uint OPER_AY_PI_8(void); +INLINE uint OPER_AY_PI_16(void); +INLINE uint OPER_AY_PI_32(void); +INLINE uint OPER_AY_PD_8(void); +INLINE uint OPER_AY_PD_16(void); +INLINE uint OPER_AY_PD_32(void); +INLINE uint OPER_AY_DI_8(void); +INLINE uint OPER_AY_DI_16(void); +INLINE uint OPER_AY_DI_32(void); +INLINE uint OPER_AY_IX_8(void); +INLINE uint OPER_AY_IX_16(void); +INLINE uint OPER_AY_IX_32(void); + +INLINE uint OPER_AX_AI_8(void); +INLINE uint OPER_AX_AI_16(void); +INLINE uint OPER_AX_AI_32(void); +INLINE uint OPER_AX_PI_8(void); +INLINE uint OPER_AX_PI_16(void); +INLINE uint OPER_AX_PI_32(void); +INLINE uint OPER_AX_PD_8(void); +INLINE uint OPER_AX_PD_16(void); +INLINE uint OPER_AX_PD_32(void); +INLINE uint OPER_AX_DI_8(void); +INLINE uint OPER_AX_DI_16(void); +INLINE uint OPER_AX_DI_32(void); +INLINE uint OPER_AX_IX_8(void); +INLINE uint OPER_AX_IX_16(void); +INLINE uint OPER_AX_IX_32(void); + +INLINE uint OPER_A7_PI_8(void); +INLINE uint OPER_A7_PD_8(void); + +INLINE uint OPER_AW_8(void); +INLINE uint OPER_AW_16(void); +INLINE uint OPER_AW_32(void); +INLINE uint OPER_AL_8(void); +INLINE uint OPER_AL_16(void); +INLINE uint OPER_AL_32(void); +INLINE uint OPER_PCDI_8(void); +INLINE uint OPER_PCDI_16(void); +INLINE uint OPER_PCDI_32(void); +INLINE uint OPER_PCIX_8(void); +INLINE uint OPER_PCIX_16(void); +INLINE uint OPER_PCIX_32(void); + +/* Stack operations */ +INLINE void m68ki_push_16(uint value); +INLINE void m68ki_push_32(uint value); +INLINE uint m68ki_pull_16(void); +INLINE uint m68ki_pull_32(void); + +/* Program flow operations */ +INLINE void m68ki_jump(uint new_pc); +INLINE void m68ki_jump_vector(uint vector); +INLINE void m68ki_branch_8(uint offset); +INLINE void m68ki_branch_16(uint offset); +INLINE void m68ki_branch_32(uint offset); + +/* Status register operations. */ +INLINE void m68ki_set_s_flag(uint value); /* Only bit 2 of value should be set (i.e. 4 or 0) */ +INLINE void m68ki_set_sm_flag(uint value); /* only bits 1 and 2 of value should be set */ +INLINE void m68ki_set_ccr(uint value); /* set the condition code register */ +INLINE void m68ki_set_sr(uint value); /* set the status register */ +INLINE void m68ki_set_sr_noint(uint value); /* set the status register */ + +/* Exception processing */ +INLINE uint m68ki_init_exception(void); /* Initial exception processing */ + +INLINE void m68ki_stack_frame_3word(uint pc, uint sr); /* Stack various frame types */ +INLINE void m68ki_stack_frame_buserr(uint sr); + +INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_0001(uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_0010(uint sr, uint vector); +INLINE void m68ki_stack_frame_1000(uint pc, uint sr, uint vector); +INLINE void m68ki_stack_frame_1010(uint sr, uint vector, uint pc); +INLINE void m68ki_stack_frame_1011(uint sr, uint vector, uint pc); + +INLINE void m68ki_exception_trap(uint vector); +INLINE void m68ki_exception_trapN(uint vector); +INLINE void m68ki_exception_trace(void); +INLINE void m68ki_exception_privilege_violation(void); +INLINE void m68ki_exception_1010(void); +INLINE void m68ki_exception_1111(void); +INLINE void m68ki_exception_illegal(void); +INLINE void m68ki_exception_format_error(void); +INLINE void m68ki_exception_address_error(void); +INLINE void m68ki_exception_interrupt(uint int_level); +INLINE void m68ki_check_interrupts(void); /* ASG: check for interrupts */ + +/* quick disassembly (used for logging) */ +char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type); + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + + +/* ---------------------------- Read Immediate ---------------------------- */ + +/* Handles all immediate reads, does address error check, function code setting, + * and prefetching if they are enabled in m68kconf.h + */ +INLINE uint m68ki_read_imm_16(void) +{ + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ +#if M68K_EMULATE_PREFETCH + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + } + REG_PC += 2; + return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3)); +#else + REG_PC += 2; + return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2)); +#endif /* M68K_EMULATE_PREFETCH */ +} +INLINE uint m68ki_read_imm_32(void) +{ +#if M68K_EMULATE_PREFETCH + uint temp_val; + + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + } + temp_val = CPU_PREF_DATA; + REG_PC += 2; + if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC); + CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR)); + temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16)); + } + REG_PC += 2; + + return temp_val; +#else + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + REG_PC += 4; + return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4)); +#endif /* M68K_EMULATE_PREFETCH */ +} + + + +/* ------------------------- Top level read/write ------------------------- */ + +/* Handles all memory accesses (except for immediate reads if they are + * configured to use separate functions in m68kconf.h). + * All memory accesses must go through these top level functions. + * These functions will also check for address error and set the function + * code if they are enabled in m68kconf.h. + */ +INLINE uint m68ki_read_8_fc(uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_8(ADDRESS_68K(address)); +} +INLINE uint m68ki_read_16_fc(uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_16(ADDRESS_68K(address)); +} +INLINE uint m68ki_read_32_fc(uint address, uint fc) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + return m68k_read_memory_32(ADDRESS_68K(address)); +} + +INLINE void m68ki_write_8_fc(uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_8(ADDRESS_68K(address), value); +} +INLINE void m68ki_write_16_fc(uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_16(ADDRESS_68K(address), value); +} +INLINE void m68ki_write_32_fc(uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_32(ADDRESS_68K(address), value); +} + +#if M68K_SIMULATE_PD_WRITES +INLINE void m68ki_write_32_pd_fc(uint address, uint fc, uint value) +{ + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + m68k_write_memory_32_pd(ADDRESS_68K(address), value); +} +#endif + + +/* --------------------- Effective Address Calculation -------------------- */ + +/* The program counter relative addressing modes cause operands to be + * retrieved from program space, not data space. + */ +INLINE uint m68ki_get_ea_pcdi(void) +{ + uint old_pc = REG_PC; + m68ki_use_program_space(); /* auto-disable */ + return old_pc + MAKE_INT_16(m68ki_read_imm_16()); +} + + +INLINE uint m68ki_get_ea_pcix(void) +{ + m68ki_use_program_space(); /* auto-disable */ + return m68ki_get_ea_ix(REG_PC); +} + +/* Indexed addressing modes are encoded as follows: + * + * Base instruction format: + * F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 + * x x x x x x x x x x | 1 1 0 | BASE REGISTER (An) + * + * Base instruction format for destination EA in move instructions: + * F E D C | B A 9 | 8 7 6 | 5 4 3 2 1 0 + * x x x x | BASE REG | 1 1 0 | X X X X X X (An) + * + * Brief extension format: + * F | E D C | B | A 9 | 8 | 7 6 5 4 3 2 1 0 + * D/A | REGISTER | W/L | SCALE | 0 | DISPLACEMENT + * + * Full extension format: + * F E D C B A 9 8 7 6 5 4 3 2 1 0 + * D/A | REGISTER | W/L | SCALE | 1 | BS | IS | BD SIZE | 0 | I/IS + * BASE DISPLACEMENT (0, 16, 32 bit) (bd) + * OUTER DISPLACEMENT (0, 16, 32 bit) (od) + * + * D/A: 0 = Dn, 1 = An (Xn) + * W/L: 0 = W (sign extend), 1 = L (.SIZE) + * SCALE: 00=1, 01=2, 10=4, 11=8 (*SCALE) + * BS: 0=add base reg, 1=suppress base reg (An suppressed) + * IS: 0=add index, 1=suppress index (Xn suppressed) + * BD SIZE: 00=reserved, 01=NULL, 10=Word, 11=Long (size of bd) + * + * IS I/IS Operation + * 0 000 No Memory Indirect + * 0 001 indir prex with null outer + * 0 010 indir prex with word outer + * 0 011 indir prex with long outer + * 0 100 reserved + * 0 101 indir postx with null outer + * 0 110 indir postx with word outer + * 0 111 indir postx with long outer + * 1 000 no memory indirect + * 1 001 mem indir with null outer + * 1 010 mem indir with word outer + * 1 011 mem indir with long outer + * 1 100-111 reserved + */ +INLINE uint m68ki_get_ea_ix(uint An) +{ + /* An = base register */ + uint extension = m68ki_read_imm_16(); + uint Xn = 0; /* Index register */ + uint bd = 0; /* Base Displacement */ + uint od = 0; /* Outer Displacement */ + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } + + /* Brief extension format */ + if(!BIT_8(extension)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + /* Add scale if proper CPU type */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + Xn <<= (extension>>9) & 3; /* SCALE */ + + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } + + /* Full extension format */ + + USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]); + + /* Check if base register is present */ + if(BIT_7(extension)) /* BS */ + An = 0; /* An */ + + /* Check if index is present */ + if(!BIT_6(extension)) /* IS */ + { + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + Xn <<= (extension>>9) & 3; /* SCALE */ + } + + /* Check if base displacement is present */ + if(BIT_5(extension)) /* BD SIZE */ + bd = BIT_4(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); + + /* If no indirect action, we are done */ + if(!(extension&7)) /* No Memory Indirect */ + return An + bd + Xn; + + /* Check if outer displacement is present */ + if(BIT_1(extension)) /* I/IS: od */ + od = BIT_0(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); + + /* Postindex */ + if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */ + return m68ki_read_32(An + bd) + Xn + od; + + /* Preindex */ + return m68ki_read_32(An + bd + Xn) + od; +} + + +/* Fetch operands */ +INLINE uint OPER_AY_AI_8(void) {uint ea = EA_AY_AI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_AI_16(void) {uint ea = EA_AY_AI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_AI_32(void) {uint ea = EA_AY_AI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_PI_8(void) {uint ea = EA_AY_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_PI_16(void) {uint ea = EA_AY_PI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_PI_32(void) {uint ea = EA_AY_PI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_PD_8(void) {uint ea = EA_AY_PD_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_PD_16(void) {uint ea = EA_AY_PD_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_PD_32(void) {uint ea = EA_AY_PD_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_DI_8(void) {uint ea = EA_AY_DI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_DI_16(void) {uint ea = EA_AY_DI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_DI_32(void) {uint ea = EA_AY_DI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AY_IX_8(void) {uint ea = EA_AY_IX_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AY_IX_16(void) {uint ea = EA_AY_IX_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AY_IX_32(void) {uint ea = EA_AY_IX_32(); return m68ki_read_32(ea);} + +INLINE uint OPER_AX_AI_8(void) {uint ea = EA_AX_AI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_AI_16(void) {uint ea = EA_AX_AI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_AI_32(void) {uint ea = EA_AX_AI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_PI_8(void) {uint ea = EA_AX_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_PI_16(void) {uint ea = EA_AX_PI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_PI_32(void) {uint ea = EA_AX_PI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_PD_8(void) {uint ea = EA_AX_PD_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_PD_16(void) {uint ea = EA_AX_PD_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_PD_32(void) {uint ea = EA_AX_PD_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_DI_8(void) {uint ea = EA_AX_DI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_DI_16(void) {uint ea = EA_AX_DI_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_DI_32(void) {uint ea = EA_AX_DI_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AX_IX_8(void) {uint ea = EA_AX_IX_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AX_IX_16(void) {uint ea = EA_AX_IX_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AX_IX_32(void) {uint ea = EA_AX_IX_32(); return m68ki_read_32(ea);} + +INLINE uint OPER_A7_PI_8(void) {uint ea = EA_A7_PI_8(); return m68ki_read_8(ea); } +INLINE uint OPER_A7_PD_8(void) {uint ea = EA_A7_PD_8(); return m68ki_read_8(ea); } + +INLINE uint OPER_AW_8(void) {uint ea = EA_AW_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AW_16(void) {uint ea = EA_AW_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AW_32(void) {uint ea = EA_AW_32(); return m68ki_read_32(ea);} +INLINE uint OPER_AL_8(void) {uint ea = EA_AL_8(); return m68ki_read_8(ea); } +INLINE uint OPER_AL_16(void) {uint ea = EA_AL_16(); return m68ki_read_16(ea);} +INLINE uint OPER_AL_32(void) {uint ea = EA_AL_32(); return m68ki_read_32(ea);} +INLINE uint OPER_PCDI_8(void) {uint ea = EA_PCDI_8(); return m68ki_read_pcrel_8(ea); } +INLINE uint OPER_PCDI_16(void) {uint ea = EA_PCDI_16(); return m68ki_read_pcrel_16(ea);} +INLINE uint OPER_PCDI_32(void) {uint ea = EA_PCDI_32(); return m68ki_read_pcrel_32(ea);} +INLINE uint OPER_PCIX_8(void) {uint ea = EA_PCIX_8(); return m68ki_read_pcrel_8(ea); } +INLINE uint OPER_PCIX_16(void) {uint ea = EA_PCIX_16(); return m68ki_read_pcrel_16(ea);} +INLINE uint OPER_PCIX_32(void) {uint ea = EA_PCIX_32(); return m68ki_read_pcrel_32(ea);} + + + +/* ---------------------------- Stack Functions --------------------------- */ + +/* Push/pull data from the stack */ +INLINE void m68ki_push_16(uint value) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); + m68ki_write_16(REG_SP, value); +} + +INLINE void m68ki_push_32(uint value) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); + m68ki_write_32(REG_SP, value); +} + +INLINE uint m68ki_pull_16(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); + return m68ki_read_16(REG_SP-2); +} + +INLINE uint m68ki_pull_32(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); + return m68ki_read_32(REG_SP-4); +} + + +/* Increment/decrement the stack as if doing a push/pull but + * don't do any memory access. + */ +INLINE void m68ki_fake_push_16(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); +} + +INLINE void m68ki_fake_push_32(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); +} + +INLINE void m68ki_fake_pull_16(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); +} + +INLINE void m68ki_fake_pull_32(void) +{ + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); +} + + +/* ----------------------------- Program Flow ----------------------------- */ + +/* Jump to a new program location or vector. + * These functions will also call the pc_changed callback if it was enabled + * in m68kconf.h. + */ +INLINE void m68ki_jump(uint new_pc) +{ + REG_PC = new_pc; + m68ki_pc_changed(REG_PC); +} + +INLINE void m68ki_jump_vector(uint vector) +{ + REG_PC = (vector<<2) + REG_VBR; + REG_PC = m68ki_read_data_32(REG_PC); + m68ki_pc_changed(REG_PC); +} + + +/* Branch to a new memory location. + * The 32-bit branch will call pc_changed if it was enabled in m68kconf.h. + * So far I've found no problems with not calling pc_changed for 8 or 16 + * bit branches. + */ +INLINE void m68ki_branch_8(uint offset) +{ + REG_PC += MAKE_INT_8(offset); +} + +INLINE void m68ki_branch_16(uint offset) +{ + REG_PC += MAKE_INT_16(offset); +} + +INLINE void m68ki_branch_32(uint offset) +{ + REG_PC += offset; + m68ki_pc_changed(REG_PC); +} + + + +/* ---------------------------- Status Register --------------------------- */ + +/* Set the S flag and change the active stack pointer. + * Note that value MUST be 4 or 0. + */ +INLINE void m68ki_set_s_flag(uint value) +{ + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S flag */ + FLAG_S = value; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; +} + +/* Set the S and M flags and change the active stack pointer. + * Note that value MUST be 0, 2, 4, or 6 (bit2 = S, bit1 = M). + */ +INLINE void m68ki_set_sm_flag(uint value) +{ + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; +} + +/* Set the S and M flags. Don't touch the stack pointer. */ +INLINE void m68ki_set_sm_flag_nosp(uint value) +{ + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; +} + + +/* Set the condition code register */ +INLINE void m68ki_set_ccr(uint value) +{ + FLAG_X = BIT_4(value) << 4; + FLAG_N = BIT_3(value) << 4; + FLAG_Z = !BIT_2(value); + FLAG_V = BIT_1(value) << 6; + FLAG_C = BIT_0(value) << 8; +} + +/* Set the status register but don't check for interrupts */ +INLINE void m68ki_set_sr_noint(uint value) +{ + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; + + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(value); + m68ki_set_sm_flag((value >> 11) & 6); +} + +/* Set the status register but don't check for interrupts nor + * change the stack pointer + */ +INLINE void m68ki_set_sr_noint_nosp(uint value) +{ + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; + + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(value); + m68ki_set_sm_flag_nosp((value >> 11) & 6); +} + +/* Set the status register and check for interrupts */ +INLINE void m68ki_set_sr(uint value) +{ + m68ki_set_sr_noint(value); + m68ki_check_interrupts(); +} + + +/* ------------------------- Exception Processing ------------------------- */ + +/* Initiate exception processing */ +INLINE uint m68ki_init_exception(void) +{ + /* Save the old status register */ + uint sr = m68ki_get_sr(); + + /* Turn off trace flag, clear pending traces */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Enter supervisor mode */ + m68ki_set_s_flag(SFLAG_SET); + + return sr; +} + +/* 3 word stack frame (68000 only) */ +INLINE void m68ki_stack_frame_3word(uint pc, uint sr) +{ + m68ki_push_32(pc); + m68ki_push_16(sr); +} + +/* Format 0 stack frame. + * This is the standard stack frame for 68010+. + */ +INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector) +{ + /* Stack a 3-word frame if we are 68000 */ + if(CPU_TYPE == CPU_TYPE_000 || CPU_TYPE == CPU_TYPE_008) + { + m68ki_stack_frame_3word(pc, sr); + return; + } + m68ki_push_16(vector<<2); + m68ki_push_32(pc); + m68ki_push_16(sr); +} + +/* Format 1 stack frame (68020). + * For 68020, this is the 4 word throwaway frame. + */ +INLINE void m68ki_stack_frame_0001(uint pc, uint sr, uint vector) +{ + m68ki_push_16(0x1000 | (vector<<2)); + m68ki_push_32(pc); + m68ki_push_16(sr); +} + +/* Format 2 stack frame. + * This is used only by 68020 for trap exceptions. + */ +INLINE void m68ki_stack_frame_0010(uint sr, uint vector) +{ + m68ki_push_32(REG_PPC); + m68ki_push_16(0x2000 | (vector<<2)); + m68ki_push_32(REG_PC); + m68ki_push_16(sr); +} + + +/* Bus error stack frame (68000 only). + */ +INLINE void m68ki_stack_frame_buserr(uint sr) +{ + m68ki_push_32(REG_PC); + m68ki_push_16(sr); + m68ki_push_16(REG_IR); + m68ki_push_32(m68ki_aerr_address); /* access address */ + /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC + * R/W 0 = write, 1 = read + * I/N 0 = instruction, 1 = not + * FC 3-bit function code + */ + m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc); +} + +/* Format 8 stack frame (68010). + * 68010 only. This is the 29 word bus/address error frame. + */ +void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) +{ + /* VERSION + * NUMBER + * INTERNAL INFORMATION, 16 WORDS + */ + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + + /* INSTRUCTION INPUT BUFFER */ + m68ki_push_16(0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); + + /* DATA INPUT BUFFER */ + m68ki_push_16(0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); + + /* DATA OUTPUT BUFFER */ + m68ki_push_16(0); + + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); + + /* FAULT ADDRESS */ + m68ki_push_32(0); + + /* SPECIAL STATUS WORD */ + m68ki_push_16(0); + + /* 1000, VECTOR OFFSET */ + m68ki_push_16(0x8000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(pc); + + /* STATUS REGISTER */ + m68ki_push_16(sr); +} + +/* Format A stack frame (short bus fault). + * This is used only by 68020 for bus fault and address error + * if the error happens at an instruction boundary. + * PC stacked is address of next instruction. + */ +void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) +{ + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(0); + + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(0); + + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(0); + + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* 1010, VECTOR OFFSET */ + m68ki_push_16(0xa000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(pc); + + /* STATUS REGISTER */ + m68ki_push_16(sr); +} + +/* Format B stack frame (long bus fault). + * This is used only by 68020 for bus fault and address error + * if the error happens during instruction execution. + * PC stacked is address of instruction in progress. + */ +void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) +{ + /* INTERNAL REGISTERS (18 words) */ + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + + /* VERSION# (4 bits), INTERNAL INFORMATION */ + m68ki_push_16(0); + + /* INTERNAL REGISTERS (3 words) */ + m68ki_push_32(0); + m68ki_push_16(0); + + /* DATA INTPUT BUFFER (2 words) */ + m68ki_push_32(0); + + /* INTERNAL REGISTERS (2 words) */ + m68ki_push_32(0); + + /* STAGE B ADDRESS (2 words) */ + m68ki_push_32(0); + + /* INTERNAL REGISTER (4 words) */ + m68ki_push_32(0); + m68ki_push_32(0); + + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(0); + + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(0); + + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(0); + + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(0); + + /* INTERNAL REGISTER */ + m68ki_push_16(0); + + /* 1011, VECTOR OFFSET */ + m68ki_push_16(0xb000 | (vector<<2)); + + /* PROGRAM COUNTER */ + m68ki_push_32(pc); + + /* STATUS REGISTER */ + m68ki_push_16(sr); +} + + +/* Used for Group 2 exceptions. + * These stack a type 2 frame on the 020. + */ +INLINE void m68ki_exception_trap(uint vector) +{ + uint sr = m68ki_init_exception(); + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + m68ki_stack_frame_0000(REG_PC, sr, vector); + else + m68ki_stack_frame_0010(sr, vector); + + m68ki_jump_vector(vector); + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[vector]); +} + +/* Trap#n stacks a 0 frame but behaves like group2 otherwise */ +INLINE void m68ki_exception_trapN(uint vector) +{ + uint sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PC, sr, vector); + m68ki_jump_vector(vector); + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[vector]); +} + +/* Exception for trace mode */ +INLINE void m68ki_exception_trace(void) +{ + uint sr = m68ki_init_exception(); + + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE); + } + else + m68ki_stack_frame_0010(sr, EXCEPTION_TRACE); + + m68ki_jump_vector(EXCEPTION_TRACE); + + /* Trace nullifies a STOP instruction */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; + + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]); +} + +/* Exception for privilege violation */ +INLINE void m68ki_exception_privilege_violation(void) +{ + uint sr = m68ki_init_exception(); + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION); + m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for A-Line instructions */ +INLINE void m68ki_exception_1010(void) +{ + uint sr; +#if M68K_LOG_1010_1111 == OPT_ON + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); +#endif + + sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1010); + m68ki_jump_vector(EXCEPTION_1010); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for F-Line instructions */ +INLINE void m68ki_exception_1111(void) +{ + uint sr; + +#if M68K_LOG_1010_1111 == OPT_ON + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); +#endif + + sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1111); + m68ki_jump_vector(EXCEPTION_1111); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for illegal instructions */ +INLINE void m68ki_exception_illegal(void) +{ + uint sr; + + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); + + sr = m68ki_init_exception(); + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION); + m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for format errror in RTE */ +INLINE void m68ki_exception_format_error(void) +{ + uint sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_FORMAT_ERROR); + m68ki_jump_vector(EXCEPTION_FORMAT_ERROR); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]); +} + +/* Exception for address error */ +INLINE void m68ki_exception_address_error(void) +{ + uint sr = m68ki_init_exception(); + + /* If we were processing a bus error, address error, or reset, + * this is a catastrophic failure. + * Halt the CPU + */ + if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET) + { +m68k_read_memory_8(0x00ffff01); + CPU_STOPPED = STOP_LEVEL_HALT; + return; + } + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + + /* Note: This is implemented for 68000 only! */ + m68ki_stack_frame_buserr(sr); + + m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR); + + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR] - CYC_INSTRUCTION[REG_IR]); +} + + +/* Service an interrupt request and start exception processing */ +void m68ki_exception_interrupt(uint int_level) +{ + uint vector; + uint sr; + uint new_pc; + + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + + /* Turn off the stopped state */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; + + /* If we are halted, don't do anything */ + if(CPU_STOPPED) + return; + + /* Acknowledge the interrupt */ + vector = m68ki_int_ack(int_level); + + /* Get the interrupt vector */ + if(vector == M68K_INT_ACK_AUTOVECTOR) + /* Use the autovectors. This is the most commonly used implementation */ + vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; + else if(vector == M68K_INT_ACK_SPURIOUS) + /* Called if no devices respond to the interrupt acknowledge */ + vector = EXCEPTION_SPURIOUS_INTERRUPT; + else if(vector > 255) + { + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); + return; + } + + /* Start exception processing */ + sr = m68ki_init_exception(); + + /* Set the interrupt mask to the level of the one being serviced */ + FLAG_INT_MASK = int_level<<8; + + /* Get the new PC */ + new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); + + /* If vector is uninitialized, call the uninitialized interrupt vector */ + if(new_pc == 0) + new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); + + /* Generate a stack frame */ + m68ki_stack_frame_0000(REG_PC, sr, vector); + if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Create throwaway frame */ + m68ki_set_sm_flag(FLAG_S); /* clear M */ + sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ + m68ki_stack_frame_0001(REG_PC, sr, vector); + } + + m68ki_jump(new_pc); + + /* Defer cycle counting until later */ + CPU_INT_CYCLES += CYC_EXCEPTION[vector]; + +#if !M68K_EMULATE_INT_ACK + /* Automatically clear IRQ if we are not using an acknowledge scheme */ + CPU_INT_LEVEL = 0; +#endif /* M68K_EMULATE_INT_ACK */ +} + + +/* ASG: Check for interrupts */ +INLINE void m68ki_check_interrupts(void) +{ + if(CPU_INT_LEVEL > FLAG_INT_MASK) + m68ki_exception_interrupt(CPU_INT_LEVEL>>8); +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KCPU__HEADER */ diff --git a/src/cpu/m68k/m68kdasm.c b/src/cpu/m68k/m68kdasm.c new file mode 100644 index 00000000..5dca4c10 --- /dev/null +++ b/src/cpu/m68k/m68kdasm.c @@ -0,0 +1,3533 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + + + +/* ======================================================================== */ +/* ================================ INCLUDES ============================== */ +/* ======================================================================== */ + +#include +#include +#include +#include "m68k.h" + +#ifndef DECL_SPEC +#define DECL_SPEC +#endif + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ +/* ======================================================================== */ + +/* unsigned int and int must be at least 32 bits wide */ +#undef uint +#define uint unsigned int + +/* Bit Isolation Functions */ +#define BIT_0(A) ((A) & 0x00000001) +#define BIT_1(A) ((A) & 0x00000002) +#define BIT_2(A) ((A) & 0x00000004) +#define BIT_3(A) ((A) & 0x00000008) +#define BIT_4(A) ((A) & 0x00000010) +#define BIT_5(A) ((A) & 0x00000020) +#define BIT_6(A) ((A) & 0x00000040) +#define BIT_7(A) ((A) & 0x00000080) +#define BIT_8(A) ((A) & 0x00000100) +#define BIT_9(A) ((A) & 0x00000200) +#define BIT_A(A) ((A) & 0x00000400) +#define BIT_B(A) ((A) & 0x00000800) +#define BIT_C(A) ((A) & 0x00001000) +#define BIT_D(A) ((A) & 0x00002000) +#define BIT_E(A) ((A) & 0x00004000) +#define BIT_F(A) ((A) & 0x00008000) +#define BIT_10(A) ((A) & 0x00010000) +#define BIT_11(A) ((A) & 0x00020000) +#define BIT_12(A) ((A) & 0x00040000) +#define BIT_13(A) ((A) & 0x00080000) +#define BIT_14(A) ((A) & 0x00100000) +#define BIT_15(A) ((A) & 0x00200000) +#define BIT_16(A) ((A) & 0x00400000) +#define BIT_17(A) ((A) & 0x00800000) +#define BIT_18(A) ((A) & 0x01000000) +#define BIT_19(A) ((A) & 0x02000000) +#define BIT_1A(A) ((A) & 0x04000000) +#define BIT_1B(A) ((A) & 0x08000000) +#define BIT_1C(A) ((A) & 0x10000000) +#define BIT_1D(A) ((A) & 0x20000000) +#define BIT_1E(A) ((A) & 0x40000000) +#define BIT_1F(A) ((A) & 0x80000000) + +/* These are the CPU types understood by this disassembler */ +#define TYPE_68000 1 +#define TYPE_68008 2 +#define TYPE_68010 4 +#define TYPE_68020 8 +#define TYPE_68030 16 +#define TYPE_68040 32 + +#define M68000_ONLY (TYPE_68000 | TYPE_68008) + +#define M68010_ONLY TYPE_68010 +#define M68010_LESS (TYPE_68000 | TYPE_68008 | TYPE_68010) +#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040) + +#define M68020_ONLY TYPE_68020 +#define M68020_LESS (TYPE_68010 | TYPE_68020) +#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040) + +#define M68030_ONLY TYPE_68030 +#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030) +#define M68030_PLUS (TYPE_68030 | TYPE_68040) + +#define M68040_PLUS TYPE_68040 + + +/* Extension word formats */ +#define EXT_8BIT_DISPLACEMENT(A) ((A)&0xff) +#define EXT_FULL(A) BIT_8(A) +#define EXT_EFFECTIVE_ZERO(A) (((A)&0xe4) == 0xc4 || ((A)&0xe2) == 0xc0) +#define EXT_BASE_REGISTER_PRESENT(A) (!BIT_7(A)) +#define EXT_INDEX_REGISTER_PRESENT(A) (!BIT_6(A)) +#define EXT_INDEX_REGISTER(A) (((A)>>12)&7) +#define EXT_INDEX_PRE_POST(A) (EXT_INDEX_PRESENT(A) && (A)&3) +#define EXT_INDEX_PRE(A) (EXT_INDEX_PRESENT(A) && ((A)&7) < 4 && ((A)&7) != 0) +#define EXT_INDEX_POST(A) (EXT_INDEX_PRESENT(A) && ((A)&7) > 4) +#define EXT_INDEX_SCALE(A) (((A)>>9)&3) +#define EXT_INDEX_LONG(A) BIT_B(A) +#define EXT_INDEX_AR(A) BIT_F(A) +#define EXT_BASE_DISPLACEMENT_PRESENT(A) (((A)&0x30) > 0x10) +#define EXT_BASE_DISPLACEMENT_WORD(A) (((A)&0x30) == 0x20) +#define EXT_BASE_DISPLACEMENT_LONG(A) (((A)&0x30) == 0x30) +#define EXT_OUTER_DISPLACEMENT_PRESENT(A) (((A)&3) > 1 && ((A)&0x47) < 0x44) +#define EXT_OUTER_DISPLACEMENT_WORD(A) (((A)&3) == 2 && ((A)&0x47) < 0x44) +#define EXT_OUTER_DISPLACEMENT_LONG(A) (((A)&3) == 3 && ((A)&0x47) < 0x44) + + +/* Opcode flags */ +#if M68K_COMPILE_FOR_MAME == OPT_ON +#define SET_OPCODE_FLAGS(x) g_opcode_type = x; +#define COMBINE_OPCODE_FLAGS(x) ((x) | g_opcode_type | DASMFLAG_SUPPORTED) +#else +#define SET_OPCODE_FLAGS(x) +#define COMBINE_OPCODE_FLAGS(x) (x) +#endif + + +/* ======================================================================== */ +/* =============================== PROTOTYPES ============================= */ +/* ======================================================================== */ + +/* Read data at the PC and increment PC */ +uint read_imm_8(void); +uint read_imm_16(void); +uint read_imm_32(void); + +/* Read data at the PC but don't imcrement the PC */ +uint peek_imm_8(void); +uint peek_imm_16(void); +uint peek_imm_32(void); + +/* make signed integers 100% portably */ +static int make_int_8(int value); +static int make_int_16(int value); + +/* make a string of a hex value */ +static char* make_signed_hex_str_8(uint val); +static char* make_signed_hex_str_16(uint val); +static char* make_signed_hex_str_32(uint val); + +/* make string of ea mode */ +static char* get_ea_mode_str(uint instruction, uint size); + +char* get_ea_mode_str_8(uint instruction); +char* get_ea_mode_str_16(uint instruction); +char* get_ea_mode_str_32(uint instruction); + +/* make string of immediate value */ +static char* get_imm_str_s(uint size); +static char* get_imm_str_u(uint size); + +char* get_imm_str_s8(void); +char* get_imm_str_s16(void); +char* get_imm_str_s32(void); + +/* Stuff to build the opcode handler jump table */ +static void build_opcode_table(void); +static int valid_ea(uint opcode, uint mask); +static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr); + +/* used to build opcode handler jump table */ +typedef struct +{ + void (*opcode_handler)(void); /* handler function */ + uint mask; /* mask on opcode */ + uint match; /* what to match after masking */ + uint ea_mask; /* what ea modes are allowed */ +} opcode_struct; + + + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +/* Opcode handler jump table */ +static void (*g_instruction_table[0x10000])(void); +/* Flag if disassembler initialized */ +static int g_initialized = 0; + +/* Address mask to simulate address lines */ +static unsigned int g_address_mask = 0xffffffff; + +static char g_dasm_str[100]; /* string to hold disassembly */ +static char g_helper_str[100]; /* string to hold helpful info */ +static uint g_cpu_pc; /* program counter */ +static uint g_cpu_ir; /* instruction register */ +static uint g_cpu_type; +static uint g_opcode_type; + +/* used by ops like asr, ror, addq, etc */ +static uint g_3bit_qdata_table[8] = {8, 1, 2, 3, 4, 5, 6, 7}; + +static uint g_5bit_data_table[32] = +{ + 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; + +static const char* g_cc[16] = +{"t", "f", "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"}; + +static const char* g_cpcc[64] = +{/* 000 001 010 011 100 101 110 111 */ + "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", /* 000 */ + "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", /* 001 */ + "sf", "seq", "gt", "ge", "lt", "le", "gl" "gle", /* 010 */ + "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st", /* 011 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 100 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 101 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 110 */ + "?", "?", "?", "?", "?", "?", "?", "?" /* 111 */ +}; + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + +#define LIMIT_CPU_TYPES(ALLOWED_CPU_TYPES) \ + if(!(g_cpu_type & ALLOWED_CPU_TYPES)) \ + { \ + d68000_illegal(); \ + return; \ + } + +#define read_imm_8() (m68k_read_disassembler_16(((g_cpu_pc+=2)-2)&g_address_mask)&0xff) +#define read_imm_16() m68k_read_disassembler_16(((g_cpu_pc+=2)-2)&g_address_mask) +#define read_imm_32() m68k_read_disassembler_32(((g_cpu_pc+=4)-4)&g_address_mask) + +#define peek_imm_8() (m68k_read_disassembler_16(g_cpu_pc & g_address_mask)&0xff) +#define peek_imm_16() m68k_read_disassembler_16(g_cpu_pc & g_address_mask) +#define peek_imm_32() m68k_read_disassembler_32(g_cpu_pc & g_address_mask) + +/* Fake a split interface */ +#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0) +#define get_ea_mode_str_16(instruction) get_ea_mode_str(instruction, 1) +#define get_ea_mode_str_32(instruction) get_ea_mode_str(instruction, 2) + +#define get_imm_str_s8() get_imm_str_s(0) +#define get_imm_str_s16() get_imm_str_s(1) +#define get_imm_str_s32() get_imm_str_s(2) + +#define get_imm_str_u8() get_imm_str_u(0) +#define get_imm_str_u16() get_imm_str_u(1) +#define get_imm_str_u32() get_imm_str_u(2) + + +/* 100% portable signed int generators */ +static int make_int_8(int value) +{ + return (value & 0x80) ? value | ~0xff : value & 0xff; +} + +static int make_int_16(int value) +{ + return (value & 0x8000) ? value | ~0xffff : value & 0xffff; +} + + +/* Get string representation of hex values */ +static char* make_signed_hex_str_8(uint val) +{ + static char str[20]; + + val &= 0xff; + + if(val == 0x80) + sprintf(str, "-$80"); + else if(val & 0x80) + sprintf(str, "-$%x", (0-val) & 0x7f); + else + sprintf(str, "$%x", val & 0x7f); + + return str; +} + +static char* make_signed_hex_str_16(uint val) +{ + static char str[20]; + + val &= 0xffff; + + if(val == 0x8000) + sprintf(str, "-$8000"); + else if(val & 0x8000) + sprintf(str, "-$%x", (0-val) & 0x7fff); + else + sprintf(str, "$%x", val & 0x7fff); + + return str; +} + +static char* make_signed_hex_str_32(uint val) +{ + static char str[20]; + + val &= 0xffffffff; + + if(val == 0x80000000) + sprintf(str, "-$80000000"); + else if(val & 0x80000000) + sprintf(str, "-$%x", (0-val) & 0x7fffffff); + else + sprintf(str, "$%x", val & 0x7fffffff); + + return str; +} + + +/* make string of immediate value */ +static char* get_imm_str_s(uint size) +{ + static char str[15]; + if(size == 0) + sprintf(str, "#%s", make_signed_hex_str_8(read_imm_8())); + else if(size == 1) + sprintf(str, "#%s", make_signed_hex_str_16(read_imm_16())); + else + sprintf(str, "#%s", make_signed_hex_str_32(read_imm_32())); + return str; +} + +static char* get_imm_str_u(uint size) +{ + static char str[15]; + if(size == 0) + sprintf(str, "#$%x", read_imm_8() & 0xff); + else if(size == 1) + sprintf(str, "#$%x", read_imm_16() & 0xffff); + else + sprintf(str, "#$%x", read_imm_32() & 0xffffffff); + return str; +} + +/* Make string of effective address mode */ +static char* get_ea_mode_str(uint instruction, uint size) +{ + static char b1[64]; + static char b2[64]; + static char* mode = b2; + uint extension; + uint base; + uint outer; + char base_reg[4]; + char index_reg[8]; + uint preindex; + uint postindex; + uint comma = 0; + uint temp_value; + char invalid_mode = 0; + + /* Switch buffers so we don't clobber on a double-call to this function */ + mode = mode == b1 ? b2 : b1; + + switch(instruction & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + /* data register direct */ + sprintf(mode, "D%d", instruction&7); + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + /* address register direct */ + sprintf(mode, "A%d", instruction&7); + break; + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + /* address register indirect */ + sprintf(mode, "(A%d)", instruction&7); + break; + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + /* address register indirect with postincrement */ + sprintf(mode, "(A%d)+", instruction&7); + break; + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + /* address register indirect with predecrement */ + sprintf(mode, "-(A%d)", instruction&7); + break; + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + /* address register indirect with displacement*/ + sprintf(mode, "(%s,A%d)", make_signed_hex_str_16(read_imm_16()), instruction&7); + break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + /* address register indirect with index */ + extension = read_imm_16(); + + if((g_cpu_type & M68010_LESS) && EXT_INDEX_SCALE(extension)) + { + invalid_mode = 1; + break; + } + + if(EXT_FULL(extension)) + { + if(g_cpu_type & M68010_LESS) + { + invalid_mode = 1; + break; + } + + if(EXT_EFFECTIVE_ZERO(extension)) + { + strcpy(mode, "0"); + break; + } + + base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + if(EXT_BASE_REGISTER_PRESENT(extension)) + sprintf(base_reg, "A%d", instruction&7); + else + *base_reg = 0; + if(EXT_INDEX_REGISTER_PRESENT(extension)) + { + sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); + } + else + *index_reg = 0; + preindex = (extension&7) > 0 && (extension&7) < 4; + postindex = (extension&7) > 4; + + strcpy(mode, "("); + if(preindex || postindex) + strcat(mode, "["); + if(base) + { + strcat(mode, make_signed_hex_str_16(base)); + comma = 1; + } + if(*base_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, base_reg); + comma = 1; + } + if(postindex) + { + strcat(mode, "]"); + comma = 1; + } + if(*index_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, index_reg); + comma = 1; + } + if(preindex) + { + strcat(mode, "]"); + comma = 1; + } + if(outer) + { + if(comma) + strcat(mode, ","); + strcat(mode, make_signed_hex_str_16(outer)); + } + strcat(mode, ")"); + break; + } + + if(EXT_8BIT_DISPLACEMENT(extension) == 0) + sprintf(mode, "(A%d,%c%d.%c", instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + else + sprintf(mode, "(%s,A%d,%c%d.%c", make_signed_hex_str_8(extension), instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); + strcat(mode, ")"); + break; + case 0x38: + /* absolute short address */ + sprintf(mode, "$%x.w", read_imm_16()); + break; + case 0x39: + /* absolute long address */ + sprintf(mode, "$%x.l", read_imm_32()); + break; + case 0x3a: + /* program counter with displacement */ + temp_value = read_imm_16(); + sprintf(mode, "(%s,PC)", make_signed_hex_str_16(temp_value)); + sprintf(g_helper_str, "; ($%x)", (make_int_16(temp_value) + g_cpu_pc-2) & 0xffffffff); + break; + case 0x3b: + /* program counter with index */ + extension = read_imm_16(); + + if((g_cpu_type & M68010_LESS) && EXT_INDEX_SCALE(extension)) + { + invalid_mode = 1; + break; + } + + if(EXT_FULL(extension)) + { + if(g_cpu_type & M68010_LESS) + { + invalid_mode = 1; + break; + } + + if(EXT_EFFECTIVE_ZERO(extension)) + { + strcpy(mode, "0"); + break; + } + base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + if(EXT_BASE_REGISTER_PRESENT(extension)) + strcpy(base_reg, "PC"); + else + *base_reg = 0; + if(EXT_INDEX_REGISTER_PRESENT(extension)) + { + sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); + } + else + *index_reg = 0; + preindex = (extension&7) > 0 && (extension&7) < 4; + postindex = (extension&7) > 4; + + strcpy(mode, "("); + if(preindex || postindex) + strcat(mode, "["); + if(base) + { + strcat(mode, make_signed_hex_str_16(base)); + comma = 1; + } + if(*base_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, base_reg); + comma = 1; + } + if(postindex) + { + strcat(mode, "]"); + comma = 1; + } + if(*index_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, index_reg); + comma = 1; + } + if(preindex) + { + strcat(mode, "]"); + comma = 1; + } + if(outer) + { + if(comma) + strcat(mode, ","); + strcat(mode, make_signed_hex_str_16(outer)); + } + strcat(mode, ")"); + break; + } + + if(EXT_8BIT_DISPLACEMENT(extension) == 0) + sprintf(mode, "(PC,%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + else + sprintf(mode, "(%s,PC,%c%d.%c", make_signed_hex_str_8(extension), EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); + strcat(mode, ")"); + break; + case 0x3c: + /* Immediate */ + sprintf(mode, "%s", get_imm_str_u(size)); + break; + default: + invalid_mode = 1; + } + + if(invalid_mode) + sprintf(mode, "INVALID %x", instruction & 0x3f); + + return mode; +} + + + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ +/* Instruction handler function names follow this convention: + * + * d68000_NAME_EXTENSIONS(void) + * where NAME is the name of the opcode it handles and EXTENSIONS are any + * extensions for special instances of that opcode. + * + * Examples: + * d68000_add_er_8(): add opcode, from effective address to register, + * size = byte + * + * d68000_asr_s_8(): arithmetic shift right, static count, size = byte + * + * + * Common extensions: + * 8 : size = byte + * 16 : size = word + * 32 : size = long + * rr : register to register + * mm : memory to memory + * r : register + * s : static + * er : effective address -> register + * re : register -> effective address + * ea : using effective address mode of operation + * d : data register direct + * a : address register direct + * ai : address register indirect + * pi : address register indirect with postincrement + * pd : address register indirect with predecrement + * di : address register indirect with displacement + * ix : address register indirect with index + * aw : absolute word + * al : absolute long + */ + +static void d68000_illegal(void) +{ + sprintf(g_dasm_str, "dc.w $%04x; ILLEGAL", g_cpu_ir); +} + +static void d68000_1010(void) +{ + sprintf(g_dasm_str, "dc.w $%04x; opcode 1010", g_cpu_ir); +} + + +static void d68000_1111(void) +{ + sprintf(g_dasm_str, "dc.w $%04x; opcode 1111", g_cpu_ir); +} + + +static void d68000_abcd_rr(void) +{ + sprintf(g_dasm_str, "abcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + + +static void d68000_abcd_mm(void) +{ + sprintf(g_dasm_str, "abcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_add_er_8(void) +{ + sprintf(g_dasm_str, "add.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + + +static void d68000_add_er_16(void) +{ + sprintf(g_dasm_str, "add.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_add_er_32(void) +{ + sprintf(g_dasm_str, "add.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_add_re_8(void) +{ + sprintf(g_dasm_str, "add.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_add_re_16(void) +{ + sprintf(g_dasm_str, "add.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_add_re_32(void) +{ + sprintf(g_dasm_str, "add.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_adda_16(void) +{ + sprintf(g_dasm_str, "adda.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_adda_32(void) +{ + sprintf(g_dasm_str, "adda.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_addi_8(void) +{ + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "addi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_addi_16(void) +{ + char* str = get_imm_str_s16(); + sprintf(g_dasm_str, "addi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_addi_32(void) +{ + char* str = get_imm_str_s32(); + sprintf(g_dasm_str, "addi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_addq_8(void) +{ + sprintf(g_dasm_str, "addq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_addq_16(void) +{ + sprintf(g_dasm_str, "addq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_addq_32(void) +{ + sprintf(g_dasm_str, "addq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_addx_rr_8(void) +{ + sprintf(g_dasm_str, "addx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_addx_rr_16(void) +{ + sprintf(g_dasm_str, "addx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_addx_rr_32(void) +{ + sprintf(g_dasm_str, "addx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_addx_mm_8(void) +{ + sprintf(g_dasm_str, "addx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_addx_mm_16(void) +{ + sprintf(g_dasm_str, "addx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_addx_mm_32(void) +{ + sprintf(g_dasm_str, "addx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_and_er_8(void) +{ + sprintf(g_dasm_str, "and.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_and_er_16(void) +{ + sprintf(g_dasm_str, "and.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_and_er_32(void) +{ + sprintf(g_dasm_str, "and.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_and_re_8(void) +{ + sprintf(g_dasm_str, "and.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_and_re_16(void) +{ + sprintf(g_dasm_str, "and.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_and_re_32(void) +{ + sprintf(g_dasm_str, "and.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_andi_8(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "andi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_andi_16(void) +{ + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "andi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_andi_32(void) +{ + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "andi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_andi_to_ccr(void) +{ + sprintf(g_dasm_str, "andi %s, CCR", get_imm_str_u8()); +} + +static void d68000_andi_to_sr(void) +{ + sprintf(g_dasm_str, "andi %s, SR", get_imm_str_u16()); +} + +static void d68000_asr_s_8(void) +{ + sprintf(g_dasm_str, "asr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asr_s_16(void) +{ + sprintf(g_dasm_str, "asr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asr_s_32(void) +{ + sprintf(g_dasm_str, "asr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asr_r_8(void) +{ + sprintf(g_dasm_str, "asr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asr_r_16(void) +{ + sprintf(g_dasm_str, "asr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asr_r_32(void) +{ + sprintf(g_dasm_str, "asr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asr_ea(void) +{ + sprintf(g_dasm_str, "asr.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_asl_s_8(void) +{ + sprintf(g_dasm_str, "asl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asl_s_16(void) +{ + sprintf(g_dasm_str, "asl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asl_s_32(void) +{ + sprintf(g_dasm_str, "asl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_asl_r_8(void) +{ + sprintf(g_dasm_str, "asl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asl_r_16(void) +{ + sprintf(g_dasm_str, "asl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asl_r_32(void) +{ + sprintf(g_dasm_str, "asl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_asl_ea(void) +{ + sprintf(g_dasm_str, "asl.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_bcc_8(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "b%-2s %x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_8(g_cpu_ir)); +} + +static void d68000_bcc_16(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "b%-2s %x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_16(read_imm_16())); +} + +static void d68020_bcc_32(void) +{ + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "b%-2s %x; (2+)", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + read_imm_32()); +} + +static void d68000_bchg_r(void) +{ + sprintf(g_dasm_str, "bchg D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_bchg_s(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bchg %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_bclr_r(void) +{ + sprintf(g_dasm_str, "bclr D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_bclr_s(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bclr %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68010_bkpt(void) +{ + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "bkpt #%d; (1+)", g_cpu_ir&7); +} + +static void d68020_bfchg(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfchg %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfclr(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfclr %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfexts(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfexts D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfextu(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfextu D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfffo(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfffo D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfins(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfins D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bfset(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfset %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68020_bftst(void) +{ + uint extension; + char offset[3]; + char width[3]; + + LIMIT_CPU_TYPES(M68020_PLUS); + + extension = read_imm_16(); + + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bftst %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); +} + +static void d68000_bra_8(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bra %x", temp_pc + make_int_8(g_cpu_ir)); +} + +static void d68000_bra_16(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bra %x", temp_pc + make_int_16(read_imm_16())); +} + +static void d68020_bra_32(void) +{ + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "bra %x; (2+)", temp_pc + read_imm_32()); +} + +static void d68000_bset_r(void) +{ + sprintf(g_dasm_str, "bset D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_bset_s(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bset %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_bsr_8(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bsr %x", temp_pc + make_int_8(g_cpu_ir)); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_bsr_16(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bsr %x", temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68020_bsr_32(void) +{ + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "bsr %x; (2+)", temp_pc + peek_imm_32()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_btst_r(void) +{ + sprintf(g_dasm_str, "btst D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_btst_s(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "btst %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_callm(void) +{ + char* str; + LIMIT_CPU_TYPES(M68020_ONLY); + str = get_imm_str_u8(); + + sprintf(g_dasm_str, "callm %s, %s; (2)", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cas_8(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.b D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cas_16(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.w D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_cas_32(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.l D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_cas2_16(void) +{ +/* CAS2 Dc1:Dc2,Du1:Dc2:(Rn1):(Rn2) +f e d c b a 9 8 7 6 5 4 3 2 1 0 + DARn1 0 0 0 Du1 0 0 0 Dc1 + DARn2 0 0 0 Du2 0 0 0 Dc2 +*/ + + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_32(); + sprintf(g_dasm_str, "cas2.w D%d:D%d:D%d:D%d, (%c%d):(%c%d); (2+)", + (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, + BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, + BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68020_cas2_32(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_32(); + sprintf(g_dasm_str, "cas2.l D%d:D%d:D%d:D%d, (%c%d):(%c%d); (2+)", + (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, + BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, + BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68000_chk_16(void) +{ + sprintf(g_dasm_str, "chk.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68020_chk_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "chk.l %s, D%d; (2+)", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68020_chk2_cmp2_8(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.b %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68020_chk2_cmp2_16(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.w %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68020_chk2_cmp2_32(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.l %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68040_cinv(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + switch((g_cpu_ir>>3)&3) + { + case 0: + sprintf(g_dasm_str, "cinv (illegal scope); (4)"); + break; + case 1: + sprintf(g_dasm_str, "cinvl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 2: + sprintf(g_dasm_str, "cinvp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 3: + sprintf(g_dasm_str, "cinva %d; (4)", (g_cpu_ir>>6)&3); + break; + } +} + +static void d68000_clr_8(void) +{ + sprintf(g_dasm_str, "clr.b %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_clr_16(void) +{ + sprintf(g_dasm_str, "clr.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_clr_32(void) +{ + sprintf(g_dasm_str, "clr.l %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_cmp_8(void) +{ + sprintf(g_dasm_str, "cmp.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_cmp_16(void) +{ + sprintf(g_dasm_str, "cmp.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_cmp_32(void) +{ + sprintf(g_dasm_str, "cmp.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_cmpa_16(void) +{ + sprintf(g_dasm_str, "cmpa.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_cmpa_32(void) +{ + sprintf(g_dasm_str, "cmpa.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_cmpi_8(void) +{ + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cmpi_pcdi_8(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cmpi_pcix_8(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_cmpi_16(void) +{ + char* str; + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_cmpi_pcdi_16(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_cmpi_pcix_16(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_cmpi_32(void) +{ + char* str; + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_cmpi_pcdi_32(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_cmpi_pcix_32(void) +{ + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_cmpm_8(void) +{ + sprintf(g_dasm_str, "cmpm.b (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_cmpm_16(void) +{ + sprintf(g_dasm_str, "cmpm.w (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_cmpm_32(void) +{ + sprintf(g_dasm_str, "cmpm.l (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68020_cpbcc_16(void) +{ + uint extension; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + new_pc += make_int_16(peek_imm_16()); + sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); +} + +static void d68020_cpbcc_32(void) +{ + uint extension; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + new_pc += peek_imm_32(); + sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); +} + +static void d68020_cpdbcc(void) +{ + uint extension1; + uint extension2; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + new_pc += make_int_16(peek_imm_16()); + sprintf(g_dasm_str, "%ddb%-4s D%d,%s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], g_cpu_ir&7, get_imm_str_s16(), new_pc, extension2); +} + +static void d68020_cpgen(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "%dgen %s; (2-3)", (g_cpu_ir>>9)&7, get_imm_str_u32()); +} + +static void d68020_cprestore(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "%drestore %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cpsave(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "%dsave %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_cpscc(void) +{ + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%ds%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_ea_mode_str_8(g_cpu_ir), extension2); +} + +static void d68020_cptrapcc_0(void) +{ + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], extension2); +} + +static void d68020_cptrapcc_16(void) +{ + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u16(), extension2); +} + +static void d68020_cptrapcc_32(void) +{ + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u32(), extension2); +} + +static void d68040_cpush(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + switch((g_cpu_ir>>3)&3) + { + case 0: + sprintf(g_dasm_str, "cpush (illegal scope); (4)"); + break; + case 1: + sprintf(g_dasm_str, "cpushl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 2: + sprintf(g_dasm_str, "cpushp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 3: + sprintf(g_dasm_str, "cpusha %d; (4)", (g_cpu_ir>>6)&3); + break; + } +} + +static void d68000_dbra(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "dbra D%d, %x", g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_dbcc(void) +{ + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "db%-2s D%d, %x", g_cc[(g_cpu_ir>>8)&0xf], g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_divs(void) +{ + sprintf(g_dasm_str, "divs.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_divu(void) +{ + sprintf(g_dasm_str, "divu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68020_divl(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + + if(BIT_A(extension)) + sprintf(g_dasm_str, "div%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); + else if((extension&7) == ((extension>>12)&7)) + sprintf(g_dasm_str, "div%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); + else + sprintf(g_dasm_str, "div%cl.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); +} + +static void d68000_eor_8(void) +{ + sprintf(g_dasm_str, "eor.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_eor_16(void) +{ + sprintf(g_dasm_str, "eor.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_eor_32(void) +{ + sprintf(g_dasm_str, "eor.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_eori_8(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "eori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_eori_16(void) +{ + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "eori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_eori_32(void) +{ + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "eori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_eori_to_ccr(void) +{ + sprintf(g_dasm_str, "eori %s, CCR", get_imm_str_u8()); +} + +static void d68000_eori_to_sr(void) +{ + sprintf(g_dasm_str, "eori %s, SR", get_imm_str_u16()); +} + +static void d68000_exg_dd(void) +{ + sprintf(g_dasm_str, "exg D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_exg_aa(void) +{ + sprintf(g_dasm_str, "exg A%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_exg_da(void) +{ + sprintf(g_dasm_str, "exg D%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_ext_16(void) +{ + sprintf(g_dasm_str, "ext.w D%d", g_cpu_ir&7); +} + +static void d68000_ext_32(void) +{ + sprintf(g_dasm_str, "ext.l D%d", g_cpu_ir&7); +} + +static void d68020_extb_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "extb.l D%d; (2+)", g_cpu_ir&7); +} + +static void d68000_jmp(void) +{ + sprintf(g_dasm_str, "jmp %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_jsr(void) +{ + sprintf(g_dasm_str, "jsr %s", get_ea_mode_str_32(g_cpu_ir)); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_lea(void) +{ + sprintf(g_dasm_str, "lea %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_link_16(void) +{ + sprintf(g_dasm_str, "link A%d, %s", g_cpu_ir&7, get_imm_str_s16()); +} + +static void d68020_link_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "link A%d, %s; (2+)", g_cpu_ir&7, get_imm_str_s32()); +} + +static void d68000_lsr_s_8(void) +{ + sprintf(g_dasm_str, "lsr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsr_s_16(void) +{ + sprintf(g_dasm_str, "lsr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsr_s_32(void) +{ + sprintf(g_dasm_str, "lsr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsr_r_8(void) +{ + sprintf(g_dasm_str, "lsr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsr_r_16(void) +{ + sprintf(g_dasm_str, "lsr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsr_r_32(void) +{ + sprintf(g_dasm_str, "lsr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsr_ea(void) +{ + sprintf(g_dasm_str, "lsr.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_lsl_s_8(void) +{ + sprintf(g_dasm_str, "lsl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsl_s_16(void) +{ + sprintf(g_dasm_str, "lsl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsl_s_32(void) +{ + sprintf(g_dasm_str, "lsl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_lsl_r_8(void) +{ + sprintf(g_dasm_str, "lsl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsl_r_16(void) +{ + sprintf(g_dasm_str, "lsl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsl_r_32(void) +{ + sprintf(g_dasm_str, "lsl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_lsl_ea(void) +{ + sprintf(g_dasm_str, "lsl.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_move_8(void) +{ + char* str = get_ea_mode_str_8(g_cpu_ir); + sprintf(g_dasm_str, "move.b %s, %s", str, get_ea_mode_str_8(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); +} + +static void d68000_move_16(void) +{ + char* str = get_ea_mode_str_16(g_cpu_ir); + sprintf(g_dasm_str, "move.w %s, %s", str, get_ea_mode_str_16(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); +} + +static void d68000_move_32(void) +{ + char* str = get_ea_mode_str_32(g_cpu_ir); + sprintf(g_dasm_str, "move.l %s, %s", str, get_ea_mode_str_32(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); +} + +static void d68000_movea_16(void) +{ + sprintf(g_dasm_str, "movea.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_movea_32(void) +{ + sprintf(g_dasm_str, "movea.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_move_to_ccr(void) +{ + sprintf(g_dasm_str, "move %s, CCR", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68010_move_fr_ccr(void) +{ + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "move CCR, %s; (1+)", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_move_fr_sr(void) +{ + sprintf(g_dasm_str, "move SR, %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_move_to_sr(void) +{ + sprintf(g_dasm_str, "move %s, SR", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_move_fr_usp(void) +{ + sprintf(g_dasm_str, "move USP, A%d", g_cpu_ir&7); +} + +static void d68000_move_to_usp(void) +{ + sprintf(g_dasm_str, "move A%d, USP", g_cpu_ir&7); +} + +static void d68010_movec(void) +{ + uint extension; + const char* reg_name; + const char* processor; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + + switch(extension & 0xfff) + { + case 0x000: + reg_name = "SFC"; + processor = "1+"; + break; + case 0x001: + reg_name = "DFC"; + processor = "1+"; + break; + case 0x800: + reg_name = "USP"; + processor = "1+"; + break; + case 0x801: + reg_name = "VBR"; + processor = "1+"; + break; + case 0x002: + reg_name = "CACR"; + processor = "2+"; + break; + case 0x802: + reg_name = "CAAR"; + processor = "2,3"; + break; + case 0x803: + reg_name = "MSP"; + processor = "2+"; + break; + case 0x804: + reg_name = "ISP"; + processor = "2+"; + break; + case 0x003: + reg_name = "TC"; + processor = "4+"; + break; + case 0x004: + reg_name = "ITT0"; + processor = "4+"; + break; + case 0x005: + reg_name = "ITT1"; + processor = "4+"; + break; + case 0x006: + reg_name = "DTT0"; + processor = "4+"; + break; + case 0x007: + reg_name = "DTT1"; + processor = "4+"; + break; + case 0x805: + reg_name = "MMUSR"; + processor = "4+"; + break; + case 0x806: + reg_name = "URP"; + processor = "4+"; + break; + case 0x807: + reg_name = "SRP"; + processor = "4+"; + break; + default: + reg_name = make_signed_hex_str_16(extension & 0xfff); + processor = "?"; + } + + if(BIT_1(g_cpu_ir)) + sprintf(g_dasm_str, "movec %c%d, %s; (%s)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, reg_name, processor); + else + sprintf(g_dasm_str, "movec %s, %c%d; (%s)", reg_name, BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, processor); +} + +static void d68000_movem_pd_16(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1<<(15-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(15-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "D%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(7-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(7-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_movem_pd_32(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1<<(15-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(15-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "D%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(7-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(7-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_movem_er_16(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", get_ea_mode_str_16(g_cpu_ir), buffer); +} + +static void d68000_movem_er_32(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", get_ea_mode_str_32(g_cpu_ir), buffer); +} + +static void d68000_movem_re_16(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_movem_re_32(void) +{ + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; + + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_movep_re_16(void) +{ + sprintf(g_dasm_str, "movep.w D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); +} + +static void d68000_movep_re_32(void) +{ + sprintf(g_dasm_str, "movep.l D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); +} + +static void d68000_movep_er_16(void) +{ + sprintf(g_dasm_str, "movep.w ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_movep_er_32(void) +{ + sprintf(g_dasm_str, "movep.l ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68010_moves_8(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.b %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.b %s, %c%d; (1+)", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68010_moves_16(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.w %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_16(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.w %s, %c%d; (1+)", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68010_moves_32(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.l %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_32(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.l %s, %c%d; (1+)", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); +} + +static void d68000_moveq(void) +{ + sprintf(g_dasm_str, "moveq #%s, D%d", make_signed_hex_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68040_move16_pi_pi(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d)+, (A%d)+; (4)", g_cpu_ir&7, (read_imm_16()>>12)&7); +} + +static void d68040_move16_pi_al(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d)+, %s; (4)", g_cpu_ir&7, get_imm_str_u32()); +} + +static void d68040_move16_al_pi(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 %s, (A%d)+; (4)", get_imm_str_u32(), g_cpu_ir&7); +} + +static void d68040_move16_ai_al(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d), %s; (4)", g_cpu_ir&7, get_imm_str_u32()); +} + +static void d68040_move16_al_ai(void) +{ + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 %s, (A%d); (4)", get_imm_str_u32(), g_cpu_ir&7); +} + +static void d68000_muls(void) +{ + sprintf(g_dasm_str, "muls.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_mulu(void) +{ + sprintf(g_dasm_str, "mulu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68020_mull(void) +{ + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + + if(BIT_A(extension)) + sprintf(g_dasm_str, "mul%c.l %s, D%d-D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); + else + sprintf(g_dasm_str, "mul%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); +} + +static void d68000_nbcd(void) +{ + sprintf(g_dasm_str, "nbcd %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_neg_8(void) +{ + sprintf(g_dasm_str, "neg.b %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_neg_16(void) +{ + sprintf(g_dasm_str, "neg.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_neg_32(void) +{ + sprintf(g_dasm_str, "neg.l %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_negx_8(void) +{ + sprintf(g_dasm_str, "negx.b %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_negx_16(void) +{ + sprintf(g_dasm_str, "negx.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_negx_32(void) +{ + sprintf(g_dasm_str, "negx.l %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_nop(void) +{ + sprintf(g_dasm_str, "nop"); +} + +static void d68000_not_8(void) +{ + sprintf(g_dasm_str, "not.b %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_not_16(void) +{ + sprintf(g_dasm_str, "not.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_not_32(void) +{ + sprintf(g_dasm_str, "not.l %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_or_er_8(void) +{ + sprintf(g_dasm_str, "or.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_or_er_16(void) +{ + sprintf(g_dasm_str, "or.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_or_er_32(void) +{ + sprintf(g_dasm_str, "or.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_or_re_8(void) +{ + sprintf(g_dasm_str, "or.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_or_re_16(void) +{ + sprintf(g_dasm_str, "or.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_or_re_32(void) +{ + sprintf(g_dasm_str, "or.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_ori_8(void) +{ + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "ori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_ori_16(void) +{ + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "ori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_ori_32(void) +{ + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "ori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_ori_to_ccr(void) +{ + sprintf(g_dasm_str, "ori %s, CCR", get_imm_str_u8()); +} + +static void d68000_ori_to_sr(void) +{ + sprintf(g_dasm_str, "ori %s, SR", get_imm_str_u16()); +} + +static void d68020_pack_rr(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "pack D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); +} + +static void d68020_pack_mm(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "pack -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); +} + +static void d68000_pea(void) +{ + sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_reset(void) +{ + sprintf(g_dasm_str, "reset"); +} + +static void d68000_ror_s_8(void) +{ + sprintf(g_dasm_str, "ror.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_ror_s_16(void) +{ + sprintf(g_dasm_str, "ror.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7],g_cpu_ir&7); +} + +static void d68000_ror_s_32(void) +{ + sprintf(g_dasm_str, "ror.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_ror_r_8(void) +{ + sprintf(g_dasm_str, "ror.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_ror_r_16(void) +{ + sprintf(g_dasm_str, "ror.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_ror_r_32(void) +{ + sprintf(g_dasm_str, "ror.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_ror_ea(void) +{ + sprintf(g_dasm_str, "ror.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_rol_s_8(void) +{ + sprintf(g_dasm_str, "rol.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_rol_s_16(void) +{ + sprintf(g_dasm_str, "rol.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_rol_s_32(void) +{ + sprintf(g_dasm_str, "rol.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_rol_r_8(void) +{ + sprintf(g_dasm_str, "rol.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_rol_r_16(void) +{ + sprintf(g_dasm_str, "rol.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_rol_r_32(void) +{ + sprintf(g_dasm_str, "rol.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_rol_ea(void) +{ + sprintf(g_dasm_str, "rol.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_roxr_s_8(void) +{ + sprintf(g_dasm_str, "roxr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_roxr_s_16(void) +{ + sprintf(g_dasm_str, "roxr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + + +static void d68000_roxr_s_32(void) +{ + sprintf(g_dasm_str, "roxr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_roxr_r_8(void) +{ + sprintf(g_dasm_str, "roxr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxr_r_16(void) +{ + sprintf(g_dasm_str, "roxr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxr_r_32(void) +{ + sprintf(g_dasm_str, "roxr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxr_ea(void) +{ + sprintf(g_dasm_str, "roxr.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_roxl_s_8(void) +{ + sprintf(g_dasm_str, "roxl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_roxl_s_16(void) +{ + sprintf(g_dasm_str, "roxl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_roxl_s_32(void) +{ + sprintf(g_dasm_str, "roxl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); +} + +static void d68000_roxl_r_8(void) +{ + sprintf(g_dasm_str, "roxl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxl_r_16(void) +{ + sprintf(g_dasm_str, "roxl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxl_r_32(void) +{ + sprintf(g_dasm_str, "roxl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); +} + +static void d68000_roxl_ea(void) +{ + sprintf(g_dasm_str, "roxl.w %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68010_rtd(void) +{ + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "rtd %s; (1+)", get_imm_str_s16()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); +} + +static void d68000_rte(void) +{ + sprintf(g_dasm_str, "rte"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); +} + +static void d68020_rtm(void) +{ + LIMIT_CPU_TYPES(M68020_ONLY); + sprintf(g_dasm_str, "rtm %c%d; (2+)", BIT_3(g_cpu_ir) ? 'A' : 'D', g_cpu_ir&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); +} + +static void d68000_rtr(void) +{ + sprintf(g_dasm_str, "rtr"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); +} + +static void d68000_rts(void) +{ + sprintf(g_dasm_str, "rts"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); +} + +static void d68000_sbcd_rr(void) +{ + sprintf(g_dasm_str, "sbcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_sbcd_mm(void) +{ + sprintf(g_dasm_str, "sbcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_scc(void) +{ + sprintf(g_dasm_str, "s%-2s %s", g_cc[(g_cpu_ir>>8)&0xf], get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_stop(void) +{ + sprintf(g_dasm_str, "stop %s", get_imm_str_s16()); +} + +static void d68000_sub_er_8(void) +{ + sprintf(g_dasm_str, "sub.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_sub_er_16(void) +{ + sprintf(g_dasm_str, "sub.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_sub_er_32(void) +{ + sprintf(g_dasm_str, "sub.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_sub_re_8(void) +{ + sprintf(g_dasm_str, "sub.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_sub_re_16(void) +{ + sprintf(g_dasm_str, "sub.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_sub_re_32(void) +{ + sprintf(g_dasm_str, "sub.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_suba_16(void) +{ + sprintf(g_dasm_str, "suba.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_suba_32(void) +{ + sprintf(g_dasm_str, "suba.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); +} + +static void d68000_subi_8(void) +{ + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "subi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_subi_16(void) +{ + char* str = get_imm_str_s16(); + sprintf(g_dasm_str, "subi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_subi_32(void) +{ + char* str = get_imm_str_s32(); + sprintf(g_dasm_str, "subi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_subq_8(void) +{ + sprintf(g_dasm_str, "subq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_subq_16(void) +{ + sprintf(g_dasm_str, "subq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_subq_32(void) +{ + sprintf(g_dasm_str, "subq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_subx_rr_8(void) +{ + sprintf(g_dasm_str, "subx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_subx_rr_16(void) +{ + sprintf(g_dasm_str, "subx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_subx_rr_32(void) +{ + sprintf(g_dasm_str, "subx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_subx_mm_8(void) +{ + sprintf(g_dasm_str, "subx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_subx_mm_16(void) +{ + sprintf(g_dasm_str, "subx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_subx_mm_32(void) +{ + sprintf(g_dasm_str, "subx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); +} + +static void d68000_swap(void) +{ + sprintf(g_dasm_str, "swap D%d", g_cpu_ir&7); +} + +static void d68000_tas(void) +{ + sprintf(g_dasm_str, "tas %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_trap(void) +{ + sprintf(g_dasm_str, "trap #$%x", g_cpu_ir&0xf); +} + +static void d68020_trapcc_0(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s; (2+)", g_cc[(g_cpu_ir>>8)&0xf]); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68020_trapcc_16(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u16()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68020_trapcc_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u32()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_trapv(void) +{ + sprintf(g_dasm_str, "trapv"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); +} + +static void d68000_tst_8(void) +{ + sprintf(g_dasm_str, "tst.b %s", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_tst_pcdi_8(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_tst_pcix_8(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68020_tst_i_8(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); +} + +static void d68000_tst_16(void) +{ + sprintf(g_dasm_str, "tst.w %s", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_tst_a_16(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_tst_pcdi_16(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_tst_pcix_16(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68020_tst_i_16(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); +} + +static void d68000_tst_32(void) +{ + sprintf(g_dasm_str, "tst.l %s", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_tst_a_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_tst_pcdi_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_tst_pcix_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68020_tst_i_32(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); +} + +static void d68000_unlk(void) +{ + sprintf(g_dasm_str, "unlk A%d", g_cpu_ir&7); +} + +static void d68020_unpk_rr(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "unpk D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); +} + +static void d68020_unpk_mm(void) +{ + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "unpk -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); +} + + + +/* ======================================================================== */ +/* ======================= INSTRUCTION TABLE BUILDER ====================== */ +/* ======================================================================== */ + +/* EA Masks: +800 = data register direct +400 = address register direct +200 = address register indirect +100 = ARI postincrement + 80 = ARI pre-decrement + 40 = ARI displacement + 20 = ARI index + 10 = absolute short + 8 = absolute long + 4 = immediate / sr + 2 = pc displacement + 1 = pc idx +*/ + +static opcode_struct g_opcode_info[] = +{ +/* opcode handler mask match ea mask */ + {d68000_1010 , 0xf000, 0xa000, 0x000}, + {d68000_1111 , 0xf000, 0xf000, 0x000}, + {d68000_abcd_rr , 0xf1f8, 0xc100, 0x000}, + {d68000_abcd_mm , 0xf1f8, 0xc108, 0x000}, + {d68000_add_er_8 , 0xf1c0, 0xd000, 0xbff}, + {d68000_add_er_16 , 0xf1c0, 0xd040, 0xfff}, + {d68000_add_er_32 , 0xf1c0, 0xd080, 0xfff}, + {d68000_add_re_8 , 0xf1c0, 0xd100, 0x3f8}, + {d68000_add_re_16 , 0xf1c0, 0xd140, 0x3f8}, + {d68000_add_re_32 , 0xf1c0, 0xd180, 0x3f8}, + {d68000_adda_16 , 0xf1c0, 0xd0c0, 0xfff}, + {d68000_adda_32 , 0xf1c0, 0xd1c0, 0xfff}, + {d68000_addi_8 , 0xffc0, 0x0600, 0xbf8}, + {d68000_addi_16 , 0xffc0, 0x0640, 0xbf8}, + {d68000_addi_32 , 0xffc0, 0x0680, 0xbf8}, + {d68000_addq_8 , 0xf1c0, 0x5000, 0xbf8}, + {d68000_addq_16 , 0xf1c0, 0x5040, 0xff8}, + {d68000_addq_32 , 0xf1c0, 0x5080, 0xff8}, + {d68000_addx_rr_8 , 0xf1f8, 0xd100, 0x000}, + {d68000_addx_rr_16 , 0xf1f8, 0xd140, 0x000}, + {d68000_addx_rr_32 , 0xf1f8, 0xd180, 0x000}, + {d68000_addx_mm_8 , 0xf1f8, 0xd108, 0x000}, + {d68000_addx_mm_16 , 0xf1f8, 0xd148, 0x000}, + {d68000_addx_mm_32 , 0xf1f8, 0xd188, 0x000}, + {d68000_and_er_8 , 0xf1c0, 0xc000, 0xbff}, + {d68000_and_er_16 , 0xf1c0, 0xc040, 0xbff}, + {d68000_and_er_32 , 0xf1c0, 0xc080, 0xbff}, + {d68000_and_re_8 , 0xf1c0, 0xc100, 0x3f8}, + {d68000_and_re_16 , 0xf1c0, 0xc140, 0x3f8}, + {d68000_and_re_32 , 0xf1c0, 0xc180, 0x3f8}, + {d68000_andi_to_ccr , 0xffff, 0x023c, 0x000}, + {d68000_andi_to_sr , 0xffff, 0x027c, 0x000}, + {d68000_andi_8 , 0xffc0, 0x0200, 0xbf8}, + {d68000_andi_16 , 0xffc0, 0x0240, 0xbf8}, + {d68000_andi_32 , 0xffc0, 0x0280, 0xbf8}, + {d68000_asr_s_8 , 0xf1f8, 0xe000, 0x000}, + {d68000_asr_s_16 , 0xf1f8, 0xe040, 0x000}, + {d68000_asr_s_32 , 0xf1f8, 0xe080, 0x000}, + {d68000_asr_r_8 , 0xf1f8, 0xe020, 0x000}, + {d68000_asr_r_16 , 0xf1f8, 0xe060, 0x000}, + {d68000_asr_r_32 , 0xf1f8, 0xe0a0, 0x000}, + {d68000_asr_ea , 0xffc0, 0xe0c0, 0x3f8}, + {d68000_asl_s_8 , 0xf1f8, 0xe100, 0x000}, + {d68000_asl_s_16 , 0xf1f8, 0xe140, 0x000}, + {d68000_asl_s_32 , 0xf1f8, 0xe180, 0x000}, + {d68000_asl_r_8 , 0xf1f8, 0xe120, 0x000}, + {d68000_asl_r_16 , 0xf1f8, 0xe160, 0x000}, + {d68000_asl_r_32 , 0xf1f8, 0xe1a0, 0x000}, + {d68000_asl_ea , 0xffc0, 0xe1c0, 0x3f8}, + {d68000_bcc_8 , 0xf000, 0x6000, 0x000}, + {d68000_bcc_16 , 0xf0ff, 0x6000, 0x000}, + {d68020_bcc_32 , 0xf0ff, 0x60ff, 0x000}, + {d68000_bchg_r , 0xf1c0, 0x0140, 0xbf8}, + {d68000_bchg_s , 0xffc0, 0x0840, 0xbf8}, + {d68000_bclr_r , 0xf1c0, 0x0180, 0xbf8}, + {d68000_bclr_s , 0xffc0, 0x0880, 0xbf8}, + {d68020_bfchg , 0xffc0, 0xeac0, 0xa78}, + {d68020_bfclr , 0xffc0, 0xecc0, 0xa78}, + {d68020_bfexts , 0xffc0, 0xebc0, 0xa7b}, + {d68020_bfextu , 0xffc0, 0xe9c0, 0xa7b}, + {d68020_bfffo , 0xffc0, 0xedc0, 0xa7b}, + {d68020_bfins , 0xffc0, 0xefc0, 0xa78}, + {d68020_bfset , 0xffc0, 0xeec0, 0xa78}, + {d68020_bftst , 0xffc0, 0xe8c0, 0xa7b}, + {d68010_bkpt , 0xfff8, 0x4848, 0x000}, + {d68000_bra_8 , 0xff00, 0x6000, 0x000}, + {d68000_bra_16 , 0xffff, 0x6000, 0x000}, + {d68020_bra_32 , 0xffff, 0x60ff, 0x000}, + {d68000_bset_r , 0xf1c0, 0x01c0, 0xbf8}, + {d68000_bset_s , 0xffc0, 0x08c0, 0xbf8}, + {d68000_bsr_8 , 0xff00, 0x6100, 0x000}, + {d68000_bsr_16 , 0xffff, 0x6100, 0x000}, + {d68020_bsr_32 , 0xffff, 0x61ff, 0x000}, + {d68000_btst_r , 0xf1c0, 0x0100, 0xbff}, + {d68000_btst_s , 0xffc0, 0x0800, 0xbfb}, + {d68020_callm , 0xffc0, 0x06c0, 0x27b}, + {d68020_cas_8 , 0xffc0, 0x0ac0, 0x3f8}, + {d68020_cas_16 , 0xffc0, 0x0cc0, 0x3f8}, + {d68020_cas_32 , 0xffc0, 0x0ec0, 0x3f8}, + {d68020_cas2_16 , 0xffff, 0x0cfc, 0x000}, + {d68020_cas2_32 , 0xffff, 0x0efc, 0x000}, + {d68000_chk_16 , 0xf1c0, 0x4180, 0xbff}, + {d68020_chk_32 , 0xf1c0, 0x4100, 0xbff}, + {d68020_chk2_cmp2_8 , 0xffc0, 0x00c0, 0x27b}, + {d68020_chk2_cmp2_16 , 0xffc0, 0x02c0, 0x27b}, + {d68020_chk2_cmp2_32 , 0xffc0, 0x04c0, 0x27b}, + {d68040_cinv , 0xff20, 0xf400, 0x000}, + {d68000_clr_8 , 0xffc0, 0x4200, 0xbf8}, + {d68000_clr_16 , 0xffc0, 0x4240, 0xbf8}, + {d68000_clr_32 , 0xffc0, 0x4280, 0xbf8}, + {d68000_cmp_8 , 0xf1c0, 0xb000, 0xbff}, + {d68000_cmp_16 , 0xf1c0, 0xb040, 0xfff}, + {d68000_cmp_32 , 0xf1c0, 0xb080, 0xfff}, + {d68000_cmpa_16 , 0xf1c0, 0xb0c0, 0xfff}, + {d68000_cmpa_32 , 0xf1c0, 0xb1c0, 0xfff}, + {d68000_cmpi_8 , 0xffc0, 0x0c00, 0xbf8}, + {d68020_cmpi_pcdi_8 , 0xffff, 0x0c3a, 0x000}, + {d68020_cmpi_pcix_8 , 0xffff, 0x0c3b, 0x000}, + {d68000_cmpi_16 , 0xffc0, 0x0c40, 0xbf8}, + {d68020_cmpi_pcdi_16 , 0xffff, 0x0c7a, 0x000}, + {d68020_cmpi_pcix_16 , 0xffff, 0x0c7b, 0x000}, + {d68000_cmpi_32 , 0xffc0, 0x0c80, 0xbf8}, + {d68020_cmpi_pcdi_32 , 0xffff, 0x0cba, 0x000}, + {d68020_cmpi_pcix_32 , 0xffff, 0x0cbb, 0x000}, + {d68000_cmpm_8 , 0xf1f8, 0xb108, 0x000}, + {d68000_cmpm_16 , 0xf1f8, 0xb148, 0x000}, + {d68000_cmpm_32 , 0xf1f8, 0xb188, 0x000}, + {d68020_cpbcc_16 , 0xf1c0, 0xf080, 0x000}, + {d68020_cpbcc_32 , 0xf1c0, 0xf0c0, 0x000}, + {d68020_cpdbcc , 0xf1f8, 0xf048, 0x000}, + {d68020_cpgen , 0xf1c0, 0xf000, 0x000}, + {d68020_cprestore , 0xf1c0, 0xf140, 0x37f}, + {d68020_cpsave , 0xf1c0, 0xf100, 0x2f8}, + {d68020_cpscc , 0xf1c0, 0xf040, 0xbf8}, + {d68020_cptrapcc_0 , 0xf1ff, 0xf07c, 0x000}, + {d68020_cptrapcc_16 , 0xf1ff, 0xf07a, 0x000}, + {d68020_cptrapcc_32 , 0xf1ff, 0xf07b, 0x000}, + {d68040_cpush , 0xff20, 0xf420, 0x000}, + {d68000_dbcc , 0xf0f8, 0x50c8, 0x000}, + {d68000_dbra , 0xfff8, 0x51c8, 0x000}, + {d68000_divs , 0xf1c0, 0x81c0, 0xbff}, + {d68000_divu , 0xf1c0, 0x80c0, 0xbff}, + {d68020_divl , 0xffc0, 0x4c40, 0xbff}, + {d68000_eor_8 , 0xf1c0, 0xb100, 0xbf8}, + {d68000_eor_16 , 0xf1c0, 0xb140, 0xbf8}, + {d68000_eor_32 , 0xf1c0, 0xb180, 0xbf8}, + {d68000_eori_to_ccr , 0xffff, 0x0a3c, 0x000}, + {d68000_eori_to_sr , 0xffff, 0x0a7c, 0x000}, + {d68000_eori_8 , 0xffc0, 0x0a00, 0xbf8}, + {d68000_eori_16 , 0xffc0, 0x0a40, 0xbf8}, + {d68000_eori_32 , 0xffc0, 0x0a80, 0xbf8}, + {d68000_exg_dd , 0xf1f8, 0xc140, 0x000}, + {d68000_exg_aa , 0xf1f8, 0xc148, 0x000}, + {d68000_exg_da , 0xf1f8, 0xc188, 0x000}, + {d68020_extb_32 , 0xfff8, 0x49c0, 0x000}, + {d68000_ext_16 , 0xfff8, 0x4880, 0x000}, + {d68000_ext_32 , 0xfff8, 0x48c0, 0x000}, + {d68000_illegal , 0xffff, 0x4afc, 0x000}, + {d68000_jmp , 0xffc0, 0x4ec0, 0x27b}, + {d68000_jsr , 0xffc0, 0x4e80, 0x27b}, + {d68000_lea , 0xf1c0, 0x41c0, 0x27b}, + {d68000_link_16 , 0xfff8, 0x4e50, 0x000}, + {d68020_link_32 , 0xfff8, 0x4808, 0x000}, + {d68000_lsr_s_8 , 0xf1f8, 0xe008, 0x000}, + {d68000_lsr_s_16 , 0xf1f8, 0xe048, 0x000}, + {d68000_lsr_s_32 , 0xf1f8, 0xe088, 0x000}, + {d68000_lsr_r_8 , 0xf1f8, 0xe028, 0x000}, + {d68000_lsr_r_16 , 0xf1f8, 0xe068, 0x000}, + {d68000_lsr_r_32 , 0xf1f8, 0xe0a8, 0x000}, + {d68000_lsr_ea , 0xffc0, 0xe2c0, 0x3f8}, + {d68000_lsl_s_8 , 0xf1f8, 0xe108, 0x000}, + {d68000_lsl_s_16 , 0xf1f8, 0xe148, 0x000}, + {d68000_lsl_s_32 , 0xf1f8, 0xe188, 0x000}, + {d68000_lsl_r_8 , 0xf1f8, 0xe128, 0x000}, + {d68000_lsl_r_16 , 0xf1f8, 0xe168, 0x000}, + {d68000_lsl_r_32 , 0xf1f8, 0xe1a8, 0x000}, + {d68000_lsl_ea , 0xffc0, 0xe3c0, 0x3f8}, + {d68000_move_8 , 0xf000, 0x1000, 0xbff}, + {d68000_move_16 , 0xf000, 0x3000, 0xfff}, + {d68000_move_32 , 0xf000, 0x2000, 0xfff}, + {d68000_movea_16 , 0xf1c0, 0x3040, 0xfff}, + {d68000_movea_32 , 0xf1c0, 0x2040, 0xfff}, + {d68000_move_to_ccr , 0xffc0, 0x44c0, 0xbff}, + {d68010_move_fr_ccr , 0xffc0, 0x42c0, 0xbf8}, + {d68000_move_to_sr , 0xffc0, 0x46c0, 0xbff}, + {d68000_move_fr_sr , 0xffc0, 0x40c0, 0xbf8}, + {d68000_move_to_usp , 0xfff8, 0x4e60, 0x000}, + {d68000_move_fr_usp , 0xfff8, 0x4e68, 0x000}, + {d68010_movec , 0xfffe, 0x4e7a, 0x000}, + {d68000_movem_pd_16 , 0xfff8, 0x48a0, 0x000}, + {d68000_movem_pd_32 , 0xfff8, 0x48e0, 0x000}, + {d68000_movem_re_16 , 0xffc0, 0x4880, 0x2f8}, + {d68000_movem_re_32 , 0xffc0, 0x48c0, 0x2f8}, + {d68000_movem_er_16 , 0xffc0, 0x4c80, 0x37b}, + {d68000_movem_er_32 , 0xffc0, 0x4cc0, 0x37b}, + {d68000_movep_er_16 , 0xf1f8, 0x0108, 0x000}, + {d68000_movep_er_32 , 0xf1f8, 0x0148, 0x000}, + {d68000_movep_re_16 , 0xf1f8, 0x0188, 0x000}, + {d68000_movep_re_32 , 0xf1f8, 0x01c8, 0x000}, + {d68010_moves_8 , 0xffc0, 0x0e00, 0x3f8}, + {d68010_moves_16 , 0xffc0, 0x0e40, 0x3f8}, + {d68010_moves_32 , 0xffc0, 0x0e80, 0x3f8}, + {d68000_moveq , 0xf100, 0x7000, 0x000}, + {d68040_move16_pi_pi , 0xfff8, 0xf620, 0x000}, + {d68040_move16_pi_al , 0xfff8, 0xf600, 0x000}, + {d68040_move16_al_pi , 0xfff8, 0xf608, 0x000}, + {d68040_move16_ai_al , 0xfff8, 0xf610, 0x000}, + {d68040_move16_al_ai , 0xfff8, 0xf618, 0x000}, + {d68000_muls , 0xf1c0, 0xc1c0, 0xbff}, + {d68000_mulu , 0xf1c0, 0xc0c0, 0xbff}, + {d68020_mull , 0xffc0, 0x4c00, 0xbff}, + {d68000_nbcd , 0xffc0, 0x4800, 0xbf8}, + {d68000_neg_8 , 0xffc0, 0x4400, 0xbf8}, + {d68000_neg_16 , 0xffc0, 0x4440, 0xbf8}, + {d68000_neg_32 , 0xffc0, 0x4480, 0xbf8}, + {d68000_negx_8 , 0xffc0, 0x4000, 0xbf8}, + {d68000_negx_16 , 0xffc0, 0x4040, 0xbf8}, + {d68000_negx_32 , 0xffc0, 0x4080, 0xbf8}, + {d68000_nop , 0xffff, 0x4e71, 0x000}, + {d68000_not_8 , 0xffc0, 0x4600, 0xbf8}, + {d68000_not_16 , 0xffc0, 0x4640, 0xbf8}, + {d68000_not_32 , 0xffc0, 0x4680, 0xbf8}, + {d68000_or_er_8 , 0xf1c0, 0x8000, 0xbff}, + {d68000_or_er_16 , 0xf1c0, 0x8040, 0xbff}, + {d68000_or_er_32 , 0xf1c0, 0x8080, 0xbff}, + {d68000_or_re_8 , 0xf1c0, 0x8100, 0x3f8}, + {d68000_or_re_16 , 0xf1c0, 0x8140, 0x3f8}, + {d68000_or_re_32 , 0xf1c0, 0x8180, 0x3f8}, + {d68000_ori_to_ccr , 0xffff, 0x003c, 0x000}, + {d68000_ori_to_sr , 0xffff, 0x007c, 0x000}, + {d68000_ori_8 , 0xffc0, 0x0000, 0xbf8}, + {d68000_ori_16 , 0xffc0, 0x0040, 0xbf8}, + {d68000_ori_32 , 0xffc0, 0x0080, 0xbf8}, + {d68020_pack_rr , 0xf1f8, 0x8140, 0x000}, + {d68020_pack_mm , 0xf1f8, 0x8148, 0x000}, + {d68000_pea , 0xffc0, 0x4840, 0x27b}, + {d68000_reset , 0xffff, 0x4e70, 0x000}, + {d68000_ror_s_8 , 0xf1f8, 0xe018, 0x000}, + {d68000_ror_s_16 , 0xf1f8, 0xe058, 0x000}, + {d68000_ror_s_32 , 0xf1f8, 0xe098, 0x000}, + {d68000_ror_r_8 , 0xf1f8, 0xe038, 0x000}, + {d68000_ror_r_16 , 0xf1f8, 0xe078, 0x000}, + {d68000_ror_r_32 , 0xf1f8, 0xe0b8, 0x000}, + {d68000_ror_ea , 0xffc0, 0xe6c0, 0x3f8}, + {d68000_rol_s_8 , 0xf1f8, 0xe118, 0x000}, + {d68000_rol_s_16 , 0xf1f8, 0xe158, 0x000}, + {d68000_rol_s_32 , 0xf1f8, 0xe198, 0x000}, + {d68000_rol_r_8 , 0xf1f8, 0xe138, 0x000}, + {d68000_rol_r_16 , 0xf1f8, 0xe178, 0x000}, + {d68000_rol_r_32 , 0xf1f8, 0xe1b8, 0x000}, + {d68000_rol_ea , 0xffc0, 0xe7c0, 0x3f8}, + {d68000_roxr_s_8 , 0xf1f8, 0xe010, 0x000}, + {d68000_roxr_s_16 , 0xf1f8, 0xe050, 0x000}, + {d68000_roxr_s_32 , 0xf1f8, 0xe090, 0x000}, + {d68000_roxr_r_8 , 0xf1f8, 0xe030, 0x000}, + {d68000_roxr_r_16 , 0xf1f8, 0xe070, 0x000}, + {d68000_roxr_r_32 , 0xf1f8, 0xe0b0, 0x000}, + {d68000_roxr_ea , 0xffc0, 0xe4c0, 0x3f8}, + {d68000_roxl_s_8 , 0xf1f8, 0xe110, 0x000}, + {d68000_roxl_s_16 , 0xf1f8, 0xe150, 0x000}, + {d68000_roxl_s_32 , 0xf1f8, 0xe190, 0x000}, + {d68000_roxl_r_8 , 0xf1f8, 0xe130, 0x000}, + {d68000_roxl_r_16 , 0xf1f8, 0xe170, 0x000}, + {d68000_roxl_r_32 , 0xf1f8, 0xe1b0, 0x000}, + {d68000_roxl_ea , 0xffc0, 0xe5c0, 0x3f8}, + {d68010_rtd , 0xffff, 0x4e74, 0x000}, + {d68000_rte , 0xffff, 0x4e73, 0x000}, + {d68020_rtm , 0xfff0, 0x06c0, 0x000}, + {d68000_rtr , 0xffff, 0x4e77, 0x000}, + {d68000_rts , 0xffff, 0x4e75, 0x000}, + {d68000_sbcd_rr , 0xf1f8, 0x8100, 0x000}, + {d68000_sbcd_mm , 0xf1f8, 0x8108, 0x000}, + {d68000_scc , 0xf0c0, 0x50c0, 0xbf8}, + {d68000_stop , 0xffff, 0x4e72, 0x000}, + {d68000_sub_er_8 , 0xf1c0, 0x9000, 0xbff}, + {d68000_sub_er_16 , 0xf1c0, 0x9040, 0xfff}, + {d68000_sub_er_32 , 0xf1c0, 0x9080, 0xfff}, + {d68000_sub_re_8 , 0xf1c0, 0x9100, 0x3f8}, + {d68000_sub_re_16 , 0xf1c0, 0x9140, 0x3f8}, + {d68000_sub_re_32 , 0xf1c0, 0x9180, 0x3f8}, + {d68000_suba_16 , 0xf1c0, 0x90c0, 0xfff}, + {d68000_suba_32 , 0xf1c0, 0x91c0, 0xfff}, + {d68000_subi_8 , 0xffc0, 0x0400, 0xbf8}, + {d68000_subi_16 , 0xffc0, 0x0440, 0xbf8}, + {d68000_subi_32 , 0xffc0, 0x0480, 0xbf8}, + {d68000_subq_8 , 0xf1c0, 0x5100, 0xbf8}, + {d68000_subq_16 , 0xf1c0, 0x5140, 0xff8}, + {d68000_subq_32 , 0xf1c0, 0x5180, 0xff8}, + {d68000_subx_rr_8 , 0xf1f8, 0x9100, 0x000}, + {d68000_subx_rr_16 , 0xf1f8, 0x9140, 0x000}, + {d68000_subx_rr_32 , 0xf1f8, 0x9180, 0x000}, + {d68000_subx_mm_8 , 0xf1f8, 0x9108, 0x000}, + {d68000_subx_mm_16 , 0xf1f8, 0x9148, 0x000}, + {d68000_subx_mm_32 , 0xf1f8, 0x9188, 0x000}, + {d68000_swap , 0xfff8, 0x4840, 0x000}, + {d68000_tas , 0xffc0, 0x4ac0, 0xbf8}, + {d68000_trap , 0xfff0, 0x4e40, 0x000}, + {d68020_trapcc_0 , 0xf0ff, 0x50fc, 0x000}, + {d68020_trapcc_16 , 0xf0ff, 0x50fa, 0x000}, + {d68020_trapcc_32 , 0xf0ff, 0x50fb, 0x000}, + {d68000_trapv , 0xffff, 0x4e76, 0x000}, + {d68000_tst_8 , 0xffc0, 0x4a00, 0xbf8}, + {d68020_tst_pcdi_8 , 0xffff, 0x4a3a, 0x000}, + {d68020_tst_pcix_8 , 0xffff, 0x4a3b, 0x000}, + {d68020_tst_i_8 , 0xffff, 0x4a3c, 0x000}, + {d68000_tst_16 , 0xffc0, 0x4a40, 0xbf8}, + {d68020_tst_a_16 , 0xfff8, 0x4a48, 0x000}, + {d68020_tst_pcdi_16 , 0xffff, 0x4a7a, 0x000}, + {d68020_tst_pcix_16 , 0xffff, 0x4a7b, 0x000}, + {d68020_tst_i_16 , 0xffff, 0x4a7c, 0x000}, + {d68000_tst_32 , 0xffc0, 0x4a80, 0xbf8}, + {d68020_tst_a_32 , 0xfff8, 0x4a88, 0x000}, + {d68020_tst_pcdi_32 , 0xffff, 0x4aba, 0x000}, + {d68020_tst_pcix_32 , 0xffff, 0x4abb, 0x000}, + {d68020_tst_i_32 , 0xffff, 0x4abc, 0x000}, + {d68000_unlk , 0xfff8, 0x4e58, 0x000}, + {d68020_unpk_rr , 0xf1f8, 0x8180, 0x000}, + {d68020_unpk_mm , 0xf1f8, 0x8188, 0x000}, + {0, 0, 0, 0} +}; + +/* Check if opcode is using a valid ea mode */ +static int valid_ea(uint opcode, uint mask) +{ + if(mask == 0) + return 1; + + switch(opcode & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + return (mask & 0x800) != 0; + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + return (mask & 0x400) != 0; + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + return (mask & 0x200) != 0; + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + return (mask & 0x100) != 0; + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + return (mask & 0x080) != 0; + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + return (mask & 0x040) != 0; + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + return (mask & 0x020) != 0; + case 0x38: + return (mask & 0x010) != 0; + case 0x39: + return (mask & 0x008) != 0; + case 0x3a: + return (mask & 0x002) != 0; + case 0x3b: + return (mask & 0x001) != 0; + case 0x3c: + return (mask & 0x004) != 0; + } + return 0; + +} + +/* Used by qsort */ +static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr) +{ + uint a = ((const opcode_struct*)aptr)->mask; + uint b = ((const opcode_struct*)bptr)->mask; + + a = ((a & 0xAAAA) >> 1) + (a & 0x5555); + a = ((a & 0xCCCC) >> 2) + (a & 0x3333); + a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F); + a = ((a & 0xFF00) >> 8) + (a & 0x00FF); + + b = ((b & 0xAAAA) >> 1) + (b & 0x5555); + b = ((b & 0xCCCC) >> 2) + (b & 0x3333); + b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F); + b = ((b & 0xFF00) >> 8) + (b & 0x00FF); + + return b - a; /* reversed to get greatest to least sorting */ +} + +/* build the opcode handler jump table */ +static void build_opcode_table(void) +{ + uint i; + uint opcode; + opcode_struct* ostruct; + uint opcode_info_length = 0; + + for(ostruct = g_opcode_info;ostruct->opcode_handler != 0;ostruct++) + opcode_info_length++; + + qsort((void *)g_opcode_info, opcode_info_length, sizeof(g_opcode_info[0]), compare_nof_true_bits); + + for(i=0;i<0x10000;i++) + { + g_instruction_table[i] = d68000_illegal; /* default to illegal */ + opcode = i; + /* search through opcode info for a match */ + for(ostruct = g_opcode_info;ostruct->opcode_handler != 0;ostruct++) + { + /* match opcode mask and allowed ea modes */ + if((opcode & ostruct->mask) == ostruct->match) + { + /* Handle destination ea for move instructions */ + if((ostruct->opcode_handler == d68000_move_8 || + ostruct->opcode_handler == d68000_move_16 || + ostruct->opcode_handler == d68000_move_32) && + !valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8)) + continue; + if(valid_ea(opcode, ostruct->ea_mask)) + { + g_instruction_table[i] = ostruct->opcode_handler; + break; + } + } + } + } +} + + + +/* ======================================================================== */ +/* ================================= API ================================== */ +/* ======================================================================== */ + +/* Disasemble one instruction at pc and store in str_buff */ +unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type) +{ + if(!g_initialized) + { + build_opcode_table(); + g_initialized = 1; + } + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + g_cpu_type = TYPE_68000; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68008: + g_cpu_type = TYPE_68008; + g_address_mask = 0x003fffff; + break; + case M68K_CPU_TYPE_68010: + g_cpu_type = TYPE_68010; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68EC020: + g_cpu_type = TYPE_68020; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68020: + g_cpu_type = TYPE_68020; + g_address_mask = 0xffffffff; + break; + case M68K_CPU_TYPE_68030: + g_cpu_type = TYPE_68030; + g_address_mask = 0xffffffff; + break; + case M68K_CPU_TYPE_68040: + g_cpu_type = TYPE_68040; + g_address_mask = 0xffffffff; + break; + default: + return 0; + } + + g_cpu_pc = pc; + g_helper_str[0] = 0; + g_cpu_ir = read_imm_16(); + g_opcode_type = 0; + g_instruction_table[g_cpu_ir](); + sprintf(str_buff, "%s%s", g_dasm_str, g_helper_str); + return COMBINE_OPCODE_FLAGS(g_cpu_pc - pc); +} + +char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type) +{ + static char buff[100]; + buff[0] = 0; + m68k_disassemble(buff, pc, cpu_type); + return buff; +} + +/* Check if the instruction is a valid one */ +unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type) +{ + if(!g_initialized) + { + build_opcode_table(); + g_initialized = 1; + } + + instruction &= 0xffff; + if(g_instruction_table[instruction] == d68000_illegal) + return 0; + + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + case M68K_CPU_TYPE_68008: + if(g_instruction_table[instruction] == d68010_bkpt) + return 0; + if(g_instruction_table[instruction] == d68010_move_fr_ccr) + return 0; + if(g_instruction_table[instruction] == d68010_movec) + return 0; + if(g_instruction_table[instruction] == d68010_moves_8) + return 0; + if(g_instruction_table[instruction] == d68010_moves_16) + return 0; + if(g_instruction_table[instruction] == d68010_moves_32) + return 0; + if(g_instruction_table[instruction] == d68010_rtd) + return 0; + case M68K_CPU_TYPE_68010: + if(g_instruction_table[instruction] == d68020_bcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_bfchg) + return 0; + if(g_instruction_table[instruction] == d68020_bfclr) + return 0; + if(g_instruction_table[instruction] == d68020_bfexts) + return 0; + if(g_instruction_table[instruction] == d68020_bfextu) + return 0; + if(g_instruction_table[instruction] == d68020_bfffo) + return 0; + if(g_instruction_table[instruction] == d68020_bfins) + return 0; + if(g_instruction_table[instruction] == d68020_bfset) + return 0; + if(g_instruction_table[instruction] == d68020_bftst) + return 0; + if(g_instruction_table[instruction] == d68020_bra_32) + return 0; + if(g_instruction_table[instruction] == d68020_bsr_32) + return 0; + if(g_instruction_table[instruction] == d68020_callm) + return 0; + if(g_instruction_table[instruction] == d68020_cas_8) + return 0; + if(g_instruction_table[instruction] == d68020_cas_16) + return 0; + if(g_instruction_table[instruction] == d68020_cas_32) + return 0; + if(g_instruction_table[instruction] == d68020_cas2_16) + return 0; + if(g_instruction_table[instruction] == d68020_cas2_32) + return 0; + if(g_instruction_table[instruction] == d68020_chk_32) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_8) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_16) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_32) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_8) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_8) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_16) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_16) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_32) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_32) + return 0; + if(g_instruction_table[instruction] == d68020_cpbcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cpbcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_cpdbcc) + return 0; + if(g_instruction_table[instruction] == d68020_cpgen) + return 0; + if(g_instruction_table[instruction] == d68020_cprestore) + return 0; + if(g_instruction_table[instruction] == d68020_cpsave) + return 0; + if(g_instruction_table[instruction] == d68020_cpscc) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_0) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_divl) + return 0; + if(g_instruction_table[instruction] == d68020_extb_32) + return 0; + if(g_instruction_table[instruction] == d68020_link_32) + return 0; + if(g_instruction_table[instruction] == d68020_mull) + return 0; + if(g_instruction_table[instruction] == d68020_pack_rr) + return 0; + if(g_instruction_table[instruction] == d68020_pack_mm) + return 0; + if(g_instruction_table[instruction] == d68020_rtm) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_0) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_a_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_a_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_32) + return 0; + if(g_instruction_table[instruction] == d68020_unpk_rr) + return 0; + if(g_instruction_table[instruction] == d68020_unpk_mm) + return 0; + case M68K_CPU_TYPE_68EC020: + case M68K_CPU_TYPE_68020: + case M68K_CPU_TYPE_68030: + if(g_instruction_table[instruction] == d68040_cinv) + return 0; + if(g_instruction_table[instruction] == d68040_cpush) + return 0; + if(g_instruction_table[instruction] == d68040_move16_pi_pi) + return 0; + if(g_instruction_table[instruction] == d68040_move16_pi_al) + return 0; + if(g_instruction_table[instruction] == d68040_move16_al_pi) + return 0; + if(g_instruction_table[instruction] == d68040_move16_ai_al) + return 0; + if(g_instruction_table[instruction] == d68040_move16_al_ai) + return 0; + } + if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 && + (g_instruction_table[instruction] == d68020_callm || + g_instruction_table[instruction] == d68020_rtm)) + return 0; + + return 1; +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/src/cpu/m68k/m68kmake.c b/src/cpu/m68k/m68kmake.c new file mode 100644 index 00000000..e2c88929 --- /dev/null +++ b/src/cpu/m68k/m68kmake.c @@ -0,0 +1,1482 @@ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.3 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright 1998-2001 Karl Stenerud. All rights reserved. + * + * This code may be freely used for non-commercial purposes as long as this + * copyright notice remains unaltered in the source code and any binary files + * containing this code in compiled form. + * + * All other lisencing terms must be negotiated with the author + * (Karl Stenerud). + * + * The latest version of this code can be obtained at: + * http://kstenerud.cjb.net + */ + +/* + * Modified For OpenVMS By: Robert Alan Byer + * byer@mail.ourservers.net + */ + + +/* ======================================================================== */ +/* ============================ CODE GENERATOR ============================ */ +/* ======================================================================== */ +/* + * This is the code generator program which will generate the opcode table + * and the final opcode handlers. + * + * It requires an input file to function (default m68k_in.c), but you can + * specify your own like so: + * + * m68kmake + * + * where output path is the path where the output files should be placed, and + * input file is the file to use for input. + * + * If you modify the input file greatly from its released form, you may have + * to tweak the configuration section a bit since I'm using static allocation + * to keep things simple. + * + * + * TODO: - build a better code generator for the move instruction. + * - Add callm and rtm instructions + * - Fix RTE to handle other format words + * - Add address error (and bus error?) handling + */ + + +const char* g_version = "3.3"; + +/* ======================================================================== */ +/* =============================== INCLUDES =============================== */ +/* ======================================================================== */ + +#include +#include +#include +#include +#include + + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +#define M68K_MAX_PATH 1024 +#define M68K_MAX_DIR 1024 + +#define MAX_LINE_LENGTH 200 /* length of 1 line */ +#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */ +#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */ +#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */ +#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */ +#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */ +#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */ +#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */ +#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */ +#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */ + +/* Default filenames */ +#define FILENAME_INPUT "m68k_in.c" +#define FILENAME_PROTOTYPE "m68kops.h" +#define FILENAME_TABLE "m68kops.c" +#define FILENAME_OPS_AC "m68kopac.c" +#define FILENAME_OPS_DM "m68kopdm.c" +#define FILENAME_OPS_NZ "m68kopnz.c" + + +/* Identifier sequences recognized by this program */ + +#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + +#define ID_BASE "M68KMAKE" +#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER" +#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER" +#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER" +#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER" +#define ID_TABLE_BODY ID_BASE "_TABLE_BODY" +#define ID_TABLE_START ID_BASE "_TABLE_START" +#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER" +#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER" +#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY" +#define ID_END ID_BASE "_END" + +#define ID_OPHANDLER_NAME ID_BASE "_OP" +#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8" +#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16" +#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32" +#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8" +#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16" +#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32" +#define ID_OPHANDLER_CC ID_BASE "_CC" +#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC" + + +#ifndef DECL_SPEC +#define DECL_SPEC +#endif /* DECL_SPEC */ + + + +/* ======================================================================== */ +/* ============================== PROTOTYPES ============================== */ +/* ======================================================================== */ + +enum { + CPU_TYPE_000 = 0, + CPU_TYPE_010, + CPU_TYPE_020, + NUM_CPUS +}; + +#define UNSPECIFIED "." +#define UNSPECIFIED_CH '.' + +#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0) +#define HAS_EA_AI(A) ((A)[0] == 'A') +#define HAS_EA_PI(A) ((A)[1] == '+') +#define HAS_EA_PD(A) ((A)[2] == '-') +#define HAS_EA_DI(A) ((A)[3] == 'D') +#define HAS_EA_IX(A) ((A)[4] == 'X') +#define HAS_EA_AW(A) ((A)[5] == 'W') +#define HAS_EA_AL(A) ((A)[6] == 'L') +#define HAS_EA_PCDI(A) ((A)[7] == 'd') +#define HAS_EA_PCIX(A) ((A)[8] == 'x') +#define HAS_EA_I(A) ((A)[9] == 'I') + +enum +{ + EA_MODE_NONE, /* No special addressing mode */ + EA_MODE_AI, /* Address register indirect */ + EA_MODE_PI, /* Address register indirect with postincrement */ + EA_MODE_PI7, /* Address register 7 indirect with postincrement */ + EA_MODE_PD, /* Address register indirect with predecrement */ + EA_MODE_PD7, /* Address register 7 indirect with predecrement */ + EA_MODE_DI, /* Address register indirect with displacement */ + EA_MODE_IX, /* Address register indirect with index */ + EA_MODE_AW, /* Absolute word */ + EA_MODE_AL, /* Absolute long */ + EA_MODE_PCDI, /* Program counter indirect with displacement */ + EA_MODE_PCIX, /* Program counter indirect with index */ + EA_MODE_I /* Immediate */ +}; + + +/* Everything we need to know about an opcode */ +typedef struct +{ + char name[MAX_NAME_LENGTH]; /* opcode handler name */ + unsigned char size; /* Size of operation */ + char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */ + char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */ + unsigned char bits; /* Number of significant bits (used for sorting the table) */ + unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */ + unsigned short op_match; /* Value to match after masking */ + char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */ + char cpu_mode[NUM_CPUS]; /* User or supervisor mode */ + char cpus[NUM_CPUS+1]; /* Allowed CPUs */ + unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020 */ +} opcode_struct; + + +/* All modifications necessary for a specific EA mode of an instruction */ +typedef struct +{ + const char* fname_add; + const char* ea_add; + unsigned int mask_add; + unsigned int match_add; +} ea_info_struct; + + +/* Holds the body of a function */ +typedef struct +{ + char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1]; + int length; +} body_struct; + + +/* Holds a sequence of search / replace strings */ +typedef struct +{ + char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1]; + int length; +} replace_struct; + + +/* Function Prototypes */ +void error_exit(const char* fmt, ...); +void perror_exit(const char* fmt, ...); +int check_strsncpy(char* dst, char* src, int maxlength); +int check_atoi(char* str, int *result); +int skip_spaces(char* str); +int num_bits(int value); +int atoh(char* buff); +int fgetline(char* buff, int nchars, FILE* file); +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type); +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea); +opcode_struct* find_illegal_opcode(void); +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea); +void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str); +void write_body(FILE* filep, body_struct* body, replace_struct* replace); +void get_base_name(char* base_name, opcode_struct* op); +void write_prototype(FILE* filep, char* base_name); +void write_function_name(FILE* filep, char* base_name); +void add_opcode_output_table_entry(opcode_struct* op, char* name); +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr); +void print_opcode_output_table(FILE* filep); +void write_table_entry(FILE* filep, opcode_struct* op); +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode); +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode); +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op); +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset); +void process_opcode_handlers(void); +void populate_table(void); +void read_insert(char* insert); + + + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +/* Name of the input file */ +char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT; + +/* File handles */ +FILE* g_input_file = NULL; +FILE* g_prototype_file = NULL; +FILE* g_table_file = NULL; +FILE* g_ops_ac_file = NULL; +FILE* g_ops_dm_file = NULL; +FILE* g_ops_nz_file = NULL; + +int g_num_functions = 0; /* Number of functions processed */ +int g_num_primitives = 0; /* Number of function primitives read */ +int g_line_number = 1; /* Current line number */ + +/* Opcode handler table */ +opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH]; + +opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH]; +int g_opcode_output_table_length = 0; + +ea_info_struct g_ea_info_table[13] = +{/* fname ea mask match */ + {"", "", 0x00, 0x00}, /* EA_MODE_NONE */ + {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */ + {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */ + {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */ + {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */ + {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */ + {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */ + {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */ + {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */ + {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */ + {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */ + {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */ + {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */ +}; + + +const char* g_cc_table[16][2] = +{ + { "t", "T"}, /* 0000 */ + { "f", "F"}, /* 0001 */ + {"hi", "HI"}, /* 0010 */ + {"ls", "LS"}, /* 0011 */ + {"cc", "CC"}, /* 0100 */ + {"cs", "CS"}, /* 0101 */ + {"ne", "NE"}, /* 0110 */ + {"eq", "EQ"}, /* 0111 */ + {"vc", "VC"}, /* 1000 */ + {"vs", "VS"}, /* 1001 */ + {"pl", "PL"}, /* 1010 */ + {"mi", "MI"}, /* 1011 */ + {"ge", "GE"}, /* 1100 */ + {"lt", "LT"}, /* 1101 */ + {"gt", "GT"}, /* 1110 */ + {"le", "LE"}, /* 1111 */ +}; + +/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */ +int g_size_select_table[33] = +{ + 0, /* unsized */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */ +}; + +/* Extra cycles required for certain EA modes */ +int g_ea_cycle_table[13][NUM_CPUS][3] = +{/* 000 010 020 */ + {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_AI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}}, /* EA_MODE_PI7 */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}}, /* EA_MODE_PD7 */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_DI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_IX */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}}, /* EA_MODE_AW */ + {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}}, /* EA_MODE_AL */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}}, /* EA_MODE_PCDI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}}, /* EA_MODE_PCIX */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}}, /* EA_MODE_I */ +}; + +/* Extra cycles for JMP instruction (000, 010) */ +int g_jmp_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 10, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for JSR instruction (000, 010) */ +int g_jsr_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 10, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for LEA instruction (000, 010) */ +int g_lea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 8, /* EA_MODE_DI */ + 12, /* EA_MODE_IX */ + 8, /* EA_MODE_AW */ + 12, /* EA_MODE_AL */ + 8, /* EA_MODE_PCDI */ + 12, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for PEA instruction (000, 010) */ +int g_pea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 6, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 10, /* EA_MODE_DI */ + 14, /* EA_MODE_IX */ + 10, /* EA_MODE_AW */ + 14, /* EA_MODE_AL */ + 10, /* EA_MODE_PCDI */ + 14, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for MOVEM instruction (000, 010) */ +int g_movem_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 0, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 4, /* EA_MODE_DI */ + 6, /* EA_MODE_IX */ + 4, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 0, /* EA_MODE_PCDI */ + 0, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for MOVES instruction (010) */ +int g_moves_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 12}, /* EA_MODE_PD */ + { 0, 6, 12}, /* EA_MODE_PD7 */ + { 0, 12, 16}, /* EA_MODE_DI */ + { 0, 16, 20}, /* EA_MODE_IX */ + { 0, 12, 16}, /* EA_MODE_AW */ + { 0, 16, 20}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + +/* Extra cycles for CLR instruction (010) */ +int g_clr_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 8}, /* EA_MODE_PD */ + { 0, 6, 8}, /* EA_MODE_PD7 */ + { 0, 8, 10}, /* EA_MODE_DI */ + { 0, 10, 14}, /* EA_MODE_IX */ + { 0, 8, 10}, /* EA_MODE_AW */ + { 0, 10, 14}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + +/* Print an error message and exit with status error */ +void error_exit(const char* fmt, ...) +{ + va_list args; + fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_ops_ac_file) fclose(g_ops_ac_file); + if(g_ops_dm_file) fclose(g_ops_dm_file); + if(g_ops_nz_file) fclose(g_ops_nz_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + +/* Print an error message, call perror(), and exit with status error */ +void perror_exit(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + perror(""); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_ops_ac_file) fclose(g_ops_ac_file); + if(g_ops_dm_file) fclose(g_ops_dm_file); + if(g_ops_nz_file) fclose(g_ops_nz_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + + +/* copy until 0 or space and exit with error if we read too far */ +int check_strsncpy(char* dst, char* src, int maxlength) +{ + char* p = dst; + while(*src && *src != ' ') + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* copy until 0 or specified character and exit with error if we read too far */ +int check_strcncpy(char* dst, char* src, char delim, int maxlength) +{ + char* p = dst; + while(*src && *src != delim) + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* convert ascii to integer and exit with error if we find invalid data */ +int check_atoi(char* str, int *result) +{ + int accum = 0; + char* p = str; + while(*p >= '0' && *p <= '9') + { + accum *= 10; + accum += *p++ - '0'; + } + if(*p != ' ' && *p != 0) + error_exit("Malformed integer value (%c)", *p); + *result = accum; + return p - str; +} + +/* Skip past spaces in a string */ +int skip_spaces(char* str) +{ + char* p = str; + + while(*p == ' ') + p++; + + return p - str; +} + +/* Count the number of set bits in a value */ +int num_bits(int value) +{ + value = ((value & 0xaaaa) >> 1) + (value & 0x5555); + value = ((value & 0xcccc) >> 2) + (value & 0x3333); + value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f); + value = ((value & 0xff00) >> 8) + (value & 0x00ff); + return value; +} + +/* Convert a hex value written in ASCII */ +int atoh(char* buff) +{ + int accum = 0; + + for(;;buff++) + { + if(*buff >= '0' && *buff <= '9') + { + accum <<= 4; + accum += *buff - '0'; + } + else if(*buff >= 'a' && *buff <= 'f') + { + accum <<= 4; + accum += *buff - 'a' + 10; + } + else break; + } + return accum; +} + +/* Get a line of text from a file, discarding any end-of-line characters */ +int fgetline(char* buff, int nchars, FILE* file) +{ + int length; + + if(fgets(buff, nchars, file) == NULL) + return -1; + if(buff[0] == '\r') + memcpy(buff, buff + 1, nchars - 1); + + length = strlen(buff); + while(length && (buff[length-1] == '\r' || buff[length-1] == '\n')) + length--; + buff[length] = 0; + g_line_number++; + + return length; +} + + + +/* ======================================================================== */ +/* =========================== HELPER FUNCTIONS =========================== */ +/* ======================================================================== */ + +/* Calculate the number of cycles an opcode requires */ +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) +{ + int size = g_size_select_table[op->size]; + + if(op->cpus[cpu_type] == '.') + return 0; + + if(cpu_type < CPU_TYPE_020) + { + if(cpu_type == CPU_TYPE_010) + { + if(strcmp(op->name, "moves") == 0) + return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size]; + if(strcmp(op->name, "clr") == 0) + return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size]; + } + + /* ASG: added these cases -- immediate modes take 2 extra cycles here */ + /* SV: but only when operating on long, and also on register direct mode */ + if(cpu_type == CPU_TYPE_000 && (ea_mode == EA_MODE_I || ea_mode == EA_MODE_NONE) && op->size == 32 && + ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "adda") == 0 || + (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "suba") == 0)) + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; + + if(strcmp(op->name, "jmp") == 0) + return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; + if(strcmp(op->name, "jsr") == 0) + return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode]; + if(strcmp(op->name, "lea") == 0) + return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode]; + if(strcmp(op->name, "pea") == 0) + return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode]; + if(strcmp(op->name, "movem") == 0) + return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode]; + } + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size]; +} + +/* Find an opcode in the opcode handler list */ +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea) +{ + opcode_struct* op; + + + for(op = g_opcode_input_table;op->name != NULL;op++) + { + if( strcmp(name, op->name) == 0 && + (size == op->size) && + strcmp(spec_proc, op->spec_proc) == 0 && + strcmp(spec_ea, op->spec_ea) == 0) + return op; + } + return NULL; +} + +/* Specifically find the illegal opcode in the list */ +opcode_struct* find_illegal_opcode(void) +{ + opcode_struct* op; + + for(op = g_opcode_input_table;op->name != NULL;op++) + { + if(strcmp(op->name, "illegal") == 0) + return op; + } + return NULL; +} + +/* Parse an opcode handler name */ +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea) +{ + char* ptr = strstr(src, ID_OPHANDLER_NAME); + + if(ptr == NULL) + return 0; + + ptr += strlen(ID_OPHANDLER_NAME) + 1; + + ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + *size = atoi(ptr); + ptr = strstr(ptr, ","); + if(ptr == NULL) return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH); + if(*ptr != ')') return 0; + ptr++; + ptr += skip_spaces(ptr); + + return 1; +} + + +/* Add a search/replace pair to a replace structure */ +void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str) +{ + if(replace->length >= MAX_REPLACE_LENGTH) + error_exit("overflow in replace structure"); + + strcpy(replace->replace[replace->length][0], search_str); + strcpy(replace->replace[replace->length++][1], replace_str); +} + +/* Write a function body while replacing any selected strings */ +void write_body(FILE* filep, body_struct* body, replace_struct* replace) +{ + int i; + int j; + char* ptr; + char output[MAX_LINE_LENGTH+1]; + char temp_buff[MAX_LINE_LENGTH+1]; + int found; + + for(i=0;ilength;i++) + { + strcpy(output, body->body[i]); + /* Check for the base directive header */ + if(strstr(output, ID_BASE) != NULL) + { + /* Search for any text we need to replace */ + found = 0; + for(j=0;jlength;j++) + { + ptr = strstr(output, replace->replace[j][0]); + if(ptr) + { + /* We found something to replace */ + found = 1; + strcpy(temp_buff, ptr+strlen(replace->replace[j][0])); + strcpy(ptr, replace->replace[j][1]); + strcat(ptr, temp_buff); + } + } + /* Found a directive with no matching replace string */ + if(!found) + error_exit("Unknown " ID_BASE " directive"); + } + fprintf(filep, "%s\n", output); + } + fprintf(filep, "\n\n"); +} + +/* Generate a base function name from an opcode struct */ +void get_base_name(char* base_name, opcode_struct* op) +{ + sprintf(base_name, "m68k_op_%s", op->name); + if(op->size > 0) + sprintf(base_name+strlen(base_name), "_%d", op->size); + if(strcmp(op->spec_proc, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_proc); + if(strcmp(op->spec_ea, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_ea); +} + +/* Write the prototype of an opcode handler function */ +void write_prototype(FILE* filep, char* base_name) +{ + fprintf(filep, "void %s(void);\n", base_name); +} + +/* Write the name of an opcode handler function */ +void write_function_name(FILE* filep, char* base_name) +{ + fprintf(filep, "void %s(void)\n", base_name); +} + +void add_opcode_output_table_entry(opcode_struct* op, char* name) +{ + opcode_struct* ptr; + if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH) + error_exit("Opcode output table overflow"); + + ptr = g_opcode_output_table + g_opcode_output_table_length++; + + *ptr = *op; + strcpy(ptr->name, name); + ptr->bits = num_bits(ptr->op_mask); +} + +/* + * Comparison function for qsort() + * For entries with an equal number of set bits in + * the mask compare the match values + */ +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr) +{ + const opcode_struct *a = aptr, *b = bptr; + if(a->bits != b->bits) + return a->bits - b->bits; + if(a->op_mask != b->op_mask) + return a->op_mask - b->op_mask; + return a->op_match - b->op_match; +} + +void print_opcode_output_table(FILE* filep) +{ + int i; + qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits); + + for(i=0;iname, op->op_mask, op->op_match); + + for(i=0;icycles[i]); + if(i < NUM_CPUS-1) + fprintf(filep, ", "); + } + + fprintf(filep, "}},\n"); +} + +/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */ +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode) +{ + int i; + + *dst = *src; + + for(i=0;icycles[i] = get_oper_cycles(dst, ea_mode, i); + if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE) + sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add); + dst->op_mask |= g_ea_info_table[ea_mode].mask_add; + dst->op_match |= g_ea_info_table[ea_mode].match_add; +} + + +/* Generate a final opcode handler from the provided data */ +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode) +{ + char str[MAX_LINE_LENGTH+1]; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + /* Set the opcode structure and write the tables, prototypes, etc */ + set_opcode_struct(opinfo, op, ea_mode); + get_base_name(str, op); + write_prototype(g_prototype_file, str); + add_opcode_output_table_entry(op, str); + write_function_name(filep, str); + + /* Add any replace strings needed */ + if(ea_mode != EA_MODE_NONE) + { + sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str); + sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str); + sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str); + sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str); + sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str); + sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str); + } + + /* Now write the function body with the selected replace strings */ + write_body(filep, body, replace); + g_num_functions++; + free(op); +} + +/* Generate opcode variants based on available addressing modes */ +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op) +{ + int old_length = replace->length; + + /* No ea modes available for this opcode */ + if(HAS_NO_EA_MODE(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE); + return; + } + + /* Check for and create specific opcodes for each available addressing mode */ + if(HAS_EA_AI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AI); + replace->length = old_length; + if(HAS_EA_PI(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7); + } + replace->length = old_length; + if(HAS_EA_PD(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7); + } + replace->length = old_length; + if(HAS_EA_DI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_DI); + replace->length = old_length; + if(HAS_EA_IX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_IX); + replace->length = old_length; + if(HAS_EA_AW(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AW); + replace->length = old_length; + if(HAS_EA_AL(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AL); + replace->length = old_length; + if(HAS_EA_PCDI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI); + replace->length = old_length; + if(HAS_EA_PCIX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX); + replace->length = old_length; + if(HAS_EA_I(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_I); + replace->length = old_length; +} + +/* Generate variants of condition code opcodes */ +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset) +{ + char repl[20]; + char replnot[20]; + int i; + int old_length = replace->length; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + *op = *op_in; + + op->op_mask |= 0x0f00; + + /* Do all condition codes except t and f */ + for(i=2;i<16;i++) + { + /* Add replace strings for this condition code */ + sprintf(repl, "COND_%s()", g_cc_table[i][1]); + sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]); + + add_replace_string(replace, ID_OPHANDLER_CC, repl); + add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot); + + /* Set the new opcode info */ + strcpy(op->name+offset, g_cc_table[i][0]); + + op->op_match = (op->op_match & 0xf0ff) | (i<<8); + + /* Generate all opcode variants for this modified opcode */ + generate_opcode_ea_variants(filep, body, replace, op); + /* Remove the above replace strings */ + replace->length = old_length; + } + free(op); +} + +/* Process the opcode handlers section of the input file */ +void process_opcode_handlers(void) +{ + FILE* input_file = g_input_file; + FILE* output_file; + char func_name[MAX_LINE_LENGTH+1]; + char oper_name[MAX_LINE_LENGTH+1]; + int oper_size; + char oper_spec_proc[MAX_LINE_LENGTH+1]; + char oper_spec_ea[MAX_LINE_LENGTH+1]; + opcode_struct* opinfo; + replace_struct* replace = malloc(sizeof(replace_struct)); + body_struct* body = malloc(sizeof(body_struct)); + + + output_file = g_ops_ac_file; + + for(;;) + { + /* Find the first line of the function */ + func_name[0] = 0; + while(strstr(func_name, ID_OPHANDLER_NAME) == NULL) + { + if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0) + { + free(replace); + free(body); + return; /* all done */ + } + if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function name"); + } + /* Get the rest of the function */ + for(body->length=0;;body->length++) + { + if(body->length > MAX_BODY_LENGTH) + error_exit("Function too long"); + + if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function body"); + + if(body->body[body->length][0] == '}') + { + body->length++; + break; + } + } + + g_num_primitives++; + + /* Extract the function name information */ + if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea)) + error_exit("Invalid " ID_OPHANDLER_NAME " format"); + + /* Find the corresponding table entry */ + opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea); + if(opinfo == NULL) + error_exit("Unable to find matching table entry for %s", func_name); + + /* Change output files if we pass 'c' or 'n' */ + if(output_file == g_ops_ac_file && oper_name[0] > 'c') + output_file = g_ops_dm_file; + else if(output_file == g_ops_dm_file && oper_name[0] > 'm') + output_file = g_ops_nz_file; + + replace->length = 0; + + /* Generate opcode variants */ + if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 1); + else if(strcmp(opinfo->name, "dbcc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 2); + else if(strcmp(opinfo->name, "trapcc") == 0) + generate_opcode_cc_variants(output_file, body, replace, opinfo, 4); + else + generate_opcode_ea_variants(output_file, body, replace, opinfo); + } + + free(replace); + free(body); +} + + +/* Populate the opcode handler table from the input file */ +void populate_table(void) +{ + char* ptr; + char bitpattern[17]; + opcode_struct* op; + char buff[MAX_LINE_LENGTH]; + int i; + int temp; + + buff[0] = 0; + + /* Find the start of the table */ + while(strcmp(buff, ID_TABLE_START) != 0) + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading table"); + + /* Process the entire table */ + for(op = g_opcode_input_table;;op++) + { + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading table"); + if(strlen(buff) == 0) + continue; + /* We finish when we find an input separator */ + if(strcmp(buff, ID_INPUT_SEPARATOR) == 0) + break; + + /* Extract the info from the table */ + ptr = buff; + + /* Name */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH); + + /* Size */ + ptr += skip_spaces(ptr); + ptr += check_atoi(ptr, &temp); + op->size = (unsigned char)temp; + + /* Special processing */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH); + + /* Specified EA Mode */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH); + + /* Bit Pattern (more processing later) */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(bitpattern, ptr, 17); + + /* Allowed Addressing Mode List */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH); + + /* CPU operating mode (U = user or supervisor, S = supervisor only */ + ptr += skip_spaces(ptr); + for(i=0;icpu_mode[i] = *ptr++; + ptr += skip_spaces(ptr); + } + + /* Allowed CPUs for this instruction */ + for(i=0;icpus[i] = UNSPECIFIED_CH; + op->cycles[i] = 0; + ptr++; + } + else + { + op->cpus[i] = '0' + i; + ptr += check_atoi(ptr, &temp); + op->cycles[i] = (unsigned char)temp; + } + } + + /* generate mask and match from bitpattern */ + op->op_mask = 0; + op->op_match = 0; + for(i=0;i<16;i++) + { + op->op_mask |= (bitpattern[i] != '.') << (15-i); + op->op_match |= (bitpattern[i] == '1') << (15-i); + } + } + /* Terminate the list */ + op->name[0] = 0; +} + +/* Read a header or footer insert from the input file */ +void read_insert(char* insert) +{ + char* ptr = insert; + char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH; + int length; + char* first_blank = NULL; + + first_blank = NULL; + + /* Skip any leading blank lines */ + for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if(length < 0) + error_exit("Premature EOF while reading inserts"); + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + + /* Read until next separator */ + for(;;) + { + /* Read a new line */ + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0) + error_exit("Premature EOF while reading inserts"); + + /* Stop if we read a separator */ + if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0) + break; + + /* keep track in case there are trailing blanks */ + if(length == 0) + { + if(first_blank == NULL) + first_blank = ptr; + } + else + first_blank = NULL; + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + } + + /* kill any trailing blank lines */ + if(first_blank) + ptr = first_blank; + *ptr++ = 0; +} + + + +/* ======================================================================== */ +/* ============================= MAIN FUNCTION ============================ */ +/* ======================================================================== */ + +int main(int argc, char **argv) +{ + /* File stuff */ + char output_path[M68K_MAX_DIR] = ""; + char filename[M68K_MAX_PATH]; + /* Section identifier */ + char section_id[MAX_LINE_LENGTH+1]; + /* Inserts */ + char temp_insert[MAX_INSERT_LENGTH+1]; + char prototype_footer_insert[MAX_INSERT_LENGTH+1]; + char table_footer_insert[MAX_INSERT_LENGTH+1]; + char ophandler_footer_insert[MAX_INSERT_LENGTH+1]; + /* Flags if we've processed certain parts already */ + int prototype_header_read = 0; + int prototype_footer_read = 0; + int table_header_read = 0; + int table_footer_read = 0; + int ophandler_header_read = 0; + int ophandler_footer_read = 0; + int table_body_read = 0; + int ophandler_body_read = 0; + + printf("\n\t\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020 emulator\n", g_version); + printf("\t\tCopyright 1998-2000 Karl Stenerud (karl@mame.net)\n\n"); + + /* Check if output path and source for the input file are given */ + if(argc > 1) + { + char *ptr; + strcpy(output_path, argv[1]); + + for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\')) + *ptr = '/'; + +#if !(defined(__DECC) && defined(VMS)) + if(output_path[strlen(output_path)-1] != '/') + strcat(output_path, "/"); +#endif + + if(argc > 2) + strcpy(g_input_filename, argv[2]); + } + + +#if defined(__DECC) && defined(VMS) + + /* Open the files we need */ + sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); + if((g_prototype_file = fopen(filename, "w")) == NULL) + perror_exit("Unable to create prototype file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_TABLE); + if((g_table_file = fopen(filename, "w")) == NULL) + perror_exit("Unable to create table file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC); + if((g_ops_ac_file = fopen(filename, "w")) == NULL) + perror_exit("Unable to create ops ac file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM); + if((g_ops_dm_file = fopen(filename, "w")) == NULL) + perror_exit("Unable to create ops dm file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ); + if((g_ops_nz_file = fopen(filename, "w")) == NULL) + perror_exit("Unable to create ops nz file (%s)\n", filename); + + if((g_input_file=fopen(g_input_filename, "r")) == NULL) + perror_exit("can't open %s for input", g_input_filename); + +#else + + + /* Open the files we need */ + sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); + if((g_prototype_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create prototype file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_TABLE); + if((g_table_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create table file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_AC); + if((g_ops_ac_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops ac file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_DM); + if((g_ops_dm_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops dm file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_OPS_NZ); + if((g_ops_nz_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create ops nz file (%s)\n", filename); + + if((g_input_file=fopen(g_input_filename, "rt")) == NULL) + perror_exit("can't open %s for input", g_input_filename); + +#endif + + /* Get to the first section of the input file */ + section_id[0] = 0; + while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0) + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + + /* Now process all sections */ + for(;;) + { + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0) + { + if(prototype_header_read) + error_exit("Duplicate prototype header"); + read_insert(temp_insert); + fprintf(g_prototype_file, "%s\n\n", temp_insert); + prototype_header_read = 1; + } + else if(strcmp(section_id, ID_TABLE_HEADER) == 0) + { + if(table_header_read) + error_exit("Duplicate table header"); + read_insert(temp_insert); + fprintf(g_table_file, "%s", temp_insert); + table_header_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0) + { + if(ophandler_header_read) + error_exit("Duplicate opcode handler header"); + read_insert(temp_insert); + fprintf(g_ops_ac_file, "%s\n\n", temp_insert); + fprintf(g_ops_dm_file, "%s\n\n", temp_insert); + fprintf(g_ops_nz_file, "%s\n\n", temp_insert); + ophandler_header_read = 1; + } + else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0) + { + if(prototype_footer_read) + error_exit("Duplicate prototype footer"); + read_insert(prototype_footer_insert); + prototype_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_FOOTER) == 0) + { + if(table_footer_read) + error_exit("Duplicate table footer"); + read_insert(table_footer_insert); + table_footer_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0) + { + if(ophandler_footer_read) + error_exit("Duplicate opcode handler footer"); + read_insert(ophandler_footer_insert); + ophandler_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Table body encountered before prototype header"); + if(!table_header_read) + error_exit("Table body encountered before table header"); + if(!ophandler_header_read) + error_exit("Table body encountered before opcode handler header"); + + if(table_body_read) + error_exit("Duplicate table body"); + + populate_table(); + table_body_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Opcode handlers encountered before prototype header"); + if(!table_header_read) + error_exit("Opcode handlers encountered before table header"); + if(!ophandler_header_read) + error_exit("Opcode handlers encountered before opcode handler header"); + if(!table_body_read) + error_exit("Opcode handlers encountered before table body"); + + if(ophandler_body_read) + error_exit("Duplicate opcode handler section"); + + process_opcode_handlers(); + + ophandler_body_read = 1; + } + else if(strcmp(section_id, ID_END) == 0) + { + /* End of input file. Do a sanity check and then write footers */ + if(!prototype_header_read) + error_exit("Missing prototype header"); + if(!prototype_footer_read) + error_exit("Missing prototype footer"); + if(!table_header_read) + error_exit("Missing table header"); + if(!table_footer_read) + error_exit("Missing table footer"); + if(!table_body_read) + error_exit("Missing table body"); + if(!ophandler_header_read) + error_exit("Missing opcode handler header"); + if(!ophandler_footer_read) + error_exit("Missing opcode handler footer"); + if(!ophandler_body_read) + error_exit("Missing opcode handler body"); + + print_opcode_output_table(g_table_file); + + fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert); + fprintf(g_table_file, "%s\n\n", table_footer_insert); + fprintf(g_ops_ac_file, "%s\n\n", ophandler_footer_insert); + fprintf(g_ops_dm_file, "%s\n\n", ophandler_footer_insert); + fprintf(g_ops_nz_file, "%s\n\n", ophandler_footer_insert); + + break; + } + else + { + error_exit("Unknown section identifier: %s", section_id); + } + } + + /* Close all files and exit */ + fclose(g_prototype_file); + fclose(g_table_file); + fclose(g_ops_ac_file); + fclose(g_ops_dm_file); + fclose(g_ops_nz_file); + fclose(g_input_file); + + printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives); + + return 0; +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/src/cpu/nec/nec.cpp b/src/cpu/nec/nec.cpp new file mode 100644 index 00000000..3352e0b4 --- /dev/null +++ b/src/cpu/nec/nec.cpp @@ -0,0 +1,762 @@ +/**************************************************************************** + + NEC V20/V30/V33 emulator + + --------------------------------------------- + + V20 = uPD70108 = 8-bit data bus @ 5MHz or 8MHz + V20HL = uPD70108H = V20 with EMS support (24-bit address bus) + + V25 = uPD70320 = V20 with on-chip features: + - 256 bytes on-chip RAM + - 8 register banks + - 4-bit input port + - 20-bit I/O port + - 2 channel serial interface + - interrupt controller + - 2 channel DMA controller + - 2 channel 16-bit timer + - new instructions: BTCLR, RETRBI, STOP, BRKCS, TSKSW, + MOVSPA, MOVSPB + + V25+ = uPD70325 = V25 @ 8MHz or 10MHz plus changes: + - faster DMA + - improved serial interface + + --------------------------------------------- + + V30 = uPD70116 = 16-bit data bus version of V20 + V30HL = uPD70116H = 16-bit data bus version of V20HL + V30MX = V30HL with separate address and data busses + + V35 = uPD70330 = 16-bit data bus version of V25 + + V35+ = uPD70335 = 16-bit data bus version of V25+ + + --------------------------------------------- + + V40 = uPD70208 = 8-bit data bus @ 10MHz + V40HL = uPD70208H = V40 with support up to 20Mhz + + --------------------------------------------- + + V50 = uPD70216 = 16-bit data bus version of V40 + V50HL = uPD70216H = 16-bit data bus version of V40HL + + --------------------------------------------- + + V41 = uPD70270 + + V51 = uPD70280 + + + + V33A = uPD70136A + + V53A = uPD70236A + + + + Instruction differences: + V20, V30, V40, V50 have dedicated emulation instructions + (BRKEM, RETEM, CALLN) + + V33A, V53A has dedicated address mode instructions + (BRKXA, RETXA) + + + + (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based + on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code + on the i286 emulator by Fabrice Frances which had initial work based on + David Hedley's pcemu(!). + + This new core features 99% accurate cycle counts for each processor, + there are still some complex situations where cycle counts are wrong, + typically where a few instructions have differing counts for odd/even + source and odd/even destination memory operands. + + Flag settings are also correct for the NEC processors rather than the + I86 versions. + + Changelist: + + 22/02/2003: + Removed cycle counts from memory accesses - they are certainly wrong, + and there is already a memory access cycle penalty in the opcodes + using them. + + Fixed save states. + + Fixed ADJBA/ADJBS/ADJ4A/ADJ4S flags/return values for all situations. + (Fixes bugs in Geostorm and Thunderblaster) + + Fixed carry flag on NEG (I thought this had been fixed circa Mame 0.58, + but it seems I never actually submitted the fix). + + Fixed many cycle counts in instructions and bug in cycle count + macros (odd word cases were testing for odd instruction word address + not data address). + + Todo! + Double check cycle timing is 100%. + +****************************************************************************/ + +#include +#include +#include "driver.h" +#include "state.h" +#include "vez.h" +//#include "emu.h" +//#include "debugger.h" + +#define offs_t int //? +//typedef UINT8 unsigned char +//typedef UINT16 unsigned short +//typedef UINT32 unsigned int +#define INT8 char +#define INT16 short +#define INT32 int +#define INPUT_LINE_NMI 0x20 // nmi + +#define NEC_INLINE +#define NEC_CPU_CPP + +unsigned char cpu_readmem20_op(unsigned int); +unsigned char cpu_readmem20_arg(unsigned int); +unsigned char cpu_readport(unsigned int); +void cpu_writeport(unsigned int,unsigned int); + +static NEC_INLINE void write_mem_word(unsigned int a, unsigned short d) +{ + cpu_writemem20((a),(unsigned char)(d)); + cpu_writemem20((a)+1,(d)>>8); +} + +static NEC_INLINE void write_port_word(unsigned int a, unsigned short d) +{ + cpu_writeport((a),(unsigned char)(d)); + cpu_writeport((a)+1,(d)>>8); +} + +typedef UINT8 BOOLEAN; +typedef UINT8 BYTE; +typedef UINT16 WORD; +typedef UINT32 DWORD; + +#include "nec.h" +#include "necpriv.h" + +static nec_state_t sChips[4]; // 4 cpus should be plenty! +static nec_state_t *sChipsPtr; + +NEC_INLINE void prefetch(nec_state_t *nec_state) +{ + nec_state->prefetch_count--; +} + +static void do_prefetch(nec_state_t *nec_state, int previous_ICount) +{ + int diff = previous_ICount - (int) nec_state->icount; + + /* The implementation is not accurate, but comes close. + * It does not respect that the V30 will fetch two bytes + * at once directly, but instead uses only 2 cycles instead + * of 4. There are however only very few sources publicly + * available and they are vague. + */ + while (nec_state->prefetch_count<0) + { + nec_state->prefetch_count++; + if (diff>nec_state->prefetch_cycles) + diff -= nec_state->prefetch_cycles; + else + nec_state->icount -= nec_state->prefetch_cycles; + } + + if (nec_state->prefetch_reset) + { + nec_state->prefetch_count = 0; + nec_state->prefetch_reset = 0; + return; + } + + while (diff>=nec_state->prefetch_cycles && nec_state->prefetch_count < nec_state->prefetch_size) + { + diff -= nec_state->prefetch_cycles; + nec_state->prefetch_count++; + } + +} + +NEC_INLINE UINT8 fetch(nec_state_t *nec_state) +{ + prefetch(nec_state); + return cpu_readop_arg(((Sreg(PS)<<4)+nec_state->ip++) ^ nec_state->fetch_xor); // ^ fetch_xor? +} + +NEC_INLINE UINT16 fetchword(nec_state_t *nec_state) +{ + UINT16 r = FETCH(); + r |= (FETCH()<<8); + return r; +} + +#include "necinstr.h" +#include "necmacro.h" +#include "necea.h" +#include "necmodrm.h" + +static UINT8 parity_table[256]; + +static UINT8 fetchop(nec_state_t *nec_state) +{ + prefetch(nec_state); + return cpu_readop(((Sreg(PS)<<4)+nec_state->ip++) ^ nec_state->fetch_xor); +} + + +/***************************************************************************/ + +int nec_reset() +{ + nec_state_t *nec_state = sChipsPtr; + + memset( &nec_state->regs.w, 0, sizeof(nec_state->regs.w)); + + nec_state->ip = 0; + nec_state->TF = 0; + nec_state->IF = 0; + nec_state->DF = 0; + nec_state->MF = 1; // brkem should set to 0 when implemented + nec_state->SignVal = 0; + nec_state->AuxVal = 0; + nec_state->OverVal = 0; + nec_state->ZeroVal = 1; + nec_state->CarryVal = 0; + nec_state->ParityVal = 1; + nec_state->pending_irq = 0; + nec_state->nmi_state = 0; + nec_state->irq_state = 0; + nec_state->poll_state = 1; + nec_state->halted = 0; + nec_state->cycles_total = 0; + nec_state->cycles_remaining = 0; + nec_state->vector = 0xff; //default vector + + Sreg(PS) = 0xffff; + Sreg(SS) = 0; + Sreg(DS0) = 0; + Sreg(DS1) = 0; + + CHANGE_PC; + + return 0; +} + +static void nec_interrupt(nec_state_t *nec_state, unsigned int_num, INTSOURCES source) +{ + UINT32 dest_seg, dest_off; + + i_pushf(nec_state); + nec_state->TF = nec_state->IF = 0; + + if (source == INT_IRQ) /* get vector */ + int_num = nec_state->vector; + + dest_off = read_mem_word(int_num*4); + dest_seg = read_mem_word(int_num*4+2); + + PUSH(Sreg(PS)); + PUSH(nec_state->ip); + nec_state->ip = (WORD)dest_off; + Sreg(PS) = (WORD)dest_seg; + CHANGE_PC; +} + +static void nec_trap(nec_state_t *nec_state) +{ + nec_instruction[fetchop(nec_state)](nec_state); + nec_interrupt(nec_state, NEC_TRAP_VECTOR, BRK); +} + +static void external_int(nec_state_t *nec_state) +{ + if (nec_state->pending_irq & NMI_IRQ) + { + nec_interrupt(nec_state, NEC_NMI_VECTOR, NMI_IRQ); + nec_state->pending_irq &= ~NMI_IRQ; + } + else if (nec_state->pending_irq) + { + /* the actual vector is retrieved after pushing flags */ + /* and clearing the IF */ + nec_interrupt(nec_state, (UINT32)-1, INT_IRQ); + nec_state->irq_state = CLEAR_LINE; + nec_state->pending_irq &= ~INT_IRQ; + } +} + +/****************************************************************************/ +/* OPCODES */ +/****************************************************************************/ + +#include "necinstr.c" + +/*****************************************************************************/ + +void nec_set_irq_line_and_vector(int irqline, int vector, int state) +{ + nec_state_t *nec_state = sChipsPtr; + + switch (irqline) + { + case 0: + nec_state->irq_state = state; + if (state == CLEAR_LINE) + nec_state->pending_irq &= ~INT_IRQ; + else + { + nec_state->vector = vector; + nec_state->pending_irq |= INT_IRQ; + nec_state->halted = 0; + } + break; + case INPUT_LINE_NMI: + if (nec_state->nmi_state == (unsigned int)state) return; + nec_state->nmi_state = state; + if (state != CLEAR_LINE) + { + nec_state->vector = vector; + nec_state->pending_irq |= NMI_IRQ; + nec_state->halted = 0; + } + break; + case NEC_INPUT_LINE_POLL: + nec_state->vector = vector; + nec_state->poll_state = state; + break; + } +} + +void nec_init(int cpu) +{ + nec_state_t *nec_state = &sChips[cpu]; + + unsigned int i, j, c; + + static const WREGS wreg_name[8]={ AW, CW, DW, BW, SP, BP, IX, IY }; + static const BREGS breg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH }; + + for (i = 0; i < 256; i++) + { + for (j = i, c = 0; j > 0; j >>= 1) + if (j & 1) c++; + parity_table[i] = !(c & 1); + } + + for (i = 0; i < 256; i++) + { + Mod_RM.reg.b[i] = breg_name[(i & 0x38) >> 3]; + Mod_RM.reg.w[i] = wreg_name[(i & 0x38) >> 3]; + } + + for (i = 0xc0; i < 0x100; i++) + { + Mod_RM.RM.w[i] = wreg_name[i & 7]; + Mod_RM.RM.b[i] = breg_name[i & 7]; + } + + memset(nec_state, 0, sizeof(*nec_state)); +} + +void necCpuOpen(int cpu) +{ + sChipsPtr = &sChips[cpu]; +} + +void necCpuClose() +{ + sChipsPtr = NULL; +} + +unsigned int nec_total_cycles() +{ + return sChipsPtr->cycles_total + (sChipsPtr->cycles_remaining - sChipsPtr->icount); +} + +void nec_new_frame() +{ + for (int i = 0; i < 4; i++) { + nec_state_t *nec_state = &sChips[i]; + nec_state->cycles_total = 0; + } +} + +void nec_set_vector(int vector) +{ + nec_state_t *nec_state = sChipsPtr; + nec_state->vector = vector; +} + +void necRunEnd() +{ + sChipsPtr->stop_run = 1; +} + +void necIdle(int cycles) +{ + sChipsPtr->icount -= cycles; +} + +int nec_execute(int cycles) +{ + nec_state_t *nec_state = sChipsPtr; + int prev_ICount; + + nec_state->icount = cycles; + nec_state->cycles_remaining = cycles; + + if (nec_state->halted) + { + nec_state->icount = 0; + //debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip); + return cycles; + } + + while((nec_state->icount>0) && (!nec_state->stop_run)) { + /* Dispatch IRQ */ + if (nec_state->pending_irq && nec_state->no_interrupt==0) + { + if (nec_state->pending_irq & NMI_IRQ) + external_int(nec_state); + else if (nec_state->IF) + external_int(nec_state); + } + + /* No interrupt allowed between last instruction and this one */ + if (nec_state->no_interrupt) + nec_state->no_interrupt--; + + //debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip); + prev_ICount = nec_state->icount; + nec_instruction[fetchop(nec_state)](nec_state); + do_prefetch(nec_state, prev_ICount); + } + + nec_state->cycles_total += cycles - nec_state->icount; + nec_state->cycles_remaining = 0; + nec_state->stop_run = 0; + + return (cycles - nec_state->icount); +} + +void necInit(int cpu, int type) +{ + nec_state_t *nec_state = &sChips[cpu]; + + nec_init(cpu); + + switch (type) + { + case V20_TYPE: + { + nec_state->fetch_xor = 0; + nec_state->chip_type=V20_TYPE; + nec_state->prefetch_size = 4; /* 3 words */ + nec_state->prefetch_cycles = 4; /* four cycles per byte */ + } + break; + + case V30_TYPE: + { + nec_state->fetch_xor = 0;//BYTE_XOR_LE(0); + nec_state->chip_type=V30_TYPE; + nec_state->prefetch_size = 6; /* 3 words */ + nec_state->prefetch_cycles = 2; /* two cycles per byte / four per word */ + } + break; + + case V33_TYPE: + { + nec_state->fetch_xor = 0;//BYTE_XOR_LE(0); + nec_state->chip_type=V33_TYPE; + nec_state->prefetch_size = 6; + /* FIXME: Need information about prefetch size and cycles for V33. + * complete guess below, nbbatman will not work + * properly without. */ + nec_state->prefetch_cycles = 1; /* two cycles per byte / four per word */ + } + break; + } +} + +int necGetPC(int n) +{ + if (n == -1) { // current cpu + return ((sChipsPtr->sregs[PS]<<4) + sChipsPtr->ip); + } else { + nec_state_t *nec_state = &sChips[n]; + return ((nec_state->sregs[PS]<<4) + nec_state->ip); + } +} + +void necScan(int cpu, int nAction) +{ + nec_state_t *nec_state = &sChips[cpu]; + + if (nAction & ACB_DRIVER_DATA) { + struct BurnArea ba; + char szText[] = "NEC #0"; + szText[5] = '1' + cpu; + + memset(&ba, 0, sizeof(ba)); + + ba.Data = (unsigned char*)nec_state; + ba.nLen = sizeof(nec_state_t); + ba.szName = szText; + BurnAcb(&ba); + } +} + + +#if 0 + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static CPU_SET_INFO( nec ) +{ + nec_state_t *nec_state = get_safe_token(device); + + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_irq_line(nec_state, NEC_INPUT_LINE_POLL, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: + if( info->i - (Sreg(PS)<<4) < 0x10000 ) + { + nec_state->ip = info->i - (Sreg(PS)<<4); + } + else + { + Sreg(PS) = info->i >> 4; + nec_state->ip = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break; + case CPUINFO_INT_SP: + if( info->i - (Sreg(SS)<<4) < 0x10000 ) + { + Wreg(SP) = info->i - (Sreg(SS)<<4); + } + else + { + Sreg(SS) = info->i >> 4; + Wreg(SP) = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break; + case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static CPU_GET_INFO( nec ) +{ + nec_state_t *nec_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + int flags; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(nec_state_t); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 80; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: info->i = (nec_state->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = nec_state->nmi_state; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: info->i = nec_state->poll_state; break; + + case CPUINFO_INT_PREVIOUSPC: /* not supported */ break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break; + case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break; + case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break; + case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break; + case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break; + case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break; + case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break; + case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break; + case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break; + case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break; + case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break; + case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break; + case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break; + case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(nec); break; + case CPUINFO_FCT_INIT: /* set per-CPU */ break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(nec); break; + case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(nec); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(necv); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(nec); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "NEC"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Bryan McPhail (V25/V35 support added by Alex W. Jackson)"); break; + + case CPUINFO_STR_FLAGS: + flags = CompressFlags(); + sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + flags & 0x8000 ? 'N':'E', + flags & 0x4000 ? '?':'.', + flags & 0x2000 ? '?':'.', + flags & 0x1000 ? '?':'.', + flags & 0x0800 ? 'O':'.', + flags & 0x0400 ? 'D':'.', + flags & 0x0200 ? 'I':'.', + flags & 0x0100 ? 'T':'.', + flags & 0x0080 ? 'S':'.', + flags & 0x0040 ? 'Z':'.', + flags & 0x0020 ? '?':'.', + flags & 0x0010 ? 'A':'.', + flags & 0x0008 ? '?':'.', + flags & 0x0004 ? 'P':'.', + flags & 0x0002 ? '.':'?', + flags & 0x0001 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%05X", (Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break; + case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break; + case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break; + case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break; + case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break; + case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break; + case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break; + case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break; + case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break; + case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break; + case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break; + case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break; + case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v20 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v20); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V20"); break; + + default: CPU_GET_INFO_CALL(nec); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v30 ) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v30); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V30"); break; + + default: CPU_GET_INFO_CALL(nec); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v33 ) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v33); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V33"); break; + + default: CPU_GET_INFO_CALL(nec); break; + } +} + +DEFINE_LEGACY_CPU_DEVICE(V20, v20); +DEFINE_LEGACY_CPU_DEVICE(V30, v30); +DEFINE_LEGACY_CPU_DEVICE(V33, v33); + +#endif diff --git a/src/cpu/nec/nec.h b/src/cpu/nec/nec.h new file mode 100644 index 00000000..1b22c808 --- /dev/null +++ b/src/cpu/nec/nec.h @@ -0,0 +1,37 @@ +/* ASG 971222 -- rewrote this interface */ +#ifndef __NEC_H_ +#define __NEC_H_ + + +typedef struct _nec_config nec_config; +struct _nec_config +{ + const UINT8* v25v35_decryptiontable; // internal decryption table +}; + +#define NEC_INPUT_LINE_INTP0 10 +#define NEC_INPUT_LINE_INTP1 11 +#define NEC_INPUT_LINE_INTP2 12 +#define NEC_INPUT_LINE_POLL 20 + +#define V25_PORT_P0 0x10000 +#define V25_PORT_P1 0x10002 +#define V25_PORT_P2 0x10004 +#define V25_PORT_PT 0x10006 + +enum +{ + NEC_PC=0, + NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY, + NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS, + NEC_PENDING +}; + +/* Public functions */ +//DECLARE_LEGACY_CPU_DEVICE(V20, v20); +//DECLARE_LEGACY_CPU_DEVICE(V25, v25); +//DECLARE_LEGACY_CPU_DEVICE(V30, v30); +//DECLARE_LEGACY_CPU_DEVICE(V33, v33); +//DECLARE_LEGACY_CPU_DEVICE(V35, v35); + +#endif diff --git a/src/cpu/nec/necea.h b/src/cpu/nec/necea.h new file mode 100644 index 00000000..cafbb27a --- /dev/null +++ b/src/cpu/nec/necea.h @@ -0,0 +1,60 @@ + +static UINT32 EA; +static UINT16 EO; +static UINT16 E16; + +static unsigned EA_000(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_001(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_002(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IX); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_003(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IY); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_004(nec_state_t *nec_state) { EO=Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_005(nec_state_t *nec_state) { EO=Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_006(nec_state_t *nec_state) { EO=FETCH(); EO+=FETCH()<<8; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_007(nec_state_t *nec_state) { EO=Wreg(BW); EA=DefaultBase(DS0)+EO; return EA; } + +static unsigned EA_100(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_101(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_102(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_103(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_104(nec_state_t *nec_state) { EO=(Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_105(nec_state_t *nec_state) { EO=(Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_106(nec_state_t *nec_state) { EO=(Wreg(BP)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_107(nec_state_t *nec_state) { EO=(Wreg(BW)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; } + +static unsigned EA_200(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_201(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_202(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IX)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_203(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IY)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_204(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_205(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } +static unsigned EA_206(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; } +static unsigned EA_207(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; } + +static unsigned (*const GetEA[192])(nec_state_t *)={ + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007, + + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107, + + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207, + EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207 +}; diff --git a/src/cpu/nec/necinstr.c b/src/cpu/nec/necinstr.c new file mode 100644 index 00000000..ac8e8a7b --- /dev/null +++ b/src/cpu/nec/necinstr.c @@ -0,0 +1,673 @@ +#define OP(num,func_name) static void func_name(nec_state_t *nec_state) + +OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x06, i_push_es ) { PUSH(Sreg(DS1)); CLKS(12,8,3); } +OP( 0x07, i_pop_es ) { POP(Sreg(DS1)); CLKS(12,8,5); } + +OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x0e, i_push_cs ) { PUSH(Sreg(PS)); CLKS(12,8,3); } +#if defined NEC_CPU_CPP +OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2; + switch (FETCH()) { + case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; + case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; + case 0x31 : ModRM = FETCH(); ModRM=0; break; + case 0x33 : ModRM = FETCH(); ModRM=0; break; + case 0xe0 : ModRM = FETCH(); ModRM=0; break; + case 0xf0 : ModRM = FETCH(); ModRM=0; break; + case 0xff : ModRM = FETCH(); ModRM=0; break; +// default: logerror("%06x: Unknown V20 instruction\n",PC(nec_state)); break; + } +} +#endif + +OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x16, i_push_ss ) { PUSH(Sreg(SS)); CLKS(12,8,3); } +OP( 0x17, i_pop_ss ) { POP(Sreg(SS)); CLKS(12,8,5); nec_state->no_interrupt=1; } + +OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x1e, i_push_ds ) { PUSH(Sreg(DS0)); CLKS(12,8,3); } +OP( 0x1f, i_pop_ds ) { POP(Sreg(DS0)); CLKS(12,8,5); } + +OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x26, i_es ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); } + +OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x2e, i_cs ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); } + +OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } +OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);} +OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } +OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; Breg(AL)=dst; CLKS(4,4,2); } +OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; Wreg(AW)=dst; CLKS(4,4,2); } +OP( 0x36, i_ss ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x37, i_aaa ) { ADJB(6, (Breg(AL) > 0xf9) ? 2 : 1); CLKS(7,7,4); } + +OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); } +OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,EA);} +OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); } +OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,EA); } +OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); } +OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); } +OP( 0x3e, i_ds ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; } +OP( 0x3f, i_aas ) { ADJB(-6, (Breg(AL) < 6) ? -2 : -1); CLKS(7,7,4); } + +OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); } +OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); } +OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); } +OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); } +OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); } +OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); } +OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); } +OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); } + +OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); } +OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); } +OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); } +OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); } +OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); } +OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); } +OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); } +OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); } + +OP( 0x50, i_push_ax ) { PUSH(Wreg(AW)); CLKS(12,8,3); } +OP( 0x51, i_push_cx ) { PUSH(Wreg(CW)); CLKS(12,8,3); } +OP( 0x52, i_push_dx ) { PUSH(Wreg(DW)); CLKS(12,8,3); } +OP( 0x53, i_push_bx ) { PUSH(Wreg(BW)); CLKS(12,8,3); } +OP( 0x54, i_push_sp ) { PUSH(Wreg(SP)); CLKS(12,8,3); } +OP( 0x55, i_push_bp ) { PUSH(Wreg(BP)); CLKS(12,8,3); } +OP( 0x56, i_push_si ) { PUSH(Wreg(IX)); CLKS(12,8,3); } +OP( 0x57, i_push_di ) { PUSH(Wreg(IY)); CLKS(12,8,3); } + +OP( 0x58, i_pop_ax ) { POP(Wreg(AW)); CLKS(12,8,5); } +OP( 0x59, i_pop_cx ) { POP(Wreg(CW)); CLKS(12,8,5); } +OP( 0x5a, i_pop_dx ) { POP(Wreg(DW)); CLKS(12,8,5); } +OP( 0x5b, i_pop_bx ) { POP(Wreg(BW)); CLKS(12,8,5); } +OP( 0x5c, i_pop_sp ) { POP(Wreg(SP)); CLKS(12,8,5); } +OP( 0x5d, i_pop_bp ) { POP(Wreg(BP)); CLKS(12,8,5); } +OP( 0x5e, i_pop_si ) { POP(Wreg(IX)); CLKS(12,8,5); } +OP( 0x5f, i_pop_di ) { POP(Wreg(IY)); CLKS(12,8,5); } + +OP( 0x60, i_pusha ) { + unsigned tmp=Wreg(SP); + PUSH(Wreg(AW)); + PUSH(Wreg(CW)); + PUSH(Wreg(DW)); + PUSH(Wreg(BW)); + PUSH(tmp); + PUSH(Wreg(BP)); + PUSH(Wreg(IX)); + PUSH(Wreg(IY)); + CLKS(67,35,20); +} +static unsigned nec_popa_tmp; +OP( 0x61, i_popa ) { + POP(Wreg(IY)); + POP(Wreg(IX)); + POP(Wreg(BP)); + POP(nec_popa_tmp); + POP(Wreg(BW)); + POP(Wreg(DW)); + POP(Wreg(CW)); + POP(Wreg(AW)); + CLKS(75,43,22); +} +OP( 0x62, i_chkind ) { + UINT32 low,high,tmp; + GetModRM; + low = GetRMWord(ModRM); + high= GetnextRMWord; + tmp= RegWord(ModRM); + if (tmphigh) { + nec_interrupt(nec_state, NEC_CHKIND_VECTOR, BRK); + } + nec_state->icount-=20; +// logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(nec_state),high,low,tmp); +} +OP( 0x64, i_repnc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break; + default: nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} + +OP( 0x65, i_repc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break; + default: nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} + +OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,Wreg(SP)); } +OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?38:47;} +OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,Wreg(SP)); } +OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?31:39; } +OP( 0x6c, i_insb ) { PutMemB(DS1,Wreg(IY),read_port_byte(Wreg(DW))); Wreg(IY)+= -2 * nec_state->DF + 1; CLK(8); } +OP( 0x6d, i_insw ) { PutMemW(DS1,Wreg(IY),read_port_word(Wreg(DW))); Wreg(IY)+= -4 * nec_state->DF + 2; CLKS(18,10,8); } +OP( 0x6e, i_outsb ) { write_port_byte(Wreg(DW),GetMemB(DS0,Wreg(IX))); Wreg(IX)+= -2 * nec_state->DF + 1; CLK(8); } +OP( 0x6f, i_outsw ) { write_port_word(Wreg(DW),GetMemW(DS0,Wreg(IX))); Wreg(IX)+= -4 * nec_state->DF + 2; CLKS(18,10,8); } + +OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); } +OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); } +OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); } +OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); } +OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); } +OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); } +OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); } +OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); } +OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); } +OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); } +OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); } +OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); } +OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); } +OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); } +OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); } +OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); } + +OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH(); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) + switch (ModRM & 0x38) { + case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; + case 0x08: ORB; PutbackRMByte(ModRM,dst); break; + case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; + case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; + case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; + case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; + case 0x30: XORB; PutbackRMByte(ModRM,dst); break; + case 0x38: SUBB; break; /* CMP */ + } +} + +OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) + switch (ModRM & 0x38) { + case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; + case 0x08: ORW; PutbackRMWord(ModRM,dst); break; + case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; + case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; + case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; + case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; + case 0x30: XORW; PutbackRMWord(ModRM,dst); break; + case 0x38: SUBW; break; /* CMP */ + } +} + +OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH()); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) + switch (ModRM & 0x38) { + case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; + case 0x08: ORB; PutbackRMByte(ModRM,dst); break; + case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; + case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; + case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; + case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; + case 0x30: XORB; PutbackRMByte(ModRM,dst); break; + case 0x38: SUBB; break; /* CMP */ + } +} + +OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH())); + if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA) + switch (ModRM & 0x38) { + case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; + case 0x08: ORW; PutbackRMWord(ModRM,dst); break; + case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; + case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; + case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; + case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; + case 0x30: XORW; PutbackRMWord(ModRM,dst); break; + case 0x38: SUBW; break; /* CMP */ + } +} + +OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); } +OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,EA); } +OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); } +OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,EA); } + +OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); } +OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,EA); } +OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); } +OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,EA); } +OP( 0x8c, i_mov_wsreg ) { GetModRM; + switch (ModRM & 0x38) { + case 0x00: PutRMWord(ModRM,Sreg(DS1)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x08: PutRMWord(ModRM,Sreg(PS)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x10: PutRMWord(ModRM,Sreg(SS)); CLKR(14,14,5,14,10,3,2,EA); break; + case 0x18: PutRMWord(ModRM,Sreg(DS0)); CLKR(14,14,5,14,10,3,2,EA); break; +// default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state)); + } +} +OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(*GetEA[ModRM])(nec_state); RegWord(ModRM)=EO; CLKS(4,4,2); } +OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,EA); + switch (ModRM & 0x38) { + case 0x00: Sreg(DS1) = src; break; /* mov es,ew */ + case 0x08: Sreg(PS) = src; break; /* mov cs,ew */ + case 0x10: Sreg(SS) = src; break; /* mov ss,ew */ + case 0x18: Sreg(DS0) = src; break; /* mov ds,ew */ +// default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state)); + } + nec_state->no_interrupt=1; +} +OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); nec_state->icount-=21; } +OP( 0x90, i_nop ) { CLK(3); /* { if (nec_state->MF == 0) printf("90 -> %06x: \n",PC(nec_state)); } */ } +OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } +OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } +OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } +OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } +OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } +OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } +OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } + +OP( 0x98, i_cbw ) { Breg(AH) = (Breg(AL) & 0x80) ? 0xff : 0; CLK(2); } +OP( 0x99, i_cwd ) { Wreg(DW) = (Breg(AH) & 0x80) ? 0xffff : 0; CLK(4); } +OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(Sreg(PS)); PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; Sreg(PS) = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,Wreg(SP)); } +OP( 0x9b, i_wait ) { if (!nec_state->poll_state) nec_state->ip--; CLK(5); } +OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); } +OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (nec_state->TF) nec_trap(nec_state); } +OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (Breg(AH) & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); } +OP( 0x9f, i_lahf ) { Breg(AH) = CompressFlags() & 0xff; CLKS(3,3,2); } + +OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); Breg(AL) = GetMemB(DS0, addr); CLKS(10,10,5); } +OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); Wreg(AW) = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); } +OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, Breg(AL)); CLKS(9,9,3); } +OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, Wreg(AW)); CLKW(13,13,5,13,9,3,addr); } +OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,Wreg(IX)); PutMemB(DS1,Wreg(IY), tmp); Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(8,8,6); } +OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,Wreg(IX)); PutMemW(DS1,Wreg(IY), tmp); Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(16,16,10); } +OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = GetMemB(DS0, Wreg(IX)); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(14,14,14); } +OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = GetMemW(DS0, Wreg(IX)); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(14,14,14); } + +OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); } +OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); } +OP( 0xaa, i_stosb ) { PutMemB(DS1,Wreg(IY),Breg(AL)); Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xab, i_stosw ) { PutMemW(DS1,Wreg(IY),Wreg(AW)); Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } +OP( 0xac, i_lodsb ) { Breg(AL) = GetMemB(DS0,Wreg(IX)); Wreg(IX) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xad, i_lodsw ) { Wreg(AW) = GetMemW(DS0,Wreg(IX)); Wreg(IX) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IX)); } +OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = Breg(AL); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); } +OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = Wreg(AW); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } + +OP( 0xb0, i_mov_ald8 ) { Breg(AL) = FETCH(); CLKS(4,4,2); } +OP( 0xb1, i_mov_cld8 ) { Breg(CL) = FETCH(); CLKS(4,4,2); } +OP( 0xb2, i_mov_dld8 ) { Breg(DL) = FETCH(); CLKS(4,4,2); } +OP( 0xb3, i_mov_bld8 ) { Breg(BL) = FETCH(); CLKS(4,4,2); } +OP( 0xb4, i_mov_ahd8 ) { Breg(AH) = FETCH(); CLKS(4,4,2); } +OP( 0xb5, i_mov_chd8 ) { Breg(CH) = FETCH(); CLKS(4,4,2); } +OP( 0xb6, i_mov_dhd8 ) { Breg(DH) = FETCH(); CLKS(4,4,2); } +OP( 0xb7, i_mov_bhd8 ) { Breg(BH) = FETCH(); CLKS(4,4,2); } + +OP( 0xb8, i_mov_axd16 ) { Breg(AL) = FETCH(); Breg(AH) = FETCH(); CLKS(4,4,2); } +OP( 0xb9, i_mov_cxd16 ) { Breg(CL) = FETCH(); Breg(CH) = FETCH(); CLKS(4,4,2); } +OP( 0xba, i_mov_dxd16 ) { Breg(DL) = FETCH(); Breg(DH) = FETCH(); CLKS(4,4,2); } +OP( 0xbb, i_mov_bxd16 ) { Breg(BL) = FETCH(); Breg(BH) = FETCH(); CLKS(4,4,2); } +OP( 0xbc, i_mov_spd16 ) { Wreg(SP) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbd, i_mov_bpd16 ) { Wreg(BP) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbe, i_mov_sid16 ) { Wreg(IX) = FETCHWORD(); CLKS(4,4,2); } +OP( 0xbf, i_mov_did16 ) { Wreg(IY) = FETCHWORD(); CLKS(4,4,2); } + +OP( 0xc0, i_rotshft_bd8 ) { + UINT32 src, dst; UINT8 c; + GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; + c=FETCH(); + CLKM(7,7,2,19,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; +// case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(c); break; + } +} + +OP( 0xc1, i_rotshft_wd8 ) { + UINT32 src, dst; UINT8 c; + GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; + c=FETCH(); + CLKM(7,7,2,27,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; +// case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(c); break; + } +} + +OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); Wreg(SP)+=count; CHANGE_PC; CLKS(24,24,10); } +OP( 0xc3, i_ret ) { POP(nec_state->ip); CHANGE_PC; CLKS(19,19,10); } +OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS1) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } +OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS0) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); } +OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:11; } +OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:15; } + +OP( 0xc8, i_enter ) { + UINT32 nb = FETCH(); + UINT32 i,level; + + nec_state->icount-=23; + nb += FETCH() << 8; + level = FETCH(); + PUSH(Wreg(BP)); + Wreg(BP)=Wreg(SP); + Wreg(SP) -= nb; + for (i=1;iicount-=16; + } + if (level) PUSH(Wreg(BP)); +} +OP( 0xc9, i_leave ) { + Wreg(SP)=Wreg(BP); + POP(Wreg(BP)); + nec_state->icount-=8; +} +OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); POP(Sreg(PS)); Wreg(SP)+=count; CHANGE_PC; CLKS(32,32,16); } +OP( 0xcb, i_retf ) { POP(nec_state->ip); POP(Sreg(PS)); CHANGE_PC; CLKS(29,29,16); } +OP( 0xcc, i_int3 ) { nec_interrupt(nec_state, 3, BRK); CLKS(50,50,24); } +OP( 0xcd, i_int ) { nec_interrupt(nec_state, FETCH(), BRK); CLKS(50,50,24); } +OP( 0xce, i_into ) { if (OF) { nec_interrupt(nec_state, NEC_BRKV_VECTOR, BRK); CLKS(52,52,26); } else CLK(3); } +OP( 0xcf, i_iret ) { POP(nec_state->ip); POP(Sreg(PS)); i_popf(nec_state); CHANGE_PC; CLKS(39,39,19); } + +OP( 0xd0, i_rotshft_b ) { + UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; + CLKM(6,6,2,16,16,7); + switch (ModRM & 0x38) { + case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break; + case 0x20: SHL_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; + case 0x28: SHR_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break; +// case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(1); nec_state->OverVal = 0; break; + } +} + +OP( 0xd1, i_rotshft_w ) { + UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; + CLKM(6,6,2,24,16,7); + switch (ModRM & 0x38) { + case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x20: SHL_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; + case 0x28: SHR_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break; +// case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(1); nec_state->OverVal = 0; break; + } +} + +OP( 0xd2, i_rotshft_bcl ) { + UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; + c=Breg(CL); + CLKM(7,7,2,19,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; + case 0x20: SHL_BYTE(c); break; + case 0x28: SHR_BYTE(c); break; +// case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_BYTE(c); break; + } +} + +OP( 0xd3, i_rotshft_wcl ) { + UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; + c=Breg(CL); + CLKM(7,7,2,27,19,6); + if (c) switch (ModRM & 0x38) { + case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; + case 0x20: SHL_WORD(c); break; + case 0x28: SHR_WORD(c); break; +// case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC(nec_state)); break; + case 0x38: SHRA_WORD(c); break; + } +} + +OP( 0xd4, i_aam ) { FETCH(); Breg(AH) = Breg(AL) / 10; Breg(AL) %= 10; SetSZPF_Word(Wreg(AW)); CLKS(15,15,12); } +OP( 0xd5, i_aad ) { FETCH(); Breg(AL) = Breg(AH) * 10 + Breg(AL); Breg(AH) = 0; SetSZPF_Byte(Breg(AL)); CLKS(7,7,8); } +OP( 0xd6, i_setalc ) { Breg(AL) = (CF)?0xff:0x00; nec_state->icount-=3; } +OP( 0xd7, i_trans ) { UINT32 dest = (Wreg(BW)+Breg(AL))&0xffff; Breg(AL) = GetMemB(DS0, dest); CLKS(9,9,5); } +OP( 0xd8, i_fpo ) { GetModRM; ModRM = ModRM; nec_state->icount-=2; } + +OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (!ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } +OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if ( ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } +OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } +OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (Wreg(CW) == 0) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } +OP( 0xe4, i_inal ) { UINT8 port = FETCH(); Breg(AL) = read_port_byte(port); CLKS(9,9,5); } +OP( 0xe5, i_inax ) { UINT8 port = FETCH(); Wreg(AW) = read_port_word(port); CLKW(13,13,7,13,9,5,port); } +OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, Breg(AL)); CLKS(8,8,3); } +OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, Wreg(AW)); CLKW(12,12,5,12,8,3,port); } + +OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(nec_state->ip); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=24; } +OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=15; } +OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); Sreg(PS) = (WORD)tmp1; nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=27; } +OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); nec_state->icount-=12; nec_state->ip = (WORD)(nec_state->ip+tmp); } +OP( 0xec, i_inaldx ) { Breg(AL) = read_port_byte(Wreg(DW)); CLKS(8,8,5);} +OP( 0xed, i_inaxdx ) { Wreg(AW) = read_port_word(Wreg(DW)); CLKW(12,12,7,12,8,5,Wreg(DW)); } +OP( 0xee, i_outdxal ) { write_port_byte(Wreg(DW), Breg(AL)); CLKS(8,8,3); } +OP( 0xef, i_outdxax ) { write_port_word(Wreg(DW), Wreg(AW)); CLKW(12,12,5,12,8,3,Wreg(DW)); } + +OP( 0xf0, i_lock ) { nec_state->no_interrupt=1; CLK(2); } +OP( 0xf2, i_repne ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; + default: nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} +OP( 0xf3, i_repe ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW); + switch(next) { /* Segments */ + case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break; + case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break; + } + + switch(next) { + case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break; + case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; + default: nec_instruction[next](nec_state); + } + nec_state->seg_prefix=FALSE; +} +OP( 0xf4, i_hlt ) { nec_state->halted=1; nec_state->icount=0; } +OP( 0xf5, i_cmc ) { nec_state->CarryVal = !CF; CLK(2); } +OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; + GetModRM; tmp = GetRMByte(ModRM); + switch (ModRM & 0x38) { + case 0x00: tmp &= FETCH(); nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Byte(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ +// case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC(nec_state)); break; + case 0x10: PutbackRMByte(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ + case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ + case 0x20: uresult = Breg(AL)*tmp; Wreg(AW)=(WORD)uresult; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ + case 0x28: result = (INT16)((INT8)Breg(AL))*(INT16)((INT8)tmp); Wreg(AW)=(WORD)result; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ + case 0x30: if (tmp) { DIVUB; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + case 0x38: if (tmp) { DIVB; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + } +} + +OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2; + GetModRM; tmp = GetRMWord(ModRM); + switch (ModRM & 0x38) { + case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Word(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ +// case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC(nec_state)); break; + case 0x10: PutbackRMWord(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ + case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ + case 0x20: uresult = Wreg(AW)*tmp; Wreg(AW)=uresult&0xffff; Wreg(DW)=((UINT32)uresult)>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ + case 0x28: result = (INT32)((INT16)Wreg(AW))*(INT32)((INT16)tmp); Wreg(AW)=result&0xffff; Wreg(DW)=result>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ + case 0x30: if (tmp) { DIVUW; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + case 0x38: if (tmp) { DIVW; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break; + } +} + +OP( 0xf8, i_clc ) { nec_state->CarryVal = 0; CLK(2); } +OP( 0xf9, i_stc ) { nec_state->CarryVal = 1; CLK(2); } +OP( 0xfa, i_di ) { SetIF(0); CLK(2); } +OP( 0xfb, i_ei ) { SetIF(1); CLK(2); } +OP( 0xfc, i_cld ) { SetDF(0); CLK(2); } +OP( 0xfd, i_std ) { SetDF(1); CLK(2); } +OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); + switch(ModRM & 0x38) { + case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */ + case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */ +// default: logerror("%06x: FE Pre with unimplemented mod\n",PC(nec_state)); + } +} +OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); + switch(ModRM & 0x38) { + case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */ + case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */ + case 0x10: PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */ + case 0x18: tmp1 = Sreg(PS); Sreg(PS) = GetnextRMWord; PUSH(tmp1); PUSH(nec_state->ip); nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */ + case 0x20: nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=13; break; /* JMP */ + case 0x28: nec_state->ip = tmp; Sreg(PS) = GetnextRMWord; CHANGE_PC; nec_state->icount-=15; break; /* JMP FAR */ + case 0x30: PUSH(tmp); nec_state->icount-=4; break; +// default: logerror("%06x: FF Pre with unimplemented mod\n",PC(nec_state)); + } +} + +static void i_invalid(nec_state_t *nec_state) +{ + nec_state->icount-=10; +// logerror("%06x: Invalid Opcode\n",PC(nec_state)); +} diff --git a/src/cpu/nec/necinstr.h b/src/cpu/nec/necinstr.h new file mode 100644 index 00000000..30bc3ffc --- /dev/null +++ b/src/cpu/nec/necinstr.h @@ -0,0 +1,507 @@ +static void i_add_br8(nec_state_t *nec_state); +static void i_add_wr16(nec_state_t *nec_state); +static void i_add_r8b(nec_state_t *nec_state); +static void i_add_r16w(nec_state_t *nec_state); +static void i_add_ald8(nec_state_t *nec_state); +static void i_add_axd16(nec_state_t *nec_state); +static void i_push_es(nec_state_t *nec_state); +static void i_pop_es(nec_state_t *nec_state); +static void i_or_br8(nec_state_t *nec_state); +static void i_or_r8b(nec_state_t *nec_state); +static void i_or_wr16(nec_state_t *nec_state); +static void i_or_r16w(nec_state_t *nec_state); +static void i_or_ald8(nec_state_t *nec_state); +static void i_or_axd16(nec_state_t *nec_state); +static void i_push_cs(nec_state_t *nec_state); +static void i_pre_nec(nec_state_t *nec_state); +static void i_adc_br8(nec_state_t *nec_state); +static void i_adc_wr16(nec_state_t *nec_state); +static void i_adc_r8b(nec_state_t *nec_state); +static void i_adc_r16w(nec_state_t *nec_state); +static void i_adc_ald8(nec_state_t *nec_state); +static void i_adc_axd16(nec_state_t *nec_state); +static void i_push_ss(nec_state_t *nec_state); +static void i_pop_ss(nec_state_t *nec_state); +static void i_sbb_br8(nec_state_t *nec_state); +static void i_sbb_wr16(nec_state_t *nec_state); +static void i_sbb_r8b(nec_state_t *nec_state); +static void i_sbb_r16w(nec_state_t *nec_state); +static void i_sbb_ald8(nec_state_t *nec_state); +static void i_sbb_axd16(nec_state_t *nec_state); +static void i_push_ds(nec_state_t *nec_state); +static void i_pop_ds(nec_state_t *nec_state); +static void i_and_br8(nec_state_t *nec_state); +static void i_and_r8b(nec_state_t *nec_state); +static void i_and_wr16(nec_state_t *nec_state); +static void i_and_r16w(nec_state_t *nec_state); +static void i_and_ald8(nec_state_t *nec_state); +static void i_and_axd16(nec_state_t *nec_state); +static void i_es(nec_state_t *nec_state); +static void i_daa(nec_state_t *nec_state); +static void i_sub_br8(nec_state_t *nec_state); +static void i_sub_wr16(nec_state_t *nec_state); +static void i_sub_r8b(nec_state_t *nec_state); +static void i_sub_r16w(nec_state_t *nec_state); +static void i_sub_ald8(nec_state_t *nec_state); +static void i_sub_axd16(nec_state_t *nec_state); +static void i_cs(nec_state_t *nec_state); +static void i_das(nec_state_t *nec_state); +static void i_xor_br8(nec_state_t *nec_state); +static void i_xor_r8b(nec_state_t *nec_state); +static void i_xor_wr16(nec_state_t *nec_state); +static void i_xor_r16w(nec_state_t *nec_state); +static void i_xor_ald8(nec_state_t *nec_state); +static void i_xor_axd16(nec_state_t *nec_state); +static void i_ss(nec_state_t *nec_state); +static void i_aaa(nec_state_t *nec_state); +static void i_cmp_br8(nec_state_t *nec_state); +static void i_cmp_wr16(nec_state_t *nec_state); +static void i_cmp_r8b(nec_state_t *nec_state); +static void i_cmp_r16w(nec_state_t *nec_state); +static void i_cmp_ald8(nec_state_t *nec_state); +static void i_cmp_axd16(nec_state_t *nec_state); +static void i_ds(nec_state_t *nec_state); +static void i_aas(nec_state_t *nec_state); +static void i_inc_ax(nec_state_t *nec_state); +static void i_inc_cx(nec_state_t *nec_state); +static void i_inc_dx(nec_state_t *nec_state); +static void i_inc_bx(nec_state_t *nec_state); +static void i_inc_sp(nec_state_t *nec_state); +static void i_inc_bp(nec_state_t *nec_state); +static void i_inc_si(nec_state_t *nec_state); +static void i_inc_di(nec_state_t *nec_state); +static void i_dec_ax(nec_state_t *nec_state); +static void i_dec_cx(nec_state_t *nec_state); +static void i_dec_dx(nec_state_t *nec_state); +static void i_dec_bx(nec_state_t *nec_state); +static void i_dec_sp(nec_state_t *nec_state); +static void i_dec_bp(nec_state_t *nec_state); +static void i_dec_si(nec_state_t *nec_state); +static void i_dec_di(nec_state_t *nec_state); +static void i_push_ax(nec_state_t *nec_state); +static void i_push_cx(nec_state_t *nec_state); +static void i_push_dx(nec_state_t *nec_state); +static void i_push_bx(nec_state_t *nec_state); +static void i_push_sp(nec_state_t *nec_state); +static void i_push_bp(nec_state_t *nec_state); +static void i_push_si(nec_state_t *nec_state); +static void i_push_di(nec_state_t *nec_state); +static void i_pop_ax(nec_state_t *nec_state); +static void i_pop_cx(nec_state_t *nec_state); +static void i_pop_dx(nec_state_t *nec_state); +static void i_pop_bx(nec_state_t *nec_state); +static void i_pop_sp(nec_state_t *nec_state); +static void i_pop_bp(nec_state_t *nec_state); +static void i_pop_si(nec_state_t *nec_state); +static void i_pop_di(nec_state_t *nec_state); +static void i_pusha(nec_state_t *nec_state); +static void i_popa(nec_state_t *nec_state); +static void i_chkind(nec_state_t *nec_state); +static void i_repnc(nec_state_t *nec_state); +static void i_repc(nec_state_t *nec_state); +static void i_push_d16(nec_state_t *nec_state); +static void i_imul_d16(nec_state_t *nec_state); +static void i_push_d8(nec_state_t *nec_state); +static void i_imul_d8(nec_state_t *nec_state); +static void i_insb(nec_state_t *nec_state); +static void i_insw(nec_state_t *nec_state); +static void i_outsb(nec_state_t *nec_state); +static void i_outsw(nec_state_t *nec_state); +static void i_jo(nec_state_t *nec_state); +static void i_jno(nec_state_t *nec_state); +static void i_jc(nec_state_t *nec_state); +static void i_jnc(nec_state_t *nec_state); +static void i_jz(nec_state_t *nec_state); +static void i_jnz(nec_state_t *nec_state); +static void i_jce(nec_state_t *nec_state); +static void i_jnce(nec_state_t *nec_state); +static void i_js(nec_state_t *nec_state); +static void i_jns(nec_state_t *nec_state); +static void i_jp(nec_state_t *nec_state); +static void i_jnp(nec_state_t *nec_state); +static void i_jl(nec_state_t *nec_state); +static void i_jnl(nec_state_t *nec_state); +static void i_jle(nec_state_t *nec_state); +static void i_jnle(nec_state_t *nec_state); +static void i_80pre(nec_state_t *nec_state); +static void i_82pre(nec_state_t *nec_state); +static void i_81pre(nec_state_t *nec_state); +static void i_83pre(nec_state_t *nec_state); +static void i_test_br8(nec_state_t *nec_state); +static void i_test_wr16(nec_state_t *nec_state); +static void i_xchg_br8(nec_state_t *nec_state); +static void i_xchg_wr16(nec_state_t *nec_state); +static void i_mov_br8(nec_state_t *nec_state); +static void i_mov_r8b(nec_state_t *nec_state); +static void i_mov_wr16(nec_state_t *nec_state); +static void i_mov_r16w(nec_state_t *nec_state); +static void i_mov_wsreg(nec_state_t *nec_state); +static void i_lea(nec_state_t *nec_state); +static void i_mov_sregw(nec_state_t *nec_state); +static void i_invalid(nec_state_t *nec_state); +static void i_popw(nec_state_t *nec_state); +static void i_nop(nec_state_t *nec_state); +static void i_xchg_axcx(nec_state_t *nec_state); +static void i_xchg_axdx(nec_state_t *nec_state); +static void i_xchg_axbx(nec_state_t *nec_state); +static void i_xchg_axsp(nec_state_t *nec_state); +static void i_xchg_axbp(nec_state_t *nec_state); +static void i_xchg_axsi(nec_state_t *nec_state); +static void i_xchg_axdi(nec_state_t *nec_state); +static void i_cbw(nec_state_t *nec_state); +static void i_cwd(nec_state_t *nec_state); +static void i_call_far(nec_state_t *nec_state); +static void i_pushf(nec_state_t *nec_state); +static void i_popf(nec_state_t *nec_state); +static void i_sahf(nec_state_t *nec_state); +static void i_lahf(nec_state_t *nec_state); +static void i_mov_aldisp(nec_state_t *nec_state); +static void i_mov_axdisp(nec_state_t *nec_state); +static void i_mov_dispal(nec_state_t *nec_state); +static void i_mov_dispax(nec_state_t *nec_state); +static void i_movsb(nec_state_t *nec_state); +static void i_movsw(nec_state_t *nec_state); +static void i_cmpsb(nec_state_t *nec_state); +static void i_cmpsw(nec_state_t *nec_state); +static void i_test_ald8(nec_state_t *nec_state); +static void i_test_axd16(nec_state_t *nec_state); +static void i_stosb(nec_state_t *nec_state); +static void i_stosw(nec_state_t *nec_state); +static void i_lodsb(nec_state_t *nec_state); +static void i_lodsw(nec_state_t *nec_state); +static void i_scasb(nec_state_t *nec_state); +static void i_scasw(nec_state_t *nec_state); +static void i_mov_ald8(nec_state_t *nec_state); +static void i_mov_cld8(nec_state_t *nec_state); +static void i_mov_dld8(nec_state_t *nec_state); +static void i_mov_bld8(nec_state_t *nec_state); +static void i_mov_ahd8(nec_state_t *nec_state); +static void i_mov_chd8(nec_state_t *nec_state); +static void i_mov_dhd8(nec_state_t *nec_state); +static void i_mov_bhd8(nec_state_t *nec_state); +static void i_mov_axd16(nec_state_t *nec_state); +static void i_mov_cxd16(nec_state_t *nec_state); +static void i_mov_dxd16(nec_state_t *nec_state); +static void i_mov_bxd16(nec_state_t *nec_state); +static void i_mov_spd16(nec_state_t *nec_state); +static void i_mov_bpd16(nec_state_t *nec_state); +static void i_mov_sid16(nec_state_t *nec_state); +static void i_mov_did16(nec_state_t *nec_state); +static void i_rotshft_bd8(nec_state_t *nec_state); +static void i_rotshft_wd8(nec_state_t *nec_state); +static void i_ret_d16(nec_state_t *nec_state); +static void i_ret(nec_state_t *nec_state); +static void i_les_dw(nec_state_t *nec_state); +static void i_lds_dw(nec_state_t *nec_state); +static void i_mov_bd8(nec_state_t *nec_state); +static void i_mov_wd16(nec_state_t *nec_state); +static void i_enter(nec_state_t *nec_state); +static void i_leave(nec_state_t *nec_state); +static void i_retf_d16(nec_state_t *nec_state); +static void i_retf(nec_state_t *nec_state); +static void i_int3(nec_state_t *nec_state); +static void i_int(nec_state_t *nec_state); +static void i_into(nec_state_t *nec_state); +static void i_iret(nec_state_t *nec_state); +static void i_rotshft_b(nec_state_t *nec_state); +static void i_rotshft_w(nec_state_t *nec_state); +static void i_rotshft_bcl(nec_state_t *nec_state); +static void i_rotshft_wcl(nec_state_t *nec_state); +static void i_aam(nec_state_t *nec_state); +static void i_aad(nec_state_t *nec_state); +static void i_setalc(nec_state_t *nec_state); +static void i_trans(nec_state_t *nec_state); +static void i_fpo(nec_state_t *nec_state); +static void i_loopne(nec_state_t *nec_state); +static void i_loope(nec_state_t *nec_state); +static void i_loop(nec_state_t *nec_state); +static void i_jcxz(nec_state_t *nec_state); +static void i_inal(nec_state_t *nec_state); +static void i_inax(nec_state_t *nec_state); +static void i_outal(nec_state_t *nec_state); +static void i_outax(nec_state_t *nec_state); +static void i_call_d16(nec_state_t *nec_state); +static void i_jmp_d16(nec_state_t *nec_state); +static void i_jmp_far(nec_state_t *nec_state); +static void i_jmp_d8(nec_state_t *nec_state); +static void i_inaldx(nec_state_t *nec_state); +static void i_inaxdx(nec_state_t *nec_state); +static void i_outdxal(nec_state_t *nec_state); +static void i_outdxax(nec_state_t *nec_state); +static void i_lock(nec_state_t *nec_state); +static void i_repne(nec_state_t *nec_state); +static void i_repe(nec_state_t *nec_state); +static void i_hlt(nec_state_t *nec_state); +static void i_cmc(nec_state_t *nec_state); +static void i_f6pre(nec_state_t *nec_state); +static void i_f7pre(nec_state_t *nec_state); +static void i_clc(nec_state_t *nec_state); +static void i_stc(nec_state_t *nec_state); +static void i_di(nec_state_t *nec_state); +static void i_ei(nec_state_t *nec_state); +static void i_cld(nec_state_t *nec_state); +static void i_std(nec_state_t *nec_state); +static void i_fepre(nec_state_t *nec_state); +static void i_ffpre(nec_state_t *nec_state); + +static void i_wait(nec_state_t *nec_state); + +static void (*const nec_instruction[256])(nec_state_t *nec_state) = +{ + i_add_br8, /* 0x00 */ + i_add_wr16, /* 0x01 */ + i_add_r8b, /* 0x02 */ + i_add_r16w, /* 0x03 */ + i_add_ald8, /* 0x04 */ + i_add_axd16, /* 0x05 */ + i_push_es, /* 0x06 */ + i_pop_es, /* 0x07 */ + i_or_br8, /* 0x08 */ + i_or_wr16, /* 0x09 */ + i_or_r8b, /* 0x0a */ + i_or_r16w, /* 0x0b */ + i_or_ald8, /* 0x0c */ + i_or_axd16, /* 0x0d */ + i_push_cs, /* 0x0e */ + i_pre_nec, /* 0x0f */ + i_adc_br8, /* 0x10 */ + i_adc_wr16, /* 0x11 */ + i_adc_r8b, /* 0x12 */ + i_adc_r16w, /* 0x13 */ + i_adc_ald8, /* 0x14 */ + i_adc_axd16, /* 0x15 */ + i_push_ss, /* 0x16 */ + i_pop_ss, /* 0x17 */ + i_sbb_br8, /* 0x18 */ + i_sbb_wr16, /* 0x19 */ + i_sbb_r8b, /* 0x1a */ + i_sbb_r16w, /* 0x1b */ + i_sbb_ald8, /* 0x1c */ + i_sbb_axd16, /* 0x1d */ + i_push_ds, /* 0x1e */ + i_pop_ds, /* 0x1f */ + i_and_br8, /* 0x20 */ + i_and_wr16, /* 0x21 */ + i_and_r8b, /* 0x22 */ + i_and_r16w, /* 0x23 */ + i_and_ald8, /* 0x24 */ + i_and_axd16, /* 0x25 */ + i_es, /* 0x26 */ + i_daa, /* 0x27 */ + i_sub_br8, /* 0x28 */ + i_sub_wr16, /* 0x29 */ + i_sub_r8b, /* 0x2a */ + i_sub_r16w, /* 0x2b */ + i_sub_ald8, /* 0x2c */ + i_sub_axd16, /* 0x2d */ + i_cs, /* 0x2e */ + i_das, /* 0x2f */ + i_xor_br8, /* 0x30 */ + i_xor_wr16, /* 0x31 */ + i_xor_r8b, /* 0x32 */ + i_xor_r16w, /* 0x33 */ + i_xor_ald8, /* 0x34 */ + i_xor_axd16, /* 0x35 */ + i_ss, /* 0x36 */ + i_aaa, /* 0x37 */ + i_cmp_br8, /* 0x38 */ + i_cmp_wr16, /* 0x39 */ + i_cmp_r8b, /* 0x3a */ + i_cmp_r16w, /* 0x3b */ + i_cmp_ald8, /* 0x3c */ + i_cmp_axd16, /* 0x3d */ + i_ds, /* 0x3e */ + i_aas, /* 0x3f */ + i_inc_ax, /* 0x40 */ + i_inc_cx, /* 0x41 */ + i_inc_dx, /* 0x42 */ + i_inc_bx, /* 0x43 */ + i_inc_sp, /* 0x44 */ + i_inc_bp, /* 0x45 */ + i_inc_si, /* 0x46 */ + i_inc_di, /* 0x47 */ + i_dec_ax, /* 0x48 */ + i_dec_cx, /* 0x49 */ + i_dec_dx, /* 0x4a */ + i_dec_bx, /* 0x4b */ + i_dec_sp, /* 0x4c */ + i_dec_bp, /* 0x4d */ + i_dec_si, /* 0x4e */ + i_dec_di, /* 0x4f */ + i_push_ax, /* 0x50 */ + i_push_cx, /* 0x51 */ + i_push_dx, /* 0x52 */ + i_push_bx, /* 0x53 */ + i_push_sp, /* 0x54 */ + i_push_bp, /* 0x55 */ + i_push_si, /* 0x56 */ + i_push_di, /* 0x57 */ + i_pop_ax, /* 0x58 */ + i_pop_cx, /* 0x59 */ + i_pop_dx, /* 0x5a */ + i_pop_bx, /* 0x5b */ + i_pop_sp, /* 0x5c */ + i_pop_bp, /* 0x5d */ + i_pop_si, /* 0x5e */ + i_pop_di, /* 0x5f */ + i_pusha, /* 0x60 */ + i_popa, /* 0x61 */ + i_chkind, /* 0x62 */ + i_invalid, /* 0x63 */ + i_repnc, /* 0x64 */ + i_repc, /* 0x65 */ + i_invalid, /* 0x66 */ + i_invalid, /* 0x67 */ + i_push_d16, /* 0x68 */ + i_imul_d16, /* 0x69 */ + i_push_d8, /* 0x6a */ + i_imul_d8, /* 0x6b */ + i_insb, /* 0x6c */ + i_insw, /* 0x6d */ + i_outsb, /* 0x6e */ + i_outsw, /* 0x6f */ + i_jo, /* 0x70 */ + i_jno, /* 0x71 */ + i_jc, /* 0x72 */ + i_jnc, /* 0x73 */ + i_jz, /* 0x74 */ + i_jnz, /* 0x75 */ + i_jce, /* 0x76 */ + i_jnce, /* 0x77 */ + i_js, /* 0x78 */ + i_jns, /* 0x79 */ + i_jp, /* 0x7a */ + i_jnp, /* 0x7b */ + i_jl, /* 0x7c */ + i_jnl, /* 0x7d */ + i_jle, /* 0x7e */ + i_jnle, /* 0x7f */ + i_80pre, /* 0x80 */ + i_81pre, /* 0x81 */ + i_82pre, /* 0x82 */ + i_83pre, /* 0x83 */ + i_test_br8, /* 0x84 */ + i_test_wr16, /* 0x85 */ + i_xchg_br8, /* 0x86 */ + i_xchg_wr16, /* 0x87 */ + i_mov_br8, /* 0x88 */ + i_mov_wr16, /* 0x89 */ + i_mov_r8b, /* 0x8a */ + i_mov_r16w, /* 0x8b */ + i_mov_wsreg, /* 0x8c */ + i_lea, /* 0x8d */ + i_mov_sregw, /* 0x8e */ + i_popw, /* 0x8f */ + i_nop, /* 0x90 */ + i_xchg_axcx, /* 0x91 */ + i_xchg_axdx, /* 0x92 */ + i_xchg_axbx, /* 0x93 */ + i_xchg_axsp, /* 0x94 */ + i_xchg_axbp, /* 0x95 */ + i_xchg_axsi, /* 0x96 */ + i_xchg_axdi, /* 0x97 */ + i_cbw, /* 0x98 */ + i_cwd, /* 0x99 */ + i_call_far, /* 0x9a */ + i_wait, /* 0x9b */ + i_pushf, /* 0x9c */ + i_popf, /* 0x9d */ + i_sahf, /* 0x9e */ + i_lahf, /* 0x9f */ + i_mov_aldisp, /* 0xa0 */ + i_mov_axdisp, /* 0xa1 */ + i_mov_dispal, /* 0xa2 */ + i_mov_dispax, /* 0xa3 */ + i_movsb, /* 0xa4 */ + i_movsw, /* 0xa5 */ + i_cmpsb, /* 0xa6 */ + i_cmpsw, /* 0xa7 */ + i_test_ald8, /* 0xa8 */ + i_test_axd16, /* 0xa9 */ + i_stosb, /* 0xaa */ + i_stosw, /* 0xab */ + i_lodsb, /* 0xac */ + i_lodsw, /* 0xad */ + i_scasb, /* 0xae */ + i_scasw, /* 0xaf */ + i_mov_ald8, /* 0xb0 */ + i_mov_cld8, /* 0xb1 */ + i_mov_dld8, /* 0xb2 */ + i_mov_bld8, /* 0xb3 */ + i_mov_ahd8, /* 0xb4 */ + i_mov_chd8, /* 0xb5 */ + i_mov_dhd8, /* 0xb6 */ + i_mov_bhd8, /* 0xb7 */ + i_mov_axd16, /* 0xb8 */ + i_mov_cxd16, /* 0xb9 */ + i_mov_dxd16, /* 0xba */ + i_mov_bxd16, /* 0xbb */ + i_mov_spd16, /* 0xbc */ + i_mov_bpd16, /* 0xbd */ + i_mov_sid16, /* 0xbe */ + i_mov_did16, /* 0xbf */ + i_rotshft_bd8, /* 0xc0 */ + i_rotshft_wd8, /* 0xc1 */ + i_ret_d16, /* 0xc2 */ + i_ret, /* 0xc3 */ + i_les_dw, /* 0xc4 */ + i_lds_dw, /* 0xc5 */ + i_mov_bd8, /* 0xc6 */ + i_mov_wd16, /* 0xc7 */ + i_enter, /* 0xc8 */ + i_leave, /* 0xc9 */ + i_retf_d16, /* 0xca */ + i_retf, /* 0xcb */ + i_int3, /* 0xcc */ + i_int, /* 0xcd */ + i_into, /* 0xce */ + i_iret, /* 0xcf */ + i_rotshft_b, /* 0xd0 */ + i_rotshft_w, /* 0xd1 */ + i_rotshft_bcl, /* 0xd2 */ + i_rotshft_wcl, /* 0xd3 */ + i_aam, /* 0xd4 */ + i_aad, /* 0xd5 */ + i_setalc, /* 0xd6 */ + i_trans, /* 0xd7 */ + i_fpo, /* 0xd8 */ + i_fpo, /* 0xd9 */ + i_fpo, /* 0xda */ + i_fpo, /* 0xdb */ + i_fpo, /* 0xdc */ + i_fpo, /* 0xdd */ + i_fpo, /* 0xde */ + i_fpo, /* 0xdf */ + i_loopne, /* 0xe0 */ + i_loope, /* 0xe1 */ + i_loop, /* 0xe2 */ + i_jcxz, /* 0xe3 */ + i_inal, /* 0xe4 */ + i_inax, /* 0xe5 */ + i_outal, /* 0xe6 */ + i_outax, /* 0xe7 */ + i_call_d16, /* 0xe8 */ + i_jmp_d16, /* 0xe9 */ + i_jmp_far, /* 0xea */ + i_jmp_d8, /* 0xeb */ + i_inaldx, /* 0xec */ + i_inaxdx, /* 0xed */ + i_outdxal, /* 0xee */ + i_outdxax, /* 0xef */ + i_lock, /* 0xf0 */ + i_invalid, /* 0xf1 */ + i_repne, /* 0xf2 */ + i_repe, /* 0xf3 */ + i_hlt, /* 0xf4 */ + i_cmc, /* 0xf5 */ + i_f6pre, /* 0xf6 */ + i_f7pre, /* 0xf7 */ + i_clc, /* 0xf8 */ + i_stc, /* 0xf9 */ + i_di, /* 0xfa */ + i_ei, /* 0xfb */ + i_cld, /* 0xfc */ + i_std, /* 0xfd */ + i_fepre, /* 0xfe */ + i_ffpre /* 0xff */ +}; diff --git a/src/cpu/nec/necmacro.h b/src/cpu/nec/necmacro.h new file mode 100644 index 00000000..af71d04b --- /dev/null +++ b/src/cpu/nec/necmacro.h @@ -0,0 +1,266 @@ +/* parameter x = result, y = source 1, z = source 2 */ + +#define SetTF(x) (nec_state->TF = (x)) +#define SetIF(x) (nec_state->IF = (x)) +#define SetDF(x) (nec_state->DF = (x)) +#define SetMD(x) (nec_state->MF = (x)) /* OB [19.07.99] Mode Flag V30 */ + +#define SetCFB(x) (nec_state->CarryVal = (x) & 0x100) +#define SetCFW(x) (nec_state->CarryVal = (x) & 0x10000) +#define SetAF(x,y,z) (nec_state->AuxVal = ((x) ^ ((y) ^ (z))) & 0x10) +#define SetSF(x) (nec_state->SignVal = (x)) +#define SetZF(x) (nec_state->ZeroVal = (x)) +#define SetPF(x) (nec_state->ParityVal = (x)) + +#define SetSZPF_Byte(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT8)(x)) +#define SetSZPF_Word(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT16)(x)) + +#define SetOFW_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000) +#define SetOFB_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80) +#define SetOFW_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000) +#define SetOFB_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80) + +#define ADDB { UINT32 res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; } +#define ADDW { UINT32 res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; } + +#define SUBB { UINT32 res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; } +#define SUBW { UINT32 res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; } + +#define ORB dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define ORW dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define ANDB dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define ANDW dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define XORB dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst) +#define XORW dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst) + +#define IncWordReg(Reg) \ + unsigned tmp = (unsigned)Wreg(Reg); \ + unsigned tmp1 = tmp+1; \ + nec_state->OverVal = (tmp == 0x7fff); \ + SetAF(tmp1,tmp,1); \ + SetSZPF_Word(tmp1); \ + Wreg(Reg)=tmp1 + +#define DecWordReg(Reg) \ + unsigned tmp = (unsigned)Wreg(Reg); \ + unsigned tmp1 = tmp-1; \ + nec_state->OverVal = (tmp == 0x8000); \ + SetAF(tmp1,tmp,1); \ + SetSZPF_Word(tmp1); \ + Wreg(Reg)=tmp1 + +#define JMP(flag) \ + int tmp; \ + EMPTY_PREFETCH(); \ + tmp = (int)((INT8)FETCH()); \ + if (flag) \ + { \ + static const UINT8 table[3]={3,10,10}; \ + nec_state->ip = (WORD)(nec_state->ip+tmp); \ + nec_state->icount-=table[nec_state->chip_type/8]; \ + CHANGE_PC; \ + return; \ + } + +#define ADJ4(param1,param2) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ + { \ + UINT16 tmp; \ + tmp = Breg(AL) + param1; \ + Breg(AL) = tmp; \ + nec_state->AuxVal = 1; \ + nec_state->CarryVal |= tmp & 0x100; \ + } \ + if (CF || (Breg(AL)>0x9f)) \ + { \ + Breg(AL) += param2; \ + nec_state->CarryVal = 1; \ + } \ + SetSZPF_Byte(Breg(AL)) + +#define ADJB(param1,param2) \ + if (AF || ((Breg(AL) & 0xf) > 9)) \ + { \ + Breg(AL) += param1; \ + Breg(AH) += param2; \ + nec_state->AuxVal = 1; \ + nec_state->CarryVal = 1; \ + } \ + else \ + { \ + nec_state->AuxVal = 0; \ + nec_state->CarryVal = 0; \ + } \ + Breg(AL) &= 0x0F + +#define BITOP_BYTE \ + ModRM = FETCH(); \ + if (ModRM >= 0xc0) { \ + tmp=Breg(Mod_RM.RM.b[ModRM]); \ + } \ + else { \ + (*GetEA[ModRM])(nec_state); \ + tmp=read_mem_byte(EA); \ + } + +#define BITOP_WORD \ + ModRM = FETCH(); \ + if (ModRM >= 0xc0) { \ + tmp=Wreg(Mod_RM.RM.w[ModRM]); \ + } \ + else { \ + (*GetEA[ModRM])(nec_state); \ + tmp=read_mem_word(EA); \ + } + +#define BIT_NOT \ + if (tmp & (1<CarryVal = dst & 0x80; dst = (dst << 1)+CF +#define ROL_WORD nec_state->CarryVal = dst & 0x8000; dst = (dst << 1)+CF +#define ROR_BYTE nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7) +#define ROR_WORD nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<15) +#define ROLC_BYTE dst = (dst << 1) + CF; SetCFB(dst) +#define ROLC_WORD dst = (dst << 1) + CF; SetCFW(dst) +#define RORC_BYTE dst = (CF<<8)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1 +#define RORC_WORD dst = (CF<<16)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1 +#define SHL_BYTE(c) nec_state->icount-=c; dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHL_WORD(c) nec_state->icount-=c; dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) +#define SHR_BYTE(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHR_WORD(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) +#define SHRA_BYTE(c) nec_state->icount-=c; dst = ((INT8)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT8)((BYTE)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst) +#define SHRA_WORD(c) nec_state->icount-=c; dst = ((INT16)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT16)((WORD)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst) + +#define DIVUB \ + uresult = Wreg(AW); \ + uresult2 = uresult % tmp; \ + if ((uresult /= tmp) > 0xff) { \ + nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \ + } else { \ + Breg(AL) = uresult; \ + Breg(AH) = uresult2; \ + } + +#define DIVB \ + result = (INT16)Wreg(AW); \ + result2 = result % (INT16)((INT8)tmp); \ + if ((result /= (INT16)((INT8)tmp)) > 0xff) { \ + nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \ + } else { \ + Breg(AL) = result; \ + Breg(AH) = result2; \ + } + +#define DIVUW \ + uresult = (((UINT32)Wreg(DW)) << 16) | Wreg(AW);\ + uresult2 = uresult % tmp; \ + if ((uresult /= tmp) > 0xffff) { \ + nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \ + } else { \ + Wreg(AW)=uresult; \ + Wreg(DW)=uresult2; \ + } + +#define DIVW \ + result = ((UINT32)Wreg(DW) << 16) + Wreg(AW); \ + result2 = result % (INT32)((INT16)tmp); \ + if ((result /= (INT32)((INT16)tmp)) > 0xffff) { \ + nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \ + } else { \ + Wreg(AW)=result; \ + Wreg(DW)=result2; \ + } + +#define ADD4S { \ + int i,v1,v2,result; \ + int count = (Breg(CL)+1)/2; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={18,19,19}; \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS0, si); \ + tmp2 = GetMemB(DS1, di); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + result = v1+v2+nec_state->CarryVal; \ + nec_state->CarryVal = result > 99 ? 1 : 0; \ + result = result % 100; \ + v1 = ((result/10)<<4) | (result % 10); \ + PutMemB(DS1, di,v1); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} + +#define SUB4S { \ + int count = (Breg(CL)+1)/2; \ + int i; \ + unsigned int v1,v2,result; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={18,19,19}; \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS1, di); \ + tmp2 = GetMemB(DS0, si); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + if (v1 < (v2+nec_state->CarryVal)) { \ + v1+=100; \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 1; \ + } else { \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 0; \ + } \ + v1 = ((result/10)<<4) | (result % 10); \ + PutMemB(DS1, di,v1); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} + +#define CMP4S { \ + int count = (Breg(CL)+1)/2; \ + int i; \ + unsigned int v1,v2,result; \ + unsigned di = Wreg(IY); \ + unsigned si = Wreg(IX); \ + static const UINT8 table[3]={14,19,19}; \ + nec_state->ZeroVal = nec_state->CarryVal = 0; \ + for (i=0;iicount-=table[nec_state->chip_type/8]; \ + tmp = GetMemB(DS1, di); \ + tmp2 = GetMemB(DS0, si); \ + v1 = (tmp>>4)*10 + (tmp&0xf); \ + v2 = (tmp2>>4)*10 + (tmp2&0xf); \ + if (v1 < (v2+nec_state->CarryVal)) { \ + v1+=100; \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 1; \ + } else { \ + result = v1-(v2+nec_state->CarryVal); \ + nec_state->CarryVal = 0; \ + } \ + v1 = ((result/10)<<4) | (result % 10); \ + if (v1) nec_state->ZeroVal = 1; \ + si++; \ + di++; \ + } \ +} diff --git a/src/cpu/nec/necmodrm.h b/src/cpu/nec/necmodrm.h new file mode 100644 index 00000000..cf8956b8 --- /dev/null +++ b/src/cpu/nec/necmodrm.h @@ -0,0 +1,104 @@ +static struct { + struct { + WREGS w[256]; + BREGS b[256]; + } reg; + struct { + WREGS w[256]; + BREGS b[256]; + } RM; +} Mod_RM; + +#define RegWord(ModRM) Wreg(Mod_RM.reg.w[ModRM]) +#define RegByte(ModRM) Breg(Mod_RM.reg.b[ModRM]) + +#define GetRMWord(ModRM) \ + ((ModRM) >= 0xc0 ? Wreg(Mod_RM.RM.w[ModRM]) : ( (*GetEA[ModRM])(nec_state), read_mem_word( EA ) )) + +#define PutbackRMWord(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) Wreg(Mod_RM.RM.w[ModRM])=val; \ + else write_mem_word(EA,val); \ +} + +#define GetnextRMWord read_mem_word((EA&0xf0000)|((EA+2)&0xffff)) + +#define PutRMWord(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + Wreg(Mod_RM.RM.w[ModRM])=val; \ + else { \ + (*GetEA[ModRM])(nec_state); \ + write_mem_word( EA ,val); \ + } \ +} + +#define PutImmRMWord(ModRM) \ +{ \ + WORD val; \ + if (ModRM >= 0xc0) \ + Wreg(Mod_RM.RM.w[ModRM]) = FETCHWORD(); \ + else { \ + (*GetEA[ModRM])(nec_state); \ + val = FETCHWORD(); \ + write_mem_word( EA , val); \ + } \ +} + +#define GetRMByte(ModRM) \ + ((ModRM) >= 0xc0 ? Breg(Mod_RM.RM.b[ModRM]) : read_mem_byte( (*GetEA[ModRM])(nec_state) )) + +#define PutRMByte(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + Breg(Mod_RM.RM.b[ModRM])=val; \ + else \ + write_mem_byte( (*GetEA[ModRM])(nec_state) ,val); \ +} + +#define PutImmRMByte(ModRM) \ +{ \ + if (ModRM >= 0xc0) \ + Breg(Mod_RM.RM.b[ModRM])=FETCH(); \ + else { \ + (*GetEA[ModRM])(nec_state); \ + write_mem_byte( EA , FETCH() ); \ + } \ +} + +#define PutbackRMByte(ModRM,val) \ +{ \ + if (ModRM >= 0xc0) \ + Breg(Mod_RM.RM.b[ModRM])=val; \ + else \ + write_mem_byte(EA,val); \ +} + +#define DEF_br8 \ + UINT32 ModRM = FETCH(),src,dst; \ + src = RegByte(ModRM); \ + dst = GetRMByte(ModRM) + +#define DEF_wr16 \ + UINT32 ModRM = FETCH(),src,dst; \ + src = RegWord(ModRM); \ + dst = GetRMWord(ModRM) + +#define DEF_r8b \ + UINT32 ModRM = FETCH(),src,dst; \ + dst = RegByte(ModRM); \ + src = GetRMByte(ModRM) + +#define DEF_r16w \ + UINT32 ModRM = FETCH(),src,dst; \ + dst = RegWord(ModRM); \ + src = GetRMWord(ModRM) + +#define DEF_ald8 \ + UINT32 src = FETCH(); \ + UINT32 dst = Breg(AL) + +#define DEF_axd16 \ + UINT32 src = FETCH(); \ + UINT32 dst = Wreg(AW); \ + src += (FETCH() << 8) diff --git a/src/cpu/nec/necpriv.h b/src/cpu/nec/necpriv.h new file mode 100644 index 00000000..2209ad5e --- /dev/null +++ b/src/cpu/nec/necpriv.h @@ -0,0 +1,178 @@ +/* Cpu types, steps of 8 to help the cycle count calculation */ +#define V33_TYPE 0 +#define V30_TYPE 8 +#define V20_TYPE 16 + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define cpu_readop cpu_readmem20_op +#define cpu_readop_arg cpu_readmem20_arg + +/* interrupt vectors */ +enum +{ + NEC_DIVIDE_VECTOR = 0, + NEC_TRAP_VECTOR = 1, + NEC_NMI_VECTOR = 2, + NEC_BRKV_VECTOR = 4, + NEC_CHKIND_VECTOR = 5 +}; + +/* interrupt sources */ +typedef enum +{ + BRK = 0, + INT_IRQ = 1, + NMI_IRQ = 2 +} INTSOURCES; + +/* NEC registers */ +typedef union +{ /* eight general registers */ + UINT16 w[8]; /* viewed as 16 bits registers */ + UINT8 b[16]; /* or as 8 bit registers */ +} necbasicregs; + +typedef struct _nec_state_t nec_state_t; +struct _nec_state_t +{ + necbasicregs regs; + offs_t fetch_xor; + UINT16 sregs[4]; + + UINT16 ip; + + /* PSW flags */ + INT32 SignVal; + UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ + UINT8 TF, IF, DF, MF; /* 0 or 1 valued flags */ + + /* interrupt related */ + UINT32 vector; + UINT32 pending_irq; + UINT32 nmi_state; + UINT32 irq_state; + UINT32 poll_state; + UINT8 no_interrupt; + UINT8 halted; + + int icount; + + UINT8 prefetch_size; + UINT8 prefetch_cycles; + INT8 prefetch_count; + UINT8 prefetch_reset; + UINT32 chip_type; + + UINT32 prefix_base; /* base address of the latest prefix segment */ + UINT8 seg_prefix; /* prefix segment indicator */ + UINT32 cycles_total; + INT32 cycles_remaining; + INT8 stop_run; +}; + +typedef enum { DS1, PS, SS, DS0 } SREGS; +typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS; +typedef enum { + AL = 0, //NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1), + AH = 1, //NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0), + CL = 2, //NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3), + CH = 3, //NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2), + DL = 4, //NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5), + DH = 5, //NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4), + BL = 6, //NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7), + BH = 7 //NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6), +} BREGS; + +#define Sreg(x) nec_state->sregs[x] +#define Wreg(x) nec_state->regs.w[x] +#define Breg(x) nec_state->regs.b[x] + +#define PC(n) ((Sreg(PS)<<4)+(n)->ip) + +#define CF (nec_state->CarryVal!=0) +#define SF (nec_state->SignVal<0) +#define ZF (nec_state->ZeroVal==0) +#define PF parity_table[(BYTE)nec_state->ParityVal] +#define AF (nec_state->AuxVal!=0) +#define OF (nec_state->OverVal!=0) + +/************************************************************************/ + +#define read_mem_byte(a) cpu_readmem20(a) +#define read_mem_word(a) (cpu_readmem20(a)+(cpu_readmem20((a)+1)<<8)) //nec_state->program->read_word_unaligned(a) +#define write_mem_byte(a,d) cpu_writemem20((a),(d)) +//#define write_mem_word(a,d) {cpu_writemem20((a),(unsigned char)(d)); cpu_writemem20((a)+1,(d)>>8); } //nec_state->program->write_word_unaligned((a),(d)) + +#define read_port_byte(a) cpu_readport(a) +#define read_port_word(a) (cpu_readport(a)+cpu_readport((a)+1)*256) +#define write_port_byte(a,d) cpu_writeport((a),(d)) +//#define write_port_word(a,d) { cpu_writeport((a),(unsigned char)(d)); (cpu_writeport((a)+1,(d)>>8); } // nec_state->io->write_word_unaligned((a),(d)) + +/************************************************************************/ + +#define CHANGE_PC do { EMPTY_PREFETCH(); } while (0) + +#define SegBase(Seg) (Sreg(Seg) << 4) + +#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4) + +#define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off))) +#define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off))) + +#define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); } +#define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); } + +/* prefetch timing */ + +//#define FETCHWORD() (cpu_readop_arg((Sreg(PS)<<4) + sChipsPtr->ip)+(cpu_readop_arg(((Sreg(PS)<<4) + sChipsPtr->ip+1))<<8)); sChipsPtr->ip+=2 +#define FETCH() cpu_readop_arg((Sreg(PS)<<4) + sChipsPtr->ip++) +#define FETCHWORD() (FETCH() + FETCH() * 256) +#define EMPTY_PREFETCH() nec_state->prefetch_reset = 1 + + +#define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); } +#define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); } + + +#define GetModRM UINT32 ModRM=FETCH() + +/* Cycle count macros: + CLK - cycle count is the same on all processors + CLKS - cycle count differs between processors, list all counts + CLKW - cycle count for word read/write differs for odd/even source/destination address + CLKM - cycle count for reg/mem instructions + CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses + + + Prefetch & buswait time is not emulated. + Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated. +*/ + +#define CLK(all) nec_state->icount-=all +#define CLKS(v20,v30,v33) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33; nec_state->icount-=(ccount>>nec_state->chip_type)&0x7f; } +#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } +#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_state->icount-=( ModRM >=0xc0 )?((ccount>>nec_state->chip_type)&0x7f):((mcount>>nec_state->chip_type)&0x7f); } +#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } + +/************************************************************************/ +#define CompressFlags() (WORD)(int(CF) | 0x02 | (int(PF) << 2) | (int(AF) << 4) | (int(ZF) << 6) \ + | (int(SF) << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \ + | (nec_state->DF << 10) | (int(OF) << 11) | 0x7000 | (nec_state->MF << 15)) + +#define ExpandFlags(f) \ +{ \ + nec_state->CarryVal = (f) & 0x0001; \ + nec_state->ParityVal = !((f) & 0x0004); \ + nec_state->AuxVal = (f) & 0x0010; \ + nec_state->ZeroVal = !((f) & 0x0040); \ + nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \ + nec_state->TF = ((f) & 0x0100) == 0x0100; \ + nec_state->IF = ((f) & 0x0200) == 0x0200; \ + nec_state->DF = ((f) & 0x0400) == 0x0400; \ + nec_state->OverVal = (f) & 0x0800; \ + nec_state->MF = ((f) & 0x8000) == 0x8000; \ +} diff --git a/src/cpu/nec/v25.cpp b/src/cpu/nec/v25.cpp new file mode 100644 index 00000000..5033d99f --- /dev/null +++ b/src/cpu/nec/v25.cpp @@ -0,0 +1,861 @@ +/**************************************************************************** + + NEC V25/V35 emulator + + --------------------------------------------- + + TODO: + + Using V20/V30 cycle counts for now. V25/V35 cycle counts + vary based on whether internal RAM access is enabled (RAMEN). + Likewise, the programmable clock divider (PCK) currently only + affects the timers, not instruction execution. + + BTCLR and STOP instructions not implemented. + + IBRK flag (trap I/O instructions) not implemented. + + Interrupt macro service function not implemented. + + Port implementation is incomplete: mode control registers are ignored. + + Timer implementation is incomplete: polling is not implemented + (reading any of the registers just returns the last value written) + + Serial interface and DMA functions not implemented. + Note that these functions differ considerably between + the V25/35 and the V25+/35+. + + Make internal RAM into a real RAM region, and use an + internal address map (remapped when IDB is written to) + instead of memory access wrapper functions. + That way the internal RAM would be visible to the debugger, + among other benefits. + +****************************************************************************/ + +#include +#include +#include "driver.h" +#include "state.h" +#include "vez.h" + +unsigned char cpu_readmem20_op(unsigned int); +unsigned char cpu_readmem20_arg(unsigned int); +unsigned char cpu_readport(unsigned int); +void cpu_writeport(unsigned int,unsigned int); + +static inline void write_port_word(unsigned int a, unsigned short d) +{ + cpu_writeport((a),(unsigned char)(d)); + cpu_writeport((a)+1,(d)>>8); +} + +#define cpu_readop cpu_readmem20_op +#define cpu_readop_arg cpu_readmem20_arg + +#define offs_t int +#define INPUT_LINE_NMI 0x20 // nmi + +#define NEC_INLINE + +typedef UINT8 BOOLEAN; +typedef UINT8 BYTE; +typedef UINT16 WORD; +typedef UINT32 DWORD; + +#include "v25priv.h" + +static void add_timer(v25_state_t *nec_state, int timer, double tmp, int param, int flags) +{ + float cycles = (nec_state->clock / 2) * (tmp * (1.000000000 / nec_state->clock)); + + nec_state->timer_param[timer] = param; + nec_state->timer_enabled[timer] = 1; + nec_state->timer_flags[timer] = flags; // 1 = periodic, 0 = oneshot + nec_state->timer_cycles_period[timer] = (int)cycles; + nec_state->timer_cycles_until_trigger[timer] = (int)cycles; +} + +#include "v25sfr.c" + +static v25_state_t sChips[4]; // 4 cpus should be plenty! +static v25_state_t *sChipsPtr; + +static void v25_timer_callback(int param) +{ + v25_state_t *nec_state = sChipsPtr; + nec_state->pending_irq |= param; +} + +NEC_INLINE void prefetch(v25_state_t *nec_state) +{ + nec_state->prefetch_count--; +} + +static void do_prefetch(v25_state_t *nec_state, int previous_ICount) +{ + int diff = previous_ICount - (int) nec_state->icount; + + /* The implementation is not accurate, but comes close. + * It does not respect that the V30 will fetch two bytes + * at once directly, but instead uses only 2 cycles instead + * of 4. There are however only very few sources publicly + * available and they are vague. + */ + while (nec_state->prefetch_count<0) + { + nec_state->prefetch_count++; + if (diff>nec_state->prefetch_cycles) + diff -= nec_state->prefetch_cycles; + else + nec_state->icount -= nec_state->prefetch_cycles; + } + + if (nec_state->prefetch_reset) + { + nec_state->prefetch_count = 0; + nec_state->prefetch_reset = 0; + return; + } + + while (diff>=nec_state->prefetch_cycles && nec_state->prefetch_count < nec_state->prefetch_size) + { + diff -= nec_state->prefetch_cycles; + nec_state->prefetch_count++; + } + +} + +NEC_INLINE UINT8 fetch(v25_state_t *nec_state) +{ + prefetch(nec_state); + return cpu_readop_arg(((Sreg(PS)<<4)+nec_state->ip++) ^ nec_state->fetch_xor); +} + +NEC_INLINE UINT16 fetchword(v25_state_t *nec_state) +{ + UINT16 r = FETCH(); + r |= (FETCH()<<8); + return r; +} + +#define nec_state_t v25_state_t + +#include "v25instr.h" +#include "necmacro.h" +#include "necea.h" +#include "necmodrm.h" + +static UINT8 parity_table[256]; + +static UINT8 fetchop(v25_state_t *nec_state) +{ + UINT8 ret; + + prefetch(nec_state); + ret = cpu_readop(((Sreg(PS)<<4)+nec_state->ip++) ^ nec_state->fetch_xor); + + if (nec_state->MF == 0) + if (nec_state->decode) + { + ret = nec_state->decode[ret]; + } + return ret; +} + + +void v25_open(int cpu) +{ + sChipsPtr = &sChips[cpu]; +} + +void v25_close() +{ + sChipsPtr = NULL; +} + + +/***************************************************************************/ + +int v25_reset() +{ + v25_state_t *nec_state = sChipsPtr; + int tmp; + + nec_state->ip = 0; + nec_state->IBRK = 1; + nec_state->F0 = 0; + nec_state->F1 = 0; + nec_state->TF = 0; + nec_state->IF = 0; + nec_state->DF = 0; + nec_state->SignVal = 0; + nec_state->AuxVal = 0; + nec_state->OverVal = 0; + nec_state->ZeroVal = 1; + nec_state->CarryVal = 0; + nec_state->ParityVal = 1; + nec_state->pending_irq = 0; + nec_state->unmasked_irq = INT_IRQ | NMI_IRQ; + nec_state->bankswitch_irq = 0; + nec_state->priority_inttu = 7; + nec_state->priority_intd = 7; + nec_state->priority_intp = 7; + nec_state->priority_ints0 = 7; + nec_state->priority_ints1 = 7; + nec_state->IRQS = nec_state->ISPR = 0; + nec_state->nmi_state = 0; + nec_state->irq_state = 0; + nec_state->poll_state = 1; + nec_state->intp_state[0] = 0; + nec_state->intp_state[1] = 0; + nec_state->intp_state[2] = 0; + nec_state->halted = 0; + nec_state->vector = 0xff; // default + nec_state->cycles_total = 0; + + nec_state->TM0 = nec_state->MD0 = nec_state->TM1 = nec_state->MD1 = 0; + nec_state->TMC0 = nec_state->TMC1 = 0; + + nec_state->RAMEN = 1; + nec_state->TB = 20; + nec_state->PCK = 8; + nec_state->IDB = 0xFFE00; + + memset (nec_state->timer_enabled, 0, sizeof(char) * 4); + + tmp = nec_state->PCK << nec_state->TB; + add_timer(nec_state, 3, tmp, INTTB, 1); + + SetRB(7); + Sreg(PS) = 0xffff; + Sreg(SS) = 0; + Sreg(DS0) = 0; + Sreg(DS1) = 0; + + CHANGE_PC; + + return 0; +} + +static void nec_interrupt(v25_state_t *nec_state, unsigned int_num, INTSOURCES source) +{ + UINT32 dest_seg, dest_off; + + i_pushf(nec_state); + nec_state->TF = nec_state->IF = 0; + nec_state->MF = nec_state->mode_state; + + switch(source) + { + case BRKN: /* force native mode */ + nec_state->MF = 1; + break; + case BRKS: /* force secure mode */ + if (nec_state->decode) + nec_state->MF = 0; +// else +// logerror("%06x: BRKS executed with no decryption table\n",PC(nec_state)); + break; + case INT_IRQ: /* get vector */ + int_num = nec_state->vector; //(*nec_state->irq_callback)(0); + break; + default: + break; + } + + dest_off = read_mem_word(int_num*4); + dest_seg = read_mem_word(int_num*4+2); + + PUSH(Sreg(PS)); + PUSH(nec_state->ip); + nec_state->ip = (WORD)dest_off; + Sreg(PS) = (WORD)dest_seg; + CHANGE_PC; +} + +static void nec_bankswitch(v25_state_t *nec_state, unsigned bank_num) +{ + int tmp = CompressFlags(); + + nec_state->TF = nec_state->IF = 0; + nec_state->MF = nec_state->mode_state; + + SetRB(bank_num); + + Wreg(PSW_SAVE) = tmp; + Wreg(PC_SAVE) = nec_state->ip; + nec_state->ip = Wreg(VECTOR_PC); + CHANGE_PC; +} + +static void nec_trap(v25_state_t *nec_state) +{ + nec_instruction[fetchop(nec_state)](nec_state); + nec_interrupt(nec_state, NEC_TRAP_VECTOR, BRK); +} + +#define INTERRUPT(source, vector, priority) \ + if(pending & (source)) { \ + nec_state->IRQS = vector; \ + nec_state->ISPR |= (1 << (priority)); \ + nec_state->pending_irq &= ~(source); \ + if(nec_state->bankswitch_irq & (source)) \ + nec_bankswitch(nec_state, priority); \ + else \ + nec_interrupt(nec_state, vector, source); \ + break; /* break out of loop */ \ + } + +/* interrupt sources subject to priority control */ +#define SOURCES (INTTU0 | INTTU1 | INTTU2 | INTD0 | INTD1 | INTP0 | INTP1 | INTP2 \ + | INTSER0 | INTSR0 | INTST0 | INTSER1 | INTSR1 | INTST1 | INTTB) + +static void external_int(v25_state_t *nec_state) +{ + int pending = nec_state->pending_irq & nec_state->unmasked_irq; + + if (pending & NMI_IRQ) + { + nec_interrupt(nec_state, NEC_NMI_VECTOR, NMI_IRQ); + nec_state->pending_irq &= ~NMI_IRQ; + } + else if (pending & SOURCES) + { + for(int i = 0; i < 8; i++) + { + if (nec_state->ISPR & (1 << i)) break; + + if (nec_state->priority_inttu == i) + { + INTERRUPT(INTTU0, NEC_INTTU0_VECTOR, i) + INTERRUPT(INTTU1, NEC_INTTU1_VECTOR, i) + INTERRUPT(INTTU2, NEC_INTTU2_VECTOR, i) + } + + if (nec_state->priority_intd == i) + { + INTERRUPT(INTD0, NEC_INTD0_VECTOR, i) + INTERRUPT(INTD1, NEC_INTD1_VECTOR, i) + } + + if (nec_state->priority_intp == i) + { + INTERRUPT(INTP0, NEC_INTP0_VECTOR, i) + INTERRUPT(INTP1, NEC_INTP1_VECTOR, i) + INTERRUPT(INTP2, NEC_INTP2_VECTOR, i) + } + + if (nec_state->priority_ints0 == i) + { + INTERRUPT(INTSER0, NEC_INTSER0_VECTOR, i) + INTERRUPT(INTSR0, NEC_INTSR0_VECTOR, i) + INTERRUPT(INTST0, NEC_INTST0_VECTOR, i) + } + + if (nec_state->priority_ints1 == i) + { + INTERRUPT(INTSER1, NEC_INTSER1_VECTOR, i) + INTERRUPT(INTSR1, NEC_INTSR1_VECTOR, i) + INTERRUPT(INTST1, NEC_INTST1_VECTOR, i) + } + + if (i == 7) + INTERRUPT(INTTB, NEC_INTTB_VECTOR, 7) + } + } + else if (pending & INT_IRQ) + { + /* the actual vector is retrieved after pushing flags */ + /* and clearing the IF */ + nec_interrupt(nec_state, (UINT32)-1, INT_IRQ); + nec_state->irq_state = CLEAR_LINE; + nec_state->pending_irq &= ~INT_IRQ; + } +} + +/****************************************************************************/ +/* OPCODES */ +/****************************************************************************/ + +#include "necinstr.c" +#include "v25instr.c" + +/*****************************************************************************/ + +void v25_set_irq_line_and_vector(int irqline, int vector, int state) +{ + v25_state_t *nec_state = sChipsPtr; + + switch (irqline) + { + case 0: + nec_state->vector = vector; + nec_state->irq_state = state; + if (state == CLEAR_LINE) + nec_state->pending_irq &= ~INT_IRQ; + else + { + nec_state->pending_irq |= INT_IRQ; + nec_state->halted = 0;; + } + break; + case INPUT_LINE_NMI: + nec_state->vector = vector; + if (nec_state->nmi_state == (unsigned int)state) return; + nec_state->nmi_state = state; + if (state != CLEAR_LINE) + { + nec_state->pending_irq |= NMI_IRQ; + nec_state->halted = 0; + } + break; + case NEC_INPUT_LINE_INTP0: + case NEC_INPUT_LINE_INTP1: + case NEC_INPUT_LINE_INTP2: + nec_state->vector = vector; + irqline -= NEC_INPUT_LINE_INTP0; + if (nec_state->intp_state[irqline] == (unsigned int)state) return; + nec_state->intp_state[irqline] = state; + if (state != CLEAR_LINE) + nec_state->pending_irq |= (INTP0 << irqline); + break; + case NEC_INPUT_LINE_POLL: + nec_state->vector = vector; + nec_state->poll_state = state; + break; + } +} + +void v25_common_init(int) +{ + v25_state_t *nec_state = sChipsPtr; + + unsigned int i, j, c; + + static const WREGS wreg_name[8]={ AW, CW, DW, BW, SP, BP, IX, IY }; + static const BREGS breg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH }; + + for (i = 0; i < 256; i++) + { + for (j = i, c = 0; j > 0; j >>= 1) + if (j & 1) c++; + parity_table[i] = !(c & 1); + } + + for (i = 0; i < 256; i++) + { + Mod_RM.reg.b[i] = breg_name[(i & 0x38) >> 3]; + Mod_RM.reg.w[i] = wreg_name[(i & 0x38) >> 3]; + } + + for (i = 0xc0; i < 0x100; i++) + { + Mod_RM.RM.w[i] = wreg_name[i & 7]; + Mod_RM.RM.b[i] = breg_name[i & 7]; + } + + memset(nec_state, 0, sizeof(*nec_state)); + + nec_state->decode = NULL; +} + +void v25_set_decode(unsigned char *table) +{ + sChipsPtr->decode = table; + sChipsPtr->mode_state = sChipsPtr->MF = (table != NULL) ? 0 : 1; +} + +unsigned int v25_total_cycles() +{ + return sChipsPtr->cycles_total + (sChipsPtr->cycles_remaining - sChipsPtr->icount); +} + +void v25_new_frame() +{ + for (int i = 0; i < 4; i++) { + nec_state_t *nec_state = &sChips[i]; + nec_state->cycles_total = 0; + } +} + +int v25_execute(int cycles) +{ + v25_state_t *nec_state = sChipsPtr; + int prev_ICount; + + int pending = nec_state->pending_irq & nec_state->unmasked_irq; + + if (nec_state->halted && pending) + { + for(int i = 0; i < 8; i++) + { + if (nec_state->ISPR & (1 << i)) break; + + if (nec_state->priority_inttu == i && (pending & (INTTU0|INTTU1|INTTU2))) + nec_state->halted = 0; + + if (nec_state->priority_intd == i && (pending & (INTD0|INTD1))) + nec_state->halted = 0; + + if (nec_state->priority_intp == i && (pending & (INTP0|INTP1|INTP2))) + nec_state->halted = 0; + + if (nec_state->priority_ints0 == i && (pending & (INTSER0|INTSR0|INTST0))) + nec_state->halted = 0; + + if (nec_state->priority_ints1 == i && (pending & (INTSER1|INTSR1|INTST1))) + nec_state->halted = 0; + + if (i == 7 && (pending & INTTB)) + nec_state->halted = 0; + } + } + + if (nec_state->halted) + { + nec_state->icount = 0; + return 0; + } + + nec_state->icount = cycles; + nec_state->cycles_remaining = cycles; + + while(nec_state->icount>0 && !nec_state->stop_run) { + /* Dispatch IRQ */ + if (nec_state->no_interrupt==0 && (nec_state->pending_irq & nec_state->unmasked_irq)) + { + if (nec_state->pending_irq & NMI_IRQ) + external_int(nec_state); + else if (nec_state->IF) + external_int(nec_state); + } + + /* No interrupt allowed between last instruction and this one */ + if (nec_state->no_interrupt) + nec_state->no_interrupt--; + + prev_ICount = nec_state->icount; + nec_instruction[fetchop(nec_state)](nec_state); + do_prefetch(nec_state, prev_ICount); + + for (int i = 0; i < 4; i++) { // timers! + if (nec_state->timer_enabled[i]) { + nec_state->timer_cycles_until_trigger[i] -= prev_ICount - nec_state->icount; + + if (nec_state->timer_cycles_until_trigger[i] <= 0) { + if (nec_state->timer_flags[i]) { // periodic + nec_state->timer_cycles_until_trigger[i] = nec_state->timer_cycles_period[i]; + } else { // oneshot + nec_state->timer_enabled[i] = 0; // disabled + } + + v25_timer_callback(nec_state->timer_param[i]); + } + } + } + } + + nec_state->stop_run = 0; + nec_state->cycles_total += cycles - nec_state->icount; + + return cycles - nec_state->icount; +} + +void v25Init(int cpu, int type, int clock) +{ + sChipsPtr = &sChips[cpu]; + v25_state_t *nec_state = sChipsPtr; + + v25_common_init(cpu); + + nec_state->clock = clock; // not divided! + + switch (type) + { + case V20_TYPE: // v25 + { + nec_state->fetch_xor = 0; + nec_state->chip_type=V20_TYPE; + nec_state->prefetch_size = 4; /* 3 words */ + nec_state->prefetch_cycles = 4; /* four cycles per byte */ + } + break; + + case V30_TYPE: // v35 + { + nec_state->fetch_xor = 0; + nec_state->chip_type=V30_TYPE; + nec_state->prefetch_size = 6; /* 3 words */ + nec_state->prefetch_cycles = 2; /* two cycles per byte / four per word */ + } + break; + } +} + +void v25RunEnd() +{ + sChipsPtr->stop_run = 1; +} + +void v25Idle(int cycles) +{ + sChipsPtr->icount -= cycles; +} + +int v25GetPC(int n) +{ + if (n == -1) { // current cpu + return ((sChipsPtr->ram.w[sChipsPtr->RBW + (PS)]<<4) + sChipsPtr->ip); + } else { + v25_state_t *nec_state = &sChips[n]; + return ((nec_state->ram.w[nec_state->RBW + (PS)]<<4) + nec_state->ip); + } +} + +void v25Scan(int cpu, int nAction) +{ + v25_state_t *nec_state = &sChips[cpu]; + + if (nAction & ACB_DRIVER_DATA) { + struct BurnArea ba; + char szText[] = "V25 #0"; + szText[5] = '1' + cpu; + + memset(&ba, 0, sizeof(ba)); + + ba.Data = (unsigned char*)nec_state; + ba.nLen = sizeof(nec_state_t); + ba.szName = szText; + BurnAcb(&ba); + } +} + +#if 0 + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static CPU_SET_INFO( v25 ) +{ + v25_state_t *nec_state = get_safe_token(device); + + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP0: set_irq_line(nec_state, NEC_INPUT_LINE_INTP0, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP1: set_irq_line(nec_state, NEC_INPUT_LINE_INTP1, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP2: set_irq_line(nec_state, NEC_INPUT_LINE_INTP2, info->i); break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_irq_line(nec_state, NEC_INPUT_LINE_POLL, info->i); break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: + if( info->i - (Sreg(PS)<<4) < 0x10000 ) + { + nec_state->ip = info->i - (Sreg(PS)<<4); + } + else + { + Sreg(PS) = info->i >> 4; + nec_state->ip = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break; + case CPUINFO_INT_SP: + if( info->i - (Sreg(SS)<<4) < 0x10000 ) + { + Wreg(SP) = info->i - (Sreg(SS)<<4); + } + else + { + Sreg(SS) = info->i >> 4; + Wreg(SP) = info->i & 0x0000f; + } + break; + case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break; + case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break; + case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static CPU_GET_INFO( v25v35 ) +{ + v25_state_t *nec_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + int flags; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(v25_state_t); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 80; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 17; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: info->i = (nec_state->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = nec_state->nmi_state; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP0: info->i = nec_state->intp_state[0]; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP1: info->i = nec_state->intp_state[1]; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP2: info->i = nec_state->intp_state[2]; break; + case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: info->i = nec_state->poll_state; break; + + case CPUINFO_INT_PREVIOUSPC: /* not supported */ break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break; + case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break; + case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break; + case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break; + case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break; + case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break; + case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break; + case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break; + case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break; + case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break; + case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break; + case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break; + case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break; + case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break; + case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(v25); break; + case CPUINFO_FCT_INIT: /* set per-CPU */ break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(v25); break; + case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(v25); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v25); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v25); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "NEC"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Bryan McPhail (V25/V35 support added by Alex W. Jackson)"); break; + + case CPUINFO_STR_FLAGS: + flags = CompressFlags(); + sprintf(info->s, "%c %d %c%c%c%c%c%c%c%c%c%c%c%c", + flags & 0x8000 ? 'N':'S', + (flags & 0x7000) >> 12, + flags & 0x0800 ? 'O':'.', + flags & 0x0400 ? 'D':'.', + flags & 0x0200 ? 'I':'.', + flags & 0x0100 ? 'T':'.', + flags & 0x0080 ? 'S':'.', + flags & 0x0040 ? 'Z':'.', + flags & 0x0020 ? '1':'.', + flags & 0x0010 ? 'A':'.', + flags & 0x0008 ? '0':'.', + flags & 0x0004 ? 'P':'.', + flags & 0x0002 ? '.':'I', + flags & 0x0001 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%05X", (Sreg(PS)<<4) + nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break; + case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break; + case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break; + case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break; + case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break; + case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break; + case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break; + case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break; + case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break; + case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break; + case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break; + case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break; + case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break; + case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v25 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v25); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V25"); break; + + default: CPU_GET_INFO_CALL(v25v35); break; + } +} + + +/************************************************************************** + * CPU-specific set_info + **************************************************************************/ + +CPU_GET_INFO( v35 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v35); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "V35"); break; + + default: CPU_GET_INFO_CALL(v25v35); break; + } +} + +DEFINE_LEGACY_CPU_DEVICE(V25, v25); +DEFINE_LEGACY_CPU_DEVICE(V35, v35); + +#endif diff --git a/src/cpu/nec/v25instr.c b/src/cpu/nec/v25instr.c new file mode 100644 index 00000000..5aa257ff --- /dev/null +++ b/src/cpu/nec/v25instr.c @@ -0,0 +1,81 @@ +#define GetRB \ + ModRM = FETCH(); \ + if (ModRM >= 0xc0) \ + tmp = Wreg(Mod_RM.RM.w[ModRM]) & 0x7; \ + else { \ + tmp = 0; \ + } + +#define RETRBI \ + tmp = (Wreg(PSW_SAVE) & 0x7000) >> 12; \ + nec_state->ip = Wreg(PC_SAVE); \ + ExpandFlags(Wreg(PSW_SAVE)); \ + SetRB(tmp); \ + CHANGE_PC + +#define TSKSW \ + Wreg(PSW_SAVE) = CompressFlags(); \ + Wreg(PC_SAVE) = nec_state->ip; \ + SetRB(tmp); \ + nec_state->ip = Wreg(PC_SAVE); \ + ExpandFlags(Wreg(PSW_SAVE)); \ + CHANGE_PC + +#define MOVSPA \ + tmp = (Wreg(PSW_SAVE) & 0x7000) >> 8; \ + Sreg(SS) = nec_state->ram.w[tmp+SS]; \ + Wreg(SP) = nec_state->ram.w[tmp+SP] + +#define MOVSPB \ + tmp <<= 4; \ + nec_state->ram.w[tmp+SS] = Sreg(SS); \ + nec_state->ram.w[tmp+SP] = Wreg(SP) + +#define FINT \ + for(tmp = 1; tmp < 0x100; tmp <<= 1) { \ + if(nec_state->ISPR & tmp) { \ + nec_state->ISPR &= ~tmp; \ + break; \ + } \ + } + +OP( 0x0f, i_pre_v25 ) { UINT32 ModRM, tmp, tmp2; + switch (FETCH()) { + case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<CarryVal=nec_state->OverVal=0; break; /* Test */ + case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; + case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; + case 0x2d : GetRB; nec_bankswitch(nec_state, tmp); CLK(15); break; + case 0x31 : ModRM = FETCH(); ModRM=0; break; + case 0x33 : ModRM = FETCH(); ModRM=0; break; + case 0x91 : RETRBI; CLK(12); break; + case 0x92 : FINT; CLK(2); nec_state->no_interrupt = 1; break; + case 0x94 : GetRB; TSKSW; CLK(20); break; + case 0x95 : GetRB; MOVSPB; CLK(11); break; + case 0x9e : nec_state->icount=0; break; + default: break; + } +} + +OP( 0x63, i_brkn ) { nec_interrupt(nec_state, FETCH(), BRKN); CLKS(50,50,24); } +OP( 0xF1, i_brks ) { nec_interrupt(nec_state, FETCH(), BRKS); CLKS(50,50,24); } diff --git a/src/cpu/nec/v25instr.h b/src/cpu/nec/v25instr.h new file mode 100644 index 00000000..2e73b022 --- /dev/null +++ b/src/cpu/nec/v25instr.h @@ -0,0 +1,510 @@ +static void i_add_br8(nec_state_t *nec_state); +static void i_add_wr16(nec_state_t *nec_state); +static void i_add_r8b(nec_state_t *nec_state); +static void i_add_r16w(nec_state_t *nec_state); +static void i_add_ald8(nec_state_t *nec_state); +static void i_add_axd16(nec_state_t *nec_state); +static void i_push_es(nec_state_t *nec_state); +static void i_pop_es(nec_state_t *nec_state); +static void i_or_br8(nec_state_t *nec_state); +static void i_or_r8b(nec_state_t *nec_state); +static void i_or_wr16(nec_state_t *nec_state); +static void i_or_r16w(nec_state_t *nec_state); +static void i_or_ald8(nec_state_t *nec_state); +static void i_or_axd16(nec_state_t *nec_state); +static void i_push_cs(nec_state_t *nec_state); +//ATTR_UNUSED static void i_pre_nec(nec_state_t *nec_state); +static void i_pre_v25(nec_state_t *nec_state); +static void i_adc_br8(nec_state_t *nec_state); +static void i_adc_wr16(nec_state_t *nec_state); +static void i_adc_r8b(nec_state_t *nec_state); +static void i_adc_r16w(nec_state_t *nec_state); +static void i_adc_ald8(nec_state_t *nec_state); +static void i_adc_axd16(nec_state_t *nec_state); +static void i_push_ss(nec_state_t *nec_state); +static void i_pop_ss(nec_state_t *nec_state); +static void i_sbb_br8(nec_state_t *nec_state); +static void i_sbb_wr16(nec_state_t *nec_state); +static void i_sbb_r8b(nec_state_t *nec_state); +static void i_sbb_r16w(nec_state_t *nec_state); +static void i_sbb_ald8(nec_state_t *nec_state); +static void i_sbb_axd16(nec_state_t *nec_state); +static void i_push_ds(nec_state_t *nec_state); +static void i_pop_ds(nec_state_t *nec_state); +static void i_and_br8(nec_state_t *nec_state); +static void i_and_r8b(nec_state_t *nec_state); +static void i_and_wr16(nec_state_t *nec_state); +static void i_and_r16w(nec_state_t *nec_state); +static void i_and_ald8(nec_state_t *nec_state); +static void i_and_axd16(nec_state_t *nec_state); +static void i_es(nec_state_t *nec_state); +static void i_daa(nec_state_t *nec_state); +static void i_sub_br8(nec_state_t *nec_state); +static void i_sub_wr16(nec_state_t *nec_state); +static void i_sub_r8b(nec_state_t *nec_state); +static void i_sub_r16w(nec_state_t *nec_state); +static void i_sub_ald8(nec_state_t *nec_state); +static void i_sub_axd16(nec_state_t *nec_state); +static void i_cs(nec_state_t *nec_state); +static void i_das(nec_state_t *nec_state); +static void i_xor_br8(nec_state_t *nec_state); +static void i_xor_r8b(nec_state_t *nec_state); +static void i_xor_wr16(nec_state_t *nec_state); +static void i_xor_r16w(nec_state_t *nec_state); +static void i_xor_ald8(nec_state_t *nec_state); +static void i_xor_axd16(nec_state_t *nec_state); +static void i_ss(nec_state_t *nec_state); +static void i_aaa(nec_state_t *nec_state); +static void i_cmp_br8(nec_state_t *nec_state); +static void i_cmp_wr16(nec_state_t *nec_state); +static void i_cmp_r8b(nec_state_t *nec_state); +static void i_cmp_r16w(nec_state_t *nec_state); +static void i_cmp_ald8(nec_state_t *nec_state); +static void i_cmp_axd16(nec_state_t *nec_state); +static void i_ds(nec_state_t *nec_state); +static void i_aas(nec_state_t *nec_state); +static void i_inc_ax(nec_state_t *nec_state); +static void i_inc_cx(nec_state_t *nec_state); +static void i_inc_dx(nec_state_t *nec_state); +static void i_inc_bx(nec_state_t *nec_state); +static void i_inc_sp(nec_state_t *nec_state); +static void i_inc_bp(nec_state_t *nec_state); +static void i_inc_si(nec_state_t *nec_state); +static void i_inc_di(nec_state_t *nec_state); +static void i_dec_ax(nec_state_t *nec_state); +static void i_dec_cx(nec_state_t *nec_state); +static void i_dec_dx(nec_state_t *nec_state); +static void i_dec_bx(nec_state_t *nec_state); +static void i_dec_sp(nec_state_t *nec_state); +static void i_dec_bp(nec_state_t *nec_state); +static void i_dec_si(nec_state_t *nec_state); +static void i_dec_di(nec_state_t *nec_state); +static void i_push_ax(nec_state_t *nec_state); +static void i_push_cx(nec_state_t *nec_state); +static void i_push_dx(nec_state_t *nec_state); +static void i_push_bx(nec_state_t *nec_state); +static void i_push_sp(nec_state_t *nec_state); +static void i_push_bp(nec_state_t *nec_state); +static void i_push_si(nec_state_t *nec_state); +static void i_push_di(nec_state_t *nec_state); +static void i_pop_ax(nec_state_t *nec_state); +static void i_pop_cx(nec_state_t *nec_state); +static void i_pop_dx(nec_state_t *nec_state); +static void i_pop_bx(nec_state_t *nec_state); +static void i_pop_sp(nec_state_t *nec_state); +static void i_pop_bp(nec_state_t *nec_state); +static void i_pop_si(nec_state_t *nec_state); +static void i_pop_di(nec_state_t *nec_state); +static void i_pusha(nec_state_t *nec_state); +static void i_popa(nec_state_t *nec_state); +static void i_chkind(nec_state_t *nec_state); +static void i_brkn(nec_state_t *nec_state); +static void i_repnc(nec_state_t *nec_state); +static void i_repc(nec_state_t *nec_state); +static void i_push_d16(nec_state_t *nec_state); +static void i_imul_d16(nec_state_t *nec_state); +static void i_push_d8(nec_state_t *nec_state); +static void i_imul_d8(nec_state_t *nec_state); +static void i_insb(nec_state_t *nec_state); +static void i_insw(nec_state_t *nec_state); +static void i_outsb(nec_state_t *nec_state); +static void i_outsw(nec_state_t *nec_state); +static void i_jo(nec_state_t *nec_state); +static void i_jno(nec_state_t *nec_state); +static void i_jc(nec_state_t *nec_state); +static void i_jnc(nec_state_t *nec_state); +static void i_jz(nec_state_t *nec_state); +static void i_jnz(nec_state_t *nec_state); +static void i_jce(nec_state_t *nec_state); +static void i_jnce(nec_state_t *nec_state); +static void i_js(nec_state_t *nec_state); +static void i_jns(nec_state_t *nec_state); +static void i_jp(nec_state_t *nec_state); +static void i_jnp(nec_state_t *nec_state); +static void i_jl(nec_state_t *nec_state); +static void i_jnl(nec_state_t *nec_state); +static void i_jle(nec_state_t *nec_state); +static void i_jnle(nec_state_t *nec_state); +static void i_80pre(nec_state_t *nec_state); +static void i_82pre(nec_state_t *nec_state); +static void i_81pre(nec_state_t *nec_state); +static void i_83pre(nec_state_t *nec_state); +static void i_test_br8(nec_state_t *nec_state); +static void i_test_wr16(nec_state_t *nec_state); +static void i_xchg_br8(nec_state_t *nec_state); +static void i_xchg_wr16(nec_state_t *nec_state); +static void i_mov_br8(nec_state_t *nec_state); +static void i_mov_r8b(nec_state_t *nec_state); +static void i_mov_wr16(nec_state_t *nec_state); +static void i_mov_r16w(nec_state_t *nec_state); +static void i_mov_wsreg(nec_state_t *nec_state); +static void i_lea(nec_state_t *nec_state); +static void i_mov_sregw(nec_state_t *nec_state); +static void i_invalid(nec_state_t *nec_state); +static void i_popw(nec_state_t *nec_state); +static void i_nop(nec_state_t *nec_state); +static void i_xchg_axcx(nec_state_t *nec_state); +static void i_xchg_axdx(nec_state_t *nec_state); +static void i_xchg_axbx(nec_state_t *nec_state); +static void i_xchg_axsp(nec_state_t *nec_state); +static void i_xchg_axbp(nec_state_t *nec_state); +static void i_xchg_axsi(nec_state_t *nec_state); +static void i_xchg_axdi(nec_state_t *nec_state); +static void i_cbw(nec_state_t *nec_state); +static void i_cwd(nec_state_t *nec_state); +static void i_call_far(nec_state_t *nec_state); +static void i_pushf(nec_state_t *nec_state); +static void i_popf(nec_state_t *nec_state); +static void i_sahf(nec_state_t *nec_state); +static void i_lahf(nec_state_t *nec_state); +static void i_mov_aldisp(nec_state_t *nec_state); +static void i_mov_axdisp(nec_state_t *nec_state); +static void i_mov_dispal(nec_state_t *nec_state); +static void i_mov_dispax(nec_state_t *nec_state); +static void i_movsb(nec_state_t *nec_state); +static void i_movsw(nec_state_t *nec_state); +static void i_cmpsb(nec_state_t *nec_state); +static void i_cmpsw(nec_state_t *nec_state); +static void i_test_ald8(nec_state_t *nec_state); +static void i_test_axd16(nec_state_t *nec_state); +static void i_stosb(nec_state_t *nec_state); +static void i_stosw(nec_state_t *nec_state); +static void i_lodsb(nec_state_t *nec_state); +static void i_lodsw(nec_state_t *nec_state); +static void i_scasb(nec_state_t *nec_state); +static void i_scasw(nec_state_t *nec_state); +static void i_mov_ald8(nec_state_t *nec_state); +static void i_mov_cld8(nec_state_t *nec_state); +static void i_mov_dld8(nec_state_t *nec_state); +static void i_mov_bld8(nec_state_t *nec_state); +static void i_mov_ahd8(nec_state_t *nec_state); +static void i_mov_chd8(nec_state_t *nec_state); +static void i_mov_dhd8(nec_state_t *nec_state); +static void i_mov_bhd8(nec_state_t *nec_state); +static void i_mov_axd16(nec_state_t *nec_state); +static void i_mov_cxd16(nec_state_t *nec_state); +static void i_mov_dxd16(nec_state_t *nec_state); +static void i_mov_bxd16(nec_state_t *nec_state); +static void i_mov_spd16(nec_state_t *nec_state); +static void i_mov_bpd16(nec_state_t *nec_state); +static void i_mov_sid16(nec_state_t *nec_state); +static void i_mov_did16(nec_state_t *nec_state); +static void i_rotshft_bd8(nec_state_t *nec_state); +static void i_rotshft_wd8(nec_state_t *nec_state); +static void i_ret_d16(nec_state_t *nec_state); +static void i_ret(nec_state_t *nec_state); +static void i_les_dw(nec_state_t *nec_state); +static void i_lds_dw(nec_state_t *nec_state); +static void i_mov_bd8(nec_state_t *nec_state); +static void i_mov_wd16(nec_state_t *nec_state); +static void i_enter(nec_state_t *nec_state); +static void i_leave(nec_state_t *nec_state); +static void i_retf_d16(nec_state_t *nec_state); +static void i_retf(nec_state_t *nec_state); +static void i_int3(nec_state_t *nec_state); +static void i_int(nec_state_t *nec_state); +static void i_into(nec_state_t *nec_state); +static void i_iret(nec_state_t *nec_state); +static void i_rotshft_b(nec_state_t *nec_state); +static void i_rotshft_w(nec_state_t *nec_state); +static void i_rotshft_bcl(nec_state_t *nec_state); +static void i_rotshft_wcl(nec_state_t *nec_state); +static void i_aam(nec_state_t *nec_state); +static void i_aad(nec_state_t *nec_state); +static void i_setalc(nec_state_t *nec_state); +static void i_trans(nec_state_t *nec_state); +static void i_fpo(nec_state_t *nec_state); +static void i_loopne(nec_state_t *nec_state); +static void i_loope(nec_state_t *nec_state); +static void i_loop(nec_state_t *nec_state); +static void i_jcxz(nec_state_t *nec_state); +static void i_inal(nec_state_t *nec_state); +static void i_inax(nec_state_t *nec_state); +static void i_outal(nec_state_t *nec_state); +static void i_outax(nec_state_t *nec_state); +static void i_call_d16(nec_state_t *nec_state); +static void i_jmp_d16(nec_state_t *nec_state); +static void i_jmp_far(nec_state_t *nec_state); +static void i_jmp_d8(nec_state_t *nec_state); +static void i_inaldx(nec_state_t *nec_state); +static void i_inaxdx(nec_state_t *nec_state); +static void i_outdxal(nec_state_t *nec_state); +static void i_outdxax(nec_state_t *nec_state); +static void i_lock(nec_state_t *nec_state); +static void i_brks(nec_state_t *nec_state); +static void i_repne(nec_state_t *nec_state); +static void i_repe(nec_state_t *nec_state); +static void i_hlt(nec_state_t *nec_state); +static void i_cmc(nec_state_t *nec_state); +static void i_f6pre(nec_state_t *nec_state); +static void i_f7pre(nec_state_t *nec_state); +static void i_clc(nec_state_t *nec_state); +static void i_stc(nec_state_t *nec_state); +static void i_di(nec_state_t *nec_state); +static void i_ei(nec_state_t *nec_state); +static void i_cld(nec_state_t *nec_state); +static void i_std(nec_state_t *nec_state); +static void i_fepre(nec_state_t *nec_state); +static void i_ffpre(nec_state_t *nec_state); + +static void i_wait(nec_state_t *nec_state); + +static void (*const nec_instruction[256])(nec_state_t *nec_state) = +{ + i_add_br8, /* 0x00 */ + i_add_wr16, /* 0x01 */ + i_add_r8b, /* 0x02 */ + i_add_r16w, /* 0x03 */ + i_add_ald8, /* 0x04 */ + i_add_axd16, /* 0x05 */ + i_push_es, /* 0x06 */ + i_pop_es, /* 0x07 */ + i_or_br8, /* 0x08 */ + i_or_wr16, /* 0x09 */ + i_or_r8b, /* 0x0a */ + i_or_r16w, /* 0x0b */ + i_or_ald8, /* 0x0c */ + i_or_axd16, /* 0x0d */ + i_push_cs, /* 0x0e */ + i_pre_v25, /* 0x0f */ + i_adc_br8, /* 0x10 */ + i_adc_wr16, /* 0x11 */ + i_adc_r8b, /* 0x12 */ + i_adc_r16w, /* 0x13 */ + i_adc_ald8, /* 0x14 */ + i_adc_axd16, /* 0x15 */ + i_push_ss, /* 0x16 */ + i_pop_ss, /* 0x17 */ + i_sbb_br8, /* 0x18 */ + i_sbb_wr16, /* 0x19 */ + i_sbb_r8b, /* 0x1a */ + i_sbb_r16w, /* 0x1b */ + i_sbb_ald8, /* 0x1c */ + i_sbb_axd16, /* 0x1d */ + i_push_ds, /* 0x1e */ + i_pop_ds, /* 0x1f */ + i_and_br8, /* 0x20 */ + i_and_wr16, /* 0x21 */ + i_and_r8b, /* 0x22 */ + i_and_r16w, /* 0x23 */ + i_and_ald8, /* 0x24 */ + i_and_axd16, /* 0x25 */ + i_es, /* 0x26 */ + i_daa, /* 0x27 */ + i_sub_br8, /* 0x28 */ + i_sub_wr16, /* 0x29 */ + i_sub_r8b, /* 0x2a */ + i_sub_r16w, /* 0x2b */ + i_sub_ald8, /* 0x2c */ + i_sub_axd16, /* 0x2d */ + i_cs, /* 0x2e */ + i_das, /* 0x2f */ + i_xor_br8, /* 0x30 */ + i_xor_wr16, /* 0x31 */ + i_xor_r8b, /* 0x32 */ + i_xor_r16w, /* 0x33 */ + i_xor_ald8, /* 0x34 */ + i_xor_axd16, /* 0x35 */ + i_ss, /* 0x36 */ + i_aaa, /* 0x37 */ + i_cmp_br8, /* 0x38 */ + i_cmp_wr16, /* 0x39 */ + i_cmp_r8b, /* 0x3a */ + i_cmp_r16w, /* 0x3b */ + i_cmp_ald8, /* 0x3c */ + i_cmp_axd16, /* 0x3d */ + i_ds, /* 0x3e */ + i_aas, /* 0x3f */ + i_inc_ax, /* 0x40 */ + i_inc_cx, /* 0x41 */ + i_inc_dx, /* 0x42 */ + i_inc_bx, /* 0x43 */ + i_inc_sp, /* 0x44 */ + i_inc_bp, /* 0x45 */ + i_inc_si, /* 0x46 */ + i_inc_di, /* 0x47 */ + i_dec_ax, /* 0x48 */ + i_dec_cx, /* 0x49 */ + i_dec_dx, /* 0x4a */ + i_dec_bx, /* 0x4b */ + i_dec_sp, /* 0x4c */ + i_dec_bp, /* 0x4d */ + i_dec_si, /* 0x4e */ + i_dec_di, /* 0x4f */ + i_push_ax, /* 0x50 */ + i_push_cx, /* 0x51 */ + i_push_dx, /* 0x52 */ + i_push_bx, /* 0x53 */ + i_push_sp, /* 0x54 */ + i_push_bp, /* 0x55 */ + i_push_si, /* 0x56 */ + i_push_di, /* 0x57 */ + i_pop_ax, /* 0x58 */ + i_pop_cx, /* 0x59 */ + i_pop_dx, /* 0x5a */ + i_pop_bx, /* 0x5b */ + i_pop_sp, /* 0x5c */ + i_pop_bp, /* 0x5d */ + i_pop_si, /* 0x5e */ + i_pop_di, /* 0x5f */ + i_pusha, /* 0x60 */ + i_popa, /* 0x61 */ + i_chkind, /* 0x62 */ + i_brkn, /* 0x63 - V25S/V35S only */ + i_repnc, /* 0x64 */ + i_repc, /* 0x65 */ + i_invalid, /* 0x66 */ + i_invalid, /* 0x67 */ + i_push_d16, /* 0x68 */ + i_imul_d16, /* 0x69 */ + i_push_d8, /* 0x6a */ + i_imul_d8, /* 0x6b */ + i_insb, /* 0x6c */ + i_insw, /* 0x6d */ + i_outsb, /* 0x6e */ + i_outsw, /* 0x6f */ + i_jo, /* 0x70 */ + i_jno, /* 0x71 */ + i_jc, /* 0x72 */ + i_jnc, /* 0x73 */ + i_jz, /* 0x74 */ + i_jnz, /* 0x75 */ + i_jce, /* 0x76 */ + i_jnce, /* 0x77 */ + i_js, /* 0x78 */ + i_jns, /* 0x79 */ + i_jp, /* 0x7a */ + i_jnp, /* 0x7b */ + i_jl, /* 0x7c */ + i_jnl, /* 0x7d */ + i_jle, /* 0x7e */ + i_jnle, /* 0x7f */ + i_80pre, /* 0x80 */ + i_81pre, /* 0x81 */ + i_82pre, /* 0x82 */ + i_83pre, /* 0x83 */ + i_test_br8, /* 0x84 */ + i_test_wr16, /* 0x85 */ + i_xchg_br8, /* 0x86 */ + i_xchg_wr16, /* 0x87 */ + i_mov_br8, /* 0x88 */ + i_mov_wr16, /* 0x89 */ + i_mov_r8b, /* 0x8a */ + i_mov_r16w, /* 0x8b */ + i_mov_wsreg, /* 0x8c */ + i_lea, /* 0x8d */ + i_mov_sregw, /* 0x8e */ + i_popw, /* 0x8f */ + i_nop, /* 0x90 */ + i_xchg_axcx, /* 0x91 */ + i_xchg_axdx, /* 0x92 */ + i_xchg_axbx, /* 0x93 */ + i_xchg_axsp, /* 0x94 */ + i_xchg_axbp, /* 0x95 */ + i_xchg_axsi, /* 0x96 */ + i_xchg_axdi, /* 0x97 */ + i_cbw, /* 0x98 */ + i_cwd, /* 0x99 */ + i_call_far, /* 0x9a */ + i_wait, /* 0x9b */ + i_pushf, /* 0x9c */ + i_popf, /* 0x9d */ + i_sahf, /* 0x9e */ + i_lahf, /* 0x9f */ + i_mov_aldisp, /* 0xa0 */ + i_mov_axdisp, /* 0xa1 */ + i_mov_dispal, /* 0xa2 */ + i_mov_dispax, /* 0xa3 */ + i_movsb, /* 0xa4 */ + i_movsw, /* 0xa5 */ + i_cmpsb, /* 0xa6 */ + i_cmpsw, /* 0xa7 */ + i_test_ald8, /* 0xa8 */ + i_test_axd16, /* 0xa9 */ + i_stosb, /* 0xaa */ + i_stosw, /* 0xab */ + i_lodsb, /* 0xac */ + i_lodsw, /* 0xad */ + i_scasb, /* 0xae */ + i_scasw, /* 0xaf */ + i_mov_ald8, /* 0xb0 */ + i_mov_cld8, /* 0xb1 */ + i_mov_dld8, /* 0xb2 */ + i_mov_bld8, /* 0xb3 */ + i_mov_ahd8, /* 0xb4 */ + i_mov_chd8, /* 0xb5 */ + i_mov_dhd8, /* 0xb6 */ + i_mov_bhd8, /* 0xb7 */ + i_mov_axd16, /* 0xb8 */ + i_mov_cxd16, /* 0xb9 */ + i_mov_dxd16, /* 0xba */ + i_mov_bxd16, /* 0xbb */ + i_mov_spd16, /* 0xbc */ + i_mov_bpd16, /* 0xbd */ + i_mov_sid16, /* 0xbe */ + i_mov_did16, /* 0xbf */ + i_rotshft_bd8, /* 0xc0 */ + i_rotshft_wd8, /* 0xc1 */ + i_ret_d16, /* 0xc2 */ + i_ret, /* 0xc3 */ + i_les_dw, /* 0xc4 */ + i_lds_dw, /* 0xc5 */ + i_mov_bd8, /* 0xc6 */ + i_mov_wd16, /* 0xc7 */ + i_enter, /* 0xc8 */ + i_leave, /* 0xc9 */ + i_retf_d16, /* 0xca */ + i_retf, /* 0xcb */ + i_int3, /* 0xcc */ + i_int, /* 0xcd */ + i_into, /* 0xce */ + i_iret, /* 0xcf */ + i_rotshft_b, /* 0xd0 */ + i_rotshft_w, /* 0xd1 */ + i_rotshft_bcl, /* 0xd2 */ + i_rotshft_wcl, /* 0xd3 */ + i_aam, /* 0xd4 */ + i_aad, /* 0xd5 */ + i_setalc, /* 0xd6 */ + i_trans, /* 0xd7 */ + i_fpo, /* 0xd8 */ + i_fpo, /* 0xd9 */ + i_fpo, /* 0xda */ + i_fpo, /* 0xdb */ + i_fpo, /* 0xdc */ + i_fpo, /* 0xdd */ + i_fpo, /* 0xde */ + i_fpo, /* 0xdf */ + i_loopne, /* 0xe0 */ + i_loope, /* 0xe1 */ + i_loop, /* 0xe2 */ + i_jcxz, /* 0xe3 */ + i_inal, /* 0xe4 */ + i_inax, /* 0xe5 */ + i_outal, /* 0xe6 */ + i_outax, /* 0xe7 */ + i_call_d16, /* 0xe8 */ + i_jmp_d16, /* 0xe9 */ + i_jmp_far, /* 0xea */ + i_jmp_d8, /* 0xeb */ + i_inaldx, /* 0xec */ + i_inaxdx, /* 0xed */ + i_outdxal, /* 0xee */ + i_outdxax, /* 0xef */ + i_lock, /* 0xf0 */ + i_brks, /* 0xf1 */ + i_repne, /* 0xf2 */ + i_repe, /* 0xf3 */ + i_hlt, /* 0xf4 */ + i_cmc, /* 0xf5 */ + i_f6pre, /* 0xf6 */ + i_f7pre, /* 0xf7 */ + i_clc, /* 0xf8 */ + i_stc, /* 0xf9 */ + i_di, /* 0xfa */ + i_ei, /* 0xfb */ + i_cld, /* 0xfc */ + i_std, /* 0xfd */ + i_fepre, /* 0xfe */ + i_ffpre /* 0xff */ +}; diff --git a/src/cpu/nec/v25priv.h b/src/cpu/nec/v25priv.h new file mode 100644 index 00000000..82a1678d --- /dev/null +++ b/src/cpu/nec/v25priv.h @@ -0,0 +1,265 @@ +/* Cpu types, steps of 8 to help the cycle count calculation */ +#define V33_TYPE 0 +#define V30_TYPE 8 +#define V20_TYPE 16 + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/* interrupt vectors */ +enum +{ + NEC_DIVIDE_VECTOR = 0, + NEC_TRAP_VECTOR = 1, + NEC_NMI_VECTOR = 2, + NEC_BRKV_VECTOR = 4, + NEC_CHKIND_VECTOR = 5, + NEC_IBRK_VECTOR = 19, + NEC_INTTU0_VECTOR = 28, + NEC_INTTU1_VECTOR = 29, + NEC_INTTU2_VECTOR = 30, + NEC_INTD0_VECTOR = 20, + NEC_INTD1_VECTOR = 21, + NEC_INTP0_VECTOR = 24, + NEC_INTP1_VECTOR = 25, + NEC_INTP2_VECTOR = 26, + NEC_INTSER0_VECTOR = 12, + NEC_INTSR0_VECTOR = 13, + NEC_INTST0_VECTOR = 14, + NEC_INTSER1_VECTOR = 16, + NEC_INTSR1_VECTOR = 17, + NEC_INTST1_VECTOR = 18, + NEC_INTTB_VECTOR = 31 +}; + +/* interrupt sources */ +typedef enum +{ + BRK = 0, + INT_IRQ = 1, + NMI_IRQ = 1 << 1, + INTTU0 = 1 << 2, + INTTU1 = 1 << 3, + INTTU2 = 1 << 4, + INTD0 = 1 << 5, + INTD1 = 1 << 6, + INTP0 = 1 << 7, + INTP1 = 1 << 8, + INTP2 = 1 << 9, + INTSER0 = 1 << 10, + INTSR0 = 1 << 11, + INTST0 = 1 << 12, + INTSER1 = 1 << 13, + INTSR1 = 1 << 14, + INTST1 = 1 << 15, + INTTB = 1 << 16, + BRKN = 1 << 17, + BRKS = 1 << 18 +} INTSOURCES; + +/* internal RAM and register banks */ +typedef union +{ + UINT16 w[128]; + UINT8 b[256]; +} internalram; + +typedef struct _v25_state_t v25_state_t; +struct _v25_state_t +{ + internalram ram; + offs_t fetch_xor; + + UINT16 ip; + + /* PSW flags */ + INT32 SignVal; + UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ + UINT8 IBRK, F0, F1, TF, IF, DF, MF; /* 0 or 1 valued flags */ + UINT8 RBW, RBB; /* current register bank base, preshifted for word and byte registers */ + + /* interrupt related */ + UINT32 vector; + UINT32 pending_irq; + UINT32 unmasked_irq; + UINT32 bankswitch_irq; + UINT8 priority_inttu, priority_intd, priority_intp, priority_ints0, priority_ints1; + UINT8 IRQS, ISPR; + UINT32 nmi_state; + UINT32 irq_state; + UINT32 poll_state; + UINT32 mode_state; + UINT32 intp_state[3]; + UINT8 no_interrupt; + UINT8 halted; + + /* timer related */ + UINT16 TM0, MD0, TM1, MD1; + UINT8 TMC0, TMC1; +// emu_timer *timers[4]; + int timer_param[4]; + int timer_cycles_period[4]; + int timer_cycles_until_trigger[4]; + unsigned char timer_enabled[4]; + unsigned char timer_flags[4]; + unsigned int clock; // unscaled! + + /* system control */ + UINT8 RAMEN, TB, PCK; /* PRC register */ + UINT32 IDB; + + int icount; + + //const nec_config *config; + unsigned char *decode; + + UINT8 prefetch_size; + UINT8 prefetch_cycles; + INT8 prefetch_count; + UINT8 prefetch_reset; + UINT32 chip_type; + + UINT32 prefix_base; /* base address of the latest prefix segment */ + UINT8 seg_prefix; /* prefix segment indicator */ + + UINT32 cycles_total; + UINT32 cycles_remaining; + INT8 stop_run; +}; + +enum { + VECTOR_PC = 0x02/2, + PSW_SAVE = 0x04/2, + PC_SAVE = 0x06/2 +}; + +typedef enum { + DS1 = 0x0E/2, + PS = 0x0C/2, + SS = 0x0A/2, + DS0 = 0x08/2 +} SREGS; + +typedef enum { + AW = 0x1E/2, + CW = 0x1C/2, + DW = 0x1A/2, + BW = 0x18/2, + SP = 0x16/2, + BP = 0x14/2, + IX = 0x12/2, + IY = 0x10/2 +} WREGS; + +typedef enum { + AL = 0x1e, //NATIVE_ENDIAN_VALUE_LE_BE(0x1E, 0x1F), + AH = 0x1f, //NATIVE_ENDIAN_VALUE_LE_BE(0x1F, 0x1E), + CL = 0x1c, //NATIVE_ENDIAN_VALUE_LE_BE(0x1C, 0x1D), + CH = 0x1d, //NATIVE_ENDIAN_VALUE_LE_BE(0x1D, 0x1C), + DL = 0x1a, //NATIVE_ENDIAN_VALUE_LE_BE(0x1A, 0x1B), + DH = 0x1b, //NATIVE_ENDIAN_VALUE_LE_BE(0x1B, 0x1A), + BL = 0x18, //NATIVE_ENDIAN_VALUE_LE_BE(0x18, 0x19), + BH = 0x19 //NATIVE_ENDIAN_VALUE_LE_BE(0x19, 0x18) +} BREGS; + +#define SetRB(x) do { nec_state->RBW = (x) << 4; nec_state->RBB = (x) << 5; } while (0) + +#define Sreg(x) nec_state->ram.w[nec_state->RBW + (x)] +#define Wreg(x) nec_state->ram.w[nec_state->RBW + (x)] +#define Breg(x) nec_state->ram.b[nec_state->RBB + (x)] + +#define PC(n) ((Sreg(PS)<<4)+(n)->ip) + +#define CF (nec_state->CarryVal!=0) +#define SF (nec_state->SignVal<0) +#define ZF (nec_state->ZeroVal==0) +#define PF parity_table[(BYTE)nec_state->ParityVal] +#define AF (nec_state->AuxVal!=0) +#define OF (nec_state->OverVal!=0) +#define RB (nec_state->RBW >> 4) + +/************************************************************************/ + +UINT8 v25_read_byte(v25_state_t *nec_state, unsigned a); +UINT16 v25_read_word(v25_state_t *nec_state, unsigned a); +void v25_write_byte(v25_state_t *nec_state, unsigned a, UINT8 d); +void v25_write_word(v25_state_t *nec_state, unsigned a, UINT16 d); + +#define read_mem_byte(a) v25_read_byte(nec_state,(a)) +#define read_mem_word(a) v25_read_word(nec_state,(a)) +#define write_mem_byte(a,d) v25_write_byte(nec_state,(a),(d)) +#define write_mem_word(a,d) v25_write_word(nec_state,(a),(d)) + +#define read_port_byte(a) cpu_readport(a) +#define read_port_word(a) (cpu_readport(a)+cpu_readport((a)+1)*256) +#define write_port_byte(a,d) cpu_writeport((a),(d)) +//#define write_port_word(a,d) { cpu_writeport((a),(unsigned char)(d)); (cpu_writeport((a)+1,(d)>>8); } + +/************************************************************************/ + +#define CHANGE_PC do { EMPTY_PREFETCH(); } while (0) + +#define SegBase(Seg) (Sreg(Seg) << 4) + +#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4) + +#define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off))) +#define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off))) + +#define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); } +#define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); } + +/* prefetch timing */ + +#define FETCH() fetch(nec_state) +#define FETCHWORD() fetchword(nec_state) +#define EMPTY_PREFETCH() nec_state->prefetch_reset = 1 + + +#define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); } +#define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); } + +#define GetModRM UINT32 ModRM=FETCH() + +/* Cycle count macros: + CLK - cycle count is the same on all processors + CLKS - cycle count differs between processors, list all counts + CLKW - cycle count for word read/write differs for odd/even source/destination address + CLKM - cycle count for reg/mem instructions + CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses + + + Prefetch & buswait time is not emulated. + Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated. +*/ + +#define CLK(all) nec_state->icount-=all +#define CLKS(v20,v30,v33) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33; nec_state->icount-=(ccount>>nec_state->chip_type)&0x7f; } +#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } +#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_state->icount-=( ModRM >=0xc0 )?((ccount>>nec_state->chip_type)&0x7f):((mcount>>nec_state->chip_type)&0x7f); } +#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); } + +/************************************************************************/ +#define CompressFlags() (WORD)(CF | (nec_state->IBRK << 1) | (PF << 2) | (nec_state->F0 << 3) | (AF << 4) \ + | (nec_state->F1 << 5) | (ZF << 6) | (SF << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \ + | (nec_state->DF << 10) | (OF << 11) | (RB << 12) | (nec_state->MF << 15)) + +#define ExpandFlags(f) \ +{ \ + nec_state->CarryVal = (f) & 0x0001; \ + nec_state->IBRK = ((f) & 0x0002) == 0x0002; \ + nec_state->ParityVal = !((f) & 0x0004); \ + nec_state->F0 = ((f) & 0x0008) == 0x0008; \ + nec_state->AuxVal = (f) & 0x0010; \ + nec_state->F1 = ((f) & 0x0020) == 0x0020; \ + nec_state->ZeroVal = !((f) & 0x0040); \ + nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \ + nec_state->TF = ((f) & 0x0100) == 0x0100; \ + nec_state->IF = ((f) & 0x0200) == 0x0200; \ + nec_state->DF = ((f) & 0x0400) == 0x0400; \ + nec_state->OverVal = (f) & 0x0800; \ + /* RB only changes on BRKCS/RETRBI/TSKSW, so skip it */ \ + nec_state->MF = ((f) & 0x8000) == 0x8000; \ +} diff --git a/src/cpu/nec/v25sfr.c b/src/cpu/nec/v25sfr.c new file mode 100644 index 00000000..7d889873 --- /dev/null +++ b/src/cpu/nec/v25sfr.c @@ -0,0 +1,412 @@ +/**************************************************************************** + + NEC V25/V35 special function registers and internal ram access + +****************************************************************************/ + +//#include "emu.h" +//#include "nec.h" +//#include "v25priv.h" + +static UINT8 read_irqcontrol(v25_state_t *nec_state, INTSOURCES source, UINT8 priority) +{ + return (((nec_state->pending_irq & source) ? 0x80 : 0x00) + | ((nec_state->unmasked_irq & source) ? 0x00 : 0x40) + | ((nec_state->bankswitch_irq & source) ? 0x10 : 0x00) + | priority); +} + +static UINT8 read_sfr(v25_state_t *nec_state, unsigned o) +{ + UINT8 ret; + + switch(o) + { + case 0x00: /* P0 */ + ret = cpu_readport(V25_PORT_P0); + break; + case 0x08: /* P1 */ + /* P1 is combined with the interrupt lines */ + ret = ((cpu_readport(V25_PORT_P1) & 0xF0) + | (nec_state->nmi_state ? 0x00 : 0x01) + | (nec_state->intp_state[0] ? 0x00 : 0x02) + | (nec_state->intp_state[1] ? 0x00 : 0x04) + | (nec_state->intp_state[2] ? 0x00 : 0x08)); + break; + case 0x10: /* P2 */ + ret = cpu_readport(V25_PORT_P2); + break; + case 0x38: /* PT */ + ret = cpu_readport(V25_PORT_PT); + break; + case 0x4C: /* EXIC0 */ + ret = read_irqcontrol(nec_state, INTP0, nec_state->priority_intp); + break; + case 0x4D: /* EXIC1 */ + ret = read_irqcontrol(nec_state, INTP1, 7); + break; + case 0x4E: /* EXIC2 */ + ret = read_irqcontrol(nec_state, INTP2, 7); + break; + case 0x9C: /* TMIC0 */ + ret = read_irqcontrol(nec_state, INTTU0, nec_state->priority_inttu); + break; + case 0x9D: /* TMIC1 */ + ret = read_irqcontrol(nec_state, INTTU1, 7); + break; + case 0x9E: /* TMIC2 */ + ret = read_irqcontrol(nec_state, INTTU2, 7); + break; + case 0xEA: /* FLAG */ + ret = ((nec_state->F0 << 3) | (nec_state->F1 << 5)); + break; + case 0xEB: /* PRC */ + ret = (nec_state->RAMEN ? 0x40 : 0); + switch (nec_state->TB) + { + case 10: + break; + case 13: + ret |= 0x04; + break; + case 16: + ret |= 0x08; + break; + case 20: + ret |= 0x0C; + break; + } + switch (nec_state->PCK) + { + case 2: + break; + case 4: + ret |= 0x01; + break; + case 8: + ret |= 0x02; + break; + } + break; + case 0xEC: /* TBIC */ + ret = read_irqcontrol(nec_state, INTTB, 7); + break; + case 0xEF: /* IRQS */ + ret = nec_state->IRQS; + break; + case 0xFC: /* ISPR */ + ret = nec_state->ISPR; + break; + case 0xFF: /* IDB */ + ret = (nec_state->IDB >> 12); + break; + default: +// logerror("%06x: Read from special function register %02x\n",PC(nec_state),o); + ret = 0; + } + return ret; +} + +static UINT16 read_sfr_word(v25_state_t *nec_state, unsigned o) +{ + UINT16 ret; + + switch(o) + { + case 0x80: /* TM0 */ +// logerror("%06x: Warning: read back TM0\n",PC(nec_state)); + ret = nec_state->TM0; + break; + case 0x82: /* MD0 */ +// logerror("%06x: Warning: read back MD0\n",PC(nec_state)); + ret = nec_state->MD0; + break; + case 0x88: /* TM1 */ +// logerror("%06x: Warning: read back TM1\n",PC(nec_state)); + ret = nec_state->TM1; + break; + case 0x8A: /* MD1 */ +// logerror("%06x: Warning: read back MD1\n",PC(nec_state)); + ret = nec_state->MD1; + break; + default: + ret = (read_sfr(nec_state, o) | (read_sfr(nec_state, o+1) << 8)); + } + return ret; +} + +static void write_irqcontrol(v25_state_t *nec_state, INTSOURCES source, UINT8 d) +{ + if(d & 0x80) + nec_state->pending_irq |= source; + else + nec_state->pending_irq &= ~source; + + if(d & 0x40) + nec_state->unmasked_irq &= ~source; + else + nec_state->unmasked_irq |= source; + +// if(d & 0x20) +// logerror("%06x: Warning: macro service function not implemented\n",PC(nec_state)); + + if(d & 0x10) + nec_state->bankswitch_irq |= source; + else + nec_state->bankswitch_irq &= ~source; +} + +static void write_sfr(v25_state_t *nec_state, unsigned o, UINT8 d) +{ + int tmp; + + static const int timebases[4] = { 10, 13, 16, 20 }; + static const int clocks[4] = { 2, 4, 8, 0 }; + + switch(o) + { + case 0x00: /* P0 */ + cpu_writeport(V25_PORT_P0, d); + break; + case 0x08: /* P1 */ + /* only the upper four bits of P1 can be used as output */ + cpu_writeport(V25_PORT_P1, d & 0xF0); + break; + case 0x10: /* P2 */ + cpu_writeport(V25_PORT_P2, d); + break; + case 0x4C: /* EXIC0 */ + write_irqcontrol(nec_state, INTP0, d); + nec_state->priority_intp = d & 0x7; + break; + case 0x4D: /* EXIC1 */ + write_irqcontrol(nec_state, INTP1, d); + break; + case 0x4E: /* EXIC2 */ + write_irqcontrol(nec_state, INTP2, d); + break; + case 0x90: /* TMC0 */ + nec_state->TMC0 = d; + if(d & 1) /* oneshot mode */ + { + if(d & 0x80) + { + tmp = nec_state->TM0 * nec_state->PCK * ((d & 0x40) ? 128 : 12 ); + //bprintf (0, _T("A0, TIME: %d\n"), tmp); + add_timer(nec_state, 0, tmp, INTTU0, 0/*oneshot*/); +// time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp; +// nec_state->timers[0]->adjust(time, INTTU0); + } + else + nec_state->timer_enabled[0] = 0; + + if(d & 0x20) + { + tmp = nec_state->MD0 * nec_state->PCK * ((d & 0x10) ? 128 : 12 ); + //bprintf (0, _T("A1, TIME: %d\n"), tmp); + add_timer(nec_state, 1, tmp, INTTU1, 0/*oneshot*/); +// time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp; +// nec_state->timers[1]->adjust(time, INTTU1); + } + else + nec_state->timer_enabled[1] = 0; + } + else /* interval mode */ + { + if(d & 0x80) + { + tmp = nec_state->MD0 * nec_state->PCK * ((d & 0x40) ? 128 : 6 ); + //bprintf (0, _T("B0, TIME: %d\n"), tmp); + add_timer(nec_state, 0, tmp, INTTU0, 1/*repeat*/); +// time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp; +// nec_state->timers[0]->adjust(time, INTTU0, time); + nec_state->timer_enabled[1] = 0; + nec_state->TM0 = nec_state->MD0; + } + else + { + nec_state->timer_enabled[0] = 0; + nec_state->timer_enabled[1] = 0; + } + } + break; + case 0x91: /* TMC1 */ + nec_state->TMC1 = d & 0xC0; + if(d & 0x80) + { + tmp = nec_state->MD1 * nec_state->PCK * ((d & 0x40) ? 128 : 6 ); + //bprintf (0, _T("C2, TIME: %d\n"), tmp); + add_timer(nec_state, 2, tmp, INTTU2, 1/*repeat*/); +// time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp; +// nec_state->timers[2]->adjust(time, INTTU2, time); + nec_state->TM1 = nec_state->MD1; + } + else + nec_state->timer_enabled[2] = 0; + break; + case 0x9C: /* TMIC0 */ + write_irqcontrol(nec_state, INTTU0, d); + nec_state->priority_inttu = d & 0x7; + break; + case 0x9D: /* TMIC1 */ + write_irqcontrol(nec_state, INTTU1, d); + break; + case 0x9E: /* TMIC2 */ + write_irqcontrol(nec_state, INTTU2, d); + break; + case 0xEA: /* FLAG */ + nec_state->F0 = ((d & 0x08) == 0x08); + nec_state->F1 = ((d & 0x20) == 0x20); + break; + case 0xEB: /* PRC */ +// logerror("%06x: PRC set to %02x\n", PC(nec_state), d); + nec_state->RAMEN = ((d & 0x40) == 0x40); + nec_state->TB = timebases[(d & 0x0C) >> 2]; + nec_state->PCK = clocks[d & 0x03]; + if (nec_state->PCK == 0) + { +// logerror(" Warning: invalid clock divider\n"); + nec_state->PCK = 8; + } + tmp = nec_state->PCK << nec_state->TB; + //bprintf (0, _T("d3, TIME: %d\n"), tmp); + add_timer(nec_state, 3, tmp, INTTB, 1/*repeat*/); +// time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp; +// nec_state->timers[3]->adjust(time, INTTB, time); +// logerror(" Internal RAM %sabled\n", (nec_state->RAMEN ? "en" : "dis")); +// logerror(" Time base set to 2^%d\n", nec_state->TB); +// logerror(" Clock divider set to %d\n", nec_state->PCK); + break; + case 0xEC: /* TBIC */ + /* time base interrupt doesn't support macro service, bank switching or priority control */ + write_irqcontrol(nec_state, INTTB, d & 0xC0); + break; + case 0xFF: /* IDB */ + nec_state->IDB = (d << 12) | 0xE00; +// logerror("%06x: IDB set to %02x\n",PC(nec_state),d); + break; +// default: +// logerror("%06x: Wrote %02x to special function register %02x\n",PC(nec_state),d,o); + } +} + +static void write_sfr_word(v25_state_t *nec_state, unsigned o, UINT16 d) +{ + switch(o) + { + case 0x80: /* TM0 */ + nec_state->TM0 = d; + break; + case 0x82: /* MD0 */ + nec_state->MD0 = d; + break; + case 0x88: /* TM1 */ + nec_state->TM1 = d; + break; + case 0x8A: /* MD1 */ + nec_state->MD1 = d; + break; + default: + write_sfr(nec_state, o, d); + write_sfr(nec_state, o+1, d >> 8); + } +} + +UINT8 v25_read_byte(v25_state_t *nec_state, unsigned a) +{ + if((a & 0xFFE00) == nec_state->IDB || a == 0xFFFFF) + { + unsigned o = a & 0x1FF; + + if(nec_state->RAMEN && o < 0x100) + return nec_state->ram.b[o]; //BYTE_XOR_LE(o)]; + + if(o >= 0x100) + return read_sfr(nec_state, o-0x100); + } + + return cpu_readmem20(a); +} + +UINT16 v25_read_word(v25_state_t *nec_state, unsigned a) +{ + if( a & 1 ) + return (v25_read_byte(nec_state, a) | (v25_read_byte(nec_state, a + 1) << 8)); + + if((a & 0xFFE00) == nec_state->IDB) + { + unsigned o = a & 0x1FF; + + if(nec_state->RAMEN && o < 0x100) + return nec_state->ram.w[o/2]; + + if(o >= 0x100) + return read_sfr_word(nec_state, o-0x100); + } + + if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */ + return (cpu_readmem20(a) | (read_sfr(nec_state, 0xFF) << 8)); + + return (cpu_readmem20(a) | (cpu_readmem20(a + 1) << 8)); + //return nec_state->program->read_word(a); +} + +void v25_write_byte(v25_state_t *nec_state, unsigned a, UINT8 d) +{ + if((a & 0xFFE00) == nec_state->IDB || a == 0xFFFFF) + { + unsigned o = a & 0x1FF; + + if(nec_state->RAMEN && o < 0x100) + { + nec_state->ram.b[o] = d; //BYTE_XOR_LE(o)] = d; + return; + } + + if(o >= 0x100) + { + write_sfr(nec_state, o-0x100, d); + return; + } + } + + cpu_writemem20(a, d); +} + +void v25_write_word(v25_state_t *nec_state, unsigned a, UINT16 d) +{ + if( a & 1 ) + { + v25_write_byte(nec_state, a, d); + v25_write_byte(nec_state, a + 1, d >> 8); + return; + } + + if((a & 0xFFE00) == nec_state->IDB) + { + unsigned o = a & 0x1FF; + + if(nec_state->RAMEN && o < 0x100) + { + nec_state->ram.w[o/2] = d; + return; + } + + if(o >= 0x100) + { + write_sfr_word(nec_state, o-0x100, d); + return; + } + } + + if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */ + { + cpu_writemem20(a, d); + write_sfr(nec_state, 0xFF, d >> 8); + return; + } + + //nec_state->program->write_word(a, d); + cpu_writemem20(a, d); + cpu_writemem20(a+1, d>>8); +} diff --git a/src/cpu/s2650/s2650.cpp b/src/cpu/s2650/s2650.cpp new file mode 100644 index 00000000..74a9e953 --- /dev/null +++ b/src/cpu/s2650/s2650.cpp @@ -0,0 +1,1500 @@ +/************************************************************************* + * + * Portable Signetics 2650 cpu emulation + * + * Written by Juergen Buchmueller for use with MAME + * + * Version 1.2 + * - changed to clock cycle counts from machine cycles + * - replaced cycle table with S2650_INLINE code (M_RET conditional case) + * - removed wrong distinct add/sub CC and OVF handling + * - cosmetics, readability + * + *************************************************************************/ + +#include "s2650.h" +#include "burnint.h" +#include "s2650_intf.h" + +#define CLEAR_LINE 0 +#define change_pc(x) \ + S.page = x & PAGE; \ + S.iar = x & PMSK; \ + +/* define this to have some interrupt information logged */ +#define VERBOSE 0 + +/* define this to expand all EA calculations S2650_INLINE */ +#define INLINE_EA 1 + +#define S2650_INLINE static inline + +static int s2650_ICount = 0; + enum +{ + S2650_PC=1, S2650_PS, S2650_R0, S2650_R1, S2650_R2, S2650_R3, + S2650_R1A, S2650_R2A, S2650_R3A, + S2650_HALT, S2650_SI, S2650_FO +}; + +typedef struct { + UINT16 ppc; /* previous program counter (page + iar) */ + UINT16 page; /* 8K page select register (A14..A13) */ + UINT16 iar; /* instruction address register (A12..A0) */ + UINT16 ea; /* effective address (A14..A0) */ + UINT8 psl; /* processor status lower */ + UINT8 psu; /* processor status upper */ + UINT8 r; /* absolute addressing dst/src register */ + UINT8 reg[7]; /* 7 general purpose registers */ + UINT8 halt; /* 1 if cpu is halted */ + UINT8 ir; /* instruction register */ + UINT16 ras[8]; /* 8 return address stack entries */ + UINT8 irq_state; +} s2650_Regs; + +static s2650_Regs S; +static s2650_Regs Store[MAX_S2650]; +int nActiveS2650 = -1; + +/* condition code changes for a byte */ +static const UINT8 ccc[0x200] = { + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x04,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84 +}; + +static void s2650_set_sense(int state); + +#define CHECK_IRQ_LINE \ + if (S.irq_state != CLEAR_LINE) \ + { \ + if( (S.psu & II) == 0 ) \ + { \ + int vector; \ + if (S.halt) \ + { \ + S.halt = 0; \ + S.iar = (S.iar + 1) & PMSK; \ + } \ + if (s2650_irqcallback[nActiveS2650]) { \ + vector = s2650_irqcallback[nActiveS2650](0) & 0xff; \ + } else { \ + vector = 0; \ + } \ + /* build effective address within first 8K page */ \ + S.ea = S2650_relative[vector] & PMSK; \ + if (vector & 0x80) /* indirect bit set ? */ \ + { \ + int addr = S.ea; \ + s2650_ICount -= 6; \ + /* build indirect 32K address */ \ + S.ea = RDMEM(addr) << 8; \ + if (!(++addr & PMSK)) addr -= PLEN; \ + S.ea = (S.ea + RDMEM(addr)) & AMSK; \ + } \ + S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP) | II; \ + S.ras[S.psu & SP] = S.page + S.iar; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + } \ + } + +/*************************************************************** + * + * set condition code (zero,plus,minus) from result + ***************************************************************/ +#define SET_CC(result) \ + S.psl = (S.psl & ~CC) | ccc[result] + +/*************************************************************** + * + * set condition code (zero,plus,minus) and overflow + ***************************************************************/ +#define SET_CC_OVF(result,value) \ + S.psl = (S.psl & ~(OVF+CC)) | \ + ccc[result + (((value) & 0x80) << 1)] + +#define SET_CC_OVF_ADD(result,value1,value2) SET_CC_OVF(result,~((value1) ^ (value2)) & ((value1) ^ (result))) +#define SET_CC_OVF_SUB(result,value1,value2) SET_CC_OVF(result,~((value1) ^ (value2)) & ((value1) ^ (result))) + +/*************************************************************** + * ROP + * read next opcode + ***************************************************************/ +S2650_INLINE UINT8 ROP(void) +{ + UINT8 result = s2650_fetch(S.page + S.iar); + S.iar = (S.iar + 1) & PMSK; + return result; +} + +/*************************************************************** + * ARG + * read next opcode argument + ***************************************************************/ +S2650_INLINE UINT8 ARG(void) +{ + UINT8 result = s2650_fetch(S.page + S.iar); + S.iar = (S.iar + 1) & PMSK; + return result; +} + +/*************************************************************** + * RDMEM + * read memory byte from addr + ***************************************************************/ +#define RDMEM(addr) s2650_read(addr) + +/*************************************************************** + * handy table to build PC relative offsets + * from HR (holding register) + ***************************************************************/ +static const int S2650_relative[0x100] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49, + -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33, + -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17, + -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49, + -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33, + -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17, + -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, +}; + +/*************************************************************** + * _REL_EA + * build effective address with relative addressing + ***************************************************************/ +#define _REL_EA(page) \ +{ \ + UINT8 hr = ARG(); /* get 'holding register' */ \ + /* build effective address within current 8K page */ \ + S.ea = page + ((S.iar + S2650_relative[hr]) & PMSK); \ + if (hr & 0x80) { /* indirect bit set ? */ \ + int addr = S.ea; \ + s2650_ICount -= 6; \ + /* build indirect 32K address */ \ + S.ea = RDMEM(addr) << 8; \ + if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\ + S.ea = (S.ea + RDMEM(addr)) & AMSK; \ + } \ +} + +/*************************************************************** + * _REL_ZERO + * build effective address with zero relative addressing + ***************************************************************/ +#define _REL_ZERO(page) \ +{ \ + UINT8 hr = ARG(); /* get 'holding register' */ \ + /* build effective address from 0 */ \ + S.ea = (S2650_relative[hr] & PMSK); \ + if (hr & 0x80) { /* indirect bit set ? */ \ + int addr = S.ea; \ + s2650_ICount -= 6; \ + /* build indirect 32K address */ \ + S.ea = RDMEM(addr) << 8; \ + if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\ + S.ea = (S.ea + RDMEM(addr)) & AMSK; \ + } \ +} + +/*************************************************************** + * _ABS_EA + * build effective address with absolute addressing + ***************************************************************/ +#define _ABS_EA() \ +{ \ + UINT8 hr, dr; \ + hr = ARG(); /* get 'holding register' */ \ + dr = ARG(); /* get 'data bus register' */ \ + /* build effective address within current 8K page */ \ + S.ea = S.page + (((hr << 8) + dr) & PMSK); \ + /* indirect addressing ? */ \ + if (hr & 0x80) { \ + int addr = S.ea; \ + s2650_ICount -= 6; \ + /* build indirect 32K address */ \ + /* build indirect 32K address */ \ + S.ea = RDMEM(addr) << 8; \ + if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\ + S.ea = (S.ea + RDMEM(addr)) & AMSK; \ + } \ + /* check indexed addressing modes */ \ + switch (hr & 0x60) { \ + case 0x00: /* not indexed */ \ + break; \ + case 0x20: /* auto increment indexed */ \ + S.reg[S.r] += 1; \ + S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK); \ + S.r = 0; /* absolute addressing reg is R0 */ \ + break; \ + case 0x40: /* auto decrement indexed */ \ + S.reg[S.r] -= 1; \ + S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK); \ + S.r = 0; /* absolute addressing reg is R0 */ \ + break; \ + case 0x60: /* indexed */ \ + S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK); \ + S.r = 0; /* absolute addressing reg is R0 */ \ + break; \ + } \ +} + +/*************************************************************** + * _BRA_EA + * build effective address with absolute addressing (branch) + ***************************************************************/ +#define _BRA_EA() \ +{ \ + UINT8 hr, dr; \ + hr = ARG(); /* get 'holding register' */ \ + dr = ARG(); /* get 'data bus register' */ \ + /* build address in 32K address space */ \ + S.ea = ((hr << 8) + dr) & AMSK; \ + /* indirect addressing ? */ \ + if (hr & 0x80) { \ + int addr = S.ea; \ + s2650_ICount -= 6; \ + /* build indirect 32K address */ \ + S.ea = RDMEM(addr) << 8; \ + if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\ + S.ea = (S.ea + RDMEM(addr)) & AMSK; \ + } \ +} + +/*************************************************************** + * SWAP_REGS + * Swap registers r1-r3 with r4-r6 (the second set) + * This is done everytime the RS bit in PSL changes + ***************************************************************/ +#define SWAP_REGS \ +{ \ + UINT8 tmp; \ + tmp = S.reg[1]; \ + S.reg[1] = S.reg[4]; \ + S.reg[4] = tmp; \ + tmp = S.reg[2]; \ + S.reg[2] = S.reg[5]; \ + S.reg[5] = tmp; \ + tmp = S.reg[3]; \ + S.reg[3] = S.reg[6]; \ + S.reg[6] = tmp; \ +} + +/*************************************************************** + * M_BRR + * Branch relative if cond is true + ***************************************************************/ +#define M_BRR(cond) \ +{ \ + if (cond) \ + { \ + REL_EA( S.page ); \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + } else S.iar = (S.iar + 1) & PMSK; \ +} + +/*************************************************************** + * M_ZBRR + * Branch relative to page zero + ***************************************************************/ +#define M_ZBRR() \ +{ \ + REL_ZERO( 0 ); \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ +} + +/*************************************************************** + * M_BRA + * Branch absolute if cond is true + ***************************************************************/ +#define M_BRA(cond) \ +{ \ + if( cond ) \ + { \ + BRA_EA(); \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + } else S.iar = (S.iar + 2) & PMSK; \ +} + +/*************************************************************** + * M_BXA + * Branch indexed absolute (EA + R3) + ***************************************************************/ +#define M_BXA() \ +{ \ + BRA_EA(); \ + S.ea = (S.ea + S.reg[3]) & AMSK; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ +} + +/*************************************************************** + * M_BSR + * Branch to subroutine relative if cond is true + ***************************************************************/ +#define M_BSR(cond) \ +{ \ + if( cond ) \ + { \ + REL_EA(S.page); \ + S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP); \ + S.ras[S.psu & SP] = S.page + S.iar; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + } else S.iar = (S.iar + 1) & PMSK; \ +} + +/*************************************************************** + * M_ZBSR + * Branch to subroutine relative to page zero + ***************************************************************/ +#define M_ZBSR() \ +{ \ + REL_ZERO(0); \ + S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP); \ + S.ras[S.psu & SP] = S.page + S.iar; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ +} + +/*************************************************************** + * M_BSA + * Branch to subroutine absolute + ***************************************************************/ +#define M_BSA(cond) \ +{ \ + if( cond ) \ + { \ + BRA_EA(); \ + S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP); \ + S.ras[S.psu & SP] = S.page + S.iar; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + } else S.iar = (S.iar + 2) & PMSK; \ +} + +/*************************************************************** + * M_BSXA + * Branch to subroutine indexed absolute (EA + R3) + ***************************************************************/ +#define M_BSXA() \ +{ \ + BRA_EA(); \ + S.ea = (S.ea + S.reg[3]) & AMSK; \ + S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP); \ + S.ras[S.psu & SP] = S.page + S.iar; \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ +} + +/*************************************************************** + * M_RET + * Return from subroutine if cond is true + ***************************************************************/ +#define M_RET(cond) \ +{ \ + if( cond ) \ + { \ + s2650_ICount -= 6; \ + S.ea = S.ras[S.psu & SP]; \ + S.psu = (S.psu & ~SP) | ((S.psu - 1) & SP); \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + } \ +} + +/*************************************************************** + * M_RETE + * Return from subroutine if cond is true + * and enable interrupts; afterwards check IRQ line + * state and eventually take next interrupt + ***************************************************************/ +#define M_RETE(cond) \ +{ \ + if( cond ) \ + { \ + S.ea = S.ras[S.psu & SP]; \ + S.psu = (S.psu & ~SP) | ((S.psu - 1) & SP); \ + S.page = S.ea & PAGE; \ + S.iar = S.ea & PMSK; \ + change_pc(S.ea); \ + S.psu &= ~II; \ + CHECK_IRQ_LINE; \ + } \ +} + +/*************************************************************** + * M_LOD + * Load destination with source register + ***************************************************************/ +#define M_LOD(dest,source) \ +{ \ + dest = source; \ + SET_CC(dest); \ +} + +/*************************************************************** + * M_STR + * Store source register to memory addr (CC unchanged) + ***************************************************************/ +#define M_STR(address,source) \ + s2650_write(address, source) + +/*************************************************************** + * M_AND + * Logical and destination with source + ***************************************************************/ +#define M_AND(dest,source) \ +{ \ + dest &= source; \ + SET_CC(dest); \ +} + +/*************************************************************** + * M_IOR + * Logical inclusive or destination with source + ***************************************************************/ +#define M_IOR(dest,source) \ +{ \ + dest |= source; \ + SET_CC(dest); \ +} + +/*************************************************************** + * M_EOR + * Logical exclusive or destination with source + ***************************************************************/ +#define M_EOR(dest,source) \ +{ \ + dest ^= source; \ + SET_CC(dest); \ +} + +/*************************************************************** + * M_ADD + * Add source to destination + * Add with carry if WC flag of PSL is set + ***************************************************************/ +#define M_ADD(dest,_source) \ +{ \ + UINT8 source = _source; \ + UINT8 before = dest; \ + /* add source; carry only if WC is set */ \ + UINT16 res = dest + source + ((S.psl >> 3) & S.psl & C); \ + S.psl &= ~(C | OVF | IDC); \ + if(res & 0x100) S.psl |= C; \ + dest = res & 0xff; \ + if( (dest & 15) < (before & 15) ) S.psl |= IDC; \ + SET_CC_OVF_ADD(dest,before,source); \ +} + +/*************************************************************** + * M_SUB + * Subtract source from destination + * Subtract with borrow if WC flag of PSL is set + ***************************************************************/ +#define M_SUB(dest,_source) \ +{ \ + UINT8 source = _source; \ + UINT8 before = dest; \ + /* subtract source; borrow only if WC is set */ \ + UINT16 res = dest - source - ((S.psl >> 3) & (S.psl ^ C) & C); \ + S.psl &= ~(C | OVF | IDC); \ + if((res & 0x100)==0) S.psl |= C; \ + dest = res & 0xff; \ + if( (dest & 15) <= (before & 15) ) S.psl |= IDC; \ + SET_CC_OVF_SUB(dest,before,source); \ +} + +/*************************************************************** + * M_COM + * Compare register against value. If COM of PSL is set, + * use unsigned, else signed comparison + ***************************************************************/ +#define M_COM(reg,val) \ +{ \ + int d; \ + S.psl &= ~CC; \ + if (S.psl & COM) d = (UINT8)reg - (UINT8)val; \ + else d = (INT8)reg - (INT8)val; \ + if( d < 0 ) S.psl |= 0x80; \ + else \ + if( d > 0 ) S.psl |= 0x40; \ +} + +/*************************************************************** + * M_DAR + * Decimal adjust register + ***************************************************************/ +#define M_DAR(dest) \ +{ \ + if ((S.psl & C) == 0) dest += 0xA0; \ + if ((S.psl & IDC) == 0) dest = (dest & 0xF0) | ((dest + 0x0A) & 0x0F);\ +} + +/*************************************************************** + * M_RRL + * Rotate register left; If WC of PSL is set, rotate + * through carry, else rotate circular + ***************************************************************/ +#define M_RRL(dest) \ +{ \ + UINT8 before = dest; \ + if( S.psl & WC ) \ + { \ + UINT8 c = S.psl & C; \ + S.psl &= ~(C + IDC); \ + dest = (before << 1) | c; \ + S.psl |= (before >> 7) + (dest & IDC); \ + } \ + else \ + { \ + dest = (before << 1) | (before >> 7); \ + } \ + SET_CC(dest); \ + S.psl = (S.psl & ~OVF) | (((dest ^ before) >> 5) & OVF); \ +} + +/*************************************************************** + * M_RRR + * Rotate register right; If WC of PSL is set, rotate + * through carry, else rotate circular + ***************************************************************/ +#define M_RRR(dest) \ +{ \ + UINT8 before = dest; \ + if (S.psl & WC) \ + { \ + UINT8 c = S.psl & C; \ + S.psl &= ~(C + IDC); \ + dest = (before >> 1) | (c << 7); \ + S.psl |= (before & C) + (dest & IDC); \ + } else dest = (before >> 1) | (before << 7); \ + SET_CC(dest); \ + S.psl = (S.psl & ~OVF) | (((dest ^ before) >> 5) & OVF); \ +} + +// bxd() not necessary + +/*************************************************************** + * M_SPSU + * Store processor status upper (PSU) to register R0 + * Checks for External Sense IO port + ***************************************************************/ +#define M_SPSU() \ +{ \ + R0 = ((S.psu & ~PSU34) | (s2650_read_port(S2650_SENSE_PORT) & SI)); \ + SET_CC(R0); \ +} + +/*************************************************************** + * M_SPSL + * Store processor status lower (PSL) to register R0 + ***************************************************************/ +#define M_SPSL() \ +{ \ + R0 = S.psl; \ + SET_CC(R0); \ +} + +/*************************************************************** + * M_CPSU + * Clear processor status upper (PSU), selective + ***************************************************************/ +#define M_CPSU() \ +{ \ + UINT8 cpsu = ARG(); \ + S.psu = S.psu & ~cpsu; \ + CHECK_IRQ_LINE; \ +} + +/*************************************************************** + * M_CPSL + * Clear processor status lower (PSL), selective + ***************************************************************/ +#define M_CPSL() \ +{ \ + UINT8 cpsl = ARG(); \ + /* select other register set now ? */ \ + if( (cpsl & RS) && (S.psl & RS) ) \ + SWAP_REGS; \ + S.psl = S.psl & ~cpsl; \ + CHECK_IRQ_LINE; \ +} + +/*************************************************************** + * M_PPSU + * Preset processor status upper (PSU), selective + * Unused bits 3 and 4 can't be set + ***************************************************************/ +#define M_PPSU() \ +{ \ + UINT8 ppsu = (ARG() & ~PSU34) & ~SI; \ + S.psu = S.psu | ppsu; \ +} + +/*************************************************************** + * M_PPSL + * Preset processor status lower (PSL), selective + ***************************************************************/ +#define M_PPSL() \ +{ \ + UINT8 ppsl = ARG(); \ + /* select 2nd register set now ? */ \ + if ((ppsl & RS) && !(S.psl & RS)) \ + SWAP_REGS; \ + S.psl = S.psl | ppsl; \ +} + +/*************************************************************** + * M_TPSU + * Test processor status upper (PSU) + ***************************************************************/ +#define M_TPSU() \ +{ \ + UINT8 tpsu = ARG(); \ + UINT8 rpsu = (S.psu | (s2650_read_port(S2650_SENSE_PORT) & SI)); \ + S.psl &= ~CC; \ + if( (rpsu & tpsu) != tpsu ) \ + S.psl |= 0x80; \ +} + +/*************************************************************** + * M_TPSL + * Test processor status lower (PSL) + ***************************************************************/ +#define M_TPSL() \ +{ \ + UINT8 tpsl = ARG(); \ + if( (S.psl & tpsl) != tpsl ) \ + S.psl = (S.psl & ~CC) | 0x80; \ + else \ + S.psl &= ~CC; \ +} + +/*************************************************************** + * M_TMI + * Test under mask immediate + ***************************************************************/ +#define M_TMI(value) \ +{ \ + UINT8 tmi = ARG(); \ + S.psl &= ~CC; \ + if( (value & tmi) != tmi ) \ + S.psl |= 0x80; \ +} + +#if INLINE_EA +#define REL_EA(page) _REL_EA(page) +#define REL_ZERO(page) _REL_ZERO(page) +#define ABS_EA() _ABS_EA() +#define BRA_EA() _BRA_EA() +#else +static void REL_EA(unsigned short page) _REL_EA(page) +static void REL_ZERO(unsigned short page) _REL_ZERO(page) +static void ABS_EA(void) _ABS_EA() +static void BRA_EA(void) _BRA_EA() +#endif + +void s2650_reset(void) +{ + memset(&S, 0, sizeof(S)); + S.psl = COM | WC; + S.psu = 0; +} +/* +static void s2650_get_context(void *dst) +{ + if( dst ) + *(s2650_Regs*)dst = S; +} + +static void s2650_set_context(void *src) +{ + if( src ) + { + S = *(s2650_Regs*)src; + S.page = S.page & PAGE; + S.iar = S.iar & PMSK; + change_pc(S.page + S.iar); + } +} +*/ +void s2650_set_irq_line(int irqline, int state) +{ + if (irqline == 1) + { + if (state == CLEAR_LINE) + s2650_set_sense(0); + else + s2650_set_sense(1); + return; + } + + S.irq_state = state; + CHECK_IRQ_LINE; +} +/* +static void s2650_set_flag(int state) +{ + if (state) + S.psu |= FO; + else + S.psu &= ~FO; +} + +static int s2650_get_flag(void) +{ + return (S.psu & FO) ? 1 : 0; +} +*/ +static void s2650_set_sense(int state) +{ + if (state) + S.psu |= SI; + else + S.psu &= ~SI; +} +/* +static int s2650_get_sense(void) +{ + return (((S.psu & SI) ? 1 : 0) | ((s2650_read_port(S2650_SENSE_PORT) & SI) ? 1 : 0)); +}*/ + +int s2650Run(int cycles) +{ + s2650_ICount = cycles; + do + { + S.ppc = S.page + S.iar; + + S.ir = ROP(); + S.r = S.ir & 3; /* register / value */ + switch (S.ir) { + case 0x00: /* LODZ,0 */ + case 0x01: /* LODZ,1 */ + case 0x02: /* LODZ,2 */ + case 0x03: /* LODZ,3 */ + s2650_ICount -= 6; + M_LOD( R0, S.reg[S.r] ); + break; + + case 0x04: /* LODI,0 v */ + case 0x05: /* LODI,1 v */ + case 0x06: /* LODI,2 v */ + case 0x07: /* LODI,3 v */ + s2650_ICount -= 6; + M_LOD( S.reg[S.r], ARG() ); + break; + + case 0x08: /* LODR,0 (*)a */ + case 0x09: /* LODR,1 (*)a */ + case 0x0a: /* LODR,2 (*)a */ + case 0x0b: /* LODR,3 (*)a */ + s2650_ICount -= 9; + REL_EA( S.page ); + M_LOD( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x0c: /* LODA,0 (*)a(,X) */ + case 0x0d: /* LODA,1 (*)a(,X) */ + case 0x0e: /* LODA,2 (*)a(,X) */ + case 0x0f: /* LODA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_LOD( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x10: /* illegal */ + case 0x11: /* illegal */ + s2650_ICount -= 7; + break; + case 0x12: /* SPSU */ + s2650_ICount -= 6; + M_SPSU(); + break; + case 0x13: /* SPSL */ + s2650_ICount -= 6; + M_SPSL(); + break; + + case 0x14: /* RETC,0 (zero) */ + case 0x15: /* RETC,1 (plus) */ + case 0x16: /* RETC,2 (minus) */ + s2650_ICount -= 9; /* +2 cycles if condition is true */ + M_RET( (S.psl >> 6) == S.r ); + break; + case 0x17: /* RETC,3 (always) */ + s2650_ICount -= 9; /* +2 cycles if condition is true */ + M_RET( 1 ); + break; + + case 0x18: /* BCTR,0 (*)a */ + case 0x19: /* BCTR,1 (*)a */ + case 0x1a: /* BCTR,2 (*)a */ + s2650_ICount -= 9; + M_BRR( (S.psl >> 6) == S.r ); + break; + case 0x1b: /* BCTR,3 (*)a */ + s2650_ICount -= 9; + M_BRR( 1 ); + break; + + case 0x1c: /* BCTA,0 (*)a */ + case 0x1d: /* BCTA,1 (*)a */ + case 0x1e: /* BCTA,2 (*)a */ + s2650_ICount -= 9; + M_BRA( (S.psl >> 6) == S.r ); + break; + case 0x1f: /* BCTA,3 (*)a */ + s2650_ICount -= 9; + M_BRA( 1 ); + break; + + case 0x20: /* EORZ,0 */ + case 0x21: /* EORZ,1 */ + case 0x22: /* EORZ,2 */ + case 0x23: /* EORZ,3 */ + s2650_ICount -= 6; + M_EOR( R0, S.reg[S.r] ); + break; + + case 0x24: /* EORI,0 v */ + case 0x25: /* EORI,1 v */ + case 0x26: /* EORI,2 v */ + case 0x27: /* EORI,3 v */ + s2650_ICount -= 6; + M_EOR( S.reg[S.r], ARG() ); + break; + + case 0x28: /* EORR,0 (*)a */ + case 0x29: /* EORR,1 (*)a */ + case 0x2a: /* EORR,2 (*)a */ + case 0x2b: /* EORR,3 (*)a */ + s2650_ICount -= 9; + REL_EA( S.page ); + M_EOR( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x2c: /* EORA,0 (*)a(,X) */ + case 0x2d: /* EORA,1 (*)a(,X) */ + case 0x2e: /* EORA,2 (*)a(,X) */ + case 0x2f: /* EORA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_EOR( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x30: /* REDC,0 */ + case 0x31: /* REDC,1 */ + case 0x32: /* REDC,2 */ + case 0x33: /* REDC,3 */ + s2650_ICount -= 6; + S.reg[S.r] = s2650_read_port(S2650_CTRL_PORT); + SET_CC( S.reg[S.r] ); + break; + + case 0x34: /* RETE,0 */ + case 0x35: /* RETE,1 */ + case 0x36: /* RETE,2 */ + s2650_ICount -= 9; + M_RETE( (S.psl >> 6) == S.r ); + break; + case 0x37: /* RETE,3 */ + s2650_ICount -= 9; + M_RETE( 1 ); + break; + + case 0x38: /* BSTR,0 (*)a */ + case 0x39: /* BSTR,1 (*)a */ + case 0x3a: /* BSTR,2 (*)a */ + s2650_ICount -= 9; + M_BSR( (S.psl >> 6) == S.r ); + break; + case 0x3b: /* BSTR,R3 (*)a */ + s2650_ICount -= 9; + M_BSR( 1 ); + break; + + case 0x3c: /* BSTA,0 (*)a */ + case 0x3d: /* BSTA,1 (*)a */ + case 0x3e: /* BSTA,2 (*)a */ + s2650_ICount -= 9; + M_BSA( (S.psl >> 6) == S.r ); + break; + case 0x3f: /* BSTA,3 (*)a */ + s2650_ICount -= 9; + M_BSA( 1 ); + break; + + case 0x40: /* HALT */ + s2650_ICount -= 6; + S.iar = (S.iar - 1) & PMSK; + S.halt = 1; + if (s2650_ICount > 0) + s2650_ICount = 0; + break; + case 0x41: /* ANDZ,1 */ + case 0x42: /* ANDZ,2 */ + case 0x43: /* ANDZ,3 */ + s2650_ICount -= 6; + M_AND( R0, S.reg[S.r] ); + break; + + case 0x44: /* ANDI,0 v */ + case 0x45: /* ANDI,1 v */ + case 0x46: /* ANDI,2 v */ + case 0x47: /* ANDI,3 v */ + s2650_ICount -= 6; + M_AND( S.reg[S.r], ARG() ); + break; + + case 0x48: /* ANDR,0 (*)a */ + case 0x49: /* ANDR,1 (*)a */ + case 0x4a: /* ANDR,2 (*)a */ + case 0x4b: /* ANDR,3 (*)a */ + s2650_ICount -= 9; + REL_EA( S.page ); + M_AND( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x4c: /* ANDA,0 (*)a(,X) */ + case 0x4d: /* ANDA,1 (*)a(,X) */ + case 0x4e: /* ANDA,2 (*)a(,X) */ + case 0x4f: /* ANDA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_AND( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x50: /* RRR,0 */ + case 0x51: /* RRR,1 */ + case 0x52: /* RRR,2 */ + case 0x53: /* RRR,3 */ + s2650_ICount -= 6; + M_RRR( S.reg[S.r] ); + break; + + case 0x54: /* REDE,0 v */ + case 0x55: /* REDE,1 v */ + case 0x56: /* REDE,2 v */ + case 0x57: /* REDE,3 v */ + s2650_ICount -= 9; + S.reg[S.r] = s2650_read_port( ARG() ); + SET_CC(S.reg[S.r]); + break; + + case 0x58: /* BRNR,0 (*)a */ + case 0x59: /* BRNR,1 (*)a */ + case 0x5a: /* BRNR,2 (*)a */ + case 0x5b: /* BRNR,3 (*)a */ + s2650_ICount -= 9; + M_BRR( S.reg[S.r] ); + break; + + case 0x5c: /* BRNA,0 (*)a */ + case 0x5d: /* BRNA,1 (*)a */ + case 0x5e: /* BRNA,2 (*)a */ + case 0x5f: /* BRNA,3 (*)a */ + s2650_ICount -= 9; + M_BRA( S.reg[S.r] ); + break; + + case 0x60: /* IORZ,0 */ + case 0x61: /* IORZ,1 */ + case 0x62: /* IORZ,2 */ + case 0x63: /* IORZ,3 */ + s2650_ICount -= 6; + M_IOR( R0, S.reg[S.r] ); + break; + + case 0x64: /* IORI,0 v */ + case 0x65: /* IORI,1 v */ + case 0x66: /* IORI,2 v */ + case 0x67: /* IORI,3 v */ + s2650_ICount -= 6; + M_IOR( S.reg[S.r], ARG() ); + break; + + case 0x68: /* IORR,0 (*)a */ + case 0x69: /* IORR,1 (*)a */ + case 0x6a: /* IORR,2 (*)a */ + case 0x6b: /* IORR,3 (*)a */ + s2650_ICount -= 9; + REL_EA( S.page ); + M_IOR( S.reg[S. r],RDMEM(S.ea) ); + break; + + case 0x6c: /* IORA,0 (*)a(,X) */ + case 0x6d: /* IORA,1 (*)a(,X) */ + case 0x6e: /* IORA,2 (*)a(,X) */ + case 0x6f: /* IORA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_IOR( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x70: /* REDD,0 */ + case 0x71: /* REDD,1 */ + case 0x72: /* REDD,2 */ + case 0x73: /* REDD,3 */ + s2650_ICount -= 6; + S.reg[S.r] = s2650_read_port(S2650_DATA_PORT); + SET_CC(S.reg[S.r]); + break; + + case 0x74: /* CPSU */ + s2650_ICount -= 9; + M_CPSU(); + break; + case 0x75: /* CPSL */ + s2650_ICount -= 9; + M_CPSL(); + break; + case 0x76: /* PPSU */ + s2650_ICount -= 9; + M_PPSU(); + break; + case 0x77: /* PPSL */ + s2650_ICount -= 9; + M_PPSL(); + break; + + case 0x78: /* BSNR,0 (*)a */ + case 0x79: /* BSNR,1 (*)a */ + case 0x7a: /* BSNR,2 (*)a */ + case 0x7b: /* BSNR,3 (*)a */ + s2650_ICount -= 9; + M_BSR( S.reg[S.r] ); + break; + + case 0x7c: /* BSNA,0 (*)a */ + case 0x7d: /* BSNA,1 (*)a */ + case 0x7e: /* BSNA,2 (*)a */ + case 0x7f: /* BSNA,3 (*)a */ + s2650_ICount -= 9; + M_BSA( S.reg[S.r] ); + break; + + case 0x80: /* ADDZ,0 */ + case 0x81: /* ADDZ,1 */ + case 0x82: /* ADDZ,2 */ + case 0x83: /* ADDZ,3 */ + s2650_ICount -= 6; + M_ADD( R0,S.reg[S.r] ); + break; + + case 0x84: /* ADDI,0 v */ + case 0x85: /* ADDI,1 v */ + case 0x86: /* ADDI,2 v */ + case 0x87: /* ADDI,3 v */ + s2650_ICount -= 6; + M_ADD( S.reg[S.r], ARG() ); + break; + + case 0x88: /* ADDR,0 (*)a */ + case 0x89: /* ADDR,1 (*)a */ + case 0x8a: /* ADDR,2 (*)a */ + case 0x8b: /* ADDR,3 (*)a */ + s2650_ICount -= 9; + REL_EA(S.page); + M_ADD( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x8c: /* ADDA,0 (*)a(,X) */ + case 0x8d: /* ADDA,1 (*)a(,X) */ + case 0x8e: /* ADDA,2 (*)a(,X) */ + case 0x8f: /* ADDA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_ADD( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0x90: /* illegal */ + case 0x91: /* illegal */ + s2650_ICount -= 7; + break; + case 0x92: /* LPSU */ + s2650_ICount -= 6; + S.psu = (R0 & ~PSU34) & ~SI; + break; + case 0x93: /* LPSL */ + s2650_ICount -= 6; + /* change register set ? */ + if ((S.psl ^ R0) & RS) + SWAP_REGS; + S.psl = R0; + break; + + case 0x94: /* DAR,0 */ + case 0x95: /* DAR,1 */ + case 0x96: /* DAR,2 */ + case 0x97: /* DAR,3 */ + s2650_ICount -= 9; + M_DAR( S.reg[S.r] ); + break; + + case 0x98: /* BCFR,0 (*)a */ + case 0x99: /* BCFR,1 (*)a */ + case 0x9a: /* BCFR,2 (*)a */ + s2650_ICount -= 9; + M_BRR( (S.psl >> 6) != S.r ); + break; + case 0x9b: /* ZBRR (*)a */ + s2650_ICount -= 9; + M_ZBRR(); + break; + + case 0x9c: /* BCFA,0 (*)a */ + case 0x9d: /* BCFA,1 (*)a */ + case 0x9e: /* BCFA,2 (*)a */ + s2650_ICount -= 9; + M_BRA( (S.psl >> 6) != S.r ); + break; + case 0x9f: /* BXA (*)a */ + s2650_ICount -= 9; + M_BXA(); + break; + + case 0xa0: /* SUBZ,0 */ + case 0xa1: /* SUBZ,1 */ + case 0xa2: /* SUBZ,2 */ + case 0xa3: /* SUBZ,3 */ + s2650_ICount -= 6; + M_SUB( R0, S.reg[S.r] ); + break; + + case 0xa4: /* SUBI,0 v */ + case 0xa5: /* SUBI,1 v */ + case 0xa6: /* SUBI,2 v */ + case 0xa7: /* SUBI,3 v */ + s2650_ICount -= 6; + M_SUB( S.reg[S.r], ARG() ); + break; + + case 0xa8: /* SUBR,0 (*)a */ + case 0xa9: /* SUBR,1 (*)a */ + case 0xaa: /* SUBR,2 (*)a */ + case 0xab: /* SUBR,3 (*)a */ + s2650_ICount -= 9; + REL_EA(S.page); + M_SUB( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0xac: /* SUBA,0 (*)a(,X) */ + case 0xad: /* SUBA,1 (*)a(,X) */ + case 0xae: /* SUBA,2 (*)a(,X) */ + case 0xaf: /* SUBA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_SUB( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0xb0: /* WRTC,0 */ + case 0xb1: /* WRTC,1 */ + case 0xb2: /* WRTC,2 */ + case 0xb3: /* WRTC,3 */ + s2650_ICount -= 6; + s2650_write_port(S2650_CTRL_PORT,S.reg[S.r]); + break; + + case 0xb4: /* TPSU */ + s2650_ICount -= 9; + M_TPSU(); + break; + case 0xb5: /* TPSL */ + s2650_ICount -= 9; + M_TPSL(); + break; + case 0xb6: /* illegal */ + case 0xb7: /* illegal */ + s2650_ICount -= 7; + break; + + case 0xb8: /* BSFR,0 (*)a */ + case 0xb9: /* BSFR,1 (*)a */ + case 0xba: /* BSFR,2 (*)a */ + s2650_ICount -= 9; + M_BSR( (S.psl >> 6) != S.r ); + break; + case 0xbb: /* ZBSR (*)a */ + s2650_ICount -= 9; + M_ZBSR(); + break; + + case 0xbc: /* BSFA,0 (*)a */ + case 0xbd: /* BSFA,1 (*)a */ + case 0xbe: /* BSFA,2 (*)a */ + s2650_ICount -= 9; + M_BSA( (S.psl >> 6) != S.r ); + break; + case 0xbf: /* BSXA (*)a */ + s2650_ICount -= 9; + M_BSXA(); + break; + + case 0xc0: /* NOP */ + s2650_ICount -= 6; + break; + case 0xc1: /* STRZ,1 */ + case 0xc2: /* STRZ,2 */ + case 0xc3: /* STRZ,3 */ + s2650_ICount -= 6; + M_LOD( S.reg[S.r], R0 ); + break; + + case 0xc4: /* illegal */ + case 0xc5: /* illegal */ + case 0xc6: /* illegal */ + case 0xc7: /* illegal */ + s2650_ICount -= 7; + break; + + case 0xc8: /* STRR,0 (*)a */ + case 0xc9: /* STRR,1 (*)a */ + case 0xca: /* STRR,2 (*)a */ + case 0xcb: /* STRR,3 (*)a */ + s2650_ICount -= 9; + REL_EA(S.page); + M_STR( S.ea, S.reg[S.r] ); + break; + + case 0xcc: /* STRA,0 (*)a(,X) */ + case 0xcd: /* STRA,1 (*)a(,X) */ + case 0xce: /* STRA,2 (*)a(,X) */ + case 0xcf: /* STRA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_STR( S.ea, S.reg[S.r] ); + break; + + case 0xd0: /* RRL,0 */ + case 0xd1: /* RRL,1 */ + case 0xd2: /* RRL,2 */ + case 0xd3: /* RRL,3 */ + s2650_ICount -= 6; + M_RRL( S.reg[S.r] ); + break; + + case 0xd4: /* WRTE,0 v */ + case 0xd5: /* WRTE,1 v */ + case 0xd6: /* WRTE,2 v */ + case 0xd7: /* WRTE,3 v */ + s2650_ICount -= 9; + s2650_write_port( ARG(), S.reg[S.r] ); + break; + + case 0xd8: /* BIRR,0 (*)a */ + case 0xd9: /* BIRR,1 (*)a */ + case 0xda: /* BIRR,2 (*)a */ + case 0xdb: /* BIRR,3 (*)a */ + s2650_ICount -= 9; + M_BRR( ++S.reg[S.r] ); + break; + + case 0xdc: /* BIRA,0 (*)a */ + case 0xdd: /* BIRA,1 (*)a */ + case 0xde: /* BIRA,2 (*)a */ + case 0xdf: /* BIRA,3 (*)a */ + s2650_ICount -= 9; + M_BRA( ++S.reg[S.r] ); + break; + + case 0xe0: /* COMZ,0 */ + case 0xe1: /* COMZ,1 */ + case 0xe2: /* COMZ,2 */ + case 0xe3: /* COMZ,3 */ + s2650_ICount -= 6; + M_COM( R0, S.reg[S.r] ); + break; + + case 0xe4: /* COMI,0 v */ + case 0xe5: /* COMI,1 v */ + case 0xe6: /* COMI,2 v */ + case 0xe7: /* COMI,3 v */ + s2650_ICount -= 6; + M_COM( S.reg[S.r], ARG() ); + break; + + case 0xe8: /* COMR,0 (*)a */ + case 0xe9: /* COMR,1 (*)a */ + case 0xea: /* COMR,2 (*)a */ + case 0xeb: /* COMR,3 (*)a */ + s2650_ICount -= 9; + REL_EA(S.page); + M_COM( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0xec: /* COMA,0 (*)a(,X) */ + case 0xed: /* COMA,1 (*)a(,X) */ + case 0xee: /* COMA,2 (*)a(,X) */ + case 0xef: /* COMA,3 (*)a(,X) */ + s2650_ICount -= 12; + ABS_EA(); + M_COM( S.reg[S.r], RDMEM(S.ea) ); + break; + + case 0xf0: /* WRTD,0 */ + case 0xf1: /* WRTD,1 */ + case 0xf2: /* WRTD,2 */ + case 0xf3: /* WRTD,3 */ + s2650_ICount -= 6; + s2650_write_port(S2650_DATA_PORT, S.reg[S.r]); + break; + + case 0xf4: /* TMI,0 v */ + case 0xf5: /* TMI,1 v */ + case 0xf6: /* TMI,2 v */ + case 0xf7: /* TMI,3 v */ + s2650_ICount -= 9; + M_TMI( S.reg[S.r] ); + break; + + case 0xf8: /* BDRR,0 (*)a */ + case 0xf9: /* BDRR,1 (*)a */ + case 0xfa: /* BDRR,2 (*)a */ + case 0xfb: /* BDRR,3 (*)a */ + s2650_ICount -= 9; + M_BRR( --S.reg[S.r] ); + break; + + case 0xfc: /* BDRA,0 (*)a */ + case 0xfd: /* BDRA,1 (*)a */ + case 0xfe: /* BDRA,2 (*)a */ + case 0xff: /* BDRA,3 (*)a */ + s2650_ICount -= 9; + M_BRA( --S.reg[S.r] ); + break; + } + } while( s2650_ICount > 0 ); + + return cycles - s2650_ICount; +} + +int s2650Scan(int nAction,int */*pnMin*/) +{ + struct BurnArea ba; + + if (nAction & ACB_DRIVER_DATA) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = &Store; + ba.nLen = sizeof(S) * MAX_S2650; + ba.szName = "All Ram"; + BurnAcb(&ba); + } + + return 0; +} + +void s2650_open(int num) +{ + nActiveS2650 = num; + memcpy (&S, &Store[nActiveS2650], sizeof (S)); +} + +void s2650_close() +{ + memcpy (&Store[nActiveS2650], &S, sizeof (S)); + nActiveS2650 = -1; +} + +void s2650_init(int num) +{ + memset (&S, 0, sizeof(S)); + memset (&Store, 0, sizeof(S) * num); +} + +void s2650_exit() +{ + memset (&S, 0, sizeof(S)); + memset (&Store, 0, sizeof(S) * MAX_S2650); +} + +int s2650_get_pc() +{ + return S.page + S.iar; +} diff --git a/src/cpu/s2650/s2650.h b/src/cpu/s2650/s2650.h new file mode 100644 index 00000000..edd2c5f9 --- /dev/null +++ b/src/cpu/s2650/s2650.h @@ -0,0 +1,33 @@ +/******************************************************* + * + * Portable Signetics 2650 cpu emulation + * + * Written by Juergen Buchmueller for use with MAME + * + *******************************************************/ + +#define PMSK 0x1fff /* mask page offset */ +#define PLEN 0x2000 /* page length */ +#define PAGE 0x6000 /* mask page */ +#define AMSK 0x7fff /* mask address range */ + +/* processor status lower */ +#define C 0x01 /* carry flag */ +#define COM 0x02 /* compare: 0 binary, 1 2s complement */ +#define OVF 0x04 /* 2s complement overflow */ +#define WC 0x08 /* with carry: use carry in arithmetic / rotate ops */ +#define RS 0x10 /* register select 0: R0/R1/R2/R3 1: R0/R4/R5/R6 */ +#define IDC 0x20 /* inter digit carry: bit-3-to-bit-4 carry */ +#define CC 0xc0 /* condition code */ + +/* processor status upper */ +#define SP 0x07 /* stack pointer: indexing 8 15bit words */ +#define PSU34 0x18 /* unused bits */ +#define II 0x20 /* interrupt inhibit 0: allow, 1: inhibit */ +#define FO 0x40 /* flag output */ +#define SI 0x80 /* sense input */ + +#define R0 S.reg[0] +#define R1 S.reg[1] +#define R2 S.reg[2] +#define R3 S.reg[3] diff --git a/src/cpu/s2650_intf.cpp b/src/cpu/s2650_intf.cpp new file mode 100644 index 00000000..fd065ea4 --- /dev/null +++ b/src/cpu/s2650_intf.cpp @@ -0,0 +1,188 @@ +#include "burnint.h" +#include "s2650_intf.h" + +#define ADDRESS_MAX 0x8000 +#define ADDRESS_MASK 0x7fff +#define PAGE 0x0100 +#define PAGE_MASK 0x00ff + +#define READ 0 +#define WRITE 1 +#define FETCH 2 + +INT32 s2650Count; + +struct s2650_handler +{ + UINT8 (*s2650Read)(UINT16 address); + void (*s2650Write)(UINT16 address, UINT8 data); + + UINT8 (*s2650ReadPort)(UINT16 port); + void (*s2650WritePort)(UINT16 port, UINT8 data); + + UINT8 *mem[3][ADDRESS_MAX / PAGE]; +}; + +struct s2650_handler sHandler[MAX_S2650]; +struct s2650_handler *sPointer; + +s2650irqcallback s2650_irqcallback[MAX_S2650]; + +void s2650MapMemory(UINT8 *ptr, INT32 nStart, INT32 nEnd, INT32 nType) +{ + for (INT32 i = nStart / PAGE; i < (nEnd / PAGE) + 1; i++) + { + if (nType & (1 << READ)) sPointer->mem[ READ][i] = ptr + ((i * PAGE) - nStart); + if (nType & (1 << WRITE)) sPointer->mem[WRITE][i] = ptr + ((i * PAGE) - nStart); + if (nType & (1 << FETCH)) sPointer->mem[FETCH][i] = ptr + ((i * PAGE) - nStart); + } +} + +void s2650SetWriteHandler(void (*write)(UINT16, UINT8)) +{ + sPointer->s2650Write = write; +} + +void s2650SetReadHandler(UINT8 (*read)(UINT16)) +{ + sPointer->s2650Read = read; +} + +void s2650SetOutHandler(void (*write)(UINT16, UINT8)) +{ + sPointer->s2650WritePort = write; +} + +void s2650SetInHandler(UINT8 (*read)(UINT16)) +{ + sPointer->s2650ReadPort = read; +} + +void s2650_write(UINT16 address, UINT8 data) +{ + address &= ADDRESS_MASK; + + if (sPointer->mem[WRITE][address / PAGE] != NULL) { + sPointer->mem[WRITE][address / PAGE][address & PAGE_MASK] = data; + return; + } + + if (sPointer->s2650Write != NULL) { + sPointer->s2650Write(address, data); + return; + } + + return; +} + +UINT8 s2650_read(UINT16 address) +{ + address &= ADDRESS_MASK; + + if (sPointer->mem[READ][address / PAGE] != NULL) { + return sPointer->mem[READ][address / PAGE][address & PAGE_MASK]; + } + + if (sPointer->s2650Read != NULL) { + return sPointer->s2650Read(address); + } + + return 0; +} + +UINT8 s2650_fetch(UINT16 address) +{ + address &= ADDRESS_MASK; + + if (sPointer->mem[FETCH][address / PAGE] != NULL) { + return sPointer->mem[FETCH][address / PAGE][address & PAGE_MASK]; + } + + return s2650_read(address); +} + +void s2650_write_port(UINT16 port, UINT8 data) +{ + if (sPointer->s2650WritePort != NULL) { + sPointer->s2650WritePort(port, data); + return; + } + + return; +} + +UINT8 s2650_read_port(UINT16 port) +{ + if (sPointer->s2650ReadPort != NULL) { + return sPointer->s2650ReadPort(port); + } + + return 0; +} + +void s2650_write_rom(UINT16 address, UINT8 data) +{ + address &= ADDRESS_MASK; + + if (sPointer->mem[READ][address / PAGE] != NULL) { + sPointer->mem[READ][address / PAGE][address & PAGE_MASK] = data; + } + + if (sPointer->mem[WRITE][address / PAGE] != NULL) { + sPointer->mem[WRITE][address / PAGE][address & PAGE_MASK] = data; + } + + if (sPointer->mem[FETCH][address / PAGE] != NULL) { + sPointer->mem[FETCH][address / PAGE][address & PAGE_MASK] = data; + } + + if (sPointer->s2650Write != NULL) { + sPointer->s2650Write(address, data); + return; + } + + return; +} + +void s2650SetIrqCallback(INT32 (*irqcallback)(INT32)) +{ + s2650_irqcallback[nActiveS2650] = irqcallback; +} + +void s2650Init(INT32 num) +{ + s2650Count = num; + memset (&sHandler, 0, sizeof (s2650_handler) * (num % MAX_S2650)); + s2650_init(num); + + for (INT32 i = 0; i < num; i++) + CpuCheatRegister(0x0008, i); +} + +void s2650Exit() +{ + memset (&sHandler, 0, sizeof (sHandler)); + s2650Count = 0; + s2650_exit(); +} + +void s2650Open(INT32 num) +{ + sPointer = &sHandler[num % MAX_S2650]; + s2650_open(num); +} + +void s2650Close() +{ + s2650_close(); +} + +INT32 s2650GetPc() +{ + return s2650_get_pc(); +} + +INT32 s2650GetActive() +{ + return nActiveS2650; +} diff --git a/src/cpu/s2650_intf.h b/src/cpu/s2650_intf.h new file mode 100644 index 00000000..46fc1bba --- /dev/null +++ b/src/cpu/s2650_intf.h @@ -0,0 +1,60 @@ +#define MAX_S2650 4 +extern INT32 nActiveS2650; +extern INT32 s2650Count; + +void s2650_write(UINT16 address, UINT8 data); +UINT8 s2650_read(UINT16 address); +UINT8 s2650_fetch(UINT16 address); +void s2650_write_port(UINT16 port, UINT8 data); +UINT8 s2650_read_port(UINT16 port); + +void s2650_write_rom(UINT16 address, UINT8 data); + +typedef INT32 (*s2650irqcallback)(INT32); +extern s2650irqcallback s2650_irqcallback[MAX_S2650]; +void s2650SetIrqCallback(INT32 (*irqcallback)(INT32)); + +void s2650_open(INT32 num); +void s2650_close(); +void s2650_init(INT32 num); +void s2650_exit(); +void s2650_reset(void); +void s2650_set_irq_line(INT32 irqline, INT32 state); +INT32 s2650_get_pc(); + +#define S2650_READ 1 +#define S2650_WRITE 2 +#define S2650_FETCH 4 +#define S2650_ROM (S2650_READ | S2650_FETCH) +#define S2650_RAM (S2650_ROM | S2650_WRITE) + +void s2650MapMemory(UINT8 *src, INT32 start, INT32 end, INT32 type); + +void s2650SetWriteHandler(void (*write)(UINT16, UINT8)); +void s2650SetReadHandler(UINT8 (*read)(UINT16)); +void s2650SetOutHandler(void (*write)(UINT16, UINT8)); +void s2650SetInHandler(UINT8 (*read)(UINT16)); + +INT32 s2650Run(INT32 cycles); +#define s2650Reset() s2650_reset() +void s2650Open(INT32 num); +void s2650Close(); +void s2650Exit(); +void s2650Init(INT32 num); +INT32 s2650GetPc(); + +INT32 s2650GetActive(); + +INT32 s2650Scan(INT32 nAction,INT32 */*pnMin*/); + +/* fake control port M/~IO=0 D/~C=0 E/~NE=0 */ +#define S2650_CTRL_PORT 0x100 + +/* fake data port M/~IO=0 D/~C=1 E/~NE=0 */ +#define S2650_DATA_PORT 0x101 + +/* extended i/o ports M/~IO=0 D/~C=x E/~NE=1 */ +#define S2650_EXT_PORT 0xff + +/* Fake Sense Line */ +#define S2650_SENSE_PORT 0x102 diff --git a/src/cpu/sek.cpp b/src/cpu/sek.cpp new file mode 100644 index 00000000..a9e27970 --- /dev/null +++ b/src/cpu/sek.cpp @@ -0,0 +1,1889 @@ +// 680x0 (Sixty Eight K) Interface +#include "burnint.h" +#include "sekdebug.h" + +#ifdef EMU_M68K +INT32 nSekM68KContextSize[SEK_MAX]; +INT8* SekM68KContext[SEK_MAX]; +#endif + +INT32 nSekCount = -1; // Number of allocated 68000s +struct SekExt *SekExt[SEK_MAX] = { NULL, }, *pSekExt = NULL; + +INT32 nSekActive = -1; // The cpu which is currently being emulated +INT32 nSekCyclesTotal, nSekCyclesScanline, nSekCyclesSegment, nSekCyclesDone, nSekCyclesToDo; + +INT32 nSekCPUType[SEK_MAX], nSekCycles[SEK_MAX], nSekIRQPending[SEK_MAX]; + +#if defined (FBA_DEBUG) + +void (*SekDbgBreakpointHandlerRead)(UINT32, INT32); +void (*SekDbgBreakpointHandlerFetch)(UINT32, INT32); +void (*SekDbgBreakpointHandlerWrite)(UINT32, INT32); + +UINT32 (*SekDbgFetchByteDisassembler)(UINT32); +UINT32 (*SekDbgFetchWordDisassembler)(UINT32); +UINT32 (*SekDbgFetchLongDisassembler)(UINT32); + +static struct { UINT32 address; INT32 id; } BreakpointDataRead[9] = { { 0, 0 }, }; +static struct { UINT32 address; INT32 id; } BreakpointDataWrite[9] = { { 0, 0 }, }; +static struct { UINT32 address; INT32 id; } BreakpointFetch[9] = { { 0, 0 }, }; + +#endif + +#if defined (EMU_A68K) +static void UpdateA68KContext() +{ + if (M68000_regs.srh & 20) { // Supervisor mode + M68000_regs.isp = M68000_regs.a[7]; + } else { // User mode + M68000_regs.usp = M68000_regs.a[7]; + } + + M68000_regs.sr = (M68000_regs.srh << 8) & 0xFF00; // T, S, M, I + M68000_regs.sr |= (M68000_regs.xc << 4) & 0x0010; // X + M68000_regs.sr |= (M68000_regs.ccr >> 4) & 0x0008; // N + M68000_regs.sr |= (M68000_regs.ccr >> 4) & 0x0004; // Z + M68000_regs.sr |= (M68000_regs.ccr >> 10) & 0x0002; // V + M68000_regs.sr |= (M68000_regs.ccr ) & 0x0001; // C +} + +static UINT32 GetA68KSR() +{ + UpdateA68KContext(); + + return M68000_regs.sr; +} + +static UINT32 GetA68KISP() +{ + UpdateA68KContext(); + + return M68000_regs.isp; +} + +static UINT32 GetA68KUSP() +{ + UpdateA68KContext(); + + return M68000_regs.usp; +} +#endif + +#if defined (FBA_DEBUG) + +inline static void CheckBreakpoint_R(UINT32 a, const UINT32 m) +{ + a &= m; + + for (INT32 i = 0; BreakpointDataRead[i].address; i++) { + if ((BreakpointDataRead[i].address & m) == a) { + +#ifdef EMU_A68K + UpdateA68KContext(); +#endif + + SekDbgBreakpointHandlerRead(a, BreakpointDataRead[i].id); + return; + } + } +} + +inline static void CheckBreakpoint_W(UINT32 a, const UINT32 m) +{ + a &= m; + + for (INT32 i = 0; BreakpointDataWrite[i].address; i++) { + if ((BreakpointDataWrite[i].address & m) == a) { + +#ifdef EMU_A68K + UpdateA68KContext(); +#endif + + SekDbgBreakpointHandlerWrite(a, BreakpointDataWrite[i].id); + return; + } + } +} + +inline static void CheckBreakpoint_PC() +{ + for (INT32 i = 0; BreakpointFetch[i].address; i++) { + if (BreakpointFetch[i].address == (UINT32)SekGetPC(-1)) { + +#ifdef EMU_A68K + UpdateA68KContext(); +#endif + + SekDbgBreakpointHandlerFetch(SekGetPC(-1), BreakpointFetch[i].id); + return; + } + } +} + +inline static void SingleStep_PC() +{ +#ifdef EMU_A68K + UpdateA68KContext(); +#endif + + SekDbgBreakpointHandlerFetch(SekGetPC(-1), 0); +} + +#endif + +// ---------------------------------------------------------------------------- +// Default memory access handlers + +UINT8 __fastcall DefReadByte(UINT32) { return 0; } +void __fastcall DefWriteByte(UINT32, UINT8) { } + +#define DEFWORDHANDLERS(i) \ + UINT16 __fastcall DefReadWord##i(UINT32 a) { SEK_DEF_READ_WORD(i, a) } \ + void __fastcall DefWriteWord##i(UINT32 a, UINT16 d) { SEK_DEF_WRITE_WORD(i, a ,d) } +#define DEFLONGHANDLERS(i) \ + UINT32 __fastcall DefReadLong##i(UINT32 a) { SEK_DEF_READ_LONG(i, a) } \ + void __fastcall DefWriteLong##i(UINT32 a, UINT32 d) { SEK_DEF_WRITE_LONG(i, a , d) } + +DEFWORDHANDLERS(0) +DEFLONGHANDLERS(0) + +#if SEK_MAXHANDLER >= 2 + DEFWORDHANDLERS(1) + DEFLONGHANDLERS(1) +#endif + +#if SEK_MAXHANDLER >= 3 + DEFWORDHANDLERS(2) + DEFLONGHANDLERS(2) +#endif + +#if SEK_MAXHANDLER >= 4 + DEFWORDHANDLERS(3) + DEFLONGHANDLERS(3) +#endif + +#if SEK_MAXHANDLER >= 5 + DEFWORDHANDLERS(4) + DEFLONGHANDLERS(4) +#endif + +#if SEK_MAXHANDLER >= 6 + DEFWORDHANDLERS(5) + DEFLONGHANDLERS(5) +#endif + +#if SEK_MAXHANDLER >= 7 + DEFWORDHANDLERS(6) + DEFLONGHANDLERS(6) +#endif + +#if SEK_MAXHANDLER >= 8 + DEFWORDHANDLERS(7) + DEFLONGHANDLERS(7) +#endif + +#if SEK_MAXHANDLER >= 9 + DEFWORDHANDLERS(8) + DEFLONGHANDLERS(8) +#endif + +#if SEK_MAXHANDLER >= 10 + DEFWORDHANDLERS(9) + DEFLONGHANDLERS(9) +#endif + +// ---------------------------------------------------------------------------- +// Memory access functions + +// Mapped Memory lookup ( for read) +#define FIND_R(x) pSekExt->MemMap[ x >> SEK_SHIFT] +// Mapped Memory lookup (+ SEK_WADD for write) +#define FIND_W(x) pSekExt->MemMap[(x >> SEK_SHIFT) + SEK_WADD] +// Mapped Memory lookup (+ SEK_WADD * 2 for fetch) +#define FIND_F(x) pSekExt->MemMap[(x >> SEK_SHIFT) + SEK_WADD * 2] + +// Normal memory access functions +inline static UINT8 ReadByte(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("read8 0x%08X\n"), a); + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + return pr[a & SEK_PAGEM]; + } + return pSekExt->ReadByte[(uintptr_t)pr](a); +} + +inline static UINT8 FetchByte(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("fetch8 0x%08X\n"), a); + + pr = FIND_F(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + return pr[a & SEK_PAGEM]; + } + return pSekExt->ReadByte[(uintptr_t)pr](a); +} + +inline static void WriteByte(UINT32 a, UINT8 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("write8 0x%08X\n"), a); + + pr = FIND_W(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + pr[a & SEK_PAGEM] = (UINT8)d; + return; + } + pSekExt->WriteByte[(uintptr_t)pr](a, d); +} + +inline static void WriteByteROM(UINT32 a, UINT8 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + pr[a & SEK_PAGEM] = (UINT8)d; + return; + } + pSekExt->WriteByte[(uintptr_t)pr](a, d); +} + +inline static UINT16 ReadWord(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("read16 0x%08X\n"), a); + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + return *((UINT16*)(pr + (a & SEK_PAGEM))); + } + return pSekExt->ReadWord[(uintptr_t)pr](a); +} + +inline static UINT16 FetchWord(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("fetch16 0x%08X\n"), a); + + pr = FIND_F(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + return *((UINT16*)(pr + (a & SEK_PAGEM))); + } + return pSekExt->ReadWord[(uintptr_t)pr](a); +} + +inline static void WriteWord(UINT32 a, UINT16 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("write16 0x%08X\n"), a); + + pr = FIND_W(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + *((UINT16*)(pr + (a & SEK_PAGEM))) = (UINT16)d; + return; + } + pSekExt->WriteWord[(uintptr_t)pr](a, d); +} + +inline static void WriteWordROM(UINT32 a, UINT16 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + *((UINT16*)(pr + (a & SEK_PAGEM))) = (UINT16)d; + return; + } + pSekExt->WriteWord[(uintptr_t)pr](a, d); +} + +inline static UINT32 ReadLong(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("read32 0x%08X\n"), a); + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + UINT32 r = *((UINT32*)(pr + (a & SEK_PAGEM))); + r = (r >> 16) | (r << 16); + return r; + } + return pSekExt->ReadLong[(uintptr_t)pr](a); +} + +inline static UINT32 FetchLong(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("fetch32 0x%08X\n"), a); + + pr = FIND_F(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + UINT32 r = *((UINT32*)(pr + (a & SEK_PAGEM))); + r = (r >> 16) | (r << 16); + return r; + } + return pSekExt->ReadLong[(uintptr_t)pr](a); +} + +inline static void WriteLong(UINT32 a, UINT32 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + +// bprintf(PRINT_NORMAL, _T("write32 0x%08X\n"), a); + + pr = FIND_W(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + d = (d >> 16) | (d << 16); + *((UINT32*)(pr + (a & SEK_PAGEM))) = d; + return; + } + pSekExt->WriteLong[(uintptr_t)pr](a, d); +} + +inline static void WriteLongROM(UINT32 a, UINT32 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + d = (d >> 16) | (d << 16); + *((UINT32*)(pr + (a & SEK_PAGEM))) = d; + return; + } + pSekExt->WriteLong[(uintptr_t)pr](a, d); +} + +#if defined (FBA_DEBUG) + +// Breakpoint checking memory access functions +UINT8 __fastcall ReadByteBP(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + + CheckBreakpoint_R(a, ~0); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + return pr[a & SEK_PAGEM]; + } + return pSekExt->ReadByte[(uintptr_t)pr](a); +} + +void __fastcall WriteByteBP(UINT32 a, UINT8 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_W(a); + + CheckBreakpoint_W(a, ~0); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + a ^= 1; + pr[a & SEK_PAGEM] = (UINT8)d; + return; + } + pSekExt->WriteByte[(uintptr_t)pr](a, d); +} + +UINT16 __fastcall ReadWordBP(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + + CheckBreakpoint_R(a, ~1); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + return *((UINT16*)(pr + (a & SEK_PAGEM))); + } + return pSekExt->ReadWord[(uintptr_t)pr](a); +} + +void __fastcall WriteWordBP(UINT32 a, UINT16 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_W(a); + + CheckBreakpoint_W(a, ~1); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + *((UINT16*)(pr + (a & SEK_PAGEM))) = (UINT16)d; + return; + } + pSekExt->WriteWord[(uintptr_t)pr](a, d); +} + +UINT32 __fastcall ReadLongBP(UINT32 a) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_R(a); + + CheckBreakpoint_R(a, ~1); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + UINT32 r = *((UINT32*)(pr + (a & SEK_PAGEM))); + r = (r >> 16) | (r << 16); + return r; + } + return pSekExt->ReadLong[(uintptr_t)pr](a); +} + +void __fastcall WriteLongBP(UINT32 a, UINT32 d) +{ + UINT8* pr; + + a &= 0xFFFFFF; + + pr = FIND_W(a); + + CheckBreakpoint_W(a, ~1); + + if ((uintptr_t)pr >= SEK_MAXHANDLER) { + d = (d >> 16) | (d << 16); + *((UINT32*)(pr + (a & SEK_PAGEM))) = d; + return; + } + pSekExt->WriteLong[(uintptr_t)pr](a, d); +} + +#endif + +// ---------------------------------------------------------------------------- +// A68K variables + +#ifdef EMU_A68K +struct A68KContext* SekRegs[SEK_MAX] = { NULL, }; +#endif + +struct A68KInter { + void (__fastcall *DebugCallback) (); + UINT8 (__fastcall *Read8) (UINT32 a); + UINT16 (__fastcall *Read16)(UINT32 a); + UINT32 (__fastcall *Read32)(UINT32 a); + void (__fastcall *Write8) (UINT32 a, UINT8 d); + void (__fastcall *Write16) (UINT32 a, UINT16 d); + void (__fastcall *Write32) (UINT32 a, UINT32 d); + void (__fastcall *ChangePc)(UINT32 a); + UINT8 (__fastcall *PcRel8) (UINT32 a); + UINT16 (__fastcall *PcRel16)(UINT32 a); + UINT32 (__fastcall *PcRel32)(UINT32 a); + UINT16 (__fastcall *Dir16)(UINT32 a); + UINT32 (__fastcall *Dir32)(UINT32 a); +}; + +extern "C" { + +#ifdef EMU_A68K + UINT8* OP_ROM = NULL; + UINT8* OP_RAM = NULL; + +#ifndef EMU_M68K + INT32 m68k_ICount = 0; +#endif + + UINT32 mem_amask = 0xFFFFFF; // 24-bit bus +#endif + + UINT32 mame_debug = 0, cur_mrhard = 0, m68k_illegal_opcode = 0, illegal_op = 0, illegal_pc = 0, opcode_entry = 0; + + struct A68KInter a68k_memory_intf; +} + +UINT8 __fastcall A68KRead8 (UINT32 a) { return ReadByte(a);} +UINT16 __fastcall A68KRead16(UINT32 a) { return ReadWord(a);} +UINT32 __fastcall A68KRead32(UINT32 a) { return ReadLong(a);} +UINT8 __fastcall A68KFetch8 (UINT32 a) { return FetchByte(a);} +UINT16 __fastcall A68KFetch16(UINT32 a) { return FetchWord(a);} +UINT32 __fastcall A68KFetch32(UINT32 a) { return FetchLong(a);} +void __fastcall A68KWrite8 (UINT32 a,UINT8 d) { WriteByte(a,d);} +void __fastcall A68KWrite16(UINT32 a,UINT16 d) { WriteWord(a,d);} +void __fastcall A68KWrite32(UINT32 a,UINT32 d) { WriteLong(a,d);} + +#if defined (FBA_DEBUG) +void __fastcall A68KCheckBreakpoint() { CheckBreakpoint_PC(); } +void __fastcall A68KSingleStep() { SingleStep_PC(); } +#endif + +#ifdef EMU_A68K +void __fastcall A68KChangePC(UINT32 pc) +{ + pc &= 0xFFFFFF; + + // Adjust OP_ROM to the current bank + OP_ROM = FIND_F(pc) - (pc & ~SEK_PAGEM); + + // Set the current bank number + M68000_regs.nAsmBank = pc >> SEK_BITS; +} +#endif + +#ifdef EMU_M68K +extern "C" { +UINT32 __fastcall M68KReadByte(UINT32 a) { return (UINT32)ReadByte(a); } +UINT32 __fastcall M68KReadWord(UINT32 a) { return (UINT32)ReadWord(a); } +UINT32 __fastcall M68KReadLong(UINT32 a) { return ReadLong(a); } + +UINT32 __fastcall M68KFetchByte(UINT32 a) { return (UINT32)FetchByte(a); } +UINT32 __fastcall M68KFetchWord(UINT32 a) { return (UINT32)FetchWord(a); } +UINT32 __fastcall M68KFetchLong(UINT32 a) { return FetchLong(a); } + +#ifdef FBA_DEBUG +UINT32 __fastcall M68KReadByteBP(UINT32 a) { return (UINT32)ReadByteBP(a); } +UINT32 __fastcall M68KReadWordBP(UINT32 a) { return (UINT32)ReadWordBP(a); } +UINT32 __fastcall M68KReadLongBP(UINT32 a) { return ReadLongBP(a); } + +void __fastcall M68KWriteByteBP(UINT32 a, UINT32 d) { WriteByteBP(a, d); } +void __fastcall M68KWriteWordBP(UINT32 a, UINT32 d) { WriteWordBP(a, d); } +void __fastcall M68KWriteLongBP(UINT32 a, UINT32 d) { WriteLongBP(a, d); } + +void M68KCheckBreakpoint() { CheckBreakpoint_PC(); } +void M68KSingleStep() { SingleStep_PC(); } + +UINT32 (__fastcall *M68KReadByteDebug)(UINT32); +UINT32 (__fastcall *M68KReadWordDebug)(UINT32); +UINT32 (__fastcall *M68KReadLongDebug)(UINT32); + +void (__fastcall *M68KWriteByteDebug)(UINT32, UINT32); +void (__fastcall *M68KWriteWordDebug)(UINT32, UINT32); +void (__fastcall *M68KWriteLongDebug)(UINT32, UINT32); +#endif + +void __fastcall M68KWriteByte(UINT32 a, UINT32 d) { WriteByte(a, d); } +void __fastcall M68KWriteWord(UINT32 a, UINT32 d) { WriteWord(a, d); } +void __fastcall M68KWriteLong(UINT32 a, UINT32 d) { WriteLong(a, d); } +} +#endif + +#if defined EMU_A68K +struct A68KInter a68k_inter_normal = { + NULL, + A68KRead8, + A68KRead16, + A68KRead32, + A68KWrite8, + A68KWrite16, + A68KWrite32, + A68KChangePC, + A68KFetch8, + A68KFetch16, + A68KFetch32, + A68KRead16, // unused + A68KRead32, // unused +}; + +#if defined (FBA_DEBUG) + +struct A68KInter a68k_inter_breakpoint = { + NULL, + ReadByteBP, + ReadWordBP, + ReadLongBP, + WriteByteBP, + WriteWordBP, + WriteLongBP, + A68KChangePC, + A68KFetch8, + A68KFetch16, + A68KFetch32, + A68KRead16, // unused + A68KRead32, // unused +}; + +#endif + +#endif + +// ---------------------------------------------------------------------------- +// Memory accesses (non-emu specific) + +UINT32 SekReadByte(UINT32 a) { return (UINT32)ReadByte(a); } +UINT32 SekReadWord(UINT32 a) { return (UINT32)ReadWord(a); } +UINT32 SekReadLong(UINT32 a) { return ReadLong(a); } + +UINT32 SekFetchByte(UINT32 a) { return (UINT32)FetchByte(a); } +UINT32 SekFetchWord(UINT32 a) { return (UINT32)FetchWord(a); } +UINT32 SekFetchLong(UINT32 a) { return FetchLong(a); } + +void SekWriteByte(UINT32 a, UINT8 d) { WriteByte(a, d); } +void SekWriteWord(UINT32 a, UINT16 d) { WriteWord(a, d); } +void SekWriteLong(UINT32 a, UINT32 d) { WriteLong(a, d); } + +void SekWriteByteROM(UINT32 a, UINT8 d) { WriteByteROM(a, d); } +void SekWriteWordROM(UINT32 a, UINT16 d) { WriteWordROM(a, d); } +void SekWriteLongROM(UINT32 a, UINT32 d) { WriteLongROM(a, d); } + +// ---------------------------------------------------------------------------- +// Callbacks for A68K + +#ifdef EMU_A68K +static INT32 A68KIRQAcknowledge(INT32 nIRQ) +{ + if (nSekIRQPending[nSekActive] & SEK_IRQSTATUS_AUTO) { + M68000_regs.irq &= 0x78; + nSekIRQPending[nSekActive] = 0; + } + + nSekIRQPending[nSekActive] = 0; + + if (pSekExt->IrqCallback) { + return pSekExt->IrqCallback(nIRQ); + } + + return -1; +} + +static INT32 A68KResetCallback() +{ + if (pSekExt->ResetCallback == NULL) { + return 0; + } + return pSekExt->ResetCallback(); +} + +static INT32 A68KRTECallback() +{ + if (pSekExt->RTECallback == NULL) { + return 0; + } + return pSekExt->RTECallback(); +} + +static INT32 A68KCmpCallback(UINT32 val, INT32 reg) +{ + if (pSekExt->CmpCallback == NULL) { + return 0; + } + return pSekExt->CmpCallback(val, reg); +} + +static INT32 SekSetup(struct A68KContext* psr) +{ + psr->IrqCallback = A68KIRQAcknowledge; + psr->ResetCallback = A68KResetCallback; + psr->RTECallback = A68KRTECallback; + psr->CmpCallback = A68KCmpCallback; + + return 0; +} +#endif + +// ---------------------------------------------------------------------------- +// Callbacks for Musashi + +#ifdef EMU_M68K +extern "C" INT32 M68KIRQAcknowledge(INT32 nIRQ) +{ + if (nSekIRQPending[nSekActive] & SEK_IRQSTATUS_AUTO) { + m68k_set_irq(0); + nSekIRQPending[nSekActive] = 0; + } + + if (pSekExt->IrqCallback) { + return pSekExt->IrqCallback(nIRQ); + } + + return M68K_INT_ACK_AUTOVECTOR; +} + +extern "C" void M68KResetCallback() +{ + if (pSekExt->ResetCallback) { + pSekExt->ResetCallback(); + } +} + +extern "C" void M68KRTECallback() +{ + if (pSekExt->RTECallback) { + pSekExt->RTECallback(); + } +} + +extern "C" void M68KcmpildCallback(UINT32 val, INT32 reg) +{ + if (pSekExt->CmpCallback) { + pSekExt->CmpCallback(val, reg); + } +} +#endif + +// ---------------------------------------------------------------------------- +// Initialisation/exit/reset + +#ifdef EMU_A68K +static INT32 SekInitCPUA68K(INT32 nCount, INT32 nCPUType) +{ + if (nCPUType != 0x68000) { + return 1; + } + + nSekCPUType[nCount] = 0; + + // Allocate emu-specific cpu states + SekRegs[nCount] = (struct A68KContext*)malloc(sizeof(struct A68KContext)); + if (SekRegs[nCount] == NULL) { + return 1; + } + + // Setup each cpu context + memset(SekRegs[nCount], 0, sizeof(struct A68KContext)); + SekSetup(SekRegs[nCount]); + + // Init cpu emulator + M68000_RESET(); + + return 0; +} +#endif + +#ifdef EMU_M68K +static INT32 SekInitCPUM68K(INT32 nCount, INT32 nCPUType) +{ + nSekCPUType[nCount] = nCPUType; + + switch (nCPUType) { + case 0x68000: + m68k_set_cpu_type(M68K_CPU_TYPE_68000); + break; + case 0x68010: + m68k_set_cpu_type(M68K_CPU_TYPE_68010); + break; + case 0x68EC020: + m68k_set_cpu_type(M68K_CPU_TYPE_68EC020); + break; + default: + return 1; + } + + nSekM68KContextSize[nCount] = m68k_context_size(); + SekM68KContext[nCount] = (INT8*)malloc(nSekM68KContextSize[nCount]); + if (SekM68KContext[nCount] == NULL) { + return 1; + } + memset(SekM68KContext[nCount], 0, nSekM68KContextSize[nCount]); + m68k_get_context(SekM68KContext[nCount]); + + return 0; +} +#endif + +void SekNewFrame() +{ + for (INT32 i = 0; i <= nSekCount; i++) { + nSekCycles[i] = 0; + } + + nSekCyclesTotal = 0; +} + +void SekSetCyclesScanline(INT32 nCycles) +{ + nSekCyclesScanline = nCycles; +} + +INT32 SekInit(INT32 nCount, INT32 nCPUType) +{ + struct SekExt* ps = NULL; + +#if !defined BUILD_A68K + bBurnUseASMCPUEmulation = false; +#endif + + if (nSekActive >= 0) { + SekClose(); + nSekActive = -1; + } + + if (nCount > nSekCount) { + nSekCount = nCount; + } + + // Allocate cpu extenal data (memory map etc) + SekExt[nCount] = (struct SekExt*)malloc(sizeof(struct SekExt)); + if (SekExt[nCount] == NULL) { + SekExit(); + return 1; + } + memset(SekExt[nCount], 0, sizeof(struct SekExt)); + + // Put in default memory handlers + ps = SekExt[nCount]; + + for (INT32 j = 0; j < SEK_MAXHANDLER; j++) { + ps->ReadByte[j] = DefReadByte; + ps->WriteByte[j] = DefWriteByte; + } + + ps->ReadWord[0] = DefReadWord0; + ps->WriteWord[0] = DefWriteWord0; + ps->ReadLong[0] = DefReadLong0; + ps->WriteLong[0] = DefWriteLong0; + +#if SEK_MAXHANDLER >= 2 + ps->ReadWord[1] = DefReadWord1; + ps->WriteWord[1] = DefWriteWord1; + ps->ReadLong[1] = DefReadLong1; + ps->WriteLong[1] = DefWriteLong1; +#endif + +#if SEK_MAXHANDLER >= 3 + ps->ReadWord[2] = DefReadWord2; + ps->WriteWord[2] = DefWriteWord2; + ps->ReadLong[2] = DefReadLong2; + ps->WriteLong[2] = DefWriteLong2; +#endif + +#if SEK_MAXHANDLER >= 4 + ps->ReadWord[3] = DefReadWord3; + ps->WriteWord[3] = DefWriteWord3; + ps->ReadLong[3] = DefReadLong3; + ps->WriteLong[3] = DefWriteLong3; +#endif + +#if SEK_MAXHANDLER >= 5 + ps->ReadWord[4] = DefReadWord4; + ps->WriteWord[4] = DefWriteWord4; + ps->ReadLong[4] = DefReadLong4; + ps->WriteLong[4] = DefWriteLong4; +#endif + +#if SEK_MAXHANDLER >= 6 + ps->ReadWord[5] = DefReadWord5; + ps->WriteWord[5] = DefWriteWord5; + ps->ReadLong[5] = DefReadLong5; + ps->WriteLong[5] = DefWriteLong5; +#endif + +#if SEK_MAXHANDLER >= 7 + ps->ReadWord[6] = DefReadWord6; + ps->WriteWord[6] = DefWriteWord6; + ps->ReadLong[6] = DefReadLong6; + ps->WriteLong[6] = DefWriteLong6; +#endif + +#if SEK_MAXHANDLER >= 8 + ps->ReadWord[7] = DefReadWord7; + ps->WriteWord[7] = DefWriteWord7; + ps->ReadLong[7] = DefReadLong7; + ps->WriteLong[7] = DefWriteLong7; +#endif + +#if SEK_MAXHANDLER >= 9 + ps->ReadWord[8] = DefReadWord8; + ps->WriteWord[8] = DefWriteWord8; + ps->ReadLong[8] = DefReadLong8; + ps->WriteLong[8] = DefWriteLong8; +#endif + +#if SEK_MAXHANDLER >= 10 + ps->ReadWord[9] = DefReadWord9; + ps->WriteWord[9] = DefWriteWord9; + ps->ReadLong[9] = DefReadLong9; + ps->WriteLong[9] = DefWriteLong9; +#endif + +#if SEK_MAXHANDLER >= 11 + for (int j = 10; j < SEK_MAXHANDLER; j++) { + ps->ReadWord[j] = DefReadWord0; + ps->WriteWord[j] = DefWriteWord0; + ps->ReadLong[j] = DefReadLong0; + ps->WriteLong[j] = DefWriteLong0; + } +#endif + + // Map the normal memory handlers + SekDbgDisableBreakpoints(); + +#ifdef EMU_A68K + if (bBurnUseASMCPUEmulation && nCPUType == 0x68000) { + if (SekInitCPUA68K(nCount, nCPUType)) { + SekExit(); + return 1; + } + } else { +#endif + +#ifdef EMU_M68K + m68k_init(); + if (SekInitCPUM68K(nCount, nCPUType)) { + SekExit(); + return 1; + } +#endif + +#ifdef EMU_A68K + } +#endif + + nSekCycles[nCount] = 0; + nSekIRQPending[nCount] = 0; + + nSekCyclesTotal = 0; + nSekCyclesScanline = 0; + + CpuCheatRegister(0x0000, nCount); + + return 0; +} + +#ifdef EMU_A68K +static void SekCPUExitA68K(INT32 i) +{ + if (SekRegs[i]) { + free(SekRegs[i]); + SekRegs[i] = NULL; + } +} +#endif + +#ifdef EMU_M68K +static void SekCPUExitM68K(INT32 i) +{ + if(SekM68KContext[i]) { + free(SekM68KContext[i]); + SekM68KContext[i] = NULL; + } +} +#endif + +INT32 SekExit() +{ + // Deallocate cpu extenal data (memory map etc) + for (INT32 i = 0; i <= nSekCount; i++) { + +#ifdef EMU_A68K + SekCPUExitA68K(i); +#endif + +#ifdef EMU_M68K + SekCPUExitM68K(i); +#endif + + // Deallocate other context data + if (SekExt[i]) { + free(SekExt[i]); + SekExt[i] = NULL; + } + } + + pSekExt = NULL; + + nSekActive = -1; + nSekCount = -1; + + return 0; +} + +void SekReset() +{ + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + // A68K has no internal support for resetting the processor, so do what's needed ourselves + M68000_regs.a[7] = FetchLong(0); // Get initial stackpointer (register A7) + M68000_regs.pc = FetchLong(4); // Get initial PC + M68000_regs.srh = 0x27; // start in supervisor state + A68KChangePC(M68000_regs.pc); + } else { +#endif + +#ifdef EMU_M68K + m68k_pulse_reset(); +#endif + +#ifdef EMU_A68K + } +#endif + +} + +// ---------------------------------------------------------------------------- +// Control the active CPU + +// Open a CPU +void SekOpen(const INT32 i) +{ + if (i != nSekActive) { + nSekActive = i; + + pSekExt = SekExt[nSekActive]; // Point to cpu context + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + memcpy(&M68000_regs, SekRegs[nSekActive], sizeof(M68000_regs)); + A68KChangePC(M68000_regs.pc); + } else { +#endif + +#ifdef EMU_M68K + m68k_set_context(SekM68KContext[nSekActive]); +#endif + +#ifdef EMU_A68K + } +#endif + + nSekCyclesTotal = nSekCycles[nSekActive]; + } +} + +// Close the active cpu +void SekClose() +{ + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + memcpy(SekRegs[nSekActive], &M68000_regs, sizeof(M68000_regs)); + } else { +#endif + +#ifdef EMU_M68K + m68k_get_context(SekM68KContext[nSekActive]); +#endif + +#ifdef EMU_A68K + } +#endif + + nSekCycles[nSekActive] = nSekCyclesTotal; +} + +// Get the current CPU +INT32 SekGetActive() +{ + return nSekActive; +} + +// Set the status of an IRQ line on the active CPU +void SekSetIRQLine(const INT32 line, const INT32 status) +{ +// bprintf(PRINT_NORMAL, _T(" - irq line %i -> %i\n"), line, status); + + if (status) { + nSekIRQPending[nSekActive] = line | status; + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + nSekCyclesTotal += (nSekCyclesToDo - nSekCyclesDone) - m68k_ICount; + nSekCyclesDone += (nSekCyclesToDo - nSekCyclesDone) - m68k_ICount; + + M68000_regs.irq = line; + m68k_ICount = nSekCyclesToDo = -1; // Force A68K to exit + } else { +#endif + +#ifdef EMU_M68K + m68k_set_irq(line); +#endif + +#ifdef EMU_A68K + } +#endif + + return; + } + + nSekIRQPending[nSekActive] = 0; + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + M68000_regs.irq &= 0x78; + } else { +#endif + +#ifdef EMU_M68K + m68k_set_irq(0); +#endif + +#ifdef EMU_A68K + } +#endif + +} + +// Adjust the active CPU's timeslice +void SekRunAdjust(const INT32 nCycles) +{ + if (nCycles < 0 && m68k_ICount < -nCycles) { + SekRunEnd(); + return; + } + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + m68k_ICount += nCycles; + nSekCyclesToDo += nCycles; + nSekCyclesSegment += nCycles; + } else { +#endif + +#ifdef EMU_M68K + nSekCyclesToDo += nCycles; + m68k_modify_timeslice(nCycles); +#endif + +#ifdef EMU_A68K + } +#endif + +} + +// End the active CPU's timeslice +void SekRunEnd() +{ + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + nSekCyclesTotal += (nSekCyclesToDo - nSekCyclesDone) - m68k_ICount; + nSekCyclesDone += (nSekCyclesToDo - nSekCyclesDone) - m68k_ICount; + nSekCyclesSegment = nSekCyclesDone; + m68k_ICount = nSekCyclesToDo = -1; // Force A68K to exit + } else { +#endif + +#ifdef EMU_M68K + m68k_end_timeslice(); +#endif + +#ifdef EMU_A68K + } +#endif + +} + +// Run the active CPU +INT32 SekRun(const INT32 nCycles) +{ + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + nSekCyclesDone = 0; + nSekCyclesSegment = nCycles; + do { + m68k_ICount = nSekCyclesToDo = nSekCyclesSegment - nSekCyclesDone; + + if (M68000_regs.irq == 0x80) { // Cpu is in stopped state till interrupt + nSekCyclesDone = nSekCyclesSegment; + nSekCyclesTotal += nSekCyclesSegment; + } else { + M68000_RUN(); + nSekCyclesDone += nSekCyclesToDo - m68k_ICount; + nSekCyclesTotal += nSekCyclesToDo - m68k_ICount; + } + } while (nSekCyclesDone < nSekCyclesSegment); + + nSekCyclesSegment = nSekCyclesDone; + nSekCyclesToDo = m68k_ICount = -1; + nSekCyclesDone = 0; + + return nSekCyclesSegment; // Return the number of cycles actually done + } else { +#endif + +#ifdef EMU_M68K + nSekCyclesToDo = nCycles; + + nSekCyclesSegment = m68k_execute(nCycles); + + nSekCyclesTotal += nSekCyclesSegment; + nSekCyclesToDo = m68k_ICount = -1; + + return nSekCyclesSegment; +#else + return 0; +#endif + +#ifdef EMU_A68K + } +#endif + +} + +// ---------------------------------------------------------------------------- +// Breakpoint support + +void SekDbgDisableBreakpoints() +{ +#if defined FBA_DEBUG && defined EMU_M68K + m68k_set_instr_hook_callback(NULL); + + M68KReadByteDebug = M68KReadByte; + M68KReadWordDebug = M68KReadWord; + M68KReadLongDebug = M68KReadLong; + + M68KWriteByteDebug = M68KWriteByte; + M68KWriteWordDebug = M68KWriteWord; + M68KWriteLongDebug = M68KWriteLong; +#endif + +#ifdef EMU_A68K + a68k_memory_intf = a68k_inter_normal; +#endif + + mame_debug = 0; +} + +#if defined (FBA_DEBUG) + +void SekDbgEnableBreakpoints() +{ + if (BreakpointDataRead[0].address || BreakpointDataWrite[0].address || BreakpointFetch[0].address) { +#if defined FBA_DEBUG && defined EMU_M68K + SekDbgDisableBreakpoints(); + + if (BreakpointFetch[0].address) { + m68k_set_instr_hook_callback(M68KCheckBreakpoint); + } + + if (BreakpointDataRead[0].address) { + M68KReadByteDebug = M68KReadByteBP; + M68KReadWordDebug = M68KReadWordBP; + M68KReadLongDebug = M68KReadLongBP; + } + + if (BreakpointDataWrite[0].address) { + M68KWriteByteDebug = M68KWriteByteBP; + M68KWriteWordDebug = M68KWriteWordBP; + M68KWriteLongDebug = M68KWriteLongBP; + } +#endif + +#ifdef EMU_A68K + a68k_memory_intf = a68k_inter_breakpoint; + if (BreakpointFetch[0].address) { + a68k_memory_intf.DebugCallback = A68KCheckBreakpoint; + mame_debug = 255; + } else { + a68k_memory_intf.DebugCallback = NULL; + mame_debug = 0; + } +#endif + } else { + SekDbgDisableBreakpoints(); + } +} + +void SekDbgEnableSingleStep() +{ +#if defined FBA_DEBUG && defined EMU_M68K + m68k_set_instr_hook_callback(M68KSingleStep); +#endif + +#ifdef EMU_A68K + a68k_memory_intf.DebugCallback = A68KSingleStep; + mame_debug = 254; +#endif +} + +INT32 SekDbgSetBreakpointDataRead(UINT32 nAddress, INT32 nIdentifier) +{ + for (INT32 i = 0; i < 8; i++) { + if (BreakpointDataRead[i].id == nIdentifier) { + + if (nAddress) { // Change breakpoint + BreakpointDataRead[i].address = nAddress; + } else { // Delete breakpoint + for ( ; i < 8; i++) { + BreakpointDataRead[i] = BreakpointDataRead[i + 1]; + } + } + + SekDbgEnableBreakpoints(); + return 0; + } + } + + // No breakpoints present, add it to the 1st slot + BreakpointDataRead[0].address = nAddress; + BreakpointDataRead[0].id = nIdentifier; + + SekDbgEnableBreakpoints(); + return 0; +} + +INT32 SekDbgSetBreakpointDataWrite(UINT32 nAddress, INT32 nIdentifier) +{ + for (INT32 i = 0; i < 8; i++) { + if (BreakpointDataWrite[i].id == nIdentifier) { + + if (nAddress) { // Change breakpoint + BreakpointDataWrite[i].address = nAddress; + } else { // Delete breakpoint + for ( ; i < 8; i++) { + BreakpointDataWrite[i] = BreakpointDataWrite[i + 1]; + } + } + + SekDbgEnableBreakpoints(); + return 0; + } + } + + // No breakpoints present, add it to the 1st slot + BreakpointDataWrite[0].address = nAddress; + BreakpointDataWrite[0].id = nIdentifier; + + SekDbgEnableBreakpoints(); + return 0; +} + +INT32 SekDbgSetBreakpointFetch(UINT32 nAddress, INT32 nIdentifier) +{ + for (INT32 i = 0; i < 8; i++) { + if (BreakpointFetch[i].id == nIdentifier) { + + if (nAddress) { // Change breakpoint + BreakpointFetch[i].address = nAddress; + } else { // Delete breakpoint + for ( ; i < 8; i++) { + BreakpointFetch[i] = BreakpointFetch[i + 1]; + } + } + + SekDbgEnableBreakpoints(); + return 0; + } + } + + // No breakpoints present, add it to the 1st slot + BreakpointFetch[0].address = nAddress; + BreakpointFetch[0].id = nIdentifier; + + SekDbgEnableBreakpoints(); + return 0; +} + +#endif + +// ---------------------------------------------------------------------------- +// Memory map setup + +// Note - each page is 1 << SEK_BITS. +INT32 SekMapMemory(UINT8* pMemory, UINT32 nStart, UINT32 nEnd, INT32 nType) +{ + UINT8* Ptr = pMemory - nStart; + UINT8** pMemMap = pSekExt->MemMap + (nStart >> SEK_SHIFT); + + // Special case for ROM banks + if (nType == SM_ROM) { + for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) { + pMemMap[0] = Ptr + i; + pMemMap[SEK_WADD * 2] = Ptr + i; + } + + return 0; + } + + for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) { + + if (nType & SM_READ) { // Read + pMemMap[0] = Ptr + i; + } + if (nType & SM_WRITE) { // Write + pMemMap[SEK_WADD] = Ptr + i; + } + if (nType & SM_FETCH) { // Fetch + pMemMap[SEK_WADD * 2] = Ptr + i; + } + } + + return 0; +} + +INT32 SekMapHandler(uintptr_t nHandler, UINT32 nStart, UINT32 nEnd, INT32 nType) +{ + UINT8** pMemMap = pSekExt->MemMap + (nStart >> SEK_SHIFT); + + // Add to memory map + for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) { + + if (nType & SM_READ) { // Read + pMemMap[0] = (UINT8*)nHandler; + } + if (nType & SM_WRITE) { // Write + pMemMap[SEK_WADD] = (UINT8*)nHandler; + } + if (nType & SM_FETCH) { // Fetch + pMemMap[SEK_WADD * 2] = (UINT8*)nHandler; + } + } + + return 0; +} + +// Set callbacks +INT32 SekSetResetCallback(pSekResetCallback pCallback) +{ + pSekExt->ResetCallback = pCallback; + + return 0; +} + +INT32 SekSetRTECallback(pSekRTECallback pCallback) +{ + pSekExt->RTECallback = pCallback; + + return 0; +} + +INT32 SekSetIrqCallback(pSekIrqCallback pCallback) +{ + pSekExt->IrqCallback = pCallback; + + return 0; +} + +INT32 SekSetCmpCallback(pSekCmpCallback pCallback) +{ + pSekExt->CmpCallback = pCallback; + + return 0; +} + +// Set handlers +INT32 SekSetReadByteHandler(INT32 i, pSekReadByteHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->ReadByte[i] = pHandler; + + return 0; +} + +INT32 SekSetWriteByteHandler(INT32 i, pSekWriteByteHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->WriteByte[i] = pHandler; + + return 0; +} + +INT32 SekSetReadWordHandler(INT32 i, pSekReadWordHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->ReadWord[i] = pHandler; + + return 0; +} + +INT32 SekSetWriteWordHandler(INT32 i, pSekWriteWordHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->WriteWord[i] = pHandler; + + return 0; +} + +INT32 SekSetReadLongHandler(INT32 i, pSekReadLongHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->ReadLong[i] = pHandler; + + return 0; +} + +INT32 SekSetWriteLongHandler(INT32 i, pSekWriteLongHandler pHandler) +{ + if (i >= SEK_MAXHANDLER) { + return 1; + } + + pSekExt->WriteLong[i] = pHandler; + + return 0; +} + +// ---------------------------------------------------------------------------- +// Query register values + +#ifdef EMU_A68K +INT32 SekGetPC(INT32 n) +#else +INT32 SekGetPC(INT32) +#endif +{ + +#ifdef EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + if (n < 0) { // Currently active CPU + return M68000_regs.pc; + } else { + return SekRegs[n]->pc; // Any CPU + } + } else { +#endif + +#ifdef EMU_M68K + return m68k_get_reg(NULL, M68K_REG_PC); +#else + return 0; +#endif + +#ifdef EMU_A68K + } +#endif + +} + +INT32 SekDbgGetCPUType() +{ + switch (nSekCPUType[nSekActive]) { + case 0: + case 0x68000: + return M68K_CPU_TYPE_68000; + case 0x68010: + return M68K_CPU_TYPE_68010; + case 0x68EC020: + return M68K_CPU_TYPE_68EC020; + } + + return 0; +} + +INT32 SekDbgGetPendingIRQ() +{ + return nSekIRQPending[nSekActive] & 7; +} + +UINT32 SekDbgGetRegister(SekRegister nRegister) +{ +#if defined EMU_A68K + if (nSekCPUType[nSekActive] == 0) { + switch (nRegister) { + case SEK_REG_D0: + return M68000_regs.d[0]; + case SEK_REG_D1: + return M68000_regs.d[1]; + case SEK_REG_D2: + return M68000_regs.d[2]; + case SEK_REG_D3: + return M68000_regs.d[3]; + case SEK_REG_D4: + return M68000_regs.d[4]; + case SEK_REG_D5: + return M68000_regs.d[5]; + case SEK_REG_D6: + return M68000_regs.d[6]; + case SEK_REG_D7: + return M68000_regs.d[7]; + + case SEK_REG_A0: + return M68000_regs.a[0]; + case SEK_REG_A1: + return M68000_regs.a[1]; + case SEK_REG_A2: + return M68000_regs.a[2]; + case SEK_REG_A3: + return M68000_regs.a[3]; + case SEK_REG_A4: + return M68000_regs.a[4]; + case SEK_REG_A5: + return M68000_regs.a[5]; + case SEK_REG_A6: + return M68000_regs.a[6]; + case SEK_REG_A7: + return M68000_regs.a[7]; + + case SEK_REG_PC: + return M68000_regs.pc; + + case SEK_REG_SR: + return GetA68KSR(); + + case SEK_REG_SP: + return M68000_regs.a[7]; + case SEK_REG_USP: + return GetA68KUSP(); + case SEK_REG_ISP: + return GetA68KISP(); + + default: + return 0; + } + } +#endif + + switch (nRegister) { + case SEK_REG_D0: + return m68k_get_reg(NULL, M68K_REG_D0); + case SEK_REG_D1: + return m68k_get_reg(NULL, M68K_REG_D1); + case SEK_REG_D2: + return m68k_get_reg(NULL, M68K_REG_D2); + case SEK_REG_D3: + return m68k_get_reg(NULL, M68K_REG_D3); + case SEK_REG_D4: + return m68k_get_reg(NULL, M68K_REG_D4); + case SEK_REG_D5: + return m68k_get_reg(NULL, M68K_REG_D5); + case SEK_REG_D6: + return m68k_get_reg(NULL, M68K_REG_D6); + case SEK_REG_D7: + return m68k_get_reg(NULL, M68K_REG_D7); + + case SEK_REG_A0: + return m68k_get_reg(NULL, M68K_REG_A0); + case SEK_REG_A1: + return m68k_get_reg(NULL, M68K_REG_A1); + case SEK_REG_A2: + return m68k_get_reg(NULL, M68K_REG_A2); + case SEK_REG_A3: + return m68k_get_reg(NULL, M68K_REG_A3); + case SEK_REG_A4: + return m68k_get_reg(NULL, M68K_REG_A4); + case SEK_REG_A5: + return m68k_get_reg(NULL, M68K_REG_A5); + case SEK_REG_A6: + return m68k_get_reg(NULL, M68K_REG_A6); + case SEK_REG_A7: + return m68k_get_reg(NULL, M68K_REG_A7); + + case SEK_REG_PC: + return m68k_get_reg(NULL, M68K_REG_PC); + + case SEK_REG_SR: + return m68k_get_reg(NULL, M68K_REG_SR); + + case SEK_REG_SP: + return m68k_get_reg(NULL, M68K_REG_SP); + case SEK_REG_USP: + return m68k_get_reg(NULL, M68K_REG_USP); + case SEK_REG_ISP: + return m68k_get_reg(NULL, M68K_REG_ISP); + case SEK_REG_MSP: + return m68k_get_reg(NULL, M68K_REG_MSP); + + case SEK_REG_VBR: + return m68k_get_reg(NULL, M68K_REG_VBR); + + case SEK_REG_SFC: + return m68k_get_reg(NULL, M68K_REG_SFC); + case SEK_REG_DFC: + return m68k_get_reg(NULL, M68K_REG_DFC); + + case SEK_REG_CACR: + return m68k_get_reg(NULL, M68K_REG_CACR); + case SEK_REG_CAAR: + return m68k_get_reg(NULL, M68K_REG_CAAR); + + default: + return 0; + } +} + +bool SekDbgSetRegister(SekRegister nRegister, UINT32 nValue) +{ + switch (nRegister) { + case SEK_REG_D0: + case SEK_REG_D1: + case SEK_REG_D2: + case SEK_REG_D3: + case SEK_REG_D4: + case SEK_REG_D5: + case SEK_REG_D6: + case SEK_REG_D7: + break; + + case SEK_REG_A0: + case SEK_REG_A1: + case SEK_REG_A2: + case SEK_REG_A3: + case SEK_REG_A4: + case SEK_REG_A5: + case SEK_REG_A6: + case SEK_REG_A7: + break; + + case SEK_REG_PC: + if (nSekCPUType[nSekActive] == 0) { +#if defined EMU_A68K + M68000_regs.pc = nValue; + A68KChangePC(M68000_regs.pc); +#endif + } else { + m68k_set_reg(M68K_REG_PC, nValue); + } + SekClose(); + return true; + + case SEK_REG_SR: + break; + + case SEK_REG_SP: + case SEK_REG_USP: + case SEK_REG_ISP: + case SEK_REG_MSP: + break; + + case SEK_REG_VBR: + break; + + case SEK_REG_SFC: + case SEK_REG_DFC: + break; + + case SEK_REG_CACR: + case SEK_REG_CAAR: + break; + + default: + break; + } + + return false; +} + +// ---------------------------------------------------------------------------- +// Savestate support + +INT32 SekScan(INT32 nAction) +{ + // Scan the 68000 states + struct BurnArea ba; + + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + memset(&ba, 0, sizeof(ba)); + + nSekActive = -1; + + for (INT32 i = 0; i <= nSekCount; i++) { + char szName[] = "MC68000 #n"; +#if defined EMU_A68K && defined EMU_M68K + INT32 nType = nSekCPUType[i]; +#endif + + szName[9] = '0' + i; + + SCAN_VAR(nSekCPUType[i]); + +#if defined EMU_A68K && defined EMU_M68K + // Switch to another core if needed + if ((nAction & ACB_WRITE) && nType != nSekCPUType[i]) { + if (nType != 0 && nType != 0x68000 && nSekCPUType[i] != 0 && nSekCPUType[i] != 0x68000) { + continue; + } + + if (nSekCPUType[i] == 0x68000) { + SekCPUExitA68K(i); + if (SekInitCPUM68K(i, 0x68000)) { + return 1; + } + } else { + SekCPUExitM68K(i); + if (SekInitCPUA68K(i, 0x68000)) { + return 1; + } + } + } +#endif + +#ifdef EMU_A68K + if (nSekCPUType[i] == 0) { + ba.Data = SekRegs[i]; + ba.nLen = sizeof(A68KContext); + ba.szName = szName; + + if (nAction & ACB_READ) { + // Blank pointers + SekRegs[i]->IrqCallback = NULL; + SekRegs[i]->ResetCallback = NULL; + } + + BurnAcb(&ba); + + // Re-setup each cpu on read/write + if (nAction & ACB_ACCESSMASK) { + SekSetup(SekRegs[i]); + } + } else { +#endif + +#ifdef EMU_M68K + if (nSekCPUType[i] != 0) { + ba.Data = SekM68KContext[i]; + ba.nLen = nSekM68KContextSize[i]; + ba.szName = szName; + BurnAcb(&ba); + } +#endif + +#ifdef EMU_A68K + } +#endif + + } + + return 0; +} diff --git a/src/cpu/sek.h b/src/cpu/sek.h new file mode 100644 index 00000000..f5eab34a --- /dev/null +++ b/src/cpu/sek.h @@ -0,0 +1,205 @@ +// 68000 (Sixty Eight K) Interface - header file + +#ifndef FASTCALL + #undef __fastcall + #define __fastcall +#endif + +#if defined BUILD_A68K + #define EMU_A68K // Use A68K Assembler 68000 emulator +#endif + +#define EMU_M68K // Use Musashi 68000 emulator + +#define SEK_MAX (4) // Maximum number of CPUs supported + +#if defined EMU_M68K + #include "m68k.h" +#endif + +// Number of bits used for each page in the fast memory map +#define SEK_BITS (10) // 10 = 0x0400 page size +#define SEK_PAGE_COUNT (1 << (24 - SEK_BITS)) // Number of pages +#define SEK_SHIFT (SEK_BITS) // Shift value = page bits +#define SEK_PAGE_SIZE (1 << SEK_BITS) // Page size +#define SEK_PAGEM (SEK_PAGE_SIZE - 1) +#define SEK_WADD (SEK_PAGE_COUNT) // Value to add for write section = Number of pages +#define SEK_MASK (SEK_WADD - 1) +#define SEK_MAXHANDLER (10) // Max. number of handlers for memory access + +#if SEK_MAXHANDLER < 1 + #error At least one set of handlers for memory access must be used. +#endif + +#ifdef EMU_A68K + extern "C" void __cdecl M68000_RUN(); + extern "C" void __cdecl M68000_RESET(); +#endif + +#ifdef EMU_A68K + // The format of the data in a68k.asm (at the _M68000_regs location) + struct A68KContext { + UINT32 d[8], a[8]; + UINT32 isp, srh, ccr, xc, pc, irq, sr; + INT32 (*IrqCallback) (INT32 nIrq); + UINT32 ppc; + INT32 (*ResetCallback)(); + INT32 (*RTECallback)(); + INT32 (*CmpCallback)(UINT32 val, INT32 reg); + UINT32 sfc, dfc, usp, vbr; + UINT32 nAsmBank, nCpuVersion; + }; + extern "C" struct A68KContext M68000_regs; + extern struct A68KContext* SekRegs[SEK_MAX]; + + extern "C" UINT8* OP_ROM; + extern "C" UINT8* OP_RAM; + + void __fastcall AsekChangePc(UINT32 pc); +#endif + +#ifdef EMU_M68K + extern "C" INT32 nSekM68KContextSize[SEK_MAX]; + extern "C" INT8* SekM68KContext[SEK_MAX]; + extern "C" INT32 m68k_ICount; +#endif + +typedef UINT8 (__fastcall *pSekReadByteHandler)(UINT32 a); +typedef void (__fastcall *pSekWriteByteHandler)(UINT32 a, UINT8 d); +typedef UINT16 (__fastcall *pSekReadWordHandler)(UINT32 a); +typedef void (__fastcall *pSekWriteWordHandler)(UINT32 a, UINT16 d); +typedef UINT32 (__fastcall *pSekReadLongHandler)(UINT32 a); +typedef void (__fastcall *pSekWriteLongHandler)(UINT32 a, UINT32 d); + +typedef INT32 (__fastcall *pSekResetCallback)(); +typedef INT32 (__fastcall *pSekRTECallback)(); +typedef INT32 (__fastcall *pSekIrqCallback)(INT32 irq); +typedef INT32 (__fastcall *pSekCmpCallback)(UINT32 val, INT32 reg); + +extern INT32 nSekCycles[SEK_MAX], nSekCPUType[SEK_MAX]; + +// Mapped memory pointers to Rom and Ram areas (Read then Write) +// These memory areas must be allocated multiples of the page size +// with a 4 byte over-run area lookup for each page (*3 for read, write and fetch) +struct SekExt { + UINT8* MemMap[SEK_PAGE_COUNT * 3]; + + // If MemMap[i] < SEK_MAXHANDLER, use the handler functions + pSekReadByteHandler ReadByte[SEK_MAXHANDLER]; + pSekWriteByteHandler WriteByte[SEK_MAXHANDLER]; + pSekReadWordHandler ReadWord[SEK_MAXHANDLER]; + pSekWriteWordHandler WriteWord[SEK_MAXHANDLER]; + pSekReadLongHandler ReadLong[SEK_MAXHANDLER]; + pSekWriteLongHandler WriteLong[SEK_MAXHANDLER]; + + pSekResetCallback ResetCallback; + pSekRTECallback RTECallback; + pSekIrqCallback IrqCallback; + pSekCmpCallback CmpCallback; +}; + +#define SEK_DEF_READ_WORD(i, a) { UINT16 d; d = (UINT16)(pSekExt->ReadByte[i](a) << 8); d |= (UINT16)(pSekExt->ReadByte[i]((a) + 1)); return d; } +#define SEK_DEF_WRITE_WORD(i, a, d) { pSekExt->WriteByte[i]((a),(UINT8)((d) >> 8)); pSekExt->WriteByte[i]((a) + 1, (UINT8)((d) & 0xff)); } +#define SEK_DEF_READ_LONG(i, a) { UINT32 d; d = pSekExt->ReadWord[i](a) << 16; d |= pSekExt->ReadWord[i]((a) + 2); return d; } +#define SEK_DEF_WRITE_LONG(i, a, d) { pSekExt->WriteWord[i]((a),(UINT16)((d) >> 16)); pSekExt->WriteWord[i]((a) + 2,(UINT16)((d) & 0xffff)); } + +extern struct SekExt *SekExt[SEK_MAX], *pSekExt; +extern INT32 nSekActive; // The cpu which is currently being emulated +extern INT32 nSekCyclesTotal, nSekCyclesScanline, nSekCyclesSegment, nSekCyclesDone, nSekCyclesToDo; + +UINT32 SekReadByte(UINT32 a); +UINT32 SekReadWord(UINT32 a); +UINT32 SekReadLong(UINT32 a); + +UINT32 SekFetchByte(UINT32 a); +UINT32 SekFetchWord(UINT32 a); +UINT32 SekFetchLong(UINT32 a); + +void SekWriteByte(UINT32 a, UINT8 d); +void SekWriteWord(UINT32 a, UINT16 d); +void SekWriteLong(UINT32 a, UINT32 d); + +void SekWriteByteROM(UINT32 a, UINT8 d); +void SekWriteWordROM(UINT32 a, UINT16 d); +void SekWriteLongROM(UINT32 a, UINT32 d); + +INT32 SekInit(INT32 nCount, INT32 nCPUType); +INT32 SekExit(); + +void SekNewFrame(); +void SekSetCyclesScanline(INT32 nCycles); + +void SekClose(); +void SekOpen(const INT32 i); +INT32 SekGetActive(); + +#define SEK_IRQSTATUS_NONE (0x0000) +#define SEK_IRQSTATUS_AUTO (0x2000) +#define SEK_IRQSTATUS_ACK (0x1000) + +void SekSetIRQLine(const INT32 line, const INT32 status); +void SekReset(); + +void SekRunEnd(); +void SekRunAdjust(const INT32 nCycles); +INT32 SekRun(const INT32 nCycles); + +inline static INT32 SekIdle(INT32 nCycles) +{ + nSekCyclesTotal += nCycles; + + return nCycles; +} + +inline static INT32 SekSegmentCycles() +{ +#ifdef EMU_M68K + return nSekCyclesDone + nSekCyclesToDo - m68k_ICount; +#else + return nSekCyclesDone + nSekCyclesToDo; +#endif +} + +inline static INT32 SekTotalCycles() +{ +#ifdef EMU_M68K + return nSekCyclesTotal + nSekCyclesToDo - m68k_ICount; +#else + return nSekCyclesTotal + nSekCyclesToDo; +#endif +} + +inline static INT32 SekCurrentScanline() +{ + return SekTotalCycles() / nSekCyclesScanline; +} + +// SekMemory types: +#define SM_READ (1) +#define SM_WRITE (2) +#define SM_FETCH (4) +#define SM_ROM (SM_READ | SM_FETCH) +#define SM_RAM (SM_READ | SM_WRITE | SM_FETCH) + +// Map areas of memory +INT32 SekMapMemory(UINT8* pMemory, UINT32 nStart, UINT32 nEnd, INT32 nType); +INT32 SekMapHandler(uintptr_t nHandler, UINT32 nStart, UINT32 nEnd, INT32 nType); + +// Set handlers +INT32 SekSetReadByteHandler(INT32 i, pSekReadByteHandler pHandler); +INT32 SekSetWriteByteHandler(INT32 i, pSekWriteByteHandler pHandler); +INT32 SekSetReadWordHandler(INT32 i, pSekReadWordHandler pHandler); +INT32 SekSetWriteWordHandler(INT32 i, pSekWriteWordHandler pHandler); +INT32 SekSetReadLongHandler(INT32 i, pSekReadLongHandler pHandler); +INT32 SekSetWriteLongHandler(INT32 i, pSekWriteLongHandler pHandler); + +// Set callbacks +INT32 SekSetResetCallback(pSekResetCallback pCallback); +INT32 SekSetRTECallback(pSekRTECallback pCallback); +INT32 SekSetIrqCallback(pSekIrqCallback pCallback); +INT32 SekSetCmpCallback(pSekCmpCallback pCallback); + +// Get a CPU's PC +INT32 SekGetPC(INT32 n); + +INT32 SekScan(INT32 nAction); diff --git a/src/cpu/sekdebug.h b/src/cpu/sekdebug.h new file mode 100644 index 00000000..d726442c --- /dev/null +++ b/src/cpu/sekdebug.h @@ -0,0 +1,27 @@ +enum SekRegister { + SEK_REG_D0, SEK_REG_D1, SEK_REG_D2, SEK_REG_D3, SEK_REG_D4, SEK_REG_D5, SEK_REG_D6, SEK_REG_D7, + SEK_REG_A0, SEK_REG_A1, SEK_REG_A2, SEK_REG_A3, SEK_REG_A4, SEK_REG_A5, SEK_REG_A6, SEK_REG_A7, + SEK_REG_PC, + SEK_REG_SR, + SEK_REG_SP, SEK_REG_USP, SEK_REG_ISP, SEK_REG_MSP, + SEK_REG_VBR, + SEK_REG_SFC, SEK_REG_DFC, + SEK_REG_CACR, SEK_REG_CAAR +}; + +extern void (*SekDbgBreakpointHandlerRead)(UINT32, INT32); +extern void (*SekDbgBreakpointHandlerFetch)(UINT32, INT32); +extern void (*SekDbgBreakpointHandlerWrite)(UINT32, INT32); + +void SekDbgDisableBreakpoints(); +void SekDbgEnableBreakpoints(); +void SekDbgEnableSingleStep(); + +INT32 SekDbgSetBreakpointDataRead(UINT32 nAddress, INT32 nIdentifier); +INT32 SekDbgSetBreakpointDataWrite(UINT32 nAddress, INT32 nIdentifier); +INT32 SekDbgSetBreakpointFetch(UINT32 nAddress, INT32 nIdentifier); + +INT32 SekDbgGetCPUType(); +INT32 SekDbgGetPendingIRQ(); +UINT32 SekDbgGetRegister(SekRegister nRegister); +bool SekDbgSetRegister(SekRegister nRegister, UINT32 nValue); diff --git a/src/cpu/sh2/sh2.cpp b/src/cpu/sh2/sh2.cpp new file mode 100644 index 00000000..9bc1384f --- /dev/null +++ b/src/cpu/sh2/sh2.cpp @@ -0,0 +1,3367 @@ +/***************************************************************************** + * + * Portable Hitachi SH-2 (SH7600 family) emulator + * + * Copyright (c) 2000 Juergen Buchmueller , + * all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on C/C++ implementation of + * the SH-2 CPU core and was adapted to the MAME CPU core requirements. + * Thanks also go to Chuck Mason and Olivier Galibert + * for letting me peek into their SEMU code :-) + * + ***************************************************************************** + * + * Port to Finalburn Alpha by OopsWare + * http://oopsware.googlepages.com/ + * + *****************************************************************************/ + +//#include +//#include +//#include + +#include "burnint.h" +#include "sh2.h" + +//#include "tchar.h" +//extern int (__cdecl *bprintf) (int nStatus, TCHAR* szFormat, ...); + +int has_sh2; + +/*typedef signed char INT8; +typedef unsigned char UINT8; +typedef signed short INT16; +typedef unsigned short UINT16; +typedef signed int INT32; +typedef unsigned int UINT32; +typedef signed long long INT64; +typedef unsigned long long UINT64;*/ + +#define BUSY_LOOP_HACKS 1 +#define FAST_OP_FETCH 1 +#define USE_JUMPTABLE 0 + +#define SH2_INT_15 15 + +#define SH2_INLINE + +#if FAST_OP_FETCH + + #define change_pc(newpc) \ + sh2->pc = (newpc); \ + pSh2Ext->opbase = pSh2Ext->MemMap[ (sh2->pc >> SH2_SHIFT) + SH2_WADD * 2 ]; \ + pSh2Ext->opbase -= (sh2->pc & ~SH2_PAGEM); + +#else + + #define change_pc(newpc) sh2->pc = (newpc); + +#endif + +#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask)) + + + +typedef struct +{ + int irq_vector; + int irq_priority; +} irq_entry; + +typedef struct +{ + UINT32 ppc; + UINT32 pc; + UINT32 pr; + UINT32 sr; + UINT32 gbr, vbr; + UINT32 mach, macl; + UINT32 r[16]; + UINT32 ea; + UINT32 delay; + UINT32 cpu_off; + UINT32 dvsr, dvdnth, dvdntl, dvcr; + UINT32 pending_irq; + UINT32 test_irq; + irq_entry irq_queue[16]; + + INT8 irq_line_state[17]; + UINT32 m[0x200]; + INT8 nmi_line_state; + + UINT16 frc; + UINT16 ocra, ocrb, icr; + UINT32 frc_base; + + int frt_input; + int internal_irq_level; + int internal_irq_vector; + +// emu_timer *timer; + UINT32 timer_cycles; + UINT32 timer_base; + int timer_active; + +// emu_timer *dma_timer[2]; + UINT32 dma_timer_cycles[2]; + UINT32 dma_timer_base[2]; + int dma_timer_active[2]; + +// int is_slave, cpu_number; + + UINT32 cycle_counts; + UINT32 sh2_cycles_to_run; + INT32 sh2_icount; + int sh2_total_cycles; + + int (*irq_callback)(int irqline); + +} SH2; + +static SH2 * sh2; + +static UINT32 sh2_GetTotalCycles() +{ + return sh2->cycle_counts + sh2->sh2_cycles_to_run - sh2->sh2_icount; +} + +static const int div_tab[4] = { 3, 5, 3, 0 }; + +enum { + ICF = 0x00800000, + OCFA = 0x00080000, + OCFB = 0x00040000, + OVF = 0x00020000 +}; + +//static TIMER_CALLBACK( sh2_timer_callback ); + +#define T 0x00000001 +#define S 0x00000002 +#define I 0x000000f0 +#define Q 0x00000100 +#define M 0x00000200 + +#define AM 0xc7ffffff + +#define FLAGS (M|Q|I|S|T) + +#define Rn ((opcode>>8)&15) +#define Rm ((opcode>>4)&15) + +static UINT32 sh2_internal_r(UINT32 A, UINT32 mask); +static void sh2_internal_w(UINT32 offset, UINT32 data, UINT32 mem_mask); + +//-- sh2 memory handler for Finalburn Alpha --------------------- + +#define SH2_BITS (16) // 16 = 0x10000 page size +#define SH2_PAGE_COUNT (1 << (32 - SH2_BITS)) // Number of pages +#define SH2_SHIFT (SH2_BITS) // Shift value = page bits +#define SH2_PAGE_SIZE (1 << SH2_BITS) // Page size +#define SH2_PAGEM (SH2_PAGE_SIZE - 1) +#define SH2_WADD (SH2_PAGE_COUNT) // Value to add for write section = Number of pages +#define SH2_MASK (SH2_WADD - 1) + +#define SH2_MAXHANDLER (8) + + +typedef struct +{ + SH2 sh2; + unsigned char * MemMap[SH2_PAGE_COUNT * 3]; + pSh2ReadByteHandler ReadByte[SH2_MAXHANDLER]; + pSh2WriteByteHandler WriteByte[SH2_MAXHANDLER]; + pSh2ReadWordHandler ReadWord[SH2_MAXHANDLER]; + pSh2WriteWordHandler WriteWord[SH2_MAXHANDLER]; + pSh2ReadLongHandler ReadLong[SH2_MAXHANDLER]; + pSh2WriteLongHandler WriteLong[SH2_MAXHANDLER]; + + unsigned char * opbase; + int suspend; +} SH2EXT; + +static SH2EXT * pSh2Ext; +static SH2EXT * Sh2Ext = NULL; + +/* SH-2 Memory Map: + * 0x00000000 ~ 0x07ffffff : user + * 0x08000000 ~ 0x0fffffff : user ( mirror ) + * 0x10000000 ~ 0x17ffffff : user ( mirror ) + * 0x18000000 ~ 0x1fffffff : user ( mirror ) + * 0x20000000 ~ 0x27ffffff : user ( mirror ) + * 0x28000000 ~ 0x2fffffff : user ( mirror ) + * 0x30000000 ~ 0x37ffffff : user ( mirror ) + * 0x38000000 ~ 0x3fffffff : user ( mirror ) + * 0x40000000 ~ 0xbfffffff : fill with 0xa5 + * 0xc0000000 ~ 0xdfffffff : extend user + * 0xe0000000 ~ 0xffffffff : internal mem + */ + +int Sh2MapMemory(unsigned char* pMemory, unsigned int nStart, unsigned int nEnd, int nType) +{ + unsigned char* Ptr = pMemory - nStart; + unsigned char** pMemMap = pSh2Ext->MemMap + (nStart >> SH2_SHIFT); + int need_mirror = (nStart < 0x08000000) ? 1 : 0; + + for (unsigned long long i = (nStart & ~SH2_PAGEM); i <= nEnd; i += SH2_PAGE_SIZE, pMemMap++) { + if (nType & 0x01 /*SM_READ*/) pMemMap[0] = Ptr + i; + if (nType & 0x02 /*SM_WRITE*/) pMemMap[SH2_WADD] = Ptr + i; + if (nType & 0x04 /*SM_FETCH*/) pMemMap[SH2_WADD*2] = Ptr + i; + + if ( need_mirror ) { + if (nType & 0x01 /*SM_READ*/) { + pMemMap[0 + (0x08000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x10000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x18000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x20000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x28000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x30000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[0 + (0x38000000 >> SH2_SHIFT)] = Ptr + i; + } + if (nType & 0x02 /*SM_WRITE*/) { + pMemMap[SH2_WADD + (0x08000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x10000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x18000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x20000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x28000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x30000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD + (0x38000000 >> SH2_SHIFT)] = Ptr + i; + } + if (nType & 0x04 /*SM_FETCH*/) { + pMemMap[SH2_WADD*2 + (0x08000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x10000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x18000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x20000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x28000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x30000000 >> SH2_SHIFT)] = Ptr + i; + pMemMap[SH2_WADD*2 + (0x38000000 >> SH2_SHIFT)] = Ptr + i; + } + } + } + return 0; +} + +int Sh2MapHandler(uintptr_t nHandler, unsigned int nStart, unsigned int nEnd, int nType) +{ + unsigned char** pMemMap = pSh2Ext->MemMap + (nStart >> SH2_SHIFT); + int need_mirror = (nStart < 0x08000000) ? 1 : 0; + + for (unsigned long long i = (nStart & ~SH2_PAGEM); i <= nEnd; i += SH2_PAGE_SIZE, pMemMap++) { + if (nType & 0x01 /*SM_READ*/) pMemMap[0] = (unsigned char*)nHandler; + if (nType & 0x02 /*SM_WRITE*/) pMemMap[SH2_WADD] = (unsigned char*)nHandler; + if (nType & 0x04 /*SM_FETCH*/) pMemMap[SH2_WADD*2] = (unsigned char*)nHandler; + + if ( need_mirror ) { + if (nType & 0x01 /*SM_READ*/) { + pMemMap[0 + (0x08000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x10000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x18000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x20000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x28000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x30000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[0 + (0x38000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + } + if (nType & 0x02 /*SM_WRITE*/) { + pMemMap[SH2_WADD + (0x08000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x10000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x18000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x20000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x28000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x30000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD + (0x38000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + } + if (nType & 0x04 /*SM_FETCH*/) { + pMemMap[SH2_WADD*2 + (0x08000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x10000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x18000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x20000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x28000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x30000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + pMemMap[SH2_WADD*2 + (0x38000000 >> SH2_SHIFT)] = (unsigned char*)nHandler; + } + } + + } + return 0; +} + +int Sh2SetReadByteHandler(int i, pSh2ReadByteHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->ReadByte[i] = pHandler; + return 0; +} + +int Sh2SetWriteByteHandler(int i, pSh2WriteByteHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->WriteByte[i] = pHandler; + return 0; +} + +int Sh2SetReadWordHandler(int i, pSh2ReadWordHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->ReadWord[i] = pHandler; + return 0; +} + +int Sh2SetWriteWordHandler(int i, pSh2WriteWordHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->WriteWord[i] = pHandler; + return 0; +} + +int Sh2SetReadLongHandler(int i, pSh2ReadLongHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->ReadLong[i] = pHandler; + return 0; +} + +int Sh2SetWriteLongHandler(int i, pSh2WriteLongHandler pHandler) +{ + if (i >= SH2_MAXHANDLER) return 1; + pSh2Ext->WriteLong[i] = pHandler; + return 0; +} + +unsigned char __fastcall Sh2InnerReadByte(unsigned int a) +{ + return sh2_internal_r((a & 0x1fc)>>2, ~(0xff << (((~a) & 3)*8))) >> (((~a) & 3)*8); +} + +unsigned short __fastcall Sh2InnerReadWord(unsigned int a) +{ + return sh2_internal_r((a & 0x1fc)>>2, ~(0xffff << (((~a) & 2)*8))) >> (((~a) & 2)*8); +} + +unsigned int __fastcall Sh2InnerReadLong(unsigned int a) +{ + return sh2_internal_r((a & 0x1fc)>>2, 0); +} + +void __fastcall Sh2InnerWriteByte(unsigned int a, unsigned char d) +{ + //bprintf(0, _T("Attempt to write byte value %02x to location %8x offset: %04x\n"), d, a, (a & 0x1fc)>>2); + sh2_internal_w((a & 0x1fc)>>2, d << (((~a) & 3)*8), ~(0xff << (((~a) & 3)*8))); +} + +void __fastcall Sh2InnerWriteWord(unsigned int a, unsigned short d) +{ + sh2_internal_w((a & 0x1fc)>>2, d << (((~a) & 2)*8), ~(0xffff << (((~a) & 2)*8))); +} + +void __fastcall Sh2InnerWriteLong(unsigned int a, unsigned int d) +{ + sh2_internal_w((a & 0x1fc)>>2, d, 0); +} + +unsigned char __fastcall Sh2EmptyReadByte(unsigned int) { return 0xa5; } +unsigned short __fastcall Sh2EmptyReadWord(unsigned int) { return 0xa5a5; } +unsigned int __fastcall Sh2EmptyReadLong(unsigned int) { return 0xa5a5a5a5; } +void __fastcall Sh2EmptyWriteByte(unsigned int, unsigned char) { } +void __fastcall Sh2EmptyWriteWord(unsigned int, unsigned short) { } +void __fastcall Sh2EmptyWriteLong(unsigned int, unsigned int) { } + +int Sh2Exit() +{ + has_sh2 = 0; + + if (Sh2Ext) { + free(Sh2Ext); + Sh2Ext = NULL; + } + pSh2Ext = NULL; + + return 0; +} + +int Sh2Init(int nCount) +{ + has_sh2 = 1; + + Sh2Ext = (SH2EXT *)malloc(sizeof(SH2EXT) * nCount); + if (Sh2Ext == NULL) { + Sh2Exit(); + return 1; + } + memset(Sh2Ext, 0, sizeof(SH2EXT) * nCount); + + extern void CpuCheatRegister(int,int); + + // init default memory handler + for (int i=0; ish2; + + Sh2MapHandler(SH2_MAXHANDLER - 1, 0xE0000000, 0xFFFFFFFF, 0x07); + Sh2MapHandler(SH2_MAXHANDLER - 2, 0x40000000, 0xBFFFFFFF, 0x07); +// Sh2MapHandler(SH2_MAXHANDLER - 3, 0xC0000000, 0xDFFFFFFF, 0x07); + + Sh2SetReadByteHandler (SH2_MAXHANDLER - 1, Sh2InnerReadByte); + Sh2SetReadWordHandler (SH2_MAXHANDLER - 1, Sh2InnerReadWord); + Sh2SetReadLongHandler (SH2_MAXHANDLER - 1, Sh2InnerReadLong); + Sh2SetWriteByteHandler(SH2_MAXHANDLER - 1, Sh2InnerWriteByte); + Sh2SetWriteWordHandler(SH2_MAXHANDLER - 1, Sh2InnerWriteWord); + Sh2SetWriteLongHandler(SH2_MAXHANDLER - 1, Sh2InnerWriteLong); + + Sh2SetReadByteHandler (SH2_MAXHANDLER - 2, Sh2EmptyReadByte); + Sh2SetReadWordHandler (SH2_MAXHANDLER - 2, Sh2EmptyReadWord); + Sh2SetReadLongHandler (SH2_MAXHANDLER - 2, Sh2EmptyReadLong); + Sh2SetWriteByteHandler(SH2_MAXHANDLER - 2, Sh2EmptyWriteByte); + Sh2SetWriteWordHandler(SH2_MAXHANDLER - 2, Sh2EmptyWriteWord); + Sh2SetWriteLongHandler(SH2_MAXHANDLER - 2, Sh2EmptyWriteLong); + + CpuCheatRegister(0x0002, i); + } + + return 0; +} + +void Sh2Open(const int i) +{ + pSh2Ext = Sh2Ext + i; + sh2 = & (pSh2Ext->sh2); +} + +void Sh2Close() +{ +} + +int Sh2GetActive() +{ + return 0; +} + +void Sh2Reset(unsigned int pc, unsigned r15) +{ + memset(sh2, 0, sizeof(SH2) - 4); + + sh2->pc = pc; + sh2->r[15] = r15; + sh2->sr = I; + + change_pc(sh2->pc & AM); + + sh2->internal_irq_level = -1; +} + +//---------------------------------------------------------------- + +unsigned char program_read_byte_32be(unsigned int /*A*/) +{ + return 0; +} + +unsigned short program_read_word_32be(unsigned int /*A*/) +{ + return 0; +} + +unsigned int program_read_dword_32be(unsigned int /*A*/) +{ + return 0; +} + +void program_write_byte_32be(unsigned int /*A*/, unsigned char /*V*/) +{ +} + +void program_write_word_32be(unsigned int /*A*/, unsigned short /*V*/) +{ +} + +void program_write_dword_32be(unsigned int /*A*/, unsigned int /*V*/) +{ +} + +//pSh2Ext->opbase + +#if FAST_OP_FETCH + +#define cpu_readop16(A) *(unsigned short *)(pSh2Ext->opbase + ((A) ^ 0x02)) + +#else + +SH2_INLINE unsigned short cpu_readop16(unsigned int A) +{ + unsigned char * pr; + pr = pSh2Ext->MemMap[ (A >> SH2_SHIFT) + SH2_WADD * 2 ]; + if ( (unsigned int)pr >= SH2_MAXHANDLER ) { + A ^= 2; + return *((unsigned short *)(pr + (A & SH2_PAGEM))); + } + return pSh2Ext->ReadWord[(unsigned int)pr](A); +} + +#endif + +// ------------------------------------------------------ + +SH2_INLINE UINT8 RB(UINT32 A) +{ +/* if (A >= 0xe0000000) return sh2_internal_r((A & 0x1fc)>>2, ~(0xff << (((~A) & 3)*8))) >> (((~A) & 3)*8); + if (A >= 0xc0000000) return program_read_byte_32be(A); + if (A >= 0x40000000) return 0xa5; + return program_read_byte_32be(A & AM); */ + + unsigned char * pr; + pr = pSh2Ext->MemMap[ A >> SH2_SHIFT ]; + if ( (uintptr_t)pr >= SH2_MAXHANDLER ) { + A ^= 3; + return pr[A & SH2_PAGEM]; + } + return pSh2Ext->ReadByte[(uintptr_t)pr](A); +} + +SH2_INLINE UINT16 RW(UINT32 A) +{ +/* if (A >= 0xe0000000) return sh2_internal_r((A & 0x1fc)>>2, ~(0xffff << (((~A) & 2)*8))) >> (((~A) & 2)*8); + if (A >= 0xc0000000) return program_read_word_32be(A); + if (A >= 0x40000000) return 0xa5a5; + return program_read_word_32be(A & AM); */ + + unsigned char * pr; + pr = pSh2Ext->MemMap[ A >> SH2_SHIFT ]; + if ( (uintptr_t)pr >= SH2_MAXHANDLER ) { + A ^= 2; + //return (pr[A & SH2_PAGEM] << 8) | pr[(A & SH2_PAGEM) + 1]; + return *((unsigned short *)(pr + (A & SH2_PAGEM))); + } + return pSh2Ext->ReadWord[(uintptr_t)pr](A); +} + +SH2_INLINE UINT16 OPRW(UINT32 A) +{ + + unsigned char * pr; + pr = pSh2Ext->MemMap[ (A >> SH2_SHIFT) + SH2_WADD * 2 ]; + if ( (uintptr_t)pr >= SH2_MAXHANDLER ) { + A ^= 2; + return *((unsigned short *)(pr + (A & SH2_PAGEM))); + } + + return 0x0000; +} + +SH2_INLINE UINT32 RL(UINT32 A) +{ +/* if (A >= 0xe0000000) return sh2_internal_r((A & 0x1fc)>>2, 0); + if (A >= 0xc0000000) return program_read_dword_32be(A); + if (A >= 0x40000000) return 0xa5a5a5a5; + return program_read_dword_32be(A & AM); */ + + unsigned char * pr; + pr = pSh2Ext->MemMap[ A >> SH2_SHIFT ]; + if ( (uintptr_t)pr >= SH2_MAXHANDLER ) { + //return (pr[(A & SH2_PAGEM) + 0] << 24) | (pr[(A & SH2_PAGEM) + 1] << 16) | (pr[(A & SH2_PAGEM) + 2] << 8) | (pr[(A & SH2_PAGEM) + 3] << 0); + return *((unsigned int *)(pr + (A & SH2_PAGEM))); + } + return pSh2Ext->ReadLong[(uintptr_t)pr](A); +} + +SH2_INLINE void WB(UINT32 A, UINT8 V) +{ +/* if (A >= 0xe0000000) { sh2_internal_w((A & 0x1fc)>>2, V << (((~A) & 3)*8), ~(0xff << (((~A) & 3)*8))); return; } + if (A >= 0xc0000000) { program_write_byte_32be(A,V); return; } + if (A >= 0x40000000) return; + program_write_byte_32be(A & AM,V); */ + + unsigned char* pr; + pr = pSh2Ext->MemMap[(A >> SH2_SHIFT) + SH2_WADD]; + if ((uintptr_t)pr >= SH2_MAXHANDLER) { + A ^= 3; + pr[A & SH2_PAGEM] = (unsigned char)V; + return; + } + pSh2Ext->WriteByte[(uintptr_t)pr](A, V); +} + +SH2_INLINE void WW(UINT32 A, UINT16 V) +{ +/* if (A >= 0xe0000000) { sh2_internal_w((A & 0x1fc)>>2, V << (((~A) & 2)*8), ~(0xffff << (((~A) & 2)*8))); return; } + if (A >= 0xc0000000) { program_write_word_32be(A,V); return; } + if (A >= 0x40000000) return; + program_write_word_32be(A & AM,V); */ + + unsigned char * pr; + pr = pSh2Ext->MemMap[(A >> SH2_SHIFT) + SH2_WADD]; + if ((uintptr_t)pr >= SH2_MAXHANDLER) { + A ^= 2; + *((unsigned short *)(pr + (A & SH2_PAGEM))) = (unsigned short)V; + return; + } + pSh2Ext->WriteWord[(uintptr_t)pr](A, V); +} + +SH2_INLINE void WL(UINT32 A, UINT32 V) +{ +/* if (A >= 0xe0000000) { sh2_internal_w((A & 0x1fc)>>2, V, 0); return; } + if (A >= 0xc0000000) { program_write_dword_32be(A,V); return; } + if (A >= 0x40000000) return; + program_write_dword_32be(A & AM,V); */ + unsigned char * pr; + pr = pSh2Ext->MemMap[(A >> SH2_SHIFT) + SH2_WADD]; + if ((uintptr_t)pr >= SH2_MAXHANDLER) { + *((unsigned int *)(pr + (A & SH2_PAGEM))) = (unsigned int)V; + return; + } + pSh2Ext->WriteLong[(uintptr_t)pr](A, V); +} + +SH2_INLINE void sh2_exception(/*const char *message,*/ int irqline) +{ + int vector; + + if (irqline != 16) + { + if (irqline <= (signed int)((sh2->sr >> 4) & 15)) /* If the cpu forbids this interrupt */ + return; + + // if this is an sh2 internal irq, use its vector + if (sh2->internal_irq_level == irqline) + { + vector = sh2->internal_irq_vector; + //LOG(("SH-2 #%d exception #%d (internal vector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message)); + } + else + { + if(sh2->m[0x38] & 0x00010000) + { + //vector = sh2->irq_callback(irqline); + //LOG(("SH-2 #%d exception #%d (external vector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message)); + //bprintf(0, _T("SH-2 exception #%d (external vector: $%x)\n"), irqline, vector); + vector = 64 + irqline/2; + + } + else + { + //sh2->irq_callback(irqline); + vector = 64 + irqline/2; + //LOG(("SH-2 #%d exception #%d (autovector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message)); + } + } + } + else + { + vector = 11; + //LOG(("SH-2 #%d nmi exception (autovector: $%x) after [%s]\n", cpu_getactivecpu(), vector, message)); + } + + sh2->r[15] -= 4; + WL( sh2->r[15], sh2->sr ); /* push SR onto stack */ + sh2->r[15] -= 4; + WL( sh2->r[15], sh2->pc ); /* push PC onto stack */ + + /* set I flags in SR */ + if (irqline > SH2_INT_15) + sh2->sr = sh2->sr | I; + else + sh2->sr = (sh2->sr & ~I) | (irqline << 4); + + /* fetch PC */ + sh2->pc = RL( sh2->vbr + vector * 4 ); + change_pc(sh2->pc & AM); +} + +#define CHECK_PENDING_IRQ(/*message*/) \ +do { \ + int irq = -1; \ + if (sh2->pending_irq & (1 << 0)) irq = 0; \ + if (sh2->pending_irq & (1 << 1)) irq = 1; \ + if (sh2->pending_irq & (1 << 2)) irq = 2; \ + if (sh2->pending_irq & (1 << 3)) irq = 3; \ + if (sh2->pending_irq & (1 << 4)) irq = 4; \ + if (sh2->pending_irq & (1 << 5)) irq = 5; \ + if (sh2->pending_irq & (1 << 6)) irq = 6; \ + if (sh2->pending_irq & (1 << 7)) irq = 7; \ + if (sh2->pending_irq & (1 << 8)) irq = 8; \ + if (sh2->pending_irq & (1 << 9)) irq = 9; \ + if (sh2->pending_irq & (1 << 10)) irq = 10; \ + if (sh2->pending_irq & (1 << 11)) irq = 11; \ + if (sh2->pending_irq & (1 << 12)) irq = 12; \ + if (sh2->pending_irq & (1 << 13)) irq = 13; \ + if (sh2->pending_irq & (1 << 14)) irq = 14; \ + if (sh2->pending_irq & (1 << 15)) irq = 15; \ + if ((sh2->internal_irq_level != -1) && (sh2->internal_irq_level > irq)) irq = sh2->internal_irq_level; \ + if (irq >= 0) \ + sh2_exception(/*message,*/irq); \ +} while(0) + + +#if USE_JUMPTABLE + + #include "sh2op.c" + +#else + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +SH2_INLINE void ADD(UINT32 m, UINT32 n) +{ + sh2->r[n] += sh2->r[m]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +SH2_INLINE void ADDI(UINT32 i, UINT32 n) +{ + sh2->r[n] += (INT32)(INT16)(INT8)i; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +SH2_INLINE void ADDC(UINT32 m, UINT32 n) +{ + UINT32 tmp0, tmp1; + + tmp1 = sh2->r[n] + sh2->r[m]; + tmp0 = sh2->r[n]; + sh2->r[n] = tmp1 + (sh2->sr & T); + if (tmp0 > tmp1) + sh2->sr |= T; + else + sh2->sr &= ~T; + if (tmp1 > sh2->r[n]) + sh2->sr |= T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1111 1 overflow + * ADDV Rm,Rn + */ +SH2_INLINE void ADDV(UINT32 m, UINT32 n) +{ + INT32 dest, src, ans; + + if ((INT32) sh2->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((INT32) sh2->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + sh2->r[n] += sh2->r[m]; + if ((INT32) sh2->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + sh2->sr |= T; + else + sh2->sr &= ~T; + } + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1001 1 - + * AND Rm,Rn + */ +SH2_INLINE void AND(UINT32 m, UINT32 n) +{ + sh2->r[n] &= sh2->r[m]; +} + + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +SH2_INLINE void ANDI(UINT32 i) +{ + sh2->r[0] &= i; +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +SH2_INLINE void ANDM(UINT32 i) +{ + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = i & RB( sh2->ea ); + WB( sh2->ea, temp ); + sh2->sh2_icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +SH2_INLINE void BF(UINT32 d) +{ + if ((sh2->sr & T) == 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + change_pc(sh2->pc & AM); + sh2->sh2_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +SH2_INLINE void BFS(UINT32 d) +{ + if ((sh2->sr & T) == 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->sh2_icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +SH2_INLINE void BRA(UINT32 d) +{ + INT32 disp = ((INT32)d << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + UINT32 next_opcode = RW(sh2->ppc & AM); + //UINT32 next_opcode = OPRW(sh2->ppc & AM); + + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009){ + //bprintf(0, _T("SH2: BUSY_LOOP_HACKS %d\n"), sh2->sh2_icount); + sh2->sh2_total_cycles += sh2->sh2_icount; + sh2->sh2_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + sh2->sh2_total_cycles -= sh2->sh2_icount; + } + } +#endif + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->sh2_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +SH2_INLINE void BRAF(UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pc += sh2->r[m] + 2; + sh2->sh2_icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +SH2_INLINE void BSR(UINT32 d) +{ + INT32 disp = ((INT32)d << 20) >> 20; + + sh2->pr = sh2->pc + 2; + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->sh2_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +SH2_INLINE void BSRF(UINT32 m) +{ + sh2->pr = sh2->pc + 2; + sh2->delay = sh2->pc; + sh2->pc += sh2->r[m] + 2; + sh2->sh2_icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +SH2_INLINE void BT(UINT32 d) +{ + if ((sh2->sr & T) != 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + change_pc(sh2->pc & AM); + sh2->sh2_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +SH2_INLINE void BTS(UINT32 d) +{ + if ((sh2->sr & T) != 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->sh2_icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +SH2_INLINE void CLRMAC(void) +{ + sh2->mach = 0; + sh2->macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +SH2_INLINE void CLRT(void) +{ + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +SH2_INLINE void CMPEQ(UINT32 m, UINT32 n) +{ + if (sh2->r[n] == sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +SH2_INLINE void CMPGE(UINT32 m, UINT32 n) +{ + if ((INT32) sh2->r[n] >= (INT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +SH2_INLINE void CMPGT(UINT32 m, UINT32 n) +{ + if ((INT32) sh2->r[n] > (INT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +SH2_INLINE void CMPHI(UINT32 m, UINT32 n) +{ + if ((UINT32) sh2->r[n] > (UINT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +SH2_INLINE void CMPHS(UINT32 m, UINT32 n) +{ + if ((UINT32) sh2->r[n] >= (UINT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +SH2_INLINE void CMPPL(UINT32 n) +{ + if ((INT32) sh2->r[n] > 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +SH2_INLINE void CMPPZ(UINT32 n) +{ + if ((INT32) sh2->r[n] >= 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +SH2_INLINE void CMPSTR(UINT32 m, UINT32 n) + { + UINT32 temp; + INT32 HH, HL, LH, LL; + temp = sh2->r[n] ^ sh2->r[m]; + HH = (temp >> 24) & 0xff; + HL = (temp >> 16) & 0xff; + LH = (temp >> 8) & 0xff; + LL = temp & 0xff; + if (HH && HL && LH && LL) + sh2->sr &= ~T; + else + sh2->sr |= T; + } + + +/* code cycles t-bit + * 1000 1000 iiii iiii 1 comparison result + * CMP/EQ #imm,R0 + */ +SH2_INLINE void CMPIM(UINT32 i) +{ + UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i; + + if (sh2->r[0] == imm) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 0111 1 calculation result + * DIV0S Rm,Rn + */ +SH2_INLINE void DIV0S(UINT32 m, UINT32 n) +{ + if ((sh2->r[n] & 0x80000000) == 0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + if ((sh2->r[m] & 0x80000000) == 0) + sh2->sr &= ~M; + else + sh2->sr |= M; + if ((sh2->r[m] ^ sh2->r[n]) & 0x80000000) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0000 0000 0001 1001 1 0 + * DIV0U + */ +SH2_INLINE void DIV0U(void) +{ + sh2->sr &= ~(M | Q | T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +SH2_INLINE void DIV1(UINT32 m, UINT32 n) +{ + UINT32 tmp0; + UINT32 old_q; + + old_q = sh2->sr & Q; + if (0x80000000 & sh2->r[n]) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + + sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); + + if (!old_q) + { + if (!(sh2->sr & M)) + { + tmp0 = sh2->r[n]; + sh2->r[n] -= sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] > tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + else + if(sh2->r[n] > tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + tmp0 = sh2->r[n]; + sh2->r[n] += sh2->r[m]; + if(!(sh2->sr & Q)) + { + if(sh2->r[n] < tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + if(sh2->r[n] < tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + } + } + } + else + { + if (!(sh2->sr & M)) + { + tmp0 = sh2->r[n]; + sh2->r[n] += sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] < tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + else + if(sh2->r[n] < tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + tmp0 = sh2->r[n]; + sh2->r[n] -= sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] > tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + else + if(sh2->r[n] > tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + } + } + + tmp0 = (sh2->sr & (Q | M)); + if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* DMULS.L Rm,Rn */ +SH2_INLINE void DMULS(UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) sh2->r[n]; + tempm = (INT32) sh2->r[m]; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + if ((INT32) (sh2->r[n] ^ sh2->r[m]) < 0) + fnLmL = -1; + else + fnLmL = 0; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + sh2->mach = Res2; + sh2->macl = Res0; + sh2->sh2_icount--; +} + +/* DMULU.L Rm,Rn */ +SH2_INLINE void DMULU(UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + + RnL = sh2->r[n] & 0x0000ffff; + RnH = (sh2->r[n] >> 16) & 0x0000ffff; + RmL = sh2->r[m] & 0x0000ffff; + RmH = (sh2->r[m] >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + sh2->mach = Res2; + sh2->macl = Res0; + sh2->sh2_icount--; +} + +/* DT Rn */ +SH2_INLINE void DT(UINT32 n) +{ + sh2->r[n]--; + if (sh2->r[n] == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +#if BUSY_LOOP_HACKS + { + UINT32 next_opcode = RW(sh2->ppc & AM); + //UINT32 next_opcode = OPRW(sh2->ppc & AM); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + //bprintf(0, _T("SH2: BUSY_LOOP_HACKS (%d)--; \n"), sh2->r[n], sh2->sh2_icount); + while (sh2->r[n] > 1 && sh2->sh2_icount > 4) + { + sh2->r[n]--; + sh2->sh2_icount -= 4; /* cycles for DT (1) and BF taken (3) */ + sh2->sh2_total_cycles += 4; + } + } + } +#endif +} + +/* EXTS.B Rm,Rn */ +SH2_INLINE void EXTSB(UINT32 m, UINT32 n) +{ + sh2->r[n] = ((INT32)sh2->r[m] << 24) >> 24; +} + +/* EXTS.W Rm,Rn */ +SH2_INLINE void EXTSW(UINT32 m, UINT32 n) +{ + sh2->r[n] = ((INT32)sh2->r[m] << 16) >> 16; +} + +/* EXTU.B Rm,Rn */ +SH2_INLINE void EXTUB(UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +SH2_INLINE void EXTUW(UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m] & 0x0000ffff; +} + +/* JMP @Rm */ +SH2_INLINE void JMP(UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->r[m]; +} + +/* JSR @Rm */ +SH2_INLINE void JSR(UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pr = sh2->pc + 2; + sh2->pc = sh2->ea = sh2->r[m]; + sh2->sh2_icount--; +} + + +/* LDC Rm,SR */ +SH2_INLINE void LDCSR(UINT32 m) +{ + sh2->sr = sh2->r[m] & FLAGS; + sh2->test_irq = 1; +} + +/* LDC Rm,GBR */ +SH2_INLINE void LDCGBR(UINT32 m) +{ + sh2->gbr = sh2->r[m]; +} + +/* LDC Rm,VBR */ +SH2_INLINE void LDCVBR(UINT32 m) +{ + sh2->vbr = sh2->r[m]; +} + +/* LDC.L @Rm+,SR */ +SH2_INLINE void LDCMSR(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->sr = RL( sh2->ea ) & FLAGS; + sh2->r[m] += 4; + sh2->sh2_icount -= 2; + sh2->test_irq = 1; +} + +/* LDC.L @Rm+,GBR */ +SH2_INLINE void LDCMGBR(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->gbr = RL( sh2->ea ); + sh2->r[m] += 4; + sh2->sh2_icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +SH2_INLINE void LDCMVBR(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->vbr = RL( sh2->ea ); + sh2->r[m] += 4; + sh2->sh2_icount -= 2; +} + +/* LDS Rm,MACH */ +SH2_INLINE void LDSMACH(UINT32 m) +{ + sh2->mach = sh2->r[m]; +} + +/* LDS Rm,MACL */ +SH2_INLINE void LDSMACL(UINT32 m) +{ + sh2->macl = sh2->r[m]; +} + +/* LDS Rm,PR */ +SH2_INLINE void LDSPR(UINT32 m) +{ + sh2->pr = sh2->r[m]; +} + +/* LDS.L @Rm+,MACH */ +SH2_INLINE void LDSMMACH(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->mach = RL( sh2->ea ); + sh2->r[m] += 4; +} + +/* LDS.L @Rm+,MACL */ +SH2_INLINE void LDSMMACL(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->macl = RL( sh2->ea ); + sh2->r[m] += 4; +} + +/* LDS.L @Rm+,PR */ +SH2_INLINE void LDSMPR(UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->pr = RL( sh2->ea ); + sh2->r[m] += 4; +} + +/* MAC.L @Rm+,@Rn+ */ +SH2_INLINE void MAC_L(UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) RL( sh2->r[n] ); + sh2->r[n] += 4; + tempm = (INT32) RL( sh2->r[m] ); + sh2->r[m] += 4; + if ((INT32) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (sh2->sr & S) + { + Res0 = sh2->macl + Res0; + if (sh2->macl > Res0) + Res2++; + Res2 += (sh2->mach & 0x0000ffff); + if (((INT32) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + sh2->mach = Res2; + sh2->macl = Res0; + } + else + { + Res0 = sh2->macl + Res0; + if (sh2->macl > Res0) + Res2++; + Res2 += sh2->mach; + sh2->mach = Res2; + sh2->macl = Res0; + } + sh2->sh2_icount -= 2; +} + +/* MAC.W @Rm+,@Rn+ */ +SH2_INLINE void MAC_W(UINT32 m, UINT32 n) +{{ + INT32 tempm, tempn, dest, src, ans; + UINT32 templ; + + tempn = (INT32) RW( sh2->r[n] ); + sh2->r[n] += 2; + tempm = (INT32) RW( sh2->r[m] ); + sh2->r[m] += 2; + templ = sh2->macl; + tempm = ((INT32) (short) tempn * (INT32) (short) tempm); + if ((INT32) sh2->macl >= 0) + dest = 0; + else + dest = 1; + if ((INT32) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + sh2->macl += tempm; + if ((INT32) sh2->macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (sh2->sr & S) + { + if (ans == 1) + { + if (src == 0) + sh2->macl = 0x7fffffff; + if (src == 2) + sh2->macl = 0x80000000; + } + } + else + { + sh2->mach += tempn; + if (templ > sh2->macl) + sh2->mach += 1; + } + sh2->sh2_icount -= 2; +}} + +/* MOV Rm,Rn */ +SH2_INLINE void MOV(UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m]; +} + +/* MOV.B Rm,@Rn */ +SH2_INLINE void MOVBS(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WB( sh2->ea, sh2->r[m] & 0x000000ff); +} + +/* MOV.W Rm,@Rn */ +SH2_INLINE void MOVWS(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WW( sh2->ea, sh2->r[m] & 0x0000ffff); +} + +/* MOV.L Rm,@Rn */ +SH2_INLINE void MOVLS(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->r[m] ); +} + +/* MOV.B @Rm,Rn */ +SH2_INLINE void MOVBL(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2->ea ); +} + +/* MOV.W @Rm,Rn */ +SH2_INLINE void MOVWL(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2->ea ); +} + +/* MOV.L @Rm,Rn */ +SH2_INLINE void MOVLL(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = RL( sh2->ea ); +} + +/* MOV.B Rm,@-Rn */ +SH2_INLINE void MOVBM(UINT32 m, UINT32 n) +{ + /* SMG : bug fix, was reading sh2->r[n] */ + UINT32 data = sh2->r[m] & 0x000000ff; + + sh2->r[n] -= 1; + WB( sh2->r[n], data ); +} + +/* MOV.W Rm,@-Rn */ +SH2_INLINE void MOVWM(UINT32 m, UINT32 n) +{ + UINT32 data = sh2->r[m] & 0x0000ffff; + + sh2->r[n] -= 2; + WW( sh2->r[n], data ); +} + +/* MOV.L Rm,@-Rn */ +SH2_INLINE void MOVLM(UINT32 m, UINT32 n) +{ + UINT32 data = sh2->r[m]; + + sh2->r[n] -= 4; + WL( sh2->r[n], data ); +} + +/* MOV.B @Rm+,Rn */ +SH2_INLINE void MOVBP(UINT32 m, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2->r[m] ); + if (n != m) + sh2->r[m] += 1; +} + +/* MOV.W @Rm+,Rn */ +SH2_INLINE void MOVWP(UINT32 m, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2->r[m] ); + if (n != m) + sh2->r[m] += 2; +} + +/* MOV.L @Rm+,Rn */ +SH2_INLINE void MOVLP(UINT32 m, UINT32 n) +{ + sh2->r[n] = RL( sh2->r[m] ); + if (n != m) + sh2->r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +SH2_INLINE void MOVBS0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WB( sh2->ea, sh2->r[m] & 0x000000ff ); +} + +/* MOV.W Rm,@(R0,Rn) */ +SH2_INLINE void MOVWS0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WW( sh2->ea, sh2->r[m] & 0x0000ffff ); +} + +/* MOV.L Rm,@(R0,Rn) */ +SH2_INLINE void MOVLS0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WL( sh2->ea, sh2->r[m] ); +} + +/* MOV.B @(R0,Rm),Rn */ +SH2_INLINE void MOVBL0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2->ea ); +} + +/* MOV.W @(R0,Rm),Rn */ +SH2_INLINE void MOVWL0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2->ea ); +} + +/* MOV.L @(R0,Rm),Rn */ +SH2_INLINE void MOVLL0(UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = RL( sh2->ea ); +} + +/* MOV #imm,Rn */ +SH2_INLINE void MOVI(UINT32 i, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) i; +} + +/* MOV.W @(disp8,PC),Rn */ +SH2_INLINE void MOVWI(UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->pc + disp * 2 + 2; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2->ea ); +} + +/* MOV.L @(disp8,PC),Rn */ +SH2_INLINE void MOVLI(UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0xff; + sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; + sh2->r[n] = RL( sh2->ea ); +} + +/* MOV.B @(disp8,GBR),R0 */ +SH2_INLINE void MOVBLG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp; + sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2->ea ); +} + +/* MOV.W @(disp8,GBR),R0 */ +SH2_INLINE void MOVWLG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 2; + sh2->r[0] = (INT32)(INT16) RW( sh2->ea ); +} + +/* MOV.L @(disp8,GBR),R0 */ +SH2_INLINE void MOVLLG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 4; + sh2->r[0] = RL( sh2->ea ); +} + +/* MOV.B R0,@(disp8,GBR) */ +SH2_INLINE void MOVBSG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp; + WB( sh2->ea, sh2->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp8,GBR) */ +SH2_INLINE void MOVWSG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 2; + WW( sh2->ea, sh2->r[0] & 0x0000ffff ); +} + +/* MOV.L R0,@(disp8,GBR) */ +SH2_INLINE void MOVLSG(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 4; + WL( sh2->ea, sh2->r[0] ); +} + +/* MOV.B R0,@(disp4,Rn) */ +SH2_INLINE void MOVBS4(UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp; + WB( sh2->ea, sh2->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp4,Rn) */ +SH2_INLINE void MOVWS4(UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp * 2; + WW( sh2->ea, sh2->r[0] & 0x0000ffff ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +SH2_INLINE void MOVLS4(UINT32 m, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp * 4; + WL( sh2->ea, sh2->r[m] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +SH2_INLINE void MOVBL4(UINT32 m, UINT32 d) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp; + sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2->ea ); +} + +/* MOV.W @(disp4,Rm),R0 */ +SH2_INLINE void MOVWL4(UINT32 m, UINT32 d) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp * 2; + sh2->r[0] = (UINT32)(INT32)(INT16) RW( sh2->ea ); +} + +/* MOV.L @(disp4,Rm),Rn */ +SH2_INLINE void MOVLL4(UINT32 m, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp * 4; + sh2->r[n] = RL( sh2->ea ); +} + +/* MOVA @(disp8,PC),R0 */ +SH2_INLINE void MOVA(UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; + sh2->r[0] = sh2->ea; +} + +/* MOVT Rn */ +SH2_INLINE void MOVT(UINT32 n) +{ + sh2->r[n] = sh2->sr & T; +} + +/* MUL.L Rm,Rn */ +SH2_INLINE void MULL(UINT32 m, UINT32 n) +{ + sh2->macl = sh2->r[n] * sh2->r[m]; + sh2->sh2_icount--; +} + +/* MULS Rm,Rn */ +SH2_INLINE void MULS(UINT32 m, UINT32 n) +{ + sh2->macl = (INT16) sh2->r[n] * (INT16) sh2->r[m]; +} + +/* MULU Rm,Rn */ +SH2_INLINE void MULU(UINT32 m, UINT32 n) +{ + sh2->macl = (UINT16) sh2->r[n] * (UINT16) sh2->r[m]; +} + +/* NEG Rm,Rn */ +SH2_INLINE void NEG(UINT32 m, UINT32 n) +{ + sh2->r[n] = 0 - sh2->r[m]; +} + +/* NEGC Rm,Rn */ +SH2_INLINE void NEGC(UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = sh2->r[m]; + sh2->r[n] = -temp - (sh2->sr & T); + if (temp || (sh2->sr & T)) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* NOP */ +SH2_INLINE void NOP(void) +{ +} + +/* NOT Rm,Rn */ +SH2_INLINE void NOT(UINT32 m, UINT32 n) +{ + sh2->r[n] = ~sh2->r[m]; +} + +/* OR Rm,Rn */ +SH2_INLINE void OR(UINT32 m, UINT32 n) +{ + sh2->r[n] |= sh2->r[m]; +} + +/* OR #imm,R0 */ +SH2_INLINE void ORI(UINT32 i) +{ + sh2->r[0] |= i; + sh2->sh2_icount -= 2; +} + +/* OR.B #imm,@(R0,GBR) */ +SH2_INLINE void ORM(UINT32 i) +{ + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = RB( sh2->ea ); + temp |= i; + WB( sh2->ea, temp ); +} + +/* ROTCL Rn */ +SH2_INLINE void ROTCL(UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[n] >> 31) & T; + sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); + sh2->sr = (sh2->sr & ~T) | temp; +} + +/* ROTCR Rn */ +SH2_INLINE void ROTCR(UINT32 n) +{ + UINT32 temp; + temp = (sh2->sr & T) << 31; + if (sh2->r[n] & T) + sh2->sr |= T; + else + sh2->sr &= ~T; + sh2->r[n] = (sh2->r[n] >> 1) | temp; +} + +/* ROTL Rn */ +SH2_INLINE void ROTL(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] = (sh2->r[n] << 1) | (sh2->r[n] >> 31); +} + +/* ROTR Rn */ +SH2_INLINE void ROTR(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] = (sh2->r[n] >> 1) | (sh2->r[n] << 31); +} + +/* RTE */ +SH2_INLINE void RTE(void) +{ + sh2->ea = sh2->r[15]; + sh2->delay = sh2->pc; + sh2->pc = RL( sh2->ea ); + sh2->r[15] += 4; + sh2->ea = sh2->r[15]; + sh2->sr = RL( sh2->ea ) & FLAGS; + sh2->r[15] += 4; + sh2->sh2_icount -= 3; + sh2->test_irq = 1; +} + +/* RTS */ +SH2_INLINE void RTS(void) +{ + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pr; + sh2->sh2_icount--; +} + +/* SETT */ +SH2_INLINE void SETT(void) +{ + sh2->sr |= T; +} + +/* SHAL Rn (same as SHLL) */ +SH2_INLINE void SHAL(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] <<= 1; +} + +/* SHAR Rn */ +SH2_INLINE void SHAR(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] = (UINT32)((INT32)sh2->r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +SH2_INLINE void SHLL(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] <<= 1; +} + +/* SHLL2 Rn */ +SH2_INLINE void SHLL2(UINT32 n) +{ + sh2->r[n] <<= 2; +} + +/* SHLL8 Rn */ +SH2_INLINE void SHLL8(UINT32 n) +{ + sh2->r[n] <<= 8; +} + +/* SHLL16 Rn */ +SH2_INLINE void SHLL16(UINT32 n) +{ + sh2->r[n] <<= 16; +} + +/* SHLR Rn */ +SH2_INLINE void SHLR(UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] >>= 1; +} + +/* SHLR2 Rn */ +SH2_INLINE void SHLR2(UINT32 n) +{ + sh2->r[n] >>= 2; +} + +/* SHLR8 Rn */ +SH2_INLINE void SHLR8(UINT32 n) +{ + sh2->r[n] >>= 8; +} + +/* SHLR16 Rn */ +SH2_INLINE void SHLR16(UINT32 n) +{ + sh2->r[n] >>= 16; +} + +/* SLEEP */ +SH2_INLINE void SLEEP(void) +{ + sh2->pc -= 2; + sh2->sh2_icount -= 2; + /* Wait_for_exception; */ +} + +/* STC SR,Rn */ +SH2_INLINE void STCSR(UINT32 n) +{ + sh2->r[n] = sh2->sr; +} + +/* STC GBR,Rn */ +SH2_INLINE void STCGBR(UINT32 n) +{ + sh2->r[n] = sh2->gbr; +} + +/* STC VBR,Rn */ +SH2_INLINE void STCVBR(UINT32 n) +{ + sh2->r[n] = sh2->vbr; +} + +/* STC.L SR,@-Rn */ +SH2_INLINE void STCMSR(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->sr ); + sh2->sh2_icount--; +} + +/* STC.L GBR,@-Rn */ +SH2_INLINE void STCMGBR(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->gbr ); + sh2->sh2_icount--; +} + +/* STC.L VBR,@-Rn */ +SH2_INLINE void STCMVBR(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->vbr ); + sh2->sh2_icount--; +} + +/* STS MACH,Rn */ +SH2_INLINE void STSMACH(UINT32 n) +{ + sh2->r[n] = sh2->mach; +} + +/* STS MACL,Rn */ +SH2_INLINE void STSMACL(UINT32 n) +{ + sh2->r[n] = sh2->macl; +} + +/* STS PR,Rn */ +SH2_INLINE void STSPR(UINT32 n) +{ + sh2->r[n] = sh2->pr; +} + +/* STS.L MACH,@-Rn */ +SH2_INLINE void STSMMACH(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->mach ); +} + +/* STS.L MACL,@-Rn */ +SH2_INLINE void STSMMACL(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->macl ); +} + +/* STS.L PR,@-Rn */ +SH2_INLINE void STSMPR(UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2->ea, sh2->pr ); +} + +/* SUB Rm,Rn */ +SH2_INLINE void SUB(UINT32 m, UINT32 n) +{ + sh2->r[n] -= sh2->r[m]; +} + +/* SUBC Rm,Rn */ +SH2_INLINE void SUBC(UINT32 m, UINT32 n) +{ + UINT32 tmp0, tmp1; + + tmp1 = sh2->r[n] - sh2->r[m]; + tmp0 = sh2->r[n]; + sh2->r[n] = tmp1 - (sh2->sr & T); + if (tmp0 < tmp1) + sh2->sr |= T; + else + sh2->sr &= ~T; + if (tmp1 < sh2->r[n]) + sh2->sr |= T; +} + +/* SUBV Rm,Rn */ +SH2_INLINE void SUBV(UINT32 m, UINT32 n) +{ + INT32 dest, src, ans; + + if ((INT32) sh2->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((INT32) sh2->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + sh2->r[n] -= sh2->r[m]; + if ((INT32) sh2->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 1) + { + if (ans == 1) + sh2->sr |= T; + else + sh2->sr &= ~T; + } + else + sh2->sr &= ~T; +} + +/* SWAP.B Rm,Rn */ +SH2_INLINE void SWAPB(UINT32 m, UINT32 n) +{ + UINT32 temp0, temp1; + + temp0 = sh2->r[m] & 0xffff0000; + temp1 = (sh2->r[m] & 0x000000ff) << 8; + sh2->r[n] = (sh2->r[m] >> 8) & 0x000000ff; + sh2->r[n] = sh2->r[n] | temp1 | temp0; +} + +/* SWAP.W Rm,Rn */ +SH2_INLINE void SWAPW(UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[m] >> 16) & 0x0000ffff; + sh2->r[n] = (sh2->r[m] << 16) | temp; +} + +/* TAS.B @Rn */ +SH2_INLINE void TAS(UINT32 n) +{ + UINT32 temp; + sh2->ea = sh2->r[n]; + /* Bus Lock enable */ + temp = RB( sh2->ea ); + if (temp == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; + temp |= 0x80; + /* Bus Lock disable */ + WB( sh2->ea, temp ); + sh2->sh2_icount -= 3; +} + +/* TRAPA #imm */ +SH2_INLINE void TRAPA(UINT32 i) +{ + UINT32 imm = i & 0xff; + + sh2->ea = sh2->vbr + imm * 4; + + sh2->r[15] -= 4; + WL( sh2->r[15], sh2->sr ); + sh2->r[15] -= 4; + WL( sh2->r[15], sh2->pc ); + + sh2->pc = RL( sh2->ea ); + change_pc(sh2->pc & AM); + + sh2->sh2_icount -= 7; +} + +/* TST Rm,Rn */ +SH2_INLINE void TST(UINT32 m, UINT32 n) +{ + if ((sh2->r[n] & sh2->r[m]) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* TST #imm,R0 */ +SH2_INLINE void TSTI(UINT32 i) +{ + UINT32 imm = i & 0xff; + + if ((imm & sh2->r[0]) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* TST.B #imm,@(R0,GBR) */ +SH2_INLINE void TSTM(UINT32 i) +{ + UINT32 imm = i & 0xff; + + sh2->ea = sh2->gbr + sh2->r[0]; + if ((imm & RB( sh2->ea )) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; + sh2->sh2_icount -= 2; +} + +/* XOR Rm,Rn */ +SH2_INLINE void XOR(UINT32 m, UINT32 n) +{ + sh2->r[n] ^= sh2->r[m]; +} + +/* XOR #imm,R0 */ +SH2_INLINE void XORI(UINT32 i) +{ + UINT32 imm = i & 0xff; + sh2->r[0] ^= imm; +} + +/* XOR.B #imm,@(R0,GBR) */ +SH2_INLINE void XORM(UINT32 i) +{ + UINT32 imm = i & 0xff; + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = RB( sh2->ea ); + temp ^= imm; + WB( sh2->ea, temp ); + sh2->sh2_icount -= 2; +} + +/* XTRCT Rm,Rn */ +SH2_INLINE void XTRCT(UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[m] << 16) & 0xffff0000; + sh2->r[n] = (sh2->r[n] >> 16) & 0x0000ffff; + sh2->r[n] |= temp; +} + +/***************************************************************************** + * OPCODE DISPATCHERS + *****************************************************************************/ + +SH2_INLINE void op0000(UINT16 opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: NOP(); break; + case 0x01: NOP(); break; + case 0x02: STCSR(Rn); break; + case 0x03: BSRF(Rn); break; + case 0x04: MOVBS0(Rm, Rn); break; + case 0x05: MOVWS0(Rm, Rn); break; + case 0x06: MOVLS0(Rm, Rn); break; + case 0x07: MULL(Rm, Rn); break; + case 0x08: CLRT(); break; + case 0x09: NOP(); break; + case 0x0a: STSMACH(Rn); break; + case 0x0b: RTS(); break; + case 0x0c: MOVBL0(Rm, Rn); break; + case 0x0d: MOVWL0(Rm, Rn); break; + case 0x0e: MOVLL0(Rm, Rn); break; + case 0x0f: MAC_L(Rm, Rn); break; + + case 0x10: NOP(); break; + case 0x11: NOP(); break; + case 0x12: STCGBR(Rn); break; + case 0x13: NOP(); break; + case 0x14: MOVBS0(Rm, Rn); break; + case 0x15: MOVWS0(Rm, Rn); break; + case 0x16: MOVLS0(Rm, Rn); break; + case 0x17: MULL(Rm, Rn); break; + case 0x18: SETT(); break; + case 0x19: DIV0U(); break; + case 0x1a: STSMACL(Rn); break; + case 0x1b: SLEEP(); break; + case 0x1c: MOVBL0(Rm, Rn); break; + case 0x1d: MOVWL0(Rm, Rn); break; + case 0x1e: MOVLL0(Rm, Rn); break; + case 0x1f: MAC_L(Rm, Rn); break; + + case 0x20: NOP(); break; + case 0x21: NOP(); break; + case 0x22: STCVBR(Rn); break; + case 0x23: BRAF(Rn); break; + case 0x24: MOVBS0(Rm, Rn); break; + case 0x25: MOVWS0(Rm, Rn); break; + case 0x26: MOVLS0(Rm, Rn); break; + case 0x27: MULL(Rm, Rn); break; + case 0x28: CLRMAC(); break; + case 0x29: MOVT(Rn); break; + case 0x2a: STSPR(Rn); break; + case 0x2b: RTE(); break; + case 0x2c: MOVBL0(Rm, Rn); break; + case 0x2d: MOVWL0(Rm, Rn); break; + case 0x2e: MOVLL0(Rm, Rn); break; + case 0x2f: MAC_L(Rm, Rn); break; + + case 0x30: NOP(); break; + case 0x31: NOP(); break; + case 0x32: NOP(); break; + case 0x33: NOP(); break; + case 0x34: MOVBS0(Rm, Rn); break; + case 0x35: MOVWS0(Rm, Rn); break; + case 0x36: MOVLS0(Rm, Rn); break; + case 0x37: MULL(Rm, Rn); break; + case 0x38: NOP(); break; + case 0x39: NOP(); break; + case 0x3a: NOP(); break; + case 0x3b: NOP(); break; + case 0x3c: MOVBL0(Rm, Rn); break; + case 0x3d: MOVWL0(Rm, Rn); break; + case 0x3e: MOVLL0(Rm, Rn); break; + case 0x3f: MAC_L(Rm, Rn); break; + + + + } +} + +SH2_INLINE void op0001(UINT16 opcode) +{ + MOVLS4(Rm, opcode & 0x0f, Rn); +} + +SH2_INLINE void op0010(UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: MOVBS(Rm, Rn); break; + case 1: MOVWS(Rm, Rn); break; + case 2: MOVLS(Rm, Rn); break; + case 3: NOP(); break; + case 4: MOVBM(Rm, Rn); break; + case 5: MOVWM(Rm, Rn); break; + case 6: MOVLM(Rm, Rn); break; + case 7: DIV0S(Rm, Rn); break; + case 8: TST(Rm, Rn); break; + case 9: AND(Rm, Rn); break; + case 10: XOR(Rm, Rn); break; + case 11: OR(Rm, Rn); break; + case 12: CMPSTR(Rm, Rn); break; + case 13: XTRCT(Rm, Rn); break; + case 14: MULU(Rm, Rn); break; + case 15: MULS(Rm, Rn); break; + } +} + +SH2_INLINE void op0011(UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: CMPEQ(Rm, Rn); break; + case 1: NOP(); break; + case 2: CMPHS(Rm, Rn); break; + case 3: CMPGE(Rm, Rn); break; + case 4: DIV1(Rm, Rn); break; + case 5: DMULU(Rm, Rn); break; + case 6: CMPHI(Rm, Rn); break; + case 7: CMPGT(Rm, Rn); break; + case 8: SUB(Rm, Rn); break; + case 9: NOP(); break; + case 10: SUBC(Rm, Rn); break; + case 11: SUBV(Rm, Rn); break; + case 12: ADD(Rm, Rn); break; + case 13: DMULS(Rm, Rn); break; + case 14: ADDC(Rm, Rn); break; + case 15: ADDV(Rm, Rn); break; + } +} + +SH2_INLINE void op0100(UINT16 opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: SHLL(Rn); break; + case 0x01: SHLR(Rn); break; + case 0x02: STSMMACH(Rn); break; + case 0x03: STCMSR(Rn); break; + case 0x04: ROTL(Rn); break; + case 0x05: ROTR(Rn); break; + case 0x06: LDSMMACH(Rn); break; + case 0x07: LDCMSR(Rn); break; + case 0x08: SHLL2(Rn); break; + case 0x09: SHLR2(Rn); break; + case 0x0a: LDSMACH(Rn); break; + case 0x0b: JSR(Rn); break; + case 0x0c: NOP(); break; + case 0x0d: NOP(); break; + case 0x0e: LDCSR(Rn); break; + case 0x0f: MAC_W(Rm, Rn); break; + + case 0x10: DT(Rn); break; + case 0x11: CMPPZ(Rn); break; + case 0x12: STSMMACL(Rn); break; + case 0x13: STCMGBR(Rn); break; + case 0x14: NOP(); break; + case 0x15: CMPPL(Rn); break; + case 0x16: LDSMMACL(Rn); break; + case 0x17: LDCMGBR(Rn); break; + case 0x18: SHLL8(Rn); break; + case 0x19: SHLR8(Rn); break; + case 0x1a: LDSMACL(Rn); break; + case 0x1b: TAS(Rn); break; + case 0x1c: NOP(); break; + case 0x1d: NOP(); break; + case 0x1e: LDCGBR(Rn); break; + case 0x1f: MAC_W(Rm, Rn); break; + + case 0x20: SHAL(Rn); break; + case 0x21: SHAR(Rn); break; + case 0x22: STSMPR(Rn); break; + case 0x23: STCMVBR(Rn); break; + case 0x24: ROTCL(Rn); break; + case 0x25: ROTCR(Rn); break; + case 0x26: LDSMPR(Rn); break; + case 0x27: LDCMVBR(Rn); break; + case 0x28: SHLL16(Rn); break; + case 0x29: SHLR16(Rn); break; + case 0x2a: LDSPR(Rn); break; + case 0x2b: JMP(Rn); break; + case 0x2c: NOP(); break; + case 0x2d: NOP(); break; + case 0x2e: LDCVBR(Rn); break; + case 0x2f: MAC_W(Rm, Rn); break; + + case 0x30: NOP(); break; + case 0x31: NOP(); break; + case 0x32: NOP(); break; + case 0x33: NOP(); break; + case 0x34: NOP(); break; + case 0x35: NOP(); break; + case 0x36: NOP(); break; + case 0x37: NOP(); break; + case 0x38: NOP(); break; + case 0x39: NOP(); break; + case 0x3a: NOP(); break; + case 0x3b: NOP(); break; + case 0x3c: NOP(); break; + case 0x3d: NOP(); break; + case 0x3e: NOP(); break; + case 0x3f: MAC_W(Rm, Rn); break; + + } +} + +SH2_INLINE void op0101(UINT16 opcode) +{ + MOVLL4(Rm, opcode & 0x0f, Rn); +} + +SH2_INLINE void op0110(UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: MOVBL(Rm, Rn); break; + case 1: MOVWL(Rm, Rn); break; + case 2: MOVLL(Rm, Rn); break; + case 3: MOV(Rm, Rn); break; + case 4: MOVBP(Rm, Rn); break; + case 5: MOVWP(Rm, Rn); break; + case 6: MOVLP(Rm, Rn); break; + case 7: NOT(Rm, Rn); break; + case 8: SWAPB(Rm, Rn); break; + case 9: SWAPW(Rm, Rn); break; + case 10: NEGC(Rm, Rn); break; + case 11: NEG(Rm, Rn); break; + case 12: EXTUB(Rm, Rn); break; + case 13: EXTUW(Rm, Rn); break; + case 14: EXTSB(Rm, Rn); break; + case 15: EXTSW(Rm, Rn); break; + } +} + +SH2_INLINE void op0111(UINT16 opcode) +{ + ADDI(opcode & 0xff, Rn); +} + +SH2_INLINE void op1000(UINT16 opcode) +{ + switch ( opcode & (15<<8) ) + { + case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break; + case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break; + case 2<< 8: NOP(); break; + case 3<< 8: NOP(); break; + case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break; + case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break; + case 6<< 8: NOP(); break; + case 7<< 8: NOP(); break; + case 8<< 8: CMPIM(opcode & 0xff); break; + case 9<< 8: BT(opcode & 0xff); break; + case 10<< 8: NOP(); break; + case 11<< 8: BF(opcode & 0xff); break; + case 12<< 8: NOP(); break; + case 13<< 8: BTS(opcode & 0xff); break; + case 14<< 8: NOP(); break; + case 15<< 8: BFS(opcode & 0xff); break; + } +} + + +SH2_INLINE void op1001(UINT16 opcode) +{ + MOVWI(opcode & 0xff, Rn); +} + +SH2_INLINE void op1010(UINT16 opcode) +{ + BRA(opcode & 0xfff); +} + +SH2_INLINE void op1011(UINT16 opcode) +{ + BSR(opcode & 0xfff); +} + +SH2_INLINE void op1100(UINT16 opcode) +{ + switch (opcode & (15<<8)) + { + case 0<<8: MOVBSG(opcode & 0xff); break; + case 1<<8: MOVWSG(opcode & 0xff); break; + case 2<<8: MOVLSG(opcode & 0xff); break; + case 3<<8: TRAPA(opcode & 0xff); break; + case 4<<8: MOVBLG(opcode & 0xff); break; + case 5<<8: MOVWLG(opcode & 0xff); break; + case 6<<8: MOVLLG(opcode & 0xff); break; + case 7<<8: MOVA(opcode & 0xff); break; + case 8<<8: TSTI(opcode & 0xff); break; + case 9<<8: ANDI(opcode & 0xff); break; + case 10<<8: XORI(opcode & 0xff); break; + case 11<<8: ORI(opcode & 0xff); break; + case 12<<8: TSTM(opcode & 0xff); break; + case 13<<8: ANDM(opcode & 0xff); break; + case 14<<8: XORM(opcode & 0xff); break; + case 15<<8: ORM(opcode & 0xff); break; + } +} + +SH2_INLINE void op1101(UINT16 opcode) +{ + MOVLI(opcode & 0xff, Rn); +} + +SH2_INLINE void op1110(UINT16 opcode) +{ + MOVI(opcode & 0xff, Rn); +} + +SH2_INLINE void op1111(UINT16 /*opcode*/) +{ + NOP(); +} + +#endif // USE_JUMPTABLE + +/***************************************************************************** + * MAME CPU INTERFACE + *****************************************************************************/ + +static void sh2_timer_resync(void) +{ + int divider = div_tab[(sh2->m[5] >> 8) & 3]; + UINT32 cur_time = sh2_GetTotalCycles(); + + if(divider) + sh2->frc += (cur_time - sh2->frc_base) >> divider; + sh2->frc_base = cur_time; +} + +static void sh2_timer_activate(void) +{ + int max_delta = 0xfffff; + UINT16 frc; + + //timer_adjust(sh2->timer, attotime_never, 0, attotime_zero); + sh2->timer_active = 0; +// sh2->timer_cycles = 0; + + frc = sh2->frc; + if(!(sh2->m[4] & OCFA)) { + UINT16 delta = sh2->ocra - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(!(sh2->m[4] & OCFB) && (sh2->ocra <= sh2->ocrb || !(sh2->m[4] & 0x010000))) { + UINT16 delta = sh2->ocrb - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(!(sh2->m[4] & OVF) && !(sh2->m[4] & 0x010000)) { + int delta = 0x10000 - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(max_delta != 0xfffff) { + int divider = div_tab[(sh2->m[5] >> 8) & 3]; + if(divider) { + max_delta <<= divider; + sh2->frc_base = sh2_GetTotalCycles(); + + //timer_adjust(sh2->timer, ATTOTIME_IN_CYCLES(max_delta, sh2->cpu_number), sh2->cpu_number, attotime_zero); + //bprintf(0, _T("SH2 Timer Actived %d\n"), max_delta); + + sh2->timer_active = 1; + sh2->timer_cycles = max_delta; + sh2->timer_base = sh2->frc_base; + + } else { +// logerror("SH2.%d: Timer event in %d cycles of external clock", sh2->cpu_number, max_delta); + //bprintf(0, _T("SH2.0: Timer event in %d cycles of external clock\n"), max_delta); + } + } +} + +static void sh2_recalc_irq(void) +{ + int irq = 0, vector = -1; + int level; + + // Timer irqs + if((sh2->m[4]>>8) & sh2->m[4] & (ICF|OCFA|OCFB|OVF)) + { + level = (sh2->m[0x18] >> 24) & 15; + if(level > irq) + { + int mask = (sh2->m[4]>>8) & sh2->m[4]; + irq = level; + if(mask & ICF) + vector = (sh2->m[0x19] >> 8) & 0x7f; + else if(mask & (OCFA|OCFB)) + vector = sh2->m[0x19] & 0x7f; + else + vector = (sh2->m[0x1a] >> 24) & 0x7f; + } + } + + // DMA irqs + if((sh2->m[0x63] & 6) == 6) { + level = (sh2->m[0x38] >> 8) & 15; + if(level > irq) { + irq = level; + vector = (sh2->m[0x68] >> 24) & 0x7f; + } + } + + if((sh2->m[0x67] & 6) == 6) { + level = (sh2->m[0x38] >> 8) & 15; + if(level > irq) { + irq = level; + vector = (sh2->m[0x6a] >> 24) & 0x7f; + } + } + + + sh2->internal_irq_level = irq; + sh2->internal_irq_vector = vector; + sh2->test_irq = 1; +} + +static void sh2_timer_callback() +{ + UINT16 frc; +// int cpunum = param; +// cpuintrf_push_context(cpunum); + sh2_timer_resync(); + + frc = sh2->frc; + + if(frc == sh2->ocrb) + sh2->m[4] |= OCFB; + + if(frc == 0x0000) + sh2->m[4] |= OVF; + + if(frc == sh2->ocra) + { + sh2->m[4] |= OCFA; + + if(sh2->m[4] & 0x010000) + sh2->frc = 0; + } + + sh2_recalc_irq(); + sh2_timer_activate(); + +// cpuintrf_pop_context(); +} + +static void sh2_dmac_callback(int dma) +{ +// cpuintrf_push_context(cpunum); + +// LOG(("SH2.%d: DMA %d complete\n", cpunum, dma)); +// bprintf(0, _T("SH2: DMA %d complete at %d\n"), dma, sh2_GetTotalCycles()); + + sh2->m[0x63+4*dma] |= 2; + sh2->dma_timer_active[dma] = 0; + sh2_recalc_irq(); + +// cpuintrf_pop_context(); +} + +static void sh2_dmac_check(int dma) +{ + if(sh2->m[0x63+4*dma] & sh2->m[0x6c] & 1) + { + if(!sh2->dma_timer_active[dma] && !(sh2->m[0x63+4*dma] & 2)) + { + int incs, incd, size; + UINT32 src, dst, count; + incd = (sh2->m[0x63+4*dma] >> 14) & 3; + incs = (sh2->m[0x63+4*dma] >> 12) & 3; + size = (sh2->m[0x63+4*dma] >> 10) & 3; + if(incd == 3 || incs == 3) + { +// logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, sh2->m[0x63+4*dma]); + //bprintf(0, _T("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n"), incd, incs, size, sh2->m[0x63+4*dma]); + return; + } + src = sh2->m[0x60+4*dma]; + dst = sh2->m[0x61+4*dma]; + count = sh2->m[0x62+4*dma]; + if(!count) + count = 0x1000000; + +// LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, src, dst, count, sh2->m[0x63+4*dma], incs, incd, size)); + //bprintf(1, _T("DMA %d start %08x, %08x, %x, %04x, %d, %d, %d : %d cys from %d\n"), dma, src, dst, count, sh2->m[0x63+4*dma], incs, incd, size, 2*count+1, Sh2GetTotalCycles()); + + sh2->dma_timer_active[dma] = 1; + //timer_adjust(sh2->dma_timer[dma], ATTOTIME_IN_CYCLES(2*count+1, sh2->cpu_number), (sh2->cpu_number<<1)|dma, attotime_zero); + sh2->dma_timer_cycles[dma] = 2 * count + 1; + sh2->dma_timer_base[dma] = sh2_GetTotalCycles(); + + src &= AM; + dst &= AM; + + switch(size) + { + case 0: + for(;count > 0; count --) + { + if(incs == 2) + src --; + if(incd == 2) + dst --; + program_write_byte_32be(dst, program_read_byte_32be(src)); + if(incs == 1) + src ++; + if(incd == 1) + dst ++; + } + break; + case 1: + src &= ~1; + dst &= ~1; + for(;count > 0; count --) + { + if(incs == 2) + src -= 2; + if(incd == 2) + dst -= 2; + program_write_word_32be(dst, program_read_word_32be(src)); + if(incs == 1) + src += 2; + if(incd == 1) + dst += 2; + } + break; + case 2: + src &= ~3; + dst &= ~3; + for(;count > 0; count --) + { + if(incs == 2) + src -= 4; + if(incd == 2) + dst -= 4; + + //program_write_dword_32be(dst, program_read_dword_32be(src)); + WL(dst, RL(src)); + + if(incs == 1) + src += 4; + if(incd == 1) + dst += 4; + + } + break; + case 3: + src &= ~3; + dst &= ~3; + count &= ~3; + for(;count > 0; count -= 4) + { + if(incd == 2) + dst -= 16; + program_write_dword_32be(dst, program_read_dword_32be(src)); + program_write_dword_32be(dst+4, program_read_dword_32be(src+4)); + program_write_dword_32be(dst+8, program_read_dword_32be(src+8)); + program_write_dword_32be(dst+12, program_read_dword_32be(src+12)); + src += 16; + if(incd == 1) + dst += 16; + } + break; + } + } + } + else + { + if(sh2->dma_timer_active[dma]) + { +// logerror("SH2: DMA %d cancelled in-flight", dma); + //bprintf(0, _T("SH2: DMA %d cancelled in-flight"), dma); + //timer_adjust(sh2->dma_timer[dma], attotime_never, 0, attotime_zero); + sh2->dma_timer_active[dma] = 0; + + } + } +} + + +static void sh2_internal_w(UINT32 offset, UINT32 data, UINT32 mem_mask) +{ + UINT32 old = sh2->m[offset]; + COMBINE_DATA(sh2->m+offset); + + // if(offset != 0x20) + // logerror("sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask); + + switch( offset ) + { + // Timers + case 0x04: // TIER, FTCSR, FRC + if((mem_mask & 0x00ffffff) != 0xffffff) + sh2_timer_resync(); + //logerror("SH2.%d: TIER write %04x @ %04x\n", sh2->cpu_number, data >> 16, mem_mask>>16); + sh2->m[4] = (sh2->m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2->m[4] & (ICF|OCFA|OCFB|OVF)); + COMBINE_DATA(&sh2->frc); + if((mem_mask & 0x00ffffff) != 0xffffff) + sh2_timer_activate(); + sh2_recalc_irq(); + break; + case 0x05: // OCRx, TCR, TOCR + //logerror("SH2.%d: TCR write %08x @ %08x\n", sh2->cpu_number, data, mem_mask); + sh2_timer_resync(); + if(sh2->m[5] & 0x10) + sh2->ocrb = (sh2->ocrb & (mem_mask >> 16)) | ((data & ~mem_mask) >> 16); + else + sh2->ocra = (sh2->ocra & (mem_mask >> 16)) | ((data & ~mem_mask) >> 16); + sh2_timer_activate(); + break; + + case 0x06: // ICR + break; + + // Interrupt vectors + case 0x18: // IPRB, VCRA + case 0x19: // VCRB, VCRC + case 0x1a: // VCRD + sh2_recalc_irq(); + break; + + // DMA + case 0x1c: // DRCR0, DRCR1 + break; + + // Watchdog + case 0x20: // WTCNT, RSTCSR + break; + + // Standby and cache + case 0x24: // SBYCR, CCR + break; + + // Interrupt vectors cont. + case 0x38: // ICR, IRPA + break; + case 0x39: // VCRWDT + break; + + // Division box + case 0x40: // DVSR + break; + case 0x41: // DVDNT + { + INT32 a = sh2->m[0x41]; + INT32 b = sh2->m[0x40]; +// LOG(("SH2 #%d div+mod %d/%d\n", cpu_getactivecpu(), a, b)); + if (b) + { + sh2->m[0x45] = a / b; + sh2->m[0x44] = a % b; + } + else + { + sh2->m[0x42] |= 0x00010000; + sh2->m[0x45] = 0x7fffffff; + sh2->m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + break; + } + case 0x42: // DVCR + sh2->m[0x42] = (sh2->m[0x42] & ~0x00001000) | (old & sh2->m[0x42] & 0x00010000); + sh2_recalc_irq(); + break; + case 0x43: // VCRDIV + sh2_recalc_irq(); + break; + case 0x44: // DVDNTH + break; + case 0x45: // DVDNTL + { + INT64 a = sh2->m[0x45] | ((UINT64)(sh2->m[0x44]) << 32); + INT64 b = (INT32)sh2->m[0x40]; +// LOG(("SH2 #%d div+mod %lld/%lld\n", cpu_getactivecpu(), a, b)); + if (b) + { + INT64 q = a / b; + if (q != (INT32)q) + { + sh2->m[0x42] |= 0x00010000; + sh2->m[0x45] = 0x7fffffff; + sh2->m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + else + { + sh2->m[0x45] = q; + sh2->m[0x44] = a % b; + } + } + else + { + sh2->m[0x42] |= 0x00010000; + sh2->m[0x45] = 0x7fffffff; + sh2->m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + break; + } + + // DMA controller + case 0x60: // SAR0 + case 0x61: // DAR0 + break; + case 0x62: // DTCR0 + sh2->m[0x62] &= 0xffffff; + break; + case 0x63: // CHCR0 + sh2->m[0x63] = (sh2->m[0x63] & ~2) | (old & sh2->m[0x63] & 2); + sh2_dmac_check(0); + break; + case 0x64: // SAR1 + case 0x65: // DAR1 + break; + case 0x66: // DTCR1 + sh2->m[0x66] &= 0xffffff; + break; + case 0x67: // CHCR1 + sh2->m[0x67] = (sh2->m[0x67] & ~2) | (old & sh2->m[0x67] & 2); + sh2_dmac_check(1); + break; + case 0x68: // VCRDMA0 + case 0x6a: // VCRDMA1 + sh2_recalc_irq(); + break; + case 0x6c: // DMAOR + sh2->m[0x6c] = (sh2->m[0x6c] & ~6) | (old & sh2->m[0x6c] & 6); + sh2_dmac_check(0); + sh2_dmac_check(1); + break; + + // Bus controller + case 0x78: // BCR1 + case 0x79: // BCR2 + case 0x7a: // WCR + case 0x7b: // MCR + case 0x7c: // RTCSR + case 0x7d: // RTCNT + case 0x7e: // RTCOR + break; + + default: + //logerror("sh2_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfffffe00+offset*4, data, mem_mask); + break; + } +} + +static UINT32 sh2_internal_r(UINT32 offset, UINT32 /*mem_mask*/) +{ + // logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask); + //bprintf(0, _T("sh2_internal_r: Read %08x (%x) @ %08x\n"), 0xfffffe00+offset*4, offset, mem_mask); + + switch( offset ) + { + case 0x04: // TIER, FTCSR, FRC + sh2_timer_resync(); + return (sh2->m[4] & 0xffff0000) | sh2->frc; + case 0x05: // OCRx, TCR, TOCR + if(sh2->m[5] & 0x10) + return (sh2->ocrb << 16) | (sh2->m[5] & 0xffff); + else + return (sh2->ocra << 16) | (sh2->m[5] & 0xffff); + case 0x06: // ICR + return sh2->icr << 16; + + case 0x38: // ICR, IPRA +// return (sh2->m[0x38] & 0x7fffffff) | (sh2->nmi_line_state == ASSERT_LINE ? 0 : 0x80000000); + return (sh2->m[0x38] & 0x7fffffff) | 0x80000000; + + case 0x78: // BCR1 +// return sh2->is_slave ? 0x00008000 : 0; + return 0; + + case 0x41: // dvdntl mirrors + case 0x47: + return sh2->m[0x45]; + + case 0x46: // dvdnth mirror + return sh2->m[0x44]; + } + return sh2->m[offset]; +} + +// ------------------------------------------------------- + +#if USE_JUMPTABLE + +int Sh2Run(int cycles) +{ + sh2->sh2_icount = cycles; + sh2->sh2_cycles_to_run = cycles; + + do + { + if ( pSh2Ext->suspend ) { + sh2->sh2_total_cycles += cycles; + sh2->sh2_icount = 0; + break; + } + + UINT16 opcode; + + if (sh2->delay) { + //opcode = cpu_readop16(WORD_XOR_BE((UINT32)(sh2->delay & AM))); + opcode = cpu_readop16(sh2->delay & AM); + change_pc(sh2->pc & AM); + sh2->delay = 0; + } else { + //opcode = cpu_readop16(WORD_XOR_BE((UINT32)(sh2->pc & AM))); + opcode = cpu_readop16(sh2->pc & AM); + sh2->pc += 2; + } + + sh2->ppc = sh2->pc; + + opcode_jumptable[opcode](opcode); + + if(sh2->test_irq && !sh2->delay) + { + CHECK_PENDING_IRQ(/*"mame_sh2_execute"*/); + sh2->test_irq = 0; + } + + sh2->sh2_icount--; + + // timer check + + { + unsigned int cy = sh2_GetTotalCycles(); + + if (sh2->dma_timer_active[0]) + if ((cy - sh2->dma_timer_base[0]) >= sh2->dma_timer_cycles[0]) + sh2_dmac_callback(0); + + if (sh2->dma_timer_active[1]) + if ((cy - sh2->dma_timer_base[1]) >= sh2->dma_timer_cycles[1]) + sh2_dmac_callback(1); + + if ( sh2->timer_active ) + if ((cy - sh2->timer_base) >= sh2->timer_cycles) + sh2_timer_callback(); + } + + + } while( sh2->sh2_icount > 0 ); + + sh2->cycle_counts += cycles - (UINT32)sh2->sh2_icount; + + return cycles - sh2->sh2_icount; +} + +#else + +int Sh2Run(int cycles) +{ + sh2->sh2_icount = cycles; + sh2->sh2_cycles_to_run = cycles; + + do + { + + if ( pSh2Ext->suspend ) { + sh2->sh2_total_cycles += cycles; + sh2->sh2_icount = 0; + break; + } + + UINT16 opcode; + + if (sh2->delay) { + //opcode = cpu_readop16(WORD_XOR_BE((UINT32)(sh2->delay & AM))); + opcode = cpu_readop16(sh2->delay & AM); + change_pc(sh2->pc & AM); + sh2->delay = 0; + } else { + //opcode = cpu_readop16(WORD_XOR_BE((UINT32)(sh2->pc & AM))); + opcode = cpu_readop16(sh2->pc & AM); + sh2->pc += 2; + } + + sh2->ppc = sh2->pc; + + switch (opcode & ( 15 << 12)) + { + case 0<<12: op0000(opcode); break; + case 1<<12: op0001(opcode); break; + case 2<<12: op0010(opcode); break; + case 3<<12: op0011(opcode); break; + case 4<<12: op0100(opcode); break; + case 5<<12: op0101(opcode); break; + case 6<<12: op0110(opcode); break; + case 7<<12: op0111(opcode); break; + case 8<<12: op1000(opcode); break; + case 9<<12: op1001(opcode); break; + case 10<<12: op1010(opcode); break; + case 11<<12: op1011(opcode); break; + case 12<<12: op1100(opcode); break; + case 13<<12: op1101(opcode); break; + case 14<<12: op1110(opcode); break; + default: op1111(opcode); break; + } + +#endif + + if(sh2->test_irq && !sh2->delay) + { + CHECK_PENDING_IRQ(/*"mame_sh2_execute"*/); + sh2->test_irq = 0; + } + + sh2->sh2_total_cycles++; + sh2->sh2_icount--; + + // timer check + + { + unsigned int cy = sh2_GetTotalCycles(); + + + if (sh2->dma_timer_active[0]) + if ((cy - sh2->dma_timer_base[0]) >= sh2->dma_timer_cycles[0]) + sh2_dmac_callback(0); + + if (sh2->dma_timer_active[1]) + if ((cy - sh2->dma_timer_base[1]) >= sh2->dma_timer_cycles[1]) + sh2_dmac_callback(1); + + if ( sh2->timer_active ) + if ((cy - sh2->timer_base) >= sh2->timer_cycles) + sh2_timer_callback(); + } + + + } while( sh2->sh2_icount > 0 ); + + sh2->cycle_counts += cycles - (UINT32)sh2->sh2_icount; + + sh2->sh2_cycles_to_run = sh2->sh2_icount; + + return cycles - sh2->sh2_icount; +} + +void Sh2SetIRQLine(const int line, const int state) +{ + if (sh2->irq_line_state[line] == state) return; + sh2->irq_line_state[line] = state; + + if( state == SH2_IRQSTATUS_NONE ) { + // LOG(("SH-2 #%d cleared irq #%d\n", cpu_getactivecpu(), line)); + sh2->pending_irq &= ~(1 << line); + } else { + //LOG(("SH-2 #%d assert irq #%d\n", cpu_getactivecpu(), line)); + sh2->pending_irq |= 1 << line; + if(sh2->delay) + sh2->test_irq = 1; + else + CHECK_PENDING_IRQ(/*"sh2_set_irq_line"*/); + + pSh2Ext->suspend = 0; + } + +} + +unsigned int Sh2GetPC(int) +{ + return (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); +} + +void Sh2SetVBR(unsigned int i) +{ + sh2->vbr = i; +} + +void Sh2BurnUntilInt(int) +{ + pSh2Ext->suspend = 1; +} + +void Sh2StopRun() +{ + sh2->sh2_total_cycles += sh2->sh2_icount; + sh2->sh2_icount = 0; + sh2->sh2_cycles_to_run = 0; +} + +int Sh2TotalCycles() +{ + return sh2->sh2_total_cycles; +} + +void Sh2NewFrame() +{ + sh2->sh2_total_cycles = 0; +} + +void Sh2BurnCycles(int cycles) +{ + sh2->sh2_icount -= cycles; + sh2->sh2_total_cycles += cycles; +} + +void __fastcall Sh2WriteByte(unsigned int a, unsigned char d) +{ + WB(a, d); +} + + +unsigned char __fastcall Sh2ReadByte(unsigned int a) +{ + return RB(a); +} + +#include "state.h" + +int Sh2Scan(int nAction) +{ + if (nAction & ACB_DRIVER_DATA) { + + char szText[] = "SH2 #0"; + + for (int i = 0; i < 1 /*nCPUCount*/; i++) { + szText[5] = '1' + i; + ScanVar(& ( Sh2Ext[i].sh2 ), sizeof(SH2) - 4, szText); + + SCAN_VAR (Sh2Ext[i].suspend); + SCAN_VAR (Sh2Ext[i].opbase); + +#if FAST_OP_FETCH + // Sh2Ext[i].opbase + if (nAction & ACB_WRITE) { + change_pc(sh2->pc & AM); + } +#endif + } + + } + + return 0; +} + diff --git a/src/cpu/sh2/sh2.h b/src/cpu/sh2/sh2.h new file mode 100644 index 00000000..3d8ed345 --- /dev/null +++ b/src/cpu/sh2/sh2.h @@ -0,0 +1,55 @@ + +#ifndef FASTCALL + #undef __fastcall + #define __fastcall +#endif + +typedef unsigned char (__fastcall *pSh2ReadByteHandler)(unsigned int a); +typedef void (__fastcall *pSh2WriteByteHandler)(unsigned int a, unsigned char d); +typedef unsigned short (__fastcall *pSh2ReadWordHandler)(unsigned int a); +typedef void (__fastcall *pSh2WriteWordHandler)(unsigned int a, unsigned short d); +typedef unsigned int (__fastcall *pSh2ReadLongHandler)(unsigned int a); +typedef void (__fastcall *pSh2WriteLongHandler)(unsigned int a, unsigned int d); + +extern int has_sh2; +void __fastcall Sh2WriteByte(unsigned int a, unsigned char d); +unsigned char __fastcall Sh2ReadByte(unsigned int a); + +int Sh2Init(int nCount); +int Sh2Exit(); + +void Sh2Open(const int i); +void Sh2Close(); +int Sh2GetActive(); + +void Sh2Reset(unsigned int pc, unsigned r15); +int Sh2Run(int cycles); + +int Sh2MapMemory(unsigned char* pMemory, unsigned int nStart, unsigned int nEnd, int nType); +int Sh2MapHandler(uintptr_t nHandler, unsigned int nStart, unsigned int nEnd, int nType); + +int Sh2SetReadByteHandler(int i, pSh2ReadByteHandler pHandler); +int Sh2SetWriteByteHandler(int i, pSh2WriteByteHandler pHandler); +int Sh2SetReadWordHandler(int i, pSh2ReadWordHandler pHandler); +int Sh2SetWriteWordHandler(int i, pSh2WriteWordHandler pHandler); +int Sh2SetReadLongHandler(int i, pSh2ReadLongHandler pHandler); +int Sh2SetWriteLongHandler(int i, pSh2WriteLongHandler pHandler); + +#define SH2_IRQSTATUS_NONE (0x00) +#define SH2_IRQSTATUS_AUTO (0x01) +//#define SH2_IRQSTATUS_ACK (0x02) + +void Sh2SetIRQLine(const int line, const int state); + +unsigned int Sh2GetPC(int n); +void Sh2StopRun(); +void Sh2SetVBR(unsigned int i); + +void Sh2BurnUntilInt(int); + +int Sh2TotalCycles(); +void Sh2NewFrame(); +void Sh2BurnCycles(int cycles); + +int Sh2Scan(int); + diff --git a/src/cpu/vez.cpp b/src/cpu/vez.cpp new file mode 100644 index 00000000..1de40984 --- /dev/null +++ b/src/cpu/vez.cpp @@ -0,0 +1,392 @@ +// Nec V20/V30/V33/V25/V35 interface +// Written by OopsWare +// http://oopsware.googlepages.com +// Heavily modified by iq_132 (Nov, 2011) + +#include "burnint.h" +#include "vez.h" + +//---------------------------------------------------------------------------------- +// nec.cpp +void necInit(INT32 cpu, INT32 type); +void necCpuOpen(INT32 cpu); +void necCpuClose(); +INT32 nec_reset(); +INT32 nec_execute(INT32 cycles); +void nec_set_irq_line_and_vector(INT32 irqline, INT32 vector, INT32 state); +UINT32 nec_total_cycles(); +void nec_new_frame(); +INT32 necGetPC(INT32 n); +void necScan(INT32 cpu, INT32 nAction); +void necRunEnd(); +void necIdle(INT32 cycles); + +// v25.cpp +INT32 v25_reset(); +void v25_open(INT32 cpu); +void v25_close(); +void v25_set_irq_line_and_vector(INT32 irqline, INT32 vector, INT32 state); +INT32 v25_execute(INT32 cycles); +void v25Init(INT32 cpu, INT32 type, INT32 clock); +void v25_set_decode(UINT8 *table); +UINT32 v25_total_cycles(); +void v25_new_frame(); +INT32 v25GetPC(INT32 n); +void v25Scan(INT32 cpu, INT32 nAction); +void v25RunEnd(); +void v25Idle(INT32 cycles); + +//---------------------------------------------------------------------------------- + +struct VezContext { + void (*cpu_open)(INT32); + void (*cpu_close)(); + INT32 (*cpu_reset)(); + INT32 (*cpu_execute)(INT32); + void (*cpu_set_irq_line)(INT32, INT32, INT32); + void (*decode)(UINT8*); + UINT32 (*total_cycles)(); + INT32 (*get_pc)(INT32); + void (*scan)(INT32, INT32); + void (*runend)(); + void (*idle)(INT32); + + UINT8 * ppMemRead[512]; + UINT8 * ppMemWrite[512]; + UINT8 * ppMemFetch[512]; + UINT8 * ppMemFetchData[512]; + + // Handlers + #ifdef FASTCALL + UINT8 (__fastcall *ReadHandler)(UINT32 a); + void (__fastcall *WriteHandler)(UINT32 a, UINT8 d); + UINT8 (__fastcall *ReadPort)(UINT32 a); + void (__fastcall *WritePort)(UINT32 a, UINT8 d); + #else + UINT8 (__cdecl *ReadHandler)(UINT32 a); + void (__cdecl *WriteHandler)(UINT32 a, UINT8 d); + UINT8 (__cdecl *ReadPort)(UINT32 a); + void (__cdecl *WritePort)(UINT32 a, UINT8 d); + #endif +}; + +static struct VezContext VezCPUContext[4]; +struct VezContext *VezCurrentCPU = 0; + +#define VEZ_MEM_SHIFT 11 +#define VEZ_MEM_MASK ((1 << VEZ_MEM_SHIFT) - 1) + +static INT32 nCPUCount = 0; +static INT32 nOpenedCPU = -1; +INT32 nVezCount; + +UINT8 __fastcall VezDummyReadHandler(UINT32) { return 0; } +void __fastcall VezDummyWriteHandler(UINT32, UINT8) { } +UINT8 __fastcall VezDummyReadPort(UINT32) { return 0; } +void __fastcall VezDummyWritePort(UINT32, UINT8) { } + +UINT8 cpu_readport(UINT32 p) +{ + p &= 0x100ff; // ? + + return VezCurrentCPU->ReadPort(p); +} + +void cpu_writeport(UINT32 p,UINT32 d) +{ + VezCurrentCPU->WritePort(p, d); +} + +UINT8 cpu_readmem20(UINT32 a) +{ + a &= 0xFFFFF; + + UINT8 * p = VezCurrentCPU->ppMemRead[ a >> VEZ_MEM_SHIFT ]; + if ( p ) + return *(p + a); + else + return VezCurrentCPU->ReadHandler(a); +} + +UINT8 cpu_readmem20_op(UINT32 a) +{ + a &= 0xFFFFF; + + UINT8 * p = VezCurrentCPU->ppMemFetch[ a >> VEZ_MEM_SHIFT ]; + if ( p ) + return *(p + a); + else + return VezCurrentCPU->ReadHandler(a); +} + +UINT8 cpu_readmem20_arg(UINT32 a) +{ + a &= 0xFFFFF; + + UINT8 * p = VezCurrentCPU->ppMemFetchData[ a >> VEZ_MEM_SHIFT ]; + if ( p ) + return *(p + a); + else + return VezCurrentCPU->ReadHandler(a); +} + +void cpu_writemem20(UINT32 a, UINT8 d) +{ + a &= 0xFFFFF; + + UINT8 * p = VezCurrentCPU->ppMemWrite[ a >> VEZ_MEM_SHIFT ]; + if ( p ) + *(p + a) = d; + else + VezCurrentCPU->WriteHandler(a, d); +} + +void VezSetReadHandler(UINT8 (__fastcall *pHandler)(UINT32)) +{ + VezCurrentCPU->ReadHandler = pHandler; +} + +void VezSetWriteHandler(void (__fastcall *pHandler)(UINT32, UINT8)) +{ + VezCurrentCPU->WriteHandler = pHandler; +} + +void VezSetReadPort(UINT8 (__fastcall *pHandler)(UINT32)) +{ + VezCurrentCPU->ReadPort = pHandler; +} + +void VezSetWritePort(void (__fastcall *pHandler)(UINT32, UINT8)) +{ + VezCurrentCPU->WritePort = pHandler; +} + +void VezSetDecode(UINT8 *table) +{ + if (VezCurrentCPU->decode) { + VezCurrentCPU->decode(table); + } +} + +INT32 VezInit(INT32 cpu, INT32 type, INT32 clock) +{ + nOpenedCPU = cpu; + VezCurrentCPU = &VezCPUContext[cpu]; + + memset(VezCurrentCPU, 0, sizeof(struct VezContext)); + + switch (type) + { + case V20_TYPE: + case V30_TYPE: + case V33_TYPE: + { + necInit(cpu, type); + + VezCurrentCPU->cpu_open = necCpuOpen; + VezCurrentCPU->cpu_close = necCpuClose; + VezCurrentCPU->cpu_reset = nec_reset; + VezCurrentCPU->cpu_execute = nec_execute; + VezCurrentCPU->cpu_set_irq_line = nec_set_irq_line_and_vector; + VezCurrentCPU->decode = NULL; // ? + VezCurrentCPU->total_cycles = nec_total_cycles; + VezCurrentCPU->get_pc = necGetPC; + VezCurrentCPU->scan = necScan; + VezCurrentCPU->runend = necRunEnd; + VezCurrentCPU->idle = necIdle; + } + break; + + case V25_TYPE: + case V35_TYPE: + { + v25Init(cpu, type&0xff, clock); + + VezCurrentCPU->cpu_open = v25_open; + VezCurrentCPU->cpu_close = v25_close; + VezCurrentCPU->cpu_reset = v25_reset; + VezCurrentCPU->cpu_execute = v25_execute; + VezCurrentCPU->cpu_set_irq_line = v25_set_irq_line_and_vector; + VezCurrentCPU->decode = v25_set_decode; + VezCurrentCPU->total_cycles = v25_total_cycles; + VezCurrentCPU->get_pc = v25GetPC; + VezCurrentCPU->scan = v25Scan; + VezCurrentCPU->runend = v25RunEnd; + VezCurrentCPU->idle = v25Idle; + + } + break; + } + + VezCurrentCPU->ReadHandler = VezDummyReadHandler; + VezCurrentCPU->WriteHandler = VezDummyWriteHandler; + VezCurrentCPU->ReadPort = VezDummyReadPort; + VezCurrentCPU->WritePort = VezDummyWritePort; + + INT32 nCount = nVezCount+1; + + nVezCount = nCPUCount = nCount; + + CpuCheatRegister(0x0001, cpu); + + return 0; +} + +INT32 VezInit(INT32 cpu, INT32 type) +{ + return VezInit(cpu, type, 0); +} + +void VezExit() +{ + nCPUCount = 0; + nOpenedCPU = -1; + nVezCount = 0; + + nOpenedCPU = -1; +} + +void VezOpen(INT32 nCPU) +{ + nOpenedCPU = nCPU; + VezCurrentCPU = &VezCPUContext[nCPU]; + VezCurrentCPU->cpu_open(nCPU); +} + +void VezClose() +{ + nOpenedCPU = -1; + VezCurrentCPU->cpu_close(); + VezCurrentCPU = 0; +} + +void VezNewFrame() +{ + // should be separated? + v25_new_frame(); + nec_new_frame(); +} + +void VezRunEnd() +{ + VezCurrentCPU->runend(); +} + +void VezIdle(INT32 cycles) +{ + VezCurrentCPU->idle(cycles); +} + +UINT32 VezTotalCycles() +{ + return VezCurrentCPU->total_cycles(); +} + +INT32 VezGetActive() +{ + return nOpenedCPU; +} + +INT32 VezMemCallback(INT32 nStart,INT32 nEnd,INT32 nMode) +{ + nStart >>= VEZ_MEM_SHIFT; + nEnd += VEZ_MEM_MASK; + nEnd >>= VEZ_MEM_SHIFT; + + for (INT32 i = nStart; i < nEnd; i++) { + switch (nMode) { + case 0: + VezCurrentCPU->ppMemRead[i] = NULL; + break; + case 1: + VezCurrentCPU->ppMemWrite[i] = NULL; + break; + case 2: + VezCurrentCPU->ppMemFetch[i] = NULL; + VezCurrentCPU->ppMemFetchData[i] = NULL; + break; + } + } + return 0; +} + +INT32 VezMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem) +{ + INT32 s = nStart >> VEZ_MEM_SHIFT; + INT32 e = (nEnd + VEZ_MEM_MASK) >> VEZ_MEM_SHIFT; + + for (INT32 i = s; i < e; i++) { + switch (nMode) { + case 0: + VezCurrentCPU->ppMemRead[i] = Mem - nStart; + break; + case 1: + VezCurrentCPU->ppMemWrite[i] = Mem - nStart; + break; + case 2: + VezCurrentCPU->ppMemFetch[i] = Mem - nStart; + VezCurrentCPU->ppMemFetchData[i] = Mem - nStart; + break; + } + } + + return 0; +} + +INT32 VezMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem1, UINT8 *Mem2) +{ + INT32 s = nStart >> VEZ_MEM_SHIFT; + INT32 e = (nEnd + VEZ_MEM_MASK) >> VEZ_MEM_SHIFT; + + if (nMode != 2) return 1; + + for (INT32 i = s; i < e; i++) { + VezCurrentCPU->ppMemFetch[i] = Mem1 - nStart; + VezCurrentCPU->ppMemFetchData[i] = Mem2 - nStart; + } + return 0; +} + +INT32 VezReset() +{ + return VezCurrentCPU->cpu_reset(); +} + +INT32 VezRun(INT32 nCycles) +{ + if (nCycles <= 0) return 0; + + return VezCurrentCPU->cpu_execute(nCycles); +} + +INT32 VezPc(INT32 n) +{ + if (n == -1) { + return VezCurrentCPU->get_pc(-1); + } else { + struct VezContext *CPU = &VezCPUContext[n]; + return CPU->get_pc(n); + } + + return 0; +} + +INT32 VezScan(INT32 nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) + return 0; + + for (INT32 i = 0; i < nCPUCount; i++) { + struct VezContext *CPU = &VezCPUContext[i]; + if (CPU->scan) { + CPU->scan(i, nAction); + } + } + + return 0; +} + +void VezSetIRQLineAndVector(const INT32 line, const INT32 vector, const INT32 status) +{ + VezCurrentCPU->cpu_set_irq_line(line, vector, status); +} diff --git a/src/cpu/vez.h b/src/cpu/vez.h new file mode 100644 index 00000000..e660af5c --- /dev/null +++ b/src/cpu/vez.h @@ -0,0 +1,60 @@ +// Nec V20/V30/V33 interface + +#define V33_TYPE 0 +#define V30_TYPE 8 +#define V20_TYPE 16 +#define V25_TYPE (V20_TYPE|(1<<16)) +#define V35_TYPE (V30_TYPE|(1<<16)) + +UINT8 cpu_readmem20(UINT32 a); +void cpu_writemem20(UINT32 a, UINT8 d); + +extern INT32 nVezCount; + +UINT32 VezTotalCycles(); +void VezNewFrame(); +void VezRunEnd(); +void VezIdle(INT32 cycles); + +INT32 VezInit(INT32 nCPU, INT32 type, INT32 clock); // v20/v25/v30/v33/v35 +INT32 VezInit(INT32 cpu, INT32 type); // v20/v30/v33 only +void VezExit(); +void VezOpen(INT32 nCPU); +void VezClose(); +INT32 VezGetActive(); + +void VezSetDecode(UINT8 *decode); // set opcode decode + +INT32 VezMemCallback(INT32 nStart,INT32 nEnd,INT32 nMode); +INT32 VezMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem); +INT32 VezMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem1, UINT8 *Mem2); + +void VezSetReadHandler(UINT8 (__fastcall *)(UINT32)); +void VezSetWriteHandler(void (__fastcall *)(UINT32, UINT8)); + +#define V25_PORT_P0 0x10000 +#define V25_PORT_P1 0x10002 +#define V25_PORT_P2 0x10004 +#define V25_PORT_PT 0x10006 + +void VezSetReadPort(UINT8 (__fastcall *)(UINT32)); +void VezSetWritePort(void (__fastcall *)(UINT32, UINT8)); +void VezSetIrqCallBack(INT32 (*cb)(INT32)); + +INT32 VezReset(); +INT32 VezPc(INT32 n); +INT32 VezScan(INT32 nAction); + +INT32 VezRun(INT32 nCycles); + +#define NEC_INPUT_LINE_INTP0 10 +#define NEC_INPUT_LINE_INTP1 11 +#define NEC_INPUT_LINE_INTP2 12 +#define NEC_INPUT_LINE_POLL 20 + +#define VEZ_IRQSTATUS_NONE 0 +#define VEZ_IRQSTATUS_ACK 1 +//#define VEZ_IRQSTATUS_AUTO 2 // unimplemented + +void VezSetIRQLineAndVector(const INT32 line, const INT32 vector, const INT32 status); + diff --git a/src/cpu/z80/z80.cpp b/src/cpu/z80/z80.cpp new file mode 100644 index 00000000..db11a529 --- /dev/null +++ b/src/cpu/z80/z80.cpp @@ -0,0 +1,4095 @@ +/***************************************************************************** + * + * z80.c + * Portable Z80 emulator V3.5 + * + * Copyright Juergen Buchmueller, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * Changes in 3.7 [Aaron Giles] + * - Changed NMI handling. NMIs are now latched in set_irq_state + * but are not taken there. Instead they are taken at the start of the + * execute loop. + * - Changed IRQ handling. IRQ state is set in set_irq_state but not taken + * except during the inner execute loop. + * - Removed x86 assembly hacks and obsolete timing loop catchers. + * Changes in 3.6 + * - Got rid of the code that would inexactly emulate a Z80, i.e. removed + * all the #if Z80_EXACT #else branches. + * - Removed leading underscores from local register name shortcuts as + * this violates the C99 standard. + * - Renamed the registers inside the Z80 context to lower case to avoid + * ambiguities (shortcuts would have had the same names as the fields + * of the structure). + * Changes in 3.5 + * - Implemented OTIR, INIR, etc. without look-up table for PF flag. + * [Ramsoft, Sean Young] + * Changes in 3.4 + * - Removed Z80-MSX specific code as it's not needed any more. + * - Implemented DAA without look-up table [Ramsoft, Sean Young] + * Changes in 3.3 + * - Fixed undocumented flags XF & YF in the non-asm versions of CP, + * and all the 16 bit arithmetic instructions. [Sean Young] + * Changes in 3.2 + * - Fixed undocumented flags XF & YF of RRCA, and CF and HF of + * INI/IND/OUTI/OUTD/INIR/INDR/OTIR/OTDR [Sean Young] + * Changes in 3.1 + * - removed the REPEAT_AT_ONCE execution of LDIR/CPIR etc. opcodes + * for readabilities sake and because the implementation was buggy + * (and I was not able to find the difference) + * Changes in 3.0 + * - 'finished' switch to dynamically overrideable cycle count tables + * Changes in 2.9: + * - added methods to access and override the cycle count tables + * - fixed handling and timing of multiple DD/FD prefixed opcodes + * Changes in 2.8: + * - OUTI/OUTD/OTIR/OTDR also pre-decrement the B register now. + * This was wrong because of a bug fix on the wrong side + * (astrocade sound driver). + * Changes in 2.7: + * - removed z80_vm specific code, it's not needed (and never was). + * Changes in 2.6: + * - BUSY_LOOP_HACKS needed to call change_pc() earlier, before + * checking the opcodes at the new address, because otherwise they + * might access the old (wrong or even NULL) banked memory region. + * Thanks to Sean Young for finding this nasty bug. + * Changes in 2.5: + * - Burning cycles always adjusts the ICount by a multiple of 4. + * - In REPEAT_AT_ONCE cases the R register wasn't incremented twice + * per repetition as it should have been. Those repeated opcodes + * could also underflow the ICount. + * - Simplified TIME_LOOP_HACKS for BC and added two more for DE + HL + * timing loops. I think those hacks weren't endian safe before too. + * Changes in 2.4: + * - z80_reset zaps the entire context, sets IX and IY to 0xffff(!) and + * sets the Z flag. With these changes the Tehkan World Cup driver + * _seems_ to work again. + * Changes in 2.3: + * - External termination of the execution loop calls z80_burn() and + * z80_vm_burn() to burn an amount of cycles (R adjustment) + * - Shortcuts which burn CPU cycles (BUSY_LOOP_HACKS and TIME_LOOP_HACKS) + * now also adjust the R register depending on the skipped opcodes. + * Changes in 2.2: + * - Fixed bugs in CPL, SCF and CCF instructions flag handling. + * - Changed variable EA and ARG16() function to UINT32; this + * produces slightly more efficient code. + * - The DD/FD XY CB opcodes where XY is 40-7F and Y is not 6/E + * are changed to calls to the X6/XE opcodes to reduce object size. + * They're hardly ever used so this should not yield a speed penalty. + * New in 2.0: + * - Optional more exact Z80 emulation (#define Z80_EXACT 1) according + * to a detailed description by Sean Young which can be found at: + * http://www.msxnet.org/tech/z80-documented.pdf + *****************************************************************************/ + +#include "burnint.h" +#include "z80.h" +#include "z80daisy.h" + +#define FALSE 0 +#define TRUE 1 +#define Z80_INLINE static +#define change_pc(newpc) Z80.pc.w.l = (newpc) + +static Z80ReadIoHandler Z80IORead; +static Z80WriteIoHandler Z80IOWrite; +static Z80ReadProgHandler Z80ProgramRead; +static Z80WriteProgHandler Z80ProgramWrite; +static Z80ReadOpHandler Z80CPUReadOp; +static Z80ReadOpArgHandler Z80CPUReadOpArg; + +unsigned char Z80Vector = 0; + +#define VERBOSE 0 + +#define LOG(x) //do { if (VERBOSE) logerror x; } while (0) + +/* execute main opcodes inside a big switch statement */ +#ifndef BIG_SWITCH +#define BIG_SWITCH 1 +#endif + +/* big flags array for ADD/ADC/SUB/SBC/CP results */ +#define BIG_FLAGS_ARRAY 1 + +/* on JP and JR opcodes check for tight loops */ +#define BUSY_LOOP_HACKS 1 + + +/****************************************************************************/ +/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */ +/* register is calculated as follows: refresh=(Z80.r&127)|(Z80.r2&128) */ +/****************************************************************************/ +#define CF 0x01 +#define NF 0x02 +#define PF 0x04 +#define VF PF +#define XF 0x08 +#define HF 0x10 +#define YF 0x20 +#define ZF 0x40 +#define SF 0x80 + +#define INT_IRQ 0x01 +#define NMI_IRQ 0x02 + +#define PRVPC Z80.prvpc.d /* previous program counter */ + +#define PCD Z80.pc.d +#define PC Z80.pc.w.l + +#define SPD Z80.sp.d +#define SP Z80.sp.w.l + +#define AFD Z80.af.d +#define AF Z80.af.w.l +#define A Z80.af.b.h +#define F Z80.af.b.l + +#define BCD Z80.bc.d +#define BC Z80.bc.w.l +#define B Z80.bc.b.h +#define C Z80.bc.b.l + +#define DED Z80.de.d +#define DE Z80.de.w.l +#define D Z80.de.b.h +#define E Z80.de.b.l + +#define HLD Z80.hl.d +#define HL Z80.hl.w.l +#define H Z80.hl.b.h +#define L Z80.hl.b.l + +#define IXD Z80.ix.d +#define IX Z80.ix.w.l +#define HX Z80.ix.b.h +#define LX Z80.ix.b.l + +#define IYD Z80.iy.d +#define IY Z80.iy.w.l +#define HY Z80.iy.b.h +#define LY Z80.iy.b.l + +#define I Z80.i +#define R Z80.r +#define R2 Z80.r2 +#define IM Z80.im +#define IFF1 Z80.iff1 +#define IFF2 Z80.iff2 +#define HALT Z80.halt + +int z80_ICount; +static Z80_Regs Z80; +UINT32 EA; + +static UINT8 SZ[256]; /* zero and sign flags */ +static UINT8 SZ_BIT[256]; /* zero, sign and parity/overflow (=zero) flags for BIT opcode */ +static UINT8 SZP[256]; /* zero, sign and parity flags */ +static UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */ +static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */ + +#if BIG_FLAGS_ARRAY +static UINT8 *SZHVC_add = 0; +static UINT8 *SZHVC_sub = 0; +#endif + +static const UINT8 cc_op[0x100] = { + 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, + 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, + 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, + 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, + 5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11, + 5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11, + 5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11, + 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11}; + +static const UINT8 cc_cb[0x100] = { + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, + 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8}; + +static const UINT8 cc_ed[0x100] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9, +12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9, +12,12,15,20, 8,14, 8,18,12,12,15,20, 8,14, 8,18, +12,12,15,20, 8,14, 8, 8,12,12,15,20, 8,14, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8, +16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UINT8 cc_xy[0x100] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4,14,20,10, 9, 9, 9, 4, 4,15,20,10, 9, 9, 9, 4, + 4, 4, 4, 4,23,23,19, 4, 4,15, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9, +19,19,19,19,19,19, 4,19, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4,14, 4,23, 4,15, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4,10, 4, 4, 4, 4, 4, 4}; + +static const UINT8 cc_xycb[0x100] = { +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, +23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23}; + +/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */ +static const UINT8 cc_ex[0x100] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */ + 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */ + 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */ + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2, + 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2}; + +static const UINT8 *cc[6]; +#define Z80_TABLE_dd Z80_TABLE_xy +#define Z80_TABLE_fd Z80_TABLE_xy + +static void take_interrupt(void); +//void Z80Burn(int cycles); + +typedef void (*funcptr)(void); + +#define PROTOTYPES(tablename,prefix) \ + Z80_INLINE void prefix##_00(void); Z80_INLINE void prefix##_01(void); Z80_INLINE void prefix##_02(void); Z80_INLINE void prefix##_03(void); \ + Z80_INLINE void prefix##_04(void); Z80_INLINE void prefix##_05(void); Z80_INLINE void prefix##_06(void); Z80_INLINE void prefix##_07(void); \ + Z80_INLINE void prefix##_08(void); Z80_INLINE void prefix##_09(void); Z80_INLINE void prefix##_0a(void); Z80_INLINE void prefix##_0b(void); \ + Z80_INLINE void prefix##_0c(void); Z80_INLINE void prefix##_0d(void); Z80_INLINE void prefix##_0e(void); Z80_INLINE void prefix##_0f(void); \ + Z80_INLINE void prefix##_10(void); Z80_INLINE void prefix##_11(void); Z80_INLINE void prefix##_12(void); Z80_INLINE void prefix##_13(void); \ + Z80_INLINE void prefix##_14(void); Z80_INLINE void prefix##_15(void); Z80_INLINE void prefix##_16(void); Z80_INLINE void prefix##_17(void); \ + Z80_INLINE void prefix##_18(void); Z80_INLINE void prefix##_19(void); Z80_INLINE void prefix##_1a(void); Z80_INLINE void prefix##_1b(void); \ + Z80_INLINE void prefix##_1c(void); Z80_INLINE void prefix##_1d(void); Z80_INLINE void prefix##_1e(void); Z80_INLINE void prefix##_1f(void); \ + Z80_INLINE void prefix##_20(void); Z80_INLINE void prefix##_21(void); Z80_INLINE void prefix##_22(void); Z80_INLINE void prefix##_23(void); \ + Z80_INLINE void prefix##_24(void); Z80_INLINE void prefix##_25(void); Z80_INLINE void prefix##_26(void); Z80_INLINE void prefix##_27(void); \ + Z80_INLINE void prefix##_28(void); Z80_INLINE void prefix##_29(void); Z80_INLINE void prefix##_2a(void); Z80_INLINE void prefix##_2b(void); \ + Z80_INLINE void prefix##_2c(void); Z80_INLINE void prefix##_2d(void); Z80_INLINE void prefix##_2e(void); Z80_INLINE void prefix##_2f(void); \ + Z80_INLINE void prefix##_30(void); Z80_INLINE void prefix##_31(void); Z80_INLINE void prefix##_32(void); Z80_INLINE void prefix##_33(void); \ + Z80_INLINE void prefix##_34(void); Z80_INLINE void prefix##_35(void); Z80_INLINE void prefix##_36(void); Z80_INLINE void prefix##_37(void); \ + Z80_INLINE void prefix##_38(void); Z80_INLINE void prefix##_39(void); Z80_INLINE void prefix##_3a(void); Z80_INLINE void prefix##_3b(void); \ + Z80_INLINE void prefix##_3c(void); Z80_INLINE void prefix##_3d(void); Z80_INLINE void prefix##_3e(void); Z80_INLINE void prefix##_3f(void); \ + Z80_INLINE void prefix##_40(void); Z80_INLINE void prefix##_41(void); Z80_INLINE void prefix##_42(void); Z80_INLINE void prefix##_43(void); \ + Z80_INLINE void prefix##_44(void); Z80_INLINE void prefix##_45(void); Z80_INLINE void prefix##_46(void); Z80_INLINE void prefix##_47(void); \ + Z80_INLINE void prefix##_48(void); Z80_INLINE void prefix##_49(void); Z80_INLINE void prefix##_4a(void); Z80_INLINE void prefix##_4b(void); \ + Z80_INLINE void prefix##_4c(void); Z80_INLINE void prefix##_4d(void); Z80_INLINE void prefix##_4e(void); Z80_INLINE void prefix##_4f(void); \ + Z80_INLINE void prefix##_50(void); Z80_INLINE void prefix##_51(void); Z80_INLINE void prefix##_52(void); Z80_INLINE void prefix##_53(void); \ + Z80_INLINE void prefix##_54(void); Z80_INLINE void prefix##_55(void); Z80_INLINE void prefix##_56(void); Z80_INLINE void prefix##_57(void); \ + Z80_INLINE void prefix##_58(void); Z80_INLINE void prefix##_59(void); Z80_INLINE void prefix##_5a(void); Z80_INLINE void prefix##_5b(void); \ + Z80_INLINE void prefix##_5c(void); Z80_INLINE void prefix##_5d(void); Z80_INLINE void prefix##_5e(void); Z80_INLINE void prefix##_5f(void); \ + Z80_INLINE void prefix##_60(void); Z80_INLINE void prefix##_61(void); Z80_INLINE void prefix##_62(void); Z80_INLINE void prefix##_63(void); \ + Z80_INLINE void prefix##_64(void); Z80_INLINE void prefix##_65(void); Z80_INLINE void prefix##_66(void); Z80_INLINE void prefix##_67(void); \ + Z80_INLINE void prefix##_68(void); Z80_INLINE void prefix##_69(void); Z80_INLINE void prefix##_6a(void); Z80_INLINE void prefix##_6b(void); \ + Z80_INLINE void prefix##_6c(void); Z80_INLINE void prefix##_6d(void); Z80_INLINE void prefix##_6e(void); Z80_INLINE void prefix##_6f(void); \ + Z80_INLINE void prefix##_70(void); Z80_INLINE void prefix##_71(void); Z80_INLINE void prefix##_72(void); Z80_INLINE void prefix##_73(void); \ + Z80_INLINE void prefix##_74(void); Z80_INLINE void prefix##_75(void); Z80_INLINE void prefix##_76(void); Z80_INLINE void prefix##_77(void); \ + Z80_INLINE void prefix##_78(void); Z80_INLINE void prefix##_79(void); Z80_INLINE void prefix##_7a(void); Z80_INLINE void prefix##_7b(void); \ + Z80_INLINE void prefix##_7c(void); Z80_INLINE void prefix##_7d(void); Z80_INLINE void prefix##_7e(void); Z80_INLINE void prefix##_7f(void); \ + Z80_INLINE void prefix##_80(void); Z80_INLINE void prefix##_81(void); Z80_INLINE void prefix##_82(void); Z80_INLINE void prefix##_83(void); \ + Z80_INLINE void prefix##_84(void); Z80_INLINE void prefix##_85(void); Z80_INLINE void prefix##_86(void); Z80_INLINE void prefix##_87(void); \ + Z80_INLINE void prefix##_88(void); Z80_INLINE void prefix##_89(void); Z80_INLINE void prefix##_8a(void); Z80_INLINE void prefix##_8b(void); \ + Z80_INLINE void prefix##_8c(void); Z80_INLINE void prefix##_8d(void); Z80_INLINE void prefix##_8e(void); Z80_INLINE void prefix##_8f(void); \ + Z80_INLINE void prefix##_90(void); Z80_INLINE void prefix##_91(void); Z80_INLINE void prefix##_92(void); Z80_INLINE void prefix##_93(void); \ + Z80_INLINE void prefix##_94(void); Z80_INLINE void prefix##_95(void); Z80_INLINE void prefix##_96(void); Z80_INLINE void prefix##_97(void); \ + Z80_INLINE void prefix##_98(void); Z80_INLINE void prefix##_99(void); Z80_INLINE void prefix##_9a(void); Z80_INLINE void prefix##_9b(void); \ + Z80_INLINE void prefix##_9c(void); Z80_INLINE void prefix##_9d(void); Z80_INLINE void prefix##_9e(void); Z80_INLINE void prefix##_9f(void); \ + Z80_INLINE void prefix##_a0(void); Z80_INLINE void prefix##_a1(void); Z80_INLINE void prefix##_a2(void); Z80_INLINE void prefix##_a3(void); \ + Z80_INLINE void prefix##_a4(void); Z80_INLINE void prefix##_a5(void); Z80_INLINE void prefix##_a6(void); Z80_INLINE void prefix##_a7(void); \ + Z80_INLINE void prefix##_a8(void); Z80_INLINE void prefix##_a9(void); Z80_INLINE void prefix##_aa(void); Z80_INLINE void prefix##_ab(void); \ + Z80_INLINE void prefix##_ac(void); Z80_INLINE void prefix##_ad(void); Z80_INLINE void prefix##_ae(void); Z80_INLINE void prefix##_af(void); \ + Z80_INLINE void prefix##_b0(void); Z80_INLINE void prefix##_b1(void); Z80_INLINE void prefix##_b2(void); Z80_INLINE void prefix##_b3(void); \ + Z80_INLINE void prefix##_b4(void); Z80_INLINE void prefix##_b5(void); Z80_INLINE void prefix##_b6(void); Z80_INLINE void prefix##_b7(void); \ + Z80_INLINE void prefix##_b8(void); Z80_INLINE void prefix##_b9(void); Z80_INLINE void prefix##_ba(void); Z80_INLINE void prefix##_bb(void); \ + Z80_INLINE void prefix##_bc(void); Z80_INLINE void prefix##_bd(void); Z80_INLINE void prefix##_be(void); Z80_INLINE void prefix##_bf(void); \ + Z80_INLINE void prefix##_c0(void); Z80_INLINE void prefix##_c1(void); Z80_INLINE void prefix##_c2(void); Z80_INLINE void prefix##_c3(void); \ + Z80_INLINE void prefix##_c4(void); Z80_INLINE void prefix##_c5(void); Z80_INLINE void prefix##_c6(void); Z80_INLINE void prefix##_c7(void); \ + Z80_INLINE void prefix##_c8(void); Z80_INLINE void prefix##_c9(void); Z80_INLINE void prefix##_ca(void); Z80_INLINE void prefix##_cb(void); \ + Z80_INLINE void prefix##_cc(void); Z80_INLINE void prefix##_cd(void); Z80_INLINE void prefix##_ce(void); Z80_INLINE void prefix##_cf(void); \ + Z80_INLINE void prefix##_d0(void); Z80_INLINE void prefix##_d1(void); Z80_INLINE void prefix##_d2(void); Z80_INLINE void prefix##_d3(void); \ + Z80_INLINE void prefix##_d4(void); Z80_INLINE void prefix##_d5(void); Z80_INLINE void prefix##_d6(void); Z80_INLINE void prefix##_d7(void); \ + Z80_INLINE void prefix##_d8(void); Z80_INLINE void prefix##_d9(void); Z80_INLINE void prefix##_da(void); Z80_INLINE void prefix##_db(void); \ + Z80_INLINE void prefix##_dc(void); Z80_INLINE void prefix##_dd(void); Z80_INLINE void prefix##_de(void); Z80_INLINE void prefix##_df(void); \ + Z80_INLINE void prefix##_e0(void); Z80_INLINE void prefix##_e1(void); Z80_INLINE void prefix##_e2(void); Z80_INLINE void prefix##_e3(void); \ + Z80_INLINE void prefix##_e4(void); Z80_INLINE void prefix##_e5(void); Z80_INLINE void prefix##_e6(void); Z80_INLINE void prefix##_e7(void); \ + Z80_INLINE void prefix##_e8(void); Z80_INLINE void prefix##_e9(void); Z80_INLINE void prefix##_ea(void); Z80_INLINE void prefix##_eb(void); \ + Z80_INLINE void prefix##_ec(void); Z80_INLINE void prefix##_ed(void); Z80_INLINE void prefix##_ee(void); Z80_INLINE void prefix##_ef(void); \ + Z80_INLINE void prefix##_f0(void); Z80_INLINE void prefix##_f1(void); Z80_INLINE void prefix##_f2(void); Z80_INLINE void prefix##_f3(void); \ + Z80_INLINE void prefix##_f4(void); Z80_INLINE void prefix##_f5(void); Z80_INLINE void prefix##_f6(void); Z80_INLINE void prefix##_f7(void); \ + Z80_INLINE void prefix##_f8(void); Z80_INLINE void prefix##_f9(void); Z80_INLINE void prefix##_fa(void); Z80_INLINE void prefix##_fb(void); \ + Z80_INLINE void prefix##_fc(void); Z80_INLINE void prefix##_fd(void); Z80_INLINE void prefix##_fe(void); Z80_INLINE void prefix##_ff(void); \ +static const funcptr tablename[0x100] = { \ + prefix##_00,prefix##_01,prefix##_02,prefix##_03,prefix##_04,prefix##_05,prefix##_06,prefix##_07, \ + prefix##_08,prefix##_09,prefix##_0a,prefix##_0b,prefix##_0c,prefix##_0d,prefix##_0e,prefix##_0f, \ + prefix##_10,prefix##_11,prefix##_12,prefix##_13,prefix##_14,prefix##_15,prefix##_16,prefix##_17, \ + prefix##_18,prefix##_19,prefix##_1a,prefix##_1b,prefix##_1c,prefix##_1d,prefix##_1e,prefix##_1f, \ + prefix##_20,prefix##_21,prefix##_22,prefix##_23,prefix##_24,prefix##_25,prefix##_26,prefix##_27, \ + prefix##_28,prefix##_29,prefix##_2a,prefix##_2b,prefix##_2c,prefix##_2d,prefix##_2e,prefix##_2f, \ + prefix##_30,prefix##_31,prefix##_32,prefix##_33,prefix##_34,prefix##_35,prefix##_36,prefix##_37, \ + prefix##_38,prefix##_39,prefix##_3a,prefix##_3b,prefix##_3c,prefix##_3d,prefix##_3e,prefix##_3f, \ + prefix##_40,prefix##_41,prefix##_42,prefix##_43,prefix##_44,prefix##_45,prefix##_46,prefix##_47, \ + prefix##_48,prefix##_49,prefix##_4a,prefix##_4b,prefix##_4c,prefix##_4d,prefix##_4e,prefix##_4f, \ + prefix##_50,prefix##_51,prefix##_52,prefix##_53,prefix##_54,prefix##_55,prefix##_56,prefix##_57, \ + prefix##_58,prefix##_59,prefix##_5a,prefix##_5b,prefix##_5c,prefix##_5d,prefix##_5e,prefix##_5f, \ + prefix##_60,prefix##_61,prefix##_62,prefix##_63,prefix##_64,prefix##_65,prefix##_66,prefix##_67, \ + prefix##_68,prefix##_69,prefix##_6a,prefix##_6b,prefix##_6c,prefix##_6d,prefix##_6e,prefix##_6f, \ + prefix##_70,prefix##_71,prefix##_72,prefix##_73,prefix##_74,prefix##_75,prefix##_76,prefix##_77, \ + prefix##_78,prefix##_79,prefix##_7a,prefix##_7b,prefix##_7c,prefix##_7d,prefix##_7e,prefix##_7f, \ + prefix##_80,prefix##_81,prefix##_82,prefix##_83,prefix##_84,prefix##_85,prefix##_86,prefix##_87, \ + prefix##_88,prefix##_89,prefix##_8a,prefix##_8b,prefix##_8c,prefix##_8d,prefix##_8e,prefix##_8f, \ + prefix##_90,prefix##_91,prefix##_92,prefix##_93,prefix##_94,prefix##_95,prefix##_96,prefix##_97, \ + prefix##_98,prefix##_99,prefix##_9a,prefix##_9b,prefix##_9c,prefix##_9d,prefix##_9e,prefix##_9f, \ + prefix##_a0,prefix##_a1,prefix##_a2,prefix##_a3,prefix##_a4,prefix##_a5,prefix##_a6,prefix##_a7, \ + prefix##_a8,prefix##_a9,prefix##_aa,prefix##_ab,prefix##_ac,prefix##_ad,prefix##_ae,prefix##_af, \ + prefix##_b0,prefix##_b1,prefix##_b2,prefix##_b3,prefix##_b4,prefix##_b5,prefix##_b6,prefix##_b7, \ + prefix##_b8,prefix##_b9,prefix##_ba,prefix##_bb,prefix##_bc,prefix##_bd,prefix##_be,prefix##_bf, \ + prefix##_c0,prefix##_c1,prefix##_c2,prefix##_c3,prefix##_c4,prefix##_c5,prefix##_c6,prefix##_c7, \ + prefix##_c8,prefix##_c9,prefix##_ca,prefix##_cb,prefix##_cc,prefix##_cd,prefix##_ce,prefix##_cf, \ + prefix##_d0,prefix##_d1,prefix##_d2,prefix##_d3,prefix##_d4,prefix##_d5,prefix##_d6,prefix##_d7, \ + prefix##_d8,prefix##_d9,prefix##_da,prefix##_db,prefix##_dc,prefix##_dd,prefix##_de,prefix##_df, \ + prefix##_e0,prefix##_e1,prefix##_e2,prefix##_e3,prefix##_e4,prefix##_e5,prefix##_e6,prefix##_e7, \ + prefix##_e8,prefix##_e9,prefix##_ea,prefix##_eb,prefix##_ec,prefix##_ed,prefix##_ee,prefix##_ef, \ + prefix##_f0,prefix##_f1,prefix##_f2,prefix##_f3,prefix##_f4,prefix##_f5,prefix##_f6,prefix##_f7, \ + prefix##_f8,prefix##_f9,prefix##_fa,prefix##_fb,prefix##_fc,prefix##_fd,prefix##_fe,prefix##_ff \ +} + +PROTOTYPES(Z80op,op); +PROTOTYPES(Z80cb,cb); +PROTOTYPES(Z80dd,dd); +PROTOTYPES(Z80ed,ed); +PROTOTYPES(Z80fd,fd); +PROTOTYPES(Z80xycb,xycb); + +/****************************************************************************/ +/* Burn an odd amount of cycles, that is instructions taking something */ +/* different from 4 T-states per opcode (and R increment) */ +/****************************************************************************/ +Z80_INLINE void BURNODD(int cycles, int opcodes, int cyclesum) +{ + if( cycles > 0 ) + { + R += (cycles / cyclesum) * opcodes; + z80_ICount -= (cycles / cyclesum) * cyclesum; + } +} + +/*************************************************************** + * define an opcode function + ***************************************************************/ +#define OP(prefix,opcode) Z80_INLINE void prefix##_##opcode(void) + +/*************************************************************** + * adjust cycle count by n T-states + ***************************************************************/ +#define CC(prefix,opcode) z80_ICount -= cc[Z80_TABLE_##prefix][opcode] + +/*************************************************************** + * execute an opcode + ***************************************************************/ +#define EXEC(prefix,opcode) \ +{ \ + unsigned op = opcode; \ + CC(prefix,op); \ + (*Z80##prefix[op])(); \ +} + +#if BIG_SWITCH +#define EXEC_INLINE(prefix,opcode) \ +{ \ + unsigned op = opcode; \ + CC(prefix,op); \ + switch(op) \ + { \ + case 0x00:prefix##_##00();break; case 0x01:prefix##_##01();break; case 0x02:prefix##_##02();break; case 0x03:prefix##_##03();break; \ + case 0x04:prefix##_##04();break; case 0x05:prefix##_##05();break; case 0x06:prefix##_##06();break; case 0x07:prefix##_##07();break; \ + case 0x08:prefix##_##08();break; case 0x09:prefix##_##09();break; case 0x0a:prefix##_##0a();break; case 0x0b:prefix##_##0b();break; \ + case 0x0c:prefix##_##0c();break; case 0x0d:prefix##_##0d();break; case 0x0e:prefix##_##0e();break; case 0x0f:prefix##_##0f();break; \ + case 0x10:prefix##_##10();break; case 0x11:prefix##_##11();break; case 0x12:prefix##_##12();break; case 0x13:prefix##_##13();break; \ + case 0x14:prefix##_##14();break; case 0x15:prefix##_##15();break; case 0x16:prefix##_##16();break; case 0x17:prefix##_##17();break; \ + case 0x18:prefix##_##18();break; case 0x19:prefix##_##19();break; case 0x1a:prefix##_##1a();break; case 0x1b:prefix##_##1b();break; \ + case 0x1c:prefix##_##1c();break; case 0x1d:prefix##_##1d();break; case 0x1e:prefix##_##1e();break; case 0x1f:prefix##_##1f();break; \ + case 0x20:prefix##_##20();break; case 0x21:prefix##_##21();break; case 0x22:prefix##_##22();break; case 0x23:prefix##_##23();break; \ + case 0x24:prefix##_##24();break; case 0x25:prefix##_##25();break; case 0x26:prefix##_##26();break; case 0x27:prefix##_##27();break; \ + case 0x28:prefix##_##28();break; case 0x29:prefix##_##29();break; case 0x2a:prefix##_##2a();break; case 0x2b:prefix##_##2b();break; \ + case 0x2c:prefix##_##2c();break; case 0x2d:prefix##_##2d();break; case 0x2e:prefix##_##2e();break; case 0x2f:prefix##_##2f();break; \ + case 0x30:prefix##_##30();break; case 0x31:prefix##_##31();break; case 0x32:prefix##_##32();break; case 0x33:prefix##_##33();break; \ + case 0x34:prefix##_##34();break; case 0x35:prefix##_##35();break; case 0x36:prefix##_##36();break; case 0x37:prefix##_##37();break; \ + case 0x38:prefix##_##38();break; case 0x39:prefix##_##39();break; case 0x3a:prefix##_##3a();break; case 0x3b:prefix##_##3b();break; \ + case 0x3c:prefix##_##3c();break; case 0x3d:prefix##_##3d();break; case 0x3e:prefix##_##3e();break; case 0x3f:prefix##_##3f();break; \ + case 0x40:prefix##_##40();break; case 0x41:prefix##_##41();break; case 0x42:prefix##_##42();break; case 0x43:prefix##_##43();break; \ + case 0x44:prefix##_##44();break; case 0x45:prefix##_##45();break; case 0x46:prefix##_##46();break; case 0x47:prefix##_##47();break; \ + case 0x48:prefix##_##48();break; case 0x49:prefix##_##49();break; case 0x4a:prefix##_##4a();break; case 0x4b:prefix##_##4b();break; \ + case 0x4c:prefix##_##4c();break; case 0x4d:prefix##_##4d();break; case 0x4e:prefix##_##4e();break; case 0x4f:prefix##_##4f();break; \ + case 0x50:prefix##_##50();break; case 0x51:prefix##_##51();break; case 0x52:prefix##_##52();break; case 0x53:prefix##_##53();break; \ + case 0x54:prefix##_##54();break; case 0x55:prefix##_##55();break; case 0x56:prefix##_##56();break; case 0x57:prefix##_##57();break; \ + case 0x58:prefix##_##58();break; case 0x59:prefix##_##59();break; case 0x5a:prefix##_##5a();break; case 0x5b:prefix##_##5b();break; \ + case 0x5c:prefix##_##5c();break; case 0x5d:prefix##_##5d();break; case 0x5e:prefix##_##5e();break; case 0x5f:prefix##_##5f();break; \ + case 0x60:prefix##_##60();break; case 0x61:prefix##_##61();break; case 0x62:prefix##_##62();break; case 0x63:prefix##_##63();break; \ + case 0x64:prefix##_##64();break; case 0x65:prefix##_##65();break; case 0x66:prefix##_##66();break; case 0x67:prefix##_##67();break; \ + case 0x68:prefix##_##68();break; case 0x69:prefix##_##69();break; case 0x6a:prefix##_##6a();break; case 0x6b:prefix##_##6b();break; \ + case 0x6c:prefix##_##6c();break; case 0x6d:prefix##_##6d();break; case 0x6e:prefix##_##6e();break; case 0x6f:prefix##_##6f();break; \ + case 0x70:prefix##_##70();break; case 0x71:prefix##_##71();break; case 0x72:prefix##_##72();break; case 0x73:prefix##_##73();break; \ + case 0x74:prefix##_##74();break; case 0x75:prefix##_##75();break; case 0x76:prefix##_##76();break; case 0x77:prefix##_##77();break; \ + case 0x78:prefix##_##78();break; case 0x79:prefix##_##79();break; case 0x7a:prefix##_##7a();break; case 0x7b:prefix##_##7b();break; \ + case 0x7c:prefix##_##7c();break; case 0x7d:prefix##_##7d();break; case 0x7e:prefix##_##7e();break; case 0x7f:prefix##_##7f();break; \ + case 0x80:prefix##_##80();break; case 0x81:prefix##_##81();break; case 0x82:prefix##_##82();break; case 0x83:prefix##_##83();break; \ + case 0x84:prefix##_##84();break; case 0x85:prefix##_##85();break; case 0x86:prefix##_##86();break; case 0x87:prefix##_##87();break; \ + case 0x88:prefix##_##88();break; case 0x89:prefix##_##89();break; case 0x8a:prefix##_##8a();break; case 0x8b:prefix##_##8b();break; \ + case 0x8c:prefix##_##8c();break; case 0x8d:prefix##_##8d();break; case 0x8e:prefix##_##8e();break; case 0x8f:prefix##_##8f();break; \ + case 0x90:prefix##_##90();break; case 0x91:prefix##_##91();break; case 0x92:prefix##_##92();break; case 0x93:prefix##_##93();break; \ + case 0x94:prefix##_##94();break; case 0x95:prefix##_##95();break; case 0x96:prefix##_##96();break; case 0x97:prefix##_##97();break; \ + case 0x98:prefix##_##98();break; case 0x99:prefix##_##99();break; case 0x9a:prefix##_##9a();break; case 0x9b:prefix##_##9b();break; \ + case 0x9c:prefix##_##9c();break; case 0x9d:prefix##_##9d();break; case 0x9e:prefix##_##9e();break; case 0x9f:prefix##_##9f();break; \ + case 0xa0:prefix##_##a0();break; case 0xa1:prefix##_##a1();break; case 0xa2:prefix##_##a2();break; case 0xa3:prefix##_##a3();break; \ + case 0xa4:prefix##_##a4();break; case 0xa5:prefix##_##a5();break; case 0xa6:prefix##_##a6();break; case 0xa7:prefix##_##a7();break; \ + case 0xa8:prefix##_##a8();break; case 0xa9:prefix##_##a9();break; case 0xaa:prefix##_##aa();break; case 0xab:prefix##_##ab();break; \ + case 0xac:prefix##_##ac();break; case 0xad:prefix##_##ad();break; case 0xae:prefix##_##ae();break; case 0xaf:prefix##_##af();break; \ + case 0xb0:prefix##_##b0();break; case 0xb1:prefix##_##b1();break; case 0xb2:prefix##_##b2();break; case 0xb3:prefix##_##b3();break; \ + case 0xb4:prefix##_##b4();break; case 0xb5:prefix##_##b5();break; case 0xb6:prefix##_##b6();break; case 0xb7:prefix##_##b7();break; \ + case 0xb8:prefix##_##b8();break; case 0xb9:prefix##_##b9();break; case 0xba:prefix##_##ba();break; case 0xbb:prefix##_##bb();break; \ + case 0xbc:prefix##_##bc();break; case 0xbd:prefix##_##bd();break; case 0xbe:prefix##_##be();break; case 0xbf:prefix##_##bf();break; \ + case 0xc0:prefix##_##c0();break; case 0xc1:prefix##_##c1();break; case 0xc2:prefix##_##c2();break; case 0xc3:prefix##_##c3();break; \ + case 0xc4:prefix##_##c4();break; case 0xc5:prefix##_##c5();break; case 0xc6:prefix##_##c6();break; case 0xc7:prefix##_##c7();break; \ + case 0xc8:prefix##_##c8();break; case 0xc9:prefix##_##c9();break; case 0xca:prefix##_##ca();break; case 0xcb:prefix##_##cb();break; \ + case 0xcc:prefix##_##cc();break; case 0xcd:prefix##_##cd();break; case 0xce:prefix##_##ce();break; case 0xcf:prefix##_##cf();break; \ + case 0xd0:prefix##_##d0();break; case 0xd1:prefix##_##d1();break; case 0xd2:prefix##_##d2();break; case 0xd3:prefix##_##d3();break; \ + case 0xd4:prefix##_##d4();break; case 0xd5:prefix##_##d5();break; case 0xd6:prefix##_##d6();break; case 0xd7:prefix##_##d7();break; \ + case 0xd8:prefix##_##d8();break; case 0xd9:prefix##_##d9();break; case 0xda:prefix##_##da();break; case 0xdb:prefix##_##db();break; \ + case 0xdc:prefix##_##dc();break; case 0xdd:prefix##_##dd();break; case 0xde:prefix##_##de();break; case 0xdf:prefix##_##df();break; \ + case 0xe0:prefix##_##e0();break; case 0xe1:prefix##_##e1();break; case 0xe2:prefix##_##e2();break; case 0xe3:prefix##_##e3();break; \ + case 0xe4:prefix##_##e4();break; case 0xe5:prefix##_##e5();break; case 0xe6:prefix##_##e6();break; case 0xe7:prefix##_##e7();break; \ + case 0xe8:prefix##_##e8();break; case 0xe9:prefix##_##e9();break; case 0xea:prefix##_##ea();break; case 0xeb:prefix##_##eb();break; \ + case 0xec:prefix##_##ec();break; case 0xed:prefix##_##ed();break; case 0xee:prefix##_##ee();break; case 0xef:prefix##_##ef();break; \ + case 0xf0:prefix##_##f0();break; case 0xf1:prefix##_##f1();break; case 0xf2:prefix##_##f2();break; case 0xf3:prefix##_##f3();break; \ + case 0xf4:prefix##_##f4();break; case 0xf5:prefix##_##f5();break; case 0xf6:prefix##_##f6();break; case 0xf7:prefix##_##f7();break; \ + case 0xf8:prefix##_##f8();break; case 0xf9:prefix##_##f9();break; case 0xfa:prefix##_##fa();break; case 0xfb:prefix##_##fb();break; \ + case 0xfc:prefix##_##fc();break; case 0xfd:prefix##_##fd();break; case 0xfe:prefix##_##fe();break; case 0xff:prefix##_##ff();break; \ + } \ +} +#else +#define EXEC_Z80_INLINE EXEC +#endif + + +/*************************************************************** + * Enter HALT state; write 1 to fake port on first execution + ***************************************************************/ +#define ENTER_HALT { \ + PC--; \ + HALT = 1; \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + Z80Burn( z80_ICount ); \ +} + +/*************************************************************** + * Leave HALT state; write 0 to fake port + ***************************************************************/ +#define LEAVE_HALT { \ + if( HALT ) \ + { \ + HALT = 0; \ + PC++; \ + } \ +} + +/*************************************************************** + * Input a byte from given I/O port + ***************************************************************/ +#define IN(port) ((UINT8)Z80IORead(port)) + +/*************************************************************** + * Output a byte to given I/O port + ***************************************************************/ +#define OUT(port,value) Z80IOWrite(port,value) + +/*************************************************************** + * Read a byte from given memory location + ***************************************************************/ +#define RM(addr) (UINT8)Z80ProgramRead(addr) + +/*************************************************************** + * Read a word from given memory location + ***************************************************************/ +Z80_INLINE void RM16( UINT32 addr, Z80_PAIR *r ) +{ + r->b.l = RM(addr); + r->b.h = RM((addr+1)&0xffff); +} + +/*************************************************************** + * Write a byte to given memory location + ***************************************************************/ +#define WM(addr,value) Z80ProgramWrite(addr,value) + +#define cpu_readop(n) Z80CPUReadOp(n) +#define cpu_readop_arg(n) Z80CPUReadOpArg(n) + +/*************************************************************** + * Write a word to given memory location + ***************************************************************/ +Z80_INLINE void WM16( UINT32 addr, Z80_PAIR *r ) +{ + WM(addr,r->b.l); + WM((addr+1)&0xffff,r->b.h); +} + +/*************************************************************** + * ROP() is identical to RM() except it is used for + * reading opcodes. In case of system with memory mapped I/O, + * this function can be used to greatly speed up emulation + ***************************************************************/ +Z80_INLINE UINT8 ROP(void) +{ + unsigned pc = PCD; + PC++; + return cpu_readop(pc); +} + +/**************************************************************** + * ARG() is identical to ROP() except it is used + * for reading opcode arguments. This difference can be used to + * support systems that use different encoding mechanisms for + * opcodes and opcode arguments + ***************************************************************/ +Z80_INLINE UINT8 ARG(void) +{ + unsigned pc = PCD; + PC++; + return cpu_readop_arg(pc); +} + +Z80_INLINE UINT32 ARG16(void) +{ + unsigned pc = PCD; + PC += 2; + return cpu_readop_arg(pc) | (cpu_readop_arg((pc+1)&0xffff) << 8); +} + +/*************************************************************** + * Calculate the effective address EA of an opcode using + * IX+offset resp. IY+offset addressing. + ***************************************************************/ +#define EAX EA = (UINT32)(UINT16)(IX + (INT8)ARG()) +#define EAY EA = (UINT32)(UINT16)(IY + (INT8)ARG()) + +/*************************************************************** + * POP + ***************************************************************/ +#define POP(DR) do { RM16( SPD, &Z80.DR ); SP += 2; } while (0) + +/*************************************************************** + * PUSH + ***************************************************************/ +#define PUSH(SR) do { SP -= 2; WM16( SPD, &Z80.SR ); } while (0) + +/*************************************************************** + * JP + ***************************************************************/ +#if BUSY_LOOP_HACKS +#define JP { \ + unsigned oldpc = PCD-1; \ + PCD = ARG16(); \ + change_pc(PCD); \ + /* speed up busy loop */ \ + if( PCD == oldpc ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount, 1, cc[Z80_TABLE_op][0xc3] ); \ + } \ + else \ + { \ + UINT8 op = cpu_readop(PCD); \ + if( PCD == oldpc-1 ) \ + { \ + /* NOP - JP $-1 or EI - JP $-1 */ \ + if ( op == 0x00 || op == 0xfb ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount-cc[Z80_TABLE_op][0x00], \ + 2, cc[Z80_TABLE_op][0x00]+cc[Z80_TABLE_op][0xc3]); \ + } \ + } \ + else \ + /* LD SP,#xxxx - JP $-3 (Galaga) */ \ + if( PCD == oldpc-3 && op == 0x31 ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount-cc[Z80_TABLE_op][0x31], \ + 2, cc[Z80_TABLE_op][0x31]+cc[Z80_TABLE_op][0xc3]); \ + } \ + } \ +} +#else +#define JP { \ + PCD = ARG16(); \ + change_pc(PCD); \ +} +#endif + +/*************************************************************** + * JP_COND + ***************************************************************/ + +#define JP_COND(cond) \ + if( cond ) \ + { \ + PCD = ARG16(); \ + change_pc(PCD); \ + } \ + else \ + { \ + PC += 2; \ + } + +/*************************************************************** + * JR + ***************************************************************/ +#define JR() \ +{ \ + unsigned oldpc = PCD-1; \ + INT8 arg = (INT8)ARG(); /* ARG() also increments PC */ \ + PC += arg; /* so don't do PC += ARG() */ \ + change_pc(PCD); \ + /* speed up busy loop */ \ + if( PCD == oldpc ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount, 1, cc[Z80_TABLE_op][0x18] ); \ + } \ + else \ + { \ + UINT8 op = cpu_readop(PCD); \ + if( PCD == oldpc-1 ) \ + { \ + /* NOP - JR $-1 or EI - JR $-1 */ \ + if ( op == 0x00 || op == 0xfb ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount-cc[Z80_TABLE_op][0x00], \ + 2, cc[Z80_TABLE_op][0x00]+cc[Z80_TABLE_op][0x18]); \ + } \ + } \ + else \ + /* LD SP,#xxxx - JR $-3 */ \ + if( PCD == oldpc-3 && op == 0x31 ) \ + { \ + if( Z80.irq_state == Z80_CLEAR_LINE ) \ + BURNODD( z80_ICount-cc[Z80_TABLE_op][0x31], \ + 2, cc[Z80_TABLE_op][0x31]+cc[Z80_TABLE_op][0x18]); \ + } \ + } \ +} + +/*************************************************************** + * JR_COND + ***************************************************************/ +#define JR_COND(cond,opcode) \ + if( cond ) \ + { \ + INT8 arg = (INT8)ARG(); /* ARG() also increments PC */ \ + PC += arg; /* so don't do PC += ARG() */ \ + CC(ex,opcode); \ + change_pc(PCD); \ + } \ + else PC++; \ + +/*************************************************************** + * CALL + ***************************************************************/ +#define CALL() \ + EA = ARG16(); \ + PUSH( pc ); \ + PCD = EA; \ + change_pc(PCD) + +/*************************************************************** + * CALL_COND + ***************************************************************/ +#define CALL_COND(cond,opcode) \ + if( cond ) \ + { \ + EA = ARG16(); \ + PUSH( pc ); \ + PCD = EA; \ + CC(ex,opcode); \ + change_pc(PCD); \ + } \ + else \ + { \ + PC+=2; \ + } + +/*************************************************************** + * RET_COND + ***************************************************************/ +#define RET_COND(cond,opcode) \ + if( cond ) \ + { \ + POP( pc ); \ + change_pc(PCD); \ + CC(ex,opcode); \ + } + +/*************************************************************** + * RETN + ***************************************************************/ +#define RETN { \ + LOG(("Z80 #%d RETN IFF1:%d IFF2:%d\n", cpu_getactivecpu(), IFF1, IFF2)); \ + POP( pc ); \ + change_pc(PCD); \ + IFF1 = IFF2; \ +} + +/*************************************************************** + * RETI + ***************************************************************/ +#define RETI { \ + POP( pc ); \ + change_pc(PCD); \ +/* according to http://www.msxnet.org/tech/z80-documented.pdf */\ + IFF1 = IFF2; \ + if (Z80.daisy) \ + z80daisy_call_reti_device(Z80.daisy); \ +} + +/*************************************************************** + * LD R,A + ***************************************************************/ +#define LD_R_A { \ + R = A; \ + R2 = A & 0x80; /* keep bit 7 of R */ \ +} + +/*************************************************************** + * LD A,R + ***************************************************************/ +#define LD_A_R { \ + A = (R & 0x7f) | R2; \ + F = (F & CF) | SZ[A] | ( IFF2 << 2 ); \ +} + +/*************************************************************** + * LD I,A + ***************************************************************/ +#define LD_I_A { \ + I = A; \ +} + +/*************************************************************** + * LD A,I + ***************************************************************/ +#define LD_A_I { \ + A = I; \ + F = (F & CF) | SZ[A] | ( IFF2 << 2 ); \ +} + +/*************************************************************** + * RST + ***************************************************************/ +#define RST(addr) \ + PUSH( pc ); \ + PCD = addr; \ + change_pc(PCD) + +/*************************************************************** + * INC r8 + ***************************************************************/ +Z80_INLINE UINT8 INC(UINT8 value) +{ + UINT8 res = value + 1; + F = (F & CF) | SZHV_inc[res]; + return (UINT8)res; +} + +/*************************************************************** + * DEC r8 + ***************************************************************/ +Z80_INLINE UINT8 DEC(UINT8 value) +{ + UINT8 res = value - 1; + F = (F & CF) | SZHV_dec[res]; + return res; +} + +/*************************************************************** + * RLCA + ***************************************************************/ +#define RLCA \ + A = (A << 1) | (A >> 7); \ + F = (F & (SF | ZF | PF)) | (A & (YF | XF | CF)) + +/*************************************************************** + * RRCA + ***************************************************************/ +#define RRCA \ + F = (F & (SF | ZF | PF)) | (A & CF); \ + A = (A >> 1) | (A << 7); \ + F |= (A & (YF | XF) ) + +/*************************************************************** + * RLA + ***************************************************************/ +#define RLA { \ + UINT8 res = (A << 1) | (F & CF); \ + UINT8 c = (A & 0x80) ? CF : 0; \ + F = (F & (SF | ZF | PF)) | c | (res & (YF | XF)); \ + A = res; \ +} + +/*************************************************************** + * RRA + ***************************************************************/ +#define RRA { \ + UINT8 res = (A >> 1) | (F << 7); \ + UINT8 c = (A & 0x01) ? CF : 0; \ + F = (F & (SF | ZF | PF)) | c | (res & (YF | XF)); \ + A = res; \ +} + +/*************************************************************** + * RRD + ***************************************************************/ +#define RRD { \ + UINT8 n = RM(HL); \ + WM( HL, (n >> 4) | (A << 4) ); \ + A = (A & 0xf0) | (n & 0x0f); \ + F = (F & CF) | SZP[A]; \ +} + +/*************************************************************** + * RLD + ***************************************************************/ +#define RLD { \ + UINT8 n = RM(HL); \ + WM( HL, (n << 4) | (A & 0x0f) ); \ + A = (A & 0xf0) | (n >> 4); \ + F = (F & CF) | SZP[A]; \ +} + +/*************************************************************** + * ADD A,n + ***************************************************************/ +#if BIG_FLAGS_ARRAY +#define ADD(value) \ +{ \ + UINT32 ah = AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) + value); \ + F = SZHVC_add[ah | res]; \ + A = res; \ +} +#else +#define ADD(value) \ +{ \ + unsigned val = value; \ + unsigned res = A + val; \ + F = SZ[(UINT8)res] | ((res >> 8) & CF) | \ + ((A ^ res ^ val) & HF) | \ + (((val ^ A ^ 0x80) & (val ^ res) & 0x80) >> 5); \ + A = (UINT8)res; \ +} +#endif + +/*************************************************************** + * ADC A,n + ***************************************************************/ +#if BIG_FLAGS_ARRAY +#define ADC(value) \ +{ \ + UINT32 ah = AFD & 0xff00, c = AFD & 1; \ + UINT32 res = (UINT8)((ah >> 8) + value + c); \ + F = SZHVC_add[(c << 16) | ah | res]; \ + A = res; \ +} +#else +#define ADC(value) \ +{ \ + unsigned val = value; \ + unsigned res = A + val + (F & CF); \ + F = SZ[res & 0xff] | ((res >> 8) & CF) | \ + ((A ^ res ^ val) & HF) | \ + (((val ^ A ^ 0x80) & (val ^ res) & 0x80) >> 5); \ + A = res; \ +} +#endif + +/*************************************************************** + * SUB n + ***************************************************************/ +#if BIG_FLAGS_ARRAY +#define SUB(value) \ +{ \ + UINT32 ah = AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) - value); \ + F = SZHVC_sub[ah | res]; \ + A = res; \ +} +#else +#define SUB(value) \ +{ \ + unsigned val = value; \ + unsigned res = A - val; \ + F = SZ[res & 0xff] | ((res >> 8) & CF) | NF | \ + ((A ^ res ^ val) & HF) | \ + (((val ^ A) & (A ^ res) & 0x80) >> 5); \ + A = res; \ +} +#endif + +/*************************************************************** + * SBC A,n + ***************************************************************/ +#if BIG_FLAGS_ARRAY +#define SBC(value) \ +{ \ + UINT32 ah = AFD & 0xff00, c = AFD & 1; \ + UINT32 res = (UINT8)((ah >> 8) - value - c); \ + F = SZHVC_sub[(c<<16) | ah | res]; \ + A = res; \ +} +#else +#define SBC(value) \ +{ \ + unsigned val = value; \ + unsigned res = A - val - (F & CF); \ + F = SZ[res & 0xff] | ((res >> 8) & CF) | NF | \ + ((A ^ res ^ val) & HF) | \ + (((val ^ A) & (A ^ res) & 0x80) >> 5); \ + A = res; \ +} +#endif + +/*************************************************************** + * NEG + ***************************************************************/ +#define NEG { \ + UINT8 value = A; \ + A = 0; \ + SUB(value); \ +} + +/*************************************************************** + * DAA + ***************************************************************/ +#define DAA { \ + UINT8 cf, nf, hf, lo, hi, diff; \ + cf = F & CF; \ + nf = F & NF; \ + hf = F & HF; \ + lo = A & 15; \ + hi = A / 16; \ + \ + if (cf) \ + { \ + diff = (lo <= 9 && !hf) ? 0x60 : 0x66; \ + } \ + else \ + { \ + if (lo >= 10) \ + { \ + diff = hi <= 8 ? 0x06 : 0x66; \ + } \ + else \ + { \ + if (hi >= 10) \ + { \ + diff = hf ? 0x66 : 0x60; \ + } \ + else \ + { \ + diff = hf ? 0x06 : 0x00; \ + } \ + } \ + } \ + if (nf) A -= diff; \ + else A += diff; \ + \ + F = SZP[A] | (F & NF); \ + if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= CF; \ + if (nf ? hf && lo <= 5 : lo >= 10) F |= HF; \ +} + +/*************************************************************** + * AND n + ***************************************************************/ +#define AND(value) \ + A &= value; \ + F = SZP[A] | HF + +/*************************************************************** + * OR n + ***************************************************************/ +#define OR(value) \ + A |= value; \ + F = SZP[A] + +/*************************************************************** + * XOR n + ***************************************************************/ +#define XOR(value) \ + A ^= value; \ + F = SZP[A] + +/*************************************************************** + * CP n + ***************************************************************/ +#if BIG_FLAGS_ARRAY +#define CP(value) \ +{ \ + unsigned val = value; \ + UINT32 ah = AFD & 0xff00; \ + UINT32 res = (UINT8)((ah >> 8) - val); \ + F = (SZHVC_sub[ah | res] & ~(YF | XF)) | \ + (val & (YF | XF)); \ +} +#else +#define CP(value) \ +{ \ + unsigned val = value; \ + unsigned res = A - val; \ + F = (SZ[res & 0xff] & (SF | ZF)) | \ + (val & (YF | XF)) | ((res >> 8) & CF) | NF | \ + ((A ^ res ^ val) & HF) | \ + ((((val ^ A) & (A ^ res)) >> 5) & VF); \ +} +#endif + +/*************************************************************** + * EX AF,AF' + ***************************************************************/ +#define EX_AF { \ + Z80_PAIR tmp; \ + tmp = Z80.af; Z80.af = Z80.af2; Z80.af2 = tmp; \ +} + +/*************************************************************** + * EX DE,HL + ***************************************************************/ +#define EX_DE_HL { \ + Z80_PAIR tmp; \ + tmp = Z80.de; Z80.de = Z80.hl; Z80.hl = tmp; \ +} + +/*************************************************************** + * EXX + ***************************************************************/ +#define EXX { \ + Z80_PAIR tmp; \ + tmp = Z80.bc; Z80.bc = Z80.bc2; Z80.bc2 = tmp; \ + tmp = Z80.de; Z80.de = Z80.de2; Z80.de2 = tmp; \ + tmp = Z80.hl; Z80.hl = Z80.hl2; Z80.hl2 = tmp; \ +} + +/*************************************************************** + * EX (SP),r16 + ***************************************************************/ +#define EXSP(DR) \ +{ \ + Z80_PAIR tmp = { { 0, 0, 0, 0 } }; \ + RM16( SPD, &tmp ); \ + WM16( SPD, &Z80.DR ); \ + Z80.DR = tmp; \ +} + + +/*************************************************************** + * ADD16 + ***************************************************************/ +#define ADD16(DR,SR) \ +{ \ + UINT32 res = Z80.DR.d + Z80.SR.d; \ + F = (F & (SF | ZF | VF)) | \ + (((Z80.DR.d ^ res ^ Z80.SR.d) >> 8) & HF) | \ + ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); \ + Z80.DR.w.l = (UINT16)res; \ +} + +/*************************************************************** + * ADC r16,r16 + ***************************************************************/ +#define ADC16(Reg) \ +{ \ + UINT32 res = HLD + Z80.Reg.d + (F & CF); \ + F = (((HLD ^ res ^ Z80.Reg.d) >> 8) & HF) | \ + ((res >> 16) & CF) | \ + ((res >> 8) & (SF | YF | XF)) | \ + ((res & 0xffff) ? 0 : ZF) | \ + (((Z80.Reg.d ^ HLD ^ 0x8000) & (Z80.Reg.d ^ res) & 0x8000) >> 13); \ + HL = (UINT16)res; \ +} + +/*************************************************************** + * SBC r16,r16 + ***************************************************************/ +#define SBC16(Reg) \ +{ \ + UINT32 res = HLD - Z80.Reg.d - (F & CF); \ + F = (((HLD ^ res ^ Z80.Reg.d) >> 8) & HF) | NF | \ + ((res >> 16) & CF) | \ + ((res >> 8) & (SF | YF | XF)) | \ + ((res & 0xffff) ? 0 : ZF) | \ + (((Z80.Reg.d ^ HLD) & (HLD ^ res) &0x8000) >> 13); \ + HL = (UINT16)res; \ +} + +/*************************************************************** + * RLC r8 + ***************************************************************/ +Z80_INLINE UINT8 RLC(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | (res >> 7)) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * RRC r8 + ***************************************************************/ +Z80_INLINE UINT8 RRC(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (res << 7)) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * RL r8 + ***************************************************************/ +Z80_INLINE UINT8 RL(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | (F & CF)) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * RR r8 + ***************************************************************/ +Z80_INLINE UINT8 RR(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (F << 7)) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * SLA r8 + ***************************************************************/ +Z80_INLINE UINT8 SLA(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = (res << 1) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * SRA r8 + ***************************************************************/ +Z80_INLINE UINT8 SRA(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = ((res >> 1) | (res & 0x80)) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * SLL r8 + ***************************************************************/ +Z80_INLINE UINT8 SLL(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x80) ? CF : 0; + res = ((res << 1) | 0x01) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * SRL r8 + ***************************************************************/ +Z80_INLINE UINT8 SRL(UINT8 value) +{ + unsigned res = value; + unsigned c = (res & 0x01) ? CF : 0; + res = (res >> 1) & 0xff; + F = SZP[res] | c; + return res; +} + +/*************************************************************** + * BIT bit,r8 + ***************************************************************/ +#undef BIT +#define BIT(bit,reg) \ + F = (F & CF) | HF | SZ_BIT[reg & (1<>8) & (YF|XF)) + +/*************************************************************** + * RES bit,r8 + ***************************************************************/ +Z80_INLINE UINT8 RES(UINT8 bit, UINT8 value) +{ + return value & ~(1< flag 5 */ \ + if( (A + io) & 0x08 ) F |= XF; /* bit 3 -> flag 3 */ \ + HL++; DE++; BC--; \ + if( BC ) F |= VF; \ +} + +/*************************************************************** + * CPI + ***************************************************************/ +#define CPI { \ + UINT8 val = RM(HL); \ + UINT8 res = A - val; \ + HL++; BC--; \ + F = (F & CF) | (SZ[res]&~(YF|XF)) | ((A^val^res)&HF) | NF; \ + if( F & HF ) res -= 1; \ + if( res & 0x02 ) F |= YF; /* bit 1 -> flag 5 */ \ + if( res & 0x08 ) F |= XF; /* bit 3 -> flag 3 */ \ + if( BC ) F |= VF; \ +} + +/*************************************************************** + * INI + ***************************************************************/ +#define INI { \ + unsigned t; \ + UINT8 io = IN(BC); \ + B--; \ + WM( HL, io ); \ + HL++; \ + F = SZ[B]; \ + t = (unsigned)((C + 1) & 0xff) + (unsigned)io; \ + if( io & SF ) F |= NF; \ + if( t & 0x100 ) F |= HF | CF; \ + F |= SZP[(UINT8)(t & 0x07) ^ B] & PF; \ +} + +/*************************************************************** + * OUTI + ***************************************************************/ +#define OUTI { \ + unsigned t; \ + UINT8 io = RM(HL); \ + B--; \ + OUT( BC, io ); \ + HL++; \ + F = SZ[B]; \ + t = (unsigned)L + (unsigned)io; \ + if( io & SF ) F |= NF; \ + if( t & 0x100 ) F |= HF | CF; \ + F |= SZP[(UINT8)(t & 0x07) ^ B] & PF; \ +} + +/*************************************************************** + * LDD + ***************************************************************/ +#define LDD { \ + UINT8 io = RM(HL); \ + WM( DE, io ); \ + F &= SF | ZF | CF; \ + if( (A + io) & 0x02 ) F |= YF; /* bit 1 -> flag 5 */ \ + if( (A + io) & 0x08 ) F |= XF; /* bit 3 -> flag 3 */ \ + HL--; DE--; BC--; \ + if( BC ) F |= VF; \ +} + +/*************************************************************** + * CPD + ***************************************************************/ +#define CPD { \ + UINT8 val = RM(HL); \ + UINT8 res = A - val; \ + HL--; BC--; \ + F = (F & CF) | (SZ[res]&~(YF|XF)) | ((A^val^res)&HF) | NF; \ + if( F & HF ) res -= 1; \ + if( res & 0x02 ) F |= YF; /* bit 1 -> flag 5 */ \ + if( res & 0x08 ) F |= XF; /* bit 3 -> flag 3 */ \ + if( BC ) F |= VF; \ +} + +/*************************************************************** + * IND + ***************************************************************/ +#define IND { \ + unsigned t; \ + UINT8 io = IN(BC); \ + B--; \ + WM( HL, io ); \ + HL--; \ + F = SZ[B]; \ + t = ((unsigned)(C - 1) & 0xff) + (unsigned)io; \ + if( io & SF ) F |= NF; \ + if( t & 0x100 ) F |= HF | CF; \ + F |= SZP[(UINT8)(t & 0x07) ^ B] & PF; \ +} + +/*************************************************************** + * OUTD + ***************************************************************/ +#define OUTD { \ + unsigned t; \ + UINT8 io = RM(HL); \ + B--; \ + OUT( BC, io ); \ + HL--; \ + F = SZ[B]; \ + t = (unsigned)L + (unsigned)io; \ + if( io & SF ) F |= NF; \ + if( t & 0x100 ) F |= HF | CF; \ + F |= SZP[(UINT8)(t & 0x07) ^ B] & PF; \ +} + +/*************************************************************** + * LDIR + ***************************************************************/ +#define LDIR \ + LDI; \ + if( BC ) \ + { \ + PC -= 2; \ + CC(ex,0xb0); \ + } + +/*************************************************************** + * CPIR + ***************************************************************/ +#define CPIR \ + CPI; \ + if( BC && !(F & ZF) ) \ + { \ + PC -= 2; \ + CC(ex,0xb1); \ + } + +/*************************************************************** + * INIR + ***************************************************************/ +#define INIR \ + INI; \ + if( B ) \ + { \ + PC -= 2; \ + CC(ex,0xb2); \ + } + +/*************************************************************** + * OTIR + ***************************************************************/ +#define OTIR \ + OUTI; \ + if( B ) \ + { \ + PC -= 2; \ + CC(ex,0xb3); \ + } + +/*************************************************************** + * LDDR + ***************************************************************/ +#define LDDR \ + LDD; \ + if( BC ) \ + { \ + PC -= 2; \ + CC(ex,0xb8); \ + } + +/*************************************************************** + * CPDR + ***************************************************************/ +#define CPDR \ + CPD; \ + if( BC && !(F & ZF) ) \ + { \ + PC -= 2; \ + CC(ex,0xb9); \ + } + +/*************************************************************** + * INDR + ***************************************************************/ +#define INDR \ + IND; \ + if( B ) \ + { \ + PC -= 2; \ + CC(ex,0xba); \ + } + +/*************************************************************** + * OTDR + ***************************************************************/ +#define OTDR \ + OUTD; \ + if( B ) \ + { \ + PC -= 2; \ + CC(ex,0xbb); \ + } + +/*************************************************************** + * EI + ***************************************************************/ +#define EI { \ + IFF1 = IFF2 = 1; \ + Z80.after_ei = TRUE; \ +} + +/********************************************************** + * opcodes with CB prefix + * rotate, shift and bit operations + **********************************************************/ +OP(cb,00) { B = RLC(B); } /* RLC B */ +OP(cb,01) { C = RLC(C); } /* RLC C */ +OP(cb,02) { D = RLC(D); } /* RLC D */ +OP(cb,03) { E = RLC(E); } /* RLC E */ +OP(cb,04) { H = RLC(H); } /* RLC H */ +OP(cb,05) { L = RLC(L); } /* RLC L */ +OP(cb,06) { WM( HL, RLC(RM(HL)) ); } /* RLC (HL) */ +OP(cb,07) { A = RLC(A); } /* RLC A */ + +OP(cb,08) { B = RRC(B); } /* RRC B */ +OP(cb,09) { C = RRC(C); } /* RRC C */ +OP(cb,0a) { D = RRC(D); } /* RRC D */ +OP(cb,0b) { E = RRC(E); } /* RRC E */ +OP(cb,0c) { H = RRC(H); } /* RRC H */ +OP(cb,0d) { L = RRC(L); } /* RRC L */ +OP(cb,0e) { WM( HL, RRC(RM(HL)) ); } /* RRC (HL) */ +OP(cb,0f) { A = RRC(A); } /* RRC A */ + +OP(cb,10) { B = RL(B); } /* RL B */ +OP(cb,11) { C = RL(C); } /* RL C */ +OP(cb,12) { D = RL(D); } /* RL D */ +OP(cb,13) { E = RL(E); } /* RL E */ +OP(cb,14) { H = RL(H); } /* RL H */ +OP(cb,15) { L = RL(L); } /* RL L */ +OP(cb,16) { WM( HL, RL(RM(HL)) ); } /* RL (HL) */ +OP(cb,17) { A = RL(A); } /* RL A */ + +OP(cb,18) { B = RR(B); } /* RR B */ +OP(cb,19) { C = RR(C); } /* RR C */ +OP(cb,1a) { D = RR(D); } /* RR D */ +OP(cb,1b) { E = RR(E); } /* RR E */ +OP(cb,1c) { H = RR(H); } /* RR H */ +OP(cb,1d) { L = RR(L); } /* RR L */ +OP(cb,1e) { WM( HL, RR(RM(HL)) ); } /* RR (HL) */ +OP(cb,1f) { A = RR(A); } /* RR A */ + +OP(cb,20) { B = SLA(B); } /* SLA B */ +OP(cb,21) { C = SLA(C); } /* SLA C */ +OP(cb,22) { D = SLA(D); } /* SLA D */ +OP(cb,23) { E = SLA(E); } /* SLA E */ +OP(cb,24) { H = SLA(H); } /* SLA H */ +OP(cb,25) { L = SLA(L); } /* SLA L */ +OP(cb,26) { WM( HL, SLA(RM(HL)) ); } /* SLA (HL) */ +OP(cb,27) { A = SLA(A); } /* SLA A */ + +OP(cb,28) { B = SRA(B); } /* SRA B */ +OP(cb,29) { C = SRA(C); } /* SRA C */ +OP(cb,2a) { D = SRA(D); } /* SRA D */ +OP(cb,2b) { E = SRA(E); } /* SRA E */ +OP(cb,2c) { H = SRA(H); } /* SRA H */ +OP(cb,2d) { L = SRA(L); } /* SRA L */ +OP(cb,2e) { WM( HL, SRA(RM(HL)) ); } /* SRA (HL) */ +OP(cb,2f) { A = SRA(A); } /* SRA A */ + +OP(cb,30) { B = SLL(B); } /* SLL B */ +OP(cb,31) { C = SLL(C); } /* SLL C */ +OP(cb,32) { D = SLL(D); } /* SLL D */ +OP(cb,33) { E = SLL(E); } /* SLL E */ +OP(cb,34) { H = SLL(H); } /* SLL H */ +OP(cb,35) { L = SLL(L); } /* SLL L */ +OP(cb,36) { WM( HL, SLL(RM(HL)) ); } /* SLL (HL) */ +OP(cb,37) { A = SLL(A); } /* SLL A */ + +OP(cb,38) { B = SRL(B); } /* SRL B */ +OP(cb,39) { C = SRL(C); } /* SRL C */ +OP(cb,3a) { D = SRL(D); } /* SRL D */ +OP(cb,3b) { E = SRL(E); } /* SRL E */ +OP(cb,3c) { H = SRL(H); } /* SRL H */ +OP(cb,3d) { L = SRL(L); } /* SRL L */ +OP(cb,3e) { WM( HL, SRL(RM(HL)) ); } /* SRL (HL) */ +OP(cb,3f) { A = SRL(A); } /* SRL A */ + +OP(cb,40) { BIT(0,B); } /* BIT 0,B */ +OP(cb,41) { BIT(0,C); } /* BIT 0,C */ +OP(cb,42) { BIT(0,D); } /* BIT 0,D */ +OP(cb,43) { BIT(0,E); } /* BIT 0,E */ +OP(cb,44) { BIT(0,H); } /* BIT 0,H */ +OP(cb,45) { BIT(0,L); } /* BIT 0,L */ +OP(cb,46) { BIT(0,RM(HL)); } /* BIT 0,(HL) */ +OP(cb,47) { BIT(0,A); } /* BIT 0,A */ + +OP(cb,48) { BIT(1,B); } /* BIT 1,B */ +OP(cb,49) { BIT(1,C); } /* BIT 1,C */ +OP(cb,4a) { BIT(1,D); } /* BIT 1,D */ +OP(cb,4b) { BIT(1,E); } /* BIT 1,E */ +OP(cb,4c) { BIT(1,H); } /* BIT 1,H */ +OP(cb,4d) { BIT(1,L); } /* BIT 1,L */ +OP(cb,4e) { BIT(1,RM(HL)); } /* BIT 1,(HL) */ +OP(cb,4f) { BIT(1,A); } /* BIT 1,A */ + +OP(cb,50) { BIT(2,B); } /* BIT 2,B */ +OP(cb,51) { BIT(2,C); } /* BIT 2,C */ +OP(cb,52) { BIT(2,D); } /* BIT 2,D */ +OP(cb,53) { BIT(2,E); } /* BIT 2,E */ +OP(cb,54) { BIT(2,H); } /* BIT 2,H */ +OP(cb,55) { BIT(2,L); } /* BIT 2,L */ +OP(cb,56) { BIT(2,RM(HL)); } /* BIT 2,(HL) */ +OP(cb,57) { BIT(2,A); } /* BIT 2,A */ + +OP(cb,58) { BIT(3,B); } /* BIT 3,B */ +OP(cb,59) { BIT(3,C); } /* BIT 3,C */ +OP(cb,5a) { BIT(3,D); } /* BIT 3,D */ +OP(cb,5b) { BIT(3,E); } /* BIT 3,E */ +OP(cb,5c) { BIT(3,H); } /* BIT 3,H */ +OP(cb,5d) { BIT(3,L); } /* BIT 3,L */ +OP(cb,5e) { BIT(3,RM(HL)); } /* BIT 3,(HL) */ +OP(cb,5f) { BIT(3,A); } /* BIT 3,A */ + +OP(cb,60) { BIT(4,B); } /* BIT 4,B */ +OP(cb,61) { BIT(4,C); } /* BIT 4,C */ +OP(cb,62) { BIT(4,D); } /* BIT 4,D */ +OP(cb,63) { BIT(4,E); } /* BIT 4,E */ +OP(cb,64) { BIT(4,H); } /* BIT 4,H */ +OP(cb,65) { BIT(4,L); } /* BIT 4,L */ +OP(cb,66) { BIT(4,RM(HL)); } /* BIT 4,(HL) */ +OP(cb,67) { BIT(4,A); } /* BIT 4,A */ + +OP(cb,68) { BIT(5,B); } /* BIT 5,B */ +OP(cb,69) { BIT(5,C); } /* BIT 5,C */ +OP(cb,6a) { BIT(5,D); } /* BIT 5,D */ +OP(cb,6b) { BIT(5,E); } /* BIT 5,E */ +OP(cb,6c) { BIT(5,H); } /* BIT 5,H */ +OP(cb,6d) { BIT(5,L); } /* BIT 5,L */ +OP(cb,6e) { BIT(5,RM(HL)); } /* BIT 5,(HL) */ +OP(cb,6f) { BIT(5,A); } /* BIT 5,A */ + +OP(cb,70) { BIT(6,B); } /* BIT 6,B */ +OP(cb,71) { BIT(6,C); } /* BIT 6,C */ +OP(cb,72) { BIT(6,D); } /* BIT 6,D */ +OP(cb,73) { BIT(6,E); } /* BIT 6,E */ +OP(cb,74) { BIT(6,H); } /* BIT 6,H */ +OP(cb,75) { BIT(6,L); } /* BIT 6,L */ +OP(cb,76) { BIT(6,RM(HL)); } /* BIT 6,(HL) */ +OP(cb,77) { BIT(6,A); } /* BIT 6,A */ + +OP(cb,78) { BIT(7,B); } /* BIT 7,B */ +OP(cb,79) { BIT(7,C); } /* BIT 7,C */ +OP(cb,7a) { BIT(7,D); } /* BIT 7,D */ +OP(cb,7b) { BIT(7,E); } /* BIT 7,E */ +OP(cb,7c) { BIT(7,H); } /* BIT 7,H */ +OP(cb,7d) { BIT(7,L); } /* BIT 7,L */ +OP(cb,7e) { BIT(7,RM(HL)); } /* BIT 7,(HL) */ +OP(cb,7f) { BIT(7,A); } /* BIT 7,A */ + +OP(cb,80) { B = RES(0,B); } /* RES 0,B */ +OP(cb,81) { C = RES(0,C); } /* RES 0,C */ +OP(cb,82) { D = RES(0,D); } /* RES 0,D */ +OP(cb,83) { E = RES(0,E); } /* RES 0,E */ +OP(cb,84) { H = RES(0,H); } /* RES 0,H */ +OP(cb,85) { L = RES(0,L); } /* RES 0,L */ +OP(cb,86) { WM( HL, RES(0,RM(HL)) ); } /* RES 0,(HL) */ +OP(cb,87) { A = RES(0,A); } /* RES 0,A */ + +OP(cb,88) { B = RES(1,B); } /* RES 1,B */ +OP(cb,89) { C = RES(1,C); } /* RES 1,C */ +OP(cb,8a) { D = RES(1,D); } /* RES 1,D */ +OP(cb,8b) { E = RES(1,E); } /* RES 1,E */ +OP(cb,8c) { H = RES(1,H); } /* RES 1,H */ +OP(cb,8d) { L = RES(1,L); } /* RES 1,L */ +OP(cb,8e) { WM( HL, RES(1,RM(HL)) ); } /* RES 1,(HL) */ +OP(cb,8f) { A = RES(1,A); } /* RES 1,A */ + +OP(cb,90) { B = RES(2,B); } /* RES 2,B */ +OP(cb,91) { C = RES(2,C); } /* RES 2,C */ +OP(cb,92) { D = RES(2,D); } /* RES 2,D */ +OP(cb,93) { E = RES(2,E); } /* RES 2,E */ +OP(cb,94) { H = RES(2,H); } /* RES 2,H */ +OP(cb,95) { L = RES(2,L); } /* RES 2,L */ +OP(cb,96) { WM( HL, RES(2,RM(HL)) ); } /* RES 2,(HL) */ +OP(cb,97) { A = RES(2,A); } /* RES 2,A */ + +OP(cb,98) { B = RES(3,B); } /* RES 3,B */ +OP(cb,99) { C = RES(3,C); } /* RES 3,C */ +OP(cb,9a) { D = RES(3,D); } /* RES 3,D */ +OP(cb,9b) { E = RES(3,E); } /* RES 3,E */ +OP(cb,9c) { H = RES(3,H); } /* RES 3,H */ +OP(cb,9d) { L = RES(3,L); } /* RES 3,L */ +OP(cb,9e) { WM( HL, RES(3,RM(HL)) ); } /* RES 3,(HL) */ +OP(cb,9f) { A = RES(3,A); } /* RES 3,A */ + +OP(cb,a0) { B = RES(4,B); } /* RES 4,B */ +OP(cb,a1) { C = RES(4,C); } /* RES 4,C */ +OP(cb,a2) { D = RES(4,D); } /* RES 4,D */ +OP(cb,a3) { E = RES(4,E); } /* RES 4,E */ +OP(cb,a4) { H = RES(4,H); } /* RES 4,H */ +OP(cb,a5) { L = RES(4,L); } /* RES 4,L */ +OP(cb,a6) { WM( HL, RES(4,RM(HL)) ); } /* RES 4,(HL) */ +OP(cb,a7) { A = RES(4,A); } /* RES 4,A */ + +OP(cb,a8) { B = RES(5,B); } /* RES 5,B */ +OP(cb,a9) { C = RES(5,C); } /* RES 5,C */ +OP(cb,aa) { D = RES(5,D); } /* RES 5,D */ +OP(cb,ab) { E = RES(5,E); } /* RES 5,E */ +OP(cb,ac) { H = RES(5,H); } /* RES 5,H */ +OP(cb,ad) { L = RES(5,L); } /* RES 5,L */ +OP(cb,ae) { WM( HL, RES(5,RM(HL)) ); } /* RES 5,(HL) */ +OP(cb,af) { A = RES(5,A); } /* RES 5,A */ + +OP(cb,b0) { B = RES(6,B); } /* RES 6,B */ +OP(cb,b1) { C = RES(6,C); } /* RES 6,C */ +OP(cb,b2) { D = RES(6,D); } /* RES 6,D */ +OP(cb,b3) { E = RES(6,E); } /* RES 6,E */ +OP(cb,b4) { H = RES(6,H); } /* RES 6,H */ +OP(cb,b5) { L = RES(6,L); } /* RES 6,L */ +OP(cb,b6) { WM( HL, RES(6,RM(HL)) ); } /* RES 6,(HL) */ +OP(cb,b7) { A = RES(6,A); } /* RES 6,A */ + +OP(cb,b8) { B = RES(7,B); } /* RES 7,B */ +OP(cb,b9) { C = RES(7,C); } /* RES 7,C */ +OP(cb,ba) { D = RES(7,D); } /* RES 7,D */ +OP(cb,bb) { E = RES(7,E); } /* RES 7,E */ +OP(cb,bc) { H = RES(7,H); } /* RES 7,H */ +OP(cb,bd) { L = RES(7,L); } /* RES 7,L */ +OP(cb,be) { WM( HL, RES(7,RM(HL)) ); } /* RES 7,(HL) */ +OP(cb,bf) { A = RES(7,A); } /* RES 7,A */ + +OP(cb,c0) { B = SET(0,B); } /* SET 0,B */ +OP(cb,c1) { C = SET(0,C); } /* SET 0,C */ +OP(cb,c2) { D = SET(0,D); } /* SET 0,D */ +OP(cb,c3) { E = SET(0,E); } /* SET 0,E */ +OP(cb,c4) { H = SET(0,H); } /* SET 0,H */ +OP(cb,c5) { L = SET(0,L); } /* SET 0,L */ +OP(cb,c6) { WM( HL, SET(0,RM(HL)) ); } /* SET 0,(HL) */ +OP(cb,c7) { A = SET(0,A); } /* SET 0,A */ + +OP(cb,c8) { B = SET(1,B); } /* SET 1,B */ +OP(cb,c9) { C = SET(1,C); } /* SET 1,C */ +OP(cb,ca) { D = SET(1,D); } /* SET 1,D */ +OP(cb,cb) { E = SET(1,E); } /* SET 1,E */ +OP(cb,cc) { H = SET(1,H); } /* SET 1,H */ +OP(cb,cd) { L = SET(1,L); } /* SET 1,L */ +OP(cb,ce) { WM( HL, SET(1,RM(HL)) ); } /* SET 1,(HL) */ +OP(cb,cf) { A = SET(1,A); } /* SET 1,A */ + +OP(cb,d0) { B = SET(2,B); } /* SET 2,B */ +OP(cb,d1) { C = SET(2,C); } /* SET 2,C */ +OP(cb,d2) { D = SET(2,D); } /* SET 2,D */ +OP(cb,d3) { E = SET(2,E); } /* SET 2,E */ +OP(cb,d4) { H = SET(2,H); } /* SET 2,H */ +OP(cb,d5) { L = SET(2,L); } /* SET 2,L */ +OP(cb,d6) { WM( HL, SET(2,RM(HL)) ); } /* SET 2,(HL) */ +OP(cb,d7) { A = SET(2,A); } /* SET 2,A */ + +OP(cb,d8) { B = SET(3,B); } /* SET 3,B */ +OP(cb,d9) { C = SET(3,C); } /* SET 3,C */ +OP(cb,da) { D = SET(3,D); } /* SET 3,D */ +OP(cb,db) { E = SET(3,E); } /* SET 3,E */ +OP(cb,dc) { H = SET(3,H); } /* SET 3,H */ +OP(cb,dd) { L = SET(3,L); } /* SET 3,L */ +OP(cb,de) { WM( HL, SET(3,RM(HL)) ); } /* SET 3,(HL) */ +OP(cb,df) { A = SET(3,A); } /* SET 3,A */ + +OP(cb,e0) { B = SET(4,B); } /* SET 4,B */ +OP(cb,e1) { C = SET(4,C); } /* SET 4,C */ +OP(cb,e2) { D = SET(4,D); } /* SET 4,D */ +OP(cb,e3) { E = SET(4,E); } /* SET 4,E */ +OP(cb,e4) { H = SET(4,H); } /* SET 4,H */ +OP(cb,e5) { L = SET(4,L); } /* SET 4,L */ +OP(cb,e6) { WM( HL, SET(4,RM(HL)) ); } /* SET 4,(HL) */ +OP(cb,e7) { A = SET(4,A); } /* SET 4,A */ + +OP(cb,e8) { B = SET(5,B); } /* SET 5,B */ +OP(cb,e9) { C = SET(5,C); } /* SET 5,C */ +OP(cb,ea) { D = SET(5,D); } /* SET 5,D */ +OP(cb,eb) { E = SET(5,E); } /* SET 5,E */ +OP(cb,ec) { H = SET(5,H); } /* SET 5,H */ +OP(cb,ed) { L = SET(5,L); } /* SET 5,L */ +OP(cb,ee) { WM( HL, SET(5,RM(HL)) ); } /* SET 5,(HL) */ +OP(cb,ef) { A = SET(5,A); } /* SET 5,A */ + +OP(cb,f0) { B = SET(6,B); } /* SET 6,B */ +OP(cb,f1) { C = SET(6,C); } /* SET 6,C */ +OP(cb,f2) { D = SET(6,D); } /* SET 6,D */ +OP(cb,f3) { E = SET(6,E); } /* SET 6,E */ +OP(cb,f4) { H = SET(6,H); } /* SET 6,H */ +OP(cb,f5) { L = SET(6,L); } /* SET 6,L */ +OP(cb,f6) { WM( HL, SET(6,RM(HL)) ); } /* SET 6,(HL) */ +OP(cb,f7) { A = SET(6,A); } /* SET 6,A */ + +OP(cb,f8) { B = SET(7,B); } /* SET 7,B */ +OP(cb,f9) { C = SET(7,C); } /* SET 7,C */ +OP(cb,fa) { D = SET(7,D); } /* SET 7,D */ +OP(cb,fb) { E = SET(7,E); } /* SET 7,E */ +OP(cb,fc) { H = SET(7,H); } /* SET 7,H */ +OP(cb,fd) { L = SET(7,L); } /* SET 7,L */ +OP(cb,fe) { WM( HL, SET(7,RM(HL)) ); } /* SET 7,(HL) */ +OP(cb,ff) { A = SET(7,A); } /* SET 7,A */ + + +/********************************************************** +* opcodes with DD/FD CB prefix +* rotate, shift and bit operations with (IX+o) +**********************************************************/ +OP(xycb,00) { B = RLC( RM(EA) ); WM( EA,B ); } /* RLC B=(XY+o) */ +OP(xycb,01) { C = RLC( RM(EA) ); WM( EA,C ); } /* RLC C=(XY+o) */ +OP(xycb,02) { D = RLC( RM(EA) ); WM( EA,D ); } /* RLC D=(XY+o) */ +OP(xycb,03) { E = RLC( RM(EA) ); WM( EA,E ); } /* RLC E=(XY+o) */ +OP(xycb,04) { H = RLC( RM(EA) ); WM( EA,H ); } /* RLC H=(XY+o) */ +OP(xycb,05) { L = RLC( RM(EA) ); WM( EA,L ); } /* RLC L=(XY+o) */ +OP(xycb,06) { WM( EA, RLC( RM(EA) ) ); } /* RLC (XY+o) */ +OP(xycb,07) { A = RLC( RM(EA) ); WM( EA,A ); } /* RLC A=(XY+o) */ + +OP(xycb,08) { B = RRC( RM(EA) ); WM( EA,B ); } /* RRC B=(XY+o) */ +OP(xycb,09) { C = RRC( RM(EA) ); WM( EA,C ); } /* RRC C=(XY+o) */ +OP(xycb,0a) { D = RRC( RM(EA) ); WM( EA,D ); } /* RRC D=(XY+o) */ +OP(xycb,0b) { E = RRC( RM(EA) ); WM( EA,E ); } /* RRC E=(XY+o) */ +OP(xycb,0c) { H = RRC( RM(EA) ); WM( EA,H ); } /* RRC H=(XY+o) */ +OP(xycb,0d) { L = RRC( RM(EA) ); WM( EA,L ); } /* RRC L=(XY+o) */ +OP(xycb,0e) { WM( EA,RRC( RM(EA) ) ); } /* RRC (XY+o) */ +OP(xycb,0f) { A = RRC( RM(EA) ); WM( EA,A ); } /* RRC A=(XY+o) */ + +OP(xycb,10) { B = RL( RM(EA) ); WM( EA,B ); } /* RL B=(XY+o) */ +OP(xycb,11) { C = RL( RM(EA) ); WM( EA,C ); } /* RL C=(XY+o) */ +OP(xycb,12) { D = RL( RM(EA) ); WM( EA,D ); } /* RL D=(XY+o) */ +OP(xycb,13) { E = RL( RM(EA) ); WM( EA,E ); } /* RL E=(XY+o) */ +OP(xycb,14) { H = RL( RM(EA) ); WM( EA,H ); } /* RL H=(XY+o) */ +OP(xycb,15) { L = RL( RM(EA) ); WM( EA,L ); } /* RL L=(XY+o) */ +OP(xycb,16) { WM( EA,RL( RM(EA) ) ); } /* RL (XY+o) */ +OP(xycb,17) { A = RL( RM(EA) ); WM( EA,A ); } /* RL A=(XY+o) */ + +OP(xycb,18) { B = RR( RM(EA) ); WM( EA,B ); } /* RR B=(XY+o) */ +OP(xycb,19) { C = RR( RM(EA) ); WM( EA,C ); } /* RR C=(XY+o) */ +OP(xycb,1a) { D = RR( RM(EA) ); WM( EA,D ); } /* RR D=(XY+o) */ +OP(xycb,1b) { E = RR( RM(EA) ); WM( EA,E ); } /* RR E=(XY+o) */ +OP(xycb,1c) { H = RR( RM(EA) ); WM( EA,H ); } /* RR H=(XY+o) */ +OP(xycb,1d) { L = RR( RM(EA) ); WM( EA,L ); } /* RR L=(XY+o) */ +OP(xycb,1e) { WM( EA,RR( RM(EA) ) ); } /* RR (XY+o) */ +OP(xycb,1f) { A = RR( RM(EA) ); WM( EA,A ); } /* RR A=(XY+o) */ + +OP(xycb,20) { B = SLA( RM(EA) ); WM( EA,B ); } /* SLA B=(XY+o) */ +OP(xycb,21) { C = SLA( RM(EA) ); WM( EA,C ); } /* SLA C=(XY+o) */ +OP(xycb,22) { D = SLA( RM(EA) ); WM( EA,D ); } /* SLA D=(XY+o) */ +OP(xycb,23) { E = SLA( RM(EA) ); WM( EA,E ); } /* SLA E=(XY+o) */ +OP(xycb,24) { H = SLA( RM(EA) ); WM( EA,H ); } /* SLA H=(XY+o) */ +OP(xycb,25) { L = SLA( RM(EA) ); WM( EA,L ); } /* SLA L=(XY+o) */ +OP(xycb,26) { WM( EA,SLA( RM(EA) ) ); } /* SLA (XY+o) */ +OP(xycb,27) { A = SLA( RM(EA) ); WM( EA,A ); } /* SLA A=(XY+o) */ + +OP(xycb,28) { B = SRA( RM(EA) ); WM( EA,B ); } /* SRA B=(XY+o) */ +OP(xycb,29) { C = SRA( RM(EA) ); WM( EA,C ); } /* SRA C=(XY+o) */ +OP(xycb,2a) { D = SRA( RM(EA) ); WM( EA,D ); } /* SRA D=(XY+o) */ +OP(xycb,2b) { E = SRA( RM(EA) ); WM( EA,E ); } /* SRA E=(XY+o) */ +OP(xycb,2c) { H = SRA( RM(EA) ); WM( EA,H ); } /* SRA H=(XY+o) */ +OP(xycb,2d) { L = SRA( RM(EA) ); WM( EA,L ); } /* SRA L=(XY+o) */ +OP(xycb,2e) { WM( EA,SRA( RM(EA) ) ); } /* SRA (XY+o) */ +OP(xycb,2f) { A = SRA( RM(EA) ); WM( EA,A ); } /* SRA A=(XY+o) */ + +OP(xycb,30) { B = SLL( RM(EA) ); WM( EA,B ); } /* SLL B=(XY+o) */ +OP(xycb,31) { C = SLL( RM(EA) ); WM( EA,C ); } /* SLL C=(XY+o) */ +OP(xycb,32) { D = SLL( RM(EA) ); WM( EA,D ); } /* SLL D=(XY+o) */ +OP(xycb,33) { E = SLL( RM(EA) ); WM( EA,E ); } /* SLL E=(XY+o) */ +OP(xycb,34) { H = SLL( RM(EA) ); WM( EA,H ); } /* SLL H=(XY+o) */ +OP(xycb,35) { L = SLL( RM(EA) ); WM( EA,L ); } /* SLL L=(XY+o) */ +OP(xycb,36) { WM( EA,SLL( RM(EA) ) ); } /* SLL (XY+o) */ +OP(xycb,37) { A = SLL( RM(EA) ); WM( EA,A ); } /* SLL A=(XY+o) */ + +OP(xycb,38) { B = SRL( RM(EA) ); WM( EA,B ); } /* SRL B=(XY+o) */ +OP(xycb,39) { C = SRL( RM(EA) ); WM( EA,C ); } /* SRL C=(XY+o) */ +OP(xycb,3a) { D = SRL( RM(EA) ); WM( EA,D ); } /* SRL D=(XY+o) */ +OP(xycb,3b) { E = SRL( RM(EA) ); WM( EA,E ); } /* SRL E=(XY+o) */ +OP(xycb,3c) { H = SRL( RM(EA) ); WM( EA,H ); } /* SRL H=(XY+o) */ +OP(xycb,3d) { L = SRL( RM(EA) ); WM( EA,L ); } /* SRL L=(XY+o) */ +OP(xycb,3e) { WM( EA,SRL( RM(EA) ) ); } /* SRL (XY+o) */ +OP(xycb,3f) { A = SRL( RM(EA) ); WM( EA,A ); } /* SRL A=(XY+o) */ + +OP(xycb,40) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,41) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,42) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,43) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,44) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,45) { xycb_46(); } /* BIT 0,(XY+o) */ +OP(xycb,46) { BIT_XY(0,RM(EA)); } /* BIT 0,(XY+o) */ +OP(xycb,47) { xycb_46(); } /* BIT 0,(XY+o) */ + +OP(xycb,48) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,49) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,4a) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,4b) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,4c) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,4d) { xycb_4e(); } /* BIT 1,(XY+o) */ +OP(xycb,4e) { BIT_XY(1,RM(EA)); } /* BIT 1,(XY+o) */ +OP(xycb,4f) { xycb_4e(); } /* BIT 1,(XY+o) */ + +OP(xycb,50) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,51) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,52) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,53) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,54) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,55) { xycb_56(); } /* BIT 2,(XY+o) */ +OP(xycb,56) { BIT_XY(2,RM(EA)); } /* BIT 2,(XY+o) */ +OP(xycb,57) { xycb_56(); } /* BIT 2,(XY+o) */ + +OP(xycb,58) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,59) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,5a) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,5b) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,5c) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,5d) { xycb_5e(); } /* BIT 3,(XY+o) */ +OP(xycb,5e) { BIT_XY(3,RM(EA)); } /* BIT 3,(XY+o) */ +OP(xycb,5f) { xycb_5e(); } /* BIT 3,(XY+o) */ + +OP(xycb,60) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,61) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,62) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,63) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,64) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,65) { xycb_66(); } /* BIT 4,(XY+o) */ +OP(xycb,66) { BIT_XY(4,RM(EA)); } /* BIT 4,(XY+o) */ +OP(xycb,67) { xycb_66(); } /* BIT 4,(XY+o) */ + +OP(xycb,68) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,69) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,6a) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,6b) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,6c) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,6d) { xycb_6e(); } /* BIT 5,(XY+o) */ +OP(xycb,6e) { BIT_XY(5,RM(EA)); } /* BIT 5,(XY+o) */ +OP(xycb,6f) { xycb_6e(); } /* BIT 5,(XY+o) */ + +OP(xycb,70) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,71) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,72) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,73) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,74) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,75) { xycb_66(); } /* BIT 6,(XY+o) */ +OP(xycb,76) { BIT_XY(6,RM(EA)); } /* BIT 6,(XY+o) */ +OP(xycb,77) { xycb_66(); } /* BIT 6,(XY+o) */ + +OP(xycb,78) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,79) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,7a) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,7b) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,7c) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,7d) { xycb_7e(); } /* BIT 7,(XY+o) */ +OP(xycb,7e) { BIT_XY(7,RM(EA)); } /* BIT 7,(XY+o) */ +OP(xycb,7f) { xycb_7e(); } /* BIT 7,(XY+o) */ + +OP(xycb,80) { B = RES(0, RM(EA) ); WM( EA,B ); } /* RES 0,B=(XY+o) */ +OP(xycb,81) { C = RES(0, RM(EA) ); WM( EA,C ); } /* RES 0,C=(XY+o) */ +OP(xycb,82) { D = RES(0, RM(EA) ); WM( EA,D ); } /* RES 0,D=(XY+o) */ +OP(xycb,83) { E = RES(0, RM(EA) ); WM( EA,E ); } /* RES 0,E=(XY+o) */ +OP(xycb,84) { H = RES(0, RM(EA) ); WM( EA,H ); } /* RES 0,H=(XY+o) */ +OP(xycb,85) { L = RES(0, RM(EA) ); WM( EA,L ); } /* RES 0,L=(XY+o) */ +OP(xycb,86) { WM( EA, RES(0,RM(EA)) ); } /* RES 0,(XY+o) */ +OP(xycb,87) { A = RES(0, RM(EA) ); WM( EA,A ); } /* RES 0,A=(XY+o) */ + +OP(xycb,88) { B = RES(1, RM(EA) ); WM( EA,B ); } /* RES 1,B=(XY+o) */ +OP(xycb,89) { C = RES(1, RM(EA) ); WM( EA,C ); } /* RES 1,C=(XY+o) */ +OP(xycb,8a) { D = RES(1, RM(EA) ); WM( EA,D ); } /* RES 1,D=(XY+o) */ +OP(xycb,8b) { E = RES(1, RM(EA) ); WM( EA,E ); } /* RES 1,E=(XY+o) */ +OP(xycb,8c) { H = RES(1, RM(EA) ); WM( EA,H ); } /* RES 1,H=(XY+o) */ +OP(xycb,8d) { L = RES(1, RM(EA) ); WM( EA,L ); } /* RES 1,L=(XY+o) */ +OP(xycb,8e) { WM( EA, RES(1,RM(EA)) ); } /* RES 1,(XY+o) */ +OP(xycb,8f) { A = RES(1, RM(EA) ); WM( EA,A ); } /* RES 1,A=(XY+o) */ + +OP(xycb,90) { B = RES(2, RM(EA) ); WM( EA,B ); } /* RES 2,B=(XY+o) */ +OP(xycb,91) { C = RES(2, RM(EA) ); WM( EA,C ); } /* RES 2,C=(XY+o) */ +OP(xycb,92) { D = RES(2, RM(EA) ); WM( EA,D ); } /* RES 2,D=(XY+o) */ +OP(xycb,93) { E = RES(2, RM(EA) ); WM( EA,E ); } /* RES 2,E=(XY+o) */ +OP(xycb,94) { H = RES(2, RM(EA) ); WM( EA,H ); } /* RES 2,H=(XY+o) */ +OP(xycb,95) { L = RES(2, RM(EA) ); WM( EA,L ); } /* RES 2,L=(XY+o) */ +OP(xycb,96) { WM( EA, RES(2,RM(EA)) ); } /* RES 2,(XY+o) */ +OP(xycb,97) { A = RES(2, RM(EA) ); WM( EA,A ); } /* RES 2,A=(XY+o) */ + +OP(xycb,98) { B = RES(3, RM(EA) ); WM( EA,B ); } /* RES 3,B=(XY+o) */ +OP(xycb,99) { C = RES(3, RM(EA) ); WM( EA,C ); } /* RES 3,C=(XY+o) */ +OP(xycb,9a) { D = RES(3, RM(EA) ); WM( EA,D ); } /* RES 3,D=(XY+o) */ +OP(xycb,9b) { E = RES(3, RM(EA) ); WM( EA,E ); } /* RES 3,E=(XY+o) */ +OP(xycb,9c) { H = RES(3, RM(EA) ); WM( EA,H ); } /* RES 3,H=(XY+o) */ +OP(xycb,9d) { L = RES(3, RM(EA) ); WM( EA,L ); } /* RES 3,L=(XY+o) */ +OP(xycb,9e) { WM( EA, RES(3,RM(EA)) ); } /* RES 3,(XY+o) */ +OP(xycb,9f) { A = RES(3, RM(EA) ); WM( EA,A ); } /* RES 3,A=(XY+o) */ + +OP(xycb,a0) { B = RES(4, RM(EA) ); WM( EA,B ); } /* RES 4,B=(XY+o) */ +OP(xycb,a1) { C = RES(4, RM(EA) ); WM( EA,C ); } /* RES 4,C=(XY+o) */ +OP(xycb,a2) { D = RES(4, RM(EA) ); WM( EA,D ); } /* RES 4,D=(XY+o) */ +OP(xycb,a3) { E = RES(4, RM(EA) ); WM( EA,E ); } /* RES 4,E=(XY+o) */ +OP(xycb,a4) { H = RES(4, RM(EA) ); WM( EA,H ); } /* RES 4,H=(XY+o) */ +OP(xycb,a5) { L = RES(4, RM(EA) ); WM( EA,L ); } /* RES 4,L=(XY+o) */ +OP(xycb,a6) { WM( EA, RES(4,RM(EA)) ); } /* RES 4,(XY+o) */ +OP(xycb,a7) { A = RES(4, RM(EA) ); WM( EA,A ); } /* RES 4,A=(XY+o) */ + +OP(xycb,a8) { B = RES(5, RM(EA) ); WM( EA,B ); } /* RES 5,B=(XY+o) */ +OP(xycb,a9) { C = RES(5, RM(EA) ); WM( EA,C ); } /* RES 5,C=(XY+o) */ +OP(xycb,aa) { D = RES(5, RM(EA) ); WM( EA,D ); } /* RES 5,D=(XY+o) */ +OP(xycb,ab) { E = RES(5, RM(EA) ); WM( EA,E ); } /* RES 5,E=(XY+o) */ +OP(xycb,ac) { H = RES(5, RM(EA) ); WM( EA,H ); } /* RES 5,H=(XY+o) */ +OP(xycb,ad) { L = RES(5, RM(EA) ); WM( EA,L ); } /* RES 5,L=(XY+o) */ +OP(xycb,ae) { WM( EA, RES(5,RM(EA)) ); } /* RES 5,(XY+o) */ +OP(xycb,af) { A = RES(5, RM(EA) ); WM( EA,A ); } /* RES 5,A=(XY+o) */ + +OP(xycb,b0) { B = RES(6, RM(EA) ); WM( EA,B ); } /* RES 6,B=(XY+o) */ +OP(xycb,b1) { C = RES(6, RM(EA) ); WM( EA,C ); } /* RES 6,C=(XY+o) */ +OP(xycb,b2) { D = RES(6, RM(EA) ); WM( EA,D ); } /* RES 6,D=(XY+o) */ +OP(xycb,b3) { E = RES(6, RM(EA) ); WM( EA,E ); } /* RES 6,E=(XY+o) */ +OP(xycb,b4) { H = RES(6, RM(EA) ); WM( EA,H ); } /* RES 6,H=(XY+o) */ +OP(xycb,b5) { L = RES(6, RM(EA) ); WM( EA,L ); } /* RES 6,L=(XY+o) */ +OP(xycb,b6) { WM( EA, RES(6,RM(EA)) ); } /* RES 6,(XY+o) */ +OP(xycb,b7) { A = RES(6, RM(EA) ); WM( EA,A ); } /* RES 6,A=(XY+o) */ + +OP(xycb,b8) { B = RES(7, RM(EA) ); WM( EA,B ); } /* RES 7,B=(XY+o) */ +OP(xycb,b9) { C = RES(7, RM(EA) ); WM( EA,C ); } /* RES 7,C=(XY+o) */ +OP(xycb,ba) { D = RES(7, RM(EA) ); WM( EA,D ); } /* RES 7,D=(XY+o) */ +OP(xycb,bb) { E = RES(7, RM(EA) ); WM( EA,E ); } /* RES 7,E=(XY+o) */ +OP(xycb,bc) { H = RES(7, RM(EA) ); WM( EA,H ); } /* RES 7,H=(XY+o) */ +OP(xycb,bd) { L = RES(7, RM(EA) ); WM( EA,L ); } /* RES 7,L=(XY+o) */ +OP(xycb,be) { WM( EA, RES(7,RM(EA)) ); } /* RES 7,(XY+o) */ +OP(xycb,bf) { A = RES(7, RM(EA) ); WM( EA,A ); } /* RES 7,A=(XY+o) */ + +OP(xycb,c0) { B = SET(0, RM(EA) ); WM( EA,B ); } /* SET 0,B=(XY+o) */ +OP(xycb,c1) { C = SET(0, RM(EA) ); WM( EA,C ); } /* SET 0,C=(XY+o) */ +OP(xycb,c2) { D = SET(0, RM(EA) ); WM( EA,D ); } /* SET 0,D=(XY+o) */ +OP(xycb,c3) { E = SET(0, RM(EA) ); WM( EA,E ); } /* SET 0,E=(XY+o) */ +OP(xycb,c4) { H = SET(0, RM(EA) ); WM( EA,H ); } /* SET 0,H=(XY+o) */ +OP(xycb,c5) { L = SET(0, RM(EA) ); WM( EA,L ); } /* SET 0,L=(XY+o) */ +OP(xycb,c6) { WM( EA, SET(0,RM(EA)) ); } /* SET 0,(XY+o) */ +OP(xycb,c7) { A = SET(0, RM(EA) ); WM( EA,A ); } /* SET 0,A=(XY+o) */ + +OP(xycb,c8) { B = SET(1, RM(EA) ); WM( EA,B ); } /* SET 1,B=(XY+o) */ +OP(xycb,c9) { C = SET(1, RM(EA) ); WM( EA,C ); } /* SET 1,C=(XY+o) */ +OP(xycb,ca) { D = SET(1, RM(EA) ); WM( EA,D ); } /* SET 1,D=(XY+o) */ +OP(xycb,cb) { E = SET(1, RM(EA) ); WM( EA,E ); } /* SET 1,E=(XY+o) */ +OP(xycb,cc) { H = SET(1, RM(EA) ); WM( EA,H ); } /* SET 1,H=(XY+o) */ +OP(xycb,cd) { L = SET(1, RM(EA) ); WM( EA,L ); } /* SET 1,L=(XY+o) */ +OP(xycb,ce) { WM( EA, SET(1,RM(EA)) ); } /* SET 1,(XY+o) */ +OP(xycb,cf) { A = SET(1, RM(EA) ); WM( EA,A ); } /* SET 1,A=(XY+o) */ + +OP(xycb,d0) { B = SET(2, RM(EA) ); WM( EA,B ); } /* SET 2,B=(XY+o) */ +OP(xycb,d1) { C = SET(2, RM(EA) ); WM( EA,C ); } /* SET 2,C=(XY+o) */ +OP(xycb,d2) { D = SET(2, RM(EA) ); WM( EA,D ); } /* SET 2,D=(XY+o) */ +OP(xycb,d3) { E = SET(2, RM(EA) ); WM( EA,E ); } /* SET 2,E=(XY+o) */ +OP(xycb,d4) { H = SET(2, RM(EA) ); WM( EA,H ); } /* SET 2,H=(XY+o) */ +OP(xycb,d5) { L = SET(2, RM(EA) ); WM( EA,L ); } /* SET 2,L=(XY+o) */ +OP(xycb,d6) { WM( EA, SET(2,RM(EA)) ); } /* SET 2,(XY+o) */ +OP(xycb,d7) { A = SET(2, RM(EA) ); WM( EA,A ); } /* SET 2,A=(XY+o) */ + +OP(xycb,d8) { B = SET(3, RM(EA) ); WM( EA,B ); } /* SET 3,B=(XY+o) */ +OP(xycb,d9) { C = SET(3, RM(EA) ); WM( EA,C ); } /* SET 3,C=(XY+o) */ +OP(xycb,da) { D = SET(3, RM(EA) ); WM( EA,D ); } /* SET 3,D=(XY+o) */ +OP(xycb,db) { E = SET(3, RM(EA) ); WM( EA,E ); } /* SET 3,E=(XY+o) */ +OP(xycb,dc) { H = SET(3, RM(EA) ); WM( EA,H ); } /* SET 3,H=(XY+o) */ +OP(xycb,dd) { L = SET(3, RM(EA) ); WM( EA,L ); } /* SET 3,L=(XY+o) */ +OP(xycb,de) { WM( EA, SET(3,RM(EA)) ); } /* SET 3,(XY+o) */ +OP(xycb,df) { A = SET(3, RM(EA) ); WM( EA,A ); } /* SET 3,A=(XY+o) */ + +OP(xycb,e0) { B = SET(4, RM(EA) ); WM( EA,B ); } /* SET 4,B=(XY+o) */ +OP(xycb,e1) { C = SET(4, RM(EA) ); WM( EA,C ); } /* SET 4,C=(XY+o) */ +OP(xycb,e2) { D = SET(4, RM(EA) ); WM( EA,D ); } /* SET 4,D=(XY+o) */ +OP(xycb,e3) { E = SET(4, RM(EA) ); WM( EA,E ); } /* SET 4,E=(XY+o) */ +OP(xycb,e4) { H = SET(4, RM(EA) ); WM( EA,H ); } /* SET 4,H=(XY+o) */ +OP(xycb,e5) { L = SET(4, RM(EA) ); WM( EA,L ); } /* SET 4,L=(XY+o) */ +OP(xycb,e6) { WM( EA, SET(4,RM(EA)) ); } /* SET 4,(XY+o) */ +OP(xycb,e7) { A = SET(4, RM(EA) ); WM( EA,A ); } /* SET 4,A=(XY+o) */ + +OP(xycb,e8) { B = SET(5, RM(EA) ); WM( EA,B ); } /* SET 5,B=(XY+o) */ +OP(xycb,e9) { C = SET(5, RM(EA) ); WM( EA,C ); } /* SET 5,C=(XY+o) */ +OP(xycb,ea) { D = SET(5, RM(EA) ); WM( EA,D ); } /* SET 5,D=(XY+o) */ +OP(xycb,eb) { E = SET(5, RM(EA) ); WM( EA,E ); } /* SET 5,E=(XY+o) */ +OP(xycb,ec) { H = SET(5, RM(EA) ); WM( EA,H ); } /* SET 5,H=(XY+o) */ +OP(xycb,ed) { L = SET(5, RM(EA) ); WM( EA,L ); } /* SET 5,L=(XY+o) */ +OP(xycb,ee) { WM( EA, SET(5,RM(EA)) ); } /* SET 5,(XY+o) */ +OP(xycb,ef) { A = SET(5, RM(EA) ); WM( EA,A ); } /* SET 5,A=(XY+o) */ + +OP(xycb,f0) { B = SET(6, RM(EA) ); WM( EA,B ); } /* SET 6,B=(XY+o) */ +OP(xycb,f1) { C = SET(6, RM(EA) ); WM( EA,C ); } /* SET 6,C=(XY+o) */ +OP(xycb,f2) { D = SET(6, RM(EA) ); WM( EA,D ); } /* SET 6,D=(XY+o) */ +OP(xycb,f3) { E = SET(6, RM(EA) ); WM( EA,E ); } /* SET 6,E=(XY+o) */ +OP(xycb,f4) { H = SET(6, RM(EA) ); WM( EA,H ); } /* SET 6,H=(XY+o) */ +OP(xycb,f5) { L = SET(6, RM(EA) ); WM( EA,L ); } /* SET 6,L=(XY+o) */ +OP(xycb,f6) { WM( EA, SET(6,RM(EA)) ); } /* SET 6,(XY+o) */ +OP(xycb,f7) { A = SET(6, RM(EA) ); WM( EA,A ); } /* SET 6,A=(XY+o) */ + +OP(xycb,f8) { B = SET(7, RM(EA) ); WM( EA,B ); } /* SET 7,B=(XY+o) */ +OP(xycb,f9) { C = SET(7, RM(EA) ); WM( EA,C ); } /* SET 7,C=(XY+o) */ +OP(xycb,fa) { D = SET(7, RM(EA) ); WM( EA,D ); } /* SET 7,D=(XY+o) */ +OP(xycb,fb) { E = SET(7, RM(EA) ); WM( EA,E ); } /* SET 7,E=(XY+o) */ +OP(xycb,fc) { H = SET(7, RM(EA) ); WM( EA,H ); } /* SET 7,H=(XY+o) */ +OP(xycb,fd) { L = SET(7, RM(EA) ); WM( EA,L ); } /* SET 7,L=(XY+o) */ +OP(xycb,fe) { WM( EA, SET(7,RM(EA)) ); } /* SET 7,(XY+o) */ +OP(xycb,ff) { A = SET(7, RM(EA) ); WM( EA,A ); } /* SET 7,A=(XY+o) */ + +OP(illegal,1) { +// logerror("Z80 #%d ill. opcode $%02x $%02x\n", +// cpu_getactivecpu(), cpu_readop((PCD-1)&0xffff), cpu_readop(PCD)); +} + +/********************************************************** + * IX register related opcodes (DD prefix) + **********************************************************/ +OP(dd,00) { illegal_1(); op_00(); } /* DB DD */ +OP(dd,01) { illegal_1(); op_01(); } /* DB DD */ +OP(dd,02) { illegal_1(); op_02(); } /* DB DD */ +OP(dd,03) { illegal_1(); op_03(); } /* DB DD */ +OP(dd,04) { illegal_1(); op_04(); } /* DB DD */ +OP(dd,05) { illegal_1(); op_05(); } /* DB DD */ +OP(dd,06) { illegal_1(); op_06(); } /* DB DD */ +OP(dd,07) { illegal_1(); op_07(); } /* DB DD */ + +OP(dd,08) { illegal_1(); op_08(); } /* DB DD */ +OP(dd,09) { ADD16(ix,bc); } /* ADD IX,BC */ +OP(dd,0a) { illegal_1(); op_0a(); } /* DB DD */ +OP(dd,0b) { illegal_1(); op_0b(); } /* DB DD */ +OP(dd,0c) { illegal_1(); op_0c(); } /* DB DD */ +OP(dd,0d) { illegal_1(); op_0d(); } /* DB DD */ +OP(dd,0e) { illegal_1(); op_0e(); } /* DB DD */ +OP(dd,0f) { illegal_1(); op_0f(); } /* DB DD */ + +OP(dd,10) { illegal_1(); op_10(); } /* DB DD */ +OP(dd,11) { illegal_1(); op_11(); } /* DB DD */ +OP(dd,12) { illegal_1(); op_12(); } /* DB DD */ +OP(dd,13) { illegal_1(); op_13(); } /* DB DD */ +OP(dd,14) { illegal_1(); op_14(); } /* DB DD */ +OP(dd,15) { illegal_1(); op_15(); } /* DB DD */ +OP(dd,16) { illegal_1(); op_16(); } /* DB DD */ +OP(dd,17) { illegal_1(); op_17(); } /* DB DD */ + +OP(dd,18) { illegal_1(); op_18(); } /* DB DD */ +OP(dd,19) { ADD16(ix,de); } /* ADD IX,DE */ +OP(dd,1a) { illegal_1(); op_1a(); } /* DB DD */ +OP(dd,1b) { illegal_1(); op_1b(); } /* DB DD */ +OP(dd,1c) { illegal_1(); op_1c(); } /* DB DD */ +OP(dd,1d) { illegal_1(); op_1d(); } /* DB DD */ +OP(dd,1e) { illegal_1(); op_1e(); } /* DB DD */ +OP(dd,1f) { illegal_1(); op_1f(); } /* DB DD */ + +OP(dd,20) { illegal_1(); op_20(); } /* DB DD */ +OP(dd,21) { IX = ARG16(); } /* LD IX,w */ +OP(dd,22) { EA = ARG16(); WM16( EA, &Z80.ix ); } /* LD (w),IX */ +OP(dd,23) { IX++; } /* INC IX */ +OP(dd,24) { HX = INC(HX); } /* INC HX */ +OP(dd,25) { HX = DEC(HX); } /* DEC HX */ +OP(dd,26) { HX = ARG(); } /* LD HX,n */ +OP(dd,27) { illegal_1(); op_27(); } /* DB DD */ + +OP(dd,28) { illegal_1(); op_28(); } /* DB DD */ +OP(dd,29) { ADD16(ix,ix); } /* ADD IX,IX */ +OP(dd,2a) { EA = ARG16(); RM16( EA, &Z80.ix ); } /* LD IX,(w) */ +OP(dd,2b) { IX--; } /* DEC IX */ +OP(dd,2c) { LX = INC(LX); } /* INC LX */ +OP(dd,2d) { LX = DEC(LX); } /* DEC LX */ +OP(dd,2e) { LX = ARG(); } /* LD LX,n */ +OP(dd,2f) { illegal_1(); op_2f(); } /* DB DD */ + +OP(dd,30) { illegal_1(); op_30(); } /* DB DD */ +OP(dd,31) { illegal_1(); op_31(); } /* DB DD */ +OP(dd,32) { illegal_1(); op_32(); } /* DB DD */ +OP(dd,33) { illegal_1(); op_33(); } /* DB DD */ +OP(dd,34) { EAX; WM( EA, INC(RM(EA)) ); } /* INC (IX+o) */ +OP(dd,35) { EAX; WM( EA, DEC(RM(EA)) ); } /* DEC (IX+o) */ +OP(dd,36) { EAX; WM( EA, ARG() ); } /* LD (IX+o),n */ +OP(dd,37) { illegal_1(); op_37(); } /* DB DD */ + +OP(dd,38) { illegal_1(); op_38(); } /* DB DD */ +OP(dd,39) { ADD16(ix,sp); } /* ADD IX,SP */ +OP(dd,3a) { illegal_1(); op_3a(); } /* DB DD */ +OP(dd,3b) { illegal_1(); op_3b(); } /* DB DD */ +OP(dd,3c) { illegal_1(); op_3c(); } /* DB DD */ +OP(dd,3d) { illegal_1(); op_3d(); } /* DB DD */ +OP(dd,3e) { illegal_1(); op_3e(); } /* DB DD */ +OP(dd,3f) { illegal_1(); op_3f(); } /* DB DD */ + +OP(dd,40) { illegal_1(); op_40(); } /* DB DD */ +OP(dd,41) { illegal_1(); op_41(); } /* DB DD */ +OP(dd,42) { illegal_1(); op_42(); } /* DB DD */ +OP(dd,43) { illegal_1(); op_43(); } /* DB DD */ +OP(dd,44) { B = HX; } /* LD B,HX */ +OP(dd,45) { B = LX; } /* LD B,LX */ +OP(dd,46) { EAX; B = RM(EA); } /* LD B,(IX+o) */ +OP(dd,47) { illegal_1(); op_47(); } /* DB DD */ + +OP(dd,48) { illegal_1(); op_48(); } /* DB DD */ +OP(dd,49) { illegal_1(); op_49(); } /* DB DD */ +OP(dd,4a) { illegal_1(); op_4a(); } /* DB DD */ +OP(dd,4b) { illegal_1(); op_4b(); } /* DB DD */ +OP(dd,4c) { C = HX; } /* LD C,HX */ +OP(dd,4d) { C = LX; } /* LD C,LX */ +OP(dd,4e) { EAX; C = RM(EA); } /* LD C,(IX+o) */ +OP(dd,4f) { illegal_1(); op_4f(); } /* DB DD */ + +OP(dd,50) { illegal_1(); op_50(); } /* DB DD */ +OP(dd,51) { illegal_1(); op_51(); } /* DB DD */ +OP(dd,52) { illegal_1(); op_52(); } /* DB DD */ +OP(dd,53) { illegal_1(); op_53(); } /* DB DD */ +OP(dd,54) { D = HX; } /* LD D,HX */ +OP(dd,55) { D = LX; } /* LD D,LX */ +OP(dd,56) { EAX; D = RM(EA); } /* LD D,(IX+o) */ +OP(dd,57) { illegal_1(); op_57(); } /* DB DD */ + +OP(dd,58) { illegal_1(); op_58(); } /* DB DD */ +OP(dd,59) { illegal_1(); op_59(); } /* DB DD */ +OP(dd,5a) { illegal_1(); op_5a(); } /* DB DD */ +OP(dd,5b) { illegal_1(); op_5b(); } /* DB DD */ +OP(dd,5c) { E = HX; } /* LD E,HX */ +OP(dd,5d) { E = LX; } /* LD E,LX */ +OP(dd,5e) { EAX; E = RM(EA); } /* LD E,(IX+o) */ +OP(dd,5f) { illegal_1(); op_5f(); } /* DB DD */ + +OP(dd,60) { HX = B; } /* LD HX,B */ +OP(dd,61) { HX = C; } /* LD HX,C */ +OP(dd,62) { HX = D; } /* LD HX,D */ +OP(dd,63) { HX = E; } /* LD HX,E */ +OP(dd,64) { } /* LD HX,HX */ +OP(dd,65) { HX = LX; } /* LD HX,LX */ +OP(dd,66) { EAX; H = RM(EA); } /* LD H,(IX+o) */ +OP(dd,67) { HX = A; } /* LD HX,A */ + +OP(dd,68) { LX = B; } /* LD LX,B */ +OP(dd,69) { LX = C; } /* LD LX,C */ +OP(dd,6a) { LX = D; } /* LD LX,D */ +OP(dd,6b) { LX = E; } /* LD LX,E */ +OP(dd,6c) { LX = HX; } /* LD LX,HX */ +OP(dd,6d) { } /* LD LX,LX */ +OP(dd,6e) { EAX; L = RM(EA); } /* LD L,(IX+o) */ +OP(dd,6f) { LX = A; } /* LD LX,A */ + +OP(dd,70) { EAX; WM( EA, B ); } /* LD (IX+o),B */ +OP(dd,71) { EAX; WM( EA, C ); } /* LD (IX+o),C */ +OP(dd,72) { EAX; WM( EA, D ); } /* LD (IX+o),D */ +OP(dd,73) { EAX; WM( EA, E ); } /* LD (IX+o),E */ +OP(dd,74) { EAX; WM( EA, H ); } /* LD (IX+o),H */ +OP(dd,75) { EAX; WM( EA, L ); } /* LD (IX+o),L */ +OP(dd,76) { illegal_1(); op_76(); } /* DB DD */ +OP(dd,77) { EAX; WM( EA, A ); } /* LD (IX+o),A */ + +OP(dd,78) { illegal_1(); op_78(); } /* DB DD */ +OP(dd,79) { illegal_1(); op_79(); } /* DB DD */ +OP(dd,7a) { illegal_1(); op_7a(); } /* DB DD */ +OP(dd,7b) { illegal_1(); op_7b(); } /* DB DD */ +OP(dd,7c) { A = HX; } /* LD A,HX */ +OP(dd,7d) { A = LX; } /* LD A,LX */ +OP(dd,7e) { EAX; A = RM(EA); } /* LD A,(IX+o) */ +OP(dd,7f) { illegal_1(); op_7f(); } /* DB DD */ + +OP(dd,80) { illegal_1(); op_80(); } /* DB DD */ +OP(dd,81) { illegal_1(); op_81(); } /* DB DD */ +OP(dd,82) { illegal_1(); op_82(); } /* DB DD */ +OP(dd,83) { illegal_1(); op_83(); } /* DB DD */ +OP(dd,84) { ADD(HX); } /* ADD A,HX */ +OP(dd,85) { ADD(LX); } /* ADD A,LX */ +OP(dd,86) { EAX; ADD(RM(EA)); } /* ADD A,(IX+o) */ +OP(dd,87) { illegal_1(); op_87(); } /* DB DD */ + +OP(dd,88) { illegal_1(); op_88(); } /* DB DD */ +OP(dd,89) { illegal_1(); op_89(); } /* DB DD */ +OP(dd,8a) { illegal_1(); op_8a(); } /* DB DD */ +OP(dd,8b) { illegal_1(); op_8b(); } /* DB DD */ +OP(dd,8c) { ADC(HX); } /* ADC A,HX */ +OP(dd,8d) { ADC(LX); } /* ADC A,LX */ +OP(dd,8e) { EAX; ADC(RM(EA)); } /* ADC A,(IX+o) */ +OP(dd,8f) { illegal_1(); op_8f(); } /* DB DD */ + +OP(dd,90) { illegal_1(); op_90(); } /* DB DD */ +OP(dd,91) { illegal_1(); op_91(); } /* DB DD */ +OP(dd,92) { illegal_1(); op_92(); } /* DB DD */ +OP(dd,93) { illegal_1(); op_93(); } /* DB DD */ +OP(dd,94) { SUB(HX); } /* SUB HX */ +OP(dd,95) { SUB(LX); } /* SUB LX */ +OP(dd,96) { EAX; SUB(RM(EA)); } /* SUB (IX+o) */ +OP(dd,97) { illegal_1(); op_97(); } /* DB DD */ + +OP(dd,98) { illegal_1(); op_98(); } /* DB DD */ +OP(dd,99) { illegal_1(); op_99(); } /* DB DD */ +OP(dd,9a) { illegal_1(); op_9a(); } /* DB DD */ +OP(dd,9b) { illegal_1(); op_9b(); } /* DB DD */ +OP(dd,9c) { SBC(HX); } /* SBC A,HX */ +OP(dd,9d) { SBC(LX); } /* SBC A,LX */ +OP(dd,9e) { EAX; SBC(RM(EA)); } /* SBC A,(IX+o) */ +OP(dd,9f) { illegal_1(); op_9f(); } /* DB DD */ + +OP(dd,a0) { illegal_1(); op_a0(); } /* DB DD */ +OP(dd,a1) { illegal_1(); op_a1(); } /* DB DD */ +OP(dd,a2) { illegal_1(); op_a2(); } /* DB DD */ +OP(dd,a3) { illegal_1(); op_a3(); } /* DB DD */ +OP(dd,a4) { AND(HX); } /* AND HX */ +OP(dd,a5) { AND(LX); } /* AND LX */ +OP(dd,a6) { EAX; AND(RM(EA)); } /* AND (IX+o) */ +OP(dd,a7) { illegal_1(); op_a7(); } /* DB DD */ + +OP(dd,a8) { illegal_1(); op_a8(); } /* DB DD */ +OP(dd,a9) { illegal_1(); op_a9(); } /* DB DD */ +OP(dd,aa) { illegal_1(); op_aa(); } /* DB DD */ +OP(dd,ab) { illegal_1(); op_ab(); } /* DB DD */ +OP(dd,ac) { XOR(HX); } /* XOR HX */ +OP(dd,ad) { XOR(LX); } /* XOR LX */ +OP(dd,ae) { EAX; XOR(RM(EA)); } /* XOR (IX+o) */ +OP(dd,af) { illegal_1(); op_af(); } /* DB DD */ + +OP(dd,b0) { illegal_1(); op_b0(); } /* DB DD */ +OP(dd,b1) { illegal_1(); op_b1(); } /* DB DD */ +OP(dd,b2) { illegal_1(); op_b2(); } /* DB DD */ +OP(dd,b3) { illegal_1(); op_b3(); } /* DB DD */ +OP(dd,b4) { OR(HX); } /* OR HX */ +OP(dd,b5) { OR(LX); } /* OR LX */ +OP(dd,b6) { EAX; OR(RM(EA)); } /* OR (IX+o) */ +OP(dd,b7) { illegal_1(); op_b7(); } /* DB DD */ + +OP(dd,b8) { illegal_1(); op_b8(); } /* DB DD */ +OP(dd,b9) { illegal_1(); op_b9(); } /* DB DD */ +OP(dd,ba) { illegal_1(); op_ba(); } /* DB DD */ +OP(dd,bb) { illegal_1(); op_bb(); } /* DB DD */ +OP(dd,bc) { CP(HX); } /* CP HX */ +OP(dd,bd) { CP(LX); } /* CP LX */ +OP(dd,be) { EAX; CP(RM(EA)); } /* CP (IX+o) */ +OP(dd,bf) { illegal_1(); op_bf(); } /* DB DD */ + +OP(dd,c0) { illegal_1(); op_c0(); } /* DB DD */ +OP(dd,c1) { illegal_1(); op_c1(); } /* DB DD */ +OP(dd,c2) { illegal_1(); op_c2(); } /* DB DD */ +OP(dd,c3) { illegal_1(); op_c3(); } /* DB DD */ +OP(dd,c4) { illegal_1(); op_c4(); } /* DB DD */ +OP(dd,c5) { illegal_1(); op_c5(); } /* DB DD */ +OP(dd,c6) { illegal_1(); op_c6(); } /* DB DD */ +OP(dd,c7) { illegal_1(); op_c7(); } /* DB DD */ + +OP(dd,c8) { illegal_1(); op_c8(); } /* DB DD */ +OP(dd,c9) { illegal_1(); op_c9(); } /* DB DD */ +OP(dd,ca) { illegal_1(); op_ca(); } /* DB DD */ +OP(dd,cb) { EAX; EXEC(xycb,ARG()); } /* ** DD CB xx */ +OP(dd,cc) { illegal_1(); op_cc(); } /* DB DD */ +OP(dd,cd) { illegal_1(); op_cd(); } /* DB DD */ +OP(dd,ce) { illegal_1(); op_ce(); } /* DB DD */ +OP(dd,cf) { illegal_1(); op_cf(); } /* DB DD */ + +OP(dd,d0) { illegal_1(); op_d0(); } /* DB DD */ +OP(dd,d1) { illegal_1(); op_d1(); } /* DB DD */ +OP(dd,d2) { illegal_1(); op_d2(); } /* DB DD */ +OP(dd,d3) { illegal_1(); op_d3(); } /* DB DD */ +OP(dd,d4) { illegal_1(); op_d4(); } /* DB DD */ +OP(dd,d5) { illegal_1(); op_d5(); } /* DB DD */ +OP(dd,d6) { illegal_1(); op_d6(); } /* DB DD */ +OP(dd,d7) { illegal_1(); op_d7(); } /* DB DD */ + +OP(dd,d8) { illegal_1(); op_d8(); } /* DB DD */ +OP(dd,d9) { illegal_1(); op_d9(); } /* DB DD */ +OP(dd,da) { illegal_1(); op_da(); } /* DB DD */ +OP(dd,db) { illegal_1(); op_db(); } /* DB DD */ +OP(dd,dc) { illegal_1(); op_dc(); } /* DB DD */ +OP(dd,dd) { illegal_1(); op_dd(); } /* DB DD */ +OP(dd,de) { illegal_1(); op_de(); } /* DB DD */ +OP(dd,df) { illegal_1(); op_df(); } /* DB DD */ + +OP(dd,e0) { illegal_1(); op_e0(); } /* DB DD */ +OP(dd,e1) { POP( ix ); } /* POP IX */ +OP(dd,e2) { illegal_1(); op_e2(); } /* DB DD */ +OP(dd,e3) { EXSP( ix ); } /* EX (SP),IX */ +OP(dd,e4) { illegal_1(); op_e4(); } /* DB DD */ +OP(dd,e5) { PUSH( ix ); } /* PUSH IX */ +OP(dd,e6) { illegal_1(); op_e6(); } /* DB DD */ +OP(dd,e7) { illegal_1(); op_e7(); } /* DB DD */ + +OP(dd,e8) { illegal_1(); op_e8(); } /* DB DD */ +OP(dd,e9) { PC = IX; change_pc(PCD); } /* JP (IX) */ +OP(dd,ea) { illegal_1(); op_ea(); } /* DB DD */ +OP(dd,eb) { illegal_1(); op_eb(); } /* DB DD */ +OP(dd,ec) { illegal_1(); op_ec(); } /* DB DD */ +OP(dd,ed) { illegal_1(); op_ed(); } /* DB DD */ +OP(dd,ee) { illegal_1(); op_ee(); } /* DB DD */ +OP(dd,ef) { illegal_1(); op_ef(); } /* DB DD */ + +OP(dd,f0) { illegal_1(); op_f0(); } /* DB DD */ +OP(dd,f1) { illegal_1(); op_f1(); } /* DB DD */ +OP(dd,f2) { illegal_1(); op_f2(); } /* DB DD */ +OP(dd,f3) { illegal_1(); op_f3(); } /* DB DD */ +OP(dd,f4) { illegal_1(); op_f4(); } /* DB DD */ +OP(dd,f5) { illegal_1(); op_f5(); } /* DB DD */ +OP(dd,f6) { illegal_1(); op_f6(); } /* DB DD */ +OP(dd,f7) { illegal_1(); op_f7(); } /* DB DD */ + +OP(dd,f8) { illegal_1(); op_f8(); } /* DB DD */ +OP(dd,f9) { SP = IX; } /* LD SP,IX */ +OP(dd,fa) { illegal_1(); op_fa(); } /* DB DD */ +OP(dd,fb) { illegal_1(); op_fb(); } /* DB DD */ +OP(dd,fc) { illegal_1(); op_fc(); } /* DB DD */ +OP(dd,fd) { illegal_1(); op_fd(); } /* DB DD */ +OP(dd,fe) { illegal_1(); op_fe(); } /* DB DD */ +OP(dd,ff) { illegal_1(); op_ff(); } /* DB DD */ + +/********************************************************** + * IY register related opcodes (FD prefix) + **********************************************************/ +OP(fd,00) { illegal_1(); op_00(); } /* DB FD */ +OP(fd,01) { illegal_1(); op_01(); } /* DB FD */ +OP(fd,02) { illegal_1(); op_02(); } /* DB FD */ +OP(fd,03) { illegal_1(); op_03(); } /* DB FD */ +OP(fd,04) { illegal_1(); op_04(); } /* DB FD */ +OP(fd,05) { illegal_1(); op_05(); } /* DB FD */ +OP(fd,06) { illegal_1(); op_06(); } /* DB FD */ +OP(fd,07) { illegal_1(); op_07(); } /* DB FD */ + +OP(fd,08) { illegal_1(); op_08(); } /* DB FD */ +OP(fd,09) { ADD16(iy,bc); } /* ADD IY,BC */ +OP(fd,0a) { illegal_1(); op_0a(); } /* DB FD */ +OP(fd,0b) { illegal_1(); op_0b(); } /* DB FD */ +OP(fd,0c) { illegal_1(); op_0c(); } /* DB FD */ +OP(fd,0d) { illegal_1(); op_0d(); } /* DB FD */ +OP(fd,0e) { illegal_1(); op_0e(); } /* DB FD */ +OP(fd,0f) { illegal_1(); op_0f(); } /* DB FD */ + +OP(fd,10) { illegal_1(); op_10(); } /* DB FD */ +OP(fd,11) { illegal_1(); op_11(); } /* DB FD */ +OP(fd,12) { illegal_1(); op_12(); } /* DB FD */ +OP(fd,13) { illegal_1(); op_13(); } /* DB FD */ +OP(fd,14) { illegal_1(); op_14(); } /* DB FD */ +OP(fd,15) { illegal_1(); op_15(); } /* DB FD */ +OP(fd,16) { illegal_1(); op_16(); } /* DB FD */ +OP(fd,17) { illegal_1(); op_17(); } /* DB FD */ + +OP(fd,18) { illegal_1(); op_18(); } /* DB FD */ +OP(fd,19) { ADD16(iy,de); } /* ADD IY,DE */ +OP(fd,1a) { illegal_1(); op_1a(); } /* DB FD */ +OP(fd,1b) { illegal_1(); op_1b(); } /* DB FD */ +OP(fd,1c) { illegal_1(); op_1c(); } /* DB FD */ +OP(fd,1d) { illegal_1(); op_1d(); } /* DB FD */ +OP(fd,1e) { illegal_1(); op_1e(); } /* DB FD */ +OP(fd,1f) { illegal_1(); op_1f(); } /* DB FD */ + +OP(fd,20) { illegal_1(); op_20(); } /* DB FD */ +OP(fd,21) { IY = ARG16(); } /* LD IY,w */ +OP(fd,22) { EA = ARG16(); WM16( EA, &Z80.iy ); } /* LD (w),IY */ +OP(fd,23) { IY++; } /* INC IY */ +OP(fd,24) { HY = INC(HY); } /* INC HY */ +OP(fd,25) { HY = DEC(HY); } /* DEC HY */ +OP(fd,26) { HY = ARG(); } /* LD HY,n */ +OP(fd,27) { illegal_1(); op_27(); } /* DB FD */ + +OP(fd,28) { illegal_1(); op_28(); } /* DB FD */ +OP(fd,29) { ADD16(iy,iy); } /* ADD IY,IY */ +OP(fd,2a) { EA = ARG16(); RM16( EA, &Z80.iy ); } /* LD IY,(w) */ +OP(fd,2b) { IY--; } /* DEC IY */ +OP(fd,2c) { LY = INC(LY); } /* INC LY */ +OP(fd,2d) { LY = DEC(LY); } /* DEC LY */ +OP(fd,2e) { LY = ARG(); } /* LD LY,n */ +OP(fd,2f) { illegal_1(); op_2f(); } /* DB FD */ + +OP(fd,30) { illegal_1(); op_30(); } /* DB FD */ +OP(fd,31) { illegal_1(); op_31(); } /* DB FD */ +OP(fd,32) { illegal_1(); op_32(); } /* DB FD */ +OP(fd,33) { illegal_1(); op_33(); } /* DB FD */ +OP(fd,34) { EAY; WM( EA, INC(RM(EA)) ); } /* INC (IY+o) */ +OP(fd,35) { EAY; WM( EA, DEC(RM(EA)) ); } /* DEC (IY+o) */ +OP(fd,36) { EAY; WM( EA, ARG() ); } /* LD (IY+o),n */ +OP(fd,37) { illegal_1(); op_37(); } /* DB FD */ + +OP(fd,38) { illegal_1(); op_38(); } /* DB FD */ +OP(fd,39) { ADD16(iy,sp); } /* ADD IY,SP */ +OP(fd,3a) { illegal_1(); op_3a(); } /* DB FD */ +OP(fd,3b) { illegal_1(); op_3b(); } /* DB FD */ +OP(fd,3c) { illegal_1(); op_3c(); } /* DB FD */ +OP(fd,3d) { illegal_1(); op_3d(); } /* DB FD */ +OP(fd,3e) { illegal_1(); op_3e(); } /* DB FD */ +OP(fd,3f) { illegal_1(); op_3f(); } /* DB FD */ + +OP(fd,40) { illegal_1(); op_40(); } /* DB FD */ +OP(fd,41) { illegal_1(); op_41(); } /* DB FD */ +OP(fd,42) { illegal_1(); op_42(); } /* DB FD */ +OP(fd,43) { illegal_1(); op_43(); } /* DB FD */ +OP(fd,44) { B = HY; } /* LD B,HY */ +OP(fd,45) { B = LY; } /* LD B,LY */ +OP(fd,46) { EAY; B = RM(EA); } /* LD B,(IY+o) */ +OP(fd,47) { illegal_1(); op_47(); } /* DB FD */ + +OP(fd,48) { illegal_1(); op_48(); } /* DB FD */ +OP(fd,49) { illegal_1(); op_49(); } /* DB FD */ +OP(fd,4a) { illegal_1(); op_4a(); } /* DB FD */ +OP(fd,4b) { illegal_1(); op_4b(); } /* DB FD */ +OP(fd,4c) { C = HY; } /* LD C,HY */ +OP(fd,4d) { C = LY; } /* LD C,LY */ +OP(fd,4e) { EAY; C = RM(EA); } /* LD C,(IY+o) */ +OP(fd,4f) { illegal_1(); op_4f(); } /* DB FD */ + +OP(fd,50) { illegal_1(); op_50(); } /* DB FD */ +OP(fd,51) { illegal_1(); op_51(); } /* DB FD */ +OP(fd,52) { illegal_1(); op_52(); } /* DB FD */ +OP(fd,53) { illegal_1(); op_53(); } /* DB FD */ +OP(fd,54) { D = HY; } /* LD D,HY */ +OP(fd,55) { D = LY; } /* LD D,LY */ +OP(fd,56) { EAY; D = RM(EA); } /* LD D,(IY+o) */ +OP(fd,57) { illegal_1(); op_57(); } /* DB FD */ + +OP(fd,58) { illegal_1(); op_58(); } /* DB FD */ +OP(fd,59) { illegal_1(); op_59(); } /* DB FD */ +OP(fd,5a) { illegal_1(); op_5a(); } /* DB FD */ +OP(fd,5b) { illegal_1(); op_5b(); } /* DB FD */ +OP(fd,5c) { E = HY; } /* LD E,HY */ +OP(fd,5d) { E = LY; } /* LD E,LY */ +OP(fd,5e) { EAY; E = RM(EA); } /* LD E,(IY+o) */ +OP(fd,5f) { illegal_1(); op_5f(); } /* DB FD */ + +OP(fd,60) { HY = B; } /* LD HY,B */ +OP(fd,61) { HY = C; } /* LD HY,C */ +OP(fd,62) { HY = D; } /* LD HY,D */ +OP(fd,63) { HY = E; } /* LD HY,E */ +OP(fd,64) { } /* LD HY,HY */ +OP(fd,65) { HY = LY; } /* LD HY,LY */ +OP(fd,66) { EAY; H = RM(EA); } /* LD H,(IY+o) */ +OP(fd,67) { HY = A; } /* LD HY,A */ + +OP(fd,68) { LY = B; } /* LD LY,B */ +OP(fd,69) { LY = C; } /* LD LY,C */ +OP(fd,6a) { LY = D; } /* LD LY,D */ +OP(fd,6b) { LY = E; } /* LD LY,E */ +OP(fd,6c) { LY = HY; } /* LD LY,HY */ +OP(fd,6d) { } /* LD LY,LY */ +OP(fd,6e) { EAY; L = RM(EA); } /* LD L,(IY+o) */ +OP(fd,6f) { LY = A; } /* LD LY,A */ + +OP(fd,70) { EAY; WM( EA, B ); } /* LD (IY+o),B */ +OP(fd,71) { EAY; WM( EA, C ); } /* LD (IY+o),C */ +OP(fd,72) { EAY; WM( EA, D ); } /* LD (IY+o),D */ +OP(fd,73) { EAY; WM( EA, E ); } /* LD (IY+o),E */ +OP(fd,74) { EAY; WM( EA, H ); } /* LD (IY+o),H */ +OP(fd,75) { EAY; WM( EA, L ); } /* LD (IY+o),L */ +OP(fd,76) { illegal_1(); op_76(); } /* DB FD */ +OP(fd,77) { EAY; WM( EA, A ); } /* LD (IY+o),A */ + +OP(fd,78) { illegal_1(); op_78(); } /* DB FD */ +OP(fd,79) { illegal_1(); op_79(); } /* DB FD */ +OP(fd,7a) { illegal_1(); op_7a(); } /* DB FD */ +OP(fd,7b) { illegal_1(); op_7b(); } /* DB FD */ +OP(fd,7c) { A = HY; } /* LD A,HY */ +OP(fd,7d) { A = LY; } /* LD A,LY */ +OP(fd,7e) { EAY; A = RM(EA); } /* LD A,(IY+o) */ +OP(fd,7f) { illegal_1(); op_7f(); } /* DB FD */ + +OP(fd,80) { illegal_1(); op_80(); } /* DB FD */ +OP(fd,81) { illegal_1(); op_81(); } /* DB FD */ +OP(fd,82) { illegal_1(); op_82(); } /* DB FD */ +OP(fd,83) { illegal_1(); op_83(); } /* DB FD */ +OP(fd,84) { ADD(HY); } /* ADD A,HY */ +OP(fd,85) { ADD(LY); } /* ADD A,LY */ +OP(fd,86) { EAY; ADD(RM(EA)); } /* ADD A,(IY+o) */ +OP(fd,87) { illegal_1(); op_87(); } /* DB FD */ + +OP(fd,88) { illegal_1(); op_88(); } /* DB FD */ +OP(fd,89) { illegal_1(); op_89(); } /* DB FD */ +OP(fd,8a) { illegal_1(); op_8a(); } /* DB FD */ +OP(fd,8b) { illegal_1(); op_8b(); } /* DB FD */ +OP(fd,8c) { ADC(HY); } /* ADC A,HY */ +OP(fd,8d) { ADC(LY); } /* ADC A,LY */ +OP(fd,8e) { EAY; ADC(RM(EA)); } /* ADC A,(IY+o) */ +OP(fd,8f) { illegal_1(); op_8f(); } /* DB FD */ + +OP(fd,90) { illegal_1(); op_90(); } /* DB FD */ +OP(fd,91) { illegal_1(); op_91(); } /* DB FD */ +OP(fd,92) { illegal_1(); op_92(); } /* DB FD */ +OP(fd,93) { illegal_1(); op_93(); } /* DB FD */ +OP(fd,94) { SUB(HY); } /* SUB HY */ +OP(fd,95) { SUB(LY); } /* SUB LY */ +OP(fd,96) { EAY; SUB(RM(EA)); } /* SUB (IY+o) */ +OP(fd,97) { illegal_1(); op_97(); } /* DB FD */ + +OP(fd,98) { illegal_1(); op_98(); } /* DB FD */ +OP(fd,99) { illegal_1(); op_99(); } /* DB FD */ +OP(fd,9a) { illegal_1(); op_9a(); } /* DB FD */ +OP(fd,9b) { illegal_1(); op_9b(); } /* DB FD */ +OP(fd,9c) { SBC(HY); } /* SBC A,HY */ +OP(fd,9d) { SBC(LY); } /* SBC A,LY */ +OP(fd,9e) { EAY; SBC(RM(EA)); } /* SBC A,(IY+o) */ +OP(fd,9f) { illegal_1(); op_9f(); } /* DB FD */ + +OP(fd,a0) { illegal_1(); op_a0(); } /* DB FD */ +OP(fd,a1) { illegal_1(); op_a1(); } /* DB FD */ +OP(fd,a2) { illegal_1(); op_a2(); } /* DB FD */ +OP(fd,a3) { illegal_1(); op_a3(); } /* DB FD */ +OP(fd,a4) { AND(HY); } /* AND HY */ +OP(fd,a5) { AND(LY); } /* AND LY */ +OP(fd,a6) { EAY; AND(RM(EA)); } /* AND (IY+o) */ +OP(fd,a7) { illegal_1(); op_a7(); } /* DB FD */ + +OP(fd,a8) { illegal_1(); op_a8(); } /* DB FD */ +OP(fd,a9) { illegal_1(); op_a9(); } /* DB FD */ +OP(fd,aa) { illegal_1(); op_aa(); } /* DB FD */ +OP(fd,ab) { illegal_1(); op_ab(); } /* DB FD */ +OP(fd,ac) { XOR(HY); } /* XOR HY */ +OP(fd,ad) { XOR(LY); } /* XOR LY */ +OP(fd,ae) { EAY; XOR(RM(EA)); } /* XOR (IY+o) */ +OP(fd,af) { illegal_1(); op_af(); } /* DB FD */ + +OP(fd,b0) { illegal_1(); op_b0(); } /* DB FD */ +OP(fd,b1) { illegal_1(); op_b1(); } /* DB FD */ +OP(fd,b2) { illegal_1(); op_b2(); } /* DB FD */ +OP(fd,b3) { illegal_1(); op_b3(); } /* DB FD */ +OP(fd,b4) { OR(HY); } /* OR HY */ +OP(fd,b5) { OR(LY); } /* OR LY */ +OP(fd,b6) { EAY; OR(RM(EA)); } /* OR (IY+o) */ +OP(fd,b7) { illegal_1(); op_b7(); } /* DB FD */ + +OP(fd,b8) { illegal_1(); op_b8(); } /* DB FD */ +OP(fd,b9) { illegal_1(); op_b9(); } /* DB FD */ +OP(fd,ba) { illegal_1(); op_ba(); } /* DB FD */ +OP(fd,bb) { illegal_1(); op_bb(); } /* DB FD */ +OP(fd,bc) { CP(HY); } /* CP HY */ +OP(fd,bd) { CP(LY); } /* CP LY */ +OP(fd,be) { EAY; CP(RM(EA)); } /* CP (IY+o) */ +OP(fd,bf) { illegal_1(); op_bf(); } /* DB FD */ + +OP(fd,c0) { illegal_1(); op_c0(); } /* DB FD */ +OP(fd,c1) { illegal_1(); op_c1(); } /* DB FD */ +OP(fd,c2) { illegal_1(); op_c2(); } /* DB FD */ +OP(fd,c3) { illegal_1(); op_c3(); } /* DB FD */ +OP(fd,c4) { illegal_1(); op_c4(); } /* DB FD */ +OP(fd,c5) { illegal_1(); op_c5(); } /* DB FD */ +OP(fd,c6) { illegal_1(); op_c6(); } /* DB FD */ +OP(fd,c7) { illegal_1(); op_c7(); } /* DB FD */ + +OP(fd,c8) { illegal_1(); op_c8(); } /* DB FD */ +OP(fd,c9) { illegal_1(); op_c9(); } /* DB FD */ +OP(fd,ca) { illegal_1(); op_ca(); } /* DB FD */ +OP(fd,cb) { EAY; EXEC(xycb,ARG()); } /* ** FD CB xx */ +OP(fd,cc) { illegal_1(); op_cc(); } /* DB FD */ +OP(fd,cd) { illegal_1(); op_cd(); } /* DB FD */ +OP(fd,ce) { illegal_1(); op_ce(); } /* DB FD */ +OP(fd,cf) { illegal_1(); op_cf(); } /* DB FD */ + +OP(fd,d0) { illegal_1(); op_d0(); } /* DB FD */ +OP(fd,d1) { illegal_1(); op_d1(); } /* DB FD */ +OP(fd,d2) { illegal_1(); op_d2(); } /* DB FD */ +OP(fd,d3) { illegal_1(); op_d3(); } /* DB FD */ +OP(fd,d4) { illegal_1(); op_d4(); } /* DB FD */ +OP(fd,d5) { illegal_1(); op_d5(); } /* DB FD */ +OP(fd,d6) { illegal_1(); op_d6(); } /* DB FD */ +OP(fd,d7) { illegal_1(); op_d7(); } /* DB FD */ + +OP(fd,d8) { illegal_1(); op_d8(); } /* DB FD */ +OP(fd,d9) { illegal_1(); op_d9(); } /* DB FD */ +OP(fd,da) { illegal_1(); op_da(); } /* DB FD */ +OP(fd,db) { illegal_1(); op_db(); } /* DB FD */ +OP(fd,dc) { illegal_1(); op_dc(); } /* DB FD */ +OP(fd,dd) { illegal_1(); op_dd(); } /* DB FD */ +OP(fd,de) { illegal_1(); op_de(); } /* DB FD */ +OP(fd,df) { illegal_1(); op_df(); } /* DB FD */ + +OP(fd,e0) { illegal_1(); op_e0(); } /* DB FD */ +OP(fd,e1) { POP( iy ); } /* POP IY */ +OP(fd,e2) { illegal_1(); op_e2(); } /* DB FD */ +OP(fd,e3) { EXSP( iy ); } /* EX (SP),IY */ +OP(fd,e4) { illegal_1(); op_e4(); } /* DB FD */ +OP(fd,e5) { PUSH( iy ); } /* PUSH IY */ +OP(fd,e6) { illegal_1(); op_e6(); } /* DB FD */ +OP(fd,e7) { illegal_1(); op_e7(); } /* DB FD */ + +OP(fd,e8) { illegal_1(); op_e8(); } /* DB FD */ +OP(fd,e9) { PC = IY; change_pc(PCD); } /* JP (IY) */ +OP(fd,ea) { illegal_1(); op_ea(); } /* DB FD */ +OP(fd,eb) { illegal_1(); op_eb(); } /* DB FD */ +OP(fd,ec) { illegal_1(); op_ec(); } /* DB FD */ +OP(fd,ed) { illegal_1(); op_ed(); } /* DB FD */ +OP(fd,ee) { illegal_1(); op_ee(); } /* DB FD */ +OP(fd,ef) { illegal_1(); op_ef(); } /* DB FD */ + +OP(fd,f0) { illegal_1(); op_f0(); } /* DB FD */ +OP(fd,f1) { illegal_1(); op_f1(); } /* DB FD */ +OP(fd,f2) { illegal_1(); op_f2(); } /* DB FD */ +OP(fd,f3) { illegal_1(); op_f3(); } /* DB FD */ +OP(fd,f4) { illegal_1(); op_f4(); } /* DB FD */ +OP(fd,f5) { illegal_1(); op_f5(); } /* DB FD */ +OP(fd,f6) { illegal_1(); op_f6(); } /* DB FD */ +OP(fd,f7) { illegal_1(); op_f7(); } /* DB FD */ + +OP(fd,f8) { illegal_1(); op_f8(); } /* DB FD */ +OP(fd,f9) { SP = IY; } /* LD SP,IY */ +OP(fd,fa) { illegal_1(); op_fa(); } /* DB FD */ +OP(fd,fb) { illegal_1(); op_fb(); } /* DB FD */ +OP(fd,fc) { illegal_1(); op_fc(); } /* DB FD */ +OP(fd,fd) { illegal_1(); op_fd(); } /* DB FD */ +OP(fd,fe) { illegal_1(); op_fe(); } /* DB FD */ +OP(fd,ff) { illegal_1(); op_ff(); } /* DB FD */ + +OP(illegal,2) +{ +// logerror("Z80 #%d ill. opcode $ed $%02x\n", +// cpu_getactivecpu(), cpu_readop((PCD-1)&0xffff)); +} + +/********************************************************** + * special opcodes (ED prefix) + **********************************************************/ +OP(ed,00) { illegal_2(); } /* DB ED */ +OP(ed,01) { illegal_2(); } /* DB ED */ +OP(ed,02) { illegal_2(); } /* DB ED */ +OP(ed,03) { illegal_2(); } /* DB ED */ +OP(ed,04) { illegal_2(); } /* DB ED */ +OP(ed,05) { illegal_2(); } /* DB ED */ +OP(ed,06) { illegal_2(); } /* DB ED */ +OP(ed,07) { illegal_2(); } /* DB ED */ + +OP(ed,08) { illegal_2(); } /* DB ED */ +OP(ed,09) { illegal_2(); } /* DB ED */ +OP(ed,0a) { illegal_2(); } /* DB ED */ +OP(ed,0b) { illegal_2(); } /* DB ED */ +OP(ed,0c) { illegal_2(); } /* DB ED */ +OP(ed,0d) { illegal_2(); } /* DB ED */ +OP(ed,0e) { illegal_2(); } /* DB ED */ +OP(ed,0f) { illegal_2(); } /* DB ED */ + +OP(ed,10) { illegal_2(); } /* DB ED */ +OP(ed,11) { illegal_2(); } /* DB ED */ +OP(ed,12) { illegal_2(); } /* DB ED */ +OP(ed,13) { illegal_2(); } /* DB ED */ +OP(ed,14) { illegal_2(); } /* DB ED */ +OP(ed,15) { illegal_2(); } /* DB ED */ +OP(ed,16) { illegal_2(); } /* DB ED */ +OP(ed,17) { illegal_2(); } /* DB ED */ + +OP(ed,18) { illegal_2(); } /* DB ED */ +OP(ed,19) { illegal_2(); } /* DB ED */ +OP(ed,1a) { illegal_2(); } /* DB ED */ +OP(ed,1b) { illegal_2(); } /* DB ED */ +OP(ed,1c) { illegal_2(); } /* DB ED */ +OP(ed,1d) { illegal_2(); } /* DB ED */ +OP(ed,1e) { illegal_2(); } /* DB ED */ +OP(ed,1f) { illegal_2(); } /* DB ED */ + +OP(ed,20) { illegal_2(); } /* DB ED */ +OP(ed,21) { illegal_2(); } /* DB ED */ +OP(ed,22) { illegal_2(); } /* DB ED */ +OP(ed,23) { illegal_2(); } /* DB ED */ +OP(ed,24) { illegal_2(); } /* DB ED */ +OP(ed,25) { illegal_2(); } /* DB ED */ +OP(ed,26) { illegal_2(); } /* DB ED */ +OP(ed,27) { illegal_2(); } /* DB ED */ + +OP(ed,28) { illegal_2(); } /* DB ED */ +OP(ed,29) { illegal_2(); } /* DB ED */ +OP(ed,2a) { illegal_2(); } /* DB ED */ +OP(ed,2b) { illegal_2(); } /* DB ED */ +OP(ed,2c) { illegal_2(); } /* DB ED */ +OP(ed,2d) { illegal_2(); } /* DB ED */ +OP(ed,2e) { illegal_2(); } /* DB ED */ +OP(ed,2f) { illegal_2(); } /* DB ED */ + +OP(ed,30) { illegal_2(); } /* DB ED */ +OP(ed,31) { illegal_2(); } /* DB ED */ +OP(ed,32) { illegal_2(); } /* DB ED */ +OP(ed,33) { illegal_2(); } /* DB ED */ +OP(ed,34) { illegal_2(); } /* DB ED */ +OP(ed,35) { illegal_2(); } /* DB ED */ +OP(ed,36) { illegal_2(); } /* DB ED */ +OP(ed,37) { illegal_2(); } /* DB ED */ + +OP(ed,38) { illegal_2(); } /* DB ED */ +OP(ed,39) { illegal_2(); } /* DB ED */ +OP(ed,3a) { illegal_2(); } /* DB ED */ +OP(ed,3b) { illegal_2(); } /* DB ED */ +OP(ed,3c) { illegal_2(); } /* DB ED */ +OP(ed,3d) { illegal_2(); } /* DB ED */ +OP(ed,3e) { illegal_2(); } /* DB ED */ +OP(ed,3f) { illegal_2(); } /* DB ED */ + +OP(ed,40) { B = IN(BC); F = (F & CF) | SZP[B]; } /* IN B,(C) */ +OP(ed,41) { OUT(BC, B); } /* OUT (C),B */ +OP(ed,42) { SBC16( bc ); } /* SBC HL,BC */ +OP(ed,43) { EA = ARG16(); WM16( EA, &Z80.bc ); } /* LD (w),BC */ +OP(ed,44) { NEG; } /* NEG */ +OP(ed,45) { RETN; } /* RETN; */ +OP(ed,46) { IM = 0; } /* IM 0 */ +OP(ed,47) { LD_I_A; } /* LD I,A */ + +OP(ed,48) { C = IN(BC); F = (F & CF) | SZP[C]; } /* IN C,(C) */ +OP(ed,49) { OUT(BC, C); } /* OUT (C),C */ +OP(ed,4a) { ADC16( bc ); } /* ADC HL,BC */ +OP(ed,4b) { EA = ARG16(); RM16( EA, &Z80.bc ); } /* LD BC,(w) */ +OP(ed,4c) { NEG; } /* NEG */ +OP(ed,4d) { RETI; } /* RETI */ +OP(ed,4e) { IM = 0; } /* IM 0 */ +OP(ed,4f) { LD_R_A; } /* LD R,A */ + +OP(ed,50) { D = IN(BC); F = (F & CF) | SZP[D]; } /* IN D,(C) */ +OP(ed,51) { OUT(BC, D); } /* OUT (C),D */ +OP(ed,52) { SBC16( de ); } /* SBC HL,DE */ +OP(ed,53) { EA = ARG16(); WM16( EA, &Z80.de ); } /* LD (w),DE */ +OP(ed,54) { NEG; } /* NEG */ +OP(ed,55) { RETN; } /* RETN; */ +OP(ed,56) { IM = 1; } /* IM 1 */ +OP(ed,57) { LD_A_I; } /* LD A,I */ + +OP(ed,58) { E = IN(BC); F = (F & CF) | SZP[E]; } /* IN E,(C) */ +OP(ed,59) { OUT(BC, E); } /* OUT (C),E */ +OP(ed,5a) { ADC16( de ); } /* ADC HL,DE */ +OP(ed,5b) { EA = ARG16(); RM16( EA, &Z80.de ); } /* LD DE,(w) */ +OP(ed,5c) { NEG; } /* NEG */ +OP(ed,5d) { RETI; } /* RETI */ +OP(ed,5e) { IM = 2; } /* IM 2 */ +OP(ed,5f) { LD_A_R; } /* LD A,R */ + +OP(ed,60) { H = IN(BC); F = (F & CF) | SZP[H]; } /* IN H,(C) */ +OP(ed,61) { OUT(BC, H); } /* OUT (C),H */ +OP(ed,62) { SBC16( hl ); } /* SBC HL,HL */ +OP(ed,63) { EA = ARG16(); WM16( EA, &Z80.hl ); } /* LD (w),HL */ +OP(ed,64) { NEG; } /* NEG */ +OP(ed,65) { RETN; } /* RETN; */ +OP(ed,66) { IM = 0; } /* IM 0 */ +OP(ed,67) { RRD; } /* RRD (HL) */ + +OP(ed,68) { L = IN(BC); F = (F & CF) | SZP[L]; } /* IN L,(C) */ +OP(ed,69) { OUT(BC, L); } /* OUT (C),L */ +OP(ed,6a) { ADC16( hl ); } /* ADC HL,HL */ +OP(ed,6b) { EA = ARG16(); RM16( EA, &Z80.hl ); } /* LD HL,(w) */ +OP(ed,6c) { NEG; } /* NEG */ +OP(ed,6d) { RETI; } /* RETI */ +OP(ed,6e) { IM = 0; } /* IM 0 */ +OP(ed,6f) { RLD; } /* RLD (HL) */ + +OP(ed,70) { UINT8 res = IN(BC); F = (F & CF) | SZP[res]; } /* IN 0,(C) */ +OP(ed,71) { OUT(BC, 0); } /* OUT (C),0 */ +OP(ed,72) { SBC16( sp ); } /* SBC HL,SP */ +OP(ed,73) { EA = ARG16(); WM16( EA, &Z80.sp ); } /* LD (w),SP */ +OP(ed,74) { NEG; } /* NEG */ +OP(ed,75) { RETN; } /* RETN; */ +OP(ed,76) { IM = 1; } /* IM 1 */ +OP(ed,77) { illegal_2(); } /* DB ED,77 */ + +OP(ed,78) { A = IN(BC); F = (F & CF) | SZP[A]; } /* IN E,(C) */ +OP(ed,79) { OUT(BC, A); } /* OUT (C),A */ +OP(ed,7a) { ADC16( sp ); } /* ADC HL,SP */ +OP(ed,7b) { EA = ARG16(); RM16( EA, &Z80.sp ); } /* LD SP,(w) */ +OP(ed,7c) { NEG; } /* NEG */ +OP(ed,7d) { RETI; } /* RETI */ +OP(ed,7e) { IM = 2; } /* IM 2 */ +OP(ed,7f) { illegal_2(); } /* DB ED,7F */ + +OP(ed,80) { illegal_2(); } /* DB ED */ +OP(ed,81) { illegal_2(); } /* DB ED */ +OP(ed,82) { illegal_2(); } /* DB ED */ +OP(ed,83) { illegal_2(); } /* DB ED */ +OP(ed,84) { illegal_2(); } /* DB ED */ +OP(ed,85) { illegal_2(); } /* DB ED */ +OP(ed,86) { illegal_2(); } /* DB ED */ +OP(ed,87) { illegal_2(); } /* DB ED */ + +OP(ed,88) { illegal_2(); } /* DB ED */ +OP(ed,89) { illegal_2(); } /* DB ED */ +OP(ed,8a) { illegal_2(); } /* DB ED */ +OP(ed,8b) { illegal_2(); } /* DB ED */ +OP(ed,8c) { illegal_2(); } /* DB ED */ +OP(ed,8d) { illegal_2(); } /* DB ED */ +OP(ed,8e) { illegal_2(); } /* DB ED */ +OP(ed,8f) { illegal_2(); } /* DB ED */ + +OP(ed,90) { illegal_2(); } /* DB ED */ +OP(ed,91) { illegal_2(); } /* DB ED */ +OP(ed,92) { illegal_2(); } /* DB ED */ +OP(ed,93) { illegal_2(); } /* DB ED */ +OP(ed,94) { illegal_2(); } /* DB ED */ +OP(ed,95) { illegal_2(); } /* DB ED */ +OP(ed,96) { illegal_2(); } /* DB ED */ +OP(ed,97) { illegal_2(); } /* DB ED */ + +OP(ed,98) { illegal_2(); } /* DB ED */ +OP(ed,99) { illegal_2(); } /* DB ED */ +OP(ed,9a) { illegal_2(); } /* DB ED */ +OP(ed,9b) { illegal_2(); } /* DB ED */ +OP(ed,9c) { illegal_2(); } /* DB ED */ +OP(ed,9d) { illegal_2(); } /* DB ED */ +OP(ed,9e) { illegal_2(); } /* DB ED */ +OP(ed,9f) { illegal_2(); } /* DB ED */ + +OP(ed,a0) { LDI; } /* LDI */ +OP(ed,a1) { CPI; } /* CPI */ +OP(ed,a2) { INI; } /* INI */ +OP(ed,a3) { OUTI; } /* OUTI */ +OP(ed,a4) { illegal_2(); } /* DB ED */ +OP(ed,a5) { illegal_2(); } /* DB ED */ +OP(ed,a6) { illegal_2(); } /* DB ED */ +OP(ed,a7) { illegal_2(); } /* DB ED */ + +OP(ed,a8) { LDD; } /* LDD */ +OP(ed,a9) { CPD; } /* CPD */ +OP(ed,aa) { IND; } /* IND */ +OP(ed,ab) { OUTD; } /* OUTD */ +OP(ed,ac) { illegal_2(); } /* DB ED */ +OP(ed,ad) { illegal_2(); } /* DB ED */ +OP(ed,ae) { illegal_2(); } /* DB ED */ +OP(ed,af) { illegal_2(); } /* DB ED */ + +OP(ed,b0) { LDIR; } /* LDIR */ +OP(ed,b1) { CPIR; } /* CPIR */ +OP(ed,b2) { INIR; } /* INIR */ +OP(ed,b3) { OTIR; } /* OTIR */ +OP(ed,b4) { illegal_2(); } /* DB ED */ +OP(ed,b5) { illegal_2(); } /* DB ED */ +OP(ed,b6) { illegal_2(); } /* DB ED */ +OP(ed,b7) { illegal_2(); } /* DB ED */ + +OP(ed,b8) { LDDR; } /* LDDR */ +OP(ed,b9) { CPDR; } /* CPDR */ +OP(ed,ba) { INDR; } /* INDR */ +OP(ed,bb) { OTDR; } /* OTDR */ +OP(ed,bc) { illegal_2(); } /* DB ED */ +OP(ed,bd) { illegal_2(); } /* DB ED */ +OP(ed,be) { illegal_2(); } /* DB ED */ +OP(ed,bf) { illegal_2(); } /* DB ED */ + +OP(ed,c0) { illegal_2(); } /* DB ED */ +OP(ed,c1) { illegal_2(); } /* DB ED */ +OP(ed,c2) { illegal_2(); } /* DB ED */ +OP(ed,c3) { illegal_2(); } /* DB ED */ +OP(ed,c4) { illegal_2(); } /* DB ED */ +OP(ed,c5) { illegal_2(); } /* DB ED */ +OP(ed,c6) { illegal_2(); } /* DB ED */ +OP(ed,c7) { illegal_2(); } /* DB ED */ + +OP(ed,c8) { illegal_2(); } /* DB ED */ +OP(ed,c9) { illegal_2(); } /* DB ED */ +OP(ed,ca) { illegal_2(); } /* DB ED */ +OP(ed,cb) { illegal_2(); } /* DB ED */ +OP(ed,cc) { illegal_2(); } /* DB ED */ +OP(ed,cd) { illegal_2(); } /* DB ED */ +OP(ed,ce) { illegal_2(); } /* DB ED */ +OP(ed,cf) { illegal_2(); } /* DB ED */ + +OP(ed,d0) { illegal_2(); } /* DB ED */ +OP(ed,d1) { illegal_2(); } /* DB ED */ +OP(ed,d2) { illegal_2(); } /* DB ED */ +OP(ed,d3) { illegal_2(); } /* DB ED */ +OP(ed,d4) { illegal_2(); } /* DB ED */ +OP(ed,d5) { illegal_2(); } /* DB ED */ +OP(ed,d6) { illegal_2(); } /* DB ED */ +OP(ed,d7) { illegal_2(); } /* DB ED */ + +OP(ed,d8) { illegal_2(); } /* DB ED */ +OP(ed,d9) { illegal_2(); } /* DB ED */ +OP(ed,da) { illegal_2(); } /* DB ED */ +OP(ed,db) { illegal_2(); } /* DB ED */ +OP(ed,dc) { illegal_2(); } /* DB ED */ +OP(ed,dd) { illegal_2(); } /* DB ED */ +OP(ed,de) { illegal_2(); } /* DB ED */ +OP(ed,df) { illegal_2(); } /* DB ED */ + +OP(ed,e0) { illegal_2(); } /* DB ED */ +OP(ed,e1) { illegal_2(); } /* DB ED */ +OP(ed,e2) { illegal_2(); } /* DB ED */ +OP(ed,e3) { illegal_2(); } /* DB ED */ +OP(ed,e4) { illegal_2(); } /* DB ED */ +OP(ed,e5) { illegal_2(); } /* DB ED */ +OP(ed,e6) { illegal_2(); } /* DB ED */ +OP(ed,e7) { illegal_2(); } /* DB ED */ + +OP(ed,e8) { illegal_2(); } /* DB ED */ +OP(ed,e9) { illegal_2(); } /* DB ED */ +OP(ed,ea) { illegal_2(); } /* DB ED */ +OP(ed,eb) { illegal_2(); } /* DB ED */ +OP(ed,ec) { illegal_2(); } /* DB ED */ +OP(ed,ed) { illegal_2(); } /* DB ED */ +OP(ed,ee) { illegal_2(); } /* DB ED */ +OP(ed,ef) { illegal_2(); } /* DB ED */ + +OP(ed,f0) { illegal_2(); } /* DB ED */ +OP(ed,f1) { illegal_2(); } /* DB ED */ +OP(ed,f2) { illegal_2(); } /* DB ED */ +OP(ed,f3) { illegal_2(); } /* DB ED */ +OP(ed,f4) { illegal_2(); } /* DB ED */ +OP(ed,f5) { illegal_2(); } /* DB ED */ +OP(ed,f6) { illegal_2(); } /* DB ED */ +OP(ed,f7) { illegal_2(); } /* DB ED */ + +OP(ed,f8) { illegal_2(); } /* DB ED */ +OP(ed,f9) { illegal_2(); } /* DB ED */ +OP(ed,fa) { illegal_2(); } /* DB ED */ +OP(ed,fb) { illegal_2(); } /* DB ED */ +OP(ed,fc) { illegal_2(); } /* DB ED */ +OP(ed,fd) { illegal_2(); } /* DB ED */ +OP(ed,fe) { illegal_2(); } /* DB ED */ +OP(ed,ff) { illegal_2(); } /* DB ED */ + + +/********************************************************** + * main opcodes + **********************************************************/ +OP(op,00) { } /* NOP */ +OP(op,01) { BC = ARG16(); } /* LD BC,w */ +OP(op,02) { WM( BC, A ); } /* LD (BC),A */ +OP(op,03) { BC++; } /* INC BC */ +OP(op,04) { B = INC(B); } /* INC B */ +OP(op,05) { B = DEC(B); } /* DEC B */ +OP(op,06) { B = ARG(); } /* LD B,n */ +OP(op,07) { RLCA; } /* RLCA */ + +OP(op,08) { EX_AF; } /* EX AF,AF' */ +OP(op,09) { ADD16(hl, bc); } /* ADD HL,BC */ +OP(op,0a) { A = RM( BC ); } /* LD A,(BC) */ +OP(op,0b) { BC--; } /* DEC BC */ +OP(op,0c) { C = INC(C); } /* INC C */ +OP(op,0d) { C = DEC(C); } /* DEC C */ +OP(op,0e) { C = ARG(); } /* LD C,n */ +OP(op,0f) { RRCA; } /* RRCA */ + +OP(op,10) { B--; JR_COND( B, 0x10 ); } /* DJNZ o */ +OP(op,11) { DE = ARG16(); } /* LD DE,w */ +OP(op,12) { WM( DE, A ); } /* LD (DE),A */ +OP(op,13) { DE++; } /* INC DE */ +OP(op,14) { D = INC(D); } /* INC D */ +OP(op,15) { D = DEC(D); } /* DEC D */ +OP(op,16) { D = ARG(); } /* LD D,n */ +OP(op,17) { RLA; } /* RLA */ + +OP(op,18) { JR(); } /* JR o */ +OP(op,19) { ADD16(hl, de); } /* ADD HL,DE */ +OP(op,1a) { A = RM( DE ); } /* LD A,(DE) */ +OP(op,1b) { DE--; } /* DEC DE */ +OP(op,1c) { E = INC(E); } /* INC E */ +OP(op,1d) { E = DEC(E); } /* DEC E */ +OP(op,1e) { E = ARG(); } /* LD E,n */ +OP(op,1f) { RRA; } /* RRA */ + +OP(op,20) { JR_COND( !(F & ZF), 0x20 ); } /* JR NZ,o */ +OP(op,21) { HL = ARG16(); } /* LD HL,w */ +OP(op,22) { EA = ARG16(); WM16( EA, &Z80.hl ); } /* LD (w),HL */ +OP(op,23) { HL++; } /* INC HL */ +OP(op,24) { H = INC(H); } /* INC H */ +OP(op,25) { H = DEC(H); } /* DEC H */ +OP(op,26) { H = ARG(); } /* LD H,n */ +OP(op,27) { DAA; } /* DAA */ + +OP(op,28) { JR_COND( F & ZF, 0x28 ); } /* JR Z,o */ +OP(op,29) { ADD16(hl, hl); } /* ADD HL,HL */ +OP(op,2a) { EA = ARG16(); RM16( EA, &Z80.hl ); } /* LD HL,(w) */ +OP(op,2b) { HL--; } /* DEC HL */ +OP(op,2c) { L = INC(L); } /* INC L */ +OP(op,2d) { L = DEC(L); } /* DEC L */ +OP(op,2e) { L = ARG(); } /* LD L,n */ +OP(op,2f) { A ^= 0xff; F = (F&(SF|ZF|PF|CF))|HF|NF|(A&(YF|XF)); } /* CPL */ + +OP(op,30) { JR_COND( !(F & CF), 0x30 ); } /* JR NC,o */ +OP(op,31) { SP = ARG16(); } /* LD SP,w */ +OP(op,32) { EA = ARG16(); WM( EA, A ); } /* LD (w),A */ +OP(op,33) { SP++; } /* INC SP */ +OP(op,34) { WM( HL, INC(RM(HL)) ); } /* INC (HL) */ +OP(op,35) { WM( HL, DEC(RM(HL)) ); } /* DEC (HL) */ +OP(op,36) { WM( HL, ARG() ); } /* LD (HL),n */ +OP(op,37) { F = (F & (SF|ZF|PF)) | CF | (A & (YF|XF)); } /* SCF */ + +OP(op,38) { JR_COND( F & CF, 0x38 ); } /* JR C,o */ +OP(op,39) { ADD16(hl, sp); } /* ADD HL,SP */ +OP(op,3a) { EA = ARG16(); A = RM( EA ); } /* LD A,(w) */ +OP(op,3b) { SP--; } /* DEC SP */ +OP(op,3c) { A = INC(A); } /* INC A */ +OP(op,3d) { A = DEC(A); } /* DEC A */ +OP(op,3e) { A = ARG(); } /* LD A,n */ +OP(op,3f) { F = ((F&(SF|ZF|PF|CF))|((F&CF)<<4)|(A&(YF|XF)))^CF; } /* CCF */ + +OP(op,40) { } /* LD B,B */ +OP(op,41) { B = C; } /* LD B,C */ +OP(op,42) { B = D; } /* LD B,D */ +OP(op,43) { B = E; } /* LD B,E */ +OP(op,44) { B = H; } /* LD B,H */ +OP(op,45) { B = L; } /* LD B,L */ +OP(op,46) { B = RM(HL); } /* LD B,(HL) */ +OP(op,47) { B = A; } /* LD B,A */ + +OP(op,48) { C = B; } /* LD C,B */ +OP(op,49) { } /* LD C,C */ +OP(op,4a) { C = D; } /* LD C,D */ +OP(op,4b) { C = E; } /* LD C,E */ +OP(op,4c) { C = H; } /* LD C,H */ +OP(op,4d) { C = L; } /* LD C,L */ +OP(op,4e) { C = RM(HL); } /* LD C,(HL) */ +OP(op,4f) { C = A; } /* LD C,A */ + +OP(op,50) { D = B; } /* LD D,B */ +OP(op,51) { D = C; } /* LD D,C */ +OP(op,52) { } /* LD D,D */ +OP(op,53) { D = E; } /* LD D,E */ +OP(op,54) { D = H; } /* LD D,H */ +OP(op,55) { D = L; } /* LD D,L */ +OP(op,56) { D = RM(HL); } /* LD D,(HL) */ +OP(op,57) { D = A; } /* LD D,A */ + +OP(op,58) { E = B; } /* LD E,B */ +OP(op,59) { E = C; } /* LD E,C */ +OP(op,5a) { E = D; } /* LD E,D */ +OP(op,5b) { } /* LD E,E */ +OP(op,5c) { E = H; } /* LD E,H */ +OP(op,5d) { E = L; } /* LD E,L */ +OP(op,5e) { E = RM(HL); } /* LD E,(HL) */ +OP(op,5f) { E = A; } /* LD E,A */ + +OP(op,60) { H = B; } /* LD H,B */ +OP(op,61) { H = C; } /* LD H,C */ +OP(op,62) { H = D; } /* LD H,D */ +OP(op,63) { H = E; } /* LD H,E */ +OP(op,64) { } /* LD H,H */ +OP(op,65) { H = L; } /* LD H,L */ +OP(op,66) { H = RM(HL); } /* LD H,(HL) */ +OP(op,67) { H = A; } /* LD H,A */ + +OP(op,68) { L = B; } /* LD L,B */ +OP(op,69) { L = C; } /* LD L,C */ +OP(op,6a) { L = D; } /* LD L,D */ +OP(op,6b) { L = E; } /* LD L,E */ +OP(op,6c) { L = H; } /* LD L,H */ +OP(op,6d) { } /* LD L,L */ +OP(op,6e) { L = RM(HL); } /* LD L,(HL) */ +OP(op,6f) { L = A; } /* LD L,A */ + +OP(op,70) { WM( HL, B ); } /* LD (HL),B */ +OP(op,71) { WM( HL, C ); } /* LD (HL),C */ +OP(op,72) { WM( HL, D ); } /* LD (HL),D */ +OP(op,73) { WM( HL, E ); } /* LD (HL),E */ +OP(op,74) { WM( HL, H ); } /* LD (HL),H */ +OP(op,75) { WM( HL, L ); } /* LD (HL),L */ +OP(op,76) { ENTER_HALT; } /* HALT */ +OP(op,77) { WM( HL, A ); } /* LD (HL),A */ + +OP(op,78) { A = B; } /* LD A,B */ +OP(op,79) { A = C; } /* LD A,C */ +OP(op,7a) { A = D; } /* LD A,D */ +OP(op,7b) { A = E; } /* LD A,E */ +OP(op,7c) { A = H; } /* LD A,H */ +OP(op,7d) { A = L; } /* LD A,L */ +OP(op,7e) { A = RM(HL); } /* LD A,(HL) */ +OP(op,7f) { } /* LD A,A */ + +OP(op,80) { ADD(B); } /* ADD A,B */ +OP(op,81) { ADD(C); } /* ADD A,C */ +OP(op,82) { ADD(D); } /* ADD A,D */ +OP(op,83) { ADD(E); } /* ADD A,E */ +OP(op,84) { ADD(H); } /* ADD A,H */ +OP(op,85) { ADD(L); } /* ADD A,L */ +OP(op,86) { ADD(RM(HL)); } /* ADD A,(HL) */ +OP(op,87) { ADD(A); } /* ADD A,A */ + +OP(op,88) { ADC(B); } /* ADC A,B */ +OP(op,89) { ADC(C); } /* ADC A,C */ +OP(op,8a) { ADC(D); } /* ADC A,D */ +OP(op,8b) { ADC(E); } /* ADC A,E */ +OP(op,8c) { ADC(H); } /* ADC A,H */ +OP(op,8d) { ADC(L); } /* ADC A,L */ +OP(op,8e) { ADC(RM(HL)); } /* ADC A,(HL) */ +OP(op,8f) { ADC(A); } /* ADC A,A */ + +OP(op,90) { SUB(B); } /* SUB B */ +OP(op,91) { SUB(C); } /* SUB C */ +OP(op,92) { SUB(D); } /* SUB D */ +OP(op,93) { SUB(E); } /* SUB E */ +OP(op,94) { SUB(H); } /* SUB H */ +OP(op,95) { SUB(L); } /* SUB L */ +OP(op,96) { SUB(RM(HL)); } /* SUB (HL) */ +OP(op,97) { SUB(A); } /* SUB A */ + +OP(op,98) { SBC(B); } /* SBC A,B */ +OP(op,99) { SBC(C); } /* SBC A,C */ +OP(op,9a) { SBC(D); } /* SBC A,D */ +OP(op,9b) { SBC(E); } /* SBC A,E */ +OP(op,9c) { SBC(H); } /* SBC A,H */ +OP(op,9d) { SBC(L); } /* SBC A,L */ +OP(op,9e) { SBC(RM(HL)); } /* SBC A,(HL) */ +OP(op,9f) { SBC(A); } /* SBC A,A */ + +OP(op,a0) { AND(B); } /* AND B */ +OP(op,a1) { AND(C); } /* AND C */ +OP(op,a2) { AND(D); } /* AND D */ +OP(op,a3) { AND(E); } /* AND E */ +OP(op,a4) { AND(H); } /* AND H */ +OP(op,a5) { AND(L); } /* AND L */ +OP(op,a6) { AND(RM(HL)); } /* AND (HL) */ +OP(op,a7) { AND(A); } /* AND A */ + +OP(op,a8) { XOR(B); } /* XOR B */ +OP(op,a9) { XOR(C); } /* XOR C */ +OP(op,aa) { XOR(D); } /* XOR D */ +OP(op,ab) { XOR(E); } /* XOR E */ +OP(op,ac) { XOR(H); } /* XOR H */ +OP(op,ad) { XOR(L); } /* XOR L */ +OP(op,ae) { XOR(RM(HL)); } /* XOR (HL) */ +OP(op,af) { XOR(A); } /* XOR A */ + +OP(op,b0) { OR(B); } /* OR B */ +OP(op,b1) { OR(C); } /* OR C */ +OP(op,b2) { OR(D); } /* OR D */ +OP(op,b3) { OR(E); } /* OR E */ +OP(op,b4) { OR(H); } /* OR H */ +OP(op,b5) { OR(L); } /* OR L */ +OP(op,b6) { OR(RM(HL)); } /* OR (HL) */ +OP(op,b7) { OR(A); } /* OR A */ + +OP(op,b8) { CP(B); } /* CP B */ +OP(op,b9) { CP(C); } /* CP C */ +OP(op,ba) { CP(D); } /* CP D */ +OP(op,bb) { CP(E); } /* CP E */ +OP(op,bc) { CP(H); } /* CP H */ +OP(op,bd) { CP(L); } /* CP L */ +OP(op,be) { CP(RM(HL)); } /* CP (HL) */ +OP(op,bf) { CP(A); } /* CP A */ + +OP(op,c0) { RET_COND( !(F & ZF), 0xc0 ); } /* RET NZ */ +OP(op,c1) { POP( bc ); } /* POP BC */ +OP(op,c2) { JP_COND( !(F & ZF) ); } /* JP NZ,a */ +OP(op,c3) { JP; } /* JP a */ +OP(op,c4) { CALL_COND( !(F & ZF), 0xc4 ); } /* CALL NZ,a */ +OP(op,c5) { PUSH( bc ); } /* PUSH BC */ +OP(op,c6) { ADD(ARG()); } /* ADD A,n */ +OP(op,c7) { RST(0x00); } /* RST 0 */ + +OP(op,c8) { RET_COND( F & ZF, 0xc8 ); } /* RET Z */ +OP(op,c9) { POP( pc ); change_pc(PCD); } /* RET */ +OP(op,ca) { JP_COND( F & ZF ); } /* JP Z,a */ +OP(op,cb) { R++; EXEC(cb,ROP()); } /* **** CB xx */ +OP(op,cc) { CALL_COND( F & ZF, 0xcc ); } /* CALL Z,a */ +OP(op,cd) { CALL(); } /* CALL a */ +OP(op,ce) { ADC(ARG()); } /* ADC A,n */ +OP(op,cf) { RST(0x08); } /* RST 1 */ + +OP(op,d0) { RET_COND( !(F & CF), 0xd0 ); } /* RET NC */ +OP(op,d1) { POP( de ); } /* POP DE */ +OP(op,d2) { JP_COND( !(F & CF) ); } /* JP NC,a */ +OP(op,d3) { unsigned n = ARG() | (A << 8); OUT( n, A ); } /* OUT (n),A */ +OP(op,d4) { CALL_COND( !(F & CF), 0xd4 ); } /* CALL NC,a */ +OP(op,d5) { PUSH( de ); } /* PUSH DE */ +OP(op,d6) { SUB(ARG()); } /* SUB n */ +OP(op,d7) { RST(0x10); } /* RST 2 */ + +OP(op,d8) { RET_COND( F & CF, 0xd8 ); } /* RET C */ +OP(op,d9) { EXX; } /* EXX */ +OP(op,da) { JP_COND( F & CF ); } /* JP C,a */ +OP(op,db) { unsigned n = ARG() | (A << 8); A = IN( n ); } /* IN A,(n) */ +OP(op,dc) { CALL_COND( F & CF, 0xdc ); } /* CALL C,a */ +OP(op,dd) { R++; EXEC(dd,ROP()); } /* **** DD xx */ +OP(op,de) { SBC(ARG()); } /* SBC A,n */ +OP(op,df) { RST(0x18); } /* RST 3 */ + +OP(op,e0) { RET_COND( !(F & PF), 0xe0 ); } /* RET PO */ +OP(op,e1) { POP( hl ); } /* POP HL */ +OP(op,e2) { JP_COND( !(F & PF) ); } /* JP PO,a */ +OP(op,e3) { EXSP( hl ); } /* EX HL,(SP) */ +OP(op,e4) { CALL_COND( !(F & PF), 0xe4 ); } /* CALL PO,a */ +OP(op,e5) { PUSH( hl ); } /* PUSH HL */ +OP(op,e6) { AND(ARG()); } /* AND n */ +OP(op,e7) { RST(0x20); } /* RST 4 */ + +OP(op,e8) { RET_COND( F & PF, 0xe8 ); } /* RET PE */ +OP(op,e9) { PC = HL; change_pc(PCD); } /* JP (HL) */ +OP(op,ea) { JP_COND( F & PF ); } /* JP PE,a */ +OP(op,eb) { EX_DE_HL; } /* EX DE,HL */ +OP(op,ec) { CALL_COND( F & PF, 0xec ); } /* CALL PE,a */ +OP(op,ed) { R++; EXEC(ed,ROP()); } /* **** ED xx */ +OP(op,ee) { XOR(ARG()); } /* XOR n */ +OP(op,ef) { RST(0x28); } /* RST 5 */ + +OP(op,f0) { RET_COND( !(F & SF), 0xf0 ); } /* RET P */ +OP(op,f1) { POP( af ); } /* POP AF */ +OP(op,f2) { JP_COND( !(F & SF) ); } /* JP P,a */ +OP(op,f3) { IFF1 = IFF2 = 0; } /* DI */ +OP(op,f4) { CALL_COND( !(F & SF), 0xf4 ); } /* CALL P,a */ +OP(op,f5) { PUSH( af ); } /* PUSH AF */ +OP(op,f6) { OR(ARG()); } /* OR n */ +OP(op,f7) { RST(0x30); } /* RST 6 */ + +OP(op,f8) { RET_COND( F & SF, 0xf8 ); } /* RET M */ +OP(op,f9) { SP = HL; } /* LD SP,HL */ +OP(op,fa) { JP_COND(F & SF); } /* JP M,a */ +OP(op,fb) { EI; } /* EI */ +OP(op,fc) { CALL_COND( F & SF, 0xfc ); } /* CALL M,a */ +OP(op,fd) { R++; EXEC(fd,ROP()); } /* **** FD xx */ +OP(op,fe) { CP(ARG()); } /* CP n */ +OP(op,ff) { RST(0x38); } /* RST 7 */ + + +static void take_interrupt(void) +{ + int irq_vector = Z80Vector; + Z80Vector = 0; + + /* there isn't a valid previous program counter */ + PRVPC = (UINT32)-1; + + /* Check if processor was halted */ + LEAVE_HALT; + + /* Clear both interrupt flip flops */ + IFF1 = IFF2 = 0; + + /* Daisy chain mode? If so, call the requesting device */ +// if (Z80.daisy) +// irq_vector = z80daisy_call_ack_device(Z80.daisy); + + /* else call back the cpu interface to retrieve the vector */ +// else +// irq_vector = (*Z80.irq_callback)(0); + +// LOG(("Z80 #%d single int. irq_vector $%02x\n", cpu_getactivecpu(), irq_vector)); + + /* Interrupt mode 2. Call [Z80.i:databyte] */ + if( IM == 2 ) + { + irq_vector = (irq_vector & 0xff) | (I << 8); + PUSH( pc ); + RM16( irq_vector, &Z80.pc ); +// LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, PCD)); + /* CALL opcode timing */ + z80_ICount -= cc[Z80_TABLE_op][0xcd]; + } + else + /* Interrupt mode 1. RST 38h */ + if( IM == 1 ) + { +// LOG(("Z80 #%d IM1 $0038\n",cpu_getactivecpu() )); + PUSH( pc ); + PCD = 0x0038; + /* RST $38 + 'interrupt latency' cycles */ + z80_ICount -= cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff]; + } + else + { + /* Interrupt mode 0. We check for CALL and JP instructions, */ + /* if neither of these were found we assume a 1 byte opcode */ + /* was placed on the databus */ +// LOG(("Z80 #%d IM0 $%04x\n",cpu_getactivecpu() , irq_vector)); + switch (irq_vector & 0xff0000) + { + case 0xcd0000: /* call */ + PUSH( pc ); + PCD = irq_vector & 0xffff; + /* CALL $xxxx + 'interrupt latency' cycles */ + z80_ICount -= cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff]; + break; + case 0xc30000: /* jump */ + PCD = irq_vector & 0xffff; + /* JP $xxxx + 2 cycles */ + z80_ICount -= cc[Z80_TABLE_op][0xc3] + cc[Z80_TABLE_ex][0xff]; + break; + default: /* rst (or other opcodes?) */ + PUSH( pc ); + PCD = irq_vector & 0x0038; + /* RST $xx + 2 cycles */ + z80_ICount -= cc[Z80_TABLE_op][PCD] + cc[Z80_TABLE_ex][PCD]; + break; + } + } + change_pc(PCD); +} + +void Z80Init() +{ + int i, p; + + /* setup cycle tables */ + cc[Z80_TABLE_op] = cc_op; + cc[Z80_TABLE_cb] = cc_cb; + cc[Z80_TABLE_ed] = cc_ed; + cc[Z80_TABLE_xy] = cc_xy; + cc[Z80_TABLE_xycb] = cc_xycb; + cc[Z80_TABLE_ex] = cc_ex; + +#if BIG_FLAGS_ARRAY + if( !SZHVC_add || !SZHVC_sub ) + { + int oldval, newval, val; + UINT8 *padd, *padc, *psub, *psbc; + /* allocate big flag arrays once */ + SZHVC_add = (UINT8 *)malloc(2*256*256); + SZHVC_sub = (UINT8 *)malloc(2*256*256); + if( !SZHVC_add || !SZHVC_sub ) + { +// fatalerror("Z80: failed to allocate 2 * 128K flags arrays!!!"); + } + padd = &SZHVC_add[ 0*256]; + padc = &SZHVC_add[256*256]; + psub = &SZHVC_sub[ 0*256]; + psbc = &SZHVC_sub[256*256]; + for (oldval = 0; oldval < 256; oldval++) + { + for (newval = 0; newval < 256; newval++) + { + /* add or adc w/o carry set */ + val = newval - oldval; + *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF; + if( newval < oldval ) *padd |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF; + padd++; + + /* adc with carry set */ + val = newval - oldval - 1; + *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF; + if( newval <= oldval ) *padc |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF; + padc++; + + /* cp, sub or sbc w/o carry set */ + val = oldval - newval; + *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF; + if( newval > oldval ) *psub |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF; + psub++; + + /* sbc with carry set */ + val = oldval - newval - 1; + *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF; + if( newval >= oldval ) *psbc |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF; + psbc++; + } + } + } +#endif + for (i = 0; i < 256; i++) + { + p = 0; + if( i&0x01 ) ++p; + if( i&0x02 ) ++p; + if( i&0x04 ) ++p; + if( i&0x08 ) ++p; + if( i&0x10 ) ++p; + if( i&0x20 ) ++p; + if( i&0x40 ) ++p; + if( i&0x80 ) ++p; + SZ[i] = i ? i & SF : ZF; + SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ + SZ_BIT[i] = i ? i & SF : ZF | PF; + SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ + SZP[i] = SZ[i] | ((p & 1) ? 0 : PF); + SZHV_inc[i] = SZ[i]; + if( i == 0x80 ) SZHV_inc[i] |= VF; + if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF; + SZHV_dec[i] = SZ[i] | NF; + if( i == 0x7f ) SZHV_dec[i] |= VF; + if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF; + } + + /* Reset registers to their initial values */ + memset(&Z80, 0, sizeof(Z80)); +// Z80.daisy = config; +// Z80.irq_callback = irqcallback; + IX = IY = 0xffff; /* IX and IY are FFFF after a reset! */ + F = ZF; /* Zero flag is set */ +} + +void Z80Reset() +{ + //struct z80_irq_daisy_chain *daisy; + //int (*irq_callback)(int irqline); + + memset(&Z80, 0, sizeof(Z80)); + + PC = 0x0000; + I = 0; + R = 0; + R2 = 0; + Z80.nmi_state = Z80_CLEAR_LINE; + Z80.nmi_pending = FALSE; + Z80.irq_state = Z80_CLEAR_LINE; + Z80.after_ei = FALSE; + + if (Z80.daisy) + z80daisy_reset(Z80.daisy); + + change_pc(PCD); +} + +void Z80Exit() +{ + +} + +int Z80Execute(int cycles) +{ + z80_ICount = cycles; + + /* check for NMIs on the way in; they can only be set externally */ + /* via timers, and can't be dynamically enabled, so it is safe */ + /* to just check here */ + if (Z80.nmi_pending) + { +// LOG(("Z80 #%d take NMI\n", cpu_getactivecpu())); + PRVPC = (UINT32)-1; /* there isn't a valid previous program counter */ + LEAVE_HALT; /* Check if processor was halted */ + + IFF1 = 0; + PUSH( pc ); + PCD = 0x0066; + change_pc(PCD); + z80_ICount -= 11; + Z80.nmi_pending = FALSE; + } + + do + { + /* check for IRQs before each instruction */ + if (Z80.irq_state != Z80_CLEAR_LINE && IFF1 && !Z80.after_ei) + take_interrupt(); + Z80.after_ei = FALSE; + + PRVPC = PCD; +// CALL_DEBUGGER(PCD); + R++; + EXEC_INLINE(op,ROP()); + } while( z80_ICount > 0 ); + + return cycles - z80_ICount; +} + +void Z80Burn(int cycles) +{ + if( cycles > 0 ) + { + /* NOP takes 4 cycles per instruction */ + int n = (cycles + 3) / 4; + R += n; + z80_ICount -= 4 * n; + } +} + +void Z80SetIrqLine(int irqline, int state) +{ + if (irqline == Z80_INPUT_LINE_NMI) + { + /* mark an NMI pending on the rising edge */ + if (Z80.nmi_state == Z80_CLEAR_LINE && state != Z80_CLEAR_LINE) + Z80.nmi_pending = TRUE; + Z80.nmi_state = state; + } + else + { + /* update the IRQ state via the daisy chain */ + Z80.irq_state = state; +// if (Z80.daisy) +// Z80.irq_state = z80daisy_update_irq_state(Z80.daisy); + + /* the main execute loop will take the interrupt */ + } +} + +void Z80GetContext (void *dst) +{ + if( dst ) + *(Z80_Regs*)dst = Z80; +} + +void Z80SetContext (void *src) +{ + if( src ) + Z80 = *(Z80_Regs*)src; + change_pc(PCD); +} + +int Z80Scan(int nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 0; + } + + SCAN_VAR(Z80); + + return 0; +} + +void Z80SetIOReadHandler(Z80ReadIoHandler handler) +{ + Z80IORead = handler; +} + +void Z80SetIOWriteHandler(Z80WriteIoHandler handler) +{ + Z80IOWrite = handler; +} + +void Z80SetProgramReadHandler(Z80ReadProgHandler handler) +{ + Z80ProgramRead = handler; +} + +void Z80SetProgramWriteHandler(Z80WriteProgHandler handler) +{ + Z80ProgramWrite = handler; +} + +void Z80SetCPUOpReadHandler(Z80ReadOpHandler handler) +{ + Z80CPUReadOp = handler; +} + +void Z80SetCPUOpArgReadHandler(Z80ReadOpArgHandler handler) +{ + Z80CPUReadOpArg = handler; +} + +int ActiveZ80GetPC() +{ + return Z80.pc.w.l; +} + +int ActiveZ80GetBC() +{ + return Z80.bc.w.l; +} + +int ActiveZ80GetDE() +{ + return Z80.de.w.l; +} + +int ActiveZ80GetHL() +{ + return Z80.hl.w.l; +} + +#if 0 +/**************************************************************************** + * Processor initialization + ****************************************************************************/ +static void z80_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + int i, p; + + /* setup cycle tables */ + cc[Z80_TABLE_op] = cc_op; + cc[Z80_TABLE_cb] = cc_cb; + cc[Z80_TABLE_ed] = cc_ed; + cc[Z80_TABLE_xy] = cc_xy; + cc[Z80_TABLE_xycb] = cc_xycb; + cc[Z80_TABLE_ex] = cc_ex; + +#if BIG_FLAGS_ARRAY + if( !SZHVC_add || !SZHVC_sub ) + { + int oldval, newval, val; + UINT8 *padd, *padc, *psub, *psbc; + /* allocate big flag arrays once */ + SZHVC_add = (UINT8 *)malloc(2*256*256); + SZHVC_sub = (UINT8 *)malloc(2*256*256); + if( !SZHVC_add || !SZHVC_sub ) + { + fatalerror("Z80: failed to allocate 2 * 128K flags arrays!!!"); + } + padd = &SZHVC_add[ 0*256]; + padc = &SZHVC_add[256*256]; + psub = &SZHVC_sub[ 0*256]; + psbc = &SZHVC_sub[256*256]; + for (oldval = 0; oldval < 256; oldval++) + { + for (newval = 0; newval < 256; newval++) + { + /* add or adc w/o carry set */ + val = newval - oldval; + *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF; + if( newval < oldval ) *padd |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF; + padd++; + + /* adc with carry set */ + val = newval - oldval - 1; + *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF; + if( newval <= oldval ) *padc |= CF; + if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF; + padc++; + + /* cp, sub or sbc w/o carry set */ + val = oldval - newval; + *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF; + if( newval > oldval ) *psub |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF; + psub++; + + /* sbc with carry set */ + val = oldval - newval - 1; + *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF; + if( newval >= oldval ) *psbc |= CF; + if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF; + psbc++; + } + } + } +#endif + for (i = 0; i < 256; i++) + { + p = 0; + if( i&0x01 ) ++p; + if( i&0x02 ) ++p; + if( i&0x04 ) ++p; + if( i&0x08 ) ++p; + if( i&0x10 ) ++p; + if( i&0x20 ) ++p; + if( i&0x40 ) ++p; + if( i&0x80 ) ++p; + SZ[i] = i ? i & SF : ZF; + SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ + SZ_BIT[i] = i ? i & SF : ZF | PF; + SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */ + SZP[i] = SZ[i] | ((p & 1) ? 0 : PF); + SZHV_inc[i] = SZ[i]; + if( i == 0x80 ) SZHV_inc[i] |= VF; + if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF; + SZHV_dec[i] = SZ[i] | NF; + if( i == 0x7f ) SZHV_dec[i] |= VF; + if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF; + } + + state_save_register_item("z80", index, Z80.prvpc.w.l); + state_save_register_item("z80", index, Z80.pc.w.l); + state_save_register_item("z80", index, Z80.sp.w.l); + state_save_register_item("z80", index, Z80.af.w.l); + state_save_register_item("z80", index, Z80.bc.w.l); + state_save_register_item("z80", index, Z80.de.w.l); + state_save_register_item("z80", index, Z80.hl.w.l); + state_save_register_item("z80", index, Z80.ix.w.l); + state_save_register_item("z80", index, Z80.iy.w.l); + state_save_register_item("z80", index, Z80.af2.w.l); + state_save_register_item("z80", index, Z80.bc2.w.l); + state_save_register_item("z80", index, Z80.de2.w.l); + state_save_register_item("z80", index, Z80.hl2.w.l); + state_save_register_item("z80", index, Z80.r); + state_save_register_item("z80", index, Z80.r2); + state_save_register_item("z80", index, Z80.iff1); + state_save_register_item("z80", index, Z80.iff2); + state_save_register_item("z80", index, Z80.halt); + state_save_register_item("z80", index, Z80.im); + state_save_register_item("z80", index, Z80.i); + state_save_register_item("z80", index, Z80.nmi_state); + state_save_register_item("z80", index, Z80.nmi_pending); + state_save_register_item("z80", index, Z80.irq_state); + state_save_register_item("z80", index, Z80.after_ei); + + /* Reset registers to their initial values */ + memset(&Z80, 0, sizeof(Z80)); + Z80.daisy = config; + Z80.irq_callback = irqcallback; + IX = IY = 0xffff; /* IX and IY are FFFF after a reset! */ + F = ZF; /* Zero flag is set */ + + Z80Vector = 0; +} + +/**************************************************************************** + * Do a reset + ****************************************************************************/ +static void z80_reset(void) +{ + PC = 0x0000; + I = 0; + R = 0; + R2 = 0; + Z80.nmi_state = Z80_CLEAR_LINE; + Z80.nmi_pending = FALSE; + Z80.irq_state = Z80_CLEAR_LINE; + Z80.after_ei = FALSE; + + if (Z80.daisy) + z80daisy_reset(Z80.daisy); + + change_pc(PCD); +} + +static void z80_exit(void) +{ +#if BIG_FLAGS_ARRAY + if (SZHVC_add) free(SZHVC_add); + SZHVC_add = NULL; + if (SZHVC_sub) free(SZHVC_sub); + SZHVC_sub = NULL; +#endif +} + +/**************************************************************************** + * Execute 'cycles' T-states. Return number of T-states really executed + ****************************************************************************/ +static int z80_execute(int cycles) +{ + z80_ICount = cycles; + + /* check for NMIs on the way in; they can only be set externally */ + /* via timers, and can't be dynamically enabled, so it is safe */ + /* to just check here */ + if (Z80.nmi_pending) + { + LOG(("Z80 #%d take NMI\n", cpu_getactivecpu())); + PRVPC = -1; /* there isn't a valid previous program counter */ + LEAVE_HALT; /* Check if processor was halted */ + + IFF1 = 0; + PUSH( pc ); + PCD = 0x0066; + change_pc(PCD); + z80_ICount -= 11; + Z80.nmi_pending = FALSE; + } + + do + { + /* check for IRQs before each instruction */ + if (Z80.irq_state != Z80_CLEAR_LINE && IFF1 && !Z80.after_ei) + take_interrupt(); + Z80.after_ei = FALSE; + + PRVPC = PCD; + CALL_DEBUGGER(PCD); + R++; + EXEC_INLINE(op,ROP()); + } while( z80_ICount > 0 ); + + return cycles - z80_ICount; +} + +/**************************************************************************** + * Burn 'cycles' T-states. Adjust R register for the lost time + ****************************************************************************/ +static void z80_burn(int cycles) +{ + if( cycles > 0 ) + { + /* NOP takes 4 cycles per instruction */ + int n = (cycles + 3) / 4; + R += n; + z80_ICount -= 4 * n; + } +} + +/**************************************************************************** + * Get all registers in given buffer + ****************************************************************************/ +static void z80_get_context (void *dst) +{ + if( dst ) + *(Z80_Regs*)dst = Z80; +} + +/**************************************************************************** + * Set all registers to given values + ****************************************************************************/ +static void z80_set_context (void *src) +{ + if( src ) + Z80 = *(Z80_Regs*)src; + change_pc(PCD); +} + +/**************************************************************************** + * Set IRQ line state + ****************************************************************************/ +static void set_irq_line(int irqline, int state) +{ + if (irqline == INPUT_LINE_NMI) + { + /* mark an NMI pending on the rising edge */ + if (Z80.nmi_state == Z80_CLEAR_LINE && state != Z80_CLEAR_LINE) + Z80.nmi_pending = TRUE; + Z80.nmi_state = state; + } + else + { + /* update the IRQ state via the daisy chain */ + Z80.irq_state = state; + if (Z80.daisy) + Z80.irq_state = z80daisy_update_irq_state(Z80.daisy); + + /* the main execute loop will take the interrupt */ + } +} + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static void z80_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(INPUT_LINE_NMI, info->i); break; + case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; + + case CPUINFO_INT_PC: PC = info->i; change_pc(PCD); break; + case CPUINFO_INT_REGISTER + Z80_PC: Z80.pc.w.l = info->i; break; + case CPUINFO_INT_SP: SP = info->i; break; + case CPUINFO_INT_REGISTER + Z80_SP: Z80.sp.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_A: Z80.af.b.h = info->i; break; + case CPUINFO_INT_REGISTER + Z80_B: Z80.bc.b.h = info->i; break; + case CPUINFO_INT_REGISTER + Z80_C: Z80.bc.b.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_D: Z80.de.b.h = info->i; break; + case CPUINFO_INT_REGISTER + Z80_E: Z80.de.b.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_H: Z80.hl.b.h = info->i; break; + case CPUINFO_INT_REGISTER + Z80_L: Z80.hl.b.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_AF: Z80.af.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_BC: Z80.bc.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_DE: Z80.de.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_HL: Z80.hl.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_IX: Z80.ix.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_IY: Z80.iy.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_R: Z80.r = info->i; Z80.r2 = info->i & 0x80; break; + case CPUINFO_INT_REGISTER + Z80_I: Z80.i = info->i; break; + case CPUINFO_INT_REGISTER + Z80_AF2: Z80.af2.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_BC2: Z80.bc2.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_DE2: Z80.de2.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_HL2: Z80.hl2.w.l = info->i; break; + case CPUINFO_INT_REGISTER + Z80_IM: Z80.im = info->i; break; + case CPUINFO_INT_REGISTER + Z80_IFF1: Z80.iff1 = info->i; break; + case CPUINFO_INT_REGISTER + Z80_IFF2: Z80.iff2 = info->i; break; + case CPUINFO_INT_REGISTER + Z80_HALT: Z80.halt = info->i; break; + + /* --- the following bits of info are set as pointers to data or functions --- */ + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_op: cc[Z80_TABLE_op] = info->p; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_cb: cc[Z80_TABLE_cb] = info->p; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ed: cc[Z80_TABLE_ed] = info->p; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_xy: cc[Z80_TABLE_xy] = info->p; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_xycb: cc[Z80_TABLE_xycb] = info->p; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ex: cc[Z80_TABLE_ex] = info->p; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void z80_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(Z80); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 16; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = Z80.nmi_state; break; + case CPUINFO_INT_INPUT_STATE + 0: info->i = Z80.irq_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = Z80.prvpc.w.l; break; + + case CPUINFO_INT_PC: info->i = PCD; break; + case CPUINFO_INT_REGISTER + Z80_PC: info->i = Z80.pc.w.l; break; + case CPUINFO_INT_SP: info->i = SPD; break; + case CPUINFO_INT_REGISTER + Z80_SP: info->i = Z80.sp.w.l; break; + case CPUINFO_INT_REGISTER + Z80_A: info->i = Z80.af.b.h; break; + case CPUINFO_INT_REGISTER + Z80_B: info->i = Z80.bc.b.h; break; + case CPUINFO_INT_REGISTER + Z80_C: info->i = Z80.bc.b.l; break; + case CPUINFO_INT_REGISTER + Z80_D: info->i = Z80.de.b.h; break; + case CPUINFO_INT_REGISTER + Z80_E: info->i = Z80.de.b.l; break; + case CPUINFO_INT_REGISTER + Z80_H: info->i = Z80.hl.b.h; break; + case CPUINFO_INT_REGISTER + Z80_L: info->i = Z80.hl.b.l; break; + case CPUINFO_INT_REGISTER + Z80_AF: info->i = Z80.af.w.l; break; + case CPUINFO_INT_REGISTER + Z80_BC: info->i = Z80.bc.w.l; break; + case CPUINFO_INT_REGISTER + Z80_DE: info->i = Z80.de.w.l; break; + case CPUINFO_INT_REGISTER + Z80_HL: info->i = Z80.hl.w.l; break; + case CPUINFO_INT_REGISTER + Z80_IX: info->i = Z80.ix.w.l; break; + case CPUINFO_INT_REGISTER + Z80_IY: info->i = Z80.iy.w.l; break; + case CPUINFO_INT_REGISTER + Z80_R: info->i = (Z80.r & 0x7f) | (Z80.r2 & 0x80); break; + case CPUINFO_INT_REGISTER + Z80_I: info->i = Z80.i; break; + case CPUINFO_INT_REGISTER + Z80_AF2: info->i = Z80.af2.w.l; break; + case CPUINFO_INT_REGISTER + Z80_BC2: info->i = Z80.bc2.w.l; break; + case CPUINFO_INT_REGISTER + Z80_DE2: info->i = Z80.de2.w.l; break; + case CPUINFO_INT_REGISTER + Z80_HL2: info->i = Z80.hl2.w.l; break; + case CPUINFO_INT_REGISTER + Z80_IM: info->i = Z80.im; break; + case CPUINFO_INT_REGISTER + Z80_IFF1: info->i = Z80.iff1; break; + case CPUINFO_INT_REGISTER + Z80_IFF2: info->i = Z80.iff2; break; + case CPUINFO_INT_REGISTER + Z80_HALT: info->i = Z80.halt; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = z80_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = z80_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = z80_set_context; break; + case CPUINFO_PTR_INIT: info->init = z80_init; break; + case CPUINFO_PTR_RESET: info->reset = z80_reset; break; + case CPUINFO_PTR_EXIT: info->exit = z80_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = z80_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; +#ifdef ENABLE_DEBUGGER + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = z80_dasm; break; +#endif + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &z80_ICount; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_op: info->p = (void *)cc[Z80_TABLE_op]; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_cb: info->p = (void *)cc[Z80_TABLE_cb]; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ed: info->p = (void *)cc[Z80_TABLE_ed]; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_xy: info->p = (void *)cc[Z80_TABLE_xy]; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_xycb: info->p = (void *)cc[Z80_TABLE_xycb]; break; + case CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ex: info->p = (void *)cc[Z80_TABLE_ex]; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "Z80"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Zilog Z80"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "3.7"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c%c%c%c%c", + Z80.af.b.l & 0x80 ? 'S':'.', + Z80.af.b.l & 0x40 ? 'Z':'.', + Z80.af.b.l & 0x20 ? '5':'.', + Z80.af.b.l & 0x10 ? 'H':'.', + Z80.af.b.l & 0x08 ? '3':'.', + Z80.af.b.l & 0x04 ? 'P':'.', + Z80.af.b.l & 0x02 ? 'N':'.', + Z80.af.b.l & 0x01 ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + Z80_PC: sprintf(info->s, "PC:%04X", Z80.pc.w.l); break; + case CPUINFO_STR_REGISTER + Z80_SP: sprintf(info->s, "SP:%04X", Z80.sp.w.l); break; + case CPUINFO_STR_REGISTER + Z80_A: sprintf(info->s, "~A:%02X", Z80.af.b.h); break; + case CPUINFO_STR_REGISTER + Z80_B: sprintf(info->s, "~B:%02X", Z80.bc.b.h); break; + case CPUINFO_STR_REGISTER + Z80_C: sprintf(info->s, "~C:%02X", Z80.bc.b.l); break; + case CPUINFO_STR_REGISTER + Z80_D: sprintf(info->s, "~D:%02X", Z80.de.b.h); break; + case CPUINFO_STR_REGISTER + Z80_E: sprintf(info->s, "~E:%02X", Z80.de.b.l); break; + case CPUINFO_STR_REGISTER + Z80_H: sprintf(info->s, "~H:%02X", Z80.hl.b.h); break; + case CPUINFO_STR_REGISTER + Z80_L: sprintf(info->s, "~L:%02X", Z80.hl.b.l); break; + case CPUINFO_STR_REGISTER + Z80_AF: sprintf(info->s, "AF:%04X", Z80.af.w.l); break; + case CPUINFO_STR_REGISTER + Z80_BC: sprintf(info->s, "BC:%04X", Z80.bc.w.l); break; + case CPUINFO_STR_REGISTER + Z80_DE: sprintf(info->s, "DE:%04X", Z80.de.w.l); break; + case CPUINFO_STR_REGISTER + Z80_HL: sprintf(info->s, "HL:%04X", Z80.hl.w.l); break; + case CPUINFO_STR_REGISTER + Z80_IX: sprintf(info->s, "IX:%04X", Z80.ix.w.l); break; + case CPUINFO_STR_REGISTER + Z80_IY: sprintf(info->s, "IY:%04X", Z80.iy.w.l); + break; + case CPUINFO_STR_REGISTER + Z80_R: sprintf(info->s, "R:%02X", (Z80.r & 0x7f) | (Z80.r2 & 0x80)); break; + case CPUINFO_STR_REGISTER + Z80_I: sprintf(info->s, "I:%02X", Z80.i); break; + case CPUINFO_STR_REGISTER + Z80_AF2: sprintf(info->s, "AF2:%04X", Z80.af2.w.l); break; + case CPUINFO_STR_REGISTER + Z80_BC2: sprintf(info->s, "BC2:%04X", Z80.bc2.w.l); break; + case CPUINFO_STR_REGISTER + Z80_DE2: sprintf(info->s, "DE2:%04X", Z80.de2.w.l); break; + case CPUINFO_STR_REGISTER + Z80_HL2: sprintf(info->s, "HL2:%04X", Z80.hl2.w.l); break; + case CPUINFO_STR_REGISTER + Z80_IM: sprintf(info->s, "IM:%X", Z80.im); break; + case CPUINFO_STR_REGISTER + Z80_IFF1: sprintf(info->s, "IFF1:%X", Z80.iff1); break; + case CPUINFO_STR_REGISTER + Z80_IFF2: sprintf(info->s, "IFF2:%X", Z80.iff2); break; + case CPUINFO_STR_REGISTER + Z80_HALT: sprintf(info->s, "HALT:%X", Z80.halt); break; + } +} + +#endif diff --git a/src/cpu/z80/z80.h b/src/cpu/z80/z80.h new file mode 100644 index 00000000..b6345c04 --- /dev/null +++ b/src/cpu/z80/z80.h @@ -0,0 +1,88 @@ +#ifndef _Z80_H_ +#define _Z80_H_ + +#define CPUINFO_PTR_CPU_SPECIFIC 0x18000 +#define Z80_CLEAR_LINE 0 +#define Z80_ASSERT_LINE 1 +#define Z80_INPUT_LINE_NMI 32 + +typedef union +{ + struct { UINT8 l,h,h2,h3; } b; + struct { UINT16 l,h; } w; + UINT32 d; +} Z80_PAIR; + +typedef struct +{ + Z80_PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy; + Z80_PAIR af2,bc2,de2,hl2; + UINT8 r,r2,iff1,iff2,halt,im,i; + UINT8 nmi_state; /* nmi line state */ + UINT8 nmi_pending; /* nmi pending */ + UINT8 irq_state; /* irq line state */ + UINT8 after_ei; /* are we in the EI shadow? */ + const struct z80_irq_daisy_chain *daisy; + int (*irq_callback)(int irqline); +} Z80_Regs; + +enum { + Z80_PC=1, Z80_SP, + Z80_A, Z80_B, Z80_C, Z80_D, Z80_E, Z80_H, Z80_L, + Z80_AF, Z80_BC, Z80_DE, Z80_HL, + Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2, + Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT, + Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3 +}; + +enum { + Z80_TABLE_op, + Z80_TABLE_cb, + Z80_TABLE_ed, + Z80_TABLE_xy, + Z80_TABLE_xycb, + Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */ +}; + +enum +{ + CPUINFO_PTR_Z80_CYCLE_TABLE = CPUINFO_PTR_CPU_SPECIFIC, + CPUINFO_PTR_Z80_CYCLE_TABLE_LAST = CPUINFO_PTR_Z80_CYCLE_TABLE + Z80_TABLE_ex +}; + +void Z80Init(); +void Z80Reset(); +void Z80Exit(); +int Z80Execute(int cycles); +void Z80Burn(int cycles); +void Z80SetIrqLine(int irqline, int state); +void Z80GetContext (void *dst); +void Z80SetContext (void *src); +int Z80Scan(int nAction); + +extern unsigned char Z80Vector; + +extern int z80_ICount; +extern UINT32 EA; + +typedef unsigned char (__fastcall *Z80ReadIoHandler)(unsigned int a); +typedef void (__fastcall *Z80WriteIoHandler)(unsigned int a, unsigned char v); +typedef unsigned char (__fastcall *Z80ReadProgHandler)(unsigned int a); +typedef void (__fastcall *Z80WriteProgHandler)(unsigned int a, unsigned char v); +typedef unsigned char (__fastcall *Z80ReadOpHandler)(unsigned int a); +typedef unsigned char (__fastcall *Z80ReadOpArgHandler)(unsigned int a); + +void Z80SetIOReadHandler(Z80ReadIoHandler handler); +void Z80SetIOWriteHandler(Z80WriteIoHandler handler); +void Z80SetProgramReadHandler(Z80ReadProgHandler handler); +void Z80SetProgramWriteHandler(Z80WriteProgHandler handler); +void Z80SetCPUOpReadHandler(Z80ReadOpHandler handler); +void Z80SetCPUOpArgReadHandler(Z80ReadOpArgHandler handler); + +int ActiveZ80GetPC(); +int ActiveZ80GetBC(); +int ActiveZ80GetDE(); +int ActiveZ80GetHL(); + +#endif + diff --git a/src/cpu/z80/z80daisy.cpp b/src/cpu/z80/z80daisy.cpp new file mode 100644 index 00000000..2a0cd4c9 --- /dev/null +++ b/src/cpu/z80/z80daisy.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + + z80daisy.c + + Z80/180 daisy chaining support functions. + +***************************************************************************/ + +#include "z80daisy.h" + +#define CLEAR_LINE 0 +#define ASSERT_LINE 1 + + +void z80daisy_reset(const struct z80_irq_daisy_chain *daisy) +{ + /* loop over all devices and call their reset function */ + for ( ; daisy->param != -1; daisy++) + if (daisy->reset) + (*daisy->reset)(daisy->param); +} + + +int z80daisy_update_irq_state(const struct z80_irq_daisy_chain *daisy) +{ + /* loop over all devices; dev[0] is highest priority */ + for ( ; daisy->param != -1; daisy++) + { + int state = (*daisy->irq_state)(daisy->param); + + /* if this device is asserting the INT line, that's the one we want */ + if (state & Z80_DAISY_INT) + return ASSERT_LINE; + + /* if this device is asserting the IEO line, it blocks everyone else */ + if (state & Z80_DAISY_IEO) + return CLEAR_LINE; + } + + return CLEAR_LINE; +} + + +int z80daisy_call_ack_device(const struct z80_irq_daisy_chain *daisy) +{ + /* loop over all devices; dev[0] is the highest priority */ + for ( ; daisy->param != -1; daisy++) + { + int state = (*daisy->irq_state)(daisy->param); + + /* if this device is asserting the INT line, that's the one we want */ + if (state & Z80_DAISY_INT) + return (*daisy->irq_ack)(daisy->param); + } + +// logerror("z80daisy_call_ack_device: failed to find an device to ack!\n"); + return 0; +} + + +void z80daisy_call_reti_device(const struct z80_irq_daisy_chain *daisy) +{ + /* loop over all devices; dev[0] is the highest priority */ + for ( ; daisy->param != -1; daisy++) + { + int state = (*daisy->irq_state)(daisy->param); + + /* if this device is asserting the IEO line, that's the one we want */ + if (state & Z80_DAISY_IEO) + { + (*daisy->irq_reti)(daisy->param); + return; + } + } + +// logerror("z80daisy_call_reti_device: failed to find an device to reti!\n"); +} diff --git a/src/cpu/z80/z80daisy.h b/src/cpu/z80/z80daisy.h new file mode 100644 index 00000000..b0e791e6 --- /dev/null +++ b/src/cpu/z80/z80daisy.h @@ -0,0 +1,36 @@ +/*************************************************************************** + + z80daisy.h + + Z80/180 daisy chaining support functions. + +***************************************************************************/ + + +#ifndef Z80DAISY_H +#define Z80DAISY_H + + +/* daisy-chain link */ +struct z80_irq_daisy_chain +{ + void (*reset)(int); /* reset callback */ + int (*irq_state)(int); /* get interrupt state */ + int (*irq_ack)(int); /* interrupt acknowledge callback */ + void (*irq_reti)(int); /* reti callback */ + int param; /* callback parameter (-1 ends list) */ +}; + + +/* these constants are returned from the irq_state function */ +#define Z80_DAISY_INT 0x01 /* interrupt request mask */ +#define Z80_DAISY_IEO 0x02 /* interrupt disable mask (IEO) */ + + +/* prototypes */ +void z80daisy_reset(const struct z80_irq_daisy_chain *daisy); +int z80daisy_update_irq_state(const struct z80_irq_daisy_chain *chain); +int z80daisy_call_ack_device(const struct z80_irq_daisy_chain *chain); +void z80daisy_call_reti_device(const struct z80_irq_daisy_chain *chain); + +#endif diff --git a/src/cpu/zet.cpp b/src/cpu/zet.cpp new file mode 100644 index 00000000..c392c848 --- /dev/null +++ b/src/cpu/zet.cpp @@ -0,0 +1,478 @@ +// Z80 (Zed Eight-Ty) Interface +#include "burnint.h" + +#define MAX_Z80 8 +static struct ZetExt * ZetCPUContext = NULL; + +typedef UINT8 (__fastcall *pZetInHandler)(UINT16 a); +typedef void (__fastcall *pZetOutHandler)(UINT16 a, UINT8 d); +typedef UINT8 (__fastcall *pZetReadHandler)(UINT16 a); +typedef void (__fastcall *pZetWriteHandler)(UINT16 a, UINT8 d); + +struct ZetExt { + Z80_Regs reg; + + UINT8* pZetMemMap[0x100 * 4]; + + pZetInHandler ZetIn; + pZetOutHandler ZetOut; + pZetReadHandler ZetRead; + pZetWriteHandler ZetWrite; + + UINT8 BusReq; +}; + +static INT32 nZetCyclesDone[MAX_Z80]; +static INT32 nZetCyclesTotal; +static INT32 nZ80ICount[MAX_Z80]; +static UINT32 Z80EA[MAX_Z80]; + +static INT32 nOpenedCPU = -1; +static INT32 nCPUCount = 0; +INT32 nHasZet = -1; + +UINT8 __fastcall ZetDummyReadHandler(UINT16) { return 0; } +void __fastcall ZetDummyWriteHandler(UINT16, UINT8) { } +UINT8 __fastcall ZetDummyInHandler(UINT16) { return 0; } +void __fastcall ZetDummyOutHandler(UINT16, UINT8) { } + +UINT8 __fastcall ZetReadIO(UINT32 a) +{ + return ZetCPUContext[nOpenedCPU].ZetIn(a); +} + +void __fastcall ZetWriteIO(UINT32 a, UINT8 d) +{ + ZetCPUContext[nOpenedCPU].ZetOut(a, d); +} + +UINT8 __fastcall ZetReadProg(UINT32 a) +{ + // check mem map + UINT8 * pr = ZetCPUContext[nOpenedCPU].pZetMemMap[0x000 | (a >> 8)]; + if (pr != NULL) { + return pr[a & 0xff]; + } + + // check handler + if (ZetCPUContext[nOpenedCPU].ZetRead != NULL) { + return ZetCPUContext[nOpenedCPU].ZetRead(a); + } + + return 0; +} + +void __fastcall ZetWriteProg(UINT32 a, UINT8 d) +{ + // check mem map + UINT8 * pr = ZetCPUContext[nOpenedCPU].pZetMemMap[0x100 | (a >> 8)]; + if (pr != NULL) { + pr[a & 0xff] = d; + return; + } + + // check handler + if (ZetCPUContext[nOpenedCPU].ZetWrite != NULL) { + ZetCPUContext[nOpenedCPU].ZetWrite(a, d); + return; + } +} + +UINT8 __fastcall ZetReadOp(UINT32 a) +{ + // check mem map + UINT8 * pr = ZetCPUContext[nOpenedCPU].pZetMemMap[0x200 | (a >> 8)]; + if (pr != NULL) { + return pr[a & 0xff]; + } + + // check read handler + if (ZetCPUContext[nOpenedCPU].ZetRead != NULL) { + return ZetCPUContext[nOpenedCPU].ZetRead(a); + } + + return 0; +} + +UINT8 __fastcall ZetReadOpArg(UINT32 a) +{ + // check mem map + UINT8 * pr = ZetCPUContext[nOpenedCPU].pZetMemMap[0x300 | (a >> 8)]; + if (pr != NULL) { + return pr[a & 0xff]; + } + + // check read handler + if (ZetCPUContext[nOpenedCPU].ZetRead != NULL) { + return ZetCPUContext[nOpenedCPU].ZetRead(a); + } + + return 0; +} + +void ZetSetReadHandler(UINT8 (__fastcall *pHandler)(UINT16)) +{ + ZetCPUContext[nOpenedCPU].ZetRead = pHandler; +} + +void ZetSetWriteHandler(void (__fastcall *pHandler)(UINT16, UINT8)) +{ + ZetCPUContext[nOpenedCPU].ZetWrite = pHandler; +} + +void ZetSetInHandler(UINT8 (__fastcall *pHandler)(UINT16)) +{ + ZetCPUContext[nOpenedCPU].ZetIn = pHandler; +} + +void ZetSetOutHandler(void (__fastcall *pHandler)(UINT16, UINT8)) +{ + ZetCPUContext[nOpenedCPU].ZetOut = pHandler; +} + +void ZetNewFrame() +{ + for (INT32 i = 0; i < nCPUCount; i++) { + nZetCyclesDone[i] = 0; + } + nZetCyclesTotal = 0; +} + +INT32 ZetInit(INT32 nCount) +{ + nOpenedCPU = -1; + + ZetCPUContext = (struct ZetExt *) malloc(nCount * sizeof(ZetExt)); + if (ZetCPUContext == NULL) return 1; + memset(ZetCPUContext, 0, nCount * sizeof(ZetExt)); + + Z80Init(); + + for (INT32 i = 0; i < nCount; i++) { + ZetCPUContext[i].ZetIn = ZetDummyInHandler; + ZetCPUContext[i].ZetOut = ZetDummyOutHandler; + ZetCPUContext[i].ZetRead = ZetDummyReadHandler; + ZetCPUContext[i].ZetWrite = ZetDummyWriteHandler; + ZetCPUContext[i].BusReq = 0; + // TODO: Z80Init() will set IX IY F regs with default value, so get them ... + Z80GetContext(&ZetCPUContext[i].reg); + + nZetCyclesDone[i] = 0; + nZ80ICount[i] = 0; + + for (INT32 j = 0; j < (0x0100 * 4); j++) { + ZetCPUContext[i].pZetMemMap[j] = NULL; + } + } + + nZetCyclesTotal = 0; + + Z80SetIOReadHandler(ZetReadIO); + Z80SetIOWriteHandler(ZetWriteIO); + Z80SetProgramReadHandler(ZetReadProg); + Z80SetProgramWriteHandler(ZetWriteProg); + Z80SetCPUOpReadHandler(ZetReadOp); + Z80SetCPUOpArgReadHandler(ZetReadOpArg); + + ZetOpen(0); + + nCPUCount = nCount % MAX_Z80; + + nHasZet = nCount; + + for (INT32 i = 0; i < nCount; i++) + CpuCheatRegister(0x0004, i); + + return 0; +} + +UINT8 ZetReadByte(UINT16 address) +{ + if (nOpenedCPU < 0) return 0; + + return ZetReadProg(address); +} + +void ZetWriteByte(UINT16 address, UINT8 data) +{ + if (nOpenedCPU < 0) return; + + ZetWriteProg(address, data); +} + +void ZetWriteRom(UINT16 address, UINT8 data) +{ + if (nOpenedCPU < 0) return; + + if (ZetCPUContext[nOpenedCPU].pZetMemMap[0x200 | (address >> 8)] != NULL) { + ZetCPUContext[nOpenedCPU].pZetMemMap[0x200 | (address >> 8)][address] = data; + } + + if (ZetCPUContext[nOpenedCPU].pZetMemMap[0x300 | (address >> 8)] != NULL) { + ZetCPUContext[nOpenedCPU].pZetMemMap[0x300 | (address >> 8)][address] = data; + } + + ZetWriteProg(address, data); +} + +void ZetClose() +{ + Z80GetContext(&ZetCPUContext[nOpenedCPU].reg); + nZetCyclesDone[nOpenedCPU] = nZetCyclesTotal; + nZ80ICount[nOpenedCPU] = z80_ICount; + Z80EA[nOpenedCPU] = EA; + + nOpenedCPU = -1; +} + +void ZetOpen(INT32 nCPU) +{ + Z80SetContext(&ZetCPUContext[nCPU].reg); + nZetCyclesTotal = nZetCyclesDone[nCPU]; + z80_ICount = nZ80ICount[nCPU]; + EA = Z80EA[nCPU]; + + nOpenedCPU = nCPU; +} + +INT32 ZetGetActive() +{ + return nOpenedCPU; +} + +INT32 ZetRun(INT32 nCycles) +{ + if (nCycles <= 0) return 0; + + if (ZetCPUContext[nOpenedCPU].BusReq) { + nZetCyclesTotal += nCycles; + return nCycles; + } + + nCycles = Z80Execute(nCycles); + + nZetCyclesTotal += nCycles; + + return nCycles; +} + +void ZetRunAdjust(INT32 /*nCycles*/) +{ +} + +void ZetRunEnd() +{ +} + +// This function will make an area callback ZetRead/ZetWrite +INT32 ZetMemCallback(INT32 nStart, INT32 nEnd, INT32 nMode) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = ZetCPUContext[nOpenedCPU].pZetMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + switch (nMode) { + case 0: + pMemMap[0 + i] = NULL; + break; + case 1: + pMemMap[0x100 + i] = NULL; + break; + case 2: + pMemMap[0x200 + i] = NULL; + pMemMap[0x300 + i] = NULL; + break; + } + } + + return 0; +} + +INT32 ZetMemEnd() +{ + return 0; +} + +void ZetExit() +{ + Z80Exit(); + if (ZetCPUContext) { + free(ZetCPUContext); + ZetCPUContext = NULL; + } + + nCPUCount = 0; + nHasZet = -1; +} + + +INT32 ZetMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = ZetCPUContext[nOpenedCPU].pZetMemMap; + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + switch (nMode) { + case 0: { + pMemMap[0 + i] = Mem + ((i - cStart) << 8); + break; + } + + case 1: { + pMemMap[0x100 + i] = Mem + ((i - cStart) << 8); + break; + } + + case 2: { + pMemMap[0x200 + i] = Mem + ((i - cStart) << 8); + pMemMap[0x300 + i] = Mem + ((i - cStart) << 8); + break; + } + } + } + + return 0; +} + +INT32 ZetMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem01, UINT8 *Mem02) +{ + UINT8 cStart = (nStart >> 8); + UINT8 **pMemMap = ZetCPUContext[nOpenedCPU].pZetMemMap; + + if (nMode != 2) { + return 1; + } + + for (UINT16 i = cStart; i <= (nEnd >> 8); i++) { + pMemMap[0x200 + i] = Mem01 + ((i - cStart) << 8); + pMemMap[0x300 + i] = Mem02 + ((i - cStart) << 8); + } + + return 0; +} + +INT32 ZetReset() +{ + Z80Reset(); + + return 0; +} + +INT32 ZetPc(INT32 n) +{ + if (n < 0) { + return ActiveZ80GetPC(); + } else { + return ZetCPUContext[n].reg.pc.w.l; + } +} + +INT32 ZetBc(INT32 n) +{ + if (n < 0) { + return ActiveZ80GetBC(); + } else { + return ZetCPUContext[n].reg.bc.w.l; + } +} + +INT32 ZetDe(INT32 n) +{ + if (n < 0) { + return ActiveZ80GetDE(); + } else { + return ZetCPUContext[n].reg.de.w.l; + } +} + +INT32 ZetHL(INT32 n) +{ + if (n < 0) { + return ActiveZ80GetHL(); + } else { + return ZetCPUContext[n].reg.hl.w.l; + } +} + +INT32 ZetScan(INT32 nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 0; + } + + char szText[] = "Z80 #0"; + + for (INT32 i = 0; i < nCPUCount; i++) { + szText[5] = '1' + i; + + ScanVar(&ZetCPUContext[i].reg, sizeof(Z80_Regs), szText); + SCAN_VAR(Z80EA[i]); + SCAN_VAR(nZ80ICount[i]); + SCAN_VAR(nZetCyclesDone[i]); + } + + SCAN_VAR(nZetCyclesTotal); + + return 0; +} + +void ZetSetIRQLine(const INT32 line, const INT32 status) +{ + switch ( status ) { + case ZET_IRQSTATUS_NONE: + Z80SetIrqLine(0, 0); + break; + case ZET_IRQSTATUS_ACK: + Z80SetIrqLine(line, 1); + break; + case ZET_IRQSTATUS_AUTO: + Z80SetIrqLine(line, 1); + Z80Execute(0); + Z80SetIrqLine(0, 0); + Z80Execute(0); + break; + } +} + +void ZetSetVector(INT32 vector) +{ + Z80Vector = vector; +} + +INT32 ZetNmi() +{ + Z80SetIrqLine(Z80_INPUT_LINE_NMI, 1); + Z80Execute(0); + Z80SetIrqLine(Z80_INPUT_LINE_NMI, 0); + Z80Execute(0); + INT32 nCycles = 12; + nZetCyclesTotal += nCycles; + + return nCycles; +} + +INT32 ZetIdle(INT32 nCycles) +{ + nZetCyclesTotal += nCycles; + + return nCycles; +} + +INT32 ZetSegmentCycles() +{ + return 0; +} + +INT32 ZetTotalCycles() +{ + return nZetCyclesTotal; +} + +void ZetSetBUSREQLine(INT32 nStatus) +{ + if (nOpenedCPU < 0) return; + + ZetCPUContext[nOpenedCPU].BusReq = nStatus; +} + +#undef MAX_Z80 diff --git a/src/cpu/zet.h b/src/cpu/zet.h new file mode 100644 index 00000000..920faae0 --- /dev/null +++ b/src/cpu/zet.h @@ -0,0 +1,51 @@ +// Z80 (Zed Eight-Ty) Interface + +#ifndef FASTCALL + #undef __fastcall + #define __fastcall +#endif + +#include "z80.h" + +extern INT32 nHasZet; +void ZetWriteByte(UINT16 address, UINT8 data); +UINT8 ZetReadByte(UINT16 address); +void ZetWriteRom(UINT16 address, UINT8 data); +INT32 ZetInit(INT32 nCount); +void ZetExit(); +void ZetNewFrame(); +void ZetOpen(INT32 nCPU); +void ZetClose(); +INT32 ZetGetActive(); +INT32 ZetMemCallback(INT32 nStart,INT32 nEnd,INT32 nMode); +INT32 ZetMemEnd(); +INT32 ZetMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem); +INT32 ZetMapArea(INT32 nStart, INT32 nEnd, INT32 nMode, UINT8 *Mem01, UINT8 *Mem02); +INT32 ZetReset(); +INT32 ZetPc(INT32 n); +INT32 ZetBc(INT32 n); +INT32 ZetDe(INT32 n); +INT32 ZetHL(INT32 n); +INT32 ZetScan(INT32 nAction); +INT32 ZetRun(INT32 nCycles); +void ZetRunEnd(); +void ZetSetIRQLine(const INT32 line, const INT32 status); +void ZetSetVector(INT32 vector); +INT32 ZetNmi(); +INT32 ZetIdle(INT32 nCycles); +INT32 ZetSegmentCycles(); +INT32 ZetTotalCycles(); + +#define ZET_IRQSTATUS_NONE 0 +#define ZET_IRQSTATUS_ACK 1 +#define ZET_IRQSTATUS_AUTO 2 + +#define ZetRaiseIrq(n) ZetSetIRQLine(n, ZET_IRQSTATUS_AUTO) +#define ZetLowerIrq() ZetSetIRQLine(0, Z80_CLEAR_LINE) + +void ZetSetReadHandler(UINT8 (__fastcall *pHandler)(UINT16)); +void ZetSetWriteHandler(void (__fastcall *pHandler)(UINT16, UINT8)); +void ZetSetInHandler(UINT8 (__fastcall *pHandler)(UINT16)); +void ZetSetOutHandler(void (__fastcall *pHandler)(UINT16, UINT8)); + +void ZetSetBUSREQLine(INT32 nStatus); diff --git a/src/depend/kaillera/client/kailleraclient.h b/src/depend/kaillera/client/kailleraclient.h new file mode 100644 index 00000000..06818e98 --- /dev/null +++ b/src/depend/kaillera/client/kailleraclient.h @@ -0,0 +1,135 @@ +/* + Kaillera client API v0.84 + (c) 2001 Christophe Thibault + + History: + 0.84: added moreInfos callback + 0.83: added clientDropped callback + 0.8 : added in-game chat function/callback + 0.72: added kailleraEndGame() method + added kailleraGetVersion() method + 0.7: modified kailleraModifyPlayValues behaviour +*/ + +#ifndef KAILLERA_CLIENT_H +#define KAILLERA_CLIENT_H + +#ifdef _WIN32 +#include +#endif + +#define KAILLERA_CLIENT_API_VERSION "0.9" + +#ifdef KAILLERA_DLL +#define DLLEXP __declspec(dllexport) int WINAPI +#else +#define DLLEXP __declspec(dllimport) int WINAPI +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct { + char *appName; + char *gameList; + + int (WINAPI *gameCallback)(char *game, int player, int numplayers); + + void (WINAPI *chatReceivedCallback)(char *nick, char *text); + void (WINAPI *clientDroppedCallback)(char *nick, int playernb); + + void (WINAPI *moreInfosCallback)(char *gamename); + } kailleraInfos; + + /* + kailleraGetVersion + Call this method to retrieve kailleraclient.dll's version + - version must point to a char[16] buffer + */ + DLLEXP kailleraGetVersion(char *version); + /* + kailleraInit: + Call this method when your program starts + */ + DLLEXP kailleraInit(); + /* + kailleraShutdown: + Call this method when your program ends + */ + DLLEXP kailleraShutdown(); + /* + kailleraSetInfos: + Use this method for setting up various infos: + Required: + - appName must be 128 chars max. + - gameList is composed of all the game names separated by a NULL char (\0). + The list ends with 2 NULL chars (\0\0). + Be sure to only put available games there. + - gameCallback will be the function called when a new game starts + game -> name of the selected game + player -> player number (1-8). 0 for spectator. + numplayers -> number of players in the game (1-8) + + Optional: + - chatReceivedCallback will be the function called when a chat line text + has been received. Set it to NULL if you don't need/want this callback. + - clientDroppedCallback will be the function called when a client drops + from the current game. Set it to NULL if you don't need/want this callback. + - moreInfosCallback will be the function called when the user selects + "More infos about this game..." in the game list context menu. + Set it to NULL if you don't need/want this feature. + */ + DLLEXP kailleraSetInfos(kailleraInfos *infos); + /* + kailleraSelectServerDialog: + Use this method for launching the Kaillera server dialog + */ + DLLEXP kailleraSelectServerDialog(HWND parent); + + /* + kailleraModifyPlayValues: + You must call this method at every frame after you retrieved values from your input devices. + This method will record/bufferize the values you send in and will manage to mix them with + the other players. + + Basically, each players sends his values and receive all players values concatened. + + e.g: + t - player 1 sends "867F" - player 2 sends "964F" + t+1 - player 1 receives "867F964F" - player 2 receives "867F964F" + + you may want to look at the modified MAME source code available on kaillera's home page + to have a working example out of this (look in inptport.c) + + Ideally, your input values should be defined like 1 bit for a given key, which has to be + unset when the key is not pressed and set when the key is pressed. + + The size of the values you pass to this function is the size for ONE player's values. + Also, it must be the SAME for a given game and should be kept to a minimum (for network + speed and latency issues). + + Be sure that the values parameters has enough space for receiving all inputs from all players + (8 players max.) + + returns: length received or -1 on network error (player no more in the game) + */ + DLLEXP kailleraModifyPlayValues(void *values, int size); + + /* + kailleraChatSend + Use this function to send a line of chat text during a game + */ + DLLEXP kailleraChatSend(char *text); + + /* + kailleraEndGame: + Your emulation thread must call this method when the user stops the emulation + */ + DLLEXP kailleraEndGame(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/depend/kaillera/client/net.cpp b/src/depend/kaillera/client/net.cpp new file mode 100644 index 00000000..7513a01b --- /dev/null +++ b/src/depend/kaillera/client/net.cpp @@ -0,0 +1,106 @@ +#include +#include +#include "net.h" + +HINSTANCE Kaillera_HDLL; +int Kaillera_Initialised; + +int (WINAPI *Kaillera_Get_Version) (char *version); +int (WINAPI *Kaillera_Init) (); +int (WINAPI *Kaillera_Shutdown) (); +int (WINAPI *Kaillera_Set_Infos) (kailleraInfos *infos); +int (WINAPI *Kaillera_Select_Server_Dialog) (HWND parent); +int (WINAPI *Kaillera_Modify_Play_Values) (void *values, int size); +int (WINAPI *Kaillera_Chat_Send) (char *text); +int (WINAPI *Kaillera_End_Game) (); + + +int WINAPI Empty_Kaillera_Get_Version(char* /*version*/) +{ + return 0; +} + +int WINAPI Empty_Kaillera_Init() +{ + return 0; +} + +int WINAPI Empty_Kaillera_Shutdown() +{ + return 0; +} + +int WINAPI Empty_Kaillera_Set_Infos(kailleraInfos* /*infos*/) +{ + return 0; +} + +int WINAPI Empty_Kaillera_Select_Server_Dialog(HWND /*parent*/) +{ + return 0; +} + +int WINAPI Empty_Kaillera_Modify_Play_Values(void* /*values*/, int /*size*/) +{ + return 0; +} + +int WINAPI Empty_Kaillera_Chat_Send(char* /*text*/) +{ + return 0; +} + +int WINAPI Empty_Kaillera_End_Game() +{ + return 0; +} + + +int Init_Network(void) +{ + Kaillera_HDLL = LoadLibrary("kailleraclient.dll"); + + if (Kaillera_HDLL != NULL) + { + Kaillera_Get_Version = (int (WINAPI *)(char *version)) GetProcAddress(Kaillera_HDLL, "_kailleraGetVersion@4"); + Kaillera_Init = (int (WINAPI *)()) GetProcAddress(Kaillera_HDLL, "_kailleraInit@0"); + Kaillera_Shutdown = (int (WINAPI *)()) GetProcAddress(Kaillera_HDLL, "_kailleraShutdown@0"); + Kaillera_Set_Infos = (int (WINAPI *)(kailleraInfos *infos)) GetProcAddress(Kaillera_HDLL, "_kailleraSetInfos@4"); + Kaillera_Select_Server_Dialog = (int (WINAPI *)(HWND parent)) GetProcAddress(Kaillera_HDLL, "_kailleraSelectServerDialog@4"); + Kaillera_Modify_Play_Values = (int (WINAPI *)(void *values, int size)) GetProcAddress(Kaillera_HDLL, "_kailleraModifyPlayValues@8"); + Kaillera_Chat_Send = (int (WINAPI *)(char *text)) GetProcAddress(Kaillera_HDLL, "_kailleraChatSend@4"); + Kaillera_End_Game = (int (WINAPI *)()) GetProcAddress(Kaillera_HDLL, "_kailleraEndGame@0"); + + if ((Kaillera_Get_Version != NULL) && (Kaillera_Init != NULL) && (Kaillera_Shutdown != NULL) && (Kaillera_Set_Infos != NULL) && (Kaillera_Select_Server_Dialog != NULL) && (Kaillera_Modify_Play_Values != NULL) && (Kaillera_Chat_Send != NULL) && (Kaillera_End_Game != NULL)) + { + Kaillera_Init(); + Kaillera_Initialised = 1; + return 0; + } + + FreeLibrary(Kaillera_HDLL); + } else { + } + + Kaillera_Get_Version = Empty_Kaillera_Get_Version; + Kaillera_Init = Empty_Kaillera_Init; + Kaillera_Shutdown = Empty_Kaillera_Shutdown; + Kaillera_Set_Infos = Empty_Kaillera_Set_Infos; + Kaillera_Select_Server_Dialog = Empty_Kaillera_Select_Server_Dialog; + Kaillera_Modify_Play_Values = Empty_Kaillera_Modify_Play_Values; + Kaillera_Chat_Send = Empty_Kaillera_Chat_Send; + Kaillera_End_Game = Empty_Kaillera_End_Game; + + Kaillera_Initialised = 0; + return 1; +} + + +void End_Network(void) +{ + if (Kaillera_Initialised) + { + Kaillera_Shutdown(); + FreeLibrary(Kaillera_HDLL); + } +} diff --git a/src/depend/kaillera/client/net.h b/src/depend/kaillera/client/net.h new file mode 100644 index 00000000..39f03bf5 --- /dev/null +++ b/src/depend/kaillera/client/net.h @@ -0,0 +1,15 @@ +#include "kailleraclient.h" + +extern int Kaillera_Initialised; + +extern int (WINAPI *Kaillera_Get_Version) (char *version); +extern int (WINAPI *Kaillera_Init) (); +extern int (WINAPI *Kaillera_Shutdown) (); +extern int (WINAPI *Kaillera_Set_Infos) (kailleraInfos *infos); +extern int (WINAPI *Kaillera_Select_Server_Dialog) (HWND parent); +extern int (WINAPI *Kaillera_Modify_Play_Values) (void *values, int size); +extern int (WINAPI *Kaillera_Chat_Send) (char *text); +extern int (WINAPI *Kaillera_End_Game) (); + +int Init_Network(void); +void End_Network(void); diff --git a/src/depend/libs/libpng/fba_libpng_v154.txt b/src/depend/libs/libpng/fba_libpng_v154.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/depend/libs/libpng/png.c b/src/depend/libs/libpng/png.c new file mode 100644 index 00000000..eed31361 --- /dev/null +++ b/src/depend/libs/libpng/png.c @@ -0,0 +1,2422 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_5_4 Your_png_h_is_not_version_1_5_4; + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + if (num_to_check > 8) + num_to_check = 8; + + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_alloc_size_t num_bytes; + + if (png_ptr == NULL) + return (NULL); + + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_alloc_size_t)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Check a user supplied version number, called from both read and write + * functions that create a png_struct + */ +int +png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver) +{ + if (user_png_ver) + { + int i = 0; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_WARNINGS_SUPPORTED + size_t pos = 0; + char m[128]; + + pos = png_safecat(m, sizeof m, pos, "Application built with libpng-"); + pos = png_safecat(m, sizeof m, pos, user_png_ver); + pos = png_safecat(m, sizeof m, pos, " but running with "); + pos = png_safecat(m, sizeof m, pos, png_libpng_ver); + + png_warning(png_ptr, m); +#endif + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + return 0; + } + } + + /* Success return. */ + return 1; +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +PNG_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer"); +} + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any iCCP entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +# endif + +# ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_const_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr == NULL) + return (NULL); + + { + size_t pos = 0; + char number_buf[5]; /* enough for a four digit year */ + +# define APPEND_STRING(string)\ + pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\ + pos, (string)) +# define APPEND_NUMBER(format, value)\ + APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) +# define APPEND(ch)\ + if (pos < (sizeof png_ptr->time_buffer)-1)\ + png_ptr->time_buffer[pos++] = (ch) + + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day % 32); + APPEND(' '); + APPEND_STRING(short_months[(ptime->month - 1) % 12]); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour % 24); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute % 60); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second % 61); + APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + +# undef APPEND +# undef APPEND_NUMBER +# undef APPEND_STRING + } + + return png_ptr->time_buffer; +} +# endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.5.4 - July 7, 2011" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE; +# else + return "libpng version 1.5.4 - July 7, 2011\ + Copyright (c) 1998-2011 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; +# endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_const_charp PNGAPI +png_get_libpng_ver(png_const_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +# endif +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +#ifdef PNG_READ_SUPPORTED +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + + return (inflateReset(&png_ptr->zstream)); +} +#endif /* PNG_READ_SUPPORTED */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32)PNG_LIBPNG_VER); +} + + + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + + return ((png_size_t)size); +} +# endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +# ifdef PNG_CHECK_cHRM_SUPPORTED + +int /* PRIVATE */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + + if (png_ptr == NULL) + return 0; + + /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white + * y must also be greater than 0. To test for the upper limit calculate + * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression + * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is + * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it + * pointless (and it produces compiler warnings!) + */ + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + ret = 0; + } + /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */ + if (white_x > PNG_FP_1 - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + + if (red_x > PNG_FP_1 - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + + if (green_x > PNG_FP_1 - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + + if (blue_x > PNG_FP_1 - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +# endif /* PNG_CHECK_cHRM_SUPPORTED */ + +void /* PRIVATE */ +png_check_IHDR(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max) + +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if (height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +# ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +# else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +# endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* Check an ASCII formated floating point value, see the more detailed + * comments in pngpriv.h + */ +/* The following is used internally to preserve the sticky flags */ +#define png_fp_add(state, flags) ((state) |= (flags)) +#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + switch (string[i]) + { + case 43: type = PNG_FP_SAW_SIGN; break; + case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; + case 46: type = PNG_FP_SAW_DOT; break; + case 48: type = PNG_FP_SAW_DIGIT; break; + case 49: case 50: case 51: case 52: + case 53: case 54: case 55: case 56: + case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; + case 69: + case 101: type = PNG_FP_SAW_E; break; + default: goto PNG_FP_End; + } + + /* Now deal with this type according to the current + * state, the type is arranged to not overlap the + * bits of the PNG_FP_STATE. + */ + switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) + { + case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, type); + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DOT: + /* Ok as trailer, ok as lead of fraction. */ + if (state & PNG_FP_SAW_DOT) /* two dots */ + goto PNG_FP_End; + + else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ + png_fp_add(state, type); + + else + png_fp_set(state, PNG_FP_FRACTION | type); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: + if (state & PNG_FP_SAW_DOT) /* delayed fraction */ + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + png_fp_add(state, type | PNG_FP_WAS_VALID); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: + goto PNG_FP_End; ** no sign in fraction */ + + /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: + goto PNG_FP_End; ** Because SAW_DOT is always set */ + + case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: + png_fp_add(state, type | PNG_FP_WAS_VALID); + break; + + case PNG_FP_FRACTION + PNG_FP_SAW_E: + /* This is correct because the trailing '.' on an + * integer is handled above - so we can only get here + * with the sequence ".E" (with no preceding digits). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +png_check_fp_string(png_const_charp string, png_size_t size) +{ + int state=0; + png_size_t char_index=0; + + if (png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0)) + return state /* must be non-zero - see above */; + + return 0; /* i.e. fail */ +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_READ_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + exp_b10 = -exp_b10; + } + + cdigits = 0; + + while (exp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + exp_b10 % 10); + exp_b10 /= 10; + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, + png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000U) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16 /* flag value */; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* READ_SCAL */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) +png_fixed_point +png_fixed(png_structp png_ptr, double fp, png_const_charp text) +{ + double r = floor(100000 * fp + .5); + + if (r > 2147483647. || r < -2147483648.) + png_fixed_error(png_ptr, text); + + return (png_fixed_point)r; +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || \ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32-bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64-bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* A local convenience routine. */ +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, + * 2010: moved from pngset.c) */ +/* + * Multiply two 32-bit numbers, V1 and V2, using 32-bit + * arithmetic, to produce a 64-bit result in the HI/LO words. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void /* PRIVATE */ +png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} +#endif /* CHECK_cHRM */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* Fixed point gamma. + * + * To calculate gamma this code implements fast log() and exp() calls using only + * fixed point arithmetic. This code has sufficient precision for either 8-bit + * or 16-bit sample values. + * + * The tables used here were calculated using simple 'bc' programs, but C double + * precision floating point arithmetic would work fine. The programs are given + * at the head of each table. + * + * 8-bit log table + * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to + * 255, so it's the base 2 logarithm of a normalized 8-bit floating point + * mantissa. The numbers are 32-bit fractions. + */ +static png_uint_32 +png_8bit_l2[128] = +{ +# if PNG_DO_BC + for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; } +# endif + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, + 24347096U, 0U +#if 0 + /* The following are the values for 16-bit tables - these work fine for the + * 8-bit conversions but produce very slightly larger errors in the 16-bit + * log (about 1.2 as opposed to 0.7 absolute error in the final value). To + * use these all the shifts below must be adjusted appropriately. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +PNG_STATIC png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return 7.99998 for the overflow (log 0) case - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return 0xffffffff; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); +} + +/* The above gives exact (to 16 binary places) log2 values for 8-bit images, + * for 16-bit images we use the most significant 8 bits of the 16-bit value to + * get an approximation then multiply the approximation by a correction factor + * determined by the remaining up to 8 bits. This requires an additional step + * in the 16-bit case. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 + * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less + * than 258. The final factor also needs to correct for the fact that our 8-bit + * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * Since these numbers are so close to '1' we can use simple linear + * interpolation between the two end values 256/257 (result -368.61) and 258/257 + * (result 367.179). The values used below are scaled by a further 64 to give + * 16-bit precision in the interpolation: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +PNG_STATIC png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return 0xffffffff; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + return (png_int_32)((lg2 + 2048) >> 12); +} + +/* The 'exp()' case must invert the above, taking a 20-bit fixed point + * logarithmic value and returning a 16 or 8-bit number as appropriate. In + * each case only the low 16 bits are relevant - the fraction - since the + * integer bits (the top 4) simply determine a shift. + * + * The worst case is the 16-bit distinction between 65535 and 65534, this + * requires perhaps spurious accuracty in the decoding of the logarithm to + * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance + * of getting this accuracy in practice. + * + * To deal with this the following exp() function works out the exponent of the + * frational part of the logarithm by using an accurate 32-bit value from the + * top four fractional bits then multiplying in the remaining bits. + */ +static png_uint_32 +png_32bit_exp[16] = +{ +# if PNG_DO_BC + for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; } +# endif + /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#if PNG_DO_BC +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +PNG_STATIC png_uint_32 +png_exp(png_fixed_point x) +{ + if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ + { + /* Obtain a 4-bit approximation */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +PNG_STATIC png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +PNG_STATIC png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* This does the right thing based on the bit_depth field of the + * png_struct, interpreting values as 8-bit or 16-bit. While the result + * is nominally a 16-bit value if bit depth is 8 then the result is + * 8-bit (as are the arguments.) + */ +png_uint_16 /* PRIVATE */ +png_gamma_correct(png_structp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} + +/* Internal function to build a single 16-bit table - the table consists of + * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount + * to shift the input values right (or 16-number_of_signifiant_bits). + * + * The caller is responsible for ensuring that the table gets cleaned up on + * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument + * should be somewhere that will be cleaned. + */ +static void +png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + /* Various values derived from 'shift': */ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int i; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_uint_16p sub_table = table[i] = + (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16)); + + /* The 'threshold' test is repeated here because it can arise for one of + * the 16-bit tables even if the others don't hit it. + */ + if (png_gamma_significant(gamma_val)) + { + /* The old code would overflow at the end and this would cause the + * 'pow' function to return a result >1, resulting in an + * arithmetic error. This code follows the spec exactly; ig is + * the recovered input sample, it always has 8-16 bits. + * + * We want input * 65535/max, rounded, the arithmetic fits in 32 + * bits (unsigned) so long as max <= 32767. + */ + unsigned int j; + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* Inline the 'max' scaling operation: */ + double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); + sub_table[j] = (png_uint_16)d; +# else + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); +# endif + } + } + else + { + /* We must still build a table, but do it the fast way. */ + unsigned int j; + + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; + + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = (png_uint_16)ig; + } + } + } +} + +/* NOTE: this function expects the *inverse* of the overall gamma transformation + * required. + */ +static void +png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int i; + png_uint_32 last; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + /* 'num' is the number of tables and also the number of low bits of low + * bits of the input 16-bit value used to select a table. Each table is + * itself index by the high 8 bits of the value. + */ + for (i = 0; i < num; i++) + table[i] = (png_uint_16p)png_malloc(png_ptr, + 256 * png_sizeof(png_uint_16)); + + /* 'gamma_val' is set to the reciprocal of the value calculated above, so + * pow(out,g) is an *input* value. 'last' is the last input value set. + * + * In the loop 'i' is used to find output values. Since the output is + * 8-bit there are only 256 possible values. The tables are set up to + * select the closest possible output value for each input by finding + * the input value at the boundary between each pair of output values + * and filling the table up to that boundary with the lower output + * value. + * + * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit + * values the code below uses a 16-bit value in i; the values start at + * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last + * entries are filled with 255). Start i at 128 and fill all 'last' + * table entries <= 'max' + */ + last = 0; + for (i = 0; i < 255; ++i) /* 8-bit output value */ + { + /* Find the corresponding maximum input value */ + png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ + + /* Find the boundary value in 16 bits: */ + png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); + + /* Adjust (round) to (16-shift) bits: */ + bound = (bound * max + 32768U)/65535U + 1U; + + while (last < bound) + { + table[last & (0xffU >> shift)][last >> (8U - shift)] = out; + last++; + } + } + + /* And fill in the final entries. */ + while (last < (num << 8)) + { + table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; + last++; + } +} + +/* Build a single 8-bit table: same as the 16-bit case but much simpler (and + * typically much faster). Note that libpng currently does no sBIT processing + * (apparently contrary to the spec) so a 256 entry table is always generated. + */ +static void +png_build_8bit_table(png_structp png_ptr, png_bytepp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_8bit_correct(i, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_byte)i; +} + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->gamma)); + + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } + else + { + png_byte shift, sig_bit; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + /* 16-bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256 entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits of + * the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } + + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ + + png_ptr->gamma_shift = shift; + +#ifdef PNG_16BIT_SUPPORTED + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be reduced + * to 8 bits. + */ + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) +#endif + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#ifdef PNG_16BIT_SUPPORTED + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->gamma)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } +} +#endif /* READ_GAMMA */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/src/depend/libs/libpng/png.h b/src/depend/libs/libpng/png.h new file mode 100644 index 00000000..c655a51a --- /dev/null +++ b/src/depend/libs/libpng/png.h @@ -0,0 +1,2588 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.5.4 - July 7, 2011 + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.5.4 - July 7, 2011: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, +# endif + + /* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +# ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include +# endif +# endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_5_4; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef PNG_CONST png_color FAR * png_const_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef PNG_CONST png_color_16 FAR * png_const_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef PNG_CONST png_color_8 FAR * png_const_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef PNG_CONST png_time FAR * png_const_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} + + +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* Values for the unknown chunk location byte */ + +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* The complete definition of png_info has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((png_size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* The complete definition of png_struct has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +typedef png_struct FAR * FAR * png_structpp; + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, + png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); + +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + PNG_CONST struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, + (png_timep ptime, time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, + int error_action, double red, double green)); +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels of + * a PNG file are returned when an alpha channel, or tRNS chunk in a palette + * file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel. The gamma encoded color channels must be + * scaled according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. The + * advantage is that the color channels can be resampled (the image can be + * scaled) in this form. The disadvantage is that normal practice is to store + * linear, not (gamma) encoded, values and this requires 16-bit channels for + * still images rather than the 8-bit channels that are just about sufficient if + * gamma encoding is used. In addition all non-transparent pixel values, + * including completely opaque ones, must be gamma encoded to produce the final + * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the + * latter being the two common names for associated alpha color channels.) + * + * Since it is not necessary to perform arithmetic on opaque color values so + * long as they are not to be resampled and are in the final color space it is + * possible to optimize the handling of alpha by storing the opaque pixels in + * the PNG format (adjusted for the output color space) while storing partially + * opaque pixels in the standard, linear, format. The accuracy required for + * standard alpha composition is relatively low, because the pixels are + * isolated, therefore typically the accuracy loss in storing 8-bit linear + * values is acceptable. (This is not true if the alpha channel is used to + * simulate transparency over large areas - use 16 bits or the PNG mode in + * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is + * treated as opaque only if the alpha value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, + double output_gamma)); +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, + int mode, png_fixed_point output_gamma)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. The values used + * correspond to the normal numbers used to describe the overall gamma of a + * computer display system; for example 2.2 for an sRGB conformant system. The + * values are scaled by 100000 in the _fixed version of the API (so 220000 for + * sRGB.) + * + * The inverse of the value is always used to provide a default for the PNG file + * encoding if it has no gAMA chunk and if png_set_gamma() has not been called + * to override the PNG gamma information. + * + * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode + * opaque pixels however pixels with lower alpha values are not encoded, + * regardless of the output gamma setting. + * + * When the standard Porter Duff handling is requested with mode 1 the output + * encoding is set to be linear and the output_gamma value is only relevant + * as a default for input data that has no gamma information. The linear output + * encoding will be overridden if png_set_gamma() is called - the results may be + * highly unexpected! + * + * The following numbers are derived from the sRGB standard and the research + * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of + * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing + * correction required to take account of any differences in the color + * environment of the original scene and the intended display environment; the + * value expresses how to *decode* the image for display, not how the original + * data was *encoded*. + * + * sRGB provides a peg for the PNG standard by defining a viewing environment. + * sRGB itself, and earlier TV standards, actually use a more complex transform + * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is + * limited to simple power laws.) By saying that an image for direct display on + * an sRGB conformant system should be stored with a gAMA chunk value of 45455 + * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification + * makes it possible to derive values for other display systems and + * environments. + * + * The Mac value is deduced from the sRGB based on an assumption that the actual + * extra viewing correction used in early Mac display systems was implemented as + * a power 1.45 lookup table. + * + * Any system where a programmable lookup table is used or where the behavior of + * the final display device characteristics can be changed requires system + * specific code to obtain the current characteristic. However this can be + * difficult and most PNG gamma correction only requires an approximate value. + * + * By default, if png_set_alpha_mode() is not called, libpng assumes that all + * values are unencoded, linear, values and that the output device also has a + * linear characteristic. This is only very rarely correct - it is invariably + * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the + * default if you don't know what the right answer is! + * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * + * NOTE: the following values can be passed to either the fixed or floating + * point APIs, but the floating point API will also accept floating point + * values. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, + (png_structp png_ptr, png_uint_32 filler, + int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, + (png_structp png_ptr, double screen_gamma, + double override_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, + (png_structp png_ptr, int method, int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)); +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_fixed_point_p + filter_weights, png_const_fixed_point_p filter_costs)); +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +#ifdef PNG_WRITE_SUPPORTED +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, + int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp + png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, + (png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +PNG_EXPORT(99, void, png_data_freer, + (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, + png_const_charp warning_message)); +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structp png_ptr, + png_const_infop info_ptr, png_fixed_point *int_white_x, + png_fixed_point *int_white_y, png_fixed_point *int_red_x, + png_fixed_point *int_red_y, png_fixed_point *int_green_x, + png_fixed_point *int_green_y, png_fixed_point *int_blue_x, + png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, + (png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)); +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma)); +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, + int *interlace_method, int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int interlace_method, int compression_method, int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, + (png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, + int *nparams, + png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, + (png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, + (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, + png_infop info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, + png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, + png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, + (png_structp png_ptr, png_infop info_ptr, + png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, png_uint_32, png_get_text, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height)); +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_structp png_ptr, png_const_infop info_ptr, int *unit, + png_fixed_point *width, + png_fixed_point *height)); +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height)); +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, + png_fixed_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (png_structp png_ptr, int keep, + png_const_bytep chunk_list, int num_chunks)); +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, + png_const_bytep chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, + png_const_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, + (png_structp png_ptr, png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structp png_ptr, png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, + png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, + png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); + +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L \ + - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define png_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define png_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(229); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/src/depend/libs/libpng/pngconf.h b/src/depend/libs/libpng/pngconf.h new file mode 100644 index 00000000..222816e3 --- /dev/null +++ b/src/depend/libs/libpng/pngconf.h @@ -0,0 +1,619 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.5.4 - July 7, 2011 + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C + * definition file for machine specific limits, this may impact the + * correctness of the definitons below (see uses of INT_MAX). + */ +# ifndef PNG_NO_LIMITS_H +# include +# endif + +/* For the memory copy APIs (i.e. the standard definitions of these), + * because this file defines png_memcpy and so on the base APIs must + * be defined here. + */ +# ifdef BSD +# include +# else +# include +# endif + +/* For png_FILE_p - this provides the standard definition of a + * FILE + */ +# ifdef PNG_STDIO_SUPPORTED +# include +# endif +#endif + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +# ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +# else + +# ifdef _NO_PROTO +# define PNGARG(arglist) () +# else +# define PNGARG(arglist) arglist +# endif /* _NO_PROTO */ + +# endif /* OF */ + +#endif /* PNGARG */ + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64) ) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* The default for PNG_IMPEXP depends on whether the library is + * being built or used. + */ +#ifndef PNG_IMPEXP +# ifdef PNGLIB_BUILD + /* Building the library */ +# if (defined(DLL_EXPORT)/*from libtool*/ ||\ + defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ + defined(_USRDLL) ||\ + defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) + /* Building a DLL. */ +# define PNG_IMPEXP PNG_DLL_EXPORT +# endif /* DLL */ +# else + /* Using the library */ +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# if defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# endif /* PNGLIB_BUILD */ +# endif /* __GNUC__ */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# endif /* PNGLIB_BUILD */ +# endif /* _MSC_VER */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. + */ +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T +typedef unsigned int png_size_t; +#else +typedef size_t png_size_t; +#endif +#define png_sizeof(x) (sizeof (x)) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K /* only used in build */ +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + * to fixed-point with a multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + typedef unsigned long png_alloc_size_t; +# else + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; +# else + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif + +#endif /* PNGCONF_H */ diff --git a/src/depend/libs/libpng/pngdebug.h b/src/depend/libs/libpng/pngdebug.h new file mode 100644 index 00000000..16f81fdd --- /dev/null +++ b/src/depend/libs/libpng/pngdebug.h @@ -0,0 +1,157 @@ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' tab characters (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +# endif +# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +# endif +# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +# endif +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# if (PNG_DEBUG > 1) +# ifndef _DEBUG +# define _DEBUG +# endif +# ifndef png_debug +# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +# endif +# endif +# else /* PNG_DEBUG_FILE || !_MSC_VER */ +# ifndef PNG_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# ifndef PNG_DEBUG_FILE +# define PNG_DEBUG_FILE stderr +# endif /* PNG_DEBUG_FILE */ + +# if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } while (0) +# endif +# endif /* __STDC __ */ +# endif /* (PNG_DEBUG > 1) */ + +# endif /* _MSC_VER */ +# endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +# define png_debug(l, m) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/src/depend/libs/libpng/pngerror.c b/src/depend/libs/libpng/pngerror.c new file mode 100644 index 00000000..4d4cebaf --- /dev/null +++ b/src/depend/libs/libpng/pngerror.c @@ -0,0 +1,672 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr, + png_const_charp error_message)),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +PNG_FUNCTION(void,PNGAPI +png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +PNG_FUNCTION(void,PNGAPI +png_err,(png_structp png_ptr),PNG_NORETURN) +{ + /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed + * erroneously as '\0', instead of the empty string "". This was + * apparently an error, introduced in libpng-1.2.20, and png_default_error + * will crash in this case. + */ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, ""); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, ""); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +/* Utility to safely appends strings to a buffer. This never errors out so + * error checking is not required in the caller. + */ +size_t +png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string) +{ + if (buffer != NULL && pos < bufsize) + { + if (string != NULL) + while (*string != '\0' && pos < bufsize-1) + buffer[pos++] = *string++; + + buffer[pos] = '\0'; + } + + return pos; +} + +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. + */ +png_charp +png_format_number(png_const_charp start, png_charp end, int format, + png_alloc_size_t number) +{ + int count = 0; /* number of digits output */ + int mincount = 1; /* minimum number required */ + int output = 0; /* digit output (for the fixed point format) */ + + *--end = '\0'; + + /* This is written so that the loop always runs at least once, even with + * number zero. + */ + while (end > start && (number != 0 || count < mincount)) + { + + static const char digits[] = "0123456789ABCDEF"; + + switch (format) + { + case PNG_NUMBER_FORMAT_fixed: + /* Needs five digits (the fraction) */ + mincount = 5; + if (output || number % 10 != 0) + { + *--end = digits[number % 10]; + output = 1; + } + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02u: + /* Expects at least 2 digits. */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_u: + *--end = digits[number % 10]; + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02x: + /* This format expects at least two digits */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_x: + *--end = digits[number & 0xf]; + number >>= 4; + break; + + default: /* an error */ + number = 0; + break; + } + + /* Keep track of the number of digits added */ + ++count; + + /* Float a fixed number here: */ + if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + { + /* End of the fraction, but maybe nothing was output? In that case + * drop the decimal point. If the number is a true zero handle that + * here. + */ + if (output) + *--end = '.'; + else if (number == 0) /* and !output */ + *--end = '0'; + } + } + + return end; +} +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} + +/* These functions support 'formatted' warning messages with up to + * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter + * is introduced by @, where 'number' starts at 1. This follows the + * standard established by X/Open for internationalizable error messages. + */ +void +png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string) +{ + if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) + (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); +} + +void +png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, + png_alloc_size_t value) +{ + char buffer[PNG_NUMBER_BUFFER_SIZE]; + png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); +} + +void +png_warning_parameter_signed(png_warning_parameters p, int number, int format, + png_int_32 value) +{ + png_alloc_size_t u; + png_charp str; + char buffer[PNG_NUMBER_BUFFER_SIZE]; + + /* Avoid overflow by doing the negate in a png_alloc_size_t: */ + u = (png_alloc_size_t)value; + if (value < 0) + u = ~u + 1; + + str = PNG_FORMAT_NUMBER(buffer, format, u); + + if (value < 0 && str > buffer) + *--str = '-'; + + png_warning_parameter(p, number, str); +} + +void +png_formatted_warning(png_structp png_ptr, png_warning_parameters p, + png_const_charp message) +{ + /* The internal buffer is just 128 bytes - enough for all our messages, + * overflow doesn't happen because this code checks! + */ + size_t i; + char msg[128]; + + for (i=0; i<(sizeof msg)-1 && *message != '\0'; ++i) + { + if (*message == '@') + { + int parameter = -1; + switch (*++message) + { + case '1': + parameter = 0; + break; + + case '2': + parameter = 1; + break; + + case '\0': + continue; /* To break out of the for loop above. */ + + default: + break; + } + + if (parameter >= 0 && parameter < PNG_WARNING_PARAMETER_COUNT) + { + /* Append this parameter */ + png_const_charp parm = p[parameter]; + png_const_charp pend = p[parameter] + (sizeof p[parameter]); + + /* No need to copy the trailing '\0' here, but there is no guarantee + * that parm[] has been initialized, so there is no guarantee of a + * trailing '\0': + */ + for (; i<(sizeof msg)-1 && parm != '\0' && parm < pend; ++i) + msg[i] = *parm++; + + ++message; + continue; + } + + /* else not a parameter and there is a character after the @ sign; just + * copy that. + */ + } + + /* At this point *message can't be '\0', even in the bad parameter case + * above where there is a lone '@' at the end of the message string. + */ + msg[i] = *message++; + } + + /* i is always less than (sizeof msg), so: */ + msg[i] = '\0'; + + /* And this is the formatted message: */ + png_warning(png_ptr, msg); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + + iin = 0; + while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') + buffer[iout++] = error_message[iin++]; + + /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ + buffer[iout] = '\0'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_ERROR_TEXT_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_FUNCTION(void, +png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + png_memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + return NULL; + + png_ptr->longjmp_fn = longjmp_fn; + return &png_ptr->longjmp_buffer; +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + /* Check on NULL only added in 1.5.4 */ + if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message ? error_message : + "undefined"); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf tmp_jmpbuf; + png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(tmp_jmpbuf, val); + } + +# else + png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(png_ptr) /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#else + PNG_UNUSED(warning_fn) +#endif +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | + PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngget.c b/src/depend/libs/libpng/pngget.c new file mode 100644 index 00000000..b5e5798c --- /dev/null +++ b/src/depend/libs/libpng/pngget.c @@ -0,0 +1,1032 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->y_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && + info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit != 0) + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, + png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +png_const_bytep PNGAPI +png_get_signature(png_const_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + if (white_x != NULL) + *white_x = info_ptr->x_white; + if (white_y != NULL) + *white_y = info_ptr->y_white; + if (red_x != NULL) + *red_x = info_ptr->x_red; + if (red_y != NULL) + *red_y = info_ptr->y_red; + if (green_x != NULL) + *green_x = info_ptr->x_green; + if (green_y != NULL) + *green_y = info_ptr->y_green; + if (blue_x != NULL) + *blue_x = info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +png_uint_32 PNGFAPI +png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + *file_gamma = info_ptr->gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma) +{ + png_fixed_point igamma; + png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma); + + if (ok) + *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA"); + + return ok; +} + +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr, + int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING_ARITHMETIC */ +# endif /* FIXED_POINT */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + + return(0); +} +#endif /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + + return (retval); +} +#endif /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +png_uint_32 PNGAPI +png_get_text(png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" : + (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + + if (num_text != NULL) + *num_text = 0; + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return info_ptr->unknown_chunks_num; + } + + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_const_structp png_ptr) +{ + return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->zbuf_size : 0L); +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_structp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structp png_ptr) +{ + return ((png_ptr->chunk_name[0] << 24) + + (png_ptr->chunk_name[1] << 16) + + (png_ptr->chunk_name[2] << 8) + + (png_ptr->chunk_name[3])); +} + +png_const_bytep PNGAPI +png_get_io_chunk_name (png_structp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pnginfo.h b/src/depend/libs/libpng/pnginfo.h new file mode 100644 index 00000000..a33bfab0 --- /dev/null +++ b/src/depend/libs/libpng/pnginfo.h @@ -0,0 +1,269 @@ + +/* pnginfo.h - header file for PNG reference library + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, using png_set_*() functions, then + * call png_write_info(). + * + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. In libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + png_fixed_point gamma; +#endif + +#ifdef PNG_sRGB_SUPPORTED + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans_alpha; /* alpha values for paletted image */ + png_color_16 trans_color; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ + png_fixed_point x_white; + png_fixed_point y_white; + png_fixed_point x_red; + png_fixed_point y_red; + png_fixed_point x_green; + png_fixed_point y_green; + png_fixed_point x_blue; + png_fixed_point y_blue; +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + int unknown_chunks_num; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) + non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/src/depend/libs/libpng/pnglibconf.h b/src/depend/libs/libpng/pnglibconf.h new file mode 100644 index 00000000..827d17e5 --- /dev/null +++ b/src/depend/libs/libpng/pnglibconf.h @@ -0,0 +1,187 @@ + +/* libpng STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.5.4 - last changed on June 22, 2011 */ + +/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Derived from: scripts/pnglibconf.dfa */ +/* If you edit this file by hand you must obey the rules expressed in */ +/* pnglibconf.dfa with respect to the dependencies between the following */ +/* symbols. It is much better to generate a new file using */ +/* scripts/libpngconf.mak */ + +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* settings */ +#define PNG_API_RULE 0 +#define PNG_CALLOC_SUPPORTED +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_sCAL_PRECISION 5 +#define PNG_USER_CHUNK_CACHE_MAX 0 +#define PNG_USER_CHUNK_MALLOC_MAX 0 +#define PNG_USER_HEIGHT_MAX 1000000L +#define PNG_USER_WIDTH_MAX 1000000L +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +/* end of settings */ +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGN_MEMORY_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_cHRM_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +#endif /* PNGLCONF_H */ diff --git a/src/depend/libs/libpng/pngmem.c b/src/depend/libs/libpng/pngmem.c new file mode 100644 index 00000000..ea606d6a --- /dev/null +++ b/src/depend/libs/libpng/pngmem.c @@ -0,0 +1,667 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (png_get_copyright(NULL)); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + + else +# endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } + +# endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + + else +# endif + + if (size != (size_t)size) + ret = NULL; + + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i, mem_level, window_bits; + png_byte huge * hptr; + int window_bits + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + window_bits = + png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ? + png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits; + + if (window_bits > 14) + num_blocks = (int)(1 << (window_bits - 14)); + + else + num_blocks = 1; + + mem_level = + png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ? + png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level; + + if (mem_level >= 7) + num_blocks += (int)(1 << (mem_level - 7)); + + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */ + + else + png_warning(png_ptr, "Out Of Memory"); +# endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +# endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */ + + else + png_warning(png_ptr, "Out Of memory"); +# endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); /* Note "O" and "M" */ + + else + png_warning(png_ptr, "Out of Memory"); +# endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + + else + ret = farmalloc(size); + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */ + + else + png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */ + } +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + farfree(ptr); +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); + } +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +# endif + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +# endif /* PNG_USER_MEM_SUPPORTED */ +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); + +# else + free(struct_ptr); + +# endif +# endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + + else +# endif + return NULL; + } +# endif + + /* Check for overflow */ +# if defined(__TURBOC__) && !defined(__FLAT__) + + if (size != (unsigned long)size) + ret = NULL; + + else + ret = farmalloc(size); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + + else + ret = halloc(size, 1); + +# else + if (size != (size_t)size) + ret = NULL; + + else + ret = malloc((size_t)size); +# endif +# endif + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); + +# else + free(ptr); + +# endif +# endif +} +#endif /* Not Borland DOS special memory handler */ + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} + + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngpread.c b/src/depend/libs/libpng/pngpread.c new file mode 100644 index 00000000..a50292a7 --- /dev/null +++ b/src/depend/libs/libpng/pngpread.c @@ -0,0 +1,1856 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.5.2 [March 31, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGCBAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ + PNG_IDAT; + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has someplace to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream (a stream with a missing end code) can still + * be handled, otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and therefore + * change the current behavior (see comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5). + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); +#endif + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place tEXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place zTXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep)text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place iTXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_size_t)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngpriv.h b/src/depend/libs/libpng/pngpriv.h new file mode 100644 index 00000000..5b4d2127 --- /dev/null +++ b/src/depend/libs/libpng/pngpriv.h @@ -0,0 +1,1358 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* Feature Test Macros. The following are defined here to ensure that correctly + * implemented libraries reveal the APIs libpng needs to build and hide those + * that are not needed and potentially damaging to the compilation. + * + * Feature Test Macros must be defined before any system header is included (see + * POSIX 1003.1 2.8.2 "POSIX Symbols." + * + * These macros only have an effect if the operating system supports either + * POSIX 1003.1 or C99, or both. On other operating systems (particularly + * Windows/Visual Studio) there is no effect; the OS specific tests below are + * still required (as of 2011-05-02.) + */ +#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ + +/* This is required for the definition of abort(), used as a last ditch + * error handler when all else fails. + */ +#include + +#define PNGLIB_BUILD +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif +#include "png.h" +#include "pnginfo.h" +#include "pngstruct.h" + +/* This is used for 16 bit gamma tables - only the top level pointers are const, + * this could be changed: + */ +typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + +/* Added at libpng-1.2.9 */ +/* Moved to pngpriv.h at libpng-1.5.0 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. We may need it here to get the correct configuration on things + * like limits. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +#ifndef PNG_UNUSED +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). Note that if you replace + * it with something other than whitespace, you must include the terminating + * semicolon. + */ +# define PNG_UNUSED(param) (void)param; +#endif + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* PNG_STATIC is used to mark internal file scope functions if they need to be + * accessed for implementation tests (see the code in tests/?*). + */ +#ifndef PNG_STATIC +# define PNG_STATIC static +#endif + +/* If warnings or errors are turned off the code is disabled or redirected here. + * From 1.5.4 functions have been added to allow very limited formatting of + * error and warning messages - this code will also be disabled here. + */ +#ifdef PNG_WARNINGS_SUPPORTED +# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +# define png_warning_parameter(p,number,string) ((void)0) +# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) +# define png_warning_parameter_signed(p,number,format,value) ((void)0) +# define png_formatted_warning(pp,p,message) ((void)(pp)) +# define PNG_WARNING_PARAMETERS(p) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +#ifndef PNG_EXTERN +/* The functions exported by PNG_EXTERN are internal functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it + * is possible to have run-time registry of chunk-handling functions, + * some of these might be made available again. +# define PNG_EXTERN extern + */ +# define PNG_EXTERN +#endif + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include + +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +#endif + +/* Moved here around 1.5.0beta36 from pngconf.h */ +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* Memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# endif +#endif +/* End of memory model/platform independent support */ +/* End of 1.5.0beta36 move from pngconf.h */ + +/* CONSTANTS and UTILITY MACROS + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. Three of these + * are defined in png.h because they need to be visible to applications + * that call png_set_unknown_chunk(). + */ +/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04 +/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 +#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ +#define PNG_BACKGROUND_EXPAND 0x0100 +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000L /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000L /* Added to libpng-1.5.4 */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L + /* 0x200000L unused */ + /* 0x400000L unused */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ +#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000L /* 5 lines added */ +#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000L /* to libpng-1.5.4 */ +#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000L +#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000L +#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000L + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximuum for png_size_t. The value can be overriden in a library build + * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably + * lower value (e.g. 255 works). A lower value may help memory usage (slightly) + * and may even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#else +PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, + png_const_charp text)); +#endif +#endif + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro wherever it's + * needed. + */ +#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} +#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +/* Gamma values (new at libpng-1.5.4): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +/* Check the user version string for compatibility, returns false if the version + * numbers aren't compatible. + */ +PNG_EXTERN int png_user_version_check(png_structp png_ptr, + png_const_charp user_png_ver); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), + PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2, + PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)), + PNG_ALLOCATED); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items, + uInt size)),PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr)); +# endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Read and check the PNG file signature */ +PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_READ_COMPRESSED_TEXT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, png_size_t prefix_length, + png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, + png_const_bytep ptr, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, + png_const_colorp palette, png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +# endif +# ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +# endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, + png_const_color_8p sbit, int color_type)); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +# endif +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_const_charp name, int compression_type, + png_const_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_const_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_const_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, + png_const_uint_16p hist, int num_hist)); +#endif + +/* Chunks that have keywords */ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_const_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text)); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_const_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_const_charp width, png_const_charp height)); +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_const_bytep prev_row, + int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* Initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info, + png_bytep row, int at_start)); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep palette_lookup, + png_const_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans, + int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_const_bytep chunk_name)); + +/* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +# ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_CHECK_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +/* Currently only used by png_check_cHRM_fixed */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif + +/* Added at libpng version 1.4.0 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr, png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite + * the end. Always leaves the buffer nul terminated. Never errors out (and + * there is no error code.) + */ +PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string); + +/* Various internal functions to handle formatted warning messages, currently + * only implemented for warnings. + */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. This utility only + * does unsigned values. + */ +PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end, + int format, png_alloc_size_t number); + +/* Convenience macro that takes an array: */ +#define PNG_FORMAT_NUMBER(buffer,format,number) \ + png_format_number(buffer, buffer + (sizeof buffer), format, number) + +/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ +#define PNG_NUMBER_BUFFER_SIZE 24 + +/* These are the integer formats currently supported, the name is formed from + * the standard printf(3) format string. + */ +#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ +#define PNG_NUMBER_FORMAT_02u 2 +#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ +#define PNG_NUMBER_FORMAT_02d 2 +#define PNG_NUMBER_FORMAT_x 3 +#define PNG_NUMBER_FORMAT_02x 4 +#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* New defines and members adding in libpng-1.5.4 */ +# define PNG_WARNING_PARAMETER_SIZE 32 +# define PNG_WARNING_PARAMETER_COUNT 8 + +/* An l-value of this type has to be passed to the APIs below to cache the + * values of the parameters to a formatted warning message. + */ +typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ + PNG_WARNING_PARAMETER_SIZE]; + +PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string); + /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, + * including the trailing '\0'. + */ +PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p, + int number, int format, png_alloc_size_t value); + /* Use png_alloc_size_t because it is an unsigned type as big as any we + * need to output. Use the following for a signed value. + */ +PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p, + int number, int format, png_int_32 value); + +PNG_EXTERN void png_formatted_warning(png_structp png_ptr, + png_warning_parameters p, png_const_charp message); + /* 'message' follows the X/Open approach of using @1, @2 to insert + * parameters previously supplied using the above functions. Errors in + * specifying the paramters will simple result in garbage substitutions. + */ +#endif + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_READ_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumpitions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, + png_size_t size, double fp, unsigned int precision)); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp)); +#endif /* FIXED_POINT */ +#endif /* READ_sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numb1.ers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ +#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ +#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ + +/* These three values don't affect the parser. They are set but not used. + */ +#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ +#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ +#define PNG_FP_NONZERO 256 /* A non-zero value */ +#define PNG_FP_STICKY 448 /* The above three flags */ + +/* This is available for the caller to store in 'state' if required. Do not + * call the parser after setting it (the parser sometimes clears it.) + */ +#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* Tests on the sticky non-zero and negative flags. To pass these checks + * the state must also indicate that the whole number is valid - this is + * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this + * is equivalent to PNG_FP_OK above.) + */ +#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) + /* NZ_MASK: the string is valid and a non-zero negative value */ +#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) + /* Z MASK: the string is valid and a non-zero value. */ + /* PNG_FP_SAW_DIGIT: the string is valid. */ +#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) +#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) +#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) + +/* The actual parser. This can be called repeatedly, it updates + * the index into the string and the state variable (which must + * be initialzed to 0). It returns a result code, as above. There + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string, + png_size_t size, int *statep, png_size_tp whereami)); + +/* This is the same but it checks a complete string and returns true + * only if it just contains a floating point number. As of 1.5.4 this + * function also returns the state at the end of parsing the number if + * it was valid (otherwise it returns 0.) This can be used for testing + * for negative or zero values using the sticky flag. + */ +PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, + png_size_t size)); +#endif /* pCAL || sCAL */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, + png_int_32 multiplied_by, png_int_32 divided_by)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* Same deal, but issue a warning on overflow and return 0. */ +PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, + png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value, + * there are no warnings. + */ +PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a)); + +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. + */ +PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, + png_fixed_point b)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * correct bit value - 0..255 or 0..65535 as required. + */ +PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr, + unsigned int value, png_fixed_point gamma_value)); +PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value)); +PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value, + png_fixed_point gamma_value)); +PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, + png_fixed_point gamma_value)); +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + int bit_depth)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNGPRIV_H */ diff --git a/src/depend/libs/libpng/pngread.c b/src/depend/libs/libpng/pngread.c new file mode 100644 index 00000000..be3df476 --- /dev/null +++ b/src/depend/libs/libpng/pngread.c @@ -0,0 +1,1454 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + volatile int png_cleanup_needed = 0; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf tmp_jmpbuf; +#endif +#endif + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + malloc_fn, mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; + +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + +# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ +#endif + PNG_ABORT(); +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + /* Call the general version checker (shared with read and write code): */ + if (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; + + if (!png_cleanup_needed) + { + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); + + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!png_cleanup_needed) + { + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: + break; /* Do nothing */ + + case Z_MEM_ERROR: + png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; + break; + + case Z_STREAM_ERROR: + png_warning(png_ptr, "zlib stream error"); + png_cleanup_needed = 1; + break; + + case Z_VERSION_ERROR: + png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; + break; + + default: png_warning(png_ptr, "Unknown zlib error"); + png_cleanup_needed = 1; + } + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + + return (png_ptr); +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, length); + + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call;" + " row buffer not reallocated"); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_read_transform_info(png_ptr, info_ptr); +#else + PNG_UNUSED(info_ptr) +#endif +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_start_read_image() call;" + " row buffer not reallocated"); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ + PNG_IDAT; +#ifdef PNG_READ_INTERLACING_SUPPORTED + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif + int ret; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_benign_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); +#endif + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, png_pass_dsp_mask[png_ptr->pass]); + + if (row != NULL) + png_combine_row(png_ptr, row, png_pass_mask[png_ptr->pass]); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#ifdef PNG_TEXT_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#ifdef PNG_READ_TEXT_SUPPORTED + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; +#endif + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_free(png_ptr, png_ptr->gamma_table); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif + + inflateEnd(&png_ptr->zstream); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + warning_fn = png_ptr->warning_fn; +#endif + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#endif + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + /* Tell libpng to strip 16-bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_SCALE_16) + { + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ + png_set_scale_16(png_ptr); + } +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* If both SCALE and STRIP are required pngrtran will effectively cancel the + * latter by doing SCALE first. This is ok and allows apps not to check for + * which is supported to get the right answer. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(png_ptr); +#endif + +/* Added at libpng-1.5.4 */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (transforms & PNG_TRANSFORM_EXPAND_16) + png_set_expand_16(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* We use png_read_image and rely on that for interlace handling, but we also + * call png_read_update_info therefore must turn on interlace handling now: + */ + (void)png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngrio.c b/src/depend/libs/libpng/pngrio.c new file mode 100644 index 00000000..e9c381c5 --- /dev/null +++ b/src/depend/libs/libpng/pngrio.c @@ -0,0 +1,176 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +# ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +# else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, read, io_ptr); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + + if (err != read) + break; + + else + check += err; + + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +# endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * + * png_ptr - pointer to a png input data structure + * + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngrtran.c b/src/depend/libs/libpng/pngrtran.c new file mode 100644 index 00000000..4e0401aa --- /dev/null +++ b/src/depend/libs/libpng/pngrtran.c @@ -0,0 +1,4953 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + if (png_ptr == NULL) + return; + + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + if (need_expand) + png_ptr->transformations |= PNG_BACKGROUND_EXPAND; + else + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the + * one that pngrtran does first (scale) happens. This is necessary to allow the + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +void PNGAPI +png_set_scale_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_scale_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SCALE_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +/* Chop 16-bit depth files to 8-bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# endif + if (is_screen) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma > 0 && output_gamma < 128) + output_gamma *= PNG_FP_1; + + /* This preserves -1 and -2 exactly: */ + output_gamma = floor(output_gamma + .5); + + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) + png_fixed_error(png_ptr, "gamma value"); + + return (png_fixed_point)output_gamma; +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +void PNGFAPI +png_set_alpha_mode_fixed(png_structp png_ptr, int mode, + png_fixed_point output_gamma) +{ + int compose = 0; + png_fixed_point file_gamma; + + png_debug(1, "in png_set_alpha_mode"); + + if (png_ptr == NULL) + return; + + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); + + /* Validate the value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out users of this API + * who use the inverse of the gamma value accidentally! Since some of these + * values are reasonable this may have to be changed. + */ + if (output_gamma < 70000 || output_gamma > 300000) + png_error(png_ptr, "output gamma out of expected range"); + + /* The default file gamma is the inverse of the output gamma; the output + * gamma may be changed below so get the file value first: + */ + file_gamma = png_reciprocal(output_gamma); + + /* There are really 8 possibilities here, composed of any combination + * of: + * + * premultiply the color channels + * do not encode non-opaque pixels + * encode the alpha as well as the color channels + * + * The differences disappear if the input/output ('screen') gamma is 1.0, + * because then the encoding is a no-op and there is only the choice of + * premultiplying the color channels or not. + * + * png_set_alpha_mode and png_set_background interact because both use + * png_compose to do the work. Calling both is only useful when + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. + */ + switch (mode) + { + case PNG_ALPHA_PNG: /* default: png standard */ + /* No compose, but it may be set by png_set_background! */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + /* The output is linear: */ + output_gamma = PNG_FP_1; + break; + + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; + /* output_gamma records the encoding of opaque pixels! */ + break; + + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ + compose = 1; + png_ptr->transformations |= PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + default: + png_error(png_ptr, "invalid alpha mode"); + } + + /* Only set the default gamma if the file gamma has not been set (this has + * the side effect that the gamma in a second call to png_set_alpha_mode will + * be ignored.) + */ + if (png_ptr->gamma == 0) + png_ptr->gamma = file_gamma; + + /* But always set the output gamma: */ + png_ptr->screen_gamma = output_gamma; + + /* Finally, if pre-multiplying, set the background fields to achieve the + * desired result. + */ + if (compose) + { + /* And obtain alpha pre-multiplication by composing on black: */ + png_memset(&png_ptr->background, 0, sizeof png_ptr->background); + png_ptr->background_gamma = png_ptr->gamma; /* just in case */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + + if (png_ptr->transformations & PNG_COMPOSE) + png_error(png_ptr, + "conflicting calls to set alpha mode and background"); + + png_ptr->transformations |= PNG_COMPOSE; + } + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) +{ + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); +} +# endif +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Dither file to 8-bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + + if (t == NULL) + break; + + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +void PNGFAPI +png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, + png_fixed_point file_gamma) +{ + png_debug(1, "in png_set_gamma_fixed"); + + if (png_ptr == NULL) + return; + + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + +#if PNG_LIBPNG_VER >= 10600 + /* Checking the gamma values for being >0 was added in 1.5.4 along with the + * premultiplied alpha support; this actually hides an undocumented feature + * of the previous implementation which allowed gamma processing to be + * disabled in background handling. There is no evidence (so far) that this + * was being used; however, png_set_background itself accepted and must still + * accept '0' for the gamma value it takes, because it isn't always used. + * + * Since this is an API change (albeit a very minor one that removes an + * undocumented API feature) it will not be made until libpng-1.6.0. + */ + if (file_gamma <= 0) + png_error(png_ptr, "invalid file gamma in png_set_gamma"); + + if (scrn_gamma <= 0) + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); +#endif + + /* Set the gamma values unconditionally - this overrides the value in the PNG + * file if a gAMA chunk was present. png_set_alpha_mode provides a + * different, easier, way to default the file gamma. + */ + png_ptr->gamma = file_gamma; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise + * it may not work correctly.) + */ +void PNGAPI +png_set_expand_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + if (png_ptr != NULL) + { + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + if (png_ptr == NULL) + return; + + switch(error_action) + { + case 1: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) + { + png_uint_16 red_int, green_int; + + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); + } + + else + { + if (red >= 0 && green >= 0) + png_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); + + /* Use the defaults, from the cHRM chunk if set, else the built in Rec + * 709 values (which correspond to sRGB, so we don't have to worry + * about the sRGB chunk!) + */ + if (png_ptr->rgb_to_gray_red_coeff == 0 && + png_ptr->rgb_to_gray_green_coeff == 0 && + png_ptr->rgb_to_gray_blue_coeff == 0) + { + png_ptr->rgb_to_gray_red_coeff = 6968; /* .212671 * 32768 + .5 */ + png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */ + png_ptr->rgb_to_gray_blue_coeff = 2366; + } + } + } +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + if (png_ptr == NULL) + return; + + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +/* In the case of gamma transformations only do transformations on images where + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it + * slows things down slightly, and also needlessly introduces small errors. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ + +/*For the moment 'png_init_palette_transformations' and + * 'png_init_rgb_transformations' only do some flag canceling optimizations. + * The intent is that these two routines should have palette or rgb operations + * extracted from 'png_init_read_transformations'. + */ +static void /* PRIVATE */ +png_init_palette_transformations(png_structp png_ptr) +{ + /* Called to handle the (input) palette case. In png_do_read_transformations + * the first step is to expand the palette if requested, so this code must + * take care to only make changes that are invariant with respect to the + * palette expansion, or only do them if there is no expansion. + * + * STRIP_ALPHA has already been handled in the caller (by setting num_trans + * to 0.) + */ + int input_has_alpha = 0; + int input_has_transparency = 0; + + if (png_ptr->num_trans > 0) + { + int i; + + /* Ignore if all the entries are opaque (unlikely!) */ + for (i=0; inum_trans; ++i) + if (png_ptr->trans_alpha[i] == 255) + continue; + else if (png_ptr->trans_alpha[i] == 0) + input_has_transparency = 1; + else + input_has_alpha = 1; + } + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; + + for (i=0; itrans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +static void /* PRIVATE */ +png_init_rgb_transformations(png_structp png_ptr) +{ + /* Added to libpng-1.5.4: check the color type to determine whether there + * is any alpha or transparency in the image and simply cancel the + * background and alpha mode stuff if there isn't. + */ + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; + int input_has_transparency = png_ptr->num_trans > 0; + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; +# endif + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND) && + !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + /* i.e., GRAY or GRAY_ALPHA */ + { + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0xff; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x55; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x11; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + default: + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + /* This internal function is called from png_read_start_row in pngrutil.c + * and it is called before the 'rowbytes' calculation is done, so the code + * in here can change or update the transformations flags. + * + * First do updates that do not depend on the details of the PNG image data + * being processed. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds + * png_set_alpha_mode and this is another source for a default file gamma so + * the test needs to be performed later - here. In addition prior to 1.5.4 + * the tests were repeated for the PALETTE color type here - this is no + * longer necessary (and doesn't seem to have been necessary before.) + */ + { + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + + if (png_ptr->gamma != 0) /* has been set */ + { + if (png_ptr->screen_gamma != 0) /* screen set too */ + gamma_correction = png_gamma_threshold(png_ptr->gamma, + png_ptr->screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma); + } + + else if (png_ptr->screen_gamma != 0) + /* The converse - assume the file matches the screen, note that this + * perhaps undesireable default can (from 1.5.4) be changed by calling + * png_set_alpha_mode (even if the alpha handling mode isn't required + * or isn't changed from the default.) + */ + png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma); + + else /* neither are set */ + /* Just in case the following prevents any processing - file and screen + * are both assumed to be linear and there is no way to introduce a + * third gamma value other than png_set_background with 'UNIQUE', and, + * prior to 1.5.4 + */ + png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1; + + /* Now turn the gamma transformation on or off as appropriate. Notice + * that PNG_GAMMA just refers to the file->screen correction. Alpha + * composition may independently cause gamma correction because it needs + * linear data (e.g. if the file has a gAMA chunk but the screen gamma + * hasn't been specified.) In any case this flag may get turned off in + * the code immediately below if the transform can be handled outside the + * row loop. + */ + if (gamma_correction) + png_ptr->transformations |= PNG_GAMMA; + + else + png_ptr->transformations &= ~PNG_GAMMA; + } +#endif + + /* Certain transformations have the effect of preventing other + * transformations that happen afterward in png_do_read_transformations, + * resolve the interdependencies here. From the code of + * png_do_read_transformations the order is: + * + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) + * 2) PNG_STRIP_ALPHA (if no compose) + * 3) PNG_RGB_TO_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY + * 5) PNG_COMPOSE + * 6) PNG_GAMMA + * 7) PNG_STRIP_ALPHA (if compose) + * 8) PNG_ENCODE_ALPHA + * 9) PNG_SCALE_16_TO_8 + * 10) PNG_16_TO_8 + * 11) PNG_QUANTIZE (converts to palette) + * 12) PNG_EXPAND_16 + * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY + * 14) PNG_INVERT_MONO + * 15) PNG_SHIFT + * 16) PNG_PACK + * 17) PNG_BGR + * 18) PNG_PACKSWAP + * 19) PNG_FILLER (includes PNG_ADD_ALPHA) + * 20) PNG_INVERT_ALPHA + * 21) PNG_SWAP_ALPHA + * 22) PNG_SWAP_BYTES + * 23) PNG_USER_TRANSFORM [must be last] + */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE)) + { + /* Stripping the alpha channel happens immediately after the 'expand' + * transformations, before all other transformation, so it cancels out + * the alpha handling. It has the side effect negating the effect of + * PNG_EXPAND_tRNS too: + */ + png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | + PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen + * so transparency information would remain just so long as it wasn't + * expanded. This produces unexpected API changes if the set of things + * that do PNG_EXPAND_tRNS changes (perfectly possible given the + * documentation - which says ask for what you want, accept what you + * get.) This makes the behavior consistent from 1.5.4: + */ + png_ptr->num_trans = 0; + } +#endif /* STRIP_ALPHA supported, no COMPOSE */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA + * settings will have no effect. + */ + if (!png_gamma_significant(png_ptr->screen_gamma)) + { + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && \ + defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* Detect gray background and attempt to enable optimization for + * gray --> RGB case. + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + * + * TODO: this code needs to be revised to avoid the complexity and + * interdependencies. The color type of the background should be recorded in + * png_set_background, along with the bit depth, then the code has a record + * of exactly what color space the background is currently in. + */ + if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) + { + /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if + * the file was greyscale the background value is gray. + */ + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + else if (png_ptr->transformations & PNG_COMPOSE) + { + /* PNG_COMPOSE: png_set_background was called with need_expand false, + * so the color is in the color space of the output or png_set_alpha_mode + * was called and the color is black. Ignore RGB_TO_GRAY because that + * happens before GRAY_TO_RGB. + */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if (png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } + } + } +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */ + + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations + * can be performed directly on the palette, and some (such as rgb to gray) + * can be optimized inside the palette. This is particularly true of the + * composite (background and alpha) stuff, which can be pretty much all done + * in the palette even if the result is expanded to RGB or gray afterward. + * + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and + * earlier and the palette stuff is actually handled on the first row. This + * leads to the reported bug that the palette returned by png_get_PLTE is not + * updated. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); + + else + png_init_rgb_transformations(png_ptr); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_EXPAND_16_SUPPORTED) + if ((png_ptr->transformations & PNG_EXPAND_16) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth != 16) + { + /* TODO: fix this. Because the expand_16 operation is after the compose + * handling the background color must be 8, not 16, bits deep, but the + * application will supply a 16-bit value so reduce it here. + * + * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at + * present, so that case is ok (until do_expand_16 is moved.) + * + * NOTE: this discards the low 16 bits of the user supplied background + * color, but until expand_16 works properly there is no choice! + */ +# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) + CHOP(png_ptr->background.red); + CHOP(png_ptr->background.green); + CHOP(png_ptr->background.blue); + CHOP(png_ptr->background.gray); +# undef CHOP + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ + + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the + * background support (see the comments in scripts/pnglibconf.dfa), this + * allows pre-multiplication of the alpha channel to be implemented as + * compositing on black. This is probably sub-optimal and has been done in + * 1.5.4 betas simply to enable external critique and testing (i.e. to + * implement the new API quickly, without lots of internal changes.) + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Includes ALPHA_MODE */ + png_ptr->background_1 = png_ptr->background; +# endif + + /* This needs to change - in the palette image case a whole set of tables are + * built when it would be quicker to just calculate the correct value for + * each palette entry directly. Also, the test is too tricky - why check + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction + * the gamma tables will not be built even if composition is required on a + * gamma encoded value. + * + * In 1.5.4 this is addressed below by an additional check on the individual + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the + * tables. + */ + if ((png_ptr->transformations & PNG_GAMMA) + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) + && (png_gamma_significant(png_ptr->gamma) || + png_gamma_significant(png_ptr->screen_gamma))) + || ((png_ptr->transformations & PNG_COMPOSE) + && (png_gamma_significant(png_ptr->gamma) + || png_gamma_significant(png_ptr->screen_gamma) +# ifdef PNG_READ_BACKGROUND_SUPPORTED + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE + && png_gamma_significant(png_ptr->background_gamma)) +# endif + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) + && png_gamma_significant(png_ptr->screen_gamma)) + ) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_COMPOSE) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* We don't get to here unless there is a tRNS chunk with non-opaque + * entries - see the checking code at the start of this function. + */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + png_fixed_point g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + default: + g = PNG_FP_1; /* back_1 */ + gs = PNG_FP_1; /* back */ + break; + } + + if (png_gamma_significant(gs)) + { + back.red = png_gamma_8bit_correct(png_ptr->background.red, + gs); + back.green = png_gamma_8bit_correct(png_ptr->background.green, + gs); + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, + gs); + } + + else + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + + if (png_gamma_significant(g)) + { + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, + g); + back_1.green = png_gamma_8bit_correct( + png_ptr->background.green, g); + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, + g); + } + + else + { + back_1.red = (png_byte)png_ptr->background.red; + back_1.green = (png_byte)png_ptr->background.green; + back_1.blue = (png_byte)png_ptr->background.blue; + } + } + + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && + png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + + /* Prevent the transformations being done again. + * + * NOTE: this is highly dubious; it zaps the transformations in + * place. This seems inconsistent with the general treatment of the + * transformations elsewhere. + */ + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + } /* color_type == PNG_COLOR_TYPE_PALETTE */ + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + png_fixed_point g = PNG_FP_1; + png_fixed_point gs = PNG_FP_1; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = png_ptr->screen_gamma; + /* gs = PNG_FP_1; */ + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + png_error(png_ptr, "invalid background gamma type"); + } + + png_ptr->background_1.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, g); + + png_ptr->background.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, gs); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = png_gamma_correct(png_ptr, + png_ptr->background.red, g); + + png_ptr->background_1.green = png_gamma_correct(png_ptr, + png_ptr->background.green, g); + + png_ptr->background_1.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, g); + + png_ptr->background.red = png_gamma_correct(png_ptr, + png_ptr->background.red, gs); + + png_ptr->background.green = png_gamma_correct(png_ptr, + png_ptr->background.green, gs); + + png_ptr->background.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, gs); + } + + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } /* color_type != PNG_COLOR_TYPE_PALETTE */ + }/* png_ptr->transformations & PNG_BACKGROUND */ + + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + /*NOTE: there are other transformations that should probably be in here + * too. + */ + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation (see the hanging else 4 lines above) */ + if ((png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + png_ptr->transformations &= ~PNG_COMPOSE; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + + if (sg < 0 || sg > 8) + sg = 0; + + if (sb < 0 || sb > 8) + sb = 0; + + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* This check must match what actually happens in + * png_do_expand_palette; if it ever checks the tRNS chunk to see if + * it is all opaque we must do the same (at present it does not.) + */ + if (png_ptr->num_trans > 0) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* The following is almost certainly wrong unless the background value is in + * the screen space! + */ + if (png_ptr->transformations & PNG_COMPOSE) + info_ptr->background = png_ptr->background; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), + * however it seems that the code in png_init_read_transformations, which has + * been called before this from png_read_update_info->png_read_start_row + * sometimes does the gamma transform and cancels the flag. + */ + info_ptr->gamma = png_ptr->gamma; +#endif + + if (info_ptr->bit_depth == 16) + { +# ifdef PNG_READ_16BIT_SUPPORTED +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# else + /* No 16 bit support: force chopping 16-bit input down to 8, in this case + * the app program can chose if both APIs are available by setting the + * correct scaling to use. + */ +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* For compatibility with previous versions use the strip method by + * default. This code works because if PNG_SCALE_16_TO_8 is already + * set the code below will do that in preference to the chop. + */ + png_ptr->transformations |= PNG_16_TO_8; + info_ptr->bit_depth = 8; +# else + +# if PNG_READ_SCALE_16_TO_8_SUPPORTED + png_ptr->transformations |= PNG_SCALE_16_TO_8; + info_ptr->bit_depth = 8; +# else + + CONFIGURATION ERROR: you must enable at least one 16 to 8 method +# endif +# endif +#endif /* !READ_16BIT_SUPPORTED */ + } + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + info_ptr->bit_depth = 16; + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + } +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + + /* Adding in 1.5.4: cache the above value in png_struct so that we can later + * check in png_rowbytes that the user buffer won't get overwritten. Note + * that the field is not always set - if png_read_update_info isn't called + * the application has to either not do any transforms or get the calculation + * right itself. + */ + png_ptr->info_rowbytes = info_ptr->rowbytes; + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this + * error is incredibly rare and incredibly easy to debug without this + * information. + */ + png_error(png_ptr, "NULL row buffer"); + } + + /* The following is debugging; prior to 1.5.4 the code was never compiled in; + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for + * selected new APIs to ensure that there is no API change. + */ + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && + !(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + /* Application has failed to call either png_read_start_image() or + * png_read_update_info() after setting transforms that expand pixels. + * This check added to libpng-1.2.19 (but not enabled until 1.5.4). + */ + png_error(png_ptr, "Uninitialized row"); + } + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + if (png_ptr->transformations & PNG_COMPOSE) + png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + !((png_ptr->transformations & PNG_COMPOSE) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && + (png_ptr->row_info.color_type & PNG_COLOR_MASK_ALPHA)) + png_do_encode_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* There is no harm in doing both of these because only one has any effect, + * by putting the 'scale' option first if the app asks for scale (either by + * calling the API or in a TRANSFORM flag) this is what happens. + */ + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (png_ptr->row_info.rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + /* Do the expansion now, after all the arithmetic has been done. Notice + * that previous transformations can handle the PNG_EXPAND_16 flag if this + * is efficient (particularly true in the case of gamma correction, where + * better accuracy results faster!) + */ + if (png_ptr->transformations & PNG_EXPAND_16) + png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /*NOTE: moved here in 1.5.4 (from much later in this list.) */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, + png_const_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + + if ( + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + default: + break; + + case 2: + { + png_bytep bp; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale rows of bit depth 16 down to 8 accurately */ +void /* PRIVATE */ +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_scale_16_to_8"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destinaton */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + /* The input is an array of 16 bit components, these must be scaled to + * 8 bits each. For a 16 bit value V the required value (from the PNG + * specification) is: + * + * (V * 255) / 65535 + * + * This reduces to round(V / 257), or floor((V + 128.5)/257) + * + * Represent V as the two byte value vhi.vlo. Make a guess that the + * result is the top byte of V, vhi, then the correction to this value + * is: + * + * error = floor(((V-vhi.vhi) + 128.5) / 257) + * = floor(((vlo-vhi) + 128.5) / 257) + * + * This can be approximated using integer arithmetic (and a signed + * shift): + * + * error = (vlo-vhi+128) >> 8; + * + * The approximate differs from the exact answer only when (vlo-vhi) is + * 128; it then gives a correction of +1 when the exact correction is + * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * input values) is: + * + * error = (vlo-vhi+128)*65535 >> 24; + * + * An alternative arithmetic calculation which also gives no errors is: + * + * (V * 255 + 32895) >> 16 + */ + + png_int_32 tmp = *sp++; /* must be signed! */ + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; + *dp++ = (png_byte)tmp; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +void /* PRIVATE */ +/* Simply discard the low byte. This was the default behavior prior + * to libpng-1.5.4. + */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destinaton */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + *dp++ = *sp; + sp += 2; /* skip low byte */ + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } +#endif + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + + else + { + /* This changes the data from G to XG */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from GG to XXGG */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from RGB to XRGB */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } +#endif + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GG to RRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This changes GA to RGBA */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GGAA to RRGGBBAA */ + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * (THIS LINK IS DEAD June 2008) + * New link: + * + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) + >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= 2; + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_COLOR); + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. This API is not used internally. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + int gamma_shift = png_ptr->gamma_shift; +#endif + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; + int shift; + + png_debug(1, "in png_do_compose"); + + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->background.gray << shift); + } + + if (!shift) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->background.gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->background.gray << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->background.gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->background.gray << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + } + } + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (!optimize) + w = gamma_from_1[w]; + *sp = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background_1.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize) + w = v; + else + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background_1.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (!optimize) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (!optimize) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (!optimize) w = gamma_from_1[w]; + *(sp + 2) = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + int gamma_shift = png_ptr->gamma_shift; + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* Encode the alpha channel to the output gamma (the input channel is always + * linear.) Called only with color types that have an alpha channel. Needs the + * from_1 tables. + */ +void /* PRIVATE */ +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_encode_alpha"); + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + if (row_info->bit_depth == 8) + { + PNG_CONST png_bytep table = png_ptr->gamma_from_1; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + + /* The alpha channel is the last component: */ + row += step - 1; + + for (; row_width > 0; --row_width, row += step) + *row = table[*row]; + + return; + } + } + + else if (row_info->bit_depth == 16) + { + PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; + PNG_CONST int gamma_shift = png_ptr->gamma_shift; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + + /* The alpha channel is the last component: */ + row += step - 2; + + for (; row_width > 0; --row_width, row += step) + { + png_uint_16 v; + + v = table[*(row + 1) >> gamma_shift][*row]; + *row = (png_byte)((v >> 8) & 0xff); + *(row + 1) = (png_byte)(v & 0xff); + } + + return; + } + } + } + + /* Only get to here if called with a weird row_info; no harm has been done, + * so just issue a warning. + */ + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift += 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (num_trans > 0) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + + else + *dp-- = trans_alpha[*sp]; + + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_color) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray & 0x01) * 0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray & 0x03) * 0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray & 0x0f) * 0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (png_byte)((gray >> 8) & 0xff); + png_byte gray_low = (png_byte)(gray & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* If the bit depth is 8 and the colour type is not a palette type expand the + * whole row to 16 bits. Has no effect otherwise. + */ +void /* PRIVATE */ +png_do_expand_16(png_row_infop row_info, png_bytep row) +{ + if (row_info->bit_depth == 8 && + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + /* The row have a sequence of bytes containing [0..255] and we need + * to turn it into another row containing [0..65535], to do this we + * calculate: + * + * (input / 255) * 65535 + * + * Which happens to be exactly input * 257 and this can be achieved + * simply by byte replication in place (copying backwards). + */ + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ + while (dp > sp) + dp[-2] = dp[-1] = *--sp, dp -= 2; + + row_info->rowbytes *= 2; + row_info->bit_depth = 16; + row_info->pixel_depth = (png_byte)(row_info->channels * 16); + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +void /* PRIVATE */ +png_do_quantize(png_row_infop row_info, png_bytep row, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); + *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngrutil.c b/src/depend/libs/libpng/pngrutil.c new file mode 100644 index 00000000..07e46e2f --- /dev/null +++ b/src/depend/libs/libpng/pngrutil.c @@ -0,0 +1,3666 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#define png_strtod(p,a,b) strtod(a,b) + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return (uval); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + png_uint_32 uval = + ((png_uint_32)(*(buf )) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + ((png_uint_32)(*(buf + 3)) ) ; + + return uval; +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format and there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000L) == 0) /* non-negative */ + return uval; + + uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */ + return -(png_int_32)uval; +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + /* ANSI-C requires an int value to accomodate at least 16 bits so this + * works and allows the compiler not to worry about possible narrowing + * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * than 16 bits either.) + */ + unsigned int val = + ((unsigned int)(*buf) << 8) + + ((unsigned int)(*(buf + 1))); + + return (png_uint_16)val; +} + +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name. */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %u", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + + else + return (0); +} + +#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +static png_size_t +png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, + png_bytep output, png_size_t output_size) +{ + png_size_t count = 0; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't + * even necessarily handle 65536 bytes) because the type uInt is "16 bits or + * more". Consequently it is necessary to chunk the input to zlib. This + * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value + * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a + * lower value in pngpriv.h and this may sometimes have a performance + * advantage, because it forces access of the input data to be separated from + * at least some of the use by some period of time. + */ + png_ptr->zstream.next_in = data; + /* avail_in is set below from 'size' */ + png_ptr->zstream.avail_in = 0; + + while (1) + { + int ret, avail; + + /* The setting of 'avail_in' used to be outside the loop, by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o + * data to be passed through zlib at the unavoidable cost of requiring a + * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX + * input bytes. + */ + if (png_ptr->zstream.avail_in == 0 && size > 0) + { + if (size <= ZLIB_IO_MAX) + { + /* The value is less than ZLIB_IO_MAX so the cast is safe: */ + png_ptr->zstream.avail_in = (uInt)size; + size = 0; + } + + else + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + size -= ZLIB_IO_MAX; + } + } + + /* Reset the output buffer each time round - we empty it + * after every inflate call. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + + /* First copy/count any new output - but only if we didn't + * get an error code. + */ + if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + { + png_size_t space = avail; /* > 0, see above */ + + if (output != 0 && output_size > count) + { + png_size_t copy = output_size - count; + + if (space < copy) + copy = space; + + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += space; + } + + if (ret == Z_OK) + continue; + + /* Termination conditions - always reset the zstream, it + * must be left in inflateInit state. + */ + png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + + if (ret == Z_STREAM_END) + return count; /* NOTE: may be zero. */ + + /* Now handle the error codes - the API always returns 0 + * and the error message is dumped into the uncompressed + * buffer if available. + */ +# ifdef PNG_WARNINGS_SUPPORTED + { + png_const_charp msg; + + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + + else switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream"; + break; + + case Z_DATA_ERROR: + msg = "Data error in compressed datastream"; + break; + + default: + msg = "Incomplete compressed datastream"; + break; + } + + png_chunk_warning(png_ptr, msg); + } +# endif + + /* 0 means an error - notice that this code simply ignores + * zero length compressed chunks as a result. + */ + return 0; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + /* The caller should guarantee this */ + if (prefix_size > chunklength) + { + /* The recovery is to delete the chunk. */ + png_warning(png_ptr, "invalid chunklength"); + prefix_size = 0; /* To delete everything */ + } + + else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + png_size_t expanded_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + 0, /* output */ + 0); /* output size */ + + /* Now check the limits on this chunk - if the limit fails the + * compressed data will be removed, the prefix will remain. + */ +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#endif + png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + + /* If the size is zero either there was an error and a message + * has already been output (warning) or the size really is zero + * and we have nothing to do - the code will exit through the + * error case below. + */ +#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ + defined(PNG_USER_CHUNK_MALLOC_MAX) + else if (expanded_size > 0) +#else + if (expanded_size > 0) +#endif + { + /* Success (maybe) - really uncompress the chunk. */ + png_size_t new_size = 0; + png_charp text = png_malloc_warn(png_ptr, + prefix_size + expanded_size + 1); + + if (text != NULL) + { + png_memcpy(text, png_ptr->chunkdata, prefix_size); + new_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + (png_bytep)(text + prefix_size), expanded_size); + text[prefix_size + expanded_size] = 0; /* just in case */ + + if (new_size == expanded_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength = prefix_size + expanded_size; + return; /* The success return! */ + } + + png_warning(png_ptr, "png_inflate logic error"); + png_free(png_ptr, text); + } + + else + png_warning(png_ptr, "Not enough memory to decompress chunk"); + } + } + + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type); + png_formatted_warning(png_ptr, p, "Unknown zTXt compression type @1"); + + /* The recovery is to simply drop the data. */ + } + + /* Generic error return - leave the prefix, delete the compressed + * data, reallocate the chunkdata to remove the potentially large + * amount of compressed data. + */ + { + png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); + + if (text != NULL) + { + if (prefix_size > 0) + png_memcpy(text, png_ptr->chunkdata, prefix_size); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + + /* This is an extra zero in the 'uncompressed' part. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + } + /* Ignore a malloc error here - it is safe. */ + } + + *newlength = prefix_size; +} +#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + default: /* invalid, png_set_IHDR calls png_error */ + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually need the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + * we have two options: an error abort, or a warning and we + * ignore the data in this chunk (which should be OK, since + * it's considered ancillary for a RGB or RGBA image). + */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_benign_error(png_ptr, "CRC error"); + } + + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + + png_crc_finish(png_ptr, length); + + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = png_get_fixed_point(NULL, buf); + + /* Check for zero gamma or an error. */ + if (igamma <= 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with out of range gamma"); + + return; + } + +# ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma); + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); + return; + } + } +# endif /* PNG_READ_sRGB_SUPPORTED */ + +# ifdef PNG_READ_GAMMA_SUPPORTED + /* Gamma correction on read is supported. */ + png_ptr->gamma = igamma; +# endif + /* And set the 'info' structure members. */ + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; + png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, + y_blue; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +# ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +# endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + + if (png_crc_finish(png_ptr, 0)) + return; + + x_white = png_get_fixed_point(NULL, buf); + y_white = png_get_fixed_point(NULL, buf + 4); + x_red = png_get_fixed_point(NULL, buf + 8); + y_red = png_get_fixed_point(NULL, buf + 12); + x_green = png_get_fixed_point(NULL, buf + 16); + y_green = png_get_fixed_point(NULL, buf + 20); + x_blue = png_get_fixed_point(NULL, buf + 24); + y_blue = png_get_fixed_point(NULL, buf + 28); + + if (x_white == PNG_FIXED_ERROR || + y_white == PNG_FIXED_ERROR || + x_red == PNG_FIXED_ERROR || + y_red == PNG_FIXED_ERROR || + x_green == PNG_FIXED_ERROR || + y_green == PNG_FIXED_ERROR || + x_blue == PNG_FIXED_ERROR || + y_blue == PNG_FIXED_ERROR) + { + png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white); + png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red); + png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red); + png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green); + png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green); + png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue); + png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) " + "when sRGB is also present"); + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Store the _white values as default coefficients for the rgb to gray + * operation if it is supported. + */ + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) + { + /* png_set_background has not been called, the coefficients must be in + * range for the following to work without overflow. + */ + if (y_red <= (1<<17) && y_green <= (1<<17) && y_blue <= (1<<17)) + { + /* The y values are chromaticities: Y/X+Y+Z, the weights for the gray + * transformation are simply the normalized Y values for red, green and + * blue scaled by 32768. + */ + png_uint_32 w = y_red + y_green + y_blue; + + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)(((png_uint_32)y_red * + 32768)/w); + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)(((png_uint_32)y_green + * 32768)/w); + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(((png_uint_32)y_blue * + 32768)/w); + } + } +#endif + + png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, + x_green, y_green, x_blue, y_blue); +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, + info_ptr->gamma); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size; + png_alloc_size_t profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if (profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if (prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC )) << 24) | + ((*(pC + 1)) << 16) | + ((*(pC + 2)) << 8) | + ((*(pC + 3)) ); + + /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, + * because profile_size is a 32 bit value. + */ + if (profile_size < profile_length) + profile_length = profile_size; + + /* And the following guarantees that profile_size == profile_length. */ + if (profile_size > profile_length) + { + PNG_WARNING_PARAMETERS(p) + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size); + png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length); + png_formatted_warning(png_ptr, p, + "Ignoring iCCP chunk with declared size = @1 and actual length = @2"); + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, + profile_size); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; + png_sPLT_entryp pp; + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + png_uint_32 dl; + png_size_t max_dl; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; + entry_start++) + /* Empty loop to find end of name */ ; + + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length (and use 'length', not 'slength' here for clarity - + * they are guaranteed to be the same, see the tests above.) + */ + data_length = length - (png_uint_32)(entry_start - + (png_bytep)png_ptr->chunkdata); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + png_color_16 background; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + background.index = buf[0]; + + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + + background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; + } + + else + background.red = background.green = background.blue = 0; + + background.gray = 0; + } + + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + background.index = 0; + background.red = + background.green = + background.blue = + background.gray = png_get_uint_16(buf); + } + + else + { + background.index = 0; + background.red = png_get_uint_16(buf); + background.green = png_get_uint_16(buf + 2); + background.blue = png_get_uint_16(buf + 4); + background.gray = 0; + } + + png_set_bKGD(png_ptr, info_ptr, &background); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + + if (num != (unsigned int)png_ptr->num_palette || num > + (unsigned int)PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + * in order to get the parameter information. + */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + * equation types. + */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + + params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)(nparams * png_sizeof(png_charp))); + + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t slength, i; + int state; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + /* Need unit type, width, \0, height: minimum 4 bytes */ + else if (length < 4) + { + png_warning(png_ptr, "sCAL chunk too short"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + length + 1); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the unit. */ + if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) + { + png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 1; + state = 0; + + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i >= slength || png_ptr->chunkdata[i++] != 0) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width"); + + else + { + png_size_t heighti = i; + + state = 0; + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i != slength) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, + "Invalid sCAL chunk ignored: non-positive height"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], + png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); + } + + /* Clean up - just free the temporarily allocated buffer. */ + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for tEXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for zTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_type = *(++text); + + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + + text++; /* Skip the compression_method byte */ + } + + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk"); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for iTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + + text++; /* Skip NUL separator */ + + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk"); +} +#endif + +/* This function is called when we haven't found a handler for a + * chunk. If there isn't a problem with the chunk itself (ie bad + * chunk name, CRC, or a critical chunk), the chunk is silently ignored + * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + * case it will be saved away to be written out later. + */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for unknown chunk"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + PNG_IDAT; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + || (png_ptr->read_user_chunk_fn != NULL) +#endif + ) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#ifndef PNG_READ_USER_CHUNKS_SUPPORTED + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + * This function can't have the "critical chunk check" incorporated + * into it, since in the future we will need to be able to call user + * functions to handle unknown critical chunks after we check that + * the chunk name itself is valid. + */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + * row. This routine takes care of alpha and transparency if requested. + * This routine also handles the two methods of progressive display + * of interlaced images, depending on the mask value. + * The mask value describes which pixels are to be combined with + * the row. The pattern always repeats every 8 pixels, so just 8 + * bits are needed. A one indicates the pixel is to be combined, + * a zero indicates the pixel is to be skipped. This is in addition + * to any alpha or transparency value associated with the pixel. If + * you want all pixels to be combined, pass 0xff (255) in mask. + */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + + /* Added in 1.5.4: the row_info should match the information returned by any + * call to png_read_update_info at this point. Do not continue if we got + * this wrong. + */ + if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)) + png_error(png_ptr, "internal row size calculation error"); + + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + + case PNG_FILTER_VALUE_SUB: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + png_const_bytep cp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_error(png_ptr, "Ignoring bad adaptive filter type"); + /*NOT REACHED */ + break; + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + PNG_IDAT; + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_init_read_transformations(png_ptr); +#endif +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + + max_pixel_depth = png_ptr->pixel_depth; + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16) + { +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + + else + max_pixel_depth = 32; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); + +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, + row_bytes + 48); + + png_ptr->old_big_row_buf_size = row_bytes + 48; + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf. + */ + png_ptr->row_buf = png_ptr->big_row_buf + 32 - + (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F); + + png_ptr->old_big_row_buf_size = row_bytes + 48; +#else + /* Use 32 bytes of padding before and 16 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 32; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; + } + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngset.c b/src/depend/libs/libpng/pngset.c new file mode 100644 index 00000000..7eaad7dd --- /dev/null +++ b/src/depend/libs/libpng/pngset.c @@ -0,0 +1,1226 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +void PNGFAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +# ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +# endif + { + info_ptr->x_white = white_x; + info_ptr->y_white = white_y; + info_ptr->x_red = red_x; + info_ptr->y_red = red_y; + info_ptr->x_green = green_x; + info_ptr->y_green = green_y; + info_ptr->x_blue = blue_x; + info_ptr->y_blue = blue_y; + info_ptr->valid |= PNG_INFO_cHRM; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't + * occur. Since the fixed point representation is assymetrical it is + * possible for 1/gamma to overflow the limit of 21474 and this means the + * gamma value must be at least 5/100000 and hence at most 20000.0. For + * safety the limits here are a little narrower. The values are 0.00016 to + * 6250.0, which are truely ridiculous gammma values (and will produce + * displays that are all black or all white.) + */ + if (file_gamma < 16 || file_gamma > 625000000) + png_warning(png_ptr, "Out of range gamma value ignored"); + + else + { + info_ptr->gamma = file_gamma; + info_ptr->valid |= PNG_INFO_gAMA; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)); + + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + info_ptr->free_me |= PNG_FREE_HIST; +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > + (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = 0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + /* Validate params[nparams] */ + for (i=0; ipcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + + png_memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + + png_memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * png_sizeof(png_charp))); + + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + + png_memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + if (unit != 1 && unit != 2) + png_error(png_ptr, "Invalid sCAL unit"); + + if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 || + swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) + png_error(png_ptr, "Invalid sCAL width"); + + if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 || + sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) + png_error(png_ptr, "Invalid sCAL height"); + + info_ptr->scal_unit = (png_byte)unit; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw); + + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_width, swidth, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh); + + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_height, sheight, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width, + double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width); + png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_const_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)srgb_intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + +# ifdef PNG_gAMA_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); +# endif + +# ifdef PNG_cHRM_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270L, 32900L, + /* red */ 64000L, 33000L, + /* green */ 30000L, 60000L, + /* blue */ 15000L, 6000L + ); +# endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen); + + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types + */ + info_ptr->iccp_compression = (png_byte)compression_type; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", ((png_ptr == NULL || + png_ptr->chunk_name[0] == '\0') ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); + info_ptr->free_me |= PNG_FREE_TEXT; + } + + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_warning(png_ptr, "text compression mode is out of range"); + continue; + } + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +# ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + + else + lang_len = 0; + + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + + else + lang_key_len = 0; + } +# else /* PNG_iTXt_SUPPORTED */ + { + png_warning(png_ptr, "iTXt chunk not supported"); + continue; + } +# endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +# ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + + else +# endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_size_t) + (key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + return(1); + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; + + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + + else + { + textp->lang=NULL; + textp->lang_key=NULL; + textp->text = textp->key + key_len + 1; + } + + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + + *(textp->text + text_length) = '\0'; + +# ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + + else +# endif + { + textp->text_length = text_length; + textp->itxt_length = 0; + } + + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = + (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + + png_memcpy(&(info_ptr->trans_color), trans_color, + png_sizeof(png_color_16)); + + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_const_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_size_t)png_sizeof(png_sPLT_t)); + + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes"); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_const_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; + info_ptr->free_me |= PNG_FREE_SPLT; +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + (png_size_t)info_ptr->unknown_chunks_num * + png_sizeof(png_unknown_chunk)); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_const_unknown_chunkp from = unknowns + i; + + png_memcpy(to->name, from->name, png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)from->size); + + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + to->size = 0; + } + + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; + info_ptr->free_me |= PNG_FREE_UNKN; +} + +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return (png_uint_32)0; + + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + return; + } + + if (chunk_list == NULL) + return; + + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_size_t)(5*(num_chunks + old_num_chunks))); + + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; + png_ptr->free_me |= PNG_FREE_LIST; +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + + info_ptr->row_pointers = row_pointers; + + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_size_t size) +{ + if (png_ptr == NULL) + return; + + png_free(png_ptr, png_ptr->zbuf); + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, "Attempt to set buffer size beyond max ignored"); + png_ptr->zbuf_size = ZLIB_IO_MAX; + size = ZLIB_IO_MAX; /* must fit */ + } + + else + png_ptr->zbuf_size = (uInt)size; + + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + + /* The following ensures a relatively safe failure if this gets called while + * the buffer is actually in use. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.avail_in = 0; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structp png_ptr, + png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + + else + png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngstruct.h b/src/depend/libs/libpng/pngstruct.h new file mode 100644 index 00000000..93b2b3eb --- /dev/null +++ b/src/depend/libs/libpng/pngstruct.h @@ -0,0 +1,337 @@ + +/* pngstruct.h - header file for PNG reference library + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#include "zlib.h" + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf longjmp_buffer; /* used in png_error */ + png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; /* function for printing warnings */ +#endif + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + uInt zbuf_size; /* size of zbuf (typically 65536) */ +#ifdef PNG_WRITE_SUPPORTED + +/* Added in 1.5.4: state to keep track of whether the zstream has been + * initialized and if so whether it is for IDAT or some other chunk. + */ +#define PNG_ZLIB_UNINITIALIZED 0 +#define PNG_ZLIB_FOR_IDAT 1 +#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */ +#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */ +#define PNG_ZLIB_IN_USE 4 /* a flag value */ + + png_uint_32 zlib_state; /* State of zlib initialization */ +/* End of material added at libpng 1.5.4 */ + + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ +#endif +/* Added at libpng 1.5.4 */ +#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \ + defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED) + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +#endif +/* End of material added at libpng 1.5.4 */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point gamma; /* file gamma value */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + char time_buffer[29]; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* which original index points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk; +#endif + +/* New members added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + png_size_t old_prev_row_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/src/depend/libs/libpng/pngtest.c b/src/depend/libs/libpng/pngtest.c new file mode 100644 index 00000000..9084ada6 --- /dev/null +++ b/src/depend/libs/libpng/pngtest.c @@ -0,0 +1,1797 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#define _POSIX_SOURCE 1 + +#include "zlib.h" +#include "png.h" +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +# include +# include +# include +# define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* The code uses memcmp and memcpy on large objects (typically row pointers) so + * it is necessary to do soemthing special on certain architectures, note that + * the actual support for this was effectively removed in 1.4, so only the + * memory remains in this program: + */ +#define CVT_PTR(ptr) (ptr) +#define CVT_PTR_NOCHECK(ptr) (ptr) +#define png_memcmp memcmp +#define png_memcpy memcpy +#define png_memset memset + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + + fprintf(stdout, "r"); +} + +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + + fprintf(stdout, "w"); +} + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL) + return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, 1, io_ptr); + png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Read Error"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(png_ptr) /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void PNGCBAPI +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + char *test; + test = png_get_error_ptr(png_ptr); + + if (test == NULL) + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + + else + fprintf(STDERR, "%s: libpng warning: %s\n", test, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void PNGCBAPI +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} +#endif /* !PNG_STDIO_SUPPORTED */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + png_sizeof(*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void PNGCBAPI +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %p\n", ptr); + + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +/* Demonstration of user chunk support of the sTER and vpAg chunks */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static png_uint_32 user_chunk_data[4]; + + /* 0: sTER mode + 1 + * 1: vpAg width + * 2: vpAg height + * 3: vpAg units + */ + +static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + png_uint_32 + *my_user_chunk_data; + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + my_user_chunk_data[0]=chunk->data[0]+1; + return (1); + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + + my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + + return (1); + +} +#endif +/* END of code to demonstrate user chunk support */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf tmp_jmpbuf; +#endif +#endif + + char inbuf[256], outbuf[256]; + + row_buf = NULL; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + user_chunk_data[0] = 0; + user_chunk_data[1] = 0; + user_chunk_data[2] = 0; + user_chunk_data[3] = 0; + png_set_read_user_chunk_fn(read_ptr, user_chunk_data, + read_user_chunk_callback); + +#endif +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); +#ifdef USE_FAR_KEYWORD + + if (setjmp(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } + +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + /* Normally one would use Z_DEFAULT_STRATEGY for text compression. + * This is here just to make pngtest replicate the results from libpng + * versions prior to 1.5.4, and to test this new API. + */ + png_set_text_compression_strategy(write_ptr, Z_FILTERED); +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + + for (i = 0; i<256; i++) + filters_used[i] = 0; + + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + NULL, 0); +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_bytep profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + * pointed to by png_convert_to_rfc1123() gets free'ed before + * we use it. + */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_bytep trans_alpha; + int num_trans; + png_color_16p trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color)) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_info_ptr are wrong because we + * haven't written anything yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + +/* If we wanted, we could write info in two steps: + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (user_chunk_data[0] != 0) + { + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + unsigned char + ster_chunk_data[1]; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %lu\n", + (unsigned long)(user_chunk_data[0] - 1)); + + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); + png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); + } + + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) + { + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + unsigned char + vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", + (unsigned long)user_chunk_data[1], + (unsigned long)user_chunk_data[2], + (unsigned long)user_chunk_data[3]); + + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); + vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); + } + +#endif +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); + +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong because we + * haven't written the end_info yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + pngtest_debug("Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + pngtest_debug("destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + pngtest_debug("Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + num_in = fread(inbuf, 1, 1, fpin); + num_out = fread(outbuf, 1, 1, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_5_4 Your_png_h_is_not_version_1_5_4; diff --git a/src/depend/libs/libpng/pngtrans.c b/src/depend/libs/libpng/pngtrans.c new file mode 100644 index 00000000..6a6908dc --- /dev/null +++ b/src/depend/libs/libpng/pngtrans.c @@ -0,0 +1,678 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_const_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_uint_16)filler; + + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA?) */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if (row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove a channel - this used to be 'png_do_strip_filler' but it used a + * somewhat weird combination of flags to determine what to do. All the calls + * to png_do_strip_filler are changed in 1.5.2 to call this instead with the + * correct arguments. + * + * The routine isn't general - the channel must be the channel at the start or + * end (not in the middle) of each pixel. + */ +void /* PRIVATE */ +png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) +{ + png_bytep sp = row; /* source pointer */ + png_bytep dp = row; /* destination pointer */ + png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + + /* At the start sp will point to the first byte to copy and dp to where + * it is copied to. ep always points just beyond the end of the row, so + * the loop simply copies (channels-1) channels until sp reaches ep. + * + * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. + * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. + */ + + /* GA, GX, XG cases */ + if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channel and, for sp, the filler */ + sp += 2, ++dp; + + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 8; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channel and, for sp, the filler */ + sp += 4, dp += 2; + + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; + } + + else + return; /* bad bit depth */ + + row_info->channels = 1; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_GRAY; + } + + /* RGBA, RGBX, XRGB cases */ + else if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 4, dp += 3; + + /* Note that the loop adds 3 to dp and 4 to sp each time. */ + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channels and, for sp, the filler */ + sp += 8, dp += 6; + + while (sp < ep) + { + /* Copy 6 bytes, skip 2 */ + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp, sp += 3; + } + + row_info->pixel_depth = 48; + } + + else + return; /* bad bit depth */ + + row_info->channels = 3; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_RGB; + } + + else + return; /* The filler channel has gone already */ + + /* Fix the rowbytes value. */ + row_info->rowbytes = dp-row; +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } +#endif + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->user_transform_ptr); +} +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +png_uint_32 PNGAPI +png_get_current_row_number(png_const_structp png_ptr) +{ + /* See the comments in png.h - this is the sub-image row when reading and + * interlaced image. + */ + if (png_ptr != NULL) + return png_ptr->row_number; + + return PNG_UINT_32_MAX; /* help the app not to fail silently */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->pass; + return 8; /* invalid */ +} +#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngwio.c b/src/depend/libs/libpng/pngwio.c new file mode 100644 index 00000000..95ffb342 --- /dev/null +++ b/src/depend/libs/libpng/pngwio.c @@ -0,0 +1,254 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length); + + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +# ifdef PNG_STDIO_SUPPORTED +void PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +} +# endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED + + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; + +# else + png_ptr->output_flush_fn = output_flush_fn; +# endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +} + +#ifdef USE_FAR_KEYWORD +# ifdef _MSC_VER +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngwrite.c b/src/depend/libs/libpng/pngwrite.c new file mode 100644 index 00000000..d1af9e89 --- /dev/null +++ b/src/depend/libs/libpng/pngwrite.c @@ -0,0 +1,1655 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED + if (info_ptr->valid & PNG_INFO_gAMA) + png_write_gAMA_fixed(png_ptr, info_ptr->gamma); +#endif +#ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_cHRM_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + png_write_cHRM_fixed(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && + !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + !(up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && + (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + !(up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && + (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */ + +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf tmp_jmpbuf; +#endif +#endif + + png_debug(1, "in png_create_write_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ +#endif +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif + PNG_ABORT(); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + + if (!png_cleanup_needed) + { + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_reset_filter_heuristics(png_ptr); +#endif + + return (png_ptr); +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_const_bytep row) +{ + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %u", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", + (unsigned long)png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + wrote_IDAT = 1; + } + } while (wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; +#endif + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Use this to save a little code space, it doesn't free the filter_costs */ + png_reset_filter_heuristics(png_ptr); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + warning_fn = png_ptr->warning_fn; +#endif + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#endif + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; + +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + + default: + png_ptr->do_filter = (png_byte)filters; break; +#else + default: + png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_UP); + } + + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_AVG); + } + + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +/* Convenience reset API. */ +static void +png_reset_filter_heuristics(png_structp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + } + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = (png_uint_16) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + if (filter_costs[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +/* The following were added to libpng-1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +void PNGAPI +png_set_text_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL; + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL; + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY; + png_ptr->zlib_text_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_text_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Text compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS; + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_text_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD; + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +/* end of API added to libpng-1.5.4 */ + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngwtran.c b/src/depend/libs/libpng/pngwtran.c new file mode 100644 index 00000000..124d708c --- /dev/null +++ b/src/depend/libs/libpng/pngwtran.c @@ -0,0 +1,633 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + + sp++; + + if (mask > 1) + mask >>= 1; + + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + + if (mask != 0x80) + *dp = (png_byte)v; + + break; + } + + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 2; + + sp++; + } + + if (shift != 6) + *dp = (png_byte)v; + + break; + } + + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 4; + + sp++; + } + + if (shift != 4) + *dp = (png_byte)v; + + break; + } + + default: + break; + } + + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_size_t i; + png_byte mask; + png_size_t row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/libpng/pngwutil.c b/src/depend/libs/libpng/pngwutil.c new file mode 100644 index 00000000..3ae5ed4e --- /dev/null +++ b/src/depend/libs/libpng/pngwutil.c @@ -0,0 +1,3179 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.5.4 [July 7, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extention.) + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} +#endif + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, chunk_name, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_const_bytep data, + png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Initialize the compressor for the appropriate type of compression. */ +static void +png_zlib_claim(png_structp png_ptr, png_uint_32 state) +{ + if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE)) + { + /* If already initialized for 'state' do not re-init. */ + if (png_ptr->zlib_state != state) + { + int ret = Z_OK; + png_const_charp who = "-"; + + /* If actually initialized for another state do a deflateEnd. */ + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + { + ret = deflateEnd(&png_ptr->zstream); + who = "end"; + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + } + + /* zlib itself detects an incomplete state on deflateEnd */ + if (ret == Z_OK) switch (state) + { +# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED + case PNG_ZLIB_FOR_TEXT: + ret = deflateInit2(&png_ptr->zstream, + png_ptr->zlib_text_level, png_ptr->zlib_text_method, + png_ptr->zlib_text_window_bits, + png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy); + who = "text"; + break; +# endif + + case PNG_ZLIB_FOR_IDAT: + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + who = "IDAT"; + break; + + default: + png_error(png_ptr, "invalid zlib state"); + } + + if (ret == Z_OK) + png_ptr->zlib_state = state; + + else /* an error in deflateEnd or deflateInit2 */ + { + size_t pos = 0; + char msg[64]; + + pos = png_safecat(msg, sizeof msg, pos, + "zlib failed to initialize compressor ("); + pos = png_safecat(msg, sizeof msg, pos, who); + + switch (ret) + { + case Z_VERSION_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") version error"); + break; + + case Z_STREAM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") stream error"); + break; + + case Z_MEM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") memory error"); + break; + + default: + pos = png_safecat(msg, sizeof msg, pos, ") unknown error"); + break; + } + + png_error(png_ptr, msg); + } + } + + /* Here on success, claim the zstream: */ + png_ptr->zlib_state |= PNG_ZLIB_IN_USE; + } + + else + png_error(png_ptr, "zstream already in use (internal error)"); +} + +/* The opposite: release the stream. It is also reset, this API will warn on + * error but will not fail. + */ +static void +png_zlib_release(png_structp png_ptr) +{ + if (png_ptr->zlib_state & PNG_ZLIB_IN_USE) + { + int ret = deflateReset(&png_ptr->zstream); + + png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE; + + if (ret != Z_OK) + { + png_const_charp err; + PNG_WARNING_PARAMETERS(p) + + switch (ret) + { + case Z_VERSION_ERROR: + err = "version"; + break; + + case Z_STREAM_ERROR: + err = "stream"; + break; + + case Z_MEM_ERROR: + err = "memory"; + break; + + default: + err = "unknown"; + break; + } + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret); + png_warning_parameter(p, 2, err); + + if (png_ptr->zstream.msg) + err = png_ptr->zstream.msg; + else + err = "[no zlib message]"; + + png_warning_parameter(p, 3, err); + + png_formatted_warning(png_ptr, p, + "zlib failed to reset compressor: @1(@2): @3"); + } + } + + else + png_warning(png_ptr, "zstream not in use (internal error)"); +} + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + png_const_bytep input; /* The uncompressed input data */ + png_size_t input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_bytep *output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_const_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = text_len; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = (png_const_bytep)text; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, + compression); + png_formatted_warning(png_ptr, p, "Unknown compression type @1"); + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT); + + /* Set up the compression buffers */ + /* TODO: the following cast hides a potential overflow problem. */ + png_ptr->zstream.avail_in = (uInt)text_len; + + /* NOTE: assume zlib doesn't overwrite the input */ + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charpp))); + + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + /* This could be optimized to realloc() */ + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, comp->input, comp->input_len); + + return; + } + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (comp->input_len >= 2 && comp->input_len < 16384) + { + unsigned int z_cmf; /* zlib compression method and flags */ + + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ + + if (comp->num_output_ptr) + z_cmf = comp->output_ptr[0][0]; + else + z_cmf = png_ptr->zbuf[0]; + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + unsigned int z_cinfo; + unsigned int half_z_window_size; + png_size_t uncompressed_text_size = comp->input_len; + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1 << (z_cinfo + 7); + + while (uncompressed_text_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + if (comp->num_output_ptr) + { + + if (comp->output_ptr[0][0] != z_cmf) + { + int tmp; + + comp->output_ptr[0][0] = (png_byte)z_cmf; + tmp = comp->output_ptr[0][1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + comp->output_ptr[0][1] = (png_byte)tmp; + } + } + else + { + int tmp; + + png_ptr->zbuf[0] = (png_byte)z_cmf; + tmp = png_ptr->zbuf[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + png_ptr->zbuf[1] = (png_byte)tmp; + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in non-IDAT chunk"); + } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + + png_free(png_ptr, comp->output_ptr[i]); + } + + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + + /* Reset zlib for another zTXt/iTXt or image data */ + png_zlib_release(png_ptr); +} +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + PNG_IHDR; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGB image"); + + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + png_ptr->channels = 1; + break; + + default: + png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGBA image"); + + png_ptr->channels = 4; + break; + + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY)) + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL)) + png_ptr->zlib_text_level = png_ptr->zlib_level; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD)) + png_ptr->zlib_text_method = png_ptr->zlib_method; +#else + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = png_ptr->zlib_level; + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; + png_ptr->zlib_text_method = png_ptr->zlib_method; +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + + /* Record that the compressor has not yet been initialized. */ + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_const_colorp palette, + png_uint_32 num_pal) +{ + PNG_PLTE; + png_uint_32 i; + png_const_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ + PNG_IDAT; + + png_debug(1, "in png_write_IDAT"); + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + /* Compute the maximum possible length of the datastream */ + + /* Number of pixels, plus for each row a filter byte + * and possibly a padding byte, so increase the maximum + * size to account for these. + */ + unsigned int z_cinfo; + unsigned int half_z_window_size; + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + + /* If it's interlaced, each block of 8 rows is sent as up to + * 14 rows, i.e., 6 additional rows, each with a filter byte + * and possibly a padding byte + */ + if (png_ptr->interlaced) + uncompressed_idat_size += ((png_ptr->height + 7)/8) * + (png_ptr->bit_depth < 8 ? 12 : 6); + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1 << (z_cinfo + 7); + + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + if (data[0] != z_cmf) + { + int tmp; + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + + png_write_chunk(png_ptr, png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; + + /* Prior to 1.5.4 this code was replicated in every caller (except at the + * end, where it isn't technically necessary). Since this function has + * flushed the data we can safely reset the zlib output buffer here. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ + PNG_IEND; + + png_debug(1, "in png_write_IEND"); + + png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ + PNG_gAMA; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ + PNG_sRGB; + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, + png_const_charp profile, int profile_len) +{ + PNG_iCCP; + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_const_bytep)profile ))<<24) | + ((*( (png_const_bytep)profile + 1))<<16) | + ((*( (png_const_bytep)profile + 2))<< 8) | + ((*( (png_const_bytep)profile + 3)) ); + + if (embedded_profile_len < 0) + { + png_warning(png_ptr, + "Embedded profile length in iCCP chunk is negative"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + + new_name[name_len + 1] = 0x00; + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + { + comp.input_len = profile_len; + png_write_compressed_data_out(png_ptr, &comp); + } + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette) +{ + PNG_sPLT; + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i = 0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) +{ + PNG_sBIT; + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ + PNG_cHRM; + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); + } +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + PNG_tRNS; + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans); + } + + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + } + + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + } + + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) +{ + PNG_bKGD; + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + + buf[0] = back->index; + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + } + + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + } + + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist) +{ + PNG_hIST; + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_const_charp ikp; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) + { + if ((png_byte)*ikp < 0x20 || + ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x, + (png_byte)*ikp); + png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1"); + *dp = ' '; + } + + else + { + *dp = *ikp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + + else if (*kp == ' ') + { + key_len--; + kwarn = 1; + } + + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len) +{ + PNG_tEXt; + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + if (text_len) + png_write_chunk_data(png_ptr, (png_const_bytep)text, + (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + PNG_zTXt; + png_size_t key_len; + png_byte buf; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + png_free(png_ptr, new_key); + + buf = (png_byte)compression; + + /* Write compression */ + png_write_chunk_data(png_ptr, &buf, (png_size_t)1); + + /* Write the compressed data */ + comp.input_len = text_len; + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + PNG_iTXt; + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression - 2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts + */ + + png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + + /* Set the compression method */ + cbuf[1] = 0; + + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + + png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + PNG_oFFs; + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) +{ + PNG_pCAL; + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + * null terminator for the last parameter. + */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long)params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + PNG_sCAL; + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + PNG_pHYs; + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_const_timep mod_time) +{ + PNG_tIME; + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)buf_size); + + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, + (png_alloc_size_t)buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + + png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT); + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + png_zlib_release(png_ptr); + png_ptr->zstream.data_type = Z_BINARY; +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + + break; + } + + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + + /* Loop through the row, only looking at the pixels that matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row); + +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_size_t i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +static void +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_size_t avail; + + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = 0; + avail = png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Record the number of bytes available - zlib supports at least 65535 + * bytes at one step, depending on the size of the zlib type 'uInt', the + * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). + * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. + * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a + * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called + * with smaller chunks of data. + */ + if (png_ptr->zstream.avail_in == 0) + { + if (avail > ZLIB_IO_MAX) + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + avail -= ZLIB_IO_MAX; + } + + else + { + /* So this will fit in the available uInt space: */ + png_ptr->zstream.avail_in = (uInt)avail; + avail = 0; + } + } + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + /* Repeat until all data has been compressed */ + } while (avail > 0 || png_ptr->zstream.avail_in > 0); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/src/depend/libs/zlib/adler32.c b/src/depend/libs/zlib/adler32.c new file mode 100644 index 00000000..65ad6a5a --- /dev/null +++ b/src/depend/libs/zlib/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/src/depend/libs/zlib/compress.c b/src/depend/libs/zlib/compress.c new file mode 100644 index 00000000..ea4dfbe9 --- /dev/null +++ b/src/depend/libs/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/src/depend/libs/zlib/crc32.c b/src/depend/libs/zlib/crc32.c new file mode 100644 index 00000000..91be372d --- /dev/null +++ b/src/depend/libs/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/src/depend/libs/zlib/crc32.h b/src/depend/libs/zlib/crc32.h new file mode 100644 index 00000000..8053b611 --- /dev/null +++ b/src/depend/libs/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/src/depend/libs/zlib/deflate.c b/src/depend/libs/zlib/deflate.c new file mode 100644 index 00000000..5c4022f3 --- /dev/null +++ b/src/depend/libs/zlib/deflate.c @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/src/depend/libs/zlib/deflate.h b/src/depend/libs/zlib/deflate.h new file mode 100644 index 00000000..cbf0d1ea --- /dev/null +++ b/src/depend/libs/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/src/depend/libs/zlib/fba_zlib_v125.txt b/src/depend/libs/zlib/fba_zlib_v125.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/depend/libs/zlib/gzclose.c b/src/depend/libs/zlib/gzclose.c new file mode 100644 index 00000000..caeb99a3 --- /dev/null +++ b/src/depend/libs/zlib/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/src/depend/libs/zlib/gzguts.h b/src/depend/libs/zlib/gzguts.h new file mode 100644 index 00000000..0f8fb79f --- /dev/null +++ b/src/depend/libs/zlib/gzguts.h @@ -0,0 +1,132 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif +#include + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifdef _MSC_VER +# include +# define vsnprintf _vsnprintf +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifdef STDC +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default i/o buffer size -- double this for output when reading */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + z_off64_t pos; /* current position in uncompressed data */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + unsigned char *next; /* next output data to deliver or write */ + /* just for reading */ + unsigned have; /* amount of output data unused at next */ + int eof; /* true if end of input file reached */ + z_off64_t start; /* where the gzip data started, for rewinding */ + z_off64_t raw; /* where the raw data started, for seeking */ + int how; /* 0: get header, 1: copy, 2: decompress */ + int direct; /* true if last read direct, false if gzip */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/src/depend/libs/zlib/gzlib.c b/src/depend/libs/zlib/gzlib.c new file mode 100644 index 00000000..603e60ed --- /dev/null +++ b/src/depend/libs/zlib/gzlib.c @@ -0,0 +1,537 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + if (state->mode == GZ_READ) { /* for reading ... */ + state->have = 0; /* no output data available */ + state->eof = 0; /* not at end of file */ + state->how = LOOK; /* look for gzip header */ + state->direct = 1; /* default for empty file */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size == 0) + return -1; + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->pos + offset >= state->raw) { + ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + if (ret == -1) + return -1; + state->have = 0; + state->eof = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->pos += offset; + return state->pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? + (unsigned)offset : state->have; + state->have -= n; + state->next += n; + state->pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? + (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) + state->eof = 0; + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/src/depend/libs/zlib/gzread.c b/src/depend/libs/zlib/gzread.c new file mode 100644 index 00000000..548201ab --- /dev/null +++ b/src/depend/libs/zlib/gzread.c @@ -0,0 +1,653 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_next4 OF((gz_statep, unsigned long *)); +local int gz_head OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_make OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + gz_avail() assumes that strm->avail_in == 0. */ +local int gz_avail(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->err != Z_OK) + return -1; + if (state->eof == 0) { + if (gz_load(state, state->in, state->size, + (unsigned *)&(strm->avail_in)) == -1) + return -1; + strm->next_in = state->in; + } + return 0; +} + +/* Get next byte from input, or -1 if end or error. */ +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) + +/* Get a four-byte little-endian integer and return 0 on success and the value + in *ret. Otherwise -1 is returned and *ret is not modified. */ +local int gz_next4(state, ret) + gz_statep state; + unsigned long *ret; +{ + int ch; + unsigned long val; + z_streamp strm = &(state->strm); + + val = NEXT(); + val += (unsigned)NEXT() << 8; + val += (unsigned long)NEXT() << 16; + ch = NEXT(); + if (ch == -1) + return -1; + val += (unsigned long)ch << 24; + *ret = val; + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->have must be zero. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression, and the gzip header will be skipped so + that the next available input data is the raw deflate stream. If direct + copying, then leftover input data from the input buffer will be copied to + the output buffer. In that case, all further file reads will be directly to + either the output buffer or a user buffer. If decompressing, the inflate + state and the check value will be initialized. gz_head() will return 0 on + success or -1 on failure. Failures may include read errors or gzip header + errors. */ +local int gz_head(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + int flags; + unsigned len; + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get some data in the input buffer */ + if (strm->avail_in == 0) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for the gzip magic header bytes 31 and 139 */ + if (strm->next_in[0] == 31) { + strm->avail_in--; + strm->next_in++; + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in && strm->next_in[0] == 139) { + /* we have a gzip header, woo hoo! */ + strm->avail_in--; + strm->next_in++; + + /* skip rest of header */ + if (NEXT() != 8) { /* compression method */ + gz_error(state, Z_DATA_ERROR, "unknown compression method"); + return -1; + } + flags = NEXT(); + if (flags & 0xe0) { /* reserved flag bits */ + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); + return -1; + } + NEXT(); /* modification time */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); /* extra flags */ + NEXT(); /* operating system */ + if (flags & 4) { /* extra field */ + len = (unsigned)NEXT(); + len += (unsigned)NEXT() << 8; + while (len--) + if (NEXT() < 0) + break; + } + if (flags & 8) /* file name */ + while (NEXT() > 0) + ; + if (flags & 16) /* comment */ + while (NEXT() > 0) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + /* an unexpected end of file is not checked for here -- it will be + noticed on the first request for uncompressed data */ + + /* set up for decompression */ + inflateReset(strm); + strm->adler = crc32(0L, Z_NULL, 0); + state->how = GZIP; + state->direct = 0; + return 0; + } + else { + /* not a gzip file -- save first byte (31) and fall to raw i/o */ + state->out[0] = 31; + state->have = 1; + } + } + + /* doing raw i/o, save start of raw data for seeking, copy any leftover + input to output -- this assumes that the output buffer is larger than + the input buffer, which also assures space for gzungetc() */ + state->raw = state->pos; + state->next = state->out; + if (strm->avail_in) { + memcpy(state->next + state->have, strm->next_in, strm->avail_in); + state->have += strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + If the end of the compressed data is reached, then verify the gzip trailer + check value and length (modulo 2^32). state->have and state->next are set + to point to the just decompressed data, and the crc is updated. If the + trailer is verified, state->how is reset to LOOK to look for the next gzip + stream or raw data, once state->have is depleted. Returns 0 on success, -1 + on failure. Failures may include invalid compressed data or a failed gzip + trailer verification. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret; + unsigned had; + unsigned long crc, len; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output and crc check value */ + state->have = had - strm->avail_out; + state->next = strm->next_out - state->have; + strm->adler = crc32(strm->adler, state->next, state->have); + + /* check gzip trailer if at end of deflate stream */ + if (ret == Z_STREAM_END) { + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + if (crc != strm->adler) { + gz_error(state, Z_DATA_ERROR, "incorrect data check"); + return -1; + } + if (len != (strm->total_out & 0xffffffffL)) { + gz_error(state, Z_DATA_ERROR, "incorrect length check"); + return -1; + } + state->how = LOOK; /* ready for next stream, once have is 0 (leave + state->direct unchanged to remember how) */ + } + + /* good decompression */ + return 0; +} + +/* Make data and put in the output buffer. Assumes that state->have == 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for (and skipped if found) to determine wither to copy or decompress. + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY + or GZIP unless the end of the input file has been reached and all data has + been processed. */ +local int gz_make(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->how == LOOK) { /* look for gzip header */ + if (gz_head(state) == -1) + return -1; + if (state->have) /* got some data from gz_head() */ + return 0; + } + if (state->how == COPY) { /* straight copy */ + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) + return -1; + state->next = state->out; + } + else if (state->how == GZIP) { /* decompress */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->have) { + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? + (unsigned)len : state->have; + state->have -= n; + state->next += n; + state->pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->have) { + n = state->have > len ? len : state->have; + memcpy(buf, state->next, n); + state->next += n; + state->have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) + break; + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->have; + state->have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->have) { + state->have--; + state->pos++; + return *(state->next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->have == 0) { + state->have = 1; + state->next = state->out + (state->size << 1) - 1; + state->next[0] = c; + state->pos--; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->have == (state->size << 1)) { + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->next == state->out) { + unsigned char *src = state->out + state->have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->next = dest; + } + state->have++; + state->next--; + state->next[0] = c; + state->pos--; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->have == 0) { + if (gz_make(state) == -1) + return NULL; /* error */ + if (state->have == 0) { /* end of file */ + if (buf == str) /* got bupkus */ + return NULL; + break; /* got something -- return it */ + } + } + + /* look for end-of-line in current output buffer */ + n = state->have > left ? left : state->have; + eol = memchr(state->next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->next, n); + state->have -= n; + state->next += n; + state->pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* found end-of-line or out of space -- terminate string and return it */ + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return 0; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->how == LOOK && state->have == 0) + (void)gz_head(state); + + /* return 1 if reading direct, 0 if decompressing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/src/depend/libs/zlib/gzwrite.c b/src/depend/libs/zlib/gzwrite.c new file mode 100644 index 00000000..e8defc68 --- /dev/null +++ b/src/depend/libs/zlib/gzwrite.c @@ -0,0 +1,531 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input and output buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + 15 + 16, 8, state->strategy); + if (ret != Z_OK) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer */ + strm->avail_out = state->size; + strm->next_out = state->out; + state->next = strm->next_out; + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->next); + if (have && ((got = write(state->fd, state->next, have)) < 0 || + (unsigned)got != have)) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + memcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->pos++; + return c; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#ifdef STDC +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf(state->in, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#else /* !STDC */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = 0; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + ret += gz_zero(state, state->skip); + } + + /* flush, free memory, and close file */ + ret += gz_comp(state, Z_FINISH); + (void)deflateEnd(&(state->strm)); + free(state->out); + free(state->in); + gz_error(state, Z_OK, NULL); + free(state->path); + ret += close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/src/depend/libs/zlib/infback.c b/src/depend/libs/zlib/infback.c new file mode 100644 index 00000000..af3a8c96 --- /dev/null +++ b/src/depend/libs/zlib/infback.c @@ -0,0 +1,632 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/src/depend/libs/zlib/inffast.c b/src/depend/libs/zlib/inffast.c new file mode 100644 index 00000000..2f1d60b4 --- /dev/null +++ b/src/depend/libs/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/src/depend/libs/zlib/inffast.h b/src/depend/libs/zlib/inffast.h new file mode 100644 index 00000000..e5c1aa4c --- /dev/null +++ b/src/depend/libs/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/src/depend/libs/zlib/inffixed.h b/src/depend/libs/zlib/inffixed.h new file mode 100644 index 00000000..75ed4b59 --- /dev/null +++ b/src/depend/libs/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/src/depend/libs/zlib/inflate.c b/src/depend/libs/zlib/inflate.c new file mode 100644 index 00000000..a8431abe --- /dev/null +++ b/src/depend/libs/zlib/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/src/depend/libs/zlib/inflate.h b/src/depend/libs/zlib/inflate.h new file mode 100644 index 00000000..95f4986d --- /dev/null +++ b/src/depend/libs/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/src/depend/libs/zlib/inftrees.c b/src/depend/libs/zlib/inftrees.c new file mode 100644 index 00000000..11e9c52a --- /dev/null +++ b/src/depend/libs/zlib/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/src/depend/libs/zlib/inftrees.h b/src/depend/libs/zlib/inftrees.h new file mode 100644 index 00000000..baa53a0b --- /dev/null +++ b/src/depend/libs/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/depend/libs/zlib/trees.c b/src/depend/libs/zlib/trees.c new file mode 100644 index 00000000..56e9bb1c --- /dev/null +++ b/src/depend/libs/zlib/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/src/depend/libs/zlib/trees.h b/src/depend/libs/zlib/trees.h new file mode 100644 index 00000000..d35639d8 --- /dev/null +++ b/src/depend/libs/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/src/depend/libs/zlib/uncompr.c b/src/depend/libs/zlib/uncompr.c new file mode 100644 index 00000000..ad98be3a --- /dev/null +++ b/src/depend/libs/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/src/depend/libs/zlib/zconf.h b/src/depend/libs/zlib/zconf.h new file mode 100644 index 00000000..02ce56c4 --- /dev/null +++ b/src/depend/libs/zlib/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/src/depend/libs/zlib/zconf.h.in b/src/depend/libs/zlib/zconf.h.in new file mode 100644 index 00000000..02ce56c4 --- /dev/null +++ b/src/depend/libs/zlib/zconf.h.in @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/src/depend/libs/zlib/zlib.h b/src/depend/libs/zlib/zlib.h new file mode 100644 index 00000000..bfbba83e --- /dev/null +++ b/src/depend/libs/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/src/depend/libs/zlib/zutil.c b/src/depend/libs/zlib/zutil.c new file mode 100644 index 00000000..898ed345 --- /dev/null +++ b/src/depend/libs/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/src/depend/libs/zlib/zutil.h b/src/depend/libs/zlib/zutil.h new file mode 100644 index 00000000..258fa887 --- /dev/null +++ b/src/depend/libs/zlib/zutil.h @@ -0,0 +1,274 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/src/depend/mingw/include/directx9/d3dx9.h b/src/depend/mingw/include/directx9/d3dx9.h new file mode 100644 index 00000000..ec5fc84c --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9.h @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9.h +// Content: D3DX utility library +// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __D3DX_INTERNAL__ +#error Incorrect D3DX header used +#endif + +#ifndef __D3DX9_H__ +#define __D3DX9_H__ + + +// Defines +#include + +#define D3DX_DEFAULT ((UINT) -1) +#define D3DX_DEFAULT_NONPOW2 ((UINT) -2) +#define D3DX_DEFAULT_FLOAT FLT_MAX +#define D3DX_FROM_FILE ((UINT) -3) +#define D3DFMT_FROM_FILE ((D3DFORMAT) -3) + +#ifndef D3DXINLINE +#ifdef _MSC_VER + #if (_MSC_VER >= 1200) + #define D3DXINLINE __forceinline + #else + #define D3DXINLINE __inline + #endif +#else + #ifdef __cplusplus + #define D3DXINLINE inline + #else + #define D3DXINLINE + #endif +#endif +#endif + + + +// Includes +#include "d3d9.h" +#include "d3dx9math.h" +#include "d3dx9core.h" +#include "d3dx9xof.h" +#include "d3dx9mesh.h" +#include "d3dx9shader.h" +#include "d3dx9effect.h" + +#include "d3dx9tex.h" +#include "d3dx9shape.h" +#include "d3dx9anim.h" + + + +// Errors +#define _FACDD 0x876 +#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) + +enum _D3DXERR { + D3DXERR_CANNOTMODIFYINDEXBUFFER = MAKE_DDHRESULT(2900), + D3DXERR_INVALIDMESH = MAKE_DDHRESULT(2901), + D3DXERR_CANNOTATTRSORT = MAKE_DDHRESULT(2902), + D3DXERR_SKINNINGNOTSUPPORTED = MAKE_DDHRESULT(2903), + D3DXERR_TOOMANYINFLUENCES = MAKE_DDHRESULT(2904), + D3DXERR_INVALIDDATA = MAKE_DDHRESULT(2905), + D3DXERR_LOADEDMESHASNODATA = MAKE_DDHRESULT(2906), + D3DXERR_DUPLICATENAMEDFRAGMENT = MAKE_DDHRESULT(2907), + D3DXERR_CANNOTREMOVELASTITEM = MAKE_DDHRESULT(2908) +}; + + +#endif //__D3DX9_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9anim.h b/src/depend/mingw/include/directx9/d3dx9anim.h new file mode 100644 index 00000000..966f539c --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9anim.h @@ -0,0 +1,1114 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9anim.h +// Content: D3DX mesh types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3DX9ANIM_H__ +#define __D3DX9ANIM_H__ + +// {698CFB3F-9289-4d95-9A57-33A94B5A65F9} +DEFINE_GUID(IID_ID3DXAnimationSet, +0x698cfb3f, 0x9289, 0x4d95, 0x9a, 0x57, 0x33, 0xa9, 0x4b, 0x5a, 0x65, 0xf9); + +// {FA4E8E3A-9786-407d-8B4C-5995893764AF} +DEFINE_GUID(IID_ID3DXKeyframedAnimationSet, +0xfa4e8e3a, 0x9786, 0x407d, 0x8b, 0x4c, 0x59, 0x95, 0x89, 0x37, 0x64, 0xaf); + +// {6CC2480D-3808-4739-9F88-DE49FACD8D4C} +DEFINE_GUID(IID_ID3DXCompressedAnimationSet, +0x6cc2480d, 0x3808, 0x4739, 0x9f, 0x88, 0xde, 0x49, 0xfa, 0xcd, 0x8d, 0x4c); + +// {AC8948EC-F86D-43e2-96DE-31FC35F96D9E} +DEFINE_GUID(IID_ID3DXAnimationController, +0xac8948ec, 0xf86d, 0x43e2, 0x96, 0xde, 0x31, 0xfc, 0x35, 0xf9, 0x6d, 0x9e); + + +//---------------------------------------------------------------------------- +// D3DXMESHDATATYPE: +// ----------------- +// This enum defines the type of mesh data present in a MeshData structure. +//---------------------------------------------------------------------------- +typedef enum _D3DXMESHDATATYPE { + D3DXMESHTYPE_MESH = 0x001, // Normal ID3DXMesh data + D3DXMESHTYPE_PMESH = 0x002, // Progressive Mesh - ID3DXPMesh + D3DXMESHTYPE_PATCHMESH = 0x003, // Patch Mesh - ID3DXPatchMesh + + D3DXMESHTYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXMESHDATATYPE; + +//---------------------------------------------------------------------------- +// D3DXMESHDATA: +// ------------- +// This struct encapsulates a the mesh data that can be present in a mesh +// container. The supported mesh types are pMesh, pPMesh, pPatchMesh. +// The valid way to access this is determined by the Type enum. +//---------------------------------------------------------------------------- +typedef struct _D3DXMESHDATA +{ + D3DXMESHDATATYPE Type; + + // current mesh data interface + union + { + LPD3DXMESH pMesh; + LPD3DXPMESH pPMesh; + LPD3DXPATCHMESH pPatchMesh; + }; +} D3DXMESHDATA, *LPD3DXMESHDATA; + +//---------------------------------------------------------------------------- +// D3DXMESHCONTAINER: +// ------------------ +// This struct encapsulates a mesh object in a transformation frame +// hierarchy. The app can derive from this structure to add other app specific +// data to this. +//---------------------------------------------------------------------------- +typedef struct _D3DXMESHCONTAINER +{ + LPSTR Name; + + D3DXMESHDATA MeshData; + + LPD3DXMATERIAL pMaterials; + LPD3DXEFFECTINSTANCE pEffects; + DWORD NumMaterials; + DWORD *pAdjacency; + + LPD3DXSKININFO pSkinInfo; + + struct _D3DXMESHCONTAINER *pNextMeshContainer; +} D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER; + +//---------------------------------------------------------------------------- +// D3DXFRAME: +// ---------- +// This struct is the encapsulates a transform frame in a transformation frame +// hierarchy. The app can derive from this structure to add other app specific +// data to this +//---------------------------------------------------------------------------- +typedef struct _D3DXFRAME +{ + LPSTR Name; + D3DXMATRIX TransformationMatrix; + + LPD3DXMESHCONTAINER pMeshContainer; + + struct _D3DXFRAME *pFrameSibling; + struct _D3DXFRAME *pFrameFirstChild; +} D3DXFRAME, *LPD3DXFRAME; + + +//---------------------------------------------------------------------------- +// ID3DXAllocateHierarchy: +// ----------------------- +// This interface is implemented by the application to allocate/free frame and +// mesh container objects. Methods on this are called during loading and +// destroying frame hierarchies +//---------------------------------------------------------------------------- +typedef interface ID3DXAllocateHierarchy ID3DXAllocateHierarchy; +typedef interface ID3DXAllocateHierarchy *LPD3DXALLOCATEHIERARCHY; + +#undef INTERFACE +#define INTERFACE ID3DXAllocateHierarchy + +DECLARE_INTERFACE(ID3DXAllocateHierarchy) +{ + // ID3DXAllocateHierarchy + + //------------------------------------------------------------------------ + // CreateFrame: + // ------------ + // Requests allocation of a frame object. + // + // Parameters: + // Name + // Name of the frame to be created + // ppNewFrame + // Returns the created frame object + // + //------------------------------------------------------------------------ + STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, + LPD3DXFRAME *ppNewFrame) PURE; + + //------------------------------------------------------------------------ + // CreateMeshContainer: + // -------------------- + // Requests allocation of a mesh container object. + // + // Parameters: + // Name + // Name of the mesh + // pMesh + // Pointer to the mesh object if basic polygon data found + // pPMesh + // Pointer to the progressive mesh object if progressive mesh data found + // pPatchMesh + // Pointer to the patch mesh object if patch data found + // pMaterials + // Array of materials used in the mesh + // pEffectInstances + // Array of effect instances used in the mesh + // NumMaterials + // Num elements in the pMaterials array + // pAdjacency + // Adjacency array for the mesh + // pSkinInfo + // Pointer to the skininfo object if the mesh is skinned + // pBoneNames + // Array of names, one for each bone in the skinned mesh. + // The numberof bones can be found from the pSkinMesh object + // pBoneOffsetMatrices + // Array of matrices, one for each bone in the skinned mesh. + // + //------------------------------------------------------------------------ + STDMETHOD(CreateMeshContainer)(THIS_ + LPCSTR Name, + CONST D3DXMESHDATA *pMeshData, + CONST D3DXMATERIAL *pMaterials, + CONST D3DXEFFECTINSTANCE *pEffectInstances, + DWORD NumMaterials, + CONST DWORD *pAdjacency, + LPD3DXSKININFO pSkinInfo, + LPD3DXMESHCONTAINER *ppNewMeshContainer) PURE; + + //------------------------------------------------------------------------ + // DestroyFrame: + // ------------- + // Requests de-allocation of a frame object. + // + // Parameters: + // pFrameToFree + // Pointer to the frame to be de-allocated + // + //------------------------------------------------------------------------ + STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree) PURE; + + //------------------------------------------------------------------------ + // DestroyMeshContainer: + // --------------------- + // Requests de-allocation of a mesh container object. + // + // Parameters: + // pMeshContainerToFree + // Pointer to the mesh container object to be de-allocated + // + //------------------------------------------------------------------------ + STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerToFree) PURE; +}; + +//---------------------------------------------------------------------------- +// ID3DXLoadUserData: +// ------------------ +// This interface is implemented by the application to load user data in a .X file +// When user data is found, these callbacks will be used to allow the application +// to load the data. +//---------------------------------------------------------------------------- +typedef interface ID3DXLoadUserData ID3DXLoadUserData; +typedef interface ID3DXLoadUserData *LPD3DXLOADUSERDATA; + +#undef INTERFACE +#define INTERFACE ID3DXLoadUserData + +DECLARE_INTERFACE(ID3DXLoadUserData) +{ + STDMETHOD(LoadTopLevelData)(LPD3DXFILEDATA pXofChildData) PURE; + + STDMETHOD(LoadFrameChildData)(LPD3DXFRAME pFrame, + LPD3DXFILEDATA pXofChildData) PURE; + + STDMETHOD(LoadMeshChildData)(LPD3DXMESHCONTAINER pMeshContainer, + LPD3DXFILEDATA pXofChildData) PURE; +}; + +//---------------------------------------------------------------------------- +// ID3DXSaveUserData: +// ------------------ +// This interface is implemented by the application to save user data in a .X file +// The callbacks are called for all data saved. The user can then add any +// child data objects to the object provided to the callback. +//---------------------------------------------------------------------------- +typedef interface ID3DXSaveUserData ID3DXSaveUserData; +typedef interface ID3DXSaveUserData *LPD3DXSAVEUSERDATA; + +#undef INTERFACE +#define INTERFACE ID3DXSaveUserData + +DECLARE_INTERFACE(ID3DXSaveUserData) +{ + STDMETHOD(AddFrameChildData)(CONST D3DXFRAME *pFrame, + LPD3DXFILESAVEOBJECT pXofSave, + LPD3DXFILESAVEDATA pXofFrameData) PURE; + + STDMETHOD(AddMeshChildData)(CONST D3DXMESHCONTAINER *pMeshContainer, + LPD3DXFILESAVEOBJECT pXofSave, + LPD3DXFILESAVEDATA pXofMeshData) PURE; + + // NOTE: this is called once per Save. All top level objects should be added using the + // provided interface. One call adds objects before the frame hierarchy, the other after + STDMETHOD(AddTopLevelDataObjectsPre)(LPD3DXFILESAVEOBJECT pXofSave) PURE; + STDMETHOD(AddTopLevelDataObjectsPost)(LPD3DXFILESAVEOBJECT pXofSave) PURE; + + // callbacks for the user to register and then save templates to the XFile + STDMETHOD(RegisterTemplates)(LPD3DXFILE pXFileApi) PURE; + STDMETHOD(SaveTemplates)(LPD3DXFILESAVEOBJECT pXofSave) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXCALLBACK_SEARCH_FLAGS: +// -------------------------- +// Flags that can be passed into ID3DXAnimationSet::GetCallback. +//---------------------------------------------------------------------------- +typedef enum _D3DXCALLBACK_SEARCH_FLAGS +{ + D3DXCALLBACK_SEARCH_EXCLUDING_INITIAL_POSITION = 0x01, // exclude callbacks at the initial position from the search + D3DXCALLBACK_SEARCH_BEHIND_INITIAL_POSITION = 0x02, // reverse the callback search direction + + D3DXCALLBACK_SEARCH_FORCE_DWORD = 0x7fffffff +} D3DXCALLBACK_SEARCH_FLAGS; + +//---------------------------------------------------------------------------- +// ID3DXAnimationSet: +// ------------------ +// This interface implements an animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationSet ID3DXAnimationSet; +typedef interface ID3DXAnimationSet *LPD3DXANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationSet + +DECLARE_INTERFACE_(ID3DXAnimationSet, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer +}; + + +//---------------------------------------------------------------------------- +// D3DXPLAYBACK_TYPE: +// ------------------ +// This enum defines the type of animation set loop modes. +//---------------------------------------------------------------------------- +typedef enum _D3DXPLAYBACK_TYPE +{ + D3DXPLAY_LOOP = 0, + D3DXPLAY_ONCE = 1, + D3DXPLAY_PINGPONG = 2, + + D3DXPLAY_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXPLAYBACK_TYPE; + + +//---------------------------------------------------------------------------- +// D3DXKEY_VECTOR3: +// ---------------- +// This structure describes a vector key for use in keyframe animation. +// It specifies a vector Value at a given Time. This is used for scale and +// translation keys. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_VECTOR3 +{ + FLOAT Time; + D3DXVECTOR3 Value; +} D3DXKEY_VECTOR3, *LPD3DXKEY_VECTOR3; + + +//---------------------------------------------------------------------------- +// D3DXKEY_QUATERNION: +// ------------------- +// This structure describes a quaternion key for use in keyframe animation. +// It specifies a quaternion Value at a given Time. This is used for rotation +// keys. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_QUATERNION +{ + FLOAT Time; + D3DXQUATERNION Value; +} D3DXKEY_QUATERNION, *LPD3DXKEY_QUATERNION; + + +//---------------------------------------------------------------------------- +// D3DXKEY_CALLBACK: +// ----------------- +// This structure describes an callback key for use in keyframe animation. +// It specifies a pointer to user data at a given Time. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_CALLBACK +{ + FLOAT Time; + LPVOID pCallbackData; +} D3DXKEY_CALLBACK, *LPD3DXKEY_CALLBACK; + + +//---------------------------------------------------------------------------- +// D3DXCOMPRESSION_FLAGS: +// ---------------------- +// Flags that can be passed into ID3DXKeyframedAnimationSet::Compress. +//---------------------------------------------------------------------------- +typedef enum _D3DXCOMPRESSION_FLAGS +{ + D3DXCOMPRESS_DEFAULT = 0x00, + + D3DXCOMPRESS_FORCE_DWORD = 0x7fffffff +} D3DXCOMPRESSION_FLAGS; + + +//---------------------------------------------------------------------------- +// ID3DXKeyframedAnimationSet: +// --------------------------- +// This interface implements a compressable keyframed animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXKeyframedAnimationSet ID3DXKeyframedAnimationSet; +typedef interface ID3DXKeyframedAnimationSet *LPD3DXKEYFRAMEDANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXKeyframedAnimationSet + +DECLARE_INTERFACE_(ID3DXKeyframedAnimationSet, ID3DXAnimationSet) +{ + // ID3DXAnimationSet + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer + + // Playback + STDMETHOD_(D3DXPLAYBACK_TYPE, GetPlaybackType)(THIS) PURE; + STDMETHOD_(DOUBLE, GetSourceTicksPerSecond)(THIS) PURE; + + // Scale keys + STDMETHOD_(UINT, GetNumScaleKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetScaleKeys)(THIS_ UINT Animation, LPD3DXKEY_VECTOR3 pScaleKeys) PURE; + STDMETHOD(GetScaleKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pScaleKey) PURE; + STDMETHOD(SetScaleKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pScaleKey) PURE; + + // Rotation keys + STDMETHOD_(UINT, GetNumRotationKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetRotationKeys)(THIS_ UINT Animation, LPD3DXKEY_QUATERNION pRotationKeys) PURE; + STDMETHOD(GetRotationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_QUATERNION pRotationKey) PURE; + STDMETHOD(SetRotationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_QUATERNION pRotationKey) PURE; + + // Translation keys + STDMETHOD_(UINT, GetNumTranslationKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetTranslationKeys)(THIS_ UINT Animation, LPD3DXKEY_VECTOR3 pTranslationKeys) PURE; + STDMETHOD(GetTranslationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pTranslationKey) PURE; + STDMETHOD(SetTranslationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pTranslationKey) PURE; + + // Callback keys + STDMETHOD_(UINT, GetNumCallbackKeys)(THIS) PURE; + STDMETHOD(GetCallbackKeys)(THIS_ LPD3DXKEY_CALLBACK pCallbackKeys) PURE; + STDMETHOD(GetCallbackKey)(THIS_ UINT Key, LPD3DXKEY_CALLBACK pCallbackKey) PURE; + STDMETHOD(SetCallbackKey)(THIS_ UINT Key, LPD3DXKEY_CALLBACK pCallbackKey) PURE; + + // Key removal methods. These are slow, and should not be used once the animation starts playing + STDMETHOD(UnregisterScaleKey)(THIS_ UINT Animation, UINT Key) PURE; + STDMETHOD(UnregisterRotationKey)(THIS_ UINT Animation, UINT Key) PURE; + STDMETHOD(UnregisterTranslationKey)(THIS_ UINT Animation, UINT Key) PURE; + + // One-time animaton SRT keyframe registration + STDMETHOD(RegisterAnimationSRTKeys)(THIS_ + LPCSTR pName, // Animation name + UINT NumScaleKeys, // Number of scale keys + UINT NumRotationKeys, // Number of rotation keys + UINT NumTranslationKeys, // Number of translation keys + CONST D3DXKEY_VECTOR3 *pScaleKeys, // Array of scale keys + CONST D3DXKEY_QUATERNION *pRotationKeys, // Array of rotation keys + CONST D3DXKEY_VECTOR3 *pTranslationKeys, // Array of translation keys + DWORD *pAnimationIndex) PURE; // Returns the animation index + + // Compression + STDMETHOD(Compress)(THIS_ + DWORD Flags, // Compression flags (use D3DXCOMPRESS_STRONG for better results) + FLOAT Lossiness, // Compression loss ratio in the [0, 1] range + LPD3DXFRAME pHierarchy, // Frame hierarchy (optional) + LPD3DXBUFFER *ppCompressedData) PURE; // Returns the compressed animation set + + STDMETHOD(UnregisterAnimation)(THIS_ UINT Index) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXCompressedAnimationSet: +// ---------------------------- +// This interface implements a compressed keyframed animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXCompressedAnimationSet ID3DXCompressedAnimationSet; +typedef interface ID3DXCompressedAnimationSet *LPD3DXCOMPRESSEDANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXCompressedAnimationSet + +DECLARE_INTERFACE_(ID3DXCompressedAnimationSet, ID3DXAnimationSet) +{ + // ID3DXAnimationSet + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer + + // Playback + STDMETHOD_(D3DXPLAYBACK_TYPE, GetPlaybackType)(THIS) PURE; + STDMETHOD_(DOUBLE, GetSourceTicksPerSecond)(THIS) PURE; + + // Scale keys + STDMETHOD(GetCompressedData)(THIS_ LPD3DXBUFFER *ppCompressedData) PURE; + + // Callback keys + STDMETHOD_(UINT, GetNumCallbackKeys)(THIS) PURE; + STDMETHOD(GetCallbackKeys)(THIS_ LPD3DXKEY_CALLBACK pCallbackKeys) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXPRIORITY_TYPE: +// ------------------ +// This enum defines the type of priority group that a track can be assigned to. +//---------------------------------------------------------------------------- +typedef enum _D3DXPRIORITY_TYPE { + D3DXPRIORITY_LOW = 0, // This track should be blended with all low priority tracks before mixed with the high priority result + D3DXPRIORITY_HIGH = 1, // This track should be blended with all high priority tracks before mixed with the low priority result + + D3DXPRIORITY_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXPRIORITY_TYPE; + +//---------------------------------------------------------------------------- +// D3DXTRACK_DESC: +// --------------- +// This structure describes the mixing information of an animation track. +// The mixing information consists of the current position, speed, and blending +// weight for the track. The Flags field also specifies whether the track is +// low or high priority. Tracks with the same priority are blended together +// and then the two resulting values are blended using the priority blend factor. +// A track also has an animation set (stored separately) associated with it. +//---------------------------------------------------------------------------- +typedef struct _D3DXTRACK_DESC +{ + D3DXPRIORITY_TYPE Priority; + FLOAT Weight; + FLOAT Speed; + DOUBLE Position; + BOOL Enable; +} D3DXTRACK_DESC, *LPD3DXTRACK_DESC; + +//---------------------------------------------------------------------------- +// D3DXEVENT_TYPE: +// --------------- +// This enum defines the type of events keyable via the animation controller. +//---------------------------------------------------------------------------- +typedef enum _D3DXEVENT_TYPE +{ + D3DXEVENT_TRACKSPEED = 0, + D3DXEVENT_TRACKWEIGHT = 1, + D3DXEVENT_TRACKPOSITION = 2, + D3DXEVENT_TRACKENABLE = 3, + D3DXEVENT_PRIORITYBLEND = 4, + + D3DXEVENT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXEVENT_TYPE; + +//---------------------------------------------------------------------------- +// D3DXTRANSITION_TYPE: +// -------------------- +// This enum defines the type of transtion performed on a event that +// transitions from one value to another. +//---------------------------------------------------------------------------- +typedef enum _D3DXTRANSITION_TYPE { + D3DXTRANSITION_LINEAR = 0x000, // Linear transition from one value to the next + D3DXTRANSITION_EASEINEASEOUT = 0x001, // Ease-In Ease-Out spline transtion from one value to the next + + D3DXTRANSITION_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXTRANSITION_TYPE; + +//---------------------------------------------------------------------------- +// D3DXEVENT_DESC: +// --------------- +// This structure describes a animation controller event. +// It gives the event's type, track (if the event is a track event), global +// start time, duration, transition method, and target value. +//---------------------------------------------------------------------------- +typedef struct _D3DXEVENT_DESC +{ + D3DXEVENT_TYPE Type; + UINT Track; + DOUBLE StartTime; + DOUBLE Duration; + D3DXTRANSITION_TYPE Transition; + union + { + FLOAT Weight; + FLOAT Speed; + DOUBLE Position; + BOOL Enable; + }; +} D3DXEVENT_DESC, *LPD3DXEVENT_DESC; + +//---------------------------------------------------------------------------- +// D3DXEVENTHANDLE: +// ---------------- +// Handle values used to efficiently reference animation controller events. +//---------------------------------------------------------------------------- +typedef DWORD D3DXEVENTHANDLE; +typedef D3DXEVENTHANDLE *LPD3DXEVENTHANDLE; + + +//---------------------------------------------------------------------------- +// ID3DXAnimationCallbackHandler: +// ------------------------------ +// This interface is intended to be implemented by the application, and can +// be used to handle callbacks in animation sets generated when +// ID3DXAnimationController::AdvanceTime() is called. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationCallbackHandler ID3DXAnimationCallbackHandler; +typedef interface ID3DXAnimationCallbackHandler *LPD3DXANIMATIONCALLBACKHANDLER; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationCallbackHandler + +DECLARE_INTERFACE(ID3DXAnimationCallbackHandler) +{ + //---------------------------------------------------------------------------- + // ID3DXAnimationCallbackHandler::HandleCallback: + // ---------------------------------------------- + // This method gets called when a callback occurs for an animation set in one + // of the tracks during the ID3DXAnimationController::AdvanceTime() call. + // + // Parameters: + // Track + // Index of the track on which the callback occured. + // pCallbackData + // Pointer to user owned callback data. + // + //---------------------------------------------------------------------------- + STDMETHOD(HandleCallback)(THIS_ UINT Track, LPVOID pCallbackData) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXAnimationController: +// ------------------------- +// This interface implements the main animation functionality. It connects +// animation sets with the transform frames that are being animated. Allows +// mixing multiple animations for blended animations or for transistions +// It adds also has methods to modify blending parameters over time to +// enable smooth transistions and other effects. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationController ID3DXAnimationController; +typedef interface ID3DXAnimationController *LPD3DXANIMATIONCONTROLLER; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationController + +DECLARE_INTERFACE_(ID3DXAnimationController, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Max sizes + STDMETHOD_(UINT, GetMaxNumAnimationOutputs)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumAnimationSets)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumTracks)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumEvents)(THIS) PURE; + + // Animation output registration + STDMETHOD(RegisterAnimationOutput)(THIS_ + LPCSTR pName, + D3DXMATRIX *pMatrix, + D3DXVECTOR3 *pScale, + D3DXQUATERNION *pRotation, + D3DXVECTOR3 *pTranslation) PURE; + + // Animation set registration + STDMETHOD(RegisterAnimationSet)(THIS_ LPD3DXANIMATIONSET pAnimSet) PURE; + STDMETHOD(UnregisterAnimationSet)(THIS_ LPD3DXANIMATIONSET pAnimSet) PURE; + + STDMETHOD_(UINT, GetNumAnimationSets)(THIS) PURE; + STDMETHOD(GetAnimationSet)(THIS_ UINT Index, LPD3DXANIMATIONSET *ppAnimationSet) PURE; + STDMETHOD(GetAnimationSetByName)(THIS_ LPCSTR szName, LPD3DXANIMATIONSET *ppAnimationSet) PURE; + + // Global time + STDMETHOD(AdvanceTime)(THIS_ DOUBLE TimeDelta, LPD3DXANIMATIONCALLBACKHANDLER pCallbackHandler) PURE; + STDMETHOD(ResetTime)(THIS) PURE; + STDMETHOD_(DOUBLE, GetTime)(THIS) PURE; + + // Tracks + STDMETHOD(SetTrackAnimationSet)(THIS_ UINT Track, LPD3DXANIMATIONSET pAnimSet) PURE; + STDMETHOD(GetTrackAnimationSet)(THIS_ UINT Track, LPD3DXANIMATIONSET *ppAnimSet) PURE; + + STDMETHOD(SetTrackPriority)(THIS_ UINT Track, D3DXPRIORITY_TYPE Priority) PURE; + + STDMETHOD(SetTrackSpeed)(THIS_ UINT Track, FLOAT Speed) PURE; + STDMETHOD(SetTrackWeight)(THIS_ UINT Track, FLOAT Weight) PURE; + STDMETHOD(SetTrackPosition)(THIS_ UINT Track, DOUBLE Position) PURE; + STDMETHOD(SetTrackEnable)(THIS_ UINT Track, BOOL Enable) PURE; + + STDMETHOD(SetTrackDesc)(THIS_ UINT Track, LPD3DXTRACK_DESC pDesc) PURE; + STDMETHOD(GetTrackDesc)(THIS_ UINT Track, LPD3DXTRACK_DESC pDesc) PURE; + + // Priority blending + STDMETHOD(SetPriorityBlend)(THIS_ FLOAT BlendWeight) PURE; + STDMETHOD_(FLOAT, GetPriorityBlend)(THIS) PURE; + + // Event keying + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackSpeed)(THIS_ UINT Track, FLOAT NewSpeed, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackWeight)(THIS_ UINT Track, FLOAT NewWeight, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackPosition)(THIS_ UINT Track, DOUBLE NewPosition, DOUBLE StartTime) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackEnable)(THIS_ UINT Track, BOOL NewEnable, DOUBLE StartTime) PURE; + + STDMETHOD_(D3DXEVENTHANDLE, KeyPriorityBlend)(THIS_ FLOAT NewBlendWeight, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + + // Event unkeying + STDMETHOD(UnkeyEvent)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(UnkeyAllTrackEvents)(THIS_ UINT Track) PURE; + STDMETHOD(UnkeyAllPriorityBlends)(THIS) PURE; + + // Event enumeration + STDMETHOD_(D3DXEVENTHANDLE, GetCurrentTrackEvent)(THIS_ UINT Track, D3DXEVENT_TYPE EventType) PURE; + STDMETHOD_(D3DXEVENTHANDLE, GetCurrentPriorityBlend)(THIS) PURE; + + STDMETHOD_(D3DXEVENTHANDLE, GetUpcomingTrackEvent)(THIS_ UINT Track, D3DXEVENTHANDLE hEvent) PURE; + STDMETHOD_(D3DXEVENTHANDLE, GetUpcomingPriorityBlend)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(ValidateEvent)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(GetEventDesc)(THIS_ D3DXEVENTHANDLE hEvent, LPD3DXEVENT_DESC pDesc) PURE; + + // Cloning + STDMETHOD(CloneAnimationController)(THIS_ + UINT MaxNumAnimationOutputs, + UINT MaxNumAnimationSets, + UINT MaxNumTracks, + UINT MaxNumEvents, + LPD3DXANIMATIONCONTROLLER *ppAnimController) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//---------------------------------------------------------------------------- +// D3DXLoadMeshHierarchyFromX: +// --------------------------- +// Loads the first frame hierarchy in a .X file. +// +// Parameters: +// Filename +// Name of the .X file +// MeshOptions +// Mesh creation options for meshes in the file (see d3dx9mesh.h) +// pD3DDevice +// D3D9 device on which meshes in the file are created in +// pAlloc +// Allocation interface used to allocate nodes of the frame hierarchy +// pUserDataLoader +// Application provided interface to allow loading of user data +// ppFrameHierarchy +// Returns root node pointer of the loaded frame hierarchy +// ppAnimController +// Returns pointer to an animation controller corresponding to animation +// in the .X file. This is created with default max tracks and events +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXA + ( + LPCSTR Filename, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXW + ( + LPCWSTR Filename, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +#ifdef UNICODE +#define D3DXLoadMeshHierarchyFromX D3DXLoadMeshHierarchyFromXW +#else +#define D3DXLoadMeshHierarchyFromX D3DXLoadMeshHierarchyFromXA +#endif + +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXInMemory + ( + LPCVOID Memory, + DWORD SizeOfMemory, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +//---------------------------------------------------------------------------- +// D3DXSaveMeshHierarchyToFile: +// ---------------------------- +// Creates a .X file and saves the mesh hierarchy and corresponding animations +// in it +// +// Parameters: +// Filename +// Name of the .X file +// XFormat +// Format of the .X file (text or binary, compressed or not, etc) +// pFrameRoot +// Root node of the hierarchy to be saved +// pAnimController +// The animation controller whose animation sets are to be stored +// pUserDataSaver +// Application provided interface to allow adding of user data to +// data objects saved to .X file +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXSaveMeshHierarchyToFileA + ( + LPCSTR Filename, + DWORD XFormat, + CONST D3DXFRAME *pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimcontroller, + LPD3DXSAVEUSERDATA pUserDataSaver + ); + +HRESULT WINAPI +D3DXSaveMeshHierarchyToFileW + ( + LPCWSTR Filename, + DWORD XFormat, + CONST D3DXFRAME *pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimController, + LPD3DXSAVEUSERDATA pUserDataSaver + ); + +#ifdef UNICODE +#define D3DXSaveMeshHierarchyToFile D3DXSaveMeshHierarchyToFileW +#else +#define D3DXSaveMeshHierarchyToFile D3DXSaveMeshHierarchyToFileA +#endif + +//---------------------------------------------------------------------------- +// D3DXFrameDestroy: +// ----------------- +// Destroys the subtree of frames under the root, including the root +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pAlloc +// Allocation interface used to de-allocate nodes of the frame hierarchy +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameDestroy + ( + LPD3DXFRAME pFrameRoot, + LPD3DXALLOCATEHIERARCHY pAlloc + ); + +//---------------------------------------------------------------------------- +// D3DXFrameAppendChild: +// --------------------- +// Add a child frame to a frame +// +// Parameters: +// pFrameParent +// Pointer to the parent node +// pFrameChild +// Pointer to the child node +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameAppendChild + ( + LPD3DXFRAME pFrameParent, + CONST D3DXFRAME *pFrameChild + ); + +//---------------------------------------------------------------------------- +// D3DXFrameFind: +// -------------- +// Finds a frame with the given name. Returns NULL if no frame found. +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// Name +// Name of frame to find +// +//---------------------------------------------------------------------------- +LPD3DXFRAME WINAPI +D3DXFrameFind + ( + CONST D3DXFRAME *pFrameRoot, + LPCSTR Name + ); + +//---------------------------------------------------------------------------- +// D3DXFrameRegisterNamedMatrices: +// ------------------------------- +// Finds all frames that have non-null names and registers each of those frame +// matrices to the given animation controller +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pAnimController +// Pointer to the animation controller where the matrices are registered +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameRegisterNamedMatrices + ( + LPD3DXFRAME pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimController + ); + +//---------------------------------------------------------------------------- +// D3DXFrameNumNamedMatrices: +// -------------------------- +// Counts number of frames in a subtree that have non-null names +// +// Parameters: +// pFrameRoot +// Pointer to the root node of the subtree +// Return Value: +// Count of frames +// +//---------------------------------------------------------------------------- +UINT WINAPI +D3DXFrameNumNamedMatrices + ( + CONST D3DXFRAME *pFrameRoot + ); + +//---------------------------------------------------------------------------- +// D3DXFrameCalculateBoundingSphere: +// --------------------------------- +// Computes the bounding sphere of all the meshes in the frame hierarchy. +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pObjectCenter +// Returns the center of the bounding sphere +// pObjectRadius +// Returns the radius of the bounding sphere +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameCalculateBoundingSphere + ( + CONST D3DXFRAME *pFrameRoot, + LPD3DXVECTOR3 pObjectCenter, + FLOAT *pObjectRadius + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateKeyframedAnimationSet: +// -------------------------------- +// This function creates a compressable keyframed animations set interface. +// +// Parameters: +// pName +// Name of the animation set +// TicksPerSecond +// Number of keyframe ticks that elapse per second +// Playback +// Playback mode of keyframe looping +// NumAnimations +// Number of SRT animations +// NumCallbackKeys +// Number of callback keys +// pCallbackKeys +// Array of callback keys +// ppAnimationSet +// Returns the animation set interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateKeyframedAnimationSet + ( + LPCSTR pName, + DOUBLE TicksPerSecond, + D3DXPLAYBACK_TYPE Playback, + UINT NumAnimations, + UINT NumCallbackKeys, + CONST D3DXKEY_CALLBACK *pCallbackKeys, + LPD3DXKEYFRAMEDANIMATIONSET *ppAnimationSet + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateCompressedAnimationSet: +// -------------------------------- +// This function creates a compressed animations set interface from +// compressed data. +// +// Parameters: +// pName +// Name of the animation set +// TicksPerSecond +// Number of keyframe ticks that elapse per second +// Playback +// Playback mode of keyframe looping +// pCompressedData +// Compressed animation SRT data +// NumCallbackKeys +// Number of callback keys +// pCallbackKeys +// Array of callback keys +// ppAnimationSet +// Returns the animation set interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateCompressedAnimationSet + ( + LPCSTR pName, + DOUBLE TicksPerSecond, + D3DXPLAYBACK_TYPE Playback, + LPD3DXBUFFER pCompressedData, + UINT NumCallbackKeys, + CONST D3DXKEY_CALLBACK *pCallbackKeys, + LPD3DXCOMPRESSEDANIMATIONSET *ppAnimationSet + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateAnimationController: +// ------------------------------ +// This function creates an animation controller object. +// +// Parameters: +// MaxNumMatrices +// Maximum number of matrices that can be animated +// MaxNumAnimationSets +// Maximum number of animation sets that can be played +// MaxNumTracks +// Maximum number of animation sets that can be blended +// MaxNumEvents +// Maximum number of outstanding events that can be scheduled at any given time +// ppAnimController +// Returns the animation controller interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateAnimationController + ( + UINT MaxNumMatrices, + UINT MaxNumAnimationSets, + UINT MaxNumTracks, + UINT MaxNumEvents, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9ANIM_H__ + + diff --git a/src/depend/mingw/include/directx9/d3dx9core.h b/src/depend/mingw/include/directx9/d3dx9core.h new file mode 100644 index 00000000..77f46ec1 --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9core.h @@ -0,0 +1,754 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9core.h +// Content: D3DX core types and functions +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9CORE_H__ +#define __D3DX9CORE_H__ + + +/////////////////////////////////////////////////////////////////////////// +// D3DX_SDK_VERSION: +// ----------------- +// This identifier is passed to D3DXCheckVersion in order to ensure that an +// application was built against the correct header files and lib files. +// This number is incremented whenever a header (or other) change would +// require applications to be rebuilt. If the version doesn't match, +// D3DXCheckVersion will return FALSE. (The number itself has no meaning.) +/////////////////////////////////////////////////////////////////////////// + +#define D3DX_VERSION 0x0902 + +#define D3DX_SDK_VERSION 43 + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +BOOL WINAPI + D3DXCheckVersion(UINT D3DSdkVersion, UINT D3DXSdkVersion); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// D3DXDebugMute +// Mutes D3DX and D3D debug spew (TRUE - mute, FALSE - not mute) +// +// returns previous mute value +// +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +BOOL WINAPI + D3DXDebugMute(BOOL Mute); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +/////////////////////////////////////////////////////////////////////////// +// D3DXGetDriverLevel: +// Returns driver version information: +// +// 700 - DX7 level driver +// 800 - DX8 level driver +// 900 - DX9 level driver +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +UINT WINAPI + D3DXGetDriverLevel(LPDIRECT3DDEVICE9 pDevice); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXBuffer: +// ------------ +// The buffer object is used by D3DX to return arbitrary size data. +// +// GetBufferPointer - +// Returns a pointer to the beginning of the buffer. +// +// GetBufferSize - +// Returns the size of the buffer, in bytes. +/////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXBuffer ID3DXBuffer; +typedef interface ID3DXBuffer *LPD3DXBUFFER; + +// {8BA5FB08-5195-40e2-AC58-0D989C3A0102} +DEFINE_GUID(IID_ID3DXBuffer, +0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2); + +#undef INTERFACE +#define INTERFACE ID3DXBuffer + +DECLARE_INTERFACE_(ID3DXBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBuffer + STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE; + STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE; +}; + + + +////////////////////////////////////////////////////////////////////////////// +// D3DXSPRITE flags: +// ----------------- +// D3DXSPRITE_DONOTSAVESTATE +// Specifies device state is not to be saved and restored in Begin/End. +// D3DXSPRITE_DONOTMODIFY_RENDERSTATE +// Specifies device render state is not to be changed in Begin. The device +// is assumed to be in a valid state to draw vertices containing POSITION0, +// TEXCOORD0, and COLOR0 data. +// D3DXSPRITE_OBJECTSPACE +// The WORLD, VIEW, and PROJECTION transforms are NOT modified. The +// transforms currently set to the device are used to transform the sprites +// when the batch is drawn (at Flush or End). If this is not specified, +// WORLD, VIEW, and PROJECTION transforms are modified so that sprites are +// drawn in screenspace coordinates. +// D3DXSPRITE_BILLBOARD +// Rotates each sprite about its center so that it is facing the viewer. +// D3DXSPRITE_ALPHABLEND +// Enables ALPHABLEND(SRCALPHA, INVSRCALPHA) and ALPHATEST(alpha > 0). +// ID3DXFont expects this to be set when drawing text. +// D3DXSPRITE_SORT_TEXTURE +// Sprites are sorted by texture prior to drawing. This is recommended when +// drawing non-overlapping sprites of uniform depth. For example, drawing +// screen-aligned text with ID3DXFont. +// D3DXSPRITE_SORT_DEPTH_FRONTTOBACK +// Sprites are sorted by depth front-to-back prior to drawing. This is +// recommended when drawing opaque sprites of varying depths. +// D3DXSPRITE_SORT_DEPTH_BACKTOFRONT +// Sprites are sorted by depth back-to-front prior to drawing. This is +// recommended when drawing transparent sprites of varying depths. +// D3DXSPRITE_DO_NOT_ADDREF_TEXTURE +// Disables calling AddRef() on every draw, and Release() on Flush() for +// better performance. +////////////////////////////////////////////////////////////////////////////// + +#define D3DXSPRITE_DONOTSAVESTATE (1 << 0) +#define D3DXSPRITE_DONOTMODIFY_RENDERSTATE (1 << 1) +#define D3DXSPRITE_OBJECTSPACE (1 << 2) +#define D3DXSPRITE_BILLBOARD (1 << 3) +#define D3DXSPRITE_ALPHABLEND (1 << 4) +#define D3DXSPRITE_SORT_TEXTURE (1 << 5) +#define D3DXSPRITE_SORT_DEPTH_FRONTTOBACK (1 << 6) +#define D3DXSPRITE_SORT_DEPTH_BACKTOFRONT (1 << 7) +#define D3DXSPRITE_DO_NOT_ADDREF_TEXTURE (1 << 8) + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXSprite: +// ------------ +// This object intends to provide an easy way to drawing sprites using D3D. +// +// Begin - +// Prepares device for drawing sprites. +// +// Draw - +// Draws a sprite. Before transformation, the sprite is the size of +// SrcRect, with its top-left corner specified by Position. The color +// and alpha channels are modulated by Color. +// +// Flush - +// Forces all batched sprites to submitted to the device. +// +// End - +// Restores device state to how it was when Begin was called. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXSprite ID3DXSprite; +typedef interface ID3DXSprite *LPD3DXSPRITE; + + +// {BA0B762D-7D28-43ec-B9DC-2F84443B0614} +DEFINE_GUID(IID_ID3DXSprite, +0xba0b762d, 0x7d28, 0x43ec, 0xb9, 0xdc, 0x2f, 0x84, 0x44, 0x3b, 0x6, 0x14); + + +#undef INTERFACE +#define INTERFACE ID3DXSprite + +DECLARE_INTERFACE_(ID3DXSprite, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXSprite + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + + STDMETHOD(GetTransform)(THIS_ D3DXMATRIX *pTransform) PURE; + STDMETHOD(SetTransform)(THIS_ CONST D3DXMATRIX *pTransform) PURE; + + STDMETHOD(SetWorldViewRH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) PURE; + STDMETHOD(SetWorldViewLH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) PURE; + + STDMETHOD(Begin)(THIS_ DWORD Flags) PURE; + STDMETHOD(Draw)(THIS_ LPDIRECT3DTEXTURE9 pTexture, CONST RECT *pSrcRect, CONST D3DXVECTOR3 *pCenter, CONST D3DXVECTOR3 *pPosition, D3DCOLOR Color) PURE; + STDMETHOD(Flush)(THIS) PURE; + STDMETHOD(End)(THIS) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateSprite( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXSPRITE* ppSprite); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFont: +// ---------- +// Font objects contain the textures and resources needed to render a specific +// font on a specific device. +// +// GetGlyphData - +// Returns glyph cache data, for a given glyph. +// +// PreloadCharacters/PreloadGlyphs/PreloadText - +// Preloads glyphs into the glyph cache textures. +// +// DrawText - +// Draws formatted text on a D3D device. Some parameters are +// surprisingly similar to those of GDI's DrawText function. See GDI +// documentation for a detailed description of these parameters. +// If pSprite is NULL, an internal sprite object will be used. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +////////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXFONT_DESCA +{ + INT Height; + UINT Width; + UINT Weight; + UINT MipLevels; + BOOL Italic; + BYTE CharSet; + BYTE OutputPrecision; + BYTE Quality; + BYTE PitchAndFamily; + CHAR FaceName[LF_FACESIZE]; + +} D3DXFONT_DESCA, *LPD3DXFONT_DESCA; + +typedef struct _D3DXFONT_DESCW +{ + INT Height; + UINT Width; + UINT Weight; + UINT MipLevels; + BOOL Italic; + BYTE CharSet; + BYTE OutputPrecision; + BYTE Quality; + BYTE PitchAndFamily; + WCHAR FaceName[LF_FACESIZE]; + +} D3DXFONT_DESCW, *LPD3DXFONT_DESCW; + +#ifdef UNICODE +typedef D3DXFONT_DESCW D3DXFONT_DESC; +typedef LPD3DXFONT_DESCW LPD3DXFONT_DESC; +#else +typedef D3DXFONT_DESCA D3DXFONT_DESC; +typedef LPD3DXFONT_DESCA LPD3DXFONT_DESC; +#endif + + +typedef interface ID3DXFont ID3DXFont; +typedef interface ID3DXFont *LPD3DXFONT; + + +// {D79DBB70-5F21-4d36-BBC2-FF525C213CDC} +DEFINE_GUID(IID_ID3DXFont, +0xd79dbb70, 0x5f21, 0x4d36, 0xbb, 0xc2, 0xff, 0x52, 0x5c, 0x21, 0x3c, 0xdc); + + +#undef INTERFACE +#define INTERFACE ID3DXFont + +DECLARE_INTERFACE_(ID3DXFont, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXFont + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9 *ppDevice) PURE; + STDMETHOD(GetDescA)(THIS_ D3DXFONT_DESCA *pDesc) PURE; + STDMETHOD(GetDescW)(THIS_ D3DXFONT_DESCW *pDesc) PURE; + STDMETHOD_(BOOL, GetTextMetricsA)(THIS_ TEXTMETRICA *pTextMetrics) PURE; + STDMETHOD_(BOOL, GetTextMetricsW)(THIS_ TEXTMETRICW *pTextMetrics) PURE; + + STDMETHOD_(HDC, GetDC)(THIS) PURE; + STDMETHOD(GetGlyphData)(THIS_ UINT Glyph, LPDIRECT3DTEXTURE9 *ppTexture, RECT *pBlackBox, POINT *pCellInc) PURE; + + STDMETHOD(PreloadCharacters)(THIS_ UINT First, UINT Last) PURE; + STDMETHOD(PreloadGlyphs)(THIS_ UINT First, UINT Last) PURE; + STDMETHOD(PreloadTextA)(THIS_ LPCSTR pString, INT Count) PURE; + STDMETHOD(PreloadTextW)(THIS_ LPCWSTR pString, INT Count) PURE; + + STDMETHOD_(INT, DrawTextA)(THIS_ LPD3DXSPRITE pSprite, LPCSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE; + STDMETHOD_(INT, DrawTextW)(THIS_ LPD3DXSPRITE pSprite, LPCWSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; + +#ifdef __cplusplus +#ifdef UNICODE + HRESULT GetDesc(D3DXFONT_DESCW *pDesc) { return GetDescW(pDesc); } + HRESULT PreloadText(LPCWSTR pString, INT Count) { return PreloadTextW(pString, Count); } +#else + HRESULT GetDesc(D3DXFONT_DESCA *pDesc) { return GetDescA(pDesc); } + HRESULT PreloadText(LPCSTR pString, INT Count) { return PreloadTextA(pString, Count); } +#endif +#endif //__cplusplus +}; + +#ifndef GetTextMetrics +#ifdef UNICODE +#define GetTextMetrics GetTextMetricsW +#else +#define GetTextMetrics GetTextMetricsA +#endif +#endif + +#ifndef DrawText +#ifdef UNICODE +#define DrawText DrawTextW +#else +#define DrawText DrawTextA +#endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateFontA( + LPDIRECT3DDEVICE9 pDevice, + INT Height, + UINT Width, + UINT Weight, + UINT MipLevels, + BOOL Italic, + DWORD CharSet, + DWORD OutputPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCSTR pFaceName, + LPD3DXFONT* ppFont); + +HRESULT WINAPI + D3DXCreateFontW( + LPDIRECT3DDEVICE9 pDevice, + INT Height, + UINT Width, + UINT Weight, + UINT MipLevels, + BOOL Italic, + DWORD CharSet, + DWORD OutputPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCWSTR pFaceName, + LPD3DXFONT* ppFont); + +#ifdef UNICODE +#define D3DXCreateFont D3DXCreateFontW +#else +#define D3DXCreateFont D3DXCreateFontA +#endif + + +HRESULT WINAPI + D3DXCreateFontIndirectA( + LPDIRECT3DDEVICE9 pDevice, + CONST D3DXFONT_DESCA* pDesc, + LPD3DXFONT* ppFont); + +HRESULT WINAPI + D3DXCreateFontIndirectW( + LPDIRECT3DDEVICE9 pDevice, + CONST D3DXFONT_DESCW* pDesc, + LPD3DXFONT* ppFont); + +#ifdef UNICODE +#define D3DXCreateFontIndirect D3DXCreateFontIndirectW +#else +#define D3DXCreateFontIndirect D3DXCreateFontIndirectA +#endif + + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXRenderToSurface: +// --------------------- +// This object abstracts rendering to surfaces. These surfaces do not +// necessarily need to be render targets. If they are not, a compatible +// render target is used, and the result copied into surface at end scene. +// +// BeginScene, EndScene - +// Call BeginScene() and EndScene() at the beginning and ending of your +// scene. These calls will setup and restore render targets, viewports, +// etc.. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXRTS_DESC +{ + UINT Width; + UINT Height; + D3DFORMAT Format; + BOOL DepthStencil; + D3DFORMAT DepthStencilFormat; + +} D3DXRTS_DESC, *LPD3DXRTS_DESC; + + +typedef interface ID3DXRenderToSurface ID3DXRenderToSurface; +typedef interface ID3DXRenderToSurface *LPD3DXRENDERTOSURFACE; + + +// {6985F346-2C3D-43b3-BE8B-DAAE8A03D894} +DEFINE_GUID(IID_ID3DXRenderToSurface, +0x6985f346, 0x2c3d, 0x43b3, 0xbe, 0x8b, 0xda, 0xae, 0x8a, 0x3, 0xd8, 0x94); + + +#undef INTERFACE +#define INTERFACE ID3DXRenderToSurface + +DECLARE_INTERFACE_(ID3DXRenderToSurface, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXRenderToSurface + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(GetDesc)(THIS_ D3DXRTS_DESC* pDesc) PURE; + + STDMETHOD(BeginScene)(THIS_ LPDIRECT3DSURFACE9 pSurface, CONST D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(EndScene)(THIS_ DWORD MipFilter) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateRenderToSurface( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + D3DFORMAT Format, + BOOL DepthStencil, + D3DFORMAT DepthStencilFormat, + LPD3DXRENDERTOSURFACE* ppRenderToSurface); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXRenderToEnvMap: +// -------------------- +// This object abstracts rendering to environment maps. These surfaces +// do not necessarily need to be render targets. If they are not, a +// compatible render target is used, and the result copied into the +// environment map at end scene. +// +// BeginCube, BeginSphere, BeginHemisphere, BeginParabolic - +// This function initiates the rendering of the environment map. As +// parameters, you pass the textures in which will get filled in with +// the resulting environment map. +// +// Face - +// Call this function to initiate the drawing of each face. For each +// environment map, you will call this six times.. once for each face +// in D3DCUBEMAP_FACES. +// +// End - +// This will restore all render targets, and if needed compose all the +// rendered faces into the environment map surfaces. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXRTE_DESC +{ + UINT Size; + UINT MipLevels; + D3DFORMAT Format; + BOOL DepthStencil; + D3DFORMAT DepthStencilFormat; + +} D3DXRTE_DESC, *LPD3DXRTE_DESC; + + +typedef interface ID3DXRenderToEnvMap ID3DXRenderToEnvMap; +typedef interface ID3DXRenderToEnvMap *LPD3DXRenderToEnvMap; + + +// {313F1B4B-C7B0-4fa2-9D9D-8D380B64385E} +DEFINE_GUID(IID_ID3DXRenderToEnvMap, +0x313f1b4b, 0xc7b0, 0x4fa2, 0x9d, 0x9d, 0x8d, 0x38, 0xb, 0x64, 0x38, 0x5e); + + +#undef INTERFACE +#define INTERFACE ID3DXRenderToEnvMap + +DECLARE_INTERFACE_(ID3DXRenderToEnvMap, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXRenderToEnvMap + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(GetDesc)(THIS_ D3DXRTE_DESC* pDesc) PURE; + + STDMETHOD(BeginCube)(THIS_ + LPDIRECT3DCUBETEXTURE9 pCubeTex) PURE; + + STDMETHOD(BeginSphere)(THIS_ + LPDIRECT3DTEXTURE9 pTex) PURE; + + STDMETHOD(BeginHemisphere)(THIS_ + LPDIRECT3DTEXTURE9 pTexZPos, + LPDIRECT3DTEXTURE9 pTexZNeg) PURE; + + STDMETHOD(BeginParabolic)(THIS_ + LPDIRECT3DTEXTURE9 pTexZPos, + LPDIRECT3DTEXTURE9 pTexZNeg) PURE; + + STDMETHOD(Face)(THIS_ D3DCUBEMAP_FACES Face, DWORD MipFilter) PURE; + STDMETHOD(End)(THIS_ DWORD MipFilter) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateRenderToEnvMap( + LPDIRECT3DDEVICE9 pDevice, + UINT Size, + UINT MipLevels, + D3DFORMAT Format, + BOOL DepthStencil, + D3DFORMAT DepthStencilFormat, + LPD3DXRenderToEnvMap* ppRenderToEnvMap); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXLine: +// ------------ +// This object intends to provide an easy way to draw lines using D3D. +// +// Begin - +// Prepares device for drawing lines +// +// Draw - +// Draws a line strip in screen-space. +// Input is in the form of a array defining points on the line strip. of D3DXVECTOR2 +// +// DrawTransform - +// Draws a line in screen-space with a specified input transformation matrix. +// +// End - +// Restores device state to how it was when Begin was called. +// +// SetPattern - +// Applies a stipple pattern to the line. Input is one 32-bit +// DWORD which describes the stipple pattern. 1 is opaque, 0 is +// transparent. +// +// SetPatternScale - +// Stretches the stipple pattern in the u direction. Input is one +// floating-point value. 0.0f is no scaling, whereas 1.0f doubles +// the length of the stipple pattern. +// +// SetWidth - +// Specifies the thickness of the line in the v direction. Input is +// one floating-point value. +// +// SetAntialias - +// Toggles line antialiasing. Input is a BOOL. +// TRUE = Antialiasing on. +// FALSE = Antialiasing off. +// +// SetGLLines - +// Toggles non-antialiased OpenGL line emulation. Input is a BOOL. +// TRUE = OpenGL line emulation on. +// FALSE = OpenGL line emulation off. +// +// OpenGL line: Regular line: +/* +// .\ .\ +// | \ / \ +// | \ .\ \ +// .\ \ \ \ +// \ \ \ \ +// \ . \ . +// \ | \ / +// \| . +// . +*/ +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + + +typedef interface ID3DXLine ID3DXLine; +typedef interface ID3DXLine *LPD3DXLINE; + + +// {D379BA7F-9042-4ac4-9F5E-58192A4C6BD8} +DEFINE_GUID(IID_ID3DXLine, +0xd379ba7f, 0x9042, 0x4ac4, 0x9f, 0x5e, 0x58, 0x19, 0x2a, 0x4c, 0x6b, 0xd8); + +#undef INTERFACE +#define INTERFACE ID3DXLine + +DECLARE_INTERFACE_(ID3DXLine, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXLine + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + + STDMETHOD(Begin)(THIS) PURE; + + STDMETHOD(Draw)(THIS_ CONST D3DXVECTOR2 *pVertexList, + DWORD dwVertexListCount, D3DCOLOR Color) PURE; + + STDMETHOD(DrawTransform)(THIS_ CONST D3DXVECTOR3 *pVertexList, + DWORD dwVertexListCount, CONST D3DXMATRIX* pTransform, + D3DCOLOR Color) PURE; + + STDMETHOD(SetPattern)(THIS_ DWORD dwPattern) PURE; + STDMETHOD_(DWORD, GetPattern)(THIS) PURE; + + STDMETHOD(SetPatternScale)(THIS_ FLOAT fPatternScale) PURE; + STDMETHOD_(FLOAT, GetPatternScale)(THIS) PURE; + + STDMETHOD(SetWidth)(THIS_ FLOAT fWidth) PURE; + STDMETHOD_(FLOAT, GetWidth)(THIS) PURE; + + STDMETHOD(SetAntialias)(THIS_ BOOL bAntialias) PURE; + STDMETHOD_(BOOL, GetAntialias)(THIS) PURE; + + STDMETHOD(SetGLLines)(THIS_ BOOL bGLLines) PURE; + STDMETHOD_(BOOL, GetGLLines)(THIS) PURE; + + STDMETHOD(End)(THIS) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateLine( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXLINE* ppLine); + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9CORE_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9effect.h b/src/depend/mingw/include/directx9/d3dx9effect.h new file mode 100644 index 00000000..a3bcd307 --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9effect.h @@ -0,0 +1,873 @@ + +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File: d3dx9effect.h +// Content: D3DX effect types and Shaders +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9EFFECT_H__ +#define __D3DX9EFFECT_H__ + + +//---------------------------------------------------------------------------- +// D3DXFX_DONOTSAVESTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, device state is not saved or restored in Begin/End. +// D3DXFX_DONOTSAVESHADERSTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, shader device state is not saved or restored in Begin/End. +// This includes pixel/vertex shaders and shader constants +// D3DXFX_DONOTSAVESAMPLERSTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, sampler device state is not saved or restored in Begin/End. +// D3DXFX_NOT_CLONEABLE +// This flag is used as a parameter to the D3DXCreateEffect family of APIs. +// When this flag is specified, the effect will be non-cloneable and will not +// contain any shader binary data. +// Furthermore, GetPassDesc will not return shader function pointers. +// Setting this flag reduces effect memory usage by about 50%. +//---------------------------------------------------------------------------- + +#define D3DXFX_DONOTSAVESTATE (1 << 0) +#define D3DXFX_DONOTSAVESHADERSTATE (1 << 1) +#define D3DXFX_DONOTSAVESAMPLERSTATE (1 << 2) + +#define D3DXFX_NOT_CLONEABLE (1 << 11) +#define D3DXFX_LARGEADDRESSAWARE (1 << 17) + +//---------------------------------------------------------------------------- +// D3DX_PARAMETER_SHARED +// Indicates that the value of a parameter will be shared with all effects +// which share the same namespace. Changing the value in one effect will +// change it in all. +// +// D3DX_PARAMETER_LITERAL +// Indicates that the value of this parameter can be treated as literal. +// Literal parameters can be marked when the effect is compiled, and their +// cannot be changed after the effect is compiled. Shared parameters cannot +// be literal. +//---------------------------------------------------------------------------- + +#define D3DX_PARAMETER_SHARED (1 << 0) +#define D3DX_PARAMETER_LITERAL (1 << 1) +#define D3DX_PARAMETER_ANNOTATION (1 << 2) + +//---------------------------------------------------------------------------- +// D3DXEFFECT_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXEFFECT_DESC +{ + LPCSTR Creator; // Creator string + UINT Parameters; // Number of parameters + UINT Techniques; // Number of techniques + UINT Functions; // Number of function entrypoints + +} D3DXEFFECT_DESC; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXPARAMETER_DESC +{ + LPCSTR Name; // Parameter name + LPCSTR Semantic; // Parameter semantic + D3DXPARAMETER_CLASS Class; // Class + D3DXPARAMETER_TYPE Type; // Component type + UINT Rows; // Number of rows + UINT Columns; // Number of columns + UINT Elements; // Number of array elements + UINT Annotations; // Number of annotations + UINT StructMembers; // Number of structure member sub-parameters + DWORD Flags; // D3DX_PARAMETER_* flags + UINT Bytes; // Parameter size, in bytes + +} D3DXPARAMETER_DESC; + + +//---------------------------------------------------------------------------- +// D3DXTECHNIQUE_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXTECHNIQUE_DESC +{ + LPCSTR Name; // Technique name + UINT Passes; // Number of passes + UINT Annotations; // Number of annotations + +} D3DXTECHNIQUE_DESC; + + +//---------------------------------------------------------------------------- +// D3DXPASS_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXPASS_DESC +{ + LPCSTR Name; // Pass name + UINT Annotations; // Number of annotations + + CONST DWORD *pVertexShaderFunction; // Vertex shader function + CONST DWORD *pPixelShaderFunction; // Pixel shader function + +} D3DXPASS_DESC; + + +//---------------------------------------------------------------------------- +// D3DXFUNCTION_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXFUNCTION_DESC +{ + LPCSTR Name; // Function name + UINT Annotations; // Number of annotations + +} D3DXFUNCTION_DESC; + + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffectPool /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffectPool ID3DXEffectPool; +typedef interface ID3DXEffectPool *LPD3DXEFFECTPOOL; + +// {9537AB04-3250-412e-8213-FCD2F8677933} +DEFINE_GUID(IID_ID3DXEffectPool, +0x9537ab04, 0x3250, 0x412e, 0x82, 0x13, 0xfc, 0xd2, 0xf8, 0x67, 0x79, 0x33); + + +#undef INTERFACE +#define INTERFACE ID3DXEffectPool + +DECLARE_INTERFACE_(ID3DXEffectPool, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // No public methods +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXBaseEffect /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXBaseEffect ID3DXBaseEffect; +typedef interface ID3DXBaseEffect *LPD3DXBASEEFFECT; + +// {017C18AC-103F-4417-8C51-6BF6EF1E56BE} +DEFINE_GUID(IID_ID3DXBaseEffect, +0x17c18ac, 0x103f, 0x4417, 0x8c, 0x51, 0x6b, 0xf6, 0xef, 0x1e, 0x56, 0xbe); + + +#undef INTERFACE +#define INTERFACE ID3DXBaseEffect + +DECLARE_INTERFACE_(ID3DXBaseEffect, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Useful for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + +}; + + +//---------------------------------------------------------------------------- +// ID3DXEffectStateManager: +// ------------------------ +// This is a user implemented interface that can be used to manage device +// state changes made by an Effect. +//---------------------------------------------------------------------------- + +typedef interface ID3DXEffectStateManager ID3DXEffectStateManager; +typedef interface ID3DXEffectStateManager *LPD3DXEFFECTSTATEMANAGER; + +// {79AAB587-6DBC-4fa7-82DE-37FA1781C5CE} +DEFINE_GUID(IID_ID3DXEffectStateManager, +0x79aab587, 0x6dbc, 0x4fa7, 0x82, 0xde, 0x37, 0xfa, 0x17, 0x81, 0xc5, 0xce); + +#undef INTERFACE +#define INTERFACE ID3DXEffectStateManager + +DECLARE_INTERFACE_(ID3DXEffectStateManager, IUnknown) +{ + // The user must correctly implement QueryInterface, AddRef, and Release. + + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // The following methods are called by the Effect when it wants to make + // the corresponding device call. Note that: + // 1. Users manage the state and are therefore responsible for making the + // the corresponding device calls themselves inside their callbacks. + // 2. Effects pay attention to the return values of the callbacks, and so + // users must pay attention to what they return in their callbacks. + + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix) PURE; + STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9 *pMaterial) PURE; + STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9 *pLight) PURE; + STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) PURE; + STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) PURE; + STDMETHOD(SetTexture)(THIS_ DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) PURE; + STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) PURE; + STDMETHOD(SetNPatchMode)(THIS_ FLOAT NumSegments) PURE; + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(SetVertexShader)(THIS_ LPDIRECT3DVERTEXSHADER9 pShader) PURE; + STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShader)(THIS_ LPDIRECT3DPIXELSHADER9 pShader) PURE; + STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffect /////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffect ID3DXEffect; +typedef interface ID3DXEffect *LPD3DXEFFECT; + +// {F6CEB4B3-4E4C-40dd-B883-8D8DE5EA0CD5} +DEFINE_GUID(IID_ID3DXEffect, +0xf6ceb4b3, 0x4e4c, 0x40dd, 0xb8, 0x83, 0x8d, 0x8d, 0xe5, 0xea, 0xc, 0xd5); + +#undef INTERFACE +#define INTERFACE ID3DXEffect + +DECLARE_INTERFACE_(ID3DXEffect, ID3DXBaseEffect) +{ + // ID3DXBaseEffect + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Usefull for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + // ID3DXBaseEffect + + + // Pool + STDMETHOD(GetPool)(THIS_ LPD3DXEFFECTPOOL* ppPool) PURE; + + // Selecting and setting a technique + STDMETHOD(SetTechnique)(THIS_ D3DXHANDLE hTechnique) PURE; + STDMETHOD_(D3DXHANDLE, GetCurrentTechnique)(THIS) PURE; + STDMETHOD(ValidateTechnique)(THIS_ D3DXHANDLE hTechnique) PURE; + STDMETHOD(FindNextValidTechnique)(THIS_ D3DXHANDLE hTechnique, D3DXHANDLE *pTechnique) PURE; + STDMETHOD_(BOOL, IsParameterUsed)(THIS_ D3DXHANDLE hParameter, D3DXHANDLE hTechnique) PURE; + + // Using current technique + // Begin starts active technique + // BeginPass begins a pass + // CommitChanges updates changes to any set calls in the pass. This should be called before + // any DrawPrimitive call to d3d + // EndPass ends a pass + // End ends active technique + STDMETHOD(Begin)(THIS_ UINT *pPasses, DWORD Flags) PURE; + STDMETHOD(BeginPass)(THIS_ UINT Pass) PURE; + STDMETHOD(CommitChanges)(THIS) PURE; + STDMETHOD(EndPass)(THIS) PURE; + STDMETHOD(End)(THIS) PURE; + + // Managing D3D Device + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; + + // Logging device calls + STDMETHOD(SetStateManager)(THIS_ LPD3DXEFFECTSTATEMANAGER pManager) PURE; + STDMETHOD(GetStateManager)(THIS_ LPD3DXEFFECTSTATEMANAGER *ppManager) PURE; + + // Parameter blocks + STDMETHOD(BeginParameterBlock)(THIS) PURE; + STDMETHOD_(D3DXHANDLE, EndParameterBlock)(THIS) PURE; + STDMETHOD(ApplyParameterBlock)(THIS_ D3DXHANDLE hParameterBlock) PURE; + STDMETHOD(DeleteParameterBlock)(THIS_ D3DXHANDLE hParameterBlock) PURE; + + // Cloning + STDMETHOD(CloneEffect)(THIS_ LPDIRECT3DDEVICE9 pDevice, LPD3DXEFFECT* ppEffect) PURE; + + // Fast path for setting variables directly in ID3DXEffect + STDMETHOD(SetRawValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT ByteOffset, UINT Bytes) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffectCompiler /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffectCompiler ID3DXEffectCompiler; +typedef interface ID3DXEffectCompiler *LPD3DXEFFECTCOMPILER; + +// {51B8A949-1A31-47e6-BEA0-4B30DB53F1E0} +DEFINE_GUID(IID_ID3DXEffectCompiler, +0x51b8a949, 0x1a31, 0x47e6, 0xbe, 0xa0, 0x4b, 0x30, 0xdb, 0x53, 0xf1, 0xe0); + + +#undef INTERFACE +#define INTERFACE ID3DXEffectCompiler + +DECLARE_INTERFACE_(ID3DXEffectCompiler, ID3DXBaseEffect) +{ + // ID3DXBaseEffect + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Usefull for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + // ID3DXBaseEffect + + // Parameter sharing, specialization, and information + STDMETHOD(SetLiteral)(THIS_ D3DXHANDLE hParameter, BOOL Literal) PURE; + STDMETHOD(GetLiteral)(THIS_ D3DXHANDLE hParameter, BOOL *pLiteral) PURE; + + // Compilation + STDMETHOD(CompileEffect)(THIS_ DWORD Flags, + LPD3DXBUFFER* ppEffect, LPD3DXBUFFER* ppErrorMsgs) PURE; + + STDMETHOD(CompileShader)(THIS_ D3DXHANDLE hFunction, LPCSTR pTarget, DWORD Flags, + LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// APIs ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//---------------------------------------------------------------------------- +// D3DXCreateEffectPool: +// --------------------- +// Creates an effect pool. Pools are used for sharing parameters between +// multiple effects. For all effects within a pool, shared parameters of the +// same name all share the same value. +// +// Parameters: +// ppPool +// Returns the created pool. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectPool( + LPD3DXEFFECTPOOL* ppPool); + + +//---------------------------------------------------------------------------- +// D3DXCreateEffect: +// ----------------- +// Creates an effect from an ascii or binary effect description. +// +// Parameters: +// pDevice +// Pointer of the device on which to create the effect +// pSrcFile +// Name of the file containing the effect description +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to effect description +// SrcDataSize +// Size of the effect description in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// Flags +// See D3DXSHADER_xxx flags. +// pSkipConstants +// A list of semi-colon delimited variable names. The effect will +// not set these variables to the device when they are referenced +// by a shader. NOTE: the variables specified here must be +// register bound in the file and must not be used in expressions +// in passes or samplers or the file will not load. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pPool +// Pointer to ID3DXEffectPool object to use for shared parameters. +// If NULL, no parameters will be shared. +// ppEffect +// Returns a buffer containing created effect. +// ppCompilationErrors +// Returns a buffer containing any error messages which occurred during +// compile. Or NULL if you do not care about the error messages. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromFile D3DXCreateEffectFromFileW +#else +#define D3DXCreateEffectFromFile D3DXCreateEffectFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateEffectFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromResource D3DXCreateEffectFromResourceW +#else +#define D3DXCreateEffectFromResource D3DXCreateEffectFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateEffect( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +// +// Ex functions that accept pSkipConstants in addition to other parameters +// + +HRESULT WINAPI + D3DXCreateEffectFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromFileEx D3DXCreateEffectFromFileExW +#else +#define D3DXCreateEffectFromFileEx D3DXCreateEffectFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateEffectFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromResourceEx D3DXCreateEffectFromResourceExW +#else +#define D3DXCreateEffectFromResourceEx D3DXCreateEffectFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateEffectEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +//---------------------------------------------------------------------------- +// D3DXCreateEffectCompiler: +// ------------------------- +// Creates an effect from an ascii or binary effect description. +// +// Parameters: +// pSrcFile +// Name of the file containing the effect description +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to effect description +// SrcDataSize +// Size of the effect description in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pPool +// Pointer to ID3DXEffectPool object to use for shared parameters. +// If NULL, no parameters will be shared. +// ppCompiler +// Returns a buffer containing created effect compiler. +// ppParseErrors +// Returns a buffer containing any error messages which occurred during +// parse. Or NULL if you do not care about the error messages. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectCompilerFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +HRESULT WINAPI + D3DXCreateEffectCompilerFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +#ifdef UNICODE +#define D3DXCreateEffectCompilerFromFile D3DXCreateEffectCompilerFromFileW +#else +#define D3DXCreateEffectCompilerFromFile D3DXCreateEffectCompilerFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateEffectCompilerFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +HRESULT WINAPI + D3DXCreateEffectCompilerFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +#ifdef UNICODE +#define D3DXCreateEffectCompilerFromResource D3DXCreateEffectCompilerFromResourceW +#else +#define D3DXCreateEffectCompilerFromResource D3DXCreateEffectCompilerFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateEffectCompiler( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +//---------------------------------------------------------------------------- +// D3DXDisassembleEffect: +// ----------------------- +// +// Parameters: +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXDisassembleEffect( + LPD3DXEFFECT pEffect, + BOOL EnableColorCode, + LPD3DXBUFFER *ppDisassembly); + + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9EFFECT_H__ + + diff --git a/src/depend/mingw/include/directx9/d3dx9math.h b/src/depend/mingw/include/directx9/d3dx9math.h new file mode 100644 index 00000000..86206136 --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9math.h @@ -0,0 +1,1798 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9math.h +// Content: D3DX math types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9MATH_H__ +#define __D3DX9MATH_H__ + +#include +//#if _MSC_VER >= 1200 +//#pragma warning(push) +//#endif +//#pragma warning(disable:4201) // anonymous unions warning + +#if __GNUC__ >= 4 +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +//=========================================================================== +// +// General purpose utilities +// +//=========================================================================== +#define D3DX_PI ((FLOAT) 3.141592654f) +#define D3DX_1BYPI ((FLOAT) 0.318309886f) + +#define D3DXToRadian( degree ) ((degree) * (D3DX_PI / 180.0f)) +#define D3DXToDegree( radian ) ((radian) * (180.0f / D3DX_PI)) + + + +//=========================================================================== +// +// 16 bit floating point numbers +// +//=========================================================================== + +#define D3DX_16F_DIG 3 // # of decimal digits of precision +#define D3DX_16F_EPSILON 4.8875809e-4f // smallest such that 1.0 + epsilon != 1.0 +#define D3DX_16F_MANT_DIG 11 // # of bits in mantissa +#define D3DX_16F_MAX 6.550400e+004 // max value +#define D3DX_16F_MAX_10_EXP 4 // max decimal exponent +#define D3DX_16F_MAX_EXP 15 // max binary exponent +#define D3DX_16F_MIN 6.1035156e-5f // min positive value +#define D3DX_16F_MIN_10_EXP (-4) // min decimal exponent +#define D3DX_16F_MIN_EXP (-14) // min binary exponent +#define D3DX_16F_RADIX 2 // exponent radix +#define D3DX_16F_ROUNDS 1 // addition rounding: near + + +typedef struct D3DXFLOAT16 +{ +#ifdef __cplusplus +public: + D3DXFLOAT16() {}; + D3DXFLOAT16( FLOAT ); + D3DXFLOAT16( CONST D3DXFLOAT16& ); + + // casting + operator FLOAT (); + + // binary operators + BOOL operator == ( CONST D3DXFLOAT16& ) const; + BOOL operator != ( CONST D3DXFLOAT16& ) const; + +protected: +#endif //__cplusplus + WORD value; +} D3DXFLOAT16, *LPD3DXFLOAT16; + + + +//=========================================================================== +// +// Vectors +// +//=========================================================================== + + +//-------------------------- +// 2D Vector +//-------------------------- +typedef struct D3DXVECTOR2 +{ +#ifdef __cplusplus +public: + D3DXVECTOR2() {}; + D3DXVECTOR2( CONST FLOAT * ); + D3DXVECTOR2( CONST D3DXFLOAT16 * ); + D3DXVECTOR2( FLOAT x, FLOAT y ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR2& operator += ( CONST D3DXVECTOR2& ); + D3DXVECTOR2& operator -= ( CONST D3DXVECTOR2& ); + D3DXVECTOR2& operator *= ( FLOAT ); + D3DXVECTOR2& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR2 operator + () const; + D3DXVECTOR2 operator - () const; + + // binary operators + D3DXVECTOR2 operator + ( CONST D3DXVECTOR2& ) const; + D3DXVECTOR2 operator - ( CONST D3DXVECTOR2& ) const; + D3DXVECTOR2 operator * ( FLOAT ) const; + D3DXVECTOR2 operator / ( FLOAT ) const; + + friend D3DXVECTOR2 operator * ( FLOAT, CONST D3DXVECTOR2& ); + + BOOL operator == ( CONST D3DXVECTOR2& ) const; + BOOL operator != ( CONST D3DXVECTOR2& ) const; + + +public: +#endif //__cplusplus + FLOAT x, y; +} D3DXVECTOR2, *LPD3DXVECTOR2; + + + +//-------------------------- +// 2D Vector (16 bit) +//-------------------------- + +typedef struct D3DXVECTOR2_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR2_16F() {}; + D3DXVECTOR2_16F( CONST FLOAT * ); + D3DXVECTOR2_16F( CONST D3DXFLOAT16 * ); + D3DXVECTOR2_16F( CONST D3DXFLOAT16 &x, CONST D3DXFLOAT16 &y ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR2_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR2_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y; + +} D3DXVECTOR2_16F, *LPD3DXVECTOR2_16F; + + + +//-------------------------- +// 3D Vector +//-------------------------- +#ifdef __cplusplus +typedef struct D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {}; + D3DXVECTOR3( CONST FLOAT * ); + D3DXVECTOR3( CONST D3DVECTOR& ); + D3DXVECTOR3( CONST D3DXFLOAT16 * ); + D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR3& operator += ( CONST D3DXVECTOR3& ); + D3DXVECTOR3& operator -= ( CONST D3DXVECTOR3& ); + D3DXVECTOR3& operator *= ( FLOAT ); + D3DXVECTOR3& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR3 operator + () const; + D3DXVECTOR3 operator - () const; + + // binary operators + D3DXVECTOR3 operator + ( CONST D3DXVECTOR3& ) const; + D3DXVECTOR3 operator - ( CONST D3DXVECTOR3& ) const; + D3DXVECTOR3 operator * ( FLOAT ) const; + D3DXVECTOR3 operator / ( FLOAT ) const; + + friend D3DXVECTOR3 operator * ( FLOAT, CONST struct D3DXVECTOR3& ); + + BOOL operator == ( CONST D3DXVECTOR3& ) const; + BOOL operator != ( CONST D3DXVECTOR3& ) const; + +} D3DXVECTOR3, *LPD3DXVECTOR3; + +#else //!__cplusplus +typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3; +#endif //!__cplusplus + + + +//-------------------------- +// 3D Vector (16 bit) +//-------------------------- +typedef struct D3DXVECTOR3_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR3_16F() {}; + D3DXVECTOR3_16F( CONST FLOAT * ); + D3DXVECTOR3_16F( CONST D3DVECTOR& ); + D3DXVECTOR3_16F( CONST D3DXFLOAT16 * ); + D3DXVECTOR3_16F( CONST D3DXFLOAT16 &x, CONST D3DXFLOAT16 &y, CONST D3DXFLOAT16 &z ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR3_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR3_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y, z; + +} D3DXVECTOR3_16F, *LPD3DXVECTOR3_16F; + + + +//-------------------------- +// 4D Vector +//-------------------------- +typedef struct D3DXVECTOR4 +{ +#ifdef __cplusplus +public: + D3DXVECTOR4() {}; + D3DXVECTOR4( CONST FLOAT* ); + D3DXVECTOR4( CONST D3DXFLOAT16* ); + D3DXVECTOR4( CONST D3DVECTOR& xyz, FLOAT w ); + D3DXVECTOR4( FLOAT x, FLOAT y, FLOAT z, FLOAT w ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR4& operator += ( CONST D3DXVECTOR4& ); + D3DXVECTOR4& operator -= ( CONST D3DXVECTOR4& ); + D3DXVECTOR4& operator *= ( FLOAT ); + D3DXVECTOR4& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR4 operator + () const; + D3DXVECTOR4 operator - () const; + + // binary operators + D3DXVECTOR4 operator + ( CONST D3DXVECTOR4& ) const; + D3DXVECTOR4 operator - ( CONST D3DXVECTOR4& ) const; + D3DXVECTOR4 operator * ( FLOAT ) const; + D3DXVECTOR4 operator / ( FLOAT ) const; + + friend D3DXVECTOR4 operator * ( FLOAT, CONST D3DXVECTOR4& ); + + BOOL operator == ( CONST D3DXVECTOR4& ) const; + BOOL operator != ( CONST D3DXVECTOR4& ) const; + +public: +#endif //__cplusplus + FLOAT x, y, z, w; +} D3DXVECTOR4, *LPD3DXVECTOR4; + + +//-------------------------- +// 4D Vector (16 bit) +//-------------------------- +typedef struct D3DXVECTOR4_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR4_16F() {}; + D3DXVECTOR4_16F( CONST FLOAT * ); + D3DXVECTOR4_16F( CONST D3DXFLOAT16* ); + D3DXVECTOR4_16F( CONST D3DXVECTOR3_16F& xyz, CONST D3DXFLOAT16& w ); + D3DXVECTOR4_16F( CONST D3DXFLOAT16& x, CONST D3DXFLOAT16& y, CONST D3DXFLOAT16& z, CONST D3DXFLOAT16& w ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR4_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR4_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y, z, w; + +} D3DXVECTOR4_16F, *LPD3DXVECTOR4_16F; + + + +//=========================================================================== +// +// Matrices +// +//=========================================================================== +#ifdef __cplusplus +typedef struct D3DXMATRIX : public D3DMATRIX +{ +public: + D3DXMATRIX() {}; + D3DXMATRIX( CONST FLOAT * ); + D3DXMATRIX( CONST D3DMATRIX& ); + D3DXMATRIX( CONST D3DXFLOAT16 * ); + D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ); + + + // access grants + FLOAT& operator () ( UINT Row, UINT Col ); + FLOAT operator () ( UINT Row, UINT Col ) const; + + // casting operators + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXMATRIX& operator *= ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator += ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator -= ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator *= ( FLOAT ); + D3DXMATRIX& operator /= ( FLOAT ); + + // unary operators + D3DXMATRIX operator + () const; + D3DXMATRIX operator - () const; + + // binary operators + D3DXMATRIX operator * ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator + ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator - ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator * ( FLOAT ) const; + D3DXMATRIX operator / ( FLOAT ) const; + + friend D3DXMATRIX operator * ( FLOAT, CONST D3DXMATRIX& ); + + BOOL operator == ( CONST D3DXMATRIX& ) const; + BOOL operator != ( CONST D3DXMATRIX& ) const; + +} D3DXMATRIX, *LPD3DXMATRIX; + +#else //!__cplusplus +typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX; +#endif //!__cplusplus + + +//--------------------------------------------------------------------------- +// Aligned Matrices +// +// This class helps keep matrices 16-byte aligned as preferred by P4 cpus. +// It aligns matrices on the stack and on the heap or in global scope. +// It does this using __declspec(align(16)) which works on VC7 and on VC 6 +// with the processor pack. Unfortunately there is no way to detect the +// latter so this is turned on only on VC7. On other compilers this is the +// the same as D3DXMATRIX. +// +// Using this class on a compiler that does not actually do the alignment +// can be dangerous since it will not expose bugs that ignore alignment. +// E.g if an object of this class in inside a struct or class, and some code +// memcopys data in it assuming tight packing. This could break on a compiler +// that eventually start aligning the matrix. +//--------------------------------------------------------------------------- +#ifdef __cplusplus +typedef struct _D3DXMATRIXA16 : public D3DXMATRIX +{ + _D3DXMATRIXA16() {} + _D3DXMATRIXA16( CONST FLOAT * ); + _D3DXMATRIXA16( CONST D3DMATRIX& ); + _D3DXMATRIXA16( CONST D3DXFLOAT16 * ); + _D3DXMATRIXA16( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ); + + // new operators + void* operator new ( size_t ); + void* operator new[] ( size_t ); + + // delete operators + void operator delete ( void* ); // These are NOT virtual; Do not + void operator delete[] ( void* ); // cast to D3DXMATRIX and delete. + + // assignment operators + _D3DXMATRIXA16& operator = ( CONST D3DXMATRIX& ); + +} _D3DXMATRIXA16; + +#else //!__cplusplus +typedef D3DXMATRIX _D3DXMATRIXA16; +#endif //!__cplusplus + + + +//#if _MSC_VER >= 1300 // VC7 +//#define D3DX_ALIGN16 __declspec(align(16)) +//#else +#define D3DX_ALIGN16 // Earlier compiler may not understand this, do nothing. +//#endif + +typedef D3DX_ALIGN16 _D3DXMATRIXA16 D3DXMATRIXA16, *LPD3DXMATRIXA16; + + + +//=========================================================================== +// +// Quaternions +// +//=========================================================================== +typedef struct D3DXQUATERNION +{ +#ifdef __cplusplus +public: + D3DXQUATERNION() {} + D3DXQUATERNION( CONST FLOAT * ); + D3DXQUATERNION( CONST D3DXFLOAT16 * ); + D3DXQUATERNION( FLOAT x, FLOAT y, FLOAT z, FLOAT w ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXQUATERNION& operator += ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator -= ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator *= ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator *= ( FLOAT ); + D3DXQUATERNION& operator /= ( FLOAT ); + + // unary operators + D3DXQUATERNION operator + () const; + D3DXQUATERNION operator - () const; + + // binary operators + D3DXQUATERNION operator + ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator - ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator * ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator * ( FLOAT ) const; + D3DXQUATERNION operator / ( FLOAT ) const; + + friend D3DXQUATERNION operator * (FLOAT, CONST D3DXQUATERNION& ); + + BOOL operator == ( CONST D3DXQUATERNION& ) const; + BOOL operator != ( CONST D3DXQUATERNION& ) const; + +#endif //__cplusplus + FLOAT x, y, z, w; +} D3DXQUATERNION, *LPD3DXQUATERNION; + + +//=========================================================================== +// +// Planes +// +//=========================================================================== +typedef struct D3DXPLANE +{ +#ifdef __cplusplus +public: + D3DXPLANE() {} + D3DXPLANE( CONST FLOAT* ); + D3DXPLANE( CONST D3DXFLOAT16* ); + D3DXPLANE( FLOAT a, FLOAT b, FLOAT c, FLOAT d ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXPLANE& operator *= ( FLOAT ); + D3DXPLANE& operator /= ( FLOAT ); + + // unary operators + D3DXPLANE operator + () const; + D3DXPLANE operator - () const; + + // binary operators + D3DXPLANE operator * ( FLOAT ) const; + D3DXPLANE operator / ( FLOAT ) const; + + friend D3DXPLANE operator * ( FLOAT, CONST D3DXPLANE& ); + + BOOL operator == ( CONST D3DXPLANE& ) const; + BOOL operator != ( CONST D3DXPLANE& ) const; + +#endif //__cplusplus + FLOAT a, b, c, d; +} D3DXPLANE, *LPD3DXPLANE; + + +//=========================================================================== +// +// Colors +// +//=========================================================================== + +typedef struct D3DXCOLOR +{ +#ifdef __cplusplus +public: + D3DXCOLOR() {} + D3DXCOLOR( DWORD argb ); + D3DXCOLOR( CONST FLOAT * ); + D3DXCOLOR( CONST D3DXFLOAT16 * ); + D3DXCOLOR( CONST D3DCOLORVALUE& ); + D3DXCOLOR( FLOAT r, FLOAT g, FLOAT b, FLOAT a ); + + // casting + operator DWORD () const; + + operator FLOAT* (); + operator CONST FLOAT* () const; + + operator D3DCOLORVALUE* (); + operator CONST D3DCOLORVALUE* () const; + + operator D3DCOLORVALUE& (); + operator CONST D3DCOLORVALUE& () const; + + // assignment operators + D3DXCOLOR& operator += ( CONST D3DXCOLOR& ); + D3DXCOLOR& operator -= ( CONST D3DXCOLOR& ); + D3DXCOLOR& operator *= ( FLOAT ); + D3DXCOLOR& operator /= ( FLOAT ); + + // unary operators + D3DXCOLOR operator + () const; + D3DXCOLOR operator - () const; + + // binary operators + D3DXCOLOR operator + ( CONST D3DXCOLOR& ) const; + D3DXCOLOR operator - ( CONST D3DXCOLOR& ) const; + D3DXCOLOR operator * ( FLOAT ) const; + D3DXCOLOR operator / ( FLOAT ) const; + + friend D3DXCOLOR operator * ( FLOAT, CONST D3DXCOLOR& ); + + BOOL operator == ( CONST D3DXCOLOR& ) const; + BOOL operator != ( CONST D3DXCOLOR& ) const; + +#endif //__cplusplus + FLOAT r, g, b, a; +} D3DXCOLOR, *LPD3DXCOLOR; + + + +//=========================================================================== +// +// D3DX math functions: +// +// NOTE: +// * All these functions can take the same object as in and out parameters. +// +// * Out parameters are typically also returned as return values, so that +// the output of one function may be used as a parameter to another. +// +//=========================================================================== + +//-------------------------- +// Float16 +//-------------------------- + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Converts an array 32-bit floats to 16-bit floats +D3DXFLOAT16* WINAPI D3DXFloat32To16Array + ( D3DXFLOAT16 *pOut, CONST FLOAT *pIn, UINT n ); + +// Converts an array 16-bit floats to 32-bit floats +FLOAT* WINAPI D3DXFloat16To32Array + ( FLOAT *pOut, CONST D3DXFLOAT16 *pIn, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 2D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec2Length + ( CONST D3DXVECTOR2 *pV ); + +FLOAT D3DXVec2LengthSq + ( CONST D3DXVECTOR2 *pV ); + +FLOAT D3DXVec2Dot + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Z component of ((x1,y1,0) cross (x2,y2,0)) +FLOAT D3DXVec2CCW + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Add + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Subtract + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2) +D3DXVECTOR2* D3DXVec2Minimize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2) +D3DXVECTOR2* D3DXVec2Maximize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Scale + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, FLOAT s ); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR2* D3DXVec2Lerp + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +D3DXVECTOR2* WINAPI D3DXVec2Normalize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR2* WINAPI D3DXVec2Hermite + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pT1, + CONST D3DXVECTOR2 *pV2, CONST D3DXVECTOR2 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR2* WINAPI D3DXVec2CatmullRom + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV0, CONST D3DXVECTOR2 *pV1, + CONST D3DXVECTOR2 *pV2, CONST D3DXVECTOR2 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR2* WINAPI D3DXVec2BaryCentric + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + CONST D3DXVECTOR2 *pV3, FLOAT f, FLOAT g); + +// Transform (x, y, 0, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec2Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, 0, 1) by matrix, project result back into w=1. +D3DXVECTOR2* WINAPI D3DXVec2TransformCoord + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, 0, 0) by matrix. +D3DXVECTOR2* WINAPI D3DXVec2TransformNormal + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform Array (x, y, 0, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec2TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n); + +// Transform Array (x, y, 0, 1) by matrix, project result back into w=1. +D3DXVECTOR2* WINAPI D3DXVec2TransformCoordArray + ( D3DXVECTOR2 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform Array (x, y, 0, 0) by matrix. +D3DXVECTOR2* WINAPI D3DXVec2TransformNormalArray + ( D3DXVECTOR2 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + + + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 3D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec3Length + ( CONST D3DXVECTOR3 *pV ); + +FLOAT D3DXVec3LengthSq + ( CONST D3DXVECTOR3 *pV ); + +FLOAT D3DXVec3Dot + ( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Cross + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Add + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Subtract + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2), ... +D3DXVECTOR3* D3DXVec3Minimize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2), ... +D3DXVECTOR3* D3DXVec3Maximize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Scale + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, FLOAT s); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR3* D3DXVec3Lerp + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +D3DXVECTOR3* WINAPI D3DXVec3Normalize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR3* WINAPI D3DXVec3Hermite + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pT1, + CONST D3DXVECTOR3 *pV2, CONST D3DXVECTOR3 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR3* WINAPI D3DXVec3CatmullRom + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV0, CONST D3DXVECTOR3 *pV1, + CONST D3DXVECTOR3 *pV2, CONST D3DXVECTOR3 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR3* WINAPI D3DXVec3BaryCentric + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + CONST D3DXVECTOR3 *pV3, FLOAT f, FLOAT g); + +// Transform (x, y, z, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec3Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, z, 1) by matrix, project result back into w=1. +D3DXVECTOR3* WINAPI D3DXVec3TransformCoord + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, z, 0) by matrix. If you transforming a normal by a +// non-affine matrix, the matrix you pass to this function should be the +// transpose of the inverse of the matrix you would use to transform a coord. +D3DXVECTOR3* WINAPI D3DXVec3TransformNormal + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + + +// Transform Array (x, y, z, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec3TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform Array (x, y, z, 1) by matrix, project result back into w=1. +D3DXVECTOR3* WINAPI D3DXVec3TransformCoordArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform (x, y, z, 0) by matrix. If you transforming a normal by a +// non-affine matrix, the matrix you pass to this function should be the +// transpose of the inverse of the matrix you would use to transform a coord. +D3DXVECTOR3* WINAPI D3DXVec3TransformNormalArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Project vector from object space into screen space +D3DXVECTOR3* WINAPI D3DXVec3Project + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld); + +// Project vector from screen space into object space +D3DXVECTOR3* WINAPI D3DXVec3Unproject + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld); + +// Project vector Array from object space into screen space +D3DXVECTOR3* WINAPI D3DXVec3ProjectArray + ( D3DXVECTOR3 *pOut, UINT OutStride,CONST D3DXVECTOR3 *pV, UINT VStride,CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld, UINT n); + +// Project vector Array from screen space into object space +D3DXVECTOR3* WINAPI D3DXVec3UnprojectArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld, UINT n); + + +#ifdef __cplusplus +} +#endif + + + +//-------------------------- +// 4D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec4Length + ( CONST D3DXVECTOR4 *pV ); + +FLOAT D3DXVec4LengthSq + ( CONST D3DXVECTOR4 *pV ); + +FLOAT D3DXVec4Dot + ( CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2 ); + +D3DXVECTOR4* D3DXVec4Add + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +D3DXVECTOR4* D3DXVec4Subtract + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2), ... +D3DXVECTOR4* D3DXVec4Minimize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2), ... +D3DXVECTOR4* D3DXVec4Maximize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +D3DXVECTOR4* D3DXVec4Scale + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, FLOAT s); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR4* D3DXVec4Lerp + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Cross-product in 4 dimensions. +D3DXVECTOR4* WINAPI D3DXVec4Cross + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + CONST D3DXVECTOR4 *pV3); + +D3DXVECTOR4* WINAPI D3DXVec4Normalize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR4* WINAPI D3DXVec4Hermite + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pT1, + CONST D3DXVECTOR4 *pV2, CONST D3DXVECTOR4 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR4* WINAPI D3DXVec4CatmullRom + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV0, CONST D3DXVECTOR4 *pV1, + CONST D3DXVECTOR4 *pV2, CONST D3DXVECTOR4 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR4* WINAPI D3DXVec4BaryCentric + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + CONST D3DXVECTOR4 *pV3, FLOAT f, FLOAT g); + +// Transform vector by matrix. +D3DXVECTOR4* WINAPI D3DXVec4Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + +// Transform vector array by matrix. +D3DXVECTOR4* WINAPI D3DXVec4TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR4 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 4D Matrix +//-------------------------- + +// inline + +D3DXMATRIX* D3DXMatrixIdentity + ( D3DXMATRIX *pOut ); + +BOOL D3DXMatrixIsIdentity + ( CONST D3DXMATRIX *pM ); + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +FLOAT WINAPI D3DXMatrixDeterminant + ( CONST D3DXMATRIX *pM ); + +HRESULT WINAPI D3DXMatrixDecompose + ( D3DXVECTOR3 *pOutScale, D3DXQUATERNION *pOutRotation, + D3DXVECTOR3 *pOutTranslation, CONST D3DXMATRIX *pM ); + +D3DXMATRIX* WINAPI D3DXMatrixTranspose + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +// Matrix multiplication. The result represents the transformation M2 +// followed by the transformation M1. (Out = M1 * M2) +D3DXMATRIX* WINAPI D3DXMatrixMultiply + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); + +// Matrix multiplication, followed by a transpose. (Out = T(M1 * M2)) +D3DXMATRIX* WINAPI D3DXMatrixMultiplyTranspose + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); + +// Calculate inverse of matrix. Inversion my fail, in which case NULL will +// be returned. The determinant of pM is also returned it pfDeterminant +// is non-NULL. +D3DXMATRIX* WINAPI D3DXMatrixInverse + ( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +// Build a matrix which scales by (sx, sy, sz) +D3DXMATRIX* WINAPI D3DXMatrixScaling + ( D3DXMATRIX *pOut, FLOAT sx, FLOAT sy, FLOAT sz ); + +// Build a matrix which translates by (x, y, z) +D3DXMATRIX* WINAPI D3DXMatrixTranslation + ( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build a matrix which rotates around the X axis +D3DXMATRIX* WINAPI D3DXMatrixRotationX + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around the Y axis +D3DXMATRIX* WINAPI D3DXMatrixRotationY + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around the Z axis +D3DXMATRIX* WINAPI D3DXMatrixRotationZ + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around an arbitrary axis +D3DXMATRIX* WINAPI D3DXMatrixRotationAxis + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle ); + +// Build a matrix from a quaternion +D3DXMATRIX* WINAPI D3DXMatrixRotationQuaternion + ( D3DXMATRIX *pOut, CONST D3DXQUATERNION *pQ); + +// Yaw around the Y axis, a pitch around the X axis, +// and a roll around the Z axis. +D3DXMATRIX* WINAPI D3DXMatrixRotationYawPitchRoll + ( D3DXMATRIX *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll ); + +// Build transformation matrix. NULL arguments are treated as identity. +// Mout = Msc-1 * Msr-1 * Ms * Msr * Msc * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixTransformation + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pScalingCenter, + CONST D3DXQUATERNION *pScalingRotation, CONST D3DXVECTOR3 *pScaling, + CONST D3DXVECTOR3 *pRotationCenter, CONST D3DXQUATERNION *pRotation, + CONST D3DXVECTOR3 *pTranslation); + +// Build 2D transformation matrix in XY plane. NULL arguments are treated as identity. +// Mout = Msc-1 * Msr-1 * Ms * Msr * Msc * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixTransformation2D + ( D3DXMATRIX *pOut, CONST D3DXVECTOR2* pScalingCenter, + FLOAT ScalingRotation, CONST D3DXVECTOR2* pScaling, + CONST D3DXVECTOR2* pRotationCenter, FLOAT Rotation, + CONST D3DXVECTOR2* pTranslation); + +// Build affine transformation matrix. NULL arguments are treated as identity. +// Mout = Ms * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation + ( D3DXMATRIX *pOut, FLOAT Scaling, CONST D3DXVECTOR3 *pRotationCenter, + CONST D3DXQUATERNION *pRotation, CONST D3DXVECTOR3 *pTranslation); + +// Build 2D affine transformation matrix in XY plane. NULL arguments are treated as identity. +// Mout = Ms * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation2D + ( D3DXMATRIX *pOut, FLOAT Scaling, CONST D3DXVECTOR2* pRotationCenter, + FLOAT Rotation, CONST D3DXVECTOR2* pTranslation); + +// Build a lookat matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixLookAtRH + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pEye, CONST D3DXVECTOR3 *pAt, + CONST D3DXVECTOR3 *pUp ); + +// Build a lookat matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixLookAtLH + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pEye, CONST D3DXVECTOR3 *pAt, + CONST D3DXVECTOR3 *pUp ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveRH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveLH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovRH + ( D3DXMATRIX *pOut, FLOAT fovy, FLOAT Aspect, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovLH + ( D3DXMATRIX *pOut, FLOAT fovy, FLOAT Aspect, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterRH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterLH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build an ortho projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoRH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build an ortho projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoLH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build an ortho projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterRH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build an ortho projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterLH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build a matrix which flattens geometry into a plane, as if casting +// a shadow from a light. +D3DXMATRIX* WINAPI D3DXMatrixShadow + ( D3DXMATRIX *pOut, CONST D3DXVECTOR4 *pLight, + CONST D3DXPLANE *pPlane ); + +// Build a matrix which reflects the coordinate system about a plane +D3DXMATRIX* WINAPI D3DXMatrixReflect + ( D3DXMATRIX *pOut, CONST D3DXPLANE *pPlane ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Quaternion +//-------------------------- + +// inline + +FLOAT D3DXQuaternionLength + ( CONST D3DXQUATERNION *pQ ); + +// Length squared, or "norm" +FLOAT D3DXQuaternionLengthSq + ( CONST D3DXQUATERNION *pQ ); + +FLOAT D3DXQuaternionDot + ( CONST D3DXQUATERNION *pQ1, CONST D3DXQUATERNION *pQ2 ); + +// (0, 0, 0, 1) +D3DXQUATERNION* D3DXQuaternionIdentity + ( D3DXQUATERNION *pOut ); + +BOOL D3DXQuaternionIsIdentity + ( CONST D3DXQUATERNION *pQ ); + +// (-x, -y, -z, w) +D3DXQUATERNION* D3DXQuaternionConjugate + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Compute a quaternin's axis and angle of rotation. Expects unit quaternions. +void WINAPI D3DXQuaternionToAxisAngle + ( CONST D3DXQUATERNION *pQ, D3DXVECTOR3 *pAxis, FLOAT *pAngle ); + +// Build a quaternion from a rotation matrix. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix + ( D3DXQUATERNION *pOut, CONST D3DXMATRIX *pM); + +// Rotation about arbitrary axis. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis + ( D3DXQUATERNION *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle ); + +// Yaw around the Y axis, a pitch around the X axis, +// and a roll around the Z axis. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationYawPitchRoll + ( D3DXQUATERNION *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll ); + +// Quaternion multiplication. The result represents the rotation Q2 +// followed by the rotation Q1. (Out = Q2 * Q1) +D3DXQUATERNION* WINAPI D3DXQuaternionMultiply + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2 ); + +D3DXQUATERNION* WINAPI D3DXQuaternionNormalize + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Conjugate and re-norm +D3DXQUATERNION* WINAPI D3DXQuaternionInverse + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Expects unit quaternions. +// if q = (cos(theta), sin(theta) * v); ln(q) = (0, theta * v) +D3DXQUATERNION* WINAPI D3DXQuaternionLn + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Expects pure quaternions. (w == 0) w is ignored in calculation. +// if q = (0, theta * v); exp(q) = (cos(theta), sin(theta) * v) +D3DXQUATERNION* WINAPI D3DXQuaternionExp + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Spherical linear interpolation between Q1 (t == 0) and Q2 (t == 1). +// Expects unit quaternions. +D3DXQUATERNION* WINAPI D3DXQuaternionSlerp + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, FLOAT t ); + +// Spherical quadrangle interpolation. +// Slerp(Slerp(Q1, C, t), Slerp(A, B, t), 2t(1-t)) +D3DXQUATERNION* WINAPI D3DXQuaternionSquad + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pA, CONST D3DXQUATERNION *pB, + CONST D3DXQUATERNION *pC, FLOAT t ); + +// Setup control points for spherical quadrangle interpolation +// from Q1 to Q2. The control points are chosen in such a way +// to ensure the continuity of tangents with adjacent segments. +void WINAPI D3DXQuaternionSquadSetup + ( D3DXQUATERNION *pAOut, D3DXQUATERNION *pBOut, D3DXQUATERNION *pCOut, + CONST D3DXQUATERNION *pQ0, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3 ); + +// Barycentric interpolation. +// Slerp(Slerp(Q1, Q2, f+g), Slerp(Q1, Q3, f+g), g/(f+g)) +D3DXQUATERNION* WINAPI D3DXQuaternionBaryCentric + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3, + FLOAT f, FLOAT g ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Plane +//-------------------------- + +// inline + +// ax + by + cz + dw +FLOAT D3DXPlaneDot + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR4 *pV); + +// ax + by + cz + d +FLOAT D3DXPlaneDotCoord + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV); + +// ax + by + cz +FLOAT D3DXPlaneDotNormal + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV); + +D3DXPLANE* D3DXPlaneScale + (D3DXPLANE *pOut, CONST D3DXPLANE *pP, FLOAT s); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Normalize plane (so that |a,b,c| == 1) +D3DXPLANE* WINAPI D3DXPlaneNormalize + ( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +// Find the intersection between a plane and a line. If the line is +// parallel to the plane, NULL is returned. +D3DXVECTOR3* WINAPI D3DXPlaneIntersectLine + ( D3DXVECTOR3 *pOut, CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV1, + CONST D3DXVECTOR3 *pV2); + +// Construct a plane from a point and a normal +D3DXPLANE* WINAPI D3DXPlaneFromPointNormal + ( D3DXPLANE *pOut, CONST D3DXVECTOR3 *pPoint, CONST D3DXVECTOR3 *pNormal); + +// Construct a plane from 3 points +D3DXPLANE* WINAPI D3DXPlaneFromPoints + ( D3DXPLANE *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + CONST D3DXVECTOR3 *pV3); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +D3DXPLANE* WINAPI D3DXPlaneTransform + ( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +// Transform an array of planes by a matrix. The vectors (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +D3DXPLANE* WINAPI D3DXPlaneTransformArray + ( D3DXPLANE *pOut, UINT OutStride, CONST D3DXPLANE *pP, UINT PStride, CONST D3DXMATRIX *pM, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Color +//-------------------------- + +// inline + +// (1-r, 1-g, 1-b, a) +D3DXCOLOR* D3DXColorNegative + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC); + +D3DXCOLOR* D3DXColorAdd + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +D3DXCOLOR* D3DXColorSubtract + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +D3DXCOLOR* D3DXColorScale + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s); + +// (r1*r2, g1*g2, b1*b2, a1*a2) +D3DXCOLOR* D3DXColorModulate + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +// Linear interpolation of r,g,b, and a. C1 + s(C2-C1) +D3DXCOLOR* D3DXColorLerp + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2, FLOAT s); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Interpolate r,g,b between desaturated color and color. +// DesaturatedColor + s(Color - DesaturatedColor) +D3DXCOLOR* WINAPI D3DXColorAdjustSaturation + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s); + +// Interpolate r,g,b between 50% grey and color. Grey + s(Color - Grey) +D3DXCOLOR* WINAPI D3DXColorAdjustContrast + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT c); + +#ifdef __cplusplus +} +#endif + + + + +//-------------------------- +// Misc +//-------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +// Calculate Fresnel term given the cosine of theta (likely obtained by +// taking the dot of two normals), and the refraction index of the material. +FLOAT WINAPI D3DXFresnelTerm + (FLOAT CosTheta, FLOAT RefractionIndex); + +#ifdef __cplusplus +} +#endif + + + +//=========================================================================== +// +// Matrix Stack +// +//=========================================================================== + +typedef interface ID3DXMatrixStack ID3DXMatrixStack; +typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK; + +// {C7885BA7-F990-4fe7-922D-8515E477DD85} +DEFINE_GUID(IID_ID3DXMatrixStack, +0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85); + + +#undef INTERFACE +#define INTERFACE ID3DXMatrixStack + +DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown) +{ + // + // IUnknown methods + // + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + // + // ID3DXMatrixStack methods + // + + // Pops the top of the stack, returns the current top + // *after* popping the top. + STDMETHOD(Pop)(THIS) PURE; + + // Pushes the stack by one, duplicating the current matrix. + STDMETHOD(Push)(THIS) PURE; + + // Loads identity in the current matrix. + STDMETHOD(LoadIdentity)(THIS) PURE; + + // Loads the given matrix into the current matrix + STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Right-Multiplies the given matrix to the current matrix. + // (transformation is about the current world origin) + STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Left-Multiplies the given matrix to the current matrix + // (transformation is about the local origin of the object) + STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Right multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the current world origin) + STDMETHOD(RotateAxis) + (THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE; + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + STDMETHOD(RotateAxisLocal) + (THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE; + + // Right multiply the current matrix with the computed rotation + // matrix. All angles are counterclockwise. (rotation is about the + // current world origin) + + // The rotation is composed of a yaw around the Y axis, a pitch around + // the X axis, and a roll around the Z axis. + STDMETHOD(RotateYawPitchRoll) + (THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE; + + // Left multiply the current matrix with the computed rotation + // matrix. All angles are counterclockwise. (rotation is about the + // local origin of the object) + + // The rotation is composed of a yaw around the Y axis, a pitch around + // the X axis, and a roll around the Z axis. + STDMETHOD(RotateYawPitchRollLocal) + (THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE; + + // Right multiply the current matrix with the computed scale + // matrix. (transformation is about the current world origin) + STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Left multiply the current matrix with the computed scale + // matrix. (transformation is about the local origin of the object) + STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Right multiply the current matrix with the computed translation + // matrix. (transformation is about the current world origin) + STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE; + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Obtain the current matrix at the top of the stack + STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +HRESULT WINAPI + D3DXCreateMatrixStack( + DWORD Flags, + LPD3DXMATRIXSTACK* ppStack); + +#ifdef __cplusplus +} +#endif + +//=========================================================================== +// +// Spherical Harmonic Runtime Routines +// +// NOTE: +// * Most of these functions can take the same object as in and out parameters. +// The exceptions are the rotation functions. +// +// * Out parameters are typically also returned as return values, so that +// the output of one function may be used as a parameter to another. +// +//============================================================================ + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +//============================================================================ +// +// Basic Spherical Harmonic math routines +// +//============================================================================ + +#define D3DXSH_MINORDER 2 +#define D3DXSH_MAXORDER 6 + +//============================================================================ +// +// D3DXSHEvalDirection: +// -------------------- +// Evaluates the Spherical Harmonic basis functions +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction to evaluate in - assumed to be normalized +// +//============================================================================ + +FLOAT* WINAPI D3DXSHEvalDirection + ( FLOAT *pOut, UINT Order, CONST D3DXVECTOR3 *pDir ); + +//============================================================================ +// +// D3DXSHRotate: +// -------------------- +// Rotates SH vector by a rotation matrix +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned (should not alias with pIn.) +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pMatrix +// Matrix used for rotation - rotation sub matrix should be orthogonal +// and have a unit determinant. +// pIn +// Input SH coeffs (rotated), incorect results if this is also output. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHRotate + ( FLOAT *pOut, UINT Order, CONST D3DXMATRIX *pMatrix, CONST FLOAT *pIn ); + +//============================================================================ +// +// D3DXSHRotateZ: +// -------------------- +// Rotates the SH vector in the Z axis by an angle +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned (should not alias with pIn.) +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// Angle +// Angle in radians to rotate around the Z axis. +// pIn +// Input SH coeffs (rotated), incorect results if this is also output. +// +//============================================================================ + + +FLOAT* WINAPI D3DXSHRotateZ + ( FLOAT *pOut, UINT Order, FLOAT Angle, CONST FLOAT *pIn ); + +//============================================================================ +// +// D3DXSHAdd: +// -------------------- +// Adds two SH vectors, pOut[i] = pA[i] + pB[i]; +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pA +// Input SH coeffs. +// pB +// Input SH coeffs (second vector.) +// +//============================================================================ + +FLOAT* WINAPI D3DXSHAdd + ( FLOAT *pOut, UINT Order, CONST FLOAT *pA, CONST FLOAT *pB ); + +//============================================================================ +// +// D3DXSHScale: +// -------------------- +// Adds two SH vectors, pOut[i] = pA[i]*Scale; +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pIn +// Input SH coeffs. +// Scale +// Scale factor. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHScale + ( FLOAT *pOut, UINT Order, CONST FLOAT *pIn, CONST FLOAT Scale ); + +//============================================================================ +// +// D3DXSHDot: +// -------------------- +// Computes the dot product of two SH vectors +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pA +// Input SH coeffs. +// pB +// Second set of input SH coeffs. +// +//============================================================================ + +FLOAT WINAPI D3DXSHDot + ( UINT Order, CONST FLOAT *pA, CONST FLOAT *pB ); + +//============================================================================ +// +// D3DXSHMultiply[O]: +// -------------------- +// Computes the product of two functions represented using SH (f and g), where: +// pOut[i] = int(y_i(s) * f(s) * g(s)), where y_i(s) is the ith SH basis +// function, f(s) and g(s) are SH functions (sum_i(y_i(s)*c_i)). The order O +// determines the lengths of the arrays, where there should always be O^2 +// coefficients. In general the product of two SH functions of order O generates +// and SH function of order 2*O - 1, but we truncate the result. This means +// that the product commutes (f*g == g*f) but doesn't associate +// (f*(g*h) != (f*g)*h. +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// pF +// Input SH coeffs for first function. +// pG +// Second set of input SH coeffs. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHMultiply2( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply3( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply4( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply5( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply6( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); + + +//============================================================================ +// +// Basic Spherical Harmonic lighting routines +// +//============================================================================ + +//============================================================================ +// +// D3DXSHEvalDirectionalLight: +// -------------------- +// Evaluates a directional light and returns spectral SH data. The output +// vector is computed so that if the intensity of R/G/B is unit the resulting +// exit radiance of a point directly under the light on a diffuse object with +// an albedo of 1 would be 1.0. This will compute 3 spectral samples, pROut +// has to be specified, while pGout and pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction light is coming from (assumed to be normalized.) +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalDirectionalLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalSphericalLight: +// -------------------- +// Evaluates a spherical light and returns spectral SH data. There is no +// normalization of the intensity of the light like there is for directional +// lights, care has to be taken when specifiying the intensities. This will +// compute 3 spectral samples, pROut has to be specified, while pGout and +// pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pPos +// Position of light - reciever is assumed to be at the origin. +// Radius +// Radius of the spherical light source. +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalSphericalLight + ( UINT Order, CONST D3DXVECTOR3 *pPos, FLOAT Radius, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalConeLight: +// -------------------- +// Evaluates a light that is a cone of constant intensity and returns spectral +// SH data. The output vector is computed so that if the intensity of R/G/B is +// unit the resulting exit radiance of a point directly under the light oriented +// in the cone direction on a diffuse object with an albedo of 1 would be 1.0. +// This will compute 3 spectral samples, pROut has to be specified, while pGout +// and pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction light is coming from (assumed to be normalized.) +// Radius +// Radius of cone in radians. +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalConeLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, FLOAT Radius, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalHemisphereLight: +// -------------------- +// Evaluates a light that is a linear interpolant between two colors over the +// sphere. The interpolant is linear along the axis of the two points, not +// over the surface of the sphere (ie: if the axis was (0,0,1) it is linear in +// Z, not in the azimuthal angle.) The resulting spherical lighting function +// is normalized so that a point on a perfectly diffuse surface with no +// shadowing and a normal pointed in the direction pDir would result in exit +// radiance with a value of 1 if the top color was white and the bottom color +// was black. This is a very simple model where Top represents the intensity +// of the "sky" and Bottom represents the intensity of the "ground". +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Axis of the hemisphere. +// Top +// Color of the upper hemisphere. +// Bottom +// Color of the lower hemisphere. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green +// pBOut +// Output SH vector for Blue +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalHemisphereLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, D3DXCOLOR Top, D3DXCOLOR Bottom, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// Basic Spherical Harmonic projection routines +// +//============================================================================ + +//============================================================================ +// +// D3DXSHProjectCubeMap: +// -------------------- +// Projects a function represented on a cube map into spherical harmonics. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pCubeMap +// CubeMap that is going to be projected into spherical harmonics +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green +// pBOut +// Output SH vector for Blue +// +//============================================================================ + +HRESULT WINAPI D3DXSHProjectCubeMap + ( UINT uOrder, LPDIRECT3DCUBETEXTURE9 pCubeMap, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + + +#ifdef __cplusplus +} +#endif + + +#include "d3dx9math.inl" + +//#if _MSC_VER >= 1200 +//#pragma warning(pop) +//#else +//#pragma warning(default:4201) +//#endif + +#endif // __D3DX9MATH_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9math.inl b/src/depend/mingw/include/directx9/d3dx9math.inl new file mode 100644 index 00000000..a3652ed4 --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9math.inl @@ -0,0 +1,2251 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9math.inl +// Content: D3DX math inline functions +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3DX9MATH_INL__ +#define __D3DX9MATH_INL__ + +//=========================================================================== +// +// Inline Class Methods +// +//=========================================================================== + +#ifdef __cplusplus + +//-------------------------- +// Float16 +//-------------------------- + +D3DXINLINE +D3DXFLOAT16::D3DXFLOAT16( FLOAT f ) +{ + D3DXFloat32To16Array(this, &f, 1); +} + +D3DXINLINE +D3DXFLOAT16::D3DXFLOAT16( CONST D3DXFLOAT16& f ) +{ + value = f.value; +} + +// casting +D3DXINLINE +D3DXFLOAT16::operator FLOAT () +{ + FLOAT f; + D3DXFloat16To32Array(&f, this, 1); + return f; +} + +// binary operators +D3DXINLINE BOOL +D3DXFLOAT16::operator == ( CONST D3DXFLOAT16& f ) const +{ + return value == f.value; +} + +D3DXINLINE BOOL +D3DXFLOAT16::operator != ( CONST D3DXFLOAT16& f ) const +{ + return value != f.value; +} + + +//-------------------------- +// 2D Vector +//-------------------------- + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; +} + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 2); +} + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( FLOAT fx, FLOAT fy ) +{ + x = fx; + y = fy; +} + + +// casting +D3DXINLINE +D3DXVECTOR2::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR2::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator += ( CONST D3DXVECTOR2& v ) +{ + x += v.x; + y += v.y; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator -= ( CONST D3DXVECTOR2& v ) +{ + x -= v.x; + y -= v.y; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator - () const +{ + return D3DXVECTOR2(-x, -y); +} + + +// binary operators +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator + ( CONST D3DXVECTOR2& v ) const +{ + return D3DXVECTOR2(x + v.x, y + v.y); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator - ( CONST D3DXVECTOR2& v ) const +{ + return D3DXVECTOR2(x - v.x, y - v.y); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator * ( FLOAT f ) const +{ + return D3DXVECTOR2(x * f, y * f); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR2(x * fInv, y * fInv); +} + +D3DXINLINE D3DXVECTOR2 +operator * ( FLOAT f, CONST D3DXVECTOR2& v ) +{ + return D3DXVECTOR2(f * v.x, f * v.y); +} + +D3DXINLINE BOOL +D3DXVECTOR2::operator == ( CONST D3DXVECTOR2& v ) const +{ + return x == v.x && y == v.y; +} + +D3DXINLINE BOOL +D3DXVECTOR2::operator != ( CONST D3DXVECTOR2& v ) const +{ + return x != v.x || y != v.y; +} + + + +//-------------------------- +// 2D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 2); +} + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); +} + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy ) +{ + x = fx; + y = fy; +} + + +// casting +D3DXINLINE +D3DXVECTOR2_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR2_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR2_16F::operator == ( CONST D3DXVECTOR2_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x); +} + +D3DXINLINE BOOL +D3DXVECTOR2_16F::operator != ( CONST D3DXVECTOR2_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x); +} + + +//-------------------------- +// 3D Vector +//-------------------------- +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST D3DVECTOR& v ) +{ + x = v.x; + y = v.y; + z = v.z; +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 3); +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( FLOAT fx, FLOAT fy, FLOAT fz ) +{ + x = fx; + y = fy; + z = fz; +} + + +// casting +D3DXINLINE +D3DXVECTOR3::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR3::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator += ( CONST D3DXVECTOR3& v ) +{ + x += v.x; + y += v.y; + z += v.z; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator -= ( CONST D3DXVECTOR3& v ) +{ + x -= v.x; + y -= v.y; + z -= v.z; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator - () const +{ + return D3DXVECTOR3(-x, -y, -z); +} + + +// binary operators +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator + ( CONST D3DXVECTOR3& v ) const +{ + return D3DXVECTOR3(x + v.x, y + v.y, z + v.z); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator - ( CONST D3DXVECTOR3& v ) const +{ + return D3DXVECTOR3(x - v.x, y - v.y, z - v.z); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator * ( FLOAT f ) const +{ + return D3DXVECTOR3(x * f, y * f, z * f); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR3(x * fInv, y * fInv, z * fInv); +} + + +D3DXINLINE D3DXVECTOR3 +operator * ( FLOAT f, CONST struct D3DXVECTOR3& v ) +{ + return D3DXVECTOR3(f * v.x, f * v.y, f * v.z); +} + + +D3DXINLINE BOOL +D3DXVECTOR3::operator == ( CONST D3DXVECTOR3& v ) const +{ + return x == v.x && y == v.y && z == v.z; +} + +D3DXINLINE BOOL +D3DXVECTOR3::operator != ( CONST D3DXVECTOR3& v ) const +{ + return x != v.x || y != v.y || z != v.z; +} + + + +//-------------------------- +// 3D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 3); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DVECTOR& v ) +{ + D3DXFloat32To16Array(&x, &v.x, 1); + D3DXFloat32To16Array(&y, &v.y, 1); + D3DXFloat32To16Array(&z, &v.z, 1); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); + *((WORD *) &z) = *((WORD *) &pf[2]); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy, CONST D3DXFLOAT16 &fz ) +{ + x = fx; + y = fy; + z = fz; +} + + +// casting +D3DXINLINE +D3DXVECTOR3_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR3_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR3_16F::operator == ( CONST D3DXVECTOR3_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x) && + *((WORD *) &z) == *((WORD *) &v.z); +} + +D3DXINLINE BOOL +D3DXVECTOR3_16F::operator != ( CONST D3DXVECTOR3_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x) || + *((WORD *) &z) != *((WORD *) &v.z); +} + + +//-------------------------- +// 4D Vector +//-------------------------- +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; + w = pf[3]; +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 4); +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST D3DVECTOR& v, FLOAT f ) +{ + x = v.x; + y = v.y; + z = v.z; + w = f; +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXVECTOR4::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR4::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator += ( CONST D3DXVECTOR4& v ) +{ + x += v.x; + y += v.y; + z += v.z; + w += v.w; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator -= ( CONST D3DXVECTOR4& v ) +{ + x -= v.x; + y -= v.y; + z -= v.z; + w -= v.w; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + w *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + w *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator - () const +{ + return D3DXVECTOR4(-x, -y, -z, -w); +} + + +// binary operators +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator + ( CONST D3DXVECTOR4& v ) const +{ + return D3DXVECTOR4(x + v.x, y + v.y, z + v.z, w + v.w); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator - ( CONST D3DXVECTOR4& v ) const +{ + return D3DXVECTOR4(x - v.x, y - v.y, z - v.z, w - v.w); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator * ( FLOAT f ) const +{ + return D3DXVECTOR4(x * f, y * f, z * f, w * f); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR4(x * fInv, y * fInv, z * fInv, w * fInv); +} + +D3DXINLINE D3DXVECTOR4 +operator * ( FLOAT f, CONST D3DXVECTOR4& v ) +{ + return D3DXVECTOR4(f * v.x, f * v.y, f * v.z, f * v.w); +} + + +D3DXINLINE BOOL +D3DXVECTOR4::operator == ( CONST D3DXVECTOR4& v ) const +{ + return x == v.x && y == v.y && z == v.z && w == v.w; +} + +D3DXINLINE BOOL +D3DXVECTOR4::operator != ( CONST D3DXVECTOR4& v ) const +{ + return x != v.x || y != v.y || z != v.z || w != v.w; +} + + + +//-------------------------- +// 4D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 4); +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); + *((DWORD *) &z) = *((DWORD *) &pf[2]); +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXVECTOR3_16F& v, CONST D3DXFLOAT16& f ) +{ + x = v.x; + y = v.y; + z = v.z; + w = f; +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy, CONST D3DXFLOAT16 &fz, CONST D3DXFLOAT16 &fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXVECTOR4_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR4_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR4_16F::operator == ( CONST D3DXVECTOR4_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x) && + *((DWORD *) &z) == *((DWORD *) &v.z); +} + +D3DXINLINE BOOL +D3DXVECTOR4_16F::operator != ( CONST D3DXVECTOR4_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x) || + *((DWORD *) &z) != *((DWORD *) &v.z); +} + + +//-------------------------- +// Matrix +//-------------------------- +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + memcpy(&_11, pf, sizeof(D3DXMATRIX)); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST D3DMATRIX& mat ) +{ + memcpy(&_11, &mat, sizeof(D3DXMATRIX)); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&_11, pf, 16); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( FLOAT f11, FLOAT f12, FLOAT f13, FLOAT f14, + FLOAT f21, FLOAT f22, FLOAT f23, FLOAT f24, + FLOAT f31, FLOAT f32, FLOAT f33, FLOAT f34, + FLOAT f41, FLOAT f42, FLOAT f43, FLOAT f44 ) +{ + _11 = f11; _12 = f12; _13 = f13; _14 = f14; + _21 = f21; _22 = f22; _23 = f23; _24 = f24; + _31 = f31; _32 = f32; _33 = f33; _34 = f34; + _41 = f41; _42 = f42; _43 = f43; _44 = f44; +} + + + +// access grants +D3DXINLINE FLOAT& +D3DXMATRIX::operator () ( UINT iRow, UINT iCol ) +{ + return m[iRow][iCol]; +} + +D3DXINLINE FLOAT +D3DXMATRIX::operator () ( UINT iRow, UINT iCol ) const +{ + return m[iRow][iCol]; +} + + +// casting operators +D3DXINLINE +D3DXMATRIX::operator FLOAT* () +{ + return (FLOAT *) &_11; +} + +D3DXINLINE +D3DXMATRIX::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &_11; +} + + +// assignment operators +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator *= ( CONST D3DXMATRIX& mat ) +{ + D3DXMatrixMultiply(this, this, &mat); + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator += ( CONST D3DXMATRIX& mat ) +{ + _11 += mat._11; _12 += mat._12; _13 += mat._13; _14 += mat._14; + _21 += mat._21; _22 += mat._22; _23 += mat._23; _24 += mat._24; + _31 += mat._31; _32 += mat._32; _33 += mat._33; _34 += mat._34; + _41 += mat._41; _42 += mat._42; _43 += mat._43; _44 += mat._44; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator -= ( CONST D3DXMATRIX& mat ) +{ + _11 -= mat._11; _12 -= mat._12; _13 -= mat._13; _14 -= mat._14; + _21 -= mat._21; _22 -= mat._22; _23 -= mat._23; _24 -= mat._24; + _31 -= mat._31; _32 -= mat._32; _33 -= mat._33; _34 -= mat._34; + _41 -= mat._41; _42 -= mat._42; _43 -= mat._43; _44 -= mat._44; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator *= ( FLOAT f ) +{ + _11 *= f; _12 *= f; _13 *= f; _14 *= f; + _21 *= f; _22 *= f; _23 *= f; _24 *= f; + _31 *= f; _32 *= f; _33 *= f; _34 *= f; + _41 *= f; _42 *= f; _43 *= f; _44 *= f; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + _11 *= fInv; _12 *= fInv; _13 *= fInv; _14 *= fInv; + _21 *= fInv; _22 *= fInv; _23 *= fInv; _24 *= fInv; + _31 *= fInv; _32 *= fInv; _33 *= fInv; _34 *= fInv; + _41 *= fInv; _42 *= fInv; _43 *= fInv; _44 *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator - () const +{ + return D3DXMATRIX(-_11, -_12, -_13, -_14, + -_21, -_22, -_23, -_24, + -_31, -_32, -_33, -_34, + -_41, -_42, -_43, -_44); +} + + +// binary operators +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator * ( CONST D3DXMATRIX& mat ) const +{ + D3DXMATRIX matT; + D3DXMatrixMultiply(&matT, this, &mat); + return matT; +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator + ( CONST D3DXMATRIX& mat ) const +{ + return D3DXMATRIX(_11 + mat._11, _12 + mat._12, _13 + mat._13, _14 + mat._14, + _21 + mat._21, _22 + mat._22, _23 + mat._23, _24 + mat._24, + _31 + mat._31, _32 + mat._32, _33 + mat._33, _34 + mat._34, + _41 + mat._41, _42 + mat._42, _43 + mat._43, _44 + mat._44); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator - ( CONST D3DXMATRIX& mat ) const +{ + return D3DXMATRIX(_11 - mat._11, _12 - mat._12, _13 - mat._13, _14 - mat._14, + _21 - mat._21, _22 - mat._22, _23 - mat._23, _24 - mat._24, + _31 - mat._31, _32 - mat._32, _33 - mat._33, _34 - mat._34, + _41 - mat._41, _42 - mat._42, _43 - mat._43, _44 - mat._44); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator * ( FLOAT f ) const +{ + return D3DXMATRIX(_11 * f, _12 * f, _13 * f, _14 * f, + _21 * f, _22 * f, _23 * f, _24 * f, + _31 * f, _32 * f, _33 * f, _34 * f, + _41 * f, _42 * f, _43 * f, _44 * f); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXMATRIX(_11 * fInv, _12 * fInv, _13 * fInv, _14 * fInv, + _21 * fInv, _22 * fInv, _23 * fInv, _24 * fInv, + _31 * fInv, _32 * fInv, _33 * fInv, _34 * fInv, + _41 * fInv, _42 * fInv, _43 * fInv, _44 * fInv); +} + + +D3DXINLINE D3DXMATRIX +operator * ( FLOAT f, CONST D3DXMATRIX& mat ) +{ + return D3DXMATRIX(f * mat._11, f * mat._12, f * mat._13, f * mat._14, + f * mat._21, f * mat._22, f * mat._23, f * mat._24, + f * mat._31, f * mat._32, f * mat._33, f * mat._34, + f * mat._41, f * mat._42, f * mat._43, f * mat._44); +} + + +D3DXINLINE BOOL +D3DXMATRIX::operator == ( CONST D3DXMATRIX& mat ) const +{ + return 0 == memcmp(this, &mat, sizeof(D3DXMATRIX)); +} + +D3DXINLINE BOOL +D3DXMATRIX::operator != ( CONST D3DXMATRIX& mat ) const +{ + return 0 != memcmp(this, &mat, sizeof(D3DXMATRIX)); +} + + + +//-------------------------- +// Aligned Matrices +//-------------------------- + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST FLOAT* f ) : + D3DXMATRIX( f ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST D3DMATRIX& m ) : + D3DXMATRIX( m ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST D3DXFLOAT16* f ) : + D3DXMATRIX( f ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ) : + D3DXMATRIX(_11, _12, _13, _14, + _21, _22, _23, _24, + _31, _32, _33, _34, + _41, _42, _43, _44) +{ +} + +#ifndef SIZE_MAX +#define SIZE_MAX ((SIZE_T)-1) +#endif + +D3DXINLINE void* +_D3DXMATRIXA16::operator new( size_t s ) +{ + if (s > (SIZE_MAX-16)) + return NULL; + LPBYTE p = ::new BYTE[s + 16]; + if (p) + { + BYTE offset = (BYTE)(16 - ((UINT_PTR)p & 15)); + p += offset; + p[-1] = offset; + } + return p; +} + +D3DXINLINE void* +_D3DXMATRIXA16::operator new[]( size_t s ) +{ + if (s > (SIZE_MAX-16)) + return NULL; + LPBYTE p = ::new BYTE[s + 16]; + if (p) + { + BYTE offset = (BYTE)(16 - ((UINT_PTR)p & 15)); + p += offset; + p[-1] = offset; + } + return p; +} + +D3DXINLINE void +_D3DXMATRIXA16::operator delete(void* p) +{ + if(p) + { + BYTE* pb = static_cast(p); + pb -= pb[-1]; + ::delete [] pb; + } +} + +D3DXINLINE void +_D3DXMATRIXA16::operator delete[](void* p) +{ + if(p) + { + BYTE* pb = static_cast(p); + pb -= pb[-1]; + ::delete [] pb; + } +} + +D3DXINLINE _D3DXMATRIXA16& +_D3DXMATRIXA16::operator=(CONST D3DXMATRIX& rhs) +{ + memcpy(&_11, &rhs, sizeof(D3DXMATRIX)); + return *this; +} + + +//-------------------------- +// Quaternion +//-------------------------- + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; + w = pf[3]; +} + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 4); +} + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXQUATERNION::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXQUATERNION::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator += ( CONST D3DXQUATERNION& q ) +{ + x += q.x; + y += q.y; + z += q.z; + w += q.w; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator -= ( CONST D3DXQUATERNION& q ) +{ + x -= q.x; + y -= q.y; + z -= q.z; + w -= q.w; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator *= ( CONST D3DXQUATERNION& q ) +{ + D3DXQuaternionMultiply(this, this, &q); + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + w *= f; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + w *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator - () const +{ + return D3DXQUATERNION(-x, -y, -z, -w); +} + + +// binary operators +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator + ( CONST D3DXQUATERNION& q ) const +{ + return D3DXQUATERNION(x + q.x, y + q.y, z + q.z, w + q.w); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator - ( CONST D3DXQUATERNION& q ) const +{ + return D3DXQUATERNION(x - q.x, y - q.y, z - q.z, w - q.w); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator * ( CONST D3DXQUATERNION& q ) const +{ + D3DXQUATERNION qT; + D3DXQuaternionMultiply(&qT, this, &q); + return qT; +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator * ( FLOAT f ) const +{ + return D3DXQUATERNION(x * f, y * f, z * f, w * f); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXQUATERNION(x * fInv, y * fInv, z * fInv, w * fInv); +} + + +D3DXINLINE D3DXQUATERNION +operator * (FLOAT f, CONST D3DXQUATERNION& q ) +{ + return D3DXQUATERNION(f * q.x, f * q.y, f * q.z, f * q.w); +} + + +D3DXINLINE BOOL +D3DXQUATERNION::operator == ( CONST D3DXQUATERNION& q ) const +{ + return x == q.x && y == q.y && z == q.z && w == q.w; +} + +D3DXINLINE BOOL +D3DXQUATERNION::operator != ( CONST D3DXQUATERNION& q ) const +{ + return x != q.x || y != q.y || z != q.z || w != q.w; +} + + + +//-------------------------- +// Plane +//-------------------------- + +D3DXINLINE +D3DXPLANE::D3DXPLANE( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + a = pf[0]; + b = pf[1]; + c = pf[2]; + d = pf[3]; +} + +D3DXINLINE +D3DXPLANE::D3DXPLANE( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&a, pf, 4); +} + +D3DXINLINE +D3DXPLANE::D3DXPLANE( FLOAT fa, FLOAT fb, FLOAT fc, FLOAT fd ) +{ + a = fa; + b = fb; + c = fc; + d = fd; +} + + +// casting +D3DXINLINE +D3DXPLANE::operator FLOAT* () +{ + return (FLOAT *) &a; +} + +D3DXINLINE +D3DXPLANE::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &a; +} + + +// assignment operators +D3DXINLINE D3DXPLANE& +D3DXPLANE::operator *= ( FLOAT f ) +{ + a *= f; + b *= f; + c *= f; + d *= f; + return *this; +} + +D3DXINLINE D3DXPLANE& +D3DXPLANE::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + a *= fInv; + b *= fInv; + c *= fInv; + d *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXPLANE +D3DXPLANE::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXPLANE +D3DXPLANE::operator - () const +{ + return D3DXPLANE(-a, -b, -c, -d); +} + + +// binary operators +D3DXINLINE D3DXPLANE +D3DXPLANE::operator * ( FLOAT f ) const +{ + return D3DXPLANE(a * f, b * f, c * f, d * f); +} + +D3DXINLINE D3DXPLANE +D3DXPLANE::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXPLANE(a * fInv, b * fInv, c * fInv, d * fInv); +} + +D3DXINLINE D3DXPLANE +operator * (FLOAT f, CONST D3DXPLANE& p ) +{ + return D3DXPLANE(f * p.a, f * p.b, f * p.c, f * p.d); +} + +D3DXINLINE BOOL +D3DXPLANE::operator == ( CONST D3DXPLANE& p ) const +{ + return a == p.a && b == p.b && c == p.c && d == p.d; +} + +D3DXINLINE BOOL +D3DXPLANE::operator != ( CONST D3DXPLANE& p ) const +{ + return a != p.a || b != p.b || c != p.c || d != p.d; +} + + + + +//-------------------------- +// Color +//-------------------------- + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( DWORD dw ) +{ + CONST FLOAT f = 1.0f / 255.0f; + r = f * (FLOAT) (unsigned char) (dw >> 16); + g = f * (FLOAT) (unsigned char) (dw >> 8); + b = f * (FLOAT) (unsigned char) (dw >> 0); + a = f * (FLOAT) (unsigned char) (dw >> 24); +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + r = pf[0]; + g = pf[1]; + b = pf[2]; + a = pf[3]; +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&r, pf, 4); +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST D3DCOLORVALUE& c ) +{ + r = c.r; + g = c.g; + b = c.b; + a = c.a; +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( FLOAT fr, FLOAT fg, FLOAT fb, FLOAT fa ) +{ + r = fr; + g = fg; + b = fb; + a = fa; +} + + +// casting +D3DXINLINE +D3DXCOLOR::operator DWORD () const +{ + DWORD dwR = r >= 1.0f ? 0xff : r <= 0.0f ? 0x00 : (DWORD) (r * 255.0f + 0.5f); + DWORD dwG = g >= 1.0f ? 0xff : g <= 0.0f ? 0x00 : (DWORD) (g * 255.0f + 0.5f); + DWORD dwB = b >= 1.0f ? 0xff : b <= 0.0f ? 0x00 : (DWORD) (b * 255.0f + 0.5f); + DWORD dwA = a >= 1.0f ? 0xff : a <= 0.0f ? 0x00 : (DWORD) (a * 255.0f + 0.5f); + + return (dwA << 24) | (dwR << 16) | (dwG << 8) | dwB; +} + + +D3DXINLINE +D3DXCOLOR::operator FLOAT * () +{ + return (FLOAT *) &r; +} + +D3DXINLINE +D3DXCOLOR::operator CONST FLOAT * () const +{ + return (CONST FLOAT *) &r; +} + + +D3DXINLINE +D3DXCOLOR::operator D3DCOLORVALUE * () +{ + return (D3DCOLORVALUE *) &r; +} + +D3DXINLINE +D3DXCOLOR::operator CONST D3DCOLORVALUE * () const +{ + return (CONST D3DCOLORVALUE *) &r; +} + + +D3DXINLINE +D3DXCOLOR::operator D3DCOLORVALUE& () +{ + return *((D3DCOLORVALUE *) &r); +} + +D3DXINLINE +D3DXCOLOR::operator CONST D3DCOLORVALUE& () const +{ + return *((CONST D3DCOLORVALUE *) &r); +} + + +// assignment operators +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator += ( CONST D3DXCOLOR& c ) +{ + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator -= ( CONST D3DXCOLOR& c ) +{ + r -= c.r; + g -= c.g; + b -= c.b; + a -= c.a; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator *= ( FLOAT f ) +{ + r *= f; + g *= f; + b *= f; + a *= f; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + r *= fInv; + g *= fInv; + b *= fInv; + a *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator - () const +{ + return D3DXCOLOR(-r, -g, -b, -a); +} + + +// binary operators +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator + ( CONST D3DXCOLOR& c ) const +{ + return D3DXCOLOR(r + c.r, g + c.g, b + c.b, a + c.a); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator - ( CONST D3DXCOLOR& c ) const +{ + return D3DXCOLOR(r - c.r, g - c.g, b - c.b, a - c.a); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator * ( FLOAT f ) const +{ + return D3DXCOLOR(r * f, g * f, b * f, a * f); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXCOLOR(r * fInv, g * fInv, b * fInv, a * fInv); +} + + +D3DXINLINE D3DXCOLOR +operator * (FLOAT f, CONST D3DXCOLOR& c ) +{ + return D3DXCOLOR(f * c.r, f * c.g, f * c.b, f * c.a); +} + + +D3DXINLINE BOOL +D3DXCOLOR::operator == ( CONST D3DXCOLOR& c ) const +{ + return r == c.r && g == c.g && b == c.b && a == c.a; +} + +D3DXINLINE BOOL +D3DXCOLOR::operator != ( CONST D3DXCOLOR& c ) const +{ + return r != c.r || g != c.g || b != c.b || a != c.a; +} + + +#endif //__cplusplus + + + +//=========================================================================== +// +// Inline functions +// +//=========================================================================== + + +//-------------------------- +// 2D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec2Length + ( CONST D3DXVECTOR2 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y); +#endif +} + +D3DXINLINE FLOAT D3DXVec2LengthSq + ( CONST D3DXVECTOR2 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y; +} + +D3DXINLINE FLOAT D3DXVec2Dot + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y; +} + +D3DXINLINE FLOAT D3DXVec2CCW + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->y - pV1->y * pV2->x; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Add + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Subtract + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Minimize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Maximize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Scale + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Lerp + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + return pOut; +} + + +//-------------------------- +// 3D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec3Length + ( CONST D3DXVECTOR3 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z); +#endif +} + +D3DXINLINE FLOAT D3DXVec3LengthSq + ( CONST D3DXVECTOR3 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y + pV->z * pV->z; +} + +D3DXINLINE FLOAT D3DXVec3Dot + ( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Cross + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Add + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + pOut->z = pV1->z + pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Minimize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z < pV2->z ? pV1->z : pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Maximize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z > pV2->z ? pV1->z : pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Scale + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + pOut->z = pV->z * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Lerp + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + pOut->z = pV1->z + s * (pV2->z - pV1->z); + return pOut; +} + + +//-------------------------- +// 4D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec4Length + ( CONST D3DXVECTOR4 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w); +#endif +} + +D3DXINLINE FLOAT D3DXVec4LengthSq + ( CONST D3DXVECTOR4 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w; +} + +D3DXINLINE FLOAT D3DXVec4Dot + ( CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z + pV1->w * pV2->w; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Add + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + pOut->z = pV1->z + pV2->z; + pOut->w = pV1->w + pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Subtract + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + pOut->w = pV1->w - pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Minimize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z < pV2->z ? pV1->z : pV2->z; + pOut->w = pV1->w < pV2->w ? pV1->w : pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Maximize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z > pV2->z ? pV1->z : pV2->z; + pOut->w = pV1->w > pV2->w ? pV1->w : pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Scale + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + pOut->z = pV->z * s; + pOut->w = pV->w * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Lerp + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + pOut->z = pV1->z + s * (pV2->z - pV1->z); + pOut->w = pV1->w + s * (pV2->w - pV1->w); + return pOut; +} + + +//-------------------------- +// 4D Matrix +//-------------------------- + +D3DXINLINE D3DXMATRIX* D3DXMatrixIdentity + ( D3DXMATRIX *pOut ) +{ +#ifdef D3DX_DEBUG + if(!pOut) + return NULL; +#endif + + pOut->m[0][1] = pOut->m[0][2] = pOut->m[0][3] = + pOut->m[1][0] = pOut->m[1][2] = pOut->m[1][3] = + pOut->m[2][0] = pOut->m[2][1] = pOut->m[2][3] = + pOut->m[3][0] = pOut->m[3][1] = pOut->m[3][2] = 0.0f; + + pOut->m[0][0] = pOut->m[1][1] = pOut->m[2][2] = pOut->m[3][3] = 1.0f; + return pOut; +} + + +D3DXINLINE BOOL D3DXMatrixIsIdentity + ( CONST D3DXMATRIX *pM ) +{ +#ifdef D3DX_DEBUG + if(!pM) + return FALSE; +#endif + + return pM->m[0][0] == 1.0f && pM->m[0][1] == 0.0f && pM->m[0][2] == 0.0f && pM->m[0][3] == 0.0f && + pM->m[1][0] == 0.0f && pM->m[1][1] == 1.0f && pM->m[1][2] == 0.0f && pM->m[1][3] == 0.0f && + pM->m[2][0] == 0.0f && pM->m[2][1] == 0.0f && pM->m[2][2] == 1.0f && pM->m[2][3] == 0.0f && + pM->m[3][0] == 0.0f && pM->m[3][1] == 0.0f && pM->m[3][2] == 0.0f && pM->m[3][3] == 1.0f; +} + + +//-------------------------- +// Quaternion +//-------------------------- + +D3DXINLINE FLOAT D3DXQuaternionLength + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w); +#else + return (FLOAT) sqrt(pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w); +#endif +} + +D3DXINLINE FLOAT D3DXQuaternionLengthSq + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return 0.0f; +#endif + + return pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w; +} + +D3DXINLINE FLOAT D3DXQuaternionDot + ( CONST D3DXQUATERNION *pQ1, CONST D3DXQUATERNION *pQ2 ) +{ +#ifdef D3DX_DEBUG + if(!pQ1 || !pQ2) + return 0.0f; +#endif + + return pQ1->x * pQ2->x + pQ1->y * pQ2->y + pQ1->z * pQ2->z + pQ1->w * pQ2->w; +} + + +D3DXINLINE D3DXQUATERNION* D3DXQuaternionIdentity + ( D3DXQUATERNION *pOut ) +{ +#ifdef D3DX_DEBUG + if(!pOut) + return NULL; +#endif + + pOut->x = pOut->y = pOut->z = 0.0f; + pOut->w = 1.0f; + return pOut; +} + +D3DXINLINE BOOL D3DXQuaternionIsIdentity + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return FALSE; +#endif + + return pQ->x == 0.0f && pQ->y == 0.0f && pQ->z == 0.0f && pQ->w == 1.0f; +} + + +D3DXINLINE D3DXQUATERNION* D3DXQuaternionConjugate + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pQ) + return NULL; +#endif + + pOut->x = -pQ->x; + pOut->y = -pQ->y; + pOut->z = -pQ->z; + pOut->w = pQ->w; + return pOut; +} + + +//-------------------------- +// Plane +//-------------------------- + +D3DXINLINE FLOAT D3DXPlaneDot + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR4 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d * pV->w; +} + +D3DXINLINE FLOAT D3DXPlaneDotCoord + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d; +} + +D3DXINLINE FLOAT D3DXPlaneDotNormal + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z; +} + +D3DXINLINE D3DXPLANE* D3DXPlaneScale + (D3DXPLANE *pOut, CONST D3DXPLANE *pP, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pP) + return NULL; +#endif + + pOut->a = pP->a * s; + pOut->b = pP->b * s; + pOut->c = pP->c * s; + pOut->d = pP->d * s; + return pOut; +} + + +//-------------------------- +// Color +//-------------------------- + +D3DXINLINE D3DXCOLOR* D3DXColorNegative + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC) + return NULL; +#endif + + pOut->r = 1.0f - pC->r; + pOut->g = 1.0f - pC->g; + pOut->b = 1.0f - pC->b; + pOut->a = pC->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorAdd + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r + pC2->r; + pOut->g = pC1->g + pC2->g; + pOut->b = pC1->b + pC2->b; + pOut->a = pC1->a + pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorSubtract + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r - pC2->r; + pOut->g = pC1->g - pC2->g; + pOut->b = pC1->b - pC2->b; + pOut->a = pC1->a - pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorScale + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC) + return NULL; +#endif + + pOut->r = pC->r * s; + pOut->g = pC->g * s; + pOut->b = pC->b * s; + pOut->a = pC->a * s; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorModulate + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r * pC2->r; + pOut->g = pC1->g * pC2->g; + pOut->b = pC1->b * pC2->b; + pOut->a = pC1->a * pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorLerp + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r + s * (pC2->r - pC1->r); + pOut->g = pC1->g + s * (pC2->g - pC1->g); + pOut->b = pC1->b + s * (pC2->b - pC1->b); + pOut->a = pC1->a + s * (pC2->a - pC1->a); + return pOut; +} + + +#endif // __D3DX9MATH_INL__ + diff --git a/src/depend/mingw/include/directx9/d3dx9mesh.h b/src/depend/mingw/include/directx9/d3dx9mesh.h new file mode 100644 index 00000000..5ecbba1b --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9mesh.h @@ -0,0 +1,3007 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9mesh.h +// Content: D3DX mesh types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9MESH_H__ +#define __D3DX9MESH_H__ + +// {7ED943DD-52E8-40b5-A8D8-76685C406330} +DEFINE_GUID(IID_ID3DXBaseMesh, +0x7ed943dd, 0x52e8, 0x40b5, 0xa8, 0xd8, 0x76, 0x68, 0x5c, 0x40, 0x63, 0x30); + +// {4020E5C2-1403-4929-883F-E2E849FAC195} +DEFINE_GUID(IID_ID3DXMesh, +0x4020e5c2, 0x1403, 0x4929, 0x88, 0x3f, 0xe2, 0xe8, 0x49, 0xfa, 0xc1, 0x95); + +// {8875769A-D579-4088-AAEB-534D1AD84E96} +DEFINE_GUID(IID_ID3DXPMesh, +0x8875769a, 0xd579, 0x4088, 0xaa, 0xeb, 0x53, 0x4d, 0x1a, 0xd8, 0x4e, 0x96); + +// {667EA4C7-F1CD-4386-B523-7C0290B83CC5} +DEFINE_GUID(IID_ID3DXSPMesh, +0x667ea4c7, 0xf1cd, 0x4386, 0xb5, 0x23, 0x7c, 0x2, 0x90, 0xb8, 0x3c, 0xc5); + +// {11EAA540-F9A6-4d49-AE6A-E19221F70CC4} +DEFINE_GUID(IID_ID3DXSkinInfo, +0x11eaa540, 0xf9a6, 0x4d49, 0xae, 0x6a, 0xe1, 0x92, 0x21, 0xf7, 0xc, 0xc4); + +// {3CE6CC22-DBF2-44f4-894D-F9C34A337139} +DEFINE_GUID(IID_ID3DXPatchMesh, +0x3ce6cc22, 0xdbf2, 0x44f4, 0x89, 0x4d, 0xf9, 0xc3, 0x4a, 0x33, 0x71, 0x39); + +//patch mesh can be quads or tris +typedef enum _D3DXPATCHMESHTYPE { + D3DXPATCHMESH_RECT = 0x001, + D3DXPATCHMESH_TRI = 0x002, + D3DXPATCHMESH_NPATCH = 0x003, + + D3DXPATCHMESH_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ +} D3DXPATCHMESHTYPE; + +// Mesh options - lower 3 bytes only, upper byte used by _D3DXMESHOPT option flags +enum _D3DXMESH { + D3DXMESH_32BIT = 0x001, // If set, then use 32 bit indices, if not set use 16 bit indices. + D3DXMESH_DONOTCLIP = 0x002, // Use D3DUSAGE_DONOTCLIP for VB & IB. + D3DXMESH_POINTS = 0x004, // Use D3DUSAGE_POINTS for VB & IB. + D3DXMESH_RTPATCHES = 0x008, // Use D3DUSAGE_RTPATCHES for VB & IB. + D3DXMESH_NPATCHES = 0x4000,// Use D3DUSAGE_NPATCHES for VB & IB. + D3DXMESH_VB_SYSTEMMEM = 0x010, // Use D3DPOOL_SYSTEMMEM for VB. Overrides D3DXMESH_MANAGEDVERTEXBUFFER + D3DXMESH_VB_MANAGED = 0x020, // Use D3DPOOL_MANAGED for VB. + D3DXMESH_VB_WRITEONLY = 0x040, // Use D3DUSAGE_WRITEONLY for VB. + D3DXMESH_VB_DYNAMIC = 0x080, // Use D3DUSAGE_DYNAMIC for VB. + D3DXMESH_VB_SOFTWAREPROCESSING = 0x8000, // Use D3DUSAGE_SOFTWAREPROCESSING for VB. + D3DXMESH_IB_SYSTEMMEM = 0x100, // Use D3DPOOL_SYSTEMMEM for IB. Overrides D3DXMESH_MANAGEDINDEXBUFFER + D3DXMESH_IB_MANAGED = 0x200, // Use D3DPOOL_MANAGED for IB. + D3DXMESH_IB_WRITEONLY = 0x400, // Use D3DUSAGE_WRITEONLY for IB. + D3DXMESH_IB_DYNAMIC = 0x800, // Use D3DUSAGE_DYNAMIC for IB. + D3DXMESH_IB_SOFTWAREPROCESSING= 0x10000, // Use D3DUSAGE_SOFTWAREPROCESSING for IB. + + D3DXMESH_VB_SHARE = 0x1000, // Valid for Clone* calls only, forces cloned mesh/pmesh to share vertex buffer + + D3DXMESH_USEHWONLY = 0x2000, // Valid for ID3DXSkinInfo::ConvertToBlendedMesh + + // Helper options + D3DXMESH_SYSTEMMEM = 0x110, // D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM + D3DXMESH_MANAGED = 0x220, // D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED + D3DXMESH_WRITEONLY = 0x440, // D3DXMESH_VB_WRITEONLY | D3DXMESH_IB_WRITEONLY + D3DXMESH_DYNAMIC = 0x880, // D3DXMESH_VB_DYNAMIC | D3DXMESH_IB_DYNAMIC + D3DXMESH_SOFTWAREPROCESSING = 0x18000 // D3DXMESH_VB_SOFTWAREPROCESSING | D3DXMESH_IB_SOFTWAREPROCESSING + +}; + +//patch mesh options +enum _D3DXPATCHMESH { + D3DXPATCHMESH_DEFAULT = 000 +}; +// option field values for specifying min value in D3DXGeneratePMesh and D3DXSimplifyMesh +enum _D3DXMESHSIMP +{ + D3DXMESHSIMP_VERTEX = 0x1, + D3DXMESHSIMP_FACE = 0x2 + +}; + +typedef enum _D3DXCLEANTYPE { + D3DXCLEAN_BACKFACING = 0x00000001, + D3DXCLEAN_BOWTIES = 0x00000002, + + // Helper options + D3DXCLEAN_SKINNING = D3DXCLEAN_BACKFACING, // Bowtie cleaning modifies geometry and breaks skinning + D3DXCLEAN_OPTIMIZATION = D3DXCLEAN_BACKFACING, + D3DXCLEAN_SIMPLIFICATION= D3DXCLEAN_BACKFACING | D3DXCLEAN_BOWTIES +} D3DXCLEANTYPE; + +enum _MAX_FVF_DECL_SIZE +{ + MAX_FVF_DECL_SIZE = MAXD3DDECLLENGTH + 1 // +1 for END +}; + +typedef enum _D3DXTANGENT +{ + D3DXTANGENT_WRAP_U = 0x01, + D3DXTANGENT_WRAP_V = 0x02, + D3DXTANGENT_WRAP_UV = 0x03, + D3DXTANGENT_DONT_NORMALIZE_PARTIALS = 0x04, + D3DXTANGENT_DONT_ORTHOGONALIZE = 0x08, + D3DXTANGENT_ORTHOGONALIZE_FROM_V = 0x010, + D3DXTANGENT_ORTHOGONALIZE_FROM_U = 0x020, + D3DXTANGENT_WEIGHT_BY_AREA = 0x040, + D3DXTANGENT_WEIGHT_EQUAL = 0x080, + D3DXTANGENT_WIND_CW = 0x0100, + D3DXTANGENT_CALCULATE_NORMALS = 0x0200, + D3DXTANGENT_GENERATE_IN_PLACE = 0x0400 +} D3DXTANGENT; + +// D3DXIMT_WRAP_U means the texture wraps in the U direction +// D3DXIMT_WRAP_V means the texture wraps in the V direction +// D3DXIMT_WRAP_UV means the texture wraps in both directions +typedef enum _D3DXIMT +{ + D3DXIMT_WRAP_U = 0x01, + D3DXIMT_WRAP_V = 0x02, + D3DXIMT_WRAP_UV = 0x03 +} D3DXIMT; + +// These options are only valid for UVAtlasCreate and UVAtlasPartition, we may add more for UVAtlasPack if necessary +// D3DXUVATLAS_DEFAULT - Meshes with more than 25k faces go through fast, meshes with fewer than 25k faces go through quality +// D3DXUVATLAS_GEODESIC_FAST - Uses approximations to improve charting speed at the cost of added stretch or more charts. +// D3DXUVATLAS_GEODESIC_QUALITY - Provides better quality charts, but requires more time and memory than fast. +typedef enum _D3DXUVATLAS +{ + D3DXUVATLAS_DEFAULT = 0x00, + D3DXUVATLAS_GEODESIC_FAST = 0x01, + D3DXUVATLAS_GEODESIC_QUALITY = 0x02 +} D3DXUVATLAS; + +typedef struct ID3DXBaseMesh *LPD3DXBASEMESH; +typedef struct ID3DXMesh *LPD3DXMESH; +typedef struct ID3DXPMesh *LPD3DXPMESH; +typedef struct ID3DXSPMesh *LPD3DXSPMESH; +typedef struct ID3DXSkinInfo *LPD3DXSKININFO; +typedef struct ID3DXPatchMesh *LPD3DXPATCHMESH; +typedef interface ID3DXTextureGutterHelper *LPD3DXTEXTUREGUTTERHELPER; +typedef interface ID3DXPRTBuffer *LPD3DXPRTBUFFER; + + +typedef struct _D3DXATTRIBUTERANGE +{ + DWORD AttribId; + DWORD FaceStart; + DWORD FaceCount; + DWORD VertexStart; + DWORD VertexCount; +} D3DXATTRIBUTERANGE; + +typedef D3DXATTRIBUTERANGE* LPD3DXATTRIBUTERANGE; + +typedef struct _D3DXMATERIAL +{ + D3DMATERIAL9 MatD3D; + LPSTR pTextureFilename; +} D3DXMATERIAL; +typedef D3DXMATERIAL *LPD3DXMATERIAL; + +typedef enum _D3DXEFFECTDEFAULTTYPE +{ + D3DXEDT_STRING = 0x1, // pValue points to a null terminated ASCII string + D3DXEDT_FLOATS = 0x2, // pValue points to an array of floats - number of floats is NumBytes / sizeof(float) + D3DXEDT_DWORD = 0x3, // pValue points to a DWORD + + D3DXEDT_FORCEDWORD = 0x7fffffff +} D3DXEFFECTDEFAULTTYPE; + +typedef struct _D3DXEFFECTDEFAULT +{ + LPSTR pParamName; + D3DXEFFECTDEFAULTTYPE Type; // type of the data pointed to by pValue + DWORD NumBytes; // size in bytes of the data pointed to by pValue + LPVOID pValue; // data for the default of the effect +} D3DXEFFECTDEFAULT, *LPD3DXEFFECTDEFAULT; + +typedef struct _D3DXEFFECTINSTANCE +{ + LPSTR pEffectFilename; + DWORD NumDefaults; + LPD3DXEFFECTDEFAULT pDefaults; +} D3DXEFFECTINSTANCE, *LPD3DXEFFECTINSTANCE; + +typedef struct _D3DXATTRIBUTEWEIGHTS +{ + FLOAT Position; + FLOAT Boundary; + FLOAT Normal; + FLOAT Diffuse; + FLOAT Specular; + FLOAT Texcoord[8]; + FLOAT Tangent; + FLOAT Binormal; +} D3DXATTRIBUTEWEIGHTS, *LPD3DXATTRIBUTEWEIGHTS; + +enum _D3DXWELDEPSILONSFLAGS +{ + D3DXWELDEPSILONS_WELDALL = 0x1, // weld all vertices marked by adjacency as being overlapping + + D3DXWELDEPSILONS_WELDPARTIALMATCHES = 0x2, // if a given vertex component is within epsilon, modify partial matched + // vertices so that both components identical AND if all components "equal" + // remove one of the vertices + D3DXWELDEPSILONS_DONOTREMOVEVERTICES = 0x4, // instructs weld to only allow modifications to vertices and not removal + // ONLY valid if D3DXWELDEPSILONS_WELDPARTIALMATCHES is set + // useful to modify vertices to be equal, but not allow vertices to be removed + + D3DXWELDEPSILONS_DONOTSPLIT = 0x8 // instructs weld to specify the D3DXMESHOPT_DONOTSPLIT flag when doing an Optimize(ATTR_SORT) + // if this flag is not set, all vertices that are in separate attribute groups + // will remain split and not welded. Setting this flag can slow down software vertex processing + +}; + +typedef struct _D3DXWELDEPSILONS +{ + FLOAT Position; // NOTE: This does NOT replace the epsilon in GenerateAdjacency + // in general, it should be the same value or greater than the one passed to GeneratedAdjacency + FLOAT BlendWeights; + FLOAT Normal; + FLOAT PSize; + FLOAT Specular; + FLOAT Diffuse; + FLOAT Texcoord[8]; + FLOAT Tangent; + FLOAT Binormal; + FLOAT TessFactor; +} D3DXWELDEPSILONS; + +typedef D3DXWELDEPSILONS* LPD3DXWELDEPSILONS; + + +#undef INTERFACE +#define INTERFACE ID3DXBaseMesh + +DECLARE_INTERFACE_(ID3DXBaseMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXMesh + +DECLARE_INTERFACE_(ID3DXMesh, ID3DXBaseMesh) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // ID3DXMesh + STDMETHOD(LockAttributeBuffer)(THIS_ DWORD Flags, DWORD** ppData) PURE; + STDMETHOD(UnlockAttributeBuffer)(THIS) PURE; + STDMETHOD(Optimize)(THIS_ DWORD Flags, CONST DWORD* pAdjacencyIn, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap, + LPD3DXMESH* ppOptMesh) PURE; + STDMETHOD(OptimizeInplace)(THIS_ DWORD Flags, CONST DWORD* pAdjacencyIn, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap) PURE; + STDMETHOD(SetAttributeTable)(THIS_ CONST D3DXATTRIBUTERANGE *pAttribTable, DWORD cAttribTableSize) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXPMesh + +DECLARE_INTERFACE_(ID3DXPMesh, ID3DXBaseMesh) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // ID3DXPMesh + STDMETHOD(ClonePMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(SetNumFaces)(THIS_ DWORD Faces) PURE; + STDMETHOD(SetNumVertices)(THIS_ DWORD Vertices) PURE; + STDMETHOD_(DWORD, GetMaxFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMinFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMaxVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetMinVertices)(THIS) PURE; + STDMETHOD(Save)(THIS_ IStream *pStream, CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances, DWORD NumMaterials) PURE; + + STDMETHOD(Optimize)(THIS_ DWORD Flags, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap, + LPD3DXMESH* ppOptMesh) PURE; + + STDMETHOD(OptimizeBaseLOD)(THIS_ DWORD Flags, DWORD* pFaceRemap) PURE; + STDMETHOD(TrimByFaces)(THIS_ DWORD NewFacesMin, DWORD NewFacesMax, DWORD *rgiFaceRemap, DWORD *rgiVertRemap) PURE; + STDMETHOD(TrimByVertices)(THIS_ DWORD NewVerticesMin, DWORD NewVerticesMax, DWORD *rgiFaceRemap, DWORD *rgiVertRemap) PURE; + + STDMETHOD(GetAdjacency)(THIS_ DWORD* pAdjacency) PURE; + + // Used to generate the immediate "ancestor" for each vertex when it is removed by a vsplit. Allows generation of geomorphs + // Vertex buffer must be equal to or greater than the maximum number of vertices in the pmesh + STDMETHOD(GenerateVertexHistory)(THIS_ DWORD* pVertexHistory) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXSPMesh + +DECLARE_INTERFACE_(ID3DXSPMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXSPMesh + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pAdjacencyOut, DWORD *pVertexRemapOut, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pAdjacencyOut, DWORD *pVertexRemapOut, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pVertexRemapOut, FLOAT *pErrorsByFace, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pVertexRemapOut, FLOAT *pErrorsbyFace, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ReduceFaces)(THIS_ DWORD Faces) PURE; + STDMETHOD(ReduceVertices)(THIS_ DWORD Vertices) PURE; + STDMETHOD_(DWORD, GetMaxFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMaxVertices)(THIS) PURE; + STDMETHOD(GetVertexAttributeWeights)(THIS_ LPD3DXATTRIBUTEWEIGHTS pVertexAttributeWeights) PURE; + STDMETHOD(GetVertexWeights)(THIS_ FLOAT *pVertexWeights) PURE; +}; + +#define UNUSED16 (0xffff) +#define UNUSED32 (0xffffffff) + +// ID3DXMesh::Optimize options - upper byte only, lower 3 bytes used from _D3DXMESH option flags +enum _D3DXMESHOPT { + D3DXMESHOPT_COMPACT = 0x01000000, + D3DXMESHOPT_ATTRSORT = 0x02000000, + D3DXMESHOPT_VERTEXCACHE = 0x04000000, + D3DXMESHOPT_STRIPREORDER = 0x08000000, + D3DXMESHOPT_IGNOREVERTS = 0x10000000, // optimize faces only, don't touch vertices + D3DXMESHOPT_DONOTSPLIT = 0x20000000, // do not split vertices shared between attribute groups when attribute sorting + D3DXMESHOPT_DEVICEINDEPENDENT = 0x00400000 // Only affects VCache. uses a static known good cache size for all cards + + // D3DXMESHOPT_SHAREVB has been removed, please use D3DXMESH_VB_SHARE instead + +}; + +// Subset of the mesh that has the same attribute and bone combination. +// This subset can be rendered in a single draw call +typedef struct _D3DXBONECOMBINATION +{ + DWORD AttribId; + DWORD FaceStart; + DWORD FaceCount; + DWORD VertexStart; + DWORD VertexCount; + DWORD* BoneId; +} D3DXBONECOMBINATION, *LPD3DXBONECOMBINATION; + +// The following types of patch combinations are supported: +// Patch type Basis Degree +// Rect Bezier 2,3,5 +// Rect B-Spline 2,3,5 +// Rect Catmull-Rom 3 +// Tri Bezier 2,3,5 +// N-Patch N/A 3 + +typedef struct _D3DXPATCHINFO +{ + D3DXPATCHMESHTYPE PatchType; + D3DDEGREETYPE Degree; + D3DBASISTYPE Basis; +} D3DXPATCHINFO, *LPD3DXPATCHINFO; + +#undef INTERFACE +#define INTERFACE ID3DXPatchMesh + +DECLARE_INTERFACE_(ID3DXPatchMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPatchMesh + + // Return creation parameters + STDMETHOD_(DWORD, GetNumPatches)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetControlVerticesPerPatch)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9 *ppDevice) PURE; + STDMETHOD(GetPatchInfo)(THIS_ LPD3DXPATCHINFO PatchInfo) PURE; + + // Control mesh access + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(LockAttributeBuffer)(THIS_ DWORD flags, DWORD** ppData) PURE; + STDMETHOD(UnlockAttributeBuffer)(THIS) PURE; + + // This function returns the size of the tessellated mesh given a tessellation level. + // This assumes uniform tessellation. For adaptive tessellation the Adaptive parameter must + // be set to TRUE and TessellationLevel should be the max tessellation. + // This will result in the max mesh size necessary for adaptive tessellation. + STDMETHOD(GetTessSize)(THIS_ FLOAT fTessLevel,DWORD Adaptive, DWORD *NumTriangles,DWORD *NumVertices) PURE; + + //GenerateAdjacency determines which patches are adjacent with provided tolerance + //this information is used internally to optimize tessellation + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Tolerance) PURE; + + //CloneMesh Creates a new patchmesh with the specified decl, and converts the vertex buffer + //to the new decl. Entries in the new decl which are new are set to 0. If the current mesh + //has adjacency, the new mesh will also have adjacency + STDMETHOD(CloneMesh)(THIS_ DWORD Options, CONST D3DVERTEXELEMENT9 *pDecl, LPD3DXPATCHMESH *pMesh) PURE; + + // Optimizes the patchmesh for efficient tessellation. This function is designed + // to perform one time optimization for patch meshes that need to be tessellated + // repeatedly by calling the Tessellate() method. The optimization performed is + // independent of the actual tessellation level used. + // Currently Flags is unused. + // If vertices are changed, Optimize must be called again + STDMETHOD(Optimize)(THIS_ DWORD flags) PURE; + + //gets and sets displacement parameters + //displacement maps can only be 2D textures MIP-MAPPING is ignored for non adapative tessellation + STDMETHOD(SetDisplaceParam)(THIS_ LPDIRECT3DBASETEXTURE9 Texture, + D3DTEXTUREFILTERTYPE MinFilter, + D3DTEXTUREFILTERTYPE MagFilter, + D3DTEXTUREFILTERTYPE MipFilter, + D3DTEXTUREADDRESS Wrap, + DWORD dwLODBias) PURE; + + STDMETHOD(GetDisplaceParam)(THIS_ LPDIRECT3DBASETEXTURE9 *Texture, + D3DTEXTUREFILTERTYPE *MinFilter, + D3DTEXTUREFILTERTYPE *MagFilter, + D3DTEXTUREFILTERTYPE *MipFilter, + D3DTEXTUREADDRESS *Wrap, + DWORD *dwLODBias) PURE; + + // Performs the uniform tessellation based on the tessellation level. + // This function will perform more efficiently if the patch mesh has been optimized using the Optimize() call. + STDMETHOD(Tessellate)(THIS_ FLOAT fTessLevel,LPD3DXMESH pMesh) PURE; + + // Performs adaptive tessellation based on the Z based adaptive tessellation criterion. + // pTrans specifies a 4D vector that is dotted with the vertices to get the per vertex + // adaptive tessellation amount. Each edge is tessellated to the average of the criterion + // at the 2 vertices it connects. + // MaxTessLevel specifies the upper limit for adaptive tesselation. + // This function will perform more efficiently if the patch mesh has been optimized using the Optimize() call. + STDMETHOD(TessellateAdaptive)(THIS_ + CONST D3DXVECTOR4 *pTrans, + DWORD dwMaxTessLevel, + DWORD dwMinTessLevel, + LPD3DXMESH pMesh) PURE; + +}; + +#undef INTERFACE +#define INTERFACE ID3DXSkinInfo + +DECLARE_INTERFACE_(ID3DXSkinInfo, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Specify the which vertices do each bones influence and by how much + STDMETHOD(SetBoneInfluence)(THIS_ DWORD bone, DWORD numInfluences, CONST DWORD* vertices, CONST FLOAT* weights) PURE; + STDMETHOD(SetBoneVertexInfluence)(THIS_ DWORD boneNum, DWORD influenceNum, float weight) PURE; + STDMETHOD_(DWORD, GetNumBoneInfluences)(THIS_ DWORD bone) PURE; + STDMETHOD(GetBoneInfluence)(THIS_ DWORD bone, DWORD* vertices, FLOAT* weights) PURE; + STDMETHOD(GetBoneVertexInfluence)(THIS_ DWORD boneNum, DWORD influenceNum, float *pWeight, DWORD *pVertexNum) PURE; + STDMETHOD(GetMaxVertexInfluences)(THIS_ DWORD* maxVertexInfluences) PURE; + STDMETHOD_(DWORD, GetNumBones)(THIS) PURE; + STDMETHOD(FindBoneVertexInfluenceIndex)(THIS_ DWORD boneNum, DWORD vertexNum, DWORD *pInfluenceIndex) PURE; + + // This gets the max face influences based on a triangle mesh with the specified index buffer + STDMETHOD(GetMaxFaceInfluences)(THIS_ LPDIRECT3DINDEXBUFFER9 pIB, DWORD NumFaces, DWORD* maxFaceInfluences) PURE; + + // Set min bone influence. Bone influences that are smaller than this are ignored + STDMETHOD(SetMinBoneInfluence)(THIS_ FLOAT MinInfl) PURE; + // Get min bone influence. + STDMETHOD_(FLOAT, GetMinBoneInfluence)(THIS) PURE; + + // Bone names are returned by D3DXLoadSkinMeshFromXof. They are not used by any other method of this object + STDMETHOD(SetBoneName)(THIS_ DWORD Bone, LPCSTR pName) PURE; // pName is copied to an internal string buffer + STDMETHOD_(LPCSTR, GetBoneName)(THIS_ DWORD Bone) PURE; // A pointer to an internal string buffer is returned. Do not free this. + + // Bone offset matrices are returned by D3DXLoadSkinMeshFromXof. They are not used by any other method of this object + STDMETHOD(SetBoneOffsetMatrix)(THIS_ DWORD Bone, CONST D3DXMATRIX *pBoneTransform) PURE; // pBoneTransform is copied to an internal buffer + STDMETHOD_(LPD3DXMATRIX, GetBoneOffsetMatrix)(THIS_ DWORD Bone) PURE; // A pointer to an internal matrix is returned. Do not free this. + + // Clone a skin info object + STDMETHOD(Clone)(THIS_ LPD3DXSKININFO* ppSkinInfo) PURE; + + // Update bone influence information to match vertices after they are reordered. This should be called + // if the target vertex buffer has been reordered externally. + STDMETHOD(Remap)(THIS_ DWORD NumVertices, DWORD* pVertexRemap) PURE; + + // These methods enable the modification of the vertex layout of the vertices that will be skinned + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(SetDeclaration)(THIS_ CONST D3DVERTEXELEMENT9 *pDeclaration) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // Apply SW skinning based on current pose matrices to the target vertices. + STDMETHOD(UpdateSkinnedMesh)(THIS_ + CONST D3DXMATRIX* pBoneTransforms, + CONST D3DXMATRIX* pBoneInvTransposeTransforms, + LPCVOID pVerticesSrc, + PVOID pVerticesDst) PURE; + + // Takes a mesh and returns a new mesh with per vertex blend weights and a bone combination + // table that describes which bones affect which subsets of the mesh + STDMETHOD(ConvertToBlendedMesh)(THIS_ + LPD3DXMESH pMesh, + DWORD Options, + CONST DWORD *pAdjacencyIn, + LPDWORD pAdjacencyOut, + DWORD* pFaceRemap, + LPD3DXBUFFER *ppVertexRemap, + DWORD* pMaxFaceInfl, + DWORD* pNumBoneCombinations, + LPD3DXBUFFER* ppBoneCombinationTable, + LPD3DXMESH* ppMesh) PURE; + + // Takes a mesh and returns a new mesh with per vertex blend weights and indices + // and a bone combination table that describes which bones palettes affect which subsets of the mesh + STDMETHOD(ConvertToIndexedBlendedMesh)(THIS_ + LPD3DXMESH pMesh, + DWORD Options, + DWORD paletteSize, + CONST DWORD *pAdjacencyIn, + LPDWORD pAdjacencyOut, + DWORD* pFaceRemap, + LPD3DXBUFFER *ppVertexRemap, + DWORD* pMaxVertexInfl, + DWORD* pNumBoneCombinations, + LPD3DXBUFFER* ppBoneCombinationTable, + LPD3DXMESH* ppMesh) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateMesh( + DWORD NumFaces, + DWORD NumVertices, + DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXCreateMeshFVF( + DWORD NumFaces, + DWORD NumVertices, + DWORD Options, + DWORD FVF, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXCreateSPMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + LPD3DXSPMESH* ppSMesh); + +// clean a mesh up for simplification, try to make manifold +HRESULT WINAPI + D3DXCleanMesh( + D3DXCLEANTYPE CleanType, + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacencyIn, + LPD3DXMESH* ppMeshOut, + DWORD* pAdjacencyOut, + LPD3DXBUFFER* ppErrorsAndWarnings); + +HRESULT WINAPI + D3DXValidMesh( + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacency, + LPD3DXBUFFER* ppErrorsAndWarnings); + +HRESULT WINAPI + D3DXGeneratePMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + DWORD MinValue, + DWORD Options, + LPD3DXPMESH* ppPMesh); + +HRESULT WINAPI + D3DXSimplifyMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + DWORD MinValue, + DWORD Options, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXComputeBoundingSphere( + CONST D3DXVECTOR3 *pFirstPosition, // pointer to first position + DWORD NumVertices, + DWORD dwStride, // count in bytes to subsequent position vectors + D3DXVECTOR3 *pCenter, + FLOAT *pRadius); + +HRESULT WINAPI + D3DXComputeBoundingBox( + CONST D3DXVECTOR3 *pFirstPosition, // pointer to first position + DWORD NumVertices, + DWORD dwStride, // count in bytes to subsequent position vectors + D3DXVECTOR3 *pMin, + D3DXVECTOR3 *pMax); + +HRESULT WINAPI + D3DXComputeNormals( + LPD3DXBASEMESH pMesh, + CONST DWORD *pAdjacency); + +HRESULT WINAPI + D3DXCreateBuffer( + DWORD NumBytes, + LPD3DXBUFFER *ppBuffer); + + +HRESULT WINAPI + D3DXLoadMeshFromXA( + LPCSTR pFilename, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXLoadMeshFromXW( + LPCWSTR pFilename, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +#ifdef UNICODE +#define D3DXLoadMeshFromX D3DXLoadMeshFromXW +#else +#define D3DXLoadMeshFromX D3DXLoadMeshFromXA +#endif + +HRESULT WINAPI + D3DXLoadMeshFromXInMemory( + LPCVOID Memory, + DWORD SizeOfMemory, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXLoadMeshFromXResource( + HMODULE Module, + LPCSTR Name, + LPCSTR Type, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXSaveMeshToXA( + LPCSTR pFilename, + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXMATERIAL* pMaterials, + CONST D3DXEFFECTINSTANCE* pEffectInstances, + DWORD NumMaterials, + DWORD Format + ); + +HRESULT WINAPI + D3DXSaveMeshToXW( + LPCWSTR pFilename, + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXMATERIAL* pMaterials, + CONST D3DXEFFECTINSTANCE* pEffectInstances, + DWORD NumMaterials, + DWORD Format + ); + +#ifdef UNICODE +#define D3DXSaveMeshToX D3DXSaveMeshToXW +#else +#define D3DXSaveMeshToX D3DXSaveMeshToXA +#endif + + +HRESULT WINAPI + D3DXCreatePMeshFromStream( + IStream *pStream, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD* pNumMaterials, + LPD3DXPMESH *ppPMesh); + +// Creates a skin info object based on the number of vertices, number of bones, and a declaration describing the vertex layout of the target vertices +// The bone names and initial bone transforms are not filled in the skin info object by this method. +HRESULT WINAPI + D3DXCreateSkinInfo( + DWORD NumVertices, + CONST D3DVERTEXELEMENT9 *pDeclaration, + DWORD NumBones, + LPD3DXSKININFO* ppSkinInfo); + +// Creates a skin info object based on the number of vertices, number of bones, and a FVF describing the vertex layout of the target vertices +// The bone names and initial bone transforms are not filled in the skin info object by this method. +HRESULT WINAPI + D3DXCreateSkinInfoFVF( + DWORD NumVertices, + DWORD FVF, + DWORD NumBones, + LPD3DXSKININFO* ppSkinInfo); + +#ifdef __cplusplus +} + +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXLoadMeshFromXof( + LPD3DXFILEDATA pxofMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +// This similar to D3DXLoadMeshFromXof, except also returns skinning info if present in the file +// If skinning info is not present, ppSkinInfo will be NULL +HRESULT WINAPI + D3DXLoadSkinMeshFromXof( + LPD3DXFILEDATA pxofMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER* ppAdjacency, + LPD3DXBUFFER* ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pMatOut, + LPD3DXSKININFO* ppSkinInfo, + LPD3DXMESH* ppMesh); + + +// The inverse of D3DXConvertTo{Indexed}BlendedMesh() functions. It figures out the skinning info from +// the mesh and the bone combination table and populates a skin info object with that data. The bone +// names and initial bone transforms are not filled in the skin info object by this method. This works +// with either a non-indexed or indexed blended mesh. It examines the FVF or declarator of the mesh to +// determine what type it is. +HRESULT WINAPI + D3DXCreateSkinInfoFromBlendedMesh( + LPD3DXBASEMESH pMesh, + DWORD NumBones, + CONST D3DXBONECOMBINATION *pBoneCombinationTable, + LPD3DXSKININFO* ppSkinInfo); + +HRESULT WINAPI + D3DXTessellateNPatches( + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacencyIn, + FLOAT NumSegs, + BOOL QuadraticInterpNormals, // if false use linear intrep for normals, if true use quadratic + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppAdjacencyOut); + + +//generates implied outputdecl from input decl +//the decl generated from this should be used to generate the output decl for +//the tessellator subroutines. + +HRESULT WINAPI + D3DXGenerateOutputDecl( + D3DVERTEXELEMENT9 *pOutput, + CONST D3DVERTEXELEMENT9 *pInput); + +//loads patches from an XFileData +//since an X file can have up to 6 different patch meshes in it, +//returns them in an array - pNumPatches will contain the number of +//meshes in the actual file. +HRESULT WINAPI + D3DXLoadPatchMeshFromXof( + LPD3DXFILEDATA pXofObjMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + PDWORD pNumMaterials, + LPD3DXPATCHMESH *ppMesh); + +//computes the size a single rect patch. +HRESULT WINAPI + D3DXRectPatchSize( + CONST FLOAT *pfNumSegs, //segments for each edge (4) + DWORD *pdwTriangles, //output number of triangles + DWORD *pdwVertices); //output number of vertices + +//computes the size of a single triangle patch +HRESULT WINAPI + D3DXTriPatchSize( + CONST FLOAT *pfNumSegs, //segments for each edge (3) + DWORD *pdwTriangles, //output number of triangles + DWORD *pdwVertices); //output number of vertices + + +//tessellates a patch into a created mesh +//similar to D3D RT patch +HRESULT WINAPI + D3DXTessellateRectPatch( + LPDIRECT3DVERTEXBUFFER9 pVB, + CONST FLOAT *pNumSegs, + CONST D3DVERTEXELEMENT9 *pdwInDecl, + CONST D3DRECTPATCH_INFO *pRectPatchInfo, + LPD3DXMESH pMesh); + + +HRESULT WINAPI + D3DXTessellateTriPatch( + LPDIRECT3DVERTEXBUFFER9 pVB, + CONST FLOAT *pNumSegs, + CONST D3DVERTEXELEMENT9 *pInDecl, + CONST D3DTRIPATCH_INFO *pTriPatchInfo, + LPD3DXMESH pMesh); + + + +//creates an NPatch PatchMesh from a D3DXMESH +HRESULT WINAPI + D3DXCreateNPatchMesh( + LPD3DXMESH pMeshSysMem, + LPD3DXPATCHMESH *pPatchMesh); + + +//creates a patch mesh +HRESULT WINAPI + D3DXCreatePatchMesh( + CONST D3DXPATCHINFO *pInfo, //patch type + DWORD dwNumPatches, //number of patches + DWORD dwNumVertices, //number of control vertices + DWORD dwOptions, //options + CONST D3DVERTEXELEMENT9 *pDecl, //format of control vertices + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXPATCHMESH *pPatchMesh); + + +//returns the number of degenerates in a patch mesh - +//text output put in string. +HRESULT WINAPI + D3DXValidPatchMesh(LPD3DXPATCHMESH pMesh, + DWORD *dwcDegenerateVertices, + DWORD *dwcDegeneratePatches, + LPD3DXBUFFER *ppErrorsAndWarnings); + +UINT WINAPI + D3DXGetFVFVertexSize(DWORD FVF); + +UINT WINAPI + D3DXGetDeclVertexSize(CONST D3DVERTEXELEMENT9 *pDecl,DWORD Stream); + +UINT WINAPI + D3DXGetDeclLength(CONST D3DVERTEXELEMENT9 *pDecl); + +HRESULT WINAPI + D3DXDeclaratorFromFVF( + DWORD FVF, + D3DVERTEXELEMENT9 pDeclarator[MAX_FVF_DECL_SIZE]); + +HRESULT WINAPI + D3DXFVFFromDeclarator( + CONST D3DVERTEXELEMENT9 *pDeclarator, + DWORD *pFVF); + +HRESULT WINAPI + D3DXWeldVertices( + LPD3DXMESH pMesh, + DWORD Flags, + CONST D3DXWELDEPSILONS *pEpsilons, + CONST DWORD *pAdjacencyIn, + DWORD *pAdjacencyOut, + DWORD *pFaceRemap, + LPD3DXBUFFER *ppVertexRemap); + +typedef struct _D3DXINTERSECTINFO +{ + DWORD FaceIndex; // index of face intersected + FLOAT U; // Barycentric Hit Coordinates + FLOAT V; // Barycentric Hit Coordinates + FLOAT Dist; // Ray-Intersection Parameter Distance +} D3DXINTERSECTINFO, *LPD3DXINTERSECTINFO; + + +HRESULT WINAPI + D3DXIntersect( + LPD3DXBASEMESH pMesh, + CONST D3DXVECTOR3 *pRayPos, + CONST D3DXVECTOR3 *pRayDir, + BOOL *pHit, // True if any faces were intersected + DWORD *pFaceIndex, // index of closest face intersected + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist, // Ray-Intersection Parameter Distance + LPD3DXBUFFER *ppAllHits, // Array of D3DXINTERSECTINFOs for all hits (not just closest) + DWORD *pCountOfHits); // Number of entries in AllHits array + +HRESULT WINAPI + D3DXIntersectSubset( + LPD3DXBASEMESH pMesh, + DWORD AttribId, + CONST D3DXVECTOR3 *pRayPos, + CONST D3DXVECTOR3 *pRayDir, + BOOL *pHit, // True if any faces were intersected + DWORD *pFaceIndex, // index of closest face intersected + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist, // Ray-Intersection Parameter Distance + LPD3DXBUFFER *ppAllHits, // Array of D3DXINTERSECTINFOs for all hits (not just closest) + DWORD *pCountOfHits); // Number of entries in AllHits array + + +HRESULT WINAPI D3DXSplitMesh + ( + LPD3DXMESH pMeshIn, + CONST DWORD *pAdjacencyIn, + CONST DWORD MaxSize, + CONST DWORD Options, + DWORD *pMeshesOut, + LPD3DXBUFFER *ppMeshArrayOut, + LPD3DXBUFFER *ppAdjacencyArrayOut, + LPD3DXBUFFER *ppFaceRemapArrayOut, + LPD3DXBUFFER *ppVertRemapArrayOut + ); + +BOOL WINAPI D3DXIntersectTri +( + CONST D3DXVECTOR3 *p0, // Triangle vertex 0 position + CONST D3DXVECTOR3 *p1, // Triangle vertex 1 position + CONST D3DXVECTOR3 *p2, // Triangle vertex 2 position + CONST D3DXVECTOR3 *pRayPos, // Ray origin + CONST D3DXVECTOR3 *pRayDir, // Ray direction + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist); // Ray-Intersection Parameter Distance + +BOOL WINAPI + D3DXSphereBoundProbe( + CONST D3DXVECTOR3 *pCenter, + FLOAT Radius, + CONST D3DXVECTOR3 *pRayPosition, + CONST D3DXVECTOR3 *pRayDirection); + +BOOL WINAPI + D3DXBoxBoundProbe( + CONST D3DXVECTOR3 *pMin, + CONST D3DXVECTOR3 *pMax, + CONST D3DXVECTOR3 *pRayPosition, + CONST D3DXVECTOR3 *pRayDirection); + + +HRESULT WINAPI D3DXComputeTangentFrame(ID3DXMesh *pMesh, + DWORD dwOptions); + +HRESULT WINAPI D3DXComputeTangentFrameEx(ID3DXMesh *pMesh, + DWORD dwTextureInSemantic, + DWORD dwTextureInIndex, + DWORD dwUPartialOutSemantic, + DWORD dwUPartialOutIndex, + DWORD dwVPartialOutSemantic, + DWORD dwVPartialOutIndex, + DWORD dwNormalOutSemantic, + DWORD dwNormalOutIndex, + DWORD dwOptions, + CONST DWORD *pdwAdjacency, + FLOAT fPartialEdgeThreshold, + FLOAT fSingularPointThreshold, + FLOAT fNormalEdgeThreshold, + ID3DXMesh **ppMeshOut, + ID3DXBuffer **ppVertexMapping); + + +//D3DXComputeTangent +// +//Computes the Tangent vectors for the TexStage texture coordinates +//and places the results in the TANGENT[TangentIndex] specified in the meshes' DECL +//puts the binorm in BINORM[BinormIndex] also specified in the decl. +// +//If neither the binorm or the tangnet are in the meshes declaration, +//the function will fail. +// +//If a tangent or Binorm field is in the Decl, but the user does not +//wish D3DXComputeTangent to replace them, then D3DX_DEFAULT specified +//in the TangentIndex or BinormIndex will cause it to ignore the specified +//semantic. +// +//Wrap should be specified if the texture coordinates wrap. + +HRESULT WINAPI D3DXComputeTangent(LPD3DXMESH Mesh, + DWORD TexStage, + DWORD TangentIndex, + DWORD BinormIndex, + DWORD Wrap, + CONST DWORD *pAdjacency); + +//============================================================================ +// +// UVAtlas apis +// +//============================================================================ +typedef HRESULT (WINAPI *LPD3DXUVATLASCB)(FLOAT fPercentDone, LPVOID lpUserContext); + +// This function creates atlases for meshes. There are two modes of operation, +// either based on the number of charts, or the maximum allowed stretch. If the +// maximum allowed stretch is 0, then each triangle will likely be in its own +// chart. + +// +// The parameters are as follows: +// pMesh - Input mesh to calculate an atlas for. This must have a position +// channel and at least a 2-d texture channel. +// uMaxChartNumber - The maximum number of charts required for the atlas. +// If this is 0, it will be parameterized based solely on +// stretch. +// fMaxStretch - The maximum amount of stretch, if 0, no stretching is allowed, +// if 1, then any amount of stretching is allowed. +// uWidth - The width of the texture the atlas will be used on. +// uHeight - The height of the texture the atlas will be used on. +// fGutter - The minimum distance, in texels between two charts on the atlas. +// this gets scaled by the width, so if fGutter is 2.5, and it is +// used on a 512x512 texture, then the minimum distance will be +// 2.5 / 512 in u-v space. +// dwTextureIndex - Specifies which texture coordinate to write to in the +// output mesh (which is cloned from the input mesh). Useful +// if your vertex has multiple texture coordinates. +// pdwAdjacency - a pointer to an array with 3 DWORDs per face, indicating +// which triangles are adjacent to each other. +// pdwFalseEdgeAdjacency - a pointer to an array with 3 DWORDS per face, indicating +// at each face, whether an edge is a false edge or not (using +// the same ordering as the adjacency data structure). If this +// is NULL, then it is assumed that there are no false edges. If +// not NULL, then a non-false edge is indicated by -1 and a false +// edge is indicated by any other value (it is not required, but +// it may be useful for the caller to use the original adjacency +// value). This allows you to parameterize a mesh of quads, and +// the edges down the middle of each quad will not be cut when +// parameterizing the mesh. +// pfIMTArray - a pointer to an array with 3 FLOATs per face, describing the +// integrated metric tensor for that face. This lets you control +// the way this triangle may be stretched in the atlas. The IMT +// passed in will be 3 floats (a,b,c) and specify a symmetric +// matrix (a b) that, given a vector (s,t), specifies the +// (b c) +// distance between a vector v1 and a vector v2 = v1 + (s,t) as +// sqrt((s, t) * M * (s, t)^T). +// In other words, this lets one specify the magnitude of the +// stretch in an arbitrary direction in u-v space. For example +// if a = b = c = 1, then this scales the vector (1,1) by 2, and +// the vector (1,-1) by 0. Note that this is multiplying the edge +// length by the square of the matrix, so if you want the face to +// stretch to twice its +// size with no shearing, the IMT value should be (2, 0, 2), which +// is just the identity matrix times 2. +// Note that this assumes you have an orientation for the triangle +// in some 2-D space. For D3DXUVAtlas, this space is created by +// letting S be the direction from the first to the second +// vertex, and T be the cross product between the normal and S. +// +// pStatusCallback - Since the atlas creation process can be very CPU intensive, +// this allows the programmer to specify a function to be called +// periodically, similarly to how it is done in the PRT simulation +// engine. +// fCallbackFrequency - This lets you specify how often the callback will be +// called. A decent default should be 0.0001f. +// pUserContext - a void pointer to be passed back to the callback function +// dwOptions - A combination of flags in the D3DXUVATLAS enum +// ppMeshOut - A pointer to a location to store a pointer for the newly created +// mesh. +// ppFacePartitioning - A pointer to a location to store a pointer for an array, +// one DWORD per face, giving the final partitioning +// created by the atlasing algorithm. +// ppVertexRemapArray - A pointer to a location to store a pointer for an array, +// one DWORD per vertex, giving the vertex it was copied +// from, if any vertices needed to be split. +// pfMaxStretchOut - A location to store the maximum stretch resulting from the +// atlasing algorithm. +// puNumChartsOut - A location to store the number of charts created, or if the +// maximum number of charts was too low, this gives the minimum +// number of charts needed to create an atlas. + +HRESULT WINAPI D3DXUVAtlasCreate(LPD3DXMESH pMesh, + UINT uMaxChartNumber, + FLOAT fMaxStretch, + UINT uWidth, + UINT uHeight, + FLOAT fGutter, + DWORD dwTextureIndex, + CONST DWORD *pdwAdjacency, + CONST DWORD *pdwFalseEdgeAdjacency, + CONST FLOAT *pfIMTArray, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppFacePartitioning, + LPD3DXBUFFER *ppVertexRemapArray, + FLOAT *pfMaxStretchOut, + UINT *puNumChartsOut); + +// This has the same exact arguments as Create, except that it does not perform the +// final packing step. This method allows one to get a partitioning out, and possibly +// modify it before sending it to be repacked. Note that if you change the +// partitioning, you'll also need to calculate new texture coordinates for any faces +// that have switched charts. +// +// The partition result adjacency output parameter is meant to be passed to the +// UVAtlasPack function, this adjacency cuts edges that are between adjacent +// charts, and also can include cuts inside of a chart in order to make it +// equivalent to a disc. For example: +// +// _______ +// | ___ | +// | |_| | +// |_____| +// +// In order to make this equivalent to a disc, we would need to add a cut, and it +// Would end up looking like: +// _______ +// | ___ | +// | |_|_| +// |_____| +// +// The resulting partition adjacency parameter cannot be NULL, because it is +// required for the packing step. + + + +HRESULT WINAPI D3DXUVAtlasPartition(LPD3DXMESH pMesh, + UINT uMaxChartNumber, + FLOAT fMaxStretch, + DWORD dwTextureIndex, + CONST DWORD *pdwAdjacency, + CONST DWORD *pdwFalseEdgeAdjacency, + CONST FLOAT *pfIMTArray, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppFacePartitioning, + LPD3DXBUFFER *ppVertexRemapArray, + LPD3DXBUFFER *ppPartitionResultAdjacency, + FLOAT *pfMaxStretchOut, + UINT *puNumChartsOut); + +// This takes the face partitioning result from Partition and packs it into an +// atlas of the given size. pdwPartitionResultAdjacency should be derived from +// the adjacency returned from the partition step. This value cannot be NULL +// because Pack needs to know where charts were cut in the partition step in +// order to find the edges of each chart. +// The options parameter is currently reserved. +HRESULT WINAPI D3DXUVAtlasPack(ID3DXMesh *pMesh, + UINT uWidth, + UINT uHeight, + FLOAT fGutter, + DWORD dwTextureIndex, + CONST DWORD *pdwPartitionResultAdjacency, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXBUFFER pFacePartitioning); + + +//============================================================================ +// +// IMT Calculation apis +// +// These functions all compute the Integrated Metric Tensor for use in the +// UVAtlas API. They all calculate the IMT with respect to the canonical +// triangle, where the coordinate system is set up so that the u axis goes +// from vertex 0 to 1 and the v axis is N x u. So, for example, the second +// vertex's canonical uv coordinates are (d,0) where d is the distance between +// vertices 0 and 1. This way the IMT does not depend on the parameterization +// of the mesh, and if the signal over the surface doesn't change, then +// the IMT doesn't need to be recalculated. +//============================================================================ + +// This callback is used by D3DXComputeIMTFromSignal. +// +// uv - The texture coordinate for the vertex. +// uPrimitiveID - Face ID of the triangle on which to compute the signal. +// uSignalDimension - The number of floats to store in pfSignalOut. +// pUserData - The pUserData pointer passed in to ComputeIMTFromSignal. +// pfSignalOut - A pointer to where to store the signal data. +typedef HRESULT (WINAPI* LPD3DXIMTSIGNALCALLBACK) + (CONST D3DXVECTOR2 *uv, + UINT uPrimitiveID, + UINT uSignalDimension, + VOID *pUserData, + FLOAT *pfSignalOut); + +// This function is used to calculate the IMT from per vertex data. It sets +// up a linear system over the triangle, solves for the jacobian J, then +// constructs the IMT from that (J^TJ). +// This function allows you to calculate the IMT based off of any value in a +// mesh (color, normal, etc) by specifying the correct stride of the array. +// The IMT computed will cause areas of the mesh that have similar values to +// take up less space in the texture. +// +// pMesh - The mesh to calculate the IMT for. +// pVertexSignal - A float array of size uSignalStride * v, where v is the +// number of vertices in the mesh. +// uSignalDimension - How many floats per vertex to use in calculating the IMT. +// uSignalStride - The number of bytes per vertex in the array. This must be +// a multiple of sizeof(float) +// ppIMTData - Where to store the buffer holding the IMT data + +HRESULT WINAPI D3DXComputeIMTFromPerVertexSignal ( + LPD3DXMESH pMesh, + CONST FLOAT *pfVertexSignal, // uSignalDimension floats per vertex + UINT uSignalDimension, + UINT uSignalStride, // stride of signal in bytes + DWORD dwOptions, // reserved for future use + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is used to calculate the IMT from data that varies over the +// surface of the mesh (generally at a higher frequency than vertex data). +// This function requires the mesh to already be parameterized (so it already +// has texture coordinates). It allows the user to define a signal arbitrarily +// over the surface of the mesh. +// +// pMesh - The mesh to calculate the IMT for. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// uSignalDimension - How many components there are in the signal. +// fMaxUVDistance - The subdivision will continue until the distance between +// all vertices is at most fMaxUVDistance. +// dwOptions - reserved for future use +// pSignalCallback - The callback to use to get the signal. +// pUserData - A pointer that will be passed in to the callback. +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromSignal( + LPD3DXMESH pMesh, + DWORD dwTextureIndex, + UINT uSignalDimension, + FLOAT fMaxUVDistance, + DWORD dwOptions, // reserved for future use + LPD3DXIMTSIGNALCALLBACK pSignalCallback, + VOID *pUserData, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is used to calculate the IMT from texture data. Given a texture +// that maps over the surface of the mesh, the algorithm computes the IMT for +// each face. This will cause large areas that are very similar to take up less +// room when parameterized with UVAtlas. The texture is assumed to be +// interpolated over the mesh bilinearly. +// +// pMesh - The mesh to calculate the IMT for. +// pTexture - The texture to load data from. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// dwOptions - Combination of one or more D3DXIMT flags. +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromTexture ( + LPD3DXMESH pMesh, + LPDIRECT3DTEXTURE9 pTexture, + DWORD dwTextureIndex, + DWORD dwOptions, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is very similar to ComputeIMTFromTexture, but it uses a +// float array to pass in the data, and it can calculate higher dimensional +// values than 4. +// +// pMesh - The mesh to calculate the IMT for. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// pfFloatArray - a pointer to a float array of size +// uWidth*uHeight*uComponents +// uWidth - The width of the texture +// uHeight - The height of the texture +// uSignalDimension - The number of floats per texel in the signal +// uComponents - The number of floats in each texel +// dwOptions - Combination of one or more D3DXIMT flags +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromPerTexelSignal( + LPD3DXMESH pMesh, + DWORD dwTextureIndex, + FLOAT *pfTexelSignal, + UINT uWidth, + UINT uHeight, + UINT uSignalDimension, + UINT uComponents, + DWORD dwOptions, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +HRESULT WINAPI + D3DXConvertMeshSubsetToSingleStrip( + LPD3DXBASEMESH MeshIn, + DWORD AttribId, + DWORD IBOptions, + LPDIRECT3DINDEXBUFFER9 *ppIndexBuffer, + DWORD *pNumIndices); + +HRESULT WINAPI + D3DXConvertMeshSubsetToStrips( + LPD3DXBASEMESH MeshIn, + DWORD AttribId, + DWORD IBOptions, + LPDIRECT3DINDEXBUFFER9 *ppIndexBuffer, + DWORD *pNumIndices, + LPD3DXBUFFER *ppStripLengths, + DWORD *pNumStrips); + + +//============================================================================ +// +// D3DXOptimizeFaces: +// -------------------- +// Generate a face remapping for a triangle list that more effectively utilizes +// vertex caches. This optimization is identical to the one provided +// by ID3DXMesh::Optimize with the hardware independent option enabled. +// +// Parameters: +// pbIndices +// Triangle list indices to use for generating a vertex ordering +// NumFaces +// Number of faces in the triangle list +// NumVertices +// Number of vertices referenced by the triangle list +// b32BitIndices +// TRUE if indices are 32 bit, FALSE if indices are 16 bit +// pFaceRemap +// Destination buffer to store face ordering +// The number stored for a given element is where in the new ordering +// the face will have come from. See ID3DXMesh::Optimize for more info. +// +//============================================================================ +HRESULT WINAPI + D3DXOptimizeFaces( + LPCVOID pbIndices, + UINT cFaces, + UINT cVertices, + BOOL b32BitIndices, + DWORD* pFaceRemap); + +//============================================================================ +// +// D3DXOptimizeVertices: +// -------------------- +// Generate a vertex remapping to optimize for in order use of vertices for +// a given set of indices. This is commonly used after applying the face +// remap generated by D3DXOptimizeFaces +// +// Parameters: +// pbIndices +// Triangle list indices to use for generating a vertex ordering +// NumFaces +// Number of faces in the triangle list +// NumVertices +// Number of vertices referenced by the triangle list +// b32BitIndices +// TRUE if indices are 32 bit, FALSE if indices are 16 bit +// pVertexRemap +// Destination buffer to store vertex ordering +// The number stored for a given element is where in the new ordering +// the vertex will have come from. See ID3DXMesh::Optimize for more info. +// +//============================================================================ +HRESULT WINAPI + D3DXOptimizeVertices( + LPCVOID pbIndices, + UINT cFaces, + UINT cVertices, + BOOL b32BitIndices, + DWORD* pVertexRemap); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +//=========================================================================== +// +// Data structures for Spherical Harmonic Precomputation +// +// +//============================================================================ + +typedef enum _D3DXSHCOMPRESSQUALITYTYPE { + D3DXSHCQUAL_FASTLOWQUALITY = 1, + D3DXSHCQUAL_SLOWHIGHQUALITY = 2, + D3DXSHCQUAL_FORCE_DWORD = 0x7fffffff +} D3DXSHCOMPRESSQUALITYTYPE; + +typedef enum _D3DXSHGPUSIMOPT { + D3DXSHGPUSIMOPT_SHADOWRES256 = 1, + D3DXSHGPUSIMOPT_SHADOWRES512 = 0, + D3DXSHGPUSIMOPT_SHADOWRES1024 = 2, + D3DXSHGPUSIMOPT_SHADOWRES2048 = 3, + + D3DXSHGPUSIMOPT_HIGHQUALITY = 4, + + D3DXSHGPUSIMOPT_FORCE_DWORD = 0x7fffffff +} D3DXSHGPUSIMOPT; + +// for all properties that are colors the luminance is computed +// if the simulator is run with a single channel using the following +// formula: R * 0.2125 + G * 0.7154 + B * 0.0721 + +typedef struct _D3DXSHMATERIAL { + D3DCOLORVALUE Diffuse; // Diffuse albedo of the surface. (Ignored if object is a Mirror) + BOOL bMirror; // Must be set to FALSE. bMirror == TRUE not currently supported + BOOL bSubSurf; // true if the object does subsurface scattering - can't do this and be a mirror + + // subsurface scattering parameters + FLOAT RelativeIndexOfRefraction; + D3DCOLORVALUE Absorption; + D3DCOLORVALUE ReducedScattering; + +} D3DXSHMATERIAL; + +// allocated in D3DXSHPRTCompSplitMeshSC +// vertices are duplicated into multiple super clusters but +// only have a valid status in one super cluster (fill in the rest) + +typedef struct _D3DXSHPRTSPLITMESHVERTDATA { + UINT uVertRemap; // vertex in original mesh this corresponds to + UINT uSubCluster; // cluster index relative to super cluster + UCHAR ucVertStatus; // 1 if vertex has valid data, 0 if it is "fill" +} D3DXSHPRTSPLITMESHVERTDATA; + +// used in D3DXSHPRTCompSplitMeshSC +// information for each super cluster that maps into face/vert arrays + +typedef struct _D3DXSHPRTSPLITMESHCLUSTERDATA { + UINT uVertStart; // initial index into remapped vertex array + UINT uVertLength; // number of vertices in this super cluster + + UINT uFaceStart; // initial index into face array + UINT uFaceLength; // number of faces in this super cluster + + UINT uClusterStart; // initial index into cluster array + UINT uClusterLength; // number of clusters in this super cluster +} D3DXSHPRTSPLITMESHCLUSTERDATA; + +// call back function for simulator +// return S_OK to keep running the simulator - anything else represents +// failure and the simulator will abort. + +typedef HRESULT (WINAPI *LPD3DXSHPRTSIMCB)(float fPercentDone, LPVOID lpUserContext); + +// interfaces for PRT buffers/simulator + +// GUIDs +// {F1827E47-00A8-49cd-908C-9D11955F8728} +DEFINE_GUID(IID_ID3DXPRTBuffer, +0xf1827e47, 0xa8, 0x49cd, 0x90, 0x8c, 0x9d, 0x11, 0x95, 0x5f, 0x87, 0x28); + +// {A758D465-FE8D-45ad-9CF0-D01E56266A07} +DEFINE_GUID(IID_ID3DXPRTCompBuffer, +0xa758d465, 0xfe8d, 0x45ad, 0x9c, 0xf0, 0xd0, 0x1e, 0x56, 0x26, 0x6a, 0x7); + +// {838F01EC-9729-4527-AADB-DF70ADE7FEA9} +DEFINE_GUID(IID_ID3DXTextureGutterHelper, +0x838f01ec, 0x9729, 0x4527, 0xaa, 0xdb, 0xdf, 0x70, 0xad, 0xe7, 0xfe, 0xa9); + +// {683A4278-CD5F-4d24-90AD-C4E1B6855D53} +DEFINE_GUID(IID_ID3DXPRTEngine, +0x683a4278, 0xcd5f, 0x4d24, 0x90, 0xad, 0xc4, 0xe1, 0xb6, 0x85, 0x5d, 0x53); + +// interface defenitions + +typedef interface ID3DXTextureGutterHelper ID3DXTextureGutterHelper; +typedef interface ID3DXPRTBuffer ID3DXPRTBuffer; + +#undef INTERFACE +#define INTERFACE ID3DXPRTBuffer + +// Buffer interface - contains "NumSamples" samples +// each sample in memory is stored as NumCoeffs scalars per channel (1 or 3) +// Same interface is used for both Vertex and Pixel PRT buffers + +DECLARE_INTERFACE_(ID3DXPRTBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPRTBuffer + STDMETHOD_(UINT, GetNumSamples)(THIS) PURE; + STDMETHOD_(UINT, GetNumCoeffs)(THIS) PURE; + STDMETHOD_(UINT, GetNumChannels)(THIS) PURE; + + STDMETHOD_(BOOL, IsTexture)(THIS) PURE; + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + // changes the number of samples allocated in the buffer + STDMETHOD(Resize)(THIS_ UINT NewSize) PURE; + + // ppData will point to the memory location where sample Start begins + // pointer is valid for at least NumSamples samples + STDMETHOD(LockBuffer)(THIS_ UINT Start, UINT NumSamples, FLOAT **ppData) PURE; + STDMETHOD(UnlockBuffer)(THIS) PURE; + + // every scalar in buffer is multiplied by Scale + STDMETHOD(ScaleBuffer)(THIS_ FLOAT Scale) PURE; + + // every scalar contains the sum of this and pBuffers values + // pBuffer must have the same storage class/dimensions + STDMETHOD(AddBuffer)(THIS_ LPD3DXPRTBUFFER pBuffer) PURE; + + // GutterHelper (described below) will fill in the gutter + // regions of a texture by interpolating "internal" values + STDMETHOD(AttachGH)(THIS_ LPD3DXTEXTUREGUTTERHELPER) PURE; + STDMETHOD(ReleaseGH)(THIS) PURE; + + // Evaluates attached gutter helper on the contents of this buffer + STDMETHOD(EvalGH)(THIS) PURE; + + // extracts a given channel into texture pTexture + // NumCoefficients starting from StartCoefficient are copied + STDMETHOD(ExtractTexture)(THIS_ UINT Channel, UINT StartCoefficient, + UINT NumCoefficients, LPDIRECT3DTEXTURE9 pTexture) PURE; + + // extracts NumCoefficients coefficients into mesh - only applicable on single channel + // buffers, otherwise just lockbuffer and copy data. With SHPRT data NumCoefficients + // should be Order^2 + STDMETHOD(ExtractToMesh)(THIS_ UINT NumCoefficients, D3DDECLUSAGE Usage, UINT UsageIndexStart, + LPD3DXMESH pScene) PURE; + +}; + +typedef interface ID3DXPRTCompBuffer ID3DXPRTCompBuffer; +typedef interface ID3DXPRTCompBuffer *LPD3DXPRTCOMPBUFFER; + +#undef INTERFACE +#define INTERFACE ID3DXPRTCompBuffer + +// compressed buffers stored a compressed version of a PRTBuffer + +DECLARE_INTERFACE_(ID3DXPRTCompBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DPRTCompBuffer + + // NumCoeffs and NumChannels are properties of input buffer + STDMETHOD_(UINT, GetNumSamples)(THIS) PURE; + STDMETHOD_(UINT, GetNumCoeffs)(THIS) PURE; + STDMETHOD_(UINT, GetNumChannels)(THIS) PURE; + + STDMETHOD_(BOOL, IsTexture)(THIS) PURE; + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + // number of clusters, and PCA vectors per-cluster + STDMETHOD_(UINT, GetNumClusters)(THIS) PURE; + STDMETHOD_(UINT, GetNumPCA)(THIS) PURE; + + // normalizes PCA weights so that they are between [-1,1] + // basis vectors are modified to reflect this + STDMETHOD(NormalizeData)(THIS) PURE; + + // copies basis vectors for cluster "Cluster" into pClusterBasis + // (NumPCA+1)*NumCoeffs*NumChannels floats + STDMETHOD(ExtractBasis)(THIS_ UINT Cluster, FLOAT *pClusterBasis) PURE; + + // UINT per sample - which cluster it belongs to + STDMETHOD(ExtractClusterIDs)(THIS_ UINT *pClusterIDs) PURE; + + // copies NumExtract PCA projection coefficients starting at StartPCA + // into pPCACoefficients - NumSamples*NumExtract floats copied + STDMETHOD(ExtractPCA)(THIS_ UINT StartPCA, UINT NumExtract, FLOAT *pPCACoefficients) PURE; + + // copies NumPCA projection coefficients starting at StartPCA + // into pTexture - should be able to cope with signed formats + STDMETHOD(ExtractTexture)(THIS_ UINT StartPCA, UINT NumpPCA, + LPDIRECT3DTEXTURE9 pTexture) PURE; + + // copies NumPCA projection coefficients into mesh pScene + // Usage is D3DDECLUSAGE where coefficients are to be stored + // UsageIndexStart is starting index + STDMETHOD(ExtractToMesh)(THIS_ UINT NumPCA, D3DDECLUSAGE Usage, UINT UsageIndexStart, + LPD3DXMESH pScene) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXTextureGutterHelper + +// ID3DXTextureGutterHelper will build and manage +// "gutter" regions in a texture - this will allow for +// bi-linear interpolation to not have artifacts when rendering +// It generates a map (in texture space) where each texel +// is in one of 3 states: +// 0 Invalid - not used at all +// 1 Inside triangle +// 2 Gutter texel +// 4 represents a gutter texel that will be computed during PRT +// For each Inside/Gutter texel it stores the face it +// belongs to and barycentric coordinates for the 1st two +// vertices of that face. Gutter vertices are assigned to +// the closest edge in texture space. +// +// When used with PRT this requires a unique parameterization +// of the model - every texel must correspond to a single point +// on the surface of the model and vice versa + +DECLARE_INTERFACE_(ID3DXTextureGutterHelper, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXTextureGutterHelper + + // dimensions of texture this is bound too + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + + // Applying gutters recomputes all of the gutter texels of class "2" + // based on texels of class "1" or "4" + + // Applies gutters to a raw float buffer - each texel is NumCoeffs floats + // Width and Height must match GutterHelper + STDMETHOD(ApplyGuttersFloat)(THIS_ FLOAT *pDataIn, UINT NumCoeffs, UINT Width, UINT Height); + + // Applies gutters to pTexture + // Dimensions must match GutterHelper + STDMETHOD(ApplyGuttersTex)(THIS_ LPDIRECT3DTEXTURE9 pTexture); + + // Applies gutters to a D3DXPRTBuffer + // Dimensions must match GutterHelper + STDMETHOD(ApplyGuttersPRT)(THIS_ LPD3DXPRTBUFFER pBuffer); + + // Resamples a texture from a mesh onto this gutterhelpers + // parameterization. It is assumed that the UV coordinates + // for this gutter helper are in TEXTURE 0 (usage/usage index) + // and the texture coordinates should all be within [0,1] for + // both sets. + // + // pTextureIn - texture represented using parameterization in pMeshIn + // pMeshIn - Mesh with texture coordinates that represent pTextureIn + // pTextureOut texture coordinates are assumed to be in + // TEXTURE 0 + // Usage - field in DECL for pMeshIn that stores texture coordinates + // for pTextureIn + // UsageIndex - which index for Usage above for pTextureIn + // pTextureOut- Resampled texture + // + // Usage would generally be D3DDECLUSAGE_TEXCOORD and UsageIndex other than zero + STDMETHOD(ResampleTex)(THIS_ LPDIRECT3DTEXTURE9 pTextureIn, + LPD3DXMESH pMeshIn, + D3DDECLUSAGE Usage, UINT UsageIndex, + LPDIRECT3DTEXTURE9 pTextureOut); + + // the routines below provide access to the data structures + // used by the Apply functions + + // face map is a UINT per texel that represents the + // face of the mesh that texel belongs too - + // only valid if same texel is valid in pGutterData + // pFaceData must be allocated by the user + STDMETHOD(GetFaceMap)(THIS_ UINT *pFaceData) PURE; + + // BaryMap is a D3DXVECTOR2 per texel + // the 1st two barycentric coordinates for the corresponding + // face (3rd weight is always 1-sum of first two) + // only valid if same texel is valid in pGutterData + // pBaryData must be allocated by the user + STDMETHOD(GetBaryMap)(THIS_ D3DXVECTOR2 *pBaryData) PURE; + + // TexelMap is a D3DXVECTOR2 per texel that + // stores the location in pixel coordinates where the + // corresponding texel is mapped + // pTexelData must be allocated by the user + STDMETHOD(GetTexelMap)(THIS_ D3DXVECTOR2 *pTexelData) PURE; + + // GutterMap is a BYTE per texel + // 0/1/2 for Invalid/Internal/Gutter texels + // 4 represents a gutter texel that will be computed + // during PRT + // pGutterData must be allocated by the user + STDMETHOD(GetGutterMap)(THIS_ BYTE *pGutterData) PURE; + + // face map is a UINT per texel that represents the + // face of the mesh that texel belongs too - + // only valid if same texel is valid in pGutterData + STDMETHOD(SetFaceMap)(THIS_ UINT *pFaceData) PURE; + + // BaryMap is a D3DXVECTOR2 per texel + // the 1st two barycentric coordinates for the corresponding + // face (3rd weight is always 1-sum of first two) + // only valid if same texel is valid in pGutterData + STDMETHOD(SetBaryMap)(THIS_ D3DXVECTOR2 *pBaryData) PURE; + + // TexelMap is a D3DXVECTOR2 per texel that + // stores the location in pixel coordinates where the + // corresponding texel is mapped + STDMETHOD(SetTexelMap)(THIS_ D3DXVECTOR2 *pTexelData) PURE; + + // GutterMap is a BYTE per texel + // 0/1/2 for Invalid/Internal/Gutter texels + // 4 represents a gutter texel that will be computed + // during PRT + STDMETHOD(SetGutterMap)(THIS_ BYTE *pGutterData) PURE; +}; + + +typedef interface ID3DXPRTEngine ID3DXPRTEngine; +typedef interface ID3DXPRTEngine *LPD3DXPRTENGINE; + +#undef INTERFACE +#define INTERFACE ID3DXPRTEngine + +// ID3DXPRTEngine is used to compute a PRT simulation +// Use the following steps to compute PRT for SH +// (1) create an interface (which includes a scene) +// (2) call SetSamplingInfo +// (3) [optional] Set MeshMaterials/albedo's (required if doing bounces) +// (4) call ComputeDirectLightingSH +// (5) [optional] call ComputeBounce +// repeat step 5 for as many bounces as wanted. +// if you want to model subsurface scattering you +// need to call ComputeSS after direct lighting and +// each bounce. +// If you want to bake the albedo into the PRT signal, you +// must call MutliplyAlbedo, otherwise the user has to multiply +// the albedo themselves. Not multiplying the albedo allows you +// to model albedo variation at a finer scale then illumination, and +// can result in better compression results. +// Luminance values are computed from RGB values using the following +// formula: R * 0.2125 + G * 0.7154 + B * 0.0721 + +DECLARE_INTERFACE_(ID3DXPRTEngine, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPRTEngine + + // This sets a material per attribute in the scene mesh and it is + // the only way to specify subsurface scattering parameters. if + // bSetAlbedo is FALSE, NumChannels must match the current + // configuration of the PRTEngine. If you intend to change + // NumChannels (through some other SetAlbedo function) it must + // happen before SetMeshMaterials is called. + // + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // bSetAlbedo sets albedo from material if TRUE - which clobbers per texel/vertex + // albedo that might have been set before. FALSE won't clobber. + // fLengthScale is used for subsurface scattering - scene is mapped into a 1mm unit cube + // and scaled by this amount + STDMETHOD(SetMeshMaterials)(THIS_ CONST D3DXSHMATERIAL **ppMaterials, UINT NumMeshes, + UINT NumChannels, BOOL bSetAlbedo, FLOAT fLengthScale) PURE; + + // setting albedo per-vertex or per-texel over rides the albedos stored per mesh + // but it does not over ride any other settings + + // sets an albedo to be used per vertex - the albedo is represented as a float + // pDataIn input pointer (pointint to albedo of 1st sample) + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // Stride - stride in bytes to get to next samples albedo + STDMETHOD(SetPerVertexAlbedo)(THIS_ CONST VOID *pDataIn, UINT NumChannels, UINT Stride) PURE; + + // represents the albedo per-texel instead of per-vertex (even if per-vertex PRT is used) + // pAlbedoTexture - texture that stores the albedo (dimension arbitrary) + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // pGH - optional gutter helper, otherwise one is constructed in computation routines and + // destroyed (if not attached to buffers) + STDMETHOD(SetPerTexelAlbedo)(THIS_ LPDIRECT3DTEXTURE9 pAlbedoTexture, + UINT NumChannels, + LPD3DXTEXTUREGUTTERHELPER pGH) PURE; + + // gets the per-vertex albedo + STDMETHOD(GetVertexAlbedo)(THIS_ D3DXCOLOR *pVertColors, UINT NumVerts) PURE; + + // If pixel PRT is being computed normals default to ones that are interpolated + // from the vertex normals. This specifies a texture that stores an object + // space normal map instead (must use a texture format that can represent signed values) + // pNormalTexture - normal map, must be same dimensions as PRTBuffers, signed + STDMETHOD(SetPerTexelNormal)(THIS_ LPDIRECT3DTEXTURE9 pNormalTexture) PURE; + + // Copies per-vertex albedo from mesh + // pMesh - mesh that represents the scene. It must have the same + // properties as the mesh used to create the PRTEngine + // Usage - D3DDECLUSAGE to extract albedos from + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + STDMETHOD(ExtractPerVertexAlbedo)(THIS_ LPD3DXMESH pMesh, + D3DDECLUSAGE Usage, + UINT NumChannels) PURE; + + // Resamples the input buffer into the output buffer + // can be used to move between per-vertex and per-texel buffers. This can also be used + // to convert single channel buffers to 3-channel buffers and vice-versa. + STDMETHOD(ResampleBuffer)(THIS_ LPD3DXPRTBUFFER pBufferIn, LPD3DXPRTBUFFER pBufferOut) PURE; + + // Returns the scene mesh - including modifications from adaptive spatial sampling + // The returned mesh only has positions, normals and texture coordinates (if defined) + // pD3DDevice - d3d device that will be used to allocate the mesh + // pFaceRemap - each face has a pointer back to the face on the original mesh that it comes from + // if the face hasn't been subdivided this will be an identity mapping + // pVertRemap - each vertex contains 3 vertices that this is a linear combination of + // pVertWeights - weights for each of above indices (sum to 1.0f) + // ppMesh - mesh that will be allocated and filled + STDMETHOD(GetAdaptedMesh)(THIS_ LPDIRECT3DDEVICE9 pD3DDevice,UINT *pFaceRemap, UINT *pVertRemap, FLOAT *pfVertWeights, LPD3DXMESH *ppMesh) PURE; + + // Number of vertices currently allocated (includes new vertices from adaptive sampling) + STDMETHOD_(UINT, GetNumVerts)(THIS) PURE; + // Number of faces currently allocated (includes new faces) + STDMETHOD_(UINT, GetNumFaces)(THIS) PURE; + + // Sets the Minimum/Maximum intersection distances, this can be used to control + // maximum distance that objects can shadow/reflect light, and help with "bad" + // art that might have near features that you don't want to shadow. This does not + // apply for GPU simulations. + // fMin - minimum intersection distance, must be positive and less than fMax + // fMax - maximum intersection distance, if 0.0f use the previous value, otherwise + // must be strictly greater than fMin + STDMETHOD(SetMinMaxIntersection)(THIS_ FLOAT fMin, FLOAT fMax) PURE; + + // This will subdivide faces on a mesh so that adaptively simulations can + // use a more conservative threshold (it won't miss features.) + // MinEdgeLength - minimum edge length that will be generated, if 0.0f a + // reasonable default will be used + // MaxSubdiv - maximum level of subdivision, if 0 is specified a default + // value will be used (5) + STDMETHOD(RobustMeshRefine)(THIS_ FLOAT MinEdgeLength, UINT MaxSubdiv) PURE; + + // This sets to sampling information used by the simulator. Adaptive sampling + // parameters are currently ignored. + // NumRays - number of rays to shoot per sample + // UseSphere - if TRUE uses spherical samples, otherwise samples over + // the hemisphere. Should only be used with GPU and Vol computations + // UseCosine - if TRUE uses a cosine weighting - not used for Vol computations + // or if only the visiblity function is desired + // Adaptive - if TRUE adaptive sampling (angular) is used + // AdaptiveThresh - threshold used to terminate adaptive angular sampling + // ignored if adaptive sampling is not set + STDMETHOD(SetSamplingInfo)(THIS_ UINT NumRays, + BOOL UseSphere, + BOOL UseCosine, + BOOL Adaptive, + FLOAT AdaptiveThresh) PURE; + + // Methods that compute the direct lighting contribution for objects + // always represente light using spherical harmonics (SH) + // the albedo is not multiplied by the signal - it just integrates + // incoming light. If NumChannels is not 1 the vector is replicated + // + // SHOrder - order of SH to use + // pDataOut - PRT buffer that is generated. Can be single channel + STDMETHOD(ComputeDirectLightingSH)(THIS_ UINT SHOrder, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Adaptive variant of above function. This will refine the mesh + // generating new vertices/faces to approximate the PRT signal + // more faithfully. + // SHOrder - order of SH to use + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - PRT buffer that is generated. Can be single channel. + STDMETHOD(ComputeDirectLightingSHAdaptive)(THIS_ UINT SHOrder, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Function that computes the direct lighting contribution for objects + // light is always represented using spherical harmonics (SH) + // This is done on the GPU and is much faster then using the CPU. + // The albedo is not multiplied by the signal - it just integrates + // incoming light. If NumChannels is not 1 the vector is replicated. + // ZBias/ZAngleBias are akin to parameters used with shadow zbuffers. + // A reasonable default for both values is 0.005, but the user should + // experiment (ZAngleBias can be zero, ZBias should not be.) + // Callbacks should not use the Direct3D9Device the simulator is using. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // + // pD3DDevice - device used to run GPU simulator - must support PS2.0 + // and FP render targets + // Flags - parameters for the GPU simulator, combination of one or more + // D3DXSHGPUSIMOPT flags. Only one SHADOWRES setting should be set and + // the defaults is 512 + // SHOrder - order of SH to use + // ZBias - bias in normal direction (for depth test) + // ZAngleBias - scaled by one minus cosine of angle with light (offset in depth) + // pDataOut - PRT buffer that is filled in. Can be single channel + STDMETHOD(ComputeDirectLightingSHGPU)(THIS_ LPDIRECT3DDEVICE9 pD3DDevice, + UINT Flags, + UINT SHOrder, + FLOAT ZBias, + FLOAT ZAngleBias, + LPD3DXPRTBUFFER pDataOut) PURE; + + + // Functions that computes subsurface scattering (using material properties) + // Albedo is not multiplied by result. This only works for per-vertex data + // use ResampleBuffer to move per-vertex data into a texture and back. + // + // pDataIn - input data (previous bounce) + // pDataOut - result of subsurface scattering simulation + // pDataTotal - [optional] results can be summed into this buffer + STDMETHOD(ComputeSS)(THIS_ LPD3DXPRTBUFFER pDataIn, + LPD3DXPRTBUFFER pDataOut, LPD3DXPRTBUFFER pDataTotal) PURE; + + // Adaptive version of ComputeSS. + // + // pDataIn - input data (previous bounce) + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - result of subsurface scattering simulation + // pDataTotal - [optional] results can be summed into this buffer + STDMETHOD(ComputeSSAdaptive)(THIS_ LPD3DXPRTBUFFER pDataIn, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut, LPD3DXPRTBUFFER pDataTotal) PURE; + + // computes a single bounce of inter-reflected light + // works for SH based PRT or generic lighting + // Albedo is not multiplied by result + // + // pDataIn - previous bounces data + // pDataOut - PRT buffer that is generated + // pDataTotal - [optional] can be used to keep a running sum + STDMETHOD(ComputeBounce)(THIS_ LPD3DXPRTBUFFER pDataIn, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Adaptive version of above function. + // + // pDataIn - previous bounces data, can be single channel + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - PRT buffer that is generated + // pDataTotal - [optional] can be used to keep a running sum + STDMETHOD(ComputeBounceAdaptive)(THIS_ LPD3DXPRTBUFFER pDataIn, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Computes projection of distant SH radiance into a local SH radiance + // function. This models how direct lighting is attenuated by the + // scene and is a form of "neighborhood transfer." The result is + // a linear operator (matrix) at every sample point, if you multiply + // this matrix by the distant SH lighting coefficients you get an + // approximation of the local incident radiance function from + // direct lighting. These resulting lighting coefficients can + // than be projected into another basis or used with any rendering + // technique that uses spherical harmonics as input. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // Generates SHOrderIn*SHOrderIn*SHOrderOut*SHOrderOut scalars + // per channel at each sample location. + // + // SHOrderIn - Order of the SH representation of distant lighting + // SHOrderOut - Order of the SH representation of local lighting + // NumVolSamples - Number of sample locations + // pSampleLocs - position of sample locations + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeVolumeSamplesDirectSH)(THIS_ UINT SHOrderIn, + UINT SHOrderOut, + UINT NumVolSamples, + CONST D3DXVECTOR3 *pSampleLocs, + LPD3DXPRTBUFFER pDataOut) PURE; + + // At each sample location computes a linear operator (matrix) that maps + // the representation of source radiance (NumCoeffs in pSurfDataIn) + // into a local incident radiance function approximated with spherical + // harmonics. For example if a light map data is specified in pSurfDataIn + // the result is an SH representation of the flow of light at each sample + // point. If PRT data for an outdoor scene is used, each sample point + // contains a matrix that models how distant lighting bounces of the objects + // in the scene and arrives at the given sample point. Combined with + // ComputeVolumeSamplesDirectSH this gives the complete representation for + // how light arrives at each sample point parameterized by distant lighting. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // Generates pSurfDataIn->NumCoeffs()*SHOrder*SHOrder scalars + // per channel at each sample location. + // + // pSurfDataIn - previous bounce data + // SHOrder - order of SH to generate projection with + // NumVolSamples - Number of sample locations + // pSampleLocs - position of sample locations + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeVolumeSamples)(THIS_ LPD3DXPRTBUFFER pSurfDataIn, + UINT SHOrder, + UINT NumVolSamples, + CONST D3DXVECTOR3 *pSampleLocs, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Computes direct lighting (SH) for a point not on the mesh + // with a given normal - cannot use texture buffers. + // + // SHOrder - order of SH to use + // NumSamples - number of sample locations + // pSampleLocs - position for each sample + // pSampleNorms - normal for each sample + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeSurfSamplesDirectSH)(THIS_ UINT SHOrder, + UINT NumSamples, + CONST D3DXVECTOR3 *pSampleLocs, + CONST D3DXVECTOR3 *pSampleNorms, + LPD3DXPRTBUFFER pDataOut) PURE; + + + // given the solution for PRT or light maps, computes transfer vector at arbitrary + // position/normal pairs in space + // + // pSurfDataIn - input data + // NumSamples - number of sample locations + // pSampleLocs - position for each sample + // pSampleNorms - normal for each sample + // pDataOut - PRT Buffer that will store output results + // pDataTotal - optional buffer to sum results into - can be NULL + STDMETHOD(ComputeSurfSamplesBounce)(THIS_ LPD3DXPRTBUFFER pSurfDataIn, + UINT NumSamples, + CONST D3DXVECTOR3 *pSampleLocs, + CONST D3DXVECTOR3 *pSampleNorms, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Frees temporary data structures that can be created for subsurface scattering + // this data is freed when the PRTComputeEngine is freed and is lazily created + STDMETHOD(FreeSSData)(THIS) PURE; + + // Frees temporary data structures that can be created for bounce simulations + // this data is freed when the PRTComputeEngine is freed and is lazily created + STDMETHOD(FreeBounceData)(THIS) PURE; + + // This computes the Local Deformable PRT (LDPRT) coefficients relative to the + // per sample normals that minimize error in a least squares sense with respect + // to the input PRT data set. These coefficients can be used with skinned/transformed + // normals to model global effects with dynamic objects. Shading normals can + // optionally be solved for - these normals (along with the LDPRT coefficients) can + // more accurately represent the PRT signal. The coefficients are for zonal + // harmonics oriented in the normal/shading normal direction. + // + // pDataIn - SH PRT dataset that is input + // SHOrder - Order of SH to compute conv coefficients for + // pNormOut - Optional array of vectors (passed in) that will be filled with + // "shading normals", LDPRT coefficients are optimized for + // these normals. This array must be the same size as the number of + // samples in pDataIn + // pDataOut - Output buffer (SHOrder zonal harmonic coefficients per channel per sample) + STDMETHOD(ComputeLDPRTCoeffs)(THIS_ LPD3DXPRTBUFFER pDataIn, + UINT SHOrder, + D3DXVECTOR3 *pNormOut, + LPD3DXPRTBUFFER pDataOut) PURE; + + // scales all the samples associated with a given sub mesh + // can be useful when using subsurface scattering + // fScale - value to scale each vector in submesh by + STDMETHOD(ScaleMeshChunk)(THIS_ UINT uMeshChunk, FLOAT fScale, LPD3DXPRTBUFFER pDataOut) PURE; + + // mutliplies each PRT vector by the albedo - can be used if you want to have the albedo + // burned into the dataset, often better not to do this. If this is not done the user + // must mutliply the albedo themselves when rendering - just multiply the albedo times + // the result of the PRT dot product. + // If pDataOut is a texture simulation result and there is an albedo texture it + // must be represented at the same resolution as the simulation buffer. You can use + // LoadSurfaceFromSurface and set a new albedo texture if this is an issue - but must + // be careful about how the gutters are handled. + // + // pDataOut - dataset that will get albedo pushed into it + STDMETHOD(MultiplyAlbedo)(THIS_ LPD3DXPRTBUFFER pDataOut) PURE; + + // Sets a pointer to an optional call back function that reports back to the + // user percentage done and gives them the option of quitting + // pCB - pointer to call back function, return S_OK for the simulation + // to continue + // Frequency - 1/Frequency is roughly the number of times the call back + // will be invoked + // lpUserContext - will be passed back to the users call back + STDMETHOD(SetCallBack)(THIS_ LPD3DXSHPRTSIMCB pCB, FLOAT Frequency, LPVOID lpUserContext) PURE; + + // Returns TRUE if the ray intersects the mesh, FALSE if it does not. This function + // takes into account settings from SetMinMaxIntersection. If the closest intersection + // is not needed this function is more efficient compared to the ClosestRayIntersection + // method. + // pRayPos - origin of ray + // pRayDir - normalized ray direction (normalization required for SetMinMax to be meaningful) + + STDMETHOD_(BOOL, ShadowRayIntersects)(THIS_ CONST D3DXVECTOR3 *pRayPos, CONST D3DXVECTOR3 *pRayDir) PURE; + + // Returns TRUE if the ray intersects the mesh, FALSE if it does not. If there is an + // intersection the closest face that was intersected and its first two barycentric coordinates + // are returned. This function takes into account settings from SetMinMaxIntersection. + // This is a slower function compared to ShadowRayIntersects and should only be used where + // needed. The third vertices barycentric coordinates will be 1 - pU - pV. + // pRayPos - origin of ray + // pRayDir - normalized ray direction (normalization required for SetMinMax to be meaningful) + // pFaceIndex - Closest face that intersects. This index is based on stacking the pBlockerMesh + // faces before the faces from pMesh + // pU - Barycentric coordinate for vertex 0 + // pV - Barycentric coordinate for vertex 1 + // pDist - Distance along ray where the intersection occured + + STDMETHOD_(BOOL, ClosestRayIntersects)(THIS_ CONST D3DXVECTOR3 *pRayPos, CONST D3DXVECTOR3 *pRayDir, + DWORD *pFaceIndex, FLOAT *pU, FLOAT *pV, FLOAT *pDist) PURE; +}; + + +// API functions for creating interfaces + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//============================================================================ +// +// D3DXCreatePRTBuffer: +// -------------------- +// Generates a PRT Buffer that can be compressed or filled by a simulator +// This function should be used to create per-vertex or volume buffers. +// When buffers are created all values are initialized to zero. +// +// Parameters: +// NumSamples +// Number of sample locations represented +// NumCoeffs +// Number of coefficients per sample location (order^2 for SH) +// NumChannels +// Number of color channels to represent (1 or 3) +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXCreatePRTBuffer( + UINT NumSamples, + UINT NumCoeffs, + UINT NumChannels, + LPD3DXPRTBUFFER* ppBuffer); + +//============================================================================ +// +// D3DXCreatePRTBufferTex: +// -------------------- +// Generates a PRT Buffer that can be compressed or filled by a simulator +// This function should be used to create per-pixel buffers. +// When buffers are created all values are initialized to zero. +// +// Parameters: +// Width +// Width of texture +// Height +// Height of texture +// NumCoeffs +// Number of coefficients per sample location (order^2 for SH) +// NumChannels +// Number of color channels to represent (1 or 3) +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXCreatePRTBufferTex( + UINT Width, + UINT Height, + UINT NumCoeffs, + UINT NumChannels, + LPD3DXPRTBUFFER* ppBuffer); + +//============================================================================ +// +// D3DXLoadPRTBufferFromFile: +// -------------------- +// Loads a PRT buffer that has been saved to disk. +// +// Parameters: +// pFilename +// Name of the file to load +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXLoadPRTBufferFromFileA( + LPCSTR pFilename, + LPD3DXPRTBUFFER* ppBuffer); + +HRESULT WINAPI + D3DXLoadPRTBufferFromFileW( + LPCWSTR pFilename, + LPD3DXPRTBUFFER* ppBuffer); + +#ifdef UNICODE +#define D3DXLoadPRTBufferFromFile D3DXLoadPRTBufferFromFileW +#else +#define D3DXLoadPRTBufferFromFile D3DXLoadPRTBufferFromFileA +#endif + + +//============================================================================ +// +// D3DXSavePRTBufferToFile: +// -------------------- +// Saves a PRTBuffer to disk. +// +// Parameters: +// pFilename +// Name of the file to save +// pBuffer +// Buffer that will be saved +// +//============================================================================ + +HRESULT WINAPI + D3DXSavePRTBufferToFileA( + LPCSTR pFileName, + LPD3DXPRTBUFFER pBuffer); + +HRESULT WINAPI + D3DXSavePRTBufferToFileW( + LPCWSTR pFileName, + LPD3DXPRTBUFFER pBuffer); + +#ifdef UNICODE +#define D3DXSavePRTBufferToFile D3DXSavePRTBufferToFileW +#else +#define D3DXSavePRTBufferToFile D3DXSavePRTBufferToFileA +#endif + + +//============================================================================ +// +// D3DXLoadPRTCompBufferFromFile: +// -------------------- +// Loads a PRTComp buffer that has been saved to disk. +// +// Parameters: +// pFilename +// Name of the file to load +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXLoadPRTCompBufferFromFileA( + LPCSTR pFilename, + LPD3DXPRTCOMPBUFFER* ppBuffer); + +HRESULT WINAPI + D3DXLoadPRTCompBufferFromFileW( + LPCWSTR pFilename, + LPD3DXPRTCOMPBUFFER* ppBuffer); + +#ifdef UNICODE +#define D3DXLoadPRTCompBufferFromFile D3DXLoadPRTCompBufferFromFileW +#else +#define D3DXLoadPRTCompBufferFromFile D3DXLoadPRTCompBufferFromFileA +#endif + +//============================================================================ +// +// D3DXSavePRTCompBufferToFile: +// -------------------- +// Saves a PRTCompBuffer to disk. +// +// Parameters: +// pFilename +// Name of the file to save +// pBuffer +// Buffer that will be saved +// +//============================================================================ + +HRESULT WINAPI + D3DXSavePRTCompBufferToFileA( + LPCSTR pFileName, + LPD3DXPRTCOMPBUFFER pBuffer); + +HRESULT WINAPI + D3DXSavePRTCompBufferToFileW( + LPCWSTR pFileName, + LPD3DXPRTCOMPBUFFER pBuffer); + +#ifdef UNICODE +#define D3DXSavePRTCompBufferToFile D3DXSavePRTCompBufferToFileW +#else +#define D3DXSavePRTCompBufferToFile D3DXSavePRTCompBufferToFileA +#endif + +//============================================================================ +// +// D3DXCreatePRTCompBuffer: +// -------------------- +// Compresses a PRT buffer (vertex or texel) +// +// Parameters: +// D3DXSHCOMPRESSQUALITYTYPE +// Quality of compression - low is faster (computes PCA per voronoi cluster) +// high is slower but better quality (clusters based on distance to affine subspace) +// NumClusters +// Number of clusters to compute +// NumPCA +// Number of basis vectors to compute +// pCB +// Optional Callback function +// lpUserContext +// Optional user context +// pBufferIn +// Buffer that will be compressed +// ppBufferOut +// Compressed buffer that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreatePRTCompBuffer( + D3DXSHCOMPRESSQUALITYTYPE Quality, + UINT NumClusters, + UINT NumPCA, + LPD3DXSHPRTSIMCB pCB, + LPVOID lpUserContext, + LPD3DXPRTBUFFER pBufferIn, + LPD3DXPRTCOMPBUFFER *ppBufferOut + ); + +//============================================================================ +// +// D3DXCreateTextureGutterHelper: +// -------------------- +// Generates a "GutterHelper" for a given set of meshes and texture +// resolution +// +// Parameters: +// Width +// Width of texture +// Height +// Height of texture +// pMesh +// Mesh that represents the scene +// GutterSize +// Number of texels to over rasterize in texture space +// this should be at least 1.0 +// ppBuffer +// GutterHelper that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreateTextureGutterHelper( + UINT Width, + UINT Height, + LPD3DXMESH pMesh, + FLOAT GutterSize, + LPD3DXTEXTUREGUTTERHELPER* ppBuffer); + + +//============================================================================ +// +// D3DXCreatePRTEngine: +// -------------------- +// Computes a PRTEngine which can efficiently generate PRT simulations +// of a scene +// +// Parameters: +// pMesh +// Mesh that represents the scene - must have an AttributeTable +// where vertices are in a unique attribute. +// pAdjacency +// Optional adjacency information +// ExtractUVs +// Set this to true if textures are going to be used for albedos +// or to store PRT vectors +// pBlockerMesh +// Optional mesh that just blocks the scene +// ppEngine +// PRTEngine that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreatePRTEngine( + LPD3DXMESH pMesh, + DWORD *pAdjacency, + BOOL ExtractUVs, + LPD3DXMESH pBlockerMesh, + LPD3DXPRTENGINE* ppEngine); + +//============================================================================ +// +// D3DXConcatenateMeshes: +// -------------------- +// Concatenates a group of meshes into one common mesh. This can optionaly transform +// each sub mesh or its texture coordinates. If no DECL is given it will +// generate a union of all of the DECL's of the sub meshes, promoting channels +// and types if neccesary. It will create an AttributeTable if possible, one can +// call OptimizeMesh with attribute sort and compacting enabled to ensure this. +// +// Parameters: +// ppMeshes +// Array of pointers to meshes that can store PRT vectors +// NumMeshes +// Number of meshes +// Options +// Passed through to D3DXCreateMesh +// pGeomXForms +// [optional] Each sub mesh is transformed by the corresponding +// matrix if this array is supplied +// pTextureXForms +// [optional] UV coordinates for each sub mesh are transformed +// by corresponding matrix if supplied +// pDecl +// [optional] Only information in this DECL is used when merging +// data +// pD3DDevice +// D3D device that is used to create the new mesh +// ppMeshOut +// Mesh that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXConcatenateMeshes( + LPD3DXMESH *ppMeshes, + UINT NumMeshes, + DWORD Options, + CONST D3DXMATRIX *pGeomXForms, + CONST D3DXMATRIX *pTextureXForms, + CONST D3DVERTEXELEMENT9 *pDecl, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH *ppMeshOut); + +//============================================================================ +// +// D3DXSHPRTCompSuperCluster: +// -------------------------- +// Used with compressed results of D3DXSHPRTSimulation. +// Generates "super clusters" - groups of clusters that can be drawn in +// the same draw call. A greedy algorithm that minimizes overdraw is used +// to group the clusters. +// +// Parameters: +// pClusterIDs +// NumVerts cluster ID's (extracted from a compressed buffer) +// pScene +// Mesh that represents composite scene passed to the simulator +// MaxNumClusters +// Maximum number of clusters allocated per super cluster +// NumClusters +// Number of clusters computed in the simulator +// pSuperClusterIDs +// Array of length NumClusters, contains index of super cluster +// that corresponding cluster was assigned to +// pNumSuperClusters +// Returns the number of super clusters allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXSHPRTCompSuperCluster( + UINT *pClusterIDs, + LPD3DXMESH pScene, + UINT MaxNumClusters, + UINT NumClusters, + UINT *pSuperClusterIDs, + UINT *pNumSuperClusters); + +//============================================================================ +// +// D3DXSHPRTCompSplitMeshSC: +// ------------------------- +// Used with compressed results of the vertex version of the PRT simulator. +// After D3DXSHRTCompSuperCluster has been called this function can be used +// to split the mesh into a group of faces/vertices per super cluster. +// Each super cluster contains all of the faces that contain any vertex +// classified in one of its clusters. All of the vertices connected to this +// set of faces are also included with the returned array ppVertStatus +// indicating whether or not the vertex belongs to the supercluster. +// +// Parameters: +// pClusterIDs +// NumVerts cluster ID's (extracted from a compressed buffer) +// NumVertices +// Number of vertices in original mesh +// NumClusters +// Number of clusters (input parameter to compression) +// pSuperClusterIDs +// Array of size NumClusters that will contain super cluster ID's (from +// D3DXSHCompSuerCluster) +// NumSuperClusters +// Number of superclusters allocated in D3DXSHCompSuerCluster +// pInputIB +// Raw index buffer for mesh - format depends on bInputIBIs32Bit +// InputIBIs32Bit +// Indicates whether the input index buffer is 32-bit (otherwise 16-bit +// is assumed) +// NumFaces +// Number of faces in the original mesh (pInputIB is 3 times this length) +// ppIBData +// LPD3DXBUFFER holds raw index buffer that will contain the resulting split faces. +// Format determined by bIBIs32Bit. Allocated by function +// pIBDataLength +// Length of ppIBData, assigned in function +// OutputIBIs32Bit +// Indicates whether the output index buffer is to be 32-bit (otherwise +// 16-bit is assumed) +// ppFaceRemap +// LPD3DXBUFFER mapping of each face in ppIBData to original faces. Length is +// *pIBDataLength/3. Optional paramter, allocated in function +// ppVertData +// LPD3DXBUFFER contains new vertex data structure. Size of pVertDataLength +// pVertDataLength +// Number of new vertices in split mesh. Assigned in function +// pSCClusterList +// Array of length NumClusters which pSCData indexes into (Cluster* fields) +// for each SC, contains clusters sorted by super cluster +// pSCData +// Structure per super cluster - contains indices into ppIBData, +// pSCClusterList and ppVertData +// +//============================================================================ + +HRESULT WINAPI + D3DXSHPRTCompSplitMeshSC( + UINT *pClusterIDs, + UINT NumVertices, + UINT NumClusters, + UINT *pSuperClusterIDs, + UINT NumSuperClusters, + LPVOID pInputIB, + BOOL InputIBIs32Bit, + UINT NumFaces, + LPD3DXBUFFER *ppIBData, + UINT *pIBDataLength, + BOOL OutputIBIs32Bit, + LPD3DXBUFFER *ppFaceRemap, + LPD3DXBUFFER *ppVertData, + UINT *pVertDataLength, + UINT *pSCClusterList, + D3DXSHPRTSPLITMESHCLUSTERDATA *pSCData); + + +#ifdef __cplusplus +} +#endif //__cplusplus + +////////////////////////////////////////////////////////////////////////////// +// +// Definitions of .X file templates used by mesh load/save functions +// that are not RM standard +// +////////////////////////////////////////////////////////////////////////////// + +// {3CF169CE-FF7C-44ab-93C0-F78F62D172E2} +DEFINE_GUID(DXFILEOBJ_XSkinMeshHeader, +0x3cf169ce, 0xff7c, 0x44ab, 0x93, 0xc0, 0xf7, 0x8f, 0x62, 0xd1, 0x72, 0xe2); + +// {B8D65549-D7C9-4995-89CF-53A9A8B031E3} +DEFINE_GUID(DXFILEOBJ_VertexDuplicationIndices, +0xb8d65549, 0xd7c9, 0x4995, 0x89, 0xcf, 0x53, 0xa9, 0xa8, 0xb0, 0x31, 0xe3); + +// {A64C844A-E282-4756-8B80-250CDE04398C} +DEFINE_GUID(DXFILEOBJ_FaceAdjacency, +0xa64c844a, 0xe282, 0x4756, 0x8b, 0x80, 0x25, 0xc, 0xde, 0x4, 0x39, 0x8c); + +// {6F0D123B-BAD2-4167-A0D0-80224F25FABB} +DEFINE_GUID(DXFILEOBJ_SkinWeights, +0x6f0d123b, 0xbad2, 0x4167, 0xa0, 0xd0, 0x80, 0x22, 0x4f, 0x25, 0xfa, 0xbb); + +// {A3EB5D44-FC22-429d-9AFB-3221CB9719A6} +DEFINE_GUID(DXFILEOBJ_Patch, +0xa3eb5d44, 0xfc22, 0x429d, 0x9a, 0xfb, 0x32, 0x21, 0xcb, 0x97, 0x19, 0xa6); + +// {D02C95CC-EDBA-4305-9B5D-1820D7704BBF} +DEFINE_GUID(DXFILEOBJ_PatchMesh, +0xd02c95cc, 0xedba, 0x4305, 0x9b, 0x5d, 0x18, 0x20, 0xd7, 0x70, 0x4b, 0xbf); + +// {B9EC94E1-B9A6-4251-BA18-94893F02C0EA} +DEFINE_GUID(DXFILEOBJ_PatchMesh9, +0xb9ec94e1, 0xb9a6, 0x4251, 0xba, 0x18, 0x94, 0x89, 0x3f, 0x2, 0xc0, 0xea); + +// {B6C3E656-EC8B-4b92-9B62-681659522947} +DEFINE_GUID(DXFILEOBJ_PMInfo, +0xb6c3e656, 0xec8b, 0x4b92, 0x9b, 0x62, 0x68, 0x16, 0x59, 0x52, 0x29, 0x47); + +// {917E0427-C61E-4a14-9C64-AFE65F9E9844} +DEFINE_GUID(DXFILEOBJ_PMAttributeRange, +0x917e0427, 0xc61e, 0x4a14, 0x9c, 0x64, 0xaf, 0xe6, 0x5f, 0x9e, 0x98, 0x44); + +// {574CCC14-F0B3-4333-822D-93E8A8A08E4C} +DEFINE_GUID(DXFILEOBJ_PMVSplitRecord, +0x574ccc14, 0xf0b3, 0x4333, 0x82, 0x2d, 0x93, 0xe8, 0xa8, 0xa0, 0x8e, 0x4c); + +// {B6E70A0E-8EF9-4e83-94AD-ECC8B0C04897} +DEFINE_GUID(DXFILEOBJ_FVFData, +0xb6e70a0e, 0x8ef9, 0x4e83, 0x94, 0xad, 0xec, 0xc8, 0xb0, 0xc0, 0x48, 0x97); + +// {F752461C-1E23-48f6-B9F8-8350850F336F} +DEFINE_GUID(DXFILEOBJ_VertexElement, +0xf752461c, 0x1e23, 0x48f6, 0xb9, 0xf8, 0x83, 0x50, 0x85, 0xf, 0x33, 0x6f); + +// {BF22E553-292C-4781-9FEA-62BD554BDD93} +DEFINE_GUID(DXFILEOBJ_DeclData, +0xbf22e553, 0x292c, 0x4781, 0x9f, 0xea, 0x62, 0xbd, 0x55, 0x4b, 0xdd, 0x93); + +// {F1CFE2B3-0DE3-4e28-AFA1-155A750A282D} +DEFINE_GUID(DXFILEOBJ_EffectFloats, +0xf1cfe2b3, 0xde3, 0x4e28, 0xaf, 0xa1, 0x15, 0x5a, 0x75, 0xa, 0x28, 0x2d); + +// {D55B097E-BDB6-4c52-B03D-6051C89D0E42} +DEFINE_GUID(DXFILEOBJ_EffectString, +0xd55b097e, 0xbdb6, 0x4c52, 0xb0, 0x3d, 0x60, 0x51, 0xc8, 0x9d, 0xe, 0x42); + +// {622C0ED0-956E-4da9-908A-2AF94F3CE716} +DEFINE_GUID(DXFILEOBJ_EffectDWord, +0x622c0ed0, 0x956e, 0x4da9, 0x90, 0x8a, 0x2a, 0xf9, 0x4f, 0x3c, 0xe7, 0x16); + +// {3014B9A0-62F5-478c-9B86-E4AC9F4E418B} +DEFINE_GUID(DXFILEOBJ_EffectParamFloats, +0x3014b9a0, 0x62f5, 0x478c, 0x9b, 0x86, 0xe4, 0xac, 0x9f, 0x4e, 0x41, 0x8b); + +// {1DBC4C88-94C1-46ee-9076-2C28818C9481} +DEFINE_GUID(DXFILEOBJ_EffectParamString, +0x1dbc4c88, 0x94c1, 0x46ee, 0x90, 0x76, 0x2c, 0x28, 0x81, 0x8c, 0x94, 0x81); + +// {E13963BC-AE51-4c5d-B00F-CFA3A9D97CE5} +DEFINE_GUID(DXFILEOBJ_EffectParamDWord, +0xe13963bc, 0xae51, 0x4c5d, 0xb0, 0xf, 0xcf, 0xa3, 0xa9, 0xd9, 0x7c, 0xe5); + +// {E331F7E4-0559-4cc2-8E99-1CEC1657928F} +DEFINE_GUID(DXFILEOBJ_EffectInstance, +0xe331f7e4, 0x559, 0x4cc2, 0x8e, 0x99, 0x1c, 0xec, 0x16, 0x57, 0x92, 0x8f); + +// {9E415A43-7BA6-4a73-8743-B73D47E88476} +DEFINE_GUID(DXFILEOBJ_AnimTicksPerSecond, +0x9e415a43, 0x7ba6, 0x4a73, 0x87, 0x43, 0xb7, 0x3d, 0x47, 0xe8, 0x84, 0x76); + +// {7F9B00B3-F125-4890-876E-1CFFBF697C4D} +DEFINE_GUID(DXFILEOBJ_CompressedAnimationSet, +0x7f9b00b3, 0xf125, 0x4890, 0x87, 0x6e, 0x1c, 0x42, 0xbf, 0x69, 0x7c, 0x4d); + +#pragma pack(push, 1) +typedef struct _XFILECOMPRESSEDANIMATIONSET +{ + DWORD CompressedBlockSize; + FLOAT TicksPerSec; + DWORD PlaybackType; + DWORD BufferLength; +} XFILECOMPRESSEDANIMATIONSET; +#pragma pack(pop) + +#define XSKINEXP_TEMPLATES \ + "xof 0303txt 0032\ + template XSkinMeshHeader \ + { \ + <3CF169CE-FF7C-44ab-93C0-F78F62D172E2> \ + WORD nMaxSkinWeightsPerVertex; \ + WORD nMaxSkinWeightsPerFace; \ + WORD nBones; \ + } \ + template VertexDuplicationIndices \ + { \ + \ + DWORD nIndices; \ + DWORD nOriginalVertices; \ + array DWORD indices[nIndices]; \ + } \ + template FaceAdjacency \ + { \ + \ + DWORD nIndices; \ + array DWORD indices[nIndices]; \ + } \ + template SkinWeights \ + { \ + <6F0D123B-BAD2-4167-A0D0-80224F25FABB> \ + STRING transformNodeName; \ + DWORD nWeights; \ + array DWORD vertexIndices[nWeights]; \ + array float weights[nWeights]; \ + Matrix4x4 matrixOffset; \ + } \ + template Patch \ + { \ + \ + DWORD nControlIndices; \ + array DWORD controlIndices[nControlIndices]; \ + } \ + template PatchMesh \ + { \ + \ + DWORD nVertices; \ + array Vector vertices[nVertices]; \ + DWORD nPatches; \ + array Patch patches[nPatches]; \ + [ ... ] \ + } \ + template PatchMesh9 \ + { \ + \ + DWORD Type; \ + DWORD Degree; \ + DWORD Basis; \ + DWORD nVertices; \ + array Vector vertices[nVertices]; \ + DWORD nPatches; \ + array Patch patches[nPatches]; \ + [ ... ] \ + } " \ + "template EffectFloats \ + { \ + \ + DWORD nFloats; \ + array float Floats[nFloats]; \ + } \ + template EffectString \ + { \ + \ + STRING Value; \ + } \ + template EffectDWord \ + { \ + <622C0ED0-956E-4da9-908A-2AF94F3CE716> \ + DWORD Value; \ + } " \ + "template EffectParamFloats \ + { \ + <3014B9A0-62F5-478c-9B86-E4AC9F4E418B> \ + STRING ParamName; \ + DWORD nFloats; \ + array float Floats[nFloats]; \ + } " \ + "template EffectParamString \ + { \ + <1DBC4C88-94C1-46ee-9076-2C28818C9481> \ + STRING ParamName; \ + STRING Value; \ + } \ + template EffectParamDWord \ + { \ + \ + STRING ParamName; \ + DWORD Value; \ + } \ + template EffectInstance \ + { \ + \ + STRING EffectFilename; \ + [ ... ] \ + } " \ + "template AnimTicksPerSecond \ + { \ + <9E415A43-7BA6-4a73-8743-B73D47E88476> \ + DWORD AnimTicksPerSecond; \ + } \ + template CompressedAnimationSet \ + { \ + <7F9B00B3-F125-4890-876E-1C42BF697C4D> \ + DWORD CompressedBlockSize; \ + FLOAT TicksPerSec; \ + DWORD PlaybackType; \ + DWORD BufferLength; \ + array DWORD CompressedData[BufferLength]; \ + } " + +#define XEXTENSIONS_TEMPLATES \ + "xof 0303txt 0032\ + template FVFData \ + { \ + \ + DWORD dwFVF; \ + DWORD nDWords; \ + array DWORD data[nDWords]; \ + } \ + template VertexElement \ + { \ + \ + DWORD Type; \ + DWORD Method; \ + DWORD Usage; \ + DWORD UsageIndex; \ + } \ + template DeclData \ + { \ + \ + DWORD nElements; \ + array VertexElement Elements[nElements]; \ + DWORD nDWords; \ + array DWORD data[nDWords]; \ + } \ + template PMAttributeRange \ + { \ + <917E0427-C61E-4a14-9C64-AFE65F9E9844> \ + DWORD iFaceOffset; \ + DWORD nFacesMin; \ + DWORD nFacesMax; \ + DWORD iVertexOffset; \ + DWORD nVerticesMin; \ + DWORD nVerticesMax; \ + } \ + template PMVSplitRecord \ + { \ + <574CCC14-F0B3-4333-822D-93E8A8A08E4C> \ + DWORD iFaceCLW; \ + DWORD iVlrOffset; \ + DWORD iCode; \ + } \ + template PMInfo \ + { \ + \ + DWORD nAttributes; \ + array PMAttributeRange attributeRanges[nAttributes]; \ + DWORD nMaxValence; \ + DWORD nMinLogicalVertices; \ + DWORD nMaxLogicalVertices; \ + DWORD nVSplits; \ + array PMVSplitRecord splitRecords[nVSplits]; \ + DWORD nAttributeMispredicts; \ + array DWORD attributeMispredicts[nAttributeMispredicts]; \ + } " + +#endif //__D3DX9MESH_H__ + + diff --git a/src/depend/mingw/include/directx9/d3dx9shader.h b/src/depend/mingw/include/directx9/d3dx9shader.h new file mode 100644 index 00000000..5ed3f01d --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9shader.h @@ -0,0 +1,1010 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File: d3dx9shader.h +// Content: D3DX Shader APIs +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9SHADER_H__ +#define __D3DX9SHADER_H__ + + +//--------------------------------------------------------------------------- +// D3DXTX_VERSION: +// -------------- +// Version token used to create a procedural texture filler in effects +// Used by D3DXFill[]TX functions +//--------------------------------------------------------------------------- +#define D3DXTX_VERSION(_Major,_Minor) (('T' << 24) | ('X' << 16) | ((_Major) << 8) | (_Minor)) + + + +//---------------------------------------------------------------------------- +// D3DXSHADER flags: +// ----------------- +// D3DXSHADER_DEBUG +// Insert debug file/line/type/symbol information. +// +// D3DXSHADER_SKIPVALIDATION +// Do not validate the generated code against known capabilities and +// constraints. This option is only recommended when compiling shaders +// you KNOW will work. (ie. have compiled before without this option.) +// Shaders are always validated by D3D before they are set to the device. +// +// D3DXSHADER_SKIPOPTIMIZATION +// Instructs the compiler to skip optimization steps during code generation. +// Unless you are trying to isolate a problem in your code using this option +// is not recommended. +// +// D3DXSHADER_PACKMATRIX_ROWMAJOR +// Unless explicitly specified, matrices will be packed in row-major order +// on input and output from the shader. +// +// D3DXSHADER_PACKMATRIX_COLUMNMAJOR +// Unless explicitly specified, matrices will be packed in column-major +// order on input and output from the shader. This is generally more +// efficient, since it allows vector-matrix multiplication to be performed +// using a series of dot-products. +// +// D3DXSHADER_PARTIALPRECISION +// Force all computations in resulting shader to occur at partial precision. +// This may result in faster evaluation of shaders on some hardware. +// +// D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT +// Force compiler to compile against the next highest available software +// target for vertex shaders. This flag also turns optimizations off, +// and debugging on. +// +// D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT +// Force compiler to compile against the next highest available software +// target for pixel shaders. This flag also turns optimizations off, +// and debugging on. +// +// D3DXSHADER_NO_PRESHADER +// Disables Preshaders. Using this flag will cause the compiler to not +// pull out static expression for evaluation on the host cpu +// +// D3DXSHADER_AVOID_FLOW_CONTROL +// Hint compiler to avoid flow-control constructs where possible. +// +// D3DXSHADER_PREFER_FLOW_CONTROL +// Hint compiler to prefer flow-control constructs where possible. +// +//---------------------------------------------------------------------------- + +#define D3DXSHADER_DEBUG (1 << 0) +#define D3DXSHADER_SKIPVALIDATION (1 << 1) +#define D3DXSHADER_SKIPOPTIMIZATION (1 << 2) +#define D3DXSHADER_PACKMATRIX_ROWMAJOR (1 << 3) +#define D3DXSHADER_PACKMATRIX_COLUMNMAJOR (1 << 4) +#define D3DXSHADER_PARTIALPRECISION (1 << 5) +#define D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT (1 << 6) +#define D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT (1 << 7) +#define D3DXSHADER_NO_PRESHADER (1 << 8) +#define D3DXSHADER_AVOID_FLOW_CONTROL (1 << 9) +#define D3DXSHADER_PREFER_FLOW_CONTROL (1 << 10) +#define D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY (1 << 12) +#define D3DXSHADER_IEEE_STRICTNESS (1 << 13) +#define D3DXSHADER_USE_LEGACY_D3DX9_31_DLL (1 << 16) + + +// optimization level flags +#define D3DXSHADER_OPTIMIZATION_LEVEL0 (1 << 14) +#define D3DXSHADER_OPTIMIZATION_LEVEL1 0 +#define D3DXSHADER_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) +#define D3DXSHADER_OPTIMIZATION_LEVEL3 (1 << 15) + + + +//---------------------------------------------------------------------------- +// D3DXCONSTTABLE flags: +// ------------------- + +#define D3DXCONSTTABLE_LARGEADDRESSAWARE (1 << 17) + + + +//---------------------------------------------------------------------------- +// D3DXHANDLE: +// ----------- +// Handle values used to efficiently reference shader and effect parameters. +// Strings can be used as handles. However, handles are not always strings. +//---------------------------------------------------------------------------- + +#ifndef D3DXFX_LARGEADDRESS_HANDLE +typedef LPCSTR D3DXHANDLE; +#else +typedef UINT_PTR D3DXHANDLE; +#endif +typedef D3DXHANDLE *LPD3DXHANDLE; + + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + + +//---------------------------------------------------------------------------- +// D3DXSEMANTIC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXSEMANTIC +{ + UINT Usage; + UINT UsageIndex; + +} D3DXSEMANTIC, *LPD3DXSEMANTIC; + + + +//---------------------------------------------------------------------------- +// D3DXREGISTER_SET: +//---------------------------------------------------------------------------- + +typedef enum _D3DXREGISTER_SET +{ + D3DXRS_BOOL, + D3DXRS_INT4, + D3DXRS_FLOAT4, + D3DXRS_SAMPLER, + + // force 32-bit size enum + D3DXRS_FORCE_DWORD = 0x7fffffff + +} D3DXREGISTER_SET, *LPD3DXREGISTER_SET; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_CLASS: +//---------------------------------------------------------------------------- + +typedef enum _D3DXPARAMETER_CLASS +{ + D3DXPC_SCALAR, + D3DXPC_VECTOR, + D3DXPC_MATRIX_ROWS, + D3DXPC_MATRIX_COLUMNS, + D3DXPC_OBJECT, + D3DXPC_STRUCT, + + // force 32-bit size enum + D3DXPC_FORCE_DWORD = 0x7fffffff + +} D3DXPARAMETER_CLASS, *LPD3DXPARAMETER_CLASS; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_TYPE: +//---------------------------------------------------------------------------- + +typedef enum _D3DXPARAMETER_TYPE +{ + D3DXPT_VOID, + D3DXPT_BOOL, + D3DXPT_INT, + D3DXPT_FLOAT, + D3DXPT_STRING, + D3DXPT_TEXTURE, + D3DXPT_TEXTURE1D, + D3DXPT_TEXTURE2D, + D3DXPT_TEXTURE3D, + D3DXPT_TEXTURECUBE, + D3DXPT_SAMPLER, + D3DXPT_SAMPLER1D, + D3DXPT_SAMPLER2D, + D3DXPT_SAMPLER3D, + D3DXPT_SAMPLERCUBE, + D3DXPT_PIXELSHADER, + D3DXPT_VERTEXSHADER, + D3DXPT_PIXELFRAGMENT, + D3DXPT_VERTEXFRAGMENT, + D3DXPT_UNSUPPORTED, + + // force 32-bit size enum + D3DXPT_FORCE_DWORD = 0x7fffffff + +} D3DXPARAMETER_TYPE, *LPD3DXPARAMETER_TYPE; + + +//---------------------------------------------------------------------------- +// D3DXCONSTANTTABLE_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXCONSTANTTABLE_DESC +{ + LPCSTR Creator; // Creator string + DWORD Version; // Shader version + UINT Constants; // Number of constants + +} D3DXCONSTANTTABLE_DESC, *LPD3DXCONSTANTTABLE_DESC; + + +//---------------------------------------------------------------------------- +// D3DXCONSTANT_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXCONSTANT_DESC +{ + LPCSTR Name; // Constant name + + D3DXREGISTER_SET RegisterSet; // Register set + UINT RegisterIndex; // Register index + UINT RegisterCount; // Number of registers occupied + + D3DXPARAMETER_CLASS Class; // Class + D3DXPARAMETER_TYPE Type; // Component type + + UINT Rows; // Number of rows + UINT Columns; // Number of columns + UINT Elements; // Number of array elements + UINT StructMembers; // Number of structure member sub-parameters + + UINT Bytes; // Data size, in bytes + LPCVOID DefaultValue; // Pointer to default value + +} D3DXCONSTANT_DESC, *LPD3DXCONSTANT_DESC; + + + +//---------------------------------------------------------------------------- +// ID3DXConstantTable: +//---------------------------------------------------------------------------- + +typedef interface ID3DXConstantTable ID3DXConstantTable; +typedef interface ID3DXConstantTable *LPD3DXCONSTANTTABLE; + +// {AB3C758F-093E-4356-B762-4DB18F1B3A01} +DEFINE_GUID(IID_ID3DXConstantTable, +0xab3c758f, 0x93e, 0x4356, 0xb7, 0x62, 0x4d, 0xb1, 0x8f, 0x1b, 0x3a, 0x1); + + +#undef INTERFACE +#define INTERFACE ID3DXConstantTable + +DECLARE_INTERFACE_(ID3DXConstantTable, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Buffer + STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE; + STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; + STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; + STDMETHOD_(UINT, GetSamplerIndex)(THIS_ D3DXHANDLE hConstant) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + // Set Constants + STDMETHOD(SetDefaults)(THIS_ LPDIRECT3DDEVICE9 pDevice) PURE; + STDMETHOD(SetValue)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, BOOL b) PURE; + STDMETHOD(SetBoolArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, INT n) PURE; + STDMETHOD(SetIntArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, FLOAT f) PURE; + STDMETHOD(SetFloatArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXTextureShader: +//---------------------------------------------------------------------------- + +typedef interface ID3DXTextureShader ID3DXTextureShader; +typedef interface ID3DXTextureShader *LPD3DXTEXTURESHADER; + +// {3E3D67F8-AA7A-405d-A857-BA01D4758426} +DEFINE_GUID(IID_ID3DXTextureShader, +0x3e3d67f8, 0xaa7a, 0x405d, 0xa8, 0x57, 0xba, 0x1, 0xd4, 0x75, 0x84, 0x26); + +#undef INTERFACE +#define INTERFACE ID3DXTextureShader + +DECLARE_INTERFACE_(ID3DXTextureShader, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Gets + STDMETHOD(GetFunction)(THIS_ LPD3DXBUFFER *ppFunction) PURE; + STDMETHOD(GetConstantBuffer)(THIS_ LPD3DXBUFFER *ppConstantBuffer) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; + STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + // Set Constants + STDMETHOD(SetDefaults)(THIS) PURE; + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hConstant, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hConstant, BOOL b) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hConstant, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hConstant, INT n) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hConstant, CONST INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hConstant, FLOAT f) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hConstant, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXINCLUDE_TYPE: +//---------------------------------------------------------------------------- + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + D3DXINC_SYSTEM, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE, *LPD3DXINCLUDE_TYPE; + + +//---------------------------------------------------------------------------- +// ID3DXInclude: +// ------------- +// This interface is intended to be implemented by the application, and can +// be used by various D3DX APIs. This enables application-specific handling +// of #include directives in source files. +// +// Open() +// Opens an include file. If successful, it should fill in ppData and +// pBytes. The data pointer returned must remain valid until Close is +// subsequently called. The name of the file is encoded in UTF-8 format. +// Close() +// Closes an include file. If Open was successful, Close is guaranteed +// to be called before the API using this interface returns. +//---------------------------------------------------------------------------- + +typedef interface ID3DXInclude ID3DXInclude; +typedef interface ID3DXInclude *LPD3DXINCLUDE; + +#undef INTERFACE +#define INTERFACE ID3DXInclude + +DECLARE_INTERFACE(ID3DXInclude) +{ + STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) PURE; + STDMETHOD(Close)(THIS_ LPCVOID pData) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// APIs ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//---------------------------------------------------------------------------- +// D3DXAssembleShader: +// ------------------- +// Assembles a shader. +// +// Parameters: +// pSrcFile +// Source file name +// hSrcModule +// Module handle. if NULL, current module will be used +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to source code +// SrcDataLen +// Size of source code, in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when assembling +// from file, and will error when assembling from resource or memory. +// Flags +// See D3DXSHADER_xxx flags +// ppShader +// Returns a buffer containing the created shader. This buffer contains +// the assembled shader code, as well as any embedded debug info. +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during assembly. If you are running in a debugger, +// these are the same messages you will see in your debug output. +//---------------------------------------------------------------------------- + + +HRESULT WINAPI + D3DXAssembleShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXAssembleShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXAssembleShaderFromFile D3DXAssembleShaderFromFileW +#else +#define D3DXAssembleShaderFromFile D3DXAssembleShaderFromFileA +#endif + + +HRESULT WINAPI + D3DXAssembleShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXAssembleShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXAssembleShaderFromResource D3DXAssembleShaderFromResourceW +#else +#define D3DXAssembleShaderFromResource D3DXAssembleShaderFromResourceA +#endif + + +HRESULT WINAPI + D3DXAssembleShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + + + +//---------------------------------------------------------------------------- +// D3DXCompileShader: +// ------------------ +// Compiles a shader. +// +// Parameters: +// pSrcFile +// Source file name. +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module. +// pSrcData +// Pointer to source code. +// SrcDataLen +// Size of source code, in bytes. +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pFunctionName +// Name of the entrypoint function where execution should begin. +// pProfile +// Instruction set to be used when generating code. Currently supported +// profiles are "vs_1_1", "vs_2_0", "vs_2_a", "vs_2_sw", "ps_1_1", +// "ps_1_2", "ps_1_3", "ps_1_4", "ps_2_0", "ps_2_a", "ps_2_sw", "tx_1_0" +// Flags +// See D3DXSHADER_xxx flags. +// ppShader +// Returns a buffer containing the created shader. This buffer contains +// the compiled shader code, as well as any embedded debug and symbol +// table info. (See D3DXGetShaderConstantTable) +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during the compile. If you are running in a debugger, +// these are the same messages you will see in your debug output. +// ppConstantTable +// Returns a ID3DXConstantTable object which can be used to set +// shader constants to the device. Alternatively, an application can +// parse the D3DXSHADER_CONSTANTTABLE block embedded as a comment within +// the shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCompileShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +HRESULT WINAPI + D3DXCompileShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +#ifdef UNICODE +#define D3DXCompileShaderFromFile D3DXCompileShaderFromFileW +#else +#define D3DXCompileShaderFromFile D3DXCompileShaderFromFileA +#endif + + +HRESULT WINAPI + D3DXCompileShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +HRESULT WINAPI + D3DXCompileShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +#ifdef UNICODE +#define D3DXCompileShaderFromResource D3DXCompileShaderFromResourceW +#else +#define D3DXCompileShaderFromResource D3DXCompileShaderFromResourceA +#endif + + +HRESULT WINAPI + D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + + +//---------------------------------------------------------------------------- +// D3DXDisassembleShader: +// ---------------------- +// Takes a binary shader, and returns a buffer containing text assembly. +// +// Parameters: +// pShader +// Pointer to the shader byte code. +// ShaderSizeInBytes +// Size of the shader byte code in bytes. +// EnableColorCode +// Emit HTML tags for color coding the output? +// pComments +// Pointer to a comment string to include at the top of the shader. +// ppDisassembly +// Returns a buffer containing the disassembled shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXDisassembleShader( + CONST DWORD* pShader, + BOOL EnableColorCode, + LPCSTR pComments, + LPD3DXBUFFER* ppDisassembly); + + +//---------------------------------------------------------------------------- +// D3DXGetPixelShaderProfile/D3DXGetVertexShaderProfile: +// ----------------------------------------------------- +// Returns the name of the HLSL profile best suited to a given device. +// +// Parameters: +// pDevice +// Pointer to the device in question +//---------------------------------------------------------------------------- + +LPCSTR WINAPI + D3DXGetPixelShaderProfile( + LPDIRECT3DDEVICE9 pDevice); + +LPCSTR WINAPI + D3DXGetVertexShaderProfile( + LPDIRECT3DDEVICE9 pDevice); + + +//---------------------------------------------------------------------------- +// D3DXFindShaderComment: +// ---------------------- +// Searches through a shader for a particular comment, denoted by a FourCC in +// the first DWORD of the comment. If the comment is not found, and no other +// error has occurred, S_FALSE is returned. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// FourCC +// FourCC used to identify the desired comment block. +// ppData +// Returns a pointer to the comment data (not including comment token +// and FourCC). Can be NULL. +// pSizeInBytes +// Returns the size of the comment data in bytes. Can be NULL. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFindShaderComment( + CONST DWORD* pFunction, + DWORD FourCC, + LPCVOID* ppData, + UINT* pSizeInBytes); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderSize: +// ------------------ +// Returns the size of the shader byte-code, in bytes. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +//---------------------------------------------------------------------------- + +UINT WINAPI + D3DXGetShaderSize( + CONST DWORD* pFunction); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderVersion: +// ----------------------- +// Returns the shader version of a given shader. Returns zero if the shader +// function is NULL. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +//---------------------------------------------------------------------------- + +DWORD WINAPI + D3DXGetShaderVersion( + CONST DWORD* pFunction); + +//---------------------------------------------------------------------------- +// D3DXGetShaderSemantics: +// ----------------------- +// Gets semantics for all input elements referenced inside a given shader. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// pSemantics +// Pointer to an array of D3DXSEMANTIC structures. The function will +// fill this array with the semantics for each input element referenced +// inside the shader. This array is assumed to contain at least +// MAXD3DDECLLENGTH elements. +// pCount +// Returns the number of elements referenced by the shader +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderInputSemantics( + CONST DWORD* pFunction, + D3DXSEMANTIC* pSemantics, + UINT* pCount); + +HRESULT WINAPI + D3DXGetShaderOutputSemantics( + CONST DWORD* pFunction, + D3DXSEMANTIC* pSemantics, + UINT* pCount); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderSamplers: +// ---------------------- +// Gets semantics for all input elements referenced inside a given shader. +// +// pFunction +// Pointer to the function DWORD stream +// pSamplers +// Pointer to an array of LPCSTRs. The function will fill this array +// with pointers to the sampler names contained within pFunction, for +// each sampler referenced inside the shader. This array is assumed to +// contain at least 16 elements. +// pCount +// Returns the number of samplers referenced by the shader +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderSamplers( + CONST DWORD* pFunction, + LPCSTR* pSamplers, + UINT* pCount); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderConstantTable: +// --------------------------- +// Gets shader constant table embedded inside shader. A constant table is +// generated by D3DXAssembleShader and D3DXCompileShader, and is embedded in +// the body of the shader. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// Flags +// See D3DXCONSTTABLE_xxx +// ppConstantTable +// Returns a ID3DXConstantTable object which can be used to set +// shader constants to the device. Alternatively, an application can +// parse the D3DXSHADER_CONSTANTTABLE block embedded as a comment within +// the shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderConstantTable( + CONST DWORD* pFunction, + LPD3DXCONSTANTTABLE* ppConstantTable); + +HRESULT WINAPI + D3DXGetShaderConstantTableEx( + CONST DWORD* pFunction, + DWORD Flags, + LPD3DXCONSTANTTABLE* ppConstantTable); + + + +//---------------------------------------------------------------------------- +// D3DXCreateTextureShader: +// ------------------------ +// Creates a texture shader object, given the compiled shader. +// +// Parameters +// pFunction +// Pointer to the function DWORD stream +// ppTextureShader +// Returns a ID3DXTextureShader object which can be used to procedurally +// fill the contents of a texture using the D3DXFillTextureTX functions. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateTextureShader( + CONST DWORD* pFunction, + LPD3DXTEXTURESHADER* ppTextureShader); + + +//---------------------------------------------------------------------------- +// D3DXPreprocessShader: +// --------------------- +// Runs the preprocessor on the specified shader or effect, but does +// not actually compile it. This is useful for evaluating the #includes +// and #defines in a shader and then emitting a reformatted token stream +// for debugging purposes or for generating a self-contained shader. +// +// Parameters: +// pSrcFile +// Source file name +// hSrcModule +// Module handle. if NULL, current module will be used +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to source code +// SrcDataLen +// Size of source code, in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when assembling +// from file, and will error when assembling from resource or memory. +// ppShaderText +// Returns a buffer containing a single large string that represents +// the resulting formatted token stream +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during assembly. If you are running in a debugger, +// these are the same messages you will see in your debug output. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXPreprocessShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXPreprocessShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXPreprocessShaderFromFile D3DXPreprocessShaderFromFileW +#else +#define D3DXPreprocessShaderFromFile D3DXPreprocessShaderFromFileA +#endif + +HRESULT WINAPI + D3DXPreprocessShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXPreprocessShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXPreprocessShaderFromResource D3DXPreprocessShaderFromResourceW +#else +#define D3DXPreprocessShaderFromResource D3DXPreprocessShaderFromResourceA +#endif + +HRESULT WINAPI + D3DXPreprocessShader( + LPCSTR pSrcData, + UINT SrcDataSize, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + + +#ifdef __cplusplus +} +#endif //__cplusplus + + +////////////////////////////////////////////////////////////////////////////// +// Shader comment block layouts ////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXSHADER_CONSTANTTABLE: +// ------------------------- +// Shader constant information; included as an CTAB comment block inside +// shaders. All offsets are BYTE offsets from start of CONSTANTTABLE struct. +// Entries in the table are sorted by Name in ascending order. +//---------------------------------------------------------------------------- + +typedef struct _D3DXSHADER_CONSTANTTABLE +{ + DWORD Size; // sizeof(D3DXSHADER_CONSTANTTABLE) + DWORD Creator; // LPCSTR offset + DWORD Version; // shader version + DWORD Constants; // number of constants + DWORD ConstantInfo; // D3DXSHADER_CONSTANTINFO[Constants] offset + DWORD Flags; // flags shader was compiled with + DWORD Target; // LPCSTR offset + +} D3DXSHADER_CONSTANTTABLE, *LPD3DXSHADER_CONSTANTTABLE; + + +typedef struct _D3DXSHADER_CONSTANTINFO +{ + DWORD Name; // LPCSTR offset + WORD RegisterSet; // D3DXREGISTER_SET + WORD RegisterIndex; // register number + WORD RegisterCount; // number of registers + WORD Reserved; // reserved + DWORD TypeInfo; // D3DXSHADER_TYPEINFO offset + DWORD DefaultValue; // offset of default value + +} D3DXSHADER_CONSTANTINFO, *LPD3DXSHADER_CONSTANTINFO; + + +typedef struct _D3DXSHADER_TYPEINFO +{ + WORD Class; // D3DXPARAMETER_CLASS + WORD Type; // D3DXPARAMETER_TYPE + WORD Rows; // number of rows (matrices) + WORD Columns; // number of columns (vectors and matrices) + WORD Elements; // array dimension + WORD StructMembers; // number of struct members + DWORD StructMemberInfo; // D3DXSHADER_STRUCTMEMBERINFO[Members] offset + +} D3DXSHADER_TYPEINFO, *LPD3DXSHADER_TYPEINFO; + + +typedef struct _D3DXSHADER_STRUCTMEMBERINFO +{ + DWORD Name; // LPCSTR offset + DWORD TypeInfo; // D3DXSHADER_TYPEINFO offset + +} D3DXSHADER_STRUCTMEMBERINFO, *LPD3DXSHADER_STRUCTMEMBERINFO; + + + +#endif //__D3DX9SHADER_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9shape.h b/src/depend/mingw/include/directx9/d3dx9shape.h new file mode 100644 index 00000000..4c230915 --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9shape.h @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9shapes.h +// Content: D3DX simple shapes +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9SHAPES_H__ +#define __D3DX9SHAPES_H__ + +/////////////////////////////////////////////////////////////////////////// +// Functions: +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//------------------------------------------------------------------------- +// D3DXCreatePolygon: +// ------------------ +// Creates a mesh containing an n-sided polygon. The polygon is centered +// at the origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Length Length of each side. +// Sides Number of sides the polygon has. (Must be >= 3) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreatePolygon( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Length, + UINT Sides, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateBox: +// -------------- +// Creates a mesh containing an axis-aligned box. The box is centered at +// the origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Width Width of box (along X-axis) +// Height Height of box (along Y-axis) +// Depth Depth of box (along Z-axis) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateBox( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Width, + FLOAT Height, + FLOAT Depth, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateCylinder: +// ------------------- +// Creates a mesh containing a cylinder. The generated cylinder is +// centered at the origin, and its axis is aligned with the Z-axis. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Radius1 Radius at -Z end (should be >= 0.0f) +// Radius2 Radius at +Z end (should be >= 0.0f) +// Length Length of cylinder (along Z-axis) +// Slices Number of slices about the main axis +// Stacks Number of stacks along the main axis +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateCylinder( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Radius1, + FLOAT Radius2, + FLOAT Length, + UINT Slices, + UINT Stacks, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateSphere: +// ----------------- +// Creates a mesh containing a sphere. The sphere is centered at the +// origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Radius Radius of the sphere (should be >= 0.0f) +// Slices Number of slices about the main axis +// Stacks Number of stacks along the main axis +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateSphere( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Radius, + UINT Slices, + UINT Stacks, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateTorus: +// ---------------- +// Creates a mesh containing a torus. The generated torus is centered at +// the origin, and its axis is aligned with the Z-axis. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// InnerRadius Inner radius of the torus (should be >= 0.0f) +// OuterRadius Outer radius of the torue (should be >= 0.0f) +// Sides Number of sides in a cross-section (must be >= 3) +// Rings Number of rings making up the torus (must be >= 3) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTorus( + LPDIRECT3DDEVICE9 pDevice, + FLOAT InnerRadius, + FLOAT OuterRadius, + UINT Sides, + UINT Rings, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateTeapot: +// ----------------- +// Creates a mesh containing a teapot. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTeapot( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateText: +// --------------- +// Creates a mesh containing the specified text using the font associated +// with the device context. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// hDC Device context, with desired font selected +// pText Text to generate +// Deviation Maximum chordal deviation from true font outlines +// Extrusion Amount to extrude text in -Z direction +// ppMesh The mesh object which will be created +// pGlyphMetrics Address of buffer to receive glyph metric data (or NULL) +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTextA( + LPDIRECT3DDEVICE9 pDevice, + HDC hDC, + LPCSTR pText, + FLOAT Deviation, + FLOAT Extrusion, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency, + LPGLYPHMETRICSFLOAT pGlyphMetrics); + +HRESULT WINAPI + D3DXCreateTextW( + LPDIRECT3DDEVICE9 pDevice, + HDC hDC, + LPCWSTR pText, + FLOAT Deviation, + FLOAT Extrusion, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency, + LPGLYPHMETRICSFLOAT pGlyphMetrics); + +#ifdef UNICODE +#define D3DXCreateText D3DXCreateTextW +#else +#define D3DXCreateText D3DXCreateTextA +#endif + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9SHAPES_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9tex.h b/src/depend/mingw/include/directx9/d3dx9tex.h new file mode 100644 index 00000000..f259e7ff --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9tex.h @@ -0,0 +1,1735 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9tex.h +// Content: D3DX texturing APIs +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9TEX_H__ +#define __D3DX9TEX_H__ + + +//---------------------------------------------------------------------------- +// D3DX_FILTER flags: +// ------------------ +// +// A valid filter must contain one of these values: +// +// D3DX_FILTER_NONE +// No scaling or filtering will take place. Pixels outside the bounds +// of the source image are assumed to be transparent black. +// D3DX_FILTER_POINT +// Each destination pixel is computed by sampling the nearest pixel +// from the source image. +// D3DX_FILTER_LINEAR +// Each destination pixel is computed by linearly interpolating between +// the nearest pixels in the source image. This filter works best +// when the scale on each axis is less than 2. +// D3DX_FILTER_TRIANGLE +// Every pixel in the source image contributes equally to the +// destination image. This is the slowest of all the filters. +// D3DX_FILTER_BOX +// Each pixel is computed by averaging a 2x2(x2) box pixels from +// the source image. Only works when the dimensions of the +// destination are half those of the source. (as with mip maps) +// +// And can be OR'd with any of these optional flags: +// +// D3DX_FILTER_MIRROR_U +// Indicates that pixels off the edge of the texture on the U-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR_V +// Indicates that pixels off the edge of the texture on the V-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR_W +// Indicates that pixels off the edge of the texture on the W-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR +// Same as specifying D3DX_FILTER_MIRROR_U | D3DX_FILTER_MIRROR_V | +// D3DX_FILTER_MIRROR_V +// D3DX_FILTER_DITHER +// Dithers the resulting image using a 4x4 order dither pattern. +// D3DX_FILTER_SRGB_IN +// Denotes that the input data is in sRGB (gamma 2.2) colorspace. +// D3DX_FILTER_SRGB_OUT +// Denotes that the output data is in sRGB (gamma 2.2) colorspace. +// D3DX_FILTER_SRGB +// Same as specifying D3DX_FILTER_SRGB_IN | D3DX_FILTER_SRGB_OUT +// +//---------------------------------------------------------------------------- + +#define D3DX_FILTER_NONE (1 << 0) +#define D3DX_FILTER_POINT (2 << 0) +#define D3DX_FILTER_LINEAR (3 << 0) +#define D3DX_FILTER_TRIANGLE (4 << 0) +#define D3DX_FILTER_BOX (5 << 0) + +#define D3DX_FILTER_MIRROR_U (1 << 16) +#define D3DX_FILTER_MIRROR_V (2 << 16) +#define D3DX_FILTER_MIRROR_W (4 << 16) +#define D3DX_FILTER_MIRROR (7 << 16) + +#define D3DX_FILTER_DITHER (1 << 19) +#define D3DX_FILTER_DITHER_DIFFUSION (2 << 19) + +#define D3DX_FILTER_SRGB_IN (1 << 21) +#define D3DX_FILTER_SRGB_OUT (2 << 21) +#define D3DX_FILTER_SRGB (3 << 21) + + +//----------------------------------------------------------------------------- +// D3DX_SKIP_DDS_MIP_LEVELS is used to skip mip levels when loading a DDS file: +//----------------------------------------------------------------------------- + +#define D3DX_SKIP_DDS_MIP_LEVELS_MASK 0x1F +#define D3DX_SKIP_DDS_MIP_LEVELS_SHIFT 26 +#define D3DX_SKIP_DDS_MIP_LEVELS(levels, filter) ((((levels) & D3DX_SKIP_DDS_MIP_LEVELS_MASK) << D3DX_SKIP_DDS_MIP_LEVELS_SHIFT) | ((filter) == D3DX_DEFAULT ? D3DX_FILTER_BOX : (filter))) + + + + +//---------------------------------------------------------------------------- +// D3DX_NORMALMAP flags: +// --------------------- +// These flags are used to control how D3DXComputeNormalMap generates normal +// maps. Any number of these flags may be OR'd together in any combination. +// +// D3DX_NORMALMAP_MIRROR_U +// Indicates that pixels off the edge of the texture on the U-axis +// should be mirrored, not wraped. +// D3DX_NORMALMAP_MIRROR_V +// Indicates that pixels off the edge of the texture on the V-axis +// should be mirrored, not wraped. +// D3DX_NORMALMAP_MIRROR +// Same as specifying D3DX_NORMALMAP_MIRROR_U | D3DX_NORMALMAP_MIRROR_V +// D3DX_NORMALMAP_INVERTSIGN +// Inverts the direction of each normal +// D3DX_NORMALMAP_COMPUTE_OCCLUSION +// Compute the per pixel Occlusion term and encodes it into the alpha. +// An Alpha of 1 means that the pixel is not obscured in anyway, and +// an alpha of 0 would mean that the pixel is completly obscured. +// +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +#define D3DX_NORMALMAP_MIRROR_U (1 << 16) +#define D3DX_NORMALMAP_MIRROR_V (2 << 16) +#define D3DX_NORMALMAP_MIRROR (3 << 16) +#define D3DX_NORMALMAP_INVERTSIGN (8 << 16) +#define D3DX_NORMALMAP_COMPUTE_OCCLUSION (16 << 16) + + + + +//---------------------------------------------------------------------------- +// D3DX_CHANNEL flags: +// ------------------- +// These flags are used by functions which operate on or more channels +// in a texture. +// +// D3DX_CHANNEL_RED +// Indicates the red channel should be used +// D3DX_CHANNEL_BLUE +// Indicates the blue channel should be used +// D3DX_CHANNEL_GREEN +// Indicates the green channel should be used +// D3DX_CHANNEL_ALPHA +// Indicates the alpha channel should be used +// D3DX_CHANNEL_LUMINANCE +// Indicates the luminaces of the red green and blue channels should be +// used. +// +//---------------------------------------------------------------------------- + +#define D3DX_CHANNEL_RED (1 << 0) +#define D3DX_CHANNEL_BLUE (1 << 1) +#define D3DX_CHANNEL_GREEN (1 << 2) +#define D3DX_CHANNEL_ALPHA (1 << 3) +#define D3DX_CHANNEL_LUMINANCE (1 << 4) + + + + +//---------------------------------------------------------------------------- +// D3DXIMAGE_FILEFORMAT: +// --------------------- +// This enum is used to describe supported image file formats. +// +//---------------------------------------------------------------------------- + +typedef enum _D3DXIMAGE_FILEFORMAT +{ + D3DXIFF_BMP = 0, + D3DXIFF_JPG = 1, + D3DXIFF_TGA = 2, + D3DXIFF_PNG = 3, + D3DXIFF_DDS = 4, + D3DXIFF_PPM = 5, + D3DXIFF_DIB = 6, + D3DXIFF_HDR = 7, //high dynamic range formats + D3DXIFF_PFM = 8, // + D3DXIFF_FORCE_DWORD = 0x7fffffff + +} D3DXIMAGE_FILEFORMAT; + + +//---------------------------------------------------------------------------- +// LPD3DXFILL2D and LPD3DXFILL3D: +// ------------------------------ +// Function types used by the texture fill functions. +// +// Parameters: +// pOut +// Pointer to a vector which the function uses to return its result. +// X,Y,Z,W will be mapped to R,G,B,A respectivly. +// pTexCoord +// Pointer to a vector containing the coordinates of the texel currently +// being evaluated. Textures and VolumeTexture texcoord components +// range from 0 to 1. CubeTexture texcoord component range from -1 to 1. +// pTexelSize +// Pointer to a vector containing the dimensions of the current texel. +// pData +// Pointer to user data. +// +//---------------------------------------------------------------------------- + +typedef VOID (WINAPI *LPD3DXFILL2D)(D3DXVECTOR4 *pOut, + CONST D3DXVECTOR2 *pTexCoord, CONST D3DXVECTOR2 *pTexelSize, LPVOID pData); + +typedef VOID (WINAPI *LPD3DXFILL3D)(D3DXVECTOR4 *pOut, + CONST D3DXVECTOR3 *pTexCoord, CONST D3DXVECTOR3 *pTexelSize, LPVOID pData); + + + +//---------------------------------------------------------------------------- +// D3DXIMAGE_INFO: +// --------------- +// This structure is used to return a rough description of what the +// the original contents of an image file looked like. +// +// Width +// Width of original image in pixels +// Height +// Height of original image in pixels +// Depth +// Depth of original image in pixels +// MipLevels +// Number of mip levels in original image +// Format +// D3D format which most closely describes the data in original image +// ResourceType +// D3DRESOURCETYPE representing the type of texture stored in the file. +// D3DRTYPE_TEXTURE, D3DRTYPE_VOLUMETEXTURE, or D3DRTYPE_CUBETEXTURE. +// ImageFileFormat +// D3DXIMAGE_FILEFORMAT representing the format of the image file. +// +//---------------------------------------------------------------------------- + +typedef struct _D3DXIMAGE_INFO +{ + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + D3DFORMAT Format; + D3DRESOURCETYPE ResourceType; + D3DXIMAGE_FILEFORMAT ImageFileFormat; + +} D3DXIMAGE_INFO; + + + + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + + +////////////////////////////////////////////////////////////////////////////// +// Image File APIs /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//; +//---------------------------------------------------------------------------- +// GetImageInfoFromFile/Resource: +// ------------------------------ +// Fills in a D3DXIMAGE_INFO struct with information about an image file. +// +// Parameters: +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetImageInfoFromFileA( + LPCSTR pSrcFile, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXGetImageInfoFromFileW( + LPCWSTR pSrcFile, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXGetImageInfoFromFile D3DXGetImageInfoFromFileW +#else +#define D3DXGetImageInfoFromFile D3DXGetImageInfoFromFileA +#endif + + +HRESULT WINAPI + D3DXGetImageInfoFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXGetImageInfoFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXGetImageInfoFromResource D3DXGetImageInfoFromResourceW +#else +#define D3DXGetImageInfoFromResource D3DXGetImageInfoFromResourceA +#endif + + +HRESULT WINAPI + D3DXGetImageInfoFromFileInMemory( + LPCVOID pSrcData, + UINT SrcDataSize, + D3DXIMAGE_INFO* pSrcInfo); + + + + +////////////////////////////////////////////////////////////////////////////// +// Load/Save Surface APIs //////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromFile/Resource: +// --------------------------------- +// Load surface from a file or resource +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcRect +// Source rectangle, or NULL for entire image +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromFileA( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCSTR pSrcFile, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadSurfaceFromFileW( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCWSTR pSrcFile, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadSurfaceFromFile D3DXLoadSurfaceFromFileW +#else +#define D3DXLoadSurfaceFromFile D3DXLoadSurfaceFromFileA +#endif + + + +HRESULT WINAPI + D3DXLoadSurfaceFromResourceA( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadSurfaceFromResourceW( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + +#ifdef UNICODE +#define D3DXLoadSurfaceFromResource D3DXLoadSurfaceFromResourceW +#else +#define D3DXLoadSurfaceFromResource D3DXLoadSurfaceFromResourceA +#endif + + + +HRESULT WINAPI + D3DXLoadSurfaceFromFileInMemory( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCVOID pSrcData, + UINT SrcDataSize, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromSurface: +// --------------------------- +// Load surface from another surface (with color conversion) +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcSurface +// Source surface +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for entire surface +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromSurface( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey); + + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromMemory: +// -------------------------- +// Load surface from memory. +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcMemory +// Pointer to the top-left corner of the source image in memory +// SrcFormat +// Pixel format of the source image. +// SrcPitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the width of one row of cells, in bytes. +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle. +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromMemory( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCVOID pSrcMemory, + D3DFORMAT SrcFormat, + UINT SrcPitch, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey); + + +//---------------------------------------------------------------------------- +// D3DXSaveSurfaceToFile: +// ---------------------- +// Save a surface to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcSurface +// Source surface, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for the entire image +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveSurfaceToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + +HRESULT WINAPI + D3DXSaveSurfaceToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + +#ifdef UNICODE +#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileW +#else +#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileA +#endif + +//---------------------------------------------------------------------------- +// D3DXSaveSurfaceToFileInMemory: +// ---------------------- +// Save a surface to a image file. +// +// Parameters: +// ppDestBuf +// address of pointer to d3dxbuffer for returning data bits +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcSurface +// Source surface, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for the entire image +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveSurfaceToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + + +////////////////////////////////////////////////////////////////////////////// +// Load/Save Volume APIs ///////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromFile/Resource: +// -------------------------------- +// Load volume from a file or resource +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcBox +// Source box, or NULL for entire image +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromFileA( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCSTR pSrcFile, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadVolumeFromFileW( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCWSTR pSrcFile, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadVolumeFromFile D3DXLoadVolumeFromFileW +#else +#define D3DXLoadVolumeFromFile D3DXLoadVolumeFromFileA +#endif + + +HRESULT WINAPI + D3DXLoadVolumeFromResourceA( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadVolumeFromResourceW( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadVolumeFromResource D3DXLoadVolumeFromResourceW +#else +#define D3DXLoadVolumeFromResource D3DXLoadVolumeFromResourceA +#endif + + + +HRESULT WINAPI + D3DXLoadVolumeFromFileInMemory( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCVOID pSrcData, + UINT SrcDataSize, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromVolume: +// ------------------------- +// Load volume from another volume (with color conversion) +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcVolume +// Source volume +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for entire volume +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromVolume( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey); + + + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromMemory: +// ------------------------- +// Load volume from memory. +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcMemory +// Pointer to the top-left corner of the source volume in memory +// SrcFormat +// Pixel format of the source volume. +// SrcRowPitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the size of one row of cells, in bytes. +// SrcSlicePitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the size of one slice of cells, in bytes. +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box. +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromMemory( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCVOID pSrcMemory, + D3DFORMAT SrcFormat, + UINT SrcRowPitch, + UINT SrcSlicePitch, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey); + + + +//---------------------------------------------------------------------------- +// D3DXSaveVolumeToFile: +// --------------------- +// Save a volume to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcVolume +// Source volume, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for the entire volume +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveVolumeToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +HRESULT WINAPI + D3DXSaveVolumeToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +#ifdef UNICODE +#define D3DXSaveVolumeToFile D3DXSaveVolumeToFileW +#else +#define D3DXSaveVolumeToFile D3DXSaveVolumeToFileA +#endif + + +//---------------------------------------------------------------------------- +// D3DXSaveVolumeToFileInMemory: +// --------------------- +// Save a volume to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcVolume +// Source volume, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for the entire volume +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveVolumeToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +////////////////////////////////////////////////////////////////////////////// +// Create/Save Texture APIs ////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXCheckTextureRequirements: +// ----------------------------- +// Checks texture creation parameters. If parameters are invalid, this +// function returns corrected parameters. +// +// Parameters: +// +// pDevice +// The D3D device to be used +// pWidth, pHeight, pDepth, pSize +// Desired size in pixels, or NULL. Returns corrected size. +// pNumMipLevels +// Number of desired mipmap levels, or NULL. Returns corrected number. +// Usage +// Texture usage flags +// pFormat +// Desired pixel format, or NULL. Returns corrected format. +// Pool +// Memory pool to be used to create texture +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCheckTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pWidth, + UINT* pHeight, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + +HRESULT WINAPI + D3DXCheckCubeTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pSize, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + +HRESULT WINAPI + D3DXCheckVolumeTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pWidth, + UINT* pHeight, + UINT* pDepth, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + + +//---------------------------------------------------------------------------- +// D3DXCreateTexture: +// ------------------ +// Create an empty texture +// +// Parameters: +// +// pDevice +// The D3D device with which the texture is going to be used. +// Width, Height, Depth, Size +// size in pixels. these must be non-zero +// MipLevels +// number of mip levels desired. if zero or D3DX_DEFAULT, a complete +// mipmap chain will be created. +// Usage +// Texture usage flags +// Format +// Pixel format. +// Pool +// Memory pool to be used to create texture +// ppTexture, ppCubeTexture, ppVolumeTexture +// The texture object that will be created +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + + +//---------------------------------------------------------------------------- +// D3DXCreateTextureFromFile/Resource: +// ----------------------------------- +// Create a texture object from a file or resource. +// +// Parameters: +// +// pDevice +// The D3D device with which the texture is going to be used. +// pSrcFile +// File name. +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pvSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// Width, Height, Depth, Size +// Size in pixels. If zero or D3DX_DEFAULT, the size will be taken from +// the file and rounded up to a power of two. If D3DX_DEFAULT_NONPOW2, +// and the device supports NONPOW2 textures, the size will not be rounded. +// If D3DX_FROM_FILE, the size will be taken exactly as it is in the file, +// and the call will fail if this violates device capabilities. +// MipLevels +// Number of mip levels. If zero or D3DX_DEFAULT, a complete mipmap +// chain will be created. If D3DX_FROM_FILE, the size will be taken +// exactly as it is in the file, and the call will fail if this violates +// device capabilities. +// Usage +// Texture usage flags +// Format +// Desired pixel format. If D3DFMT_UNKNOWN, the format will be +// taken from the file. If D3DFMT_FROM_FILE, the format will be taken +// exactly as it is in the file, and the call will fail if the device does +// not support the given format. +// Pool +// Memory pool to be used to create texture +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// MipFilter +// D3DX_FILTER flags controlling how each miplevel is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_BOX. +// Use the D3DX_SKIP_DDS_MIP_LEVELS macro to specify both a filter and the +// number of mip levels to skip when loading DDS files. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// pPalette +// 256 color palette to be filled in, or NULL +// ppTexture, ppCubeTexture, ppVolumeTexture +// The texture object that will be created +// +//---------------------------------------------------------------------------- + +// FromFile + +HRESULT WINAPI + D3DXCreateTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromFile D3DXCreateTextureFromFileW +#else +#define D3DXCreateTextureFromFile D3DXCreateTextureFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromFile D3DXCreateCubeTextureFromFileW +#else +#define D3DXCreateCubeTextureFromFile D3DXCreateCubeTextureFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromFile D3DXCreateVolumeTextureFromFileW +#else +#define D3DXCreateVolumeTextureFromFile D3DXCreateVolumeTextureFromFileA +#endif + + +// FromResource + +HRESULT WINAPI + D3DXCreateTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromResource D3DXCreateTextureFromResourceW +#else +#define D3DXCreateTextureFromResource D3DXCreateTextureFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromResource D3DXCreateCubeTextureFromResourceW +#else +#define D3DXCreateCubeTextureFromResource D3DXCreateCubeTextureFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromResource D3DXCreateVolumeTextureFromResourceW +#else +#define D3DXCreateVolumeTextureFromResource D3DXCreateVolumeTextureFromResourceA +#endif + + +// FromFileEx + +HRESULT WINAPI + D3DXCreateTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromFileEx D3DXCreateTextureFromFileExW +#else +#define D3DXCreateTextureFromFileEx D3DXCreateTextureFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromFileEx D3DXCreateCubeTextureFromFileExW +#else +#define D3DXCreateCubeTextureFromFileEx D3DXCreateCubeTextureFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromFileEx D3DXCreateVolumeTextureFromFileExW +#else +#define D3DXCreateVolumeTextureFromFileEx D3DXCreateVolumeTextureFromFileExA +#endif + + +// FromResourceEx + +HRESULT WINAPI + D3DXCreateTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromResourceEx D3DXCreateTextureFromResourceExW +#else +#define D3DXCreateTextureFromResourceEx D3DXCreateTextureFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromResourceEx D3DXCreateCubeTextureFromResourceExW +#else +#define D3DXCreateCubeTextureFromResourceEx D3DXCreateCubeTextureFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromResourceEx D3DXCreateVolumeTextureFromResourceExW +#else +#define D3DXCreateVolumeTextureFromResourceEx D3DXCreateVolumeTextureFromResourceExA +#endif + + +// FromFileInMemory + +HRESULT WINAPI + D3DXCreateTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + +// FromFileInMemoryEx + +HRESULT WINAPI + D3DXCreateTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + + +//---------------------------------------------------------------------------- +// D3DXSaveTextureToFile: +// ---------------------- +// Save a texture to a file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcTexture +// Source texture, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// +//---------------------------------------------------------------------------- + + +HRESULT WINAPI + D3DXSaveTextureToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + +HRESULT WINAPI + D3DXSaveTextureToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + +#ifdef UNICODE +#define D3DXSaveTextureToFile D3DXSaveTextureToFileW +#else +#define D3DXSaveTextureToFile D3DXSaveTextureToFileA +#endif + + +//---------------------------------------------------------------------------- +// D3DXSaveTextureToFileInMemory: +// ---------------------- +// Save a texture to a file. +// +// Parameters: +// ppDestBuf +// address of a d3dxbuffer pointer to return the image data +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcTexture +// Source texture, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveTextureToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + + + + +////////////////////////////////////////////////////////////////////////////// +// Misc Texture APIs ///////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXFilterTexture: +// ------------------ +// Filters mipmaps levels of a texture. +// +// Parameters: +// pBaseTexture +// The texture object to be filtered +// pPalette +// 256 color palette to be used, or NULL for non-palettized formats +// SrcLevel +// The level whose image is used to generate the subsequent levels. +// Filter +// D3DX_FILTER flags controlling how each miplevel is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_BOX, +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFilterTexture( + LPDIRECT3DBASETEXTURE9 pBaseTexture, + CONST PALETTEENTRY* pPalette, + UINT SrcLevel, + DWORD Filter); + +#define D3DXFilterCubeTexture D3DXFilterTexture +#define D3DXFilterVolumeTexture D3DXFilterTexture + + + +//---------------------------------------------------------------------------- +// D3DXFillTexture: +// ---------------- +// Uses a user provided function to fill each texel of each mip level of a +// given texture. +// +// Paramters: +// pTexture, pCubeTexture, pVolumeTexture +// Pointer to the texture to be filled. +// pFunction +// Pointer to user provided evalutor function which will be used to +// compute the value of each texel. +// pData +// Pointer to an arbitrary block of user defined data. This pointer +// will be passed to the function provided in pFunction +//----------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFillTexture( + LPDIRECT3DTEXTURE9 pTexture, + LPD3DXFILL2D pFunction, + LPVOID pData); + +HRESULT WINAPI + D3DXFillCubeTexture( + LPDIRECT3DCUBETEXTURE9 pCubeTexture, + LPD3DXFILL3D pFunction, + LPVOID pData); + +HRESULT WINAPI + D3DXFillVolumeTexture( + LPDIRECT3DVOLUMETEXTURE9 pVolumeTexture, + LPD3DXFILL3D pFunction, + LPVOID pData); + +//--------------------------------------------------------------------------- +// D3DXFillTextureTX: +// ------------------ +// Uses a TX Shader target to function to fill each texel of each mip level +// of a given texture. The TX Shader target should be a compiled function +// taking 2 paramters and returning a float4 color. +// +// Paramters: +// pTexture, pCubeTexture, pVolumeTexture +// Pointer to the texture to be filled. +// pTextureShader +// Pointer to the texture shader to be used to fill in the texture +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFillTextureTX( + LPDIRECT3DTEXTURE9 pTexture, + LPD3DXTEXTURESHADER pTextureShader); + + +HRESULT WINAPI + D3DXFillCubeTextureTX( + LPDIRECT3DCUBETEXTURE9 pCubeTexture, + LPD3DXTEXTURESHADER pTextureShader); + + +HRESULT WINAPI + D3DXFillVolumeTextureTX( + LPDIRECT3DVOLUMETEXTURE9 pVolumeTexture, + LPD3DXTEXTURESHADER pTextureShader); + + + +//---------------------------------------------------------------------------- +// D3DXComputeNormalMap: +// --------------------- +// Converts a height map into a normal map. The (x,y,z) components of each +// normal are mapped to the (r,g,b) channels of the output texture. +// +// Parameters +// pTexture +// Pointer to the destination texture +// pSrcTexture +// Pointer to the source heightmap texture +// pSrcPalette +// Source palette of 256 colors, or NULL +// Flags +// D3DX_NORMALMAP flags +// Channel +// D3DX_CHANNEL specifying source of height information +// Amplitude +// The constant value which the height information is multiplied by. +//--------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXComputeNormalMap( + LPDIRECT3DTEXTURE9 pTexture, + LPDIRECT3DTEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette, + DWORD Flags, + DWORD Channel, + FLOAT Amplitude); + + + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9TEX_H__ + diff --git a/src/depend/mingw/include/directx9/d3dx9xof.h b/src/depend/mingw/include/directx9/d3dx9xof.h new file mode 100644 index 00000000..c513f0fc --- /dev/null +++ b/src/depend/mingw/include/directx9/d3dx9xof.h @@ -0,0 +1,299 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9xof.h +// Content: D3DX .X File types and functions +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#if !defined( __D3DX9XOF_H__ ) +#define __D3DX9XOF_H__ + +#if defined( __cplusplus ) +extern "C" { +#endif // defined( __cplusplus ) + +//---------------------------------------------------------------------------- +// D3DXF_FILEFORMAT +// This flag is used to specify what file type to use when saving to disk. +// _BINARY, and _TEXT are mutually exclusive, while +// _COMPRESSED is an optional setting that works with all file types. +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILEFORMAT; + +#define D3DXF_FILEFORMAT_BINARY 0 +#define D3DXF_FILEFORMAT_TEXT 1 +#define D3DXF_FILEFORMAT_COMPRESSED 2 + +//---------------------------------------------------------------------------- +// D3DXF_FILESAVEOPTIONS +// This flag is used to specify where to save the file to. Each flag is +// mutually exclusive, indicates the data location of the file, and also +// chooses which additional data will specify the location. +// _TOFILE is paired with a filename (LPCSTR) +// _TOWFILE is paired with a filename (LPWSTR) +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILESAVEOPTIONS; + +#define D3DXF_FILESAVE_TOFILE 0x00L +#define D3DXF_FILESAVE_TOWFILE 0x01L + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADOPTIONS +// This flag is used to specify where to load the file from. Each flag is +// mutually exclusive, indicates the data location of the file, and also +// chooses which additional data will specify the location. +// _FROMFILE is paired with a filename (LPCSTR) +// _FROMWFILE is paired with a filename (LPWSTR) +// _FROMRESOURCE is paired with a (D3DXF_FILELOADRESOUCE*) description. +// _FROMMEMORY is paired with a (D3DXF_FILELOADMEMORY*) description. +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILELOADOPTIONS; + +#define D3DXF_FILELOAD_FROMFILE 0x00L +#define D3DXF_FILELOAD_FROMWFILE 0x01L +#define D3DXF_FILELOAD_FROMRESOURCE 0x02L +#define D3DXF_FILELOAD_FROMMEMORY 0x03L + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADRESOURCE: +//---------------------------------------------------------------------------- + +typedef struct _D3DXF_FILELOADRESOURCE +{ + HMODULE hModule; // Desc + LPCSTR lpName; // Desc + LPCSTR lpType; // Desc +} D3DXF_FILELOADRESOURCE; + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADMEMORY: +//---------------------------------------------------------------------------- + +typedef struct _D3DXF_FILELOADMEMORY +{ + LPCVOID lpMemory; // Desc + SIZE_T dSize; // Desc +} D3DXF_FILELOADMEMORY; + +#if defined( _WIN32 ) && !defined( _NO_COM ) + +// {cef08cf9-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFile, +0xcef08cf9, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfa-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileSaveObject, +0xcef08cfa, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfb-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileSaveData, +0xcef08cfb, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfc-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileEnumObject, +0xcef08cfc, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfd-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileData, +0xcef08cfd, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +#endif // defined( _WIN32 ) && !defined( _NO_COM ) + +#if defined( __cplusplus ) +#if !defined( DECLSPEC_UUID ) +#if _MSC_VER >= 1100 +#define DECLSPEC_UUID( x ) __declspec( uuid( x ) ) +#else // !( _MSC_VER >= 1100 ) +#define DECLSPEC_UUID( x ) +#endif // !( _MSC_VER >= 1100 ) +#endif // !defined( DECLSPEC_UUID ) + +interface DECLSPEC_UUID( "cef08cf9-7b4f-4429-9624-2a690a933201" ) + ID3DXFile; +interface DECLSPEC_UUID( "cef08cfa-7b4f-4429-9624-2a690a933201" ) + ID3DXFileSaveObject; +interface DECLSPEC_UUID( "cef08cfb-7b4f-4429-9624-2a690a933201" ) + ID3DXFileSaveData; +interface DECLSPEC_UUID( "cef08cfc-7b4f-4429-9624-2a690a933201" ) + ID3DXFileEnumObject; +interface DECLSPEC_UUID( "cef08cfd-7b4f-4429-9624-2a690a933201" ) + ID3DXFileData; + +#if defined( _COM_SMARTPTR_TYPEDEF ) +_COM_SMARTPTR_TYPEDEF( ID3DXFile, + __uuidof( ID3DXFile ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileSaveObject, + __uuidof( ID3DXFileSaveObject ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileSaveData, + __uuidof( ID3DXFileSaveData ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileEnumObject, + __uuidof( ID3DXFileEnumObject ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileData, + __uuidof( ID3DXFileData ) ); +#endif // defined( _COM_SMARTPTR_TYPEDEF ) +#endif // defined( __cplusplus ) + +typedef interface ID3DXFile ID3DXFile; +typedef interface ID3DXFileSaveObject ID3DXFileSaveObject; +typedef interface ID3DXFileSaveData ID3DXFileSaveData; +typedef interface ID3DXFileEnumObject ID3DXFileEnumObject; +typedef interface ID3DXFileData ID3DXFileData; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFile ///////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFile + +DECLARE_INTERFACE_( ID3DXFile, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( CreateEnumObject )( THIS_ LPCVOID, D3DXF_FILELOADOPTIONS, + ID3DXFileEnumObject** ) PURE; + STDMETHOD( CreateSaveObject )( THIS_ LPCVOID, D3DXF_FILESAVEOPTIONS, + D3DXF_FILEFORMAT, ID3DXFileSaveObject** ) PURE; + STDMETHOD( RegisterTemplates )( THIS_ LPCVOID, SIZE_T ) PURE; + STDMETHOD( RegisterEnumTemplates )( THIS_ ID3DXFileEnumObject* ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileSaveObject /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileSaveObject + +DECLARE_INTERFACE_( ID3DXFileSaveObject, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetFile )( THIS_ ID3DXFile** ) PURE; + STDMETHOD( AddDataObject )( THIS_ REFGUID, LPCSTR, CONST GUID*, + SIZE_T, LPCVOID, ID3DXFileSaveData** ) PURE; + STDMETHOD( Save )( THIS ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileSaveData ///////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileSaveData + +DECLARE_INTERFACE_( ID3DXFileSaveData, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetSave )( THIS_ ID3DXFileSaveObject** ) PURE; + STDMETHOD( GetName )( THIS_ LPSTR, SIZE_T* ) PURE; + STDMETHOD( GetId )( THIS_ LPGUID ) PURE; + STDMETHOD( GetType )( THIS_ GUID* ) PURE; + STDMETHOD( AddDataObject )( THIS_ REFGUID, LPCSTR, CONST GUID*, + SIZE_T, LPCVOID, ID3DXFileSaveData** ) PURE; + STDMETHOD( AddDataReference )( THIS_ LPCSTR, CONST GUID* ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileEnumObject /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileEnumObject + +DECLARE_INTERFACE_( ID3DXFileEnumObject, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetFile )( THIS_ ID3DXFile** ) PURE; + STDMETHOD( GetChildren )( THIS_ SIZE_T* ) PURE; + STDMETHOD( GetChild )( THIS_ SIZE_T, ID3DXFileData** ) PURE; + STDMETHOD( GetDataObjectById )( THIS_ REFGUID, ID3DXFileData** ) PURE; + STDMETHOD( GetDataObjectByName )( THIS_ LPCSTR, ID3DXFileData** ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileData ///////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileData + +DECLARE_INTERFACE_( ID3DXFileData, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetEnum )( THIS_ ID3DXFileEnumObject** ) PURE; + STDMETHOD( GetName )( THIS_ LPSTR, SIZE_T* ) PURE; + STDMETHOD( GetId )( THIS_ LPGUID ) PURE; + STDMETHOD( Lock )( THIS_ SIZE_T*, LPCVOID* ) PURE; + STDMETHOD( Unlock )( THIS ) PURE; + STDMETHOD( GetType )( THIS_ GUID* ) PURE; + STDMETHOD_( BOOL, IsReference )( THIS ) PURE; + STDMETHOD( GetChildren )( THIS_ SIZE_T* ) PURE; + STDMETHOD( GetChild )( THIS_ SIZE_T, ID3DXFileData** ) PURE; +}; + +STDAPI D3DXFileCreate( ID3DXFile** lplpDirectXFile ); + +/* + * DirectX File errors. + */ + +#define _FACD3DXF 0x876 + +#define D3DXFERR_BADOBJECT MAKE_HRESULT( 1, _FACD3DXF, 900 ) +#define D3DXFERR_BADVALUE MAKE_HRESULT( 1, _FACD3DXF, 901 ) +#define D3DXFERR_BADTYPE MAKE_HRESULT( 1, _FACD3DXF, 902 ) +#define D3DXFERR_NOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 903 ) +#define D3DXFERR_NOTDONEYET MAKE_HRESULT( 1, _FACD3DXF, 904 ) +#define D3DXFERR_FILENOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 905 ) +#define D3DXFERR_RESOURCENOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 906 ) +#define D3DXFERR_BADRESOURCE MAKE_HRESULT( 1, _FACD3DXF, 907 ) +#define D3DXFERR_BADFILETYPE MAKE_HRESULT( 1, _FACD3DXF, 908 ) +#define D3DXFERR_BADFILEVERSION MAKE_HRESULT( 1, _FACD3DXF, 909 ) +#define D3DXFERR_BADFILEFLOATSIZE MAKE_HRESULT( 1, _FACD3DXF, 910 ) +#define D3DXFERR_BADFILE MAKE_HRESULT( 1, _FACD3DXF, 911 ) +#define D3DXFERR_PARSEERROR MAKE_HRESULT( 1, _FACD3DXF, 912 ) +#define D3DXFERR_BADARRAYSIZE MAKE_HRESULT( 1, _FACD3DXF, 913 ) +#define D3DXFERR_BADDATAREFERENCE MAKE_HRESULT( 1, _FACD3DXF, 914 ) +#define D3DXFERR_NOMOREOBJECTS MAKE_HRESULT( 1, _FACD3DXF, 915 ) +#define D3DXFERR_NOMOREDATA MAKE_HRESULT( 1, _FACD3DXF, 916 ) +#define D3DXFERR_BADCACHEFILE MAKE_HRESULT( 1, _FACD3DXF, 917 ) + +/* + * DirectX File object types. + */ + +#ifndef WIN_TYPES +#define WIN_TYPES(itype, ptype) typedef interface itype *LP##ptype, **LPLP##ptype +#endif + +WIN_TYPES(ID3DXFile, D3DXFILE); +WIN_TYPES(ID3DXFileEnumObject, D3DXFILEENUMOBJECT); +WIN_TYPES(ID3DXFileSaveObject, D3DXFILESAVEOBJECT); +WIN_TYPES(ID3DXFileData, D3DXFILEDATA); +WIN_TYPES(ID3DXFileSaveData, D3DXFILESAVEDATA); + +#if defined( __cplusplus ) +} // extern "C" +#endif // defined( __cplusplus ) + +#endif // !defined( __D3DX9XOF_H__ ) + + diff --git a/src/depend/mingw/include/mingw_win32.h b/src/depend/mingw/include/mingw_win32.h new file mode 100644 index 00000000..16d0aadc --- /dev/null +++ b/src/depend/mingw/include/mingw_win32.h @@ -0,0 +1,89 @@ +// Additions to the Cygwin/MinGW win32 headers +// ***********************************************************************************************************// +// Updated August 18, 2008 - Made adjustmens for newer versions of MinGW Win32 API definitions (CaptainCPS-X) // +// ***********************************************************************************************************// +#include + +#undef NM_FIRST +#define NM_FIRST (0U - 0U) + +#if (_WIN32_IE >= 0x0300) + #define NMLVKEYDOWN LV_KEYDOWN +#endif + +#ifndef MNS_NOCHECK +#define MNS_NOCHECK (0x80000000) +#endif + +#ifndef MNS_MODELESS +#define MNS_MODELESS (0x40000000) +#endif + +#ifndef MNS_DRAGDROP +#define MNS_DRAGDROP (0x20000000) +#endif + +#ifndef MNS_AUTODISMISS +#define MNS_AUTODISMISS (0x10000000) +#endif + +#ifndef MNS_NOTIFYBYPOS +#define MNS_NOTIFYBYPOS (0x08000000) +#endif + +#ifndef MNS_CHECKORBMP +#define MNS_CHECKORBMP (0x04000000) +#endif + +//#define MIM_MAXHEIGHT (0x00000001) +//#define MIM_BACKGROUND (0x00000002) +//#define MIM_HELPID (0x00000004) +//#define MIM_MENUDATA (0x00000008) +//#define MIM_STYLE (0x00000010) +//#define MIM_APPLYTOSUBMENUS (0x80000000) + +#ifndef WM_UNINITMENUPOPUP +#define WM_UNINITMENUPOPUP (0x0125) +#endif + +#define ENM_SCROLLEVENTS (8) + +// Rich edit +#define ST_DEFAULT (0) +#define ST_KEEPUNDO (1) +#define ST_SELECTION (2) + +#if __W32API_MAJOR_VERSION >=3 && __W32API_MINOR_VERSION < 8 +typedef struct _settextex +{ + DWORD flags; + UINT codepage; +} SETTEXTEX; +#endif + +// Macro used for handling Window Messages +#if not defined HANDLE_WM_DISPLAYCHANGE + #define HANDLE_WM_DISPLAYCHANGE(hwnd, wParam, lParam, fn) ((fn)((hwnd), (UINT)(wParam), (UINT)LOWORD(lParam), (UINT)HIWORD(wParam)), 0L) +#endif + +#if _WIN32_WINNT < 0x0500 + #define VK_OEM_PLUS 0xBB + #define VK_OEM_COMMA 0xBC + #define VK_OEM_MINUS 0xBD + #define VK_OEM_PERIOD 0xBE +#endif + +#ifndef LVM_SORTITEMSEX +#define LVM_SORTITEMSEX (LVM_FIRST + 81) +#endif + +#ifndef ListView_SortItemsEx +#define ListView_SortItemsEx(hwndLV, _pfnCompare, _lPrm) \ + (BOOL)SNDMSG((hwndLV), LVM_SORTITEMSEX, (WPARAM)(LPARAM)(_lPrm), (LPARAM)(PFNLVCOMPARE)(_pfnCompare)) +#endif + +// prevent some warnings on some header defines (warning: right-hand operand of comma has no effect) +#undef HANDLE_WM_PAINT +#define HANDLE_WM_PAINT(hwnd,wParam,lParam,fn) ((fn)(hwnd)) +#undef HANDLE_WM_INITMENUPOPUP +#define HANDLE_WM_INITMENUPOPUP(hwnd,wParam,lParam,fn) ((fn)((hwnd),(HMENU)(wParam),(UINT)LOWORD(lParam),(BOOL)HIWORD(lParam))) diff --git a/src/depend/mingw/include/xaudio2/audiodefs.h b/src/depend/mingw/include/xaudio2/audiodefs.h new file mode 100644 index 00000000..ff995ecc --- /dev/null +++ b/src/depend/mingw/include/xaudio2/audiodefs.h @@ -0,0 +1,263 @@ +/*************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: audiodefs.h + * Content: Basic constants and data types for audio work. + * + * Remarks: This header file defines all of the audio format constants and + * structures required for XAudio2 and XACT work. Providing these + * in a single location avoids certain dependency problems in the + * legacy audio headers (mmreg.h, mmsystem.h, ksmedia.h). + * + * NOTE: Including the legacy headers after this one may cause a + * compilation error, because they define some of the same types + * defined here without preprocessor guards to avoid multiple + * definitions. If a source file needs one of the old headers, + * it must include it before including audiodefs.h. + * + ***************************************************************************/ + +#ifndef __AUDIODEFS_INCLUDED__ +#define __AUDIODEFS_INCLUDED__ + +#include // For WORD, DWORD, etc. + +#pragma pack(push, 1) // Pack structures to 1-byte boundaries + + +/************************************************************************** + * + * WAVEFORMATEX: Base structure for many audio formats. Format-specific + * extensions can be defined for particular formats by using a non-zero + * cbSize value and adding extra fields to the end of this structure. + * + ***************************************************************************/ + +#ifndef _WAVEFORMATEX_ + + #define _WAVEFORMATEX_ + typedef struct tWAVEFORMATEX + { + WORD wFormatTag; // Integer identifier of the format + WORD nChannels; // Number of audio channels + DWORD nSamplesPerSec; // Audio sample rate + DWORD nAvgBytesPerSec; // Bytes per second (possibly approximate) + WORD nBlockAlign; // Size in bytes of a sample block (all channels) + WORD wBitsPerSample; // Size in bits of a single per-channel sample + WORD cbSize; // Bytes of extra data appended to this struct + } WAVEFORMATEX; + +#endif + +// Defining pointer types outside of the #if block to make sure they are +// defined even if mmreg.h or mmsystem.h is #included before this file + +typedef WAVEFORMATEX *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX; +typedef const WAVEFORMATEX *PCWAVEFORMATEX, *LPCWAVEFORMATEX; + + +/************************************************************************** + * + * WAVEFORMATEXTENSIBLE: Extended version of WAVEFORMATEX that should be + * used as a basis for all new audio formats. The format tag is replaced + * with a GUID, allowing new formats to be defined without registering a + * format tag with Microsoft. There are also new fields that can be used + * to specify the spatial positions for each channel and the bit packing + * used for wide samples (e.g. 24-bit PCM samples in 32-bit containers). + * + ***************************************************************************/ + +#ifndef _WAVEFORMATEXTENSIBLE_ + + #define _WAVEFORMATEXTENSIBLE_ + typedef struct + { + WAVEFORMATEX Format; // Base WAVEFORMATEX data + union + { + WORD wValidBitsPerSample; // Valid bits in each sample container + WORD wSamplesPerBlock; // Samples per block of audio data; valid + // if wBitsPerSample=0 (but rarely used). + WORD wReserved; // Zero if neither case above applies. + } Samples; + DWORD dwChannelMask; // Positions of the audio channels + GUID SubFormat; // Format identifier GUID + } WAVEFORMATEXTENSIBLE; + +#endif + +typedef WAVEFORMATEXTENSIBLE *PWAVEFORMATEXTENSIBLE, *LPWAVEFORMATEXTENSIBLE; +typedef const WAVEFORMATEXTENSIBLE *PCWAVEFORMATEXTENSIBLE, *LPCWAVEFORMATEXTENSIBLE; + + + +/************************************************************************** + * + * Define the most common wave format tags used in WAVEFORMATEX formats. + * + ***************************************************************************/ + +#ifndef WAVE_FORMAT_PCM // Pulse Code Modulation + + // If WAVE_FORMAT_PCM is not defined, we need to define some legacy types + // for compatibility with the Windows mmreg.h / mmsystem.h header files. + + // Old general format structure (information common to all formats) + typedef struct waveformat_tag + { + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + } WAVEFORMAT, *PWAVEFORMAT, NEAR *NPWAVEFORMAT, FAR *LPWAVEFORMAT; + + // Specific format structure for PCM data + typedef struct pcmwaveformat_tag + { + WAVEFORMAT wf; + WORD wBitsPerSample; + } PCMWAVEFORMAT, *PPCMWAVEFORMAT, NEAR *NPPCMWAVEFORMAT, FAR *LPPCMWAVEFORMAT; + + #define WAVE_FORMAT_PCM 0x0001 + +#endif + +#ifndef WAVE_FORMAT_ADPCM // Microsoft Adaptive Differental PCM + + // Replicate the Microsoft ADPCM type definitions from mmreg.h. + + typedef struct adpcmcoef_tag + { + short iCoef1; + short iCoef2; + } ADPCMCOEFSET; + + #pragma warning(push) + #pragma warning(disable:4200) // Disable zero-sized array warnings + + typedef struct adpcmwaveformat_tag { + WAVEFORMATEX wfx; + WORD wSamplesPerBlock; + WORD wNumCoef; + ADPCMCOEFSET aCoef[]; // Always 7 coefficient pairs for MS ADPCM + } ADPCMWAVEFORMAT; + + #pragma warning(pop) + + #define WAVE_FORMAT_ADPCM 0x0002 + +#endif + +// Other frequently used format tags + +#ifndef WAVE_FORMAT_UNKNOWN + #define WAVE_FORMAT_UNKNOWN 0x0000 // Unknown or invalid format tag +#endif + +#ifndef WAVE_FORMAT_IEEE_FLOAT + #define WAVE_FORMAT_IEEE_FLOAT 0x0003 // 32-bit floating-point +#endif + +#ifndef WAVE_FORMAT_MPEGLAYER3 + #define WAVE_FORMAT_MPEGLAYER3 0x0055 // ISO/MPEG Layer3 +#endif + +#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF + #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 // Dolby Audio Codec 3 over S/PDIF +#endif + +#ifndef WAVE_FORMAT_WMAUDIO2 + #define WAVE_FORMAT_WMAUDIO2 0x0161 // Windows Media Audio +#endif + +#ifndef WAVE_FORMAT_WMAUDIO3 + #define WAVE_FORMAT_WMAUDIO3 0x0162 // Windows Media Audio Pro +#endif + +#ifndef WAVE_FORMAT_WMASPDIF + #define WAVE_FORMAT_WMASPDIF 0x0164 // Windows Media Audio over S/PDIF +#endif + +#ifndef WAVE_FORMAT_EXTENSIBLE + #define WAVE_FORMAT_EXTENSIBLE 0xFFFE // All WAVEFORMATEXTENSIBLE formats +#endif + + +/************************************************************************** + * + * Define the most common wave format GUIDs used in WAVEFORMATEXTENSIBLE + * formats. Note that including the Windows ksmedia.h header after this + * one will cause build problems; this cannot be avoided, since ksmedia.h + * defines these macros without preprocessor guards. + * + ***************************************************************************/ + +#ifdef __cplusplus // uuid() and __uuidof() are only available in C++ + + #ifndef KSDATAFORMAT_SUBTYPE_PCM + struct __declspec(uuid("00000001-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_PCM_STRUCT; + #define KSDATAFORMAT_SUBTYPE_PCM __uuidof(KSDATAFORMAT_SUBTYPE_PCM_STRUCT) + #endif + + #ifndef KSDATAFORMAT_SUBTYPE_ADPCM + struct __declspec(uuid("00000002-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT; + #define KSDATAFORMAT_SUBTYPE_ADPCM __uuidof(KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT) + #endif + + #ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT + struct __declspec(uuid("00000003-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT; + #define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT __uuidof(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT) + #endif + +#endif + + +/************************************************************************** + * + * Speaker positions used in the WAVEFORMATEXTENSIBLE dwChannelMask field. + * + ***************************************************************************/ + +#ifndef SPEAKER_FRONT_LEFT + #define SPEAKER_FRONT_LEFT 0x00000001 + #define SPEAKER_FRONT_RIGHT 0x00000002 + #define SPEAKER_FRONT_CENTER 0x00000004 + #define SPEAKER_LOW_FREQUENCY 0x00000008 + #define SPEAKER_BACK_LEFT 0x00000010 + #define SPEAKER_BACK_RIGHT 0x00000020 + #define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040 + #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080 + #define SPEAKER_BACK_CENTER 0x00000100 + #define SPEAKER_SIDE_LEFT 0x00000200 + #define SPEAKER_SIDE_RIGHT 0x00000400 + #define SPEAKER_TOP_CENTER 0x00000800 + #define SPEAKER_TOP_FRONT_LEFT 0x00001000 + #define SPEAKER_TOP_FRONT_CENTER 0x00002000 + #define SPEAKER_TOP_FRONT_RIGHT 0x00004000 + #define SPEAKER_TOP_BACK_LEFT 0x00008000 + #define SPEAKER_TOP_BACK_CENTER 0x00010000 + #define SPEAKER_TOP_BACK_RIGHT 0x00020000 + #define SPEAKER_RESERVED 0x7FFC0000 + #define SPEAKER_ALL 0x80000000 + #define _SPEAKER_POSITIONS_ +#endif + +#ifndef SPEAKER_STEREO + #define SPEAKER_MONO (SPEAKER_FRONT_CENTER) + #define SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) + #define SPEAKER_2POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY) + #define SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) + #define SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_4POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) + #define SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) + #define SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) + #define SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) +#endif + + +#pragma pack(pop) + +#endif // #ifndef __AUDIODEFS_INCLUDED__ diff --git a/src/depend/mingw/include/xaudio2/sal.h b/src/depend/mingw/include/xaudio2/sal.h new file mode 100644 index 00000000..3f99ab9a --- /dev/null +++ b/src/depend/mingw/include/xaudio2/sal.h @@ -0,0 +1,252 @@ +#pragma once + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +/*#define __null*/ // << Conflicts with GCC internal type __null +#define __notnull +#define __maybenull +#define __readonly +#define __notreadonly +#define __maybereadonly +#define __valid +#define __notvalid +#define __maybevalid +#define __readableTo(extent) +#define __elem_readableTo(size) +#define __byte_readableTo(size) +#define __writableTo(size) +#define __elem_writableTo(size) +#define __byte_writableTo(size) +#define __deref +#define __pre +#define __post +#define __precond(expr) +#define __postcond(expr) +#define __exceptthat +#define __execeptthat +#define __inner_success(expr) +#define __inner_checkReturn +#define __inner_typefix(ctype) +#define __inner_override +#define __inner_callback +#define __inner_blocksOn(resource) +#define __inner_fallthrough_dec +#define __inner_fallthrough +#define __refparam +#define __inner_control_entrypoint(category) +#define __inner_data_entrypoint(category) + +#define __ecount(size) +#define __bcount(size) +#define __in +#define __in_ecount(size) +#define __in_bcount(size) +#define __in_z +#define __in_ecount_z(size) +#define __in_bcount_z(size) +#define __in_nz +#define __in_ecount_nz(size) +#define __in_bcount_nz(size) +#define __out +#define __out_ecount(size) +#define __out_bcount(size) +#define __out_ecount_part(size,length) +#define __out_bcount_part(size,length) +#define __out_ecount_full(size) +#define __out_bcount_full(size) +#define __out_z +#define __out_z_opt +#define __out_ecount_z(size) +#define __out_bcount_z(size) +#define __out_ecount_part_z(size,length) +#define __out_bcount_part_z(size,length) +#define __out_ecount_full_z(size) +#define __out_bcount_full_z(size) +#define __out_nz +#define __out_nz_opt +#define __out_ecount_nz(size) +#define __out_bcount_nz(size) +#define __inout +#define __inout_ecount(size) +#define __inout_bcount(size) +#define __inout_ecount_part(size,length) +#define __inout_bcount_part(size,length) +#define __inout_ecount_full(size) +#define __inout_bcount_full(size) +#define __inout_z +#define __inout_ecount_z(size) +#define __inout_bcount_z(size) +#define __inout_nz +#define __inout_ecount_nz(size) +#define __inout_bcount_nz(size) +#define __ecount_opt(size) +#define __bcount_opt(size) +#define __in_opt +#define __in_ecount_opt(size) +#define __in_bcount_opt(size) +#define __in_z_opt +#define __in_ecount_z_opt(size) +#define __in_bcount_z_opt(size) +#define __in_nz_opt +#define __in_ecount_nz_opt(size) +#define __in_bcount_nz_opt(size) +#define __out_opt +#define __out_ecount_opt(size) +#define __out_bcount_opt(size) +#define __out_ecount_part_opt(size,length) +#define __out_bcount_part_opt(size,length) +#define __out_ecount_full_opt(size) +#define __out_bcount_full_opt(size) +#define __out_ecount_z_opt(size) +#define __out_bcount_z_opt(size) +#define __out_ecount_part_z_opt(size,length) +#define __out_bcount_part_z_opt(size,length) +#define __out_ecount_full_z_opt(size) +#define __out_bcount_full_z_opt(size) +#define __out_ecount_nz_opt(size) +#define __out_bcount_nz_opt(size) +#define __inout_opt +#define __inout_ecount_opt(size) +#define __inout_bcount_opt(size) +#define __inout_ecount_part_opt(size,length) +#define __inout_bcount_part_opt(size,length) +#define __inout_ecount_full_opt(size) +#define __inout_bcount_full_opt(size) +#define __inout_z_opt +#define __inout_ecount_z_opt(size) +#define __inout_ecount_z_opt(size) +#define __inout_bcount_z_opt(size) +#define __inout_nz_opt +#define __inout_ecount_nz_opt(size) +#define __inout_bcount_nz_opt(size) +#define __deref_ecount(size) +#define __deref_bcount(size) +#define __deref_out +#define __deref_out_ecount(size) +#define __deref_out_bcount(size) +#define __deref_out_ecount_part(size,length) +#define __deref_out_bcount_part(size,length) +#define __deref_out_ecount_full(size) +#define __deref_out_bcount_full(size) +#define __deref_out_z +#define __deref_out_ecount_z(size) +#define __deref_out_bcount_z(size) +#define __deref_out_nz +#define __deref_out_ecount_nz(size) +#define __deref_out_bcount_nz(size) +#define __deref_inout +#define __deref_inout_z +#define __deref_inout_ecount(size) +#define __deref_inout_bcount(size) +#define __deref_inout_ecount_part(size,length) +#define __deref_inout_bcount_part(size,length) +#define __deref_inout_ecount_full(size) +#define __deref_inout_bcount_full(size) +#define __deref_inout_z +#define __deref_inout_ecount_z(size) +#define __deref_inout_bcount_z(size) +#define __deref_inout_nz +#define __deref_inout_ecount_nz(size) +#define __deref_inout_bcount_nz(size) +#define __deref_ecount_opt(size) +#define __deref_bcount_opt(size) +#define __deref_out_opt +#define __deref_out_ecount_opt(size) +#define __deref_out_bcount_opt(size) +#define __deref_out_ecount_part_opt(size,length) +#define __deref_out_bcount_part_opt(size,length) +#define __deref_out_ecount_full_opt(size) +#define __deref_out_bcount_full_opt(size) +#define __deref_out_z_opt +#define __deref_out_ecount_z_opt(size) +#define __deref_out_bcount_z_opt(size) +#define __deref_out_nz_opt +#define __deref_out_ecount_nz_opt(size) +#define __deref_out_bcount_nz_opt(size) +#define __deref_inout_opt +#define __deref_inout_ecount_opt(size) +#define __deref_inout_bcount_opt(size) +#define __deref_inout_ecount_part_opt(size,length) +#define __deref_inout_bcount_part_opt(size,length) +#define __deref_inout_ecount_full_opt(size) +#define __deref_inout_bcount_full_opt(size) +#define __deref_inout_z_opt +#define __deref_inout_ecount_z_opt(size) +#define __deref_inout_bcount_z_opt(size) +#define __deref_inout_nz_opt +#define __deref_inout_ecount_nz_opt(size) +#define __deref_inout_bcount_nz_opt(size) +#define __deref_opt_ecount(size) +#define __deref_opt_bcount(size) +#define __deref_opt_out +#define __deref_opt_out_z +#define __deref_opt_out_ecount(size) +#define __deref_opt_out_bcount(size) +#define __deref_opt_out_ecount_part(size,length) +#define __deref_opt_out_bcount_part(size,length) +#define __deref_opt_out_ecount_full(size) +#define __deref_opt_out_bcount_full(size) +#define __deref_opt_inout +#define __deref_opt_inout_ecount(size) +#define __deref_opt_inout_bcount(size) +#define __deref_opt_inout_ecount_part(size,length) +#define __deref_opt_inout_bcount_part(size,length) +#define __deref_opt_inout_ecount_full(size) +#define __deref_opt_inout_bcount_full(size) +#define __deref_opt_inout_z +#define __deref_opt_inout_ecount_z(size) +#define __deref_opt_inout_bcount_z(size) +#define __deref_opt_inout_nz +#define __deref_opt_inout_ecount_nz(size) +#define __deref_opt_inout_bcount_nz(size) +#define __deref_opt_ecount_opt(size) +#define __deref_opt_bcount_opt(size) +#define __deref_opt_out_opt +#define __deref_opt_out_ecount_opt(size) +#define __deref_opt_out_bcount_opt(size) +#define __deref_opt_out_ecount_part_opt(size,length) +#define __deref_opt_out_bcount_part_opt(size,length) +#define __deref_opt_out_ecount_full_opt(size) +#define __deref_opt_out_bcount_full_opt(size) +#define __deref_opt_out_z_opt +#define __deref_opt_out_ecount_z_opt(size) +#define __deref_opt_out_bcount_z_opt(size) +#define __deref_opt_out_nz_opt +#define __deref_opt_out_ecount_nz_opt(size) +#define __deref_opt_out_bcount_nz_opt(size) +#define __deref_opt_inout_opt +#define __deref_opt_inout_ecount_opt(size) +#define __deref_opt_inout_bcount_opt(size) +#define __deref_opt_inout_ecount_part_opt(size,length) +#define __deref_opt_inout_bcount_part_opt(size,length) +#define __deref_opt_inout_ecount_full_opt(size) +#define __deref_opt_inout_bcount_full_opt(size) +#define __deref_opt_inout_z_opt +#define __deref_opt_inout_ecount_z_opt(size) +#define __deref_opt_inout_bcount_z_opt(size) +#define __deref_opt_inout_nz_opt +#define __deref_opt_inout_ecount_nz_opt(size) +#define __deref_opt_inout_bcount_nz_opt(size) + +#define __success(expr) +#define __nullterminated +#define __nullnullterminated +#define __reserved +#define __checkReturn +#define __typefix(ctype) +#define __override +#define __callback +#define __format_string +#define __blocksOn(resource) +#define __control_entrypoint(category) +#define __data_entrypoint(category) + +#ifndef __fallthrough + #define __fallthrough __inner_fallthrough +#endif + +#ifndef __analysis_assume + #define __analysis_assume(expr) +#endif diff --git a/src/depend/mingw/include/xaudio2/xaudio2.h b/src/depend/mingw/include/xaudio2/xaudio2.h new file mode 100644 index 00000000..ca5df8cb --- /dev/null +++ b/src/depend/mingw/include/xaudio2/xaudio2.h @@ -0,0 +1,1290 @@ +/*------------------------------------------------------------------------- + Moddified by CaptainCPS for use with MinGW / GCC 4.6.1 + + Thanks to PortAudio for their 'sal.h' compatible with MinGW ! +-------------------------------------------------------------------------*/ + +/************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: xaudio2.h + * Content: Declarations for the XAudio2 game audio API. + * + **************************************************************************/ + +#ifndef __XAUDIO2_INCLUDED__ +#define __XAUDIO2_INCLUDED__ + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +/************************************************************************** + * + * XAudio2 COM object class and interface IDs. + * + **************************************************************************/ + +//#include // For DEFINE_CLSID and DEFINE_IID + +// XAudio 2.0 (March 2008 SDK) +//DEFINE_CLSID(XAudio2, fac23f48, 31f5, 45a8, b4, 9b, 52, 25, d6, 14, 01, aa); +//DEFINE_CLSID(XAudio2_Debug, fac23f48, 31f5, 45a8, b4, 9b, 52, 25, d6, 14, 01, db); + +// XAudio 2.1 (June 2008 SDK) +//DEFINE_CLSID(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08); +//DEFINE_CLSID(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd); + +// XAudio 2.2 (August 2008 SDK) +//DEFINE_CLSID(XAudio2, b802058a, 464a, 42db, bc, 10, b6, 50, d6, f2, 58, 6a); +//DEFINE_CLSID(XAudio2_Debug, 97dfb7e7, 5161, 4015, 87, a9, c7, 9e, 6a, 19, 52, cc); + +// XAudio 2.3 (November 2008 SDK) +//DEFINE_CLSID(XAudio2, 4c5e637a, 16c7, 4de3, 9c, 46, 5e, d2, 21, 81, 96, 2d); +//DEFINE_CLSID(XAudio2_Debug, ef0aa05d, 8075, 4e5d, be, ad, 45, be, 0c, 3c, cb, b3); + +// XAudio 2.4 (March 2009 SDK) +//DEFINE_CLSID(XAudio2, 03219e78, 5bc3, 44d1, b9, 2e, f6, 3d, 89, cc, 65, 26); +//DEFINE_CLSID(XAudio2_Debug, 4256535c, 1ea4, 4d4b, 8a, d5, f9, db, 76, 2e, ca, 9e); + +// XAudio 2.5 (August 2009 SDK) +//DEFINE_CLSID(XAudio2, 4c9b6dde, 6809, 46e6, a2, 78, 9b, 6a, 97, 58, 86, 70); +//DEFINE_CLSID(XAudio2_Debug, 715bdd1a, aa82, 436b, b0, fa, 6a, ce, a3, 9b, d0, a1); + +// XAudio 2.6 (February 2010 SDK) +//DEFINE_CLSID(XAudio2, 3eda9b49, 2085, 498b, 9b, b2, 39, a6, 77, 84, 93, de); +//DEFINE_CLSID(XAudio2_Debug, 47199894, 7cc2, 444d, 98, 73, ce, d2, 56, 2c, c6, 0e); + +// XAudio 2.7 (June 2010 SDK) +DEFINE_GUID(CLSID_XAudio2, 0x5a508685, 0xa254, 0x4fba, 0x9b, 0x82, 0x9a, 0x24, 0xb0, 0x03, 0x06, 0xaf); +DEFINE_GUID(CLSID_XAudio2_Debug, 0xdb05ea35, 0x0329, 0x4d4b, 0xa5, 0x3a, 0x6d, 0xea, 0xd0, 0x3d, 0x38, 0x52); +DEFINE_GUID(IID_IXAudio2, 0x8bcf1f58, 0x9fe7, 0x4583, 0x8a, 0xc6, 0xe2, 0xad, 0xc4, 0x65, 0xc8, 0xbb); + +// Ignore the rest of this header if only the GUID definitions were requested +#ifndef GUID_DEFS_ONLY + +#ifdef _XBOX + #include // Xbox COM declarations (IUnknown, etc) +#else + #include // Windows COM declarations +#endif + +#include // Markers for documenting API semantics +#include // Basic audio data types and constants +#include // Data types and constants for XMA2 audio + +// All structures defined in this file use tight field packing +#pragma pack(push, 1) + + +/************************************************************************** + * + * XAudio2 constants, flags and error codes. + * + **************************************************************************/ + +// Numeric boundary values +#define XAUDIO2_MAX_BUFFER_BYTES 0x80000000 // Maximum bytes allowed in a source buffer +#define XAUDIO2_MAX_QUEUED_BUFFERS 64 // Maximum buffers allowed in a voice queue +#define XAUDIO2_MAX_BUFFERS_SYSTEM 2 // Maximum buffers allowed for system threads (Xbox 360 only) +#define XAUDIO2_MAX_AUDIO_CHANNELS 64 // Maximum channels in an audio stream +#define XAUDIO2_MIN_SAMPLE_RATE 1000 // Minimum audio sample rate supported +#define XAUDIO2_MAX_SAMPLE_RATE 200000 // Maximum audio sample rate supported +#define XAUDIO2_MAX_VOLUME_LEVEL 16777216.0f // Maximum acceptable volume level (2^24) +#define XAUDIO2_MIN_FREQ_RATIO (1/1024.0f) // Minimum SetFrequencyRatio argument +#define XAUDIO2_MAX_FREQ_RATIO 1024.0f // Maximum MaxFrequencyRatio argument +#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f // Default MaxFrequencyRatio argument +#define XAUDIO2_MAX_FILTER_ONEOVERQ 1.5f // Maximum XAUDIO2_FILTER_PARAMETERS.OneOverQ +#define XAUDIO2_MAX_FILTER_FREQUENCY 1.0f // Maximum XAUDIO2_FILTER_PARAMETERS.Frequency +#define XAUDIO2_MAX_LOOP_COUNT 254 // Maximum non-infinite XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_MAX_INSTANCES 8 // Maximum simultaneous XAudio2 objects on Xbox 360 + +// For XMA voices on Xbox 360 there is an additional restriction on the MaxFrequencyRatio +// argument and the voice's sample rate: the product of these numbers cannot exceed 600000 +// for one-channel voices or 300000 for voices with more than one channel. +#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MONO 600000 +#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL 300000 + +// Numeric values with special meanings +#define XAUDIO2_COMMIT_NOW 0 // Used as an OperationSet argument +#define XAUDIO2_COMMIT_ALL 0 // Used in IXAudio2::CommitChanges +#define XAUDIO2_INVALID_OPSET (UINT32)(-1) // Not allowed for OperationSet arguments +#define XAUDIO2_NO_LOOP_REGION 0 // Used in XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_LOOP_INFINITE 255 // Used in XAUDIO2_BUFFER.LoopCount +#define XAUDIO2_DEFAULT_CHANNELS 0 // Used in CreateMasteringVoice +#define XAUDIO2_DEFAULT_SAMPLERATE 0 // Used in CreateMasteringVoice + +// Flags +#define XAUDIO2_DEBUG_ENGINE 0x0001 // Used in XAudio2Create on Windows only +#define XAUDIO2_VOICE_NOPITCH 0x0002 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_VOICE_NOSRC 0x0004 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_VOICE_USEFILTER 0x0008 // Used in IXAudio2::CreateSource/SubmixVoice +#define XAUDIO2_VOICE_MUSIC 0x0010 // Used in IXAudio2::CreateSourceVoice +#define XAUDIO2_PLAY_TAILS 0x0020 // Used in IXAudio2SourceVoice::Stop +#define XAUDIO2_END_OF_STREAM 0x0040 // Used in XAUDIO2_BUFFER.Flags +#define XAUDIO2_SEND_USEFILTER 0x0080 // Used in XAUDIO2_SEND_DESCRIPTOR.Flags + +// Default parameters for the built-in filter +#define XAUDIO2_DEFAULT_FILTER_TYPE LowPassFilter +#define XAUDIO2_DEFAULT_FILTER_FREQUENCY XAUDIO2_MAX_FILTER_FREQUENCY +#define XAUDIO2_DEFAULT_FILTER_ONEOVERQ 1.0f + +// Internal XAudio2 constants +#ifdef _XBOX + #define XAUDIO2_QUANTUM_NUMERATOR 2 // On Xbox 360, XAudio2 processes audio + #define XAUDIO2_QUANTUM_DENOMINATOR 375 // in 5.333ms chunks (= 2/375 seconds) +#else + #define XAUDIO2_QUANTUM_NUMERATOR 1 // On Windows, XAudio2 processes audio + #define XAUDIO2_QUANTUM_DENOMINATOR 100 // in 10ms chunks (= 1/100 seconds) +#endif +#define XAUDIO2_QUANTUM_MS (1000.0f * XAUDIO2_QUANTUM_NUMERATOR / XAUDIO2_QUANTUM_DENOMINATOR) + +// XAudio2 error codes +#define FACILITY_XAUDIO2 0x896 +#define XAUDIO2_E_INVALID_CALL 0x88960001 // An API call or one of its arguments was illegal +#define XAUDIO2_E_XMA_DECODER_ERROR 0x88960002 // The XMA hardware suffered an unrecoverable error +#define XAUDIO2_E_XAPO_CREATION_FAILED 0x88960003 // XAudio2 failed to initialize an XAPO effect +#define XAUDIO2_E_DEVICE_INVALIDATED 0x88960004 // An audio device became unusable (unplugged, etc) + + +/************************************************************************** + * + * Forward declarations for the XAudio2 interfaces. + * + **************************************************************************/ + +#ifdef __cplusplus + #define FWD_DECLARE(x) interface x +#else + #define FWD_DECLARE(x) typedef interface x x +#endif + +FWD_DECLARE(IXAudio2); +FWD_DECLARE(IXAudio2Voice); +FWD_DECLARE(IXAudio2SourceVoice); +FWD_DECLARE(IXAudio2SubmixVoice); +FWD_DECLARE(IXAudio2MasteringVoice); +FWD_DECLARE(IXAudio2EngineCallback); +FWD_DECLARE(IXAudio2VoiceCallback); + + +/************************************************************************** + * + * XAudio2 structures and enumerations. + * + **************************************************************************/ + +// Used in IXAudio2::Initialize +#ifdef _XBOX + typedef enum XAUDIO2_XBOX_HWTHREAD_SPECIFIER + { + XboxThread0 = 0x01, + XboxThread1 = 0x02, + XboxThread2 = 0x04, + XboxThread3 = 0x08, + XboxThread4 = 0x10, + XboxThread5 = 0x20, + XAUDIO2_ANY_PROCESSOR = XboxThread4, + XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR + } XAUDIO2_XBOX_HWTHREAD_SPECIFIER, XAUDIO2_PROCESSOR; +#else + typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER + { + Processor1 = 0x00000001, + Processor2 = 0x00000002, + Processor3 = 0x00000004, + Processor4 = 0x00000008, + Processor5 = 0x00000010, + Processor6 = 0x00000020, + Processor7 = 0x00000040, + Processor8 = 0x00000080, + Processor9 = 0x00000100, + Processor10 = 0x00000200, + Processor11 = 0x00000400, + Processor12 = 0x00000800, + Processor13 = 0x00001000, + Processor14 = 0x00002000, + Processor15 = 0x00004000, + Processor16 = 0x00008000, + Processor17 = 0x00010000, + Processor18 = 0x00020000, + Processor19 = 0x00040000, + Processor20 = 0x00080000, + Processor21 = 0x00100000, + Processor22 = 0x00200000, + Processor23 = 0x00400000, + Processor24 = 0x00800000, + Processor25 = 0x01000000, + Processor26 = 0x02000000, + Processor27 = 0x04000000, + Processor28 = 0x08000000, + Processor29 = 0x10000000, + Processor30 = 0x20000000, + Processor31 = 0x40000000, + Processor32 = 0x80000000, + XAUDIO2_ANY_PROCESSOR = 0xffffffff, + XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR + } XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR; +#endif + +// Used in XAUDIO2_DEVICE_DETAILS below to describe the types of applications +// that the user has specified each device as a default for. 0 means that the +// device isn't the default for any role. +typedef enum XAUDIO2_DEVICE_ROLE +{ + NotDefaultDevice = 0x0, + DefaultConsoleDevice = 0x1, + DefaultMultimediaDevice = 0x2, + DefaultCommunicationsDevice = 0x4, + DefaultGameDevice = 0x8, + GlobalDefaultDevice = 0xf, + InvalidDeviceRole = ~GlobalDefaultDevice +} XAUDIO2_DEVICE_ROLE; + +// Returned by IXAudio2::GetDeviceDetails +typedef struct XAUDIO2_DEVICE_DETAILS +{ + WCHAR DeviceID[256]; // String identifier for the audio device. + WCHAR DisplayName[256]; // Friendly name suitable for display to a human. + XAUDIO2_DEVICE_ROLE Role; // Roles that the device should be used for. + WAVEFORMATEXTENSIBLE OutputFormat; // The device's native PCM audio output format. +} XAUDIO2_DEVICE_DETAILS; + +// Returned by IXAudio2Voice::GetVoiceDetails +typedef struct XAUDIO2_VOICE_DETAILS +{ + UINT32 CreationFlags; // Flags the voice was created with. + UINT32 InputChannels; // Channels in the voice's input audio. + UINT32 InputSampleRate; // Sample rate of the voice's input audio. +} XAUDIO2_VOICE_DETAILS; + +// Used in XAUDIO2_VOICE_SENDS below +typedef struct XAUDIO2_SEND_DESCRIPTOR +{ + UINT32 Flags; // Either 0 or XAUDIO2_SEND_USEFILTER. + IXAudio2Voice* pOutputVoice; // This send's destination voice. +} XAUDIO2_SEND_DESCRIPTOR; + +// Used in the voice creation functions and in IXAudio2Voice::SetOutputVoices +typedef struct XAUDIO2_VOICE_SENDS +{ + UINT32 SendCount; // Number of sends from this voice. + XAUDIO2_SEND_DESCRIPTOR* pSends; // Array of SendCount send descriptors. +} XAUDIO2_VOICE_SENDS; + +// Used in XAUDIO2_EFFECT_CHAIN below +typedef struct XAUDIO2_EFFECT_DESCRIPTOR +{ + IUnknown* pEffect; // Pointer to the effect object's IUnknown interface. + BOOL InitialState; // TRUE if the effect should begin in the enabled state. + UINT32 OutputChannels; // How many output channels the effect should produce. +} XAUDIO2_EFFECT_DESCRIPTOR; + +// Used in the voice creation functions and in IXAudio2Voice::SetEffectChain +typedef struct XAUDIO2_EFFECT_CHAIN +{ + UINT32 EffectCount; // Number of effects in this voice's effect chain. + XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors; // Array of effect descriptors. +} XAUDIO2_EFFECT_CHAIN; + +// Used in XAUDIO2_FILTER_PARAMETERS below +typedef enum XAUDIO2_FILTER_TYPE +{ + LowPassFilter, // Attenuates frequencies above the cutoff frequency. + BandPassFilter, // Attenuates frequencies outside a given range. + HighPassFilter, // Attenuates frequencies below the cutoff frequency. + NotchFilter // Attenuates frequencies inside a given range. +} XAUDIO2_FILTER_TYPE; + +// Used in IXAudio2Voice::Set/GetFilterParameters and Set/GetOutputFilterParameters +typedef struct XAUDIO2_FILTER_PARAMETERS +{ + XAUDIO2_FILTER_TYPE Type; // Low-pass, band-pass or high-pass. + float Frequency; // Radian frequency (2 * sin(pi*CutoffFrequency/SampleRate)); + // must be >= 0 and <= XAUDIO2_MAX_FILTER_FREQUENCY + // (giving a maximum CutoffFrequency of SampleRate/6). + float OneOverQ; // Reciprocal of the filter's quality factor Q; + // must be > 0 and <= XAUDIO2_MAX_FILTER_ONEOVERQ. +} XAUDIO2_FILTER_PARAMETERS; + +// Used in IXAudio2SourceVoice::SubmitSourceBuffer +typedef struct XAUDIO2_BUFFER +{ + UINT32 Flags; // Either 0 or XAUDIO2_END_OF_STREAM. + UINT32 AudioBytes; // Size of the audio data buffer in bytes. + const BYTE* pAudioData; // Pointer to the audio data buffer. + UINT32 PlayBegin; // First sample in this buffer to be played. + UINT32 PlayLength; // Length of the region to be played in samples, + // or 0 to play the whole buffer. + UINT32 LoopBegin; // First sample of the region to be looped. + UINT32 LoopLength; // Length of the desired loop region in samples, + // or 0 to loop the entire buffer. + UINT32 LoopCount; // Number of times to repeat the loop region, + // or XAUDIO2_LOOP_INFINITE to loop forever. + void* pContext; // Context value to be passed back in callbacks. +} XAUDIO2_BUFFER; + +// Used in IXAudio2SourceVoice::SubmitSourceBuffer when submitting XWMA data. +// NOTE: If an XWMA sound is submitted in more than one buffer, each buffer's +// pDecodedPacketCumulativeBytes[PacketCount-1] value must be subtracted from +// all the entries in the next buffer's pDecodedPacketCumulativeBytes array. +// And whether a sound is submitted in more than one buffer or not, the final +// buffer of the sound should use the XAUDIO2_END_OF_STREAM flag, or else the +// client must call IXAudio2SourceVoice::Discontinuity after submitting it. +typedef struct XAUDIO2_BUFFER_WMA +{ + const UINT32* pDecodedPacketCumulativeBytes; // Decoded packet's cumulative size array. + // Each element is the number of bytes accumulated + // when the corresponding XWMA packet is decoded in + // order. The array must have PacketCount elements. + UINT32 PacketCount; // Number of XWMA packets submitted. Must be >= 1 and + // divide evenly into XAUDIO2_BUFFER.AudioBytes. +} XAUDIO2_BUFFER_WMA; + +// Returned by IXAudio2SourceVoice::GetState +typedef struct XAUDIO2_VOICE_STATE +{ + void* pCurrentBufferContext; // The pContext value provided in the XAUDIO2_BUFFER + // that is currently being processed, or NULL if + // there are no buffers in the queue. + UINT32 BuffersQueued; // Number of buffers currently queued on the voice + // (including the one that is being processed). + UINT64 SamplesPlayed; // Total number of samples produced by the voice since + // it began processing the current audio stream. +} XAUDIO2_VOICE_STATE; + +// Returned by IXAudio2::GetPerformanceData +typedef struct XAUDIO2_PERFORMANCE_DATA +{ + // CPU usage information + UINT64 AudioCyclesSinceLastQuery; // CPU cycles spent on audio processing since the + // last call to StartEngine or GetPerformanceData. + UINT64 TotalCyclesSinceLastQuery; // Total CPU cycles elapsed since the last call + // (only counts the CPU XAudio2 is running on). + UINT32 MinimumCyclesPerQuantum; // Fewest CPU cycles spent processing any one + // audio quantum since the last call. + UINT32 MaximumCyclesPerQuantum; // Most CPU cycles spent processing any one + // audio quantum since the last call. + + // Memory usage information + UINT32 MemoryUsageInBytes; // Total heap space currently in use. + + // Audio latency and glitching information + UINT32 CurrentLatencyInSamples; // Minimum delay from when a sample is read from a + // source buffer to when it reaches the speakers. + UINT32 GlitchesSinceEngineStarted; // Audio dropouts since the engine was started. + + // Data about XAudio2's current workload + UINT32 ActiveSourceVoiceCount; // Source voices currently playing. + UINT32 TotalSourceVoiceCount; // Source voices currently existing. + UINT32 ActiveSubmixVoiceCount; // Submix voices currently playing/existing. + + UINT32 ActiveResamplerCount; // Resample xAPOs currently active. + UINT32 ActiveMatrixMixCount; // MatrixMix xAPOs currently active. + + // Usage of the hardware XMA decoder (Xbox 360 only) + UINT32 ActiveXmaSourceVoices; // Number of source voices decoding XMA data. + UINT32 ActiveXmaStreams; // A voice can use more than one XMA stream. +} XAUDIO2_PERFORMANCE_DATA; + +// Used in IXAudio2::SetDebugConfiguration +typedef struct XAUDIO2_DEBUG_CONFIGURATION +{ + UINT32 TraceMask; // Bitmap of enabled debug message types. + UINT32 BreakMask; // Message types that will break into the debugger. + BOOL LogThreadID; // Whether to log the thread ID with each message. + BOOL LogFileline; // Whether to log the source file and line number. + BOOL LogFunctionName; // Whether to log the function name. + BOOL LogTiming; // Whether to log message timestamps. +} XAUDIO2_DEBUG_CONFIGURATION; + +// Values for the TraceMask and BreakMask bitmaps. Only ERRORS and WARNINGS +// are valid in BreakMask. WARNINGS implies ERRORS, DETAIL implies INFO, and +// FUNC_CALLS implies API_CALLS. By default, TraceMask is ERRORS and WARNINGS +// and all the other settings are zero. +#define XAUDIO2_LOG_ERRORS 0x0001 // For handled errors with serious effects. +#define XAUDIO2_LOG_WARNINGS 0x0002 // For handled errors that may be recoverable. +#define XAUDIO2_LOG_INFO 0x0004 // Informational chit-chat (e.g. state changes). +#define XAUDIO2_LOG_DETAIL 0x0008 // More detailed chit-chat. +#define XAUDIO2_LOG_API_CALLS 0x0010 // Public API function entries and exits. +#define XAUDIO2_LOG_FUNC_CALLS 0x0020 // Internal function entries and exits. +#define XAUDIO2_LOG_TIMING 0x0040 // Delays detected and other timing data. +#define XAUDIO2_LOG_LOCKS 0x0080 // Usage of critical sections and mutexes. +#define XAUDIO2_LOG_MEMORY 0x0100 // Memory heap usage information. +#define XAUDIO2_LOG_STREAMING 0x1000 // Audio streaming information. + + +/************************************************************************** + * + * IXAudio2: Top-level XAudio2 COM interface. + * + **************************************************************************/ + +// Use default arguments if compiling as C++ +#ifdef __cplusplus + #define X2DEFAULT(x) =x +#else + #define X2DEFAULT(x) +#endif + +#undef INTERFACE +#define INTERFACE IXAudio2 +DECLARE_INTERFACE_(IXAudio2, IUnknown) +{ + // NAME: IXAudio2::QueryInterface + // DESCRIPTION: Queries for a given COM interface on the XAudio2 object. + // Only IID_IUnknown and IID_IXAudio2 are supported. + // + // ARGUMENTS: + // riid - IID of the interface to be obtained. + // ppvInterface - Returns a pointer to the requested interface. + // + STDMETHOD(QueryInterface) (THIS_ REFIID riid, __deref_out void** ppvInterface) PURE; + + // NAME: IXAudio2::AddRef + // DESCRIPTION: Adds a reference to the XAudio2 object. + // + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + + // NAME: IXAudio2::Release + // DESCRIPTION: Releases a reference to the XAudio2 object. + // + STDMETHOD_(ULONG, Release) (THIS) PURE; + + // NAME: IXAudio2::GetDeviceCount + // DESCRIPTION: Returns the number of audio output devices available. + // + // ARGUMENTS: + // pCount - Returns the device count. + // + STDMETHOD(GetDeviceCount) (THIS_ __out UINT32* pCount) PURE; + + // NAME: IXAudio2::GetDeviceDetails + // DESCRIPTION: Returns information about the device with the given index. + // + // ARGUMENTS: + // Index - Index of the device to be queried. + // pDeviceDetails - Returns the device details. + // + STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, __out XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE; + + // NAME: IXAudio2::Initialize + // DESCRIPTION: Sets global XAudio2 parameters and prepares it for use. + // + // ARGUMENTS: + // Flags - Flags specifying the XAudio2 object's behavior. Currently unused. + // XAudio2Processor - An XAUDIO2_PROCESSOR enumeration value that specifies + // the hardware thread (Xbox) or processor (Windows) that XAudio2 will use. + // The enumeration values are platform-specific; platform-independent code + // can use XAUDIO2_DEFAULT_PROCESSOR to use the default on each platform. + // + STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE; + + // NAME: IXAudio2::RegisterForCallbacks + // DESCRIPTION: Adds a new client to receive XAudio2's engine callbacks. + // + // ARGUMENTS: + // pCallback - Callback interface to be called during each processing pass. + // + STDMETHOD(RegisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE; + + // NAME: IXAudio2::UnregisterForCallbacks + // DESCRIPTION: Removes an existing receiver of XAudio2 engine callbacks. + // + // ARGUMENTS: + // pCallback - Previously registered callback interface to be removed. + // + STDMETHOD_(void, UnregisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE; + + // NAME: IXAudio2::CreateSourceVoice + // DESCRIPTION: Creates and configures a source voice. + // + // ARGUMENTS: + // ppSourceVoice - Returns the new object's IXAudio2SourceVoice interface. + // pSourceFormat - Format of the audio that will be fed to the voice. + // Flags - XAUDIO2_VOICE flags specifying the source voice's behavior. + // MaxFrequencyRatio - Maximum SetFrequencyRatio argument to be allowed. + // pCallback - Optional pointer to a client-provided callback interface. + // pSendList - Optional list of voices this voice should send audio to. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice** ppSourceVoice, + __in const WAVEFORMATEX* pSourceFormat, + UINT32 Flags X2DEFAULT(0), + float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO), + __in_opt IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL), + __in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2::CreateSubmixVoice + // DESCRIPTION: Creates and configures a submix voice. + // + // ARGUMENTS: + // ppSubmixVoice - Returns the new object's IXAudio2SubmixVoice interface. + // InputChannels - Number of channels in this voice's input audio data. + // InputSampleRate - Sample rate of this voice's input audio data. + // Flags - XAUDIO2_VOICE flags specifying the submix voice's behavior. + // ProcessingStage - Arbitrary number that determines the processing order. + // pSendList - Optional list of voices this voice should send audio to. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateSubmixVoice) (THIS_ __deref_out IXAudio2SubmixVoice** ppSubmixVoice, + UINT32 InputChannels, UINT32 InputSampleRate, + UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0), + __in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + + // NAME: IXAudio2::CreateMasteringVoice + // DESCRIPTION: Creates and configures a mastering voice. + // + // ARGUMENTS: + // ppMasteringVoice - Returns the new object's IXAudio2MasteringVoice interface. + // InputChannels - Number of channels in this voice's input audio data. + // InputSampleRate - Sample rate of this voice's input audio data. + // Flags - XAUDIO2_VOICE flags specifying the mastering voice's behavior. + // DeviceIndex - Identifier of the device to receive the output audio. + // pEffectChain - Optional list of effects to apply to the audio data. + // + STDMETHOD(CreateMasteringVoice) (THIS_ __deref_out IXAudio2MasteringVoice** ppMasteringVoice, + UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS), + UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE), + UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0), + __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2::StartEngine + // DESCRIPTION: Creates and starts the audio processing thread. + // + STDMETHOD(StartEngine) (THIS) PURE; + + // NAME: IXAudio2::StopEngine + // DESCRIPTION: Stops and destroys the audio processing thread. + // + STDMETHOD_(void, StopEngine) (THIS) PURE; + + // NAME: IXAudio2::CommitChanges + // DESCRIPTION: Atomically applies a set of operations previously tagged + // with a given identifier. + // + // ARGUMENTS: + // OperationSet - Identifier of the set of operations to be applied. + // + STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE; + + // NAME: IXAudio2::GetPerformanceData + // DESCRIPTION: Returns current resource usage details: memory, CPU, etc. + // + // ARGUMENTS: + // pPerfData - Returns the performance data structure. + // + STDMETHOD_(void, GetPerformanceData) (THIS_ __out XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE; + + // NAME: IXAudio2::SetDebugConfiguration + // DESCRIPTION: Configures XAudio2's debug output (in debug builds only). + // + // ARGUMENTS: + // pDebugConfiguration - Structure describing the debug output behavior. + // pReserved - Optional parameter; must be NULL. + // + STDMETHOD_(void, SetDebugConfiguration) (THIS_ __in_opt const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration, + __in_opt __reserved void* pReserved X2DEFAULT(NULL)) PURE; +}; + + +/************************************************************************** + * + * IXAudio2Voice: Base voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2Voice +DECLARE_INTERFACE(IXAudio2Voice) +{ + // These methods are declared in a macro so that the same declarations + // can be used in the derived voice types (IXAudio2SourceVoice, etc). + + #define Declare_IXAudio2Voice_Methods() \ + \ + /* NAME: IXAudio2Voice::GetVoiceDetails + // DESCRIPTION: Returns the basic characteristics of this voice. + // + // ARGUMENTS: + // pVoiceDetails - Returns the voice's details. + */\ + STDMETHOD_(void, GetVoiceDetails) (THIS_ __out XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputVoices + // DESCRIPTION: Replaces the set of submix/mastering voices that receive + // this voice's output. + // + // ARGUMENTS: + // pSendList - Optional list of voices this voice should send audio to. + */\ + STDMETHOD(SetOutputVoices) (THIS_ __in_opt const XAUDIO2_VOICE_SENDS* pSendList) PURE; \ + \ + /* NAME: IXAudio2Voice::SetEffectChain + // DESCRIPTION: Replaces this voice's current effect chain with a new one. + // + // ARGUMENTS: + // pEffectChain - Structure describing the new effect chain to be used. + */\ + STDMETHOD(SetEffectChain) (THIS_ __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \ + \ + /* NAME: IXAudio2Voice::EnableEffect + // DESCRIPTION: Enables an effect in this voice's effect chain. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::DisableEffect + // DESCRIPTION: Disables an effect in this voice's effect chain. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetEffectState + // DESCRIPTION: Returns the running state of an effect. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pEnabled - Returns the enabled/disabled state of the given effect. + */\ + STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, __out BOOL* pEnabled) PURE; \ + \ + /* NAME: IXAudio2Voice::SetEffectParameters + // DESCRIPTION: Sets effect-specific parameters. + // + // REMARKS: Unlike IXAPOParameters::SetParameters, this method may + // be called from any thread. XAudio2 implements + // appropriate synchronization to copy the parameters to the + // realtime audio processing thread. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pParameters - Pointer to an effect-specific parameters block. + // ParametersByteSize - Size of the pParameters array in bytes. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \ + __in_bcount(ParametersByteSize) const void* pParameters, \ + UINT32 ParametersByteSize, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetEffectParameters + // DESCRIPTION: Obtains the current effect-specific parameters. + // + // ARGUMENTS: + // EffectIndex - Index of an effect within this voice's effect chain. + // pParameters - Returns the current values of the effect-specific parameters. + // ParametersByteSize - Size of the pParameters array in bytes. + */\ + STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, \ + __out_bcount(ParametersByteSize) void* pParameters, \ + UINT32 ParametersByteSize) PURE; \ + \ + /* NAME: IXAudio2Voice::SetFilterParameters + // DESCRIPTION: Sets this voice's filter parameters. + // + // ARGUMENTS: + // pParameters - Pointer to the filter's parameter structure. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetFilterParameters) (THIS_ __in const XAUDIO2_FILTER_PARAMETERS* pParameters, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetFilterParameters + // DESCRIPTION: Returns this voice's current filter parameters. + // + // ARGUMENTS: + // pParameters - Returns the filter parameters. + */\ + STDMETHOD_(void, GetFilterParameters) (THIS_ __out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputFilterParameters + // DESCRIPTION: Sets the filter parameters on one of this voice's sends. + // + // ARGUMENTS: + // pDestinationVoice - Destination voice of the send whose filter parameters will be set. + // pParameters - Pointer to the filter's parameter structure. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + __in const XAUDIO2_FILTER_PARAMETERS* pParameters, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetOutputFilterParameters + // DESCRIPTION: Returns the filter parameters from one of this voice's sends. + // + // ARGUMENTS: + // pDestinationVoice - Destination voice of the send whose filter parameters will be read. + // pParameters - Returns the filter parameters. + */\ + STDMETHOD_(void, GetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + __out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ + \ + /* NAME: IXAudio2Voice::SetVolume + // DESCRIPTION: Sets this voice's overall volume level. + // + // ARGUMENTS: + // Volume - New overall volume level to be used, as an amplitude factor. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetVolume) (THIS_ float Volume, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetVolume + // DESCRIPTION: Obtains this voice's current overall volume level. + // + // ARGUMENTS: + // pVolume: Returns the voice's current overall volume level. + */\ + STDMETHOD_(void, GetVolume) (THIS_ __out float* pVolume) PURE; \ + \ + /* NAME: IXAudio2Voice::SetChannelVolumes + // DESCRIPTION: Sets this voice's per-channel volume levels. + // + // ARGUMENTS: + // Channels - Used to confirm the voice's channel count. + // pVolumes - Array of per-channel volume levels to be used. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, __in_ecount(Channels) const float* pVolumes, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetChannelVolumes + // DESCRIPTION: Returns this voice's current per-channel volume levels. + // + // ARGUMENTS: + // Channels - Used to confirm the voice's channel count. + // pVolumes - Returns an array of the current per-channel volume levels. + */\ + STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, __out_ecount(Channels) float* pVolumes) PURE; \ + \ + /* NAME: IXAudio2Voice::SetOutputMatrix + // DESCRIPTION: Sets the volume levels used to mix from each channel of this + // voice's output audio to each channel of a given destination + // voice's input audio. + // + // ARGUMENTS: + // pDestinationVoice - The destination voice whose mix matrix to change. + // SourceChannels - Used to confirm this voice's output channel count + // (the number of channels produced by the last effect in the chain). + // DestinationChannels - Confirms the destination voice's input channels. + // pLevelMatrix - Array of [SourceChannels * DestinationChannels] send + // levels. The level used to send from source channel S to destination + // channel D should be in pLevelMatrix[S + SourceChannels * D]. + // OperationSet - Used to identify this call as part of a deferred batch. + */\ + STDMETHOD(SetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + __in_ecount(SourceChannels * DestinationChannels) const float* pLevelMatrix, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + \ + /* NAME: IXAudio2Voice::GetOutputMatrix + // DESCRIPTION: Obtains the volume levels used to send each channel of this + // voice's output audio to each channel of a given destination + // voice's input audio. + // + // ARGUMENTS: + // pDestinationVoice - The destination voice whose mix matrix to obtain. + // SourceChannels - Used to confirm this voice's output channel count + // (the number of channels produced by the last effect in the chain). + // DestinationChannels - Confirms the destination voice's input channels. + // pLevelMatrix - Array of send levels, as above. + */\ + STDMETHOD_(void, GetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + __out_ecount(SourceChannels * DestinationChannels) float* pLevelMatrix) PURE; \ + \ + /* NAME: IXAudio2Voice::DestroyVoice + // DESCRIPTION: Destroys this voice, stopping it if necessary and removing + // it from the XAudio2 graph. + */\ + STDMETHOD_(void, DestroyVoice) (THIS) PURE + + Declare_IXAudio2Voice_Methods(); +}; + + +/************************************************************************** + * + * IXAudio2SourceVoice: Source voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2SourceVoice +DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // NAME: IXAudio2SourceVoice::Start + // DESCRIPTION: Makes this voice start consuming and processing audio. + // + // ARGUMENTS: + // Flags - Flags controlling how the voice should be started. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(Start) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::Stop + // DESCRIPTION: Makes this voice stop consuming audio. + // + // ARGUMENTS: + // Flags - Flags controlling how the voice should be stopped. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(Stop) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::SubmitSourceBuffer + // DESCRIPTION: Adds a new audio buffer to this voice's input queue. + // + // ARGUMENTS: + // pBuffer - Pointer to the buffer structure to be queued. + // pBufferWMA - Additional structure used only when submitting XWMA data. + // + STDMETHOD(SubmitSourceBuffer) (THIS_ __in const XAUDIO2_BUFFER* pBuffer, __in_opt const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE; + + // NAME: IXAudio2SourceVoice::FlushSourceBuffers + // DESCRIPTION: Removes all pending audio buffers from this voice's queue. + // + STDMETHOD(FlushSourceBuffers) (THIS) PURE; + + // NAME: IXAudio2SourceVoice::Discontinuity + // DESCRIPTION: Notifies the voice of an intentional break in the stream of + // audio buffers (e.g. the end of a sound), to prevent XAudio2 + // from interpreting an empty buffer queue as a glitch. + // + STDMETHOD(Discontinuity) (THIS) PURE; + + // NAME: IXAudio2SourceVoice::ExitLoop + // DESCRIPTION: Breaks out of the current loop when its end is reached. + // + // ARGUMENTS: + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::GetState + // DESCRIPTION: Returns the number of buffers currently queued on this voice, + // the pContext value associated with the currently processing + // buffer (if any), and other voice state information. + // + // ARGUMENTS: + // pVoiceState - Returns the state information. + // + STDMETHOD_(void, GetState) (THIS_ __out XAUDIO2_VOICE_STATE* pVoiceState) PURE; + + // NAME: IXAudio2SourceVoice::SetFrequencyRatio + // DESCRIPTION: Sets this voice's frequency adjustment, i.e. its pitch. + // + // ARGUMENTS: + // Ratio - Frequency change, expressed as source frequency / target frequency. + // OperationSet - Used to identify this call as part of a deferred batch. + // + STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio, + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + + // NAME: IXAudio2SourceVoice::GetFrequencyRatio + // DESCRIPTION: Returns this voice's current frequency adjustment ratio. + // + // ARGUMENTS: + // pRatio - Returns the frequency adjustment. + // + STDMETHOD_(void, GetFrequencyRatio) (THIS_ __out float* pRatio) PURE; + + // NAME: IXAudio2SourceVoice::SetSourceSampleRate + // DESCRIPTION: Reconfigures this voice to treat its source data as being + // at a different sample rate than the original one specified + // in CreateSourceVoice's pSourceFormat argument. + // + // ARGUMENTS: + // UINT32 - The intended sample rate of further submitted source data. + // + STDMETHOD(SetSourceSampleRate) (THIS_ UINT32 NewSourceSampleRate) PURE; +}; + + +/************************************************************************** + * + * IXAudio2SubmixVoice: Submixing voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2SubmixVoice +DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // There are currently no methods specific to submix voices. +}; + + +/************************************************************************** + * + * IXAudio2MasteringVoice: Mastering voice management interface. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2MasteringVoice +DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) +{ + // Methods from IXAudio2Voice base interface + Declare_IXAudio2Voice_Methods(); + + // There are currently no methods specific to mastering voices. +}; + + +/************************************************************************** + * + * IXAudio2EngineCallback: Client notification interface for engine events. + * + * REMARKS: Contains methods to notify the client when certain events happen + * in the XAudio2 engine. This interface should be implemented by + * the client. XAudio2 will call these methods via the interface + * pointer provided by the client when it calls XAudio2Create or + * IXAudio2::Initialize. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2EngineCallback +DECLARE_INTERFACE(IXAudio2EngineCallback) +{ + // Called by XAudio2 just before an audio processing pass begins. + STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE; + + // Called just after an audio processing pass ends. + STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE; + + // Called in the event of a critical system error which requires XAudio2 + // to be closed down and restarted. The error code is given in Error. + STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE; +}; + + +/************************************************************************** + * + * IXAudio2VoiceCallback: Client notification interface for voice events. + * + * REMARKS: Contains methods to notify the client when certain events happen + * in an XAudio2 voice. This interface should be implemented by the + * client. XAudio2 will call these methods via an interface pointer + * provided by the client in the IXAudio2::CreateSourceVoice call. + * + **************************************************************************/ + +#undef INTERFACE +#define INTERFACE IXAudio2VoiceCallback +DECLARE_INTERFACE(IXAudio2VoiceCallback) +{ + // Called just before this voice's processing pass begins. + STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE; + + // Called just after this voice's processing pass ends. + STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE; + + // Called when this voice has just finished playing a buffer stream + // (as marked with the XAUDIO2_END_OF_STREAM flag on the last buffer). + STDMETHOD_(void, OnStreamEnd) (THIS) PURE; + + // Called when this voice is about to start processing a new buffer. + STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE; + + // Called when this voice has just finished processing a buffer. + // The buffer can now be reused or destroyed. + STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE; + + // Called when this voice has just reached the end position of a loop. + STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE; + + // Called in the event of a critical error during voice processing, + // such as a failing xAPO or an error from the hardware XMA decoder. + // The voice may have to be destroyed and re-created to recover from + // the error. The callback arguments report which buffer was being + // processed when the error occurred, and its HRESULT code. + STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE; +}; + + +/************************************************************************** + * + * Macros to make it easier to use the XAudio2 COM interfaces in C code. + * + **************************************************************************/ + +#ifndef __cplusplus + +// IXAudio2 +#define IXAudio2_QueryInterface(This,riid,ppvInterface) ((This)->lpVtbl->QueryInterface(This,riid,ppvInterface)) +#define IXAudio2_AddRef(This) ((This)->lpVtbl->AddRef(This)) +#define IXAudio2_Release(This) ((This)->lpVtbl->Release(This)) +#define IXAudio2_GetDeviceCount(This,puCount) ((This)->lpVtbl->GetDeviceCount(This,puCount)) +#define IXAudio2_GetDeviceDetails(This,Index,pDeviceDetails) ((This)->lpVtbl->GetDeviceDetails(This,Index,pDeviceDetails)) +#define IXAudio2_Initialize(This,Flags,XAudio2Processor) ((This)->lpVtbl->Initialize(This,Flags,XAudio2Processor)) +#define IXAudio2_CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain) ((This)->lpVtbl->CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain)) +#define IXAudio2_CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain) ((This)->lpVtbl->CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain)) +#define IXAudio2_CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain) ((This)->lpVtbl->CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain)) +#define IXAudio2_StartEngine(This) ((This)->lpVtbl->StartEngine(This)) +#define IXAudio2_StopEngine(This) ((This)->lpVtbl->StopEngine(This)) +#define IXAudio2_CommitChanges(This,OperationSet) ((This)->lpVtbl->CommitChanges(This,OperationSet)) +#define IXAudio2_GetPerformanceData(This,pPerfData) ((This)->lpVtbl->GetPerformanceData(This,pPerfData)) +#define IXAudio2_SetDebugConfiguration(This,pDebugConfiguration,pReserved) ((This)->lpVtbl->SetDebugConfiguration(This,pDebugConfiguration,pReserved)) + +// IXAudio2Voice +#define IXAudio2Voice_GetVoiceDetails(This,pVoiceDetails) ((This)->lpVtbl->GetVoiceDetails(This,pVoiceDetails)) +#define IXAudio2Voice_SetOutputVoices(This,pSendList) ((This)->lpVtbl->SetOutputVoices(This,pSendList)) +#define IXAudio2Voice_SetEffectChain(This,pEffectChain) ((This)->lpVtbl->SetEffectChain(This,pEffectChain)) +#define IXAudio2Voice_EnableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->EnableEffect(This,EffectIndex,OperationSet)) +#define IXAudio2Voice_DisableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->DisableEffect(This,EffectIndex,OperationSet)) +#define IXAudio2Voice_GetEffectState(This,EffectIndex,pEnabled) ((This)->lpVtbl->GetEffectState(This,EffectIndex,pEnabled)) +#define IXAudio2Voice_SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize, OperationSet) ((This)->lpVtbl->SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize,OperationSet)) +#define IXAudio2Voice_GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize) ((This)->lpVtbl->GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize)) +#define IXAudio2Voice_SetFilterParameters(This,pParameters,OperationSet) ((This)->lpVtbl->SetFilterParameters(This,pParameters,OperationSet)) +#define IXAudio2Voice_GetFilterParameters(This,pParameters) ((This)->lpVtbl->GetFilterParameters(This,pParameters)) +#define IXAudio2Voice_SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet) ((This)->lpVtbl->SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet)) +#define IXAudio2Voice_GetOutputFilterParameters(This,pDestinationVoice,pParameters) ((This)->lpVtbl->GetOutputFilterParameters(This,pDestinationVoice,pParameters)) +#define IXAudio2Voice_SetVolume(This,Volume,OperationSet) ((This)->lpVtbl->SetVolume(This,Volume,OperationSet)) +#define IXAudio2Voice_GetVolume(This,pVolume) ((This)->lpVtbl->GetVolume(This,pVolume)) +#define IXAudio2Voice_SetChannelVolumes(This,Channels,pVolumes,OperationSet) ((This)->lpVtbl->SetChannelVolumes(This,Channels,pVolumes,OperationSet)) +#define IXAudio2Voice_GetChannelVolumes(This,Channels,pVolumes) ((This)->lpVtbl->GetChannelVolumes(This,Channels,pVolumes)) +#define IXAudio2Voice_SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet) ((This)->lpVtbl->SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet)) +#define IXAudio2Voice_GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix) ((This)->lpVtbl->GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix)) +#define IXAudio2Voice_DestroyVoice(This) ((This)->lpVtbl->DestroyVoice(This)) + +// IXAudio2SourceVoice +#define IXAudio2SourceVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2SourceVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2SourceVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2SourceVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2SourceVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2SourceVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2SourceVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2SourceVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2SourceVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2SourceVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2SourceVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2SourceVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2SourceVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2SourceVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2SourceVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2SourceVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2SourceVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2SourceVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2SourceVoice_DestroyVoice IXAudio2Voice_DestroyVoice +#define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet)) +#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet)) +#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA)) +#define IXAudio2SourceVoice_FlushSourceBuffers(This) ((This)->lpVtbl->FlushSourceBuffers(This)) +#define IXAudio2SourceVoice_Discontinuity(This) ((This)->lpVtbl->Discontinuity(This)) +#define IXAudio2SourceVoice_ExitLoop(This,OperationSet) ((This)->lpVtbl->ExitLoop(This,OperationSet)) +#define IXAudio2SourceVoice_GetState(This,pVoiceState) ((This)->lpVtbl->GetState(This,pVoiceState)) +#define IXAudio2SourceVoice_SetFrequencyRatio(This,Ratio,OperationSet) ((This)->lpVtbl->SetFrequencyRatio(This,Ratio,OperationSet)) +#define IXAudio2SourceVoice_GetFrequencyRatio(This,pRatio) ((This)->lpVtbl->GetFrequencyRatio(This,pRatio)) +#define IXAudio2SourceVoice_SetSourceSampleRate(This,NewSourceSampleRate) ((This)->lpVtbl->SetSourceSampleRate(This,NewSourceSampleRate)) + +// IXAudio2SubmixVoice +#define IXAudio2SubmixVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2SubmixVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2SubmixVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2SubmixVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2SubmixVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2SubmixVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2SubmixVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2SubmixVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2SubmixVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2SubmixVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2SubmixVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2SubmixVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2SubmixVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2SubmixVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2SubmixVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2SubmixVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2SubmixVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2SubmixVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2SubmixVoice_DestroyVoice IXAudio2Voice_DestroyVoice + +// IXAudio2MasteringVoice +#define IXAudio2MasteringVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails +#define IXAudio2MasteringVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices +#define IXAudio2MasteringVoice_SetEffectChain IXAudio2Voice_SetEffectChain +#define IXAudio2MasteringVoice_EnableEffect IXAudio2Voice_EnableEffect +#define IXAudio2MasteringVoice_DisableEffect IXAudio2Voice_DisableEffect +#define IXAudio2MasteringVoice_GetEffectState IXAudio2Voice_GetEffectState +#define IXAudio2MasteringVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters +#define IXAudio2MasteringVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters +#define IXAudio2MasteringVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters +#define IXAudio2MasteringVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters +#define IXAudio2MasteringVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters +#define IXAudio2MasteringVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters +#define IXAudio2MasteringVoice_SetVolume IXAudio2Voice_SetVolume +#define IXAudio2MasteringVoice_GetVolume IXAudio2Voice_GetVolume +#define IXAudio2MasteringVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes +#define IXAudio2MasteringVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes +#define IXAudio2MasteringVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix +#define IXAudio2MasteringVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix +#define IXAudio2MasteringVoice_DestroyVoice IXAudio2Voice_DestroyVoice + +#endif // #ifndef __cplusplus + + +/************************************************************************** + * + * Utility functions used to convert from pitch in semitones and volume + * in decibels to the frequency and amplitude ratio units used by XAudio2. + * These are only defined if the client #defines XAUDIO2_HELPER_FUNCTIONS + * prior to #including xaudio2.h. + * + **************************************************************************/ + +#ifdef XAUDIO2_HELPER_FUNCTIONS + +#define _USE_MATH_DEFINES // Make math.h define M_PI +#include // For powf, log10f, sinf and asinf + +// Calculate the argument to SetVolume from a decibel value +__inline float XAudio2DecibelsToAmplitudeRatio(float Decibels) +{ + return powf(10.0f, Decibels / 20.0f); +} + +// Recover a volume in decibels from an amplitude factor +__inline float XAudio2AmplitudeRatioToDecibels(float Volume) +{ + if (Volume == 0) + { + return -3.402823466e+38f; // Smallest float value (-FLT_MAX) + } + return 20.0f * log10f(Volume); +} + +// Calculate the argument to SetFrequencyRatio from a semitone value +__inline float XAudio2SemitonesToFrequencyRatio(float Semitones) +{ + // FrequencyRatio = 2 ^ Octaves + // = 2 ^ (Semitones / 12) + return powf(2.0f, Semitones / 12.0f); +} + +// Recover a pitch in semitones from a frequency ratio +__inline float XAudio2FrequencyRatioToSemitones(float FrequencyRatio) +{ + // Semitones = 12 * log2(FrequencyRatio) + // = 12 * log2(10) * log10(FrequencyRatio) + return 39.86313713864835f * log10f(FrequencyRatio); +} + +// Convert from filter cutoff frequencies expressed in Hertz to the radian +// frequency values used in XAUDIO2_FILTER_PARAMETERS.Frequency. Note that +// the highest CutoffFrequency supported is SampleRate/6. Higher values of +// CutoffFrequency will return XAUDIO2_MAX_FILTER_FREQUENCY. +__inline float XAudio2CutoffFrequencyToRadians(float CutoffFrequency, UINT32 SampleRate) +{ + if ((UINT32)(CutoffFrequency * 6.0f) >= SampleRate) + { + return XAUDIO2_MAX_FILTER_FREQUENCY; + } + return 2.0f * sinf((float)M_PI * CutoffFrequency / SampleRate); +} + +// Convert from radian frequencies back to absolute frequencies in Hertz +__inline float XAudio2RadiansToCutoffFrequency(float Radians, float SampleRate) +{ + return SampleRate * asinf(Radians / 2.0f) / (float)M_PI; +} +#endif // #ifdef XAUDIO2_HELPER_FUNCTIONS + + +/************************************************************************** + * + * XAudio2Create: Top-level function that creates an XAudio2 instance. + * + * On Windows this is just an inline function that calls CoCreateInstance + * and Initialize. The arguments are described above, under Initialize, + * except that the XAUDIO2_DEBUG_ENGINE flag can be used here to select + * the debug version of XAudio2. + * + * On Xbox, this function is implemented in the XAudio2 library, and the + * XAUDIO2_DEBUG_ENGINE flag has no effect; the client must explicitly + * link with the debug version of the library to obtain debug behavior. + * + **************************************************************************/ + +#ifdef _XBOX + +STDAPI XAudio2Create(__deref_out IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)); + +#else // Windows + +__inline HRESULT XAudio2Create(__deref_out IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) +{ + // Instantiate the appropriate XAudio2 engine + IXAudio2* pXAudio2; + + #ifdef __cplusplus + + HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2, + NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2); + if (SUCCEEDED(hr)) + { + hr = pXAudio2->Initialize(Flags, XAudio2Processor); + + if (SUCCEEDED(hr)) + { + *ppXAudio2 = pXAudio2; + } + else + { + pXAudio2->Release(); + } + } + + #else + + HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? &CLSID_XAudio2_Debug : &CLSID_XAudio2, + NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void**)&pXAudio2); + if (SUCCEEDED(hr)) + { + hr = pXAudio2->lpVtbl->Initialize(pXAudio2, Flags, XAudio2Processor); + + if (SUCCEEDED(hr)) + { + *ppXAudio2 = pXAudio2; + } + else + { + pXAudio2->lpVtbl->Release(pXAudio2); + } + } + + #endif // #ifdef __cplusplus + + return hr; +} + +#endif // #ifdef _XBOX + + +// Undo the #pragma pack(push, 1) directive at the top of this file +#pragma pack(pop) + +#endif // #ifndef GUID_DEFS_ONLY +#endif // #ifndef __XAUDIO2_INCLUDED__ diff --git a/src/depend/mingw/include/xaudio2/xaudio2fx.h b/src/depend/mingw/include/xaudio2/xaudio2fx.h new file mode 100644 index 00000000..38aafcc6 --- /dev/null +++ b/src/depend/mingw/include/xaudio2/xaudio2fx.h @@ -0,0 +1,439 @@ +/*------------------------------------------------------------------------- + Moddified by CaptainCPS for use with MinGW / GCC 4.6.1 + + Thanks to PortAudio for their 'sal.h' compatible with MinGW ! +-------------------------------------------------------------------------*/ + +/************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: xaudio2fx.h + * Content: Declarations for the audio effects included with XAudio2. + * + **************************************************************************/ + +#ifndef __XAUDIO2FX_INCLUDED__ +#define __XAUDIO2FX_INCLUDED__ + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +/************************************************************************** + * + * XAudio2 effect class IDs. + * + **************************************************************************/ + +//#include "comdecl.h" // For DEFINE_CLSID and DEFINE_IID + +// XAudio 2.0 (March 2008 SDK) +//DEFINE_CLSID(AudioVolumeMeter, C0C56F46, 29B1, 44E9, 99, 39, A3, 2C, E8, 68, 67, E2); +//DEFINE_CLSID(AudioVolumeMeter_Debug, C0C56F46, 29B1, 44E9, 99, 39, A3, 2C, E8, 68, 67, DB); +//DEFINE_CLSID(AudioReverb, 6F6EA3A9, 2CF5, 41CF, 91, C1, 21, 70, B1, 54, 00, 63); +//DEFINE_CLSID(AudioReverb_Debug, 6F6EA3A9, 2CF5, 41CF, 91, C1, 21, 70, B1, 54, 00, DB); + +// XAudio 2.1 (June 2008 SDK) +//DEFINE_CLSID(AudioVolumeMeter, c1e3f122, a2ea, 442c, 85, 4f, 20, d9, 8f, 83, 57, a1); +//DEFINE_CLSID(AudioVolumeMeter_Debug, 6d97a461, b02d, 48ae, b5, 43, 82, bc, 35, fd, fa, e2); +//DEFINE_CLSID(AudioReverb, f4769300, b949, 4df9, b3, 33, 00, d3, 39, 32, e9, a6); +//DEFINE_CLSID(AudioReverb_Debug, aea2cabc, 8c7c, 46aa, ba, 44, 0e, 6d, 75, 88, a1, f2); + +// XAudio 2.2 (August 2008 SDK) +//DEFINE_CLSID(AudioVolumeMeter, f5ca7b34, 8055, 42c0, b8, 36, 21, 61, 29, eb, 7e, 30); +//DEFINE_CLSID(AudioVolumeMeter_Debug, f796f5f7, 6059, 4a9f, 98, 2d, 61, ee, c2, ed, 67, ca); +//DEFINE_CLSID(AudioReverb, 629cf0de, 3ecc, 41e7, 99, 26, f7, e4, 3e, eb, ec, 51); +//DEFINE_CLSID(AudioReverb_Debug, 4aae4299, 3260, 46d4, 97, cc, 6c, c7, 60, c8, 53, 29); + +// XAudio 2.3 (November 2008 SDK) +//DEFINE_CLSID(AudioVolumeMeter, e180344b, ac83, 4483, 95, 9e, 18, a5, c5, 6a, 5e, 19); +//DEFINE_CLSID(AudioVolumeMeter_Debug, 922a0a56, 7d13, 40ae, a4, 81, 3c, 6c, 60, f1, 14, 01); +//DEFINE_CLSID(AudioReverb, 9cab402c, 1d37, 44b4, 88, 6d, fa, 4f, 36, 17, 0a, 4c); +//DEFINE_CLSID(AudioReverb_Debug, eadda998, 3be6, 4505, 84, be, ea, 06, 36, 5d, b9, 6b); + +// XAudio 2.4 (March 2009 SDK) +//DEFINE_CLSID(AudioVolumeMeter, c7338b95, 52b8, 4542, aa, 79, 42, eb, 01, 6c, 8c, 1c); +//DEFINE_CLSID(AudioVolumeMeter_Debug, 524bd872, 5c0b, 4217, bd, b8, 0a, 86, 81, 83, 0b, a5); +//DEFINE_CLSID(AudioReverb, 8bb7778b, 645b, 4475, 9a, 73, 1d, e3, 17, 0b, d3, af); +//DEFINE_CLSID(AudioReverb_Debug, da7738a2, cd0c, 4367, 9a, ac, d7, ea, d7, c6, 4f, 98); + +// XAudio 2.5 (March 2009 SDK) +//DEFINE_CLSID(AudioVolumeMeter, 2139e6da, c341, 4774, 9a, c3, b4, e0, 26, 34, 7f, 64); +//DEFINE_CLSID(AudioVolumeMeter_Debug, a5cc4e13, ca00, 416b, a6, ee, 49, fe, e7, b5, 43, d0); +//DEFINE_CLSID(AudioReverb, d06df0d0, 8518, 441e, 82, 2f, 54, 51, d5, c5, 95, b8); +//DEFINE_CLSID(AudioReverb_Debug, 613604ec, 304c, 45ec, a4, ed, 7a, 1c, 61, 2e, 9e, 72); + +// XAudio 2.6 (February 2010 SDK) +//DEFINE_CLSID(AudioVolumeMeter, e48c5a3f, 93ef, 43bb, a0, 92, 2c, 7c, eb, 94, 6f, 27); +//DEFINE_CLSID(AudioVolumeMeter_Debug, 9a9eaef7, a9e0, 4088, 9b, 1b, 9c, a0, 3a, 1a, ec, d4); +//DEFINE_CLSID(AudioReverb, cecec95a, d894, 491a, be, e3, 5e, 10, 6f, b5, 9f, 2d); +//DEFINE_CLSID(AudioReverb_Debug, 99a1c72e, 364c, 4c1b, 96, 23, fd, 5c, 8a, bd, 90, c7); + +// XAudio 2.7 (June 2010 SDK) +DEFINE_GUID(CLSID_AudioVolumeMeter, 0xcac1105f, 0x619b, 0x4d04, 0x83, 0x1a, 0x44, 0xe1, 0xcb, 0xf1, 0x2d, 0x57); +DEFINE_GUID(CLSID_AudioVolumeMeter_Debug, 0x2d9a0f9c, 0xe67b, 0x4b24, 0xab, 0x44, 0x92, 0xb3, 0xe7, 0x70, 0xc0, 0x20); +DEFINE_GUID(CLSID_AudioReverb, 0x6a93130e, 0x1d53, 0x41d1, 0xa9, 0xcf, 0xe7, 0x58, 0x80, 0x0b, 0xb1, 0x79); +DEFINE_GUID(CLSID_AudioReverb_Debug, 0xc4f82dd4, 0xcb4e, 0x4ce1, 0x8b, 0xdb, 0xee, 0x32, 0xd4, 0x19, 0x82, 0x69); + +// Ignore the rest of this header if only the GUID definitions were requested +#ifndef GUID_DEFS_ONLY + +#ifdef _XBOX + #include // Xbox COM declarations (IUnknown, etc) +#else + #include // Windows COM declarations +#endif +#include // For log10() + +// All structures defined in this file should use tight packing +#pragma pack(push, 1) + + +/************************************************************************** + * + * Effect creation functions. On Windows, these are just inline functions + * that call CoCreateInstance and Initialize; the XAUDIO2FX_DEBUG flag can + * be used to select the debug version of the effects. On Xbox, these map + * to real functions included in xaudio2.lib, and the XAUDIO2FX_DEBUG flag + * is ignored; the application must link with the debug library to use the + * debug functionality. + * + **************************************************************************/ + +// Use default values for some parameters if building C++ code +#ifdef __cplusplus + #define DEFAULT(x) =x +#else + #define DEFAULT(x) +#endif + +#define XAUDIO2FX_DEBUG 1 // To select the debug version of an effect + +#ifdef _XBOX + + STDAPI CreateAudioVolumeMeter(__deref_out IUnknown** ppApo); + STDAPI CreateAudioReverb(__deref_out IUnknown** ppApo); + + __inline HRESULT XAudio2CreateVolumeMeter(__deref_out IUnknown** ppApo, UINT32 /*Flags*/ DEFAULT(0)) + { + return CreateAudioVolumeMeter(ppApo); + } + + __inline HRESULT XAudio2CreateReverb(__deref_out IUnknown** ppApo, UINT32 /*Flags*/ DEFAULT(0)) + { + return CreateAudioReverb(ppApo); + } + +#else // Windows + + __inline HRESULT XAudio2CreateVolumeMeter(__deref_out IUnknown** ppApo, UINT32 Flags DEFAULT(0)) + { + #ifdef __cplusplus + return CoCreateInstance((Flags & XAUDIO2FX_DEBUG) ? CLSID_AudioVolumeMeter_Debug + : CLSID_AudioVolumeMeter, + NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)ppApo); + #else + return CoCreateInstance((Flags & XAUDIO2FX_DEBUG) ? &CLSID_AudioVolumeMeter_Debug + : &CLSID_AudioVolumeMeter, + NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppApo); + #endif + } + + __inline HRESULT XAudio2CreateReverb(__deref_out IUnknown** ppApo, UINT32 Flags DEFAULT(0)) + { + #ifdef __cplusplus + return CoCreateInstance((Flags & XAUDIO2FX_DEBUG) ? CLSID_AudioReverb_Debug + : CLSID_AudioReverb, + NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)ppApo); + #else + return CoCreateInstance((Flags & XAUDIO2FX_DEBUG) ? &CLSID_AudioReverb_Debug + : &CLSID_AudioReverb, + NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppApo); + #endif + } + +#endif // #ifdef _XBOX + + + +/************************************************************************** + * + * Volume meter parameters. + * The volume meter supports FLOAT32 audio formats and must be used in-place. + * + **************************************************************************/ + +// XAUDIO2FX_VOLUMEMETER_LEVELS: Receives results from GetEffectParameters(). +// The user is responsible for allocating pPeakLevels, pRMSLevels, and +// initializing ChannelCount accordingly. +// The volume meter does not support SetEffectParameters(). +typedef struct XAUDIO2FX_VOLUMEMETER_LEVELS +{ + float* pPeakLevels; // Peak levels table: receives maximum absolute level for each channel + // over a processing pass; may be NULL if pRMSLevls != NULL, + // otherwise must have at least ChannelCount elements. + float* pRMSLevels; // Root mean square levels table: receives RMS level for each channel + // over a processing pass; may be NULL if pPeakLevels != NULL, + // otherwise must have at least ChannelCount elements. + UINT32 ChannelCount; // Number of channels being processed by the volume meter APO +} XAUDIO2FX_VOLUMEMETER_LEVELS; + + + +/************************************************************************** + * + * Reverb parameters. + * The reverb supports only FLOAT32 audio with the following channel + * configurations: + * Input: Mono Output: Mono + * Input: Mono Output: 5.1 + * Input: Stereo Output: Stereo + * Input: Stereo Output: 5.1 + * The framerate must be within [20000, 48000] Hz. + * + * When using mono input, delay filters associated with the right channel + * are not executed. In this case, parameters such as PositionRight and + * PositionMatrixRight have no effect. This also means the reverb uses + * less CPU when hosted in a mono submix. + * + **************************************************************************/ + +#define XAUDIO2FX_REVERB_MIN_FRAMERATE 20000 +#define XAUDIO2FX_REVERB_MAX_FRAMERATE 48000 + +// XAUDIO2FX_REVERB_PARAMETERS: Native parameter set for the reverb effect + +typedef struct XAUDIO2FX_REVERB_PARAMETERS +{ + // ratio of wet (processed) signal to dry (original) signal + float WetDryMix; // [0, 100] (percentage) + + // Delay times + UINT32 ReflectionsDelay; // [0, 300] in ms + BYTE ReverbDelay; // [0, 85] in ms + BYTE RearDelay; // [0, 5] in ms + + // Indexed parameters + BYTE PositionLeft; // [0, 30] no units + BYTE PositionRight; // [0, 30] no units, ignored when configured to mono + BYTE PositionMatrixLeft; // [0, 30] no units + BYTE PositionMatrixRight; // [0, 30] no units, ignored when configured to mono + BYTE EarlyDiffusion; // [0, 15] no units + BYTE LateDiffusion; // [0, 15] no units + BYTE LowEQGain; // [0, 12] no units + BYTE LowEQCutoff; // [0, 9] no units + BYTE HighEQGain; // [0, 8] no units + BYTE HighEQCutoff; // [0, 14] no units + + // Direct parameters + float RoomFilterFreq; // [20, 20000] in Hz + float RoomFilterMain; // [-100, 0] in dB + float RoomFilterHF; // [-100, 0] in dB + float ReflectionsGain; // [-100, 20] in dB + float ReverbGain; // [-100, 20] in dB + float DecayTime; // [0.1, inf] in seconds + float Density; // [0, 100] (percentage) + float RoomSize; // [1, 100] in feet +} XAUDIO2FX_REVERB_PARAMETERS; + + +// Maximum, minimum and default values for the parameters above +#define XAUDIO2FX_REVERB_MIN_WET_DRY_MIX 0.0f +#define XAUDIO2FX_REVERB_MIN_REFLECTIONS_DELAY 0 +#define XAUDIO2FX_REVERB_MIN_REVERB_DELAY 0 +#define XAUDIO2FX_REVERB_MIN_REAR_DELAY 0 +#define XAUDIO2FX_REVERB_MIN_POSITION 0 +#define XAUDIO2FX_REVERB_MIN_DIFFUSION 0 +#define XAUDIO2FX_REVERB_MIN_LOW_EQ_GAIN 0 +#define XAUDIO2FX_REVERB_MIN_LOW_EQ_CUTOFF 0 +#define XAUDIO2FX_REVERB_MIN_HIGH_EQ_GAIN 0 +#define XAUDIO2FX_REVERB_MIN_HIGH_EQ_CUTOFF 0 +#define XAUDIO2FX_REVERB_MIN_ROOM_FILTER_FREQ 20.0f +#define XAUDIO2FX_REVERB_MIN_ROOM_FILTER_MAIN -100.0f +#define XAUDIO2FX_REVERB_MIN_ROOM_FILTER_HF -100.0f +#define XAUDIO2FX_REVERB_MIN_REFLECTIONS_GAIN -100.0f +#define XAUDIO2FX_REVERB_MIN_REVERB_GAIN -100.0f +#define XAUDIO2FX_REVERB_MIN_DECAY_TIME 0.1f +#define XAUDIO2FX_REVERB_MIN_DENSITY 0.0f +#define XAUDIO2FX_REVERB_MIN_ROOM_SIZE 0.0f + +#define XAUDIO2FX_REVERB_MAX_WET_DRY_MIX 100.0f +#define XAUDIO2FX_REVERB_MAX_REFLECTIONS_DELAY 300 +#define XAUDIO2FX_REVERB_MAX_REVERB_DELAY 85 +#define XAUDIO2FX_REVERB_MAX_REAR_DELAY 5 +#define XAUDIO2FX_REVERB_MAX_POSITION 30 +#define XAUDIO2FX_REVERB_MAX_DIFFUSION 15 +#define XAUDIO2FX_REVERB_MAX_LOW_EQ_GAIN 12 +#define XAUDIO2FX_REVERB_MAX_LOW_EQ_CUTOFF 9 +#define XAUDIO2FX_REVERB_MAX_HIGH_EQ_GAIN 8 +#define XAUDIO2FX_REVERB_MAX_HIGH_EQ_CUTOFF 14 +#define XAUDIO2FX_REVERB_MAX_ROOM_FILTER_FREQ 20000.0f +#define XAUDIO2FX_REVERB_MAX_ROOM_FILTER_MAIN 0.0f +#define XAUDIO2FX_REVERB_MAX_ROOM_FILTER_HF 0.0f +#define XAUDIO2FX_REVERB_MAX_REFLECTIONS_GAIN 20.0f +#define XAUDIO2FX_REVERB_MAX_REVERB_GAIN 20.0f +#define XAUDIO2FX_REVERB_MAX_DENSITY 100.0f +#define XAUDIO2FX_REVERB_MAX_ROOM_SIZE 100.0f + +#define XAUDIO2FX_REVERB_DEFAULT_WET_DRY_MIX 100.0f +#define XAUDIO2FX_REVERB_DEFAULT_REFLECTIONS_DELAY 5 +#define XAUDIO2FX_REVERB_DEFAULT_REVERB_DELAY 5 +#define XAUDIO2FX_REVERB_DEFAULT_REAR_DELAY 5 +#define XAUDIO2FX_REVERB_DEFAULT_POSITION 6 +#define XAUDIO2FX_REVERB_DEFAULT_POSITION_MATRIX 27 +#define XAUDIO2FX_REVERB_DEFAULT_EARLY_DIFFUSION 8 +#define XAUDIO2FX_REVERB_DEFAULT_LATE_DIFFUSION 8 +#define XAUDIO2FX_REVERB_DEFAULT_LOW_EQ_GAIN 8 +#define XAUDIO2FX_REVERB_DEFAULT_LOW_EQ_CUTOFF 4 +#define XAUDIO2FX_REVERB_DEFAULT_HIGH_EQ_GAIN 8 +#define XAUDIO2FX_REVERB_DEFAULT_HIGH_EQ_CUTOFF 4 +#define XAUDIO2FX_REVERB_DEFAULT_ROOM_FILTER_FREQ 5000.0f +#define XAUDIO2FX_REVERB_DEFAULT_ROOM_FILTER_MAIN 0.0f +#define XAUDIO2FX_REVERB_DEFAULT_ROOM_FILTER_HF 0.0f +#define XAUDIO2FX_REVERB_DEFAULT_REFLECTIONS_GAIN 0.0f +#define XAUDIO2FX_REVERB_DEFAULT_REVERB_GAIN 0.0f +#define XAUDIO2FX_REVERB_DEFAULT_DECAY_TIME 1.0f +#define XAUDIO2FX_REVERB_DEFAULT_DENSITY 100.0f +#define XAUDIO2FX_REVERB_DEFAULT_ROOM_SIZE 100.0f + + +// XAUDIO2FX_REVERB_I3DL2_PARAMETERS: Parameter set compliant with the I3DL2 standard + +typedef struct XAUDIO2FX_REVERB_I3DL2_PARAMETERS +{ + // ratio of wet (processed) signal to dry (original) signal + float WetDryMix; // [0, 100] (percentage) + + // Standard I3DL2 parameters + INT32 Room; // [-10000, 0] in mB (hundredths of decibels) + INT32 RoomHF; // [-10000, 0] in mB (hundredths of decibels) + float RoomRolloffFactor; // [0.0, 10.0] + float DecayTime; // [0.1, 20.0] in seconds + float DecayHFRatio; // [0.1, 2.0] + INT32 Reflections; // [-10000, 1000] in mB (hundredths of decibels) + float ReflectionsDelay; // [0.0, 0.3] in seconds + INT32 Reverb; // [-10000, 2000] in mB (hundredths of decibels) + float ReverbDelay; // [0.0, 0.1] in seconds + float Diffusion; // [0.0, 100.0] (percentage) + float Density; // [0.0, 100.0] (percentage) + float HFReference; // [20.0, 20000.0] in Hz +} XAUDIO2FX_REVERB_I3DL2_PARAMETERS; + + +// ReverbConvertI3DL2ToNative: Utility function to map from I3DL2 to native parameters + +__inline void ReverbConvertI3DL2ToNative +( + __in const XAUDIO2FX_REVERB_I3DL2_PARAMETERS* pI3DL2, + __out XAUDIO2FX_REVERB_PARAMETERS* pNative +) +{ + float reflectionsDelay; + float reverbDelay; + + // RoomRolloffFactor is ignored + + // These parameters have no equivalent in I3DL2 + pNative->RearDelay = XAUDIO2FX_REVERB_DEFAULT_REAR_DELAY; // 5 + pNative->PositionLeft = XAUDIO2FX_REVERB_DEFAULT_POSITION; // 6 + pNative->PositionRight = XAUDIO2FX_REVERB_DEFAULT_POSITION; // 6 + pNative->PositionMatrixLeft = XAUDIO2FX_REVERB_DEFAULT_POSITION_MATRIX; // 27 + pNative->PositionMatrixRight = XAUDIO2FX_REVERB_DEFAULT_POSITION_MATRIX; // 27 + pNative->RoomSize = XAUDIO2FX_REVERB_DEFAULT_ROOM_SIZE; // 100 + pNative->LowEQCutoff = 4; + pNative->HighEQCutoff = 6; + + // The rest of the I3DL2 parameters map to the native property set + pNative->RoomFilterMain = (float)pI3DL2->Room / 100.0f; + pNative->RoomFilterHF = (float)pI3DL2->RoomHF / 100.0f; + + if (pI3DL2->DecayHFRatio >= 1.0f) + { + INT32 index = (INT32)(-4.0 * log10(pI3DL2->DecayHFRatio)); + if (index < -8) index = -8; + pNative->LowEQGain = (BYTE)((index < 0) ? index + 8 : 8); + pNative->HighEQGain = 8; + pNative->DecayTime = pI3DL2->DecayTime * pI3DL2->DecayHFRatio; + } + else + { + INT32 index = (INT32)(4.0 * log10(pI3DL2->DecayHFRatio)); + if (index < -8) index = -8; + pNative->LowEQGain = 8; + pNative->HighEQGain = (BYTE)((index < 0) ? index + 8 : 8); + pNative->DecayTime = pI3DL2->DecayTime; + } + + reflectionsDelay = pI3DL2->ReflectionsDelay * 1000.0f; + if (reflectionsDelay >= XAUDIO2FX_REVERB_MAX_REFLECTIONS_DELAY) // 300 + { + reflectionsDelay = (float)(XAUDIO2FX_REVERB_MAX_REFLECTIONS_DELAY - 1); + } + else if (reflectionsDelay <= 1) + { + reflectionsDelay = 1; + } + pNative->ReflectionsDelay = (UINT32)reflectionsDelay; + + reverbDelay = pI3DL2->ReverbDelay * 1000.0f; + if (reverbDelay >= XAUDIO2FX_REVERB_MAX_REVERB_DELAY) // 85 + { + reverbDelay = (float)(XAUDIO2FX_REVERB_MAX_REVERB_DELAY - 1); + } + pNative->ReverbDelay = (BYTE)reverbDelay; + + pNative->ReflectionsGain = pI3DL2->Reflections / 100.0f; + pNative->ReverbGain = pI3DL2->Reverb / 100.0f; + pNative->EarlyDiffusion = (BYTE)(15.0f * pI3DL2->Diffusion / 100.0f); + pNative->LateDiffusion = pNative->EarlyDiffusion; + pNative->Density = pI3DL2->Density; + pNative->RoomFilterFreq = pI3DL2->HFReference; + + pNative->WetDryMix = pI3DL2->WetDryMix; +} + + +/************************************************************************** + * + * Standard I3DL2 reverb presets (100% wet). + * + **************************************************************************/ + +#define XAUDIO2FX_I3DL2_PRESET_DEFAULT {100,-10000, 0,0.0f, 1.00f,0.50f,-10000,0.020f,-10000,0.040f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_GENERIC {100, -1000, -100,0.0f, 1.49f,0.83f, -2602,0.007f, 200,0.011f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_PADDEDCELL {100, -1000,-6000,0.0f, 0.17f,0.10f, -1204,0.001f, 207,0.002f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_ROOM {100, -1000, -454,0.0f, 0.40f,0.83f, -1646,0.002f, 53,0.003f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_BATHROOM {100, -1000,-1200,0.0f, 1.49f,0.54f, -370,0.007f, 1030,0.011f,100.0f, 60.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_LIVINGROOM {100, -1000,-6000,0.0f, 0.50f,0.10f, -1376,0.003f, -1104,0.004f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_STONEROOM {100, -1000, -300,0.0f, 2.31f,0.64f, -711,0.012f, 83,0.017f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_AUDITORIUM {100, -1000, -476,0.0f, 4.32f,0.59f, -789,0.020f, -289,0.030f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_CONCERTHALL {100, -1000, -500,0.0f, 3.92f,0.70f, -1230,0.020f, -2,0.029f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_CAVE {100, -1000, 0,0.0f, 2.91f,1.30f, -602,0.015f, -302,0.022f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_ARENA {100, -1000, -698,0.0f, 7.24f,0.33f, -1166,0.020f, 16,0.030f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_HANGAR {100, -1000,-1000,0.0f,10.05f,0.23f, -602,0.020f, 198,0.030f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_CARPETEDHALLWAY {100, -1000,-4000,0.0f, 0.30f,0.10f, -1831,0.002f, -1630,0.030f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_HALLWAY {100, -1000, -300,0.0f, 1.49f,0.59f, -1219,0.007f, 441,0.011f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_STONECORRIDOR {100, -1000, -237,0.0f, 2.70f,0.79f, -1214,0.013f, 395,0.020f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_ALLEY {100, -1000, -270,0.0f, 1.49f,0.86f, -1204,0.007f, -4,0.011f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_FOREST {100, -1000,-3300,0.0f, 1.49f,0.54f, -2560,0.162f, -613,0.088f, 79.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_CITY {100, -1000, -800,0.0f, 1.49f,0.67f, -2273,0.007f, -2217,0.011f, 50.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_MOUNTAINS {100, -1000,-2500,0.0f, 1.49f,0.21f, -2780,0.300f, -2014,0.100f, 27.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_QUARRY {100, -1000,-1000,0.0f, 1.49f,0.83f,-10000,0.061f, 500,0.025f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_PLAIN {100, -1000,-2000,0.0f, 1.49f,0.50f, -2466,0.179f, -2514,0.100f, 21.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_PARKINGLOT {100, -1000, 0,0.0f, 1.65f,1.50f, -1363,0.008f, -1153,0.012f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_SEWERPIPE {100, -1000,-1000,0.0f, 2.81f,0.14f, 429,0.014f, 648,0.021f, 80.0f, 60.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_UNDERWATER {100, -1000,-4000,0.0f, 1.49f,0.10f, -449,0.007f, 1700,0.011f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_SMALLROOM {100, -1000, -600,0.0f, 1.10f,0.83f, -400,0.005f, 500,0.010f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_MEDIUMROOM {100, -1000, -600,0.0f, 1.30f,0.83f, -1000,0.010f, -200,0.020f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_LARGEROOM {100, -1000, -600,0.0f, 1.50f,0.83f, -1600,0.020f, -1000,0.040f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_MEDIUMHALL {100, -1000, -600,0.0f, 1.80f,0.70f, -1300,0.015f, -800,0.030f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_LARGEHALL {100, -1000, -600,0.0f, 1.80f,0.70f, -2000,0.030f, -1400,0.060f,100.0f,100.0f,5000.0f} +#define XAUDIO2FX_I3DL2_PRESET_PLATE {100, -1000, -200,0.0f, 1.30f,0.90f, 0,0.002f, 0,0.010f,100.0f, 75.0f,5000.0f} + + +// Undo the #pragma pack(push, 1) at the top of this file +#pragma pack(pop) + +#endif // #ifndef GUID_DEFS_ONLY +#endif // #ifndef __XAUDIO2FX_INCLUDED__ diff --git a/src/depend/mingw/include/xaudio2/xma2defs.h b/src/depend/mingw/include/xaudio2/xma2defs.h new file mode 100644 index 00000000..ab80279d --- /dev/null +++ b/src/depend/mingw/include/xaudio2/xma2defs.h @@ -0,0 +1,728 @@ +/*------------------------------------------------------------------------- + Moddified by CaptainCPS for use with MinGW / GCC 4.6.1 + + Thanks to PortAudio for their 'sal.h' compatible with MinGW ! +-------------------------------------------------------------------------*/ + +/*************************************************************************** + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: xma2defs.h + * Content: Constants, data types and functions for XMA2 compressed audio. + * + ***************************************************************************/ + +#ifndef __XMA2DEFS_INCLUDED__ +#define __XMA2DEFS_INCLUDED__ + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#include // Markers for documenting API semantics +#include // For S_OK, E_FAIL +#include // Basic data types and constants for audio work + + +/*************************************************************************** + * Overview + ***************************************************************************/ + +// A typical XMA2 file contains these RIFF chunks: +// +// 'fmt' or 'XMA2' chunk (or both): A description of the XMA data's structure +// and characteristics (length, channels, sample rate, loops, block size, etc). +// +// 'seek' chunk: A seek table to help navigate the XMA data. +// +// 'data' chunk: The encoded XMA2 data. +// +// The encoded XMA2 data is structured as a set of BLOCKS, which contain PACKETS, +// which contain FRAMES, which contain SUBFRAMES (roughly speaking). The frames +// in a file may also be divided into several subsets, called STREAMS. +// +// FRAME: A variable-sized segment of XMA data that decodes to exactly 512 mono +// or stereo PCM samples. This is the smallest unit of XMA data that can +// be decoded in isolation. Frames are an arbitrary number of bits in +// length, and need not be byte-aligned. See "XMA frame structure" below. +// +// SUBFRAME: A region of bits in an XMA frame that decodes to 128 mono or stereo +// samples. The XMA decoder cannot decode a subframe in isolation; it needs +// a whole frame to work with. However, it can begin emitting the frame's +// decoded samples at any one of the four subframe boundaries. Subframes +// can be addressed for seeking and looping purposes. +// +// PACKET: A 2Kb region containing a 32-bit header and some XMA frames. Frames +// can (and usually do) span packets. A packet's header includes the offset +// in bits of the first frame that begins within that packet. All of the +// frames that begin in a given packet belong to the same "stream" (see the +// Multichannel Audio section below). +// +// STREAM: A set of packets within an XMA file that all contain data for the +// same mono or stereo component of a PCM file with more than two channels. +// The packets comprising a given stream may be interleaved with each other +// more or less arbitrarily; see Multichannel Audio. +// +// BLOCK: An array of XMA packets; or, to break it down differently, a series of +// consecutive XMA frames, padded at the end with reserved data. A block +// must contain at least one 2Kb packet per stream, and it can hold up to +// 4095 packets (8190Kb), but its size is typically in the 32Kb-128Kb range. +// (The size chosen involves a trade-off between memory use and efficiency +// of reading from permanent storage.) +// +// XMA frames do not span blocks, so a block is guaranteed to begin with a +// set of complete frames, one per stream. Also, a block in a multi-stream +// XMA2 file always contains the same number of samples for each stream; +// see Multichannel Audio. +// +// The 'data' chunk in an XMA2 file is an array of XMA2WAVEFORMAT.BlockCount XMA +// blocks, all the same size (as specified in XMA2WAVEFORMAT.BlockSizeInBytes) +// except for the last one, which may be shorter. + + +// MULTICHANNEL AUDIO: the XMA decoder can only decode raw XMA data into either +// mono or stereo PCM data. In order to encode a 6-channel file (say), the file +// must be deinterleaved into 3 stereo streams that are encoded independently, +// producing 3 encoded XMA data streams. Then the packets in these 3 streams +// are interleaved to produce a single XMA2 file, and some information is added +// to the file so that the original 6-channel audio can be reconstructed at +// decode time. This works using the concept of an XMA stream (see above). +// +// The frames for all the streams in an XMA file are interleaved in an arbitrary +// order. To locate a frame that belongs to a given stream in a given XMA block, +// you must examine the first few packets in the block. Here (and only here) the +// packets are guaranteed to be presented in stream order, so that all frames +// beginning in packet 0 belong to stream 0 (the first stereo pair), etc. +// +// (This means that when decoding multi-stream XMA files, only entire XMA blocks +// should be submitted to the decoder; otherwise it cannot know which frames +// belong to which stream.) +// +// Once you have one frame that belongs to a given stream, you can find the next +// one by looking at the frame's 'NextFrameOffsetBits' value (which is stored in +// its first 15 bits; see XMAFRAME below). The GetXmaFrameBitPosition function +// uses this technique. + + +// SEEKING IN XMA2 FILES: Here is some pseudocode to find the byte position and +// subframe in an XMA2 file which will contain sample S when decoded. +// +// 1. Traverse the seek table to find the XMA2 block containing sample S. The +// seek table is an array of big-endian DWORDs, one per block in the file. +// The Nth DWORD is the total number of PCM samples that would be obtained +// by decoding the entire XMA file up to the end of block N. Hence, the +// block we want is the first one whose seek table entry is greater than S. +// (See the GetXmaBlockContainingSample helper function.) +// +// 2. Calculate which frame F within the block found above contains sample S. +// Since each frame decodes to 512 samples, this is straightforward. The +// first frame in the block produces samples X to X + 512, where X is the +// seek table entry for the prior block. So F is (S - X) / 512. +// +// 3. Find the bit offset within the block where frame F starts. Since frames +// are variable-sized, this can only be done by traversing all the frames in +// the block until we reach frame F. (See GetXmaFrameBitPosition.) +// +// 4. Frame F has four 128-sample subframes. To find the subframe containing S, +// we can use the formula (S % 512) / 128. +// +// In the case of multi-stream XMA files, sample S is a multichannel sample with +// parts coming from several frames, one per stream. To find all these frames, +// steps 2-4 need to be repeated for each stream N, using the knowledge that the +// first packets in a block are presented in stream order. The frame traversal +// in step 3 must be started at the first frame in the Nth packet of the block, +// which will be the first frame for stream N. (And the packet header will tell +// you the first frame's start position within the packet.) +// +// Step 1 can be performed using the GetXmaBlockContainingSample function below, +// and steps 2-4 by calling GetXmaDecodePositionForSample once for each stream. + + + +/*************************************************************************** + * XMA constants + ***************************************************************************/ + +// Size of the PCM samples produced by the XMA decoder +#define XMA_OUTPUT_SAMPLE_BYTES 2u +#define XMA_OUTPUT_SAMPLE_BITS (XMA_OUTPUT_SAMPLE_BYTES * 8u) + +// Size of an XMA packet +#define XMA_BYTES_PER_PACKET 2048u +#define XMA_BITS_PER_PACKET (XMA_BYTES_PER_PACKET * 8u) + +// Size of an XMA packet header +#define XMA_PACKET_HEADER_BYTES 4u +#define XMA_PACKET_HEADER_BITS (XMA_PACKET_HEADER_BYTES * 8u) + +// Sample blocks in a decoded XMA frame +#define XMA_SAMPLES_PER_FRAME 512u + +// Sample blocks in a decoded XMA subframe +#define XMA_SAMPLES_PER_SUBFRAME 128u + +// Maximum encoded data that can be submitted to the XMA decoder at a time +#define XMA_READBUFFER_MAX_PACKETS 4095u +#define XMA_READBUFFER_MAX_BYTES (XMA_READBUFFER_MAX_PACKETS * XMA_BYTES_PER_PACKET) + +// Maximum size allowed for the XMA decoder's output buffers +#define XMA_WRITEBUFFER_MAX_BYTES (31u * 256u) + +// Required byte alignment of the XMA decoder's output buffers +#define XMA_WRITEBUFFER_BYTE_ALIGNMENT 256u + +// Decode chunk sizes for the XMA_PLAYBACK_INIT.subframesToDecode field +#define XMA_MIN_SUBFRAMES_TO_DECODE 1u +#define XMA_MAX_SUBFRAMES_TO_DECODE 8u +#define XMA_OPTIMAL_SUBFRAMES_TO_DECODE 4u + +// LoopCount<255 means finite repetitions; LoopCount=255 means infinite looping +#define XMA_MAX_LOOPCOUNT 254u +#define XMA_INFINITE_LOOP 255u + + + +/*************************************************************************** + * XMA format structures + ***************************************************************************/ + +// The currently recommended way to express format information for XMA2 files +// is the XMA2WAVEFORMATEX structure. This structure is fully compliant with +// the WAVEFORMATEX standard and contains all the information needed to parse +// and manage XMA2 files in a compact way. + +#define WAVE_FORMAT_XMA2 0x166 + +typedef struct XMA2WAVEFORMATEX +{ + WAVEFORMATEX wfx; + // Meaning of the WAVEFORMATEX fields here: + // wFormatTag; // Audio format type; always WAVE_FORMAT_XMA2 + // nChannels; // Channel count of the decoded audio + // nSamplesPerSec; // Sample rate of the decoded audio + // nAvgBytesPerSec; // Used internally by the XMA encoder + // nBlockAlign; // Decoded sample size; channels * wBitsPerSample / 8 + // wBitsPerSample; // Bits per decoded mono sample; always 16 for XMA + // cbSize; // Size in bytes of the rest of this structure (34) + + WORD NumStreams; // Number of audio streams (1 or 2 channels each) + DWORD ChannelMask; // Spatial positions of the channels in this file, + // stored as SPEAKER_xxx values (see audiodefs.h) + DWORD SamplesEncoded; // Total number of PCM samples the file decodes to + DWORD BytesPerBlock; // XMA block size (but the last one may be shorter) + DWORD PlayBegin; // First valid sample in the decoded audio + DWORD PlayLength; // Length of the valid part of the decoded audio + DWORD LoopBegin; // Beginning of the loop region in decoded sample terms + DWORD LoopLength; // Length of the loop region in decoded sample terms + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + BYTE EncoderVersion; // Version of XMA encoder that generated the file + WORD BlockCount; // XMA blocks in file (and entries in its seek table) +} XMA2WAVEFORMATEX, *PXMA2WAVEFORMATEX; + + +// The legacy XMA format structures are described here for reference, but they +// should not be used in new content. XMAWAVEFORMAT was the structure used in +// XMA version 1 files. XMA2WAVEFORMAT was used in early XMA2 files; it is not +// placed in the usual 'fmt' RIFF chunk but in its own 'XMA2' chunk. + +#ifndef WAVE_FORMAT_XMA +#define WAVE_FORMAT_XMA 0x0165 + +// Values used in the ChannelMask fields below. Similar to the SPEAKER_xxx +// values defined in audiodefs.h, but modified to fit in a single byte. +#ifndef XMA_SPEAKER_LEFT + #define XMA_SPEAKER_LEFT 0x01 + #define XMA_SPEAKER_RIGHT 0x02 + #define XMA_SPEAKER_CENTER 0x04 + #define XMA_SPEAKER_LFE 0x08 + #define XMA_SPEAKER_LEFT_SURROUND 0x10 + #define XMA_SPEAKER_RIGHT_SURROUND 0x20 + #define XMA_SPEAKER_LEFT_BACK 0x40 + #define XMA_SPEAKER_RIGHT_BACK 0x80 +#endif + + +// Used in XMAWAVEFORMAT for per-stream data +typedef struct XMASTREAMFORMAT +{ + DWORD PsuedoBytesPerSec; // Used by the XMA encoder (typo preserved for legacy reasons) + DWORD SampleRate; // The stream's decoded sample rate (in XMA2 files, + // this is the same for all streams in the file). + DWORD LoopStart; // Bit offset of the frame containing the loop start + // point, relative to the beginning of the stream. + DWORD LoopEnd; // Bit offset of the frame containing the loop end. + BYTE SubframeData; // Two 4-bit numbers specifying the exact location of + // the loop points within the frames that contain them. + // SubframeEnd: Subframe of the loop end frame where + // the loop ends. Ranges from 0 to 3. + // SubframeSkip: Subframes to skip in the start frame to + // reach the loop. Ranges from 0 to 4. + BYTE Channels; // Number of channels in the stream (1 or 2) + WORD ChannelMask; // Spatial positions of the channels in the stream +} XMASTREAMFORMAT; + +// Legacy XMA1 format structure +typedef struct XMAWAVEFORMAT +{ + WORD FormatTag; // Audio format type (always WAVE_FORMAT_XMA) + WORD BitsPerSample; // Bit depth (currently required to be 16) + WORD EncodeOptions; // Options for XMA encoder/decoder + WORD LargestSkip; // Largest skip used in interleaving streams + WORD NumStreams; // Number of interleaved audio streams + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + BYTE Version; // XMA encoder version that generated the file. + // Always 3 or higher for XMA2 files. + XMASTREAMFORMAT XmaStreams[1]; // Per-stream format information; the actual + // array length is in the NumStreams field. +} XMAWAVEFORMAT; + + +// Used in XMA2WAVEFORMAT for per-stream data +typedef struct XMA2STREAMFORMAT +{ + BYTE Channels; // Number of channels in the stream (1 or 2) + BYTE RESERVED; // Reserved for future use + WORD ChannelMask; // Spatial positions of the channels in the stream +} XMA2STREAMFORMAT; + +// Legacy XMA2 format structure (big-endian byte ordering) +typedef struct XMA2WAVEFORMAT +{ + BYTE Version; // XMA encoder version that generated the file. + // Always 3 or higher for XMA2 files. + BYTE NumStreams; // Number of interleaved audio streams + BYTE RESERVED; // Reserved for future use + BYTE LoopCount; // Number of loop repetitions; 255 = infinite + DWORD LoopBegin; // Loop begin point, in samples + DWORD LoopEnd; // Loop end point, in samples + DWORD SampleRate; // The file's decoded sample rate + DWORD EncodeOptions; // Options for the XMA encoder/decoder + DWORD PsuedoBytesPerSec; // Used internally by the XMA encoder + DWORD BlockSizeInBytes; // Size in bytes of this file's XMA blocks (except + // possibly the last one). Always a multiple of + // 2Kb, since XMA blocks are arrays of 2Kb packets. + DWORD SamplesEncoded; // Total number of PCM samples encoded in this file + DWORD SamplesInSource; // Actual number of PCM samples in the source + // material used to generate this file + DWORD BlockCount; // Number of XMA blocks in this file (and hence + // also the number of entries in its seek table) + XMA2STREAMFORMAT Streams[1]; // Per-stream format information; the actual + // array length is in the NumStreams field. +} XMA2WAVEFORMAT; + +#endif // #ifndef WAVE_FORMAT_XMA + + + +/*************************************************************************** + * XMA packet structure (in big-endian form) + ***************************************************************************/ + +typedef struct XMA2PACKET +{ + int FrameCount : 6; // Number of XMA frames that begin in this packet + int FrameOffsetInBits : 15; // Bit of XmaData where the first complete frame begins + int PacketMetaData : 3; // Metadata stored in the packet (always 1 for XMA2) + int PacketSkipCount : 8; // How many packets belonging to other streams must be + // skipped to find the next packet belonging to this one + BYTE XmaData[XMA_BYTES_PER_PACKET - sizeof(DWORD)]; // XMA encoded data +} XMA2PACKET; + +// E.g. if the first DWORD of a packet is 0x30107902: +// +// 001100 000001000001111 001 00000010 +// | | | |____ Skip 2 packets to find the next one for this stream +// | | |___________ XMA2 signature (always 001) +// | |_____________________ First frame starts 527 bits into packet +// |________________________________ Packet contains 12 frames + + +// Helper functions to extract the fields above from an XMA packet. (Note that +// the bitfields cannot be read directly on little-endian architectures such as +// the Intel x86, as they are laid out in big-endian form.) + +__inline DWORD GetXmaPacketFrameCount(__in_bcount(1) const BYTE* pPacket) +{ + return (DWORD)(pPacket[0] >> 2); +} + +__inline DWORD GetXmaPacketFirstFrameOffsetInBits(__in_bcount(3) const BYTE* pPacket) +{ + return ((DWORD)(pPacket[0] & 0x3) << 13) | + ((DWORD)(pPacket[1]) << 5) | + ((DWORD)(pPacket[2]) >> 3); +} + +__inline DWORD GetXmaPacketMetadata(__in_bcount(3) const BYTE* pPacket) +{ + return (DWORD)(pPacket[2] & 0x7); +} + +__inline DWORD GetXmaPacketSkipCount(__in_bcount(4) const BYTE* pPacket) +{ + return (DWORD)(pPacket[3]); +} + + + +/*************************************************************************** + * XMA frame structure + ***************************************************************************/ + +// There is no way to represent the XMA frame as a C struct, since it is a +// variable-sized string of bits that need not be stored at a byte-aligned +// position in memory. This is the layout: +// +// XMAFRAME +// { +// LengthInBits: A 15-bit number representing the length of this frame. +// XmaData: Encoded XMA data; its size in bits is (LengthInBits - 15). +// } + +// Size in bits of the frame's initial LengthInBits field +#define XMA_BITS_IN_FRAME_LENGTH_FIELD 15 + +// Special LengthInBits value that marks an invalid final frame +#define XMA_FINAL_FRAME_MARKER 0x7FFF + + + +/*************************************************************************** + * XMA helper functions + ***************************************************************************/ + +// We define a local ASSERT macro to equal the global one if it exists. +// You can define XMA2DEFS_ASSERT in advance to override this default. +#ifndef XMA2DEFS_ASSERT + #ifdef ASSERT + #define XMA2DEFS_ASSERT ASSERT + #else + #define XMA2DEFS_ASSERT(a) /* No-op by default */ + #endif +#endif + + +// GetXmaBlockContainingSample: Use a given seek table to find the XMA block +// containing a given decoded sample. Note that the seek table entries in an +// XMA file are stored in big-endian form and may need to be converted prior +// to calling this function. + +__inline HRESULT GetXmaBlockContainingSample +( + DWORD nBlockCount, // Blocks in the file (= seek table entries) + __in_ecount(nBlockCount) const DWORD* pSeekTable, // Pointer to the seek table data + DWORD nDesiredSample, // Decoded sample to locate + __out DWORD* pnBlockContainingSample, // Index of the block containing the sample + __out DWORD* pnSampleOffsetWithinBlock // Position of the sample in this block +) +{ + DWORD nPreviousTotalSamples = 0; + DWORD nBlock; + DWORD nTotalSamplesSoFar; + + XMA2DEFS_ASSERT(pSeekTable); + XMA2DEFS_ASSERT(pnBlockContainingSample); + XMA2DEFS_ASSERT(pnSampleOffsetWithinBlock); + + for (nBlock = 0; nBlock < nBlockCount; ++nBlock) + { + nTotalSamplesSoFar = pSeekTable[nBlock]; + if (nTotalSamplesSoFar > nDesiredSample) + { + *pnBlockContainingSample = nBlock; + *pnSampleOffsetWithinBlock = nDesiredSample - nPreviousTotalSamples; + return S_OK; + } + nPreviousTotalSamples = nTotalSamplesSoFar; + } + + return E_FAIL; +} + + +// GetXmaFrameLengthInBits: Reads a given frame's LengthInBits field. + +__inline DWORD GetXmaFrameLengthInBits +( + __in_bcount(nBitPosition / 8 + 3) + __in const BYTE* pPacket, // Pointer to XMA packet[s] containing the frame + DWORD nBitPosition // Bit offset of the frame within this packet +) +{ + DWORD nRegion; + DWORD nBytePosition = nBitPosition / 8; + DWORD nBitOffset = nBitPosition % 8; + + if (nBitOffset < 2) // Only need to read 2 bytes (and might not be safe to read more) + { + nRegion = (DWORD)(pPacket[nBytePosition+0]) << 8 | + (DWORD)(pPacket[nBytePosition+1]); + return (nRegion >> (1 - nBitOffset)) & 0x7FFF; // Last 15 bits + } + else // Need to read 3 bytes + { + nRegion = (DWORD)(pPacket[nBytePosition+0]) << 16 | + (DWORD)(pPacket[nBytePosition+1]) << 8 | + (DWORD)(pPacket[nBytePosition+2]); + return (nRegion >> (9 - nBitOffset)) & 0x7FFF; // Last 15 bits + } +} + + +// GetXmaFrameBitPosition: Calculates the bit offset of a given frame within +// an XMA block or set of blocks. Returns 0 on failure. + +__inline DWORD GetXmaFrameBitPosition +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex, // Stream within which to seek + DWORD nDesiredFrame // Frame sought +) +{ + const BYTE* pCurrentPacket; + DWORD nPacketsExamined = 0; + DWORD nFrameCountSoFar = 0; + DWORD nFramesToSkip; + DWORD nFrameBitOffset; + + XMA2DEFS_ASSERT(pXmaData); + XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0); + + // Get the first XMA packet belonging to the desired stream, relying on the + // fact that the first packets for each stream are in consecutive order at + // the beginning of an XMA block. + + pCurrentPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET; + for (;;) + { + // If we have exceeded the size of the XMA data, return failure + if (pCurrentPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes) + { + return 0; + } + + // If the current packet contains the frame we are looking for... + if (nFrameCountSoFar + GetXmaPacketFrameCount(pCurrentPacket) > nDesiredFrame) + { + // See how many frames in this packet we need to skip to get to it + XMA2DEFS_ASSERT(nDesiredFrame >= nFrameCountSoFar); + nFramesToSkip = nDesiredFrame - nFrameCountSoFar; + + // Get the bit offset of the first frame in this packet + nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pCurrentPacket); + + // Advance nFrameBitOffset to the frame of interest + while (nFramesToSkip--) + { + nFrameBitOffset += GetXmaFrameLengthInBits(pCurrentPacket, nFrameBitOffset); + } + + // The bit offset to return is the number of bits from pXmaData to + // pCurrentPacket plus the bit offset of the frame of interest + return (DWORD)(pCurrentPacket - pXmaData) * 8 + nFrameBitOffset; + } + + // If we haven't found the right packet yet, advance our counters + ++nPacketsExamined; + nFrameCountSoFar += GetXmaPacketFrameCount(pCurrentPacket); + + // And skip to the next packet belonging to the same stream + pCurrentPacket += XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pCurrentPacket) + 1); + } +} + + +// GetLastXmaFrameBitPosition: Calculates the bit offset of the last complete +// frame in an XMA block or set of blocks. + +__inline DWORD GetLastXmaFrameBitPosition +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex // Stream within which to seek +) +{ + const BYTE* pLastPacket; + DWORD nBytesToNextPacket; + DWORD nFrameBitOffset; + DWORD nFramesInLastPacket; + + XMA2DEFS_ASSERT(pXmaData); + XMA2DEFS_ASSERT(nXmaDataBytes % XMA_BYTES_PER_PACKET == 0); + XMA2DEFS_ASSERT(nXmaDataBytes >= XMA_BYTES_PER_PACKET * (nStreamIndex + 1)); + + // Get the first XMA packet belonging to the desired stream, relying on the + // fact that the first packets for each stream are in consecutive order at + // the beginning of an XMA block. + pLastPacket = pXmaData + nStreamIndex * XMA_BYTES_PER_PACKET; + + // Search for the last packet belonging to the desired stream + for (;;) + { + nBytesToNextPacket = XMA_BYTES_PER_PACKET * (GetXmaPacketSkipCount(pLastPacket) + 1); + XMA2DEFS_ASSERT(nBytesToNextPacket); + if (pLastPacket + nBytesToNextPacket + XMA_BYTES_PER_PACKET > pXmaData + nXmaDataBytes) + { + break; // The next packet would extend beyond the end of pXmaData + } + pLastPacket += nBytesToNextPacket; + } + + // The last packet can sometimes have no seekable frames, in which case we + // have to use the previous one + if (GetXmaPacketFrameCount(pLastPacket) == 0) + { + pLastPacket -= nBytesToNextPacket; + } + + // Found the last packet. Get the bit offset of its first frame. + nFrameBitOffset = XMA_PACKET_HEADER_BITS + GetXmaPacketFirstFrameOffsetInBits(pLastPacket); + + // Traverse frames until we reach the last one + nFramesInLastPacket = GetXmaPacketFrameCount(pLastPacket); + while (--nFramesInLastPacket) + { + nFrameBitOffset += GetXmaFrameLengthInBits(pLastPacket, nFrameBitOffset); + } + + // The bit offset to return is the number of bits from pXmaData to + // pLastPacket plus the offset of the last frame in this packet. + return (DWORD)(pLastPacket - pXmaData) * 8 + nFrameBitOffset; +} + + +// GetXmaDecodePositionForSample: Obtains the information needed to make the +// decoder generate audio starting at a given sample position relative to the +// beginning of the given XMA block: the bit offset of the appropriate frame, +// and the right subframe within that frame. This data can be passed directly +// to the XMAPlaybackSetDecodePosition function. + +__inline HRESULT GetXmaDecodePositionForSample +( + __in_bcount(nXmaDataBytes) const BYTE* pXmaData, // Pointer to XMA block[s] + DWORD nXmaDataBytes, // Size of pXmaData in bytes + DWORD nStreamIndex, // Stream within which to seek + DWORD nDesiredSample, // Sample sought + __out DWORD* pnBitOffset, // Returns the bit offset within pXmaData of + // the frame containing the sample sought + __out DWORD* pnSubFrame // Returns the subframe containing the sample +) +{ + DWORD nDesiredFrame = nDesiredSample / XMA_SAMPLES_PER_FRAME; + DWORD nSubFrame = (nDesiredSample % XMA_SAMPLES_PER_FRAME) / XMA_SAMPLES_PER_SUBFRAME; + DWORD nBitOffset = GetXmaFrameBitPosition(pXmaData, nXmaDataBytes, nStreamIndex, nDesiredFrame); + + XMA2DEFS_ASSERT(pnBitOffset); + XMA2DEFS_ASSERT(pnSubFrame); + + if (nBitOffset) + { + *pnBitOffset = nBitOffset; + *pnSubFrame = nSubFrame; + return S_OK; + } + else + { + return E_FAIL; + } +} + + +// GetXmaSampleRate: Obtains the legal XMA sample rate (24, 32, 44.1 or 48Khz) +// corresponding to a generic sample rate. + +__inline DWORD GetXmaSampleRate(DWORD dwGeneralRate) +{ + DWORD dwXmaRate = 48000; // Default XMA rate for all rates above 44100Hz + + if (dwGeneralRate <= 24000) dwXmaRate = 24000; + else if (dwGeneralRate <= 32000) dwXmaRate = 32000; + else if (dwGeneralRate <= 44100) dwXmaRate = 44100; + + return dwXmaRate; +} + + +// Functions to convert between WAVEFORMATEXTENSIBLE channel masks (combinations +// of the SPEAKER_xxx flags defined in audiodefs.h) and XMA channel masks (which +// are limited to eight possible speaker positions: left, right, center, low +// frequency, side left, side right, back left and back right). + +__inline DWORD GetStandardChannelMaskFromXmaMask(BYTE bXmaMask) +{ + DWORD dwStandardMask = 0; + + if (bXmaMask & XMA_SPEAKER_LEFT) dwStandardMask |= SPEAKER_FRONT_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT) dwStandardMask |= SPEAKER_FRONT_RIGHT; + if (bXmaMask & XMA_SPEAKER_CENTER) dwStandardMask |= SPEAKER_FRONT_CENTER; + if (bXmaMask & XMA_SPEAKER_LFE) dwStandardMask |= SPEAKER_LOW_FREQUENCY; + if (bXmaMask & XMA_SPEAKER_LEFT_SURROUND) dwStandardMask |= SPEAKER_SIDE_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT_SURROUND) dwStandardMask |= SPEAKER_SIDE_RIGHT; + if (bXmaMask & XMA_SPEAKER_LEFT_BACK) dwStandardMask |= SPEAKER_BACK_LEFT; + if (bXmaMask & XMA_SPEAKER_RIGHT_BACK) dwStandardMask |= SPEAKER_BACK_RIGHT; + + return dwStandardMask; +} + +__inline BYTE GetXmaChannelMaskFromStandardMask(DWORD dwStandardMask) +{ + BYTE bXmaMask = 0; + + if (dwStandardMask & SPEAKER_FRONT_LEFT) bXmaMask |= XMA_SPEAKER_LEFT; + if (dwStandardMask & SPEAKER_FRONT_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT; + if (dwStandardMask & SPEAKER_FRONT_CENTER) bXmaMask |= XMA_SPEAKER_CENTER; + if (dwStandardMask & SPEAKER_LOW_FREQUENCY) bXmaMask |= XMA_SPEAKER_LFE; + if (dwStandardMask & SPEAKER_SIDE_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_SURROUND; + if (dwStandardMask & SPEAKER_SIDE_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_SURROUND; + if (dwStandardMask & SPEAKER_BACK_LEFT) bXmaMask |= XMA_SPEAKER_LEFT_BACK; + if (dwStandardMask & SPEAKER_BACK_RIGHT) bXmaMask |= XMA_SPEAKER_RIGHT_BACK; + + return bXmaMask; +} + + +// LocalizeXma2Format: Modifies a XMA2WAVEFORMATEX structure in place to comply +// with the current platform's byte-ordering rules (little- or big-endian). + +__inline HRESULT LocalizeXma2Format(__inout XMA2WAVEFORMATEX* pXma2Format) +{ + #define XMASWAP2BYTES(n) ((WORD)(((n) >> 8) | (((n) & 0xff) << 8))) + #define XMASWAP4BYTES(n) ((DWORD)((n) >> 24 | (n) << 24 | ((n) & 0xff00) << 8 | ((n) & 0xff0000) >> 8)) + + if (pXma2Format->wfx.wFormatTag == WAVE_FORMAT_XMA2) + { + return S_OK; + } + else if (XMASWAP2BYTES(pXma2Format->wfx.wFormatTag) == WAVE_FORMAT_XMA2) + { + pXma2Format->wfx.wFormatTag = XMASWAP2BYTES(pXma2Format->wfx.wFormatTag); + pXma2Format->wfx.nChannels = XMASWAP2BYTES(pXma2Format->wfx.nChannels); + pXma2Format->wfx.nSamplesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nSamplesPerSec); + pXma2Format->wfx.nAvgBytesPerSec = XMASWAP4BYTES(pXma2Format->wfx.nAvgBytesPerSec); + pXma2Format->wfx.nBlockAlign = XMASWAP2BYTES(pXma2Format->wfx.nBlockAlign); + pXma2Format->wfx.wBitsPerSample = XMASWAP2BYTES(pXma2Format->wfx.wBitsPerSample); + pXma2Format->wfx.cbSize = XMASWAP2BYTES(pXma2Format->wfx.cbSize); + pXma2Format->NumStreams = XMASWAP2BYTES(pXma2Format->NumStreams); + pXma2Format->ChannelMask = XMASWAP4BYTES(pXma2Format->ChannelMask); + pXma2Format->SamplesEncoded = XMASWAP4BYTES(pXma2Format->SamplesEncoded); + pXma2Format->BytesPerBlock = XMASWAP4BYTES(pXma2Format->BytesPerBlock); + pXma2Format->PlayBegin = XMASWAP4BYTES(pXma2Format->PlayBegin); + pXma2Format->PlayLength = XMASWAP4BYTES(pXma2Format->PlayLength); + pXma2Format->LoopBegin = XMASWAP4BYTES(pXma2Format->LoopBegin); + pXma2Format->LoopLength = XMASWAP4BYTES(pXma2Format->LoopLength); + pXma2Format->BlockCount = XMASWAP2BYTES(pXma2Format->BlockCount); + return S_OK; + } + else + { + return E_FAIL; // Not a recognizable XMA2 format + } + + #undef XMASWAP2BYTES + #undef XMASWAP4BYTES +} + + +#endif // #ifndef __XMA2DEFS_INCLUDED__ diff --git a/src/depend/scripts/build_details.cpp b/src/depend/scripts/build_details.cpp new file mode 100644 index 00000000..70dd62e8 --- /dev/null +++ b/src/depend/scripts/build_details.cpp @@ -0,0 +1,42 @@ +#include + +int main(int /*argc*/, char** /*argv*/) +{ + printf("#define BUILD_TIME %s\n", __TIME__); + printf("#define BUILD_DATE %s\n", __DATE__); + +#ifdef _UNICODE + printf("#define BUILD_CHAR Unicode\n"); +#else + printf("#define BUILD_CHAR ANSI\n"); +#endif + +#if !defined BUILD_X64_EXE + printf("#define BUILD_CPU X86\n"); +#else + printf("#define BUILD_CPU X64\n"); +#endif + +#if defined __GNUC__ + printf("#define BUILD_COMP GCC %i.%i.%i\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +#elif defined _MSC_VER + #if _MSC_VER >= 1300 && _MSC_VER < 1310 + printf("#define BUILD_COMP Visual C++ 2002\n"); + #elif _MSC_VER >= 1310 && _MSC_VER < 1320 + printf("#define BUILD_COMP Visual C++ 2003\n"); + #else + printf("#define BUILD_COMP Visual C++ %i.%i\n", _MSC_VER / 100 - 6, _MSC_VER % 100 / 10); + #endif +#else + printf("#define BUILD_COMP Unknown compiler\n"); +#endif + +// Visual C's resource compiler doesn't define _MSC_VER, but we need it for VERSION resources +#ifdef _MSC_VER + printf("#ifndef _MSC_VER\n"); + printf(" #define _MSC_VER %i\n", _MSC_VER); + printf("#endif\n"); +#endif + + return 0; +} diff --git a/src/depend/scripts/cave_sprite_func.pl b/src/depend/scripts/cave_sprite_func.pl new file mode 100644 index 00000000..b32a3c31 --- /dev/null +++ b/src/depend/scripts/cave_sprite_func.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl -w + +use strict; + +my $OutfileFun; +my $OutfileTab; + +# Process command line arguments +if ( $ARGV[0] =~ /^-o/i ) { + if ( $ARGV[0] =~ /^-o$/i ) { + $OutfileFun = $ARGV[1]; + } else { + $ARGV[0] =~ /(?<=-o)(.*)/i; + $OutfileFun = $1; + } +} + +unless ( $OutfileFun ) { + die "Usage: $0 -o \n\n"; +} + +$OutfileTab = $OutfileFun; +$OutfileTab =~ s/(\.\w+)/_table$1/; + +open( OUTFILEFUN, ">$OutfileFun" ) or die "\nError: Couldn't open OUTPUT file $OutfileFun: $!"; +open( OUTFILETAB, ">$OutfileTab" ) or die "\nError: Couldn't open OUTPUT file $OutfileTab: $!"; + +print "Generating $OutfileFun & $OutfileTab...\n"; + +# Generate optimized functions and a table with the function names + +print OUTFILEFUN "#define EIGHTBIT 1\n"; +print OUTFILEFUN "#define ROT 0\n\n"; +print OUTFILEFUN "#define BPP 16\n"; + +print OUTFILETAB "// Table with all function addresses.\n"; +print OUTFILETAB "static RenderSpriteFunction RenderSpriteFunctionTable[] = {\n"; + +for ( my $Size = 320; $Size <= 384; $Size += 64 ) { + my @ZBuffer = ( "_NOZBUFFER", "_RZBUFFER", "_WZBUFFER", "_RWZBUFFER" ); + my $Flip; + my $Zoom; + + print OUTFILEFUN "#define XSIZE $Size\n"; + + my $FunctionName = "&RenderSprite16_" . $Size . "_ROT0"; + + # No scaling + + print OUTFILEFUN "#define ZOOM 0\n"; + + for ( my $Function = 0; $Function < 8; $Function++ ) { + if ( ($Function & 3) == 0 ) { + print OUTFILEFUN "#define XFLIP " . (($Function & 4) / 4) . "\n"; + + if ( ($Function & 4) == 0 ) { + $Flip = "_NOFLIP"; + } else { + $Flip = "_FLIPX"; + } + + print OUTFILETAB "\t"; + } + + print OUTFILEFUN "#define ZBUFFER " . ($Function & 3) . "\n"; + + print OUTFILEFUN "#include \"cave_sprite_render.h\"\n"; + + print OUTFILETAB $FunctionName . $Flip . "_NOZOOM_CLIPX" . $ZBuffer[$Function & 3] . "_256, "; + + print OUTFILEFUN "#undef ZBUFFER\n"; + + if ( ($Function & 3) == 3 ) { + print OUTFILEFUN "#undef XFLIP\n"; + + print OUTFILETAB "\n"; + } + } + + print OUTFILEFUN "#undef ZOOM\n\n"; + + # Scale up/down + + print OUTFILEFUN "#define XFLIP 0\n"; + + for ( my $Function = 0; $Function < 8; $Function++ ) { + if ( ($Function & 3) == 0 ) { + print OUTFILEFUN "#define ZOOM " . (1 + ($Function & 4) / 4) . "\n"; + + if ( ($Function & 4) == 0 ) { + $Zoom = "_ZOOMOUT"; + } else { + $Zoom = "_ZOOMIN"; + } + + print OUTFILETAB "\t"; + } + print OUTFILEFUN "#define ZBUFFER " . ($Function & 3) . "\n"; + print OUTFILEFUN "#include \"cave_sprite_render_zoom.h\"\n"; + print OUTFILEFUN "#undef ZBUFFER\n"; + + print OUTFILETAB $FunctionName . "_NOFLIP" . $Zoom . "_NOCLIP" . $ZBuffer[$Function & 3] . "_256, "; + + if ( ($Function & 3) == 3 ) { + print OUTFILEFUN "#undef ZOOM\n\n"; + + print OUTFILETAB "\n"; + } + } + + print OUTFILEFUN "#undef XFLIP\n"; + print OUTFILEFUN "#undef XSIZE\n\n"; +} + +print OUTFILEFUN "#undef BPP\n\n"; +print OUTFILEFUN "#undef ROT\n\n"; +print OUTFILEFUN "#undef EIGHTBIT\n\n"; + +print OUTFILETAB "};\n\n"; + +$OutfileTab =~ /(?:.*[\\\/])(.*)/; +print OUTFILEFUN "#include \"$1\"\n"; + +print OUTFILETAB "static RenderSpriteFunction* RenderSprite_ROT0[2] = {\n\t&RenderSpriteFunctionTable[0],\n\t&RenderSpriteFunctionTable[16]\n};\n"; + +close( OUTFILETAB ); +close( OUTFILEFUN ); diff --git a/src/depend/scripts/cave_tile_func.pl b/src/depend/scripts/cave_tile_func.pl new file mode 100644 index 00000000..e670e6a7 --- /dev/null +++ b/src/depend/scripts/cave_tile_func.pl @@ -0,0 +1,103 @@ +#!/usr/bin/perl -w + +use strict; + +my $OutfileFun; +my $OutfileTab; + +# Process command line arguments +if ( $ARGV[0] =~ /^-o/i ) { + if ( $ARGV[0] =~ /^-o$/i ) { + $OutfileFun = $ARGV[1]; + } else { + $ARGV[0] =~ /(?<=-o)(.*)/i; + $OutfileFun = $1; + } +} + +unless ( $OutfileFun ) { + die "Usage: $0 -o \n\n"; +} + +$OutfileTab = $OutfileFun; +$OutfileTab =~ s/(\.\w+)/_table$1/; + +open( OUTFILEFUN, ">$OutfileFun" ) or die "\nError: Couldn't open OUTPUT file $OutfileFun: $!"; +open( OUTFILETAB, ">$OutfileTab" ) or die "\nError: Couldn't open OUTPUT file $OutfileTab: $!"; + +print "Generating $OutfileFun & $OutfileTab...\n"; + +# Generate optimized functions and a table with the function names + +print OUTFILEFUN "#define XFLIP 0\n"; +print OUTFILEFUN "#define YFLIP 0\n"; +print OUTFILEFUN "#define ROT 0\n\n"; +print OUTFILEFUN "#define BPP 16\n"; + +print OUTFILETAB "// Table with all function addresses.\n"; +print OUTFILETAB "static RenderTileFunction RenderTileFunctionTable[] = {\n"; + +for ( my $Size = 320; $Size <= 384; $Size += 64 ) { + my $RowScroll; + my $RowSelect; + + print OUTFILEFUN "#define XSIZE $Size\n"; + print OUTFILEFUN "#define EIGHTBIT 1\n"; + + my $FunctionName = "&RenderTile16_" . $Size . "_ROT0_NOFLIP"; + + for ( my $Function = 0; $Function < 3; $Function++ ) { + if ( ($Function & 1) == 0 ) { + $RowScroll = "_NOROWSCROLL"; + + if ( ($Function & 2) == 0 ) { + $RowSelect = "_NOROWSELECT"; + } else { + $RowSelect = "_ROWSELECT"; + } + } else { + $RowScroll = "_ROWSCROLL"; + } + + print OUTFILEFUN "#define ROWSCROLL " . ($Function & 1) . "\n"; + print OUTFILEFUN "#define ROWSELECT " . (($Function & 2) / 2) . "\n"; + + print OUTFILETAB "\t"; + + print OUTFILEFUN "#define DOCLIP 0\n"; + print OUTFILEFUN "#include \"cave_tile_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $RowScroll . $RowSelect . "_NOCLIP_256, "; + + print OUTFILEFUN "#define DOCLIP 1\n"; + print OUTFILEFUN "#include \"cave_tile_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $RowScroll . $RowSelect . "_CLIP_256, "; + + print OUTFILEFUN "#undef ROWSELECT\n"; + print OUTFILEFUN "#undef ROWSCROLL\n"; + + print OUTFILETAB "\n"; + } + print OUTFILEFUN "#undef EIGHTBIT\n\n"; + print OUTFILEFUN "#undef XSIZE\n\n"; +} + +print OUTFILEFUN "#undef BPP\n\n"; +print OUTFILEFUN "#undef ROT\n\n"; + +print OUTFILEFUN "#undef YFLIP\n"; +print OUTFILEFUN "#undef XFLIP\n\n"; + +print OUTFILETAB "};\n\n"; + +$OutfileTab =~ /(?:.*[\\\/])(.*)/; +print OUTFILEFUN "#include \"$1\"\n"; + +print OUTFILETAB "static RenderTileFunction* RenderTile_ROT0[2] = {\n\t&RenderTileFunctionTable[0],\n\t&RenderTileFunctionTable[6]\n};\n"; + +close( OUTFILETAB ); +close( OUTFILEFUN ); + diff --git a/src/depend/scripts/fixrc.pl b/src/depend/scripts/fixrc.pl new file mode 100644 index 00000000..f7540cc8 --- /dev/null +++ b/src/depend/scripts/fixrc.pl @@ -0,0 +1,92 @@ +#!/usr/bin/perl -w + +# Fixes .rc files generated by Microsoft Developer Studio so that windres will +# correctly interpret them. To ensure correct paths to files, execute this script +# from the same place you will execute windres. + +use strict; + +my $Infile; +my $Outfile; +my $PathPrefix; + +# Process command line arguments +for ( my $i = 0; $i < scalar @ARGV; $i++ ) {{ + + # Output file + if ( $ARGV[$i] =~ /^-o/i ) { + if ( $ARGV[$i] =~ /^-o$/i ) { + $i++; + if ( $i < scalar @ARGV ) { + $Outfile = $ARGV[$i]; + } + } else { + $ARGV[$i] =~ /(?<=-o)(.*)/i; + $Outfile = $1; + } + next; + } + + # Input file + $Infile = $ARGV[$i]; +}} + +unless ( $Infile and $Outfile ) { + die "Usage: $0 -o \n\n"; +} + +if ( $Infile =~ /.*(?=\/.*$)/ ) { + $PathPrefix = "$&/"; +} else { + $PathPrefix = ""; +} + +open( INFILE, $Infile ) or die "\nError: Couldn't open INPUT file $Infile: $!"; +open( OUTFILE, ">$Outfile" ) or die "\nError: Couldn't open OUTPUT file $Outfile: $!"; + +print "Converting $Infile for use with windres...\n"; + +# first define missing constants and include needed files +print OUTFILE << "marker"; +// This file is a windres compatible version of $Infile +// It was fixed by $0 (perl $]) + +// afxres.h cannot be redistributed, so define constants and include files needed here +#ifndef _MSC_VER + + #ifndef RC_INVOKED + #define RC_INVOKED + #endif + + #include + #include + + #ifndef IDC_STATIC + #define IDC_STATIC (-1) + #endif + +#endif + +marker + +while ( my $line = ) { + chomp $line; + if ( $line =~ /^\#include \"afxres.h\"/ ) { + print OUTFILE "#ifdef _MSC_VER\n"; + print OUTFILE "$line\n"; + print OUTFILE "#endif\n"; + } else { + # add NOT WS_POPUP to all windows with WS_CHILD specified + $line =~ s/(? [-l ] [...]\n\n"; +} + +open( OUTFILE, ">$Outfile" ) or die "\nError: Couldn't open OUTPUT file $Outfile $!"; + +print "Generating gamelist in $Outfile...\n"; + +# Build a list of all drivers +foreach my $filename ( @Filelist ) { + open( INFILE, $filename ) or die "\nError: Couldn't read $filename $!"; + while ( my $line = ) { + + # Strip C++ style // comments + if ( $line =~ /(.*?)\/\// ) { + $line = $1; + } + + # Strip C style /* comments */ + if ( $line =~ /(.*)\/\*/ ) { + my $temp = $1; + while ( $line and !($line =~ /\*\/(.*)/) ) { + $line = ; + } + $line = $temp; + substr( $line, length( $line ) ) = $1; + } + + # get included .cpp.h files in the same directory + if ( $line =~ /^\s*#include "d_\w*.h"/ ) { + $line =~ /^\s*#include "(.*)"/; + my $newfile = $1; + $filename =~ /(.*[\/\\])[^\/\\]/; + push( @Filelist, "$1$newfile" ); + } + + if ( $line =~ /struct\s+BurnDriver([D|X]?)\s+(\w+)(.*)/ ) { + + # We're at the start of a BurnDriver declaration + + # Create a hash key with the name of the structure, + # Fill the first element of the array with the driver status + my $name = $2; + $Drivers{$name}[0] = "$1"; + + # Read the Burndriver structure into a variable + my $struct = $3; + do { + $line = ; + + # Strip C++ style // comments + if ( $line =~ /(.*?)\/\// ) { + $line = $1; + } + + substr( $struct, length( $struct ) ) = $line; + } until $line =~ /;/; + + # Strip anything after the ; + $struct =~ /(.*;)/s; + $struct = $1; + + # Strip C style /* comments */ + while ( $struct =~ /(.*)\/\*.*?\*\/(.*)/s ) { + $struct = $1; + substr( $struct, length( $struct ) ) = $2; + } + + # We now have the complete Burndriver structure without comments + + # Extract the strings from the variable + $struct =~ /\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0)\s*,\s*(".*"|null|0),\s*(L".*"|null|0)\s*,\s*(L".*"|null|0)\s*,\s*(L".*"|null|0)\s*,\s*(L".*"|null|0)\s*,\s*(\d|[^,]*)/si; + + $Drivers{$name}[1] = $1; # Name + $Drivers{$name}[2] = $6; # Full name + $Drivers{$name}[3] = $7; # Remarks + $Drivers{$name}[4] = $8; # Company + $Drivers{$name}[5] = $9; # Hardware + $Drivers{$name}[6] = $5; # Year of release + $Drivers{$name}[7] = $2; # Parent + + if ( $14 ne "1" && ($14 =~ /BDF_GAME_WORKING/) == 0 ) { # Working status + $Drivers{$name}[8] = "NOT WORKING"; + } else { + $Drivers{$name}[8] = ""; + } + $Drivers{$name}[9] = "$filename"; # Filename + + # Convert NULL/null/0 to empty string or remove quotes + foreach $line ( @{$Drivers{$name}} ) { + if ( $line =~ /^(null|NULL|0)/ ) { + $line = ""; + } else { + $line =~ /(^"?)(.*)\1/; + $line = $2; + } + } + + # We only want the 1st name + $Drivers{$name}[2] =~ /(.*)\\0.*/; + $Drivers{$name}[2] = $1; + + $Drivers{$name}[10] = $Drivers{$name}[2]; + if ( $struct =~ /BDF_PROTOTYPE/ || $struct =~ /BDF_BOOTLEG/ || $Drivers{$name}[3] ne "" ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . " ["; + } + if ( $struct =~ /BDF_PROTOTYPE/ ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . "Prototype"; + if ( $struct =~ /BDF_BOOTLEG/ || $Drivers{$name}[3] ne "" ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . ", "; + } + } + if ( $struct =~ /BDF_BOOTLEG/ ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . "Bootleg"; + if ( $Drivers{$name}[3] ne "" ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . ", "; + } + } + if ( $Drivers{$name}[3] ne "" ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . "$Drivers{$name}[3]"; + } + if ( $struct =~ /BDF_PROTOTYPE/ || $struct =~ /BDF_BOOTLEG/ || $Drivers{$name}[3] ne "" ) { + $Drivers{$name}[10] = "$Drivers{$name}[10]" . "]"; + } + } + } + close( INFILE ); +} + +# Sort the list of drivers using the decorated game name as the key +@Driverlist = sort { + lc( $Drivers{$a}[10] ) cmp lc( $Drivers{$b}[10] ); +} keys %Drivers; + +# first define needed constants and include needed files +print OUTFILE << "CPPEND"; +// This file was generated by $0 (perl $]) + +// Declaration of all drivers +#define DRV extern struct BurnDriver +CPPEND + +my $Debug = 0; +foreach my $name ( @Driverlist ) { + + if ( $Drivers{$name}[0] eq "X" ) { + print OUTFILE "//"; + } else { + if ( $Drivers{$name}[0] eq "D" ) { + unless ( $Debug == 1) { + $Debug = 1; + print OUTFILE "#if defined FBA_DEBUG\n"; + } + } else { + if ( $Debug == 1 ) { + $Debug = 0; + print OUTFILE "#endif\n"; + } + } + print OUTFILE "DRV"; + } + print OUTFILE "\t\t$name;"; + if ( $Drivers{$name}[0] eq "D" or $Drivers{$name}[0] eq "X" ) { + my $column = int( (9 + length( $name )) / 4 ); + while ( $column < 8 ) { + print OUTFILE "\t"; + $column ++; + } + print OUTFILE "// "; + if ( $Drivers{$name}[3] ) { + print OUTFILE "$Drivers{$name}[3]"; + } else { + print OUTFILE "no comment"; + } + if ( $Drivers{$name}[8] ) { + print OUTFILE " [$Drivers{$name}[8]]"; + } + print OUTFILE "\n"; + } else { + print OUTFILE "\n"; + } +} +if ( $Debug == 1 ) { + print OUTFILE "#endif\n"; +} + +print OUTFILE << "CPPEND"; +#undef DRV + +// Structure containing addresses of all drivers +// Needs to be kept sorted (using the full game name as the key) to prevent problems with the gamelist in Kaillera +static struct BurnDriver* pDriver[] = { +CPPEND + +$Debug = 0; +foreach my $name ( @Driverlist ) { + if ( $Drivers{$name}[0] eq "X" ) { + print OUTFILE "//"; + } else { + if ( $Drivers{$name}[0] eq "D" ) { + unless ( $Debug == 1) { + $Debug = 1; + print OUTFILE "#if defined FBA_DEBUG\n"; + } + } else { + if ( $Debug == 1 ) { + $Debug = 0; + print OUTFILE "#endif\n"; + } + } + } + print OUTFILE "\t&$name,"; + my $column = int( (6 + length( $name )) / 4 ); + while ( $column < 8 ) { + print OUTFILE "\t"; + $column++; + } + print OUTFILE "// $Drivers{$name}[2]"; + if ( $Drivers{$name}[0] eq "D" or $Drivers{$name}[0] eq "X" ) { + print OUTFILE " ["; + if ( $Drivers{$name}[3] ) { + print OUTFILE "$Drivers{$name}[3]"; + } else { + print OUTFILE "no comment"; + } + if ( $Drivers{$name}[8] ) { + print OUTFILE ", $Drivers{$name}[8]"; + } + print OUTFILE "]\n"; + } else { + if ( $Drivers{$name}[8] ) { + print OUTFILE " ["; + if ( $Drivers{$name}[3] ) { + print OUTFILE "$Drivers{$name}[3]"; + } else { + print OUTFILE "no comment"; + } + print OUTFILE ", $Drivers{$name}[8]]"; + } + print OUTFILE "\n"; + } +} +if ( $Debug == 1 ) { + print OUTFILE "#endif\n"; +} + +print OUTFILE "};\n"; + +close( OUTFILE ); + +if ( $Listfile ) { + + open( OUTFILE, ">$Listfile" ) or die "\nError: Couldn't open OUTPUT file $Listfile $!"; + + print "Generating gamelist.txt...\n"; + + print OUTFILE "This list contains all games supported by FB Alpha.\x0d\x0a\x0d\x0a"; + + print OUTFILE scalar @Driverlist . " games supported in total; "; + print OUTFILE "X = excluded from build; "; + print OUTFILE "D = included in debug build only; "; + print OUTFILE "NW = not working\x0d\x0a\x0d\x0a"; + + print OUTFILE " name\t\t status full name\t\t\t\t\t\t parent\t year\t company\t hardware\t remarks\x0d\x0a"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------+\x0d\x0a"; + + my $Text; + + foreach my $name ( @Driverlist ) { + + print OUTFILE "| $Drivers{$name}[1]"; + my $column = int( (2 + length( $Drivers{$name}[1] )) / 8 ); + while ( $column < 2 ) { + print OUTFILE "\t"; + $column++; + } + + print OUTFILE "| "; + if ( $Drivers{$name}[0] ) { + print OUTFILE "$Drivers{$name}[0]"; + } else { + print OUTFILE " "; + } + if ( $Drivers{$name}[8] ) { + print OUTFILE " NW"; + } + print OUTFILE "\t"; + $column++; + + $Text = substr( $Drivers{$name}[2], 0, 54); + print OUTFILE "| $Text"; + $column += int( (2 + length( $Text )) / 8 ); + while ( $column < 10 ) { + print OUTFILE "\t"; + $column++; + } + + print OUTFILE "| $Drivers{$name}[7]"; + $column += int( (2 + length( $Drivers{$name}[7] )) / 8 ); + while ( $column < 12 ) { + print OUTFILE "\t"; + $column++; + } + print OUTFILE "| $Drivers{$name}[6]"; + $column += int( (2 + length( $Drivers{$name}[6] )) / 8 ); + while ( $column < 13 ) { + print OUTFILE "\t"; + $column++; + } + + $Text = substr( $Drivers{$name}[4], 0, 14); + print OUTFILE "| $Text"; + $column += int( (2 + length( $Text )) / 8 ); + while ( $column < 15 ) { + print OUTFILE "\t"; + $column++; + } + + $Text = substr( $Drivers{$name}[5], 0, 14); + print OUTFILE "| $Text"; + $column += int( (2 + length( $Text )) / 8 ); + while ( $column < 17 ) { + print OUTFILE "\t"; + $column++; + } + + $Text = substr( $Drivers{$name}[3], 0, 38); + print OUTFILE "| $Text"; + $column += int( ( 2 + length( $Text )) / 8 ); + while ( $column < 22 ) { + print OUTFILE "\t"; + $column++; + } + print OUTFILE "|\x0d\x0a"; + } + + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "+-------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------"; + print OUTFILE "--------+\x0d\x0a"; + + close( OUTFILE ); +} diff --git a/src/depend/scripts/license2rtf.pl b/src/depend/scripts/license2rtf.pl new file mode 100644 index 00000000..4e25536d --- /dev/null +++ b/src/depend/scripts/license2rtf.pl @@ -0,0 +1,115 @@ +#!/usr/bin/perl -w + +use strict; + +my $Outfile; +my $Infile; + +my $Font = "Tahoma"; +my $FontSize = 16; + +my $escape = 0; + +my %FontFamilies = ("Tahoma", "swiss", + "Times New Roman", "roman" +); + +# Process command line arguments +for ( my $i = 0; $i < scalar @ARGV; $i++ ) {{ + + # Output file + if ( $ARGV[$i] =~ /^-o/i ) { + if ( $ARGV[$i] =~ /^-o$/i ) { + $i++; + if ( $i < scalar @ARGV ) { + $Outfile = $ARGV[$i]; + } + } else { + $ARGV[$i] =~ /(?<=-o)(.*)/i; + $Outfile = $1; + } + next; + } + # Font + if ( $ARGV[$i] =~ /^-f/i ) { + if ( $ARGV[$i] =~ /^-f$/i ) { + $i++; + if ( $i < scalar @ARGV ) { + $Font = $ARGV[$i]; + } + } else { + $ARGV[$i] =~ /(?<=-f)(.*)/i; + $Font = $1; + } + next; + } + # Font size + if ( $ARGV[$i] =~ /^-s/i ) { + if ( $ARGV[$i] =~ /^-s$/i ) { + $i++; + if ( $i < scalar @ARGV ) { + $FontSize = $ARGV[$i]; + } + } else { + $ARGV[$i] =~ /(?<=-s)(.*)/i; + $FontSize = $1; + } + next; + } + if ( $ARGV[$i] =~ /^-esc/i ) { + $escape = 1; + } + + $Infile = $ARGV[$i]; + next; +}} + +unless ( $Outfile and $Font and $FontSize and $Infile ) { + die "Usage: $0 -o [-f -s -escape]\n\n"; +} + +open( INFILE, $Infile ) or die "\nError: Couldn't open INPUT file $Infile $!"; +open( OUTFILE, ">$Outfile" ) or die "\nError: Couldn't open OUTPUT file $Outfile $!"; + +print "Generating $Outfile...\n"; + +print OUTFILE "{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl(\\f0\\f$FontFamilies{$Font}\\fprq2 $Font;)}{\\colortbl\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green0\\blue191;}\\deflang1033\\horzdoc\\fromtext\\pard\\plain\\f0\\fs$FontSize"; + +while ( my $line = ) { + + # kill line endings (Cygin perl has problems with chomp) + $line =~ s/[\r\n]//gm; + + $line = "$line\\par"; + + # if a paragraph starts with " - " treat it as a bulleted paragraph + if ($line =~ /^\s-\s/) { + $line =~ s/^\s-\s//; + $line = "\\pard{\\*\\pn\\pnlvlblt\\pnindent0{\\pntxtb\\\'B7}}\\fi-144\\li144 $line\\pard"; + } + + # highlight URLs + $line =~ s/(http:\/\/[\w~\/\.\-]*)/\\cf2 $1\\cf0/g; + + # if a paragraph starts with "DISCLAIMER:" make the text bold and red + if ($line =~ /^DISCLAIMER/) { + $line = "\\cf1\\b $line\\b0\\cf0"; + } + + # if a paragraph starts with a quote make the text italic + if ($line =~ /^\"/) { + $line = "\\i $line\\i0"; + } + + if ($escape) { + # Escape quotes and backslashes + $line =~ s/([\"\\])/\$1/g; + } + + print OUTFILE "$line "; +} + +print OUTFILE "}"; + +close( OUTFILE ); +close( INFILE ); diff --git a/src/depend/scripts/neo_sprite_func.pl b/src/depend/scripts/neo_sprite_func.pl new file mode 100644 index 00000000..0b4679f1 --- /dev/null +++ b/src/depend/scripts/neo_sprite_func.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl -w + +use strict; + +my $OutfileFun; +my $OutfileTab; + +# Process command line arguments +if ( $ARGV[0] =~ /^-o/i ) { + if ( $ARGV[0] =~ /^-o$/i ) { + $OutfileFun = $ARGV[1]; + } else { + $ARGV[0] =~ /(?<=-o)(.*)/i; + $OutfileFun = $1; + } +} + +unless ( $OutfileFun ) { + die "Usage: $0 -o \n\n"; +} + +$OutfileTab = $OutfileFun; +$OutfileTab =~ s/(\.\w+)/_table$1/; + +open( OUTFILEFUN, ">$OutfileFun" ) or die "\nError: Couldn't open OUTPUT file $OutfileFun: $!"; +open( OUTFILETAB, ">$OutfileTab" ) or die "\nError: Couldn't open OUTPUT file $OutfileTab: $!"; + +print "Generating $OutfileFun & $OutfileTab...\n"; + +# Generate optimized functions and a table with the function names + +print OUTFILETAB "// Table with all function addresses.\n"; +print OUTFILETAB "static RenderBankFunction RenderBankFunctionTable[] = {\n"; + +print OUTFILEFUN "#define ISOPAQUE 0\n\n"; + +for ( my $Bitdepth = 16; $Bitdepth <= 32; $Bitdepth += 8 ) { + print OUTFILEFUN "// " . $Bitdepth . "-bit rendering functions.\n"; + print OUTFILEFUN "#define BPP $Bitdepth\n\n"; + + my $FunctionName = "&RenderBank" . $Bitdepth; + my $DoClip; + + for ( my $Function = 0; $Function < 32; $Function++ ) { + if ( ($Function & 15) == 0 ) { + print OUTFILEFUN "#define DOCLIP " . ($Function & 16) / 16 . "\n"; + + if ( ($Function & 16) == 0 ) { + $DoClip = "_NOCLIP"; + } else { + $DoClip = "_CLIP"; + } + print OUTFILETAB "\t"; + } + + print OUTFILEFUN "#define XZOOM " . ($Function & 15) . "\n"; + print OUTFILEFUN "#include \"neo_sprite_render.h\"\n"; + print OUTFILEFUN "#undef XZOOM\n"; + + print OUTFILETAB "$FunctionName" . "_ZOOM" . ($Function & 15) . $DoClip . "_TRANS, "; + + if ( ($Function & 15) == 15 ) { + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB "\n"; + } + + } + print OUTFILEFUN "#undef BPP\n\n"; +} +print OUTFILEFUN "#undef ISOPAQUE\n\n"; + +$OutfileTab =~ /(?:.*[\\\/])(.*)/; +print OUTFILEFUN "#include \"$1\"\n"; + +print OUTFILETAB "};\n\n"; +print OUTFILETAB "static RenderBankFunction* RenderBankNormal[3] = {\n\t&RenderBankFunctionTable[0],\n\t&RenderBankFunctionTable[32],\n\t&RenderBankFunctionTable[64]\n};\n"; + +close( OUTFILETAB ); +close( OUTFILEFUN ); + diff --git a/src/depend/scripts/psikyo_tile_func.pl b/src/depend/scripts/psikyo_tile_func.pl new file mode 100644 index 00000000..dfa93d99 --- /dev/null +++ b/src/depend/scripts/psikyo_tile_func.pl @@ -0,0 +1,95 @@ +#!/usr/bin/perl -w + +use strict; + +my $OutfileFun; +my $OutfileTab; + +# Process command line arguments +if ( $ARGV[0] =~ /^-o/i ) { + if ( $ARGV[0] =~ /^-o$/i ) { + $OutfileFun = $ARGV[1]; + } else { + $ARGV[0] =~ /(?<=-o)(.*)/i; + $OutfileFun = $1; + } +} + +unless ( $OutfileFun ) { + die "Usage: $0 -o \n\n"; +} + +$OutfileTab = $OutfileFun; +$OutfileTab =~ s/(\.\w+)/_table$1/; + +open( OUTFILEFUN, ">$OutfileFun" ) or die "\nError: Couldn't open OUTPUT file $OutfileFun: $!"; +open( OUTFILETAB, ">$OutfileTab" ) or die "\nError: Couldn't open OUTPUT file $OutfileTab: $!"; + +print "Generating $OutfileFun & $OutfileTab...\n"; + +# Generate optimized functions and a table with the function names + +my @TransFun = ( 0, 15, -1 ); +my @TransTab = ( "_TRANS0", "_TRANS15", "_SOLID" ); + +my $RowScroll; +my $Clip; + +print OUTFILEFUN "#define ROT 0\n"; +print OUTFILEFUN "#define BPP 16\n"; +print OUTFILEFUN "#define FLIP 0\n"; +print OUTFILEFUN "#define ZOOM 0\n"; +print OUTFILEFUN "#define ZBUFFER 0\n"; +print OUTFILEFUN "\n"; + +print OUTFILETAB "// Table with all function addresses.\n"; +print OUTFILETAB "static RenderTileFunction RenderTile[] = {\n"; + +for ( my $Function = 0; $Function < 6; $Function++ ) { + my $FunctionName = "&RenderTile16" . $TransTab[($Function & 6) / 2] . "_NOFLIP_ROT0"; + + if ( ($Function & 1) == 0 ) { + $RowScroll = "_NOROWSCROLL"; + print OUTFILEFUN "#define TRANS " . $TransFun[($Function & 6) / 2] . "\n\n"; + } else { + $RowScroll = "_ROWSCROLL"; + } + + print OUTFILEFUN "#define ROWSCROLL " . (($Function & 1) / 1) . "\n"; + print OUTFILETAB "\t"; + + print OUTFILEFUN "#define DOCLIP 0\n"; + print OUTFILEFUN "#include \"psikyo_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $RowScroll . "_NOZOOM_NOZBUFFER_NOCLIP, "; + + print OUTFILEFUN "#define DOCLIP 1\n"; + print OUTFILEFUN "#include \"psikyo_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $RowScroll . "_NOZOOM_NOZBUFFER_CLIP, "; + + print OUTFILEFUN "#undef ROWSCROLL\n"; + if ( ($Function & 1) == 1 ) { + print OUTFILEFUN "\n#undef TRANS\n"; + } + + print OUTFILETAB "\n"; +} + +print OUTFILEFUN "#undef ZBUFFER\n"; +print OUTFILEFUN "#undef ZOOM\n"; +print OUTFILEFUN "#undef FLIP\n"; +print OUTFILEFUN "#undef BPP\n"; +print OUTFILEFUN "#undef ROT\n"; +print OUTFILEFUN "\n"; + +print OUTFILETAB "};\n\n"; + +$OutfileTab =~ /(?:.*[\\\/])(.*)/; +print OUTFILEFUN "#include \"$1\"\n"; + +close( OUTFILETAB ); +close( OUTFILEFUN ); + diff --git a/src/depend/scripts/toa_gp9001_func.pl b/src/depend/scripts/toa_gp9001_func.pl new file mode 100644 index 00000000..ff0f2a47 --- /dev/null +++ b/src/depend/scripts/toa_gp9001_func.pl @@ -0,0 +1,113 @@ +#!/usr/bin/perl -w + +use strict; + +my $OutfileFun; +my $OutfileTab; + +# Process command line arguments +if ( $ARGV[0] =~ /^-o/i ) { + if ( $ARGV[0] =~ /^-o$/i ) { + $OutfileFun = $ARGV[1]; + } else { + $ARGV[0] =~ /(?<=-o)(.*)/i; + $OutfileFun = $1; + } +} + +unless ( $OutfileFun ) { + die "Usage: $0 -o \n\n"; +} + +$OutfileTab = $OutfileFun; +$OutfileTab =~ s/(\.\w+)/_table$1/; + +open( OUTFILEFUN, ">$OutfileFun" ) or die "\nError: Couldn't open OUTPUT file $OutfileFun: $!"; +open( OUTFILETAB, ">$OutfileTab" ) or die "\nError: Couldn't open OUTPUT file $OutfileTab: $!"; + +print "Generating $OutfileFun & $OutfileTab...\n"; + +# Generate optimized functions and a table with the function names + +print OUTFILETAB "// Table with all function addresses.\n"; +print OUTFILETAB "static RenderTileFunction RenderTileFunctionTable[] = {\n"; + +for ( my $Rot = 0; $Rot <= 270; $Rot += 270) { + my @Flip = ( "_NOFLIP", "_FLIPX", "_FLIPY", "_FLIPXY" ); + my $IsOpaque; + + if ( $Rot == 270 ) { + print OUTFILEFUN "#ifdef DRIVER_ROTATION\n"; + + print OUTFILETAB "#ifdef DRIVER_ROTATION\n"; + } + + print OUTFILEFUN "#define ROT $Rot\n\n"; + for ( my $Bitdepth = 16; $Bitdepth <= 32; $Bitdepth += 8 ) { + print OUTFILEFUN "// " . $Bitdepth . "-bit rendering functions.\n"; + print OUTFILEFUN "#define BPP $Bitdepth\n\n"; + + my $FunctionName = "&RenderTile" . $Bitdepth . "_ROT" . "$Rot"; + + for ( my $Function = 0; $Function < 8; $Function++ ) { + if ( ($Function & 3) == 0 ) { + print OUTFILEFUN "#define ISOPAQUE " . ($Function & 4) / 4 . "\n"; + + print OUTFILETAB "\t"; + + if ( ($Function & 4) == 0 ) { + $IsOpaque = "_TRANS"; + } else { + $IsOpaque = "_OPAQUE"; + } + } + print OUTFILEFUN "#define XFLIP " . ($Function & 1) . "\n"; + print OUTFILEFUN "#define YFLIP " . ($Function & 2) / 2 . "\n"; + + print OUTFILEFUN "#define DOCLIP 0\n"; + print OUTFILEFUN "#include \"toa_gp9001_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $Flip[$Function & 3] . "_NOCLIP" . $IsOpaque . ", "; + + print OUTFILEFUN "#define DOCLIP 1\n"; + print OUTFILEFUN "#include \"toa_gp9001_render.h\"\n"; + print OUTFILEFUN "#undef DOCLIP\n"; + + print OUTFILETAB $FunctionName . $Flip[$Function & 3] . "_CLIP" . $IsOpaque . ", "; + + print OUTFILEFUN "#undef YFLIP\n"; + print OUTFILEFUN "#undef XFLIP\n\n"; + + if ( ($Function & 3) == 3 ) { + print OUTFILEFUN "#undef ISOPAQUE\n\n"; + + print OUTFILETAB "\n"; + } + } + print OUTFILEFUN "#undef BPP\n\n"; + } + print OUTFILEFUN "#undef ROT\n\n"; + + if ( $Rot == 270 ) { + print OUTFILEFUN "#endif\n"; + + print OUTFILETAB "#endif\n"; + } +} + +print OUTFILEFUN "\n"; + +print OUTFILETAB "};\n\n"; + +$OutfileTab =~ /(?:.*[\\\/])(.*)/; +print OUTFILEFUN "#include \"$1\"\n"; + +print OUTFILETAB "static RenderTileFunction* RenderTile_ROT0[3] = {\n\t&RenderTileFunctionTable[0],\n\t&RenderTileFunctionTable[16],\n\t&RenderTileFunctionTable[32]\n};\n"; +print OUTFILETAB "#ifdef DRIVER_ROTATION\n"; +print OUTFILETAB "static RenderTileFunction* RenderTile_ROT270[3] = {\n\t&RenderTileFunctionTable[48],\n\t&RenderTileFunctionTable[64],\n\t&RenderTileFunctionTable[80]\n};\n"; +print OUTFILETAB "#endif\n"; + +close( OUTFILETAB ); +close( OUTFILEFUN ); + diff --git a/src/depend/vc/include/afxres.h b/src/depend/vc/include/afxres.h new file mode 100644 index 00000000..c867a1b8 --- /dev/null +++ b/src/depend/vc/include/afxres.h @@ -0,0 +1,6 @@ +#include +#include + +#ifndef IDC_STATIC + #define IDC_STATIC (-1) +#endif diff --git a/src/interface/aud_dsp.cpp b/src/interface/aud_dsp.cpp new file mode 100644 index 00000000..8ef9bb27 --- /dev/null +++ b/src/interface/aud_dsp.cpp @@ -0,0 +1,64 @@ +// DSP_ComaC module +// ---------------- +// by Daniel Moreno - ComaC (2001) < comac2k@teleline.es > +// +// This module just fakes the "dsp.c" functions of FinalBurn and uses +// a IIR low pass filter, which is pretty faster and has a better +// frequency response. + + +#include +#include "burner.h" +#include "lowpass2.h" + +// NOTE: don't modify these defines unless you are 100% sure you know how +// to deal with the parameters of a 2nd order resonant lowpass filter. +// DO NOT EVEN MODIFY SampleFreq!!!! +// +// BTW: if you are curious, these parameters imitate the behavour of +// finalburn's "old" convolution filter. +// ---------------------------------------------------------------------- +#define SampleFreq 44100.0 + +#define CutFreq 14000.0 +#define Q 0.4 +#define Gain 1.0 + +#define CutFreq2 1500.0 +#define Q2 0.3 +#define Gain2 1.475 + + +class LowPass2 *LP1 = NULL, *LP2 = NULL; + + +INT32 DspDo(INT16 *Buff, INT32 Len) +{ + if ((!LP1) || (!LP2)) { return 1; } + + LP1->Filter(Buff, Len); // Left + LP2->Filter(Buff+1, Len); // Right + + return 0; +} + + +INT32 DspInit(void) +{ + LP1 = new LowPass2(CutFreq, SampleFreq, Q, Gain, + CutFreq2, Q2, Gain2); + LP2 = new LowPass2(CutFreq, SampleFreq, Q, Gain, + CutFreq2, Q2, Gain2); + return 0; +} + +INT32 DspExit(void) +{ + delete LP1; + delete LP2; + + LP1 = NULL; + LP2 = NULL; + + return 0; +} diff --git a/src/interface/aud_dsp.h b/src/interface/aud_dsp.h new file mode 100644 index 00000000..df1ecdb9 --- /dev/null +++ b/src/interface/aud_dsp.h @@ -0,0 +1,4 @@ +// dsp.cpp +INT32 DspInit(); +INT32 DspExit(); +INT32 DspDo(INT16* Wave, INT32 nCount); diff --git a/src/interface/aud_interface.cpp b/src/interface/aud_interface.cpp new file mode 100644 index 00000000..45c1ae58 --- /dev/null +++ b/src/interface/aud_interface.cpp @@ -0,0 +1,184 @@ +// Audio Output +#include "burner.h" + +INT32 nAudSampleRate[8] = { 22050, 22050, 22050, 22050, 22050, 22050, 22050, 22050 }; // sample rate +INT32 nAudVolume = 10000; // Sound volume (% * 100) +INT32 nAudSegCount = 6; // Segs in the pdsbLoop buffer +INT32 nAudSegLen = 0; // Seg length in samples (calculated from Rate/Fps) +INT32 nAudAllocSegLen = 0; +UINT8 bAudOkay = 0; // True if DSound was initted okay +UINT8 bAudPlaying = 0; // True if the Loop buffer is playing + +INT32 nAudDSPModule[8] = { 0, }; // DSP module to use: 0 = none, 1 = low-pass filter + +INT16* nAudNextSound = NULL; // The next sound seg we will add to the sample loop + +UINT32 nAudSelect = 0; // Which audio plugin is selected +static UINT32 nAudActive = 0; + +#if defined (BUILD_WIN32) + extern struct AudOut AudOutDx; + extern struct AudOut AudOutXAudio2; +#elif defined (BUILD_SDL) + extern struct AudOut AudOutSDL; +#endif + +static struct AudOut *pAudOut[]= +{ +#if defined (BUILD_WIN32) + &AudOutDx, + &AudOutXAudio2, +#elif defined (BUILD_SDL) + &AudOutSDL, +#endif +}; + +#define AUD_LEN (sizeof(pAudOut)/sizeof(pAudOut[0])) + +static InterfaceInfo AudInfo = { NULL, NULL, NULL }; + +// for NeoGeo CD (WAV playback) +void wav_pause(bool bResume); + +INT32 AudBlankSound() +{ + wav_pause(false); // pause / stop if needed + + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + return pAudOut[nAudActive]->BlankSound(); +} + +// This function checks the Sound loop, and if necessary gets some more sound +INT32 AudSoundCheck() +{ + if(!bRunPause) wav_pause(true); // resume, if needed + + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + return pAudOut[nAudActive]->SoundCheck(); +} + +INT32 AudSoundInit() +{ + INT32 nRet; + + if (nAudSelect >= AUD_LEN) { + return 1; + } + + nAudActive = nAudSelect; + + if ((nRet = pAudOut[nAudActive]->SoundInit()) == 0) { + bAudOkay = true; + } + + return nRet; +} + +INT32 AudSetCallback(INT32 (*pCallback)(INT32)) +{ + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + return pAudOut[nAudActive]->SetCallback(pCallback); +} + +INT32 AudSoundPlay() +{ + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + + INT32 nRet = pAudOut[nAudActive]->SoundPlay(); + if (!nRet) { + bAudPlaying = true; + if (bCDEmuOkay) wav_pause(true); + } + + return nRet; +} + +INT32 AudSoundStop() +{ + if (nAudActive >= AUD_LEN) { + return 1; + } + + bAudPlaying = false; + if (bCDEmuOkay) wav_pause(false); + + return pAudOut[nAudActive]->SoundStop(); +} + +INT32 AudSoundExit() +{ + IntInfoFree(&AudInfo); + + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + bAudOkay = false; + + INT32 nRet = pAudOut[nAudActive]->SoundExit(); + + nAudActive = 0; + + return nRet; +} + +INT32 AudSoundSetVolume() +{ + if (!bAudOkay || nAudActive >= AUD_LEN) { + return 1; + } + return pAudOut[nAudActive]->SoundSetVolume(); +} + +InterfaceInfo* AudGetInfo() +{ + if (IntInfoInit(&AudInfo)) { + IntInfoFree(&AudInfo); + return NULL; + } + + if (bAudOkay) { + TCHAR szString[MAX_PATH] = _T(""); + + AudInfo.pszModuleName = pAudOut[nAudActive]->szModuleName; + + _sntprintf(szString, MAX_PATH, _T("Playback at %iHz, %i%% volume"), nAudSampleRate[nAudActive], nAudVolume / 100); + IntInfoAddStringInterface(&AudInfo, szString); + + if (nAudDSPModule[nAudActive]) { + IntInfoAddStringInterface(&AudInfo, _T("Applying low-pass filter")); + } + + if (pAudOut[nAudSelect]->GetPluginSettings) { + pAudOut[nAudSelect]->GetPluginSettings(&AudInfo); + } + } else { + IntInfoAddStringInterface(&AudInfo, _T("Audio plugin not initialised")); + } + + return &AudInfo; +} + +INT32 AudSelect(UINT32 nPlugIn) +{ + if (nPlugIn < AUD_LEN) { + nAudSelect = nPlugIn; + return 0; + } + + return 1; +} + +void AudWriteSilence() +{ + if (nAudNextSound) { + memset(nAudNextSound, 0, nAudAllocSegLen); + } +} diff --git a/src/interface/cd_interface.cpp b/src/interface/cd_interface.cpp new file mode 100644 index 00000000..79382f17 --- /dev/null +++ b/src/interface/cd_interface.cpp @@ -0,0 +1,141 @@ +// CD/CD-ROM support +#include "burner.h" + +bool bCDEmuOkay = false; +UINT32 nCDEmuSelect = 0; + +CDEmuStatusValue CDEmuStatus; + +static InterfaceInfo CDEmuInfo = { NULL, NULL, NULL }; + +#if defined BUILD_WIN32 + extern struct CDEmuDo isowavDo; +#elif defined BUILD_SDL + + // CD emulation module + +#endif + +static struct CDEmuDo* pCDEmuDo[] = +{ +#if defined BUILD_WIN32 + &isowavDo, +#elif defined BUILD_SDL + + // CD emulation module + +#endif +}; + +#define CDEMU_LEN (sizeof(pCDEmuDo) / sizeof(pCDEmuDo[0])) + +TCHAR CDEmuImage[MAX_PATH] = _T(""); + + +// ---------------------------------------------------------------------------- + +INT32 CDEmuExit() +{ + IntInfoFree(&CDEmuInfo); + + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return 1; + } + bCDEmuOkay = false; + + return pCDEmuDo[nCDEmuSelect]->CDEmuExit(); +} + +INT32 CDEmuInit() +{ + INT32 nRet; + + if (nCDEmuSelect >= CDEMU_LEN) { + return 1; + } + + CDEmuStatus = idle; + + if ((nRet = pCDEmuDo[nCDEmuSelect]->CDEmuInit()) == 0) { + bCDEmuOkay = true; + } + + return nRet; +} + +INT32 CDEmuStop() +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return 1; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuStop(); +} + +INT32 CDEmuPlay(UINT8 M, UINT8 S, UINT8 F) +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return 1; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuPlay(M, S, F); +} + +INT32 CDEmuLoadSector(INT32 LBA, char* pBuffer) +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return 0; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuLoadSector(LBA, pBuffer); +} + +UINT8* CDEmuReadTOC(INT32 track) +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return NULL; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuReadTOC(track); +} + +UINT8* CDEmuReadQChannel() +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return NULL; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuReadQChannel(); +} + +INT32 CDEmuGetSoundBuffer(INT16* buffer, INT32 samples) +{ + if (!bCDEmuOkay || nCDEmuSelect >= CDEMU_LEN) { + return 1; + } + + return pCDEmuDo[nCDEmuSelect]->CDEmuGetSoundBuffer(buffer, samples); +} + +InterfaceInfo* CDEmuGetInfo() +{ + if (IntInfoInit(&CDEmuInfo)) { + IntInfoFree(&CDEmuInfo); + return NULL; + } + + if (bCDEmuOkay) { + + CDEmuInfo.pszModuleName = pCDEmuDo[nCDEmuSelect]->szModuleName; + + if (pCDEmuDo[nCDEmuSelect]->GetPluginSettings) { + pCDEmuDo[nCDEmuSelect]->GetPluginSettings(&CDEmuInfo); + } + } else { + IntInfoAddStringInterface(&CDEmuInfo, _T("CD/CD-ROM emulation module not initialised")); + } + + return &CDEmuInfo; + + return NULL; +} diff --git a/src/interface/cd_interface.h b/src/interface/cd_interface.h new file mode 100644 index 00000000..2b112276 --- /dev/null +++ b/src/interface/cd_interface.h @@ -0,0 +1,41 @@ +#ifndef CD_INTERFACE_H_ +#define CD_INTERFACE_H_ + +// ---------------------------------------------------------------------------- +// CD emulation module + +enum CDEmuStatusValue { idle = 0, reading, playing, paused, seeking, fastforward, fastreverse }; + +extern TCHAR CDEmuImage[MAX_PATH]; + +INT32 CDEmuInit(); +INT32 CDEmuExit(); +INT32 CDEmuStop(); +INT32 CDEmuPlay(UINT8 M, UINT8 S, UINT8 F); +INT32 CDEmuLoadSector(INT32 LBA, char* pBuffer); +UINT8* CDEmuReadTOC(INT32 track); +UINT8* CDEmuReadQChannel(); +INT32 CDEmuGetSoundBuffer(INT16* buffer, INT32 samples); + +static inline CDEmuStatusValue CDEmuGetStatus() +{ + extern CDEmuStatusValue CDEmuStatus; + + return CDEmuStatus; +} + +static inline void CDEmuStartRead() +{ + extern CDEmuStatusValue CDEmuStatus; + + CDEmuStatus = seeking; +} + +static inline void CDEmuPause() +{ + extern CDEmuStatusValue CDEmuStatus; + + CDEmuStatus = paused; +} + +#endif /*CD_INTERFACE_H_*/ diff --git a/src/interface/inp_interface.cpp b/src/interface/inp_interface.cpp new file mode 100644 index 00000000..ad767c97 --- /dev/null +++ b/src/interface/inp_interface.cpp @@ -0,0 +1,468 @@ +// Burner Input module +#include "burner.h" + +UINT32 nInputSelect = 0; +bool bInputOkay = false; + +static bool bCinpOkay; + +#if defined (BUILD_WIN32) + extern struct InputInOut InputInOutDInput; +#elif defined (BUILD_SDL) + extern struct InputInOut InputInOutSDL; +#endif + +static struct InputInOut *pInputInOut[]= +{ +#if defined (BUILD_WIN32) + &InputInOutDInput, +#elif defined (BUILD_SDL) + &InputInOutSDL, +#endif +}; + +#define INPUT_LEN (sizeof(pInputInOut) / sizeof(pInputInOut[0])) + +static InterfaceInfo InpInfo = { NULL, NULL, NULL }; + +inline INT32 CinpState(const INT32 nCode) +{ + // Return off for keyboard inputs if current input is turned off + if (nCode < 0x4000 && !bCinpOkay) { + return 0; + } + + // Read from Direct Input + return pInputInOut[nInputSelect]->ReadSwitch(nCode); +} + +// Read an axis of a joystick +inline INT32 CinpJoyAxis(const INT32 i, const INT32 nAxis) +{ + // Read from Direct Input + return pInputInOut[nInputSelect]->ReadJoyAxis(i, nAxis); +} + +// Read an axis of a mouse +inline INT32 CinpMouseAxis(const INT32 i, const INT32 nAxis) +{ + // Read from Direct Input + return pInputInOut[nInputSelect]->ReadMouseAxis(i, nAxis); +} + +// Do one frames worth of keyboard input sliders +static INT32 InputTick() +{ + struct GameInp *pgi; + UINT32 i; + + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + INT32 nAdd = 0; + if ((pgi->nInput & GIT_GROUP_SLIDER) == 0) { // not a slider + continue; + } + + if (pgi->nInput == GIT_KEYSLIDER) { + // Get states of the two keys + if (CinpState(pgi->Input.Slider.SliderAxis.nSlider[0])) { + nAdd -= 0x100; + } + if (CinpState(pgi->Input.Slider.SliderAxis.nSlider[1])) { + nAdd += 0x100; + } + } + + if (pgi->nInput == GIT_JOYSLIDER) { + // Get state of the axis + nAdd = CinpJoyAxis(pgi->Input.Slider.JoyAxis.nJoy, pgi->Input.Slider.JoyAxis.nAxis); + nAdd /= 0x100; + } + + // nAdd is now -0x100 to +0x100 + + // Change to slider speed + nAdd *= pgi->Input.Slider.nSliderSpeed; + nAdd /= 0x100; + + if (pgi->Input.Slider.nSliderCenter) { // Attact to center + INT32 v = pgi->Input.Slider.nSliderValue - 0x8000; + v *= (pgi->Input.Slider.nSliderCenter - 1); + v /= pgi->Input.Slider.nSliderCenter; + v += 0x8000; + pgi->Input.Slider.nSliderValue = v; + } + + pgi->Input.Slider.nSliderValue += nAdd; + // Limit slider + if (pgi->Input.Slider.nSliderValue < 0x0100) { + pgi->Input.Slider.nSliderValue = 0x0100; + } + if (pgi->Input.Slider.nSliderValue > 0xFF00) { + pgi->Input.Slider.nSliderValue = 0xFF00; + } + } + return 0; +} + +INT32 InputInit() +{ + INT32 nRet; + + bInputOkay = false; + + if (nInputSelect >= INPUT_LEN) { + return 1; + } + + if ((nRet = pInputInOut[nInputSelect]->Init()) == 0) { + bInputOkay = true; + } + + return nRet; +} + +INT32 InputExit() +{ + IntInfoFree(&InpInfo); + + if (nInputSelect >= INPUT_LEN) { + return 1; + } + + bInputOkay = false; + + return pInputInOut[nInputSelect]->Exit(); +} + +// This will request exclusive access for mouse and/or request input processing if the application is in the foreground only +// - bExcusive = 1 - Request exclusive access to inputs (this may apply to only the mouse or all input, depending on the API) +// This function will show or hide the mouse cursor as appropriate +// - bForeground = 1 - Request input processing only if application is in foreground (this may not be supported by all APIs) +INT32 InputSetCooperativeLevel(const bool bExclusive, const bool bForeground) +{ + if (!bInputOkay || nInputSelect >= INPUT_LEN) { + return 1; + } + if (pInputInOut[nInputSelect]->SetCooperativeLevel == NULL) { + return 0; + } + + return pInputInOut[nInputSelect]->SetCooperativeLevel(bExclusive, bForeground); +} + +// This will process all PC-side inputs and optionally update the emulated game side. +INT32 InputMake(bool bCopy) +{ + struct GameInp* pgi; + UINT32 i; + + if (!bInputOkay || nInputSelect >= INPUT_LEN) { + return 1; + } + + pInputInOut[nInputSelect]->NewFrame(); // Poll joysticks etc + + bCinpOkay = AppProcessKeyboardInput(); + + InputTick(); + + for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) { + if (pgi->Input.pVal == NULL) { + continue; + } + + switch (pgi->nInput) { + case 0: // Undefined + pgi->Input.nVal = 0; + break; + case GIT_CONSTANT: // Constant value + pgi->Input.nVal = pgi->Input.Constant.nConst; + if (bCopy) { + *(pgi->Input.pVal) = pgi->Input.nVal; + } + break; + case GIT_SWITCH: { // Digital input + INT32 s = CinpState(pgi->Input.Switch.nCode); + + if (pgi->nType & BIT_GROUP_ANALOG) { + // Set analog controls to full + if (s) { + pgi->Input.nVal = 0xFFFF; + } else { + pgi->Input.nVal = 0x0001; + } + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + } else { + // Binary controls + if (s) { + pgi->Input.nVal = 1; + } else { + pgi->Input.nVal = 0; + } + if (bCopy) { + *(pgi->Input.pVal) = pgi->Input.nVal; + } + } + + break; + } + case GIT_KEYSLIDER: // Keyboard slider + case GIT_JOYSLIDER: { // Joystick slider + INT32 nSlider = pgi->Input.Slider.nSliderValue; + if (pgi->nType == BIT_ANALOG_REL) { + nSlider -= 0x8000; + nSlider >>= 4; + } + + pgi->Input.nVal = (UINT16)nSlider; + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + break; + } + case GIT_MOUSEAXIS: // Mouse axis + pgi->Input.nVal = (UINT16)(CinpMouseAxis(pgi->Input.MouseAxis.nMouse, pgi->Input.MouseAxis.nAxis) * nAnalogSpeed); + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + break; + case GIT_JOYAXIS_FULL: { // Joystick axis + INT32 nJoy = CinpJoyAxis(pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + + if (pgi->nType == BIT_ANALOG_REL) { + nJoy *= nAnalogSpeed; + nJoy >>= 13; + + // Clip axis to 8 bits + if (nJoy < -32768) { + nJoy = -32768; + } + if (nJoy > 32767) { + nJoy = 32767; + } + } else { + nJoy >>= 1; + nJoy += 0x8000; + + // Clip axis to 16 bits + if (nJoy < 0x0001) { + nJoy = 0x0001; + } + if (nJoy > 0xFFFF) { + nJoy = 0xFFFF; + } + } + + pgi->Input.nVal = (UINT16)nJoy; + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + + break; + } + case GIT_JOYAXIS_NEG: { // Joystick axis Lo + INT32 nJoy = CinpJoyAxis(pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + if (nJoy < 32767) { + nJoy = -nJoy; + + if (nJoy < 0x0000) { + nJoy = 0x0000; + } + if (nJoy > 0xFFFF) { + nJoy = 0xFFFF; + } + + pgi->Input.nVal = (UINT16)nJoy; + } else { + pgi->Input.nVal = 0; + } + + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + break; + } + case GIT_JOYAXIS_POS: { // Joystick axis Hi + INT32 nJoy = CinpJoyAxis(pgi->Input.JoyAxis.nJoy, pgi->Input.JoyAxis.nAxis); + if (nJoy > 32767) { + + if (nJoy < 0x0000) { + nJoy = 0x0000; + } + if (nJoy > 0xFFFF) { + nJoy = 0xFFFF; + } + + pgi->Input.nVal = (UINT16)nJoy; + } else { + pgi->Input.nVal = 0; + } + + if (bCopy) { + *(pgi->Input.pShortVal) = pgi->Input.nVal; + } + break; + } + } + } + + for (i = 0; i < nMacroCount; i++, pgi++) { + if (pgi->Macro.nMode) { // Macro is defined + if (bCopy && CinpState(pgi->Macro.Switch.nCode)) { + for (INT32 j = 0; j < 4; j++) { + if (pgi->Macro.pVal[j]) { + *(pgi->Macro.pVal[j]) = pgi->Macro.nVal[j]; + } + } + } + } + } + + return 0; +} + +// Use this function as follows: +// - First call with nFlags = 2 +// - Then call with nFlags = 4 until all controls are released +// - Then call with nFlags = 8 until a control is activated +// - Then call with nFlags = 16 until all controls are released again +// It will continue to return a control (reflecting the direction an axis is moved in) +// Use this to handle analog controls correctly +// +// Call with nFlags & 1 to indicate that controls need to be polled (when normal input processing is disabled) +INT32 InputFind(const INT32 nFlags) +{ + static INT32 nInputCode, nDelay, nJoyPrevPos; + + INT32 nFind; + + if (nInputSelect >= INPUT_LEN) { + return 1; + } + + if (nFlags & 1) { + pInputInOut[nInputSelect]->NewFrame(); + } + + nFind = pInputInOut[nInputSelect]->Find(nFlags & 2); + + switch (nFlags) { + case 4: { + return nFind; + } + case 8: { + if (nFind >= 0) { + nInputCode = nFind; + if ((nInputCode & 0x4000) && (nInputCode & 0xFF) < 0x10) { + nJoyPrevPos = CinpJoyAxis((nInputCode >> 8) & 0x3F, (nInputCode >> 1) & 0x07); + } + nDelay = 0; + } + + return nFind; + } + case 16: { + + // Treat joystick axes specially + // Wait until the axis reports no movement for some time + if ((nInputCode & 0x4000) && (nInputCode & 0xFF) < 0x10) { + INT32 nJoyPos = CinpJoyAxis((nInputCode >> 8) & 0x3F, (nInputCode >> 1) & 0x07); + INT32 nJoyDelta = nJoyPrevPos - nJoyPos; + + nJoyPrevPos = nJoyPos; + + if (nFind != -1) { + nInputCode = nFind; + } + + // While the movement is within the threshold, treat it as no movement + if (nJoyDelta > -0x0100 || nJoyDelta < 0x0100) { + nDelay++; + if (nDelay > 64) { + return -1; + } + } else { + nDelay = 0; + } + + return nInputCode; + } + + // Treat mouse axes specially + // Wait until the axis reports no movement/movement in the same direction for some time + if ((nInputCode & 0x8000) && (nInputCode & 0xFF) < 0x06) { + INT32 nMouseDelta = CinpMouseAxis((nInputCode >> 8) & 0x3F, (nInputCode >> 1) & 0x07); + if (nFind == -1 || ((nInputCode & 1) ? nMouseDelta > 0 : nMouseDelta < 0)) { + nDelay++; + if (nDelay > 128) { + return -1; + } + } else { + nDelay = 0; + nInputCode = nFind; + } + + return nInputCode; + } + + return nFind; + } + } + + return -1; +} + +// Get the name of a control and/or the device it's on (not all API's may support this) +// Either parameter can be passed as NULL +INT32 InputGetControlName(INT32 nCode, TCHAR* pszDeviceName, TCHAR* pszControlName) +{ + if (!bInputOkay || nInputSelect >= INPUT_LEN) { + return 1; + } + if (pInputInOut[nInputSelect]->GetControlName == NULL) { + return 1; + } + + return pInputInOut[nInputSelect]->GetControlName(nCode, pszDeviceName, pszControlName); +} + +InterfaceInfo* InputGetInfo() +{ + if (IntInfoInit(&InpInfo)) { + IntInfoFree(&InpInfo); + return NULL; + } + + if (bInputOkay) { + InpInfo.pszModuleName = pInputInOut[nInputSelect]->szModuleName; + + if (pInputInOut[nInputSelect]->GetPluginSettings) { + pInputInOut[nInputSelect]->GetPluginSettings(&InpInfo); + } + + for (INT32 nType = 0; nType < 3; nType++) { + INT32 nDeviceTypes[] = { 0x0000, 0x8000, 0x4000 }; + TCHAR nDeviceTypeNames[][16] = { _T("keyboard"), _T("mouse "), _T("joystick") }; + TCHAR nDeviceName[MAX_PATH] = _T(""); + INT32 nActiveDevice = 0; + + while (nActiveDevice < 16 && pInputInOut[nInputSelect]->GetControlName(nDeviceTypes[nType] | (nActiveDevice << 8), nDeviceName, NULL) == 0 && nDeviceName[0]) { + TCHAR szString[MAX_PATH] = _T(""); + + _sntprintf(szString, MAX_PATH, _T("%s %d %s"), nDeviceTypeNames[nType], nActiveDevice, nDeviceName); + + if (IntInfoAddStringInterface(&InpInfo, szString)) { + break; + } + + nActiveDevice++; + } + } + } else { + IntInfoAddStringInterface(&InpInfo, _T("Input plugin not initialised")); + } + + return &InpInfo; +} diff --git a/src/interface/inp_keys.h b/src/interface/inp_keys.h new file mode 100644 index 00000000..4d1318b6 --- /dev/null +++ b/src/interface/inp_keys.h @@ -0,0 +1,148 @@ +// FB Alpha key definitions + +#define FBK_ESCAPE 0x01 +#define FBK_1 0x02 +#define FBK_2 0x03 +#define FBK_3 0x04 +#define FBK_4 0x05 +#define FBK_5 0x06 +#define FBK_6 0x07 +#define FBK_7 0x08 +#define FBK_8 0x09 +#define FBK_9 0x0A +#define FBK_0 0x0B +#define FBK_MINUS 0x0C // - on main keyboard +#define FBK_EQUALS 0x0D +#define FBK_BACK 0x0E // backspace +#define FBK_TAB 0x0F +#define FBK_Q 0x10 +#define FBK_W 0x11 +#define FBK_E 0x12 +#define FBK_R 0x13 +#define FBK_T 0x14 +#define FBK_Y 0x15 +#define FBK_U 0x16 +#define FBK_I 0x17 +#define FBK_O 0x18 +#define FBK_P 0x19 +#define FBK_LBRACKET 0x1A +#define FBK_RBRACKET 0x1B +#define FBK_RETURN 0x1C // Enter on main keyboard +#define FBK_LCONTROL 0x1D +#define FBK_A 0x1E +#define FBK_S 0x1F +#define FBK_D 0x20 +#define FBK_F 0x21 +#define FBK_G 0x22 +#define FBK_H 0x23 +#define FBK_J 0x24 +#define FBK_K 0x25 +#define FBK_L 0x26 +#define FBK_SEMICOLON 0x27 +#define FBK_APOSTROPHE 0x28 +#define FBK_GRAVE 0x29 // accent grave +#define FBK_LSHIFT 0x2A +#define FBK_BACKSLASH 0x2B +#define FBK_Z 0x2C +#define FBK_X 0x2D +#define FBK_C 0x2E +#define FBK_V 0x2F +#define FBK_B 0x30 +#define FBK_N 0x31 +#define FBK_M 0x32 +#define FBK_COMMA 0x33 +#define FBK_PERIOD 0x34 // . on main keyboard +#define FBK_SLASH 0x35 // / on main keyboard +#define FBK_RSHIFT 0x36 +#define FBK_MULTIPLY 0x37 // * on numeric keypad +#define FBK_LALT 0x38 // left Alt +#define FBK_SPACE 0x39 +#define FBK_CAPITAL 0x3A +#define FBK_F1 0x3B +#define FBK_F2 0x3C +#define FBK_F3 0x3D +#define FBK_F4 0x3E +#define FBK_F5 0x3F +#define FBK_F6 0x40 +#define FBK_F7 0x41 +#define FBK_F8 0x42 +#define FBK_F9 0x43 +#define FBK_F10 0x44 +#define FBK_NUMLOCK 0x45 +#define FBK_SCROLL 0x46 // Scroll Lock +#define FBK_NUMPAD7 0x47 +#define FBK_NUMPAD8 0x48 +#define FBK_NUMPAD9 0x49 +#define FBK_SUBTRACT 0x4A // - on numeric keypad +#define FBK_NUMPAD4 0x4B +#define FBK_NUMPAD5 0x4C +#define FBK_NUMPAD6 0x4D +#define FBK_ADD 0x4E // + on numeric keypad +#define FBK_NUMPAD1 0x4F +#define FBK_NUMPAD2 0x50 +#define FBK_NUMPAD3 0x51 +#define FBK_NUMPAD0 0x52 +#define FBK_DECIMAL 0x53 // . on numeric keypad +#define FBK_OEM_102 0x56 // < > | on UK/Germany keyboards +#define FBK_F11 0x57 +#define FBK_F12 0x58 + +#define FBK_F13 0x64 // (NEC PC98) +#define FBK_F14 0x65 // (NEC PC98) +#define FBK_F15 0x66 // (NEC PC98) + +#define FBK_KANA 0x70 // (Japanese keyboard) +#define FBK_ABNT_C1 0x73 // / ? on Portugese (Brazilian) keyboards +#define FBK_CONVERT 0x79 // (Japanese keyboard) +#define FBK_NOCONVERT 0x7B // (Japanese keyboard) +#define FBK_YEN 0x7D // (Japanese keyboard) +#define FBK_ABNT_C2 0x7E // Numpad . on Portugese (Brazilian) keyboards +#define FBK_NUMPADEQUALS 0x8D // = on numeric keypad (NEC PC98) +#define FBK_PREVTRACK 0x90 // Previous Track (FBK_CIRCUMFLEX on Japanese keyboard) +#define FBK_AT 0x91 // (NEC PC98) +#define FBK_COLON 0x92 // (NEC PC98) +#define FBK_UNDERLINE 0x93 // (NEC PC98) +#define FBK_KANJI 0x94 // (Japanese keyboard) +#define FBK_STOP 0x95 // (NEC PC98) +#define FBK_AX 0x96 // (Japan AX) +#define FBK_UNLABELED 0x97 // (J3100) +#define FBK_NEXTTRACK 0x99 // Next Track +#define FBK_NUMPADENTER 0x9C // Enter on numeric keypad +#define FBK_RCONTROL 0x9D +#define FBK_MUTE 0xA0 // Mute +#define FBK_CALCULATOR 0xA1 // Calculator +#define FBK_PLAYPAUSE 0xA2 // Play / Pause +#define FBK_MEDIASTOP 0xA4 // Media Stop +#define FBK_VOLUMEDOWN 0xAE // Volume - +#define FBK_VOLUMEUP 0xB0 // Volume + +#define FBK_WEBHOME 0xB2 // Web home +#define FBK_NUMPADCOMMA 0xB3 // , on numeric keypad (NEC PC98) +#define FBK_DIVIDE 0xB5 // / on numeric keypad +#define FBK_SYSRQ 0xB7 +#define FBK_RALT 0xB8 // right Alt +#define FBK_PAUSE 0xC5 // Pause +#define FBK_HOME 0xC7 // Home on arrow keypad +#define FBK_UPARROW 0xC8 // UpArrow on arrow keypad +#define FBK_PRIOR 0xC9 // PgUp on arrow keypad +#define FBK_LEFTARROW 0xCB // LeftArrow on arrow keypad +#define FBK_RIGHTARROW 0xCD // RightArrow on arrow keypad +#define FBK_END 0xCF // End on arrow keypad +#define FBK_DOWNARROW 0xD0 // DownArrow on arrow keypad +#define FBK_NEXT 0xD1 // PgDn on arrow keypad +#define FBK_INSERT 0xD2 // Insert on arrow keypad +#define FBK_DELETE 0xD3 // Delete on arrow keypad +#define FBK_LWIN 0xDB // Left Windows key +#define FBK_RWIN 0xDC // Right Windows key +#define FBK_APPS 0xDD // AppMenu key +#define FBK_POWER 0xDE // System Power +#define FBK_SLEEP 0xDF // System Sleep +#define FBK_WAKE 0xE3 // System Wake +#define FBK_WEBSEARCH 0xE5 // Web Search +#define FBK_WEBFAVORITES 0xE6 // Web Favorites +#define FBK_WEBREFRESH 0xE7 // Web Refresh +#define FBK_WEBSTOP 0xE8 // Web Stop +#define FBK_WEBFORWARD 0xE9 // Web Forward +#define FBK_WEBBACK 0xEA // Web Back +#define FBK_MYCOMPUTER 0xEB // My Computer +#define FBK_MAIL 0xEC // Mail +#define FBK_MEDIASELECT 0xED // Media Select diff --git a/src/interface/interface.cpp b/src/interface/interface.cpp new file mode 100644 index 00000000..eab71d3d --- /dev/null +++ b/src/interface/interface.cpp @@ -0,0 +1,96 @@ +#include "burner.h" + +#define INT_INFO_STRINGS (8) + +INT32 IntInfoFree(InterfaceInfo* pInfo) +{ + if (pInfo->ppszInterfaceSettings) { + for (INT32 i = 0; i < INT_INFO_STRINGS; i++) { + if (pInfo->ppszInterfaceSettings[i]) { + free(pInfo->ppszInterfaceSettings[i]); + pInfo->ppszInterfaceSettings[i] = NULL; + } + } + } + if (pInfo->ppszInterfaceSettings) { + free(pInfo->ppszInterfaceSettings); + pInfo->ppszInterfaceSettings = NULL; + } + + if (pInfo->ppszModuleSettings) { + for (INT32 i = 0; i < INT_INFO_STRINGS; i++) { + if (pInfo->ppszModuleSettings[i]) { + free(pInfo->ppszModuleSettings[i]); + pInfo->ppszModuleSettings[i] = NULL; + } + } + } + if (pInfo->ppszModuleSettings) { + free(pInfo->ppszModuleSettings); + pInfo->ppszModuleSettings = NULL; + } + + memset(pInfo, 0, sizeof(InterfaceInfo)); + + return 0; +} + +INT32 IntInfoInit(InterfaceInfo* pInfo) +{ + IntInfoFree(pInfo); + + pInfo->ppszInterfaceSettings = (TCHAR**)malloc((INT_INFO_STRINGS + 1) * sizeof(TCHAR*)); + if (pInfo->ppszInterfaceSettings == NULL) { + return 1; + } + memset(pInfo->ppszInterfaceSettings, 0, (INT_INFO_STRINGS + 1) * sizeof(TCHAR*)); + + pInfo->ppszModuleSettings = (TCHAR**)malloc((INT_INFO_STRINGS + 1) * sizeof(TCHAR*)); + if (pInfo->ppszModuleSettings == NULL) { + return 1; + } + memset(pInfo->ppszModuleSettings, 0, (INT_INFO_STRINGS + 1) * sizeof(TCHAR*)); + + return 0; +} + +INT32 IntInfoAddStringInterface(InterfaceInfo* pInfo, TCHAR* szString) +{ + INT32 i; + + for (i = 0; pInfo->ppszInterfaceSettings[i] && i < INT_INFO_STRINGS; i++) { } + + if (i >= INT_INFO_STRINGS) { + return 1; + } + + pInfo->ppszInterfaceSettings[i] = (TCHAR*)malloc(MAX_PATH * sizeof(TCHAR)); + if (pInfo->ppszInterfaceSettings[i] == NULL) { + return 1; + } + + _tcsncpy(pInfo->ppszInterfaceSettings[i], szString, MAX_PATH); + + return 0; +} + +INT32 IntInfoAddStringModule(InterfaceInfo* pInfo, TCHAR* szString) +{ + INT32 i; + + for (i = 0; pInfo->ppszModuleSettings[i] && i < INT_INFO_STRINGS; i++) { } + + if (i >= INT_INFO_STRINGS) { + return 1; + } + + pInfo->ppszModuleSettings[i] = (TCHAR*)malloc(MAX_PATH * sizeof(TCHAR)); + if (pInfo->ppszModuleSettings[i] == NULL) { + return 1; + } + + _tcsncpy(pInfo->ppszModuleSettings[i], szString, MAX_PATH); + + return 0; +} + diff --git a/src/interface/interface.h b/src/interface/interface.h new file mode 100644 index 00000000..e10083a4 --- /dev/null +++ b/src/interface/interface.h @@ -0,0 +1,242 @@ +#ifdef FBA_DEBUG + #define PRINT_DEBUG_INFO +#endif + +// GameInp structure +#include "gameinp.h" +// Key codes +#include "inp_keys.h" + +// Interface info (used for all modules) +struct InterfaceInfo { + const TCHAR* pszModuleName; + TCHAR** ppszInterfaceSettings; + TCHAR** ppszModuleSettings; +}; + +INT32 IntInfoFree(InterfaceInfo* pInfo); +INT32 IntInfoInit(InterfaceInfo* pInfo); +INT32 IntInfoAddStringInterface(InterfaceInfo* pInfo, TCHAR* szString); +INT32 IntInfoAddStringModule(InterfaceInfo* pInfo, TCHAR* szString); + +// Input plugin: +struct InputInOut { + INT32 (*Init)(); + INT32 (*Exit)(); + INT32 (*SetCooperativeLevel)(bool bExclusive, bool bForeground); + // Setup new frame + INT32 (*NewFrame)(); + // Read digital + INT32 (*ReadSwitch)(INT32 nCode); + // Read analog + INT32 (*ReadJoyAxis)(INT32 i, INT32 nAxis); + INT32 (*ReadMouseAxis)(INT32 i, INT32 nAxis); + // Find out which control is activated + INT32 (*Find)(bool CreateBaseline); + // Get the name of a control + INT32 (*GetControlName)(INT32 nCode, TCHAR* pszDeviceName, TCHAR* pszControlName); + // Get plugin info + INT32 (*GetPluginSettings)(InterfaceInfo* pInfo); + const TCHAR* szModuleName; +}; + +INT32 InputInit(); +INT32 InputExit(); +INT32 InputSetCooperativeLevel(const bool bExclusive, const bool bForeGround); +INT32 InputMake(bool bCopy); +INT32 InputFind(const INT32 nFlags); +INT32 InputGetControlName(INT32 nCode, TCHAR* pszDeviceName, TCHAR* pszControlName); +InterfaceInfo* InputGetInfo(); + +extern bool bInputOkay; +extern UINT32 nInputSelect; + +// CD emulation module + +struct CDEmuDo { + INT32 (*CDEmuExit)(); + INT32 (*CDEmuInit)(); + INT32 (*CDEmuStop)(); + INT32 (*CDEmuPlay)(UINT8 M, UINT8 S, UINT8 F); + INT32 (*CDEmuLoadSector)(INT32 LBA, char* pBuffer); + UINT8* (*CDEmuReadTOC)(INT32 track); + UINT8* (*CDEmuReadQChannel)(); + INT32 (*CDEmuGetSoundBuffer)(INT16* buffer, INT32 samples); + // Get plugin info + INT32 (*GetPluginSettings)(InterfaceInfo* pInfo); + const TCHAR* szModuleName; +}; + +#include "cd_interface.h" + +InterfaceInfo* CDEmuGetInfo(); + +extern bool bCDEmuOkay; +extern UINT32 nCDEmuSelect; + +extern CDEmuStatusValue CDEmuStatus; + +// Profiling plugin +struct ProfileDo { + INT32 (*ProfileExit)(); + INT32 (*ProfileInit)(); + INT32 (*ProfileStart)(INT32 nSubSystem); + INT32 (*ProfileEnd)(INT32 nSubSystem); + double (*ProfileReadLast)(INT32 nSubSystem); + double (*ProfileReadAverage)(INT32 nSubSystem); + // Get plugin info + INT32 (*GetPluginSettings)(InterfaceInfo* pInfo); + const TCHAR* szModuleName; +}; + +extern bool bProfileOkay; +extern UINT32 nProfileSelect; + +INT32 ProfileInit(); +INT32 ProfileExit(); +INT32 ProfileProfileStart(INT32 nSubSystem); +INT32 ProfileProfileEnd(INT32 nSubSustem); +double ProfileProfileReadLast(INT32 nSubSustem); +double ProfileProfileReadAverage(INT32 nSubSustem); +InterfaceInfo* ProfileGetInfo(); + +// Audio Output plugin +struct AudOut { + INT32 (*BlankSound)(); + INT32 (*SoundCheck)(); + INT32 (*SoundInit)(); + INT32 (*SetCallback)(INT32 (*pCallback)(INT32)); + INT32 (*SoundPlay)(); + INT32 (*SoundStop)(); + INT32 (*SoundExit)(); + INT32 (*SoundSetVolume)(); + // Get plugin info + INT32 (*GetPluginSettings)(InterfaceInfo* pInfo); + const TCHAR* szModuleName; +}; + +INT32 AudSelect(UINT32 nPlugIn); +INT32 AudSoundInit(); +INT32 AudSoundExit(); +INT32 AudSetCallback(INT32 (*pCallback)(INT32)); +INT32 AudSoundPlay(); +INT32 AudSoundStop(); +INT32 AudBlankSound(); +INT32 AudSoundCheck(); +INT32 AudSoundSetVolume(); +InterfaceInfo* AudGetInfo(); +void AudWriteSilence(); + +extern INT32 nAudSampleRate[8]; // sample rate +extern INT32 nAudVolume; // Sound volume (% * 100) +extern INT32 nAudSegCount; // Segs in the pdsbLoop buffer +extern INT32 nAudSegLen; // Seg length in samples (calculated from Rate/Fps) +extern INT32 nAudAllocSegLen; +extern INT16 *nAudNextSound; // The next sound seg we will add to the sample loop +extern UINT8 bAudOkay; // True if DSound was initted okay +extern UINT8 bAudPlaying; // True if the Loop buffer is playing +extern INT32 nAudDSPModule[8]; // DSP module to use: 0 = none, 1 = low-pass filter +extern UINT32 nAudSelect; + +// Video Output plugin: +struct VidOut { + INT32 (*Init)(); + INT32 (*Exit)(); + INT32 (*Frame)(bool bRedraw); + INT32 (*Paint)(INT32 bValidate); + INT32 (*ImageSize)(RECT* pRect, INT32 nGameWidth, INT32 nGameHeight); + // Get plugin info + INT32 (*GetPluginSettings)(InterfaceInfo* pInfo); + const TCHAR* szModuleName; +}; + +INT32 VidSelect(UINT32 nPlugin); +INT32 VidInit(); +INT32 VidExit(); +INT32 VidReInitialise(); +INT32 VidFrame(); +INT32 VidRedraw(); +INT32 VidRecalcPal(); +INT32 VidPaint(INT32 bValidate); +INT32 VidImageSize(RECT* pRect, INT32 nGameWidth, INT32 nGameHeight); +const TCHAR* VidGetModuleName(); +InterfaceInfo* VidGetInfo(); + +#ifdef BUILD_WIN32 + extern HWND hVidWnd; +#endif + +extern bool bVidOkay; +extern UINT32 nVidSelect; +extern INT32 nVidWidth, nVidHeight, nVidDepth, nVidRefresh; + +extern INT32 nVidHorWidth, nVidHorHeight; +extern INT32 nVidVerWidth, nVidVerHeight; + +extern INT32 nVidFullscreen; +extern INT32 bVidBilinear; +extern INT32 bVidScanlines; +extern INT32 bVidScanRotate; +extern INT32 bVidScanBilinear; +extern INT32 nVidScanIntensity; +extern INT32 bVidScanHalf; +extern INT32 bVidScanDelay; +extern INT32 nVidFeedbackIntensity; +extern INT32 nVidFeedbackOverSaturation; +extern INT32 bVidCorrectAspect; +extern INT32 bVidArcaderes; + +extern INT32 bVidArcaderesHor; +extern INT32 bVidArcaderesVer; + +extern INT32 nVidRotationAdjust; +extern INT32 bVidUseHardwareGamma; +extern INT32 bVidAutoSwitchFull; +extern INT32 bVidForce16bit; +extern INT32 nVidTransferMethod; +extern float fVidScreenAngle; +extern float fVidScreenCurvature; +extern INT64 nVidBlitterOpt[]; +extern INT32 bVidFullStretch; +extern INT32 bVidTripleBuffer; +extern INT32 bVidVSync; +extern double dVidCubicB; +extern double dVidCubicC; +extern INT32 bVidDX9Bilinear; +extern INT32 bVidHardwareVertex; +extern INT32 bVidMotionBlur; +extern INT32 nVidScrnWidth, nVidScrnHeight; +extern INT32 nVidScrnDepth; + +extern INT32 nVidScrnAspectX, nVidScrnAspectY; + +extern UINT8* pVidImage; +extern INT32 nVidImageWidth, nVidImageHeight; +extern INT32 nVidImageLeft, nVidImageTop; +extern INT32 nVidImagePitch, nVidImageBPP; +extern INT32 nVidImageDepth; + +extern "C" UINT32 (__cdecl *VidHighCol) (INT32 r, INT32 g, INT32 b, INT32 i); + +// vid_directx_support.cpp + +INT32 VidSNewTinyMsg(const TCHAR* pText, INT32 nRGB = 0, INT32 nDuration = 0, INT32 nPiority = 5); + +INT32 VidSNewShortMsg(const TCHAR* pText, INT32 nRGB = 0, INT32 nDuration = 0, INT32 nPiority = 5); +void VidSKillShortMsg(); + +INT32 VidSAddChatMsg(const TCHAR* pID, INT32 nIDRGB, const TCHAR* pMain, INT32 nMainRGB); + +#define MAX_CHAT_SIZE (128) + +extern INT32 nVidSDisplayStatus; +extern INT32 nMaxChatFontSize; +extern INT32 nMinChatFontSize; +extern bool bEditActive; +extern bool bEditTextChanged; +extern TCHAR EditText[MAX_CHAT_SIZE + 1]; + +// osd text display for dx9 +extern TCHAR OSDMsg[MAX_PATH]; +extern UINT32 nOSDTimer; +void VidSKillOSDMsg(); diff --git a/src/interface/lowpass2.cpp b/src/interface/lowpass2.cpp new file mode 100644 index 00000000..d15d0062 --- /dev/null +++ b/src/interface/lowpass2.cpp @@ -0,0 +1,118 @@ +// LowPass2 module +// --------------- +// by Daniel Moreno - ComaC (2001) < comac2k@teleline.es > +// +// This is a straight-forward implementation of a 2nd order resonant +// lowpass filter. Well... in fact there are two lowpass filters being +// calculated at the same time, since the old convolution filter cannot +// be emulated with only one. +// +// The only optimization i've made is to change doubles for fixed point +// integers. + +#include +#include "burner.h" +#include "lowpass2.h" + +#define PI 3.141592653589793238462643383279502884197169399375105820974944592307816 +#define FixBits 15 +#define Fixed(A) ( (int)((A) * (1 << FixBits)) ) + + +#define SATURATE(Min, Max, Val) ( (Val) <= (Min) ? (Min) : (Val) > (Max) ? (Max) : (Val) ) + +// In case we know we will not run out of range (speeds up by 5% on gcc2.95.3): +//#define SATURATE(Min, Max, Val) (Val) + + + +LowPass2::LowPass2(void) +{ +} + + +LowPass2::LowPass2(double Freq, double SampleRate, double Q, double Gain, + double Freq2, double Q2, double Gain2) +{ + SetParam(Freq, SampleRate, Q, Gain, Freq2, Q2, Gain2); +} + + +void LowPass2::Filter(INT16 *Buff, INT32 Tam) +{ + INT32 a; + INT32 Tmp, Tmp2; + + for (a = 0; a < Tam*2; a += 2) + { + Tmp = (b0*Buff[a] + b1*i1 + b2*i2 + - a1*o1 - a2*o2) / (1 << FixBits); + + Tmp2 = (b0b*Buff[a] + b1b*i1 + b2b*i2 + - a1b*o1b - a2b*o2b) / (1 << FixBits); + + i2 = i1; + i1 = Buff[a]; + o2 = o1; + o1 = Tmp; + + o2b = o1b; + o1b = Tmp2; + + // Buff[a] = (short)SATURATE(-32768, 32767, Tmp + Tmp2); + Buff[a] = (INT16)SATURATE(-32768, 32767, Tmp + Tmp2)*(1-bRunPause); + } +} + + + +void LowPass2::SetParam(double Freq, double SampleRate, double Q, double Gain, + double Freq2, double Q2, double Gain2) +{ + double omega, sn, cs, alpha; + + if (Q < 0) { Q = 0; } + + if (Freq < 0) { Freq = 0; } + if (Freq > SampleRate/2) { Freq = SampleRate/2; } + + omega = PI * 2 * Freq / SampleRate; + sn = sin(omega); + cs = cos(omega); + alpha = sn / (2 * Q); + + a0 = Fixed(1 + alpha); + b0 = Fixed( ((1 - cs) / 2) * Gain / (1 + alpha) ); + b1 = Fixed( (1 - cs) * Gain / (1 + alpha) ); + b2 = Fixed( ((1 - cs) / 2) * Gain / (1 + alpha) ); + a1 = Fixed( (-2 * cs) / (1 + alpha) ); + a2 = Fixed( (1 - alpha) / (1 + alpha) ); + + + if (Q2 < 0) { Q2 = 0; } + + if (Freq2 < 0) { Freq2 = 0; } + if (Freq2 > SampleRate/2) { Freq2 = SampleRate/2; } + + omega = PI * 2 * Freq2 / SampleRate; + sn = sin(omega); + cs = cos(omega); + alpha = sn / (2 * Q2); + + a0b = Fixed(1 + alpha); + b0b = Fixed( ((1 - cs) / 2) * Gain2 / (1 + alpha) ); + b1b = Fixed( (1 - cs) * Gain2 / (1 + alpha) ); + b2b = Fixed( ((1 - cs) / 2) * Gain2 / (1 + alpha) ); + a1b = Fixed( (-2 * cs) / (1 + alpha) ); + a2b = Fixed( (1 - alpha) / (1 + alpha) ); + + i0 = 0; + i1 = 0; + i2 = 0; + o0 = 0; + o1 = 0; + o2 = 0; + o0b = 0; + o1b = 0; + o2b = 0; +} diff --git a/src/interface/lowpass2.h b/src/interface/lowpass2.h new file mode 100644 index 00000000..f6e8a707 --- /dev/null +++ b/src/interface/lowpass2.h @@ -0,0 +1,25 @@ +#ifndef HIPASS_INCLUDED +#define HIPASS_INCLUDED + +class LowPass2 +{ +public: + LowPass2(void); + LowPass2(double Freq, double SampleRate, double Q, double Gain, + double Freq2, double Q2, double Gain2); + + void Filter(INT16 *Buff, INT32 Tam); + void SetParam(double Freq, double SampleRate, double Q, double Gain, + double Freq2, double Q2, double Gain2); + +private: + INT32 a0, a1, a2, b0, b1, b2; + INT32 i0, i1, i2, o0, o1, o2; + + INT32 a0b, a1b, a2b, b0b, b1b, b2b; + INT32 o0b, o1b, o2b; + + // Yes, I know some of these are not used +}; + +#endif diff --git a/src/interface/prf_interface.cpp b/src/interface/prf_interface.cpp new file mode 100644 index 00000000..856e9a5f --- /dev/null +++ b/src/interface/prf_interface.cpp @@ -0,0 +1,108 @@ +// Profiling support +#include "burner.h" + +bool bProfileOkay = false; +UINT32 nProfileSelect = 0; + +static InterfaceInfo ProfileInfo = { NULL, NULL, NULL }; + +#if defined (BUILD_WIN32) + extern struct ProfileDo cntDoPerfCount; +#elif defined (BUILD_SDL) + extern struct ProfileDo cntDoPerfCount; +#endif + +static struct ProfileDo* pProfileDo[] = +{ +#if defined (BUILD_WIN32) + &cntDoPerfCount, +#elif defined (BUILD_SDL) + &cntDoPerfCount, +#endif +}; + +#define PROFILE_LEN (sizeof(pProfileDo) / sizeof(pProfileDo[0])) + +INT32 ProfileExit() +{ + IntInfoFree(&ProfileInfo); + + if (!bProfileOkay || nProfileSelect >= PROFILE_LEN) { + return 1; + } + bProfileOkay = false; + + return pProfileDo[nProfileSelect]->ProfileExit(); +} + +INT32 ProfileInit() +{ + INT32 nRet; + + if (nProfileSelect >= PROFILE_LEN) { + return 1; + } + + if ((nRet = pProfileDo[nProfileSelect]->ProfileInit()) == 0) { + bProfileOkay = true; + } + + return nRet; +} + +INT32 ProfileProfileStart(INT32 nSubSystem) +{ + if (!bProfileOkay || nProfileSelect >= PROFILE_LEN) { + return 1; + } + + return pProfileDo[nProfileSelect]->ProfileStart(nSubSystem); +} + +INT32 ProfileProfileEnd(INT32 nSubSystem) +{ + if (!bProfileOkay || nProfileSelect >= PROFILE_LEN) { + return 1; + } + + return pProfileDo[nProfileSelect]->ProfileEnd(nSubSystem); +} + +double ProfileProfileReadLast(INT32 nSubSystem) +{ + if (!bProfileOkay || nProfileSelect >= PROFILE_LEN) { + return 0.0; + } + + return pProfileDo[nProfileSelect]->ProfileReadLast(nSubSystem); +} + +double ProfileProfileReadAverage(INT32 nSubSystem) +{ + if (!bProfileOkay || nProfileSelect >= PROFILE_LEN) { + return 0.0; + } + + return pProfileDo[nProfileSelect]->ProfileReadAverage(nSubSystem); +} + +InterfaceInfo* ProfileGetInfo() +{ + if (IntInfoInit(&ProfileInfo)) { + IntInfoFree(&ProfileInfo); + return NULL; + } + + if (bProfileOkay) { + + ProfileInfo.pszModuleName = pProfileDo[nProfileSelect]->szModuleName; + + if (pProfileDo[nProfileSelect]->GetPluginSettings) { + pProfileDo[nProfileSelect]->GetPluginSettings(&ProfileInfo); + } + } else { + IntInfoAddStringInterface(&ProfileInfo, _T("Profiling module not initialised")); + } + + return &ProfileInfo; +} diff --git a/src/interface/scalers/2xpm.cpp b/src/interface/scalers/2xpm.cpp new file mode 100644 index 00000000..50a1d195 --- /dev/null +++ b/src/interface/scalers/2xpm.cpp @@ -0,0 +1,548 @@ +//--------------------------------------------------------------------------------------------------------------------------- +// 2xPM_LQ plugin for Kega Fusion - Pablo Medina (aka "pm") (pjmedina3@yahoo.com) +// Check for updated versions at: http://2xpm.freeservers.com +//--------------------------------------------------------------------------------------------------------------------------- + +//#include "2xpm_lq.h" + +//--------------------------------------------------------------------------------------------------------------------------- + +#define ENHANCE_COLORS 0 +#define LQ_ALPHA_BLEND 0 +#define SHOW_CHANGES 0 + +unsigned short int pg_red_mask; +unsigned short int pg_green_mask; +unsigned short int pg_blue_mask; +unsigned short int pg_lbmask; + +#define RED_MASK565 0xF800 +#define GREEN_MASK565 0x07E0 +#define BLUE_MASK565 0x001F + +#define RED_MASK555 0x7C00 +#define GREEN_MASK555 0x03E0 +#define BLUE_MASK555 0x001F + +#define PG_LBMASK565 0xF7DE +#define PG_LBMASK555 0x7BDE + +#if LQ_ALPHA_BLEND +#define ALPHA_BLEND_128_W(dst, src) dst = (src + dst) >> 1 +#else +#define ALPHA_BLEND_128_W(dst, src) dst = ((src & pg_lbmask) >> 1) + ((dst & pg_lbmask) >> 1) +#endif + +//--------------------------------------------------------------------------------------------------------------------------- + +static void _2xpm_lq_1516(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH) +{ + unsigned long x, y; + unsigned char *src, *dest; + unsigned short int PA, PB, PC, PD, PE, PF, PG, PH, PI; + register unsigned short int *start_addr1, *start_addr2, *start_addr3; + unsigned long next_line, next_line_src; + unsigned short int *dst_pixel; + unsigned long src_width, src_height; + unsigned long complete_line_src, complete_line_dst; + unsigned char auto_blend; + unsigned short int E[4]; + unsigned long src_pitch; + unsigned char pprev; + unsigned char dont_reblit; + + src = (unsigned char *)SrcPtr; + dest = (unsigned char *)DstPtr; + src_pitch = SrcPitch; + + next_line_src = src_pitch >> 1; + next_line = DstPitch >> 1; + + src_width = SrcW; + src_height = SrcH; + complete_line_src = next_line_src - SrcW; + complete_line_dst = DstPitch - SrcW * 2; + + start_addr2 = (unsigned short int *)(src - 2); + start_addr1 = start_addr2; + start_addr3 = start_addr2 + src_pitch; + + dst_pixel = (unsigned short int *)(dest); + + y = src_height - 1; + //for (y = 0; y < src_height; y++) + do + { + //if (y == src_height - 1) + if (!y) + start_addr3 = start_addr2; + auto_blend = 0; + pprev = 1; + x = src_width - 1; + + //for (x = 0; x < src_width; x++) + do + { + PB = start_addr1[1]; + PE = start_addr2[1]; + PH = start_addr3[1]; + + PA = start_addr1[pprev]; + PD = start_addr2[pprev]; + PG = start_addr3[pprev]; + + //if (x < src_width - 1) + if (x) + { + PC = start_addr1[2]; + PF = start_addr2[2]; + PI = start_addr3[2]; + } else { + PC = PB; + PF = PE; + PI = PH; + } + +#if SHOW_CHANGES + unsigned short int PDE = PE; + PE = 0; +#endif + E[0] = E[1] = E[2] = E[3] = PE; + + dont_reblit = 0; + + // Horizontal + if (!dont_reblit) + if (PD != PF) + { + if ((PE != PD) && (PD == PH) && (PD == PI) && (PE != PG) + && ((PD != PG) || (PE != PF) || (PA != PD)) + && (!((PD == PA) && (PD == PG) && (PE == PB) && (PE == PF))) + ) + { + E[2] = PH; + ALPHA_BLEND_128_W(E[3], PH); + dont_reblit = 1; + } + + else if ((PE != PF) && (PF == PH) && (PF == PG) && (PE != PI) + && ((PF != PI) || (PE != PD) || (PC != PF)) + && (!((PF == PC) && (PF == PI) && (PE == PB) && (PE == PD))) + ) + { + ALPHA_BLEND_128_W(E[2], PH); + E[3] = PH; + dont_reblit = 1; + } + } + + if (!dont_reblit) + { + if ((PB != PH) && (PD != PF)) + { + if ((PB == PD) && (PE != PD) + && (!((PE == PF) && (((PE == PA) && (PB == PC)) + || ((PD == PA) && (PD == PC) && (PG != PD) && (PG != PE))))) + && (!((PB == PA) && (PB == PG)))) + ALPHA_BLEND_128_W(E[0], PB); + + else if ((PB == PF) && (PE != PF) + && (!((PE == PD) && (((PE == PC) && (PB == PA)) + || ((PF == PA) && (PF == PC) && (PE == PD) && (PI != PF) && (PI != PE))))) + && (!((PB == PC) && (PB == PI))) + ) + ALPHA_BLEND_128_W(E[1], PB); + + if ((PH == PD) && ((PE != PG) || (PE != PD) || ((PE != PF) && (PF == PI))) + && (!((PE == PF) && (((PE == PG) && (PH == PI)) + || ((PD == PG) && (PD == PI) && (PE == PF) && (PA != PD) && (PA != PE)) + || ((PE == PG) && (PH == PI))))) + && (!((PH == PG) && (PH == PA))) + ) + ALPHA_BLEND_128_W(E[2], PH); + + else if ((PH == PF) && ((PE != PI) || (PE != PF)) + && (!((PE == PD) && (((PE == PI) && (PH == PG)) + || ((PF == PG) && (PF == PI) && (PC != PF) && (PI != PE))))) + && (!((PH == PI) && (PH == PC))) + ) + ALPHA_BLEND_128_W(E[3], PH); + } else +#if SHOW_CHANGES + PE = PDE; +#endif + if ((PD == PB) && (PD == PF) && (PD == PH) && (PD != PE)) + { + if ((PD == PG) || (PD == PC)) + { + ALPHA_BLEND_128_W(E[1], PD); + E[2] = E[1]; + } + if ((PD == PA) || (PD == PI)) + { + ALPHA_BLEND_128_W(E[0], PD); + E[3] = E[0]; + } + } + } + + dst_pixel[0] = E[0]; + dst_pixel[1] = E[1]; + dst_pixel[next_line] = E[2]; + dst_pixel[next_line + 1] = E[3]; + + start_addr1++; + start_addr2++; + start_addr3++; + + dst_pixel += 2; + pprev = 0; + } while (x--); + + start_addr2 += complete_line_src; + start_addr1 = start_addr2 - next_line_src; + start_addr3 = start_addr2 + next_line_src; + dst_pixel += complete_line_dst; + } while(y--); +} + +//--------------------------------------------------------------------------------------------------------------------------- + +void _2xpm_lq(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH, int nDepth) +{ + if (nDepth == 15) { + pg_red_mask = RED_MASK555; + pg_green_mask = GREEN_MASK555; + pg_blue_mask = BLUE_MASK555; + pg_lbmask = PG_LBMASK555; + } + else if (nDepth == 16) { + pg_red_mask = RED_MASK565; + pg_green_mask = GREEN_MASK565; + pg_blue_mask = BLUE_MASK565; + pg_lbmask = PG_LBMASK565; + } + else { + return; + } + + _2xpm_lq_1516(SrcPtr, DstPtr, SrcPitch, DstPitch, SrcW, SrcH); +} + +//--------------------------------------------------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------------------------------------- +// 2xPM plugin for Kega Fusion - Pablo Medina (aka "pm") (pjmedina3@yahoo.com) +// Check for updated versions at: http://2xpm.freeservers.com +//--------------------------------------------------------------------------------------------------------------------------- + +//#include "2xpm_hq.h" + +#define LQ_ALPHA_BLEND 0 +#define SHOW_CHANGES 0 + +#if LQ_ALPHA_BLEND +#define ALPHA_BLEND_128_W(dst, src) dst = ((src & pg_lbmask) >> 1) + ((dst & pg_lbmask) >> 1) +#define ALPHA_BLEND_64_W(dst, src) dst = src +#define ALPHA_BLEND_192_W(dst, src) dst = src +#else +#define ALPHA_BLEND_128_W(dst, src) dst = ((src & pg_lbmask) >> 1) + ((dst & pg_lbmask) >> 1) + +/* Weird */ +#define ALPHA_BLEND_64_W(dst, src) \ + dst = ( \ + (pg_red_mask & ((dst & pg_red_mask) + \ + ((((src & pg_red_mask) - \ + (dst & pg_red_mask))) >>2))) | \ + (pg_green_mask & ((dst & pg_green_mask) + \ + ((((src & pg_green_mask) - \ + (dst & pg_green_mask))) >>2))) | \ + (pg_blue_mask & ((dst & pg_blue_mask) + \ + ((((src & pg_blue_mask) - \ + (dst & pg_blue_mask))) >>2))) ) + +#define ALPHA_BLEND_192_W(dst, src) \ + dst = ( \ + (pg_red_mask & ((dst & pg_red_mask) + \ + ((((src & pg_red_mask) - \ + (dst & pg_red_mask)) * 192) >>8))) | \ + (pg_green_mask & ((dst & pg_green_mask) + \ + ((((src & pg_green_mask) - \ + (dst & pg_green_mask)) * 192) >>8))) | \ + (pg_blue_mask & ((dst & pg_blue_mask) + \ + ((((src & pg_blue_mask) - \ + (dst & pg_blue_mask)) * 192) >>8))) ); +#endif + +#define ALPHA_BLEND_W(dst, src, alpha) \ +dst = ( \ + (pg_red_mask & ((dst & pg_red_mask) + \ + ((((src & pg_red_mask) - \ + (dst & pg_red_mask)) * alpha) >>8))) | \ + (pg_green_mask & ((dst & pg_green_mask) + \ + ((((src & pg_green_mask) - \ + (dst & pg_green_mask)) * alpha) >>8))) | \ + (pg_blue_mask & ((dst & pg_blue_mask) + \ + ((((src & pg_blue_mask) - \ + (dst & pg_blue_mask)) * alpha) >>8))) ); \ + + //#define ALPHA_BLEND_128_W(dst, src) dst = src + +//--------------------------------------------------------------------------------------------------------------------------- + +static void _2xpm_hq_1516(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH) +{ + unsigned long x, y; + unsigned char *src, *dest; + unsigned short int PA, PB, PC, PD, PE, PF, PG, PH, PI; + register unsigned short int *start_addr1, *start_addr2, *start_addr3; + unsigned long next_line, next_line_src; + unsigned short int *dst_pixel; + unsigned long src_width, src_height; + unsigned long complete_line_src, complete_line_dst; + unsigned char auto_blend; + unsigned short int E[4]; + unsigned long src_pitch; + unsigned char pprev; + unsigned char dont_reblit; + + src = (unsigned char *)SrcPtr; + dest = (unsigned char *)DstPtr; + src_pitch = SrcPitch; + + next_line_src = src_pitch >> 1; + next_line = DstPitch >> 1; + + src_width = SrcW; + src_height = SrcH; + complete_line_src = next_line_src - SrcW; + complete_line_dst = DstPitch - SrcW * 2; + + start_addr2 = (unsigned short int *)(src - 2); + start_addr1 = start_addr2; + start_addr3 = start_addr2 + src_pitch; + + dst_pixel = (unsigned short int *)(dest); + + y = src_height; + //for (y = 0; y < src_height; y++) + while(y--) + { + //if (y == src_height - 1) + if (!y) + start_addr3 = start_addr2; + auto_blend = 0; + pprev = 1; + x = src_width; + + //for (x = 0; x < src_width; x++) + while(x--) + { + PB = start_addr1[1]; + PE = start_addr2[1]; + PH = start_addr3[1]; + + PA = start_addr1[pprev]; + PD = start_addr2[pprev]; + PG = start_addr3[pprev]; + + //if (x < src_width - 1) + if (x) + { + PC = start_addr1[2]; + PF = start_addr2[2]; + PI = start_addr3[2]; + } else { + PC = start_addr1[1]; + PF = start_addr2[1]; + PI = start_addr3[1]; + } + +#if SHOW_CHANGES + unsigned short int PDE = PE; + PE = 0; +#endif + + + dont_reblit = 0; + + /* Color enhancer */ + /* + unsigned char pattern = ((PE == PA) << 0) | ((PE == PB) << 1) | ((PE == PC) << 2) + | ((PE == PD) << 3) | ((PE == PF) << 4) + | ((PE == PG) << 5) | ((PE == PH) << 6) | ((PE == PI) << 7); + */ + + E[0] = E[1] = E[2] = E[3] = PE; + + // Horizontal + if (!dont_reblit) + { + if (PD != PF) + { + if ((PE != PD) && (PD == PH) && (PD == PI) && (PE != PG) + && ((PD != PG) || (PE != PF) || (PA != PD)) + && (!((PD == PA) && (PD == PG) && (PE == PB) && (PE == PF))) + ) + { + E[2] = PH; + ALPHA_BLEND_128_W(E[3], PH); + dont_reblit = 1; + } + + else if ((PE != PF) && (PF == PH) && (PF == PG) && (PE != PI) + && ((PF != PI) || (PE != PD) || (PC != PF)) + && (!((PF == PC) && (PF == PI) && (PE == PB) && (PE == PD))) + ) + { + ALPHA_BLEND_128_W(E[2], PH); + E[3] = PH; + dont_reblit = 1; + } + } + // Vertical + if (PB != PH) + { + if (PE != PB) + { + if ((PA != PB) || (PB != PC) || (PE != PH)) + { + if ((PB == PD) && (PB == PG) && (PE != PA) + && (!((PD == PA) && (PD == PC) && (PE == PH) && (PE == PF))) + ) + { + ALPHA_BLEND_192_W(E[0], PB); + ALPHA_BLEND_64_W(E[2], PB); + dont_reblit = 1; + } + else if ((PB == PF) && (PB == PI) && (PE != PC) + && (!((PF == PC) && (PF == PA) && (PE == PH) && (PE == PD))) + ) + { + ALPHA_BLEND_192_W(E[1], PB); + ALPHA_BLEND_64_W(E[3], PB); + dont_reblit = 1; + } + } + } + + if (PE != PH) + { + if ((PG != PH) || (PE != PB) || (PH != PI)) + { + if ((PH == PD) && (PH == PA) && (PE != PG) + && (!((PD == PG) && (PD == PI) && (PE == PB) && (PE == PF))) + ) + { + ALPHA_BLEND_192_W(E[2], PH); + ALPHA_BLEND_64_W(E[0], PH); + dont_reblit = 1; + } + + else if ((PH == PF) && (PH == PC) && (PE != PI) + && (!((PF == PI) && (PF == PG) && (PE == PB) && (PE == PD))) + ) + { + ALPHA_BLEND_192_W(E[3], PH); + ALPHA_BLEND_64_W(E[1], PH); + dont_reblit = 1; + } + } + } + } + } + + if (!dont_reblit) + { + if ((PB != PH) && (PD != PF)) + { + if ((PB == PD) && (PE != PD) + && (!((PE == PA) && (PB == PC) && (PE == PF))) // Block + && (!((PB == PA) && (PB == PG))) + && (!((PD == PA) && (PD == PC) && (PE == PF) && (PG != PD) && (PG != PE))) // OK + ) + ALPHA_BLEND_128_W(E[0], PB); + + if ((PB == PF) && (PE != PF) + && (!((PE == PC) && (PB == PA) && (PE == PD))) // Block + && (!((PB == PC) && (PB == PI))) + && (!((PF == PA) && (PF == PC) && (PE == PD) && (PI != PF) && (PI != PE))) // OK + ) + ALPHA_BLEND_128_W(E[1], PB); + + if ((PH == PD) && ((PE != PG) || (PE != PD)) + && (!((PE == PG) && (PH == PI) && (PE == PF))) // Block + && (!((PH == PG) && (PH == PA))) + && (!((PD == PG) && (PD == PI) && (PE == PF) && (PA != PD) && (PA != PE))) // OK + ) + ALPHA_BLEND_128_W(E[2], PH); + + if ((PH == PF) && ((PE != PI) || (PE != PF)) + && (!((PE == PI) && (PH == PG) && (PE == PD))) // Block + && (!((PH == PI) && (PH == PC))) + && (!((PF == PG) && (PF == PI) && (PE == PD) && (PC != PF) && (PI != PE))) // OK + ) + ALPHA_BLEND_128_W(E[3], PH); + } else +#if SHOW_CHANGES + PE = PDE; +#endif + if ((PD == PB) && (PD == PF) && (PD == PH) && (PD != PE)) + { + if ((PD == PG) || (PD == PC)) + { + ALPHA_BLEND_128_W(E[1], PD); + E[2] = E[1]; + } + if ((PD == PA) || (PD == PI)) + { + ALPHA_BLEND_128_W(E[0], PD); + E[3] = E[0]; + } + } + } + + dst_pixel[0] = E[0]; + dst_pixel[1] = E[1]; + dst_pixel[next_line] = E[2]; + dst_pixel[next_line + 1] = E[3]; + + start_addr1++; + start_addr2++; + start_addr3++; + + dst_pixel += 2; + pprev = 0; + } + + start_addr2 += complete_line_src; + start_addr1 = start_addr2 - next_line_src; + start_addr3 = start_addr2 + next_line_src; + dst_pixel += complete_line_dst; + } +} + +//--------------------------------------------------------------------------------------------------------------------------- + +void _2xpm_hq(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH, int nDepth) +{ + if (nDepth == 15) { + pg_red_mask = RED_MASK555; + pg_green_mask = GREEN_MASK555; + pg_blue_mask = BLUE_MASK555; + pg_lbmask = PG_LBMASK555; + } + else if (nDepth == 16) { + pg_red_mask = RED_MASK565; + pg_green_mask = GREEN_MASK565; + pg_blue_mask = BLUE_MASK565; + pg_lbmask = PG_LBMASK565; + } + else { + return; + } + + _2xpm_hq_1516(SrcPtr, DstPtr, SrcPitch, DstPitch, SrcW, SrcH); +} + +//--------------------------------------------------------------------------------------------------------------------------- diff --git a/src/interface/scalers/2xsai.cpp b/src/interface/scalers/2xsai.cpp new file mode 100644 index 00000000..3f460f86 --- /dev/null +++ b/src/interface/scalers/2xsai.cpp @@ -0,0 +1,1208 @@ +//ref: http://vba-rerecording.googlecode.com/svn/trunk/src/2xsai.cpp + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef int s32; + +static u32 colorMask = 0xF7DEF7DE; +static u32 lowPixelMask = 0x08210821; +static u32 qcolorMask = 0xE79CE79C; +static u32 qlowpixelMask = 0x18631863; +static u32 redblueMask = 0xF81F; +static u32 greenMask = 0x7E0; + +int Init_2xSaI(u32 BitFormat, u32 systemColorDepth) +{ + if(systemColorDepth == 16) { + if (BitFormat == 565) { + colorMask = 0xF7DEF7DE; + lowPixelMask = 0x08210821; + qcolorMask = 0xE79CE79C; + qlowpixelMask = 0x18631863; + redblueMask = 0xF81F; + greenMask = 0x7E0; + } else if (BitFormat == 555) { + colorMask = 0x7BDE7BDE; + lowPixelMask = 0x04210421; + qcolorMask = 0x739C739C; + qlowpixelMask = 0x0C630C63; + redblueMask = 0x7C1F; + greenMask = 0x3E0; + } else { + return 0; + } + } else if(systemColorDepth == 32) { + colorMask = 0xfefefe; + lowPixelMask = 0x010101; + qcolorMask = 0xfcfcfc; + qlowpixelMask = 0x030303; + } else + return 0; + + return 1; +} + +static inline int GetResult1 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline int GetResult2 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r -= 1; + if (y <= 1) + r += 1; + return r; +} + +static inline int GetResult (u32 A, u32 B, u32 C, u32 D) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline u32 INTERPOLATE (u32 A, u32 B) +{ + if (A != B) { + return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + + (A & B & lowPixelMask)); + } else + return A; +} + +static inline u32 Q_INTERPOLATE (u32 A, u32 B, u32 C, u32 D) +{ + register u32 x = ((A & qcolorMask) >> 2) + + ((B & qcolorMask) >> 2) + + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); + register u32 y = (A & qlowpixelMask) + + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); + + y = (y >> 2) & qlowpixelMask; + return x + y; +} + +static inline int GetResult1_32 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline int GetResult2_32 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r -= 1; + if (y <= 1) + r += 1; + return r; +} + +#define BLUE_MASK565 0x001F001F +#define RED_MASK565 0xF800F800 +#define GREEN_MASK565 0x07E007E0 + +#define BLUE_MASK555 0x001F001F +#define RED_MASK555 0x7C007C00 +#define GREEN_MASK555 0x03E003E0 + +void Super2xSaI (u8 *srcPtr, u32 srcPitch, + u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, + int width, int height) +{ + u16 *bP; + u8 *dP; + u32 inc_bP; + u32 Nextline = srcPitch >> 1; + + { + inc_bP = 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; + dP = (u8 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + //--------------------------------------- B1 B2 + // 4 5 6 S2 + // 1 2 3 S1 + // A1 A2 + + colorB0 = *(bP - Nextline - 1); + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + colorB3 = *(bP - Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + //-------------------------------------- + if (color2 == color6 && color5 != color3) { + product2b = product1b = color2; + } else if (color5 == color3 && color2 != color6) { + product2b = product1b = color5; + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else { + product2b = product1b = INTERPOLATE (color5, color6); + } + } else { + if (color6 == color3 && color3 == colorA1 + && color2 != colorA2 && color3 != colorA0) + product2b = + Q_INTERPOLATE (color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 + && colorA1 != color3 && color2 != colorA3) + product2b = + Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 + && color5 != colorB2 && color6 != colorB0) + product1b = + Q_INTERPOLATE (color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 + && colorB1 != color6 && color5 != colorB3) + product1b = + Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 + && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 + && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE (color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 + && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 + && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE (color2, color5); + else + product1a = color5; + +#ifdef WORDS_BIGENDIAN + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((u32 *) dP) = product1a; + *((u32 *) (dP + dstPitch)) = product2a; + + bP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + deltaPtr += srcPitch; + } // endof: for (; height; height--) + } +} + +void Super2xSaI32 (u8 *srcPtr, u32 srcPitch, + u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, + int width, int height) +{ + u32 *bP; + u32 *dP; + u32 inc_bP; + u32 Nextline = srcPitch >> 2; + inc_bP = 1; + + for (; height; height--) { + bP = (u32 *) srcPtr; + dP = (u32 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + //--------------------------------------- B1 B2 + // 4 5 6 S2 + // 1 2 3 S1 + // A1 A2 + + colorB0 = *(bP - Nextline - 1); + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + colorB3 = *(bP - Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + //-------------------------------------- + if (color2 == color6 && color5 != color3) { + product2b = product1b = color2; + } else if (color5 == color3 && color2 != color6) { + product2b = product1b = color5; + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else { + product2b = product1b = INTERPOLATE (color5, color6); + } + } else { + if (color6 == color3 && color3 == colorA1 + && color2 != colorA2 && color3 != colorA0) + product2b = + Q_INTERPOLATE (color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 + && colorA1 != color3 && color2 != colorA3) + product2b = + Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 + && color5 != colorB2 && color6 != colorB0) + product1b = + Q_INTERPOLATE (color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 + && colorB1 != color6 && color5 != colorB3) + product1b = + Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 + && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 + && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE (color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 + && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 + && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE (color2, color5); + else + product1a = color5; + *(dP) = product1a; + *(dP+1) = product1b; + *(dP + (dstPitch >> 2)) = product2a; + *(dP + (dstPitch >> 2) + 1) = product2b; + + bP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + // deltaPtr += srcPitch; + } // endof: for (; height; height--) +} + +void SuperEagle (u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 *dP; + u16 *bP; + u16 *xP; + u32 inc_bP; + + { + inc_bP = 1; + + u32 Nextline = srcPitch >> 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; + xP = (u16 *) deltaPtr; + dP = dstPtr; + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + + // -------------------------------------- + if (color2 == color6 && color5 != color3) { + product1b = product2a = color2; + if ((color1 == color2) || (color6 == colorB2)) { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); + // product1a = color2; + } else { + product1a = INTERPOLATE (color5, color6); + } + + if ((color6 == colorS2) || (color2 == colorA1)) { + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); + // product2b = color2; + } else { + product2b = INTERPOLATE (color2, color3); + } + } else if (color5 == color3 && color2 != color6) { + product2b = product1a = color5; + + if ((colorB1 == color5) || (color3 == colorS1)) { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); + // product1b = color5; + } else { + product1b = INTERPOLATE (color5, color6); + } + + if ((color3 == colorA2) || (color4 == color5)) { + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); + // product2a = color5; + } else { + product2a = INTERPOLATE (color2, color3); + } + + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } else if (r < 0) { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } else { + product2b = product1a = color5; + product1b = product2a = color2; + } + } else { + product2b = product1a = INTERPOLATE (color2, color6); + product2b = + Q_INTERPOLATE (color3, color3, color3, product2b); + product1a = + Q_INTERPOLATE (color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE (color5, color3); + product2a = + Q_INTERPOLATE (color2, color2, color2, product2a); + product1b = + Q_INTERPOLATE (color6, color6, color6, product1b); + + // product1a = color5; + // product1b = color6; + // product2a = color2; + // product2b = color3; + } +#ifdef WORDS_BIGENDIAN + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((u32 *) dP) = product1a; + *((u32 *) (dP + dstPitch)) = product2a; + *xP = color5; + + bP += inc_bP; + xP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + deltaPtr += srcPitch; + } // endof: for (height; height; height--) + } +} + +void SuperEagle32 (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dP; + u32 *bP; +// u32 *xP; + u32 inc_bP; + + inc_bP = 1; + + u32 Nextline = srcPitch >> 2; + + for (; height; height--) { + bP = (u32 *) srcPtr; +// xP = (u32 *) deltaPtr; + dP = (u32 *)dstPtr; + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + + // -------------------------------------- + if (color2 == color6 && color5 != color3) { + product1b = product2a = color2; + if ((color1 == color2) || (color6 == colorB2)) { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); + // product1a = color2; + } else { + product1a = INTERPOLATE (color5, color6); + } + + if ((color6 == colorS2) || (color2 == colorA1)) { + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); + // product2b = color2; + } else { + product2b = INTERPOLATE (color2, color3); + } + } else if (color5 == color3 && color2 != color6) { + product2b = product1a = color5; + + if ((colorB1 == color5) || (color3 == colorS1)) { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); + // product1b = color5; + } else { + product1b = INTERPOLATE (color5, color6); + } + + if ((color3 == colorA2) || (color4 == color5)) { + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); + // product2a = color5; + } else { + product2a = INTERPOLATE (color2, color3); + } + + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } else if (r < 0) { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } else { + product2b = product1a = color5; + product1b = product2a = color2; + } + } else { + product2b = product1a = INTERPOLATE (color2, color6); + product2b = + Q_INTERPOLATE (color3, color3, color3, product2b); + product1a = + Q_INTERPOLATE (color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE (color5, color3); + product2a = + Q_INTERPOLATE (color2, color2, color2, product2a); + product1b = + Q_INTERPOLATE (color6, color6, color6, product1b); + + // product1a = color5; + // product1b = color6; + // product2a = color2; + // product2b = color3; + } + *(dP) = product1a; + *(dP+1) = product1b; + *(dP + (dstPitch >> 2)) = product2a; + *(dP + (dstPitch >> 2) +1) = product2b; +// *xP = color5; + + bP += inc_bP; +// xP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; +// deltaPtr += srcPitch; + } // endof: for (height; height; height--) +} + +void _2xSaI (u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 *dP; + u16 *bP; + u32 inc_bP; + + { + inc_bP = 1; + + u32 Nextline = srcPitch >> 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; + dP = dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + + register u32 colorA, colorB; + u32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + + colorM, colorN, colorO, colorP; + u32 product, product1, product2; + + //--------------------------------------- + // Map of the pixels: I|E F|J + // G|A B|K + // H|C D|L + // M|N O|P + colorI = *(bP - Nextline - 1); + colorE = *(bP - Nextline); + colorF = *(bP - Nextline + 1); + colorJ = *(bP - Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) { + if (((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ))) { + product = colorA; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM))) { + product1 = colorA; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorA; + } else if ((colorB == colorC) && (colorA != colorD)) { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI))) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI))) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorB; + } else if ((colorA == colorD) && (colorB == colorC)) { + if (colorA == colorB) { + product = colorA; + product1 = colorA; + product2 = colorA; + } else { + register int r = 0; + + product1 = INTERPOLATE (colorA, colorC); + product = INTERPOLATE (colorA, colorB); + + r += + GetResult1 (colorA, colorB, colorG, colorE, + colorI); + r += + GetResult2 (colorB, colorA, colorK, colorF, + colorJ); + r += + GetResult2 (colorB, colorA, colorH, colorN, + colorM); + r += + GetResult1 (colorA, colorB, colorL, colorO, + colorP); + + if (r > 0) + product2 = colorA; + else if (r < 0) + product2 = colorB; + else { + product2 = + Q_INTERPOLATE (colorA, colorB, colorC, + colorD); + } + } + } else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ)) { + product = colorA; + } else if ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI)) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM)) { + product1 = colorA; + } else if ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI)) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + } + +#ifdef WORDS_BIGENDIAN + product = (colorA << 16) | product ; + product1 = (product1 << 16) | product2 ; +#else + product = colorA | (product << 16); + product1 = product1 | (product2 << 16); +#endif + *((s32 *) dP) = product; + *((u32 *) (dP + dstPitch)) = product1; + + bP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + deltaPtr += srcPitch; + } // endof: for (height; height; height--) + } +} + +void _2xSaI32 (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dP; + u32 *bP; + u32 inc_bP = 1; + + u32 Nextline = srcPitch >> 2; + + for (; height; height--) { + bP = (u32 *) srcPtr; + dP = (u32 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + register u32 colorA, colorB; + u32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + + colorM, colorN, colorO, colorP; + u32 product, product1, product2; + + //--------------------------------------- + // Map of the pixels: I|E F|J + // G|A B|K + // H|C D|L + // M|N O|P + colorI = *(bP - Nextline - 1); + colorE = *(bP - Nextline); + colorF = *(bP - Nextline + 1); + colorJ = *(bP - Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) { + if (((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ))) { + product = colorA; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM))) { + product1 = colorA; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorA; + } else if ((colorB == colorC) && (colorA != colorD)) { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI))) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI))) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorB; + } else if ((colorA == colorD) && (colorB == colorC)) { + if (colorA == colorB) { + product = colorA; + product1 = colorA; + product2 = colorA; + } else { + register int r = 0; + + product1 = INTERPOLATE (colorA, colorC); + product = INTERPOLATE (colorA, colorB); + + r += + GetResult1 (colorA, colorB, colorG, colorE, + colorI); + r += + GetResult2 (colorB, colorA, colorK, colorF, + colorJ); + r += + GetResult2 (colorB, colorA, colorH, colorN, + colorM); + r += + GetResult1 (colorA, colorB, colorL, colorO, + colorP); + + if (r > 0) + product2 = colorA; + else if (r < 0) + product2 = colorB; + else { + product2 = + Q_INTERPOLATE (colorA, colorB, colorC, + colorD); + } + } + } else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ)) { + product = colorA; + } else if ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI)) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM)) { + product1 = colorA; + } else if ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI)) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + } + *(dP) = colorA; + *(dP + 1) = product; + *(dP + (dstPitch >> 2)) = product1; + *(dP + (dstPitch >> 2) + 1) = product2; + + bP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + // deltaPtr += srcPitch; + } // endof: for (height; height; height--) +} + +static u32 Bilinear (u32 A, u32 B, u32 x) +{ + unsigned long areaA, areaB; + unsigned long result; + + if (A == B) + return A; + + areaB = (x >> 11) & 0x1f; // reduce 16 bit fraction to 5 bits + areaA = 0x20 - areaB; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + + result = ((areaA * A) + (areaB * B)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); +} + +static u32 Bilinear4 (u32 A, u32 B, u32 C, u32 D, u32 x, + u32 y) +{ + unsigned long areaA, areaB, areaC, areaD; + unsigned long result, xy; + + x = (x >> 11) & 0x1f; + y = (y >> 11) & 0x1f; + xy = (x * y) >> 5; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + C = (C & redblueMask) | ((C & greenMask) << 16); + D = (D & redblueMask) | ((D & greenMask) << 16); + + areaA = 0x20 + xy - x - y; + areaB = x - xy; + areaC = y - xy; + areaD = xy; + + result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); +} + +void Scale_2xSaI (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, + u32 dstWidth, u32 dstHeight, int width, int height) +{ + u8 *dP; + u16 *bP; + + u32 w; + u32 h; + u32 dw; + u32 dh; + u32 hfinish; + u32 wfinish; + + u32 Nextline = srcPitch >> 1; + + wfinish = (width - 1) << 16; // convert to fixed point + dw = wfinish / (dstWidth - 1); + hfinish = (height - 1) << 16; // convert to fixed point + dh = hfinish / (dstHeight - 1); + + for (h = 0; h < hfinish; h += dh) { + u32 y1, y2; + + y1 = h & 0xffff; // fraction part of fixed point + bP = (u16 *) (srcPtr + ((h >> 16) * srcPitch)); + dP = dstPtr; + y2 = 0x10000 - y1; + + w = 0; + + for (; w < wfinish;) { + u32 A, B, C, D; + u32 E, F, G, H; + u32 I, J, K, L; + u32 x1, x2, a1, f1, f2; + u32 position, product1; + + position = w >> 16; + A = bP[position]; // current pixel + B = bP[position + 1]; // next pixel + C = bP[position + Nextline]; + D = bP[position + Nextline + 1]; + E = bP[position - Nextline]; + F = bP[position - Nextline + 1]; + G = bP[position - 1]; + H = bP[position + Nextline - 1]; + I = bP[position + 2]; + J = bP[position + Nextline + 2]; + K = bP[position + Nextline + Nextline]; + L = bP[position + Nextline + Nextline + 1]; + + x1 = w & 0xffff; // fraction part of fixed point + x2 = 0x10000 - x1; + + /*0*/ + if (A == B && C == D && A == C) + product1 = A; + else /*1*/ if (A == D && B != C) { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y1 <= f1 && A == J && A != E) // close to B + { + a1 = f1 - y1; + product1 = Bilinear (A, B, a1); + } else if (y1 >= f1 && A == G && A != L) // close to C + { + a1 = y1 - f1; + product1 = Bilinear (A, C, a1); + } + else if (x1 >= f2 && A == E && A != J) // close to B + { + a1 = x1 - f2; + product1 = Bilinear (A, B, a1); + } + else if (x1 <= f2 && A == L && A != G) // close to C + { + a1 = f2 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 >= x1) // close to C + { + a1 = y1 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 <= x1) // close to B + { + a1 = x1 - y1; + product1 = Bilinear (A, B, a1); + } + } + else + /*2*/ + if (B == C && A != D) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y2 >= f1 && B == H && B != F) // close to A + { + a1 = y2 - f1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= f1 && B == I && B != K) // close to D + { + a1 = f1 - y2; + product1 = Bilinear (B, D, a1); + } + else if (x2 >= f2 && B == F && B != H) // close to A + { + a1 = x2 - f2; + product1 = Bilinear (B, A, a1); + } + else if (x2 <= f2 && B == K && B != I) // close to D + { + a1 = f2 - x2; + product1 = Bilinear (B, D, a1); + } + else if (y2 >= x1) // close to A + { + a1 = y2 - x1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= x1) // close to D + { + a1 = x1 - y2; + product1 = Bilinear (B, D, a1); + } + } + /*3*/ + else + { + product1 = Bilinear4 (A, B, C, D, x1, y1); + } + + //end First Pixel + *(u32 *) dP = product1; + dP += 2; + w += dw; + } + dstPtr += dstPitch; + } +} diff --git a/src/interface/scalers/2xsaimmx.asm b/src/interface/scalers/2xsaimmx.asm new file mode 100644 index 00000000..30e3f271 --- /dev/null +++ b/src/interface/scalers/2xsaimmx.asm @@ -0,0 +1,2067 @@ +;/*---------------------------------------------------------------------* +; * The following (piece of) code, (part of) the 2xSaI engine, * +; * copyright (c) 2001 by Derek Liauw Kie Fa. * +; * Non-Commercial use of the engine is allowed and is encouraged, * +; * provided that appropriate credit be given and that this copyright * +; * notice will not be removed under any circumstance. * +; * You may freely modify this code, but I request * +; * that any improvements to the engine be submitted to me, so * +; * that I can implement these improvements in newer versions of * +; * the engine. * +; * If you need more information, have any comments or suggestions, * +; * you can e-mail me. My e-mail: DerekL666@yahoo.com * +; *---------------------------------------------------------------------*/ + +;---------------------- +; 2xSaI, Super2xSaI, SuperEagle .. FINAL. no versioning anymore.. +;---------------------- + + BITS 32 +%ifdef __DJGPP__ +; GLOBAL __2xSaILine +; GLOBAL __2xSaISuperEagleLine +; GLOBAL _Init_2xSaIMMX +%else + global _2xSaILine + global __2xSaILine + global _2xSaISuperEagleLine + global __2xSaISuperEagleLine + global _2xSaISuper2xSaILine + global __2xSaISuper2xSaILine + global Init_2xSaIMMX + global _Init_2xSaIMMX +%endif + SECTION .text ALIGN = 32 + +%ifdef __DJGPP__ +;EXTERN_C void __2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width, +; uint8 *dstPtr, uint32 dstPitch, uint16 dstSegment); +%else +;EXTERN_C void _2xSaILine (uint8 *srcPtr, uint32 srcPitch, uint32 width, +; uint8 *dstPtr, uint32 dstPitch); +%endif + +srcPtr equ 8 +deltaPtr equ 12 +srcPitch equ 16 +width equ 20 +dstOffset equ 24 +dstPitch equ 28 +dstSegment equ 32 + + +colorB0 equ -2 +colorB1 equ 0 +colorB2 equ 2 +colorB3 equ 4 + +color7 equ -2 +color8 equ 0 +color9 equ 2 + +color4 equ -2 +color5 equ 0 +color6 equ 2 +colorS2 equ 4 + +color1 equ -2 +color2 equ 0 +color3 equ 2 +colorS1 equ 4 + +colorA0 equ -2 +colorA1 equ 0 +colorA2 equ 2 +colorA3 equ 4 + + + + + + + + + +_2xSaISuper2xSaILine: +__2xSaISuper2xSaILine: +; Store some stuff + push ebp + mov ebp, esp + pushad + +; Prepare the destination +%ifdef __DJGPP__ + ; Set the selector + mov eax, [ebp+dstSegment] + mov fs, ax +%endif + mov edx, [ebp+dstOffset] ; edx points to the screen +; Prepare the source + ; eax points to colorA + mov eax, [ebp+srcPtr] ;eax points to colorA + mov ebx, [ebp+srcPitch] ;ebx contains the source pitch + mov ecx, [ebp+width] ;ecx contains the number of pixels to process + ; eax now points to colorB1 + sub eax, ebx ;eax points to B1 which is the base + +; Main Loop +.Loop: push ecx + + ;-----Check Delta------------------ + mov ecx, [ebp+deltaPtr] + + + ;load source img + movq mm0, [eax+colorB0] + movq mm1, [eax+colorB3] + movq mm2, [eax+ebx+color4] + movq mm3, [eax+ebx+colorS2] + movq mm4, [eax+ebx+ebx+color1] + movq mm5, [eax+ebx+ebx+colorS1] + push eax + add eax, ebx + movq mm6, [eax+ebx+ebx+colorA0] + movq mm7, [eax+ebx+ebx+colorA3] + pop eax + + ;compare to delta + pcmpeqw mm0, [ecx+2+colorB0] + pcmpeqw mm1, [ecx+2+colorB3] + pcmpeqw mm2, [ecx+ebx+2+color4] + pcmpeqw mm3, [ecx+ebx+2+colorS2] + pcmpeqw mm4, [ecx+ebx+ebx+2+color1] + pcmpeqw mm5, [ecx+ebx+ebx+2+colorS1] + add ecx, ebx + pcmpeqw mm6, [ecx+ebx+ebx+2+colorA0] + pcmpeqw mm7, [ecx+ebx+ebx+2+colorA3] + sub ecx, ebx + + + ;compose results + pand mm0, mm1 + pand mm2, mm3 + pand mm4, mm5 + pand mm6, mm7 + pand mm0, mm2 + pand mm4, mm6 + pxor mm7, mm7 + pand mm0, mm4 + movq mm6, [eax+colorB0] + pcmpeqw mm7, mm0 ;did any compare give us a zero ? + + movq [ecx+2+colorB0], mm6 + + packsswb mm7, mm7 + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_PROCESS ;no, so we can skip + + ;End Delta + + ;--------------------------------- + movq mm0, [eax+ebx+color5] + movq mm1, [eax+ebx+color6] + movq mm2, mm0 + movq mm3, mm1 + movq mm4, mm0 + movq mm5, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + movq [I56Pixel], mm0 + movq mm7, mm0 + + ;------------------- + movq mm0, mm7 + movq mm1, mm4 ;5,5,5,6 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + movq [I5556Pixel], mm0 + ;-------------------- + + movq mm0, mm7 + movq mm1, mm5 ;6,6,6,5 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [I5666Pixel], mm0 + + ;------------------------- + ;------------------------- + movq mm0, [eax+ebx+ebx+color2] + movq mm1, [eax+ebx+ebx+color3] + movq mm2, mm0 + movq mm3, mm1 + movq mm4, mm0 + movq mm5, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [I23Pixel], mm0 + movq mm7, mm0 + + ;--------------------- + movq mm0, mm7 + movq mm1, mm4 ;2,2,2,3 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [I2223Pixel], mm0 + + ;---------------------- + movq mm0, mm7 + movq mm1, mm5 ;3,3,3,2 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [I2333Pixel], mm0 + + + ;-------------------- +;//////////////////////////////// +; Decide which "branch" to take +;-------------------------------- + movq mm0, [eax+ebx+color5] + movq mm1, [eax+ebx+color6] + movq mm6, mm0 + movq mm7, mm1 + pcmpeqw mm0, [eax+ebx+ebx+color3] + pcmpeqw mm1, [eax+ebx+ebx+color2] + pcmpeqw mm6, mm7 + + movq mm2, mm0 + movq mm3, mm0 + + pand mm0, mm1 ;colorA == colorD && colorB == colorC + pxor mm7, mm7 + + pcmpeqw mm2, mm7 + pand mm6, mm0 + pand mm2, mm1 ;colorA != colorD && colorB == colorC + + pcmpeqw mm1, mm7 + + pand mm1, mm3 ;colorA == colorD && colorB != colorC + pxor mm0, mm6 + por mm1, mm6 + movq mm7, mm0 + movq [Mask26], mm2 + packsswb mm7, mm7 + movq [Mask35], mm1 + + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_GUESS + +;--------------------------------------------- + movq mm6, mm0 + movq mm4, [eax+ebx+colorA] + movq mm5, [eax+ebx+colorB] + pxor mm7, mm7 + pand mm6, [ONE] + + movq mm0, [eax+colorE] + movq mm1, [eax+ebx+colorG] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+colorF] + movq mm1, [eax+ebx+colorK] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + push eax + add eax, ebx + movq mm0, [eax+ebx+colorH] + movq mm1, [eax+ebx+ebx+colorN] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+ebx+colorL] + movq mm1, [eax+ebx+ebx+colorO] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + pop eax + movq mm1, mm7 + pxor mm0, mm0 + pcmpgtw mm7, mm0 + pcmpgtw mm0, mm1 + + por mm7, [Mask35] + por mm0, [Mask26] + movq [Mask35], mm7 + movq [Mask26], mm0 + +.SKIP_GUESS: + + ;Start the ASSEMBLY !!! eh... compose all the results together to form the final image... + + + movq mm0, [eax+ebx+color5] + movq mm1, [eax+ebx+ebx+color2] + movq mm2, mm0 + movq mm3, mm1 + movq mm4, mm0 + movq mm5, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + ;--------------------------- + + + +%ifdef dfhsdfhsdahdsfhdsfh + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE(color2, color5); + else + product1a = color5; + +%endif + + + movq mm7, [Mask26] + movq mm6, [eax+colorB2] + movq mm5, [eax+ebx+ebx+color2] + movq mm4, [eax+ebx+ebx+color1] + pcmpeqw mm4, mm5 + pcmpeqw mm6, mm5 + pxor mm5, mm5 + pand mm7, mm4 + pcmpeqw mm6, mm5 + pand mm7, mm6 + + + + movq mm6, [eax+ebx+ebx+color3] + movq mm5, [eax+ebx+ebx+color2] + movq mm4, [eax+ebx+ebx+color1] + movq mm2, [eax+ebx+color5] + movq mm1, [eax+ebx+color4] + movq mm3, [eax+colorB0] + + pcmpeqw mm2, mm4 + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm3, mm5 + pxor mm5, mm5 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm6, mm1 + pand mm2, mm3 + pand mm6, mm2 + por mm7, mm6 + + + movq mm6, mm7 + pcmpeqw mm6, mm5 + pand mm7, mm0 + + movq mm1, [eax+ebx+color5] + pand mm6, mm1 + por mm7, mm6 + movq [final1a], mm7 ;finished 1a + + + + ;-------------------------------- + + movq mm7, [Mask35] + push eax + add eax, ebx + movq mm6, [eax+ebx+ebx+colorA2] + pop eax + movq mm5, [eax+ebx+color5] + movq mm4, [eax+ebx+color4] + pcmpeqw mm4, mm5 + pcmpeqw mm6, mm5 + pxor mm5, mm5 + pand mm7, mm4 + pcmpeqw mm6, mm5 + pand mm7, mm6 + + + + movq mm6, [eax+ebx+color6] + movq mm5, [eax+ebx+color5] + movq mm4, [eax+ebx+color4] + movq mm2, [eax+ebx+ebx+color2] + movq mm1, [eax+ebx+ebx+color1] + push eax + add eax, ebx + movq mm3, [eax+ebx+ebx+colorA0] + pop eax + + pcmpeqw mm2, mm4 + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm3, mm5 + pxor mm5, mm5 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm6, mm1 + pand mm2, mm3 + pand mm6, mm2 + por mm7, mm6 + + + movq mm6, mm7 + pcmpeqw mm6, mm5 + pand mm7, mm0 + + movq mm1, [eax+ebx+ebx+color2] + pand mm6, mm1 + por mm7, mm6 + movq [final2a], mm7 ;finished 2a + + + ;-------------------------------------------- + + +%ifdef dfhsdfhsdahdsfhdsfh + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); +%endif + + push eax + add eax, ebx + pxor mm7, mm7 + movq mm0, [eax+ebx+ebx+colorA0] + movq mm1, [eax+ebx+ebx+colorA1] + movq mm2, [eax+ebx+ebx+colorA2] + movq mm3, [eax+ebx+ebx+colorA3] + pop eax + movq mm4, [eax+ebx+ebx+color2] + movq mm5, [eax+ebx+ebx+color3] + movq mm6, [eax+ebx+color6] + + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm4, mm2 + pcmpeqw mm0, mm5 + pcmpeqw mm4, mm7 + pcmpeqw mm0, mm7 + pand mm0, mm4 + pand mm6, mm1 + pand mm0, mm6 + + movq mm4, [eax+ebx+color2] + movq mm5, [eax+ebx+ebx+color5] + movq mm6, [eax+ebx+ebx+color3] + + pcmpeqw mm5, mm4 + pcmpeqw mm2, mm4 + pcmpeqw mm1, mm6 + pcmpeqw mm3, mm4 + pcmpeqw mm1, mm7 + pcmpeqw mm3, mm7 + pand mm2, mm5 + pand mm1, mm3 + pand mm1, mm2 + + movq mm2, mm0 + movq mm7, [I2333Pixel] + movq mm6, [I2223Pixel] + movq mm5, [I23Pixel] + movq mm4, [Mask35] + movq mm3, [Mask26] + + por mm2, mm4 + pand mm4, [eax+ebx+ebx+color3] + por mm2, mm3 + pand mm3, [eax+ebx+ebx+color2] + por mm2, mm1 + pand mm0, mm7 + pand mm1, mm6 + pxor mm7, mm7 + pcmpeqw mm2, mm7 + por mm0, mm1 + por mm3, mm4 + pand mm2, mm5 + por mm0, mm3 + por mm0, mm2 + movq [final2b], mm0 + + ;----------------------------------- + + + pxor mm7, mm7 + movq mm0, [eax+colorB0] + movq mm1, [eax+colorB1] + movq mm2, [eax+colorB2] + movq mm3, [eax+colorB3] + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+color6] + movq mm6, [eax+ebx+ebx+color3] + + pcmpeqw mm6, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm4, mm2 + pcmpeqw mm0, mm5 + pcmpeqw mm4, mm7 + pcmpeqw mm0, mm7 + pand mm0, mm4 + pand mm6, mm1 + pand mm0, mm6 + + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+ebx+color2] + movq mm6, [eax+ebx+color6] + + pcmpeqw mm5, mm4 + pcmpeqw mm2, mm4 + pcmpeqw mm1, mm6 + pcmpeqw mm3, mm4 + pcmpeqw mm1, mm7 + pcmpeqw mm3, mm7 + pand mm2, mm5 + pand mm1, mm3 + pand mm1, mm2 + + movq mm2, mm0 + movq mm7, [I5666Pixel] + movq mm6, [I5556Pixel] + movq mm5, [I56Pixel] + movq mm4, [Mask35] + movq mm3, [Mask26] + + por mm2, mm4 + pand mm4, [eax+ebx+color5] + por mm2, mm3 + pand mm3, [eax+ebx+color6] + por mm2, mm1 + pand mm0, mm7 + pand mm1, mm6 + pxor mm7, mm7 + pcmpeqw mm2, mm7 + por mm0, mm1 + por mm3, mm4 + pand mm2, mm5 + por mm0, mm3 + por mm0, mm2 + movq [final1b], mm0 + + ;--------- + + movq mm0, [final1a] + movq mm4, [final2a] + movq mm2, [final1b] + movq mm6, [final2b] + + movq mm1, mm0 + movq mm5, mm4 + + + punpcklwd mm0, mm2 + punpckhwd mm1, mm2 + + punpcklwd mm4, mm6 + punpckhwd mm5, mm6 + + +%ifdef FAR_POINTER + movq [fs:edx], mm0 + movq [fs:edx+8], mm1 + push edx + add edx, [ebp+dstPitch] + movq [fs:edx], mm4 + movq [fs:edx+8], mm5 + pop edx +%else + movq [es:edx], mm0 + movq [es:edx+8], mm1 + push edx + add edx, [ebp+dstPitch] + movq [es:edx], mm4 + movq [es:edx+8], mm5 + pop edx +%endif +.SKIP_PROCESS: + mov ecx, [ebp+deltaPtr] + add ecx, 8 + mov [ebp+deltaPtr], ecx + add edx, 16 + add eax, 8 + + pop ecx + sub ecx, 4 + cmp ecx, 0 + jg near .Loop + +; Restore some stuff + popad + mov esp, ebp + pop ebp + emms + ret + + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- + + + + + + + +_2xSaISuperEagleLine: +__2xSaISuperEagleLine: +; Store some stuff + push ebp + mov ebp, esp + pushad + +; Prepare the destination +%ifdef __DJGPP__ + ; Set the selector + mov eax, [ebp+dstSegment] + mov fs, ax +%endif + mov edx, [ebp+dstOffset] ; edx points to the screen +; Prepare the source + ; eax points to colorA + mov eax, [ebp+srcPtr] + mov ebx, [ebp+srcPitch] + mov ecx, [ebp+width] + ; eax now points to colorB1 + sub eax, ebx + +; Main Loop +.Loop: push ecx + + ;-----Check Delta------------------ + mov ecx, [ebp+deltaPtr] + + movq mm0, [eax+colorB0] + movq mm1, [eax+colorB3] + movq mm2, [eax+ebx+color4] + movq mm3, [eax+ebx+colorS2] + movq mm4, [eax+ebx+ebx+color1] + movq mm5, [eax+ebx+ebx+colorS1] + push eax + add eax, ebx + movq mm6, [eax+ebx+ebx+colorA0] + movq mm7, [eax+ebx+ebx+colorA3] + pop eax + + pcmpeqw mm0, [ecx+2+colorB0] + pcmpeqw mm1, [ecx+2+colorB3] + pcmpeqw mm2, [ecx+ebx+2+color4] + pcmpeqw mm3, [ecx+ebx+2+colorS2] + pcmpeqw mm4, [ecx+ebx+ebx+2+color1] + pcmpeqw mm5, [ecx+ebx+ebx+2+colorS1] + add ecx, ebx + pcmpeqw mm6, [ecx+ebx+ebx+2+colorA0] + pcmpeqw mm7, [ecx+ebx+ebx+2+colorA3] + sub ecx, ebx + + + pand mm0, mm1 + pand mm2, mm3 + pand mm4, mm5 + pand mm6, mm7 + pand mm0, mm2 + pand mm4, mm6 + pxor mm7, mm7 + pand mm0, mm4 + movq mm6, [eax+colorB0] + pcmpeqw mm7, mm0 + + movq [ecx+2+colorB0], mm6 + + packsswb mm7, mm7 + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_PROCESS + + ;End Delta + + ;--------------------------------- + movq mm0, [eax+ebx+color5] + movq mm1, [eax+ebx+color6] + movq mm2, mm0 + movq mm3, mm1 + movq mm4, mm0 + movq mm5, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + movq [I56Pixel], mm0 + movq mm7, mm0 + + ;------------------- + movq mm0, mm7 + movq mm1, mm4 ;5,5,5,6 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + movq [product1a], mm0 + ;-------------------- + + movq mm0, mm7 + movq mm1, mm5 ;6,6,6,5 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [product1b], mm0 + + ;------------------------- + ;------------------------- + movq mm0, [eax+ebx+ebx+color2] + movq mm1, [eax+ebx+ebx+color3] + movq mm2, mm0 + movq mm3, mm1 + movq mm4, mm0 + movq mm5, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [I23Pixel], mm0 + movq mm7, mm0 + + ;--------------------- + movq mm0, mm7 + movq mm1, mm4 ;2,2,2,3 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [product2a], mm0 + + ;---------------------- + movq mm0, mm7 + movq mm1, mm5 ;3,3,3,2 + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 + movq [product2b], mm0 + + + ;//////////////////////////////// + ; Decide which "branch" to take + ;-------------------------------- + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+color6] + movq mm6, [eax+ebx+ebx+color3] + movq mm7, [eax+ebx+ebx+color2] + + pxor mm3, mm3 + movq mm0, mm4 + movq mm1, mm5 + + pcmpeqw mm0, mm6 + pcmpeqw mm1, mm7 + pcmpeqw mm1, mm3 + pand mm0, mm1 + movq [Mask35], mm0 + + movq mm0, [eax+ebx+ebx+colorS1] + movq mm1, [eax+ebx+color4] + push eax + add eax, ebx + movq mm2, [eax+ebx+ebx+colorA2] + pop eax + movq mm3, [eax+colorB1] + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm4 + pcmpeqw mm3, mm4 + pand mm0, mm1 + pand mm2, mm3 + por mm0, mm2 + pand mm0, [Mask35] + movq [Mask35b], mm0 + + ;----------- + pxor mm3, mm3 + movq mm0, mm4 + movq mm1, mm5 + + pcmpeqw mm0, mm6 + pcmpeqw mm1, mm7 + pcmpeqw mm0, mm3 + pand mm0, mm1 + movq [Mask26], mm0 + + movq mm0, [eax+ebx+ebx+color1] + movq mm1, [eax+ebx+colorS2] + push eax + add eax, ebx + movq mm2, [eax+ebx+ebx+colorA1] + pop eax + movq mm3, [eax+colorB2] + pcmpeqw mm0, mm5 + pcmpeqw mm1, mm5 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm1 + pand mm2, mm3 + por mm0, mm2 + pand mm0, [Mask26] + movq [Mask26b], mm0 + + ;-------------------- + movq mm0, mm4 + movq mm1, mm5 + movq mm2, mm0 + + pcmpeqw mm2, mm1 + pcmpeqw mm0, mm6 + pcmpeqw mm1, mm7 + pand mm0, mm1 + pand mm2, mm0 + pxor mm0, mm2 + movq mm7, mm0 + + ;------------------ + packsswb mm7, mm7 + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_GUESS + +;--------------------------------------------- +; Map of the pixels: I|E F|J +; G|A B|K +; H|C D|L +; M|N O|P + movq mm6, mm0 + movq mm4, [eax+ebx+color5] + movq mm5, [eax+ebx+color6] + pxor mm7, mm7 + pand mm6, [ONE] + + movq mm0, [eax+colorB1] + movq mm1, [eax+ebx+color4] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+colorB2] + movq mm1, [eax+ebx+colorS2] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + push eax + add eax, ebx + movq mm0, [eax+ebx+color1] + movq mm1, [eax+ebx+ebx+colorA1] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+ebx+colorS1] + movq mm1, [eax+ebx+ebx+colorA2] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + pop eax + movq mm1, mm7 + pxor mm0, mm0 + pcmpgtw mm7, mm0 + pcmpgtw mm0, mm1 + + por mm7, [Mask35] + por mm1, [Mask26] + movq [Mask35], mm7 + movq [Mask26], mm1 + +.SKIP_GUESS: + ;Start the ASSEMBLY !!! + + movq mm4, [Mask35] + movq mm5, [Mask26] + movq mm6, [Mask35b] + movq mm7, [Mask26b] + + movq mm0, [eax+ebx+color5] + movq mm1, [eax+ebx+color6] + movq mm2, [eax+ebx+ebx+color2] + movq mm3, [eax+ebx+ebx+color3] + pcmpeqw mm0, mm2 + pcmpeqw mm1, mm3 + movq mm2, mm4 + movq mm3, mm5 + por mm0, mm1 + por mm2, mm3 + pand mm2, mm0 + pxor mm0, mm2 + movq mm3, mm0 + + movq mm2, mm0 + pxor mm0, mm0 + por mm2, mm4 + pxor mm4, mm6 + por mm2, mm5 + pxor mm5, mm7 + pcmpeqw mm2, mm0 + ;---------------- + + movq mm0, [eax+ebx+color5] + movq mm1, mm3 + por mm1, mm4 + por mm1, mm6 + pand mm0, mm1 + movq mm1, mm5 + pand mm1, [I56Pixel] + por mm0, mm1 + movq mm1, mm7 + pand mm1, [product1b] + por mm0, mm1 + movq mm1, mm2 + pand mm1, [product1a] + por mm0, mm1 + movq [final1a], mm0 + + movq mm0, [eax+ebx+color6] + movq mm1, mm3 + por mm1, mm5 + por mm1, mm7 + pand mm0, mm1 + movq mm1, mm4 + pand mm1, [I56Pixel] + por mm0, mm1 + movq mm1, mm6 + pand mm1, [product1a] + por mm0, mm1 + movq mm1, mm2 + pand mm1, [product1b] + por mm0, mm1 + movq [final1b], mm0 + + movq mm0, [eax+ebx+ebx+color2] + movq mm1, mm3 + por mm1, mm5 + por mm1, mm7 + pand mm0, mm1 + movq mm1, mm4 + pand mm1, [I23Pixel] + por mm0, mm1 + movq mm1, mm6 + pand mm1, [product2b] + por mm0, mm1 + movq mm1, mm2 + pand mm1, [product2a] + por mm0, mm1 + movq [final2a], mm0 + + movq mm0, [eax+ebx+ebx+color3] + movq mm1, mm3 + por mm1, mm4 + por mm1, mm6 + pand mm0, mm1 + movq mm1, mm5 + pand mm1, [I23Pixel] + por mm0, mm1 + movq mm1, mm7 + pand mm1, [product2a] + por mm0, mm1 + movq mm1, mm2 + pand mm1, [product2b] + por mm0, mm1 + movq [final2b], mm0 + + + movq mm0, [final1a] + movq mm2, [final1b] + movq mm1, mm0 + movq mm4, [final2a] + movq mm6, [final2b] + movq mm5, mm4 + punpcklwd mm0, mm2 + punpckhwd mm1, mm2 + punpcklwd mm4, mm6 + punpckhwd mm5, mm6 + + + + +%ifdef __DJGPP__ + movq [fs:edx], mm0 + movq [fs:edx+8], mm1 + push edx + add edx, [ebp+dstPitch] + movq [fs:edx], mm4 + movq [fs:edx+8], mm5 + pop edx +%else + movq [es:edx], mm0 + movq [es:edx+8], mm1 + push edx + add edx, [ebp+dstPitch] + movq [es:edx], mm4 + movq [es:edx+8], mm5 + pop edx +%endif +.SKIP_PROCESS: + mov ecx, [ebp+deltaPtr] + add ecx, 8 + mov [ebp+deltaPtr], ecx + add edx, 16 + add eax, 8 + + pop ecx + sub ecx, 4 + cmp ecx, 0 + jg near .Loop + +; Restore some stuff + popad + mov esp, ebp + pop ebp + emms + ret + + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- + + +;This is 2xSaI +colorI equ -2 +colorE equ 0 +colorF equ 2 +colorJ equ 4 + +colorG equ -2 +colorA equ 0 +colorB equ 2 +colorK equ 4 + +colorH equ -2 +colorC equ 0 +colorD equ 2 +colorL equ 4 + +colorM equ -2 +colorN equ 0 +colorO equ 2 +colorP equ 4 + +_2xSaILine: +__2xSaILine: +; Store some stuff + push ebp + mov ebp, esp + pushad + +; Prepare the destination +%ifdef __DJGPP__ + ; Set the selector + mov eax, [ebp+dstSegment] + mov fs, ax +%endif + mov edx, [ebp+dstOffset] ; edx points to the screen +; Prepare the source + ; eax points to colorA + mov eax, [ebp+srcPtr] + mov ebx, [ebp+srcPitch] + mov ecx, [ebp+width] + ; eax now points to colorE + sub eax, ebx + + +; Main Loop +.Loop: push ecx + + ;-----Check Delta------------------ + mov ecx, [ebp+deltaPtr] + + movq mm0, [eax+colorI] + movq mm1, [eax+colorJ] + movq mm2, [eax+ebx+colorG] + movq mm3, [eax+ebx+colorK] + movq mm4, [eax+ebx+ebx+colorH] + movq mm5, [eax+ebx+ebx+colorL] + push eax + add eax, ebx + movq mm6, [eax+ebx+ebx+colorM] + movq mm7, [eax+ebx+ebx+colorP] + pop eax + + pcmpeqw mm0, [ecx+2+colorI] + pcmpeqw mm1, [ecx+2+colorK] + pcmpeqw mm2, [ecx+ebx+2+colorG] + pcmpeqw mm3, [ecx+ebx+2+colorK] + pcmpeqw mm4, [ecx+ebx+ebx+2+colorH] + pcmpeqw mm5, [ecx+ebx+ebx+2+colorL] + add ecx, ebx + pcmpeqw mm6, [ecx+ebx+ebx+2+colorM] + pcmpeqw mm7, [ecx+ebx+ebx+2+colorP] + sub ecx, ebx + + + pand mm0, mm1 + pand mm2, mm3 + pand mm4, mm5 + pand mm6, mm7 + pand mm0, mm2 + pand mm4, mm6 + pxor mm7, mm7 + pand mm0, mm4 + movq mm6, [eax+colorI] + pcmpeqw mm7, mm0 + + movq [ecx+2+colorI], mm6 + + packsswb mm7, mm7 + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_PROCESS + + ;End Delta + + ;--------------------------------- + + +;1 + ;if ((colorA == colorD) && (colorB != colorC) && (colorA == colorE) && (colorB == colorL) + movq mm0, [eax+ebx+colorA] ;mm0 and mm1 contain colorA + movq mm2, [eax+ebx+colorB] ;mm2 and mm3 contain colorB + + movq mm1, mm0 + movq mm3, mm2 + + pcmpeqw mm0, [eax+ebx+ebx+colorD] + pcmpeqw mm1, [eax+colorE] + pcmpeqw mm2, [eax+ebx+ebx+colorL] + pcmpeqw mm3, [eax+ebx+ebx+colorC] + + pand mm0, mm1 + pxor mm1, mm1 + pand mm0, mm2 + pcmpeqw mm3, mm1 + pand mm0, mm3 ;result in mm0 + + ;if ((colorA == colorC) && (colorB != colorE) && (colorA == colorF) && (colorB == colorJ) + movq mm4, [eax+ebx+colorA] ;mm4 and mm5 contain colorA + movq mm6, [eax+ebx+colorB] ;mm6 and mm7 contain colorB + movq mm5, mm4 + movq mm7, mm6 + + pcmpeqw mm4, [eax+ebx+ebx+colorC] + pcmpeqw mm5, [eax+colorF] + pcmpeqw mm6, [eax+colorJ] + pcmpeqw mm7, [eax+colorE] + + pand mm4, mm5 + pxor mm5, mm5 + pand mm4, mm6 + pcmpeqw mm7, mm5 + pand mm4, mm7 ;result in mm4 + + por mm0, mm4 ;combine the masks + movq [Mask1], mm0 + + ;-------------------------------------------- + +;2 + ;if ((colorB == colorC) && (colorA != colorD) && (colorB == colorF) && (colorA == colorH) + movq mm0, [eax+ebx+colorB] ;mm0 and mm1 contain colorB + movq mm2, [eax+ebx+colorA] ;mm2 and mm3 contain colorA + movq mm1, mm0 + movq mm3, mm2 + + pcmpeqw mm0, [eax+ebx+ebx+colorC] + pcmpeqw mm1, [eax+colorF] + pcmpeqw mm2, [eax+ebx+ebx+colorH] + pcmpeqw mm3, [eax+ebx+ebx+colorD] + + pand mm0, mm1 + pxor mm1, mm1 + pand mm0, mm2 + pcmpeqw mm3, mm1 + pand mm0, mm3 ;result in mm0 + + ;if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI) + movq mm4, [eax+ebx+colorB] ;mm4 and mm5 contain colorB + movq mm6, [eax+ebx+colorA] ;mm6 and mm7 contain colorA + movq mm5, mm4 + movq mm7, mm6 + + pcmpeqw mm4, [eax+ebx+ebx+colorD] + pcmpeqw mm5, [eax+colorE] + pcmpeqw mm6, [eax+colorI] + pcmpeqw mm7, [eax+colorF] + + pand mm4, mm5 + pxor mm5, mm5 + pand mm4, mm6 + pcmpeqw mm7, mm5 + pand mm4, mm7 ;result in mm4 + + por mm0, mm4 ;combine the masks + movq [Mask2], mm0 + + +;interpolate colorA and colorB + movq mm0, [eax+ebx+colorA] + movq mm1, [eax+ebx+colorB] + + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + + ;assemble the pixels + movq mm1, [eax+ebx+colorA] + movq mm2, [eax+ebx+colorB] + + movq mm3, [Mask1] + movq mm5, mm1 + movq mm4, [Mask2] + movq mm6, mm1 + + pand mm1, mm3 + por mm3, mm4 + pxor mm7, mm7 + pand mm2, mm4 + + pcmpeqw mm3, mm7 + por mm1, mm2 + pand mm0, mm3 + + por mm0, mm1 + + punpcklwd mm5, mm0 + punpckhwd mm6, mm0 + +%ifdef __DJGPP__ + movq [fs:edx], mm5 + movq [fs:edx+8], mm6 +%else + movq [es:edx], mm5 + movq [es:edx+8], mm6 +%endif + +;------------------------------------------------ +; Create the Nextline +;------------------------------------------------ +;3 ;if ((colorA == colorD) && (colorB != colorC) && (colorA == colorG) && (colorC == colorO) + movq mm0, [eax+ebx+colorA] ;mm0 and mm1 contain colorA + movq mm2, [eax+ebx+ebx+colorC] ;mm2 and mm3 contain colorC + movq mm1, mm0 + movq mm3, mm2 + + push eax + add eax, ebx + pcmpeqw mm0, [eax+ebx+colorD] + pcmpeqw mm1, [eax+colorG] + pcmpeqw mm2, [eax+ebx+ebx+colorO] + pcmpeqw mm3, [eax+colorB] + pop eax + + pand mm0, mm1 + pxor mm1, mm1 + pand mm0, mm2 + pcmpeqw mm3, mm1 + pand mm0, mm3 ;result in mm0 + + ;if ((colorA == colorB) && (colorG != colorC) && (colorA == colorH) && (colorC == colorM) + movq mm4, [eax+ebx+colorA] ;mm4 and mm5 contain colorA + movq mm6, [eax+ebx+ebx+colorC] ;mm6 and mm7 contain colorC + movq mm5, mm4 + movq mm7, mm6 + + push eax + add eax, ebx + pcmpeqw mm4, [eax+ebx+colorH] + pcmpeqw mm5, [eax+colorB] + pcmpeqw mm6, [eax+ebx+ebx+colorM] + pcmpeqw mm7, [eax+colorG] + pop eax + + pand mm4, mm5 + pxor mm5, mm5 + pand mm4, mm6 + pcmpeqw mm7, mm5 + pand mm4, mm7 ;result in mm4 + + por mm0, mm4 ;combine the masks + movq [Mask1], mm0 + ;-------------------------------------------- + +;4 + ;if ((colorB == colorC) && (colorA != colorD) && (colorC == colorH) && (colorA == colorF) + movq mm0, [eax+ebx+ebx+colorC] ;mm0 and mm1 contain colorC + movq mm2, [eax+ebx+colorA] ;mm2 and mm3 contain colorA + movq mm1, mm0 + movq mm3, mm2 + + pcmpeqw mm0, [eax+ebx+colorB] + pcmpeqw mm1, [eax+ebx+ebx+colorH] + pcmpeqw mm2, [eax+colorF] + pcmpeqw mm3, [eax+ebx+ebx+colorD] + + pand mm0, mm1 + pxor mm1, mm1 + pand mm0, mm2 + pcmpeqw mm3, mm1 + pand mm0, mm3 ;result in mm0 + + ;if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI) + movq mm4, [eax+ebx+ebx+colorC] ;mm4 and mm5 contain colorC + movq mm6, [eax+ebx+colorA] ;mm6 and mm7 contain colorA + movq mm5, mm4 + movq mm7, mm6 + + pcmpeqw mm4, [eax+ebx+ebx+colorD] + pcmpeqw mm5, [eax+ebx+colorG] + pcmpeqw mm6, [eax+colorI] + pcmpeqw mm7, [eax+ebx+ebx+colorH] + + pand mm4, mm5 + pxor mm5, mm5 + pand mm4, mm6 + pcmpeqw mm7, mm5 + pand mm4, mm7 ;result in mm4 + + por mm0, mm4 ;combine the masks + movq [Mask2], mm0 + ;---------------------------------------------- + +;interpolate colorA and colorC + movq mm0, [eax+ebx+colorA] + movq mm1, [eax+ebx+ebx+colorC] + + movq mm2, mm0 + movq mm3, mm1 + + pand mm0, [colorMask] + pand mm1, [colorMask] + + psrlw mm0, 1 + psrlw mm1, 1 + + pand mm3, [lowPixelMask] + paddw mm0, mm1 + + pand mm3, mm2 + paddw mm0, mm3 ;mm0 contains the interpolated values + ;------------- + + ;assemble the pixels + movq mm1, [eax+ebx+colorA] + movq mm2, [eax+ebx+ebx+colorC] + + movq mm3, [Mask1] + movq mm4, [Mask2] + + pand mm1, mm3 + pand mm2, mm4 + + por mm3, mm4 + pxor mm7, mm7 + por mm1, mm2 + + pcmpeqw mm3, mm7 + pand mm0, mm3 + por mm0, mm1 + movq [ACPixel], mm0 + +;//////////////////////////////// +; Decide which "branch" to take +;-------------------------------- + movq mm0, [eax+ebx+colorA] + movq mm1, [eax+ebx+colorB] + movq mm6, mm0 + movq mm7, mm1 + pcmpeqw mm0, [eax+ebx+ebx+colorD] + pcmpeqw mm1, [eax+ebx+ebx+colorC] + pcmpeqw mm6, mm7 + + movq mm2, mm0 + movq mm3, mm0 + + pand mm0, mm1 ;colorA == colorD && colorB == colorC + pxor mm7, mm7 + + pcmpeqw mm2, mm7 + pand mm6, mm0 + pand mm2, mm1 ;colorA != colorD && colorB == colorC + + pcmpeqw mm1, mm7 + + pand mm1, mm3 ;colorA == colorD && colorB != colorC + pxor mm0, mm6 + por mm1, mm6 + movq mm7, mm0 + movq [Mask2], mm2 + packsswb mm7, mm7 + movq [Mask1], mm1 + + movd ecx, mm7 + test ecx, ecx + jz near .SKIP_GUESS +;--------------------------------------------- +; Map of the pixels: I|E F|J +; G|A B|K +; H|C D|L +; M|N O|P + movq mm6, mm0 + movq mm4, [eax+ebx+colorA] + movq mm5, [eax+ebx+colorB] + pxor mm7, mm7 + pand mm6, [ONE] + + movq mm0, [eax+colorE] + movq mm1, [eax+ebx+colorG] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+colorF] + movq mm1, [eax+ebx+colorK] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + push eax + add eax, ebx + movq mm0, [eax+ebx+colorH] + movq mm1, [eax+ebx+ebx+colorN] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + movq mm0, [eax+ebx+colorL] + movq mm1, [eax+ebx+ebx+colorO] + movq mm2, mm0 + movq mm3, mm1 + pcmpeqw mm0, mm4 + pcmpeqw mm1, mm4 + pcmpeqw mm2, mm5 + pcmpeqw mm3, mm5 + pand mm0, mm6 + pand mm1, mm6 + pand mm2, mm6 + pand mm3, mm6 + paddw mm0, mm1 + paddw mm2, mm3 + + pxor mm3, mm3 + pcmpgtw mm0, mm6 + pcmpgtw mm2, mm6 + pcmpeqw mm0, mm3 + pcmpeqw mm2, mm3 + pand mm0, mm6 + pand mm2, mm6 + paddw mm7, mm0 + psubw mm7, mm2 + + pop eax + movq mm1, mm7 + pxor mm0, mm0 + pcmpgtw mm7, mm0 + pcmpgtw mm0, mm1 + + por mm7, [Mask1] + por mm1, [Mask2] + movq [Mask1], mm7 + movq [Mask2], mm1 + +.SKIP_GUESS: + ;---------------------------- + ;interpolate A, B, C and D + movq mm0, [eax+ebx+colorA] + movq mm1, [eax+ebx+colorB] + movq mm4, mm0 + movq mm2, [eax+ebx+ebx+colorC] + movq mm5, mm1 + movq mm3, [qcolorMask] + movq mm6, mm2 + movq mm7, [qlowpixelMask] + + pand mm0, mm3 + pand mm1, mm3 + pand mm2, mm3 + pand mm3, [eax+ebx+ebx+colorD] + + psrlw mm0, 2 + pand mm4, mm7 + psrlw mm1, 2 + pand mm5, mm7 + psrlw mm2, 2 + pand mm6, mm7 + psrlw mm3, 2 + pand mm7, [eax+ebx+ebx+colorD] + + paddw mm0, mm1 + paddw mm2, mm3 + + paddw mm4, mm5 + paddw mm6, mm7 + + paddw mm4, mm6 + paddw mm0, mm2 + psrlw mm4, 2 + pand mm4, [qlowpixelMask] + paddw mm0, mm4 ;mm0 contains the interpolated value of A, B, C and D + +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + ;assemble the pixels + movq mm1, [Mask1] + movq mm2, [Mask2] + movq mm4, [eax+ebx+colorA] + movq mm5, [eax+ebx+colorB] + pand mm4, mm1 + pand mm5, mm2 + + pxor mm7, mm7 + por mm1, mm2 + por mm4, mm5 + pcmpeqw mm1, mm7 + pand mm0, mm1 + por mm4, mm0 ;mm4 contains the diagonal pixels + + movq mm0, [ACPixel] + movq mm1, mm0 + punpcklwd mm0, mm4 + punpckhwd mm1, mm4 + + push edx + add edx, [ebp+dstPitch] + +%ifdef __DJGPP__ + movq [fs:edx], mm0 + movq [fs:edx+8], mm1 +%else + movq [es:edx], mm0 + movq [es:edx+8], mm1 +%endif + pop edx + +.SKIP_PROCESS: + mov ecx, [ebp+deltaPtr] + add ecx, 8 + mov [ebp+deltaPtr], ecx + add edx, 16 + add eax, 8 + + pop ecx + sub ecx, 4 + cmp ecx, 0 + jg near .Loop + +; Restore some stuff + popad + mov esp, ebp + pop ebp + emms + ret + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- + +Init_2xSaIMMX: +_Init_2xSaIMMX: +; Store some stuff + push ebp + mov ebp, esp + push edx + + +;Damn thing doesn't work +; mov eax,1 +; cpuid +; test edx, 0x00800000 ;test bit 23 +; jz end2 ;bit not set => no MMX detected + + mov eax, [ebp+8] ;PixelFormat + cmp eax, 555 + jz Bits555 + cmp eax, 565 + jz Bits565 +end2: + mov eax, 1 + jmp end +Bits555: + mov edx, 0x7BDE7BDE + mov eax, colorMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0x04210421 + mov eax, lowPixelMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0x739C739C + mov eax, qcolorMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0x0C630C63 + mov eax, qlowpixelMask + mov [eax], edx + mov [eax+4], edx + mov eax, 0 + jmp end +Bits565: + mov edx, 0xF7DEF7DE + mov eax, colorMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0x08210821 + mov eax, lowPixelMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0xE79CE79C + mov eax, qcolorMask + mov [eax], edx + mov [eax+4], edx + mov edx, 0x18631863 + mov eax, qlowpixelMask + mov [eax], edx + mov [eax+4], edx + mov eax, 0 + jmp end +end: + pop edx + mov esp, ebp + pop ebp + ret + + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- + + SECTION .data ALIGN = 32 +;Some constants +colorMask dd 0xF7DEF7DE, 0xF7DEF7DE +lowPixelMask dd 0x08210821, 0x08210821 + +qcolorMask dd 0xE79CE79C, 0xE79CE79C +qlowpixelMask dd 0x18631863, 0x18631863 + +FALSE dd 0x00000000, 0x00000000 +TRUE dd 0xffffffff, 0xffffffff +ONE dd 0x00010001, 0x00010001 + + + SECTION .bss ALIGN = 32 +ACPixel resb 8 +Mask1 resb 8 +Mask2 resb 8 + +I56Pixel resb 8 +I23Pixel resb 8 +I5556Pixel resb 8 +I2223Pixel resb 8 +I5666Pixel resb 8 +I2333Pixel resb 8 +Mask26 resb 8 +Mask35 resb 8 +Mask26b resb 8 +Mask35b resb 8 +product1a resb 8 +product1b resb 8 +product2a resb 8 +product2b resb 8 +final1a resb 8 +final1b resb 8 +final2a resb 8 +final2b resb 8 + + + diff --git a/src/interface/scalers/eagle_fm.asm b/src/interface/scalers/eagle_fm.asm new file mode 100644 index 00000000..4dc98775 --- /dev/null +++ b/src/interface/scalers/eagle_fm.asm @@ -0,0 +1,462 @@ +; +; Eagle.asm +; +; Eagle version 0.41 for NASM +; +; Written by Dirk Stevens +; +; compile with : nasm -f coff eagle.asm for use with DJGPP +; Using optimization with DJGPP and coff objects could result in +; erronous behaviour! +; +; History : +; Date Version Comments +; +; 30-Sep-1998 0.41 - Minor modification in 16bit MMX code +; +; 20-Jun-1998 0.40 -Added 16bit color support for MMX +; -Incorporated Larry Bank's suggestions +; +; 29-March-1998 0.31 -eagle_bmp for use in plain bmps +; +; 28-March-1998 0.30 -Handle buffer internally +; -Added optimised MMX copying (fast!) +; -Everything is done in one routine +; +; 15-March-1998 0.20 -First NASM version +; -Added parameter for Eagle_Lines +; -Added support for MMX +; -Optimised further for non-MMX +; +;------------------------------------------------------------ + +; +; This 16-bit MMX Eagle implementation uses a flat memory map +; +;------------------------------------------------------------ + + BITS 32 + GLOBAL _eagle_mmx16 + GLOBAL __eagle_mmx16 + SECTION .text + +; +; Eagle for 16bit color +; Supported for MMX *only* +; + +_eagle_mmx16: +__eagle_mmx16: + +; void eagle_mmx16(unsigned long *lb, +; unsigned long *lb2, +; short width, +; unsigned long *screen_address1, +; unsigned long *screen_address2); + + pushad + + push ebp + + mov esi,[esp+8+32] + mov ebx,[esp+12+32] + mov ecx,[esp+16+32] + mov edi, _eagle_buffer + mov eax, _eagle_buffer+4096 + and edi, 0xFFFFFFE0 + and eax, 0xFFFFFFE0 + + + mov ebp, ebx + + shr ecx, 3 ; divide by 8 because mmx registers / 16 bit color + + xor dx,dx + +.L0 + push ecx + xchg eax,ecx + + movq mm1,[ebp] + movq mm0,[esi] + add ebp,8 + add esi,8 + + ; added for mmx16 + + push ebp + push ecx + mov ebp, ecx + + mov word cx, [_dlx] + + ; end of added + + movd eax, mm0 + movd ebx, mm1 + +; cmp dhx, bx + cmp dx, bx + jne .L6001 +.L1001 + cmp bx, ax + jne .L3001 +.L2001 + mov [edi],ax +; mov [ecx],dhx + mov [ebp],dx + mov [edi+2],ax + mov [ebp+2],bx + jmp .L11 +.L3001 +; cmp dhx, dlx + cmp dx, cx + jne .L5001 +.L4001 +; mov [edi],dx ; mmmh +; mov [ecx],dx ; mmmh +; mov [edi],dl +; mov [ecx],dl +; mov [edi+1],dh +; mov [ecx+1],dh + mov [edi],cx + mov [ebp],cx + mov [edi+2],dx + mov [ebp+2],dx + + jmp .L11 +.L5001 + mov [edi],cx +; mov [ecx],dhx + mov [ebp],dx + mov [edi+2],ax + mov [ebp+2],bx + jmp .L11 +.L6001 +; cmp dlx, ax + cmp cx, ax + jne .L12001 +.L7001 +; cmp dlx, dhx + cmp cx, dx + jne .L9001 +.L8001 +; mov [edi],dx ; mmmh +; mov [ecx],dx ; mmmh +; mov [edi],dl +; mov [ecx],dl +; mov [edi+1],dh +; mov [ecx+1],dh +; mov [edi],dlx +; mov [ecx],dlx + mov [edi],cx + mov [ebp],cx +; mov [edi+2],dhx +; mov [ecx+2],dhx + mov [edi+2],dx + mov [ebp+2],dx + + jmp .L11 +.L9001 + cmp ax,bx + jne .L11001 +.L10001 +; mov [edi],dlx + mov [edi],cx + mov [ebp],bx + mov [edi+2],ax + mov [ebp+2],bx + jmp .L11 +.L11001 +.L12001 +; mov [edi],dlx +; mov [ecx],dhx + mov [edi],cx + mov [ebp],dx + mov [edi+2],ax + mov [ebp+2],bx + +.L11 + + movq mm4, mm1 + + movq mm2, mm0 + + pcmpeqd mm7, mm7 ; set mm7 to FFFFFFFFFFFFFFFF + + ;pcmpeqb mm4, mm0 ; byte compare equal mm0 with mm1 and store in mm4 + pcmpeqw mm4, mm0 ; word compare equal mm0 with mm1 and store in mm4 + + ;psllq mm2, 8 ; shift mm0 left one byte and store in mm2 + psllq mm2, 16 ; shift mm0 left one word and store in mm2 + + movq mm3, mm0 + + movq mm5, mm4 ; store byte compare mm0 with mm1 in mm5 + + ;pcmpeqb mm2, mm0 ; byte compare mm0 with mm2 and store in mm2 + pcmpeqw mm2, mm0 ; word compare mm0 with mm2 and store in mm2 + + ;psrlq mm3, 8 ; shift mm0 right one byte and store in mm3 + psrlq mm3, 16 ; shift mm0 right one word and store in mm3 + + pand mm2, mm5 + + movq mm6, mm1 ; and mm5 with mm1 + + movq mm5, mm2 ; not mm2 and store in mm5 + + pxor mm5, mm7 + +; psllq mm6, 8 + psllq mm6, 16 + + pand mm2, mm0 ; and mm0 with mm2 + + pand mm5, mm6 + + por mm2, mm5 ; mm2 now contains right-bottom of quad + + ;pcmpeqb mm3, mm0 ; byte compare mm3 with mm0 and store in mm3 + pcmpeqw mm3, mm0 ; word compare mm3 with mm0 and store in mm3 + + movq mm5, mm4 ; word compare of mm0 with mm1 store in mm5 + + pand mm3, mm4 + + movq mm5, mm3 ; not mm3 store in mm5 + + movq mm6, mm1 + + pxor mm5, mm7 + + pand mm3, mm0 + + ;psrlq mm6, 8 + psrlq mm6, 16 + + pand mm5, mm6 + + ;psrlq mm2, 8 + psrlq mm2, 16 + + por mm3, mm5 + +; now write the 16 bytes of the bottom line + + movq mm4, mm2 + + movq mm6, mm2 + +; punpcklbw mm4, mm3 + +; punpckhbw mm6, mm3 + + punpcklwd mm4, mm3 + + punpckhwd mm6, mm3 + +; movq [ecx+2],mm4 + movq [ebp+4],mm4 + +; movq [ecx+10],mm6 + movq [ebp+12],mm6 + + +; start with top line + + movq mm2, mm1 + movq mm3, mm1 + movq mm4, mm0 + + pcmpeqd mm7, mm7 ; set mm7 to FFFFFFFFFFFFFFFF + + ;pcmpeqb mm4, mm1 ; byte compare equal mm0 with mm1 and store in mm4 + pcmpeqw mm4, mm1 ; word compare equal mm0 with mm1 and store in mm4 + + ;psllq mm2, 8 ; shift mm0 left one byte and store in mm2 + psllq mm2, 16 ; shift mm0 left one word and store in mm2 + + ;psrlq mm3, 8 ; shift mm0 right one byte and store in mm3 + psrlq mm3, 16 ; shift mm0 right one word and store in mm3 + + movq mm5, mm4 ; store byte compare mm0 with mm1 in mm5 + + ;pcmpeqb mm2, mm1 ; byte compare mm0 with mm2 and store in mm2 + pcmpeqw mm2, mm1 ; word compare mm0 with mm2 and store in mm2 + + pand mm2, mm5 + + movq mm5, mm2 ; not mm2 and store in mm5 + pxor mm5, mm7 + + pand mm2, mm1 ; and mm0 with mm2 + + movq mm6, mm0 ; and mm5 with mm1 + ;psllq mm6, 8 + psllq mm6, 16 + pand mm5, mm6 + + por mm2, mm5 ; mm2 now contains right-bottom of quad + + + movq mm5, mm4 ; byte compare of mm0 with mm1 store in mm5 + + ;pcmpeqb mm3, mm1 ; byte compare mm3 with mm0 and store in mm3 + pcmpeqw mm3, mm1 ; word compare mm3 with mm0 and store in mm3 + + pand mm3, mm5 + + movq mm5, mm3 ; not mm3 store in mm5 + pxor mm5, mm7 + + pand mm3, mm1 + + movq mm6, mm0 + ;psrlq mm6, 8 + psrlq mm6, 16 + pand mm5, mm6 + + por mm3, mm5 + +; now write the 16 bytes of the top line + + ;psrlq mm2, 8 + psrlq mm2, 16 + + movq mm4, mm2 + + movq mm6, mm2 + +; punpcklbw mm4, mm3 + +; punpckhbw mm6, mm3 + + punpcklwd mm4, mm3 + + punpckhwd mm6, mm3 + +; movq [edi+2],mm4 + movq [edi+4],mm4 +; psrlq mm0, 56 ; 64-8 = 56 + psrlq mm0, 48 ; 64-16 = 48 +; movq [edi+10],mm6 + movq [edi+12],mm6 + ;psrlq mm1, 56 + psrlq mm1, 48 + + +; +; restore ebp and ecx +; + + pop ecx + pop ebp + +; +; End of restore +; + + add edi, 16 + add ecx, 16 + + movd edx, mm0 + mov word [_dlx], dx + movd ebx, mm1 + mov dx, bx + + pop eax + xchg eax,ecx + + dec ecx + jnz near .L0 + +.L333 + + mov esi, _eagle_buffer + mov ebx, _eagle_buffer+4096 + and esi, 0xFFFFFFE0 + and ebx, 0xFFFFFFE0 + + mov ecx,[esp+16+32] + mov edi,[esp+20+32] + mov eax,[esp+24+32] + + ;shr ecx, 5 + shr ecx, 4 + + push ecx + +.first_loop: + movq mm0, [ esi ] + movq mm1, [ esi + 8 ] + movq mm2, [ esi + 16] + movq mm3, [ esi + 24] + movq mm4, [ esi + 32] + movq mm5, [ esi + 40] + movq mm6, [ esi + 48] + movq mm7, [ esi + 56] + + movq [edi], mm0 + movq [edi + 8], mm1 + movq [edi + 16], mm2 + movq [edi + 24], mm3 + movq [edi + 32], mm4 + movq [edi + 40], mm5 + movq [edi + 48], mm6 + movq [edi + 56], mm7 + + add edi, 64 + add esi, 64 + + dec ecx + jnz .first_loop + + pop ecx + + mov edi, eax + mov esi, ebx + + +.second_loop: + movq mm0, [ esi ] + movq mm1, [ esi + 8 ] + movq mm2, [ esi + 16] + movq mm3, [ esi + 24] + movq mm4, [ esi + 32] + movq mm5, [ esi + 40] + movq mm6, [ esi + 48] + movq mm7, [ esi + 56] + + movq [edi], mm0 + movq [edi + 8], mm1 + movq [edi + 16], mm2 + movq [edi + 24], mm3 + movq [edi + 32], mm4 + movq [edi + 40], mm5 + movq [edi + 48], mm6 + movq [edi + 56], mm7 + + add edi, 64 + add esi, 64 + + dec ecx + jz .continue_here + jmp .second_loop + +.continue_here + pop eax + mov ebp, eax + + popad + + ret + + SECTION .bss +_offset32 resb 32 +_eagle_buffer resb 16384 +_tripline1 resb 8 +_tripline2 resb 8 +_tripline3 resb 8 +_dlx resb 32 + diff --git a/src/interface/scalers/epx.cpp b/src/interface/scalers/epx.cpp new file mode 100644 index 00000000..9a2bc3ea --- /dev/null +++ b/src/interface/scalers/epx.cpp @@ -0,0 +1,223 @@ +// epxb, epxc filter, added by regret +// source from Snes9X rerecording (http://code.google.com/p/snes9x151-rerecording/) + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef unsigned int uint32; +# ifdef __GNUC__ /* long long is not part of ISO C++ */ +__extension__ +# endif +typedef long long int64; +typedef unsigned long long uint64; + +#define Mask_2 0x07E0 // 00000 111111 00000 +#define Mask13 0xF81F // 11111 000000 11111 +#define Mask_1 0x001F // 00000 000000 11111 +#define Mask_3 0xF800 // 11111 000000 00000 +#define CONVERT_16_TO_32(pixel) \ + (((((pixel) >> 11) ) << /*RedShift+3*/ 19) | \ + ((((pixel) >> 6) & 0x1f) << /*GreenShift+3*/11) | \ + (((pixel) & 0x1f) << /*BlueShift+3*/ 3)) + +#define Interp01(c1, c2) \ + ((((c1) == (c2)) ? (c1) : \ + (((((((c1) & Mask_2) * 3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \ + ((((((c1) & Mask13) * 3) + ((c2) & Mask13)) >> 2) & Mask13)))) + +#define LSB_FIRST + +#ifdef LSB_FIRST + #define TWO_PIX(left,right) ((left) | ((right) << 16)) + #define THREE_PIX(left,middle,right) uint48((left) | ((middle) << 16), (right)) + #define TWO_PIX_32(left,right) (CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(right) << 32)) + #define THREE_PIX_32(left,middle,right) uint96(CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(middle) << 32), CONVERT_16_TO_32(right)) +#else + #define TWO_PIX(left,right) ((right) | ((left) << 16)) + #define THREE_PIX(left,middle,right) uint48((middle) | ((left) << 16), (right)) // is this right? +// #define THREE_PIX(left,middle,right) uint48((right) | ((middle) << 16), (left)) // or this? +#endif + +// shared EPX-type loop macros +// All of these parameters will be constant values, +// so I hope the compiler is smart enough to optimize away "if(0) ..." + +#define DrawRows(scale,diags) \ + { \ + h = srcHeight - 1; \ + DoRow(0,1,scale,diags); \ + for (h = srcHeight - 2; h; h--) \ + DoRow(1,1,scale,diags); \ + DoRow(1,0,scale,diags); \ + } + +#define DoRow(topValid,botValid,scale,diags) \ + { \ + w = srcWidth - 1; \ + InitLine(topValid,botValid,scale,diags); \ + DrawPix(0,topValid,0,botValid); \ + for (w = srcWidth - 2; w; w--) \ + { \ + NextPixel(topValid,botValid,1,diags); \ + DrawPix(topValid,topValid,botValid,botValid); \ + } \ + NextPixel(topValid,botValid,0,diags); \ + DrawPix(topValid,0,botValid,0); \ + srcPtr += srcPitch; \ + dstPtr += dstPitch * scale; \ + } + +#define InitLine(topValid, botValid, scale, diags) \ + { \ + if(topValid) uP = (uint16 *) (srcPtr - srcPitch); \ + if(botValid) lP = (uint16 *) (srcPtr + srcPitch); \ + sP = (uint16 *) srcPtr; \ + dP1 = (destType *) dstPtr; \ + dP2 = (destType *) (dstPtr + dstPitch); \ + if(scale>=3) dP3 = (destType *) (dstPtr + (dstPitch<<1)); \ + if(topValid) colorD = *uP++; \ + if(botValid) colorB = *lP++; \ + colorX = *sP++; \ + colorC = *sP; \ + if(diags) if(topValid) colorH = *uP; \ + if(diags) if(botValid) colorG = *lP; \ + } + +#define NextPixel(topValid, botValid, rightValid, diags) \ + { \ + colorA = colorX; \ + colorX = colorC; \ + if(rightValid) colorC = *++sP; \ + if(diags) { \ + if(botValid){ \ + colorF = colorB; \ + colorB = colorG; \ + if(rightValid) colorG = *++lP; \ + } \ + if(topValid){ \ + colorE = colorD; \ + colorD = colorH; \ + if(rightValid) colorH = *++uP; \ + } \ + } else { \ + if(botValid) colorB = *lP++; \ + if(topValid) colorD = *uP++; \ + } \ + } + +#define DrawInit(scale,uintDest) \ + uint8 *srcPtr = src, *dstPtr = dst; \ + const uint32 srcPitch = srcpitch, dstPitch = dstpitch; \ + const uint32 srcHeight = nHeight; \ + const uint32 srcWidth = nWidth; \ + uint16 colorX, colorA, colorB, colorC, colorD, colorE=0, colorF=0, colorG=0, colorH=0; \ + uint16 *sP, *uP, *lP; \ + typedef uintDest destType; \ + destType *dP1, *dP2, *dP3=0; \ + int w, h; + +// code for improved 2X EPX, which tends to do better with diagonal edges than regular EPX +void RenderEPXB(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int vidDepth) +{ + // E D H + // A X C + // F B G + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX)) \ + && ((!on00||!on01||!on10|!on11) || \ + ((colorX == colorA) || (colorX == colorB) || (colorX == colorC) || (colorX == colorD) || /* diagonal */ \ + (((colorE != colorG) || (colorX == colorF) || (colorX == colorH)) && /* edge */ \ + ((colorF != colorH) || (colorX == colorE) || (colorX == colorG)))))) /* smoothing */ \ + { \ + *dP1++ = _TWO_PIX((on00 && colorD == colorA && (colorX != colorE || colorX != colorG || colorD != colorH || colorA != colorF)) ? colorD : colorX, \ + (on01 && colorC == colorD && (colorX != colorH || colorX != colorF || colorC != colorG || colorD != colorE)) ? colorC : colorX); \ + *dP2++ = _TWO_PIX((on10 && colorA == colorB && (colorX != colorF || colorX != colorH || colorA != colorE || colorB != colorG)) ? colorA : colorX, \ + (on11 && colorB == colorC && (colorX != colorG || colorX != colorE || colorB != colorF || colorC != colorH)) ? colorB : colorX); \ + } else { \ + *dP1++ = _TWO_PIX(colorX, colorX); \ + *dP2++ = _TWO_PIX(colorX, colorX); \ + } \ + } + + // again, this supports 32-bit or 16-bit rendering + if(vidDepth == 32) + { +#define _TWO_PIX TWO_PIX_32 + DrawInit(2,uint64); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + else + { +#define _TWO_PIX TWO_PIX + DrawInit(2,uint32); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + + #undef DrawPix +} + +#define Interp44(c1, c2, c3, c4) \ + ((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) + ((c3) & Mask_2) + ((c4) & Mask_2)) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 5 + ((c2) & Mask13) + ((c3) & Mask13) + ((c4) & Mask13)) >> 3) & Mask13)) + +// EPX3 scaled down to 2X +void RenderEPXC(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int vidDepth) +{ + // E D H + // A X C + // F B G + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \ + { \ + const bool XnE = colorX != colorE; \ + const bool XnF = colorX != colorF; \ + const bool XnG = colorX != colorG; \ + const bool XnH = colorX != colorH; \ + const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \ + const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \ + const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \ + const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \ + if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \ + ((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \ + { \ + const uint16 colorAA = on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX; \ + const uint16 colorBB = on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX; \ + const uint16 colorCC = on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX; \ + const uint16 colorDD = on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX; \ + *dP1++ = _TWO_PIX(Interp44(on00 && DA ? colorA : colorX, colorDD, colorAA, colorX), Interp44(on01 && CD ? colorC : colorX, colorBB, colorCC, colorX)); \ + *dP2++ = _TWO_PIX(Interp44(on10 && AB ? colorA : colorX, colorAA, colorBB, colorX), Interp44(on11 && BC ? colorC : colorX, colorCC, colorDD, colorX)); \ + } else { \ + *dP1++ = _TWO_PIX(Interp01(colorX, on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX), Interp01(colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX)); \ + *dP2++ = _TWO_PIX(Interp01(colorX, on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX), Interp01(colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX)); \ + } \ + } else { \ + *dP1++ = _TWO_PIX(colorX, colorX); \ + *dP2++ = _TWO_PIX(colorX, colorX); \ + } \ + } + + if(vidDepth == 32) + { +#define _TWO_PIX TWO_PIX_32 + DrawInit(2,uint64); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + else + { +#define _TWO_PIX TWO_PIX + DrawInit(2,uint32); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + + #undef DrawPix +} diff --git a/src/interface/scalers/hq2x32.asm b/src/interface/scalers/hq2x32.asm new file mode 100644 index 00000000..86070f52 --- /dev/null +++ b/src/interface/scalers/hq2x32.asm @@ -0,0 +1,1934 @@ +;hq2x filter +;---------------------------------------------------------- +;Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +GLOBAL _hq2x_32 + +EXTERN _LUT16to32 +EXTERN _RGBtoYUV + +SECTION .bss +linesleft resd 1 +xcounter resd 1 +cross resd 1 +nextline resd 1 +prevline resd 1 +w1 resd 1 +w2 resd 1 +w3 resd 1 +w4 resd 1 +w5 resd 1 +w6 resd 1 +w7 resd 1 +w8 resd 1 +w9 resd 1 +c1 resd 1 +c2 resd 1 +c3 resd 1 +c4 resd 1 +c5 resd 1 +c6 resd 1 +c7 resd 1 +c8 resd 1 +c9 resd 1 + +SECTION .data + +reg_blank dd 0,0 +const3 dd 0x00030003,0x00000003 +const5 dd 0x00050005,0x00000005 +const6 dd 0x00060006,0x00000006 +const14 dd 0x000E000E,0x0000000E +threshold dd 0x00300706,0x00000000 + +SECTION .text + +%macro TestDiff 2 + xor ecx,ecx + mov edx,[%1] + cmp edx,[%2] + je %%fin + mov ecx,_RGBtoYUV + movd mm1,[ecx+edx*4] + movq mm5,mm1 + mov edx,[%2] + movd mm2,[ecx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd ecx,mm1 +%%fin: +%endmacro + +%macro DiffOrNot 4 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + jmp %%fin +%%same: + %4 +%%fin +%endmacro + +%macro DiffOrNot 6 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + jmp %%fin +%%same: + %5 + %6 +%%fin +%endmacro + +%macro DiffOrNot 8 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + %5 + jmp %%fin +%%same: + %6 + %7 + %8 +%%fin +%endmacro + +%macro DiffOrNot 10 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + %5 + %6 + jmp %%fin +%%same: + %7 + %8 + %9 + %10 +%%fin +%endmacro + +%macro Interp1 3 + mov edx,%2 + shl edx,2 + add edx,%3 + sub edx,%2 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp2 4 + mov edx,%2 + shl edx,1 + add edx,%3 + add edx,%4 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp5 3 + mov edx,%2 + add edx,%3 + shr edx,1 + mov %1,edx +%endmacro + +%macro Interp6 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + pmullw mm1, [const5] + psllw mm2, 1 + paddw mm1, mm3 + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp7 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + pmullw mm1, [const6] + paddw mm2, mm3 + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp9 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + psllw mm1, 1 + paddw mm2, mm3 + pmullw mm2, [const3] + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp10 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + pmullw mm1, [const14] + paddw mm2, mm3 + paddw mm1, mm2 + psrlw mm1, 4 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro PIXEL00_0 0 + mov [edi],eax +%endmacro + +%macro PIXEL00_10 0 + Interp1 [edi],eax,[c1] +%endmacro + +%macro PIXEL00_11 0 + Interp1 [edi],eax,[c4] +%endmacro + +%macro PIXEL00_12 0 + Interp1 [edi],eax,[c2] +%endmacro + +%macro PIXEL00_20 0 + Interp2 [edi],eax,[c4],[c2] +%endmacro + +%macro PIXEL00_21 0 + Interp2 [edi],eax,[c1],[c2] +%endmacro + +%macro PIXEL00_22 0 + Interp2 [edi],eax,[c1],[c4] +%endmacro + +%macro PIXEL00_60 0 + Interp6 [edi],[c2],[c4] +%endmacro + +%macro PIXEL00_61 0 + Interp6 [edi],[c4],[c2] +%endmacro + +%macro PIXEL00_70 0 + Interp7 [edi],[c4],[c2] +%endmacro + +%macro PIXEL00_90 0 + Interp9 [edi],[c4],[c2] +%endmacro + +%macro PIXEL00_100 0 + Interp10 [edi],[c4],[c2] +%endmacro + +%macro PIXEL01_0 0 + mov [edi+4],eax +%endmacro + +%macro PIXEL01_10 0 + Interp1 [edi+4],eax,[c3] +%endmacro + +%macro PIXEL01_11 0 + Interp1 [edi+4],eax,[c2] +%endmacro + +%macro PIXEL01_12 0 + Interp1 [edi+4],eax,[c6] +%endmacro + +%macro PIXEL01_20 0 + Interp2 [edi+4],eax,[c2],[c6] +%endmacro + +%macro PIXEL01_21 0 + Interp2 [edi+4],eax,[c3],[c6] +%endmacro + +%macro PIXEL01_22 0 + Interp2 [edi+4],eax,[c3],[c2] +%endmacro + +%macro PIXEL01_60 0 + Interp6 [edi+4],[c6],[c2] +%endmacro + +%macro PIXEL01_61 0 + Interp6 [edi+4],[c2],[c6] +%endmacro + +%macro PIXEL01_70 0 + Interp7 [edi+4],[c2],[c6] +%endmacro + +%macro PIXEL01_90 0 + Interp9 [edi+4],[c2],[c6] +%endmacro + +%macro PIXEL01_100 0 + Interp10 [edi+4],[c2],[c6] +%endmacro + +%macro PIXEL10_0 0 + mov [edi+ebx],eax +%endmacro + +%macro PIXEL10_10 0 + Interp1 [edi+ebx],eax,[c7] +%endmacro + +%macro PIXEL10_11 0 + Interp1 [edi+ebx],eax,[c8] +%endmacro + +%macro PIXEL10_12 0 + Interp1 [edi+ebx],eax,[c4] +%endmacro + +%macro PIXEL10_20 0 + Interp2 [edi+ebx],eax,[c8],[c4] +%endmacro + +%macro PIXEL10_21 0 + Interp2 [edi+ebx],eax,[c7],[c4] +%endmacro + +%macro PIXEL10_22 0 + Interp2 [edi+ebx],eax,[c7],[c8] +%endmacro + +%macro PIXEL10_60 0 + Interp6 [edi+ebx],[c4],[c8] +%endmacro + +%macro PIXEL10_61 0 + Interp6 [edi+ebx],[c8],[c4] +%endmacro + +%macro PIXEL10_70 0 + Interp7 [edi+ebx],[c8],[c4] +%endmacro + +%macro PIXEL10_90 0 + Interp9 [edi+ebx],[c8],[c4] +%endmacro + +%macro PIXEL10_100 0 + Interp10 [edi+ebx],[c8],[c4] +%endmacro + +%macro PIXEL11_0 0 + mov [edi+ebx+4],eax +%endmacro + +%macro PIXEL11_10 0 + Interp1 [edi+ebx+4],eax,[c9] +%endmacro + +%macro PIXEL11_11 0 + Interp1 [edi+ebx+4],eax,[c6] +%endmacro + +%macro PIXEL11_12 0 + Interp1 [edi+ebx+4],eax,[c8] +%endmacro + +%macro PIXEL11_20 0 + Interp2 [edi+ebx+4],eax,[c6],[c8] +%endmacro + +%macro PIXEL11_21 0 + Interp2 [edi+ebx+4],eax,[c9],[c8] +%endmacro + +%macro PIXEL11_22 0 + Interp2 [edi+ebx+4],eax,[c9],[c6] +%endmacro + +%macro PIXEL11_60 0 + Interp6 [edi+ebx+4],[c8],[c6] +%endmacro + +%macro PIXEL11_61 0 + Interp6 [edi+ebx+4],[c6],[c8] +%endmacro + +%macro PIXEL11_70 0 + Interp7 [edi+ebx+4],[c6],[c8] +%endmacro + +%macro PIXEL11_90 0 + Interp9 [edi+ebx+4],[c6],[c8] +%endmacro + +%macro PIXEL11_100 0 + Interp10 [edi+ebx+4],[c6],[c8] +%endmacro + +inbuffer equ 8 +outbuffer equ 12 +Xres equ 16 +Yres equ 20 +pitch equ 24 + +_hq2x_32: + push ebp + mov ebp,esp + pushad + + mov esi,[ebp+inbuffer] + mov edi,[ebp+outbuffer] + mov edx,[ebp+Yres] + mov [linesleft],edx + mov ebx,[ebp+Xres] + shl ebx,1 + mov dword[prevline],0 + mov dword[nextline],ebx +.loopy + push edi + mov ecx,[ebp+Xres] + sub ecx,2 ; x={Xres-2, Xres-1} are special cases. + mov dword[xcounter],ecx + ; x=0 - special case + mov ebx,[prevline] + movq mm5,[esi+ebx] + movq mm6,[esi] + mov ebx,[nextline] + movq mm7,[esi+ebx] + movd eax,mm5 + movzx edx,ax + mov [w1],edx + mov [w2],edx + shr eax,16 + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + mov [w5],edx + shr eax,16 + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + mov [w8],edx + shr eax,16 + mov [w9],eax + jmp .flags +.loopx + mov ebx,[prevline] + movq mm5,[esi+ebx-2] + movq mm6,[esi-2] + mov ebx,[nextline] + movq mm7,[esi+ebx-2] + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + psrlq mm5,32 + movd eax,mm5 + movzx edx,ax + mov [w3],edx + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + psrlq mm6,32 + movd eax,mm6 + movzx edx,ax + mov [w6],edx + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + psrlq mm7,32 + movd eax,mm7 + movzx edx,ax + mov [w9],edx +.flags + mov ebx,_RGBtoYUV + mov eax,[w5] + xor ecx,ecx + movd mm5,[ebx+eax*4] + mov dword[cross],0 + + mov edx,[w2] + cmp eax,edx + je .noflag2 + or dword[cross],1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag2 + or ecx,2 +.noflag2 + mov edx,[w4] + cmp eax,edx + je .noflag4 + or dword[cross],2 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag4 + or ecx,8 +.noflag4 + mov edx,[w6] + cmp eax,edx + je .noflag6 + or dword[cross],4 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag6 + or ecx,16 +.noflag6 + mov edx,[w8] + cmp eax,edx + je .noflag8 + or dword[cross],8 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag8 + or ecx,64 +.noflag8 + test ecx,ecx + jnz .testflag1 + mov ecx,[cross] + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + jmp [FuncTable2+ecx*4] +.testflag1 + mov edx,[w1] + cmp eax,edx + je .noflag1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag1 + or ecx,1 +.noflag1 + mov edx,[w3] + cmp eax,edx + je .noflag3 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag3 + or ecx,4 +.noflag3 + mov edx,[w7] + cmp eax,edx + je .noflag7 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag7 + or ecx,32 +.noflag7 + mov edx,[w9] + cmp eax,edx + je .noflag9 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag9 + or ecx,128 +.noflag9 + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + mov edx,[w2] + mov edx,[ebx+edx*4] + mov [c2],edx + mov edx,[w4] + mov edx,[ebx+edx*4] + mov [c4],edx + mov edx,[w6] + mov edx,[ebx+edx*4] + mov [c6],edx + mov edx,[w8] + mov edx,[ebx+edx*4] + mov [c8],edx + test ecx,0x005A + jz .switch + mov edx,[w1] + mov edx,[ebx+edx*4] + mov [c1],edx + mov edx,[w3] + mov edx,[ebx+edx*4] + mov [c3],edx + mov edx,[w7] + mov edx,[ebx+edx*4] + mov [c7],edx + mov edx,[w9] + mov edx,[ebx+edx*4] + mov [c9],edx +.switch + mov ebx,[ebp+pitch] + jmp [FuncTable+ecx*4] + +..@flag0 +..@flag1 +..@flag4 +..@flag32 +..@flag128 +..@flag5 +..@flag132 +..@flag160 +..@flag33 +..@flag129 +..@flag36 +..@flag133 +..@flag164 +..@flag161 +..@flag37 +..@flag165 +; PIXEL00_20 +; PIXEL01_20 +; PIXEL10_20 +; PIXEL11_20 + +; the same, only optimized + shl eax,1 + mov ecx,eax + add ecx,[c2] + mov edx,ecx + add edx,[c4] + shr edx,2 + mov [edi],edx + add ecx,[c6] + shr ecx,2 + mov [edi+4],ecx + mov ecx,eax + add ecx,[c8] + mov edx,ecx + add edx,[c4] + shr edx,2 + mov [edi+ebx],edx + add ecx,[c6] + shr ecx,2 + mov [edi+ebx+4],ecx + jmp .loopx_end +..@flag2 +..@flag34 +..@flag130 +..@flag162 + PIXEL00_22 + PIXEL01_21 + PIXEL10_20 + PIXEL11_20 + jmp .loopx_end +..@flag16 +..@flag17 +..@flag48 +..@flag49 + PIXEL00_20 + PIXEL01_22 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag64 +..@flag65 +..@flag68 +..@flag69 + PIXEL00_20 + PIXEL01_20 + PIXEL10_21 + PIXEL11_22 + jmp .loopx_end +..@flag8 +..@flag12 +..@flag136 +..@flag140 + PIXEL00_21 + PIXEL01_20 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag3 +..@flag35 +..@flag131 +..@flag163 + PIXEL00_11 + PIXEL01_21 + PIXEL10_20 + PIXEL11_20 + jmp .loopx_end +..@flag6 +..@flag38 +..@flag134 +..@flag166 + PIXEL00_22 + PIXEL01_12 + PIXEL10_20 + PIXEL11_20 + jmp .loopx_end +..@flag20 +..@flag21 +..@flag52 +..@flag53 + PIXEL00_20 + PIXEL01_11 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag144 +..@flag145 +..@flag176 +..@flag177 + PIXEL00_20 + PIXEL01_22 + PIXEL10_20 + PIXEL11_12 + jmp .loopx_end +..@flag192 +..@flag193 +..@flag196 +..@flag197 + PIXEL00_20 + PIXEL01_20 + PIXEL10_21 + PIXEL11_11 + jmp .loopx_end +..@flag96 +..@flag97 +..@flag100 +..@flag101 + PIXEL00_20 + PIXEL01_20 + PIXEL10_12 + PIXEL11_22 + jmp .loopx_end +..@flag40 +..@flag44 +..@flag168 +..@flag172 + PIXEL00_21 + PIXEL01_20 + PIXEL10_11 + PIXEL11_20 + jmp .loopx_end +..@flag9 +..@flag13 +..@flag137 +..@flag141 + PIXEL00_12 + PIXEL01_20 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag18 +..@flag50 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_20 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag80 +..@flag81 + PIXEL00_20 + PIXEL01_22 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_20 + jmp .loopx_end +..@flag72 +..@flag76 + PIXEL00_21 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag10 +..@flag138 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_20 + PIXEL01_21 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag66 + PIXEL00_22 + PIXEL01_21 + PIXEL10_21 + PIXEL11_22 + jmp .loopx_end +..@flag24 + PIXEL00_21 + PIXEL01_22 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag7 +..@flag39 +..@flag135 + PIXEL00_11 + PIXEL01_12 + PIXEL10_20 + PIXEL11_20 + jmp .loopx_end +..@flag148 +..@flag149 +..@flag180 + PIXEL00_20 + PIXEL01_11 + PIXEL10_20 + PIXEL11_12 + jmp .loopx_end +..@flag224 +..@flag228 +..@flag225 + PIXEL00_20 + PIXEL01_20 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag41 +..@flag169 +..@flag45 + PIXEL00_12 + PIXEL01_20 + PIXEL10_11 + PIXEL11_20 + jmp .loopx_end +..@flag22 +..@flag54 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag208 +..@flag209 + PIXEL00_20 + PIXEL01_22 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag104 +..@flag108 + PIXEL00_21 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag11 +..@flag139 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_21 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag19 +..@flag51 + DiffOrNot w2,w6,PIXEL00_11,PIXEL01_10,PIXEL00_60,PIXEL01_90 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag146 +..@flag178 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_10,PIXEL11_12,PIXEL01_90,PIXEL11_61 + PIXEL10_20 + jmp .loopx_end +..@flag84 +..@flag85 + PIXEL00_20 + DiffOrNot w6,w8,PIXEL01_11,PIXEL11_10,PIXEL01_60,PIXEL11_90 + PIXEL10_21 + jmp .loopx_end +..@flag112 +..@flag113 + PIXEL00_20 + PIXEL01_22 + DiffOrNot w6,w8,PIXEL10_12,PIXEL11_10,PIXEL10_61,PIXEL11_90 + jmp .loopx_end +..@flag200 +..@flag204 + PIXEL00_21 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_10,PIXEL11_11,PIXEL10_90,PIXEL11_60 + jmp .loopx_end +..@flag73 +..@flag77 + DiffOrNot w8,w4,PIXEL00_12,PIXEL10_10,PIXEL00_61,PIXEL10_90 + PIXEL01_20 + PIXEL11_22 + jmp .loopx_end +..@flag42 +..@flag170 + DiffOrNot w4,w2,PIXEL00_10,PIXEL10_11,PIXEL00_90,PIXEL10_60 + PIXEL01_21 + PIXEL11_20 + jmp .loopx_end +..@flag14 +..@flag142 + DiffOrNot w4,w2,PIXEL00_10,PIXEL01_12,PIXEL00_90,PIXEL01_61 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag67 + PIXEL00_11 + PIXEL01_21 + PIXEL10_21 + PIXEL11_22 + jmp .loopx_end +..@flag70 + PIXEL00_22 + PIXEL01_12 + PIXEL10_21 + PIXEL11_22 + jmp .loopx_end +..@flag28 + PIXEL00_21 + PIXEL01_11 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag152 + PIXEL00_21 + PIXEL01_22 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag194 + PIXEL00_22 + PIXEL01_21 + PIXEL10_21 + PIXEL11_11 + jmp .loopx_end +..@flag98 + PIXEL00_22 + PIXEL01_21 + PIXEL10_12 + PIXEL11_22 + jmp .loopx_end +..@flag56 + PIXEL00_21 + PIXEL01_22 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag25 + PIXEL00_12 + PIXEL01_22 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag26 +..@flag31 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag82 +..@flag214 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag88 +..@flag248 + PIXEL00_21 + PIXEL01_22 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag74 +..@flag107 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_21 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag27 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_10 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag86 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_21 + PIXEL11_10 + jmp .loopx_end +..@flag216 + PIXEL00_21 + PIXEL01_22 + PIXEL10_10 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag106 + PIXEL00_10 + PIXEL01_21 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag30 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag210 + PIXEL00_22 + PIXEL01_10 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag120 + PIXEL00_21 + PIXEL01_22 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_10 + jmp .loopx_end +..@flag75 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_21 + PIXEL10_10 + PIXEL11_22 + jmp .loopx_end +..@flag29 + PIXEL00_12 + PIXEL01_11 + PIXEL10_22 + PIXEL11_21 + jmp .loopx_end +..@flag198 + PIXEL00_22 + PIXEL01_12 + PIXEL10_21 + PIXEL11_11 + jmp .loopx_end +..@flag184 + PIXEL00_21 + PIXEL01_22 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag99 + PIXEL00_11 + PIXEL01_21 + PIXEL10_12 + PIXEL11_22 + jmp .loopx_end +..@flag57 + PIXEL00_12 + PIXEL01_22 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag71 + PIXEL00_11 + PIXEL01_12 + PIXEL10_21 + PIXEL11_22 + jmp .loopx_end +..@flag156 + PIXEL00_21 + PIXEL01_11 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag226 + PIXEL00_22 + PIXEL01_21 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag60 + PIXEL00_21 + PIXEL01_11 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag195 + PIXEL00_11 + PIXEL01_21 + PIXEL10_21 + PIXEL11_11 + jmp .loopx_end +..@flag102 + PIXEL00_22 + PIXEL01_12 + PIXEL10_12 + PIXEL11_22 + jmp .loopx_end +..@flag153 + PIXEL00_12 + PIXEL01_22 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag58 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag83 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag92 + PIXEL00_21 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag202 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + PIXEL01_21 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + PIXEL11_11 + jmp .loopx_end +..@flag78 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + PIXEL11_22 + jmp .loopx_end +..@flag154 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag114 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag89 + PIXEL00_12 + PIXEL01_22 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag90 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag55 +..@flag23 + DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90 + PIXEL10_20 + PIXEL11_21 + jmp .loopx_end +..@flag182 +..@flag150 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61 + PIXEL10_20 + jmp .loopx_end +..@flag213 +..@flag212 + PIXEL00_20 + DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90 + PIXEL10_21 + jmp .loopx_end +..@flag241 +..@flag240 + PIXEL00_20 + PIXEL01_22 + DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90 + jmp .loopx_end +..@flag236 +..@flag232 + PIXEL00_21 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60 + jmp .loopx_end +..@flag109 +..@flag105 + DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90 + PIXEL01_20 + PIXEL11_22 + jmp .loopx_end +..@flag171 +..@flag43 + DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60 + PIXEL01_21 + PIXEL11_20 + jmp .loopx_end +..@flag143 +..@flag15 + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61 + PIXEL10_22 + PIXEL11_20 + jmp .loopx_end +..@flag124 + PIXEL00_21 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_10 + jmp .loopx_end +..@flag203 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_21 + PIXEL10_10 + PIXEL11_11 + jmp .loopx_end +..@flag62 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag211 + PIXEL00_11 + PIXEL01_10 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag118 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_12 + PIXEL11_10 + jmp .loopx_end +..@flag217 + PIXEL00_12 + PIXEL01_22 + PIXEL10_10 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag110 + PIXEL00_10 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag155 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_10 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag188 + PIXEL00_21 + PIXEL01_11 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag185 + PIXEL00_12 + PIXEL01_22 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag61 + PIXEL00_12 + PIXEL01_11 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag157 + PIXEL00_12 + PIXEL01_11 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag103 + PIXEL00_11 + PIXEL01_12 + PIXEL10_12 + PIXEL11_22 + jmp .loopx_end +..@flag227 + PIXEL00_11 + PIXEL01_21 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag230 + PIXEL00_22 + PIXEL01_12 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag199 + PIXEL00_11 + PIXEL01_12 + PIXEL10_21 + PIXEL11_11 + jmp .loopx_end +..@flag220 + PIXEL00_21 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag158 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag234 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + PIXEL01_21 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_11 + jmp .loopx_end +..@flag242 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag59 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag121 + PIXEL00_12 + PIXEL01_22 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag87 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag79 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + PIXEL11_22 + jmp .loopx_end +..@flag122 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag94 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag218 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag91 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag229 + PIXEL00_20 + PIXEL01_20 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag167 + PIXEL00_11 + PIXEL01_12 + PIXEL10_20 + PIXEL11_20 + jmp .loopx_end +..@flag173 + PIXEL00_12 + PIXEL01_20 + PIXEL10_11 + PIXEL11_20 + jmp .loopx_end +..@flag181 + PIXEL00_20 + PIXEL01_11 + PIXEL10_20 + PIXEL11_12 + jmp .loopx_end +..@flag186 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag115 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag93 + PIXEL00_12 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag206 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + PIXEL11_11 + jmp .loopx_end +..@flag205 +..@flag201 + PIXEL00_12 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_10,PIXEL10_70 + PIXEL11_11 + jmp .loopx_end +..@flag174 +..@flag46 + DiffOrNot w4,w2,PIXEL00_10,PIXEL00_70 + PIXEL01_12 + PIXEL10_11 + PIXEL11_20 + jmp .loopx_end +..@flag179 +..@flag147 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_10,PIXEL01_70 + PIXEL10_20 + PIXEL11_12 + jmp .loopx_end +..@flag117 +..@flag116 + PIXEL00_20 + PIXEL01_11 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_10,PIXEL11_70 + jmp .loopx_end +..@flag189 + PIXEL00_12 + PIXEL01_11 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag231 + PIXEL00_11 + PIXEL01_12 + PIXEL10_12 + PIXEL11_11 + jmp .loopx_end +..@flag126 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_10 + jmp .loopx_end +..@flag219 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_10 + PIXEL10_10 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag125 + DiffOrNot w8,w4,PIXEL00_12,PIXEL10_0,PIXEL00_61,PIXEL10_90 + PIXEL01_11 + PIXEL11_10 + jmp .loopx_end +..@flag221 + PIXEL00_12 + DiffOrNot w6,w8,PIXEL01_11,PIXEL11_0,PIXEL01_60,PIXEL11_90 + PIXEL10_10 + jmp .loopx_end +..@flag207 + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_12,PIXEL00_90,PIXEL01_61 + PIXEL10_10 + PIXEL11_11 + jmp .loopx_end +..@flag238 + PIXEL00_10 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_0,PIXEL11_11,PIXEL10_90,PIXEL11_60 + jmp .loopx_end +..@flag190 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL11_12,PIXEL01_90,PIXEL11_61 + PIXEL10_11 + jmp .loopx_end +..@flag187 + DiffOrNot w4,w2,PIXEL00_0,PIXEL10_11,PIXEL00_90,PIXEL10_60 + PIXEL01_10 + PIXEL11_12 + jmp .loopx_end +..@flag243 + PIXEL00_11 + PIXEL01_10 + DiffOrNot w6,w8,PIXEL10_12,PIXEL11_0,PIXEL10_61,PIXEL11_90 + jmp .loopx_end +..@flag119 + DiffOrNot w2,w6,PIXEL00_11,PIXEL01_0,PIXEL00_60,PIXEL01_90 + PIXEL10_12 + PIXEL11_10 + jmp .loopx_end +..@flag237 +..@flag233 + PIXEL00_12 + PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + PIXEL11_11 + jmp .loopx_end +..@flag175 +..@flag47 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + PIXEL01_12 + PIXEL10_11 + PIXEL11_20 + jmp .loopx_end +..@flag183 +..@flag151 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_20 + PIXEL11_12 + jmp .loopx_end +..@flag245 +..@flag244 + PIXEL00_20 + PIXEL01_11 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag250 + PIXEL00_10 + PIXEL01_10 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag123 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_10 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_10 + jmp .loopx_end +..@flag95 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_10 + PIXEL11_10 + jmp .loopx_end +..@flag222 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_10 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag252 + PIXEL00_21 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag249 + PIXEL00_12 + PIXEL01_22 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag235 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_21 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + PIXEL11_11 + jmp .loopx_end +..@flag111 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_22 + jmp .loopx_end +..@flag63 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_11 + PIXEL11_21 + jmp .loopx_end +..@flag159 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_22 + PIXEL11_12 + jmp .loopx_end +..@flag215 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_21 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag246 + PIXEL00_22 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag254 + PIXEL00_10 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag253 + PIXEL00_12 + PIXEL01_11 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag251 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_10 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag239 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + PIXEL01_12 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + PIXEL11_11 + jmp .loopx_end +..@flag127 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_20 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_20 + PIXEL11_10 + jmp .loopx_end +..@flag191 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_11 + PIXEL11_12 + jmp .loopx_end +..@flag223 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_10 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_20 + jmp .loopx_end +..@flag247 + PIXEL00_11 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + PIXEL10_12 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end +..@flag255 + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_100 + DiffOrNot w2,w6,PIXEL01_0,PIXEL01_100 + DiffOrNot w8,w4,PIXEL10_0,PIXEL10_100 + DiffOrNot w6,w8,PIXEL11_0,PIXEL11_100 + jmp .loopx_end + + +..@cross0 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+ebx],eax + mov [edi+ebx+4],eax + jmp .loopx_end +..@cross1 + mov ecx,[w2] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],edx + mov [edi+4],edx + mov [edi+ebx],eax + mov [edi+ebx+4],eax + jmp .loopx_end +..@cross2 + mov ecx,[w4] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],edx + mov [edi+4],eax + mov [edi+ebx],edx + mov [edi+ebx+4],eax + jmp .loopx_end +..@cross4 + mov ecx,[w6] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],edx + mov [edi+ebx],eax + mov [edi+ebx+4],edx + jmp .loopx_end +..@cross8 + mov ecx,[w8] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+ebx],edx + mov [edi+ebx+4],edx + jmp .loopx_end +..@crossN + mov edx,[w2] + mov ecx,[ebx+edx*4] + mov [c2],ecx + mov edx,[w4] + mov ecx,[ebx+edx*4] + mov [c4],ecx + mov edx,[w6] + mov ecx,[ebx+edx*4] + mov [c6],ecx + mov edx,[w8] + mov ecx,[ebx+edx*4] + mov [c8],ecx + mov ebx,[ebp+pitch] + jmp ..@flag0 + +.loopx_end + add esi,2 + add edi,8 + dec dword[xcounter] + jle .xres_2 + jmp .loopx + +.xres_2 + ; x=Xres-2 - special case + jl .xres_1 + mov ebx,[prevline] + movq mm5,[esi+ebx-4] + movq mm6,[esi-4] + mov ebx,[nextline] + movq mm7,[esi+ebx-4] + psrlq mm5,16 + psrlq mm6,16 + psrlq mm7,16 + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + psrlq mm5,32 + movd eax,mm5 + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + psrlq mm6,32 + movd eax,mm6 + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + psrlq mm7,32 + movd eax,mm7 + mov [w9],eax + jmp .flags + +.xres_1 + cmp dword[xcounter],-1 + jl .nexty + ; x=Xres-1 - special case + mov ebx,[prevline] + movq mm5,[esi+ebx-6] + movq mm6,[esi-6] + mov ebx,[nextline] + movq mm7,[esi+ebx-6] + psrlq mm5,32 + psrlq mm6,32 + psrlq mm7,32 + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + mov [w9],eax + jmp .flags +.nexty + pop edi + add edi,ebx + add edi,ebx + dec dword[linesleft] + jz .fin + mov ebx,[ebp+Xres] + shl ebx,1 + cmp dword[linesleft],1 + je .lastline + mov dword[nextline],ebx + neg ebx + mov dword[prevline],ebx + jmp .loopy +.lastline + mov dword[nextline],0 + neg ebx + mov dword[prevline],ebx + jmp .loopy +.fin + emms + popad + mov esp,ebp + pop ebp + ret + +SECTION .data +FuncTable + dd ..@flag0, ..@flag1, ..@flag2, ..@flag3, ..@flag4, ..@flag5, ..@flag6, ..@flag7 + dd ..@flag8, ..@flag9, ..@flag10, ..@flag11, ..@flag12, ..@flag13, ..@flag14, ..@flag15 + dd ..@flag16, ..@flag17, ..@flag18, ..@flag19, ..@flag20, ..@flag21, ..@flag22, ..@flag23 + dd ..@flag24, ..@flag25, ..@flag26, ..@flag27, ..@flag28, ..@flag29, ..@flag30, ..@flag31 + dd ..@flag32, ..@flag33, ..@flag34, ..@flag35, ..@flag36, ..@flag37, ..@flag38, ..@flag39 + dd ..@flag40, ..@flag41, ..@flag42, ..@flag43, ..@flag44, ..@flag45, ..@flag46, ..@flag47 + dd ..@flag48, ..@flag49, ..@flag50, ..@flag51, ..@flag52, ..@flag53, ..@flag54, ..@flag55 + dd ..@flag56, ..@flag57, ..@flag58, ..@flag59, ..@flag60, ..@flag61, ..@flag62, ..@flag63 + dd ..@flag64, ..@flag65, ..@flag66, ..@flag67, ..@flag68, ..@flag69, ..@flag70, ..@flag71 + dd ..@flag72, ..@flag73, ..@flag74, ..@flag75, ..@flag76, ..@flag77, ..@flag78, ..@flag79 + dd ..@flag80, ..@flag81, ..@flag82, ..@flag83, ..@flag84, ..@flag85, ..@flag86, ..@flag87 + dd ..@flag88, ..@flag89, ..@flag90, ..@flag91, ..@flag92, ..@flag93, ..@flag94, ..@flag95 + dd ..@flag96, ..@flag97, ..@flag98, ..@flag99, ..@flag100, ..@flag101, ..@flag102, ..@flag103 + dd ..@flag104, ..@flag105, ..@flag106, ..@flag107, ..@flag108, ..@flag109, ..@flag110, ..@flag111 + dd ..@flag112, ..@flag113, ..@flag114, ..@flag115, ..@flag116, ..@flag117, ..@flag118, ..@flag119 + dd ..@flag120, ..@flag121, ..@flag122, ..@flag123, ..@flag124, ..@flag125, ..@flag126, ..@flag127 + dd ..@flag128, ..@flag129, ..@flag130, ..@flag131, ..@flag132, ..@flag133, ..@flag134, ..@flag135 + dd ..@flag136, ..@flag137, ..@flag138, ..@flag139, ..@flag140, ..@flag141, ..@flag142, ..@flag143 + dd ..@flag144, ..@flag145, ..@flag146, ..@flag147, ..@flag148, ..@flag149, ..@flag150, ..@flag151 + dd ..@flag152, ..@flag153, ..@flag154, ..@flag155, ..@flag156, ..@flag157, ..@flag158, ..@flag159 + dd ..@flag160, ..@flag161, ..@flag162, ..@flag163, ..@flag164, ..@flag165, ..@flag166, ..@flag167 + dd ..@flag168, ..@flag169, ..@flag170, ..@flag171, ..@flag172, ..@flag173, ..@flag174, ..@flag175 + dd ..@flag176, ..@flag177, ..@flag178, ..@flag179, ..@flag180, ..@flag181, ..@flag182, ..@flag183 + dd ..@flag184, ..@flag185, ..@flag186, ..@flag187, ..@flag188, ..@flag189, ..@flag190, ..@flag191 + dd ..@flag192, ..@flag193, ..@flag194, ..@flag195, ..@flag196, ..@flag197, ..@flag198, ..@flag199 + dd ..@flag200, ..@flag201, ..@flag202, ..@flag203, ..@flag204, ..@flag205, ..@flag206, ..@flag207 + dd ..@flag208, ..@flag209, ..@flag210, ..@flag211, ..@flag212, ..@flag213, ..@flag214, ..@flag215 + dd ..@flag216, ..@flag217, ..@flag218, ..@flag219, ..@flag220, ..@flag221, ..@flag222, ..@flag223 + dd ..@flag224, ..@flag225, ..@flag226, ..@flag227, ..@flag228, ..@flag229, ..@flag230, ..@flag231 + dd ..@flag232, ..@flag233, ..@flag234, ..@flag235, ..@flag236, ..@flag237, ..@flag238, ..@flag239 + dd ..@flag240, ..@flag241, ..@flag242, ..@flag243, ..@flag244, ..@flag245, ..@flag246, ..@flag247 + dd ..@flag248, ..@flag249, ..@flag250, ..@flag251, ..@flag252, ..@flag253, ..@flag254, ..@flag255 + +FuncTable2 + dd ..@cross0, ..@cross1, ..@cross2, ..@crossN, + dd ..@cross4, ..@crossN, ..@crossN, ..@crossN, + dd ..@cross8, ..@crossN, ..@crossN, ..@crossN, + dd ..@crossN, ..@crossN, ..@crossN, ..@crossN + diff --git a/src/interface/scalers/hq2xs.cpp b/src/interface/scalers/hq2xs.cpp new file mode 100644 index 00000000..80ca525c --- /dev/null +++ b/src/interface/scalers/hq2xs.cpp @@ -0,0 +1,352 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#include "interp.h" + +unsigned interp_mask[2]; +unsigned interp_bits_per_pixel; + +/***************************************************************************/ +/* HQ2xS C implementation */ + +/* + * This effect is derived from the hq2x effect made by Maxim Stepin + */ + +static void hq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count) +{ + unsigned i; + + for(i=0;i> 3; + r = (int)((c[j] & 0xF800)) >> 8; + } else { + b = (int)((c[j] & 0x1F)) << 3; + g = (int)((c[j] & 0x3E0)) >> 2; + r = (int)((c[j] & 0x7C00)) >> 7; + } + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + #define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right +#define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right +#define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left +#define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left +#define IC(p0) c[p0] +#define I11(p0,p1) interp_16_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_16_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_16_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_16_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_16_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_16_151(c[p0], c[p1]) + + switch (mask) { +#include "hq2xs.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +static void hq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + #define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right +#define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right +#define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left +#define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "hq2xs.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +void hq2xS(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u16 *dst0 = (u16 *)dstPtr; + u16 *dst1 = dst0 + (dstPitch >> 1); + + u16 *src0 = (u16 *)srcPtr; + u16 *src1 = src0 + (srcPitch >> 1); + u16 *src2 = src1 + (srcPitch >> 1); + + hq2xS_16_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch; + dst1 += dstPitch; + hq2xS_16_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 1; + --count; + } + dst0 += dstPitch; + dst1 += dstPitch; + hq2xS_16_def(dst0, dst1, src0, src1, src1, width); +} + +void hq2xS32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dst0 = (u32 *)dstPtr; + u32 *dst1 = dst0 + (dstPitch >> 2); + + u32 *src0 = (u32 *)srcPtr; + u32 *src1 = src0 + (srcPitch >> 2); + u32 *src2 = src1 + (srcPitch >> 2); + hq2xS_32_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src1, width); +} + +void hq2xS_init(unsigned bits_per_pixel) +{ + interp_set(bits_per_pixel); +} diff --git a/src/interface/scalers/hq2xs.h b/src/interface/scalers/hq2xs.h new file mode 100644 index 00000000..64c5778b --- /dev/null +++ b/src/interface/scalers/hq2xs.h @@ -0,0 +1,1824 @@ +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 10 : +case 138 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 11 : +case 139 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 15 : +case 143 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 18 : +case 50 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = I31(4, 2); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 22 : +case 54 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 23 : +case 55 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 24 : +case 66 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 25 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 26 : +case 31 : +case 95 : +{ + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 27 : +case 75 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 28 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 29 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 30 : +case 86 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 42 : +case 170 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 43 : +case 171 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 46 : +case 174 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 56 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 57 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 58 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 59 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 60 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 61 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 62 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 63 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 67 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 70 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 71 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 72 : +case 76 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 73 : +case 77 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = I31(4, 6); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 74 : +case 107 : +case 123 : +{ + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 78 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 79 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 81 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 83 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 84 : +case 85 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = I31(4, 8); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 87 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 89 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 90 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 91 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 92 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 93 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 94 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 98 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 99 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 102 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 103 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 104 : +case 108 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 105 : +case 109 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 106 : +case 120 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 110 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 111 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 113 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = I31(4, 8); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 114 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 115 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 116 : +case 117 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 118 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 119 : +{ + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 121 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 122 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 124 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 125 : +{ + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 126 : +{ + P0 = I31(4, 0); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 127 : +{ + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 146 : +case 178 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = I31(4, 2); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 147 : +case 179 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 150 : +case 182 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 151 : +case 183 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 152 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 153 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 154 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 155 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 156 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 157 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 158 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 159 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 184 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 185 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 186 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 187 : +{ + P1 = I31(4, 2); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 188 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 189 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 190 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 191 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 194 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 195 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 198 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 199 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 200 : +case 204 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = I31(4, 6); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 201 : +case 205 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } +} break; +case 202 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 203 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 206 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 207 : +{ + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 208 : +case 209 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 210 : +case 216 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 211 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 212 : +case 213 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 215 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 217 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 218 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 219 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 220 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 221 : +{ + P0 = I31(4, 1); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 223 : +{ + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 226 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 227 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 230 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 231 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 232 : +case 236 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } +} break; +case 234 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 235 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 238 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 239 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 240 : +case 241 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 242 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 243 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 244 : +case 245 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 246 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 247 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 249 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 251 : +{ + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 252 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 253 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 254 : +{ + P0 = I31(4, 0); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 255 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; diff --git a/src/interface/scalers/hq2xs_16.cpp b/src/interface/scalers/hq2xs_16.cpp new file mode 100644 index 00000000..d7671d75 --- /dev/null +++ b/src/interface/scalers/hq2xs_16.cpp @@ -0,0 +1,764 @@ +// hq2xs, hq2xbold, hq3xs, hq3xbold filters, added by regret +// source from Snes9X v1.51+ (http://code.google.com/p/snes9x151-rerecording/) + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef unsigned int uint32; + +#define Mask_2 0x07E0 // 00000 111111 00000 +#define Mask13 0xF81F // 11111 000000 11111 +#define Mask_1 0x001F // 00000 000000 11111 +#define Mask_3 0xF800 // 11111 000000 00000 +#define NUMBITS (16) + +static int RGBtoYUV[1<> 1) & Mask_2) + \ + (((((c1) & Mask13) + ((c2) & Mask13)) >> 1) & Mask13))) +#define Interp01(c1, c2) \ + ((((c1) == (c2)) ? (c1) : \ + (((((((c1) & Mask_2) * 3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \ + ((((((c1) & Mask13) * 3) + ((c2) & Mask13)) >> 2) & Mask13)))) +#define Halve(c1) \ + ((((((c1) & Mask_2)) >> 1) & Mask_2) + \ + (((((c1) & Mask13)) >> 1) & Mask13)) +#define ThreeQuarters(c1) \ + ((((((c1) & Mask_2)*3) >> 2) & Mask_2) + \ + (((((c1) & Mask13)*3) >> 2) & Mask13)) + +#define Ymask 0xFF0000 +#define Umask 0x00FF00 +#define Vmask 0x0000FF +#define trY 0x300000 +#define trU 0x000700 +#define trV 0x000006 + +#define Absolute(c) \ + (!((c) & (1 << 31)) ? (c) : (~(c) + 1)) + +static inline bool Diff(int c1, int c2) +{ + int c1y = (c1 & Ymask) - (c2 & Ymask); + if (Absolute(c1y) > trY) return true; + int c1u = (c1 & Umask) - (c2 & Umask); + if (Absolute(c1u) > trU) return true; + int c1v = (c1 & Vmask) - (c2 & Vmask); + if (Absolute(c1v) > trV) return true; + + return false; +} + +void InitLUTs(void) +{ + int c, r, g, b, y, u, v; + + for (c = 0 ; c < (1<> 3; + r = (int)((c & 0xF800)) >> 8; + RGBtoBright[c] = r+r+r + g+g+g + b+b; + + y = (int)( 0.256788f*r + 0.504129f*g + 0.097906f*b + 0.5f) + 16; + u = (int)(-0.148223f*r - 0.290993f*g + 0.439216f*b + 0.5f) + 128; + v = (int)( 0.439216f*r - 0.367788f*g - 0.071427f*b + 0.5f) + 128; + + RGBtoYUV[c] = (y << 16) + (u << 8) + v; + +// y = (r + g + b) >> 2; +// u = 128 + ((r - b) >> 2); +// v = 128 + ((-r + 2 * g - b) >> 3); +// +// RGBtoYUVLQ[c] = (y << 16) + (u << 8) + v; + } +} + +#define Interp02(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 2) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 2) & Mask13)) + +#define Interp06(c1, c2, c3) \ + ((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) * 2 + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 5 + ((c2) & Mask13) * 2 + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp07(c1, c2, c3) \ + ((((((c1) & Mask_2) * 6 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 6 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp09(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 3 + ((c3) & Mask_2) * 3) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) * 3 + ((c3) & Mask13) * 3) >> 3) & Mask13)) + +#define Interp10(c1, c2, c3) \ + ((((((c1) & Mask_2) * 14 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 4) & Mask_2) + \ + (((((c1) & Mask13) * 14 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 4) & Mask13)) + + +// HQ2xS + +#define PIXEL00_0 *(dp) = w5 +#define PIXEL00_10 *(dp) = Interp01(w5, w1) +#define PIXEL00_11 *(dp) = Interp01(w5, w4) +#define PIXEL00_12 *(dp) = Interp01(w5, w2) +#define PIXEL00_20 *(dp) = Interp02(w5, w4, w2) +#define PIXEL00_21 *(dp) = Interp02(w5, w1, w2) +#define PIXEL00_22 *(dp) = Interp02(w5, w1, w4) +#define PIXEL00_60 *(dp) = Interp06(w5, w2, w4) +#define PIXEL00_61 *(dp) = Interp06(w5, w4, w2) +#define PIXEL00_70 *(dp) = Interp07(w5, w4, w2) +#define PIXEL00_90 *(dp) = Interp09(w5, w4, w2) +#define PIXEL00_100 *(dp) = Interp10(w5, w4, w2) + +#define PIXEL01_0 *(dp + 1) = w5 +#define PIXEL01_10 *(dp + 1) = Interp01(w5, w3) +#define PIXEL01_11 *(dp + 1) = Interp01(w5, w2) +#define PIXEL01_12 *(dp + 1) = Interp01(w5, w6) +#define PIXEL01_20 *(dp + 1) = Interp02(w5, w2, w6) +#define PIXEL01_21 *(dp + 1) = Interp02(w5, w3, w6) +#define PIXEL01_22 *(dp + 1) = Interp02(w5, w3, w2) +#define PIXEL01_60 *(dp + 1) = Interp06(w5, w6, w2) +#define PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w6) +#define PIXEL01_70 *(dp + 1) = Interp07(w5, w2, w6) +#define PIXEL01_90 *(dp + 1) = Interp09(w5, w2, w6) +#define PIXEL01_100 *(dp + 1) = Interp10(w5, w2, w6) + +#define PIXEL10_0 *(dp + dst1line) = w5 +#define PIXEL10_10 *(dp + dst1line) = Interp01(w5, w7) +#define PIXEL10_11 *(dp + dst1line) = Interp01(w5, w8) +#define PIXEL10_12 *(dp + dst1line) = Interp01(w5, w4) +#define PIXEL10_20 *(dp + dst1line) = Interp02(w5, w8, w4) +#define PIXEL10_21 *(dp + dst1line) = Interp02(w5, w7, w4) +#define PIXEL10_22 *(dp + dst1line) = Interp02(w5, w7, w8) +#define PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w8) +#define PIXEL10_61 *(dp + dst1line) = Interp06(w5, w8, w4) +#define PIXEL10_70 *(dp + dst1line) = Interp07(w5, w8, w4) +#define PIXEL10_90 *(dp + dst1line) = Interp09(w5, w8, w4) +#define PIXEL10_100 *(dp + dst1line) = Interp10(w5, w8, w4) + +#define PIXEL11_0 *(dp + dst1line + 1) = w5 +#define PIXEL11_10 *(dp + dst1line + 1) = Interp01(w5, w9) +#define PIXEL11_11 *(dp + dst1line + 1) = Interp01(w5, w6) +#define PIXEL11_12 *(dp + dst1line + 1) = Interp01(w5, w8) +#define PIXEL11_20 *(dp + dst1line + 1) = Interp02(w5, w6, w8) +#define PIXEL11_21 *(dp + dst1line + 1) = Interp02(w5, w9, w8) +#define PIXEL11_22 *(dp + dst1line + 1) = Interp02(w5, w9, w6) +#define PIXEL11_60 *(dp + dst1line + 1) = Interp06(w5, w8, w6) +#define PIXEL11_61 *(dp + dst1line + 1) = Interp06(w5, w6, w8) +#define PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w6, w8) +#define PIXEL11_90 *(dp + dst1line + 1) = Interp09(w5, w6, w8) +#define PIXEL11_100 *(dp + dst1line + 1) = Interp10(w5, w6, w8) + + +#define HQ2XCASES \ + case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: PIXEL00_20; PIXEL01_20; PIXEL10_20; PIXEL11_20; break; \ + case 2: case 34: case 130: case 162: PIXEL00_22; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 16: case 17: case 48: case 49: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_21; break; \ + case 64: case 65: case 68: case 69: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_22; break; \ + case 8: case 12: case 136: case 140: PIXEL00_21; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 3: case 35: case 131: case 163: PIXEL00_11; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 6: case 38: case 134: case 166: PIXEL00_22; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 20: case 21: case 52: case 53: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_21; break; \ + case 144: case 145: case 176: case 177: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_12; break; \ + case 192: case 193: case 196: case 197: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_11; break; \ + case 96: case 97: case 100: case 101: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_22; break; \ + case 40: case 44: case 168: case 172: PIXEL00_21; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 9: case 13: case 137: case 141: PIXEL00_12; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 18: case 50: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 80: case 81: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_20; break; \ + case 72: case 76: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_20; PIXEL11_22; break; \ + case 10: case 138: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 66: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 24: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 7: case 39: case 135: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 148: case 149: case 180: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 224: case 228: case 225: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 41: case 169: case 45: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 22: case 54: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 208: case 209: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 104: case 108: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 11: case 139: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 19: case 51: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_10; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 146: case 178: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 84: case 85: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_10; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 112: case 113: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_10; else PIXEL10_61, PIXEL11_90; break; \ + case 200: case 204: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 73: case 77: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_10; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 42: case 170: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 14: case 142: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 67: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 70: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 28: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 152: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 194: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 98: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 56: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 25: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 26: case 31: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 82: case 214: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 88: case 248: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 74: case 107: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 27: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_21; break; \ + case 86: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; PIXEL11_10; break; \ + case 216: PIXEL00_21; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 106: PIXEL00_10; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 30: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 210: PIXEL00_22; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 120: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 75: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_22; break; \ + case 29: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 198: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 184: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 99: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 57: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 71: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 156: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 226: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 60: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 195: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 102: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 153: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 58: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 83: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 92: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 202: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 78: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 154: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_22; PIXEL11_12; break; \ + case 114: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 89: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 90: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 55: case 23: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 182: case 150: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 213: case 212: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 241: case 240: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 236: case 232: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 109: case 105: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 171: case 43: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 143: case 15: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 124: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 203: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_11; break; \ + case 62: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 211: PIXEL00_11; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 118: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; PIXEL11_10; break; \ + case 217: PIXEL00_12; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 110: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 155: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_12; break; \ + case 188: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 185: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 61: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 157: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 103: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 227: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 230: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 199: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 220: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 158: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_12; break; \ + case 234: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_11; break; \ + case 242: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 59: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 121: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 87: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 79: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 122: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 94: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 218: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 91: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 229: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 167: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 173: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 181: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 186: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_12; break; \ + case 115: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 93: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 206: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 205: case 201: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 174: case 46: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 179: case 147: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_20; PIXEL11_12; break; \ + case 117: case 116: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 189: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 231: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 126: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 219: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 125: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_11; PIXEL11_10; break; \ + case 221: PIXEL00_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_10; break; \ + case 207: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_10; PIXEL11_11; break; \ + case 238: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 190: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_11; break; \ + case 187: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_10; PIXEL11_12; break; \ + case 243: PIXEL00_11; PIXEL01_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 119: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_12; PIXEL11_10; break; \ + case 237: case 233: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 175: case 47: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 183: case 151: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_20; PIXEL11_12; break; \ + case 245: case 244: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 250: PIXEL00_10; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 123: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 95: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; PIXEL11_10; break; \ + case 222: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 252: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 249: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 235: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 111: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 63: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 159: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_22; PIXEL11_12; break; \ + case 215: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 246: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 254: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 253: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 251: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 239: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 127: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 191: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_11; PIXEL11_12; break; \ + case 223: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 247: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 255: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; + + +void RenderHQ2XS(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int type) +{ + uint8 *srcPtr = src; + uint8 *dstPtr = dst; + uint32 srcPitch = srcpitch; + uint32 dstPitch = dstpitch; + int width = nWidth; + int height = nHeight; + + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + if (type == 0) // hq2xs + { + bool nosame = true; + if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5) + nosame = false; + + if(nosame) + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0); + if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1); + if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2); + if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3); + if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4); + if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5); + if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6); + if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7); + } + else + { + y = RGBtoYUV[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + } + } + else if (type == 1) // hq2xbold + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } + + switch (pattern) + { + HQ2XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 2; + } + + dp += ((dst1line - width) << 1); + sp += (src1line - width); + } +} + + +// HQ3xS + +#define PIXEL00_1M *(dp) = Interp01(w5, w1); +#define PIXEL00_1U *(dp) = Interp01(w5, w2); +#define PIXEL00_1L *(dp) = Interp01(w5, w4); +#define PIXEL00_2 *(dp) = Interp02(w5, w4, w2); +#define PIXEL00_4 *(dp) = Interp04(w5, w4, w2); +#define PIXEL00_5 *(dp) = Interp05(w4, w2); +#define PIXEL00_C *(dp) = w5; + +#define PIXEL01_1 *(dp + 1) = Interp01(w5, w2); +#define PIXEL01_3 *(dp + 1) = Interp03(w5, w2); +#define PIXEL01_6 *(dp + 1) = Interp01(w2, w5); +#define PIXEL01_C *(dp + 1) = w5; + +#define PIXEL02_1M *(dp + 2) = Interp01(w5, w3); +#define PIXEL02_1U *(dp + 2) = Interp01(w5, w2); +#define PIXEL02_1R *(dp + 2) = Interp01(w5, w6); +#define PIXEL02_2 *(dp + 2) = Interp02(w5, w2, w6); +#define PIXEL02_4 *(dp + 2) = Interp04(w5, w2, w6); +#define PIXEL02_5 *(dp + 2) = Interp05(w2, w6); +#define PIXEL02_C *(dp + 2) = w5; + +#define PIXEL10_1 *(dp + dst1line) = Interp01(w5, w4); +#define PIXEL10_3 *(dp + dst1line) = Interp03(w5, w4); +#define PIXEL10_6 *(dp + dst1line) = Interp01(w4, w5); +#define PIXEL10_C *(dp + dst1line) = w5; + +#define PIXEL11 *(dp + dst1line + 1) = w5; + +#define PIXEL12_1 *(dp + dst1line + 2) = Interp01(w5, w6); +#define PIXEL12_3 *(dp + dst1line + 2) = Interp03(w5, w6); +#define PIXEL12_6 *(dp + dst1line + 2) = Interp01(w6, w5); +#define PIXEL12_C *(dp + dst1line + 2) = w5; + +#define PIXEL20_1M *(dp + dst1line + dst1line) = Interp01(w5, w7); +#define PIXEL20_1D *(dp + dst1line + dst1line) = Interp01(w5, w8); +#define PIXEL20_1L *(dp + dst1line + dst1line) = Interp01(w5, w4); +#define PIXEL20_2 *(dp + dst1line + dst1line) = Interp02(w5, w8, w4); +#define PIXEL20_4 *(dp + dst1line + dst1line) = Interp04(w5, w8, w4); +#define PIXEL20_5 *(dp + dst1line + dst1line) = Interp05(w8, w4); +#define PIXEL20_C *(dp + dst1line + dst1line) = w5; + +#define PIXEL21_1 *(dp + dst1line + dst1line + 1) = Interp01(w5, w8); +#define PIXEL21_3 *(dp + dst1line + dst1line + 1) = Interp03(w5, w8); +#define PIXEL21_6 *(dp + dst1line + dst1line + 1) = Interp01(w8, w5); +#define PIXEL21_C *(dp + dst1line + dst1line + 1) = w5; + +#define PIXEL22_1M *(dp + dst1line + dst1line + 2) = Interp01(w5, w9); +#define PIXEL22_1D *(dp + dst1line + dst1line + 2) = Interp01(w5, w8); +#define PIXEL22_1R *(dp + dst1line + dst1line + 2) = Interp01(w5, w6); +#define PIXEL22_2 *(dp + dst1line + dst1line + 2) = Interp02(w5, w6, w8); +#define PIXEL22_4 *(dp + dst1line + dst1line + 2) = Interp04(w5, w6, w8); +#define PIXEL22_5 *(dp + dst1line + dst1line + 2) = Interp05(w6, w8); +#define PIXEL22_C *(dp + dst1line + dst1line + 2) = w5; + +#define Interp03(c1, c2) \ + (((c1 == c2) ? c1 : \ + ((((((c1) & Mask_2) * 7 + ((c2) & Mask_2)) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 7 + ((c2) & Mask13)) >> 3) & Mask13)))) + +#define Interp04(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 7 + ((c3) & Mask_2) * 7) >> 4) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) * 7 + ((c3) & Mask13) * 7) >> 4) & Mask13)) + +#define HQ3XCASES \ + case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 2: case 34: case 130: case 162: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 16: case 17: case 48: case 49: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 64: case 65: case 68: case 69: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 8: case 12: case 136: case 140: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 3: case 35: case 131: case 163: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 6: case 38: case 134: case 166: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 20: case 21: case 52: case 53: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 144: case 145: case 176: case 177: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 192: case 193: case 196: case 197: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 96: case 97: case 100: case 101: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 40: case 44: case 168: case 172: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 9: case 13: case 137: case 141: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 18: case 50: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 80: case 81: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 72: case 76: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 10: case 138: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 66: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 24: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 7: case 39: case 135: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 148: case 149: case 180: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 224: case 228: case 225: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 41: case 169: case 45: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 22: case 54: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 208: case 209: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 104: case 108: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 11: case 139: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 19: case 51: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 146: case 178: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\ + case 84: case 85: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\ + case 112: case 113: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_1M } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 200: case 204: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\ + case 73: case 77: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\ + case 42: case 170: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\ + case 14: case 142: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 67: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 70: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 28: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 152: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 194: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 98: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 56: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 25: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 26: case 31: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 82: case 214: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 88: case 248: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 74: case 107: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 27: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 86: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 216: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 106: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 30: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 210: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 120: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 75: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 29: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 198: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 184: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 99: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 57: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 71: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 156: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 226: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 60: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 195: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 102: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 153: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 58: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 83: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 92: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 202: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 78: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\ + case 154: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 114: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 89: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 90: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 55: case 23: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 182: case 150: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\ + case 213: case 212: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\ + case 241: case 240: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 236: case 232: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\ + case 109: case 105: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\ + case 171: case 43: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\ + case 143: case 15: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 124: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 203: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 62: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 211: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 118: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 217: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 110: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 155: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 188: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 185: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 61: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 157: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 103: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 227: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 230: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 199: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 220: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 158: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 234: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1R break; }\ + case 242: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL20_1L if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 59: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 121: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 87: { PIXEL00_1L if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 79: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\ + case 122: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 94: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 218: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 91: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 229: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 167: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 173: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 181: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 186: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 115: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 93: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 206: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 205: case 201: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 174: case 46: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 179: case 147: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 117: case 116: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 189: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 231: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 126: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 219: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 125: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C PIXEL22_1M break; }\ + case 221: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_1U PIXEL01_1 PIXEL10_C PIXEL11 PIXEL20_1M break; }\ + case 207: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 238: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 break; }\ + case 190: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 break; }\ + case 187: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL21_1 PIXEL22_1D break; }\ + case 243: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 119: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 237: case 233: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 175: case 47: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 183: case 151: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 245: case 244: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 250: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 123: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 95: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 222: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 252: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 249: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 235: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 111: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 63: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 159: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 215: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 246: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 254: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_2 } break; }\ + case 253: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 251: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_2 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 239: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 127: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_2 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 191: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 223: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_2 PIXEL12_3 } PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 247: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 255: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; } + + +void RenderHQ3XS(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int type) +{ + uint8 *srcPtr = src; + uint8 *dstPtr = dst; + uint32 srcPitch = srcpitch; + uint32 dstPitch = dstpitch; + int width = nWidth; + int height = nHeight; + + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + if (type == 0) // hq3xs + { + bool nosame = true; + if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5) + nosame = false; + + if(nosame) + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0); + if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1); + if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2); + if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3); + if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4); + if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5); + if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6); + if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7); + } + else + { + y = RGBtoYUV[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + } + } + else if (type == 1) // hq3xbold + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } + + switch (pattern) + { + HQ3XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 3; + } + + dp += ((dst1line - width) * 3); + sp += (src1line - width); + } +} diff --git a/src/interface/scalers/hq3x32.asm b/src/interface/scalers/hq3x32.asm new file mode 100644 index 00000000..e45deddd --- /dev/null +++ b/src/interface/scalers/hq3x32.asm @@ -0,0 +1,2475 @@ +;hq3x filter +;---------------------------------------------------------- +;Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +GLOBAL _hq3x_32 + +EXTERN _LUT16to32 +EXTERN _RGBtoYUV + +SECTION .bss +firstline resd 1 +linesleft resd 1 +xcounter resd 1 +cross resd 1 +nextline resd 1 +prevline resd 1 +w1 resd 1 +w2 resd 1 +w3 resd 1 +w4 resd 1 +w5 resd 1 +w6 resd 1 +w7 resd 1 +w8 resd 1 +w9 resd 1 +c1 resd 1 +c2 resd 1 +c3 resd 1 +c4 resd 1 +c5 resd 1 +c6 resd 1 +c7 resd 1 +c8 resd 1 +c9 resd 1 + +SECTION .data + +reg_blank dd 0,0 +const7 dd 0x00070007,0x00000007 +threshold dd 0x00300706,0x00000000 + +SECTION .text + +%macro TestDiff 2 + xor ecx,ecx + mov edx,[%1] + cmp edx,[%2] + je %%fin + mov ecx,_RGBtoYUV + movd mm1,[ecx+edx*4] + movq mm5,mm1 + mov edx,[%2] + movd mm2,[ecx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd ecx,mm1 +%%fin: +%endmacro + +%macro DiffOrNot 4 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + jmp %%fin +%%same: + %4 +%%fin +%endmacro + +%macro DiffOrNot 6 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + jmp %%fin +%%same: + %5 + %6 +%%fin +%endmacro + +%macro DiffOrNot 8 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + %5 + jmp %%fin +%%same: + %6 + %7 + %8 +%%fin +%endmacro + +%macro DiffOrNot 10 + TestDiff %1,%2 + test ecx,ecx + jz %%same + %3 + %4 + %5 + %6 + jmp %%fin +%%same: + %7 + %8 + %9 + %10 +%%fin +%endmacro + +%macro Interp1 3 + mov edx,%2 + shl edx,2 + add edx,%3 + sub edx,%2 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp2 4 + mov edx,%2 + shl edx,1 + add edx,%3 + add edx,%4 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp3 2 + movd mm1, eax + movd mm2, %2 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + pmullw mm1, [const7] + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp4 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + psllw mm1, 1 + paddw mm2, mm3 + pmullw mm2, [const7] + paddw mm1, mm2 + psrlw mm1, 4 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp5 3 + mov edx,%2 + add edx,%3 + shr edx,1 + mov %1,edx +%endmacro + +%macro PIXEL00_1M 0 + Interp1 [edi],eax,[c1] +%endmacro + +%macro PIXEL00_1U 0 + Interp1 [edi],eax,[c2] +%endmacro + +%macro PIXEL00_1L 0 + Interp1 [edi],eax,[c4] +%endmacro + +%macro PIXEL00_2 0 + Interp2 [edi],eax,[c4],[c2] +%endmacro + +%macro PIXEL00_4 0 + Interp4 [edi],[c4],[c2] +%endmacro + +%macro PIXEL00_5 0 + Interp5 [edi],[c4],[c2] +%endmacro + +%macro PIXEL00_C 0 + mov [edi],eax +%endmacro + +%macro PIXEL01_1 0 + Interp1 [edi+4],eax,[c2] +%endmacro + +%macro PIXEL01_3 0 + Interp3 [edi+4],[c2] +%endmacro + +%macro PIXEL01_6 0 + Interp1 [edi+4],[c2],eax +%endmacro + +%macro PIXEL01_C 0 + mov [edi+4],eax +%endmacro + +%macro PIXEL02_1M 0 + Interp1 [edi+8],eax,[c3] +%endmacro + +%macro PIXEL02_1U 0 + Interp1 [edi+8],eax,[c2] +%endmacro + +%macro PIXEL02_1R 0 + Interp1 [edi+8],eax,[c6] +%endmacro + +%macro PIXEL02_2 0 + Interp2 [edi+8],eax,[c2],[c6] +%endmacro + +%macro PIXEL02_4 0 + Interp4 [edi+8],[c2],[c6] +%endmacro + +%macro PIXEL02_5 0 + Interp5 [edi+8],[c2],[c6] +%endmacro + +%macro PIXEL02_C 0 + mov [edi+8],eax +%endmacro + +%macro PIXEL10_1 0 + Interp1 [edi+ebx],eax,[c4] +%endmacro + +%macro PIXEL10_3 0 + Interp3 [edi+ebx],[c4] +%endmacro + +%macro PIXEL10_6 0 + Interp1 [edi+ebx],[c4],eax +%endmacro + +%macro PIXEL10_C 0 + mov [edi+ebx],eax +%endmacro + +%macro PIXEL11 0 + mov [edi+ebx+4],eax +%endmacro + +%macro PIXEL12_1 0 + Interp1 [edi+ebx+8],eax,[c6] +%endmacro + +%macro PIXEL12_3 0 + Interp3 [edi+ebx+8],[c6] +%endmacro + +%macro PIXEL12_6 0 + Interp1 [edi+ebx+8],[c6],eax +%endmacro + +%macro PIXEL12_C 0 + mov [edi+ebx+8],eax +%endmacro + +%macro PIXEL20_1M 0 + Interp1 [edi+ebx*2],eax,[c7] +%endmacro + +%macro PIXEL20_1D 0 + Interp1 [edi+ebx*2],eax,[c8] +%endmacro + +%macro PIXEL20_1L 0 + Interp1 [edi+ebx*2],eax,[c4] +%endmacro + +%macro PIXEL20_2 0 + Interp2 [edi+ebx*2],eax,[c8],[c4] +%endmacro + +%macro PIXEL20_4 0 + Interp4 [edi+ebx*2],[c8],[c4] +%endmacro + +%macro PIXEL20_5 0 + Interp5 [edi+ebx*2],[c8],[c4] +%endmacro + +%macro PIXEL20_C 0 + mov [edi+ebx*2],eax +%endmacro + +%macro PIXEL21_1 0 + Interp1 [edi+ebx*2+4],eax,[c8] +%endmacro + +%macro PIXEL21_3 0 + Interp3 [edi+ebx*2+4],[c8] +%endmacro + +%macro PIXEL21_6 0 + Interp1 [edi+ebx*2+4],[c8],eax +%endmacro + +%macro PIXEL21_C 0 + mov [edi+ebx*2+4],eax +%endmacro + +%macro PIXEL22_1M 0 + Interp1 [edi+ebx*2+8],eax,[c9] +%endmacro + +%macro PIXEL22_1D 0 + Interp1 [edi+ebx*2+8],eax,[c8] +%endmacro + +%macro PIXEL22_1R 0 + Interp1 [edi+ebx*2+8],eax,[c6] +%endmacro + +%macro PIXEL22_2 0 + Interp2 [edi+ebx*2+8],eax,[c6],[c8] +%endmacro + +%macro PIXEL22_4 0 + Interp4 [edi+ebx*2+8],[c6],[c8] +%endmacro + +%macro PIXEL22_5 0 + Interp5 [edi+ebx*2+8],[c6],[c8] +%endmacro + +%macro PIXEL22_C 0 + mov [edi+ebx*2+8],eax +%endmacro + +inbuffer equ 8 +outbuffer equ 12 +Xres equ 16 +Yres equ 20 +pitch equ 24 + +_hq3x_32: + push ebp + mov ebp,esp + pushad + + mov esi,[ebp+inbuffer] + mov edi,[ebp+outbuffer] + mov edx,[ebp+Yres] + mov [linesleft],edx + mov dword[firstline],1 +.loopy + push edi + mov ebx,[ebp+Xres] + shl ebx,1 + movzx eax,word[esi] + mov [w5],eax + mov [w6],eax + mov edx,eax + xor ecx,ecx + cmp dword[firstline],1 + je .firstline + sub ecx,ebx + movzx eax,word[esi+ecx] +.firstline + mov [prevline],ecx + mov [w2],eax + mov [w3],eax + xor ecx,ecx + cmp dword[linesleft],1 + je .lastline + add ecx,ebx + movzx edx,word[esi+ecx] +.lastline + mov [nextline],ecx + mov [w8],edx + mov [w9],edx + mov ecx,[ebp+Xres] + mov dword[xcounter],ecx +.loopx + mov eax,[w2] + mov ebx,[w5] + mov edx,[w8] + mov [w1],eax + mov [w4],ebx + mov [w7],edx + mov eax,[w3] + mov ebx,[w6] + mov edx,[w9] + mov [w2],eax + mov [w5],ebx + mov [w8],edx + cmp dword[xcounter],1 + je .flags + movzx eax,word[esi+2] + mov [w6],eax + mov ebx,[prevline] + movzx edx,word[esi+ebx+2] + mov [w3],edx + mov ebx,[nextline] + movzx eax,word[esi+ebx+2] + mov [w9],eax +.flags + mov ebx,_RGBtoYUV + mov eax,[w5] + xor ecx,ecx + movd mm5,[ebx+eax*4] + mov dword[cross],0 + + mov edx,[w2] + cmp eax,edx + je .noflag2 + or dword[cross],1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag2 + or ecx,2 +.noflag2 + mov edx,[w4] + cmp eax,edx + je .noflag4 + or dword[cross],2 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag4 + or ecx,8 +.noflag4 + mov edx,[w6] + cmp eax,edx + je .noflag6 + or dword[cross],4 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag6 + or ecx,16 +.noflag6 + mov edx,[w8] + cmp eax,edx + je .noflag8 + or dword[cross],8 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag8 + or ecx,64 +.noflag8 + test ecx,ecx + jnz .testflag1 + mov ecx,[cross] + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + jmp [FuncTable2+ecx*4] +.testflag1 + mov edx,[w1] + cmp eax,edx + je .noflag1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag1 + or ecx,1 +.noflag1 + mov edx,[w3] + cmp eax,edx + je .noflag3 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag3 + or ecx,4 +.noflag3 + mov edx,[w7] + cmp eax,edx + je .noflag7 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag7 + or ecx,32 +.noflag7 + mov edx,[w9] + cmp eax,edx + je .noflag9 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag9 + or ecx,128 +.noflag9 + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + mov edx,[w2] + mov edx,[ebx+edx*4] + mov [c2],edx + mov edx,[w4] + mov edx,[ebx+edx*4] + mov [c4],edx + mov edx,[w6] + mov edx,[ebx+edx*4] + mov [c6],edx + mov edx,[w8] + mov edx,[ebx+edx*4] + mov [c8],edx + test ecx,0x005A + jz .switch + mov edx,[w1] + mov edx,[ebx+edx*4] + mov [c1],edx + mov edx,[w3] + mov edx,[ebx+edx*4] + mov [c3],edx + mov edx,[w7] + mov edx,[ebx+edx*4] + mov [c7],edx + mov edx,[w9] + mov edx,[ebx+edx*4] + mov [c9],edx +.switch + mov ebx,[ebp+pitch] + jmp [FuncTable+ecx*4] + +..@flag0 +..@flag1 +..@flag4 +..@flag32 +..@flag128 +..@flag5 +..@flag132 +..@flag160 +..@flag33 +..@flag129 +..@flag36 +..@flag133 +..@flag164 +..@flag161 +..@flag37 +..@flag165 +; PIXEL00_2 +; PIXEL01_1 +; PIXEL02_2 +; PIXEL10_1 +; PIXEL11 +; PIXEL12_1 +; PIXEL20_2 +; PIXEL21_1 +; PIXEL22_2 + +; the same, only optimized + mov ecx,eax + shl ecx,1 + add ecx,[c2] + mov edx,ecx + add edx,[c4] + shr edx,2 + mov [edi],edx + mov edx,ecx + add edx,eax + shr edx,2 + mov [edi+4],edx + add ecx,[c6] + shr ecx,2 + mov [edi+8],ecx + mov ecx,eax + shl ecx,2 + sub ecx,eax + mov edx,ecx + add edx,[c4] + shr edx,2 + mov [edi+ebx],edx + mov [edi+ebx+4],eax + add ecx,[c6] + shr ecx,2 + mov [edi+ebx+8],ecx + mov ecx,eax + shl ecx,1 + add ecx,[c8] + mov edx,ecx + add edx,[c4] + shr edx,2 + mov [edi+ebx*2],edx + mov edx,ecx + add edx,eax + shr edx,2 + mov [edi+ebx*2+4],edx + add ecx,[c6] + shr ecx,2 + mov [edi+ebx*2+8],ecx + jmp .loopx_end +..@flag2 +..@flag34 +..@flag130 +..@flag162 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag16 +..@flag17 +..@flag48 +..@flag49 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag64 +..@flag65 +..@flag68 +..@flag69 + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag8 +..@flag12 +..@flag136 +..@flag140 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag3 +..@flag35 +..@flag131 +..@flag163 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag6 +..@flag38 +..@flag134 +..@flag166 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag20 +..@flag21 +..@flag52 +..@flag53 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag144 +..@flag145 +..@flag176 +..@flag177 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag192 +..@flag193 +..@flag196 +..@flag197 + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag96 +..@flag97 +..@flag100 +..@flag101 + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag40 +..@flag44 +..@flag168 +..@flag172 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag9 +..@flag13 +..@flag137 +..@flag141 + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag18 +..@flag50 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_1M,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag80 +..@flag81 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_1M,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag72 +..@flag76 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_1M,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag10 +..@flag138 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag66 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag24 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag7 +..@flag39 +..@flag135 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag148 +..@flag149 +..@flag180 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag224 +..@flag228 +..@flag225 + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag41 +..@flag169 +..@flag45 + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag22 +..@flag54 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag208 +..@flag209 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag104 +..@flag108 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag11 +..@flag139 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag19 +..@flag51 + DiffOrNot w2,w6,PIXEL00_1L,PIXEL01_C,PIXEL02_1M,PIXEL12_C,PIXEL00_2,PIXEL01_6,PIXEL02_5,PIXEL12_1 + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag146 +..@flag178 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_1M,PIXEL12_C,PIXEL22_1D,PIXEL01_1,PIXEL02_5,PIXEL12_6,PIXEL22_2 + PIXEL00_1M + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + jmp .loopx_end +..@flag84 +..@flag85 + DiffOrNot w6,w8,PIXEL02_1U,PIXEL12_C,PIXEL21_C,PIXEL22_1M,PIXEL02_2,PIXEL12_6,PIXEL21_1,PIXEL22_5 + PIXEL00_2 + PIXEL01_1 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + jmp .loopx_end +..@flag112 +..@flag113 + DiffOrNot w6,w8,PIXEL12_C,PIXEL20_1L,PIXEL21_C,PIXEL22_1M,PIXEL12_1,PIXEL20_2,PIXEL21_6,PIXEL22_5 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + jmp .loopx_end +..@flag200 +..@flag204 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_1M,PIXEL21_C,PIXEL22_1R,PIXEL10_1,PIXEL20_5,PIXEL21_6,PIXEL22_2 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + jmp .loopx_end +..@flag73 +..@flag77 + DiffOrNot w8,w4,PIXEL00_1U,PIXEL10_C,PIXEL20_1M,PIXEL21_C,PIXEL00_2,PIXEL10_6,PIXEL20_5,PIXEL21_1 + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + PIXEL22_1M + jmp .loopx_end +..@flag42 +..@flag170 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL01_C,PIXEL10_C,PIXEL20_1D,PIXEL00_5,PIXEL01_1,PIXEL10_6,PIXEL20_2 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag14 +..@flag142 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL01_C,PIXEL02_1R,PIXEL10_C,PIXEL00_5,PIXEL01_6,PIXEL02_2,PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag67 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag70 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag28 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag152 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag194 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag98 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag56 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag25 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag26 +..@flag31 + DiffOrNot w4,w2,PIXEL00_C,PIXEL10_C,PIXEL00_4,PIXEL10_3 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL12_C,PIXEL02_4,PIXEL12_3 + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag82 +..@flag214 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL01_3,PIXEL02_4 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + DiffOrNot w6,w8,PIXEL21_C,PIXEL22_C,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag88 +..@flag248 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL11 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL10_3,PIXEL20_4 + PIXEL21_C + DiffOrNot w6,w8,PIXEL12_C,PIXEL22_C,PIXEL12_3,PIXEL22_4 + jmp .loopx_end +..@flag74 +..@flag107 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL00_4,PIXEL01_3 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_C,PIXEL21_C,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag27 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag86 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag216 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag106 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag30 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_C + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag210 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag120 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag75 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag29 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag198 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag184 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag99 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag57 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag71 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag156 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag226 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag60 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag195 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag102 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag153 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag58 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag83 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag92 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag202 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag78 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag154 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag114 + PIXEL00_1M + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag89 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag90 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag55 +..@flag23 + DiffOrNot w2,w6,PIXEL00_1L,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL00_2,PIXEL01_6,PIXEL02_5,PIXEL12_1 + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag182 +..@flag150 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL22_1D,PIXEL01_1,PIXEL02_5,PIXEL12_6,PIXEL22_2 + PIXEL00_1M + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + jmp .loopx_end +..@flag213 +..@flag212 + DiffOrNot w6,w8,PIXEL02_1U,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL02_2,PIXEL12_6,PIXEL21_1,PIXEL22_5 + PIXEL00_2 + PIXEL01_1 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + jmp .loopx_end +..@flag241 +..@flag240 + DiffOrNot w6,w8,PIXEL12_C,PIXEL20_1L,PIXEL21_C,PIXEL22_C,PIXEL12_1,PIXEL20_2,PIXEL21_6,PIXEL22_5 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + jmp .loopx_end +..@flag236 +..@flag232 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL22_1R,PIXEL10_1,PIXEL20_5,PIXEL21_6,PIXEL22_2 + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + jmp .loopx_end +..@flag109 +..@flag105 + DiffOrNot w8,w4,PIXEL00_1U,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL00_2,PIXEL10_6,PIXEL20_5,PIXEL21_1 + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + PIXEL22_1M + jmp .loopx_end +..@flag171 +..@flag43 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL20_1D,PIXEL00_5,PIXEL01_1,PIXEL10_6,PIXEL20_2 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag143 +..@flag15 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL02_1R,PIXEL10_C,PIXEL00_5,PIXEL01_6,PIXEL02_2,PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag124 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag203 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag62 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag211 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag118 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_1 + PIXEL11 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag217 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag110 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag155 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag188 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag185 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag61 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag157 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag103 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag227 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag230 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag199 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag220 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag158 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_C + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag234 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + PIXEL02_1M + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1R + jmp .loopx_end +..@flag242 + PIXEL00_1M + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL20_1L + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag59 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag121 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag87 + PIXEL00_1L + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag79 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1R + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag122 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag94 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL10_C + PIXEL11 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag218 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_C + PIXEL11 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag91 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag229 + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag167 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag173 + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag181 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag186 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag115 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag93 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag206 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag205 +..@flag201 + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_1M,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag174 +..@flag46 + DiffOrNot w4,w2,PIXEL00_1M,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag179 +..@flag147 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_1M,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag117 +..@flag116 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_1M,PIXEL22_2 + jmp .loopx_end +..@flag189 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag231 + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag126 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_4,PIXEL12_3 + PIXEL11 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag219 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_4,PIXEL01_3,PIXEL10_3 + PIXEL02_1M + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag125 + DiffOrNot w8,w4,PIXEL00_1U,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL00_2,PIXEL10_6,PIXEL20_5,PIXEL21_1 + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + PIXEL22_1M + jmp .loopx_end +..@flag221 + DiffOrNot w6,w8,PIXEL02_1U,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL02_2,PIXEL12_6,PIXEL21_1,PIXEL22_5 + PIXEL00_1U + PIXEL01_1 + PIXEL10_C + PIXEL11 + PIXEL20_1M + jmp .loopx_end +..@flag207 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL02_1R,PIXEL10_C,PIXEL00_5,PIXEL01_6,PIXEL02_2,PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag238 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL22_1R,PIXEL10_1,PIXEL20_5,PIXEL21_6,PIXEL22_2 + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL11 + PIXEL12_1 + jmp .loopx_end +..@flag190 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL22_1D,PIXEL01_1,PIXEL02_5,PIXEL12_6,PIXEL22_2 + PIXEL00_1M + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + jmp .loopx_end +..@flag187 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL20_1D,PIXEL00_5,PIXEL01_1,PIXEL10_6,PIXEL20_2 + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag243 + DiffOrNot w6,w8,PIXEL12_C,PIXEL20_1L,PIXEL21_C,PIXEL22_C,PIXEL12_1,PIXEL20_2,PIXEL21_6,PIXEL22_5 + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + jmp .loopx_end +..@flag119 + DiffOrNot w2,w6,PIXEL00_1L,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL00_2,PIXEL01_6,PIXEL02_5,PIXEL12_1 + PIXEL10_1 + PIXEL11 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag237 +..@flag233 + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag175 +..@flag47 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + jmp .loopx_end +..@flag183 +..@flag151 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag245 +..@flag244 + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end +..@flag250 + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL11 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL10_3,PIXEL20_4 + PIXEL21_C + DiffOrNot w6,w8,PIXEL12_C,PIXEL22_C,PIXEL12_3,PIXEL22_4 + jmp .loopx_end +..@flag123 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL00_4,PIXEL01_3 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_C,PIXEL21_C,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag95 + DiffOrNot w4,w2,PIXEL00_C,PIXEL10_C,PIXEL00_4,PIXEL10_3 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL12_C,PIXEL02_4,PIXEL12_3 + PIXEL11 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + jmp .loopx_end +..@flag222 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL01_3,PIXEL02_4 + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + DiffOrNot w6,w8,PIXEL21_C,PIXEL22_C,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag252 + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL10_3,PIXEL20_4 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end +..@flag249 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL12_C,PIXEL22_C,PIXEL12_3,PIXEL22_4 + jmp .loopx_end +..@flag235 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL00_4,PIXEL01_3 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag111 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_C,PIXEL21_C,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag63 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL12_C,PIXEL02_4,PIXEL12_3 + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + jmp .loopx_end +..@flag159 + DiffOrNot w4,w2,PIXEL00_C,PIXEL10_C,PIXEL00_4,PIXEL10_3 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag215 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + DiffOrNot w6,w8,PIXEL21_C,PIXEL22_C,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag246 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL01_3,PIXEL02_4 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end +..@flag254 + PIXEL00_1M + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL01_3,PIXEL02_4 + PIXEL11 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL10_3,PIXEL20_4 + DiffOrNot w6,w8,PIXEL12_C,PIXEL21_C,PIXEL22_C,PIXEL12_3,PIXEL21_3,PIXEL22_2 + jmp .loopx_end +..@flag253 + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end +..@flag251 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL00_4,PIXEL01_3 + PIXEL02_1M + PIXEL11 + DiffOrNot w8,w4,PIXEL10_C,PIXEL20_C,PIXEL21_C,PIXEL10_3,PIXEL20_2,PIXEL21_3 + DiffOrNot w6,w8,PIXEL12_C,PIXEL22_C,PIXEL12_3,PIXEL22_4 + jmp .loopx_end +..@flag239 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + PIXEL22_1R + jmp .loopx_end +..@flag127 + DiffOrNot w4,w2,PIXEL00_C,PIXEL01_C,PIXEL10_C,PIXEL00_2,PIXEL01_3,PIXEL10_3 + DiffOrNot w2,w6,PIXEL02_C,PIXEL12_C,PIXEL02_4,PIXEL12_3 + PIXEL11 + DiffOrNot w8,w4,PIXEL20_C,PIXEL21_C,PIXEL20_4,PIXEL21_3 + PIXEL22_1M + jmp .loopx_end +..@flag191 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + jmp .loopx_end +..@flag223 + DiffOrNot w4,w2,PIXEL00_C,PIXEL10_C,PIXEL00_4,PIXEL10_3 + DiffOrNot w2,w6,PIXEL01_C,PIXEL02_C,PIXEL12_C,PIXEL01_3,PIXEL02_2,PIXEL12_3 + PIXEL11 + PIXEL20_1M + DiffOrNot w6,w8,PIXEL21_C,PIXEL22_C,PIXEL21_3,PIXEL22_4 + jmp .loopx_end +..@flag247 + PIXEL00_1L + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end +..@flag255 + DiffOrNot w4,w2,PIXEL00_C,PIXEL00_2 + PIXEL01_C + DiffOrNot w2,w6,PIXEL02_C,PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_C + DiffOrNot w8,w4,PIXEL20_C,PIXEL20_2 + PIXEL21_C + DiffOrNot w6,w8,PIXEL22_C,PIXEL22_2 + jmp .loopx_end + +..@cross0 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+8],eax + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx*2],eax + mov [edi+ebx*2+4],eax + mov [edi+ebx*2+8],eax + jmp .loopx_end +..@cross1 + mov ecx,[w2] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],edx + mov [edi+4],edx + mov [edi+8],edx + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx*2],eax + mov [edi+ebx*2+4],eax + mov [edi+ebx*2+8],eax + jmp .loopx_end +..@cross2 + mov ecx,[w4] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],edx + mov [edi+4],eax + mov [edi+8],eax + mov [edi+ebx],edx + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx*2],edx + mov [edi+ebx*2+4],eax + mov [edi+ebx*2+8],eax + jmp .loopx_end +..@cross4 + mov ecx,[w6] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+8],edx + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],edx + mov [edi+ebx*2],eax + mov [edi+ebx*2+4],eax + mov [edi+ebx*2+8],edx + jmp .loopx_end +..@cross8 + mov ecx,[w8] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+8],eax + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx*2],edx + mov [edi+ebx*2+4],edx + mov [edi+ebx*2+8],edx + jmp .loopx_end +..@crossN + mov edx,[w2] + mov ecx,[ebx+edx*4] + mov [c2],ecx + mov edx,[w4] + mov ecx,[ebx+edx*4] + mov [c4],ecx + mov edx,[w6] + mov ecx,[ebx+edx*4] + mov [c6],ecx + mov edx,[w8] + mov ecx,[ebx+edx*4] + mov [c8],ecx + mov ebx,[ebp+pitch] + jmp ..@flag0 + +.loopx_end + add esi,2 + add edi,12 + dec dword[xcounter] + jz .nexty + jmp .loopx +.nexty + mov dword[firstline],0 + + pop edi + add edi,ebx + add edi,ebx + add edi,ebx + + dec dword[linesleft] + jz .fin + jmp .loopy +.fin + emms + popad + mov esp,ebp + pop ebp + ret + +SECTION .data +FuncTable + dd ..@flag0, ..@flag1, ..@flag2, ..@flag3, ..@flag4, ..@flag5, ..@flag6, ..@flag7 + dd ..@flag8, ..@flag9, ..@flag10, ..@flag11, ..@flag12, ..@flag13, ..@flag14, ..@flag15 + dd ..@flag16, ..@flag17, ..@flag18, ..@flag19, ..@flag20, ..@flag21, ..@flag22, ..@flag23 + dd ..@flag24, ..@flag25, ..@flag26, ..@flag27, ..@flag28, ..@flag29, ..@flag30, ..@flag31 + dd ..@flag32, ..@flag33, ..@flag34, ..@flag35, ..@flag36, ..@flag37, ..@flag38, ..@flag39 + dd ..@flag40, ..@flag41, ..@flag42, ..@flag43, ..@flag44, ..@flag45, ..@flag46, ..@flag47 + dd ..@flag48, ..@flag49, ..@flag50, ..@flag51, ..@flag52, ..@flag53, ..@flag54, ..@flag55 + dd ..@flag56, ..@flag57, ..@flag58, ..@flag59, ..@flag60, ..@flag61, ..@flag62, ..@flag63 + dd ..@flag64, ..@flag65, ..@flag66, ..@flag67, ..@flag68, ..@flag69, ..@flag70, ..@flag71 + dd ..@flag72, ..@flag73, ..@flag74, ..@flag75, ..@flag76, ..@flag77, ..@flag78, ..@flag79 + dd ..@flag80, ..@flag81, ..@flag82, ..@flag83, ..@flag84, ..@flag85, ..@flag86, ..@flag87 + dd ..@flag88, ..@flag89, ..@flag90, ..@flag91, ..@flag92, ..@flag93, ..@flag94, ..@flag95 + dd ..@flag96, ..@flag97, ..@flag98, ..@flag99, ..@flag100, ..@flag101, ..@flag102, ..@flag103 + dd ..@flag104, ..@flag105, ..@flag106, ..@flag107, ..@flag108, ..@flag109, ..@flag110, ..@flag111 + dd ..@flag112, ..@flag113, ..@flag114, ..@flag115, ..@flag116, ..@flag117, ..@flag118, ..@flag119 + dd ..@flag120, ..@flag121, ..@flag122, ..@flag123, ..@flag124, ..@flag125, ..@flag126, ..@flag127 + dd ..@flag128, ..@flag129, ..@flag130, ..@flag131, ..@flag132, ..@flag133, ..@flag134, ..@flag135 + dd ..@flag136, ..@flag137, ..@flag138, ..@flag139, ..@flag140, ..@flag141, ..@flag142, ..@flag143 + dd ..@flag144, ..@flag145, ..@flag146, ..@flag147, ..@flag148, ..@flag149, ..@flag150, ..@flag151 + dd ..@flag152, ..@flag153, ..@flag154, ..@flag155, ..@flag156, ..@flag157, ..@flag158, ..@flag159 + dd ..@flag160, ..@flag161, ..@flag162, ..@flag163, ..@flag164, ..@flag165, ..@flag166, ..@flag167 + dd ..@flag168, ..@flag169, ..@flag170, ..@flag171, ..@flag172, ..@flag173, ..@flag174, ..@flag175 + dd ..@flag176, ..@flag177, ..@flag178, ..@flag179, ..@flag180, ..@flag181, ..@flag182, ..@flag183 + dd ..@flag184, ..@flag185, ..@flag186, ..@flag187, ..@flag188, ..@flag189, ..@flag190, ..@flag191 + dd ..@flag192, ..@flag193, ..@flag194, ..@flag195, ..@flag196, ..@flag197, ..@flag198, ..@flag199 + dd ..@flag200, ..@flag201, ..@flag202, ..@flag203, ..@flag204, ..@flag205, ..@flag206, ..@flag207 + dd ..@flag208, ..@flag209, ..@flag210, ..@flag211, ..@flag212, ..@flag213, ..@flag214, ..@flag215 + dd ..@flag216, ..@flag217, ..@flag218, ..@flag219, ..@flag220, ..@flag221, ..@flag222, ..@flag223 + dd ..@flag224, ..@flag225, ..@flag226, ..@flag227, ..@flag228, ..@flag229, ..@flag230, ..@flag231 + dd ..@flag232, ..@flag233, ..@flag234, ..@flag235, ..@flag236, ..@flag237, ..@flag238, ..@flag239 + dd ..@flag240, ..@flag241, ..@flag242, ..@flag243, ..@flag244, ..@flag245, ..@flag246, ..@flag247 + dd ..@flag248, ..@flag249, ..@flag250, ..@flag251, ..@flag252, ..@flag253, ..@flag254, ..@flag255 + +FuncTable2 + dd ..@cross0, ..@cross1, ..@cross2, ..@crossN, + dd ..@cross4, ..@crossN, ..@crossN, ..@crossN, + dd ..@cross8, ..@crossN, ..@crossN, ..@crossN, + dd ..@crossN, ..@crossN, ..@crossN, ..@crossN + diff --git a/src/interface/scalers/hq3xs.cpp b/src/interface/scalers/hq3xs.cpp new file mode 100644 index 00000000..8a8f0cd2 --- /dev/null +++ b/src/interface/scalers/hq3xs.cpp @@ -0,0 +1,266 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "hq_shared32.h" +#include "interp.h" + +#define SIZE_PIXEL 2 // 16bit = 2 bytes +#define PIXELTYPE unsigned short +#define Interp1 Interp1_16 +#define Interp2 Interp2_16 +#define Interp3 Interp3_16 +#define Interp4 Interp4_16 +#define Interp5 Interp5_16 + +void hq3xS(unsigned char * pIn, unsigned int srcPitch, + unsigned char *, + unsigned char * pOut, unsigned int dstPitch, + int Xres, int Yres) +{ + int i, j; + PIXELTYPE c[10]; + + // +----+----+----+ + // | | | | + // | c1 | c2 | c3 | + // +----+----+----+ + // | | | | + // | c4 | c5 | c6 | + // +----+----+----+ + // | | | | + // | c7 | c8 | c9 | + // +----+----+----+ + + for (j=0; j> 3; + r = (int)((c[j] & 0xF800)) >> 8; + } else { + b = (int)((c[j] & 0x1F)) << 3; + g = (int)((c[j] & 0x3E0)) >> 2; + r = (int)((c[j] & 0x7C00)) >> 7; + } + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + const int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + #define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[5]; + if(ABS(brightArray[1] - centerBright) > diffBright) + pattern |= 1 << 0; + if(ABS(brightArray[2] - centerBright) > diffBright) + pattern |= 1 << 1; + if(ABS(brightArray[3] - centerBright) > diffBright) + pattern |= 1 << 2; + if(ABS(brightArray[4] - centerBright) > diffBright) + pattern |= 1 << 3; + if(ABS(brightArray[6] - centerBright) > diffBright) + pattern |= 1 << 4; + if(ABS(brightArray[7] - centerBright) > diffBright) + pattern |= 1 << 5; + if(ABS(brightArray[8] - centerBright) > diffBright) + pattern |= 1 << 6; + if(ABS(brightArray[9] - centerBright) > diffBright) + pattern |= 1 << 7; + } + +#define Diff(x,y) false//(ABS((x) - (y)) > diffBright) +#undef cget +#define cget(x) brightArray[x] +#include "hq3xs.h" +#undef cget +#undef Diff + pIn+=SIZE_PIXEL; + pOut+=3<<1; + } + pIn+=srcPitch-(Xres<<1); + pOut+=dstPitch-(3*Xres<<1); + pOut+=dstPitch<<1; + // pIn+=SIZE_PIXEL; + // pOut+=3*SIZE_PIXEL; + //} + //pIn+=srcPitch-(4*Xres); + //pOut+=dstPitch-(3*Xres*SIZE_PIXEL); + //pOut+=2*dstPitch; + } +} + +#undef Interp1 +#undef Interp2 +#undef Interp3 +#undef Interp4 +#undef Interp5 +#undef SIZE_PIXEL +#undef PIXELTYPE +#define SIZE_PIXEL 4 // 32bit = 4 bytes +#define PIXELTYPE unsigned int + +void hq3xS32(unsigned char * pIn, unsigned int srcPitch, + unsigned char *, + unsigned char * pOut, unsigned int dstPitch, + int Xres, int Yres) +{ + int i, j; + unsigned int line; + PIXELTYPE c[10]; + + // +----+----+----+ + // | | | | + // | c1 | c2 | c3 | + // +----+----+----+ + // | | | | + // | c4 | c5 | c6 | + // +----+----+----+ + // | | | | + // | c7 | c8 | c9 | + // +----+----+----+ + + for (j=0; j0) && (j0) + { + c[1] = *((PIXELTYPE*)(pIn - line - SIZE_PIXEL)); + c[4] = *((PIXELTYPE*)(pIn - SIZE_PIXEL)); + c[7] = *((PIXELTYPE*)(pIn + line - SIZE_PIXEL)); + } + else + { + c[1] = c[2]; + c[4] = c[5]; + c[7] = c[8]; + } + + if (i> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + #define ABS(x) ((x) < 0 ? -(x) : (x)) + + const int centerBright = brightArray[5]; + if(ABS(brightArray[1] - centerBright) > diffBright) + pattern |= 1 << 0; + if(ABS(brightArray[2] - centerBright) > diffBright) + pattern |= 1 << 1; + if(ABS(brightArray[3] - centerBright) > diffBright) + pattern |= 1 << 2; + if(ABS(brightArray[4] - centerBright) > diffBright) + pattern |= 1 << 3; + if(ABS(brightArray[6] - centerBright) > diffBright) + pattern |= 1 << 4; + if(ABS(brightArray[7] - centerBright) > diffBright) + pattern |= 1 << 5; + if(ABS(brightArray[8] - centerBright) > diffBright) + pattern |= 1 << 6; + if(ABS(brightArray[9] - centerBright) > diffBright) + pattern |= 1 << 7; + } + +#define Diff(x,y) false//(ABS((x) - (y)) > diffBright) +#undef cget +#define cget(x) brightArray[x] +#include "hq3xs.h" +#undef cget +#undef Diff + pIn+=SIZE_PIXEL; + pOut+=3<<2; + } + pIn+=srcPitch-(Xres<<2); + pOut+=dstPitch-(3*Xres<<2); + pOut+=dstPitch<<1; + // pIn+=SIZE_PIXEL; + // pOut+=3*SIZE_PIXEL; + //} + //pIn+=srcPitch-(4*Xres); + //pOut+=dstPitch-(3*Xres*SIZE_PIXEL); + //pOut+=2*dstPitch; + } +} diff --git a/src/interface/scalers/hq3xs.h b/src/interface/scalers/hq3xs.h new file mode 100644 index 00000000..36191542 --- /dev/null +++ b/src/interface/scalers/hq3xs.h @@ -0,0 +1,3692 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#define PIXEL00_1M Interp1( pOut, c[5], c[1] ); +#define PIXEL00_1U Interp1( pOut, c[5], c[2] ); +#define PIXEL00_1L Interp1( pOut, c[5], c[4] ); +#define PIXEL00_2 Interp2( pOut, c[5], c[4], c[2] ); +#define PIXEL00_4 Interp4( pOut, c[5], c[4], c[2] ); +#define PIXEL00_5 Interp5( pOut, c[4], c[2] ); +#define PIXEL00_C *((PIXELTYPE*)(pOut)) = c[5]; + +#define PIXEL01_1 Interp1( pOut+SIZE_PIXEL, c[5], c[2] ); +#define PIXEL01_3 Interp3( pOut+SIZE_PIXEL, c[5], c[2] ); +#define PIXEL01_6 Interp1( pOut+SIZE_PIXEL, c[2], c[5] ); +#define PIXEL01_C *((PIXELTYPE*)(pOut+SIZE_PIXEL)) = c[5]; + +#define PIXEL02_1M Interp1( pOut+SIZE_PIXEL+SIZE_PIXEL, c[5], c[3] ); +#define PIXEL02_1U Interp1( pOut+SIZE_PIXEL+SIZE_PIXEL, c[5], c[2] ); +#define PIXEL02_1R Interp1( pOut+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6] ); +#define PIXEL02_2 Interp2( pOut+SIZE_PIXEL+SIZE_PIXEL, c[5], c[2], c[6] ); +#define PIXEL02_4 Interp4( pOut+SIZE_PIXEL+SIZE_PIXEL, c[5], c[2], c[6] ); +#define PIXEL02_5 Interp5( pOut+SIZE_PIXEL+SIZE_PIXEL, c[2], c[6] ); +#define PIXEL02_C *((PIXELTYPE*)(pOut+SIZE_PIXEL+SIZE_PIXEL)) = c[5]; + +#define PIXEL10_1 Interp1( pOut+dstPitch, c[5], c[4] ); +#define PIXEL10_3 Interp3( pOut+dstPitch, c[5], c[4] ); +#define PIXEL10_6 Interp1( pOut+dstPitch, c[4], c[5] ); +#define PIXEL10_C *((PIXELTYPE*)(pOut+dstPitch)) = c[5]; + +#define PIXEL11 *((PIXELTYPE*)(pOut+dstPitch+SIZE_PIXEL)) = c[5]; + +#define PIXEL12_1 Interp1( pOut+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6] ); +#define PIXEL12_3 Interp3( pOut+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6] ); +#define PIXEL12_6 Interp1( pOut+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[6], c[5] ); +#define PIXEL12_C *((PIXELTYPE*)(pOut+dstPitch+SIZE_PIXEL+SIZE_PIXEL)) = c[5]; + +#define PIXEL20_1M Interp1( pOut+dstPitch+dstPitch, c[5], c[7] ); +#define PIXEL20_1D Interp1( pOut+dstPitch+dstPitch, c[5], c[8] ); +#define PIXEL20_1L Interp1( pOut+dstPitch+dstPitch, c[5], c[4] ); +#define PIXEL20_2 Interp2( pOut+dstPitch+dstPitch, c[5], c[8], c[4] ); +#define PIXEL20_4 Interp4( pOut+dstPitch+dstPitch, c[5], c[8], c[4] ); +#define PIXEL20_5 Interp5( pOut+dstPitch+dstPitch, c[8], c[4] ); +#define PIXEL20_C *((PIXELTYPE*)(pOut+dstPitch+dstPitch)) = c[5]; + +#define PIXEL21_1 Interp1( pOut+dstPitch+dstPitch+SIZE_PIXEL, c[5], c[8] ); +#define PIXEL21_3 Interp3( pOut+dstPitch+dstPitch+SIZE_PIXEL, c[5], c[8] ); +#define PIXEL21_6 Interp1( pOut+dstPitch+dstPitch+SIZE_PIXEL, c[8], c[5] ); +#define PIXEL21_C *((PIXELTYPE*)(pOut+dstPitch+dstPitch+SIZE_PIXEL)) = c[5]; + +#define PIXEL22_1M Interp1( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[9] ); +#define PIXEL22_1D Interp1( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[8] ); +#define PIXEL22_1R Interp1( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6] ); +#define PIXEL22_2 Interp2( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6], c[8] ); +#define PIXEL22_4 Interp4( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[5], c[6], c[8] ); +#define PIXEL22_5 Interp5( pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL, c[6], c[8] ); +#define PIXEL22_C *((PIXELTYPE*)(pOut+dstPitch+dstPitch+SIZE_PIXEL+SIZE_PIXEL)) = c[5]; + +#ifndef cget +#define cget(x) c[x] +#endif + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 2: + case 34: + case 130: + case 162: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 16: + case 17: + case 48: + case 49: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 64: + case 65: + case 68: + case 69: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 8: + case 12: + case 136: + case 140: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 3: + case 35: + case 131: + case 163: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 6: + case 38: + case 134: + case 166: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 20: + case 21: + case 52: + case 53: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 144: + case 145: + case 176: + case 177: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + break; + } + case 192: + case 193: + case 196: + case 197: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 96: + case 97: + case 100: + case 101: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 40: + case 44: + case 168: + case 172: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + break; + } + case 9: + case 13: + case 137: + case 141: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 18: + case 50: + { + PIXEL00_1M + + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_1M + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 80: + case 81: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_1M + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 72: + case 76: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_1M + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 10: + case 138: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 66: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 24: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 7: + case 39: + case 135: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 148: + case 149: + case 180: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + break; + } + case 224: + case 228: + case 225: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 41: + case 169: + case 45: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + break; + } + case 22: + case 54: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 208: + case 209: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 104: + case 108: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 11: + case 139: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 19: + case 51: + { + if (Diff(cget(2), cget(6))) + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL12_C + } + else + { + PIXEL00_2 + PIXEL01_6 + PIXEL02_5 + PIXEL12_1 + } + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 146: + case 178: + { + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_1M + PIXEL12_C + PIXEL22_1D + } + else + { + PIXEL01_1 + PIXEL02_5 + PIXEL12_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + break; + } + case 84: + case 85: + { + if (Diff(cget(6), cget(8))) + { + PIXEL02_1U + PIXEL12_C + PIXEL21_C + PIXEL22_1M + } + else + { + PIXEL02_2 + PIXEL12_6 + PIXEL21_1 + PIXEL22_5 + } + PIXEL00_2 + PIXEL01_1 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + break; + } + case 112: + case 113: + { + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + } + else + { + PIXEL12_1 + PIXEL20_2 + PIXEL21_6 + PIXEL22_5 + } + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + break; + } + case 200: + case 204: + { + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + } + else + { + PIXEL10_1 + PIXEL20_5 + PIXEL21_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + break; + } + case 73: + case 77: + { + if (Diff(cget(8), cget(4))) + { + PIXEL00_1U + PIXEL10_C + PIXEL20_1M + PIXEL21_C + } + else + { + PIXEL00_2 + PIXEL10_6 + PIXEL20_5 + PIXEL21_1 + } + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + PIXEL22_1M + break; + } + case 42: + case 170: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + PIXEL01_C + PIXEL10_C + PIXEL20_1D + } + else + { + PIXEL00_5 + PIXEL01_1 + PIXEL10_6 + PIXEL20_2 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL21_1 + PIXEL22_2 + break; + } + case 14: + case 142: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_C + } + else + { + PIXEL00_5 + PIXEL01_6 + PIXEL02_2 + PIXEL10_1 + } + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 67: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 70: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 28: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 152: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 194: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 98: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 56: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 25: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 26: + case 31: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL10_3 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL02_4 + PIXEL12_3 + } + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 82: + case 214: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + } + else + { + PIXEL01_3 + PIXEL02_4 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 88: + case 248: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + } + else + { + PIXEL10_3 + PIXEL20_4 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL22_4 + } + break; + } + case 74: + case 107: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + } + else + { + PIXEL00_4 + PIXEL01_3 + } + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 27: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 86: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_1 + PIXEL11 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 216: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 106: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 30: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_C + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 210: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 120: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 75: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 29: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1M + break; + } + case 198: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 184: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 99: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 57: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 71: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 156: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 226: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 60: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 195: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 102: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 153: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 58: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 83: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 92: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 202: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 78: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1M + break; + } + case 154: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 114: + { + PIXEL00_1M + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 89: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 90: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 55: + case 23: + { + if (Diff(cget(2), cget(6))) + { + PIXEL00_1L + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL00_2 + PIXEL01_6 + PIXEL02_5 + PIXEL12_1 + } + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + PIXEL22_1M + break; + } + case 182: + case 150: + { + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + PIXEL22_1D + } + else + { + PIXEL01_1 + PIXEL02_5 + PIXEL12_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL10_1 + PIXEL11 + PIXEL20_2 + PIXEL21_1 + break; + } + case 213: + case 212: + { + if (Diff(cget(6), cget(8))) + { + PIXEL02_1U + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL02_2 + PIXEL12_6 + PIXEL21_1 + PIXEL22_5 + } + PIXEL00_2 + PIXEL01_1 + PIXEL10_1 + PIXEL11 + PIXEL20_1M + break; + } + case 241: + case 240: + { + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL20_1L + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_1 + PIXEL20_2 + PIXEL21_6 + PIXEL22_5 + } + PIXEL00_2 + PIXEL01_1 + PIXEL02_1M + PIXEL10_1 + PIXEL11 + break; + } + case 236: + case 232: + { + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + PIXEL22_1R + } + else + { + PIXEL10_1 + PIXEL20_5 + PIXEL21_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + break; + } + case 109: + case 105: + { + if (Diff(cget(8), cget(4))) + { + PIXEL00_1U + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL00_2 + PIXEL10_6 + PIXEL20_5 + PIXEL21_1 + } + PIXEL01_1 + PIXEL02_2 + PIXEL11 + PIXEL12_1 + PIXEL22_1M + break; + } + case 171: + case 43: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + PIXEL20_1D + } + else + { + PIXEL00_5 + PIXEL01_1 + PIXEL10_6 + PIXEL20_2 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL21_1 + PIXEL22_2 + break; + } + case 143: + case 15: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL02_1R + PIXEL10_C + } + else + { + PIXEL00_5 + PIXEL01_6 + PIXEL02_2 + PIXEL10_1 + } + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_1 + PIXEL22_2 + break; + } + case 124: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 203: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 62: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 211: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 118: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_1 + PIXEL11 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 217: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 110: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 155: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 188: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 185: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 61: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 157: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 103: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 227: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 230: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 199: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 220: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 158: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_C + PIXEL11 + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 234: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1M + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1R + break; + } + case 242: + { + PIXEL00_1M + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL20_1L + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 59: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 121: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 87: + { + PIXEL00_1L + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_1 + PIXEL11 + PIXEL20_1M + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 79: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1R + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1M + break; + } + case 122: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 94: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_C + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 218: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 91: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 229: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_2 + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 167: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_2 + PIXEL21_1 + PIXEL22_2 + break; + } + case 173: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + break; + } + case 181: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + break; + } + case 186: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 115: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 93: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 206: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 205: + case 201: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_1M + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 174: + case 46: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_1M + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + break; + } + case 179: + case 147: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_1M + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + break; + } + case 117: + case 116: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_1M + } + else + { + PIXEL22_2 + } + break; + } + case 189: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 231: + { + PIXEL00_1L + PIXEL01_C + PIXEL02_1R + PIXEL10_1 + PIXEL11 + PIXEL12_1 + PIXEL20_1L + PIXEL21_C + PIXEL22_1R + break; + } + case 126: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_4 + PIXEL12_3 + } + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 219: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL01_3 + PIXEL10_3 + } + PIXEL02_1M + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 125: + { + if (Diff(cget(8), cget(4))) + { + PIXEL00_1U + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL00_2 + PIXEL10_6 + PIXEL20_5 + PIXEL21_1 + } + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + PIXEL22_1M + break; + } + case 221: + { + if (Diff(cget(6), cget(8))) + { + PIXEL02_1U + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL02_2 + PIXEL12_6 + PIXEL21_1 + PIXEL22_5 + } + PIXEL00_1U + PIXEL01_1 + PIXEL10_C + PIXEL11 + PIXEL20_1M + break; + } + case 207: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL02_1R + PIXEL10_C + } + else + { + PIXEL00_5 + PIXEL01_6 + PIXEL02_2 + PIXEL10_1 + } + PIXEL11 + PIXEL12_1 + PIXEL20_1M + PIXEL21_C + PIXEL22_1R + break; + } + case 238: + { + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + PIXEL22_1R + } + else + { + PIXEL10_1 + PIXEL20_5 + PIXEL21_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL01_C + PIXEL02_1R + PIXEL11 + PIXEL12_1 + break; + } + case 190: + { + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + PIXEL22_1D + } + else + { + PIXEL01_1 + PIXEL02_5 + PIXEL12_6 + PIXEL22_2 + } + PIXEL00_1M + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + break; + } + case 187: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + PIXEL20_1D + } + else + { + PIXEL00_5 + PIXEL01_1 + PIXEL10_6 + PIXEL20_2 + } + PIXEL02_1M + PIXEL11 + PIXEL12_C + PIXEL21_1 + PIXEL22_1D + break; + } + case 243: + { + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL20_1L + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_1 + PIXEL20_2 + PIXEL21_6 + PIXEL22_5 + } + PIXEL00_1L + PIXEL01_C + PIXEL02_1M + PIXEL10_1 + PIXEL11 + break; + } + case 119: + { + if (Diff(cget(2), cget(6))) + { + PIXEL00_1L + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL00_2 + PIXEL01_6 + PIXEL02_5 + PIXEL12_1 + } + PIXEL10_1 + PIXEL11 + PIXEL20_1L + PIXEL21_C + PIXEL22_1M + break; + } + case 237: + case 233: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_2 + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 175: + case 47: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + PIXEL20_1D + PIXEL21_1 + PIXEL22_2 + break; + } + case 183: + case 151: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_2 + PIXEL21_1 + PIXEL22_1D + break; + } + case 245: + case 244: + { + PIXEL00_2 + PIXEL01_1 + PIXEL02_1U + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + case 250: + { + PIXEL00_1M + PIXEL01_C + PIXEL02_1M + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + } + else + { + PIXEL10_3 + PIXEL20_4 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL22_4 + } + break; + } + case 123: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + } + else + { + PIXEL00_4 + PIXEL01_3 + } + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 95: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL10_3 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL02_4 + PIXEL12_3 + } + PIXEL11 + PIXEL20_1M + PIXEL21_C + PIXEL22_1M + break; + } + case 222: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + } + else + { + PIXEL01_3 + PIXEL02_4 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 252: + { + PIXEL00_1M + PIXEL01_1 + PIXEL02_1U + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + } + else + { + PIXEL10_3 + PIXEL20_4 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + case 249: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1M + PIXEL10_C + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL22_4 + } + break; + } + case 235: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + } + else + { + PIXEL00_4 + PIXEL01_3 + } + PIXEL02_1M + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 111: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 63: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL02_4 + PIXEL12_3 + } + PIXEL10_C + PIXEL11 + PIXEL20_1D + PIXEL21_1 + PIXEL22_1M + break; + } + case 159: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL10_3 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL11 + PIXEL12_C + PIXEL20_1M + PIXEL21_1 + PIXEL22_1D + break; + } + case 215: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 246: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + } + else + { + PIXEL01_3 + PIXEL02_4 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + case 254: + { + PIXEL00_1M + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + } + else + { + PIXEL01_3 + PIXEL02_4 + } + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + } + else + { + PIXEL10_3 + PIXEL20_4 + } + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL21_3 + PIXEL22_2 + } + break; + } + case 253: + { + PIXEL00_1U + PIXEL01_1 + PIXEL02_1U + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + case 251: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + } + else + { + PIXEL00_4 + PIXEL01_3 + } + PIXEL02_1M + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL10_C + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL10_3 + PIXEL20_2 + PIXEL21_3 + } + if (Diff(cget(6), cget(8))) + { + PIXEL12_C + PIXEL22_C + } + else + { + PIXEL12_3 + PIXEL22_4 + } + break; + } + case 239: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + PIXEL02_1R + PIXEL10_C + PIXEL11 + PIXEL12_1 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + PIXEL22_1R + break; + } + case 127: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL01_C + PIXEL10_C + } + else + { + PIXEL00_2 + PIXEL01_3 + PIXEL10_3 + } + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL02_4 + PIXEL12_3 + } + PIXEL11 + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + PIXEL21_C + } + else + { + PIXEL20_4 + PIXEL21_3 + } + PIXEL22_1M + break; + } + case 191: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + PIXEL20_1D + PIXEL21_1 + PIXEL22_1D + break; + } + case 223: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + PIXEL10_C + } + else + { + PIXEL00_4 + PIXEL10_3 + } + if (Diff(cget(2), cget(6))) + { + PIXEL01_C + PIXEL02_C + PIXEL12_C + } + else + { + PIXEL01_3 + PIXEL02_2 + PIXEL12_3 + } + PIXEL11 + PIXEL20_1M + if (Diff(cget(6), cget(8))) + { + PIXEL21_C + PIXEL22_C + } + else + { + PIXEL21_3 + PIXEL22_4 + } + break; + } + case 247: + { + PIXEL00_1L + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL10_1 + PIXEL11 + PIXEL12_C + PIXEL20_1L + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + case 255: + { + if (Diff(cget(4), cget(2))) + { + PIXEL00_C + } + else + { + PIXEL00_2 + } + PIXEL01_C + if (Diff(cget(2), cget(6))) + { + PIXEL02_C + } + else + { + PIXEL02_2 + } + PIXEL10_C + PIXEL11 + PIXEL12_C + if (Diff(cget(8), cget(4))) + { + PIXEL20_C + } + else + { + PIXEL20_2 + } + PIXEL21_C + if (Diff(cget(6), cget(8))) + { + PIXEL22_C + } + else + { + PIXEL22_2 + } + break; + } + } diff --git a/src/interface/scalers/hq4x32.asm b/src/interface/scalers/hq4x32.asm new file mode 100644 index 00000000..4987d10d --- /dev/null +++ b/src/interface/scalers/hq4x32.asm @@ -0,0 +1,4015 @@ +;hq4x filter +;---------------------------------------------------------- +;Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +GLOBAL _hq4x_32 + +EXTERN _LUT16to32 +EXTERN _RGBtoYUV + +SECTION .bss +linesleft resd 1 +xcounter resd 1 +cross resd 1 +nextline resd 1 +prevline resd 1 +w1 resd 1 +w2 resd 1 +w3 resd 1 +w4 resd 1 +w5 resd 1 +w6 resd 1 +w7 resd 1 +w8 resd 1 +w9 resd 1 +c1 resd 1 +c2 resd 1 +c3 resd 1 +c4 resd 1 +c5 resd 1 +c6 resd 1 +c7 resd 1 +c8 resd 1 +c9 resd 1 + +SECTION .data + +reg_blank dd 0,0 +const3 dd 0x00030003,0x00000003 +const5 dd 0x00050005,0x00000005 +const6 dd 0x00060006,0x00000006 +const7 dd 0x00070007,0x00000007 +threshold dd 0x00300706,0x00000000 + +SECTION .text + +%macro AUXADDRESS 0 + mov ecx, edi + add ecx, ebx + add ecx, ebx +%endmacro + +%macro TestDiff 2 + mov edx,[%1] + sub edx,[%2] + jz %%fin + mov edx,[%1] + shl edx,2 + add edx,_RGBtoYUV + movd mm1,[edx] + movq mm5,mm1 + mov edx,[%2] + shl edx,2 + add edx,_RGBtoYUV + movd mm2,[edx] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 +%%fin: +%endmacro + +%macro DiffOrNot 4 + TestDiff %1,%2 + test edx,edx + jz %%same + %3 + jmp %%fin +%%same: + %4 +%%fin +%endmacro + +%macro DiffOrNot 8 + TestDiff %1,%2 + test edx,edx + jz %%same + %3 + %4 + %5 + jmp %%fin +%%same: + %6 + %7 + %8 +%%fin +%endmacro + +%macro DiffOrNot 10 + TestDiff %1,%2 + test edx,edx + jz %%same + %3 + %4 + %5 + %6 + jmp %%fin +%%same: + %7 + %8 + %9 + %10 +%%fin +%endmacro + +%macro DiffOrNot 14 + TestDiff %1,%2 + test edx,edx + jz %%same + %3 + %4 + %5 + %6 + %7 + %8 + jmp %%fin +%%same: + %9 + %10 + %11 + %12 + %13 + %14 +%%fin +%endmacro + +%macro Interp1 3 + mov edx,%2 + shl edx,2 + add edx,%3 + sub edx,%2 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp2 4 + mov edx,%2 + shl edx,1 + add edx,%3 + add edx,%4 + shr edx,2 + mov %1,edx +%endmacro + +%macro Interp3 2 + movd mm1, eax + movd mm2, %2 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + pmullw mm1, [const7] + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp5 3 + mov edx,%2 + add edx,%3 + shr edx,1 + mov %1,edx +%endmacro + +%macro Interp6 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + pmullw mm1, [const5] + psllw mm2, 1 + paddw mm1, mm3 + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp7 3 + movd mm1, eax + movd mm2, %2 + movd mm3, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + punpcklbw mm3, [reg_blank] + pmullw mm1, [const6] + paddw mm2, mm3 + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro Interp8 3 + movd mm1, %2 + movd mm2, %3 + punpcklbw mm1, [reg_blank] + punpcklbw mm2, [reg_blank] + pmullw mm1, [const5] + pmullw mm2, [const3] + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, [reg_blank] + movd %1, mm1 +%endmacro + +%macro PIXEL00_0 0 + mov [edi],eax +%endmacro + +%macro PIXEL00_11 0 + Interp1 [edi],eax,[c4] +%endmacro + +%macro PIXEL00_12 0 + Interp1 [edi],eax,[c2] +%endmacro + +%macro PIXEL00_20 0 + Interp2 [edi],eax,[c2],[c4] +%endmacro + +%macro PIXEL00_50 0 + Interp5 [edi],[c2],[c4] +%endmacro + +%macro PIXEL00_80 0 + Interp8 [edi],eax,[c1] +%endmacro + +%macro PIXEL00_81 0 + Interp8 [edi],eax,[c4] +%endmacro + +%macro PIXEL00_82 0 + Interp8 [edi],eax,[c2] +%endmacro + +%macro PIXEL01_0 0 + mov [edi+4],eax +%endmacro + +%macro PIXEL01_10 0 + Interp1 [edi+4],eax,[c1] +%endmacro + +%macro PIXEL01_12 0 + Interp1 [edi+4],eax,[c2] +%endmacro + +%macro PIXEL01_14 0 + Interp1 [edi+4],[c2],eax +%endmacro + +%macro PIXEL01_21 0 + Interp2 [edi+4],[c2],eax,[c4] +%endmacro + +%macro PIXEL01_31 0 + Interp3 [edi+4],[c4] +%endmacro + +%macro PIXEL01_50 0 + Interp5 [edi+4],[c2],eax +%endmacro + +%macro PIXEL01_60 0 + Interp6 [edi+4],[c2],[c4] +%endmacro + +%macro PIXEL01_61 0 + Interp6 [edi+4],[c2],[c1] +%endmacro + +%macro PIXEL01_82 0 + Interp8 [edi+4],eax,[c2] +%endmacro + +%macro PIXEL01_83 0 + Interp8 [edi+4],[c2],[c4] +%endmacro + +%macro PIXEL02_0 0 + mov [edi+8],eax +%endmacro + +%macro PIXEL02_10 0 + Interp1 [edi+8],eax,[c3] +%endmacro + +%macro PIXEL02_11 0 + Interp1 [edi+8],eax,[c2] +%endmacro + +%macro PIXEL02_13 0 + Interp1 [edi+8],[c2],eax +%endmacro + +%macro PIXEL02_21 0 + Interp2 [edi+8],[c2],eax,[c6] +%endmacro + +%macro PIXEL02_32 0 + Interp3 [edi+8],[c6] +%endmacro + +%macro PIXEL02_50 0 + Interp5 [edi+8],[c2],eax +%endmacro + +%macro PIXEL02_60 0 + Interp6 [edi+8],[c2],[c6] +%endmacro + +%macro PIXEL02_61 0 + Interp6 [edi+8],[c2],[c3] +%endmacro + +%macro PIXEL02_81 0 + Interp8 [edi+8],eax,[c2] +%endmacro + +%macro PIXEL02_83 0 + Interp8 [edi+8],[c2],[c6] +%endmacro + +%macro PIXEL03_0 0 + mov [edi+12],eax +%endmacro + +%macro PIXEL03_11 0 + Interp1 [edi+12],eax,[c2] +%endmacro + +%macro PIXEL03_12 0 + Interp1 [edi+12],eax,[c6] +%endmacro + +%macro PIXEL03_20 0 + Interp2 [edi+12],eax,[c2],[c6] +%endmacro + +%macro PIXEL03_50 0 + Interp5 [edi+12],[c2],[c6] +%endmacro + +%macro PIXEL03_80 0 + Interp8 [edi+12],eax,[c3] +%endmacro + +%macro PIXEL03_81 0 + Interp8 [edi+12],eax,[c2] +%endmacro + +%macro PIXEL03_82 0 + Interp8 [edi+12],eax,[c6] +%endmacro + +%macro PIXEL10_0 0 + mov [edi+ebx],eax +%endmacro + +%macro PIXEL10_10 0 + Interp1 [edi+ebx],eax,[c1] +%endmacro + +%macro PIXEL10_11 0 + Interp1 [edi+ebx],eax,[c4] +%endmacro + +%macro PIXEL10_13 0 + Interp1 [edi+ebx],[c4],eax +%endmacro + +%macro PIXEL10_21 0 + Interp2 [edi+ebx],[c4],eax,[c2] +%endmacro + +%macro PIXEL10_32 0 + Interp3 [edi+ebx],[c2] +%endmacro + +%macro PIXEL10_50 0 + Interp5 [edi+ebx],[c4],eax +%endmacro + +%macro PIXEL10_60 0 + Interp6 [edi+ebx],[c4],[c2] +%endmacro + +%macro PIXEL10_61 0 + Interp6 [edi+ebx],[c4],[c1] +%endmacro + +%macro PIXEL10_81 0 + Interp8 [edi+ebx],eax,[c4] +%endmacro + +%macro PIXEL10_83 0 + Interp8 [edi+ebx],[c4],[c2] +%endmacro + +%macro PIXEL11_0 0 + mov [edi+ebx+4],eax +%endmacro + +%macro PIXEL11_30 0 + Interp3 [edi+ebx+4],[c1] +%endmacro + +%macro PIXEL11_31 0 + Interp3 [edi+ebx+4],[c4] +%endmacro + +%macro PIXEL11_32 0 + Interp3 [edi+ebx+4],[c2] +%endmacro + +%macro PIXEL11_70 0 + Interp7 [edi+ebx+4],[c4],[c2] +%endmacro + +%macro PIXEL12_0 0 + mov [edi+ebx+8],eax +%endmacro + +%macro PIXEL12_30 0 + Interp3 [edi+ebx+8],[c3] +%endmacro + +%macro PIXEL12_31 0 + Interp3 [edi+ebx+8],[c2] +%endmacro + +%macro PIXEL12_32 0 + Interp3 [edi+ebx+8],[c6] +%endmacro + +%macro PIXEL12_70 0 + Interp7 [edi+ebx+8],[c6],[c2] +%endmacro + +%macro PIXEL13_0 0 + mov [edi+ebx+12],eax +%endmacro + +%macro PIXEL13_10 0 + Interp1 [edi+ebx+12],eax,[c3] +%endmacro + +%macro PIXEL13_12 0 + Interp1 [edi+ebx+12],eax,[c6] +%endmacro + +%macro PIXEL13_14 0 + Interp1 [edi+ebx+12],[c6],eax +%endmacro + +%macro PIXEL13_21 0 + Interp2 [edi+ebx+12],[c6],eax,[c2] +%endmacro + +%macro PIXEL13_31 0 + Interp3 [edi+ebx+12],[c2] +%endmacro + +%macro PIXEL13_50 0 + Interp5 [edi+ebx+12],[c6],eax +%endmacro + +%macro PIXEL13_60 0 + Interp6 [edi+ebx+12],[c6],[c2] +%endmacro + +%macro PIXEL13_61 0 + Interp6 [edi+ebx+12],[c6],[c3] +%endmacro + +%macro PIXEL13_82 0 + Interp8 [edi+ebx+12],eax,[c6] +%endmacro + +%macro PIXEL13_83 0 + Interp8 [edi+ebx+12],[c6],[c2] +%endmacro + +%macro PIXEL20_0 0 + mov [ecx],eax +%endmacro + +%macro PIXEL20_10 0 + Interp1 [ecx],eax,[c7] +%endmacro + +%macro PIXEL20_12 0 + Interp1 [ecx],eax,[c4] +%endmacro + +%macro PIXEL20_14 0 + Interp1 [ecx],[c4],eax +%endmacro + +%macro PIXEL20_21 0 + Interp2 [ecx],[c4],eax,[c8] +%endmacro + +%macro PIXEL20_31 0 + Interp3 [ecx],[c8] +%endmacro + +%macro PIXEL20_50 0 + Interp5 [ecx],[c4],eax +%endmacro + +%macro PIXEL20_60 0 + Interp6 [ecx],[c4],[c8] +%endmacro + +%macro PIXEL20_61 0 + Interp6 [ecx],[c4],[c7] +%endmacro + +%macro PIXEL20_82 0 + Interp8 [ecx],eax,[c4] +%endmacro + +%macro PIXEL20_83 0 + Interp8 [ecx],[c4],[c8] +%endmacro + +%macro PIXEL21_0 0 + mov [ecx+4],eax +%endmacro + +%macro PIXEL21_30 0 + Interp3 [ecx+4],[c7] +%endmacro + +%macro PIXEL21_31 0 + Interp3 [ecx+4],[c8] +%endmacro + +%macro PIXEL21_32 0 + Interp3 [ecx+4],[c4] +%endmacro + +%macro PIXEL21_70 0 + Interp7 [ecx+4],[c4],[c8] +%endmacro + +%macro PIXEL22_0 0 + mov [ecx+8],eax +%endmacro + +%macro PIXEL22_30 0 + Interp3 [ecx+8],[c9] +%endmacro + +%macro PIXEL22_31 0 + Interp3 [ecx+8],[c6] +%endmacro + +%macro PIXEL22_32 0 + Interp3 [ecx+8],[c8] +%endmacro + +%macro PIXEL22_70 0 + Interp7 [ecx+8],[c6],[c8] +%endmacro + +%macro PIXEL23_0 0 + mov [ecx+12],eax +%endmacro + +%macro PIXEL23_10 0 + Interp1 [ecx+12],eax,[c9] +%endmacro + +%macro PIXEL23_11 0 + Interp1 [ecx+12],eax,[c6] +%endmacro + +%macro PIXEL23_13 0 + Interp1 [ecx+12],[c6],eax +%endmacro + +%macro PIXEL23_21 0 + Interp2 [ecx+12],[c6],eax,[c8] +%endmacro + +%macro PIXEL23_32 0 + Interp3 [ecx+12],[c8] +%endmacro + +%macro PIXEL23_50 0 + Interp5 [ecx+12],[c6],eax +%endmacro + +%macro PIXEL23_60 0 + Interp6 [ecx+12],[c6],[c8] +%endmacro + +%macro PIXEL23_61 0 + Interp6 [ecx+12],[c6],[c9] +%endmacro + +%macro PIXEL23_81 0 + Interp8 [ecx+12],eax,[c6] +%endmacro + +%macro PIXEL23_83 0 + Interp8 [ecx+12],[c6],[c8] +%endmacro + +%macro PIXEL30_0 0 + mov [ecx+ebx],eax +%endmacro + +%macro PIXEL30_11 0 + Interp1 [ecx+ebx],eax,[c8] +%endmacro + +%macro PIXEL30_12 0 + Interp1 [ecx+ebx],eax,[c4] +%endmacro + +%macro PIXEL30_20 0 + Interp2 [ecx+ebx],eax,[c8],[c4] +%endmacro + +%macro PIXEL30_50 0 + Interp5 [ecx+ebx],[c8],[c4] +%endmacro + +%macro PIXEL30_80 0 + Interp8 [ecx+ebx],eax,[c7] +%endmacro + +%macro PIXEL30_81 0 + Interp8 [ecx+ebx],eax,[c8] +%endmacro + +%macro PIXEL30_82 0 + Interp8 [ecx+ebx],eax,[c4] +%endmacro + +%macro PIXEL31_0 0 + mov [ecx+ebx+4],eax +%endmacro + +%macro PIXEL31_10 0 + Interp1 [ecx+ebx+4],eax,[c7] +%endmacro + +%macro PIXEL31_11 0 + Interp1 [ecx+ebx+4],eax,[c8] +%endmacro + +%macro PIXEL31_13 0 + Interp1 [ecx+ebx+4],[c8],eax +%endmacro + +%macro PIXEL31_21 0 + Interp2 [ecx+ebx+4],[c8],eax,[c4] +%endmacro + +%macro PIXEL31_32 0 + Interp3 [ecx+ebx+4],[c4] +%endmacro + +%macro PIXEL31_50 0 + Interp5 [ecx+ebx+4],[c8],eax +%endmacro + +%macro PIXEL31_60 0 + Interp6 [ecx+ebx+4],[c8],[c4] +%endmacro + +%macro PIXEL31_61 0 + Interp6 [ecx+ebx+4],[c8],[c7] +%endmacro + +%macro PIXEL31_81 0 + Interp8 [ecx+ebx+4],eax,[c8] +%endmacro + +%macro PIXEL31_83 0 + Interp8 [ecx+ebx+4],[c8],[c4] +%endmacro + +%macro PIXEL32_0 0 + mov [ecx+ebx+8],eax +%endmacro + +%macro PIXEL32_10 0 + Interp1 [ecx+ebx+8],eax,[c9] +%endmacro + +%macro PIXEL32_12 0 + Interp1 [ecx+ebx+8],eax,[c8] +%endmacro + +%macro PIXEL32_14 0 + Interp1 [ecx+ebx+8],[c8],eax +%endmacro + +%macro PIXEL32_21 0 + Interp2 [ecx+ebx+8],[c8],eax,[c6] +%endmacro + +%macro PIXEL32_31 0 + Interp3 [ecx+ebx+8],[c6] +%endmacro + +%macro PIXEL32_50 0 + Interp5 [ecx+ebx+8],[c8],eax +%endmacro + +%macro PIXEL32_60 0 + Interp6 [ecx+ebx+8],[c8],[c6] +%endmacro + +%macro PIXEL32_61 0 + Interp6 [ecx+ebx+8],[c8],[c9] +%endmacro + +%macro PIXEL32_82 0 + Interp8 [ecx+ebx+8],eax,[c8] +%endmacro + +%macro PIXEL32_83 0 + Interp8 [ecx+ebx+8],[c8],[c6] +%endmacro + +%macro PIXEL33_0 0 + mov [ecx+ebx+12],eax +%endmacro + +%macro PIXEL33_11 0 + Interp1 [ecx+ebx+12],eax,[c6] +%endmacro + +%macro PIXEL33_12 0 + Interp1 [ecx+ebx+12],eax,[c8] +%endmacro + +%macro PIXEL33_20 0 + Interp2 [ecx+ebx+12],eax,[c8],[c6] +%endmacro + +%macro PIXEL33_50 0 + Interp5 [ecx+ebx+12],[c8],[c6] +%endmacro + +%macro PIXEL33_80 0 + Interp8 [ecx+ebx+12],eax,[c9] +%endmacro + +%macro PIXEL33_81 0 + Interp8 [ecx+ebx+12],eax,[c6] +%endmacro + +%macro PIXEL33_82 0 + Interp8 [ecx+ebx+12],eax,[c8] +%endmacro + +inbuffer equ 8 +outbuffer equ 12 +Xres equ 16 +Yres equ 20 +pitch equ 24 + +_hq4x_32: + push ebp + mov ebp,esp + pushad + + mov esi,[ebp+inbuffer] + mov edi,[ebp+outbuffer] + mov edx,[ebp+Yres] + mov [linesleft],edx + mov ebx,[ebp+Xres] + shl ebx,1 + mov dword[prevline],0 + mov dword[nextline],ebx +.loopy + push edi + mov ecx,[ebp+Xres] + sub ecx,2 ; x={Xres-2, Xres-1} are special cases. + mov dword[xcounter],ecx + ; x=0 - special case + mov ebx,[prevline] + movq mm5,[esi+ebx] + movq mm6,[esi] + mov ebx,[nextline] + movq mm7,[esi+ebx] + movd eax,mm5 + movzx edx,ax + mov [w1],edx + mov [w2],edx + shr eax,16 + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + mov [w5],edx + shr eax,16 + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + mov [w8],edx + shr eax,16 + mov [w9],eax + jmp .flags +.loopx + mov ebx,[prevline] + movq mm5,[esi+ebx-2] + movq mm6,[esi-2] + mov ebx,[nextline] + movq mm7,[esi+ebx-2] + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + psrlq mm5,32 + movd eax,mm5 + movzx edx,ax + mov [w3],edx + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + psrlq mm6,32 + movd eax,mm6 + movzx edx,ax + mov [w6],edx + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + psrlq mm7,32 + movd eax,mm7 + movzx edx,ax + mov [w9],edx +.flags + mov ebx,_RGBtoYUV + mov eax,[w5] + xor ecx,ecx + movd mm5,[ebx+eax*4] + mov dword[cross],0 + + mov edx,[w2] + cmp eax,edx + je .noflag2 + or dword[cross],1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag2 + or ecx,2 +.noflag2 + mov edx,[w4] + cmp eax,edx + je .noflag4 + or dword[cross],2 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag4 + or ecx,8 +.noflag4 + mov edx,[w6] + cmp eax,edx + je .noflag6 + or dword[cross],4 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag6 + or ecx,16 +.noflag6 + mov edx,[w8] + cmp eax,edx + je .noflag8 + or dword[cross],8 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag8 + or ecx,64 +.noflag8 + cmp dword[cross],0 + jnz .testflag1 + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + mov ebx,[ebp+pitch] + AUXADDRESS + mov [edi],eax + mov [edi+4],eax + mov [edi+8],eax + mov [edi+12],eax + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx+12],eax + mov [ecx],eax + mov [ecx+4],eax + mov [ecx+8],eax + mov [ecx+12],eax + mov [ecx+ebx],eax + mov [ecx+ebx+4],eax + mov [ecx+ebx+8],eax + mov [ecx+ebx+12],eax + jmp .loopx_end +.testflag1 + mov edx,[w1] + cmp eax,edx + je .noflag1 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag1 + or ecx,1 +.noflag1 + mov edx,[w3] + cmp eax,edx + je .noflag3 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag3 + or ecx,4 +.noflag3 + mov edx,[w7] + cmp eax,edx + je .noflag7 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag7 + or ecx,32 +.noflag7 + mov edx,[w9] + cmp eax,edx + je .noflag9 + movq mm1,mm5 + movd mm2,[ebx+edx*4] + psubusb mm1,mm2 + psubusb mm2,mm5 + por mm1,mm2 + psubusb mm1,[threshold] + movd edx,mm1 + test edx,edx + jz .noflag9 + or ecx,128 +.noflag9 + mov ebx,_LUT16to32 + mov eax,[ebx+eax*4] + mov edx,[w2] + mov edx,[ebx+edx*4] + mov [c2],edx + mov edx,[w4] + mov edx,[ebx+edx*4] + mov [c4],edx + mov edx,[w6] + mov edx,[ebx+edx*4] + mov [c6],edx + mov edx,[w8] + mov edx,[ebx+edx*4] + mov [c8],edx + test ecx,0x005A + jz .switch + mov edx,[w1] + mov edx,[ebx+edx*4] + mov [c1],edx + mov edx,[w3] + mov edx,[ebx+edx*4] + mov [c3],edx + mov edx,[w7] + mov edx,[ebx+edx*4] + mov [c7],edx + mov edx,[w9] + mov edx,[ebx+edx*4] + mov [c9],edx +.switch + mov ebx,[ebp+pitch] + jmp [FuncTable+ecx*4] + +..@flag0 +..@flag1 +..@flag4 +..@flag32 +..@flag128 +..@flag5 +..@flag132 +..@flag160 +..@flag33 +..@flag129 +..@flag36 +..@flag133 +..@flag164 +..@flag161 +..@flag37 +..@flag165 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag2 +..@flag34 +..@flag130 +..@flag162 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag16 +..@flag17 +..@flag48 +..@flag49 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag64 +..@flag65 +..@flag68 +..@flag69 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag8 +..@flag12 +..@flag136 +..@flag140 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag3 +..@flag35 +..@flag131 +..@flag163 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag6 +..@flag38 +..@flag134 +..@flag166 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag20 +..@flag21 +..@flag52 +..@flag53 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag144 +..@flag145 +..@flag176 +..@flag177 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag192 +..@flag193 +..@flag196 +..@flag197 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag96 +..@flag97 +..@flag100 +..@flag101 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag40 +..@flag44 +..@flag168 +..@flag172 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag9 +..@flag13 +..@flag137 +..@flag141 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag18 +..@flag50 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_50,PIXEL03_50,PIXEL12_0,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag80 +..@flag81 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag72 +..@flag76 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_50,PIXEL21_0,PIXEL30_50,PIXEL31_50 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag10 +..@flag138 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_50,PIXEL01_50,PIXEL10_50,PIXEL11_0 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag66 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag24 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag7 +..@flag39 +..@flag135 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag148 +..@flag149 +..@flag180 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag224 +..@flag228 +..@flag225 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag41 +..@flag169 +..@flag45 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag22 +..@flag54 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag208 +..@flag209 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag104 +..@flag108 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag11 +..@flag139 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag19 +..@flag51 + AUXADDRESS + DiffOrNot w2,w6,PIXEL00_81,PIXEL01_31,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL00_12,PIXEL01_14,PIXEL02_83,PIXEL03_50,PIXEL12_70,PIXEL13_21 + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag146 +..@flag178 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL23_32,PIXEL33_82,PIXEL02_21,PIXEL03_50,PIXEL12_70,PIXEL13_83,PIXEL23_13,PIXEL33_11 + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + jmp .loopx_end +..@flag84 +..@flag85 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + DiffOrNot w6,w8,PIXEL03_81,PIXEL13_31,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL03_12,PIXEL13_14,PIXEL22_70,PIXEL23_83,PIXEL32_21,PIXEL33_50 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL20_61 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag112 +..@flag113 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL30_82,PIXEL31_32,PIXEL32_10,PIXEL33_80,PIXEL22_70,PIXEL23_21,PIXEL30_11,PIXEL31_13,PIXEL32_83,PIXEL33_50 + jmp .loopx_end +..@flag200 +..@flag204 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL32_31,PIXEL33_81,PIXEL20_21,PIXEL21_70,PIXEL30_50,PIXEL31_83,PIXEL32_14,PIXEL33_12 + PIXEL22_31 + PIXEL23_81 + jmp .loopx_end +..@flag73 +..@flag77 + AUXADDRESS + DiffOrNot w8,w4,PIXEL00_82,PIXEL10_32,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL00_11,PIXEL10_13,PIXEL20_83,PIXEL21_70,PIXEL30_50,PIXEL31_21 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag42 +..@flag170 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL20_31,PIXEL30_81,PIXEL00_50,PIXEL01_21,PIXEL10_83,PIXEL11_70,PIXEL20_14,PIXEL30_12 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag14 +..@flag142 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL02_32,PIXEL03_82,PIXEL10_10,PIXEL11_30,PIXEL00_50,PIXEL01_83,PIXEL02_13,PIXEL03_11,PIXEL10_21,PIXEL11_70 + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag67 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag70 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag28 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag152 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag194 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag98 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag56 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag25 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag26 +..@flag31 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL11_0 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag82 +..@flag214 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag88 +..@flag248 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + jmp .loopx_end +..@flag74 +..@flag107 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag27 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag86 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag216 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag106 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag30 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag210 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag120 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag75 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag29 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_61 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag198 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag184 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_61 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag99 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag57 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag71 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_30 + PIXEL23_61 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag156 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag226 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_61 + PIXEL11_30 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag60 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag195 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag102 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag153 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag58 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag83 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL10_81 + PIXEL11_31 + PIXEL20_61 + PIXEL21_30 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag92 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag202 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag78 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag154 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag114 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL10_61 + PIXEL11_30 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + PIXEL30_82 + PIXEL31_32 + jmp .loopx_end +..@flag89 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag90 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag55 +..@flag23 + AUXADDRESS + DiffOrNot w2,w6,PIXEL00_81,PIXEL01_31,PIXEL02_0,PIXEL03_0,PIXEL12_0,PIXEL13_0,PIXEL00_12,PIXEL01_14,PIXEL02_83,PIXEL03_50,PIXEL12_70,PIXEL13_21 + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_30 + PIXEL23_10 + PIXEL30_20 + PIXEL31_60 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag182 +..@flag150 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL12_0,PIXEL13_0,PIXEL23_32,PIXEL33_82,PIXEL02_21,PIXEL03_50,PIXEL12_70,PIXEL13_83,PIXEL23_13,PIXEL33_11 + PIXEL10_61 + PIXEL11_30 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + jmp .loopx_end +..@flag213 +..@flag212 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + DiffOrNot w6,w8,PIXEL03_81,PIXEL13_31,PIXEL22_0,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL03_12,PIXEL13_14,PIXEL22_70,PIXEL23_83,PIXEL32_21,PIXEL33_50 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL20_61 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag241 +..@flag240 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_61 + PIXEL03_80 + PIXEL10_60 + PIXEL11_70 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_0,PIXEL23_0,PIXEL30_82,PIXEL31_32,PIXEL32_0,PIXEL33_0,PIXEL22_70,PIXEL23_21,PIXEL30_11,PIXEL31_13,PIXEL32_83,PIXEL33_50 + jmp .loopx_end +..@flag236 +..@flag232 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_60 + PIXEL03_20 + PIXEL10_10 + PIXEL11_30 + PIXEL12_70 + PIXEL13_60 + DiffOrNot w8,w4,PIXEL20_0,PIXEL21_0,PIXEL30_0,PIXEL31_0,PIXEL32_31,PIXEL33_81,PIXEL20_21,PIXEL21_70,PIXEL30_50,PIXEL31_83,PIXEL32_14,PIXEL33_12 + PIXEL22_31 + PIXEL23_81 + jmp .loopx_end +..@flag109 +..@flag105 + AUXADDRESS + DiffOrNot w8,w4,PIXEL00_82,PIXEL10_32,PIXEL20_0,PIXEL21_0,PIXEL30_0,PIXEL31_0,PIXEL00_11,PIXEL10_13,PIXEL20_83,PIXEL21_70,PIXEL30_50,PIXEL31_21 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag171 +..@flag43 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL11_0,PIXEL20_31,PIXEL30_81,PIXEL00_50,PIXEL01_21,PIXEL10_83,PIXEL11_70,PIXEL20_14,PIXEL30_12 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag143 +..@flag15 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL02_32,PIXEL03_82,PIXEL10_0,PIXEL11_0,PIXEL00_50,PIXEL01_83,PIXEL02_13,PIXEL03_11,PIXEL10_21,PIXEL11_70 + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_70 + PIXEL23_60 + PIXEL30_80 + PIXEL31_61 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag124 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag203 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_10 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag62 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag211 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_10 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag118 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_10 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag217 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag110 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_10 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag155 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag188 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag185 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag61 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag157 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag103 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_61 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag227 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_61 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag230 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_61 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag199 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_61 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag220 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + jmp .loopx_end +..@flag158 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag234 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_61 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag242 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL10_61 + PIXEL11_30 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_82 + PIXEL31_32 + jmp .loopx_end +..@flag59 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL11_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag121 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag87 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL20_61 + PIXEL21_30 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag79 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_32 + PIXEL03_82 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag122 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag94 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL12_0 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag218 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + jmp .loopx_end +..@flag91 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL11_0 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag229 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_60 + PIXEL03_20 + PIXEL10_60 + PIXEL11_70 + PIXEL12_70 + PIXEL13_60 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag167 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_60 + PIXEL21_70 + PIXEL22_70 + PIXEL23_60 + PIXEL30_20 + PIXEL31_60 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag173 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag181 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag186 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag115 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL10_81 + PIXEL11_31 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + PIXEL30_82 + PIXEL31_32 + jmp .loopx_end +..@flag93 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + jmp .loopx_end +..@flag206 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag205 +..@flag201 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + DiffOrNot w8,w4,PIXEL20_10,PIXEL21_30,PIXEL30_80,PIXEL31_10,PIXEL20_12,PIXEL21_0,PIXEL30_20,PIXEL31_11 + PIXEL22_31 + PIXEL23_81 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag174 +..@flag46 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_80,PIXEL01_10,PIXEL10_10,PIXEL11_30,PIXEL00_20,PIXEL01_12,PIXEL10_11,PIXEL11_0 + PIXEL02_32 + PIXEL03_82 + PIXEL12_32 + PIXEL13_82 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag179 +..@flag147 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + DiffOrNot w2,w6,PIXEL02_10,PIXEL03_80,PIXEL12_30,PIXEL13_10,PIXEL02_11,PIXEL03_20,PIXEL12_0,PIXEL13_12 + PIXEL10_81 + PIXEL11_31 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag117 +..@flag116 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_30,PIXEL23_10,PIXEL32_10,PIXEL33_80,PIXEL22_0,PIXEL23_11,PIXEL32_12,PIXEL33_20 + PIXEL30_82 + PIXEL31_32 + jmp .loopx_end +..@flag189 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag231 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_32 + PIXEL03_82 + PIXEL10_81 + PIXEL11_31 + PIXEL12_32 + PIXEL13_82 + PIXEL20_82 + PIXEL21_32 + PIXEL22_31 + PIXEL23_81 + PIXEL30_82 + PIXEL31_32 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag126 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag219 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag125 + AUXADDRESS + DiffOrNot w8,w4,PIXEL00_82,PIXEL10_32,PIXEL20_0,PIXEL21_0,PIXEL30_0,PIXEL31_0,PIXEL00_11,PIXEL10_13,PIXEL20_83,PIXEL21_70,PIXEL30_50,PIXEL31_21 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag221 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + DiffOrNot w6,w8,PIXEL03_81,PIXEL13_31,PIXEL22_0,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL03_12,PIXEL13_14,PIXEL22_70,PIXEL23_83,PIXEL32_21,PIXEL33_50 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL20_10 + PIXEL21_30 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag207 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL02_32,PIXEL03_82,PIXEL10_0,PIXEL11_0,PIXEL00_50,PIXEL01_83,PIXEL02_13,PIXEL03_11,PIXEL10_21,PIXEL11_70 + PIXEL12_32 + PIXEL13_82 + PIXEL20_10 + PIXEL21_30 + PIXEL22_31 + PIXEL23_81 + PIXEL30_80 + PIXEL31_10 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag238 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_32 + PIXEL03_82 + PIXEL10_10 + PIXEL11_30 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_0,PIXEL21_0,PIXEL30_0,PIXEL31_0,PIXEL32_31,PIXEL33_81,PIXEL20_21,PIXEL21_70,PIXEL30_50,PIXEL31_83,PIXEL32_14,PIXEL33_12 + PIXEL22_31 + PIXEL23_81 + jmp .loopx_end +..@flag190 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL12_0,PIXEL13_0,PIXEL23_32,PIXEL33_82,PIXEL02_21,PIXEL03_50,PIXEL12_70,PIXEL13_83,PIXEL23_13,PIXEL33_11 + PIXEL10_10 + PIXEL11_30 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + jmp .loopx_end +..@flag187 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL11_0,PIXEL20_31,PIXEL30_81,PIXEL00_50,PIXEL01_21,PIXEL10_83,PIXEL11_70,PIXEL20_14,PIXEL30_12 + PIXEL02_10 + PIXEL03_80 + PIXEL12_30 + PIXEL13_10 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag243 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_10 + PIXEL03_80 + PIXEL10_81 + PIXEL11_31 + PIXEL12_30 + PIXEL13_10 + PIXEL20_82 + PIXEL21_32 + DiffOrNot w6,w8,PIXEL22_0,PIXEL23_0,PIXEL30_82,PIXEL31_32,PIXEL32_0,PIXEL33_0,PIXEL22_70,PIXEL23_21,PIXEL30_11,PIXEL31_13,PIXEL32_83,PIXEL33_50 + jmp .loopx_end +..@flag119 + AUXADDRESS + DiffOrNot w2,w6,PIXEL00_81,PIXEL01_31,PIXEL02_0,PIXEL03_0,PIXEL12_0,PIXEL13_0,PIXEL00_12,PIXEL01_14,PIXEL02_83,PIXEL03_50,PIXEL12_70,PIXEL13_21 + PIXEL10_81 + PIXEL11_31 + PIXEL20_82 + PIXEL21_32 + PIXEL22_30 + PIXEL23_10 + PIXEL30_82 + PIXEL31_32 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag237 +..@flag233 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_60 + PIXEL03_20 + PIXEL10_32 + PIXEL11_32 + PIXEL12_70 + PIXEL13_60 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag175 +..@flag47 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + PIXEL20_31 + PIXEL21_31 + PIXEL22_70 + PIXEL23_60 + PIXEL30_81 + PIXEL31_81 + PIXEL32_60 + PIXEL33_20 + jmp .loopx_end +..@flag183 +..@flag151 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_60 + PIXEL21_70 + PIXEL22_32 + PIXEL23_32 + PIXEL30_20 + PIXEL31_60 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag245 +..@flag244 + AUXADDRESS + PIXEL00_20 + PIXEL01_60 + PIXEL02_81 + PIXEL03_81 + PIXEL10_60 + PIXEL11_70 + PIXEL12_31 + PIXEL13_31 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag250 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + PIXEL02_10 + PIXEL03_80 + PIXEL10_10 + PIXEL11_30 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + jmp .loopx_end +..@flag123 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag95 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL11_0 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_30 + PIXEL23_10 + PIXEL30_80 + PIXEL31_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag222 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag252 + AUXADDRESS + PIXEL00_80 + PIXEL01_61 + PIXEL02_81 + PIXEL03_81 + PIXEL10_10 + PIXEL11_30 + PIXEL12_31 + PIXEL13_31 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag249 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_61 + PIXEL03_80 + PIXEL10_32 + PIXEL11_32 + PIXEL12_30 + PIXEL13_10 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + jmp .loopx_end +..@flag235 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_61 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag111 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_61 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag63 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_30 + PIXEL23_10 + PIXEL30_81 + PIXEL31_81 + PIXEL32_61 + PIXEL33_80 + jmp .loopx_end +..@flag159 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_32 + PIXEL23_32 + PIXEL30_80 + PIXEL31_61 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag215 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_61 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag246 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_61 + PIXEL11_30 + PIXEL12_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag254 + AUXADDRESS + PIXEL00_80 + PIXEL01_10 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_10 + PIXEL11_30 + PIXEL12_0 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag253 + AUXADDRESS + PIXEL00_82 + PIXEL01_82 + PIXEL02_81 + PIXEL03_81 + PIXEL10_32 + PIXEL11_32 + PIXEL12_31 + PIXEL13_31 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag251 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_10 + PIXEL03_80 + PIXEL11_0 + PIXEL12_30 + PIXEL13_10 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + jmp .loopx_end +..@flag239 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + PIXEL02_32 + PIXEL03_82 + PIXEL10_0 + PIXEL11_0 + PIXEL12_32 + PIXEL13_82 + PIXEL20_0 + PIXEL21_0 + PIXEL22_31 + PIXEL23_81 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + PIXEL32_31 + PIXEL33_81 + jmp .loopx_end +..@flag127 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + DiffOrNot w2,w6,PIXEL02_0,PIXEL03_0,PIXEL13_0,PIXEL02_50,PIXEL03_50,PIXEL13_50 + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + DiffOrNot w8,w4,PIXEL20_0,PIXEL30_0,PIXEL31_0,PIXEL20_50,PIXEL30_50,PIXEL31_50 + PIXEL21_0 + PIXEL22_30 + PIXEL23_10 + PIXEL32_10 + PIXEL33_80 + jmp .loopx_end +..@flag191 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_31 + PIXEL21_31 + PIXEL22_32 + PIXEL23_32 + PIXEL30_81 + PIXEL31_81 + PIXEL32_82 + PIXEL33_82 + jmp .loopx_end +..@flag223 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL01_0,PIXEL10_0,PIXEL00_50,PIXEL01_50,PIXEL10_50 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_10 + PIXEL21_30 + PIXEL22_0 + DiffOrNot w6,w8,PIXEL23_0,PIXEL32_0,PIXEL33_0,PIXEL23_50,PIXEL32_50,PIXEL33_50 + PIXEL30_80 + PIXEL31_10 + jmp .loopx_end +..@flag247 + AUXADDRESS + PIXEL00_81 + PIXEL01_31 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL10_81 + PIXEL11_31 + PIXEL12_0 + PIXEL13_0 + PIXEL20_82 + PIXEL21_32 + PIXEL22_0 + PIXEL23_0 + PIXEL30_82 + PIXEL31_32 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end +..@flag255 + AUXADDRESS + DiffOrNot w4,w2,PIXEL00_0,PIXEL00_20 + PIXEL01_0 + PIXEL02_0 + DiffOrNot w2,w6,PIXEL03_0,PIXEL03_20 + PIXEL10_0 + PIXEL11_0 + PIXEL12_0 + PIXEL13_0 + PIXEL20_0 + PIXEL21_0 + PIXEL22_0 + PIXEL23_0 + DiffOrNot w8,w4,PIXEL30_0,PIXEL30_20 + PIXEL31_0 + PIXEL32_0 + DiffOrNot w6,w8,PIXEL33_0,PIXEL33_20 + jmp .loopx_end + + +..@cross0 + mov ebx,[ebp+pitch] + AUXADDRESS + mov [edi],eax + mov [edi+4],eax + mov [edi+8],eax + mov [edi+12],eax + mov [edi+ebx],eax + mov [edi+ebx+4],eax + mov [edi+ebx+8],eax + mov [edi+ebx+12],eax + mov [ecx],eax + mov [ecx+4],eax + mov [ecx+8],eax + mov [ecx+12],eax + mov [ecx+ebx],eax + mov [ecx+ebx+4],eax + mov [ecx+ebx+8],eax + mov [ecx+ebx+12],eax + jmp .loopx_end +..@cross1 + mov ecx,[w2] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov [edi],edx + mov [edi+4],edx + mov [edi+8],edx + mov [edi+12],edx + mov ebx,[ebp+pitch] + AUXADDRESS + mov [edi],edx + mov [edi+4],edx + mov [edi+ebx],eax + mov [edi+ebx+4],eax + jmp .loopx_end +..@cross2 + mov ecx,[w4] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],edx + mov [edi+4],eax + mov [edi+ebx],edx + mov [edi+ebx+4],eax + jmp .loopx_end +..@cross4 + mov ecx,[w6] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],edx + mov [edi+ebx],eax + mov [edi+ebx+4],edx + jmp .loopx_end +..@cross8 + mov ecx,[w8] + mov edx,eax + shl edx,2 + add edx,[ebx+ecx*4] + sub edx,eax + shr edx,2 + mov ebx,[ebp+pitch] + mov [edi],eax + mov [edi+4],eax + mov [edi+ebx],edx + mov [edi+ebx+4],edx + jmp .loopx_end +..@crossN + mov edx,[w2] + mov ecx,[ebx+edx*4] + mov [c2],ecx + mov edx,[w4] + mov ecx,[ebx+edx*4] + mov [c4],ecx + mov edx,[w6] + mov ecx,[ebx+edx*4] + mov [c6],ecx + mov edx,[w8] + mov ecx,[ebx+edx*4] + mov [c8],ecx + mov ebx,[ebp+pitch] + jmp ..@flag0 + +.loopx_end + add esi,2 + add edi,16 + dec dword[xcounter] + jle .xres_2 + jmp .loopx +.xres_2 + ; x=Xres-2 - special case + jl .xres_1 + mov ebx,[prevline] + movq mm5,[esi+ebx-4] + movq mm6,[esi-4] + mov ebx,[nextline] + movq mm7,[esi+ebx-4] + psrlq mm5,16 + psrlq mm6,16 + psrlq mm7,16 + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + psrlq mm5,32 + movd eax,mm5 + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + psrlq mm6,32 + movd eax,mm6 + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + psrlq mm7,32 + movd eax,mm7 + mov [w9],eax + jmp .flags +.xres_1 + cmp dword[xcounter],-1 + jl .nexty + ; x=Xres-1 - special case + mov ebx,[prevline] + movq mm5,[esi+ebx-6] + movq mm6,[esi-6] + mov ebx,[nextline] + movq mm7,[esi+ebx-6] + psrlq mm5,32 + psrlq mm6,32 + psrlq mm7,32 + movd eax,mm5 + movzx edx,ax + mov [w1],edx + shr eax,16 + mov [w2],eax + mov [w3],eax + movd eax,mm6 + movzx edx,ax + mov [w4],edx + shr eax,16 + mov [w5],eax + mov [w6],eax + movd eax,mm7 + movzx edx,ax + mov [w7],edx + shr eax,16 + mov [w8],eax + mov [w9],eax + jmp .flags +.nexty + pop edi + add edi,ebx + add edi,ebx + add edi,ebx + add edi,ebx + dec dword[linesleft] + jz .fin + mov ebx,[ebp+Xres] + shl ebx,1 + cmp dword[linesleft],1 + je .lastline + mov dword[nextline],ebx + neg ebx + mov dword[prevline],ebx + jmp .loopy +.lastline + mov dword[nextline],0 + neg ebx + mov dword[prevline],ebx + jmp .loopy +.fin + emms + popad + mov esp,ebp + pop ebp + ret + +SECTION .data +FuncTable + dd ..@flag0, ..@flag1, ..@flag2, ..@flag3, ..@flag4, ..@flag5, ..@flag6, ..@flag7 + dd ..@flag8, ..@flag9, ..@flag10, ..@flag11, ..@flag12, ..@flag13, ..@flag14, ..@flag15 + dd ..@flag16, ..@flag17, ..@flag18, ..@flag19, ..@flag20, ..@flag21, ..@flag22, ..@flag23 + dd ..@flag24, ..@flag25, ..@flag26, ..@flag27, ..@flag28, ..@flag29, ..@flag30, ..@flag31 + dd ..@flag32, ..@flag33, ..@flag34, ..@flag35, ..@flag36, ..@flag37, ..@flag38, ..@flag39 + dd ..@flag40, ..@flag41, ..@flag42, ..@flag43, ..@flag44, ..@flag45, ..@flag46, ..@flag47 + dd ..@flag48, ..@flag49, ..@flag50, ..@flag51, ..@flag52, ..@flag53, ..@flag54, ..@flag55 + dd ..@flag56, ..@flag57, ..@flag58, ..@flag59, ..@flag60, ..@flag61, ..@flag62, ..@flag63 + dd ..@flag64, ..@flag65, ..@flag66, ..@flag67, ..@flag68, ..@flag69, ..@flag70, ..@flag71 + dd ..@flag72, ..@flag73, ..@flag74, ..@flag75, ..@flag76, ..@flag77, ..@flag78, ..@flag79 + dd ..@flag80, ..@flag81, ..@flag82, ..@flag83, ..@flag84, ..@flag85, ..@flag86, ..@flag87 + dd ..@flag88, ..@flag89, ..@flag90, ..@flag91, ..@flag92, ..@flag93, ..@flag94, ..@flag95 + dd ..@flag96, ..@flag97, ..@flag98, ..@flag99, ..@flag100, ..@flag101, ..@flag102, ..@flag103 + dd ..@flag104, ..@flag105, ..@flag106, ..@flag107, ..@flag108, ..@flag109, ..@flag110, ..@flag111 + dd ..@flag112, ..@flag113, ..@flag114, ..@flag115, ..@flag116, ..@flag117, ..@flag118, ..@flag119 + dd ..@flag120, ..@flag121, ..@flag122, ..@flag123, ..@flag124, ..@flag125, ..@flag126, ..@flag127 + dd ..@flag128, ..@flag129, ..@flag130, ..@flag131, ..@flag132, ..@flag133, ..@flag134, ..@flag135 + dd ..@flag136, ..@flag137, ..@flag138, ..@flag139, ..@flag140, ..@flag141, ..@flag142, ..@flag143 + dd ..@flag144, ..@flag145, ..@flag146, ..@flag147, ..@flag148, ..@flag149, ..@flag150, ..@flag151 + dd ..@flag152, ..@flag153, ..@flag154, ..@flag155, ..@flag156, ..@flag157, ..@flag158, ..@flag159 + dd ..@flag160, ..@flag161, ..@flag162, ..@flag163, ..@flag164, ..@flag165, ..@flag166, ..@flag167 + dd ..@flag168, ..@flag169, ..@flag170, ..@flag171, ..@flag172, ..@flag173, ..@flag174, ..@flag175 + dd ..@flag176, ..@flag177, ..@flag178, ..@flag179, ..@flag180, ..@flag181, ..@flag182, ..@flag183 + dd ..@flag184, ..@flag185, ..@flag186, ..@flag187, ..@flag188, ..@flag189, ..@flag190, ..@flag191 + dd ..@flag192, ..@flag193, ..@flag194, ..@flag195, ..@flag196, ..@flag197, ..@flag198, ..@flag199 + dd ..@flag200, ..@flag201, ..@flag202, ..@flag203, ..@flag204, ..@flag205, ..@flag206, ..@flag207 + dd ..@flag208, ..@flag209, ..@flag210, ..@flag211, ..@flag212, ..@flag213, ..@flag214, ..@flag215 + dd ..@flag216, ..@flag217, ..@flag218, ..@flag219, ..@flag220, ..@flag221, ..@flag222, ..@flag223 + dd ..@flag224, ..@flag225, ..@flag226, ..@flag227, ..@flag228, ..@flag229, ..@flag230, ..@flag231 + dd ..@flag232, ..@flag233, ..@flag234, ..@flag235, ..@flag236, ..@flag237, ..@flag238, ..@flag239 + dd ..@flag240, ..@flag241, ..@flag242, ..@flag243, ..@flag244, ..@flag245, ..@flag246, ..@flag247 + dd ..@flag248, ..@flag249, ..@flag250, ..@flag251, ..@flag252, ..@flag253, ..@flag254, ..@flag255 + + diff --git a/src/interface/scalers/hq_shared32.cpp b/src/interface/scalers/hq_shared32.cpp new file mode 100644 index 00000000..93df3677 --- /dev/null +++ b/src/interface/scalers/hq_shared32.cpp @@ -0,0 +1,413 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "hq_shared32.h" + +const unsigned __int64 reg_blank = 0x0000000000000000; +const unsigned __int64 const7 = 0x0000000700070007; +const unsigned __int64 treshold = 0x0000000000300706; + +void Interp1(unsigned char * pc, unsigned int c1, unsigned int c2) +{ + //*((int*)pc) = (c1*3+c2)/4; + +#ifdef MMX + __asm + { + mov eax, pc + movd mm1, c1 + movd mm2, c2 + movq mm0, mm1 + pslld mm0, 2 + psubd mm0, mm1 + paddd mm0, mm2 + psrld mm0, 2 + movd [eax], mm0 + EMMS + } +#else + __asm + { + mov eax, pc + mov edx, c1 + shl edx, 2 + add edx, c2 + sub edx, c1 + shr edx, 2 + mov [eax], edx + } +#endif +} + +void Interp2(unsigned char * pc, unsigned int c1, unsigned int c2, unsigned int c3) +{ + //*((int*)pc) = (c1*2+c2+c3)/4; + +#ifdef MMX + __asm + { + mov eax, pc + movd mm0, c1 + movd mm1, c2 + movd mm2, c3 + pslld mm0, 1 + paddd mm0, mm1 + paddd mm0, mm2 + psrad mm0, 2 + movd [eax], mm0 + EMMS + } +#else + __asm + { + mov eax, pc + mov edx, c1 + shl edx, 1 + add edx, c2 + add edx, c3 + shr edx, 2 + mov [eax], edx + } +#endif +} + +void Interp3(unsigned char * pc, unsigned int c1, unsigned int c2) +{ + //*((int*)pc) = (c1*7+c2)/8; + //*((int*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) + + // (((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3; + +#ifdef MMX + __asm + { + mov eax, pc + movd mm1, c1 + movd mm2, c2 + punpcklbw mm1, reg_blank + punpcklbw mm2, reg_blank + pmullw mm1, const7 + paddw mm1, mm2 + psrlw mm1, 3 + packuswb mm1, reg_blank + movd [eax], mm1 + EMMS + } +#else + __asm + { + mov eax, c1 + mov ebx, c2 + mov ecx, eax + shl ecx, 3 + sub ecx, eax + add ecx, ebx + shr ecx, 3 + mov eax, pc + mov [eax], ecx + } +#endif +} + +void Interp4(unsigned char * pc, unsigned int c1, unsigned int c2, unsigned int c3) +{ + //*((int*)pc) = (c1*2+(c2+c3)*7)/16; + //*((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*7 ) & 0x000FF000) + + // (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*7 ) & 0x0FF00FF0)) >> 4; + +#ifdef MMX + __asm + { + mov eax, pc + movd mm1, c1 + movd mm2, c2 + movd mm3, c3 + punpcklbw mm1, reg_blank + punpcklbw mm2, reg_blank + punpcklbw mm3, reg_blank + psllw mm1, 1 + paddw mm2, mm3 + pmullw mm2, const7 + paddw mm1, mm2 + psrlw mm1, 4 + packuswb mm1, reg_blank + movd [eax], mm1 + EMMS + } +#else + + __asm + { + mov eax, [c1] + and eax, 0FF00h + shl eax, 1 + mov ecx, [c2] + and ecx, 0FF00h + mov edx, [c3] + and edx, 0FF00h + add ecx, edx + imul ecx, ecx,7 + add eax, ecx + and eax, 0FF000h + + mov ebx, [c1] + and ebx, 0FF00FFh + shl ebx, 1 + mov ecx, [c2] + and ecx, 0FF00FFh + mov edx, [c3] + and edx, 0FF00FFh + add ecx, edx + imul ecx, ecx,7 + add ebx, ecx + and ebx, 0FF00FF0h + + add eax, ebx + shr eax, 4 + + mov ebx, pc + mov [ebx], eax + } +#endif +} + +void Interp5(unsigned char * pc, unsigned int c1, unsigned int c2) +{ + //*((int*)pc) = (c1+c2)/2; + +#ifdef MMX + __asm + { + mov eax, pc + movd mm0, c1 + movd mm1, c2 + paddd mm0, mm1 + psrad mm0, 1 + movd [eax], mm0 + EMMS + } +#else + __asm + { + mov eax, pc + mov edx, c1 + add edx, c2 + shr edx, 1 + mov [eax], edx + } +#endif +} + + +#include "interp.h" + +void Interp1_16(unsigned char * pc, unsigned short c1, unsigned short c2) +{ + *((unsigned short*)pc) = interp_16_31(c1, c2); + //*((int*)pc) = (c1*3+c2)/4; +} + +void Interp2_16(unsigned char * pc, unsigned short c1, unsigned short c2, unsigned short c3) +{ + *((unsigned short*)pc) = interp_16_211(c1, c2, c3); + //*((int*)pc) = (c1*2+c2+c3)/4; +} + +void Interp3_16(unsigned char * pc, unsigned short c1, unsigned short c2) +{ + *((unsigned short*)pc) = interp_16_71(c1, c2); +// *((unsigned short*)pc) = (c1*7+c2)/8; +// *((unsigned short*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) + +// (((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3; +} + +void Interp4_16(unsigned char * pc, unsigned short c1, unsigned short c2, unsigned short c3) +{ + *((unsigned short*)pc) = interp_16_772(c2, c3, c1); +// *((unsigned short*)pc) = (c1*2+(c2+c3)*7)/16; +// *((unsigned short*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*7 ) & 0x000FF000) + +// (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*7 ) & 0x0FF00FF0)) >> 4; +} + +void Interp5_16(unsigned char * pc, unsigned short c1, unsigned short c2) +{ + *((unsigned short*)pc) = interp_16_11(c1, c2); +} + + + + +bool Diff(unsigned int c1, unsigned int c2) +{ + unsigned int + YUV1 = RGBtoYUV(c1), + YUV2 = RGBtoYUV(c2); + + if (YUV1 == YUV2) return false; // Save some processing power + +#ifdef MMX + unsigned int retval; + __asm + { + mov eax, 0x7FFFFFFF + movd mm7, eax ;mm7 = ABS_MASK = 0x7FFFFFFF + + ; Copy source colors in first reg + movd mm0, YUV1 + movd mm1, YUV2 + + mov eax, 0x00FF0000 + movd mm6, eax ;mm6 = Ymask = 0x00FF0000 + + ; Calculate color Y difference + movq mm2, mm0 + movq mm3, mm1 + pand mm2, mm6 + pand mm3, mm6 + psubd mm2, mm3 + pand mm2, mm7 + + mov eax, 0x0000FF00 + movd mm6, eax ;mm6 = Umask = 0x0000FF00 + + ; Calculate color U difference + movq mm3, mm0 + movq mm4, mm1 + pand mm3, mm6 + pand mm4, mm6 + psubd mm3, mm4 + pand mm3, mm7 + + mov eax, 0x000000FF + movd mm6, eax ;mm6 = Vmask = 0x000000FF + + ; Calculate color V difference + movq mm4, mm0 + movq mm5, mm1 + pand mm4, mm6 + pand mm5, mm6 + psubd mm4, mm5 + pand mm4, mm7 + + mov eax, 0x00300000 + movd mm5, eax ;mm5 = trY = 0x00300000 + mov eax, 0x00000700 + movd mm6, eax ;mm6 = trU = 0x00000700 + mov eax, 0x00000006 + movd mm7, eax ;mm7 = trV = 0x00000006 + + ; Compare the results + pcmpgtd mm2, trY + pcmpgtd mm3, trU + pcmpgtd mm4, trV + por mm2, mm3 + por mm2, mm4 + + movd retval, mm2 + + EMMS + } + return (retval != 0); +#else + return + ( abs32((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || + ( abs32((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || + ( abs32((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ); +#endif +} + + +unsigned int RGBtoYUV(unsigned int c) +{ // Division through 3 slows down the emulation about 10% !!! +#ifdef MMX + unsigned int retval; + __asm + { + movd mm0, c + movq mm1, mm0 + movq mm2, mm0 ;mm0=mm1=mm2=c + + mov eax, 0x000000FF + movd mm5, eax ;mm5 = REDMASK = 0x000000FF + mov eax, 0x0000FF00 + movd mm6, eax ;mm6 = GREENMASK = 0x0000FF00 + mov eax, 0x00FF0000 + movd mm7, eax ;mm7 = BLUEMASK = 0x00FF0000 + + + pand mm0, mm5 + pand mm1, mm6 + pand mm2, mm7 ;mm0=R mm1=G mm2=B + + movq mm3, mm0 + paddd mm3, mm1 + paddd mm3, mm2 +; psrld mm3, 2 ;mm3=Y +; pslld mm3, 16 + pslld mm3, 14 ;mm3=Y<<16 + + mov eax, 512 + movd mm7, eax ;mm7 = 128 << 2 = 512 + + movq mm4, mm0 + psubd mm4, mm2 +; psrld mm4, 2 +; paddd mm4, mm7 ;mm4=U +; pslld mm4, 8 ;mm4=U<<8 + paddd mm4, mm7 + pslld mm4, 6 + + mov eax, 128 + movd mm7, eax ;mm7 = 128 + + movq mm5, mm1 + pslld mm5, 1 + psubd mm5, mm0 + psubd mm5, mm2 + psrld mm5, 3 + paddd mm5, mm7 ;mm5=V + + paddd mm5, mm4 + paddd mm5, mm3 + + movd retval, mm5 + + EMMS + } + return retval; +#else + unsigned char r, g, b, Y, u, v; + r = (c & 0x000000FF); + g = (c & 0x0000FF00) >> 8; + b = (c & 0x00FF0000) >> 16; + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((-r + 2*g -b)>>3); + return (Y<<16) + (u<<8) + v; + + // Extremely High Quality Code + //unsigned char r, g, b; + //r = c & 0xFF; + //g = (c >> 8) & 0xFF; + //b = (c >> 16) & 0xFF; + //unsigned char y, u, v; + //y = (0.256788 * r + 0.504129 * g + 0.097906 * b) + 16; + //u = (-0.148223 * r - 0.290993 * g + 0.439216 * b) + 128; + //v = (0.439216 * r - 0.367788 * g - 0.071427 * b) + 128; + //return (y << 16) + (u << 8) + v; +#endif +} diff --git a/src/interface/scalers/hq_shared32.h b/src/interface/scalers/hq_shared32.h new file mode 100644 index 00000000..af071c42 --- /dev/null +++ b/src/interface/scalers/hq_shared32.h @@ -0,0 +1,41 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#define abs32(value) (value & 0x7FFFFFFF) +#define abs16(value) (value & 0x7FFF) + +const int Ymask = 0x00FF0000; +const int Umask = 0x0000FF00; +const int Vmask = 0x000000FF; +const int trY = 0x00300000; +const int trU = 0x00000700; +const int trV = 0x00000006; + +void Interp1(unsigned char * pc, unsigned int c1, unsigned int c2); +void Interp2(unsigned char * pc, unsigned int c1, unsigned int c2, unsigned int c3); +void Interp3(unsigned char * pc, unsigned int c1, unsigned int c2); +void Interp4(unsigned char * pc, unsigned int c1, unsigned int c2, unsigned int c3); +void Interp5(unsigned char * pc, unsigned int c1, unsigned int c2); +void Interp1_16(unsigned char * pc, unsigned short c1, unsigned short c2); +void Interp2_16(unsigned char * pc, unsigned short c1, unsigned short c2, unsigned short c3); +void Interp3_16(unsigned char * pc, unsigned short c1, unsigned short c2); +void Interp4_16(unsigned char * pc, unsigned short c1, unsigned short c2, unsigned short c3); +void Interp5_16(unsigned char * pc, unsigned short c1, unsigned short c2); +bool Diff(unsigned int c1, unsigned int c2); +unsigned int RGBtoYUV(unsigned int c); diff --git a/src/interface/scalers/interp.h b/src/interface/scalers/interp.h new file mode 100644 index 00000000..5e604922 --- /dev/null +++ b/src/interface/scalers/interp.h @@ -0,0 +1,355 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#ifndef __INTERP_H +#define __INTERP_H + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +/***************************************************************************/ +/* Basic types */ + +/***************************************************************************/ +/* interpolation */ + +extern unsigned interp_mask[2]; +extern unsigned interp_bits_per_pixel; + +#define INTERP_16_MASK_1(v) (v & interp_mask[0]) +#define INTERP_16_MASK_2(v) (v & interp_mask[1]) + +static inline u16 interp_16_521(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8); +} + +static inline u16 interp_16_332(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8); +} + +static inline u16 interp_16_611(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8); +} + +static inline u16 interp_16_71(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8); +} + +static inline u16 interp_16_211(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4); +} + +static inline u16 interp_16_772(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16) + | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16); +} + +static inline u16 interp_16_11(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2); +} + +static u16 interp_16_31(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4); +} + +static inline u16 interp_16_1411(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16); +} + +static inline u16 interp_16_431(u16 p1, u16 p2, u16 p3) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8); +} + +static inline u16 interp_16_53(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8); +} + +static inline u16 interp_16_151(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16); +} + +static inline u16 interp_16_97(u16 p1, u16 p2) +{ + return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16) + | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16); +} + +#define INTERP_32_MASK_1(v) (v & 0xFF00FF) +#define INTERP_32_MASK_2(v) (v & 0x00FF00) + +static inline u32 interp_32_521(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8); +} + +static inline u32 interp_32_332(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8); +} + +static inline u32 interp_32_211(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4); +} + +static inline u32 interp_32_611(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8); +} + +static inline u32 interp_32_71(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8); +} + +static inline u32 interp_32_772(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16) + | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16); +} + +static inline u32 interp_32_11(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2); +} + +static u32 interp_32_31(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4); +} + +static inline u32 interp_32_1411(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16); +} + +static inline u32 interp_32_431(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8); +} + +static inline u32 interp_32_53(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8); +} + +static inline u32 interp_32_151(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16); +} + +static inline u32 interp_32_97(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16); +} + +/***************************************************************************/ +/* diff */ +/* +#define INTERP_Y_LIMIT (0x30*4) +#define INTERP_U_LIMIT (0x07*4) +#define INTERP_V_LIMIT (0x06*8) + +static int interp_16_diff(u16 p1, u16 p2) +{ + int r, g, b; + int y, u, v; + + if (p1 == p2) + return 0; + + if (interp_bits_per_pixel == 16) { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; + r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + } else { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; + r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; + } + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + +return 0; +} + +static int interp_32_diff(u32 p1, u32 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) + return 0; + + b = (int)((p1 & 0xFF) - (p2 & 0xFF)); + g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; + r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + + +#define INTERP_LIMIT2 (96000) +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MIN(x,y) ((x) < (y) ? (x) : (y)) + +static int interp_16_diff2(u16 p1, u16 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF79E) == (p2 & 0xF79E)) + return 0; + + if (interp_bits_per_pixel == 16) { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; + r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + } else { + b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; + g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; + r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; + } + +// yb = 30*r + 58*g + 12*b; + y = 33*r + 36*g + 31*b; + u = -14*r - 29*g + 44*b; + v = 62*r - 51*g - 10*b; + + if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2) + return 1; + return 0; +} + +static int interp_32_diff2(u32 p1, u32 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF0F0F0) == (p2 & 0xF0F0F0)) + return 0; + + b = (int)((p1 & 0xF8) - (p2 & 0xF8)); + g = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + r = (int)((p1 & 0xF80000) - (p2 & 0xF80000)) >> 16; + +// y = 30*r + 58*g + 12*b; + y = 33*r + 36*g + 31*b; + u = -14*r - 29*g + 44*b; + v = 62*r - 51*g - 10*b; + + if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2) + return 1; + + return 0; +} +*/ +static void interp_set(unsigned bits_per_pixel) +{ + interp_bits_per_pixel = bits_per_pixel; + + switch (bits_per_pixel) { + case 15 : + interp_mask[0] = 0x7C1F; + interp_mask[1] = 0x03E0; + break; + case 16 : + interp_mask[0] = 0xF81F; + interp_mask[1] = 0x07E0; + break; + case 32 : + interp_mask[0] = 0xFF00FF; + interp_mask[1] = 0x00FF00; + break; + } +} + +#endif diff --git a/src/interface/scalers/scale2x.h b/src/interface/scalers/scale2x.h new file mode 100644 index 00000000..c277e973 --- /dev/null +++ b/src/interface/scalers/scale2x.h @@ -0,0 +1,924 @@ +/* + * This file is part of the Scale2x project. + * + * Copyright (C) 2001-2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This file contains a C and MMX implementation of the Scale2x effect. + * + * You can find an high level description of the effect at : + * + * http://scale2x.sourceforge.net/ + * + * Alternatively at the previous license terms, you are allowed to use this + * code in your program with these conditions: + * - the program is not used in commercial activities. + * - the whole source code of the program is released with the binary. + * - derivative works of the program are allowed. + */ + +#ifndef __SCALE2X_H +#define __SCALE2X_H + +#include + +/***************************************************************************/ +/* Basic types */ + +typedef unsigned char scale2x_uint8; +typedef unsigned short scale2x_uint16; +typedef unsigned scale2x_uint32; + +/***************************************************************************/ +/* Scale2x C implementation */ + +static void scale2x_8_def_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +static void scale2x_16_def_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +static void scale2x_32_def_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +/** + * Scale by a factor of 2 a row of pixels of 8 bits. + * The function is implemented in C. + * The pixels over the left and right borders are assumed of the same color of + * the pixels on the border. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +static inline void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + scale2x_8_def_single(dst0, src0, src1, src2, count); + scale2x_8_def_single(dst1, src2, src1, src0, count); +} + +/** + * Scale by a factor of 2 a row of pixels of 16 bits. + * This function operates like scale2x_8_def() but for 16 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +static inline void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +{ + assert(count >= 2); + + scale2x_16_def_single(dst0, src0, src1, src2, count); + scale2x_16_def_single(dst1, src2, src1, src0, count); +} + +/** + * Scale by a factor of 2 a row of pixels of 32 bits. + * This function operates like scale2x_8_def() but for 32 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +static inline void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +{ + assert(count >= 2); + + scale2x_32_def_single(dst0, src0, src1, src2, count); + scale2x_32_def_single(dst1, src2, src1, src0, count); +} + +/***************************************************************************/ +/* Scale2x MMX implementation */ + +#if defined(__GNUC__) && defined(__i386__) + +/* + * Apply the Scale2x effect at a single row. + * This function must be called only by the other scale2x functions. + * + * Considering the pixel map : + * + * ABC (src0) + * DEF (src1) + * GHI (src2) + * + * this functions compute 2 new pixels in substitution of the source pixel E + * like this map : + * + * ab (dst) + * + * with these variables : + * + * ¤t -> E + * ¤t_left -> D + * ¤t_right -> F + * ¤t_upper -> B + * ¤t_lower -> H + * + * %0 -> current_upper + * %1 -> current + * %2 -> current_lower + * %3 -> dst + * %4 -> counter + * + * %mm0 -> *current_left + * %mm1 -> *current_next + * %mm2 -> tmp0 + * %mm3 -> tmp1 + * %mm4 -> tmp2 + * %mm5 -> tmp3 + * %mm6 -> *current_upper + * %mm7 -> *current + */ +static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 16); + assert(count % 8 == 0); + + /* always do the first and last run */ + count -= 2*8; + + __asm__ __volatile__( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "psrlq $56, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $3, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $56, %%mm1\n" + "psrlq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +{ + assert(count >= 8); + assert(count % 4 == 0); + + /* always do the first and last run */ + count -= 2*4; + + __asm__ __volatile__( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "psrlq $48, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $2, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $48, %%mm1\n" + "psrlq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +{ + assert(count >= 4); + assert(count % 2 == 0); + + /* always do the first and last run */ + count -= 2*2; + + __asm__ __volatile__( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "psrlq $32, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $1, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $32, %%mm1\n" + "psrlq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +/** + * Scale by a factor of 2 a row of pixels of 8 bits. + * This is a very fast MMX implementation. + * The implementation uses a combination of cmp/and/not operations to + * completly remove the need of conditional jumps. This trick give the + * major speed improvement. + * Also, using the 8 bytes MMX registers more than one pixel are computed + * at the same time. + * Before calling this function you must ensure that the currenct CPU supports + * the MMX instruction set. After calling it you must be sure to call the EMMS + * instruction before any floating-point operation. + * The pixels over the left and right borders are assumed of the same color of + * the pixels on the border. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 16 and a multiple of 8. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +#if 0 +static void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 16); + assert(count % 8 == 0); + + scale2x_8_mmx_single(dst0, src0, src1, src2, count); + scale2x_8_mmx_single(dst1, src2, src1, src0, count); +} +#endif +/** + * Scale by a factor of 2 a row of pixels of 16 bits. + * This function operates like scale2x_8_mmx() but for 16 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 8 and a multiple of 4. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +static void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) +{ + assert(count >= 8); + assert(count % 4 == 0); + + scale2x_16_mmx_single(dst0, src0, src1, src2, count); + scale2x_16_mmx_single(dst1, src2, src1, src0, count); +} + +/** + * Scale by a factor of 2 a row of pixels of 32 bits. + * This function operates like scale2x_8_mmx() but for 32 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 4 and a multiple of 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +static void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) +{ + assert(count >= 4); + assert(count % 2 == 0); + + scale2x_32_mmx_single(dst0, src0, src1, src2, count); + scale2x_32_mmx_single(dst1, src2, src1, src0, count); +} + +#endif + +#endif diff --git a/src/interface/scalers/scale2x_vc.h b/src/interface/scalers/scale2x_vc.h new file mode 100644 index 00000000..49f99a44 --- /dev/null +++ b/src/interface/scalers/scale2x_vc.h @@ -0,0 +1,443 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 1999-2002 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This file contains an inline MMX implentation of the Scale2x effect, + * which compiles with Visual Studio. + * + * You can found an high level description of the effect at : + * + * http://scale2x.sourceforge.net/scale2x.html + * + * Alternatively at the previous license terms, you are allowed to use this + * code in your program with these conditions: + * - the program is not used in commercial activities. + * - the whole source code of the program is released with the binary. + * - derivative works of the program are allowed. + */ + +#ifndef __SCALE2XV_H +#define __SCALE2XV_H + +/* See scale2x.h for function descriptions and information */ +#include "scale2x.h" + +#ifdef _MSC_VER + +/***************************************************************************/ +/* Scale2x MMX implementation */ + +static void internal_scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { + /* always do the first and last run */ + count -= 2*4; + + __asm { + mov eax, src0; + mov ebx, src1; + mov ecx, src2; + mov edx, dst; + mov esi, count; + + /* first run */ + /* set the current, current_pre, current_next registers */ + pxor mm0,mm0; /* use a fake black out of screen */ + movq mm7, qword ptr [ebx]; + movq mm1, qword ptr [ebx + 8]; + psrlq mm0, 48; + psllq mm1, 48; + movq mm2, mm7; + movq mm3, mm7; + psllq mm2, 16; + psrlq mm3, 16; + por mm0, mm2; + por mm1, mm3; + + /* current_upper */ + movq mm6, qword ptr [eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2, mm0; + movq mm4, mm1; + movq mm3, mm0; + movq mm5, mm1; + pcmpeqw mm2, mm6; + pcmpeqw mm4, mm6; + pcmpeqw mm3, qword ptr [ecx]; + pcmpeqw mm5, qword ptr [ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqw mm2,mm1; + pcmpeqw mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpcklwd mm2,mm4; + punpckhwd mm3,mm4; + movq qword ptr [edx], mm2; + movq qword ptr [edx + 8], mm3; + + /* next */ + add eax, 8; + add ebx, 8; + add ecx, 8; + add edx, 16; + + /* central runs */ + shr esi, 2; + jz label1; + align 4; + label0: + + /* set the current, current_pre, current_next registers */ + movq mm0, qword ptr [ebx-8]; + movq mm7, qword ptr [ebx]; + movq mm1, qword ptr [ebx+8]; + psrlq mm0,48; + psllq mm1,48; + movq mm2,mm7; + movq mm3,mm7; + psllq mm2,16; + psrlq mm3,16; + por mm0,mm2; + por mm1,mm3; + + /* current_upper */ + movq mm6, qword ptr [eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2,mm0; + movq mm4,mm1; + movq mm3,mm0; + movq mm5,mm1; + pcmpeqw mm2,mm6; + pcmpeqw mm4,mm6; + pcmpeqw mm3, qword ptr [ecx]; + pcmpeqw mm5, qword ptr [ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqw mm2,mm1; + pcmpeqw mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpcklwd mm2,mm4; + punpckhwd mm3,mm4; + movq qword ptr [edx], mm2; + movq qword ptr [edx+8], mm3; + + /* next */ + add eax,8; + add ebx,8; + add ecx,8; + add edx,16; + + dec esi; + jnz label0; + label1: + + /* final run */ + /* set the current, current_pre, current_next registers */ + movq mm0, qword ptr [ebx-8]; + movq mm7, qword ptr [ebx]; + pxor mm1,mm1; /* use a fake black out of screen */ + psrlq mm0,48; + psllq mm1,48; + movq mm2,mm7; + movq mm3,mm7; + psllq mm2,16; + psrlq mm3,16; + por mm0,mm2; + por mm1,mm3; + + /* current_upper */ + movq mm6, qword ptr [eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2,mm0; + movq mm4,mm1; + movq mm3,mm0; + movq mm5,mm1; + pcmpeqw mm2,mm6; + pcmpeqw mm4,mm6; + pcmpeqw mm3, qword ptr [ecx]; + pcmpeqw mm5, qword ptr [ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqw mm2,mm1; + pcmpeqw mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpcklwd mm2,mm4; + punpckhwd mm3,mm4; + movq qword ptr [edx], mm2; + movq qword ptr [edx+8], mm3; + + mov src0, eax; + mov src1, ebx; + mov src2, ecx; + mov dst, edx; + mov count, esi; + } +} + +static void internal_scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { + /* always do the first and last run */ + count -= 2*2; + + __asm { + mov eax, src0; + mov ebx, src1; + mov ecx, src2; + mov edx, dst; + mov esi, count; + + /* first run */ + /* set the current, current_pre, current_next registers */ + pxor mm0,mm0; + movq mm7,qword ptr [ebx]; + movq mm1,qword ptr [ebx + 8]; + psrlq mm0,32; + psllq mm1,32; + movq mm2,mm7; + movq mm3,mm7; + psllq mm2,32; + psrlq mm3,32; + por mm0,mm2; + por mm1,mm3; + + /* current_upper */ + movq mm6,qword ptr [eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2,mm0; + movq mm4,mm1; + movq mm3,mm0; + movq mm5,mm1; + pcmpeqd mm2,mm6; + pcmpeqd mm4,mm6; + pcmpeqd mm3,qword ptr [ecx]; + pcmpeqd mm5,qword ptr [ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqd mm2,mm1; + pcmpeqd mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpckldq mm2,mm4; + punpckhdq mm3,mm4; + movq qword ptr [edx],mm2; + movq qword ptr [edx+8],mm3; + + /* next */ + add eax,8; + add ebx,8; + add ecx,8; + add edx,16; + + /* central runs */ + shr esi,1; + jz label1; +label0: + + /* set the current, current_pre, current_next registers */ + movq mm0,qword ptr [ebx-8]; + movq mm7,qword ptr [ebx]; + movq mm1,qword ptr [ebx+8]; + psrlq mm0,32; + psllq mm1,32; + movq mm2,mm7; + movq mm3,mm7; + psllq mm2,32; + psrlq mm3,32; + por mm0,mm2; + por mm1,mm3; + + /* current_upper */ + movq mm6,qword ptr[eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2,mm0; + movq mm4,mm1; + movq mm3,mm0; + movq mm5,mm1; + pcmpeqd mm2,mm6; + pcmpeqd mm4,mm6; + pcmpeqd mm3,qword ptr[ecx]; + pcmpeqd mm5,qword ptr[ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqd mm2,mm1; + pcmpeqd mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpckldq mm2,mm4; + punpckhdq mm3,mm4; + movq qword ptr [edx],mm2; + movq qword ptr [edx+8],mm3; + + /* next */ + add eax,8; + add ebx,8; + add ecx,8; + add edx,16; + + dec esi; + jnz label0; +label1: + + /* final run */ + /* set the current, current_pre, current_next registers */ + movq mm0,qword ptr [ebx-8]; + movq mm7,qword ptr [ebx]; + pxor mm1,mm1; + psrlq mm0,32; + psllq mm1,32; + movq mm2,mm7; + movq mm3,mm7; + psllq mm2,32; + psrlq mm3,32; + por mm0,mm2; + por mm1,mm3; + + /* current_upper */ + movq mm6,qword ptr [eax]; + + /* compute the upper-left pixel for dst0 on %%mm2 */ + /* compute the upper-right pixel for dst0 on %%mm4 */ + movq mm2,mm0; + movq mm4,mm1; + movq mm3,mm0; + movq mm5,mm1; + pcmpeqd mm2,mm6; + pcmpeqd mm4,mm6; + pcmpeqd mm3,qword ptr [ecx]; + pcmpeqd mm5,qword ptr [ecx]; + pandn mm3,mm2; + pandn mm5,mm4; + movq mm2,mm0; + movq mm4,mm1; + pcmpeqd mm2,mm1; + pcmpeqd mm4,mm0; + pandn mm2,mm3; + pandn mm4,mm5; + movq mm3,mm2; + movq mm5,mm4; + pand mm2,mm6; + pand mm4,mm6; + pandn mm3,mm7; + pandn mm5,mm7; + por mm2,mm3; + por mm4,mm5; + + /* set *dst0 */ + movq mm3,mm2; + punpckldq mm2,mm4; + punpckhdq mm3,mm4; + movq qword ptr [edx],mm2; + movq qword ptr [edx+8],mm3; + + mov src0, eax; + mov src1, ebx; + mov src2, ecx; + mov dst, edx; + mov count, esi; + } +} + +static void internal_scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { + internal_scale2x_16_mmx_single(dst0, src0, src1, src2, count); + internal_scale2x_16_mmx_single(dst1, src2, src1, src0, count); +} + +static void internal_scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { + internal_scale2x_32_mmx_single(dst0, src0, src1, src2, count); + internal_scale2x_32_mmx_single(dst1, src2, src1, src0, count); +} +#endif + +#endif diff --git a/src/interface/scalers/scale3x.h b/src/interface/scalers/scale3x.h new file mode 100644 index 00000000..2a836683 --- /dev/null +++ b/src/interface/scalers/scale3x.h @@ -0,0 +1,292 @@ +/* + * This file is part of the Scale2x project. + * + * Copyright (C) 2001-2003 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This file contains a C implementation of the Scale3x effect. + * + * You can find an high level description of the effect at : + * + * http://scale2x.sourceforge.net/ + * + * Alternatively at the previous license terms, you are allowed to use this + * code in your program with these conditions: + * - the program is not used in commercial activities. + * - the whole source code of the program is released with the binary. + * - derivative works of the program are allowed. + */ + +#ifndef __SCALE3X_H +#define __SCALE3X_H + +#include + +/***************************************************************************/ +/* Basic types */ + +typedef unsigned char scale3x_uint8; +typedef unsigned short scale3x_uint16; +typedef unsigned scale3x_uint32; + +/***************************************************************************/ +/* Scale3x C implementation */ + +static void scale3x_8_def_single(scale3x_uint8* dst, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 3; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + + ++src0; + ++src1; + ++src2; + + dst += 3; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + dst[2] = src1[0]; +} + +static void scale3x_8_def_fill(scale3x_uint8* dst, const scale3x_uint8* src, unsigned count) +{ + while (count) { + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + + ++src; + dst += 3; + --count; + } +} + +static void scale3x_16_def_single(scale3x_uint16* dst, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 3; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + + ++src0; + ++src1; + ++src2; + + dst += 3; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + dst[2] = src1[0]; +} + +static void scale3x_16_def_fill(scale3x_uint16* dst, const scale3x_uint16* src, unsigned count) +{ + while (count) { + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + + ++src; + dst += 3; + --count; + } +} + +static void scale3x_32_def_single(scale3x_uint32* dst, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 3; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst[2] = src0[0]; + else + dst[2] = src1[0]; + + ++src0; + ++src1; + ++src2; + + dst += 3; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; + dst[2] = src1[0]; +} + +static void scale3x_32_def_fill(scale3x_uint32* dst, const scale3x_uint32* src, unsigned count) +{ + while (count) { + dst[0] = src[0]; + dst[1] = src[0]; + dst[2] = src[0]; + + ++src; + dst += 3; + --count; + } +} + +/** + * Scale by a factor of 3 a row of pixels of 8 bits. + * The function is implemented in C. + * The pixels over the left and right borders are assumed of the same color of + * the pixels on the border. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, triple length in pixels. + * \param dst1 Second destination row, triple length in pixels. + * \param dst2 Third destination row, triple length in pixels. + */ +static inline void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + scale3x_8_def_single(dst0, src0, src1, src2, count); + scale3x_8_def_fill(dst1, src1, count); + scale3x_8_def_single(dst2, src2, src1, src0, count); +} + +/** + * Scale by a factor of 3 a row of pixels of 16 bits. + * This function operates like scale3x_8_def() but for 16 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, triple length in pixels. + * \param dst1 Second destination row, triple length in pixels. + * \param dst2 Third destination row, triple length in pixels. + */ +static inline void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) +{ + assert(count >= 2); + + scale3x_16_def_single(dst0, src0, src1, src2, count); + scale3x_16_def_fill(dst1, src1, count); + scale3x_16_def_single(dst2, src2, src1, src0, count); +} + +/** + * Scale by a factor of 3 a row of pixels of 32 bits. + * This function operates like scale3x_8_def() but for 32 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, triple length in pixels. + * \param dst1 Second destination row, triple length in pixels. + * \param dst2 Third destination row, triple length in pixels. + */ +static inline void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) +{ + assert(count >= 2); + + scale3x_32_def_single(dst0, src0, src1, src2, count); + scale3x_32_def_fill(dst1, src1, count); + scale3x_32_def_single(dst2, src2, src1, src0, count); +} + +#endif diff --git a/src/interface/scalers/superscale.asm b/src/interface/scalers/superscale.asm new file mode 100644 index 00000000..f998933c --- /dev/null +++ b/src/interface/scalers/superscale.asm @@ -0,0 +1,207 @@ +;SuperScale by ElSemi +; +; Based on the original idea of 2xScale of AdvanceMAME. +; AdvanceMAME code is GPLed and I didn't get permisson to use it. so this code is +; my own implementation of that effect. +; similar to Kawaks' KScale effect +; +;It expands the central pixel of a 3x3 matrix to 2x2 pixels resulting in a 2x scale in +;both axis. +; +;A B C E0 E1 +;D E F -> E2 E3 +;G H I +; +; +;Original algorithm (AdvanceMAME) +; +;E0 = (D == B && B != F && D != H) ? D : E; +;E1 = (B == F && B != D && F != H) ? F : E; +;E2 = (D == H && D != B && H != F) ? D : E; +;E3 = (H == F && D != H && B != F) ? F : E; +; +; +;(I'll only put the first 2 equations as the 3rd and 4th +;are symmetrical ABC<->GHI) +; +;Reduce variable usage +; +;D==B => E0=D -> E0=B +; D!=H -> B!=H +; +;B==F => E1=F -> E1=B +; F!=H -> B!=H +; +;Group and reorder +; +;E0=(B==D && B!=F && B!=H)?B:E; +;E1=(B!=D && B==F && B!=H)?B:E; +; +;as you can see, there are only 3 "real" conditions (B==D, B==F, and B!=H). the other +;2 can be get reversing the first 1 conditions (B!=D, B!=F) that makes the code +;suitable to pcmpeqw,pand,pandn + + BITS 32 + SECTION .text ALIGN = 32 + GLOBAL _superscale_line + GLOBAL _superscale_line_75 + +%macro ALIGN32 0 + times ($$-$)&31 nop +%endmacro + +_superscale_line: + push ebp + mov ebp,esp + push eax + push esi + push ebx + push edi + push ecx + + mov eax,[ebp+8h] ;ABC ;line -1 + mov esi,[ebp+0Ch] ;DEF ;current line + mov ebx,[ebp+10h] ;GHI ;line +1 + mov edi,[ebp+14h] ;dst + mov ecx,[ebp+18h] ;count + shr ecx,2 ;/4, we'll make 4 pixels per loop + ALIGN32 +iloop: +;This code makes 4 pixels per loop +;The comments refer only to 1 pixel (the 3rd one to make explanations clearer and +;closer to the algorithm) +; v + movq mm0,[eax] ;xABC +;v movq mm1,[esi] ;xDEF + movq mm2,[ebx] ;xGHI + movq mm3,[esi-2] ;xxDE + movq mm1,[esi] ;xDEF + movq mm4,[esi+2] ;DEFx + +;Prepare basic comparisons + pcmpeqw mm2,mm0 ;mm2=xABC==xGHI (B==H) + pcmpeqw mm3,mm0 ;mm3=xABC==xxDE (B==D) + pcmpeqw mm4,mm0 ;mm4=xABC==DEFx (B==F) + movq mm5,mm2 ;mm5=(B==H) (we need this for both pixel conditions) + +;prepare pixel masks + pandn mm2,mm3 ;mm2=(B==D) && (B!=H) + pandn mm5,mm4 ;mm5=(B==F) && (B!=H) + pandn mm4,mm2 ;mm4=(B==D) && (B!=H) && (B!=F) -> left pixel mask + pandn mm3,mm5 ;mm3=(B==F) && (B!=H) && (B!=D) -> right pixel mask + +;Mask pixels and merge + movq mm2,mm4 ;store to temp as I will overwrite them in the masking process + movq mm5,mm3 ; + pand mm4,mm0 ;Mask out pixels that don't satisfy the conditions + pand mm3,mm0 ;leaving only the "new" pixels (E0,E1=B) + pandn mm2,mm1 ;Invert the mask and merge to get the pixels that remain + pandn mm5,mm1 ;unchanged (E0,E1=E) + por mm4,mm2 ;merge both data to get the final pixels xxE0x + por mm3,mm5 ;xxE1x + movq mm0,mm4 + ;merge both regs, interleaving E0 and E1 data + punpcklwd mm4,mm3 ;in 2 regs (mm4|mm0) + punpckhwd mm0,mm3 ; + movq [edi],mm4 + movq [edi+8],mm0 + add eax,8 + add esi,8 + add ebx,8 + add edi,16 + loop iloop + + pop ecx + pop edi + pop ebx + pop esi + pop eax + pop ebp + ret + +ALIGN32 + +_superscale_line_75: ;do a 75% reduction on the final pixel colour + push ebp + mov ebp,esp + push eax + push esi + push ebx + push edi + push ecx + + mov eax,[ebp+8h] ;ABC ;line -1 + mov esi,[ebp+0Ch] ;DEF ;current line + mov ebx,[ebp+10h] ;GHI ;line +1 + mov edi,[ebp+14h] ;dst + mov ecx,[ebp+1Ch] ;mask + movq mm7,[ecx] ; + mov ecx,[ebp+18h] ;count + shr ecx,2 ;/4, we'll make 4 pixels per loop + ALIGN32 +iloop2: +;This code makes 4 pixels per loop resulting in 8 pixels expansion +;The comments refer only to 1 pixel (the 3rd one to make explanations clearer and +;closer to the algorithm) +; v + movq mm0,[eax] ;xABC +;v movq mm1,[esi] ;xDEF + movq mm2,[ebx] ;xGHI + movq mm3,[esi-2] ;xxDE + movq mm1,[esi] ;xDEF + movq mm4,[esi+2] ;DEFx + +;Prepare basic conditions + pcmpeqw mm2,mm0 ;mm2=xABC==xGHI (B==H) + pcmpeqw mm3,mm0 ;mm3=xABC==xxDE (B==D) + pcmpeqw mm4,mm0 ;mm4=xABC==DEFx (B==F) + movq mm5,mm2 ;mm5=(B==H) (we need this for both pixel conditions) + +;Prepare pixel masks + pandn mm2,mm3 ;mm2=(B==D) && (B!=H) + pandn mm5,mm4 ;mm5=(B==F) && (B!=H) + pandn mm4,mm2 ;mm4=(B==D) && (B!=H) && (B!=F) -> left pixel mask + pandn mm3,mm5 ;mm3=(B==F) && (B!=H) && (B!=D) -> right pixel mask + +;Mask pixels and merge + movq mm2,mm4 ;store to temp as I will overwrite them in the masking process + movq mm5,mm3 ; + pand mm4,mm0 ;Mask out pixels that don't satisfy the conditions + pand mm3,mm0 ;leaving only the "new" pixels (E0,E1=B) + pandn mm2,mm1 ;Invert the mask and merge to get the pixels that remain + pandn mm5,mm1 ;unchanged (E0,E1=E) + por mm4,mm2 ;merge both data to get the final pixels xxE0x + por mm3,mm5 ;xxE1x + movq mm0,mm4 ;merge both regs, interleaving E0 and E1 data + punpcklwd mm4,mm3 ;in 2 regs (mm4|mm0) + punpckhwd mm0,mm3 ; + +;Reduce color bright to 75% using shift/mask + psrlw mm4,1 + psrlw mm0,1 + pand mm4,mm7 + pand mm0,mm7 + movq mm2,mm4 + movq mm1,mm0 + psrlw mm2,1 + psrlw mm1,1 + pand mm2,mm7 + pand mm1,mm7 + paddw mm4,mm2 + paddw mm0,mm1 + movq [edi],mm4 + movq [edi+8],mm0 + add eax,8 + add esi,8 + add ebx,8 + add edi,16 + dec ecx + jnz near iloop2 + + pop ecx + pop edi + pop ebx + pop esi + pop eax + pop ebp + ret diff --git a/src/interface/vid_interface.cpp b/src/interface/vid_interface.cpp new file mode 100644 index 00000000..cda06efa --- /dev/null +++ b/src/interface/vid_interface.cpp @@ -0,0 +1,449 @@ +// Video Output - (calls all the Vid Out plugins) +#include "burner.h" + +#define DEFAULT_IMAGE_WIDTH (304) +#define DEFAULT_IMAGE_HEIGHT (224) + +#define ENABLE_PREVIEW + +#if defined (BUILD_WIN32) + extern struct VidOut VidOutDDraw; + extern struct VidOut VidOutD3D; + extern struct VidOut VidOutDDrawFX; + extern struct VidOut VidOutDX9; + extern struct VidOut VidOutDX9Alt; +#elif defined (BUILD_SDL) + extern struct VidOut VidOutSDLOpenGL; + extern struct VidOut VidOutSDLFX; +#endif + +static struct VidOut *pVidOut[] = { +#if defined (BUILD_WIN32) + &VidOutDDraw, + &VidOutD3D, + &VidOutDDrawFX, + &VidOutDX9, + &VidOutDX9Alt, +#elif defined (BUILD_SDL) + &VidOutSDLOpenGL, + &VidOutSDLFX, +#endif +}; + +#define VID_LEN (sizeof(pVidOut) / sizeof(pVidOut[0])) + +INT64 nVidBlitterOpt[VID_LEN] = {0, }; // Options for the blitter module (meaning depens on module) + +static InterfaceInfo VidInfo = { NULL, NULL, NULL }; + +UINT32 nVidSelect = 0; // Which video output is selected +static UINT32 nVidActive = 0; + +bool bVidOkay = false; + +INT32 nVidWidth = 640, nVidHeight = 480, nVidDepth = 16, nVidRefresh = 0; + +INT32 nVidHorWidth = 640, nVidHorHeight = 480; // Default Horizontal oritated resolution +INT32 nVidVerWidth = 640, nVidVerHeight = 480; // Default Vertical oriented resoultion + +INT32 nVidFullscreen = 0; +INT32 bVidFullStretch = 0; // 1 = stretch to fill the entire window/screen +INT32 bVidCorrectAspect = 1; // 1 = stretch to fill the window/screen while maintaining the correct aspect ratio +INT32 bVidVSync = 0; // 1 = sync blits/pageflips/presents to the screen +INT32 bVidTripleBuffer = 0; // 1 = use triple buffering +INT32 bVidBilinear = 1; // 1 = enable bi-linear filtering (D3D blitter) +INT32 bVidScanlines = 0; // 1 = draw scanlines +INT32 bVidScanRotate = 1; // 1 = rotate scanlines and RGB effects for rotated games +INT32 bVidScanBilinear = 1; // 1 = use bi-linear filtering for scanlines (D3D blitter, debug variable) +INT32 nVidScanIntensity = 0x00BFBFBF; // The maximum colour-value for the scanlines (D3D blitter) +INT32 bVidScanHalf = 1; // Draw scanlines at half intensity instead of black (DDraw blitter) +INT32 bVidScanDelay = 0; // Blend the previous image with the current one +INT32 nVidFeedbackIntensity = 0x40; // Blend factor for previous frame (D3D blitter) +INT32 nVidFeedbackOverSaturation = 0x00; // Add this to the current frame blend factor +INT32 bVidUseHardwareGamma = 1; // Use the video hardware when correcting gamma +INT32 bVidAutoSwitchFull = 0; // 1 = auto switch to fullscreen on loading driver +INT32 bVidArcaderes = 0; // Use game resolution for fullscreen modes + +INT32 bVidArcaderesHor = 0; +INT32 bVidArcaderesVer = 0; + +INT32 nVidRotationAdjust = 0; // & 1: do not rotate the graphics for vertical games, & 2: Reverse flipping for vertical games +INT32 bVidForce16bit = 1; // Emulate the game in 16-bit even when the screen is 32-bit (D3D blitter) +INT32 nVidTransferMethod = -1; // How to transfer the game image to video memory and/or a texture -- + // 0 = blit from system memory / use driver/DirectX texture management + // 1 = copy to a video memory surface, then use bltfast() + // -1 = autodetect for ddraw, equals 1 for d3d +float fVidScreenAngle = 0.174533f; // The angle at which to tilt the screen backwards (in radians, D3D blitter) +float fVidScreenCurvature = 0.698132f; // The angle of the maximum screen curvature (in radians, D3D blitter) +double dVidCubicB = 0.0; // Paremeters for the cubic filter (default is the CAtmull-Rom spline, DX9 blitter) +double dVidCubicC = 0.5; // + +INT32 bVidDX9Bilinear = 1; // 1 = enable bi-linear filtering (D3D9 Alt blitter) +INT32 bVidHardwareVertex = 0; // 1 = use hardware vertex processing +INT32 bVidMotionBlur = 0; // 1 = motion blur + +#ifdef BUILD_WIN32 + HWND hVidWnd = NULL; // Actual window used for video +#endif + +INT32 nVidScrnWidth = 0, nVidScrnHeight = 0; // Actual Screen dimensions (0 if in windowed mode) +INT32 nVidScrnDepth = 0; // Actual screen depth + +INT32 nVidScrnAspectX = 4, nVidScrnAspectY = 3; // Aspect ratio of the display screen + +UINT8* pVidImage = NULL; // Memory buffer +INT32 nVidImageWidth = DEFAULT_IMAGE_WIDTH; // Memory buffer size +INT32 nVidImageHeight = DEFAULT_IMAGE_HEIGHT; // +INT32 nVidImageLeft = 0, nVidImageTop = 0; // Memory buffer visible area offsets +INT32 nVidImagePitch = 0, nVidImageBPP = 0; // Memory buffer pitch and bytes per pixel +INT32 nVidImageDepth = 0; // Memory buffer bits per pixel + +UINT32 (__cdecl *VidHighCol) (INT32 r, INT32 g, INT32 b, INT32 i); +static bool bVidRecalcPalette; + +static UINT8* pVidTransImage = NULL; +static UINT32* pVidTransPalette = NULL; + +static UINT32 __cdecl HighCol15(INT32 r, INT32 g, INT32 b, INT32 /* i */) +{ + UINT32 t; + + t = (r << 7) & 0x7C00; + t |= (g << 2) & 0x03E0; + t |= (b >> 3) & 0x001F; + + return t; +} + +INT32 VidSelect(UINT32 nPlugin) +{ + if (nPlugin < VID_LEN) { + nVidSelect = nPlugin; + return 0; + } else { + return 1; + } +} + +// Forward to VidOut functions +INT32 VidInit() +{ +#if defined (BUILD_WIN32) && defined (ENABLE_PREVIEW) + HBITMAP hbitmap = NULL; + BITMAP bitmap; +#endif + + INT32 nRet = 1; + + VidExit(); + +#if defined (BUILD_WIN32) && defined (ENABLE_PREVIEW) + if (!bDrvOkay) { + //hbitmap = (HBITMAP)LoadImage(hAppInst, _T("BMP_SPLASH"), IMAGE_BITMAP, 304, 224, 0); + hbitmap = (HBITMAP)LoadImage(hAppInst, MAKEINTRESOURCE(BMP_SPLASH), IMAGE_BITMAP, 304, 224, 0); + + GetObject(hbitmap, sizeof(BITMAP), &bitmap); + + nVidImageWidth = bitmap.bmWidth; nVidImageHeight = bitmap.bmHeight; + nVidImageLeft = nVidImageTop = 0; + } +#endif + +#if defined (BUILD_WIN32) && defined (ENABLE_PREVIEW) + if ((nVidSelect < VID_LEN) && (bDrvOkay || hbitmap)) { +#else + if ((nVidSelect < VID_LEN) && bDrvOkay) { +#endif + nVidActive = nVidSelect; + if ((nRet = pVidOut[nVidActive]->Init()) == 0) { + nBurnBpp = nVidImageBPP; // Set Burn library Bytes per pixel + + bVidOkay = true; + + if (bDrvOkay && (BurnDrvGetFlags() & BDF_16BIT_ONLY) && nVidImageBPP > 2) { + nBurnBpp = 2; + + pVidTransPalette = (UINT32*)malloc(32768 * sizeof(UINT32)); + pVidTransImage = (UINT8*)malloc(nVidImageWidth * nVidImageHeight * sizeof(INT16)); + + BurnHighCol = HighCol15; + + if (pVidTransPalette == NULL || pVidTransImage == NULL) { + VidExit(); + nRet = 1; + } + } + } + } + +#if defined (BUILD_WIN32) && defined (ENABLE_PREVIEW) + if (bVidOkay && hbitmap) { + BITMAPINFO bitmapinfo; + UINT8* pLineBuffer = (UINT8*)malloc(bitmap.bmWidth * 4); + HDC hDC = GetDC(hVidWnd); + + if (hDC && pLineBuffer) { + + memset(&bitmapinfo, 0, sizeof(BITMAPINFO)); + bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFO); + bitmapinfo.bmiHeader.biWidth = bitmap.bmWidth; + bitmapinfo.bmiHeader.biHeight = bitmap.bmHeight; + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 24; + bitmapinfo.bmiHeader.biCompression = BI_RGB; + + for (INT32 y = 0; y < nVidImageHeight; y++) { + UINT8* pd = pVidImage + y * nVidImagePitch; + UINT8* ps = pLineBuffer; + + GetDIBits(hDC, hbitmap, nVidImageHeight - 1 - y, 1, ps, &bitmapinfo, DIB_RGB_COLORS); + + for (INT32 x = 0; x < nVidImageWidth; x++, ps += 3) { + UINT32 nColour = VidHighCol(ps[2], ps[1], ps[0], 0); + switch (nVidImageBPP) { + case 2: + *((UINT16*)pd) = (UINT16)nColour; + pd += 2; + break; + case 3: + pd[0] = (nColour >> 16) & 0xFF; + ps[1] = (nColour >> 8) & 0xFF; + pd[2] = (nColour >> 0) & 0xFF; + pd += 3; + break; + case 4: + *((UINT32*)pd) = nColour; + pd += 4; + break; + } + } + } + } + if (hDC) { + ReleaseDC(hVidWnd, hDC); + } + if (pLineBuffer) { + free(pLineBuffer); + pLineBuffer = NULL; + } + } + + if (hbitmap) { + DeleteObject(hbitmap); + } +#endif + + return nRet; +} + +INT32 VidExit() +{ + IntInfoFree(&VidInfo); + + if (bVidOkay) { + INT32 nRet = pVidOut[nVidActive]->Exit(); + +#if defined (BUILD_WIN32) + hVidWnd = NULL; +#endif + + bVidOkay = false; + + nVidImageWidth = DEFAULT_IMAGE_WIDTH; nVidImageHeight = DEFAULT_IMAGE_HEIGHT; + + nVidImageBPP = nVidImageDepth = 0; + nBurnPitch = nBurnBpp = 0; + + if (pVidTransPalette) { + free(pVidTransPalette); + pVidTransPalette = NULL; + } + if (pVidTransImage) { + free(pVidTransImage); + pVidTransImage = NULL; + } + + return nRet; + } else { + return 1; + } +} + +static INT32 VidDoFrame(bool bRedraw) +{ + INT32 nRet; + + if (pVidTransImage) { + UINT16* pSrc = (UINT16*)pVidTransImage; + UINT8* pDest = pVidImage; + + if (bVidRecalcPalette) { + for (INT32 r = 0; r < 256; r += 8) { + for (INT32 g = 0; g < 256; g += 8) { + for (INT32 b = 0; b < 256; b += 8) { + pVidTransPalette[(r << 7) | (g << 2) | (b >> 3)] = VidHighCol(r | (r >> 5), g | (g >> 5), b | (b >> 5), 0); + } + } + } + + bVidRecalcPalette = false; + } + + pBurnDraw = pVidTransImage; + nBurnPitch = nVidImageWidth * 2; + + nRet = pVidOut[nVidActive]->Frame(bRedraw); + + pBurnDraw = NULL; + nBurnPitch = 0; + + switch (nVidImageBPP) { + case 3: { + for (INT32 y = 0; y < nVidImageHeight; y++, pSrc += nVidImageWidth, pDest += nVidImagePitch) { + for (INT32 x = 0; x < nVidImageWidth; x++) { + UINT32 c = pVidTransPalette[pSrc[x]]; + *(pDest + (x * 3) + 0) = c & 0xFF; + *(pDest + (x * 3) + 1) = (c >> 8) & 0xFF; + *(pDest + (x * 3) + 2) = c >> 16; + } + } + break; + } + case 4: { + for (INT32 y = 0; y < nVidImageHeight; y++, pSrc += nVidImageWidth, pDest += nVidImagePitch) { + for (INT32 x = 0; x < nVidImageWidth; x++) { + ((UINT32*)pDest)[x] = pVidTransPalette[pSrc[x]]; + } + } + break; + } + } + } else { + pBurnDraw = pVidImage; + nBurnPitch = nVidImagePitch; + + nRet = pVidOut[nVidActive]->Frame(bRedraw); + + pBurnDraw = NULL; + nBurnPitch = 0; + } + + return nRet; +} + +INT32 VidReInitialise() +{ + if (pVidTransImage) { + free(pVidTransImage); + pVidTransImage = NULL; + } + pVidTransImage = (UINT8*)malloc(nVidImageWidth * nVidImageHeight * sizeof(INT16)); + + return 0; +} + +INT32 VidFrame() +{ + if (bVidOkay && bDrvOkay) { + return VidDoFrame(0); + } else { + return 1; + } +} + +INT32 VidRedraw() +{ + if (bVidOkay /* && bDrvOkay */) { + return VidDoFrame(1); + } else { + return 1; + } +} + +INT32 VidRecalcPal() +{ + bVidRecalcPalette = true; + + return BurnRecalcPal(); +} + +// If bValidate & 1, the video code should use ValidateRect() to validate the rectangle it draws. +INT32 VidPaint(INT32 bValidate) +{ + if (bVidOkay /* && bDrvOkay */) { + return pVidOut[nVidActive]->Paint(bValidate); + } else { + return 1; + } +} + +INT32 VidImageSize(RECT* pRect, INT32 nGameWidth, INT32 nGameHeight) +{ + if (bVidOkay) { + return pVidOut[nVidActive]->ImageSize(pRect, nGameWidth, nGameHeight); + } else { + return pVidOut[nVidSelect]->ImageSize(pRect, nGameWidth, nGameHeight); + } +} + +const TCHAR* VidGetModuleName() +{ + const TCHAR* pszName = NULL; + + if (bVidOkay) { + pszName = pVidOut[nVidActive]->szModuleName; + } else { + pszName = pVidOut[nVidSelect]->szModuleName; + } + + if (pszName) { + return pszName; + } + + return FBALoadStringEx(hAppInst, IDS_ERR_UNKNOWN, true); +} + +InterfaceInfo* VidGetInfo() +{ + if (IntInfoInit(&VidInfo)) { + IntInfoFree(&VidInfo); + return NULL; + } + + if (bVidOkay) { + TCHAR szString[MAX_PATH] = _T(""); + RECT rect; + + VidInfo.pszModuleName = pVidOut[nVidActive]->szModuleName; + +#if defined (BUILD_WIN32) + GetClientScreenRect(hVidWnd, &rect); + if (nVidFullscreen == 0) { + rect.top += nMenuHeight; + _sntprintf(szString, MAX_PATH, _T("Running in windowed mode, $ix%i, %ibpp"), rect.right - rect.left, rect.bottom - rect.top, nVidScrnDepth); + } else { + _sntprintf(szString, MAX_PATH, _T("Running fullscreen, $ix$i, %ibpp"), nVidScrnWidth, nVidScrnHeight, nVidScrnDepth); + } +#elif defined (BUILD_SDL) + _sntprintf(szString, MAX_PATH, _T("Filler for fullscreen/windowed mode & image size")); +#endif + + IntInfoAddStringInterface(&VidInfo, szString); + + _sntprintf(szString, MAX_PATH, _T("Source image %ix%i, %ibpp"), nVidImageWidth, nVidImageHeight, nVidImageDepth); + IntInfoAddStringInterface(&VidInfo, szString); + + if (pVidTransImage) { + _sntprintf(szString, MAX_PATH, _T("Using generic software 15->%ibpp wrapper"), nVidImageDepth); + IntInfoAddStringInterface(&VidInfo, szString); + } + + if (pVidOut[nVidActive]->GetPluginSettings) { + pVidOut[nVidActive]->GetPluginSettings(&VidInfo); + } + } else { + IntInfoAddStringInterface(&VidInfo, _T("Video plugin not initialised")); + } + + return &VidInfo; +} diff --git a/src/interface/vid_softfx.cpp b/src/interface/vid_softfx.cpp new file mode 100644 index 00000000..fbb3f12f --- /dev/null +++ b/src/interface/vid_softfx.cpp @@ -0,0 +1,944 @@ +// Software blitter effects + +#include "burner.h" +#include "vid_softfx.h" + +typedef unsigned long uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +#ifndef _WIN32 + typedef unsigned long DWORD; +#endif + +void _2xpm_lq(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH, int nDepth); +void _2xpm_hq(void *SrcPtr, void *DstPtr, unsigned long SrcPitch, unsigned long DstPitch, unsigned long SrcW, unsigned long SrcH, int nDepth); + +extern void hq2xS_init(unsigned bits_per_pixel); +extern void hq2xS(unsigned char*, unsigned int, unsigned char*, unsigned char*, unsigned int, int, int); +extern void hq2xS32(unsigned char*, unsigned int, unsigned char*, unsigned char*, unsigned int, int, int); +#if defined _MSC_VER && defined BUILD_X86_ASM +extern void hq3xS(unsigned char*,unsigned int,unsigned char*,unsigned char*,unsigned int,int,int); +extern void hq3xS32(unsigned char*,unsigned int,unsigned char*,unsigned char*,unsigned int,int,int); +#endif + +extern int Init_2xSaI(unsigned int BitFormat, unsigned int systemColorDepth); +extern void _2xSaI32(unsigned char*, unsigned int, unsigned char*, unsigned char*, unsigned int, int, int); +extern void Super2xSaI32(unsigned char*, unsigned int, unsigned char*, unsigned char*, unsigned int, int, int); +extern void SuperEagle32(unsigned char*, unsigned int, unsigned char*, unsigned char*, unsigned int, int, int); + +extern void InitLUTs(); +extern void RenderHQ2XS(unsigned char*, unsigned int, unsigned char*, unsigned int, int, int, int type); +extern void RenderHQ3XS(unsigned char*, unsigned int, unsigned char*, unsigned int, int, int, int type); + +void RenderEPXB(unsigned char*, unsigned int, unsigned char*, unsigned int, int, int, int); +void RenderEPXC(unsigned char*, unsigned int, unsigned char*, unsigned int, int, int, int); + +#if defined __GNUC__ + #include "scale2x.h" +#elif defined _MSC_VER && defined BUILD_X86_ASM + #include "scale2x_vc.h" + #define scale2x_16_mmx internal_scale2x_16_mmx + #define scale2x_32_mmx internal_scale2x_32_mmx +#endif +#include "scale3x.h" + +#if defined BUILD_X86_ASM +extern "C" void __cdecl superscale_line(UINT16 *src0, UINT16 *src1, UINT16 *src2, UINT16 *dst, UINT32 width, UINT64 *mask); +extern "C" void __cdecl superscale_line_75(UINT16 *src0, UINT16 *src1, UINT16 *src2, UINT16 *dst, UINT32 width, UINT64 *mask); + +#ifdef __ELF__ + #define LUT16to32 _LUT16to32 + #define RGBtoYUV _RGBtoYUV + #define hq2x_32 _hq2x_32 + #define hq3x_32 _hq3x_32 + #define hq4x_32 _hq4x_32 +#endif + +extern "C" void __cdecl _eagle_mmx16(unsigned long* lb, unsigned long* lb2, short width, unsigned long* screen_address1, unsigned long* screen_address2); + +extern "C" void __cdecl _2xSaISuperEagleLine(uint8* srcPtr, uint8* deltaPtr, uint32 srcPitch, uint32 width, uint8* dstPtr, uint32 dstPitch, uint16 dstBlah); +extern "C" void __cdecl _2xSaILine(uint8* srcPtr, uint8* deltaPtr, uint32 srcPitch, uint32 width, uint8* dstPtr, uint32 dstPitch, uint16 dstBlah); +extern "C" void __cdecl _2xSaISuper2xSaILine(uint8* srcPtr, uint8* deltaPtr, uint32 srcPitch, uint32 width, uint8* dstPtr, uint32 dstPitch, uint16 dstBlah); +extern "C" void __cdecl Init_2xSaIMMX(uint32 BitFormat); + +extern "C" { + void __cdecl hq2x_32(unsigned char*, unsigned char*, DWORD, DWORD, DWORD); + void __cdecl hq3x_32(unsigned char*, unsigned char*, DWORD, DWORD, DWORD); + void __cdecl hq4x_32(unsigned char*, unsigned char*, DWORD, DWORD, DWORD); + + unsigned int LUT16to32[65536]; + unsigned int RGBtoYUV[65536]; +} +#endif + +#define FXF_MMX (1 << 31) + +static struct { TCHAR* pszName; int nZoom; unsigned int nFlags; } SoftFXInfo[] = { + { _T("Plain Software Scale"), 2, 0 }, + + { _T("AdvanceMAME Scale2x"), 2, FXF_MMX }, + { _T("AdvanceMAME Scale3x"), 3, 0 }, + { _T("2xPM LQ"), 2, FXF_MMX }, + { _T("2xPM HQ"), 2, FXF_MMX }, + { _T("Eagle Graphics"), 2, FXF_MMX }, + { _T("SuperEagle"), 2, FXF_MMX }, + { _T("2xSaI"), 2, FXF_MMX }, + { _T("Super 2xSaI"), 2, FXF_MMX }, + { _T("SuperEagle (VBA)"), 2, FXF_MMX }, + { _T("2xSaI (VBA)"), 2, FXF_MMX }, + { _T("Super 2xSaI (VBA)"), 2, FXF_MMX }, + { _T("SuperScale"), 2, FXF_MMX }, + { _T("SuperScale (75% Scanlines)"), 2, FXF_MMX }, + { _T("hq2x Filter"), 2, FXF_MMX }, + { _T("hq3x Filter"), 3, FXF_MMX }, + { _T("hq4x Filter"), 4, FXF_MMX }, + { _T("hq2xS (VBA) Filter"), 2, 0 }, + { _T("hq3xS (VBA) Filter"), 3, FXF_MMX }, + { _T("hq2xS (SNES9X) Filter"), 2, FXF_MMX }, + { _T("hq3xS (SNEX9X) Filter"), 3, FXF_MMX }, + { _T("hq2xBold Filter"), 2, FXF_MMX }, + { _T("hq3xBold Filter"), 3, FXF_MMX }, + { _T("EPXB Filter"), 2, FXF_MMX }, + { _T("EPXC Filter"), 2, FXF_MMX }, +}; + +static unsigned char* pSoftFXImage = NULL; +static int nSoftFXImageWidth = 0; +static int nSoftFXImageHeight = 0; +static int nSoftFXImagePitch = 0; + +static unsigned char* pSoftFXXBuffer = NULL; + +static int nSoftFXRotate = 0; +static int nSoftFXBlitter = 0; +static bool nSoftFXEnlarge = 0; + +static bool MMXSupport() +{ +#if defined BUILD_X86_ASM + unsigned int nSignatureEAX = 0, nSignatureEBX = 0, nSignatureECX = 0, nSignatureEDX = 0; + + CPUID(1, nSignatureEAX, nSignatureEBX, nSignatureECX, nSignatureEDX); + + return (nSignatureEDX >> 23) & 1; // bit 23 of edx ndicates MMX support +#else + return 0; +#endif +} + +TCHAR* VidSoftFXGetEffect(int nEffect) +{ + return SoftFXInfo[nEffect].pszName; +} + +int VidSoftFXGetZoom(int nEffect) +{ + return SoftFXInfo[nEffect].nZoom; +} + +int VidSoftFXCheckDepth(int nEffect, int nDepth) +{ + switch (nEffect) { + case FILTER_PLAIN: + return nDepth; + case FILTER_ADVMAME_SCALE_2X: + case FILTER_ADVMAME_SCALE_3X: + case FILTER_HQ2XS_VBA: + case FILTER_HQ3XS_VBA: + if (nDepth == 16 || nDepth == 32) { + return nDepth; + } + break; + case FILTER_EAGLE: + case FILTER_HQ2XS_SNES9X: + case FILTER_HQ3XS_SNES9X: + case FILTER_HQ2XBOLD: + case FILTER_HQ3XBOLD: + case FILTER_EPXB: + case FILTER_EPXC: + if (nDepth == 16) { + return nDepth; + } + break; + case FILTER_2XPM_LQ: + case FILTER_2XPM_HQ: + case FILTER_SUPEREAGLE: + case FILTER_2XSAI: + case FILTER_SUPER_2XSAI: + case FILTER_SUPERSCALE: + case FILTER_SUPERSCALE_75SCAN: + if (nDepth == 15 || nDepth == 16) { + return nDepth; + } + break; + case FILTER_SUPEREAGLE_VBA: + case FILTER_2XSAI_VBA: + case FILTER_SUPER_2XSAI_VBA: + if (nDepth == 15 || nDepth == 16 || nDepth == 32) { + return nDepth; + } + break; + case FILTER_HQ2X: + case FILTER_HQ3X: + case FILTER_HQ4X: + if (nDepth == 15 || nDepth == 16) { + return 32; + } + break; + } + + return 0; +} + +void VidSoftFXExit() +{ + if (pSoftFXXBuffer) { + free(pSoftFXXBuffer); + pSoftFXXBuffer = NULL; + } + + if (nSoftFXRotate) { + free(pSoftFXImage); + pSoftFXImage = NULL; + } + pSoftFXImage = NULL; + + nSoftFXRotate = 0; + nSoftFXEnlarge = 0; + nSoftFXBlitter = 0; + + return; +} + +int VidSoftFXInit(int nBlitter, int nRotate) +{ + nSoftFXBlitter = nBlitter; + nSoftFXEnlarge = true; + + if ((MMXSupport() == false && (SoftFXInfo[nSoftFXBlitter].nFlags & FXF_MMX)) || VidSoftFXCheckDepth(nSoftFXBlitter, nVidImageDepth) == 0) { + VidSoftFXExit(); + return 1; + } + + pSoftFXImage = pVidImage + nVidImageLeft * nVidImageBPP; + + nSoftFXImageWidth = nVidImageWidth; nSoftFXImageHeight = nVidImageHeight; + + nSoftFXRotate = 0; + if (bDrvOkay) { + BurnDrvGetFullSize(&nSoftFXImageWidth, &nSoftFXImageHeight); + + if ((nRotate & 1) && (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)) { + nSoftFXRotate |= 1; + + BurnDrvGetFullSize(&nSoftFXImageHeight, &nSoftFXImageWidth); + } + + if ((nRotate & 2) && (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED)) { + nSoftFXRotate |= 2; + } + + if (nSoftFXRotate) { + pSoftFXImage = (unsigned char*)malloc(nSoftFXImageWidth * nSoftFXImageHeight * nVidImageBPP); + if (pSoftFXImage == NULL) { + VidSoftFXExit(); + return 1; + } + } + } + nSoftFXImagePitch = nSoftFXImageWidth * nVidImageBPP; + + if (nSoftFXBlitter >= FILTER_SUPEREAGLE && nSoftFXBlitter <= FILTER_SUPER_2XSAI) { // Initialize the 2xSaI engine + pSoftFXXBuffer = (unsigned char*)malloc((nSoftFXImageHeight + 2) * nSoftFXImagePitch); + if (pSoftFXXBuffer == NULL) { + VidSoftFXExit(); + return 1; + } + + memset(pSoftFXXBuffer, 0, (nSoftFXImageHeight + 2) * nSoftFXImagePitch); + +#if defined BUILD_X86_ASM + if (nVidImageDepth == 15) { + Init_2xSaIMMX(555); + } else { + Init_2xSaIMMX(565); + } +#endif + } + + if (nSoftFXBlitter >= FILTER_SUPEREAGLE_VBA && nSoftFXBlitter <= FILTER_SUPER_2XSAI_VBA) { + int nMemLen = (nSoftFXImageHeight + /*2*/4) * nSoftFXImagePitch; + pSoftFXXBuffer = (unsigned char*)malloc(nMemLen); + if (pSoftFXXBuffer == NULL) { + VidSoftFXExit(); + return 1; + } + + memset(pSoftFXXBuffer, 0, nMemLen); + +#if defined BUILD_X86_ASM + if (nVidImageDepth == 15) { + Init_2xSaIMMX(555); + } + else if (nVidImageDepth == 16) { + Init_2xSaIMMX(565); + } + else { + Init_2xSaI(565, 32); // 32 bit + } +#endif + } + +#if defined BUILD_X86_ASM + if (nSoftFXBlitter >= FILTER_HQ2X && nSoftFXBlitter <= FILTER_HQ4X) { + int i, j, k, r, g, b, Y, u, v; + + if (nVidImageDepth == 15) { + for (i = 0; i < 32768; i++) { + LUT16to32[i] = ((i & 0x7C00) << 9) + ((i & 0x03E0) << 6) + ((i & 0x001F) << 3); + } + + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + for (k = 0; k < 32; k++) { + r = i << 3; + g = j << 3; + b = k << 3; + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((-r + 2 * g - b) >> 3); + RGBtoYUV[(i << 10) + (j << 5) + k] = (Y << 16) + (u << 8) + v; + } + } + } + } else { + for (i = 0; i < 65536; i++) { + LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3); + } + + for (i = 0; i < 32; i++) { + for (j = 0; j < 64; j++) { + for (k = 0; k < 32; k++) { + r = i << 3; + g = j << 2; + b = k << 3; + Y = (r + g + b) >> 2; + u = 128 + ((r - b) >> 2); + v = 128 + ((-r + 2 * g - b) >> 3); + RGBtoYUV[(i << 11) + (j << 5) + k] = (Y << 16) + (u << 8) + v; + } + } + } + } + } +#endif + + if (nSoftFXBlitter >= FILTER_HQ2XS_VBA && nSoftFXBlitter <= FILTER_HQ3XS_VBA) { + hq2xS_init(nVidImageDepth); + } + + if (nSoftFXBlitter == FILTER_HQ2XS_SNES9X || nSoftFXBlitter == FILTER_HQ3XS_SNES9X || nSoftFXBlitter == FILTER_HQ2XBOLD || nSoftFXBlitter == FILTER_HQ3XBOLD) { + InitLUTs(); + } + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * SoftFX initialised: using %s in %i-bit mode.\n"), SoftFXInfo[nSoftFXBlitter].pszName, nVidImageDepth); +#endif + + return 0; +} + +int VidSoftFXScale(RECT* pRect, int nGameWidth, int nGameHeight) +{ + int nWidth = pRect->right - pRect->left; + int nHeight = pRect->bottom - pRect->top; + + nSoftFXEnlarge = false; + + if ((nWidth >= (nGameWidth * SoftFXInfo[nSoftFXBlitter].nZoom)) && (nHeight >= (nGameHeight * SoftFXInfo[nSoftFXBlitter].nZoom))) { + nWidth = nGameWidth * SoftFXInfo[nSoftFXBlitter].nZoom; + nHeight = nGameHeight * SoftFXInfo[nSoftFXBlitter].nZoom; + nSoftFXEnlarge = true; + } + + if (!nSoftFXEnlarge) { + nWidth = nGameWidth; + nHeight = nGameHeight; + } + + pRect->left = (pRect->right + pRect->left) / 2; + pRect->left -= nWidth / 2; + pRect->right = pRect->left + nWidth; + + pRect->top = (pRect->bottom + pRect->top) / 2; + pRect->top -= nHeight / 2; + pRect->bottom = pRect->top + nHeight; + + return 0; +} + +static void VidSoftFXRotate() +{ + if (nSoftFXRotate) { + unsigned char* ps; + unsigned char* pd = pSoftFXImage; + if (nSoftFXRotate & 2) { + pd += nSoftFXImageHeight * nSoftFXImagePitch - nVidImageBPP; + } + + switch (nVidImageBPP) { + case 4: { + switch (nSoftFXRotate) { + case 1: { + for (int y = 0; y < nSoftFXImageHeight; y++) { + ps = pVidImage + (nSoftFXImageHeight + nVidImageLeft - 1 - y) * 4; + for (int x = 0; x < nSoftFXImageWidth; x++) { + *(int*)pd = *(int*)ps; + ps += nVidImagePitch; + pd += 4; + } + } + break; + } + case 2: { + for (int y = 0; y < nSoftFXImageHeight; y++) { + ps = pVidImage + y * nVidImagePitch + nVidImageLeft * 2; + for (int x = 0; x < nSoftFXImageWidth; x++) { + *(int*)pd = *(int*)ps; + ps += 4; + pd -= 4; + } + } + break; + } + case 3: { + for (int y = 0; y > 1; + UINT16 *dst0=(UINT16 *)pd; + UINT16 *dst1=(UINT16 *)(pd + nPitch); + UINT16 *src0=(UINT16 *)(ps - nSoftFXImagePitch); + UINT16 *src1=(UINT16 *)ps; + UINT16 *src2=(UINT16 *)(ps + nSoftFXImagePitch); + UINT64 mask = 0x7BEF7BEF7BEF7BEFLL; + if (nVidImageDepth == 15) mask = 0x3DEF3DEF3DEF3DEFLL; + + for (int y = 0; y < nSoftFXImageHeight; y++) { + superscale_line(src0, src1, src2, dst0, nSoftFXImageWidth, &mask); + superscale_line(src2, src1, src0, dst1, nSoftFXImageWidth, &mask); + + src0 = src1; + src1 = src2; + src2 += srcNextline; + + dst0 += nPitch; + dst1 += nPitch; + } +#ifdef __GNUC__ + __asm__ __volatile__( + "emms\n" + ); +#else + __asm { + emms; + } +#endif + break; + } + case FILTER_SUPERSCALE_75SCAN: { + UINT32 srcNextline = nSoftFXImagePitch >> 1; + UINT16 *dst0=(UINT16 *)pd; + UINT16 *dst1=(UINT16 *)(pd + nPitch); + UINT16 *src0=(UINT16 *)(ps - nSoftFXImagePitch); + UINT16 *src1=(UINT16 *)ps; + UINT16 *src2=(UINT16 *)(ps + nSoftFXImagePitch); + UINT64 mask = 0x7BEF7BEF7BEF7BEFLL; + if (nVidImageDepth == 15) mask = 0x3DEF3DEF3DEF3DEFLL; + + for (int y = 0; y < nSoftFXImageHeight; y++) { + superscale_line(src0, src1, src2, dst0, nSoftFXImageWidth, &mask); + superscale_line_75(src2, src1, src0, dst1, nSoftFXImageWidth, &mask); + + src0 = src1; + src1 = src2; + src2 += srcNextline; + + dst0 += nPitch; + dst1 += nPitch; + } +#ifdef __GNUC__ + __asm__ __volatile__( + "emms\n" + ); +#else + __asm { + emms; + } +#endif + break; + } + case FILTER_HQ2X: { // hq2x filter (16BPP -> 32BPP) + hq2x_32(ps, pd, nSoftFXImageWidth, nSoftFXImageHeight, nPitch); + break; + } + case FILTER_HQ3X: { // hq3x filter (16BPP -> 32BPP) + hq3x_32(ps, pd, nSoftFXImageWidth, nSoftFXImageHeight, nPitch); + break; + } + case FILTER_HQ4X: { // hq4x filter (16BPP -> 32BPP) + hq4x_32(ps, pd, nSoftFXImageWidth, nSoftFXImageHeight, nPitch); + break; + } +#endif + case FILTER_HQ2XS_VBA: { // hq2xS filter (16/32BPP only) + if (nVidImageDepth == 16) { + hq2xS(ps, nSoftFXImagePitch, NULL, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight); + } + else if (nVidImageDepth == 32) { + hq2xS32(ps, nSoftFXImagePitch, NULL, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight); + } + break; + } + case FILTER_HQ3XS_VBA: { // hq3xS filter (16/32BPP only) +#if defined _MSC_VER && defined BUILD_X86_ASM + if (nVidImageDepth == 16) { + hq3xS(ps, nSoftFXImagePitch, NULL, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight); + } + else if (nVidImageDepth == 32) { + hq3xS32(ps, nSoftFXImagePitch, NULL, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight); + } + break; +#endif + } + case FILTER_HQ2XS_SNES9X: { + RenderHQ2XS(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, 0); + break; + } + case FILTER_HQ3XS_SNES9X: { + RenderHQ3XS(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, 0); + break; + } + case FILTER_HQ2XBOLD: { + RenderHQ2XS(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, 1); + break; + } + case FILTER_HQ3XBOLD: { + RenderHQ3XS(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, 1); + break; + } + case FILTER_EPXB: { + RenderEPXB(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, nVidImageDepth); + break; + } + case FILTER_EPXC: { + RenderEPXC(ps, nSoftFXImagePitch, pd, nPitch, nSoftFXImageWidth, nSoftFXImageHeight, nVidImageDepth); + break; + } + } +} + +#ifdef SOFTFX_ENABLE_DIRECTX + +int VidSoftFXApplyEffectDirectX(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + DDSURFACEDESC2 ddsd; + + VidSoftFXRotate(); + + // Lock the surface so we can write to it + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (FAILED(pSurf->Lock(pRect, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { + return 1; + } + + VidSoftFXApplyEffect(pSoftFXImage, (unsigned char*)ddsd.lpSurface, ddsd.lPitch); + + pSurf->Unlock(NULL); + + return 0; +} + +#endif + +#ifdef SOFTFX_ENABLE_SDL + +int VidSoftFXApplyEffectSDL(SDL_Surface* pSurf) +{ + VidSoftFXRotate(); + + // Lock the surface so we can write to it + if (SDL_LockSurface(pSurf)) { + return 1; + } + + VidSoftFXApplyEffect(pSoftFXImage, (unsigned char*)pSurf->pixels, pSurf->pitch); + + SDL_UnlockSurface(pSurf); + + return 0; +} + +#endif + +int VidFilterApplyEffect(unsigned char* pd, int pitch) +{ + if (!pd) { + return 1; + } + + VidSoftFXRotate(); + VidSoftFXApplyEffect(pSoftFXImage, pd, pitch); + + return 0; +} diff --git a/src/interface/vid_softfx.h b/src/interface/vid_softfx.h new file mode 100644 index 00000000..523e2f1b --- /dev/null +++ b/src/interface/vid_softfx.h @@ -0,0 +1,60 @@ +// Sotfware effects + +#ifdef BUILD_WIN32 + #define SOFTFX_ENABLE_DIRECTX +#endif +#ifdef BUILD_SDL + #define SOFTFX_ENABLE_SDL +#endif + +#ifdef SOFTFX_ENABLE_DIRECTX + #include "vid_directx_support.h" +#endif +#ifdef SOFTFX_ENABLE_SDL + #include +#endif + +#define FILTER_PLAIN 0 +#define FILTER_ADVMAME_SCALE_2X 1 +#define FILTER_ADVMAME_SCALE_3X 2 +#define FILTER_2XPM_LQ 3 +#define FILTER_2XPM_HQ 4 +#define FILTER_EAGLE 5 +#define FILTER_SUPEREAGLE 6 +#define FILTER_2XSAI 7 +#define FILTER_SUPER_2XSAI 8 +#define FILTER_SUPEREAGLE_VBA 9 +#define FILTER_2XSAI_VBA 10 +#define FILTER_SUPER_2XSAI_VBA 11 +#define FILTER_SUPERSCALE 12 +#define FILTER_SUPERSCALE_75SCAN 13 +#define FILTER_HQ2X 14 +#define FILTER_HQ3X 15 +#define FILTER_HQ4X 16 +#define FILTER_HQ2XS_VBA 17 +#define FILTER_HQ3XS_VBA 18 +#define FILTER_HQ2XS_SNES9X 19 +#define FILTER_HQ3XS_SNES9X 20 +#define FILTER_HQ2XBOLD 21 +#define FILTER_HQ3XBOLD 22 +#define FILTER_EPXB 23 +#define FILTER_EPXC 24 + +TCHAR* VidSoftFXGetEffect(int nEffect); +int VidSoftFXGetZoom(int nEffect); +int VidSoftFXCheckDepth(int nEffect, int nDepth); + +void VidSoftFXExit(); +int VidSoftFXInit(int nBlitter, int nRotate); + +int VidSoftFXScale(RECT* pRect, int nGameWidth, int nGameHeight); + +#ifdef SOFTFX_ENABLE_DIRECTX +int VidSoftFXApplyEffectDirectX(IDirectDrawSurface7* pSurf, RECT* pRect); +#endif + +#ifdef SOFTFX_ENABLE_SDL +int VidSoftFXApplyEffectSDL(SDL_Surface* pSurf); +#endif + +int VidFilterApplyEffect(unsigned char* pd, int pitch); diff --git a/src/interface/vid_support.cpp b/src/interface/vid_support.cpp new file mode 100644 index 00000000..40e2fc27 --- /dev/null +++ b/src/interface/vid_support.cpp @@ -0,0 +1,39 @@ +// Support functions for all blitters +#include "burner.h" +#include "vid_support.h" + +// --------------------------------------------------------------------------- +// General + +static UINT8* pVidSFullImage = NULL; + +void VidSFreeVidImage() +{ + if (pVidSFullImage) { + free(pVidSFullImage); + pVidSFullImage = NULL; + } + pVidImage = NULL; +} + +INT32 VidSAllocVidImage() +{ + INT32 nMemLen = 0; + + VidSFreeVidImage(); + + // Allocate an extra line above and below the image to accomodate effects + nVidImagePitch = nVidImageWidth * ((nVidImageDepth + 7) >> 3); + nMemLen = (nVidImageHeight + 2) * nVidImagePitch; + pVidSFullImage = (UINT8*)malloc(nMemLen); + + if (pVidSFullImage) { + memset(pVidSFullImage, 0, nMemLen); + pVidImage = pVidSFullImage + nVidImagePitch; + return 0; + } else { + pVidImage = NULL; + return 1; + } +} + diff --git a/src/interface/vid_support.h b/src/interface/vid_support.h new file mode 100644 index 00000000..e97fa3ae --- /dev/null +++ b/src/interface/vid_support.h @@ -0,0 +1,2 @@ +void VidSFreeVidImage(); +INT32 VidSAllocVidImage(); diff --git a/src/interface/win32/aud_dsound3.cpp b/src/interface/win32/aud_dsound3.cpp new file mode 100644 index 00000000..b99c5a34 --- /dev/null +++ b/src/interface/win32/aud_dsound3.cpp @@ -0,0 +1,304 @@ +// DirectSound module +#include "burner.h" +#include "aud_dsp.h" +#include + +#include +#define DIRECTSOUND_VERSION 0x0300 // Only need version from DirectX 3 +#include + +#include "dsound_core.h" + +// Sound is split into a series of 'segs', one seg for each frame +// The Loop buffer is a multiple of this seg length. + +static IDirectSound* pDS = NULL; // DirectSound interface +static IDirectSoundBuffer* pdsbPrim = NULL; // Primary buffer +static IDirectSoundBuffer* pdsbLoop = NULL; // (Secondary) Loop buffer +static int cbLoopLen = 0; // Loop length (in bytes) calculated + +int (*DSoundGetNextSound)(int); // Callback used to request more sound + +static int nDSoundFps; // Application fps * 100 +static long nDSoundVol = 0; + +static int DSoundGetNextSoundFiller(int) // int bDraw +{ + if (nAudNextSound == NULL) { + return 1; + } + memset(nAudNextSound, 0, nAudSegLen << 2); // Write silence into the buffer + + return 0; +} + +static inline int DxSetCallback(int (*pCallback)(int)) +{ + if (pCallback == NULL) { + DSoundGetNextSound = DSoundGetNextSoundFiller; + } else { + DSoundGetNextSound = pCallback; + } + + return 0; +} + +static int DxBlankSound() +{ + void *pData = NULL, *pData2 = NULL; + DWORD cbLen = 0, cbLen2 = 0; + + // Lock the Loop buffer + if (FAILED(pdsbLoop->Lock(0, cbLoopLen, &pData, &cbLen, &pData2, &cbLen2, 0))) { + return 1; + } + memset(pData, 0, cbLen); + + // Unlock (2nd 0 is because we wrote nothing to second part) + pdsbLoop->Unlock(pData, cbLen, pData2, 0); + + // Also blank the nAudNextSound buffer + if (nAudNextSound) { + memset(nAudNextSound, 0, nAudSegLen << 2); + } + + return 0; +} + +static int nDSoundNextSeg = 0; // We have filled the sound in the loop up to the beginning of 'nNextSeg' + +#define WRAP_INC(x) { x++; if (x >= nAudSegCount) x = 0; } + +bool bRunFrame = false; + +// This function checks the DSound loop, and if necessary does a callback to update the emulation +static int DxSoundCheck() +{ + int nPlaySeg = 0, nFollowingSeg = 0; + DWORD nPlay = 0, nWrite = 0; + + if (pdsbLoop == NULL) { + return 1; + } + + // We should do nothing until nPlay has left nDSoundNextSeg + pdsbLoop->GetCurrentPosition(&nPlay, &nWrite); + + nPlaySeg = nPlay / (nAudSegLen << 2); + + if (nPlaySeg > nAudSegCount -1 ) { + nPlaySeg = nAudSegCount - 1; + } + if (nPlaySeg < 0) { // important to ensure nPlaySeg clipped for below + nPlaySeg = 0; + } + + if (nDSoundNextSeg == nPlaySeg) { + //Sleep(2); // Don't need to do anything for a bit + //bRunFrame = true; + return 0; + } + + // work out which seg we will fill next + nFollowingSeg = nDSoundNextSeg; + WRAP_INC(nFollowingSeg); + + while (nDSoundNextSeg != nPlaySeg) { + void *pData = NULL, *pData2 = NULL; + DWORD cbLen = 0, cbLen2 = 0; + int bDraw; + + // fill nNextSeg + + // Lock the relevant seg of the loop buffer + if (SUCCEEDED(pdsbLoop->Lock(nDSoundNextSeg * (nAudSegLen << 2), nAudSegLen << 2, &pData, &cbLen, &pData2, &cbLen2, 0))) { + // Locked the segment, so write the sound we calculated last time + memcpy(pData, nAudNextSound, nAudSegLen << 2); + + // Unlock (2nd 0 is because we wrote nothing to second part) + pdsbLoop->Unlock(pData, cbLen, pData2, 0); + } + + bDraw = (nFollowingSeg == nPlaySeg) || bAlwaysDrawFrames; // If this is the last seg of sound, flag bDraw (to draw the graphics) + + if(bDraw) { + DSoundGetNextSound(bDraw); // get more sound into nAudNextSound + } + + if(!bDraw) { + bRunFrame = true; + RunIdle(); + } + + if (nAudDSPModule[0]) { + DspDo(nAudNextSound, nAudSegLen); + } + + nDSoundNextSeg = nFollowingSeg; + WRAP_INC(nFollowingSeg); + } + + return 0; +} + +static int DxSoundExit() +{ + DspExit(); + + if (nAudNextSound) { + free(nAudNextSound); + nAudNextSound = NULL; + } + + DSoundGetNextSound = NULL; + + // Release the (Secondary) Loop Sound Buffer + RELEASE(pdsbLoop); + // Release the Primary Sound Buffer + RELEASE(pdsbPrim); + // Release the DirectSound interface + RELEASE(pDS); + + return 0; +} + +static int DxSoundInit() +{ + int nRet = 0; + DSBUFFERDESC dsbd; + WAVEFORMATEX wfx; + + if (nAudSampleRate <= 0) { + return 1; + } + + nDSoundFps = nAppVirtualFps; + + // Calculate the Seg Length and Loop length (round to nearest sample) + nAudSegLen = (nAudSampleRate[0] * 100 + (nDSoundFps >> 1)) / nDSoundFps; + cbLoopLen = (nAudSegLen * nAudSegCount) << 2; + + // Make the format of the sound + memset(&wfx, 0, sizeof(wfx)); + wfx.cbSize = sizeof(wfx); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; // stereo + wfx.nSamplesPerSec = nAudSampleRate[0]; // sample rate + wfx.wBitsPerSample = 16; // 16-bit + wfx.nBlockAlign = 4; // bytes per sample + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + // Create the DirectSound interface + if (FAILED(_DirectSoundCreate(NULL, &pDS, NULL))) { + return 1; + } + + // Set the coop level + nRet = pDS->SetCooperativeLevel(hScrnWnd, DSSCL_PRIORITY); + + // Make the primary sound buffer + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + if (FAILED(pDS->CreateSoundBuffer(&dsbd, &pdsbPrim, NULL))) { + DxSoundExit(); + return 1; + } + + { + // Set the format of the primary sound buffer (not critical if it fails) + if (nAudSampleRate[0] < 44100) { + wfx.nSamplesPerSec = 44100; + } + pdsbPrim->SetFormat(&wfx); + + wfx.nSamplesPerSec = nAudSampleRate[0]; + } + + // Make the loop sound buffer + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + // A standard secondary buffer (accurate position, plays in the background, and can notify). + dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLVOLUME; + dsbd.dwBufferBytes = cbLoopLen; + dsbd.lpwfxFormat = &wfx; // Same format as the primary buffer + if (FAILED(pDS->CreateSoundBuffer(&dsbd, &pdsbLoop, NULL))) { + AudSoundExit(); + return 1; + } + + nAudNextSound = (short*)malloc(nAudSegLen << 2); // The next sound block to put in the stream + if (nAudNextSound == NULL) { + DxSoundExit(); + return 1; + } + + DxSetCallback(NULL); + + DspInit(); + + return 0; +} + +static int DxSoundPlay() +{ + DxBlankSound(); + pdsbLoop->SetVolume(nDSoundVol); + + // Play the looping buffer + if (FAILED(pdsbLoop->Play(0, 0, DSBPLAY_LOOPING))) { + return 1; + } + bAudPlaying = 1; + + return 0; +} + +static int DxSoundStop() +{ + bAudPlaying = 0; + + if (bAudOkay == 0) { + return 1; + } + + // Stop the looping buffer + pdsbLoop->Stop(); + + return 0; +} + +static int DxSoundSetVolume() +{ + if (nAudVolume == 10000) { + nDSoundVol = DSBVOLUME_MAX; + } else { + if (nAudVolume == 0) { + nDSoundVol = DSBVOLUME_MIN; + } else { + nDSoundVol = DSBVOLUME_MAX - (long)(10000.0 * pow(10.0, nAudVolume / -5000.0)) + 100; + } + } + + if (nDSoundVol < DSBVOLUME_MIN) { + nDSoundVol = DSBVOLUME_MIN; + } + + if (FAILED(pdsbLoop->SetVolume(nDSoundVol))) { + return 0; + } + + return 1; +} + +static int DxGetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + + _sntprintf(szString, MAX_PATH, _T("Audio is delayed by approx. %ims"), int(100000.0 / (nDSoundFps / (nAudSegCount - 1.0)))); + IntInfoAddStringModule(pInfo, szString); + + return 0; +} + +struct AudOut AudOutDx = { DxBlankSound, DxSoundCheck, DxSoundInit, DxSetCallback, DxSoundPlay, DxSoundStop, DxSoundExit, DxSoundSetVolume, DxGetSettings, _T("DirectSound3 audio output") }; diff --git a/src/interface/win32/aud_xaudio2.cpp b/src/interface/win32/aud_xaudio2.cpp new file mode 100644 index 00000000..a37def0d --- /dev/null +++ b/src/interface/win32/aud_xaudio2.cpp @@ -0,0 +1,379 @@ +#include "burner.h" +#include "aud_dsp.h" + +//#ifdef _MSC_VER +#include +#include +#include + +static IXAudio2* pXAudio2 = NULL; +static IXAudio2MasteringVoice* pMasterVoice = NULL; +static IXAudio2SourceVoice* pSourceVoice = NULL; +static XAUDIO2_BUFFER sAudioBuffer; +static XAUDIO2_VOICE_STATE vState; +static IUnknown* pXAPO = NULL; +static bool effectEnable = false; + +int (*XAudio2GetNextSound)(int); + +BYTE* pAudioBuffers = NULL; +int currentBuffer = 0; + +static int cbLoopLen = 0; // Loop length (in bytes) calculated +static int nXAudio2Fps = 0; // Application fps * 100 +static float nXAudio2Vol = 1.0f; + +struct StreamingVoiceContext : public IXAudio2VoiceCallback +{ + HANDLE hBufferEndEvent; + + StreamingVoiceContext() { + hBufferEndEvent = NULL; + hBufferEndEvent = CreateEvent( NULL, FALSE, FALSE, NULL); + } + virtual ~StreamingVoiceContext() { + CloseHandle(hBufferEndEvent); + hBufferEndEvent = NULL; + } + + STDMETHOD_(void, OnBufferEnd) (void */*pBufferContext*/) { + SetEvent(hBufferEndEvent); + } + + // dummies: + STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32 /*BytesRequired*/) {} + STDMETHOD_(void, OnVoiceProcessingPassEnd) () {} + STDMETHOD_(void, OnStreamEnd) () {} + STDMETHOD_(void, OnBufferStart) (void */*pBufferContext*/) {} + STDMETHOD_(void, OnLoopEnd) (void */*pBufferContext*/) {} + STDMETHOD_(void, OnVoiceError) (void */*pBufferContext*/, HRESULT /*Error*/) {}; +}; +StreamingVoiceContext voiceContext; + +static int XAudio2GetNextSoundFiller(int) +{ + if (nAudNextSound == NULL) { + return 1; + } + AudWriteSilence(); + + return 0; +} + +static int XAudio2SetCallback(int (*pCallback)(int)) +{ + if (pCallback == NULL) { + XAudio2GetNextSound = XAudio2GetNextSoundFiller; + } else { + XAudio2GetNextSound = pCallback; + } + + return 0; +} + +static int XAudio2BlankSound() +{ + if (pAudioBuffers) { + memset(pAudioBuffers, 0, cbLoopLen); + } + + // Also blank the nAudNextSound buffer + if (nAudNextSound) { + AudWriteSilence(); + } + + return 0; +} + +static int XAudio2Check() +{ + if (!pSourceVoice || !pAudioBuffers) { + return 1; + } + + while (true) { + pSourceVoice->GetState(&vState); + + assert(vState.BuffersQueued < (unsigned int)nAudSegCount); + + if (vState.BuffersQueued < (unsigned int)nAudSegCount - 1) { + if (vState.BuffersQueued == 0) { + // buffers ran dry + } + // there is at least one free buffer + break; + } else { + // the maximum number of buffers is currently queued + if (bAlwaysDrawFrames) { + // wait for one buffer to finish playing + WaitForSingleObject(voiceContext.hBufferEndEvent, INFINITE); + } else { + // drop current audio frame + //Sleep(2); + return 0; + } + } + } + + XAudio2GetNextSound(true); + + // dsp update + if (nAudDSPModule[1] & 1) { + if (bRunPause) + AudWriteSilence(); + else + DspDo(nAudNextSound, nAudSegLen); + } + + if (nAudDSPModule[1] & 2) { + if (!effectEnable) { + pSourceVoice->EnableEffect(0); + effectEnable = true; + } + } else { + if (effectEnable) { + pSourceVoice->DisableEffect(0); + effectEnable = false; + } + } + + // copy & protect the audio data in own memory area while playing it + memcpy(&pAudioBuffers[currentBuffer * nAudAllocSegLen], nAudNextSound, nAudAllocSegLen); + + sAudioBuffer.AudioBytes = nAudAllocSegLen; + sAudioBuffer.pAudioData = &pAudioBuffers[currentBuffer * nAudAllocSegLen]; + + currentBuffer++; + currentBuffer %= (nAudSegCount); + + HRESULT hr = pSourceVoice->SubmitSourceBuffer(&sAudioBuffer); // send buffer to queue + assert(hr == S_OK); + + return 0; +} + +static int XAudio2EffectInit() +{ + HRESULT hr = XAudio2CreateReverb(&pXAPO); + if (FAILED(hr)) { + return 1; + } + + XAUDIO2_EFFECT_DESCRIPTOR descriptor; + descriptor.InitialState = TRUE; + descriptor.OutputChannels = 2; + descriptor.pEffect = pXAPO; + + XAUDIO2_EFFECT_CHAIN chain; + chain.EffectCount = 1; + chain.pEffectDescriptors = &descriptor; + + hr = pSourceVoice->SetEffectChain(&chain); + if (FAILED(hr)) { + return 1; + } + + if (nAudDSPModule[1] & 2) { + pSourceVoice->EnableEffect(0); + effectEnable = true; + } else { + pSourceVoice->DisableEffect(0); + effectEnable = false; + } + + return 0; +} + +static void XAudio2EffectExit() +{ + RELEASE(pXAPO); +} + +static void XAudio2ExitVoices() +{ + if (pSourceVoice) { + pSourceVoice->Stop(0); + pSourceVoice->DestroyVoice(); + pSourceVoice = NULL; + } + if (pMasterVoice) { + pMasterVoice->DestroyVoice(); + pMasterVoice = NULL; + } +} + +static int XAudio2Exit() +{ + DspExit(); + + // Cleanup XAudio2 + + XAudio2EffectExit(); + + XAudio2ExitVoices(); + + RELEASE(pXAudio2); + CoUninitialize(); + + if (nAudNextSound) { + free(nAudNextSound); + nAudNextSound = NULL; + } + + if (pAudioBuffers) { + free(pAudioBuffers); + pAudioBuffers = NULL; + } + + XAudio2GetNextSound = NULL; + + return 0; +} + +static int XAudio2InitVoices() +{ + HRESULT hr; + + // Create a mastering voice + if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, nAudSampleRate[1], 0, 0, NULL))) { + return 1; + } + + // Make the format of the sound + WAVEFORMATEX wfx; + memset(&wfx, 0, sizeof(wfx)); + wfx.cbSize = sizeof(wfx); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; // stereo + wfx.nSamplesPerSec = nAudSampleRate[1]; // sample rate + wfx.wBitsPerSample = 16; // 16-bit + wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8; // bytes per sample + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + // Create the source voice + if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, &wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &voiceContext, NULL, NULL))) { + return 1; + } + + return 0; +} + +static int XAudio2Init() +{ + if (nAudSampleRate[1] <= 0) { + return 0; + } + + nXAudio2Fps = nAppVirtualFps; + + // Calculate the Seg Length and Loop length (round to nearest sample) + nAudSegLen = (nAudSampleRate[1] * 100 + (nXAudio2Fps >> 1)) / nXAudio2Fps; + nAudAllocSegLen = nAudSegLen << 2; + cbLoopLen = (nAudSegLen * nAudSegCount) << 2; + + // Initialize XAudio2 + + if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) { + return 1; + } + + HRESULT hr; + if (FAILED(hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))) { + CoUninitialize(); + return 1; + } + + if (XAudio2InitVoices()) { + XAudio2Exit(); + return 1; + } + + ZeroMemory(&sAudioBuffer, sizeof(sAudioBuffer)); + + nAudNextSound = (short*)malloc(nAudAllocSegLen); // The next sound block to put in the stream + if (nAudNextSound == NULL) { + XAudio2Exit(); + return 1; + } + + // create own buffers to store sound data because it must not be + // manipulated while the voice plays from it + pAudioBuffers = (BYTE *)malloc(cbLoopLen); + if (pAudioBuffers == NULL) { + XAudio2Exit(); + return 1; + } + currentBuffer = 0; + + XAudio2SetCallback(NULL); + + DspInit(); + + XAudio2EffectInit(); + + return 0; +} + +static int XAudio2Play() +{ + if (pSourceVoice == NULL) { + return 1; + } + + XAudio2BlankSound(); + pSourceVoice->SetVolume(nXAudio2Vol); + + if (FAILED(pSourceVoice->Start(0))) { + return 1; + } + return 0; +} + +static int XAudio2Stop() +{ + if (!bAudOkay) { + return 1; + } + + if (pSourceVoice) { + pSourceVoice->Stop(0); + } + + return 0; +} + +static int XAudio2SetVolume() +{ + if (nAudVolume == 10000) { + nXAudio2Vol = 1.0f; + } else { + if (nAudVolume == 0) { + nXAudio2Vol = 0.0f; + } else { + nXAudio2Vol = 1.0f - (1.0f * pow(10.0, nAudVolume / -5000.0)) + 0.01f; + } + } + + if (nXAudio2Vol < 0.0f) { + nXAudio2Vol = 0.0f; + } + + if (!pSourceVoice || FAILED(pSourceVoice->SetVolume(nXAudio2Vol))) { + return 1; + } + + return 0; +} + +static int XAudio2GetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + _sntprintf(szString, MAX_PATH, _T("Audio is delayed by approx. %ims"), int(100000.0 / (nXAudio2Fps / (nAudSegCount - 1.0)))); + IntInfoAddStringModule(pInfo, szString); + return 0; +} + +struct AudOut AudOutXAudio2 = { XAudio2BlankSound, XAudio2Check, XAudio2Init, XAudio2SetCallback, XAudio2Play, XAudio2Stop, XAudio2Exit, XAudio2SetVolume, XAudio2GetSettings, _T("XAudio2 audio output") }; +//#else +//struct AudOut AudOutXAudio2 = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _T("XAudio2 audio output") }; +//#endif diff --git a/src/interface/win32/cd_isowav.cpp b/src/interface/win32/cd_isowav.cpp new file mode 100644 index 00000000..7233ab83 --- /dev/null +++ b/src/interface/win32/cd_isowav.cpp @@ -0,0 +1,595 @@ +// ---------------------------------------------------------------------------- +// iso/cue/wav support +/*----------------------------------------------------------------------------- +Modified by: CaptainCPS-X +Updates: + (10/24/2011) + - removed libmad and MP3 support + - added my custom DirectSound library to add WAV support + - removed most (if not all) references to MP3 + - modified a few other things as needed +------------------------------------------------------------------------------*/ +#include "burner.h" +#include "cdsound.h" + +#define MAXIMUM_NUMBER_TRACKS (100) + +#define CD_FRAMES_MINUTE (60 * 75) +#define CD_FRAMES_SECOND ( 75) +#define CD_FRAMES_PREGAP ( 2 * 75) + +struct isowavTRACK_DATA { + char Control; + char TrackNumber; + char Address[4]; + TCHAR* Filename; +}; + +struct isowavCDROM_TOC { + char FirstTrack; + char LastTrack; + isowavTRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +}; + +static isowavCDROM_TOC* isowavTOC; + +static FILE* isowavFile = NULL; +static int isowavTrack = 0; +static int isowavLBA = 0; + +// ----------------------------------------------------------------------------- + +static const char* isowavLBAToMSF(const int LBA) +{ + static char address[4]; + + address[0] = 0; + address[1] = LBA / CD_FRAMES_MINUTE; + address[2] = LBA % CD_FRAMES_MINUTE / CD_FRAMES_SECOND; + address[3] = LBA % CD_FRAMES_SECOND; + + return address; +} + +static int isowavMSFToLBA(const char* address) +{ + int LBA; + + LBA = address[3]; + LBA += address[2] * CD_FRAMES_SECOND; + LBA += address[1] * CD_FRAMES_MINUTE; + + return LBA; +} + +// ----------------------------------------------------------------------------- + +static int isowavGetTrackSizes() +{ + // determine the lenght of the .iso / .mp3 files to complete the TOC + + FILE* h; + + for (int i = isowavTOC->FirstTrack - 1; i < isowavTOC->LastTrack; i++) { + + const char* address; + + if (isowavTOC->TrackData[i].Control & 4) { + + // data track + + h = _tfopen(isowavTOC->TrackData[i].Filename, _T("rb")); + if (h == NULL) return 1; + + fseek(h, 0, SEEK_END); + + address = isowavLBAToMSF((ftell(h) + 2047) / 2048 + isowavMSFToLBA(isowavTOC->TrackData[i].Address)); + + if(h) fclose(h); + + } else { + + // audio track + + h = _tfopen(isowavTOC->TrackData[i].Filename, _T("rb")); + if (h == NULL)return 1; + + fseek(h, 0, SEEK_END); + + address = isowavLBAToMSF(((ftell(h) + 2047) / 2048) + isowavMSFToLBA(isowavTOC->TrackData[i].Address)); + if(h) fclose(h); + } + + isowavTOC->TrackData[i + 1].Address[0] += 0; // always 0 [?] + isowavTOC->TrackData[i + 1].Address[1] += address[1]; // M + isowavTOC->TrackData[i + 1].Address[2] += address[2]; // S + isowavTOC->TrackData[i + 1].Address[3] += address[3]; // F + } + + return 0; +} + +static int isowavTestISO() +{ + TCHAR fullname[MAX_PATH]; + TCHAR* filename; + int length = 0; + int offset = 0; + int track = 2; + FILE* h; + + _tcscpy(fullname, CDEmuImage); + length = _tcslen(fullname); + + // assume CD-ROM mode1/2048 format + + if (length <= 4 && (_tcscmp(_T(".iso"), fullname + length - 4) || _tcscmp(_T(".bin"), fullname + length - 4))) { + return 1; + } + + // create a TOC with only the data track first + + isowavTOC->FirstTrack = 1; + isowavTOC->LastTrack = 1; + + isowavTOC->TrackData[0].TrackNumber = 1; + + isowavTOC->TrackData[0].Address[1] = 0; + isowavTOC->TrackData[0].Address[2] = 2; + isowavTOC->TrackData[0].Address[3] = 0; + + isowavTOC->TrackData[0].Filename = (TCHAR*)malloc((length + 1) * sizeof(TCHAR)); + if (isowavTOC->TrackData[0].Filename == NULL) { + return 1; + } + _tcscpy(isowavTOC->TrackData[0].Filename, fullname); + + isowavTOC->TrackData[0].Control = 4; + + // if the filename has a number in it, try to find .mp3 tracks + + filename = ExtractFilename(fullname); + offset = (filename - fullname) + length - 6; + while (offset >= 0 && fullname[offset] != _T('0') && fullname[offset + 1] != _T('1')) { + offset--; + } + if (offset < 0) { + return isowavGetTrackSizes(); + } + + _stprintf(fullname + length - 4, _T(".wav")); + + while (1) { + fullname[offset] = _T('0') + track / 10; fullname[offset + 1] = _T('0') + track % 10; + + if ((h = _tfopen(fullname, _T("rb"))) == NULL) { + break; + } + fclose(h); + + isowavTOC->TrackData[track - 1].TrackNumber = track; + + isowavTOC->TrackData[track - 1].Filename = (TCHAR*)malloc((length + 1) * sizeof(TCHAR)); + if (isowavTOC->TrackData[track - 1].Filename == NULL) { + return 1; + } + _tcscpy(isowavTOC->TrackData[track - 1].Filename, fullname); + + isowavTOC->LastTrack = track; + + track++; + } + + return isowavGetTrackSizes(); +} + +static int isowavParseCueFile() +{ + TCHAR szLine[1024]; + TCHAR szFile[1024]; + TCHAR* s; + TCHAR* t; + FILE* h; + int track = 0; + int length; + + isowavTOC->FirstTrack = 1; + isowavTOC->LastTrack = 1; + + isowavTOC->TrackData[0].Address[1] = 0; + isowavTOC->TrackData[0].Address[2] = 2; + isowavTOC->TrackData[0].Address[3] = 0; + + h = _tfopen(CDEmuImage, _T("rt")); + if (h == NULL) { + return 1; + } + + while (1) { + if (_fgetts(szLine, sizeof(szLine), h) == NULL) { + break; + } + + length = _tcslen(szLine); + // get rid of the linefeed at the end + while (length && (szLine[length - 1] == _T('\r') || szLine[length - 1] == _T('\n'))) { + szLine[length - 1] = 0; + length--; + } + + s = szLine; + + // file info + if ((t = LabelCheck(s, _T("FILE"))) != 0) { + s = t; + + TCHAR* szQuote; + + // read filename + QuoteRead(&szQuote, NULL, s); + + _sntprintf(szFile, ExtractFilename(CDEmuImage) - CDEmuImage, _T("%s"), CDEmuImage); + _sntprintf(szFile + (ExtractFilename(CDEmuImage) - CDEmuImage), 1024 - (ExtractFilename(CDEmuImage) - CDEmuImage), _T("\\%s"), szQuote); + + continue; + } + + // track info + if ((t = LabelCheck(s, _T("TRACK"))) != 0) { + s = t; + + // track number + track = _tcstol(s, &t, 10); + + if (track < 1 || track > MAXIMUM_NUMBER_TRACKS) { + fclose(h); + return 1; + } + + if (track < isowavTOC->FirstTrack) { + isowavTOC->FirstTrack = track; + } + if (track > isowavTOC->LastTrack) { + isowavTOC->LastTrack = track; + } + isowavTOC->TrackData[track - 1].TrackNumber = track; + + isowavTOC->TrackData[track - 1].Filename = (TCHAR*)malloc((_tcslen(szFile) + 1) * sizeof(TCHAR)); + if (isowavTOC->TrackData[track - 1].Filename == NULL) { + fclose(h); + return 1; + } + _tcscpy(isowavTOC->TrackData[track - 1].Filename, szFile); + + s = t; + + // type of track + + if ((t = LabelCheck(s, _T("MODE1/2048"))) != 0) { + isowavTOC->TrackData[track - 1].Control = 4; + + continue; + } + if ((t = LabelCheck(s, _T("AUDIO"))) != 0) { + isowavTOC->TrackData[track - 1].Control = 0; + + continue; + } + + fclose(h); + return 1; + } + + // pregap + if ((t = LabelCheck(s, _T("PREGAP"))) != 0) { + s = t; + + int M, S, F; + + // pregap M + M = _tcstol(s, &t, 10); + s = t + 1; + // pregap S + S = _tcstol(s, &t, 10); + s = t + 1; + // pregap F + F = _tcstol(s, &t, 10); + + if (M < 0 || M > 100 || S < 0 || S > 59 || F < 0 || F > 74) { + fclose(h); + return 1; + } + + isowavTOC->TrackData[track - 1].Address[1] = M; + isowavTOC->TrackData[track - 1].Address[2] = S; + isowavTOC->TrackData[track - 1].Address[3] = F; + + continue; + } + } + + fclose(h); + + return isowavGetTrackSizes(); +} + +// ----------------------------------------------------------------------------- + +static int isowavExit() +{ + wav_exit(); + + if (isowavFile) { + fclose(isowavFile); + isowavFile = NULL; + } + + isowavTrack = 0; + isowavLBA = 0; + + if (isowavTOC) { + for (int i = 0; i < MAXIMUM_NUMBER_TRACKS; i++) { + free(isowavTOC->TrackData[i].Filename); + } + + free(isowavTOC); + isowavTOC = NULL; + } + + return 0; +} + +static int isowavInit() +{ + wav_exit(); + + isowavTOC = (isowavCDROM_TOC*)malloc(sizeof(isowavCDROM_TOC)); + if (isowavTOC == NULL) { + return 1; + } + memset(isowavTOC, 0, sizeof(isowavCDROM_TOC)); + + TCHAR* filename = ExtractFilename(CDEmuImage); + + if (_tcslen(filename) < 4) { + return 1; + } + + if (_tcscmp(_T(".cue"), filename + _tcslen(filename) - 4) == 0) { + if (isowavParseCueFile()) { + dprintf(_T("*** Couldn't parse .cue file\n")); + isowavExit(); + + return 1; + } + } else { + if (isowavTestISO()) { + dprintf(_T("*** Couldn't find .iso / .bin file\n")); + isowavExit(); + + return 1; + } + } + + dprintf(_T(" CD image TOC read\n")); + + for (int i = isowavTOC->FirstTrack - 1; i < isowavTOC->LastTrack; i++) { + dprintf(_T(" track %2i start %02i:%02i:%02i control 0x%02X %s\n"), isowavTOC->TrackData[i].TrackNumber, isowavTOC->TrackData[i].Address[1], isowavTOC->TrackData[i].Address[2], isowavTOC->TrackData[i].Address[3], isowavTOC->TrackData[i].Control, isowavTOC->TrackData[i].Filename); + } + dprintf(_T(" total running time %02i:%02i:%02i\n"), isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[1], isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[2], isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[3]); + + CDEmuStatus = idle; + + return 0; +} + +TCHAR* GetIsoPath() +{ + if(isowavTOC) { + return isowavTOC->TrackData[0].Filename; + } + return NULL; +} + +static int isowavStop() +{ + wav_stop(); + + if (isowavFile) { + fclose(isowavFile); + isowavFile = NULL; + } + CDEmuStatus = idle; + return 0; +} + +static int isowavPlayLBA(int LBA) +{ + isowavLBA = LBA; + + for (isowavTrack = isowavTOC->FirstTrack - 1; isowavTrack < isowavTOC->LastTrack; isowavTrack++) { + if (isowavLBA < isowavMSFToLBA(isowavTOC->TrackData[isowavTrack + 1].Address)) { + break; + } + } + + if (isowavTrack >= isowavTOC->LastTrack) { + return 1; + } + + bprintf(PRINT_IMPORTANT, _T(" playing track %2i - %s\n"), isowavTrack + 1, isowavTOC->TrackData[isowavTrack].Filename); + + isowavFile = _tfopen(isowavTOC->TrackData[isowavTrack].Filename, _T("rb")); + if (isowavFile == NULL) { + return 1; + } + + if( _tcsstr(isowavTOC->TrackData[isowavTrack].Filename, _T(".wav")) || _tcsstr(isowavTOC->TrackData[isowavTrack].Filename, _T(".WAV"))) { + // is a wav, no need to keep this file pointer + if (isowavFile) { + fclose(isowavFile); + isowavFile = NULL; + } + + if(wav_open(isowavTOC->TrackData[isowavTrack].Filename)) { + wav_play(); + } else { + // error creating the WAV stream + return 1; + } + } + + //dprintf(_T("*** WAV: wBitsPerSample: %d \n"), wav->g_pStreamingSound->m_pWaveFile->m_pwfx->wBitsPerSample); + //dprintf(_T("*** WAV: nAvgBytesPerSec: %d \n"), wav->g_pStreamingSound->m_pWaveFile->m_pwfx->nAvgBytesPerSec); + //dprintf(_T("*** WAV: m_dwSize: %d \n"), wav->g_pStreamingSound->m_pWaveFile->m_dwSize); + //dprintf(_T("*** WAV: nBlockAlign: %d \n"), wav->g_pStreamingSound->m_pWaveFile->m_pwfx->nBlockAlign); + + isowavLBA = isowavMSFToLBA(isowavTOC->TrackData[isowavTrack].Address); + CDEmuStatus = playing; + + return 0; +} + +static int isowavPlay(unsigned char M, unsigned char S, unsigned char F) +{ + const char address[] = { 0, M, S, F }; + + return isowavPlayLBA(isowavMSFToLBA(address)); +} + +static int isowavLoadSector(int LBA, char* pBuffer) +{ + LBA += CD_FRAMES_PREGAP; + + if (LBA != isowavLBA) { + + int track; + + for (track = isowavTOC->FirstTrack - 1; track < isowavTOC->LastTrack; track++) { + if (LBA < isowavMSFToLBA(isowavTOC->TrackData[track + 1].Address)) { + break; + } + } + + if (isowavFile == NULL || track != isowavTrack) { + isowavStop(); + + isowavTrack = track; + + bprintf(PRINT_IMPORTANT, _T(" reading track %2i - %s\n"), isowavTrack + 1, isowavTOC->TrackData[isowavTrack].Filename); + + isowavFile = _tfopen(isowavTOC->TrackData[isowavTrack].Filename, _T("rb")); + if (isowavFile == NULL) { + return 0; + } + } + + if (fseek(isowavFile, (LBA - isowavMSFToLBA(isowavTOC->TrackData[isowavTrack].Address)) * 2048, SEEK_SET)) { + dprintf(_T("*** couldn't seek\n")); + + return 0; + } + + isowavLBA = (ftell(isowavFile) + 2047) / 2048; + + CDEmuStatus = reading; + } + + if (fread(pBuffer, 1, 2048, isowavFile) <= 0) { + dprintf(_T("*** couldn't read from file\n")); + + isowavStop(); + + return 0; + } + + isowavLBA = isowavMSFToLBA(isowavTOC->TrackData[isowavTrack].Address) + (ftell(isowavFile) + 2047) / 2048; + + return isowavLBA - CD_FRAMES_PREGAP; +} + +static unsigned char* isowavReadTOC(int track) +{ + static unsigned char TOCEntry[4]; + + if (track == -1) { + TOCEntry[0] = isowavTOC->FirstTrack - 1; + TOCEntry[1] = isowavTOC->LastTrack; + TOCEntry[2] = 0; + TOCEntry[3] = 0; + + return TOCEntry; + } + if (track == -2) { + TOCEntry[0] = isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[1]; + TOCEntry[1] = isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[2]; + TOCEntry[2] = isowavTOC->TrackData[(int)isowavTOC->LastTrack].Address[3]; + + TOCEntry[3] = 0; + + return TOCEntry; + } + + if (track >= isowavTOC->FirstTrack - 1 && track <= isowavTOC->LastTrack) { + TOCEntry[0] = isowavTOC->TrackData[track - 1].Address[1]; + TOCEntry[1] = isowavTOC->TrackData[track - 1].Address[2]; + TOCEntry[2] = isowavTOC->TrackData[track - 1].Address[3]; + TOCEntry[3] = isowavTOC->TrackData[track - 1].Control; + } + + return TOCEntry; +} + +static unsigned char* isowavReadQChannel() +{ + static unsigned char QChannelData[8]; + + switch (CDEmuStatus) { + case reading: + case playing: { + const char* AddressAbs = isowavLBAToMSF(isowavLBA); + const char* AddressRel = isowavLBAToMSF(isowavLBA - isowavMSFToLBA(isowavTOC->TrackData[isowavTrack].Address)); + + QChannelData[0] = isowavTOC->TrackData[isowavTrack].TrackNumber; + + QChannelData[1] = AddressAbs[1]; + QChannelData[2] = AddressAbs[2]; + QChannelData[3] = AddressAbs[3]; + + QChannelData[4] = AddressRel[1]; + QChannelData[5] = AddressRel[2]; + QChannelData[6] = AddressRel[3]; + + QChannelData[7] = isowavTOC->TrackData[isowavTrack].Control; + + break; + } + case paused: { + break; + } + default: { + memset(QChannelData, 0, sizeof(QChannelData)); + } + } + + return QChannelData; +} + +static int isowavGetSoundBuffer(short* /*buffer*/, int /*samples*/) +{ + // --------------------------------------------------------------------- + // TODO: + // Port the old 'isomp3GetSoundBuffer()' function from 'cd_isomp3.cpp' + // to use WAVE stream data, porting that function will fix the + // 00:00 progress status on the main NeoGeo CD BIOS menu. + // --------------------------------------------------------------------- + + return 0; +} + +static int isowavGetSettings(InterfaceInfo* /*pInfo*/) +{ + return 0; +} + +struct CDEmuDo isowavDo = { isowavExit, isowavInit, isowavStop, isowavPlay, isowavLoadSector, isowavReadTOC, isowavReadQChannel, isowavGetSoundBuffer, isowavGetSettings, _T("cue/iso/wav CD emulation") }; diff --git a/src/interface/win32/cdsound.cpp b/src/interface/win32/cdsound.cpp new file mode 100644 index 00000000..4813501a --- /dev/null +++ b/src/interface/win32/cdsound.cpp @@ -0,0 +1,411 @@ +#include "burner.h" +#include "cdsound.h" + +WavClass::WavClass() +{ + m_DirectSound = 0; + m_primaryBuffer = 0; + m_secondaryBuffer1 = 0; +} + +WavClass::WavClass(const WavClass&) +{ + // +} + +WavClass::~WavClass() +{ + // +} + +bool WavClass::Initialize(HWND hwnd, TCHAR* szFile) +{ + bool result; + + // Initialize direct sound and the primary sound buffer. + result = InitializeDirectSound(hwnd); + if(!result) + { + return false; + } + + // Load a wave audio file onto a secondary buffer. + result = LoadWaveFile(szFile, &m_secondaryBuffer1); + if(!result) + { + return false; + } + + return true; +} + +void WavClass::Shutdown() +{ + // Release the secondary buffer. + ShutdownWaveFile(&m_secondaryBuffer1); + + // Shutdown the Direct Sound API. + ShutdownDirectSound(); + + return; +} + +bool WavClass::InitializeDirectSound(HWND hwnd) +{ + HRESULT result; + DSBUFFERDESC bufferDesc; + WAVEFORMATEX waveFormat; + + // Initialize the direct sound interface pointer for the default sound device. + result = _DirectSoundCreate(NULL, &m_DirectSound, NULL); + if(FAILED(result)) + { + return false; + } + + // Set the cooperative level to priority so the format of the primary sound buffer can be modified. + result = m_DirectSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY); + if(FAILED(result)) + { + return false; + } + + GUID guidNULL; + memset(&guidNULL,0,sizeof(GUID)); + + // Setup the primary buffer description. + bufferDesc.dwSize = sizeof(DSBUFFERDESC); + bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; + bufferDesc.dwBufferBytes = 0; + bufferDesc.dwReserved = 0; + bufferDesc.lpwfxFormat = NULL; + bufferDesc.guid3DAlgorithm = guidNULL; //GUID_NULL; + + // Get control of the primary sound buffer on the default sound device. + result = m_DirectSound->CreateSoundBuffer(&bufferDesc, &m_primaryBuffer, NULL); + if(FAILED(result)) + { + return false; + } + + // Setup the format of the primary sound bufffer. + // In this case it is a .WAV file recorded at 44,100 samples per second in 16-bit stereo (cd audio format). + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nSamplesPerSec = 44100; + waveFormat.wBitsPerSample = 16; + waveFormat.nChannels = 2; + waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + waveFormat.cbSize = 0; + + // Set the primary buffer to be the wave format specified. + result = m_primaryBuffer->SetFormat(&waveFormat); + if(FAILED(result)) + { + return false; + } + + return true; +} + +void WavClass::ShutdownDirectSound() +{ + // Release the primary sound buffer pointer. + if(m_primaryBuffer) + { + m_primaryBuffer->Release(); + m_primaryBuffer = 0; + } + + // Release the direct sound interface pointer. + if(m_DirectSound) + { + m_DirectSound->Release(); + m_DirectSound = 0; + } + + return; +} + +bool WavClass::LoadWaveFile(TCHAR* filename, IDirectSoundBuffer** secondaryBuffer) +{ + FILE* filePtr; + unsigned int count; + WaveHeaderType waveFileHeader; + WAVEFORMATEX waveFormat; + DSBUFFERDESC bufferDesc; + HRESULT result; + IDirectSoundBuffer* tempBuffer; + unsigned char* waveData; + unsigned char* bufferPtr; + unsigned long bufferSize; + + + // Open the wave file in binary. + filePtr = _tfopen(filename, _T("rb")); + if(!filePtr) + { + return false; + } + + // Read in the wave file header. + count = fread(&waveFileHeader, sizeof(waveFileHeader), 1, filePtr); + if(count != 1) + { + return false; + } + + // Check that the chunk ID is the RIFF format. + if((waveFileHeader.chunkId[0] != 'R') || (waveFileHeader.chunkId[1] != 'I') || + (waveFileHeader.chunkId[2] != 'F') || (waveFileHeader.chunkId[3] != 'F')) + { + return false; + } + + // Check that the file format is the WAVE format. + if((waveFileHeader.format[0] != 'W') || (waveFileHeader.format[1] != 'A') || + (waveFileHeader.format[2] != 'V') || (waveFileHeader.format[3] != 'E')) + { + return false; + } + + // Check that the sub chunk ID is the fmt format. + if((waveFileHeader.subChunkId[0] != 'f') || (waveFileHeader.subChunkId[1] != 'm') || + (waveFileHeader.subChunkId[2] != 't') || (waveFileHeader.subChunkId[3] != ' ')) + { + return false; + } + + // Check that the audio format is WAVE_FORMAT_PCM. + if(waveFileHeader.audioFormat != WAVE_FORMAT_PCM) + { + return false; + } + + // Check that the wave file was recorded in stereo format. + if(waveFileHeader.numChannels != 2) + { + return false; + } + + // Check that the wave file was recorded at a sample rate of 44.1 KHz. + if(waveFileHeader.sampleRate != 44100) + { + return false; + } + + // Ensure that the wave file was recorded in 16 bit format. + if(waveFileHeader.bitsPerSample != 16) + { + return false; + } + + // Check for the data chunk header. + if((waveFileHeader.dataChunkId[0] != 'd') || (waveFileHeader.dataChunkId[1] != 'a') || + (waveFileHeader.dataChunkId[2] != 't') || (waveFileHeader.dataChunkId[3] != 'a')) + { + return false; + } + + // Set the wave format of secondary buffer that this wave file will be loaded onto. + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nSamplesPerSec = 44100; + waveFormat.wBitsPerSample = 16; + waveFormat.nChannels = 2; + waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + waveFormat.cbSize = 0; + + GUID guidNULL; + memset(&guidNULL,0,sizeof(GUID)); + + // Set the buffer description of the secondary sound buffer that the wave file will be loaded onto. + bufferDesc.dwSize = sizeof(DSBUFFERDESC); + bufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY; + bufferDesc.dwBufferBytes = waveFileHeader.dataSize; + bufferDesc.dwReserved = 0; + bufferDesc.lpwfxFormat = &waveFormat; + bufferDesc.guid3DAlgorithm = guidNULL; //GUID_NULL; + + // Create a temporary sound buffer with the specific buffer settings. + result = m_DirectSound->CreateSoundBuffer(&bufferDesc, &tempBuffer, NULL); + if(FAILED(result)) + { + return false; + } + + // Test the buffer format against the direct sound 8 interface and create the secondary buffer. + result = tempBuffer->QueryInterface(IID_IDirectSoundBuffer, (void**)&*secondaryBuffer); + if(FAILED(result)) + { + return false; + } + + // Release the temporary buffer. + tempBuffer->Release(); + tempBuffer = 0; + + // Move to the beginning of the wave data which starts at the end of the data chunk header. + fseek(filePtr, sizeof(WaveHeaderType), SEEK_SET); + + // Create a temporary buffer to hold the wave file data. + waveData = new unsigned char[waveFileHeader.dataSize]; + if(!waveData) + { + return false; + } + + // Read in the wave file data into the newly created buffer. + count = fread(waveData, 1, waveFileHeader.dataSize, filePtr); + if(count != waveFileHeader.dataSize) + { + return false; + } + + // Close the file once done reading. + int error = fclose(filePtr); + if(error != 0) + { + return false; + } + + // Lock the secondary buffer to write wave data into it. + result = (*secondaryBuffer)->Lock(0, waveFileHeader.dataSize, (void**)&bufferPtr, (DWORD*)&bufferSize, NULL, 0, 0); + if(FAILED(result)) + { + return false; + } + + // Copy the wave data into the buffer. + memcpy(bufferPtr, waveData, waveFileHeader.dataSize); + + // Unlock the secondary buffer after the data has been written to it. + result = (*secondaryBuffer)->Unlock((void*)bufferPtr, bufferSize, NULL, 0); + if(FAILED(result)) + { + return false; + } + + // Release the wave data since it was copied into the secondary buffer. + delete [] waveData; + waveData = 0; + + return true; +} + +void WavClass::ShutdownWaveFile(IDirectSoundBuffer** secondaryBuffer) +{ + // Release the secondary sound buffer. + if(*secondaryBuffer) + { + (*secondaryBuffer)->Release(); + *secondaryBuffer = 0; + } + + return; +} + +#include "cd_interface.h" + +WavClass* wav; +extern HWND hScrnWnd; + +void wav_exit() +{ + if(wav) { + wav_stop(); + wav->Shutdown(); + wav = NULL; + } +} + +int wav_open(TCHAR* szFile) +{ + wav_exit(); + + if(hScrnWnd) { + wav = new WavClass; + wav->Initialize(hScrnWnd, szFile); + } else { + return 0; + } + + return 1; +} + +void wav_stop() +{ + if(!wav) return; + + wav->GetSecondaryBuffer()->Stop(); + wav->GetSecondaryBuffer()->SetCurrentPosition( 0 ); +} + +void wav_play() +{ + if(!wav) return; + + HRESULT result; + + // Play the contents of the secondary sound buffer. + IDirectSoundBuffer* m_secondaryBuffer1 = wav->GetSecondaryBuffer(); + if(!m_secondaryBuffer1) { + // + return; + } + + // Set volume of the buffer to 100%. + result = m_secondaryBuffer1->SetVolume(DSBVOLUME_MAX); + if(FAILED(result)) + { + return; + } + + result = m_secondaryBuffer1->Play(0, 0, DSBPLAY_LOOPING); + if(FAILED(result)) { + // + return; + } +} + +void wav_pause(bool bResume) +{ + if(!wav) return; + + if(!bResume) + { + DWORD pdwStatus; + wav->GetSecondaryBuffer()->GetStatus(&pdwStatus); + if((pdwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING) + { + HRESULT result; + result = wav->GetSecondaryBuffer()->Stop(); + if(FAILED(result)) { + // + } + } + + } else { + DWORD pdwStatus; + wav->GetSecondaryBuffer()->GetStatus(&pdwStatus); + if((pdwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING) + { + if(CDEmuGetStatus() == playing) + { + HRESULT result; + + // Set volume of the buffer to 100%. + result = wav->GetSecondaryBuffer()->SetVolume(DSBVOLUME_MAX); + if(FAILED(result)) + { + return; + } + + result = wav->GetSecondaryBuffer()->Play(0, 0, DSBPLAY_LOOPING); + if(FAILED(result)) { + // + } + } + } + } +} diff --git a/src/interface/win32/cdsound.h b/src/interface/win32/cdsound.h new file mode 100644 index 00000000..94d0b276 --- /dev/null +++ b/src/interface/win32/cdsound.h @@ -0,0 +1,58 @@ +#ifndef _WavClass_H_ +#define _WavClass_H_ + +//#include +#include "dsound_core.h" + +class WavClass +{ +private: + struct WaveHeaderType + { + char chunkId[4]; + unsigned long chunkSize; + char format[4]; + char subChunkId[4]; + unsigned long subChunkSize; + unsigned short audioFormat; + unsigned short numChannels; + unsigned long sampleRate; + unsigned long bytesPerSecond; + unsigned short blockAlign; + unsigned short bitsPerSample; + char dataChunkId[4]; + unsigned long dataSize; + }; + +public: + WavClass(); + WavClass(const WavClass&); + ~WavClass(); + + bool Initialize(HWND, TCHAR*); + void Shutdown(); + + bool InitializeDirectSound(HWND); + void ShutdownDirectSound(); + + bool LoadWaveFile(TCHAR*, IDirectSoundBuffer**); + void ShutdownWaveFile(IDirectSoundBuffer**); + + bool PlayWaveFile(); + + IDirectSound* GetDirectSound() { return m_DirectSound; } + IDirectSoundBuffer* GetPrimaryBuffer() { return m_primaryBuffer; } + IDirectSoundBuffer* GetSecondaryBuffer() { return m_secondaryBuffer1; } + +private: + IDirectSound* m_DirectSound; + IDirectSoundBuffer* m_primaryBuffer; + IDirectSoundBuffer* m_secondaryBuffer1; +}; + +void wav_exit(); +int wav_open(TCHAR* szFile); +void wav_stop(); +void wav_play(); + +#endif diff --git a/src/interface/win32/ddraw_core.cpp b/src/interface/win32/ddraw_core.cpp new file mode 100644 index 00000000..2cf61c30 --- /dev/null +++ b/src/interface/win32/ddraw_core.cpp @@ -0,0 +1,72 @@ +#include "burner.h" +#include "ddraw_core.h" + +// DirectDrawCreateEx +HRESULT (WINAPI* _DirectDrawCreateEx) (GUID FAR*, LPVOID*, REFIID, IUnknown FAR*); +HRESULT WINAPI Empty_DirectDrawCreateEx (GUID FAR*, LPVOID*, REFIID, IUnknown FAR*) { return 0; } + +// DirectDrawCreateClipper +HRESULT (WINAPI* _DirectDrawCreateClipper) (DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR*); +HRESULT WINAPI Empty_DirectDrawCreateClipper (DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR*) { return 0; } + +// DirectDrawEnumerateEx +#ifdef UNICODE +HRESULT (WINAPI* _DirectDrawEnumerateEx) (LPDDENUMCALLBACKEXW, LPVOID, DWORD); +HRESULT WINAPI Empty_DirectDrawEnumerateEx (LPDDENUMCALLBACKEXW, LPVOID, DWORD) { return 0; } +#else +HRESULT (WINAPI* _DirectDrawEnumerateEx) (LPDDENUMCALLBACKEXA, LPVOID, DWORD); +HRESULT WINAPI Empty_DirectDrawEnumerateEx (LPDDENUMCALLBACKEXA, LPVOID, DWORD) { return 0; } +#endif + +static HINSTANCE hDDCore; +static BOOL nDDCoreInit = FALSE; + +/* +static void DDCore_Exit() +{ + FreeLibrary(hDDCore); +} +*/ + +// Macro for easy handling of functions +#define _LOADFN(_rettype, _name, _empty, _params, _hinst, _str ) \ + \ + _name = (_rettype (WINAPI *)_params) GetProcAddress(_hinst, _str); \ + \ + if(!_name) { \ + _name = _empty; \ + return 0; \ + } + +static INT32 DDCore_GetFunctions() +{ + if(!nDDCoreInit) return 0; + + _LOADFN(HRESULT, _DirectDrawCreateEx, Empty_DirectDrawCreateEx, (GUID FAR*, LPVOID*, REFIID, IUnknown FAR*), hDDCore, "DirectDrawCreateEx"); + _LOADFN(HRESULT, _DirectDrawCreateClipper, Empty_DirectDrawCreateClipper, (DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR*), hDDCore, "DirectDrawCreateClipper"); +#ifdef UNICODE + _LOADFN(HRESULT, _DirectDrawEnumerateEx, Empty_DirectDrawEnumerateEx, (LPDDENUMCALLBACKEXW, LPVOID, DWORD), hDDCore, "DirectDrawEnumerateExW"); +#else + _LOADFN(HRESULT, _DirectDrawEnumerateEx, Empty_DirectDrawEnumerateEx, (LPDDENUMCALLBACKEXA, LPVOID, DWORD), hDDCore, "DirectDrawEnumerateExA"); +#endif + return 1; +} + +INT32 DDCore_Init() +{ + hDDCore = LoadLibrary(_T("ddraw.dll")); + + if(!hDDCore) { + MessageBox(NULL, _T("Loading of DDRAW.DLL failed."), _T("Error"), MB_OK | MB_ICONERROR); + nDDCoreInit = FALSE; + return 0; + } + + nDDCoreInit = TRUE; + if(!DDCore_GetFunctions()) { + MessageBox(NULL, _T("There was a problem while loading functions from DDRAW.DLL"), _T("Error"), MB_OK | MB_ICONERROR); + return 0; + } + + return 1; +} diff --git a/src/interface/win32/ddraw_core.h b/src/interface/win32/ddraw_core.h new file mode 100644 index 00000000..bb7b26f5 --- /dev/null +++ b/src/interface/win32/ddraw_core.h @@ -0,0 +1,21 @@ +#ifndef _DDRAW_CORE_ +#define _DDRAW_CORE_ + +#include + +// DirectDrawCreateEx +extern HRESULT (WINAPI* _DirectDrawCreateEx) (GUID FAR*, LPVOID*, REFIID, IUnknown FAR*); + +// DirectDrawCreateClipper +extern HRESULT (WINAPI* _DirectDrawCreateClipper) (DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR*); + +// DirectDrawEnumerateEx +#ifdef UNICODE +extern HRESULT (WINAPI* _DirectDrawEnumerateEx) (LPDDENUMCALLBACKEXW, LPVOID, DWORD); +#else +extern HRESULT (WINAPI* _DirectDrawEnumerateEx) (LPDDENUMCALLBACKEXA, LPVOID, DWORD); +#endif + +INT32 DDCore_Init(); + +#endif diff --git a/src/interface/win32/dinput_core.cpp b/src/interface/win32/dinput_core.cpp new file mode 100644 index 00000000..f1c53fa2 --- /dev/null +++ b/src/interface/win32/dinput_core.cpp @@ -0,0 +1,602 @@ +#include "burner.h" +#include "dinput_core.h" + +#ifndef DIDFT_OPTIONAL +#define DIDFT_OPTIONAL 0x80000000 +#endif + +#define numObjects(x) (sizeof(x) / sizeof(x[0])) + +static const DIOBJECTDATAFORMAT dfDIJoystick[] = { + { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, +}; + +const DIDATAFORMAT c_dfDIJoystick = { + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_ABSAXIS, + sizeof(DIJOYSTATE), + numObjects(dfDIJoystick), + (LPDIOBJECTDATAFORMAT)dfDIJoystick +}; + +static const DIOBJECTDATAFORMAT dfDIJoystick2[] = { + { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(11),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(12),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(13),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(14),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(15),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(16),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(17),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(18),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(19),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(20),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(21),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(22),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(23),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(24),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(25),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(26),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(27),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(28),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(29),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(30),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(31),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(32),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(33),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(34),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(35),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(36),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(37),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(38),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(39),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(40),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(41),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(42),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(43),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(44),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(45),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(46),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(47),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(48),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(49),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(50),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(51),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(52),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(53),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(54),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(55),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(56),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(57),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(58),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(59),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(60),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(61),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(62),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(63),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(64),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(65),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(66),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(67),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(68),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(69),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(70),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(71),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(72),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(73),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(74),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(75),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(76),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(77),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(78),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(79),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(80),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(81),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(82),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(83),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(84),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(85),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(86),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(87),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(88),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(89),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(90),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(91),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(92),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(93),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(94),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(95),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(96),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(97),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(98),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(99),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(100),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(101),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(102),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(103),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(104),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(105),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(106),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(107),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(108),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(109),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(110),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(111),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(112),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(113),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(114),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(115),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(116),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(117),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(118),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(119),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(120),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(121),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(122),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(123),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(124),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(125),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(126),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { NULL,DIJOFS_BUTTON(127),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, + { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lVX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lVY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lVZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lVRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lVRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lVRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglVSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lAX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lAY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lAZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lARx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lARy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lARz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglASlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_XAxis,FIELD_OFFSET(DIJOYSTATE2,lFX),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_YAxis,FIELD_OFFSET(DIJOYSTATE2,lFY),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_ZAxis,FIELD_OFFSET(DIJOYSTATE2,lFZ),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RxAxis,FIELD_OFFSET(DIJOYSTATE2,lFRx),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RyAxis,FIELD_OFFSET(DIJOYSTATE2,lFRy),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_RzAxis,FIELD_OFFSET(DIJOYSTATE2,lFRz),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[0]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, + { &GUID_Slider,FIELD_OFFSET(DIJOYSTATE2,rglFSlider[1]),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, +}; + +const DIDATAFORMAT c_dfDIJoystick2 = { + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_ABSAXIS, + sizeof(DIJOYSTATE2), + numObjects(dfDIJoystick2), + (LPDIOBJECTDATAFORMAT)dfDIJoystick2 +}; + +static const DIOBJECTDATAFORMAT dfDIMouse[] = { + { &GUID_XAxis, DIMOFS_X, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_YAxis, DIMOFS_Y, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_ZAxis, DIMOFS_Z, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_Button, DIMOFS_BUTTON0, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON1, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON2, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON3, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 } +}; + +const DIDATAFORMAT c_dfDIMouse = { + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_RELAXIS, + sizeof(DIMOUSESTATE), + numObjects(dfDIMouse), + (LPDIOBJECTDATAFORMAT)dfDIMouse +}; + +static const DIOBJECTDATAFORMAT dfDIMouse2[] = { + { &GUID_XAxis, DIMOFS_X, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_YAxis, DIMOFS_Y, DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_ZAxis, DIMOFS_Z, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_AXIS, 0 }, + { &GUID_Button, DIMOFS_BUTTON0, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON1, DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON2, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON3, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON4, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON5, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON6, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 }, + { &GUID_Button, DIMOFS_BUTTON7, DIDFT_OPTIONAL | DIDFT_ANYINSTANCE | DIDFT_BUTTON, 0 } +}; + +const DIDATAFORMAT c_dfDIMouse2 = { + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_RELAXIS, + sizeof(DIMOUSESTATE2), + numObjects(dfDIMouse2), + (LPDIOBJECTDATAFORMAT)dfDIMouse2 +}; + +static const DIOBJECTDATAFORMAT dfDIKeyboard[] = { + { &GUID_Key,0,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(0),0}, + { &GUID_Key,1,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(1),0}, + { &GUID_Key,2,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(2),0}, + { &GUID_Key,3,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(3),0}, + { &GUID_Key,4,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(4),0}, + { &GUID_Key,5,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(5),0}, + { &GUID_Key,6,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(6),0}, + { &GUID_Key,7,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(7),0}, + { &GUID_Key,8,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(8),0}, + { &GUID_Key,9,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(9),0}, + { &GUID_Key,10,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(10),0}, + { &GUID_Key,11,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(11),0}, + { &GUID_Key,12,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(12),0}, + { &GUID_Key,13,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(13),0}, + { &GUID_Key,14,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(14),0}, + { &GUID_Key,15,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(15),0}, + { &GUID_Key,16,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(16),0}, + { &GUID_Key,17,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(17),0}, + { &GUID_Key,18,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(18),0}, + { &GUID_Key,19,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(19),0}, + { &GUID_Key,20,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(20),0}, + { &GUID_Key,21,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(21),0}, + { &GUID_Key,22,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(22),0}, + { &GUID_Key,23,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(23),0}, + { &GUID_Key,24,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(24),0}, + { &GUID_Key,25,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(25),0}, + { &GUID_Key,26,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(26),0}, + { &GUID_Key,27,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(27),0}, + { &GUID_Key,28,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(28),0}, + { &GUID_Key,29,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(29),0}, + { &GUID_Key,30,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(30),0}, + { &GUID_Key,31,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(31),0}, + { &GUID_Key,32,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(32),0}, + { &GUID_Key,33,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(33),0}, + { &GUID_Key,34,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(34),0}, + { &GUID_Key,35,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(35),0}, + { &GUID_Key,36,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(36),0}, + { &GUID_Key,37,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(37),0}, + { &GUID_Key,38,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(38),0}, + { &GUID_Key,39,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(39),0}, + { &GUID_Key,40,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(40),0}, + { &GUID_Key,41,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(41),0}, + { &GUID_Key,42,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(42),0}, + { &GUID_Key,43,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(43),0}, + { &GUID_Key,44,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(44),0}, + { &GUID_Key,45,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(45),0}, + { &GUID_Key,46,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(46),0}, + { &GUID_Key,47,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(47),0}, + { &GUID_Key,48,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(48),0}, + { &GUID_Key,49,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(49),0}, + { &GUID_Key,50,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(50),0}, + { &GUID_Key,51,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(51),0}, + { &GUID_Key,52,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(52),0}, + { &GUID_Key,53,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(53),0}, + { &GUID_Key,54,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(54),0}, + { &GUID_Key,55,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(55),0}, + { &GUID_Key,56,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(56),0}, + { &GUID_Key,57,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(57),0}, + { &GUID_Key,58,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(58),0}, + { &GUID_Key,59,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(59),0}, + { &GUID_Key,60,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(60),0}, + { &GUID_Key,61,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(61),0}, + { &GUID_Key,62,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(62),0}, + { &GUID_Key,63,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(63),0}, + { &GUID_Key,64,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(64),0}, + { &GUID_Key,65,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(65),0}, + { &GUID_Key,66,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(66),0}, + { &GUID_Key,67,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(67),0}, + { &GUID_Key,68,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(68),0}, + { &GUID_Key,69,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(69),0}, + { &GUID_Key,70,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(70),0}, + { &GUID_Key,71,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(71),0}, + { &GUID_Key,72,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(72),0}, + { &GUID_Key,73,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(73),0}, + { &GUID_Key,74,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(74),0}, + { &GUID_Key,75,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(75),0}, + { &GUID_Key,76,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(76),0}, + { &GUID_Key,77,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(77),0}, + { &GUID_Key,78,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(78),0}, + { &GUID_Key,79,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(79),0}, + { &GUID_Key,80,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(80),0}, + { &GUID_Key,81,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(81),0}, + { &GUID_Key,82,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(82),0}, + { &GUID_Key,83,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(83),0}, + { &GUID_Key,84,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(84),0}, + { &GUID_Key,85,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(85),0}, + { &GUID_Key,86,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(86),0}, + { &GUID_Key,87,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(87),0}, + { &GUID_Key,88,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(88),0}, + { &GUID_Key,89,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(89),0}, + { &GUID_Key,90,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(90),0}, + { &GUID_Key,91,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(91),0}, + { &GUID_Key,92,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(92),0}, + { &GUID_Key,93,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(93),0}, + { &GUID_Key,94,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(94),0}, + { &GUID_Key,95,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(95),0}, + { &GUID_Key,96,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(96),0}, + { &GUID_Key,97,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(97),0}, + { &GUID_Key,98,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(98),0}, + { &GUID_Key,99,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(99),0}, + { &GUID_Key,100,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(100),0}, + { &GUID_Key,101,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(101),0}, + { &GUID_Key,102,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(102),0}, + { &GUID_Key,103,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(103),0}, + { &GUID_Key,104,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(104),0}, + { &GUID_Key,105,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(105),0}, + { &GUID_Key,106,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(106),0}, + { &GUID_Key,107,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(107),0}, + { &GUID_Key,108,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(108),0}, + { &GUID_Key,109,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(109),0}, + { &GUID_Key,110,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(110),0}, + { &GUID_Key,111,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(111),0}, + { &GUID_Key,112,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(112),0}, + { &GUID_Key,113,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(113),0}, + { &GUID_Key,114,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(114),0}, + { &GUID_Key,115,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(115),0}, + { &GUID_Key,116,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(116),0}, + { &GUID_Key,117,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(117),0}, + { &GUID_Key,118,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(118),0}, + { &GUID_Key,119,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(119),0}, + { &GUID_Key,120,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(120),0}, + { &GUID_Key,121,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(121),0}, + { &GUID_Key,122,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(122),0}, + { &GUID_Key,123,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(123),0}, + { &GUID_Key,124,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(124),0}, + { &GUID_Key,125,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(125),0}, + { &GUID_Key,126,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(126),0}, + { &GUID_Key,127,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(127),0}, + { &GUID_Key,128,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(128),0}, + { &GUID_Key,129,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(129),0}, + { &GUID_Key,130,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(130),0}, + { &GUID_Key,131,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(131),0}, + { &GUID_Key,132,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(132),0}, + { &GUID_Key,133,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(133),0}, + { &GUID_Key,134,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(134),0}, + { &GUID_Key,135,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(135),0}, + { &GUID_Key,136,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(136),0}, + { &GUID_Key,137,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(137),0}, + { &GUID_Key,138,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(138),0}, + { &GUID_Key,139,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(139),0}, + { &GUID_Key,140,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(140),0}, + { &GUID_Key,141,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(141),0}, + { &GUID_Key,142,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(142),0}, + { &GUID_Key,143,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(143),0}, + { &GUID_Key,144,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(144),0}, + { &GUID_Key,145,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(145),0}, + { &GUID_Key,146,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(146),0}, + { &GUID_Key,147,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(147),0}, + { &GUID_Key,148,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(148),0}, + { &GUID_Key,149,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(149),0}, + { &GUID_Key,150,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(150),0}, + { &GUID_Key,151,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(151),0}, + { &GUID_Key,152,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(152),0}, + { &GUID_Key,153,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(153),0}, + { &GUID_Key,154,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(154),0}, + { &GUID_Key,155,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(155),0}, + { &GUID_Key,156,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(156),0}, + { &GUID_Key,157,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(157),0}, + { &GUID_Key,158,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(158),0}, + { &GUID_Key,159,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(159),0}, + { &GUID_Key,160,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(160),0}, + { &GUID_Key,161,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(161),0}, + { &GUID_Key,162,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(162),0}, + { &GUID_Key,163,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(163),0}, + { &GUID_Key,164,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(164),0}, + { &GUID_Key,165,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(165),0}, + { &GUID_Key,166,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(166),0}, + { &GUID_Key,167,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(167),0}, + { &GUID_Key,168,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(168),0}, + { &GUID_Key,169,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(169),0}, + { &GUID_Key,170,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(170),0}, + { &GUID_Key,171,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(171),0}, + { &GUID_Key,172,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(172),0}, + { &GUID_Key,173,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(173),0}, + { &GUID_Key,174,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(174),0}, + { &GUID_Key,175,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(175),0}, + { &GUID_Key,176,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(176),0}, + { &GUID_Key,177,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(177),0}, + { &GUID_Key,178,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(178),0}, + { &GUID_Key,179,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(179),0}, + { &GUID_Key,180,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(180),0}, + { &GUID_Key,181,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(181),0}, + { &GUID_Key,182,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(182),0}, + { &GUID_Key,183,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(183),0}, + { &GUID_Key,184,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(184),0}, + { &GUID_Key,185,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(185),0}, + { &GUID_Key,186,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(186),0}, + { &GUID_Key,187,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(187),0}, + { &GUID_Key,188,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(188),0}, + { &GUID_Key,189,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(189),0}, + { &GUID_Key,190,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(190),0}, + { &GUID_Key,191,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(191),0}, + { &GUID_Key,192,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(192),0}, + { &GUID_Key,193,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(193),0}, + { &GUID_Key,194,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(194),0}, + { &GUID_Key,195,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(195),0}, + { &GUID_Key,196,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(196),0}, + { &GUID_Key,197,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(197),0}, + { &GUID_Key,198,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(198),0}, + { &GUID_Key,199,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(199),0}, + { &GUID_Key,200,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(200),0}, + { &GUID_Key,201,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(201),0}, + { &GUID_Key,202,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(202),0}, + { &GUID_Key,203,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(203),0}, + { &GUID_Key,204,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(204),0}, + { &GUID_Key,205,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(205),0}, + { &GUID_Key,206,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(206),0}, + { &GUID_Key,207,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(207),0}, + { &GUID_Key,208,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(208),0}, + { &GUID_Key,209,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(209),0}, + { &GUID_Key,210,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(210),0}, + { &GUID_Key,211,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(211),0}, + { &GUID_Key,212,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(212),0}, + { &GUID_Key,213,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(213),0}, + { &GUID_Key,214,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(214),0}, + { &GUID_Key,215,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(215),0}, + { &GUID_Key,216,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(216),0}, + { &GUID_Key,217,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(217),0}, + { &GUID_Key,218,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(218),0}, + { &GUID_Key,219,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(219),0}, + { &GUID_Key,220,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(220),0}, + { &GUID_Key,221,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(221),0}, + { &GUID_Key,222,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(222),0}, + { &GUID_Key,223,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(223),0}, + { &GUID_Key,224,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(224),0}, + { &GUID_Key,225,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(225),0}, + { &GUID_Key,226,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(226),0}, + { &GUID_Key,227,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(227),0}, + { &GUID_Key,228,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(228),0}, + { &GUID_Key,229,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(229),0}, + { &GUID_Key,230,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(230),0}, + { &GUID_Key,231,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(231),0}, + { &GUID_Key,232,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(232),0}, + { &GUID_Key,233,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(233),0}, + { &GUID_Key,234,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(234),0}, + { &GUID_Key,235,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(235),0}, + { &GUID_Key,236,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(236),0}, + { &GUID_Key,237,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(237),0}, + { &GUID_Key,238,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(238),0}, + { &GUID_Key,239,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(239),0}, + { &GUID_Key,240,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(240),0}, + { &GUID_Key,241,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(241),0}, + { &GUID_Key,242,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(242),0}, + { &GUID_Key,243,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(243),0}, + { &GUID_Key,244,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(244),0}, + { &GUID_Key,245,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(245),0}, + { &GUID_Key,246,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(246),0}, + { &GUID_Key,247,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(247),0}, + { &GUID_Key,248,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(248),0}, + { &GUID_Key,249,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(249),0}, + { &GUID_Key,250,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(250),0}, + { &GUID_Key,251,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(251),0}, + { &GUID_Key,252,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(252),0}, + { &GUID_Key,253,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(253),0}, + { &GUID_Key,254,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(254),0}, + { &GUID_Key,255,DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(255),0} +}; + +const DIDATAFORMAT c_dfDIKeyboard = { + sizeof(DIDATAFORMAT), + sizeof(DIOBJECTDATAFORMAT), + DIDF_RELAXIS, + 256, + numObjects(dfDIKeyboard), + (LPDIOBJECTDATAFORMAT)dfDIKeyboard +}; + +// DirectInput8Create +HRESULT (WINAPI* _DirectInput8Create) (HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN); +HRESULT WINAPI Empty_DirectInput8Create (HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN) { return 0; } + +static HINSTANCE hDICore; +static BOOL nDICoreInit = FALSE; + +/* +static void DICore_Exit() +{ + FreeLibrary(hDICore); +} +*/ + +// Macro for easy handling of functions +#define _LOADFN(_rettype, _name, _empty, _params, _hinst, _str ) \ + \ + _name = (_rettype (WINAPI *)_params) GetProcAddress(_hinst, _str); \ + \ + if(!_name) { \ + _name = _empty; \ + return 0; \ + } + +static INT32 DICore_GetFunctions() +{ + if(!nDICoreInit) return 0; + + _LOADFN(HRESULT, _DirectInput8Create, Empty_DirectInput8Create, (HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN), hDICore, "DirectInput8Create"); + + return 1; +} + +INT32 DICore_Init() +{ + hDICore = LoadLibrary(_T("dinput8.dll")); + + if(!hDICore) { + MessageBox(NULL, _T("Loading of DINPUT8.DLL failed."), _T("Error"), MB_OK | MB_ICONERROR); + nDICoreInit = FALSE; + return 0; + } + + nDICoreInit = TRUE; + if(!DICore_GetFunctions()) { + MessageBox(NULL, _T("There was a problem while loading functions from DINPUT8.DLL"), _T("Error"), MB_OK | MB_ICONERROR); + return 0; + } + + return 1; +} diff --git a/src/interface/win32/dinput_core.h b/src/interface/win32/dinput_core.h new file mode 100644 index 00000000..34eb3e3c --- /dev/null +++ b/src/interface/win32/dinput_core.h @@ -0,0 +1,16 @@ +#ifndef _DINPUT_CORE_ +#define _DINPUT_CORE_ + +#define DIRECTINPUT_VERSION 0x0800 +#include + +extern const DIDATAFORMAT c_dfDIJoystick2; +extern const DIDATAFORMAT c_dfDIMouse2; +extern const DIDATAFORMAT c_dfDIKeyboard; + +// DirectInput8Create +extern HRESULT (WINAPI* _DirectInput8Create) (HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN); + +INT32 DICore_Init(); + +#endif diff --git a/src/interface/win32/directx9_core.cpp b/src/interface/win32/directx9_core.cpp new file mode 100644 index 00000000..df4818f5 --- /dev/null +++ b/src/interface/win32/directx9_core.cpp @@ -0,0 +1,158 @@ +#include "burner.h" +#include "directx9_core.h" + +// Direct3DCreate9 +LPDIRECT3D9 (WINAPI* _Direct3DCreate9) (UINT); +LPDIRECT3D9 WINAPI Empty_Direct3DCreate9 (UINT) { return NULL; } + +// D3DXFillTextureTX +HRESULT (WINAPI* _D3DXFillTextureTX) (LPDIRECT3DTEXTURE9, LPD3DXTEXTURESHADER); +HRESULT WINAPI Empty_D3DXFillTextureTX (LPDIRECT3DTEXTURE9, LPD3DXTEXTURESHADER) { return 0; } + +// D3DXCreateBuffer +HRESULT (WINAPI* _D3DXCreateBuffer) (DWORD,LPD3DXBUFFER*); +HRESULT WINAPI Empty_D3DXCreateBuffer (DWORD,LPD3DXBUFFER*) { return 0; } + +// D3DXCreateEffectFromResource +#ifdef UNICODE +HRESULT (WINAPI* _D3DXCreateEffectFromResource) (LPDIRECT3DDEVICE9,HMODULE,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +HRESULT WINAPI Empty_D3DXCreateEffectFromResource (LPDIRECT3DDEVICE9,HMODULE,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*) { return 0; } +#else +HRESULT (WINAPI* _D3DXCreateEffectFromResource) (LPDIRECT3DDEVICE9,HMODULE,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +HRESULT WINAPI Empty_D3DXCreateEffectFromResource (LPDIRECT3DDEVICE9,HMODULE,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*) { return 0; } +#endif + +// D3DXCreateEffectFromFile +#ifdef UNICODE +HRESULT (WINAPI* _D3DXCreateEffectFromFile) (LPDIRECT3DDEVICE9,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +HRESULT WINAPI Empty_D3DXCreateEffectFromFile (LPDIRECT3DDEVICE9,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*) { return 0; } +#else +HRESULT (WINAPI* _D3DXCreateEffectFromFile) (LPDIRECT3DDEVICE9,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +HRESULT WINAPI Empty_D3DXCreateEffectFromFile (LPDIRECT3DDEVICE9,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*) { return 0; } +#endif + +// D3DXLoadSurfaceFromMemory +HRESULT (WINAPI* _D3DXLoadSurfaceFromMemory) (LPDIRECT3DSURFACE9,const PALETTEENTRY*,const RECT*,LPCVOID,D3DFORMAT,UINT,const PALETTEENTRY*,const RECT*,DWORD,D3DCOLOR); +HRESULT WINAPI Empty_D3DXLoadSurfaceFromMemory (LPDIRECT3DSURFACE9,const PALETTEENTRY*,const RECT*,LPCVOID,D3DFORMAT,UINT,const PALETTEENTRY*,const RECT*,DWORD,D3DCOLOR) { return 0; } + +// D3DXCompileShaderFromResource +#ifdef UNICODE +HRESULT (WINAPI* _D3DXCompileShaderFromResource) (HMODULE,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +HRESULT WINAPI Empty_D3DXCompileShaderFromResource (HMODULE,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*) { return 0; } +#else +HRESULT (WINAPI* _D3DXCompileShaderFromResource) (HMODULE,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +HRESULT WINAPI Empty_D3DXCompileShaderFromResource (HMODULE,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*) { return 0; } +#endif + +// D3DXCompileShaderFromFile +#ifdef UNICODE +HRESULT (WINAPI* _D3DXCompileShaderFromFile) (LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +HRESULT WINAPI Empty_D3DXCompileShaderFromFile (LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*) { return 0; } +#else +HRESULT (WINAPI* _D3DXCompileShaderFromFile) (LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +HRESULT WINAPI Empty_D3DXCompileShaderFromFile (LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*) { return 0; } +#endif + +// D3DXCreateTextureShader +HRESULT (WINAPI* _D3DXCreateTextureShader) (const DWORD*, LPD3DXTEXTURESHADER*); +HRESULT WINAPI Empty_D3DXCreateTextureShader (const DWORD*,LPD3DXTEXTURESHADER*) { return 0; } + +// D3DXCreateFont +#ifdef UNICODE +HRESULT (WINAPI* _D3DXCreateFont) (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPD3DXFONT*); +HRESULT WINAPI Empty_D3DXCreateFont (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPD3DXFONT*) { return 0; } +#else +HRESULT (WINAPI* _D3DXCreateFont) (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPD3DXFONT*); +HRESULT WINAPI Empty_D3DXCreateFont (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPD3DXFONT*) { return 0; } +#endif + +static HINSTANCE hDx9Core_D3D9; +static HINSTANCE hDx9Core_D3DX9; +static BOOL nDx9CoreInit = FALSE; + +/* +static void Dx9Core_Exit() +{ + FreeLibrary(hDx9Core_D3D9); + FreeLibrary(hDx9Core_D3DX9); +} +*/ + +// Macro for easy handling of functions +#define _LOADFN(_rettype, _name, _empty, _params, _hinst, _str ) \ + \ + _name = (_rettype (WINAPI *)_params) GetProcAddress(_hinst, _str); \ + \ + if(!_name) { \ + _name = _empty; \ + return 0; \ + } + +static INT32 Dx9Core_GetFunctions() +{ + if(!nDx9CoreInit) return 0; + + // D3D9.DLL + _LOADFN(LPDIRECT3D9, _Direct3DCreate9, Empty_Direct3DCreate9, (UINT), hDx9Core_D3D9, "Direct3DCreate9"); + + // D3DX9.DLL + _LOADFN(HRESULT, _D3DXFillTextureTX, Empty_D3DXFillTextureTX, (LPDIRECT3DTEXTURE9, LPD3DXTEXTURESHADER), hDx9Core_D3DX9, "D3DXFillTextureTX"); + +#ifdef UNICODE + _LOADFN(HRESULT, _D3DXCreateEffectFromResource, Empty_D3DXCreateEffectFromResource, (LPDIRECT3DDEVICE9, HMODULE, LPCWSTR, const D3DXMACRO*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*), hDx9Core_D3DX9, "D3DXCreateEffectFromResourceW"); +#else + _LOADFN(HRESULT, _D3DXCreateEffectFromResource, Empty_D3DXCreateEffectFromResource, (LPDIRECT3DDEVICE9, HMODULE, LPCTSTR, const D3DXMACRO*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*), hDx9Core_D3DX9, "D3DXCreateEffectFromResourceA"); +#endif + +#ifdef UNICODE + _LOADFN(HRESULT, _D3DXCreateEffectFromFile, Empty_D3DXCreateEffectFromFile, (LPDIRECT3DDEVICE9,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*), hDx9Core_D3DX9, "D3DXCreateEffectFromFileW"); +#else + _LOADFN(HRESULT, _D3DXCreateEffectFromFile, Empty_D3DXCreateEffectFromFile, (LPDIRECT3DDEVICE9,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*), hDx9Core_D3DX9, "D3DXCreateEffectFromFileA"); +#endif + + _LOADFN(HRESULT, _D3DXCreateBuffer, Empty_D3DXCreateBuffer, (DWORD,LPD3DXBUFFER*), hDx9Core_D3DX9, "D3DXCreateBuffer"); + + _LOADFN(HRESULT, _D3DXLoadSurfaceFromMemory, Empty_D3DXLoadSurfaceFromMemory, (LPDIRECT3DSURFACE9, const PALETTEENTRY*, const RECT*, LPCVOID,D3DFORMAT, UINT, const PALETTEENTRY*, const RECT*, DWORD, D3DCOLOR), hDx9Core_D3DX9, "D3DXLoadSurfaceFromMemory"); + +#ifdef UNICODE + _LOADFN(HRESULT, _D3DXCompileShaderFromResource, Empty_D3DXCompileShaderFromResource, (HMODULE, LPCWSTR, const D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*), hDx9Core_D3DX9, "D3DXCompileShaderFromResourceW"); +#else + _LOADFN(HRESULT, _D3DXCompileShaderFromResource, Empty_D3DXCompileShaderFromResource, (HMODULE, LPCTSTR, const D3DXMACRO*, LPD3DXINCLUDE, LPCSTR, LPCSTR, DWORD, LPD3DXBUFFER*, LPD3DXBUFFER*, LPD3DXCONSTANTTABLE*), hDx9Core_D3DX9, "D3DXCompileShaderFromResourceA"); +#endif + +#ifdef UNICODE + _LOADFN(HRESULT, _D3DXCompileShaderFromFile, Empty_D3DXCompileShaderFromFile, (LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*), hDx9Core_D3DX9, "D3DXCompileShaderFromFileW"); +#else + _LOADFN(HRESULT, _D3DXCompileShaderFromFile, Empty_D3DXCompileShaderFromFile, (LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*), hDx9Core_D3DX9, "D3DXCompileShaderFromFileA"); +#endif + + _LOADFN(HRESULT, _D3DXCreateTextureShader, Empty_D3DXCreateTextureShader, (const DWORD*, LPD3DXTEXTURESHADER*), hDx9Core_D3DX9, "D3DXCreateTextureShader"); + +#ifdef UNICODE + _LOADFN(HRESULT, _D3DXCreateFont, Empty_D3DXCreateFont, (LPDIRECT3DDEVICE9, INT, UINT, UINT, UINT, BOOL, DWORD, DWORD, DWORD, DWORD, LPCWSTR, LPD3DXFONT*), hDx9Core_D3DX9, "D3DXCreateFontW"); +#else + _LOADFN(HRESULT, _D3DXCreateFont, Empty_D3DXCreateFont, (LPDIRECT3DDEVICE9, INT, UINT, UINT, UINT, BOOL, DWORD, DWORD, DWORD, DWORD, LPCTSTR, LPD3DXFONT*), hDx9Core_D3DX9, "D3DXCreateFontA"); +#endif + + return 1; +} + +INT32 Dx9Core_Init() +{ + hDx9Core_D3D9 = LoadLibrary(_T("d3d9.dll")); + hDx9Core_D3DX9 = LoadLibrary(_T("D3DX9_43.dll")); + + if(!hDx9Core_D3D9 || !hDx9Core_D3DX9) { + MessageBox(NULL, _T("Loading of D3D9.DLL and D3DX9_43.DLL failed."), _T("Error"), MB_OK | MB_ICONERROR); + nDx9CoreInit = FALSE; + return 0; + } + + nDx9CoreInit = TRUE; + if(!Dx9Core_GetFunctions()) { + MessageBox(NULL, _T("There was a problem while loading functions from D3D9.DLL and D3DX9_43.DLL"), _T("Error"), MB_OK | MB_ICONERROR); + return 0; + } + + return 1; +} diff --git a/src/interface/win32/directx9_core.h b/src/interface/win32/directx9_core.h new file mode 100644 index 00000000..21d5d244 --- /dev/null +++ b/src/interface/win32/directx9_core.h @@ -0,0 +1,63 @@ +#ifndef _DIRECTX9_CORE_ +#define _DIRECTX9_CORE_ + +#include +#include + +#ifndef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY +#define D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY 0x1000 +#endif + +// Direct3DCreate9 +extern LPDIRECT3D9 (WINAPI* _Direct3DCreate9) (UINT); + +// D3DXFillTextureTX +extern HRESULT (WINAPI* _D3DXFillTextureTX) (LPDIRECT3DTEXTURE9, LPD3DXTEXTURESHADER); + +// D3DXCreateBuffer +extern HRESULT (WINAPI* _D3DXCreateBuffer) (DWORD,LPD3DXBUFFER*); + +// D3DXCreateEffectFromResource +#ifdef UNICODE +extern HRESULT (WINAPI* _D3DXCreateEffectFromResource) (LPDIRECT3DDEVICE9, HMODULE, LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +#else +extern HRESULT (WINAPI* _D3DXCreateEffectFromResource) (LPDIRECT3DDEVICE9, HMODULE, LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +#endif + +// D3DXCreateEffectFromFile +#ifdef UNICODE +extern HRESULT (WINAPI* _D3DXCreateEffectFromFile) (LPDIRECT3DDEVICE9,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +#else +extern HRESULT (WINAPI* _D3DXCreateEffectFromFile) (LPDIRECT3DDEVICE9,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,DWORD,LPD3DXEFFECTPOOL,LPD3DXEFFECT*,LPD3DXBUFFER*); +#endif + +// D3DXLoadSurfaceFromMemory +extern HRESULT (WINAPI* _D3DXLoadSurfaceFromMemory) (LPDIRECT3DSURFACE9,const PALETTEENTRY*,const RECT*,LPCVOID,D3DFORMAT,UINT,const PALETTEENTRY*,const RECT*,DWORD,D3DCOLOR); + +// D3DXCompileShaderFromResource +#ifdef UNICODE +extern HRESULT (WINAPI* _D3DXCompileShaderFromResource) (HMODULE,LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +#else +extern HRESULT (WINAPI* _D3DXCompileShaderFromResource) (HMODULE,LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +#endif + +// D3DXCompileShaderFromFile +#ifdef UNICODE +extern HRESULT (WINAPI* _D3DXCompileShaderFromFile) (LPCWSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +#else +extern HRESULT (WINAPI* _D3DXCompileShaderFromFile) (LPCTSTR,const D3DXMACRO*,LPD3DXINCLUDE,LPCSTR,LPCSTR,DWORD,LPD3DXBUFFER*,LPD3DXBUFFER*,LPD3DXCONSTANTTABLE*); +#endif + +// D3DXCreateTextureShader +extern HRESULT (WINAPI* _D3DXCreateTextureShader) (const DWORD*, LPD3DXTEXTURESHADER*); + +// D3DXCreateFont +#ifdef UNICODE +extern HRESULT (WINAPI* _D3DXCreateFont) (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPD3DXFONT*); +#else +extern HRESULT (WINAPI* _D3DXCreateFont) (LPDIRECT3DDEVICE9,INT,UINT,UINT,UINT,BOOL,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPD3DXFONT*); +#endif + +INT32 Dx9Core_Init(); + +#endif diff --git a/src/interface/win32/dsound_core.cpp b/src/interface/win32/dsound_core.cpp new file mode 100644 index 00000000..41a19e6b --- /dev/null +++ b/src/interface/win32/dsound_core.cpp @@ -0,0 +1,54 @@ +#include "burner.h" +#include "dsound_core.h" + +// DirectSoundCreate +HRESULT (WINAPI *_DirectSoundCreate) (LPGUID, LPDIRECTSOUND*, LPUNKNOWN); +HRESULT WINAPI Empty_DirectSoundCreate (LPGUID, LPDIRECTSOUND*, LPUNKNOWN) { return 0; } + +static HINSTANCE hDSCore; +static BOOL nDSCoreInit = FALSE; + +/* +static void DSCore_Exit() +{ + FreeLibrary(hDSCore); +} +*/ + +// Macro for easy handling of functions +#define _LOADFN(_rettype, _name, _empty, _params, _hinst, _str ) \ + \ + _name = (_rettype (WINAPI *)_params) GetProcAddress(_hinst, _str); \ + \ + if(!_name) { \ + _name = _empty; \ + return 0; \ + } + +static INT32 DSCore_GetFunctions() +{ + if(!nDSCoreInit) return 0; + + _LOADFN(HRESULT, _DirectSoundCreate, Empty_DirectSoundCreate, (LPGUID, LPDIRECTSOUND*, LPUNKNOWN), hDSCore, "DirectSoundCreate"); + + return 1; +} + +INT32 DSCore_Init() +{ + hDSCore = LoadLibrary(_T("dsound.dll")); + + if(!hDSCore) { + MessageBox(NULL, _T("Loading of DSOUND.DLL failed."), _T("Error"), MB_OK | MB_ICONERROR); + nDSCoreInit = FALSE; + return 0; + } + + nDSCoreInit = TRUE; + if(!DSCore_GetFunctions()) { + MessageBox(NULL, _T("There was a problem while loading functions from DSOUND.DLL"), _T("Error"), MB_OK | MB_ICONERROR); + return 0; + } + + return 1; +} diff --git a/src/interface/win32/dsound_core.h b/src/interface/win32/dsound_core.h new file mode 100644 index 00000000..7fadd972 --- /dev/null +++ b/src/interface/win32/dsound_core.h @@ -0,0 +1,11 @@ +#ifndef _DSOUND_CORE_ +#define _DSOUND_CORE_ + +#include + +// DirectSoundCreate +extern HRESULT (WINAPI *_DirectSoundCreate)(LPGUID, LPDIRECTSOUND*, LPUNKNOWN); + +INT32 DSCore_Init(); + +#endif diff --git a/src/interface/win32/inp_dinput.cpp b/src/interface/win32/inp_dinput.cpp new file mode 100644 index 00000000..476f32a1 --- /dev/null +++ b/src/interface/win32/inp_dinput.cpp @@ -0,0 +1,876 @@ +// DirectInput module +// updated to dinput8 by regret + +#include "burner.h" +#include "inp_keys.h" + +#include + +#define DIRECTINPUT_VERSION 0x0800 +#include + +//#ifdef _MSC_VER +//#pragma comment(lib, "dinput8") +//#pragma comment(lib, "dxguid") +//#endif + +#include "dinput_core.h" + +#define MAX_KEYBOARD (1) +#define MAX_GAMEPAD (8) +#define MAX_JOYAXIS (8) +#define MAX_MOUSE (4) +#define MAX_MOUSEAXIS (3) + +static BOOL CALLBACK gamepadEnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE, LPVOID); +static BOOL CALLBACK mouseEnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE, LPVOID); +static BOOL CALLBACK gamepadEnumCallback(LPCDIDEVICEINSTANCE, LPVOID); +static BOOL CALLBACK mouseEnumCallback(LPCDIDEVICEINSTANCE, LPVOID); + + +//class InputDI : public Input { +//public: + struct keyboardData { + IDirectInputDevice8W* lpdid; + unsigned char state[256]; + unsigned char readStatus; + } keyboardProperties[MAX_KEYBOARD]; + + struct gamepadData { + IDirectInputDevice8W* lpdid; + DIJOYSTATE2 dijs; + DWORD dwAxisType[MAX_JOYAXIS]; + DWORD dwAxisBaseline[MAX_JOYAXIS]; + DWORD dwAxes; + DWORD dwPOVs; + DWORD dwButtons; + unsigned char readStatus; + } gamepadProperties[MAX_GAMEPAD]; + + struct mouseData { + IDirectInputDevice8W* lpdid; + DIMOUSESTATE2 dims; + DWORD dwAxisType[MAX_MOUSEAXIS]; + DWORD dwAxes; + DWORD dwButtons; + unsigned char readStatus; + } mouseProperties[MAX_MOUSE]; + + int keyboardCount; // Number of keyboards connected to this machine + int gamepadCount; // Number of gamepads connected to this machine + int mouseCount; // Number of mice connected to this machine + + IDirectInput8W* pDI; + HWND hDinpWnd; + + int gamepadInitSingle() + { + gamepadData* gamepad = &gamepadProperties[gamepadCount]; + if (gamepad->lpdid == NULL) { + return 1; + } + + if (FAILED(gamepad->lpdid->SetDataFormat(&c_dfDIJoystick2))) { + return 1; + } + + DIDEVCAPS didcl; + memset(&didcl, 0, sizeof(didcl)); + didcl.dwSize = sizeof(DIDEVCAPS); + if (FAILED(gamepad->lpdid->GetCapabilities(&didcl))) { + return 1; + } + + gamepad->dwAxes = didcl.dwAxes; + gamepad->dwPOVs = didcl.dwPOVs; + gamepad->dwButtons = didcl.dwButtons; + + gamepad->lpdid->SetCooperativeLevel(hDinpWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND); + gamepad->lpdid->EnumObjects(gamepadEnumAxesCallback, /*(void*)this*/ gamepad->lpdid, DIDFT_AXIS); + gamepad->lpdid->Acquire(); + + return 0; + } + + int mouseInitSingle() + { + mouseData* mouse = &mouseProperties[mouseCount]; + if (mouse->lpdid == NULL) { + return 1; + } + + if (FAILED(mouse->lpdid->SetDataFormat(&c_dfDIMouse2))) { + return 1; + } + + DIDEVCAPS didcl; + memset(&didcl, 0, sizeof(didcl)); + didcl.dwSize = sizeof(didcl); + mouse->lpdid->GetCapabilities(&didcl); + + mouse->dwAxes = didcl.dwAxes; + mouse->dwButtons = didcl.dwButtons; + + mouse->lpdid->SetCooperativeLevel(hDinpWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + mouse->lpdid->EnumObjects(mouseEnumAxesCallback, /*(void*)this*/mouse->lpdid, DIDFT_AXIS); + mouse->lpdid->Acquire(); + + return 0; + } + + bool mouseEnumDevice(LPCDIDEVICEINSTANCE instance) + { + if (!instance) { + return DIENUM_CONTINUE; + } + + if (mouseCount >= MAX_MOUSE) { + return DIENUM_STOP; + } + + // Create the DirectInput interface + if (FAILED(pDI->CreateDevice(instance->guidInstance, &mouseProperties[mouseCount].lpdid, NULL))) { + return DIENUM_CONTINUE; + } + + if (!mouseInitSingle()) { + mouseCount++; + } + + return DIENUM_CONTINUE; + } + + bool gamepadEnumDevice(LPCDIDEVICEINSTANCE instance) + { + if (!instance) { + return DIENUM_CONTINUE; + } + + if (gamepadCount >= MAX_GAMEPAD) { + return DIENUM_STOP; + } + + // Create the DirectInput interface + if (FAILED(pDI->CreateDevice(instance->guidInstance, &gamepadProperties[gamepadCount].lpdid, NULL))) { + return DIENUM_CONTINUE; + } + + if (gamepadInitSingle() == 0) { + gamepadCount++; + } + + return DIENUM_CONTINUE; + } + + bool mouseEnumObject(LPCDIDEVICEOBJECTINSTANCE instance) + { + mouseData* p = &mouseProperties[mouseCount]; + + // Store the flags for later use + ((mouseData*)p)->dwAxisType[DIDFT_GETINSTANCE(instance->dwType)] = instance->dwType; + return DIENUM_CONTINUE; + } + + bool gamepadEnumObject(LPCDIDEVICEOBJECTINSTANCE instance) + { + if (!(DIDFT_GETTYPE(instance->dwType) & DIDFT_AXIS)) { + return DIENUM_CONTINUE; + } + + gamepadData* p = &gamepadProperties[gamepadCount]; + p->dwAxisType[DIDFT_GETINSTANCE(instance->dwType)] = instance->dwType; + + // Set axis range + DIPROPRANGE range; + range.diph.dwSize = sizeof(range); + range.diph.dwHeaderSize = sizeof(range.diph); + range.diph.dwHow = DIPH_BYID; + range.diph.dwObj = instance->dwType; + range.lMin = -32768; + range.lMax = +32767; + if (FAILED(p->lpdid->SetProperty(DIPROP_RANGE, &range.diph))) { + if (FAILED(p->lpdid->GetProperty(DIPROP_RANGE, &range.diph)) || range.lMin >= 0 || range.lMax <= 0) { + return DIENUM_CONTINUE; + } + } + + return DIENUM_CONTINUE; + } + + int setCooperativeLevel(bool exclusive, bool foreGround) + { + if (keyboardProperties[0].lpdid) { + keyboardProperties[0].lpdid->Unacquire(); + if (foreGround) { + keyboardProperties[0].lpdid->SetCooperativeLevel(hDinpWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND | (nVidFullscreen ? DISCL_NOWINKEY : 0)); + } else { + keyboardProperties[0].lpdid->SetCooperativeLevel(hDinpWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND | (nVidFullscreen ? DISCL_NOWINKEY : 0)); + } + keyboardProperties[0].lpdid->Acquire(); + } + + // mouse 0 is the system mouse + if (mouseProperties[0].lpdid) { + mouseProperties[0].lpdid->Unacquire(); + if (exclusive) { + POINT point = { 0, 0 }; + RECT rect; + + // Ensure the cursor is centered on the input window + ClientToScreen(hDinpWnd, &point); + GetClientRect(hDinpWnd, &rect); + SetCursorPos(point.x + rect.right / 2, point.y + rect.bottom / 2); + + SetForegroundWindow(hDinpWnd); + SetWindowPos(hDinpWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + mouseProperties[0].lpdid->SetCooperativeLevel(hDinpWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND); + } else { + mouseProperties[0].lpdid->SetCooperativeLevel(hDinpWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + } + mouseProperties[0].lpdid->Acquire(); + } + + // Windows/DirectInput don't always hide the cursor for us + if (bDrvOkay && (exclusive || nVidFullscreen)) { + while (ShowCursor(FALSE) >= 0) {} + } else { + while (ShowCursor(TRUE) < 0) {} + } + + return 0; + } + + int exit() + { + // Release the keyboard interface + for (int i = 0; i < MAX_KEYBOARD; i++) { + RELEASE(keyboardProperties[i].lpdid) + } + keyboardCount = 0; + + // Release the gamepad interfaces + for (int i = 0; i < MAX_GAMEPAD; i++) { + RELEASE(gamepadProperties[i].lpdid) + } + gamepadCount = 0; + + // Release the mouse interface + for (int i = 0; i < MAX_MOUSE; i++) { + RELEASE(mouseProperties[i].lpdid) + } + mouseCount = 0; + + // Release the DirectInput interface + RELEASE(pDI) + + return 0; + } + + int init() + { + hDinpWnd = hScrnWnd; + + exit(); + + memset(&keyboardProperties, 0, sizeof(keyboardProperties)); + memset(&gamepadProperties, 0, sizeof(gamepadProperties)); + memset(&mouseProperties, 0, sizeof(mouseProperties)); + + if (FAILED(_DirectInput8Create(hAppInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&pDI, NULL))) { + return 1; + } + + // keyboard + if (FAILED(pDI->CreateDevice(GUID_SysKeyboard, &keyboardProperties[0].lpdid, NULL))) { + return 1; + } + keyboardProperties[0].lpdid->SetDataFormat(&c_dfDIKeyboard); + keyboardProperties[0].lpdid->SetCooperativeLevel(hDinpWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + keyboardProperties[0].lpdid->Acquire(); + keyboardCount = 1; + + // Enumerate and set up the mice connected to the system + // Note that under Win2K/WinXP only one mouse device will be enumerated + if (FAILED(pDI->EnumDevices(DI8DEVTYPE_MOUSE, mouseEnumCallback, /*(void*)this*/pDI, DIEDFL_ATTACHEDONLY))) { + return 1; + } + + // Enumerate and set up the gamepads connected to the system + if (FAILED(pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, gamepadEnumCallback, /*(void*)this*/pDI, DIEDFL_ATTACHEDONLY))) { + return 1; + } + + return 0; + } + + // Call before checking for Input in a frame + int newFrame() + { + // No gamepads have been read for this frame + for (int i = 0; i < gamepadCount; i++) { + gamepadProperties[i].readStatus = 0; + } + + // mouse not read this frame + for (int i = 0; i < mouseCount; i++) { + mouseProperties[i].readStatus = 0; + } + + // keyboard not read this frame + for (int i = 0; i < keyboardCount; i++) { + keyboardProperties[i].readStatus = 0; + } + + return 0; + } + + // Read the keyboard + int readKeyboard(keyboardData* keyboard) + { + if (keyboard->readStatus) { // Already read this frame - ready to go + return 0; + } + if (!keyboard->lpdid) { + return 1; + } + + // Read keyboard, reacquiring if neccesary + HRESULT ret = DI_OK; + for (int j = 0; j < 2; j++) { + ret = keyboard->lpdid->GetDeviceState(sizeof(keyboard->state), (void*)keyboard->state); + if (ret != DIERR_INPUTLOST && ret != DIERR_NOTACQUIRED) { + break; + } + keyboard->lpdid->Acquire(); // If DIERR_INPUTLOST, reacquire and try again + } + if (FAILED(ret)) { // Failed to read the keyboard + return 1; + } + + // The keyboard has been successfully Read this frame + keyboard->readStatus = 1; + + return 0; + } + + // Read one of the gamepads + int readGamepad(gamepadData* gamepad) + { + if (gamepad->readStatus == 1) { // Already read this frame - ready to go + return 0; + } + if (gamepad->readStatus == 2) { // Error reading gamepad + return 1; + } + if (!gamepad->lpdid) { + return 1; + } + + gamepad->readStatus = 2; // Mark gamepad as trying to read + + // Poll + read gamepad, reacquiring if neccesary + HRESULT ret = DI_OK; + for (int j = 0; j < 2; j++) { + gamepad->lpdid->Poll(); + + ret = gamepad->lpdid->GetDeviceState(sizeof(gamepad->dijs), &gamepad->dijs); + if (ret != DIERR_INPUTLOST && ret != DIERR_NOTACQUIRED) { + break; + } + gamepad->lpdid->Acquire(); // If DIERR_INPUTLOST, reacquire and try again + } + if (FAILED(ret)) { + return 1; + } + + // This gamepad had been successfully Read this frame + gamepad->readStatus = 1; + + return 0; + } + + // Check a subcode (the 40xx bit in 4001, 4102 etc) for a gamepad input code + int gamepadState(gamepadData* gamepad, unsigned int subCode) + { + if (subCode < 0x10) { // gamepad directions + // Some drivers don't assign unused axes a value of 0 + if (!(gamepad->dwAxisType[subCode >> 1] & DIDFT_AXIS)) { + return 0; + } + + const int DEADZONE = 0x4000; + + switch (subCode) { + case 0x00: return gamepad->dijs.lX < -DEADZONE; // Left + case 0x01: return gamepad->dijs.lX > DEADZONE; // Right + case 0x02: return gamepad->dijs.lY < -DEADZONE; // Up + case 0x03: return gamepad->dijs.lY > DEADZONE; // Down + case 0x04: return gamepad->dijs.lZ < -DEADZONE; + case 0x05: return gamepad->dijs.lZ > DEADZONE; + case 0x06: return gamepad->dijs.lRx < -DEADZONE; + case 0x07: return gamepad->dijs.lRx > DEADZONE; + case 0x08: return gamepad->dijs.lRy < -DEADZONE; + case 0x09: return gamepad->dijs.lRy > DEADZONE; + case 0x0A: return gamepad->dijs.lRz < -DEADZONE; + case 0x0B: return gamepad->dijs.lRz > DEADZONE; + case 0x0C: return gamepad->dijs.rglSlider[0] < -DEADZONE; + case 0x0D: return gamepad->dijs.rglSlider[0] > DEADZONE; + case 0x0E: return gamepad->dijs.rglSlider[1] < -DEADZONE; + case 0x0F: return gamepad->dijs.rglSlider[1] > DEADZONE; + } + } + + if (subCode < 0x10 + (gamepad->dwPOVs << 2)) { // POV hat controls + DWORD hatDirection = gamepad->dijs.rgdwPOV[(subCode & 0x0F) >> 2]; + if ((LOWORD(hatDirection) != 0xFFFF)) { + switch (subCode & 3) { + case 0: // Left + return (hatDirection >= 22500 && hatDirection <= 31500); + case 1: // Right + return (hatDirection >= 4500 && hatDirection <= 13500); + case 2: // Up + return (hatDirection >= 31500 || hatDirection <= 4500); + case 3: // Down + return (hatDirection >= 13500 && hatDirection <= 22500); + } + } + return 0; + } + if (subCode < 0x80) { // Undefined + return 0; + } + if (subCode < 0x80 + gamepad->dwButtons) { // gamepad buttons + return (gamepad->dijs.rgbButtons[subCode & 0x7F] & 0x80) ? 1 : 0; + } + + return 0; + } + + // Read the mouse + int readMouse(mouseData* mouse) + { + if (mouse->readStatus) { // Already read this frame - ready to go + return 0; + } + if (!mouse->lpdid) { + return 1; + } + + // Read mouse, reacquiring if neccesary + HRESULT ret = DI_OK; + for (int j = 0; j < 2; j++) { + ret = mouse->lpdid->GetDeviceState(sizeof(mouse->dims), (void*)&mouse->dims); + if (ret != DIERR_INPUTLOST) { + break; + } + mouse->lpdid->Acquire(); // If DIERR_INPUTLOST, reacquire and try again + } + if (FAILED(ret)) { // Failed to read the mouse + return 1; + } + + // The mouse has been successfully Read this frame + mouse->readStatus = 1; + + return 0; + } + + // Check a subcode (the 80xx bit in 8001, 8102 etc) for a mouse input code + int checkMouseState(mouseData* mouse, unsigned int subCode) + { + if (subCode < 0x80) { // Undefined + return 0; + } + if (subCode < 0x80 + mouse->dwButtons) { // mouse buttons + return (mouse->dims.rgbButtons[subCode & 0x7F] & 0x80) ? 1 : 0; + } + + return 0; + } + + // Get the state (pressed = 1, not pressed = 0) of a particular input code + int getState(int code) + { + if (code < 0) { + return 0; + } + + if (code < 256) { + if (readKeyboard(&keyboardProperties[0])) { // Check keyboard has been read - return not pressed on error + return 0; + } + return (keyboardProperties[0].state[code] & 0x80) ? 1 : 0; + } + + if (code < 0x4000) { + return 0; + } + + // Codes 4000-8000 = Joysticks + if (code < 0x8000) { + int i = (code - 0x4000) >> 8; + if (i >= gamepadCount) { // This gamepad number isn't connected + return 0; + } + if (readGamepad(&gamepadProperties[i])) { // Error polling the gamepad + return 0; + } + + // Find the gamepad state in our array + return gamepadState(&gamepadProperties[i], code & 0xFF); + } + + // Codes 8000-C000 = mouse + if (code < 0xC000) { + int i = (code - 0x8000) >> 8; + if (i >= mouseCount) { // This mouse number isn't connected + return 0; + } + if (readMouse(&mouseProperties[i])) { // Error Reading the mouse + return 0; + } + return checkMouseState(&mouseProperties[i], code & 0xFF); + } + + return 0; + } + + // Read one gamepad axis + int readGamepadAxis(int i, int axis) + { + gamepadData* gamepad = &gamepadProperties[i]; + + if (i < 0 || i >= gamepadCount) { // This gamepad isn't connected + return 0; + } + if (readGamepad(gamepad)) { // Error polling the gamepad + return 0; + } + + // Some drivers don't assign unused axes a value of 0 + if (!(gamepad->dwAxisType[axis & (MAX_JOYAXIS - 1)] & DIDFT_AXIS)) { + return 0; + } + + switch (axis) { + case 0: + return gamepad->dijs.lX; + case 1: + return gamepad->dijs.lY; + case 2: + return gamepad->dijs.lZ; + case 3: + return gamepad->dijs.lRx; + case 4: + return gamepad->dijs.lRy; + case 5: + return gamepad->dijs.lRz; + case 6: + return gamepad->dijs.rglSlider[0]; + case 7: + return gamepad->dijs.rglSlider[1]; + } + + return 0; + } + + // Read one mouse axis + int readMouseAxis(int i, int axis) + { + mouseData* mouse = &mouseProperties[i]; + + if (i < 0 || i >= mouseCount) { // This mouse isn't connected + return 0; + } + if (readMouse(mouse) != 0) { // Error polling the mouse + return 0; + } + + // Some drivers don't assign unused axes a value of 0 + if (!(mouse->dwAxisType[axis & (MAX_MOUSEAXIS - 1)] & DIDFT_AXIS)) { + return 0; + } + + switch (axis) { + case 0: + return mouse->dims.lX; + case 1: + return mouse->dims.lY; + case 2: + return mouse->dims.lZ / WHEEL_DELTA; + } + + return 0; + } + + // This function finds which key is pressed + // To ensure analog gamepad axes are handled correctly, call with createBaseline = true the 1st time + int find(bool createBaseline) + { + int retVal = -1; // assume nothing pressed + + // check if any keyboard keys are pressed + if (!readKeyboard(&keyboardProperties[0])) { + for (int i = 0; i < 256; i++) { + if (keyboardProperties[0].state[i] & 0x80) { + retVal = i; + goto End; + } + } + } + + // Now check all the connected gamepads + for (int i = 0; i < gamepadCount; i++) { + gamepadData* gamepad = &gamepadProperties[i]; + if (readGamepad(gamepad)) { // There was an error polling the gamepad + continue; + } + + for (unsigned int j = 0; j < 0x10; j++) { // Axes + int delta = gamepad->dwAxisBaseline[j >> 1] - readGamepadAxis(i, (j >> 1)); + if (delta < -0x4000 || delta > 0x4000) { + if (gamepadState(gamepad, j)) { + retVal = 0x4000 | (i << 8) | j; + goto End; + } + } + } + + for (unsigned int j = 0x10; j < 0x10 + (gamepad->dwPOVs << 2); j++) { // POV hats + if (gamepadState(gamepad, j)) { + retVal = 0x4000 | (i << 8) | j; + goto End; + } + } + + for (unsigned int j = 0x80; j < 0x80 + gamepad->dwButtons; j++) { // Buttons + if (gamepadState(gamepad, j)) { + retVal = 0x4000 | (i << 8) | j; + goto End; + } + } + } + + // Now check all the connected mice + for (int i = 0; i < mouseCount; i++) { + mouseData* mouse = &mouseProperties[i]; + if (readMouse(mouse)) { + continue; + } + + for (unsigned int j = 0x80; j < 0x80 + mouse->dwButtons; j++) { + if (checkMouseState(mouse, j)) { + retVal = 0x8000 | (i << 8) | j; + goto End; + } + } + + int maxDelta = 0, maxAxis = 0; + for (unsigned int j = 0; j < MAX_MOUSEAXIS; j++) { + int delta = readMouseAxis(i, j); + if (abs(maxDelta) < abs(delta)) { + maxDelta = delta; + maxAxis = j; + } + } + if (maxDelta < 0) { + return 0x8000 | (i << 8) | (maxAxis << 1) | 0; + } + if (maxDelta > 0) { + return 0x8000 | (i << 8) | (maxAxis << 1) | 1; + } + } + + End: + + if (createBaseline) { + for (int i = 0; i < gamepadCount; i++) { + for (int j = 0; j < MAX_JOYAXIS; j++) { + gamepadProperties[i].dwAxisBaseline[j] = readGamepadAxis(i, j); + } + } + } + + return retVal; + } + + int getControlName(int code, wchar_t* deviceName, wchar_t* controlName) + { + IDirectInputDevice8W* lpdid = NULL; + DWORD* pdwAxisType = NULL; + DWORD dwMouseAxes = 0, dwPOVs = 0, dwButtons = 0; + DWORD dwObj = 0; + int deviceType = code & 0xC000; + + if (deviceName) { + deviceName[0] = '\0'; + } + if (controlName) { + controlName[0] = '\0'; + } + + switch (deviceType) { + case 0x0000: { + int i = (code >> 8) & 0x3F; + + if (i >= keyboardCount) { // This keyboard isn't connected + return 0; + } + if (keyboardProperties[i].lpdid == NULL) { + return 1; + } + + if (deviceName) { + DIDEVICEINSTANCE didi; + + memset(&didi, 0, sizeof(didi)); + didi.dwSize = sizeof(didi); + + keyboardProperties[i].lpdid->GetDeviceInfo(&didi); + _snwprintf(deviceName, MAX_PATH, L"System keyboard: %s", didi.tszInstanceName); + } + if (controlName) { + DIDEVICEOBJECTINSTANCE didoi; + + memset(&didoi, 0, sizeof(didoi)); + didoi.dwSize = sizeof(didoi); + + if (SUCCEEDED(keyboardProperties[i].lpdid->GetObjectInfo(&didoi, DIDFT_MAKEINSTANCE(code & 0xFF) | DIDFT_PSHBUTTON, DIPH_BYID))) { + wcsncpy(controlName, didoi.tszName, MAX_PATH); + } + } + + return 0; + } + case 0x4000: { + int i = (code >> 8) & 0x3F; + + if (i >= gamepadCount) { // This gamepad isn't connected + return 0; + } + lpdid = gamepadProperties[i].lpdid; + pdwAxisType = gamepadProperties[i].dwAxisType; + dwPOVs = gamepadProperties[i].dwPOVs; + dwButtons = gamepadProperties[i].dwButtons; + break; + } + case 0x8000: { + int i = (code >> 8) & 0x3F; + + if (i >= mouseCount) { // This mouse isn't connected + return 0; + } + lpdid = mouseProperties[i].lpdid; + pdwAxisType = mouseProperties[i].dwAxisType; + dwMouseAxes = mouseProperties[i].dwAxes; + dwButtons = mouseProperties[i].dwButtons; + break; + } + } + + if (lpdid == NULL) { + return 1; + } + + if (deviceName) { + DIDEVICEINSTANCE didi; + + memset(&didi, 0, sizeof(didi)); + didi.dwSize = sizeof(didi); + + if (SUCCEEDED(lpdid->GetDeviceInfo(&didi))) { + + // Special treatment for the system mouse + if ((code & 0xFF00) == 0x8000) { + _snwprintf(deviceName, MAX_PATH, L"System mouse: %s", didi.tszInstanceName); + } else { + wcsncpy(deviceName, didi.tszInstanceName, MAX_PATH); + } + } + } + if (controlName) { + DIDEVICEOBJECTINSTANCE didoi; + + unsigned int subCode = code & 0xFF; + + if ((subCode >> 1) < ((deviceType == 0x4000) ? MAX_JOYAXIS : MAX_MOUSEAXIS)) { + if (pdwAxisType[subCode >> 1] & DIDFT_AXIS) { + dwObj = pdwAxisType[subCode >> 1]; + } + } + if (subCode >= 0x10 && subCode < 0x10 + (dwPOVs << 2)) { + dwObj = DIDFT_POV | DIDFT_MAKEINSTANCE((subCode & 0x0F) >> 2); + } + if (subCode >= 0x80 && subCode < 0x80 + dwButtons) { + dwObj = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE((subCode & 0x7F) + dwMouseAxes); + } + + memset(&didoi, 0, sizeof(didoi)); + didoi.dwSize = sizeof(didoi); + + if (SUCCEEDED(lpdid->GetObjectInfo(&didoi, dwObj, DIPH_BYID))) { + wcsncpy(controlName, didoi.tszName, MAX_PATH); + } + } + + return 0; + } + + int get(void* info) + { + InterfaceInfo* pInfo = (InterfaceInfo*)info; + if (!pInfo) { + return 1; + } + + return 0; + } + +/* InputDI() { + keyboardCount = 0; + gamepadCount = 0; + mouseCount = 0; + + pDI = NULL; + hDinpWnd = NULL; + + memset(&keyboardProperties, 0, sizeof(keyboardProperties)); + memset(&gamepadProperties, 0, sizeof(gamepadProperties)); + memset(&mouseProperties, 0, sizeof(mouseProperties)); + } + + ~InputDI() { + exit(); + } +};*/ + +// Callback that evaluates and sets up each gamepad axis +static BOOL CALLBACK gamepadEnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID /*p*/) +{ +// return ((InputDI*)p)->gamepadEnumObject(instance); + return gamepadEnumObject(instance); +} + +// Callback that evaluates and sets up each mouse axis +static BOOL CALLBACK mouseEnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID /*p*/) +{ +// return ((InputDI*)p)->mouseEnumObject(instance); + return mouseEnumObject(instance); +} + +// Callback that evaluates each gamepad DirectInput device +static BOOL CALLBACK gamepadEnumCallback(LPCDIDEVICEINSTANCE instance, LPVOID /*p*/) +{ +// return ((InputDI*)p)->gamepadEnumDevice(instance); + return gamepadEnumDevice(instance); +} + +// Callback that evaluates each mouse DirectInput device +static BOOL CALLBACK mouseEnumCallback(LPCDIDEVICEINSTANCE instance, LPVOID /*p*/) +{ +// return ((InputDI*)p)->mouseEnumDevice(instance); + return mouseEnumDevice(instance); +} + +struct InputInOut InputInOutDInput = { init, exit, setCooperativeLevel, newFrame, getState, readGamepadAxis, readMouseAxis, find, getControlName, NULL, _T("DirectInput8 input") }; diff --git a/src/interface/win32/prf_performance_counter.cpp b/src/interface/win32/prf_performance_counter.cpp new file mode 100644 index 00000000..2f0adcd9 --- /dev/null +++ b/src/interface/win32/prf_performance_counter.cpp @@ -0,0 +1,88 @@ +// Profiling support +#include "burner.h" + +static double dcntTimerFreq; + +static struct { LARGE_INTEGER start; LARGE_INTEGER count[256]; LARGE_INTEGER tally; int index; int max_count; } cntSubsysInfo[16]; + +int cntExit() +{ + return 0; +} + +int cntInit() +{ + LARGE_INTEGER f; + + cntExit(); + + QueryPerformanceFrequency(&f); + + // Use milliseconds when reporting profile information + dcntTimerFreq = (double)f.QuadPart / 1000.0; + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 256; j++) { + cntSubsysInfo[i].count[j].QuadPart = 0; + } + cntSubsysInfo[i].start.QuadPart = 0; + cntSubsysInfo[i].tally.QuadPart = 0; + cntSubsysInfo[i].index = 0; + cntSubsysInfo[i].max_count = 32; + } + +#ifdef PRINT_DEBUG_INFO + dprintf(_T("*** PerformanceCounter profiler initialised (timer frequency is %.2lf MHz).\n"), (double)f.QuadPart / 1000000.0); +#endif + + return 0; +} + +int cntProfileStart(int nSubSystem) +{ + QueryPerformanceCounter(&cntSubsysInfo[nSubSystem].start); + + return 0; +} + +int cntProfileEnd(int nSubSystem) +{ + cntSubsysInfo[nSubSystem].index++; + if (cntSubsysInfo[nSubSystem].index >= cntSubsysInfo[nSubSystem].max_count) { + cntSubsysInfo[nSubSystem].index = 0; + } + + cntSubsysInfo[nSubSystem].tally.QuadPart -= cntSubsysInfo[nSubSystem].count[cntSubsysInfo[nSubSystem].index].QuadPart; + + QueryPerformanceCounter(&cntSubsysInfo[nSubSystem].count[cntSubsysInfo[nSubSystem].index]); + cntSubsysInfo[nSubSystem].count[cntSubsysInfo[nSubSystem].index].QuadPart -= cntSubsysInfo[nSubSystem].start.QuadPart; + + cntSubsysInfo[nSubSystem].tally.QuadPart += cntSubsysInfo[nSubSystem].count[cntSubsysInfo[nSubSystem].index].QuadPart; + + return 0; +} + +double cntProfileReadLast(int nSubSystem) +{ + return (double)cntSubsysInfo[nSubSystem].count[cntSubsysInfo[nSubSystem].index].QuadPart / dcntTimerFreq; +} + +double cntProfileReadAverage(int nSubSystem) +{ + return (double)(cntSubsysInfo[nSubSystem].tally.QuadPart / (cntSubsysInfo[nSubSystem].max_count)) / dcntTimerFreq; +} + +static int cntProfileGetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + + _sntprintf(szString, MAX_PATH, _T("timer frequency is %.2lfMHz\n"), (double)f.QuadPart / 1000000.0); + IntInfoAddStringModule(pInfo, szString); + + return 0; +} + +struct ProfileDo cntDoPerfCount = { cntExit, cntInit, cntProfileStart, cntProfileEnd, cntProfileReadLast, cntProfileReadAverage, cntProfileGetSettings, _T("PerformanceCounter profiler") }; diff --git a/src/interface/win32/resource/bicubic.fx b/src/interface/win32/resource/bicubic.fx new file mode 100644 index 00000000..4737b6a1 --- /dev/null +++ b/src/interface/win32/resource/bicubic.fx @@ -0,0 +1,801 @@ +// Bi-cubic filtering using 3D hardware + +// float4x4 worldViewProj : WorldViewProjection; + +// you need to change these if you load a different texture: +const float2 imageSize = { 512.0, 256.0 }; +const float2 intermediateSize = { 512.0*4, 256.0 }; +const float4 scanIntensity = { 0.5, 0.5, 0.5, 0.0 }; +const float scanSize = 1.0; + +#ifndef BC_MACROS + // Use variables to allow real-time adjustments + const float B = 1.0 / 3.0; + const float C = 1.0 / 3.0; +#else + // Use macros for speed + #ifndef B + #define B (1.0/3.0) + #endif + #ifndef C + #define C ((1.0 - B) / 2.0) + #endif +#endif + +texture imageTexture; +texture intermediateTexture; +texture scanTexture; +texture weightTex; + +sampler imageSampler = sampler_state +{ + texture = ; + MagFilter = Point; + MinFilter = Point; + MipFilter = None; + AddressU = Border; + AddressV = Border; +}; + +sampler intermediateSampler = sampler_state +{ + texture = ; + MagFilter = Point; + MinFilter = Point; + MipFilter = None; + AddressU = Border; + AddressV = Border; +}; + +sampler scanImageSampler = sampler_state +{ + texture = ; + MagFilter = Linear; + MinFilter = Linear; + MipFilter = None; + AddressU = Wrap; + AddressV = Wrap; +}; + +sampler weightSampler20 = sampler_state +{ + texture = ; + MagFilter = Linear; + MinFilter = Linear; + MipFilter = None; + AddressU = Clamp; + AddressV = Clamp; +}; + +sampler weightSampler14 = sampler_state +{ + texture = ; + MagFilter = Point; + MinFilter = Point; + MipFilter = None; + AddressU = Wrap; + AddressV = Clamp; +}; + +// vertex shader +struct a2v { + float4 pos : POSITION; + float4 texcoord : TEXCOORD0; +}; +struct v2f { + float4 pos : POSITION; + float4 texcoord : TEXCOORD0; +}; + +v2f defaultVS(a2v IN) +{ + v2f OUT; + OUT.pos = IN.pos;//mul(IN.pos, worldViewProj); + OUT.texcoord = IN.texcoord; + return OUT; +} + +v2f bicubicVS(a2v IN) +{ + v2f OUT; + OUT.pos = IN.pos;//mul(IN.pos, worldViewProj); + OUT.texcoord = IN.texcoord - 0.5 / imageSize.xyxy; + return OUT; +} + +struct a2v2 { + float4 pos : POSITION; + float4 texcoord0 : TEXCOORD0; + float4 texcoord1 : TEXCOORD1; +}; +struct v2f2 { + float4 pos : POSITION; + float4 texcoord0 : TEXCOORD0; + float4 texcoord1 : TEXCOORD1; +}; +struct v2f5 { + float4 pos : POSITION; + float4 texcoord0 : TEXCOORD0; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + float4 texcoord3 : TEXCOORD3; + float4 texcoord4 : TEXCOORD4; +}; + +v2f5 bicubicP0VS(a2v2 IN) +{ + v2f5 OUT; + float4 offsets = float4(-1.0f, 0.0f, 1.0f, 2.0f) / imageSize.xxxx; + + OUT.pos = IN.pos; + OUT.texcoord0 = IN.texcoord0 - 0.5 / imageSize.xyxy; + OUT.texcoord1 = IN.texcoord1; + + OUT.texcoord2 = OUT.texcoord0; + OUT.texcoord3 = OUT.texcoord0; + OUT.texcoord4 = OUT.texcoord0; + + OUT.texcoord2.x += offsets.x; + OUT.texcoord3.x += offsets.z; + OUT.texcoord4.x += offsets.w; + + return OUT; +} + +v2f5 bicubicP1VS(a2v2 IN) +{ + v2f5 OUT; + float4 offsets = float4(-1.0f, 0.0f, 1.0f, 2.0f) / imageSize.yyyy; + + OUT.pos = IN.pos;//mul(IN.pos, worldViewProj); + OUT.texcoord0 = IN.texcoord0 + 0.5 / intermediateSize.xyxy; + OUT.texcoord1 = IN.texcoord1; + + OUT.texcoord2 = OUT.texcoord0; + OUT.texcoord3 = OUT.texcoord0; + OUT.texcoord4 = OUT.texcoord0; + + OUT.texcoord2.y += offsets.x; + OUT.texcoord3.y += offsets.z; + OUT.texcoord4.y += offsets.w; + + return OUT; +} + +v2f2 bicubicP1ScanVS(a2v2 IN) +{ + v2f2 OUT; + + OUT.pos = IN.pos;//mul(IN.pos, worldViewProj); + OUT.texcoord0 = IN.texcoord0; + OUT.texcoord1 = IN.texcoord1; + + return OUT; +} + +// Compute 4 weights using a Mitchell-Netravali cubic polynomial: +// w = (2 - B*3/2 - C) * x^3 + (-3 + B*2 + C ) * x^2 + (1 - B/3 ) for 0 < x < 1 +// w = ( -B/6 - C) * x^3 + ( B + C*5) * x^2 + (-B*2 - C*8) * x + ( B*4/3 + C*4) for 1 < x < 2 +// B = blurring, C = ringing, 0 <= B <= 1, B + 2*C = 1, using B = 0, C = 0.75 yields nVidia's sample +float4 computeWeights(float x) +{ + float4 w; + + // First calculate (x+1, x, 1-x, 2-x) + float4 x1 = x * float4(1, 1, -1, -1) + float4(1, 0, 1, 2); + float4 x2 = x1 * x1; + float4 x3 = x2 * x1; + + // Calculate the polynomial + w = x3 * float2(-B/6.0 - C, 2.0 - B*3.0/2.0 - C).xyyx; + w += x2 * float2( B + C*5.0, -3.0 + B*2.0 + C).xyyx; + w += x1 * float2(-B*2.0 - C*8.0, 0 ).xyyx; + w += float2( B*4.0/3.0 + C*4.0, 1.0 - B/3.0 ).xyyx; + + return w; +} + +// Generate the LUT texture +float4 genWeightTex20(float2 p : POSITION) : COLOR +{ + return computeWeights(p.x); +} +float4 genWeightTex14(float2 p : POSITION) : COLOR +{ + return abs(computeWeights(p.x)); +} + +// filter 4 values +float4 cubicFilter(float4 w, float4 c0, float4 c1, float4 c2, float4 c3) +{ + return c0*w[0] + c1*w[1] + c2*w[2] + c3*w[3]; +} +float4 cubicFilterh(half4 w, half4 c0, half4 c1, half4 c2, half4 c3) +{ + return c0*w[0] + c1*w[1] + c2*w[2] + c3*w[3]; +} + +// pixel shaders + +// Single-pass, use full precision +float4 tex2D_bicubicSPHQ(sampler2D tex, float2 t) +{ + float2 f = frac(t*imageSize); + + // filter in x + float4 w = computeWeights(f.x); + float4 t0 = cubicFilter(w, tex2D(tex, t+float2(-1, -1)/imageSize), + tex2D(tex, t+float2( 0, -1)/imageSize), + tex2D(tex, t+float2( 1, -1)/imageSize), + tex2D(tex, t+float2( 2, -1)/imageSize) ); + float4 t1 = cubicFilter(w, tex2D(tex, t+float2(-1, 0)/imageSize), + tex2D(tex, t+float2( 0, 0)/imageSize), + tex2D(tex, t+float2( 1, 0)/imageSize), + tex2D(tex, t+float2( 2, 0)/imageSize) ); + float4 t2 = cubicFilter(w, tex2D(tex, t+float2(-1, 1)/imageSize), + tex2D(tex, t+float2( 0, 1)/imageSize), + tex2D(tex, t+float2( 1, 1)/imageSize), + tex2D(tex, t+float2( 2, 1)/imageSize) ); + float4 t3 = cubicFilter(w, tex2D(tex, t+float2(-1, 2)/imageSize), + tex2D(tex, t+float2( 0, 2)/imageSize), + tex2D(tex, t+float2( 1, 2)/imageSize), + tex2D(tex, t+float2( 2, 2)/imageSize) ); + + // filter in y + w = computeWeights(f.y); + return cubicFilter(w, t0, t1, t2, t3); +} + +// Single-pass, use partial precision where possible +float4 tex2D_bicubicSP(sampler2D tex, sampler1D weightTex, float2 t) +{ + float2 f = frac(t*imageSize); + + // filter in x + float4 w = tex1D(weightTex, f.x); + half4 t0 = cubicFilterh(w, tex2D(tex, t+float2(-1, -1)/imageSize), + tex2D(tex, t+float2( 0, -1)/imageSize), + tex2D(tex, t+float2( 1, -1)/imageSize), + tex2D(tex, t+float2( 2, -1)/imageSize) ); + half4 t1 = cubicFilterh(w, tex2D(tex, t+float2(-1, 0)/imageSize), + tex2D(tex, t+float2( 0, 0)/imageSize), + tex2D(tex, t+float2( 1, 0)/imageSize), + tex2D(tex, t+float2( 2, 0)/imageSize) ); + half4 t2 = cubicFilterh(w, tex2D(tex, t+float2(-1, 1)/imageSize), + tex2D(tex, t+float2( 0, 1)/imageSize), + tex2D(tex, t+float2( 1, 1)/imageSize), + tex2D(tex, t+float2( 2, 1)/imageSize) ); + half4 t3 = cubicFilterh(w, tex2D(tex, t+float2(-1, 2)/imageSize), + tex2D(tex, t+float2( 0, 2)/imageSize), + tex2D(tex, t+float2( 1, 2)/imageSize), + tex2D(tex, t+float2( 2, 2)/imageSize) ); + + // filter in y + w = tex1D(weightTex, f.y); + return cubicFilterh(w, t0, t1, t2, t3); +} + +// Multi-pass, use full precision +float4 tex2D_bicubicP0HQ(sampler2D tex, float2 t) +{ + float2 f = frac(t*imageSize); + + // filter in x + float4 w = computeWeights(f.x); + return cubicFilter(w, tex2D(tex, t+float2(-1, 0)/imageSize), + tex2D(tex, t+float2( 0, 0)/imageSize), + tex2D(tex, t+float2( 1, 0)/imageSize), + tex2D(tex, t+float2( 2, 0)/imageSize) ); + +} + +float4 tex2D_bicubicP1HQ(sampler2D tex, float2 t) +{ + float2 f = frac(t*intermediateSize); + + // filter in y + float4 w = computeWeights(f.y); + return cubicFilter(w, tex2D(tex, t+float2(0, -1)/intermediateSize), + tex2D(tex, t+float2(0, 0)/intermediateSize), + tex2D(tex, t+float2(0, 1)/intermediateSize), + tex2D(tex, t+float2(0, 2)/intermediateSize) ); + +} + +// Multi-pass, PS2.0, use partial precision where possible +float4 tex2D_bicubicP020(sampler2D tex, sampler1D weightTex, float2 t, float2 t0, float2 t1, float2 t2, float2 t3) +{ + float2 f = frac(t*imageSize); + + // filter in x + float4 w = tex1D(weightTex, f.x); + return cubicFilterh(w, tex2D(tex, t0), + tex2D(tex, t1), + tex2D(tex, t2), + tex2D(tex, t3) ); +} + +float4 tex2D_bicubicP120(sampler2D tex, sampler1D weightTex, float2 t, float2 t0, float2 t1, float2 t2, float2 t3) +{ + float2 f = frac(t*intermediateSize); + + // filter in y + float4 w = tex1D(weightTex, f.y); + return cubicFilterh(w, tex2D(tex, t0), + tex2D(tex, t1), + tex2D(tex, t2), + tex2D(tex, t3) ); +} + +// Multi-pass, compatible with PS1.4, use partial precision where possible +float4 tex2D_bicubicP014(sampler2D tex, sampler1D weightTex, float2 t, float2 t0, float2 t1, float2 t2, float2 t3) +{ + // filter in x + float4 w = tex1D(weightTex, t.x); + return cubicFilterh(w, -tex2D(tex, t0), + tex2D(tex, t1), + tex2D(tex, t2), + -tex2D(tex, t3) ); +} + +float4 tex2D_bicubicP114(sampler2D tex, sampler1D weightTex, float2 t, float2 t0, float2 t1, float2 t2, float2 t3) +{ + // filter in y + float4 w = tex1D(weightTex, t.y); + return cubicFilterh(w, -tex2D(tex, t0), + tex2D(tex, t1), + tex2D(tex, t2), + -tex2D(tex, t3) ); +} + +float4 bicubicSPHQPS(v2f IN) : COLOR +{ + return tex2D_bicubicSPHQ(imageSampler, IN.texcoord); +} + +float4 bicubicSPPS(v2f IN) : COLOR +{ + return tex2D_bicubicSP(imageSampler, weightSampler20, IN.texcoord); +} + +float4 bicubicP0HQPS(v2f IN) : COLOR +{ + return tex2D_bicubicP0HQ(imageSampler, IN.texcoord); +} +float4 bicubicP1HQPS(v2f IN) : COLOR +{ + return tex2D_bicubicP1HQ(intermediateSampler, IN.texcoord); +} + +float4 bicubicP0PS20(v2f5 IN) : COLOR +{ + return tex2D_bicubicP020(imageSampler, weightSampler20, IN.texcoord0, IN.texcoord2, IN.texcoord0, IN.texcoord3, IN.texcoord4); +} +float4 bicubicP1PS20(v2f5 IN) : COLOR +{ + return tex2D_bicubicP120(intermediateSampler, weightSampler20, IN.texcoord0, IN.texcoord2, IN.texcoord0, IN.texcoord3, IN.texcoord4); +} + +float4 bicubicP0PS14(v2f5 IN) : COLOR +{ + return tex2D_bicubicP014(imageSampler, weightSampler14, IN.texcoord1, IN.texcoord2, IN.texcoord0, IN.texcoord3, IN.texcoord4); +} +float4 bicubicP1PS14(v2f5 IN) : COLOR +{ + return tex2D_bicubicP114(intermediateSampler, weightSampler14, IN.texcoord1, IN.texcoord2, IN.texcoord0, IN.texcoord3, IN.texcoord4); +} + +// use this for arbitrarily sized scanlines +float4 bicubicP1ScanPS(v2f2 IN) : COLOR +{ + float4 col1 = tex2D(intermediateSampler, IN.texcoord0); + float4 col2 = tex2D(scanImageSampler, frac(IN.texcoord1) * scanSize); + + return col1 * (scanIntensity + col2 - scanIntensity * col2); +} + +technique SinglePassHQBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicVS(); + PixelShader = compile ps_2_0 bicubicSPHQPS(); + } +} + +technique SinglePassBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicVS(); + PixelShader = compile ps_2_0 bicubicSPPS(); + } +} + +technique MultiPassHQBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0HQPS(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicP1VS(); + PixelShader = compile ps_2_0 bicubicP1HQPS(); + } +} + +technique MultiPassBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0PS20(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicP1VS(); + PixelShader = compile ps_2_0 bicubicP1PS20(); + } +} + +technique MultiPassHP20Bicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0PS14(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicP1VS(); + PixelShader = compile ps_2_0 bicubicP1PS14(); + } +} + +technique MultiPassHP14Bicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_1_4 bicubicP0PS14(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + VertexShader = compile vs_1_1 bicubicP1VS(); + PixelShader = compile ps_1_4 bicubicP1PS14(); + } +} + +technique Bilinear < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=geometry;"; + > { + Texture[0] = ; + TexCoordIndex[0] = 0; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorOP[0] = SELECTARG1; + AlphaOp[0] = DISABLE; + + ColorOP[1] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique Point < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=geometry;"; + > { + Texture[0] = ; + TexCoordIndex[0] = 0; + AddressU[0] = CLAMP; + AddressV[0] = CLAMP; + MinFilter[0] = POINT; + MagFilter[0] = POINT; + ColorArg1[0] = TEXTURE; + ColorOP[0] = SELECTARG1; + + AlphaOp[0] = DISABLE; + ColorOP[1] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique ScanHQBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0HQPS(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { +#if 0 + VertexShader = compile vs_1_1 bicubicP1ScanVS(); + PixelShader = compile ps_2_0 bicubicP1ScanPS(); +#else + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; +#endif + } +} + +technique ScanBicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0PS20(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique ScanHP20Bicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_2_0 bicubicP0PS14(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique ScanHP14Bicubic < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + VertexShader = compile vs_1_1 bicubicP0VS(); + PixelShader = compile ps_1_4 bicubicP0PS14(); + } + pass p1 < + string Script = "Draw=geometry;"; + > { + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique ScanBilinear < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=texture;"; + > { + Texture[0] = ; + TexCoordIndex[0] = 0; + AddressU[0] = BORDER; + AddressV[0] = BORDER; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorOP[0] = SELECTARG1; + AlphaOp[0] = DISABLE; + + ColorOP[1] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } + pass p1 < + string Script = "Draw=geometry;"; + > { + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = POINT; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + +technique ScanPoint < + string Script = "Pass=p0;"; +> { + pass p0 < + string Script = "Draw=geometry;"; + > { + // Stage 0 has the scanlines + Texture[0] = ; + TexCoordIndex[0] = 1; + AddressU[0] = WRAP; + AddressV[0] = WRAP; + MinFilter[0] = LINEAR; + MagFilter[0] = LINEAR; + ColorArg1[0] = TEXTURE; + ColorArg2[0] = TFACTOR; + ColorOP[0] = ADDSMOOTH; + + AlphaOp[0] = DISABLE; + + // Stage 1 has the image + Texture[1] = ; + TexCoordIndex[1] = 0; + AddressU[1] = BORDER; + AddressV[1] = BORDER; + MinFilter[1] = LINEAR; + MagFilter[1] = POINT; + ColorArg1[1] = TEXTURE; + ColorArg2[1] = CURRENT; + ColorOP[1] = MODULATE; + + ColorOP[2] = DISABLE; + + VertexShader = NULL; + PixelShader = NULL; + } +} + diff --git a/src/interface/win32/rgb_pattern.h b/src/interface/win32/rgb_pattern.h new file mode 100644 index 00000000..9fe30961 --- /dev/null +++ b/src/interface/win32/rgb_pattern.h @@ -0,0 +1,210 @@ +// d3d RGB effects patterns + +static const unsigned char pattern_18x10_large_round[] = +{ + 0x00,0x00,0x5f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, + 0x5f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, + + 0x00,0x00,0xdf,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, + 0xdf,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x9f,0x00,0xff, + 0x00,0xdf,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x9f,0xff, + + 0x00,0x00,0xff,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x00,0x00, 0x5f,0x00,0x00,0xff, 0xe1,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xe1,0x00,0xff, + 0x00,0xff,0x00,0xff, 0x00,0xdf,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xe1,0xff, + + 0x00,0x00,0xdf,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, + 0xdf,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x9f,0x00,0xff, + 0x00,0xdf,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x9f,0xff, + + 0x00,0x00,0x5f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, + 0x5f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, + + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0xdf,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0x3f,0x00,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0x3f,0xff, + 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, + + 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xe1,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xdf,0x00,0xff, 0x00,0x5f,0x00,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xe1,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, + 0x00,0x00,0x00,0x00, 0x5f,0x00,0x00,0xff, 0xe1,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, + + 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0xdf,0x00,0xff, 0x00,0x9f,0x00,0xff, 0x00,0x3f,0x00,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x9f,0xff, 0x00,0x00,0x3f,0xff, + 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x9f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, + + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x3f,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0x3f,0x00,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x3f,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x3f,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x3f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00 +}; + +static const unsigned char pattern_12x10_large_ellipsoid[] = +{ + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x00,0x00, + + 0x7f,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x7f,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x7f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x7f,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x00,0x00, + + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x00,0x00, + + 0x1f,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x00,0x00, + + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x00,0x00, + 0x1f,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x00,0x00, + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + + 0x00,0x7f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x7f,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x00,0x00, + 0x7f,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x7f,0x00,0xff, 0x00,0xff,0x00,0xff, + + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0x00,0x00, + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x00,0x00, + 0x1f,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x00,0x00,0x00, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + + 0x1f,0x00,0x00,0x00, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x1f,0x00,0x00, 0x00,0x7f,0x00,0xff, + 0x00,0x1f,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x1f,0x00, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0x00, 0x00,0x00,0x00,0x00 +}; + +static const unsigned char pattern_10x6_large_dot[] = +{ + 0x00,0xff,0x00,0x00, 0x00,0x7f,0xff,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, + 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, 0xff,0x7f,0x00,0x00, + + 0x00,0xff,0x00,0x00, 0x00,0x3f,0xff,0x00, 0x00,0x00,0xbf,0x00, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, + 0x00,0xbf,0x00,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0xbf,0x00,0x00,0x00, 0xff,0x3f,0x00,0x00, + + 0x00,0xbf,0x00,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0xbf,0x00,0x00,0x00, 0xff,0x3f,0x00,0x00, + 0x00,0xff,0x00,0x00, 0x00,0x3f,0xff,0x00, 0x00,0x00,0xbf,0x00, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, + + 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, 0xff,0x7f,0x00,0x00, + 0x00,0xff,0x00,0x00, 0x00,0x7f,0xff,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff, + + 0x00,0xbf,0x00,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0xbf,0x00,0x00,0x00, 0xff,0x3f,0x00,0x00, + 0x00,0xff,0x00,0x00, 0x00,0x3f,0xff,0x00, 0x00,0x00,0xbf,0x00, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, + + 0x00,0xff,0x00,0x00, 0x00,0x3f,0xff,0x00, 0x00,0x00,0xbf,0x00, 0x00,0x00,0x00,0xff, 0xff,0x00,0x00,0x00, + 0x00,0xbf,0x00,0x00, 0x00,0x00,0xff,0x00, 0x00,0x00,0x00,0xff, 0xbf,0x00,0x00,0x00, 0xff,0x3f,0x00,0x00 +}; + +static const unsigned char pattern_9x10_ellipsoid[] = +{ + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, + 0x7f,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x00,0x7f,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x7f,0x00,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x7f,0xff, + 0x5f,0x00,0x00,0xff, 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, + 0x1f,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, 0x1f,0x00,0x00,0xff, + 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x5f,0x00,0x00,0xff, + 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x7f,0x00,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x7f,0xff, 0x7f,0x00,0x00,0xff, + 0xff,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x00,0x7f,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0x5f,0xff, 0x00,0x00,0xdf,0xff, 0x00,0x00,0x5f,0xff, 0x5f,0x00,0x00,0xff, + 0xdf,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0xdf,0x00,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff, 0x1f,0x00,0x00,0xff, + 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + 0x1f,0x00,0x00,0xff, 0x7f,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x7f,0x00,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0x1f,0xff, 0x00,0x00,0x7f,0xff, 0x00,0x00,0x1f,0xff +}; + +static const unsigned char pattern_8x8_mame_rgbtiny[] = +{ + 0x00,0xff,0x00,0x00, 0x00,0x80,0x00,0x00, 0x00,0x80,0xff,0x00, 0x80,0x00,0xff,0x00, + 0x80,0x00,0x00,0x00, 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + + 0x00,0xff,0x00,0x00, 0x00,0x80,0x00,0x00, 0x00,0x80,0xff,0x00, 0x80,0x00,0xff,0x00, + 0x80,0x00,0x00,0x00, 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + + 0x00,0x80,0x00,0x00, 0x00,0x00,0x00,0x00, 0x80,0xff,0x80,0x00, 0xff,0x80,0x80,0x00, + 0x00,0x00,0x00,0x00, 0x80,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + + 0x00,0x00,0x00,0x00, 0x80,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + 0x00,0x80,0x00,0x00, 0x00,0x00,0x00,0x00, 0x80,0xff,0x80,0x00, 0xff,0x80,0x80,0x00, + + 0x80,0x00,0x00,0x00, 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + 0x00,0xff,0x00,0x00, 0x00,0x80,0x00,0x00, 0x00,0x80,0xff,0x00, 0x80,0x00,0xff,0x00, + + 0x80,0x00,0x00,0x00, 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + 0x00,0xff,0x00,0x00, 0x00,0x80,0x00,0x00, 0x00,0x80,0xff,0x00, 0x80,0x00,0xff,0x00, + + 0x00,0x00,0x00,0x00, 0x80,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00, + 0x00,0x80,0x00,0x00, 0x00,0x00,0x00,0x00, 0x80,0xff,0x80,0x00, 0xff,0x80,0x80,0x00, + + 0x00,0x80,0x00,0x00, 0x00,0x00,0x00,0x00, 0x80,0xff,0x80,0x00, 0xff,0x80,0x80,0x00, + 0x00,0x00,0x00,0x00, 0x80,0x00,0x00,0x00, 0xff,0xff,0xff,0x00, 0xff,0xff,0xff,0x00 +}; + +static const unsigned char pattern_6x8_rgb_pattern[] = +{ + 0xbf,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0xbf,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x00,0xbf,0xff, 0x00,0x00,0x1f,0xff, + 0xff,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x5f,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x5f,0xff, + 0xbf,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0xbf,0x00,0xff, 0x00,0x1f,0x00,0xff, 0x00,0x00,0xbf,0xff, 0x00,0x00,0x1f,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0xbf,0xff, 0x00,0x00,0x1f,0xff, 0xbf,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0xbf,0x00,0xff, + 0x00,0x5f,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x5f,0xff, 0xff,0x00,0x00,0xff, 0x5f,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x1f,0x00,0xff, 0x00,0x00,0xbf,0xff, 0x00,0x00,0x1f,0xff, 0xbf,0x00,0x00,0xff, 0x1f,0x00,0x00,0xff, 0x00,0xbf,0x00,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 +}; + +static const unsigned char pattern_4x6_rgb_pattern[] = +{ + 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, + 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 +}; + +static const unsigned char pattern_4x4_mame_rgbtiny[] = +{ + 0x00,0xff,0x00,0x00, 0x00,0x00,0xff,0x00, 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0xff, 0xff,0xff,0xff,0xff, 0x00,0x00,0x00,0xff, 0xff,0xff,0xff,0xff, + 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0xff, 0x00,0xff,0x00,0x00, 0x00,0x00,0xff,0x00, + 0x00,0x00,0x00,0xff, 0xff,0xff,0xff,0xff, 0x00,0x00,0x00,0xff, 0xff,0xff,0xff,0xff +}; + +static const unsigned char pattern_4x4_rgb_pattern[] = +{ + 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, + 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0x00,0x00, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff +}; + +static const unsigned char pattern_3x1_aperture_grille[] = +{ + 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0x00,0xff,0xff +}; + +// pattern info + +static struct { const TCHAR* szName; const unsigned char* pData; } BuiltinPatternInfo[] = +{ + { _T("18x10_large_round.i.rgb"), pattern_18x10_large_round }, + { _T("12x10_large_ellipsoid.i.rgb"), pattern_12x10_large_ellipsoid }, + { _T("10x6_large_dot.i.rgb"), pattern_10x6_large_dot }, + { _T("9x10_ellipsoid.i.rgb"), pattern_9x10_ellipsoid }, + { _T("8x8_mame_rgbtiny.i.rgb"), pattern_8x8_mame_rgbtiny }, + { _T("6x8_rgb_pattern.i.rgb"), pattern_6x8_rgb_pattern }, + { _T("4x6_rgb_pattern.i.rgb"), pattern_4x6_rgb_pattern }, + { _T("4x4_mame_rgbtiny.i.rgb"), pattern_4x4_mame_rgbtiny }, + { _T("4x4_rgb_pattern.i.rgb"), pattern_4x4_rgb_pattern }, + { _T("3x1_aperture_grille.i.rgb"), pattern_3x1_aperture_grille }, + + { NULL, NULL } +}; diff --git a/src/interface/win32/vid_d3d.cpp b/src/interface/win32/vid_d3d.cpp new file mode 100644 index 00000000..ee38bdcb --- /dev/null +++ b/src/interface/win32/vid_d3d.cpp @@ -0,0 +1,2428 @@ +// DirectD3D blitter + +// #define USE_D3D_REFERENCE_DEVICE + +#include "burner.h" + +#if !defined BUILD_X64_EXE + +// #include "vid_directx_support.h" +#include +#include "vid_softfx.h" + +// #define ENABLE_PROFILING FBA_DEBUG + +#define DIRECT3D_VERSION 0x0700 // Use this Direct3D version +#define D3D_OVERLOADS +#include + +#include "rgb_pattern.h" + +#include "ddraw_core.h" + +const float PI = 3.14159265358979323846f; + +typedef struct _D3DTLVERTEX2 { + union { D3DVALUE sx; D3DVALUE dvSX; }; + union { D3DVALUE sy; D3DVALUE dvSY; }; + union { D3DVALUE sz; D3DVALUE dvSZ; }; + union { D3DVALUE rhw; D3DVALUE dvRHW; }; + union { D3DCOLOR color; D3DCOLOR dcColor; }; + union { D3DCOLOR specular; D3DCOLOR dcSpecular; }; + union { D3DVALUE tu; D3DVALUE dvTU; }; + union { D3DVALUE tv; D3DVALUE dvTV; }; + union { D3DVALUE tu1; D3DVALUE dvTU1; }; + union { D3DVALUE tv1; D3DVALUE dvTV1; }; +#if(DIRECT3D_VERSION >= 0x0500) + #if (defined __cplusplus) && (defined D3D_OVERLOADS) + _D3DTLVERTEX2() { } + _D3DTLVERTEX2(const D3DVECTOR& v, float _rhw, D3DCOLOR _color, D3DCOLOR _specular, float _tu, float _tv, float _tu1, float _tv1) + { + sx = v.x; sy = v.y; sz = v.z; rhw = _rhw; + color = _color; specular = _specular; + tu = _tu; tv = _tv; + tu1 = _tu1; tv1 = _tv1; + } + #endif +#endif +} D3DTLVERTEX2, *LPD3DTLVERTEX2; + +#define D3DFVF_TLVERTEX2 ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) ) + +typedef struct _D3DLVERTEX2 { + union { D3DVALUE x; D3DVALUE dvX; }; + union { D3DVALUE y; D3DVALUE dvY; }; + union { D3DVALUE z; D3DVALUE dvZ; }; + DWORD dwReserved; + union { D3DCOLOR color; D3DCOLOR dcColor; }; + union { D3DCOLOR specular; D3DCOLOR dcSpecular; }; + union { D3DVALUE tu; D3DVALUE dvTU; }; + union { D3DVALUE tv; D3DVALUE dvTV; }; + union { D3DVALUE tu1; D3DVALUE dvTU1; }; + union { D3DVALUE tv1; D3DVALUE dvTV1; }; +#if(DIRECT3D_VERSION >= 0x0500) + #if (defined __cplusplus) && (defined D3D_OVERLOADS) + _D3DLVERTEX2() { } + _D3DLVERTEX2(const D3DVECTOR& v, D3DCOLOR _color, D3DCOLOR _specular, float _tu, float _tv, float _tu1, float _tv1) + { + x = v.x; y = v.y; z = v.z; dwReserved = 0; + color = _color; specular = _specular; + tu = _tu; tv = _tv; + tu1 = _tu1; tv1 = _tv1; + } + #endif +#endif +} D3DLVERTEX2, *LPD3DLVERTEX2; + +#define D3DFVF_LVERTEX2 ( D3DFVF_XYZ | D3DFVF_RESERVED1 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) ) + +typedef struct _D3DVERTEX2 { + union { D3DVALUE x; D3DVALUE dvX; }; + union { D3DVALUE y; D3DVALUE dvY; }; + union { D3DVALUE z; D3DVALUE dvZ; }; + union { D3DVALUE nx; D3DVALUE dvNX; }; + union { D3DVALUE ny; D3DVALUE dvNY; }; + union { D3DVALUE nz; D3DVALUE dvNZ; }; + union { D3DVALUE tu; D3DVALUE dvTU; }; + union { D3DVALUE tv; D3DVALUE dvTV; }; + union { D3DVALUE tu1; D3DVALUE dvTU1; }; + union { D3DVALUE tv1; D3DVALUE dvTV1; }; +#if(DIRECT3D_VERSION >= 0x0500) + #if (defined __cplusplus) && (defined D3D_OVERLOADS) + _D3DVERTEX2() { } + _D3DVERTEX2(const D3DVECTOR& v, const D3DVECTOR& n, float _tu, float _tv, float _tu1, float _tv1) + { + x = v.x; y = v.y; z = v.z; + nx = n.x; ny = n.y; nz = n.z; + tu = _tu; tv = _tv; + tu1 = _tu1; tv1 = _tv1; + } + #endif +#endif +} D3DVERTEX2, *LPD3DVERTEX2; + +#define D3DFVF_VERTEX2 ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) ) + +static bool bLostControl; + +static bool bUsePageflip; // Use a flipping surface when in fullscreen mode +static bool bUseTriplebuffer; + +static bool bMultiTexturing; +static bool bRenderToTexture; + +struct EffectPreset { + int nUseFilter; // -1: disable, 1: enable, use specified settings, 0: don't change + int nUseEffects; // + int nUseScanlines; // + int nUseFeedback; // + int nUsePrescale; // + + int nIntensity; + int nFloor; + int nSaturation; + int nPatternMode; + TCHAR* pPatternName; + int nAttenuation; + int nBlendMode; + + int nScanIntensity; + + int nAmount; + int nOverSaturation; +}; + +static const EffectPreset PresetInfo[] = { + { 0, -1, -1, 0, -1, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }, // 1x zoom + { 1, 1, 1, 0, 0, 0x0080, 0x20, 0x00, 0, _T("4x4_rgb_pattern.i.rgb"), 0x00, 0, 0x008F8F8F, 0, 0 }, // 2x zoom + { 1, 1, 1, 0, 0, 0x00A0, 0x30, 0x00, 2, _T("4x6_rgb_pattern.i.rgb"), 0x00, 0, 0x005F5F5F, 0, 0 }, // 3x zoom + { 1, 1, 1, 0, 1, 0x0080, 0x20, 0x00, 3, _T("6x8_rgb_pattern.i.rgb"), 0x20, 0, 0x004F4F4F, 0, 0 }, // 4x zoom + { 1, 1, 1, 0, 1, 0x0060, 0x10, 0x48, 3, _T("9x10_ellipsoid.i.rgb"), 0x20, 0, 0x005F5F5F, 0, 0 }, // 5x zoom + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }, // 6x zoom + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }, // 7x zoom + { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0 }, // 8x zoom + + // Selectable presets + { 0, 1, -1, 0, 0, 0x0100, 0x80, 0x40, 2, _T("4x6_rgb_pattern.i.rgb"), 0, 1, 0, 0, 0 }, // Small Faint RGB mask + { 0, 1, -1, 0, 0, 0x0100, 0x80, 0x40, 2, _T("10x6_large_dot.i.rgb"), 0, 1, 0, 0, 0 }, // Large RGB Dot mask + { 0, 1, -1, 0, 0, 0x0100, 0x90, 0x80, 2, _T("12x10_large_ellipsoid.i.rgb"), 0, 1, 0, 0, 0 }, // Large Faint RGB mask + { 0, 1, -1, 0, 0, 0x0100, 0xC0, 0x00, 0, _T("4x4_mame_rgbtiny.i.rgb"), 0, 1, 0, 0, 0 }, // MAME rgbtiny small + { 0, 1, -1, 0, 0, 0x0100, 0xD0, 0x00, 0, _T("8x8_mame_rgbtiny.i.rgb"), 0, 1, 0, 0, 0 }, // MAME rgbtiny large + { 0, 1, 1, 0, 0, 0x0030, 0x00, 0x00, 0, _T("3x1_aperture_grille.i.rgb"), 0x20, 0, 0x00BFBFBF, 0, 0 }, // Aperture Grille + { 0, 1, -1, 0, 0, 0x0040, 0x00, 0x00, 0, _T("10x6_large_dot.i.rgb"), 0x08, 0, 0, 0, 0 }, // Large Oversaturated RGB Dot + { 0, 1, -1, 0, 0, 0x00E0, 0x00, 0x40, 3, _T("18x10_large_round.i.rgb"), 0x10, 0, 0, 0, 0 }, // Huge Oversaturated pattern +}; + +static bool bCreateImage = false; + +static bool bUseRGBEffects = false; // Use RGB effects + +static int nRGBScanlineIntensity = 0; // Scanline intensity when RGB effects are used + +static int nRGBEffectIntensity = 0x0100; // Multiply pattern RGB values with this +static int nRGBEffectFloor = 0x00; // Minimum pattern colour grey-value +static int nRGBEffectSaturation = 0x00; // Minimum saturation of the pattern colours +static int nRGBEffectPatternmode = 0; // How to use the Floor/Saturation values +static int nRGBEffectAttenuation = 0; // How much to attenuate the image before applying RGB effects +static TCHAR* pRGBEffectPatternName = _T("4x6 RGB Pattern.rgb"); // Pattern to use +static int nRGBEffectBlendmode = 1; // Set of D3D blendmodes + +static int nRotateGame; +static bool bRotateEffects; // Use rotated scanlines/RGB patterns for rotated games + +static bool bUseLighting; +static bool bUse3DProjection; + +static float fPreviousScreenAngle; +static float fPreviousScreenCurvature; + +static int nPreScale = 0; +static int nPreScaleZoom = 0; +static int nPreScaleEffect = 0; + +static IDirectDraw7* pDD = NULL; // DirectDraw interface +static IDirect3D7* pD3D = NULL; // Direct3D interface +static IDirect3DDevice7* pD3DDevice = NULL; + +static D3DDEVICEDESC7 d3dDeviceDesc; // holds capabilities of the 3D hardware + +static IDirectDrawSurface7* pPrimarySurf = NULL; // Primary surface +static IDirectDrawSurface7* pBackbuffer = NULL; // Back buffer surface + +static D3DVIEWPORT7 Viewport = {0, 0, 0, 0, 0.0f, 10.0f}; + +static RECT Dest = { 0, 0, 0, 0 }; +static RECT Render; + +static int nZoomFactor; + +static int nGameWidth = 0, nGameHeight = 0; // Game screen size +static int nGameImageWidth, nGameImageHeight; + +static IDirectDrawSurface7* pEmuImage[4] = {NULL, }; // The emulator screen surfaces/textures + +static int nTextureWidth, nTextureHeight; +static int nPreScaleTextureWidth, nPreScaleTextureHeight; +static IDirectDrawSurface7* pScanlineTexture[2] = {NULL, }; // The scanline textures + +static IDirectDrawSurface7* pRGBEffectTexture = NULL; // The RGB effects texture + +static DWORD nScanlineOp; + +static int n3DScreenGridSize; + +static D3DTLVERTEX2 vScreen[4]; // Vectors for emulator image, screen coordinates +static D3DVERTEX2* v3DScreen = NULL; // Vectors for emulator image, 3D coordinates +static D3DTLVERTEX vFeedbackImage[4]; // Vectors for feedback + +static D3DMATRIX matWorld; +static D3DMATRIX matView; +static D3DMATRIX matProjection; +// static D3DMATRIX matIdentity = D3DMATRIX(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); + +static void SetWorldMatrix() +{ +/* + matView._12 = matView._13 = matView._14 = 0.0f; + matView._21 = matView._23 = matView._24 = 0.0f; + matView._31 = matView._32 = matView._34 = 0.0f; + matView._41 = 0.0f; + matView._11 = matView._22 = matView._33 = matView._44 = 1.0f; + + matView._42 = -1.0f; + matView._43 = fNearPlane; + + pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matView); +*/ + + matWorld._12 = matWorld._13 = matWorld._14 = matWorld._21 = matWorld._24 = 0.0f; + matWorld._31 = matWorld._34 = matWorld._41 = matWorld._42 = matWorld._43 = 0.0f; + matWorld._11 = matWorld._44 = 1.0f; + + matWorld._22 = (float)cos(fVidScreenAngle); + matWorld._23 = (float)sin(fVidScreenAngle); + matWorld._32 = -(float)sin(fVidScreenAngle); + matWorld._33 = (float)cos(fVidScreenAngle); + + pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld); + +// pD3DDevice->MultiplyTransform(D3DTRANSFORMSTATE_WORLD, &matWorld); +} + +static void SetViewMatrix(float fNearPlane) +{ + matView._12 = matView._13 = matView._14 = 0.0f; + matView._21 = matView._23 = matView._24 = 0.0f; + matView._31 = matView._32 = matView._34 = 0.0f; + matView._41 = 0.0f; + matView._11 = matView._22 = matView._33 = matView._44 = 1.0f; + + matView._42 = -1.0f; + matView._43 = fNearPlane; + + pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView); +} + +static void SetProjectionMatrix(float fNearPlane) +{ + // Set projection matrix for perspective + memset(&matProjection, 0, sizeof(D3DMATRIX)); + + float fFarPlane = 1000.0f; + float Q = fFarPlane / (fFarPlane - fNearPlane); + + matProjection._11 = fNearPlane; + matProjection._22 = fNearPlane; + matProjection._33 = Q; + matProjection._34 = 1.0f; + matProjection._43 = -Q * fNearPlane; + + pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProjection); +} + +static int GetTextureSize(int nSize) +{ + int nTextureSize = 128; + + while (nTextureSize < nSize) { + nTextureSize <<= 1; + } + + return nTextureSize; +} + +static int Update3DScreen() +{ + if (bUse3DProjection) { + + if (v3DScreen == NULL) { + v3DScreen = (D3DVERTEX2*)malloc(6 * n3DScreenGridSize * n3DScreenGridSize * sizeof(D3DVERTEX2)); + if (v3DScreen == NULL) { + return 1; + } + } + + // Use a 3D world and tilt the image backward + + if (fVidScreenCurvature == 0.0f && !bUseLighting) { + v3DScreen[nRotateGame & 2 ? 3 : 0] = D3DVERTEX2(D3DVECTOR(-1.0f, 2.0f, 0.0f), D3DVECTOR(0, 0, 1), vScreen[0].tu, vScreen[0].tv, vScreen[0].tu1, vScreen[0].tv1); + v3DScreen[nRotateGame & 2 ? 2 : 1] = D3DVERTEX2(D3DVECTOR( 1.0f, 2.0f, 0.0f), D3DVECTOR(0, 0, 1), vScreen[1].tu, vScreen[1].tv, vScreen[1].tu1, vScreen[1].tv1); + v3DScreen[nRotateGame & 2 ? 1 : 2] = D3DVERTEX2(D3DVECTOR(-1.0f, 0.0f, 0.0f), D3DVECTOR(0, 0, 1), vScreen[2].tu, vScreen[2].tv, vScreen[2].tu1, vScreen[2].tv1); + v3DScreen[nRotateGame & 2 ? 0 : 3] = D3DVERTEX2(D3DVECTOR( 1.0f, 0.0f, 0.0f), D3DVECTOR(0, 0, 1), vScreen[3].tu, vScreen[3].tv, vScreen[3].tu1, vScreen[3].tv1); + } else { + int nGameAspectX = 4, nGameAspectY = 3; + + double dXAngle, dYAngle; + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & (BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED)) && nVidRotationAdjust) { + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + } + + if (nGameAspectX > nGameAspectY) { + dXAngle = (double)fVidScreenCurvature; + dYAngle = (double)fVidScreenCurvature * nGameAspectY / nGameAspectX; + } else { + dXAngle = (double)fVidScreenCurvature * nGameAspectX / nGameAspectY; + dYAngle = (double)fVidScreenCurvature; + } + + double dXFactor = 1.0 / sin(dXAngle / 2); + double dYFactor = 1.0 / sin(dYAngle / 2); + + for (int y = 0; y < n3DScreenGridSize; y++) { + + double dTop = dYFactor * sin(-dYAngle / 2 + dYAngle * y / n3DScreenGridSize); + double dBottom = dYFactor * sin(-dYAngle / 2 + dYAngle * (y + 1) / n3DScreenGridSize); + + double dTopFactor = cos(-dYAngle / 2 + dYAngle * y / n3DScreenGridSize); + double dBottomFactor = cos(-dYAngle / 2 + dYAngle * (y + 1) / n3DScreenGridSize); + + for (int x = 0; x < n3DScreenGridSize; x++) { + + double dLeft = dXFactor * sin(-dXAngle / 2 + dXAngle * x / n3DScreenGridSize); + double dRight = dXFactor * sin(-dXAngle / 2 + dXAngle * (x + 1) / n3DScreenGridSize); + + double dLeftFactor = cos(-dXAngle / 2 + dXAngle * x / n3DScreenGridSize); + double dRightFactor = cos(-dXAngle / 2 + dXAngle * (x + 1) / n3DScreenGridSize); + + if (nRotateGame & 1) { + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 0] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dLeft), (float)(1.0 - dLeftFactor * dTop), (float)(1.0 - dTopFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 1] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dRight), (float)(1.0 - dRightFactor * dTop), (float)(1.0 - dTopFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 2] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dLeft), (float)(1.0 - dLeftFactor * dBottom), (float)(1.0 - dBottomFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 3] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dRight), (float)(1.0 - dRightFactor * dTop), (float)(1.0 - dTopFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 4] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dLeft), (float)(1.0 - dLeftFactor * dBottom), (float)(1.0 - dBottomFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * y + ((n3DScreenGridSize - 1 - x) * 6 * n3DScreenGridSize) + 5] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dRight), (float)(1.0 - dRightFactor * dBottom), (float)(1.0 - dBottomFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + } else { + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 0] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dLeft), (float)(1.0 - dLeftFactor * dTop), (float)(1.0 - dTopFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 1] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dRight), (float)(1.0 - dRightFactor * dTop), (float)(1.0 - dTopFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 2] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dLeft), (float)(1.0 - dLeftFactor * dBottom), (float)(1.0 - dBottomFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 3] = D3DVERTEX2(D3DVECTOR((float)(dTopFactor * dRight), (float)(1.0 - dRightFactor * dTop), (float)(1.0 - dTopFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 4] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dLeft), (float)(1.0 - dLeftFactor * dBottom), (float)(1.0 - dBottomFactor * dLeftFactor) ), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + v3DScreen[6 * x + (y * 6 * n3DScreenGridSize) + 5] = D3DVERTEX2(D3DVECTOR((float)(dBottomFactor * dRight), (float)(1.0 - dRightFactor * dBottom), (float)(1.0 - dBottomFactor * dRightFactor)), D3DVECTOR(0, 0, 0), 0, 0, 0, 0); + } + } + } + + // Compute the vertex normals + for (int x = 0; x < n3DScreenGridSize; x++) { + for (int y = 0; y < n3DScreenGridSize; y++) { + int i = 6 * x + (y * 6 * n3DScreenGridSize); + + for (int j = 0; j < 6; j++) { + v3DScreen[i + j].nx = v3DScreen[i + j].x; v3DScreen[i + j].ny = v3DScreen[i + j].y - 1.0f; v3DScreen[i + j].nz = (1.0f - v3DScreen[i + j].z) / fVidScreenCurvature; + } + } + } + + // Texture mapping coordinates for the emulator image + for (int y = 0; y < n3DScreenGridSize; y++) { + float tuLeft, tuRight; + float tvTop, tvBottom; + + int ry = nRotateGame & 2 ? n3DScreenGridSize - 1 - y : y; + + tvTop = ((float)nGameImageHeight / nTextureHeight) * y / n3DScreenGridSize; + tvBottom = ((float)nGameImageHeight / nTextureHeight) * (y + 1) / n3DScreenGridSize; + + for (int x = 0; x < n3DScreenGridSize; x++) { + + int rx = nRotateGame & 2 ? n3DScreenGridSize - 1 - x : x; + + tuLeft = (float(nGameImageWidth) / nTextureWidth) * x / n3DScreenGridSize; + tuRight = (float(nGameImageWidth) / nTextureWidth) * (x + 1) / n3DScreenGridSize; + + if (nRotateGame & 1) { + int i = 6 * (n3DScreenGridSize - 1 - rx) + ((n3DScreenGridSize - 1 - ry) * 6 * n3DScreenGridSize); + v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tv = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tv = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tv = tvTop; + + v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tv = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tv = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tv = tvBottom; + } else { + int i = 6 * rx + (ry * 6 * n3DScreenGridSize); + v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tv = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tv = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tv = tvBottom; + + v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tv = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tu = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tv = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tu = tuRight; v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tv = tvBottom; + } + } + } + + // Texture mapping coordinates for the scanlines + for (int y = 0; y < n3DScreenGridSize; y++) { + float tuLeft, tuRight; + float tvTop, tvBottom; + + int ry = nRotateGame & 2 ? n3DScreenGridSize - 1 - y : y; + + tvTop = float(nGameImageHeight) * y / n3DScreenGridSize; + tvBottom = float(nGameImageHeight) * (y + 1) / n3DScreenGridSize; + + for (int x = 0; x < n3DScreenGridSize; x++) { + + int rx = nRotateGame & 2 ? n3DScreenGridSize - 1 - x : x; + + tuLeft = float(nGameImageWidth) * x / n3DScreenGridSize; + tuRight = float(nGameImageWidth) * (x + 1) / n3DScreenGridSize; + + if ((!(nRotateGame & 1) && bRotateEffects) || ((nRotateGame & 1) && !bRotateEffects)) { + int i = 6 * (n3DScreenGridSize - 1 - rx) + ((n3DScreenGridSize - 1 - ry) * 6 * n3DScreenGridSize); + v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tv1 = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tv1 = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tv1 = tvTop; + + v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tv1 = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tv1 = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tv1 = tvBottom; + } else { + int i = 6 * rx + (ry * 6 * n3DScreenGridSize); + v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 5 : 0)].tv1 = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 4 : 1)].tv1 = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 3 : 2)].tv1 = tvBottom; + + v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 2 : 3)].tv1 = tvTop; + v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tu1 = tuLeft; v3DScreen[i + (nRotateGame & 2 ? 1 : 4)].tv1 = tvBottom; + v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tu1 = tuRight; v3DScreen[i + (nRotateGame & 2 ? 0 : 5)].tv1 = tvBottom; + } + } + } + } + } + + return 0; +} + +static void PutPixel(unsigned char** ppSurface, unsigned int nColour) +{ + switch (nVidScrnDepth) { + case 15: + *((unsigned short*)(*ppSurface)) = ((nColour >> 9) & 0x7C00) | ((nColour >> 6) & 0x03E0) | ((nColour >> 3) & 0x001F); + *ppSurface += 2; + break; + case 16: + *((unsigned short*)(*ppSurface)) = ((nColour >> 8) & 0xF800) | ((nColour >> 5) & 0x07E0) | ((nColour >> 3) & 0x001F); + *ppSurface += 2; + break; + case 24: + (*ppSurface)[0] = (nColour >> 16) & 0xFF; + (*ppSurface)[1] = (nColour >> 8) & 0xFF; + (*ppSurface)[2] = (nColour >> 0) & 0xFF; + *ppSurface += 3; + break; + case 32: + *((unsigned int*)(*ppSurface)) = nColour; + *ppSurface += 4; + break; + } +} + +static int ReleaseSurfaces() +{ + // Release effects surfaces + RELEASE(pRGBEffectTexture); + RELEASE(pScanlineTexture[0]); + RELEASE(pScanlineTexture[1]); + + // Release game-image surfaces + RELEASE(pEmuImage[0]); + RELEASE(pEmuImage[1]); + RELEASE(pEmuImage[2]); + RELEASE(pEmuImage[3]); + + VidSFreeVidImage(); + + return 0; +} + +static int vidExit() +{ + VidSExitOSD(); + + if (v3DScreen) { + free(v3DScreen); + v3DScreen = NULL; + } + + VidSoftFXExit(); + + ReleaseSurfaces(); + + VidSRestoreGamma(); + + RELEASE(pD3DDevice); + RELEASE(pD3D); + + VidSRestoreScreenMode(); + + if (bUsePageflip == false) { + RELEASE(pBackbuffer); // explicitly free the off-screen surface when not usign pageflipping + } + RELEASE(pPrimarySurf); + pBackbuffer = NULL; + + VidSExit(); + + RELEASE(pDD); + + return 0; +} + +static HRESULT CALLBACK myEnumTexturesCallback(DDPIXELFORMAT* pddpf, void* pPreferredddpf) +{ + if (pddpf->dwFlags == DDPF_RGB && pddpf->dwRGBBitCount == 16) { + + if (VidSoftFXCheckDepth(nPreScaleEffect, 15) == 15) { + // Use 15-bit format if supported by the 3D hardware and the effects blitter + if(pddpf->dwRBitMask == 0x7C00 && pddpf->dwGBitMask == 0x03E0 && pddpf->dwBBitMask == 0x001F) { + memcpy(pPreferredddpf, pddpf, sizeof(DDPIXELFORMAT) ); + + return D3DENUMRET_CANCEL; + } + } + + // Use 16-bit format otherwise + if(pddpf->dwRBitMask == 0xF800 && pddpf->dwGBitMask == 0x07E0 && pddpf->dwBBitMask == 0x001F) { + memcpy(pPreferredddpf, pddpf, sizeof(DDPIXELFORMAT) ); + } + } + return D3DENUMRET_OK; +} + +static int vidCreateGameSurfaces() +{ + bool bForceTextureFormat; + + DDSURFACEDESC2 ddsd; + DDPIXELFORMAT ddpf; + + // Determine if we should use a texture format different from the screen format + bForceTextureFormat = false; + if (VidSoftFXCheckDepth(nPreScaleEffect, 16) != 32 && nVidScrnDepth > 16 && + ((bDrvOkay || VidSoftFXCheckDepth(nPreScaleEffect, 32) != 32) || + (bDrvOkay && (bVidForce16bit || !bDoGamma || (nVidFullscreen && bVidUseHardwareGamma) || (!nVidFullscreen && bHardwareGammaOnly))))) + { + memset(&ddpf, 0, sizeof(DDPIXELFORMAT)); + + pD3DDevice->EnumTextureFormats(&myEnumTexturesCallback, (void*)&ddpf); + + if (ddpf.dwSize) { + bForceTextureFormat = true; + } + } + + // Create a secondary surface to render the game image onto for the feedback effect + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE; + + ddsd.dwWidth = (nPreScale & 1) ? nPreScaleTextureWidth : nTextureWidth; + ddsd.dwHeight = (nPreScale & 2) ? nPreScaleTextureHeight : nTextureHeight; + + memset(&ddsd.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT)); + + if (FAILED(pDD->CreateSurface(&ddsd, &pEmuImage[1], NULL))) { + bRenderToTexture = false; + } else { + + IDirectDrawSurface7* pPreviousTarget; + if (FAILED(pD3DDevice->GetRenderTarget(&pPreviousTarget))) { + bRenderToTexture = false; + } else { + if (FAILED(pD3DDevice->SetRenderTarget(pEmuImage[1], 0))) { + bRenderToTexture = false; + } else { + bRenderToTexture = true; + + VidSClearSurface(pEmuImage[1], 0, NULL); + } + pD3DDevice->SetRenderTarget(pPreviousTarget, 0); + pPreviousTarget->Release(); + } + } + + if (!bRenderToTexture) { + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Warning: Device can't render to textures. Using fall-back method for pre-scale/feedback.\n")); +#endif + + RELEASE(pEmuImage[1]); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + + ddsd.dwWidth = (nPreScale & 1) ? nPreScaleTextureWidth : nTextureWidth; + ddsd.dwHeight = (nPreScale & 2) ? nPreScaleTextureHeight : nTextureHeight; + + memset(&ddsd.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT)); + + if (FAILED(pDD->CreateSurface(&ddsd, &pEmuImage[1], NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create secondary game surface(s) for pre-scale/feedback.\n")); +#endif + return 1; + } + + VidSClearSurface(pEmuImage[1], 0, NULL); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = (nPreScale & 1) ? nPreScaleTextureWidth : nTextureWidth; + ddsd.dwHeight = (nPreScale & 2) ? nPreScaleTextureHeight : nTextureHeight; + + if (FAILED(pDD->CreateSurface(&ddsd, &pEmuImage[3], NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create secondary game surface(s) for pre-scale/feedback.\n")); +#endif + return 1; + } + + VidSClearSurface(pEmuImage[3], 0, NULL); + } + + if (nVidTransferMethod <= 0) { + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = nTextureWidth; + ddsd.dwHeight = nTextureHeight; + + if (nPreScaleEffect) { + ddsd.dwWidth = nPreScaleTextureWidth; + ddsd.dwHeight = nPreScaleTextureHeight; + } + + if (bForceTextureFormat) { + ddsd.dwFlags |= DDSD_PIXELFORMAT; + + memcpy(&ddsd.ddpfPixelFormat, &ddpf, sizeof(DDPIXELFORMAT)); + } + + if (FAILED(pDD->CreateSurface(&ddsd, &pEmuImage[2], NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create secondary game surface for transfer.\n")); +#endif + return 1; + } + + VidSClearSurface(pEmuImage[2], 0, NULL); + } + + // Create a surface for the texture that will contain the game image + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + if (nVidTransferMethod > 0) { + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_HINTDYNAMIC | DDSCAPS2_TEXTUREMANAGE; + } + + ddsd.dwWidth = nTextureWidth; + ddsd.dwHeight = nTextureHeight; + + if (nPreScaleEffect) { + ddsd.dwWidth = nPreScaleTextureWidth; + ddsd.dwHeight = nPreScaleTextureHeight; + } + + if (bForceTextureFormat) { + ddsd.dwFlags |= DDSD_PIXELFORMAT; + + memcpy(&ddsd.ddpfPixelFormat, &ddpf, sizeof(DDPIXELFORMAT)); + } + + if (FAILED(pDD->CreateSurface(&ddsd, &pEmuImage[0], NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create game texture surface.\n")); +#endif + return 1; + } + + VidSClearSurface(pEmuImage[0], 0, NULL); + + return 0; +} + +static int InitEffectsSurfaces() +{ + DDSURFACEDESC2 ddsd; + + for (int i = 0, nSize = 2; i < 2; i++, nSize <<= 1) { + int Scanlines[][8] = { { 0xFFFFFF, 0x000000 }, { 0x9F9F9F, 0xFFFFFF, 0x9F9F9F, 0x000000 } }; + + if (pScanlineTexture[i]) { + + if (FAILED(pScanlineTexture[i]->IsLost())) { + if (FAILED(pScanlineTexture[i]->Restore())) { + return 1; + } + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (FAILED(pScanlineTexture[i]->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL))) { + return 1; + } + + for (int y = 0; y < nSize; y++) { + unsigned char* pSurface = (unsigned char*)ddsd.lpSurface + y * ddsd.lPitch; + int nColour = Scanlines[i][y]; + for (int x = 0; x < nSize; x++) { + PutPixel(&pSurface, nColour); + } + } + + pScanlineTexture[i]->Unlock(NULL); + } + } + + if (pRGBEffectTexture) { + TCHAR pFilename[MAX_PATH] = _T(""); + int nPatternSize, nPatternXSize, nPatternYSize; + unsigned char* RGBPattern = NULL; + + if (FAILED(pRGBEffectTexture->IsLost())) { + if (FAILED(pRGBEffectTexture->Restore())) { + return 1; + } + } + + // Get the filename and size of a pattern + _tcscpy(pFilename, _T("pattern\\")); + _tcscat(pFilename, pRGBEffectPatternName); + _stscanf(pRGBEffectPatternName, _T("%i x %i"), &nPatternXSize, &nPatternYSize); + nPatternSize = nPatternXSize * nPatternYSize * 4; + + for (int i = 0; BuiltinPatternInfo[i].szName; i++) { + if (!_tcscmp(BuiltinPatternInfo[i].szName, pRGBEffectPatternName)) { + RGBPattern = (unsigned char*)malloc(nPatternSize); + memcpy(RGBPattern, BuiltinPatternInfo[i].pData, nPatternSize); + break; + } + } + + if (RGBPattern == NULL) { + FILE* fp = _tfopen(pFilename, _T("rb")); + if (fp) { + + // Read the file containing the pattern data + fseek(fp, 0, SEEK_END); + + // Check if the file is the correct size. + if (ftell(fp) != nPatternSize) { + + fclose(fp); + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("RGB pattern \'%s\' has an incorrect size.\nIt should be %i bytes long."), pRGBEffectPatternName, nPatternSize); + FBAPopupDisplay(PUF_TYPE_WARNING); + return 1; + } + + RGBPattern = (unsigned char*)malloc(nPatternSize); + fseek(fp, 0, SEEK_SET); + fread(RGBPattern, 1, nPatternSize, fp); + fclose(fp); + } + } + + if (RGBPattern) { + // Pre-process the pattern + for (int y = 0; y < nPatternYSize; y++) { + unsigned char* pPattern = &RGBPattern[y * (nPatternXSize << 2)]; + for (int x = 0; x < nPatternXSize; x++) { + switch (nRGBEffectPatternmode) { + case 0: + case 1: { + if (nRGBEffectPatternmode == 0 || pPattern[(x << 2) + 3]) { + int n; + for (int z = 0; z < 3; z++) { + n = nRGBEffectIntensity * pPattern[(x << 2) + z] / 256; + pPattern[(x << 2) + z] = (n > 255) ? 255 : nRGBEffectFloor + (n * (256 - nRGBEffectFloor) / 256); + } + } + break; + } + case 2: + case 3: { + int nSaturate = 0; + int nMax = 0; + int n; + + if (pPattern[(x << 2) + 0] != pPattern[(x << 2) + 1] || pPattern[(x << 2) + 0] != pPattern[(x << 2) + 2] || pPattern[(x << 2) + 1] != pPattern[(x << 2) + 2]) { + + if (pPattern[(x << 2) + 0] >= pPattern[(x << 2) + 1] && pPattern[(x << 2) + 0] >= pPattern[(x << 2) + 2]) { + nMax = pPattern[(x << 2) + 0]; + nSaturate |= 1; + } + if (pPattern[(x << 2) + 1] >= pPattern[(x << 2) + 0] && pPattern[(x << 2) + 1] >= pPattern[(x << 2) + 2]) { + nMax = pPattern[(x << 2) + 1]; + nSaturate |= 2; + } + if (pPattern[(x << 2) + 2] >= pPattern[(x << 2) + 0] && pPattern[(x << 2) + 2] >= pPattern[(x << 2) + 1]) { + nMax = pPattern[(x << 2) + 2]; + nSaturate |= 4; + } + + nSaturate ^= 7; + } + + for (int z = 0; z < 3; z++) { + if (nRGBEffectPatternmode == 2 || pPattern[(x << 2) + 3]) { + n = pPattern[(x << 2) + z]; + if (nSaturate & (1 << z)) { + n += (nMax - n) * nRGBEffectSaturation / 256; + } + n = n * nRGBEffectIntensity / 256; + pPattern[(x << 2) + z] = (n > 255) ? 255 : nRGBEffectFloor + (n * (256 - nRGBEffectFloor) / 256); + } + } + break; + } + } + } + } + + // Replicate the pattern over the needed size + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (FAILED(pRGBEffectTexture->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL))) { + return 1; + } else { + if ((!(nRotateGame & 1) && bRotateEffects) || ((nRotateGame & 1) && !bRotateEffects)) { + for (unsigned int y = 0; y < ddsd.dwHeight; y++) { + int ry = nRotateGame & 2 ? ddsd.dwHeight - 1 - y : y; + unsigned char* pSurface = (unsigned char*)ddsd.lpSurface + ddsd.lPitch * y; + unsigned char* pPattern = &RGBPattern[(ry % nPatternXSize) << 2]; + for (unsigned int x = 0; x < ddsd.dwWidth; x++) { + int rx = nRotateGame & 2 ? ddsd.dwWidth - 1 - x : x; + int nColour = pPattern[((rx % nPatternYSize) * (nPatternXSize << 2)) + 0] << 16; + nColour |= pPattern[((rx % nPatternYSize) * (nPatternXSize << 2)) + 1] << 8; + nColour |= pPattern[((rx % nPatternYSize) * (nPatternXSize << 2)) + 2]; + + PutPixel(&pSurface, nColour); + } + } + } else { + for (unsigned int y = 0; y < ddsd.dwHeight; y++) { + int ry = nRotateGame & 2 ? ddsd.dwHeight - 1 - y : y; + unsigned char* pSurface = (unsigned char*)ddsd.lpSurface + ddsd.lPitch * y; + unsigned char* pPattern = &RGBPattern[(ry % nPatternYSize) * nPatternXSize << 2]; + for (unsigned int x = 0; x < ddsd.dwWidth; x++) { + int rx = nRotateGame & 2 ? ddsd.dwWidth - 1 - x : x; + int nColour = pPattern[((rx % nPatternXSize) << 2) + 0] << 16; + nColour |= pPattern[((rx % nPatternXSize) << 2) + 1] << 8; + nColour |= pPattern[((rx % nPatternXSize) << 2) + 2]; + + PutPixel(&pSurface, nColour); + } + } + } + pRGBEffectTexture->Unlock(NULL); + } + + if (RGBPattern) { + free(RGBPattern); + RGBPattern = NULL; + } + } else { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE, _T("Couldn't find RGB pattern.")); + FBAPopupDisplay(PUF_TYPE_WARNING); + return 1; + } + } + + return 0; +} + +// Create extra surfaces for textures and effects +static int vidCreateEffectsSurfaces() +{ + DDSURFACEDESC2 ddsd; + + // Create the scanline textures + for (int i = 0, nSize = 2; i < 2; i++, nSize <<= 1) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = nSize; + ddsd.dwHeight = nSize; + + if (FAILED(pDD->CreateSurface(&ddsd, &pScanlineTexture[i], NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create scanline texture.\n")); +#endif + return 1; + } + } + + if (bUseRGBEffects) { + // Create the RGB effect texture + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; +// ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + if (!nVidFullscreen || (nVidFullscreen && bVidFullStretch)) { + ddsd.dwWidth = nVidScrnWidth; + ddsd.dwHeight = nVidScrnHeight; + } else { + if (bVidArcaderes) { + ddsd.dwWidth = nGameWidth; + ddsd.dwHeight = nGameHeight; + } else { + RECT rect = { 0, 0, nVidScrnWidth, nVidScrnHeight }; + + VidImageSize(&rect, nGameWidth, nGameHeight); + + ddsd.dwWidth = rect.right - rect.left; + ddsd.dwHeight = rect.bottom - rect.top; + } + } + + if (FAILED(pDD->CreateSurface(&ddsd, &pRGBEffectTexture, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create RGB effects surface.\n")); +#endif + return 1; + } + } + + InitEffectsSurfaces(); + + return 0; +} + +static int vidAllocSurfaces() +{ + if (pDD == NULL || pD3DDevice == NULL) { + return 1; + } + + if (bDrvOkay) { + BurnDrvGetFullSize(&nVidImageWidth, &nVidImageHeight); + BurnDrvGetVisibleOffs(&nVidImageLeft, &nVidImageTop); + } + + if (nRotateGame & 1) { + nGameImageWidth = nGameHeight; + nGameImageHeight = nGameWidth; + } else { + nGameImageWidth = nGameWidth; + nGameImageHeight = nGameHeight; + } + + nTextureWidth = GetTextureSize(nGameImageWidth); + nTextureHeight = GetTextureSize(nGameImageHeight); + nPreScaleTextureWidth = GetTextureSize(nGameImageWidth * nPreScaleZoom); + nPreScaleTextureHeight = GetTextureSize(nGameImageHeight * nPreScaleZoom); + + // 2xSaI etc. needs an extra line below the image + if (nPreScaleEffect >= FILTER_SUPEREAGLE && nPreScaleEffect <= FILTER_SUPER_2XSAI && nGameImageHeight == nTextureHeight) { + nTextureHeight <<= 1; + } + + if (d3dDeviceDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) { + if (nTextureWidth < nTextureHeight) { + nTextureWidth = nTextureHeight; + } + if (nTextureHeight < nTextureWidth) { + nTextureHeight = nTextureWidth; + } + } + + if ((int)d3dDeviceDesc.dwMaxTextureWidth < nTextureWidth || (int)d3dDeviceDesc.dwMaxTextureHeight < nTextureHeight) { + FBAPopupAddText(PUF_TEXT_NO_TRANSLATE,_T("Required texture size not supported by 3D hardware.")); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } + + // Allocate all DirectX surfaces + if (vidCreateGameSurfaces()) { + ReleaseSurfaces(); + return 1; + } + if (vidCreateEffectsSurfaces()) { + ReleaseSurfaces(); + return 1; + } + + nVidImageDepth = VidSGetSurfaceDepth(pEmuImage[0]); // Get colourdepth of game (texture) surface + + for (int i = 0; i < 2; i++) { + int nDepth[] = { 15, 16, 32 }; + if (VidSoftFXCheckDepth(nPreScaleEffect, nDepth[i]) == nVidImageDepth) { + nVidImageDepth = nDepth[i]; + break; + } + } + + nVidImageBPP = (nVidImageDepth + 7) >> 3; + + VidSAllocVidImage(); // Set up memory buffer for Burn library + + SetBurnHighCol(nVidImageDepth); + + return 0; +} + +static int vidClear() +{ + if (pPrimarySurf == NULL) { + return 1; + } + + //if(bVidVSync && !nVidFullscreen) { pDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } + + if (nVidFullscreen) { + VidSClearSurface(pPrimarySurf, 0, NULL); // Clear front buffer + if (bUsePageflip) { + pPrimarySurf->Flip(NULL, DDFLIP_WAIT); + VidSClearSurface(pPrimarySurf, 0, NULL); // Clear 1st page of backbuffer + + if (bUseTriplebuffer) { + pPrimarySurf->Flip(NULL, DDFLIP_WAIT); + VidSClearSurface(pPrimarySurf, 0, NULL); // Clear 2nd page of backbuffer + } + + pPrimarySurf->Flip(NULL, DDFLIP_WAIT); + } else { + VidSClearSurface(pBackbuffer, 0, NULL); // Clear backbuffer + } + } else { + VidSClearSurface(pBackbuffer, 0, NULL); // Clear backbuffer + } + + return 0; +} + +static int vidInitBuffers(bool bTriple) +{ + DDSURFACEDESC2 ddsd; + DDSCAPS2 ddscaps; + + bUsePageflip = false; + + if (bDrvOkay && nVidFullscreen) { + if (bTriple) { + bUsePageflip = true; + } else { + DDCAPS ddcaps; + + memset(&ddcaps, 0, sizeof(ddcaps)); + ddcaps.dwSize = sizeof(ddcaps); + + pDD->GetCaps(&ddcaps, NULL); + //if (ddcaps.dwCaps2 & DDCAPS2_FLIPNOVSYNC) { + bUsePageflip = true; + //} + } + } + + // Create the primary surface + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (nVidFullscreen && bUsePageflip) { + // Allocate a complex surface that supports page flipping. + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY; + ddsd.dwBackBufferCount = bVidTripleBuffer ? 2 : 1; + } else { + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; + } + + if (FAILED(pDD->CreateSurface(&ddsd, &pPrimarySurf, NULL))) { + pPrimarySurf = NULL; + return 1; + } + + // Get the back buffer + if (nVidFullscreen && bUsePageflip) { + memset(&ddscaps, 0, sizeof(ddscaps)); + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + if (FAILED(pPrimarySurf->GetAttachedSurface(&ddscaps, &pBackbuffer))) { + RELEASE(pPrimarySurf); + pBackbuffer = NULL; + return 1; + } + + bUseTriplebuffer = bTriple; + + } else { + // Running in windowed mode or using blt() transfer the final image. Allocate an off-screen surface to render to. + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY; + ddsd.dwWidth = nVidScrnWidth; + ddsd.dwHeight = nVidScrnHeight; + if (FAILED(pDD->CreateSurface(&ddsd, &pBackbuffer, NULL))) { + RELEASE(pPrimarySurf); + pBackbuffer = NULL; + return 1; + } + } + + nVidScrnDepth = VidSGetSurfaceDepth(pPrimarySurf); // Get colourdepth of primary surface + + vidClear(); // Clear the surfaces we've just allocated + + return 0; +} + +static GUID MyGuid; +static int nWantDriver; + +#if 1 && defined(PRINT_DEBUG_INFO) +static int nCurrentDriver; +#ifdef UNICODE +static BOOL PASCAL MyEnumDisplayDrivers(GUID FAR* pGuid, LPWSTR pszDesc, LPWSTR /*pszName*/, LPVOID /*pContext*/, HMONITOR hMonitor) +#else +static BOOL PASCAL MyEnumDisplayDrivers(GUID FAR* pGuid, LPSTR pszDesc, LPSTR /*pszName*/, LPVOID /*pContext*/, HMONITOR hMonitor) +#endif +{ + if (nCurrentDriver == nWantDriver && pGuid) { + memcpy(&MyGuid, pGuid, sizeof(GUID)); + } + + if (nCurrentDriver == 0) { + dprintf(_T(" %s\n"), pszDesc); + } else { + MONITORINFOEX mi; + mi.cbSize = sizeof(mi); + + GetMonitorInfo(hMonitor, (MONITORINFO*)&mi); + + dprintf(_T(" Display %d (%s on %s"), nCurrentDriver, mi.szDevice, pszDesc); + if (mi.dwFlags & MONITORINFOF_PRIMARY) { + dprintf(_T(", primary")); + } + dprintf(_T(")\n")); + } + + nCurrentDriver++; + + return DDENUMRET_OK; +} +#endif + +#if 0 +static HRESULT CALLBACK MyEnumDevicesCallback(LPSTR lpDeviceDescription, LPSTR /*lpDeviceName*/, LPD3DDEVICEDESC7, LPVOID) +{ + dprintf(_T(" %s\n"), lpDeviceDescription); + + return DDENUMRET_OK; +} +#endif + +static int vidInit() +{ +#ifdef ENABLE_PROFILING + ProfileInit(); +#endif + + bCreateImage = true; + + bUseTriplebuffer = false; + + hVidWnd = nVidFullscreen ? hScrnWnd : hVideoWindow; // Use Screen window for video + + nWantDriver = 0; +#if 1 && defined(PRINT_DEBUG_INFO) + nCurrentDriver = 0; + memset(&MyGuid, 0, sizeof(GUID)); + dprintf(_T(" ** Enumerating available DirectDraw drivers:\n")); + _DirectDrawEnumerateEx(MyEnumDisplayDrivers, NULL, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_DETACHEDSECONDARYDEVICES | DDENUM_NONDISPLAYDEVICES); +#endif + + // Get pointer to DirectDraw device + _DirectDrawCreateEx(nWantDriver ? &MyGuid : NULL, (void**)&pDD, IID_IDirectDraw7, NULL); + + VidSInit(pDD); + + // Get pointer to D3D device + if (FAILED(pDD->QueryInterface(IID_IDirect3D7, (void**)&pD3D))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't access Direct3D.\n")); +#endif + vidExit(); + return 1; + } + +#if 0 && defined(PRINT_DEBUG_INFO) + dprintf(_T(" ** Enumerating available 3D devices:\n")); + pD3D->EnumDevices(MyEnumDevicesCallback, NULL); +#endif + + pPrimarySurf = NULL; // No primary surface yet + pBackbuffer = NULL; + + nGameWidth = nVidImageWidth; nGameHeight = nVidImageHeight; + + nRotateGame = 0; + if (bDrvOkay) { + // Get the game screen size + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (nVidRotationAdjust & 1) { + int n = nGameWidth; + nGameWidth = nGameHeight; + nGameHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } else { + nRotateGame |= 1; + } + } + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + nRotateGame ^= 2; + } + } + + nPreScale = 0; + nPreScaleZoom = 2; + nPreScaleEffect = 0; + if (nVidBlitterOpt[nVidSelect] & 0x01000000) { + nPreScale = 3; + + if (nVidBlitterOpt[nVidSelect] & 0x02000000) { + nPreScaleEffect = (unsigned long long)(nVidBlitterOpt[nVidSelect] >> 32); + nPreScaleZoom = VidSoftFXGetZoom(nPreScaleEffect); + } else { + if (bVidScanlines) { + nPreScale &= 2; + } + } + } + + // Set up the display mode + if (nVidFullscreen) { + int nZoomlevel; + if (nVidBlitterOpt[nVidSelect] & 0x04000000) { + nZoomlevel = nPreScaleZoom; + } else { + nZoomlevel = nScreenSize; + } + if (VidSEnterFullscreenMode(nZoomlevel, 0)) { + vidExit(); + return 1; + } + } else { + RECT rect; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + nVidScrnWidth = rect.right - rect.left; + nVidScrnHeight = rect.bottom - rect.top; + + pDD->SetCooperativeLevel(hVidWnd, DDSCL_NORMAL); + } + +#ifdef PRINT_DEBUG_INFO + { + // Display amount of free video memory + DDSCAPS2 ddsCaps2; + DWORD dwTotal; + DWORD dwFree; + + memset(&ddsCaps2, 0, sizeof(ddsCaps2)); + ddsCaps2.dwCaps = DDSCAPS_PRIMARYSURFACE; + + dprintf(_T(" ** Starting Direct3D7 blitter.\n")); + + if (SUCCEEDED(pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree))) { + dprintf(_T(" * Initialising video: Total video memory minus display surface: %.2fMB.\n"), (double)dwTotal / (1024 * 1024)); + } + } +#endif + + if (bVidTripleBuffer) { + if (vidInitBuffers(1)) { // Try to make triple buffer +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Warning: Couldn't allocate a triple-buffering surface.\n")); +#endif + } + } + + if (pPrimarySurf == NULL) { // No primary surface yet, so try normal + vidInitBuffers(0); + } + + if (pPrimarySurf == NULL) { // No primary surface, fail +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create primary surface.\n")); +#endif + vidExit(); + return 1; + } + + if (nVidFullscreen) { + pDD->Compact(); + } + + VidSClipperInit(pPrimarySurf); // Initialise clipper + + VidSSetupGamma(pPrimarySurf); // Set up gamma controls + + if (bVidScanRotate && nGameWidth < nGameHeight) { + bRotateEffects = true; + } else { + bRotateEffects = false; + } + + if (nRotateGame & 1) { + bRotateEffects = !bRotateEffects; + } + + bUse3DProjection = false; + if (nVidBlitterOpt[nVidSelect] & 0x00100000) { + bUse3DProjection = true; + } + bUseLighting = false; + n3DScreenGridSize = 16; + if (nVidBlitterOpt[nVidSelect] & 0x00200000) { + bUseLighting = true; + n3DScreenGridSize *= 2; + } + + bUseRGBEffects = false; + if (nVidBlitterOpt[nVidSelect] & 0x00010000) { + int nPreset = -1; + + if (nVidBlitterOpt[nVidSelect] & 0x00020000) { + RECT rect = { 0, 0, 0, 0 }; + int nScaledSize, nOriginalSize; + + GetClientScreenRect(hVidWnd, &rect); + if (!nVidFullscreen) { + rect.top += 0 /*nMenuHeight*/; + } + VidImageSize(&rect, nGameWidth, nGameHeight); + + if (bVidScanRotate && nGameWidth < nGameHeight) { + nScaledSize = rect.right - rect.left; + nOriginalSize = nGameWidth; + } else { + nScaledSize = rect.bottom - rect.top; + nOriginalSize = nGameHeight; + } + + for (int n = 7; n >= 0; n--) { + if (nScaledSize >= (n + 1) * nOriginalSize) { + nPreset = n; + break; + } + } + } else { + nPreset = nVidBlitterOpt[nVidSelect] & 0xFF; + } + + if (nPreset != -1) { + if (PresetInfo[nPreset].nUseFilter != 0) { + bVidBilinear = PresetInfo[nPreset].nUseFilter == 1 ? true : false; + } + + if (PresetInfo[nPreset].nUseEffects != 0) { + bUseRGBEffects = PresetInfo[nPreset].nUseEffects == 1 ? true : false; + if (PresetInfo[nPreset].nUseEffects == 1) { + nRGBEffectIntensity = PresetInfo[nPreset].nIntensity; + nRGBEffectFloor = PresetInfo[nPreset].nFloor; + nRGBEffectSaturation = PresetInfo[nPreset].nSaturation; + nRGBEffectPatternmode = PresetInfo[nPreset].nPatternMode; + pRGBEffectPatternName = PresetInfo[nPreset].pPatternName; + nRGBEffectAttenuation = PresetInfo[nPreset].nAttenuation; + nRGBEffectBlendmode = PresetInfo[nPreset].nBlendMode; + } + } + + if (PresetInfo[nPreset].nUseScanlines != 0) { + bVidScanlines = PresetInfo[nPreset].nUseScanlines == 1 ? true : false; + if (PresetInfo[nPreset].nUseScanlines == 1) { + nRGBScanlineIntensity = PresetInfo[nPreset].nScanIntensity; + } + } + + if (PresetInfo[nPreset].nUseFeedback != 0) { + bVidScanDelay = PresetInfo[nPreset].nUseFeedback == 1 ? true : false; + if (PresetInfo[nPreset].nUseFeedback == 1) { + nVidFeedbackIntensity = PresetInfo[nPreset].nAmount; + nVidFeedbackOverSaturation = PresetInfo[nPreset].nOverSaturation; + } + } + + if (PresetInfo[nPreset].nUsePrescale != 0) { + if (PresetInfo[nPreset].nUsePrescale == 1) { + nVidBlitterOpt[nVidSelect] |= 0x01000000; + } else { + nVidBlitterOpt[nVidSelect] &= ~0x01000000; + } + } + + if (nVidBlitterOpt[nVidSelect] & 0x00020000) { + // Modify the effect a bit if it's rotated + if ((!(nRotateGame & 1) && bRotateEffects) || ((nRotateGame & 1) && !bRotateEffects)) { + nRGBEffectIntensity = nRGBEffectIntensity * 0xF0 / 0x0100; + nRGBEffectSaturation += (0x0100 - nRGBEffectSaturation) * 0x70 / 0x0100; + int nScan = (((nRGBScanlineIntensity >> 16) & 0xFF) * 0xE0 / 0x0100) << 16; + nScan |= (((nRGBScanlineIntensity >> 8) & 0xFF) * 0xE0 / 0x0100) << 8; + nScan |= (((nRGBScanlineIntensity >> 0) & 0xFF) * 0xE0 / 0x0100) << 0; + nRGBScanlineIntensity = nScan; + } + } + } + } + + if (bRotateEffects) { + nPreScale = ((nPreScale >> 1) | (nPreScale << 1)) & 3; + } + + pD3DDevice = NULL; + +#ifdef USE_D3D_REFERENCE_DEVICE + if (FAILED(pD3D->CreateDevice(IID_IDirect3DRefDevice, pBackbuffer, &pD3DDevice))) { + #ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't access Direct3D Reference device.\n")); + #endif + vidExit(); + return 1; + } else { + dprintf(_T(" * Using Direct3D Reference device.\n")); + } +#else + if (bUse3DProjection) { + if (FAILED(pD3D->CreateDevice(IID_IDirect3DTnLHalDevice, pBackbuffer, &pD3DDevice))) { + pD3DDevice = NULL; + #ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Warning: Couldn't get TnL 3D hardware, falling back to software TnL.\n")); + #endif + } + } + if (pD3DDevice == NULL) { + if (FAILED(pD3D->CreateDevice(IID_IDirect3DHALDevice, pBackbuffer, &pD3DDevice))) { + #ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't access 3D hardware.\n")); + #endif + vidExit(); + return 1; + } + } +#endif + + pD3DDevice->GetCaps(&d3dDeviceDesc); // Get the capabilities of the 3D hardware + + bMultiTexturing = false; + if (d3dDeviceDesc.wMaxSimultaneousTextures >= 2 && d3dDeviceDesc.wMaxTextureBlendStages >= 2) { + bMultiTexturing = true; + } + +#ifdef PRINT_DEBUG_INFO + if (!bMultiTexturing) { + dprintf(_T(" * Warning: Using fall-back method for rendering scanlines.\n")); + } +#endif + + nScanlineOp = D3DTOP_ADD; + if (d3dDeviceDesc.dwTextureOpCaps & D3DTEXOPCAPS_ADDSMOOTH) { + nScanlineOp = D3DTOP_ADDSMOOTH; + } + +#ifdef PRINT_DEBUG_INFO + if (nScanlineOp != D3DTOP_ADDSMOOTH) { + dprintf(_T(" * Warning: Using fall-back method for blending scanlines.\n")); + } +#endif + + // Init the buffer surfaces + if (vidAllocSurfaces()) { + ReleaseSurfaces(); + return 1; + } + + if (nPreScaleEffect) { + if (VidSoftFXInit(nPreScaleEffect, 0)) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't initialise software SoftFX.\n")); +#endif + vidExit(); + return 1; + } + } + + // Add a viewport + Viewport.dwX = 0; + Viewport.dwY = 0; + Viewport.dwWidth = nVidScrnWidth; + Viewport.dwHeight = nVidScrnHeight; + + if (FAILED(pD3DDevice->SetViewport(&Viewport))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't set initial viewport.\n")); +#endif + vidExit(); + return 1; + } + + pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE); + + if (bUse3DProjection) { + pD3DDevice->SetRenderState(D3DRENDERSTATE_COLORVERTEX, FALSE); + } + + pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE); + + // The polygons for the emulator image on the screen + { + int nWidth = nGameImageWidth; + int nHeight = nGameImageHeight; + int nTexWidth = nTextureWidth; + int nTexHeight = nTextureHeight; + + if (nPreScaleEffect) { + if (nPreScale & 1) { + nWidth *= nPreScaleZoom; + nTexWidth = nPreScaleTextureWidth; + } + if (nPreScale & 2) { + nHeight *= nPreScaleZoom; + nTexHeight = nPreScaleTextureHeight; + } + } + + if (nRotateGame & 1) { + vScreen[nRotateGame & 2 ? 3 : 0] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, (float)nWidth / nTexWidth, 0, 0, 0); + vScreen[nRotateGame & 2 ? 2 : 1] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, (float)nWidth / nTexWidth, (float)nHeight / nTexHeight, 0, 0); + vScreen[nRotateGame & 2 ? 1 : 2] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, 0, 0, 0, 0); + vScreen[nRotateGame & 2 ? 0 : 3] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, 0, (float)nHeight / nTexHeight, 0, 0); + } else { + vScreen[nRotateGame & 2 ? 3 : 0] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, 0, 0, 0, 0); + vScreen[nRotateGame & 2 ? 2 : 1] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, (float)nWidth / nTexWidth, 0, 0, 0); + vScreen[nRotateGame & 2 ? 1 : 2] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, 0, (float)nHeight / nTexHeight, 0, 0); + vScreen[nRotateGame & 2 ? 0 : 3] = D3DTLVERTEX2(D3DVECTOR(0, 0, 0), 1, 0xFFFFFFFF, 0, (float)nWidth / nTexWidth, (float)nHeight / nTexHeight, 0, 0); + } + } + + // Set the texture coordinates for the scanlines + if ((!(nRotateGame & 1) && bRotateEffects) || ((nRotateGame & 1) && !bRotateEffects)) { + vScreen[nRotateGame & 2 ? 3 : 0].tu1 = float(nGameHeight); vScreen[nRotateGame & 2 ? 3 : 0].tv1 = 0; + vScreen[nRotateGame & 2 ? 2 : 1].tu1 = float(nGameHeight); vScreen[nRotateGame & 2 ? 2 : 1].tv1 = (float)nGameWidth; + vScreen[nRotateGame & 2 ? 1 : 2].tu1 = 0; vScreen[nRotateGame & 2 ? 1 : 2].tv1 = 0; + vScreen[nRotateGame & 2 ? 0 : 3].tu1 = 0; vScreen[nRotateGame & 2 ? 0 : 3].tv1 = (float)nGameWidth; + } else { + vScreen[nRotateGame & 2 ? 3 : 0].tu1 = 0; vScreen[nRotateGame & 2 ? 3 : 0].tv1 = 0; + vScreen[nRotateGame & 2 ? 2 : 1].tu1 = float(nGameWidth); vScreen[nRotateGame & 2 ? 2 : 1].tv1 = 0; + vScreen[nRotateGame & 2 ? 1 : 2].tu1 = 0; vScreen[nRotateGame & 2 ? 1 : 2].tv1 = (float)nGameHeight; + vScreen[nRotateGame & 2 ? 0 : 3].tu1 = float(nGameWidth); vScreen[nRotateGame & 2 ? 0 : 3].tv1 = (float)nGameHeight; + } + + { + int nWidth = nGameImageWidth; + int nHeight = nGameImageHeight; + + if (nPreScale & 1) { + nWidth *= nPreScaleZoom; + } + if (nPreScale & 2) { + nHeight *= nPreScaleZoom; + } + + vFeedbackImage[nRotateGame & 2 ? 3 : 0] = D3DTLVERTEX(D3DVECTOR(-0.5, -0.5, 2.0f), 1, 0, 0, 0, 0); + vFeedbackImage[nRotateGame & 2 ? 2 : 1] = D3DTLVERTEX(D3DVECTOR(-0.5 + nWidth, -0.5, 2.0f), 1, 0, 0, float(nGameImageWidth) / nTextureWidth, 0); + vFeedbackImage[nRotateGame & 2 ? 1 : 2] = D3DTLVERTEX(D3DVECTOR(-0.5, -0.5 + nHeight, 2.0f), 1, 0, 0, 0, float(nGameImageHeight) / nTextureHeight); + vFeedbackImage[nRotateGame & 2 ? 0 : 3] = D3DTLVERTEX(D3DVECTOR(-0.5 + nWidth, -0.5 + nHeight, 2.0f), 1, 0, 0, float(nGameImageWidth) / nTextureWidth, float(nGameImageHeight) / nTextureHeight); + } + + // Force an update of the matrices + fPreviousScreenAngle = 9999.0f; + fPreviousScreenCurvature = 9999.0f; + + if (Update3DScreen()) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't initialise 3D geometry.\n")); +#endif + vidExit(); + return 1; + } + + int nFlags = 0; + if (nVidScrnWidth < 1280) { + nFlags++; + if (nVidScrnWidth < 1024) { + nFlags++; + if (nVidScrnWidth < 640) { + nFlags++; + } + } + } + VidSInitOSD(nFlags); + +#ifdef PRINT_DEBUG_INFO + { + DDSCAPS2 ddsCaps2; + DWORD dwTotal; + DWORD dwFree; + + memset(&ddsCaps2, 0, sizeof(ddsCaps2)); + ddsCaps2.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if (SUCCEEDED(pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree))) { + dprintf(_T(" * Initialisation complete: %.2fMB video memory free.\n"), (double)dwFree / (1024 * 1024)); + dprintf(_T(" Displaying and rendering in %i-bit mode, emulation running in %i-bit mode.\n"), nVidScrnDepth, nVidImageDepth); + if (nVidFullscreen) { + dprintf(_T(" Running in fullscreen mode (%i x %i), "), nVidScrnWidth, nVidScrnHeight); + if (bUseTriplebuffer) { + dprintf(_T("using a triple buffer.\n")); + } else { + if (bUsePageflip) { + dprintf(_T("using a double buffer.\n")); + } else { + dprintf(_T("using BltFast() to transfer the final image.\n")); + } + } + } else { + dprintf(_T(" Running in windowed mode, using Blt() to transfer the final image.\n")); + } + } + } +#endif + + bLostControl = false; + + return 0; +} + +// Scale the image to fit the screen/window +static int vidScale(RECT* pRect, int nWidth, int nHeight) +{ + if ((nVidBlitterOpt[nVidSelect] & 0x07000000) == 0x07000000) { + return VidSoftFXScale(pRect, nWidth, nHeight); + } + + return VidSScaleImage(pRect, nWidth, nHeight, bVidScanRotate); +} + +// Render the polygons with the emulator image +static inline void RenderPolygons() +{ + if (bUse3DProjection) { + if (fVidScreenCurvature == 0.0f && !bUseLighting) { + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, (void*)v3DScreen, 4, 0); + } else { + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, (void*)v3DScreen, 6 * n3DScreenGridSize * n3DScreenGridSize, 0); + } + } else { + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX2, (void*)vScreen, 4, 0); + } +} + +static int vidRenderImageA() +{ + if (bLostControl) { // We've lost control of the video hardware + return 1; + } + + if (FAILED(pBackbuffer->IsLost())) { // We've lost control of the video hardware + return 1; + } + + GetClientScreenRect(hVidWnd, &Dest); + + if (nVidFullscreen == 0) { + Dest.top += 0 /*nMenuHeight*/; + } + + if (bVidArcaderes && nVidFullscreen) { + Dest.left = (Dest.right + Dest.left) / 2; + Dest.left -= nGameWidth / 2; + Dest.right = Dest.left + nGameWidth; + + Dest.top = (Dest.top + Dest.bottom) / 2; + Dest.top -= nGameHeight / 2; + Dest.bottom = Dest.top + nGameHeight; + } else { + vidScale(&Dest, nGameWidth, nGameHeight); + } + + if (nVidFullscreen) { + Render.left = Dest.left; + Render.right = Dest.right; + Render.top = Dest.top; + Render.bottom = Dest.bottom; + } else { + Render.left = 0; + Render.right = Dest.right - Dest.left; + Render.top = 0; + Render.bottom = Dest.bottom - Dest.top; + } + + if (((nRotateGame & 1) && !bRotateEffects) || (!(nRotateGame & 1) && bRotateEffects)) { + nZoomFactor = (Render.right - Render.left) / nGameWidth; + } else { + nZoomFactor = (Render.bottom - Render.top) / nGameHeight; + } + + if (bUseRGBEffects) { + RECT rect = {0, 0, Render.right - Render.left, Render.bottom - Render.top}; + pBackbuffer->BltFast(Render.left, Render.top, pRGBEffectTexture, &rect, DDBLTFAST_WAIT); + } else { + if (bUse3DProjection) { + RECT rect = { Render.left, Render.top, Render.right, Render.top + 52 }; + VidSClearSurface(pBackbuffer, 0, &rect); + } + } + + return 0; +} + +static int vidRenderImageB() +{ + int bScanlines = 0, nScanlineSize = 0; + unsigned int nColour; + int nPage; + + if (bLostControl) { // We've lost control of the video hardware + return 1; + } + + if (FAILED(pBackbuffer->IsLost())) { // We've lost control of the video hardware + return 1; + } + + if ((bDrvOkay && bVidScanDelay) || (nPreScale && nPreScaleEffect == 0)) { + + if (FAILED(pD3DDevice->BeginScene())) { + return 1; + } + + if (bRenderToTexture) { + pD3DDevice->SetRenderTarget(pEmuImage[1], 0); + } else { + pD3DDevice->SetRenderTarget(pEmuImage[3], 0); + } + + Viewport.dwX = 0; + Viewport.dwY = 0; + Viewport.dwWidth = nGameImageWidth; + Viewport.dwHeight = nGameImageHeight; + + if (nPreScale & 1) { + Viewport.dwWidth *= nPreScaleZoom; + } + + if (nPreScale & 2) { + Viewport.dwHeight *= nPreScaleZoom; + } + + pD3DDevice->SetViewport(&Viewport); + + nColour = (0xFF - nVidFeedbackIntensity) + nVidFeedbackOverSaturation; + nColour = (nColour > 0x0FF) ? 0xFF : nColour; + nColour = (nVidFeedbackIntensity << 24) | (nColour << 16) | (nColour << 8) | nColour; + + vFeedbackImage[0].color = nColour; + vFeedbackImage[1].color = nColour; + vFeedbackImage[2].color = nColour; + vFeedbackImage[3].color = nColour; + + pD3DDevice->SetTexture(0, pEmuImage[0]); + + pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + if (bDrvOkay && bVidScanDelay) { + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCALPHA); + } else { + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO); + } + + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, (void*)vFeedbackImage, 4, 0); + + if (FAILED(pD3DDevice->EndScene())) { + return 1; + } + + pD3DDevice->SetTexture(0, NULL); + + pD3DDevice->SetRenderTarget(pBackbuffer, 0); + + if (!bRenderToTexture) { + RECT rect = {0, 0, nGameImageWidth, nGameImageHeight}; + + if (nPreScale & 1) { + rect.right = nPreScaleTextureWidth; + } + if (nPreScale & 2) { + rect.bottom = nPreScaleTextureHeight; + } + + pEmuImage[1]->BltFast(0, 0, pEmuImage[3], &rect, DDBLTFAST_WAIT); + } + + nPage = 1; + } else { + nPage = 0; + } + + // Set up for the emulator image + if (FAILED(pD3DDevice->BeginScene())) { + return 1; + } + + if (bUse3DProjection) { + + // It should only do this when the window size/pos has changed + if (nVidFullscreen == 0) { + static RECT prevDest = { 0, 0, 0, 0 }; + if (Render.left != prevDest.left || Render.top != prevDest.top || Render.right != prevDest.right || Render.bottom != prevDest.bottom) { + prevDest.left = Render.left; + prevDest.top = Render.top; + prevDest.right = Render.right; + prevDest.bottom = Render.bottom; + + VidSClearSurface(pBackbuffer, 0, &Render); + } + } + + if (fVidScreenAngle != fPreviousScreenAngle || fVidScreenCurvature != fPreviousScreenCurvature) { + Update3DScreen(); + VidSClearSurface(pBackbuffer, 0, NULL); + SetWorldMatrix(); + SetViewMatrix(2.0f); + SetProjectionMatrix(2.0f); + + fPreviousScreenAngle = fVidScreenAngle; + fPreviousScreenCurvature = fVidScreenCurvature; + } + + Viewport.dwX = Render.left; + Viewport.dwY = Render.top; + Viewport.dwWidth = Render.right - Render.left; + Viewport.dwHeight = Render.bottom - Render.top; + } else { + Viewport.dwX = 0; + Viewport.dwY = 0; + Viewport.dwWidth = nVidScrnWidth; + Viewport.dwHeight = nVidScrnHeight; + + vScreen[0].sx = -0.5f + (float)Render.left; + vScreen[0].sy = -0.5f + (float)Render.top; + vScreen[1].sx = -0.5f + (float)Render.right; + vScreen[1].sy = -0.5f + (float)Render.top; + vScreen[2].sx = -0.5f + (float)Render.left; + vScreen[2].sy = -0.5f + (float)Render.bottom; + vScreen[3].sx = -0.5f + (float)Render.right; + vScreen[3].sy = -0.5f + (float)Render.bottom; + } + + pD3DDevice->SetViewport(&Viewport); + + if (bUseRGBEffects) { + nColour = ((0xFF - nRGBEffectAttenuation) << 24) | nRGBScanlineIntensity; + if (nRGBEffectBlendmode == 0) { + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCCOLOR); + } else { + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTCOLOR); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO); + } + } else { + nColour = ((0xFF - nRGBEffectAttenuation) << 24) | nVidScanIntensity; + + if (bUse3DProjection && bUseLighting) { + + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO); + + pD3DDevice->LightEnable(0, TRUE); + pD3DDevice->LightEnable(1, TRUE); + + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_CURRENT); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + RenderPolygons(); + + pD3DDevice->LightEnable(1, FALSE); + pD3DDevice->LightEnable(0, FALSE); + + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_INVDESTCOLOR); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); + } else { + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO); + } + } + + if (bVidScanlines) { + if (nZoomFactor >= 2) { + bScanlines = 1; + } + if (nZoomFactor >= 4 || bVidFullStretch) { + nScanlineSize++; + } + } + + pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, nColour); + + if (bMultiTexturing) { + + if (bScanlines) { + if (bVidScanBilinear) { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } else { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_POINT); + } + if (bVidBilinear) { + pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } else { + pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } + + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, nScanlineOp); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 1); + + pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + + pD3DDevice->SetTexture(0, pScanlineTexture[nScanlineSize]); + pD3DDevice->SetTexture(1, pEmuImage[nPage]); + + } else { + if (bVidBilinear) { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } else { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_POINT); + } + + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + pD3DDevice->SetTexture(0, pEmuImage[nPage]); + } + + RenderPolygons(); + + pD3DDevice->SetTexture(0, NULL); + pD3DDevice->SetTexture(1, NULL); + + } else { // multi-texturing not supported by hardware + + if (bVidBilinear) { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } else { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_POINT); + } + + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + + pD3DDevice->SetTexture(0, pEmuImage[nPage]); + + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + RenderPolygons(); + + pD3DDevice->SetTexture(0, NULL); + + if (bScanlines) { + + if (bVidScanBilinear) { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC); + } else { + pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT); + pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_POINT); + } + + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR); + pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, nScanlineOp); + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 1); + + pD3DDevice->SetTexture(0, pScanlineTexture[nScanlineSize]); + + pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTCOLOR); + pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO); + + RenderPolygons(); + + pD3DDevice->SetTexture(0, NULL); + } + } + + if (FAILED(pD3DDevice->EndScene())) { + return 1; + } + + return 0; +} + +// Copy the game image to the texture and render the image using 3D hardware +static int vidBurnToSurf() +{ + if (bLostControl) { // We've lost control of the video hardware + return 1; + } + + RECT rect = { 0, 0, nGameImageWidth, nGameImageHeight }; + + DDSURFACEDESC2 ddsd; + + unsigned char *pd, *ps; + int nSize = nGameImageWidth * nVidImageBPP; + int nPitch; + + // Lock the surface so we can write to it + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (nVidTransferMethod <= 0) { + if (nPreScaleEffect) { + + rect.right *= nPreScaleZoom; + rect.bottom *= nPreScaleZoom; + + VidSoftFXApplyEffectDirectX(pEmuImage[2], NULL); + } else { + // Copy the image to a surface (located in video memory), then use bltfast() to blit it to the texture + if (FAILED(pEmuImage[2]->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { + return 1; + } + ps = pVidImage + nVidImageLeft * nVidImageBPP; + pd = (unsigned char*)ddsd.lpSurface; + nPitch = ddsd.lPitch; + + for (int y = 0; y < nGameImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + memcpy(pd, ps, nSize); + } + + pEmuImage[2]->Unlock(NULL); + } + + pEmuImage[0]->BltFast(0, 0, pEmuImage[2], &rect, DDBLTFAST_WAIT); + } else { + if (nPreScaleEffect) { + + rect.right *= nPreScaleZoom; + rect.bottom *= nPreScaleZoom; + + VidSoftFXApplyEffectDirectX(pEmuImage[0], &rect); + } else { + // Use the surface supplied by DirectX texture management and let it perform the blit + if (FAILED(pEmuImage[0]->Lock(&rect, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL))) { + return 1; + } + + ps = pVidImage + nVidImageLeft * nVidImageBPP; + pd = (unsigned char*)ddsd.lpSurface; + nPitch = ddsd.lPitch; + + for (int y = 0; y < nGameImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + memcpy(pd, ps, nSize); + } + + pEmuImage[0]->Unlock(NULL); + } + } + + return 0; +} + +// Run one frame and render the screen +static int vidFrame(bool bRedraw) // bRedraw = 0 +{ + // Check if we've lost control of the video hardware + if (FAILED(pPrimarySurf->IsLost()) || FAILED(pDD->TestCooperativeLevel())) { + bLostControl = true; + } + + // If we've lost control, see if we've regained it and attempt to restore surfaces + if (bLostControl) { + if (FAILED(pDD->TestCooperativeLevel())) { + return 1; + } + + if (nVidFullscreen) { + pDD->Compact(); + } + + if (FAILED(pPrimarySurf->IsLost())) { + if (FAILED(pPrimarySurf->Restore())) { + return 1; + } + } + + if (!bUsePageflip) { + if (FAILED(pBackbuffer->IsLost())) { + if (FAILED(pBackbuffer->Restore())) { + return 1; + } + } + } + + for (int i = 0; i < 4; i++) { + + // Skip texture 0 if we're using DirectX texture management + if (nVidTransferMethod > 0 && i == 0) { + continue; + } + + if (pEmuImage[i]) { + if (FAILED(pEmuImage[i]->IsLost())) { + if (FAILED(pEmuImage[i]->Restore())) { + return 1; + } + } + } + } + + if (InitEffectsSurfaces()) { // Restore RGB effects and/or scanline surfaces + return 1; + } + + if (VidSRestoreOSD()) { + return 1; + } + + vidClear(); // Clear screen + + bLostControl = false; + } + +#ifdef ENABLE_PROFILING + ProfileProfileStart(0); +#else + vidRenderImageA(); +#endif + + if (bDrvOkay) { + if (bRedraw) { // Redraw current frame + if (BurnDrvRedraw()) { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } else { + BurnDrvFrame(); // Run one frame and draw the screen + } + } +#ifdef ENABLE_PROFILING + ProfileProfileEnd(0); + + ProfileProfileStart(1); +#endif + + vidBurnToSurf(); // Copy the memory buffer + +#ifdef ENABLE_PROFILING + ProfileProfileStart(2); + vidRenderImageA(); +#endif + + vidRenderImageB(); // Use 3D hardware to render the image + +#ifdef ENABLE_PROFILING + { + // Force the D3D pipeline to be flushed + + DDSURFACEDESC2 ddsd; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (SUCCEEDED(pBackbuffer->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { + unsigned char c = *((unsigned char*)ddsd.lpSurface); + + pBackbuffer->Unlock(NULL); + } + } + + ProfileProfileEnd(2); + ProfileProfileEnd(1); + + dprintf(_T("burn %.2lfms; blit %.2lf; effect %.2lf\n"), ProfileProfileReadAverage(0), ProfileProfileReadAverage(1), ProfileProfileReadAverage(2)); +#endif + + return 0; +} + +// Paint the Dtos surface onto the primary surface +int vidPaint(int bValidate) +{ + RECT rect; + + if (bLostControl) { // We've lost control of the video hardware + return 1; + } + + if (FAILED(pPrimarySurf->IsLost())) { // We've lost control of the video hardware + return 1; + } + + if (!bUsePageflip) { + GetClientScreenRect(hVidWnd, &rect); + rect.top += 0 /*nMenuHeight*/; + + vidScale(&rect, nGameWidth, nGameHeight); + + if ((rect.right - rect.left) != (Dest.right - Dest.left) || (rect.bottom - rect.top ) != (Dest.bottom - Dest.top)) { + bValidate |= 2; + } + } + + if (bValidate & 2) { + vidRenderImageA(); + vidRenderImageB(); + } + + // Display OSD text message + VidSDisplayOSD(pBackbuffer, &Render, 0); + + if(bVidVSync && !nVidFullscreen) { pDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } + + // Display final image + if (bUsePageflip) { + if (bUseTriplebuffer) { + if (FAILED(pPrimarySurf->Flip(NULL, DDFLIP_WAIT))) { + return 1; + } + } else { + if (FAILED(pPrimarySurf->Flip(NULL, DDFLIP_NOVSYNC | DDFLIP_WAIT))) { + return 1; + } + } + } else { + + if (nVidFullscreen) { + if (FAILED(pPrimarySurf->BltFast(Dest.left, Dest.top, pBackbuffer, &Dest, DDBLTFAST_WAIT))) { + return 1; + } + } else { + RECT RGBDest = {0, 0, Dest.right - Dest.left, Dest.bottom - Dest.top}; + + if (FAILED(pPrimarySurf->Blt(&rect, pBackbuffer, &RGBDest, DDBLT_ASYNC, NULL))) { + if (FAILED(pPrimarySurf->Blt(&rect, pBackbuffer, &RGBDest, DDBLT_WAIT, NULL))) { + return 1; + } + } + //if(bVidVSync && !nVidFullscreen) { pDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } + + } + + if (bValidate & 1) { + // Validate the rectangle we just drew + POINT c = {0, 0}; + ClientToScreen(hVidWnd, &c); + rect.left -= c.x; rect.right -= c.x; + rect.top -= c.y; rect.bottom -= c.y; + ValidateRect(hVidWnd, &rect); + } + } + + return 0; +} + +static int vidGetSettings(InterfaceInfo* pInfo) +{ + if (nVidFullscreen) { + if (bUseTriplebuffer) { + IntInfoAddStringModule(pInfo, _T("Using a triple buffer")); + } else { + if (bUsePageflip) { + IntInfoAddStringModule(pInfo, _T("Using a double buffer")); + } else { + IntInfoAddStringModule(pInfo, _T("Using Bltfast() to transfer the image")); + } + } + } else { + IntInfoAddStringModule(pInfo, _T("Using Blt() to transfer the image")); + } + + if (nPreScale) { + TCHAR szString[MAX_PATH] = _T(""); + + if (nPreScaleEffect) { + _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%ix zoom)"), VidSoftFXGetEffect(nPreScaleEffect), nPreScaleZoom); + } else { + _sntprintf(szString, MAX_PATH, _T("Prescaling using 3D hardware (%ix zoom)"), nPreScaleZoom); + } + IntInfoAddStringModule(pInfo, szString); + } + + if (bUse3DProjection || bUseRGBEffects || bVidScanDelay || bVidScanlines) { + TCHAR* pszEffect[8] = { _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T("") }; + TCHAR szString[MAX_PATH] = _T(""); + + if (bUse3DProjection) { + pszEffect[0] = _T("3D projection"); + } + if (bUseRGBEffects) { + pszEffect[0] = _T("RGB effects"); + } + + if (bVidScanDelay || bVidScanlines) { + pszEffect[1] = _T(","); + if (bVidScanDelay && bVidScanlines) { + pszEffect[2] = _T(" feedback"); + pszEffect[3] = _T(","); + pszEffect[4] = _T(" scanlines"); + } else { + if (bVidScanDelay) { + pszEffect[2] = _T(" feedback"); + } + if (bVidScanlines) { + pszEffect[2] = _T(" scanlines"); + } + } + } + + _sntprintf(szString, MAX_PATH, _T("Applying %s%s%s%s%s%s%s%s"), pszEffect[0], pszEffect[1], pszEffect[2], pszEffect[3], pszEffect[4], pszEffect[5], pszEffect[6], pszEffect[7]); + IntInfoAddStringModule(pInfo, szString); + } + + if (nVidTransferMethod > 0) { + TCHAR szString[MAX_PATH] = _T(""); + + _sntprintf(szString, MAX_PATH, _T("Using Direct3D texture management"), VidSoftFXGetEffect(nPreScaleEffect), nPreScaleZoom); + IntInfoAddStringModule(pInfo, szString); + } + + return 0; +} + +// The video output plugin: +struct VidOut VidOutD3D = { vidInit, vidExit, vidFrame, vidPaint, vidScale, vidGetSettings, _T("DirectDraw7 / Direct3D7 Enhanced video output") }; +#else +struct VidOut VidOutD3D = { NULL, NULL, NULL, NULL, NULL, NULL, _T("DirectDraw7 / Direct3D7 Enhanced video output") }; +#endif + diff --git a/src/interface/win32/vid_ddraw.cpp b/src/interface/win32/vid_ddraw.cpp new file mode 100644 index 00000000..ef8469ea --- /dev/null +++ b/src/interface/win32/vid_ddraw.cpp @@ -0,0 +1,1147 @@ +// DirectDraw blitter + +#include "burner.h" + +#if !defined BUILD_X64_EXE + #include "vid_directx_support.h" +#endif + +#include +#define DIRECT3D_VERSION 0x0700 // Use this Direct3D version + +#if defined BUILD_X64_EXE + #include "vid_directx_support.h" +#endif + +#include "ddraw_core.h" + +static IDirectDraw7* DtoDD = NULL; // DirectDraw interface +static IDirectDrawSurface7* DtoPrim = NULL; // Primary surface +static IDirectDrawSurface7* DtoBack = NULL; // Back buffer surface + +static int nRotateGame; +static bool bRotateScanlines; +static DDBLTFX* DtoBltFx = NULL; // We use mirrored blits for flipped games + +static IDirectDrawSurface7* pddsDtos = NULL; // The screen surface +static int nGameWidth = 0, nGameHeight = 0; // screen size + +static bool bDtosScan; + +static RECT Src = { 0, 0, 0, 0 }; +static RECT Dest = { 0, 0, 0, 0 }; + +static int nHalfMask = 0; + +static int nUseSys; // Use System or Video memory + +static int DtoPrimClear() +{ + if (DtoPrim == NULL) { + return 1; + } + + VidSClearSurface(DtoPrim, 0, NULL); // Clear 1st page + + if (DtoBack) { // We're using a triple buffer + VidSClearSurface(DtoBack, 0, NULL); // Clear 2nd page + DtoPrim->Flip(NULL, DDFLIP_WAIT); + VidSClearSurface(DtoBack, 0, NULL); // Clear 3rd page + } + + return 0; +} + +static int DtoPrimInit(int bTriple) +{ + DDSURFACEDESC2 ddsd; + + // Create the primary surface + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (bTriple) { // Make a primary surface capable of triple bufferring + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY; + ddsd.dwBackBufferCount = 2; + } else { + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + } + + if (FAILED(DtoDD->CreateSurface(&ddsd, &DtoPrim, NULL))) { + return 1; + } + + if (bTriple) { + // Get the back buffer + memset(&ddsd.ddsCaps, 0, sizeof(ddsd.ddsCaps)); + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + + if (FAILED(DtoPrim->GetAttachedSurface(&ddsd.ddsCaps, &DtoBack))) { // Failed to make triple buffer + RELEASE(DtoPrim) + return 1; + } + + DtoPrimClear(); // Clear surfaces + } + + return 0; +} + +// Try to autodetect the best secondary buffer type to use, based on the hardware capabilities +static int AutodetectUseSys() +{ + DDCAPS ddc; + + memset(&ddc, 0, sizeof(ddc)); + ddc.dwSize = sizeof(ddc); + DtoDD->GetCaps(&ddc, NULL); + + if (ddc.dwCaps & DDCAPS_BLTSTRETCH) { // If it can do a hardware stretch use video memory + return 0; + } else { // Otherwise use system memory: + return 1; + } +} + +// Create a secondary DirectDraw surface for the game image +static int DtosMakeSurf() +{ + int nRet; + + nUseSys = 0; + DDSURFACEDESC2 ddsd; + + if (DtoDD == NULL) { + return 1; + } + + nUseSys = nVidTransferMethod; + if (nUseSys < 0) { + nUseSys = AutodetectUseSys(); + } + + // Try to allocate buffer in Video memory first, if that fails use System memory + do { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if (nUseSys == 0) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + } else { + if (nUseSys == 1) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + } + + ddsd.dwWidth = nGameWidth << 1; // Make the surface large enough to add scanlines + ddsd.dwHeight = nGameHeight << 1; // + + nRet = DtoDD->CreateSurface(&ddsd, &pddsDtos, NULL); + + if (SUCCEEDED(nRet)) { // Break early, so nUseSys will keep its value + break; + } + + } while (++nUseSys <= 1); + + if (FAILED(nRet)) { + return 1; + } + + nVidScrnDepth = VidSGetSurfaceDepth(pddsDtos); // Get colourdepth of primary surface + + VidSClearSurface(pddsDtos, 0, NULL); + + return 0; +} + +static int DtosExit() +{ + RELEASE(pddsDtos); + + VidSFreeVidImage(); + + VidSExitOSD(); + + return 0; +} + +static int DtosInit() +{ + if (DtoDD == NULL) { + return 1; + } + + if (nRotateGame & 1) { + nVidImageWidth = nGameHeight; + nVidImageHeight = nGameWidth; + } else { + nVidImageWidth = nGameWidth; + nVidImageHeight = nGameHeight; + } + + if (bVidScanRotate && nGameWidth < nGameHeight) { + bRotateScanlines = true; + } else { + bRotateScanlines = false; + } + + nVidImageDepth = VidSGetSurfaceDepth(DtoPrim); // Get color depth of primary surface + nVidImageBPP = (nVidImageDepth + 7) >> 3; + + // Make the mask to mask out all but the lowest intensity bit + if (nVidImageDepth == 15) { + nHalfMask = 0xFBDEFBDE; + } else { + if (nVidImageDepth == 16) { + nHalfMask = 0xF7DEF7DE; + } else { + nHalfMask = 0xFEFEFEFE; + } + } + + // Make the normal memory buffer + if (VidSAllocVidImage()) { + DtosExit(); + return 1; + } + + // Make the DirectDraw secondary surface + if (DtosMakeSurf()) { + DtosExit(); + return 1; + } + + // Use our callback to get colors: + SetBurnHighCol(nVidImageDepth); + + Dest.left = 0; Dest.right = -1; + + RECT rect = { 0, 0, 0, 0 }; + GetClientScreenRect(hVidWnd, &rect); + rect.top += 0 /*nMenuHeight*/; + + VidSScaleImage(&rect, nGameWidth, nGameHeight, bVidScanRotate); + + VidSInitOSD(4); + + return 0; +} + +static int vidExit() +{ + VidSRestoreGamma(); + + VidSRestoreScreenMode(); + + DtosExit(); + + RELEASE(DtoPrim) // a single call releases all surfaces + DtoBack = NULL; + + VidSExit(); + + if (DtoBltFx) { + free(DtoBltFx); + DtoBltFx = NULL; + } + + RELEASE(DtoDD) + + return 0; +} + +static GUID MyGuid; +static int nWantDriver; + +#ifdef PRINT_DEBUG_INFO +static int nCurrentDriver; +#ifdef UNICODE +static BOOL PASCAL MyEnumDisplayDrivers(GUID FAR* pGuid, LPWSTR pszDesc, LPWSTR /*pszName*/, LPVOID /*pContext*/, HMONITOR /*hMonitor*/) +#else +static BOOL PASCAL MyEnumDisplayDrivers(GUID FAR* pGuid, LPSTR pszDesc, LPSTR /*pszName*/, LPVOID /*pContext*/, HMONITOR /*hMonitor*/) +#endif +{ + if (nCurrentDriver == nWantDriver) { + memcpy(&MyGuid, pGuid, sizeof(GUID)); + } + + if (nCurrentDriver == 0) { + dprintf(_T(" %s\n"), pszDesc); + } else { + dprintf(_T(" Display %d (on %s)\n"), nCurrentDriver, pszDesc); + } + + nCurrentDriver++; + + return DDENUMRET_OK; +} +#endif + +static int vidInit() +{ + hVidWnd = nVidFullscreen ? hScrnWnd : hVideoWindow; // Use Screen window for video + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Enumerating available drivers:\n")); + nWantDriver = 0; + nCurrentDriver = 0; + _DirectDrawEnumerateEx(MyEnumDisplayDrivers, NULL, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_DETACHEDSECONDARYDEVICES | DDENUM_NONDISPLAYDEVICES); +#endif + + // Get pointer to DirectDraw device + _DirectDrawCreateEx(nWantDriver ? &MyGuid : NULL, (void**)&DtoDD, IID_IDirectDraw7, NULL); + + VidSInit(DtoDD); + + nGameWidth = nVidImageWidth; nGameHeight = nVidImageHeight; + + nRotateGame = 0; + if (bDrvOkay) { + DtoBltFx = NULL; + + // Get the game screen size + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (nVidRotationAdjust & 1) { + int n = nGameWidth; + nGameWidth = nGameHeight; + nGameHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } else { + nRotateGame |= 1; + } + } + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + nRotateGame ^= 2; + } + + if (nRotateGame & 2) { + DDCAPS ddcaps; + + // Disable flipping until we've checked the hardware supports it + nRotateGame &= ~2; + + memset(&ddcaps, 0, sizeof(ddcaps)); + ddcaps.dwSize = sizeof(ddcaps); + + DtoDD->GetCaps(&ddcaps, NULL); + if ((ddcaps.dwFXCaps & DDFXCAPS_BLTMIRRORLEFTRIGHT) && (ddcaps.dwFXCaps & DDFXCAPS_BLTMIRRORUPDOWN)) { + + DtoBltFx = (DDBLTFX*)malloc(sizeof(DDBLTFX)); + if (DtoBltFx == NULL) { + vidExit(); + return 1; + } + + memset(DtoBltFx, 0, sizeof(DDBLTFX)); + + DtoBltFx->dwSize = sizeof(DDBLTFX); + DtoBltFx->dwDDFX = DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN; + + // Enable flipping now + nRotateGame |= 2; + } + } + } + + DtoPrim = NULL; // No primary surface yet + DtoBack = NULL; + + // Remember the changes to the display + if (nVidFullscreen) { + if (VidSEnterFullscreenMode(nScreenSize, 0)) { + vidExit(); + return 1; + } + } else { + DtoDD->SetCooperativeLevel(hVidWnd, DDSCL_NORMAL); + } + +#ifdef PRINT_DEBUG_INFO + { + // Display amount of free video memory + DDSCAPS2 ddsCaps2; + DWORD dwTotal; + DWORD dwFree; + + memset(&ddsCaps2, 0, sizeof(ddsCaps2)); + ddsCaps2.dwCaps = DDSCAPS_PRIMARYSURFACE; + + dprintf(_T(" ** Starting DirectDraw7 blitter.\n")); + + if (SUCCEEDED(DtoDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree))) { + dprintf(_T(" * Initialising video: Total video memory minus display surface: %.2fMB.\n"), (double)dwTotal / (1024 * 1024)); + } + + if (bDrvOkay) { + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + if (nRotateGame & 2) { + dprintf(_T(" * Using graphics hardware to rotate the image 180 degrees.\n")); + } else { + dprintf(_T(" * Warning: Graphics hardware does not support mirroring blits.\n Image orientation will be incorrect.\n")); + } + } + } + } +#endif + + if (bVidTripleBuffer && nVidFullscreen) { + if (DtoPrimInit(1)) { // Try to make triple buffer + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Warning: Couldn't allocate a triple-buffering surface.\n")); +#endif + + // If we fail, fail entirely and make a normal buffer + RELEASE(DtoPrim) + } + } + + if (DtoPrim == NULL) { + // No primary surface yet, so try normal + if (DtoPrimInit(0)) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create primary surface.\n")); +#endif + + vidExit(); + return 1; + } + } + + if (nVidFullscreen) { + DtoDD->Compact(); + } + + VidSClipperInit(DtoPrim); + + VidSSetupGamma(DtoPrim); + + // Init the buffer surfaces + if (DtosInit()) { + vidExit(); + return 1; + } + +#ifdef PRINT_DEBUG_INFO + { + DDSCAPS2 ddsCaps2; + DWORD dwTotal; + DWORD dwFree; + + memset(&ddsCaps2, 0, sizeof(ddsCaps2)); + ddsCaps2.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if (SUCCEEDED(DtoDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree))) { + dprintf(_T(" * Initialisation complete: %.2fMB video memory free.\n"), (double)dwFree / (1024 * 1024)); + dprintf(_T(" Displaying and rendering in %i-bit mode, emulation running in %i-bit mode.\n"), nVidScrnDepth, nVidImageDepth); + if (nUseSys) { + dprintf(_T(" Blitting directly from system memory.\n")); + } else { + dprintf(_T(" Transferring the image to video memory before blitting.\n")); + } + if (nVidFullscreen) { + dprintf(_T(" Running in fullscreen mode (%i x %i)"), nVidScrnWidth, nVidScrnHeight); + if (DtoBack != NULL) { + dprintf(_T(", using a triple buffer")); + } + dprintf(_T(".\n")); + } else { + dprintf(_T(" Running in windowed mode.\n")); + } + } + } +#endif + + return 0; +} + +// Copy pVidImage to pddsDtos, rotate +static int vidRenderRotate(DDSURFACEDESC2* ddsd) +{ + unsigned char *pd, *ps, *pdd; + unsigned char *Surf; + int nPitch; + + Surf = (unsigned char*)ddsd->lpSurface; + nPitch = ddsd->lPitch; + + pd = Surf; + + if (bDtosScan) { + if (bVidScanHalf) { + if (bVidScanRotate) { + switch (nVidImageBPP) { + case 4: { + int t; + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 4; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + t = *(int*)ps; + ps += nVidImagePitch; + *(int*)pdd = t; + pdd += 4; + *(int*)pdd = (t & 0xFEFEFE) >> 1; + pdd += 4; + } + } + break; + } + case 3: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 3; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + pdd[0] = ps[0]; + pdd[1] = ps[1]; + pdd[2] = ps[2]; + pdd[3] = ps[0] >> 1; + pdd[4] = ps[1] >> 1; + pdd[5] = ps[2] >> 1; + ps += nVidImagePitch; + pdd +=6; + } + } + break; + } + case 2: { + short t; + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 2; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + t = *(short*)ps; + ps += nVidImagePitch; + *(short*)pdd = t; + pdd += 2; + *(short*)pdd = (t & nHalfMask) >> 1; + pdd += 2; + } + } + break; + } + } + + } else { + unsigned char* pBuffer = (unsigned char*)malloc(nPitch); + unsigned char* pd2; + + switch (nVidImageBPP) { + case 4: { + int t; + for (int y = 0; y < nGameHeight; y++, pd += nPitch * 2) { + ps = pVidImage + (nGameHeight - 1 - y) * 4; + pdd = pd; + pd2 = pBuffer; + for (int x = 0; x < nGameWidth; x++) { + t = *(int*)ps; + ps += nVidImagePitch; + *(int*)pdd = t; + *(int*)pd2 = t; + pdd += 4; + pd2 += 4; + } + pdd = pd + nPitch; + for (ps = pBuffer; ps < (pBuffer + nGameWidth * 4); ps += 4) { + *(int*)pdd = (*(int*)ps & 0xFEFEFE) >> 1; + pdd += 4; + } + } + break; + } + case 3: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch * 2) { + ps = pVidImage + (nGameHeight - 1 - y) * 3; + pdd = pd; + pd2 = pBuffer; + for (int x = 0; x < nGameWidth; x++) { + pdd[0] = ps[0]; + pd2[0] = ps[0]; + pdd[1] = ps[1]; + pd2[1] = ps[1]; + pdd[2] = ps[2]; + pd2[2] = ps[2]; + ps += nVidImagePitch; + pdd += 3; + pd2 += 3; + } + pdd = pd + nPitch; + for (ps = pBuffer; ps < (pBuffer + nGameWidth * 3); ps += 3) { + pdd[0] = ps[0] >> 1; + pdd[1] = ps[1] >> 1; + pdd[2] = ps[2] >> 1; + pdd += 3; + } + } + break; + } + case 2: { + short t; + for (int y = 0; y < nGameHeight; y++, pd += nPitch * 2) { + ps = pVidImage + (nGameHeight - 1 - y) * 2; + pdd = pd; + pd2 = pBuffer; + for (int x = 0; x < nGameWidth; x++) { + t = *(short*)ps; + ps += nVidImagePitch; + *(short*)pdd = t; + *(short*)pd2 = t; + pdd += 2; + pd2 += 2; + } + pdd = pd + nPitch; + for (ps = pBuffer; ps < (pBuffer + nGameWidth * 2); ps += 4) { + *(unsigned int*)pdd = (*(unsigned int*)ps & nHalfMask) >> 1; + pdd += 4; + } + } + break; + } + } + if (pBuffer) { + free (pBuffer); + pBuffer = NULL; + } + } + } else { + int nPixelSize = nVidImageBPP; + if (bVidScanRotate) { + nPixelSize <<= 1; + } else { + nPitch <<= 1; + } + + switch (nVidImageBPP) { + case 4: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 4; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + *(int*)pdd = *(int*)ps; + ps += nVidImagePitch; + pdd += nPixelSize; + } + } + break; + } + case 3: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 3; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + pdd[0] = ps[0]; + pdd[1] = ps[1]; + pdd[2] = ps[2]; + ps += nVidImagePitch; + pdd += nPixelSize; + } + } + break; + } + case 2: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 2; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + *(short*)pdd = *(short*)ps; + ps += nVidImagePitch; + pdd += nPixelSize; + } + } + break; + } + } + } + } else { + switch (nVidImageBPP) { + case 4: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 4; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + *(int*)pdd = *(int*)ps; + ps += nVidImagePitch; + pdd += 4; + } + } + break; + } + case 3: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 3; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + pdd[0] = ps[0]; + pdd[1] = ps[1]; + pdd[2] = ps[2]; + ps += nVidImagePitch; + pdd +=3; + } + } + break; + } + case 2: { + for (int y = 0; y < nGameHeight; y++, pd += nPitch) { + ps = pVidImage + (nGameHeight - 1 - y) * 2; + pdd = pd; + for (int x = 0; x < nGameWidth; x++) { + *(short*)pdd = *(short*)ps; + ps += nVidImagePitch; + pdd += 2; + } + } + break; + } + } + } + + return 0; +} + +// Copy pVidImage to pddsDtos, don't rotate, add scanlines in odd lines if needed +static int vidRenderNoRotateHorScanlines(DDSURFACEDESC2* ddsd, int nField, int nHalf) +{ + unsigned char *pd, *ps; + + unsigned char* Surf = (unsigned char*)ddsd->lpSurface; + int nPitch = ddsd->lPitch; + if (bDtosScan) { + if (nField) { // copy to odd fields + Surf += nPitch; + } + nPitch <<= 1; + } + + pd = Surf; ps = pVidImage; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + if (nHalf == 0) { + memcpy(pd, ps, nVidImagePitch); + } else { + unsigned char* psEnd = ps + nVidImagePitch; + unsigned char* pdp = pd; + unsigned char* psp = ps; + + do { + unsigned int t; + t = *((unsigned int *)(psp)); + t = (t & nHalfMask) >> 1; + *((unsigned int *)(pdp)) = t; + + psp += 4; + pdp += 4; + } while (psp < psEnd); + } + } + + return 0; +} + +// Copy pVidImage to pddsDtos, don't rotate, add rotated scanlines +static int vidRenderNoRotateVertScanlines(DDSURFACEDESC2* ddsd) +{ + unsigned char *pd, *ps; + unsigned char* Surf = (unsigned char*)ddsd->lpSurface; + int nPitch = ddsd->lPitch; + + if (bVidScanHalf) { + pd = Surf; ps = pVidImage; + switch (nVidImageBPP) { + case 4: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + unsigned int t = *(unsigned int*)psp; + *(unsigned int*)pdp = t; + psp += 4; + pdp += 4; + *(unsigned int*)pdp = (t & 0xFEFEFE) >> 1; + pdp += 4; + } while (psp < psEnd); + } + break; + } + case 3: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + pdp[0] = psp[0]; + pdp[1] = psp[1]; + pdp[2] = psp[2]; + pdp[3] = psp[0] >> 1; + pdp[4] = psp[1] >> 1; + pdp[5] = psp[2] >> 1; + psp += 3; + pdp += 6; + } while (psp < psEnd); + } + break; + } + case 2: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + unsigned short t; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + t = *(unsigned short*)psp; + *(unsigned short*)pdp = t; + psp += 2; + pdp += 2; + *(unsigned short*)pdp = (t & nHalfMask) >> 1; + pdp += 2; + } while (psp < psEnd); + } + break; + } + } + + } else { + pd = Surf; ps = pVidImage; + switch (nVidImageBPP) { + case 4: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + *(unsigned int*)pdp = *(unsigned int*)psp; + + psp += 4; + pdp += 8; + } while (psp < psEnd); + } + break; + } + case 3: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + pdp[0] = psp[0]; + pdp[1] = psp[1]; + pdp[2] = psp[2]; + + psp += 3; + pdp += 6; + } while (psp < psEnd); + } + break; + } + case 2: { + unsigned char* pdp; + unsigned char* psp; + unsigned char* psEnd; + for (int y = 0; y < nVidImageHeight; y++, pd += nPitch, ps += nVidImagePitch) { + pdp = pd; + psp = ps; + psEnd = ps + nVidImagePitch; + do { + *(unsigned short*)pdp = *(unsigned short*)psp; + + psp += 2; + pdp += 4; + } while (psp < psEnd); + } + break; + } + } + } + + return 0; +} + +static int vidBurnToSurf() +{ + DDSURFACEDESC2 ddsd; + + if (pddsDtos == NULL) { + return 1; + } + + if (DtoPrim->IsLost()) { // We've lost control of the screen + return 1; + } + + GetClientScreenRect(hVidWnd, &Dest); + + if (!nVidFullscreen) { + Dest.top += 0 /*nMenuHeight*/; + } + + if (bVidArcaderes && nVidFullscreen) { + Dest.left = (Dest.right + Dest.left) / 2; + Dest.left -= nGameWidth / 2; + Dest.right = Dest.left + nGameWidth; + + Dest.top = (Dest.top + Dest.bottom) / 2; + Dest.top -= nGameHeight / 2; + Dest.bottom = Dest.top + nGameHeight; + } else { + VidSScaleImage(&Dest, nGameWidth, nGameHeight, bVidScanRotate); + } + + Src.right = nGameWidth; + Src.bottom = nGameHeight; + bool bScan = false; + + if (bVidScanlines) { // See if the display window is large enough to add scanlines if needed + if (bRotateScanlines) { + if (Dest.right - Dest.left >= (nGameWidth << 1)) { // We need to add vertical scanlines + Src.right <<= 1; + bScan = true; + } + } else { + if (Dest.bottom - Dest.top >= (nGameHeight << 1)) { // We need to add horizontal scanlines + Src.bottom <<= 1; + bScan = true; + } + } + } + + // Lock the surface so we can write to it + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (FAILED(pddsDtos->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL))) { + return 1; + } + + if (bScan && !bDtosScan) { // Scanlines were just enabled. We need to clear the screen + for (int y = 0; y < (nVidImageHeight << 1); y++) { + memset(((unsigned char*)ddsd.lpSurface) + y * ddsd.lPitch, 0, ddsd.lPitch); + } + } + + bDtosScan = bScan; + + if (nRotateGame & 1) { + vidRenderRotate(&ddsd); + } else { + if (bDtosScan && bRotateScanlines) { + vidRenderNoRotateVertScanlines(&ddsd); + } else { + vidRenderNoRotateHorScanlines(&ddsd, 0, 0); + if (bDtosScan && bVidScanHalf) { + vidRenderNoRotateHorScanlines(&ddsd, 1, 1); + } + } + } + + pddsDtos->Unlock(NULL); + + return 0; +} + +// Run one frame and render the screen +int vidFrame(bool bRedraw) // bRedraw = 0 +{ + if (pVidImage == NULL) { + return 1; + } + + if (DtoPrim->IsLost()) { // We've lost control of the screen + if (VidSRestoreOSD()) { + return 1; + } + + if (FAILED(DtoDD->RestoreAllSurfaces())) { + return 1; + } + + DtoPrimClear(); + } + + if (bDrvOkay) { + if (bRedraw) { // Redraw current frame + if (BurnDrvRedraw()) { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } else { + BurnDrvFrame(); // Run one frame and draw the screen + } + } + + vidBurnToSurf(); + + return 0; +} + +// Paint the Dtos surface onto the primary surface +static int vidPaint(int bValidate) +{ + if (DtoPrim == NULL || pddsDtos == NULL) { + return 1; + } + + if (DtoPrim->IsLost()) { // We've lost control of the screen + return 1; + } + + if (!nVidFullscreen) { // Check if the window has changed since we prepared the image + RECT rect = { 0, 0, 0, 0 }; + + GetClientScreenRect(hVidWnd, &rect); + rect.top += 0 /*nMenuHeight*/; + + VidSScaleImage(&rect, nGameWidth, nGameHeight, bVidScanRotate); + + if (Dest.left != rect.left || Dest.right != rect.right || Dest.top != rect.top || Dest.bottom != rect.bottom) { + bValidate |= 2; + } + } + + if (bValidate & 2) { + vidBurnToSurf(); + } + + DWORD dwBltFlags = 0; // See if we need to use blit effects + if (DtoBltFx) { + dwBltFlags |= DDBLT_DDFX; + } + + if (bVidVSync && !nVidFullscreen) { DtoDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } + + if (DtoBack != NULL) { // Triple bufferring + if (FAILED(DtoBack->Blt(&Dest, pddsDtos, &Src, DDBLT_ASYNC | dwBltFlags, DtoBltFx))) { + if (FAILED(DtoBack->Blt(&Dest, pddsDtos, &Src, DDBLT_WAIT | dwBltFlags, DtoBltFx))) { + return 1; + } + } + VidSDisplayOSD(DtoBack, &Dest, 0); + + DtoPrim->Flip(NULL, DDFLIP_WAIT); + } else { // Normal + RECT rect = { 0, 0, nGameWidth, nGameHeight }; + int nFlags = 0; + + if (bDtosScan) { + if (bRotateScanlines) { + nFlags |= 0x01; + } else { + nFlags |= 0x02; + } + } + + // Display OSD text message + VidSDisplayOSD(pddsDtos, &rect, nFlags); + + if (FAILED(DtoPrim->Blt(&Dest, pddsDtos, &Src, DDBLT_ASYNC | dwBltFlags, DtoBltFx))) { + if (FAILED(DtoPrim->Blt(&Dest, pddsDtos, &Src, DDBLT_WAIT | dwBltFlags, DtoBltFx))) { + return 1; + } + } +/* + DWORD lpdwScanLine; + RECT window; + GetWindowRect(hVidWnd, &window); + + while (1) + { + DtoDD->GetScanLine(&lpdwScanLine); + if (lpdwScanLine >= (unsigned int)window.bottom) { + break; + } + //Sleep(1); + } +*/ + } + + if (bValidate & 1) { + // Validate the rectangle we just drew + POINT c = {0, 0}; + ClientToScreen(hVidWnd, &c); + Dest.left -= c.x; Dest.right -= c.x; + Dest.top -= c.y; Dest.bottom -= c.y; + ValidateRect(hVidWnd, &Dest); + } + + return 0; +} + +static int vidScale(RECT* pRect, int nWidth, int nHeight) +{ + return VidSScaleImage(pRect, nWidth, nHeight, bVidScanRotate); +} + +static int vidGetSettings(InterfaceInfo* pInfo) +{ + if (nVidFullscreen && DtoBack) { + IntInfoAddStringModule(pInfo, _T("Using a triple buffer")); + } else { + IntInfoAddStringModule(pInfo, _T("Using Blt() to transfer the image")); + } + + if (nUseSys) { + IntInfoAddStringModule(pInfo, _T("Using system memory")); + } else { + IntInfoAddStringModule(pInfo, _T("Using video memory for the final blit")); + } + + if (nRotateGame) { + TCHAR* pszEffect[8] = { _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T("") }; + TCHAR szString[MAX_PATH] = _T(""); + + pszEffect[0] = _T("Using "); + if (nRotateGame & 1) { + pszEffect[1] = _T("software rotation"); + } + if (nRotateGame & 2) { + if (nRotateGame & 1) { + pszEffect[2] = _T(" and"); + } + pszEffect[3] = _T(" hardware mirroring"); + } + pszEffect[4] = _T(", "); + + _sntprintf(szString, MAX_PATH, _T("%s%s%s%s%s%s%s%s"), pszEffect[0], pszEffect[1], pszEffect[2], pszEffect[3], pszEffect[4], pszEffect[5], pszEffect[6], pszEffect[7]); + IntInfoAddStringModule(pInfo, szString); + } + + if (bDtosScan) { + TCHAR* pszEffect[8] = { _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T(""), _T("") }; + TCHAR szString[MAX_PATH] = _T(""); + + pszEffect[0] = _T("Applying "); + if (bVidScanHalf) { + pszEffect[1] = _T("50% "); + } + if (bVidScanRotate) { + pszEffect[2] = _T("rotated "); + } + pszEffect[3] = _T("scanlines"); + + _sntprintf(szString, MAX_PATH, _T("%s%s%s%s%s%s%s%s"), pszEffect[0], pszEffect[1], pszEffect[2], pszEffect[3], pszEffect[4], pszEffect[5], pszEffect[6], pszEffect[7]); + IntInfoAddStringModule(pInfo, szString); + } + + return 0; +} + +// The video output plugin: +struct VidOut VidOutDDraw = { vidInit, vidExit, vidFrame, vidPaint, vidScale, vidGetSettings, _T("DirectDraw7 video output") }; diff --git a/src/interface/win32/vid_ddrawfx.cpp b/src/interface/win32/vid_ddrawfx.cpp new file mode 100644 index 00000000..f3526a45 --- /dev/null +++ b/src/interface/win32/vid_ddrawfx.cpp @@ -0,0 +1,573 @@ +// Software blitter effects via DirectDraw +#include "burner.h" + +#if !defined BUILD_X64_EXE +// #include "vid_directx_support.h" + #include "vid_softfx.h" +#endif + +#include +#define DIRECT3D_VERSION 0x0700 // Use this Direct3D version + +#if defined BUILD_X64_EXE +// #include "vid_directx_support.h" + #include "vid_softfx.h" +#endif + +#include "ddraw_core.h" + +static IDirectDraw7* BlitFXDD = NULL; // DirectDraw interface +static IDirectDrawSurface7* BlitFXPrim = NULL; // Primary surface +static IDirectDrawSurface7* BlitFXBack = NULL; // Back buffer surface + +static int nGameWidth = 0, nGameHeight = 0; // screen size +IDirectDrawSurface7* pddsBlitFX[2] = {NULL, }; // The image surfaces + +static int nSize; +static int nUseBlitter; + +static int nUseSys; +static int nDirectAccess = 1; +static int nRotateGame = 0; + +static int PrimClear() +{ + if (BlitFXPrim == NULL) { + return 1; + } + VidSClearSurface(BlitFXPrim, 0, NULL); // Clear 1st page + + if (BlitFXBack == NULL) { + return 0; + } + + VidSClearSurface(BlitFXBack, 0, NULL); // Clear 2nd page + BlitFXPrim->Flip(NULL, DDFLIP_WAIT); // wait till the flip actually occurs + VidSClearSurface(BlitFXBack, 0, NULL); // Clear 3rd page + + return 0; +} + +static int AutodetectUseSys() +{ + // Try to autodetect the best secondary buffer type to use, based on the cards capabilities + DDCAPS ddc; + if (BlitFXDD == NULL) { + return 1; + } + memset(&ddc, 0, sizeof(ddc)); + ddc.dwSize = sizeof(ddc); + BlitFXDD->GetCaps(&ddc, NULL); + + if (ddc.dwCaps & DDCAPS_BLTSTRETCH) { // If it can do a hardware stretch use video memory + return 0; + } else { // Otherwise use system memory: + return 1; + } +} + +// Create a secondary DD surface for the screen +static int BlitFXMakeSurf() +{ + int nRet; + DDSURFACEDESC2 ddsd; + + if (BlitFXDD == NULL) { + return 1; + } + + nUseSys = nVidTransferMethod; + if (nUseSys < 0) { + nUseSys = AutodetectUseSys(); + } + + nDirectAccess = 0; + if (nUseSys == 0 && nUseBlitter != 0) { + nDirectAccess = ((nVidBlitterOpt[nVidSelect] >> 9) & 1) ^ 1; + } + + pddsBlitFX[0] = NULL; + pddsBlitFX[1] = NULL; + + // Try to allocate buffer in Video memory if required, always allocate one in System memory + if (nUseSys == 0) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = nGameWidth * nSize; + ddsd.dwHeight = nGameHeight * nSize; + + nRet = BlitFXDD->CreateSurface(&ddsd, &pddsBlitFX[0], NULL); + + if (nRet < 0 || pddsBlitFX[0] == NULL) { // Allocation in Video meory has failed, so use System memory only + pddsBlitFX[0] = NULL; + nDirectAccess = 0; + nUseSys = 1; + } + } + + if (nDirectAccess == 0) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + + ddsd.dwWidth = nGameWidth * nSize; + ddsd.dwHeight = nGameHeight * nSize; + + nRet = BlitFXDD->CreateSurface(&ddsd, &pddsBlitFX[1], NULL); + + if (nRet < 0 || pddsBlitFX[1] == NULL) { + return 1; + } + } + + VidSClearSurface(pddsBlitFX[1 ^ nDirectAccess], 0, NULL); + + return 0; +} + +static int PrimInit(int bTriple) +{ + DDSURFACEDESC2 ddsd; + int nRet = 0; + + // Create the primary surface + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (bTriple) { + // Make a primary surface capable of triple bufferring + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY; + ddsd.dwBackBufferCount = 2; + } else { + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + } + + BlitFXPrim = NULL; + nRet = BlitFXDD->CreateSurface(&ddsd, &BlitFXPrim, NULL); + if (nRet < 0 || BlitFXPrim == NULL) { + return 1; + } + + if (bTriple == 0) { // We are done + return 0; + } + + // Get the back buffer + memset(&ddsd.ddsCaps, 0, sizeof(ddsd.ddsCaps)); + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + + BlitFXBack = NULL; + nRet = BlitFXPrim->GetAttachedSurface(&ddsd.ddsCaps, &BlitFXBack); + if (nRet < 0 || BlitFXBack == NULL) { // Failed to make triple buffer + RELEASE(BlitFXPrim) + return 1; + } + + PrimClear(); // Clear all three pages + return 0; +} + +static int BlitFXExit() +{ + RELEASE(pddsBlitFX[0]); + RELEASE(pddsBlitFX[1]); + + VidSFreeVidImage(); + + nRotateGame = 0; + + return 0; +} + +static int BlitFXInit() +{ + if (BlitFXDD == NULL) { + return 1; + } + + if (nRotateGame & 1) { + nVidImageWidth = nGameHeight; + nVidImageHeight = nGameWidth; + } else { + nVidImageWidth = nGameWidth; + nVidImageHeight = nGameHeight; + } + + RECT rect = { 0, 0, 0, 0 }; + GetClientScreenRect(hVidWnd, &rect); + if (!nVidFullscreen) { + rect.top += 0 /*nMenuHeight*/; + } + + if (nUseBlitter >= FILTER_SUPEREAGLE && nUseBlitter <= FILTER_SUPER_2XSAI) { + nVidImageDepth = 16; // Use 565 format + } else { + nVidImageDepth = VidSGetSurfaceDepth(BlitFXPrim); // Use color depth of primary surface + } + nVidImageBPP = (nVidImageDepth + 7) >> 3; + nBurnBpp = nVidImageBPP; // Set Burn library Bytes per pixel + + // Use our callback to get colors: + SetBurnHighCol(nVidImageDepth); + + // Make the normal memory buffer + if (VidSAllocVidImage()) { + BlitFXExit(); + return 1; + } + + // Make the DirectDraw secondary surface + if (BlitFXMakeSurf()) { + BlitFXExit(); + return 1; + } + + return 0; +} + +static int Exit() +{ + VidSExitOSD(); + + BlitFXExit(); + + VidSRestoreGamma(); + + RELEASE(BlitFXPrim); // a single call releases all surfaces + BlitFXBack = NULL; + + VidSRestoreScreenMode(); + + VidSExit(); + + RELEASE(BlitFXDD) + + return 0; +} + +static int Init() +{ + if (hScrnWnd == NULL) { + return 1; + } + + hVidWnd = nVidFullscreen ? hScrnWnd : hVideoWindow; // Use Screen window for video + + nUseBlitter = nVidBlitterOpt[nVidSelect] & 0xFF; + + // Get pointer to DirectDraw device + _DirectDrawCreateEx(NULL, (void**)&BlitFXDD, IID_IDirectDraw7, NULL); + + VidSInit(BlitFXDD); + + nGameWidth = nVidImageWidth; nGameHeight = nVidImageHeight; + + nRotateGame = 0; + if (bDrvOkay) { + // Get the game screen size + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (nVidRotationAdjust & 1) { + int n = nGameWidth; + nGameWidth = nGameHeight; + nGameHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } else { + nRotateGame |= 1; + } + } + + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + nRotateGame ^= 2; + } + } + + BlitFXPrim = NULL; // No primary surface yet + BlitFXBack = NULL; + + bVidScanlines = 0; // !!! + nSize = VidSoftFXGetZoom(nUseBlitter); + + // Remember the changes to the display + if (nVidFullscreen) { + int nZoom = nSize; + if ((nVidBlitterOpt[nVidSelect] & 0x0100) == 0) { + nZoom = nScreenSize; + } + + if (VidSEnterFullscreenMode(nZoom, VidSoftFXCheckDepth(nUseBlitter, 16))) { + Exit(); + return 1; + } + + if (bVidTripleBuffer) { + if (PrimInit(1)) { // Try to make triple buffer + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_TRIPLE)); + FBAPopupDisplay(PUF_TYPE_WARNING); + + // If we fail, fail entirely and make a normal buffer + RELEASE(BlitFXBack); + RELEASE(BlitFXPrim); + } + } + } else { + BlitFXDD->SetCooperativeLevel(hVidWnd, DDSCL_NORMAL); + } + + if (BlitFXPrim == NULL) { + // No primary surface yet, so try normal + if (PrimInit(0)) { + RELEASE(BlitFXBack); + RELEASE(BlitFXPrim); + } + } + + if (BlitFXPrim == NULL) { // No primary surface + Exit(); + return 1; + } + + if (nVidFullscreen) { + BlitFXDD->Compact(); + } + + VidSClipperInit(BlitFXPrim); + + VidSSetupGamma(BlitFXPrim); + + // Initialize the buffer surfaces + BlitFXInit(); + + if (VidSoftFXInit(nUseBlitter, nRotateGame)) { + if (VidSoftFXInit(0, nRotateGame)) { + Exit(); + return 1; + } + } + + VidSInitOSD(4 - nSize); + + return 0; +} + +static int vidScale(RECT* pRect, int nWidth, int nHeight) +{ + if (nVidBlitterOpt[nVidSelect] & 0x0100) { + return VidSoftFXScale(pRect, nWidth, nHeight); + } + + return VidSScaleImage(pRect, nWidth, nHeight, false); +} + +// Copy BlitFXsMem to pddsBlitFX +static int MemToSurf() +{ + if (pddsBlitFX == NULL) { + return 1; + } + + if (BlitFXPrim->IsLost()) { // We've lost control of the screen + return 1; + } + + VidSoftFXApplyEffectDirectX(pddsBlitFX[1 ^ nDirectAccess], NULL); + + if (nUseSys == 0 && nDirectAccess == 0) { + DDSURFACEDESC2 ddsd; + DDSURFACEDESC2 ddsdVid; + + // Lock the surface so we can write to it + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + pddsBlitFX[1]->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (ddsd.lpSurface == NULL) { + return 1; + } + unsigned char* Surf = (unsigned char*)ddsd.lpSurface; + int nPitch = ddsd.lPitch; + + // Lock the surface so we can write to it + memset(&ddsdVid, 0, sizeof(ddsdVid)); + ddsdVid.dwSize = sizeof(ddsdVid); + pddsBlitFX[0]->Lock(NULL, &ddsdVid, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (ddsdVid.lpSurface == NULL) { + return 1; + } + + unsigned char *pd, *ps; + + unsigned char* VidSurf = (unsigned char*)ddsdVid.lpSurface; + int nVidPitch = ddsdVid.lPitch; + int nHeight = nGameHeight * nSize; + + pd = VidSurf; ps = Surf; + for (int y = 0; y < nHeight; y++, pd += nVidPitch, ps += nPitch) { + memcpy(pd, ps, nPitch); + } + + pddsBlitFX[0]->Unlock(NULL); + pddsBlitFX[1]->Unlock(NULL); + } + + return 0; +} + +// Run one frame and render the screen +static int Frame(bool bRedraw) // bRedraw = 0 +{ + if (pVidImage == NULL) { + return 1; + } + + if (BlitFXPrim->IsLost()) { // We've lost control of the screen + + if (VidSRestoreOSD()) { + return 1; + } + + if (FAILED(BlitFXDD->RestoreAllSurfaces())) { + return 1; + } + + PrimClear(); + } + + if (bDrvOkay) { + if (bRedraw) { // Redraw current frame + if (BurnDrvRedraw()) { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } else { + BurnDrvFrame(); // Run one frame and draw the screen + } + } + + MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting + + return 0; +} + +// Paint the BlitFX surface onto the primary surface +static int Paint(int bValidate) +{ + RECT Dest = {0, 0, 0, 0}; + + if (BlitFXPrim == NULL || pddsBlitFX[nUseSys] == NULL) { + return 1; + } + + if (BlitFXPrim->IsLost()) { // We've lost control of the screen + return 1; + } + + GetClientScreenRect(hVidWnd, &Dest); + if (!nVidFullscreen) { + Dest.top += 0 /*nMenuHeight*/; + } + + if (bVidArcaderes && nVidFullscreen) { + Dest.left = (Dest.right + Dest.left) / 2; + Dest.left -= nGameWidth / 2; + Dest.right = Dest.left + nGameWidth; + + Dest.top = (Dest.top + Dest.bottom) / 2; + Dest.top -= nGameHeight / 2; + Dest.bottom = Dest.top + nGameHeight; + } else { + if (!bVidFullStretch) { + vidScale(&Dest, nGameWidth, nGameHeight); + } + } + + if (bValidate & 2) { + MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting + } + + RECT rect = { 0, 0, nGameWidth, nGameHeight }; + rect.right *= nSize; + rect.bottom *= nSize; + + // Display OSD text message + VidSDisplayOSD(pddsBlitFX[nUseSys], &rect, 0); + + if (bVidVSync && !nVidFullscreen) { BlitFXDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND, NULL); } + + if (BlitFXBack != NULL) { + // Triple bufferring + if (BlitFXBack->Blt(&Dest, pddsBlitFX[nUseSys], NULL, DDBLT_WAIT, NULL) < 0) { + return 1; + } + BlitFXPrim->Flip(NULL, DDFLIP_WAIT); + } else { + // Normal + if (BlitFXPrim->Blt(&Dest, pddsBlitFX[nUseSys], NULL, DDBLT_WAIT, NULL) < 0) { + return 1; + } + } + + + +/* + DWORD lpdwScanLine; + RECT window; + GetWindowRect(hVidWnd, &window); + + while(1) { + BlitFXDD->GetScanLine(&lpdwScanLine); + if (lpdwScanLine >= (unsigned int)window.bottom) { + break; + } + //Sleep(1); + } +*/ + + if (bValidate & 1) { + // Validate the rectangle we just drew + POINT c = {0, 0}; + ClientToScreen(hVidWnd, &c); + Dest.left -= c.x; Dest.right -= c.x; + Dest.top -= c.y; Dest.bottom -= c.y; + ValidateRect(hVidWnd, &Dest); + } + + return 0; +} + +static int GetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + + if (nVidFullscreen && BlitFXBack) { + IntInfoAddStringModule(pInfo, _T("Using a triple buffer")); + } else { + IntInfoAddStringModule(pInfo, _T("Using Blt() to transfer the image")); + } + + _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%ix zoom)"), VidSoftFXGetEffect(nUseBlitter), nSize); + IntInfoAddStringModule(pInfo, szString); + + if (nUseSys) { + IntInfoAddStringModule(pInfo, _T("Using system memory")); + } else { + if (nDirectAccess) { + IntInfoAddStringModule(pInfo, _T("Using video memory for effect buffers")); + } else { + IntInfoAddStringModule(pInfo, _T("Using video memory for the final blit")); + } + } + + if (nRotateGame) { + IntInfoAddStringModule(pInfo, _T("Using software rotation")); + } + + return 0; +} + +// The Video Output plugin: +struct VidOut VidOutDDrawFX = { Init, Exit, Frame, Paint, vidScale, GetSettings, _T("DirectDraw7 Software Effects video output") }; diff --git a/src/interface/win32/vid_directx9.cpp b/src/interface/win32/vid_directx9.cpp new file mode 100644 index 00000000..dd966198 --- /dev/null +++ b/src/interface/win32/vid_directx9.cpp @@ -0,0 +1,2230 @@ +// DirectX9 Enhanced video output +#include "burner.h" +#include "vid_softfx.h" + +//#ifdef _MSC_VER +//#pragma comment(lib, "d3d9") +//#pragma comment(lib, "d3dx9") + + +// #define ENABLE_PROFILING FBA_DEBUG +// #define LOAD_EFFECT_FROM_FILE + +#include +#define DIRECT3D_VERSION 0x0900 // Use this Direct3D version +#define D3D_OVERLOADS +#include +#include + +#include "directx9_core.h" + +const float PI = 3.14159265358979323846f; + +typedef struct _D3DLVERTEX2 { + union { FLOAT x; FLOAT dvX; }; + union { FLOAT y; FLOAT dvY; }; + union { FLOAT z; FLOAT dvZ; }; + union { D3DCOLOR color; D3DCOLOR dcColor; }; + union { D3DCOLOR specular; D3DCOLOR dcSpecular; }; + union { FLOAT tu; FLOAT dvTU; }; + union { FLOAT tv; FLOAT dvTV; }; + union { FLOAT tu1; FLOAT dvTU1; }; + union { FLOAT tv1; FLOAT dvTV1; }; +#if(DIRECT3D_VERSION >= 0x0500) + #if (defined __cplusplus) && (defined D3D_OVERLOADS) + _D3DLVERTEX2() { } + _D3DLVERTEX2(FLOAT _x, FLOAT _y, FLOAT _z, D3DCOLOR _color, D3DCOLOR _specular, FLOAT _tu, FLOAT _tv, FLOAT _tu1, FLOAT _tv1) + { + x = _x; y = _y; z = _z; + color = _color; specular = _specular; + tu = _tu; tv = _tv; + tu1 = _tu1; tv1 = _tv1; + } + #endif +#endif +} D3DLVERTEX2, *LPD3DLVERTEX2; + +#define D3DFVF_LVERTEX2 ( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE2(3) ) + +#define RENDER_STRIPS (4) + +#define DX9_SHADERPRECISION ((nVidBlitterOpt[nVidSelect] & (7 << 28)) >> 28) +#define DX9_FILTER ((nVidBlitterOpt[nVidSelect] & (3 << 24)) >> 24) +#define DX9_USE_PS20 ( nVidBlitterOpt[nVidSelect] & (1 << 9)) +#define DX9_USE_FPTEXTURE ( nVidBlitterOpt[nVidSelect] & (1 << 8)) + +static IDirect3D9* pD3D = NULL; // Direct3D interface +static D3DPRESENT_PARAMETERS d3dpp; +static IDirect3DDevice9* pD3DDevice = NULL; +static IDirect3DVertexBuffer9* pVB[RENDER_STRIPS] = { NULL, }; +static IDirect3DTexture9* pTexture = NULL; +static IDirect3DTexture9* pScanlineTexture[2] = { NULL, }; +static int nTextureWidth = 0, nTextureHeight = 0; +static IDirect3DSurface9* pSurface = NULL; + +static IDirect3DVertexBuffer9* pIntermediateVB = NULL; +static IDirect3DTexture9* pIntermediateTexture = NULL; +static int nIntermediateTextureWidth, nIntermediateTextureHeight; + +static ID3DXEffect* pEffect = NULL; +static ID3DXTextureShader* pEffectShader = NULL; +static D3DXHANDLE hTechnique = NULL; +//static D3DXHANDLE hScanIntensity = NULL; +static IDirect3DTexture9* pEffectTexture = NULL; + +static ID3DXFont* pFont = NULL; // OSD font +static D3DCOLOR osdColor = D3DCOLOR_ARGB(0xFF, 0xFF, 0xFF, 0xFF); + +static double dPrevCubicB, dPrevCubicC; + +static bool bUsePS14; + +static int nGameWidth = 0, nGameHeight = 0; // Game screen size +static int nGameImageWidth, nGameImageHeight; + +static int nRotateGame; +static int nImageWidth, nImageHeight/*, nImageZoom*/; + +static RECT Dest; + +// ---------------------------------------------------------------------------- + +static TCHAR* TextureFormatString(D3DFORMAT nFormat) +{ + switch (nFormat) { + case D3DFMT_X1R5G5B5: + return _T("16-bit xRGB 1555"); + case D3DFMT_R5G6B5: + return _T("16-bit RGB 565"); + case D3DFMT_X8R8G8B8: + return _T("32-bit xRGB 8888"); + case D3DFMT_A8R8G8B8: + return _T("32-bit ARGB 8888"); + case D3DFMT_A16B16G16R16F: + return _T("64-bit ARGB 16161616fp"); + case D3DFMT_A32B32G32R32F: + return _T("128-bit ARGB 32323232fp"); + default: + return _T("unknown format"); + } + + return _T("unknown format"); +} + +// ---------------------------------------------------------------------------- + +static int GetTextureSize(int nSize) +{ + int nTextureSize = 128; + + while (nTextureSize < nSize) { + nTextureSize <<= 1; + } + + return nTextureSize; +} + +/* +static void PutPixel(unsigned char** ppSurface, unsigned int nColour) +{ + switch (nVidScrnDepth) { + case 15: + *((unsigned short*)(*ppSurface)) = ((nColour >> 9) & 0x7C00) | ((nColour >> 6) & 0x03E0) | ((nColour >> 3) & 0x001F); + *ppSurface += 2; + break; + case 16: + *((unsigned short*)(*ppSurface)) = ((nColour >> 8) & 0xF800) | ((nColour >> 5) & 0x07E0) | ((nColour >> 3) & 0x001F); + *ppSurface += 2; + break; + case 24: + (*ppSurface)[0] = (nColour >> 16) & 0xFF; + (*ppSurface)[1] = (nColour >> 8) & 0xFF; + (*ppSurface)[2] = (nColour >> 0) & 0xFF; + *ppSurface += 3; + break; + case 32: + *((unsigned int*)(*ppSurface)) = nColour; + *ppSurface += 4; + break; + } +} +*/ + +// Select optimal full-screen resolution +int dx9SelectFullscreenMode(VidSDisplayScoreInfo* pScoreInfo) +{ + //int nWidth, nHeight; + + if (bVidArcaderes) { + if (!VidSGetArcaderes((int*)&(pScoreInfo->nBestWidth), (int*)&(pScoreInfo->nBestHeight))) { + return 1; + } + } else { + if (nScreenSize) { + D3DFORMAT nFormat = (nVidDepth == 16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8; + D3DDISPLAYMODE dm; + + memset(pScoreInfo, 0, sizeof(VidSDisplayScoreInfo)); + pScoreInfo->nRequestedZoom = nScreenSize; + VidSInitScoreInfo(pScoreInfo); + + // Enumerate the available screenmodes + for (int i = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, nFormat) - 1; i >= 0; i--) { + if (FAILED(pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, nFormat, i, &dm))) { + return 1; + } + pScoreInfo->nModeWidth = dm.Width; + pScoreInfo->nModeHeight = dm.Height; + + VidSScoreDisplayMode(pScoreInfo); + } + + if (pScoreInfo->nBestWidth == -1U) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_NOMODE)); + FBAPopupDisplay(PUF_TYPE_ERROR); + return 1; + } + } else { + pScoreInfo->nBestWidth = nVidWidth; + pScoreInfo->nBestHeight = nVidHeight; + } + } + + if (!bDrvOkay && (pScoreInfo->nBestWidth < 640 || pScoreInfo->nBestHeight < 480)) { + return 1; + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +static void FillEffectTexture() +{ + FLOAT B = (FLOAT)dVidCubicB; + FLOAT C = (FLOAT)dVidCubicC; + + if (pEffect == NULL) { + return; + } + +/* + if (dVidCubicSharpness > 0.5) { + C = dVidCubicSharpness; + B = 0.0; + } else { + C = dVidCubicSharpness; + B = 1.0 - 2.0 * C; + } +*/ + + if (DX9_SHADERPRECISION == 4 || bUsePS14) { + B = 0.0; + } + + if (pEffectShader && pEffectTexture) { + pEffectShader->SetFloat("B", B); + pEffectShader->SetFloat("C", C); + + _D3DXFillTextureTX(pEffectTexture, pEffectShader); + } + + pEffect->SetFloat("B", B); + pEffect->SetFloat("C", C); +} + +// ---------------------------------------------------------------------------- + +static void dx9ReleaseResources() +{ + RELEASE(pEffect); + RELEASE(pEffectShader); + RELEASE(pEffectTexture); + + RELEASE(pScanlineTexture[0]); + RELEASE(pScanlineTexture[1]); + RELEASE(pIntermediateTexture); + + RELEASE(pSurface); + RELEASE(pTexture); + + for (int y = 0; y < RENDER_STRIPS; y++) { + RELEASE(pVB[y]); + } + RELEASE(pIntermediateVB); +} + +static int dx9Exit() +{ + dx9ReleaseResources(); + + VidSFreeVidImage(); + + RELEASE(pFont); + RELEASE(pD3DDevice); + RELEASE(pD3D); + + nRotateGame = 0; + + return 0; +} + +static int dx9SurfaceInit() +{ + D3DFORMAT nFormat = D3DFMT_UNKNOWN; + + if (nRotateGame & 1) { + nVidImageWidth = nGameHeight; + nVidImageHeight = nGameWidth; + } else { + nVidImageWidth = nGameWidth; + nVidImageHeight = nGameHeight; + } + + nGameImageWidth = nVidImageWidth; + nGameImageHeight = nVidImageHeight; + + if (bDrvOkay && (BurnDrvGetFlags() & BDF_16BIT_ONLY)) { + nVidImageDepth = 15; + } else { + nVidImageDepth = nVidScrnDepth; + } + + switch (nVidImageDepth) { + case 32: + nFormat = D3DFMT_X8R8G8B8; + break; + case 24: + nFormat = D3DFMT_R8G8B8; + break; + case 16: + nFormat = D3DFMT_R5G6B5; + break; + case 15: + nFormat = D3DFMT_X1R5G5B5; + break; + } + + nVidImageBPP = (nVidImageDepth + 7) >> 3; + nBurnBpp = nVidImageBPP; // Set Burn library Bytes per pixel + + // Use our callback to get colors: + SetBurnHighCol(nVidImageDepth); + + // Make the normal memory buffer + if (VidSAllocVidImage()) { + dx9Exit(); + return 1; + } + + if (FAILED(pD3DDevice->CreateOffscreenPlainSurface(nVidImageWidth, nVidImageHeight, nFormat, D3DPOOL_DEFAULT, &pSurface, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create surface.\n")); +#endif + return 1; + } +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Allocated a %i x %i (%s) surface.\n"), nVidImageWidth, nVidImageHeight, TextureFormatString(nFormat)); +#endif + + nTextureWidth = GetTextureSize(nGameImageWidth); + nTextureHeight = GetTextureSize(nGameImageHeight); + + if (FAILED(pD3DDevice->CreateTexture(nTextureWidth, nTextureHeight, 1, D3DUSAGE_RENDERTARGET, nFormat, D3DPOOL_DEFAULT, &pTexture, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create texture.\n")); +#endif + return 1; + } +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Allocated a %i x %i (%s) image texture.\n"), nTextureWidth, nTextureHeight, TextureFormatString(nFormat)); +#endif + + return 0; +} + +static int dx9EffectSurfaceInit() +{ + D3DFORMAT nFormat; + + if (DX9_FILTER == 2 && (bUsePS14 || (DX9_SHADERPRECISION != 0 && DX9_SHADERPRECISION != 2))) { + switch (DX9_SHADERPRECISION) { + case 0: + nFormat = D3DFMT_A32B32G32R32F; + break; + case 1: + nFormat = D3DFMT_A16B16G16R16F; + break; + case 2: + nFormat = D3DFMT_A32B32G32R32F; + break; + case 3: + nFormat = D3DFMT_A16B16G16R16F; + break; + default: + nFormat = D3DFMT_A8R8G8B8; + } + + if (bUsePS14) { + nFormat = D3DFMT_A8R8G8B8; + } + + if (FAILED(pD3DDevice->CreateTexture(1024, 1, 1, D3DUSAGE_RENDERTARGET, nFormat, D3DPOOL_DEFAULT, &pEffectTexture, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create effects texture.\n")); +#endif + return 1; + } +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Allocated a %i x %i (%s) LUT texture.\n"), 1024, 1, TextureFormatString(nFormat)); +#endif + } + + if ((DX9_FILTER == 1 && bVidScanlines) || (DX9_FILTER == 2 && (bUsePS14 || DX9_SHADERPRECISION >= 2 || bVidScanlines))) { + if (nVidFullscreen) { + nIntermediateTextureWidth = GetTextureSize(nRotateGame ? nVidScrnHeight : nVidScrnWidth); + } else { + nIntermediateTextureWidth = GetTextureSize(nRotateGame ? SystemWorkArea.bottom - SystemWorkArea.top : SystemWorkArea.right - SystemWorkArea.left); + } + nIntermediateTextureHeight = nTextureHeight; + + nFormat = D3DFMT_A8R8G8B8; + if ((DX9_FILTER == 2) && !bUsePS14 && DX9_USE_FPTEXTURE) { +#if 0 + if ((DX9_SHADERPRECISION == 0 || DX9_SHADERPRECISION == 2) && !bVidScanlines) { + nFormat = D3DFMT_A32B32G32R32F; + } else { + nFormat = D3DFMT_A16B16G16R16F; + } +#else + nFormat = D3DFMT_A16B16G16R16F; +#endif + } + + if (FAILED(pD3DDevice->CreateTexture(nIntermediateTextureWidth, nIntermediateTextureHeight, 1, D3DUSAGE_RENDERTARGET, nFormat, D3DPOOL_DEFAULT, &pIntermediateTexture, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create intermediate texture.\n")); +#endif + return 1; + } +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Allocated a %i x %i (%s) intermediate texture.\n"), nIntermediateTextureWidth, nIntermediateTextureHeight, TextureFormatString(nFormat)); +#endif + } + + { + // Clear textures and set border colour + + IDirect3DSurface9* pSurf; + + pTexture->GetSurfaceLevel(0, &pSurf); + pD3DDevice->ColorFill(pSurf, 0, D3DCOLOR_XRGB(0, 0, 0)); + RELEASE(pSurf); + + if (pIntermediateTexture) { + pIntermediateTexture->GetSurfaceLevel(0, &pSurf); + pD3DDevice->ColorFill(pSurf, 0, D3DCOLOR_XRGB(0, 0, 0)); + RELEASE(pSurf); + } + + pD3DDevice->SetSamplerState(0, D3DSAMP_BORDERCOLOR, D3DCOLOR_XRGB(0, 0, 0)); + pD3DDevice->SetSamplerState(1, D3DSAMP_BORDERCOLOR, D3DCOLOR_XRGB(0, 0, 0)); + } + + // Allocate scanline textures + for (int i = 0, nSize = 2; i < 2; i++, nSize <<= 1) { + RECT rect = { 0, 0, nSize, nSize }; + IDirect3DSurface9* pSurf = NULL; + + unsigned int scan2x2[] = { 0xFFFFFF, 0xFFFFFF, + 0x000000, 0x000000 }; + + unsigned int scan4x4[] = { 0x9F9F9F, 0x9F9F9F, 0x9F9F9F, 0x9F9F9F, + 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, + 0x9F9F9F, 0x9F9F9F, 0x9F9F9F, 0x9F9F9F, + 0x000000, 0x000000, 0x000000, 0x000000 }; + + unsigned int* scandata[] = { scan2x2, scan4x4 }; + + if (FAILED(pD3DDevice->CreateTexture(nSize, nSize, 1, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &(pScanlineTexture[i]), NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create texture.\n")); +#endif + return 1; + } + if (FAILED(pScanlineTexture[i]->GetSurfaceLevel(0, &pSurf))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't get texture surface.\n")); +#endif + } + + if (FAILED(_D3DXLoadSurfaceFromMemory(pSurf, NULL, &rect, scandata[i], D3DFMT_X8R8G8B8, nSize * sizeof(int), NULL, &rect, D3DX_FILTER_NONE, 0))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: D3DXLoadSurfaceFromMemory failed.\n")); +#endif + } + + RELEASE(pSurf); + } + + return 0; +} + +int dx9GeometryInit() +{ + for (int y = 0; y < RENDER_STRIPS; y++) { + + D3DLVERTEX2 vScreen[4]; + + // The polygons for the emulator image on the screen + { + int nWidth = pIntermediateTexture ? nImageWidth : nGameImageWidth; + int nHeight = nGameImageHeight; + int nTexWidth = pIntermediateTexture ? nIntermediateTextureWidth : nTextureWidth; + int nTexHeight = nTextureHeight; + + // Add 0.0000001 to ensure consistent rounding + double dTexCoordXl = 0.0000001; + double dTexCoordXr = (double)nWidth / (double)nTexWidth + 0.0000001; + double dTexCoordYt = (double)nHeight * (double)(y + 0) / (double)(nTexHeight * RENDER_STRIPS) + 0.0000001; + double dTexCoordYb = (double)nHeight * (double)(y + 1) / (double)(nTexHeight * RENDER_STRIPS) + 0.0000001; + + double dLeft = 1.0 - 2.0; + double dRight = 1.0 - 0.0; + double dTop = 1.0 - (((double)((nRotateGame & 1) ? (RENDER_STRIPS - y - 0) : (y + 0))) * 2.0 / RENDER_STRIPS); + double dBottom = 1.0 - (((double)((nRotateGame & 1) ? (RENDER_STRIPS - y - 1) : (y + 1))) * 2.0 / RENDER_STRIPS); + + // ugly fix for flipped game, modified by regret + if ((nRotateGame & 1) && (nRotateGame & 2)) { + dTop = 1.0 - (((double)(y + 0)) * 2.0 / RENDER_STRIPS); + dBottom = 1.0 - (((double)(y + 1)) * 2.0 / RENDER_STRIPS); + } + else if (nRotateGame & 2) { + dTop = 1.0 - (((double)(RENDER_STRIPS - y - 0)) * 2.0 / RENDER_STRIPS); + dBottom = 1.0 - (((double)(RENDER_STRIPS - y - 1)) * 2.0 / RENDER_STRIPS); + } + + if (pIntermediateTexture && bVidScanlines) { + dTexCoordXl += 0.5 / (double)nIntermediateTextureWidth; + dTexCoordXr += 0.5 / (double)nIntermediateTextureWidth; + dTexCoordYt += 1.0 / (double)nIntermediateTextureHeight; + dTexCoordYb += 1.0 / (double)nIntermediateTextureHeight; + } + +#if 0 + if (nPreScaleEffect) { + if (nPreScale & 1) { + nWidth *= nPreScaleZoom; + nTexWidth = nPreScaleTextureWidth; + } + if (nPreScale & 2) { + nHeight *= nPreScaleZoom; + nTexHeight = nPreScaleTextureHeight; + } + } +#endif + + // Set up the vertices for the game image, including the texture coordinates for the game image only + // ugly fix for flipped game, modified by regret + if (nRotateGame & 1) { + vScreen[(nRotateGame & 2) ? 3 : 0] = D3DLVERTEX2(dTop, dLeft, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXr : dTexCoordXl, dTexCoordYt, 0, 0); + vScreen[(nRotateGame & 2) ? 2 : 1] = D3DLVERTEX2(dTop, dRight, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXl : dTexCoordXr, dTexCoordYt, 0, 0); + vScreen[(nRotateGame & 2) ? 1 : 2] = D3DLVERTEX2(dBottom, dLeft, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXr : dTexCoordXl, dTexCoordYb, 0, 0); + vScreen[(nRotateGame & 2) ? 0 : 3] = D3DLVERTEX2(dBottom, dRight, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXl : dTexCoordXr, dTexCoordYb, 0, 0); + } else { + vScreen[(nRotateGame & 2) ? 3 : 0] = D3DLVERTEX2(dLeft, dTop, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXr : dTexCoordXl, dTexCoordYt, 0, 0); + vScreen[(nRotateGame & 2) ? 2 : 1] = D3DLVERTEX2(dRight, dTop, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXl : dTexCoordXr, dTexCoordYt, 0, 0); + vScreen[(nRotateGame & 2) ? 1 : 2] = D3DLVERTEX2(dLeft, dBottom, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXr : dTexCoordXl, dTexCoordYb, 0, 0); + vScreen[(nRotateGame & 2) ? 0 : 3] = D3DLVERTEX2(dRight, dBottom, 0.0, 0xFFFFFFFF, 0, (nRotateGame & 2) ? dTexCoordXl : dTexCoordXr, dTexCoordYb, 0, 0); + } + + { + // Set up the 2nd pair of texture coordinates, used for scanlines or the high performance version of the cubic filter + + double dScanOffset = nGameImageHeight / -2.0; + + if (bVidScanlines) { + int s, z = nImageHeight / nGameImageHeight; + + for (s = 2; s < z; s <<= 1) { } + dScanOffset += 0.5 / s; + } else { + dScanOffset += 0.5; + } + + // Set the texture coordinates for the scanlines + if (nRotateGame & 1) { + vScreen[nRotateGame & 2 ? 3 : 0].tu1 = dScanOffset + 0.0; vScreen[nRotateGame & 2 ? 3 : 0].tv1 = dScanOffset + 0.0 + 0.0000001; + vScreen[nRotateGame & 2 ? 2 : 1].tu1 = dScanOffset + (double)nGameHeight; vScreen[nRotateGame & 2 ? 2 : 1].tv1 = dScanOffset + 0.0 + 0.0000001; + vScreen[nRotateGame & 2 ? 1 : 2].tu1 = dScanOffset + 0.0; vScreen[nRotateGame & 2 ? 1 : 2].tv1 = dScanOffset + (double)nGameWidth / RENDER_STRIPS + 0.0000001; + vScreen[nRotateGame & 2 ? 0 : 3].tu1 = dScanOffset + (double)nGameHeight; vScreen[nRotateGame & 2 ? 0 : 3].tv1 = dScanOffset + (double)nGameWidth / RENDER_STRIPS + 0.0000001; + } else { + vScreen[nRotateGame & 2 ? 3 : 0].tu1 = dScanOffset + 0.0; vScreen[nRotateGame & 2 ? 3 : 0].tv1 = dScanOffset + 0.0 + 0.0000001; + vScreen[nRotateGame & 2 ? 2 : 1].tu1 = dScanOffset + (double)nGameWidth; vScreen[nRotateGame & 2 ? 2 : 1].tv1 = dScanOffset + 0.0 + 0.0000001; + vScreen[nRotateGame & 2 ? 1 : 2].tu1 = dScanOffset + 0.0; vScreen[nRotateGame & 2 ? 1 : 2].tv1 = dScanOffset + (double)nGameHeight / RENDER_STRIPS + 0.0000001; + vScreen[nRotateGame & 2 ? 0 : 3].tu1 = dScanOffset + (double)nGameWidth; vScreen[nRotateGame & 2 ? 0 : 3].tv1 = dScanOffset + (double)nGameHeight / RENDER_STRIPS + 0.0000001; + } + } + } + + { + D3DLVERTEX2* pVertexData; + + if (FAILED(pVB[y]->Lock(0, 4 * sizeof(D3DLVERTEX2), (void**)&pVertexData, 0))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create vertex buffer.\n")); +#endif + return 1; + } + memcpy(pVertexData, &vScreen, 4 * sizeof(D3DLVERTEX2)); + pVB[y]->Unlock(); + } + } + + if (bVidScanlines) { + pEffect->SetTexture("scanTexture", pScanlineTexture[(nImageHeight / nGameImageHeight >= 4) ? 1 : 0]); + } + + if (pIntermediateTexture) { + D3DLVERTEX2* pVertexData; + D3DLVERTEX2 vTemp[4]; + + double dTexCoordXl = 0.0; + double dTexCoordXr = (double)nGameImageWidth / (double)nTextureWidth; + double dTexCoordYt = 0.0 + 0.0000001; + double dTexCoordYb = 1.0 + 0.0000001; + + if (DX9_FILTER == 1) { + dTexCoordYt -= 0.5 / nTextureHeight; + dTexCoordYb -= 0.5 / nTextureHeight; + } + + vTemp[0] = D3DLVERTEX2(-1.0, 1.0, 0.0, 0xFFFFFFFF, 0, dTexCoordXl, dTexCoordYt, 0.5 , 0.5); + vTemp[1] = D3DLVERTEX2( 1.0, 1.0, 0.0, 0xFFFFFFFF, 0, dTexCoordXr, dTexCoordYt, 0.5 + nGameImageWidth, 0.5); + vTemp[2] = D3DLVERTEX2(-1.0, -1.0, 0.0, 0xFFFFFFFF, 0, dTexCoordXl, dTexCoordYb, 0.5, 0.5 + nGameImageHeight); + vTemp[3] = D3DLVERTEX2( 1.0, -1.0, 0.0, 0xFFFFFFFF, 0, dTexCoordXr, dTexCoordYb, 0.5 + nGameImageWidth, 0.5 + nGameImageHeight); + + if (FAILED(pIntermediateVB->Lock(0, 4 * sizeof(D3DLVERTEX2), (void**)&pVertexData, 0))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create vertex buffer.\n")); +#endif + return 1; + } + + memcpy(pVertexData, &vTemp, 4 * sizeof(D3DLVERTEX2)); + pIntermediateVB->Unlock(); + } + + return 0; +} + +int dx9EffectInit() +{ +// Set up the bicubic filter + +// char szB[MAX_PATH] = "(1.0)"; +// char szC[MAX_PATH] = "(0.0)"; +// D3DXMACRO d3dxm[] = {{ "USE_BC_MACRO", "1", }, { "B", szB, }, { "C", szC, }, { NULL, NULL, }}; + + char* pszTechniqueOpt[] = { "ScanBilinear", "Bilinear", "ScanPoint", "Point" }; + char* pszTechnique = NULL; + + ID3DXBuffer* pErrorBuffer = NULL; + FLOAT pFloatArray[2]; + + pEffect = NULL; + pEffectShader = NULL; + + _D3DXCreateBuffer(0x10000, &pErrorBuffer); + +#ifdef LOAD_EFFECT_FROM_FILE + if (FAILED(_D3DXCreateEffectFromFile(pD3DDevice, _T("bicubic.fx"), NULL /* d3dxm */, NULL, D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &pEffect, &pErrorBuffer))) { +#else + if (FAILED(_D3DXCreateEffectFromResource(pD3DDevice, NULL, MAKEINTRESOURCE(ID_DX9EFFECT), NULL /* d3dxm */, NULL, D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &pEffect, &pErrorBuffer))) { +#endif +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't compile effect.\n")); + dprintf(_T("\n%hs\n\n"), pErrorBuffer->GetBufferPointer()); +#endif + goto HANDLE_ERROR; + } + + // Check if we need to use PS1.4 (instead of 2.0) + bUsePS14 = !DX9_USE_PS20; + if (pEffect->GetTechniqueByName("SinglePassHQBicubic") == NULL) { + bUsePS14 = true; + } + + if (dx9EffectSurfaceInit()) { + goto HANDLE_ERROR; + } + + switch (DX9_FILTER) { + case 1: { + pszTechnique = bVidScanlines ? pszTechniqueOpt[0] : pszTechniqueOpt[1]; + break; + } + case 2: { + if (bVidScanlines) { + char* pszFunction[8] = { "ScanHQBicubic", "ScanBicubic", "ScanHQBicubic", "ScanBicubic", "ScanHP20Bicubic", "ScanHP14Bicubic", "ScanHP14Bicubic", "ScanHP14Bicubic" }; + pszTechnique = pszFunction[bUsePS14 ? 7 : DX9_SHADERPRECISION]; + } else { + char* pszFunction[8] = { "SinglePassHQBicubic", "SinglePassBicubic", "MultiPassHQBicubic", "MultiPassBicubic", "MultiPassHP20Bicubic", "MultiPassHP14Bicubic", "MultiPassHP14Bicubic", "MultiPassHP14Bicubic" }; + pszTechnique = pszFunction[bUsePS14 ? 7 : DX9_SHADERPRECISION]; + } + break; + } + default: { + pszTechnique = bVidScanlines ? pszTechniqueOpt[2] : pszTechniqueOpt[3]; + break; + } + } + + pEffect->SetTexture("imageTexture", pTexture); + pEffect->SetTexture("intermediateTexture", pIntermediateTexture); + pEffect->SetTexture("scanTexture", pScanlineTexture[(nImageHeight / nGameImageHeight >= 4) ? 1 : 0]); + + pFloatArray[0] = nTextureWidth; pFloatArray[1] = nTextureHeight; + pEffect->SetFloatArray("imageSize", pFloatArray, 2); + pFloatArray[0] = 1.0 / nTextureWidth; pFloatArray[1] = 1.0 / nTextureHeight; + pEffect->SetFloatArray("texelSize", pFloatArray, 2); + +/* + { + FLOAT fScanIntensity[4] = { (float)((nVidScanIntensity >> 16) & 255) / 255.0, + (float)((nVidScanIntensity >> 8) & 255) / 255.0, + (float)((nVidScanIntensity >> 0) & 255) / 255.0, + (float)((nVidScanIntensity >> 24) & 255) / 255.0 }; + + pEffect->SetFloatArray("scanIntensity", fScanIntensity, 4); + } +*/ + hTechnique = pEffect->GetTechniqueByName(pszTechnique); + if (FAILED(pEffect->SetTechnique(hTechnique))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't set technique.\n")); +#endif + goto HANDLE_ERROR; + } + + pEffect->SetTexture("weightTex", pEffectTexture); + + { + ID3DXBuffer* pEffectShaderBuffer = NULL; + _D3DXCreateBuffer(0x10000, &pEffectShaderBuffer); + +#ifdef LOAD_EFFECT_FROM_FILE + if (FAILED(_D3DXCompileShaderFromFile(_T("bicubic.fx"), NULL, NULL, (DX9_SHADERPRECISION < 4 && !bUsePS14) ? "genWeightTex20" : "genWeightTex14", "tx_1_0", 0, &pEffectShaderBuffer, &pErrorBuffer, NULL))) { +#else + if (FAILED(_D3DXCompileShaderFromResource(NULL, MAKEINTRESOURCE(ID_DX9EFFECT), NULL, NULL, (DX9_SHADERPRECISION < 4 && !bUsePS14) ? "genWeightTex20" : "genWeightTex14", "tx_1_0", 0, &pEffectShaderBuffer, &pErrorBuffer, NULL))) { +#endif +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't compile shader.\n")); + dprintf(_T("\n%hs\n\n"), pErrorBuffer->GetBufferPointer()); +#endif + goto HANDLE_ERROR; + } + + if (FAILED(_D3DXCreateTextureShader((DWORD*)(pEffectShaderBuffer->GetBufferPointer()), &pEffectShader))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create texture shader.\n")); +#endif + RELEASE(pEffectShaderBuffer); + + goto HANDLE_ERROR; + } + + FillEffectTexture(); + + RELEASE(pEffectShaderBuffer); + } + + RELEASE(pErrorBuffer); + + return 0; + +HANDLE_ERROR: + + RELEASE(pErrorBuffer); + + return 1; +} + +// ==> osd for dx9 video output (ugly), added by regret +static int dx9CreateFont() +{ + if (pFont) { + return 0; + } + + HRESULT hr = _D3DXCreateFont(pD3DDevice, d3dpp.BackBufferHeight / 18, + 0, FW_DEMIBOLD, 1, FALSE, + DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, + DEFAULT_PITCH || FF_DONTCARE, + _T("Arial"), &pFont); + + if (FAILED(hr)) { + return 1; + } + return 0; +} + +static void dx9DrawText() +{ + if (nVidSDisplayStatus == 0 || nOSDTimer == 0) { + return; + } + + if (nFramesEmulated > nOSDTimer) { + VidSKillShortMsg(); + VidSKillOSDMsg(); + } + + RECT osdRect; + if (nVidFullscreen) { + osdRect.left = Dest.left; + osdRect.top = Dest.top; + osdRect.right = Dest.right - 1; + osdRect.bottom = Dest.bottom - 1; + } else { + osdRect.left = 0; + osdRect.top = 0; + osdRect.right = Dest.right - Dest.left - 1; + osdRect.bottom = Dest.bottom - Dest.top - 1; + } + + pFont->DrawText(NULL, OSDMsg, -1, &osdRect, DT_RIGHT | DT_TOP, osdColor); +} +// <== osd for dx9 video output (ugly) + +static int dx9Init() +{ + if (nVidFullscreen && !hScrnWnd) { + return 1; + } + +#ifdef ENABLE_PROFILING + ProfileInit(); +#endif + +#ifdef PRINT_DEBUG_INFO + dprintf(_T("*** Initialising Direct3D 9 blitter.\n")); +#endif + + hVidWnd = nVidFullscreen ? hScrnWnd : hVideoWindow; // Use Screen window for video + + // Get pointer to Direct3D + if ((pD3D = _Direct3DCreate9(D3D_SDK_VERSION)) == NULL) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't initialise Direct3D.\n")); +#endif + dx9Exit(); + return 1; + } + + memset(&d3dpp, 0, sizeof(d3dpp)); + if (nVidFullscreen) { + VidSDisplayScoreInfo ScoreInfo; + if (dx9SelectFullscreenMode(&ScoreInfo)) { + dx9Exit(); +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't determine display mode.\n")); +#endif + return 1; + } + + d3dpp.BackBufferWidth = ScoreInfo.nBestWidth; + d3dpp.BackBufferHeight = ScoreInfo.nBestHeight; + d3dpp.BackBufferFormat = (nVidDepth == 16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8; + d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP; + d3dpp.BackBufferCount = bVidTripleBuffer ? 2 : 1; + d3dpp.hDeviceWindow = hVidWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } else { + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; + d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; + d3dpp.hDeviceWindow = hVidWnd; + d3dpp.Windowed = TRUE; + d3dpp.PresentationInterval = bVidVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + } + + DWORD dwBehaviorFlags = bVidVSync ? (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED) : (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE); +#ifdef _DEBUG + dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT; +#endif + + if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hVidWnd, dwBehaviorFlags, &d3dpp, &pD3DDevice))) { +// if (FAILED(pD3D->CreateDevice(pD3D->GetAdapterCount() - 1, D3DDEVTYPE_REF, hVidWnd, dwBehaviorFlags, &d3dpp, &pD3DDevice))) { + +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create Direct3D device.\n")); +#endif + + if (nVidFullscreen) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_PROBLEM)); + if (bVidArcaderes && (d3dpp.BackBufferWidth != 320 && d3dpp.BackBufferHeight != 240)) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_CUSTRES)); + } + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + dx9Exit(); + return 1; + } + + { + D3DDISPLAYMODE dm; + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm); + nVidScrnWidth = dm.Width; nVidScrnHeight = dm.Height; + nVidScrnDepth = (dm.Format == D3DFMT_R5G6B5) ? 16 : 32; + } + + nGameWidth = nVidImageWidth; nGameHeight = nVidImageHeight; + + nRotateGame = 0; + if (bDrvOkay) { + // Get the game screen size + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (nVidRotationAdjust & 1) { + int n = nGameWidth; + nGameWidth = nGameHeight; + nGameHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } else { + nRotateGame |= 1; + } + } + + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + nRotateGame ^= 2; + } + } + +// VidSSetupGamma(BlitFXPrim); + + // Initialize the buffer surfaces + if (dx9SurfaceInit()) { + dx9Exit(); + return 1; + } + if (dx9EffectInit()) { + dx9Exit(); + return 1; + } + + for (int y = 0; y < RENDER_STRIPS; y++) { + if (FAILED(pD3DDevice->CreateVertexBuffer(4 * sizeof(D3DLVERTEX2), D3DUSAGE_WRITEONLY, D3DFVF_LVERTEX2, D3DPOOL_DEFAULT, &pVB[y], NULL))) { + dx9Exit(); + return 1; + } + } + if (FAILED(pD3DDevice->CreateVertexBuffer(4 * sizeof(D3DLVERTEX2), D3DUSAGE_WRITEONLY, D3DFVF_LVERTEX2, D3DPOOL_DEFAULT, &pIntermediateVB, NULL))) { + dx9Exit(); + return 1; + } + + nImageWidth = 0; nImageHeight = 0; + + dPrevCubicB = dPrevCubicC = -999; + + pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + // Clear the swapchain's buffers + if (nVidFullscreen) { + for (int i = 0; i < 3; i++) { + pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + pD3DDevice->Present(NULL, NULL, NULL, NULL); + } + } else { + RECT rect; + + GetClientScreenRect(hVidWnd, &rect); + rect.top += 0 /*nMenuHeight*/; rect.bottom += 0 /*nMenuHeight*/; + pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + pD3DDevice->Present(&rect, &rect, NULL, NULL); + } + + // Create osd font + dx9CreateFont(); + +#ifdef PRINT_DEBUG_INFO + { + dprintf(_T(" * Initialisation complete: %.2lfMB texture memory free (total).\n"), (double)pD3DDevice->GetAvailableTextureMem() / (1024 * 1024)); + dprintf(_T(" Displaying and rendering in %i-bit mode, emulation running in %i-bit mode.\n"), nVidScrnDepth, nVidImageDepth); + if (nVidFullscreen) { + dprintf(_T(" Running in fullscreen mode (%i x %i), "), nVidScrnWidth, nVidScrnHeight); + dprintf(_T("using a %s buffer.\n"), bVidTripleBuffer ? _T("triple") : _T("double")); + } else { + dprintf(_T(" Running in windowed mode, using D3DSWAPEFFECT_COPY to present the image.\n")); + } + } +#endif + + return 0; +} + +static int dx9Reset() +{ +#ifdef PRINT_DEBUG_INFO + dprintf(_T("*** Resestting Direct3D device.\n")); +#endif + + if (pFont) { + pFont->OnLostDevice(); + } + + dx9ReleaseResources(); + + if (FAILED(pD3DDevice->Reset(&d3dpp))) { + return 1; + } + + if (pFont) { + pFont->OnResetDevice(); + } + + dx9SurfaceInit(); + dx9EffectInit(); + + for (int y = 0; y < RENDER_STRIPS; y++) { + pD3DDevice->CreateVertexBuffer(4 * sizeof(D3DLVERTEX2), D3DUSAGE_WRITEONLY, D3DFVF_LVERTEX2, D3DPOOL_DEFAULT, &pVB[y], NULL); + } + pD3DDevice->CreateVertexBuffer(4 * sizeof(D3DLVERTEX2), D3DUSAGE_WRITEONLY, D3DFVF_LVERTEX2, D3DPOOL_DEFAULT, &pIntermediateVB, NULL); + + pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + nImageWidth = 0; nImageHeight = 0; + + dPrevCubicB = dPrevCubicC = -999; + + return 0; +} + +static int dx9Scale(RECT* pRect, int nWidth, int nHeight) +{ + return VidSScaleImage(pRect, nWidth, nHeight, bVidScanRotate); +} + +// Copy BlitFXsMem to pddsBlitFX +static int dx9MemToSurf() +{ + GetClientScreenRect(hVidWnd, &Dest); + + if (nVidFullscreen == 0) { + Dest.top += 0 /*nMenuHeight*/; + } + + if (bVidArcaderes && nVidFullscreen) { + Dest.left = (Dest.right + Dest.left) / 2; + Dest.left -= nGameWidth / 2; + Dest.right = Dest.left + nGameWidth; + + Dest.top = (Dest.top + Dest.bottom) / 2; + Dest.top -= nGameHeight / 2; + Dest.bottom = Dest.top + nGameHeight; + } else { + dx9Scale(&Dest, nGameWidth, nGameHeight); + } + + { + int nNewImageWidth = nRotateGame ? (Dest.bottom - Dest.top) : (Dest.right - Dest.left); + int nNewImageHeight = nRotateGame ? (Dest.right - Dest.left) : (Dest.bottom - Dest.top); + + if (nImageWidth != nNewImageWidth || nImageHeight != nNewImageHeight) { + nImageWidth = nNewImageWidth; + nImageHeight = nNewImageHeight; + dx9GeometryInit(); + } + } + + { + if (dPrevCubicB != dVidCubicB || dPrevCubicC != dVidCubicC) { + dPrevCubicB = dVidCubicB; + dPrevCubicC = dVidCubicC; + FillEffectTexture(); + } + } + + { + // Copy the game image to a surface in video memory + + D3DLOCKED_RECT lr; + + if (FAILED(pSurface->LockRect(&lr, NULL, 0))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't lock surface.\n")); +#endif + return 1; + } + + unsigned char* ps = pVidImage + nVidImageLeft * nVidImageBPP; + unsigned char* pd = (unsigned char*)lr.pBits; + int p = lr.Pitch; + int s = nVidImageWidth * nVidImageBPP; + + for (int y = 0; y < nVidImageHeight; y++, pd += p, ps += nVidImagePitch) { + memcpy(pd, ps, s); + } + + pSurface->UnlockRect(); + } + + { + // Copy the game image onto a texture for rendering + + RECT rect = { 0, 0, nVidImageWidth, nVidImageHeight }; + IDirect3DSurface9* pDest; + + if (FAILED(pTexture->GetSurfaceLevel(0, &pDest))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't get texture surface.\n")); + return 1; +#endif + } + + if (FAILED(pD3DDevice->StretchRect(pSurface, &rect, pDest, &rect, D3DTEXF_NONE))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't copy image.\n")); +#endif + } + + pDest->Release(); + } + +#ifdef ENABLE_PROFILING + { + // Force the D3D pipeline to be flushed + + D3DLVERTEX2* pVertexData; + + if (SUCCEEDED(pIntermediateVB->Lock(0, 4 * sizeof(D3DLVERTEX2), (void**)&pVertexData, 0))) { + pIntermediateVB->Unlock(); + } + + ProfileProfileStart(2); + } +#endif + + pD3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, nVidScanIntensity); + + UINT nTotalPasses, nPass = 0; + pEffect->Begin(&nTotalPasses, D3DXFX_DONOTSAVESTATE); + + if (nTotalPasses > 1) { + IDirect3DSurface9* pPreviousTarget; + IDirect3DSurface9* pNewTarget; + D3DVIEWPORT9 vp; + + pD3DDevice->GetRenderTarget(0, &pPreviousTarget); + pIntermediateTexture->GetSurfaceLevel(0, &pNewTarget); + pD3DDevice->SetRenderTarget(0, pNewTarget); + + vp.X = 0; + vp.Y = 0; + vp.Width = nImageWidth; + vp.Height = nTextureHeight; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + + pD3DDevice->SetViewport(&vp); + + pD3DDevice->BeginScene(); + + pD3DDevice->SetFVF(D3DFVF_LVERTEX2); + + pEffect->BeginPass(nPass); + pEffect->CommitChanges(); + + pD3DDevice->SetStreamSource(0, pIntermediateVB, 0, sizeof(D3DLVERTEX2)); + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + pEffect->EndPass(); + + pD3DDevice->EndScene(); + + pD3DDevice->SetRenderTarget(0, pPreviousTarget); + + RELEASE(pPreviousTarget); + RELEASE(pNewTarget); + + nPass++; + } + +#if 0 + { + // blit the intermediate texture to the screen + + RECT srect = { 0, 0, Dest.right - Dest.left, 256 }; + RECT drect = { 0, nMenuHeight, Dest.right - Dest.left, nMenuHeight + 256 }; + IDirect3DSurface9* pDest; + IDirect3DSurface9* pSrc; + + pD3DDevice->GetRenderTarget(0, &pDest); + pIntermediateTexture->GetSurfaceLevel(0, &pSrc); + + pD3DDevice->StretchRect(pSrc, &srect, pDest, &drect, D3DTEXF_NONE); + + pSrc->Release(); + pDest->Release(); + + pEffect->End(); + + return 0; + } +#endif + +#ifdef ENABLE_PROFILING + { + // Force the D3D pipeline to be flushed + + D3DLVERTEX2* pVertexData; + + if (SUCCEEDED(pIntermediateVB->Lock(0, 4 * sizeof(D3DLVERTEX2), (void**)&pVertexData, 0))) { + pIntermediateVB->Unlock(); + } + + ProfileProfileEnd(2); + } + ProfileProfileStart(0); +#endif + + { + D3DVIEWPORT9 vp; + + // Set the size of the image on the PC screen + if (nVidFullscreen) { + vp.X = Dest.left; + vp.Y = Dest.top; + vp.Width = Dest.right - Dest.left; + vp.Height = Dest.bottom - Dest.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + } else { + vp.X = 0; + vp.Y = 0; + vp.Width = Dest.right - Dest.left; + vp.Height = Dest.bottom - Dest.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + } + + pD3DDevice->SetViewport(&vp); + + pD3DDevice->BeginScene(); + + pD3DDevice->SetFVF(D3DFVF_LVERTEX2); + +// pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + + pEffect->BeginPass(nPass); + pEffect->CommitChanges(); + + for (int y = 0; y < RENDER_STRIPS; y++) { + pD3DDevice->SetStreamSource(0, pVB[y], 0, sizeof(D3DLVERTEX2)); + pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } + pEffect->EndPass(); + + // draw osd text + dx9DrawText(); + + pD3DDevice->EndScene(); + } + + pEffect->End(); + +#ifdef ENABLE_PROFILING + { + // Force the D3D pipeline to be flushed + + D3DLVERTEX2* pVertexData; + + if (SUCCEEDED(pVB[RENDER_STRIPS - 1]->Lock(0, 4 * sizeof(D3DLVERTEX2), (void**)&pVertexData, 0))) { + pVB[RENDER_STRIPS - 1]->Unlock(); + } + + ProfileProfileEnd(0); + } +#endif + + return 0; +} + +// Run one frame and render the screen +static int dx9Frame(bool bRedraw) // bRedraw = 0 +{ + if (pVidImage == NULL) { + return 1; + } + + HRESULT nCoopLevel = pD3DDevice->TestCooperativeLevel(); + if (nCoopLevel != D3D_OK) { // We've lost control of the screen + if (nCoopLevel != D3DERR_DEVICENOTRESET) { + return 1; + } + + if (dx9Reset()) { + return 1; + } + } + +#ifdef ENABLE_PROFILING +// ProfileProfileStart(0); +#endif + + if (bDrvOkay) { + if (bRedraw) { // Redraw current frame + if (BurnDrvRedraw()) { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } else { + BurnDrvFrame(); // Run one frame and draw the screen + } + } + +#ifdef ENABLE_PROFILING +// ProfileProfileEnd(0); + ProfileProfileStart(1); +#endif + + dx9MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting + +#ifdef ENABLE_PROFILING + ProfileProfileEnd(1); + + dprintf(_T(" blit %3.2lf (effect p1 %3.2lf - effect p2 %3.2lf)\n"), ProfileProfileReadAverage(1), ProfileProfileReadAverage(2), ProfileProfileReadAverage(0)); +#endif + + return 0; +} + +// Paint the BlitFX surface onto the primary surface +static int dx9Paint(int bValidate) +{ + if (pD3DDevice->TestCooperativeLevel()) { // We've lost control of the screen + return 1; + } + + RECT rect = { 0, 0, 0, 0 }; + + if (!nVidFullscreen) { + GetClientScreenRect(hVidWnd, &rect); + rect.top += 0 /*nMenuHeight*/; + + dx9Scale(&rect, nGameWidth, nGameHeight); + + if ((rect.right - rect.left) != (Dest.right - Dest.left) || (rect.bottom - rect.top ) != (Dest.bottom - Dest.top)) { + bValidate |= 2; + } + } + + if (bValidate & 2) { + dx9MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting + } + + // Display OSD text message +// VidSDisplayOSD(pddsBlitFX[nUseSys], &rect, 0); + + if (nVidFullscreen) { + pD3DDevice->Present(NULL, NULL, NULL, NULL); + } else { + RECT src = { 0, 0, Dest.right - Dest.left, Dest.bottom - Dest.top }; + + POINT c = { 0, 0 }; + ClientToScreen(hVidWnd, &c); + RECT dst = { rect.left - c.x, rect.top - c.y, rect.right - c.x, rect.bottom - c.y }; + + /* + if (bVidVSync) { + D3DRASTER_STATUS rs; + RECT window; + + GetWindowRect(hVidWnd, &window); + + while (1) { + pD3DDevice->GetRasterStatus(0, &rs); + if (rs.InVBlank || rs.ScanLine >= window.bottom) { + break; + } + Sleep(1); + } + } + */ + + pD3DDevice->Present(&src, &dst, NULL, NULL); + + // Validate the rectangle we just drew + if (bValidate & 1) { + ValidateRect(hVidWnd, &dst); + } + } + + return 0; +} + +// ---------------------------------------------------------------------------- + +static int dx9GetSettings(InterfaceInfo* pInfo) +{ + TCHAR szString[MAX_PATH] = _T(""); + + if (nVidFullscreen) { + if (bVidTripleBuffer) { + IntInfoAddStringModule(pInfo, _T("Using a triple buffer")); + } else { + IntInfoAddStringModule(pInfo, _T("Using a double buffer")); + } + } else { + IntInfoAddStringModule(pInfo, _T("Using D3DSWAPEFFECT_COPY to present the image")); + } + switch (DX9_FILTER) { + case 1: { + IntInfoAddStringModule(pInfo, _T("Applying linear filter")); + break; + } + case 2: { + _sntprintf(szString, MAX_PATH, _T("Applying cubic filter using VS1.1 & %s"), bUsePS14 ? _T("PS1.4") : _T("PS2.0")); + IntInfoAddStringModule(pInfo, szString); + + if (bUsePS14) { + IntInfoAddStringModule(pInfo, _T("Using high-performance implementation")); + break; + } + + if (bVidScanlines) { + switch (DX9_SHADERPRECISION) { + case 0: + case 2: + IntInfoAddStringModule(pInfo, _T("Using reference implementation")); + break; + case 1: + case 3: + IntInfoAddStringModule(pInfo, _T("Using partial precision implementation")); + break; + case 4: + IntInfoAddStringModule(pInfo, _T("Using high-performance implementation")); + break; + } + } else { + switch (DX9_SHADERPRECISION) { + case 0: + IntInfoAddStringModule(pInfo, _T("Using single-pass reference implementation")); + break; + case 1: + IntInfoAddStringModule(pInfo, _T("Using partial precision single-pass implementation")); + break; + case 2: + IntInfoAddStringModule(pInfo, _T("Using full precision multi-pass implementation")); + break; + case 3: + IntInfoAddStringModule(pInfo, _T("Using partial precision multi-pass implementation")); + break; + case 4: + IntInfoAddStringModule(pInfo, _T("Using high-performance multi-pass implementation")); + break; + } + } + if (DX9_USE_FPTEXTURE) { + _sntprintf(szString, MAX_PATH, _T("Using floating-point textures where applicable")); + IntInfoAddStringModule(pInfo, szString); + } + break; + } + default: { + IntInfoAddStringModule(pInfo, _T("Applying point filter")); + } + } + if (bVidScanlines) { + _sntprintf(szString, MAX_PATH, _T("Applying scanlines at %.1lf%% brightness"), (double)(nVidScanIntensity & 255) / 2.55); + IntInfoAddStringModule(pInfo, szString); + } + + return 0; +} + +// The Video Output plugin: +struct VidOut VidOutDX9 = { dx9Init, dx9Exit, dx9Frame, dx9Paint, dx9Scale, dx9GetSettings, _T("DirectX9 Experimental video output") }; +//#else +//struct VidOut VidOutDX9 = { NULL, NULL, NULL, NULL, NULL, NULL, _T("DirectX9 Experimental video output") }; +//#endif + + + + + + + + + + + +// Direct3D9 video output +// rewritten by regret (Motion Blur source from VBA-M) + +struct d3dvertex { + float x, y, z, rhw; //screen coords + float u, v; //texture coords +}; + +struct transp_vertex { + float x, y, z, rhw; + D3DCOLOR color; + float u, v; +}; + +#undef D3DFVF_LVERTEX2 +#define D3DFVF_LVERTEX2 (D3DFVF_XYZRHW | D3DFVF_TEX1) + +IDirect3DTexture9* emuTexture[2]; +static unsigned char mbCurrentTexture = 0; // current texture for motion blur +static bool mbTextureEmpty = true; +static d3dvertex vertex[4]; +static transp_vertex transpVertex[4]; + +D3DFORMAT textureFormat; + +static int nPreScale = 0; +static int nPreScaleZoom = 0; +static int nPreScaleEffect = 0; + +// Select optimal full-screen resolution +static int dx9AltSelectFullscreenMode(VidSDisplayScoreInfo* pScoreInfo) +{ + if (bVidArcaderes) { + if (!VidSGetArcaderes((int*)&(pScoreInfo->nBestWidth), (int*)&(pScoreInfo->nBestHeight))) { + return 1; + } + } else { + pScoreInfo->nBestWidth = nVidWidth; + pScoreInfo->nBestHeight = nVidHeight; + } + + if (!bDrvOkay && (pScoreInfo->nBestWidth < 640 || pScoreInfo->nBestHeight < 480)) { + return 1; + } + + return 0; +} + +static void dx9AltReleaseTexture() +{ + RELEASE(pTexture) + RELEASE(emuTexture[0]) + RELEASE(emuTexture[1]) +} + +static int dx9AltExit() +{ + VidSoftFXExit(); + + dx9AltReleaseTexture(); + + VidSFreeVidImage(); + + RELEASE(pFont) + RELEASE(pD3DDevice) + RELEASE(pD3D) + + nRotateGame = 0; + + VidSKillShortMsg(); + VidSKillOSDMsg(); + + return 0; +} + +static int dx9AltResize(int width, int height) +{ + if (FAILED(pD3DDevice->CreateTexture(width, height, 1, 0, textureFormat, D3DPOOL_SYSTEMMEM, &pTexture, NULL))) { + return 1; + } + + if (!emuTexture[0]) { + if (FAILED(pD3DDevice->CreateTexture(width, height, 1, 0, textureFormat, D3DPOOL_DEFAULT, &emuTexture[0], NULL))) { + return 1; + } + } + + if (!emuTexture[1] && bVidMotionBlur) { + if (FAILED(pD3DDevice->CreateTexture(width, height, 1, 0, textureFormat, D3DPOOL_DEFAULT, &emuTexture[1], NULL))) { + return 1; + } + mbTextureEmpty = true; + } + + return 0; +} + +static int dx9AltTextureInit() +{ + if (nRotateGame & 1) { + nVidImageWidth = nGameHeight; + nVidImageHeight = nGameWidth; + } else { + nVidImageWidth = nGameWidth; + nVidImageHeight = nGameHeight; + } + + nGameImageWidth = nVidImageWidth; + nGameImageHeight = nVidImageHeight; + + nVidImageDepth = nVidScrnDepth; + + // Determine if we should use a texture format different from the screen format + if ((bDrvOkay && VidSoftFXCheckDepth(nPreScaleEffect, 32) != 32) || (bDrvOkay && bVidForce16bit)) { + nVidImageDepth = 16; + } + + switch (nVidImageDepth) { + case 32: + textureFormat = D3DFMT_X8R8G8B8; + break; + case 24: + textureFormat = D3DFMT_R8G8B8; + break; + case 16: + textureFormat = D3DFMT_R5G6B5; + break; + case 15: + textureFormat = D3DFMT_X1R5G5B5; + break; + } + + nVidImageBPP = (nVidImageDepth + 7) >> 3; + nBurnBpp = nVidImageBPP; // Set Burn library Bytes per pixel + + // Use our callback to get colors: + SetBurnHighCol(nVidImageDepth); + + // Make the normal memory buffer + if (VidSAllocVidImage()) { + dx9AltExit(); + return 1; + } + + nTextureWidth = GetTextureSize(nGameImageWidth * nPreScaleZoom); + nTextureHeight = GetTextureSize(nGameImageHeight * nPreScaleZoom); + + if (dx9AltResize(nTextureWidth, nTextureHeight)) { + return 1; + } + + return 0; +} + +// Vertex format: +// +// 0---------1 +// | /| +// | / | +// | / | +// | / | +// |/ | +// 2---------3 +// +// (x,y) screen coords, in pixels +// (u,v) texture coords, betweeen 0.0 (top, left) to 1.0 (bottom, right) +static int dx9AltSetVertex(unsigned int px, unsigned int py, unsigned int pw, unsigned int ph, unsigned int tw, unsigned int th, unsigned int x, unsigned int y, unsigned int w, unsigned int h) +{ + // configure triangles + // -0.5f is necessary in order to match texture alignment to display pixels + float diff = -0.5f; + if (nRotateGame & 1) { + if (nRotateGame & 2) { + vertex[2].x = vertex[3].x = (double)(y ) + diff; + vertex[0].x = vertex[1].x = (double)(y + h) + diff; + vertex[1].y = vertex[3].y = (double)(x + w) + diff; + vertex[0].y = vertex[2].y = (double)(x ) + diff; + } else { + vertex[0].x = vertex[1].x = (double)(y ) + diff; + vertex[2].x = vertex[3].x = (double)(y + h) + diff; + vertex[1].y = vertex[3].y = (double)(x ) + diff; + vertex[0].y = vertex[2].y = (double)(x + w) + diff; + } + } else { + if (nRotateGame & 2) { + vertex[1].x = vertex[3].x = (double)(y ) + diff; + vertex[0].x = vertex[2].x = (double)(y + h) + diff; + vertex[2].y = vertex[3].y = (double)(x ) + diff; + vertex[0].y = vertex[1].y = (double)(x + w) + diff; + } else { + vertex[0].x = vertex[2].x = (double)(x ) + diff; + vertex[1].x = vertex[3].x = (double)(x + w) + diff; + vertex[0].y = vertex[1].y = (double)(y ) + diff; + vertex[2].y = vertex[3].y = (double)(y + h) + diff; + } + } + + double rw = (double)w / (double)pw * (double)tw; + double rh = (double)h / (double)ph * (double)th; + vertex[0].u = vertex[2].u = (double)(px ) / rw; + vertex[1].u = vertex[3].u = (double)(px + w) / rw; + vertex[0].v = vertex[1].v = (double)(py ) / rh; + vertex[2].v = vertex[3].v = (double)(py + h) / rh; + + // Z-buffer and RHW are unused for 2D blit, set to normal values + vertex[0].z = vertex[1].z = vertex[2].z = vertex[3].z = 0.0f; + vertex[0].rhw = vertex[1].rhw = vertex[2].rhw = vertex[3].rhw = 1.0f; + + // configure semi-transparent triangles + if (bVidMotionBlur) { + D3DCOLOR semiTrans = D3DCOLOR_ARGB(0x7F, 0xFF, 0xFF, 0xFF); + transpVertex[0].x = vertex[0].x; + transpVertex[0].y = vertex[0].y; + transpVertex[0].z = vertex[0].z; + transpVertex[0].rhw = vertex[0].rhw; + transpVertex[0].color = semiTrans; + transpVertex[0].u = vertex[0].u; + transpVertex[0].v = vertex[0].v; + transpVertex[1].x = vertex[1].x; + transpVertex[1].y = vertex[1].y; + transpVertex[1].z = vertex[1].z; + transpVertex[1].rhw = vertex[1].rhw; + transpVertex[1].color = semiTrans; + transpVertex[1].u = vertex[1].u; + transpVertex[1].v = vertex[1].v; + transpVertex[2].x = vertex[2].x; + transpVertex[2].y = vertex[2].y; + transpVertex[2].z = vertex[2].z; + transpVertex[2].rhw = vertex[2].rhw; + transpVertex[2].color = semiTrans; + transpVertex[2].u = vertex[2].u; + transpVertex[2].v = vertex[2].v; + transpVertex[3].x = vertex[3].x; + transpVertex[3].y = vertex[3].y; + transpVertex[3].z = vertex[3].z; + transpVertex[3].rhw = vertex[3].rhw; + transpVertex[3].color = semiTrans; + transpVertex[3].u = vertex[3].u; + transpVertex[3].v = vertex[3].v; + } + + return 0; +} + +// ==> osd for dx9 video output (ugly), added by regret +static int dx9AltCreateFont() +{ + if (pFont) { + return 0; + } + + HRESULT hr = _D3DXCreateFont(pD3DDevice, d3dpp.BackBufferHeight / 40, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH || FF_DONTCARE, _T("Arial"), &pFont); + + if (FAILED(hr)) { + return 1; + } + + return 0; +} + +static void dx9AltDrawText() +{ + if (!nOSDTimer) { + return; + } + + if (nFramesEmulated > nOSDTimer) { + VidSKillShortMsg(); + VidSKillOSDMsg(); + } + + RECT osdRect; + if (nVidFullscreen) { + osdRect.left = Dest.left; + osdRect.top = Dest.top; + osdRect.right = Dest.right - 1; + osdRect.bottom = Dest.bottom - 1; + } else { + osdRect.left = 0; + osdRect.top = 0; + osdRect.right = Dest.right - Dest.left - 1; + osdRect.bottom = Dest.bottom - Dest.top - 1; + } + + if (nOSDTimer) { + pFont->DrawText(NULL, OSDMsg, -1, &osdRect, DT_RIGHT | DT_TOP, osdColor); + } +} +// <== osd for dx9 video output (ugly) + +static int dx9AltInit() +{ + if (hScrnWnd == NULL) { + return 1; + } + + hVidWnd = hScrnWnd; + + // Get pointer to Direct3D + if ((pD3D = _Direct3DCreate9(D3D_SDK_VERSION)) == NULL) { + dx9AltExit(); + return 1; + } + + // check selected atapter + D3DDISPLAYMODE dm; + pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm); + + memset(&d3dpp, 0, sizeof(d3dpp)); + if (nVidFullscreen) { + VidSDisplayScoreInfo ScoreInfo; + memset(&ScoreInfo, 0, sizeof(VidSDisplayScoreInfo)); + + if (dx9AltSelectFullscreenMode(&ScoreInfo)) { + dx9AltExit(); + return 1; + } + + bool sizefit = true; + if (ScoreInfo.nBestWidth > dm.Width || ScoreInfo.nBestHeight > dm.Height) { + sizefit = false; + } + + d3dpp.BackBufferWidth = sizefit ? ScoreInfo.nBestWidth : dm.Width; + d3dpp.BackBufferHeight = sizefit ? ScoreInfo.nBestHeight : dm.Height; + d3dpp.BackBufferFormat = (nVidDepth == 16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8; + d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP; + d3dpp.BackBufferCount = bVidTripleBuffer ? 2 : 1; + d3dpp.hDeviceWindow = hVidWnd; + d3dpp.FullScreen_RefreshRateInHz = dm.RefreshRate; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } else { + d3dpp.BackBufferWidth = dm.Width; + d3dpp.BackBufferHeight = dm.Height; + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferCount = 1; + d3dpp.hDeviceWindow = hVidWnd; + d3dpp.Windowed = TRUE; + d3dpp.PresentationInterval = bVidVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + } + + DWORD dwBehaviorFlags = D3DCREATE_FPU_PRESERVE; + if (bVidHardwareVertex) { + dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; + } else { + dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; + } + + if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hVidWnd, dwBehaviorFlags, &d3dpp, &pD3DDevice))) { + if (nVidFullscreen) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_PROBLEM), d3dpp.BackBufferWidth, d3dpp.BackBufferHeight, d3dpp.BackBufferFormat, d3dpp.FullScreen_RefreshRateInHz); + if (bVidArcaderes && (d3dpp.BackBufferWidth != 320 && d3dpp.BackBufferHeight != 240)) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_CUSTRES)); + } + FBAPopupDisplay(PUF_TYPE_ERROR); + } + + dx9AltExit(); + return 1; + } + + { + nVidScrnWidth = dm.Width; nVidScrnHeight = dm.Height; + nVidScrnDepth = (dm.Format == D3DFMT_R5G6B5) ? 16 : 32; + } + + nGameWidth = nVidImageWidth; + nGameHeight = nVidImageHeight; + nRotateGame = 0; + + if (bDrvOkay) { + // Get the game screen size + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (nVidRotationAdjust & 1) { + int n = nGameWidth; + nGameWidth = nGameHeight; + nGameHeight = n; + nRotateGame |= (nVidRotationAdjust & 2); + } else { + nRotateGame |= 1; + } + } + + if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + nRotateGame ^= 2; + } + } + + // enable vertex alpha blending + if (bVidMotionBlur) { + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + } else { + mbCurrentTexture = 0; + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); + pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + // apply vertex alpha values to texture + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + + // for filter + nPreScale = 3; + nPreScaleZoom = 2; + nPreScaleEffect = 0; + if (bDrvOkay) { + nPreScaleEffect = nVidBlitterOpt[nVidSelect] & 0xFF; + nPreScaleZoom = VidSoftFXGetZoom(nPreScaleEffect); + } + + // Initialize the buffer surfaces + if (dx9AltTextureInit()) { + dx9AltExit(); + return 1; + } + + if (nPreScaleEffect) { + if (VidSoftFXInit(nPreScaleEffect, 0)) { + dx9AltExit(); + return 1; + } + } + + pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, bVidDX9Bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT); + pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, bVidDX9Bilinear ? D3DTEXF_LINEAR : D3DTEXF_POINT); + + nImageWidth = 0; nImageHeight = 0; + + // Clear the swapchain's buffers + if (nVidFullscreen) { + for (int i = 0; i < 3; i++) { + pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + pD3DDevice->Present(NULL, NULL, NULL, NULL); + } + } else { + RECT rect; + GetClientScreenRect(hVidWnd, &rect); + + pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + pD3DDevice->Present(&rect, &rect, NULL, NULL); + } + + // Create osd font + dx9AltCreateFont(); + + return 0; +} + +static int dx9AltReset() +{ + if (pFont) { + pFont->OnLostDevice(); + } + + dx9AltReleaseTexture(); + + if (FAILED(pD3DDevice->Reset(&d3dpp))) { + return 1; + } + + if (pFont) { + pFont->OnResetDevice(); + } + + if (bVidMotionBlur) { + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + } else { + mbCurrentTexture = 0; + pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); + pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + // apply vertex alpha values to texture + pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + + dx9AltTextureInit(); + + nImageWidth = 0; nImageHeight = 0; + + return 0; +} + +static int dx9AltScale(RECT* rect, int width, int height) +{ + if (nVidBlitterOpt[nVidSelect] & 0x0100) { + return VidSoftFXScale(rect, width, height); + } + return VidSScaleImage(rect, width, height, bVidScanRotate); +} + +static void VidSCpyImg32(unsigned char* dst, unsigned int dstPitch, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height) +{ + // fast, iterative C version + // copies an width*height array of visible pixels from src to dst + // srcPitch and dstPitch are the number of garbage bytes after a scanline + register unsigned short lineSize = width << 2; + + while (height--) { + memcpy(dst, src, lineSize); + src += srcPitch; + dst += dstPitch; + } +} + +static void VidSCpyImg16(unsigned char* dst, unsigned int dstPitch, unsigned char *src, unsigned int srcPitch, unsigned short width, unsigned short height) +{ + register unsigned short lineSize = width << 1; + + while (height--) { + memcpy(dst, src, lineSize); + src += srcPitch; + dst += dstPitch; + } +} + +// Copy BlitFXsMem to pddsBlitFX +static int dx9AltRender() +{ + GetClientScreenRect(hVidWnd, &Dest); + + if (bVidArcaderes && nVidFullscreen) { + Dest.left = (Dest.right + Dest.left) / 2; + Dest.left -= nGameWidth / 2; + Dest.right = Dest.left + nGameWidth; + + Dest.top = (Dest.top + Dest.bottom) / 2; + Dest.top -= nGameHeight / 2; + Dest.bottom = Dest.top + nGameHeight; + } else { + dx9AltScale(&Dest, nGameWidth, nGameHeight); + } + + { + int nNewImageWidth = nRotateGame ? (Dest.bottom - Dest.top) : (Dest.right - Dest.left); + int nNewImageHeight = nRotateGame ? (Dest.right - Dest.left) : (Dest.bottom - Dest.top); + + if (nImageWidth != nNewImageWidth || nImageHeight != nNewImageHeight) { + nImageWidth = nNewImageWidth; + nImageHeight = nNewImageHeight; + + int nWidth = nGameImageWidth; + int nHeight = nGameImageHeight; + + if (nPreScaleEffect) { + if (nPreScale & 1) { + nWidth *= nPreScaleZoom; + } + if (nPreScale & 2) { + nHeight *= nPreScaleZoom; + } + } + + if (nVidFullscreen) { + dx9AltSetVertex(0, 0, nWidth, nHeight, nTextureWidth, nTextureHeight, nRotateGame ? Dest.top : Dest.left, nRotateGame ? Dest.left : Dest.top, nImageWidth, nImageHeight); + } else { + dx9AltSetVertex(0, 0, nWidth, nHeight, nTextureWidth, nTextureHeight, 0, 0, nImageWidth, nImageHeight); + } + + D3DVIEWPORT9 vp; + + // Set the size of the image on the PC screen + if (nVidFullscreen) { + vp.X = Dest.left; + vp.Y = Dest.top; + vp.Width = Dest.right - Dest.left; + vp.Height = Dest.bottom - Dest.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + } else { + vp.X = 0; + vp.Y = 0; + vp.Width = Dest.right - Dest.left; + vp.Height = Dest.bottom - Dest.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + } + + pD3DDevice->SetViewport(&vp); + } + } + + pD3DDevice->BeginScene(); + + { + // Copy the game image onto a texture for rendering + D3DLOCKED_RECT d3dlr; + pTexture->LockRect(0, &d3dlr, 0, 0); + + int pitch = d3dlr.Pitch; + unsigned char* pd = (unsigned char*)d3dlr.pBits; + + if (nPreScaleEffect) { + VidFilterApplyEffect(pd, pitch); + } else { + unsigned char* ps = pVidImage + nVidImageLeft * nVidImageBPP; + int s = nVidImageWidth * nVidImageBPP; + + switch (nVidImageDepth) { + case 32: + VidSCpyImg32(pd, pitch, ps, s, nVidImageWidth, nVidImageHeight); + break; + case 16: + VidSCpyImg16(pd, pitch, ps, s, nVidImageWidth, nVidImageHeight); + break; + } + } + + pTexture->UnlockRect(0); + } + + pD3DDevice->UpdateTexture(pTexture, emuTexture[mbCurrentTexture]); + + if (bVidMotionBlur) { + // Motion Blur enabled + if (!mbTextureEmpty) { + // draw previous frame to the screen + pD3DDevice->SetTexture( 0, emuTexture[mbCurrentTexture ^ 1]); + pD3DDevice->SetFVF(D3DFVF_LVERTEX2); + pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex, sizeof(d3dvertex)); + // draw the current frame with transparency to the screen + pD3DDevice->SetTexture(0, emuTexture[mbCurrentTexture]); + pD3DDevice->SetFVF(D3DFVF_LVERTEX2 | D3DFVF_DIFFUSE); + pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, transpVertex, sizeof(transp_vertex)); + } else { + mbTextureEmpty = false; + // draw the current frame to the screen + pD3DDevice->SetTexture(0, emuTexture[ mbCurrentTexture]); + pD3DDevice->SetFVF(D3DFVF_LVERTEX2); + pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex, sizeof(d3dvertex)); + } + mbCurrentTexture ^= 1; // switch current texture + } else { + // draw the current frame to the screen + pD3DDevice->SetTexture( 0, emuTexture[mbCurrentTexture] ); + pD3DDevice->SetFVF(D3DFVF_LVERTEX2); + pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertex, sizeof(d3dvertex)); + } + + // draw osd text + dx9AltDrawText(); + + pD3DDevice->EndScene(); + + return 0; +} + +// Run one frame and render the screen +static int dx9AltFrame(bool bRedraw) // bRedraw = 0 +{ + if (pVidImage == NULL) { + return 1; + } + + HRESULT nCoopLevel = pD3DDevice->TestCooperativeLevel(); + if (nCoopLevel != D3D_OK) { // We've lost control of the screen + if (nCoopLevel != D3DERR_DEVICENOTRESET) { + return 1; + } + + if (dx9AltReset()) { + return 1; + } + } + + if (bDrvOkay) { + if (bRedraw) { // Redraw current frame + if (BurnDrvRedraw()) { + BurnDrvFrame(); // No redraw function provided, advance one frame + } + } else { + BurnDrvFrame(); // Run one frame and draw the screen + } + } + + dx9AltRender(); + + return 0; +} + +// Paint the BlitFX surface onto the primary surface +static int dx9AltPaint(int bValidate) +{ + if (pD3DDevice->TestCooperativeLevel()) { // We've lost control of the screen + return 1; + } + + RECT rect = { 0, 0, 0, 0 }; + + if (!nVidFullscreen) { + GetClientScreenRect(hVidWnd, &rect); + rect.top += nMenuHeight; + + dx9AltScale(&rect, nGameWidth, nGameHeight); + + if ((rect.right - rect.left) != (Dest.right - Dest.left) || (rect.bottom - rect.top ) != (Dest.bottom - Dest.top)) { + bValidate |= 2; + } + } + + if (bValidate & 2) { + dx9AltRender(); + } + + if (nVidFullscreen) { + pD3DDevice->Present(NULL, NULL, NULL, NULL); + } else { + RECT src = { 0, 0, Dest.right - Dest.left, Dest.bottom - Dest.top }; + POINT c = { 0, 0 }; + ClientToScreen(hVidWnd, &c); + RECT dst = { rect.left - c.x, rect.top - c.y, rect.right - c.x, rect.bottom - c.y }; + + pD3DDevice->Present(&src, &dst, NULL, NULL); + + // Validate the rectangle we just drew + if (bValidate & 1) { + ValidateRect(hVidWnd, &dst); + } + } + + return 0; +} + +static int dx9AltGetSettings(InterfaceInfo* pInfo) +{ + if (nVidFullscreen) { + if (bVidTripleBuffer) { + IntInfoAddStringModule(pInfo, _T("Using a triple buffer")); + } else { + IntInfoAddStringModule(pInfo, _T("Using a double buffer")); + } + } + + if (bDrvOkay) { + TCHAR szString[MAX_PATH] = _T(""); + + _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%ix zoom)"), VidSoftFXGetEffect(nPreScaleEffect), nPreScaleZoom); + IntInfoAddStringModule(pInfo, szString); + } + + if (bVidDX9Bilinear) { + IntInfoAddStringModule(pInfo, _T("Applying linear filter")); + } else { + IntInfoAddStringModule(pInfo, _T("Applying point filter")); + } + + if (bVidMotionBlur) { + IntInfoAddStringModule(pInfo, _T("Applying motion blur effect")); + } + + return 0; +} + +// The Video Output plugin: +struct VidOut VidOutDX9Alt = { dx9AltInit, dx9AltExit, dx9AltFrame, dx9AltPaint, dx9AltScale, dx9AltGetSettings, _T("DirectX9 Alternate video output") }; + + + + + + diff --git a/src/interface/win32/vid_directx_support.cpp b/src/interface/win32/vid_directx_support.cpp new file mode 100644 index 00000000..5fce9fb1 --- /dev/null +++ b/src/interface/win32/vid_directx_support.cpp @@ -0,0 +1,1689 @@ +// Support functions for blitters that use DirectX +#include "burner.h" + +#if !defined BUILD_X64_EXE + #include "vid_directx_support.h" +#endif + +#include +#define DIRECT3D_VERSION 0x0700 // Use this Direct3D version + +#if defined BUILD_X64_EXE + #include "vid_directx_support.h" +#endif + +#include "ddraw_core.h" + +// --------------------------------------------------------------------------- +// General + +static IDirectDraw7* pDD = NULL; + +void VidSExit() +{ + pDD = NULL; +} + +int VidSInit(IDirectDraw7* pDD7) +{ + pDD = pDD7; + + if (pDD == NULL) { + return 1; + } + + return 0; +} + +// --------------------------------------------------------------------------- + +// Get bit-depth of a surface (15/16/24/32) + +int VidSGetSurfaceDepth(IDirectDrawSurface7* pSurf) +{ + DDPIXELFORMAT ddpf; + if (pSurf == NULL) { + return 0; + } + + // Find out the pixelformat of the screen surface + memset(&ddpf, 0, sizeof(ddpf)); + ddpf.dwSize = sizeof(ddpf); + + if (SUCCEEDED(pSurf->GetPixelFormat(&ddpf))) { + int nDepth = ddpf.dwRGBBitCount; + if (nDepth == 16 && ddpf.dwGBitMask == 0x03E0) { + nDepth = 15; + } + + return nDepth; + } + + return 0; +} + +// Clear a surface to a specified colour + +int VidSClearSurface(IDirectDrawSurface7* pSurf, unsigned int nColour, RECT* pRect) +{ + DDBLTFX BltFx; + + if (pSurf == NULL) { + return 1; + } + + memset(&BltFx, 0, sizeof(BltFx)); + BltFx.dwSize = sizeof(BltFx); + BltFx.dwFillColor = nColour; + + if (FAILED(pSurf->Blt(NULL, NULL, pRect, DDBLT_COLORFILL, &BltFx))) { + return 1; + } else { + return 0; + } +} + +// Clipper + +int VidSClipperInit(IDirectDrawSurface7* pSurf) +{ + if (nVidFullscreen && bDrvOkay) { + return 0; + } + + IDirectDrawClipper *pClipper = NULL; + + if (SUCCEEDED(_DirectDrawCreateClipper(0, &pClipper, NULL))) { + if (SUCCEEDED(pClipper->SetHWnd(0, hVidWnd))) { + pSurf->SetClipper(pClipper); + RELEASE(pClipper); + + return 0; + } + } + + return 1; +} + +// --------------------------------------------------------------------------- +// Gamma controls + +static IDirectDrawGammaControl* pGammaControl; +static DDGAMMARAMP* pFBAGamma = NULL; +static DDGAMMARAMP* pSysGamma = NULL; + +void VidSRestoreGamma() +{ + if (pGammaControl) { + if (pSysGamma) { + pGammaControl->SetGammaRamp(0, pSysGamma); + } + + if (pSysGamma) { + free(pSysGamma); + pSysGamma = NULL; + } + if (pFBAGamma) { + free(pFBAGamma); + pFBAGamma = NULL; + } + + RELEASE(pGammaControl); + } +} + +int VidSUpdateGamma() +{ + if (pGammaControl) { + if (bDoGamma) { + for (int i = 0; i < 256; i++) { + int nValue = (int)(65535.0 * pow((i / 255.0), nGamma)); + pFBAGamma->red[i] = nValue; + pFBAGamma->green[i] = nValue; + pFBAGamma->blue[i] = nValue; + } + pGammaControl->SetGammaRamp(0, pFBAGamma); + } else { + pGammaControl->SetGammaRamp(0, pSysGamma); + } + } + + return 0; +} + +int VidSSetupGamma(IDirectDrawSurface7* pSurf) +{ + pGammaControl = NULL; + + if (!bVidUseHardwareGamma || !nVidFullscreen) { + return 0; + } + + if (FAILED(pSurf->QueryInterface(IID_IDirectDrawGammaControl, (void**)&pGammaControl))) { + pGammaControl = NULL; +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Warning: Couldn't use hardware gamma controls.\n")); +#endif + + return 1; + } + + pSysGamma = (DDGAMMARAMP*)malloc(sizeof(DDGAMMARAMP)); + if (pSysGamma == NULL) { + VidSRestoreGamma(); + return 1; + } + pGammaControl->GetGammaRamp(0, pSysGamma); + + pFBAGamma = (DDGAMMARAMP*)malloc(sizeof(DDGAMMARAMP)); + if (pFBAGamma == NULL) { + VidSRestoreGamma(); + return 1; + } + + VidSUpdateGamma(); + + return 0; +} + +// --------------------------------------------------------------------------- +// Fullscreen mode support routines + +int VidSScoreDisplayMode(VidSDisplayScoreInfo* pScoreInfo) +{ + // Continue if the resolution is too low + if (pScoreInfo->nModeWidth < pScoreInfo->nRequestedWidth || pScoreInfo->nModeHeight < pScoreInfo->nRequestedHeight) { + return 0; + } + + // Only test standard resolutions if below 512 x 384 + if ((pScoreInfo->nModeWidth == 320 && pScoreInfo->nModeHeight == 240) || (pScoreInfo->nModeWidth == 400 && pScoreInfo->nModeHeight == 300) || (pScoreInfo->nModeWidth >= 512 && pScoreInfo->nModeHeight >= 384)) { + + if (pScoreInfo->nRequestedWidth == 0 || pScoreInfo->nRequestedHeight == 0) { + RECT rect = {0, 0, 0, 0}; + int nGameWidth = nVidImageWidth, nGameHeight = nVidImageHeight; + unsigned int nScore; + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) && (nVidRotationAdjust & 1)) { + BurnDrvGetVisibleSize(&nGameHeight, &nGameWidth); + } else { + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + } + } + + nVidScrnWidth = rect.right = pScoreInfo->nModeWidth; + nVidScrnHeight = rect.bottom = pScoreInfo->nModeHeight; + VidImageSize(&rect, nGameWidth, nGameHeight); + + // Continue if the resolution is too low + if (!bDrvOkay) { + if ((unsigned int)(rect.bottom - rect.top) < pScoreInfo->nRequestedHeight) { + return 0; + } + } else { + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if ((unsigned int)(rect.right - rect.left) < pScoreInfo->nRequestedWidth) { + return 0; + } + } else { + if ((unsigned int)(rect.bottom - rect.top) < pScoreInfo->nRequestedHeight) { + return 0; + } + } + } + + // Score resolutions based on how many pixels are unused and the pixel aspect + nScore = 65536 * (pScoreInfo->nModeWidth - (unsigned)(rect.right - rect.left)) + (pScoreInfo->nModeHeight - (unsigned)(rect.bottom - rect.top)); + nScore = (int)((double)nScore * ((double)pScoreInfo->nModeWidth * nVidScrnAspectY / pScoreInfo->nModeHeight / nVidScrnAspectX)); + if (nScore < pScoreInfo->nBestScore) { + pScoreInfo->nBestScore = nScore; + pScoreInfo->nBestWidth = pScoreInfo->nModeWidth; + pScoreInfo->nBestHeight = pScoreInfo->nModeHeight; + } + } else { + // Select the lowest resolution that will fit the image + if (pScoreInfo->nModeWidth < pScoreInfo->nBestWidth && pScoreInfo->nModeHeight < pScoreInfo->nBestHeight) { + pScoreInfo->nBestWidth = pScoreInfo->nModeWidth; + pScoreInfo->nBestHeight = pScoreInfo->nModeHeight; + } + } + } + + return 0; +} + +int VidSInitScoreInfo(VidSDisplayScoreInfo* pScoreInfo) +{ + int nGameWidth = nVidImageWidth, nGameHeight = nVidImageHeight; + int nGameAspectX = 4, nGameAspectY = 3; + + pScoreInfo->nBestWidth = -1U; + pScoreInfo->nBestHeight = -1U; + pScoreInfo->nBestScore = -1U; + + if (pScoreInfo->nRequestedZoom == 0) { + return 0; + } + + pScoreInfo->nRequestedWidth = 0; + pScoreInfo->nRequestedHeight = 0; + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) && (nVidRotationAdjust & 1)) { + BurnDrvGetVisibleSize(&nGameHeight, &nGameWidth); + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + } + + if (!bVidCorrectAspect || bVidFullStretch || (nVidSelect == 1 && (nVidBlitterOpt[1] & 0x07000000) == 0x07000000) || (nVidSelect == 2 && nVidBlitterOpt[2] & 0x00000100)) { + pScoreInfo->nRequestedWidth = nGameWidth * pScoreInfo->nRequestedZoom; + pScoreInfo->nRequestedHeight = nGameHeight * pScoreInfo->nRequestedZoom; + } else { + if (bDrvOkay) { + if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + pScoreInfo->nRequestedWidth = nGameWidth * pScoreInfo->nRequestedZoom; + } else { + pScoreInfo->nRequestedHeight = nGameHeight * pScoreInfo->nRequestedZoom; + } + } + } + + return 0; +} + +static HRESULT WINAPI myEnumModesCallback(LPDDSURFACEDESC2 pSurfaceDesc, void* lpContext) +{ + ((VidSDisplayScoreInfo*)lpContext)->nModeWidth = pSurfaceDesc->dwWidth; + ((VidSDisplayScoreInfo*)lpContext)->nModeHeight = pSurfaceDesc->dwHeight; + + VidSScoreDisplayMode((VidSDisplayScoreInfo*)lpContext); + + return DDENUMRET_OK; +} + +void VidSRestoreScreenMode() +{ + if (pDD == NULL) { + return; + } + + // Undo the changes we made to the display + pDD->SetCooperativeLevel(NULL, DDSCL_NORMAL); + + nVidScrnWidth = 0; + nVidScrnHeight = 0; + + return; +} + +// Enter fullscreen mode, select optimal full-screen resolution +int VidSEnterFullscreenMode(int nZoom, int nDepth) +{ + int nWidth, nHeight; + + if (pDD == NULL) { + return 1; + } + + if (nDepth == 0) { + nDepth = nVidDepth; + } + if (nDepth == 15) { + nDepth = 16; + } + + if (FAILED(pDD->SetCooperativeLevel(hVidWnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))) { + return 1; + } + + if (bVidArcaderes) { + if (!VidSGetArcaderes(&nWidth, &nHeight)) { + return 1; + } + } else { + if (nZoom) { + DDSURFACEDESC2 ddsd; + VidSDisplayScoreInfo ScoreInfo; + + memset(&ScoreInfo, 0, sizeof(VidSDisplayScoreInfo)); + ScoreInfo.nRequestedZoom = nZoom; + VidSInitScoreInfo(&ScoreInfo); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_PIXELFORMAT; + + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = nDepth; + + pDD->EnumDisplayModes(0, &ddsd, (void*)&ScoreInfo, myEnumModesCallback); + + if (ScoreInfo.nBestWidth == -1U) { + + VidSRestoreScreenMode(); + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_NOMODE)); + FBAPopupDisplay(PUF_TYPE_ERROR); + + return 1; + } + + nWidth = ScoreInfo.nBestWidth; + nHeight = ScoreInfo.nBestHeight; + } else { + nWidth = nVidWidth; + nHeight = nVidHeight; + } + } + + if (!bDrvOkay && (nWidth < 640 || nHeight < 480)) { + return 1; + } + + if (FAILED(pDD->SetDisplayMode(nWidth, nHeight, nDepth, nVidRefresh, 0))) { + VidSRestoreScreenMode(); + + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_PROBLEM)); + if (bVidArcaderes && (nWidth != 320 && nHeight != 240)) { + FBAPopupAddText(PUF_TEXT_DEFAULT, MAKEINTRESOURCE(IDS_ERR_UI_FULL_CUSTRES)); + } + FBAPopupDisplay(PUF_TYPE_ERROR); + + nVidScrnWidth = 0; + nVidScrnHeight = 0; + + return 1; + } + + nVidScrnWidth = nWidth; + nVidScrnHeight = nHeight; + + return 0; +} + +// --------------------------------------------------------------------------- + +// Compute the resolution needed to run a game without scaling and filling the screen +// (taking into account the aspect ratios of the game and monitor) +bool VidSGetArcaderes(int* pWidth, int* pHeight) +{ + int nGameWidth, nGameHeight; + int nGameAspectX, nGameAspectY; + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) && (nVidRotationAdjust & 1)) { + BurnDrvGetVisibleSize(&nGameHeight, &nGameWidth); + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight); + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + + double dMonAspect = (double)nVidScrnAspectX / nVidScrnAspectY; + double dGameAspect = (double)nGameAspectX / nGameAspectY; + + if (dMonAspect > dGameAspect) { + *pWidth = nGameHeight * nGameAspectY * nGameWidth * nVidScrnAspectX / (nGameHeight * nGameAspectX * nVidScrnAspectY); + *pHeight = nGameHeight; + } else { + *pWidth = nGameWidth; + *pHeight = nGameWidth * nGameAspectX * nGameHeight * nVidScrnAspectY / (nGameWidth * nGameAspectY * nVidScrnAspectX); + } + + // Horizontal resolution must be a multiple of 8 + if (*pWidth - nGameWidth < 8) { + *pWidth = (*pWidth + 7) & ~7; + } else { + *pWidth = (*pWidth + 4) & ~7; + } + } else { + return false; + } + + return true; +} + +// This function takes a rectangle and scales it to either: +// - The largest possible multiple of both X and Y; +// - The largest possible multiple of Y, modifying X to ensure the correct aspect ratio; +// - The window size +int VidSScaleImage(RECT* pRect, int nGameWidth, int nGameHeight, bool bVertScanlines) +{ + int xm, ym; // The multiple of nScrnWidth and nScrnHeight we can fit in + int nScrnWidth, nScrnHeight; + + int nGameAspectX = 4, nGameAspectY = 3; + int nWidth = pRect->right - pRect->left; + int nHeight = pRect->bottom - pRect->top; + + if (bVidFullStretch) { // Arbitrary stretch + return 0; + } + + if (bDrvOkay) { + if ((BurnDrvGetFlags() & (BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED)) && (nVidRotationAdjust & 1)) { + BurnDrvGetAspect(&nGameAspectY, &nGameAspectX); + } else { + BurnDrvGetAspect(&nGameAspectX, &nGameAspectY); + } + } + + xm = nWidth / nGameWidth; + ym = nHeight / nGameHeight; + + if (nVidFullscreen) { + nScrnWidth = nVidScrnWidth; + nScrnHeight = nVidScrnHeight; + } else { + nScrnWidth = SystemWorkArea.right - SystemWorkArea.left; + nScrnHeight = SystemWorkArea.bottom - SystemWorkArea.top; + } + + if (bVidCorrectAspect && bVidScanlines && ((ym >= 2 && xm) || (ym && xm >= 2 && bVertScanlines))) { // Correct aspect ratio with scanlines + int nWidthScratch, nHeightScratch; + if (nGameWidth < nGameHeight && bVertScanlines) { + int xmScratch = xm; + do { + nWidthScratch = nGameWidth * xmScratch; + nHeightScratch = nWidthScratch * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX); + xmScratch--; + } while (nHeightScratch > nHeight && xmScratch >= 2); + if (nHeightScratch > nHeight) { // The image is too high + if (nGameWidth < nGameHeight) { // Vertical games + nWidth = nHeight * nVidScrnAspectX * nGameAspectX * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectY); + } else { // Horizontal games + nWidth = nHeight * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY); + } + } else { + nWidth = nWidthScratch; + nHeight = nHeightScratch; + } + } else { + int ymScratch = ym; + do { + nHeightScratch = nGameHeight * ymScratch; + nWidthScratch = nHeightScratch * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY); + ymScratch--; + } while (nWidthScratch > nWidth && ymScratch >= 2); + if (nWidthScratch > nWidth) { // The image is too wide + if (nGameWidth < nGameHeight) { // Vertical games + nHeight = nWidth * nVidScrnAspectY * nGameAspectY * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectX); + } else { // Horizontal games + nHeight = nWidth * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX); + } + } else { + nWidth = nWidthScratch; + nHeight = nHeightScratch; + } + } + } else { + if (bVidCorrectAspect) { // Correct aspect ratio + int nWidthScratch; + nWidthScratch = nHeight * nVidScrnAspectY * nGameAspectX * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectY); + if (nWidthScratch > nWidth) { // The image is too wide + if (nGameWidth < nGameHeight) { // Vertical games + nHeight = nWidth * nVidScrnAspectY * nGameAspectY * nScrnWidth / (nScrnHeight * nVidScrnAspectX * nGameAspectX); + } else { // Horizontal games + nHeight = nWidth * nVidScrnAspectX * nGameAspectY * nScrnHeight / (nScrnWidth * nVidScrnAspectY * nGameAspectX); + } + } else { + nWidth = nWidthScratch; + } + } else { + if (xm && ym) { // Don't correct aspect ratio + if (xm > ym) { + xm = ym; + } else { + ym = xm; + } + nWidth = nGameWidth * xm; + nHeight = nGameHeight * ym; + } else { + if (xm) { + nWidth = nGameWidth * xm * nHeight / nGameHeight; + } else { + if (ym) { + nHeight = nGameHeight * ym * nWidth / nGameWidth; + } + } + } + } + } + + pRect->left = (pRect->right + pRect->left) / 2; + pRect->left -= nWidth / 2; + pRect->right = pRect->left + nWidth; + + pRect->top = (pRect->top + pRect->bottom) / 2; + pRect->top -= nHeight / 2; + pRect->bottom = pRect->top + nHeight; + + return 0; +} + +// --------------------------------------------------------------------------- +// Text display routines + +static struct { TCHAR pMsgText[32]; COLORREF nColour; int nPriority; unsigned int nTimer; } VidSShortMsg = { _T(""), 0, 0, 0,}; +static HFONT ShortMsgFont = NULL; + +static unsigned char nStatusSymbols[4] = {0x3B, 0xC2, 0x3D, 0x34}; //"pause", "record", "kaillera" and "play" in font Webdings, respectivelly +static HFONT StatusFont = NULL; + +#define CHAT_SIZE 11 + +static struct { TCHAR* pIDText; COLORREF nIDColour; TCHAR* pMainText; COLORREF nMainColour; } VidSChatMessage[CHAT_SIZE]; +static bool bChatInitialised = false; + +static HFONT ChatIDFont = NULL; +static HFONT ChatMainFont = NULL; +static unsigned int nChatTimer; +static int nChatFontSize; +static int nChatShadowOffset; +static int nChatOverFlow; +static bool bDrawChat; + +static HFONT EditTextFont = NULL; +static HFONT EditCursorFont = NULL; +static DWORD nPrevStart, nPrevEnd; +static int nCursorTime; +static int nCursorState = 0; +static int nEditSize; +static int nEditShadowOffset; + +static struct { TCHAR pMsgText[64]; COLORREF nColour; int nPriority; unsigned int nTimer; } VidSTinyMsg = {_T(""), 0, 0, 0}; +static HFONT TinyMsgFont = NULL; + +static IDirectDrawSurface7* pShortMsgSurf = NULL; +static IDirectDrawSurface7* pStatusSurf = NULL; +static IDirectDrawSurface7* pChatSurf = NULL; +static IDirectDrawSurface7* pEditSurf = NULL; +static IDirectDrawSurface7* pTinyMsgSurf = NULL; + +static unsigned int nKeyColour = 0x000001; + +static int nStatus = 0; +static int nPrevStatus = -1; + +int nVidSDisplayStatus = 1; // 1 = display pause/record/replay/kaillera icons in the upper right corner of the display + +int nMaxChatFontSize = 36; // Maximum size of the font used for the Kaillera chat function (1280x960 or higher) +int nMinChatFontSize = 12; // Minimum size of the font used for the Kaillera chat function (arcade resolution) + +static int nZoom; // & 1: zoom X, & 2: zoom Y + +static int nShortMsgFlags; +static int nStatusFlags; + +bool bEditActive = false; +bool bEditTextChanged = false; +TCHAR EditText[MAX_CHAT_SIZE + 1] = _T(""); + +TCHAR OSDMsg[MAX_PATH] = _T(""); +unsigned int nOSDTimer = 0; + +static BOOL MyTextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString, int nShadowOffset, int nColour) +{ + // Print a black shadow + SetTextColor(hdc, 0); + if (nShadowOffset >= 2) { + TextOut(hdc, nXStart + nShadowOffset, nYStart + nShadowOffset, lpString, cbString); + } + // Print a black outline + TextOut(hdc, nXStart - 1, nYStart - 1, lpString, cbString); + TextOut(hdc, nXStart + 0, nYStart - 1, lpString, cbString); + TextOut(hdc, nXStart + 1, nYStart - 1, lpString, cbString); + TextOut(hdc, nXStart + 1, nYStart + 0, lpString, cbString); + TextOut(hdc, nXStart + 1, nYStart + 1, lpString, cbString); + TextOut(hdc, nXStart + 0, nYStart + 1, lpString, cbString); + TextOut(hdc, nXStart - 1, nYStart + 1, lpString, cbString); + TextOut(hdc, nXStart - 1, nYStart + 0, lpString, cbString); + // Print the text on top + SetTextColor(hdc, nColour); + + return TextOut(hdc, nXStart, nYStart, lpString, cbString); +} + +static BOOL MyExtTextOut(HDC hdc, int X, int Y, UINT fuOptions, CONST RECT* lprc, LPCTSTR lpString, UINT cbCount, CONST INT* lpDx, int nShadowOffset, int nColour) +{ + // Print a black shadow + SetTextColor(hdc, 0); + if (nShadowOffset >= 2) { + ExtTextOut(hdc, X + nShadowOffset, Y + nShadowOffset, fuOptions, lprc, lpString, cbCount, lpDx); + } + // Print a black outline + ExtTextOut(hdc, X - 1, Y - 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X + 0, Y - 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X + 1, Y - 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X + 1, Y + 0, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X + 1, Y + 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X + 0, Y + 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X - 1, Y + 1, fuOptions, lprc, lpString, cbCount, lpDx); + ExtTextOut(hdc, X - 1, Y + 0, fuOptions, lprc, lpString, cbCount, lpDx); + // Print the text on top + SetTextColor(hdc, nColour); + + return ExtTextOut(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx); +} + +static void VidSExitTinyMsg() +{ + VidSTinyMsg.nTimer = 0; + + if (TinyMsgFont) { + DeleteObject(TinyMsgFont); + TinyMsgFont = NULL; + } + + RELEASE(pTinyMsgSurf); +} + +static void VidSExitShortMsg() +{ + VidSShortMsg.nTimer = 0; + + if (ShortMsgFont) { + DeleteObject(ShortMsgFont); + ShortMsgFont = NULL; + } + + RELEASE(pShortMsgSurf); +} + +static void VidSExitStatus() +{ + if (StatusFont) { + DeleteObject(StatusFont); + StatusFont = NULL; + } + + RELEASE(pStatusSurf); +} + +void VidSExitChat() +{ + nChatTimer = 0; + + if (ChatIDFont) { + DeleteObject(ChatIDFont); + ChatIDFont = NULL; + } + if (ChatMainFont) { + DeleteObject(ChatMainFont); + ChatMainFont = NULL; + } + + for (int i = 0; i < CHAT_SIZE; i++) { + if (VidSChatMessage[i].pIDText) { + free(VidSChatMessage[i].pIDText); + VidSChatMessage[i].pIDText = NULL; + } + if (VidSChatMessage[i].pMainText) { + free(VidSChatMessage[i].pMainText); + VidSChatMessage[i].pMainText = NULL; + } + } + + RELEASE(pChatSurf); +} + +static void VidSExitEdit() +{ + bEditActive = false; + + if (EditTextFont) { + DeleteObject(EditTextFont); + EditTextFont = NULL; + } + if (EditCursorFont) { + DeleteObject(EditCursorFont); + EditCursorFont = NULL; + } + + RELEASE(pEditSurf); +} + +void VidSExitOSD() +{ + VidSExitTinyMsg(); + if (kNetGame) { + VidSExitEdit(); + } + VidSExitChat(); + VidSExitShortMsg(); + VidSExitStatus(); +} + +static int VidSInitTinyMsg(int /*nFlags*/) +{ + DDSURFACEDESC2 ddsd; + + VidSExitTinyMsg(); + + TinyMsgFont = CreateFont(12, 0, 0, 0, FW_SEMIBOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("MS Sans Serif")); + VidSTinyMsg.nTimer = 0; + + // create surface to display the text + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = 300; + ddsd.dwHeight = 20; + + ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = nKeyColour; + ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = nKeyColour; + + if (FAILED(pDD->CreateSurface(&ddsd, &pTinyMsgSurf, NULL))) { +#ifdef PRINT_DEBUG_INFO + printf(" * Error: Couldn't create OSD texture.\n"); +#endif + return 1; + } + + VidSClearSurface(pTinyMsgSurf, nKeyColour, NULL); + + return 0; +} + +static int VidSInitShortMsg(int nFlags) +{ + DDSURFACEDESC2 ddsd; + + VidSExitShortMsg(); + + nShortMsgFlags = nFlags; + + ShortMsgFont = CreateFont(30, 0, 0, 0, FW_DEMIBOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + VidSShortMsg.nTimer = 0; + + // create surface to display the text + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = 192; + ddsd.dwHeight = 32; + + ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = nKeyColour; + ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = nKeyColour; + + if (FAILED(pDD->CreateSurface(&ddsd, &pShortMsgSurf, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create OSD texture.\n")); +#endif + return 1; + } + + VidSClearSurface(pShortMsgSurf, nKeyColour, NULL); + + return 0; +} + +static int VidSInitStatus(int nFlags) +{ + DDSURFACEDESC2 ddsd; + + VidSExitStatus(); + + nStatusFlags = nFlags; + + StatusFont = CreateFont(48, 0, 0, 0, FW_DEMIBOLD, 0, 0, 0, DEFAULT_CHARSET, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Webdings")); + nPrevStatus = -1; + + // create surface to display the text + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + ddsd.dwWidth = 192; + ddsd.dwHeight = 50; + + ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = nKeyColour; + ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = nKeyColour; + + if (FAILED(pDD->CreateSurface(&ddsd, &pStatusSurf, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create OSD texture.\n")); +#endif + return 1; + } + + VidSClearSurface(pStatusSurf, nKeyColour, NULL); + + return 0; +} + +static int VidSInitChat(int /*nFlags*/) +{ + DDSURFACEDESC2 ddsd; + + if (bChatInitialised) { + VidSExitChat(); + } else { +// for (int i = 0; i < CHAT_SIZE + (CHAT_SIZE >> 1); i++) { + for (int i = 0; i < CHAT_SIZE; i++) { + VidSChatMessage[i].pIDText = NULL; + VidSChatMessage[i].pMainText = NULL; + } + bChatInitialised = true; + } + + //nChatFontSize = nMaxChatFontSize - ((nMaxChatFontSize - nMinChatFontSize) * nFlags) / 4; + nChatFontSize = 20; // used for cheat search only at the minute so only used in a window + + ChatIDFont = CreateFont(nChatFontSize, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + if (nChatFontSize > 20) { + ChatMainFont = CreateFont(nChatFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + } else { + ChatMainFont = CreateFont(nChatFontSize, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + } + + nChatShadowOffset = (nChatFontSize / 16) + 1; + nChatOverFlow = 0; + bDrawChat = false; + + // create surface to display the text + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + if (nVidFullscreen) { + RECT rect; + GetClientScreenRect(hScrnWnd, &rect); + ddsd.dwWidth = rect.right - rect.left; + } else { + extern RECT SystemWorkArea; + ddsd.dwWidth = SystemWorkArea.right - SystemWorkArea.left; + } + ddsd.dwHeight = nChatFontSize * (CHAT_SIZE + (CHAT_SIZE >> 1)); + + ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = nKeyColour; + ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = nKeyColour; + + if (FAILED(pDD->CreateSurface(&ddsd, &pChatSurf, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create Chat texture.\n")); +#endif + return 1; + } + + VidSClearSurface(pChatSurf, nKeyColour, NULL); + + bDrawChat = true; + + return 0; +} + +static int VidSInitEdit(int nFlags) +{ + DDSURFACEDESC2 ddsd; + + VidSExitEdit(); + + nEditSize = nMaxChatFontSize + 8 - ((nMaxChatFontSize - nMinChatFontSize) * nFlags) / 4; + + EditTextFont = CreateFont(nEditSize - 8, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + EditCursorFont = CreateFont(nEditSize - 8, 0, 0, 0, FW_BOLD, 0, TRUE, 0, 0, 0, 0, ANTIALIASED_QUALITY, FF_SWISS, _T("Lucida")); + + nEditShadowOffset = ((nEditSize - 8) / 16) + 1; + + // create surface to display the text + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT; + + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + + if (nVidFullscreen) { + RECT rect; + GetClientScreenRect(hScrnWnd, &rect); + ddsd.dwWidth = rect.right - rect.left; + } else { + extern RECT SystemWorkArea; + ddsd.dwWidth = SystemWorkArea.right - SystemWorkArea.left; + } + ddsd.dwHeight = nEditSize; + + ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = nKeyColour; + ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = nKeyColour; + + if (FAILED(pDD->CreateSurface(&ddsd, &pEditSurf, NULL))) { +#ifdef PRINT_DEBUG_INFO + dprintf(_T(" * Error: Couldn't create OSD texture.\n")); +#endif + return 1; + } + + VidSClearSurface(pEditSurf, nKeyColour, NULL); + + return 0; +} + +int VidSInitOSD(int nFlags) +{ +#ifdef PRINT_DEBUG_INFO +// dprintf(_T(" ** OSD initialised.\n")); +#endif + + if (pDD == NULL) { + return 1; + } + + if (VidSInitStatus(nFlags)) { + return 1; + } + if (VidSInitShortMsg(nFlags)) { + return 1; + } + if (VidSInitChat(nFlags)) { + return 1; + } + if (kNetGame) { + if (VidSInitEdit(nFlags)) { + return 1; + } + } + if (VidSInitTinyMsg(nFlags)) { + return 1; + } + + return 0; +} + +int VidSRestoreOSD() +{ + if (pShortMsgSurf) { + if (FAILED(pShortMsgSurf->IsLost())) { + if (FAILED(pShortMsgSurf->Restore())) { + return 1; + } + VidSClearSurface(pShortMsgSurf, nKeyColour, NULL); + + VidSShortMsg.nTimer = 0; + } + } + + if (pTinyMsgSurf) { + if (FAILED(pTinyMsgSurf->IsLost())) { + if (FAILED(pTinyMsgSurf->Restore())) { + return 1; + } + VidSClearSurface(pTinyMsgSurf, nKeyColour, NULL); + + VidSTinyMsg.nTimer = 0; + } + } + + if (pStatusSurf) { + if (FAILED(pStatusSurf->IsLost())) { + if (FAILED(pStatusSurf->Restore())) { + return 1; + } + VidSClearSurface(pStatusSurf, nKeyColour, NULL); + + nPrevStatus = -1; + } + } + + if (pChatSurf) { + if (FAILED(pChatSurf->IsLost())) { + if (FAILED(pChatSurf->Restore())) { + return 1; + } + VidSClearSurface(pChatSurf, nKeyColour, NULL); + } + } + + if (kNetGame) { + if (pEditSurf) { + if (FAILED(pEditSurf->IsLost())) { + if (FAILED(pEditSurf->Restore())) { + return 1; + } + VidSClearSurface(pEditSurf, nKeyColour, NULL); + } + } + } + + return 0; +} + +static void VidSDisplayTinyMsg(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + if (VidSTinyMsg.nTimer) { + RECT src = { 0, 0, 300, 20 }; + RECT dest = { pRect->right - 320, pRect->bottom - 24, pRect->right - 8, pRect->bottom - 4 }; + + // Switch off message display when the message has been displayed long enough + if (nFramesEmulated > VidSTinyMsg.nTimer) { + VidSTinyMsg.nTimer = 0; + } + + if (dest.left < pRect->left) { + src.left = pRect->left - dest.left; + dest.left = pRect->left; + } + + if (nZoom & 2) { + dest.top <<= 1; + dest.bottom <<= 1; + } + + if (nZoom & 1) { + dest.left <<= 1; + dest.right <<= 1; + } + + // Blit the message to the surface using a colourkey + pSurf->Blt(&dest, pTinyMsgSurf, &src, DDBLT_ASYNC | DDBLT_KEYSRC, NULL); + } +} + +static void VidSDisplayShortMsg(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + if (VidSShortMsg.nTimer) { + RECT src = { 0, 0, 192, 32 }; + RECT dest = { 0, pRect->top + 4, pRect->right - 8, pRect->top + 36 }; + + // Switch off message display when the message has been displayed long enough + if (nFramesEmulated > VidSShortMsg.nTimer) { + VidSShortMsg.nTimer = 0; + } + + if (nStatus) { + for (int x = 0; x < 4; x++) { + if (nStatus & (1 << x)) { + dest.right -= 48; + } + } + + dest.top += 10; + dest.bottom += 10; + } + + dest.left = dest.right - 192; + if (dest.left < pRect->left) { + src.left = pRect->left - dest.left; + dest.left = pRect->left; + } + + if (nZoom & 2) { + dest.top <<= 1; + dest.bottom <<= 1; + } + + if (nZoom & 1) { + dest.left <<= 1; + dest.right <<= 1; + } + + // Blit the message to the surface using a colourkey + pSurf->Blt(&dest, pShortMsgSurf, &src, DDBLT_ASYNC | DDBLT_KEYSRC, NULL); + } +} + +static void VidSDisplayStatus(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + nStatus = 0; + + if (nVidSDisplayStatus == 0) { + return; + } + + if (bRunPause) { + nStatus |= 1; + } + if (kNetGame) { + nStatus |= 2; + } + if (nReplayStatus == 1) { + nStatus |= 4; + } + if (nReplayStatus == 2) { + nStatus |= 8; + } + + if (nStatus != nPrevStatus) { + nPrevStatus = nStatus; + if (nStatus) { + // Print the message + HDC hDC; + HFONT hFont; + TCHAR szStatus[8]; + + // Clear the surface first + VidSClearSurface(pStatusSurf, nKeyColour, NULL); + + // Make the status string + memset(szStatus, 0, sizeof(szStatus)); + for (int i = 0, j = 0; i < 4; i++) { + if (nStatus & (1 << i)) { + szStatus[j] = nStatusSymbols[i]; + j++; + } + } + + pStatusSurf->GetDC(&hDC); + SetBkMode(hDC, TRANSPARENT); + hFont = (HFONT)SelectObject(hDC, StatusFont); + SetTextAlign(hDC, TA_TOP | TA_RIGHT); + + MyTextOut(hDC, 192 - 2, 0, szStatus, _tcslen(szStatus), 2, RGB(0xFF, 0x3F, 0x3F)); + + // Clean up + SelectObject(hDC, hFont); + pStatusSurf->ReleaseDC(hDC); + } + } + + if (nStatus) { + RECT src = { 192, 0, 192, 48 }; + RECT dest = { 0, pRect->top + 4, pRect->right - 4, pRect->top + 52 }; + for (int x = 0; x < 4; x++) { + if (nStatus & (1 << x)) { + src.left -= 48; + } + } + dest.left = dest.right - (src.right - src.left); + + if (nZoom & 2) { + dest.top <<= 1; + dest.bottom <<= 1; + } + + if (nZoom & 1) { + dest.left <<= 1; + dest.right <<= 1; + } + + // Blit the message to the surface using a colourkey + pSurf->Blt(&dest, pStatusSurf, &src, DDBLT_ASYNC | DDBLT_KEYSRC, NULL); + } +} + +static int VidSDrawChat(RECT* dest) +{ + bool bContent = false; + + if (pChatSurf == NULL) { + return 1; + } + + VidSClearSurface(pChatSurf, nKeyColour, NULL); + + for (int i = 0; i < CHAT_SIZE; i++) { + if (VidSChatMessage[i].pIDText || VidSChatMessage[i].pMainText) { + bContent = true; + break; + } + } + + if (bContent) { + + nChatTimer = nFramesEmulated + 300; + + // Print the message + HDC hDC; + HFONT hFont; + int nStringLength; + int nFit = 0; + SIZE sizeID, sizeMain; + + // Clear the surface first + VidSClearSurface(pChatSurf, nKeyColour, NULL); + + pChatSurf->GetDC(&hDC); + SetBkMode(hDC, TRANSPARENT); + + hFont = (HFONT)SelectObject(hDC, ChatIDFont); + SetTextAlign(hDC, TA_TOP | TA_LEFT); + + nChatOverFlow = 0; + + for (int i = 0; i < CHAT_SIZE; i++) { + + // Exit when too many lines are displayed + if (nChatOverFlow > (CHAT_SIZE >> 1)) { + break; + } + + if (VidSChatMessage[i].pIDText) { + SelectObject(hDC, ChatIDFont); + nStringLength = _tcslen(VidSChatMessage[i].pIDText); + MyExtTextOut(hDC, 0, (i + nChatOverFlow) * nChatFontSize, ETO_CLIPPED, dest, VidSChatMessage[i].pIDText, nStringLength, NULL, nChatShadowOffset, VidSChatMessage[i].nIDColour); + GetTextExtentPoint32(hDC, VidSChatMessage[i].pIDText, nStringLength, &sizeID); + } else { + sizeID.cx = 0; + } + + if (VidSChatMessage[i].pMainText) { + SelectObject(hDC, ChatMainFont); + nStringLength = _tcslen(VidSChatMessage[i].pMainText); + GetTextExtentExPoint(hDC, VidSChatMessage[i].pMainText, nStringLength, dest->right - sizeID.cx, &nFit, NULL, &sizeMain); + + if (nFit < nStringLength) { + // The string doesn't fit on the screen in one line, break the line on the last space that fits + while (nFit > 0 && (VidSChatMessage[i].pMainText[nFit] != ' ')) { + nFit--; + } + + nStringLength = nFit; + MyExtTextOut(hDC, sizeID.cx, (i + nChatOverFlow) * nChatFontSize, ETO_CLIPPED, dest, VidSChatMessage[i].pMainText, nStringLength, NULL, nChatShadowOffset, VidSChatMessage[i].nMainColour); + + nChatOverFlow++; + + nStringLength = _tcslen(&(VidSChatMessage[i].pMainText[nFit + 1])); + MyExtTextOut(hDC, sizeID.cx, (i + nChatOverFlow) * nChatFontSize, ETO_CLIPPED, dest, &(VidSChatMessage[i].pMainText[nFit + 1]), nStringLength, NULL, nChatShadowOffset, VidSChatMessage[i].nMainColour); + } else { + SelectObject(hDC, ChatMainFont); + MyTextOut(hDC, sizeID.cx, (i + nChatOverFlow) * nChatFontSize, VidSChatMessage[i].pMainText, nStringLength, nChatShadowOffset, VidSChatMessage[i].nMainColour); + } + } + } + + // Clean up + SelectObject(hDC, hFont); + pChatSurf->ReleaseDC(hDC); + } else { + nChatTimer = 0; + } + + return 0; +} + +static void VidSDisplayChat(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + if (nChatTimer || bDrawChat) { + // Blit the message to the surface using a colourkey + RECT src = { 0, 0, pRect->right - pRect->left, nChatFontSize * (CHAT_SIZE + (CHAT_SIZE >> 1)) }; + + // Update the message if needed + if (bDrawChat) { + VidSDrawChat(&src); + bDrawChat = false; + } + + if (nChatTimer) { + RECT dest = { pRect->left, pRect->bottom - nChatFontSize * (CHAT_SIZE + nChatOverFlow), pRect->right, pRect->bottom }; + src.bottom = nChatFontSize * (CHAT_SIZE + nChatOverFlow); + + if (bEditActive) { + dest.top -= nEditSize; + dest.bottom -= nEditSize; + } else { + dest.top -= 4; + dest.bottom -= 4; + } + + if (nZoom & 2) { + dest.top <<= 1; + dest.bottom <<= 1; + } + + if (nZoom & 1) { + dest.left <<= 1; + dest.right <<= 1; + } + + pSurf->Blt(&dest, pChatSurf, &src, DDBLT_ASYNC | DDBLT_KEYSRC, NULL); + } + + // Scroll message if needed + if (nFramesEmulated > nChatTimer) { + nChatTimer = 0; + VidSAddChatMsg(NULL, 0, NULL, 0); + bDrawChat = true; + } + } +} + +static void VidSDisplayEdit(IDirectDrawSurface7* pSurf, RECT* pRect) +{ + if (bEditActive) { + RECT src = { 0, 0, pRect->right - pRect->left, nEditSize }; + RECT dest = { pRect->left, pRect->bottom - nEditSize, pRect->right, pRect->bottom }; + + if (nZoom & 2) { + dest.top <<= 1; + dest.bottom <<= 1; + } + + if (nZoom & 1) { + dest.left <<= 1; + dest.right <<= 1; + } + + DWORD nStart, nEnd; + SendMessage(hwndChat, EM_GETSEL, (WPARAM)&nStart, (WPARAM)&nEnd); + + if (nStart != nPrevStart || nEnd != nPrevEnd) { + nPrevStart = nStart; + nPrevEnd = nEnd; + bEditTextChanged = true; + nCursorTime = nFramesEmulated + 30; + nCursorState = 1; + } else { + if (GetCurrentFrame() > nCursorTime) { + nCursorTime = nFramesEmulated + 30; + nCursorState = !nCursorState; + bEditTextChanged = true; + } + } + + if (bEditTextChanged) { + if (pEditSurf == NULL) { + return; + } + + // Print the message + HDC hDC; + HFONT hFont; + SIZE size; + int pos; + + TCHAR Space[] = _T(" "); + unsigned int nFit = 0; + TCHAR* pText = EditText; + +// bool bDisplayCursor = false; +// if (GetFocus()) { +// bDisplayCursor = true; +// } + + // Clear the surface first + VidSClearSurface(pEditSurf, nKeyColour, NULL); + + pEditSurf->GetDC(&hDC); + SetBkMode(hDC, TRANSPARENT); + hFont = (HFONT)SelectObject(hDC, EditTextFont); + SetTextAlign(hDC, TA_TOP | TA_LEFT); + + // If the string is wider than the screen, shift the display to the right. + pos = 0; + do { + GetTextExtentExPoint(hDC, pText, _tcslen(pText), src.right - pos - nEditSize, (int*)&nFit, NULL, &size); + if (nFit < nStart) { + pos -= src.right * 3 / 5; + } + } while (nFit < nStart); + + if (nStart == _tcslen(pText)) { + if (nStart) { + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, pText, nStart, NULL, nEditShadowOffset, RGB(0xDF, 0xDF, 0xFF)); + } + + GetTextExtentPoint32(hDC, pText, nStart, &size); + pos += size.cx; + + if (nCursorState) { + SelectObject(hDC, EditCursorFont); + } + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, Space, 1, NULL, nEditShadowOffset, RGB(0xFF, 0xFF, 0xFF)); + } else { + if (nStart) { + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, pText, nStart, NULL, nEditShadowOffset, RGB(0xDF, 0xDF, 0xFF)); + } + + GetTextExtentPoint32(hDC, pText, nStart, &size); + pos += size.cx; + + if (nEnd == nStart) { + if (nCursorState) { + SelectObject(hDC, EditCursorFont); + } + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, pText + nStart, 1, NULL, nEditShadowOffset, RGB(0xFF, 0xFF, 0xFF)); + + GetTextExtentPoint32(hDC, pText + nStart, 1, &size); + pos += size.cx; + + // We really printed one character past the end of the selection + nEnd++; + } else { + // Highlight selected characters + SelectObject(hDC, EditTextFont); + // SetTextColor(hDC, RGB(0x7F, 0x1F, 0x1F)); + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, pText + nStart, nEnd - nStart, NULL, nEditShadowOffset, RGB(0xFF, 0xFF, 0xDF)); + + GetTextExtentPoint32(hDC, pText + nStart, nEnd - nStart, &size); + pos += size.cx; + } + + if (nEnd < _tcslen(EditText)) { + SelectObject(hDC, EditTextFont); + MyExtTextOut(hDC, pos + 3, 3, ETO_CLIPPED, &src, pText + nEnd, _tcslen(pText) - nEnd, NULL, nEditShadowOffset, RGB(0xDF, 0xDF, 0xFF)); + } + } + + // Clean up + SelectObject(hDC, hFont); + pEditSurf->ReleaseDC(hDC); + + bEditTextChanged = false; + } + + // Blit the message to the surface using a colourkey + pSurf->Blt(&dest, pEditSurf, &src, DDBLT_ASYNC | DDBLT_KEYSRC, NULL); + } +} + +void VidSDisplayOSD(IDirectDrawSurface7* pSurf, RECT* pRect, int nFlags) +{ + nZoom = nFlags & 3; + + VidSDisplayStatus(pSurf, pRect); + VidSDisplayTinyMsg(pSurf, pRect); + VidSDisplayShortMsg(pSurf, pRect); + VidSDisplayChat(pSurf, pRect); + if (kNetGame) { + VidSDisplayEdit(pSurf, pRect); + } +} + +int VidSNewTinyMsg(const TCHAR* pText, int nRGB, int nDuration, int nPriority) // int nRGB = 0, int nDuration = 0, int nPriority = 5 +{ + // If a message with a higher priority is being displayed, exit. + if (VidSTinyMsg.nTimer && VidSTinyMsg.nPriority > nPriority) { + return 1; + } + + int nSize = _tcslen(pText); + if (nSize > 63) { + nSize = 63; + } + _tcsncpy(VidSTinyMsg.pMsgText, pText, nSize); + VidSTinyMsg.pMsgText[nSize] = 0; + + if (nRGB) { + // Convert RGB value to COLORREF + VidSTinyMsg.nColour = RGB((nRGB >> 16), ((nRGB >> 8) & 0xFF), (nRGB & 0xFF)); + } else { + // Default message colour (yellow) + VidSTinyMsg.nColour = RGB(0xFF, 0xFF, 0x7F); + } + if (nDuration) { + VidSTinyMsg.nTimer = nFramesEmulated + nDuration; + } else { + VidSTinyMsg.nTimer = nFramesEmulated + 120; + } + VidSTinyMsg.nPriority = nPriority; + + { + if (pTinyMsgSurf == NULL) { + return 1; + } + + // Print the message + HDC hDC; + HFONT hFont; + + // Clear the surface first + VidSClearSurface(pTinyMsgSurf, nKeyColour, NULL); + + pTinyMsgSurf->GetDC(&hDC); + SetBkMode(hDC, TRANSPARENT); + hFont = (HFONT)SelectObject(hDC, TinyMsgFont); + SetTextAlign(hDC, TA_BOTTOM | TA_RIGHT); + + // Print a black shadow + SetTextColor(hDC, 0); + TextOut(hDC, 300, 20, VidSTinyMsg.pMsgText, _tcslen(VidSTinyMsg.pMsgText)); + // Print the text on top + SetTextColor(hDC, VidSTinyMsg.nColour); + TextOut(hDC, 300 - 1, 20 - 1, VidSTinyMsg.pMsgText, _tcslen(VidSTinyMsg.pMsgText)); + + // Clean up + SelectObject(hDC, hFont); + pTinyMsgSurf->ReleaseDC(hDC); + } + + return 0; + } + +int VidSNewShortMsg(const TCHAR* pText, int nRGB, int nDuration, int nPriority) // int nRGB = 0, int nDuration = 0, int nPriority = 5 +{ + // If a message with a higher priority is being displayed, exit. + if (VidSShortMsg.nTimer && VidSShortMsg.nPriority > nPriority) { + return 1; + } + + int nSize = _tcslen(pText); + if (nSize > 31) { + nSize = 31; + } + _tcsncpy(VidSShortMsg.pMsgText, pText, nSize); + VidSShortMsg.pMsgText[nSize] = 0; + + // copy osd message + memset(OSDMsg, '\0', MAX_PATH); + _tcsncpy(OSDMsg, pText, nSize); + + if (nRGB) { + // Convert RGB value to COLORREF + VidSShortMsg.nColour = RGB((nRGB >> 16), ((nRGB >> 8) & 0xFF), (nRGB & 0xFF)); + } else { + // Default message colour (yellow) + VidSShortMsg.nColour = RGB(0xFF, 0xFF, 0x7F); + } + if (nDuration) { + VidSShortMsg.nTimer = nFramesEmulated + nDuration; + } else { + VidSShortMsg.nTimer = nFramesEmulated + 120; + } + nOSDTimer = VidSShortMsg.nTimer; + VidSShortMsg.nPriority = nPriority; + + { + if (pShortMsgSurf == NULL) { + return 1; + } + + // Print the message + HDC hDC; + HFONT hFont; + + // Clear the surface first + VidSClearSurface(pShortMsgSurf, nKeyColour, NULL); + + pShortMsgSurf->GetDC(&hDC); + SetBkMode(hDC, TRANSPARENT); + hFont = (HFONT)SelectObject(hDC, ShortMsgFont); + SetTextAlign(hDC, TA_TOP | TA_RIGHT); + + MyTextOut(hDC, 192 - 2, 0, VidSShortMsg.pMsgText, _tcslen(VidSShortMsg.pMsgText), 2, VidSShortMsg.nColour); + + // Clean up + SelectObject(hDC, hFont); + pShortMsgSurf->ReleaseDC(hDC); + } + + return 0; +} + +void VidSKillShortMsg() +{ + VidSShortMsg.nTimer = 0; +} + +void VidSKillTinyMsg() +{ + VidSTinyMsg.nTimer = 0; +} + +void VidSKillOSDMsg() +{ + nOSDTimer = 0; +} + +int VidSAddChatMsg(const TCHAR* pID, int nIDRGB, const TCHAR* pMain, int nMainRGB) +{ + if (pID || pMain) { + // Scroll the text buffers up one entry + if (VidSChatMessage[0].pIDText) { + free(VidSChatMessage[0].pIDText); + VidSChatMessage[0].pIDText = NULL; + } + if (VidSChatMessage[0].pMainText) { + free(VidSChatMessage[0].pMainText); + VidSChatMessage[0].pMainText = NULL; + } + + for (int i = 1; i < CHAT_SIZE; i++) { + VidSChatMessage[i - 1].pIDText = VidSChatMessage[i].pIDText; + VidSChatMessage[i - 1].nIDColour = VidSChatMessage[i].nIDColour; + VidSChatMessage[i - 1].pMainText = VidSChatMessage[i].pMainText; + VidSChatMessage[i - 1].nMainColour = VidSChatMessage[i].nMainColour; + } + + // Put the new entry in the last position + if (pID) { + int nSize = _tcslen(pID); + VidSChatMessage[CHAT_SIZE - 1].pIDText = (TCHAR*)malloc((nSize + 1) * sizeof(TCHAR)); + _tcscpy(VidSChatMessage[CHAT_SIZE - 1].pIDText, pID); + VidSChatMessage[CHAT_SIZE - 1].pIDText[nSize] = 0; + VidSChatMessage[CHAT_SIZE - 1].nIDColour = RGB((nIDRGB >> 16), ((nIDRGB >> 8) & 0xFF), (nIDRGB & 0xFF)); + } else { + VidSChatMessage[CHAT_SIZE - 1].pIDText = NULL; + } + if (pMain) { + int nSize = _tcslen(pMain); + VidSChatMessage[CHAT_SIZE - 1].pMainText = (TCHAR*)malloc((nSize + 1) * sizeof(TCHAR)); + _tcscpy(VidSChatMessage[CHAT_SIZE - 1].pMainText, pMain); + VidSChatMessage[CHAT_SIZE - 1].pMainText[nSize] = 0; + VidSChatMessage[CHAT_SIZE - 1].nMainColour = RGB((nMainRGB >> 16), ((nMainRGB >> 8) & 0xFF), (nMainRGB & 0xFF)); + } else { + VidSChatMessage[CHAT_SIZE - 1].pMainText = NULL; + } + } else { + for (int i = 0; i < CHAT_SIZE; i++) { + if (VidSChatMessage[i].pIDText || VidSChatMessage[i].pMainText) { + if (VidSChatMessage[i].pIDText) { + free(VidSChatMessage[i].pIDText); + VidSChatMessage[i].pIDText = NULL; + } + if (VidSChatMessage[i].pMainText) { + free(VidSChatMessage[i].pMainText); + VidSChatMessage[i].pMainText = NULL; + } + + break; + } + } + } + + bDrawChat = true; + + return 0; +} diff --git a/src/interface/win32/vid_directx_support.h b/src/interface/win32/vid_directx_support.h new file mode 100644 index 00000000..9ed0ec3a --- /dev/null +++ b/src/interface/win32/vid_directx_support.h @@ -0,0 +1,46 @@ +//#define DIRECTDRAW_VERSION 7 // Use this DirectDraw version +#include +#include "vid_support.h" + +// General +void VidSExit(); +int VidSInit(IDirectDraw7* pDD7); + +// Miscellaneous +int VidSGetSurfaceDepth(IDirectDrawSurface7* pSurf); +int VidSClearSurface(IDirectDrawSurface7* pSurf, unsigned int nColour, RECT* pRect); + +// Clipper +int VidSClipperInit(IDirectDrawSurface7* pSurf); + +// Gamma controls +void VidSRestoreGamma(); +int VidSUpdateGamma(); +int VidSSetupGamma(IDirectDrawSurface7* pSurf); + +// Select optimal full-screen resolution +struct VidSDisplayScoreInfo { + // Filled in advance by the caller + unsigned int nRequestedWidth; unsigned int nRequestedHeight; unsigned int nRequestedDepth; unsigned int nRequestedZoom; + unsigned int nModeWidth; unsigned int nModeHeight; unsigned int nModeDepth; + // Filled by the scoring routine + unsigned int nBestWidth; unsigned int nBestHeight; unsigned int nBestDepth; + unsigned int nBestScore; +}; + +int VidSScoreDisplayMode(VidSDisplayScoreInfo* pScoreInfo); +int VidSInitScoreInfo(VidSDisplayScoreInfo* pScoreInfo); + +void VidSRestoreScreenMode(); +int VidSEnterFullscreenMode(int nZoom, int nDepth); + +// Image size +int VidSScaleImage(RECT* pRect, int nGameWidth, int nGameHeight, bool bVertScanlines); +bool VidSGetArcaderes(int* pWidth, int* pHeight); + +// Text display +void VidSExitOSD(); +int VidSInitOSD(int nFlags); +int VidSRestoreOSD(); +void VidSDisplayOSD(IDirectDrawSurface7* pSurf, RECT* pRect, int nFlags); + diff --git a/src/license.txt b/src/license.txt new file mode 100644 index 00000000..43adc884 --- /dev/null +++ b/src/license.txt @@ -0,0 +1,47 @@ +You may freely use, modify, and distribute both the FB Alpha source code and binary, however the following restrictions apply to the FB Alpha original material (see below for a list of libraries with differing licenses, please consult their respective documentation for more information): + + - You may not sell, lease, rent or otherwise seek to gain monetary profit from FB Alpha; + - You must make public any changes you make to the source code; + - You must include, verbatim, the full text of this license; + - You may not distribute binaries which support games with copyright dates less then three years old; + - You may not distribute FB Alpha with ROM images unless you have the legal right to distribute them; + - You may use dynamic linked libraries (dlls) for network play only (all other use is prohibited); + - You may not ask for donations to support your work on any project that uses the FB Alpha source code. + +FB Alpha can currently be obtained from http://www.barryharris.me.uk/. + +FB Alpha would not exist without a lot of code from the MAME project. The MAME project is subject to it's own license, which can be found at http://mamedev.org/legal.html. Due to the use of MAME code in FB Alpha, FB Alpha is also subject to the terms of the MAME license. + +FB Alpha is based on Final Burn (formally at http://www.finalburn.com/), see additional text below. +Musashi MC68000/MC68010/MC68EC020 core by Karl Stenerud (http://www.mamedev.org/). +A68K MC68000 core by Mike Coates & Darren Olafson (http://www.mamedev.org/). +YM3812/YM3526/Y8950 core by Jarek Burczynski & Tatsuyuki Satoh (http://www.mamedev.org/). +YM2151 core by Jarek Burczynski (http://www.mamedev.org/). +YM2413 core by Jarek Burczynski (http://www.mamedev.org/). +YMF278B core by R. Belmont & O.Galibert (http://www.mamedev.org/). +YM2608/YM2610/YM2612/YM2203 cores by Jarek Burczynski & Tatsuyuki Satoh (http://www.mamedev.org/). +AY8910/YM2149 core by various authors (http://www.mamedev.org/). +M6502 emulation core by Marat (http://fms.komkon.org/EMUL8/). +I8039 emulation core by Mirko Buffoni (http://www.mamedev.org/). +ARM7 emulation core by Steve Ellenoff (http://www.mamedev.org/). +Z80 emulation core by Juergen Buchmueller (http://www.mamedev.org/). +PNG functionality provided by libpng (http://www.libpng.org/) and PNGlib (http://www.madwizard.org/). +Zip functionality provided by zlib (http://www.zlib.net/). + +Some graphics effects provided by the Scale2x, 2xPM, Eagle Graphics, 2xSaI, hq2x/hq3x/hq4x, hq2xS/hq3xS/SuperEagle/2xSaI (VBA), hq2xS/hq3xS/hq2xBold/hq3xBold/EPXB/EPXC (SNES9X ReRecording) and SuperScale libraries (http://scale2x.sourceforge.net/, http://2xpm.freeservers.com/, http://retrofx.com/, http://elektron.its.tudelft.nl/~dalikifa/, http://www.hiend3d.com/, http://code.google.com/p/vba-rerecording/, http://code.google.com/p/snes9x151-rerecording/, http://nebula.emulatronia.com/). + +Miscellaneous other components from various sources. Copyright and license information are contained in the relevant parts of the source code. + +All material not covered above © 2004-2010 Team FB Alpha. + +DISCLAIMER: The authors of FB Alpha don't guarantee its fitness for any purpose, implied or otherwise, and do not accept responsibility for any damages whatsoever that might occur when using FB Alpha. All games emulated by FB Alpha, including any images and sounds therein, are copyrighted by their respective copyright holders. FB Alpha DOES NOT INCLUDE any ROM images of emulated games. + +The following information and license conditions accompanied the original Final Burn emulator. They also apply to FB Alpha: + +"Copyright (c)2001 Dave (formally of www.finalburn.com), all rights reserved. This refers to all code except where stated otherwise (e.g. unzip and zlib code)." + +"You can use, modify and redistribute this code freely as long as you don't do so commercially. This copyright notice must remain with the code. If your program uses this code, you must either distribute or link to the source code. If you modify or improve this code, you must distribute the source code improvements." + +"Dave" +"Former Homepage: www.finalburn.com" +"E-mail: dave@finalburn.com" diff --git a/whatsnew.html b/whatsnew.html new file mode 100644 index 00000000..f5636791 --- /dev/null +++ b/whatsnew.html @@ -0,0 +1,2142 @@ + + + + + +FB Alpha - What's New + + + + + + + + + \ No newline at end of file
+

FB Alpha - What's New

+

http://www.barryharris.me.uk
+http://neosource.1emu.net/forums

+ +

v0.2.97.14

+
    +
  • Fixed missing menu in Windows XP [CaptainCPS, doomking]
  • +
  • Fixed Neo Geo CD dialog game scanning timeout [CaptainCPS]
  • +
  • Better organised the Neo Geo menu items [CaptainCPS]
  • +
+ + +

v0.2.97.14

+
    +
  • Ported the V20/V30/V33/V25/V35 CPU core from MAME [iq_132]
  • +
  • Updated Vez interface to support above CPU core port [iq_132]
  • +
  • Updated the M72, M90, Dynamite Duke and Raiden drivers to support the new Vez interface [iq_132]
  • +
  • Added sound support to the V25 based Toaplan drivers Batsugun, Dogyuun, Knuckle Bash and Grind Stormer [iq_132]
  • +
  • Added Risky Challenge and Gussun to release builds [iq_132]
  • +
  • Ported the M6502 CPU core from MAME, and added an interface for it, replacing the old core [Barry]
  • +
  • Enabled the sub-CPU types in the M6502 CPU Core and added support for them in the interface [iq_132]
  • +
  • Added support for the new M6502 core to the Renegade driver, fixing some graphic issues [Barry]
  • +
  • Added support for the new M6502 core to the DEC-8 driver, adding sound to all games [Barry]
  • +
  • Added support for the new M6502 core to the Karnov driver, adding sound to all games [Barry]
  • +
  • Updated the Gauntlet, Mole Attack, Mysterious Stones and Scrambled Egg drivers to support the new M6502 core [Barry]
  • +
  • Added SAA1099 sound core module and added support to the XOR World driver which now has sound [iq_132]
  • +
  • Added support to the DAC module for up to eight DACs [Barry]
  • +
  • Added BURN_SND_CLIP macro [Barry]
  • +
  • Fixed rendering MSM6295 sound in Seibu sound module [Barry]
  • +
  • Added Neo Geo CD Load Game dialog [CaptainCPS]
  • +
  • Integrated the Neo Geo CD Load Game dialog with the rest of the application and fixed several x64 issues [Barry]
  • +
  • Removed the BurnMedia functionality since it is replaced by the Neo Geo CD id module, and updated all drivers to reflect the new structure [Barry]
  • +
  • Changed the burn, burn/devices, burn/drivers, burn/sound, burner and interface folders to use defined variable types, allowing better control for ports to other architectures [Barry]
  • +
  • Changed the CPU interfaces to use defined variable types [Barry]
  • +
  • Fixed the source code tree to build with MinGW64 and GCC 4.6.1 allowing MinGW to build x86 and x64 builds [Barry]
  • +
  • Consolidated the mingw345 and mingw452 makefiles, and added support for GCC 4.6.1 to the makefile [Barry]
  • +
  • Moved the rules to makefile.rules and included makefile.rules in the mingw and vc makefiles [Barry]
  • +
  • Moved some win32 specific stuff from burner.h to burner_win32.h [kev]
  • +
  • Some 64-bit code fixes [TheMaister]
  • +
  • Changed the DirectX support to load the functions at runtime, removing the need for linking to the libraries [CaptainCPS]
  • +
  • Added support for building the experimental DirectX9 blitter and xAudio2 module with MinGW [CaptainCPS]
  • +
  • Tidied the DirectX changes to compile cleanly [Barry]
  • +
  • Added an alternative DirectX 9 blitter written by regret and modified it to work with FB Alpha [Barry, regret]
  • +
  • Added driver for Dragon Ninja, Heavy Barrel and Robocop on DEC-0 hardware [Barry]
  • +
  • Added bootleg of Knights of the Round to the CPS-1 driver [Barry, JacKc]
  • +
  • Added clone of Pang 3 to the CPS-1 driver [Barry]
  • +
  • Added clone of Street Fighter II Champion Edition to the CPS-1 driver [Barry]
  • +
  • Added clone of Cobra Command to the DEC-8 driver [Barry]
  • +
  • Added clone of Puckman to the Pacman driver [JacKc]
  • +
  • Improved the asic27_kov protection simulation, allowing Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan to work, albeit with incorrect roms due to rom-hoarding [iq_132]
  • +
  • Added clone of Ninja Warriors to the Taito drivers [JacKc]
  • +
  • Added Fix Eight to the Toaplan drivers [iq_132]
  • +
  • Added Ghox to the Toaplan drivers [iq_132]
  • +
  • Added support for the analog paddle in Ghox [Barry]
  • +
  • Added clone of Alien Storm to the Sega System 18 driver [JacKc]
  • +
  • Added clone of JJ Squakwers to the Seta driver [JacKc]
  • +
  • Added clone of Ikari III to the SNK68 driver [JacKc]
  • +
  • Added Pipi & Bibis to the Toaplan drivers [iq_132]
  • +
  • Cleaned up 1945K-III driver and added support for generic rendering [iq_132]
  • +
  • Cleaned up the 4 Enraya driver and added support for 'unknown Pacman gambling game' [iq_132]
  • +
  • Fixed sound in Aquarium driver [Barry]
  • +
  • Fixed sound in Armed Formation driver [Barry]
  • +
  • Fixed crash in the Baraduke driver [Barry]
  • +
  • Fixed Saturn in the Blue Print driver [Barry]
  • +
  • Fixed sound in Caveman Ninja bootleg in the Caveman Ninja driver [Barry]
  • +
  • Fixed crash when exiting CPS-1 drivers [Barry]
  • +
  • Fixed sound in SD Gundam Psycho Salamander no Kyoui in D-Con driver [Barry]
  • +
  • Fixed coin inputs in Garyoret in the DEC-8 driver [Barry]
  • +
  • Fixed an app crash in the Garyoret and Gondo drivers in the DEC-8 driver [Barry]
  • +
  • Fixed orientation in Last Mission in the DEC-8 driver [Barry]
  • +
  • Fixed Shackled in the DEC-8 driver [Barry]
  • +
  • Corrected main and sub CPU clocks in the Double Dragon driver [Barry]
  • +
  • Fixed music tempo in Double Dragon [Barry]
  • +
  • Improved the volume balance between the YM2151 and the MSM5205's in the Double Dragon driver [Barry]
  • +
  • Added overclocking support to the Double Dragon driver [Barry]
  • +
  • Improved video timing and sound balance in the Exed Exes driver [Barry]
  • +
  • Added sample support to the Galaga driver [Barry]
  • +
  • Fixed sound in Got-cha Mini Game Festival [Barry]
  • +
  • Fixed clone of Gyrodine in the Kyugo driver [Barry]
  • +
  • Fixed orientation of vertical games in the Lady Bug driver [Barry]
  • +
  • Fixed bootleg of Legend of Kage in the Legend of Kage driver [Barry]
  • +
  • Added ADPCM sound to Avengers and Trojan in the Legendary Wings driver [Barry]
  • +
  • Fixed music tempo in the M92 driver [Barry]
  • +
  • Fixed crash in Magical Cat Adventure driver [Barry]
  • +
  • Added support for second DAC in Mogua Desse driver [Barry]
  • +
  • Fixed sound in Mug Smashers driver [Barry]
  • +
  • Added support for the NeoOpen BIOS v0.1 beta to the NeoGeo driver [Barry]
  • +
  • Fixed driver reset in Task Force Harrier in the NMK16 driver [Barry]
  • +
  • Fixed sound in the Afega games in the NMK16 driver [Barry]
  • +
  • Fixed music tempo in Macross 2 and Thunder Dragon in the NMK16 driver [Barry]
  • +
  • Big cleanup of the Pacman driver, adding support for Pengo and a few clones [iq_132]
  • +
  • Fixed orientation of all games in the Pacman driver [Barry]
  • +
  • Fixed Paint Roller in the Pacman driver and added to release builds [Barry]
  • +
  • Fixed inputs in Ponpoko in the Pacman driver [Barry]
  • +
  • Fixed Woodpecker (set 2) in the Pacman driver and added to release builds [Barry]
  • +
  • Fixed sound in Pass driver [Barry]
  • +
  • Fixed sound in Power Instinct (bootleg set 2) [Barry]
  • +
  • Fixed service mode dips in Pushman driver [Barry]
  • +
  • Fixed crash in Pushman (Korea, set 2) [Barry]
  • +
  • Added Rally X to release builds since I obviously forgot when I wrote the driver! [Barry]
  • +
  • Emulated the MCU in the Renegade driver [Barry]
  • +
  • Emulated the custom ADPCM sound in the Renegade driver [Barry]
  • +
  • Fixed DAC sound in Route 16 driver [Barry]
  • +
  • Added NVRAM saving in the Seta 2 driver, meaning that gun callibrations are stored when exiting [Barry]
  • +
  • Fixed clone of Joe & Mac Returns in Simple 156 driver [Barry]
  • +
  • Fixed sound in SUNA16 driver [Barry]
  • +
  • Fixed Get Star (bootleg set 1) in Tiger Heli driver [Barry]
  • +
  • Emulated MCU in non-bootleg versions of Alcon and Slapfight in Tiger Heli drivers which are now working [Barry]
  • +
  • Simulated MCU in non-bootleg version of Get Star in Tiger Heli driver which is now working [Barry]
  • +
  • Added clone of Get Star to the Tiger Heli driver [Barry]
  • +
  • Added ADPCM sound to Toramich in the Tiger Road driver [Barry]
  • +
  • Fixed DAC sound in Kabuki-Z in the TNZS driver [Barry]
  • +
  • Fixed inputs and added sound in bootleg of Toki in the Toki driver [Barry]
  • +
  • Fixed sound in Jumping Pop in Tumble Pop bootleg driver [Barry]
  • +
  • Fixed sound in Buccaneers and Kickle Cubele in the Vigilante driver [Barry]
  • +
  • Fixed orientation in Vulgus [Barry]
  • +
  • Fixed WWF WrestleFest (US bootleg) in WWF Wrestlefest driver [Barry]
  • +
  • Fixed sound in Magic Bubble in the Yun Sung 16 driver [Barry]
  • +
  • Fixed a crash when starting the Neo Geo driver from the command-line [Barry]
  • +
  • Removed a 64Mb rom limit on Neo Geo sprite ROM size, fixing kof98ae and maybe some others [Barry]
  • +
  • Fixed an app crash when exiting drivers using the taito_m68705 module [Barry]
  • +
  • Moved Atari and Kaneko16 into the misc categories and added a category for Irem to the game selection dialog [Barry]
  • +
  • Fixed nullifying pointers in BurnFree in the Burn memory module [Barry]
  • +
  • Tidied all drivers in the misc_post90s and misc_pre90s folders, and updated to use Burn Memory module and BURN_SND_CLIP macro [Barry]
  • +
  • Moved Kaneko Pandora code to it's own file [Barry]
  • +
  • Moved Air Buster driver to misc_post90s folder [Barry]
  • +
  • Changed sega_decode_317 in the System1 driver to support external use and removed the duplicated code in the Angel Kids driver [Barry]
  • +
  • Matched all sets to MAME 0.144u1 [Barry]
  • +
+ + +

v0.2.97.13

+

This version features what is effectively a new Neo Geo driver. The emulation should be at least as good as before, but now with added support for MVS Multislot and Neo Geo CD. The Neo Geo CD support is preliminary at this stage, compatibility is pretty good, but some games don't work currently.

+
    +
  • Neo Geo Updates
      +
    • Added support for Neo Geo MVS multi-slot emulation and Neo Geo CDZ [Barry, heavily based on some old code from Jan_Klaassen]
    • +
    • Changed the ISO+MP3 CD Interface module to ISO+WAV [CaptainCPS]
    • +
    • Added some demo roms to the Neo Geo driver [Barry]
    • +
    • Added support for the prototype sprite roms to the Neo Geo driver [Barry]
    • +
    • Fixed text layer tiles in kof10th [iq_132]
    • +
    • Added a hack to the sprite routines for Samurai Shodown RPG text boxes [iq_132]
    • +
    • Added prototype of Alpha Mission II to the Neo Geo driver [Barry]
    • +
    • Added prototype of Burning Fight to the Neo Geo driver [Barry]
    • +
    • Added prototype of King of the Monsters 2 to the Neo Geo driver [Barry, JacKc]
    • +
    • Fixed "most recent games" list when using Neo Geo multi-slot [Barry]
    • +
    • Added a module to identify Neo Geo CD games [CaptainCPS]
    • +
  • +
  • Ported H6280 CPU Core from MAME [iq_132]
  • +
  • Added module to support vector games [iq_132]
  • +
  • Added driver for Aztarac [iq_132]
  • +
  • Hooked up analog joystick and dial in Aztarac driver [Barry]
  • +
  • Added driver for games on Data East DECO16 hardware [iq_132]
  • +
  • Added clone of Guwange to the Cave driver [Barry]
  • +
  • Added alternate bootleg of Street Fighter II - champion edition Accelerator! to the CPS-1 driver [JacKc]
  • +
  • Added two clones of Battle Shark to the Taito-Z driver [Barry]
  • +
  • Updated all source code with checks for memory used before freeing and NULLing all allocated memory after freeing [Barry]
  • +
  • Optimised the Irem GA20 sound core [iq_132]
  • +
  • Changed the MS5205 stream buffer allocation to account for differing refresh rates, fixing the crash in the Double Dragon driver when exiting games [Barry]
  • +
  • Fixed some stability issues in the Cave drivers [Barry]
  • +
  • Fixed inputs in Robocop 2 in the DECO16 driver [Barry]
  • +
  • Fixed savestate support in the Taito-Z driver when no Z80 is present [Barry]
  • +
  • Fixed an issue where the state of Tatio games was being auto-saved when it shouldn't be [Barry]
  • +
  • Fixed screen clear code in Toaplan-1 games [Barry]
  • +
  • Fixed Sound Error in Battle Bakraid [Barry]
  • +
  • Fixed some stability issues in the Toaplan drivers [Barry]
  • +
  • Fixed dat file generation module to output the html entities for the characters <> [Barry]
  • +
  • Updated the description tag of the generated dat files to identify between arcade and Megadrive [Barry]
  • +
  • Fixed some duplicate game descriptions [Barry]
  • +
  • Removed a duplicate set of Demon World from the driver [Barry]
  • +
  • Removed bioses from the driver count in the game selection dialog [Barry]
  • +
  • Changed the background colour of clones in the game selection dialog to make them stand out a little bit more [Barry]
  • +
  • Matched all sets to MAME 0.143u9 [Barry]
  • +
  • Matched the Megadrive sets to MESS 0.143u8 [Barry]
  • +
  • Updated the help file to reflect above changes [Barry]
  • +
+ + +

v0.2.97.12

+

Note: This version has some changes to the Megadrive driver. The driver is now based on the MESS software list.

+

The game shortnames are prepended by md_ to differentiate them from the arcade games where conflicts occur. FB Alpha will look for your roms in the normal zip names, you do not need to create a new copy of the games and prepend md_. It is advisable to have the Megadrive roms in the seventh or eighth rom paths to avoid conflicts with arcade games. Support files will need to retain the md_ in order to avoid conflicts, however.

+

All Megadrive games are now enabled (except for Virtua Racing because the SVP isn't emulated), most should work, however, some may not.

+
    +
  • Megadrive Changes
    • +
    • Updated Megadrive driver based on MESS 0.143u7 software list [Barry]
    • +
    • Made the seventh rom path special like the eighth one so that Megadrive roms can be stored in one of the last two paths and still allow supplementary FB Alpha roms to be in a seperate path [Barry]
    • +
    • Made the short name in the game selection dialog slightly longer to accomodate the Megadrive short names [Barry]
    • +
    • Increased the maximum number for sek handlers to 10 [Barry]
    • +
    • Added better SRAM support and support for custom mappers as per MESS [Barry]
    • +
    • Removed menu option for making a datfile with both arcade games and Megadrive games, the two would conflict, and arcade and Megadrive dats need to be handled seperately [Barry]
    • +
    • Updated the dat file creation module to remove the md_ from the Megadrive shortnames [Barry]
    • +
    +
  • Added clone of Aquajack to the Taito-Z driver [Barry]
  • +
  • Added clone of Vigilante to the Vigilante driver [Barry]
  • +
  • Fixed music tempo and continuity in Item M90 and M92 drivers [iq_132]
  • +
  • Added option to the YM2413 to decrease volume and used it to correct sound in the Mitchell driver [Barry]
  • +
  • Fixed the gun inputs in Zombie Raid [Barry]
  • +
  • Fixed the support file path creation for the IPS folders on app init [Barry]
  • +
  • Fixed immediate update of Apply Patches checkbox in game selection dialog when applying IPS Patches [Barry]
  • +
  • Added ability to search the drivers short name as well as the description in the Game Selection dialog [Barry]
  • +
  • Made the Game Selection dialog search interactive and removed the Search button [Barry]
  • +
  • Made the Game Selection dialog choose the current loaded game if a game is currently loaded [Barry]
  • +
  • Fixed crash when (de)selecting auto-frameskip and using the DirectSound audio module [Barry]
  • +
  • Restored the uxtheme style for the application [Barry]
  • +
  • Matched all sets to MAME 0.143u7 [Barry]
  • +
+ + +

v0.2.97.11

+
    +
  • Readded the IPS Manager functionality, updating it to support x64 and the new PNG routines [Barry]
  • +
  • Added a search option to the Game Selection dialog [Barry]
  • +
  • Updated the help file to reflect above changes [Barry]
  • +
+ + +

v0.2.97.10

+
    +
  • Redesigned the game selection dialog [Barry]
  • +
  • Added a dialog to view roms and/or samples required by a driver to the game selection dialog [Barry]
  • +
  • Removed the incomplete Neo Geo multi-slot implementation [Barry]
  • +
  • Removed the "save decrypted C roms" functionality [Barry]
  • +
  • Removed the jukebox functionality and resources [Barry]
  • +
  • Removed support for datfiles other than the latest ClrMAME format [Barry]
  • +
  • Removed the package importer and resources [Barry]
  • +
  • Removed the menu themes and resources [Barry]
  • +
  • Removed skins and resources [Barry]
  • +
  • Removed the gamelist translation module and resources [Barry]
  • +
  • Removed icons support and resources [Barry]
  • +
  • Removed the favourites functionality and resources [Barry]
  • +
  • Removed the context menu from the game selection dialog [Barry]
  • +
  • Removed IPS Patch functionality and resources [Barry]
  • +
  • Removed the game information dialog and resources [Barry]
  • +
  • Removed unneeded support file paths and resources [Barry]
  • +
  • Removed IPS Patch functionality and resources [Barry]
  • +
  • Restructured source code and removed any unneeded modules [Barry]
  • +
  • Removed PNGlib and updated preview loading code to use libPNG [Barry, heavily based on some old code from Jan_Klaassen]
  • +
  • Updated preview loading code to allow interpolation on resizing [Barry, heavily based on some old code from Jan_Klaassen]
  • +
  • Fixed the localisation template support [Barry]
  • +
  • Tidied up the resource files [Barry]
  • +
  • Added flag to the makefile allowing X86 assembly code to not be built, and added support in the code to not build X86 assembly when defined [Barry]
  • +
  • Fixed sound rendering in the YM2151 module when not using the MMX routines [Barry]
  • +
  • Tidied up the source code to compile with Microsoft tools when building in an X64 environment [Barry]
  • +
  • Added an option in the makefile to build an X64 binary, and updated the VC makefile and source code to support it [Barry]
  • +
  • Added ability to change the volume of the YM2203 module and used it to bring down the volume in the 1943 driver [Barry]
  • +
  • Fixed FM Interpolation rendering routine in the YM2203 module [Barry]
  • +
  • Added support for the YM2610 module to mix the sounds into one stream (mono) and updated the Bonze Adventure, Darius 2, Operation Thunderbolt, Taito-B, Taito-Z and Welltris drivers to use it [Barry]
  • +
  • Added Super Chase to release builds as it works fine except for sound [Barry]
  • +
  • Fixed missing sounds in the 1943 driver [Barry]
  • +
  • Disabled the corrupt boot screen in Last Hope in the Neo Geo driver [Barry, with info from Johnboy]
  • +
  • Corrected default dip values in the PS2 datafile System 16B version of Bloxeed [Barry]
  • +
  • Fixed some rom sizes in the Irem M72 driver [Barry]
  • +
  • Updated the help file based on the above feature cull [Barry]
  • +
+ + +

v0.2.97.09

+
    +
  • Ported the ARM CPU core from MAME [iq_132] +
  • Ported the MSM5205 sound core from MAME, replacing the old core [iq_132]
      +
    • Updated the Asuka driver to use it [Barry]
    • +
    • Updated the Double Dragon driver to use it [Barry]
    • +
    • Updated the Street Fighter driver to use it [iq_132]
    • +
    • Updated the Taito Misc driver to use it, giving ADPCM sound in Darius [Barry]
    • +
    • Updated the Tecmo driver to use it [Barry]
    • +
  • +
  • Ported the ES8712 sound core from MAME [iq_132]
  • +
  • Updated the TMZ280B core to support missing sound modes [iq_132]
  • +
  • Tidied up the samples interface [Barry]
      +
    • Updated the DrvBurnStruct to support sample filename, and sample lists
    • +
    • Updated the sample module initialisation to use the BurnSampleInfo struct
    • +
    • Updated the Rally X driver to use the new code
    • +
    • Added the sample path to the Support Path dialog and the config file making it configurable
    • +
    • Added a Sample Info tab to the game information dialog
    • +
    • Added "uses samples from" info to the game information, game selection, and jukebox dialogs
    • +
    • Added sample support to the dat file writing module
    • +
  • +
  • Updated the zlib library to v1.2.5 [Barry]
  • +
  • Updated the libpng library to v1.5.4 [Barry]
  • +
  • Added regret's DirectInput8 module and updated it for FB Alpha, replacing the DirectInput7 module [Barry]
  • +
  • Removed dependency on dxguid lib since it is no longer available [Barry]
  • +
  • Added ability to compile without A68K, definable via BUILD_A68K makefile option [Barry]
  • +
  • Rewrote the Taito TC0100SCN module and updated all the drivers that used it, adding support for multiple screens and hopefully making it faster [Barry]
  • +
  • Added double width support to the TC0480SCP module [Barry]
  • +
  • Added multiple chip support to the PC080SN module [Barry]
  • +
  • Fixed sprite rendering order in Warrior Blade [Barry]
  • +
  • Added a memory management module to the burn library [iq_132]
  • +
  • Added support to the generic tiles module to decode single tiles [Barry]
  • +
  • Reduced the volume in the K053260 core to remove distortion and corrected the left and right channels [Barry, reported by Huggybaby]
  • +
  • Fixed Loop Address in Sega PCM Module, as per MAME 0.141u1, fixing sound in Super Monaco Grand Prix [Barry]
  • +
  • Added driver for Backfire [iq_132]
  • +
  • Added driver for Chack'n Pop [iq_132]
  • +
  • Added driver for Darius II (dual screen) and Warrior Blade [Barry]
  • +
  • Added driver for games on Data East Simple 156 System hardware [iq_132]
  • +
  • Added driver for Dynamite Duke [iq_132]
  • +
  • Added driver for games on Gaelco hardware [iq_132]
  • +
  • Added driver for games on Irem M62 hardware [Barry]
  • +
  • Added driver for games on Irem M63 hardware [iq_132]
  • +
  • Added driver for games on Irem M72 hardware [iq_132]
  • +
  • Added driver for games on Irem M90 hardware, replacing old driver [iq_132]
  • +
  • Added driver for games on Irem M92 hardware, replacing old driver [iq_132]
  • +
  • Added driver for Lord of Gun and Alien Challenge [iq_132]
  • +
  • Added driver for Marine Boy [kenshiro]
  • +
  • Added driver for Operation Thunderbolt [Barry]
  • +
  • Added driver for Pocket Gal Deluxe [iq_132]
  • +
  • Added Cave games to the PGM driver and made other improvements to the driver [iq_132]
  • +
  • Added some non-working clones to the PGM driver [JacKc]
  • +
  • Added driver for the S2650 based Pacman games [iq_132]
  • +
  • Added Fantasy Zone 2 to the Sega System 16B driver [Barry]
  • +
  • Added driver for games on Seta hardware [iq_132]
  • +
  • Added driver for Success Joe [iq_132]
  • +
  • Added driver for games on Taito-B hardware [iq_132]
  • +
  • Added driver for games on Tecmo System hardware [iq_132]
  • +
  • Added driver for Varia Metal [iq_132]
  • +
  • Added driver for World Cup '90 bootleg hardware [Barry]
  • +
  • Added driver for Xor World [iq_132]
  • +
  • Added The Pit to the Galaxian driver [Barry]
  • +
  • Added Triple Draw Poker to the Galaxian driver [Barry]
  • +
  • Added Puzzle Break to the Hyper Pacman driver [Barry]
  • +
  • Added a module for the Taito TC0180VCU tilemap chip [iq_132]
  • +
  • Added a module for the Tatio TC0640FIO I/O chip [Barry]
  • +
  • Ported MAME's Time Keeper module to FB Alpha [Barry]
  • +
  • Fixed some inputs in the Taito B driver [Barry]
  • +
  • Added Thunder Fox to the Taito F2 driver [Barry]
  • +
  • Added Operation Wolf 3, Slapshot and Top Speed to the Taito Misc driver [Barry]
  • +
  • Added Volfied to the Taito Misc driver [Barry]
  • +
  • Added bootleg of 1943 to the 1943 driver [Barry]
  • +
  • Added 2 clones to the 1943 driver [Barry]
  • +
  • Added clone of Armed Formation to the Armed Formation driver [Barry]
  • +
  • Added clone of Black Tiger to the Black Tiger button [Barry]
  • +
  • Added clone of Blood Bros. to the Blood Bros. driver [BisonSAS]
  • +
  • Added Koro Koro Quest and Crusher Makochan to the Cave driver [iq_132]
  • +
  • Removed fake region switches and added clones to Air Gallet, Mazinger Z and Pretty Soldier Sailor Moon in the Cave driver [Barry]
  • +
  • Added clone of 1941 to the CPS-1 driver [Barry]
  • +
  • Added bootleg of Cadillacs and Dinosaurs (Dinosaur Hunter) to the CPS-1 driver [Barry, JacKc]
  • +
  • Added 2 clones of Captain Commando to the CPS-1 driver [Barry]
  • +
  • Added clone of Dynasty Wars to the CPS-1 driver [Barry]
  • +
  • Added clone of Final Fight to the CPS-1 driver [Barry]
  • +
  • Added 2 clones of Forgotten Worlds to the CPS-1 driver [Barry]
  • +
  • Added 2 clones of King of Dragons to the CPS-1 driver [Barry]
  • +
  • Added clone of Knights of the Round to the CPS-1 driver [Barry]
  • +
  • Added bootleg of The Punisher to the CPS-1 driver [JacKc]
  • +
  • Added bootleg of Street Fighter 2 to the CPS-1 driver [Barry]
  • +
  • Added 2 clones of Street Fighter 2 to the CPS-1 driver [Barry]
  • +
  • Added clone of Street Fighter 2 Champion Edition to the CPS-1 driver [Barry]
  • +
  • Added clone of UN Squadron to the CPS-1 driver [Barry]
  • +
  • Added clone of Dungeons & Dragons: Tower of Doom to the CPS-2 driver [Barry]
  • +
  • Added clone of Eco Fighters to the CPS-2 driver [Barry]
  • +
  • Added clone of Gigawing to the CPS-2 driver [Barry]
  • +
  • Added clone of Marvel vs. Capcom to the CPS-2 driver [Barry]
  • +
  • Added clone of Ring of Destruction to the CPS-2 driver [Barry]
  • +
  • Added clone of Street Fighter Alpha to the CPS-2 driver [Barry]
  • +
  • Added clone of Street Fighter Alpha 2 to the CPS-2 driver [Barry]
  • +
  • Added 2 clones of Street Fighter Alpha 3 to the CPS-2 driver [Barry]
  • +
  • Added 3 clones of X-Men: Children of the Atom to the CPS-2 driver [Barry]
  • +
  • Added clone of X-Men vs. Street Fighter to the CPS-2 driver [Barry]
  • +
  • Added several Phoenix sets to the CPS-2 driver [Barry]
  • +
  • Added clones of Red Earth to the CPS-3 driver [Barry]
  • +
  • Added support to the CPS-3 driver for JoJo's Venture USA BIOS [Barry]
  • +
  • Added support to the CPS-3 driver for Street Fighter III Hispanic BIOS [Barry]
  • +
  • Added 2 clones of Street Fighter Zero to the CPS Changer driver [Barry]
  • +
  • Added 3 clones of Street Fighter Zero to the CPS Changer driver [JacKc]
  • +
  • Added clone of Double Dragon to the Double Dragon driver [Barry]
  • +
  • Added clone of Biomechanical Toy to the Gaelco driver [Barry]
  • +
  • Added clone of Amidar to the Galaxian driver [Barry]
  • +
  • Added clone of Defend the Terra Attack on the Red UFO to the Galaxian driver [Barry]
  • +
  • Added clone of Hot Shocker to the Galaxian driver [Barry]
  • +
  • Added 2 clones of Moon Cresta to the Galaxian driver [Barry]
  • +
  • Added clone of Moon Shuttle to the Galaxian driver [Barry]
  • +
  • Added clone of Scorpion to the Galaxian driver [Barry]
  • +
  • Added clone of Scramble to the Galaxian driver [Barry]
  • +
  • Added clone of Streaking to the Galaxian driver [Barry]
  • +
  • Added bootleg of Gyruss to the Gyruss driver [Barry]
  • +
  • Added clone of Parodius DA! to the Konami driver [Barry]
  • +
  • Added clone of Teenage Mutant Ninja Turtles to the Konami driver [Barry]
  • +
  • Added clone of Iron Clad to the Neo Geo driver [JacKc]
  • +
  • Added clone of Jockey GP to the Neo Geo driver [Barry]
  • +
  • Added clone of King of Fighters '97 to the Neo Geo driver [Barry]
  • +
  • Added clone of King of Fighters '98 to the Neo Geo driver [Barry]
  • +
  • Added Last Hope to the Neo Geo driver [Barry, Robert]
  • +
  • Added clone of Quiz Daisousa Sen to the Neo Geo driver [Barry, JacKC]
  • +
  • Added clone of Quiz King of Fighters to the Neo Geo driver [Barry, JacKC]
  • +
  • Added clone of Real Bout Fatal Fury Special to the Neo Geo driver [Barry, JacKC]
  • +
  • Added Oriental Legend Special Plus to the PGM driver[iq_132, info from CreamyMami]
  • +
  • Added clone of Prehistoric Isle to the Prehistoric Isle driver [Barry]
  • +
  • Added clone of Space Bomber to the Psikyo SH-2 driver [Barry]
  • +
  • Added clone of Fantasy Zone to the Sega System 16A driver [Barry]
  • +
  • Added clone of Shinobi to the Sega System 16A driver [Barry]
  • +
  • Added clone of Bloxeed to the Sega System 16B driver [Barry]
  • +
  • Added clone of Fantasy Zone to the Sega System 16B driver [Barry]
  • +
  • Added clone of Heavyweight Champ to the Sega System 16B diver [Barry]
  • +
  • Added the ISG bootlegs to the Sega System 16B driver [Barry]
  • +
  • Added clone of Desert Breaker to the Sega System 18 driver [Barry]
  • +
  • Added clone of Galaxy Force 2 to the Sega Y-Board driver [Barry]
  • +
  • Added clone of Rail Chase to the Sega Y-Board driver [Barry]
  • +
  • Added clone of Street Fighter to the Street Fighter driver [Barry]
  • +
  • Added clone of Armed Police Batrider to the Toaplan-2 driver [Barry]
  • +
  • Added clone of Dogyuun to the Toaplan-2 driver [Barry]
  • +
  • Added clone of Vigilante to the Vigilante driver [Barry]
  • +
  • Made the foreground layer in Air Buster transparent [Barry, reported by BisonSAS]
  • +
  • Fixed the background rendering in Anteater [Barry]
  • +
  • Tidied the dips in the Blood Bros. driver [BisonSAS]
  • +
  • Tidied up the dips, titles, and manufacturers in the Cave driver as well as fixing EEPROM config in Hotdog Storm and Metomoquester and fixing savestates [BisonSAS]
  • +
  • Made the Resale versions of CPS-1 games run at 12MHz [Barry]
  • +
  • Tidied up dips and added Unicode title to the Crash Race driver [BisonSAS]
  • +
  • Forced the Demon World driver to use the Musashi 68000 core [iq_132]
  • +
  • Fixed the Gun Smoke driver video and sound speed [Lantus]
  • +
  • Added unicode titles, fixed some inputs and dips, and corrected some resolutions in all of the Konami drivers [BisonSAS]
  • +
  • Fixed the sprite offset in the Konami Ultraman driver [BisonSAS]
  • +
  • Fixed inputs and dips and added Unicode titles to the Magical Cat Adventure driver [BisonSAS]
  • +
  • Fixed an error in the Metal Slug 5 (bootleg) driver initialisation [kenshiro]
  • +
  • Fixed inputs and added Unicode title to the Mogura driver [BisonSAS]
  • +
  • Labelled the HyperFlip button in Moon War [Barry]
  • +
  • Tidied up the Power Instinct driver fixing some Z80 handling, Z80 reads and writes, sound hardware handling and boosted the interleave to fix the sound [Barry, reported by BisonSAS]
  • +
  • Fixed a romsize in the Robocop driver [JacKc]
  • +
  • Correctly cleared the screen in the Seta2 driver, fixing Subsino logo in Penguin Brothers [Barry, reported by BisonSAS]
  • +
  • Added unicode titles to the Tumble Pop bootleg driver [BisonSAS]
  • +
  • Fixed dip switches in the Turbo Outrun driver [Barry]
  • +
  • Fixed inputs and dips and added Unicode titles to the Welltris driver [BisonSAS]
  • +
  • Corrected clocks in the Double Dragon driver [Barry]
  • +
  • Corrected clocks in World Cup 90 as per MAME 0.136u4 [Barry]
  • +
  • Added ability to adjust CPU speed in the World Cup 90 driver [Barry]
  • +
  • Added ability to adjust CPU speed in the Sega drivers [Barry]
  • +
  • Added ability to adjust CPU speed in the Megadrive driver [Barry, suggested by manliodp]
  • +
  • Fixed a psikyosh crash and implemented the graphics banking[iq_132]
  • +
  • Fixed rotated screenshots [BisonSAS, regret (FBAShuffle)]
  • +
  • Fixed the "include" implementation in the cheat file parser [BisonSAS]
  • +
  • Removed kof95a as it seems to be a bad dump [JacKc]
  • +
  • Excluded Neo Geo "decrypted C sets" from the build [Barry]
  • +
  • Added support to the Neo Geo driver for a new BIOS rom [Barry]
  • +
  • Corrected the Iron Clad V3 rom in the Neo Geo driver [JacKc]
  • +
  • Updated the Forgotton Worlds alt gfx set loading routine to support the new rom layout [Barry]
  • +
  • Updated the CPS-1 mappers as per MAME [Barry]
  • +
  • Updated the dat file writing module to ignore the CPS-3 driver when writing the ROM_VERIFY dat [Barry]
  • +
  • Fixed priorities in Magical Cat Adventure driver [iq_132]
  • +
  • Fixed sprites in Bloxeed, making it working [Barry]
  • +
  • Improvements to the M68705 core [iq_132]
  • +
  • Tidied up the dips and the driver for Batrider, Battle Garegga, Batsugun and Dogyuun [JackC]
  • +
  • Added 1360x768 to the auto-detect aspect ratio code [CaptainCPS]
  • +
  • Fixed the favorites feature with drivers longer than 8 characters [CaptainCPS]
  • +
  • Reverted back to the perl script for generating driverlist.h and amended it to support the changes to the BurnDriver struct since it was last used [Barry]
  • +
  • Tidied code to build without warning using GCC 3.4.5 and GCC 4.5.2 [Barry]
  • +
  • Updated the compile guides to work with the newest available tools [Barry]
  • +
  • Matched all sets to MAME 0.143u6 [Barry]
  • +
+ + +

v0.2.97.08

+
    +
  • Added a sample player to the Burn library to allow external samples to used with drivers [iq_132]
  • +
  • Added a module to display LEDs on screen [iq_132]
  • +
  • Ported MAME's M6805 core and added an interface for it to the burn library [iq_132]
  • +
  • Added an interface to the M68705 core for Taito games [iq_132]
  • +
  • Enabled the Y8950 emulation in fmopl.c and created a module for it in the burn library [Barry]
  • +
  • Fixed VSynch support in all blitters [CaptainCPS]
  • +
  • Added a RGB hex display to the Palette Viewer [Barry]
  • +
  • Added support to the System 16 FD1094 interface for multiple CPUs [Barry]
  • +
  • Added memory callback support to the HD6309 core interface [Barry]
  • +
  • Added custom tile size support to the Generic Tiles Rendering module [Barry]
  • +
  • Added generic rendering for games using transparency tables [iq_132]
  • +
  • Added support to the Namco Sound module for stereo sound and fixed the mono output [iq_132]
  • +
  • Added CUS30 handling to the Namco Sound module [iq_132]
  • +
  • Enabled m6803_internal_register_r in the M6800 CPU core [iq_132]
  • +
  • Added driver for Air Buster [iq_132]
  • +
  • Added driver for games on Angel Kids hardware [iq_132]
  • +
  • Added driver for Baraduke [iq_132]
  • +
  • Added driver for Egg Hunt [iq_132]
  • +
  • Added driver for Fairy Land Story [iq_132]
  • +
  • Added driver for Ginga NinkyouDen [iq_132]
  • +
  • Hooked up the Y8950 sound in Ginga NinkyouDen [Barry]
  • +
  • Added driver for games on Lady Bug hardware [iq_132]
  • +
  • Added driver for Markham [iq_132]
  • +
  • Added driver for Mogura Desse [iq_132]
  • +
  • Added driver for Pushman [iq_132]
  • +
  • Added driver for Sky Kid [iq_132]
  • +
  • Added driver for Speed Spin [iq_132]
  • +
  • Added driver for Asuka & Asuka and similar games on Taito hardware [iq_132 (thanks to JackC for testing)]
  • +
  • Added driver for Welltris [iq_132]
  • +
  • Added clone of 1942 to the 1942 driver [Barry]
  • +
  • Added clone of Arkanoid to the Arkanoid driver [Barry]
  • +
  • Enabled clones of Arkanoid that require the M68705 CPU [iq_132]
  • +
  • Added bootleg of Final Fight to the CPS-1 driver [Barry]
  • +
  • Added clone of Pang 3 to the CPS-1 driver [Barry]
  • +
  • Added Street Fighter 2 (Double K.O. Turbo II) bootleg to the CPS-1 driver [iq_132]
  • +
  • Added clone of Dark Stalkers to the CPS-2 driver [Barry]
  • +
  • Added clone of Dungeons & Dragons: Shadow Over Mystara to the CPS-2 driver [Barry]
  • +
  • Added clone of Hyper Street Fighter 2 to the CPS-2 driver [Barry]
  • +
  • Added clone of Mega Man 2 to the CPS-2 driver [Barry]
  • +
  • Added clone of Super Puzzle Fighter 2 Turbo to the CPS-2 driver [Barry]
  • +
  • Rewrote the Dec0 driver from scratch (currently preliminary) [Barry]
  • +
  • Added Dark Tower to the Double Dragon driver [Barry]
  • +
  • Added clone of Moon Cresta to the Galaxian driver [Barry]
  • +
  • Added clone of Scramble to the Galaxian driver [Barry]
  • +
  • Added WOW New Fantasia to the Gals Panic driver [BisonSAS]
  • +
  • Added clone of Ghosts n' Goblins to the Ghost's n' Goblins driver [Barry]
  • +
  • Added clone of X-Men to the Konami driver [Barry]
  • +
  • Added clone of Airwolf to the Kyugo driver [Barry]
  • +
  • Added clone of Last Duel to the Mad Gear driver [Barry]
  • +
  • Added clone of King of Fighters '95 to the Neo Geo driver [iq_132]
  • +
  • Added clone of Samurai Shodown II to the Neo Geo driver [Barry]
  • +
  • Added clone of Samurai Shodown IV to the Neo Geo driver [Barry]
  • +
  • Added Ironclad to the the Neo Geo driver [iq_132]
  • +
  • Added kof96ep, kof97pla, kf2k1pls, kf2k1pa, cthd2k3a, kf2k2plb, kf2k2plc, kf2k4pls, mslug5b, kof96cn, kof96ae, kof97cn, kof97xt, kof98ae and kf2k2ps2 to the Neo Geo driver [Barry]
  • +
  • Added Popeye-Man to the Pacman driver [Barry]
  • +
  • Added preliminary driver for Rally X [Barry]
  • +
  • Added clone of Alien Syndrome to the Sega System 16B driver [Barry]
  • +
  • Added clone of Super Hang-On to the Sega Hang-On driver (enabled in debug builds only because it doesn't work) [Barry]
  • +
  • Added clone of Mega Blast to the Taito F2 driver [Barry]
  • +
  • Enabled clones of Tiger Heli that require the M68705 core [iq_132]
  • +
  • Added Demon World, Fire Shark, Rally Bike, and Vimana to the Toaplan-1 driver [iq_132]
  • +
  • Added Knuckle Bash 2 to the Toaplan-2 driver [iq_132]
  • +
  • Added clone of Outzone to the Toaplan-1 driver [Barry]
  • +
  • PGM Changes [iq_132]
      +
    • 02-27-2010
        +
      • Added kov2a and kov2b (kov2b is disabled) partially dumped sets
      • +
      • Thanks to JackC for helping sort a few sets.
      • +
    • +
    • 12-05-2009
        +
      • Added Happy6in1 (XingXing)
      • +
      • Added newer 68k bios (XingXing)
      • +
      • Added fake dip switch to switch beween 68k bios versions
      • +
      • Added kovsh103 (XingXing)
      • +
      • Added martmastc102 (XingXing)
      • +
      • Added region dips for martmastc102
      • +
      • Added proper dump for demon front (alt) (XingXing)
      • +
      • Added several pgm bootleg/hacks from MAME Plus
      • +
      • Added proper dump for orlegendc
      • +
      • Labeled region dips as "fake" as they are really hacks since PGM games usually have their regions supplied by the protection devices.
      • +
    • +
  • +
  • Corrected the CPU clocks in the Outrun driver as per MAME 0.135u4 [Barry]
  • +
  • Fixed a memory issue when exiting the CPS-1 driver [iq_132]
  • +
  • Fixed a crash when loading games in the Blood Bros. driver [BisonSAS and iq_132]
  • +
  • Fixed graphics in My Angel 2 [iq_132]
  • +
  • Emulated the M68705 in Legend of Kage rather than simulate it [iq_132]
  • +
  • Added layer disable to the CPS-3 driver [iq_132]
  • +
  • Fixed CPS-3 sound synch when using non-standard frame rates [CaptainCPS]
  • +
  • Fixed a romname in mslug4nd [kenshiro]
  • +
  • Fixed init bug in Guardians in the Seta-2 driver [kenshiro]
  • +
  • Added UniCode titles and fixed some details in the Cross Pang driver [BisonSAS]
  • +
  • Fixed crash in the D-Con driver [BisonSAS and iq_132]
  • +
  • Corrected dipswitches in the F-1 Grand Prix driver [BisonSAS
  • +
  • Fixed graphics in Fantasia II (Less Explicit) in the Gals Panic driver [BisonSAS]
  • +
  • Fixed crash in Ultra Balloon (SunA16 driver) [Bruce Lee and iq_132]
  • +
  • Various fixes in the Tao Taido driver [BisonSAS]
  • +
  • Added a new support file importer module [CaptainCPS]
  • +
  • Added option to use a background image in the menu bar [CaptainCPS]
  • +
  • Updated the jukebox and improved Neo Geo support [CaptainCPS]
  • +
  • Converted the driver list generation perl script to C++ and changed the documentation output to HTML [CaptainCPS]
  • +
  • Fixed an issue when loading tracklists in the jukebox [CaptainCPS]
  • +
  • Updated the megadrive driver to the latest one generated from the database on barryharris.me.uk [Barry]
  • +
  • Matched all sets to MAME 0.136u3 [Barry]
  • +
  • Updated libpng to version 1.4.0 [Barry]
  • +
  • Fixed a MSVC compile issue with the latest libpng [CaptainCPS]
  • +
+ +

v0.2.97.07

+
    +
  • Ported YM2413 core from SMS Plus and added an interface for it [Barry]
  • +
  • Added a seperate timer to the YM3812 interface allowing the chip to be used with other FM chips and updated all the drivers that use it [Barry]
  • +
  • Added support to the AY8910 core to handle the ports outside of the init function, and updated the YM2203 interface to use them [iq_132]
  • +
  • Fixed a stupid bug I introduced in the K051649 core [Barry]
  • +
  • Added timer support for the M6502 CPU [iq_132]
  • +
  • Seperated the op code area for the M6502 CPU [iq_132]
  • +
  • Fixed cheat support in the SH-2 CPU core [iq_132]
  • +
  • Small fix to the Z80 core to reset the registers [iq_132]
  • +
  • Fixed typo in the HD6309 core as per MAME 0.132u4 [iq_132]
  • +
  • Added a palette viewer for games on Cave, CPS-1/2/3, Megadrive, Neo Geo, PGM, Psikyo and Toaplan hardware and any game using the generic tiles module, which covers most games [Barry]
  • +
  • Fixed the XML Dat file output to properly support ampersands in rom names [Barry]
  • +
  • Made the maximum rom name length 100 characters instead of 32 [Barry]
  • +
  • Added a warning to BurnTransferCopy when BurnTransferInit hasn't been called [iq_132]
  • +
  • Fixed an issue with reporting some sound options in the System Info dialog that came about when changing the sound interface to plug-ins [Barry]
  • +
  • Removed the active Z80 core from the System Info dialog as the ZET interface only supports one core [Barry]
  • +
  • Added support for Vista, Server 2008 and Windows 7 detection to the System Info dialog [Barry]
  • +
  • Added an Atari filter to the game selection dialog [Barry]
  • +
  • Added driver for Blood Bros. and Sky Smasher [iq_132]
  • +
  • Added driver for D-Con and SD Gundam Psycho Salamander no Kyoui [iq_132]
  • +
  • Added a preliminary driver for games on DEC-8 hardware [iq_132]
  • +
  • Added a preliminary driver for Gauntlet [Barry]
  • +
  • Added driver for games on Karnov hardware [iq_132]
  • +
  • Added driver for Konami Twin 16 hardware [iq_132]
  • +
  • Added Bells & Whistles and Sunset Riders to the Konami drivers [Barry]
  • +
  • Added Lightning Fighters, Punk Shot, Quiz Gakumon no Susume, Teenage Mutant Ninja Turtles - Turtles in Time, Thunder Cross II to the Konami drivers [iq_132]
  • +
  • Added driver for Mitchell hardware [Barry]
  • +
  • Added driver for games on NMK16 hardware [iq_132]
  • +
  • Added driver for games on Psikyo SH hardware [iq_132]
  • +
  • Added driver for Return of the Invaders [iq_132]
  • +
  • Added driver for scooter Shooter [iq_132]
  • +
  • Added Atomic Point and Snapper to the Sega System 16B driver [Barry]
  • +
  • Added driver for Speed Rumbler [iq_132]
  • +
  • Added preliminary driver for Toki [iq_132]
  • +
  • Added driver for Vendetta, press F2 whilst booting to pass the ROM test [iq_132]
  • +
  • Added driver for games on Yun Sung 16 hardware [iq_132]
  • +
  • Added driver for WWF Superstars [iq_132]
  • +
  • Added bootleg of Street Fighter 2 to the CPS-1 driver [Barry]
  • +
  • Added Street Fighter II - Champion Edition Accelerator! bootleg to the CPS-1 driver [Barry]
  • +
  • Added Street Fighter II Quicken Pt-I bootleg to the CPS-1 driver [Barry]
  • +
  • Added sf2m9, sf2m10, sf2m11 and sf2m12 to the CPS-1 driver [Barry]
  • +
  • Added clone of Dungeons & Dragons to the CPS-2 driver [Barry]
  • +
  • Added clone of Battle of Atlantis to the Galaxian driver [Barry]
  • +
  • Added a clone of Dambusters to the Galaxian driver [Barry]
  • +
  • Added Kamakazi III to the Galaxian driver [Barry]
  • +
  • Added various games and clones to the New Zealand Story driver [iq_132]
  • +
  • Added clone of Pacman to the Galaxian driver [Barry]
  • +
  • Added Phoenix Part 2 to the Galaxian driver [Barry]
  • +
  • Added clone of Space War S to the Galaxian driver [Barry]
  • +
  • Added clone of Strategy X to the Galaxian driver [Barry]
  • +
  • Added clone of Metal Slug 4 to the Neo Geo driver [Barry]
  • +
  • Added clone of Outrun to the Outrun driver [Barry]
  • +
  • Added a clone to the Shadow Force driver [Barry]
  • +
  • Added Back Fire to the Tecmo driver [iq_132]
  • +
  • Added clone of Hellfire to the Toaplan-1 driver [Barry]
  • +
  • Added clone of Battle Garegga to the Toaplan-2 driver [Barry]
  • +
  • Added clone of X-Men to the X-Men driver [Barry]
  • +
  • Fixed potential memory leak in the Tengai driver rom loading [kenshiro]
  • +
  • Fixed the palette decoding in Dambusters to work with the correct PROM dump [Barry]
  • +
  • Added Z-Rejection support to the K053245 module, fixing sprites in Bells & Whistles and Sunset Riders [iq_132]
  • +
  • Added a module for the Konami K053936 IC module [iq_132]
  • +
  • Added shadow support to the Konami IC chips where necessary [iq_132]
  • +
  • Fixed Cue Brick [Barry]
  • +
  • Fixed an issue with coin inputs in the 2 Player versions of Crime Fighters [iq_132]
  • +
  • Fixed the Haunted Castle driver [Rasek, iq_132]
  • +
  • Fixed an issue with the Konami Twin 16 driver when compiling with VC [Barry]
  • +
  • Added support for the new graphic roms in gradius2 [Barry]
  • +
  • Fixed savestates in the Gyrus driver [iq_132]
  • +
  • Fixed the sound in Scooter Shoorer [Barry]
  • +
  • Tidied up the Mad Gear driver to support the new sets and increased interleave which fixes the music [Barry]
  • +
  • Modified the Power Instinct driver to use the generic drawing routines [iq_132]
  • +
  • Added Mobile Suit Gundam EX Revue and the Sammy shooting games to the Seta2 driver [iq_132]
  • +
  • Fixed the gun inputs in the Sammy shooting games [Barry]
  • +
  • Added the ability to read from the X1-010 sound chip and hooked it up in the Seta2 driver, improving the sound [Barry]
  • +
  • Fixed memory leaks in the Shadow Force driver's graphic rom loading [kenshiro]
  • +
  • Tidied the Toki driver and added sound [Barry]
  • +
  • PGM Updates [iq_132] +
      +
    • Fixed kov2106 thanks to the FBA Shuffle team :) [iq_132]
    • +
    • Added a few small speedups +
        +
      • Only recalculate the whole palette when needed now rather than every frame [iq_132]
      • +
      • Clear all video buffers in one loop [iq_132]
      • +
    • +
    • Fixed a crash when doing line scroll (see kovsh intro - fire stage background) [iq_132]
    • +
    • Fixed sound after save state load [iq_132]
    • +
  • +
  • Megadrive Updates [Barry] +
      +
    • Fixed an issue with games' buggy sound programs expecting certain results back [Barry]
    • +
    • Added support for some custom banking cartridges [Barry]
    • +
    • Updated the web-based Megadrive driver database with the new games from HazeMD 0.14a [Barry]
    • +
    • Removed rom editing capability from the web form [Barry]
    • +
    • Updated the web-based Megadrive driver generator to support games with multiple roms [Barry]
    • +
    • Added a check to the driver generator to make sure any non-working parents are included in release builds if they have working clones [Barry]
    • +
  • +
  • Matched all sets to MAME 0.134u3 [Barry]
  • +
  • Changed the dat file output using the ROM_VERIFY compile-time flag to produce the XML datfile type [Barry]
  • +
  • Updated libpng to version 1.2.40 [Barry]
  • +
  • Updated the compile guides to work with the newest available tools [Barry]
  • +
+ +

v0.2.97.06

+

This version includes a big change in the Z80 CPU interface. Specifically MAME's Z80 core is now used for all games. This should give better results and make the program more portable. We have done a lot of testing but if you notice any new problems please let us know and we can fix them.

+

This version also includes changes in the EEPROM code and input assignment code. As well as the changed save states for the ZET interface, these render old config and save files pretty much useless. It is advised to delete the contents of the config\games folder before using this version. Savestates are a bit hit-and-miss at the moment anyway. I plan to pay some attention to savestates in the next version and hopefully boost compatibility.

+
    +
  • Fixed the ZET interface when used with MAME's Z80 CPU core and removed support for all other Z80 CPU cores [Barry]
  • +
  • Updated lots of drivers to work with the changes to the ZET interface [Barry]
  • +
  • Updated some more drivers to work with the ZET interface changes [iq_132]
  • +
  • Improved existing Konami IC chip emulation and added support for some new chips [iq_132]
  • +
  • Ported the K0051649, K053260 and K054539 sound cores from MAME [iq_132]
  • +
  • Fixed the K0051649, K053260 and K054539 sound cores sample rate support [Barry]
  • +
  • Added a seperate timer to the YM3526 interface allowing the chip to be used with other FM chips [Barry]
  • +
  • Added support for the M6801 CPU in the M6800 interface [Barry]
  • +
  • Finally, and I do mean finally fixed the bug in the RF5C68 core, giving full sound in Sega System 18 [Barry]
  • +
  • Fixed the issues with the YM2203 core [Barry]
  • +
  • Big update to the cheat interface supporting multiple CPUs [iq_132]
  • +
  • Added savestate support to the Namco Sound module [Barry]
  • +
  • Converted the Galaga driver to use the ZET interface and added savestate support [Barry]
  • +
  • Converted the Sega System 1 driver to use the ZET interface [Barry]
  • +
  • Converted the MC8123 Sega System 16B games to use the ZET interface [Barry]
  • +
  • Converted the games in the Galaxian driver that used a custom interface to use the ZET interface [Barry]
  • +
  • Fixed savestate support in the M6809 CPU interface [iq_132]
  • +
  • Fixed savestate support in the M6800 series CPU interface [Barry]
  • +
  • Replaced the EEPROM code with a port from MAME [iq_132]
  • +
  • Updated the Battle Bakraid, Cave, CPS-1, CPS-2, ESD 16, Kaneko 16, Midas, Space Gun and Zero Point 2 drivers to work with the new EEPROM code [Barry, iq_132]
  • +
  • Fixed problem with the low-pass filter in the DirectSound plugin [Barry]
  • +
  • Added lots of Konami games [iq_132]
  • +
  • Added driver for Bubble Bobble and clones [Barry]
  • +
  • Added driver for Arabian [iq_132]
  • +
  • Added a bootleg of SCI to the Taito Z driver [Barry]
  • +
  • Added a clone of Forgotten Worlds to the CPS-1 driver [Barry]
  • +
  • Added clone of The Combatribes [Barry]
  • +
  • Added clone of Final Star Force [iq_132]
  • +
  • Added clone of The Legend of Kage[iq_132]
  • +
  • Fixed the DAC sound in King & Balloon [Barry]
  • +
  • Fixed Mighty Monkey and clones and enabled in release builds [Barry]
  • +
  • Enabled the Kangaroo driver in release builds now that the ZET interface changes made it work [iq_132]
  • +
  • Added support for hardware specific input presets, cps.ini, Neo Geo.ini and pgm.ini [Barry]
  • +
  • Added a Save preset button to the input dialog to save the currently defined inputs into a hardware preset file [Barry]
  • +
  • Updated the help file with details of the new items in the Input Dialog [Barry]
  • +
  • Fixed some issues with saving and reading files for drivers with more than 8 characters in their name [Barry]
  • +
  • Fixed an issue when updating the previous games list with drivers with more than 8 characters in their name [Barry]
  • +
  • Widened the short gamename column in the selection dialog [Barry]
  • +
  • Disabled the rather annoying system beep in DEBUG builds [iq_132]
  • +
  • Matched all sets to MAME 0.131u3 [Barry]
  • +
+ +

v0.2.97.05

+
    +
  • Tidied source to compile cleanly with GCC 3.4.5, GCC 4.3.3 and the latest Microsoft SDKs [Barry]
  • +
  • Wrote compile guides for the above which are available on my website [Barry]
  • +
  • Replaced the readme.txt with a detailed Windows help file [Barry]
  • +
  • Replaced the whatsnew.txt with a HTML document and added a link to it from the help menu [Barry]
  • +
  • Updated libpng to the current version (1.2.35) [Barry]
  • +
  • Made a new higher quality icon, with support for the nice big vista icon [Barry]
  • +
  • Ported MAME's Konami CPU core [iq_132]
  • +
  • Fixed an issue with the M6809 interface [iq_132]
  • +
  • Fixed Konami core to compile with VC [Barry]
  • +
  • Added Signed Write support to the DAC core [Barry]
  • +
  • Added control over the volume of the DAC core [Barry]
  • +
  • Added option to control whether the DAC core adds to the current buffer or not [Barry]
  • +
  • Big update to the Megadrive driver [Barry] +
      +
    • Greatly improved timing +
        +
      • Changed the YM2612 to use the 68000 for timing since the Z80 can be disabled
      • +
      • Properly supported PAL
      • +
      • Updated the reset routine to support switching between regions
      • +
    • +
    • Changed to MAME's Z80 core - it works much better
    • +
    • Basic SRAM support
    • +
    • Added support for most games that require special init functions
    • +
    • General tidy-up and many small fixes
    • +
    • Most games now work - testing is under way to enable games that are working (see my site for details on how you can help this effort)
    • +
    • Updated to the latest driver generated from the database
    • +
  • +
  • Added driver for 1943 [Barry]
  • +
  • Added driver for F1 Grand Prix [iq_132]
  • +
  • Added driver for games on Fuuki FG-3 hardware [iq_132]
  • +
  • Added driver for Gyrus [iq_132]
  • +
  • Added driver for Haunted Castle [iq_132]
  • +
  • Added driver for Lethal Crash Race [iq_132]
  • +
  • Added driver for Vigilante and games on similar hardware [Barry]
  • +
  • Added clone of Chase HQ to the Taito Z driver [Barry]
  • +
  • Added clone of Mighty Pang to the CPS-2 driver [Barry]
  • +
  • Added clone of Night Warriors to the CPS-2 driver [Barry]
  • +
  • Added clone of Operation Wolf to the Taito Misc driver [Barry]
  • +
  • Added support for the Neo Geo Deck BIOS [Barry]
  • +
  • Made the Neo Geo BIOS select more intuitive [Barry]
  • +
  • Improved the PGM driver, see changes.txt in the PGM folder for full details [iq_132]
  • +
  • Simulated the protection in Oriental Legends Special/Super making it playable [XingXing]
  • +
  • Fixed background colours and added savestates to 1943 [iq_132]
  • +
  • Fixed an issue with some sprites in World Cup '90 [Barry]
  • +
  • Fixed text layer in Metal Slug 4 Plus [kenshiro]
  • +
  • Added XAudio2 Sound plugin, partially based on FBA Shuffle [Barry]
  • +
  • Fixed an issue with the Neo Geo driver flags, fixing Memory Cards and Button Macros [Barry]
  • +
  • Added the full range of button combinations to the Neo Geo macros [Barry]
  • +
  • Added macro support for the PGM driver [Barry]
  • +
  • Changed the parent filters in the selection dialog to behave in the expected way [Barry]
  • +
  • Fixed MAWS links [Barry]
  • +
  • Moved the FPS display in the DirectX 9 blitter to the top right [FBAShuffle]
  • +
  • Matched all sets to MAME 0.131 [Barry]
  • +
+ +

v0.2.97.04

+
    +
  • Moved Namco sound to it's own module and updated the Pac-Man driver [Barry]
  • +
  • Added driver for Galaga [Barry]
  • +
  • Added driver for Pass [iq_132]
  • +
  • Added a hack to get Knights of Valour 2 Plus working [XingXing]
  • +
  • Tidied up the SoftFX blitters [Barry] +
      +
    • Updated the Enhanced blitter to allow more filters
    • +
    • Added support to the ini file for long long integers to support the Enhanced blitter
    • +
    • Added hq2xS, hq3xS, hq2xBold, hq3xBold, EPXB and EPXC filters from SNES9X ReRecording
    • +
    • Added SuperEagle, 2xSaI, Super 2xSaI filters from VBA ReRecording
    • +
  • +
  • Fixed issue with board roms in ClrMAME XML DAT generation [Barry]
  • +
  • Changed ampersands in the ClrMAME XML DAT output to their HTML entity [Barry]
  • +
  • Some updates to the Megadrive driver via the online generator [nj7, JackC, arturf]
  • +
  • Fixed some rom sizes in non-working parents [Barry, pointed out by JackC]
  • +
  • Fixed license2rtf.pl to allow hyphens in URLs [Barry]
  • +
  • Matched all sets to MAME 0.129u6
  • +
+ +

v0.2.97.03

+
    +
  • Ported MAME's ARM7 CPU core and added an interface to it [iq_132]
  • +
  • Fixed some issues with the ARM7 code when compiled with VC [Barry]
  • +
  • Ported MAME's S2650 CPU core and added an interface for it [iq_132]
  • +
  • Added support for IRQ callbacks to the S2650 interface [Barry]
  • +
  • Added support to retrieve the PC from the S2650 interface [Barry]
  • +
  • Added support for hiscore.dat [Barry] +
      +
    • The default path is support\hiscores, and .hi files will be stored there
    • +
    • The path is configurable via the support files dialog
    • +
    • hiscore.dat should be placed in the path
    • +
    • Hi Scores are only loaded and saved if the option "Save high scores when supported" is enabled
    • +
    • Hi scores are only loaded and saved if a driver supports it (the various info dialogs will inform in the comments section if high scores are supported for a game)
    • +
    • Added support to the Galaxian and World Cup 90 drivers
    • +
  • +
  • Added S2650 support to the cheat and hiscore modules [Barry]
  • +
  • Added support for hq2xS and hq3xS filters from FBA Shuffle (hq3xS only built with VC) [Barry]
  • +
  • Added 2xPM LQ and 2xPM HQ to the SoftFX blitters [Barry]
  • +
  • Big update to the PGM driver (see driver for details) [iq_132, tested by JackC and Aquashark]
  • +
  • Added games on the S2650 CPU to the Galaxian driver [Barry]
  • +
  • Added clone of Super Cobra to the Galaxian driver [Barry]
  • +
  • Added clone of Dogyuun to the Toaplan2 driver [Barry]
  • +
  • Added clone of World Cup 90 to the driver [Barry]
  • +
  • Added driver for Diver Boy [iq_132]
  • +
  • Added driver for games on Armed Formation hardware [iq_132]
  • +
  • Added driver for games on Magical Cat Adventure hardware [iq_132]
  • +
  • Added driver for Sky Fox [iq_132]
  • +
  • Added driver for Got-cha Mini Game Festival [iq_132]
  • +
  • Updated EPOS driver, fixing Dealer [iq_132]
  • +
  • Added Warriors of Fate to the CPS Changer driver [iq_132]
  • +
  • Changed the Megadrive driver to be generated from a status database on my website [Barry]
  • +
  • Fixed sprite based Capcom logos in CPS-2 Phoenix games [Barry]
  • +
  • Fixed memory leak with CPS-2 games, noticed by kenshiro and Leaf [Barry]
  • +
  • Added savestate support to the Galaxian driver [Barry]
  • +
  • Fixed the default dips in Tiger Road and hooked up the correct dips in F1 Dream [Barry]
  • +
  • Corrected aspect ratio for Bank Panic [CaptainCPS]
  • +
  • Cleaned up the 4 En Raya, Ambush, Dotrikun, Minivader, Silkroad and Wall Crash drivers [iq_132]
  • +
  • Fixed an error in the selection dialog when pressing Cancel [CaptainCPS]
  • +
  • Corrected an issue with scaling some PNGs for the selection dialog [CaptainCPS]
  • +
  • Improved the Options tab in the selection dialog [CaptainCPS]
  • +
  • Stopped the selection dialog switching to the favourites tab when adding a game to your favourites [CaptainCPS]
  • +
  • Fixed the game information printed from the favourites game list [Barry]
  • +
  • Added new clrMame Pro XML dat file output [Barry]
  • +
  • Fixed rotated games when using the DirectX 9 blitter [fbashuffle]
  • +
  • Added FPS display to the DirectX 9 blitter [fbashuffle]
  • +
  • Matched all sets to MAME 0.129u5 [Barry]
  • +
+ +

v0.2.97.02

+
    +
  • Added a driver for games on Galaxian hardware, 177 new sets [Barry]
  • +
  • Added support for insane sample Galaxian sound sample hardware and the various AY8910 interfaces in the Galaxian driver [Barry]
  • +
  • Moved PPI8255 module to the burn folder so it can be accessed by all drivers [Barry]
  • +
  • Added support for a third PPI8255 [Barry]
  • +
  • Added driver for Aquarium [iq_132]
  • +
  • Added driver for Dark Seal [iq_132]
  • +
  • Added driver for games on Deniam hardware [iq_132]
  • +
  • Added driver for games on Midas hardware [iq_132]
  • +
  • Changed the left and right sound channels in the CPS-3 driver [Barry]
  • +
  • Fixed the speed-up hacks for Jojo's Venture [Barry]
  • +
  • Improved analog controls in the Sega drivers when used with analog devices [CaptainCPS]
  • +
  • Added some clones to the Toaplan2 driver [Barry]
  • +
  • Added some new Phoenix sets to the CPS-2 driver (provided by bonky0013) [Barry]
  • +
  • Some renames of roms in Neo Geo decrypted sets as reported by pmc2 [Barry]
  • +
  • Fixed the aspect ratio in the Arkanoid driver [CaptainCPS]
  • +
  • Added support to the Game Information dialog for Select, Versus, How To, Scores, Bosses and Game over previews [Barry]
  • +
  • Added configurable path support for the above new previews [Barry]
  • +
  • Fixed issue with selection dialog when clicking filters too fast [CaptainCPS]
  • +
  • Added buttons to the selection dialog for tasks in the context-sensitive menu [CaptainCPS]
  • +
  • Moved the options in the selection dialog to their own tab [CaptainCPS]
  • +
  • Tidied the selection dialog [CaptainCPS]
  • +
  • Tidied the rom and support path dialogs and made them less cumbersome [CaptainCPS]
  • +
  • Changed the PNG load functions to use PNGlib [CaptainCPS]
  • +
  • Added support for loading support files from zips [CaptainCPS]
  • +
  • Added filter for Galaxian hardware to the selection dialog [Barry]
  • +
  • Matched all set to MAME 0.129u3 [Barry]
  • +
  • nb, the source is now doule-zipped similar to MAME for better compression
  • +
+ +

v0.2.97.01

+
    +
  • Added driver for Black Tiger [iq_132]
  • +
  • Added driver for Block Out [iq_132]
  • +
  • Added driver for Blue Print [iq_132]
  • +
  • Added driver for Cross Pang [iq_132]
  • +
  • Added driver for Mug Smashers [iq_132]
  • +
  • Added driver for Pirates [iq_132]
  • +
  • Added driver for Tao Taido [iq_132]
  • +
  • Added clone of Double Dragon 3 to the Double Dragon 3 driver [Barry]
  • +
  • Added clone of Power Instinct to the Power Instinct driver [Barry]
  • +
  • Added Street Fighter 2 Rainbow Set 3 to the CPS-1 driver [Barry]
  • +
  • Applied fm.c fixes from MAME 0.128u2 [Barry]
  • +
  • Added support to Zet to get the DE register [iq_132]
  • +
  • Fixed the sound in Double Axle [Barry]
  • +
  • Corrected the clocks in Prehistoric Isle fixing the music tempo [Barry]
  • +
  • Fixed decryption for Street Fighter Zero 2 Alpha and clones [Barry]
  • +
  • Matched all sets to MAME 0.128u7 [Barry]
  • +
  • Changed the version string to include leading zeros in the final section [Barry]
  • +
+ +

v0.2.96.99

+
    +
  • Added driver for Contra [iq_132]
  • +
  • Added driver Funny Bubble [iq_132]
  • +
  • Added driver for Legend of Kage [iq_132]
  • +
  • Added driver for games on Legendary Wings hardware [iq_132]
  • +
  • Added driver for Son Son [iq_132]
  • +
  • Added Cue Brick to the Konami driver [Barry]
  • +
  • Added clone of Armored Warriors to the CPS-2 driver [Barry]
  • +
  • Added clone of Capcom Sports Club to the CPS-2 driver [Barry]
  • +
  • Added clone of Giga Wing to the CPS-2 driver [Barry]
  • +
  • Small speed-up in the generic tile handling, improving the speed slightly in lots of drivers [Barry]
  • +
  • Corrected the text rom size in Samurai Shodown V and Samuari Shodown V Special [Barry]
  • +
  • Updated the Neo Geo Bios roms [Barry]
  • +
  • Added support for the Samurai Shodown V bootleg [Barry]
  • +
  • Hooked up the region dip switch in the PCB version of Metal Slug 5 - this won't work until we have dumps of the actual PCB program roms though [Barry]
  • +
  • Corrected the road colours in Enforce [Barry]
  • +
  • Fixed sound in Ali Baba [iq_132]
  • +
  • Fixed an issue with icon handling in the favourites module [CaptainCPS]
  • +
  • Disabled the Neo Geo multislot menu item until such time it does something useful [Barry]
  • +
  • Matched all sets to MAME 0.128
  • +
+ +

v0.2.96.98

+
    +
  • Removed the keys for Neo Geo M1 decryption - the values are now derived from the rom, thanks to Haze and cyberwills [Barry]
  • +
  • Fixed a memory issue in the HD6309 and M6809 CPU interfaces [kev]
  • +
  • Allowed hi-res PNG images [CaptainCPS]
  • +
+ +

v0.2.96.97

+
    +
  • Added decryption of the Neo Geo M1 roms, thanks to Andreas Naive and Haze [Barry]
  • +
  • Added clone of Marvel vs Capcom to the CPS-2 driver [Barry]
  • +
  • Added clone of Tengai to the Psikyo driver [Barry]
  • +
  • Moved Cps1Draw() out of a loop resuling in a big speed up for CPS-1 [Barry]
  • +
  • Added a "Deselect All" button to the IPS Manager dialog [Barry]
  • +
  • Fixed an issue with the menu translation template [Barry]
  • +
  • Matched all sets to MAME 0.127u4 [Barry]
  • +
+ +

v0.2.96.96

+
    +
  • Ported MAME's M6809 CPU core [Barry]
  • +
  • Ported MAME's HD6309 CPU core [Barry]
  • +
  • Ported MAME's M6800, HD63701 CPU cores [Barry]
  • +
  • Added an interface to the M6809 core and added support for it to BurnTimer and the cheat module [Barry]
  • +
  • Added an interface to the HD6309 core and added support for it to BurnTimer and the cheat module [Barry]
  • +
  • Added an interface to the M6800 and family cores and added support for them to BurnTimer and the cheat module [Barry]
  • +
  • Added driver for Double Dragon and Double Dragon II [Barry]
  • +
  • Added driver for Ghouls & Ghosts [Barry]
  • +
  • Added driver for Renegade [Barry]
  • +
  • Added SNK16 driver [iq_132]
  • +
  • Added clone of The New Zealand Story to it's driver [iq_132]
  • +
  • Added analog inputs to the SNK16 driver [Barry]
  • +
  • Hooked up the sound CPU comms in the Power Instinct 2 driver [Barry]
  • +
  • Very big update to the Jukebox [CaptainCPS]
  • +
  • Rewrote favourites module - delete your old favorites.dat file [CaptainCPS]
  • +
  • Added support for icons in the gamelists [CaptainCPS]
  • +
  • Added options to configure vertical and horizontal full-screen resolutions seperately [CaptainCPS]
  • +
  • Fixed another bug when FBA was used under Vista [CaptainCPS]
  • +
  • Made the inputs dialog stop the sound properly when using the shortcut key [CaptainCPS]
  • +
  • Applied the dialog sound fix above to the dip switch and cheat dialogs [Barry]
  • +
  • Fixed a memory leak when loading PNGs [CaptainCPS]
  • +
  • Optimised the automatic support file download feature [CaptainCPS]
  • +
  • Matched all sets to MAME 0.127u2 [Barry]
  • +
+ +

v0.2.96.95

+
    +
  • Added driver for Zero Zone and Las Vegas Girl [iq_132]
  • +
  • Added a clone of Three Wonders to the CPS-1 driver [Barry]
  • +
  • Changed the FD1089 module to use the external keys [Barry]
  • +
  • Set CPS-3 back to 60fps [Barry]
  • +
  • Matched all sets to MAME 0.127u1 [Barry]
  • +
+ +

v0.2.96.94

+
    +
  • Fixed Windows Vista crash when opening the game selection dialog [CaptainCPS]
  • +
  • Added Missing In Action to the TMNT driver [Barry]
  • +
  • Removed an unnecessary array in sys16_run.cpp reducing the exe size [Barry]
  • +
+ +

v0.2.96.93

+
    +
  • Added support for the K007232 sound chip [Barry]
  • +
  • Added support for the K051960 and K052109 gfx chips [Barry]
  • +
  • Rewrote the TMNT driver which is now fully working [Barry]
  • +
  • Added driver for Commando and clones [Barry]
  • +
  • Added ESD16 driver [iq_132]
  • +
  • Added NMG5 driver [iq_132]
  • +
  • Added Tecmo driver [iq_132]
  • +
  • Added SunA16 driver [iq_132]
  • +
  • Added Kangaroo driver to debug builds [iq_132]
  • +
  • Added daimakr2 to the CPS-1 driver [Barry]
  • +
  • Added snowbrod to the Snow Bros. driver [Barry]
  • +
  • Added sound to the Pacman driver and fixed some issues with the default inputs [Barry]
  • +
  • Added support for the YM3562 sound chip [Barry]
  • +
  • Added the YM3526 sound to bestbest in the SunA16 driver [Barry]
  • +
  • Added DAC support to Stratovox [iq_132]
  • +
  • Corrected the refresh rate in the CPS-1 driver [Barry]
  • +
  • Changed the refresh rate in the CPS-3 driver [Barry]
  • +
  • Imported fixes from MAME 0.126u5 for fm.c [Barry]
  • +
  • Reduced DAC volume in fm.c for YM2612 matching MAME 0.127 [Barry]
  • +
  • Marked the fake CHD CPS-3 sets as hacks so they can be filtered out [Barry]
  • +
  • Fixed an issue with cheats in Z80 (ZET) based games [Barry]
  • +
  • Added a feature to auto-download support files [CaptainCPS]
  • +
  • Merged all the LoadPNG() calls [CaptainCPS]
  • +
  • Added favourite gamelist support [CaptainCPS]
  • +
  • Allowed the recent gameslist to cycle games currently in the list [CaptainCPS]
  • +
  • Fixed issues with mouse events on the game window [CaptainCPS]
  • +
  • Added zlib/libPNG to FBA source, they are now compiled rather than using pre-compiled libraries [CaptainCPS]
  • +
  • Some updates to the minGW Win32 header file allowing Win32 API Versions 3.8+ to be used, and also to add support for some new functionality to older versions[Barry, CaptainCPS]
  • +
  • Added a filter for Konami games [Barry]
  • +
  • Matched all sets to MAME 0.127 [Barry]
  • +
+ +
From this point forward, all releases are handled by Barry and each individual contribution is labelled.
+ +

v0.2.96.92

+
    +
  • CaptainCPS readded netplay and removed the dependancy on any external dlls - use them at your own risk
  • +
  • Fixed a problem with the SuperScale filter on nVidia gfx cards
  • +
  • Merged in CaptainCPS's improvements to the game selection dialog
  • +
  • Fixed a problem with the game information dialog displaying incorrect images
  • +
  • Updated the romcenter dat module to support the latest romcenter
  • +
  • Imported fixes from MAME 0.126u4 for fm.c
  • +
  • Added a flag for MVS Cartidges and changed hardware description output
  • +
  • Matched all sets to MAME 0.126u4
  • +
+ +

v0.2.96.91

+
    +
  • Added the 2xPM filter to the softfx filters with help from CaptainCPS
  • +
  • Added ElSemi's SuperScale and SuperScale75 filters
  • +
  • Made the IPS Manager fallback to Simplified Chinese as a last resort as this is the reference language for the MAME Plus IPS collection
  • +
  • Made the IPS Manager description vertically scrollable for long descriptions and reorganised the dialog
  • +
  • Added CaptainCPS's auto monitor aspect ratio code
  • +
  • Added driver for Unico games
  • +
  • Moved the drawing code in CPS-1/CPS-2 to happen after the VBLANK IRQ - this shouldn't cause any problems but if you see anything that didn't happen in previous builds let us know
  • +
+ +

v0.2.96.90

+
    +
  • Burner (interface) changes +
      +
    • Added board type, genre and family filters to the game selection dialog +
        +
      • Updated all drivers with the new flags
      • +
      • Amended the relevant dialogs to display the new genre and family information
      • +
      • Added the genre and family flags to the -listextrainfo output
      • +
    • +
    • Added gamelist localisation functionality +
        +
      • It works in much the same way as the UI localisation, beware though, that if you have a large file it can take some time to start the program, try and keep the file small and with only the titles you want to translate
      • +
      • Maximum titles to translate is currently set at 5000
      • +
      • The advantage of doing it this way is that the whole program benefits from translated titles, not just certain parts and the speed hit is only felt once rather than every time a title is retrieved
      • +
      • Obviously this only works with UNICODE build
      • +
    • +
    • Fixed some issues with clicking behind some dialog boxes
    • +
    • Fixed a problem with the config file, allowing multi-byte paths to be specified
    • +
    • Double clicking on cheats in the dialog now selects the next option, thanks to sho
    • +
    • Changed the menu in the game selection dialog to a basic menu
    • +
    • Increased the width of the info boxes in the game selection dialog to use all available space (and not crop text unnecessarily)
    • +
  • +
  • Burn (emulation) changes +
      +
    • Hooked up the SN76496's in Van-Van Car
    • +
    • Finished up sf2m13 thanks to a small patch posted by iq_132 years ago
    • +
    • Added various homebrew games and demos (can be filtered out if you don't want to see them)
    • +
    • Added various decrypted C sets to the Neo Geo driver (can be filtered out if you don't want to see them)
    • +
    • Fixed a rom size issue in 8ballact
    • +
    • Matched all sets to MAME 0.126u3
    • +
  • +
+ +

v0.2.96.89

+
    +
  • Added IPS support via a manager dialog. +
      +
    • Right click on the game list, open the manager, enable the patches you want, they are saved to a config file, then right click and play with your saved patches
    • +
  • +
  • Fixed a problem with the saving of config files where the game title has unicode in it
  • +
  • Added iq_132's Street Fighter driver
  • +
  • Seperated the pacman driver from the misc section
  • +
  • Removed some CPS-1 hacks
  • +
+ +

v0.2.96.88

+
    +
  • Fixed an issue with the monitor aspect radio buttons
  • +
  • Various fixes to the themed menus
  • +
  • Added themed menus to the game selection dialog
  • +
  • Prevented modeless menus being used with themes
  • +
  • Added options to view details in MAWS, CAESAR, and progretto EMMA to the game selection context menu
  • +
  • Added PNG support to the place holder image
  • +
  • Added option to choose skins to the Misc menu
  • +
  • Improved the localisation support for the game selection dialog and the game information dialog
  • +
  • Added "Enable VSync" to the video menu
  • +
  • Matched all sets to MAME 0.126u2
  • +
+ +

v0.2.96.87

+
    +
  • Added dynamic video size switching to the core
  • +
  • Merged in CaptainCPS's menu themes code and added the options to the misc menu (disabled by default)
  • +
  • Merged in kev's and oopswares changes to zet and added CZ80 to the source distribution
  • +
  • Fixed an issue causing the preview image not to display on program start when the Enhanced blitter was enable
  • +
  • Fixed an issue with localisation support and added an option to reset to UI default language
  • +
  • Changed the hotkeys for cheat search to be used with Ctrl
  • +
  • Added support for the widescreen mode in Street Fighter III 2nd Impact
  • +
  • Added a fake dipswitch to Street Fighter III for widescreen since the game seems to support it
  • +
  • Added extracted roms to all CPS-3 sets (noone is likely to port CHD support just for CPS-3 which already works anyway)
  • +
  • Added fake dip hack to make Red Earth and War Zard work
  • +
  • Added sf2m8 to release builds
  • +
  • Added tigerhb1 to the Tiger Heli driver
  • +
  • Fixed a potential crash in the ICS2115 reset routine (spotted by iq_132)
  • +
  • Matched all sets to MAME 0.126u1
  • +
+ +

v0.2.96.86

+
    +
  • Burner (interface) changes +
      +
    • Added a game information dialog to burner
    • +
    • Tidied up the game selection dialog and seperated Kaneko 16 and Psikyo
    • +
    • Added a context menu to the game selection dialog
    • +
    • Added a most recently played games menu item
    • +
    • Changed the roms dir config dialog to support upto 8 paths
    • +
    • Fixed an issue with the roms dir config dialog that didn't let the user clear an entry
    • +
    • Added the roms dir config dialog to the Misc menu
    • +
    • Added a dialog to configure support files (previews, titles, flyers, marquees, controls, cabinets, pcbs, cheats and history) and added it to the Misc menu
    • +
    • Added an option to the Misc menu to stop FBA playing with the Num Lock status (don't use this if you use a Hotrod or X-Arcade stick)
    • +
    • Added an option to the Video menu to auto-switch to full screen after loading a game from the selection dialog
    • +
    • Added iq_132s improvements to the cheat system +
        +
      • Adds support for Nebula/Kawaks cheat dats
      • +
      • Adds limited (although most cheats work) support for the old format MAME cheat.dat file
      • +
      • Adds cheat support to drivers using the ZET interface, or NEC, SH-2 and M6502 CPUs
      • +
    • +
    • Added a basic cheat search engine
    • +
    • Added a jukebox player - this is very preliminary and only supports WWF Wrestlefest for now (it has many problems for now)
    • +
    • Added a menu item to write decrypted C Neo Geo roms to disk
    • +
    • Various little GUI fixes/improvements
    • +
  • +
  • Burn (emulation) changes +
      +
    • Merged in Oopsware's changes to the ZET interface improving support for MAME's Z80 emulator - some things are still broken though so DOZE is still the default
    • +
    • Added a function to the CPU interfaces to return the active CPU
    • +
    • Fixed a screen clearing issue in the CPS-1 and CPS-2 drivers when not using a 16-bit colour depth
    • +
    • Added various bootlegs to the CPS-1 driver in various states of working and attempted to differentiate between the good, the bad and the ugly (dumps)
    • +
    • Added offset support to the CPS-1 scroll layers
    • +
    • Added a flag to define whether or not CPS-1 sprite rendering should happen in reverse
    • +
    • Fixed an issue with rom loading in the sf2yyc driver
    • +
    • Got the sf2m3 set working and the sf2m1 set almost working
    • +
    • Added "Phoenix Edition" sets to the CPS-2 driver
    • +
    • Changed to iq_132s current Neo Geo driver (thanks to iq_132 for updating it)
    • +
    • Enabled the decrpyted C Neo Geo clones and bootlegs from Kawaks
    • +
    • Added two clones of Night Striker to the Taito driver
    • +
    • Changed some dip switches in the Double Dragon 3 driver
    • +
    • Added Wonder League '96 to the Tumble Pop bootleg driver
    • +
    • Updated dip switches in Wonder League Star and Jumping Pop
    • +
    • Added the 16-bit only flag to the megadrive games - fixes rendering issues in the basic blitters
    • +
    • Added iq_132s Vulgus driver
    • +
    • Matched all sets to MAME 0.126
    • +
  • +
+ +

v0.2.96.85

+
    +
  • Added Mazinger Z, Metamoqester, Power Instinct 2 and Power Instinct Legends to the Cave driver
  • +
  • Lagged the sprite palette in all CPS-2 games - fixes issue in ssf2 attract
  • +
  • Tidied up the CPS-2 split graphics rom loading
  • +
  • Properly fixed the qadj ninja sprite bug without resorting to hacks
  • +
  • Changed the 68000 clock frequency in later CPS-1 games
  • +
  • Various fixes to the Double Dragon 3 / Combatribes driver
  • +
  • Added an Italian bootleg of The Combatribes to the ddragon3 driver
  • +
  • Added clone of Turbo Outrun and clone of Alien Storm to the Sega drivers
  • +
  • Added iq_132s Bionic Commando driver
  • +
  • Added iq_132s Ninja Gaiden driver
  • +
  • Matched all sets to MAME 0.125u6
  • +
+ +

v0.2.96.84

+
    +
  • Added module to emulate the TC0280GRD/TC0430GRW Taito roz layer chips
  • +
  • Added support to the TC0100SCN module for double width rendering
  • +
  • Added support to the TC0100SCN and TC0110PCR emulation for multiple chips
  • +
  • Fixed priorities in Metal Black
  • +
  • Fixed the CPS-1 palette and added screen clearing to the last palette entry
  • +
  • Fixed a glitch in the ninja's sprite animation in qadj in the CPS-1 driver
  • +
  • Added support for split CPS-2 graphics roms
  • +
  • Added rent version of Capcom Sports Club to the CPS-2 driver
  • +
  • Added clone of Mighty Pang to the CPS-2 driver
  • +
  • Added Hotdog Storm to the Cave driver
  • +
  • Added iq_132s The Legend of Silkroad driver
  • +
  • Added BisonSAS's fixes to the CPS-3 driver
  • +
  • Added proper screen clearing to the Final Star Force driver
  • +
  • BisonSAS added various unicode titles and dip switches to 1943
  • +
  • Matched all sets to MAME 0.125u4
  • +
+ +

v0.2.96.83

+
    +
  • Added a module to control the Taito IC chips in a more efficient way
  • +
  • Added a module to do all the common Taito functions and tidied the drivers
  • +
  • Rewrote the PC080SN and PC090OJ emulation adding support for row scroll, double width and other features
  • +
  • Added tile banking support to the TC0100SCN emulation
  • +
  • Added support for configurable bit-depths to the TC0100SCN emulation
  • +
  • Added palette offset support to the TC0480SCP emulation
  • +
  • Added driver for Darius
  • +
  • Added Dead Connection, Dino Rex, Growl, Koshien, Liquid Kids, Mahjong Quest, Mega Blast, Metal Black, Ninja Kids, Solitary Fighter and various quiz games to the Taito F2 driver
  • +
  • Rewrote the Operation Wolf, Rainbow Islands and Rastan drivers to support the new Taito IC module
  • +
  • Added Jumping and the original versions of Operation Wolf to the Taito PC080SN & PC090OJ based driver
  • +
  • Rewrote the Taito X driver to support the new Taito IC module
  • +
  • Added Balloon Brothers, Gigandes and Last Striker to the Taito X driver
  • +
  • Added iq_132s Dr. Tomy driver
  • +
  • Added iq_132s Exed Exes driver
  • +
  • Added proper screen clearing to the Hyper Pacman driver
  • +
  • Fixed a small bug in the ClrMAME dat generation with missing quotes
  • +
  • Matched all sets to MAME 0.125u2
  • +
+ +

v0.2.96.82

+
    +
  • Added driver for Taito F-2 hardware supporting Final Blow, Football Champ, Gun & Frontier, Liquid Kids and Super Space Invaders '91
  • +
  • Added tilemap flip support to the TC0100SCN emulation
  • +
  • Added priority map support to the TC0100SCN emulation to allow sprite blending in the Taito F2 driver
  • +
  • Added support to the CPS-1 driver for loading stars from alternate format graphics roms
  • +
  • Corrected all dips in the CPS-1 driver
  • +
  • Updated mappers and configs in the CPS-1 driver to match MAME
  • +
  • Big tidy up of the CPS-1 and CPS-2 drivers
  • +
  • Added dynwaru and ffightj2 to the CPS-1 driver
  • +
  • Added clone of Street Fighter Alpha 2 to the CPS-2 driver
  • +
  • Added iq_132s driver for Pirate Ship Higemaru
  • +
  • Updated megadrive driver to nganiere's which fixes some game names
  • +
  • Matched all sets to MAME 0.125
  • +
+ +

v0.2.96.81

+
    +
  • Added support for the TC0480SCP Taito tilemap controller
  • +
  • Rewrote the System 16 tile rendering to allow proper col and row scroll and also support alternate tilemap selection
  • +
  • Added Double Axle to the Taito Z driver
  • +
  • Added 1942w to the 1942 driver
  • +
  • Added more games to the System 1 driver
  • +
  • Added iq_132s Green Beret driver
  • +
  • Updated the CPS-1 mappers as per MAME
  • +
  • Corrected clock in Varth
  • +
  • Corrected clocks in the Kyugo driver as per MAME
  • +
  • Corrected sprite positioning in the Kyugo driver
  • +
  • Added a feature allowing users to go to fullscreen and back by double-clicking
  • +
  • Added command line option -listextrainfo
  • +
  • Fixed compile errors when using the MAME Z80 core with the Zet interface
  • +
  • Updated the Mole, Green Beret, Pooyan and Gun Smoke drivers with BisonSAS' changes
  • +
+ +

v0.2.96.80

+
    +
  • Ported MAME's Z80 core to FBA
  • +
  • Hooked up MAME's Z80 core in the System 16 games that use MC-8123 encryption, sound now works in these games
  • +
  • Hooked up MAME's Z80 core in the Sega System 1 games, encrypted games now work
  • +
  • Added more games to the Sega System 1 driver
  • +
  • Changed the Sega System 1 drivers to appear in the Sega games list
  • +
  • Got the YM2151 sound working in Cotton
  • +
  • Added support for the UPD7759 sound chip
  • +
  • Hooked the UPD7759 chip up in the System 16B driver
  • +
  • Hooked the UPD7759 chip up in the prehisle driver
  • +
  • Hooked the UPD7759 chip up in the tmnt driver
  • +
  • Rewrote the Sega PCM support - solves quite a few problems, particuarly in enduror, outrun and smgp
  • +
  • Fixed an issue in the Sega System X driver which caused missing sounds in abcop and smgp
  • +
  • Fixed bug in the YM2612 emulation when more than one chip is emulated
  • +
  • Changed the CPS-1 rendering code to use the mapper tables from MAME
  • +
  • Added smgpja to the X-Board driver
  • +
  • Added shinobi4 to the System 16B driver
  • +
  • Added ledstrm2 to the madgear driver
  • +
  • Added command line options, -listinfowithmd and -listinfomdonly
  • +
  • Fixed the version output in dat files
  • +
  • Fixed bug where any rom errors weren't reported
  • +
  • Matched all sets to MAME 0.124u3
  • +
+ +

v0.2.96.79

+
    +
  • Corrected sound in the tnzs driver
  • +
  • Correctly fixed coins in the wc90 driver
  • +
  • Enabled Tazmania in the megadrive driver (it works and I like it :) )
  • +
  • Added support to the FM core interfaces for sound mixing
  • +
  • Removed kaillera support. The client can be removed and probably should be due to being a potential security risk. Left netplay, chat, etc. code in the program so it has potential to be used with a different netplay system.
  • +
+ +

v0.2.96.78

+
    +
  • Added oopsware's Picodrive Megadrive driver port and tidied up and improved
  • +
  • Started to go through Megadrive games and enabling ones that work in release builds. Only got to letter B and checked my favourites!
  • +
  • Added iq_132s Funky Bee driver
  • +
  • Added iq_132s Pooyan driver
  • +
  • Ported MAME's I8039 core to FBA
  • +
  • Added support for DAC sound
  • +
  • Hooked up the I8039 and DAC in System 16A to add voice support to the driver
  • +
  • Added gpilotsh and samshoh to the Neo Geo driver
  • +
  • Updated the SN7649 emulator to determine whether to add to the sound buffer or not
  • +
  • Removed the AY8910 part of the YM2612 emulation since it's not needed
  • +
  • Fixed sound in 1943
  • +
  • Fixed sound in Gunsmoke
  • +
  • Changed the default DAT file handling to not include Megadrive games
  • +
  • Added menu option to write DATs including Megadrive games
  • +
+ +

v0.2.96.77

+
    +
  • Added driver for Taito Z hardware
  • +
  • Added oopsware's Raiden driver and updated the nec core and vez module
  • +
  • Retidied the nec core and vez module
  • +
  • Added iq_132s Gun Smoke driver
  • +
  • Added iq_132s Scrambled Egg driver
  • +
  • Changed the M6502 core to Marat's with the interface wrote by kev
  • +
  • Added kev's m90 driver and his updates to the m92 driver to debug builds
  • +
  • Tidied the m90 and m92 drivers and corrected the gfx decoding in the m90 driver
  • +
  • Updated Dec0 drivers to kev's latest version
  • +
  • Updated Jack the Giantkiller driver to the iq_132s latest version
  • +
  • Made the "In Game" tab the default on the game selection dialog
  • +
  • Added a checkbox for Taito to the game selection dialog
  • +
  • Changed some names to prevent duplicate descriptions
  • +
  • Matched all sets to MAME 0.124u1
  • +
+ +

v0.2.96.76

+
    +
  • Added driver for games on Tumble Pop bootleg hardware
  • +
  • Tidied the System 1 driver and enabled working sets in normal builds
  • +
  • Added support for the SN76496 family of sound chips
  • +
  • Added sound to the Mr. Do driver
  • +
  • Added sound to the Bank Panic driver
  • +
  • Fixed missing music in Combatribes
  • +
  • Fixed a compile issue with VC in the Bank Panic and New Zealand Story drivers
  • +
  • Fixed an issue in VC builds with inputs not working in various drivers
  • +
  • Fixed a bug in the Mysterious Stones driver with AY8910 memory allocation
  • +
  • Corrected the ZetBc call in the 1943 driver making it playable (but still preliminary)
  • +
  • Updated the Jack the Giantkiller driver to iq_132s latest release
  • +
  • Updated the dec0 and tmnt drivers to the latest versions released by kev
  • +
  • Matched all sets to MAME 0.124a
  • +
+ +

v0.2.96.75

+
    +
  • Added driver for Double Dragon 3 / Combatribes
  • +
  • Added driver for WWF Wrestlemania
  • +
  • Added driver for Kyugo Z80-based hardware
  • +
  • Updated the pacman driver to the latest version released by iq_132
  • +
  • Added iq_132s Bank Panic driver
  • +
  • Added iq_132s Mr. Do driver
  • +
  • Added iq_132s Mysterious Stones driver
  • +
  • Added iq_132s The New Zealand Story driver
  • +
  • Added clone of Real Bout Fatal Fury to Neo Geo driver
  • +
  • Added clone of Metal Slug 5 to Neo Geo driver
  • +
  • Added clone of Dungeons & Dragons: tower of doom to the CPS-2 driver
  • +
  • Matched all sets to MAME 0.123u4
  • +
+ +

v0.2.96.74

+
    +
  • Updated the CPS-3 driver to include Oopsware's latest fixes
  • +
  • Fixed a problem with the size of m1 rom in Metal Slug 5
  • +
+ +

v0.2.96.73

+

Thanks go to the neosource forum regulars for a lot of this stuff. iq_132 has +written many drivers for older games, and Oopsware has contributed some impressive +drivers too. CaptainCPS and KOF2112 have also tidied up some things. This list +is from memory and some stuff is sure to be missing. Here's what's new anyway;

+ +
    +
  • Added a generic tiles decoding routine and updated various drivers to use it
  • +
  • Added support for 32x32 tiles in the generic tile rendering module
  • +
  • Added support for multiple YM2203s to the YM2203 interface
  • +
  • Updated all sets to match MAME 0.123u1
  • +
  • Tidied up all source code to compile cleanly for all builds (unicode, non-unicode, debug, non-debug)
  • +
  • Added support for M6502 CPU
  • +
  • Added support for SH-2 CPU
  • +
  • Added support for NEC V30 family CPU
  • +
  • Seperated misc drivers into "Misc (pre 90s)" and "Misc (post 90s)"
  • +
  • Moved some common sound cores into the burn folder
  • +
  • Added various clones and fixed some little issues in various games
  • +
  • Added driver for Madgear and Last Duel
  • +
  • Added driver for 1942
  • +
  • Added preliminary driver for 1943 and added support to the Zet interface to get the BC register
  • +
  • Added Oopsware's CPS-3 driver
  • +
  • Added various drivers by iq_132
  • +
  • Cleaned up the drivers by iq_132 (seperated into Misc pre 90s category, corrected aspect ratios, fixed rom-sets, etc.)
  • +
  • Added driver for seta2 hardware
  • +
  • Added preliminary driver for m92 hardware in debug builds
  • +
  • Added a d_parent module to put required parent drivers that don't have a specific driver
  • +
+ +

v0.2.96.72

+

This list is nothing like exhaustive. These are only the highlights of a big new version;

+ +
    +
  • Thanks to the contributions of OopsWare we have some nice new drivers +
      +
    • PGM Hardware
    • +
    • Video System Hardware
    • +
    • 1945k III
    • +
    • Gals Panic
    • +
    • Power Instinct
    • +
    • Shadow Force
    • +
  • +
  • I have been busy with the following +
      +
    • Added a Sega System 18 driver
    • +
    • Added Ace Attacker, Excite League and Super League to the Sega System 16 drivers
    • +
    • Added various bootlegs to the Sega System 16 driver
    • +
    • Added driver for Kaneko 16 Hardware
    • +
    • Added Honey Dolls, Snow Bros. 3, and The Winter Bobble to the Pandora based driver
    • +
    • Added a generic lightgun interface to the burn library and converted all existing drivers to use it
    • +
    • Emulated column and row scroll in System 16 tilemaps (still has a few issues with a few instances)
    • +
    • Added support for (multiple) YM2612/3438 sound chips (as used by System 18)
    • +
    • Added support for the RF5C68 PCM sound chip (still has issues which escape me at present, used by System 18)
    • +
    • Fixed an issue with high BPP support in the generic tiles interface
    • +
    • Matched all sets to MAME 0.117u3 and added some clones to various driver
    • +
  • +
  • Added Ganbare Ginkun and Riot to the Tecmo 16 driver [BisonSAS]
  • +
  • Added kev's preliminary Dec0 driver to debug builds [kev]
  • +
+ +

v0.2.96.71

+
    +
  • Added driver for Galaxy Force 2 (gforce2, gforce2j)
  • +
  • Added driver for G-LOC (gloc, glocr360)
  • +
  • Added driver for Line of Fire (loffire, loffirej, loffireu)
  • +
  • Added driver for Major League (mjleague)
  • +
  • Added driver for Power Drift (pdrift, pdrifta, pdrifte, pdriftj)
  • +
  • Added driver for Rail Chase (rchase)
  • +
  • Added driver for Strike Fighter (strkgftr)
  • +
  • Fixed sprite flip in Sonic Boom
  • +
  • Added some unicode titles [BisonSAS]
  • +
  • Matched sets to MAME 0.114u1
  • +
+ +

v0.2.96.70

+
    +
  • Datfiles should be sorted properly now - thanks to LogiqX for pointing out the errors again
  • +
+ +

v0.2.96.69

+
    +
  • Optimised the FD1094 routines resulting in a big speedup for those games
  • +
  • Fixed some minor dat file issues - thanks to LogiqX for pointing them out
  • +
+ +

v0.2.96.68

+
    +
  • Added driver for Bullet using Aaron's preliminary FD1094 key (bullet)
  • +
  • Added driver for Enduro Racer (enduror, enduror1, endurobl)
  • +
  • Added driver for Final Tetris (finalttr)
  • +
  • Added driver for Hang-On (hangon)
  • +
  • Added driver for SDI (sdi, sdib, sdibl, defense)
  • +
  • Added driver for Space Harrier (sharrier, sharrir1)
  • +
  • Added driver for Sukeban Jansi Ryuko (sjryuko, sjryuko1)
  • +
  • Added driver for Twin Adventure (twinadv, twinadvk)
  • +
  • Emulated the NVRAM for X-Board, Out Run, System 16B and System 16A drivers, although Out Run games don't seem to use it
  • +
  • Emulated the PPI I/O Chip and hooked it up for the System 16A and Out Run drivers
  • +
  • Fixed a bug in the System 16 Tilemap rendering (fixes Golden Axe, Wrestle War and some others)
  • +
  • Optimisations to the graphics rendering in the System 16, Out Run and X-Board drivers
  • +
  • Added an interface to the YM2203 FM sound core
  • +
  • Added mahjong controls to the default assignment routine and updated the mahjong games to use it
  • +
  • Fixed savestate support in some Cave drivers [BisonSAS]
  • +
  • Various driver cleanups [BisonSAS]
  • +
  • Improved the rom verify feature and moved the define to the makefile
  • +
  • Updated some unicode titles [BisonSAS]
  • +
  • Updated sets to match MAME 0.114
  • +
+ +

v0.2.96.67

+
    +
  • Added driver for AB Cop (abcop)
  • +
  • Added driver for After Burner (aburner2, aburner)
  • +
  • Added driver for Dunk Shot (dunkshot)
  • +
  • Added driver for E-Swat (eswat, eswatj, eswatu)
  • +
  • Added driver for Golden Axe (goldnaxe, goldnaxj, goldnaxu, goldnax1, goldnax2, goldnax3)
  • +
  • Added driver for GP Rider (gprider, gprider1)
  • +
  • Added driver for Heavyweight Champ (hwchamp)
  • +
  • Added driver for Racing Hero (rachero)
  • +
  • Added driver for RyuKyu (ryukyu)
  • +
  • Added driver for Super Monaco GP (smgp, smgp5, smgp6, smgpj, smgpu, smgpu1, smgpu2, smgpu3)
  • +
  • Added driver for Thunder Blade (thndrbld, thndrbd1)
  • +
  • Added Jan's preliminary driver for Madgear in debug builds only (madgear)
  • +
  • Added Kev's preliminary driver for Teenage Mutant Ninja Turtles in debug builds only (tmnt, tmntu, tmntua, tmht, tmntj, tmht2p, tmnt2pj, tmnt2po)
  • +
  • Rewrite of the Bombjack driver [kev]
  • +
  • Fixed a crash in some FD-1094 encrypted games
  • +
  • Fixed the reset function for FD-1094 encrypted games
  • +
  • Cleanups to the Taito 68K drivers [BisonSAS]
  • +
  • Fixed bug in the preview cycling code for the Game Select dialog [CaptainCPS]
  • +
+ +

v0.2.96.66

+
    +
  • Added driver for Cotton (cotton, cottonj, cottonu)
  • +
  • Added driver for Out Run (outrun, outrun1, outrun2, outrunb)
  • +
  • Added driver for Passing Shot (passshot, passshta, passshtj)
  • +
  • Added driver for Super Hang-On (shangon, shangon2, shangon3, shangnle)
  • +
  • Added driver for Turbo Out Run (toutrun, toutrun2)
  • +
  • Fixed a bug in the System 16 Sprite rendering [kev]
  • +
  • Fixed a problem with memory card support
  • +
  • Updated the region dips in the Battle Bakraid and Batrider drivers [BisonSAS]
  • +
  • Forced the Battle Bakraid driver to use the Musashi 68K core [BisonSAS]
  • +
  • Updated some unicode titles [BisonSAS]
  • +
+ +

v0.2.96.65

+
    +
  • Corrected the rom size of the v4 rom in lastbldh and lastsold
  • +
  • Finally beat the bug that sometimes hides the license dialog (hopefully!)
  • +
  • Updated the load dialog based on code from CaptainCPS, should be the last change as I'm really happy with it
  • +
  • Updated sets to match MAME 0.112u4
  • +
+ +

v0.2.96.64

+
    +
  • Big update to the System 16 drivers - these drivers are still preliminary and thus still have issues (major issues only listed); +
      +
    • Dynamic memory maps for System 16B are not emulated
    • +
    • Row and Column scroll not emulated for System 16A and B
    • +
    • Alernate tilemap select for System 16B not emulated
    • +
    • Some of the FD1094 encrypted games require a driver reset after loading before they boot
    • +
    • There are plenty of other small issues as well but most games are running well
    • +
  • +
  • Added driver for Biomechanical Toy (biomtoy) [kev, cleanup by BisonSAS]
  • +
  • Fixed blank tile bug in the Prehistoric Isle driver
  • +
  • Fixed bad tiles in The King of Fighters 99 driver [BisonSAS, Ryo, Robert, Yuri, Takuma)
  • +
  • Updated the CPS-1 drivers to allow brightness control in the palette
  • +
  • Removed the XOR from spf2ta now the decryption key is known
  • +
  • Cleanup to the Bombjack driver [BisonSAS]
  • +
  • Fixed issues with savestates in several drivers
  • +
  • Changed the game selection dialog again
  • +
  • Added/fixed several non-Latin titles [doomking, BisonSAS]
  • +
  • Updated several romsets to match MAME 0.112u3
  • +
  • Fixed the perl script that generates the driver list so that sets can be assigned to debug builds only again
  • +
+ +

v0.2.96.63

+
    +
  • Added garoubl to the Garou driver
  • +
+ +

v0.2.96.62

+
    +
  • Added driver for Choko (choko)
  • +
  • Added driver for Jyangokushi: Haoh no Saihai (jyangoku)
  • +
  • Added various CPS-2 clones now the decryption keys are known
  • +
  • Added rastsag1 to the Rastan driver
  • +
  • Fixed bug with EEPROM on startup in CPS games
  • +
  • Fixed crash bug in Q-Sound games with sound disabled
  • +
  • Enabled the "Tournament" mode in the tournament versions of Super Street Fighter 2 - now they try to connect to other terminals (if you just want to play the games then change the setup in the "Test Menu", access using F2)
  • +
  • Fixed bug in datfile generation module
  • +
  • Various rom changes to match MAME 0.112u2 (with the exception of the XOR for spf2ta)
  • +
+ +

v0.2.96.61

+
    +
  • Fixed bug in System 16 sound - won't test with volume down in future!
  • +
+ +

v0.2.96.60

+
    +
  • Added Sega System 16A driver supporting Action Fighter, Alex Kidd, Fantasy Zone, Quartet, Shinobi and Time Scanner
  • +
  • Added various clones to the CPS-2 driver as the keys are now known
  • +
  • Added driver for Street Fighter Alpha CPS-Changer
  • +
  • Various renames and XOR removals to match MAME 0.111u5
  • +
  • Improved save state support in numerous drivers
  • +
  • Dropped the "(BH)" monikor from the App title
  • +
+ +

v0.2.96.59

+
    +
  • Fixed issues with sound in irrmaze, joyjoy, mahretsu, pspikes2 and socbrawl
  • +
  • Added sf2m2 to the Street Fighter 2 Champion Edition driver
  • +
  • Amended the game selection dialog and separated CPS-1/CPS-2 games
  • +
  • Widened the dip switch dialog
  • +
+ +

v0.2.96.58

+

This is a fairly big update; changes are summarised below;

+
    +
  • Neo Geo +
      +
    • Added driver for Diggerman (diggerma)
    • +
    • Added driver for Jockey Grand Prix (jockeygp)
    • +
    • Added driver for Metal Slug 5 (mslug5, ms5plus, ms5pcb)
    • +
    • Added driver for Pochi and Nyaa (pnyaa)
    • +
    • Added driver for Samurai Shodown V (samsho5, samsho5h, samsho5b, samsh5sp, samsh5sh, samsh5sn)
    • +
    • Added driver for SvC Chaos - SNK vs Capcom (svc, svcboot, svcplus, svcplusa, svcsplus, svcpcb, svcpcba)
    • +
    • Added driver for The King of Fighters 2003 (kof2003, kf2k3bl, kf2k3bla, kf2k3pl, kf2k3upl, kf2k3pcb)
    • +
    • Added driver for V-Liner (vliner, vlinero)
    • +
    • Added driver for Zintrick (zintrckb)
    • +
    • Added aof3k to the Art of Fighting 3 driver
    • +
    • Added ct2k3sp to the Crouching Tiger Hidden Dragon 2003 driver
    • +
    • Added kog to the King of Fighters '97 driver
    • +
    • Added lastsold to the Last Blade driver
    • +
    • Added mslug3b6 to the Metal Slug 3 driver
    • +
    • Added ms4plus to the Metal Slug 4 driver
    • +
    • Added fswords to the Samurai Shodown III driver
    • +
    • Added lans2004 to the Shock Troopers 2 driver
    • +
    • Added kof10th, kf10thep, kf2k5uni, kf2k2mp, kf2k2mp2, kf2k2pls, kf2k2pla, kof2k4se to the King of Fighters 2002 driver
    • +
    • ROMset changes to match MAME affecting the kizuna, kof2000, kof2001, kof2002, lastblda, matrim, mslug4, and rbff1 drivers
    • +
    • Added emulation for PVC Protection
    • +
    • Added extra emulation for various bootlegs and gambling games
    • +
    • Enabled a protection patch for Metal Slug X making the game playable
    • +
    • Updated Universe BIOS to latest version (2.2)
    • +
    • Added missing bioses from MAME
    • +
    • Added a compile-time define in the Neo Geo driver to strictly match the MAME bios set for romset validation purposes
    • +
    • Removed driver for bangbedp
    • +
  • +
  • CPS-2 +
      +
    • Added the decryption algorithm routines to allow games to be decrytped without XORs
    • +
    • Removed the XORs from drivers where the decryption key is known
    • +
    • Added driver for Hyper Street Fighter 2 (hsf2a)
    • +
    • Added driver for Puzz Loop 2 (pzloop2, pzloop2j)
    • +
    • Added 19xxa to the 19XX driver
    • +
    • Added avspa to the Alien vs Predator driver
    • +
    • Added armwar to the Armored Warriors driver
    • +
    • Added ddsomr1, ddsomr3 to the Dungeons & Dragons: Shadow of Mystara driver
    • +
    • Added ddtodr1 to the Dungeons & Dragons: Tower of Doom driver
    • +
    • Added mshj to the Marvel Super Heroes driver
    • +
    • Added mshvsfj2 to the Marvel Super Heroes vs Street Fighter driver
    • +
    • Added spf2ta to the Super Puzzle Fighter 2 Turbo driver
    • +
    • Added ssf2tbr1 to the Super Street Fighter 2 driver
    • +
    • Added ssf2u to the Super Street Fighter 2 Turbo driver
    • +
    • Added xmvsfu to the X-Men vs Street Fighter driver
    • +
    • Emulated the paddles in Puzz Loop 2 (pzloop2, pzloop2j)
    • +
    • ROMset changes to match MAME affecting the armwar, avsp, ddsom, ddtod, dstlk, msh, mshvsf, msvc, progear, sfa, sfa3, sgemf, spf2t, vhunt2, and xmvsf drivers
    • +
    • Corrected the descriptions in the Cyberbots driver
    • +
    • Disabled drivers for games without XORs or decryption keys
    • +
  • +
  • CPS-1 +
      +
    • Added cawingr1 to the Carrier Air Wing driver
    • +
    • Added ffightua to the Final Fight driver
    • +
    • Fixed the Saturday Night Slam Masters driver so the games now boot
    • +
    • ROMset changes to match MAME affecting the forgottn, sf2, and varth drivers
    • +
    • Removed driver for knightsh
    • +
  • +
  • Toaplan +
      +
    • Added driver for Hell Fire (hellfire, hellfir1, hellfir2)
    • +
    • Added driver for Truxton (truxton)
    • +
    • Added driver for Zero wing (zerowing)
    • +
    • Added batsugna to the Batsugun driver
    • +
    • Added outzoneb, outzonec to the Out Zone driver
    • +
    • Fixed the dip switches in the Out Zone driver
    • +
    • ROMset changes to match MAME affecting the bbakraid, dogyuun, outzone and shippumd drivers
    • +
  • +
  • Cave +
      +
    • Added donpachk to the Donpachi driver
    • +
    • Added theroes to the Gaia driver
    • +
    • Added uopoko to the Puzzle Uo Poko driver
    • +
    • ROMset changes to match MAME affecting the btlkroad, ddonpach, dfeveron, donpach, gaia and uopoko drivers
    • +
  • +
  • Misc +
      +
    • Added driver for Cooki and Bibi 2
    • +
    • Added driver for Cooki and Bibi 3
    • +
    • Added driver for More More
    • +
    • Added driver for More More Plus
    • +
    • Added driver for Puzzle King
    • +
    • Added driver for Toppy & Rappy
    • +
    • Added driver for Twinkle
    • +
    • Added driver for XESS - The New Revolution (SemiCom 3-in-1)
    • +
    • Added gtstarba to the Guardian driver
    • +
    • Added newsa to the News driver
    • +
    • Added slapftuk, slapfgtr to the Slap Fight driver
    • +
    • Added snowbroc to the Snow Bros. driver
    • +
    • Added solomon to the Solomons Key driver
    • +
    • Added s1945a, s1945k to the Strikers 1945 driver
    • +
    • Added supermanj to the Superman driver
    • +
    • Added tigerhb2 to the Tiger Heli driver
    • +
    • Added daisenpu to the Twin Hawk driver
    • +
    • Fixed the sound generated by the YM2151 in the Final Star Force driver
    • +
    • Fixed the hang bug in the Rastan driver when starting the game
    • +
    • ROMset changes to match MAME affecting the gunbird, opwolf, rastan, s1945, solomon, tengai and tigerh drivers
    • +
  • +
  • Application +
      +
    • Added a NODUMP flag for rom definitions and updated DAT file generation and rom scan routines to support it
    • +
    • Increased the max length of a rom name to 32 characters
    • +
    • Added support for the extra V-Liner inputs to the input dialog
    • +
    • Made game selection dialog wider to accomodate longer game titles
    • +
    • Fixed the player descriptions in the input dialog (Player 0 becomes Player 1, etc.)
    • +
  • +
+ +
From this point forward, all releases are handled by Barry and each external contribution is labelled.

The releases below were available on the old FBA site.
+ +

v0.2.95.23

+

Time for another FinalBurn Alpha release, bringing with it an assortment of fixes and additions. Grab it while it’s hot, from our files page. Any bugs / issues should be reported to the FBA official forums.

+
    +
  • This is still an alpha release!
  • +
  • Note that, if compiled with GCC, you will need to use version 3.3.x, and the experimental DirectX 9 blitter is not built
  • +
  • Changed the way FB Alpha looks for ROMs. Now, it will always check the last path for any given .zip file, even when a .zip file of the same name is present in another path. This way, we can keep ROMs that are only needed for FB Alpha seperate without sacrifising compatibility with other emulators
  • +
  • Changed the way Neo Geo memory cards work, allowing the use of 1 megabit cards
  • +
  • Emulated protection in Super Sidekicks (was patched before)
  • +
  • Fixed the last few bad game names / bad ROM definitions
  • +
  • Fixed a few minor issues in the makefile for mingw/cygwin
  • +
  • The debugger is now only compiled for debug builds
  • +
  • Minor updates to compile documentation
  • +
  • Fixed a crash at startup for some systems when autopause was activated
  • +
+ +

v0.2.95.22

+

This release fixes a few bugs that crept into yesterdays release. GCC is supported in this release, with a few stipulations. See below for more details regarding compiling this release with GCC. Grab this latest release from our files page.

+
    +
  • This is still an alpha release!
  • +
  • Note that, if compiled with GCC, you will need to use version 3.3.x, and the experimental DirectX 9 blitter is not built
  • +
  • Implemented workarounds to the FB Alpha executable to allow the use of windres as the resource compiler (it cannot zero-terminate strings or use a string as an RCDATA resource)
  • +
  • Cleaned up the makefiles (variables/options now defined in the main makefile)
  • +
  • Fixed a few game names / bad ROM definitions
  • +
  • Fixed CPS1 games sound / crashing if started as the 1st game
  • +
  • Fixed the Psikyo games that use an YM2610 for sound
  • +
  • Fixed a few problems with ANSI builds
  • +
+ +

v0.2.95.21

+

At long last it’s time for a new version of FBA! On offer are the standard build, the source code and an optimised binary for use on Win9x / Pentium machines. You can download the latest version, from our Files page.

+

This is still an alpha release!

+

Note that this version CANNOT be compiled with GCC!

+
    +
  • converted all code to optionally use unicode
  • +
  • Added a driver for 68EC020 based Psikyo hardware
  • +
  • Added a second 68000 CPU core. For plain 68000 CPUs you can select which core to use, the new one also emulates 68010 and 68EC020 CPUs
  • +
  • Fixed the overclock feature for Neo Geo
  • +
  • Added a DirectX Graphics 9 blitter (see system requirements, below)
  • +
  • Performed miscellaneous minor bugfixes
  • +
+ +

v0.2.94.98

+

Special Christmas Eve Release!

+

A new version of FBA has been released, with the following fixes and updates. Please remember that this is still considered to be an alpha release and while we are pretty sure most of the nastier bugs have been squashed, a few may remain. So if you find a bug, please report it to the appropriate forum. All that remains is too wish our Christmas celebrating users a Merry Christmas! And to everyone else, happy Winter Solstice!

+
    +
  • Fixed all the new bugs introduced in the previous version
  • +
  • Fixed the raster effects in Samurai Shodown 3
  • +
  • Preview images can be any png file upto 1024×0124 pixels
  • +
  • Added descriptive text to screenshot png files
  • +
  • Added a system information dialog that’s used when FB Alpha crashes
  • +
  • Added the english language versions of mahoudai and shippumd
  • +
+ +

v0.2.94.97

+

There is a new version of FBA available from our downloads page. At present an upgrade .msi is unavailable. Any users wishing to upgrade, should download the standard fba_029497.exe and extract the contents to their installation directory.

+

This is an alpha release! Again, although we expect very few problems, there still might be some we’ve not seen.

+
    +
  • Fixed most of the remaining problems in v0.2.94.96
  • +
  • Shortcut keys have changed
  • +
  • Directories used by FB Alpha have changed
  • +
  • Readme updated (read it completely even if you’ve read the earlier versions)
  • +
  • The Neo Geo driver now always uses a real AES BIOS in AES mode, more differences between AES and MVS are emulated now as well
  • +
+ +

v0.2.94.96

+

All the files are now back online. If you downloaded the previous installer, then you only have to download the smaller upgrade installer this time around. There is also an optimised build for K6 users; as after all, they are people too… Please remember to delete the contents of you cfg/ folder before you start FBA, as the old cfg files will not be fully compatible with the new release.

+ +

v0.2.94.95

+

A new version of FBA has been released. This version fixes most of the problems in v0.2.94.56. If you downloaded the fba.msi last time, we recommend that you wait for the fba_029495_update.msi that should be released later this evening. For all the K6 people out there, an optimized K6 version will be available shortly as well. Please note that certain CPS1 games still lack sound. Downloads are currently available from the torrents page. Direct downloads will be available in a little while. If you are using FB Alpha v0.2.94.56, please upgrade. Delete all files in the FB Alpha cfg directory.

+ +

v0.2.94.56

+
    +
  • Added a driver for Neo Geo games
  • +
  • too many other improvements to name
  • +
+ +

v0.2.94

+
    +
  • Added a driver for Cave games
  • +
  • Added a driver for Rainbow Islands
  • +
  • Added support for X-Arcade joystick
  • +
  • Improved compatibility of the Direct3D blitter, and added new options
  • +
  • re-added 3x macros for Street Fighter 2 style games
  • +
  • Added 4-point interpolation to the ADPCM sound cores
  • +
+ +

v0.2.92

+
    +
  • Small bug-fix release, relating to inputs (Z-Axis), NetPlay Chat font-size and a small speed increase
  • +
+ +

v0.2.91

+

(This is basically a new emulator with far too many new features to list - the following is merely a very brief summary).

+
    +
  • Toaplan2 emulation
  • +
  • Massively improved CPS-2 emulation with support for all currently XORed games
  • +
  • Improved CPS-1 emulation with support for the recent (Chinese?) hacks
  • +
  • Many, many UI enhancements
  • +
  • New blitters - including RGB effects, etc
  • +
  • Demo recording and playback
  • +
+ +

v0.2.5

+
    +
  • Fixed menu/cheat incompatibilty bug
  • +
  • Added a suprise (in the source)
  • +
+ +

v0.2.4.0

+
    +
  • Fixed dstlk driver for euro parent set
  • +
  • Added mvsc driver
  • +
+ +

v0.2.3.0

+
    +
  • This build should fix the drop in performance that has been experienced by people with slow PC's. This was probably caused by new Platform SDK DirectX 8.0 elements. Please let us know if you still experience a drop in performance
  • +
  • Fixed bug with Mercs driver
  • +
+ +

v0.2.2.7

+
    +
  • Added starfield emulation
  • +
  • Added support for changing layer-sprite priorities with raster effects. (fixes glitches in Manhattan and Apocalypse stages)
  • +
  • Fixed pgear/armwar glitch
  • +
  • Added hotkeys for savestate slots
  • +
  • Updated the cheat engine so it can use same cheats for multiple games
  • +
  • Added screenshot feature
  • +
  • Added a basic shot factory. F8 to activate
  • +
  • Slightly changed shot factory to include sprite toggle
  • +
  • Updated the fbcheat.dat file with a ton of cheats
  • +
  • Driver changes
  • +
  • Fixed controls for mercs & clones
  • +
+ +

v0.2.2

+
    +
  • Fixed cawing & clones buildings gfx error
  • +
  • Fixed repeating sounds
  • +
  • Fixed sound crashing in DDTOD and other games
  • +
  • Changed keys for volume up and down
  • +
  • Fixed aspect ratio for vertical games
  • +
  • Added the third button to the mtwins driver
  • +
  • fixed crash bugs in cawingj, knightsj, qadj, striderj, varthj & varthu
  • +
  • Added more cheats
  • +
+ +

v0.2.1

+
    +
  • Added drivers for ddtod, sfz3a, vsava, xmvsf & xmcota
  • +
+ +

v0.138a

+
    +
  • Added Drivers for mshvsf, mshvsfj, mshvsfjr1, vsav & armwar
  • +
  • No further updates have been made to this version
  • +
+ +

v0.137a

+
    +
  • Fixed auto-pause
  • +
  • Fixes to dozea.asm
  • +
  • Fixed HotRod inputs
  • +
  • Fixed an input menu bug when there's no DIP-SW data available
  • +
  • Updated and fixed dipinfo.dat file
  • +
  • Updated fbcheat.dat file
  • +
  • Added volume control
  • +
  • Added more accelerators
  • +
+ +

v0.137

+

REALLY IMPORTANT BIT: We require your feedback/input, regarding any problems/bugs you may have with the Kaillera netplay & new menu. Please report any bugs to http://www.xsorbit.com/users/LEvilElmo/index.cgi - and use the FinalBurn Alpha Bug Report Board. Remember to provide details about your PC's spec's, OS, etc etc.

+

SECOND IMPORTANT BIT: Ayeye & HyperYagami have joined "Team FB Alpha."

+
    +
  • Added a new GUI
  • +
  • Added rom scanning to check what roms you have
  • +
  • Added options to show all, CPS-1 only or CPS-2 only games
  • +
  • Added option to only show the games you got
  • +
  • Added esc=exit for all dialogs
  • +
  • Added CPS1 QSound (thanks for info ElSemi)
  • +
  • Added IIR low pass filter
  • +
  • Added Dip Switches Engine
  • +
  • Fixed stupid error I made with the cheat dialog column widths :P
  • +
  • Set nApplyCheatEveryXFrame to 0 as standard
  • +
  • Fixed so the 4 player fix for batcirj only applies to netplay
  • +
  • Added light blue background as standard for SFA3 + clones in netplay
  • +
  • Added flip monitor as standard for XMvSF in netplay
  • +
  • Added drivers for ddsom, dstlk, dstlkr1, sfa & sfar1
  • +
  • Updated cheats file
  • +
+ +

v0.136 WIP

+
    +
  • A small fix so the the option bReadInputEveryFrame is always *ON* during netplay. Changing the value in the .ini file now only effects local play
  • +
  • Disabled the T key during netplay until i can fix it and still make FB run under Win95
  • +
  • Fixed four player in Battle Circuit
  • +
+ +

v0.136

+

REALLY IMPORTANT BIT: Delete all of the files in the "cfg folder" apart from the "finalburn file." The new cheat engine has "issues" with the old config files.

+
    +
  • Disabled the T (talk) key during netply until i can figure out a way of fixing the problem
  • +
  • A small fix so the the option bReadInputEveryFrame is now always ON during netplay. Changing the value in the .ini file now only effects local play
  • +
  • Merged in some changes from big fool
  • +
  • Added an options dialog, still needs a bit of work but works in its current state
  • +
  • Added the layer toggle code by gangta and removed the old Alt+L layer toggle stuff keys alt+6 -0 are used
  • +
  • Added version 2 of HyperYagami's Cheat engine. A lack of space on the cheat menu has ment that you cannot disable cheats, but that doesn't really matter. Also made a small change for netplay cus the input dialog was getting screwed
  • +
  • Removed the Dat type code from the .ini file. Use the buttons under options instead
  • +
  • Cheat options input screen added :)
  • +
  • Fixed 4 player under Battle Circuit
  • +
  • Added lots more cheats to the fbcheat.dat file
  • +
  • Fixed so the 4/3 player fixes only applies to the netplay games
  • +
  • Minor tweak to the Options Input screen
  • +
  • Added Mike's lovely FBA logo to all the doc's
  • +
+ +

v0.135

+
    +
  • Readded Ayeye's pause code, works a lot better now. Also added his latest version which fixes a few bugs. the game will now pause when the panel is shown and when the window loses foucus. It is still disabled during netplay
  • +
  • Readded HyperYagami's multi rom path stuff
  • +
  • Fixed the updated Megaman driver
  • +
  • Added the first version of HyperYagami's cheat engine as well as making a few changes to disable it during multiplayer
  • +
  • A small fix so the the option bReadInputEveryFrame is always off during netplay. Changing the value in the .ini file now only effects local play
  • +
  • Fixed the warnings that were starting to creep in all over the place
  • +
  • Added region switches for: Battle Circuit, Eco Fighters, Armored Warriors & Street Fighter Zero 2 Alpha
  • +
  • Fixed player 2 & 3 controls in Mercs
  • +
  • Merged Logiqxs driver changes
  • +
  • Merged Logiqxs .dat generator and added .ini setting for it
  • +
  • Added Hotrod support in the ini
  • +
  • Added extra ports to CPS_RW.CPP to get the kicks working in sf2ue and gain more control over rotation in forgottn
  • +
  • Altered the Driver list so that all drivers are listed alphabetically, this fixes the "Alphabetical Doubling" in the game list, when creating an online game
  • +
  • Got 3Player controls working in Knights of the Round
  • +
  • Yet another tweak to the load menu - everything should now be in the correct order
  • +
  • Added AvsP 3 Player fix & DD:SoM 4 Player fix, should work fine in netplay now!
  • +
  • Fixed Ghouls, SSF2T & SF2T + Clones in netplay, they were unplayable before!
  • +
  • Fixed the region switches in netplay!
  • +
  • Added region switches for: DD:ToD, Pnickies, Mega Man
  • +
  • Added Infinite Time cheats to all 1 on 1 fighting games
  • +
  • Fixed the QNDream controller
  • +
+ +

v0.134

+

FinalBurn Alpha is now updated by "Team FB Alpha" (LoopMaster, KEV, Mike_Haggar & TrebleWinner)

+
    +
  • Fixed FFightj GFX Loading
  • +
  • Added 2 new fields to the driver structure
  • +
  • Added Treble Winner's changes fixing descriptions of many of the inputs
  • +
  • Changed the load dialog to support the new text fields
  • +
  • Removed the multi rom path code as it needs fixing
  • +
  • Added Merged CPS1 Drivers (Rest of the games!)
  • +
  • Fixed Mercs and clones, Cawingj, Cworld2j, Pnickj & Qad GFX Loading
  • +
  • Fixed 3wonders and clones & willow and clones GFX Loading + Banks
  • +
  • Added the inputs that was missing, but were included in MAME
  • +
  • Added Captain Commando and clones driver
  • +
  • Added Mega Twins and clones driver (thanks to Diablo82 & Treble_Winner)
  • +
  • Fixed SF2 Init13 (thanks to Treble_Winner)
  • +
  • Added TrebleWinners default controls code. Default controls can now be set in the ini (eg: 0=keyboard, 1=joystick 1, 2=joystick 2, etc...
  • +
  • Minor tweak to the load menu display
  • +
  • Added Ayeye's Pause Code. FinalBurn Alpha will now pause when the window loses focus. NB: the gui must be hidden for this to occur
  • +
  • Fixed problems with Win95/Kaillera incompatabilities (KEV)
  • +
  • Added drivers for the new CPS2shock releases (Battle Circuit, Eco Fighters, SFA3 clones & Vampire clone)
  • +
+ +

v0.133

+
    +
  • An apology for releasing the debug version by accident, sorry all. C++ caused several lock ups & crashes on my PC before I built the .exe file. Several configuration setting's fouled up & I lost a few unimportant files as well :(
  • +
+ +

v0.132

+
    +
  • Hack Fixed the UN Squadron driver (KEV)
  • +
  • Add WIP for better Multiply protection
  • +
  • Patched Knights of the round so you can play it
  • +
  • Added King of Dragons driver By Mike_Haggar with a fix by KEV
  • +
  • Added Support for 1941 and clones
  • +
  • A fully working King Of the Dragons Driver
  • +
  • A very very small tweak to the game selection dialog
  • +
  • Re-added a few lines in drv.cpp to fix on-line mode and tweaked rom search path
  • +
  • Added Better support for the CPS1 board IDs to get all the games that need it working and changed drivers as needed
  • +
  • Added Merged CPS2 Drivers (All games!)
  • +
  • Added Merged CPS1 Drivers for : UN Squadron, Varth, Strider, MSword and Final Fight!
  • +
  • Added Merged Sf2 and Sf2ce drivers with all clones with thanks to JeldrosJ3 for SF2RB2
  • +
  • Fixed the problem with Marvel Super Heroes (Japan) loading the USA version instead of the Japan version.
  • +
+ +

v0.131

+
    +
  • Now compiled with Christophe's Alpha 5 Kaillera code
  • +
  • Fixed the crash when using Strider Hiryu (USA)
  • +
  • Multiple ROM path support added courtesy of HyperYagami
  • +
+ +

v0.130

+
    +
  • Now compiled with Christophe's Alpha 4 Kaillera code, a new version of the kailleraclient.dll is also included in this release
  • +
  • Added lots of new drivers for Street Fighter (C.E. & Turbo), mainly clones though, thanks to everyone who donated these. Too many to mention here, but SF2 Red Wave & Rainbow Edition are included
  • +
  • Drivers added for Magic Sword (Mike Haggar) and UN Squadron (KEV)
  • +
  • Added my own Knights of the Round driver, thanks go out to Mike Haggar for fixing the GFX issues. Unfortunately the in-game controls don't work at present :(
  • +
  • In theory it should be possible to play against someone who is using FinalBurn Kaillera Alpha 4, as both use the same code. That said, it would be better if you play against someone who is using Final Burn Alpha v0.130 :)
  • +
+ +

v0.129

+
    +
  • There's no need to use patched XOR's anymore! Armwar, Pgear & Pgearr1 now use the original XOR tables released by Raz. A very big thankyou goes out to Raz & FinalDave for helping me solve this problem :)
  • +
  • Pgearr1 now works correctly, and no longer reports the "1010 EXCEPTION 0000716C" message
  • +
  • Re-ordered the games list. CPS-1/CPS-Changer games can now be found at the bottom of the game list, in alphabetical order
  • +
  • Forced "bReadInputEveryFrame" to default as "0" (off). According to Raz this should help with the netplay. The "bDrvSaveAll" option should also be set to "0" if you are using the netplay feature
  • +
+ +

v0.128

+
    +
  • Added Christophe's Kaillera source code (Alpha3), so netplay is now available!
  • +
+ +

v0.127

+
    +
  • Enabled the CPS-1 drivers for: +
      +
    • Megaman/Rockman: The Power Battle
    • +
    • Final Fight (World)
    • +
    • Ghouls & Ghosts
    • +
    • Strider
    • +
    • Street Fighter 2 (ETC)
    • +
    • Street Fighter 2: C.E. (ETC)
    • +
    • Street Fighter 2 Turbo (USA)
    • +
  • +
  • Enabled the CPS-Changer driver for: +
      +
    • Street Fighter Zero
    • +
  • +
+ +

v0.126

+
    +
  • Updated all CPS-2 drivers, to be compliant with Logiqx CPS-2 DAT 20010727
  • +
  • Added drivers for Armwar, Pgear & Pgearr1 - they currently use Haze's patched XOR's
  • +
  • You need to add the following patched XOR's to the following ROMset's: +
      +
    • pgear_xor_haze.zip ------> pgear.zip
    • +
    • pgearr1_xor_haze.zip ----> pgearr1.zip
    • +
    • armwar_xor_haze.zip -----> armwar.zip
    • +
  • +
  • Pgearr1 loads but does not work properly, it only displays a "1010 EXCEPTION 0000716C"
  • +
+ +

v0.125

+
    +
  • Altered Driver for Ddsomj so that it now points to Ddsomjr1
  • +
+ +

v0.124

+
    +
  • Removed CPS-1 & Sega drivers
  • +
  • Added Drivers for all CPS-2 titles, with the exception of Armoured Warriors & Powered Gear
  • +
+ +